commit d7b361ba44891330d2f1607e3915e80aa7bb4a41 Author: Floris Bos Date: Wed Mar 4 16:55:40 2020 +0100 Qt/QML edition diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..767766d --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,213 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2020 Raspberry Pi (Trading) Limited + +cmake_minimum_required(VERSION 2.8.12) +if (APPLE) +set(CMAKE_OSX_DEPLOYMENT_TARGET "10.12" CACHE STRING "" FORCE) +endif() + +project(imagingutility LANGUAGES CXX) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) + +# Adding headers explicity so they are displayed in Qt Creator +set(HEADERS config.h imagewriter.h networkaccessmanagerfactory.h nan.h drivelistitem.h drivelistmodel.h driveformatthread.h powersaveblocker.h + downloadthread.h downloadextractthread.h dependencies/mountutils/src/mountutils.hpp) + +# Add 3rd-party dependencies +if (APPLE) +set_source_files_properties("icons/imagingutility.icns" PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") +set(DEPENDENCIES mac/macfile.cpp mac/macfile.h dependencies/mountutils/src/darwin/functions.cpp + dependencies/drivelist/src/darwin/list.mm dependencies/drivelist/src/darwin/REDiskList.m icons/imagingutility.icns) +enable_language(OBJC C) +elseif (UNIX) +set(DEPENDENCIES dependencies/mountutils/src/linux/functions.cpp linux/linuxdrivelist.cpp linux/udisks2api.cpp linux/udisks2api.h) +elseif (WIN32) +set(DEPENDENCIES dependencies/mountutils/src/windows/functions.cpp dependencies/drivelist/src/windows/list.cpp + windows/winfile.cpp windows/winfile.h + windows/imagingutility.rc) +set(EXTRALIBS setupapi) +endif() + +include_directories(BEFORE .) + +# Test if we need libatomic +include(CheckCXXSourceCompiles) +check_cxx_source_compiles(" + #include + #include + int main() { + std::atomic x; + x = 1; + return (int) x; + }" + atomicbuiltin) + +if (NOT atomicbuiltin) + find_library(ATOMIC_LIBRARY NAMES atomic libatomic.so.1) + if (NOT ATOMIC_LIBRARY) + message( FATAL_ERROR "Missing libatomic while architecture does need it" ) + endif() +endif() + +set(SOURCES "main.cpp" "imagewriter.cpp" "networkaccessmanagerfactory.cpp" + "drivelistitem.cpp" "drivelistmodel.cpp" "downloadthread.cpp" "downloadextractthread.cpp" + "driveformatthread.cpp" "powersaveblocker.cpp" "qml.qrc") + +if (WIN32) + set(CMAKE_CXX_FLAGS "-s -O2") + # Adding WIN32 prevents a console window being opened on Windows + add_executable(${PROJECT_NAME} WIN32 ${SOURCES} ${HEADERS} ${DEPENDENCIES}) +else() + add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS} ${DEPENDENCIES}) +endif() + +find_package(Qt5 COMPONENTS Core Quick Widgets REQUIRED) + +# Because dependencies are typically not available by default on Windows, build bundled code +if (WIN32) + # Target Windows 7 (needed for drivelist module) + add_definitions(-DWINVER=0x0601 -D_WIN32_WINNT=0x0601) + + # Bundled zlib + add_subdirectory(dependencies/zlib-1.2.11) + set(ZLIB_LIBRARY zlibstatic) + set(ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/dependencies/zlib-1.2.11) + + # Bundled libcurl + set(CMAKE_CURL_INCLUDES) + set(CURL_LIBRARIES cmcurl) + add_subdirectory(dependencies/cmcurl) + set(CURL_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/dependencies/cmcurl/include) + + # Bundled liblzma + add_subdirectory(dependencies/cmliblzma) + set(LIBLZMA_HAS_AUTO_DECODER 1) + set(LIBLZMA_HAS_EASY_ENCODER 1) + set(LIBLZMA_HAS_LZMA_PRESET 1) + set(LIBLZMA_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/dependencies/cmliblzma/liblzma/api) + set(LIBLZMA_LIBRARY cmliblzma) + + # Bundled libarchive + set(ENABLE_TEST OFF CACHE BOOL "") + set(ENABLE_TAR OFF CACHE BOOL "") + set(ENABLE_CPIO OFF CACHE BOOL "") + set(ENABLE_CAT OFF CACHE BOOL "") + add_subdirectory(dependencies/libarchive-3.4.2) + set(LibArchive_LIBRARIES archive_static) + set(LibArchive_INCLUDE_DIR dependencies/libarchive-3.4.2/libarchive) + + # Bundled fat32format + add_subdirectory(dependencies/fat32format) + add_dependencies(${PROJECT_NAME} fat32format) + + # Code signing + find_program(SIGNTOOL "signtool.exe" PATHS "c:/Program Files (x86)/Microsoft SDKs/ClickOnce/SignTool") + if (NOT SIGNTOOL) + message(FATAL_ERROR "Unable to locate signtool.exe used for code signing") + endif() + + add_custom_command(TARGET ${PROJECT_NAME} + POST_BUILD + COMMAND "${SIGNTOOL}" sign /tr http://timestamp.digicert.com /td sha256 /fd sha256 /a "${CMAKE_BINARY_DIR}/${PROJECT_NAME}.exe") + + add_custom_command(TARGET ${PROJECT_NAME} + POST_BUILD + COMMAND "${SIGNTOOL}" sign /tr http://timestamp.digicert.com /td sha256 /fd sha256 /a "${CMAKE_BINARY_DIR}/dependencies/fat32format/fat32format.exe") + + # Windeploy + find_program(WINDEPLOYQT "windeployqt.exe" PATHS "${Qt5_DIR}/../../../bin") + if (NOT WINDEPLOYQT) + message(FATAL_ERROR "Unable to locate windeployqt.exe") + endif() + + file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/deploy") + + add_custom_command(TARGET ${PROJECT_NAME} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_BINARY_DIR}/${PROJECT_NAME}.exe" "${CMAKE_BINARY_DIR}/dependencies/fat32format/fat32format.exe" "${CMAKE_SOURCE_DIR}/license.txt" + "${CMAKE_BINARY_DIR}/deploy") + + add_custom_command(TARGET ${PROJECT_NAME} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + "${Qt5_DIR}/../../../bin/libssl-1_1.dll" "${Qt5_DIR}/../../../bin/libcrypto-1_1.dll" + "${CMAKE_BINARY_DIR}/deploy") + + add_custom_command(TARGET ${PROJECT_NAME} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/windows/imagingutility.nsi" + "${CMAKE_BINARY_DIR}") + + add_custom_command(TARGET ${PROJECT_NAME} + POST_BUILD + COMMAND "${WINDEPLOYQT}" --no-translations --no-webkit2 --no-opengl-sw --angle --qmldir "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_BINARY_DIR}/deploy/imagingutility.exe") + + # Remove excess files + add_custom_command(TARGET ${PROJECT_NAME} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E remove + "${CMAKE_BINARY_DIR}/deploy/imageformats/qtiff.dll" + "${CMAKE_BINARY_DIR}/deploy/imageformats/qwebp.dll" + "${CMAKE_BINARY_DIR}/deploy/imageformats/qgif.dll") + +elseif(APPLE) + find_package(ZLIB REQUIRED) + find_package(CURL REQUIRED) + + # Bundled liblzma + add_subdirectory(dependencies/cmliblzma) + set(LIBLZMA_HAS_AUTO_DECODER 1) + set(LIBLZMA_HAS_EASY_ENCODER 1) + set(LIBLZMA_HAS_LZMA_PRESET 1) + set(LIBLZMA_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/dependencies/cmliblzma/liblzma/api) + set(LIBLZMA_LIBRARY cmliblzma) + + # Bundled libarchive + set(ENABLE_TEST OFF CACHE BOOL "") + set(ENABLE_TAR OFF CACHE BOOL "") + set(ENABLE_CPIO OFF CACHE BOOL "") + set(ENABLE_CAT OFF CACHE BOOL "") + add_subdirectory(dependencies/libarchive-3.4.2) + set(LibArchive_LIBRARIES archive_static) + set(LibArchive_INCLUDE_DIR dependencies/libarchive-3.4.2/libarchive) + + find_library(Cocoa Cocoa) + find_library(CoreFoundation CoreFoundation) + find_library(DiskArbitration DiskArbitration) + find_library(Security Security) + #find_package(Qt5 COMPONENTS Svg) + #set(EXTRALIBS ${CoreFoundation} ${DiskArbitration} ${Security} ${Cocoa} Qt5::Svg) + set(EXTRALIBS ${CoreFoundation} ${DiskArbitration} ${Security} ${Cocoa}) + set_target_properties(${PROJECT_NAME} PROPERTIES MACOSX_BUNDLE YES + MACOSX_BUNDLE_BUNDLE_NAME "Raspberry Pi Imager" + MACOSX_BUNDLE_GUI_IDENTIFIER "org.raspberrypi.imagingutility" + MACOSX_BUNDLE_ICON_FILE "imagingutility.icns") + + find_program(MACDEPLOYQT "macdeployqt" PATHS "${Qt5_DIR}/../../../bin") + if (NOT MACDEPLOYQT) + message(FATAL_ERROR "Unable to locate macdeployqt") + endif() + + add_custom_command(TARGET ${PROJECT_NAME} + POST_BUILD + COMMAND "${MACDEPLOYQT}" "${CMAKE_BINARY_DIR}/${PROJECT_NAME}.app" -qmldir="${CMAKE_CURRENT_SOURCE_DIR}") + +else() + find_package(ZLIB REQUIRED) + find_package(CURL REQUIRED) + find_package(LibArchive REQUIRED) + find_package(Qt5 COMPONENTS DBus) + set(EXTRALIBS Qt5::DBus) + + install(TARGETS imagingutility DESTINATION bin) + install(FILES icons/imagingutility.png DESTINATION share/pixmaps) + install(FILES linux/imagingutility.desktop DESTINATION share/applications) +endif() + +include_directories(${CURL_INCLUDE_DIR} ${LibArchive_INCLUDE_DIR}) +target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Quick Qt5::Widgets ${CURL_LIBRARIES} ${LibArchive_LIBRARIES} ${ATOMIC_LIBRARY} ${EXTRALIBS}) diff --git a/CMakeLists.txt.user b/CMakeLists.txt.user new file mode 100644 index 0000000..08f48df --- /dev/null +++ b/CMakeLists.txt.user @@ -0,0 +1,197 @@ + + + + + + EnvironmentId + {fa1f6c87-775d-479f-a47b-1fd318d7f63f} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + true + false + 0 + true + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + {9c1e45be-5f41-4f90-a917-bfa746393751} + 0 + 0 + 0 + + + /devwork/build-imagingutility-Desktop_9c1e45-Minimum Size Release + + + + + all + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Build + + ProjectExplorer.BuildSteps.Build + + + + + + all + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Minimum Size Release + Minimum Size Release + CMakeProjectManager.CMakeBuildConfiguration + + 1 + + + 0 + Deploy + + ProjectExplorer.BuildSteps.Deploy + + 1 + Deploy locally + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + false + false + 0 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + imagingutility + + false + + /devwork/build-imagingutility-Desktop_9c1e45-Minimum Size Release + 2 + + imagingutility + + CMakeProjectManager.CMakeRunConfiguration.imagingutility + 3768 + false + true + false + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 18 + + + Version + 18 + + diff --git a/README.md b/README.md new file mode 100644 index 0000000..0cd8e08 --- /dev/null +++ b/README.md @@ -0,0 +1,103 @@ +# imagingutility + +Raspberry Pi Imaging Utility + +## License + +The main code of the Imaging Utility is made available under the terms of the Apache license. +See license.txt and files in "dependencies" folder for more information about the various open source licenses that apply to the third-party dependencies used such as Qt, libarchive, drivelist, mountutils and libcurl. + +## How to rebuild + +### Debian/Ubuntu Linux + +#### Get dependencies + +Install the build dependencies: + +``` +sudo apt install --no-install-recommends build-essential devscripts debhelper cmake git libarchive-dev libcurl4-openssl-dev \ + qtbase5-dev qtbase5-dev-tools qtdeclarative5-dev \ + qml-module-qtquick2 qml-module-qtquick-controls2 qml-module-qt-labs-settings qml-module-qtquick-layouts qml-module-qtquick-templates2 qml-module-qtquick-window2 qml-module-qtgraphicaleffects +``` + +#### Get the source + +``` +git clone --depth 1 https://github.com/raspberrypi/imagingutility +``` + +#### Build the Debian package + +``` +cd imagingutility +debuild -uc -us +``` + +debuild will compile everything, create a .deb package and put it in the parent directory. +Can install it with apt: + +``` +cd .. +sudo apt install ./imagingutility*.deb +``` + +It should create an icon in the start menu under "Utilities" or "Accessories". +The imaging utility will normally be run as regular user, and will call udisks2 over DBus to perform privileged operations like opening the disk device for writing. +If udisks2 is not functional on your Linux distribution, you can alternatively start it as "root" with sudo and similar tools. + +### Windows + +#### Get dependencies + +- Get the Qt online installer from: https://www.qt.io/download-open-source +During installation, choose a Qt 5.x with Mingw32 32-bit toolchain and CMake. + +- If using the official Qt distribution that does NOT have schannel (Windows native SSL library) support, compile OpenSSL libraries ( https://wiki.qt.io/Compiling_OpenSSL_with_MinGW ) and copy the libssl/crypto DLLs to C:\qt\5.x\mingw73_32\bin + +- For building installer get Nullsoft scriptable install system: https://nsis.sourceforge.io/Download + +- It is assumed you already have a proper code signing certificate, and signtool.exe from the Windows SDK installed. +If NOT and are you only compiling for your own personal use, comment out all lines mentioning signtool from CMakelists.txt and the .nsi installer script. + +#### Building + +Building can be done manually using the command-line, using "cmake", "make", etc., but if you are not that familar with setting up a proper Windows build environment (setting paths, etc.), it is easiest to use the Qt creator GUI instead. + +- Download source .zip from github and extract it to a folder on disk +- Open CMakeLists.txt in Qt creator. +- For builds you distribute to others, make sure you choose "Release" in the toolchain settings and not the debug flavour. +- Menu "Build" -> "Build all" +- Result will be in ../build_imagingutility_someversion +- Go to the BUILD folder, right click on the .nsi script "Compile NSIS script", to create installer. + +Note: the CMake integration in Qt Creator is a bit flaky at times. If you made any custom changes to the CMakeLists.txt file and it subsequently gets in an endless loop where it never finishes the "configures" stage while re-processing the file, delete "build_imagingutility_someversion" directory and try again. + +### Mac OS X + +#### Get dependencies + +- Get the Qt online installer from: https://www.qt.io/download-open-source +During installation, choose a Qt 5.x edition and CMake. +- For creating a .DMG for distribution you can use an utility like: https://github.com/sindresorhus/create-dmg +- It is assumed you have an Apple developer subscription, and already have a "Developer ID" code signing certificate for distribution outside the Mac Store. (Privileged apps are not allowed in the Mac store) + +#### Building + +- Download source .zip from github and extract it to a folder on disk +- Start Qt Creator (may need to start "finder" navigate to home folder using the "Go" menu, and find Qt folder to start it manually as it may not have created icon in Applications), and open CMakeLists.txt +- Menu "Build" -> "Build all" +- Result will be in ../build_imagingutility_someversion +- For distribution to others: code sign the .app, create a DMG, code sign the DMG, submit it for notarization to Apple and staple the notarization ticket to the DMG. + +## Other notes + +### Debugging + +On Linux and Mac the application will print debug messages to console by default if started from console. +On Windows start the application with the command-line option --debug to let it open a console window. + +### Custom repository + +If the application is started with "--repo " it will use a custom image repository. +So can simply create another 'start menu shortcut' to the application with that parameter to use the application with your own images. diff --git a/config.h b/config.h new file mode 100644 index 0000000..b428783 --- /dev/null +++ b/config.h @@ -0,0 +1,35 @@ +#ifndef CONFIG_H +#define CONFIG_H + +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + + +/* Repository URL */ +// #define OSLIST_URL "http://f.maxnet.eu/os_list_imagingutility.json" +#define OSLIST_URL "https://downloads.raspberrypi.org/os_list_imagingutility.json" + +/* Hash algorithm for verifying (uncompressed image) checksum */ +#define OSLIST_HASH_ALGORITHM QCryptographicHash::Sha256 + +/* Hide system drives from list */ +#define DRIVELIST_FILTER_SYSTEM_DRIVES true + +/* Update progressbar every 0.1 second */ +#define PROGRESS_UPDATE_INTERVAL 100 + +/* Block size used for writes (currently used when using .zip images only) */ +#define IMAGEWRITER_BLOCKSIZE 1*1024*1024 + +/* Block size used when reading during verify stage */ +#define IMAGEWRITER_VERIFY_BLOCKSIZE 128*1024 + +/* Enable caching */ +#define IMAGEWRITER_ENABLE_CACHE_DEFAULT true + +/* Do not cache if it would bring free disk space under 5 GB */ +#define IMAGEWRITER_MINIMAL_SPACE_FOR_CACHING 5*1024*1024*1024ll + +#endif // CONFIG_H diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..d6eb1dd --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +imagingutility (1.0) unstable; urgency=medium + + * Initial Release. + + -- Floris Bos Thu, 20 Feb 2020 11:54:04 +0100 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..f599e28 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +10 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..5a90547 --- /dev/null +++ b/debian/control @@ -0,0 +1,18 @@ +Source: imagingutility +Section: admin +Priority: optional +Maintainer: Floris Bos +Build-Depends: debhelper (>= 10), cmake, libarchive-dev, libcurl4-openssl-dev | libcurl4-gnutls-dev, + qtbase5-dev, qtbase5-dev-tools, qtdeclarative5-dev, + qml-module-qtquick2, qml-module-qtquick-controls2, qml-module-qt-labs-settings, qml-module-qtquick-layouts, qml-module-qtquick-templates2, qml-module-qtquick-window2, qml-module-qtgraphicaleffects +Standards-Version: 4.1.2 +Homepage: https://www.raspberrypi.org/ + +Package: imagingutility +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, + qml-module-qtquick2, qml-module-qtquick-controls2, qml-module-qt-labs-settings, qml-module-qtquick-layouts, qml-module-qtquick-templates2, qml-module-qtquick-window2, qml-module-qtgraphicaleffects, + dosfstools, fdisk +Recommends: udisks2 +Description: Raspberry Pi imaging utility + Graphical user-interface to write disk images and format SD cards. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..3dec578 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,31 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: imagingutility +Source: + +Files: * +Copyright: 2020 Raspberry Pi (Trading) Limited +License: Apache-2.0 + +Files: dependencies/mountutils/* dependencies/drivelist/* +Copyright: 2017 Balena.io +License: Apache-2.0 + +Files-Excluded: dependencies/cmcurl/* dependencies/cmliblzma/* dependencies/fat32format/* dependencies/libarchive-3.4.1/* dependencies/zlib-1.2.11/* +Comment: Not used in Linux build (depending on the official packages instead) + +License: Apache-2.0 + 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 + . + https://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. + . + On Debian systems, the complete text of the Apache version 2.0 license + can be found in "/usr/share/common-licenses/Apache-2.0". + diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..64b89e0 --- /dev/null +++ b/debian/rules @@ -0,0 +1,8 @@ +#!/usr/bin/make -f +# See debhelper(7) (uncomment to enable) +# output every command that modifies files on the build system. +#export DH_VERBOSE = 1 + +%: + dh $@ + diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..89ae9db --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (native) diff --git a/dependencies/cmcurl/CMake/CMakeConfigurableFile.in b/dependencies/cmcurl/CMake/CMakeConfigurableFile.in new file mode 100644 index 0000000..df2c382 --- /dev/null +++ b/dependencies/cmcurl/CMake/CMakeConfigurableFile.in @@ -0,0 +1 @@ +@CMAKE_CONFIGURABLE_FILE_CONTENT@ diff --git a/dependencies/cmcurl/CMake/CurlSymbolHiding.cmake b/dependencies/cmcurl/CMake/CurlSymbolHiding.cmake new file mode 100644 index 0000000..60ee8e6 --- /dev/null +++ b/dependencies/cmcurl/CMake/CurlSymbolHiding.cmake @@ -0,0 +1,61 @@ +include(CheckCSourceCompiles) + +option(CURL_HIDDEN_SYMBOLS "Set to ON to hide libcurl internal symbols (=hide all symbols that aren't officially external)." ON) +mark_as_advanced(CURL_HIDDEN_SYMBOLS) + +if(CURL_HIDDEN_SYMBOLS) + set(SUPPORTS_SYMBOL_HIDING FALSE) + + if(CMAKE_C_COMPILER_ID MATCHES "Clang") + set(SUPPORTS_SYMBOL_HIDING TRUE) + set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))") + set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden") + elseif(CMAKE_COMPILER_IS_GNUCC) + if(NOT CMAKE_VERSION VERSION_LESS 2.8.10) + set(GCC_VERSION ${CMAKE_C_COMPILER_VERSION}) + else() + execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion + OUTPUT_VARIABLE GCC_VERSION) + endif() + if(NOT GCC_VERSION VERSION_LESS 3.4) + # note: this is considered buggy prior to 4.0 but the autotools don't care, so let's ignore that fact + set(SUPPORTS_SYMBOL_HIDING TRUE) + set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))") + set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden") + endif() + elseif(CMAKE_C_COMPILER_ID MATCHES "SunPro" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 8.0) + set(SUPPORTS_SYMBOL_HIDING TRUE) + set(_SYMBOL_EXTERN "__global") + set(_CFLAG_SYMBOLS_HIDE "-xldscope=hidden") + elseif(CMAKE_C_COMPILER_ID MATCHES "Intel" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 9.0) + # note: this should probably just check for version 9.1.045 but I'm not 100% sure + # so let's to it the same way autotools do. + set(SUPPORTS_SYMBOL_HIDING TRUE) + set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))") + set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden") + check_c_source_compiles("#include + int main (void) { printf(\"icc fvisibility bug test\"); return 0; }" _no_bug) + if(NOT _no_bug) + set(SUPPORTS_SYMBOL_HIDING FALSE) + set(_SYMBOL_EXTERN "") + set(_CFLAG_SYMBOLS_HIDE "") + endif() + elseif(MSVC) + set(SUPPORTS_SYMBOL_HIDING TRUE) + endif() + + set(HIDES_CURL_PRIVATE_SYMBOLS ${SUPPORTS_SYMBOL_HIDING}) +elseif(MSVC) + if(NOT CMAKE_VERSION VERSION_LESS 3.7) + set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) #present since 3.4.3 but broken + set(HIDES_CURL_PRIVATE_SYMBOLS FALSE) + else() + message(WARNING "Hiding private symbols regardless CURL_HIDDEN_SYMBOLS being disabled.") + set(HIDES_CURL_PRIVATE_SYMBOLS TRUE) + endif() +else() + set(HIDES_CURL_PRIVATE_SYMBOLS FALSE) +endif() + +set(CURL_CFLAG_SYMBOLS_HIDE ${_CFLAG_SYMBOLS_HIDE}) +set(CURL_EXTERN_SYMBOL ${_SYMBOL_EXTERN}) diff --git a/dependencies/cmcurl/CMake/CurlTests.c b/dependencies/cmcurl/CMake/CurlTests.c new file mode 100644 index 0000000..07b516b --- /dev/null +++ b/dependencies/cmcurl/CMake/CurlTests.c @@ -0,0 +1,615 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifdef TIME_WITH_SYS_TIME +/* Time with sys/time test */ + +#include +#include +#include + +int +main () +{ +if ((struct tm *) 0) +return 0; + ; + return 0; +} + +#endif + +#ifdef HAVE_FCNTL_O_NONBLOCK + +/* headers for FCNTL_O_NONBLOCK test */ +#include +#include +#include +/* */ +#if defined(sun) || defined(__sun__) || \ + defined(__SUNPRO_C) || defined(__SUNPRO_CC) +# if defined(__SVR4) || defined(__srv4__) +# define PLATFORM_SOLARIS +# else +# define PLATFORM_SUNOS4 +# endif +#endif +#if (defined(_AIX) || defined(__xlC__)) && !defined(_AIX41) +# define PLATFORM_AIX_V3 +#endif +/* */ +#if defined(PLATFORM_SUNOS4) || defined(PLATFORM_AIX_V3) || defined(__BEOS__) +#error "O_NONBLOCK does not work on this platform" +#endif + +int +main () +{ + /* O_NONBLOCK source test */ + int flags = 0; + if(0 != fcntl(0, F_SETFL, flags | O_NONBLOCK)) + return 1; + return 0; +} +#endif + +/* tests for gethostbyaddr_r or gethostbyname_r */ +#if defined(HAVE_GETHOSTBYADDR_R_5_REENTRANT) || \ + defined(HAVE_GETHOSTBYADDR_R_7_REENTRANT) || \ + defined(HAVE_GETHOSTBYADDR_R_8_REENTRANT) || \ + defined(HAVE_GETHOSTBYNAME_R_3_REENTRANT) || \ + defined(HAVE_GETHOSTBYNAME_R_5_REENTRANT) || \ + defined(HAVE_GETHOSTBYNAME_R_6_REENTRANT) +# define _REENTRANT + /* no idea whether _REENTRANT is always set, just invent a new flag */ +# define TEST_GETHOSTBYFOO_REENTRANT +#endif +#if defined(HAVE_GETHOSTBYADDR_R_5) || \ + defined(HAVE_GETHOSTBYADDR_R_7) || \ + defined(HAVE_GETHOSTBYADDR_R_8) || \ + defined(HAVE_GETHOSTBYNAME_R_3) || \ + defined(HAVE_GETHOSTBYNAME_R_5) || \ + defined(HAVE_GETHOSTBYNAME_R_6) || \ + defined(TEST_GETHOSTBYFOO_REENTRANT) +#include +#include +int main(void) +{ + char *address = "example.com"; + int length = 0; + int type = 0; + struct hostent h; + int rc = 0; +#if defined(HAVE_GETHOSTBYADDR_R_5) || \ + defined(HAVE_GETHOSTBYADDR_R_5_REENTRANT) || \ + \ + defined(HAVE_GETHOSTBYNAME_R_3) || \ + defined(HAVE_GETHOSTBYNAME_R_3_REENTRANT) + struct hostent_data hdata; +#elif defined(HAVE_GETHOSTBYADDR_R_7) || \ + defined(HAVE_GETHOSTBYADDR_R_7_REENTRANT) || \ + defined(HAVE_GETHOSTBYADDR_R_8) || \ + defined(HAVE_GETHOSTBYADDR_R_8_REENTRANT) || \ + \ + defined(HAVE_GETHOSTBYNAME_R_5) || \ + defined(HAVE_GETHOSTBYNAME_R_5_REENTRANT) || \ + defined(HAVE_GETHOSTBYNAME_R_6) || \ + defined(HAVE_GETHOSTBYNAME_R_6_REENTRANT) + char buffer[8192]; + int h_errnop; + struct hostent *hp; +#endif + +#ifndef gethostbyaddr_r + (void)gethostbyaddr_r; +#endif + +#if defined(HAVE_GETHOSTBYADDR_R_5) || \ + defined(HAVE_GETHOSTBYADDR_R_5_REENTRANT) + rc = gethostbyaddr_r(address, length, type, &h, &hdata); +#elif defined(HAVE_GETHOSTBYADDR_R_7) || \ + defined(HAVE_GETHOSTBYADDR_R_7_REENTRANT) + hp = gethostbyaddr_r(address, length, type, &h, buffer, 8192, &h_errnop); + (void)hp; +#elif defined(HAVE_GETHOSTBYADDR_R_8) || \ + defined(HAVE_GETHOSTBYADDR_R_8_REENTRANT) + rc = gethostbyaddr_r(address, length, type, &h, buffer, 8192, &hp, &h_errnop); +#endif + +#if defined(HAVE_GETHOSTBYNAME_R_3) || \ + defined(HAVE_GETHOSTBYNAME_R_3_REENTRANT) + rc = gethostbyname_r(address, &h, &hdata); +#elif defined(HAVE_GETHOSTBYNAME_R_5) || \ + defined(HAVE_GETHOSTBYNAME_R_5_REENTRANT) + rc = gethostbyname_r(address, &h, buffer, 8192, &h_errnop); + (void)hp; /* not used for test */ +#elif defined(HAVE_GETHOSTBYNAME_R_6) || \ + defined(HAVE_GETHOSTBYNAME_R_6_REENTRANT) + rc = gethostbyname_r(address, &h, buffer, 8192, &hp, &h_errnop); +#endif + + (void)length; + (void)type; + (void)rc; + return 0; +} +#endif + +#ifdef HAVE_SOCKLEN_T +#ifdef _WIN32 +#include +#else +#include +#include +#endif +int +main () +{ +if ((socklen_t *) 0) + return 0; +if (sizeof (socklen_t)) + return 0; + ; + return 0; +} +#endif +#ifdef HAVE_IN_ADDR_T +#include +#include +#include + +int +main () +{ +if ((in_addr_t *) 0) + return 0; +if (sizeof (in_addr_t)) + return 0; + ; + return 0; +} +#endif + +#ifdef HAVE_BOOL_T +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_STDBOOL_H +#include +#endif +int +main () +{ +if (sizeof (bool *) ) + return 0; + ; + return 0; +} +#endif + +#ifdef STDC_HEADERS +#include +#include +#include +#include +int main() { return 0; } +#endif +#ifdef RETSIGTYPE_TEST +#include +#include +#ifdef signal +# undef signal +#endif +#ifdef __cplusplus +extern "C" void (*signal (int, void (*)(int)))(int); +#else +void (*signal ()) (); +#endif + +int +main () +{ + return 0; +} +#endif +#ifdef HAVE_INET_NTOA_R_DECL +#include + +typedef void (*func_type)(); + +int main() +{ +#ifndef inet_ntoa_r + func_type func; + func = (func_type)inet_ntoa_r; + (void)func; +#endif + return 0; +} +#endif +#ifdef HAVE_INET_NTOA_R_DECL_REENTRANT +#define _REENTRANT +#include + +typedef void (*func_type)(); + +int main() +{ +#ifndef inet_ntoa_r + func_type func; + func = (func_type)&inet_ntoa_r; + (void)func; +#endif + return 0; +} +#endif +#ifdef HAVE_GETADDRINFO +#include +#include +#include + +int main(void) { + struct addrinfo hints, *ai; + int error; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; +#ifndef getaddrinfo + (void)getaddrinfo; +#endif + error = getaddrinfo("127.0.0.1", "8080", &hints, &ai); + if (error) { + return 1; + } + return 0; +} +#endif +#ifdef HAVE_FILE_OFFSET_BITS +#ifdef _FILE_OFFSET_BITS +#undef _FILE_OFFSET_BITS +#endif +#define _FILE_OFFSET_BITS 64 +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int main () { ; return 0; } +#endif +#ifdef HAVE_IOCTLSOCKET +/* includes start */ +#ifdef HAVE_WINDOWS_H +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include +# ifdef HAVE_WINSOCK2_H +# include +# else +# ifdef HAVE_WINSOCK_H +# include +# endif +# endif +#endif + +int +main () +{ + +/* ioctlsocket source code */ + int socket; + unsigned long flags = ioctlsocket(socket, FIONBIO, &flags); + + ; + return 0; +} + +#endif +#ifdef HAVE_IOCTLSOCKET_CAMEL +/* includes start */ +#ifdef HAVE_WINDOWS_H +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include +# ifdef HAVE_WINSOCK2_H +# include +# else +# ifdef HAVE_WINSOCK_H +# include +# endif +# endif +#endif + +int +main () +{ + +/* IoctlSocket source code */ + if(0 != IoctlSocket(0, 0, 0)) + return 1; + ; + return 0; +} +#endif +#ifdef HAVE_IOCTLSOCKET_CAMEL_FIONBIO +/* includes start */ +#ifdef HAVE_WINDOWS_H +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include +# ifdef HAVE_WINSOCK2_H +# include +# else +# ifdef HAVE_WINSOCK_H +# include +# endif +# endif +#endif + +int +main () +{ + +/* IoctlSocket source code */ + long flags = 0; + if(0 != ioctlsocket(0, FIONBIO, &flags)) + return 1; + ; + return 0; +} +#endif +#ifdef HAVE_IOCTLSOCKET_FIONBIO +/* includes start */ +#ifdef HAVE_WINDOWS_H +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include +# ifdef HAVE_WINSOCK2_H +# include +# else +# ifdef HAVE_WINSOCK_H +# include +# endif +# endif +#endif + +int +main () +{ + + int flags = 0; + if(0 != ioctlsocket(0, FIONBIO, &flags)) + return 1; + + ; + return 0; +} +#endif +#ifdef HAVE_IOCTL_FIONBIO +/* headers for FIONBIO test */ +/* includes start */ +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_SYS_SOCKET_H +# include +#endif +#ifdef HAVE_SYS_IOCTL_H +# include +#endif +#ifdef HAVE_STROPTS_H +# include +#endif + +int +main () +{ + + int flags = 0; + if(0 != ioctl(0, FIONBIO, &flags)) + return 1; + + ; + return 0; +} +#endif +#ifdef HAVE_IOCTL_SIOCGIFADDR +/* headers for FIONBIO test */ +/* includes start */ +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_SYS_SOCKET_H +# include +#endif +#ifdef HAVE_SYS_IOCTL_H +# include +#endif +#ifdef HAVE_STROPTS_H +# include +#endif +#include + +int +main () +{ + struct ifreq ifr; + if(0 != ioctl(0, SIOCGIFADDR, &ifr)) + return 1; + + ; + return 0; +} +#endif +#ifdef HAVE_SETSOCKOPT_SO_NONBLOCK +/* includes start */ +#ifdef HAVE_WINDOWS_H +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include +# ifdef HAVE_WINSOCK2_H +# include +# else +# ifdef HAVE_WINSOCK_H +# include +# endif +# endif +#endif +/* includes start */ +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_SOCKET_H +# include +#endif +/* includes end */ + +int +main () +{ + if(0 != setsockopt(0, SOL_SOCKET, SO_NONBLOCK, 0, 0)) + return 1; + ; + return 0; +} +#endif +#ifdef HAVE_GLIBC_STRERROR_R +#include +#include + +void check(char c) {} + +int +main () { + char buffer[1024]; + /* This will not compile if strerror_r does not return a char* */ + check(strerror_r(EACCES, buffer, sizeof(buffer))[0]); + return 0; +} +#endif +#ifdef HAVE_POSIX_STRERROR_R +#include +#include + +/* float, because a pointer can't be implicitly cast to float */ +void check(float f) {} + +int +main () { + char buffer[1024]; + /* This will not compile if strerror_r does not return an int */ + check(strerror_r(EACCES, buffer, sizeof(buffer))); + return 0; +} +#endif +#ifdef HAVE_FSETXATTR_6 +#include /* header from libc, not from libattr */ +int +main() { + fsetxattr(0, 0, 0, 0, 0, 0); + return 0; +} +#endif +#ifdef HAVE_FSETXATTR_5 +#include /* header from libc, not from libattr */ +int +main() { + fsetxattr(0, 0, 0, 0, 0); + return 0; +} +#endif +#ifdef HAVE_CLOCK_GETTIME_MONOTONIC +#include +int +main() { + struct timespec ts = {0, 0}; + clock_gettime(CLOCK_MONOTONIC, &ts); + return 0; +} +#endif +#ifdef HAVE_BUILTIN_AVAILABLE +int +main() { + if(__builtin_available(macOS 10.12, *)) {} + return 0; +} +#endif +#ifdef HAVE_VARIADIC_MACROS_C99 +#define c99_vmacro3(first, ...) fun3(first, __VA_ARGS__) +#define c99_vmacro2(first, ...) fun2(first, __VA_ARGS__) + +int fun3(int arg1, int arg2, int arg3); +int fun2(int arg1, int arg2); + +int fun3(int arg1, int arg2, int arg3) { + return arg1 + arg2 + arg3; +} +int fun2(int arg1, int arg2) { + return arg1 + arg2; +} + +int +main() { + int res3 = c99_vmacro3(1, 2, 3); + int res2 = c99_vmacro2(1, 2); + (void)res3; + (void)res2; + return 0; +} +#endif +#ifdef HAVE_VARIADIC_MACROS_GCC +#define gcc_vmacro3(first, args...) fun3(first, args) +#define gcc_vmacro2(first, args...) fun2(first, args) + +int fun3(int arg1, int arg2, int arg3); +int fun2(int arg1, int arg2); + +int fun3(int arg1, int arg2, int arg3) { + return arg1 + arg2 + arg3; +} +int fun2(int arg1, int arg2) { + return arg1 + arg2; +} + +int +main() { + int res3 = gcc_vmacro3(1, 2, 3); + int res2 = gcc_vmacro2(1, 2); + (void)res3; + (void)res2; + return 0; +} +#endif diff --git a/dependencies/cmcurl/CMake/FindBrotli.cmake b/dependencies/cmcurl/CMake/FindBrotli.cmake new file mode 100644 index 0000000..351b8f7 --- /dev/null +++ b/dependencies/cmcurl/CMake/FindBrotli.cmake @@ -0,0 +1,20 @@ +include(FindPackageHandleStandardArgs) + +find_path(BROTLI_INCLUDE_DIR "brotli/decode.h") + +find_library(BROTLICOMMON_LIBRARY NAMES brotlicommon) +find_library(BROTLIDEC_LIBRARY NAMES brotlidec) + +find_package_handle_standard_args(BROTLI + FOUND_VAR + BROTLI_FOUND + REQUIRED_VARS + BROTLIDEC_LIBRARY + BROTLICOMMON_LIBRARY + BROTLI_INCLUDE_DIR + FAIL_MESSAGE + "Could NOT find BROTLI" +) + +set(BROTLI_INCLUDE_DIRS ${BROTLI_INCLUDE_DIR}) +set(BROTLI_LIBRARIES ${BROTLICOMMON_LIBRARY} ${BROTLIDEC_LIBRARY}) diff --git a/dependencies/cmcurl/CMake/FindCARES.cmake b/dependencies/cmcurl/CMake/FindCARES.cmake new file mode 100644 index 0000000..723044a --- /dev/null +++ b/dependencies/cmcurl/CMake/FindCARES.cmake @@ -0,0 +1,42 @@ +# - Find c-ares +# Find the c-ares includes and library +# This module defines +# CARES_INCLUDE_DIR, where to find ares.h, etc. +# CARES_LIBRARIES, the libraries needed to use c-ares. +# CARES_FOUND, If false, do not try to use c-ares. +# also defined, but not for general use are +# CARES_LIBRARY, where to find the c-ares library. + +find_path(CARES_INCLUDE_DIR ares.h + /usr/local/include + /usr/include + ) + +set(CARES_NAMES ${CARES_NAMES} cares) +find_library(CARES_LIBRARY + NAMES ${CARES_NAMES} + PATHS /usr/lib /usr/local/lib + ) + +if(CARES_LIBRARY AND CARES_INCLUDE_DIR) + set(CARES_LIBRARIES ${CARES_LIBRARY}) + set(CARES_FOUND "YES") +else() + set(CARES_FOUND "NO") +endif() + + +if(CARES_FOUND) + if(NOT CARES_FIND_QUIETLY) + message(STATUS "Found c-ares: ${CARES_LIBRARIES}") + endif() +else() + if(CARES_FIND_REQUIRED) + message(FATAL_ERROR "Could not find c-ares library") + endif() +endif() + +mark_as_advanced( + CARES_LIBRARY + CARES_INCLUDE_DIR + ) diff --git a/dependencies/cmcurl/CMake/FindGSS.cmake b/dependencies/cmcurl/CMake/FindGSS.cmake new file mode 100644 index 0000000..8a28f2f --- /dev/null +++ b/dependencies/cmcurl/CMake/FindGSS.cmake @@ -0,0 +1,285 @@ +# - Try to find the GSS Kerberos library +# Once done this will define +# +# GSS_ROOT_DIR - Set this variable to the root installation of GSS +# +# Read-Only variables: +# GSS_FOUND - system has the Heimdal library +# GSS_FLAVOUR - "MIT" or "Heimdal" if anything found. +# GSS_INCLUDE_DIR - the Heimdal include directory +# GSS_LIBRARIES - The libraries needed to use GSS +# GSS_LINK_DIRECTORIES - Directories to add to linker search path +# GSS_LINKER_FLAGS - Additional linker flags +# GSS_COMPILER_FLAGS - Additional compiler flags +# GSS_VERSION - This is set to version advertised by pkg-config or read from manifest. +# In case the library is found but no version info available it'll be set to "unknown" + +set(_MIT_MODNAME mit-krb5-gssapi) +set(_HEIMDAL_MODNAME heimdal-gssapi) + +include(CheckIncludeFile) +include(CheckIncludeFiles) +include(CheckTypeSize) + +set(_GSS_ROOT_HINTS + "${GSS_ROOT_DIR}" + "$ENV{GSS_ROOT_DIR}" +) + +# try to find library using system pkg-config if user didn't specify root dir +if(NOT GSS_ROOT_DIR AND NOT "$ENV{GSS_ROOT_DIR}") + if(UNIX) + find_package(PkgConfig QUIET) + pkg_search_module(_GSS_PKG ${_MIT_MODNAME} ${_HEIMDAL_MODNAME}) + list(APPEND _GSS_ROOT_HINTS "${_GSS_PKG_PREFIX}") + elseif(WIN32) + list(APPEND _GSS_ROOT_HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos;InstallDir]") + endif() +endif() + +if(NOT _GSS_FOUND) #not found by pkg-config. Let's take more traditional approach. + find_file(_GSS_CONFIGURE_SCRIPT + NAMES + "krb5-config" + HINTS + ${_GSS_ROOT_HINTS} + PATH_SUFFIXES + bin + NO_CMAKE_PATH + NO_CMAKE_ENVIRONMENT_PATH + ) + + # if not found in user-supplied directories, maybe system knows better + find_file(_GSS_CONFIGURE_SCRIPT + NAMES + "krb5-config" + PATH_SUFFIXES + bin + ) + + if(_GSS_CONFIGURE_SCRIPT) + execute_process( + COMMAND ${_GSS_CONFIGURE_SCRIPT} "--cflags" "gssapi" + OUTPUT_VARIABLE _GSS_CFLAGS + RESULT_VARIABLE _GSS_CONFIGURE_FAILED + ) + message(STATUS "CFLAGS: ${_GSS_CFLAGS}") + if(NOT _GSS_CONFIGURE_FAILED) # 0 means success + # should also work in an odd case when multiple directories are given + string(STRIP "${_GSS_CFLAGS}" _GSS_CFLAGS) + string(REGEX REPLACE " +-I" ";" _GSS_CFLAGS "${_GSS_CFLAGS}") + string(REGEX REPLACE " +-([^I][^ \\t;]*)" ";-\\1" _GSS_CFLAGS "${_GSS_CFLAGS}") + + foreach(_flag ${_GSS_CFLAGS}) + if(_flag MATCHES "^-I.*") + string(REGEX REPLACE "^-I" "" _val "${_flag}") + list(APPEND _GSS_INCLUDE_DIR "${_val}") + else() + list(APPEND _GSS_COMPILER_FLAGS "${_flag}") + endif() + endforeach() + endif() + + execute_process( + COMMAND ${_GSS_CONFIGURE_SCRIPT} "--libs" "gssapi" + OUTPUT_VARIABLE _GSS_LIB_FLAGS + RESULT_VARIABLE _GSS_CONFIGURE_FAILED + ) + message(STATUS "LDFLAGS: ${_GSS_LIB_FLAGS}") + + if(NOT _GSS_CONFIGURE_FAILED) # 0 means success + # this script gives us libraries and link directories. Blah. We have to deal with it. + string(STRIP "${_GSS_LIB_FLAGS}" _GSS_LIB_FLAGS) + string(REGEX REPLACE " +-(L|l)" ";-\\1" _GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}") + string(REGEX REPLACE " +-([^Ll][^ \\t;]*)" ";-\\1" _GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}") + + foreach(_flag ${_GSS_LIB_FLAGS}) + if(_flag MATCHES "^-l.*") + string(REGEX REPLACE "^-l" "" _val "${_flag}") + list(APPEND _GSS_LIBRARIES "${_val}") + elseif(_flag MATCHES "^-L.*") + string(REGEX REPLACE "^-L" "" _val "${_flag}") + list(APPEND _GSS_LINK_DIRECTORIES "${_val}") + else() + list(APPEND _GSS_LINKER_FLAGS "${_flag}") + endif() + endforeach() + endif() + + execute_process( + COMMAND ${_GSS_CONFIGURE_SCRIPT} "--version" + OUTPUT_VARIABLE _GSS_VERSION + RESULT_VARIABLE _GSS_CONFIGURE_FAILED + ) + + # older versions may not have the "--version" parameter. In this case we just don't care. + if(_GSS_CONFIGURE_FAILED) + set(_GSS_VERSION 0) + endif() + + execute_process( + COMMAND ${_GSS_CONFIGURE_SCRIPT} "--vendor" + OUTPUT_VARIABLE _GSS_VENDOR + RESULT_VARIABLE _GSS_CONFIGURE_FAILED + ) + + # older versions may not have the "--vendor" parameter. In this case we just don't care. + if(_GSS_CONFIGURE_FAILED) + set(GSS_FLAVOUR "Heimdal") # most probably, shouldn't really matter + else() + if(_GSS_VENDOR MATCHES ".*H|heimdal.*") + set(GSS_FLAVOUR "Heimdal") + else() + set(GSS_FLAVOUR "MIT") + endif() + endif() + + else() # either there is no config script or we are on platform that doesn't provide one (Windows?) + + find_path(_GSS_INCLUDE_DIR + NAMES + "gssapi/gssapi.h" + HINTS + ${_GSS_ROOT_HINTS} + PATH_SUFFIXES + include + inc + ) + + if(_GSS_INCLUDE_DIR) #jay, we've found something + set(CMAKE_REQUIRED_INCLUDES "${_GSS_INCLUDE_DIR}") + check_include_files( "gssapi/gssapi_generic.h;gssapi/gssapi_krb5.h" _GSS_HAVE_MIT_HEADERS) + + if(_GSS_HAVE_MIT_HEADERS) + set(GSS_FLAVOUR "MIT") + else() + # prevent compiling the header - just check if we can include it + set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D__ROKEN_H__") + check_include_file( "roken.h" _GSS_HAVE_ROKEN_H) + + check_include_file( "heimdal/roken.h" _GSS_HAVE_HEIMDAL_ROKEN_H) + if(_GSS_HAVE_ROKEN_H OR _GSS_HAVE_HEIMDAL_ROKEN_H) + set(GSS_FLAVOUR "Heimdal") + endif() + set(CMAKE_REQUIRED_DEFINITIONS "") + endif() + else() + # I'm not convienced if this is the right way but this is what autotools do at the moment + find_path(_GSS_INCLUDE_DIR + NAMES + "gssapi.h" + HINTS + ${_GSS_ROOT_HINTS} + PATH_SUFFIXES + include + inc + ) + + if(_GSS_INCLUDE_DIR) + set(GSS_FLAVOUR "Heimdal") + endif() + endif() + + # if we have headers, check if we can link libraries + if(GSS_FLAVOUR) + set(_GSS_LIBDIR_SUFFIXES "") + set(_GSS_LIBDIR_HINTS ${_GSS_ROOT_HINTS}) + get_filename_component(_GSS_CALCULATED_POTENTIAL_ROOT "${_GSS_INCLUDE_DIR}" PATH) + list(APPEND _GSS_LIBDIR_HINTS ${_GSS_CALCULATED_POTENTIAL_ROOT}) + + if(WIN32) + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + list(APPEND _GSS_LIBDIR_SUFFIXES "lib/AMD64") + if(GSS_FLAVOUR STREQUAL "MIT") + set(_GSS_LIBNAME "gssapi64") + else() + set(_GSS_LIBNAME "libgssapi") + endif() + else() + list(APPEND _GSS_LIBDIR_SUFFIXES "lib/i386") + if(GSS_FLAVOUR STREQUAL "MIT") + set(_GSS_LIBNAME "gssapi32") + else() + set(_GSS_LIBNAME "libgssapi") + endif() + endif() + else() + list(APPEND _GSS_LIBDIR_SUFFIXES "lib;lib64") # those suffixes are not checked for HINTS + if(GSS_FLAVOUR STREQUAL "MIT") + set(_GSS_LIBNAME "gssapi_krb5") + else() + set(_GSS_LIBNAME "gssapi") + endif() + endif() + + find_library(_GSS_LIBRARIES + NAMES + ${_GSS_LIBNAME} + HINTS + ${_GSS_LIBDIR_HINTS} + PATH_SUFFIXES + ${_GSS_LIBDIR_SUFFIXES} + ) + + endif() + endif() +else() + if(_GSS_PKG_${_MIT_MODNAME}_VERSION) + set(GSS_FLAVOUR "MIT") + set(_GSS_VERSION _GSS_PKG_${_MIT_MODNAME}_VERSION) + else() + set(GSS_FLAVOUR "Heimdal") + set(_GSS_VERSION _GSS_PKG_${_MIT_HEIMDAL}_VERSION) + endif() +endif() + +set(GSS_INCLUDE_DIR ${_GSS_INCLUDE_DIR}) +set(GSS_LIBRARIES ${_GSS_LIBRARIES}) +set(GSS_LINK_DIRECTORIES ${_GSS_LINK_DIRECTORIES}) +set(GSS_LINKER_FLAGS ${_GSS_LINKER_FLAGS}) +set(GSS_COMPILER_FLAGS ${_GSS_COMPILER_FLAGS}) +set(GSS_VERSION ${_GSS_VERSION}) + +if(GSS_FLAVOUR) + if(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "Heimdal") + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.amd64.manifest") + else() + set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.x86.manifest") + endif() + + if(EXISTS "${GSS_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}") + file(STRINGS "${GSS_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}" heimdal_version_str + REGEX "^.*version=\"[0-9]\\.[^\"]+\".*$") + + string(REGEX MATCH "[0-9]\\.[^\"]+" + GSS_VERSION "${heimdal_version_str}") + endif() + + if(NOT GSS_VERSION) + set(GSS_VERSION "Heimdal Unknown") + endif() + elseif(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "MIT") + get_filename_component(_MIT_VERSION "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos\\SDK\\CurrentVersion;VersionString]" NAME CACHE) + if(WIN32 AND _MIT_VERSION) + set(GSS_VERSION "${_MIT_VERSION}") + else() + set(GSS_VERSION "MIT Unknown") + endif() + endif() +endif() + +include(FindPackageHandleStandardArgs) + +set(_GSS_REQUIRED_VARS GSS_LIBRARIES GSS_FLAVOUR) + +find_package_handle_standard_args(GSS + REQUIRED_VARS + ${_GSS_REQUIRED_VARS} + VERSION_VAR + GSS_VERSION + FAIL_MESSAGE + "Could NOT find GSS, try to set the path to GSS root folder in the system variable GSS_ROOT_DIR" +) + +mark_as_advanced(GSS_INCLUDE_DIR GSS_LIBRARIES) diff --git a/dependencies/cmcurl/CMake/FindLibSSH2.cmake b/dependencies/cmcurl/CMake/FindLibSSH2.cmake new file mode 100644 index 0000000..84822db --- /dev/null +++ b/dependencies/cmcurl/CMake/FindLibSSH2.cmake @@ -0,0 +1,35 @@ +# - Try to find the libssh2 library +# Once done this will define +# +# LIBSSH2_FOUND - system has the libssh2 library +# LIBSSH2_INCLUDE_DIR - the libssh2 include directory +# LIBSSH2_LIBRARY - the libssh2 library name + +if(LIBSSH2_INCLUDE_DIR AND LIBSSH2_LIBRARY) + set(LibSSH2_FIND_QUIETLY TRUE) +endif() + +find_path(LIBSSH2_INCLUDE_DIR libssh2.h +) + +find_library(LIBSSH2_LIBRARY NAMES ssh2 +) + +if(LIBSSH2_INCLUDE_DIR) + file(STRINGS "${LIBSSH2_INCLUDE_DIR}/libssh2.h" libssh2_version_str REGEX "^#define[\t ]+LIBSSH2_VERSION_NUM[\t ]+0x[0-9][0-9][0-9][0-9][0-9][0-9].*") + + string(REGEX REPLACE "^.*LIBSSH2_VERSION_NUM[\t ]+0x([0-9][0-9]).*$" "\\1" LIBSSH2_VERSION_MAJOR "${libssh2_version_str}") + string(REGEX REPLACE "^.*LIBSSH2_VERSION_NUM[\t ]+0x[0-9][0-9]([0-9][0-9]).*$" "\\1" LIBSSH2_VERSION_MINOR "${libssh2_version_str}") + string(REGEX REPLACE "^.*LIBSSH2_VERSION_NUM[\t ]+0x[0-9][0-9][0-9][0-9]([0-9][0-9]).*$" "\\1" LIBSSH2_VERSION_PATCH "${libssh2_version_str}") + + string(REGEX REPLACE "^0(.+)" "\\1" LIBSSH2_VERSION_MAJOR "${LIBSSH2_VERSION_MAJOR}") + string(REGEX REPLACE "^0(.+)" "\\1" LIBSSH2_VERSION_MINOR "${LIBSSH2_VERSION_MINOR}") + string(REGEX REPLACE "^0(.+)" "\\1" LIBSSH2_VERSION_PATCH "${LIBSSH2_VERSION_PATCH}") + + set(LIBSSH2_VERSION "${LIBSSH2_VERSION_MAJOR}.${LIBSSH2_VERSION_MINOR}.${LIBSSH2_VERSION_PATCH}") +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(LibSSH2 DEFAULT_MSG LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY ) + +mark_as_advanced(LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY LIBSSH2_VERSION_MAJOR LIBSSH2_VERSION_MINOR LIBSSH2_VERSION_PATCH LIBSSH2_VERSION) diff --git a/dependencies/cmcurl/CMake/FindMbedTLS.cmake b/dependencies/cmcurl/CMake/FindMbedTLS.cmake new file mode 100644 index 0000000..a916395 --- /dev/null +++ b/dependencies/cmcurl/CMake/FindMbedTLS.cmake @@ -0,0 +1,13 @@ +find_path(MBEDTLS_INCLUDE_DIRS mbedtls/ssl.h) + +find_library(MBEDTLS_LIBRARY mbedtls) +find_library(MBEDX509_LIBRARY mbedx509) +find_library(MBEDCRYPTO_LIBRARY mbedcrypto) + +set(MBEDTLS_LIBRARIES "${MBEDTLS_LIBRARY}" "${MBEDX509_LIBRARY}" "${MBEDCRYPTO_LIBRARY}") + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(MBEDTLS DEFAULT_MSG + MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY) + +mark_as_advanced(MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY) diff --git a/dependencies/cmcurl/CMake/FindNGHTTP2.cmake b/dependencies/cmcurl/CMake/FindNGHTTP2.cmake new file mode 100644 index 0000000..348b961 --- /dev/null +++ b/dependencies/cmcurl/CMake/FindNGHTTP2.cmake @@ -0,0 +1,18 @@ +include(FindPackageHandleStandardArgs) + +find_path(NGHTTP2_INCLUDE_DIR "nghttp2/nghttp2.h") + +find_library(NGHTTP2_LIBRARY NAMES nghttp2) + +find_package_handle_standard_args(NGHTTP2 + FOUND_VAR + NGHTTP2_FOUND + REQUIRED_VARS + NGHTTP2_LIBRARY + NGHTTP2_INCLUDE_DIR + FAIL_MESSAGE + "Could NOT find NGHTTP2" +) + +set(NGHTTP2_INCLUDE_DIRS ${NGHTTP2_INCLUDE_DIR}) +set(NGHTTP2_LIBRARIES ${NGHTTP2_LIBRARY}) diff --git a/dependencies/cmcurl/CMake/Macros.cmake b/dependencies/cmcurl/CMake/Macros.cmake new file mode 100644 index 0000000..7f71345 --- /dev/null +++ b/dependencies/cmcurl/CMake/Macros.cmake @@ -0,0 +1,88 @@ +#File defines convenience macros for available feature testing + +# This macro checks if the symbol exists in the library and if it +# does, it prepends library to the list. It is intended to be called +# multiple times with a sequence of possibly dependent libraries in +# order of least-to-most-dependent. Some libraries depend on others +# to link correctly. +macro(check_library_exists_concat LIBRARY SYMBOL VARIABLE) + check_library_exists("${LIBRARY};${CURL_LIBS}" ${SYMBOL} "${CMAKE_LIBRARY_PATH}" + ${VARIABLE}) + if(${VARIABLE}) + set(CURL_LIBS ${LIBRARY} ${CURL_LIBS}) + endif() +endmacro() + +# Check if header file exists and add it to the list. +# This macro is intended to be called multiple times with a sequence of +# possibly dependent header files. Some headers depend on others to be +# compiled correctly. +macro(check_include_file_concat FILE VARIABLE) + check_include_files("${CURL_INCLUDES};${FILE}" ${VARIABLE}) + if(${VARIABLE}) + set(CURL_INCLUDES ${CURL_INCLUDES} ${FILE}) + set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -D${VARIABLE}") + endif() +endmacro() + +# For other curl specific tests, use this macro. +macro(curl_internal_test CURL_TEST) + if(NOT DEFINED "${CURL_TEST}") + set(MACRO_CHECK_FUNCTION_DEFINITIONS + "-D${CURL_TEST} ${CURL_TEST_DEFINES} ${CMAKE_REQUIRED_FLAGS}") + if(CMAKE_REQUIRED_LIBRARIES) + set(CURL_TEST_ADD_LIBRARIES + "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}") + endif() + + message(STATUS "Performing Curl Test ${CURL_TEST}") + try_compile(${CURL_TEST} + ${CMAKE_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/CMake/CurlTests.c + CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} + "${CURL_TEST_ADD_LIBRARIES}" + OUTPUT_VARIABLE OUTPUT) + if(${CURL_TEST}) + set(${CURL_TEST} 1 CACHE INTERNAL "Curl test ${FUNCTION}") + message(STATUS "Performing Curl Test ${CURL_TEST} - Success") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Performing Curl Test ${CURL_TEST} passed with the following output:\n" + "${OUTPUT}\n") + else() + message(STATUS "Performing Curl Test ${CURL_TEST} - Failed") + set(${CURL_TEST} "" CACHE INTERNAL "Curl test ${FUNCTION}") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Performing Curl Test ${CURL_TEST} failed with the following output:\n" + "${OUTPUT}\n") + endif() + endif() +endmacro() + +macro(curl_nroff_check) + find_program(NROFF NAMES gnroff nroff) + if(NROFF) + # Need a way to write to stdin, this will do + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/nroff-input.txt" "test") + # Tests for a valid nroff option to generate a manpage + foreach(_MANOPT "-man" "-mandoc") + execute_process(COMMAND "${NROFF}" ${_MANOPT} + OUTPUT_VARIABLE NROFF_MANOPT_OUTPUT + INPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/nroff-input.txt" + ERROR_QUIET) + # Save the option if it was valid + if(NROFF_MANOPT_OUTPUT) + message("Found *nroff option: -- ${_MANOPT}") + set(NROFF_MANOPT ${_MANOPT}) + set(NROFF_USEFUL ON) + break() + endif() + endforeach() + # No need for the temporary file + file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/nroff-input.txt") + if(NOT NROFF_USEFUL) + message(WARNING "Found no *nroff option to get plaintext from man pages") + endif() + else() + message(WARNING "Found no *nroff program") + endif() +endmacro() diff --git a/dependencies/cmcurl/CMake/OtherTests.cmake b/dependencies/cmcurl/CMake/OtherTests.cmake new file mode 100644 index 0000000..c1c9aa3 --- /dev/null +++ b/dependencies/cmcurl/CMake/OtherTests.cmake @@ -0,0 +1,264 @@ +include(CheckCSourceCompiles) +# The begin of the sources (macros and includes) +set(_source_epilogue "#undef inline") + +macro(add_header_include check header) + if(${check}) + set(_source_epilogue "${_source_epilogue}\n#include <${header}>") + endif() +endmacro() + +set(signature_call_conv) +if(HAVE_WINDOWS_H) + add_header_include(HAVE_WINSOCK2_H "winsock2.h") + add_header_include(HAVE_WINDOWS_H "windows.h") + add_header_include(HAVE_WINSOCK_H "winsock.h") + set(_source_epilogue + "${_source_epilogue}\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif") + set(signature_call_conv "PASCAL") + if(HAVE_LIBWS2_32) + set(CMAKE_REQUIRED_LIBRARIES ws2_32) + endif() +else() + add_header_include(HAVE_SYS_TYPES_H "sys/types.h") + add_header_include(HAVE_SYS_SOCKET_H "sys/socket.h") +endif() + +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + +check_c_source_compiles("${_source_epilogue} +int main(void) { + recv(0, 0, 0, 0); + return 0; +}" curl_cv_recv) +if(curl_cv_recv) + if(NOT DEFINED curl_cv_func_recv_args OR "${curl_cv_func_recv_args}" STREQUAL "unknown") + foreach(recv_retv "int" "ssize_t" ) + foreach(recv_arg1 "SOCKET" "int" ) + foreach(recv_arg2 "char *" "void *" ) + foreach(recv_arg3 "int" "size_t" "socklen_t" "unsigned int") + foreach(recv_arg4 "int" "unsigned int") + if(NOT curl_cv_func_recv_done) + unset(curl_cv_func_recv_test CACHE) + check_c_source_compiles(" + ${_source_epilogue} + extern ${recv_retv} ${signature_call_conv} + recv(${recv_arg1}, ${recv_arg2}, ${recv_arg3}, ${recv_arg4}); + int main(void) { + ${recv_arg1} s=0; + ${recv_arg2} buf=0; + ${recv_arg3} len=0; + ${recv_arg4} flags=0; + ${recv_retv} res = recv(s, buf, len, flags); + (void) res; + return 0; + }" + curl_cv_func_recv_test) + message(STATUS + "Tested: ${recv_retv} recv(${recv_arg1}, ${recv_arg2}, ${recv_arg3}, ${recv_arg4})") + if(curl_cv_func_recv_test) + set(curl_cv_func_recv_args + "${recv_arg1},${recv_arg2},${recv_arg3},${recv_arg4},${recv_retv}") + set(RECV_TYPE_ARG1 "${recv_arg1}") + set(RECV_TYPE_ARG2 "${recv_arg2}") + set(RECV_TYPE_ARG3 "${recv_arg3}") + set(RECV_TYPE_ARG4 "${recv_arg4}") + set(RECV_TYPE_RETV "${recv_retv}") + set(HAVE_RECV 1) + set(curl_cv_func_recv_done 1) + endif() + endif() + endforeach() + endforeach() + endforeach() + endforeach() + endforeach() + else() + string(REGEX REPLACE "^([^,]*),[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG1 "${curl_cv_func_recv_args}") + string(REGEX REPLACE "^[^,]*,([^,]*),[^,]*,[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG2 "${curl_cv_func_recv_args}") + string(REGEX REPLACE "^[^,]*,[^,]*,([^,]*),[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG3 "${curl_cv_func_recv_args}") + string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,([^,]*),[^,]*$" "\\1" RECV_TYPE_ARG4 "${curl_cv_func_recv_args}") + string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,[^,]*,([^,]*)$" "\\1" RECV_TYPE_RETV "${curl_cv_func_recv_args}") + endif() + + if("${curl_cv_func_recv_args}" STREQUAL "unknown") + message(FATAL_ERROR "Cannot find proper types to use for recv args") + endif() +else() + message(FATAL_ERROR "Unable to link function recv") +endif() +set(curl_cv_func_recv_args "${curl_cv_func_recv_args}" CACHE INTERNAL "Arguments for recv") +set(HAVE_RECV 1) + +check_c_source_compiles("${_source_epilogue} +int main(void) { + send(0, 0, 0, 0); + return 0; +}" curl_cv_send) +if(curl_cv_send) + if(NOT DEFINED curl_cv_func_send_args OR "${curl_cv_func_send_args}" STREQUAL "unknown") + foreach(send_retv "int" "ssize_t" ) + foreach(send_arg1 "SOCKET" "int" "ssize_t" ) + foreach(send_arg2 "const char *" "const void *" "void *" "char *") + foreach(send_arg3 "int" "size_t" "socklen_t" "unsigned int") + foreach(send_arg4 "int" "unsigned int") + if(NOT curl_cv_func_send_done) + unset(curl_cv_func_send_test CACHE) + check_c_source_compiles(" + ${_source_epilogue} + extern ${send_retv} ${signature_call_conv} + send(${send_arg1}, ${send_arg2}, ${send_arg3}, ${send_arg4}); + int main(void) { + ${send_arg1} s=0; + ${send_arg2} buf=0; + ${send_arg3} len=0; + ${send_arg4} flags=0; + ${send_retv} res = send(s, buf, len, flags); + (void) res; + return 0; + }" + curl_cv_func_send_test) + message(STATUS + "Tested: ${send_retv} send(${send_arg1}, ${send_arg2}, ${send_arg3}, ${send_arg4})") + if(curl_cv_func_send_test) + string(REGEX REPLACE "(const) .*" "\\1" send_qual_arg2 "${send_arg2}") + string(REGEX REPLACE "const (.*)" "\\1" send_arg2 "${send_arg2}") + set(curl_cv_func_send_args + "${send_arg1},${send_arg2},${send_arg3},${send_arg4},${send_retv},${send_qual_arg2}") + set(SEND_TYPE_ARG1 "${send_arg1}") + set(SEND_TYPE_ARG2 "${send_arg2}") + set(SEND_TYPE_ARG3 "${send_arg3}") + set(SEND_TYPE_ARG4 "${send_arg4}") + set(SEND_TYPE_RETV "${send_retv}") + set(HAVE_SEND 1) + set(curl_cv_func_send_done 1) + endif() + endif() + endforeach() + endforeach() + endforeach() + endforeach() + endforeach() + else() + string(REGEX REPLACE "^([^,]*),[^,]*,[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG1 "${curl_cv_func_send_args}") + string(REGEX REPLACE "^[^,]*,([^,]*),[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG2 "${curl_cv_func_send_args}") + string(REGEX REPLACE "^[^,]*,[^,]*,([^,]*),[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG3 "${curl_cv_func_send_args}") + string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,([^,]*),[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG4 "${curl_cv_func_send_args}") + string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,[^,]*,([^,]*),[^,]*$" "\\1" SEND_TYPE_RETV "${curl_cv_func_send_args}") + string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,([^,]*)$" "\\1" SEND_QUAL_ARG2 "${curl_cv_func_send_args}") + endif() + + if("${curl_cv_func_send_args}" STREQUAL "unknown") + message(FATAL_ERROR "Cannot find proper types to use for send args") + endif() + set(SEND_QUAL_ARG2 "const") +else() + message(FATAL_ERROR "Unable to link function send") +endif() +set(curl_cv_func_send_args "${curl_cv_func_send_args}" CACHE INTERNAL "Arguments for send") +set(HAVE_SEND 1) + +check_c_source_compiles("${_source_epilogue} + int main(void) { + int flag = MSG_NOSIGNAL; + (void)flag; + return 0; + }" HAVE_MSG_NOSIGNAL) + +if(NOT HAVE_WINDOWS_H) + add_header_include(HAVE_SYS_TIME_H "sys/time.h") + add_header_include(TIME_WITH_SYS_TIME "time.h") + add_header_include(HAVE_TIME_H "time.h") +endif() +check_c_source_compiles("${_source_epilogue} +int main(void) { + struct timeval ts; + ts.tv_sec = 0; + ts.tv_usec = 0; + (void)ts; + return 0; +}" HAVE_STRUCT_TIMEVAL) + +set(HAVE_SIG_ATOMIC_T 1) +set(CMAKE_REQUIRED_FLAGS) +if(HAVE_SIGNAL_H) + set(CMAKE_REQUIRED_FLAGS "-DHAVE_SIGNAL_H") + set(CMAKE_EXTRA_INCLUDE_FILES "signal.h") +endif() +check_type_size("sig_atomic_t" SIZEOF_SIG_ATOMIC_T) +if(HAVE_SIZEOF_SIG_ATOMIC_T) + check_c_source_compiles(" + #ifdef HAVE_SIGNAL_H + # include + #endif + int main(void) { + static volatile sig_atomic_t dummy = 0; + (void)dummy; + return 0; + }" HAVE_SIG_ATOMIC_T_NOT_VOLATILE) + if(NOT HAVE_SIG_ATOMIC_T_NOT_VOLATILE) + set(HAVE_SIG_ATOMIC_T_VOLATILE 1) + endif() +endif() + +if(HAVE_WINDOWS_H) + set(CMAKE_EXTRA_INCLUDE_FILES winsock2.h) +else() + set(CMAKE_EXTRA_INCLUDE_FILES) + if(HAVE_SYS_SOCKET_H) + set(CMAKE_EXTRA_INCLUDE_FILES sys/socket.h) + endif() +endif() + +check_type_size("struct sockaddr_storage" SIZEOF_STRUCT_SOCKADDR_STORAGE) +if(HAVE_SIZEOF_STRUCT_SOCKADDR_STORAGE) + set(HAVE_STRUCT_SOCKADDR_STORAGE 1) +endif() + +unset(CMAKE_TRY_COMPILE_TARGET_TYPE) + +if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) + # if not cross-compilation... + include(CheckCSourceRuns) + set(CMAKE_REQUIRED_FLAGS "") + if(HAVE_SYS_POLL_H) + set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H") + elseif(HAVE_POLL_H) + set(CMAKE_REQUIRED_FLAGS "-DHAVE_POLL_H") + endif() + check_c_source_runs(" + #include + #include + + #ifdef HAVE_SYS_POLL_H + # include + #elif HAVE_POLL_H + # include + #endif + + int main(void) + { + if(0 != poll(0, 0, 10)) { + return 1; /* fail */ + } + else { + /* detect the 10.12 poll() breakage */ + struct timeval before, after; + int rc; + size_t us; + + gettimeofday(&before, NULL); + rc = poll(NULL, 0, 500); + gettimeofday(&after, NULL); + + us = (after.tv_sec - before.tv_sec) * 1000000 + + (after.tv_usec - before.tv_usec); + + if(us < 400000) { + return 1; + } + } + return 0; + }" HAVE_POLL_FINE) +endif() + diff --git a/dependencies/cmcurl/CMake/Platforms/WindowsCache.cmake b/dependencies/cmcurl/CMake/Platforms/WindowsCache.cmake new file mode 100644 index 0000000..2dbe1bb --- /dev/null +++ b/dependencies/cmcurl/CMake/Platforms/WindowsCache.cmake @@ -0,0 +1,121 @@ +if(NOT UNIX) + if(WIN32) + set(HAVE_LIBDL 0) + set(HAVE_LIBUCB 0) + set(HAVE_LIBSOCKET 0) + set(NOT_NEED_LIBNSL 0) + set(HAVE_LIBNSL 0) + set(HAVE_GETHOSTNAME 1) + set(HAVE_LIBZ 0) + set(HAVE_LIBCRYPTO 0) + + set(HAVE_DLOPEN 0) + + set(HAVE_ALLOCA_H 0) + set(HAVE_ARPA_INET_H 0) + set(HAVE_DLFCN_H 0) + set(HAVE_FCNTL_H 1) + set(HAVE_INTTYPES_H 0) + set(HAVE_IO_H 1) + set(HAVE_MALLOC_H 1) + set(HAVE_MEMORY_H 1) + set(HAVE_NETDB_H 0) + set(HAVE_NETINET_IF_ETHER_H 0) + set(HAVE_NETINET_IN_H 0) + set(HAVE_NET_IF_H 0) + set(HAVE_PROCESS_H 1) + set(HAVE_PWD_H 0) + set(HAVE_SETJMP_H 1) + set(HAVE_SGTTY_H 0) + set(HAVE_SIGNAL_H 1) + set(HAVE_SOCKIO_H 0) + set(HAVE_STDINT_H 0) + set(HAVE_STDLIB_H 1) + set(HAVE_STRINGS_H 0) + set(HAVE_STRING_H 1) + set(HAVE_SYS_PARAM_H 0) + set(HAVE_SYS_POLL_H 0) + set(HAVE_SYS_SELECT_H 0) + set(HAVE_SYS_SOCKET_H 0) + set(HAVE_SYS_SOCKIO_H 0) + set(HAVE_SYS_STAT_H 1) + set(HAVE_SYS_TIME_H 0) + set(HAVE_SYS_TYPES_H 1) + set(HAVE_SYS_UTIME_H 1) + set(HAVE_TERMIOS_H 0) + set(HAVE_TERMIO_H 0) + set(HAVE_TIME_H 1) + set(HAVE_UNISTD_H 0) + set(HAVE_UTIME_H 0) + set(HAVE_X509_H 0) + set(HAVE_ZLIB_H 0) + + set(HAVE_SOCKET 1) + set(HAVE_POLL 0) + set(HAVE_SELECT 1) + set(HAVE_STRDUP 1) + set(HAVE_STRSTR 1) + set(HAVE_STRTOK_R 0) + set(HAVE_STRFTIME 1) + set(HAVE_UNAME 0) + set(HAVE_STRCASECMP 0) + set(HAVE_STRICMP 1) + set(HAVE_STRCMPI 1) + set(HAVE_GETHOSTBYADDR 1) + set(HAVE_GETTIMEOFDAY 0) + set(HAVE_INET_ADDR 1) + set(HAVE_INET_NTOA 1) + set(HAVE_INET_NTOA_R 0) + set(HAVE_TCGETATTR 0) + set(HAVE_TCSETATTR 0) + set(HAVE_PERROR 1) + set(HAVE_CLOSESOCKET 1) + set(HAVE_SETVBUF 0) + set(HAVE_SIGSETJMP 0) + set(HAVE_GETPASS_R 0) + set(HAVE_STRLCAT 0) + set(HAVE_GETPWUID 0) + set(HAVE_GETEUID 0) + set(HAVE_UTIME 1) + set(HAVE_RAND_EGD 0) + set(HAVE_RAND_SCREEN 0) + set(HAVE_RAND_STATUS 0) + set(HAVE_GMTIME_R 0) + set(HAVE_LOCALTIME_R 0) + set(HAVE_GETHOSTBYADDR_R 0) + set(HAVE_GETHOSTBYNAME_R 0) + set(HAVE_SIGNAL_FUNC 1) + set(HAVE_SIGNAL_MACRO 0) + + set(HAVE_GETHOSTBYADDR_R_5 0) + set(HAVE_GETHOSTBYADDR_R_5_REENTRANT 0) + set(HAVE_GETHOSTBYADDR_R_7 0) + set(HAVE_GETHOSTBYADDR_R_7_REENTRANT 0) + set(HAVE_GETHOSTBYADDR_R_8 0) + set(HAVE_GETHOSTBYADDR_R_8_REENTRANT 0) + set(HAVE_GETHOSTBYNAME_R_3 0) + set(HAVE_GETHOSTBYNAME_R_3_REENTRANT 0) + set(HAVE_GETHOSTBYNAME_R_5 0) + set(HAVE_GETHOSTBYNAME_R_5_REENTRANT 0) + set(HAVE_GETHOSTBYNAME_R_6 0) + set(HAVE_GETHOSTBYNAME_R_6_REENTRANT 0) + + set(TIME_WITH_SYS_TIME 0) + set(HAVE_O_NONBLOCK 0) + set(HAVE_IN_ADDR_T 0) + set(HAVE_INET_NTOA_R_DECL 0) + set(HAVE_INET_NTOA_R_DECL_REENTRANT 0) + if(ENABLE_IPV6) + set(HAVE_GETADDRINFO 1) + else() + set(HAVE_GETADDRINFO 0) + endif() + set(STDC_HEADERS 1) + set(RETSIGTYPE_TEST 1) + + set(HAVE_SIGACTION 0) + set(HAVE_MACRO_SIGSETJMP 0) + else() + message("This file should be included on Windows platform only") + endif() +endif() diff --git a/dependencies/cmcurl/CMake/Utilities.cmake b/dependencies/cmcurl/CMake/Utilities.cmake new file mode 100644 index 0000000..5cb1d44 --- /dev/null +++ b/dependencies/cmcurl/CMake/Utilities.cmake @@ -0,0 +1,13 @@ +# File containing various utilities + +# Returns a list of arguments that evaluate to true +function(count_true output_count_var) + set(lst) + foreach(option_var IN LISTS ARGN) + if(${option_var}) + list(APPEND lst ${option_var}) + endif() + endforeach() + list(LENGTH lst lst_len) + set(${output_count_var} ${lst_len} PARENT_SCOPE) +endfunction() diff --git a/dependencies/cmcurl/CMake/cmake_uninstall.cmake.in b/dependencies/cmcurl/CMake/cmake_uninstall.cmake.in new file mode 100644 index 0000000..5178fd8 --- /dev/null +++ b/dependencies/cmcurl/CMake/cmake_uninstall.cmake.in @@ -0,0 +1,26 @@ +if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") +endif() + +if(NOT DEFINED CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@") +endif() +message(${CMAKE_INSTALL_PREFIX}) + +file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) +string(REGEX REPLACE "\n" ";" files "${files}") +foreach(file ${files}) + message(STATUS "Uninstalling $ENV{DESTDIR}${file}") + if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") + exec_program( + "@CMAKE_COMMAND@" ARGS "-E rm -f \"$ENV{DESTDIR}${file}\"" + OUTPUT_VARIABLE rm_out + RETURN_VALUE rm_retval + ) + if(NOT "${rm_retval}" STREQUAL 0) + message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") + endif() + else() + message(STATUS "File $ENV{DESTDIR}${file} does not exist.") + endif() +endforeach() diff --git a/dependencies/cmcurl/CMake/curl-config.cmake.in b/dependencies/cmcurl/CMake/curl-config.cmake.in new file mode 100644 index 0000000..1294e17 --- /dev/null +++ b/dependencies/cmcurl/CMake/curl-config.cmake.in @@ -0,0 +1,12 @@ +@PACKAGE_INIT@ + +include(CMakeFindDependencyMacro) +if(@USE_OPENSSL@) + find_dependency(OpenSSL @OPENSSL_VERSION_MAJOR@) +endif() +if(@USE_ZLIB@) + find_dependency(ZLIB @ZLIB_VERSION_MAJOR@) +endif() + +include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake") +check_required_components("@PROJECT_NAME@") diff --git a/dependencies/cmcurl/CMakeLists.txt b/dependencies/cmcurl/CMakeLists.txt new file mode 100644 index 0000000..7109433 --- /dev/null +++ b/dependencies/cmcurl/CMakeLists.txt @@ -0,0 +1,1502 @@ +# Set curl options as needed for CMake build +set(BUILD_CURL_EXE OFF CACHE INTERNAL "No curl exe") +set(BUILD_DASHBOARD_REPORTS OFF CACHE INTERNAL "No curl dashboard reports") +set(BUILD_RELEASE_DEBUG_DIRS OFF CACHE INTERNAL "No curl release/debug dirs") +set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "Build shared libraries") +set(CMAKE_USE_GSSAPI OFF CACHE INTERNAL "Disable curl gssapi") +set(CMAKE_USE_LIBSSH2 OFF CACHE INTERNAL "Disable curl libssh2") +set(CMAKE_USE_OPENLDAP OFF CACHE INTERNAL "No curl OpenLDAP") +set(CURL_DISABLE_COOKIES OFF CACHE INTERNAL "Do not disable curl cookie support") +set(CURL_DISABLE_CRYPTO_AUTH OFF CACHE INTERNAL "Do not disable curl crypto auth") +set(CURL_DISABLE_DICT ON CACHE INTERNAL "Disable curl dict protocol?") +set(CURL_DISABLE_FILE OFF CACHE INTERNAL "Disable curl file protocol?") +set(CURL_DISABLE_FTP OFF CACHE INTERNAL "Disable curl ftp protocol?") +set(CURL_DISABLE_GOPHER ON CACHE INTERNAL "Disable curl gopher protocol?") +set(CURL_DISABLE_HTTP OFF CACHE INTERNAL "Disable curl http protocol?") +set(CURL_DISABLE_IMAP ON CACHE INTERNAL "Disable curl imap protocol?") +set(CURL_DISABLE_LDAP ON CACHE INTERNAL "Disable curl ldap protocol?") +set(CURL_DISABLE_LDAPS ON CACHE INTERNAL "Disable curl ldaps protocol?") +set(CURL_DISABLE_POP3 ON CACHE INTERNAL "Disable curl pop3 protocol?") +set(CURL_DISABLE_PROXY OFF CACHE INTERNAL "Do not disable curl proxy") +set(CURL_DISABLE_RTSP ON CACHE INTERNAL "Disable curl rtsp protocol?") +set(CURL_DISABLE_SMTP ON CACHE INTERNAL "Disable curl smtp protocol?") +set(CURL_DISABLE_TELNET ON CACHE INTERNAL "Disable curl telnet protocol?") +set(CURL_DISABLE_TFTP ON CACHE INTERNAL "Disable curl tftp protocol?") +set(CURL_DISABLE_VERBOSE_STRINGS OFF CACHE INTERNAL "Do not disable curl verbosity") +set(CURL_HIDDEN_SYMBOLS OFF CACHE INTERNAL "No curl hidden symbols") +set(CURL_WERROR OFF CACHE INTERNAL "Turn compiler warnings into errors") +set(DISABLED_THREADSAFE OFF CACHE INTERNAL "Curl can use thread-safe functions") +set(ENABLE_ARES OFF CACHE INTERNAL "No curl c-ares support") +set(ENABLE_CURLDEBUG OFF CACHE INTERNAL "No curl TrackMemory features") +set(ENABLE_DEBUG OFF CACHE INTERNAL "No curl debug features") +set(ENABLE_IPV6 ON CACHE INTERNAL "Enable curl IPv6 support detection") +set(ENABLE_MANUAL OFF CACHE INTERNAL "No curl built-in manual") +set(ENABLE_THREADED_RESOLVER OFF CACHE INTERNAL "No curl POSIX threaded DNS lookup") +set(ENABLE_UNIX_SOCKETS OFF CACHE INTERNAL "No curl Unix domain sockets support") +set(HTTP_ONLY OFF CACHE INTERNAL "Curl is not http-only") +set(PICKY_COMPILER OFF CACHE INTERNAL "Enable picky compiler options") +set(USE_WIN32_LDAP OFF CACHE INTERNAL "No curl Windows LDAP") +if(CMAKE_USE_OPENSSL) +elseif(WIN32) + set(CMAKE_USE_WINSSL ON CACHE INTERNAL "enable Windows native SSL/TLS") + set(CURL_WINDOWS_SSPI ON CACHE INTERNAL "Use windows libraries to allow NTLM authentication without openssl") +elseif(APPLE) + # Use OS X SSL/TLS native implementation if available on target version. + if(CMAKE_OSX_DEPLOYMENT_TARGET) + set(OSX_VERSION ${CMAKE_OSX_DEPLOYMENT_TARGET}) + else() + execute_process( + COMMAND sw_vers -productVersion + OUTPUT_VARIABLE OSX_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + endif() + if(NOT OSX_VERSION VERSION_LESS 10.6 AND + CMAKE_C_COMPILER_ID MATCHES "GNU|Clang|AppleClang") + set(CMAKE_USE_SECTRANSP ON CACHE INTERNAL "enable Apple OS native SSL/TLS") + else() + set(CMAKE_USE_SECTRANSP OFF CACHE INTERNAL "enable Apple OS native SSL/TLS") + endif() + unset(CMAKE_USE_DARWINSSL CACHE) +endif() +set(CMAKE_USE_MBEDTLS OFF CACHE INTERNAL "Enable mbedTLS for SSL/TLS") + +# Windows Vista and above have inet_pton, but this will link on +# older versions and then the executable will fail to launch at +# runtime on older versions because no DLL provides the symbol. +if(WIN32) + set(HAVE_INET_PTON 0 CACHE INTERNAL "Do not use inet_pton") +endif() + +# Starting with OSX 10.11 there is an unrelated libnetwork library which will +# be picked up during curl configuration. Linking against this library is +# unnecessary and breaks backward compatibility of the resulting binaries +# because libnetwork is unavailable on older OSX versions. +if(APPLE) + set(HAVE_LIBNETWORK 0 CACHE INTERNAL "Do not use libnetwork") +endif(APPLE) + +# Disable warnings to avoid changing 3rd party code. +if(CMAKE_C_COMPILER_ID MATCHES + "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel)$") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w") +elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall") +endif() + +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.haxx.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +########################################################################### +# curl/libcurl CMake script +# by Tetetest and Sukender (Benoit Neil) + +# TODO: +# The output .so file lacks the soname number which we currently have within the lib/Makefile.am file +# Add full (4 or 5 libs) SSL support +# Add INSTALL target (EXTRA_DIST variables in Makefile.am may be moved to Makefile.inc so that CMake/CPack is aware of what's to include). +# Add CTests(?) +# Check on all possible platforms +# Test with as many configurations possible (With or without any option) +# Create scripts that help keeping the CMake build system up to date (to reduce maintenance). According to Tetetest: +# - lists of headers that 'configure' checks for; +# - curl-specific tests (the ones that are in m4/curl-*.m4 files); +# - (most obvious thing:) curl version numbers. +# Add documentation subproject +# +# To check: +# (From Daniel Stenberg) The cmake build selected to run gcc with -fPIC on my box while the plain configure script did not. +# (From Daniel Stenberg) The gcc command line use neither -g nor any -O options. As a developer, I also treasure our configure scripts's --enable-debug option that sets a long range of "picky" compiler options. +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}") +include(Utilities) +include(Macros) +include(CMakeDependentOption) +include(CheckCCompilerFlag) + +project(CURL C) + +if(0) # This code not needed for building within CMake. +message(WARNING "the curl cmake build system is poorly maintained. Be aware") +endif() + +file(READ ${CURL_SOURCE_DIR}/include/curl/curlver.h CURL_VERSION_H_CONTENTS) +string(REGEX MATCH "#define LIBCURL_VERSION \"[^\"]*" + CURL_VERSION ${CURL_VERSION_H_CONTENTS}) +string(REGEX REPLACE "[^\"]+\"" "" CURL_VERSION ${CURL_VERSION}) +string(REGEX MATCH "#define LIBCURL_VERSION_NUM 0x[0-9a-fA-F]+" + CURL_VERSION_NUM ${CURL_VERSION_H_CONTENTS}) +string(REGEX REPLACE "[^0]+0x" "" CURL_VERSION_NUM ${CURL_VERSION_NUM}) + + +# Setup package meta-data +# SET(PACKAGE "curl") +if(0) # This code not needed for building within CMake. +message(STATUS "curl version=[${CURL_VERSION}]") +endif() +# SET(PACKAGE_TARNAME "curl") +# SET(PACKAGE_NAME "curl") +# SET(PACKAGE_VERSION "-") +# SET(PACKAGE_STRING "curl-") +# SET(PACKAGE_BUGREPORT "a suitable curl mailing list => https://curl.haxx.se/mail/") +set(OPERATING_SYSTEM "${CMAKE_SYSTEM_NAME}") +set(OS "\"${CMAKE_SYSTEM_NAME}\"") + +include_directories(${CURL_SOURCE_DIR}/include) + +option(CURL_WERROR "Turn compiler warnings into errors" OFF) +option(PICKY_COMPILER "Enable picky compiler options" ON) +option(BUILD_CURL_EXE "Set to ON to build curl executable." ON) +option(BUILD_SHARED_LIBS "Build shared libraries" ON) +option(ENABLE_ARES "Set to ON to enable c-ares support" OFF) +if(WIN32) + option(CURL_STATIC_CRT "Set to ON to build libcurl with static CRT on Windows (/MT)." OFF) + option(ENABLE_INET_PTON "Set to OFF to prevent usage of inet_pton when building against modern SDKs while still requiring compatibility with older Windows versions, such as Windows XP, Windows Server 2003 etc." ON) +endif() + +if(0) # This code not needed for building within CMake. +cmake_dependent_option(ENABLE_THREADED_RESOLVER "Set to ON to enable threaded DNS lookup" + ON "NOT ENABLE_ARES" + OFF) +endif() + +option(ENABLE_DEBUG "Set to ON to enable curl debug features" OFF) +option(ENABLE_CURLDEBUG "Set to ON to build with TrackMemory feature enabled" OFF) + +if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG) + if(PICKY_COMPILER) + foreach(_CCOPT -pedantic -Wall -W -Wpointer-arith -Wwrite-strings -Wunused -Wshadow -Winline -Wnested-externs -Wmissing-declarations -Wmissing-prototypes -Wno-long-long -Wfloat-equal -Wno-multichar -Wsign-compare -Wundef -Wno-format-nonliteral -Wendif-labels -Wstrict-prototypes -Wdeclaration-after-statement -Wstrict-aliasing=3 -Wcast-align -Wtype-limits -Wold-style-declaration -Wmissing-parameter-type -Wempty-body -Wclobbered -Wignored-qualifiers -Wconversion -Wno-sign-conversion -Wvla -Wdouble-promotion -Wno-system-headers -Wno-pedantic-ms-format) + # surprisingly, CHECK_C_COMPILER_FLAG needs a new variable to store each new + # test result in. + check_c_compiler_flag(${_CCOPT} OPT${_CCOPT}) + if(OPT${_CCOPT}) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_CCOPT}") + endif() + endforeach() + endif() +endif() + +if(ENABLE_DEBUG) + # DEBUGBUILD will be defined only for Debug builds + set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS $<$:DEBUGBUILD>) + set(ENABLE_CURLDEBUG ON) +endif() + +if(ENABLE_CURLDEBUG) + set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS CURLDEBUG) +endif() + +if(0) # This code not needed for building within CMake. +# For debug libs and exes, add "-d" postfix +if(NOT DEFINED CMAKE_DEBUG_POSTFIX) + set(CMAKE_DEBUG_POSTFIX "-d") +endif() +endif() + +# initialize CURL_LIBS +set(CURL_LIBS "") + +if(ENABLE_ARES) + set(USE_ARES 1) + find_package(CARES REQUIRED) + list(APPEND CURL_LIBS ${CARES_LIBRARY}) + set(CURL_LIBS ${CURL_LIBS} ${CARES_LIBRARY}) +endif() + +if(0) # This code not needed for building within CMake. +include(CurlSymbolHiding) +endif() + +option(HTTP_ONLY "disables all protocols except HTTP (This overrides all CURL_DISABLE_* options)" OFF) +mark_as_advanced(HTTP_ONLY) +option(CURL_DISABLE_FTP "disables FTP" OFF) +mark_as_advanced(CURL_DISABLE_FTP) +option(CURL_DISABLE_LDAP "disables LDAP" OFF) +mark_as_advanced(CURL_DISABLE_LDAP) +option(CURL_DISABLE_TELNET "disables Telnet" OFF) +mark_as_advanced(CURL_DISABLE_TELNET) +option(CURL_DISABLE_DICT "disables DICT" OFF) +mark_as_advanced(CURL_DISABLE_DICT) +option(CURL_DISABLE_FILE "disables FILE" OFF) +mark_as_advanced(CURL_DISABLE_FILE) +option(CURL_DISABLE_TFTP "disables TFTP" OFF) +mark_as_advanced(CURL_DISABLE_TFTP) +option(CURL_DISABLE_HTTP "disables HTTP" OFF) +mark_as_advanced(CURL_DISABLE_HTTP) + +option(CURL_DISABLE_LDAPS "to disable LDAPS" OFF) +mark_as_advanced(CURL_DISABLE_LDAPS) + +option(CURL_DISABLE_RTSP "to disable RTSP" OFF) +mark_as_advanced(CURL_DISABLE_RTSP) +option(CURL_DISABLE_PROXY "to disable proxy" OFF) +mark_as_advanced(CURL_DISABLE_PROXY) +option(CURL_DISABLE_POP3 "to disable POP3" OFF) +mark_as_advanced(CURL_DISABLE_POP3) +option(CURL_DISABLE_IMAP "to disable IMAP" OFF) +mark_as_advanced(CURL_DISABLE_IMAP) +option(CURL_DISABLE_SMTP "to disable SMTP" OFF) +mark_as_advanced(CURL_DISABLE_SMTP) +option(CURL_DISABLE_GOPHER "to disable Gopher" OFF) +mark_as_advanced(CURL_DISABLE_GOPHER) + +if(HTTP_ONLY) + set(CURL_DISABLE_FTP ON) + set(CURL_DISABLE_LDAP ON) + set(CURL_DISABLE_LDAPS ON) + set(CURL_DISABLE_TELNET ON) + set(CURL_DISABLE_DICT ON) + set(CURL_DISABLE_FILE ON) + set(CURL_DISABLE_TFTP ON) + set(CURL_DISABLE_RTSP ON) + set(CURL_DISABLE_POP3 ON) + set(CURL_DISABLE_IMAP ON) + set(CURL_DISABLE_SMTP ON) + set(CURL_DISABLE_GOPHER ON) +endif() + +option(CURL_DISABLE_COOKIES "to disable cookies support" OFF) +mark_as_advanced(CURL_DISABLE_COOKIES) + +option(CURL_DISABLE_CRYPTO_AUTH "to disable cryptographic authentication" OFF) +mark_as_advanced(CURL_DISABLE_CRYPTO_AUTH) +option(CURL_DISABLE_VERBOSE_STRINGS "to disable verbose strings" OFF) +mark_as_advanced(CURL_DISABLE_VERBOSE_STRINGS) +option(ENABLE_IPV6 "Define if you want to enable IPv6 support" ON) +mark_as_advanced(ENABLE_IPV6) +if(ENABLE_IPV6 AND NOT WIN32) + include(CheckStructHasMember) + check_struct_has_member("struct sockaddr_in6" sin6_addr "netinet/in.h" + HAVE_SOCKADDR_IN6_SIN6_ADDR) + check_struct_has_member("struct sockaddr_in6" sin6_scope_id "netinet/in.h" + HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) + if(NOT HAVE_SOCKADDR_IN6_SIN6_ADDR) + message(WARNING "struct sockaddr_in6 not available, disabling IPv6 support") + # Force the feature off as this name is used as guard macro... + set(ENABLE_IPV6 OFF + CACHE BOOL "Define if you want to enable IPv6 support" FORCE) + endif() +endif() + +if(0) # This code not needed for building within CMake. +# Required for building manual, docs, tests +curl_nroff_check() +find_package(Perl) + +cmake_dependent_option(ENABLE_MANUAL "to provide the built-in manual" + ON "NROFF_USEFUL;PERL_FOUND" + OFF) + +if(NOT PERL_FOUND) + message(STATUS "Perl not found, testing disabled.") + set(BUILD_TESTING OFF) +endif() +if(ENABLE_MANUAL) + set(USE_MANUAL ON) +endif() +endif() + +# We need ansi c-flags, especially on HP +set(CMAKE_C_FLAGS "${CMAKE_ANSI_CFLAGS} ${CMAKE_C_FLAGS}") +set(CMAKE_REQUIRED_FLAGS ${CMAKE_ANSI_CFLAGS}) + +if(CURL_STATIC_CRT) + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MTd") +endif() + +# Disable warnings on Borland to avoid changing 3rd party code. +if(BORLAND) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w-") +endif() + +# If we are on AIX, do the _ALL_SOURCE magic +if(${CMAKE_SYSTEM_NAME} MATCHES AIX) + set(_ALL_SOURCE 1) +endif() + +# Include all the necessary files for macros +include(CheckFunctionExists) +include(CheckIncludeFile) +include(CheckIncludeFiles) +include(CheckLibraryExists) +include(CheckSymbolExists) +include(CheckTypeSize) +include(CheckCSourceCompiles) + +# On windows preload settings +if(WIN32) + set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WINSOCKAPI_=") + include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/Platforms/WindowsCache.cmake) +endif() + +if(ENABLE_THREADED_RESOLVER) + find_package(Threads REQUIRED) + if(WIN32) + set(USE_THREADS_WIN32 ON) + else() + set(USE_THREADS_POSIX ${CMAKE_USE_PTHREADS_INIT}) + set(HAVE_PTHREAD_H ${CMAKE_USE_PTHREADS_INIT}) + endif() + set(CURL_LIBS ${CURL_LIBS} ${CMAKE_THREAD_LIBS_INIT}) +endif() + +# Check for all needed libraries +if(0) # This code not needed for building within CMake. +check_library_exists_concat("dl" dlopen HAVE_LIBDL) +else() + # Use the cmake-defined dl libs as dl is should not be used + # on HPUX, but rather dld this avoids a warning + list(APPEND CURL_LIBS ${CMAKE_DL_LIBS}) +endif() +check_library_exists_concat("socket" connect HAVE_LIBSOCKET) +check_library_exists("c" gethostbyname "" NOT_NEED_LIBNSL) + +# Yellowtab Zeta needs different libraries than BeOS 5. +if(BEOS) + set(NOT_NEED_LIBNSL 1) + check_library_exists_concat("bind" gethostbyname HAVE_LIBBIND) + check_library_exists_concat("bnetapi" closesocket HAVE_LIBBNETAPI) +endif() + +check_library_exists_concat("network" recv HAVE_LIBNETWORK) + +if(NOT NOT_NEED_LIBNSL) + check_library_exists_concat("nsl" gethostbyname HAVE_LIBNSL) +endif() + +check_function_exists(gethostname HAVE_GETHOSTNAME) + +if(WIN32) + check_library_exists_concat("ws2_32" getch HAVE_LIBWS2_32) + check_library_exists_concat("winmm" getch HAVE_LIBWINMM) + list(APPEND CURL_LIBS "advapi32") +endif() + +# check SSL libraries +# TODO support GNUTLS, NSS, POLARSSL, CYASSL + +if(APPLE) + option(CMAKE_USE_SECTRANSP "enable Apple OS native SSL/TLS" OFF) +endif() +if(WIN32) + option(CMAKE_USE_WINSSL "enable Windows native SSL/TLS" OFF) + cmake_dependent_option(CURL_WINDOWS_SSPI "Use windows libraries to allow NTLM authentication without openssl" ON + CMAKE_USE_WINSSL OFF) +endif() +option(CMAKE_USE_MBEDTLS "Enable mbedTLS for SSL/TLS" OFF) + +set(openssl_default ON) +if(WIN32 OR CMAKE_USE_SECTRANSP OR CMAKE_USE_WINSSL OR CMAKE_USE_MBEDTLS) + set(openssl_default OFF) +endif() + +count_true(enabled_ssl_options_count + CMAKE_USE_WINSSL + CMAKE_USE_SECTRANSP + CMAKE_USE_OPENSSL + CMAKE_USE_MBEDTLS +) +if(enabled_ssl_options_count GREATER "1") + set(CURL_WITH_MULTI_SSL ON) +endif() + +if(CMAKE_USE_WINSSL) + set(SSL_ENABLED ON) + set(USE_SCHANNEL ON) # Windows native SSL/TLS support + set(USE_WINDOWS_SSPI ON) # CMAKE_USE_WINSSL implies CURL_WINDOWS_SSPI + list(APPEND CURL_LIBS "crypt32") +endif() +if(CURL_WINDOWS_SSPI) + set(USE_WINDOWS_SSPI ON) + set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -DSECURITY_WIN32") +endif() + +if(CMAKE_USE_DARWINSSL) + message(FATAL_ERROR "The cmake option CMAKE_USE_DARWINSSL was renamed to CMAKE_USE_SECTRANSP.") +endif() + +if(CMAKE_USE_SECTRANSP) + find_library(COREFOUNDATION_FRAMEWORK "CoreFoundation") + if(NOT COREFOUNDATION_FRAMEWORK) + message(FATAL_ERROR "CoreFoundation framework not found") + endif() + + find_library(SECURITY_FRAMEWORK "Security") + if(NOT SECURITY_FRAMEWORK) + message(FATAL_ERROR "Security framework not found") + endif() + + set(SSL_ENABLED ON) + set(USE_SECTRANSP ON) + list(APPEND CURL_LIBS "${COREFOUNDATION_FRAMEWORK}" "${SECURITY_FRAMEWORK}") +endif() + +if(CMAKE_USE_OPENSSL) + find_package(OpenSSL) + if(NOT OpenSSL_FOUND) + message(FATAL_ERROR + "Could not find OpenSSL. Install an OpenSSL development package or " + "configure CMake with -DCMAKE_USE_OPENSSL=OFF to build without OpenSSL.") + endif() + set(SSL_ENABLED ON) + set(USE_OPENSSL ON) + set(HAVE_LIBCRYPTO ON) + set(HAVE_LIBSSL ON) + list(APPEND CURL_LIBS ${OPENSSL_LIBRARIES}) + include_directories(${OPENSSL_INCLUDE_DIR}) + + set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) + check_include_file("openssl/crypto.h" HAVE_OPENSSL_CRYPTO_H) + check_include_file("openssl/err.h" HAVE_OPENSSL_ERR_H) + check_include_file("openssl/pem.h" HAVE_OPENSSL_PEM_H) + check_include_file("openssl/rsa.h" HAVE_OPENSSL_RSA_H) + check_include_file("openssl/ssl.h" HAVE_OPENSSL_SSL_H) + check_include_file("openssl/x509.h" HAVE_OPENSSL_X509_H) + check_include_file("openssl/rand.h" HAVE_OPENSSL_RAND_H) + check_symbol_exists(RAND_status "${CURL_INCLUDES}" HAVE_RAND_STATUS) + check_symbol_exists(RAND_screen "${CURL_INCLUDES}" HAVE_RAND_SCREEN) + check_symbol_exists(RAND_egd "${CURL_INCLUDES}" HAVE_RAND_EGD) + + # Optionally build with a specific CA cert bundle. + if(CURL_CA_BUNDLE) + add_definitions(-DCURL_CA_BUNDLE="${CURL_CA_BUNDLE}") + endif() + # Optionally build with a specific CA cert dir. + if(CURL_CA_PATH) + add_definitions(-DCURL_CA_PATH="${CURL_CA_PATH}") + endif() +endif() + +if(CMAKE_USE_MBEDTLS) + find_package(MbedTLS REQUIRED) + set(SSL_ENABLED ON) + set(USE_MBEDTLS ON) + list(APPEND CURL_LIBS ${MBEDTLS_LIBRARIES}) + include_directories(${MBEDTLS_INCLUDE_DIRS}) +endif() + +option(USE_NGHTTP2 "Use Nghttp2 library" OFF) +if(USE_NGHTTP2) + find_package(NGHTTP2 REQUIRED) + include_directories(${NGHTTP2_INCLUDE_DIRS}) + list(APPEND CURL_LIBS ${NGHTTP2_LIBRARIES}) +endif() + +if(NOT CURL_DISABLE_LDAP) + if(WIN32) + option(USE_WIN32_LDAP "Use Windows LDAP implementation" ON) + if(USE_WIN32_LDAP) + check_library_exists_concat("wldap32" cldap_open HAVE_WLDAP32) + if(NOT HAVE_WLDAP32) + set(USE_WIN32_LDAP OFF) + endif() + endif() + endif() + + option(CMAKE_USE_OPENLDAP "Use OpenLDAP code." OFF) + mark_as_advanced(CMAKE_USE_OPENLDAP) + set(CMAKE_LDAP_LIB "ldap" CACHE STRING "Name or full path to ldap library") + set(CMAKE_LBER_LIB "lber" CACHE STRING "Name or full path to lber library") + + if(CMAKE_USE_OPENLDAP AND USE_WIN32_LDAP) + message(FATAL_ERROR "Cannot use USE_WIN32_LDAP and CMAKE_USE_OPENLDAP at the same time") + endif() + + # Now that we know, we're not using windows LDAP... + if(USE_WIN32_LDAP) + check_include_file_concat("winldap.h" HAVE_WINLDAP_H) + check_include_file_concat("winber.h" HAVE_WINBER_H) + else() + # Check for LDAP + set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_LIBRARIES}) + check_library_exists_concat(${CMAKE_LDAP_LIB} ldap_init HAVE_LIBLDAP) + check_library_exists_concat(${CMAKE_LBER_LIB} ber_init HAVE_LIBLBER) + + set(CMAKE_REQUIRED_INCLUDES_BAK ${CMAKE_REQUIRED_INCLUDES}) + set(CMAKE_LDAP_INCLUDE_DIR "" CACHE STRING "Path to LDAP include directory") + if(CMAKE_LDAP_INCLUDE_DIR) + list(APPEND CMAKE_REQUIRED_INCLUDES ${CMAKE_LDAP_INCLUDE_DIR}) + endif() + check_include_file_concat("ldap.h" HAVE_LDAP_H) + check_include_file_concat("lber.h" HAVE_LBER_H) + + if(NOT HAVE_LDAP_H) + message(STATUS "LDAP_H not found CURL_DISABLE_LDAP set ON") + set(CURL_DISABLE_LDAP ON CACHE BOOL "" FORCE) + set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES_BAK}) #LDAP includes won't be used + elseif(NOT HAVE_LIBLDAP) + message(STATUS "LDAP library '${CMAKE_LDAP_LIB}' not found CURL_DISABLE_LDAP set ON") + set(CURL_DISABLE_LDAP ON CACHE BOOL "" FORCE) + set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES_BAK}) #LDAP includes won't be used + else() + if(CMAKE_USE_OPENLDAP) + set(USE_OPENLDAP ON) + endif() + if(CMAKE_LDAP_INCLUDE_DIR) + include_directories(${CMAKE_LDAP_INCLUDE_DIR}) + endif() + set(NEED_LBER_H ON) + set(_HEADER_LIST) + if(HAVE_WINDOWS_H) + list(APPEND _HEADER_LIST "windows.h") + endif() + if(HAVE_SYS_TYPES_H) + list(APPEND _HEADER_LIST "sys/types.h") + endif() + list(APPEND _HEADER_LIST "ldap.h") + + set(_SRC_STRING "") + foreach(_HEADER ${_HEADER_LIST}) + set(_INCLUDE_STRING "${_INCLUDE_STRING}#include <${_HEADER}>\n") + endforeach() + + set(_SRC_STRING + " + ${_INCLUDE_STRING} + int main(int argc, char ** argv) + { + BerValue *bvp = NULL; + BerElement *bep = ber_init(bvp); + ber_free(bep, 1); + return 0; + }" + ) + set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -DLDAP_DEPRECATED=1") + list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LDAP_LIB}) + if(HAVE_LIBLBER) + list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LBER_LIB}) + endif() + check_c_source_compiles("${_SRC_STRING}" NOT_NEED_LBER_H) + unset(CMAKE_REQUIRED_LIBRARIES) + + if(NOT_NEED_LBER_H) + set(NEED_LBER_H OFF) + else() + set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -DNEED_LBER_H") + endif() + endif() + endif() +endif() + +# No ldap, no ldaps. +if(CURL_DISABLE_LDAP) + if(NOT CURL_DISABLE_LDAPS) + message(STATUS "LDAP needs to be enabled to support LDAPS") + set(CURL_DISABLE_LDAPS ON CACHE BOOL "" FORCE) + endif() +endif() + +if(NOT CURL_DISABLE_LDAPS) + check_include_file_concat("ldap_ssl.h" HAVE_LDAP_SSL_H) + check_include_file_concat("ldapssl.h" HAVE_LDAPSSL_H) +endif() + +# Check for idn +check_library_exists_concat("idn2" idn2_lookup_ul HAVE_LIBIDN2) + +# Check for symbol dlopen (same as HAVE_LIBDL) +check_library_exists("${CURL_LIBS}" dlopen "" HAVE_DLOPEN) + +if(0) # This code not needed for building within CMake. +option(CURL_ZLIB "Set to ON to enable building curl with zlib support." ON) +set(HAVE_LIBZ OFF) +set(HAVE_ZLIB_H OFF) +set(USE_ZLIB OFF) +if(CURL_ZLIB) + find_package(ZLIB QUIET) + if(ZLIB_FOUND) + set(HAVE_ZLIB_H ON) + set(HAVE_LIBZ ON) + set(USE_ZLIB ON) + + # Depend on ZLIB via imported targets if supported by the running + # version of CMake. This allows our dependents to get our dependencies + # transitively. + if(NOT CMAKE_VERSION VERSION_LESS 3.4) + list(APPEND CURL_LIBS ZLIB::ZLIB) + else() + list(APPEND CURL_LIBS ${ZLIB_LIBRARIES}) + include_directories(${ZLIB_INCLUDE_DIRS}) + endif() + list(APPEND CMAKE_REQUIRED_INCLUDES ${ZLIB_INCLUDE_DIRS}) + endif() +endif() +endif() + +#----------------------------------------------------------------------------- +# CMake-specific curl code. + +if(CURL_SPECIAL_LIBZ) + set(CURL_LIBS ${CURL_LIBS} "${CURL_SPECIAL_LIBZ}") + include_directories(${CURL_SPECIAL_LIBZ_INCLUDES}) + set(HAVE_LIBZ 0) + set(HAVE_ZLIB_H 0) +endif() + +option(CURL_BROTLI "Set to ON to enable building curl with brotli support." OFF) +set(HAVE_BROTLI OFF) +if(CURL_BROTLI) + find_package(BROTLI QUIET) + if(BROTLI_FOUND) + set(HAVE_BROTLI ON) + list(APPEND CURL_LIBS ${BROTLI_LIBRARIES}) + include_directories(${BROTLI_INCLUDE_DIRS}) + list(APPEND CMAKE_REQUIRED_INCLUDES ${BROTLI_INCLUDE_DIRS}) + endif() +endif() + +#libSSH2 +option(CMAKE_USE_LIBSSH2 "Use libSSH2" ON) +mark_as_advanced(CMAKE_USE_LIBSSH2) +set(USE_LIBSSH2 OFF) +set(HAVE_LIBSSH2 OFF) +set(HAVE_LIBSSH2_H OFF) + +if(CMAKE_USE_LIBSSH2) + find_package(LibSSH2) + if(LIBSSH2_FOUND) + list(APPEND CURL_LIBS ${LIBSSH2_LIBRARY}) + set(CMAKE_REQUIRED_LIBRARIES ${LIBSSH2_LIBRARY}) + list(APPEND CMAKE_REQUIRED_INCLUDES "${LIBSSH2_INCLUDE_DIR}") + include_directories("${LIBSSH2_INCLUDE_DIR}") + set(HAVE_LIBSSH2 ON) + set(USE_LIBSSH2 ON) + + # find_package has already found the headers + set(HAVE_LIBSSH2_H ON) + set(CURL_INCLUDES ${CURL_INCLUDES} "${LIBSSH2_INCLUDE_DIR}/libssh2.h") + set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -DHAVE_LIBSSH2_H") + + # now check for specific libssh2 symbols as they were added in different versions + set(CMAKE_EXTRA_INCLUDE_FILES "libssh2.h") + check_function_exists(libssh2_version HAVE_LIBSSH2_VERSION) + check_function_exists(libssh2_init HAVE_LIBSSH2_INIT) + check_function_exists(libssh2_exit HAVE_LIBSSH2_EXIT) + check_function_exists(libssh2_scp_send64 HAVE_LIBSSH2_SCP_SEND64) + check_function_exists(libssh2_session_handshake HAVE_LIBSSH2_SESSION_HANDSHAKE) + set(CMAKE_EXTRA_INCLUDE_FILES "") + unset(CMAKE_REQUIRED_LIBRARIES) + endif() +endif() + +option(CMAKE_USE_GSSAPI "Use GSSAPI implementation (right now only Heimdal is supported with CMake build)" OFF) +mark_as_advanced(CMAKE_USE_GSSAPI) + +if(CMAKE_USE_GSSAPI) + find_package(GSS) + + set(HAVE_GSSAPI ${GSS_FOUND}) + if(GSS_FOUND) + + message(STATUS "Found ${GSS_FLAVOUR} GSSAPI version: \"${GSS_VERSION}\"") + + list(APPEND CMAKE_REQUIRED_INCLUDES ${GSS_INCLUDE_DIR}) + check_include_file_concat("gssapi/gssapi.h" HAVE_GSSAPI_GSSAPI_H) + check_include_file_concat("gssapi/gssapi_generic.h" HAVE_GSSAPI_GSSAPI_GENERIC_H) + check_include_file_concat("gssapi/gssapi_krb5.h" HAVE_GSSAPI_GSSAPI_KRB5_H) + + if(GSS_FLAVOUR STREQUAL "Heimdal") + set(HAVE_GSSHEIMDAL ON) + else() # MIT + set(HAVE_GSSMIT ON) + set(_INCLUDE_LIST "") + if(HAVE_GSSAPI_GSSAPI_H) + list(APPEND _INCLUDE_LIST "gssapi/gssapi.h") + endif() + if(HAVE_GSSAPI_GSSAPI_GENERIC_H) + list(APPEND _INCLUDE_LIST "gssapi/gssapi_generic.h") + endif() + if(HAVE_GSSAPI_GSSAPI_KRB5_H) + list(APPEND _INCLUDE_LIST "gssapi/gssapi_krb5.h") + endif() + + string(REPLACE ";" " " _COMPILER_FLAGS_STR "${GSS_COMPILER_FLAGS}") + string(REPLACE ";" " " _LINKER_FLAGS_STR "${GSS_LINKER_FLAGS}") + + foreach(_dir ${GSS_LINK_DIRECTORIES}) + set(_LINKER_FLAGS_STR "${_LINKER_FLAGS_STR} -L\"${_dir}\"") + endforeach() + + set(CMAKE_REQUIRED_FLAGS "${_COMPILER_FLAGS_STR} ${_LINKER_FLAGS_STR}") + set(CMAKE_REQUIRED_LIBRARIES ${GSS_LIBRARIES}) + check_symbol_exists("GSS_C_NT_HOSTBASED_SERVICE" ${_INCLUDE_LIST} HAVE_GSS_C_NT_HOSTBASED_SERVICE) + if(NOT HAVE_GSS_C_NT_HOSTBASED_SERVICE) + set(HAVE_OLD_GSSMIT ON) + endif() + unset(CMAKE_REQUIRED_LIBRARIES) + + endif() + + include_directories(${GSS_INCLUDE_DIR}) + link_directories(${GSS_LINK_DIRECTORIES}) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GSS_COMPILER_FLAGS}") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${GSS_LINKER_FLAGS}") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GSS_LINKER_FLAGS}") + list(APPEND CURL_LIBS ${GSS_LIBRARIES}) + + else() + message(WARNING "GSSAPI support has been requested but no supporting libraries found. Skipping.") + endif() +endif() + +option(ENABLE_UNIX_SOCKETS "Define if you want Unix domain sockets support" ON) +if(ENABLE_UNIX_SOCKETS) + include(CheckStructHasMember) + check_struct_has_member("struct sockaddr_un" sun_path "sys/un.h" USE_UNIX_SOCKETS) +else() + unset(USE_UNIX_SOCKETS CACHE) +endif() + + +if(0) # This code not needed for building within CMake. +# +# CA handling +# +set(CURL_CA_BUNDLE "auto" CACHE STRING + "Path to the CA bundle. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.") +set(CURL_CA_FALLBACK OFF CACHE BOOL + "Set ON to use built-in CA store of TLS backend. Defaults to OFF") +set(CURL_CA_PATH "auto" CACHE STRING + "Location of default CA path. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.") + +if("${CURL_CA_BUNDLE}" STREQUAL "") + message(FATAL_ERROR "Invalid value of CURL_CA_BUNDLE. Use 'none', 'auto' or file path.") +elseif("${CURL_CA_BUNDLE}" STREQUAL "none") + unset(CURL_CA_BUNDLE CACHE) +elseif("${CURL_CA_BUNDLE}" STREQUAL "auto") + unset(CURL_CA_BUNDLE CACHE) + set(CURL_CA_BUNDLE_AUTODETECT TRUE) +else() + set(CURL_CA_BUNDLE_SET TRUE) +endif() + +if("${CURL_CA_PATH}" STREQUAL "") + message(FATAL_ERROR "Invalid value of CURL_CA_PATH. Use 'none', 'auto' or directory path.") +elseif("${CURL_CA_PATH}" STREQUAL "none") + unset(CURL_CA_PATH CACHE) +elseif("${CURL_CA_PATH}" STREQUAL "auto") + unset(CURL_CA_PATH CACHE) + set(CURL_CA_PATH_AUTODETECT TRUE) +else() + set(CURL_CA_PATH_SET TRUE) +endif() + +if(CURL_CA_BUNDLE_SET AND CURL_CA_PATH_AUTODETECT) + # Skip autodetection of unset CA path because CA bundle is set explicitly +elseif(CURL_CA_PATH_SET AND CURL_CA_BUNDLE_AUTODETECT) + # Skip autodetection of unset CA bundle because CA path is set explicitly +elseif(CURL_CA_PATH_AUTODETECT OR CURL_CA_BUNDLE_AUTODETECT) + # first try autodetecting a CA bundle, then a CA path + + if(CURL_CA_BUNDLE_AUTODETECT) + set(SEARCH_CA_BUNDLE_PATHS + /etc/ssl/certs/ca-certificates.crt + /etc/pki/tls/certs/ca-bundle.crt + /usr/share/ssl/certs/ca-bundle.crt + /usr/local/share/certs/ca-root-nss.crt + /etc/ssl/cert.pem) + + foreach(SEARCH_CA_BUNDLE_PATH ${SEARCH_CA_BUNDLE_PATHS}) + if(EXISTS "${SEARCH_CA_BUNDLE_PATH}") + message(STATUS "Found CA bundle: ${SEARCH_CA_BUNDLE_PATH}") + set(CURL_CA_BUNDLE "${SEARCH_CA_BUNDLE_PATH}") + set(CURL_CA_BUNDLE_SET TRUE CACHE BOOL "Path to the CA bundle has been set") + break() + endif() + endforeach() + endif() + + if(CURL_CA_PATH_AUTODETECT AND (NOT CURL_CA_PATH_SET)) + if(EXISTS "/etc/ssl/certs") + set(CURL_CA_PATH "/etc/ssl/certs") + set(CURL_CA_PATH_SET TRUE CACHE BOOL "Path to the CA bundle has been set") + endif() + endif() +endif() + +if(CURL_CA_PATH_SET AND NOT USE_OPENSSL AND NOT USE_MBEDTLS) + message(FATAL_ERROR + "CA path only supported by OpenSSL, GnuTLS or mbed TLS. " + "Set CURL_CA_PATH=none or enable one of those TLS backends.") +endif() +endif() + +# Check for header files +if(NOT UNIX) + check_include_file_concat("windows.h" HAVE_WINDOWS_H) + check_include_file_concat("winsock.h" HAVE_WINSOCK_H) + check_include_file_concat("ws2tcpip.h" HAVE_WS2TCPIP_H) + check_include_file_concat("winsock2.h" HAVE_WINSOCK2_H) + if(NOT CURL_WINDOWS_SSPI AND USE_OPENSSL) + set(CURL_LIBS ${CURL_LIBS} "crypt32") + endif() +else() + set(HAVE_WINDOWS_H 0) + set(HAVE_WINSOCK_H 0) + set(HAVE_WS2TCPIP_H 0) + set(HAVE_WINSOCK2_H 0) +endif() + +check_include_file_concat("stdio.h" HAVE_STDIO_H) +check_include_file_concat("inttypes.h" HAVE_INTTYPES_H) +check_include_file_concat("sys/filio.h" HAVE_SYS_FILIO_H) +check_include_file_concat("sys/ioctl.h" HAVE_SYS_IOCTL_H) +check_include_file_concat("sys/param.h" HAVE_SYS_PARAM_H) +check_include_file_concat("sys/poll.h" HAVE_SYS_POLL_H) +check_include_file_concat("sys/resource.h" HAVE_SYS_RESOURCE_H) +check_include_file_concat("sys/select.h" HAVE_SYS_SELECT_H) +check_include_file_concat("sys/socket.h" HAVE_SYS_SOCKET_H) +check_include_file_concat("sys/sockio.h" HAVE_SYS_SOCKIO_H) +check_include_file_concat("sys/stat.h" HAVE_SYS_STAT_H) +check_include_file_concat("sys/time.h" HAVE_SYS_TIME_H) +check_include_file_concat("sys/types.h" HAVE_SYS_TYPES_H) +check_include_file_concat("sys/uio.h" HAVE_SYS_UIO_H) +check_include_file_concat("sys/un.h" HAVE_SYS_UN_H) +check_include_file_concat("sys/utime.h" HAVE_SYS_UTIME_H) +check_include_file_concat("sys/xattr.h" HAVE_SYS_XATTR_H) +check_include_file_concat("alloca.h" HAVE_ALLOCA_H) +check_include_file_concat("arpa/inet.h" HAVE_ARPA_INET_H) +check_include_file_concat("arpa/tftp.h" HAVE_ARPA_TFTP_H) +check_include_file_concat("assert.h" HAVE_ASSERT_H) +check_include_file_concat("crypto.h" HAVE_CRYPTO_H) +check_include_file_concat("des.h" HAVE_DES_H) +check_include_file_concat("err.h" HAVE_ERR_H) +check_include_file_concat("errno.h" HAVE_ERRNO_H) +check_include_file_concat("fcntl.h" HAVE_FCNTL_H) +check_include_file_concat("idn2.h" HAVE_IDN2_H) +check_include_file_concat("ifaddrs.h" HAVE_IFADDRS_H) +check_include_file_concat("io.h" HAVE_IO_H) +check_include_file_concat("krb.h" HAVE_KRB_H) +check_include_file_concat("libgen.h" HAVE_LIBGEN_H) +check_include_file_concat("locale.h" HAVE_LOCALE_H) +check_include_file_concat("net/if.h" HAVE_NET_IF_H) +check_include_file_concat("netdb.h" HAVE_NETDB_H) +check_include_file_concat("netinet/in.h" HAVE_NETINET_IN_H) +check_include_file_concat("netinet/tcp.h" HAVE_NETINET_TCP_H) + +check_include_file_concat("pem.h" HAVE_PEM_H) +check_include_file_concat("poll.h" HAVE_POLL_H) +check_include_file_concat("pwd.h" HAVE_PWD_H) +check_include_file_concat("rsa.h" HAVE_RSA_H) +check_include_file_concat("setjmp.h" HAVE_SETJMP_H) +check_include_file_concat("sgtty.h" HAVE_SGTTY_H) +check_include_file_concat("signal.h" HAVE_SIGNAL_H) +check_include_file_concat("ssl.h" HAVE_SSL_H) +check_include_file_concat("stdbool.h" HAVE_STDBOOL_H) +check_include_file_concat("stdint.h" HAVE_STDINT_H) +check_include_file_concat("stdio.h" HAVE_STDIO_H) +check_include_file_concat("stdlib.h" HAVE_STDLIB_H) +check_include_file_concat("string.h" HAVE_STRING_H) +check_include_file_concat("strings.h" HAVE_STRINGS_H) +check_include_file_concat("stropts.h" HAVE_STROPTS_H) +check_include_file_concat("termio.h" HAVE_TERMIO_H) +check_include_file_concat("termios.h" HAVE_TERMIOS_H) +check_include_file_concat("time.h" HAVE_TIME_H) +check_include_file_concat("unistd.h" HAVE_UNISTD_H) +check_include_file_concat("utime.h" HAVE_UTIME_H) +check_include_file_concat("x509.h" HAVE_X509_H) + +check_include_file_concat("process.h" HAVE_PROCESS_H) +check_include_file_concat("stddef.h" HAVE_STDDEF_H) +check_include_file_concat("dlfcn.h" HAVE_DLFCN_H) +check_include_file_concat("malloc.h" HAVE_MALLOC_H) +check_include_file_concat("memory.h" HAVE_MEMORY_H) +check_include_file_concat("netinet/if_ether.h" HAVE_NETINET_IF_ETHER_H) +check_include_file_concat("stdint.h" HAVE_STDINT_H) +check_include_file_concat("sockio.h" HAVE_SOCKIO_H) +check_include_file_concat("sys/utsname.h" HAVE_SYS_UTSNAME_H) + +check_type_size(size_t SIZEOF_SIZE_T) +check_type_size(ssize_t SIZEOF_SSIZE_T) +check_type_size("long long" SIZEOF_LONG_LONG) +check_type_size("long" SIZEOF_LONG) +check_type_size("short" SIZEOF_SHORT) +check_type_size("int" SIZEOF_INT) +check_type_size("__int64" SIZEOF___INT64) +check_type_size("time_t" SIZEOF_TIME_T) + +if(HAVE_SIZEOF_LONG_LONG) + set(HAVE_LONGLONG 1) + set(HAVE_LL 1) +endif() + +find_file(RANDOM_FILE urandom /dev) +mark_as_advanced(RANDOM_FILE) + +# Check for some functions that are used +if(HAVE_LIBWS2_32) + set(CMAKE_REQUIRED_LIBRARIES ws2_32) +elseif(HAVE_LIBSOCKET) + set(CMAKE_REQUIRED_LIBRARIES socket) +elseif(HAVE_LIBNETWORK) + set(CMAKE_REQUIRED_LIBRARIES network) +endif() + +check_symbol_exists(basename "${CURL_INCLUDES}" HAVE_BASENAME) +check_symbol_exists(socket "${CURL_INCLUDES}" HAVE_SOCKET) +check_symbol_exists(select "${CURL_INCLUDES}" HAVE_SELECT) +check_symbol_exists(poll "${CURL_INCLUDES}" HAVE_POLL) +check_symbol_exists(strdup "${CURL_INCLUDES}" HAVE_STRDUP) +check_symbol_exists(strstr "${CURL_INCLUDES}" HAVE_STRSTR) +check_symbol_exists(strtok_r "${CURL_INCLUDES}" HAVE_STRTOK_R) +check_symbol_exists(strftime "${CURL_INCLUDES}" HAVE_STRFTIME) +check_symbol_exists(uname "${CURL_INCLUDES}" HAVE_UNAME) +check_symbol_exists(strcasecmp "${CURL_INCLUDES}" HAVE_STRCASECMP) +check_symbol_exists(stricmp "${CURL_INCLUDES}" HAVE_STRICMP) +check_symbol_exists(strcmpi "${CURL_INCLUDES}" HAVE_STRCMPI) +check_symbol_exists(strncmpi "${CURL_INCLUDES}" HAVE_STRNCMPI) +check_symbol_exists(alarm "${CURL_INCLUDES}" HAVE_ALARM) +if(NOT HAVE_STRNCMPI) + set(HAVE_STRCMPI) +endif() +check_symbol_exists(gethostbyaddr "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR) +check_symbol_exists(gethostbyaddr_r "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR_R) +check_symbol_exists(gettimeofday "${CURL_INCLUDES}" HAVE_GETTIMEOFDAY) +check_symbol_exists(inet_addr "${CURL_INCLUDES}" HAVE_INET_ADDR) +check_symbol_exists(inet_ntoa "${CURL_INCLUDES}" HAVE_INET_NTOA) +check_symbol_exists(inet_ntoa_r "${CURL_INCLUDES}" HAVE_INET_NTOA_R) +check_symbol_exists(tcsetattr "${CURL_INCLUDES}" HAVE_TCSETATTR) +check_symbol_exists(tcgetattr "${CURL_INCLUDES}" HAVE_TCGETATTR) +check_symbol_exists(perror "${CURL_INCLUDES}" HAVE_PERROR) +check_symbol_exists(closesocket "${CURL_INCLUDES}" HAVE_CLOSESOCKET) +check_symbol_exists(setvbuf "${CURL_INCLUDES}" HAVE_SETVBUF) +check_symbol_exists(sigsetjmp "${CURL_INCLUDES}" HAVE_SIGSETJMP) +check_symbol_exists(getpass_r "${CURL_INCLUDES}" HAVE_GETPASS_R) +check_symbol_exists(strlcat "${CURL_INCLUDES}" HAVE_STRLCAT) +check_symbol_exists(getpwuid "${CURL_INCLUDES}" HAVE_GETPWUID) +check_symbol_exists(getpwuid_r "${CURL_INCLUDES}" HAVE_GETPWUID_R) +check_symbol_exists(geteuid "${CURL_INCLUDES}" HAVE_GETEUID) +check_symbol_exists(utime "${CURL_INCLUDES}" HAVE_UTIME) +check_symbol_exists(gmtime_r "${CURL_INCLUDES}" HAVE_GMTIME_R) +check_symbol_exists(localtime_r "${CURL_INCLUDES}" HAVE_LOCALTIME_R) + +check_symbol_exists(gethostbyname "${CURL_INCLUDES}" HAVE_GETHOSTBYNAME) +check_symbol_exists(gethostbyname_r "${CURL_INCLUDES}" HAVE_GETHOSTBYNAME_R) + +check_symbol_exists(signal "${CURL_INCLUDES}" HAVE_SIGNAL_FUNC) +check_symbol_exists(SIGALRM "${CURL_INCLUDES}" HAVE_SIGNAL_MACRO) +if(HAVE_SIGNAL_FUNC AND HAVE_SIGNAL_MACRO) + set(HAVE_SIGNAL 1) +endif() +check_symbol_exists(uname "${CURL_INCLUDES}" HAVE_UNAME) +check_symbol_exists(strtoll "${CURL_INCLUDES}" HAVE_STRTOLL) +check_symbol_exists(_strtoi64 "${CURL_INCLUDES}" HAVE__STRTOI64) +check_symbol_exists(strerror_r "${CURL_INCLUDES}" HAVE_STRERROR_R) +check_symbol_exists(siginterrupt "${CURL_INCLUDES}" HAVE_SIGINTERRUPT) +check_symbol_exists(perror "${CURL_INCLUDES}" HAVE_PERROR) +check_symbol_exists(fork "${CURL_INCLUDES}" HAVE_FORK) +check_symbol_exists(getaddrinfo "${CURL_INCLUDES}" HAVE_GETADDRINFO) +check_symbol_exists(freeaddrinfo "${CURL_INCLUDES}" HAVE_FREEADDRINFO) +check_symbol_exists(freeifaddrs "${CURL_INCLUDES}" HAVE_FREEIFADDRS) +check_symbol_exists(pipe "${CURL_INCLUDES}" HAVE_PIPE) +check_symbol_exists(ftruncate "${CURL_INCLUDES}" HAVE_FTRUNCATE) +check_symbol_exists(getprotobyname "${CURL_INCLUDES}" HAVE_GETPROTOBYNAME) +check_symbol_exists(getpeername "${CURL_INCLUDES}" HAVE_GETPEERNAME) +check_symbol_exists(getsockname "${CURL_INCLUDES}" HAVE_GETSOCKNAME) +check_symbol_exists(getrlimit "${CURL_INCLUDES}" HAVE_GETRLIMIT) +check_symbol_exists(setlocale "${CURL_INCLUDES}" HAVE_SETLOCALE) +check_symbol_exists(setmode "${CURL_INCLUDES}" HAVE_SETMODE) +check_symbol_exists(setrlimit "${CURL_INCLUDES}" HAVE_SETRLIMIT) +check_symbol_exists(fcntl "${CURL_INCLUDES}" HAVE_FCNTL) +check_symbol_exists(ioctl "${CURL_INCLUDES}" HAVE_IOCTL) +check_symbol_exists(setsockopt "${CURL_INCLUDES}" HAVE_SETSOCKOPT) +check_function_exists(mach_absolute_time HAVE_MACH_ABSOLUTE_TIME) + +# symbol exists in win32, but function does not. +if(WIN32) + if(ENABLE_INET_PTON) + check_function_exists(inet_pton HAVE_INET_PTON) + # _WIN32_WINNT_VISTA (0x0600) + add_definitions(-D_WIN32_WINNT=0x0600) + else() + # _WIN32_WINNT_WINXP (0x0501) + add_definitions(-D_WIN32_WINNT=0x0501) + endif() +else() + check_function_exists(inet_pton HAVE_INET_PTON) +endif() + +check_symbol_exists(fsetxattr "${CURL_INCLUDES}" HAVE_FSETXATTR) +if(HAVE_FSETXATTR) + foreach(CURL_TEST HAVE_FSETXATTR_5 HAVE_FSETXATTR_6) + curl_internal_test(${CURL_TEST}) + endforeach() +endif() + +# sigaction and sigsetjmp are special. Use special mechanism for +# detecting those, but only if previous attempt failed. +if(HAVE_SIGNAL_H) + check_symbol_exists(sigaction "signal.h" HAVE_SIGACTION) +endif() + +if(NOT HAVE_SIGSETJMP) + if(HAVE_SETJMP_H) + check_symbol_exists(sigsetjmp "setjmp.h" HAVE_MACRO_SIGSETJMP) + if(HAVE_MACRO_SIGSETJMP) + set(HAVE_SIGSETJMP 1) + endif() + endif() +endif() + +# If there is no stricmp(), do not allow LDAP to parse URLs +if(NOT HAVE_STRICMP) + set(HAVE_LDAP_URL_PARSE 1) +endif() + +# Do curl specific tests +foreach(CURL_TEST + HAVE_FCNTL_O_NONBLOCK + HAVE_IOCTLSOCKET + HAVE_IOCTLSOCKET_CAMEL + HAVE_IOCTLSOCKET_CAMEL_FIONBIO + HAVE_IOCTLSOCKET_FIONBIO + HAVE_IOCTL_FIONBIO + HAVE_IOCTL_SIOCGIFADDR + HAVE_SETSOCKOPT_SO_NONBLOCK + HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID + TIME_WITH_SYS_TIME + HAVE_O_NONBLOCK + HAVE_GETHOSTBYADDR_R_5 + HAVE_GETHOSTBYADDR_R_7 + HAVE_GETHOSTBYADDR_R_8 + HAVE_GETHOSTBYADDR_R_5_REENTRANT + HAVE_GETHOSTBYADDR_R_7_REENTRANT + HAVE_GETHOSTBYADDR_R_8_REENTRANT + HAVE_GETHOSTBYNAME_R_3 + HAVE_GETHOSTBYNAME_R_5 + HAVE_GETHOSTBYNAME_R_6 + HAVE_GETHOSTBYNAME_R_3_REENTRANT + HAVE_GETHOSTBYNAME_R_5_REENTRANT + HAVE_GETHOSTBYNAME_R_6_REENTRANT + HAVE_IN_ADDR_T + HAVE_BOOL_T + STDC_HEADERS + RETSIGTYPE_TEST + HAVE_INET_NTOA_R_DECL + HAVE_INET_NTOA_R_DECL_REENTRANT + HAVE_GETADDRINFO + HAVE_FILE_OFFSET_BITS + HAVE_VARIADIC_MACROS_C99 + HAVE_VARIADIC_MACROS_GCC + ) + curl_internal_test(${CURL_TEST}) +endforeach() + +if(HAVE_FILE_OFFSET_BITS) + set(_FILE_OFFSET_BITS 64) + set(CMAKE_REQUIRED_FLAGS "-D_FILE_OFFSET_BITS=64") +endif() +check_type_size("off_t" SIZEOF_OFF_T) + +# include this header to get the type +set(CMAKE_REQUIRED_INCLUDES "${CURL_SOURCE_DIR}/include") +set(CMAKE_EXTRA_INCLUDE_FILES "curl/system.h") +check_type_size("curl_off_t" SIZEOF_CURL_OFF_T) +set(CMAKE_EXTRA_INCLUDE_FILES "") + +set(CMAKE_REQUIRED_FLAGS) + +foreach(CURL_TEST + HAVE_GLIBC_STRERROR_R + HAVE_POSIX_STRERROR_R + ) + curl_internal_test(${CURL_TEST}) +endforeach() + +# Check for reentrant +foreach(CURL_TEST + HAVE_GETHOSTBYADDR_R_5 + HAVE_GETHOSTBYADDR_R_7 + HAVE_GETHOSTBYADDR_R_8 + HAVE_GETHOSTBYNAME_R_3 + HAVE_GETHOSTBYNAME_R_5 + HAVE_GETHOSTBYNAME_R_6 + HAVE_INET_NTOA_R_DECL_REENTRANT) + if(NOT ${CURL_TEST}) + if(${CURL_TEST}_REENTRANT) + set(NEED_REENTRANT 1) + endif() + endif() +endforeach() + +if(NEED_REENTRANT) + foreach(CURL_TEST + HAVE_GETHOSTBYADDR_R_5 + HAVE_GETHOSTBYADDR_R_7 + HAVE_GETHOSTBYADDR_R_8 + HAVE_GETHOSTBYNAME_R_3 + HAVE_GETHOSTBYNAME_R_5 + HAVE_GETHOSTBYNAME_R_6) + set(${CURL_TEST} 0) + if(${CURL_TEST}_REENTRANT) + set(${CURL_TEST} 1) + endif() + endforeach() +endif() + +if(HAVE_INET_NTOA_R_DECL_REENTRANT) + set(HAVE_INET_NTOA_R_DECL 1) + set(NEED_REENTRANT 1) +endif() + +# Check clock_gettime(CLOCK_MONOTONIC, x) support +curl_internal_test(HAVE_CLOCK_GETTIME_MONOTONIC) + +# Check compiler support of __builtin_available() +curl_internal_test(HAVE_BUILTIN_AVAILABLE) + +# Some other minor tests + +if(NOT HAVE_IN_ADDR_T) + set(in_addr_t "unsigned long") +endif() + +# Fix libz / zlib.h + +if(NOT CURL_SPECIAL_LIBZ) + if(NOT HAVE_LIBZ) + set(HAVE_ZLIB_H 0) + endif() + + if(NOT HAVE_ZLIB_H) + set(HAVE_LIBZ 0) + endif() +endif() + +# Check for nonblocking +set(HAVE_DISABLED_NONBLOCKING 1) +if(HAVE_FIONBIO OR + HAVE_IOCTLSOCKET OR + HAVE_IOCTLSOCKET_CASE OR + HAVE_O_NONBLOCK) + set(HAVE_DISABLED_NONBLOCKING) +endif() + +if(RETSIGTYPE_TEST) + set(RETSIGTYPE void) +else() + set(RETSIGTYPE int) +endif() + +if(CMAKE_COMPILER_IS_GNUCC AND APPLE) + include(CheckCCompilerFlag) + check_c_compiler_flag(-Wno-long-double HAVE_C_FLAG_Wno_long_double) + if(HAVE_C_FLAG_Wno_long_double) + # The Mac version of GCC warns about use of long double. Disable it. + get_source_file_property(MPRINTF_COMPILE_FLAGS mprintf.c COMPILE_FLAGS) + if(MPRINTF_COMPILE_FLAGS) + set(MPRINTF_COMPILE_FLAGS "${MPRINTF_COMPILE_FLAGS} -Wno-long-double") + else() + set(MPRINTF_COMPILE_FLAGS "-Wno-long-double") + endif() + set_source_files_properties(mprintf.c PROPERTIES + COMPILE_FLAGS ${MPRINTF_COMPILE_FLAGS}) + endif() +endif() + +# TODO test which of these headers are required +if(WIN32) + set(CURL_PULL_WS2TCPIP_H ${HAVE_WS2TCPIP_H}) +else() + set(CURL_PULL_SYS_TYPES_H ${HAVE_SYS_TYPES_H}) + set(CURL_PULL_SYS_SOCKET_H ${HAVE_SYS_SOCKET_H}) + set(CURL_PULL_SYS_POLL_H ${HAVE_SYS_POLL_H}) +endif() +set(CURL_PULL_STDINT_H ${HAVE_STDINT_H}) +set(CURL_PULL_INTTYPES_H ${HAVE_INTTYPES_H}) + +include(CMake/OtherTests.cmake) + +add_definitions(-DHAVE_CONFIG_H) + +# For Windows, all compilers used by CMake should support large files +if(WIN32) + set(USE_WIN32_LARGE_FILES ON) + + # Use the manifest embedded in the Windows Resource + set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} -DCURL_EMBED_MANIFEST") +endif() + +if(MSVC) + # Disable default manifest added by CMake + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO") + + add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE) + if(CMAKE_C_FLAGS MATCHES "/W[0-4]") + string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + else() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4") + endif() +endif() + +if(CURL_WERROR) + if(MSVC_VERSION) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX") + else() + # this assumes clang or gcc style options + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") + endif() +endif() + +# Ugly (but functional) way to include "Makefile.inc" by transforming it (= regenerate it). +function(transform_makefile_inc INPUT_FILE OUTPUT_FILE) + file(READ ${INPUT_FILE} MAKEFILE_INC_TEXT) + string(REPLACE "$(top_srcdir)" "\${CURL_SOURCE_DIR}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) + string(REPLACE "$(top_builddir)" "\${CURL_BINARY_DIR}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) + + string(REGEX REPLACE "\\\\\n" "!π!α!" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) + string(REGEX REPLACE "([a-zA-Z_][a-zA-Z0-9_]*)[\t ]*=[\t ]*([^\n]*)" "SET(\\1 \\2)" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) + string(REPLACE "!π!α!" "\n" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) + + string(REGEX REPLACE "\\$\\(([a-zA-Z_][a-zA-Z0-9_]*)\\)" "\${\\1}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) # Replace $() with ${} + string(REGEX REPLACE "@([a-zA-Z_][a-zA-Z0-9_]*)@" "\${\\1}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) # Replace @@ with ${}, even if that may not be read by CMake scripts. + file(WRITE ${OUTPUT_FILE} ${MAKEFILE_INC_TEXT}) + +endfunction() + +if(0) # This code not needed for building within CMake. +include(GNUInstallDirs) + +set(CURL_INSTALL_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}) +set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") +set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated") +set(project_config "${generated_dir}/${PROJECT_NAME}Config.cmake") +set(version_config "${generated_dir}/${PROJECT_NAME}ConfigVersion.cmake") +endif() + +if(USE_MANUAL) + add_subdirectory(docs) +endif() + +add_subdirectory(lib) + +if(BUILD_CURL_EXE) + add_subdirectory(src) +endif() + +#----------------------------------------------------------------------------- +# CMake-specific curl code. +#add_executable(curltest curltest.c) +#target_link_libraries(curltest cmcurl) + +#if(BUILD_TESTING AND CMAKE_CURL_TEST_URL) +# add_test(curl curltest ${CMAKE_CURL_TEST_URL}) +#endif() + +#install(FILES COPYING DESTINATION ${CMAKE_DOC_DIR}/cmcurl) +#----------------------------------------------------------------------------- + +if(0) # This code not needed for building within CMake. +include(CTest) +if(BUILD_TESTING) + add_subdirectory(tests) +endif() + +# Helper to populate a list (_items) with a label when conditions (the remaining +# args) are satisfied +function(_add_if label) + # TODO need to disable policy CMP0054 (CMake 3.1) to allow this indirection + if(${ARGN}) + set(_items ${_items} "${label}" PARENT_SCOPE) + endif() +endfunction() + +# Clear list and try to detect available features +set(_items) +_add_if("SSL" SSL_ENABLED) +_add_if("IPv6" ENABLE_IPV6) +_add_if("unix-sockets" USE_UNIX_SOCKETS) +_add_if("libz" HAVE_LIBZ) +_add_if("AsynchDNS" USE_ARES OR USE_THREADS_POSIX OR USE_THREADS_WIN32) +_add_if("IDN" HAVE_LIBIDN2) +_add_if("Largefile" (CURL_SIZEOF_CURL_OFF_T GREATER 4) AND + ((SIZEOF_OFF_T GREATER 4) OR USE_WIN32_LARGE_FILES)) +# TODO SSP1 (WinSSL) check is missing +_add_if("SSPI" USE_WINDOWS_SSPI) +_add_if("GSS-API" HAVE_GSSAPI) +# TODO SSP1 missing for SPNEGO +_add_if("SPNEGO" NOT CURL_DISABLE_CRYPTO_AUTH AND + (HAVE_GSSAPI OR USE_WINDOWS_SSPI)) +_add_if("Kerberos" NOT CURL_DISABLE_CRYPTO_AUTH AND + (HAVE_GSSAPI OR USE_WINDOWS_SSPI)) +# NTLM support requires crypto function adaptions from various SSL libs +# TODO alternative SSL libs tests for SSP1, GNUTLS, NSS +if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_WINDOWS_SSPI OR USE_SECTRANSP OR USE_MBEDTLS)) + _add_if("NTLM" 1) + # TODO missing option (autoconf: --enable-ntlm-wb) + _add_if("NTLM_WB" NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED) +endif() +# TODO missing option (--enable-tls-srp), depends on GNUTLS_SRP/OPENSSL_SRP +_add_if("TLS-SRP" USE_TLS_SRP) +# TODO option --with-nghttp2 tests for nghttp2 lib and nghttp2/nghttp2.h header +_add_if("HTTP2" USE_NGHTTP2) +string(REPLACE ";" " " SUPPORT_FEATURES "${_items}") +message(STATUS "Enabled features: ${SUPPORT_FEATURES}") + +# Clear list and try to detect available protocols +set(_items) +_add_if("HTTP" NOT CURL_DISABLE_HTTP) +_add_if("HTTPS" NOT CURL_DISABLE_HTTP AND SSL_ENABLED) +_add_if("FTP" NOT CURL_DISABLE_FTP) +_add_if("FTPS" NOT CURL_DISABLE_FTP AND SSL_ENABLED) +_add_if("FILE" NOT CURL_DISABLE_FILE) +_add_if("TELNET" NOT CURL_DISABLE_TELNET) +_add_if("LDAP" NOT CURL_DISABLE_LDAP) +# CURL_DISABLE_LDAP implies CURL_DISABLE_LDAPS +# TODO check HAVE_LDAP_SSL (in autoconf this is enabled with --enable-ldaps) +_add_if("LDAPS" NOT CURL_DISABLE_LDAPS AND + ((USE_OPENLDAP AND SSL_ENABLED) OR + (NOT USE_OPENLDAP AND HAVE_LDAP_SSL))) +_add_if("DICT" NOT CURL_DISABLE_DICT) +_add_if("TFTP" NOT CURL_DISABLE_TFTP) +_add_if("GOPHER" NOT CURL_DISABLE_GOPHER) +_add_if("POP3" NOT CURL_DISABLE_POP3) +_add_if("POP3S" NOT CURL_DISABLE_POP3 AND SSL_ENABLED) +_add_if("IMAP" NOT CURL_DISABLE_IMAP) +_add_if("IMAPS" NOT CURL_DISABLE_IMAP AND SSL_ENABLED) +_add_if("SMTP" NOT CURL_DISABLE_SMTP) +_add_if("SMTPS" NOT CURL_DISABLE_SMTP AND SSL_ENABLED) +_add_if("SCP" USE_LIBSSH2) +_add_if("SFTP" USE_LIBSSH2) +_add_if("RTSP" NOT CURL_DISABLE_RTSP) +_add_if("RTMP" USE_LIBRTMP) +if(_items) + list(SORT _items) +endif() +string(REPLACE ";" " " SUPPORT_PROTOCOLS "${_items}") +message(STATUS "Enabled protocols: ${SUPPORT_PROTOCOLS}") + +# Clear list and collect SSL backends +set(_items) +_add_if("WinSSL" SSL_ENABLED AND USE_WINDOWS_SSPI) +_add_if("OpenSSL" SSL_ENABLED AND USE_OPENSSL) +_add_if("Secure Transport" SSL_ENABLED AND USE_SECTRANSP) +_add_if("mbedTLS" SSL_ENABLED AND USE_MBEDTLS) +if(_items) + list(SORT _items) +endif() +string(REPLACE ";" " " SSL_BACKENDS "${_items}") +message(STATUS "Enabled SSL backends: ${SSL_BACKENDS}") + +# curl-config needs the following options to be set. +set(CC "${CMAKE_C_COMPILER}") +# TODO probably put a -D... options here? +set(CONFIGURE_OPTIONS "") +# TODO when to set "-DCURL_STATICLIB" for CPPFLAG_CURL_STATICLIB? +set(CPPFLAG_CURL_STATICLIB "") +set(CURLVERSION "${CURL_VERSION}") +if(BUILD_SHARED_LIBS) + set(ENABLE_SHARED "yes") + set(ENABLE_STATIC "no") +else() + set(ENABLE_SHARED "no") + set(ENABLE_STATIC "yes") +endif() +set(exec_prefix "\${prefix}") +set(includedir "\${prefix}/include") +set(LDFLAGS "${CMAKE_SHARED_LINKER_FLAGS}") +set(LIBCURL_LIBS "") +set(libdir "${CMAKE_INSTALL_PREFIX}/lib") +foreach(_lib ${CMAKE_C_IMPLICIT_LINK_LIBRARIES} ${CURL_LIBS}) + if(_lib MATCHES ".*/.*" OR _lib MATCHES "^-") + set(LIBCURL_LIBS "${LIBCURL_LIBS} ${_lib}") + else() + set(LIBCURL_LIBS "${LIBCURL_LIBS} -l${_lib}") + endif() +endforeach() +# "a" (Linux) or "lib" (Windows) +string(REPLACE "." "" libext "${CMAKE_STATIC_LIBRARY_SUFFIX}") +set(prefix "${CMAKE_INSTALL_PREFIX}") +# Set this to "yes" to append all libraries on which -lcurl is dependent +set(REQUIRE_LIB_DEPS "no") +# SUPPORT_FEATURES +# SUPPORT_PROTOCOLS +set(VERSIONNUM "${CURL_VERSION_NUM}") + +# Finally generate a "curl-config" matching this config +# Use: +# * ENABLE_SHARED +# * ENABLE_STATIC +configure_file("${CURL_SOURCE_DIR}/curl-config.in" + "${CURL_BINARY_DIR}/curl-config" @ONLY) +install(FILES "${CURL_BINARY_DIR}/curl-config" + DESTINATION ${CMAKE_INSTALL_BINDIR} + PERMISSIONS + OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE + WORLD_READ WORLD_EXECUTE) + +# Finally generate a pkg-config file matching this config +configure_file("${CURL_SOURCE_DIR}/libcurl.pc.in" + "${CURL_BINARY_DIR}/libcurl.pc" @ONLY) +install(FILES "${CURL_BINARY_DIR}/libcurl.pc" + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) + +# install headers +install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/curl" + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + FILES_MATCHING PATTERN "*.h") + +include(CMakePackageConfigHelpers) +write_basic_package_version_file( + "${version_config}" + VERSION ${CURL_VERSION} + COMPATIBILITY SameMajorVersion +) + +# Use: +# * TARGETS_EXPORT_NAME +# * PROJECT_NAME +configure_package_config_file(CMake/curl-config.cmake.in + "${project_config}" + INSTALL_DESTINATION ${CURL_INSTALL_CMAKE_DIR} +) + +install( + EXPORT "${TARGETS_EXPORT_NAME}" + NAMESPACE "${PROJECT_NAME}::" + DESTINATION ${CURL_INSTALL_CMAKE_DIR} +) + +install( + FILES ${version_config} ${project_config} + DESTINATION ${CURL_INSTALL_CMAKE_DIR} +) + +# Workaround for MSVS10 to avoid the Dialog Hell +# FIXME: This could be removed with future version of CMake. +if(MSVC_VERSION EQUAL 1600) + set(CURL_SLN_FILENAME "${CMAKE_CURRENT_BINARY_DIR}/CURL.sln") + if(EXISTS "${CURL_SLN_FILENAME}") + file(APPEND "${CURL_SLN_FILENAME}" "\n# This should be regenerated!\n") + endif() +endif() + +if(NOT TARGET uninstall) + configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/CMake/cmake_uninstall.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake + IMMEDIATE @ONLY) + + add_custom_target(uninstall + COMMAND ${CMAKE_COMMAND} -P + ${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake) +endif() +endif() diff --git a/dependencies/cmcurl/COPYING b/dependencies/cmcurl/COPYING new file mode 100644 index 0000000..3528bd7 --- /dev/null +++ b/dependencies/cmcurl/COPYING @@ -0,0 +1,22 @@ +COPYRIGHT AND PERMISSION NOTICE + +Copyright (c) 1996 - 2019, Daniel Stenberg, , and many +contributors, see the THANKS file. + +All rights reserved. + +Permission to use, copy, modify, and distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright +notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall not +be used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization of the copyright holder. diff --git a/dependencies/cmcurl/curltest.c b/dependencies/cmcurl/curltest.c new file mode 100644 index 0000000..f80e758 --- /dev/null +++ b/dependencies/cmcurl/curltest.c @@ -0,0 +1,81 @@ +#include "curl/curl.h" + +#include +#include +#include + +int test_curl(const char* url) +{ + CURL* curl; + CURLcode r; + char proxy[1024]; + int proxy_type = 0; + + if (getenv("HTTP_PROXY")) { + proxy_type = 1; + if (getenv("HTTP_PROXY_PORT")) { + sprintf(proxy, "%s:%s", getenv("HTTP_PROXY"), getenv("HTTP_PROXY_PORT")); + } else { + sprintf(proxy, "%s", getenv("HTTP_PROXY")); + } + if (getenv("HTTP_PROXY_TYPE")) { + /* HTTP/SOCKS4/SOCKS5 */ + if (strcmp(getenv("HTTP_PROXY_TYPE"), "HTTP") == 0) { + proxy_type = 1; + } else if (strcmp(getenv("HTTP_PROXY_TYPE"), "SOCKS4") == 0) { + proxy_type = 2; + } else if (strcmp(getenv("HTTP_PROXY_TYPE"), "SOCKS5") == 0) { + proxy_type = 3; + } + } + } + + curl = curl_easy_init(); + if (!curl) { + fprintf(stderr, "curl_easy_init failed\n"); + return 1; + } + + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); + curl_easy_setopt(curl, CURLOPT_HEADER, 1); + + if (proxy_type > 0) { + curl_easy_setopt(curl, CURLOPT_PROXY, proxy); + switch (proxy_type) { + case 2: + curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4); + break; + case 3: + curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); + break; + default: + curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); + } + } + + curl_easy_setopt(curl, CURLOPT_URL, url); + r = curl_easy_perform(curl); + curl_easy_cleanup(curl); + + if (r != CURLE_OK) { + fprintf(stderr, "error: fetching '%s' failed: %s\n", url, + curl_easy_strerror(r)); + return 1; + } + + return 0; +} + +int main(int argc, const char* argv[]) +{ + int r; + curl_global_init(CURL_GLOBAL_DEFAULT); + if (argc == 2) { + r = test_curl(argv[1]); + } else { + fprintf(stderr, "error: no URL given as first argument\n"); + r = 1; + } + curl_global_cleanup(); + return r; +} diff --git a/dependencies/cmcurl/include/curl/curl.h b/dependencies/cmcurl/include/curl/curl.h new file mode 100644 index 0000000..089c427 --- /dev/null +++ b/dependencies/cmcurl/include/curl/curl.h @@ -0,0 +1,2869 @@ +#ifndef __CURL_CURL_H +#define __CURL_CURL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * If you have libcurl problems, all docs and details are found here: + * https://curl.haxx.se/libcurl/ + * + * curl-library mailing list subscription and unsubscription web interface: + * https://cool.haxx.se/mailman/listinfo/curl-library/ + */ + +#ifdef CURL_NO_OLDIES +#define CURL_STRICTER +#endif + +#include "curlver.h" /* libcurl version defines */ +#include "system.h" /* determine things run-time */ + +/* + * Define WIN32 when build target is Win32 API + */ + +#if (defined(_WIN32) || defined(__WIN32__)) && \ + !defined(WIN32) && !defined(__SYMBIAN32__) +#define WIN32 +#endif + +#include +#include + +#if defined(__FreeBSD__) && (__FreeBSD__ >= 2) +/* Needed for __FreeBSD_version symbol definition */ +#include +#endif + +/* The include stuff here below is mainly for time_t! */ +#include +#include + +#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__) +#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || \ + defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H)) +/* The check above prevents the winsock2 inclusion if winsock.h already was + included, since they can't co-exist without problems */ +#include +#include +#endif +#endif + +/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish + libc5-based Linux systems. Only include it on systems that are known to + require it! */ +#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \ + defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \ + defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \ + defined(__CYGWIN__) || \ + (defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) +#include +#endif + +#if !defined(WIN32) && !defined(_WIN32_WCE) +#include +#endif + +#if !defined(WIN32) && !defined(__WATCOMC__) && !defined(__VXWORKS__) +#include +#endif + +#if defined __BEOS__ || defined __HAIKU__ +#include +#endif + +/* Compatibility for non-Clang compilers */ +#ifndef __has_declspec_attribute +# define __has_declspec_attribute(x) 0 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER) +typedef struct Curl_easy CURL; +typedef struct Curl_share CURLSH; +#else +typedef void CURL; +typedef void CURLSH; +#endif + +/* + * libcurl external API function linkage decorations. + */ + +#ifdef CURL_STATICLIB +# define CURL_EXTERN +#elif defined(WIN32) || defined(__SYMBIAN32__) || \ + (__has_declspec_attribute(dllexport) && \ + __has_declspec_attribute(dllimport)) +# if defined(BUILDING_LIBCURL) +# define CURL_EXTERN __declspec(dllexport) +# else +# define CURL_EXTERN __declspec(dllimport) +# endif +#elif defined(BUILDING_LIBCURL) && defined(CURL_HIDDEN_SYMBOLS) +# define CURL_EXTERN CURL_EXTERN_SYMBOL +#else +# define CURL_EXTERN +#endif + +#ifndef curl_socket_typedef +/* socket typedef */ +#if defined(WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H) +typedef SOCKET curl_socket_t; +#define CURL_SOCKET_BAD INVALID_SOCKET +#else +typedef int curl_socket_t; +#define CURL_SOCKET_BAD -1 +#endif +#define curl_socket_typedef +#endif /* curl_socket_typedef */ + +/* enum for the different supported SSL backends */ +typedef enum { + CURLSSLBACKEND_NONE = 0, + CURLSSLBACKEND_OPENSSL = 1, + CURLSSLBACKEND_GNUTLS = 2, + CURLSSLBACKEND_NSS = 3, + CURLSSLBACKEND_OBSOLETE4 = 4, /* Was QSOSSL. */ + CURLSSLBACKEND_GSKIT = 5, + CURLSSLBACKEND_POLARSSL = 6, + CURLSSLBACKEND_WOLFSSL = 7, + CURLSSLBACKEND_SCHANNEL = 8, + CURLSSLBACKEND_SECURETRANSPORT = 9, + CURLSSLBACKEND_AXTLS = 10, /* never used since 7.63.0 */ + CURLSSLBACKEND_MBEDTLS = 11, + CURLSSLBACKEND_MESALINK = 12 +} curl_sslbackend; + +/* aliases for library clones and renames */ +#define CURLSSLBACKEND_LIBRESSL CURLSSLBACKEND_OPENSSL +#define CURLSSLBACKEND_BORINGSSL CURLSSLBACKEND_OPENSSL + +/* deprecated names: */ +#define CURLSSLBACKEND_CYASSL CURLSSLBACKEND_WOLFSSL +#define CURLSSLBACKEND_DARWINSSL CURLSSLBACKEND_SECURETRANSPORT + +struct curl_httppost { + struct curl_httppost *next; /* next entry in the list */ + char *name; /* pointer to allocated name */ + long namelength; /* length of name length */ + char *contents; /* pointer to allocated data contents */ + long contentslength; /* length of contents field, see also + CURL_HTTPPOST_LARGE */ + char *buffer; /* pointer to allocated buffer contents */ + long bufferlength; /* length of buffer field */ + char *contenttype; /* Content-Type */ + struct curl_slist *contentheader; /* list of extra headers for this form */ + struct curl_httppost *more; /* if one field name has more than one + file, this link should link to following + files */ + long flags; /* as defined below */ + +/* specified content is a file name */ +#define CURL_HTTPPOST_FILENAME (1<<0) +/* specified content is a file name */ +#define CURL_HTTPPOST_READFILE (1<<1) +/* name is only stored pointer do not free in formfree */ +#define CURL_HTTPPOST_PTRNAME (1<<2) +/* contents is only stored pointer do not free in formfree */ +#define CURL_HTTPPOST_PTRCONTENTS (1<<3) +/* upload file from buffer */ +#define CURL_HTTPPOST_BUFFER (1<<4) +/* upload file from pointer contents */ +#define CURL_HTTPPOST_PTRBUFFER (1<<5) +/* upload file contents by using the regular read callback to get the data and + pass the given pointer as custom pointer */ +#define CURL_HTTPPOST_CALLBACK (1<<6) +/* use size in 'contentlen', added in 7.46.0 */ +#define CURL_HTTPPOST_LARGE (1<<7) + + char *showfilename; /* The file name to show. If not set, the + actual file name will be used (if this + is a file part) */ + void *userp; /* custom pointer used for + HTTPPOST_CALLBACK posts */ + curl_off_t contentlen; /* alternative length of contents + field. Used if CURL_HTTPPOST_LARGE is + set. Added in 7.46.0 */ +}; + +/* This is the CURLOPT_PROGRESSFUNCTION callback proto. It is now considered + deprecated but was the only choice up until 7.31.0 */ +typedef int (*curl_progress_callback)(void *clientp, + double dltotal, + double dlnow, + double ultotal, + double ulnow); + +/* This is the CURLOPT_XFERINFOFUNCTION callback proto. It was introduced in + 7.32.0, it avoids floating point and provides more detailed information. */ +typedef int (*curl_xferinfo_callback)(void *clientp, + curl_off_t dltotal, + curl_off_t dlnow, + curl_off_t ultotal, + curl_off_t ulnow); + +#ifndef CURL_MAX_READ_SIZE + /* The maximum receive buffer size configurable via CURLOPT_BUFFERSIZE. */ +#define CURL_MAX_READ_SIZE 524288 +#endif + +#ifndef CURL_MAX_WRITE_SIZE + /* Tests have proven that 20K is a very bad buffer size for uploads on + Windows, while 16K for some odd reason performed a lot better. + We do the ifndef check to allow this value to easier be changed at build + time for those who feel adventurous. The practical minimum is about + 400 bytes since libcurl uses a buffer of this size as a scratch area + (unrelated to network send operations). */ +#define CURL_MAX_WRITE_SIZE 16384 +#endif + +#ifndef CURL_MAX_HTTP_HEADER +/* The only reason to have a max limit for this is to avoid the risk of a bad + server feeding libcurl with a never-ending header that will cause reallocs + infinitely */ +#define CURL_MAX_HTTP_HEADER (100*1024) +#endif + +/* This is a magic return code for the write callback that, when returned, + will signal libcurl to pause receiving on the current transfer. */ +#define CURL_WRITEFUNC_PAUSE 0x10000001 + +typedef size_t (*curl_write_callback)(char *buffer, + size_t size, + size_t nitems, + void *outstream); + +/* This callback will be called when a new resolver request is made */ +typedef int (*curl_resolver_start_callback)(void *resolver_state, + void *reserved, void *userdata); + +/* enumeration of file types */ +typedef enum { + CURLFILETYPE_FILE = 0, + CURLFILETYPE_DIRECTORY, + CURLFILETYPE_SYMLINK, + CURLFILETYPE_DEVICE_BLOCK, + CURLFILETYPE_DEVICE_CHAR, + CURLFILETYPE_NAMEDPIPE, + CURLFILETYPE_SOCKET, + CURLFILETYPE_DOOR, /* is possible only on Sun Solaris now */ + + CURLFILETYPE_UNKNOWN /* should never occur */ +} curlfiletype; + +#define CURLFINFOFLAG_KNOWN_FILENAME (1<<0) +#define CURLFINFOFLAG_KNOWN_FILETYPE (1<<1) +#define CURLFINFOFLAG_KNOWN_TIME (1<<2) +#define CURLFINFOFLAG_KNOWN_PERM (1<<3) +#define CURLFINFOFLAG_KNOWN_UID (1<<4) +#define CURLFINFOFLAG_KNOWN_GID (1<<5) +#define CURLFINFOFLAG_KNOWN_SIZE (1<<6) +#define CURLFINFOFLAG_KNOWN_HLINKCOUNT (1<<7) + +/* Content of this structure depends on information which is known and is + achievable (e.g. by FTP LIST parsing). Please see the url_easy_setopt(3) man + page for callbacks returning this structure -- some fields are mandatory, + some others are optional. The FLAG field has special meaning. */ +struct curl_fileinfo { + char *filename; + curlfiletype filetype; + time_t time; /* always zero! */ + unsigned int perm; + int uid; + int gid; + curl_off_t size; + long int hardlinks; + + struct { + /* If some of these fields is not NULL, it is a pointer to b_data. */ + char *time; + char *perm; + char *user; + char *group; + char *target; /* pointer to the target filename of a symlink */ + } strings; + + unsigned int flags; + + /* used internally */ + char *b_data; + size_t b_size; + size_t b_used; +}; + +/* return codes for CURLOPT_CHUNK_BGN_FUNCTION */ +#define CURL_CHUNK_BGN_FUNC_OK 0 +#define CURL_CHUNK_BGN_FUNC_FAIL 1 /* tell the lib to end the task */ +#define CURL_CHUNK_BGN_FUNC_SKIP 2 /* skip this chunk over */ + +/* if splitting of data transfer is enabled, this callback is called before + download of an individual chunk started. Note that parameter "remains" works + only for FTP wildcard downloading (for now), otherwise is not used */ +typedef long (*curl_chunk_bgn_callback)(const void *transfer_info, + void *ptr, + int remains); + +/* return codes for CURLOPT_CHUNK_END_FUNCTION */ +#define CURL_CHUNK_END_FUNC_OK 0 +#define CURL_CHUNK_END_FUNC_FAIL 1 /* tell the lib to end the task */ + +/* If splitting of data transfer is enabled this callback is called after + download of an individual chunk finished. + Note! After this callback was set then it have to be called FOR ALL chunks. + Even if downloading of this chunk was skipped in CHUNK_BGN_FUNC. + This is the reason why we don't need "transfer_info" parameter in this + callback and we are not interested in "remains" parameter too. */ +typedef long (*curl_chunk_end_callback)(void *ptr); + +/* return codes for FNMATCHFUNCTION */ +#define CURL_FNMATCHFUNC_MATCH 0 /* string corresponds to the pattern */ +#define CURL_FNMATCHFUNC_NOMATCH 1 /* pattern doesn't match the string */ +#define CURL_FNMATCHFUNC_FAIL 2 /* an error occurred */ + +/* callback type for wildcard downloading pattern matching. If the + string matches the pattern, return CURL_FNMATCHFUNC_MATCH value, etc. */ +typedef int (*curl_fnmatch_callback)(void *ptr, + const char *pattern, + const char *string); + +/* These are the return codes for the seek callbacks */ +#define CURL_SEEKFUNC_OK 0 +#define CURL_SEEKFUNC_FAIL 1 /* fail the entire transfer */ +#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking can't be done, so + libcurl might try other means instead */ +typedef int (*curl_seek_callback)(void *instream, + curl_off_t offset, + int origin); /* 'whence' */ + +/* This is a return code for the read callback that, when returned, will + signal libcurl to immediately abort the current transfer. */ +#define CURL_READFUNC_ABORT 0x10000000 +/* This is a return code for the read callback that, when returned, will + signal libcurl to pause sending data on the current transfer. */ +#define CURL_READFUNC_PAUSE 0x10000001 + +/* Return code for when the trailing headers' callback has terminated + without any errors*/ +#define CURL_TRAILERFUNC_OK 0 +/* Return code for when was an error in the trailing header's list and we + want to abort the request */ +#define CURL_TRAILERFUNC_ABORT 1 + +typedef size_t (*curl_read_callback)(char *buffer, + size_t size, + size_t nitems, + void *instream); + +typedef int (*curl_trailer_callback)(struct curl_slist **list, + void *userdata); + +typedef enum { + CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */ + CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */ + CURLSOCKTYPE_LAST /* never use */ +} curlsocktype; + +/* The return code from the sockopt_callback can signal information back + to libcurl: */ +#define CURL_SOCKOPT_OK 0 +#define CURL_SOCKOPT_ERROR 1 /* causes libcurl to abort and return + CURLE_ABORTED_BY_CALLBACK */ +#define CURL_SOCKOPT_ALREADY_CONNECTED 2 + +typedef int (*curl_sockopt_callback)(void *clientp, + curl_socket_t curlfd, + curlsocktype purpose); + +struct curl_sockaddr { + int family; + int socktype; + int protocol; + unsigned int addrlen; /* addrlen was a socklen_t type before 7.18.0 but it + turned really ugly and painful on the systems that + lack this type */ + struct sockaddr addr; +}; + +typedef curl_socket_t +(*curl_opensocket_callback)(void *clientp, + curlsocktype purpose, + struct curl_sockaddr *address); + +typedef int +(*curl_closesocket_callback)(void *clientp, curl_socket_t item); + +typedef enum { + CURLIOE_OK, /* I/O operation successful */ + CURLIOE_UNKNOWNCMD, /* command was unknown to callback */ + CURLIOE_FAILRESTART, /* failed to restart the read */ + CURLIOE_LAST /* never use */ +} curlioerr; + +typedef enum { + CURLIOCMD_NOP, /* no operation */ + CURLIOCMD_RESTARTREAD, /* restart the read stream from start */ + CURLIOCMD_LAST /* never use */ +} curliocmd; + +typedef curlioerr (*curl_ioctl_callback)(CURL *handle, + int cmd, + void *clientp); + +#ifndef CURL_DID_MEMORY_FUNC_TYPEDEFS +/* + * The following typedef's are signatures of malloc, free, realloc, strdup and + * calloc respectively. Function pointers of these types can be passed to the + * curl_global_init_mem() function to set user defined memory management + * callback routines. + */ +typedef void *(*curl_malloc_callback)(size_t size); +typedef void (*curl_free_callback)(void *ptr); +typedef void *(*curl_realloc_callback)(void *ptr, size_t size); +typedef char *(*curl_strdup_callback)(const char *str); +typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size); + +#define CURL_DID_MEMORY_FUNC_TYPEDEFS +#endif + +/* the kind of data that is passed to information_callback*/ +typedef enum { + CURLINFO_TEXT = 0, + CURLINFO_HEADER_IN, /* 1 */ + CURLINFO_HEADER_OUT, /* 2 */ + CURLINFO_DATA_IN, /* 3 */ + CURLINFO_DATA_OUT, /* 4 */ + CURLINFO_SSL_DATA_IN, /* 5 */ + CURLINFO_SSL_DATA_OUT, /* 6 */ + CURLINFO_END +} curl_infotype; + +typedef int (*curl_debug_callback) + (CURL *handle, /* the handle/transfer this concerns */ + curl_infotype type, /* what kind of data */ + char *data, /* points to the data */ + size_t size, /* size of the data pointed to */ + void *userptr); /* whatever the user please */ + +/* All possible error codes from all sorts of curl functions. Future versions + may return other values, stay prepared. + + Always add new return codes last. Never *EVER* remove any. The return + codes must remain the same! + */ + +typedef enum { + CURLE_OK = 0, + CURLE_UNSUPPORTED_PROTOCOL, /* 1 */ + CURLE_FAILED_INIT, /* 2 */ + CURLE_URL_MALFORMAT, /* 3 */ + CURLE_NOT_BUILT_IN, /* 4 - [was obsoleted in August 2007 for + 7.17.0, reused in April 2011 for 7.21.5] */ + CURLE_COULDNT_RESOLVE_PROXY, /* 5 */ + CURLE_COULDNT_RESOLVE_HOST, /* 6 */ + CURLE_COULDNT_CONNECT, /* 7 */ + CURLE_WEIRD_SERVER_REPLY, /* 8 */ + CURLE_REMOTE_ACCESS_DENIED, /* 9 a service was denied by the server + due to lack of access - when login fails + this is not returned. */ + CURLE_FTP_ACCEPT_FAILED, /* 10 - [was obsoleted in April 2006 for + 7.15.4, reused in Dec 2011 for 7.24.0]*/ + CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */ + CURLE_FTP_ACCEPT_TIMEOUT, /* 12 - timeout occurred accepting server + [was obsoleted in August 2007 for 7.17.0, + reused in Dec 2011 for 7.24.0]*/ + CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */ + CURLE_FTP_WEIRD_227_FORMAT, /* 14 */ + CURLE_FTP_CANT_GET_HOST, /* 15 */ + CURLE_HTTP2, /* 16 - A problem in the http2 framing layer. + [was obsoleted in August 2007 for 7.17.0, + reused in July 2014 for 7.38.0] */ + CURLE_FTP_COULDNT_SET_TYPE, /* 17 */ + CURLE_PARTIAL_FILE, /* 18 */ + CURLE_FTP_COULDNT_RETR_FILE, /* 19 */ + CURLE_OBSOLETE20, /* 20 - NOT USED */ + CURLE_QUOTE_ERROR, /* 21 - quote command failure */ + CURLE_HTTP_RETURNED_ERROR, /* 22 */ + CURLE_WRITE_ERROR, /* 23 */ + CURLE_OBSOLETE24, /* 24 - NOT USED */ + CURLE_UPLOAD_FAILED, /* 25 - failed upload "command" */ + CURLE_READ_ERROR, /* 26 - couldn't open/read from file */ + CURLE_OUT_OF_MEMORY, /* 27 */ + /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error + instead of a memory allocation error if CURL_DOES_CONVERSIONS + is defined + */ + CURLE_OPERATION_TIMEDOUT, /* 28 - the timeout time was reached */ + CURLE_OBSOLETE29, /* 29 - NOT USED */ + CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */ + CURLE_FTP_COULDNT_USE_REST, /* 31 - the REST command failed */ + CURLE_OBSOLETE32, /* 32 - NOT USED */ + CURLE_RANGE_ERROR, /* 33 - RANGE "command" didn't work */ + CURLE_HTTP_POST_ERROR, /* 34 */ + CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */ + CURLE_BAD_DOWNLOAD_RESUME, /* 36 - couldn't resume download */ + CURLE_FILE_COULDNT_READ_FILE, /* 37 */ + CURLE_LDAP_CANNOT_BIND, /* 38 */ + CURLE_LDAP_SEARCH_FAILED, /* 39 */ + CURLE_OBSOLETE40, /* 40 - NOT USED */ + CURLE_FUNCTION_NOT_FOUND, /* 41 - NOT USED starting with 7.53.0 */ + CURLE_ABORTED_BY_CALLBACK, /* 42 */ + CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */ + CURLE_OBSOLETE44, /* 44 - NOT USED */ + CURLE_INTERFACE_FAILED, /* 45 - CURLOPT_INTERFACE failed */ + CURLE_OBSOLETE46, /* 46 - NOT USED */ + CURLE_TOO_MANY_REDIRECTS, /* 47 - catch endless re-direct loops */ + CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */ + CURLE_TELNET_OPTION_SYNTAX, /* 49 - Malformed telnet option */ + CURLE_OBSOLETE50, /* 50 - NOT USED */ + CURLE_OBSOLETE51, /* 51 - NOT USED */ + CURLE_GOT_NOTHING, /* 52 - when this is a specific error */ + CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */ + CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as + default */ + CURLE_SEND_ERROR, /* 55 - failed sending network data */ + CURLE_RECV_ERROR, /* 56 - failure in receiving network data */ + CURLE_OBSOLETE57, /* 57 - NOT IN USE */ + CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */ + CURLE_SSL_CIPHER, /* 59 - couldn't use specified cipher */ + CURLE_PEER_FAILED_VERIFICATION, /* 60 - peer's certificate or fingerprint + wasn't verified fine */ + CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized/bad encoding */ + CURLE_LDAP_INVALID_URL, /* 62 - Invalid LDAP URL */ + CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */ + CURLE_USE_SSL_FAILED, /* 64 - Requested FTP SSL level failed */ + CURLE_SEND_FAIL_REWIND, /* 65 - Sending the data requires a rewind + that failed */ + CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */ + CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not + accepted and we failed to login */ + CURLE_TFTP_NOTFOUND, /* 68 - file not found on server */ + CURLE_TFTP_PERM, /* 69 - permission problem on server */ + CURLE_REMOTE_DISK_FULL, /* 70 - out of disk space on server */ + CURLE_TFTP_ILLEGAL, /* 71 - Illegal TFTP operation */ + CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */ + CURLE_REMOTE_FILE_EXISTS, /* 73 - File already exists */ + CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */ + CURLE_CONV_FAILED, /* 75 - conversion failed */ + CURLE_CONV_REQD, /* 76 - caller must register conversion + callbacks using curl_easy_setopt options + CURLOPT_CONV_FROM_NETWORK_FUNCTION, + CURLOPT_CONV_TO_NETWORK_FUNCTION, and + CURLOPT_CONV_FROM_UTF8_FUNCTION */ + CURLE_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing + or wrong format */ + CURLE_REMOTE_FILE_NOT_FOUND, /* 78 - remote file not found */ + CURLE_SSH, /* 79 - error from the SSH layer, somewhat + generic so the error message will be of + interest when this has happened */ + + CURLE_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL + connection */ + CURLE_AGAIN, /* 81 - socket is not ready for send/recv, + wait till it's ready and try again (Added + in 7.18.2) */ + CURLE_SSL_CRL_BADFILE, /* 82 - could not load CRL file, missing or + wrong format (Added in 7.19.0) */ + CURLE_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in + 7.19.0) */ + CURLE_FTP_PRET_FAILED, /* 84 - a PRET command failed */ + CURLE_RTSP_CSEQ_ERROR, /* 85 - mismatch of RTSP CSeq numbers */ + CURLE_RTSP_SESSION_ERROR, /* 86 - mismatch of RTSP Session Ids */ + CURLE_FTP_BAD_FILE_LIST, /* 87 - unable to parse FTP file list */ + CURLE_CHUNK_FAILED, /* 88 - chunk callback reported error */ + CURLE_NO_CONNECTION_AVAILABLE, /* 89 - No connection available, the + session will be queued */ + CURLE_SSL_PINNEDPUBKEYNOTMATCH, /* 90 - specified pinned public key did not + match */ + CURLE_SSL_INVALIDCERTSTATUS, /* 91 - invalid certificate status */ + CURLE_HTTP2_STREAM, /* 92 - stream error in HTTP/2 framing layer + */ + CURLE_RECURSIVE_API_CALL, /* 93 - an api function was called from + inside a callback */ + CURL_LAST /* never use! */ +} CURLcode; + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Previously obsolete error code re-used in 7.38.0 */ +#define CURLE_OBSOLETE16 CURLE_HTTP2 + +/* Previously obsolete error codes re-used in 7.24.0 */ +#define CURLE_OBSOLETE10 CURLE_FTP_ACCEPT_FAILED +#define CURLE_OBSOLETE12 CURLE_FTP_ACCEPT_TIMEOUT + +/* compatibility with older names */ +#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING +#define CURLE_FTP_WEIRD_SERVER_REPLY CURLE_WEIRD_SERVER_REPLY + +/* The following were added in 7.62.0 */ +#define CURLE_SSL_CACERT CURLE_PEER_FAILED_VERIFICATION + +/* The following were added in 7.21.5, April 2011 */ +#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION + +/* The following were added in 7.17.1 */ +/* These are scheduled to disappear by 2009 */ +#define CURLE_SSL_PEER_CERTIFICATE CURLE_PEER_FAILED_VERIFICATION + +/* The following were added in 7.17.0 */ +/* These are scheduled to disappear by 2009 */ +#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* no one should be using this! */ +#define CURLE_BAD_PASSWORD_ENTERED CURLE_OBSOLETE46 +#define CURLE_BAD_CALLING_ORDER CURLE_OBSOLETE44 +#define CURLE_FTP_USER_PASSWORD_INCORRECT CURLE_OBSOLETE10 +#define CURLE_FTP_CANT_RECONNECT CURLE_OBSOLETE16 +#define CURLE_FTP_COULDNT_GET_SIZE CURLE_OBSOLETE32 +#define CURLE_FTP_COULDNT_SET_ASCII CURLE_OBSOLETE29 +#define CURLE_FTP_WEIRD_USER_REPLY CURLE_OBSOLETE12 +#define CURLE_FTP_WRITE_ERROR CURLE_OBSOLETE20 +#define CURLE_LIBRARY_NOT_FOUND CURLE_OBSOLETE40 +#define CURLE_MALFORMAT_USER CURLE_OBSOLETE24 +#define CURLE_SHARE_IN_USE CURLE_OBSOLETE57 +#define CURLE_URL_MALFORMAT_USER CURLE_NOT_BUILT_IN + +#define CURLE_FTP_ACCESS_DENIED CURLE_REMOTE_ACCESS_DENIED +#define CURLE_FTP_COULDNT_SET_BINARY CURLE_FTP_COULDNT_SET_TYPE +#define CURLE_FTP_QUOTE_ERROR CURLE_QUOTE_ERROR +#define CURLE_TFTP_DISKFULL CURLE_REMOTE_DISK_FULL +#define CURLE_TFTP_EXISTS CURLE_REMOTE_FILE_EXISTS +#define CURLE_HTTP_RANGE_ERROR CURLE_RANGE_ERROR +#define CURLE_FTP_SSL_FAILED CURLE_USE_SSL_FAILED + +/* The following were added earlier */ + +#define CURLE_OPERATION_TIMEOUTED CURLE_OPERATION_TIMEDOUT + +#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR +#define CURLE_HTTP_PORT_FAILED CURLE_INTERFACE_FAILED +#define CURLE_FTP_COULDNT_STOR_FILE CURLE_UPLOAD_FAILED + +#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE +#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME + +/* This was the error code 50 in 7.7.3 and a few earlier versions, this + is no longer used by libcurl but is instead #defined here only to not + make programs break */ +#define CURLE_ALREADY_COMPLETE 99999 + +/* Provide defines for really old option names */ +#define CURLOPT_FILE CURLOPT_WRITEDATA /* name changed in 7.9.7 */ +#define CURLOPT_INFILE CURLOPT_READDATA /* name changed in 7.9.7 */ +#define CURLOPT_WRITEHEADER CURLOPT_HEADERDATA + +/* Since long deprecated options with no code in the lib that does anything + with them. */ +#define CURLOPT_WRITEINFO CURLOPT_OBSOLETE40 +#define CURLOPT_CLOSEPOLICY CURLOPT_OBSOLETE72 + +#endif /*!CURL_NO_OLDIES*/ + +/* This prototype applies to all conversion callbacks */ +typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length); + +typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */ + void *ssl_ctx, /* actually an + OpenSSL SSL_CTX */ + void *userptr); + +typedef enum { + CURLPROXY_HTTP = 0, /* added in 7.10, new in 7.19.4 default is to use + CONNECT HTTP/1.1 */ + CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT + HTTP/1.0 */ + CURLPROXY_HTTPS = 2, /* added in 7.52.0 */ + CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already + in 7.10 */ + CURLPROXY_SOCKS5 = 5, /* added in 7.10 */ + CURLPROXY_SOCKS4A = 6, /* added in 7.18.0 */ + CURLPROXY_SOCKS5_HOSTNAME = 7 /* Use the SOCKS5 protocol but pass along the + host name rather than the IP address. added + in 7.18.0 */ +} curl_proxytype; /* this enum was added in 7.10 */ + +/* + * Bitmasks for CURLOPT_HTTPAUTH and CURLOPT_PROXYAUTH options: + * + * CURLAUTH_NONE - No HTTP authentication + * CURLAUTH_BASIC - HTTP Basic authentication (default) + * CURLAUTH_DIGEST - HTTP Digest authentication + * CURLAUTH_NEGOTIATE - HTTP Negotiate (SPNEGO) authentication + * CURLAUTH_GSSNEGOTIATE - Alias for CURLAUTH_NEGOTIATE (deprecated) + * CURLAUTH_NTLM - HTTP NTLM authentication + * CURLAUTH_DIGEST_IE - HTTP Digest authentication with IE flavour + * CURLAUTH_NTLM_WB - HTTP NTLM authentication delegated to winbind helper + * CURLAUTH_BEARER - HTTP Bearer token authentication + * CURLAUTH_ONLY - Use together with a single other type to force no + * authentication or just that single type + * CURLAUTH_ANY - All fine types set + * CURLAUTH_ANYSAFE - All fine types except Basic + */ + +#define CURLAUTH_NONE ((unsigned long)0) +#define CURLAUTH_BASIC (((unsigned long)1)<<0) +#define CURLAUTH_DIGEST (((unsigned long)1)<<1) +#define CURLAUTH_NEGOTIATE (((unsigned long)1)<<2) +/* Deprecated since the advent of CURLAUTH_NEGOTIATE */ +#define CURLAUTH_GSSNEGOTIATE CURLAUTH_NEGOTIATE +/* Used for CURLOPT_SOCKS5_AUTH to stay terminologically correct */ +#define CURLAUTH_GSSAPI CURLAUTH_NEGOTIATE +#define CURLAUTH_NTLM (((unsigned long)1)<<3) +#define CURLAUTH_DIGEST_IE (((unsigned long)1)<<4) +#define CURLAUTH_NTLM_WB (((unsigned long)1)<<5) +#define CURLAUTH_BEARER (((unsigned long)1)<<6) +#define CURLAUTH_ONLY (((unsigned long)1)<<31) +#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE) +#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE)) + +#define CURLSSH_AUTH_ANY ~0 /* all types supported by the server */ +#define CURLSSH_AUTH_NONE 0 /* none allowed, silly but complete */ +#define CURLSSH_AUTH_PUBLICKEY (1<<0) /* public/private key files */ +#define CURLSSH_AUTH_PASSWORD (1<<1) /* password */ +#define CURLSSH_AUTH_HOST (1<<2) /* host key files */ +#define CURLSSH_AUTH_KEYBOARD (1<<3) /* keyboard interactive */ +#define CURLSSH_AUTH_AGENT (1<<4) /* agent (ssh-agent, pageant...) */ +#define CURLSSH_AUTH_GSSAPI (1<<5) /* gssapi (kerberos, ...) */ +#define CURLSSH_AUTH_DEFAULT CURLSSH_AUTH_ANY + +#define CURLGSSAPI_DELEGATION_NONE 0 /* no delegation (default) */ +#define CURLGSSAPI_DELEGATION_POLICY_FLAG (1<<0) /* if permitted by policy */ +#define CURLGSSAPI_DELEGATION_FLAG (1<<1) /* delegate always */ + +#define CURL_ERROR_SIZE 256 + +enum curl_khtype { + CURLKHTYPE_UNKNOWN, + CURLKHTYPE_RSA1, + CURLKHTYPE_RSA, + CURLKHTYPE_DSS, + CURLKHTYPE_ECDSA, + CURLKHTYPE_ED25519 +}; + +struct curl_khkey { + const char *key; /* points to a zero-terminated string encoded with base64 + if len is zero, otherwise to the "raw" data */ + size_t len; + enum curl_khtype keytype; +}; + +/* this is the set of return values expected from the curl_sshkeycallback + callback */ +enum curl_khstat { + CURLKHSTAT_FINE_ADD_TO_FILE, + CURLKHSTAT_FINE, + CURLKHSTAT_REJECT, /* reject the connection, return an error */ + CURLKHSTAT_DEFER, /* do not accept it, but we can't answer right now so + this causes a CURLE_DEFER error but otherwise the + connection will be left intact etc */ + CURLKHSTAT_LAST /* not for use, only a marker for last-in-list */ +}; + +/* this is the set of status codes pass in to the callback */ +enum curl_khmatch { + CURLKHMATCH_OK, /* match */ + CURLKHMATCH_MISMATCH, /* host found, key mismatch! */ + CURLKHMATCH_MISSING, /* no matching host/key found */ + CURLKHMATCH_LAST /* not for use, only a marker for last-in-list */ +}; + +typedef int + (*curl_sshkeycallback) (CURL *easy, /* easy handle */ + const struct curl_khkey *knownkey, /* known */ + const struct curl_khkey *foundkey, /* found */ + enum curl_khmatch, /* libcurl's view on the keys */ + void *clientp); /* custom pointer passed from app */ + +/* parameter for the CURLOPT_USE_SSL option */ +typedef enum { + CURLUSESSL_NONE, /* do not attempt to use SSL */ + CURLUSESSL_TRY, /* try using SSL, proceed anyway otherwise */ + CURLUSESSL_CONTROL, /* SSL for the control connection or fail */ + CURLUSESSL_ALL, /* SSL for all communication or fail */ + CURLUSESSL_LAST /* not an option, never use */ +} curl_usessl; + +/* Definition of bits for the CURLOPT_SSL_OPTIONS argument: */ + +/* - ALLOW_BEAST tells libcurl to allow the BEAST SSL vulnerability in the + name of improving interoperability with older servers. Some SSL libraries + have introduced work-arounds for this flaw but those work-arounds sometimes + make the SSL communication fail. To regain functionality with those broken + servers, a user can this way allow the vulnerability back. */ +#define CURLSSLOPT_ALLOW_BEAST (1<<0) + +/* - NO_REVOKE tells libcurl to disable certificate revocation checks for those + SSL backends where such behavior is present. */ +#define CURLSSLOPT_NO_REVOKE (1<<1) + +/* The default connection attempt delay in milliseconds for happy eyeballs. + CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 and happy-eyeballs-timeout-ms.d document + this value, keep them in sync. */ +#define CURL_HET_DEFAULT 200L + +/* The default connection upkeep interval in milliseconds. */ +#define CURL_UPKEEP_INTERVAL_DEFAULT 60000L + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Backwards compatibility with older names */ +/* These are scheduled to disappear by 2009 */ + +#define CURLFTPSSL_NONE CURLUSESSL_NONE +#define CURLFTPSSL_TRY CURLUSESSL_TRY +#define CURLFTPSSL_CONTROL CURLUSESSL_CONTROL +#define CURLFTPSSL_ALL CURLUSESSL_ALL +#define CURLFTPSSL_LAST CURLUSESSL_LAST +#define curl_ftpssl curl_usessl +#endif /*!CURL_NO_OLDIES*/ + +/* parameter for the CURLOPT_FTP_SSL_CCC option */ +typedef enum { + CURLFTPSSL_CCC_NONE, /* do not send CCC */ + CURLFTPSSL_CCC_PASSIVE, /* Let the server initiate the shutdown */ + CURLFTPSSL_CCC_ACTIVE, /* Initiate the shutdown */ + CURLFTPSSL_CCC_LAST /* not an option, never use */ +} curl_ftpccc; + +/* parameter for the CURLOPT_FTPSSLAUTH option */ +typedef enum { + CURLFTPAUTH_DEFAULT, /* let libcurl decide */ + CURLFTPAUTH_SSL, /* use "AUTH SSL" */ + CURLFTPAUTH_TLS, /* use "AUTH TLS" */ + CURLFTPAUTH_LAST /* not an option, never use */ +} curl_ftpauth; + +/* parameter for the CURLOPT_FTP_CREATE_MISSING_DIRS option */ +typedef enum { + CURLFTP_CREATE_DIR_NONE, /* do NOT create missing dirs! */ + CURLFTP_CREATE_DIR, /* (FTP/SFTP) if CWD fails, try MKD and then CWD + again if MKD succeeded, for SFTP this does + similar magic */ + CURLFTP_CREATE_DIR_RETRY, /* (FTP only) if CWD fails, try MKD and then CWD + again even if MKD failed! */ + CURLFTP_CREATE_DIR_LAST /* not an option, never use */ +} curl_ftpcreatedir; + +/* parameter for the CURLOPT_FTP_FILEMETHOD option */ +typedef enum { + CURLFTPMETHOD_DEFAULT, /* let libcurl pick */ + CURLFTPMETHOD_MULTICWD, /* single CWD operation for each path part */ + CURLFTPMETHOD_NOCWD, /* no CWD at all */ + CURLFTPMETHOD_SINGLECWD, /* one CWD to full dir, then work on file */ + CURLFTPMETHOD_LAST /* not an option, never use */ +} curl_ftpmethod; + +/* bitmask defines for CURLOPT_HEADEROPT */ +#define CURLHEADER_UNIFIED 0 +#define CURLHEADER_SEPARATE (1<<0) + +/* CURLALTSVC_* are bits for the CURLOPT_ALTSVC_CTRL option */ +#define CURLALTSVC_IMMEDIATELY (1<<0) +#define CURLALTSVC_ALTUSED (1<<1) +#define CURLALTSVC_READONLYFILE (1<<2) +#define CURLALTSVC_H1 (1<<3) +#define CURLALTSVC_H2 (1<<4) +#define CURLALTSVC_H3 (1<<5) + +/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */ +#define CURLPROTO_HTTP (1<<0) +#define CURLPROTO_HTTPS (1<<1) +#define CURLPROTO_FTP (1<<2) +#define CURLPROTO_FTPS (1<<3) +#define CURLPROTO_SCP (1<<4) +#define CURLPROTO_SFTP (1<<5) +#define CURLPROTO_TELNET (1<<6) +#define CURLPROTO_LDAP (1<<7) +#define CURLPROTO_LDAPS (1<<8) +#define CURLPROTO_DICT (1<<9) +#define CURLPROTO_FILE (1<<10) +#define CURLPROTO_TFTP (1<<11) +#define CURLPROTO_IMAP (1<<12) +#define CURLPROTO_IMAPS (1<<13) +#define CURLPROTO_POP3 (1<<14) +#define CURLPROTO_POP3S (1<<15) +#define CURLPROTO_SMTP (1<<16) +#define CURLPROTO_SMTPS (1<<17) +#define CURLPROTO_RTSP (1<<18) +#define CURLPROTO_RTMP (1<<19) +#define CURLPROTO_RTMPT (1<<20) +#define CURLPROTO_RTMPE (1<<21) +#define CURLPROTO_RTMPTE (1<<22) +#define CURLPROTO_RTMPS (1<<23) +#define CURLPROTO_RTMPTS (1<<24) +#define CURLPROTO_GOPHER (1<<25) +#define CURLPROTO_SMB (1<<26) +#define CURLPROTO_SMBS (1<<27) +#define CURLPROTO_ALL (~0) /* enable everything */ + +/* long may be 32 or 64 bits, but we should never depend on anything else + but 32 */ +#define CURLOPTTYPE_LONG 0 +#define CURLOPTTYPE_OBJECTPOINT 10000 +#define CURLOPTTYPE_STRINGPOINT 10000 +#define CURLOPTTYPE_FUNCTIONPOINT 20000 +#define CURLOPTTYPE_OFF_T 30000 + +/* *STRINGPOINT is an alias for OBJECTPOINT to allow tools to extract the + string options from the header file */ + +/* name is uppercase CURLOPT_, + type is one of the defined CURLOPTTYPE_ + number is unique identifier */ +#ifdef CINIT +#undef CINIT +#endif + +#ifdef CURL_ISOCPP +#define CINIT(na,t,nu) CURLOPT_ ## na = CURLOPTTYPE_ ## t + nu +#else +/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ +#define LONG CURLOPTTYPE_LONG +#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT +#define STRINGPOINT CURLOPTTYPE_OBJECTPOINT +#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT +#define OFF_T CURLOPTTYPE_OFF_T +#define CINIT(name,type,number) CURLOPT_/**/name = type + number +#endif + +/* + * This macro-mania below setups the CURLOPT_[what] enum, to be used with + * curl_easy_setopt(). The first argument in the CINIT() macro is the [what] + * word. + */ + +typedef enum { + /* This is the FILE * or void * the regular output should be written to. */ + CINIT(WRITEDATA, OBJECTPOINT, 1), + + /* The full URL to get/put */ + CINIT(URL, STRINGPOINT, 2), + + /* Port number to connect to, if other than default. */ + CINIT(PORT, LONG, 3), + + /* Name of proxy to use. */ + CINIT(PROXY, STRINGPOINT, 4), + + /* "user:password;options" to use when fetching. */ + CINIT(USERPWD, STRINGPOINT, 5), + + /* "user:password" to use with proxy. */ + CINIT(PROXYUSERPWD, STRINGPOINT, 6), + + /* Range to get, specified as an ASCII string. */ + CINIT(RANGE, STRINGPOINT, 7), + + /* not used */ + + /* Specified file stream to upload from (use as input): */ + CINIT(READDATA, OBJECTPOINT, 9), + + /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE + * bytes big. */ + CINIT(ERRORBUFFER, OBJECTPOINT, 10), + + /* Function that will be called to store the output (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CINIT(WRITEFUNCTION, FUNCTIONPOINT, 11), + + /* Function that will be called to read the input (instead of fread). The + * parameters will use fread() syntax, make sure to follow them. */ + CINIT(READFUNCTION, FUNCTIONPOINT, 12), + + /* Time-out the read operation after this amount of seconds */ + CINIT(TIMEOUT, LONG, 13), + + /* If the CURLOPT_INFILE is used, this can be used to inform libcurl about + * how large the file being sent really is. That allows better error + * checking and better verifies that the upload was successful. -1 means + * unknown size. + * + * For large file support, there is also a _LARGE version of the key + * which takes an off_t type, allowing platforms with larger off_t + * sizes to handle larger files. See below for INFILESIZE_LARGE. + */ + CINIT(INFILESIZE, LONG, 14), + + /* POST static input fields. */ + CINIT(POSTFIELDS, OBJECTPOINT, 15), + + /* Set the referrer page (needed by some CGIs) */ + CINIT(REFERER, STRINGPOINT, 16), + + /* Set the FTP PORT string (interface name, named or numerical IP address) + Use i.e '-' to use default address. */ + CINIT(FTPPORT, STRINGPOINT, 17), + + /* Set the User-Agent string (examined by some CGIs) */ + CINIT(USERAGENT, STRINGPOINT, 18), + + /* If the download receives less than "low speed limit" bytes/second + * during "low speed time" seconds, the operations is aborted. + * You could i.e if you have a pretty high speed connection, abort if + * it is less than 2000 bytes/sec during 20 seconds. + */ + + /* Set the "low speed limit" */ + CINIT(LOW_SPEED_LIMIT, LONG, 19), + + /* Set the "low speed time" */ + CINIT(LOW_SPEED_TIME, LONG, 20), + + /* Set the continuation offset. + * + * Note there is also a _LARGE version of this key which uses + * off_t types, allowing for large file offsets on platforms which + * use larger-than-32-bit off_t's. Look below for RESUME_FROM_LARGE. + */ + CINIT(RESUME_FROM, LONG, 21), + + /* Set cookie in request: */ + CINIT(COOKIE, STRINGPOINT, 22), + + /* This points to a linked list of headers, struct curl_slist kind. This + list is also used for RTSP (in spite of its name) */ + CINIT(HTTPHEADER, OBJECTPOINT, 23), + + /* This points to a linked list of post entries, struct curl_httppost */ + CINIT(HTTPPOST, OBJECTPOINT, 24), + + /* name of the file keeping your private SSL-certificate */ + CINIT(SSLCERT, STRINGPOINT, 25), + + /* password for the SSL or SSH private key */ + CINIT(KEYPASSWD, STRINGPOINT, 26), + + /* send TYPE parameter? */ + CINIT(CRLF, LONG, 27), + + /* send linked-list of QUOTE commands */ + CINIT(QUOTE, OBJECTPOINT, 28), + + /* send FILE * or void * to store headers to, if you use a callback it + is simply passed to the callback unmodified */ + CINIT(HEADERDATA, OBJECTPOINT, 29), + + /* point to a file to read the initial cookies from, also enables + "cookie awareness" */ + CINIT(COOKIEFILE, STRINGPOINT, 31), + + /* What version to specifically try to use. + See CURL_SSLVERSION defines below. */ + CINIT(SSLVERSION, LONG, 32), + + /* What kind of HTTP time condition to use, see defines */ + CINIT(TIMECONDITION, LONG, 33), + + /* Time to use with the above condition. Specified in number of seconds + since 1 Jan 1970 */ + CINIT(TIMEVALUE, LONG, 34), + + /* 35 = OBSOLETE */ + + /* Custom request, for customizing the get command like + HTTP: DELETE, TRACE and others + FTP: to use a different list command + */ + CINIT(CUSTOMREQUEST, STRINGPOINT, 36), + + /* FILE handle to use instead of stderr */ + CINIT(STDERR, OBJECTPOINT, 37), + + /* 38 is not used */ + + /* send linked-list of post-transfer QUOTE commands */ + CINIT(POSTQUOTE, OBJECTPOINT, 39), + + CINIT(OBSOLETE40, OBJECTPOINT, 40), /* OBSOLETE, do not use! */ + + CINIT(VERBOSE, LONG, 41), /* talk a lot */ + CINIT(HEADER, LONG, 42), /* throw the header out too */ + CINIT(NOPROGRESS, LONG, 43), /* shut off the progress meter */ + CINIT(NOBODY, LONG, 44), /* use HEAD to get http document */ + CINIT(FAILONERROR, LONG, 45), /* no output on http error codes >= 400 */ + CINIT(UPLOAD, LONG, 46), /* this is an upload */ + CINIT(POST, LONG, 47), /* HTTP POST method */ + CINIT(DIRLISTONLY, LONG, 48), /* bare names when listing directories */ + + CINIT(APPEND, LONG, 50), /* Append instead of overwrite on upload! */ + + /* Specify whether to read the user+password from the .netrc or the URL. + * This must be one of the CURL_NETRC_* enums below. */ + CINIT(NETRC, LONG, 51), + + CINIT(FOLLOWLOCATION, LONG, 52), /* use Location: Luke! */ + + CINIT(TRANSFERTEXT, LONG, 53), /* transfer data in text/ASCII format */ + CINIT(PUT, LONG, 54), /* HTTP PUT */ + + /* 55 = OBSOLETE */ + + /* DEPRECATED + * Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_progress_callback + * prototype defines. */ + CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56), + + /* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION + callbacks */ + CINIT(PROGRESSDATA, OBJECTPOINT, 57), +#define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA + + /* We want the referrer field set automatically when following locations */ + CINIT(AUTOREFERER, LONG, 58), + + /* Port of the proxy, can be set in the proxy string as well with: + "[host]:[port]" */ + CINIT(PROXYPORT, LONG, 59), + + /* size of the POST input data, if strlen() is not good to use */ + CINIT(POSTFIELDSIZE, LONG, 60), + + /* tunnel non-http operations through a HTTP proxy */ + CINIT(HTTPPROXYTUNNEL, LONG, 61), + + /* Set the interface string to use as outgoing network interface */ + CINIT(INTERFACE, STRINGPOINT, 62), + + /* Set the krb4/5 security level, this also enables krb4/5 awareness. This + * is a string, 'clear', 'safe', 'confidential' or 'private'. If the string + * is set but doesn't match one of these, 'private' will be used. */ + CINIT(KRBLEVEL, STRINGPOINT, 63), + + /* Set if we should verify the peer in ssl handshake, set 1 to verify. */ + CINIT(SSL_VERIFYPEER, LONG, 64), + + /* The CApath or CAfile used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CINIT(CAINFO, STRINGPOINT, 65), + + /* 66 = OBSOLETE */ + /* 67 = OBSOLETE */ + + /* Maximum number of http redirects to follow */ + CINIT(MAXREDIRS, LONG, 68), + + /* Pass a long set to 1 to get the date of the requested document (if + possible)! Pass a zero to shut it off. */ + CINIT(FILETIME, LONG, 69), + + /* This points to a linked list of telnet options */ + CINIT(TELNETOPTIONS, OBJECTPOINT, 70), + + /* Max amount of cached alive connections */ + CINIT(MAXCONNECTS, LONG, 71), + + CINIT(OBSOLETE72, LONG, 72), /* OBSOLETE, do not use! */ + + /* 73 = OBSOLETE */ + + /* Set to explicitly use a new connection for the upcoming transfer. + Do not use this unless you're absolutely sure of this, as it makes the + operation slower and is less friendly for the network. */ + CINIT(FRESH_CONNECT, LONG, 74), + + /* Set to explicitly forbid the upcoming transfer's connection to be re-used + when done. Do not use this unless you're absolutely sure of this, as it + makes the operation slower and is less friendly for the network. */ + CINIT(FORBID_REUSE, LONG, 75), + + /* Set to a file name that contains random data for libcurl to use to + seed the random engine when doing SSL connects. */ + CINIT(RANDOM_FILE, STRINGPOINT, 76), + + /* Set to the Entropy Gathering Daemon socket pathname */ + CINIT(EGDSOCKET, STRINGPOINT, 77), + + /* Time-out connect operations after this amount of seconds, if connects are + OK within this time, then fine... This only aborts the connect phase. */ + CINIT(CONNECTTIMEOUT, LONG, 78), + + /* Function that will be called to store headers (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CINIT(HEADERFUNCTION, FUNCTIONPOINT, 79), + + /* Set this to force the HTTP request to get back to GET. Only really usable + if POST, PUT or a custom request have been used first. + */ + CINIT(HTTPGET, LONG, 80), + + /* Set if we should verify the Common name from the peer certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches the + * provided hostname. */ + CINIT(SSL_VERIFYHOST, LONG, 81), + + /* Specify which file name to write all known cookies in after completed + operation. Set file name to "-" (dash) to make it go to stdout. */ + CINIT(COOKIEJAR, STRINGPOINT, 82), + + /* Specify which SSL ciphers to use */ + CINIT(SSL_CIPHER_LIST, STRINGPOINT, 83), + + /* Specify which HTTP version to use! This must be set to one of the + CURL_HTTP_VERSION* enums set below. */ + CINIT(HTTP_VERSION, LONG, 84), + + /* Specifically switch on or off the FTP engine's use of the EPSV command. By + default, that one will always be attempted before the more traditional + PASV command. */ + CINIT(FTP_USE_EPSV, LONG, 85), + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */ + CINIT(SSLCERTTYPE, STRINGPOINT, 86), + + /* name of the file keeping your private SSL-key */ + CINIT(SSLKEY, STRINGPOINT, 87), + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */ + CINIT(SSLKEYTYPE, STRINGPOINT, 88), + + /* crypto engine for the SSL-sub system */ + CINIT(SSLENGINE, STRINGPOINT, 89), + + /* set the crypto engine for the SSL-sub system as default + the param has no meaning... + */ + CINIT(SSLENGINE_DEFAULT, LONG, 90), + + /* Non-zero value means to use the global dns cache */ + CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91), /* DEPRECATED, do not use! */ + + /* DNS cache timeout */ + CINIT(DNS_CACHE_TIMEOUT, LONG, 92), + + /* send linked-list of pre-transfer QUOTE commands */ + CINIT(PREQUOTE, OBJECTPOINT, 93), + + /* set the debug function */ + CINIT(DEBUGFUNCTION, FUNCTIONPOINT, 94), + + /* set the data for the debug function */ + CINIT(DEBUGDATA, OBJECTPOINT, 95), + + /* mark this as start of a cookie session */ + CINIT(COOKIESESSION, LONG, 96), + + /* The CApath directory used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CINIT(CAPATH, STRINGPOINT, 97), + + /* Instruct libcurl to use a smaller receive buffer */ + CINIT(BUFFERSIZE, LONG, 98), + + /* Instruct libcurl to not use any signal/alarm handlers, even when using + timeouts. This option is useful for multi-threaded applications. + See libcurl-the-guide for more background information. */ + CINIT(NOSIGNAL, LONG, 99), + + /* Provide a CURLShare for mutexing non-ts data */ + CINIT(SHARE, OBJECTPOINT, 100), + + /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default), + CURLPROXY_HTTPS, CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and + CURLPROXY_SOCKS5. */ + CINIT(PROXYTYPE, LONG, 101), + + /* Set the Accept-Encoding string. Use this to tell a server you would like + the response to be compressed. Before 7.21.6, this was known as + CURLOPT_ENCODING */ + CINIT(ACCEPT_ENCODING, STRINGPOINT, 102), + + /* Set pointer to private data */ + CINIT(PRIVATE, OBJECTPOINT, 103), + + /* Set aliases for HTTP 200 in the HTTP Response header */ + CINIT(HTTP200ALIASES, OBJECTPOINT, 104), + + /* Continue to send authentication (user+password) when following locations, + even when hostname changed. This can potentially send off the name + and password to whatever host the server decides. */ + CINIT(UNRESTRICTED_AUTH, LONG, 105), + + /* Specifically switch on or off the FTP engine's use of the EPRT command ( + it also disables the LPRT attempt). By default, those ones will always be + attempted before the good old traditional PORT command. */ + CINIT(FTP_USE_EPRT, LONG, 106), + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_USERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + CINIT(HTTPAUTH, LONG, 107), + + /* Set the ssl context callback function, currently only for OpenSSL ssl_ctx + in second argument. The function must be matching the + curl_ssl_ctx_callback proto. */ + CINIT(SSL_CTX_FUNCTION, FUNCTIONPOINT, 108), + + /* Set the userdata for the ssl context callback function's third + argument */ + CINIT(SSL_CTX_DATA, OBJECTPOINT, 109), + + /* FTP Option that causes missing dirs to be created on the remote server. + In 7.19.4 we introduced the convenience enums for this option using the + CURLFTP_CREATE_DIR prefix. + */ + CINIT(FTP_CREATE_MISSING_DIRS, LONG, 110), + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_PROXYUSERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + CINIT(PROXYAUTH, LONG, 111), + + /* FTP option that changes the timeout, in seconds, associated with + getting a response. This is different from transfer timeout time and + essentially places a demand on the FTP server to acknowledge commands + in a timely manner. */ + CINIT(FTP_RESPONSE_TIMEOUT, LONG, 112), +#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT + + /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to + tell libcurl to resolve names to those IP versions only. This only has + affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */ + CINIT(IPRESOLVE, LONG, 113), + + /* Set this option to limit the size of a file that will be downloaded from + an HTTP or FTP server. + + Note there is also _LARGE version which adds large file support for + platforms which have larger off_t sizes. See MAXFILESIZE_LARGE below. */ + CINIT(MAXFILESIZE, LONG, 114), + + /* See the comment for INFILESIZE above, but in short, specifies + * the size of the file being uploaded. -1 means unknown. + */ + CINIT(INFILESIZE_LARGE, OFF_T, 115), + + /* Sets the continuation offset. There is also a LONG version of this; + * look above for RESUME_FROM. + */ + CINIT(RESUME_FROM_LARGE, OFF_T, 116), + + /* Sets the maximum size of data that will be downloaded from + * an HTTP or FTP server. See MAXFILESIZE above for the LONG version. + */ + CINIT(MAXFILESIZE_LARGE, OFF_T, 117), + + /* Set this option to the file name of your .netrc file you want libcurl + to parse (using the CURLOPT_NETRC option). If not set, libcurl will do + a poor attempt to find the user's home directory and check for a .netrc + file in there. */ + CINIT(NETRC_FILE, STRINGPOINT, 118), + + /* Enable SSL/TLS for FTP, pick one of: + CURLUSESSL_TRY - try using SSL, proceed anyway otherwise + CURLUSESSL_CONTROL - SSL for the control connection or fail + CURLUSESSL_ALL - SSL for all communication or fail + */ + CINIT(USE_SSL, LONG, 119), + + /* The _LARGE version of the standard POSTFIELDSIZE option */ + CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120), + + /* Enable/disable the TCP Nagle algorithm */ + CINIT(TCP_NODELAY, LONG, 121), + + /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 123 OBSOLETE. Gone in 7.16.0 */ + /* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 127 OBSOLETE. Gone in 7.16.0 */ + /* 128 OBSOLETE. Gone in 7.16.0 */ + + /* When FTP over SSL/TLS is selected (with CURLOPT_USE_SSL), this option + can be used to change libcurl's default action which is to first try + "AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK + response has been received. + + Available parameters are: + CURLFTPAUTH_DEFAULT - let libcurl decide + CURLFTPAUTH_SSL - try "AUTH SSL" first, then TLS + CURLFTPAUTH_TLS - try "AUTH TLS" first, then SSL + */ + CINIT(FTPSSLAUTH, LONG, 129), + + CINIT(IOCTLFUNCTION, FUNCTIONPOINT, 130), + CINIT(IOCTLDATA, OBJECTPOINT, 131), + + /* 132 OBSOLETE. Gone in 7.16.0 */ + /* 133 OBSOLETE. Gone in 7.16.0 */ + + /* zero terminated string for pass on to the FTP server when asked for + "account" info */ + CINIT(FTP_ACCOUNT, STRINGPOINT, 134), + + /* feed cookie into cookie engine */ + CINIT(COOKIELIST, STRINGPOINT, 135), + + /* ignore Content-Length */ + CINIT(IGNORE_CONTENT_LENGTH, LONG, 136), + + /* Set to non-zero to skip the IP address received in a 227 PASV FTP server + response. Typically used for FTP-SSL purposes but is not restricted to + that. libcurl will then instead use the same IP address it used for the + control connection. */ + CINIT(FTP_SKIP_PASV_IP, LONG, 137), + + /* Select "file method" to use when doing FTP, see the curl_ftpmethod + above. */ + CINIT(FTP_FILEMETHOD, LONG, 138), + + /* Local port number to bind the socket to */ + CINIT(LOCALPORT, LONG, 139), + + /* Number of ports to try, including the first one set with LOCALPORT. + Thus, setting it to 1 will make no additional attempts but the first. + */ + CINIT(LOCALPORTRANGE, LONG, 140), + + /* no transfer, set up connection and let application use the socket by + extracting it with CURLINFO_LASTSOCKET */ + CINIT(CONNECT_ONLY, LONG, 141), + + /* Function that will be called to convert from the + network encoding (instead of using the iconv calls in libcurl) */ + CINIT(CONV_FROM_NETWORK_FUNCTION, FUNCTIONPOINT, 142), + + /* Function that will be called to convert to the + network encoding (instead of using the iconv calls in libcurl) */ + CINIT(CONV_TO_NETWORK_FUNCTION, FUNCTIONPOINT, 143), + + /* Function that will be called to convert from UTF8 + (instead of using the iconv calls in libcurl) + Note that this is used only for SSL certificate processing */ + CINIT(CONV_FROM_UTF8_FUNCTION, FUNCTIONPOINT, 144), + + /* if the connection proceeds too quickly then need to slow it down */ + /* limit-rate: maximum number of bytes per second to send or receive */ + CINIT(MAX_SEND_SPEED_LARGE, OFF_T, 145), + CINIT(MAX_RECV_SPEED_LARGE, OFF_T, 146), + + /* Pointer to command string to send if USER/PASS fails. */ + CINIT(FTP_ALTERNATIVE_TO_USER, STRINGPOINT, 147), + + /* callback function for setting socket options */ + CINIT(SOCKOPTFUNCTION, FUNCTIONPOINT, 148), + CINIT(SOCKOPTDATA, OBJECTPOINT, 149), + + /* set to 0 to disable session ID re-use for this transfer, default is + enabled (== 1) */ + CINIT(SSL_SESSIONID_CACHE, LONG, 150), + + /* allowed SSH authentication methods */ + CINIT(SSH_AUTH_TYPES, LONG, 151), + + /* Used by scp/sftp to do public/private key authentication */ + CINIT(SSH_PUBLIC_KEYFILE, STRINGPOINT, 152), + CINIT(SSH_PRIVATE_KEYFILE, STRINGPOINT, 153), + + /* Send CCC (Clear Command Channel) after authentication */ + CINIT(FTP_SSL_CCC, LONG, 154), + + /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */ + CINIT(TIMEOUT_MS, LONG, 155), + CINIT(CONNECTTIMEOUT_MS, LONG, 156), + + /* set to zero to disable the libcurl's decoding and thus pass the raw body + data to the application even when it is encoded/compressed */ + CINIT(HTTP_TRANSFER_DECODING, LONG, 157), + CINIT(HTTP_CONTENT_DECODING, LONG, 158), + + /* Permission used when creating new files and directories on the remote + server for protocols that support it, SFTP/SCP/FILE */ + CINIT(NEW_FILE_PERMS, LONG, 159), + CINIT(NEW_DIRECTORY_PERMS, LONG, 160), + + /* Set the behaviour of POST when redirecting. Values must be set to one + of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */ + CINIT(POSTREDIR, LONG, 161), + + /* used by scp/sftp to verify the host's public key */ + CINIT(SSH_HOST_PUBLIC_KEY_MD5, STRINGPOINT, 162), + + /* Callback function for opening socket (instead of socket(2)). Optionally, + callback is able change the address or refuse to connect returning + CURL_SOCKET_BAD. The callback should have type + curl_opensocket_callback */ + CINIT(OPENSOCKETFUNCTION, FUNCTIONPOINT, 163), + CINIT(OPENSOCKETDATA, OBJECTPOINT, 164), + + /* POST volatile input fields. */ + CINIT(COPYPOSTFIELDS, OBJECTPOINT, 165), + + /* set transfer mode (;type=) when doing FTP via an HTTP proxy */ + CINIT(PROXY_TRANSFER_MODE, LONG, 166), + + /* Callback function for seeking in the input stream */ + CINIT(SEEKFUNCTION, FUNCTIONPOINT, 167), + CINIT(SEEKDATA, OBJECTPOINT, 168), + + /* CRL file */ + CINIT(CRLFILE, STRINGPOINT, 169), + + /* Issuer certificate */ + CINIT(ISSUERCERT, STRINGPOINT, 170), + + /* (IPv6) Address scope */ + CINIT(ADDRESS_SCOPE, LONG, 171), + + /* Collect certificate chain info and allow it to get retrievable with + CURLINFO_CERTINFO after the transfer is complete. */ + CINIT(CERTINFO, LONG, 172), + + /* "name" and "pwd" to use when fetching. */ + CINIT(USERNAME, STRINGPOINT, 173), + CINIT(PASSWORD, STRINGPOINT, 174), + + /* "name" and "pwd" to use with Proxy when fetching. */ + CINIT(PROXYUSERNAME, STRINGPOINT, 175), + CINIT(PROXYPASSWORD, STRINGPOINT, 176), + + /* Comma separated list of hostnames defining no-proxy zones. These should + match both hostnames directly, and hostnames within a domain. For + example, local.com will match local.com and www.local.com, but NOT + notlocal.com or www.notlocal.com. For compatibility with other + implementations of this, .local.com will be considered to be the same as + local.com. A single * is the only valid wildcard, and effectively + disables the use of proxy. */ + CINIT(NOPROXY, STRINGPOINT, 177), + + /* block size for TFTP transfers */ + CINIT(TFTP_BLKSIZE, LONG, 178), + + /* Socks Service */ + CINIT(SOCKS5_GSSAPI_SERVICE, STRINGPOINT, 179), /* DEPRECATED, do not use! */ + + /* Socks Service */ + CINIT(SOCKS5_GSSAPI_NEC, LONG, 180), + + /* set the bitmask for the protocols that are allowed to be used for the + transfer, which thus helps the app which takes URLs from users or other + external inputs and want to restrict what protocol(s) to deal + with. Defaults to CURLPROTO_ALL. */ + CINIT(PROTOCOLS, LONG, 181), + + /* set the bitmask for the protocols that libcurl is allowed to follow to, + as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs + to be set in both bitmasks to be allowed to get redirected to. Defaults + to all protocols except FILE and SCP. */ + CINIT(REDIR_PROTOCOLS, LONG, 182), + + /* set the SSH knownhost file name to use */ + CINIT(SSH_KNOWNHOSTS, STRINGPOINT, 183), + + /* set the SSH host key callback, must point to a curl_sshkeycallback + function */ + CINIT(SSH_KEYFUNCTION, FUNCTIONPOINT, 184), + + /* set the SSH host key callback custom pointer */ + CINIT(SSH_KEYDATA, OBJECTPOINT, 185), + + /* set the SMTP mail originator */ + CINIT(MAIL_FROM, STRINGPOINT, 186), + + /* set the list of SMTP mail receiver(s) */ + CINIT(MAIL_RCPT, OBJECTPOINT, 187), + + /* FTP: send PRET before PASV */ + CINIT(FTP_USE_PRET, LONG, 188), + + /* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */ + CINIT(RTSP_REQUEST, LONG, 189), + + /* The RTSP session identifier */ + CINIT(RTSP_SESSION_ID, STRINGPOINT, 190), + + /* The RTSP stream URI */ + CINIT(RTSP_STREAM_URI, STRINGPOINT, 191), + + /* The Transport: header to use in RTSP requests */ + CINIT(RTSP_TRANSPORT, STRINGPOINT, 192), + + /* Manually initialize the client RTSP CSeq for this handle */ + CINIT(RTSP_CLIENT_CSEQ, LONG, 193), + + /* Manually initialize the server RTSP CSeq for this handle */ + CINIT(RTSP_SERVER_CSEQ, LONG, 194), + + /* The stream to pass to INTERLEAVEFUNCTION. */ + CINIT(INTERLEAVEDATA, OBJECTPOINT, 195), + + /* Let the application define a custom write method for RTP data */ + CINIT(INTERLEAVEFUNCTION, FUNCTIONPOINT, 196), + + /* Turn on wildcard matching */ + CINIT(WILDCARDMATCH, LONG, 197), + + /* Directory matching callback called before downloading of an + individual file (chunk) started */ + CINIT(CHUNK_BGN_FUNCTION, FUNCTIONPOINT, 198), + + /* Directory matching callback called after the file (chunk) + was downloaded, or skipped */ + CINIT(CHUNK_END_FUNCTION, FUNCTIONPOINT, 199), + + /* Change match (fnmatch-like) callback for wildcard matching */ + CINIT(FNMATCH_FUNCTION, FUNCTIONPOINT, 200), + + /* Let the application define custom chunk data pointer */ + CINIT(CHUNK_DATA, OBJECTPOINT, 201), + + /* FNMATCH_FUNCTION user pointer */ + CINIT(FNMATCH_DATA, OBJECTPOINT, 202), + + /* send linked-list of name:port:address sets */ + CINIT(RESOLVE, OBJECTPOINT, 203), + + /* Set a username for authenticated TLS */ + CINIT(TLSAUTH_USERNAME, STRINGPOINT, 204), + + /* Set a password for authenticated TLS */ + CINIT(TLSAUTH_PASSWORD, STRINGPOINT, 205), + + /* Set authentication type for authenticated TLS */ + CINIT(TLSAUTH_TYPE, STRINGPOINT, 206), + + /* Set to 1 to enable the "TE:" header in HTTP requests to ask for + compressed transfer-encoded responses. Set to 0 to disable the use of TE: + in outgoing requests. The current default is 0, but it might change in a + future libcurl release. + + libcurl will ask for the compressed methods it knows of, and if that + isn't any, it will not ask for transfer-encoding at all even if this + option is set to 1. + + */ + CINIT(TRANSFER_ENCODING, LONG, 207), + + /* Callback function for closing socket (instead of close(2)). The callback + should have type curl_closesocket_callback */ + CINIT(CLOSESOCKETFUNCTION, FUNCTIONPOINT, 208), + CINIT(CLOSESOCKETDATA, OBJECTPOINT, 209), + + /* allow GSSAPI credential delegation */ + CINIT(GSSAPI_DELEGATION, LONG, 210), + + /* Set the name servers to use for DNS resolution */ + CINIT(DNS_SERVERS, STRINGPOINT, 211), + + /* Time-out accept operations (currently for FTP only) after this amount + of milliseconds. */ + CINIT(ACCEPTTIMEOUT_MS, LONG, 212), + + /* Set TCP keepalive */ + CINIT(TCP_KEEPALIVE, LONG, 213), + + /* non-universal keepalive knobs (Linux, AIX, HP-UX, more) */ + CINIT(TCP_KEEPIDLE, LONG, 214), + CINIT(TCP_KEEPINTVL, LONG, 215), + + /* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */ + CINIT(SSL_OPTIONS, LONG, 216), + + /* Set the SMTP auth originator */ + CINIT(MAIL_AUTH, STRINGPOINT, 217), + + /* Enable/disable SASL initial response */ + CINIT(SASL_IR, LONG, 218), + + /* Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_xferinfo_callback + * prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */ + CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219), + + /* The XOAUTH2 bearer token */ + CINIT(XOAUTH2_BEARER, STRINGPOINT, 220), + + /* Set the interface string to use as outgoing network + * interface for DNS requests. + * Only supported by the c-ares DNS backend */ + CINIT(DNS_INTERFACE, STRINGPOINT, 221), + + /* Set the local IPv4 address to use for outgoing DNS requests. + * Only supported by the c-ares DNS backend */ + CINIT(DNS_LOCAL_IP4, STRINGPOINT, 222), + + /* Set the local IPv6 address to use for outgoing DNS requests. + * Only supported by the c-ares DNS backend */ + CINIT(DNS_LOCAL_IP6, STRINGPOINT, 223), + + /* Set authentication options directly */ + CINIT(LOGIN_OPTIONS, STRINGPOINT, 224), + + /* Enable/disable TLS NPN extension (http2 over ssl might fail without) */ + CINIT(SSL_ENABLE_NPN, LONG, 225), + + /* Enable/disable TLS ALPN extension (http2 over ssl might fail without) */ + CINIT(SSL_ENABLE_ALPN, LONG, 226), + + /* Time to wait for a response to a HTTP request containing an + * Expect: 100-continue header before sending the data anyway. */ + CINIT(EXPECT_100_TIMEOUT_MS, LONG, 227), + + /* This points to a linked list of headers used for proxy requests only, + struct curl_slist kind */ + CINIT(PROXYHEADER, OBJECTPOINT, 228), + + /* Pass in a bitmask of "header options" */ + CINIT(HEADEROPT, LONG, 229), + + /* The public key in DER form used to validate the peer public key + this option is used only if SSL_VERIFYPEER is true */ + CINIT(PINNEDPUBLICKEY, STRINGPOINT, 230), + + /* Path to Unix domain socket */ + CINIT(UNIX_SOCKET_PATH, STRINGPOINT, 231), + + /* Set if we should verify the certificate status. */ + CINIT(SSL_VERIFYSTATUS, LONG, 232), + + /* Set if we should enable TLS false start. */ + CINIT(SSL_FALSESTART, LONG, 233), + + /* Do not squash dot-dot sequences */ + CINIT(PATH_AS_IS, LONG, 234), + + /* Proxy Service Name */ + CINIT(PROXY_SERVICE_NAME, STRINGPOINT, 235), + + /* Service Name */ + CINIT(SERVICE_NAME, STRINGPOINT, 236), + + /* Wait/don't wait for pipe/mutex to clarify */ + CINIT(PIPEWAIT, LONG, 237), + + /* Set the protocol used when curl is given a URL without a protocol */ + CINIT(DEFAULT_PROTOCOL, STRINGPOINT, 238), + + /* Set stream weight, 1 - 256 (default is 16) */ + CINIT(STREAM_WEIGHT, LONG, 239), + + /* Set stream dependency on another CURL handle */ + CINIT(STREAM_DEPENDS, OBJECTPOINT, 240), + + /* Set E-xclusive stream dependency on another CURL handle */ + CINIT(STREAM_DEPENDS_E, OBJECTPOINT, 241), + + /* Do not send any tftp option requests to the server */ + CINIT(TFTP_NO_OPTIONS, LONG, 242), + + /* Linked-list of host:port:connect-to-host:connect-to-port, + overrides the URL's host:port (only for the network layer) */ + CINIT(CONNECT_TO, OBJECTPOINT, 243), + + /* Set TCP Fast Open */ + CINIT(TCP_FASTOPEN, LONG, 244), + + /* Continue to send data if the server responds early with an + * HTTP status code >= 300 */ + CINIT(KEEP_SENDING_ON_ERROR, LONG, 245), + + /* The CApath or CAfile used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CINIT(PROXY_CAINFO, STRINGPOINT, 246), + + /* The CApath directory used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CINIT(PROXY_CAPATH, STRINGPOINT, 247), + + /* Set if we should verify the proxy in ssl handshake, + set 1 to verify. */ + CINIT(PROXY_SSL_VERIFYPEER, LONG, 248), + + /* Set if we should verify the Common name from the proxy certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches + * the provided hostname. */ + CINIT(PROXY_SSL_VERIFYHOST, LONG, 249), + + /* What version to specifically try to use for proxy. + See CURL_SSLVERSION defines below. */ + CINIT(PROXY_SSLVERSION, LONG, 250), + + /* Set a username for authenticated TLS for proxy */ + CINIT(PROXY_TLSAUTH_USERNAME, STRINGPOINT, 251), + + /* Set a password for authenticated TLS for proxy */ + CINIT(PROXY_TLSAUTH_PASSWORD, STRINGPOINT, 252), + + /* Set authentication type for authenticated TLS for proxy */ + CINIT(PROXY_TLSAUTH_TYPE, STRINGPOINT, 253), + + /* name of the file keeping your private SSL-certificate for proxy */ + CINIT(PROXY_SSLCERT, STRINGPOINT, 254), + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") for + proxy */ + CINIT(PROXY_SSLCERTTYPE, STRINGPOINT, 255), + + /* name of the file keeping your private SSL-key for proxy */ + CINIT(PROXY_SSLKEY, STRINGPOINT, 256), + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") for + proxy */ + CINIT(PROXY_SSLKEYTYPE, STRINGPOINT, 257), + + /* password for the SSL private key for proxy */ + CINIT(PROXY_KEYPASSWD, STRINGPOINT, 258), + + /* Specify which SSL ciphers to use for proxy */ + CINIT(PROXY_SSL_CIPHER_LIST, STRINGPOINT, 259), + + /* CRL file for proxy */ + CINIT(PROXY_CRLFILE, STRINGPOINT, 260), + + /* Enable/disable specific SSL features with a bitmask for proxy, see + CURLSSLOPT_* */ + CINIT(PROXY_SSL_OPTIONS, LONG, 261), + + /* Name of pre proxy to use. */ + CINIT(PRE_PROXY, STRINGPOINT, 262), + + /* The public key in DER form used to validate the proxy public key + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CINIT(PROXY_PINNEDPUBLICKEY, STRINGPOINT, 263), + + /* Path to an abstract Unix domain socket */ + CINIT(ABSTRACT_UNIX_SOCKET, STRINGPOINT, 264), + + /* Suppress proxy CONNECT response headers from user callbacks */ + CINIT(SUPPRESS_CONNECT_HEADERS, LONG, 265), + + /* The request target, instead of extracted from the URL */ + CINIT(REQUEST_TARGET, STRINGPOINT, 266), + + /* bitmask of allowed auth methods for connections to SOCKS5 proxies */ + CINIT(SOCKS5_AUTH, LONG, 267), + + /* Enable/disable SSH compression */ + CINIT(SSH_COMPRESSION, LONG, 268), + + /* Post MIME data. */ + CINIT(MIMEPOST, OBJECTPOINT, 269), + + /* Time to use with the CURLOPT_TIMECONDITION. Specified in number of + seconds since 1 Jan 1970. */ + CINIT(TIMEVALUE_LARGE, OFF_T, 270), + + /* Head start in milliseconds to give happy eyeballs. */ + CINIT(HAPPY_EYEBALLS_TIMEOUT_MS, LONG, 271), + + /* Function that will be called before a resolver request is made */ + CINIT(RESOLVER_START_FUNCTION, FUNCTIONPOINT, 272), + + /* User data to pass to the resolver start callback. */ + CINIT(RESOLVER_START_DATA, OBJECTPOINT, 273), + + /* send HAProxy PROXY protocol header? */ + CINIT(HAPROXYPROTOCOL, LONG, 274), + + /* shuffle addresses before use when DNS returns multiple */ + CINIT(DNS_SHUFFLE_ADDRESSES, LONG, 275), + + /* Specify which TLS 1.3 ciphers suites to use */ + CINIT(TLS13_CIPHERS, STRINGPOINT, 276), + CINIT(PROXY_TLS13_CIPHERS, STRINGPOINT, 277), + + /* Disallow specifying username/login in URL. */ + CINIT(DISALLOW_USERNAME_IN_URL, LONG, 278), + + /* DNS-over-HTTPS URL */ + CINIT(DOH_URL, STRINGPOINT, 279), + + /* Preferred buffer size to use for uploads */ + CINIT(UPLOAD_BUFFERSIZE, LONG, 280), + + /* Time in ms between connection upkeep calls for long-lived connections. */ + CINIT(UPKEEP_INTERVAL_MS, LONG, 281), + + /* Specify URL using CURL URL API. */ + CINIT(CURLU, OBJECTPOINT, 282), + + /* add trailing data just after no more data is available */ + CINIT(TRAILERFUNCTION, FUNCTIONPOINT, 283), + + /* pointer to be passed to HTTP_TRAILER_FUNCTION */ + CINIT(TRAILERDATA, OBJECTPOINT, 284), + + /* set this to 1L to allow HTTP/0.9 responses or 0L to disallow */ + CINIT(HTTP09_ALLOWED, LONG, 285), + + /* alt-svc control bitmask */ + CINIT(ALTSVC_CTRL, LONG, 286), + + /* alt-svc cache file name to possibly read from/write to */ + CINIT(ALTSVC, STRINGPOINT, 287), + + /* maximum age of a connection to consider it for reuse (in seconds) */ + CINIT(MAXAGE_CONN, LONG, 288), + + CURLOPT_LASTENTRY /* the last unused */ +} CURLoption; + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Backwards compatibility with older names */ +/* These are scheduled to disappear by 2011 */ + +/* This was added in version 7.19.1 */ +#define CURLOPT_POST301 CURLOPT_POSTREDIR + +/* These are scheduled to disappear by 2009 */ + +/* The following were added in 7.17.0 */ +#define CURLOPT_SSLKEYPASSWD CURLOPT_KEYPASSWD +#define CURLOPT_FTPAPPEND CURLOPT_APPEND +#define CURLOPT_FTPLISTONLY CURLOPT_DIRLISTONLY +#define CURLOPT_FTP_SSL CURLOPT_USE_SSL + +/* The following were added earlier */ + +#define CURLOPT_SSLCERTPASSWD CURLOPT_KEYPASSWD +#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL + +#else +/* This is set if CURL_NO_OLDIES is defined at compile-time */ +#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */ +#endif + + + /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host + name resolves addresses using more than one IP protocol version, this + option might be handy to force libcurl to use a specific IP version. */ +#define CURL_IPRESOLVE_WHATEVER 0 /* default, resolves addresses to all IP + versions that your system allows */ +#define CURL_IPRESOLVE_V4 1 /* resolve to IPv4 addresses */ +#define CURL_IPRESOLVE_V6 2 /* resolve to IPv6 addresses */ + + /* three convenient "aliases" that follow the name scheme better */ +#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER + + /* These enums are for use with the CURLOPT_HTTP_VERSION option. */ +enum { + CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd + like the library to choose the best possible + for us! */ + CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */ + CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */ + CURL_HTTP_VERSION_2_0, /* please use HTTP 2 in the request */ + CURL_HTTP_VERSION_2TLS, /* use version 2 for HTTPS, version 1.1 for HTTP */ + CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE, /* please use HTTP 2 without HTTP/1.1 + Upgrade */ + + CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */ +}; + +/* Convenience definition simple because the name of the version is HTTP/2 and + not 2.0. The 2_0 version of the enum name was set while the version was + still planned to be 2.0 and we stick to it for compatibility. */ +#define CURL_HTTP_VERSION_2 CURL_HTTP_VERSION_2_0 + +/* + * Public API enums for RTSP requests + */ +enum { + CURL_RTSPREQ_NONE, /* first in list */ + CURL_RTSPREQ_OPTIONS, + CURL_RTSPREQ_DESCRIBE, + CURL_RTSPREQ_ANNOUNCE, + CURL_RTSPREQ_SETUP, + CURL_RTSPREQ_PLAY, + CURL_RTSPREQ_PAUSE, + CURL_RTSPREQ_TEARDOWN, + CURL_RTSPREQ_GET_PARAMETER, + CURL_RTSPREQ_SET_PARAMETER, + CURL_RTSPREQ_RECORD, + CURL_RTSPREQ_RECEIVE, + CURL_RTSPREQ_LAST /* last in list */ +}; + + /* These enums are for use with the CURLOPT_NETRC option. */ +enum CURL_NETRC_OPTION { + CURL_NETRC_IGNORED, /* The .netrc will never be read. + * This is the default. */ + CURL_NETRC_OPTIONAL, /* A user:password in the URL will be preferred + * to one in the .netrc. */ + CURL_NETRC_REQUIRED, /* A user:password in the URL will be ignored. + * Unless one is set programmatically, the .netrc + * will be queried. */ + CURL_NETRC_LAST +}; + +enum { + CURL_SSLVERSION_DEFAULT, + CURL_SSLVERSION_TLSv1, /* TLS 1.x */ + CURL_SSLVERSION_SSLv2, + CURL_SSLVERSION_SSLv3, + CURL_SSLVERSION_TLSv1_0, + CURL_SSLVERSION_TLSv1_1, + CURL_SSLVERSION_TLSv1_2, + CURL_SSLVERSION_TLSv1_3, + + CURL_SSLVERSION_LAST /* never use, keep last */ +}; + +enum { + CURL_SSLVERSION_MAX_NONE = 0, + CURL_SSLVERSION_MAX_DEFAULT = (CURL_SSLVERSION_TLSv1 << 16), + CURL_SSLVERSION_MAX_TLSv1_0 = (CURL_SSLVERSION_TLSv1_0 << 16), + CURL_SSLVERSION_MAX_TLSv1_1 = (CURL_SSLVERSION_TLSv1_1 << 16), + CURL_SSLVERSION_MAX_TLSv1_2 = (CURL_SSLVERSION_TLSv1_2 << 16), + CURL_SSLVERSION_MAX_TLSv1_3 = (CURL_SSLVERSION_TLSv1_3 << 16), + + /* never use, keep last */ + CURL_SSLVERSION_MAX_LAST = (CURL_SSLVERSION_LAST << 16) +}; + +enum CURL_TLSAUTH { + CURL_TLSAUTH_NONE, + CURL_TLSAUTH_SRP, + CURL_TLSAUTH_LAST /* never use, keep last */ +}; + +/* symbols to use with CURLOPT_POSTREDIR. + CURL_REDIR_POST_301, CURL_REDIR_POST_302 and CURL_REDIR_POST_303 + can be bitwise ORed so that CURL_REDIR_POST_301 | CURL_REDIR_POST_302 + | CURL_REDIR_POST_303 == CURL_REDIR_POST_ALL */ + +#define CURL_REDIR_GET_ALL 0 +#define CURL_REDIR_POST_301 1 +#define CURL_REDIR_POST_302 2 +#define CURL_REDIR_POST_303 4 +#define CURL_REDIR_POST_ALL \ + (CURL_REDIR_POST_301|CURL_REDIR_POST_302|CURL_REDIR_POST_303) + +typedef enum { + CURL_TIMECOND_NONE, + + CURL_TIMECOND_IFMODSINCE, + CURL_TIMECOND_IFUNMODSINCE, + CURL_TIMECOND_LASTMOD, + + CURL_TIMECOND_LAST +} curl_TimeCond; + +/* Special size_t value signaling a zero-terminated string. */ +#define CURL_ZERO_TERMINATED ((size_t) -1) + +/* curl_strequal() and curl_strnequal() are subject for removal in a future + release */ +CURL_EXTERN int curl_strequal(const char *s1, const char *s2); +CURL_EXTERN int curl_strnequal(const char *s1, const char *s2, size_t n); + +/* Mime/form handling support. */ +typedef struct curl_mime_s curl_mime; /* Mime context. */ +typedef struct curl_mimepart_s curl_mimepart; /* Mime part context. */ + +/* + * NAME curl_mime_init() + * + * DESCRIPTION + * + * Create a mime context and return its handle. The easy parameter is the + * target handle. + */ +CURL_EXTERN curl_mime *curl_mime_init(CURL *easy); + +/* + * NAME curl_mime_free() + * + * DESCRIPTION + * + * release a mime handle and its substructures. + */ +CURL_EXTERN void curl_mime_free(curl_mime *mime); + +/* + * NAME curl_mime_addpart() + * + * DESCRIPTION + * + * Append a new empty part to the given mime context and return a handle to + * the created part. + */ +CURL_EXTERN curl_mimepart *curl_mime_addpart(curl_mime *mime); + +/* + * NAME curl_mime_name() + * + * DESCRIPTION + * + * Set mime/form part name. + */ +CURL_EXTERN CURLcode curl_mime_name(curl_mimepart *part, const char *name); + +/* + * NAME curl_mime_filename() + * + * DESCRIPTION + * + * Set mime part remote file name. + */ +CURL_EXTERN CURLcode curl_mime_filename(curl_mimepart *part, + const char *filename); + +/* + * NAME curl_mime_type() + * + * DESCRIPTION + * + * Set mime part type. + */ +CURL_EXTERN CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype); + +/* + * NAME curl_mime_encoder() + * + * DESCRIPTION + * + * Set mime data transfer encoder. + */ +CURL_EXTERN CURLcode curl_mime_encoder(curl_mimepart *part, + const char *encoding); + +/* + * NAME curl_mime_data() + * + * DESCRIPTION + * + * Set mime part data source from memory data, + */ +CURL_EXTERN CURLcode curl_mime_data(curl_mimepart *part, + const char *data, size_t datasize); + +/* + * NAME curl_mime_filedata() + * + * DESCRIPTION + * + * Set mime part data source from named file. + */ +CURL_EXTERN CURLcode curl_mime_filedata(curl_mimepart *part, + const char *filename); + +/* + * NAME curl_mime_data_cb() + * + * DESCRIPTION + * + * Set mime part data source from callback function. + */ +CURL_EXTERN CURLcode curl_mime_data_cb(curl_mimepart *part, + curl_off_t datasize, + curl_read_callback readfunc, + curl_seek_callback seekfunc, + curl_free_callback freefunc, + void *arg); + +/* + * NAME curl_mime_subparts() + * + * DESCRIPTION + * + * Set mime part data source from subparts. + */ +CURL_EXTERN CURLcode curl_mime_subparts(curl_mimepart *part, + curl_mime *subparts); +/* + * NAME curl_mime_headers() + * + * DESCRIPTION + * + * Set mime part headers. + */ +CURL_EXTERN CURLcode curl_mime_headers(curl_mimepart *part, + struct curl_slist *headers, + int take_ownership); + +/* Old form API. */ +/* name is uppercase CURLFORM_ */ +#ifdef CFINIT +#undef CFINIT +#endif + +#ifdef CURL_ISOCPP +#define CFINIT(name) CURLFORM_ ## name +#else +/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ +#define CFINIT(name) CURLFORM_/**/name +#endif + +typedef enum { + CFINIT(NOTHING), /********* the first one is unused ************/ + + /* */ + CFINIT(COPYNAME), + CFINIT(PTRNAME), + CFINIT(NAMELENGTH), + CFINIT(COPYCONTENTS), + CFINIT(PTRCONTENTS), + CFINIT(CONTENTSLENGTH), + CFINIT(FILECONTENT), + CFINIT(ARRAY), + CFINIT(OBSOLETE), + CFINIT(FILE), + + CFINIT(BUFFER), + CFINIT(BUFFERPTR), + CFINIT(BUFFERLENGTH), + + CFINIT(CONTENTTYPE), + CFINIT(CONTENTHEADER), + CFINIT(FILENAME), + CFINIT(END), + CFINIT(OBSOLETE2), + + CFINIT(STREAM), + CFINIT(CONTENTLEN), /* added in 7.46.0, provide a curl_off_t length */ + + CURLFORM_LASTENTRY /* the last unused */ +} CURLformoption; + +#undef CFINIT /* done */ + +/* structure to be used as parameter for CURLFORM_ARRAY */ +struct curl_forms { + CURLformoption option; + const char *value; +}; + +/* use this for multipart formpost building */ +/* Returns code for curl_formadd() + * + * Returns: + * CURL_FORMADD_OK on success + * CURL_FORMADD_MEMORY if the FormInfo allocation fails + * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form + * CURL_FORMADD_NULL if a null pointer was given for a char + * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed + * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used + * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error) + * CURL_FORMADD_MEMORY if a curl_httppost struct cannot be allocated + * CURL_FORMADD_MEMORY if some allocation for string copying failed. + * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array + * + ***************************************************************************/ +typedef enum { + CURL_FORMADD_OK, /* first, no error */ + + CURL_FORMADD_MEMORY, + CURL_FORMADD_OPTION_TWICE, + CURL_FORMADD_NULL, + CURL_FORMADD_UNKNOWN_OPTION, + CURL_FORMADD_INCOMPLETE, + CURL_FORMADD_ILLEGAL_ARRAY, + CURL_FORMADD_DISABLED, /* libcurl was built with this disabled */ + + CURL_FORMADD_LAST /* last */ +} CURLFORMcode; + +/* + * NAME curl_formadd() + * + * DESCRIPTION + * + * Pretty advanced function for building multi-part formposts. Each invoke + * adds one part that together construct a full post. Then use + * CURLOPT_HTTPPOST to send it off to libcurl. + */ +CURL_EXTERN CURLFORMcode curl_formadd(struct curl_httppost **httppost, + struct curl_httppost **last_post, + ...); + +/* + * callback function for curl_formget() + * The void *arg pointer will be the one passed as second argument to + * curl_formget(). + * The character buffer passed to it must not be freed. + * Should return the buffer length passed to it as the argument "len" on + * success. + */ +typedef size_t (*curl_formget_callback)(void *arg, const char *buf, + size_t len); + +/* + * NAME curl_formget() + * + * DESCRIPTION + * + * Serialize a curl_httppost struct built with curl_formadd(). + * Accepts a void pointer as second argument which will be passed to + * the curl_formget_callback function. + * Returns 0 on success. + */ +CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg, + curl_formget_callback append); +/* + * NAME curl_formfree() + * + * DESCRIPTION + * + * Free a multipart formpost previously built with curl_formadd(). + */ +CURL_EXTERN void curl_formfree(struct curl_httppost *form); + +/* + * NAME curl_getenv() + * + * DESCRIPTION + * + * Returns a malloc()'ed string that MUST be curl_free()ed after usage is + * complete. DEPRECATED - see lib/README.curlx + */ +CURL_EXTERN char *curl_getenv(const char *variable); + +/* + * NAME curl_version() + * + * DESCRIPTION + * + * Returns a static ascii string of the libcurl version. + */ +CURL_EXTERN char *curl_version(void); + +/* + * NAME curl_easy_escape() + * + * DESCRIPTION + * + * Escapes URL strings (converts all letters consider illegal in URLs to their + * %XX versions). This function returns a new allocated string or NULL if an + * error occurred. + */ +CURL_EXTERN char *curl_easy_escape(CURL *handle, + const char *string, + int length); + +/* the previous version: */ +CURL_EXTERN char *curl_escape(const char *string, + int length); + + +/* + * NAME curl_easy_unescape() + * + * DESCRIPTION + * + * Unescapes URL encoding in strings (converts all %XX codes to their 8bit + * versions). This function returns a new allocated string or NULL if an error + * occurred. + * Conversion Note: On non-ASCII platforms the ASCII %XX codes are + * converted into the host encoding. + */ +CURL_EXTERN char *curl_easy_unescape(CURL *handle, + const char *string, + int length, + int *outlength); + +/* the previous version */ +CURL_EXTERN char *curl_unescape(const char *string, + int length); + +/* + * NAME curl_free() + * + * DESCRIPTION + * + * Provided for de-allocation in the same translation unit that did the + * allocation. Added in libcurl 7.10 + */ +CURL_EXTERN void curl_free(void *p); + +/* + * NAME curl_global_init() + * + * DESCRIPTION + * + * curl_global_init() should be invoked exactly once for each application that + * uses libcurl and before any call of other libcurl functions. + * + * This function is not thread-safe! + */ +CURL_EXTERN CURLcode curl_global_init(long flags); + +/* + * NAME curl_global_init_mem() + * + * DESCRIPTION + * + * curl_global_init() or curl_global_init_mem() should be invoked exactly once + * for each application that uses libcurl. This function can be used to + * initialize libcurl and set user defined memory management callback + * functions. Users can implement memory management routines to check for + * memory leaks, check for mis-use of the curl library etc. User registered + * callback routines with be invoked by this library instead of the system + * memory management routines like malloc, free etc. + */ +CURL_EXTERN CURLcode curl_global_init_mem(long flags, + curl_malloc_callback m, + curl_free_callback f, + curl_realloc_callback r, + curl_strdup_callback s, + curl_calloc_callback c); + +/* + * NAME curl_global_cleanup() + * + * DESCRIPTION + * + * curl_global_cleanup() should be invoked exactly once for each application + * that uses libcurl + */ +CURL_EXTERN void curl_global_cleanup(void); + +/* linked-list structure for the CURLOPT_QUOTE option (and other) */ +struct curl_slist { + char *data; + struct curl_slist *next; +}; + +/* + * NAME curl_global_sslset() + * + * DESCRIPTION + * + * When built with multiple SSL backends, curl_global_sslset() allows to + * choose one. This function can only be called once, and it must be called + * *before* curl_global_init(). + * + * The backend can be identified by the id (e.g. CURLSSLBACKEND_OPENSSL). The + * backend can also be specified via the name parameter (passing -1 as id). + * If both id and name are specified, the name will be ignored. If neither id + * nor name are specified, the function will fail with + * CURLSSLSET_UNKNOWN_BACKEND and set the "avail" pointer to the + * NULL-terminated list of available backends. + * + * Upon success, the function returns CURLSSLSET_OK. + * + * If the specified SSL backend is not available, the function returns + * CURLSSLSET_UNKNOWN_BACKEND and sets the "avail" pointer to a NULL-terminated + * list of available SSL backends. + * + * The SSL backend can be set only once. If it has already been set, a + * subsequent attempt to change it will result in a CURLSSLSET_TOO_LATE. + */ + +typedef struct { + curl_sslbackend id; + const char *name; +} curl_ssl_backend; + +typedef enum { + CURLSSLSET_OK = 0, + CURLSSLSET_UNKNOWN_BACKEND, + CURLSSLSET_TOO_LATE, + CURLSSLSET_NO_BACKENDS /* libcurl was built without any SSL support */ +} CURLsslset; + +CURL_EXTERN CURLsslset curl_global_sslset(curl_sslbackend id, const char *name, + const curl_ssl_backend ***avail); + +/* + * NAME curl_slist_append() + * + * DESCRIPTION + * + * Appends a string to a linked list. If no list exists, it will be created + * first. Returns the new list, after appending. + */ +CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *, + const char *); + +/* + * NAME curl_slist_free_all() + * + * DESCRIPTION + * + * free a previously built curl_slist. + */ +CURL_EXTERN void curl_slist_free_all(struct curl_slist *); + +/* + * NAME curl_getdate() + * + * DESCRIPTION + * + * Returns the time, in seconds since 1 Jan 1970 of the time string given in + * the first argument. The time argument in the second parameter is unused + * and should be set to NULL. + */ +CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused); + +/* info about the certificate chain, only for OpenSSL builds. Asked + for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */ +struct curl_certinfo { + int num_of_certs; /* number of certificates with information */ + struct curl_slist **certinfo; /* for each index in this array, there's a + linked list with textual information in the + format "name: value" */ +}; + +/* Information about the SSL library used and the respective internal SSL + handle, which can be used to obtain further information regarding the + connection. Asked for with CURLINFO_TLS_SSL_PTR or CURLINFO_TLS_SESSION. */ +struct curl_tlssessioninfo { + curl_sslbackend backend; + void *internals; +}; + +#define CURLINFO_STRING 0x100000 +#define CURLINFO_LONG 0x200000 +#define CURLINFO_DOUBLE 0x300000 +#define CURLINFO_SLIST 0x400000 +#define CURLINFO_PTR 0x400000 /* same as SLIST */ +#define CURLINFO_SOCKET 0x500000 +#define CURLINFO_OFF_T 0x600000 +#define CURLINFO_MASK 0x0fffff +#define CURLINFO_TYPEMASK 0xf00000 + +typedef enum { + CURLINFO_NONE, /* first, never use this */ + CURLINFO_EFFECTIVE_URL = CURLINFO_STRING + 1, + CURLINFO_RESPONSE_CODE = CURLINFO_LONG + 2, + CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE + 3, + CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE + 4, + CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE + 5, + CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6, + CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE + 7, + CURLINFO_SIZE_UPLOAD_T = CURLINFO_OFF_T + 7, + CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE + 8, + CURLINFO_SIZE_DOWNLOAD_T = CURLINFO_OFF_T + 8, + CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE + 9, + CURLINFO_SPEED_DOWNLOAD_T = CURLINFO_OFF_T + 9, + CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE + 10, + CURLINFO_SPEED_UPLOAD_T = CURLINFO_OFF_T + 10, + CURLINFO_HEADER_SIZE = CURLINFO_LONG + 11, + CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12, + CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13, + CURLINFO_FILETIME = CURLINFO_LONG + 14, + CURLINFO_FILETIME_T = CURLINFO_OFF_T + 14, + CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15, + CURLINFO_CONTENT_LENGTH_DOWNLOAD_T = CURLINFO_OFF_T + 15, + CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16, + CURLINFO_CONTENT_LENGTH_UPLOAD_T = CURLINFO_OFF_T + 16, + CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17, + CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18, + CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE + 19, + CURLINFO_REDIRECT_COUNT = CURLINFO_LONG + 20, + CURLINFO_PRIVATE = CURLINFO_STRING + 21, + CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG + 22, + CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG + 23, + CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG + 24, + CURLINFO_OS_ERRNO = CURLINFO_LONG + 25, + CURLINFO_NUM_CONNECTS = CURLINFO_LONG + 26, + CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27, + CURLINFO_COOKIELIST = CURLINFO_SLIST + 28, + CURLINFO_LASTSOCKET = CURLINFO_LONG + 29, + CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30, + CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31, + CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32, + CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33, + CURLINFO_CERTINFO = CURLINFO_PTR + 34, + CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35, + CURLINFO_RTSP_SESSION_ID = CURLINFO_STRING + 36, + CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37, + CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG + 38, + CURLINFO_RTSP_CSEQ_RECV = CURLINFO_LONG + 39, + CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40, + CURLINFO_LOCAL_IP = CURLINFO_STRING + 41, + CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42, + CURLINFO_TLS_SESSION = CURLINFO_PTR + 43, + CURLINFO_ACTIVESOCKET = CURLINFO_SOCKET + 44, + CURLINFO_TLS_SSL_PTR = CURLINFO_PTR + 45, + CURLINFO_HTTP_VERSION = CURLINFO_LONG + 46, + CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47, + CURLINFO_PROTOCOL = CURLINFO_LONG + 48, + CURLINFO_SCHEME = CURLINFO_STRING + 49, + /* Fill in new entries below here! */ + + /* Preferably these would be defined conditionally based on the + sizeof curl_off_t being 64-bits */ + CURLINFO_TOTAL_TIME_T = CURLINFO_OFF_T + 50, + CURLINFO_NAMELOOKUP_TIME_T = CURLINFO_OFF_T + 51, + CURLINFO_CONNECT_TIME_T = CURLINFO_OFF_T + 52, + CURLINFO_PRETRANSFER_TIME_T = CURLINFO_OFF_T + 53, + CURLINFO_STARTTRANSFER_TIME_T = CURLINFO_OFF_T + 54, + CURLINFO_REDIRECT_TIME_T = CURLINFO_OFF_T + 55, + CURLINFO_APPCONNECT_TIME_T = CURLINFO_OFF_T + 56, + + CURLINFO_LASTONE = 56 +} CURLINFO; + +/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as + CURLINFO_HTTP_CODE */ +#define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE + +typedef enum { + CURLCLOSEPOLICY_NONE, /* first, never use this */ + + CURLCLOSEPOLICY_OLDEST, + CURLCLOSEPOLICY_LEAST_RECENTLY_USED, + CURLCLOSEPOLICY_LEAST_TRAFFIC, + CURLCLOSEPOLICY_SLOWEST, + CURLCLOSEPOLICY_CALLBACK, + + CURLCLOSEPOLICY_LAST /* last, never use this */ +} curl_closepolicy; + +#define CURL_GLOBAL_SSL (1<<0) /* no purpose since since 7.57.0 */ +#define CURL_GLOBAL_WIN32 (1<<1) +#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32) +#define CURL_GLOBAL_NOTHING 0 +#define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL +#define CURL_GLOBAL_ACK_EINTR (1<<2) + + +/***************************************************************************** + * Setup defines, protos etc for the sharing stuff. + */ + +/* Different data locks for a single share */ +typedef enum { + CURL_LOCK_DATA_NONE = 0, + /* CURL_LOCK_DATA_SHARE is used internally to say that + * the locking is just made to change the internal state of the share + * itself. + */ + CURL_LOCK_DATA_SHARE, + CURL_LOCK_DATA_COOKIE, + CURL_LOCK_DATA_DNS, + CURL_LOCK_DATA_SSL_SESSION, + CURL_LOCK_DATA_CONNECT, + CURL_LOCK_DATA_PSL, + CURL_LOCK_DATA_LAST +} curl_lock_data; + +/* Different lock access types */ +typedef enum { + CURL_LOCK_ACCESS_NONE = 0, /* unspecified action */ + CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */ + CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */ + CURL_LOCK_ACCESS_LAST /* never use */ +} curl_lock_access; + +typedef void (*curl_lock_function)(CURL *handle, + curl_lock_data data, + curl_lock_access locktype, + void *userptr); +typedef void (*curl_unlock_function)(CURL *handle, + curl_lock_data data, + void *userptr); + + +typedef enum { + CURLSHE_OK, /* all is fine */ + CURLSHE_BAD_OPTION, /* 1 */ + CURLSHE_IN_USE, /* 2 */ + CURLSHE_INVALID, /* 3 */ + CURLSHE_NOMEM, /* 4 out of memory */ + CURLSHE_NOT_BUILT_IN, /* 5 feature not present in lib */ + CURLSHE_LAST /* never use */ +} CURLSHcode; + +typedef enum { + CURLSHOPT_NONE, /* don't use */ + CURLSHOPT_SHARE, /* specify a data type to share */ + CURLSHOPT_UNSHARE, /* specify which data type to stop sharing */ + CURLSHOPT_LOCKFUNC, /* pass in a 'curl_lock_function' pointer */ + CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */ + CURLSHOPT_USERDATA, /* pass in a user data pointer used in the lock/unlock + callback functions */ + CURLSHOPT_LAST /* never use */ +} CURLSHoption; + +CURL_EXTERN CURLSH *curl_share_init(void); +CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...); +CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *); + +/**************************************************************************** + * Structures for querying information about the curl library at runtime. + */ + +typedef enum { + CURLVERSION_FIRST, + CURLVERSION_SECOND, + CURLVERSION_THIRD, + CURLVERSION_FOURTH, + CURLVERSION_FIFTH, + CURLVERSION_LAST /* never actually use this */ +} CURLversion; + +/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by + basically all programs ever that want to get version information. It is + meant to be a built-in version number for what kind of struct the caller + expects. If the struct ever changes, we redefine the NOW to another enum + from above. */ +#define CURLVERSION_NOW CURLVERSION_FIFTH + +typedef struct { + CURLversion age; /* age of the returned struct */ + const char *version; /* LIBCURL_VERSION */ + unsigned int version_num; /* LIBCURL_VERSION_NUM */ + const char *host; /* OS/host/cpu/machine when configured */ + int features; /* bitmask, see defines below */ + const char *ssl_version; /* human readable string */ + long ssl_version_num; /* not used anymore, always 0 */ + const char *libz_version; /* human readable string */ + /* protocols is terminated by an entry with a NULL protoname */ + const char * const *protocols; + + /* The fields below this were added in CURLVERSION_SECOND */ + const char *ares; + int ares_num; + + /* This field was added in CURLVERSION_THIRD */ + const char *libidn; + + /* These field were added in CURLVERSION_FOURTH */ + + /* Same as '_libiconv_version' if built with HAVE_ICONV */ + int iconv_ver_num; + + const char *libssh_version; /* human readable string */ + + /* These fields were added in CURLVERSION_FIFTH */ + + unsigned int brotli_ver_num; /* Numeric Brotli version + (MAJOR << 24) | (MINOR << 12) | PATCH */ + const char *brotli_version; /* human readable string. */ + +} curl_version_info_data; + +#define CURL_VERSION_IPV6 (1<<0) /* IPv6-enabled */ +#define CURL_VERSION_KERBEROS4 (1<<1) /* Kerberos V4 auth is supported + (deprecated) */ +#define CURL_VERSION_SSL (1<<2) /* SSL options are present */ +#define CURL_VERSION_LIBZ (1<<3) /* libz features are present */ +#define CURL_VERSION_NTLM (1<<4) /* NTLM auth is supported */ +#define CURL_VERSION_GSSNEGOTIATE (1<<5) /* Negotiate auth is supported + (deprecated) */ +#define CURL_VERSION_DEBUG (1<<6) /* Built with debug capabilities */ +#define CURL_VERSION_ASYNCHDNS (1<<7) /* Asynchronous DNS resolves */ +#define CURL_VERSION_SPNEGO (1<<8) /* SPNEGO auth is supported */ +#define CURL_VERSION_LARGEFILE (1<<9) /* Supports files larger than 2GB */ +#define CURL_VERSION_IDN (1<<10) /* Internationized Domain Names are + supported */ +#define CURL_VERSION_SSPI (1<<11) /* Built against Windows SSPI */ +#define CURL_VERSION_CONV (1<<12) /* Character conversions supported */ +#define CURL_VERSION_CURLDEBUG (1<<13) /* Debug memory tracking supported */ +#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */ +#define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegation to winbind helper + is supported */ +#define CURL_VERSION_HTTP2 (1<<16) /* HTTP2 support built-in */ +#define CURL_VERSION_GSSAPI (1<<17) /* Built against a GSS-API library */ +#define CURL_VERSION_KERBEROS5 (1<<18) /* Kerberos V5 auth is supported */ +#define CURL_VERSION_UNIX_SOCKETS (1<<19) /* Unix domain sockets support */ +#define CURL_VERSION_PSL (1<<20) /* Mozilla's Public Suffix List, used + for cookie domain verification */ +#define CURL_VERSION_HTTPS_PROXY (1<<21) /* HTTPS-proxy support built-in */ +#define CURL_VERSION_MULTI_SSL (1<<22) /* Multiple SSL backends available */ +#define CURL_VERSION_BROTLI (1<<23) /* Brotli features are present. */ +#define CURL_VERSION_ALTSVC (1<<24) /* Alt-Svc handling built-in */ + + /* + * NAME curl_version_info() + * + * DESCRIPTION + * + * This function returns a pointer to a static copy of the version info + * struct. See above. + */ +CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion); + +/* + * NAME curl_easy_strerror() + * + * DESCRIPTION + * + * The curl_easy_strerror function may be used to turn a CURLcode value + * into the equivalent human readable error string. This is useful + * for printing meaningful error messages. + */ +CURL_EXTERN const char *curl_easy_strerror(CURLcode); + +/* + * NAME curl_share_strerror() + * + * DESCRIPTION + * + * The curl_share_strerror function may be used to turn a CURLSHcode value + * into the equivalent human readable error string. This is useful + * for printing meaningful error messages. + */ +CURL_EXTERN const char *curl_share_strerror(CURLSHcode); + +/* + * NAME curl_easy_pause() + * + * DESCRIPTION + * + * The curl_easy_pause function pauses or unpauses transfers. Select the new + * state by setting the bitmask, use the convenience defines below. + * + */ +CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask); + +#define CURLPAUSE_RECV (1<<0) +#define CURLPAUSE_RECV_CONT (0) + +#define CURLPAUSE_SEND (1<<2) +#define CURLPAUSE_SEND_CONT (0) + +#define CURLPAUSE_ALL (CURLPAUSE_RECV|CURLPAUSE_SEND) +#define CURLPAUSE_CONT (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT) + +#ifdef __cplusplus +} +#endif + +/* unfortunately, the easy.h and multi.h include files need options and info + stuff before they can be included! */ +#include "easy.h" /* nothing in curl is fun without the easy stuff */ +#include "multi.h" +#include "urlapi.h" + +/* the typechecker doesn't work in C++ (yet) */ +#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \ + ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && \ + !defined(__cplusplus) && !defined(CURL_DISABLE_TYPECHECK) +#include "typecheck-gcc.h" +#else +#if defined(__STDC__) && (__STDC__ >= 1) +#if 0 /* Triggers clang -Wdisabled-macro-expansion, skip for CMake. */ +/* This preprocessor magic that replaces a call with the exact same call is + only done to make sure application authors pass exactly three arguments + to these functions. */ +#define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param) +#define curl_easy_getinfo(handle,info,arg) curl_easy_getinfo(handle,info,arg) +#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) +#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param) +#endif +#endif /* __STDC__ >= 1 */ +#endif /* gcc >= 4.3 && !__cplusplus */ + +#endif /* __CURL_CURL_H */ diff --git a/dependencies/cmcurl/include/curl/curlver.h b/dependencies/cmcurl/include/curl/curlver.h new file mode 100644 index 0000000..04efb93 --- /dev/null +++ b/dependencies/cmcurl/include/curl/curlver.h @@ -0,0 +1,77 @@ +#ifndef __CURL_CURLVER_H +#define __CURL_CURLVER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* This header file contains nothing but libcurl version info, generated by + a script at release-time. This was made its own header file in 7.11.2 */ + +/* This is the global package copyright */ +#define LIBCURL_COPYRIGHT "1996 - 2019 Daniel Stenberg, ." + +/* This is the version number of the libcurl package from which this header + file origins: */ +#define LIBCURL_VERSION "7.65.0" + +/* The numeric version number is also available "in parts" by using these + defines: */ +#define LIBCURL_VERSION_MAJOR 7 +#define LIBCURL_VERSION_MINOR 65 +#define LIBCURL_VERSION_PATCH 0 + +/* This is the numeric version of the libcurl version number, meant for easier + parsing and comparions by programs. The LIBCURL_VERSION_NUM define will + always follow this syntax: + + 0xXXYYZZ + + Where XX, YY and ZZ are the main version, release and patch numbers in + hexadecimal (using 8 bits each). All three numbers are always represented + using two digits. 1.2 would appear as "0x010200" while version 9.11.7 + appears as "0x090b07". + + This 6-digit (24 bits) hexadecimal number does not show pre-release number, + and it is always a greater number in a more recent release. It makes + comparisons with greater than and less than work. + + Note: This define is the full hex number and _does not_ use the + CURL_VERSION_BITS() macro since curl's own configure script greps for it + and needs it to contain the full number. +*/ +#define LIBCURL_VERSION_NUM 0x074100 + +/* + * This is the date and time when the full source package was created. The + * timestamp is not stored in git, as the timestamp is properly set in the + * tarballs by the maketgz script. + * + * The format of the date follows this template: + * + * "2007-11-23" + */ +#define LIBCURL_TIMESTAMP "[unreleased]" + +#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|(z)) +#define CURL_AT_LEAST_VERSION(x,y,z) \ + (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z)) + +#endif /* __CURL_CURLVER_H */ diff --git a/dependencies/cmcurl/include/curl/easy.h b/dependencies/cmcurl/include/curl/easy.h new file mode 100644 index 0000000..f42a8a9 --- /dev/null +++ b/dependencies/cmcurl/include/curl/easy.h @@ -0,0 +1,112 @@ +#ifndef __CURL_EASY_H +#define __CURL_EASY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +CURL_EXTERN CURL *curl_easy_init(void); +CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...); +CURL_EXTERN CURLcode curl_easy_perform(CURL *curl); +CURL_EXTERN void curl_easy_cleanup(CURL *curl); + +/* + * NAME curl_easy_getinfo() + * + * DESCRIPTION + * + * Request internal information from the curl session with this function. The + * third argument MUST be a pointer to a long, a pointer to a char * or a + * pointer to a double (as the documentation describes elsewhere). The data + * pointed to will be filled in accordingly and can be relied upon only if the + * function returns CURLE_OK. This function is intended to get used *AFTER* a + * performed transfer, all results from this function are undefined until the + * transfer is completed. + */ +CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...); + + +/* + * NAME curl_easy_duphandle() + * + * DESCRIPTION + * + * Creates a new curl session handle with the same options set for the handle + * passed in. Duplicating a handle could only be a matter of cloning data and + * options, internal state info and things like persistent connections cannot + * be transferred. It is useful in multithreaded applications when you can run + * curl_easy_duphandle() for each new thread to avoid a series of identical + * curl_easy_setopt() invokes in every thread. + */ +CURL_EXTERN CURL *curl_easy_duphandle(CURL *curl); + +/* + * NAME curl_easy_reset() + * + * DESCRIPTION + * + * Re-initializes a CURL handle to the default values. This puts back the + * handle to the same state as it was in when it was just created. + * + * It does keep: live connections, the Session ID cache, the DNS cache and the + * cookies. + */ +CURL_EXTERN void curl_easy_reset(CURL *curl); + +/* + * NAME curl_easy_recv() + * + * DESCRIPTION + * + * Receives data from the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, + size_t *n); + +/* + * NAME curl_easy_send() + * + * DESCRIPTION + * + * Sends data over the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer, + size_t buflen, size_t *n); + + +/* + * NAME curl_easy_upkeep() + * + * DESCRIPTION + * + * Performs connection upkeep for the given session handle. + */ +CURL_EXTERN CURLcode curl_easy_upkeep(CURL *curl); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dependencies/cmcurl/include/curl/mprintf.h b/dependencies/cmcurl/include/curl/mprintf.h new file mode 100644 index 0000000..e20f546 --- /dev/null +++ b/dependencies/cmcurl/include/curl/mprintf.h @@ -0,0 +1,50 @@ +#ifndef __CURL_MPRINTF_H +#define __CURL_MPRINTF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include +#include /* needed for FILE */ +#include "curl.h" /* for CURL_EXTERN */ + +#ifdef __cplusplus +extern "C" { +#endif + +CURL_EXTERN int curl_mprintf(const char *format, ...); +CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...); +CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...); +CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength, + const char *format, ...); +CURL_EXTERN int curl_mvprintf(const char *format, va_list args); +CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args); +CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args); +CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength, + const char *format, va_list args); +CURL_EXTERN char *curl_maprintf(const char *format, ...); +CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args); + +#ifdef __cplusplus +} +#endif + +#endif /* __CURL_MPRINTF_H */ diff --git a/dependencies/cmcurl/include/curl/multi.h b/dependencies/cmcurl/include/curl/multi.h new file mode 100644 index 0000000..b19dbaf --- /dev/null +++ b/dependencies/cmcurl/include/curl/multi.h @@ -0,0 +1,441 @@ +#ifndef __CURL_MULTI_H +#define __CURL_MULTI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +/* + This is an "external" header file. Don't give away any internals here! + + GOALS + + o Enable a "pull" interface. The application that uses libcurl decides where + and when to ask libcurl to get/send data. + + o Enable multiple simultaneous transfers in the same thread without making it + complicated for the application. + + o Enable the application to select() on its own file descriptors and curl's + file descriptors simultaneous easily. + +*/ + +/* + * This header file should not really need to include "curl.h" since curl.h + * itself includes this file and we expect user applications to do #include + * without the need for especially including multi.h. + * + * For some reason we added this include here at one point, and rather than to + * break existing (wrongly written) libcurl applications, we leave it as-is + * but with this warning attached. + */ +#include "curl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER) +typedef struct Curl_multi CURLM; +#else +typedef void CURLM; +#endif + +typedef enum { + CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or + curl_multi_socket*() soon */ + CURLM_OK, + CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */ + CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */ + CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */ + CURLM_INTERNAL_ERROR, /* this is a libcurl bug */ + CURLM_BAD_SOCKET, /* the passed in socket argument did not match */ + CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */ + CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was + attempted to get added - again */ + CURLM_RECURSIVE_API_CALL, /* an api function was called from inside a + callback */ + CURLM_LAST +} CURLMcode; + +/* just to make code nicer when using curl_multi_socket() you can now check + for CURLM_CALL_MULTI_SOCKET too in the same style it works for + curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */ +#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM + +/* bitmask bits for CURLMOPT_PIPELINING */ +#define CURLPIPE_NOTHING 0L +#define CURLPIPE_HTTP1 1L +#define CURLPIPE_MULTIPLEX 2L + +typedef enum { + CURLMSG_NONE, /* first, not used */ + CURLMSG_DONE, /* This easy handle has completed. 'result' contains + the CURLcode of the transfer */ + CURLMSG_LAST /* last, not used */ +} CURLMSG; + +struct CURLMsg { + CURLMSG msg; /* what this message means */ + CURL *easy_handle; /* the handle it concerns */ + union { + void *whatever; /* message-specific data */ + CURLcode result; /* return code for transfer */ + } data; +}; +typedef struct CURLMsg CURLMsg; + +/* Based on poll(2) structure and values. + * We don't use pollfd and POLL* constants explicitly + * to cover platforms without poll(). */ +#define CURL_WAIT_POLLIN 0x0001 +#define CURL_WAIT_POLLPRI 0x0002 +#define CURL_WAIT_POLLOUT 0x0004 + +struct curl_waitfd { + curl_socket_t fd; + short events; + short revents; /* not supported yet */ +}; + +/* + * Name: curl_multi_init() + * + * Desc: inititalize multi-style curl usage + * + * Returns: a new CURLM handle to use in all 'curl_multi' functions. + */ +CURL_EXTERN CURLM *curl_multi_init(void); + +/* + * Name: curl_multi_add_handle() + * + * Desc: add a standard curl handle to the multi stack + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle, + CURL *curl_handle); + + /* + * Name: curl_multi_remove_handle() + * + * Desc: removes a curl handle from the multi stack again + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle, + CURL *curl_handle); + + /* + * Name: curl_multi_fdset() + * + * Desc: Ask curl for its fd_set sets. The app can use these to select() or + * poll() on. We want curl_multi_perform() called as soon as one of + * them are ready. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle, + fd_set *read_fd_set, + fd_set *write_fd_set, + fd_set *exc_fd_set, + int *max_fd); + +/* + * Name: curl_multi_wait() + * + * Desc: Poll on all fds within a CURLM set as well as any + * additional fds passed to the function. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret); + + /* + * Name: curl_multi_perform() + * + * Desc: When the app thinks there's data available for curl it calls this + * function to read/write whatever there is right now. This returns + * as soon as the reads and writes are done. This function does not + * require that there actually is data available for reading or that + * data can be written, it can be called just in case. It returns + * the number of handles that still transfer data in the second + * argument's integer-pointer. + * + * Returns: CURLMcode type, general multi error code. *NOTE* that this only + * returns errors etc regarding the whole multi stack. There might + * still have occurred problems on individual transfers even when + * this returns OK. + */ +CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle, + int *running_handles); + + /* + * Name: curl_multi_cleanup() + * + * Desc: Cleans up and removes a whole multi stack. It does not free or + * touch any individual easy handles in any way. We need to define + * in what state those handles will be if this function is called + * in the middle of a transfer. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle); + +/* + * Name: curl_multi_info_read() + * + * Desc: Ask the multi handle if there's any messages/informationals from + * the individual transfers. Messages include informationals such as + * error code from the transfer or just the fact that a transfer is + * completed. More details on these should be written down as well. + * + * Repeated calls to this function will return a new struct each + * time, until a special "end of msgs" struct is returned as a signal + * that there is no more to get at this point. + * + * The data the returned pointer points to will not survive calling + * curl_multi_cleanup(). + * + * The 'CURLMsg' struct is meant to be very simple and only contain + * very basic information. If more involved information is wanted, + * we will provide the particular "transfer handle" in that struct + * and that should/could/would be used in subsequent + * curl_easy_getinfo() calls (or similar). The point being that we + * must never expose complex structs to applications, as then we'll + * undoubtably get backwards compatibility problems in the future. + * + * Returns: A pointer to a filled-in struct, or NULL if it failed or ran out + * of structs. It also writes the number of messages left in the + * queue (after this read) in the integer the second argument points + * to. + */ +CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle, + int *msgs_in_queue); + +/* + * Name: curl_multi_strerror() + * + * Desc: The curl_multi_strerror function may be used to turn a CURLMcode + * value into the equivalent human readable error string. This is + * useful for printing meaningful error messages. + * + * Returns: A pointer to a zero-terminated error message. + */ +CURL_EXTERN const char *curl_multi_strerror(CURLMcode); + +/* + * Name: curl_multi_socket() and + * curl_multi_socket_all() + * + * Desc: An alternative version of curl_multi_perform() that allows the + * application to pass in one of the file descriptors that have been + * detected to have "action" on them and let libcurl perform. + * See man page for details. + */ +#define CURL_POLL_NONE 0 +#define CURL_POLL_IN 1 +#define CURL_POLL_OUT 2 +#define CURL_POLL_INOUT 3 +#define CURL_POLL_REMOVE 4 + +#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD + +#define CURL_CSELECT_IN 0x01 +#define CURL_CSELECT_OUT 0x02 +#define CURL_CSELECT_ERR 0x04 + +typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */ + curl_socket_t s, /* socket */ + int what, /* see above */ + void *userp, /* private callback + pointer */ + void *socketp); /* private socket + pointer */ +/* + * Name: curl_multi_timer_callback + * + * Desc: Called by libcurl whenever the library detects a change in the + * maximum number of milliseconds the app is allowed to wait before + * curl_multi_socket() or curl_multi_perform() must be called + * (to allow libcurl's timed events to take place). + * + * Returns: The callback should return zero. + */ +typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */ + long timeout_ms, /* see above */ + void *userp); /* private callback + pointer */ + +CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s, + int *running_handles); + +CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle, + curl_socket_t s, + int ev_bitmask, + int *running_handles); + +CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle, + int *running_handles); + +#ifndef CURL_ALLOW_OLD_MULTI_SOCKET +/* This macro below was added in 7.16.3 to push users who recompile to use + the new curl_multi_socket_action() instead of the old curl_multi_socket() +*/ +#define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z) +#endif + +/* + * Name: curl_multi_timeout() + * + * Desc: Returns the maximum number of milliseconds the app is allowed to + * wait before curl_multi_socket() or curl_multi_perform() must be + * called (to allow libcurl's timed events to take place). + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle, + long *milliseconds); + +#undef CINIT /* re-using the same name as in curl.h */ + +#ifdef CURL_ISOCPP +#define CINIT(name,type,num) CURLMOPT_ ## name = CURLOPTTYPE_ ## type + num +#else +/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ +#define LONG CURLOPTTYPE_LONG +#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT +#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT +#define OFF_T CURLOPTTYPE_OFF_T +#define CINIT(name,type,number) CURLMOPT_/**/name = type + number +#endif + +typedef enum { + /* This is the socket callback function pointer */ + CINIT(SOCKETFUNCTION, FUNCTIONPOINT, 1), + + /* This is the argument passed to the socket callback */ + CINIT(SOCKETDATA, OBJECTPOINT, 2), + + /* set to 1 to enable pipelining for this multi handle */ + CINIT(PIPELINING, LONG, 3), + + /* This is the timer callback function pointer */ + CINIT(TIMERFUNCTION, FUNCTIONPOINT, 4), + + /* This is the argument passed to the timer callback */ + CINIT(TIMERDATA, OBJECTPOINT, 5), + + /* maximum number of entries in the connection cache */ + CINIT(MAXCONNECTS, LONG, 6), + + /* maximum number of (pipelining) connections to one host */ + CINIT(MAX_HOST_CONNECTIONS, LONG, 7), + + /* maximum number of requests in a pipeline */ + CINIT(MAX_PIPELINE_LENGTH, LONG, 8), + + /* a connection with a content-length longer than this + will not be considered for pipelining */ + CINIT(CONTENT_LENGTH_PENALTY_SIZE, OFF_T, 9), + + /* a connection with a chunk length longer than this + will not be considered for pipelining */ + CINIT(CHUNK_LENGTH_PENALTY_SIZE, OFF_T, 10), + + /* a list of site names(+port) that are blacklisted from + pipelining */ + CINIT(PIPELINING_SITE_BL, OBJECTPOINT, 11), + + /* a list of server types that are blacklisted from + pipelining */ + CINIT(PIPELINING_SERVER_BL, OBJECTPOINT, 12), + + /* maximum number of open connections in total */ + CINIT(MAX_TOTAL_CONNECTIONS, LONG, 13), + + /* This is the server push callback function pointer */ + CINIT(PUSHFUNCTION, FUNCTIONPOINT, 14), + + /* This is the argument passed to the server push callback */ + CINIT(PUSHDATA, OBJECTPOINT, 15), + + CURLMOPT_LASTENTRY /* the last unused */ +} CURLMoption; + + +/* + * Name: curl_multi_setopt() + * + * Desc: Sets options for the multi handle. + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle, + CURLMoption option, ...); + + +/* + * Name: curl_multi_assign() + * + * Desc: This function sets an association in the multi handle between the + * given socket and a private pointer of the application. This is + * (only) useful for curl_multi_socket uses. + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle, + curl_socket_t sockfd, void *sockp); + + +/* + * Name: curl_push_callback + * + * Desc: This callback gets called when a new stream is being pushed by the + * server. It approves or denies the new stream. + * + * Returns: CURL_PUSH_OK or CURL_PUSH_DENY. + */ +#define CURL_PUSH_OK 0 +#define CURL_PUSH_DENY 1 + +struct curl_pushheaders; /* forward declaration only */ + +CURL_EXTERN char *curl_pushheader_bynum(struct curl_pushheaders *h, + size_t num); +CURL_EXTERN char *curl_pushheader_byname(struct curl_pushheaders *h, + const char *name); + +typedef int (*curl_push_callback)(CURL *parent, + CURL *easy, + size_t num_headers, + struct curl_pushheaders *headers, + void *userp); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif diff --git a/dependencies/cmcurl/include/curl/stdcheaders.h b/dependencies/cmcurl/include/curl/stdcheaders.h new file mode 100644 index 0000000..027b6f4 --- /dev/null +++ b/dependencies/cmcurl/include/curl/stdcheaders.h @@ -0,0 +1,33 @@ +#ifndef __STDC_HEADERS_H +#define __STDC_HEADERS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +size_t fread(void *, size_t, size_t, FILE *); +size_t fwrite(const void *, size_t, size_t, FILE *); + +int strcasecmp(const char *, const char *); +int strncasecmp(const char *, const char *, size_t); + +#endif /* __STDC_HEADERS_H */ diff --git a/dependencies/cmcurl/include/curl/system.h b/dependencies/cmcurl/include/curl/system.h new file mode 100644 index 0000000..1e555ec --- /dev/null +++ b/dependencies/cmcurl/include/curl/system.h @@ -0,0 +1,493 @@ +#ifndef __CURL_SYSTEM_H +#define __CURL_SYSTEM_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Try to keep one section per platform, compiler and architecture, otherwise, + * if an existing section is reused for a different one and later on the + * original is adjusted, probably the piggybacking one can be adversely + * changed. + * + * In order to differentiate between platforms/compilers/architectures use + * only compiler built in predefined preprocessor symbols. + * + * curl_off_t + * ---------- + * + * For any given platform/compiler curl_off_t must be typedef'ed to a 64-bit + * wide signed integral data type. The width of this data type must remain + * constant and independent of any possible large file support settings. + * + * As an exception to the above, curl_off_t shall be typedef'ed to a 32-bit + * wide signed integral data type if there is no 64-bit type. + * + * As a general rule, curl_off_t shall not be mapped to off_t. This rule shall + * only be violated if off_t is the only 64-bit data type available and the + * size of off_t is independent of large file support settings. Keep your + * build on the safe side avoiding an off_t gating. If you have a 64-bit + * off_t then take for sure that another 64-bit data type exists, dig deeper + * and you will find it. + * + */ + +#if defined(__DJGPP__) || defined(__GO32__) +# if defined(__DJGPP__) && (__DJGPP__ > 1) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__SALFORDC__) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__BORLANDC__) +# if (__BORLANDC__ < 0x520) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__TURBOC__) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__WATCOMC__) +# if defined(__386__) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__POCC__) +# if (__POCC__ < 280) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# elif defined(_MSC_VER) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__LCC__) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__SYMBIAN32__) +# if defined(__EABI__) /* Treat all ARM compilers equally */ +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__CW32__) +# pragma longlong on +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__VC32__) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int + +#elif defined(__MWERKS__) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(_WIN32_WCE) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__MINGW32__) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_WS2TCPIP_H 1 + +#elif defined(__VMS) +# if defined(__VAX) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int + +#elif defined(__OS400__) +# if defined(__ILEC400__) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(__MVS__) +# if defined(__IBMC__) || defined(__IBMCPP__) +# if defined(_ILP32) +# elif defined(_LP64) +# endif +# if defined(_LONG_LONG) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(_LP64) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(__370__) +# if defined(__IBMC__) || defined(__IBMCPP__) +# if defined(_ILP32) +# elif defined(_LP64) +# endif +# if defined(_LONG_LONG) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(_LP64) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(TPF) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__TINYC__) /* also known as tcc */ + +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* Oracle Solaris Studio */ +# if !defined(__LP64) && (defined(__ILP32) || \ + defined(__i386) || \ + defined(__sparcv8) || \ + defined(__sparcv8plus)) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__LP64) || \ + defined(__amd64) || defined(__sparcv9) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#elif defined(__xlc__) /* IBM xlc compiler */ +# if !defined(_LP64) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +/* ===================================== */ +/* KEEP MSVC THE PENULTIMATE ENTRY */ +/* ===================================== */ + +#elif defined(_MSC_VER) +# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +/* ===================================== */ +/* KEEP GENERIC GCC THE LAST ENTRY */ +/* ===================================== */ + +#elif defined(__GNUC__) && !defined(_SCO_DS) +# if !defined(__LP64__) && \ + (defined(__ILP32__) || defined(__i386__) || defined(__hppa__) || \ + defined(__ppc__) || defined(__powerpc__) || defined(__arm__) || \ + defined(__sparc__) || defined(__mips__) || defined(__sh__) || \ + defined(__XTENSA__) || \ + (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 4) || \ + (defined(__LONG_MAX__) && __LONG_MAX__ == 2147483647L)) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__LP64__) || \ + defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__) || \ + (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8) || \ + (defined(__LONG_MAX__) && __LONG_MAX__ == 9223372036854775807L) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#else +/* generic "safe guess" on old 32 bit style */ +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int +#endif + +#ifdef _AIX +/* AIX needs */ +#define CURL_PULL_SYS_POLL_H +#endif + + +/* CURL_PULL_WS2TCPIP_H is defined above when inclusion of header file */ +/* ws2tcpip.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_WS2TCPIP_H +# include +# include +# include +#endif + +/* CURL_PULL_SYS_TYPES_H is defined above when inclusion of header file */ +/* sys/types.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_SYS_TYPES_H +# include +#endif + +/* CURL_PULL_SYS_SOCKET_H is defined above when inclusion of header file */ +/* sys/socket.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_SYS_SOCKET_H +# include +#endif + +/* CURL_PULL_SYS_POLL_H is defined above when inclusion of header file */ +/* sys/poll.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_SYS_POLL_H +# include +#endif + +/* Data type definition of curl_socklen_t. */ +#ifdef CURL_TYPEOF_CURL_SOCKLEN_T + typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t; +#endif + +/* Data type definition of curl_off_t. */ + +#ifdef CURL_TYPEOF_CURL_OFF_T + typedef CURL_TYPEOF_CURL_OFF_T curl_off_t; +#endif + +/* + * CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow + * these to be visible and exported by the external libcurl interface API, + * while also making them visible to the library internals, simply including + * curl_setup.h, without actually needing to include curl.h internally. + * If some day this section would grow big enough, all this should be moved + * to its own header file. + */ + +/* + * Figure out if we can use the ## preprocessor operator, which is supported + * by ISO/ANSI C and C++. Some compilers support it without setting __STDC__ + * or __cplusplus so we need to carefully check for them too. + */ + +#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \ + defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \ + defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \ + defined(__ILEC400__) + /* This compiler is believed to have an ISO compatible preprocessor */ +#define CURL_ISOCPP +#else + /* This compiler is believed NOT to have an ISO compatible preprocessor */ +#undef CURL_ISOCPP +#endif + +/* + * Macros for minimum-width signed and unsigned curl_off_t integer constants. + */ + +#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551) +# define __CURL_OFF_T_C_HLPR2(x) x +# define __CURL_OFF_T_C_HLPR1(x) __CURL_OFF_T_C_HLPR2(x) +# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \ + __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T) +# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \ + __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU) +#else +# ifdef CURL_ISOCPP +# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix +# else +# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix +# endif +# define __CURL_OFF_T_C_HLPR1(Val,Suffix) __CURL_OFF_T_C_HLPR2(Val,Suffix) +# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T) +# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU) +#endif + +#endif /* __CURL_SYSTEM_H */ diff --git a/dependencies/cmcurl/include/curl/typecheck-gcc.h b/dependencies/cmcurl/include/curl/typecheck-gcc.h new file mode 100644 index 0000000..2d1de4d --- /dev/null +++ b/dependencies/cmcurl/include/curl/typecheck-gcc.h @@ -0,0 +1,694 @@ +#ifndef __CURL_TYPECHECK_GCC_H +#define __CURL_TYPECHECK_GCC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* wraps curl_easy_setopt() with typechecking */ + +/* To add a new kind of warning, add an + * if(_curl_is_sometype_option(_curl_opt)) + * if(!_curl_is_sometype(value)) + * _curl_easy_setopt_err_sometype(); + * block and define _curl_is_sometype_option, _curl_is_sometype and + * _curl_easy_setopt_err_sometype below + * + * NOTE: We use two nested 'if' statements here instead of the && operator, in + * order to work around gcc bug #32061. It affects only gcc 4.3.x/4.4.x + * when compiling with -Wlogical-op. + * + * To add an option that uses the same type as an existing option, you'll just + * need to extend the appropriate _curl_*_option macro + */ +#define curl_easy_setopt(handle, option, value) \ +__extension__ ({ \ + __typeof__(option) _curl_opt = option; \ + if(__builtin_constant_p(_curl_opt)) { \ + if(_curl_is_long_option(_curl_opt)) \ + if(!_curl_is_long(value)) \ + _curl_easy_setopt_err_long(); \ + if(_curl_is_off_t_option(_curl_opt)) \ + if(!_curl_is_off_t(value)) \ + _curl_easy_setopt_err_curl_off_t(); \ + if(_curl_is_string_option(_curl_opt)) \ + if(!_curl_is_string(value)) \ + _curl_easy_setopt_err_string(); \ + if(_curl_is_write_cb_option(_curl_opt)) \ + if(!_curl_is_write_cb(value)) \ + _curl_easy_setopt_err_write_callback(); \ + if((_curl_opt) == CURLOPT_RESOLVER_START_FUNCTION) \ + if(!_curl_is_resolver_start_callback(value)) \ + _curl_easy_setopt_err_resolver_start_callback(); \ + if((_curl_opt) == CURLOPT_READFUNCTION) \ + if(!_curl_is_read_cb(value)) \ + _curl_easy_setopt_err_read_cb(); \ + if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \ + if(!_curl_is_ioctl_cb(value)) \ + _curl_easy_setopt_err_ioctl_cb(); \ + if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \ + if(!_curl_is_sockopt_cb(value)) \ + _curl_easy_setopt_err_sockopt_cb(); \ + if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \ + if(!_curl_is_opensocket_cb(value)) \ + _curl_easy_setopt_err_opensocket_cb(); \ + if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \ + if(!_curl_is_progress_cb(value)) \ + _curl_easy_setopt_err_progress_cb(); \ + if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \ + if(!_curl_is_debug_cb(value)) \ + _curl_easy_setopt_err_debug_cb(); \ + if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \ + if(!_curl_is_ssl_ctx_cb(value)) \ + _curl_easy_setopt_err_ssl_ctx_cb(); \ + if(_curl_is_conv_cb_option(_curl_opt)) \ + if(!_curl_is_conv_cb(value)) \ + _curl_easy_setopt_err_conv_cb(); \ + if((_curl_opt) == CURLOPT_SEEKFUNCTION) \ + if(!_curl_is_seek_cb(value)) \ + _curl_easy_setopt_err_seek_cb(); \ + if(_curl_is_cb_data_option(_curl_opt)) \ + if(!_curl_is_cb_data(value)) \ + _curl_easy_setopt_err_cb_data(); \ + if((_curl_opt) == CURLOPT_ERRORBUFFER) \ + if(!_curl_is_error_buffer(value)) \ + _curl_easy_setopt_err_error_buffer(); \ + if((_curl_opt) == CURLOPT_STDERR) \ + if(!_curl_is_FILE(value)) \ + _curl_easy_setopt_err_FILE(); \ + if(_curl_is_postfields_option(_curl_opt)) \ + if(!_curl_is_postfields(value)) \ + _curl_easy_setopt_err_postfields(); \ + if((_curl_opt) == CURLOPT_HTTPPOST) \ + if(!_curl_is_arr((value), struct curl_httppost)) \ + _curl_easy_setopt_err_curl_httpost(); \ + if((_curl_opt) == CURLOPT_MIMEPOST) \ + if(!_curl_is_ptr((value), curl_mime)) \ + _curl_easy_setopt_err_curl_mimepost(); \ + if(_curl_is_slist_option(_curl_opt)) \ + if(!_curl_is_arr((value), struct curl_slist)) \ + _curl_easy_setopt_err_curl_slist(); \ + if((_curl_opt) == CURLOPT_SHARE) \ + if(!_curl_is_ptr((value), CURLSH)) \ + _curl_easy_setopt_err_CURLSH(); \ + } \ + curl_easy_setopt(handle, _curl_opt, value); \ +}) + +/* wraps curl_easy_getinfo() with typechecking */ +#define curl_easy_getinfo(handle, info, arg) \ +__extension__ ({ \ + __typeof__(info) _curl_info = info; \ + if(__builtin_constant_p(_curl_info)) { \ + if(_curl_is_string_info(_curl_info)) \ + if(!_curl_is_arr((arg), char *)) \ + _curl_easy_getinfo_err_string(); \ + if(_curl_is_long_info(_curl_info)) \ + if(!_curl_is_arr((arg), long)) \ + _curl_easy_getinfo_err_long(); \ + if(_curl_is_double_info(_curl_info)) \ + if(!_curl_is_arr((arg), double)) \ + _curl_easy_getinfo_err_double(); \ + if(_curl_is_slist_info(_curl_info)) \ + if(!_curl_is_arr((arg), struct curl_slist *)) \ + _curl_easy_getinfo_err_curl_slist(); \ + if(_curl_is_tlssessioninfo_info(_curl_info)) \ + if(!_curl_is_arr((arg), struct curl_tlssessioninfo *)) \ + _curl_easy_getinfo_err_curl_tlssesssioninfo(); \ + if(_curl_is_certinfo_info(_curl_info)) \ + if(!_curl_is_arr((arg), struct curl_certinfo *)) \ + _curl_easy_getinfo_err_curl_certinfo(); \ + if(_curl_is_socket_info(_curl_info)) \ + if(!_curl_is_arr((arg), curl_socket_t)) \ + _curl_easy_getinfo_err_curl_socket(); \ + if(_curl_is_off_t_info(_curl_info)) \ + if(!_curl_is_arr((arg), curl_off_t)) \ + _curl_easy_getinfo_err_curl_off_t(); \ + } \ + curl_easy_getinfo(handle, _curl_info, arg); \ +}) + +/* + * For now, just make sure that the functions are called with three arguments + */ +#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) +#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param) + + +/* the actual warnings, triggered by calling the _curl_easy_setopt_err* + * functions */ + +/* To define a new warning, use _CURL_WARNING(identifier, "message") */ +#define _CURL_WARNING(id, message) \ + static void __attribute__((__warning__(message))) \ + __attribute__((__unused__)) __attribute__((__noinline__)) \ + id(void) { __asm__(""); } + +_CURL_WARNING(_curl_easy_setopt_err_long, + "curl_easy_setopt expects a long argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_curl_off_t, + "curl_easy_setopt expects a curl_off_t argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_string, + "curl_easy_setopt expects a " + "string ('char *' or char[]) argument for this option" + ) +_CURL_WARNING(_curl_easy_setopt_err_write_callback, + "curl_easy_setopt expects a curl_write_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_resolver_start_callback, + "curl_easy_setopt expects a " + "curl_resolver_start_callback argument for this option" + ) +_CURL_WARNING(_curl_easy_setopt_err_read_cb, + "curl_easy_setopt expects a curl_read_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_ioctl_cb, + "curl_easy_setopt expects a curl_ioctl_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_sockopt_cb, + "curl_easy_setopt expects a curl_sockopt_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_opensocket_cb, + "curl_easy_setopt expects a " + "curl_opensocket_callback argument for this option" + ) +_CURL_WARNING(_curl_easy_setopt_err_progress_cb, + "curl_easy_setopt expects a curl_progress_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_debug_cb, + "curl_easy_setopt expects a curl_debug_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_ssl_ctx_cb, + "curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_conv_cb, + "curl_easy_setopt expects a curl_conv_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_seek_cb, + "curl_easy_setopt expects a curl_seek_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_cb_data, + "curl_easy_setopt expects a " + "private data pointer as argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_error_buffer, + "curl_easy_setopt expects a " + "char buffer of CURL_ERROR_SIZE as argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_FILE, + "curl_easy_setopt expects a 'FILE *' argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_postfields, + "curl_easy_setopt expects a 'void *' or 'char *' argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_curl_httpost, + "curl_easy_setopt expects a 'struct curl_httppost *' " + "argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_curl_mimepost, + "curl_easy_setopt expects a 'curl_mime *' " + "argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_curl_slist, + "curl_easy_setopt expects a 'struct curl_slist *' argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_CURLSH, + "curl_easy_setopt expects a CURLSH* argument for this option") + +_CURL_WARNING(_curl_easy_getinfo_err_string, + "curl_easy_getinfo expects a pointer to 'char *' for this info") +_CURL_WARNING(_curl_easy_getinfo_err_long, + "curl_easy_getinfo expects a pointer to long for this info") +_CURL_WARNING(_curl_easy_getinfo_err_double, + "curl_easy_getinfo expects a pointer to double for this info") +_CURL_WARNING(_curl_easy_getinfo_err_curl_slist, + "curl_easy_getinfo expects a pointer to 'struct curl_slist *' for this info") +_CURL_WARNING(_curl_easy_getinfo_err_curl_tlssesssioninfo, + "curl_easy_getinfo expects a pointer to " + "'struct curl_tlssessioninfo *' for this info") +_CURL_WARNING(_curl_easy_getinfo_err_curl_certinfo, + "curl_easy_getinfo expects a pointer to " + "'struct curl_certinfo *' for this info") +_CURL_WARNING(_curl_easy_getinfo_err_curl_socket, + "curl_easy_getinfo expects a pointer to curl_socket_t for this info") +_CURL_WARNING(_curl_easy_getinfo_err_curl_off_t, + "curl_easy_getinfo expects a pointer to curl_off_t for this info") + +/* groups of curl_easy_setops options that take the same type of argument */ + +/* To add a new option to one of the groups, just add + * (option) == CURLOPT_SOMETHING + * to the or-expression. If the option takes a long or curl_off_t, you don't + * have to do anything + */ + +/* evaluates to true if option takes a long argument */ +#define _curl_is_long_option(option) \ + (0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT) + +#define _curl_is_off_t_option(option) \ + ((option) > CURLOPTTYPE_OFF_T) + +/* evaluates to true if option takes a char* argument */ +#define _curl_is_string_option(option) \ + ((option) == CURLOPT_ABSTRACT_UNIX_SOCKET || \ + (option) == CURLOPT_ACCEPT_ENCODING || \ + (option) == CURLOPT_ALTSVC || \ + (option) == CURLOPT_CAINFO || \ + (option) == CURLOPT_CAPATH || \ + (option) == CURLOPT_COOKIE || \ + (option) == CURLOPT_COOKIEFILE || \ + (option) == CURLOPT_COOKIEJAR || \ + (option) == CURLOPT_COOKIELIST || \ + (option) == CURLOPT_CRLFILE || \ + (option) == CURLOPT_CUSTOMREQUEST || \ + (option) == CURLOPT_DEFAULT_PROTOCOL || \ + (option) == CURLOPT_DNS_INTERFACE || \ + (option) == CURLOPT_DNS_LOCAL_IP4 || \ + (option) == CURLOPT_DNS_LOCAL_IP6 || \ + (option) == CURLOPT_DNS_SERVERS || \ + (option) == CURLOPT_DOH_URL || \ + (option) == CURLOPT_EGDSOCKET || \ + (option) == CURLOPT_FTPPORT || \ + (option) == CURLOPT_FTP_ACCOUNT || \ + (option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \ + (option) == CURLOPT_INTERFACE || \ + (option) == CURLOPT_ISSUERCERT || \ + (option) == CURLOPT_KEYPASSWD || \ + (option) == CURLOPT_KRBLEVEL || \ + (option) == CURLOPT_LOGIN_OPTIONS || \ + (option) == CURLOPT_MAIL_AUTH || \ + (option) == CURLOPT_MAIL_FROM || \ + (option) == CURLOPT_NETRC_FILE || \ + (option) == CURLOPT_NOPROXY || \ + (option) == CURLOPT_PASSWORD || \ + (option) == CURLOPT_PINNEDPUBLICKEY || \ + (option) == CURLOPT_PRE_PROXY || \ + (option) == CURLOPT_PROXY || \ + (option) == CURLOPT_PROXYPASSWORD || \ + (option) == CURLOPT_PROXYUSERNAME || \ + (option) == CURLOPT_PROXYUSERPWD || \ + (option) == CURLOPT_PROXY_CAINFO || \ + (option) == CURLOPT_PROXY_CAPATH || \ + (option) == CURLOPT_PROXY_CRLFILE || \ + (option) == CURLOPT_PROXY_KEYPASSWD || \ + (option) == CURLOPT_PROXY_PINNEDPUBLICKEY || \ + (option) == CURLOPT_PROXY_SERVICE_NAME || \ + (option) == CURLOPT_PROXY_SSLCERT || \ + (option) == CURLOPT_PROXY_SSLCERTTYPE || \ + (option) == CURLOPT_PROXY_SSLKEY || \ + (option) == CURLOPT_PROXY_SSLKEYTYPE || \ + (option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \ + (option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \ + (option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \ + (option) == CURLOPT_PROXY_TLSAUTH_TYPE || \ + (option) == CURLOPT_RANDOM_FILE || \ + (option) == CURLOPT_RANGE || \ + (option) == CURLOPT_REFERER || \ + (option) == CURLOPT_RTSP_SESSION_ID || \ + (option) == CURLOPT_RTSP_STREAM_URI || \ + (option) == CURLOPT_RTSP_TRANSPORT || \ + (option) == CURLOPT_SERVICE_NAME || \ + (option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \ + (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \ + (option) == CURLOPT_SSH_KNOWNHOSTS || \ + (option) == CURLOPT_SSH_PRIVATE_KEYFILE || \ + (option) == CURLOPT_SSH_PUBLIC_KEYFILE || \ + (option) == CURLOPT_SSLCERT || \ + (option) == CURLOPT_SSLCERTTYPE || \ + (option) == CURLOPT_SSLENGINE || \ + (option) == CURLOPT_SSLKEY || \ + (option) == CURLOPT_SSLKEYTYPE || \ + (option) == CURLOPT_SSL_CIPHER_LIST || \ + (option) == CURLOPT_TLSAUTH_PASSWORD || \ + (option) == CURLOPT_TLSAUTH_TYPE || \ + (option) == CURLOPT_TLSAUTH_USERNAME || \ + (option) == CURLOPT_UNIX_SOCKET_PATH || \ + (option) == CURLOPT_URL || \ + (option) == CURLOPT_USERAGENT || \ + (option) == CURLOPT_USERNAME || \ + (option) == CURLOPT_USERPWD || \ + (option) == CURLOPT_XOAUTH2_BEARER || \ + 0) + +/* evaluates to true if option takes a curl_write_callback argument */ +#define _curl_is_write_cb_option(option) \ + ((option) == CURLOPT_HEADERFUNCTION || \ + (option) == CURLOPT_WRITEFUNCTION) + +/* evaluates to true if option takes a curl_conv_callback argument */ +#define _curl_is_conv_cb_option(option) \ + ((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \ + (option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \ + (option) == CURLOPT_CONV_FROM_UTF8_FUNCTION) + +/* evaluates to true if option takes a data argument to pass to a callback */ +#define _curl_is_cb_data_option(option) \ + ((option) == CURLOPT_CHUNK_DATA || \ + (option) == CURLOPT_CLOSESOCKETDATA || \ + (option) == CURLOPT_DEBUGDATA || \ + (option) == CURLOPT_FNMATCH_DATA || \ + (option) == CURLOPT_HEADERDATA || \ + (option) == CURLOPT_INTERLEAVEDATA || \ + (option) == CURLOPT_IOCTLDATA || \ + (option) == CURLOPT_OPENSOCKETDATA || \ + (option) == CURLOPT_PRIVATE || \ + (option) == CURLOPT_PROGRESSDATA || \ + (option) == CURLOPT_READDATA || \ + (option) == CURLOPT_SEEKDATA || \ + (option) == CURLOPT_SOCKOPTDATA || \ + (option) == CURLOPT_SSH_KEYDATA || \ + (option) == CURLOPT_SSL_CTX_DATA || \ + (option) == CURLOPT_WRITEDATA || \ + (option) == CURLOPT_RESOLVER_START_DATA || \ + (option) == CURLOPT_CURLU || \ + 0) + +/* evaluates to true if option takes a POST data argument (void* or char*) */ +#define _curl_is_postfields_option(option) \ + ((option) == CURLOPT_POSTFIELDS || \ + (option) == CURLOPT_COPYPOSTFIELDS || \ + 0) + +/* evaluates to true if option takes a struct curl_slist * argument */ +#define _curl_is_slist_option(option) \ + ((option) == CURLOPT_HTTP200ALIASES || \ + (option) == CURLOPT_HTTPHEADER || \ + (option) == CURLOPT_MAIL_RCPT || \ + (option) == CURLOPT_POSTQUOTE || \ + (option) == CURLOPT_PREQUOTE || \ + (option) == CURLOPT_PROXYHEADER || \ + (option) == CURLOPT_QUOTE || \ + (option) == CURLOPT_RESOLVE || \ + (option) == CURLOPT_TELNETOPTIONS || \ + 0) + +/* groups of curl_easy_getinfo infos that take the same type of argument */ + +/* evaluates to true if info expects a pointer to char * argument */ +#define _curl_is_string_info(info) \ + (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG) + +/* evaluates to true if info expects a pointer to long argument */ +#define _curl_is_long_info(info) \ + (CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE) + +/* evaluates to true if info expects a pointer to double argument */ +#define _curl_is_double_info(info) \ + (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST) + +/* true if info expects a pointer to struct curl_slist * argument */ +#define _curl_is_slist_info(info) \ + (((info) == CURLINFO_SSL_ENGINES) || ((info) == CURLINFO_COOKIELIST)) + +/* true if info expects a pointer to struct curl_tlssessioninfo * argument */ +#define _curl_is_tlssessioninfo_info(info) \ + (((info) == CURLINFO_TLS_SSL_PTR) || ((info) == CURLINFO_TLS_SESSION)) + +/* true if info expects a pointer to struct curl_certinfo * argument */ +#define _curl_is_certinfo_info(info) ((info) == CURLINFO_CERTINFO) + +/* true if info expects a pointer to struct curl_socket_t argument */ +#define _curl_is_socket_info(info) \ + (CURLINFO_SOCKET < (info) && (info) < CURLINFO_OFF_T) + +/* true if info expects a pointer to curl_off_t argument */ +#define _curl_is_off_t_info(info) \ + (CURLINFO_OFF_T < (info)) + + +/* typecheck helpers -- check whether given expression has requested type*/ + +/* For pointers, you can use the _curl_is_ptr/_curl_is_arr macros, + * otherwise define a new macro. Search for __builtin_types_compatible_p + * in the GCC manual. + * NOTE: these macros MUST NOT EVALUATE their arguments! The argument is + * the actual expression passed to the curl_easy_setopt macro. This + * means that you can only apply the sizeof and __typeof__ operators, no + * == or whatsoever. + */ + +/* XXX: should evaluate to true if expr is a pointer */ +#define _curl_is_any_ptr(expr) \ + (sizeof(expr) == sizeof(void *)) + +/* evaluates to true if expr is NULL */ +/* XXX: must not evaluate expr, so this check is not accurate */ +#define _curl_is_NULL(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL))) + +/* evaluates to true if expr is type*, const type* or NULL */ +#define _curl_is_ptr(expr, type) \ + (_curl_is_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), type *) || \ + __builtin_types_compatible_p(__typeof__(expr), const type *)) + +/* evaluates to true if expr is one of type[], type*, NULL or const type* */ +#define _curl_is_arr(expr, type) \ + (_curl_is_ptr((expr), type) || \ + __builtin_types_compatible_p(__typeof__(expr), type [])) + +/* evaluates to true if expr is a string */ +#define _curl_is_string(expr) \ + (_curl_is_arr((expr), char) || \ + _curl_is_arr((expr), signed char) || \ + _curl_is_arr((expr), unsigned char)) + +/* evaluates to true if expr is a long (no matter the signedness) + * XXX: for now, int is also accepted (and therefore short and char, which + * are promoted to int when passed to a variadic function) */ +#define _curl_is_long(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), long) || \ + __builtin_types_compatible_p(__typeof__(expr), signed long) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned long) || \ + __builtin_types_compatible_p(__typeof__(expr), int) || \ + __builtin_types_compatible_p(__typeof__(expr), signed int) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned int) || \ + __builtin_types_compatible_p(__typeof__(expr), short) || \ + __builtin_types_compatible_p(__typeof__(expr), signed short) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned short) || \ + __builtin_types_compatible_p(__typeof__(expr), char) || \ + __builtin_types_compatible_p(__typeof__(expr), signed char) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned char)) + +/* evaluates to true if expr is of type curl_off_t */ +#define _curl_is_off_t(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), curl_off_t)) + +/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */ +/* XXX: also check size of an char[] array? */ +#define _curl_is_error_buffer(expr) \ + (_curl_is_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), char *) || \ + __builtin_types_compatible_p(__typeof__(expr), char[])) + +/* evaluates to true if expr is of type (const) void* or (const) FILE* */ +#if 0 +#define _curl_is_cb_data(expr) \ + (_curl_is_ptr((expr), void) || \ + _curl_is_ptr((expr), FILE)) +#else /* be less strict */ +#define _curl_is_cb_data(expr) \ + _curl_is_any_ptr(expr) +#endif + +/* evaluates to true if expr is of type FILE* */ +#define _curl_is_FILE(expr) \ + (_curl_is_NULL(expr) || \ + (__builtin_types_compatible_p(__typeof__(expr), FILE *))) + +/* evaluates to true if expr can be passed as POST data (void* or char*) */ +#define _curl_is_postfields(expr) \ + (_curl_is_ptr((expr), void) || \ + _curl_is_arr((expr), char) || \ + _curl_is_arr((expr), unsigned char)) + +/* helper: __builtin_types_compatible_p distinguishes between functions and + * function pointers, hide it */ +#define _curl_callback_compatible(func, type) \ + (__builtin_types_compatible_p(__typeof__(func), type) || \ + __builtin_types_compatible_p(__typeof__(func) *, type)) + +/* evaluates to true if expr is of type curl_resolver_start_callback */ +#define _curl_is_resolver_start_callback(expr) \ + (_curl_is_NULL(expr) || \ + _curl_callback_compatible((expr), curl_resolver_start_callback)) + +/* evaluates to true if expr is of type curl_read_callback or "similar" */ +#define _curl_is_read_cb(expr) \ + (_curl_is_NULL(expr) || \ + _curl_callback_compatible((expr), __typeof__(fread) *) || \ + _curl_callback_compatible((expr), curl_read_callback) || \ + _curl_callback_compatible((expr), _curl_read_callback1) || \ + _curl_callback_compatible((expr), _curl_read_callback2) || \ + _curl_callback_compatible((expr), _curl_read_callback3) || \ + _curl_callback_compatible((expr), _curl_read_callback4) || \ + _curl_callback_compatible((expr), _curl_read_callback5) || \ + _curl_callback_compatible((expr), _curl_read_callback6)) +typedef size_t (*_curl_read_callback1)(char *, size_t, size_t, void *); +typedef size_t (*_curl_read_callback2)(char *, size_t, size_t, const void *); +typedef size_t (*_curl_read_callback3)(char *, size_t, size_t, FILE *); +typedef size_t (*_curl_read_callback4)(void *, size_t, size_t, void *); +typedef size_t (*_curl_read_callback5)(void *, size_t, size_t, const void *); +typedef size_t (*_curl_read_callback6)(void *, size_t, size_t, FILE *); + +/* evaluates to true if expr is of type curl_write_callback or "similar" */ +#define _curl_is_write_cb(expr) \ + (_curl_is_read_cb(expr) || \ + _curl_callback_compatible((expr), __typeof__(fwrite) *) || \ + _curl_callback_compatible((expr), curl_write_callback) || \ + _curl_callback_compatible((expr), _curl_write_callback1) || \ + _curl_callback_compatible((expr), _curl_write_callback2) || \ + _curl_callback_compatible((expr), _curl_write_callback3) || \ + _curl_callback_compatible((expr), _curl_write_callback4) || \ + _curl_callback_compatible((expr), _curl_write_callback5) || \ + _curl_callback_compatible((expr), _curl_write_callback6)) +typedef size_t (*_curl_write_callback1)(const char *, size_t, size_t, void *); +typedef size_t (*_curl_write_callback2)(const char *, size_t, size_t, + const void *); +typedef size_t (*_curl_write_callback3)(const char *, size_t, size_t, FILE *); +typedef size_t (*_curl_write_callback4)(const void *, size_t, size_t, void *); +typedef size_t (*_curl_write_callback5)(const void *, size_t, size_t, + const void *); +typedef size_t (*_curl_write_callback6)(const void *, size_t, size_t, FILE *); + +/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */ +#define _curl_is_ioctl_cb(expr) \ + (_curl_is_NULL(expr) || \ + _curl_callback_compatible((expr), curl_ioctl_callback) || \ + _curl_callback_compatible((expr), _curl_ioctl_callback1) || \ + _curl_callback_compatible((expr), _curl_ioctl_callback2) || \ + _curl_callback_compatible((expr), _curl_ioctl_callback3) || \ + _curl_callback_compatible((expr), _curl_ioctl_callback4)) +typedef curlioerr (*_curl_ioctl_callback1)(CURL *, int, void *); +typedef curlioerr (*_curl_ioctl_callback2)(CURL *, int, const void *); +typedef curlioerr (*_curl_ioctl_callback3)(CURL *, curliocmd, void *); +typedef curlioerr (*_curl_ioctl_callback4)(CURL *, curliocmd, const void *); + +/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */ +#define _curl_is_sockopt_cb(expr) \ + (_curl_is_NULL(expr) || \ + _curl_callback_compatible((expr), curl_sockopt_callback) || \ + _curl_callback_compatible((expr), _curl_sockopt_callback1) || \ + _curl_callback_compatible((expr), _curl_sockopt_callback2)) +typedef int (*_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype); +typedef int (*_curl_sockopt_callback2)(const void *, curl_socket_t, + curlsocktype); + +/* evaluates to true if expr is of type curl_opensocket_callback or + "similar" */ +#define _curl_is_opensocket_cb(expr) \ + (_curl_is_NULL(expr) || \ + _curl_callback_compatible((expr), curl_opensocket_callback) || \ + _curl_callback_compatible((expr), _curl_opensocket_callback1) || \ + _curl_callback_compatible((expr), _curl_opensocket_callback2) || \ + _curl_callback_compatible((expr), _curl_opensocket_callback3) || \ + _curl_callback_compatible((expr), _curl_opensocket_callback4)) +typedef curl_socket_t (*_curl_opensocket_callback1) + (void *, curlsocktype, struct curl_sockaddr *); +typedef curl_socket_t (*_curl_opensocket_callback2) + (void *, curlsocktype, const struct curl_sockaddr *); +typedef curl_socket_t (*_curl_opensocket_callback3) + (const void *, curlsocktype, struct curl_sockaddr *); +typedef curl_socket_t (*_curl_opensocket_callback4) + (const void *, curlsocktype, const struct curl_sockaddr *); + +/* evaluates to true if expr is of type curl_progress_callback or "similar" */ +#define _curl_is_progress_cb(expr) \ + (_curl_is_NULL(expr) || \ + _curl_callback_compatible((expr), curl_progress_callback) || \ + _curl_callback_compatible((expr), _curl_progress_callback1) || \ + _curl_callback_compatible((expr), _curl_progress_callback2)) +typedef int (*_curl_progress_callback1)(void *, + double, double, double, double); +typedef int (*_curl_progress_callback2)(const void *, + double, double, double, double); + +/* evaluates to true if expr is of type curl_debug_callback or "similar" */ +#define _curl_is_debug_cb(expr) \ + (_curl_is_NULL(expr) || \ + _curl_callback_compatible((expr), curl_debug_callback) || \ + _curl_callback_compatible((expr), _curl_debug_callback1) || \ + _curl_callback_compatible((expr), _curl_debug_callback2) || \ + _curl_callback_compatible((expr), _curl_debug_callback3) || \ + _curl_callback_compatible((expr), _curl_debug_callback4) || \ + _curl_callback_compatible((expr), _curl_debug_callback5) || \ + _curl_callback_compatible((expr), _curl_debug_callback6) || \ + _curl_callback_compatible((expr), _curl_debug_callback7) || \ + _curl_callback_compatible((expr), _curl_debug_callback8)) +typedef int (*_curl_debug_callback1) (CURL *, + curl_infotype, char *, size_t, void *); +typedef int (*_curl_debug_callback2) (CURL *, + curl_infotype, char *, size_t, const void *); +typedef int (*_curl_debug_callback3) (CURL *, + curl_infotype, const char *, size_t, void *); +typedef int (*_curl_debug_callback4) (CURL *, + curl_infotype, const char *, size_t, const void *); +typedef int (*_curl_debug_callback5) (CURL *, + curl_infotype, unsigned char *, size_t, void *); +typedef int (*_curl_debug_callback6) (CURL *, + curl_infotype, unsigned char *, size_t, const void *); +typedef int (*_curl_debug_callback7) (CURL *, + curl_infotype, const unsigned char *, size_t, void *); +typedef int (*_curl_debug_callback8) (CURL *, + curl_infotype, const unsigned char *, size_t, const void *); + +/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */ +/* this is getting even messier... */ +#define _curl_is_ssl_ctx_cb(expr) \ + (_curl_is_NULL(expr) || \ + _curl_callback_compatible((expr), curl_ssl_ctx_callback) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback1) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback2) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback3) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback4) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback5) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback6) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback7) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback8)) +typedef CURLcode (*_curl_ssl_ctx_callback1)(CURL *, void *, void *); +typedef CURLcode (*_curl_ssl_ctx_callback2)(CURL *, void *, const void *); +typedef CURLcode (*_curl_ssl_ctx_callback3)(CURL *, const void *, void *); +typedef CURLcode (*_curl_ssl_ctx_callback4)(CURL *, const void *, + const void *); +#ifdef HEADER_SSL_H +/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX + * this will of course break if we're included before OpenSSL headers... + */ +typedef CURLcode (*_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *); +typedef CURLcode (*_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *); +typedef CURLcode (*_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *); +typedef CURLcode (*_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX, + const void *); +#else +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8; +#endif + +/* evaluates to true if expr is of type curl_conv_callback or "similar" */ +#define _curl_is_conv_cb(expr) \ + (_curl_is_NULL(expr) || \ + _curl_callback_compatible((expr), curl_conv_callback) || \ + _curl_callback_compatible((expr), _curl_conv_callback1) || \ + _curl_callback_compatible((expr), _curl_conv_callback2) || \ + _curl_callback_compatible((expr), _curl_conv_callback3) || \ + _curl_callback_compatible((expr), _curl_conv_callback4)) +typedef CURLcode (*_curl_conv_callback1)(char *, size_t length); +typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length); +typedef CURLcode (*_curl_conv_callback3)(void *, size_t length); +typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length); + +/* evaluates to true if expr is of type curl_seek_callback or "similar" */ +#define _curl_is_seek_cb(expr) \ + (_curl_is_NULL(expr) || \ + _curl_callback_compatible((expr), curl_seek_callback) || \ + _curl_callback_compatible((expr), _curl_seek_callback1) || \ + _curl_callback_compatible((expr), _curl_seek_callback2)) +typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int); +typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int); + + +#endif /* __CURL_TYPECHECK_GCC_H */ diff --git a/dependencies/cmcurl/include/curl/urlapi.h b/dependencies/cmcurl/include/curl/urlapi.h new file mode 100644 index 0000000..58e89d8 --- /dev/null +++ b/dependencies/cmcurl/include/curl/urlapi.h @@ -0,0 +1,123 @@ +#ifndef __CURL_URLAPI_H +#define __CURL_URLAPI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2018 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* the error codes for the URL API */ +typedef enum { + CURLUE_OK, + CURLUE_BAD_HANDLE, /* 1 */ + CURLUE_BAD_PARTPOINTER, /* 2 */ + CURLUE_MALFORMED_INPUT, /* 3 */ + CURLUE_BAD_PORT_NUMBER, /* 4 */ + CURLUE_UNSUPPORTED_SCHEME, /* 5 */ + CURLUE_URLDECODE, /* 6 */ + CURLUE_OUT_OF_MEMORY, /* 7 */ + CURLUE_USER_NOT_ALLOWED, /* 8 */ + CURLUE_UNKNOWN_PART, /* 9 */ + CURLUE_NO_SCHEME, /* 10 */ + CURLUE_NO_USER, /* 11 */ + CURLUE_NO_PASSWORD, /* 12 */ + CURLUE_NO_OPTIONS, /* 13 */ + CURLUE_NO_HOST, /* 14 */ + CURLUE_NO_PORT, /* 15 */ + CURLUE_NO_QUERY, /* 16 */ + CURLUE_NO_FRAGMENT /* 17 */ +} CURLUcode; + +typedef enum { + CURLUPART_URL, + CURLUPART_SCHEME, + CURLUPART_USER, + CURLUPART_PASSWORD, + CURLUPART_OPTIONS, + CURLUPART_HOST, + CURLUPART_PORT, + CURLUPART_PATH, + CURLUPART_QUERY, + CURLUPART_FRAGMENT, + CURLUPART_ZONEID /* added in 7.65.0 */ +} CURLUPart; + +#define CURLU_DEFAULT_PORT (1<<0) /* return default port number */ +#define CURLU_NO_DEFAULT_PORT (1<<1) /* act as if no port number was set, + if the port number matches the + default for the scheme */ +#define CURLU_DEFAULT_SCHEME (1<<2) /* return default scheme if + missing */ +#define CURLU_NON_SUPPORT_SCHEME (1<<3) /* allow non-supported scheme */ +#define CURLU_PATH_AS_IS (1<<4) /* leave dot sequences */ +#define CURLU_DISALLOW_USER (1<<5) /* no user+password allowed */ +#define CURLU_URLDECODE (1<<6) /* URL decode on get */ +#define CURLU_URLENCODE (1<<7) /* URL encode on set */ +#define CURLU_APPENDQUERY (1<<8) /* append a form style part */ +#define CURLU_GUESS_SCHEME (1<<9) /* legacy curl-style guessing */ + +typedef struct Curl_URL CURLU; + +/* + * curl_url() creates a new CURLU handle and returns a pointer to it. + * Must be freed with curl_url_cleanup(). + */ +CURL_EXTERN CURLU *curl_url(void); + +/* + * curl_url_cleanup() frees the CURLU handle and related resources used for + * the URL parsing. It will not free strings previously returned with the URL + * API. + */ +CURL_EXTERN void curl_url_cleanup(CURLU *handle); + +/* + * curl_url_dup() duplicates a CURLU handle and returns a new copy. The new + * handle must also be freed with curl_url_cleanup(). + */ +CURL_EXTERN CURLU *curl_url_dup(CURLU *in); + +/* + * curl_url_get() extracts a specific part of the URL from a CURLU + * handle. Returns error code. The returned pointer MUST be freed with + * curl_free() afterwards. + */ +CURL_EXTERN CURLUcode curl_url_get(CURLU *handle, CURLUPart what, + char **part, unsigned int flags); + +/* + * curl_url_set() sets a specific part of the URL in a CURLU handle. Returns + * error code. The passed in string will be copied. Passing a NULL instead of + * a part string, clears that part. + */ +CURL_EXTERN CURLUcode curl_url_set(CURLU *handle, CURLUPart what, + const char *part, unsigned int flags); + + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif diff --git a/dependencies/cmcurl/lib/CMakeLists.txt b/dependencies/cmcurl/lib/CMakeLists.txt new file mode 100644 index 0000000..2a6279c --- /dev/null +++ b/dependencies/cmcurl/lib/CMakeLists.txt @@ -0,0 +1,147 @@ +set(LIB_NAME cmcurl) + +if(BUILD_SHARED_LIBS) + set(CURL_STATICLIB NO) +else() + set(CURL_STATICLIB YES) +endif() + +# Use: +# * CURL_STATICLIB +configure_file(curl_config.h.cmake + ${CMAKE_CURRENT_BINARY_DIR}/curl_config.h) + +transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake") +include(${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake) + +list(APPEND HHEADERS + ${CMAKE_CURRENT_BINARY_DIR}/curl_config.h + ) + +if(MSVC AND NOT CURL_STATICLIB) + list(APPEND CSOURCES libcurl.rc) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4127") +endif() + +# SET(CSOURCES +# # memdebug.c -not used +# # nwlib.c - Not used +# # strtok.c - specify later +# # strtoofft.c - specify later +# ) + +# # if we have Kerberos 4, right now this is never on +# #OPTION(CURL_KRB4 "Use Kerberos 4" OFF) +# IF(CURL_KRB4) +# SET(CSOURCES ${CSOURCES} +# krb4.c +# security.c +# ) +# ENDIF(CURL_KRB4) + +# #OPTION(CURL_MALLOC_DEBUG "Debug mallocs in Curl" OFF) +# MARK_AS_ADVANCED(CURL_MALLOC_DEBUG) +# IF(CURL_MALLOC_DEBUG) +# SET(CSOURCES ${CSOURCES} +# memdebug.c +# ) +# ENDIF(CURL_MALLOC_DEBUG) + +# # only build compat strtoofft if we need to +# IF(NOT HAVE_STRTOLL AND NOT HAVE__STRTOI64) +# SET(CSOURCES ${CSOURCES} +# strtoofft.c +# ) +# ENDIF(NOT HAVE_STRTOLL AND NOT HAVE__STRTOI64) + + +# The rest of the build + +include_directories(${CMAKE_CURRENT_BINARY_DIR}/../include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include) +include_directories(${CMAKE_CURRENT_BINARY_DIR}/..) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) +if(USE_ARES) + include_directories(${CARES_INCLUDE_DIR}) +endif() + +# For windows we want to install OPENSSL_LIBRARIES dlls +# and also copy them into the build tree so that testing +# can find them. +if(CMAKE_USE_OPENSSL AND OPENSSL_FOUND AND WIN32) + find_file(CMAKE_EAY_DLL NAME libeay32.dll HINTS ${OPENSSL_INCLUDE_DIR}/..) + find_file(CMAKE_SSL_DLL NAME ssleay32.dll HINTS ${OPENSSL_INCLUDE_DIR}/..) + mark_as_advanced(CMAKE_EAY_DLL CMAKE_SSL_DLL) + if(CMAKE_SSL_DLL AND CMAKE_EAY_DLL) + set(CMAKE_CURL_SSL_DLLS ${CMake_BIN_DIR}/${CMAKE_CFG_INTDIR}/libeay32.dll + ${CMake_BIN_DIR}/${CMAKE_CFG_INTDIR}/ssleay32.dll) + add_custom_command(OUTPUT + ${CMake_BIN_DIR}/${CMAKE_CFG_INTDIR}/libeay32.dll + DEPENDS ${CMAKE_EAY_DLL} + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_EAY_DLL} + ${CMake_BIN_DIR}/${CMAKE_CFG_INTDIR}/libeay32.dll) + add_custom_command(OUTPUT + ${CMake_BIN_DIR}/${CMAKE_CFG_INTDIR}/ssleay32.dll + DEPENDS ${CMAKE_SSL_DLL} + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SSL_DLL} + ${CMake_BIN_DIR}/${CMAKE_CFG_INTDIR}/ssleay32.dll) + install(PROGRAMS ${CMAKE_EAY_DLL} ${CMAKE_SSL_DLL} DESTINATION bin) + endif() +endif() + +add_library( + ${LIB_NAME} + ${HHEADERS} ${CSOURCES} + ${CMAKE_CURL_SSL_DLLS} + ) + +if(NOT BUILD_SHARED_LIBS) + set_target_properties(${LIB_NAME} PROPERTIES INTERFACE_COMPILE_DEFINITIONS CURL_STATICLIB) +endif() + +target_link_libraries(${LIB_NAME} ${CURL_LIBS}) + +if(0) # This code not needed for building within CMake. +if(WIN32) + add_definitions(-D_USRDLL) +endif() +endif() + +set_target_properties(${LIB_NAME} PROPERTIES COMPILE_DEFINITIONS BUILDING_LIBCURL) + +if(0) # This code not needed for building within CMake. +if(HIDES_CURL_PRIVATE_SYMBOLS) + set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS") + set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_FLAGS ${CURL_CFLAG_SYMBOLS_HIDE}) +endif() + +# Remove the "lib" prefix since the library is already named "libcurl". +set_target_properties(${LIB_NAME} PROPERTIES PREFIX "") +set_target_properties(${LIB_NAME} PROPERTIES IMPORT_PREFIX "") + +if(WIN32) + if(BUILD_SHARED_LIBS) + # Add "_imp" as a suffix before the extension to avoid conflicting with the statically linked "libcurl.lib" + set_target_properties(${LIB_NAME} PROPERTIES IMPORT_SUFFIX "_imp.lib") + endif() +endif() + +target_include_directories(${LIB_NAME} INTERFACE + $ + $) + +install(TARGETS ${LIB_NAME} + EXPORT ${TARGETS_EXPORT_NAME} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) + +export(TARGETS ${LIB_NAME} + APPEND FILE ${PROJECT_BINARY_DIR}/libcurl-target.cmake + NAMESPACE CURL:: +) + +endif() diff --git a/dependencies/cmcurl/lib/Makefile.inc b/dependencies/cmcurl/lib/Makefile.inc new file mode 100644 index 0000000..235b82b --- /dev/null +++ b/dependencies/cmcurl/lib/Makefile.inc @@ -0,0 +1,84 @@ +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.haxx.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +########################################################################### + +LIB_VAUTH_CFILES = vauth/vauth.c vauth/cleartext.c vauth/cram.c \ + vauth/digest.c vauth/digest_sspi.c vauth/krb5_gssapi.c \ + vauth/krb5_sspi.c vauth/ntlm.c vauth/ntlm_sspi.c vauth/oauth2.c \ + vauth/spnego_gssapi.c vauth/spnego_sspi.c + +LIB_VAUTH_HFILES = vauth/vauth.h vauth/digest.h vauth/ntlm.h + +LIB_VTLS_CFILES = vtls/openssl.c vtls/gtls.c vtls/vtls.c vtls/nss.c \ + vtls/polarssl.c vtls/polarssl_threadlock.c \ + vtls/cyassl.c vtls/schannel.c vtls/schannel_verify.c \ + vtls/sectransp.c vtls/gskit.c vtls/mbedtls.c vtls/mesalink.c + +LIB_VTLS_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h \ + vtls/nssg.h vtls/polarssl.h vtls/polarssl_threadlock.h \ + vtls/cyassl.h vtls/schannel.h vtls/sectransp.h vtls/gskit.h \ + vtls/mbedtls.h vtls/mesalink.h + +LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \ + cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c \ + ldap.c version.c getenv.c escape.c mprintf.c telnet.c netrc.c \ + getinfo.c transfer.c strcase.c easy.c security.c curl_fnmatch.c \ + fileinfo.c ftplistparser.c wildcard.c krb5.c memdebug.c http_chunks.c \ + strtok.c connect.c llist.c hash.c multi.c content_encoding.c share.c \ + http_digest.c md4.c md5.c http_negotiate.c inet_pton.c strtoofft.c \ + strerror.c amigaos.c hostasyn.c hostip4.c hostip6.c hostsyn.c \ + inet_ntop.c parsedate.c select.c tftp.c splay.c strdup.c socks.c \ + ssh.c ssh-libssh.c curl_addrinfo.c socks_gssapi.c socks_sspi.c \ + curl_sspi.c slist.c nonblock.c curl_memrchr.c imap.c pop3.c smtp.c \ + pingpong.c rtsp.c curl_threads.c warnless.c hmac.c curl_rtmp.c \ + openldap.c curl_gethostname.c gopher.c idn_win32.c \ + http_proxy.c non-ascii.c asyn-ares.c asyn-thread.c curl_gssapi.c \ + http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c rand.c \ + curl_multibyte.c hostcheck.c conncache.c dotdot.c \ + x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c \ + mime.c sha256.c setopt.c curl_path.c curl_ctype.c curl_range.c psl.c \ + doh.c urlapi.c curl_get_line.c altsvc.c + +LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \ + formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h \ + speedcheck.h urldata.h curl_ldap.h escape.h telnet.h getinfo.h \ + strcase.h curl_sec.h memdebug.h http_chunks.h curl_fnmatch.h \ + wildcard.h fileinfo.h ftplistparser.h strtok.h connect.h llist.h \ + hash.h content_encoding.h share.h curl_md4.h curl_md5.h http_digest.h \ + http_negotiate.h inet_pton.h amigaos.h strtoofft.h strerror.h \ + inet_ntop.h curlx.h curl_memory.h curl_setup.h transfer.h select.h \ + easyif.h multiif.h parsedate.h tftp.h sockaddr.h splay.h strdup.h \ + socks.h ssh.h curl_base64.h curl_addrinfo.h curl_sspi.h \ + slist.h nonblock.h curl_memrchr.h imap.h pop3.h smtp.h pingpong.h \ + rtsp.h curl_threads.h warnless.h curl_hmac.h curl_rtmp.h \ + curl_gethostname.h gopher.h http_proxy.h non-ascii.h asyn.h \ + http_ntlm.h curl_gssapi.h curl_ntlm_wb.h curl_ntlm_core.h \ + curl_sasl.h curl_multibyte.h hostcheck.h conncache.h \ + curl_setup_once.h multihandle.h setup-vms.h dotdot.h \ + x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h \ + curl_printf.h system_win32.h rand.h mime.h curl_sha256.h setopt.h \ + curl_path.h curl_ctype.h curl_range.h psl.h doh.h urlapi-int.h \ + curl_get_line.h altsvc.h + +LIB_RCFILES = libcurl.rc + +CSOURCES = $(LIB_CFILES) $(LIB_VAUTH_CFILES) $(LIB_VTLS_CFILES) +HHEADERS = $(LIB_HFILES) $(LIB_VAUTH_HFILES) $(LIB_VTLS_HFILES) diff --git a/dependencies/cmcurl/lib/altsvc.c b/dependencies/cmcurl/lib/altsvc.c new file mode 100644 index 0000000..85a4e01 --- /dev/null +++ b/dependencies/cmcurl/lib/altsvc.c @@ -0,0 +1,569 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +/* + * The Alt-Svc: header is defined in RFC 7838: + * https://tools.ietf.org/html/rfc7838 + */ +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_ALTSVC) +#include +#include "urldata.h" +#include "altsvc.h" +#include "curl_get_line.h" +#include "strcase.h" +#include "parsedate.h" +#include "sendf.h" +#include "warnless.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#define MAX_ALTSVC_LINE 4095 +#define MAX_ALTSVC_DATELENSTR "64" +#define MAX_ALTSVC_DATELEN 64 +#define MAX_ALTSVC_HOSTLENSTR "512" +#define MAX_ALTSVC_HOSTLEN 512 +#define MAX_ALTSVC_ALPNLENSTR "10" +#define MAX_ALTSVC_ALPNLEN 10 + +static enum alpnid alpn2alpnid(char *name) +{ + if(strcasecompare(name, "h1")) + return ALPN_h1; + if(strcasecompare(name, "h2")) + return ALPN_h2; + if(strcasecompare(name, "h2c")) + return ALPN_h2c; + if(strcasecompare(name, "h3")) + return ALPN_h3; + return ALPN_none; /* unknown, probably rubbish input */ +} + +/* Given the ALPN ID, return the name */ +const char *Curl_alpnid2str(enum alpnid id) +{ + switch(id) { + case ALPN_h1: + return "h1"; + case ALPN_h2: + return "h2"; + case ALPN_h2c: + return "h2c"; + case ALPN_h3: + return "h3"; + default: + return ""; /* bad */ + } +} + + +static void altsvc_free(struct altsvc *as) +{ + free(as->srchost); + free(as->dsthost); + free(as); +} + +static struct altsvc *altsvc_createid(const char *srchost, + const char *dsthost, + enum alpnid srcalpnid, + enum alpnid dstalpnid, + unsigned int srcport, + unsigned int dstport) +{ + struct altsvc *as = calloc(sizeof(struct altsvc), 1); + if(!as) + return NULL; + + as->srchost = strdup(srchost); + if(!as->srchost) + goto error; + as->dsthost = strdup(dsthost); + if(!as->dsthost) + goto error; + + as->srcalpnid = srcalpnid; + as->dstalpnid = dstalpnid; + as->srcport = curlx_ultous(srcport); + as->dstport = curlx_ultous(dstport); + + return as; + error: + altsvc_free(as); + return NULL; +} + +static struct altsvc *altsvc_create(char *srchost, + char *dsthost, + char *srcalpn, + char *dstalpn, + unsigned int srcport, + unsigned int dstport) +{ + enum alpnid dstalpnid = alpn2alpnid(dstalpn); + enum alpnid srcalpnid = alpn2alpnid(srcalpn); + if(!srcalpnid || !dstalpnid) + return NULL; + return altsvc_createid(srchost, dsthost, srcalpnid, dstalpnid, + srcport, dstport); +} + +/* only returns SERIOUS errors */ +static CURLcode altsvc_add(struct altsvcinfo *asi, char *line) +{ + /* Example line: + h2 example.com 443 h3 shiny.example.com 8443 "20191231 10:00:00" 1 + */ + char srchost[MAX_ALTSVC_HOSTLEN + 1]; + char dsthost[MAX_ALTSVC_HOSTLEN + 1]; + char srcalpn[MAX_ALTSVC_ALPNLEN + 1]; + char dstalpn[MAX_ALTSVC_ALPNLEN + 1]; + char date[MAX_ALTSVC_DATELEN + 1]; + unsigned int srcport; + unsigned int dstport; + unsigned int prio; + unsigned int persist; + int rc; + + rc = sscanf(line, + "%" MAX_ALTSVC_ALPNLENSTR "s %" MAX_ALTSVC_HOSTLENSTR "s %u " + "%" MAX_ALTSVC_ALPNLENSTR "s %" MAX_ALTSVC_HOSTLENSTR "s %u " + "\"%" MAX_ALTSVC_DATELENSTR "[^\"]\" %u %u", + srcalpn, srchost, &srcport, + dstalpn, dsthost, &dstport, + date, &persist, &prio); + if(9 == rc) { + struct altsvc *as; + time_t expires = curl_getdate(date, NULL); + as = altsvc_create(srchost, dsthost, srcalpn, dstalpn, srcport, dstport); + if(as) { + as->expires = expires; + as->prio = prio; + as->persist = persist ? 1 : 0; + Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node); + asi->num++; /* one more entry */ + } + } + + return CURLE_OK; +} + +/* + * Load alt-svc entries from the given file. The text based line-oriented file + * format is documented here: + * https://github.com/curl/curl/wiki/QUIC-implementation + * + * This function only returns error on major problems that prevents alt-svc + * handling to work completely. It will ignore individual syntactical errors + * etc. + */ +static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file) +{ + CURLcode result = CURLE_OK; + char *line = NULL; + FILE *fp = fopen(file, FOPEN_READTEXT); + if(fp) { + line = malloc(MAX_ALTSVC_LINE); + if(!line) + goto fail; + while(Curl_get_line(line, MAX_ALTSVC_LINE, fp)) { + char *lineptr = line; + while(*lineptr && ISBLANK(*lineptr)) + lineptr++; + if(*lineptr == '#') + /* skip commented lines */ + continue; + + altsvc_add(asi, lineptr); + } + free(line); /* free the line buffer */ + fclose(fp); + } + return result; + + fail: + free(line); + fclose(fp); + return CURLE_OUT_OF_MEMORY; +} + +/* + * Write this single altsvc entry to a single output line + */ + +static CURLcode altsvc_out(struct altsvc *as, FILE *fp) +{ + struct tm stamp; + CURLcode result = Curl_gmtime(as->expires, &stamp); + if(result) + return result; + + fprintf(fp, + "%s %s %u " + "%s %s %u " + "\"%d%02d%02d " + "%02d:%02d:%02d\" " + "%u %d\n", + Curl_alpnid2str(as->srcalpnid), as->srchost, as->srcport, + Curl_alpnid2str(as->dstalpnid), as->dsthost, as->dstport, + stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday, + stamp.tm_hour, stamp.tm_min, stamp.tm_sec, + as->persist, as->prio); + return CURLE_OK; +} + +/* ---- library-wide functions below ---- */ + +/* + * Curl_altsvc_init() creates a new altsvc cache. + * It returns the new instance or NULL if something goes wrong. + */ +struct altsvcinfo *Curl_altsvc_init(void) +{ + struct altsvcinfo *asi = calloc(sizeof(struct altsvcinfo), 1); + if(!asi) + return NULL; + Curl_llist_init(&asi->list, NULL); + + /* set default behavior */ + asi->flags = CURLALTSVC_H1 +#ifdef USE_NGHTTP2 + | CURLALTSVC_H2 +#endif +#ifdef USE_HTTP3 + | CURLALTSVC_H3 +#endif + ; + return asi; +} + +/* + * Curl_altsvc_load() loads alt-svc from file. + */ +CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file) +{ + CURLcode result; + DEBUGASSERT(asi); + result = altsvc_load(asi, file); + return result; +} + +/* + * Curl_altsvc_ctrl() passes on the external bitmask. + */ +CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl) +{ + DEBUGASSERT(asi); + if(!ctrl) + /* unexpected */ + return CURLE_BAD_FUNCTION_ARGUMENT; + asi->flags = ctrl; + return CURLE_OK; +} + +/* + * Curl_altsvc_cleanup() frees an altsvc cache instance and all associated + * resources. + */ +void Curl_altsvc_cleanup(struct altsvcinfo *altsvc) +{ + struct curl_llist_element *e; + struct curl_llist_element *n; + if(altsvc) { + for(e = altsvc->list.head; e; e = n) { + struct altsvc *as = e->ptr; + n = e->next; + altsvc_free(as); + } + free(altsvc); + } +} + +/* + * Curl_altsvc_save() writes the altsvc cache to a file. + */ +CURLcode Curl_altsvc_save(struct altsvcinfo *altsvc, const char *file) +{ + struct curl_llist_element *e; + struct curl_llist_element *n; + CURLcode result = CURLE_OK; + FILE *out; + + if(!altsvc) + /* no cache activated */ + return CURLE_OK; + + if((altsvc->flags & CURLALTSVC_READONLYFILE) || !file[0]) + /* marked as read-only or zero length file name */ + return CURLE_OK; + out = fopen(file, FOPEN_WRITETEXT); + if(!out) + return CURLE_WRITE_ERROR; + fputs("# Your alt-svc cache. https://curl.haxx.se/docs/alt-svc.html\n" + "# This file was generated by libcurl! Edit at your own risk.\n", + out); + for(e = altsvc->list.head; e; e = n) { + struct altsvc *as = e->ptr; + n = e->next; + result = altsvc_out(as, out); + if(result) + break; + } + fclose(out); + return result; +} + +static CURLcode getalnum(const char **ptr, char *alpnbuf, size_t buflen) +{ + size_t len; + const char *protop; + const char *p = *ptr; + while(*p && ISBLANK(*p)) + p++; + protop = p; + while(*p && ISALNUM(*p)) + p++; + len = p - protop; + + if(!len || (len >= buflen)) + return CURLE_BAD_FUNCTION_ARGUMENT; + memcpy(alpnbuf, protop, len); + alpnbuf[len] = 0; + *ptr = p; + return CURLE_OK; +} + +/* altsvc_flush() removes all alternatives for this source origin from the + list */ +static void altsvc_flush(struct altsvcinfo *asi, enum alpnid srcalpnid, + const char *srchost, unsigned short srcport) +{ + struct curl_llist_element *e; + struct curl_llist_element *n; + for(e = asi->list.head; e; e = n) { + struct altsvc *as = e->ptr; + n = e->next; + if((srcalpnid == as->srcalpnid) && + (srcport == as->srcport) && + strcasecompare(srchost, as->srchost)) { + Curl_llist_remove(&asi->list, e, NULL); + altsvc_free(as); + asi->num--; + } + } +} + +#ifdef DEBUGBUILD +/* to play well with debug builds, we can *set* a fixed time this will + return */ +static time_t debugtime(void *unused) +{ + char *timestr = getenv("CURL_TIME"); + (void)unused; + if(timestr) { + unsigned long val = strtol(timestr, NULL, 10); + return (time_t)val; + } + return time(NULL); +} +#define time(x) debugtime(x) +#endif + +/* + * Curl_altsvc_parse() takes an incoming alt-svc response header and stores + * the data correctly in the cache. + * + * 'value' points to the header *value*. That's contents to the right of the + * header name. + */ +CURLcode Curl_altsvc_parse(struct Curl_easy *data, + struct altsvcinfo *asi, const char *value, + enum alpnid srcalpnid, const char *srchost, + unsigned short srcport) +{ + const char *p = value; + size_t len; + enum alpnid dstalpnid = srcalpnid; /* the same by default */ + char namebuf[MAX_ALTSVC_HOSTLEN] = ""; + char alpnbuf[MAX_ALTSVC_ALPNLEN] = ""; + struct altsvc *as; + unsigned short dstport = srcport; /* the same by default */ + const char *semip; + time_t maxage = 24 * 3600; /* default is 24 hours */ + bool persist = FALSE; + CURLcode result = getalnum(&p, alpnbuf, sizeof(alpnbuf)); + if(result) + return result; + + DEBUGASSERT(asi); + + /* Flush all cached alternatives for this source origin, if any */ + altsvc_flush(asi, srcalpnid, srchost, srcport); + + /* "clear" is a magic keyword */ + if(strcasecompare(alpnbuf, "clear")) { + return CURLE_OK; + } + + /* The 'ma' and 'persist' flags are annoyingly meant for all alternatives + but are set after the list on the line. Scan for the semicolons and get + those fields first! */ + semip = p; + do { + semip = strchr(semip, ';'); + if(semip) { + char option[32]; + unsigned long num; + char *end_ptr; + semip++; /* pass the semicolon */ + result = getalnum(&semip, option, sizeof(option)); + if(result) + break; + while(*semip && ISBLANK(*semip)) + semip++; + if(*semip != '=') + continue; + semip++; + num = strtoul(semip, &end_ptr, 10); + if(num < ULONG_MAX) { + if(strcasecompare("ma", option)) + maxage = num; + else if(strcasecompare("persist", option) && (num == 1)) + persist = TRUE; + } + semip = end_ptr; + } + } while(semip); + + do { + if(*p == '=') { + /* [protocol]="[host][:port]" */ + dstalpnid = alpn2alpnid(alpnbuf); + if(!dstalpnid) { + infof(data, "Unknown alt-svc protocol \"%s\", ignoring...\n", alpnbuf); + return CURLE_OK; + } + p++; + if(*p == '\"') { + const char *dsthost; + p++; + if(*p != ':') { + /* host name starts here */ + const char *hostp = p; + while(*p && (ISALNUM(*p) || (*p == '.') || (*p == '-'))) + p++; + len = p - hostp; + if(!len || (len >= MAX_ALTSVC_HOSTLEN)) + return CURLE_BAD_FUNCTION_ARGUMENT; + memcpy(namebuf, hostp, len); + namebuf[len] = 0; + dsthost = namebuf; + } + else { + /* no destination name, use source host */ + dsthost = srchost; + } + if(*p == ':') { + /* a port number */ + char *end_ptr; + unsigned long port = strtoul(++p, &end_ptr, 10); + if(port > USHRT_MAX || end_ptr == p || *end_ptr != '\"') { + infof(data, "Unknown alt-svc port number, ignoring...\n"); + return CURLE_OK; + } + p = end_ptr; + dstport = curlx_ultous(port); + } + if(*p++ != '\"') + return CURLE_BAD_FUNCTION_ARGUMENT; + as = altsvc_createid(srchost, dsthost, + srcalpnid, dstalpnid, + srcport, dstport); + if(as) { + /* The expires time also needs to take the Age: value (if any) into + account. [See RFC 7838 section 3.1] */ + as->expires = maxage + time(NULL); + as->persist = persist; + Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node); + asi->num++; /* one more entry */ + infof(data, "Added alt-svc: %s:%d over %s\n", dsthost, dstport, + Curl_alpnid2str(dstalpnid)); + } + } + /* after the double quote there can be a comma if there's another + string or a semicolon if no more */ + if(*p == ',') { + /* comma means another alternative is presented */ + p++; + result = getalnum(&p, alpnbuf, sizeof(alpnbuf)); + if(result) + /* failed to parse, but since we already did at least one host we + return OK */ + return CURLE_OK; + } + } + } while(*p && (*p != ';') && (*p != '\n') && (*p != '\r')); + + return CURLE_OK; +} + +/* + * Return TRUE on a match + */ +bool Curl_altsvc_lookup(struct altsvcinfo *asi, + enum alpnid srcalpnid, const char *srchost, + int srcport, + enum alpnid *dstalpnid, const char **dsthost, + int *dstport) +{ + struct curl_llist_element *e; + struct curl_llist_element *n; + time_t now = time(NULL); + DEBUGASSERT(asi); + DEBUGASSERT(srchost); + DEBUGASSERT(dsthost); + + for(e = asi->list.head; e; e = n) { + struct altsvc *as = e->ptr; + n = e->next; + if(as->expires < now) { + /* an expired entry, remove */ + altsvc_free(as); + continue; + } + if((as->srcalpnid == srcalpnid) && + strcasecompare(as->srchost, srchost) && + as->srcport == srcport) { + /* match */ + *dstalpnid = as->dstalpnid; + *dsthost = as->dsthost; + *dstport = as->dstport; + return TRUE; + } + } + return FALSE; +} + +#endif /* CURL_DISABLE_HTTP || USE_ALTSVC */ diff --git a/dependencies/cmcurl/lib/altsvc.h b/dependencies/cmcurl/lib/altsvc.h new file mode 100644 index 0000000..eefb45b --- /dev/null +++ b/dependencies/cmcurl/lib/altsvc.h @@ -0,0 +1,77 @@ +#ifndef HEADER_CURL_ALTSVC_H +#define HEADER_CURL_ALTSVC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_ALTSVC) +#include +#include "llist.h" + +enum alpnid { + ALPN_none, + ALPN_h1, + ALPN_h2, + ALPN_h2c, + ALPN_h3 +}; + +struct altsvc { + char *srchost; + char *dsthost; + unsigned short srcport; + unsigned short dstport; + enum alpnid srcalpnid; + enum alpnid dstalpnid; + time_t expires; + bool persist; + int prio; + struct curl_llist_element node; +}; + +struct altsvcinfo { + char *filename; + struct curl_llist list; /* list of entries */ + size_t num; /* number of alt-svc entries */ + long flags; /* the publicly set bitmask */ +}; + +const char *Curl_alpnid2str(enum alpnid id); +struct altsvcinfo *Curl_altsvc_init(void); +CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file); +CURLcode Curl_altsvc_save(struct altsvcinfo *asi, const char *file); +CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl); +void Curl_altsvc_cleanup(struct altsvcinfo *altsvc); +CURLcode Curl_altsvc_parse(struct Curl_easy *data, + struct altsvcinfo *altsvc, const char *value, + enum alpnid srcalpn, const char *srchost, + unsigned short srcport); +bool Curl_altsvc_lookup(struct altsvcinfo *asi, + enum alpnid srcalpnid, const char *srchost, + int srcport, + enum alpnid *dstalpnid, const char **dsthost, + int *dstport); +#else +/* disabled */ +#define Curl_altsvc_save(a,b) +#endif /* CURL_DISABLE_HTTP || USE_ALTSVC */ +#endif /* HEADER_CURL_ALTSVC_H */ diff --git a/dependencies/cmcurl/lib/amigaos.c b/dependencies/cmcurl/lib/amigaos.c new file mode 100644 index 0000000..cf44bdc --- /dev/null +++ b/dependencies/cmcurl/lib/amigaos.c @@ -0,0 +1,95 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef __AMIGA__ +# include "amigaos.h" +# if defined(HAVE_PROTO_BSDSOCKET_H) && !defined(USE_AMISSL) +# include +# endif +# ifdef __libnix__ +# include +# endif +#endif + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#ifdef __AMIGA__ +#if defined(HAVE_PROTO_BSDSOCKET_H) && !defined(USE_AMISSL) +struct Library *SocketBase = NULL; +extern int errno, h_errno; + +#ifdef __libnix__ +void __request(const char *msg); +#else +# define __request(msg) Printf(msg "\n\a") +#endif + +void Curl_amiga_cleanup() +{ + if(SocketBase) { + CloseLibrary(SocketBase); + SocketBase = NULL; + } +} + +bool Curl_amiga_init() +{ + if(!SocketBase) + SocketBase = OpenLibrary("bsdsocket.library", 4); + + if(!SocketBase) { + __request("No TCP/IP Stack running!"); + return FALSE; + } + + if(SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (ULONG) &errno, + SBTM_SETVAL(SBTC_LOGTAGPTR), (ULONG) "curl", + TAG_DONE)) { + __request("SocketBaseTags ERROR"); + return FALSE; + } + +#ifndef __libnix__ + atexit(Curl_amiga_cleanup); +#endif + + return TRUE; +} + +#ifdef __libnix__ +ADD2EXIT(Curl_amiga_cleanup, -50); +#endif + +#endif /* HAVE_PROTO_BSDSOCKET_H */ + +#ifdef USE_AMISSL +void Curl_amiga_X509_free(X509 *a) +{ + X509_free(a); +} +#endif /* USE_AMISSL */ +#endif /* __AMIGA__ */ + diff --git a/dependencies/cmcurl/lib/amigaos.h b/dependencies/cmcurl/lib/amigaos.h new file mode 100644 index 0000000..c776c9c --- /dev/null +++ b/dependencies/cmcurl/lib/amigaos.h @@ -0,0 +1,44 @@ +#ifndef HEADER_CURL_AMIGAOS_H +#define HEADER_CURL_AMIGAOS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if defined(__AMIGA__) && defined(HAVE_BSDSOCKET_H) && !defined(USE_AMISSL) + +bool Curl_amiga_init(); +void Curl_amiga_cleanup(); + +#else + +#define Curl_amiga_init() 1 +#define Curl_amiga_cleanup() Curl_nop_stmt + +#endif + +#ifdef USE_AMISSL +#include +void Curl_amiga_X509_free(X509 *a); +#endif /* USE_AMISSL */ + +#endif /* HEADER_CURL_AMIGAOS_H */ + diff --git a/dependencies/cmcurl/lib/arpa_telnet.h b/dependencies/cmcurl/lib/arpa_telnet.h new file mode 100644 index 0000000..232680e --- /dev/null +++ b/dependencies/cmcurl/lib/arpa_telnet.h @@ -0,0 +1,108 @@ +#ifndef HEADER_CURL_ARPA_TELNET_H +#define HEADER_CURL_ARPA_TELNET_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifndef CURL_DISABLE_TELNET +/* + * Telnet option defines. Add more here if in need. + */ +#define CURL_TELOPT_BINARY 0 /* binary 8bit data */ +#define CURL_TELOPT_ECHO 1 /* just echo! */ +#define CURL_TELOPT_SGA 3 /* Suppress Go Ahead */ +#define CURL_TELOPT_EXOPL 255 /* EXtended OPtions List */ +#define CURL_TELOPT_TTYPE 24 /* Terminal TYPE */ +#define CURL_TELOPT_NAWS 31 /* Negotiate About Window Size */ +#define CURL_TELOPT_XDISPLOC 35 /* X DISPlay LOCation */ + +#define CURL_TELOPT_NEW_ENVIRON 39 /* NEW ENVIRONment variables */ +#define CURL_NEW_ENV_VAR 0 +#define CURL_NEW_ENV_VALUE 1 + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +/* + * The telnet options represented as strings + */ +static const char * const telnetoptions[]= +{ + "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", + "NAME", "STATUS", "TIMING MARK", "RCTE", + "NAOL", "NAOP", "NAOCRD", "NAOHTS", + "NAOHTD", "NAOFFD", "NAOVTS", "NAOVTD", + "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO", + "DE TERMINAL", "SUPDUP", "SUPDUP OUTPUT", "SEND LOCATION", + "TERM TYPE", "END OF RECORD", "TACACS UID", "OUTPUT MARKING", + "TTYLOC", "3270 REGIME", "X3 PAD", "NAWS", + "TERM SPEED", "LFLOW", "LINEMODE", "XDISPLOC", + "OLD-ENVIRON", "AUTHENTICATION", "ENCRYPT", "NEW-ENVIRON" +}; +#endif + +#define CURL_TELOPT_MAXIMUM CURL_TELOPT_NEW_ENVIRON + +#define CURL_TELOPT_OK(x) ((x) <= CURL_TELOPT_MAXIMUM) +#define CURL_TELOPT(x) telnetoptions[x] + +#define CURL_NTELOPTS 40 + +/* + * First some defines + */ +#define CURL_xEOF 236 /* End Of File */ +#define CURL_SE 240 /* Sub negotiation End */ +#define CURL_NOP 241 /* No OPeration */ +#define CURL_DM 242 /* Data Mark */ +#define CURL_GA 249 /* Go Ahead, reverse the line */ +#define CURL_SB 250 /* SuBnegotiation */ +#define CURL_WILL 251 /* Our side WILL use this option */ +#define CURL_WONT 252 /* Our side WON'T use this option */ +#define CURL_DO 253 /* DO use this option! */ +#define CURL_DONT 254 /* DON'T use this option! */ +#define CURL_IAC 255 /* Interpret As Command */ + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +/* + * Then those numbers represented as strings: + */ +static const char * const telnetcmds[]= +{ + "EOF", "SUSP", "ABORT", "EOR", "SE", + "NOP", "DMARK", "BRK", "IP", "AO", + "AYT", "EC", "EL", "GA", "SB", + "WILL", "WONT", "DO", "DONT", "IAC" +}; +#endif + +#define CURL_TELCMD_MINIMUM CURL_xEOF /* the first one */ +#define CURL_TELCMD_MAXIMUM CURL_IAC /* surprise, 255 is the last one! ;-) */ + +#define CURL_TELQUAL_IS 0 +#define CURL_TELQUAL_SEND 1 +#define CURL_TELQUAL_INFO 2 +#define CURL_TELQUAL_NAME 3 + +#define CURL_TELCMD_OK(x) ( ((unsigned int)(x) >= CURL_TELCMD_MINIMUM) && \ + ((unsigned int)(x) <= CURL_TELCMD_MAXIMUM) ) +#define CURL_TELCMD(x) telnetcmds[(x)-CURL_TELCMD_MINIMUM] + +#endif /* CURL_DISABLE_TELNET */ + +#endif /* HEADER_CURL_ARPA_TELNET_H */ diff --git a/dependencies/cmcurl/lib/asyn-ares.c b/dependencies/cmcurl/lib/asyn-ares.c new file mode 100644 index 0000000..8561a47 --- /dev/null +++ b/dependencies/cmcurl/lib/asyn-ares.c @@ -0,0 +1,826 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +/*********************************************************************** + * Only for ares-enabled builds + * And only for functions that fulfill the asynch resolver backend API + * as defined in asyn.h, nothing else belongs in this file! + **********************************************************************/ + +#ifdef CURLRES_ARES + +#include +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#ifdef HAVE_PROCESS_H +#include +#endif + +#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "hash.h" +#include "share.h" +#include "strerror.h" +#include "url.h" +#include "multiif.h" +#include "inet_pton.h" +#include "connect.h" +#include "select.h" +#include "progress.h" + +# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \ + (defined(WIN32) || defined(__SYMBIAN32__)) +# define CARES_STATICLIB +# endif +# include +# include /* really old c-ares didn't include this by + itself */ + +#if ARES_VERSION >= 0x010500 +/* c-ares 1.5.0 or later, the callback proto is modified */ +#define HAVE_CARES_CALLBACK_TIMEOUTS 1 +#endif + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +struct ResolverResults { + int num_pending; /* number of ares_gethostbyname() requests */ + Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares parts */ + int last_status; + struct curltime happy_eyeballs_dns_time; /* when this timer started, or 0 */ +}; + +/* How long we are willing to wait for additional parallel responses after + obtaining a "definitive" one. + + This is intended to equal the c-ares default timeout. cURL always uses that + default value. Unfortunately, c-ares doesn't expose its default timeout in + its API, but it is officially documented as 5 seconds. + + See query_completed_cb() for an explanation of how this is used. + */ +#define HAPPY_EYEBALLS_DNS_TIMEOUT 5000 + +/* + * Curl_resolver_global_init() - the generic low-level asynchronous name + * resolve API. Called from curl_global_init() to initialize global resolver + * environment. Initializes ares library. + */ +int Curl_resolver_global_init(void) +{ +#ifdef CARES_HAVE_ARES_LIBRARY_INIT + if(ares_library_init(ARES_LIB_INIT_ALL)) { + return CURLE_FAILED_INIT; + } +#endif + return CURLE_OK; +} + +/* + * Curl_resolver_global_cleanup() + * + * Called from curl_global_cleanup() to destroy global resolver environment. + * Deinitializes ares library. + */ +void Curl_resolver_global_cleanup(void) +{ +#ifdef CARES_HAVE_ARES_LIBRARY_CLEANUP + ares_library_cleanup(); +#endif +} + + +static void Curl_ares_sock_state_cb(void *data, ares_socket_t socket_fd, + int readable, int writable) +{ + struct Curl_easy *easy = data; + if(!readable && !writable) { + DEBUGASSERT(easy); + Curl_multi_closed(easy, socket_fd); + } +} + +/* + * Curl_resolver_init() + * + * Called from curl_easy_init() -> Curl_open() to initialize resolver + * URL-state specific environment ('resolver' member of the UrlState + * structure). Fills the passed pointer by the initialized ares_channel. + */ +CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver) +{ + int status; + struct ares_options options; + int optmask = ARES_OPT_SOCK_STATE_CB; + options.sock_state_cb = Curl_ares_sock_state_cb; + options.sock_state_cb_data = easy; + status = ares_init_options((ares_channel*)resolver, &options, optmask); + if(status != ARES_SUCCESS) { + if(status == ARES_ENOMEM) + return CURLE_OUT_OF_MEMORY; + else + return CURLE_FAILED_INIT; + } + return CURLE_OK; + /* make sure that all other returns from this function should destroy the + ares channel before returning error! */ +} + +/* + * Curl_resolver_cleanup() + * + * Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver + * URL-state specific environment ('resolver' member of the UrlState + * structure). Destroys the ares channel. + */ +void Curl_resolver_cleanup(void *resolver) +{ + ares_destroy((ares_channel)resolver); +} + +/* + * Curl_resolver_duphandle() + * + * Called from curl_easy_duphandle() to duplicate resolver URL-state specific + * environment ('resolver' member of the UrlState structure). Duplicates the + * 'from' ares channel and passes the resulting channel to the 'to' pointer. + */ +CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to, void *from) +{ + (void)from; + /* + * it would be better to call ares_dup instead, but right now + * it is not possible to set 'sock_state_cb_data' outside of + * ares_init_options + */ + return Curl_resolver_init(easy, to); +} + +static void destroy_async_data(struct Curl_async *async); + +/* + * Cancel all possibly still on-going resolves for this connection. + */ +void Curl_resolver_cancel(struct connectdata *conn) +{ + if(conn->data && conn->data->state.resolver) + ares_cancel((ares_channel)conn->data->state.resolver); + destroy_async_data(&conn->async); +} + +/* + * We're equivalent to Curl_resolver_cancel() for the c-ares resolver. We + * never block. + */ +void Curl_resolver_kill(struct connectdata *conn) +{ + /* We don't need to check the resolver state because we can be called safely + at any time and we always do the same thing. */ + Curl_resolver_cancel(conn); +} + +/* + * destroy_async_data() cleans up async resolver data. + */ +static void destroy_async_data(struct Curl_async *async) +{ + free(async->hostname); + + if(async->os_specific) { + struct ResolverResults *res = (struct ResolverResults *)async->os_specific; + if(res) { + if(res->temp_ai) { + Curl_freeaddrinfo(res->temp_ai); + res->temp_ai = NULL; + } + free(res); + } + async->os_specific = NULL; + } + + async->hostname = NULL; +} + +/* + * Curl_resolver_getsock() is called when someone from the outside world + * (using curl_multi_fdset()) wants to get our fd_set setup and we're talking + * with ares. The caller must make sure that this function is only called when + * we have a working ares channel. + * + * Returns: sockets-in-use-bitmap + */ + +int Curl_resolver_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) + +{ + struct timeval maxtime; + struct timeval timebuf; + struct timeval *timeout; + long milli; + int max = ares_getsock((ares_channel)conn->data->state.resolver, + (ares_socket_t *)socks, numsocks); + + maxtime.tv_sec = CURL_TIMEOUT_RESOLVE; + maxtime.tv_usec = 0; + + timeout = ares_timeout((ares_channel)conn->data->state.resolver, &maxtime, + &timebuf); + milli = (timeout->tv_sec * 1000) + (timeout->tv_usec/1000); + if(milli == 0) + milli += 10; + Curl_expire(conn->data, milli, EXPIRE_ASYNC_NAME); + + return max; +} + +/* + * waitperform() + * + * 1) Ask ares what sockets it currently plays with, then + * 2) wait for the timeout period to check for action on ares' sockets. + * 3) tell ares to act on all the sockets marked as "with action" + * + * return number of sockets it worked on + */ + +static int waitperform(struct connectdata *conn, int timeout_ms) +{ + struct Curl_easy *data = conn->data; + int nfds; + int bitmask; + ares_socket_t socks[ARES_GETSOCK_MAXNUM]; + struct pollfd pfd[ARES_GETSOCK_MAXNUM]; + int i; + int num = 0; + + bitmask = ares_getsock((ares_channel)data->state.resolver, socks, + ARES_GETSOCK_MAXNUM); + + for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) { + pfd[i].events = 0; + pfd[i].revents = 0; + if(ARES_GETSOCK_READABLE(bitmask, i)) { + pfd[i].fd = socks[i]; + pfd[i].events |= POLLRDNORM|POLLIN; + } + if(ARES_GETSOCK_WRITABLE(bitmask, i)) { + pfd[i].fd = socks[i]; + pfd[i].events |= POLLWRNORM|POLLOUT; + } + if(pfd[i].events != 0) + num++; + else + break; + } + + if(num) + nfds = Curl_poll(pfd, num, timeout_ms); + else + nfds = 0; + + if(!nfds) + /* Call ares_process() unconditonally here, even if we simply timed out + above, as otherwise the ares name resolve won't timeout! */ + ares_process_fd((ares_channel)data->state.resolver, ARES_SOCKET_BAD, + ARES_SOCKET_BAD); + else { + /* move through the descriptors and ask for processing on them */ + for(i = 0; i < num; i++) + ares_process_fd((ares_channel)data->state.resolver, + (pfd[i].revents & (POLLRDNORM|POLLIN))? + pfd[i].fd:ARES_SOCKET_BAD, + (pfd[i].revents & (POLLWRNORM|POLLOUT))? + pfd[i].fd:ARES_SOCKET_BAD); + } + return nfds; +} + +/* + * Curl_resolver_is_resolved() is called repeatedly to check if a previous + * name resolve request has completed. It should also make sure to time-out if + * the operation seems to take too long. + * + * Returns normal CURLcode errors. + */ +CURLcode Curl_resolver_is_resolved(struct connectdata *conn, + struct Curl_dns_entry **dns) +{ + struct Curl_easy *data = conn->data; + struct ResolverResults *res = (struct ResolverResults *) + conn->async.os_specific; + CURLcode result = CURLE_OK; + + if(dns) + *dns = NULL; + + waitperform(conn, 0); + + /* Now that we've checked for any last minute results above, see if there are + any responses still pending when the EXPIRE_HAPPY_EYEBALLS_DNS timer + expires. */ + if(res + && res->num_pending + /* This is only set to non-zero if the timer was started. */ + && (res->happy_eyeballs_dns_time.tv_sec + || res->happy_eyeballs_dns_time.tv_usec) + && (Curl_timediff(Curl_now(), res->happy_eyeballs_dns_time) + >= HAPPY_EYEBALLS_DNS_TIMEOUT)) { + /* Remember that the EXPIRE_HAPPY_EYEBALLS_DNS timer is no longer + running. */ + memset( + &res->happy_eyeballs_dns_time, 0, sizeof(res->happy_eyeballs_dns_time)); + + /* Cancel the raw c-ares request, which will fire query_completed_cb() with + ARES_ECANCELLED synchronously for all pending responses. This will + leave us with res->num_pending == 0, which is perfect for the next + block. */ + ares_cancel((ares_channel)data->state.resolver); + DEBUGASSERT(res->num_pending == 0); + } + + if(res && !res->num_pending) { + if(dns) { + (void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai); + /* temp_ai ownership is moved to the connection, so we need not free-up + them */ + res->temp_ai = NULL; + } + if(!conn->async.dns) { + failf(data, "Could not resolve: %s (%s)", + conn->async.hostname, ares_strerror(conn->async.status)); + result = conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY: + CURLE_COULDNT_RESOLVE_HOST; + } + else if(dns) + *dns = conn->async.dns; + + destroy_async_data(&conn->async); + } + + return result; +} + +/* + * Curl_resolver_wait_resolv() + * + * Waits for a resolve to finish. This function should be avoided since using + * this risk getting the multi interface to "hang". + * + * If 'entry' is non-NULL, make it point to the resolved dns entry + * + * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, + * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors. + */ +CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, + struct Curl_dns_entry **entry) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + timediff_t timeout; + struct curltime now = Curl_now(); + struct Curl_dns_entry *temp_entry; + + if(entry) + *entry = NULL; /* clear on entry */ + + timeout = Curl_timeleft(data, &now, TRUE); + if(timeout < 0) { + /* already expired! */ + connclose(conn, "Timed out before name resolve started"); + return CURLE_OPERATION_TIMEDOUT; + } + if(!timeout) + timeout = CURL_TIMEOUT_RESOLVE * 1000; /* default name resolve timeout */ + + /* Wait for the name resolve query to complete. */ + while(!result) { + struct timeval *tvp, tv, store; + int itimeout; + int timeout_ms; + + itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeout; + + store.tv_sec = itimeout/1000; + store.tv_usec = (itimeout%1000)*1000; + + tvp = ares_timeout((ares_channel)data->state.resolver, &store, &tv); + + /* use the timeout period ares returned to us above if less than one + second is left, otherwise just use 1000ms to make sure the progress + callback gets called frequent enough */ + if(!tvp->tv_sec) + timeout_ms = (int)(tvp->tv_usec/1000); + else + timeout_ms = 1000; + + waitperform(conn, timeout_ms); + result = Curl_resolver_is_resolved(conn, entry?&temp_entry:NULL); + + if(result || conn->async.done) + break; + + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + else { + struct curltime now2 = Curl_now(); + timediff_t timediff = Curl_timediff(now2, now); /* spent time */ + if(timediff <= 0) + timeout -= 1; /* always deduct at least 1 */ + else if(timediff > timeout) + timeout = -1; + else + timeout -= (long)timediff; + now = now2; /* for next loop */ + } + if(timeout < 0) + result = CURLE_OPERATION_TIMEDOUT; + } + if(result) + /* failure, so we cancel the ares operation */ + ares_cancel((ares_channel)data->state.resolver); + + /* Operation complete, if the lookup was successful we now have the entry + in the cache. */ + if(entry) + *entry = conn->async.dns; + + if(result) + /* close the connection, since we can't return failure here without + cleaning up this connection properly. */ + connclose(conn, "c-ares resolve failed"); + + return result; +} + +/* Connects results to the list */ +static void compound_results(struct ResolverResults *res, + Curl_addrinfo *ai) +{ + Curl_addrinfo *ai_tail; + if(!ai) + return; + ai_tail = ai; + + while(ai_tail->ai_next) + ai_tail = ai_tail->ai_next; + + /* Add the new results to the list of old results. */ + ai_tail->ai_next = res->temp_ai; + res->temp_ai = ai; +} + +/* + * ares_query_completed_cb() is the callback that ares will call when + * the host query initiated by ares_gethostbyname() from Curl_getaddrinfo(), + * when using ares, is completed either successfully or with failure. + */ +static void query_completed_cb(void *arg, /* (struct connectdata *) */ + int status, +#ifdef HAVE_CARES_CALLBACK_TIMEOUTS + int timeouts, +#endif + struct hostent *hostent) +{ + struct connectdata *conn = (struct connectdata *)arg; + struct ResolverResults *res; + +#ifdef HAVE_CARES_CALLBACK_TIMEOUTS + (void)timeouts; /* ignored */ +#endif + + if(ARES_EDESTRUCTION == status) + /* when this ares handle is getting destroyed, the 'arg' pointer may not + be valid so only defer it when we know the 'status' says its fine! */ + return; + + res = (struct ResolverResults *)conn->async.os_specific; + if(res) { + res->num_pending--; + + if(CURL_ASYNC_SUCCESS == status) { + Curl_addrinfo *ai = Curl_he2ai(hostent, conn->async.port); + if(ai) { + compound_results(res, ai); + } + } + /* A successful result overwrites any previous error */ + if(res->last_status != ARES_SUCCESS) + res->last_status = status; + + /* If there are responses still pending, we presume they must be the + complementary IPv4 or IPv6 lookups that we started in parallel in + Curl_resolver_getaddrinfo() (for Happy Eyeballs). If we've got a + "definitive" response from one of a set of parallel queries, we need to + think about how long we're willing to wait for more responses. */ + if(res->num_pending + /* Only these c-ares status values count as "definitive" for these + purposes. For example, ARES_ENODATA is what we expect when there is + no IPv6 entry for a domain name, and that's not a reason to get more + aggressive in our timeouts for the other response. Other errors are + either a result of bad input (which should affect all parallel + requests), local or network conditions, non-definitive server + responses, or us cancelling the request. */ + && (status == ARES_SUCCESS || status == ARES_ENOTFOUND)) { + /* Right now, there can only be up to two parallel queries, so don't + bother handling any other cases. */ + DEBUGASSERT(res->num_pending == 1); + + /* It's possible that one of these parallel queries could succeed + quickly, but the other could always fail or timeout (when we're + talking to a pool of DNS servers that can only successfully resolve + IPv4 address, for example). + + It's also possible that the other request could always just take + longer because it needs more time or only the second DNS server can + fulfill it successfully. But, to align with the philosophy of Happy + Eyeballs, we don't want to wait _too_ long or users will think + requests are slow when IPv6 lookups don't actually work (but IPv4 ones + do). + + So, now that we have a usable answer (some IPv4 addresses, some IPv6 + addresses, or "no such domain"), we start a timeout for the remaining + pending responses. Even though it is typical that this resolved + request came back quickly, that needn't be the case. It might be that + this completing request didn't get a result from the first DNS server + or even the first round of the whole DNS server pool. So it could + already be quite some time after we issued the DNS queries in the + first place. Without modifying c-ares, we can't know exactly where in + its retry cycle we are. We could guess based on how much time has + gone by, but it doesn't really matter. Happy Eyeballs tells us that, + given usable information in hand, we simply don't want to wait "too + much longer" after we get a result. + + We simply wait an additional amount of time equal to the default + c-ares query timeout. That is enough time for a typical parallel + response to arrive without being "too long". Even on a network + where one of the two types of queries is failing or timing out + constantly, this will usually mean we wait a total of the default + c-ares timeout (5 seconds) plus the round trip time for the successful + request, which seems bearable. The downside is that c-ares might race + with us to issue one more retry just before we give up, but it seems + better to "waste" that request instead of trying to guess the perfect + timeout to prevent it. After all, we don't even know where in the + c-ares retry cycle each request is. + */ + res->happy_eyeballs_dns_time = Curl_now(); + Curl_expire( + conn->data, HAPPY_EYEBALLS_DNS_TIMEOUT, EXPIRE_HAPPY_EYEBALLS_DNS); + } + } +} + +/* + * Curl_resolver_getaddrinfo() - when using ares + * + * Returns name information about the given hostname and port number. If + * successful, the 'hostent' is returned and the forth argument will point to + * memory we need to free after use. That memory *MUST* be freed with + * Curl_freeaddrinfo(), nothing else. + */ +Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, + const char *hostname, + int port, + int *waitp) +{ + char *bufp; + struct Curl_easy *data = conn->data; + struct in_addr in; + int family = PF_INET; +#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ + struct in6_addr in6; +#endif /* CURLRES_IPV6 */ + + *waitp = 0; /* default to synchronous response */ + + /* First check if this is an IPv4 address string */ + if(Curl_inet_pton(AF_INET, hostname, &in) > 0) { + /* This is a dotted IP address 123.123.123.123-style */ + return Curl_ip2addr(AF_INET, &in, hostname, port); + } + +#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ + /* Otherwise, check if this is an IPv6 address string */ + if(Curl_inet_pton (AF_INET6, hostname, &in6) > 0) + /* This must be an IPv6 address literal. */ + return Curl_ip2addr(AF_INET6, &in6, hostname, port); + + switch(conn->ip_version) { + default: +#if ARES_VERSION >= 0x010601 + family = PF_UNSPEC; /* supported by c-ares since 1.6.1, so for older + c-ares versions this just falls through and defaults + to PF_INET */ + break; +#endif + case CURL_IPRESOLVE_V4: + family = PF_INET; + break; + case CURL_IPRESOLVE_V6: + family = PF_INET6; + break; + } +#endif /* CURLRES_IPV6 */ + + bufp = strdup(hostname); + if(bufp) { + struct ResolverResults *res = NULL; + free(conn->async.hostname); + conn->async.hostname = bufp; + conn->async.port = port; + conn->async.done = FALSE; /* not done */ + conn->async.status = 0; /* clear */ + conn->async.dns = NULL; /* clear */ + res = calloc(sizeof(struct ResolverResults), 1); + if(!res) { + free(conn->async.hostname); + conn->async.hostname = NULL; + return NULL; + } + conn->async.os_specific = res; + + /* initial status - failed */ + res->last_status = ARES_ENOTFOUND; +#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ + if(family == PF_UNSPEC) { + if(Curl_ipv6works()) { + res->num_pending = 2; + + /* areschannel is already setup in the Curl_open() function */ + ares_gethostbyname((ares_channel)data->state.resolver, hostname, + PF_INET, query_completed_cb, conn); + ares_gethostbyname((ares_channel)data->state.resolver, hostname, + PF_INET6, query_completed_cb, conn); + } + else { + res->num_pending = 1; + + /* areschannel is already setup in the Curl_open() function */ + ares_gethostbyname((ares_channel)data->state.resolver, hostname, + PF_INET, query_completed_cb, conn); + } + } + else +#endif /* CURLRES_IPV6 */ + { + res->num_pending = 1; + + /* areschannel is already setup in the Curl_open() function */ + ares_gethostbyname((ares_channel)data->state.resolver, hostname, family, + query_completed_cb, conn); + } + + *waitp = 1; /* expect asynchronous response */ + } + return NULL; /* no struct yet */ +} + +CURLcode Curl_set_dns_servers(struct Curl_easy *data, + char *servers) +{ + CURLcode result = CURLE_NOT_BUILT_IN; + int ares_result; + + /* If server is NULL or empty, this would purge all DNS servers + * from ares library, which will cause any and all queries to fail. + * So, just return OK if none are configured and don't actually make + * any changes to c-ares. This lets c-ares use it's defaults, which + * it gets from the OS (for instance from /etc/resolv.conf on Linux). + */ + if(!(servers && servers[0])) + return CURLE_OK; + +#if (ARES_VERSION >= 0x010704) + ares_result = ares_set_servers_csv(data->state.resolver, servers); + switch(ares_result) { + case ARES_SUCCESS: + result = CURLE_OK; + break; + case ARES_ENOMEM: + result = CURLE_OUT_OF_MEMORY; + break; + case ARES_ENOTINITIALIZED: + case ARES_ENODATA: + case ARES_EBADSTR: + default: + result = CURLE_BAD_FUNCTION_ARGUMENT; + break; + } +#else /* too old c-ares version! */ + (void)data; + (void)(ares_result); +#endif + return result; +} + +CURLcode Curl_set_dns_interface(struct Curl_easy *data, + const char *interf) +{ +#if (ARES_VERSION >= 0x010704) + if(!interf) + interf = ""; + + ares_set_local_dev((ares_channel)data->state.resolver, interf); + + return CURLE_OK; +#else /* c-ares version too old! */ + (void)data; + (void)interf; + return CURLE_NOT_BUILT_IN; +#endif +} + +CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data, + const char *local_ip4) +{ +#if (ARES_VERSION >= 0x010704) + struct in_addr a4; + + if((!local_ip4) || (local_ip4[0] == 0)) { + a4.s_addr = 0; /* disabled: do not bind to a specific address */ + } + else { + if(Curl_inet_pton(AF_INET, local_ip4, &a4) != 1) { + return CURLE_BAD_FUNCTION_ARGUMENT; + } + } + + ares_set_local_ip4((ares_channel)data->state.resolver, ntohl(a4.s_addr)); + + return CURLE_OK; +#else /* c-ares version too old! */ + (void)data; + (void)local_ip4; + return CURLE_NOT_BUILT_IN; +#endif +} + +CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data, + const char *local_ip6) +{ +#if (ARES_VERSION >= 0x010704) && defined(ENABLE_IPV6) + unsigned char a6[INET6_ADDRSTRLEN]; + + if((!local_ip6) || (local_ip6[0] == 0)) { + /* disabled: do not bind to a specific address */ + memset(a6, 0, sizeof(a6)); + } + else { + if(Curl_inet_pton(AF_INET6, local_ip6, a6) != 1) { + return CURLE_BAD_FUNCTION_ARGUMENT; + } + } + + ares_set_local_ip6((ares_channel)data->state.resolver, a6); + + return CURLE_OK; +#else /* c-ares version too old! */ + (void)data; + (void)local_ip6; + return CURLE_NOT_BUILT_IN; +#endif +} +#endif /* CURLRES_ARES */ diff --git a/dependencies/cmcurl/lib/asyn-thread.c b/dependencies/cmcurl/lib/asyn-thread.c new file mode 100644 index 0000000..55e0811 --- /dev/null +++ b/dependencies/cmcurl/lib/asyn-thread.c @@ -0,0 +1,760 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +/*********************************************************************** + * Only for threaded name resolves builds + **********************************************************************/ +#ifdef CURLRES_THREADED + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#if defined(USE_THREADS_POSIX) +# ifdef HAVE_PTHREAD_H +# include +# endif +#elif defined(USE_THREADS_WIN32) +# ifdef HAVE_PROCESS_H +# include +# endif +#endif + +#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +#ifdef HAVE_GETADDRINFO +# define RESOLVER_ENOMEM EAI_MEMORY +#else +# define RESOLVER_ENOMEM ENOMEM +#endif + +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "hash.h" +#include "share.h" +#include "strerror.h" +#include "url.h" +#include "multiif.h" +#include "inet_pton.h" +#include "inet_ntop.h" +#include "curl_threads.h" +#include "connect.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +struct resdata { + struct curltime start; +}; + +/* + * Curl_resolver_global_init() + * Called from curl_global_init() to initialize global resolver environment. + * Does nothing here. + */ +int Curl_resolver_global_init(void) +{ + return CURLE_OK; +} + +/* + * Curl_resolver_global_cleanup() + * Called from curl_global_cleanup() to destroy global resolver environment. + * Does nothing here. + */ +void Curl_resolver_global_cleanup(void) +{ +} + +/* + * Curl_resolver_init() + * Called from curl_easy_init() -> Curl_open() to initialize resolver + * URL-state specific environment ('resolver' member of the UrlState + * structure). + */ +CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver) +{ + (void)easy; + *resolver = calloc(1, sizeof(struct resdata)); + if(!*resolver) + return CURLE_OUT_OF_MEMORY; + return CURLE_OK; +} + +/* + * Curl_resolver_cleanup() + * Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver + * URL-state specific environment ('resolver' member of the UrlState + * structure). + */ +void Curl_resolver_cleanup(void *resolver) +{ + free(resolver); +} + +/* + * Curl_resolver_duphandle() + * Called from curl_easy_duphandle() to duplicate resolver URL state-specific + * environment ('resolver' member of the UrlState structure). + */ +CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to, void *from) +{ + (void)from; + return Curl_resolver_init(easy, to); +} + +static void destroy_async_data(struct Curl_async *); + +/* + * Cancel all possibly still on-going resolves for this connection. + */ +void Curl_resolver_cancel(struct connectdata *conn) +{ + destroy_async_data(&conn->async); +} + +/* This function is used to init a threaded resolve */ +static bool init_resolve_thread(struct connectdata *conn, + const char *hostname, int port, + const struct addrinfo *hints); + + +/* Data for synchronization between resolver thread and its parent */ +struct thread_sync_data { + curl_mutex_t * mtx; + int done; + + char *hostname; /* hostname to resolve, Curl_async.hostname + duplicate */ + int port; + int sock_error; + Curl_addrinfo *res; +#ifdef HAVE_GETADDRINFO + struct addrinfo hints; +#endif + struct thread_data *td; /* for thread-self cleanup */ +}; + +struct thread_data { + curl_thread_t thread_hnd; + unsigned int poll_interval; + time_t interval_end; + struct thread_sync_data tsd; +}; + +static struct thread_sync_data *conn_thread_sync_data(struct connectdata *conn) +{ + return &(((struct thread_data *)conn->async.os_specific)->tsd); +} + +/* Destroy resolver thread synchronization data */ +static +void destroy_thread_sync_data(struct thread_sync_data * tsd) +{ + if(tsd->mtx) { + Curl_mutex_destroy(tsd->mtx); + free(tsd->mtx); + } + + free(tsd->hostname); + + if(tsd->res) + Curl_freeaddrinfo(tsd->res); + + memset(tsd, 0, sizeof(*tsd)); +} + +/* Initialize resolver thread synchronization data */ +static +int init_thread_sync_data(struct thread_data * td, + const char *hostname, + int port, + const struct addrinfo *hints) +{ + struct thread_sync_data *tsd = &td->tsd; + + memset(tsd, 0, sizeof(*tsd)); + + tsd->td = td; + tsd->port = port; + /* Treat the request as done until the thread actually starts so any early + * cleanup gets done properly. + */ + tsd->done = 1; +#ifdef HAVE_GETADDRINFO + DEBUGASSERT(hints); + tsd->hints = *hints; +#else + (void) hints; +#endif + + tsd->mtx = malloc(sizeof(curl_mutex_t)); + if(tsd->mtx == NULL) + goto err_exit; + + Curl_mutex_init(tsd->mtx); + + tsd->sock_error = CURL_ASYNC_SUCCESS; + + /* Copying hostname string because original can be destroyed by parent + * thread during gethostbyname execution. + */ + tsd->hostname = strdup(hostname); + if(!tsd->hostname) + goto err_exit; + + return 1; + + err_exit: + /* Memory allocation failed */ + destroy_thread_sync_data(tsd); + return 0; +} + +static int getaddrinfo_complete(struct connectdata *conn) +{ + struct thread_sync_data *tsd = conn_thread_sync_data(conn); + int rc; + + rc = Curl_addrinfo_callback(conn, tsd->sock_error, tsd->res); + /* The tsd->res structure has been copied to async.dns and perhaps the DNS + cache. Set our copy to NULL so destroy_thread_sync_data doesn't free it. + */ + tsd->res = NULL; + + return rc; +} + + +#ifdef HAVE_GETADDRINFO + +/* + * getaddrinfo_thread() resolves a name and then exits. + * + * For builds without ARES, but with ENABLE_IPV6, create a resolver thread + * and wait on it. + */ +static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg) +{ + struct thread_sync_data *tsd = (struct thread_sync_data*)arg; + struct thread_data *td = tsd->td; + char service[12]; + int rc; + + msnprintf(service, sizeof(service), "%d", tsd->port); + + rc = Curl_getaddrinfo_ex(tsd->hostname, service, &tsd->hints, &tsd->res); + + if(rc != 0) { + tsd->sock_error = SOCKERRNO?SOCKERRNO:rc; + if(tsd->sock_error == 0) + tsd->sock_error = RESOLVER_ENOMEM; + } + else { + Curl_addrinfo_set_port(tsd->res, tsd->port); + } + + Curl_mutex_acquire(tsd->mtx); + if(tsd->done) { + /* too late, gotta clean up the mess */ + Curl_mutex_release(tsd->mtx); + destroy_thread_sync_data(tsd); + free(td); + } + else { + tsd->done = 1; + Curl_mutex_release(tsd->mtx); + } + + return 0; +} + +#else /* HAVE_GETADDRINFO */ + +/* + * gethostbyname_thread() resolves a name and then exits. + */ +static unsigned int CURL_STDCALL gethostbyname_thread(void *arg) +{ + struct thread_sync_data *tsd = (struct thread_sync_data *)arg; + struct thread_data *td = tsd->td; + + tsd->res = Curl_ipv4_resolve_r(tsd->hostname, tsd->port); + + if(!tsd->res) { + tsd->sock_error = SOCKERRNO; + if(tsd->sock_error == 0) + tsd->sock_error = RESOLVER_ENOMEM; + } + + Curl_mutex_acquire(tsd->mtx); + if(tsd->done) { + /* too late, gotta clean up the mess */ + Curl_mutex_release(tsd->mtx); + destroy_thread_sync_data(tsd); + free(td); + } + else { + tsd->done = 1; + Curl_mutex_release(tsd->mtx); + } + + return 0; +} + +#endif /* HAVE_GETADDRINFO */ + +/* + * destroy_async_data() cleans up async resolver data and thread handle. + */ +static void destroy_async_data(struct Curl_async *async) +{ + if(async->os_specific) { + struct thread_data *td = (struct thread_data*) async->os_specific; + int done; + + /* + * if the thread is still blocking in the resolve syscall, detach it and + * let the thread do the cleanup... + */ + Curl_mutex_acquire(td->tsd.mtx); + done = td->tsd.done; + td->tsd.done = 1; + Curl_mutex_release(td->tsd.mtx); + + if(!done) { + Curl_thread_destroy(td->thread_hnd); + } + else { + if(td->thread_hnd != curl_thread_t_null) + Curl_thread_join(&td->thread_hnd); + + destroy_thread_sync_data(&td->tsd); + + free(async->os_specific); + } + } + async->os_specific = NULL; + + free(async->hostname); + async->hostname = NULL; +} + +/* + * init_resolve_thread() starts a new thread that performs the actual + * resolve. This function returns before the resolve is done. + * + * Returns FALSE in case of failure, otherwise TRUE. + */ +static bool init_resolve_thread(struct connectdata *conn, + const char *hostname, int port, + const struct addrinfo *hints) +{ + struct thread_data *td = calloc(1, sizeof(struct thread_data)); + int err = ENOMEM; + + conn->async.os_specific = (void *)td; + if(!td) + goto errno_exit; + + conn->async.port = port; + conn->async.done = FALSE; + conn->async.status = 0; + conn->async.dns = NULL; + td->thread_hnd = curl_thread_t_null; + + if(!init_thread_sync_data(td, hostname, port, hints)) { + conn->async.os_specific = NULL; + free(td); + goto errno_exit; + } + + free(conn->async.hostname); + conn->async.hostname = strdup(hostname); + if(!conn->async.hostname) + goto err_exit; + + /* The thread will set this to 1 when complete. */ + td->tsd.done = 0; + +#ifdef HAVE_GETADDRINFO + td->thread_hnd = Curl_thread_create(getaddrinfo_thread, &td->tsd); +#else + td->thread_hnd = Curl_thread_create(gethostbyname_thread, &td->tsd); +#endif + + if(!td->thread_hnd) { + /* The thread never started, so mark it as done here for proper cleanup. */ + td->tsd.done = 1; + err = errno; + goto err_exit; + } + + return TRUE; + + err_exit: + destroy_async_data(&conn->async); + + errno_exit: + errno = err; + return FALSE; +} + +/* + * resolver_error() calls failf() with the appropriate message after a resolve + * error + */ + +static CURLcode resolver_error(struct connectdata *conn) +{ + const char *host_or_proxy; + CURLcode result; + + if(conn->bits.httpproxy) { + host_or_proxy = "proxy"; + result = CURLE_COULDNT_RESOLVE_PROXY; + } + else { + host_or_proxy = "host"; + result = CURLE_COULDNT_RESOLVE_HOST; + } + + failf(conn->data, "Could not resolve %s: %s", host_or_proxy, + conn->async.hostname); + + return result; +} + +static CURLcode thread_wait_resolv(struct connectdata *conn, + struct Curl_dns_entry **entry, + bool report) +{ + struct thread_data *td = (struct thread_data*) conn->async.os_specific; + CURLcode result = CURLE_OK; + + DEBUGASSERT(conn && td); + DEBUGASSERT(td->thread_hnd != curl_thread_t_null); + + /* wait for the thread to resolve the name */ + if(Curl_thread_join(&td->thread_hnd)) { + if(entry) + result = getaddrinfo_complete(conn); + } + else + DEBUGASSERT(0); + + conn->async.done = TRUE; + + if(entry) + *entry = conn->async.dns; + + if(!conn->async.dns && report) + /* a name was not resolved, report error */ + result = resolver_error(conn); + + destroy_async_data(&conn->async); + + if(!conn->async.dns && report) + connclose(conn, "asynch resolve failed"); + + return result; +} + + +/* + * Until we gain a way to signal the resolver threads to stop early, we must + * simply wait for them and ignore their results. + */ +void Curl_resolver_kill(struct connectdata *conn) +{ + struct thread_data *td = (struct thread_data*) conn->async.os_specific; + + /* If we're still resolving, we must wait for the threads to fully clean up, + unfortunately. Otherwise, we can simply cancel to clean up any resolver + data. */ + if(td && td->thread_hnd != curl_thread_t_null) + (void)thread_wait_resolv(conn, NULL, FALSE); + else + Curl_resolver_cancel(conn); +} + +/* + * Curl_resolver_wait_resolv() + * + * Waits for a resolve to finish. This function should be avoided since using + * this risk getting the multi interface to "hang". + * + * If 'entry' is non-NULL, make it point to the resolved dns entry + * + * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, + * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors. + * + * This is the version for resolves-in-a-thread. + */ +CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, + struct Curl_dns_entry **entry) +{ + return thread_wait_resolv(conn, entry, TRUE); +} + +/* + * Curl_resolver_is_resolved() is called repeatedly to check if a previous + * name resolve request has completed. It should also make sure to time-out if + * the operation seems to take too long. + */ +CURLcode Curl_resolver_is_resolved(struct connectdata *conn, + struct Curl_dns_entry **entry) +{ + struct Curl_easy *data = conn->data; + struct thread_data *td = (struct thread_data*) conn->async.os_specific; + int done = 0; + + *entry = NULL; + + if(!td) { + DEBUGASSERT(td); + return CURLE_COULDNT_RESOLVE_HOST; + } + + Curl_mutex_acquire(td->tsd.mtx); + done = td->tsd.done; + Curl_mutex_release(td->tsd.mtx); + + if(done) { + getaddrinfo_complete(conn); + + if(!conn->async.dns) { + CURLcode result = resolver_error(conn); + destroy_async_data(&conn->async); + return result; + } + destroy_async_data(&conn->async); + *entry = conn->async.dns; + } + else { + /* poll for name lookup done with exponential backoff up to 250ms */ + timediff_t elapsed = Curl_timediff(Curl_now(), + data->progress.t_startsingle); + if(elapsed < 0) + elapsed = 0; + + if(td->poll_interval == 0) + /* Start at 1ms poll interval */ + td->poll_interval = 1; + else if(elapsed >= td->interval_end) + /* Back-off exponentially if last interval expired */ + td->poll_interval *= 2; + + if(td->poll_interval > 250) + td->poll_interval = 250; + + td->interval_end = elapsed + td->poll_interval; + Curl_expire(conn->data, td->poll_interval, EXPIRE_ASYNC_NAME); + } + + return CURLE_OK; +} + +int Curl_resolver_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + time_t milli; + timediff_t ms; + struct Curl_easy *data = conn->data; + struct resdata *reslv = (struct resdata *)data->state.resolver; + (void)socks; + (void)numsocks; + ms = Curl_timediff(Curl_now(), reslv->start); + if(ms < 3) + milli = 0; + else if(ms <= 50) + milli = ms/3; + else if(ms <= 250) + milli = 50; + else + milli = 200; + Curl_expire(data, milli, EXPIRE_ASYNC_NAME); + return 0; +} + +#ifndef HAVE_GETADDRINFO +/* + * Curl_getaddrinfo() - for platforms without getaddrinfo + */ +Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, + const char *hostname, + int port, + int *waitp) +{ + struct in_addr in; + struct Curl_easy *data = conn->data; + struct resdata *reslv = (struct resdata *)data->state.resolver; + + *waitp = 0; /* default to synchronous response */ + + if(Curl_inet_pton(AF_INET, hostname, &in) > 0) + /* This is a dotted IP address 123.123.123.123-style */ + return Curl_ip2addr(AF_INET, &in, hostname, port); + + reslv->start = Curl_now(); + + /* fire up a new resolver thread! */ + if(init_resolve_thread(conn, hostname, port, NULL)) { + *waitp = 1; /* expect asynchronous response */ + return NULL; + } + + failf(conn->data, "getaddrinfo() thread failed\n"); + + return NULL; +} + +#else /* !HAVE_GETADDRINFO */ + +/* + * Curl_resolver_getaddrinfo() - for getaddrinfo + */ +Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, + const char *hostname, + int port, + int *waitp) +{ + struct addrinfo hints; + char sbuf[12]; + int pf = PF_INET; + struct Curl_easy *data = conn->data; + struct resdata *reslv = (struct resdata *)data->state.resolver; + + *waitp = 0; /* default to synchronous response */ + +#ifndef USE_RESOLVE_ON_IPS + { + struct in_addr in; + /* First check if this is an IPv4 address string */ + if(Curl_inet_pton(AF_INET, hostname, &in) > 0) + /* This is a dotted IP address 123.123.123.123-style */ + return Curl_ip2addr(AF_INET, &in, hostname, port); + } +#ifdef CURLRES_IPV6 + { + struct in6_addr in6; + /* check if this is an IPv6 address string */ + if(Curl_inet_pton(AF_INET6, hostname, &in6) > 0) + /* This is an IPv6 address literal */ + return Curl_ip2addr(AF_INET6, &in6, hostname, port); + } +#endif /* CURLRES_IPV6 */ +#endif /* !USE_RESOLVE_ON_IPS */ + +#ifdef CURLRES_IPV6 + /* + * Check if a limited name resolve has been requested. + */ + switch(conn->ip_version) { + case CURL_IPRESOLVE_V4: + pf = PF_INET; + break; + case CURL_IPRESOLVE_V6: + pf = PF_INET6; + break; + default: + pf = PF_UNSPEC; + break; + } + + if((pf != PF_INET) && !Curl_ipv6works()) + /* The stack seems to be a non-IPv6 one */ + pf = PF_INET; +#endif /* CURLRES_IPV6 */ + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = pf; + hints.ai_socktype = conn->socktype; + + msnprintf(sbuf, sizeof(sbuf), "%d", port); + + reslv->start = Curl_now(); + /* fire up a new resolver thread! */ + if(init_resolve_thread(conn, hostname, port, &hints)) { + *waitp = 1; /* expect asynchronous response */ + return NULL; + } + + failf(data, "getaddrinfo() thread failed to start\n"); + return NULL; + +} + +#endif /* !HAVE_GETADDRINFO */ + +CURLcode Curl_set_dns_servers(struct Curl_easy *data, + char *servers) +{ + (void)data; + (void)servers; + return CURLE_NOT_BUILT_IN; + +} + +CURLcode Curl_set_dns_interface(struct Curl_easy *data, + const char *interf) +{ + (void)data; + (void)interf; + return CURLE_NOT_BUILT_IN; +} + +CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data, + const char *local_ip4) +{ + (void)data; + (void)local_ip4; + return CURLE_NOT_BUILT_IN; +} + +CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data, + const char *local_ip6) +{ + (void)data; + (void)local_ip6; + return CURLE_NOT_BUILT_IN; +} + +#endif /* CURLRES_THREADED */ diff --git a/dependencies/cmcurl/lib/asyn.h b/dependencies/cmcurl/lib/asyn.h new file mode 100644 index 0000000..ccd4b1f --- /dev/null +++ b/dependencies/cmcurl/lib/asyn.h @@ -0,0 +1,184 @@ +#ifndef HEADER_CURL_ASYN_H +#define HEADER_CURL_ASYN_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include "curl_addrinfo.h" + +struct addrinfo; +struct hostent; +struct Curl_easy; +struct connectdata; +struct Curl_dns_entry; + +/* + * This header defines all functions in the internal asynch resolver interface. + * All asynch resolvers need to provide these functions. + * asyn-ares.c and asyn-thread.c are the current implementations of asynch + * resolver backends. + */ + +/* + * Curl_resolver_global_init() + * + * Called from curl_global_init() to initialize global resolver environment. + * Returning anything else than CURLE_OK fails curl_global_init(). + */ +int Curl_resolver_global_init(void); + +/* + * Curl_resolver_global_cleanup() + * Called from curl_global_cleanup() to destroy global resolver environment. + */ +void Curl_resolver_global_cleanup(void); + +/* + * Curl_resolver_init() + * Called from curl_easy_init() -> Curl_open() to initialize resolver + * URL-state specific environment ('resolver' member of the UrlState + * structure). Should fill the passed pointer by the initialized handler. + * Returning anything else than CURLE_OK fails curl_easy_init() with the + * correspondent code. + */ +CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver); + +/* + * Curl_resolver_cleanup() + * Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver + * URL-state specific environment ('resolver' member of the UrlState + * structure). Should destroy the handler and free all resources connected to + * it. + */ +void Curl_resolver_cleanup(void *resolver); + +/* + * Curl_resolver_duphandle() + * Called from curl_easy_duphandle() to duplicate resolver URL-state specific + * environment ('resolver' member of the UrlState structure). Should + * duplicate the 'from' handle and pass the resulting handle to the 'to' + * pointer. Returning anything else than CURLE_OK causes failed + * curl_easy_duphandle() call. + */ +CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to, + void *from); + +/* + * Curl_resolver_cancel(). + * + * It is called from inside other functions to cancel currently performing + * resolver request. Should also free any temporary resources allocated to + * perform a request. This never waits for resolver threads to complete. + * + * It is safe to call this when conn is in any state. + */ +void Curl_resolver_cancel(struct connectdata *conn); + +/* + * Curl_resolver_kill(). + * + * This acts like Curl_resolver_cancel() except it will block until any threads + * associated with the resolver are complete. This never blocks for resolvers + * that do not use threads. This is intended to be the "last chance" function + * that cleans up an in-progress resolver completely (before its owner is about + * to die). + * + * It is safe to call this when conn is in any state. + */ +void Curl_resolver_kill(struct connectdata *conn); + +/* Curl_resolver_getsock() + * + * This function is called from the multi_getsock() function. 'sock' is a + * pointer to an array to hold the file descriptors, with 'numsock' being the + * size of that array (in number of entries). This function is supposed to + * return bitmask indicating what file descriptors (referring to array indexes + * in the 'sock' array) to wait for, read/write. + */ +int Curl_resolver_getsock(struct connectdata *conn, curl_socket_t *sock, + int numsocks); + +/* + * Curl_resolver_is_resolved() + * + * Called repeatedly to check if a previous name resolve request has + * completed. It should also make sure to time-out if the operation seems to + * take too long. + * + * Returns normal CURLcode errors. + */ +CURLcode Curl_resolver_is_resolved(struct connectdata *conn, + struct Curl_dns_entry **dns); + +/* + * Curl_resolver_wait_resolv() + * + * Waits for a resolve to finish. This function should be avoided since using + * this risk getting the multi interface to "hang". + * + * If 'entry' is non-NULL, make it point to the resolved dns entry + * + * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, + * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors. + */ +CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, + struct Curl_dns_entry **dnsentry); + +/* + * Curl_resolver_getaddrinfo() - when using this resolver + * + * Returns name information about the given hostname and port number. If + * successful, the 'hostent' is returned and the forth argument will point to + * memory we need to free after use. That memory *MUST* be freed with + * Curl_freeaddrinfo(), nothing else. + * + * Each resolver backend must of course make sure to return data in the + * correct format to comply with this. + */ +Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, + const char *hostname, + int port, + int *waitp); + +#ifndef CURLRES_ASYNCH +/* convert these functions if an asynch resolver isn't used */ +#define Curl_resolver_cancel(x) Curl_nop_stmt +#define Curl_resolver_kill(x) Curl_nop_stmt +#define Curl_resolver_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST +#define Curl_resolver_wait_resolv(x,y) CURLE_COULDNT_RESOLVE_HOST +#define Curl_resolver_getsock(x,y,z) 0 +#define Curl_resolver_duphandle(x,y,z) CURLE_OK +#define Curl_resolver_init(x,y) CURLE_OK +#define Curl_resolver_global_init() CURLE_OK +#define Curl_resolver_global_cleanup() Curl_nop_stmt +#define Curl_resolver_cleanup(x) Curl_nop_stmt +#endif + +#ifdef CURLRES_ASYNCH +#define Curl_resolver_asynch() 1 +#else +#define Curl_resolver_asynch() 0 +#endif + + +/********** end of generic resolver interface functions *****************/ +#endif /* HEADER_CURL_ASYN_H */ diff --git a/dependencies/cmcurl/lib/base64.c b/dependencies/cmcurl/lib/base64.c new file mode 100644 index 0000000..fb081a6 --- /dev/null +++ b/dependencies/cmcurl/lib/base64.c @@ -0,0 +1,326 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* Base64 encoding/decoding */ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP_AUTH) || defined(USE_LIBSSH2) || \ + defined(USE_LIBSSH) || !defined(CURL_DISABLE_LDAP) || \ + !defined(CURL_DISABLE_DOH) || defined(USE_SSL) + +#include "urldata.h" /* for the Curl_easy definition */ +#include "warnless.h" +#include "curl_base64.h" +#include "non-ascii.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* ---- Base64 Encoding/Decoding Table --- */ +static const char base64[]= + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/* The Base 64 encoding with an URL and filename safe alphabet, RFC 4648 + section 5 */ +static const char base64url[]= + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + +static size_t decodeQuantum(unsigned char *dest, const char *src) +{ + size_t padding = 0; + const char *s, *p; + unsigned long i, x = 0; + + for(i = 0, s = src; i < 4; i++, s++) { + if(*s == '=') { + x = (x << 6); + padding++; + } + else { + unsigned long v = 0; + p = base64; + + while(*p && (*p != *s)) { + v++; + p++; + } + + if(*p == *s) + x = (x << 6) + v; + else + return 0; + } + } + + if(padding < 1) + dest[2] = curlx_ultouc(x & 0xFFUL); + + x >>= 8; + if(padding < 2) + dest[1] = curlx_ultouc(x & 0xFFUL); + + x >>= 8; + dest[0] = curlx_ultouc(x & 0xFFUL); + + return 3 - padding; +} + +/* + * Curl_base64_decode() + * + * Given a base64 NUL-terminated string at src, decode it and return a + * pointer in *outptr to a newly allocated memory area holding decoded + * data. Size of decoded data is returned in variable pointed by outlen. + * + * Returns CURLE_OK on success, otherwise specific error code. Function + * output shall not be considered valid unless CURLE_OK is returned. + * + * When decoded data length is 0, returns NULL in *outptr. + * + * @unittest: 1302 + */ +CURLcode Curl_base64_decode(const char *src, + unsigned char **outptr, size_t *outlen) +{ + size_t srclen = 0; + size_t length = 0; + size_t padding = 0; + size_t i; + size_t numQuantums; + size_t rawlen = 0; + unsigned char *pos; + unsigned char *newstr; + + *outptr = NULL; + *outlen = 0; + srclen = strlen(src); + + /* Check the length of the input string is valid */ + if(!srclen || srclen % 4) + return CURLE_BAD_CONTENT_ENCODING; + + /* Find the position of any = padding characters */ + while((src[length] != '=') && src[length]) + length++; + + /* A maximum of two = padding characters is allowed */ + if(src[length] == '=') { + padding++; + if(src[length + 1] == '=') + padding++; + } + + /* Check the = padding characters weren't part way through the input */ + if(length + padding != srclen) + return CURLE_BAD_CONTENT_ENCODING; + + /* Calculate the number of quantums */ + numQuantums = srclen / 4; + + /* Calculate the size of the decoded string */ + rawlen = (numQuantums * 3) - padding; + + /* Allocate our buffer including room for a zero terminator */ + newstr = malloc(rawlen + 1); + if(!newstr) + return CURLE_OUT_OF_MEMORY; + + pos = newstr; + + /* Decode the quantums */ + for(i = 0; i < numQuantums; i++) { + size_t result = decodeQuantum(pos, src); + if(!result) { + free(newstr); + + return CURLE_BAD_CONTENT_ENCODING; + } + + pos += result; + src += 4; + } + + /* Zero terminate */ + *pos = '\0'; + + /* Return the decoded data */ + *outptr = newstr; + *outlen = rawlen; + + return CURLE_OK; +} + +static CURLcode base64_encode(const char *table64, + struct Curl_easy *data, + const char *inputbuff, size_t insize, + char **outptr, size_t *outlen) +{ + CURLcode result; + unsigned char ibuf[3]; + unsigned char obuf[4]; + int i; + int inputparts; + char *output; + char *base64data; + char *convbuf = NULL; + + const char *indata = inputbuff; + + *outptr = NULL; + *outlen = 0; + + if(!insize) + insize = strlen(indata); + +#if SIZEOF_SIZE_T == 4 + if(insize > UINT_MAX/4) + return CURLE_OUT_OF_MEMORY; +#endif + + base64data = output = malloc(insize * 4 / 3 + 4); + if(!output) + return CURLE_OUT_OF_MEMORY; + + /* + * The base64 data needs to be created using the network encoding + * not the host encoding. And we can't change the actual input + * so we copy it to a buffer, translate it, and use that instead. + */ + result = Curl_convert_clone(data, indata, insize, &convbuf); + if(result) { + free(output); + return result; + } + + if(convbuf) + indata = (char *)convbuf; + + while(insize > 0) { + for(i = inputparts = 0; i < 3; i++) { + if(insize > 0) { + inputparts++; + ibuf[i] = (unsigned char) *indata; + indata++; + insize--; + } + else + ibuf[i] = 0; + } + + obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2); + obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \ + ((ibuf[1] & 0xF0) >> 4)); + obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \ + ((ibuf[2] & 0xC0) >> 6)); + obuf[3] = (unsigned char) (ibuf[2] & 0x3F); + + switch(inputparts) { + case 1: /* only one byte read */ + msnprintf(output, 5, "%c%c==", + table64[obuf[0]], + table64[obuf[1]]); + break; + + case 2: /* two bytes read */ + msnprintf(output, 5, "%c%c%c=", + table64[obuf[0]], + table64[obuf[1]], + table64[obuf[2]]); + break; + + default: + msnprintf(output, 5, "%c%c%c%c", + table64[obuf[0]], + table64[obuf[1]], + table64[obuf[2]], + table64[obuf[3]]); + break; + } + output += 4; + } + + /* Zero terminate */ + *output = '\0'; + + /* Return the pointer to the new data (allocated memory) */ + *outptr = base64data; + + free(convbuf); + + /* Return the length of the new data */ + *outlen = strlen(base64data); + + return CURLE_OK; +} + +/* + * Curl_base64_encode() + * + * Given a pointer to an input buffer and an input size, encode it and + * return a pointer in *outptr to a newly allocated memory area holding + * encoded data. Size of encoded data is returned in variable pointed by + * outlen. + * + * Input length of 0 indicates input buffer holds a NUL-terminated string. + * + * Returns CURLE_OK on success, otherwise specific error code. Function + * output shall not be considered valid unless CURLE_OK is returned. + * + * When encoded data length is 0, returns NULL in *outptr. + * + * @unittest: 1302 + */ +CURLcode Curl_base64_encode(struct Curl_easy *data, + const char *inputbuff, size_t insize, + char **outptr, size_t *outlen) +{ + return base64_encode(base64, data, inputbuff, insize, outptr, outlen); +} + +/* + * Curl_base64url_encode() + * + * Given a pointer to an input buffer and an input size, encode it and + * return a pointer in *outptr to a newly allocated memory area holding + * encoded data. Size of encoded data is returned in variable pointed by + * outlen. + * + * Input length of 0 indicates input buffer holds a NUL-terminated string. + * + * Returns CURLE_OK on success, otherwise specific error code. Function + * output shall not be considered valid unless CURLE_OK is returned. + * + * When encoded data length is 0, returns NULL in *outptr. + * + * @unittest: 1302 + */ +CURLcode Curl_base64url_encode(struct Curl_easy *data, + const char *inputbuff, size_t insize, + char **outptr, size_t *outlen) +{ + return base64_encode(base64url, data, inputbuff, insize, outptr, outlen); +} + +#endif /* no users so disabled */ diff --git a/dependencies/cmcurl/lib/conncache.c b/dependencies/cmcurl/lib/conncache.c new file mode 100644 index 0000000..5350919 --- /dev/null +++ b/dependencies/cmcurl/lib/conncache.c @@ -0,0 +1,631 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2016, Linus Nielsen Feltzing, + * Copyright (C) 2012 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "urldata.h" +#include "url.h" +#include "progress.h" +#include "multiif.h" +#include "sendf.h" +#include "conncache.h" +#include "share.h" +#include "sigpipe.h" +#include "connect.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#ifdef CURLDEBUG +/* the debug versions of these macros make extra certain that the lock is + never doubly locked or unlocked */ +#define CONN_LOCK(x) if((x)->share) { \ + Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE); \ + DEBUGASSERT(!(x)->state.conncache_lock); \ + (x)->state.conncache_lock = TRUE; \ + } + +#define CONN_UNLOCK(x) if((x)->share) { \ + DEBUGASSERT((x)->state.conncache_lock); \ + (x)->state.conncache_lock = FALSE; \ + Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT); \ + } +#else +#define CONN_LOCK(x) if((x)->share) \ + Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE) +#define CONN_UNLOCK(x) if((x)->share) \ + Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT) +#endif + +static void conn_llist_dtor(void *user, void *element) +{ + struct connectdata *conn = element; + (void)user; + conn->bundle = NULL; +} + +static CURLcode bundle_create(struct Curl_easy *data, + struct connectbundle **cb_ptr) +{ + (void)data; + DEBUGASSERT(*cb_ptr == NULL); + *cb_ptr = malloc(sizeof(struct connectbundle)); + if(!*cb_ptr) + return CURLE_OUT_OF_MEMORY; + + (*cb_ptr)->num_connections = 0; + (*cb_ptr)->multiuse = BUNDLE_UNKNOWN; + + Curl_llist_init(&(*cb_ptr)->conn_list, (curl_llist_dtor) conn_llist_dtor); + return CURLE_OK; +} + +static void bundle_destroy(struct connectbundle *cb_ptr) +{ + if(!cb_ptr) + return; + + Curl_llist_destroy(&cb_ptr->conn_list, NULL); + + free(cb_ptr); +} + +/* Add a connection to a bundle */ +static void bundle_add_conn(struct connectbundle *cb_ptr, + struct connectdata *conn) +{ + Curl_llist_insert_next(&cb_ptr->conn_list, cb_ptr->conn_list.tail, conn, + &conn->bundle_node); + conn->bundle = cb_ptr; + cb_ptr->num_connections++; +} + +/* Remove a connection from a bundle */ +static int bundle_remove_conn(struct connectbundle *cb_ptr, + struct connectdata *conn) +{ + struct curl_llist_element *curr; + + curr = cb_ptr->conn_list.head; + while(curr) { + if(curr->ptr == conn) { + Curl_llist_remove(&cb_ptr->conn_list, curr, NULL); + cb_ptr->num_connections--; + conn->bundle = NULL; + return 1; /* we removed a handle */ + } + curr = curr->next; + } + return 0; +} + +static void free_bundle_hash_entry(void *freethis) +{ + struct connectbundle *b = (struct connectbundle *) freethis; + + bundle_destroy(b); +} + +int Curl_conncache_init(struct conncache *connc, int size) +{ + int rc; + + /* allocate a new easy handle to use when closing cached connections */ + connc->closure_handle = curl_easy_init(); + if(!connc->closure_handle) + return 1; /* bad */ + + rc = Curl_hash_init(&connc->hash, size, Curl_hash_str, + Curl_str_key_compare, free_bundle_hash_entry); + if(rc) { + Curl_close(connc->closure_handle); + connc->closure_handle = NULL; + } + else + connc->closure_handle->state.conn_cache = connc; + + return rc; +} + +void Curl_conncache_destroy(struct conncache *connc) +{ + if(connc) + Curl_hash_destroy(&connc->hash); +} + +/* creates a key to find a bundle for this connection */ +static void hashkey(struct connectdata *conn, char *buf, + size_t len) /* something like 128 is fine */ +{ + const char *hostname; + + if(conn->bits.socksproxy) + hostname = conn->socks_proxy.host.name; + else if(conn->bits.httpproxy) + hostname = conn->http_proxy.host.name; + else if(conn->bits.conn_to_host) + hostname = conn->conn_to_host.name; + else + hostname = conn->host.name; + + DEBUGASSERT(len > 32); + + /* put the number first so that the hostname gets cut off if too long */ + msnprintf(buf, len, "%ld%s", conn->port, hostname); +} + +void Curl_conncache_unlock(struct Curl_easy *data) +{ + CONN_UNLOCK(data); +} + +/* Returns number of connections currently held in the connection cache. + Locks/unlocks the cache itself! +*/ +size_t Curl_conncache_size(struct Curl_easy *data) +{ + size_t num; + CONN_LOCK(data); + num = data->state.conn_cache->num_conn; + CONN_UNLOCK(data); + return num; +} + +/* Returns number of connections currently held in the connections's bundle + Locks/unlocks the cache itself! +*/ +size_t Curl_conncache_bundle_size(struct connectdata *conn) +{ + size_t num; + CONN_LOCK(conn->data); + num = conn->bundle->num_connections; + CONN_UNLOCK(conn->data); + return num; +} + +/* Look up the bundle with all the connections to the same host this + connectdata struct is setup to use. + + **NOTE**: When it returns, it holds the connection cache lock! */ +struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn, + struct conncache *connc) +{ + struct connectbundle *bundle = NULL; + CONN_LOCK(conn->data); + if(connc) { + char key[128]; + hashkey(conn, key, sizeof(key)); + bundle = Curl_hash_pick(&connc->hash, key, strlen(key)); + } + + return bundle; +} + +static bool conncache_add_bundle(struct conncache *connc, + char *key, + struct connectbundle *bundle) +{ + void *p = Curl_hash_add(&connc->hash, key, strlen(key), bundle); + + return p?TRUE:FALSE; +} + +static void conncache_remove_bundle(struct conncache *connc, + struct connectbundle *bundle) +{ + struct curl_hash_iterator iter; + struct curl_hash_element *he; + + if(!connc) + return; + + Curl_hash_start_iterate(&connc->hash, &iter); + + he = Curl_hash_next_element(&iter); + while(he) { + if(he->ptr == bundle) { + /* The bundle is destroyed by the hash destructor function, + free_bundle_hash_entry() */ + Curl_hash_delete(&connc->hash, he->key, he->key_len); + return; + } + + he = Curl_hash_next_element(&iter); + } +} + +CURLcode Curl_conncache_add_conn(struct conncache *connc, + struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct connectbundle *bundle; + struct connectbundle *new_bundle = NULL; + struct Curl_easy *data = conn->data; + + /* *find_bundle() locks the connection cache */ + bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache); + if(!bundle) { + int rc; + char key[128]; + + result = bundle_create(data, &new_bundle); + if(result) { + goto unlock; + } + + hashkey(conn, key, sizeof(key)); + rc = conncache_add_bundle(data->state.conn_cache, key, new_bundle); + + if(!rc) { + bundle_destroy(new_bundle); + result = CURLE_OUT_OF_MEMORY; + goto unlock; + } + bundle = new_bundle; + } + + bundle_add_conn(bundle, conn); + conn->connection_id = connc->next_connection_id++; + connc->num_conn++; + + DEBUGF(infof(conn->data, "Added connection %ld. " + "The cache now contains %zu members\n", + conn->connection_id, connc->num_conn)); + + unlock: + CONN_UNLOCK(data); + + return result; +} + +/* + * Removes the connectdata object from the connection cache *and* clears the + * ->data pointer association. Pass TRUE/FALSE in the 'lock' argument + * depending on if the parent function already holds the lock or not. + */ +void Curl_conncache_remove_conn(struct Curl_easy *data, + struct connectdata *conn, bool lock) +{ + struct connectbundle *bundle = conn->bundle; + struct conncache *connc = data->state.conn_cache; + + /* The bundle pointer can be NULL, since this function can be called + due to a failed connection attempt, before being added to a bundle */ + if(bundle) { + if(lock) { + CONN_LOCK(data); + } + bundle_remove_conn(bundle, conn); + if(bundle->num_connections == 0) + conncache_remove_bundle(connc, bundle); + conn->bundle = NULL; /* removed from it */ + if(connc) { + connc->num_conn--; + DEBUGF(infof(data, "The cache now contains %zu members\n", + connc->num_conn)); + } + conn->data = NULL; /* clear the association */ + if(lock) { + CONN_UNLOCK(data); + } + } +} + +/* This function iterates the entire connection cache and calls the function + func() with the connection pointer as the first argument and the supplied + 'param' argument as the other. + + The conncache lock is still held when the callback is called. It needs it, + so that it can safely continue traversing the lists once the callback + returns. + + Returns 1 if the loop was aborted due to the callback's return code. + + Return 0 from func() to continue the loop, return 1 to abort it. + */ +bool Curl_conncache_foreach(struct Curl_easy *data, + struct conncache *connc, + void *param, + int (*func)(struct connectdata *conn, void *param)) +{ + struct curl_hash_iterator iter; + struct curl_llist_element *curr; + struct curl_hash_element *he; + + if(!connc) + return FALSE; + + CONN_LOCK(data); + Curl_hash_start_iterate(&connc->hash, &iter); + + he = Curl_hash_next_element(&iter); + while(he) { + struct connectbundle *bundle; + + bundle = he->ptr; + he = Curl_hash_next_element(&iter); + + curr = bundle->conn_list.head; + while(curr) { + /* Yes, we need to update curr before calling func(), because func() + might decide to remove the connection */ + struct connectdata *conn = curr->ptr; + curr = curr->next; + + if(1 == func(conn, param)) { + CONN_UNLOCK(data); + return TRUE; + } + } + } + CONN_UNLOCK(data); + return FALSE; +} + +/* Return the first connection found in the cache. Used when closing all + connections. + + NOTE: no locking is done here as this is presumably only done when cleaning + up a cache! +*/ +static struct connectdata * +conncache_find_first_connection(struct conncache *connc) +{ + struct curl_hash_iterator iter; + struct curl_hash_element *he; + struct connectbundle *bundle; + + Curl_hash_start_iterate(&connc->hash, &iter); + + he = Curl_hash_next_element(&iter); + while(he) { + struct curl_llist_element *curr; + bundle = he->ptr; + + curr = bundle->conn_list.head; + if(curr) { + return curr->ptr; + } + + he = Curl_hash_next_element(&iter); + } + + return NULL; +} + +/* + * Give ownership of a connection back to the connection cache. Might + * disconnect the oldest existing in there to make space. + * + * Return TRUE if stored, FALSE if closed. + */ +bool Curl_conncache_return_conn(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + + /* data->multi->maxconnects can be negative, deal with it. */ + size_t maxconnects = + (data->multi->maxconnects < 0) ? data->multi->num_easy * 4: + data->multi->maxconnects; + struct connectdata *conn_candidate = NULL; + + conn->data = NULL; /* no owner anymore */ + conn->lastused = Curl_now(); /* it was used up until now */ + if(maxconnects > 0 && + Curl_conncache_size(data) > maxconnects) { + infof(data, "Connection cache is full, closing the oldest one.\n"); + + conn_candidate = Curl_conncache_extract_oldest(data); + if(conn_candidate) { + /* the winner gets the honour of being disconnected */ + (void)Curl_disconnect(data, conn_candidate, /* dead_connection */ FALSE); + } + } + + return (conn_candidate == conn) ? FALSE : TRUE; + +} + +/* + * This function finds the connection in the connection bundle that has been + * unused for the longest time. + * + * Does not lock the connection cache! + * + * Returns the pointer to the oldest idle connection, or NULL if none was + * found. + */ +struct connectdata * +Curl_conncache_extract_bundle(struct Curl_easy *data, + struct connectbundle *bundle) +{ + struct curl_llist_element *curr; + timediff_t highscore = -1; + timediff_t score; + struct curltime now; + struct connectdata *conn_candidate = NULL; + struct connectdata *conn; + + (void)data; + + now = Curl_now(); + + curr = bundle->conn_list.head; + while(curr) { + conn = curr->ptr; + + if(!CONN_INUSE(conn) && !conn->data) { + /* Set higher score for the age passed since the connection was used */ + score = Curl_timediff(now, conn->lastused); + + if(score > highscore) { + highscore = score; + conn_candidate = conn; + } + } + curr = curr->next; + } + if(conn_candidate) { + /* remove it to prevent another thread from nicking it */ + bundle_remove_conn(bundle, conn_candidate); + data->state.conn_cache->num_conn--; + DEBUGF(infof(data, "The cache now contains %zu members\n", + data->state.conn_cache->num_conn)); + conn_candidate->data = data; /* associate! */ + } + + return conn_candidate; +} + +/* + * This function finds the connection in the connection cache that has been + * unused for the longest time and extracts that from the bundle. + * + * Returns the pointer to the connection, or NULL if none was found. + */ +struct connectdata * +Curl_conncache_extract_oldest(struct Curl_easy *data) +{ + struct conncache *connc = data->state.conn_cache; + struct curl_hash_iterator iter; + struct curl_llist_element *curr; + struct curl_hash_element *he; + timediff_t highscore =- 1; + timediff_t score; + struct curltime now; + struct connectdata *conn_candidate = NULL; + struct connectbundle *bundle; + struct connectbundle *bundle_candidate = NULL; + + now = Curl_now(); + + CONN_LOCK(data); + Curl_hash_start_iterate(&connc->hash, &iter); + + he = Curl_hash_next_element(&iter); + while(he) { + struct connectdata *conn; + + bundle = he->ptr; + + curr = bundle->conn_list.head; + while(curr) { + conn = curr->ptr; + + if(!CONN_INUSE(conn) && !conn->data) { + /* Set higher score for the age passed since the connection was used */ + score = Curl_timediff(now, conn->lastused); + + if(score > highscore) { + highscore = score; + conn_candidate = conn; + bundle_candidate = bundle; + } + } + curr = curr->next; + } + + he = Curl_hash_next_element(&iter); + } + if(conn_candidate) { + /* remove it to prevent another thread from nicking it */ + bundle_remove_conn(bundle_candidate, conn_candidate); + connc->num_conn--; + DEBUGF(infof(data, "The cache now contains %zu members\n", + connc->num_conn)); + conn_candidate->data = data; /* associate! */ + } + CONN_UNLOCK(data); + + return conn_candidate; +} + +void Curl_conncache_close_all_connections(struct conncache *connc) +{ + struct connectdata *conn; + + conn = conncache_find_first_connection(connc); + while(conn) { + SIGPIPE_VARIABLE(pipe_st); + conn->data = connc->closure_handle; + + sigpipe_ignore(conn->data, &pipe_st); + /* This will remove the connection from the cache */ + connclose(conn, "kill all"); + (void)Curl_disconnect(connc->closure_handle, conn, FALSE); + sigpipe_restore(&pipe_st); + + conn = conncache_find_first_connection(connc); + } + + if(connc->closure_handle) { + SIGPIPE_VARIABLE(pipe_st); + sigpipe_ignore(connc->closure_handle, &pipe_st); + + Curl_hostcache_clean(connc->closure_handle, + connc->closure_handle->dns.hostcache); + Curl_close(connc->closure_handle); + sigpipe_restore(&pipe_st); + } +} + +#if 0 +/* Useful for debugging the connection cache */ +void Curl_conncache_print(struct conncache *connc) +{ + struct curl_hash_iterator iter; + struct curl_llist_element *curr; + struct curl_hash_element *he; + + if(!connc) + return; + + fprintf(stderr, "=Bundle cache=\n"); + + Curl_hash_start_iterate(connc->hash, &iter); + + he = Curl_hash_next_element(&iter); + while(he) { + struct connectbundle *bundle; + struct connectdata *conn; + + bundle = he->ptr; + + fprintf(stderr, "%s -", he->key); + curr = bundle->conn_list->head; + while(curr) { + conn = curr->ptr; + + fprintf(stderr, " [%p %d]", (void *)conn, conn->inuse); + curr = curr->next; + } + fprintf(stderr, "\n"); + + he = Curl_hash_next_element(&iter); + } +} +#endif diff --git a/dependencies/cmcurl/lib/conncache.h b/dependencies/cmcurl/lib/conncache.h new file mode 100644 index 0000000..35be9e0 --- /dev/null +++ b/dependencies/cmcurl/lib/conncache.h @@ -0,0 +1,86 @@ +#ifndef HEADER_CURL_CONNCACHE_H +#define HEADER_CURL_CONNCACHE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2015 - 2019, Daniel Stenberg, , et al. + * Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * All accesses to struct fields and changing of data in the connection cache + * and connectbundles must be done with the conncache LOCKED. The cache might + * be shared. + */ + +struct conncache { + struct curl_hash hash; + size_t num_conn; + long next_connection_id; + struct curltime last_cleanup; + /* handle used for closing cached connections */ + struct Curl_easy *closure_handle; +}; + +#define BUNDLE_NO_MULTIUSE -1 +#define BUNDLE_UNKNOWN 0 /* initial value */ +#define BUNDLE_MULTIPLEX 2 + +struct connectbundle { + int multiuse; /* supports multi-use */ + size_t num_connections; /* Number of connections in the bundle */ + struct curl_llist conn_list; /* The connectdata members of the bundle */ +}; + +/* returns 1 on error, 0 is fine */ +int Curl_conncache_init(struct conncache *, int size); +void Curl_conncache_destroy(struct conncache *connc); + +/* return the correct bundle, to a host or a proxy */ +struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn, + struct conncache *connc); +void Curl_conncache_unlock(struct Curl_easy *data); +/* returns number of connections currently held in the connection cache */ +size_t Curl_conncache_size(struct Curl_easy *data); +size_t Curl_conncache_bundle_size(struct connectdata *conn); + +bool Curl_conncache_return_conn(struct connectdata *conn); +CURLcode Curl_conncache_add_conn(struct conncache *connc, + struct connectdata *conn) WARN_UNUSED_RESULT; +void Curl_conncache_remove_conn(struct Curl_easy *data, + struct connectdata *conn, + bool lock); +bool Curl_conncache_foreach(struct Curl_easy *data, + struct conncache *connc, + void *param, + int (*func)(struct connectdata *conn, + void *param)); + +struct connectdata * +Curl_conncache_find_first_connection(struct conncache *connc); + +struct connectdata * +Curl_conncache_extract_bundle(struct Curl_easy *data, + struct connectbundle *bundle); +struct connectdata * +Curl_conncache_extract_oldest(struct Curl_easy *data); +void Curl_conncache_close_all_connections(struct conncache *connc); +void Curl_conncache_print(struct conncache *connc); + +#endif /* HEADER_CURL_CONNCACHE_H */ diff --git a/dependencies/cmcurl/lib/connect.c b/dependencies/cmcurl/lib/connect.c new file mode 100644 index 0000000..002535b --- /dev/null +++ b/dependencies/cmcurl/lib/connect.c @@ -0,0 +1,1462 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_NETINET_IN_H +#include /* may need it */ +#endif +#ifdef HAVE_SYS_UN_H +#include /* for sockaddr_un */ +#endif +#ifdef HAVE_LINUX_TCP_H +#include +#elif defined(HAVE_NETINET_TCP_H) +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE)) +#include +#endif +#ifdef NETWARE +#undef in_addr_t +#define in_addr_t unsigned long +#endif +#ifdef __VMS +#include +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "if2ip.h" +#include "strerror.h" +#include "connect.h" +#include "select.h" +#include "url.h" /* for Curl_safefree() */ +#include "multiif.h" +#include "sockaddr.h" /* required for Curl_sockaddr_storage */ +#include "inet_ntop.h" +#include "inet_pton.h" +#include "vtls/vtls.h" /* for Curl_ssl_check_cxn() */ +#include "progress.h" +#include "warnless.h" +#include "conncache.h" +#include "multihandle.h" +#include "system_win32.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#ifdef __SYMBIAN32__ +/* This isn't actually supported under Symbian OS */ +#undef SO_NOSIGPIPE +#endif + +static bool verifyconnect(curl_socket_t sockfd, int *error); + +#if defined(__DragonFly__) || defined(HAVE_WINSOCK_H) +/* DragonFlyBSD and Windows use millisecond units */ +#define KEEPALIVE_FACTOR(x) (x *= 1000) +#else +#define KEEPALIVE_FACTOR(x) +#endif + +#if defined(HAVE_WINSOCK2_H) && !defined(SIO_KEEPALIVE_VALS) +#define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4) + +struct tcp_keepalive { + u_long onoff; + u_long keepalivetime; + u_long keepaliveinterval; +}; +#endif + +static void +tcpkeepalive(struct Curl_easy *data, + curl_socket_t sockfd) +{ + int optval = data->set.tcp_keepalive?1:0; + + /* only set IDLE and INTVL if setting KEEPALIVE is successful */ + if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, + (void *)&optval, sizeof(optval)) < 0) { + infof(data, "Failed to set SO_KEEPALIVE on fd %d\n", sockfd); + } + else { +#if defined(SIO_KEEPALIVE_VALS) + struct tcp_keepalive vals; + DWORD dummy; + vals.onoff = 1; + optval = curlx_sltosi(data->set.tcp_keepidle); + KEEPALIVE_FACTOR(optval); + vals.keepalivetime = optval; + optval = curlx_sltosi(data->set.tcp_keepintvl); + KEEPALIVE_FACTOR(optval); + vals.keepaliveinterval = optval; + if(WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, (LPVOID) &vals, sizeof(vals), + NULL, 0, &dummy, NULL, NULL) != 0) { + infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd %d: %d\n", + (int)sockfd, WSAGetLastError()); + } +#else +#ifdef TCP_KEEPIDLE + optval = curlx_sltosi(data->set.tcp_keepidle); + KEEPALIVE_FACTOR(optval); + if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, + (void *)&optval, sizeof(optval)) < 0) { + infof(data, "Failed to set TCP_KEEPIDLE on fd %d\n", sockfd); + } +#endif +#ifdef TCP_KEEPINTVL + optval = curlx_sltosi(data->set.tcp_keepintvl); + KEEPALIVE_FACTOR(optval); + if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL, + (void *)&optval, sizeof(optval)) < 0) { + infof(data, "Failed to set TCP_KEEPINTVL on fd %d\n", sockfd); + } +#endif +#ifdef TCP_KEEPALIVE + /* Mac OS X style */ + optval = curlx_sltosi(data->set.tcp_keepidle); + KEEPALIVE_FACTOR(optval); + if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE, + (void *)&optval, sizeof(optval)) < 0) { + infof(data, "Failed to set TCP_KEEPALIVE on fd %d\n", sockfd); + } +#endif +#endif + } +} + +static CURLcode +singleipconnect(struct connectdata *conn, + const Curl_addrinfo *ai, /* start connecting to this */ + curl_socket_t *sock); + +/* + * Curl_timeleft() returns the amount of milliseconds left allowed for the + * transfer/connection. If the value is negative, the timeout time has already + * elapsed. + * + * The start time is stored in progress.t_startsingle - as set with + * Curl_pgrsTime(..., TIMER_STARTSINGLE); + * + * If 'nowp' is non-NULL, it points to the current time. + * 'duringconnect' is FALSE if not during a connect, as then of course the + * connect timeout is not taken into account! + * + * @unittest: 1303 + */ +timediff_t Curl_timeleft(struct Curl_easy *data, + struct curltime *nowp, + bool duringconnect) +{ + int timeout_set = 0; + timediff_t timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0; + struct curltime now; + + /* if a timeout is set, use the most restrictive one */ + + if(data->set.timeout > 0) + timeout_set |= 1; + if(duringconnect && (data->set.connecttimeout > 0)) + timeout_set |= 2; + + switch(timeout_set) { + case 1: + timeout_ms = data->set.timeout; + break; + case 2: + timeout_ms = data->set.connecttimeout; + break; + case 3: + if(data->set.timeout < data->set.connecttimeout) + timeout_ms = data->set.timeout; + else + timeout_ms = data->set.connecttimeout; + break; + default: + /* use the default */ + if(!duringconnect) + /* if we're not during connect, there's no default timeout so if we're + at zero we better just return zero and not make it a negative number + by the math below */ + return 0; + break; + } + + if(!nowp) { + now = Curl_now(); + nowp = &now; + } + + /* subtract elapsed time */ + if(duringconnect) + /* since this most recent connect started */ + timeout_ms -= Curl_timediff(*nowp, data->progress.t_startsingle); + else + /* since the entire operation started */ + timeout_ms -= Curl_timediff(*nowp, data->progress.t_startop); + if(!timeout_ms) + /* avoid returning 0 as that means no timeout! */ + return -1; + + return timeout_ms; +} + +static CURLcode bindlocal(struct connectdata *conn, + curl_socket_t sockfd, int af, unsigned int scope) +{ + struct Curl_easy *data = conn->data; + + struct Curl_sockaddr_storage sa; + struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */ + curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */ + struct sockaddr_in *si4 = (struct sockaddr_in *)&sa; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa; +#endif + + struct Curl_dns_entry *h = NULL; + unsigned short port = data->set.localport; /* use this port number, 0 for + "random" */ + /* how many port numbers to try to bind to, increasing one at a time */ + int portnum = data->set.localportrange; + const char *dev = data->set.str[STRING_DEVICE]; + int error; + + /************************************************************* + * Select device to bind socket to + *************************************************************/ + if(!dev && !port) + /* no local kind of binding was requested */ + return CURLE_OK; + + memset(&sa, 0, sizeof(struct Curl_sockaddr_storage)); + + if(dev && (strlen(dev)<255) ) { + char myhost[256] = ""; + int done = 0; /* -1 for error, 1 for address found */ + bool is_interface = FALSE; + bool is_host = FALSE; + static const char *if_prefix = "if!"; + static const char *host_prefix = "host!"; + + if(strncmp(if_prefix, dev, strlen(if_prefix)) == 0) { + dev += strlen(if_prefix); + is_interface = TRUE; + } + else if(strncmp(host_prefix, dev, strlen(host_prefix)) == 0) { + dev += strlen(host_prefix); + is_host = TRUE; + } + + /* interface */ + if(!is_host) { +#ifdef SO_BINDTODEVICE + /* I am not sure any other OSs than Linux that provide this feature, + * and at the least I cannot test. --Ben + * + * This feature allows one to tightly bind the local socket to a + * particular interface. This will force even requests to other + * local interfaces to go out the external interface. + * + * + * Only bind to the interface when specified as interface, not just + * as a hostname or ip address. + * + * interface might be a VRF, eg: vrf-blue, which means it cannot be + * converted to an IP address and would fail Curl_if2ip. Simply try + * to use it straight away. + */ + if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, + dev, (curl_socklen_t)strlen(dev) + 1) == 0) { + /* This is typically "errno 1, error: Operation not permitted" if + * you're not running as root or another suitable privileged + * user. + * If it succeeds it means the parameter was a valid interface and + * not an IP address. Return immediately. + */ + return CURLE_OK; + } +#endif + + switch(Curl_if2ip(af, scope, conn->scope_id, dev, + myhost, sizeof(myhost))) { + case IF2IP_NOT_FOUND: + if(is_interface) { + /* Do not fall back to treating it as a host name */ + failf(data, "Couldn't bind to interface '%s'", dev); + return CURLE_INTERFACE_FAILED; + } + break; + case IF2IP_AF_NOT_SUPPORTED: + /* Signal the caller to try another address family if available */ + return CURLE_UNSUPPORTED_PROTOCOL; + case IF2IP_FOUND: + is_interface = TRUE; + /* + * We now have the numerical IP address in the 'myhost' buffer + */ + infof(data, "Local Interface %s is ip %s using address family %i\n", + dev, myhost, af); + done = 1; + break; + } + } + if(!is_interface) { + /* + * This was not an interface, resolve the name as a host name + * or IP number + * + * Temporarily force name resolution to use only the address type + * of the connection. The resolve functions should really be changed + * to take a type parameter instead. + */ + long ipver = conn->ip_version; + int rc; + + if(af == AF_INET) + conn->ip_version = CURL_IPRESOLVE_V4; +#ifdef ENABLE_IPV6 + else if(af == AF_INET6) + conn->ip_version = CURL_IPRESOLVE_V6; +#endif + + rc = Curl_resolv(conn, dev, 0, FALSE, &h); + if(rc == CURLRESOLV_PENDING) + (void)Curl_resolver_wait_resolv(conn, &h); + conn->ip_version = ipver; + + if(h) { + /* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */ + Curl_printable_address(h->addr, myhost, sizeof(myhost)); + infof(data, "Name '%s' family %i resolved to '%s' family %i\n", + dev, af, myhost, h->addr->ai_family); + Curl_resolv_unlock(data, h); + done = 1; + } + else { + /* + * provided dev was no interface (or interfaces are not supported + * e.g. solaris) no ip address and no domain we fail here + */ + done = -1; + } + } + + if(done > 0) { +#ifdef ENABLE_IPV6 + /* IPv6 address */ + if(af == AF_INET6) { +#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID + char *scope_ptr = strchr(myhost, '%'); + if(scope_ptr) + *(scope_ptr++) = 0; +#endif + if(Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0) { + si6->sin6_family = AF_INET6; + si6->sin6_port = htons(port); +#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID + if(scope_ptr) + /* The "myhost" string either comes from Curl_if2ip or from + Curl_printable_address. The latter returns only numeric scope + IDs and the former returns none at all. So the scope ID, if + present, is known to be numeric */ + si6->sin6_scope_id = atoi(scope_ptr); +#endif + } + sizeof_sa = sizeof(struct sockaddr_in6); + } + else +#endif + /* IPv4 address */ + if((af == AF_INET) && + (Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) { + si4->sin_family = AF_INET; + si4->sin_port = htons(port); + sizeof_sa = sizeof(struct sockaddr_in); + } + } + + if(done < 1) { + /* errorbuf is set false so failf will overwrite any message already in + the error buffer, so the user receives this error message instead of a + generic resolve error. */ + data->state.errorbuf = FALSE; + failf(data, "Couldn't bind to '%s'", dev); + return CURLE_INTERFACE_FAILED; + } + } + else { + /* no device was given, prepare sa to match af's needs */ +#ifdef ENABLE_IPV6 + if(af == AF_INET6) { + si6->sin6_family = AF_INET6; + si6->sin6_port = htons(port); + sizeof_sa = sizeof(struct sockaddr_in6); + } + else +#endif + if(af == AF_INET) { + si4->sin_family = AF_INET; + si4->sin_port = htons(port); + sizeof_sa = sizeof(struct sockaddr_in); + } + } + + for(;;) { + if(bind(sockfd, sock, sizeof_sa) >= 0) { + /* we succeeded to bind */ + struct Curl_sockaddr_storage add; + curl_socklen_t size = sizeof(add); + memset(&add, 0, sizeof(struct Curl_sockaddr_storage)); + if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) { + char buffer[STRERROR_LEN]; + data->state.os_errno = error = SOCKERRNO; + failf(data, "getsockname() failed with errno %d: %s", + error, Curl_strerror(error, buffer, sizeof(buffer))); + return CURLE_INTERFACE_FAILED; + } + infof(data, "Local port: %hu\n", port); + conn->bits.bound = TRUE; + return CURLE_OK; + } + + if(--portnum > 0) { + infof(data, "Bind to local port %hu failed, trying next\n", port); + port++; /* try next port */ + /* We re-use/clobber the port variable here below */ + if(sock->sa_family == AF_INET) + si4->sin_port = ntohs(port); +#ifdef ENABLE_IPV6 + else + si6->sin6_port = ntohs(port); +#endif + } + else + break; + } + { + char buffer[STRERROR_LEN]; + data->state.os_errno = error = SOCKERRNO; + failf(data, "bind failed with errno %d: %s", + error, Curl_strerror(error, buffer, sizeof(buffer))); + } + + return CURLE_INTERFACE_FAILED; +} + +/* + * verifyconnect() returns TRUE if the connect really has happened. + */ +static bool verifyconnect(curl_socket_t sockfd, int *error) +{ + bool rc = TRUE; +#ifdef SO_ERROR + int err = 0; + curl_socklen_t errSize = sizeof(err); + +#ifdef WIN32 + /* + * In October 2003 we effectively nullified this function on Windows due to + * problems with it using all CPU in multi-threaded cases. + * + * In May 2004, we bring it back to offer more info back on connect failures. + * Gisle Vanem could reproduce the former problems with this function, but + * could avoid them by adding this SleepEx() call below: + * + * "I don't have Rational Quantify, but the hint from his post was + * ntdll::NtRemoveIoCompletion(). So I'd assume the SleepEx (or maybe + * just Sleep(0) would be enough?) would release whatever + * mutex/critical-section the ntdll call is waiting on. + * + * Someone got to verify this on Win-NT 4.0, 2000." + */ + +#ifdef _WIN32_WCE + Sleep(0); +#else + SleepEx(0, FALSE); +#endif + +#endif + + if(0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize)) + err = SOCKERRNO; +#ifdef _WIN32_WCE + /* Old WinCE versions don't support SO_ERROR */ + if(WSAENOPROTOOPT == err) { + SET_SOCKERRNO(0); + err = 0; + } +#endif +#if defined(EBADIOCTL) && defined(__minix) + /* Minix 3.1.x doesn't support getsockopt on UDP sockets */ + if(EBADIOCTL == err) { + SET_SOCKERRNO(0); + err = 0; + } +#endif + if((0 == err) || (EISCONN == err)) + /* we are connected, awesome! */ + rc = TRUE; + else + /* This wasn't a successful connect */ + rc = FALSE; + if(error) + *error = err; +#else + (void)sockfd; + if(error) + *error = SOCKERRNO; +#endif + return rc; +} + +/* Used within the multi interface. Try next IP address, return TRUE if no + more address exists or error */ +static CURLcode trynextip(struct connectdata *conn, + int sockindex, + int tempindex) +{ + const int other = tempindex ^ 1; + CURLcode result = CURLE_COULDNT_CONNECT; + + /* First clean up after the failed socket. + Don't close it yet to ensure that the next IP's socket gets a different + file descriptor, which can prevent bugs when the curl_multi_socket_action + interface is used with certain select() replacements such as kqueue. */ + curl_socket_t fd_to_close = conn->tempsock[tempindex]; + conn->tempsock[tempindex] = CURL_SOCKET_BAD; + + if(sockindex == FIRSTSOCKET) { + Curl_addrinfo *ai = NULL; + int family = AF_UNSPEC; + + if(conn->tempaddr[tempindex]) { + /* find next address in the same protocol family */ + family = conn->tempaddr[tempindex]->ai_family; + ai = conn->tempaddr[tempindex]->ai_next; + } +#ifdef ENABLE_IPV6 + else if(conn->tempaddr[0]) { + /* happy eyeballs - try the other protocol family */ + int firstfamily = conn->tempaddr[0]->ai_family; + family = (firstfamily == AF_INET) ? AF_INET6 : AF_INET; + ai = conn->tempaddr[0]->ai_next; + } +#endif + + while(ai) { + if(conn->tempaddr[other]) { + /* we can safely skip addresses of the other protocol family */ + while(ai && ai->ai_family != family) + ai = ai->ai_next; + } + + if(ai) { + result = singleipconnect(conn, ai, &conn->tempsock[tempindex]); + if(result == CURLE_COULDNT_CONNECT) { + ai = ai->ai_next; + continue; + } + + conn->tempaddr[tempindex] = ai; + } + break; + } + } + + if(fd_to_close != CURL_SOCKET_BAD) + Curl_closesocket(conn, fd_to_close); + + return result; +} + +/* Copies connection info into the session handle to make it available + when the session handle is no longer associated with a connection. */ +void Curl_persistconninfo(struct connectdata *conn) +{ + memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN); + memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN); + conn->data->info.conn_scheme = conn->handler->scheme; + conn->data->info.conn_protocol = conn->handler->protocol; + conn->data->info.conn_primary_port = conn->primary_port; + conn->data->info.conn_local_port = conn->local_port; +} + +UNITTEST bool getaddressinfo(struct sockaddr *sa, char *addr, + long *port); + +/* retrieves ip address and port from a sockaddr structure. + note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */ +UNITTEST bool getaddressinfo(struct sockaddr *sa, char *addr, + long *port) +{ + struct sockaddr_in *si = NULL; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 *si6 = NULL; +#endif +#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX) + struct sockaddr_un *su = NULL; +#endif + + switch(sa->sa_family) { + case AF_INET: + si = (struct sockaddr_in *)(void *) sa; + if(Curl_inet_ntop(sa->sa_family, &si->sin_addr, + addr, MAX_IPADR_LEN)) { + unsigned short us_port = ntohs(si->sin_port); + *port = us_port; + return TRUE; + } + break; +#ifdef ENABLE_IPV6 + case AF_INET6: + si6 = (struct sockaddr_in6 *)(void *) sa; + if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr, + addr, MAX_IPADR_LEN)) { + unsigned short us_port = ntohs(si6->sin6_port); + *port = us_port; + return TRUE; + } + break; +#endif +#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX) + case AF_UNIX: + su = (struct sockaddr_un*)sa; + msnprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path); + *port = 0; + return TRUE; +#endif + default: + break; + } + + addr[0] = '\0'; + *port = 0; + errno = EAFNOSUPPORT; + return FALSE; +} + +/* retrieves the start/end point information of a socket of an established + connection */ +void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd) +{ + if(conn->socktype == SOCK_DGRAM) + /* there's no connection! */ + return; + +#if defined(HAVE_GETPEERNAME) || defined(HAVE_GETSOCKNAME) + if(!conn->bits.reuse && !conn->bits.tcp_fastopen) { + struct Curl_easy *data = conn->data; + char buffer[STRERROR_LEN]; + struct Curl_sockaddr_storage ssrem; + struct Curl_sockaddr_storage ssloc; + curl_socklen_t len; +#ifdef HAVE_GETPEERNAME + len = sizeof(struct Curl_sockaddr_storage); + if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) { + int error = SOCKERRNO; + failf(data, "getpeername() failed with errno %d: %s", + error, Curl_strerror(error, buffer, sizeof(buffer))); + return; + } +#endif +#ifdef HAVE_GETSOCKNAME + len = sizeof(struct Curl_sockaddr_storage); + memset(&ssloc, 0, sizeof(ssloc)); + if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) { + int error = SOCKERRNO; + failf(data, "getsockname() failed with errno %d: %s", + error, Curl_strerror(error, buffer, sizeof(buffer))); + return; + } +#endif +#ifdef HAVE_GETPEERNAME + if(!getaddressinfo((struct sockaddr*)&ssrem, + conn->primary_ip, &conn->primary_port)) { + failf(data, "ssrem inet_ntop() failed with errno %d: %s", + errno, Curl_strerror(errno, buffer, sizeof(buffer))); + return; + } + memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN); +#endif +#ifdef HAVE_GETSOCKNAME + if(!getaddressinfo((struct sockaddr*)&ssloc, + conn->local_ip, &conn->local_port)) { + failf(data, "ssloc inet_ntop() failed with errno %d: %s", + errno, Curl_strerror(errno, buffer, sizeof(buffer))); + return; + } +#endif + } +#else /* !HAVE_GETSOCKNAME && !HAVE_GETPEERNAME */ + (void)sockfd; /* unused */ +#endif + + /* persist connection info in session handle */ + Curl_persistconninfo(conn); +} + +/* + * Curl_is_connected() checks if the socket has connected. + */ + +CURLcode Curl_is_connected(struct connectdata *conn, + int sockindex, + bool *connected) +{ + struct Curl_easy *data = conn->data; + CURLcode result = CURLE_OK; + timediff_t allow; + int error = 0; + struct curltime now; + int rc; + int i; + + DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET); + + *connected = FALSE; /* a very negative world view is best */ + + if(conn->bits.tcpconnect[sockindex]) { + /* we are connected already! */ + *connected = TRUE; + return CURLE_OK; + } + + now = Curl_now(); + + /* figure out how long time we have left to connect */ + allow = Curl_timeleft(data, &now, TRUE); + + if(allow < 0) { + /* time-out, bail out, go home */ + failf(data, "Connection time-out"); + return CURLE_OPERATION_TIMEDOUT; + } + + for(i = 0; i<2; i++) { + const int other = i ^ 1; + if(conn->tempsock[i] == CURL_SOCKET_BAD) + continue; + +#ifdef mpeix + /* Call this function once now, and ignore the results. We do this to + "clear" the error state on the socket so that we can later read it + reliably. This is reported necessary on the MPE/iX operating system. */ + (void)verifyconnect(conn->tempsock[i], NULL); +#endif + + /* check socket for connect */ + rc = SOCKET_WRITABLE(conn->tempsock[i], 0); + + if(rc == 0) { /* no connection yet */ + error = 0; + if(Curl_timediff(now, conn->connecttime) >= conn->timeoutms_per_addr) { + infof(data, "After %ldms connect time, move on!\n", + conn->timeoutms_per_addr); + error = ETIMEDOUT; + } + + /* should we try another protocol family? */ + if(i == 0 && conn->tempaddr[1] == NULL && + (Curl_timediff(now, conn->connecttime) >= + data->set.happy_eyeballs_timeout)) { + trynextip(conn, sockindex, 1); + } + } + else if(rc == CURL_CSELECT_OUT || conn->bits.tcp_fastopen) { + if(verifyconnect(conn->tempsock[i], &error)) { + /* we are connected with TCP, awesome! */ + + /* use this socket from now on */ + conn->sock[sockindex] = conn->tempsock[i]; + conn->ip_addr = conn->tempaddr[i]; + conn->tempsock[i] = CURL_SOCKET_BAD; +#ifdef ENABLE_IPV6 + conn->bits.ipv6 = (conn->ip_addr->ai_family == AF_INET6)?TRUE:FALSE; +#endif + + /* close the other socket, if open */ + if(conn->tempsock[other] != CURL_SOCKET_BAD) { + Curl_closesocket(conn, conn->tempsock[other]); + conn->tempsock[other] = CURL_SOCKET_BAD; + } + + /* see if we need to do any proxy magic first once we connected */ + result = Curl_connected_proxy(conn, sockindex); + if(result) + return result; + + conn->bits.tcpconnect[sockindex] = TRUE; + + *connected = TRUE; + if(sockindex == FIRSTSOCKET) + Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */ + Curl_updateconninfo(conn, conn->sock[sockindex]); + Curl_verboseconnect(conn); + + return CURLE_OK; + } + infof(data, "Connection failed\n"); + } + else if(rc & CURL_CSELECT_ERR) + (void)verifyconnect(conn->tempsock[i], &error); + + /* + * The connection failed here, we should attempt to connect to the "next + * address" for the given host. But first remember the latest error. + */ + if(error) { + data->state.os_errno = error; + SET_SOCKERRNO(error); + if(conn->tempaddr[i]) { + CURLcode status; + char ipaddress[MAX_IPADR_LEN]; + char buffer[STRERROR_LEN]; + Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN); + infof(data, "connect to %s port %ld failed: %s\n", + ipaddress, conn->port, + Curl_strerror(error, buffer, sizeof(buffer))); + + conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ? + allow : allow / 2; + + status = trynextip(conn, sockindex, i); + if(status != CURLE_COULDNT_CONNECT + || conn->tempsock[other] == CURL_SOCKET_BAD) + /* the last attempt failed and no other sockets remain open */ + result = status; + } + } + } + + if(result) { + /* no more addresses to try */ + const char *hostname; + char buffer[STRERROR_LEN]; + + /* if the first address family runs out of addresses to try before + the happy eyeball timeout, go ahead and try the next family now */ + if(conn->tempaddr[1] == NULL) { + result = trynextip(conn, sockindex, 1); + if(!result) + return result; + } + + if(conn->bits.socksproxy) + hostname = conn->socks_proxy.host.name; + else if(conn->bits.httpproxy) + hostname = conn->http_proxy.host.name; + else if(conn->bits.conn_to_host) + hostname = conn->conn_to_host.name; + else + hostname = conn->host.name; + + failf(data, "Failed to connect to %s port %ld: %s", + hostname, conn->port, + Curl_strerror(error, buffer, sizeof(buffer))); + } + + return result; +} + +static void tcpnodelay(struct connectdata *conn, curl_socket_t sockfd) +{ +#if defined(TCP_NODELAY) +#if !defined(CURL_DISABLE_VERBOSE_STRINGS) + struct Curl_easy *data = conn->data; +#endif + curl_socklen_t onoff = (curl_socklen_t) 1; + int level = IPPROTO_TCP; + char buffer[STRERROR_LEN]; + +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) conn; +#endif + + if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff, + sizeof(onoff)) < 0) + infof(data, "Could not set TCP_NODELAY: %s\n", + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + else + infof(data, "TCP_NODELAY set\n"); +#else + (void)conn; + (void)sockfd; +#endif +} + +#ifdef SO_NOSIGPIPE +/* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when + sending data to a dead peer (instead of relying on the 4th argument to send + being MSG_NOSIGNAL). Possibly also existing and in use on other BSD + systems? */ +static void nosigpipe(struct connectdata *conn, + curl_socket_t sockfd) +{ + struct Curl_easy *data = conn->data; + int onoff = 1; + if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff, + sizeof(onoff)) < 0) { + char buffer[STRERROR_LEN]; + infof(data, "Could not set SO_NOSIGPIPE: %s\n", + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + } +} +#else +#define nosigpipe(x,y) Curl_nop_stmt +#endif + +#ifdef USE_WINSOCK +/* When you run a program that uses the Windows Sockets API, you may + experience slow performance when you copy data to a TCP server. + + https://support.microsoft.com/kb/823764 + + Work-around: Make the Socket Send Buffer Size Larger Than the Program Send + Buffer Size + + The problem described in this knowledge-base is applied only to pre-Vista + Windows. Following function trying to detect OS version and skips + SO_SNDBUF adjustment for Windows Vista and above. +*/ +#define DETECT_OS_NONE 0 +#define DETECT_OS_PREVISTA 1 +#define DETECT_OS_VISTA_OR_LATER 2 + +void Curl_sndbufset(curl_socket_t sockfd) +{ + int val = CURL_MAX_WRITE_SIZE + 32; + int curval = 0; + int curlen = sizeof(curval); + + static int detectOsState = DETECT_OS_NONE; + + if(detectOsState == DETECT_OS_NONE) { + if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT, + VERSION_GREATER_THAN_EQUAL)) + detectOsState = DETECT_OS_VISTA_OR_LATER; + else + detectOsState = DETECT_OS_PREVISTA; + } + + if(detectOsState == DETECT_OS_VISTA_OR_LATER) + return; + + if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0) + if(curval > val) + return; + + setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val)); +} +#endif + +/* + * singleipconnect() + * + * Note that even on connect fail it returns CURLE_OK, but with 'sock' set to + * CURL_SOCKET_BAD. Other errors will however return proper errors. + * + * singleipconnect() connects to the given IP only, and it may return without + * having connected. + */ +static CURLcode singleipconnect(struct connectdata *conn, + const Curl_addrinfo *ai, + curl_socket_t *sockp) +{ + struct Curl_sockaddr_ex addr; + int rc = -1; + int error = 0; + bool isconnected = FALSE; + struct Curl_easy *data = conn->data; + curl_socket_t sockfd; + CURLcode result; + char ipaddress[MAX_IPADR_LEN]; + long port; + bool is_tcp; +#ifdef TCP_FASTOPEN_CONNECT + int optval = 1; +#endif + char buffer[STRERROR_LEN]; + + *sockp = CURL_SOCKET_BAD; + + result = Curl_socket(conn, ai, &addr, &sockfd); + if(result) + /* Failed to create the socket, but still return OK since we signal the + lack of socket as well. This allows the parent function to keep looping + over alternative addresses/socket families etc. */ + return CURLE_OK; + + /* store remote address and port used in this connection attempt */ + if(!getaddressinfo((struct sockaddr*)&addr.sa_addr, + ipaddress, &port)) { + /* malformed address or bug in inet_ntop, try next address */ + failf(data, "sa_addr inet_ntop() failed with errno %d: %s", + errno, Curl_strerror(errno, buffer, sizeof(buffer))); + Curl_closesocket(conn, sockfd); + return CURLE_OK; + } + infof(data, " Trying %s:%ld...\n", ipaddress, port); + +#ifdef ENABLE_IPV6 + is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) && + addr.socktype == SOCK_STREAM; +#else + is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM; +#endif + if(is_tcp && data->set.tcp_nodelay) + tcpnodelay(conn, sockfd); + + nosigpipe(conn, sockfd); + + Curl_sndbufset(sockfd); + + if(is_tcp && data->set.tcp_keepalive) + tcpkeepalive(data, sockfd); + + if(data->set.fsockopt) { + /* activate callback for setting socket options */ + Curl_set_in_callback(data, true); + error = data->set.fsockopt(data->set.sockopt_client, + sockfd, + CURLSOCKTYPE_IPCXN); + Curl_set_in_callback(data, false); + + if(error == CURL_SOCKOPT_ALREADY_CONNECTED) + isconnected = TRUE; + else if(error) { + Curl_closesocket(conn, sockfd); /* close the socket and bail out */ + return CURLE_ABORTED_BY_CALLBACK; + } + } + + /* possibly bind the local end to an IP, interface or port */ + if(addr.family == AF_INET +#ifdef ENABLE_IPV6 + || addr.family == AF_INET6 +#endif + ) { + result = bindlocal(conn, sockfd, addr.family, + Curl_ipv6_scope((struct sockaddr*)&addr.sa_addr)); + if(result) { + Curl_closesocket(conn, sockfd); /* close socket and bail out */ + if(result == CURLE_UNSUPPORTED_PROTOCOL) { + /* The address family is not supported on this interface. + We can continue trying addresses */ + return CURLE_COULDNT_CONNECT; + } + return result; + } + } + + /* set socket non-blocking */ + (void)curlx_nonblock(sockfd, TRUE); + + conn->connecttime = Curl_now(); + if(conn->num_addr > 1) + Curl_expire(data, conn->timeoutms_per_addr, EXPIRE_DNS_PER_NAME); + + /* Connect TCP sockets, bind UDP */ + if(!isconnected && (conn->socktype == SOCK_STREAM)) { + if(conn->bits.tcp_fastopen) { +#if defined(CONNECT_DATA_IDEMPOTENT) /* Darwin */ +# if defined(HAVE_BUILTIN_AVAILABLE) + /* while connectx function is available since macOS 10.11 / iOS 9, + it did not have the interface declared correctly until + Xcode 9 / macOS SDK 10.13 */ + if(__builtin_available(macOS 10.11, iOS 9.0, tvOS 9.0, watchOS 2.0, *)) { + sa_endpoints_t endpoints; + endpoints.sae_srcif = 0; + endpoints.sae_srcaddr = NULL; + endpoints.sae_srcaddrlen = 0; + endpoints.sae_dstaddr = &addr.sa_addr; + endpoints.sae_dstaddrlen = addr.addrlen; + + rc = connectx(sockfd, &endpoints, SAE_ASSOCID_ANY, + CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT, + NULL, 0, NULL, NULL); + } + else { + rc = connect(sockfd, &addr.sa_addr, addr.addrlen); + } +# else + rc = connect(sockfd, &addr.sa_addr, addr.addrlen); +# endif /* HAVE_BUILTIN_AVAILABLE */ +#elif defined(TCP_FASTOPEN_CONNECT) /* Linux >= 4.11 */ + if(setsockopt(sockfd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT, + (void *)&optval, sizeof(optval)) < 0) + infof(data, "Failed to enable TCP Fast Open on fd %d\n", sockfd); + else + infof(data, "TCP_FASTOPEN_CONNECT set\n"); + + rc = connect(sockfd, &addr.sa_addr, addr.addrlen); +#elif defined(MSG_FASTOPEN) /* old Linux */ + if(conn->given->flags & PROTOPT_SSL) + rc = connect(sockfd, &addr.sa_addr, addr.addrlen); + else + rc = 0; /* Do nothing */ +#endif + } + else { + rc = connect(sockfd, &addr.sa_addr, addr.addrlen); + } + + if(-1 == rc) + error = SOCKERRNO; + } + else { + *sockp = sockfd; + return CURLE_OK; + } + + if(-1 == rc) { + switch(error) { + case EINPROGRESS: + case EWOULDBLOCK: +#if defined(EAGAIN) +#if (EAGAIN) != (EWOULDBLOCK) + /* On some platforms EAGAIN and EWOULDBLOCK are the + * same value, and on others they are different, hence + * the odd #if + */ + case EAGAIN: +#endif +#endif + result = CURLE_OK; + break; + + default: + /* unknown error, fallthrough and try another address! */ + infof(data, "Immediate connect fail for %s: %s\n", + ipaddress, Curl_strerror(error, buffer, sizeof(buffer))); + data->state.os_errno = error; + + /* connect failed */ + Curl_closesocket(conn, sockfd); + result = CURLE_COULDNT_CONNECT; + } + } + + if(!result) + *sockp = sockfd; + + return result; +} + +/* + * TCP connect to the given host with timeout, proxy or remote doesn't matter. + * There might be more than one IP address to try out. Fill in the passed + * pointer with the connected socket. + */ + +CURLcode Curl_connecthost(struct connectdata *conn, /* context */ + const struct Curl_dns_entry *remotehost) +{ + struct Curl_easy *data = conn->data; + struct curltime before = Curl_now(); + CURLcode result = CURLE_COULDNT_CONNECT; + + timediff_t timeout_ms = Curl_timeleft(data, &before, TRUE); + + if(timeout_ms < 0) { + /* a precaution, no need to continue if time already is up */ + failf(data, "Connection time-out"); + return CURLE_OPERATION_TIMEDOUT; + } + + conn->num_addr = Curl_num_addresses(remotehost->addr); + conn->tempaddr[0] = remotehost->addr; + conn->tempaddr[1] = NULL; + conn->tempsock[0] = CURL_SOCKET_BAD; + conn->tempsock[1] = CURL_SOCKET_BAD; + + /* Max time for the next connection attempt */ + conn->timeoutms_per_addr = + conn->tempaddr[0]->ai_next == NULL ? timeout_ms : timeout_ms / 2; + + /* start connecting to first IP */ + while(conn->tempaddr[0]) { + result = singleipconnect(conn, conn->tempaddr[0], &(conn->tempsock[0])); + if(!result) + break; + conn->tempaddr[0] = conn->tempaddr[0]->ai_next; + } + + if(conn->tempsock[0] == CURL_SOCKET_BAD) { + if(!result) + result = CURLE_COULDNT_CONNECT; + return result; + } + + data->info.numconnects++; /* to track the number of connections made */ + Curl_expire(conn->data, data->set.happy_eyeballs_timeout, + EXPIRE_HAPPY_EYEBALLS); + + return CURLE_OK; +} + +struct connfind { + struct connectdata *tofind; + bool found; +}; + +static int conn_is_conn(struct connectdata *conn, void *param) +{ + struct connfind *f = (struct connfind *)param; + if(conn == f->tofind) { + f->found = TRUE; + return 1; + } + return 0; +} + +/* + * Used to extract socket and connectdata struct for the most recent + * transfer on the given Curl_easy. + * + * The returned socket will be CURL_SOCKET_BAD in case of failure! + */ +curl_socket_t Curl_getconnectinfo(struct Curl_easy *data, + struct connectdata **connp) +{ + DEBUGASSERT(data); + + /* this works for an easy handle: + * - that has been used for curl_easy_perform() + * - that is associated with a multi handle, and whose connection + * was detached with CURLOPT_CONNECT_ONLY + */ + if(data->state.lastconnect && (data->multi_easy || data->multi)) { + struct connectdata *c = data->state.lastconnect; + struct connfind find; + find.tofind = data->state.lastconnect; + find.found = FALSE; + + Curl_conncache_foreach(data, data->multi_easy? + &data->multi_easy->conn_cache: + &data->multi->conn_cache, &find, conn_is_conn); + + if(!find.found) { + data->state.lastconnect = NULL; + return CURL_SOCKET_BAD; + } + + if(connp) { + /* only store this if the caller cares for it */ + *connp = c; + c->data = data; + } + return c->sock[FIRSTSOCKET]; + } + else + return CURL_SOCKET_BAD; +} + +/* + * Check if a connection seems to be alive. + */ +bool Curl_connalive(struct connectdata *conn) +{ + /* First determine if ssl */ + if(conn->ssl[FIRSTSOCKET].use) { + /* use the SSL context */ + if(!Curl_ssl_check_cxn(conn)) + return false; /* FIN received */ + } +/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */ +#ifdef MSG_PEEK + else if(conn->sock[FIRSTSOCKET] == CURL_SOCKET_BAD) + return false; + else { + /* use the socket */ + char buf; + if(recv((RECV_TYPE_ARG1)conn->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf, + (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) { + return false; /* FIN received */ + } + } +#endif + return true; +} + +/* + * Close a socket. + * + * 'conn' can be NULL, beware! + */ +int Curl_closesocket(struct connectdata *conn, + curl_socket_t sock) +{ + if(conn && conn->fclosesocket) { + if((sock == conn->sock[SECONDARYSOCKET]) && + conn->sock_accepted[SECONDARYSOCKET]) + /* if this socket matches the second socket, and that was created with + accept, then we MUST NOT call the callback but clear the accepted + status */ + conn->sock_accepted[SECONDARYSOCKET] = FALSE; + else { + int rc; + Curl_multi_closed(conn->data, sock); + Curl_set_in_callback(conn->data, true); + rc = conn->fclosesocket(conn->closesocket_client, sock); + Curl_set_in_callback(conn->data, false); + return rc; + } + } + + if(conn) + /* tell the multi-socket code about this */ + Curl_multi_closed(conn->data, sock); + + sclose(sock); + + return 0; +} + +/* + * Create a socket based on info from 'conn' and 'ai'. + * + * 'addr' should be a pointer to the correct struct to get data back, or NULL. + * 'sockfd' must be a pointer to a socket descriptor. + * + * If the open socket callback is set, used that! + * + */ +CURLcode Curl_socket(struct connectdata *conn, + const Curl_addrinfo *ai, + struct Curl_sockaddr_ex *addr, + curl_socket_t *sockfd) +{ + struct Curl_easy *data = conn->data; + struct Curl_sockaddr_ex dummy; + + if(!addr) + /* if the caller doesn't want info back, use a local temp copy */ + addr = &dummy; + + /* + * The Curl_sockaddr_ex structure is basically libcurl's external API + * curl_sockaddr structure with enough space available to directly hold + * any protocol-specific address structures. The variable declared here + * will be used to pass / receive data to/from the fopensocket callback + * if this has been set, before that, it is initialized from parameters. + */ + + addr->family = ai->ai_family; + addr->socktype = conn->socktype; + addr->protocol = conn->socktype == SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol; + addr->addrlen = ai->ai_addrlen; + + if(addr->addrlen > sizeof(struct Curl_sockaddr_storage)) + addr->addrlen = sizeof(struct Curl_sockaddr_storage); + memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen); + + if(data->set.fopensocket) { + /* + * If the opensocket callback is set, all the destination address + * information is passed to the callback. Depending on this information the + * callback may opt to abort the connection, this is indicated returning + * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When + * the callback returns a valid socket the destination address information + * might have been changed and this 'new' address will actually be used + * here to connect. + */ + Curl_set_in_callback(data, true); + *sockfd = data->set.fopensocket(data->set.opensocket_client, + CURLSOCKTYPE_IPCXN, + (struct curl_sockaddr *)addr); + Curl_set_in_callback(data, false); + } + else + /* opensocket callback not set, so simply create the socket now */ + *sockfd = socket(addr->family, addr->socktype, addr->protocol); + + if(*sockfd == CURL_SOCKET_BAD) + /* no socket, no connection */ + return CURLE_COULDNT_CONNECT; + +#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) + if(conn->scope_id && (addr->family == AF_INET6)) { + struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr; + sa6->sin6_scope_id = conn->scope_id; + } +#endif + + return CURLE_OK; + +} + +/* + * Curl_conncontrol() marks streams or connection for closure. + */ +void Curl_conncontrol(struct connectdata *conn, + int ctrl /* see defines in header */ +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + , const char *reason +#endif + ) +{ + /* close if a connection, or a stream that isn't multiplexed */ + bool closeit = (ctrl == CONNCTRL_CONNECTION) || + ((ctrl == CONNCTRL_STREAM) && !(conn->handler->flags & PROTOPT_STREAM)); + if((ctrl == CONNCTRL_STREAM) && + (conn->handler->flags & PROTOPT_STREAM)) + DEBUGF(infof(conn->data, "Kill stream: %s\n", reason)); + else if((bit)closeit != conn->bits.close) { + DEBUGF(infof(conn->data, "Marked for [%s]: %s\n", + closeit?"closure":"keep alive", reason)); + conn->bits.close = closeit; /* the only place in the source code that + should assign this bit */ + } +} + +/* Data received can be cached at various levels, so check them all here. */ +bool Curl_conn_data_pending(struct connectdata *conn, int sockindex) +{ + int readable; + + if(Curl_ssl_data_pending(conn, sockindex) || + Curl_recv_has_postponed_data(conn, sockindex)) + return true; + + readable = SOCKET_READABLE(conn->sock[sockindex], 0); + return (readable > 0 && (readable & CURL_CSELECT_IN)); +} diff --git a/dependencies/cmcurl/lib/connect.h b/dependencies/cmcurl/lib/connect.h new file mode 100644 index 0000000..6a5c755 --- /dev/null +++ b/dependencies/cmcurl/lib/connect.h @@ -0,0 +1,144 @@ +#ifndef HEADER_CURL_CONNECT_H +#define HEADER_CURL_CONNECT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#include "nonblock.h" /* for curlx_nonblock(), formerly Curl_nonblock() */ +#include "sockaddr.h" +#include "timeval.h" + +CURLcode Curl_is_connected(struct connectdata *conn, + int sockindex, + bool *connected); + +CURLcode Curl_connecthost(struct connectdata *conn, + const struct Curl_dns_entry *host); + +/* generic function that returns how much time there's left to run, according + to the timeouts set */ +timediff_t Curl_timeleft(struct Curl_easy *data, + struct curltime *nowp, + bool duringconnect); + +#define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */ + +/* + * Used to extract socket and connectdata struct for the most recent + * transfer on the given Curl_easy. + * + * The returned socket will be CURL_SOCKET_BAD in case of failure! + */ +curl_socket_t Curl_getconnectinfo(struct Curl_easy *data, + struct connectdata **connp); + +/* + * Check if a connection seems to be alive. + */ +bool Curl_connalive(struct connectdata *conn); + +#ifdef USE_WINSOCK +/* When you run a program that uses the Windows Sockets API, you may + experience slow performance when you copy data to a TCP server. + + https://support.microsoft.com/kb/823764 + + Work-around: Make the Socket Send Buffer Size Larger Than the Program Send + Buffer Size + +*/ +void Curl_sndbufset(curl_socket_t sockfd); +#else +#define Curl_sndbufset(y) Curl_nop_stmt +#endif + +void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd); +void Curl_persistconninfo(struct connectdata *conn); +int Curl_closesocket(struct connectdata *conn, curl_socket_t sock); + +/* + * The Curl_sockaddr_ex structure is basically libcurl's external API + * curl_sockaddr structure with enough space available to directly hold any + * protocol-specific address structures. The variable declared here will be + * used to pass / receive data to/from the fopensocket callback if this has + * been set, before that, it is initialized from parameters. + */ +struct Curl_sockaddr_ex { + int family; + int socktype; + int protocol; + unsigned int addrlen; + union { + struct sockaddr addr; + struct Curl_sockaddr_storage buff; + } _sa_ex_u; +}; +#define sa_addr _sa_ex_u.addr + +/* + * Create a socket based on info from 'conn' and 'ai'. + * + * Fill in 'addr' and 'sockfd' accordingly if OK is returned. If the open + * socket callback is set, used that! + * + */ +CURLcode Curl_socket(struct connectdata *conn, + const Curl_addrinfo *ai, + struct Curl_sockaddr_ex *addr, + curl_socket_t *sockfd); + +/* + * Curl_conncontrol() marks the end of a connection/stream. The 'closeit' + * argument specifies if it is the end of a connection or a stream. + * + * For stream-based protocols (such as HTTP/2), a stream close will not cause + * a connection close. Other protocols will close the connection for both + * cases. + * + * It sets the bit.close bit to TRUE (with an explanation for debug builds), + * when the connection will close. + */ + +#define CONNCTRL_KEEP 0 /* undo a marked closure */ +#define CONNCTRL_CONNECTION 1 +#define CONNCTRL_STREAM 2 + +void Curl_conncontrol(struct connectdata *conn, + int closeit +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + , const char *reason +#endif + ); + +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) +#define streamclose(x,y) Curl_conncontrol(x, CONNCTRL_STREAM, y) +#define connclose(x,y) Curl_conncontrol(x, CONNCTRL_CONNECTION, y) +#define connkeep(x,y) Curl_conncontrol(x, CONNCTRL_KEEP, y) +#else /* if !DEBUGBUILD || CURL_DISABLE_VERBOSE_STRINGS */ +#define streamclose(x,y) Curl_conncontrol(x, CONNCTRL_STREAM) +#define connclose(x,y) Curl_conncontrol(x, CONNCTRL_CONNECTION) +#define connkeep(x,y) Curl_conncontrol(x, CONNCTRL_KEEP) +#endif + +bool Curl_conn_data_pending(struct connectdata *conn, int sockindex); + +#endif /* HEADER_CURL_CONNECT_H */ diff --git a/dependencies/cmcurl/lib/content_encoding.c b/dependencies/cmcurl/lib/content_encoding.c new file mode 100644 index 0000000..6d47537 --- /dev/null +++ b/dependencies/cmcurl/lib/content_encoding.c @@ -0,0 +1,1020 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "urldata.h" +#include +#include + +#ifdef HAVE_ZLIB_H +#include +#ifdef __SYMBIAN32__ +/* zlib pollutes the namespace with this definition */ +#undef WIN32 +#endif +#endif + +#ifdef HAVE_BROTLI +#include +#endif + +#include "sendf.h" +#include "http.h" +#include "content_encoding.h" +#include "strdup.h" +#include "strcase.h" +#include "curl_memory.h" +#include "memdebug.h" + +#define CONTENT_ENCODING_DEFAULT "identity" + +#ifndef CURL_DISABLE_HTTP + +#define DSIZ CURL_MAX_WRITE_SIZE /* buffer size for decompressed data */ + + +#ifdef HAVE_LIBZ + +/* Comment this out if zlib is always going to be at least ver. 1.2.0.4 + (doing so will reduce code size slightly). */ +#define OLD_ZLIB_SUPPORT 1 + +#define GZIP_MAGIC_0 0x1f +#define GZIP_MAGIC_1 0x8b + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ + +typedef enum { + ZLIB_UNINIT, /* uninitialized */ + ZLIB_INIT, /* initialized */ + ZLIB_INFLATING, /* inflating started. */ + ZLIB_EXTERNAL_TRAILER, /* reading external trailer */ + ZLIB_GZIP_HEADER, /* reading gzip header */ + ZLIB_GZIP_INFLATING, /* inflating gzip stream */ + ZLIB_INIT_GZIP /* initialized in transparent gzip mode */ +} zlibInitState; + +/* Writer parameters. */ +typedef struct { + zlibInitState zlib_init; /* zlib init state */ + uInt trailerlen; /* Remaining trailer byte count. */ + z_stream z; /* State structure for zlib. */ +} zlib_params; + + +static voidpf +zalloc_cb(voidpf opaque, unsigned int items, unsigned int size) +{ + (void) opaque; + /* not a typo, keep it calloc() */ + return (voidpf) calloc(items, size); +} + +static void +zfree_cb(voidpf opaque, voidpf ptr) +{ + (void) opaque; + free(ptr); +} + +static CURLcode +process_zlib_error(struct connectdata *conn, z_stream *z) +{ + struct Curl_easy *data = conn->data; + if(z->msg) + failf(data, "Error while processing content unencoding: %s", + z->msg); + else + failf(data, "Error while processing content unencoding: " + "Unknown failure within decompression software."); + + return CURLE_BAD_CONTENT_ENCODING; +} + +static CURLcode +exit_zlib(struct connectdata *conn, + z_stream *z, zlibInitState *zlib_init, CURLcode result) +{ + if(*zlib_init == ZLIB_GZIP_HEADER) + Curl_safefree(z->next_in); + + if(*zlib_init != ZLIB_UNINIT) { + if(inflateEnd(z) != Z_OK && result == CURLE_OK) + result = process_zlib_error(conn, z); + *zlib_init = ZLIB_UNINIT; + } + + return result; +} + +static CURLcode process_trailer(struct connectdata *conn, zlib_params *zp) +{ + z_stream *z = &zp->z; + CURLcode result = CURLE_OK; + uInt len = z->avail_in < zp->trailerlen? z->avail_in: zp->trailerlen; + + /* Consume expected trailer bytes. Terminate stream if exhausted. + Issue an error if unexpected bytes follow. */ + + zp->trailerlen -= len; + z->avail_in -= len; + z->next_in += len; + if(z->avail_in) + result = CURLE_WRITE_ERROR; + if(result || !zp->trailerlen) + result = exit_zlib(conn, z, &zp->zlib_init, result); + else { + /* Only occurs for gzip with zlib < 1.2.0.4 or raw deflate. */ + zp->zlib_init = ZLIB_EXTERNAL_TRAILER; + } + return result; +} + +static CURLcode inflate_stream(struct connectdata *conn, + contenc_writer *writer, zlibInitState started) +{ + zlib_params *zp = (zlib_params *) &writer->params; + z_stream *z = &zp->z; /* zlib state structure */ + uInt nread = z->avail_in; + Bytef *orig_in = z->next_in; + bool done = FALSE; + CURLcode result = CURLE_OK; /* Curl_client_write status */ + char *decomp; /* Put the decompressed data here. */ + + /* Check state. */ + if(zp->zlib_init != ZLIB_INIT && + zp->zlib_init != ZLIB_INFLATING && + zp->zlib_init != ZLIB_INIT_GZIP && + zp->zlib_init != ZLIB_GZIP_INFLATING) + return exit_zlib(conn, z, &zp->zlib_init, CURLE_WRITE_ERROR); + + /* Dynamically allocate a buffer for decompression because it's uncommonly + large to hold on the stack */ + decomp = malloc(DSIZ); + if(decomp == NULL) + return exit_zlib(conn, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); + + /* because the buffer size is fixed, iteratively decompress and transfer to + the client via downstream_write function. */ + while(!done) { + int status; /* zlib status */ + done = TRUE; + + /* (re)set buffer for decompressed output for every iteration */ + z->next_out = (Bytef *) decomp; + z->avail_out = DSIZ; + +#ifdef Z_BLOCK + /* Z_BLOCK is only available in zlib ver. >= 1.2.0.5 */ + status = inflate(z, Z_BLOCK); +#else + /* fallback for zlib ver. < 1.2.0.5 */ + status = inflate(z, Z_SYNC_FLUSH); +#endif + + /* Flush output data if some. */ + if(z->avail_out != DSIZ) { + if(status == Z_OK || status == Z_STREAM_END) { + zp->zlib_init = started; /* Data started. */ + result = Curl_unencode_write(conn, writer->downstream, decomp, + DSIZ - z->avail_out); + if(result) { + exit_zlib(conn, z, &zp->zlib_init, result); + break; + } + } + } + + /* Dispatch by inflate() status. */ + switch(status) { + case Z_OK: + /* Always loop: there may be unflushed latched data in zlib state. */ + done = FALSE; + break; + case Z_BUF_ERROR: + /* No more data to flush: just exit loop. */ + break; + case Z_STREAM_END: + result = process_trailer(conn, zp); + break; + case Z_DATA_ERROR: + /* some servers seem to not generate zlib headers, so this is an attempt + to fix and continue anyway */ + if(zp->zlib_init == ZLIB_INIT) { + /* Do not use inflateReset2(): only available since zlib 1.2.3.4. */ + (void) inflateEnd(z); /* don't care about the return code */ + if(inflateInit2(z, -MAX_WBITS) == Z_OK) { + z->next_in = orig_in; + z->avail_in = nread; + zp->zlib_init = ZLIB_INFLATING; + zp->trailerlen = 4; /* Tolerate up to 4 unknown trailer bytes. */ + done = FALSE; + break; + } + zp->zlib_init = ZLIB_UNINIT; /* inflateEnd() already called. */ + } + /* FALLTHROUGH */ + default: + result = exit_zlib(conn, z, &zp->zlib_init, process_zlib_error(conn, z)); + break; + } + } + free(decomp); + + /* We're about to leave this call so the `nread' data bytes won't be seen + again. If we are in a state that would wrongly allow restart in raw mode + at the next call, assume output has already started. */ + if(nread && zp->zlib_init == ZLIB_INIT) + zp->zlib_init = started; /* Cannot restart anymore. */ + + return result; +} + + +/* Deflate handler. */ +static CURLcode deflate_init_writer(struct connectdata *conn, + contenc_writer *writer) +{ + zlib_params *zp = (zlib_params *) &writer->params; + z_stream *z = &zp->z; /* zlib state structure */ + + if(!writer->downstream) + return CURLE_WRITE_ERROR; + + /* Initialize zlib */ + z->zalloc = (alloc_func) zalloc_cb; + z->zfree = (free_func) zfree_cb; + + if(inflateInit(z) != Z_OK) + return process_zlib_error(conn, z); + zp->zlib_init = ZLIB_INIT; + return CURLE_OK; +} + +static CURLcode deflate_unencode_write(struct connectdata *conn, + contenc_writer *writer, + const char *buf, size_t nbytes) +{ + zlib_params *zp = (zlib_params *) &writer->params; + z_stream *z = &zp->z; /* zlib state structure */ + + /* Set the compressed input when this function is called */ + z->next_in = (Bytef *) buf; + z->avail_in = (uInt) nbytes; + + if(zp->zlib_init == ZLIB_EXTERNAL_TRAILER) + return process_trailer(conn, zp); + + /* Now uncompress the data */ + return inflate_stream(conn, writer, ZLIB_INFLATING); +} + +static void deflate_close_writer(struct connectdata *conn, + contenc_writer *writer) +{ + zlib_params *zp = (zlib_params *) &writer->params; + z_stream *z = &zp->z; /* zlib state structure */ + + exit_zlib(conn, z, &zp->zlib_init, CURLE_OK); +} + +static const content_encoding deflate_encoding = { + "deflate", + NULL, + deflate_init_writer, + deflate_unencode_write, + deflate_close_writer, + sizeof(zlib_params) +}; + + +/* Gzip handler. */ +static CURLcode gzip_init_writer(struct connectdata *conn, + contenc_writer *writer) +{ + zlib_params *zp = (zlib_params *) &writer->params; + z_stream *z = &zp->z; /* zlib state structure */ + + if(!writer->downstream) + return CURLE_WRITE_ERROR; + + /* Initialize zlib */ + z->zalloc = (alloc_func) zalloc_cb; + z->zfree = (free_func) zfree_cb; + + if(strcmp(zlibVersion(), "1.2.0.4") >= 0) { + /* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */ + if(inflateInit2(z, MAX_WBITS + 32) != Z_OK) { + return process_zlib_error(conn, z); + } + zp->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */ + } + else { + /* we must parse the gzip header and trailer ourselves */ + if(inflateInit2(z, -MAX_WBITS) != Z_OK) { + return process_zlib_error(conn, z); + } + zp->trailerlen = 8; /* A CRC-32 and a 32-bit input size (RFC 1952, 2.2) */ + zp->zlib_init = ZLIB_INIT; /* Initial call state */ + } + + return CURLE_OK; +} + +#ifdef OLD_ZLIB_SUPPORT +/* Skip over the gzip header */ +static enum { + GZIP_OK, + GZIP_BAD, + GZIP_UNDERFLOW +} check_gzip_header(unsigned char const *data, ssize_t len, ssize_t *headerlen) +{ + int method, flags; + const ssize_t totallen = len; + + /* The shortest header is 10 bytes */ + if(len < 10) + return GZIP_UNDERFLOW; + + if((data[0] != GZIP_MAGIC_0) || (data[1] != GZIP_MAGIC_1)) + return GZIP_BAD; + + method = data[2]; + flags = data[3]; + + if(method != Z_DEFLATED || (flags & RESERVED) != 0) { + /* Can't handle this compression method or unknown flag */ + return GZIP_BAD; + } + + /* Skip over time, xflags, OS code and all previous bytes */ + len -= 10; + data += 10; + + if(flags & EXTRA_FIELD) { + ssize_t extra_len; + + if(len < 2) + return GZIP_UNDERFLOW; + + extra_len = (data[1] << 8) | data[0]; + + if(len < (extra_len + 2)) + return GZIP_UNDERFLOW; + + len -= (extra_len + 2); + data += (extra_len + 2); + } + + if(flags & ORIG_NAME) { + /* Skip over NUL-terminated file name */ + while(len && *data) { + --len; + ++data; + } + if(!len || *data) + return GZIP_UNDERFLOW; + + /* Skip over the NUL */ + --len; + ++data; + } + + if(flags & COMMENT) { + /* Skip over NUL-terminated comment */ + while(len && *data) { + --len; + ++data; + } + if(!len || *data) + return GZIP_UNDERFLOW; + + /* Skip over the NUL */ + --len; + } + + if(flags & HEAD_CRC) { + if(len < 2) + return GZIP_UNDERFLOW; + + len -= 2; + } + + *headerlen = totallen - len; + return GZIP_OK; +} +#endif + +static CURLcode gzip_unencode_write(struct connectdata *conn, + contenc_writer *writer, + const char *buf, size_t nbytes) +{ + zlib_params *zp = (zlib_params *) &writer->params; + z_stream *z = &zp->z; /* zlib state structure */ + + if(zp->zlib_init == ZLIB_INIT_GZIP) { + /* Let zlib handle the gzip decompression entirely */ + z->next_in = (Bytef *) buf; + z->avail_in = (uInt) nbytes; + /* Now uncompress the data */ + return inflate_stream(conn, writer, ZLIB_INIT_GZIP); + } + +#ifndef OLD_ZLIB_SUPPORT + /* Support for old zlib versions is compiled away and we are running with + an old version, so return an error. */ + return exit_zlib(conn, z, &zp->zlib_init, CURLE_WRITE_ERROR); + +#else + /* This next mess is to get around the potential case where there isn't + * enough data passed in to skip over the gzip header. If that happens, we + * malloc a block and copy what we have then wait for the next call. If + * there still isn't enough (this is definitely a worst-case scenario), we + * make the block bigger, copy the next part in and keep waiting. + * + * This is only required with zlib versions < 1.2.0.4 as newer versions + * can handle the gzip header themselves. + */ + + switch(zp->zlib_init) { + /* Skip over gzip header? */ + case ZLIB_INIT: + { + /* Initial call state */ + ssize_t hlen; + + switch(check_gzip_header((unsigned char *) buf, nbytes, &hlen)) { + case GZIP_OK: + z->next_in = (Bytef *) buf + hlen; + z->avail_in = (uInt) (nbytes - hlen); + zp->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */ + break; + + case GZIP_UNDERFLOW: + /* We need more data so we can find the end of the gzip header. It's + * possible that the memory block we malloc here will never be freed if + * the transfer abruptly aborts after this point. Since it's unlikely + * that circumstances will be right for this code path to be followed in + * the first place, and it's even more unlikely for a transfer to fail + * immediately afterwards, it should seldom be a problem. + */ + z->avail_in = (uInt) nbytes; + z->next_in = malloc(z->avail_in); + if(z->next_in == NULL) { + return exit_zlib(conn, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); + } + memcpy(z->next_in, buf, z->avail_in); + zp->zlib_init = ZLIB_GZIP_HEADER; /* Need more gzip header data state */ + /* We don't have any data to inflate yet */ + return CURLE_OK; + + case GZIP_BAD: + default: + return exit_zlib(conn, z, &zp->zlib_init, process_zlib_error(conn, z)); + } + + } + break; + + case ZLIB_GZIP_HEADER: + { + /* Need more gzip header data state */ + ssize_t hlen; + z->avail_in += (uInt) nbytes; + z->next_in = Curl_saferealloc(z->next_in, z->avail_in); + if(z->next_in == NULL) { + return exit_zlib(conn, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); + } + /* Append the new block of data to the previous one */ + memcpy(z->next_in + z->avail_in - nbytes, buf, nbytes); + + switch(check_gzip_header(z->next_in, z->avail_in, &hlen)) { + case GZIP_OK: + /* This is the zlib stream data */ + free(z->next_in); + /* Don't point into the malloced block since we just freed it */ + z->next_in = (Bytef *) buf + hlen + nbytes - z->avail_in; + z->avail_in = (uInt) (z->avail_in - hlen); + zp->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */ + break; + + case GZIP_UNDERFLOW: + /* We still don't have any data to inflate! */ + return CURLE_OK; + + case GZIP_BAD: + default: + return exit_zlib(conn, z, &zp->zlib_init, process_zlib_error(conn, z)); + } + + } + break; + + case ZLIB_EXTERNAL_TRAILER: + z->next_in = (Bytef *) buf; + z->avail_in = (uInt) nbytes; + return process_trailer(conn, zp); + + case ZLIB_GZIP_INFLATING: + default: + /* Inflating stream state */ + z->next_in = (Bytef *) buf; + z->avail_in = (uInt) nbytes; + break; + } + + if(z->avail_in == 0) { + /* We don't have any data to inflate; wait until next time */ + return CURLE_OK; + } + + /* We've parsed the header, now uncompress the data */ + return inflate_stream(conn, writer, ZLIB_GZIP_INFLATING); +#endif +} + +static void gzip_close_writer(struct connectdata *conn, + contenc_writer *writer) +{ + zlib_params *zp = (zlib_params *) &writer->params; + z_stream *z = &zp->z; /* zlib state structure */ + + exit_zlib(conn, z, &zp->zlib_init, CURLE_OK); +} + +static const content_encoding gzip_encoding = { + "gzip", + "x-gzip", + gzip_init_writer, + gzip_unencode_write, + gzip_close_writer, + sizeof(zlib_params) +}; + +#endif /* HAVE_LIBZ */ + + +#ifdef HAVE_BROTLI + +/* Writer parameters. */ +typedef struct { + BrotliDecoderState *br; /* State structure for brotli. */ +} brotli_params; + + +static CURLcode brotli_map_error(BrotliDecoderErrorCode be) +{ + switch(be) { + case BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE: + case BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE: + case BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET: + case BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME: + case BROTLI_DECODER_ERROR_FORMAT_CL_SPACE: + case BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE: + case BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT: + case BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1: + case BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2: + case BROTLI_DECODER_ERROR_FORMAT_TRANSFORM: + case BROTLI_DECODER_ERROR_FORMAT_DICTIONARY: + case BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS: + case BROTLI_DECODER_ERROR_FORMAT_PADDING_1: + case BROTLI_DECODER_ERROR_FORMAT_PADDING_2: +#ifdef BROTLI_DECODER_ERROR_COMPOUND_DICTIONARY + case BROTLI_DECODER_ERROR_COMPOUND_DICTIONARY: +#endif +#ifdef BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET + case BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET: +#endif + case BROTLI_DECODER_ERROR_INVALID_ARGUMENTS: + return CURLE_BAD_CONTENT_ENCODING; + case BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES: + case BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS: + case BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP: + case BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1: + case BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2: + case BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES: + return CURLE_OUT_OF_MEMORY; + default: + break; + } + return CURLE_WRITE_ERROR; +} + +static CURLcode brotli_init_writer(struct connectdata *conn, + contenc_writer *writer) +{ + brotli_params *bp = (brotli_params *) &writer->params; + + (void) conn; + + if(!writer->downstream) + return CURLE_WRITE_ERROR; + + bp->br = BrotliDecoderCreateInstance(NULL, NULL, NULL); + return bp->br? CURLE_OK: CURLE_OUT_OF_MEMORY; +} + +static CURLcode brotli_unencode_write(struct connectdata *conn, + contenc_writer *writer, + const char *buf, size_t nbytes) +{ + brotli_params *bp = (brotli_params *) &writer->params; + const uint8_t *src = (const uint8_t *) buf; + char *decomp; + uint8_t *dst; + size_t dstleft; + CURLcode result = CURLE_OK; + BrotliDecoderResult r = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT; + + if(!bp->br) + return CURLE_WRITE_ERROR; /* Stream already ended. */ + + decomp = malloc(DSIZ); + if(!decomp) + return CURLE_OUT_OF_MEMORY; + + while((nbytes || r == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) && + result == CURLE_OK) { + dst = (uint8_t *) decomp; + dstleft = DSIZ; + r = BrotliDecoderDecompressStream(bp->br, + &nbytes, &src, &dstleft, &dst, NULL); + result = Curl_unencode_write(conn, writer->downstream, + decomp, DSIZ - dstleft); + if(result) + break; + switch(r) { + case BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT: + case BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT: + break; + case BROTLI_DECODER_RESULT_SUCCESS: + BrotliDecoderDestroyInstance(bp->br); + bp->br = NULL; + if(nbytes) + result = CURLE_WRITE_ERROR; + break; + default: + result = brotli_map_error(BrotliDecoderGetErrorCode(bp->br)); + break; + } + } + free(decomp); + return result; +} + +static void brotli_close_writer(struct connectdata *conn, + contenc_writer *writer) +{ + brotli_params *bp = (brotli_params *) &writer->params; + + (void) conn; + + if(bp->br) { + BrotliDecoderDestroyInstance(bp->br); + bp->br = NULL; + } +} + +static const content_encoding brotli_encoding = { + "br", + NULL, + brotli_init_writer, + brotli_unencode_write, + brotli_close_writer, + sizeof(brotli_params) +}; +#endif + + +/* Identity handler. */ +static CURLcode identity_init_writer(struct connectdata *conn, + contenc_writer *writer) +{ + (void) conn; + return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR; +} + +static CURLcode identity_unencode_write(struct connectdata *conn, + contenc_writer *writer, + const char *buf, size_t nbytes) +{ + return Curl_unencode_write(conn, writer->downstream, buf, nbytes); +} + +static void identity_close_writer(struct connectdata *conn, + contenc_writer *writer) +{ + (void) conn; + (void) writer; +} + +static const content_encoding identity_encoding = { + "identity", + "none", + identity_init_writer, + identity_unencode_write, + identity_close_writer, + 0 +}; + + +/* supported content encodings table. */ +static const content_encoding * const encodings[] = { + &identity_encoding, +#ifdef HAVE_LIBZ + &deflate_encoding, + &gzip_encoding, +#endif +#ifdef HAVE_BROTLI + &brotli_encoding, +#endif + NULL +}; + + +/* Return a list of comma-separated names of supported encodings. */ +char *Curl_all_content_encodings(void) +{ + size_t len = 0; + const content_encoding * const *cep; + const content_encoding *ce; + char *ace; + + for(cep = encodings; *cep; cep++) { + ce = *cep; + if(!strcasecompare(ce->name, CONTENT_ENCODING_DEFAULT)) + len += strlen(ce->name) + 2; + } + + if(!len) + return strdup(CONTENT_ENCODING_DEFAULT); + + ace = malloc(len); + if(ace) { + char *p = ace; + for(cep = encodings; *cep; cep++) { + ce = *cep; + if(!strcasecompare(ce->name, CONTENT_ENCODING_DEFAULT)) { + strcpy(p, ce->name); + p += strlen(p); + *p++ = ','; + *p++ = ' '; + } + } + p[-2] = '\0'; + } + + return ace; +} + + +/* Real client writer: no downstream. */ +static CURLcode client_init_writer(struct connectdata *conn, + contenc_writer *writer) +{ + (void) conn; + return writer->downstream? CURLE_WRITE_ERROR: CURLE_OK; +} + +static CURLcode client_unencode_write(struct connectdata *conn, + contenc_writer *writer, + const char *buf, size_t nbytes) +{ + struct Curl_easy *data = conn->data; + struct SingleRequest *k = &data->req; + + (void) writer; + + if(!nbytes || k->ignorebody) + return CURLE_OK; + + return Curl_client_write(conn, CLIENTWRITE_BODY, (char *) buf, nbytes); +} + +static void client_close_writer(struct connectdata *conn, + contenc_writer *writer) +{ + (void) conn; + (void) writer; +} + +static const content_encoding client_encoding = { + NULL, + NULL, + client_init_writer, + client_unencode_write, + client_close_writer, + 0 +}; + + +/* Deferred error dummy writer. */ +static CURLcode error_init_writer(struct connectdata *conn, + contenc_writer *writer) +{ + (void) conn; + return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR; +} + +static CURLcode error_unencode_write(struct connectdata *conn, + contenc_writer *writer, + const char *buf, size_t nbytes) +{ + char *all = Curl_all_content_encodings(); + + (void) writer; + (void) buf; + (void) nbytes; + + if(!all) + return CURLE_OUT_OF_MEMORY; + failf(conn->data, "Unrecognized content encoding type. " + "libcurl understands %s content encodings.", all); + free(all); + return CURLE_BAD_CONTENT_ENCODING; +} + +static void error_close_writer(struct connectdata *conn, + contenc_writer *writer) +{ + (void) conn; + (void) writer; +} + +static const content_encoding error_encoding = { + NULL, + NULL, + error_init_writer, + error_unencode_write, + error_close_writer, + 0 +}; + +/* Create an unencoding writer stage using the given handler. */ +static contenc_writer *new_unencoding_writer(struct connectdata *conn, + const content_encoding *handler, + contenc_writer *downstream) +{ + size_t sz = offsetof(contenc_writer, params) + handler->paramsize; + contenc_writer *writer = (contenc_writer *) calloc(1, sz); + + if(writer) { + writer->handler = handler; + writer->downstream = downstream; + if(handler->init_writer(conn, writer)) { + free(writer); + writer = NULL; + } + } + + return writer; +} + +/* Write data using an unencoding writer stack. */ +CURLcode Curl_unencode_write(struct connectdata *conn, contenc_writer *writer, + const char *buf, size_t nbytes) +{ + if(!nbytes) + return CURLE_OK; + return writer->handler->unencode_write(conn, writer, buf, nbytes); +} + +/* Close and clean-up the connection's writer stack. */ +void Curl_unencode_cleanup(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + struct SingleRequest *k = &data->req; + contenc_writer *writer = k->writer_stack; + + while(writer) { + k->writer_stack = writer->downstream; + writer->handler->close_writer(conn, writer); + free(writer); + writer = k->writer_stack; + } +} + +/* Find the content encoding by name. */ +static const content_encoding *find_encoding(const char *name, size_t len) +{ + const content_encoding * const *cep; + + for(cep = encodings; *cep; cep++) { + const content_encoding *ce = *cep; + if((strncasecompare(name, ce->name, len) && !ce->name[len]) || + (ce->alias && strncasecompare(name, ce->alias, len) && !ce->alias[len])) + return ce; + } + return NULL; +} + +/* Set-up the unencoding stack from the Content-Encoding header value. + * See RFC 7231 section 3.1.2.2. */ +CURLcode Curl_build_unencoding_stack(struct connectdata *conn, + const char *enclist, int maybechunked) +{ + struct Curl_easy *data = conn->data; + struct SingleRequest *k = &data->req; + + do { + const char *name; + size_t namelen; + + /* Parse a single encoding name. */ + while(ISSPACE(*enclist) || *enclist == ',') + enclist++; + + name = enclist; + + for(namelen = 0; *enclist && *enclist != ','; enclist++) + if(!ISSPACE(*enclist)) + namelen = enclist - name + 1; + + /* Special case: chunked encoding is handled at the reader level. */ + if(maybechunked && namelen == 7 && strncasecompare(name, "chunked", 7)) { + k->chunk = TRUE; /* chunks coming our way. */ + Curl_httpchunk_init(conn); /* init our chunky engine. */ + } + else if(namelen) { + const content_encoding *encoding = find_encoding(name, namelen); + contenc_writer *writer; + + if(!k->writer_stack) { + k->writer_stack = new_unencoding_writer(conn, &client_encoding, NULL); + + if(!k->writer_stack) + return CURLE_OUT_OF_MEMORY; + } + + if(!encoding) + encoding = &error_encoding; /* Defer error at stack use. */ + + /* Stack the unencoding stage. */ + writer = new_unencoding_writer(conn, encoding, k->writer_stack); + if(!writer) + return CURLE_OUT_OF_MEMORY; + k->writer_stack = writer; + } + } while(*enclist); + + return CURLE_OK; +} + +#else +/* Stubs for builds without HTTP. */ +CURLcode Curl_build_unencoding_stack(struct connectdata *conn, + const char *enclist, int maybechunked) +{ + (void) conn; + (void) enclist; + (void) maybechunked; + return CURLE_NOT_BUILT_IN; +} + +CURLcode Curl_unencode_write(struct connectdata *conn, contenc_writer *writer, + const char *buf, size_t nbytes) +{ + (void) conn; + (void) writer; + (void) buf; + (void) nbytes; + return CURLE_NOT_BUILT_IN; +} + +void Curl_unencode_cleanup(struct connectdata *conn) +{ + (void) conn; +} + +char *Curl_all_content_encodings(void) +{ + return strdup(CONTENT_ENCODING_DEFAULT); /* Satisfy caller. */ +} + +#endif /* CURL_DISABLE_HTTP */ diff --git a/dependencies/cmcurl/lib/content_encoding.h b/dependencies/cmcurl/lib/content_encoding.h new file mode 100644 index 0000000..4cd52be --- /dev/null +++ b/dependencies/cmcurl/lib/content_encoding.h @@ -0,0 +1,55 @@ +#ifndef HEADER_CURL_CONTENT_ENCODING_H +#define HEADER_CURL_CONTENT_ENCODING_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +/* Decoding writer. */ +typedef struct contenc_writer_s contenc_writer; +typedef struct content_encoding_s content_encoding; + +struct contenc_writer_s { + const content_encoding *handler; /* Encoding handler. */ + contenc_writer *downstream; /* Downstream writer. */ + void *params; /* Encoding-specific storage (variable length). */ +}; + +/* Content encoding writer. */ +struct content_encoding_s { + const char *name; /* Encoding name. */ + const char *alias; /* Encoding name alias. */ + CURLcode (*init_writer)(struct connectdata *conn, contenc_writer *writer); + CURLcode (*unencode_write)(struct connectdata *conn, contenc_writer *writer, + const char *buf, size_t nbytes); + void (*close_writer)(struct connectdata *conn, contenc_writer *writer); + size_t paramsize; +}; + + +CURLcode Curl_build_unencoding_stack(struct connectdata *conn, + const char *enclist, int maybechunked); +CURLcode Curl_unencode_write(struct connectdata *conn, contenc_writer *writer, + const char *buf, size_t nbytes); +void Curl_unencode_cleanup(struct connectdata *conn); +char *Curl_all_content_encodings(void); + +#endif /* HEADER_CURL_CONTENT_ENCODING_H */ diff --git a/dependencies/cmcurl/lib/cookie.c b/dependencies/cmcurl/lib/cookie.c new file mode 100644 index 0000000..9a9e14d --- /dev/null +++ b/dependencies/cmcurl/lib/cookie.c @@ -0,0 +1,1657 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/*** + + +RECEIVING COOKIE INFORMATION +============================ + +struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, + const char *file, struct CookieInfo *inc, bool newsession); + + Inits a cookie struct to store data in a local file. This is always + called before any cookies are set. + +struct Cookie *Curl_cookie_add(struct Curl_easy *data, + struct CookieInfo *c, bool httpheader, char *lineptr, + const char *domain, const char *path); + + The 'lineptr' parameter is a full "Set-cookie:" line as + received from a server. + + The function need to replace previously stored lines that this new + line supersedes. + + It may remove lines that are expired. + + It should return an indication of success/error. + + +SENDING COOKIE INFORMATION +========================== + +struct Cookies *Curl_cookie_getlist(struct CookieInfo *cookie, + char *host, char *path, bool secure); + + For a given host and path, return a linked list of cookies that + the client should send to the server if used now. The secure + boolean informs the cookie if a secure connection is achieved or + not. + + It shall only return cookies that haven't expired. + + +Example set of cookies: + + Set-cookie: PRODUCTINFO=webxpress; domain=.fidelity.com; path=/; secure + Set-cookie: PERSONALIZE=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; + domain=.fidelity.com; path=/ftgw; secure + Set-cookie: FidHist=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; + domain=.fidelity.com; path=/; secure + Set-cookie: FidOrder=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; + domain=.fidelity.com; path=/; secure + Set-cookie: DisPend=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; + domain=.fidelity.com; path=/; secure + Set-cookie: FidDis=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; + domain=.fidelity.com; path=/; secure + Set-cookie: + Session_Key@6791a9e0-901a-11d0-a1c8-9b012c88aa77=none;expires=Monday, + 13-Jun-1988 03:04:55 GMT; domain=.fidelity.com; path=/; secure +****/ + + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) + +#include "urldata.h" +#include "cookie.h" +#include "psl.h" +#include "strtok.h" +#include "sendf.h" +#include "slist.h" +#include "share.h" +#include "strtoofft.h" +#include "strcase.h" +#include "curl_get_line.h" +#include "curl_memrchr.h" +#include "inet_pton.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +static void freecookie(struct Cookie *co) +{ + free(co->expirestr); + free(co->domain); + free(co->path); + free(co->spath); + free(co->name); + free(co->value); + free(co->maxage); + free(co->version); + free(co); +} + +static bool tailmatch(const char *cooke_domain, const char *hostname) +{ + size_t cookie_domain_len = strlen(cooke_domain); + size_t hostname_len = strlen(hostname); + + if(hostname_len < cookie_domain_len) + return FALSE; + + if(!strcasecompare(cooke_domain, hostname + hostname_len-cookie_domain_len)) + return FALSE; + + /* A lead char of cookie_domain is not '.'. + RFC6265 4.1.2.3. The Domain Attribute says: + For example, if the value of the Domain attribute is + "example.com", the user agent will include the cookie in the Cookie + header when making HTTP requests to example.com, www.example.com, and + www.corp.example.com. + */ + if(hostname_len == cookie_domain_len) + return TRUE; + if('.' == *(hostname + hostname_len - cookie_domain_len - 1)) + return TRUE; + return FALSE; +} + +/* + * Return true if the given string is an IP(v4|v6) address. + */ +static bool isip(const char *domain) +{ + struct in_addr addr; +#ifdef ENABLE_IPV6 + struct in6_addr addr6; +#endif + + if(Curl_inet_pton(AF_INET, domain, &addr) +#ifdef ENABLE_IPV6 + || Curl_inet_pton(AF_INET6, domain, &addr6) +#endif + ) { + /* domain name given as IP address */ + return TRUE; + } + + return FALSE; +} + +/* + * matching cookie path and url path + * RFC6265 5.1.4 Paths and Path-Match + */ +static bool pathmatch(const char *cookie_path, const char *request_uri) +{ + size_t cookie_path_len; + size_t uri_path_len; + char *uri_path = NULL; + char *pos; + bool ret = FALSE; + + /* cookie_path must not have last '/' separator. ex: /sample */ + cookie_path_len = strlen(cookie_path); + if(1 == cookie_path_len) { + /* cookie_path must be '/' */ + return TRUE; + } + + uri_path = strdup(request_uri); + if(!uri_path) + return FALSE; + pos = strchr(uri_path, '?'); + if(pos) + *pos = 0x0; + + /* #-fragments are already cut off! */ + if(0 == strlen(uri_path) || uri_path[0] != '/') { + free(uri_path); + uri_path = strdup("/"); + if(!uri_path) + return FALSE; + } + + /* here, RFC6265 5.1.4 says + 4. Output the characters of the uri-path from the first character up + to, but not including, the right-most %x2F ("/"). + but URL path /hoge?fuga=xxx means /hoge/index.cgi?fuga=xxx in some site + without redirect. + Ignore this algorithm because /hoge is uri path for this case + (uri path is not /). + */ + + uri_path_len = strlen(uri_path); + + if(uri_path_len < cookie_path_len) { + ret = FALSE; + goto pathmatched; + } + + /* not using checkprefix() because matching should be case-sensitive */ + if(strncmp(cookie_path, uri_path, cookie_path_len)) { + ret = FALSE; + goto pathmatched; + } + + /* The cookie-path and the uri-path are identical. */ + if(cookie_path_len == uri_path_len) { + ret = TRUE; + goto pathmatched; + } + + /* here, cookie_path_len < uri_path_len */ + if(uri_path[cookie_path_len] == '/') { + ret = TRUE; + goto pathmatched; + } + + ret = FALSE; + +pathmatched: + free(uri_path); + return ret; +} + +/* + * Return the top-level domain, for optimal hashing. + */ +static const char *get_top_domain(const char * const domain, size_t *outlen) +{ + size_t len; + const char *first = NULL, *last; + + if(!domain) + return NULL; + + len = strlen(domain); + last = memrchr(domain, '.', len); + if(last) { + first = memrchr(domain, '.', (last - domain)); + if(first) + len -= (++first - domain); + } + + if(outlen) + *outlen = len; + + return first? first: domain; +} + +/* + * A case-insensitive hash for the cookie domains. + */ +static size_t cookie_hash_domain(const char *domain, const size_t len) +{ + const char *end = domain + len; + size_t h = 5381; + + while(domain < end) { + h += h << 5; + h ^= Curl_raw_toupper(*domain++); + } + + return (h % COOKIE_HASH_SIZE); +} + +/* + * Hash this domain. + */ +static size_t cookiehash(const char * const domain) +{ + const char *top; + size_t len; + + if(!domain || isip(domain)) + return 0; + + top = get_top_domain(domain, &len); + return cookie_hash_domain(top, len); +} + +/* + * cookie path sanitize + */ +static char *sanitize_cookie_path(const char *cookie_path) +{ + size_t len; + char *new_path = strdup(cookie_path); + if(!new_path) + return NULL; + + /* some stupid site sends path attribute with '"'. */ + len = strlen(new_path); + if(new_path[0] == '\"') { + memmove((void *)new_path, (const void *)(new_path + 1), len); + len--; + } + if(len && (new_path[len - 1] == '\"')) { + new_path[len - 1] = 0x0; + len--; + } + + /* RFC6265 5.2.4 The Path Attribute */ + if(new_path[0] != '/') { + /* Let cookie-path be the default-path. */ + free(new_path); + new_path = strdup("/"); + return new_path; + } + + /* convert /hoge/ to /hoge */ + if(len && new_path[len - 1] == '/') { + new_path[len - 1] = 0x0; + } + + return new_path; +} + +/* + * Load cookies from all given cookie files (CURLOPT_COOKIEFILE). + * + * NOTE: OOM or cookie parsing failures are ignored. + */ +void Curl_cookie_loadfiles(struct Curl_easy *data) +{ + struct curl_slist *list = data->change.cookielist; + if(list) { + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + while(list) { + struct CookieInfo *newcookies = Curl_cookie_init(data, + list->data, + data->cookies, + data->set.cookiesession); + if(!newcookies) + /* Failure may be due to OOM or a bad cookie; both are ignored + * but only the first should be + */ + infof(data, "ignoring failed cookie_init for %s\n", list->data); + else + data->cookies = newcookies; + list = list->next; + } + curl_slist_free_all(data->change.cookielist); /* clean up list */ + data->change.cookielist = NULL; /* don't do this again! */ + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + } +} + +/* + * strstore() makes a strdup() on the 'newstr' and if '*str' is non-NULL + * that will be freed before the allocated string is stored there. + * + * It is meant to easily replace strdup() + */ +static void strstore(char **str, const char *newstr) +{ + free(*str); + *str = strdup(newstr); +} + +/* + * remove_expired() removes expired cookies. + */ +static void remove_expired(struct CookieInfo *cookies) +{ + struct Cookie *co, *nx; + curl_off_t now = (curl_off_t)time(NULL); + unsigned int i; + + for(i = 0; i < COOKIE_HASH_SIZE; i++) { + struct Cookie *pv = NULL; + co = cookies->cookies[i]; + while(co) { + nx = co->next; + if(co->expires && co->expires < now) { + if(!pv) { + cookies->cookies[i] = co->next; + } + else { + pv->next = co->next; + } + cookies->numcookies--; + freecookie(co); + } + else { + pv = co; + } + co = nx; + } + } +} + +/* Make sure domain contains a dot or is localhost. */ +static bool bad_domain(const char *domain) +{ + return !strchr(domain, '.') && !strcasecompare(domain, "localhost"); +} + +/**************************************************************************** + * + * Curl_cookie_add() + * + * Add a single cookie line to the cookie keeping object. + * + * Be aware that sometimes we get an IP-only host name, and that might also be + * a numerical IPv6 address. + * + * Returns NULL on out of memory or invalid cookie. This is suboptimal, + * as they should be treated separately. + ***************************************************************************/ + +struct Cookie * +Curl_cookie_add(struct Curl_easy *data, + /* The 'data' pointer here may be NULL at times, and thus + must only be used very carefully for things that can deal + with data being NULL. Such as infof() and similar */ + + struct CookieInfo *c, + bool httpheader, /* TRUE if HTTP header-style line */ + bool noexpire, /* if TRUE, skip remove_expired() */ + char *lineptr, /* first character of the line */ + const char *domain, /* default domain */ + const char *path, /* full path used when this cookie is set, + used to get default path for the cookie + unless set */ + bool secure) /* TRUE if connection is over secure origin */ +{ + struct Cookie *clist; + struct Cookie *co; + struct Cookie *lastc = NULL; + time_t now = time(NULL); + bool replace_old = FALSE; + bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */ + size_t myhash; + +#ifdef CURL_DISABLE_VERBOSE_STRINGS + (void)data; +#endif + + /* First, alloc and init a new struct for it */ + co = calloc(1, sizeof(struct Cookie)); + if(!co) + return NULL; /* bail out if we're this low on memory */ + + if(httpheader) { + /* This line was read off a HTTP-header */ + char name[MAX_NAME]; + char what[MAX_NAME]; + const char *ptr; + const char *semiptr; + + size_t linelength = strlen(lineptr); + if(linelength > MAX_COOKIE_LINE) { + /* discard overly long lines at once */ + free(co); + return NULL; + } + + semiptr = strchr(lineptr, ';'); /* first, find a semicolon */ + + while(*lineptr && ISBLANK(*lineptr)) + lineptr++; + + ptr = lineptr; + do { + /* we have a = pair or a stand-alone word here */ + name[0] = what[0] = 0; /* init the buffers */ + if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;\r\n=] =%" + MAX_NAME_TXT "[^;\r\n]", + name, what)) { + /* Use strstore() below to properly deal with received cookie + headers that have the same string property set more than once, + and then we use the last one. */ + const char *whatptr; + bool done = FALSE; + bool sep; + size_t len = strlen(what); + size_t nlen = strlen(name); + const char *endofn = &ptr[ nlen ]; + + if(nlen >= (MAX_NAME-1) || len >= (MAX_NAME-1) || + ((nlen + len) > MAX_NAME)) { + /* too long individual name or contents, or too long combination of + name + contents. Chrome and Firefox support 4095 or 4096 bytes + combo. */ + freecookie(co); + infof(data, "oversized cookie dropped, name/val %zu + %zu bytes\n", + nlen, len); + return NULL; + } + + /* name ends with a '=' ? */ + sep = (*endofn == '=')?TRUE:FALSE; + + if(nlen) { + endofn--; /* move to the last character */ + if(ISBLANK(*endofn)) { + /* skip trailing spaces in name */ + while(*endofn && ISBLANK(*endofn) && nlen) { + endofn--; + nlen--; + } + name[nlen] = 0; /* new end of name */ + } + } + + /* Strip off trailing whitespace from the 'what' */ + while(len && ISBLANK(what[len-1])) { + what[len-1] = 0; + len--; + } + + /* Skip leading whitespace from the 'what' */ + whatptr = what; + while(*whatptr && ISBLANK(*whatptr)) + whatptr++; + + /* + * Check if we have a reserved prefix set before anything else, as we + * otherwise have to test for the prefix in both the cookie name and + * "the rest". Prefixes must start with '__' and end with a '-', so + * only test for names where that can possibly be true. + */ + if(nlen > 3 && name[0] == '_' && name[1] == '_') { + if(strncasecompare("__Secure-", name, 9)) + co->prefix |= COOKIE_PREFIX__SECURE; + else if(strncasecompare("__Host-", name, 7)) + co->prefix |= COOKIE_PREFIX__HOST; + } + + if(!co->name) { + /* The very first name/value pair is the actual cookie name */ + if(!sep) { + /* Bad name/value pair. */ + badcookie = TRUE; + break; + } + co->name = strdup(name); + co->value = strdup(whatptr); + done = TRUE; + if(!co->name || !co->value) { + badcookie = TRUE; + break; + } + } + else if(!len) { + /* this was a "=" with no content, and we must allow + 'secure' and 'httponly' specified this weirdly */ + done = TRUE; + /* + * secure cookies are only allowed to be set when the connection is + * using a secure protocol, or when the cookie is being set by + * reading from file + */ + if(strcasecompare("secure", name)) { + if(secure || !c->running) { + co->secure = TRUE; + } + else { + badcookie = TRUE; + break; + } + } + else if(strcasecompare("httponly", name)) + co->httponly = TRUE; + else if(sep) + /* there was a '=' so we're not done parsing this field */ + done = FALSE; + } + if(done) + ; + else if(strcasecompare("path", name)) { + strstore(&co->path, whatptr); + if(!co->path) { + badcookie = TRUE; /* out of memory bad */ + break; + } + free(co->spath); /* if this is set again */ + co->spath = sanitize_cookie_path(co->path); + if(!co->spath) { + badcookie = TRUE; /* out of memory bad */ + break; + } + } + else if(strcasecompare("domain", name)) { + bool is_ip; + + /* Now, we make sure that our host is within the given domain, + or the given domain is not valid and thus cannot be set. */ + + if('.' == whatptr[0]) + whatptr++; /* ignore preceding dot */ + +#ifndef USE_LIBPSL + /* + * Without PSL we don't know when the incoming cookie is set on a + * TLD or otherwise "protected" suffix. To reduce risk, we require a + * dot OR the exact host name being "localhost". + */ + if(bad_domain(whatptr)) + domain = ":"; +#endif + + is_ip = isip(domain ? domain : whatptr); + + if(!domain + || (is_ip && !strcmp(whatptr, domain)) + || (!is_ip && tailmatch(whatptr, domain))) { + strstore(&co->domain, whatptr); + if(!co->domain) { + badcookie = TRUE; + break; + } + if(!is_ip) + co->tailmatch = TRUE; /* we always do that if the domain name was + given */ + } + else { + /* we did not get a tailmatch and then the attempted set domain + is not a domain to which the current host belongs. Mark as + bad. */ + badcookie = TRUE; + infof(data, "skipped cookie with bad tailmatch domain: %s\n", + whatptr); + } + } + else if(strcasecompare("version", name)) { + strstore(&co->version, whatptr); + if(!co->version) { + badcookie = TRUE; + break; + } + } + else if(strcasecompare("max-age", name)) { + /* Defined in RFC2109: + + Optional. The Max-Age attribute defines the lifetime of the + cookie, in seconds. The delta-seconds value is a decimal non- + negative integer. After delta-seconds seconds elapse, the + client should discard the cookie. A value of zero means the + cookie should be discarded immediately. + + */ + strstore(&co->maxage, whatptr); + if(!co->maxage) { + badcookie = TRUE; + break; + } + } + else if(strcasecompare("expires", name)) { + strstore(&co->expirestr, whatptr); + if(!co->expirestr) { + badcookie = TRUE; + break; + } + } + /* + else this is the second (or more) name we don't know + about! */ + } + else { + /* this is an "illegal" = pair */ + } + + if(!semiptr || !*semiptr) { + /* we already know there are no more cookies */ + semiptr = NULL; + continue; + } + + ptr = semiptr + 1; + while(*ptr && ISBLANK(*ptr)) + ptr++; + semiptr = strchr(ptr, ';'); /* now, find the next semicolon */ + + if(!semiptr && *ptr) + /* There are no more semicolons, but there's a final name=value pair + coming up */ + semiptr = strchr(ptr, '\0'); + } while(semiptr); + + if(co->maxage) { + CURLofft offt; + offt = curlx_strtoofft((*co->maxage == '\"')? + &co->maxage[1]:&co->maxage[0], NULL, 10, + &co->expires); + if(offt == CURL_OFFT_FLOW) + /* overflow, used max value */ + co->expires = CURL_OFF_T_MAX; + else if(!offt) { + if(!co->expires) + /* already expired */ + co->expires = 1; + else if(CURL_OFF_T_MAX - now < co->expires) + /* would overflow */ + co->expires = CURL_OFF_T_MAX; + else + co->expires += now; + } + } + else if(co->expirestr) { + /* Note that if the date couldn't get parsed for whatever reason, + the cookie will be treated as a session cookie */ + co->expires = curl_getdate(co->expirestr, NULL); + + /* Session cookies have expires set to 0 so if we get that back + from the date parser let's add a second to make it a + non-session cookie */ + if(co->expires == 0) + co->expires = 1; + else if(co->expires < 0) + co->expires = 0; + } + + if(!badcookie && !co->domain) { + if(domain) { + /* no domain was given in the header line, set the default */ + co->domain = strdup(domain); + if(!co->domain) + badcookie = TRUE; + } + } + + if(!badcookie && !co->path && path) { + /* No path was given in the header line, set the default. + Note that the passed-in path to this function MAY have a '?' and + following part that MUST not be stored as part of the path. */ + char *queryp = strchr(path, '?'); + + /* queryp is where the interesting part of the path ends, so now we + want to the find the last */ + char *endslash; + if(!queryp) + endslash = strrchr(path, '/'); + else + endslash = memrchr(path, '/', (queryp - path)); + if(endslash) { + size_t pathlen = (endslash-path + 1); /* include end slash */ + co->path = malloc(pathlen + 1); /* one extra for the zero byte */ + if(co->path) { + memcpy(co->path, path, pathlen); + co->path[pathlen] = 0; /* zero terminate */ + co->spath = sanitize_cookie_path(co->path); + if(!co->spath) + badcookie = TRUE; /* out of memory bad */ + } + else + badcookie = TRUE; + } + } + + if(badcookie || !co->name) { + /* we didn't get a cookie name or a bad one, + this is an illegal line, bail out */ + freecookie(co); + return NULL; + } + + } + else { + /* This line is NOT a HTTP header style line, we do offer support for + reading the odd netscape cookies-file format here */ + char *ptr; + char *firstptr; + char *tok_buf = NULL; + int fields; + + /* IE introduced HTTP-only cookies to prevent XSS attacks. Cookies + marked with httpOnly after the domain name are not accessible + from javascripts, but since curl does not operate at javascript + level, we include them anyway. In Firefox's cookie files, these + lines are preceded with #HttpOnly_ and then everything is + as usual, so we skip 10 characters of the line.. + */ + if(strncmp(lineptr, "#HttpOnly_", 10) == 0) { + lineptr += 10; + co->httponly = TRUE; + } + + if(lineptr[0]=='#') { + /* don't even try the comments */ + free(co); + return NULL; + } + /* strip off the possible end-of-line characters */ + ptr = strchr(lineptr, '\r'); + if(ptr) + *ptr = 0; /* clear it */ + ptr = strchr(lineptr, '\n'); + if(ptr) + *ptr = 0; /* clear it */ + + firstptr = strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */ + + /* Now loop through the fields and init the struct we already have + allocated */ + for(ptr = firstptr, fields = 0; ptr && !badcookie; + ptr = strtok_r(NULL, "\t", &tok_buf), fields++) { + switch(fields) { + case 0: + if(ptr[0]=='.') /* skip preceding dots */ + ptr++; + co->domain = strdup(ptr); + if(!co->domain) + badcookie = TRUE; + break; + case 1: + /* This field got its explanation on the 23rd of May 2001 by + Andrés García: + + flag: A TRUE/FALSE value indicating if all machines within a given + domain can access the variable. This value is set automatically by + the browser, depending on the value you set for the domain. + + As far as I can see, it is set to true when the cookie says + .domain.com and to false when the domain is complete www.domain.com + */ + co->tailmatch = strcasecompare(ptr, "TRUE")?TRUE:FALSE; + break; + case 2: + /* It turns out, that sometimes the file format allows the path + field to remain not filled in, we try to detect this and work + around it! Andrés García made us aware of this... */ + if(strcmp("TRUE", ptr) && strcmp("FALSE", ptr)) { + /* only if the path doesn't look like a boolean option! */ + co->path = strdup(ptr); + if(!co->path) + badcookie = TRUE; + else { + co->spath = sanitize_cookie_path(co->path); + if(!co->spath) { + badcookie = TRUE; /* out of memory bad */ + } + } + break; + } + /* this doesn't look like a path, make one up! */ + co->path = strdup("/"); + if(!co->path) + badcookie = TRUE; + co->spath = strdup("/"); + if(!co->spath) + badcookie = TRUE; + fields++; /* add a field and fall down to secure */ + /* FALLTHROUGH */ + case 3: + co->secure = FALSE; + if(strcasecompare(ptr, "TRUE")) { + if(secure || c->running) + co->secure = TRUE; + else + badcookie = TRUE; + } + break; + case 4: + if(curlx_strtoofft(ptr, NULL, 10, &co->expires)) + badcookie = TRUE; + break; + case 5: + co->name = strdup(ptr); + if(!co->name) + badcookie = TRUE; + else { + /* For Netscape file format cookies we check prefix on the name */ + if(strncasecompare("__Secure-", co->name, 9)) + co->prefix |= COOKIE_PREFIX__SECURE; + else if(strncasecompare("__Host-", co->name, 7)) + co->prefix |= COOKIE_PREFIX__HOST; + } + break; + case 6: + co->value = strdup(ptr); + if(!co->value) + badcookie = TRUE; + break; + } + } + if(6 == fields) { + /* we got a cookie with blank contents, fix it */ + co->value = strdup(""); + if(!co->value) + badcookie = TRUE; + else + fields++; + } + + if(!badcookie && (7 != fields)) + /* we did not find the sufficient number of fields */ + badcookie = TRUE; + + if(badcookie) { + freecookie(co); + return NULL; + } + + } + + if(co->prefix & COOKIE_PREFIX__SECURE) { + /* The __Secure- prefix only requires that the cookie be set secure */ + if(!co->secure) { + freecookie(co); + return NULL; + } + } + if(co->prefix & COOKIE_PREFIX__HOST) { + /* + * The __Host- prefix requires the cookie to be secure, have a "/" path + * and not have a domain set. + */ + if(co->secure && co->path && strcmp(co->path, "/") == 0 && !co->tailmatch) + ; + else { + freecookie(co); + return NULL; + } + } + + if(!c->running && /* read from a file */ + c->newsession && /* clean session cookies */ + !co->expires) { /* this is a session cookie since it doesn't expire! */ + freecookie(co); + return NULL; + } + + co->livecookie = c->running; + co->creationtime = ++c->lastct; + + /* now, we have parsed the incoming line, we must now check if this + supersedes an already existing cookie, which it may if the previous have + the same domain and path as this */ + + /* at first, remove expired cookies */ + if(!noexpire) + remove_expired(c); + +#ifdef USE_LIBPSL + /* Check if the domain is a Public Suffix and if yes, ignore the cookie. */ + if(domain && co->domain && !isip(co->domain)) { + const psl_ctx_t *psl = Curl_psl_use(data); + int acceptable; + + if(psl) { + acceptable = psl_is_cookie_domain_acceptable(psl, domain, co->domain); + Curl_psl_release(data); + } + else + acceptable = !bad_domain(domain); + + if(!acceptable) { + infof(data, "cookie '%s' dropped, domain '%s' must not " + "set cookies for '%s'\n", co->name, domain, co->domain); + freecookie(co); + return NULL; + } + } +#endif + + myhash = cookiehash(co->domain); + clist = c->cookies[myhash]; + replace_old = FALSE; + while(clist) { + if(strcasecompare(clist->name, co->name)) { + /* the names are identical */ + + if(clist->domain && co->domain) { + if(strcasecompare(clist->domain, co->domain) && + (clist->tailmatch == co->tailmatch)) + /* The domains are identical */ + replace_old = TRUE; + } + else if(!clist->domain && !co->domain) + replace_old = TRUE; + + if(replace_old) { + /* the domains were identical */ + + if(clist->spath && co->spath) { + if(clist->secure && !co->secure && !secure) { + size_t cllen; + const char *sep; + + /* + * A non-secure cookie may not overlay an existing secure cookie. + * For an existing cookie "a" with path "/login", refuse a new + * cookie "a" with for example path "/login/en", while the path + * "/loginhelper" is ok. + */ + + sep = strchr(clist->spath + 1, '/'); + + if(sep) + cllen = sep - clist->spath; + else + cllen = strlen(clist->spath); + + if(strncasecompare(clist->spath, co->spath, cllen)) { + freecookie(co); + return NULL; + } + } + else if(strcasecompare(clist->spath, co->spath)) + replace_old = TRUE; + else + replace_old = FALSE; + } + else if(!clist->spath && !co->spath) + replace_old = TRUE; + else + replace_old = FALSE; + + } + + if(replace_old && !co->livecookie && clist->livecookie) { + /* Both cookies matched fine, except that the already present + cookie is "live", which means it was set from a header, while + the new one isn't "live" and thus only read from a file. We let + live cookies stay alive */ + + /* Free the newcomer and get out of here! */ + freecookie(co); + return NULL; + } + + if(replace_old) { + co->next = clist->next; /* get the next-pointer first */ + + /* when replacing, creationtime is kept from old */ + co->creationtime = clist->creationtime; + + /* then free all the old pointers */ + free(clist->name); + free(clist->value); + free(clist->domain); + free(clist->path); + free(clist->spath); + free(clist->expirestr); + free(clist->version); + free(clist->maxage); + + *clist = *co; /* then store all the new data */ + + free(co); /* free the newly alloced memory */ + co = clist; /* point to the previous struct instead */ + + /* We have replaced a cookie, now skip the rest of the list but + make sure the 'lastc' pointer is properly set */ + do { + lastc = clist; + clist = clist->next; + } while(clist); + break; + } + } + lastc = clist; + clist = clist->next; + } + + if(c->running) + /* Only show this when NOT reading the cookies from a file */ + infof(data, "%s cookie %s=\"%s\" for domain %s, path %s, " + "expire %" CURL_FORMAT_CURL_OFF_T "\n", + replace_old?"Replaced":"Added", co->name, co->value, + co->domain, co->path, co->expires); + + if(!replace_old) { + /* then make the last item point on this new one */ + if(lastc) + lastc->next = co; + else + c->cookies[myhash] = co; + c->numcookies++; /* one more cookie in the jar */ + } + + return co; +} + + +/***************************************************************************** + * + * Curl_cookie_init() + * + * Inits a cookie struct to read data from a local file. This is always + * called before any cookies are set. File may be NULL. + * + * If 'newsession' is TRUE, discard all "session cookies" on read from file. + * + * Returns NULL on out of memory. Invalid cookies are ignored. + ****************************************************************************/ +struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, + const char *file, + struct CookieInfo *inc, + bool newsession) +{ + struct CookieInfo *c; + FILE *fp = NULL; + bool fromfile = TRUE; + char *line = NULL; + + if(NULL == inc) { + /* we didn't get a struct, create one */ + c = calloc(1, sizeof(struct CookieInfo)); + if(!c) + return NULL; /* failed to get memory */ + c->filename = strdup(file?file:"none"); /* copy the name just in case */ + if(!c->filename) + goto fail; /* failed to get memory */ + } + else { + /* we got an already existing one, use that */ + c = inc; + } + c->running = FALSE; /* this is not running, this is init */ + + if(file && !strcmp(file, "-")) { + fp = stdin; + fromfile = FALSE; + } + else if(file && !*file) { + /* points to a "" string */ + fp = NULL; + } + else + fp = file?fopen(file, FOPEN_READTEXT):NULL; + + c->newsession = newsession; /* new session? */ + + if(fp) { + char *lineptr; + bool headerline; + + line = malloc(MAX_COOKIE_LINE); + if(!line) + goto fail; + while(Curl_get_line(line, MAX_COOKIE_LINE, fp)) { + if(checkprefix("Set-Cookie:", line)) { + /* This is a cookie line, get it! */ + lineptr = &line[11]; + headerline = TRUE; + } + else { + lineptr = line; + headerline = FALSE; + } + while(*lineptr && ISBLANK(*lineptr)) + lineptr++; + + Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL, TRUE); + } + free(line); /* free the line buffer */ + remove_expired(c); /* run this once, not on every cookie */ + + if(fromfile) + fclose(fp); + } + + c->running = TRUE; /* now, we're running */ + + return c; + +fail: + free(line); + if(!inc) + /* Only clean up if we allocated it here, as the original could still be in + * use by a share handle */ + Curl_cookie_cleanup(c); + if(fromfile && fp) + fclose(fp); + return NULL; /* out of memory */ +} + +/* sort this so that the longest path gets before the shorter path */ +static int cookie_sort(const void *p1, const void *p2) +{ + struct Cookie *c1 = *(struct Cookie **)p1; + struct Cookie *c2 = *(struct Cookie **)p2; + size_t l1, l2; + + /* 1 - compare cookie path lengths */ + l1 = c1->path ? strlen(c1->path) : 0; + l2 = c2->path ? strlen(c2->path) : 0; + + if(l1 != l2) + return (l2 > l1) ? 1 : -1 ; /* avoid size_t <=> int conversions */ + + /* 2 - compare cookie domain lengths */ + l1 = c1->domain ? strlen(c1->domain) : 0; + l2 = c2->domain ? strlen(c2->domain) : 0; + + if(l1 != l2) + return (l2 > l1) ? 1 : -1 ; /* avoid size_t <=> int conversions */ + + /* 3 - compare cookie name lengths */ + l1 = c1->name ? strlen(c1->name) : 0; + l2 = c2->name ? strlen(c2->name) : 0; + + if(l1 != l2) + return (l2 > l1) ? 1 : -1; + + /* 4 - compare cookie creation time */ + return (c2->creationtime > c1->creationtime) ? 1 : -1; +} + +/* sort cookies only according to creation time */ +static int cookie_sort_ct(const void *p1, const void *p2) +{ + struct Cookie *c1 = *(struct Cookie **)p1; + struct Cookie *c2 = *(struct Cookie **)p2; + + return (c2->creationtime > c1->creationtime) ? 1 : -1; +} + +#define CLONE(field) \ + do { \ + if(src->field) { \ + d->field = strdup(src->field); \ + if(!d->field) \ + goto fail; \ + } \ + } while(0) + +static struct Cookie *dup_cookie(struct Cookie *src) +{ + struct Cookie *d = calloc(sizeof(struct Cookie), 1); + if(d) { + CLONE(expirestr); + CLONE(domain); + CLONE(path); + CLONE(spath); + CLONE(name); + CLONE(value); + CLONE(maxage); + CLONE(version); + d->expires = src->expires; + d->tailmatch = src->tailmatch; + d->secure = src->secure; + d->livecookie = src->livecookie; + d->httponly = src->httponly; + d->creationtime = src->creationtime; + } + return d; + + fail: + freecookie(d); + return NULL; +} + +/***************************************************************************** + * + * Curl_cookie_getlist() + * + * For a given host and path, return a linked list of cookies that the + * client should send to the server if used now. The secure boolean informs + * the cookie if a secure connection is achieved or not. + * + * It shall only return cookies that haven't expired. + * + ****************************************************************************/ + +struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, + const char *host, const char *path, + bool secure) +{ + struct Cookie *newco; + struct Cookie *co; + struct Cookie *mainco = NULL; + size_t matches = 0; + bool is_ip; + const size_t myhash = cookiehash(host); + + if(!c || !c->cookies[myhash]) + return NULL; /* no cookie struct or no cookies in the struct */ + + /* at first, remove expired cookies */ + remove_expired(c); + + /* check if host is an IP(v4|v6) address */ + is_ip = isip(host); + + co = c->cookies[myhash]; + + while(co) { + /* if the cookie requires we're secure we must only continue if we are! */ + if(co->secure?secure:TRUE) { + + /* now check if the domain is correct */ + if(!co->domain || + (co->tailmatch && !is_ip && tailmatch(co->domain, host)) || + ((!co->tailmatch || is_ip) && strcasecompare(host, co->domain)) ) { + /* the right part of the host matches the domain stuff in the + cookie data */ + + /* now check the left part of the path with the cookies path + requirement */ + if(!co->spath || pathmatch(co->spath, path) ) { + + /* and now, we know this is a match and we should create an + entry for the return-linked-list */ + + newco = dup_cookie(co); + if(newco) { + /* then modify our next */ + newco->next = mainco; + + /* point the main to us */ + mainco = newco; + + matches++; + } + else + goto fail; + } + } + } + co = co->next; + } + + if(matches) { + /* Now we need to make sure that if there is a name appearing more than + once, the longest specified path version comes first. To make this + the swiftest way, we just sort them all based on path length. */ + struct Cookie **array; + size_t i; + + /* alloc an array and store all cookie pointers */ + array = malloc(sizeof(struct Cookie *) * matches); + if(!array) + goto fail; + + co = mainco; + + for(i = 0; co; co = co->next) + array[i++] = co; + + /* now sort the cookie pointers in path length order */ + qsort(array, matches, sizeof(struct Cookie *), cookie_sort); + + /* remake the linked list order according to the new order */ + + mainco = array[0]; /* start here */ + for(i = 0; inext = array[i + 1]; + array[matches-1]->next = NULL; /* terminate the list */ + + free(array); /* remove the temporary data again */ + } + + return mainco; /* return the new list */ + +fail: + /* failure, clear up the allocated chain and return NULL */ + Curl_cookie_freelist(mainco); + return NULL; +} + +/***************************************************************************** + * + * Curl_cookie_clearall() + * + * Clear all existing cookies and reset the counter. + * + ****************************************************************************/ +void Curl_cookie_clearall(struct CookieInfo *cookies) +{ + if(cookies) { + unsigned int i; + for(i = 0; i < COOKIE_HASH_SIZE; i++) { + Curl_cookie_freelist(cookies->cookies[i]); + cookies->cookies[i] = NULL; + } + cookies->numcookies = 0; + } +} + +/***************************************************************************** + * + * Curl_cookie_freelist() + * + * Free a list of cookies previously returned by Curl_cookie_getlist(); + * + ****************************************************************************/ + +void Curl_cookie_freelist(struct Cookie *co) +{ + struct Cookie *next; + while(co) { + next = co->next; + freecookie(co); + co = next; + } +} + + +/***************************************************************************** + * + * Curl_cookie_clearsess() + * + * Free all session cookies in the cookies list. + * + ****************************************************************************/ +void Curl_cookie_clearsess(struct CookieInfo *cookies) +{ + struct Cookie *first, *curr, *next, *prev = NULL; + unsigned int i; + + if(!cookies) + return; + + for(i = 0; i < COOKIE_HASH_SIZE; i++) { + if(!cookies->cookies[i]) + continue; + + first = curr = prev = cookies->cookies[i]; + + for(; curr; curr = next) { + next = curr->next; + if(!curr->expires) { + if(first == curr) + first = next; + + if(prev == curr) + prev = next; + else + prev->next = next; + + freecookie(curr); + cookies->numcookies--; + } + else + prev = curr; + } + + cookies->cookies[i] = first; + } +} + + +/***************************************************************************** + * + * Curl_cookie_cleanup() + * + * Free a "cookie object" previous created with Curl_cookie_init(). + * + ****************************************************************************/ +void Curl_cookie_cleanup(struct CookieInfo *c) +{ + if(c) { + unsigned int i; + free(c->filename); + for(i = 0; i < COOKIE_HASH_SIZE; i++) + Curl_cookie_freelist(c->cookies[i]); + free(c); /* free the base struct as well */ + } +} + +/* get_netscape_format() + * + * Formats a string for Netscape output file, w/o a newline at the end. + * + * Function returns a char * to a formatted line. Has to be free()d +*/ +static char *get_netscape_format(const struct Cookie *co) +{ + return aprintf( + "%s" /* httponly preamble */ + "%s%s\t" /* domain */ + "%s\t" /* tailmatch */ + "%s\t" /* path */ + "%s\t" /* secure */ + "%" CURL_FORMAT_CURL_OFF_T "\t" /* expires */ + "%s\t" /* name */ + "%s", /* value */ + co->httponly?"#HttpOnly_":"", + /* Make sure all domains are prefixed with a dot if they allow + tailmatching. This is Mozilla-style. */ + (co->tailmatch && co->domain && co->domain[0] != '.')? ".":"", + co->domain?co->domain:"unknown", + co->tailmatch?"TRUE":"FALSE", + co->path?co->path:"/", + co->secure?"TRUE":"FALSE", + co->expires, + co->name, + co->value?co->value:""); +} + +/* + * cookie_output() + * + * Writes all internally known cookies to the specified file. Specify + * "-" as file name to write to stdout. + * + * The function returns non-zero on write failure. + */ +static int cookie_output(struct CookieInfo *c, const char *dumphere) +{ + struct Cookie *co; + FILE *out; + bool use_stdout = FALSE; + + if(!c) + /* no cookie engine alive */ + return 0; + + /* at first, remove expired cookies */ + remove_expired(c); + + if(!strcmp("-", dumphere)) { + /* use stdout */ + out = stdout; + use_stdout = TRUE; + } + else { + out = fopen(dumphere, FOPEN_WRITETEXT); + if(!out) { + return 1; /* failure */ + } + } + + fputs("# Netscape HTTP Cookie File\n" + "# https://curl.haxx.se/docs/http-cookies.html\n" + "# This file was generated by libcurl! Edit at your own risk.\n\n", + out); + + if(c->numcookies) { + unsigned int i; + unsigned int j; + struct Cookie **array; + + array = malloc(sizeof(struct Cookie *) * c->numcookies); + if(!array) { + if(!use_stdout) + fclose(out); + return 1; + } + + j = 0; + for(i = 0; i < COOKIE_HASH_SIZE; i++) { + for(co = c->cookies[i]; co; co = co->next) { + if(!co->domain) + continue; + array[j++] = co; + } + } + + qsort(array, c->numcookies, sizeof(struct Cookie *), cookie_sort_ct); + + for(i = 0; i < j; i++) { + char *format_ptr = get_netscape_format(array[i]); + if(format_ptr == NULL) { + fprintf(out, "#\n# Fatal libcurl error\n"); + free(array); + if(!use_stdout) + fclose(out); + return 1; + } + fprintf(out, "%s\n", format_ptr); + free(format_ptr); + } + + free(array); + } + if(!use_stdout) + fclose(out); + + return 0; +} + +static struct curl_slist *cookie_list(struct Curl_easy *data) +{ + struct curl_slist *list = NULL; + struct curl_slist *beg; + struct Cookie *c; + char *line; + unsigned int i; + + if((data->cookies == NULL) || + (data->cookies->numcookies == 0)) + return NULL; + + for(i = 0; i < COOKIE_HASH_SIZE; i++) { + for(c = data->cookies->cookies[i]; c; c = c->next) { + if(!c->domain) + continue; + line = get_netscape_format(c); + if(!line) { + curl_slist_free_all(list); + return NULL; + } + beg = Curl_slist_append_nodup(list, line); + if(!beg) { + free(line); + curl_slist_free_all(list); + return NULL; + } + list = beg; + } + } + + return list; +} + +struct curl_slist *Curl_cookie_list(struct Curl_easy *data) +{ + struct curl_slist *list; + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + list = cookie_list(data); + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + return list; +} + +void Curl_flush_cookies(struct Curl_easy *data, int cleanup) +{ + if(data->set.str[STRING_COOKIEJAR]) { + if(data->change.cookielist) { + /* If there is a list of cookie files to read, do it first so that + we have all the told files read before we write the new jar. + Curl_cookie_loadfiles() LOCKS and UNLOCKS the share itself! */ + Curl_cookie_loadfiles(data); + } + + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + + /* if we have a destination file for all the cookies to get dumped to */ + if(cookie_output(data->cookies, data->set.str[STRING_COOKIEJAR])) + infof(data, "WARNING: failed to save cookies in %s\n", + data->set.str[STRING_COOKIEJAR]); + } + else { + if(cleanup && data->change.cookielist) { + /* since nothing is written, we can just free the list of cookie file + names */ + curl_slist_free_all(data->change.cookielist); /* clean up list */ + data->change.cookielist = NULL; + } + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + } + + if(cleanup && (!data->share || (data->cookies != data->share->cookies))) { + Curl_cookie_cleanup(data->cookies); + } + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); +} + +#endif /* CURL_DISABLE_HTTP || CURL_DISABLE_COOKIES */ diff --git a/dependencies/cmcurl/lib/cookie.h b/dependencies/cmcurl/lib/cookie.h new file mode 100644 index 0000000..b2730cf --- /dev/null +++ b/dependencies/cmcurl/lib/cookie.h @@ -0,0 +1,120 @@ +#ifndef HEADER_CURL_COOKIE_H +#define HEADER_CURL_COOKIE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#include + +struct Cookie { + struct Cookie *next; /* next in the chain */ + char *name; /* = value */ + char *value; /* name = */ + char *path; /* path = which is in Set-Cookie: */ + char *spath; /* sanitized cookie path */ + char *domain; /* domain = */ + curl_off_t expires; /* expires = */ + char *expirestr; /* the plain text version */ + bool tailmatch; /* whether we do tail-matching of the domain name */ + + /* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */ + char *version; /* Version = */ + char *maxage; /* Max-Age = */ + + bool secure; /* whether the 'secure' keyword was used */ + bool livecookie; /* updated from a server, not a stored file */ + bool httponly; /* true if the httponly directive is present */ + int creationtime; /* time when the cookie was written */ + unsigned char prefix; /* bitmap fields indicating which prefix are set */ +}; + +/* + * Available cookie prefixes, as defined in + * draft-ietf-httpbis-rfc6265bis-02 + */ +#define COOKIE_PREFIX__SECURE (1<<0) +#define COOKIE_PREFIX__HOST (1<<1) + +#define COOKIE_HASH_SIZE 256 + +struct CookieInfo { + /* linked list of cookies we know of */ + struct Cookie *cookies[COOKIE_HASH_SIZE]; + + char *filename; /* file we read from/write to */ + bool running; /* state info, for cookie adding information */ + long numcookies; /* number of cookies in the "jar" */ + bool newsession; /* new session, discard session cookies on load */ + int lastct; /* last creation-time used in the jar */ +}; + +/* This is the maximum line length we accept for a cookie line. RFC 2109 + section 6.3 says: + + "at least 4096 bytes per cookie (as measured by the size of the characters + that comprise the cookie non-terminal in the syntax description of the + Set-Cookie header)" + + We allow max 5000 bytes cookie header. Max 4095 bytes length per cookie + name and value. Name + value may not exceed 4096 bytes. + +*/ +#define MAX_COOKIE_LINE 5000 + +/* This is the maximum length of a cookie name or content we deal with: */ +#define MAX_NAME 4096 +#define MAX_NAME_TXT "4095" + +struct Curl_easy; +/* + * Add a cookie to the internal list of cookies. The domain and path arguments + * are only used if the header boolean is TRUE. + */ + +struct Cookie *Curl_cookie_add(struct Curl_easy *data, + struct CookieInfo *, bool header, bool noexpiry, + char *lineptr, + const char *domain, const char *path, + bool secure); + +struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *, + const char *, bool); +void Curl_cookie_freelist(struct Cookie *cookies); +void Curl_cookie_clearall(struct CookieInfo *cookies); +void Curl_cookie_clearsess(struct CookieInfo *cookies); + +#if defined(CURL_DISABLE_HTTP) || defined(CURL_DISABLE_COOKIES) +#define Curl_cookie_list(x) NULL +#define Curl_cookie_loadfiles(x) Curl_nop_stmt +#define Curl_cookie_init(x,y,z,w) NULL +#define Curl_cookie_cleanup(x) Curl_nop_stmt +#define Curl_flush_cookies(x,y) Curl_nop_stmt +#else +void Curl_flush_cookies(struct Curl_easy *data, int cleanup); +void Curl_cookie_cleanup(struct CookieInfo *); +struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, + const char *, struct CookieInfo *, bool); +struct curl_slist *Curl_cookie_list(struct Curl_easy *data); +void Curl_cookie_loadfiles(struct Curl_easy *data); +#endif + +#endif /* HEADER_CURL_COOKIE_H */ diff --git a/dependencies/cmcurl/lib/curl_addrinfo.c b/dependencies/cmcurl/lib/curl_addrinfo.c new file mode 100644 index 0000000..16c4779 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_addrinfo.c @@ -0,0 +1,624 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_NETINET_IN6_H +# include +#endif +#ifdef HAVE_NETDB_H +# include +#endif +#ifdef HAVE_ARPA_INET_H +# include +#endif +#ifdef HAVE_SYS_UN_H +# include +#endif + +#ifdef __VMS +# include +# include +#endif + +#if defined(NETWARE) && defined(__NOVELL_LIBC__) +# undef in_addr_t +# define in_addr_t unsigned long +#endif + +#if defined(WIN32) && defined(USE_UNIX_SOCKETS) +#include +#endif + +#include + +#include "curl_addrinfo.h" +#include "inet_pton.h" +#include "warnless.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Curl_freeaddrinfo() + * + * This is used to free a linked list of Curl_addrinfo structs along + * with all its associated allocated storage. This function should be + * called once for each successful call to Curl_getaddrinfo_ex() or to + * any function call which actually allocates a Curl_addrinfo struct. + */ + +#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \ + defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__) + /* workaround icc 9.1 optimizer issue */ +# define vqualifier volatile +#else +# define vqualifier +#endif + +void +Curl_freeaddrinfo(Curl_addrinfo *cahead) +{ + Curl_addrinfo *vqualifier canext; + Curl_addrinfo *ca; + + for(ca = cahead; ca != NULL; ca = canext) { + free(ca->ai_addr); + free(ca->ai_canonname); + canext = ca->ai_next; + + free(ca); + } +} + + +#ifdef HAVE_GETADDRINFO +/* + * Curl_getaddrinfo_ex() + * + * This is a wrapper function around system's getaddrinfo(), with + * the only difference that instead of returning a linked list of + * addrinfo structs this one returns a linked list of Curl_addrinfo + * ones. The memory allocated by this function *MUST* be free'd with + * Curl_freeaddrinfo(). For each successful call to this function + * there must be an associated call later to Curl_freeaddrinfo(). + * + * There should be no single call to system's getaddrinfo() in the + * whole library, any such call should be 'routed' through this one. + */ + +int +Curl_getaddrinfo_ex(const char *nodename, + const char *servname, + const struct addrinfo *hints, + Curl_addrinfo **result) +{ + const struct addrinfo *ai; + struct addrinfo *aihead; + Curl_addrinfo *cafirst = NULL; + Curl_addrinfo *calast = NULL; + Curl_addrinfo *ca; + size_t ss_size; + int error; + + *result = NULL; /* assume failure */ + + error = getaddrinfo(nodename, servname, hints, &aihead); + if(error) + return error; + + /* traverse the addrinfo list */ + + for(ai = aihead; ai != NULL; ai = ai->ai_next) { + + /* ignore elements with unsupported address family, */ + /* settle family-specific sockaddr structure size. */ + if(ai->ai_family == AF_INET) + ss_size = sizeof(struct sockaddr_in); +#ifdef ENABLE_IPV6 + else if(ai->ai_family == AF_INET6) + ss_size = sizeof(struct sockaddr_in6); +#endif + else + continue; + + /* ignore elements without required address info */ + if((ai->ai_addr == NULL) || !(ai->ai_addrlen > 0)) + continue; + + /* ignore elements with bogus address size */ + if((size_t)ai->ai_addrlen < ss_size) + continue; + + ca = malloc(sizeof(Curl_addrinfo)); + if(!ca) { + error = EAI_MEMORY; + break; + } + + /* copy each structure member individually, member ordering, */ + /* size, or padding might be different for each platform. */ + + ca->ai_flags = ai->ai_flags; + ca->ai_family = ai->ai_family; + ca->ai_socktype = ai->ai_socktype; + ca->ai_protocol = ai->ai_protocol; + ca->ai_addrlen = (curl_socklen_t)ss_size; + ca->ai_addr = NULL; + ca->ai_canonname = NULL; + ca->ai_next = NULL; + + ca->ai_addr = malloc(ss_size); + if(!ca->ai_addr) { + error = EAI_MEMORY; + free(ca); + break; + } + memcpy(ca->ai_addr, ai->ai_addr, ss_size); + + if(ai->ai_canonname != NULL) { + ca->ai_canonname = strdup(ai->ai_canonname); + if(!ca->ai_canonname) { + error = EAI_MEMORY; + free(ca->ai_addr); + free(ca); + break; + } + } + + /* if the return list is empty, this becomes the first element */ + if(!cafirst) + cafirst = ca; + + /* add this element last in the return list */ + if(calast) + calast->ai_next = ca; + calast = ca; + + } + + /* destroy the addrinfo list */ + if(aihead) + freeaddrinfo(aihead); + + /* if we failed, also destroy the Curl_addrinfo list */ + if(error) { + Curl_freeaddrinfo(cafirst); + cafirst = NULL; + } + else if(!cafirst) { +#ifdef EAI_NONAME + /* rfc3493 conformant */ + error = EAI_NONAME; +#else + /* rfc3493 obsoleted */ + error = EAI_NODATA; +#endif +#ifdef USE_WINSOCK + SET_SOCKERRNO(error); +#endif + } + + *result = cafirst; + + /* This is not a CURLcode */ + return error; +} +#endif /* HAVE_GETADDRINFO */ + + +/* + * Curl_he2ai() + * + * This function returns a pointer to the first element of a newly allocated + * Curl_addrinfo struct linked list filled with the data of a given hostent. + * Curl_addrinfo is meant to work like the addrinfo struct does for a IPv6 + * stack, but usable also for IPv4, all hosts and environments. + * + * The memory allocated by this function *MUST* be free'd later on calling + * Curl_freeaddrinfo(). For each successful call to this function there + * must be an associated call later to Curl_freeaddrinfo(). + * + * Curl_addrinfo defined in "lib/curl_addrinfo.h" + * + * struct Curl_addrinfo { + * int ai_flags; + * int ai_family; + * int ai_socktype; + * int ai_protocol; + * curl_socklen_t ai_addrlen; * Follow rfc3493 struct addrinfo * + * char *ai_canonname; + * struct sockaddr *ai_addr; + * struct Curl_addrinfo *ai_next; + * }; + * typedef struct Curl_addrinfo Curl_addrinfo; + * + * hostent defined in + * + * struct hostent { + * char *h_name; + * char **h_aliases; + * int h_addrtype; + * int h_length; + * char **h_addr_list; + * }; + * + * for backward compatibility: + * + * #define h_addr h_addr_list[0] + */ + +Curl_addrinfo * +Curl_he2ai(const struct hostent *he, int port) +{ + Curl_addrinfo *ai; + Curl_addrinfo *prevai = NULL; + Curl_addrinfo *firstai = NULL; + struct sockaddr_in *addr; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 *addr6; +#endif + CURLcode result = CURLE_OK; + int i; + char *curr; + + if(!he) + /* no input == no output! */ + return NULL; + + DEBUGASSERT((he->h_name != NULL) && (he->h_addr_list != NULL)); + + for(i = 0; (curr = he->h_addr_list[i]) != NULL; i++) { + + size_t ss_size; +#ifdef ENABLE_IPV6 + if(he->h_addrtype == AF_INET6) + ss_size = sizeof(struct sockaddr_in6); + else +#endif + ss_size = sizeof(struct sockaddr_in); + + ai = calloc(1, sizeof(Curl_addrinfo)); + if(!ai) { + result = CURLE_OUT_OF_MEMORY; + break; + } + ai->ai_canonname = strdup(he->h_name); + if(!ai->ai_canonname) { + result = CURLE_OUT_OF_MEMORY; + free(ai); + break; + } + ai->ai_addr = calloc(1, ss_size); + if(!ai->ai_addr) { + result = CURLE_OUT_OF_MEMORY; + free(ai->ai_canonname); + free(ai); + break; + } + + if(!firstai) + /* store the pointer we want to return from this function */ + firstai = ai; + + if(prevai) + /* make the previous entry point to this */ + prevai->ai_next = ai; + + ai->ai_family = he->h_addrtype; + + /* we return all names as STREAM, so when using this address for TFTP + the type must be ignored and conn->socktype be used instead! */ + ai->ai_socktype = SOCK_STREAM; + + ai->ai_addrlen = (curl_socklen_t)ss_size; + + /* leave the rest of the struct filled with zero */ + + switch(ai->ai_family) { + case AF_INET: + addr = (void *)ai->ai_addr; /* storage area for this info */ + + memcpy(&addr->sin_addr, curr, sizeof(struct in_addr)); + addr->sin_family = (CURL_SA_FAMILY_T)(he->h_addrtype); + addr->sin_port = htons((unsigned short)port); + break; + +#ifdef ENABLE_IPV6 + case AF_INET6: + addr6 = (void *)ai->ai_addr; /* storage area for this info */ + + memcpy(&addr6->sin6_addr, curr, sizeof(struct in6_addr)); + addr6->sin6_family = (CURL_SA_FAMILY_T)(he->h_addrtype); + addr6->sin6_port = htons((unsigned short)port); + break; +#endif + } + + prevai = ai; + } + + if(result) { + Curl_freeaddrinfo(firstai); + firstai = NULL; + } + + return firstai; +} + + +struct namebuff { + struct hostent hostentry; + union { + struct in_addr ina4; +#ifdef ENABLE_IPV6 + struct in6_addr ina6; +#endif + } addrentry; + char *h_addr_list[2]; +}; + + +/* + * Curl_ip2addr() + * + * This function takes an internet address, in binary form, as input parameter + * along with its address family and the string version of the address, and it + * returns a Curl_addrinfo chain filled in correctly with information for the + * given address/host + */ + +Curl_addrinfo * +Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port) +{ + Curl_addrinfo *ai; + +#if defined(__VMS) && \ + defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64) +#pragma pointer_size save +#pragma pointer_size short +#pragma message disable PTRMISMATCH +#endif + + struct hostent *h; + struct namebuff *buf; + char *addrentry; + char *hoststr; + size_t addrsize; + + DEBUGASSERT(inaddr && hostname); + + buf = malloc(sizeof(struct namebuff)); + if(!buf) + return NULL; + + hoststr = strdup(hostname); + if(!hoststr) { + free(buf); + return NULL; + } + + switch(af) { + case AF_INET: + addrsize = sizeof(struct in_addr); + addrentry = (void *)&buf->addrentry.ina4; + memcpy(addrentry, inaddr, sizeof(struct in_addr)); + break; +#ifdef ENABLE_IPV6 + case AF_INET6: + addrsize = sizeof(struct in6_addr); + addrentry = (void *)&buf->addrentry.ina6; + memcpy(addrentry, inaddr, sizeof(struct in6_addr)); + break; +#endif + default: + free(hoststr); + free(buf); + return NULL; + } + + h = &buf->hostentry; + h->h_name = hoststr; + h->h_aliases = NULL; + h->h_addrtype = (short)af; + h->h_length = (short)addrsize; + h->h_addr_list = &buf->h_addr_list[0]; + h->h_addr_list[0] = addrentry; + h->h_addr_list[1] = NULL; /* terminate list of entries */ + +#if defined(__VMS) && \ + defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64) +#pragma pointer_size restore +#pragma message enable PTRMISMATCH +#endif + + ai = Curl_he2ai(h, port); + + free(hoststr); + free(buf); + + return ai; +} + +/* + * Given an IPv4 or IPv6 dotted string address, this converts it to a proper + * allocated Curl_addrinfo struct and returns it. + */ +Curl_addrinfo *Curl_str2addr(char *address, int port) +{ + struct in_addr in; + if(Curl_inet_pton(AF_INET, address, &in) > 0) + /* This is a dotted IP address 123.123.123.123-style */ + return Curl_ip2addr(AF_INET, &in, address, port); +#ifdef ENABLE_IPV6 + { + struct in6_addr in6; + if(Curl_inet_pton(AF_INET6, address, &in6) > 0) + /* This is a dotted IPv6 address ::1-style */ + return Curl_ip2addr(AF_INET6, &in6, address, port); + } +#endif + return NULL; /* bad input format */ +} + +#ifdef USE_UNIX_SOCKETS +/** + * Given a path to a Unix domain socket, return a newly allocated Curl_addrinfo + * struct initialized with this path. + * Set '*longpath' to TRUE if the error is a too long path. + */ +Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract) +{ + Curl_addrinfo *ai; + struct sockaddr_un *sa_un; + size_t path_len; + + *longpath = FALSE; + + ai = calloc(1, sizeof(Curl_addrinfo)); + if(!ai) + return NULL; + ai->ai_addr = calloc(1, sizeof(struct sockaddr_un)); + if(!ai->ai_addr) { + free(ai); + return NULL; + } + + sa_un = (void *) ai->ai_addr; + sa_un->sun_family = AF_UNIX; + + /* sun_path must be able to store the NUL-terminated path */ + path_len = strlen(path) + 1; + if(path_len > sizeof(sa_un->sun_path)) { + free(ai->ai_addr); + free(ai); + *longpath = TRUE; + return NULL; + } + + ai->ai_family = AF_UNIX; + ai->ai_socktype = SOCK_STREAM; /* assume reliable transport for HTTP */ + ai->ai_addrlen = (curl_socklen_t) + ((offsetof(struct sockaddr_un, sun_path) + path_len) & 0x7FFFFFFF); + + /* Abstract Unix domain socket have NULL prefix instead of suffix */ + if(abstract) + memcpy(sa_un->sun_path + 1, path, path_len - 1); + else + memcpy(sa_un->sun_path, path, path_len); /* copy NUL byte */ + + return ai; +} +#endif + +#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \ + defined(HAVE_FREEADDRINFO) +/* + * curl_dbg_freeaddrinfo() + * + * This is strictly for memory tracing and are using the same style as the + * family otherwise present in memdebug.c. I put these ones here since they + * require a bunch of structs I didn't want to include in memdebug.c + */ + +void +curl_dbg_freeaddrinfo(struct addrinfo *freethis, + int line, const char *source) +{ + curl_dbg_log("ADDR %s:%d freeaddrinfo(%p)\n", + source, line, (void *)freethis); +#ifdef USE_LWIPSOCK + lwip_freeaddrinfo(freethis); +#else + (freeaddrinfo)(freethis); +#endif +} +#endif /* defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO) */ + + +#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) +/* + * curl_dbg_getaddrinfo() + * + * This is strictly for memory tracing and are using the same style as the + * family otherwise present in memdebug.c. I put these ones here since they + * require a bunch of structs I didn't want to include in memdebug.c + */ + +int +curl_dbg_getaddrinfo(const char *hostname, + const char *service, + const struct addrinfo *hints, + struct addrinfo **result, + int line, const char *source) +{ +#ifdef USE_LWIPSOCK + int res = lwip_getaddrinfo(hostname, service, hints, result); +#else + int res = (getaddrinfo)(hostname, service, hints, result); +#endif + if(0 == res) + /* success */ + curl_dbg_log("ADDR %s:%d getaddrinfo() = %p\n", + source, line, (void *)*result); + else + curl_dbg_log("ADDR %s:%d getaddrinfo() failed\n", + source, line); + return res; +} +#endif /* defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) */ + +#if defined(HAVE_GETADDRINFO) && defined(USE_RESOLVE_ON_IPS) +/* + * Work-arounds the sin6_port is always zero bug on iOS 9.3.2 and Mac OS X + * 10.11.5. + */ +void Curl_addrinfo_set_port(Curl_addrinfo *addrinfo, int port) +{ + Curl_addrinfo *ca; + struct sockaddr_in *addr; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 *addr6; +#endif + for(ca = addrinfo; ca != NULL; ca = ca->ai_next) { + switch(ca->ai_family) { + case AF_INET: + addr = (void *)ca->ai_addr; /* storage area for this info */ + addr->sin_port = htons((unsigned short)port); + break; + +#ifdef ENABLE_IPV6 + case AF_INET6: + addr6 = (void *)ca->ai_addr; /* storage area for this info */ + addr6->sin6_port = htons((unsigned short)port); + break; +#endif + } + } +} +#endif diff --git a/dependencies/cmcurl/lib/curl_addrinfo.h b/dependencies/cmcurl/lib/curl_addrinfo.h new file mode 100644 index 0000000..205e121 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_addrinfo.h @@ -0,0 +1,107 @@ +#ifndef HEADER_CURL_ADDRINFO_H +#define HEADER_CURL_ADDRINFO_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_NETDB_H +# include +#endif +#ifdef HAVE_ARPA_INET_H +# include +#endif + +#ifdef __VMS +# include +# include +# include +#endif + + +/* + * Curl_addrinfo is our internal struct definition that we use to allow + * consistent internal handling of this data. We use this even when the + * system provides an addrinfo structure definition. And we use this for + * all sorts of IPv4 and IPV6 builds. + */ + +struct Curl_addrinfo { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + curl_socklen_t ai_addrlen; /* Follow rfc3493 struct addrinfo */ + char *ai_canonname; + struct sockaddr *ai_addr; + struct Curl_addrinfo *ai_next; +}; +typedef struct Curl_addrinfo Curl_addrinfo; + +void +Curl_freeaddrinfo(Curl_addrinfo *cahead); + +#ifdef HAVE_GETADDRINFO +int +Curl_getaddrinfo_ex(const char *nodename, + const char *servname, + const struct addrinfo *hints, + Curl_addrinfo **result); +#endif + +Curl_addrinfo * +Curl_he2ai(const struct hostent *he, int port); + +Curl_addrinfo * +Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port); + +Curl_addrinfo *Curl_str2addr(char *dotted, int port); + +#ifdef USE_UNIX_SOCKETS +Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract); +#endif + +#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \ + defined(HAVE_FREEADDRINFO) +void +curl_dbg_freeaddrinfo(struct addrinfo *freethis, int line, const char *source); +#endif + +#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) +int +curl_dbg_getaddrinfo(const char *hostname, const char *service, + const struct addrinfo *hints, struct addrinfo **result, + int line, const char *source); +#endif + +#ifdef HAVE_GETADDRINFO +#ifdef USE_RESOLVE_ON_IPS +void Curl_addrinfo_set_port(Curl_addrinfo *addrinfo, int port); +#else +#define Curl_addrinfo_set_port(x,y) +#endif +#endif + +#endif /* HEADER_CURL_ADDRINFO_H */ diff --git a/dependencies/cmcurl/lib/curl_base64.h b/dependencies/cmcurl/lib/curl_base64.h new file mode 100644 index 0000000..7e9fc26 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_base64.h @@ -0,0 +1,35 @@ +#ifndef HEADER_CURL_BASE64_H +#define HEADER_CURL_BASE64_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +CURLcode Curl_base64_encode(struct Curl_easy *data, + const char *inputbuff, size_t insize, + char **outptr, size_t *outlen); +CURLcode Curl_base64url_encode(struct Curl_easy *data, + const char *inputbuff, size_t insize, + char **outptr, size_t *outlen); + +CURLcode Curl_base64_decode(const char *src, + unsigned char **outptr, size_t *outlen); + +#endif /* HEADER_CURL_BASE64_H */ diff --git a/dependencies/cmcurl/lib/curl_config.h.cmake b/dependencies/cmcurl/lib/curl_config.h.cmake new file mode 100644 index 0000000..b285c3f --- /dev/null +++ b/dependencies/cmcurl/lib/curl_config.h.cmake @@ -0,0 +1,1024 @@ +/* lib/curl_config.h.in. Generated somehow by cmake. */ + +/* when building libcurl itself */ +#cmakedefine BUILDING_LIBCURL 1 + +/* to disable cookies support */ +#cmakedefine CURL_DISABLE_COOKIES 1 + +/* to disable cryptographic authentication */ +#cmakedefine CURL_DISABLE_CRYPTO_AUTH 1 + +/* to disable DICT */ +#cmakedefine CURL_DISABLE_DICT 1 + +/* to disable FILE */ +#cmakedefine CURL_DISABLE_FILE 1 + +/* to disable FTP */ +#cmakedefine CURL_DISABLE_FTP 1 + +/* to disable GOPHER */ +#cmakedefine CURL_DISABLE_GOPHER 1 + +/* to disable IMAP */ +#cmakedefine CURL_DISABLE_IMAP 1 + +/* to disable HTTP */ +#cmakedefine CURL_DISABLE_HTTP 1 + +/* to disable LDAP */ +#cmakedefine CURL_DISABLE_LDAP 1 + +/* to disable LDAPS */ +#cmakedefine CURL_DISABLE_LDAPS 1 + +/* to disable POP3 */ +#cmakedefine CURL_DISABLE_POP3 1 + +/* to disable proxies */ +#cmakedefine CURL_DISABLE_PROXY 1 + +/* to disable RTSP */ +#cmakedefine CURL_DISABLE_RTSP 1 + +/* to disable SMB */ +#cmakedefine CURL_DISABLE_SMB 1 + +/* to disable SMTP */ +#cmakedefine CURL_DISABLE_SMTP 1 + +/* to disable TELNET */ +#cmakedefine CURL_DISABLE_TELNET 1 + +/* to disable TFTP */ +#cmakedefine CURL_DISABLE_TFTP 1 + +/* to disable verbose strings */ +#cmakedefine CURL_DISABLE_VERBOSE_STRINGS 1 + +/* to make a symbol visible */ +#cmakedefine CURL_EXTERN_SYMBOL ${CURL_EXTERN_SYMBOL} +/* Ensure using CURL_EXTERN_SYMBOL is possible */ +#ifndef CURL_EXTERN_SYMBOL +#define CURL_EXTERN_SYMBOL +#endif + +/* Use Windows LDAP implementation */ +#cmakedefine USE_WIN32_LDAP 1 + +/* when not building a shared library */ +#cmakedefine CURL_STATICLIB 1 + +/* your Entropy Gathering Daemon socket pathname */ +#cmakedefine EGD_SOCKET ${EGD_SOCKET} + +/* Define if you want to enable IPv6 support */ +#cmakedefine ENABLE_IPV6 1 + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#cmakedefine GETNAMEINFO_QUAL_ARG1 ${GETNAMEINFO_QUAL_ARG1} + +/* Define to the type of arg 1 for getnameinfo. */ +#cmakedefine GETNAMEINFO_TYPE_ARG1 ${GETNAMEINFO_TYPE_ARG1} + +/* Define to the type of arg 2 for getnameinfo. */ +#cmakedefine GETNAMEINFO_TYPE_ARG2 ${GETNAMEINFO_TYPE_ARG2} + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#cmakedefine GETNAMEINFO_TYPE_ARG46 ${GETNAMEINFO_TYPE_ARG46} + +/* Define to the type of arg 7 for getnameinfo. */ +#cmakedefine GETNAMEINFO_TYPE_ARG7 ${GETNAMEINFO_TYPE_ARG7} + +/* Specifies the number of arguments to getservbyport_r */ +#cmakedefine GETSERVBYPORT_R_ARGS ${GETSERVBYPORT_R_ARGS} + +/* Specifies the size of the buffer to pass to getservbyport_r */ +#cmakedefine GETSERVBYPORT_R_BUFSIZE ${GETSERVBYPORT_R_BUFSIZE} + +/* Define to 1 if you have the alarm function. */ +#cmakedefine HAVE_ALARM 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ARPA_TFTP_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ASSERT_H 1 + +/* Define to 1 if you have the `basename' function. */ +#cmakedefine HAVE_BASENAME 1 + +/* Define to 1 if bool is an available type. */ +#cmakedefine HAVE_BOOL_T 1 + +/* Define to 1 if you have the __builtin_available function. */ +#cmakedefine HAVE_BUILTIN_AVAILABLE 1 + +/* Define to 1 if you have the clock_gettime function and monotonic timer. */ +#cmakedefine HAVE_CLOCK_GETTIME_MONOTONIC 1 + +/* Define to 1 if you have the `closesocket' function. */ +#cmakedefine HAVE_CLOSESOCKET 1 + +/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ +#cmakedefine HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_CRYPTO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_DES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */ +#cmakedefine HAVE_ENGINE_LOAD_BUILTIN_ENGINES 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ERR_H 1 + +/* Define to 1 if you have the fcntl function. */ +#cmakedefine HAVE_FCNTL 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_FCNTL_H 1 + +/* Define to 1 if you have a working fcntl O_NONBLOCK function. */ +#cmakedefine HAVE_FCNTL_O_NONBLOCK 1 + +/* Define to 1 if you have the fdopen function. */ +#cmakedefine HAVE_FDOPEN 1 + +/* Define to 1 if you have the `fork' function. */ +#cmakedefine HAVE_FORK 1 + +/* Define to 1 if you have the freeaddrinfo function. */ +#cmakedefine HAVE_FREEADDRINFO 1 + +/* Define to 1 if you have the freeifaddrs function. */ +#cmakedefine HAVE_FREEIFADDRS 1 + +/* Define to 1 if you have the ftruncate function. */ +#cmakedefine HAVE_FTRUNCATE 1 + +/* Define to 1 if you have a working getaddrinfo function. */ +#cmakedefine HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the `geteuid' function. */ +#cmakedefine HAVE_GETEUID 1 + +/* Define to 1 if you have the gethostbyaddr function. */ +#cmakedefine HAVE_GETHOSTBYADDR 1 + +/* Define to 1 if you have the gethostbyaddr_r function. */ +#cmakedefine HAVE_GETHOSTBYADDR_R 1 + +/* gethostbyaddr_r() takes 5 args */ +#cmakedefine HAVE_GETHOSTBYADDR_R_5 1 + +/* gethostbyaddr_r() takes 7 args */ +#cmakedefine HAVE_GETHOSTBYADDR_R_7 1 + +/* gethostbyaddr_r() takes 8 args */ +#cmakedefine HAVE_GETHOSTBYADDR_R_8 1 + +/* Define to 1 if you have the gethostbyname function. */ +#cmakedefine HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the gethostbyname_r function. */ +#cmakedefine HAVE_GETHOSTBYNAME_R 1 + +/* gethostbyname_r() takes 3 args */ +#cmakedefine HAVE_GETHOSTBYNAME_R_3 1 + +/* gethostbyname_r() takes 5 args */ +#cmakedefine HAVE_GETHOSTBYNAME_R_5 1 + +/* gethostbyname_r() takes 6 args */ +#cmakedefine HAVE_GETHOSTBYNAME_R_6 1 + +/* Define to 1 if you have the gethostname function. */ +#cmakedefine HAVE_GETHOSTNAME 1 + +/* Define to 1 if you have a working getifaddrs function. */ +#cmakedefine HAVE_GETIFADDRS 1 + +/* Define to 1 if you have the getnameinfo function. */ +#cmakedefine HAVE_GETNAMEINFO 1 + +/* Define to 1 if you have the `getpass_r' function. */ +#cmakedefine HAVE_GETPASS_R 1 + +/* Define to 1 if you have the `getppid' function. */ +#cmakedefine HAVE_GETPPID 1 + +/* Define to 1 if you have the `getprotobyname' function. */ +#cmakedefine HAVE_GETPROTOBYNAME 1 + +/* Define to 1 if you have the `getpeername' function. */ +#cmakedefine HAVE_GETPEERNAME 1 + +/* Define to 1 if you have the `getsockname' function. */ +#cmakedefine HAVE_GETSOCKNAME 1 + +/* Define to 1 if you have the `getpwuid' function. */ +#cmakedefine HAVE_GETPWUID 1 + +/* Define to 1 if you have the `getpwuid_r' function. */ +#cmakedefine HAVE_GETPWUID_R 1 + +/* Define to 1 if you have the `getrlimit' function. */ +#cmakedefine HAVE_GETRLIMIT 1 + +/* Define to 1 if you have the getservbyport_r function. */ +#cmakedefine HAVE_GETSERVBYPORT_R 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#cmakedefine HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have a working glibc-style strerror_r function. */ +#cmakedefine HAVE_GLIBC_STRERROR_R 1 + +/* Define to 1 if you have a working gmtime_r function. */ +#cmakedefine HAVE_GMTIME_R 1 + +/* if you have the gssapi libraries */ +#cmakedefine HAVE_GSSAPI 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_GSSAPI_GSSAPI_GENERIC_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_GSSAPI_GSSAPI_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_GSSAPI_GSSAPI_KRB5_H 1 + +/* if you have the GNU gssapi libraries */ +#cmakedefine HAVE_GSSGNU 1 + +/* if you have the Heimdal gssapi libraries */ +#cmakedefine HAVE_GSSHEIMDAL 1 + +/* if you have the MIT gssapi libraries */ +#cmakedefine HAVE_GSSMIT 1 + +/* Define to 1 if you have the `idna_strerror' function. */ +#cmakedefine HAVE_IDNA_STRERROR 1 + +/* Define to 1 if you have the `idn_free' function. */ +#cmakedefine HAVE_IDN_FREE 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_IDN_FREE_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_IFADDRS_H 1 + +/* Define to 1 if you have the `inet_addr' function. */ +#cmakedefine HAVE_INET_ADDR 1 + +/* Define to 1 if you have the inet_ntoa_r function. */ +#cmakedefine HAVE_INET_NTOA_R 1 + +/* inet_ntoa_r() takes 2 args */ +#cmakedefine HAVE_INET_NTOA_R_2 1 + +/* inet_ntoa_r() takes 3 args */ +#cmakedefine HAVE_INET_NTOA_R_3 1 + +/* Define to 1 if you have a IPv6 capable working inet_ntop function. */ +#cmakedefine HAVE_INET_NTOP 1 + +/* Define to 1 if you have a IPv6 capable working inet_pton function. */ +#cmakedefine HAVE_INET_PTON 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the ioctl function. */ +#cmakedefine HAVE_IOCTL 1 + +/* Define to 1 if you have the ioctlsocket function. */ +#cmakedefine HAVE_IOCTLSOCKET 1 + +/* Define to 1 if you have the IoctlSocket camel case function. */ +#cmakedefine HAVE_IOCTLSOCKET_CAMEL 1 + +/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function. + */ +#cmakedefine HAVE_IOCTLSOCKET_CAMEL_FIONBIO 1 + +/* Define to 1 if you have a working ioctlsocket FIONBIO function. */ +#cmakedefine HAVE_IOCTLSOCKET_FIONBIO 1 + +/* Define to 1 if you have a working ioctl FIONBIO function. */ +#cmakedefine HAVE_IOCTL_FIONBIO 1 + +/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */ +#cmakedefine HAVE_IOCTL_SIOCGIFADDR 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_IO_H 1 + +/* if you have the Kerberos4 libraries (including -ldes) */ +#cmakedefine HAVE_KRB4 1 + +/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */ +#cmakedefine HAVE_KRB_GET_OUR_IP_FOR_REALM 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_KRB_H 1 + +/* Define to 1 if you have the lber.h header file. */ +#cmakedefine HAVE_LBER_H 1 + +/* Define to 1 if you have the ldapssl.h header file. */ +#cmakedefine HAVE_LDAPSSL_H 1 + +/* Define to 1 if you have the ldap.h header file. */ +#cmakedefine HAVE_LDAP_H 1 + +/* Use LDAPS implementation */ +#cmakedefine HAVE_LDAP_SSL 1 + +/* Define to 1 if you have the ldap_ssl.h header file. */ +#cmakedefine HAVE_LDAP_SSL_H 1 + +/* Define to 1 if you have the `ldap_url_parse' function. */ +#cmakedefine HAVE_LDAP_URL_PARSE 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LIBGEN_H 1 + +/* Define to 1 if you have the `idn' library (-lidn). */ +#cmakedefine HAVE_LIBIDN 1 + +/* Define to 1 if you have the `resolv' library (-lresolv). */ +#cmakedefine HAVE_LIBRESOLV 1 + +/* Define to 1 if you have the `resolve' library (-lresolve). */ +#cmakedefine HAVE_LIBRESOLVE 1 + +/* Define to 1 if you have the `socket' library (-lsocket). */ +#cmakedefine HAVE_LIBSOCKET 1 + +/* Define to 1 if you have the `ssh2' library (-lssh2). */ +#cmakedefine HAVE_LIBSSH2 1 + +/* Define to 1 if libssh2 provides `libssh2_version'. */ +#cmakedefine HAVE_LIBSSH2_VERSION 1 + +/* Define to 1 if libssh2 provides `libssh2_init'. */ +#cmakedefine HAVE_LIBSSH2_INIT 1 + +/* Define to 1 if libssh2 provides `libssh2_exit'. */ +#cmakedefine HAVE_LIBSSH2_EXIT 1 + +/* Define to 1 if libssh2 provides `libssh2_scp_send64'. */ +#cmakedefine HAVE_LIBSSH2_SCP_SEND64 1 + +/* Define to 1 if libssh2 provides `libssh2_session_handshake'. */ +#cmakedefine HAVE_LIBSSH2_SESSION_HANDSHAKE 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LIBSSH2_H 1 + +/* Define to 1 if you have the `ssl' library (-lssl). */ +#cmakedefine HAVE_LIBSSL 1 + +/* if zlib is available */ +#cmakedefine HAVE_LIBZ 1 + +/* if brotli is available */ +#cmakedefine HAVE_BROTLI 1 + +/* if your compiler supports LL */ +#cmakedefine HAVE_LL 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LOCALE_H 1 + +/* Define to 1 if you have a working localtime_r function. */ +#cmakedefine HAVE_LOCALTIME_R 1 + +/* Define to 1 if the compiler supports the 'long long' data type. */ +#cmakedefine HAVE_LONGLONG 1 + +/* Define to 1 if you have the malloc.h header file. */ +#cmakedefine HAVE_MALLOC_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MEMORY_H 1 + +/* Define to 1 if you have the MSG_NOSIGNAL flag. */ +#cmakedefine HAVE_MSG_NOSIGNAL 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETINET_TCP_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NET_IF_H 1 + +/* Define to 1 if NI_WITHSCOPEID exists and works. */ +#cmakedefine HAVE_NI_WITHSCOPEID 1 + +/* if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE */ +#cmakedefine HAVE_OLD_GSSMIT 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENSSL_CRYPTO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENSSL_ENGINE_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENSSL_ERR_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENSSL_PEM_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENSSL_PKCS12_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENSSL_RSA_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENSSL_SSL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENSSL_X509_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_PEM_H 1 + +/* Define to 1 if you have the `perror' function. */ +#cmakedefine HAVE_PERROR 1 + +/* Define to 1 if you have the `pipe' function. */ +#cmakedefine HAVE_PIPE 1 + +/* Define to 1 if you have a working poll function. */ +#cmakedefine HAVE_POLL 1 + +/* If you have a fine poll */ +#cmakedefine HAVE_POLL_FINE 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_POLL_H 1 + +/* Define to 1 if you have a working POSIX-style strerror_r function. */ +#cmakedefine HAVE_POSIX_STRERROR_R 1 + +/* Define to 1 if you have the header file */ +#cmakedefine HAVE_PTHREAD_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_PWD_H 1 + +/* Define to 1 if you have the `RAND_egd' function. */ +#cmakedefine HAVE_RAND_EGD 1 + +/* Define to 1 if you have the `RAND_screen' function. */ +#cmakedefine HAVE_RAND_SCREEN 1 + +/* Define to 1 if you have the `RAND_status' function. */ +#cmakedefine HAVE_RAND_STATUS 1 + +/* Define to 1 if you have the recv function. */ +#cmakedefine HAVE_RECV 1 + +/* Define to 1 if you have the recvfrom function. */ +#cmakedefine HAVE_RECVFROM 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_RSA_H 1 + +/* Define to 1 if you have the select function. */ +#cmakedefine HAVE_SELECT 1 + +/* Define to 1 if you have the send function. */ +#cmakedefine HAVE_SEND 1 + +/* Define to 1 if you have the 'fsetxattr' function. */ +#cmakedefine HAVE_FSETXATTR 1 + +/* fsetxattr() takes 5 args */ +#cmakedefine HAVE_FSETXATTR_5 1 + +/* fsetxattr() takes 6 args */ +#cmakedefine HAVE_FSETXATTR_6 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SETJMP_H 1 + +/* Define to 1 if you have the `setlocale' function. */ +#cmakedefine HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setmode' function. */ +#cmakedefine HAVE_SETMODE 1 + +/* Define to 1 if you have the `setrlimit' function. */ +#cmakedefine HAVE_SETRLIMIT 1 + +/* Define to 1 if you have the setsockopt function. */ +#cmakedefine HAVE_SETSOCKOPT 1 + +/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ +#cmakedefine HAVE_SETSOCKOPT_SO_NONBLOCK 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SGTTY_H 1 + +/* Define to 1 if you have the sigaction function. */ +#cmakedefine HAVE_SIGACTION 1 + +/* Define to 1 if you have the siginterrupt function. */ +#cmakedefine HAVE_SIGINTERRUPT 1 + +/* Define to 1 if you have the signal function. */ +#cmakedefine HAVE_SIGNAL 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the sigsetjmp function or macro. */ +#cmakedefine HAVE_SIGSETJMP 1 + +/* Define to 1 if sig_atomic_t is an available typedef. */ +#cmakedefine HAVE_SIG_ATOMIC_T 1 + +/* Define to 1 if sig_atomic_t is already defined as volatile. */ +#cmakedefine HAVE_SIG_ATOMIC_T_VOLATILE 1 + +/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */ +#cmakedefine HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +/* Define to 1 if you have the `socket' function. */ +#cmakedefine HAVE_SOCKET 1 + +/* Define to 1 if you have the `SSL_get_shutdown' function. */ +#cmakedefine HAVE_SSL_GET_SHUTDOWN 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SSL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDLIB_H 1 + +/* Define to 1 if you have the strcasecmp function. */ +#cmakedefine HAVE_STRCASECMP 1 + +/* Define to 1 if you have the strcasestr function. */ +#cmakedefine HAVE_STRCASESTR 1 + +/* Define to 1 if you have the strcmpi function. */ +#cmakedefine HAVE_STRCMPI 1 + +/* Define to 1 if you have the strdup function. */ +#cmakedefine HAVE_STRDUP 1 + +/* Define to 1 if you have the strerror_r function. */ +#cmakedefine HAVE_STRERROR_R 1 + +/* Define to 1 if you have the stricmp function. */ +#cmakedefine HAVE_STRICMP 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRING_H 1 + +/* Define to 1 if you have the strlcat function. */ +#cmakedefine HAVE_STRLCAT 1 + +/* Define to 1 if you have the `strlcpy' function. */ +#cmakedefine HAVE_STRLCPY 1 + +/* Define to 1 if you have the strncasecmp function. */ +#cmakedefine HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the strncmpi function. */ +#cmakedefine HAVE_STRNCMPI 1 + +/* Define to 1 if you have the strnicmp function. */ +#cmakedefine HAVE_STRNICMP 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STROPTS_H 1 + +/* Define to 1 if you have the strstr function. */ +#cmakedefine HAVE_STRSTR 1 + +/* Define to 1 if you have the strtok_r function. */ +#cmakedefine HAVE_STRTOK_R 1 + +/* Define to 1 if you have the strtoll function. */ +#cmakedefine HAVE_STRTOLL 1 + +/* if struct sockaddr_storage is defined */ +#cmakedefine HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if you have the timeval struct. */ +#cmakedefine HAVE_STRUCT_TIMEVAL 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_FILIO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_POLL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_SOCKIO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_UIO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_UN_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_UTIME_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_TERMIOS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_TERMIO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_TLD_H 1 + +/* Define to 1 if you have the `tld_strerror' function. */ +#cmakedefine HAVE_TLD_STRERROR 1 + +/* Define to 1 if you have the `uname' function. */ +#cmakedefine HAVE_UNAME 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `utime' function. */ +#cmakedefine HAVE_UTIME 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UTIME_H 1 + +/* Define to 1 if compiler supports C99 variadic macro style. */ +#cmakedefine HAVE_VARIADIC_MACROS_C99 1 + +/* Define to 1 if compiler supports old gcc variadic macro style. */ +#cmakedefine HAVE_VARIADIC_MACROS_GCC 1 + +/* Define to 1 if you have the winber.h header file. */ +#cmakedefine HAVE_WINBER_H 1 + +/* Define to 1 if you have the windows.h header file. */ +#cmakedefine HAVE_WINDOWS_H 1 + +/* Define to 1 if you have the winldap.h header file. */ +#cmakedefine HAVE_WINLDAP_H 1 + +/* Define to 1 if you have the winsock2.h header file. */ +#cmakedefine HAVE_WINSOCK2_H 1 + +/* Define to 1 if you have the winsock.h header file. */ +#cmakedefine HAVE_WINSOCK_H 1 + +/* Define this symbol if your OS supports changing the contents of argv */ +#cmakedefine HAVE_WRITABLE_ARGV 1 + +/* Define to 1 if you have the writev function. */ +#cmakedefine HAVE_WRITEV 1 + +/* Define to 1 if you have the ws2tcpip.h header file. */ +#cmakedefine HAVE_WS2TCPIP_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_X509_H 1 + +/* Define if you have the header file. */ +#cmakedefine HAVE_PROCESS_H 1 + +/* if you have the zlib.h header file */ +#cmakedefine HAVE_ZLIB_H 1 + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#cmakedefine LT_OBJDIR ${LT_OBJDIR} + +/* If you lack a fine basename() prototype */ +#cmakedefine NEED_BASENAME_PROTO 1 + +/* Define to 1 if you need the lber.h header file even with ldap.h */ +#cmakedefine NEED_LBER_H 1 + +/* Define to 1 if you need the malloc.h header file even with stdlib.h */ +#cmakedefine NEED_MALLOC_H 1 + +/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ +#cmakedefine NEED_REENTRANT 1 + +/* cpu-machine-OS */ +#cmakedefine OS ${OS} + +/* Name of package */ +#cmakedefine PACKAGE ${PACKAGE} + +/* Define to the address where bug reports for this package should be sent. */ +#cmakedefine PACKAGE_BUGREPORT ${PACKAGE_BUGREPORT} + +/* Define to the full name of this package. */ +#cmakedefine PACKAGE_NAME ${PACKAGE_NAME} + +/* Define to the full name and version of this package. */ +#cmakedefine PACKAGE_STRING ${PACKAGE_STRING} + +/* Define to the one symbol short name of this package. */ +#cmakedefine PACKAGE_TARNAME ${PACKAGE_TARNAME} + +/* Define to the version of this package. */ +#cmakedefine PACKAGE_VERSION ${PACKAGE_VERSION} + +/* a suitable file to read random data from */ +#cmakedefine RANDOM_FILE "${RANDOM_FILE}" + +/* Define to the type of arg 1 for recvfrom. */ +#cmakedefine RECVFROM_TYPE_ARG1 ${RECVFROM_TYPE_ARG1} + +/* Define to the type pointed by arg 2 for recvfrom. */ +#cmakedefine RECVFROM_TYPE_ARG2 ${RECVFROM_TYPE_ARG2} + +/* Define to 1 if the type pointed by arg 2 for recvfrom is void. */ +#cmakedefine RECVFROM_TYPE_ARG2_IS_VOID 1 + +/* Define to the type of arg 3 for recvfrom. */ +#cmakedefine RECVFROM_TYPE_ARG3 ${RECVFROM_TYPE_ARG3} + +/* Define to the type of arg 4 for recvfrom. */ +#cmakedefine RECVFROM_TYPE_ARG4 ${RECVFROM_TYPE_ARG4} + +/* Define to the type pointed by arg 5 for recvfrom. */ +#cmakedefine RECVFROM_TYPE_ARG5 ${RECVFROM_TYPE_ARG5} + +/* Define to 1 if the type pointed by arg 5 for recvfrom is void. */ +#cmakedefine RECVFROM_TYPE_ARG5_IS_VOID 1 + +/* Define to the type pointed by arg 6 for recvfrom. */ +#cmakedefine RECVFROM_TYPE_ARG6 ${RECVFROM_TYPE_ARG6} + +/* Define to 1 if the type pointed by arg 6 for recvfrom is void. */ +#cmakedefine RECVFROM_TYPE_ARG6_IS_VOID 1 + +/* Define to the function return type for recvfrom. */ +#cmakedefine RECVFROM_TYPE_RETV ${RECVFROM_TYPE_RETV} + +/* Define to the type of arg 1 for recv. */ +#cmakedefine RECV_TYPE_ARG1 ${RECV_TYPE_ARG1} + +/* Define to the type of arg 2 for recv. */ +#cmakedefine RECV_TYPE_ARG2 ${RECV_TYPE_ARG2} + +/* Define to the type of arg 3 for recv. */ +#cmakedefine RECV_TYPE_ARG3 ${RECV_TYPE_ARG3} + +/* Define to the type of arg 4 for recv. */ +#cmakedefine RECV_TYPE_ARG4 ${RECV_TYPE_ARG4} + +/* Define to the function return type for recv. */ +#cmakedefine RECV_TYPE_RETV ${RECV_TYPE_RETV} + +/* Define as the return type of signal handlers (`int' or `void'). */ +#cmakedefine RETSIGTYPE ${RETSIGTYPE} + +/* Define to the type qualifier of arg 5 for select. */ +#cmakedefine SELECT_QUAL_ARG5 ${SELECT_QUAL_ARG5} + +/* Define to the type of arg 1 for select. */ +#cmakedefine SELECT_TYPE_ARG1 ${SELECT_TYPE_ARG1} + +/* Define to the type of args 2, 3 and 4 for select. */ +#cmakedefine SELECT_TYPE_ARG234 ${SELECT_TYPE_ARG234} + +/* Define to the type of arg 5 for select. */ +#cmakedefine SELECT_TYPE_ARG5 ${SELECT_TYPE_ARG5} + +/* Define to the function return type for select. */ +#cmakedefine SELECT_TYPE_RETV ${SELECT_TYPE_RETV} + +/* Define to the type qualifier of arg 2 for send. */ +#cmakedefine SEND_QUAL_ARG2 ${SEND_QUAL_ARG2} + +/* Define to the type of arg 1 for send. */ +#cmakedefine SEND_TYPE_ARG1 ${SEND_TYPE_ARG1} + +/* Define to the type of arg 2 for send. */ +#cmakedefine SEND_TYPE_ARG2 ${SEND_TYPE_ARG2} + +/* Define to the type of arg 3 for send. */ +#cmakedefine SEND_TYPE_ARG3 ${SEND_TYPE_ARG3} + +/* Define to the type of arg 4 for send. */ +#cmakedefine SEND_TYPE_ARG4 ${SEND_TYPE_ARG4} + +/* Define to the function return type for send. */ +#cmakedefine SEND_TYPE_RETV ${SEND_TYPE_RETV} + +/* The size of `int', as computed by sizeof. */ +@SIZEOF_INT_CODE@ + +/* The size of `short', as computed by sizeof. */ +@SIZEOF_SHORT_CODE@ + +/* The size of `long', as computed by sizeof. */ +@SIZEOF_LONG_CODE@ + +/* The size of `long long', as computed by sizeof. */ +@SIZEOF_LONG_LONG_CODE@ + +/* The size of `__int64', as computed by sizeof. */ +@SIZEOF___INT64_CODE@ + +/* The size of `off_t', as computed by sizeof. */ +@SIZEOF_OFF_T_CODE@ + +/* The size of `curl_off_t', as computed by sizeof. */ +@SIZEOF_CURL_OFF_T_CODE@ + +/* The size of `size_t', as computed by sizeof. */ +@SIZEOF_SIZE_T_CODE@ + +/* The size of `ssize_t', as computed by sizeof. */ +@SIZEOF_SSIZE_T_CODE@ + +/* The size of `time_t', as computed by sizeof. */ +@SIZEOF_TIME_T_CODE@ + +/* Define to 1 if you have the ANSI C header files. */ +#cmakedefine STDC_HEADERS 1 + +/* Define to the type of arg 3 for strerror_r. */ +#cmakedefine STRERROR_R_TYPE_ARG3 ${STRERROR_R_TYPE_ARG3} + +/* Define to 1 if you can safely include both and . */ +#cmakedefine TIME_WITH_SYS_TIME 1 + +/* Define if you want to enable c-ares support */ +#cmakedefine USE_ARES 1 + +/* Define if you want to enable POSIX threaded DNS lookup */ +#cmakedefine USE_THREADS_POSIX 1 + +/* Define if you want to enable WIN32 threaded DNS lookup */ +#cmakedefine USE_THREADS_WIN32 1 + +/* Define to disable non-blocking sockets. */ +#cmakedefine USE_BLOCKING_SOCKETS 1 + +/* if GnuTLS is enabled */ +#cmakedefine USE_GNUTLS 1 + +/* if PolarSSL is enabled */ +#cmakedefine USE_POLARSSL 1 + +/* if Secure Transport is enabled */ +#cmakedefine USE_SECTRANSP 1 + +/* if mbedTLS is enabled */ +#cmakedefine USE_MBEDTLS 1 + +/* if libSSH2 is in use */ +#cmakedefine USE_LIBSSH2 1 + +/* If you want to build curl with the built-in manual */ +#cmakedefine USE_MANUAL 1 + +/* if NSS is enabled */ +#cmakedefine USE_NSS 1 + +/* if you want to use OpenLDAP code instead of legacy ldap implementation */ +#cmakedefine USE_OPENLDAP 1 + +/* if OpenSSL is in use */ +#cmakedefine USE_OPENSSL 1 + +/* to enable NGHTTP2 */ +#cmakedefine USE_NGHTTP2 1 + +/* if Unix domain sockets are enabled */ +#cmakedefine USE_UNIX_SOCKETS + +/* to enable SSPI support */ +#cmakedefine USE_WINDOWS_SSPI 1 + +/* to enable Windows SSL */ +#cmakedefine USE_SCHANNEL 1 + +/* enable multiple SSL backends */ +#cmakedefine CURL_WITH_MULTI_SSL 1 + +/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */ +#cmakedefine USE_YASSLEMUL 1 + +/* Version number of package */ +#cmakedefine VERSION ${VERSION} + +/* Define to 1 if OS is AIX. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +#cmakedefine _FILE_OFFSET_BITS ${_FILE_OFFSET_BITS} + +/* Define for large files, on AIX-style hosts. */ +#cmakedefine _LARGE_FILES ${_LARGE_FILES} + +/* define this if you need it to compile thread-safe code */ +#cmakedefine _THREAD_SAFE ${_THREAD_SAFE} + +/* Define to empty if `const' does not conform to ANSI C. */ +#cmakedefine const ${const} + +/* Type to use in place of in_addr_t when system does not provide it. */ +#cmakedefine in_addr_t ${in_addr_t} + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif + +/* Define to `unsigned int' if does not define. */ +#cmakedefine size_t ${size_t} + +/* the signed version of size_t */ +#ifndef SIZEOF_SSIZE_T +# if SIZEOF_LONG == SIZEOF_SIZE_T + typedef long ssize_t; +# elif SIZEOF_LONG_LONG == SIZEOF_SIZE_T + typedef long long ssize_t; +# elif SIZEOF___INT64 == SIZEOF_SIZE_T + typedef __int64 ssize_t; +# else + typedef int ssize_t; +# endif +#endif + +/* Define to 1 if you have the mach_absolute_time function. */ +#cmakedefine HAVE_MACH_ABSOLUTE_TIME 1 diff --git a/dependencies/cmcurl/lib/curl_ctype.c b/dependencies/cmcurl/lib/curl_ctype.c new file mode 100644 index 0000000..1a47fb5 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_ctype.c @@ -0,0 +1,133 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DOES_CONVERSIONS + +#undef _U +#define _U (1<<0) /* upper case */ +#undef _L +#define _L (1<<1) /* lower case */ +#undef _N +#define _N (1<<2) /* decimal numerical digit */ +#undef _S +#define _S (1<<3) /* space */ +#undef _P +#define _P (1<<4) /* punctuation */ +#undef _C +#define _C (1<<5) /* control */ +#undef _X +#define _X (1<<6) /* hexadecimal letter */ +#undef _B +#define _B (1<<7) /* blank */ + +static const unsigned char ascii[128] = { + _C, _C, _C, _C, _C, _C, _C, _C, + _C, _C|_S, _C|_S, _C|_S, _C|_S, _C|_S, _C, _C, + _C, _C, _C, _C, _C, _C, _C, _C, + _C, _C, _C, _C, _C, _C, _C, _C, + _S|_B, _P, _P, _P, _P, _P, _P, _P, + _P, _P, _P, _P, _P, _P, _P, _P, + _N, _N, _N, _N, _N, _N, _N, _N, + _N, _N, _P, _P, _P, _P, _P, _P, + _P, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U, + _U, _U, _U, _U, _U, _U, _U, _U, + _U, _U, _U, _U, _U, _U, _U, _U, + _U, _U, _U, _P, _P, _P, _P, _P, + _P, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L, + _L, _L, _L, _L, _L, _L, _L, _L, + _L, _L, _L, _L, _L, _L, _L, _L, + _L, _L, _L, _P, _P, _P, _P, _C +}; + +int Curl_isspace(int c) +{ + if((c < 0) || (c >= 0x80)) + return FALSE; + return (ascii[c] & _S); +} + +int Curl_isdigit(int c) +{ + if((c < 0) || (c >= 0x80)) + return FALSE; + return (ascii[c] & _N); +} + +int Curl_isalnum(int c) +{ + if((c < 0) || (c >= 0x80)) + return FALSE; + return (ascii[c] & (_N|_U|_L)); +} + +int Curl_isxdigit(int c) +{ + if((c < 0) || (c >= 0x80)) + return FALSE; + return (ascii[c] & (_N|_X)); +} + +int Curl_isgraph(int c) +{ + if((c < 0) || (c >= 0x80) || (c == ' ')) + return FALSE; + return (ascii[c] & (_N|_X|_U|_L|_P|_S)); +} + +int Curl_isprint(int c) +{ + if((c < 0) || (c >= 0x80)) + return FALSE; + return (ascii[c] & (_N|_X|_U|_L|_P|_S)); +} + +int Curl_isalpha(int c) +{ + if((c < 0) || (c >= 0x80)) + return FALSE; + return (ascii[c] & (_U|_L)); +} + +int Curl_isupper(int c) +{ + if((c < 0) || (c >= 0x80)) + return FALSE; + return (ascii[c] & (_U)); +} + +int Curl_islower(int c) +{ + if((c < 0) || (c >= 0x80)) + return FALSE; + return (ascii[c] & (_L)); +} + +int Curl_iscntrl(int c) +{ + if((c < 0) || (c >= 0x80)) + return FALSE; + return (ascii[c] & (_C)); +} + +#endif /* !CURL_DOES_CONVERSIONS */ diff --git a/dependencies/cmcurl/lib/curl_ctype.h b/dependencies/cmcurl/lib/curl_ctype.h new file mode 100644 index 0000000..6e94bb1 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_ctype.h @@ -0,0 +1,81 @@ +#ifndef HEADER_CURL_CTYPE_H +#define HEADER_CURL_CTYPE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef CURL_DOES_CONVERSIONS + +/* + * Uppercase macro versions of ANSI/ISO is*() functions/macros which + * avoid negative number inputs with argument byte codes > 127. + * + * For non-ASCII platforms the C library character classification routines + * are used despite being locale-dependent, because this is better than + * not to work at all. + */ +#include + +#define ISSPACE(x) (isspace((int) ((unsigned char)x))) +#define ISDIGIT(x) (isdigit((int) ((unsigned char)x))) +#define ISALNUM(x) (isalnum((int) ((unsigned char)x))) +#define ISXDIGIT(x) (isxdigit((int) ((unsigned char)x))) +#define ISGRAPH(x) (isgraph((int) ((unsigned char)x))) +#define ISALPHA(x) (isalpha((int) ((unsigned char)x))) +#define ISPRINT(x) (isprint((int) ((unsigned char)x))) +#define ISUPPER(x) (isupper((int) ((unsigned char)x))) +#define ISLOWER(x) (islower((int) ((unsigned char)x))) +#define ISCNTRL(x) (iscntrl((int) ((unsigned char)x))) +#define ISASCII(x) (isascii((int) ((unsigned char)x))) + +#else + +int Curl_isspace(int c); +int Curl_isdigit(int c); +int Curl_isalnum(int c); +int Curl_isxdigit(int c); +int Curl_isgraph(int c); +int Curl_isprint(int c); +int Curl_isalpha(int c); +int Curl_isupper(int c); +int Curl_islower(int c); +int Curl_iscntrl(int c); + +#define ISSPACE(x) (Curl_isspace((int) ((unsigned char)x))) +#define ISDIGIT(x) (Curl_isdigit((int) ((unsigned char)x))) +#define ISALNUM(x) (Curl_isalnum((int) ((unsigned char)x))) +#define ISXDIGIT(x) (Curl_isxdigit((int) ((unsigned char)x))) +#define ISGRAPH(x) (Curl_isgraph((int) ((unsigned char)x))) +#define ISALPHA(x) (Curl_isalpha((int) ((unsigned char)x))) +#define ISPRINT(x) (Curl_isprint((int) ((unsigned char)x))) +#define ISUPPER(x) (Curl_isupper((int) ((unsigned char)x))) +#define ISLOWER(x) (Curl_islower((int) ((unsigned char)x))) +#define ISCNTRL(x) (Curl_iscntrl((int) ((unsigned char)x))) +#define ISASCII(x) (((x) >= 0) && ((x) <= 0x80)) + +#endif + +#define ISBLANK(x) (int)((((unsigned char)x) == ' ') || \ + (((unsigned char)x) == '\t')) + +#endif /* HEADER_CURL_CTYPE_H */ diff --git a/dependencies/cmcurl/lib/curl_des.c b/dependencies/cmcurl/lib/curl_des.c new file mode 100644 index 0000000..b123a00 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_des.c @@ -0,0 +1,63 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2015, Steve Holme, . + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_NTLM) && !defined(USE_OPENSSL) + +#include "curl_des.h" + +/* + * Curl_des_set_odd_parity() + * + * This is used to apply odd parity to the given byte array. It is typically + * used by when a cryptography engines doesn't have it's own version. + * + * The function is a port of the Java based oddParity() function over at: + * + * https://davenport.sourceforge.io/ntlm.html + * + * Parameters: + * + * bytes [in/out] - The data whose parity bits are to be adjusted for + * odd parity. + * len [out] - The length of the data. + */ +void Curl_des_set_odd_parity(unsigned char *bytes, size_t len) +{ + size_t i; + + for(i = 0; i < len; i++) { + unsigned char b = bytes[i]; + + bool needs_parity = (((b >> 7) ^ (b >> 6) ^ (b >> 5) ^ + (b >> 4) ^ (b >> 3) ^ (b >> 2) ^ + (b >> 1)) & 0x01) == 0; + + if(needs_parity) + bytes[i] |= 0x01; + else + bytes[i] &= 0xfe; + } +} + +#endif /* USE_NTLM && !USE_OPENSSL */ diff --git a/dependencies/cmcurl/lib/curl_des.h b/dependencies/cmcurl/lib/curl_des.h new file mode 100644 index 0000000..129060f --- /dev/null +++ b/dependencies/cmcurl/lib/curl_des.h @@ -0,0 +1,34 @@ +#ifndef HEADER_CURL_DES_H +#define HEADER_CURL_DES_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2015, Steve Holme, . + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_NTLM) && !defined(USE_OPENSSL) + +/* Applies odd parity to the given byte array */ +void Curl_des_set_odd_parity(unsigned char *bytes, size_t length); + +#endif /* USE_NTLM && !USE_OPENSSL */ + +#endif /* HEADER_CURL_DES_H */ diff --git a/dependencies/cmcurl/lib/curl_endian.c b/dependencies/cmcurl/lib/curl_endian.c new file mode 100644 index 0000000..b7563b3 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_endian.c @@ -0,0 +1,124 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "curl_endian.h" + +/* + * Curl_read16_le() + * + * This function converts a 16-bit integer from the little endian format, as + * used in the incoming package to whatever endian format we're using + * natively. + * + * Parameters: + * + * buf [in] - A pointer to a 2 byte buffer. + * + * Returns the integer. + */ +unsigned short Curl_read16_le(const unsigned char *buf) +{ + return (unsigned short)(((unsigned short)buf[0]) | + ((unsigned short)buf[1] << 8)); +} + +/* + * Curl_read32_le() + * + * This function converts a 32-bit integer from the little endian format, as + * used in the incoming package to whatever endian format we're using + * natively. + * + * Parameters: + * + * buf [in] - A pointer to a 4 byte buffer. + * + * Returns the integer. + */ +unsigned int Curl_read32_le(const unsigned char *buf) +{ + return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) | + ((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24); +} + +/* + * Curl_read16_be() + * + * This function converts a 16-bit integer from the big endian format, as + * used in the incoming package to whatever endian format we're using + * natively. + * + * Parameters: + * + * buf [in] - A pointer to a 2 byte buffer. + * + * Returns the integer. + */ +unsigned short Curl_read16_be(const unsigned char *buf) +{ + return (unsigned short)(((unsigned short)buf[0] << 8) | + ((unsigned short)buf[1])); +} + +/* + * write32_le() + * + * This function converts a 32-bit integer from the native endian format, + * to little endian format ready for sending down the wire. + * + * Parameters: + * + * value [in] - The 32-bit integer value. + * buffer [in] - A pointer to the output buffer. + */ +static void write32_le(const int value, unsigned char *buffer) +{ + buffer[0] = (char)(value & 0x000000FF); + buffer[1] = (char)((value & 0x0000FF00) >> 8); + buffer[2] = (char)((value & 0x00FF0000) >> 16); + buffer[3] = (char)((value & 0xFF000000) >> 24); +} + +#if (CURL_SIZEOF_CURL_OFF_T > 4) +/* + * Curl_write64_le() + * + * This function converts a 64-bit integer from the native endian format, + * to little endian format ready for sending down the wire. + * + * Parameters: + * + * value [in] - The 64-bit integer value. + * buffer [in] - A pointer to the output buffer. + */ +#if defined(HAVE_LONGLONG) +void Curl_write64_le(const long long value, unsigned char *buffer) +#else +void Curl_write64_le(const __int64 value, unsigned char *buffer) +#endif +{ + write32_le((int)value, buffer); + write32_le((int)(value >> 32), buffer + 4); +} +#endif /* CURL_SIZEOF_CURL_OFF_T > 4 */ diff --git a/dependencies/cmcurl/lib/curl_endian.h b/dependencies/cmcurl/lib/curl_endian.h new file mode 100644 index 0000000..4f345a6 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_endian.h @@ -0,0 +1,46 @@ +#ifndef HEADER_CURL_ENDIAN_H +#define HEADER_CURL_ENDIAN_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* Converts a 16-bit integer from little endian */ +unsigned short Curl_read16_le(const unsigned char *buf); + +/* Converts a 32-bit integer from little endian */ +unsigned int Curl_read32_le(const unsigned char *buf); + +/* Converts a 16-bit integer from big endian */ +unsigned short Curl_read16_be(const unsigned char *buf); + +/* Converts a 32-bit integer to little endian */ +void Curl_write32_le(const int value, unsigned char *buffer); + +#if (CURL_SIZEOF_CURL_OFF_T > 4) +/* Converts a 64-bit integer to little endian */ +#if defined(HAVE_LONGLONG) +void Curl_write64_le(const long long value, unsigned char *buffer); +#else +void Curl_write64_le(const __int64 value, unsigned char *buffer); +#endif +#endif + +#endif /* HEADER_CURL_ENDIAN_H */ diff --git a/dependencies/cmcurl/lib/curl_fnmatch.c b/dependencies/cmcurl/lib/curl_fnmatch.c new file mode 100644 index 0000000..ab3e742 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_fnmatch.c @@ -0,0 +1,389 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#ifndef CURL_DISABLE_FTP +#include + +#include "curl_fnmatch.h" +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +#ifndef HAVE_FNMATCH + +#define CURLFNM_CHARSET_LEN (sizeof(char) * 256) +#define CURLFNM_CHSET_SIZE (CURLFNM_CHARSET_LEN + 15) + +#define CURLFNM_NEGATE CURLFNM_CHARSET_LEN + +#define CURLFNM_ALNUM (CURLFNM_CHARSET_LEN + 1) +#define CURLFNM_DIGIT (CURLFNM_CHARSET_LEN + 2) +#define CURLFNM_XDIGIT (CURLFNM_CHARSET_LEN + 3) +#define CURLFNM_ALPHA (CURLFNM_CHARSET_LEN + 4) +#define CURLFNM_PRINT (CURLFNM_CHARSET_LEN + 5) +#define CURLFNM_BLANK (CURLFNM_CHARSET_LEN + 6) +#define CURLFNM_LOWER (CURLFNM_CHARSET_LEN + 7) +#define CURLFNM_GRAPH (CURLFNM_CHARSET_LEN + 8) +#define CURLFNM_SPACE (CURLFNM_CHARSET_LEN + 9) +#define CURLFNM_UPPER (CURLFNM_CHARSET_LEN + 10) + +typedef enum { + CURLFNM_SCHS_DEFAULT = 0, + CURLFNM_SCHS_RIGHTBR, + CURLFNM_SCHS_RIGHTBRLEFTBR +} setcharset_state; + +typedef enum { + CURLFNM_PKW_INIT = 0, + CURLFNM_PKW_DDOT +} parsekey_state; + +typedef enum { + CCLASS_OTHER = 0, + CCLASS_DIGIT, + CCLASS_UPPER, + CCLASS_LOWER +} char_class; + +#define SETCHARSET_OK 1 +#define SETCHARSET_FAIL 0 + +static int parsekeyword(unsigned char **pattern, unsigned char *charset) +{ + parsekey_state state = CURLFNM_PKW_INIT; +#define KEYLEN 10 + char keyword[KEYLEN] = { 0 }; + int found = FALSE; + int i; + unsigned char *p = *pattern; + for(i = 0; !found; i++) { + char c = *p++; + if(i >= KEYLEN) + return SETCHARSET_FAIL; + switch(state) { + case CURLFNM_PKW_INIT: + if(ISLOWER(c)) + keyword[i] = c; + else if(c == ':') + state = CURLFNM_PKW_DDOT; + else + return SETCHARSET_FAIL; + break; + case CURLFNM_PKW_DDOT: + if(c == ']') + found = TRUE; + else + return SETCHARSET_FAIL; + } + } +#undef KEYLEN + + *pattern = p; /* move caller's pattern pointer */ + if(strcmp(keyword, "digit") == 0) + charset[CURLFNM_DIGIT] = 1; + else if(strcmp(keyword, "alnum") == 0) + charset[CURLFNM_ALNUM] = 1; + else if(strcmp(keyword, "alpha") == 0) + charset[CURLFNM_ALPHA] = 1; + else if(strcmp(keyword, "xdigit") == 0) + charset[CURLFNM_XDIGIT] = 1; + else if(strcmp(keyword, "print") == 0) + charset[CURLFNM_PRINT] = 1; + else if(strcmp(keyword, "graph") == 0) + charset[CURLFNM_GRAPH] = 1; + else if(strcmp(keyword, "space") == 0) + charset[CURLFNM_SPACE] = 1; + else if(strcmp(keyword, "blank") == 0) + charset[CURLFNM_BLANK] = 1; + else if(strcmp(keyword, "upper") == 0) + charset[CURLFNM_UPPER] = 1; + else if(strcmp(keyword, "lower") == 0) + charset[CURLFNM_LOWER] = 1; + else + return SETCHARSET_FAIL; + return SETCHARSET_OK; +} + +/* Return the character class. */ +static char_class charclass(unsigned char c) +{ + if(ISUPPER(c)) + return CCLASS_UPPER; + if(ISLOWER(c)) + return CCLASS_LOWER; + if(ISDIGIT(c)) + return CCLASS_DIGIT; + return CCLASS_OTHER; +} + +/* Include a character or a range in set. */ +static void setcharorrange(unsigned char **pp, unsigned char *charset) +{ + unsigned char *p = (*pp)++; + unsigned char c = *p++; + + charset[c] = 1; + if(ISALNUM(c) && *p++ == '-') { + char_class cc = charclass(c); + unsigned char endrange = *p++; + + if(endrange == '\\') + endrange = *p++; + if(endrange >= c && charclass(endrange) == cc) { + while(c++ != endrange) + if(charclass(c) == cc) /* Chars in class may be not consecutive. */ + charset[c] = 1; + *pp = p; + } + } +} + +/* returns 1 (true) if pattern is OK, 0 if is bad ("p" is pattern pointer) */ +static int setcharset(unsigned char **p, unsigned char *charset) +{ + setcharset_state state = CURLFNM_SCHS_DEFAULT; + bool something_found = FALSE; + unsigned char c; + + memset(charset, 0, CURLFNM_CHSET_SIZE); + for(;;) { + c = **p; + if(!c) + return SETCHARSET_FAIL; + + switch(state) { + case CURLFNM_SCHS_DEFAULT: + if(c == ']') { + if(something_found) + return SETCHARSET_OK; + something_found = TRUE; + state = CURLFNM_SCHS_RIGHTBR; + charset[c] = 1; + (*p)++; + } + else if(c == '[') { + unsigned char *pp = *p + 1; + + if(*pp++ == ':' && parsekeyword(&pp, charset)) + *p = pp; + else { + charset[c] = 1; + (*p)++; + } + something_found = TRUE; + } + else if(c == '^' || c == '!') { + if(!something_found) { + if(charset[CURLFNM_NEGATE]) { + charset[c] = 1; + something_found = TRUE; + } + else + charset[CURLFNM_NEGATE] = 1; /* negate charset */ + } + else + charset[c] = 1; + (*p)++; + } + else if(c == '\\') { + c = *(++(*p)); + if(c) + setcharorrange(p, charset); + else + charset['\\'] = 1; + something_found = TRUE; + } + else { + setcharorrange(p, charset); + something_found = TRUE; + } + break; + case CURLFNM_SCHS_RIGHTBR: + if(c == '[') { + state = CURLFNM_SCHS_RIGHTBRLEFTBR; + charset[c] = 1; + (*p)++; + } + else if(c == ']') { + return SETCHARSET_OK; + } + else if(ISPRINT(c)) { + charset[c] = 1; + (*p)++; + state = CURLFNM_SCHS_DEFAULT; + } + else + /* used 'goto fail' instead of 'return SETCHARSET_FAIL' to avoid a + * nonsense warning 'statement not reached' at end of the fnc when + * compiling on Solaris */ + goto fail; + break; + case CURLFNM_SCHS_RIGHTBRLEFTBR: + if(c == ']') + return SETCHARSET_OK; + state = CURLFNM_SCHS_DEFAULT; + charset[c] = 1; + (*p)++; + break; + } + } +fail: + return SETCHARSET_FAIL; +} + +static int loop(const unsigned char *pattern, const unsigned char *string, + int maxstars) +{ + unsigned char *p = (unsigned char *)pattern; + unsigned char *s = (unsigned char *)string; + unsigned char charset[CURLFNM_CHSET_SIZE] = { 0 }; + + for(;;) { + unsigned char *pp; + + switch(*p) { + case '*': + if(!maxstars) + return CURL_FNMATCH_NOMATCH; + /* Regroup consecutive stars and question marks. This can be done because + '*?*?*' can be expressed as '??*'. */ + for(;;) { + if(*++p == '\0') + return CURL_FNMATCH_MATCH; + if(*p == '?') { + if(!*s++) + return CURL_FNMATCH_NOMATCH; + } + else if(*p != '*') + break; + } + /* Skip string characters until we find a match with pattern suffix. */ + for(maxstars--; *s; s++) { + if(loop(p, s, maxstars) == CURL_FNMATCH_MATCH) + return CURL_FNMATCH_MATCH; + } + return CURL_FNMATCH_NOMATCH; + case '?': + if(!*s) + return CURL_FNMATCH_NOMATCH; + s++; + p++; + break; + case '\0': + return *s? CURL_FNMATCH_NOMATCH: CURL_FNMATCH_MATCH; + case '\\': + if(p[1]) + p++; + if(*s++ != *p++) + return CURL_FNMATCH_NOMATCH; + break; + case '[': + pp = p + 1; /* Copy in case of syntax error in set. */ + if(setcharset(&pp, charset)) { + int found = FALSE; + if(!*s) + return CURL_FNMATCH_NOMATCH; + if(charset[(unsigned int)*s]) + found = TRUE; + else if(charset[CURLFNM_ALNUM]) + found = ISALNUM(*s); + else if(charset[CURLFNM_ALPHA]) + found = ISALPHA(*s); + else if(charset[CURLFNM_DIGIT]) + found = ISDIGIT(*s); + else if(charset[CURLFNM_XDIGIT]) + found = ISXDIGIT(*s); + else if(charset[CURLFNM_PRINT]) + found = ISPRINT(*s); + else if(charset[CURLFNM_SPACE]) + found = ISSPACE(*s); + else if(charset[CURLFNM_UPPER]) + found = ISUPPER(*s); + else if(charset[CURLFNM_LOWER]) + found = ISLOWER(*s); + else if(charset[CURLFNM_BLANK]) + found = ISBLANK(*s); + else if(charset[CURLFNM_GRAPH]) + found = ISGRAPH(*s); + + if(charset[CURLFNM_NEGATE]) + found = !found; + + if(!found) + return CURL_FNMATCH_NOMATCH; + p = pp + 1; + s++; + break; + } + /* Syntax error in set; mismatch! */ + return CURL_FNMATCH_NOMATCH; + + default: + if(*p++ != *s++) + return CURL_FNMATCH_NOMATCH; + break; + } + } +} + +/* + * @unittest: 1307 + */ +int Curl_fnmatch(void *ptr, const char *pattern, const char *string) +{ + (void)ptr; /* the argument is specified by the curl_fnmatch_callback + prototype, but not used by Curl_fnmatch() */ + if(!pattern || !string) { + return CURL_FNMATCH_FAIL; + } + return loop((unsigned char *)pattern, (unsigned char *)string, 2); +} +#else +#include +/* + * @unittest: 1307 + */ +int Curl_fnmatch(void *ptr, const char *pattern, const char *string) +{ + int rc; + (void)ptr; /* the argument is specified by the curl_fnmatch_callback + prototype, but not used by Curl_fnmatch() */ + if(!pattern || !string) { + return CURL_FNMATCH_FAIL; + } + rc = fnmatch(pattern, string, 0); + switch(rc) { + case 0: + return CURL_FNMATCH_MATCH; + case FNM_NOMATCH: + return CURL_FNMATCH_NOMATCH; + default: + return CURL_FNMATCH_FAIL; + } + /* not reached */ +} + +#endif + +#endif /* if FTP is disabled */ diff --git a/dependencies/cmcurl/lib/curl_fnmatch.h b/dependencies/cmcurl/lib/curl_fnmatch.h new file mode 100644 index 0000000..69ffe39 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_fnmatch.h @@ -0,0 +1,44 @@ +#ifndef HEADER_CURL_FNMATCH_H +#define HEADER_CURL_FNMATCH_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#define CURL_FNMATCH_MATCH 0 +#define CURL_FNMATCH_NOMATCH 1 +#define CURL_FNMATCH_FAIL 2 + +/* default pattern matching function + * ================================= + * Implemented with recursive backtracking, if you want to use Curl_fnmatch, + * please note that there is not implemented UTF/UNICODE support. + * + * Implemented features: + * '?' notation, does not match UTF characters + * '*' can also work with UTF string + * [a-zA-Z0-9] enumeration support + * + * keywords: alnum, digit, xdigit, alpha, print, blank, lower, graph, space + * and upper (use as "[[:alnum:]]") + */ +int Curl_fnmatch(void *ptr, const char *pattern, const char *string); + +#endif /* HEADER_CURL_FNMATCH_H */ diff --git a/dependencies/cmcurl/lib/curl_get_line.c b/dependencies/cmcurl/lib/curl_get_line.c new file mode 100644 index 0000000..c419485 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_get_line.c @@ -0,0 +1,55 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "curl_get_line.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * get_line() makes sure to only return complete whole lines that fit in 'len' + * bytes and end with a newline. + */ +char *Curl_get_line(char *buf, int len, FILE *input) +{ + bool partial = FALSE; + while(1) { + char *b = fgets(buf, len, input); + if(b) { + size_t rlen = strlen(b); + if(rlen && (b[rlen-1] == '\n')) { + if(partial) { + partial = FALSE; + continue; + } + return b; + } + /* read a partial, discard the next piece that ends with newline */ + partial = TRUE; + } + else + break; + } + return NULL; +} diff --git a/dependencies/cmcurl/lib/curl_get_line.h b/dependencies/cmcurl/lib/curl_get_line.h new file mode 100644 index 0000000..532ab08 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_get_line.h @@ -0,0 +1,29 @@ +#ifndef HEADER_CURL_GET_LINE_H +#define HEADER_CURL_GET_LINE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* get_line() makes sure to only return complete whole lines that fit in 'len' + * bytes and end with a newline. */ +char *Curl_get_line(char *buf, int len, FILE *input); + +#endif /* HEADER_CURL_GET_LINE_H */ diff --git a/dependencies/cmcurl/lib/curl_gethostname.c b/dependencies/cmcurl/lib/curl_gethostname.c new file mode 100644 index 0000000..8337c72 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_gethostname.c @@ -0,0 +1,100 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "curl_gethostname.h" + +/* + * Curl_gethostname() is a wrapper around gethostname() which allows + * overriding the host name that the function would normally return. + * This capability is used by the test suite to verify exact matching + * of NTLM authentication, which exercises libcurl's MD4 and DES code + * as well as by the SMTP module when a hostname is not provided. + * + * For libcurl debug enabled builds host name overriding takes place + * when environment variable CURL_GETHOSTNAME is set, using the value + * held by the variable to override returned host name. + * + * Note: The function always returns the un-qualified hostname rather + * than being provider dependent. + * + * For libcurl shared library release builds the test suite preloads + * another shared library named libhostname using the LD_PRELOAD + * mechanism which intercepts, and might override, the gethostname() + * function call. In this case a given platform must support the + * LD_PRELOAD mechanism and additionally have environment variable + * CURL_GETHOSTNAME set in order to override the returned host name. + * + * For libcurl static library release builds no overriding takes place. + */ + +int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen) +{ +#ifndef HAVE_GETHOSTNAME + + /* Allow compilation and return failure when unavailable */ + (void) name; + (void) namelen; + return -1; + +#else + int err; + char *dot; + +#ifdef DEBUGBUILD + + /* Override host name when environment variable CURL_GETHOSTNAME is set */ + const char *force_hostname = getenv("CURL_GETHOSTNAME"); + if(force_hostname) { + strncpy(name, force_hostname, namelen); + err = 0; + } + else { + name[0] = '\0'; + err = gethostname(name, namelen); + } + +#else /* DEBUGBUILD */ + + /* The call to system's gethostname() might get intercepted by the + libhostname library when libcurl is built as a non-debug shared + library when running the test suite. */ + name[0] = '\0'; + err = gethostname(name, namelen); + +#endif + + name[namelen - 1] = '\0'; + + if(err) + return err; + + /* Truncate domain, leave only machine name */ + dot = strchr(name, '.'); + if(dot) + *dot = '\0'; + + return 0; +#endif + +} diff --git a/dependencies/cmcurl/lib/curl_gethostname.h b/dependencies/cmcurl/lib/curl_gethostname.h new file mode 100644 index 0000000..07517c5 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_gethostname.h @@ -0,0 +1,31 @@ +#ifndef HEADER_CURL_GETHOSTNAME_H +#define HEADER_CURL_GETHOSTNAME_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* Hostname buffer size */ +#define HOSTNAME_MAX 1024 + +/* This returns the local machine's un-qualified hostname */ +int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen); + +#endif /* HEADER_CURL_GETHOSTNAME_H */ diff --git a/dependencies/cmcurl/lib/curl_gssapi.c b/dependencies/cmcurl/lib/curl_gssapi.c new file mode 100644 index 0000000..d854ab0 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_gssapi.c @@ -0,0 +1,136 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2011 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_GSSAPI + +#include "curl_gssapi.h" +#include "sendf.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +static char spnego_oid_bytes[] = "\x2b\x06\x01\x05\x05\x02"; +gss_OID_desc Curl_spnego_mech_oid = { 6, &spnego_oid_bytes }; +static char krb5_oid_bytes[] = "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"; +gss_OID_desc Curl_krb5_mech_oid = { 9, &krb5_oid_bytes }; + +OM_uint32 Curl_gss_init_sec_context( + struct Curl_easy *data, + OM_uint32 *minor_status, + gss_ctx_id_t *context, + gss_name_t target_name, + gss_OID mech_type, + gss_channel_bindings_t input_chan_bindings, + gss_buffer_t input_token, + gss_buffer_t output_token, + const bool mutual_auth, + OM_uint32 *ret_flags) +{ + OM_uint32 req_flags = GSS_C_REPLAY_FLAG; + + if(mutual_auth) + req_flags |= GSS_C_MUTUAL_FLAG; + + if(data->set.gssapi_delegation & CURLGSSAPI_DELEGATION_POLICY_FLAG) { +#ifdef GSS_C_DELEG_POLICY_FLAG + req_flags |= GSS_C_DELEG_POLICY_FLAG; +#else + infof(data, "warning: support for CURLGSSAPI_DELEGATION_POLICY_FLAG not " + "compiled in\n"); +#endif + } + + if(data->set.gssapi_delegation & CURLGSSAPI_DELEGATION_FLAG) + req_flags |= GSS_C_DELEG_FLAG; + + return gss_init_sec_context(minor_status, + GSS_C_NO_CREDENTIAL, /* cred_handle */ + context, + target_name, + mech_type, + req_flags, + 0, /* time_req */ + input_chan_bindings, + input_token, + NULL, /* actual_mech_type */ + output_token, + ret_flags, + NULL /* time_rec */); +} + +#define GSS_LOG_BUFFER_LEN 1024 +static size_t display_gss_error(OM_uint32 status, int type, + char *buf, size_t len) { + OM_uint32 maj_stat; + OM_uint32 min_stat; + OM_uint32 msg_ctx = 0; + gss_buffer_desc status_string; + + do { + maj_stat = gss_display_status(&min_stat, + status, + type, + GSS_C_NO_OID, + &msg_ctx, + &status_string); + if(GSS_LOG_BUFFER_LEN > len + status_string.length + 3) { + len += msnprintf(buf + len, GSS_LOG_BUFFER_LEN - len, + "%.*s. ", (int)status_string.length, + (char *)status_string.value); + } + gss_release_buffer(&min_stat, &status_string); + } while(!GSS_ERROR(maj_stat) && msg_ctx != 0); + + return len; +} + +/* + * Curl_gss_log_error() + * + * This is used to log a GSS-API error status. + * + * Parameters: + * + * data [in] - The session handle. + * prefix [in] - The prefix of the log message. + * major [in] - The major status code. + * minor [in] - The minor status code. + */ +void Curl_gss_log_error(struct Curl_easy *data, const char *prefix, + OM_uint32 major, OM_uint32 minor) +{ + char buf[GSS_LOG_BUFFER_LEN]; + size_t len = 0; + + if(major != GSS_S_FAILURE) + len = display_gss_error(major, GSS_C_GSS_CODE, buf, len); + + display_gss_error(minor, GSS_C_MECH_CODE, buf, len); + + infof(data, "%s%s\n", prefix, buf); +} + +#endif /* HAVE_GSSAPI */ diff --git a/dependencies/cmcurl/lib/curl_gssapi.h b/dependencies/cmcurl/lib/curl_gssapi.h new file mode 100644 index 0000000..88f68db --- /dev/null +++ b/dependencies/cmcurl/lib/curl_gssapi.h @@ -0,0 +1,61 @@ +#ifndef HEADER_CURL_GSSAPI_H +#define HEADER_CURL_GSSAPI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2011 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include "urldata.h" + +#ifdef HAVE_GSSAPI +extern gss_OID_desc Curl_spnego_mech_oid; +extern gss_OID_desc Curl_krb5_mech_oid; + +/* Common method for using GSS-API */ +OM_uint32 Curl_gss_init_sec_context( + struct Curl_easy *data, + OM_uint32 *minor_status, + gss_ctx_id_t *context, + gss_name_t target_name, + gss_OID mech_type, + gss_channel_bindings_t input_chan_bindings, + gss_buffer_t input_token, + gss_buffer_t output_token, + const bool mutual_auth, + OM_uint32 *ret_flags); + +/* Helper to log a GSS-API error status */ +void Curl_gss_log_error(struct Curl_easy *data, const char *prefix, + OM_uint32 major, OM_uint32 minor); + +/* Provide some definitions missing in old headers */ +#ifdef HAVE_OLD_GSSMIT +#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name +#define NCOMPAT 1 +#endif + +/* Define our privacy and integrity protection values */ +#define GSSAUTH_P_NONE 1 +#define GSSAUTH_P_INTEGRITY 2 +#define GSSAUTH_P_PRIVACY 4 + +#endif /* HAVE_GSSAPI */ +#endif /* HEADER_CURL_GSSAPI_H */ diff --git a/dependencies/cmcurl/lib/curl_hmac.h b/dependencies/cmcurl/lib/curl_hmac.h new file mode 100644 index 0000000..756dc9e --- /dev/null +++ b/dependencies/cmcurl/lib/curl_hmac.h @@ -0,0 +1,67 @@ +#ifndef HEADER_CURL_HMAC_H +#define HEADER_CURL_HMAC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifndef CURL_DISABLE_CRYPTO_AUTH + +typedef void (* HMAC_hinit_func)(void *context); +typedef void (* HMAC_hupdate_func)(void *context, + const unsigned char *data, + unsigned int len); +typedef void (* HMAC_hfinal_func)(unsigned char *result, void *context); + + +/* Per-hash function HMAC parameters. */ + +typedef struct { + HMAC_hinit_func hmac_hinit; /* Initialize context procedure. */ + HMAC_hupdate_func hmac_hupdate; /* Update context with data. */ + HMAC_hfinal_func hmac_hfinal; /* Get final result procedure. */ + unsigned int hmac_ctxtsize; /* Context structure size. */ + unsigned int hmac_maxkeylen; /* Maximum key length (bytes). */ + unsigned int hmac_resultlen; /* Result length (bytes). */ +} HMAC_params; + + +/* HMAC computation context. */ + +typedef struct { + const HMAC_params *hmac_hash; /* Hash function definition. */ + void *hmac_hashctxt1; /* Hash function context 1. */ + void *hmac_hashctxt2; /* Hash function context 2. */ +} HMAC_context; + + +/* Prototypes. */ + +HMAC_context * Curl_HMAC_init(const HMAC_params *hashparams, + const unsigned char *key, + unsigned int keylen); +int Curl_HMAC_update(HMAC_context *context, + const unsigned char *data, + unsigned int len); +int Curl_HMAC_final(HMAC_context *context, unsigned char *result); + +#endif + +#endif /* HEADER_CURL_HMAC_H */ diff --git a/dependencies/cmcurl/lib/curl_ldap.h b/dependencies/cmcurl/lib/curl_ldap.h new file mode 100644 index 0000000..94c0029 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_ldap.h @@ -0,0 +1,34 @@ +#ifndef HEADER_CURL_LDAP_H +#define HEADER_CURL_LDAP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifndef CURL_DISABLE_LDAP +extern const struct Curl_handler Curl_handler_ldap; + +#if !defined(CURL_DISABLE_LDAPS) && \ + ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ + (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) +extern const struct Curl_handler Curl_handler_ldaps; +#endif + +#endif +#endif /* HEADER_CURL_LDAP_H */ diff --git a/dependencies/cmcurl/lib/curl_md4.h b/dependencies/cmcurl/lib/curl_md4.h new file mode 100644 index 0000000..392203f --- /dev/null +++ b/dependencies/cmcurl/lib/curl_md4.h @@ -0,0 +1,37 @@ +#ifndef HEADER_CURL_MD4_H +#define HEADER_CURL_MD4_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_NSS) || defined(USE_OS400CRYPTO) || \ + (defined(USE_OPENSSL) && defined(OPENSSL_NO_MD4)) || \ + (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) + +void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len); + +#endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) || + (defined(USE_OPENSSL) && defined(OPENSSL_NO_MD4)) || + (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) */ + +#endif /* HEADER_CURL_MD4_H */ diff --git a/dependencies/cmcurl/lib/curl_md5.h b/dependencies/cmcurl/lib/curl_md5.h new file mode 100644 index 0000000..aaf25f6 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_md5.h @@ -0,0 +1,63 @@ +#ifndef HEADER_CURL_MD5_H +#define HEADER_CURL_MD5_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifndef CURL_DISABLE_CRYPTO_AUTH +#include "curl_hmac.h" + +#define MD5_DIGEST_LEN 16 + +typedef void (* Curl_MD5_init_func)(void *context); +typedef void (* Curl_MD5_update_func)(void *context, + const unsigned char *data, + unsigned int len); +typedef void (* Curl_MD5_final_func)(unsigned char *result, void *context); + +typedef struct { + Curl_MD5_init_func md5_init_func; /* Initialize context procedure */ + Curl_MD5_update_func md5_update_func; /* Update context with data */ + Curl_MD5_final_func md5_final_func; /* Get final result procedure */ + unsigned int md5_ctxtsize; /* Context structure size */ + unsigned int md5_resultlen; /* Result length (bytes) */ +} MD5_params; + +typedef struct { + const MD5_params *md5_hash; /* Hash function definition */ + void *md5_hashctx; /* Hash function context */ +} MD5_context; + +extern const MD5_params Curl_DIGEST_MD5[1]; +extern const HMAC_params Curl_HMAC_MD5[1]; + +void Curl_md5it(unsigned char *output, + const unsigned char *input); + +MD5_context * Curl_MD5_init(const MD5_params *md5params); +CURLcode Curl_MD5_update(MD5_context *context, + const unsigned char *data, + unsigned int len); +CURLcode Curl_MD5_final(MD5_context *context, unsigned char *result); + +#endif + +#endif /* HEADER_CURL_MD5_H */ diff --git a/dependencies/cmcurl/lib/curl_memory.h b/dependencies/cmcurl/lib/curl_memory.h new file mode 100644 index 0000000..ce38a08 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_memory.h @@ -0,0 +1,156 @@ +#ifndef HEADER_CURL_MEMORY_H +#define HEADER_CURL_MEMORY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Nasty internal details ahead... + * + * File curl_memory.h must be included by _all_ *.c source files + * that use memory related functions strdup, malloc, calloc, realloc + * or free, and given source file is used to build libcurl library. + * It should be included immediately before memdebug.h as the last files + * included to avoid undesired interaction with other memory function + * headers in dependent libraries. + * + * There is nearly no exception to above rule. All libcurl source + * files in 'lib' subdirectory as well as those living deep inside + * 'packages' subdirectories and linked together in order to build + * libcurl library shall follow it. + * + * File lib/strdup.c is an exception, given that it provides a strdup + * clone implementation while using malloc. Extra care needed inside + * this one. + * + * The need for curl_memory.h inclusion is due to libcurl's feature + * of allowing library user to provide memory replacement functions, + * memory callbacks, at runtime with curl_global_init_mem() + * + * Any *.c source file used to build libcurl library that does not + * include curl_memory.h and uses any memory function of the five + * mentioned above will compile without any indication, but it will + * trigger weird memory related issues at runtime. + * + * OTOH some source files from 'lib' subdirectory may additionally be + * used directly as source code when using some curlx_ functions by + * third party programs that don't even use libcurl at all. When using + * these source files in this way it is necessary these are compiled + * with CURLX_NO_MEMORY_CALLBACKS defined, in order to ensure that no + * attempt of calling libcurl's memory callbacks is done from code + * which can not use this machinery. + * + * Notice that libcurl's 'memory tracking' system works chaining into + * the memory callback machinery. This implies that when compiling + * 'lib' source files with CURLX_NO_MEMORY_CALLBACKS defined this file + * disengages usage of libcurl's 'memory tracking' system, defining + * MEMDEBUG_NODEFINES and overriding CURLDEBUG purpose. + * + * CURLX_NO_MEMORY_CALLBACKS takes precedence over CURLDEBUG. This is + * done in order to allow building a 'memory tracking' enabled libcurl + * and at the same time allow building programs which do not use it. + * + * Programs and libraries in 'tests' subdirectories have specific + * purposes and needs, and as such each one will use whatever fits + * best, depending additionally whether it links with libcurl or not. + * + * Caveat emptor. Proper curlx_* separation is a work in progress + * the same as CURLX_NO_MEMORY_CALLBACKS usage, some adjustments may + * still be required. IOW don't use them yet, there are sharp edges. + */ + +#ifdef HEADER_CURL_MEMDEBUG_H +#error "Header memdebug.h shall not be included before curl_memory.h" +#endif + +#ifndef CURLX_NO_MEMORY_CALLBACKS + +#ifndef CURL_DID_MEMORY_FUNC_TYPEDEFS /* only if not already done */ +/* + * The following memory function replacement typedef's are COPIED from + * curl/curl.h and MUST match the originals. We copy them to avoid having to + * include curl/curl.h here. We avoid that include since it includes stdio.h + * and other headers that may get messed up with defines done here. + */ +typedef void *(*curl_malloc_callback)(size_t size); +typedef void (*curl_free_callback)(void *ptr); +typedef void *(*curl_realloc_callback)(void *ptr, size_t size); +typedef char *(*curl_strdup_callback)(const char *str); +typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size); +#define CURL_DID_MEMORY_FUNC_TYPEDEFS +#endif + +extern curl_malloc_callback Curl_cmalloc; +extern curl_free_callback Curl_cfree; +extern curl_realloc_callback Curl_crealloc; +extern curl_strdup_callback Curl_cstrdup; +extern curl_calloc_callback Curl_ccalloc; +#if defined(WIN32) && defined(UNICODE) +extern curl_wcsdup_callback Curl_cwcsdup; +#endif + +#ifndef CURLDEBUG + +/* + * libcurl's 'memory tracking' system defines strdup, malloc, calloc, + * realloc and free, along with others, in memdebug.h in a different + * way although still using memory callbacks forward declared above. + * When using the 'memory tracking' system (CURLDEBUG defined) we do + * not define here the five memory functions given that definitions + * from memdebug.h are the ones that shall be used. + */ + +#undef strdup +#define strdup(ptr) Curl_cstrdup(ptr) +#undef malloc +#define malloc(size) Curl_cmalloc(size) +#undef calloc +#define calloc(nbelem,size) Curl_ccalloc(nbelem, size) +#undef realloc +#define realloc(ptr,size) Curl_crealloc(ptr, size) +#undef free +#define free(ptr) Curl_cfree(ptr) + +#ifdef WIN32 +# ifdef UNICODE +# undef wcsdup +# define wcsdup(ptr) Curl_cwcsdup(ptr) +# undef _wcsdup +# define _wcsdup(ptr) Curl_cwcsdup(ptr) +# undef _tcsdup +# define _tcsdup(ptr) Curl_cwcsdup(ptr) +# else +# undef _tcsdup +# define _tcsdup(ptr) Curl_cstrdup(ptr) +# endif +#endif + +#endif /* CURLDEBUG */ + +#else /* CURLX_NO_MEMORY_CALLBACKS */ + +#ifndef MEMDEBUG_NODEFINES +#define MEMDEBUG_NODEFINES +#endif + +#endif /* CURLX_NO_MEMORY_CALLBACKS */ + +#endif /* HEADER_CURL_MEMORY_H */ diff --git a/dependencies/cmcurl/lib/curl_memrchr.c b/dependencies/cmcurl/lib/curl_memrchr.c new file mode 100644 index 0000000..eeb3044 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_memrchr.c @@ -0,0 +1,62 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "curl_memrchr.h" +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +#ifndef HAVE_MEMRCHR + +/* + * Curl_memrchr() + * + * Our memrchr() function clone for systems which lack this function. The + * memrchr() function is like the memchr() function, except that it searches + * backwards from the end of the n bytes pointed to by s instead of forward + * from the beginning. + */ + +void * +Curl_memrchr(const void *s, int c, size_t n) +{ + if(n > 0) { + const unsigned char *p = s; + const unsigned char *q = s; + + p += n - 1; + + while(p >= q) { + if(*p == (unsigned char)c) + return (void *)p; + p--; + } + } + return NULL; +} + +#endif /* HAVE_MEMRCHR */ diff --git a/dependencies/cmcurl/lib/curl_memrchr.h b/dependencies/cmcurl/lib/curl_memrchr.h new file mode 100644 index 0000000..747509c --- /dev/null +++ b/dependencies/cmcurl/lib/curl_memrchr.h @@ -0,0 +1,44 @@ +#ifndef HEADER_CURL_MEMRCHR_H +#define HEADER_CURL_MEMRCHR_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_MEMRCHR + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#else /* HAVE_MEMRCHR */ + +void *Curl_memrchr(const void *s, int c, size_t n); + +#define memrchr(x,y,z) Curl_memrchr((x),(y),(z)) + +#endif /* HAVE_MEMRCHR */ + +#endif /* HEADER_CURL_MEMRCHR_H */ diff --git a/dependencies/cmcurl/lib/curl_multibyte.c b/dependencies/cmcurl/lib/curl_multibyte.c new file mode 100644 index 0000000..e48334f --- /dev/null +++ b/dependencies/cmcurl/lib/curl_multibyte.c @@ -0,0 +1,84 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#if defined(USE_WIN32_IDN) || ((defined(USE_WINDOWS_SSPI) || \ + defined(USE_WIN32_LDAP)) && defined(UNICODE)) + + /* + * MultiByte conversions using Windows kernel32 library. + */ + +#include "curl_multibyte.h" +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8) +{ + wchar_t *str_w = NULL; + + if(str_utf8) { + int str_w_len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, + str_utf8, -1, NULL, 0); + if(str_w_len > 0) { + str_w = malloc(str_w_len * sizeof(wchar_t)); + if(str_w) { + if(MultiByteToWideChar(CP_UTF8, 0, str_utf8, -1, str_w, + str_w_len) == 0) { + free(str_w); + return NULL; + } + } + } + } + + return str_w; +} + +char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w) +{ + char *str_utf8 = NULL; + + if(str_w) { + int bytes = WideCharToMultiByte(CP_UTF8, 0, str_w, -1, + NULL, 0, NULL, NULL); + if(bytes > 0) { + str_utf8 = malloc(bytes); + if(str_utf8) { + if(WideCharToMultiByte(CP_UTF8, 0, str_w, -1, str_utf8, bytes, + NULL, NULL) == 0) { + free(str_utf8); + return NULL; + } + } + } + } + + return str_utf8; +} + +#endif /* USE_WIN32_IDN || ((USE_WINDOWS_SSPI || USE_WIN32_LDAP) && UNICODE) */ diff --git a/dependencies/cmcurl/lib/curl_multibyte.h b/dependencies/cmcurl/lib/curl_multibyte.h new file mode 100644 index 0000000..615f5c0 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_multibyte.h @@ -0,0 +1,92 @@ +#ifndef HEADER_CURL_MULTIBYTE_H +#define HEADER_CURL_MULTIBYTE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if defined(USE_WIN32_IDN) || ((defined(USE_WINDOWS_SSPI) || \ + defined(USE_WIN32_LDAP)) && defined(UNICODE)) + + /* + * MultiByte conversions using Windows kernel32 library. + */ + +wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8); +char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w); + +#endif /* USE_WIN32_IDN || ((USE_WINDOWS_SSPI || USE_WIN32_LDAP) && UNICODE) */ + + +#if defined(USE_WIN32_IDN) || defined(USE_WINDOWS_SSPI) || \ + defined(USE_WIN32_LDAP) + +/* + * Macros Curl_convert_UTF8_to_tchar(), Curl_convert_tchar_to_UTF8() + * and Curl_unicodefree() main purpose is to minimize the number of + * preprocessor conditional directives needed by code using these + * to differentiate UNICODE from non-UNICODE builds. + * + * When building with UNICODE defined, this two macros + * Curl_convert_UTF8_to_tchar() and Curl_convert_tchar_to_UTF8() + * return a pointer to a newly allocated memory area holding result. + * When the result is no longer needed, allocated memory is intended + * to be free'ed with Curl_unicodefree(). + * + * When building without UNICODE defined, this macros + * Curl_convert_UTF8_to_tchar() and Curl_convert_tchar_to_UTF8() + * return the pointer received as argument. Curl_unicodefree() does + * no actual free'ing of this pointer it is simply set to NULL. + */ + +#ifdef UNICODE + +#define Curl_convert_UTF8_to_tchar(ptr) Curl_convert_UTF8_to_wchar((ptr)) +#define Curl_convert_tchar_to_UTF8(ptr) Curl_convert_wchar_to_UTF8((ptr)) +#define Curl_unicodefree(ptr) \ + do {if((ptr)) {free((ptr)); (ptr) = NULL;}} WHILE_FALSE + +typedef union { + unsigned short *tchar_ptr; + const unsigned short *const_tchar_ptr; + unsigned short *tbyte_ptr; + const unsigned short *const_tbyte_ptr; +} xcharp_u; + +#else + +#define Curl_convert_UTF8_to_tchar(ptr) (ptr) +#define Curl_convert_tchar_to_UTF8(ptr) (ptr) +#define Curl_unicodefree(ptr) \ + do {(ptr) = NULL;} WHILE_FALSE + +typedef union { + char *tchar_ptr; + const char *const_tchar_ptr; + unsigned char *tbyte_ptr; + const unsigned char *const_tbyte_ptr; +} xcharp_u; + +#endif /* UNICODE */ + +#endif /* USE_WIN32_IDN || USE_WINDOWS_SSPI || USE_WIN32_LDAP */ + +#endif /* HEADER_CURL_MULTIBYTE_H */ diff --git a/dependencies/cmcurl/lib/curl_ntlm_core.c b/dependencies/cmcurl/lib/curl_ntlm_core.c new file mode 100644 index 0000000..b6df38f --- /dev/null +++ b/dependencies/cmcurl/lib/curl_ntlm_core.c @@ -0,0 +1,824 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_NTLM) + +/* + * NTLM details: + * + * https://davenport.sourceforge.io/ntlm.html + * https://www.innovation.ch/java/ntlm.html + */ + +/* Please keep the SSL backend-specific #if branches in this order: + + 1. USE_OPENSSL + 2. USE_GNUTLS_NETTLE + 3. USE_GNUTLS + 4. USE_NSS + 5. USE_MBEDTLS + 6. USE_SECTRANSP + 7. USE_OS400CRYPTO + 8. USE_WIN32_CRYPTO + + This ensures that: + - the same SSL branch gets activated throughout this source + file even if multiple backends are enabled at the same time. + - OpenSSL and NSS have higher priority than Windows Crypt, due + to issues with the latter supporting NTLM2Session responses + in NTLM type-3 messages. + */ + +#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO) + +#ifdef USE_OPENSSL + +# include +# ifndef OPENSSL_NO_MD4 +# include +# else +# include "curl_md4.h" +# endif +# include +# include +# include +# if (OPENSSL_VERSION_NUMBER < 0x00907001L) +# define DES_key_schedule des_key_schedule +# define DES_cblock des_cblock +# define DES_set_odd_parity des_set_odd_parity +# define DES_set_key des_set_key +# define DES_ecb_encrypt des_ecb_encrypt +# define DESKEY(x) x +# define DESKEYARG(x) x +# else +# define DESKEYARG(x) *x +# define DESKEY(x) &x +# endif + +#elif defined(USE_GNUTLS_NETTLE) + +# include +# include + +#elif defined(USE_GNUTLS) + +# include +# define MD5_DIGEST_LENGTH 16 +# define MD4_DIGEST_LENGTH 16 + +#elif defined(USE_NSS) + +# include +# include +# include +# include "curl_md4.h" +# define MD5_DIGEST_LENGTH MD5_LENGTH + +#elif defined(USE_MBEDTLS) + +# include +# include +# if !defined(MBEDTLS_MD4_C) +# include "curl_md4.h" +# endif + +#elif defined(USE_SECTRANSP) + +# include +# include + +#elif defined(USE_OS400CRYPTO) +# include "cipher.mih" /* mih/cipher */ +# include "curl_md4.h" +#elif defined(USE_WIN32_CRYPTO) +# include +#else +# error "Can't compile NTLM support without a crypto library." +#endif + +#include "urldata.h" +#include "non-ascii.h" +#include "strcase.h" +#include "curl_ntlm_core.h" +#include "curl_md5.h" +#include "curl_hmac.h" +#include "warnless.h" +#include "curl_endian.h" +#include "curl_des.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#define NTLM_HMAC_MD5_LEN (16) +#define NTLMv2_BLOB_SIGNATURE "\x01\x01\x00\x00" +#define NTLMv2_BLOB_LEN (44 -16 + ntlm->target_info_len + 4) + +/* +* Turns a 56-bit key into being 64-bit wide. +*/ +static void extend_key_56_to_64(const unsigned char *key_56, char *key) +{ + key[0] = key_56[0]; + key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1)); + key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2)); + key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3)); + key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4)); + key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5)); + key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6)); + key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF); +} + +#ifdef USE_OPENSSL +/* + * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The + * key schedule ks is also set. + */ +static void setup_des_key(const unsigned char *key_56, + DES_key_schedule DESKEYARG(ks)) +{ + DES_cblock key; + + /* Expand the 56-bit key to 64-bits */ + extend_key_56_to_64(key_56, (char *) &key); + + /* Set the key parity to odd */ + DES_set_odd_parity(&key); + + /* Set the key */ + DES_set_key(&key, ks); +} + +#elif defined(USE_GNUTLS_NETTLE) + +static void setup_des_key(const unsigned char *key_56, + struct des_ctx *des) +{ + char key[8]; + + /* Expand the 56-bit key to 64-bits */ + extend_key_56_to_64(key_56, key); + + /* Set the key parity to odd */ + Curl_des_set_odd_parity((unsigned char *) key, sizeof(key)); + + /* Set the key */ + des_set_key(des, (const uint8_t *) key); +} + +#elif defined(USE_GNUTLS) + +/* + * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. + */ +static void setup_des_key(const unsigned char *key_56, + gcry_cipher_hd_t *des) +{ + char key[8]; + + /* Expand the 56-bit key to 64-bits */ + extend_key_56_to_64(key_56, key); + + /* Set the key parity to odd */ + Curl_des_set_odd_parity((unsigned char *) key, sizeof(key)); + + /* Set the key */ + gcry_cipher_setkey(*des, key, sizeof(key)); +} + +#elif defined(USE_NSS) + +/* + * Expands a 56 bit key KEY_56 to 64 bit and encrypts 64 bit of data, using + * the expanded key. The caller is responsible for giving 64 bit of valid + * data is IN and (at least) 64 bit large buffer as OUT. + */ +static bool encrypt_des(const unsigned char *in, unsigned char *out, + const unsigned char *key_56) +{ + const CK_MECHANISM_TYPE mech = CKM_DES_ECB; /* DES cipher in ECB mode */ + PK11SlotInfo *slot = NULL; + char key[8]; /* expanded 64 bit key */ + SECItem key_item; + PK11SymKey *symkey = NULL; + SECItem *param = NULL; + PK11Context *ctx = NULL; + int out_len; /* not used, required by NSS */ + bool rv = FALSE; + + /* use internal slot for DES encryption (requires NSS to be initialized) */ + slot = PK11_GetInternalKeySlot(); + if(!slot) + return FALSE; + + /* Expand the 56-bit key to 64-bits */ + extend_key_56_to_64(key_56, key); + + /* Set the key parity to odd */ + Curl_des_set_odd_parity((unsigned char *) key, sizeof(key)); + + /* Import the key */ + key_item.data = (unsigned char *)key; + key_item.len = sizeof(key); + symkey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap, CKA_ENCRYPT, + &key_item, NULL); + if(!symkey) + goto fail; + + /* Create the DES encryption context */ + param = PK11_ParamFromIV(mech, /* no IV in ECB mode */ NULL); + if(!param) + goto fail; + ctx = PK11_CreateContextBySymKey(mech, CKA_ENCRYPT, symkey, param); + if(!ctx) + goto fail; + + /* Perform the encryption */ + if(SECSuccess == PK11_CipherOp(ctx, out, &out_len, /* outbuflen */ 8, + (unsigned char *)in, /* inbuflen */ 8) + && SECSuccess == PK11_Finalize(ctx)) + rv = /* all OK */ TRUE; + +fail: + /* cleanup */ + if(ctx) + PK11_DestroyContext(ctx, PR_TRUE); + if(symkey) + PK11_FreeSymKey(symkey); + if(param) + SECITEM_FreeItem(param, PR_TRUE); + PK11_FreeSlot(slot); + return rv; +} + +#elif defined(USE_MBEDTLS) + +static bool encrypt_des(const unsigned char *in, unsigned char *out, + const unsigned char *key_56) +{ + mbedtls_des_context ctx; + char key[8]; + + /* Expand the 56-bit key to 64-bits */ + extend_key_56_to_64(key_56, key); + + /* Set the key parity to odd */ + mbedtls_des_key_set_parity((unsigned char *) key); + + /* Perform the encryption */ + mbedtls_des_init(&ctx); + mbedtls_des_setkey_enc(&ctx, (unsigned char *) key); + return mbedtls_des_crypt_ecb(&ctx, in, out) == 0; +} + +#elif defined(USE_SECTRANSP) + +static bool encrypt_des(const unsigned char *in, unsigned char *out, + const unsigned char *key_56) +{ + char key[8]; + size_t out_len; + CCCryptorStatus err; + + /* Expand the 56-bit key to 64-bits */ + extend_key_56_to_64(key_56, key); + + /* Set the key parity to odd */ + Curl_des_set_odd_parity((unsigned char *) key, sizeof(key)); + + /* Perform the encryption */ + err = CCCrypt(kCCEncrypt, kCCAlgorithmDES, kCCOptionECBMode, key, + kCCKeySizeDES, NULL, in, 8 /* inbuflen */, out, + 8 /* outbuflen */, &out_len); + + return err == kCCSuccess; +} + +#elif defined(USE_OS400CRYPTO) + +static bool encrypt_des(const unsigned char *in, unsigned char *out, + const unsigned char *key_56) +{ + char key[8]; + _CIPHER_Control_T ctl; + + /* Setup the cipher control structure */ + ctl.Func_ID = ENCRYPT_ONLY; + ctl.Data_Len = sizeof(key); + + /* Expand the 56-bit key to 64-bits */ + extend_key_56_to_64(key_56, ctl.Crypto_Key); + + /* Set the key parity to odd */ + Curl_des_set_odd_parity((unsigned char *) ctl.Crypto_Key, ctl.Data_Len); + + /* Perform the encryption */ + _CIPHER((_SPCPTR *) &out, &ctl, (_SPCPTR *) &in); + + return TRUE; +} + +#elif defined(USE_WIN32_CRYPTO) + +static bool encrypt_des(const unsigned char *in, unsigned char *out, + const unsigned char *key_56) +{ + HCRYPTPROV hprov; + HCRYPTKEY hkey; + struct { + BLOBHEADER hdr; + unsigned int len; + char key[8]; + } blob; + DWORD len = 8; + + /* Acquire the crypto provider */ + if(!CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT)) + return FALSE; + + /* Setup the key blob structure */ + memset(&blob, 0, sizeof(blob)); + blob.hdr.bType = PLAINTEXTKEYBLOB; + blob.hdr.bVersion = 2; + blob.hdr.aiKeyAlg = CALG_DES; + blob.len = sizeof(blob.key); + + /* Expand the 56-bit key to 64-bits */ + extend_key_56_to_64(key_56, blob.key); + + /* Set the key parity to odd */ + Curl_des_set_odd_parity((unsigned char *) blob.key, sizeof(blob.key)); + + /* Import the key */ + if(!CryptImportKey(hprov, (BYTE *) &blob, sizeof(blob), 0, 0, &hkey)) { + CryptReleaseContext(hprov, 0); + + return FALSE; + } + + memcpy(out, in, 8); + + /* Perform the encryption */ + CryptEncrypt(hkey, 0, FALSE, 0, out, &len, len); + + CryptDestroyKey(hkey); + CryptReleaseContext(hprov, 0); + + return TRUE; +} + +#endif /* defined(USE_WIN32_CRYPTO) */ + + /* + * takes a 21 byte array and treats it as 3 56-bit DES keys. The + * 8 byte plaintext is encrypted with each key and the resulting 24 + * bytes are stored in the results array. + */ +void Curl_ntlm_core_lm_resp(const unsigned char *keys, + const unsigned char *plaintext, + unsigned char *results) +{ +#ifdef USE_OPENSSL + DES_key_schedule ks; + + setup_des_key(keys, DESKEY(ks)); + DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results, + DESKEY(ks), DES_ENCRYPT); + + setup_des_key(keys + 7, DESKEY(ks)); + DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 8), + DESKEY(ks), DES_ENCRYPT); + + setup_des_key(keys + 14, DESKEY(ks)); + DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 16), + DESKEY(ks), DES_ENCRYPT); +#elif defined(USE_GNUTLS_NETTLE) + struct des_ctx des; + setup_des_key(keys, &des); + des_encrypt(&des, 8, results, plaintext); + setup_des_key(keys + 7, &des); + des_encrypt(&des, 8, results + 8, plaintext); + setup_des_key(keys + 14, &des); + des_encrypt(&des, 8, results + 16, plaintext); +#elif defined(USE_GNUTLS) + gcry_cipher_hd_t des; + + gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); + setup_des_key(keys, &des); + gcry_cipher_encrypt(des, results, 8, plaintext, 8); + gcry_cipher_close(des); + + gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); + setup_des_key(keys + 7, &des); + gcry_cipher_encrypt(des, results + 8, 8, plaintext, 8); + gcry_cipher_close(des); + + gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); + setup_des_key(keys + 14, &des); + gcry_cipher_encrypt(des, results + 16, 8, plaintext, 8); + gcry_cipher_close(des); +#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \ + || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) + encrypt_des(plaintext, results, keys); + encrypt_des(plaintext, results + 8, keys + 7); + encrypt_des(plaintext, results + 16, keys + 14); +#endif +} + +/* + * Set up lanmanager hashed password + */ +CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data, + const char *password, + unsigned char *lmbuffer /* 21 bytes */) +{ + CURLcode result; + unsigned char pw[14]; + static const unsigned char magic[] = { + 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */ + }; + size_t len = CURLMIN(strlen(password), 14); + + Curl_strntoupper((char *)pw, password, len); + memset(&pw[len], 0, 14 - len); + + /* + * The LanManager hashed password needs to be created using the + * password in the network encoding not the host encoding. + */ + result = Curl_convert_to_network(data, (char *)pw, 14); + if(result) + return result; + + { + /* Create LanManager hashed password. */ + +#ifdef USE_OPENSSL + DES_key_schedule ks; + + setup_des_key(pw, DESKEY(ks)); + DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer, + DESKEY(ks), DES_ENCRYPT); + + setup_des_key(pw + 7, DESKEY(ks)); + DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer + 8), + DESKEY(ks), DES_ENCRYPT); +#elif defined(USE_GNUTLS_NETTLE) + struct des_ctx des; + setup_des_key(pw, &des); + des_encrypt(&des, 8, lmbuffer, magic); + setup_des_key(pw + 7, &des); + des_encrypt(&des, 8, lmbuffer + 8, magic); +#elif defined(USE_GNUTLS) + gcry_cipher_hd_t des; + + gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); + setup_des_key(pw, &des); + gcry_cipher_encrypt(des, lmbuffer, 8, magic, 8); + gcry_cipher_close(des); + + gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); + setup_des_key(pw + 7, &des); + gcry_cipher_encrypt(des, lmbuffer + 8, 8, magic, 8); + gcry_cipher_close(des); +#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \ + || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) + encrypt_des(magic, lmbuffer, pw); + encrypt_des(magic, lmbuffer + 8, pw + 7); +#endif + + memset(lmbuffer + 16, 0, 21 - 16); + } + + return CURLE_OK; +} + +#ifdef USE_NTRESPONSES +static void ascii_to_unicode_le(unsigned char *dest, const char *src, + size_t srclen) +{ + size_t i; + for(i = 0; i < srclen; i++) { + dest[2 * i] = (unsigned char)src[i]; + dest[2 * i + 1] = '\0'; + } +} + +#if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI) + +static void ascii_uppercase_to_unicode_le(unsigned char *dest, + const char *src, size_t srclen) +{ + size_t i; + for(i = 0; i < srclen; i++) { + dest[2 * i] = (unsigned char)(Curl_raw_toupper(src[i])); + dest[2 * i + 1] = '\0'; + } +} + +#endif /* USE_NTLM_V2 && !USE_WINDOWS_SSPI */ + +/* + * Set up nt hashed passwords + * @unittest: 1600 + */ +CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data, + const char *password, + unsigned char *ntbuffer /* 21 bytes */) +{ + size_t len = strlen(password); + unsigned char *pw; + CURLcode result; + if(len > SIZE_T_MAX/2) /* avoid integer overflow */ + return CURLE_OUT_OF_MEMORY; + pw = len ? malloc(len * 2) : strdup(""); + if(!pw) + return CURLE_OUT_OF_MEMORY; + + ascii_to_unicode_le(pw, password, len); + + /* + * The NT hashed password needs to be created using the password in the + * network encoding not the host encoding. + */ + result = Curl_convert_to_network(data, (char *)pw, len * 2); + if(result) + return result; + + { + /* Create NT hashed password. */ +#ifdef USE_OPENSSL +#if !defined(OPENSSL_NO_MD4) + MD4_CTX MD4pw; + MD4_Init(&MD4pw); + MD4_Update(&MD4pw, pw, 2 * len); + MD4_Final(ntbuffer, &MD4pw); +#else + Curl_md4it(ntbuffer, pw, 2 * len); +#endif +#elif defined(USE_GNUTLS_NETTLE) + struct md4_ctx MD4pw; + md4_init(&MD4pw); + md4_update(&MD4pw, (unsigned int)(2 * len), pw); + md4_digest(&MD4pw, MD4_DIGEST_SIZE, ntbuffer); +#elif defined(USE_GNUTLS) + gcry_md_hd_t MD4pw; + gcry_md_open(&MD4pw, GCRY_MD_MD4, 0); + gcry_md_write(MD4pw, pw, 2 * len); + memcpy(ntbuffer, gcry_md_read(MD4pw, 0), MD4_DIGEST_LENGTH); + gcry_md_close(MD4pw); +#elif defined(USE_NSS) + Curl_md4it(ntbuffer, pw, 2 * len); +#elif defined(USE_MBEDTLS) +#if defined(MBEDTLS_MD4_C) + mbedtls_md4(pw, 2 * len, ntbuffer); +#else + Curl_md4it(ntbuffer, pw, 2 * len); +#endif +#elif defined(USE_SECTRANSP) + (void)CC_MD4(pw, (CC_LONG)(2 * len), ntbuffer); +#elif defined(USE_OS400CRYPTO) + Curl_md4it(ntbuffer, pw, 2 * len); +#elif defined(USE_WIN32_CRYPTO) + HCRYPTPROV hprov; + if(CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT)) { + HCRYPTHASH hhash; + if(CryptCreateHash(hprov, CALG_MD4, 0, 0, &hhash)) { + DWORD length = 16; + CryptHashData(hhash, pw, (unsigned int)len * 2, 0); + CryptGetHashParam(hhash, HP_HASHVAL, ntbuffer, &length, 0); + CryptDestroyHash(hhash); + } + CryptReleaseContext(hprov, 0); + } +#endif + + memset(ntbuffer + 16, 0, 21 - 16); + } + + free(pw); + + return CURLE_OK; +} + +#if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI) + +/* This returns the HMAC MD5 digest */ +static CURLcode hmac_md5(const unsigned char *key, unsigned int keylen, + const unsigned char *data, unsigned int datalen, + unsigned char *output) +{ + HMAC_context *ctxt = Curl_HMAC_init(Curl_HMAC_MD5, key, keylen); + + if(!ctxt) + return CURLE_OUT_OF_MEMORY; + + /* Update the digest with the given challenge */ + Curl_HMAC_update(ctxt, data, datalen); + + /* Finalise the digest */ + Curl_HMAC_final(ctxt, output); + + return CURLE_OK; +} + +/* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode + * (uppercase UserName + Domain) as the data + */ +CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen, + const char *domain, size_t domlen, + unsigned char *ntlmhash, + unsigned char *ntlmv2hash) +{ + /* Unicode representation */ + size_t identity_len; + unsigned char *identity; + CURLcode result = CURLE_OK; + + /* we do the length checks below separately to avoid integer overflow risk + on extreme data lengths */ + if((userlen > SIZE_T_MAX/2) || + (domlen > SIZE_T_MAX/2) || + ((userlen + domlen) > SIZE_T_MAX/2)) + return CURLE_OUT_OF_MEMORY; + + identity_len = (userlen + domlen) * 2; + identity = malloc(identity_len); + + if(!identity) + return CURLE_OUT_OF_MEMORY; + + ascii_uppercase_to_unicode_le(identity, user, userlen); + ascii_to_unicode_le(identity + (userlen << 1), domain, domlen); + + result = hmac_md5(ntlmhash, 16, identity, curlx_uztoui(identity_len), + ntlmv2hash); + free(identity); + + return result; +} + +/* + * Curl_ntlm_core_mk_ntlmv2_resp() + * + * This creates the NTLMv2 response as set in the ntlm type-3 message. + * + * Parameters: + * + * ntlmv2hash [in] - The ntlmv2 hash (16 bytes) + * challenge_client [in] - The client nonce (8 bytes) + * ntlm [in] - The ntlm data struct being used to read TargetInfo + and Server challenge received in the type-2 message + * ntresp [out] - The address where a pointer to newly allocated + * memory holding the NTLMv2 response. + * ntresp_len [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, + unsigned char *challenge_client, + struct ntlmdata *ntlm, + unsigned char **ntresp, + unsigned int *ntresp_len) +{ +/* NTLMv2 response structure : +------------------------------------------------------------------------------ +0 HMAC MD5 16 bytes +------BLOB-------------------------------------------------------------------- +16 Signature 0x01010000 +20 Reserved long (0x00000000) +24 Timestamp LE, 64-bit signed value representing the number of + tenths of a microsecond since January 1, 1601. +32 Client Nonce 8 bytes +40 Unknown 4 bytes +44 Target Info N bytes (from the type-2 message) +44+N Unknown 4 bytes +------------------------------------------------------------------------------ +*/ + + unsigned int len = 0; + unsigned char *ptr = NULL; + unsigned char hmac_output[NTLM_HMAC_MD5_LEN]; + curl_off_t tw; + + CURLcode result = CURLE_OK; + +#if CURL_SIZEOF_CURL_OFF_T < 8 +#error "this section needs 64bit support to work" +#endif + + /* Calculate the timestamp */ +#ifdef DEBUGBUILD + char *force_timestamp = getenv("CURL_FORCETIME"); + if(force_timestamp) + tw = CURL_OFF_T_C(11644473600) * 10000000; + else +#endif + tw = ((curl_off_t)time(NULL) + CURL_OFF_T_C(11644473600)) * 10000000; + + /* Calculate the response len */ + len = NTLM_HMAC_MD5_LEN + NTLMv2_BLOB_LEN; + + /* Allocate the response */ + ptr = calloc(1, len); + if(!ptr) + return CURLE_OUT_OF_MEMORY; + + /* Create the BLOB structure */ + msnprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN, + "%c%c%c%c" /* NTLMv2_BLOB_SIGNATURE */ + "%c%c%c%c", /* Reserved = 0 */ + NTLMv2_BLOB_SIGNATURE[0], NTLMv2_BLOB_SIGNATURE[1], + NTLMv2_BLOB_SIGNATURE[2], NTLMv2_BLOB_SIGNATURE[3], + 0, 0, 0, 0); + + Curl_write64_le(tw, ptr + 24); + memcpy(ptr + 32, challenge_client, 8); + memcpy(ptr + 44, ntlm->target_info, ntlm->target_info_len); + + /* Concatenate the Type 2 challenge with the BLOB and do HMAC MD5 */ + memcpy(ptr + 8, &ntlm->nonce[0], 8); + result = hmac_md5(ntlmv2hash, NTLM_HMAC_MD5_LEN, ptr + 8, + NTLMv2_BLOB_LEN + 8, hmac_output); + if(result) { + free(ptr); + return result; + } + + /* Concatenate the HMAC MD5 output with the BLOB */ + memcpy(ptr, hmac_output, NTLM_HMAC_MD5_LEN); + + /* Return the response */ + *ntresp = ptr; + *ntresp_len = len; + + return result; +} + +/* + * Curl_ntlm_core_mk_lmv2_resp() + * + * This creates the LMv2 response as used in the ntlm type-3 message. + * + * Parameters: + * + * ntlmv2hash [in] - The ntlmv2 hash (16 bytes) + * challenge_client [in] - The client nonce (8 bytes) + * challenge_client [in] - The server challenge (8 bytes) + * lmresp [out] - The LMv2 response (24 bytes) + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash, + unsigned char *challenge_client, + unsigned char *challenge_server, + unsigned char *lmresp) +{ + unsigned char data[16]; + unsigned char hmac_output[16]; + CURLcode result = CURLE_OK; + + memcpy(&data[0], challenge_server, 8); + memcpy(&data[8], challenge_client, 8); + + result = hmac_md5(ntlmv2hash, 16, &data[0], 16, hmac_output); + if(result) + return result; + + /* Concatenate the HMAC MD5 output with the client nonce */ + memcpy(lmresp, hmac_output, 16); + memcpy(lmresp + 16, challenge_client, 8); + + return result; +} + +#endif /* USE_NTLM_V2 && !USE_WINDOWS_SSPI */ + +#endif /* USE_NTRESPONSES */ + +#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */ + +#endif /* USE_NTLM */ diff --git a/dependencies/cmcurl/lib/curl_ntlm_core.h b/dependencies/cmcurl/lib/curl_ntlm_core.h new file mode 100644 index 0000000..3b4b805 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_ntlm_core.h @@ -0,0 +1,105 @@ +#ifndef HEADER_CURL_NTLM_CORE_H +#define HEADER_CURL_NTLM_CORE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_NTLM) + +/* If NSS is the first available SSL backend (see order in curl_ntlm_core.c) + then it must be initialized to be used by NTLM. */ +#if !defined(USE_OPENSSL) && \ + !defined(USE_GNUTLS_NETTLE) && \ + !defined(USE_GNUTLS) && \ + defined(USE_NSS) +#define NTLM_NEEDS_NSS_INIT +#endif + +#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO) + +#ifdef USE_OPENSSL +# include +#endif + +/* Define USE_NTRESPONSES in order to make the type-3 message include + * the NT response message. */ +#define USE_NTRESPONSES + +/* Define USE_NTLM2SESSION in order to make the type-3 message include the + NTLM2Session response message, requires USE_NTRESPONSES defined to 1 and a + Crypto engine that we have curl_ssl_md5sum() for. */ +#if defined(USE_NTRESPONSES) && !defined(USE_WIN32_CRYPTO) +#define USE_NTLM2SESSION +#endif + +/* Define USE_NTLM_V2 in order to allow the type-3 message to include the + LMv2 and NTLMv2 response messages, requires USE_NTRESPONSES defined to 1 + and support for 64-bit integers. */ +#if defined(USE_NTRESPONSES) && (CURL_SIZEOF_CURL_OFF_T > 4) +#define USE_NTLM_V2 +#endif + +void Curl_ntlm_core_lm_resp(const unsigned char *keys, + const unsigned char *plaintext, + unsigned char *results); + +CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data, + const char *password, + unsigned char *lmbuffer /* 21 bytes */); + +#ifdef USE_NTRESPONSES +CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data, + const char *password, + unsigned char *ntbuffer /* 21 bytes */); + +#if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI) + +CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen, + const unsigned char *data, unsigned int datalen, + unsigned char *output); + +CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen, + const char *domain, size_t domlen, + unsigned char *ntlmhash, + unsigned char *ntlmv2hash); + +CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, + unsigned char *challenge_client, + struct ntlmdata *ntlm, + unsigned char **ntresp, + unsigned int *ntresp_len); + +CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash, + unsigned char *challenge_client, + unsigned char *challenge_server, + unsigned char *lmresp); + +#endif /* USE_NTLM_V2 && !USE_WINDOWS_SSPI */ + +#endif /* USE_NTRESPONSES */ + +#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */ + +#endif /* USE_NTLM */ + +#endif /* HEADER_CURL_NTLM_CORE_H */ diff --git a/dependencies/cmcurl/lib/curl_ntlm_wb.c b/dependencies/cmcurl/lib/curl_ntlm_wb.c new file mode 100644 index 0000000..80266e2 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_ntlm_wb.c @@ -0,0 +1,489 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \ + defined(NTLM_WB_ENABLED) + +/* + * NTLM details: + * + * https://davenport.sourceforge.io/ntlm.html + * https://www.innovation.ch/java/ntlm.html + */ + +#define DEBUG_ME 0 + +#ifdef HAVE_SYS_WAIT_H +#include +#endif +#ifdef HAVE_SIGNAL_H +#include +#endif +#ifdef HAVE_PWD_H +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "select.h" +#include "vauth/ntlm.h" +#include "curl_ntlm_core.h" +#include "curl_ntlm_wb.h" +#include "url.h" +#include "strerror.h" +#include "strdup.h" +#include "strcase.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#if DEBUG_ME +# define DEBUG_OUT(x) x +#else +# define DEBUG_OUT(x) Curl_nop_stmt +#endif + +/* Portable 'sclose_nolog' used only in child process instead of 'sclose' + to avoid fooling the socket leak detector */ +#if defined(HAVE_CLOSESOCKET) +# define sclose_nolog(x) closesocket((x)) +#elif defined(HAVE_CLOSESOCKET_CAMEL) +# define sclose_nolog(x) CloseSocket((x)) +#else +# define sclose_nolog(x) close((x)) +#endif + +void Curl_http_auth_cleanup_ntlm_wb(struct connectdata *conn) +{ + if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD) { + sclose(conn->ntlm_auth_hlpr_socket); + conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD; + } + + if(conn->ntlm_auth_hlpr_pid) { + int i; + for(i = 0; i < 4; i++) { + pid_t ret = waitpid(conn->ntlm_auth_hlpr_pid, NULL, WNOHANG); + if(ret == conn->ntlm_auth_hlpr_pid || errno == ECHILD) + break; + switch(i) { + case 0: + kill(conn->ntlm_auth_hlpr_pid, SIGTERM); + break; + case 1: + /* Give the process another moment to shut down cleanly before + bringing down the axe */ + Curl_wait_ms(1); + break; + case 2: + kill(conn->ntlm_auth_hlpr_pid, SIGKILL); + break; + case 3: + break; + } + } + conn->ntlm_auth_hlpr_pid = 0; + } + + free(conn->challenge_header); + conn->challenge_header = NULL; + free(conn->response_header); + conn->response_header = NULL; +} + +static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) +{ + curl_socket_t sockfds[2]; + pid_t child_pid; + const char *username; + char *slash, *domain = NULL; + const char *ntlm_auth = NULL; + char *ntlm_auth_alloc = NULL; +#if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID) + struct passwd pw, *pw_res; + char pwbuf[1024]; +#endif + char buffer[STRERROR_LEN]; + + /* Return if communication with ntlm_auth already set up */ + if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD || + conn->ntlm_auth_hlpr_pid) + return CURLE_OK; + + username = userp; + /* The real ntlm_auth really doesn't like being invoked with an + empty username. It won't make inferences for itself, and expects + the client to do so (mostly because it's really designed for + servers like squid to use for auth, and client support is an + afterthought for it). So try hard to provide a suitable username + if we don't already have one. But if we can't, provide the + empty one anyway. Perhaps they have an implementation of the + ntlm_auth helper which *doesn't* need it so we might as well try */ + if(!username || !username[0]) { + username = getenv("NTLMUSER"); + if(!username || !username[0]) + username = getenv("LOGNAME"); + if(!username || !username[0]) + username = getenv("USER"); +#if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID) + if((!username || !username[0]) && + !getpwuid_r(geteuid(), &pw, pwbuf, sizeof(pwbuf), &pw_res) && + pw_res) { + username = pw.pw_name; + } +#endif + if(!username || !username[0]) + username = userp; + } + slash = strpbrk(username, "\\/"); + if(slash) { + domain = strdup(username); + if(!domain) + return CURLE_OUT_OF_MEMORY; + slash = domain + (slash - username); + *slash = '\0'; + username = username + (slash - domain) + 1; + } + + /* For testing purposes, when DEBUGBUILD is defined and environment + variable CURL_NTLM_WB_FILE is set a fake_ntlm is used to perform + NTLM challenge/response which only accepts commands and output + strings pre-written in test case definitions */ +#ifdef DEBUGBUILD + ntlm_auth_alloc = curl_getenv("CURL_NTLM_WB_FILE"); + if(ntlm_auth_alloc) + ntlm_auth = ntlm_auth_alloc; + else +#endif + ntlm_auth = NTLM_WB_FILE; + + if(access(ntlm_auth, X_OK) != 0) { + failf(conn->data, "Could not access ntlm_auth: %s errno %d: %s", + ntlm_auth, errno, Curl_strerror(errno, buffer, sizeof(buffer))); + goto done; + } + + if(socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) { + failf(conn->data, "Could not open socket pair. errno %d: %s", + errno, Curl_strerror(errno, buffer, sizeof(buffer))); + goto done; + } + + child_pid = fork(); + if(child_pid == -1) { + sclose(sockfds[0]); + sclose(sockfds[1]); + failf(conn->data, "Could not fork. errno %d: %s", + errno, Curl_strerror(errno, buffer, sizeof(buffer))); + goto done; + } + else if(!child_pid) { + /* + * child process + */ + + /* Don't use sclose in the child since it fools the socket leak detector */ + sclose_nolog(sockfds[0]); + if(dup2(sockfds[1], STDIN_FILENO) == -1) { + failf(conn->data, "Could not redirect child stdin. errno %d: %s", + errno, Curl_strerror(errno, buffer, sizeof(buffer))); + exit(1); + } + + if(dup2(sockfds[1], STDOUT_FILENO) == -1) { + failf(conn->data, "Could not redirect child stdout. errno %d: %s", + errno, Curl_strerror(errno, buffer, sizeof(buffer))); + exit(1); + } + + if(domain) + execl(ntlm_auth, ntlm_auth, + "--helper-protocol", "ntlmssp-client-1", + "--use-cached-creds", + "--username", username, + "--domain", domain, + NULL); + else + execl(ntlm_auth, ntlm_auth, + "--helper-protocol", "ntlmssp-client-1", + "--use-cached-creds", + "--username", username, + NULL); + + sclose_nolog(sockfds[1]); + failf(conn->data, "Could not execl(). errno %d: %s", + errno, Curl_strerror(errno, buffer, sizeof(buffer))); + exit(1); + } + + sclose(sockfds[1]); + conn->ntlm_auth_hlpr_socket = sockfds[0]; + conn->ntlm_auth_hlpr_pid = child_pid; + free(domain); + free(ntlm_auth_alloc); + return CURLE_OK; + +done: + free(domain); + free(ntlm_auth_alloc); + return CURLE_REMOTE_ACCESS_DENIED; +} + +/* if larger than this, something is seriously wrong */ +#define MAX_NTLM_WB_RESPONSE 100000 + +static CURLcode ntlm_wb_response(struct connectdata *conn, + const char *input, curlntlm state) +{ + char *buf = malloc(NTLM_BUFSIZE); + size_t len_in = strlen(input), len_out = 0; + + if(!buf) + return CURLE_OUT_OF_MEMORY; + + while(len_in > 0) { + ssize_t written = swrite(conn->ntlm_auth_hlpr_socket, input, len_in); + if(written == -1) { + /* Interrupted by a signal, retry it */ + if(errno == EINTR) + continue; + /* write failed if other errors happen */ + goto done; + } + input += written; + len_in -= written; + } + /* Read one line */ + while(1) { + ssize_t size; + char *newbuf; + + size = sread(conn->ntlm_auth_hlpr_socket, buf + len_out, NTLM_BUFSIZE); + if(size == -1) { + if(errno == EINTR) + continue; + goto done; + } + else if(size == 0) + goto done; + + len_out += size; + if(buf[len_out - 1] == '\n') { + buf[len_out - 1] = '\0'; + break; + } + + if(len_out > MAX_NTLM_WB_RESPONSE) { + failf(conn->data, "too large ntlm_wb response!"); + free(buf); + return CURLE_OUT_OF_MEMORY; + } + + newbuf = Curl_saferealloc(buf, len_out + NTLM_BUFSIZE); + if(!newbuf) + return CURLE_OUT_OF_MEMORY; + + buf = newbuf; + } + + /* Samba/winbind installed but not configured */ + if(state == NTLMSTATE_TYPE1 && + len_out == 3 && + buf[0] == 'P' && buf[1] == 'W') + goto done; + /* invalid response */ + if(len_out < 4) + goto done; + if(state == NTLMSTATE_TYPE1 && + (buf[0]!='Y' || buf[1]!='R' || buf[2]!=' ')) + goto done; + if(state == NTLMSTATE_TYPE2 && + (buf[0]!='K' || buf[1]!='K' || buf[2]!=' ') && + (buf[0]!='A' || buf[1]!='F' || buf[2]!=' ')) + goto done; + + conn->response_header = aprintf("NTLM %.*s", len_out - 4, buf + 3); + free(buf); + if(!conn->response_header) + return CURLE_OUT_OF_MEMORY; + return CURLE_OK; +done: + free(buf); + return CURLE_REMOTE_ACCESS_DENIED; +} + +CURLcode Curl_input_ntlm_wb(struct connectdata *conn, + bool proxy, + const char *header) +{ + curlntlm *state = proxy ? &conn->proxy_ntlm_state : &conn->http_ntlm_state; + + if(!checkprefix("NTLM", header)) + return CURLE_BAD_CONTENT_ENCODING; + + header += strlen("NTLM"); + while(*header && ISSPACE(*header)) + header++; + + if(*header) { + conn->challenge_header = strdup(header); + if(!conn->challenge_header) + return CURLE_OUT_OF_MEMORY; + + *state = NTLMSTATE_TYPE2; /* We got a type-2 message */ + } + else { + if(*state == NTLMSTATE_LAST) { + infof(conn->data, "NTLM auth restarted\n"); + Curl_http_auth_cleanup_ntlm_wb(conn); + } + else if(*state == NTLMSTATE_TYPE3) { + infof(conn->data, "NTLM handshake rejected\n"); + Curl_http_auth_cleanup_ntlm_wb(conn); + *state = NTLMSTATE_NONE; + return CURLE_REMOTE_ACCESS_DENIED; + } + else if(*state >= NTLMSTATE_TYPE1) { + infof(conn->data, "NTLM handshake failure (internal error)\n"); + return CURLE_REMOTE_ACCESS_DENIED; + } + + *state = NTLMSTATE_TYPE1; /* We should send away a type-1 */ + } + + return CURLE_OK; +} + +/* + * This is for creating ntlm header output by delegating challenge/response + * to Samba's winbind daemon helper ntlm_auth. + */ +CURLcode Curl_output_ntlm_wb(struct connectdata *conn, + bool proxy) +{ + /* point to the address of the pointer that holds the string to send to the + server, which is for a plain host or for a HTTP proxy */ + char **allocuserpwd; + /* point to the name and password for this */ + const char *userp; + curlntlm *state; + struct auth *authp; + + CURLcode res = CURLE_OK; + char *input; + + DEBUGASSERT(conn); + DEBUGASSERT(conn->data); + + if(proxy) { + allocuserpwd = &conn->allocptr.proxyuserpwd; + userp = conn->http_proxy.user; + state = &conn->proxy_ntlm_state; + authp = &conn->data->state.authproxy; + } + else { + allocuserpwd = &conn->allocptr.userpwd; + userp = conn->user; + state = &conn->http_ntlm_state; + authp = &conn->data->state.authhost; + } + authp->done = FALSE; + + /* not set means empty */ + if(!userp) + userp = ""; + + switch(*state) { + case NTLMSTATE_TYPE1: + default: + /* Use Samba's 'winbind' daemon to support NTLM authentication, + * by delegating the NTLM challenge/response protocol to a helper + * in ntlm_auth. + * http://devel.squid-cache.org/ntlm/squid_helper_protocol.html + * https://www.samba.org/samba/docs/man/manpages-3/winbindd.8.html + * https://www.samba.org/samba/docs/man/manpages-3/ntlm_auth.1.html + * Preprocessor symbol 'NTLM_WB_ENABLED' is defined when this + * feature is enabled and 'NTLM_WB_FILE' symbol holds absolute + * filename of ntlm_auth helper. + * If NTLM authentication using winbind fails, go back to original + * request handling process. + */ + /* Create communication with ntlm_auth */ + res = ntlm_wb_init(conn, userp); + if(res) + return res; + res = ntlm_wb_response(conn, "YR\n", *state); + if(res) + return res; + + free(*allocuserpwd); + *allocuserpwd = aprintf("%sAuthorization: %s\r\n", + proxy ? "Proxy-" : "", + conn->response_header); + DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd)); + free(conn->response_header); + if(!*allocuserpwd) + return CURLE_OUT_OF_MEMORY; + conn->response_header = NULL; + break; + + case NTLMSTATE_TYPE2: + input = aprintf("TT %s\n", conn->challenge_header); + if(!input) + return CURLE_OUT_OF_MEMORY; + res = ntlm_wb_response(conn, input, *state); + free(input); + input = NULL; + if(res) + return res; + + free(*allocuserpwd); + *allocuserpwd = aprintf("%sAuthorization: %s\r\n", + proxy ? "Proxy-" : "", + conn->response_header); + DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd)); + *state = NTLMSTATE_TYPE3; /* we sent a type-3 */ + authp->done = TRUE; + Curl_http_auth_cleanup_ntlm_wb(conn); + if(!*allocuserpwd) + return CURLE_OUT_OF_MEMORY; + break; + + case NTLMSTATE_TYPE3: + /* connection is already authenticated, + * don't send a header in future requests */ + *state = NTLMSTATE_LAST; + /* FALLTHROUGH */ + case NTLMSTATE_LAST: + Curl_safefree(*allocuserpwd); + authp->done = TRUE; + break; + } + + return CURLE_OK; +} + +#endif /* !CURL_DISABLE_HTTP && USE_NTLM && NTLM_WB_ENABLED */ diff --git a/dependencies/cmcurl/lib/curl_ntlm_wb.h b/dependencies/cmcurl/lib/curl_ntlm_wb.h new file mode 100644 index 0000000..3cf841c --- /dev/null +++ b/dependencies/cmcurl/lib/curl_ntlm_wb.h @@ -0,0 +1,41 @@ +#ifndef HEADER_CURL_NTLM_WB_H +#define HEADER_CURL_NTLM_WB_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \ + defined(NTLM_WB_ENABLED) + +/* this is for ntlm header input */ +CURLcode Curl_input_ntlm_wb(struct connectdata *conn, bool proxy, + const char *header); + +/* this is for creating ntlm header output */ +CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy); + +void Curl_http_auth_cleanup_ntlm_wb(struct connectdata *conn); + +#endif /* !CURL_DISABLE_HTTP && USE_NTLM && NTLM_WB_ENABLED */ + +#endif /* HEADER_CURL_NTLM_WB_H */ diff --git a/dependencies/cmcurl/lib/curl_path.c b/dependencies/cmcurl/lib/curl_path.c new file mode 100644 index 0000000..85dddce --- /dev/null +++ b/dependencies/cmcurl/lib/curl_path.c @@ -0,0 +1,199 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_SSH) + +#include +#include "curl_memory.h" +#include "curl_path.h" +#include "escape.h" +#include "memdebug.h" + +/* figure out the path to work with in this particular request */ +CURLcode Curl_getworkingpath(struct connectdata *conn, + char *homedir, /* when SFTP is used */ + char **path) /* returns the allocated + real path to work with */ +{ + struct Curl_easy *data = conn->data; + char *real_path = NULL; + char *working_path; + size_t working_path_len; + CURLcode result = + Curl_urldecode(data, data->state.up.path, 0, &working_path, + &working_path_len, FALSE); + if(result) + return result; + + /* Check for /~/, indicating relative to the user's home directory */ + if(conn->handler->protocol & CURLPROTO_SCP) { + real_path = malloc(working_path_len + 1); + if(real_path == NULL) { + free(working_path); + return CURLE_OUT_OF_MEMORY; + } + if((working_path_len > 3) && (!memcmp(working_path, "/~/", 3))) + /* It is referenced to the home directory, so strip the leading '/~/' */ + memcpy(real_path, working_path + 3, 4 + working_path_len-3); + else + memcpy(real_path, working_path, 1 + working_path_len); + } + else if(conn->handler->protocol & CURLPROTO_SFTP) { + if((working_path_len > 1) && (working_path[1] == '~')) { + size_t homelen = strlen(homedir); + real_path = malloc(homelen + working_path_len + 1); + if(real_path == NULL) { + free(working_path); + return CURLE_OUT_OF_MEMORY; + } + /* It is referenced to the home directory, so strip the + leading '/' */ + memcpy(real_path, homedir, homelen); + real_path[homelen] = '/'; + real_path[homelen + 1] = '\0'; + if(working_path_len > 3) { + memcpy(real_path + homelen + 1, working_path + 3, + 1 + working_path_len -3); + } + } + else { + real_path = malloc(working_path_len + 1); + if(real_path == NULL) { + free(working_path); + return CURLE_OUT_OF_MEMORY; + } + memcpy(real_path, working_path, 1 + working_path_len); + } + } + + free(working_path); + + /* store the pointer for the caller to receive */ + *path = real_path; + + return CURLE_OK; +} + +/* The get_pathname() function is being borrowed from OpenSSH sftp.c + version 4.6p1. */ +/* + * Copyright (c) 2001-2004 Damien Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir) +{ + const char *cp = *cpp, *end; + char quot; + unsigned int i, j; + size_t fullPathLength, pathLength; + bool relativePath = false; + static const char WHITESPACE[] = " \t\r\n"; + + if(!*cp) { + *cpp = NULL; + *path = NULL; + return CURLE_QUOTE_ERROR; + } + /* Ignore leading whitespace */ + cp += strspn(cp, WHITESPACE); + /* Allocate enough space for home directory and filename + separator */ + fullPathLength = strlen(cp) + strlen(homedir) + 2; + *path = malloc(fullPathLength); + if(*path == NULL) + return CURLE_OUT_OF_MEMORY; + + /* Check for quoted filenames */ + if(*cp == '\"' || *cp == '\'') { + quot = *cp++; + + /* Search for terminating quote, unescape some chars */ + for(i = j = 0; i <= strlen(cp); i++) { + if(cp[i] == quot) { /* Found quote */ + i++; + (*path)[j] = '\0'; + break; + } + if(cp[i] == '\0') { /* End of string */ + /*error("Unterminated quote");*/ + goto fail; + } + if(cp[i] == '\\') { /* Escaped characters */ + i++; + if(cp[i] != '\'' && cp[i] != '\"' && + cp[i] != '\\') { + /*error("Bad escaped character '\\%c'", + cp[i]);*/ + goto fail; + } + } + (*path)[j++] = cp[i]; + } + + if(j == 0) { + /*error("Empty quotes");*/ + goto fail; + } + *cpp = cp + i + strspn(cp + i, WHITESPACE); + } + else { + /* Read to end of filename - either to white space or terminator */ + end = strpbrk(cp, WHITESPACE); + if(end == NULL) + end = strchr(cp, '\0'); + /* return pointer to second parameter if it exists */ + *cpp = end + strspn(end, WHITESPACE); + pathLength = 0; + relativePath = (cp[0] == '/' && cp[1] == '~' && cp[2] == '/'); + /* Handling for relative path - prepend home directory */ + if(relativePath) { + strcpy(*path, homedir); + pathLength = strlen(homedir); + (*path)[pathLength++] = '/'; + (*path)[pathLength] = '\0'; + cp += 3; + } + /* Copy path name up until first "white space" */ + memcpy(&(*path)[pathLength], cp, (int)(end - cp)); + pathLength += (int)(end - cp); + (*path)[pathLength] = '\0'; + } + return CURLE_OK; + + fail: + Curl_safefree(*path); + return CURLE_QUOTE_ERROR; +} + +#endif /* if SSH is used */ diff --git a/dependencies/cmcurl/lib/curl_path.h b/dependencies/cmcurl/lib/curl_path.h new file mode 100644 index 0000000..636c37f --- /dev/null +++ b/dependencies/cmcurl/lib/curl_path.h @@ -0,0 +1,47 @@ +#ifndef HEADER_CURL_PATH_H +#define HEADER_CURL_PATH_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include +#include "urldata.h" + +#ifdef WIN32 +# undef PATH_MAX +# define PATH_MAX MAX_PATH +# ifndef R_OK +# define R_OK 4 +# endif +#endif + +#ifndef PATH_MAX +#define PATH_MAX 1024 /* just an extra precaution since there are systems that + have their definition hidden well */ +#endif + +CURLcode Curl_getworkingpath(struct connectdata *conn, + char *homedir, + char **path); + +CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir); +#endif /* HEADER_CURL_PATH_H */ diff --git a/dependencies/cmcurl/lib/curl_printf.h b/dependencies/cmcurl/lib/curl_printf.h new file mode 100644 index 0000000..0d37b8e --- /dev/null +++ b/dependencies/cmcurl/lib/curl_printf.h @@ -0,0 +1,48 @@ +#ifndef HEADER_CURL_PRINTF_H +#define HEADER_CURL_PRINTF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * This header should be included by ALL code in libcurl that uses any + * *rintf() functions. + */ + +#include + +# undef printf +# undef fprintf +# undef msnprintf +# undef vprintf +# undef vfprintf +# undef vsnprintf +# undef aprintf +# undef vaprintf +# define printf curl_mprintf +# define fprintf curl_mfprintf +# define msnprintf curl_msnprintf +# define vprintf curl_mvprintf +# define vfprintf curl_mvfprintf +# define mvsnprintf curl_mvsnprintf +# define aprintf curl_maprintf +# define vaprintf curl_mvaprintf +#endif /* HEADER_CURL_PRINTF_H */ diff --git a/dependencies/cmcurl/lib/curl_range.c b/dependencies/cmcurl/lib/curl_range.c new file mode 100644 index 0000000..aa3c493 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_range.c @@ -0,0 +1,95 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include +#include "curl_range.h" +#include "sendf.h" +#include "strtoofft.h" + +/* Only include this function if one or more of FTP, FILE are enabled. */ +#if !defined(CURL_DISABLE_FTP) || !defined(CURL_DISABLE_FILE) + + /* + Check if this is a range download, and if so, set the internal variables + properly. + */ +CURLcode Curl_range(struct connectdata *conn) +{ + curl_off_t from, to; + char *ptr; + char *ptr2; + struct Curl_easy *data = conn->data; + + if(data->state.use_range && data->state.range) { + CURLofft from_t; + CURLofft to_t; + from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from); + if(from_t == CURL_OFFT_FLOW) + return CURLE_RANGE_ERROR; + while(*ptr && (ISSPACE(*ptr) || (*ptr == '-'))) + ptr++; + to_t = curlx_strtoofft(ptr, &ptr2, 0, &to); + if(to_t == CURL_OFFT_FLOW) + return CURLE_RANGE_ERROR; + if((to_t == CURL_OFFT_INVAL) && !from_t) { + /* X - */ + data->state.resume_from = from; + DEBUGF(infof(data, "RANGE %" CURL_FORMAT_CURL_OFF_T " to end of file\n", + from)); + } + else if((from_t == CURL_OFFT_INVAL) && !to_t) { + /* -Y */ + data->req.maxdownload = to; + data->state.resume_from = -to; + DEBUGF(infof(data, "RANGE the last %" CURL_FORMAT_CURL_OFF_T " bytes\n", + to)); + } + else { + /* X-Y */ + curl_off_t totalsize; + + /* Ensure the range is sensible - to should follow from. */ + if(from > to) + return CURLE_RANGE_ERROR; + + totalsize = to - from; + if(totalsize == CURL_OFF_T_MAX) + return CURLE_RANGE_ERROR; + + data->req.maxdownload = totalsize + 1; /* include last byte */ + data->state.resume_from = from; + DEBUGF(infof(data, "RANGE from %" CURL_FORMAT_CURL_OFF_T + " getting %" CURL_FORMAT_CURL_OFF_T " bytes\n", + from, data->req.maxdownload)); + } + DEBUGF(infof(data, "range-download from %" CURL_FORMAT_CURL_OFF_T + " to %" CURL_FORMAT_CURL_OFF_T ", totally %" + CURL_FORMAT_CURL_OFF_T " bytes\n", + from, to, data->req.maxdownload)); + } + else + data->req.maxdownload = -1; + return CURLE_OK; +} + +#endif diff --git a/dependencies/cmcurl/lib/curl_range.h b/dependencies/cmcurl/lib/curl_range.h new file mode 100644 index 0000000..2350df9 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_range.h @@ -0,0 +1,30 @@ +#ifndef HEADER_CURL_RANGE_H +#define HEADER_CURL_RANGE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include "urldata.h" + +CURLcode Curl_range(struct connectdata *conn); + +#endif /* HEADER_CURL_RANGE_H */ diff --git a/dependencies/cmcurl/lib/curl_rtmp.c b/dependencies/cmcurl/lib/curl_rtmp.c new file mode 100644 index 0000000..16b1de1 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_rtmp.c @@ -0,0 +1,316 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2019, Daniel Stenberg, , et al. + * Copyright (C) 2010, Howard Chu, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_LIBRTMP + +#include "curl_rtmp.h" +#include "urldata.h" +#include "nonblock.h" /* for curlx_nonblock */ +#include "progress.h" /* for Curl_pgrsSetUploadSize */ +#include "transfer.h" +#include "warnless.h" +#include +#include +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +#if defined(WIN32) && !defined(USE_LWIPSOCK) +#define setsockopt(a,b,c,d,e) (setsockopt)(a,b,c,(const char *)d,(int)e) +#define SET_RCVTIMEO(tv,s) int tv = s*1000 +#elif defined(LWIP_SO_SNDRCVTIMEO_NONSTANDARD) +#define SET_RCVTIMEO(tv,s) int tv = s*1000 +#else +#define SET_RCVTIMEO(tv,s) struct timeval tv = {s,0} +#endif + +#define DEF_BUFTIME (2*60*60*1000) /* 2 hours */ + +static CURLcode rtmp_setup_connection(struct connectdata *conn); +static CURLcode rtmp_do(struct connectdata *conn, bool *done); +static CURLcode rtmp_done(struct connectdata *conn, CURLcode, bool premature); +static CURLcode rtmp_connect(struct connectdata *conn, bool *done); +static CURLcode rtmp_disconnect(struct connectdata *conn, bool dead); + +static Curl_recv rtmp_recv; +static Curl_send rtmp_send; + +/* + * RTMP protocol handler.h, based on https://rtmpdump.mplayerhq.hu + */ + +const struct Curl_handler Curl_handler_rtmp = { + "RTMP", /* scheme */ + rtmp_setup_connection, /* setup_connection */ + rtmp_do, /* do_it */ + rtmp_done, /* done */ + ZERO_NULL, /* do_more */ + rtmp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_RTMP, /* defport */ + CURLPROTO_RTMP, /* protocol */ + PROTOPT_NONE /* flags*/ +}; + +const struct Curl_handler Curl_handler_rtmpt = { + "RTMPT", /* scheme */ + rtmp_setup_connection, /* setup_connection */ + rtmp_do, /* do_it */ + rtmp_done, /* done */ + ZERO_NULL, /* do_more */ + rtmp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_RTMPT, /* defport */ + CURLPROTO_RTMPT, /* protocol */ + PROTOPT_NONE /* flags*/ +}; + +const struct Curl_handler Curl_handler_rtmpe = { + "RTMPE", /* scheme */ + rtmp_setup_connection, /* setup_connection */ + rtmp_do, /* do_it */ + rtmp_done, /* done */ + ZERO_NULL, /* do_more */ + rtmp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_RTMP, /* defport */ + CURLPROTO_RTMPE, /* protocol */ + PROTOPT_NONE /* flags*/ +}; + +const struct Curl_handler Curl_handler_rtmpte = { + "RTMPTE", /* scheme */ + rtmp_setup_connection, /* setup_connection */ + rtmp_do, /* do_it */ + rtmp_done, /* done */ + ZERO_NULL, /* do_more */ + rtmp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_RTMPT, /* defport */ + CURLPROTO_RTMPTE, /* protocol */ + PROTOPT_NONE /* flags*/ +}; + +const struct Curl_handler Curl_handler_rtmps = { + "RTMPS", /* scheme */ + rtmp_setup_connection, /* setup_connection */ + rtmp_do, /* do_it */ + rtmp_done, /* done */ + ZERO_NULL, /* do_more */ + rtmp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_RTMPS, /* defport */ + CURLPROTO_RTMPS, /* protocol */ + PROTOPT_NONE /* flags*/ +}; + +const struct Curl_handler Curl_handler_rtmpts = { + "RTMPTS", /* scheme */ + rtmp_setup_connection, /* setup_connection */ + rtmp_do, /* do_it */ + rtmp_done, /* done */ + ZERO_NULL, /* do_more */ + rtmp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_RTMPS, /* defport */ + CURLPROTO_RTMPTS, /* protocol */ + PROTOPT_NONE /* flags*/ +}; + +static CURLcode rtmp_setup_connection(struct connectdata *conn) +{ + RTMP *r = RTMP_Alloc(); + if(!r) + return CURLE_OUT_OF_MEMORY; + + RTMP_Init(r); + RTMP_SetBufferMS(r, DEF_BUFTIME); + if(!RTMP_SetupURL(r, conn->data->change.url)) { + RTMP_Free(r); + return CURLE_URL_MALFORMAT; + } + conn->proto.generic = r; + return CURLE_OK; +} + +static CURLcode rtmp_connect(struct connectdata *conn, bool *done) +{ + RTMP *r = conn->proto.generic; + SET_RCVTIMEO(tv, 10); + + r->m_sb.sb_socket = (int)conn->sock[FIRSTSOCKET]; + + /* We have to know if it's a write before we send the + * connect request packet + */ + if(conn->data->set.upload) + r->Link.protocol |= RTMP_FEATURE_WRITE; + + /* For plain streams, use the buffer toggle trick to keep data flowing */ + if(!(r->Link.lFlags & RTMP_LF_LIVE) && + !(r->Link.protocol & RTMP_FEATURE_HTTP)) + r->Link.lFlags |= RTMP_LF_BUFX; + + (void)curlx_nonblock(r->m_sb.sb_socket, FALSE); + setsockopt(r->m_sb.sb_socket, SOL_SOCKET, SO_RCVTIMEO, + (char *)&tv, sizeof(tv)); + + if(!RTMP_Connect1(r, NULL)) + return CURLE_FAILED_INIT; + + /* Clients must send a periodic BytesReceived report to the server */ + r->m_bSendCounter = true; + + *done = TRUE; + conn->recv[FIRSTSOCKET] = rtmp_recv; + conn->send[FIRSTSOCKET] = rtmp_send; + return CURLE_OK; +} + +static CURLcode rtmp_do(struct connectdata *conn, bool *done) +{ + struct Curl_easy *data = conn->data; + RTMP *r = conn->proto.generic; + + if(!RTMP_ConnectStream(r, 0)) + return CURLE_FAILED_INIT; + + if(conn->data->set.upload) { + Curl_pgrsSetUploadSize(data, data->state.infilesize); + Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); + } + else + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); + *done = TRUE; + return CURLE_OK; +} + +static CURLcode rtmp_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + (void)conn; /* unused */ + (void)status; /* unused */ + (void)premature; /* unused */ + + return CURLE_OK; +} + +static CURLcode rtmp_disconnect(struct connectdata *conn, + bool dead_connection) +{ + RTMP *r = conn->proto.generic; + (void)dead_connection; + if(r) { + conn->proto.generic = NULL; + RTMP_Close(r); + RTMP_Free(r); + } + return CURLE_OK; +} + +static ssize_t rtmp_recv(struct connectdata *conn, int sockindex, char *buf, + size_t len, CURLcode *err) +{ + RTMP *r = conn->proto.generic; + ssize_t nread; + + (void)sockindex; /* unused */ + + nread = RTMP_Read(r, buf, curlx_uztosi(len)); + if(nread < 0) { + if(r->m_read.status == RTMP_READ_COMPLETE || + r->m_read.status == RTMP_READ_EOF) { + conn->data->req.size = conn->data->req.bytecount; + nread = 0; + } + else + *err = CURLE_RECV_ERROR; + } + return nread; +} + +static ssize_t rtmp_send(struct connectdata *conn, int sockindex, + const void *buf, size_t len, CURLcode *err) +{ + RTMP *r = conn->proto.generic; + ssize_t num; + + (void)sockindex; /* unused */ + + num = RTMP_Write(r, (char *)buf, curlx_uztosi(len)); + if(num < 0) + *err = CURLE_SEND_ERROR; + + return num; +} +#endif /* USE_LIBRTMP */ diff --git a/dependencies/cmcurl/lib/curl_rtmp.h b/dependencies/cmcurl/lib/curl_rtmp.h new file mode 100644 index 0000000..3306e22 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_rtmp.h @@ -0,0 +1,33 @@ +#ifndef HEADER_CURL_RTMP_H +#define HEADER_CURL_RTMP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010, Howard Chu, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifdef USE_LIBRTMP +extern const struct Curl_handler Curl_handler_rtmp; +extern const struct Curl_handler Curl_handler_rtmpt; +extern const struct Curl_handler Curl_handler_rtmpe; +extern const struct Curl_handler Curl_handler_rtmpte; +extern const struct Curl_handler Curl_handler_rtmps; +extern const struct Curl_handler Curl_handler_rtmpts; +#endif + +#endif /* HEADER_CURL_RTMP_H */ diff --git a/dependencies/cmcurl/lib/curl_sasl.c b/dependencies/cmcurl/lib/curl_sasl.c new file mode 100644 index 0000000..018e422 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_sasl.c @@ -0,0 +1,629 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC2195 CRAM-MD5 authentication + * RFC2617 Basic and Digest Access Authentication + * RFC2831 DIGEST-MD5 authentication + * RFC4422 Simple Authentication and Security Layer (SASL) + * RFC4616 PLAIN authentication + * RFC6749 OAuth 2.0 Authorization Framework + * RFC7628 A Set of SASL Mechanisms for OAuth + * Draft LOGIN SASL Mechanism + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_SMTP) || \ + !defined(CURL_DISABLE_POP3) + +#include +#include "urldata.h" + +#include "curl_base64.h" +#include "curl_md5.h" +#include "vauth/vauth.h" +#include "vtls/vtls.h" +#include "curl_hmac.h" +#include "curl_sasl.h" +#include "warnless.h" +#include "strtok.h" +#include "sendf.h" +#include "non-ascii.h" /* included for Curl_convert_... prototypes */ +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* Supported mechanisms */ +static const struct { + const char *name; /* Name */ + size_t len; /* Name length */ + unsigned int bit; /* Flag bit */ +} mechtable[] = { + { "LOGIN", 5, SASL_MECH_LOGIN }, + { "PLAIN", 5, SASL_MECH_PLAIN }, + { "CRAM-MD5", 8, SASL_MECH_CRAM_MD5 }, + { "DIGEST-MD5", 10, SASL_MECH_DIGEST_MD5 }, + { "GSSAPI", 6, SASL_MECH_GSSAPI }, + { "EXTERNAL", 8, SASL_MECH_EXTERNAL }, + { "NTLM", 4, SASL_MECH_NTLM }, + { "XOAUTH2", 7, SASL_MECH_XOAUTH2 }, + { "OAUTHBEARER", 11, SASL_MECH_OAUTHBEARER }, + { ZERO_NULL, 0, 0 } +}; + +/* + * Curl_sasl_cleanup() + * + * This is used to cleanup any libraries or curl modules used by the sasl + * functions. + * + * Parameters: + * + * conn [in] - The connection data. + * authused [in] - The authentication mechanism used. + */ +void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused) +{ +#if defined(USE_KERBEROS5) + /* Cleanup the gssapi structure */ + if(authused == SASL_MECH_GSSAPI) { + Curl_auth_cleanup_gssapi(&conn->krb5); + } +#endif + +#if defined(USE_NTLM) + /* Cleanup the NTLM structure */ + if(authused == SASL_MECH_NTLM) { + Curl_auth_cleanup_ntlm(&conn->ntlm); + } +#endif + +#if !defined(USE_KERBEROS5) && !defined(USE_NTLM) + /* Reserved for future use */ + (void)conn; + (void)authused; +#endif +} + +/* + * Curl_sasl_decode_mech() + * + * Convert a SASL mechanism name into a token. + * + * Parameters: + * + * ptr [in] - The mechanism string. + * maxlen [in] - Maximum mechanism string length. + * len [out] - If not NULL, effective name length. + * + * Returns the SASL mechanism token or 0 if no match. + */ +unsigned int Curl_sasl_decode_mech(const char *ptr, size_t maxlen, size_t *len) +{ + unsigned int i; + char c; + + for(i = 0; mechtable[i].name; i++) { + if(maxlen >= mechtable[i].len && + !memcmp(ptr, mechtable[i].name, mechtable[i].len)) { + if(len) + *len = mechtable[i].len; + + if(maxlen == mechtable[i].len) + return mechtable[i].bit; + + c = ptr[mechtable[i].len]; + if(!ISUPPER(c) && !ISDIGIT(c) && c != '-' && c != '_') + return mechtable[i].bit; + } + } + + return 0; +} + +/* + * Curl_sasl_parse_url_auth_option() + * + * Parse the URL login options. + */ +CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl, + const char *value, size_t len) +{ + CURLcode result = CURLE_OK; + size_t mechlen; + + if(!len) + return CURLE_URL_MALFORMAT; + + if(sasl->resetprefs) { + sasl->resetprefs = FALSE; + sasl->prefmech = SASL_AUTH_NONE; + } + + if(!strncmp(value, "*", len)) + sasl->prefmech = SASL_AUTH_DEFAULT; + else { + unsigned int mechbit = Curl_sasl_decode_mech(value, len, &mechlen); + if(mechbit && mechlen == len) + sasl->prefmech |= mechbit; + else + result = CURLE_URL_MALFORMAT; + } + + return result; +} + +/* + * Curl_sasl_init() + * + * Initializes the SASL structure. + */ +void Curl_sasl_init(struct SASL *sasl, const struct SASLproto *params) +{ + sasl->params = params; /* Set protocol dependent parameters */ + sasl->state = SASL_STOP; /* Not yet running */ + sasl->authmechs = SASL_AUTH_NONE; /* No known authentication mechanism yet */ + sasl->prefmech = SASL_AUTH_DEFAULT; /* Prefer all mechanisms */ + sasl->authused = SASL_AUTH_NONE; /* No the authentication mechanism used */ + sasl->resetprefs = TRUE; /* Reset prefmech upon AUTH parsing. */ + sasl->mutual_auth = FALSE; /* No mutual authentication (GSSAPI only) */ + sasl->force_ir = FALSE; /* Respect external option */ +} + +/* + * state() + * + * This is the ONLY way to change SASL state! + */ +static void state(struct SASL *sasl, struct connectdata *conn, + saslstate newstate) +{ +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* for debug purposes */ + static const char * const names[]={ + "STOP", + "PLAIN", + "LOGIN", + "LOGIN_PASSWD", + "EXTERNAL", + "CRAMMD5", + "DIGESTMD5", + "DIGESTMD5_RESP", + "NTLM", + "NTLM_TYPE2MSG", + "GSSAPI", + "GSSAPI_TOKEN", + "GSSAPI_NO_DATA", + "OAUTH2", + "OAUTH2_RESP", + "CANCEL", + "FINAL", + /* LAST */ + }; + + if(sasl->state != newstate) + infof(conn->data, "SASL %p state change from %s to %s\n", + (void *)sasl, names[sasl->state], names[newstate]); +#else + (void) conn; +#endif + + sasl->state = newstate; +} + +/* + * Curl_sasl_can_authenticate() + * + * Check if we have enough auth data and capabilities to authenticate. + */ +bool Curl_sasl_can_authenticate(struct SASL *sasl, struct connectdata *conn) +{ + /* Have credentials been provided? */ + if(conn->bits.user_passwd) + return TRUE; + + /* EXTERNAL can authenticate without a user name and/or password */ + if(sasl->authmechs & sasl->prefmech & SASL_MECH_EXTERNAL) + return TRUE; + + return FALSE; +} + +/* + * Curl_sasl_start() + * + * Calculate the required login details for SASL authentication. + */ +CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn, + bool force_ir, saslprogress *progress) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + unsigned int enabledmechs; + const char *mech = NULL; + char *resp = NULL; + size_t len = 0; + saslstate state1 = SASL_STOP; + saslstate state2 = SASL_FINAL; + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; +#if defined(USE_KERBEROS5) || defined(USE_NTLM) + const char *service = data->set.str[STRING_SERVICE_NAME] ? + data->set.str[STRING_SERVICE_NAME] : + sasl->params->service; +#endif + + sasl->force_ir = force_ir; /* Latch for future use */ + sasl->authused = 0; /* No mechanism used yet */ + enabledmechs = sasl->authmechs & sasl->prefmech; + *progress = SASL_IDLE; + + /* Calculate the supported authentication mechanism, by decreasing order of + security, as well as the initial response where appropriate */ + if((enabledmechs & SASL_MECH_EXTERNAL) && !conn->passwd[0]) { + mech = SASL_MECH_STRING_EXTERNAL; + state1 = SASL_EXTERNAL; + sasl->authused = SASL_MECH_EXTERNAL; + + if(force_ir || data->set.sasl_ir) + result = Curl_auth_create_external_message(data, conn->user, &resp, + &len); + } + else if(conn->bits.user_passwd) { +#if defined(USE_KERBEROS5) + if((enabledmechs & SASL_MECH_GSSAPI) && Curl_auth_is_gssapi_supported() && + Curl_auth_user_contains_domain(conn->user)) { + sasl->mutual_auth = FALSE; + mech = SASL_MECH_STRING_GSSAPI; + state1 = SASL_GSSAPI; + state2 = SASL_GSSAPI_TOKEN; + sasl->authused = SASL_MECH_GSSAPI; + + if(force_ir || data->set.sasl_ir) + result = Curl_auth_create_gssapi_user_message(data, conn->user, + conn->passwd, + service, + data->conn->host.name, + sasl->mutual_auth, + NULL, &conn->krb5, + &resp, &len); + } + else +#endif +#ifndef CURL_DISABLE_CRYPTO_AUTH + if((enabledmechs & SASL_MECH_DIGEST_MD5) && + Curl_auth_is_digest_supported()) { + mech = SASL_MECH_STRING_DIGEST_MD5; + state1 = SASL_DIGESTMD5; + sasl->authused = SASL_MECH_DIGEST_MD5; + } + else if(enabledmechs & SASL_MECH_CRAM_MD5) { + mech = SASL_MECH_STRING_CRAM_MD5; + state1 = SASL_CRAMMD5; + sasl->authused = SASL_MECH_CRAM_MD5; + } + else +#endif +#ifdef USE_NTLM + if((enabledmechs & SASL_MECH_NTLM) && Curl_auth_is_ntlm_supported()) { + mech = SASL_MECH_STRING_NTLM; + state1 = SASL_NTLM; + state2 = SASL_NTLM_TYPE2MSG; + sasl->authused = SASL_MECH_NTLM; + + if(force_ir || data->set.sasl_ir) + result = Curl_auth_create_ntlm_type1_message(data, + conn->user, conn->passwd, + service, + hostname, + &conn->ntlm, &resp, + &len); + } + else +#endif + if((enabledmechs & SASL_MECH_OAUTHBEARER) && conn->oauth_bearer) { + mech = SASL_MECH_STRING_OAUTHBEARER; + state1 = SASL_OAUTH2; + state2 = SASL_OAUTH2_RESP; + sasl->authused = SASL_MECH_OAUTHBEARER; + + if(force_ir || data->set.sasl_ir) + result = Curl_auth_create_oauth_bearer_message(data, conn->user, + hostname, + port, + conn->oauth_bearer, + &resp, &len); + } + else if((enabledmechs & SASL_MECH_XOAUTH2) && conn->oauth_bearer) { + mech = SASL_MECH_STRING_XOAUTH2; + state1 = SASL_OAUTH2; + sasl->authused = SASL_MECH_XOAUTH2; + + if(force_ir || data->set.sasl_ir) + result = Curl_auth_create_xoauth_bearer_message(data, conn->user, + conn->oauth_bearer, + &resp, &len); + } + else if(enabledmechs & SASL_MECH_PLAIN) { + mech = SASL_MECH_STRING_PLAIN; + state1 = SASL_PLAIN; + sasl->authused = SASL_MECH_PLAIN; + + if(force_ir || data->set.sasl_ir) + result = Curl_auth_create_plain_message(data, NULL, conn->user, + conn->passwd, &resp, &len); + } + else if(enabledmechs & SASL_MECH_LOGIN) { + mech = SASL_MECH_STRING_LOGIN; + state1 = SASL_LOGIN; + state2 = SASL_LOGIN_PASSWD; + sasl->authused = SASL_MECH_LOGIN; + + if(force_ir || data->set.sasl_ir) + result = Curl_auth_create_login_message(data, conn->user, &resp, &len); + } + } + + if(!result && mech) { + if(resp && sasl->params->maxirlen && + strlen(mech) + len > sasl->params->maxirlen) { + free(resp); + resp = NULL; + } + + result = sasl->params->sendauth(conn, mech, resp); + if(!result) { + *progress = SASL_INPROGRESS; + state(sasl, conn, resp ? state2 : state1); + } + } + + free(resp); + + return result; +} + +/* + * Curl_sasl_continue() + * + * Continue the authentication. + */ +CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn, + int code, saslprogress *progress) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + saslstate newstate = SASL_FINAL; + char *resp = NULL; + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; +#if !defined(CURL_DISABLE_CRYPTO_AUTH) + char *chlg = NULL; + size_t chlglen = 0; +#endif +#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \ + defined(USE_NTLM) + const char *service = data->set.str[STRING_SERVICE_NAME] ? + data->set.str[STRING_SERVICE_NAME] : + sasl->params->service; + char *serverdata; +#endif + size_t len = 0; + + *progress = SASL_INPROGRESS; + + if(sasl->state == SASL_FINAL) { + if(code != sasl->params->finalcode) + result = CURLE_LOGIN_DENIED; + *progress = SASL_DONE; + state(sasl, conn, SASL_STOP); + return result; + } + + if(sasl->state != SASL_CANCEL && sasl->state != SASL_OAUTH2_RESP && + code != sasl->params->contcode) { + *progress = SASL_DONE; + state(sasl, conn, SASL_STOP); + return CURLE_LOGIN_DENIED; + } + + switch(sasl->state) { + case SASL_STOP: + *progress = SASL_DONE; + return result; + case SASL_PLAIN: + result = Curl_auth_create_plain_message(data, NULL, conn->user, + conn->passwd, &resp, &len); + break; + case SASL_LOGIN: + result = Curl_auth_create_login_message(data, conn->user, &resp, &len); + newstate = SASL_LOGIN_PASSWD; + break; + case SASL_LOGIN_PASSWD: + result = Curl_auth_create_login_message(data, conn->passwd, &resp, &len); + break; + case SASL_EXTERNAL: + result = Curl_auth_create_external_message(data, conn->user, &resp, &len); + break; + +#ifndef CURL_DISABLE_CRYPTO_AUTH + case SASL_CRAMMD5: + sasl->params->getmessage(data->state.buffer, &serverdata); + result = Curl_auth_decode_cram_md5_message(serverdata, &chlg, &chlglen); + if(!result) + result = Curl_auth_create_cram_md5_message(data, chlg, conn->user, + conn->passwd, &resp, &len); + free(chlg); + break; + case SASL_DIGESTMD5: + sasl->params->getmessage(data->state.buffer, &serverdata); + result = Curl_auth_create_digest_md5_message(data, serverdata, + conn->user, conn->passwd, + service, + &resp, &len); + newstate = SASL_DIGESTMD5_RESP; + break; + case SASL_DIGESTMD5_RESP: + resp = strdup(""); + if(!resp) + result = CURLE_OUT_OF_MEMORY; + break; +#endif + +#ifdef USE_NTLM + case SASL_NTLM: + /* Create the type-1 message */ + result = Curl_auth_create_ntlm_type1_message(data, + conn->user, conn->passwd, + service, hostname, + &conn->ntlm, &resp, &len); + newstate = SASL_NTLM_TYPE2MSG; + break; + case SASL_NTLM_TYPE2MSG: + /* Decode the type-2 message */ + sasl->params->getmessage(data->state.buffer, &serverdata); + result = Curl_auth_decode_ntlm_type2_message(data, serverdata, + &conn->ntlm); + if(!result) + result = Curl_auth_create_ntlm_type3_message(data, conn->user, + conn->passwd, &conn->ntlm, + &resp, &len); + break; +#endif + +#if defined(USE_KERBEROS5) + case SASL_GSSAPI: + result = Curl_auth_create_gssapi_user_message(data, conn->user, + conn->passwd, + service, + data->conn->host.name, + sasl->mutual_auth, NULL, + &conn->krb5, + &resp, &len); + newstate = SASL_GSSAPI_TOKEN; + break; + case SASL_GSSAPI_TOKEN: + sasl->params->getmessage(data->state.buffer, &serverdata); + if(sasl->mutual_auth) { + /* Decode the user token challenge and create the optional response + message */ + result = Curl_auth_create_gssapi_user_message(data, NULL, NULL, + NULL, NULL, + sasl->mutual_auth, + serverdata, &conn->krb5, + &resp, &len); + newstate = SASL_GSSAPI_NO_DATA; + } + else + /* Decode the security challenge and create the response message */ + result = Curl_auth_create_gssapi_security_message(data, serverdata, + &conn->krb5, + &resp, &len); + break; + case SASL_GSSAPI_NO_DATA: + sasl->params->getmessage(data->state.buffer, &serverdata); + /* Decode the security challenge and create the response message */ + result = Curl_auth_create_gssapi_security_message(data, serverdata, + &conn->krb5, + &resp, &len); + break; +#endif + + case SASL_OAUTH2: + /* Create the authorisation message */ + if(sasl->authused == SASL_MECH_OAUTHBEARER) { + result = Curl_auth_create_oauth_bearer_message(data, conn->user, + hostname, + port, + conn->oauth_bearer, + &resp, &len); + + /* Failures maybe sent by the server as continuations for OAUTHBEARER */ + newstate = SASL_OAUTH2_RESP; + } + else + result = Curl_auth_create_xoauth_bearer_message(data, conn->user, + conn->oauth_bearer, + &resp, &len); + break; + + case SASL_OAUTH2_RESP: + /* The continuation is optional so check the response code */ + if(code == sasl->params->finalcode) { + /* Final response was received so we are done */ + *progress = SASL_DONE; + state(sasl, conn, SASL_STOP); + return result; + } + else if(code == sasl->params->contcode) { + /* Acknowledge the continuation by sending a 0x01 response base64 + encoded */ + resp = strdup("AQ=="); + if(!resp) + result = CURLE_OUT_OF_MEMORY; + break; + } + else { + *progress = SASL_DONE; + state(sasl, conn, SASL_STOP); + return CURLE_LOGIN_DENIED; + } + + case SASL_CANCEL: + /* Remove the offending mechanism from the supported list */ + sasl->authmechs ^= sasl->authused; + + /* Start an alternative SASL authentication */ + result = Curl_sasl_start(sasl, conn, sasl->force_ir, progress); + newstate = sasl->state; /* Use state from Curl_sasl_start() */ + break; + default: + failf(data, "Unsupported SASL authentication mechanism"); + result = CURLE_UNSUPPORTED_PROTOCOL; /* Should not happen */ + break; + } + + switch(result) { + case CURLE_BAD_CONTENT_ENCODING: + /* Cancel dialog */ + result = sasl->params->sendcont(conn, "*"); + newstate = SASL_CANCEL; + break; + case CURLE_OK: + if(resp) + result = sasl->params->sendcont(conn, resp); + break; + default: + newstate = SASL_STOP; /* Stop on error */ + *progress = SASL_DONE; + break; + } + + free(resp); + + state(sasl, conn, newstate); + + return result; +} +#endif /* protocols are enabled that use SASL */ diff --git a/dependencies/cmcurl/lib/curl_sasl.h b/dependencies/cmcurl/lib/curl_sasl.h new file mode 100644 index 0000000..7647a48 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_sasl.h @@ -0,0 +1,143 @@ +#ifndef HEADER_CURL_SASL_H +#define HEADER_CURL_SASL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +struct Curl_easy; +struct connectdata; + +/* Authentication mechanism flags */ +#define SASL_MECH_LOGIN (1 << 0) +#define SASL_MECH_PLAIN (1 << 1) +#define SASL_MECH_CRAM_MD5 (1 << 2) +#define SASL_MECH_DIGEST_MD5 (1 << 3) +#define SASL_MECH_GSSAPI (1 << 4) +#define SASL_MECH_EXTERNAL (1 << 5) +#define SASL_MECH_NTLM (1 << 6) +#define SASL_MECH_XOAUTH2 (1 << 7) +#define SASL_MECH_OAUTHBEARER (1 << 8) + +/* Authentication mechanism values */ +#define SASL_AUTH_NONE 0 +#define SASL_AUTH_ANY ~0U +#define SASL_AUTH_DEFAULT (SASL_AUTH_ANY & ~SASL_MECH_EXTERNAL) + +/* Authentication mechanism strings */ +#define SASL_MECH_STRING_LOGIN "LOGIN" +#define SASL_MECH_STRING_PLAIN "PLAIN" +#define SASL_MECH_STRING_CRAM_MD5 "CRAM-MD5" +#define SASL_MECH_STRING_DIGEST_MD5 "DIGEST-MD5" +#define SASL_MECH_STRING_GSSAPI "GSSAPI" +#define SASL_MECH_STRING_EXTERNAL "EXTERNAL" +#define SASL_MECH_STRING_NTLM "NTLM" +#define SASL_MECH_STRING_XOAUTH2 "XOAUTH2" +#define SASL_MECH_STRING_OAUTHBEARER "OAUTHBEARER" + +/* SASL machine states */ +typedef enum { + SASL_STOP, + SASL_PLAIN, + SASL_LOGIN, + SASL_LOGIN_PASSWD, + SASL_EXTERNAL, + SASL_CRAMMD5, + SASL_DIGESTMD5, + SASL_DIGESTMD5_RESP, + SASL_NTLM, + SASL_NTLM_TYPE2MSG, + SASL_GSSAPI, + SASL_GSSAPI_TOKEN, + SASL_GSSAPI_NO_DATA, + SASL_OAUTH2, + SASL_OAUTH2_RESP, + SASL_CANCEL, + SASL_FINAL +} saslstate; + +/* Progress indicator */ +typedef enum { + SASL_IDLE, + SASL_INPROGRESS, + SASL_DONE +} saslprogress; + +/* Protocol dependent SASL parameters */ +struct SASLproto { + const char *service; /* The service name */ + int contcode; /* Code to receive when continuation is expected */ + int finalcode; /* Code to receive upon authentication success */ + size_t maxirlen; /* Maximum initial response length */ + CURLcode (*sendauth)(struct connectdata *conn, + const char *mech, const char *ir); + /* Send authentication command */ + CURLcode (*sendcont)(struct connectdata *conn, const char *contauth); + /* Send authentication continuation */ + void (*getmessage)(char *buffer, char **outptr); + /* Get SASL response message */ +}; + +/* Per-connection parameters */ +struct SASL { + const struct SASLproto *params; /* Protocol dependent parameters */ + saslstate state; /* Current machine state */ + unsigned int authmechs; /* Accepted authentication mechanisms */ + unsigned int prefmech; /* Preferred authentication mechanism */ + unsigned int authused; /* Auth mechanism used for the connection */ + bool resetprefs; /* For URL auth option parsing. */ + bool mutual_auth; /* Mutual authentication enabled (GSSAPI only) */ + bool force_ir; /* Protocol always supports initial response */ +}; + +/* This is used to test whether the line starts with the given mechanism */ +#define sasl_mech_equal(line, wordlen, mech) \ + (wordlen == (sizeof(mech) - 1) / sizeof(char) && \ + !memcmp(line, mech, wordlen)) + +/* This is used to cleanup any libraries or curl modules used by the sasl + functions */ +void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused); + +/* Convert a mechanism name to a token */ +unsigned int Curl_sasl_decode_mech(const char *ptr, + size_t maxlen, size_t *len); + +/* Parse the URL login options */ +CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl, + const char *value, size_t len); + +/* Initializes an SASL structure */ +void Curl_sasl_init(struct SASL *sasl, const struct SASLproto *params); + +/* Check if we have enough auth data and capabilities to authenticate */ +bool Curl_sasl_can_authenticate(struct SASL *sasl, struct connectdata *conn); + +/* Calculate the required login details for SASL authentication */ +CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn, + bool force_ir, saslprogress *progress); + +/* Continue an SASL authentication */ +CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn, + int code, saslprogress *progress); + +#endif /* HEADER_CURL_SASL_H */ diff --git a/dependencies/cmcurl/lib/curl_sec.h b/dependencies/cmcurl/lib/curl_sec.h new file mode 100644 index 0000000..7bdde26 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_sec.h @@ -0,0 +1,51 @@ +#ifndef HEADER_CURL_SECURITY_H +#define HEADER_CURL_SECURITY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +struct Curl_sec_client_mech { + const char *name; + size_t size; + int (*init)(void *); + int (*auth)(void *, struct connectdata *); + void (*end)(void *); + int (*check_prot)(void *, int); + int (*overhead)(void *, int, int); + int (*encode)(void *, const void *, int, int, void **); + int (*decode)(void *, void *, int, int, struct connectdata *); +}; + +#define AUTH_OK 0 +#define AUTH_CONTINUE 1 +#define AUTH_ERROR 2 + +#ifdef HAVE_GSSAPI +int Curl_sec_read_msg(struct connectdata *conn, char *, + enum protection_level); +void Curl_sec_end(struct connectdata *); +CURLcode Curl_sec_login(struct connectdata *); +int Curl_sec_request_prot(struct connectdata *conn, const char *level); + +extern struct Curl_sec_client_mech Curl_krb5_client_mech; +#endif + +#endif /* HEADER_CURL_SECURITY_H */ diff --git a/dependencies/cmcurl/lib/curl_setup.h b/dependencies/cmcurl/lib/curl_setup.h new file mode 100644 index 0000000..efba5dd --- /dev/null +++ b/dependencies/cmcurl/lib/curl_setup.h @@ -0,0 +1,845 @@ +#ifndef HEADER_CURL_SETUP_H +#define HEADER_CURL_SETUP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#if defined(BUILDING_LIBCURL) && !defined(CURL_NO_OLDIES) +#define CURL_NO_OLDIES +#endif + +/* + * Define WIN32 when build target is Win32 API + */ + +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) && \ + !defined(__SYMBIAN32__) +#define WIN32 +#endif + +#ifdef WIN32 +/* + * Don't include unneeded stuff in Windows headers to avoid compiler + * warnings and macro clashes. + * Make sure to define this macro before including any Windows headers. + */ +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# ifndef NOGDI +# define NOGDI +# endif +#endif + +/* + * Include configuration script results or hand-crafted + * configuration file for platforms which lack config tool. + */ + +#ifdef HAVE_CONFIG_H + +#include "curl_config.h" + +#else /* HAVE_CONFIG_H */ + +#ifdef _WIN32_WCE +# include "config-win32ce.h" +#else +# ifdef WIN32 +# include "config-win32.h" +# endif +#endif + +#if defined(macintosh) && defined(__MRC__) +# include "config-mac.h" +#endif + +#ifdef __riscos__ +# include "config-riscos.h" +#endif + +#ifdef __AMIGA__ +# include "config-amigaos.h" +#endif + +#ifdef __SYMBIAN32__ +# include "config-symbian.h" +#endif + +#ifdef __OS400__ +# include "config-os400.h" +#endif + +#ifdef TPF +# include "config-tpf.h" +#endif + +#ifdef __VXWORKS__ +# include "config-vxworks.h" +#endif + +#endif /* HAVE_CONFIG_H */ + +#if defined(_MSC_VER) +# pragma warning(push,1) +#endif + +/* ================================================================ */ +/* Definition of preprocessor macros/symbols which modify compiler */ +/* behavior or generated code characteristics must be done here, */ +/* as appropriate, before any system header file is included. It is */ +/* also possible to have them defined in the config file included */ +/* before this point. As a result of all this we frown inclusion of */ +/* system header files in our config files, avoid this at any cost. */ +/* ================================================================ */ + +/* + * AIX 4.3 and newer needs _THREAD_SAFE defined to build + * proper reentrant code. Others may also need it. + */ + +#ifdef NEED_THREAD_SAFE +# ifndef _THREAD_SAFE +# define _THREAD_SAFE +# endif +#endif + +/* + * Tru64 needs _REENTRANT set for a few function prototypes and + * things to appear in the system header files. Unixware needs it + * to build proper reentrant code. Others may also need it. + */ + +#ifdef NEED_REENTRANT +# ifndef _REENTRANT +# define _REENTRANT +# endif +#endif + +/* Solaris needs this to get a POSIX-conformant getpwuid_r */ +#if defined(sun) || defined(__sun) +# ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +# endif +#endif + +/* ================================================================ */ +/* If you need to include a system header file for your platform, */ +/* please, do it beyond the point further indicated in this file. */ +/* ================================================================ */ + +#include + +#define CURL_SIZEOF_CURL_OFF_T SIZEOF_CURL_OFF_T + +/* + * Disable other protocols when http is the only one desired. + */ + +#ifdef HTTP_ONLY +# ifndef CURL_DISABLE_TFTP +# define CURL_DISABLE_TFTP +# endif +# ifndef CURL_DISABLE_FTP +# define CURL_DISABLE_FTP +# endif +# ifndef CURL_DISABLE_LDAP +# define CURL_DISABLE_LDAP +# endif +# ifndef CURL_DISABLE_TELNET +# define CURL_DISABLE_TELNET +# endif +# ifndef CURL_DISABLE_DICT +# define CURL_DISABLE_DICT +# endif +# ifndef CURL_DISABLE_FILE +# define CURL_DISABLE_FILE +# endif +# ifndef CURL_DISABLE_RTSP +# define CURL_DISABLE_RTSP +# endif +# ifndef CURL_DISABLE_POP3 +# define CURL_DISABLE_POP3 +# endif +# ifndef CURL_DISABLE_IMAP +# define CURL_DISABLE_IMAP +# endif +# ifndef CURL_DISABLE_SMTP +# define CURL_DISABLE_SMTP +# endif +# ifndef CURL_DISABLE_GOPHER +# define CURL_DISABLE_GOPHER +# endif +# ifndef CURL_DISABLE_SMB +# define CURL_DISABLE_SMB +# endif +#endif + +/* + * When http is disabled rtsp is not supported. + */ + +#if defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_RTSP) +# define CURL_DISABLE_RTSP +#endif + +/* ================================================================ */ +/* No system header file shall be included in this file before this */ +/* point. The only allowed ones are those included from curl/system.h */ +/* ================================================================ */ + +/* + * OS/400 setup file includes some system headers. + */ + +#ifdef __OS400__ +# include "setup-os400.h" +#endif + +/* + * VMS setup file includes some system headers. + */ + +#ifdef __VMS +# include "setup-vms.h" +#endif + +/* + * Use getaddrinfo to resolve the IPv4 address literal. If the current network + * interface doesn't support IPv4, but supports IPv6, NAT64, and DNS64, + * performing this task will result in a synthesized IPv6 address. + */ +#ifdef __APPLE__ +#define USE_RESOLVE_ON_IPS 1 +#endif + +/* + * Include header files for windows builds before redefining anything. + * Use this preprocessor block only to include or exclude windows.h, + * winsock2.h, ws2tcpip.h or winsock.h. Any other windows thing belongs + * to any other further and independent block. Under Cygwin things work + * just as under linux (e.g. ) and the winsock headers should + * never be included when __CYGWIN__ is defined. configure script takes + * care of this, not defining HAVE_WINDOWS_H, HAVE_WINSOCK_H, HAVE_WINSOCK2_H, + * neither HAVE_WS2TCPIP_H when __CYGWIN__ is defined. + */ + +#ifdef HAVE_WINDOWS_H +# if defined(UNICODE) && !defined(_UNICODE) +# define _UNICODE +# endif +# if defined(_UNICODE) && !defined(UNICODE) +# define UNICODE +# endif +# include +# include +# ifdef HAVE_WINSOCK2_H +# include +# ifdef HAVE_WS2TCPIP_H +# include +# endif +# else +# ifdef HAVE_WINSOCK_H +# include +# endif +# endif +# include +# ifdef UNICODE + typedef wchar_t *(*curl_wcsdup_callback)(const wchar_t *str); +# endif +#endif + +/* + * Define USE_WINSOCK to 2 if we have and use WINSOCK2 API, else + * define USE_WINSOCK to 1 if we have and use WINSOCK API, else + * undefine USE_WINSOCK. + */ + +#undef USE_WINSOCK + +#ifdef HAVE_WINSOCK2_H +# define USE_WINSOCK 2 +#else +# ifdef HAVE_WINSOCK_H +# define USE_WINSOCK 1 +# endif +#endif + +#ifdef USE_LWIPSOCK +# include +# include +# include +#endif + +#ifdef HAVE_EXTRA_STRICMP_H +# include +#endif + +#ifdef HAVE_EXTRA_STRDUP_H +# include +#endif + +#ifdef TPF +# include /* for bzero, strcasecmp, and strncasecmp */ +# include /* for strcpy and strlen */ +# include /* for rand and srand */ +# include /* for select and ioctl*/ +# include /* for in_addr_t definition */ +# include /* for tpf_process_signals */ + /* change which select is used for libcurl */ +# define select(a,b,c,d,e) tpf_select_libcurl(a,b,c,d,e) +#endif + +#ifdef __VXWORKS__ +# include /* for generic BSD socket functions */ +# include /* for basic I/O interface functions */ +#endif + +#ifdef __AMIGA__ +# include +# include +# include +# include +# ifdef HAVE_PROTO_BSDSOCKET_H +# include /* ensure bsdsocket.library use */ +# define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,0) +# endif +#endif + +#include +#ifdef HAVE_ASSERT_H +#include +#endif + +#ifdef __TANDEM /* for nsr-tandem-nsk systems */ +#include +#endif + +#ifndef STDC_HEADERS /* no standard C headers! */ +#include +#endif + +#ifdef __POCC__ +# include +# include +# define sys_nerr EILSEQ +#endif + +/* + * Salford-C kludge section (mostly borrowed from wxWidgets). + */ +#ifdef __SALFORDC__ + #pragma suppress 353 /* Possible nested comments */ + #pragma suppress 593 /* Define not used */ + #pragma suppress 61 /* enum has no name */ + #pragma suppress 106 /* unnamed, unused parameter */ + #include +#endif + +/* Default Windows file API selection. */ +#ifdef _WIN32 +# if defined(_MSC_VER) && (_INTEGRAL_MAX_BITS >= 64) +# define USE_WIN32_LARGE_FILES +# elif defined(__MINGW32__) +# define USE_WIN32_LARGE_FILES +# else +# define USE_WIN32_SMALL_FILES +# endif +#endif + +/* + * Large file (>2Gb) support using WIN32 functions. + */ + +#ifdef USE_WIN32_LARGE_FILES +# include +# include +# include +# undef lseek +# define lseek(fdes,offset,whence) _lseeki64(fdes, offset, whence) +# undef fstat +# define fstat(fdes,stp) _fstati64(fdes, stp) +# undef stat +# define stat(fname,stp) _stati64(fname, stp) +# define struct_stat struct _stati64 +# define LSEEK_ERROR (__int64)-1 +#endif + +/* + * Small file (<2Gb) support using WIN32 functions. + */ + +#ifdef USE_WIN32_SMALL_FILES +# include +# include +# include +# ifndef _WIN32_WCE +# undef lseek +# define lseek(fdes,offset,whence) _lseek(fdes, (long)offset, whence) +# define fstat(fdes,stp) _fstat(fdes, stp) +# define stat(fname,stp) _stat(fname, stp) +# define struct_stat struct _stat +# endif +# define LSEEK_ERROR (long)-1 +#endif + +#ifndef struct_stat +# define struct_stat struct stat +#endif + +#ifndef LSEEK_ERROR +# define LSEEK_ERROR (off_t)-1 +#endif + +#ifndef SIZEOF_TIME_T +/* assume default size of time_t to be 32 bit */ +#define SIZEOF_TIME_T 4 +#endif + +/* + * Default sizeof(off_t) in case it hasn't been defined in config file. + */ + +#ifndef SIZEOF_OFF_T +# if defined(__VMS) && !defined(__VAX) +# if defined(_LARGEFILE) +# define SIZEOF_OFF_T 8 +# endif +# elif defined(__OS400__) && defined(__ILEC400__) +# if defined(_LARGE_FILES) +# define SIZEOF_OFF_T 8 +# endif +# elif defined(__MVS__) && defined(__IBMC__) +# if defined(_LP64) || defined(_LARGE_FILES) +# define SIZEOF_OFF_T 8 +# endif +# elif defined(__370__) && defined(__IBMC__) +# if defined(_LP64) || defined(_LARGE_FILES) +# define SIZEOF_OFF_T 8 +# endif +# endif +# ifndef SIZEOF_OFF_T +# define SIZEOF_OFF_T 4 +# endif +#endif + +#if (SIZEOF_CURL_OFF_T == 4) +# define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFF) +#else + /* assume CURL_SIZEOF_CURL_OFF_T == 8 */ +# define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFFFFFFFFFF) +#endif +#define CURL_OFF_T_MIN (-CURL_OFF_T_MAX - CURL_OFF_T_C(1)) + +#if (SIZEOF_TIME_T == 4) +# ifdef HAVE_TIME_T_UNSIGNED +# define TIME_T_MAX UINT_MAX +# define TIME_T_MIN 0 +# else +# define TIME_T_MAX INT_MAX +# define TIME_T_MIN INT_MIN +# endif +#else +# ifdef HAVE_TIME_T_UNSIGNED +# define TIME_T_MAX 0xFFFFFFFFFFFFFFFF +# define TIME_T_MIN 0 +# else +# define TIME_T_MAX 0x7FFFFFFFFFFFFFFF +# define TIME_T_MIN (-TIME_T_MAX - 1) +# endif +#endif + +#ifndef SIZE_T_MAX +/* some limits.h headers have this defined, some don't */ +#if defined(SIZEOF_SIZE_T) && (SIZEOF_SIZE_T > 4) +#define SIZE_T_MAX 18446744073709551615U +#else +#define SIZE_T_MAX 4294967295U +#endif +#endif + +/* + * Arg 2 type for gethostname in case it hasn't been defined in config file. + */ + +#ifndef GETHOSTNAME_TYPE_ARG2 +# ifdef USE_WINSOCK +# define GETHOSTNAME_TYPE_ARG2 int +# else +# define GETHOSTNAME_TYPE_ARG2 size_t +# endif +#endif + +/* Below we define some functions. They should + + 4. set the SIGALRM signal timeout + 5. set dir/file naming defines + */ + +#ifdef WIN32 + +# define DIR_CHAR "\\" +# define DOT_CHAR "_" + +#else /* WIN32 */ + +# ifdef MSDOS /* Watt-32 */ + +# include +# define select(n,r,w,x,t) select_s(n,r,w,x,t) +# define ioctl(x,y,z) ioctlsocket(x,y,(char *)(z)) +# include +# ifdef word +# undef word +# endif +# ifdef byte +# undef byte +# endif + +# endif /* MSDOS */ + +# ifdef __minix + /* Minix 3 versions up to at least 3.1.3 are missing these prototypes */ + extern char *strtok_r(char *s, const char *delim, char **last); + extern struct tm *gmtime_r(const time_t * const timep, struct tm *tmp); +# endif + +# define DIR_CHAR "/" +# ifndef DOT_CHAR +# define DOT_CHAR "." +# endif + +# ifdef MSDOS +# undef DOT_CHAR +# define DOT_CHAR "_" +# endif + +# ifndef fileno /* sunos 4 have this as a macro! */ + int fileno(FILE *stream); +# endif + +#endif /* WIN32 */ + +/* + * msvc 6.0 requires PSDK in order to have INET6_ADDRSTRLEN + * defined in ws2tcpip.h as well as to provide IPv6 support. + * Does not apply if lwIP is used. + */ + +#if defined(_MSC_VER) && !defined(__POCC__) && !defined(USE_LWIPSOCK) +# if !defined(HAVE_WS2TCPIP_H) || \ + ((_MSC_VER < 1300) && !defined(INET6_ADDRSTRLEN)) +# undef HAVE_GETADDRINFO_THREADSAFE +# undef HAVE_FREEADDRINFO +# undef HAVE_GETADDRINFO +# undef HAVE_GETNAMEINFO +# undef ENABLE_IPV6 +# endif +#endif + +/* ---------------------------------------------------------------- */ +/* resolver specialty compile-time defines */ +/* CURLRES_* defines to use in the host*.c sources */ +/* ---------------------------------------------------------------- */ + +/* + * lcc-win32 doesn't have _beginthreadex(), lacks threads support. + */ + +#if defined(__LCC__) && defined(WIN32) +# undef USE_THREADS_POSIX +# undef USE_THREADS_WIN32 +#endif + +/* + * MSVC threads support requires a multi-threaded runtime library. + * _beginthreadex() is not available in single-threaded ones. + */ + +#if defined(_MSC_VER) && !defined(__POCC__) && !defined(_MT) +# undef USE_THREADS_POSIX +# undef USE_THREADS_WIN32 +#endif + +/* + * Mutually exclusive CURLRES_* definitions. + */ + +#ifdef USE_ARES +# define CURLRES_ASYNCH +# define CURLRES_ARES +/* now undef the stock libc functions just to avoid them being used */ +# undef HAVE_GETADDRINFO +# undef HAVE_FREEADDRINFO +# undef HAVE_GETHOSTBYNAME +#elif defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) +# define CURLRES_ASYNCH +# define CURLRES_THREADED +#else +# define CURLRES_SYNCH +#endif + +#ifdef ENABLE_IPV6 +# define CURLRES_IPV6 +#else +# define CURLRES_IPV4 +#endif + +/* ---------------------------------------------------------------- */ + +/* + * When using WINSOCK, TELNET protocol requires WINSOCK2 API. + */ + +#if defined(USE_WINSOCK) && (USE_WINSOCK != 2) +# define CURL_DISABLE_TELNET 1 +#endif + +/* + * msvc 6.0 does not have struct sockaddr_storage and + * does not define IPPROTO_ESP in winsock2.h. But both + * are available if PSDK is properly installed. + */ + +#if defined(_MSC_VER) && !defined(__POCC__) +# if !defined(HAVE_WINSOCK2_H) || ((_MSC_VER < 1300) && !defined(IPPROTO_ESP)) +# undef HAVE_STRUCT_SOCKADDR_STORAGE +# endif +#endif + +/* + * Intentionally fail to build when using msvc 6.0 without PSDK installed. + * The brave of heart can circumvent this, defining ALLOW_MSVC6_WITHOUT_PSDK + * in lib/config-win32.h although absolutely discouraged and unsupported. + */ + +#if defined(_MSC_VER) && !defined(__POCC__) +# if !defined(HAVE_WINDOWS_H) || ((_MSC_VER < 1300) && !defined(_FILETIME_)) +# if !defined(ALLOW_MSVC6_WITHOUT_PSDK) +# error MSVC 6.0 requires "February 2003 Platform SDK" a.k.a. \ + "Windows Server 2003 PSDK" +# else +# define CURL_DISABLE_LDAP 1 +# endif +# endif +#endif + +#ifdef NETWARE +int netware_init(void); +#ifndef __NOVELL_LIBC__ +#include +#include +#endif +#endif + +#if defined(HAVE_LIBIDN2) && defined(HAVE_IDN2_H) && !defined(USE_WIN32_IDN) +/* The lib and header are present */ +#define USE_LIBIDN2 +#endif + +#if defined(USE_LIBIDN2) && defined(USE_WIN32_IDN) +#error "Both libidn2 and WinIDN are enabled, choose one." +#endif + +#define LIBIDN_REQUIRED_VERSION "0.4.1" + +#if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_NSS) || \ + defined(USE_POLARSSL) || defined(USE_MBEDTLS) || \ + defined(USE_CYASSL) || defined(USE_SCHANNEL) || \ + defined(USE_SECTRANSP) || defined(USE_GSKIT) || defined(USE_MESALINK) +#define USE_SSL /* SSL support has been enabled */ +#endif + +/* Single point where USE_SPNEGO definition might be defined */ +#if !defined(CURL_DISABLE_CRYPTO_AUTH) && \ + (defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)) +#define USE_SPNEGO +#endif + +/* Single point where USE_KERBEROS5 definition might be defined */ +#if !defined(CURL_DISABLE_CRYPTO_AUTH) && \ + (defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)) +#define USE_KERBEROS5 +#endif + +/* Single point where USE_NTLM definition might be defined */ +#if !defined(CURL_DISABLE_NTLM) && !defined(CURL_DISABLE_CRYPTO_AUTH) +#if defined(USE_OPENSSL) || defined(USE_WINDOWS_SSPI) || \ + defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_SECTRANSP) || \ + defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \ + defined(USE_MBEDTLS) + +#define USE_NTLM + +# if defined(USE_MBEDTLS) +/* Get definition of MBEDTLS_MD4_C */ +# include +# endif + +#endif +#endif + +#ifdef CURL_WANTS_CA_BUNDLE_ENV +#error "No longer supported. Set CURLOPT_CAINFO at runtime instead." +#endif + +#if defined(USE_LIBSSH2) || defined(USE_LIBSSH) || defined(USE_WOLFSSH) +#define USE_SSH +#endif + +/* + * Provide a mechanism to silence picky compilers, such as gcc 4.6+. + * Parameters should of course normally not be unused, but for example when + * we have multiple implementations of the same interface it may happen. + */ + +#if defined(__GNUC__) && ((__GNUC__ >= 3) || \ + ((__GNUC__ == 2) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 7))) +# define UNUSED_PARAM __attribute__((__unused__)) +# define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +#else +# define UNUSED_PARAM /*NOTHING*/ +# define WARN_UNUSED_RESULT +#endif + +/* + * Include macros and defines that should only be processed once. + */ + +#ifndef HEADER_CURL_SETUP_ONCE_H +#include "curl_setup_once.h" +#endif + +/* + * Definition of our NOP statement Object-like macro + */ + +#ifndef Curl_nop_stmt +# define Curl_nop_stmt do { } WHILE_FALSE +#endif + +/* + * Ensure that Winsock and lwIP TCP/IP stacks are not mixed. + */ + +#if defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H) +# if defined(SOCKET) || \ + defined(USE_WINSOCK) || \ + defined(HAVE_WINSOCK_H) || \ + defined(HAVE_WINSOCK2_H) || \ + defined(HAVE_WS2TCPIP_H) +# error "Winsock and lwIP TCP/IP stack definitions shall not coexist!" +# endif +#endif + +/* + * Portable symbolic names for Winsock shutdown() mode flags. + */ + +#ifdef USE_WINSOCK +# define SHUT_RD 0x00 +# define SHUT_WR 0x01 +# define SHUT_RDWR 0x02 +#endif + +/* Define S_ISREG if not defined by system headers, f.e. MSVC */ +#if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG) +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#endif + +/* Define S_ISDIR if not defined by system headers, f.e. MSVC */ +#if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#endif + +/* In Windows the default file mode is text but an application can override it. +Therefore we specify it explicitly. https://github.com/curl/curl/pull/258 +*/ +#if defined(WIN32) || defined(MSDOS) +#define FOPEN_READTEXT "rt" +#define FOPEN_WRITETEXT "wt" +#define FOPEN_APPENDTEXT "at" +#elif defined(__CYGWIN__) +/* Cygwin has specific behavior we need to address when WIN32 is not defined. +https://cygwin.com/cygwin-ug-net/using-textbinary.html +For write we want our output to have line endings of LF and be compatible with +other Cygwin utilities. For read we want to handle input that may have line +endings either CRLF or LF so 't' is appropriate. +*/ +#define FOPEN_READTEXT "rt" +#define FOPEN_WRITETEXT "w" +#define FOPEN_APPENDTEXT "a" +#else +#define FOPEN_READTEXT "r" +#define FOPEN_WRITETEXT "w" +#define FOPEN_APPENDTEXT "a" +#endif + +/* WinSock destroys recv() buffer when send() failed. + * Enabled automatically for Windows and for Cygwin as Cygwin sockets are + * wrappers for WinSock sockets. https://github.com/curl/curl/issues/657 + * Define DONT_USE_RECV_BEFORE_SEND_WORKAROUND to force disable workaround. + */ +#if !defined(DONT_USE_RECV_BEFORE_SEND_WORKAROUND) +# if defined(WIN32) || defined(__CYGWIN__) +# define USE_RECV_BEFORE_SEND_WORKAROUND +# endif +#else /* DONT_USE_RECV_BEFORE_SEND_WORKAROUND */ +# ifdef USE_RECV_BEFORE_SEND_WORKAROUND +# undef USE_RECV_BEFORE_SEND_WORKAROUND +# endif +#endif /* DONT_USE_RECV_BEFORE_SEND_WORKAROUND */ + +/* Detect Windows App environment which has a restricted access + * to the Win32 APIs. */ +# if (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)) || \ + defined(WINAPI_FAMILY) +# include +# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \ + !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +# define CURL_WINDOWS_APP +# endif +# endif + +/* for systems that don't detect this in configure, use a sensible default */ +#ifndef CURL_SA_FAMILY_T +#define CURL_SA_FAMILY_T unsigned short +#endif + +/* Some convenience macros to get the larger/smaller value out of two given. + We prefix with CURL to prevent name collisions. */ +#define CURLMAX(x,y) ((x)>(y)?(x):(y)) +#define CURLMIN(x,y) ((x)<(y)?(x):(y)) + +/* Some versions of the Android SDK is missing the declaration */ +#if defined(HAVE_GETPWUID_R) && defined(HAVE_DECL_GETPWUID_R_MISSING) +struct passwd; +int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, + size_t buflen, struct passwd **result); +#endif + +#ifdef DEBUGBUILD +#define UNITTEST +#else +#define UNITTEST static +#endif + +#endif /* HEADER_CURL_SETUP_H */ diff --git a/dependencies/cmcurl/lib/curl_setup_once.h b/dependencies/cmcurl/lib/curl_setup_once.h new file mode 100644 index 0000000..413ccea --- /dev/null +++ b/dependencies/cmcurl/lib/curl_setup_once.h @@ -0,0 +1,517 @@ +#ifndef HEADER_CURL_SETUP_ONCE_H +#define HEADER_CURL_SETUP_ONCE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + + +/* + * Inclusion of common header files. + */ + +#include +#include +#include +#include +#include + +#ifdef HAVE_ERRNO_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef NEED_MALLOC_H +#include +#endif + +#ifdef NEED_MEMORY_H +#include +#endif + +#ifdef HAVE_SYS_STAT_H +#include +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#ifdef TIME_WITH_SYS_TIME +#include +#endif +#else +#ifdef HAVE_TIME_H +#include +#endif +#endif + +#ifdef WIN32 +#include +#include +#endif + +#if defined(HAVE_STDBOOL_H) && defined(HAVE_BOOL_T) +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef __hpux +# if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL) +# ifdef _APP32_64BIT_OFF_T +# define OLD_APP32_64BIT_OFF_T _APP32_64BIT_OFF_T +# undef _APP32_64BIT_OFF_T +# else +# undef OLD_APP32_64BIT_OFF_T +# endif +# endif +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef __hpux +# if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL) +# ifdef OLD_APP32_64BIT_OFF_T +# define _APP32_64BIT_OFF_T OLD_APP32_64BIT_OFF_T +# undef OLD_APP32_64BIT_OFF_T +# endif +# endif +#endif + +/* + * Definition of timeval struct for platforms that don't have it. + */ + +#ifndef HAVE_STRUCT_TIMEVAL +struct timeval { + long tv_sec; + long tv_usec; +}; +#endif + + +/* + * If we have the MSG_NOSIGNAL define, make sure we use + * it as the fourth argument of function send() + */ + +#ifdef HAVE_MSG_NOSIGNAL +#define SEND_4TH_ARG MSG_NOSIGNAL +#else +#define SEND_4TH_ARG 0 +#endif + + +#if defined(__minix) +/* Minix doesn't support recv on TCP sockets */ +#define sread(x,y,z) (ssize_t)read((RECV_TYPE_ARG1)(x), \ + (RECV_TYPE_ARG2)(y), \ + (RECV_TYPE_ARG3)(z)) + +#elif defined(HAVE_RECV) +/* + * The definitions for the return type and arguments types + * of functions recv() and send() belong and come from the + * configuration file. Do not define them in any other place. + * + * HAVE_RECV is defined if you have a function named recv() + * which is used to read incoming data from sockets. If your + * function has another name then don't define HAVE_RECV. + * + * If HAVE_RECV is defined then RECV_TYPE_ARG1, RECV_TYPE_ARG2, + * RECV_TYPE_ARG3, RECV_TYPE_ARG4 and RECV_TYPE_RETV must also + * be defined. + * + * HAVE_SEND is defined if you have a function named send() + * which is used to write outgoing data on a connected socket. + * If yours has another name then don't define HAVE_SEND. + * + * If HAVE_SEND is defined then SEND_TYPE_ARG1, SEND_QUAL_ARG2, + * SEND_TYPE_ARG2, SEND_TYPE_ARG3, SEND_TYPE_ARG4 and + * SEND_TYPE_RETV must also be defined. + */ + +#if !defined(RECV_TYPE_ARG1) || \ + !defined(RECV_TYPE_ARG2) || \ + !defined(RECV_TYPE_ARG3) || \ + !defined(RECV_TYPE_ARG4) || \ + !defined(RECV_TYPE_RETV) + /* */ + Error Missing_definition_of_return_and_arguments_types_of_recv + /* */ +#else +#define sread(x,y,z) (ssize_t)recv((RECV_TYPE_ARG1)(x), \ + (RECV_TYPE_ARG2)(y), \ + (RECV_TYPE_ARG3)(z), \ + (RECV_TYPE_ARG4)(0)) +#endif +#else /* HAVE_RECV */ +#ifndef sread + /* */ + Error Missing_definition_of_macro_sread + /* */ +#endif +#endif /* HAVE_RECV */ + + +#if defined(__minix) +/* Minix doesn't support send on TCP sockets */ +#define swrite(x,y,z) (ssize_t)write((SEND_TYPE_ARG1)(x), \ + (SEND_TYPE_ARG2)(y), \ + (SEND_TYPE_ARG3)(z)) + +#elif defined(HAVE_SEND) +#if !defined(SEND_TYPE_ARG1) || \ + !defined(SEND_QUAL_ARG2) || \ + !defined(SEND_TYPE_ARG2) || \ + !defined(SEND_TYPE_ARG3) || \ + !defined(SEND_TYPE_ARG4) || \ + !defined(SEND_TYPE_RETV) + /* */ + Error Missing_definition_of_return_and_arguments_types_of_send + /* */ +#else +#define swrite(x,y,z) (ssize_t)send((SEND_TYPE_ARG1)(x), \ + (SEND_QUAL_ARG2 SEND_TYPE_ARG2)(y), \ + (SEND_TYPE_ARG3)(z), \ + (SEND_TYPE_ARG4)(SEND_4TH_ARG)) +#endif +#else /* HAVE_SEND */ +#ifndef swrite + /* */ + Error Missing_definition_of_macro_swrite + /* */ +#endif +#endif /* HAVE_SEND */ + + +#if 0 +#if defined(HAVE_RECVFROM) +/* + * Currently recvfrom is only used on udp sockets. + */ +#if !defined(RECVFROM_TYPE_ARG1) || \ + !defined(RECVFROM_TYPE_ARG2) || \ + !defined(RECVFROM_TYPE_ARG3) || \ + !defined(RECVFROM_TYPE_ARG4) || \ + !defined(RECVFROM_TYPE_ARG5) || \ + !defined(RECVFROM_TYPE_ARG6) || \ + !defined(RECVFROM_TYPE_RETV) + /* */ + Error Missing_definition_of_return_and_arguments_types_of_recvfrom + /* */ +#else +#define sreadfrom(s,b,bl,f,fl) (ssize_t)recvfrom((RECVFROM_TYPE_ARG1) (s), \ + (RECVFROM_TYPE_ARG2 *)(b), \ + (RECVFROM_TYPE_ARG3) (bl), \ + (RECVFROM_TYPE_ARG4) (0), \ + (RECVFROM_TYPE_ARG5 *)(f), \ + (RECVFROM_TYPE_ARG6 *)(fl)) +#endif +#else /* HAVE_RECVFROM */ +#ifndef sreadfrom + /* */ + Error Missing_definition_of_macro_sreadfrom + /* */ +#endif +#endif /* HAVE_RECVFROM */ + + +#ifdef RECVFROM_TYPE_ARG6_IS_VOID +# define RECVFROM_ARG6_T int +#else +# define RECVFROM_ARG6_T RECVFROM_TYPE_ARG6 +#endif +#endif /* if 0 */ + + +/* + * Function-like macro definition used to close a socket. + */ + +#if defined(HAVE_CLOSESOCKET) +# define sclose(x) closesocket((x)) +#elif defined(HAVE_CLOSESOCKET_CAMEL) +# define sclose(x) CloseSocket((x)) +#elif defined(HAVE_CLOSE_S) +# define sclose(x) close_s((x)) +#elif defined(USE_LWIPSOCK) +# define sclose(x) lwip_close((x)) +#else +# define sclose(x) close((x)) +#endif + +/* + * Stack-independent version of fcntl() on sockets: + */ +#if defined(USE_LWIPSOCK) +# define sfcntl lwip_fcntl +#else +# define sfcntl fcntl +#endif + +#define TOLOWER(x) (tolower((int) ((unsigned char)x))) + + +/* + * 'bool' stuff compatible with HP-UX headers. + */ + +#if defined(__hpux) && !defined(HAVE_BOOL_T) + typedef int bool; +# define false 0 +# define true 1 +# define HAVE_BOOL_T +#endif + + +/* + * 'bool' exists on platforms with , i.e. C99 platforms. + * On non-C99 platforms there's no bool, so define an enum for that. + * On C99 platforms 'false' and 'true' also exist. Enum uses a + * global namespace though, so use bool_false and bool_true. + */ + +#ifndef HAVE_BOOL_T + typedef enum { + bool_false = 0, + bool_true = 1 + } bool; + +/* + * Use a define to let 'true' and 'false' use those enums. There + * are currently no use of true and false in libcurl proper, but + * there are some in the examples. This will cater for any later + * code happening to use true and false. + */ +# define false bool_false +# define true bool_true +# define HAVE_BOOL_T +#endif + + +/* + * Redefine TRUE and FALSE too, to catch current use. With this + * change, 'bool found = 1' will give a warning on MIPSPro, but + * 'bool found = TRUE' will not. Change tested on IRIX/MIPSPro, + * AIX 5.1/Xlc, Tru64 5.1/cc, w/make test too. + */ + +#ifndef TRUE +#define TRUE true +#endif +#ifndef FALSE +#define FALSE false +#endif + +#include "curl_ctype.h" + +/* + * Macro WHILE_FALSE may be used to build single-iteration do-while loops, + * avoiding compiler warnings. Mostly intended for other macro definitions. + */ + +#define WHILE_FALSE while(0) + +#if defined(_MSC_VER) && !defined(__POCC__) +# undef WHILE_FALSE +# if (_MSC_VER < 1500) +# define WHILE_FALSE while(1, 0) +# else +# define WHILE_FALSE \ +__pragma(warning(push)) \ +__pragma(warning(disable:4127)) \ +while(0) \ +__pragma(warning(pop)) +# endif +#endif + + +/* + * Typedef to 'int' if sig_atomic_t is not an available 'typedefed' type. + */ + +#ifndef HAVE_SIG_ATOMIC_T +typedef int sig_atomic_t; +#define HAVE_SIG_ATOMIC_T +#endif + + +/* + * Convenience SIG_ATOMIC_T definition + */ + +#ifdef HAVE_SIG_ATOMIC_T_VOLATILE +#define SIG_ATOMIC_T static sig_atomic_t +#else +#define SIG_ATOMIC_T static volatile sig_atomic_t +#endif + + +/* + * Default return type for signal handlers. + */ + +#ifndef RETSIGTYPE +#define RETSIGTYPE void +#endif + + +/* + * Macro used to include code only in debug builds. + */ + +#ifdef DEBUGBUILD +#define DEBUGF(x) x +#else +#define DEBUGF(x) do { } WHILE_FALSE +#endif + + +/* + * Macro used to include assertion code only in debug builds. + */ + +#if defined(DEBUGBUILD) && defined(HAVE_ASSERT_H) +#define DEBUGASSERT(x) assert(x) +#else +#define DEBUGASSERT(x) do { } WHILE_FALSE +#endif + + +/* + * Macro SOCKERRNO / SET_SOCKERRNO() returns / sets the *socket-related* errno + * (or equivalent) on this platform to hide platform details to code using it. + */ + +#ifdef USE_WINSOCK +#define SOCKERRNO ((int)WSAGetLastError()) +#define SET_SOCKERRNO(x) (WSASetLastError((int)(x))) +#else +#define SOCKERRNO (errno) +#define SET_SOCKERRNO(x) (errno = (x)) +#endif + + +/* + * Portable error number symbolic names defined to Winsock error codes. + */ + +#ifdef USE_WINSOCK +#undef EBADF /* override definition in errno.h */ +#define EBADF WSAEBADF +#undef EINTR /* override definition in errno.h */ +#define EINTR WSAEINTR +#undef EINVAL /* override definition in errno.h */ +#define EINVAL WSAEINVAL +#undef EWOULDBLOCK /* override definition in errno.h */ +#define EWOULDBLOCK WSAEWOULDBLOCK +#undef EINPROGRESS /* override definition in errno.h */ +#define EINPROGRESS WSAEINPROGRESS +#undef EALREADY /* override definition in errno.h */ +#define EALREADY WSAEALREADY +#undef ENOTSOCK /* override definition in errno.h */ +#define ENOTSOCK WSAENOTSOCK +#undef EDESTADDRREQ /* override definition in errno.h */ +#define EDESTADDRREQ WSAEDESTADDRREQ +#undef EMSGSIZE /* override definition in errno.h */ +#define EMSGSIZE WSAEMSGSIZE +#undef EPROTOTYPE /* override definition in errno.h */ +#define EPROTOTYPE WSAEPROTOTYPE +#undef ENOPROTOOPT /* override definition in errno.h */ +#define ENOPROTOOPT WSAENOPROTOOPT +#undef EPROTONOSUPPORT /* override definition in errno.h */ +#define EPROTONOSUPPORT WSAEPROTONOSUPPORT +#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT +#undef EOPNOTSUPP /* override definition in errno.h */ +#define EOPNOTSUPP WSAEOPNOTSUPP +#define EPFNOSUPPORT WSAEPFNOSUPPORT +#undef EAFNOSUPPORT /* override definition in errno.h */ +#define EAFNOSUPPORT WSAEAFNOSUPPORT +#undef EADDRINUSE /* override definition in errno.h */ +#define EADDRINUSE WSAEADDRINUSE +#undef EADDRNOTAVAIL /* override definition in errno.h */ +#define EADDRNOTAVAIL WSAEADDRNOTAVAIL +#undef ENETDOWN /* override definition in errno.h */ +#define ENETDOWN WSAENETDOWN +#undef ENETUNREACH /* override definition in errno.h */ +#define ENETUNREACH WSAENETUNREACH +#undef ENETRESET /* override definition in errno.h */ +#define ENETRESET WSAENETRESET +#undef ECONNABORTED /* override definition in errno.h */ +#define ECONNABORTED WSAECONNABORTED +#undef ECONNRESET /* override definition in errno.h */ +#define ECONNRESET WSAECONNRESET +#undef ENOBUFS /* override definition in errno.h */ +#define ENOBUFS WSAENOBUFS +#undef EISCONN /* override definition in errno.h */ +#define EISCONN WSAEISCONN +#undef ENOTCONN /* override definition in errno.h */ +#define ENOTCONN WSAENOTCONN +#define ESHUTDOWN WSAESHUTDOWN +#define ETOOMANYREFS WSAETOOMANYREFS +#undef ETIMEDOUT /* override definition in errno.h */ +#define ETIMEDOUT WSAETIMEDOUT +#undef ECONNREFUSED /* override definition in errno.h */ +#define ECONNREFUSED WSAECONNREFUSED +#undef ELOOP /* override definition in errno.h */ +#define ELOOP WSAELOOP +#ifndef ENAMETOOLONG /* possible previous definition in errno.h */ +#define ENAMETOOLONG WSAENAMETOOLONG +#endif +#define EHOSTDOWN WSAEHOSTDOWN +#undef EHOSTUNREACH /* override definition in errno.h */ +#define EHOSTUNREACH WSAEHOSTUNREACH +#ifndef ENOTEMPTY /* possible previous definition in errno.h */ +#define ENOTEMPTY WSAENOTEMPTY +#endif +#define EPROCLIM WSAEPROCLIM +#define EUSERS WSAEUSERS +#define EDQUOT WSAEDQUOT +#define ESTALE WSAESTALE +#define EREMOTE WSAEREMOTE +#endif + +/* + * Macro argv_item_t hides platform details to code using it. + */ + +#ifdef __VMS +#define argv_item_t __char_ptr32 +#else +#define argv_item_t char * +#endif + + +/* + * We use this ZERO_NULL to avoid picky compiler warnings, + * when assigning a NULL pointer to a function pointer var. + */ + +#define ZERO_NULL 0 + + +#endif /* HEADER_CURL_SETUP_ONCE_H */ diff --git a/dependencies/cmcurl/lib/curl_sha256.h b/dependencies/cmcurl/lib/curl_sha256.h new file mode 100644 index 0000000..6db4b04 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_sha256.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_SHA256_H +#define HEADER_CURL_SHA256_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Florin Petriuc, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifndef CURL_DISABLE_CRYPTO_AUTH + +void Curl_sha256it(unsigned char *outbuffer, + const unsigned char *input); + +#endif + +#endif /* HEADER_CURL_SHA256_H */ diff --git a/dependencies/cmcurl/lib/curl_sspi.c b/dependencies/cmcurl/lib/curl_sspi.c new file mode 100644 index 0000000..1d0de4e --- /dev/null +++ b/dependencies/cmcurl/lib/curl_sspi.c @@ -0,0 +1,236 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_WINDOWS_SSPI + +#include +#include "curl_sspi.h" +#include "curl_multibyte.h" +#include "system_win32.h" +#include "warnless.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* We use our own typedef here since some headers might lack these */ +typedef PSecurityFunctionTable (APIENTRY *INITSECURITYINTERFACE_FN)(VOID); + +/* See definition of SECURITY_ENTRYPOINT in sspi.h */ +#ifdef UNICODE +# ifdef _WIN32_WCE +# define SECURITYENTRYPOINT L"InitSecurityInterfaceW" +# else +# define SECURITYENTRYPOINT "InitSecurityInterfaceW" +# endif +#else +# define SECURITYENTRYPOINT "InitSecurityInterfaceA" +#endif + +/* Handle of security.dll or secur32.dll, depending on Windows version */ +HMODULE s_hSecDll = NULL; + +/* Pointer to SSPI dispatch table */ +PSecurityFunctionTable s_pSecFn = NULL; + +/* + * Curl_sspi_global_init() + * + * This is used to load the Security Service Provider Interface (SSPI) + * dynamic link library portably across all Windows versions, without + * the need to directly link libcurl, nor the application using it, at + * build time. + * + * Once this function has been executed, Windows SSPI functions can be + * called through the Security Service Provider Interface dispatch table. + * + * Parameters: + * + * None. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_sspi_global_init(void) +{ + INITSECURITYINTERFACE_FN pInitSecurityInterface; + + /* If security interface is not yet initialized try to do this */ + if(!s_hSecDll) { + /* Security Service Provider Interface (SSPI) functions are located in + * security.dll on WinNT 4.0 and in secur32.dll on Win9x. Win2K and XP + * have both these DLLs (security.dll forwards calls to secur32.dll) */ + + /* Load SSPI dll into the address space of the calling process */ + if(Curl_verify_windows_version(4, 0, PLATFORM_WINNT, VERSION_EQUAL)) + s_hSecDll = Curl_load_library(TEXT("security.dll")); + else + s_hSecDll = Curl_load_library(TEXT("secur32.dll")); + if(!s_hSecDll) + return CURLE_FAILED_INIT; + + /* Get address of the InitSecurityInterfaceA function from the SSPI dll */ + pInitSecurityInterface = + CURLX_FUNCTION_CAST(INITSECURITYINTERFACE_FN, + (GetProcAddress(s_hSecDll, SECURITYENTRYPOINT))); + if(!pInitSecurityInterface) + return CURLE_FAILED_INIT; + + /* Get pointer to Security Service Provider Interface dispatch table */ + s_pSecFn = pInitSecurityInterface(); + if(!s_pSecFn) + return CURLE_FAILED_INIT; + } + + return CURLE_OK; +} + +/* + * Curl_sspi_global_cleanup() + * + * This deinitializes the Security Service Provider Interface from libcurl. + * + * Parameters: + * + * None. + */ +void Curl_sspi_global_cleanup(void) +{ + if(s_hSecDll) { + FreeLibrary(s_hSecDll); + s_hSecDll = NULL; + s_pSecFn = NULL; + } +} + +/* + * Curl_create_sspi_identity() + * + * This is used to populate a SSPI identity structure based on the supplied + * username and password. + * + * Parameters: + * + * userp [in] - The user name in the format User or Domain\User. + * passwdp [in] - The user's password. + * identity [in/out] - The identity structure. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp, + SEC_WINNT_AUTH_IDENTITY *identity) +{ + xcharp_u useranddomain; + xcharp_u user, dup_user; + xcharp_u domain, dup_domain; + xcharp_u passwd, dup_passwd; + size_t domlen = 0; + + domain.const_tchar_ptr = TEXT(""); + + /* Initialize the identity */ + memset(identity, 0, sizeof(*identity)); + + useranddomain.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)userp); + if(!useranddomain.tchar_ptr) + return CURLE_OUT_OF_MEMORY; + + user.const_tchar_ptr = _tcschr(useranddomain.const_tchar_ptr, TEXT('\\')); + if(!user.const_tchar_ptr) + user.const_tchar_ptr = _tcschr(useranddomain.const_tchar_ptr, TEXT('/')); + + if(user.tchar_ptr) { + domain.tchar_ptr = useranddomain.tchar_ptr; + domlen = user.tchar_ptr - useranddomain.tchar_ptr; + user.tchar_ptr++; + } + else { + user.tchar_ptr = useranddomain.tchar_ptr; + domain.const_tchar_ptr = TEXT(""); + domlen = 0; + } + + /* Setup the identity's user and length */ + dup_user.tchar_ptr = _tcsdup(user.tchar_ptr); + if(!dup_user.tchar_ptr) { + Curl_unicodefree(useranddomain.tchar_ptr); + return CURLE_OUT_OF_MEMORY; + } + identity->User = dup_user.tbyte_ptr; + identity->UserLength = curlx_uztoul(_tcslen(dup_user.tchar_ptr)); + dup_user.tchar_ptr = NULL; + + /* Setup the identity's domain and length */ + dup_domain.tchar_ptr = malloc(sizeof(TCHAR) * (domlen + 1)); + if(!dup_domain.tchar_ptr) { + Curl_unicodefree(useranddomain.tchar_ptr); + return CURLE_OUT_OF_MEMORY; + } + _tcsncpy(dup_domain.tchar_ptr, domain.tchar_ptr, domlen); + *(dup_domain.tchar_ptr + domlen) = TEXT('\0'); + identity->Domain = dup_domain.tbyte_ptr; + identity->DomainLength = curlx_uztoul(domlen); + dup_domain.tchar_ptr = NULL; + + Curl_unicodefree(useranddomain.tchar_ptr); + + /* Setup the identity's password and length */ + passwd.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)passwdp); + if(!passwd.tchar_ptr) + return CURLE_OUT_OF_MEMORY; + dup_passwd.tchar_ptr = _tcsdup(passwd.tchar_ptr); + if(!dup_passwd.tchar_ptr) { + Curl_unicodefree(passwd.tchar_ptr); + return CURLE_OUT_OF_MEMORY; + } + identity->Password = dup_passwd.tbyte_ptr; + identity->PasswordLength = curlx_uztoul(_tcslen(dup_passwd.tchar_ptr)); + dup_passwd.tchar_ptr = NULL; + + Curl_unicodefree(passwd.tchar_ptr); + + /* Setup the identity's flags */ + identity->Flags = SECFLAG_WINNT_AUTH_IDENTITY; + + return CURLE_OK; +} + +/* + * Curl_sspi_free_identity() + * + * This is used to free the contents of a SSPI identifier structure. + * + * Parameters: + * + * identity [in/out] - The identity structure. + */ +void Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY *identity) +{ + if(identity) { + Curl_safefree(identity->User); + Curl_safefree(identity->Password); + Curl_safefree(identity->Domain); + } +} + +#endif /* USE_WINDOWS_SSPI */ diff --git a/dependencies/cmcurl/lib/curl_sspi.h b/dependencies/cmcurl/lib/curl_sspi.h new file mode 100644 index 0000000..2bbf947 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_sspi.h @@ -0,0 +1,350 @@ +#ifndef HEADER_CURL_SSPI_H +#define HEADER_CURL_SSPI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_WINDOWS_SSPI + +#include + +/* + * When including the following three headers, it is mandatory to define either + * SECURITY_WIN32 or SECURITY_KERNEL, indicating who is compiling the code. + */ + +#undef SECURITY_WIN32 +#undef SECURITY_KERNEL +#define SECURITY_WIN32 1 +#include +#include +#include + +CURLcode Curl_sspi_global_init(void); +void Curl_sspi_global_cleanup(void); + +/* This is used to populate the domain in a SSPI identity structure */ +CURLcode Curl_override_sspi_http_realm(const char *chlg, + SEC_WINNT_AUTH_IDENTITY *identity); + +/* This is used to generate an SSPI identity structure */ +CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp, + SEC_WINNT_AUTH_IDENTITY *identity); + +/* This is used to free an SSPI identity structure */ +void Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY *identity); + +/* Forward-declaration of global variables defined in curl_sspi.c */ +extern HMODULE s_hSecDll; +extern PSecurityFunctionTable s_pSecFn; + +/* Provide some definitions missing in old headers */ +#define SP_NAME_DIGEST "WDigest" +#define SP_NAME_NTLM "NTLM" +#define SP_NAME_NEGOTIATE "Negotiate" +#define SP_NAME_KERBEROS "Kerberos" + +#ifndef ISC_REQ_USE_HTTP_STYLE +#define ISC_REQ_USE_HTTP_STYLE 0x01000000 +#endif + +#ifndef ISC_RET_REPLAY_DETECT +#define ISC_RET_REPLAY_DETECT 0x00000004 +#endif + +#ifndef ISC_RET_SEQUENCE_DETECT +#define ISC_RET_SEQUENCE_DETECT 0x00000008 +#endif + +#ifndef ISC_RET_CONFIDENTIALITY +#define ISC_RET_CONFIDENTIALITY 0x00000010 +#endif + +#ifndef ISC_RET_ALLOCATED_MEMORY +#define ISC_RET_ALLOCATED_MEMORY 0x00000100 +#endif + +#ifndef ISC_RET_STREAM +#define ISC_RET_STREAM 0x00008000 +#endif + +#ifndef SEC_E_INSUFFICIENT_MEMORY +# define SEC_E_INSUFFICIENT_MEMORY ((HRESULT)0x80090300L) +#endif +#ifndef SEC_E_INVALID_HANDLE +# define SEC_E_INVALID_HANDLE ((HRESULT)0x80090301L) +#endif +#ifndef SEC_E_UNSUPPORTED_FUNCTION +# define SEC_E_UNSUPPORTED_FUNCTION ((HRESULT)0x80090302L) +#endif +#ifndef SEC_E_TARGET_UNKNOWN +# define SEC_E_TARGET_UNKNOWN ((HRESULT)0x80090303L) +#endif +#ifndef SEC_E_INTERNAL_ERROR +# define SEC_E_INTERNAL_ERROR ((HRESULT)0x80090304L) +#endif +#ifndef SEC_E_SECPKG_NOT_FOUND +# define SEC_E_SECPKG_NOT_FOUND ((HRESULT)0x80090305L) +#endif +#ifndef SEC_E_NOT_OWNER +# define SEC_E_NOT_OWNER ((HRESULT)0x80090306L) +#endif +#ifndef SEC_E_CANNOT_INSTALL +# define SEC_E_CANNOT_INSTALL ((HRESULT)0x80090307L) +#endif +#ifndef SEC_E_INVALID_TOKEN +# define SEC_E_INVALID_TOKEN ((HRESULT)0x80090308L) +#endif +#ifndef SEC_E_CANNOT_PACK +# define SEC_E_CANNOT_PACK ((HRESULT)0x80090309L) +#endif +#ifndef SEC_E_QOP_NOT_SUPPORTED +# define SEC_E_QOP_NOT_SUPPORTED ((HRESULT)0x8009030AL) +#endif +#ifndef SEC_E_NO_IMPERSONATION +# define SEC_E_NO_IMPERSONATION ((HRESULT)0x8009030BL) +#endif +#ifndef SEC_E_LOGON_DENIED +# define SEC_E_LOGON_DENIED ((HRESULT)0x8009030CL) +#endif +#ifndef SEC_E_UNKNOWN_CREDENTIALS +# define SEC_E_UNKNOWN_CREDENTIALS ((HRESULT)0x8009030DL) +#endif +#ifndef SEC_E_NO_CREDENTIALS +# define SEC_E_NO_CREDENTIALS ((HRESULT)0x8009030EL) +#endif +#ifndef SEC_E_MESSAGE_ALTERED +# define SEC_E_MESSAGE_ALTERED ((HRESULT)0x8009030FL) +#endif +#ifndef SEC_E_OUT_OF_SEQUENCE +# define SEC_E_OUT_OF_SEQUENCE ((HRESULT)0x80090310L) +#endif +#ifndef SEC_E_NO_AUTHENTICATING_AUTHORITY +# define SEC_E_NO_AUTHENTICATING_AUTHORITY ((HRESULT)0x80090311L) +#endif +#ifndef SEC_E_BAD_PKGID +# define SEC_E_BAD_PKGID ((HRESULT)0x80090316L) +#endif +#ifndef SEC_E_CONTEXT_EXPIRED +# define SEC_E_CONTEXT_EXPIRED ((HRESULT)0x80090317L) +#endif +#ifndef SEC_E_INCOMPLETE_MESSAGE +# define SEC_E_INCOMPLETE_MESSAGE ((HRESULT)0x80090318L) +#endif +#ifndef SEC_E_INCOMPLETE_CREDENTIALS +# define SEC_E_INCOMPLETE_CREDENTIALS ((HRESULT)0x80090320L) +#endif +#ifndef SEC_E_BUFFER_TOO_SMALL +# define SEC_E_BUFFER_TOO_SMALL ((HRESULT)0x80090321L) +#endif +#ifndef SEC_E_WRONG_PRINCIPAL +# define SEC_E_WRONG_PRINCIPAL ((HRESULT)0x80090322L) +#endif +#ifndef SEC_E_TIME_SKEW +# define SEC_E_TIME_SKEW ((HRESULT)0x80090324L) +#endif +#ifndef SEC_E_UNTRUSTED_ROOT +# define SEC_E_UNTRUSTED_ROOT ((HRESULT)0x80090325L) +#endif +#ifndef SEC_E_ILLEGAL_MESSAGE +# define SEC_E_ILLEGAL_MESSAGE ((HRESULT)0x80090326L) +#endif +#ifndef SEC_E_CERT_UNKNOWN +# define SEC_E_CERT_UNKNOWN ((HRESULT)0x80090327L) +#endif +#ifndef SEC_E_CERT_EXPIRED +# define SEC_E_CERT_EXPIRED ((HRESULT)0x80090328L) +#endif +#ifndef SEC_E_ENCRYPT_FAILURE +# define SEC_E_ENCRYPT_FAILURE ((HRESULT)0x80090329L) +#endif +#ifndef SEC_E_DECRYPT_FAILURE +# define SEC_E_DECRYPT_FAILURE ((HRESULT)0x80090330L) +#endif +#ifndef SEC_E_ALGORITHM_MISMATCH +# define SEC_E_ALGORITHM_MISMATCH ((HRESULT)0x80090331L) +#endif +#ifndef SEC_E_SECURITY_QOS_FAILED +# define SEC_E_SECURITY_QOS_FAILED ((HRESULT)0x80090332L) +#endif +#ifndef SEC_E_UNFINISHED_CONTEXT_DELETED +# define SEC_E_UNFINISHED_CONTEXT_DELETED ((HRESULT)0x80090333L) +#endif +#ifndef SEC_E_NO_TGT_REPLY +# define SEC_E_NO_TGT_REPLY ((HRESULT)0x80090334L) +#endif +#ifndef SEC_E_NO_IP_ADDRESSES +# define SEC_E_NO_IP_ADDRESSES ((HRESULT)0x80090335L) +#endif +#ifndef SEC_E_WRONG_CREDENTIAL_HANDLE +# define SEC_E_WRONG_CREDENTIAL_HANDLE ((HRESULT)0x80090336L) +#endif +#ifndef SEC_E_CRYPTO_SYSTEM_INVALID +# define SEC_E_CRYPTO_SYSTEM_INVALID ((HRESULT)0x80090337L) +#endif +#ifndef SEC_E_MAX_REFERRALS_EXCEEDED +# define SEC_E_MAX_REFERRALS_EXCEEDED ((HRESULT)0x80090338L) +#endif +#ifndef SEC_E_MUST_BE_KDC +# define SEC_E_MUST_BE_KDC ((HRESULT)0x80090339L) +#endif +#ifndef SEC_E_STRONG_CRYPTO_NOT_SUPPORTED +# define SEC_E_STRONG_CRYPTO_NOT_SUPPORTED ((HRESULT)0x8009033AL) +#endif +#ifndef SEC_E_TOO_MANY_PRINCIPALS +# define SEC_E_TOO_MANY_PRINCIPALS ((HRESULT)0x8009033BL) +#endif +#ifndef SEC_E_NO_PA_DATA +# define SEC_E_NO_PA_DATA ((HRESULT)0x8009033CL) +#endif +#ifndef SEC_E_PKINIT_NAME_MISMATCH +# define SEC_E_PKINIT_NAME_MISMATCH ((HRESULT)0x8009033DL) +#endif +#ifndef SEC_E_SMARTCARD_LOGON_REQUIRED +# define SEC_E_SMARTCARD_LOGON_REQUIRED ((HRESULT)0x8009033EL) +#endif +#ifndef SEC_E_SHUTDOWN_IN_PROGRESS +# define SEC_E_SHUTDOWN_IN_PROGRESS ((HRESULT)0x8009033FL) +#endif +#ifndef SEC_E_KDC_INVALID_REQUEST +# define SEC_E_KDC_INVALID_REQUEST ((HRESULT)0x80090340L) +#endif +#ifndef SEC_E_KDC_UNABLE_TO_REFER +# define SEC_E_KDC_UNABLE_TO_REFER ((HRESULT)0x80090341L) +#endif +#ifndef SEC_E_KDC_UNKNOWN_ETYPE +# define SEC_E_KDC_UNKNOWN_ETYPE ((HRESULT)0x80090342L) +#endif +#ifndef SEC_E_UNSUPPORTED_PREAUTH +# define SEC_E_UNSUPPORTED_PREAUTH ((HRESULT)0x80090343L) +#endif +#ifndef SEC_E_DELEGATION_REQUIRED +# define SEC_E_DELEGATION_REQUIRED ((HRESULT)0x80090345L) +#endif +#ifndef SEC_E_BAD_BINDINGS +# define SEC_E_BAD_BINDINGS ((HRESULT)0x80090346L) +#endif +#ifndef SEC_E_MULTIPLE_ACCOUNTS +# define SEC_E_MULTIPLE_ACCOUNTS ((HRESULT)0x80090347L) +#endif +#ifndef SEC_E_NO_KERB_KEY +# define SEC_E_NO_KERB_KEY ((HRESULT)0x80090348L) +#endif +#ifndef SEC_E_CERT_WRONG_USAGE +# define SEC_E_CERT_WRONG_USAGE ((HRESULT)0x80090349L) +#endif +#ifndef SEC_E_DOWNGRADE_DETECTED +# define SEC_E_DOWNGRADE_DETECTED ((HRESULT)0x80090350L) +#endif +#ifndef SEC_E_SMARTCARD_CERT_REVOKED +# define SEC_E_SMARTCARD_CERT_REVOKED ((HRESULT)0x80090351L) +#endif +#ifndef SEC_E_ISSUING_CA_UNTRUSTED +# define SEC_E_ISSUING_CA_UNTRUSTED ((HRESULT)0x80090352L) +#endif +#ifndef SEC_E_REVOCATION_OFFLINE_C +# define SEC_E_REVOCATION_OFFLINE_C ((HRESULT)0x80090353L) +#endif +#ifndef SEC_E_PKINIT_CLIENT_FAILURE +# define SEC_E_PKINIT_CLIENT_FAILURE ((HRESULT)0x80090354L) +#endif +#ifndef SEC_E_SMARTCARD_CERT_EXPIRED +# define SEC_E_SMARTCARD_CERT_EXPIRED ((HRESULT)0x80090355L) +#endif +#ifndef SEC_E_NO_S4U_PROT_SUPPORT +# define SEC_E_NO_S4U_PROT_SUPPORT ((HRESULT)0x80090356L) +#endif +#ifndef SEC_E_CROSSREALM_DELEGATION_FAILURE +# define SEC_E_CROSSREALM_DELEGATION_FAILURE ((HRESULT)0x80090357L) +#endif +#ifndef SEC_E_REVOCATION_OFFLINE_KDC +# define SEC_E_REVOCATION_OFFLINE_KDC ((HRESULT)0x80090358L) +#endif +#ifndef SEC_E_ISSUING_CA_UNTRUSTED_KDC +# define SEC_E_ISSUING_CA_UNTRUSTED_KDC ((HRESULT)0x80090359L) +#endif +#ifndef SEC_E_KDC_CERT_EXPIRED +# define SEC_E_KDC_CERT_EXPIRED ((HRESULT)0x8009035AL) +#endif +#ifndef SEC_E_KDC_CERT_REVOKED +# define SEC_E_KDC_CERT_REVOKED ((HRESULT)0x8009035BL) +#endif +#ifndef SEC_E_INVALID_PARAMETER +# define SEC_E_INVALID_PARAMETER ((HRESULT)0x8009035DL) +#endif +#ifndef SEC_E_DELEGATION_POLICY +# define SEC_E_DELEGATION_POLICY ((HRESULT)0x8009035EL) +#endif +#ifndef SEC_E_POLICY_NLTM_ONLY +# define SEC_E_POLICY_NLTM_ONLY ((HRESULT)0x8009035FL) +#endif + +#ifndef SEC_I_CONTINUE_NEEDED +# define SEC_I_CONTINUE_NEEDED ((HRESULT)0x00090312L) +#endif +#ifndef SEC_I_COMPLETE_NEEDED +# define SEC_I_COMPLETE_NEEDED ((HRESULT)0x00090313L) +#endif +#ifndef SEC_I_COMPLETE_AND_CONTINUE +# define SEC_I_COMPLETE_AND_CONTINUE ((HRESULT)0x00090314L) +#endif +#ifndef SEC_I_LOCAL_LOGON +# define SEC_I_LOCAL_LOGON ((HRESULT)0x00090315L) +#endif +#ifndef SEC_I_CONTEXT_EXPIRED +# define SEC_I_CONTEXT_EXPIRED ((HRESULT)0x00090317L) +#endif +#ifndef SEC_I_INCOMPLETE_CREDENTIALS +# define SEC_I_INCOMPLETE_CREDENTIALS ((HRESULT)0x00090320L) +#endif +#ifndef SEC_I_RENEGOTIATE +# define SEC_I_RENEGOTIATE ((HRESULT)0x00090321L) +#endif +#ifndef SEC_I_NO_LSA_CONTEXT +# define SEC_I_NO_LSA_CONTEXT ((HRESULT)0x00090323L) +#endif +#ifndef SEC_I_SIGNATURE_NEEDED +# define SEC_I_SIGNATURE_NEEDED ((HRESULT)0x0009035CL) +#endif + +#ifndef CRYPT_E_REVOKED +# define CRYPT_E_REVOKED ((HRESULT)0x80092010L) +#endif + +#ifdef UNICODE +# define SECFLAG_WINNT_AUTH_IDENTITY \ + (unsigned long)SEC_WINNT_AUTH_IDENTITY_UNICODE +#else +# define SECFLAG_WINNT_AUTH_IDENTITY \ + (unsigned long)SEC_WINNT_AUTH_IDENTITY_ANSI +#endif + +/* + * Definitions required from ntsecapi.h are directly provided below this point + * to avoid including ntsecapi.h due to a conflict with OpenSSL's safestack.h + */ +#define KERB_WRAP_NO_ENCRYPT 0x80000001 + +#endif /* USE_WINDOWS_SSPI */ + +#endif /* HEADER_CURL_SSPI_H */ diff --git a/dependencies/cmcurl/lib/curl_threads.c b/dependencies/cmcurl/lib/curl_threads.c new file mode 100644 index 0000000..8e5937a --- /dev/null +++ b/dependencies/cmcurl/lib/curl_threads.c @@ -0,0 +1,155 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#if defined(USE_THREADS_POSIX) +# ifdef HAVE_PTHREAD_H +# include +# endif +#elif defined(USE_THREADS_WIN32) +# ifdef HAVE_PROCESS_H +# include +# endif +#endif + +#include "curl_threads.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +#if defined(USE_THREADS_POSIX) + +struct curl_actual_call { + unsigned int (*func)(void *); + void *arg; +}; + +static void *curl_thread_create_thunk(void *arg) +{ + struct curl_actual_call * ac = arg; + unsigned int (*func)(void *) = ac->func; + void *real_arg = ac->arg; + + free(ac); + + (*func)(real_arg); + + return 0; +} + +curl_thread_t Curl_thread_create(unsigned int (*func) (void *), void *arg) +{ + curl_thread_t t = malloc(sizeof(pthread_t)); + struct curl_actual_call *ac = malloc(sizeof(struct curl_actual_call)); + if(!(ac && t)) + goto err; + + ac->func = func; + ac->arg = arg; + + if(pthread_create(t, NULL, curl_thread_create_thunk, ac) != 0) + goto err; + + return t; + +err: + free(t); + free(ac); + return curl_thread_t_null; +} + +void Curl_thread_destroy(curl_thread_t hnd) +{ + if(hnd != curl_thread_t_null) { + pthread_detach(*hnd); + free(hnd); + } +} + +int Curl_thread_join(curl_thread_t *hnd) +{ + int ret = (pthread_join(**hnd, NULL) == 0); + + free(*hnd); + *hnd = curl_thread_t_null; + + return ret; +} + +#elif defined(USE_THREADS_WIN32) + +/* !checksrc! disable SPACEBEFOREPAREN 1 */ +curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *), + void *arg) +{ +#ifdef _WIN32_WCE + typedef HANDLE curl_win_thread_handle_t; +#elif defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) + typedef unsigned long curl_win_thread_handle_t; +#else + typedef uintptr_t curl_win_thread_handle_t; +#endif + curl_thread_t t; + curl_win_thread_handle_t thread_handle; +#ifdef _WIN32_WCE + thread_handle = CreateThread(NULL, 0, func, arg, 0, NULL); +#else + thread_handle = _beginthreadex(NULL, 0, func, arg, 0, NULL); +#endif + t = (curl_thread_t)thread_handle; + if((t == 0) || (t == LongToHandle(-1L))) { +#ifdef _WIN32_WCE + DWORD gle = GetLastError(); + errno = ((gle == ERROR_ACCESS_DENIED || + gle == ERROR_NOT_ENOUGH_MEMORY) ? + EACCES : EINVAL); +#endif + return curl_thread_t_null; + } + return t; +} + +void Curl_thread_destroy(curl_thread_t hnd) +{ + CloseHandle(hnd); +} + +int Curl_thread_join(curl_thread_t *hnd) +{ +#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \ + (_WIN32_WINNT < _WIN32_WINNT_VISTA) + int ret = (WaitForSingleObject(*hnd, INFINITE) == WAIT_OBJECT_0); +#else + int ret = (WaitForSingleObjectEx(*hnd, INFINITE, FALSE) == WAIT_OBJECT_0); +#endif + + Curl_thread_destroy(*hnd); + + *hnd = curl_thread_t_null; + + return ret; +} + +#endif /* USE_THREADS_* */ diff --git a/dependencies/cmcurl/lib/curl_threads.h b/dependencies/cmcurl/lib/curl_threads.h new file mode 100644 index 0000000..2a93644 --- /dev/null +++ b/dependencies/cmcurl/lib/curl_threads.h @@ -0,0 +1,64 @@ +#ifndef HEADER_CURL_THREADS_H +#define HEADER_CURL_THREADS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if defined(USE_THREADS_POSIX) +# define CURL_STDCALL +# define curl_mutex_t pthread_mutex_t +# define curl_thread_t pthread_t * +# define curl_thread_t_null (pthread_t *)0 +# define Curl_mutex_init(m) pthread_mutex_init(m, NULL) +# define Curl_mutex_acquire(m) pthread_mutex_lock(m) +# define Curl_mutex_release(m) pthread_mutex_unlock(m) +# define Curl_mutex_destroy(m) pthread_mutex_destroy(m) +#elif defined(USE_THREADS_WIN32) +# define CURL_STDCALL __stdcall +# define curl_mutex_t CRITICAL_SECTION +# define curl_thread_t HANDLE +# define curl_thread_t_null (HANDLE)0 +# if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \ + (_WIN32_WINNT < _WIN32_WINNT_VISTA) || \ + (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)) +# define Curl_mutex_init(m) InitializeCriticalSection(m) +# else +# define Curl_mutex_init(m) InitializeCriticalSectionEx(m, 0, 1) +# endif +# define Curl_mutex_acquire(m) EnterCriticalSection(m) +# define Curl_mutex_release(m) LeaveCriticalSection(m) +# define Curl_mutex_destroy(m) DeleteCriticalSection(m) +#endif + +#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) + +/* !checksrc! disable SPACEBEFOREPAREN 1 */ +curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *), + void *arg); + +void Curl_thread_destroy(curl_thread_t hnd); + +int Curl_thread_join(curl_thread_t *hnd); + +#endif /* USE_THREADS_POSIX || USE_THREADS_WIN32 */ + +#endif /* HEADER_CURL_THREADS_H */ diff --git a/dependencies/cmcurl/lib/curlx.h b/dependencies/cmcurl/lib/curlx.h new file mode 100644 index 0000000..3e9b516 --- /dev/null +++ b/dependencies/cmcurl/lib/curlx.h @@ -0,0 +1,103 @@ +#ifndef HEADER_CURL_CURLX_H +#define HEADER_CURL_CURLX_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Defines protos and includes all header files that provide the curlx_* + * functions. The curlx_* functions are not part of the libcurl API, but are + * stand-alone functions whose sources can be built and linked by apps if need + * be. + */ + +#include +/* this is still a public header file that provides the curl_mprintf() + functions while they still are offered publicly. They will be made library- + private one day */ + +#include "strcase.h" +/* "strcase.h" provides the strcasecompare protos */ + +#include "strtoofft.h" +/* "strtoofft.h" provides this function: curlx_strtoofft(), returns a + curl_off_t number from a given string. +*/ + +#include "nonblock.h" +/* "nonblock.h" provides curlx_nonblock() */ + +#include "warnless.h" +/* "warnless.h" provides functions: + + curlx_ultous() + curlx_ultouc() + curlx_uztosi() +*/ + +/* Now setup curlx_ * names for the functions that are to become curlx_ and + be removed from a future libcurl official API: + curlx_getenv + curlx_mprintf (and its variations) + curlx_strcasecompare + curlx_strncasecompare + +*/ + +#define curlx_getenv curl_getenv +#define curlx_mvsnprintf curl_mvsnprintf +#define curlx_msnprintf curl_msnprintf +#define curlx_maprintf curl_maprintf +#define curlx_mvaprintf curl_mvaprintf +#define curlx_msprintf curl_msprintf +#define curlx_mprintf curl_mprintf +#define curlx_mfprintf curl_mfprintf +#define curlx_mvsprintf curl_mvsprintf +#define curlx_mvprintf curl_mvprintf +#define curlx_mvfprintf curl_mvfprintf + +#ifdef ENABLE_CURLX_PRINTF +/* If this define is set, we define all "standard" printf() functions to use + the curlx_* version instead. It makes the source code transparent and + easier to understand/patch. Undefine them first. */ +# undef printf +# undef fprintf +# undef sprintf +# undef msnprintf +# undef vprintf +# undef vfprintf +# undef vsprintf +# undef mvsnprintf +# undef aprintf +# undef vaprintf + +# define printf curlx_mprintf +# define fprintf curlx_mfprintf +# define sprintf curlx_msprintf +# define msnprintf curlx_msnprintf +# define vprintf curlx_mvprintf +# define vfprintf curlx_mvfprintf +# define mvsnprintf curlx_mvsnprintf +# define aprintf curlx_maprintf +# define vaprintf curlx_mvaprintf +#endif /* ENABLE_CURLX_PRINTF */ + +#endif /* HEADER_CURL_CURLX_H */ diff --git a/dependencies/cmcurl/lib/dict.c b/dependencies/cmcurl/lib/dict.c new file mode 100644 index 0000000..208a233 --- /dev/null +++ b/dependencies/cmcurl/lib/dict.c @@ -0,0 +1,276 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_DICT + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#ifdef HAVE_SYS_SELECT_H +#include +#endif + +#include "urldata.h" +#include +#include "transfer.h" +#include "sendf.h" +#include "escape.h" +#include "progress.h" +#include "dict.h" +#include "strcase.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * Forward declarations. + */ + +static CURLcode dict_do(struct connectdata *conn, bool *done); + +/* + * DICT protocol handler. + */ + +const struct Curl_handler Curl_handler_dict = { + "DICT", /* scheme */ + ZERO_NULL, /* setup_connection */ + dict_do, /* do_it */ + ZERO_NULL, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_DICT, /* defport */ + CURLPROTO_DICT, /* protocol */ + PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */ +}; + +static char *unescape_word(struct Curl_easy *data, const char *inputbuff) +{ + char *newp = NULL; + char *dictp; + size_t len; + + CURLcode result = Curl_urldecode(data, inputbuff, 0, &newp, &len, FALSE); + if(!newp || result) + return NULL; + + dictp = malloc(len*2 + 1); /* add one for terminating zero */ + if(dictp) { + char *ptr; + char ch; + int olen = 0; + /* According to RFC2229 section 2.2, these letters need to be escaped with + \[letter] */ + for(ptr = newp; + (ch = *ptr) != 0; + ptr++) { + if((ch <= 32) || (ch == 127) || + (ch == '\'') || (ch == '\"') || (ch == '\\')) { + dictp[olen++] = '\\'; + } + dictp[olen++] = ch; + } + dictp[olen] = 0; + } + free(newp); + return dictp; +} + +static CURLcode dict_do(struct connectdata *conn, bool *done) +{ + char *word; + char *eword; + char *ppath; + char *database = NULL; + char *strategy = NULL; + char *nthdef = NULL; /* This is not part of the protocol, but required + by RFC 2229 */ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; + + char *path = data->state.up.path; + + *done = TRUE; /* unconditionally */ + + if(conn->bits.user_passwd) { + /* AUTH is missing */ + } + + if(strncasecompare(path, DICT_MATCH, sizeof(DICT_MATCH)-1) || + strncasecompare(path, DICT_MATCH2, sizeof(DICT_MATCH2)-1) || + strncasecompare(path, DICT_MATCH3, sizeof(DICT_MATCH3)-1)) { + + word = strchr(path, ':'); + if(word) { + word++; + database = strchr(word, ':'); + if(database) { + *database++ = (char)0; + strategy = strchr(database, ':'); + if(strategy) { + *strategy++ = (char)0; + nthdef = strchr(strategy, ':'); + if(nthdef) { + *nthdef = (char)0; + } + } + } + } + + if((word == NULL) || (*word == (char)0)) { + infof(data, "lookup word is missing\n"); + word = (char *)"default"; + } + if((database == NULL) || (*database == (char)0)) { + database = (char *)"!"; + } + if((strategy == NULL) || (*strategy == (char)0)) { + strategy = (char *)"."; + } + + eword = unescape_word(data, word); + if(!eword) + return CURLE_OUT_OF_MEMORY; + + result = Curl_sendf(sockfd, conn, + "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n" + "MATCH " + "%s " /* database */ + "%s " /* strategy */ + "%s\r\n" /* word */ + "QUIT\r\n", + + database, + strategy, + eword + ); + + free(eword); + + if(result) { + failf(data, "Failed sending DICT request"); + return result; + } + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); /* no upload */ + } + else if(strncasecompare(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) || + strncasecompare(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) || + strncasecompare(path, DICT_DEFINE3, sizeof(DICT_DEFINE3)-1)) { + + word = strchr(path, ':'); + if(word) { + word++; + database = strchr(word, ':'); + if(database) { + *database++ = (char)0; + nthdef = strchr(database, ':'); + if(nthdef) { + *nthdef = (char)0; + } + } + } + + if((word == NULL) || (*word == (char)0)) { + infof(data, "lookup word is missing\n"); + word = (char *)"default"; + } + if((database == NULL) || (*database == (char)0)) { + database = (char *)"!"; + } + + eword = unescape_word(data, word); + if(!eword) + return CURLE_OUT_OF_MEMORY; + + result = Curl_sendf(sockfd, conn, + "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n" + "DEFINE " + "%s " /* database */ + "%s\r\n" /* word */ + "QUIT\r\n", + database, + eword); + + free(eword); + + if(result) { + failf(data, "Failed sending DICT request"); + return result; + } + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); + } + else { + + ppath = strchr(path, '/'); + if(ppath) { + int i; + + ppath++; + for(i = 0; ppath[i]; i++) { + if(ppath[i] == ':') + ppath[i] = ' '; + } + result = Curl_sendf(sockfd, conn, + "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n" + "%s\r\n" + "QUIT\r\n", ppath); + if(result) { + failf(data, "Failed sending DICT request"); + return result; + } + + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); + } + } + + return CURLE_OK; +} +#endif /*CURL_DISABLE_DICT*/ diff --git a/dependencies/cmcurl/lib/dict.h b/dependencies/cmcurl/lib/dict.h new file mode 100644 index 0000000..12c0f33 --- /dev/null +++ b/dependencies/cmcurl/lib/dict.h @@ -0,0 +1,29 @@ +#ifndef HEADER_CURL_DICT_H +#define HEADER_CURL_DICT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifndef CURL_DISABLE_DICT +extern const struct Curl_handler Curl_handler_dict; +#endif + +#endif /* HEADER_CURL_DICT_H */ diff --git a/dependencies/cmcurl/lib/doh.c b/dependencies/cmcurl/lib/doh.c new file mode 100644 index 0000000..6d1f330 --- /dev/null +++ b/dependencies/cmcurl/lib/doh.c @@ -0,0 +1,967 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2018 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_DOH + +#include "urldata.h" +#include "curl_addrinfo.h" +#include "doh.h" + +#include "sendf.h" +#include "multiif.h" +#include "url.h" +#include "share.h" +#include "curl_base64.h" +#include "connect.h" +#include "strdup.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#define DNS_CLASS_IN 0x01 +#define DOH_MAX_RESPONSE_SIZE 3000 /* bytes */ + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static const char * const errors[]={ + "", + "Bad label", + "Out of range", + "Label loop", + "Too small", + "Out of memory", + "RDATA length", + "Malformat", + "Bad RCODE", + "Unexpected TYPE", + "Unexpected CLASS", + "No content", + "Bad ID" +}; + +static const char *doh_strerror(DOHcode code) +{ + if((code >= DOH_OK) && (code <= DOH_DNS_BAD_ID)) + return errors[code]; + return "bad error code"; +} +#endif + +#ifdef DEBUGBUILD +#define UNITTEST +#else +#define UNITTEST static +#endif + +UNITTEST DOHcode doh_encode(const char *host, + DNStype dnstype, + unsigned char *dnsp, /* buffer */ + size_t len, /* buffer size */ + size_t *olen) /* output length */ +{ + size_t hostlen = strlen(host); + unsigned char *orig = dnsp; + const char *hostp = host; + + if(len < (12 + hostlen + 4)) + return DOH_TOO_SMALL_BUFFER; + + *dnsp++ = 0; /* 16 bit id */ + *dnsp++ = 0; + *dnsp++ = 0x01; /* |QR| Opcode |AA|TC|RD| Set the RD bit */ + *dnsp++ = '\0'; /* |RA| Z | RCODE | */ + *dnsp++ = '\0'; + *dnsp++ = 1; /* QDCOUNT (number of entries in the question section) */ + *dnsp++ = '\0'; + *dnsp++ = '\0'; /* ANCOUNT */ + *dnsp++ = '\0'; + *dnsp++ = '\0'; /* NSCOUNT */ + *dnsp++ = '\0'; + *dnsp++ = '\0'; /* ARCOUNT */ + + /* store a QNAME */ + do { + char *dot = strchr(hostp, '.'); + size_t labellen; + bool found = false; + if(dot) { + found = true; + labellen = dot - hostp; + } + else + labellen = strlen(hostp); + if(labellen > 63) { + /* too long label, error out */ + *olen = 0; + return DOH_DNS_BAD_LABEL; + } + *dnsp++ = (unsigned char)labellen; + memcpy(dnsp, hostp, labellen); + dnsp += labellen; + hostp += labellen + 1; + if(!found) { + *dnsp++ = 0; /* terminating zero */ + break; + } + } while(1); + + *dnsp++ = '\0'; /* upper 8 bit TYPE */ + *dnsp++ = (unsigned char)dnstype; + *dnsp++ = '\0'; /* upper 8 bit CLASS */ + *dnsp++ = DNS_CLASS_IN; /* IN - "the Internet" */ + + *olen = dnsp - orig; + return DOH_OK; +} + +static size_t +doh_write_cb(void *contents, size_t size, size_t nmemb, void *userp) +{ + size_t realsize = size * nmemb; + struct dohresponse *mem = (struct dohresponse *)userp; + + if((mem->size + realsize) > DOH_MAX_RESPONSE_SIZE) + /* suspiciously much for us */ + return 0; + + mem->memory = Curl_saferealloc(mem->memory, mem->size + realsize); + if(!mem->memory) + /* out of memory! */ + return 0; + + memcpy(&(mem->memory[mem->size]), contents, realsize); + mem->size += realsize; + + return realsize; +} + +/* called from multi.c when this DOH transfer is complete */ +static int Curl_doh_done(struct Curl_easy *doh, CURLcode result) +{ + struct Curl_easy *data = doh->set.dohfor; + /* so one of the DOH request done for the 'data' transfer is now complete! */ + data->req.doh.pending--; + infof(data, "a DOH request is completed, %u to go\n", data->req.doh.pending); + if(result) + infof(data, "DOH request %s\n", curl_easy_strerror(result)); + + if(!data->req.doh.pending) { + /* DOH completed */ + curl_slist_free_all(data->req.doh.headers); + data->req.doh.headers = NULL; + Curl_expire(data, 0, EXPIRE_RUN_NOW); + } + return 0; +} + +#define ERROR_CHECK_SETOPT(x,y) \ +do { \ + result = curl_easy_setopt(doh, x, y); \ + if(result) \ + goto error; \ +} WHILE_FALSE + +static CURLcode dohprobe(struct Curl_easy *data, + struct dnsprobe *p, DNStype dnstype, + const char *host, + const char *url, CURLM *multi, + struct curl_slist *headers) +{ + struct Curl_easy *doh = NULL; + char *nurl = NULL; + CURLcode result = CURLE_OK; + timediff_t timeout_ms; + DOHcode d = doh_encode(host, dnstype, p->dohbuffer, sizeof(p->dohbuffer), + &p->dohlen); + if(d) { + failf(data, "Failed to encode DOH packet [%d]\n", d); + return CURLE_OUT_OF_MEMORY; + } + + p->dnstype = dnstype; + p->serverdoh.memory = NULL; + /* the memory will be grown as needed by realloc in the doh_write_cb + function */ + p->serverdoh.size = 0; + + /* Note: this is code for sending the DoH request with GET but there's still + no logic that actually enables this. We should either add that ability or + yank out the GET code. Discuss! */ + if(data->set.doh_get) { + char *b64; + size_t b64len; + result = Curl_base64url_encode(data, (char *)p->dohbuffer, p->dohlen, + &b64, &b64len); + if(result) + goto error; + nurl = aprintf("%s?dns=%s", url, b64); + free(b64); + if(!nurl) { + result = CURLE_OUT_OF_MEMORY; + goto error; + } + url = nurl; + } + + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + /* Curl_open() is the internal version of curl_easy_init() */ + result = Curl_open(&doh); + if(!result) { + /* pass in the struct pointer via a local variable to please coverity and + the gcc typecheck helpers */ + struct dohresponse *resp = &p->serverdoh; + ERROR_CHECK_SETOPT(CURLOPT_URL, url); + ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_write_cb); + ERROR_CHECK_SETOPT(CURLOPT_WRITEDATA, resp); + if(!data->set.doh_get) { + ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDS, p->dohbuffer); + ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDSIZE, (long)p->dohlen); + } + ERROR_CHECK_SETOPT(CURLOPT_HTTPHEADER, headers); +#ifdef USE_NGHTTP2 + ERROR_CHECK_SETOPT(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS); +#endif +#ifndef CURLDEBUG + /* enforce HTTPS if not debug */ + ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTPS); +#endif + ERROR_CHECK_SETOPT(CURLOPT_TIMEOUT_MS, (long)timeout_ms); + if(data->set.verbose) + ERROR_CHECK_SETOPT(CURLOPT_VERBOSE, 1L); + if(data->set.no_signal) + ERROR_CHECK_SETOPT(CURLOPT_NOSIGNAL, 1L); + + /* Inherit *some* SSL options from the user's transfer. This is a + best-guess as to which options are needed for compatibility. #3661 */ + if(data->set.ssl.falsestart) + ERROR_CHECK_SETOPT(CURLOPT_SSL_FALSESTART, 1L); + if(data->set.ssl.primary.verifyhost) + ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYHOST, 2L); + if(data->set.proxy_ssl.primary.verifyhost) + ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_VERIFYHOST, 2L); + if(data->set.ssl.primary.verifypeer) + ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYPEER, 1L); + if(data->set.proxy_ssl.primary.verifypeer) + ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_VERIFYPEER, 1L); + if(data->set.ssl.primary.verifystatus) + ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYSTATUS, 1L); + if(data->set.str[STRING_SSL_CAFILE_ORIG]) { + ERROR_CHECK_SETOPT(CURLOPT_CAINFO, + data->set.str[STRING_SSL_CAFILE_ORIG]); + } + if(data->set.str[STRING_SSL_CAFILE_PROXY]) { + ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAINFO, + data->set.str[STRING_SSL_CAFILE_PROXY]); + } + if(data->set.str[STRING_SSL_CAPATH_ORIG]) { + ERROR_CHECK_SETOPT(CURLOPT_CAPATH, + data->set.str[STRING_SSL_CAPATH_ORIG]); + } + if(data->set.str[STRING_SSL_CAPATH_PROXY]) { + ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAPATH, + data->set.str[STRING_SSL_CAPATH_PROXY]); + } + if(data->set.str[STRING_SSL_CRLFILE_ORIG]) { + ERROR_CHECK_SETOPT(CURLOPT_CRLFILE, + data->set.str[STRING_SSL_CRLFILE_ORIG]); + } + if(data->set.str[STRING_SSL_CRLFILE_PROXY]) { + ERROR_CHECK_SETOPT(CURLOPT_PROXY_CRLFILE, + data->set.str[STRING_SSL_CRLFILE_PROXY]); + } + if(data->set.ssl.certinfo) + ERROR_CHECK_SETOPT(CURLOPT_CERTINFO, 1L); + if(data->set.str[STRING_SSL_RANDOM_FILE]) { + ERROR_CHECK_SETOPT(CURLOPT_RANDOM_FILE, + data->set.str[STRING_SSL_RANDOM_FILE]); + } + if(data->set.str[STRING_SSL_EGDSOCKET]) { + ERROR_CHECK_SETOPT(CURLOPT_EGDSOCKET, + data->set.str[STRING_SSL_EGDSOCKET]); + } + if(data->set.ssl.no_revoke) + ERROR_CHECK_SETOPT(CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE); + if(data->set.proxy_ssl.no_revoke) + ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE); + if(data->set.ssl.fsslctx) + ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_FUNCTION, data->set.ssl.fsslctx); + if(data->set.ssl.fsslctxp) + ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_DATA, data->set.ssl.fsslctxp); + + doh->set.fmultidone = Curl_doh_done; + doh->set.dohfor = data; /* identify for which transfer this is done */ + p->easy = doh; + + /* add this transfer to the multi handle */ + if(curl_multi_add_handle(multi, doh)) + goto error; + } + else + goto error; + free(nurl); + return CURLE_OK; + + error: + free(nurl); + Curl_close(doh); + return result; +} + +/* + * Curl_doh() resolves a name using DOH. It resolves a name and returns a + * 'Curl_addrinfo *' with the address information. + */ + +Curl_addrinfo *Curl_doh(struct connectdata *conn, + const char *hostname, + int port, + int *waitp) +{ + struct Curl_easy *data = conn->data; + CURLcode result = CURLE_OK; + *waitp = TRUE; /* this never returns synchronously */ + (void)conn; + (void)hostname; + (void)port; + + /* start clean, consider allocating this struct on demand */ + memset(&data->req.doh, 0, sizeof(struct dohdata)); + + data->req.doh.host = hostname; + data->req.doh.port = port; + data->req.doh.headers = + curl_slist_append(NULL, + "Content-Type: application/dns-message"); + if(!data->req.doh.headers) + goto error; + + if(conn->ip_version != CURL_IPRESOLVE_V6) { + /* create IPv4 DOH request */ + result = dohprobe(data, &data->req.doh.probe[0], DNS_TYPE_A, + hostname, data->set.str[STRING_DOH], + data->multi, data->req.doh.headers); + if(result) + goto error; + data->req.doh.pending++; + } + + if(conn->ip_version != CURL_IPRESOLVE_V4) { + /* create IPv6 DOH request */ + result = dohprobe(data, &data->req.doh.probe[1], DNS_TYPE_AAAA, + hostname, data->set.str[STRING_DOH], + data->multi, data->req.doh.headers); + if(result) + goto error; + data->req.doh.pending++; + } + return NULL; + + error: + curl_slist_free_all(data->req.doh.headers); + data->req.doh.headers = NULL; + curl_easy_cleanup(data->req.doh.probe[0].easy); + data->req.doh.probe[0].easy = NULL; + curl_easy_cleanup(data->req.doh.probe[1].easy); + data->req.doh.probe[1].easy = NULL; + return NULL; +} + +static DOHcode skipqname(unsigned char *doh, size_t dohlen, + unsigned int *indexp) +{ + unsigned char length; + do { + if(dohlen < (*indexp + 1)) + return DOH_DNS_OUT_OF_RANGE; + length = doh[*indexp]; + if((length & 0xc0) == 0xc0) { + /* name pointer, advance over it and be done */ + if(dohlen < (*indexp + 2)) + return DOH_DNS_OUT_OF_RANGE; + *indexp += 2; + break; + } + if(length & 0xc0) + return DOH_DNS_BAD_LABEL; + if(dohlen < (*indexp + 1 + length)) + return DOH_DNS_OUT_OF_RANGE; + *indexp += 1 + length; + } while(length); + return DOH_OK; +} + +static unsigned short get16bit(unsigned char *doh, int index) +{ + return (unsigned short)((doh[index] << 8) | doh[index + 1]); +} + +static unsigned int get32bit(unsigned char *doh, int index) +{ + return (doh[index] << 24) | (doh[index + 1] << 16) | + (doh[index + 2] << 8) | doh[index + 3]; +} + +static DOHcode store_a(unsigned char *doh, int index, struct dohentry *d) +{ + /* silently ignore addresses over the limit */ + if(d->numaddr < DOH_MAX_ADDR) { + struct dohaddr *a = &d->addr[d->numaddr]; + a->type = DNS_TYPE_A; + memcpy(&a->ip.v4, &doh[index], 4); + d->numaddr++; + } + return DOH_OK; +} + +static DOHcode store_aaaa(unsigned char *doh, int index, struct dohentry *d) +{ + /* silently ignore addresses over the limit */ + if(d->numaddr < DOH_MAX_ADDR) { + struct dohaddr *a = &d->addr[d->numaddr]; + a->type = DNS_TYPE_AAAA; + memcpy(&a->ip.v6, &doh[index], 16); + d->numaddr++; + } + return DOH_OK; +} + +static DOHcode cnameappend(struct cnamestore *c, + unsigned char *src, + size_t len) +{ + if(!c->alloc) { + c->allocsize = len + 1; + c->alloc = malloc(c->allocsize); + if(!c->alloc) + return DOH_OUT_OF_MEM; + } + else if(c->allocsize < (c->allocsize + len + 1)) { + char *ptr; + c->allocsize += len + 1; + ptr = realloc(c->alloc, c->allocsize); + if(!ptr) { + free(c->alloc); + return DOH_OUT_OF_MEM; + } + c->alloc = ptr; + } + memcpy(&c->alloc[c->len], src, len); + c->len += len; + c->alloc[c->len] = 0; /* keep it zero terminated */ + return DOH_OK; +} + +static DOHcode store_cname(unsigned char *doh, + size_t dohlen, + unsigned int index, + struct dohentry *d) +{ + struct cnamestore *c; + unsigned int loop = 128; /* a valid DNS name can never loop this much */ + unsigned char length; + + if(d->numcname == DOH_MAX_CNAME) + return DOH_OK; /* skip! */ + + c = &d->cname[d->numcname++]; + do { + if(index >= dohlen) + return DOH_DNS_OUT_OF_RANGE; + length = doh[index]; + if((length & 0xc0) == 0xc0) { + int newpos; + /* name pointer, get the new offset (14 bits) */ + if((index + 1) >= dohlen) + return DOH_DNS_OUT_OF_RANGE; + + /* move to the the new index */ + newpos = (length & 0x3f) << 8 | doh[index + 1]; + index = newpos; + continue; + } + else if(length & 0xc0) + return DOH_DNS_BAD_LABEL; /* bad input */ + else + index++; + + if(length) { + DOHcode rc; + if(c->len) { + rc = cnameappend(c, (unsigned char *)".", 1); + if(rc) + return rc; + } + if((index + length) > dohlen) + return DOH_DNS_BAD_LABEL; + + rc = cnameappend(c, &doh[index], length); + if(rc) + return rc; + index += length; + } + } while(length && --loop); + + if(!loop) + return DOH_DNS_LABEL_LOOP; + return DOH_OK; +} + +static DOHcode rdata(unsigned char *doh, + size_t dohlen, + unsigned short rdlength, + unsigned short type, + int index, + struct dohentry *d) +{ + /* RDATA + - A (TYPE 1): 4 bytes + - AAAA (TYPE 28): 16 bytes + - NS (TYPE 2): N bytes */ + DOHcode rc; + + switch(type) { + case DNS_TYPE_A: + if(rdlength != 4) + return DOH_DNS_RDATA_LEN; + rc = store_a(doh, index, d); + if(rc) + return rc; + break; + case DNS_TYPE_AAAA: + if(rdlength != 16) + return DOH_DNS_RDATA_LEN; + rc = store_aaaa(doh, index, d); + if(rc) + return rc; + break; + case DNS_TYPE_CNAME: + rc = store_cname(doh, dohlen, index, d); + if(rc) + return rc; + break; + default: + /* unsupported type, just skip it */ + break; + } + return DOH_OK; +} + +static void init_dohentry(struct dohentry *de) +{ + memset(de, 0, sizeof(*de)); + de->ttl = INT_MAX; +} + + +UNITTEST DOHcode doh_decode(unsigned char *doh, + size_t dohlen, + DNStype dnstype, + struct dohentry *d) +{ + unsigned char rcode; + unsigned short qdcount; + unsigned short ancount; + unsigned short type = 0; + unsigned short rdlength; + unsigned short nscount; + unsigned short arcount; + unsigned int index = 12; + DOHcode rc; + + if(dohlen < 12) + return DOH_TOO_SMALL_BUFFER; /* too small */ + if(!doh || doh[0] || doh[1]) + return DOH_DNS_BAD_ID; /* bad ID */ + rcode = doh[3] & 0x0f; + if(rcode) + return DOH_DNS_BAD_RCODE; /* bad rcode */ + + qdcount = get16bit(doh, 4); + while(qdcount) { + rc = skipqname(doh, dohlen, &index); + if(rc) + return rc; /* bad qname */ + if(dohlen < (index + 4)) + return DOH_DNS_OUT_OF_RANGE; + index += 4; /* skip question's type and class */ + qdcount--; + } + + ancount = get16bit(doh, 6); + while(ancount) { + unsigned short class; + unsigned int ttl; + + rc = skipqname(doh, dohlen, &index); + if(rc) + return rc; /* bad qname */ + + if(dohlen < (index + 2)) + return DOH_DNS_OUT_OF_RANGE; + + type = get16bit(doh, index); + if((type != DNS_TYPE_CNAME) && (type != dnstype)) + /* Not the same type as was asked for nor CNAME */ + return DOH_DNS_UNEXPECTED_TYPE; + index += 2; + + if(dohlen < (index + 2)) + return DOH_DNS_OUT_OF_RANGE; + class = get16bit(doh, index); + if(DNS_CLASS_IN != class) + return DOH_DNS_UNEXPECTED_CLASS; /* unsupported */ + index += 2; + + if(dohlen < (index + 4)) + return DOH_DNS_OUT_OF_RANGE; + + ttl = get32bit(doh, index); + if(ttl < d->ttl) + d->ttl = ttl; + index += 4; + + if(dohlen < (index + 2)) + return DOH_DNS_OUT_OF_RANGE; + + rdlength = get16bit(doh, index); + index += 2; + if(dohlen < (index + rdlength)) + return DOH_DNS_OUT_OF_RANGE; + + rc = rdata(doh, dohlen, rdlength, type, index, d); + if(rc) + return rc; /* bad rdata */ + index += rdlength; + ancount--; + } + + nscount = get16bit(doh, 8); + while(nscount) { + rc = skipqname(doh, dohlen, &index); + if(rc) + return rc; /* bad qname */ + + if(dohlen < (index + 8)) + return DOH_DNS_OUT_OF_RANGE; + + index += 2 + 2 + 4; /* type, class and ttl */ + + if(dohlen < (index + 2)) + return DOH_DNS_OUT_OF_RANGE; + + rdlength = get16bit(doh, index); + index += 2; + if(dohlen < (index + rdlength)) + return DOH_DNS_OUT_OF_RANGE; + index += rdlength; + nscount--; + } + + arcount = get16bit(doh, 10); + while(arcount) { + rc = skipqname(doh, dohlen, &index); + if(rc) + return rc; /* bad qname */ + + if(dohlen < (index + 8)) + return DOH_DNS_OUT_OF_RANGE; + + index += 2 + 2 + 4; /* type, class and ttl */ + + if(dohlen < (index + 2)) + return DOH_DNS_OUT_OF_RANGE; + + rdlength = get16bit(doh, index); + index += 2; + if(dohlen < (index + rdlength)) + return DOH_DNS_OUT_OF_RANGE; + index += rdlength; + arcount--; + } + + if(index != dohlen) + return DOH_DNS_MALFORMAT; /* something is wrong */ + + if((type != DNS_TYPE_NS) && !d->numcname && !d->numaddr) + /* nothing stored! */ + return DOH_NO_CONTENT; + + return DOH_OK; /* ok */ +} + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static void showdoh(struct Curl_easy *data, + struct dohentry *d) +{ + int i; + infof(data, "TTL: %u seconds\n", d->ttl); + for(i = 0; i < d->numaddr; i++) { + struct dohaddr *a = &d->addr[i]; + if(a->type == DNS_TYPE_A) { + infof(data, "DOH A: %u.%u.%u.%u\n", + a->ip.v4[0], a->ip.v4[1], + a->ip.v4[2], a->ip.v4[3]); + } + else if(a->type == DNS_TYPE_AAAA) { + int j; + char buffer[128]; + char *ptr; + size_t len; + msnprintf(buffer, 128, "DOH AAAA: "); + ptr = &buffer[10]; + len = 118; + for(j = 0; j < 16; j += 2) { + size_t l; + msnprintf(ptr, len, "%s%02x%02x", j?":":"", d->addr[i].ip.v6[j], + d->addr[i].ip.v6[j + 1]); + l = strlen(ptr); + len -= l; + ptr += l; + } + infof(data, "%s\n", buffer); + } + } + for(i = 0; i < d->numcname; i++) { + infof(data, "CNAME: %s\n", d->cname[i].alloc); + } +} +#else +#define showdoh(x,y) +#endif + +/* + * doh2ai() + * + * This function returns a pointer to the first element of a newly allocated + * Curl_addrinfo struct linked list filled with the data from a set of DOH + * lookups. Curl_addrinfo is meant to work like the addrinfo struct does for + * a IPv6 stack, but usable also for IPv4, all hosts and environments. + * + * The memory allocated by this function *MUST* be free'd later on calling + * Curl_freeaddrinfo(). For each successful call to this function there + * must be an associated call later to Curl_freeaddrinfo(). + */ + +static Curl_addrinfo * +doh2ai(const struct dohentry *de, const char *hostname, int port) +{ + Curl_addrinfo *ai; + Curl_addrinfo *prevai = NULL; + Curl_addrinfo *firstai = NULL; + struct sockaddr_in *addr; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 *addr6; +#endif + CURLcode result = CURLE_OK; + int i; + + if(!de) + /* no input == no output! */ + return NULL; + + for(i = 0; i < de->numaddr; i++) { + size_t ss_size; + CURL_SA_FAMILY_T addrtype; + if(de->addr[i].type == DNS_TYPE_AAAA) { +#ifndef ENABLE_IPV6 + /* we can't handle IPv6 addresses */ + continue; +#else + ss_size = sizeof(struct sockaddr_in6); + addrtype = AF_INET6; +#endif + } + else { + ss_size = sizeof(struct sockaddr_in); + addrtype = AF_INET; + } + + ai = calloc(1, sizeof(Curl_addrinfo)); + if(!ai) { + result = CURLE_OUT_OF_MEMORY; + break; + } + ai->ai_canonname = strdup(hostname); + if(!ai->ai_canonname) { + result = CURLE_OUT_OF_MEMORY; + free(ai); + break; + } + ai->ai_addr = calloc(1, ss_size); + if(!ai->ai_addr) { + result = CURLE_OUT_OF_MEMORY; + free(ai->ai_canonname); + free(ai); + break; + } + + if(!firstai) + /* store the pointer we want to return from this function */ + firstai = ai; + + if(prevai) + /* make the previous entry point to this */ + prevai->ai_next = ai; + + ai->ai_family = addrtype; + + /* we return all names as STREAM, so when using this address for TFTP + the type must be ignored and conn->socktype be used instead! */ + ai->ai_socktype = SOCK_STREAM; + + ai->ai_addrlen = (curl_socklen_t)ss_size; + + /* leave the rest of the struct filled with zero */ + + switch(ai->ai_family) { + case AF_INET: + addr = (void *)ai->ai_addr; /* storage area for this info */ + DEBUGASSERT(sizeof(struct in_addr) == sizeof(de->addr[i].ip.v4)); + memcpy(&addr->sin_addr, &de->addr[i].ip.v4, sizeof(struct in_addr)); + addr->sin_family = (CURL_SA_FAMILY_T)addrtype; + addr->sin_port = htons((unsigned short)port); + break; + +#ifdef ENABLE_IPV6 + case AF_INET6: + addr6 = (void *)ai->ai_addr; /* storage area for this info */ + DEBUGASSERT(sizeof(struct in6_addr) == sizeof(de->addr[i].ip.v6)); + memcpy(&addr6->sin6_addr, &de->addr[i].ip.v6, sizeof(struct in6_addr)); + addr6->sin6_family = (CURL_SA_FAMILY_T)addrtype; + addr6->sin6_port = htons((unsigned short)port); + break; +#endif + } + + prevai = ai; + } + + if(result) { + Curl_freeaddrinfo(firstai); + firstai = NULL; + } + + return firstai; +} + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static const char *type2name(DNStype dnstype) +{ + return (dnstype == DNS_TYPE_A)?"A":"AAAA"; +} +#endif + +UNITTEST void de_cleanup(struct dohentry *d) +{ + int i = 0; + for(i = 0; i < d->numcname; i++) { + free(d->cname[i].alloc); + } +} + +CURLcode Curl_doh_is_resolved(struct connectdata *conn, + struct Curl_dns_entry **dnsp) +{ + struct Curl_easy *data = conn->data; + *dnsp = NULL; /* defaults to no response */ + + if(!data->req.doh.probe[0].easy && !data->req.doh.probe[1].easy) { + failf(data, "Could not DOH-resolve: %s", conn->async.hostname); + return conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY: + CURLE_COULDNT_RESOLVE_HOST; + } + else if(!data->req.doh.pending) { + DOHcode rc; + DOHcode rc2; + struct dohentry de; + /* remove DOH handles from multi handle and close them */ + curl_multi_remove_handle(data->multi, data->req.doh.probe[0].easy); + Curl_close(data->req.doh.probe[0].easy); + curl_multi_remove_handle(data->multi, data->req.doh.probe[1].easy); + Curl_close(data->req.doh.probe[1].easy); + + /* parse the responses, create the struct and return it! */ + init_dohentry(&de); + rc = doh_decode(data->req.doh.probe[0].serverdoh.memory, + data->req.doh.probe[0].serverdoh.size, + data->req.doh.probe[0].dnstype, + &de); + free(data->req.doh.probe[0].serverdoh.memory); + if(rc) { + infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc), + type2name(data->req.doh.probe[0].dnstype), + data->req.doh.host); + } + rc2 = doh_decode(data->req.doh.probe[1].serverdoh.memory, + data->req.doh.probe[1].serverdoh.size, + data->req.doh.probe[1].dnstype, + &de); + free(data->req.doh.probe[1].serverdoh.memory); + if(rc2) { + infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc2), + type2name(data->req.doh.probe[1].dnstype), + data->req.doh.host); + } + if(!rc || !rc2) { + struct Curl_dns_entry *dns; + struct Curl_addrinfo *ai; + + infof(data, "DOH Host name: %s\n", data->req.doh.host); + showdoh(data, &de); + + ai = doh2ai(&de, data->req.doh.host, data->req.doh.port); + if(!ai) { + de_cleanup(&de); + return CURLE_OUT_OF_MEMORY; + } + + if(data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + /* we got a response, store it in the cache */ + dns = Curl_cache_addr(data, ai, data->req.doh.host, data->req.doh.port); + + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + + de_cleanup(&de); + if(!dns) + /* returned failure, bail out nicely */ + Curl_freeaddrinfo(ai); + else { + conn->async.dns = dns; + *dnsp = dns; + return CURLE_OK; + } + } + de_cleanup(&de); + + return CURLE_COULDNT_RESOLVE_HOST; + } + + return CURLE_OK; +} + +#endif /* CURL_DISABLE_DOH */ diff --git a/dependencies/cmcurl/lib/doh.h b/dependencies/cmcurl/lib/doh.h new file mode 100644 index 0000000..34bfa6f --- /dev/null +++ b/dependencies/cmcurl/lib/doh.h @@ -0,0 +1,113 @@ +#ifndef HEADER_CURL_DOH_H +#define HEADER_CURL_DOH_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2018 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "urldata.h" +#include "curl_addrinfo.h" + +#ifndef CURL_DISABLE_DOH + +/* + * Curl_doh() resolve a name using DoH (DNS-over-HTTPS). It resolves a name + * and returns a 'Curl_addrinfo *' with the address information. + */ + +Curl_addrinfo *Curl_doh(struct connectdata *conn, + const char *hostname, + int port, + int *waitp); + +CURLcode Curl_doh_is_resolved(struct connectdata *conn, + struct Curl_dns_entry **dns); + +int Curl_doh_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); + +typedef enum { + DOH_OK, + DOH_DNS_BAD_LABEL, /* 1 */ + DOH_DNS_OUT_OF_RANGE, /* 2 */ + DOH_DNS_LABEL_LOOP, /* 3 */ + DOH_TOO_SMALL_BUFFER, /* 4 */ + DOH_OUT_OF_MEM, /* 5 */ + DOH_DNS_RDATA_LEN, /* 6 */ + DOH_DNS_MALFORMAT, /* 7 */ + DOH_DNS_BAD_RCODE, /* 8 - no such name */ + DOH_DNS_UNEXPECTED_TYPE, /* 9 */ + DOH_DNS_UNEXPECTED_CLASS, /* 10 */ + DOH_NO_CONTENT, /* 11 */ + DOH_DNS_BAD_ID /* 12 */ +} DOHcode; + +typedef enum { + DNS_TYPE_A = 1, + DNS_TYPE_NS = 2, + DNS_TYPE_CNAME = 5, + DNS_TYPE_AAAA = 28 +} DNStype; + +#define DOH_MAX_ADDR 24 +#define DOH_MAX_CNAME 4 + +struct cnamestore { + size_t len; /* length of cname */ + char *alloc; /* allocated pointer */ + size_t allocsize; /* allocated size */ +}; + +struct dohaddr { + int type; + union { + unsigned char v4[4]; /* network byte order */ + unsigned char v6[16]; + } ip; +}; + +struct dohentry { + unsigned int ttl; + int numaddr; + struct dohaddr addr[DOH_MAX_ADDR]; + int numcname; + struct cnamestore cname[DOH_MAX_CNAME]; +}; + + +#ifdef DEBUGBUILD +DOHcode doh_encode(const char *host, + DNStype dnstype, + unsigned char *dnsp, /* buffer */ + size_t len, /* buffer size */ + size_t *olen); /* output length */ +DOHcode doh_decode(unsigned char *doh, + size_t dohlen, + DNStype dnstype, + struct dohentry *d); +void de_cleanup(struct dohentry *d); +#endif + +#else /* if DOH is disabled */ +#define Curl_doh(a,b,c,d) NULL +#define Curl_doh_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST +#endif + +#endif /* HEADER_CURL_DOH_H */ diff --git a/dependencies/cmcurl/lib/dotdot.c b/dependencies/cmcurl/lib/dotdot.c new file mode 100644 index 0000000..2c6177a --- /dev/null +++ b/dependencies/cmcurl/lib/dotdot.c @@ -0,0 +1,182 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "dotdot.h" +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * "Remove Dot Segments" + * https://tools.ietf.org/html/rfc3986#section-5.2.4 + */ + +/* + * Curl_dedotdotify() + * @unittest: 1395 + * + * This function gets a zero-terminated path with dot and dotdot sequences + * passed in and strips them off according to the rules in RFC 3986 section + * 5.2.4. + * + * The function handles a query part ('?' + stuff) appended but it expects + * that fragments ('#' + stuff) have already been cut off. + * + * RETURNS + * + * an allocated dedotdotified output string + */ +char *Curl_dedotdotify(const char *input) +{ + size_t inlen = strlen(input); + char *clone; + size_t clen = inlen; /* the length of the cloned input */ + char *out = malloc(inlen + 1); + char *outptr; + char *orgclone; + char *queryp; + if(!out) + return NULL; /* out of memory */ + + *out = 0; /* zero terminates, for inputs like "./" */ + + /* get a cloned copy of the input */ + clone = strdup(input); + if(!clone) { + free(out); + return NULL; + } + orgclone = clone; + outptr = out; + + if(!*clone) { + /* zero length string, return that */ + free(out); + return clone; + } + + /* + * To handle query-parts properly, we must find it and remove it during the + * dotdot-operation and then append it again at the end to the output + * string. + */ + queryp = strchr(clone, '?'); + if(queryp) + *queryp = 0; + + do { + + /* A. If the input buffer begins with a prefix of "../" or "./", then + remove that prefix from the input buffer; otherwise, */ + + if(!strncmp("./", clone, 2)) { + clone += 2; + clen -= 2; + } + else if(!strncmp("../", clone, 3)) { + clone += 3; + clen -= 3; + } + + /* B. if the input buffer begins with a prefix of "/./" or "/.", where + "." is a complete path segment, then replace that prefix with "/" in + the input buffer; otherwise, */ + else if(!strncmp("/./", clone, 3)) { + clone += 2; + clen -= 2; + } + else if(!strcmp("/.", clone)) { + clone[1]='/'; + clone++; + clen -= 1; + } + + /* C. if the input buffer begins with a prefix of "/../" or "/..", where + ".." is a complete path segment, then replace that prefix with "/" in + the input buffer and remove the last segment and its preceding "/" (if + any) from the output buffer; otherwise, */ + + else if(!strncmp("/../", clone, 4)) { + clone += 3; + clen -= 3; + /* remove the last segment from the output buffer */ + while(outptr > out) { + outptr--; + if(*outptr == '/') + break; + } + *outptr = 0; /* zero-terminate where it stops */ + } + else if(!strcmp("/..", clone)) { + clone[2]='/'; + clone += 2; + clen -= 2; + /* remove the last segment from the output buffer */ + while(outptr > out) { + outptr--; + if(*outptr == '/') + break; + } + *outptr = 0; /* zero-terminate where it stops */ + } + + /* D. if the input buffer consists only of "." or "..", then remove + that from the input buffer; otherwise, */ + + else if(!strcmp(".", clone) || !strcmp("..", clone)) { + *clone = 0; + *out = 0; + } + + else { + /* E. move the first path segment in the input buffer to the end of + the output buffer, including the initial "/" character (if any) and + any subsequent characters up to, but not including, the next "/" + character or the end of the input buffer. */ + + do { + *outptr++ = *clone++; + clen--; + } while(*clone && (*clone != '/')); + *outptr = 0; + } + + } while(*clone); + + if(queryp) { + size_t qlen; + /* There was a query part, append that to the output. The 'clone' string + may now have been altered so we copy from the original input string + from the correct index. */ + size_t oindex = queryp - orgclone; + qlen = strlen(&input[oindex]); + memcpy(outptr, &input[oindex], qlen + 1); /* include the end zero byte */ + } + + free(orgclone); + return out; +} diff --git a/dependencies/cmcurl/lib/dotdot.h b/dependencies/cmcurl/lib/dotdot.h new file mode 100644 index 0000000..125af43 --- /dev/null +++ b/dependencies/cmcurl/lib/dotdot.h @@ -0,0 +1,25 @@ +#ifndef HEADER_CURL_DOTDOT_H +#define HEADER_CURL_DOTDOT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +char *Curl_dedotdotify(const char *input); +#endif /* HEADER_CURL_DOTDOT_H */ diff --git a/dependencies/cmcurl/lib/easy.c b/dependencies/cmcurl/lib/easy.c new file mode 100644 index 0000000..4a6f965 --- /dev/null +++ b/dependencies/cmcurl/lib/easy.c @@ -0,0 +1,1157 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +/* + * See comment in curl_memory.h for the explanation of this sanity check. + */ + +#ifdef CURLX_NO_MEMORY_CALLBACKS +#error "libcurl shall not ever be built with CURLX_NO_MEMORY_CALLBACKS defined" +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#include "urldata.h" +#include +#include "transfer.h" +#include "vtls/vtls.h" +#include "url.h" +#include "getinfo.h" +#include "hostip.h" +#include "share.h" +#include "strdup.h" +#include "progress.h" +#include "easyif.h" +#include "multiif.h" +#include "select.h" +#include "sendf.h" /* for failf function prototype */ +#include "connect.h" /* for Curl_getconnectinfo */ +#include "slist.h" +#include "mime.h" +#include "amigaos.h" +#include "non-ascii.h" +#include "warnless.h" +#include "multiif.h" +#include "sigpipe.h" +#include "ssh.h" +#include "setopt.h" +#include "http_digest.h" +#include "system_win32.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +void Curl_version_init(void); + +/* true globals -- for curl_global_init() and curl_global_cleanup() */ +static unsigned int initialized; +static long init_flags; + +/* + * strdup (and other memory functions) is redefined in complicated + * ways, but at this point it must be defined as the system-supplied strdup + * so the callback pointer is initialized correctly. + */ +#if defined(_WIN32_WCE) +#define system_strdup _strdup +#elif !defined(HAVE_STRDUP) +#define system_strdup curlx_strdup +#else +#define system_strdup strdup +#endif + +#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__) +# pragma warning(disable:4232) /* MSVC extension, dllimport identity */ +#endif + +#ifndef __SYMBIAN32__ +/* + * If a memory-using function (like curl_getenv) is used before + * curl_global_init() is called, we need to have these pointers set already. + */ +curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc; +curl_free_callback Curl_cfree = (curl_free_callback)free; +curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc; +curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup; +curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc; +#if defined(WIN32) && defined(UNICODE) +curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup; +#endif +#else +/* + * Symbian OS doesn't support initialization to code in writable static data. + * Initialization will occur in the curl_global_init() call. + */ +curl_malloc_callback Curl_cmalloc; +curl_free_callback Curl_cfree; +curl_realloc_callback Curl_crealloc; +curl_strdup_callback Curl_cstrdup; +curl_calloc_callback Curl_ccalloc; +#endif + +#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__) +# pragma warning(default:4232) /* MSVC extension, dllimport identity */ +#endif + +/** + * curl_global_init() globally initializes curl given a bitwise set of the + * different features of what to initialize. + */ +static CURLcode global_init(long flags, bool memoryfuncs) +{ + if(initialized++) + return CURLE_OK; + + if(memoryfuncs) { + /* Setup the default memory functions here (again) */ + Curl_cmalloc = (curl_malloc_callback)malloc; + Curl_cfree = (curl_free_callback)free; + Curl_crealloc = (curl_realloc_callback)realloc; + Curl_cstrdup = (curl_strdup_callback)system_strdup; + Curl_ccalloc = (curl_calloc_callback)calloc; +#if defined(WIN32) && defined(UNICODE) + Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup; +#endif + } + + if(!Curl_ssl_init()) { + DEBUGF(fprintf(stderr, "Error: Curl_ssl_init failed\n")); + return CURLE_FAILED_INIT; + } + +#ifdef WIN32 + if(Curl_win32_init(flags)) { + DEBUGF(fprintf(stderr, "Error: win32_init failed\n")); + return CURLE_FAILED_INIT; + } +#endif + +#ifdef __AMIGA__ + if(!Curl_amiga_init()) { + DEBUGF(fprintf(stderr, "Error: Curl_amiga_init failed\n")); + return CURLE_FAILED_INIT; + } +#endif + +#ifdef NETWARE + if(netware_init()) { + DEBUGF(fprintf(stderr, "Warning: LONG namespace not available\n")); + } +#endif + + if(Curl_resolver_global_init()) { + DEBUGF(fprintf(stderr, "Error: resolver_global_init failed\n")); + return CURLE_FAILED_INIT; + } + + (void)Curl_ipv6works(); + +#if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_INIT) + if(libssh2_init(0)) { + DEBUGF(fprintf(stderr, "Error: libssh2_init failed\n")); + return CURLE_FAILED_INIT; + } +#endif + +#if defined(USE_LIBSSH) + if(ssh_init()) { + DEBUGF(fprintf(stderr, "Error: libssh_init failed\n")); + return CURLE_FAILED_INIT; + } +#endif + + if(flags & CURL_GLOBAL_ACK_EINTR) + Curl_ack_eintr = 1; + + init_flags = flags; + + Curl_version_init(); + + return CURLE_OK; +} + + +/** + * curl_global_init() globally initializes curl given a bitwise set of the + * different features of what to initialize. + */ +CURLcode curl_global_init(long flags) +{ + return global_init(flags, TRUE); +} + +/* + * curl_global_init_mem() globally initializes curl and also registers the + * user provided callback routines. + */ +CURLcode curl_global_init_mem(long flags, curl_malloc_callback m, + curl_free_callback f, curl_realloc_callback r, + curl_strdup_callback s, curl_calloc_callback c) +{ + /* Invalid input, return immediately */ + if(!m || !f || !r || !s || !c) + return CURLE_FAILED_INIT; + + if(initialized) { + /* Already initialized, don't do it again, but bump the variable anyway to + work like curl_global_init() and require the same amount of cleanup + calls. */ + initialized++; + return CURLE_OK; + } + + /* set memory functions before global_init() in case it wants memory + functions */ + Curl_cmalloc = m; + Curl_cfree = f; + Curl_cstrdup = s; + Curl_crealloc = r; + Curl_ccalloc = c; + + /* Call the actual init function, but without setting */ + return global_init(flags, FALSE); +} + +/** + * curl_global_cleanup() globally cleanups curl, uses the value of + * "init_flags" to determine what needs to be cleaned up and what doesn't. + */ +void curl_global_cleanup(void) +{ + if(!initialized) + return; + + if(--initialized) + return; + + Curl_ssl_cleanup(); + Curl_resolver_global_cleanup(); + +#ifdef WIN32 + Curl_win32_cleanup(init_flags); +#endif + + Curl_amiga_cleanup(); + +#if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_EXIT) + (void)libssh2_exit(); +#endif + +#if defined(USE_LIBSSH) + (void)ssh_finalize(); +#endif + + init_flags = 0; +} + +/* + * curl_easy_init() is the external interface to alloc, setup and init an + * easy handle that is returned. If anything goes wrong, NULL is returned. + */ +struct Curl_easy *curl_easy_init(void) +{ + CURLcode result; + struct Curl_easy *data; + + /* Make sure we inited the global SSL stuff */ + if(!initialized) { + result = curl_global_init(CURL_GLOBAL_DEFAULT); + if(result) { + /* something in the global init failed, return nothing */ + DEBUGF(fprintf(stderr, "Error: curl_global_init failed\n")); + return NULL; + } + } + + /* We use curl_open() with undefined URL so far */ + result = Curl_open(&data); + if(result) { + DEBUGF(fprintf(stderr, "Error: Curl_open failed\n")); + return NULL; + } + + return data; +} + +#ifdef CURLDEBUG + +struct socketmonitor { + struct socketmonitor *next; /* the next node in the list or NULL */ + struct pollfd socket; /* socket info of what to monitor */ +}; + +struct events { + long ms; /* timeout, run the timeout function when reached */ + bool msbump; /* set TRUE when timeout is set by callback */ + int num_sockets; /* number of nodes in the monitor list */ + struct socketmonitor *list; /* list of sockets to monitor */ + int running_handles; /* store the returned number */ +}; + +/* events_timer + * + * Callback that gets called with a new value when the timeout should be + * updated. + */ + +static int events_timer(struct Curl_multi *multi, /* multi handle */ + long timeout_ms, /* see above */ + void *userp) /* private callback pointer */ +{ + struct events *ev = userp; + (void)multi; + if(timeout_ms == -1) + /* timeout removed */ + timeout_ms = 0; + else if(timeout_ms == 0) + /* timeout is already reached! */ + timeout_ms = 1; /* trigger asap */ + + ev->ms = timeout_ms; + ev->msbump = TRUE; + return 0; +} + + +/* poll2cselect + * + * convert from poll() bit definitions to libcurl's CURL_CSELECT_* ones + */ +static int poll2cselect(int pollmask) +{ + int omask = 0; + if(pollmask & POLLIN) + omask |= CURL_CSELECT_IN; + if(pollmask & POLLOUT) + omask |= CURL_CSELECT_OUT; + if(pollmask & POLLERR) + omask |= CURL_CSELECT_ERR; + return omask; +} + + +/* socketcb2poll + * + * convert from libcurl' CURL_POLL_* bit definitions to poll()'s + */ +static short socketcb2poll(int pollmask) +{ + short omask = 0; + if(pollmask & CURL_POLL_IN) + omask |= POLLIN; + if(pollmask & CURL_POLL_OUT) + omask |= POLLOUT; + return omask; +} + +/* events_socket + * + * Callback that gets called with information about socket activity to + * monitor. + */ +static int events_socket(struct Curl_easy *easy, /* easy handle */ + curl_socket_t s, /* socket */ + int what, /* see above */ + void *userp, /* private callback + pointer */ + void *socketp) /* private socket + pointer */ +{ + struct events *ev = userp; + struct socketmonitor *m; + struct socketmonitor *prev = NULL; + +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) easy; +#endif + (void)socketp; + + m = ev->list; + while(m) { + if(m->socket.fd == s) { + + if(what == CURL_POLL_REMOVE) { + struct socketmonitor *nxt = m->next; + /* remove this node from the list of monitored sockets */ + if(prev) + prev->next = nxt; + else + ev->list = nxt; + free(m); + m = nxt; + infof(easy, "socket cb: socket %d REMOVED\n", s); + } + else { + /* The socket 's' is already being monitored, update the activity + mask. Convert from libcurl bitmask to the poll one. */ + m->socket.events = socketcb2poll(what); + infof(easy, "socket cb: socket %d UPDATED as %s%s\n", s, + (what&CURL_POLL_IN)?"IN":"", + (what&CURL_POLL_OUT)?"OUT":""); + } + break; + } + prev = m; + m = m->next; /* move to next node */ + } + if(!m) { + if(what == CURL_POLL_REMOVE) { + /* this happens a bit too often, libcurl fix perhaps? */ + /* fprintf(stderr, + "%s: socket %d asked to be REMOVED but not present!\n", + __func__, s); */ + } + else { + m = malloc(sizeof(struct socketmonitor)); + if(m) { + m->next = ev->list; + m->socket.fd = s; + m->socket.events = socketcb2poll(what); + m->socket.revents = 0; + ev->list = m; + infof(easy, "socket cb: socket %d ADDED as %s%s\n", s, + (what&CURL_POLL_IN)?"IN":"", + (what&CURL_POLL_OUT)?"OUT":""); + } + else + return CURLE_OUT_OF_MEMORY; + } + } + + return 0; +} + + +/* + * events_setup() + * + * Do the multi handle setups that only event-based transfers need. + */ +static void events_setup(struct Curl_multi *multi, struct events *ev) +{ + /* timer callback */ + curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, events_timer); + curl_multi_setopt(multi, CURLMOPT_TIMERDATA, ev); + + /* socket callback */ + curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, events_socket); + curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, ev); +} + + +/* wait_or_timeout() + * + * waits for activity on any of the given sockets, or the timeout to trigger. + */ + +static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev) +{ + bool done = FALSE; + CURLMcode mcode = CURLM_OK; + CURLcode result = CURLE_OK; + + while(!done) { + CURLMsg *msg; + struct socketmonitor *m; + struct pollfd *f; + struct pollfd fds[4]; + int numfds = 0; + int pollrc; + int i; + struct curltime before; + struct curltime after; + + /* populate the fds[] array */ + for(m = ev->list, f = &fds[0]; m; m = m->next) { + f->fd = m->socket.fd; + f->events = m->socket.events; + f->revents = 0; + /* fprintf(stderr, "poll() %d check socket %d\n", numfds, f->fd); */ + f++; + numfds++; + } + + /* get the time stamp to use to figure out how long poll takes */ + before = Curl_now(); + + /* wait for activity or timeout */ + pollrc = Curl_poll(fds, numfds, (int)ev->ms); + + after = Curl_now(); + + ev->msbump = FALSE; /* reset here */ + + if(0 == pollrc) { + /* timeout! */ + ev->ms = 0; + /* fprintf(stderr, "call curl_multi_socket_action(TIMEOUT)\n"); */ + mcode = curl_multi_socket_action(multi, CURL_SOCKET_TIMEOUT, 0, + &ev->running_handles); + } + else if(pollrc > 0) { + /* loop over the monitored sockets to see which ones had activity */ + for(i = 0; i< numfds; i++) { + if(fds[i].revents) { + /* socket activity, tell libcurl */ + int act = poll2cselect(fds[i].revents); /* convert */ + infof(multi->easyp, "call curl_multi_socket_action(socket %d)\n", + fds[i].fd); + mcode = curl_multi_socket_action(multi, fds[i].fd, act, + &ev->running_handles); + } + } + + if(!ev->msbump) { + /* If nothing updated the timeout, we decrease it by the spent time. + * If it was updated, it has the new timeout time stored already. + */ + timediff_t timediff = Curl_timediff(after, before); + if(timediff > 0) { + if(timediff > ev->ms) + ev->ms = 0; + else + ev->ms -= (long)timediff; + } + } + } + else + return CURLE_RECV_ERROR; + + if(mcode) + return CURLE_URL_MALFORMAT; + + /* we don't really care about the "msgs_in_queue" value returned in the + second argument */ + msg = curl_multi_info_read(multi, &pollrc); + if(msg) { + result = msg->data.result; + done = TRUE; + } + } + + return result; +} + + +/* easy_events() + * + * Runs a transfer in a blocking manner using the events-based API + */ +static CURLcode easy_events(struct Curl_multi *multi) +{ + /* this struct is made static to allow it to be used after this function + returns and curl_multi_remove_handle() is called */ + static struct events evs = {2, FALSE, 0, NULL, 0}; + + /* if running event-based, do some further multi inits */ + events_setup(multi, &evs); + + return wait_or_timeout(multi, &evs); +} +#else /* CURLDEBUG */ +/* when not built with debug, this function doesn't exist */ +#define easy_events(x) CURLE_NOT_BUILT_IN +#endif + +static CURLcode easy_transfer(struct Curl_multi *multi) +{ + bool done = FALSE; + CURLMcode mcode = CURLM_OK; + CURLcode result = CURLE_OK; + + while(!done && !mcode) { + int still_running = 0; + bool gotsocket = FALSE; + + mcode = Curl_multi_wait(multi, NULL, 0, 1000, NULL, &gotsocket); + + if(!mcode) { + if(!gotsocket) { + long sleep_ms; + + /* If it returns without any filedescriptor instantly, we need to + avoid busy-looping during periods where it has nothing particular + to wait for */ + curl_multi_timeout(multi, &sleep_ms); + if(sleep_ms) { + if(sleep_ms > 1000) + sleep_ms = 1000; + Curl_wait_ms((int)sleep_ms); + } + } + + mcode = curl_multi_perform(multi, &still_running); + } + + /* only read 'still_running' if curl_multi_perform() return OK */ + if(!mcode && !still_running) { + int rc; + CURLMsg *msg = curl_multi_info_read(multi, &rc); + if(msg) { + result = msg->data.result; + done = TRUE; + } + } + } + + /* Make sure to return some kind of error if there was a multi problem */ + if(mcode) { + result = (mcode == CURLM_OUT_OF_MEMORY) ? CURLE_OUT_OF_MEMORY : + /* The other multi errors should never happen, so return + something suitably generic */ + CURLE_BAD_FUNCTION_ARGUMENT; + } + + return result; +} + + +/* + * easy_perform() is the external interface that performs a blocking + * transfer as previously setup. + * + * CONCEPT: This function creates a multi handle, adds the easy handle to it, + * runs curl_multi_perform() until the transfer is done, then detaches the + * easy handle, destroys the multi handle and returns the easy handle's return + * code. + * + * REALITY: it can't just create and destroy the multi handle that easily. It + * needs to keep it around since if this easy handle is used again by this + * function, the same multi handle must be re-used so that the same pools and + * caches can be used. + * + * DEBUG: if 'events' is set TRUE, this function will use a replacement engine + * instead of curl_multi_perform() and use curl_multi_socket_action(). + */ +static CURLcode easy_perform(struct Curl_easy *data, bool events) +{ + struct Curl_multi *multi; + CURLMcode mcode; + CURLcode result = CURLE_OK; + SIGPIPE_VARIABLE(pipe_st); + + if(!data) + return CURLE_BAD_FUNCTION_ARGUMENT; + + if(data->set.errorbuffer) + /* clear this as early as possible */ + data->set.errorbuffer[0] = 0; + + if(data->multi) { + failf(data, "easy handle already used in multi handle"); + return CURLE_FAILED_INIT; + } + + if(data->multi_easy) + multi = data->multi_easy; + else { + /* this multi handle will only ever have a single easy handled attached + to it, so make it use minimal hashes */ + multi = Curl_multi_handle(1, 3); + if(!multi) + return CURLE_OUT_OF_MEMORY; + data->multi_easy = multi; + } + + if(multi->in_callback) + return CURLE_RECURSIVE_API_CALL; + + /* Copy the MAXCONNECTS option to the multi handle */ + curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects); + + mcode = curl_multi_add_handle(multi, data); + if(mcode) { + curl_multi_cleanup(multi); + if(mcode == CURLM_OUT_OF_MEMORY) + return CURLE_OUT_OF_MEMORY; + return CURLE_FAILED_INIT; + } + + sigpipe_ignore(data, &pipe_st); + + /* assign this after curl_multi_add_handle() since that function checks for + it and rejects this handle otherwise */ + data->multi = multi; + + /* run the transfer */ + result = events ? easy_events(multi) : easy_transfer(multi); + + /* ignoring the return code isn't nice, but atm we can't really handle + a failure here, room for future improvement! */ + (void)curl_multi_remove_handle(multi, data); + + sigpipe_restore(&pipe_st); + + /* The multi handle is kept alive, owned by the easy handle */ + return result; +} + + +/* + * curl_easy_perform() is the external interface that performs a blocking + * transfer as previously setup. + */ +CURLcode curl_easy_perform(struct Curl_easy *data) +{ + return easy_perform(data, FALSE); +} + +#ifdef CURLDEBUG +/* + * curl_easy_perform_ev() is the external interface that performs a blocking + * transfer using the event-based API internally. + */ +CURLcode curl_easy_perform_ev(struct Curl_easy *data) +{ + return easy_perform(data, TRUE); +} + +#endif + +/* + * curl_easy_cleanup() is the external interface to cleaning/freeing the given + * easy handle. + */ +void curl_easy_cleanup(struct Curl_easy *data) +{ + SIGPIPE_VARIABLE(pipe_st); + + if(!data) + return; + + sigpipe_ignore(data, &pipe_st); + Curl_close(data); + sigpipe_restore(&pipe_st); +} + +/* + * curl_easy_getinfo() is an external interface that allows an app to retrieve + * information from a performed transfer and similar. + */ +#undef curl_easy_getinfo +CURLcode curl_easy_getinfo(struct Curl_easy *data, CURLINFO info, ...) +{ + va_list arg; + void *paramp; + CURLcode result; + + va_start(arg, info); + paramp = va_arg(arg, void *); + + result = Curl_getinfo(data, info, paramp); + + va_end(arg); + return result; +} + +static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src) +{ + CURLcode result = CURLE_OK; + enum dupstring i; + + /* Copy src->set into dst->set first, then deal with the strings + afterwards */ + dst->set = src->set; + Curl_mime_initpart(&dst->set.mimepost, dst); + + /* clear all string pointers first */ + memset(dst->set.str, 0, STRING_LAST * sizeof(char *)); + + /* duplicate all strings */ + for(i = (enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) { + result = Curl_setstropt(&dst->set.str[i], src->set.str[i]); + if(result) + return result; + } + + /* duplicate memory areas pointed to */ + i = STRING_COPYPOSTFIELDS; + if(src->set.postfieldsize && src->set.str[i]) { + /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */ + dst->set.str[i] = Curl_memdup(src->set.str[i], + curlx_sotouz(src->set.postfieldsize)); + if(!dst->set.str[i]) + return CURLE_OUT_OF_MEMORY; + /* point to the new copy */ + dst->set.postfields = dst->set.str[i]; + } + + /* Duplicate mime data. */ + result = Curl_mime_duppart(&dst->set.mimepost, &src->set.mimepost); + + if(src->set.resolve) + dst->change.resolve = dst->set.resolve; + + return result; +} + +/* + * curl_easy_duphandle() is an external interface to allow duplication of a + * given input easy handle. The returned handle will be a new working handle + * with all options set exactly as the input source handle. + */ +struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) +{ + struct Curl_easy *outcurl = calloc(1, sizeof(struct Curl_easy)); + if(NULL == outcurl) + goto fail; + + /* + * We setup a few buffers we need. We should probably make them + * get setup on-demand in the code, as that would probably decrease + * the likeliness of us forgetting to init a buffer here in the future. + */ + outcurl->set.buffer_size = data->set.buffer_size; + outcurl->state.buffer = malloc(outcurl->set.buffer_size + 1); + if(!outcurl->state.buffer) + goto fail; + + outcurl->state.headerbuff = malloc(HEADERSIZE); + if(!outcurl->state.headerbuff) + goto fail; + outcurl->state.headersize = HEADERSIZE; + + /* copy all userdefined values */ + if(dupset(outcurl, data)) + goto fail; + + /* the connection cache is setup on demand */ + outcurl->state.conn_cache = NULL; + + outcurl->state.lastconnect = NULL; + + outcurl->progress.flags = data->progress.flags; + outcurl->progress.callback = data->progress.callback; + + if(data->cookies) { + /* If cookies are enabled in the parent handle, we enable them + in the clone as well! */ + outcurl->cookies = Curl_cookie_init(data, + data->cookies->filename, + outcurl->cookies, + data->set.cookiesession); + if(!outcurl->cookies) + goto fail; + } + + /* duplicate all values in 'change' */ + if(data->change.cookielist) { + outcurl->change.cookielist = + Curl_slist_duplicate(data->change.cookielist); + if(!outcurl->change.cookielist) + goto fail; + } + + if(data->change.url) { + outcurl->change.url = strdup(data->change.url); + if(!outcurl->change.url) + goto fail; + outcurl->change.url_alloc = TRUE; + } + + if(data->change.referer) { + outcurl->change.referer = strdup(data->change.referer); + if(!outcurl->change.referer) + goto fail; + outcurl->change.referer_alloc = TRUE; + } + + /* Reinitialize an SSL engine for the new handle + * note: the engine name has already been copied by dupset */ + if(outcurl->set.str[STRING_SSL_ENGINE]) { + if(Curl_ssl_set_engine(outcurl, outcurl->set.str[STRING_SSL_ENGINE])) + goto fail; + } + + /* Clone the resolver handle, if present, for the new handle */ + if(Curl_resolver_duphandle(outcurl, + &outcurl->state.resolver, + data->state.resolver)) + goto fail; + + Curl_convert_setup(outcurl); + + Curl_initinfo(outcurl); + + outcurl->magic = CURLEASY_MAGIC_NUMBER; + + /* we reach this point and thus we are OK */ + + return outcurl; + + fail: + + if(outcurl) { + curl_slist_free_all(outcurl->change.cookielist); + outcurl->change.cookielist = NULL; + Curl_safefree(outcurl->state.buffer); + Curl_safefree(outcurl->state.headerbuff); + Curl_safefree(outcurl->change.url); + Curl_safefree(outcurl->change.referer); + Curl_freeset(outcurl); + free(outcurl); + } + + return NULL; +} + +/* + * curl_easy_reset() is an external interface that allows an app to re- + * initialize a session handle to the default values. + */ +void curl_easy_reset(struct Curl_easy *data) +{ + Curl_free_request_state(data); + + /* zero out UserDefined data: */ + Curl_freeset(data); + memset(&data->set, 0, sizeof(struct UserDefined)); + (void)Curl_init_userdefined(data); + + /* zero out Progress data: */ + memset(&data->progress, 0, sizeof(struct Progress)); + + /* zero out PureInfo data: */ + Curl_initinfo(data); + + data->progress.flags |= PGRS_HIDE; + data->state.current_speed = -1; /* init to negative == impossible */ + + /* zero out authentication data: */ + memset(&data->state.authhost, 0, sizeof(struct auth)); + memset(&data->state.authproxy, 0, sizeof(struct auth)); + +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) + Curl_http_auth_cleanup_digest(data); +#endif +} + +/* + * curl_easy_pause() allows an application to pause or unpause a specific + * transfer and direction. This function sets the full new state for the + * current connection this easy handle operates on. + * + * NOTE: if you have the receiving paused and you call this function to remove + * the pausing, you may get your write callback called at this point. + * + * Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h + * + * NOTE: This is one of few API functions that are allowed to be called from + * within a callback. + */ +CURLcode curl_easy_pause(struct Curl_easy *data, int action) +{ + struct SingleRequest *k = &data->req; + CURLcode result = CURLE_OK; + + /* first switch off both pause bits */ + int newstate = k->keepon &~ (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE); + + /* set the new desired pause bits */ + newstate |= ((action & CURLPAUSE_RECV)?KEEP_RECV_PAUSE:0) | + ((action & CURLPAUSE_SEND)?KEEP_SEND_PAUSE:0); + + /* put it back in the keepon */ + k->keepon = newstate; + + if(!(newstate & KEEP_RECV_PAUSE) && data->state.tempcount) { + /* there are buffers for sending that can be delivered as the receive + pausing is lifted! */ + unsigned int i; + unsigned int count = data->state.tempcount; + struct tempbuf writebuf[3]; /* there can only be three */ + struct connectdata *conn = data->conn; + struct Curl_easy *saved_data = NULL; + + /* copy the structs to allow for immediate re-pausing */ + for(i = 0; i < data->state.tempcount; i++) { + writebuf[i] = data->state.tempwrite[i]; + data->state.tempwrite[i].buf = NULL; + } + data->state.tempcount = 0; + + /* set the connection's current owner */ + if(conn->data != data) { + saved_data = conn->data; + conn->data = data; + } + + for(i = 0; i < count; i++) { + /* even if one function returns error, this loops through and frees all + buffers */ + if(!result) + result = Curl_client_write(conn, writebuf[i].type, writebuf[i].buf, + writebuf[i].len); + free(writebuf[i].buf); + } + + /* recover previous owner of the connection */ + if(saved_data) + conn->data = saved_data; + + if(result) + return result; + } + + /* if there's no error and we're not pausing both directions, we want + to have this handle checked soon */ + if(!result && + ((newstate&(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) != + (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) ) + Curl_expire(data, 0, EXPIRE_RUN_NOW); /* get this handle going again */ + + /* This transfer may have been moved in or out of the bundle, update + the corresponding socket callback, if used */ + Curl_updatesocket(data); + + return result; +} + + +static CURLcode easy_connection(struct Curl_easy *data, + curl_socket_t *sfd, + struct connectdata **connp) +{ + if(data == NULL) + return CURLE_BAD_FUNCTION_ARGUMENT; + + /* only allow these to be called on handles with CURLOPT_CONNECT_ONLY */ + if(!data->set.connect_only) { + failf(data, "CONNECT_ONLY is required!"); + return CURLE_UNSUPPORTED_PROTOCOL; + } + + *sfd = Curl_getconnectinfo(data, connp); + + if(*sfd == CURL_SOCKET_BAD) { + failf(data, "Failed to get recent socket"); + return CURLE_UNSUPPORTED_PROTOCOL; + } + + return CURLE_OK; +} + +/* + * Receives data from the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + * Returns CURLE_OK on success, error code on error. + */ +CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen, + size_t *n) +{ + curl_socket_t sfd; + CURLcode result; + ssize_t n1; + struct connectdata *c; + + if(Curl_is_in_callback(data)) + return CURLE_RECURSIVE_API_CALL; + + result = easy_connection(data, &sfd, &c); + if(result) + return result; + + *n = 0; + result = Curl_read(c, sfd, buffer, buflen, &n1); + + if(result) + return result; + + *n = (size_t)n1; + + return CURLE_OK; +} + +/* + * Sends data over the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer, + size_t buflen, size_t *n) +{ + curl_socket_t sfd; + CURLcode result; + ssize_t n1; + struct connectdata *c = NULL; + + if(Curl_is_in_callback(data)) + return CURLE_RECURSIVE_API_CALL; + + result = easy_connection(data, &sfd, &c); + if(result) + return result; + + *n = 0; + result = Curl_write(c, sfd, buffer, buflen, &n1); + + if(n1 == -1) + return CURLE_SEND_ERROR; + + /* detect EAGAIN */ + if(!result && !n1) + return CURLE_AGAIN; + + *n = (size_t)n1; + + return result; +} + +/* + * Performs connection upkeep for the given session handle. + */ +CURLcode curl_easy_upkeep(struct Curl_easy *data) +{ + /* Verify that we got an easy handle we can work with. */ + if(!GOOD_EASY_HANDLE(data)) + return CURLE_BAD_FUNCTION_ARGUMENT; + + if(data->multi_easy) { + /* Use the common function to keep connections alive. */ + return Curl_upkeep(&data->multi_easy->conn_cache, data); + } + else { + /* No connections, so just return success */ + return CURLE_OK; + } +} diff --git a/dependencies/cmcurl/lib/easyif.h b/dependencies/cmcurl/lib/easyif.h new file mode 100644 index 0000000..6ba7e54 --- /dev/null +++ b/dependencies/cmcurl/lib/easyif.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_EASYIF_H +#define HEADER_CURL_EASYIF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Prototypes for library-wide functions provided by easy.c + */ +#ifdef CURLDEBUG +CURL_EXTERN CURLcode curl_easy_perform_ev(struct Curl_easy *easy); +#endif + +#endif /* HEADER_CURL_EASYIF_H */ diff --git a/dependencies/cmcurl/lib/escape.c b/dependencies/cmcurl/lib/escape.c new file mode 100644 index 0000000..7121db3 --- /dev/null +++ b/dependencies/cmcurl/lib/escape.c @@ -0,0 +1,244 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* Escape and unescape URL encoding in strings. The functions return a new + * allocated string or NULL if an error occurred. */ + +#include "curl_setup.h" + +#include + +#include "urldata.h" +#include "warnless.h" +#include "non-ascii.h" +#include "escape.h" +#include "strdup.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* Portable character check (remember EBCDIC). Do not use isalnum() because + its behavior is altered by the current locale. + See https://tools.ietf.org/html/rfc3986#section-2.3 +*/ +bool Curl_isunreserved(unsigned char in) +{ + switch(in) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': + case '-': case '.': case '_': case '~': + return TRUE; + default: + break; + } + return FALSE; +} + +/* for ABI-compatibility with previous versions */ +char *curl_escape(const char *string, int inlength) +{ + return curl_easy_escape(NULL, string, inlength); +} + +/* for ABI-compatibility with previous versions */ +char *curl_unescape(const char *string, int length) +{ + return curl_easy_unescape(NULL, string, length, NULL); +} + +char *curl_easy_escape(struct Curl_easy *data, const char *string, + int inlength) +{ + size_t alloc; + char *ns; + char *testing_ptr = NULL; + size_t newlen; + size_t strindex = 0; + size_t length; + CURLcode result; + + if(inlength < 0) + return NULL; + + alloc = (inlength?(size_t)inlength:strlen(string)) + 1; + newlen = alloc; + + ns = malloc(alloc); + if(!ns) + return NULL; + + length = alloc-1; + while(length--) { + unsigned char in = *string; /* we need to treat the characters unsigned */ + + if(Curl_isunreserved(in)) + /* just copy this */ + ns[strindex++] = in; + else { + /* encode it */ + newlen += 2; /* the size grows with two, since this'll become a %XX */ + if(newlen > alloc) { + alloc *= 2; + testing_ptr = Curl_saferealloc(ns, alloc); + if(!testing_ptr) + return NULL; + ns = testing_ptr; + } + + result = Curl_convert_to_network(data, (char *)&in, 1); + if(result) { + /* Curl_convert_to_network calls failf if unsuccessful */ + free(ns); + return NULL; + } + + msnprintf(&ns[strindex], 4, "%%%02X", in); + + strindex += 3; + } + string++; + } + ns[strindex] = 0; /* terminate it */ + return ns; +} + +/* + * Curl_urldecode() URL decodes the given string. + * + * Optionally detects control characters (byte codes lower than 32) in the + * data and rejects such data. + * + * Returns a pointer to a malloced string in *ostring with length given in + * *olen. If length == 0, the length is assumed to be strlen(string). + * + * 'data' can be set to NULL but then this function can't convert network + * data to host for non-ascii. + */ +CURLcode Curl_urldecode(struct Curl_easy *data, + const char *string, size_t length, + char **ostring, size_t *olen, + bool reject_ctrl) +{ + size_t alloc = (length?length:strlen(string)) + 1; + char *ns = malloc(alloc); + size_t strindex = 0; + unsigned long hex; + CURLcode result = CURLE_OK; + + if(!ns) + return CURLE_OUT_OF_MEMORY; + + while(--alloc > 0) { + unsigned char in = *string; + if(('%' == in) && (alloc > 2) && + ISXDIGIT(string[1]) && ISXDIGIT(string[2])) { + /* this is two hexadecimal digits following a '%' */ + char hexstr[3]; + char *ptr; + hexstr[0] = string[1]; + hexstr[1] = string[2]; + hexstr[2] = 0; + + hex = strtoul(hexstr, &ptr, 16); + + in = curlx_ultouc(hex); /* this long is never bigger than 255 anyway */ + + if(data) { + result = Curl_convert_from_network(data, (char *)&in, 1); + if(result) { + /* Curl_convert_from_network calls failf if unsuccessful */ + free(ns); + return result; + } + } + + string += 2; + alloc -= 2; + } + + if(reject_ctrl && (in < 0x20)) { + free(ns); + return CURLE_URL_MALFORMAT; + } + + ns[strindex++] = in; + string++; + } + ns[strindex] = 0; /* terminate it */ + + if(olen) + /* store output size */ + *olen = strindex; + + /* store output string */ + *ostring = ns; + + return CURLE_OK; +} + +/* + * Unescapes the given URL escaped string of given length. Returns a + * pointer to a malloced string with length given in *olen. + * If length == 0, the length is assumed to be strlen(string). + * If olen == NULL, no output length is stored. + */ +char *curl_easy_unescape(struct Curl_easy *data, const char *string, + int length, int *olen) +{ + char *str = NULL; + if(length >= 0) { + size_t inputlen = length; + size_t outputlen; + CURLcode res = Curl_urldecode(data, string, inputlen, &str, &outputlen, + FALSE); + if(res) + return NULL; + + if(olen) { + if(outputlen <= (size_t) INT_MAX) + *olen = curlx_uztosi(outputlen); + else + /* too large to return in an int, fail! */ + Curl_safefree(str); + } + } + return str; +} + +/* For operating systems/environments that use different malloc/free + systems for the app and for this library, we provide a free that uses + the library's memory system */ +void curl_free(void *p) +{ + free(p); +} diff --git a/dependencies/cmcurl/lib/escape.h b/dependencies/cmcurl/lib/escape.h new file mode 100644 index 0000000..d8bbe5c --- /dev/null +++ b/dependencies/cmcurl/lib/escape.h @@ -0,0 +1,33 @@ +#ifndef HEADER_CURL_ESCAPE_H +#define HEADER_CURL_ESCAPE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +/* Escape and unescape URL encoding in strings. The functions return a new + * allocated string or NULL if an error occurred. */ + +bool Curl_isunreserved(unsigned char in); +CURLcode Curl_urldecode(struct Curl_easy *data, + const char *string, size_t length, + char **ostring, size_t *olen, + bool reject_crlf); + +#endif /* HEADER_CURL_ESCAPE_H */ diff --git a/dependencies/cmcurl/lib/file.c b/dependencies/cmcurl/lib/file.c new file mode 100644 index 0000000..d349cd9 --- /dev/null +++ b/dependencies/cmcurl/lib/file.c @@ -0,0 +1,544 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_FILE + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#ifdef HAVE_FCNTL_H +#include +#endif + +#include "strtoofft.h" +#include "urldata.h" +#include +#include "progress.h" +#include "sendf.h" +#include "escape.h" +#include "file.h" +#include "speedcheck.h" +#include "getinfo.h" +#include "transfer.h" +#include "url.h" +#include "parsedate.h" /* for the week day and month names */ +#include "warnless.h" +#include "curl_range.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#if defined(WIN32) || defined(MSDOS) || defined(__EMX__) || \ + defined(__SYMBIAN32__) +#define DOS_FILESYSTEM 1 +#endif + +#ifdef OPEN_NEEDS_ARG3 +# define open_readonly(p,f) open((p),(f),(0)) +#else +# define open_readonly(p,f) open((p),(f)) +#endif + +/* + * Forward declarations. + */ + +static CURLcode file_do(struct connectdata *, bool *done); +static CURLcode file_done(struct connectdata *conn, + CURLcode status, bool premature); +static CURLcode file_connect(struct connectdata *conn, bool *done); +static CURLcode file_disconnect(struct connectdata *conn, + bool dead_connection); +static CURLcode file_setup_connection(struct connectdata *conn); + +/* + * FILE scheme handler. + */ + +const struct Curl_handler Curl_handler_file = { + "FILE", /* scheme */ + file_setup_connection, /* setup_connection */ + file_do, /* do_it */ + file_done, /* done */ + ZERO_NULL, /* do_more */ + file_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + file_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + 0, /* defport */ + CURLPROTO_FILE, /* protocol */ + PROTOPT_NONETWORK | PROTOPT_NOURLQUERY /* flags */ +}; + + +static CURLcode file_setup_connection(struct connectdata *conn) +{ + /* allocate the FILE specific struct */ + conn->data->req.protop = calloc(1, sizeof(struct FILEPROTO)); + if(!conn->data->req.protop) + return CURLE_OUT_OF_MEMORY; + + return CURLE_OK; +} + +/* + * file_connect() gets called from Curl_protocol_connect() to allow us to + * do protocol-specific actions at connect-time. We emulate a + * connect-then-transfer protocol and "connect" to the file here + */ +static CURLcode file_connect(struct connectdata *conn, bool *done) +{ + struct Curl_easy *data = conn->data; + char *real_path; + struct FILEPROTO *file = data->req.protop; + int fd; +#ifdef DOS_FILESYSTEM + size_t i; + char *actual_path; +#endif + size_t real_path_len; + + CURLcode result = Curl_urldecode(data, data->state.up.path, 0, &real_path, + &real_path_len, FALSE); + if(result) + return result; + +#ifdef DOS_FILESYSTEM + /* If the first character is a slash, and there's + something that looks like a drive at the beginning of + the path, skip the slash. If we remove the initial + slash in all cases, paths without drive letters end up + relative to the current directory which isn't how + browsers work. + + Some browsers accept | instead of : as the drive letter + separator, so we do too. + + On other platforms, we need the slash to indicate an + absolute pathname. On Windows, absolute paths start + with a drive letter. + */ + actual_path = real_path; + if((actual_path[0] == '/') && + actual_path[1] && + (actual_path[2] == ':' || actual_path[2] == '|')) { + actual_path[2] = ':'; + actual_path++; + real_path_len--; + } + + /* change path separators from '/' to '\\' for DOS, Windows and OS/2 */ + for(i = 0; i < real_path_len; ++i) + if(actual_path[i] == '/') + actual_path[i] = '\\'; + else if(!actual_path[i]) { /* binary zero */ + Curl_safefree(real_path); + return CURLE_URL_MALFORMAT; + } + + fd = open_readonly(actual_path, O_RDONLY|O_BINARY); + file->path = actual_path; +#else + if(memchr(real_path, 0, real_path_len)) { + /* binary zeroes indicate foul play */ + Curl_safefree(real_path); + return CURLE_URL_MALFORMAT; + } + + fd = open_readonly(real_path, O_RDONLY); + file->path = real_path; +#endif + file->freepath = real_path; /* free this when done */ + + file->fd = fd; + if(!data->set.upload && (fd == -1)) { + failf(data, "Couldn't open file %s", data->state.up.path); + file_done(conn, CURLE_FILE_COULDNT_READ_FILE, FALSE); + return CURLE_FILE_COULDNT_READ_FILE; + } + *done = TRUE; + + return CURLE_OK; +} + +static CURLcode file_done(struct connectdata *conn, + CURLcode status, bool premature) +{ + struct FILEPROTO *file = conn->data->req.protop; + (void)status; /* not used */ + (void)premature; /* not used */ + + if(file) { + Curl_safefree(file->freepath); + file->path = NULL; + if(file->fd != -1) + close(file->fd); + file->fd = -1; + } + + return CURLE_OK; +} + +static CURLcode file_disconnect(struct connectdata *conn, + bool dead_connection) +{ + struct FILEPROTO *file = conn->data->req.protop; + (void)dead_connection; /* not used */ + + if(file) { + Curl_safefree(file->freepath); + file->path = NULL; + if(file->fd != -1) + close(file->fd); + file->fd = -1; + } + + return CURLE_OK; +} + +#ifdef DOS_FILESYSTEM +#define DIRSEP '\\' +#else +#define DIRSEP '/' +#endif + +static CURLcode file_upload(struct connectdata *conn) +{ + struct FILEPROTO *file = conn->data->req.protop; + const char *dir = strchr(file->path, DIRSEP); + int fd; + int mode; + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + char *buf = data->state.buffer; + curl_off_t bytecount = 0; + struct_stat file_stat; + const char *buf2; + + /* + * Since FILE: doesn't do the full init, we need to provide some extra + * assignments here. + */ + conn->data->req.upload_fromhere = buf; + + if(!dir) + return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */ + + if(!dir[1]) + return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */ + +#ifdef O_BINARY +#define MODE_DEFAULT O_WRONLY|O_CREAT|O_BINARY +#else +#define MODE_DEFAULT O_WRONLY|O_CREAT +#endif + + if(data->state.resume_from) + mode = MODE_DEFAULT|O_APPEND; + else + mode = MODE_DEFAULT|O_TRUNC; + + fd = open(file->path, mode, conn->data->set.new_file_perms); + if(fd < 0) { + failf(data, "Can't open %s for writing", file->path); + return CURLE_WRITE_ERROR; + } + + if(-1 != data->state.infilesize) + /* known size of data to "upload" */ + Curl_pgrsSetUploadSize(data, data->state.infilesize); + + /* treat the negative resume offset value as the case of "-" */ + if(data->state.resume_from < 0) { + if(fstat(fd, &file_stat)) { + close(fd); + failf(data, "Can't get the size of %s", file->path); + return CURLE_WRITE_ERROR; + } + data->state.resume_from = (curl_off_t)file_stat.st_size; + } + + while(!result) { + size_t nread; + size_t nwrite; + size_t readcount; + result = Curl_fillreadbuffer(conn, data->set.buffer_size, &readcount); + if(result) + break; + + if(!readcount) + break; + + nread = readcount; + + /*skip bytes before resume point*/ + if(data->state.resume_from) { + if((curl_off_t)nread <= data->state.resume_from) { + data->state.resume_from -= nread; + nread = 0; + buf2 = buf; + } + else { + buf2 = buf + data->state.resume_from; + nread -= (size_t)data->state.resume_from; + data->state.resume_from = 0; + } + } + else + buf2 = buf; + + /* write the data to the target */ + nwrite = write(fd, buf2, nread); + if(nwrite != nread) { + result = CURLE_SEND_ERROR; + break; + } + + bytecount += nread; + + Curl_pgrsSetUploadCounter(data, bytecount); + + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + else + result = Curl_speedcheck(data, Curl_now()); + } + if(!result && Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + + close(fd); + + return result; +} + +/* + * file_do() is the protocol-specific function for the do-phase, separated + * from the connect-phase above. Other protocols merely setup the transfer in + * the do-phase, to have it done in the main transfer loop but since some + * platforms we support don't allow select()ing etc on file handles (as + * opposed to sockets) we instead perform the whole do-operation in this + * function. + */ +static CURLcode file_do(struct connectdata *conn, bool *done) +{ + /* This implementation ignores the host name in conformance with + RFC 1738. Only local files (reachable via the standard file system) + are supported. This means that files on remotely mounted directories + (via NFS, Samba, NT sharing) can be accessed through a file:// URL + */ + CURLcode result = CURLE_OK; + struct_stat statbuf; /* struct_stat instead of struct stat just to allow the + Windows version to have a different struct without + having to redefine the simple word 'stat' */ + curl_off_t expected_size = 0; + bool size_known; + bool fstated = FALSE; + struct Curl_easy *data = conn->data; + char *buf = data->state.buffer; + curl_off_t bytecount = 0; + int fd; + struct FILEPROTO *file; + + *done = TRUE; /* unconditionally */ + + Curl_pgrsStartNow(data); + + if(data->set.upload) + return file_upload(conn); + + file = conn->data->req.protop; + + /* get the fd from the connection phase */ + fd = file->fd; + + /* VMS: This only works reliable for STREAMLF files */ + if(-1 != fstat(fd, &statbuf)) { + /* we could stat it, then read out the size */ + expected_size = statbuf.st_size; + /* and store the modification time */ + data->info.filetime = statbuf.st_mtime; + fstated = TRUE; + } + + if(fstated && !data->state.range && data->set.timecondition) { + if(!Curl_meets_timecondition(data, data->info.filetime)) { + *done = TRUE; + return CURLE_OK; + } + } + + if(fstated) { + time_t filetime; + struct tm buffer; + const struct tm *tm = &buffer; + char header[80]; + msnprintf(header, sizeof(header), + "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", + expected_size); + result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0); + if(result) + return result; + + result = Curl_client_write(conn, CLIENTWRITE_HEADER, + (char *)"Accept-ranges: bytes\r\n", 0); + if(result) + return result; + + filetime = (time_t)statbuf.st_mtime; + result = Curl_gmtime(filetime, &buffer); + if(result) + return result; + + /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ + msnprintf(header, sizeof(header), + "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n%s", + Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], + tm->tm_mday, + Curl_month[tm->tm_mon], + tm->tm_year + 1900, + tm->tm_hour, + tm->tm_min, + tm->tm_sec, + data->set.opt_no_body ? "": "\r\n"); + result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0); + if(result) + return result; + /* set the file size to make it available post transfer */ + Curl_pgrsSetDownloadSize(data, expected_size); + if(data->set.opt_no_body) + return result; + } + + /* Check whether file range has been specified */ + result = Curl_range(conn); + if(result) + return result; + + /* Adjust the start offset in case we want to get the N last bytes + * of the stream if the filesize could be determined */ + if(data->state.resume_from < 0) { + if(!fstated) { + failf(data, "Can't get the size of file."); + return CURLE_READ_ERROR; + } + data->state.resume_from += (curl_off_t)statbuf.st_size; + } + + if(data->state.resume_from <= expected_size) + expected_size -= data->state.resume_from; + else { + failf(data, "failed to resume file:// transfer"); + return CURLE_BAD_DOWNLOAD_RESUME; + } + + /* A high water mark has been specified so we obey... */ + if(data->req.maxdownload > 0) + expected_size = data->req.maxdownload; + + if(!fstated || (expected_size == 0)) + size_known = FALSE; + else + size_known = TRUE; + + /* The following is a shortcut implementation of file reading + this is both more efficient than the former call to download() and + it avoids problems with select() and recv() on file descriptors + in Winsock */ + if(fstated) + Curl_pgrsSetDownloadSize(data, expected_size); + + if(data->state.resume_from) { + if(data->state.resume_from != + lseek(fd, data->state.resume_from, SEEK_SET)) + return CURLE_BAD_DOWNLOAD_RESUME; + } + + Curl_pgrsTime(data, TIMER_STARTTRANSFER); + + while(!result) { + ssize_t nread; + /* Don't fill a whole buffer if we want less than all data */ + size_t bytestoread; + + if(size_known) { + bytestoread = (expected_size < data->set.buffer_size) ? + curlx_sotouz(expected_size) : (size_t)data->set.buffer_size; + } + else + bytestoread = data->set.buffer_size-1; + + nread = read(fd, buf, bytestoread); + + if(nread > 0) + buf[nread] = 0; + + if(nread <= 0 || (size_known && (expected_size == 0))) + break; + + bytecount += nread; + if(size_known) + expected_size -= nread; + + result = Curl_client_write(conn, CLIENTWRITE_BODY, buf, nread); + if(result) + return result; + + Curl_pgrsSetDownloadCounter(data, bytecount); + + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + else + result = Curl_speedcheck(data, Curl_now()); + } + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + + return result; +} + +#endif diff --git a/dependencies/cmcurl/lib/file.h b/dependencies/cmcurl/lib/file.h new file mode 100644 index 0000000..20828ad --- /dev/null +++ b/dependencies/cmcurl/lib/file.h @@ -0,0 +1,40 @@ +#ifndef HEADER_CURL_FILE_H +#define HEADER_CURL_FILE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + + +/**************************************************************************** + * FILE unique setup + ***************************************************************************/ +struct FILEPROTO { + char *path; /* the path we operate on */ + char *freepath; /* pointer to the allocated block we must free, this might + differ from the 'path' pointer */ + int fd; /* open file descriptor to read from! */ +}; + +#ifndef CURL_DISABLE_FILE +extern const struct Curl_handler Curl_handler_file; +#endif + +#endif /* HEADER_CURL_FILE_H */ diff --git a/dependencies/cmcurl/lib/fileinfo.c b/dependencies/cmcurl/lib/fileinfo.c new file mode 100644 index 0000000..2630c9e --- /dev/null +++ b/dependencies/cmcurl/lib/fileinfo.c @@ -0,0 +1,44 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#ifndef CURL_DISABLE_FTP +#include "strdup.h" +#include "fileinfo.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +struct fileinfo *Curl_fileinfo_alloc(void) +{ + return calloc(1, sizeof(struct fileinfo)); +} + +void Curl_fileinfo_cleanup(struct fileinfo *finfo) +{ + if(!finfo) + return; + + Curl_safefree(finfo->info.b_data); + free(finfo); +} +#endif diff --git a/dependencies/cmcurl/lib/fileinfo.h b/dependencies/cmcurl/lib/fileinfo.h new file mode 100644 index 0000000..f4d8f3b --- /dev/null +++ b/dependencies/cmcurl/lib/fileinfo.h @@ -0,0 +1,36 @@ +#ifndef HEADER_CURL_FILEINFO_H +#define HEADER_CURL_FILEINFO_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include +#include "llist.h" + +struct fileinfo { + struct curl_fileinfo info; + struct curl_llist_element list; +}; + +struct fileinfo *Curl_fileinfo_alloc(void); +void Curl_fileinfo_cleanup(struct fileinfo *finfo); + +#endif /* HEADER_CURL_FILEINFO_H */ diff --git a/dependencies/cmcurl/lib/formdata.c b/dependencies/cmcurl/lib/formdata.c new file mode 100644 index 0000000..429d479 --- /dev/null +++ b/dependencies/cmcurl/lib/formdata.c @@ -0,0 +1,950 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "formdata.h" +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME) + +#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME) +#include +#endif + +#include "urldata.h" /* for struct Curl_easy */ +#include "mime.h" +#include "non-ascii.h" +#include "vtls/vtls.h" +#include "strcase.h" +#include "sendf.h" +#include "strdup.h" +#include "rand.h" +#include "warnless.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + + +#define HTTPPOST_PTRNAME CURL_HTTPPOST_PTRNAME +#define HTTPPOST_FILENAME CURL_HTTPPOST_FILENAME +#define HTTPPOST_PTRCONTENTS CURL_HTTPPOST_PTRCONTENTS +#define HTTPPOST_READFILE CURL_HTTPPOST_READFILE +#define HTTPPOST_PTRBUFFER CURL_HTTPPOST_PTRBUFFER +#define HTTPPOST_CALLBACK CURL_HTTPPOST_CALLBACK +#define HTTPPOST_BUFFER CURL_HTTPPOST_BUFFER + +/*************************************************************************** + * + * AddHttpPost() + * + * Adds a HttpPost structure to the list, if parent_post is given becomes + * a subpost of parent_post instead of a direct list element. + * + * Returns newly allocated HttpPost on success and NULL if malloc failed. + * + ***************************************************************************/ +static struct curl_httppost * +AddHttpPost(char *name, size_t namelength, + char *value, curl_off_t contentslength, + char *buffer, size_t bufferlength, + char *contenttype, + long flags, + struct curl_slist *contentHeader, + char *showfilename, char *userp, + struct curl_httppost *parent_post, + struct curl_httppost **httppost, + struct curl_httppost **last_post) +{ + struct curl_httppost *post; + post = calloc(1, sizeof(struct curl_httppost)); + if(post) { + post->name = name; + post->namelength = (long)(name?(namelength?namelength:strlen(name)):0); + post->contents = value; + post->contentlen = contentslength; + post->buffer = buffer; + post->bufferlength = (long)bufferlength; + post->contenttype = contenttype; + post->contentheader = contentHeader; + post->showfilename = showfilename; + post->userp = userp; + post->flags = flags | CURL_HTTPPOST_LARGE; + } + else + return NULL; + + if(parent_post) { + /* now, point our 'more' to the original 'more' */ + post->more = parent_post->more; + + /* then move the original 'more' to point to ourselves */ + parent_post->more = post; + } + else { + /* make the previous point to this */ + if(*last_post) + (*last_post)->next = post; + else + (*httppost) = post; + + (*last_post) = post; + } + return post; +} + +/*************************************************************************** + * + * AddFormInfo() + * + * Adds a FormInfo structure to the list presented by parent_form_info. + * + * Returns newly allocated FormInfo on success and NULL if malloc failed/ + * parent_form_info is NULL. + * + ***************************************************************************/ +static FormInfo * AddFormInfo(char *value, + char *contenttype, + FormInfo *parent_form_info) +{ + FormInfo *form_info; + form_info = calloc(1, sizeof(struct FormInfo)); + if(form_info) { + if(value) + form_info->value = value; + if(contenttype) + form_info->contenttype = contenttype; + form_info->flags = HTTPPOST_FILENAME; + } + else + return NULL; + + if(parent_form_info) { + /* now, point our 'more' to the original 'more' */ + form_info->more = parent_form_info->more; + + /* then move the original 'more' to point to ourselves */ + parent_form_info->more = form_info; + } + + return form_info; +} + +/*************************************************************************** + * + * FormAdd() + * + * Stores a formpost parameter and builds the appropriate linked list. + * + * Has two principal functionalities: using files and byte arrays as + * post parts. Byte arrays are either copied or just the pointer is stored + * (as the user requests) while for files only the filename and not the + * content is stored. + * + * While you may have only one byte array for each name, multiple filenames + * are allowed (and because of this feature CURLFORM_END is needed after + * using CURLFORM_FILE). + * + * Examples: + * + * Simple name/value pair with copied contents: + * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", + * CURLFORM_COPYCONTENTS, "value", CURLFORM_END); + * + * name/value pair where only the content pointer is remembered: + * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", + * CURLFORM_PTRCONTENTS, ptr, CURLFORM_CONTENTSLENGTH, 10, CURLFORM_END); + * (if CURLFORM_CONTENTSLENGTH is missing strlen () is used) + * + * storing a filename (CONTENTTYPE is optional!): + * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", + * CURLFORM_FILE, "filename1", CURLFORM_CONTENTTYPE, "plain/text", + * CURLFORM_END); + * + * storing multiple filenames: + * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", + * CURLFORM_FILE, "filename1", CURLFORM_FILE, "filename2", CURLFORM_END); + * + * Returns: + * CURL_FORMADD_OK on success + * CURL_FORMADD_MEMORY if the FormInfo allocation fails + * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form + * CURL_FORMADD_NULL if a null pointer was given for a char + * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed + * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used + * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error) + * CURL_FORMADD_MEMORY if a HttpPost struct cannot be allocated + * CURL_FORMADD_MEMORY if some allocation for string copying failed. + * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array + * + ***************************************************************************/ + +static +CURLFORMcode FormAdd(struct curl_httppost **httppost, + struct curl_httppost **last_post, + va_list params) +{ + FormInfo *first_form, *current_form, *form = NULL; + CURLFORMcode return_value = CURL_FORMADD_OK; + const char *prevtype = NULL; + struct curl_httppost *post = NULL; + CURLformoption option; + struct curl_forms *forms = NULL; + char *array_value = NULL; /* value read from an array */ + + /* This is a state variable, that if TRUE means that we're parsing an + array that we got passed to us. If FALSE we're parsing the input + va_list arguments. */ + bool array_state = FALSE; + + /* + * We need to allocate the first struct to fill in. + */ + first_form = calloc(1, sizeof(struct FormInfo)); + if(!first_form) + return CURL_FORMADD_MEMORY; + + current_form = first_form; + + /* + * Loop through all the options set. Break if we have an error to report. + */ + while(return_value == CURL_FORMADD_OK) { + + /* first see if we have more parts of the array param */ + if(array_state && forms) { + /* get the upcoming option from the given array */ + option = forms->option; + array_value = (char *)forms->value; + + forms++; /* advance this to next entry */ + if(CURLFORM_END == option) { + /* end of array state */ + array_state = FALSE; + continue; + } + } + else { + /* This is not array-state, get next option */ + option = va_arg(params, CURLformoption); + if(CURLFORM_END == option) + break; + } + + switch(option) { + case CURLFORM_ARRAY: + if(array_state) + /* we don't support an array from within an array */ + return_value = CURL_FORMADD_ILLEGAL_ARRAY; + else { + forms = va_arg(params, struct curl_forms *); + if(forms) + array_state = TRUE; + else + return_value = CURL_FORMADD_NULL; + } + break; + + /* + * Set the Name property. + */ + case CURLFORM_PTRNAME: +#ifdef CURL_DOES_CONVERSIONS + /* Treat CURLFORM_PTR like CURLFORM_COPYNAME so that libcurl will copy + * the data in all cases so that we'll have safe memory for the eventual + * conversion. + */ +#else + current_form->flags |= HTTPPOST_PTRNAME; /* fall through */ +#endif + /* FALLTHROUGH */ + case CURLFORM_COPYNAME: + if(current_form->name) + return_value = CURL_FORMADD_OPTION_TWICE; + else { + char *name = array_state? + array_value:va_arg(params, char *); + if(name) + current_form->name = name; /* store for the moment */ + else + return_value = CURL_FORMADD_NULL; + } + break; + case CURLFORM_NAMELENGTH: + if(current_form->namelength) + return_value = CURL_FORMADD_OPTION_TWICE; + else + current_form->namelength = + array_state?(size_t)array_value:(size_t)va_arg(params, long); + break; + + /* + * Set the contents property. + */ + case CURLFORM_PTRCONTENTS: + current_form->flags |= HTTPPOST_PTRCONTENTS; + /* FALLTHROUGH */ + case CURLFORM_COPYCONTENTS: + if(current_form->value) + return_value = CURL_FORMADD_OPTION_TWICE; + else { + char *value = + array_state?array_value:va_arg(params, char *); + if(value) + current_form->value = value; /* store for the moment */ + else + return_value = CURL_FORMADD_NULL; + } + break; + case CURLFORM_CONTENTSLENGTH: + current_form->contentslength = + array_state?(size_t)array_value:(size_t)va_arg(params, long); + break; + + case CURLFORM_CONTENTLEN: + current_form->flags |= CURL_HTTPPOST_LARGE; + current_form->contentslength = + array_state?(curl_off_t)(size_t)array_value:va_arg(params, curl_off_t); + break; + + /* Get contents from a given file name */ + case CURLFORM_FILECONTENT: + if(current_form->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_READFILE)) + return_value = CURL_FORMADD_OPTION_TWICE; + else { + const char *filename = array_state? + array_value:va_arg(params, char *); + if(filename) { + current_form->value = strdup(filename); + if(!current_form->value) + return_value = CURL_FORMADD_MEMORY; + else { + current_form->flags |= HTTPPOST_READFILE; + current_form->value_alloc = TRUE; + } + } + else + return_value = CURL_FORMADD_NULL; + } + break; + + /* We upload a file */ + case CURLFORM_FILE: + { + const char *filename = array_state?array_value: + va_arg(params, char *); + + if(current_form->value) { + if(current_form->flags & HTTPPOST_FILENAME) { + if(filename) { + char *fname = strdup(filename); + if(!fname) + return_value = CURL_FORMADD_MEMORY; + else { + form = AddFormInfo(fname, NULL, current_form); + if(!form) { + free(fname); + return_value = CURL_FORMADD_MEMORY; + } + else { + form->value_alloc = TRUE; + current_form = form; + form = NULL; + } + } + } + else + return_value = CURL_FORMADD_NULL; + } + else + return_value = CURL_FORMADD_OPTION_TWICE; + } + else { + if(filename) { + current_form->value = strdup(filename); + if(!current_form->value) + return_value = CURL_FORMADD_MEMORY; + else { + current_form->flags |= HTTPPOST_FILENAME; + current_form->value_alloc = TRUE; + } + } + else + return_value = CURL_FORMADD_NULL; + } + break; + } + + case CURLFORM_BUFFERPTR: + current_form->flags |= HTTPPOST_PTRBUFFER|HTTPPOST_BUFFER; + if(current_form->buffer) + return_value = CURL_FORMADD_OPTION_TWICE; + else { + char *buffer = + array_state?array_value:va_arg(params, char *); + if(buffer) { + current_form->buffer = buffer; /* store for the moment */ + current_form->value = buffer; /* make it non-NULL to be accepted + as fine */ + } + else + return_value = CURL_FORMADD_NULL; + } + break; + + case CURLFORM_BUFFERLENGTH: + if(current_form->bufferlength) + return_value = CURL_FORMADD_OPTION_TWICE; + else + current_form->bufferlength = + array_state?(size_t)array_value:(size_t)va_arg(params, long); + break; + + case CURLFORM_STREAM: + current_form->flags |= HTTPPOST_CALLBACK; + if(current_form->userp) + return_value = CURL_FORMADD_OPTION_TWICE; + else { + char *userp = + array_state?array_value:va_arg(params, char *); + if(userp) { + current_form->userp = userp; + current_form->value = userp; /* this isn't strictly true but we + derive a value from this later on + and we need this non-NULL to be + accepted as a fine form part */ + } + else + return_value = CURL_FORMADD_NULL; + } + break; + + case CURLFORM_CONTENTTYPE: + { + const char *contenttype = + array_state?array_value:va_arg(params, char *); + if(current_form->contenttype) { + if(current_form->flags & HTTPPOST_FILENAME) { + if(contenttype) { + char *type = strdup(contenttype); + if(!type) + return_value = CURL_FORMADD_MEMORY; + else { + form = AddFormInfo(NULL, type, current_form); + if(!form) { + free(type); + return_value = CURL_FORMADD_MEMORY; + } + else { + form->contenttype_alloc = TRUE; + current_form = form; + form = NULL; + } + } + } + else + return_value = CURL_FORMADD_NULL; + } + else + return_value = CURL_FORMADD_OPTION_TWICE; + } + else { + if(contenttype) { + current_form->contenttype = strdup(contenttype); + if(!current_form->contenttype) + return_value = CURL_FORMADD_MEMORY; + else + current_form->contenttype_alloc = TRUE; + } + else + return_value = CURL_FORMADD_NULL; + } + break; + } + case CURLFORM_CONTENTHEADER: + { + /* this "cast increases required alignment of target type" but + we consider it OK anyway */ + struct curl_slist *list = array_state? + (struct curl_slist *)(void *)array_value: + va_arg(params, struct curl_slist *); + + if(current_form->contentheader) + return_value = CURL_FORMADD_OPTION_TWICE; + else + current_form->contentheader = list; + + break; + } + case CURLFORM_FILENAME: + case CURLFORM_BUFFER: + { + const char *filename = array_state?array_value: + va_arg(params, char *); + if(current_form->showfilename) + return_value = CURL_FORMADD_OPTION_TWICE; + else { + current_form->showfilename = strdup(filename); + if(!current_form->showfilename) + return_value = CURL_FORMADD_MEMORY; + else + current_form->showfilename_alloc = TRUE; + } + break; + } + default: + return_value = CURL_FORMADD_UNKNOWN_OPTION; + break; + } + } + + if(CURL_FORMADD_OK != return_value) { + /* On error, free allocated fields for all nodes of the FormInfo linked + list without deallocating nodes. List nodes are deallocated later on */ + FormInfo *ptr; + for(ptr = first_form; ptr != NULL; ptr = ptr->more) { + if(ptr->name_alloc) { + Curl_safefree(ptr->name); + ptr->name_alloc = FALSE; + } + if(ptr->value_alloc) { + Curl_safefree(ptr->value); + ptr->value_alloc = FALSE; + } + if(ptr->contenttype_alloc) { + Curl_safefree(ptr->contenttype); + ptr->contenttype_alloc = FALSE; + } + if(ptr->showfilename_alloc) { + Curl_safefree(ptr->showfilename); + ptr->showfilename_alloc = FALSE; + } + } + } + + if(CURL_FORMADD_OK == return_value) { + /* go through the list, check for completeness and if everything is + * alright add the HttpPost item otherwise set return_value accordingly */ + + post = NULL; + for(form = first_form; + form != NULL; + form = form->more) { + if(((!form->name || !form->value) && !post) || + ( (form->contentslength) && + (form->flags & HTTPPOST_FILENAME) ) || + ( (form->flags & HTTPPOST_FILENAME) && + (form->flags & HTTPPOST_PTRCONTENTS) ) || + + ( (!form->buffer) && + (form->flags & HTTPPOST_BUFFER) && + (form->flags & HTTPPOST_PTRBUFFER) ) || + + ( (form->flags & HTTPPOST_READFILE) && + (form->flags & HTTPPOST_PTRCONTENTS) ) + ) { + return_value = CURL_FORMADD_INCOMPLETE; + break; + } + if(((form->flags & HTTPPOST_FILENAME) || + (form->flags & HTTPPOST_BUFFER)) && + !form->contenttype) { + char *f = (form->flags & HTTPPOST_BUFFER)? + form->showfilename : form->value; + char const *type; + type = Curl_mime_contenttype(f); + if(!type) + type = prevtype; + if(!type) + type = FILE_CONTENTTYPE_DEFAULT; + + /* our contenttype is missing */ + form->contenttype = strdup(type); + if(!form->contenttype) { + return_value = CURL_FORMADD_MEMORY; + break; + } + form->contenttype_alloc = TRUE; + } + if(form->name && form->namelength) { + /* Name should not contain nul bytes. */ + size_t i; + for(i = 0; i < form->namelength; i++) + if(!form->name[i]) { + return_value = CURL_FORMADD_NULL; + break; + } + if(return_value != CURL_FORMADD_OK) + break; + } + if(!(form->flags & HTTPPOST_PTRNAME) && + (form == first_form) ) { + /* Note that there's small risk that form->name is NULL here if the + app passed in a bad combo, so we better check for that first. */ + if(form->name) { + /* copy name (without strdup; possibly not nul-terminated) */ + form->name = Curl_memdup(form->name, form->namelength? + form->namelength: + strlen(form->name) + 1); + } + if(!form->name) { + return_value = CURL_FORMADD_MEMORY; + break; + } + form->name_alloc = TRUE; + } + if(!(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE | + HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER | + HTTPPOST_CALLBACK)) && form->value) { + /* copy value (without strdup; possibly contains null characters) */ + size_t clen = (size_t) form->contentslength; + if(!clen) + clen = strlen(form->value) + 1; + + form->value = Curl_memdup(form->value, clen); + + if(!form->value) { + return_value = CURL_FORMADD_MEMORY; + break; + } + form->value_alloc = TRUE; + } + post = AddHttpPost(form->name, form->namelength, + form->value, form->contentslength, + form->buffer, form->bufferlength, + form->contenttype, form->flags, + form->contentheader, form->showfilename, + form->userp, + post, httppost, + last_post); + + if(!post) { + return_value = CURL_FORMADD_MEMORY; + break; + } + + if(form->contenttype) + prevtype = form->contenttype; + } + if(CURL_FORMADD_OK != return_value) { + /* On error, free allocated fields for nodes of the FormInfo linked + list which are not already owned by the httppost linked list + without deallocating nodes. List nodes are deallocated later on */ + FormInfo *ptr; + for(ptr = form; ptr != NULL; ptr = ptr->more) { + if(ptr->name_alloc) { + Curl_safefree(ptr->name); + ptr->name_alloc = FALSE; + } + if(ptr->value_alloc) { + Curl_safefree(ptr->value); + ptr->value_alloc = FALSE; + } + if(ptr->contenttype_alloc) { + Curl_safefree(ptr->contenttype); + ptr->contenttype_alloc = FALSE; + } + if(ptr->showfilename_alloc) { + Curl_safefree(ptr->showfilename); + ptr->showfilename_alloc = FALSE; + } + } + } + } + + /* Always deallocate FormInfo linked list nodes without touching node + fields given that these have either been deallocated or are owned + now by the httppost linked list */ + while(first_form) { + FormInfo *ptr = first_form->more; + free(first_form); + first_form = ptr; + } + + return return_value; +} + +/* + * curl_formadd() is a public API to add a section to the multipart formpost. + * + * @unittest: 1308 + */ + +CURLFORMcode curl_formadd(struct curl_httppost **httppost, + struct curl_httppost **last_post, + ...) +{ + va_list arg; + CURLFORMcode result; + va_start(arg, last_post); + result = FormAdd(httppost, last_post, arg); + va_end(arg); + return result; +} + +/* + * curl_formget() + * Serialize a curl_httppost struct. + * Returns 0 on success. + * + * @unittest: 1308 + */ +int curl_formget(struct curl_httppost *form, void *arg, + curl_formget_callback append) +{ + CURLcode result; + curl_mimepart toppart; + + Curl_mime_initpart(&toppart, NULL); /* default form is empty */ + result = Curl_getformdata(NULL, &toppart, form, NULL); + if(!result) + result = Curl_mime_prepare_headers(&toppart, "multipart/form-data", + NULL, MIMESTRATEGY_FORM); + + while(!result) { + char buffer[8192]; + size_t nread = Curl_mime_read(buffer, 1, sizeof(buffer), &toppart); + + if(!nread) + break; + + switch(nread) { + default: + if(append(arg, buffer, nread) != nread) + result = CURLE_READ_ERROR; + break; + case CURL_READFUNC_ABORT: + case CURL_READFUNC_PAUSE: + break; + } + } + + Curl_mime_cleanpart(&toppart); + return (int) result; +} + +/* + * curl_formfree() is an external function to free up a whole form post + * chain + */ +void curl_formfree(struct curl_httppost *form) +{ + struct curl_httppost *next; + + if(!form) + /* no form to free, just get out of this */ + return; + + do { + next = form->next; /* the following form line */ + + /* recurse to sub-contents */ + curl_formfree(form->more); + + if(!(form->flags & HTTPPOST_PTRNAME)) + free(form->name); /* free the name */ + if(!(form->flags & + (HTTPPOST_PTRCONTENTS|HTTPPOST_BUFFER|HTTPPOST_CALLBACK)) + ) + free(form->contents); /* free the contents */ + free(form->contenttype); /* free the content type */ + free(form->showfilename); /* free the faked file name */ + free(form); /* free the struct */ + form = next; + } while(form); /* continue */ +} + + +/* Set mime part name, taking care of non nul-terminated name string. */ +static CURLcode setname(curl_mimepart *part, const char *name, size_t len) +{ + char *zname; + CURLcode res; + + if(!name || !len) + return curl_mime_name(part, name); + zname = malloc(len + 1); + if(!zname) + return CURLE_OUT_OF_MEMORY; + memcpy(zname, name, len); + zname[len] = '\0'; + res = curl_mime_name(part, zname); + free(zname); + return res; +} + +/* + * Curl_getformdata() converts a linked list of "meta data" into a mime + * structure. The input list is in 'post', while the output is stored in + * mime part at '*finalform'. + * + * This function will not do a failf() for the potential memory failures but + * should for all other errors it spots. Just note that this function MAY get + * a NULL pointer in the 'data' argument. + */ + +CURLcode Curl_getformdata(struct Curl_easy *data, + curl_mimepart *finalform, + struct curl_httppost *post, + curl_read_callback fread_func) +{ + CURLcode result = CURLE_OK; + curl_mime *form = NULL; + curl_mimepart *part; + struct curl_httppost *file; + + Curl_mime_cleanpart(finalform); /* default form is empty */ + + if(!post) + return result; /* no input => no output! */ + + form = curl_mime_init(data); + if(!form) + result = CURLE_OUT_OF_MEMORY; + + if(!result) + result = curl_mime_subparts(finalform, form); + + /* Process each top part. */ + for(; !result && post; post = post->next) { + /* If we have more than a file here, create a mime subpart and fill it. */ + curl_mime *multipart = form; + if(post->more) { + part = curl_mime_addpart(form); + if(!part) + result = CURLE_OUT_OF_MEMORY; + if(!result) + result = setname(part, post->name, post->namelength); + if(!result) { + multipart = curl_mime_init(data); + if(!multipart) + result = CURLE_OUT_OF_MEMORY; + } + if(!result) + result = curl_mime_subparts(part, multipart); + } + + /* Generate all the part contents. */ + for(file = post; !result && file; file = file->more) { + /* Create the part. */ + part = curl_mime_addpart(multipart); + if(!part) + result = CURLE_OUT_OF_MEMORY; + + /* Set the headers. */ + if(!result) + result = curl_mime_headers(part, file->contentheader, 0); + + /* Set the content type. */ + if(!result && file->contenttype) + result = curl_mime_type(part, file->contenttype); + + /* Set field name. */ + if(!result && !post->more) + result = setname(part, post->name, post->namelength); + + /* Process contents. */ + if(!result) { + curl_off_t clen = post->contentslength; + + if(post->flags & CURL_HTTPPOST_LARGE) + clen = post->contentlen; + if(!clen) + clen = -1; + + if(post->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE)) { + if(!strcmp(file->contents, "-")) { + /* There are a few cases where the code below won't work; in + particular, freopen(stdin) by the caller is not guaranteed + to result as expected. This feature has been kept for backward + compatibility: use of "-" pseudo file name should be avoided. */ + result = curl_mime_data_cb(part, (curl_off_t) -1, + (curl_read_callback) fread, + CURLX_FUNCTION_CAST(curl_seek_callback, + fseek), + NULL, (void *) stdin); + } + else + result = curl_mime_filedata(part, file->contents); + if(!result && (post->flags & HTTPPOST_READFILE)) + result = curl_mime_filename(part, NULL); + } + else if(post->flags & HTTPPOST_BUFFER) + result = curl_mime_data(part, post->buffer, + post->bufferlength? post->bufferlength: -1); + else if(post->flags & HTTPPOST_CALLBACK) + /* the contents should be read with the callback and the size is set + with the contentslength */ + result = curl_mime_data_cb(part, clen, + fread_func, NULL, NULL, post->userp); + else { + result = curl_mime_data(part, post->contents, (ssize_t) clen); +#ifdef CURL_DOES_CONVERSIONS + /* Convert textual contents now. */ + if(!result && data && part->datasize) + result = Curl_convert_to_network(data, part->data, part->datasize); +#endif + } + } + + /* Set fake file name. */ + if(!result && post->showfilename) + if(post->more || (post->flags & (HTTPPOST_FILENAME | HTTPPOST_BUFFER | + HTTPPOST_CALLBACK))) + result = curl_mime_filename(part, post->showfilename); + } + } + + if(result) + Curl_mime_cleanpart(finalform); + + return result; +} + +#else +/* if disabled */ +CURLFORMcode curl_formadd(struct curl_httppost **httppost, + struct curl_httppost **last_post, + ...) +{ + (void)httppost; + (void)last_post; + return CURL_FORMADD_DISABLED; +} + +int curl_formget(struct curl_httppost *form, void *arg, + curl_formget_callback append) +{ + (void) form; + (void) arg; + (void) append; + return CURL_FORMADD_DISABLED; +} + +void curl_formfree(struct curl_httppost *form) +{ + (void)form; + /* does nothing HTTP is disabled */ +} + +#endif /* if disabled */ diff --git a/dependencies/cmcurl/lib/formdata.h b/dependencies/cmcurl/lib/formdata.h new file mode 100644 index 0000000..cb20805 --- /dev/null +++ b/dependencies/cmcurl/lib/formdata.h @@ -0,0 +1,60 @@ +#ifndef HEADER_CURL_FORMDATA_H +#define HEADER_CURL_FORMDATA_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_MIME + +/* used by FormAdd for temporary storage */ +typedef struct FormInfo { + char *name; + bool name_alloc; + size_t namelength; + char *value; + bool value_alloc; + curl_off_t contentslength; + char *contenttype; + bool contenttype_alloc; + long flags; + char *buffer; /* pointer to existing buffer used for file upload */ + size_t bufferlength; + char *showfilename; /* The file name to show. If not set, the actual + file name will be used */ + bool showfilename_alloc; + char *userp; /* pointer for the read callback */ + struct curl_slist *contentheader; + struct FormInfo *more; +} FormInfo; + +CURLcode Curl_getformdata(struct Curl_easy *data, + curl_mimepart *, + struct curl_httppost *post, + curl_read_callback fread_func); +#else +/* disabled */ +#define Curl_getformdata(a,b,c,d) CURLE_NOT_BUILT_IN +#endif + + +#endif /* HEADER_CURL_FORMDATA_H */ diff --git a/dependencies/cmcurl/lib/ftp.c b/dependencies/cmcurl/lib/ftp.c new file mode 100644 index 0000000..53510f8 --- /dev/null +++ b/dependencies/cmcurl/lib/ftp.c @@ -0,0 +1,4443 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_FTP + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_UTSNAME_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +#include +#include "urldata.h" +#include "sendf.h" +#include "if2ip.h" +#include "hostip.h" +#include "progress.h" +#include "transfer.h" +#include "escape.h" +#include "http.h" /* for HTTP proxy tunnel stuff */ +#include "socks.h" +#include "ftp.h" +#include "fileinfo.h" +#include "ftplistparser.h" +#include "curl_range.h" +#include "curl_sec.h" +#include "strtoofft.h" +#include "strcase.h" +#include "vtls/vtls.h" +#include "connect.h" +#include "strerror.h" +#include "inet_ntop.h" +#include "inet_pton.h" +#include "select.h" +#include "parsedate.h" /* for the week day and month names */ +#include "sockaddr.h" /* required for Curl_sockaddr_storage */ +#include "multiif.h" +#include "url.h" +#include "strcase.h" +#include "speedcheck.h" +#include "warnless.h" +#include "http_proxy.h" +#include "non-ascii.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#ifndef NI_MAXHOST +#define NI_MAXHOST 1025 +#endif +#ifndef INET_ADDRSTRLEN +#define INET_ADDRSTRLEN 16 +#endif + +#ifdef CURL_DISABLE_VERBOSE_STRINGS +#define ftp_pasv_verbose(a,b,c,d) Curl_nop_stmt +#endif + +/* Local API functions */ +#ifndef DEBUGBUILD +static void _state(struct connectdata *conn, + ftpstate newstate); +#define state(x,y) _state(x,y) +#else +static void _state(struct connectdata *conn, + ftpstate newstate, + int lineno); +#define state(x,y) _state(x,y,__LINE__) +#endif + +static CURLcode ftp_sendquote(struct connectdata *conn, + struct curl_slist *quote); +static CURLcode ftp_quit(struct connectdata *conn); +static CURLcode ftp_parse_url_path(struct connectdata *conn); +static CURLcode ftp_regular_transfer(struct connectdata *conn, bool *done); +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static void ftp_pasv_verbose(struct connectdata *conn, + Curl_addrinfo *ai, + char *newhost, /* ascii version */ + int port); +#endif +static CURLcode ftp_state_prepare_transfer(struct connectdata *conn); +static CURLcode ftp_state_mdtm(struct connectdata *conn); +static CURLcode ftp_state_quote(struct connectdata *conn, + bool init, ftpstate instate); +static CURLcode ftp_nb_type(struct connectdata *conn, + bool ascii, ftpstate newstate); +static int ftp_need_type(struct connectdata *conn, + bool ascii); +static CURLcode ftp_do(struct connectdata *conn, bool *done); +static CURLcode ftp_done(struct connectdata *conn, + CURLcode, bool premature); +static CURLcode ftp_connect(struct connectdata *conn, bool *done); +static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection); +static CURLcode ftp_do_more(struct connectdata *conn, int *completed); +static CURLcode ftp_multi_statemach(struct connectdata *conn, bool *done); +static int ftp_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); +static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); +static CURLcode ftp_doing(struct connectdata *conn, + bool *dophase_done); +static CURLcode ftp_setup_connection(struct connectdata * conn); + +static CURLcode init_wc_data(struct connectdata *conn); +static CURLcode wc_statemach(struct connectdata *conn); + +static void wc_data_dtor(void *ptr); + +static CURLcode ftp_state_retr(struct connectdata *conn, curl_off_t filesize); + +static CURLcode ftp_readresp(curl_socket_t sockfd, + struct pingpong *pp, + int *ftpcode, + size_t *size); +static CURLcode ftp_dophase_done(struct connectdata *conn, + bool connected); + +/* easy-to-use macro: */ +#define PPSENDF(x,y,z) result = Curl_pp_sendf(x,y,z); \ + if(result) \ + return result + + +/* + * FTP protocol handler. + */ + +const struct Curl_handler Curl_handler_ftp = { + "FTP", /* scheme */ + ftp_setup_connection, /* setup_connection */ + ftp_do, /* do_it */ + ftp_done, /* done */ + ftp_do_more, /* do_more */ + ftp_connect, /* connect_it */ + ftp_multi_statemach, /* connecting */ + ftp_doing, /* doing */ + ftp_getsock, /* proto_getsock */ + ftp_getsock, /* doing_getsock */ + ftp_domore_getsock, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ftp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_FTP, /* defport */ + CURLPROTO_FTP, /* protocol */ + PROTOPT_DUAL | PROTOPT_CLOSEACTION | PROTOPT_NEEDSPWD | + PROTOPT_NOURLQUERY | PROTOPT_PROXY_AS_HTTP | + PROTOPT_WILDCARD /* flags */ +}; + + +#ifdef USE_SSL +/* + * FTPS protocol handler. + */ + +const struct Curl_handler Curl_handler_ftps = { + "FTPS", /* scheme */ + ftp_setup_connection, /* setup_connection */ + ftp_do, /* do_it */ + ftp_done, /* done */ + ftp_do_more, /* do_more */ + ftp_connect, /* connect_it */ + ftp_multi_statemach, /* connecting */ + ftp_doing, /* doing */ + ftp_getsock, /* proto_getsock */ + ftp_getsock, /* doing_getsock */ + ftp_domore_getsock, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ftp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_FTPS, /* defport */ + CURLPROTO_FTPS, /* protocol */ + PROTOPT_SSL | PROTOPT_DUAL | PROTOPT_CLOSEACTION | + PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY | PROTOPT_WILDCARD /* flags */ +}; +#endif + +static void close_secondarysocket(struct connectdata *conn) +{ + if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) { + Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]); + conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; + } + conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE; +} + +/* + * NOTE: back in the old days, we added code in the FTP code that made NOBODY + * requests on files respond with headers passed to the client/stdout that + * looked like HTTP ones. + * + * This approach is not very elegant, it causes confusion and is error-prone. + * It is subject for removal at the next (or at least a future) soname bump. + * Until then you can test the effects of the removal by undefining the + * following define named CURL_FTP_HTTPSTYLE_HEAD. + */ +#define CURL_FTP_HTTPSTYLE_HEAD 1 + +static void freedirs(struct ftp_conn *ftpc) +{ + if(ftpc->dirs) { + int i; + for(i = 0; i < ftpc->dirdepth; i++) { + free(ftpc->dirs[i]); + ftpc->dirs[i] = NULL; + } + free(ftpc->dirs); + ftpc->dirs = NULL; + ftpc->dirdepth = 0; + } + Curl_safefree(ftpc->file); + + /* no longer of any use */ + Curl_safefree(ftpc->newhost); +} + +/* Returns non-zero if the given string contains CR (\r) or LF (\n), + which are not allowed within RFC 959 . + Note: The input string is in the client's encoding which might + not be ASCII, so escape sequences \r & \n must be used instead + of hex values 0x0d & 0x0a. +*/ +static bool isBadFtpString(const char *string) +{ + return ((NULL != strchr(string, '\r')) || + (NULL != strchr(string, '\n'))) ? TRUE : FALSE; +} + +/*********************************************************************** + * + * AcceptServerConnect() + * + * After connection request is received from the server this function is + * called to accept the connection and close the listening socket + * + */ +static CURLcode AcceptServerConnect(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + curl_socket_t sock = conn->sock[SECONDARYSOCKET]; + curl_socket_t s = CURL_SOCKET_BAD; +#ifdef ENABLE_IPV6 + struct Curl_sockaddr_storage add; +#else + struct sockaddr_in add; +#endif + curl_socklen_t size = (curl_socklen_t) sizeof(add); + + if(0 == getsockname(sock, (struct sockaddr *) &add, &size)) { + size = sizeof(add); + + s = accept(sock, (struct sockaddr *) &add, &size); + } + Curl_closesocket(conn, sock); /* close the first socket */ + + if(CURL_SOCKET_BAD == s) { + failf(data, "Error accept()ing server connect"); + return CURLE_FTP_PORT_FAILED; + } + infof(data, "Connection accepted from server\n"); + /* when this happens within the DO state it is important that we mark us as + not needing DO_MORE anymore */ + conn->bits.do_more = FALSE; + + conn->sock[SECONDARYSOCKET] = s; + (void)curlx_nonblock(s, TRUE); /* enable non-blocking */ + conn->sock_accepted[SECONDARYSOCKET] = TRUE; + + if(data->set.fsockopt) { + int error = 0; + + /* activate callback for setting socket options */ + Curl_set_in_callback(data, true); + error = data->set.fsockopt(data->set.sockopt_client, + s, + CURLSOCKTYPE_ACCEPT); + Curl_set_in_callback(data, false); + + if(error) { + close_secondarysocket(conn); + return CURLE_ABORTED_BY_CALLBACK; + } + } + + return CURLE_OK; + +} + +/* + * ftp_timeleft_accept() returns the amount of milliseconds left allowed for + * waiting server to connect. If the value is negative, the timeout time has + * already elapsed. + * + * The start time is stored in progress.t_acceptdata - as set with + * Curl_pgrsTime(..., TIMER_STARTACCEPT); + * + */ +static timediff_t ftp_timeleft_accept(struct Curl_easy *data) +{ + timediff_t timeout_ms = DEFAULT_ACCEPT_TIMEOUT; + timediff_t other; + struct curltime now; + + if(data->set.accepttimeout > 0) + timeout_ms = data->set.accepttimeout; + + now = Curl_now(); + + /* check if the generic timeout possibly is set shorter */ + other = Curl_timeleft(data, &now, FALSE); + if(other && (other < timeout_ms)) + /* note that this also works fine for when other happens to be negative + due to it already having elapsed */ + timeout_ms = other; + else { + /* subtract elapsed time */ + timeout_ms -= Curl_timediff(now, data->progress.t_acceptdata); + if(!timeout_ms) + /* avoid returning 0 as that means no timeout! */ + return -1; + } + + return timeout_ms; +} + + +/*********************************************************************** + * + * ReceivedServerConnect() + * + * After allowing server to connect to us from data port, this function + * checks both data connection for connection establishment and ctrl + * connection for a negative response regarding a failure in connecting + * + */ +static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received) +{ + struct Curl_easy *data = conn->data; + curl_socket_t ctrl_sock = conn->sock[FIRSTSOCKET]; + curl_socket_t data_sock = conn->sock[SECONDARYSOCKET]; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + int result; + time_t timeout_ms; + ssize_t nread; + int ftpcode; + + *received = FALSE; + + timeout_ms = ftp_timeleft_accept(data); + infof(data, "Checking for server connect\n"); + if(timeout_ms < 0) { + /* if a timeout was already reached, bail out */ + failf(data, "Accept timeout occurred while waiting server connect"); + return CURLE_FTP_ACCEPT_TIMEOUT; + } + + /* First check whether there is a cached response from server */ + if(pp->cache_size && pp->cache && pp->cache[0] > '3') { + /* Data connection could not be established, let's return */ + infof(data, "There is negative response in cache while serv connect\n"); + Curl_GetFTPResponse(&nread, conn, &ftpcode); + return CURLE_FTP_ACCEPT_FAILED; + } + + result = Curl_socket_check(ctrl_sock, data_sock, CURL_SOCKET_BAD, 0); + + /* see if the connection request is already here */ + switch(result) { + case -1: /* error */ + /* let's die here */ + failf(data, "Error while waiting for server connect"); + return CURLE_FTP_ACCEPT_FAILED; + case 0: /* Server connect is not received yet */ + break; /* loop */ + default: + + if(result & CURL_CSELECT_IN2) { + infof(data, "Ready to accept data connection from server\n"); + *received = TRUE; + } + else if(result & CURL_CSELECT_IN) { + infof(data, "Ctrl conn has data while waiting for data conn\n"); + Curl_GetFTPResponse(&nread, conn, &ftpcode); + + if(ftpcode/100 > 3) + return CURLE_FTP_ACCEPT_FAILED; + + return CURLE_WEIRD_SERVER_REPLY; + } + + break; + } /* switch() */ + + return CURLE_OK; +} + + +/*********************************************************************** + * + * InitiateTransfer() + * + * After connection from server is accepted this function is called to + * setup transfer parameters and initiate the data transfer. + * + */ +static CURLcode InitiateTransfer(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + CURLcode result = CURLE_OK; + + if(conn->bits.ftp_use_data_ssl) { + /* since we only have a plaintext TCP connection here, we must now + * do the TLS stuff */ + infof(data, "Doing the SSL/TLS handshake on the data stream\n"); + result = Curl_ssl_connect(conn, SECONDARYSOCKET); + if(result) + return result; + } + + if(conn->proto.ftpc.state_saved == FTP_STOR) { + /* When we know we're uploading a specified file, we can get the file + size prior to the actual upload. */ + Curl_pgrsSetUploadSize(data, data->state.infilesize); + + /* set the SO_SNDBUF for the secondary socket for those who need it */ + Curl_sndbufset(conn->sock[SECONDARYSOCKET]); + + Curl_setup_transfer(data, -1, -1, FALSE, SECONDARYSOCKET); + } + else { + /* FTP download: */ + Curl_setup_transfer(data, SECONDARYSOCKET, + conn->proto.ftpc.retr_size_saved, FALSE, -1); + } + + conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */ + state(conn, FTP_STOP); + + return CURLE_OK; +} + +/*********************************************************************** + * + * AllowServerConnect() + * + * When we've issue the PORT command, we have told the server to connect to + * us. This function checks whether data connection is established if so it is + * accepted. + * + */ +static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected) +{ + struct Curl_easy *data = conn->data; + time_t timeout_ms; + CURLcode result = CURLE_OK; + + *connected = FALSE; + infof(data, "Preparing for accepting server on data port\n"); + + /* Save the time we start accepting server connect */ + Curl_pgrsTime(data, TIMER_STARTACCEPT); + + timeout_ms = ftp_timeleft_accept(data); + if(timeout_ms < 0) { + /* if a timeout was already reached, bail out */ + failf(data, "Accept timeout occurred while waiting server connect"); + return CURLE_FTP_ACCEPT_TIMEOUT; + } + + /* see if the connection request is already here */ + result = ReceivedServerConnect(conn, connected); + if(result) + return result; + + if(*connected) { + result = AcceptServerConnect(conn); + if(result) + return result; + + result = InitiateTransfer(conn); + if(result) + return result; + } + else { + /* Add timeout to multi handle and break out of the loop */ + if(!result && *connected == FALSE) { + Curl_expire(data, data->set.accepttimeout > 0 ? + data->set.accepttimeout: DEFAULT_ACCEPT_TIMEOUT, 0); + } + } + + return result; +} + +/* macro to check for a three-digit ftp status code at the start of the + given string */ +#define STATUSCODE(line) (ISDIGIT(line[0]) && ISDIGIT(line[1]) && \ + ISDIGIT(line[2])) + +/* macro to check for the last line in an FTP server response */ +#define LASTLINE(line) (STATUSCODE(line) && (' ' == line[3])) + +static bool ftp_endofresp(struct connectdata *conn, char *line, size_t len, + int *code) +{ + (void)conn; + + if((len > 3) && LASTLINE(line)) { + *code = curlx_sltosi(strtol(line, NULL, 10)); + return TRUE; + } + + return FALSE; +} + +static CURLcode ftp_readresp(curl_socket_t sockfd, + struct pingpong *pp, + int *ftpcode, /* return the ftp-code if done */ + size_t *size) /* size of the response */ +{ + struct connectdata *conn = pp->conn; + struct Curl_easy *data = conn->data; +#ifdef HAVE_GSSAPI + char * const buf = data->state.buffer; +#endif + CURLcode result = CURLE_OK; + int code; + + result = Curl_pp_readresp(sockfd, pp, &code, size); + +#if defined(HAVE_GSSAPI) + /* handle the security-oriented responses 6xx ***/ + switch(code) { + case 631: + code = Curl_sec_read_msg(conn, buf, PROT_SAFE); + break; + case 632: + code = Curl_sec_read_msg(conn, buf, PROT_PRIVATE); + break; + case 633: + code = Curl_sec_read_msg(conn, buf, PROT_CONFIDENTIAL); + break; + default: + /* normal ftp stuff we pass through! */ + break; + } +#endif + + /* store the latest code for later retrieval */ + data->info.httpcode = code; + + if(ftpcode) + *ftpcode = code; + + if(421 == code) { + /* 421 means "Service not available, closing control connection." and FTP + * servers use it to signal that idle session timeout has been exceeded. + * If we ignored the response, it could end up hanging in some cases. + * + * This response code can come at any point so having it treated + * generically is a good idea. + */ + infof(data, "We got a 421 - timeout!\n"); + state(conn, FTP_STOP); + return CURLE_OPERATION_TIMEDOUT; + } + + return result; +} + +/* --- parse FTP server responses --- */ + +/* + * Curl_GetFTPResponse() is a BLOCKING function to read the full response + * from a server after a command. + * + */ + +CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */ + struct connectdata *conn, + int *ftpcode) /* return the ftp-code */ +{ + /* + * We cannot read just one byte per read() and then go back to select() as + * the OpenSSL read() doesn't grok that properly. + * + * Alas, read as much as possible, split up into lines, use the ending + * line in a response or continue reading. */ + + curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; + struct Curl_easy *data = conn->data; + CURLcode result = CURLE_OK; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + size_t nread; + int cache_skip = 0; + int value_to_be_ignored = 0; + + if(ftpcode) + *ftpcode = 0; /* 0 for errors */ + else + /* make the pointer point to something for the rest of this function */ + ftpcode = &value_to_be_ignored; + + *nreadp = 0; + + while(!*ftpcode && !result) { + /* check and reset timeout value every lap */ + time_t timeout = Curl_pp_state_timeout(pp, FALSE); + time_t interval_ms; + + if(timeout <= 0) { + failf(data, "FTP response timeout"); + return CURLE_OPERATION_TIMEDOUT; /* already too little time */ + } + + interval_ms = 1000; /* use 1 second timeout intervals */ + if(timeout < interval_ms) + interval_ms = timeout; + + /* + * Since this function is blocking, we need to wait here for input on the + * connection and only then we call the response reading function. We do + * timeout at least every second to make the timeout check run. + * + * A caution here is that the ftp_readresp() function has a cache that may + * contain pieces of a response from the previous invoke and we need to + * make sure we don't just wait for input while there is unhandled data in + * that cache. But also, if the cache is there, we call ftp_readresp() and + * the cache wasn't good enough to continue we must not just busy-loop + * around this function. + * + */ + + if(pp->cache && (cache_skip < 2)) { + /* + * There's a cache left since before. We then skipping the wait for + * socket action, unless this is the same cache like the previous round + * as then the cache was deemed not enough to act on and we then need to + * wait for more data anyway. + */ + } + else if(!Curl_conn_data_pending(conn, FIRSTSOCKET)) { + switch(SOCKET_READABLE(sockfd, interval_ms)) { + case -1: /* select() error, stop reading */ + failf(data, "FTP response aborted due to select/poll error: %d", + SOCKERRNO); + return CURLE_RECV_ERROR; + + case 0: /* timeout */ + if(Curl_pgrsUpdate(conn)) + return CURLE_ABORTED_BY_CALLBACK; + continue; /* just continue in our loop for the timeout duration */ + + default: /* for clarity */ + break; + } + } + result = ftp_readresp(sockfd, pp, ftpcode, &nread); + if(result) + break; + + if(!nread && pp->cache) + /* bump cache skip counter as on repeated skips we must wait for more + data */ + cache_skip++; + else + /* when we got data or there is no cache left, we reset the cache skip + counter */ + cache_skip = 0; + + *nreadp += nread; + + } /* while there's buffer left and loop is requested */ + + pp->pending_resp = FALSE; + + return result; +} + +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* for debug purposes */ +static const char * const ftp_state_names[]={ + "STOP", + "WAIT220", + "AUTH", + "USER", + "PASS", + "ACCT", + "PBSZ", + "PROT", + "CCC", + "PWD", + "SYST", + "NAMEFMT", + "QUOTE", + "RETR_PREQUOTE", + "STOR_PREQUOTE", + "POSTQUOTE", + "CWD", + "MKD", + "MDTM", + "TYPE", + "LIST_TYPE", + "RETR_TYPE", + "STOR_TYPE", + "SIZE", + "RETR_SIZE", + "STOR_SIZE", + "REST", + "RETR_REST", + "PORT", + "PRET", + "PASV", + "LIST", + "RETR", + "STOR", + "QUIT" +}; +#endif + +/* This is the ONLY way to change FTP state! */ +static void _state(struct connectdata *conn, + ftpstate newstate +#ifdef DEBUGBUILD + , int lineno +#endif + ) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + +#if defined(DEBUGBUILD) + +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) lineno; +#else + if(ftpc->state != newstate) + infof(conn->data, "FTP %p (line %d) state change from %s to %s\n", + (void *)ftpc, lineno, ftp_state_names[ftpc->state], + ftp_state_names[newstate]); +#endif +#endif + + ftpc->state = newstate; +} + +static CURLcode ftp_state_user(struct connectdata *conn) +{ + CURLcode result; + struct FTP *ftp = conn->data->req.protop; + /* send USER */ + PPSENDF(&conn->proto.ftpc.pp, "USER %s", ftp->user?ftp->user:""); + + state(conn, FTP_USER); + conn->data->state.ftp_trying_alternative = FALSE; + + return CURLE_OK; +} + +static CURLcode ftp_state_pwd(struct connectdata *conn) +{ + CURLcode result; + + /* send PWD to discover our entry point */ + PPSENDF(&conn->proto.ftpc.pp, "%s", "PWD"); + state(conn, FTP_PWD); + + return CURLE_OK; +} + +/* For the FTP "protocol connect" and "doing" phases only */ +static int ftp_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks); +} + +/* For the FTP "DO_MORE" phase only */ +static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if(!numsocks) + return GETSOCK_BLANK; + + /* When in DO_MORE state, we could be either waiting for us to connect to a + * remote site, or we could wait for that site to connect to us. Or just + * handle ordinary commands. + */ + + if(FTP_STOP == ftpc->state) { + int bits = GETSOCK_READSOCK(0); + + /* if stopped and still in this state, then we're also waiting for a + connect on the secondary connection */ + socks[0] = conn->sock[FIRSTSOCKET]; + + if(!conn->data->set.ftp_use_port) { + int s; + int i; + /* PORT is used to tell the server to connect to us, and during that we + don't do happy eyeballs, but we do if we connect to the server */ + for(s = 1, i = 0; i<2; i++) { + if(conn->tempsock[i] != CURL_SOCKET_BAD) { + socks[s] = conn->tempsock[i]; + bits |= GETSOCK_WRITESOCK(s++); + } + } + } + else { + socks[1] = conn->sock[SECONDARYSOCKET]; + bits |= GETSOCK_WRITESOCK(1) | GETSOCK_READSOCK(1); + } + + return bits; + } + return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks); +} + +/* This is called after the FTP_QUOTE state is passed. + + ftp_state_cwd() sends the range of CWD commands to the server to change to + the correct directory. It may also need to send MKD commands to create + missing ones, if that option is enabled. +*/ +static CURLcode ftp_state_cwd(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if(ftpc->cwddone) + /* already done and fine */ + result = ftp_state_mdtm(conn); + else { + ftpc->count2 = 0; /* count2 counts failed CWDs */ + + /* count3 is set to allow a MKD to fail once. In the case when first CWD + fails and then MKD fails (due to another session raced it to create the + dir) this then allows for a second try to CWD to it */ + ftpc->count3 = (conn->data->set.ftp_create_missing_dirs == 2)?1:0; + + if((conn->data->set.ftp_filemethod == FTPFILE_NOCWD) && !ftpc->cwdcount) + /* No CWD necessary */ + result = ftp_state_mdtm(conn); + else if(conn->bits.reuse && ftpc->entrypath) { + /* This is a re-used connection. Since we change directory to where the + transfer is taking place, we must first get back to the original dir + where we ended up after login: */ + ftpc->cwdcount = 0; /* we count this as the first path, then we add one + for all upcoming ones in the ftp->dirs[] array */ + PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->entrypath); + state(conn, FTP_CWD); + } + else { + if(ftpc->dirdepth) { + ftpc->cwdcount = 1; + /* issue the first CWD, the rest is sent when the CWD responses are + received... */ + PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->dirs[ftpc->cwdcount -1]); + state(conn, FTP_CWD); + } + else { + /* No CWD necessary */ + result = ftp_state_mdtm(conn); + } + } + } + return result; +} + +typedef enum { + EPRT, + PORT, + DONE +} ftpport; + +static CURLcode ftp_state_use_port(struct connectdata *conn, + ftpport fcmd) /* start with this */ + +{ + CURLcode result = CURLE_OK; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct Curl_easy *data = conn->data; + curl_socket_t portsock = CURL_SOCKET_BAD; + char myhost[256] = ""; + + struct Curl_sockaddr_storage ss; + Curl_addrinfo *res, *ai; + curl_socklen_t sslen; + char hbuf[NI_MAXHOST]; + struct sockaddr *sa = (struct sockaddr *)&ss; + struct sockaddr_in * const sa4 = (void *)sa; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 * const sa6 = (void *)sa; +#endif + char tmp[1024]; + static const char mode[][5] = { "EPRT", "PORT" }; + int rc; + int error; + char *host = NULL; + char *string_ftpport = data->set.str[STRING_FTPPORT]; + struct Curl_dns_entry *h = NULL; + unsigned short port_min = 0; + unsigned short port_max = 0; + unsigned short port; + bool possibly_non_local = TRUE; + char buffer[STRERROR_LEN]; + char *addr = NULL; + + /* Step 1, figure out what is requested, + * accepted format : + * (ipv4|ipv6|domain|interface)?(:port(-range)?)? + */ + + if(data->set.str[STRING_FTPPORT] && + (strlen(data->set.str[STRING_FTPPORT]) > 1)) { + +#ifdef ENABLE_IPV6 + size_t addrlen = INET6_ADDRSTRLEN > strlen(string_ftpport) ? + INET6_ADDRSTRLEN : strlen(string_ftpport); +#else + size_t addrlen = INET_ADDRSTRLEN > strlen(string_ftpport) ? + INET_ADDRSTRLEN : strlen(string_ftpport); +#endif + char *ip_start = string_ftpport; + char *ip_end = NULL; + char *port_start = NULL; + char *port_sep = NULL; + + addr = calloc(addrlen + 1, 1); + if(!addr) + return CURLE_OUT_OF_MEMORY; + +#ifdef ENABLE_IPV6 + if(*string_ftpport == '[') { + /* [ipv6]:port(-range) */ + ip_start = string_ftpport + 1; + ip_end = strchr(string_ftpport, ']'); + if(ip_end) + strncpy(addr, ip_start, ip_end - ip_start); + } + else +#endif + if(*string_ftpport == ':') { + /* :port */ + ip_end = string_ftpport; + } + else { + ip_end = strchr(string_ftpport, ':'); + if(ip_end) { + /* either ipv6 or (ipv4|domain|interface):port(-range) */ +#ifdef ENABLE_IPV6 + if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) { + /* ipv6 */ + port_min = port_max = 0; + strcpy(addr, string_ftpport); + ip_end = NULL; /* this got no port ! */ + } + else +#endif + /* (ipv4|domain|interface):port(-range) */ + strncpy(addr, string_ftpport, ip_end - ip_start); + } + else + /* ipv4|interface */ + strcpy(addr, string_ftpport); + } + + /* parse the port */ + if(ip_end != NULL) { + port_start = strchr(ip_end, ':'); + if(port_start) { + port_min = curlx_ultous(strtoul(port_start + 1, NULL, 10)); + port_sep = strchr(port_start, '-'); + if(port_sep) { + port_max = curlx_ultous(strtoul(port_sep + 1, NULL, 10)); + } + else + port_max = port_min; + } + } + + /* correct errors like: + * :1234-1230 + * :-4711, in this case port_min is (unsigned)-1, + * therefore port_min > port_max for all cases + * but port_max = (unsigned)-1 + */ + if(port_min > port_max) + port_min = port_max = 0; + + + if(*addr != '\0') { + /* attempt to get the address of the given interface name */ + switch(Curl_if2ip(conn->ip_addr->ai_family, + Curl_ipv6_scope(conn->ip_addr->ai_addr), + conn->scope_id, addr, hbuf, sizeof(hbuf))) { + case IF2IP_NOT_FOUND: + /* not an interface, use the given string as host name instead */ + host = addr; + break; + case IF2IP_AF_NOT_SUPPORTED: + return CURLE_FTP_PORT_FAILED; + case IF2IP_FOUND: + host = hbuf; /* use the hbuf for host name */ + } + } + else + /* there was only a port(-range) given, default the host */ + host = NULL; + } /* data->set.ftpport */ + + if(!host) { + /* not an interface and not a host name, get default by extracting + the IP from the control connection */ + sslen = sizeof(ss); + if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) { + failf(data, "getsockname() failed: %s", + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + free(addr); + return CURLE_FTP_PORT_FAILED; + } + switch(sa->sa_family) { +#ifdef ENABLE_IPV6 + case AF_INET6: + Curl_inet_ntop(sa->sa_family, &sa6->sin6_addr, hbuf, sizeof(hbuf)); + break; +#endif + default: + Curl_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, sizeof(hbuf)); + break; + } + host = hbuf; /* use this host name */ + possibly_non_local = FALSE; /* we know it is local now */ + } + + /* resolv ip/host to ip */ + rc = Curl_resolv(conn, host, 0, FALSE, &h); + if(rc == CURLRESOLV_PENDING) + (void)Curl_resolver_wait_resolv(conn, &h); + if(h) { + res = h->addr; + /* when we return from this function, we can forget about this entry + to we can unlock it now already */ + Curl_resolv_unlock(data, h); + } /* (h) */ + else + res = NULL; /* failure! */ + + if(res == NULL) { + failf(data, "failed to resolve the address provided to PORT: %s", host); + free(addr); + return CURLE_FTP_PORT_FAILED; + } + + free(addr); + host = NULL; + + /* step 2, create a socket for the requested address */ + + portsock = CURL_SOCKET_BAD; + error = 0; + for(ai = res; ai; ai = ai->ai_next) { + result = Curl_socket(conn, ai, NULL, &portsock); + if(result) { + error = SOCKERRNO; + continue; + } + break; + } + if(!ai) { + failf(data, "socket failure: %s", + Curl_strerror(error, buffer, sizeof(buffer))); + return CURLE_FTP_PORT_FAILED; + } + + /* step 3, bind to a suitable local address */ + + memcpy(sa, ai->ai_addr, ai->ai_addrlen); + sslen = ai->ai_addrlen; + + for(port = port_min; port <= port_max;) { + if(sa->sa_family == AF_INET) + sa4->sin_port = htons(port); +#ifdef ENABLE_IPV6 + else + sa6->sin6_port = htons(port); +#endif + /* Try binding the given address. */ + if(bind(portsock, sa, sslen) ) { + /* It failed. */ + error = SOCKERRNO; + if(possibly_non_local && (error == EADDRNOTAVAIL)) { + /* The requested bind address is not local. Use the address used for + * the control connection instead and restart the port loop + */ + infof(data, "bind(port=%hu) on non-local address failed: %s\n", port, + Curl_strerror(error, buffer, sizeof(buffer))); + + sslen = sizeof(ss); + if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) { + failf(data, "getsockname() failed: %s", + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + Curl_closesocket(conn, portsock); + return CURLE_FTP_PORT_FAILED; + } + port = port_min; + possibly_non_local = FALSE; /* don't try this again */ + continue; + } + if(error != EADDRINUSE && error != EACCES) { + failf(data, "bind(port=%hu) failed: %s", port, + Curl_strerror(error, buffer, sizeof(buffer))); + Curl_closesocket(conn, portsock); + return CURLE_FTP_PORT_FAILED; + } + } + else + break; + + port++; + } + + /* maybe all ports were in use already*/ + if(port > port_max) { + failf(data, "bind() failed, we ran out of ports!"); + Curl_closesocket(conn, portsock); + return CURLE_FTP_PORT_FAILED; + } + + /* get the name again after the bind() so that we can extract the + port number it uses now */ + sslen = sizeof(ss); + if(getsockname(portsock, (struct sockaddr *)sa, &sslen)) { + failf(data, "getsockname() failed: %s", + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + Curl_closesocket(conn, portsock); + return CURLE_FTP_PORT_FAILED; + } + + /* step 4, listen on the socket */ + + if(listen(portsock, 1)) { + failf(data, "socket failure: %s", + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + Curl_closesocket(conn, portsock); + return CURLE_FTP_PORT_FAILED; + } + + /* step 5, send the proper FTP command */ + + /* get a plain printable version of the numerical address to work with + below */ + Curl_printable_address(ai, myhost, sizeof(myhost)); + +#ifdef ENABLE_IPV6 + if(!conn->bits.ftp_use_eprt && conn->bits.ipv6) + /* EPRT is disabled but we are connected to a IPv6 host, so we ignore the + request and enable EPRT again! */ + conn->bits.ftp_use_eprt = TRUE; +#endif + + for(; fcmd != DONE; fcmd++) { + + if(!conn->bits.ftp_use_eprt && (EPRT == fcmd)) + /* if disabled, goto next */ + continue; + + if((PORT == fcmd) && sa->sa_family != AF_INET) + /* PORT is IPv4 only */ + continue; + + switch(sa->sa_family) { + case AF_INET: + port = ntohs(sa4->sin_port); + break; +#ifdef ENABLE_IPV6 + case AF_INET6: + port = ntohs(sa6->sin6_port); + break; +#endif + default: + continue; /* might as well skip this */ + } + + if(EPRT == fcmd) { + /* + * Two fine examples from RFC2428; + * + * EPRT |1|132.235.1.2|6275| + * + * EPRT |2|1080::8:800:200C:417A|5282| + */ + + result = Curl_pp_sendf(&ftpc->pp, "%s |%d|%s|%hu|", mode[fcmd], + sa->sa_family == AF_INET?1:2, + myhost, port); + if(result) { + failf(data, "Failure sending EPRT command: %s", + curl_easy_strerror(result)); + Curl_closesocket(conn, portsock); + /* don't retry using PORT */ + ftpc->count1 = PORT; + /* bail out */ + state(conn, FTP_STOP); + return result; + } + break; + } + if(PORT == fcmd) { + char *source = myhost; + char *dest = tmp; + + /* translate x.x.x.x to x,x,x,x */ + while(source && *source) { + if(*source == '.') + *dest = ','; + else + *dest = *source; + dest++; + source++; + } + *dest = 0; + msnprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff)); + + result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], tmp); + if(result) { + failf(data, "Failure sending PORT command: %s", + curl_easy_strerror(result)); + Curl_closesocket(conn, portsock); + /* bail out */ + state(conn, FTP_STOP); + return result; + } + break; + } + } + + /* store which command was sent */ + ftpc->count1 = fcmd; + + close_secondarysocket(conn); + + /* we set the secondary socket variable to this for now, it is only so that + the cleanup function will close it in case we fail before the true + secondary stuff is made */ + conn->sock[SECONDARYSOCKET] = portsock; + + /* this tcpconnect assignment below is a hackish work-around to make the + multi interface with active FTP work - as it will not wait for a + (passive) connect in Curl_is_connected(). + + The *proper* fix is to make sure that the active connection from the + server is done in a non-blocking way. Currently, it is still BLOCKING. + */ + conn->bits.tcpconnect[SECONDARYSOCKET] = TRUE; + + state(conn, FTP_PORT); + return result; +} + +static CURLcode ftp_state_use_pasv(struct connectdata *conn) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + CURLcode result = CURLE_OK; + /* + Here's the excecutive summary on what to do: + + PASV is RFC959, expect: + 227 Entering Passive Mode (a1,a2,a3,a4,p1,p2) + + LPSV is RFC1639, expect: + 228 Entering Long Passive Mode (4,4,a1,a2,a3,a4,2,p1,p2) + + EPSV is RFC2428, expect: + 229 Entering Extended Passive Mode (|||port|) + + */ + + static const char mode[][5] = { "EPSV", "PASV" }; + int modeoff; + +#ifdef PF_INET6 + if(!conn->bits.ftp_use_epsv && conn->bits.ipv6) + /* EPSV is disabled but we are connected to a IPv6 host, so we ignore the + request and enable EPSV again! */ + conn->bits.ftp_use_epsv = TRUE; +#endif + + modeoff = conn->bits.ftp_use_epsv?0:1; + + PPSENDF(&ftpc->pp, "%s", mode[modeoff]); + + ftpc->count1 = modeoff; + state(conn, FTP_PASV); + infof(conn->data, "Connect data stream passively\n"); + + return result; +} + +/* + * ftp_state_prepare_transfer() starts PORT, PASV or PRET etc. + * + * REST is the last command in the chain of commands when a "head"-like + * request is made. Thus, if an actual transfer is to be made this is where we + * take off for real. + */ +static CURLcode ftp_state_prepare_transfer(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct FTP *ftp = conn->data->req.protop; + struct Curl_easy *data = conn->data; + + if(ftp->transfer != FTPTRANSFER_BODY) { + /* doesn't transfer any data */ + + /* still possibly do PRE QUOTE jobs */ + state(conn, FTP_RETR_PREQUOTE); + result = ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE); + } + else if(data->set.ftp_use_port) { + /* We have chosen to use the PORT (or similar) command */ + result = ftp_state_use_port(conn, EPRT); + } + else { + /* We have chosen (this is default) to use the PASV (or similar) command */ + if(data->set.ftp_use_pret) { + /* The user has requested that we send a PRET command + to prepare the server for the upcoming PASV */ + if(!conn->proto.ftpc.file) { + PPSENDF(&conn->proto.ftpc.pp, "PRET %s", + data->set.str[STRING_CUSTOMREQUEST]? + data->set.str[STRING_CUSTOMREQUEST]: + (data->set.ftp_list_only?"NLST":"LIST")); + } + else if(data->set.upload) { + PPSENDF(&conn->proto.ftpc.pp, "PRET STOR %s", conn->proto.ftpc.file); + } + else { + PPSENDF(&conn->proto.ftpc.pp, "PRET RETR %s", conn->proto.ftpc.file); + } + state(conn, FTP_PRET); + } + else { + result = ftp_state_use_pasv(conn); + } + } + return result; +} + +static CURLcode ftp_state_rest(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct FTP *ftp = conn->data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if((ftp->transfer != FTPTRANSFER_BODY) && ftpc->file) { + /* if a "head"-like request is being made (on a file) */ + + /* Determine if server can respond to REST command and therefore + whether it supports range */ + PPSENDF(&conn->proto.ftpc.pp, "REST %d", 0); + + state(conn, FTP_REST); + } + else + result = ftp_state_prepare_transfer(conn); + + return result; +} + +static CURLcode ftp_state_size(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct FTP *ftp = conn->data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if((ftp->transfer == FTPTRANSFER_INFO) && ftpc->file) { + /* if a "head"-like request is being made (on a file) */ + + /* we know ftpc->file is a valid pointer to a file name */ + PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file); + + state(conn, FTP_SIZE); + } + else + result = ftp_state_rest(conn); + + return result; +} + +static CURLcode ftp_state_list(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct FTP *ftp = data->req.protop; + + /* If this output is to be machine-parsed, the NLST command might be better + to use, since the LIST command output is not specified or standard in any + way. It has turned out that the NLST list output is not the same on all + servers either... */ + + /* + if FTPFILE_NOCWD was specified, we are currently in + the user's home directory, so we should add the path + as argument for the LIST / NLST / or custom command. + Whether the server will support this, is uncertain. + + The other ftp_filemethods will CWD into dir/dir/ first and + then just do LIST (in that case: nothing to do here) + */ + char *cmd, *lstArg, *slashPos; + const char *inpath = ftp->path; + + lstArg = NULL; + if((data->set.ftp_filemethod == FTPFILE_NOCWD) && + inpath && inpath[0] && strchr(inpath, '/')) { + size_t n = strlen(inpath); + + /* Check if path does not end with /, as then we cut off the file part */ + if(inpath[n - 1] != '/') { + /* chop off the file part if format is dir/dir/file */ + slashPos = strrchr(inpath, '/'); + n = slashPos - inpath; + } + result = Curl_urldecode(data, inpath, n, &lstArg, NULL, TRUE); + if(result) + return result; + } + + cmd = aprintf("%s%s%s", + data->set.str[STRING_CUSTOMREQUEST]? + data->set.str[STRING_CUSTOMREQUEST]: + (data->set.ftp_list_only?"NLST":"LIST"), + lstArg? " ": "", + lstArg? lstArg: ""); + + if(!cmd) { + free(lstArg); + return CURLE_OUT_OF_MEMORY; + } + + result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", cmd); + + free(lstArg); + free(cmd); + + if(result) + return result; + + state(conn, FTP_LIST); + + return result; +} + +static CURLcode ftp_state_retr_prequote(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + /* We've sent the TYPE, now we must send the list of prequote strings */ + + result = ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE); + + return result; +} + +static CURLcode ftp_state_stor_prequote(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + /* We've sent the TYPE, now we must send the list of prequote strings */ + + result = ftp_state_quote(conn, TRUE, FTP_STOR_PREQUOTE); + + return result; +} + +static CURLcode ftp_state_type(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct FTP *ftp = conn->data->req.protop; + struct Curl_easy *data = conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + /* If we have selected NOBODY and HEADER, it means that we only want file + information. Which in FTP can't be much more than the file size and + date. */ + if(data->set.opt_no_body && ftpc->file && + ftp_need_type(conn, data->set.prefer_ascii)) { + /* The SIZE command is _not_ RFC 959 specified, and therefore many servers + may not support it! It is however the only way we have to get a file's + size! */ + + ftp->transfer = FTPTRANSFER_INFO; + /* this means no actual transfer will be made */ + + /* Some servers return different sizes for different modes, and thus we + must set the proper type before we check the size */ + result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_TYPE); + if(result) + return result; + } + else + result = ftp_state_size(conn); + + return result; +} + +/* This is called after the CWD commands have been done in the beginning of + the DO phase */ +static CURLcode ftp_state_mdtm(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + /* Requested time of file or time-depended transfer? */ + if((data->set.get_filetime || data->set.timecondition) && ftpc->file) { + + /* we have requested to get the modified-time of the file, this is a white + spot as the MDTM is not mentioned in RFC959 */ + PPSENDF(&ftpc->pp, "MDTM %s", ftpc->file); + + state(conn, FTP_MDTM); + } + else + result = ftp_state_type(conn); + + return result; +} + + +/* This is called after the TYPE and possible quote commands have been sent */ +static CURLcode ftp_state_ul_setup(struct connectdata *conn, + bool sizechecked) +{ + CURLcode result = CURLE_OK; + struct FTP *ftp = conn->data->req.protop; + struct Curl_easy *data = conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if((data->state.resume_from && !sizechecked) || + ((data->state.resume_from > 0) && sizechecked)) { + /* we're about to continue the uploading of a file */ + /* 1. get already existing file's size. We use the SIZE command for this + which may not exist in the server! The SIZE command is not in + RFC959. */ + + /* 2. This used to set REST. But since we can do append, we + don't another ftp command. We just skip the source file + offset and then we APPEND the rest on the file instead */ + + /* 3. pass file-size number of bytes in the source file */ + /* 4. lower the infilesize counter */ + /* => transfer as usual */ + int seekerr = CURL_SEEKFUNC_OK; + + if(data->state.resume_from < 0) { + /* Got no given size to start from, figure it out */ + PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file); + state(conn, FTP_STOR_SIZE); + return result; + } + + /* enable append */ + data->set.ftp_append = TRUE; + + /* Let's read off the proper amount of bytes from the input. */ + if(conn->seek_func) { + Curl_set_in_callback(data, true); + seekerr = conn->seek_func(conn->seek_client, data->state.resume_from, + SEEK_SET); + Curl_set_in_callback(data, false); + } + + if(seekerr != CURL_SEEKFUNC_OK) { + curl_off_t passed = 0; + if(seekerr != CURL_SEEKFUNC_CANTSEEK) { + failf(data, "Could not seek stream"); + return CURLE_FTP_COULDNT_USE_REST; + } + /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ + do { + size_t readthisamountnow = + (data->state.resume_from - passed > data->set.buffer_size) ? + (size_t)data->set.buffer_size : + curlx_sotouz(data->state.resume_from - passed); + + size_t actuallyread = + data->state.fread_func(data->state.buffer, 1, readthisamountnow, + data->state.in); + + passed += actuallyread; + if((actuallyread == 0) || (actuallyread > readthisamountnow)) { + /* this checks for greater-than only to make sure that the + CURL_READFUNC_ABORT return code still aborts */ + failf(data, "Failed to read data"); + return CURLE_FTP_COULDNT_USE_REST; + } + } while(passed < data->state.resume_from); + } + /* now, decrease the size of the read */ + if(data->state.infilesize>0) { + data->state.infilesize -= data->state.resume_from; + + if(data->state.infilesize <= 0) { + infof(data, "File already completely uploaded\n"); + + /* no data to transfer */ + Curl_setup_transfer(data, -1, -1, FALSE, -1); + + /* Set ->transfer so that we won't get any error in + * ftp_done() because we didn't transfer anything! */ + ftp->transfer = FTPTRANSFER_NONE; + + state(conn, FTP_STOP); + return CURLE_OK; + } + } + /* we've passed, proceed as normal */ + } /* resume_from */ + + PPSENDF(&ftpc->pp, data->set.ftp_append?"APPE %s":"STOR %s", + ftpc->file); + + state(conn, FTP_STOR); + + return result; +} + +static CURLcode ftp_state_quote(struct connectdata *conn, + bool init, + ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct FTP *ftp = data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + bool quote = FALSE; + struct curl_slist *item; + + switch(instate) { + case FTP_QUOTE: + default: + item = data->set.quote; + break; + case FTP_RETR_PREQUOTE: + case FTP_STOR_PREQUOTE: + item = data->set.prequote; + break; + case FTP_POSTQUOTE: + item = data->set.postquote; + break; + } + + /* + * This state uses: + * 'count1' to iterate over the commands to send + * 'count2' to store whether to allow commands to fail + */ + + if(init) + ftpc->count1 = 0; + else + ftpc->count1++; + + if(item) { + int i = 0; + + /* Skip count1 items in the linked list */ + while((i< ftpc->count1) && item) { + item = item->next; + i++; + } + if(item) { + char *cmd = item->data; + if(cmd[0] == '*') { + cmd++; + ftpc->count2 = 1; /* the sent command is allowed to fail */ + } + else + ftpc->count2 = 0; /* failure means cancel operation */ + + PPSENDF(&ftpc->pp, "%s", cmd); + state(conn, instate); + quote = TRUE; + } + } + + if(!quote) { + /* No more quote to send, continue to ... */ + switch(instate) { + case FTP_QUOTE: + default: + result = ftp_state_cwd(conn); + break; + case FTP_RETR_PREQUOTE: + if(ftp->transfer != FTPTRANSFER_BODY) + state(conn, FTP_STOP); + else { + if(ftpc->known_filesize != -1) { + Curl_pgrsSetDownloadSize(data, ftpc->known_filesize); + result = ftp_state_retr(conn, ftpc->known_filesize); + } + else { + if(data->set.ignorecl) { + /* This code is to support download of growing files. It prevents + the state machine from requesting the file size from the + server. With an unknown file size the download continues until + the server terminates it, otherwise the client stops if the + received byte count exceeds the reported file size. Set option + CURLOPT_IGNORE_CONTENT_LENGTH to 1 to enable this behavior.*/ + PPSENDF(&ftpc->pp, "RETR %s", ftpc->file); + state(conn, FTP_RETR); + } + else { + PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file); + state(conn, FTP_RETR_SIZE); + } + } + } + break; + case FTP_STOR_PREQUOTE: + result = ftp_state_ul_setup(conn, FALSE); + break; + case FTP_POSTQUOTE: + break; + } + } + + return result; +} + +/* called from ftp_state_pasv_resp to switch to PASV in case of EPSV + problems */ +static CURLcode ftp_epsv_disable(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + if(conn->bits.ipv6 && !(conn->bits.tunnel_proxy || conn->bits.socksproxy)) { + /* We can't disable EPSV when doing IPv6, so this is instead a fail */ + failf(conn->data, "Failed EPSV attempt, exiting\n"); + return CURLE_WEIRD_SERVER_REPLY; + } + + infof(conn->data, "Failed EPSV attempt. Disabling EPSV\n"); + /* disable it for next transfer */ + conn->bits.ftp_use_epsv = FALSE; + conn->data->state.errorbuf = FALSE; /* allow error message to get + rewritten */ + PPSENDF(&conn->proto.ftpc.pp, "%s", "PASV"); + conn->proto.ftpc.count1++; + /* remain in/go to the FTP_PASV state */ + state(conn, FTP_PASV); + return result; +} + + +static char *control_address(struct connectdata *conn) +{ + /* Returns the control connection IP address. + If a proxy tunnel is used, returns the original host name instead, because + the effective control connection address is the proxy address, + not the ftp host. */ + if(conn->bits.tunnel_proxy || conn->bits.socksproxy) + return conn->host.name; + + return conn->ip_addr_str; +} + +static CURLcode ftp_state_pasv_resp(struct connectdata *conn, + int ftpcode) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + CURLcode result; + struct Curl_easy *data = conn->data; + struct Curl_dns_entry *addr = NULL; + int rc; + unsigned short connectport; /* the local port connect() should use! */ + char *str = &data->state.buffer[4]; /* start on the first letter */ + + /* if we come here again, make sure the former name is cleared */ + Curl_safefree(ftpc->newhost); + + if((ftpc->count1 == 0) && + (ftpcode == 229)) { + /* positive EPSV response */ + char *ptr = strchr(str, '('); + if(ptr) { + unsigned int num; + char separator[4]; + ptr++; + if(5 == sscanf(ptr, "%c%c%c%u%c", + &separator[0], + &separator[1], + &separator[2], + &num, + &separator[3])) { + const char sep1 = separator[0]; + int i; + + /* The four separators should be identical, or else this is an oddly + formatted reply and we bail out immediately. */ + for(i = 1; i<4; i++) { + if(separator[i] != sep1) { + ptr = NULL; /* set to NULL to signal error */ + break; + } + } + if(num > 0xffff) { + failf(data, "Illegal port number in EPSV reply"); + return CURLE_FTP_WEIRD_PASV_REPLY; + } + if(ptr) { + ftpc->newport = (unsigned short)(num & 0xffff); + ftpc->newhost = strdup(control_address(conn)); + if(!ftpc->newhost) + return CURLE_OUT_OF_MEMORY; + } + } + else + ptr = NULL; + } + if(!ptr) { + failf(data, "Weirdly formatted EPSV reply"); + return CURLE_FTP_WEIRD_PASV_REPLY; + } + } + else if((ftpc->count1 == 1) && + (ftpcode == 227)) { + /* positive PASV response */ + unsigned int ip[4]; + unsigned int port[2]; + + /* + * Scan for a sequence of six comma-separated numbers and use them as + * IP+port indicators. + * + * Found reply-strings include: + * "227 Entering Passive Mode (127,0,0,1,4,51)" + * "227 Data transfer will passively listen to 127,0,0,1,4,51" + * "227 Entering passive mode. 127,0,0,1,4,51" + */ + while(*str) { + if(6 == sscanf(str, "%u,%u,%u,%u,%u,%u", + &ip[0], &ip[1], &ip[2], &ip[3], + &port[0], &port[1])) + break; + str++; + } + + if(!*str || (ip[0] > 255) || (ip[1] > 255) || (ip[2] > 255) || + (ip[3] > 255) || (port[0] > 255) || (port[1] > 255) ) { + failf(data, "Couldn't interpret the 227-response"); + return CURLE_FTP_WEIRD_227_FORMAT; + } + + /* we got OK from server */ + if(data->set.ftp_skip_ip) { + /* told to ignore the remotely given IP but instead use the host we used + for the control connection */ + infof(data, "Skip %u.%u.%u.%u for data connection, re-use %s instead\n", + ip[0], ip[1], ip[2], ip[3], + conn->host.name); + ftpc->newhost = strdup(control_address(conn)); + } + else + ftpc->newhost = aprintf("%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); + + if(!ftpc->newhost) + return CURLE_OUT_OF_MEMORY; + + ftpc->newport = (unsigned short)(((port[0]<<8) + port[1]) & 0xffff); + } + else if(ftpc->count1 == 0) { + /* EPSV failed, move on to PASV */ + return ftp_epsv_disable(conn); + } + else { + failf(data, "Bad PASV/EPSV response: %03d", ftpcode); + return CURLE_FTP_WEIRD_PASV_REPLY; + } + + if(conn->bits.proxy) { + /* + * This connection uses a proxy and we need to connect to the proxy again + * here. We don't want to rely on a former host lookup that might've + * expired now, instead we remake the lookup here and now! + */ + const char * const host_name = conn->bits.socksproxy ? + conn->socks_proxy.host.name : conn->http_proxy.host.name; + rc = Curl_resolv(conn, host_name, (int)conn->port, FALSE, &addr); + if(rc == CURLRESOLV_PENDING) + /* BLOCKING, ignores the return code but 'addr' will be NULL in + case of failure */ + (void)Curl_resolver_wait_resolv(conn, &addr); + + connectport = + (unsigned short)conn->port; /* we connect to the proxy's port */ + + if(!addr) { + failf(data, "Can't resolve proxy host %s:%hu", host_name, connectport); + return CURLE_COULDNT_RESOLVE_PROXY; + } + } + else { + /* normal, direct, ftp connection */ + rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, FALSE, &addr); + if(rc == CURLRESOLV_PENDING) + /* BLOCKING */ + (void)Curl_resolver_wait_resolv(conn, &addr); + + connectport = ftpc->newport; /* we connect to the remote port */ + + if(!addr) { + failf(data, "Can't resolve new host %s:%hu", ftpc->newhost, connectport); + return CURLE_FTP_CANT_GET_HOST; + } + } + + conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE; + result = Curl_connecthost(conn, addr); + + if(result) { + Curl_resolv_unlock(data, addr); /* we're done using this address */ + if(ftpc->count1 == 0 && ftpcode == 229) + return ftp_epsv_disable(conn); + + return result; + } + + + /* + * When this is used from the multi interface, this might've returned with + * the 'connected' set to FALSE and thus we are now awaiting a non-blocking + * connect to connect. + */ + + if(data->set.verbose) + /* this just dumps information about this second connection */ + ftp_pasv_verbose(conn, addr->addr, ftpc->newhost, connectport); + + Curl_resolv_unlock(data, addr); /* we're done using this address */ + + Curl_safefree(conn->secondaryhostname); + conn->secondary_port = ftpc->newport; + conn->secondaryhostname = strdup(ftpc->newhost); + if(!conn->secondaryhostname) + return CURLE_OUT_OF_MEMORY; + + conn->bits.do_more = TRUE; + state(conn, FTP_STOP); /* this phase is completed */ + + return result; +} + +static CURLcode ftp_state_port_resp(struct connectdata *conn, + int ftpcode) +{ + struct Curl_easy *data = conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + ftpport fcmd = (ftpport)ftpc->count1; + CURLcode result = CURLE_OK; + + /* The FTP spec tells a positive response should have code 200. + Be more permissive here to tolerate deviant servers. */ + if(ftpcode / 100 != 2) { + /* the command failed */ + + if(EPRT == fcmd) { + infof(data, "disabling EPRT usage\n"); + conn->bits.ftp_use_eprt = FALSE; + } + fcmd++; + + if(fcmd == DONE) { + failf(data, "Failed to do PORT"); + result = CURLE_FTP_PORT_FAILED; + } + else + /* try next */ + result = ftp_state_use_port(conn, fcmd); + } + else { + infof(data, "Connect data stream actively\n"); + state(conn, FTP_STOP); /* end of DO phase */ + result = ftp_dophase_done(conn, FALSE); + } + + return result; +} + +static CURLcode ftp_state_mdtm_resp(struct connectdata *conn, + int ftpcode) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct FTP *ftp = data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + switch(ftpcode) { + case 213: + { + /* we got a time. Format should be: "YYYYMMDDHHMMSS[.sss]" where the + last .sss part is optional and means fractions of a second */ + int year, month, day, hour, minute, second; + if(6 == sscanf(&data->state.buffer[4], "%04d%02d%02d%02d%02d%02d", + &year, &month, &day, &hour, &minute, &second)) { + /* we have a time, reformat it */ + char timebuf[24]; + time_t secs = time(NULL); + + msnprintf(timebuf, sizeof(timebuf), + "%04d%02d%02d %02d:%02d:%02d GMT", + year, month, day, hour, minute, second); + /* now, convert this into a time() value: */ + data->info.filetime = curl_getdate(timebuf, &secs); + } + +#ifdef CURL_FTP_HTTPSTYLE_HEAD + /* If we asked for a time of the file and we actually got one as well, + we "emulate" a HTTP-style header in our output. */ + + if(data->set.opt_no_body && + ftpc->file && + data->set.get_filetime && + (data->info.filetime >= 0) ) { + char headerbuf[128]; + time_t filetime = data->info.filetime; + struct tm buffer; + const struct tm *tm = &buffer; + + result = Curl_gmtime(filetime, &buffer); + if(result) + return result; + + /* format: "Tue, 15 Nov 1994 12:45:26" */ + msnprintf(headerbuf, sizeof(headerbuf), + "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n", + Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], + tm->tm_mday, + Curl_month[tm->tm_mon], + tm->tm_year + 1900, + tm->tm_hour, + tm->tm_min, + tm->tm_sec); + result = Curl_client_write(conn, CLIENTWRITE_BOTH, headerbuf, 0); + if(result) + return result; + } /* end of a ridiculous amount of conditionals */ +#endif + } + break; + default: + infof(data, "unsupported MDTM reply format\n"); + break; + case 550: /* "No such file or directory" */ + failf(data, "Given file does not exist"); + result = CURLE_FTP_COULDNT_RETR_FILE; + break; + } + + if(data->set.timecondition) { + if((data->info.filetime > 0) && (data->set.timevalue > 0)) { + switch(data->set.timecondition) { + case CURL_TIMECOND_IFMODSINCE: + default: + if(data->info.filetime <= data->set.timevalue) { + infof(data, "The requested document is not new enough\n"); + ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */ + data->info.timecond = TRUE; + state(conn, FTP_STOP); + return CURLE_OK; + } + break; + case CURL_TIMECOND_IFUNMODSINCE: + if(data->info.filetime > data->set.timevalue) { + infof(data, "The requested document is not old enough\n"); + ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */ + data->info.timecond = TRUE; + state(conn, FTP_STOP); + return CURLE_OK; + } + break; + } /* switch */ + } + else { + infof(data, "Skipping time comparison\n"); + } + } + + if(!result) + result = ftp_state_type(conn); + + return result; +} + +static CURLcode ftp_state_type_resp(struct connectdata *conn, + int ftpcode, + ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + if(ftpcode/100 != 2) { + /* "sasserftpd" and "(u)r(x)bot ftpd" both responds with 226 after a + successful 'TYPE I'. While that is not as RFC959 says, it is still a + positive response code and we allow that. */ + failf(data, "Couldn't set desired mode"); + return CURLE_FTP_COULDNT_SET_TYPE; + } + if(ftpcode != 200) + infof(data, "Got a %03d response code instead of the assumed 200\n", + ftpcode); + + if(instate == FTP_TYPE) + result = ftp_state_size(conn); + else if(instate == FTP_LIST_TYPE) + result = ftp_state_list(conn); + else if(instate == FTP_RETR_TYPE) + result = ftp_state_retr_prequote(conn); + else if(instate == FTP_STOR_TYPE) + result = ftp_state_stor_prequote(conn); + + return result; +} + +static CURLcode ftp_state_retr(struct connectdata *conn, + curl_off_t filesize) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct FTP *ftp = data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if(data->set.max_filesize && (filesize > data->set.max_filesize)) { + failf(data, "Maximum file size exceeded"); + return CURLE_FILESIZE_EXCEEDED; + } + ftp->downloadsize = filesize; + + if(data->state.resume_from) { + /* We always (attempt to) get the size of downloads, so it is done before + this even when not doing resumes. */ + if(filesize == -1) { + infof(data, "ftp server doesn't support SIZE\n"); + /* We couldn't get the size and therefore we can't know if there really + is a part of the file left to get, although the server will just + close the connection when we start the connection so it won't cause + us any harm, just not make us exit as nicely. */ + } + else { + /* We got a file size report, so we check that there actually is a + part of the file left to get, or else we go home. */ + if(data->state.resume_from< 0) { + /* We're supposed to download the last abs(from) bytes */ + if(filesize < -data->state.resume_from) { + failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T + ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")", + data->state.resume_from, filesize); + return CURLE_BAD_DOWNLOAD_RESUME; + } + /* convert to size to download */ + ftp->downloadsize = -data->state.resume_from; + /* download from where? */ + data->state.resume_from = filesize - ftp->downloadsize; + } + else { + if(filesize < data->state.resume_from) { + failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T + ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")", + data->state.resume_from, filesize); + return CURLE_BAD_DOWNLOAD_RESUME; + } + /* Now store the number of bytes we are expected to download */ + ftp->downloadsize = filesize-data->state.resume_from; + } + } + + if(ftp->downloadsize == 0) { + /* no data to transfer */ + Curl_setup_transfer(data, -1, -1, FALSE, -1); + infof(data, "File already completely downloaded\n"); + + /* Set ->transfer so that we won't get any error in ftp_done() + * because we didn't transfer the any file */ + ftp->transfer = FTPTRANSFER_NONE; + state(conn, FTP_STOP); + return CURLE_OK; + } + + /* Set resume file transfer offset */ + infof(data, "Instructs server to resume from offset %" + CURL_FORMAT_CURL_OFF_T "\n", data->state.resume_from); + + PPSENDF(&ftpc->pp, "REST %" CURL_FORMAT_CURL_OFF_T, + data->state.resume_from); + + state(conn, FTP_RETR_REST); + } + else { + /* no resume */ + PPSENDF(&ftpc->pp, "RETR %s", ftpc->file); + state(conn, FTP_RETR); + } + + return result; +} + +static CURLcode ftp_state_size_resp(struct connectdata *conn, + int ftpcode, + ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + curl_off_t filesize = -1; + char *buf = data->state.buffer; + + /* get the size from the ascii string: */ + if(ftpcode == 213) + /* ignores parsing errors, which will make the size remain unknown */ + (void)curlx_strtoofft(buf + 4, NULL, 0, &filesize); + + if(instate == FTP_SIZE) { +#ifdef CURL_FTP_HTTPSTYLE_HEAD + if(-1 != filesize) { + char clbuf[128]; + msnprintf(clbuf, sizeof(clbuf), + "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize); + result = Curl_client_write(conn, CLIENTWRITE_BOTH, clbuf, 0); + if(result) + return result; + } +#endif + Curl_pgrsSetDownloadSize(data, filesize); + result = ftp_state_rest(conn); + } + else if(instate == FTP_RETR_SIZE) { + Curl_pgrsSetDownloadSize(data, filesize); + result = ftp_state_retr(conn, filesize); + } + else if(instate == FTP_STOR_SIZE) { + data->state.resume_from = filesize; + result = ftp_state_ul_setup(conn, TRUE); + } + + return result; +} + +static CURLcode ftp_state_rest_resp(struct connectdata *conn, + int ftpcode, + ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + switch(instate) { + case FTP_REST: + default: +#ifdef CURL_FTP_HTTPSTYLE_HEAD + if(ftpcode == 350) { + char buffer[24]= { "Accept-ranges: bytes\r\n" }; + result = Curl_client_write(conn, CLIENTWRITE_BOTH, buffer, 0); + if(result) + return result; + } +#endif + result = ftp_state_prepare_transfer(conn); + break; + + case FTP_RETR_REST: + if(ftpcode != 350) { + failf(conn->data, "Couldn't use REST"); + result = CURLE_FTP_COULDNT_USE_REST; + } + else { + PPSENDF(&ftpc->pp, "RETR %s", ftpc->file); + state(conn, FTP_RETR); + } + break; + } + + return result; +} + +static CURLcode ftp_state_stor_resp(struct connectdata *conn, + int ftpcode, ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + if(ftpcode >= 400) { + failf(data, "Failed FTP upload: %0d", ftpcode); + state(conn, FTP_STOP); + /* oops, we never close the sockets! */ + return CURLE_UPLOAD_FAILED; + } + + conn->proto.ftpc.state_saved = instate; + + /* PORT means we are now awaiting the server to connect to us. */ + if(data->set.ftp_use_port) { + bool connected; + + state(conn, FTP_STOP); /* no longer in STOR state */ + + result = AllowServerConnect(conn, &connected); + if(result) + return result; + + if(!connected) { + struct ftp_conn *ftpc = &conn->proto.ftpc; + infof(data, "Data conn was not available immediately\n"); + ftpc->wait_data_conn = TRUE; + } + + return CURLE_OK; + } + return InitiateTransfer(conn); +} + +/* for LIST and RETR responses */ +static CURLcode ftp_state_get_resp(struct connectdata *conn, + int ftpcode, + ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct FTP *ftp = data->req.protop; + + if((ftpcode == 150) || (ftpcode == 125)) { + + /* + A; + 150 Opening BINARY mode data connection for /etc/passwd (2241 + bytes). (ok, the file is being transferred) + + B: + 150 Opening ASCII mode data connection for /bin/ls + + C: + 150 ASCII data connection for /bin/ls (137.167.104.91,37445) (0 bytes). + + D: + 150 Opening ASCII mode data connection for [file] (0.0.0.0,0) (545 bytes) + + E: + 125 Data connection already open; Transfer starting. */ + + curl_off_t size = -1; /* default unknown size */ + + + /* + * It appears that there are FTP-servers that return size 0 for files when + * SIZE is used on the file while being in BINARY mode. To work around + * that (stupid) behavior, we attempt to parse the RETR response even if + * the SIZE returned size zero. + * + * Debugging help from Salvatore Sorrentino on February 26, 2003. + */ + + if((instate != FTP_LIST) && + !data->set.prefer_ascii && + (ftp->downloadsize < 1)) { + /* + * It seems directory listings either don't show the size or very + * often uses size 0 anyway. ASCII transfers may very well turn out + * that the transferred amount of data is not the same as this line + * tells, why using this number in those cases only confuses us. + * + * Example D above makes this parsing a little tricky */ + char *bytes; + char *buf = data->state.buffer; + bytes = strstr(buf, " bytes"); + if(bytes) { + long in = (long)(--bytes-buf); + /* this is a hint there is size information in there! ;-) */ + while(--in) { + /* scan for the left parenthesis and break there */ + if('(' == *bytes) + break; + /* skip only digits */ + if(!ISDIGIT(*bytes)) { + bytes = NULL; + break; + } + /* one more estep backwards */ + bytes--; + } + /* if we have nothing but digits: */ + if(bytes++) { + /* get the number! */ + (void)curlx_strtoofft(bytes, NULL, 0, &size); + } + } + } + else if(ftp->downloadsize > -1) + size = ftp->downloadsize; + + if(size > data->req.maxdownload && data->req.maxdownload > 0) + size = data->req.size = data->req.maxdownload; + else if((instate != FTP_LIST) && (data->set.prefer_ascii)) + size = -1; /* kludge for servers that understate ASCII mode file size */ + + infof(data, "Maxdownload = %" CURL_FORMAT_CURL_OFF_T "\n", + data->req.maxdownload); + + if(instate != FTP_LIST) + infof(data, "Getting file with size: %" CURL_FORMAT_CURL_OFF_T "\n", + size); + + /* FTP download: */ + conn->proto.ftpc.state_saved = instate; + conn->proto.ftpc.retr_size_saved = size; + + if(data->set.ftp_use_port) { + bool connected; + + result = AllowServerConnect(conn, &connected); + if(result) + return result; + + if(!connected) { + struct ftp_conn *ftpc = &conn->proto.ftpc; + infof(data, "Data conn was not available immediately\n"); + state(conn, FTP_STOP); + ftpc->wait_data_conn = TRUE; + } + } + else + return InitiateTransfer(conn); + } + else { + if((instate == FTP_LIST) && (ftpcode == 450)) { + /* simply no matching files in the dir listing */ + ftp->transfer = FTPTRANSFER_NONE; /* don't download anything */ + state(conn, FTP_STOP); /* this phase is over */ + } + else { + failf(data, "RETR response: %03d", ftpcode); + return instate == FTP_RETR && ftpcode == 550? + CURLE_REMOTE_FILE_NOT_FOUND: + CURLE_FTP_COULDNT_RETR_FILE; + } + } + + return result; +} + +/* after USER, PASS and ACCT */ +static CURLcode ftp_state_loggedin(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + if(conn->ssl[FIRSTSOCKET].use) { + /* PBSZ = PROTECTION BUFFER SIZE. + + The 'draft-murray-auth-ftp-ssl' (draft 12, page 7) says: + + Specifically, the PROT command MUST be preceded by a PBSZ + command and a PBSZ command MUST be preceded by a successful + security data exchange (the TLS negotiation in this case) + + ... (and on page 8): + + Thus the PBSZ command must still be issued, but must have a + parameter of '0' to indicate that no buffering is taking place + and the data connection should not be encapsulated. + */ + PPSENDF(&conn->proto.ftpc.pp, "PBSZ %d", 0); + state(conn, FTP_PBSZ); + } + else { + result = ftp_state_pwd(conn); + } + return result; +} + +/* for USER and PASS responses */ +static CURLcode ftp_state_user_resp(struct connectdata *conn, + int ftpcode, + ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct FTP *ftp = data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + (void)instate; /* no use for this yet */ + + /* some need password anyway, and others just return 2xx ignored */ + if((ftpcode == 331) && (ftpc->state == FTP_USER)) { + /* 331 Password required for ... + (the server requires to send the user's password too) */ + PPSENDF(&ftpc->pp, "PASS %s", ftp->passwd?ftp->passwd:""); + state(conn, FTP_PASS); + } + else if(ftpcode/100 == 2) { + /* 230 User ... logged in. + (the user logged in with or without password) */ + result = ftp_state_loggedin(conn); + } + else if(ftpcode == 332) { + if(data->set.str[STRING_FTP_ACCOUNT]) { + PPSENDF(&ftpc->pp, "ACCT %s", data->set.str[STRING_FTP_ACCOUNT]); + state(conn, FTP_ACCT); + } + else { + failf(data, "ACCT requested but none available"); + result = CURLE_LOGIN_DENIED; + } + } + else { + /* All other response codes, like: + + 530 User ... access denied + (the server denies to log the specified user) */ + + if(conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER] && + !conn->data->state.ftp_trying_alternative) { + /* Ok, USER failed. Let's try the supplied command. */ + PPSENDF(&conn->proto.ftpc.pp, "%s", + conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]); + conn->data->state.ftp_trying_alternative = TRUE; + state(conn, FTP_USER); + result = CURLE_OK; + } + else { + failf(data, "Access denied: %03d", ftpcode); + result = CURLE_LOGIN_DENIED; + } + } + return result; +} + +/* for ACCT response */ +static CURLcode ftp_state_acct_resp(struct connectdata *conn, + int ftpcode) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + if(ftpcode != 230) { + failf(data, "ACCT rejected by server: %03d", ftpcode); + result = CURLE_FTP_WEIRD_PASS_REPLY; /* FIX */ + } + else + result = ftp_state_loggedin(conn); + + return result; +} + + +static CURLcode ftp_statemach_act(struct connectdata *conn) +{ + CURLcode result; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + struct Curl_easy *data = conn->data; + int ftpcode; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + static const char ftpauth[][4] = { "SSL", "TLS" }; + size_t nread = 0; + + if(pp->sendleft) + return Curl_pp_flushsend(pp); + + result = ftp_readresp(sock, pp, &ftpcode, &nread); + if(result) + return result; + + if(ftpcode) { + /* we have now received a full FTP server response */ + switch(ftpc->state) { + case FTP_WAIT220: + if(ftpcode == 230) + /* 230 User logged in - already! */ + return ftp_state_user_resp(conn, ftpcode, ftpc->state); + else if(ftpcode != 220) { + failf(data, "Got a %03d ftp-server response when 220 was expected", + ftpcode); + return CURLE_WEIRD_SERVER_REPLY; + } + + /* We have received a 220 response fine, now we proceed. */ +#ifdef HAVE_GSSAPI + if(data->set.krb) { + /* If not anonymous login, try a secure login. Note that this + procedure is still BLOCKING. */ + + Curl_sec_request_prot(conn, "private"); + /* We set private first as default, in case the line below fails to + set a valid level */ + Curl_sec_request_prot(conn, data->set.str[STRING_KRB_LEVEL]); + + if(Curl_sec_login(conn)) + infof(data, "Logging in with password in cleartext!\n"); + else + infof(data, "Authentication successful\n"); + } +#endif + + if(data->set.use_ssl && + (!conn->ssl[FIRSTSOCKET].use || + (conn->bits.proxy_ssl_connected[FIRSTSOCKET] && + !conn->proxy_ssl[FIRSTSOCKET].use))) { + /* We don't have a SSL/TLS connection yet, but FTPS is + requested. Try a FTPS connection now */ + + ftpc->count3 = 0; + switch(data->set.ftpsslauth) { + case CURLFTPAUTH_DEFAULT: + case CURLFTPAUTH_SSL: + ftpc->count2 = 1; /* add one to get next */ + ftpc->count1 = 0; + break; + case CURLFTPAUTH_TLS: + ftpc->count2 = -1; /* subtract one to get next */ + ftpc->count1 = 1; + break; + default: + failf(data, "unsupported parameter to CURLOPT_FTPSSLAUTH: %d", + (int)data->set.ftpsslauth); + return CURLE_UNKNOWN_OPTION; /* we don't know what to do */ + } + PPSENDF(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]); + state(conn, FTP_AUTH); + } + else { + result = ftp_state_user(conn); + if(result) + return result; + } + + break; + + case FTP_AUTH: + /* we have gotten the response to a previous AUTH command */ + + /* RFC2228 (page 5) says: + * + * If the server is willing to accept the named security mechanism, + * and does not require any security data, it must respond with + * reply code 234/334. + */ + + if((ftpcode == 234) || (ftpcode == 334)) { + /* Curl_ssl_connect is BLOCKING */ + result = Curl_ssl_connect(conn, FIRSTSOCKET); + if(!result) { + conn->bits.ftp_use_data_ssl = FALSE; /* clear-text data */ + result = ftp_state_user(conn); + } + } + else if(ftpc->count3 < 1) { + ftpc->count3++; + ftpc->count1 += ftpc->count2; /* get next attempt */ + result = Curl_pp_sendf(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]); + /* remain in this same state */ + } + else { + if(data->set.use_ssl > CURLUSESSL_TRY) + /* we failed and CURLUSESSL_CONTROL or CURLUSESSL_ALL is set */ + result = CURLE_USE_SSL_FAILED; + else + /* ignore the failure and continue */ + result = ftp_state_user(conn); + } + + if(result) + return result; + break; + + case FTP_USER: + case FTP_PASS: + result = ftp_state_user_resp(conn, ftpcode, ftpc->state); + break; + + case FTP_ACCT: + result = ftp_state_acct_resp(conn, ftpcode); + break; + + case FTP_PBSZ: + PPSENDF(&ftpc->pp, "PROT %c", + data->set.use_ssl == CURLUSESSL_CONTROL ? 'C' : 'P'); + state(conn, FTP_PROT); + + break; + + case FTP_PROT: + if(ftpcode/100 == 2) + /* We have enabled SSL for the data connection! */ + conn->bits.ftp_use_data_ssl = + (data->set.use_ssl != CURLUSESSL_CONTROL) ? TRUE : FALSE; + /* FTP servers typically responds with 500 if they decide to reject + our 'P' request */ + else if(data->set.use_ssl > CURLUSESSL_CONTROL) + /* we failed and bails out */ + return CURLE_USE_SSL_FAILED; + + if(data->set.ftp_ccc) { + /* CCC - Clear Command Channel + */ + PPSENDF(&ftpc->pp, "%s", "CCC"); + state(conn, FTP_CCC); + } + else { + result = ftp_state_pwd(conn); + if(result) + return result; + } + break; + + case FTP_CCC: + if(ftpcode < 500) { + /* First shut down the SSL layer (note: this call will block) */ + result = Curl_ssl_shutdown(conn, FIRSTSOCKET); + + if(result) { + failf(conn->data, "Failed to clear the command channel (CCC)"); + return result; + } + } + + /* Then continue as normal */ + result = ftp_state_pwd(conn); + if(result) + return result; + break; + + case FTP_PWD: + if(ftpcode == 257) { + char *ptr = &data->state.buffer[4]; /* start on the first letter */ + const size_t buf_size = data->set.buffer_size; + char *dir; + bool entry_extracted = FALSE; + + dir = malloc(nread + 1); + if(!dir) + return CURLE_OUT_OF_MEMORY; + + /* Reply format is like + 257[rubbish]"" and the + RFC959 says + + The directory name can contain any character; embedded + double-quotes should be escaped by double-quotes (the + "quote-doubling" convention). + */ + + /* scan for the first double-quote for non-standard responses */ + while(ptr < &data->state.buffer[buf_size] + && *ptr != '\n' && *ptr != '\0' && *ptr != '"') + ptr++; + + if('\"' == *ptr) { + /* it started good */ + char *store; + ptr++; + for(store = dir; *ptr;) { + if('\"' == *ptr) { + if('\"' == ptr[1]) { + /* "quote-doubling" */ + *store = ptr[1]; + ptr++; + } + else { + /* end of path */ + entry_extracted = TRUE; + break; /* get out of this loop */ + } + } + else + *store = *ptr; + store++; + ptr++; + } + *store = '\0'; /* zero terminate */ + } + if(entry_extracted) { + /* If the path name does not look like an absolute path (i.e.: it + does not start with a '/'), we probably need some server-dependent + adjustments. For example, this is the case when connecting to + an OS400 FTP server: this server supports two name syntaxes, + the default one being incompatible with standard paths. In + addition, this server switches automatically to the regular path + syntax when one is encountered in a command: this results in + having an entrypath in the wrong syntax when later used in CWD. + The method used here is to check the server OS: we do it only + if the path name looks strange to minimize overhead on other + systems. */ + + if(!ftpc->server_os && dir[0] != '/') { + + result = Curl_pp_sendf(&ftpc->pp, "%s", "SYST"); + if(result) { + free(dir); + return result; + } + Curl_safefree(ftpc->entrypath); + ftpc->entrypath = dir; /* remember this */ + infof(data, "Entry path is '%s'\n", ftpc->entrypath); + /* also save it where getinfo can access it: */ + data->state.most_recent_ftp_entrypath = ftpc->entrypath; + state(conn, FTP_SYST); + break; + } + + Curl_safefree(ftpc->entrypath); + ftpc->entrypath = dir; /* remember this */ + infof(data, "Entry path is '%s'\n", ftpc->entrypath); + /* also save it where getinfo can access it: */ + data->state.most_recent_ftp_entrypath = ftpc->entrypath; + } + else { + /* couldn't get the path */ + free(dir); + infof(data, "Failed to figure out path\n"); + } + } + state(conn, FTP_STOP); /* we are done with the CONNECT phase! */ + DEBUGF(infof(data, "protocol connect phase DONE\n")); + break; + + case FTP_SYST: + if(ftpcode == 215) { + char *ptr = &data->state.buffer[4]; /* start on the first letter */ + char *os; + char *store; + + os = malloc(nread + 1); + if(!os) + return CURLE_OUT_OF_MEMORY; + + /* Reply format is like + 215 + */ + while(*ptr == ' ') + ptr++; + for(store = os; *ptr && *ptr != ' ';) + *store++ = *ptr++; + *store = '\0'; /* zero terminate */ + + /* Check for special servers here. */ + + if(strcasecompare(os, "OS/400")) { + /* Force OS400 name format 1. */ + result = Curl_pp_sendf(&ftpc->pp, "%s", "SITE NAMEFMT 1"); + if(result) { + free(os); + return result; + } + /* remember target server OS */ + Curl_safefree(ftpc->server_os); + ftpc->server_os = os; + state(conn, FTP_NAMEFMT); + break; + } + /* Nothing special for the target server. */ + /* remember target server OS */ + Curl_safefree(ftpc->server_os); + ftpc->server_os = os; + } + else { + /* Cannot identify server OS. Continue anyway and cross fingers. */ + } + + state(conn, FTP_STOP); /* we are done with the CONNECT phase! */ + DEBUGF(infof(data, "protocol connect phase DONE\n")); + break; + + case FTP_NAMEFMT: + if(ftpcode == 250) { + /* Name format change successful: reload initial path. */ + ftp_state_pwd(conn); + break; + } + + state(conn, FTP_STOP); /* we are done with the CONNECT phase! */ + DEBUGF(infof(data, "protocol connect phase DONE\n")); + break; + + case FTP_QUOTE: + case FTP_POSTQUOTE: + case FTP_RETR_PREQUOTE: + case FTP_STOR_PREQUOTE: + if((ftpcode >= 400) && !ftpc->count2) { + /* failure response code, and not allowed to fail */ + failf(conn->data, "QUOT command failed with %03d", ftpcode); + return CURLE_QUOTE_ERROR; + } + result = ftp_state_quote(conn, FALSE, ftpc->state); + if(result) + return result; + + break; + + case FTP_CWD: + if(ftpcode/100 != 2) { + /* failure to CWD there */ + if(conn->data->set.ftp_create_missing_dirs && + ftpc->cwdcount && !ftpc->count2) { + /* try making it */ + ftpc->count2++; /* counter to prevent CWD-MKD loops */ + PPSENDF(&ftpc->pp, "MKD %s", ftpc->dirs[ftpc->cwdcount - 1]); + state(conn, FTP_MKD); + } + else { + /* return failure */ + failf(data, "Server denied you to change to the given directory"); + ftpc->cwdfail = TRUE; /* don't remember this path as we failed + to enter it */ + return CURLE_REMOTE_ACCESS_DENIED; + } + } + else { + /* success */ + ftpc->count2 = 0; + if(++ftpc->cwdcount <= ftpc->dirdepth) { + /* send next CWD */ + PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->cwdcount - 1]); + } + else { + result = ftp_state_mdtm(conn); + if(result) + return result; + } + } + break; + + case FTP_MKD: + if((ftpcode/100 != 2) && !ftpc->count3--) { + /* failure to MKD the dir */ + failf(data, "Failed to MKD dir: %03d", ftpcode); + return CURLE_REMOTE_ACCESS_DENIED; + } + state(conn, FTP_CWD); + /* send CWD */ + PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->cwdcount - 1]); + break; + + case FTP_MDTM: + result = ftp_state_mdtm_resp(conn, ftpcode); + break; + + case FTP_TYPE: + case FTP_LIST_TYPE: + case FTP_RETR_TYPE: + case FTP_STOR_TYPE: + result = ftp_state_type_resp(conn, ftpcode, ftpc->state); + break; + + case FTP_SIZE: + case FTP_RETR_SIZE: + case FTP_STOR_SIZE: + result = ftp_state_size_resp(conn, ftpcode, ftpc->state); + break; + + case FTP_REST: + case FTP_RETR_REST: + result = ftp_state_rest_resp(conn, ftpcode, ftpc->state); + break; + + case FTP_PRET: + if(ftpcode != 200) { + /* there only is this one standard OK return code. */ + failf(data, "PRET command not accepted: %03d", ftpcode); + return CURLE_FTP_PRET_FAILED; + } + result = ftp_state_use_pasv(conn); + break; + + case FTP_PASV: + result = ftp_state_pasv_resp(conn, ftpcode); + break; + + case FTP_PORT: + result = ftp_state_port_resp(conn, ftpcode); + break; + + case FTP_LIST: + case FTP_RETR: + result = ftp_state_get_resp(conn, ftpcode, ftpc->state); + break; + + case FTP_STOR: + result = ftp_state_stor_resp(conn, ftpcode, ftpc->state); + break; + + case FTP_QUIT: + /* fallthrough, just stop! */ + default: + /* internal error */ + state(conn, FTP_STOP); + break; + } + } /* if(ftpcode) */ + + return result; +} + + +/* called repeatedly until done from multi.c */ +static CURLcode ftp_multi_statemach(struct connectdata *conn, + bool *done) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + CURLcode result = Curl_pp_statemach(&ftpc->pp, FALSE, FALSE); + + /* Check for the state outside of the Curl_socket_check() return code checks + since at times we are in fact already in this state when this function + gets called. */ + *done = (ftpc->state == FTP_STOP) ? TRUE : FALSE; + + return result; +} + +static CURLcode ftp_block_statemach(struct connectdata *conn) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + CURLcode result = CURLE_OK; + + while(ftpc->state != FTP_STOP) { + result = Curl_pp_statemach(pp, TRUE, TRUE /* disconnecting */); + if(result) + break; + } + + return result; +} + +/* + * ftp_connect() should do everything that is to be considered a part of + * the connection phase. + * + * The variable 'done' points to will be TRUE if the protocol-layer connect + * phase is done when this function returns, or FALSE if not. + * + */ +static CURLcode ftp_connect(struct connectdata *conn, + bool *done) /* see description above */ +{ + CURLcode result; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + + *done = FALSE; /* default to not done yet */ + + /* We always support persistent connections on ftp */ + connkeep(conn, "FTP default"); + + pp->response_time = RESP_TIMEOUT; /* set default response time-out */ + pp->statemach_act = ftp_statemach_act; + pp->endofresp = ftp_endofresp; + pp->conn = conn; + + if(conn->handler->flags & PROTOPT_SSL) { + /* BLOCKING */ + result = Curl_ssl_connect(conn, FIRSTSOCKET); + if(result) + return result; + } + + Curl_pp_init(pp); /* init the generic pingpong data */ + + /* When we connect, we start in the state where we await the 220 + response */ + state(conn, FTP_WAIT220); + + result = ftp_multi_statemach(conn, done); + + return result; +} + +/*********************************************************************** + * + * ftp_done() + * + * The DONE function. This does what needs to be done after a single DO has + * performed. + * + * Input argument is already checked for validity. + */ +static CURLcode ftp_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + struct Curl_easy *data = conn->data; + struct FTP *ftp = data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + ssize_t nread; + int ftpcode; + CURLcode result = CURLE_OK; + char *path = NULL; + + if(!ftp) + return CURLE_OK; + + switch(status) { + case CURLE_BAD_DOWNLOAD_RESUME: + case CURLE_FTP_WEIRD_PASV_REPLY: + case CURLE_FTP_PORT_FAILED: + case CURLE_FTP_ACCEPT_FAILED: + case CURLE_FTP_ACCEPT_TIMEOUT: + case CURLE_FTP_COULDNT_SET_TYPE: + case CURLE_FTP_COULDNT_RETR_FILE: + case CURLE_PARTIAL_FILE: + case CURLE_UPLOAD_FAILED: + case CURLE_REMOTE_ACCESS_DENIED: + case CURLE_FILESIZE_EXCEEDED: + case CURLE_REMOTE_FILE_NOT_FOUND: + case CURLE_WRITE_ERROR: + /* the connection stays alive fine even though this happened */ + /* fall-through */ + case CURLE_OK: /* doesn't affect the control connection's status */ + if(!premature) + break; + + /* until we cope better with prematurely ended requests, let them + * fallback as if in complete failure */ + /* FALLTHROUGH */ + default: /* by default, an error means the control connection is + wedged and should not be used anymore */ + ftpc->ctl_valid = FALSE; + ftpc->cwdfail = TRUE; /* set this TRUE to prevent us to remember the + current path, as this connection is going */ + connclose(conn, "FTP ended with bad error code"); + result = status; /* use the already set error code */ + break; + } + + /* now store a copy of the directory we are in */ + free(ftpc->prevpath); + + if(data->state.wildcardmatch) { + if(data->set.chunk_end && ftpc->file) { + Curl_set_in_callback(data, true); + data->set.chunk_end(data->wildcard.customptr); + Curl_set_in_callback(data, false); + } + ftpc->known_filesize = -1; + } + + if(!result) + /* get the "raw" path */ + result = Curl_urldecode(data, ftp->path, 0, &path, NULL, TRUE); + if(result) { + /* We can limp along anyway (and should try to since we may already be in + * the error path) */ + ftpc->ctl_valid = FALSE; /* mark control connection as bad */ + connclose(conn, "FTP: out of memory!"); /* mark for connection closure */ + ftpc->prevpath = NULL; /* no path remembering */ + } + else { + size_t flen = ftpc->file?strlen(ftpc->file):0; /* file is "raw" already */ + size_t dlen = strlen(path)-flen; + if(!ftpc->cwdfail) { + ftpc->prevmethod = data->set.ftp_filemethod; + if(dlen && (data->set.ftp_filemethod != FTPFILE_NOCWD)) { + ftpc->prevpath = path; + if(flen) + /* if 'path' is not the whole string */ + ftpc->prevpath[dlen] = 0; /* terminate */ + } + else { + free(path); + /* we never changed dir */ + ftpc->prevpath = strdup(""); + if(!ftpc->prevpath) + return CURLE_OUT_OF_MEMORY; + } + if(ftpc->prevpath) + infof(data, "Remembering we are in dir \"%s\"\n", ftpc->prevpath); + } + else { + ftpc->prevpath = NULL; /* no path */ + free(path); + } + } + /* free the dir tree and file parts */ + freedirs(ftpc); + + /* shut down the socket to inform the server we're done */ + +#ifdef _WIN32_WCE + shutdown(conn->sock[SECONDARYSOCKET], 2); /* SD_BOTH */ +#endif + + if(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) { + if(!result && ftpc->dont_check && data->req.maxdownload > 0) { + /* partial download completed */ + result = Curl_pp_sendf(pp, "%s", "ABOR"); + if(result) { + failf(data, "Failure sending ABOR command: %s", + curl_easy_strerror(result)); + ftpc->ctl_valid = FALSE; /* mark control connection as bad */ + connclose(conn, "ABOR command failed"); /* connection closure */ + } + } + + if(conn->ssl[SECONDARYSOCKET].use) { + /* The secondary socket is using SSL so we must close down that part + first before we close the socket for real */ + Curl_ssl_close(conn, SECONDARYSOCKET); + + /* Note that we keep "use" set to TRUE since that (next) connection is + still requested to use SSL */ + } + close_secondarysocket(conn); + } + + if(!result && (ftp->transfer == FTPTRANSFER_BODY) && ftpc->ctl_valid && + pp->pending_resp && !premature) { + /* + * Let's see what the server says about the transfer we just performed, + * but lower the timeout as sometimes this connection has died while the + * data has been transferred. This happens when doing through NATs etc that + * abandon old silent connections. + */ + long old_time = pp->response_time; + + pp->response_time = 60*1000; /* give it only a minute for now */ + pp->response = Curl_now(); /* timeout relative now */ + + result = Curl_GetFTPResponse(&nread, conn, &ftpcode); + + pp->response_time = old_time; /* set this back to previous value */ + + if(!nread && (CURLE_OPERATION_TIMEDOUT == result)) { + failf(data, "control connection looks dead"); + ftpc->ctl_valid = FALSE; /* mark control connection as bad */ + connclose(conn, "Timeout or similar in FTP DONE operation"); /* close */ + } + + if(result) + return result; + + if(ftpc->dont_check && data->req.maxdownload > 0) { + /* we have just sent ABOR and there is no reliable way to check if it was + * successful or not; we have to close the connection now */ + infof(data, "partial download completed, closing connection\n"); + connclose(conn, "Partial download with no ability to check"); + return result; + } + + if(!ftpc->dont_check) { + /* 226 Transfer complete, 250 Requested file action okay, completed. */ + if((ftpcode != 226) && (ftpcode != 250)) { + failf(data, "server did not report OK, got %d", ftpcode); + result = CURLE_PARTIAL_FILE; + } + } + } + + if(result || premature) + /* the response code from the transfer showed an error already so no + use checking further */ + ; + else if(data->set.upload) { + if((-1 != data->state.infilesize) && + (data->state.infilesize != data->req.writebytecount) && + !data->set.crlf && + (ftp->transfer == FTPTRANSFER_BODY)) { + failf(data, "Uploaded unaligned file size (%" CURL_FORMAT_CURL_OFF_T + " out of %" CURL_FORMAT_CURL_OFF_T " bytes)", + data->req.bytecount, data->state.infilesize); + result = CURLE_PARTIAL_FILE; + } + } + else { + if((-1 != data->req.size) && + (data->req.size != data->req.bytecount) && +#ifdef CURL_DO_LINEEND_CONV + /* Most FTP servers don't adjust their file SIZE response for CRLFs, so + * we'll check to see if the discrepancy can be explained by the number + * of CRLFs we've changed to LFs. + */ + ((data->req.size + data->state.crlf_conversions) != + data->req.bytecount) && +#endif /* CURL_DO_LINEEND_CONV */ + (data->req.maxdownload != data->req.bytecount)) { + failf(data, "Received only partial file: %" CURL_FORMAT_CURL_OFF_T + " bytes", data->req.bytecount); + result = CURLE_PARTIAL_FILE; + } + else if(!ftpc->dont_check && + !data->req.bytecount && + (data->req.size>0)) { + failf(data, "No data was received!"); + result = CURLE_FTP_COULDNT_RETR_FILE; + } + } + + /* clear these for next connection */ + ftp->transfer = FTPTRANSFER_BODY; + ftpc->dont_check = FALSE; + + /* Send any post-transfer QUOTE strings? */ + if(!status && !result && !premature && data->set.postquote) + result = ftp_sendquote(conn, data->set.postquote); + Curl_safefree(ftp->pathalloc); + return result; +} + +/*********************************************************************** + * + * ftp_sendquote() + * + * Where a 'quote' means a list of custom commands to send to the server. + * The quote list is passed as an argument. + * + * BLOCKING + */ + +static +CURLcode ftp_sendquote(struct connectdata *conn, struct curl_slist *quote) +{ + struct curl_slist *item; + ssize_t nread; + int ftpcode; + CURLcode result; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + + item = quote; + while(item) { + if(item->data) { + char *cmd = item->data; + bool acceptfail = FALSE; + + /* if a command starts with an asterisk, which a legal FTP command never + can, the command will be allowed to fail without it causing any + aborts or cancels etc. It will cause libcurl to act as if the command + is successful, whatever the server reponds. */ + + if(cmd[0] == '*') { + cmd++; + acceptfail = TRUE; + } + + PPSENDF(&conn->proto.ftpc.pp, "%s", cmd); + + pp->response = Curl_now(); /* timeout relative now */ + + result = Curl_GetFTPResponse(&nread, conn, &ftpcode); + if(result) + return result; + + if(!acceptfail && (ftpcode >= 400)) { + failf(conn->data, "QUOT string not accepted: %s", cmd); + return CURLE_QUOTE_ERROR; + } + } + + item = item->next; + } + + return CURLE_OK; +} + +/*********************************************************************** + * + * ftp_need_type() + * + * Returns TRUE if we in the current situation should send TYPE + */ +static int ftp_need_type(struct connectdata *conn, + bool ascii_wanted) +{ + return conn->proto.ftpc.transfertype != (ascii_wanted?'A':'I'); +} + +/*********************************************************************** + * + * ftp_nb_type() + * + * Set TYPE. We only deal with ASCII or BINARY so this function + * sets one of them. + * If the transfer type is not sent, simulate on OK response in newstate + */ +static CURLcode ftp_nb_type(struct connectdata *conn, + bool ascii, ftpstate newstate) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + CURLcode result; + char want = (char)(ascii?'A':'I'); + + if(ftpc->transfertype == want) { + state(conn, newstate); + return ftp_state_type_resp(conn, 200, newstate); + } + + PPSENDF(&ftpc->pp, "TYPE %c", want); + state(conn, newstate); + + /* keep track of our current transfer type */ + ftpc->transfertype = want; + return CURLE_OK; +} + +/*************************************************************************** + * + * ftp_pasv_verbose() + * + * This function only outputs some informationals about this second connection + * when we've issued a PASV command before and thus we have connected to a + * possibly new IP address. + * + */ +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static void +ftp_pasv_verbose(struct connectdata *conn, + Curl_addrinfo *ai, + char *newhost, /* ascii version */ + int port) +{ + char buf[256]; + Curl_printable_address(ai, buf, sizeof(buf)); + infof(conn->data, "Connecting to %s (%s) port %d\n", newhost, buf, port); +} +#endif + +/* + * ftp_do_more() + * + * This function shall be called when the second FTP (data) connection is + * connected. + * + * 'complete' can return 0 for incomplete, 1 for done and -1 for go back + * (which basically is only for when PASV is being sent to retry a failed + * EPSV). + */ + +static CURLcode ftp_do_more(struct connectdata *conn, int *completep) +{ + struct Curl_easy *data = conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + CURLcode result = CURLE_OK; + bool connected = FALSE; + bool complete = FALSE; + + /* the ftp struct is inited in ftp_connect() */ + struct FTP *ftp = data->req.protop; + + /* if the second connection isn't done yet, wait for it */ + if(!conn->bits.tcpconnect[SECONDARYSOCKET]) { + if(Curl_connect_ongoing(conn)) { + /* As we're in TUNNEL_CONNECT state now, we know the proxy name and port + aren't used so we blank their arguments. */ + result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0); + + return result; + } + + result = Curl_is_connected(conn, SECONDARYSOCKET, &connected); + + /* Ready to do more? */ + if(connected) { + DEBUGF(infof(data, "DO-MORE connected phase starts\n")); + } + else { + if(result && (ftpc->count1 == 0)) { + *completep = -1; /* go back to DOING please */ + /* this is a EPSV connect failing, try PASV instead */ + return ftp_epsv_disable(conn); + } + return result; + } + } + + result = Curl_proxy_connect(conn, SECONDARYSOCKET); + if(result) + return result; + + if(CONNECT_SECONDARYSOCKET_PROXY_SSL()) + return result; + + if(conn->bits.tunnel_proxy && conn->bits.httpproxy && + Curl_connect_ongoing(conn)) + return result; + + + if(ftpc->state) { + /* already in a state so skip the initial commands. + They are only done to kickstart the do_more state */ + result = ftp_multi_statemach(conn, &complete); + + *completep = (int)complete; + + /* if we got an error or if we don't wait for a data connection return + immediately */ + if(result || (ftpc->wait_data_conn != TRUE)) + return result; + + if(ftpc->wait_data_conn) + /* if we reach the end of the FTP state machine here, *complete will be + TRUE but so is ftpc->wait_data_conn, which says we need to wait for + the data connection and therefore we're not actually complete */ + *completep = 0; + } + + if(ftp->transfer <= FTPTRANSFER_INFO) { + /* a transfer is about to take place, or if not a file name was given + so we'll do a SIZE on it later and then we need the right TYPE first */ + + if(ftpc->wait_data_conn == TRUE) { + bool serv_conned; + + result = ReceivedServerConnect(conn, &serv_conned); + if(result) + return result; /* Failed to accept data connection */ + + if(serv_conned) { + /* It looks data connection is established */ + result = AcceptServerConnect(conn); + ftpc->wait_data_conn = FALSE; + if(!result) + result = InitiateTransfer(conn); + + if(result) + return result; + + *completep = 1; /* this state is now complete when the server has + connected back to us */ + } + } + else if(data->set.upload) { + result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_STOR_TYPE); + if(result) + return result; + + result = ftp_multi_statemach(conn, &complete); + if(ftpc->wait_data_conn) + /* if we reach the end of the FTP state machine here, *complete will be + TRUE but so is ftpc->wait_data_conn, which says we need to wait for + the data connection and therefore we're not actually complete */ + *completep = 0; + else + *completep = (int)complete; + } + else { + /* download */ + ftp->downloadsize = -1; /* unknown as of yet */ + + result = Curl_range(conn); + + if(result == CURLE_OK && data->req.maxdownload >= 0) { + /* Don't check for successful transfer */ + ftpc->dont_check = TRUE; + } + + if(result) + ; + else if(data->set.ftp_list_only || !ftpc->file) { + /* The specified path ends with a slash, and therefore we think this + is a directory that is requested, use LIST. But before that we + need to set ASCII transfer mode. */ + + /* But only if a body transfer was requested. */ + if(ftp->transfer == FTPTRANSFER_BODY) { + result = ftp_nb_type(conn, TRUE, FTP_LIST_TYPE); + if(result) + return result; + } + /* otherwise just fall through */ + } + else { + result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_RETR_TYPE); + if(result) + return result; + } + + result = ftp_multi_statemach(conn, &complete); + *completep = (int)complete; + } + return result; + } + + if(!result && (ftp->transfer != FTPTRANSFER_BODY)) + /* no data to transfer. FIX: it feels like a kludge to have this here + too! */ + Curl_setup_transfer(data, -1, -1, FALSE, -1); + + if(!ftpc->wait_data_conn) { + /* no waiting for the data connection so this is now complete */ + *completep = 1; + DEBUGF(infof(data, "DO-MORE phase ends with %d\n", (int)result)); + } + + return result; +} + + + +/*********************************************************************** + * + * ftp_perform() + * + * This is the actual DO function for FTP. Get a file/directory according to + * the options previously setup. + */ + +static +CURLcode ftp_perform(struct connectdata *conn, + bool *connected, /* connect status after PASV / PORT */ + bool *dophase_done) +{ + /* this is FTP and no proxy */ + CURLcode result = CURLE_OK; + + DEBUGF(infof(conn->data, "DO phase starts\n")); + + if(conn->data->set.opt_no_body) { + /* requested no body means no transfer... */ + struct FTP *ftp = conn->data->req.protop; + ftp->transfer = FTPTRANSFER_INFO; + } + + *dophase_done = FALSE; /* not done yet */ + + /* start the first command in the DO phase */ + result = ftp_state_quote(conn, TRUE, FTP_QUOTE); + if(result) + return result; + + /* run the state-machine */ + result = ftp_multi_statemach(conn, dophase_done); + + *connected = conn->bits.tcpconnect[SECONDARYSOCKET]; + + infof(conn->data, "ftp_perform ends with SECONDARY: %d\n", *connected); + + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete1\n")); + } + + return result; +} + +static void wc_data_dtor(void *ptr) +{ + struct ftp_wc *ftpwc = ptr; + if(ftpwc && ftpwc->parser) + Curl_ftp_parselist_data_free(&ftpwc->parser); + free(ftpwc); +} + +static CURLcode init_wc_data(struct connectdata *conn) +{ + char *last_slash; + struct FTP *ftp = conn->data->req.protop; + char *path = ftp->path; + struct WildcardData *wildcard = &(conn->data->wildcard); + CURLcode result = CURLE_OK; + struct ftp_wc *ftpwc = NULL; + + last_slash = strrchr(ftp->path, '/'); + if(last_slash) { + last_slash++; + if(last_slash[0] == '\0') { + wildcard->state = CURLWC_CLEAN; + result = ftp_parse_url_path(conn); + return result; + } + wildcard->pattern = strdup(last_slash); + if(!wildcard->pattern) + return CURLE_OUT_OF_MEMORY; + last_slash[0] = '\0'; /* cut file from path */ + } + else { /* there is only 'wildcard pattern' or nothing */ + if(path[0]) { + wildcard->pattern = strdup(path); + if(!wildcard->pattern) + return CURLE_OUT_OF_MEMORY; + path[0] = '\0'; + } + else { /* only list */ + wildcard->state = CURLWC_CLEAN; + result = ftp_parse_url_path(conn); + return result; + } + } + + /* program continues only if URL is not ending with slash, allocate needed + resources for wildcard transfer */ + + /* allocate ftp protocol specific wildcard data */ + ftpwc = calloc(1, sizeof(struct ftp_wc)); + if(!ftpwc) { + result = CURLE_OUT_OF_MEMORY; + goto fail; + } + + /* INITIALIZE parselist structure */ + ftpwc->parser = Curl_ftp_parselist_data_alloc(); + if(!ftpwc->parser) { + result = CURLE_OUT_OF_MEMORY; + goto fail; + } + + wildcard->protdata = ftpwc; /* put it to the WildcardData tmp pointer */ + wildcard->dtor = wc_data_dtor; + + /* wildcard does not support NOCWD option (assert it?) */ + if(conn->data->set.ftp_filemethod == FTPFILE_NOCWD) + conn->data->set.ftp_filemethod = FTPFILE_MULTICWD; + + /* try to parse ftp url */ + result = ftp_parse_url_path(conn); + if(result) { + goto fail; + } + + wildcard->path = strdup(ftp->path); + if(!wildcard->path) { + result = CURLE_OUT_OF_MEMORY; + goto fail; + } + + /* backup old write_function */ + ftpwc->backup.write_function = conn->data->set.fwrite_func; + /* parsing write function */ + conn->data->set.fwrite_func = Curl_ftp_parselist; + /* backup old file descriptor */ + ftpwc->backup.file_descriptor = conn->data->set.out; + /* let the writefunc callback know what curl pointer is working with */ + conn->data->set.out = conn; + + infof(conn->data, "Wildcard - Parsing started\n"); + return CURLE_OK; + + fail: + if(ftpwc) { + Curl_ftp_parselist_data_free(&ftpwc->parser); + free(ftpwc); + } + Curl_safefree(wildcard->pattern); + wildcard->dtor = ZERO_NULL; + wildcard->protdata = NULL; + return result; +} + +/* This is called recursively */ +static CURLcode wc_statemach(struct connectdata *conn) +{ + struct WildcardData * const wildcard = &(conn->data->wildcard); + CURLcode result = CURLE_OK; + + switch(wildcard->state) { + case CURLWC_INIT: + result = init_wc_data(conn); + if(wildcard->state == CURLWC_CLEAN) + /* only listing! */ + break; + wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING; + break; + + case CURLWC_MATCHING: { + /* In this state is LIST response successfully parsed, so lets restore + previous WRITEFUNCTION callback and WRITEDATA pointer */ + struct ftp_wc *ftpwc = wildcard->protdata; + conn->data->set.fwrite_func = ftpwc->backup.write_function; + conn->data->set.out = ftpwc->backup.file_descriptor; + ftpwc->backup.write_function = ZERO_NULL; + ftpwc->backup.file_descriptor = NULL; + wildcard->state = CURLWC_DOWNLOADING; + + if(Curl_ftp_parselist_geterror(ftpwc->parser)) { + /* error found in LIST parsing */ + wildcard->state = CURLWC_CLEAN; + return wc_statemach(conn); + } + if(wildcard->filelist.size == 0) { + /* no corresponding file */ + wildcard->state = CURLWC_CLEAN; + return CURLE_REMOTE_FILE_NOT_FOUND; + } + return wc_statemach(conn); + } + + case CURLWC_DOWNLOADING: { + /* filelist has at least one file, lets get first one */ + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct curl_fileinfo *finfo = wildcard->filelist.head->ptr; + struct FTP *ftp = conn->data->req.protop; + + char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename); + if(!tmp_path) + return CURLE_OUT_OF_MEMORY; + + /* switch default ftp->path and tmp_path */ + free(ftp->pathalloc); + ftp->pathalloc = ftp->path = tmp_path; + + infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename); + if(conn->data->set.chunk_bgn) { + long userresponse; + Curl_set_in_callback(conn->data, true); + userresponse = conn->data->set.chunk_bgn( + finfo, wildcard->customptr, (int)wildcard->filelist.size); + Curl_set_in_callback(conn->data, false); + switch(userresponse) { + case CURL_CHUNK_BGN_FUNC_SKIP: + infof(conn->data, "Wildcard - \"%s\" skipped by user\n", + finfo->filename); + wildcard->state = CURLWC_SKIP; + return wc_statemach(conn); + case CURL_CHUNK_BGN_FUNC_FAIL: + return CURLE_CHUNK_FAILED; + } + } + + if(finfo->filetype != CURLFILETYPE_FILE) { + wildcard->state = CURLWC_SKIP; + return wc_statemach(conn); + } + + if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE) + ftpc->known_filesize = finfo->size; + + result = ftp_parse_url_path(conn); + if(result) + return result; + + /* we don't need the Curl_fileinfo of first file anymore */ + Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL); + + if(wildcard->filelist.size == 0) { /* remains only one file to down. */ + wildcard->state = CURLWC_CLEAN; + /* after that will be ftp_do called once again and no transfer + will be done because of CURLWC_CLEAN state */ + return CURLE_OK; + } + } break; + + case CURLWC_SKIP: { + if(conn->data->set.chunk_end) { + Curl_set_in_callback(conn->data, true); + conn->data->set.chunk_end(conn->data->wildcard.customptr); + Curl_set_in_callback(conn->data, false); + } + Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL); + wildcard->state = (wildcard->filelist.size == 0) ? + CURLWC_CLEAN : CURLWC_DOWNLOADING; + return wc_statemach(conn); + } + + case CURLWC_CLEAN: { + struct ftp_wc *ftpwc = wildcard->protdata; + result = CURLE_OK; + if(ftpwc) + result = Curl_ftp_parselist_geterror(ftpwc->parser); + + wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE; + } break; + + case CURLWC_DONE: + case CURLWC_ERROR: + case CURLWC_CLEAR: + if(wildcard->dtor) + wildcard->dtor(wildcard->protdata); + break; + } + + return result; +} + +/*********************************************************************** + * + * ftp_do() + * + * This function is registered as 'curl_do' function. It decodes the path + * parts etc as a wrapper to the actual DO function (ftp_perform). + * + * The input argument is already checked for validity. + */ +static CURLcode ftp_do(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + *done = FALSE; /* default to false */ + ftpc->wait_data_conn = FALSE; /* default to no such wait */ + + if(conn->data->state.wildcardmatch) { + result = wc_statemach(conn); + if(conn->data->wildcard.state == CURLWC_SKIP || + conn->data->wildcard.state == CURLWC_DONE) { + /* do not call ftp_regular_transfer */ + return CURLE_OK; + } + if(result) /* error, loop or skipping the file */ + return result; + } + else { /* no wildcard FSM needed */ + result = ftp_parse_url_path(conn); + if(result) + return result; + } + + result = ftp_regular_transfer(conn, done); + + return result; +} + + +CURLcode Curl_ftpsend(struct connectdata *conn, const char *cmd) +{ + ssize_t bytes_written; +#define SBUF_SIZE 1024 + char s[SBUF_SIZE]; + size_t write_len; + char *sptr = s; + CURLcode result = CURLE_OK; +#ifdef HAVE_GSSAPI + enum protection_level data_sec = conn->data_prot; +#endif + + if(!cmd) + return CURLE_BAD_FUNCTION_ARGUMENT; + + write_len = strlen(cmd); + if(!write_len || write_len > (sizeof(s) -3)) + return CURLE_BAD_FUNCTION_ARGUMENT; + + memcpy(&s, cmd, write_len); + strcpy(&s[write_len], "\r\n"); /* append a trailing CRLF */ + write_len += 2; + bytes_written = 0; + + result = Curl_convert_to_network(conn->data, s, write_len); + /* Curl_convert_to_network calls failf if unsuccessful */ + if(result) + return result; + + for(;;) { +#ifdef HAVE_GSSAPI + conn->data_prot = PROT_CMD; +#endif + result = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len, + &bytes_written); +#ifdef HAVE_GSSAPI + DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST); + conn->data_prot = data_sec; +#endif + + if(result) + break; + + if(conn->data->set.verbose) + Curl_debug(conn->data, CURLINFO_HEADER_OUT, sptr, (size_t)bytes_written); + + if(bytes_written != (ssize_t)write_len) { + write_len -= bytes_written; + sptr += bytes_written; + } + else + break; + } + + return result; +} + +/*********************************************************************** + * + * ftp_quit() + * + * This should be called before calling sclose() on an ftp control connection + * (not data connections). We should then wait for the response from the + * server before returning. The calling code should then try to close the + * connection. + * + */ +static CURLcode ftp_quit(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + if(conn->proto.ftpc.ctl_valid) { + result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", "QUIT"); + if(result) { + failf(conn->data, "Failure sending QUIT command: %s", + curl_easy_strerror(result)); + conn->proto.ftpc.ctl_valid = FALSE; /* mark control connection as bad */ + connclose(conn, "QUIT command failed"); /* mark for connection closure */ + state(conn, FTP_STOP); + return result; + } + + state(conn, FTP_QUIT); + + result = ftp_block_statemach(conn); + } + + return result; +} + +/*********************************************************************** + * + * ftp_disconnect() + * + * Disconnect from an FTP server. Cleanup protocol-specific per-connection + * resources. BLOCKING. + */ +static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + + /* We cannot send quit unconditionally. If this connection is stale or + bad in any way, sending quit and waiting around here will make the + disconnect wait in vain and cause more problems than we need to. + + ftp_quit() will check the state of ftp->ctl_valid. If it's ok it + will try to send the QUIT command, otherwise it will just return. + */ + if(dead_connection) + ftpc->ctl_valid = FALSE; + + /* The FTP session may or may not have been allocated/setup at this point! */ + (void)ftp_quit(conn); /* ignore errors on the QUIT */ + + if(ftpc->entrypath) { + struct Curl_easy *data = conn->data; + if(data->state.most_recent_ftp_entrypath == ftpc->entrypath) { + data->state.most_recent_ftp_entrypath = NULL; + } + free(ftpc->entrypath); + ftpc->entrypath = NULL; + } + + freedirs(ftpc); + free(ftpc->prevpath); + ftpc->prevpath = NULL; + free(ftpc->server_os); + ftpc->server_os = NULL; + + Curl_pp_disconnect(pp); + +#ifdef HAVE_GSSAPI + Curl_sec_end(conn); +#endif + + return CURLE_OK; +} + +/*********************************************************************** + * + * ftp_parse_url_path() + * + * Parse the URL path into separate path components. + * + */ +static +CURLcode ftp_parse_url_path(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + /* the ftp struct is already inited in ftp_connect() */ + struct FTP *ftp = data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + const char *slash_pos; /* position of the first '/' char in curpos */ + const char *path_to_use = ftp->path; + const char *cur_pos; + const char *filename = NULL; + + cur_pos = path_to_use; /* current position in path. point at the begin of + next path component */ + + ftpc->ctl_valid = FALSE; + ftpc->cwdfail = FALSE; + + switch(data->set.ftp_filemethod) { + case FTPFILE_NOCWD: + /* fastest, but less standard-compliant */ + + /* + The best time to check whether the path is a file or directory is right + here. so: + + the first condition in the if() right here, is there just in case + someone decides to set path to NULL one day + */ + if(path_to_use[0] && + (path_to_use[strlen(path_to_use) - 1] != '/') ) + filename = path_to_use; /* this is a full file path */ + /* + else { + ftpc->file is not used anywhere other than for operations on a file. + In other words, never for directory operations. + So we can safely leave filename as NULL here and use it as a + argument in dir/file decisions. + } + */ + break; + + case FTPFILE_SINGLECWD: + /* get the last slash */ + if(!path_to_use[0]) { + /* no dir, no file */ + ftpc->dirdepth = 0; + break; + } + slash_pos = strrchr(cur_pos, '/'); + if(slash_pos || !*cur_pos) { + size_t dirlen = slash_pos-cur_pos; + CURLcode result; + + ftpc->dirs = calloc(1, sizeof(ftpc->dirs[0])); + if(!ftpc->dirs) + return CURLE_OUT_OF_MEMORY; + + if(!dirlen) + dirlen++; + + result = Curl_urldecode(conn->data, slash_pos ? cur_pos : "/", + slash_pos ? dirlen : 1, + &ftpc->dirs[0], NULL, + TRUE); + if(result) { + freedirs(ftpc); + return result; + } + ftpc->dirdepth = 1; /* we consider it to be a single dir */ + filename = slash_pos ? slash_pos + 1 : cur_pos; /* rest is file name */ + } + else + filename = cur_pos; /* this is a file name only */ + break; + + default: /* allow pretty much anything */ + case FTPFILE_MULTICWD: + ftpc->dirdepth = 0; + ftpc->diralloc = 5; /* default dir depth to allocate */ + ftpc->dirs = calloc(ftpc->diralloc, sizeof(ftpc->dirs[0])); + if(!ftpc->dirs) + return CURLE_OUT_OF_MEMORY; + + /* we have a special case for listing the root dir only */ + if(!strcmp(path_to_use, "/")) { + cur_pos++; /* make it point to the zero byte */ + ftpc->dirs[0] = strdup("/"); + ftpc->dirdepth++; + } + else { + /* parse the URL path into separate path components */ + while((slash_pos = strchr(cur_pos, '/')) != NULL) { + /* 1 or 0 pointer offset to indicate absolute directory */ + ssize_t absolute_dir = ((cur_pos - ftp->path > 0) && + (ftpc->dirdepth == 0))?1:0; + + /* seek out the next path component */ + if(slash_pos-cur_pos) { + /* we skip empty path components, like "x//y" since the FTP command + CWD requires a parameter and a non-existent parameter a) doesn't + work on many servers and b) has no effect on the others. */ + size_t len = slash_pos - cur_pos + absolute_dir; + CURLcode result = + Curl_urldecode(conn->data, cur_pos - absolute_dir, len, + &ftpc->dirs[ftpc->dirdepth], NULL, + TRUE); + if(result) { + freedirs(ftpc); + return result; + } + } + else { + cur_pos = slash_pos + 1; /* jump to the rest of the string */ + if(!ftpc->dirdepth) { + /* path starts with a slash, add that as a directory */ + ftpc->dirs[ftpc->dirdepth] = strdup("/"); + if(!ftpc->dirs[ftpc->dirdepth++]) { /* run out of memory ... */ + failf(data, "no memory"); + freedirs(ftpc); + return CURLE_OUT_OF_MEMORY; + } + } + continue; + } + + cur_pos = slash_pos + 1; /* jump to the rest of the string */ + if(++ftpc->dirdepth >= ftpc->diralloc) { + /* enlarge array */ + char **bigger; + ftpc->diralloc *= 2; /* double the size each time */ + bigger = realloc(ftpc->dirs, ftpc->diralloc * sizeof(ftpc->dirs[0])); + if(!bigger) { + freedirs(ftpc); + return CURLE_OUT_OF_MEMORY; + } + ftpc->dirs = bigger; + } + } + } + filename = cur_pos; /* the rest is the file name */ + break; + } /* switch */ + + if(filename && *filename) { + CURLcode result = + Curl_urldecode(conn->data, filename, 0, &ftpc->file, NULL, TRUE); + + if(result) { + freedirs(ftpc); + return result; + } + } + else + ftpc->file = NULL; /* instead of point to a zero byte, we make it a NULL + pointer */ + + if(data->set.upload && !ftpc->file && (ftp->transfer == FTPTRANSFER_BODY)) { + /* We need a file name when uploading. Return error! */ + failf(data, "Uploading to a URL without a file name!"); + return CURLE_URL_MALFORMAT; + } + + ftpc->cwddone = FALSE; /* default to not done */ + + if(ftpc->prevpath) { + /* prevpath is "raw" so we convert the input path before we compare the + strings */ + size_t dlen; + char *path; + CURLcode result = + Curl_urldecode(conn->data, ftp->path, 0, &path, &dlen, TRUE); + if(result) { + freedirs(ftpc); + return result; + } + + dlen -= ftpc->file?strlen(ftpc->file):0; + if((dlen == strlen(ftpc->prevpath)) && + !strncmp(path, ftpc->prevpath, dlen) && + (ftpc->prevmethod == data->set.ftp_filemethod)) { + infof(data, "Request has same path as previous transfer\n"); + ftpc->cwddone = TRUE; + } + free(path); + } + + return CURLE_OK; +} + +/* call this when the DO phase has completed */ +static CURLcode ftp_dophase_done(struct connectdata *conn, + bool connected) +{ + struct FTP *ftp = conn->data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if(connected) { + int completed; + CURLcode result = ftp_do_more(conn, &completed); + + if(result) { + close_secondarysocket(conn); + return result; + } + } + + if(ftp->transfer != FTPTRANSFER_BODY) + /* no data to transfer */ + Curl_setup_transfer(conn->data, -1, -1, FALSE, -1); + else if(!connected) + /* since we didn't connect now, we want do_more to get called */ + conn->bits.do_more = TRUE; + + ftpc->ctl_valid = TRUE; /* seems good */ + + return CURLE_OK; +} + +/* called from multi.c while DOing */ +static CURLcode ftp_doing(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result = ftp_multi_statemach(conn, dophase_done); + + if(result) + DEBUGF(infof(conn->data, "DO phase failed\n")); + else if(*dophase_done) { + result = ftp_dophase_done(conn, FALSE /* not connected */); + + DEBUGF(infof(conn->data, "DO phase is complete2\n")); + } + return result; +} + +/*********************************************************************** + * + * ftp_regular_transfer() + * + * The input argument is already checked for validity. + * + * Performs all commands done before a regular transfer between a local and a + * remote host. + * + * ftp->ctl_valid starts out as FALSE, and gets set to TRUE if we reach the + * ftp_done() function without finding any major problem. + */ +static +CURLcode ftp_regular_transfer(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result = CURLE_OK; + bool connected = FALSE; + struct Curl_easy *data = conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + data->req.size = -1; /* make sure this is unknown at this point */ + + Curl_pgrsSetUploadCounter(data, 0); + Curl_pgrsSetDownloadCounter(data, 0); + Curl_pgrsSetUploadSize(data, -1); + Curl_pgrsSetDownloadSize(data, -1); + + ftpc->ctl_valid = TRUE; /* starts good */ + + result = ftp_perform(conn, + &connected, /* have we connected after PASV/PORT */ + dophase_done); /* all commands in the DO-phase done? */ + + if(!result) { + + if(!*dophase_done) + /* the DO phase has not completed yet */ + return CURLE_OK; + + result = ftp_dophase_done(conn, connected); + + if(result) + return result; + } + else + freedirs(ftpc); + + return result; +} + +static CURLcode ftp_setup_connection(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + char *type; + struct FTP *ftp; + + conn->data->req.protop = ftp = calloc(sizeof(struct FTP), 1); + if(NULL == ftp) + return CURLE_OUT_OF_MEMORY; + + ftp->path = &data->state.up.path[1]; /* don't include the initial slash */ + + /* FTP URLs support an extension like ";type=" that + * we'll try to get now! */ + type = strstr(ftp->path, ";type="); + + if(!type) + type = strstr(conn->host.rawalloc, ";type="); + + if(type) { + char command; + *type = 0; /* it was in the middle of the hostname */ + command = Curl_raw_toupper(type[6]); + conn->bits.type_set = TRUE; + + switch(command) { + case 'A': /* ASCII mode */ + data->set.prefer_ascii = TRUE; + break; + + case 'D': /* directory mode */ + data->set.ftp_list_only = TRUE; + break; + + case 'I': /* binary mode */ + default: + /* switch off ASCII */ + data->set.prefer_ascii = FALSE; + break; + } + } + + /* get some initial data into the ftp struct */ + ftp->transfer = FTPTRANSFER_BODY; + ftp->downloadsize = 0; + + /* No need to duplicate user+password, the connectdata struct won't change + during a session, but we re-init them here since on subsequent inits + since the conn struct may have changed or been replaced. + */ + ftp->user = conn->user; + ftp->passwd = conn->passwd; + if(isBadFtpString(ftp->user)) + return CURLE_URL_MALFORMAT; + if(isBadFtpString(ftp->passwd)) + return CURLE_URL_MALFORMAT; + + conn->proto.ftpc.known_filesize = -1; /* unknown size for now */ + + return CURLE_OK; +} + +#endif /* CURL_DISABLE_FTP */ diff --git a/dependencies/cmcurl/lib/ftp.h b/dependencies/cmcurl/lib/ftp.h new file mode 100644 index 0000000..828d69a --- /dev/null +++ b/dependencies/cmcurl/lib/ftp.h @@ -0,0 +1,162 @@ +#ifndef HEADER_CURL_FTP_H +#define HEADER_CURL_FTP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "pingpong.h" + +#ifndef CURL_DISABLE_FTP +extern const struct Curl_handler Curl_handler_ftp; + +#ifdef USE_SSL +extern const struct Curl_handler Curl_handler_ftps; +#endif + +CURLcode Curl_ftpsend(struct connectdata *, const char *cmd); +CURLcode Curl_GetFTPResponse(ssize_t *nread, struct connectdata *conn, + int *ftpcode); +#endif /* CURL_DISABLE_FTP */ + +/**************************************************************************** + * FTP unique setup + ***************************************************************************/ +typedef enum { + FTP_STOP, /* do nothing state, stops the state machine */ + FTP_WAIT220, /* waiting for the initial 220 response immediately after + a connect */ + FTP_AUTH, + FTP_USER, + FTP_PASS, + FTP_ACCT, + FTP_PBSZ, + FTP_PROT, + FTP_CCC, + FTP_PWD, + FTP_SYST, + FTP_NAMEFMT, + FTP_QUOTE, /* waiting for a response to a command sent in a quote list */ + FTP_RETR_PREQUOTE, + FTP_STOR_PREQUOTE, + FTP_POSTQUOTE, + FTP_CWD, /* change dir */ + FTP_MKD, /* if the dir didn't exist */ + FTP_MDTM, /* to figure out the datestamp */ + FTP_TYPE, /* to set type when doing a head-like request */ + FTP_LIST_TYPE, /* set type when about to do a dir list */ + FTP_RETR_TYPE, /* set type when about to RETR a file */ + FTP_STOR_TYPE, /* set type when about to STOR a file */ + FTP_SIZE, /* get the remote file's size for head-like request */ + FTP_RETR_SIZE, /* get the remote file's size for RETR */ + FTP_STOR_SIZE, /* get the size for STOR */ + FTP_REST, /* when used to check if the server supports it in head-like */ + FTP_RETR_REST, /* when asking for "resume" in for RETR */ + FTP_PORT, /* generic state for PORT, LPRT and EPRT, check count1 */ + FTP_PRET, /* generic state for PRET RETR, PRET STOR and PRET LIST/NLST */ + FTP_PASV, /* generic state for PASV and EPSV, check count1 */ + FTP_LIST, /* generic state for LIST, NLST or a custom list command */ + FTP_RETR, + FTP_STOR, /* generic state for STOR and APPE */ + FTP_QUIT, + FTP_LAST /* never used */ +} ftpstate; + +struct ftp_parselist_data; /* defined later in ftplistparser.c */ + +struct ftp_wc { + struct ftp_parselist_data *parser; + + struct { + curl_write_callback write_function; + FILE *file_descriptor; + } backup; +}; + +typedef enum { + FTPFILE_MULTICWD = 1, /* as defined by RFC1738 */ + FTPFILE_NOCWD = 2, /* use SIZE / RETR / STOR on the full path */ + FTPFILE_SINGLECWD = 3 /* make one CWD, then SIZE / RETR / STOR on the + file */ +} curl_ftpfile; + +/* This FTP struct is used in the Curl_easy. All FTP data that is + connection-oriented must be in FTP_conn to properly deal with the fact that + perhaps the Curl_easy is changed between the times the connection is + used. */ +struct FTP { + char *user; /* user name string */ + char *passwd; /* password string */ + char *path; /* points to the urlpieces struct field */ + char *pathalloc; /* if non-NULL a pointer to an allocated path */ + + /* transfer a file/body or not, done as a typedefed enum just to make + debuggers display the full symbol and not just the numerical value */ + curl_pp_transfer transfer; + curl_off_t downloadsize; +}; + + +/* ftp_conn is used for struct connection-oriented data in the connectdata + struct */ +struct ftp_conn { + struct pingpong pp; + char *entrypath; /* the PWD reply when we logged on */ + char **dirs; /* realloc()ed array for path components */ + int dirdepth; /* number of entries used in the 'dirs' array */ + int diralloc; /* number of entries allocated for the 'dirs' array */ + char *file; /* decoded file */ + bool dont_check; /* Set to TRUE to prevent the final (post-transfer) + file size and 226/250 status check. It should still + read the line, just ignore the result. */ + bool ctl_valid; /* Tells Curl_ftp_quit() whether or not to do anything. If + the connection has timed out or been closed, this + should be FALSE when it gets to Curl_ftp_quit() */ + bool cwddone; /* if it has been determined that the proper CWD combo + already has been done */ + int cwdcount; /* number of CWD commands issued */ + bool cwdfail; /* set TRUE if a CWD command fails, as then we must prevent + caching the current directory */ + bool wait_data_conn; /* this is set TRUE if data connection is waited */ + char *prevpath; /* conn->path from the previous transfer */ + curl_ftpfile prevmethod; /* ftp method in previous transfer */ + char transfertype; /* set by ftp_transfertype for use by Curl_client_write()a + and others (A/I or zero) */ + int count1; /* general purpose counter for the state machine */ + int count2; /* general purpose counter for the state machine */ + int count3; /* general purpose counter for the state machine */ + ftpstate state; /* always use ftp.c:state() to change state! */ + ftpstate state_saved; /* transfer type saved to be reloaded after + data connection is established */ + curl_off_t retr_size_saved; /* Size of retrieved file saved */ + char *server_os; /* The target server operating system. */ + curl_off_t known_filesize; /* file size is different from -1, if wildcard + LIST parsing was done and wc_statemach set + it */ + /* newhost is the (allocated) IP addr or host name to connect the data + connection to */ + char *newhost; /* this is the pair to connect the DATA... */ + unsigned short newport; /* connection to */ + +}; + +#define DEFAULT_ACCEPT_TIMEOUT 60000 /* milliseconds == one minute */ + +#endif /* HEADER_CURL_FTP_H */ diff --git a/dependencies/cmcurl/lib/ftplistparser.c b/dependencies/cmcurl/lib/ftplistparser.c new file mode 100644 index 0000000..c4eb437 --- /dev/null +++ b/dependencies/cmcurl/lib/ftplistparser.c @@ -0,0 +1,1019 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/** + * Now implemented: + * + * 1) Unix version 1 + * drwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog + * 2) Unix version 2 + * drwxr-xr-x 1 user01 ftp 512 Jan 29 1997 prog + * 3) Unix version 3 + * drwxr-xr-x 1 1 1 512 Jan 29 23:32 prog + * 4) Unix symlink + * lrwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog -> prog2000 + * 5) DOS style + * 01-29-97 11:32PM prog + */ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_FTP + +#include + +#include "urldata.h" +#include "fileinfo.h" +#include "llist.h" +#include "strtoofft.h" +#include "ftp.h" +#include "ftplistparser.h" +#include "curl_fnmatch.h" +#include "curl_memory.h" +#include "multiif.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* allocs buffer which will contain one line of LIST command response */ +#define FTP_BUFFER_ALLOCSIZE 160 + +typedef enum { + PL_UNIX_TOTALSIZE = 0, + PL_UNIX_FILETYPE, + PL_UNIX_PERMISSION, + PL_UNIX_HLINKS, + PL_UNIX_USER, + PL_UNIX_GROUP, + PL_UNIX_SIZE, + PL_UNIX_TIME, + PL_UNIX_FILENAME, + PL_UNIX_SYMLINK +} pl_unix_mainstate; + +typedef union { + enum { + PL_UNIX_TOTALSIZE_INIT = 0, + PL_UNIX_TOTALSIZE_READING + } total_dirsize; + + enum { + PL_UNIX_HLINKS_PRESPACE = 0, + PL_UNIX_HLINKS_NUMBER + } hlinks; + + enum { + PL_UNIX_USER_PRESPACE = 0, + PL_UNIX_USER_PARSING + } user; + + enum { + PL_UNIX_GROUP_PRESPACE = 0, + PL_UNIX_GROUP_NAME + } group; + + enum { + PL_UNIX_SIZE_PRESPACE = 0, + PL_UNIX_SIZE_NUMBER + } size; + + enum { + PL_UNIX_TIME_PREPART1 = 0, + PL_UNIX_TIME_PART1, + PL_UNIX_TIME_PREPART2, + PL_UNIX_TIME_PART2, + PL_UNIX_TIME_PREPART3, + PL_UNIX_TIME_PART3 + } time; + + enum { + PL_UNIX_FILENAME_PRESPACE = 0, + PL_UNIX_FILENAME_NAME, + PL_UNIX_FILENAME_WINDOWSEOL + } filename; + + enum { + PL_UNIX_SYMLINK_PRESPACE = 0, + PL_UNIX_SYMLINK_NAME, + PL_UNIX_SYMLINK_PRETARGET1, + PL_UNIX_SYMLINK_PRETARGET2, + PL_UNIX_SYMLINK_PRETARGET3, + PL_UNIX_SYMLINK_PRETARGET4, + PL_UNIX_SYMLINK_TARGET, + PL_UNIX_SYMLINK_WINDOWSEOL + } symlink; +} pl_unix_substate; + +typedef enum { + PL_WINNT_DATE = 0, + PL_WINNT_TIME, + PL_WINNT_DIRORSIZE, + PL_WINNT_FILENAME +} pl_winNT_mainstate; + +typedef union { + enum { + PL_WINNT_TIME_PRESPACE = 0, + PL_WINNT_TIME_TIME + } time; + enum { + PL_WINNT_DIRORSIZE_PRESPACE = 0, + PL_WINNT_DIRORSIZE_CONTENT + } dirorsize; + enum { + PL_WINNT_FILENAME_PRESPACE = 0, + PL_WINNT_FILENAME_CONTENT, + PL_WINNT_FILENAME_WINEOL + } filename; +} pl_winNT_substate; + +/* This struct is used in wildcard downloading - for parsing LIST response */ +struct ftp_parselist_data { + enum { + OS_TYPE_UNKNOWN = 0, + OS_TYPE_UNIX, + OS_TYPE_WIN_NT + } os_type; + + union { + struct { + pl_unix_mainstate main; + pl_unix_substate sub; + } UNIX; + + struct { + pl_winNT_mainstate main; + pl_winNT_substate sub; + } NT; + } state; + + CURLcode error; + struct fileinfo *file_data; + unsigned int item_length; + size_t item_offset; + struct { + size_t filename; + size_t user; + size_t group; + size_t time; + size_t perm; + size_t symlink_target; + } offsets; +}; + +struct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void) +{ + return calloc(1, sizeof(struct ftp_parselist_data)); +} + + +void Curl_ftp_parselist_data_free(struct ftp_parselist_data **parserp) +{ + struct ftp_parselist_data *parser = *parserp; + if(parser) + Curl_fileinfo_cleanup(parser->file_data); + free(parser); + *parserp = NULL; +} + + +CURLcode Curl_ftp_parselist_geterror(struct ftp_parselist_data *pl_data) +{ + return pl_data->error; +} + + +#define FTP_LP_MALFORMATED_PERM 0x01000000 + +static int ftp_pl_get_permission(const char *str) +{ + int permissions = 0; + /* USER */ + if(str[0] == 'r') + permissions |= 1 << 8; + else if(str[0] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + if(str[1] == 'w') + permissions |= 1 << 7; + else if(str[1] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + + if(str[2] == 'x') + permissions |= 1 << 6; + else if(str[2] == 's') { + permissions |= 1 << 6; + permissions |= 1 << 11; + } + else if(str[2] == 'S') + permissions |= 1 << 11; + else if(str[2] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + /* GROUP */ + if(str[3] == 'r') + permissions |= 1 << 5; + else if(str[3] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + if(str[4] == 'w') + permissions |= 1 << 4; + else if(str[4] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + if(str[5] == 'x') + permissions |= 1 << 3; + else if(str[5] == 's') { + permissions |= 1 << 3; + permissions |= 1 << 10; + } + else if(str[5] == 'S') + permissions |= 1 << 10; + else if(str[5] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + /* others */ + if(str[6] == 'r') + permissions |= 1 << 2; + else if(str[6] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + if(str[7] == 'w') + permissions |= 1 << 1; + else if(str[7] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + if(str[8] == 'x') + permissions |= 1; + else if(str[8] == 't') { + permissions |= 1; + permissions |= 1 << 9; + } + else if(str[8] == 'T') + permissions |= 1 << 9; + else if(str[8] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + + return permissions; +} + +static CURLcode ftp_pl_insert_finfo(struct connectdata *conn, + struct fileinfo *infop) +{ + curl_fnmatch_callback compare; + struct WildcardData *wc = &conn->data->wildcard; + struct ftp_wc *ftpwc = wc->protdata; + struct curl_llist *llist = &wc->filelist; + struct ftp_parselist_data *parser = ftpwc->parser; + bool add = TRUE; + struct curl_fileinfo *finfo = &infop->info; + + /* move finfo pointers to b_data */ + char *str = finfo->b_data; + finfo->filename = str + parser->offsets.filename; + finfo->strings.group = parser->offsets.group ? + str + parser->offsets.group : NULL; + finfo->strings.perm = parser->offsets.perm ? + str + parser->offsets.perm : NULL; + finfo->strings.target = parser->offsets.symlink_target ? + str + parser->offsets.symlink_target : NULL; + finfo->strings.time = str + parser->offsets.time; + finfo->strings.user = parser->offsets.user ? + str + parser->offsets.user : NULL; + + /* get correct fnmatch callback */ + compare = conn->data->set.fnmatch; + if(!compare) + compare = Curl_fnmatch; + + /* filter pattern-corresponding filenames */ + Curl_set_in_callback(conn->data, true); + if(compare(conn->data->set.fnmatch_data, wc->pattern, + finfo->filename) == 0) { + /* discard symlink which is containing multiple " -> " */ + if((finfo->filetype == CURLFILETYPE_SYMLINK) && finfo->strings.target && + (strstr(finfo->strings.target, " -> "))) { + add = FALSE; + } + } + else { + add = FALSE; + } + Curl_set_in_callback(conn->data, false); + + if(add) { + Curl_llist_insert_next(llist, llist->tail, finfo, &infop->list); + } + else { + Curl_fileinfo_cleanup(infop); + } + + ftpwc->parser->file_data = NULL; + return CURLE_OK; +} + +size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, + void *connptr) +{ + size_t bufflen = size*nmemb; + struct connectdata *conn = (struct connectdata *)connptr; + struct ftp_wc *ftpwc = conn->data->wildcard.protdata; + struct ftp_parselist_data *parser = ftpwc->parser; + struct fileinfo *infop; + struct curl_fileinfo *finfo; + unsigned long i = 0; + CURLcode result; + size_t retsize = bufflen; + + if(parser->error) { /* error in previous call */ + /* scenario: + * 1. call => OK.. + * 2. call => OUT_OF_MEMORY (or other error) + * 3. (last) call => is skipped RIGHT HERE and the error is hadled later + * in wc_statemach() + */ + goto fail; + } + + if(parser->os_type == OS_TYPE_UNKNOWN && bufflen > 0) { + /* considering info about FILE response format */ + parser->os_type = (buffer[0] >= '0' && buffer[0] <= '9') ? + OS_TYPE_WIN_NT : OS_TYPE_UNIX; + } + + while(i < bufflen) { /* FSM */ + + char c = buffer[i]; + if(!parser->file_data) { /* tmp file data is not allocated yet */ + parser->file_data = Curl_fileinfo_alloc(); + if(!parser->file_data) { + parser->error = CURLE_OUT_OF_MEMORY; + goto fail; + } + parser->file_data->info.b_data = malloc(FTP_BUFFER_ALLOCSIZE); + if(!parser->file_data->info.b_data) { + parser->error = CURLE_OUT_OF_MEMORY; + goto fail; + } + parser->file_data->info.b_size = FTP_BUFFER_ALLOCSIZE; + parser->item_offset = 0; + parser->item_length = 0; + } + + infop = parser->file_data; + finfo = &infop->info; + finfo->b_data[finfo->b_used++] = c; + + if(finfo->b_used >= finfo->b_size - 1) { + /* if it is important, extend buffer space for file data */ + char *tmp = realloc(finfo->b_data, + finfo->b_size + FTP_BUFFER_ALLOCSIZE); + if(tmp) { + finfo->b_size += FTP_BUFFER_ALLOCSIZE; + finfo->b_data = tmp; + } + else { + Curl_fileinfo_cleanup(parser->file_data); + parser->file_data = NULL; + parser->error = CURLE_OUT_OF_MEMORY; + goto fail; + } + } + + switch(parser->os_type) { + case OS_TYPE_UNIX: + switch(parser->state.UNIX.main) { + case PL_UNIX_TOTALSIZE: + switch(parser->state.UNIX.sub.total_dirsize) { + case PL_UNIX_TOTALSIZE_INIT: + if(c == 't') { + parser->state.UNIX.sub.total_dirsize = PL_UNIX_TOTALSIZE_READING; + parser->item_length++; + } + else { + parser->state.UNIX.main = PL_UNIX_FILETYPE; + /* start FSM again not considering size of directory */ + finfo->b_used = 0; + continue; + } + break; + case PL_UNIX_TOTALSIZE_READING: + parser->item_length++; + if(c == '\r') { + parser->item_length--; + finfo->b_used--; + } + else if(c == '\n') { + finfo->b_data[parser->item_length - 1] = 0; + if(strncmp("total ", finfo->b_data, 6) == 0) { + char *endptr = finfo->b_data + 6; + /* here we can deal with directory size, pass the leading white + spaces and then the digits */ + while(ISSPACE(*endptr)) + endptr++; + while(ISDIGIT(*endptr)) + endptr++; + if(*endptr != 0) { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + parser->state.UNIX.main = PL_UNIX_FILETYPE; + finfo->b_used = 0; + } + else { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + } + break; + } + break; + case PL_UNIX_FILETYPE: + switch(c) { + case '-': + finfo->filetype = CURLFILETYPE_FILE; + break; + case 'd': + finfo->filetype = CURLFILETYPE_DIRECTORY; + break; + case 'l': + finfo->filetype = CURLFILETYPE_SYMLINK; + break; + case 'p': + finfo->filetype = CURLFILETYPE_NAMEDPIPE; + break; + case 's': + finfo->filetype = CURLFILETYPE_SOCKET; + break; + case 'c': + finfo->filetype = CURLFILETYPE_DEVICE_CHAR; + break; + case 'b': + finfo->filetype = CURLFILETYPE_DEVICE_BLOCK; + break; + case 'D': + finfo->filetype = CURLFILETYPE_DOOR; + break; + default: + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + parser->state.UNIX.main = PL_UNIX_PERMISSION; + parser->item_length = 0; + parser->item_offset = 1; + break; + case PL_UNIX_PERMISSION: + parser->item_length++; + if(parser->item_length <= 9) { + if(!strchr("rwx-tTsS", c)) { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + } + else if(parser->item_length == 10) { + unsigned int perm; + if(c != ' ') { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + finfo->b_data[10] = 0; /* terminate permissions */ + perm = ftp_pl_get_permission(finfo->b_data + parser->item_offset); + if(perm & FTP_LP_MALFORMATED_PERM) { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_PERM; + parser->file_data->info.perm = perm; + parser->offsets.perm = parser->item_offset; + + parser->item_length = 0; + parser->state.UNIX.main = PL_UNIX_HLINKS; + parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_PRESPACE; + } + break; + case PL_UNIX_HLINKS: + switch(parser->state.UNIX.sub.hlinks) { + case PL_UNIX_HLINKS_PRESPACE: + if(c != ' ') { + if(c >= '0' && c <= '9') { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_NUMBER; + } + else { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + } + break; + case PL_UNIX_HLINKS_NUMBER: + parser->item_length ++; + if(c == ' ') { + char *p; + long int hlinks; + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + hlinks = strtol(finfo->b_data + parser->item_offset, &p, 10); + if(p[0] == '\0' && hlinks != LONG_MAX && hlinks != LONG_MIN) { + parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT; + parser->file_data->info.hardlinks = hlinks; + } + parser->item_length = 0; + parser->item_offset = 0; + parser->state.UNIX.main = PL_UNIX_USER; + parser->state.UNIX.sub.user = PL_UNIX_USER_PRESPACE; + } + else if(c < '0' || c > '9') { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + break; + } + break; + case PL_UNIX_USER: + switch(parser->state.UNIX.sub.user) { + case PL_UNIX_USER_PRESPACE: + if(c != ' ') { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.UNIX.sub.user = PL_UNIX_USER_PARSING; + } + break; + case PL_UNIX_USER_PARSING: + parser->item_length++; + if(c == ' ') { + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + parser->offsets.user = parser->item_offset; + parser->state.UNIX.main = PL_UNIX_GROUP; + parser->state.UNIX.sub.group = PL_UNIX_GROUP_PRESPACE; + parser->item_offset = 0; + parser->item_length = 0; + } + break; + } + break; + case PL_UNIX_GROUP: + switch(parser->state.UNIX.sub.group) { + case PL_UNIX_GROUP_PRESPACE: + if(c != ' ') { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.UNIX.sub.group = PL_UNIX_GROUP_NAME; + } + break; + case PL_UNIX_GROUP_NAME: + parser->item_length++; + if(c == ' ') { + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + parser->offsets.group = parser->item_offset; + parser->state.UNIX.main = PL_UNIX_SIZE; + parser->state.UNIX.sub.size = PL_UNIX_SIZE_PRESPACE; + parser->item_offset = 0; + parser->item_length = 0; + } + break; + } + break; + case PL_UNIX_SIZE: + switch(parser->state.UNIX.sub.size) { + case PL_UNIX_SIZE_PRESPACE: + if(c != ' ') { + if(c >= '0' && c <= '9') { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.UNIX.sub.size = PL_UNIX_SIZE_NUMBER; + } + else { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + } + break; + case PL_UNIX_SIZE_NUMBER: + parser->item_length++; + if(c == ' ') { + char *p; + curl_off_t fsize; + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + if(!curlx_strtoofft(finfo->b_data + parser->item_offset, + &p, 10, &fsize)) { + if(p[0] == '\0' && fsize != CURL_OFF_T_MAX && + fsize != CURL_OFF_T_MIN) { + parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE; + parser->file_data->info.size = fsize; + } + parser->item_length = 0; + parser->item_offset = 0; + parser->state.UNIX.main = PL_UNIX_TIME; + parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART1; + } + } + else if(!ISDIGIT(c)) { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + break; + } + break; + case PL_UNIX_TIME: + switch(parser->state.UNIX.sub.time) { + case PL_UNIX_TIME_PREPART1: + if(c != ' ') { + if(ISALNUM(c)) { + parser->item_offset = finfo->b_used -1; + parser->item_length = 1; + parser->state.UNIX.sub.time = PL_UNIX_TIME_PART1; + } + else { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + } + break; + case PL_UNIX_TIME_PART1: + parser->item_length++; + if(c == ' ') { + parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART2; + } + else if(!ISALNUM(c) && c != '.') { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + break; + case PL_UNIX_TIME_PREPART2: + parser->item_length++; + if(c != ' ') { + if(ISALNUM(c)) { + parser->state.UNIX.sub.time = PL_UNIX_TIME_PART2; + } + else { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + } + break; + case PL_UNIX_TIME_PART2: + parser->item_length++; + if(c == ' ') { + parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART3; + } + else if(!ISALNUM(c) && c != '.') { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + break; + case PL_UNIX_TIME_PREPART3: + parser->item_length++; + if(c != ' ') { + if(ISALNUM(c)) { + parser->state.UNIX.sub.time = PL_UNIX_TIME_PART3; + } + else { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + } + break; + case PL_UNIX_TIME_PART3: + parser->item_length++; + if(c == ' ') { + finfo->b_data[parser->item_offset + parser->item_length -1] = 0; + parser->offsets.time = parser->item_offset; + /* + if(ftp_pl_gettime(parser, finfo->b_data + parser->item_offset)) { + parser->file_data->flags |= CURLFINFOFLAG_KNOWN_TIME; + } + */ + if(finfo->filetype == CURLFILETYPE_SYMLINK) { + parser->state.UNIX.main = PL_UNIX_SYMLINK; + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRESPACE; + } + else { + parser->state.UNIX.main = PL_UNIX_FILENAME; + parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_PRESPACE; + } + } + else if(!ISALNUM(c) && c != '.' && c != ':') { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + break; + } + break; + case PL_UNIX_FILENAME: + switch(parser->state.UNIX.sub.filename) { + case PL_UNIX_FILENAME_PRESPACE: + if(c != ' ') { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_NAME; + } + break; + case PL_UNIX_FILENAME_NAME: + parser->item_length++; + if(c == '\r') { + parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_WINDOWSEOL; + } + else if(c == '\n') { + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + parser->offsets.filename = parser->item_offset; + parser->state.UNIX.main = PL_UNIX_FILETYPE; + result = ftp_pl_insert_finfo(conn, infop); + if(result) { + parser->error = result; + goto fail; + } + } + break; + case PL_UNIX_FILENAME_WINDOWSEOL: + if(c == '\n') { + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + parser->offsets.filename = parser->item_offset; + parser->state.UNIX.main = PL_UNIX_FILETYPE; + result = ftp_pl_insert_finfo(conn, infop); + if(result) { + parser->error = result; + goto fail; + } + } + else { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + break; + } + break; + case PL_UNIX_SYMLINK: + switch(parser->state.UNIX.sub.symlink) { + case PL_UNIX_SYMLINK_PRESPACE: + if(c != ' ') { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME; + } + break; + case PL_UNIX_SYMLINK_NAME: + parser->item_length++; + if(c == ' ') { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET1; + } + else if(c == '\r' || c == '\n') { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + break; + case PL_UNIX_SYMLINK_PRETARGET1: + parser->item_length++; + if(c == '-') { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET2; + } + else if(c == '\r' || c == '\n') { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + else { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME; + } + break; + case PL_UNIX_SYMLINK_PRETARGET2: + parser->item_length++; + if(c == '>') { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET3; + } + else if(c == '\r' || c == '\n') { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + else { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME; + } + break; + case PL_UNIX_SYMLINK_PRETARGET3: + parser->item_length++; + if(c == ' ') { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET4; + /* now place where is symlink following */ + finfo->b_data[parser->item_offset + parser->item_length - 4] = 0; + parser->offsets.filename = parser->item_offset; + parser->item_length = 0; + parser->item_offset = 0; + } + else if(c == '\r' || c == '\n') { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + else { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME; + } + break; + case PL_UNIX_SYMLINK_PRETARGET4: + if(c != '\r' && c != '\n') { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_TARGET; + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + } + else { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + break; + case PL_UNIX_SYMLINK_TARGET: + parser->item_length++; + if(c == '\r') { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_WINDOWSEOL; + } + else if(c == '\n') { + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + parser->offsets.symlink_target = parser->item_offset; + result = ftp_pl_insert_finfo(conn, infop); + if(result) { + parser->error = result; + goto fail; + } + parser->state.UNIX.main = PL_UNIX_FILETYPE; + } + break; + case PL_UNIX_SYMLINK_WINDOWSEOL: + if(c == '\n') { + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + parser->offsets.symlink_target = parser->item_offset; + result = ftp_pl_insert_finfo(conn, infop); + if(result) { + parser->error = result; + goto fail; + } + parser->state.UNIX.main = PL_UNIX_FILETYPE; + } + else { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + break; + } + break; + } + break; + case OS_TYPE_WIN_NT: + switch(parser->state.NT.main) { + case PL_WINNT_DATE: + parser->item_length++; + if(parser->item_length < 9) { + if(!strchr("0123456789-", c)) { /* only simple control */ + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + } + else if(parser->item_length == 9) { + if(c == ' ') { + parser->state.NT.main = PL_WINNT_TIME; + parser->state.NT.sub.time = PL_WINNT_TIME_PRESPACE; + } + else { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + } + else { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + break; + case PL_WINNT_TIME: + parser->item_length++; + switch(parser->state.NT.sub.time) { + case PL_WINNT_TIME_PRESPACE: + if(!ISSPACE(c)) { + parser->state.NT.sub.time = PL_WINNT_TIME_TIME; + } + break; + case PL_WINNT_TIME_TIME: + if(c == ' ') { + parser->offsets.time = parser->item_offset; + finfo->b_data[parser->item_offset + parser->item_length -1] = 0; + parser->state.NT.main = PL_WINNT_DIRORSIZE; + parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_PRESPACE; + parser->item_length = 0; + } + else if(!strchr("APM0123456789:", c)) { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + break; + } + break; + case PL_WINNT_DIRORSIZE: + switch(parser->state.NT.sub.dirorsize) { + case PL_WINNT_DIRORSIZE_PRESPACE: + if(c != ' ') { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_CONTENT; + } + break; + case PL_WINNT_DIRORSIZE_CONTENT: + parser->item_length ++; + if(c == ' ') { + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + if(strcmp("", finfo->b_data + parser->item_offset) == 0) { + finfo->filetype = CURLFILETYPE_DIRECTORY; + finfo->size = 0; + } + else { + char *endptr; + if(curlx_strtoofft(finfo->b_data + + parser->item_offset, + &endptr, 10, &finfo->size)) { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + /* correct file type */ + parser->file_data->info.filetype = CURLFILETYPE_FILE; + } + + parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE; + parser->item_length = 0; + parser->state.NT.main = PL_WINNT_FILENAME; + parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE; + } + break; + } + break; + case PL_WINNT_FILENAME: + switch(parser->state.NT.sub.filename) { + case PL_WINNT_FILENAME_PRESPACE: + if(c != ' ') { + parser->item_offset = finfo->b_used -1; + parser->item_length = 1; + parser->state.NT.sub.filename = PL_WINNT_FILENAME_CONTENT; + } + break; + case PL_WINNT_FILENAME_CONTENT: + parser->item_length++; + if(c == '\r') { + parser->state.NT.sub.filename = PL_WINNT_FILENAME_WINEOL; + finfo->b_data[finfo->b_used - 1] = 0; + } + else if(c == '\n') { + parser->offsets.filename = parser->item_offset; + finfo->b_data[finfo->b_used - 1] = 0; + parser->offsets.filename = parser->item_offset; + result = ftp_pl_insert_finfo(conn, infop); + if(result) { + parser->error = result; + goto fail; + } + parser->state.NT.main = PL_WINNT_DATE; + parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE; + } + break; + case PL_WINNT_FILENAME_WINEOL: + if(c == '\n') { + parser->offsets.filename = parser->item_offset; + result = ftp_pl_insert_finfo(conn, infop); + if(result) { + parser->error = result; + goto fail; + } + parser->state.NT.main = PL_WINNT_DATE; + parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE; + } + else { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + break; + } + break; + } + break; + default: + retsize = bufflen + 1; + goto fail; + } + + i++; + } + return retsize; + +fail: + + /* Clean up any allocated memory. */ + if(parser->file_data) { + Curl_fileinfo_cleanup(parser->file_data); + parser->file_data = NULL; + } + + return retsize; +} + +#endif /* CURL_DISABLE_FTP */ diff --git a/dependencies/cmcurl/lib/ftplistparser.h b/dependencies/cmcurl/lib/ftplistparser.h new file mode 100644 index 0000000..8128887 --- /dev/null +++ b/dependencies/cmcurl/lib/ftplistparser.h @@ -0,0 +1,41 @@ +#ifndef HEADER_CURL_FTPLISTPARSER_H +#define HEADER_CURL_FTPLISTPARSER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifndef CURL_DISABLE_FTP + +/* WRITEFUNCTION callback for parsing LIST responses */ +size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, + void *connptr); + +struct ftp_parselist_data; /* defined inside ftplibparser.c */ + +CURLcode Curl_ftp_parselist_geterror(struct ftp_parselist_data *pl_data); + +struct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void); + +void Curl_ftp_parselist_data_free(struct ftp_parselist_data **pl_data); + +#endif /* CURL_DISABLE_FTP */ +#endif /* HEADER_CURL_FTPLISTPARSER_H */ diff --git a/dependencies/cmcurl/lib/getenv.c b/dependencies/cmcurl/lib/getenv.c new file mode 100644 index 0000000..89d181d --- /dev/null +++ b/dependencies/cmcurl/lib/getenv.c @@ -0,0 +1,54 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include +#include "curl_memory.h" + +#include "memdebug.h" + +static +char *GetEnv(const char *variable) +{ +#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP) + (void)variable; + return NULL; +#else +#ifdef WIN32 + char env[MAX_PATH]; /* MAX_PATH is from windef.h */ + char *temp = getenv(variable); + env[0] = '\0'; + if(temp != NULL) + ExpandEnvironmentStringsA(temp, env, sizeof(env)); + return (env[0] != '\0')?strdup(env):NULL; +#else + char *env = getenv(variable); + return (env && env[0])?strdup(env):NULL; +#endif +#endif +} + +char *curl_getenv(const char *v) +{ + return GetEnv(v); +} diff --git a/dependencies/cmcurl/lib/getinfo.c b/dependencies/cmcurl/lib/getinfo.c new file mode 100644 index 0000000..e118da8 --- /dev/null +++ b/dependencies/cmcurl/lib/getinfo.c @@ -0,0 +1,490 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "urldata.h" +#include "getinfo.h" + +#include "vtls/vtls.h" +#include "connect.h" /* Curl_getconnectinfo() */ +#include "progress.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Initialize statistical and informational data. + * + * This function is called in curl_easy_reset, curl_easy_duphandle and at the + * beginning of a perform session. It must reset the session-info variables, + * in particular all variables in struct PureInfo. + */ +CURLcode Curl_initinfo(struct Curl_easy *data) +{ + struct Progress *pro = &data->progress; + struct PureInfo *info = &data->info; + + pro->t_nslookup = 0; + pro->t_connect = 0; + pro->t_appconnect = 0; + pro->t_pretransfer = 0; + pro->t_starttransfer = 0; + pro->timespent = 0; + pro->t_redirect = 0; + pro->is_t_startransfer_set = false; + + info->httpcode = 0; + info->httpproxycode = 0; + info->httpversion = 0; + info->filetime = -1; /* -1 is an illegal time and thus means unknown */ + info->timecond = FALSE; + + info->header_size = 0; + info->request_size = 0; + info->proxyauthavail = 0; + info->httpauthavail = 0; + info->numconnects = 0; + + free(info->contenttype); + info->contenttype = NULL; + + free(info->wouldredirect); + info->wouldredirect = NULL; + + info->conn_primary_ip[0] = '\0'; + info->conn_local_ip[0] = '\0'; + info->conn_primary_port = 0; + info->conn_local_port = 0; + + info->conn_scheme = 0; + info->conn_protocol = 0; + +#ifdef USE_SSL + Curl_ssl_free_certinfo(data); +#endif + return CURLE_OK; +} + +static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info, + const char **param_charp) +{ + switch(info) { + case CURLINFO_EFFECTIVE_URL: + *param_charp = data->change.url?data->change.url:(char *)""; + break; + case CURLINFO_CONTENT_TYPE: + *param_charp = data->info.contenttype; + break; + case CURLINFO_PRIVATE: + *param_charp = (char *) data->set.private_data; + break; + case CURLINFO_FTP_ENTRY_PATH: + /* Return the entrypath string from the most recent connection. + This pointer was copied from the connectdata structure by FTP. + The actual string may be free()ed by subsequent libcurl calls so + it must be copied to a safer area before the next libcurl call. + Callers must never free it themselves. */ + *param_charp = data->state.most_recent_ftp_entrypath; + break; + case CURLINFO_REDIRECT_URL: + /* Return the URL this request would have been redirected to if that + option had been enabled! */ + *param_charp = data->info.wouldredirect; + break; + case CURLINFO_PRIMARY_IP: + /* Return the ip address of the most recent (primary) connection */ + *param_charp = data->info.conn_primary_ip; + break; + case CURLINFO_LOCAL_IP: + /* Return the source/local ip address of the most recent (primary) + connection */ + *param_charp = data->info.conn_local_ip; + break; + case CURLINFO_RTSP_SESSION_ID: + *param_charp = data->set.str[STRING_RTSP_SESSION_ID]; + break; + case CURLINFO_SCHEME: + *param_charp = data->info.conn_scheme; + break; + + default: + return CURLE_UNKNOWN_OPTION; + } + + return CURLE_OK; +} + +static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info, + long *param_longp) +{ + curl_socket_t sockfd; + + union { + unsigned long *to_ulong; + long *to_long; + } lptr; + + switch(info) { + case CURLINFO_RESPONSE_CODE: + *param_longp = data->info.httpcode; + break; + case CURLINFO_HTTP_CONNECTCODE: + *param_longp = data->info.httpproxycode; + break; + case CURLINFO_FILETIME: + if(data->info.filetime > LONG_MAX) + *param_longp = LONG_MAX; + else if(data->info.filetime < LONG_MIN) + *param_longp = LONG_MIN; + else + *param_longp = (long)data->info.filetime; + break; + case CURLINFO_HEADER_SIZE: + *param_longp = (long)data->info.header_size; + break; + case CURLINFO_REQUEST_SIZE: + *param_longp = (long)data->info.request_size; + break; + case CURLINFO_SSL_VERIFYRESULT: + *param_longp = data->set.ssl.certverifyresult; + break; + case CURLINFO_PROXY_SSL_VERIFYRESULT: + *param_longp = data->set.proxy_ssl.certverifyresult; + break; + case CURLINFO_REDIRECT_COUNT: + *param_longp = data->set.followlocation; + break; + case CURLINFO_HTTPAUTH_AVAIL: + lptr.to_long = param_longp; + *lptr.to_ulong = data->info.httpauthavail; + break; + case CURLINFO_PROXYAUTH_AVAIL: + lptr.to_long = param_longp; + *lptr.to_ulong = data->info.proxyauthavail; + break; + case CURLINFO_OS_ERRNO: + *param_longp = data->state.os_errno; + break; + case CURLINFO_NUM_CONNECTS: + *param_longp = data->info.numconnects; + break; + case CURLINFO_LASTSOCKET: + sockfd = Curl_getconnectinfo(data, NULL); + + /* note: this is not a good conversion for systems with 64 bit sockets and + 32 bit longs */ + if(sockfd != CURL_SOCKET_BAD) + *param_longp = (long)sockfd; + else + /* this interface is documented to return -1 in case of badness, which + may not be the same as the CURL_SOCKET_BAD value */ + *param_longp = -1; + break; + case CURLINFO_PRIMARY_PORT: + /* Return the (remote) port of the most recent (primary) connection */ + *param_longp = data->info.conn_primary_port; + break; + case CURLINFO_LOCAL_PORT: + /* Return the local port of the most recent (primary) connection */ + *param_longp = data->info.conn_local_port; + break; + case CURLINFO_CONDITION_UNMET: + /* return if the condition prevented the document to get transferred */ + *param_longp = data->info.timecond ? 1L : 0L; + break; + case CURLINFO_RTSP_CLIENT_CSEQ: + *param_longp = data->state.rtsp_next_client_CSeq; + break; + case CURLINFO_RTSP_SERVER_CSEQ: + *param_longp = data->state.rtsp_next_server_CSeq; + break; + case CURLINFO_RTSP_CSEQ_RECV: + *param_longp = data->state.rtsp_CSeq_recv; + break; + case CURLINFO_HTTP_VERSION: + switch(data->info.httpversion) { + case 10: + *param_longp = CURL_HTTP_VERSION_1_0; + break; + case 11: + *param_longp = CURL_HTTP_VERSION_1_1; + break; + case 20: + *param_longp = CURL_HTTP_VERSION_2_0; + break; + default: + *param_longp = CURL_HTTP_VERSION_NONE; + break; + } + break; + case CURLINFO_PROTOCOL: + *param_longp = data->info.conn_protocol; + break; + + default: + return CURLE_UNKNOWN_OPTION; + } + + return CURLE_OK; +} + +#define DOUBLE_SECS(x) (double)(x)/1000000 + +static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info, + curl_off_t *param_offt) +{ + switch(info) { + case CURLINFO_FILETIME_T: + *param_offt = (curl_off_t)data->info.filetime; + break; + case CURLINFO_SIZE_UPLOAD_T: + *param_offt = data->progress.uploaded; + break; + case CURLINFO_SIZE_DOWNLOAD_T: + *param_offt = data->progress.downloaded; + break; + case CURLINFO_SPEED_DOWNLOAD_T: + *param_offt = data->progress.dlspeed; + break; + case CURLINFO_SPEED_UPLOAD_T: + *param_offt = data->progress.ulspeed; + break; + case CURLINFO_CONTENT_LENGTH_DOWNLOAD_T: + *param_offt = (data->progress.flags & PGRS_DL_SIZE_KNOWN)? + data->progress.size_dl:-1; + break; + case CURLINFO_CONTENT_LENGTH_UPLOAD_T: + *param_offt = (data->progress.flags & PGRS_UL_SIZE_KNOWN)? + data->progress.size_ul:-1; + break; + case CURLINFO_TOTAL_TIME_T: + *param_offt = data->progress.timespent; + break; + case CURLINFO_NAMELOOKUP_TIME_T: + *param_offt = data->progress.t_nslookup; + break; + case CURLINFO_CONNECT_TIME_T: + *param_offt = data->progress.t_connect; + break; + case CURLINFO_APPCONNECT_TIME_T: + *param_offt = data->progress.t_appconnect; + break; + case CURLINFO_PRETRANSFER_TIME_T: + *param_offt = data->progress.t_pretransfer; + break; + case CURLINFO_STARTTRANSFER_TIME_T: + *param_offt = data->progress.t_starttransfer; + break; + case CURLINFO_REDIRECT_TIME_T: + *param_offt = data->progress.t_redirect; + break; + + default: + return CURLE_UNKNOWN_OPTION; + } + + return CURLE_OK; +} + +static CURLcode getinfo_double(struct Curl_easy *data, CURLINFO info, + double *param_doublep) +{ + switch(info) { + case CURLINFO_TOTAL_TIME: + *param_doublep = DOUBLE_SECS(data->progress.timespent); + break; + case CURLINFO_NAMELOOKUP_TIME: + *param_doublep = DOUBLE_SECS(data->progress.t_nslookup); + break; + case CURLINFO_CONNECT_TIME: + *param_doublep = DOUBLE_SECS(data->progress.t_connect); + break; + case CURLINFO_APPCONNECT_TIME: + *param_doublep = DOUBLE_SECS(data->progress.t_appconnect); + break; + case CURLINFO_PRETRANSFER_TIME: + *param_doublep = DOUBLE_SECS(data->progress.t_pretransfer); + break; + case CURLINFO_STARTTRANSFER_TIME: + *param_doublep = DOUBLE_SECS(data->progress.t_starttransfer); + break; + case CURLINFO_SIZE_UPLOAD: + *param_doublep = (double)data->progress.uploaded; + break; + case CURLINFO_SIZE_DOWNLOAD: + *param_doublep = (double)data->progress.downloaded; + break; + case CURLINFO_SPEED_DOWNLOAD: + *param_doublep = (double)data->progress.dlspeed; + break; + case CURLINFO_SPEED_UPLOAD: + *param_doublep = (double)data->progress.ulspeed; + break; + case CURLINFO_CONTENT_LENGTH_DOWNLOAD: + *param_doublep = (data->progress.flags & PGRS_DL_SIZE_KNOWN)? + (double)data->progress.size_dl:-1; + break; + case CURLINFO_CONTENT_LENGTH_UPLOAD: + *param_doublep = (data->progress.flags & PGRS_UL_SIZE_KNOWN)? + (double)data->progress.size_ul:-1; + break; + case CURLINFO_REDIRECT_TIME: + *param_doublep = DOUBLE_SECS(data->progress.t_redirect); + break; + + default: + return CURLE_UNKNOWN_OPTION; + } + + return CURLE_OK; +} + +static CURLcode getinfo_slist(struct Curl_easy *data, CURLINFO info, + struct curl_slist **param_slistp) +{ + union { + struct curl_certinfo *to_certinfo; + struct curl_slist *to_slist; + } ptr; + + switch(info) { + case CURLINFO_SSL_ENGINES: + *param_slistp = Curl_ssl_engines_list(data); + break; + case CURLINFO_COOKIELIST: + *param_slistp = Curl_cookie_list(data); + break; + case CURLINFO_CERTINFO: + /* Return the a pointer to the certinfo struct. Not really an slist + pointer but we can pretend it is here */ + ptr.to_certinfo = &data->info.certs; + *param_slistp = ptr.to_slist; + break; + case CURLINFO_TLS_SESSION: + case CURLINFO_TLS_SSL_PTR: + { + struct curl_tlssessioninfo **tsip = (struct curl_tlssessioninfo **) + param_slistp; + struct curl_tlssessioninfo *tsi = &data->tsi; +#ifdef USE_SSL + struct connectdata *conn = data->conn; +#endif + + *tsip = tsi; + tsi->backend = Curl_ssl_backend(); + tsi->internals = NULL; + +#ifdef USE_SSL + if(conn && tsi->backend != CURLSSLBACKEND_NONE) { + unsigned int i; + for(i = 0; i < (sizeof(conn->ssl) / sizeof(conn->ssl[0])); ++i) { + if(conn->ssl[i].use) { + tsi->internals = Curl_ssl->get_internals(&conn->ssl[i], info); + break; + } + } + } +#endif + } + break; + default: + return CURLE_UNKNOWN_OPTION; + } + + return CURLE_OK; +} + +static CURLcode getinfo_socket(struct Curl_easy *data, CURLINFO info, + curl_socket_t *param_socketp) +{ + switch(info) { + case CURLINFO_ACTIVESOCKET: + *param_socketp = Curl_getconnectinfo(data, NULL); + break; + default: + return CURLE_UNKNOWN_OPTION; + } + + return CURLE_OK; +} + +CURLcode Curl_getinfo(struct Curl_easy *data, CURLINFO info, ...) +{ + va_list arg; + long *param_longp = NULL; + double *param_doublep = NULL; + curl_off_t *param_offt = NULL; + const char **param_charp = NULL; + struct curl_slist **param_slistp = NULL; + curl_socket_t *param_socketp = NULL; + int type; + CURLcode result = CURLE_UNKNOWN_OPTION; + + if(!data) + return result; + + va_start(arg, info); + + type = CURLINFO_TYPEMASK & (int)info; + switch(type) { + case CURLINFO_STRING: + param_charp = va_arg(arg, const char **); + if(param_charp) + result = getinfo_char(data, info, param_charp); + break; + case CURLINFO_LONG: + param_longp = va_arg(arg, long *); + if(param_longp) + result = getinfo_long(data, info, param_longp); + break; + case CURLINFO_DOUBLE: + param_doublep = va_arg(arg, double *); + if(param_doublep) + result = getinfo_double(data, info, param_doublep); + break; + case CURLINFO_OFF_T: + param_offt = va_arg(arg, curl_off_t *); + if(param_offt) + result = getinfo_offt(data, info, param_offt); + break; + case CURLINFO_SLIST: + param_slistp = va_arg(arg, struct curl_slist **); + if(param_slistp) + result = getinfo_slist(data, info, param_slistp); + break; + case CURLINFO_SOCKET: + param_socketp = va_arg(arg, curl_socket_t *); + if(param_socketp) + result = getinfo_socket(data, info, param_socketp); + break; + default: + break; + } + + va_end(arg); + + return result; +} diff --git a/dependencies/cmcurl/lib/getinfo.h b/dependencies/cmcurl/lib/getinfo.h new file mode 100644 index 0000000..aecf717 --- /dev/null +++ b/dependencies/cmcurl/lib/getinfo.h @@ -0,0 +1,27 @@ +#ifndef HEADER_CURL_GETINFO_H +#define HEADER_CURL_GETINFO_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +CURLcode Curl_getinfo(struct Curl_easy *data, CURLINFO info, ...); +CURLcode Curl_initinfo(struct Curl_easy *data); + +#endif /* HEADER_CURL_GETINFO_H */ diff --git a/dependencies/cmcurl/lib/gopher.c b/dependencies/cmcurl/lib/gopher.c new file mode 100644 index 0000000..b296c62 --- /dev/null +++ b/dependencies/cmcurl/lib/gopher.c @@ -0,0 +1,174 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_GOPHER + +#include "urldata.h" +#include +#include "transfer.h" +#include "sendf.h" +#include "progress.h" +#include "gopher.h" +#include "select.h" +#include "strdup.h" +#include "url.h" +#include "escape.h" +#include "warnless.h" +#include "curl_printf.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * Forward declarations. + */ + +static CURLcode gopher_do(struct connectdata *conn, bool *done); + +/* + * Gopher protocol handler. + * This is also a nice simple template to build off for simple + * connect-command-download protocols. + */ + +const struct Curl_handler Curl_handler_gopher = { + "GOPHER", /* scheme */ + ZERO_NULL, /* setup_connection */ + gopher_do, /* do_it */ + ZERO_NULL, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_GOPHER, /* defport */ + CURLPROTO_GOPHER, /* protocol */ + PROTOPT_NONE /* flags */ +}; + +static CURLcode gopher_do(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; + char *gopherpath; + char *path = data->state.up.path; + char *query = data->state.up.query; + char *sel = NULL; + char *sel_org = NULL; + ssize_t amount, k; + size_t len; + + *done = TRUE; /* unconditionally */ + + /* path is guaranteed non-NULL */ + DEBUGASSERT(path); + + if(query) + gopherpath = aprintf("%s?%s", path, query); + else + gopherpath = strdup(path); + + if(!gopherpath) + return CURLE_OUT_OF_MEMORY; + + /* Create selector. Degenerate cases: / and /1 => convert to "" */ + if(strlen(gopherpath) <= 2) { + sel = (char *)""; + len = strlen(sel); + free(gopherpath); + } + else { + char *newp; + + /* Otherwise, drop / and the first character (i.e., item type) ... */ + newp = gopherpath; + newp += 2; + + /* ... and finally unescape */ + result = Curl_urldecode(data, newp, 0, &sel, &len, FALSE); + free(gopherpath); + if(result) + return result; + sel_org = sel; + } + + /* We use Curl_write instead of Curl_sendf to make sure the entire buffer is + sent, which could be sizeable with long selectors. */ + k = curlx_uztosz(len); + + for(;;) { + result = Curl_write(conn, sockfd, sel, k, &amount); + if(!result) { /* Which may not have written it all! */ + result = Curl_client_write(conn, CLIENTWRITE_HEADER, sel, amount); + if(result) + break; + + k -= amount; + sel += amount; + if(k < 1) + break; /* but it did write it all */ + } + else + break; + + /* Don't busyloop. The entire loop thing is a work-around as it causes a + BLOCKING behavior which is a NO-NO. This function should rather be + split up in a do and a doing piece where the pieces that aren't + possible to send now will be sent in the doing function repeatedly + until the entire request is sent. + + Wait a while for the socket to be writable. Note that this doesn't + acknowledge the timeout. + */ + if(SOCKET_WRITABLE(sockfd, 100) < 0) { + result = CURLE_SEND_ERROR; + break; + } + } + + free(sel_org); + + if(!result) + /* We can use Curl_sendf to send the terminal \r\n relatively safely and + save allocing another string/doing another _write loop. */ + result = Curl_sendf(sockfd, conn, "\r\n"); + if(result) { + failf(data, "Failed sending Gopher request"); + return result; + } + result = Curl_client_write(conn, CLIENTWRITE_HEADER, (char *)"\r\n", 2); + if(result) + return result; + + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); + return CURLE_OK; +} +#endif /*CURL_DISABLE_GOPHER*/ diff --git a/dependencies/cmcurl/lib/gopher.h b/dependencies/cmcurl/lib/gopher.h new file mode 100644 index 0000000..501c990 --- /dev/null +++ b/dependencies/cmcurl/lib/gopher.h @@ -0,0 +1,29 @@ +#ifndef HEADER_CURL_GOPHER_H +#define HEADER_CURL_GOPHER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifndef CURL_DISABLE_GOPHER +extern const struct Curl_handler Curl_handler_gopher; +#endif + +#endif /* HEADER_CURL_GOPHER_H */ diff --git a/dependencies/cmcurl/lib/hash.c b/dependencies/cmcurl/lib/hash.c new file mode 100644 index 0000000..421d68f --- /dev/null +++ b/dependencies/cmcurl/lib/hash.c @@ -0,0 +1,351 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "hash.h" +#include "llist.h" +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +static void +hash_element_dtor(void *user, void *element) +{ + struct curl_hash *h = (struct curl_hash *) user; + struct curl_hash_element *e = (struct curl_hash_element *) element; + + if(e->ptr) { + h->dtor(e->ptr); + e->ptr = NULL; + } + + e->key_len = 0; + + free(e); +} + +/* Initializes a hash structure. + * Return 1 on error, 0 is fine. + * + * @unittest: 1602 + * @unittest: 1603 + */ +int +Curl_hash_init(struct curl_hash *h, + int slots, + hash_function hfunc, + comp_function comparator, + curl_hash_dtor dtor) +{ + if(!slots || !hfunc || !comparator ||!dtor) { + return 1; /* failure */ + } + + h->hash_func = hfunc; + h->comp_func = comparator; + h->dtor = dtor; + h->size = 0; + h->slots = slots; + + h->table = malloc(slots * sizeof(struct curl_llist)); + if(h->table) { + int i; + for(i = 0; i < slots; ++i) + Curl_llist_init(&h->table[i], (curl_llist_dtor) hash_element_dtor); + return 0; /* fine */ + } + h->slots = 0; + return 1; /* failure */ +} + +static struct curl_hash_element * +mk_hash_element(const void *key, size_t key_len, const void *p) +{ + /* allocate the struct plus memory after it to store the key */ + struct curl_hash_element *he = malloc(sizeof(struct curl_hash_element) + + key_len); + if(he) { + /* copy the key */ + memcpy(he->key, key, key_len); + he->key_len = key_len; + he->ptr = (void *) p; + } + return he; +} + +#define FETCH_LIST(x,y,z) &x->table[x->hash_func(y, z, x->slots)] + +/* Insert the data in the hash. If there already was a match in the hash, + * that data is replaced. + * + * @unittest: 1305 + * @unittest: 1602 + * @unittest: 1603 + */ +void * +Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p) +{ + struct curl_hash_element *he; + struct curl_llist_element *le; + struct curl_llist *l = FETCH_LIST(h, key, key_len); + + for(le = l->head; le; le = le->next) { + he = (struct curl_hash_element *) le->ptr; + if(h->comp_func(he->key, he->key_len, key, key_len)) { + Curl_llist_remove(l, le, (void *)h); + --h->size; + break; + } + } + + he = mk_hash_element(key, key_len, p); + if(he) { + Curl_llist_insert_next(l, l->tail, he, &he->list); + ++h->size; + return p; /* return the new entry */ + } + + return NULL; /* failure */ +} + +/* Remove the identified hash entry. + * Returns non-zero on failure. + * + * @unittest: 1603 + */ +int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len) +{ + struct curl_llist_element *le; + struct curl_llist *l = FETCH_LIST(h, key, key_len); + + for(le = l->head; le; le = le->next) { + struct curl_hash_element *he = le->ptr; + if(h->comp_func(he->key, he->key_len, key, key_len)) { + Curl_llist_remove(l, le, (void *) h); + --h->size; + return 0; + } + } + return 1; +} + +/* Retrieves a hash element. + * + * @unittest: 1603 + */ +void * +Curl_hash_pick(struct curl_hash *h, void *key, size_t key_len) +{ + struct curl_llist_element *le; + struct curl_llist *l; + + if(h) { + l = FETCH_LIST(h, key, key_len); + for(le = l->head; le; le = le->next) { + struct curl_hash_element *he = le->ptr; + if(h->comp_func(he->key, he->key_len, key, key_len)) { + return he->ptr; + } + } + } + + return NULL; +} + +#if defined(DEBUGBUILD) && defined(AGGRESIVE_TEST) +void +Curl_hash_apply(curl_hash *h, void *user, + void (*cb)(void *user, void *ptr)) +{ + struct curl_llist_element *le; + int i; + + for(i = 0; i < h->slots; ++i) { + for(le = (h->table[i])->head; + le; + le = le->next) { + curl_hash_element *el = le->ptr; + cb(user, el->ptr); + } + } +} +#endif + +/* Destroys all the entries in the given hash and resets its attributes, + * prepping the given hash for [static|dynamic] deallocation. + * + * @unittest: 1305 + * @unittest: 1602 + * @unittest: 1603 + */ +void +Curl_hash_destroy(struct curl_hash *h) +{ + int i; + + for(i = 0; i < h->slots; ++i) { + Curl_llist_destroy(&h->table[i], (void *) h); + } + + Curl_safefree(h->table); + h->size = 0; + h->slots = 0; +} + +/* Removes all the entries in the given hash. + * + * @unittest: 1602 + */ +void +Curl_hash_clean(struct curl_hash *h) +{ + Curl_hash_clean_with_criterium(h, NULL, NULL); +} + +/* Cleans all entries that pass the comp function criteria. */ +void +Curl_hash_clean_with_criterium(struct curl_hash *h, void *user, + int (*comp)(void *, void *)) +{ + struct curl_llist_element *le; + struct curl_llist_element *lnext; + struct curl_llist *list; + int i; + + if(!h) + return; + + for(i = 0; i < h->slots; ++i) { + list = &h->table[i]; + le = list->head; /* get first list entry */ + while(le) { + struct curl_hash_element *he = le->ptr; + lnext = le->next; + /* ask the callback function if we shall remove this entry or not */ + if(comp == NULL || comp(user, he->ptr)) { + Curl_llist_remove(list, le, (void *) h); + --h->size; /* one less entry in the hash now */ + } + le = lnext; + } + } +} + +size_t Curl_hash_str(void *key, size_t key_length, size_t slots_num) +{ + const char *key_str = (const char *) key; + const char *end = key_str + key_length; + size_t h = 5381; + + while(key_str < end) { + h += h << 5; + h ^= *key_str++; + } + + return (h % slots_num); +} + +size_t Curl_str_key_compare(void *k1, size_t key1_len, + void *k2, size_t key2_len) +{ + if((key1_len == key2_len) && !memcmp(k1, k2, key1_len)) + return 1; + + return 0; +} + +void Curl_hash_start_iterate(struct curl_hash *hash, + struct curl_hash_iterator *iter) +{ + iter->hash = hash; + iter->slot_index = 0; + iter->current_element = NULL; +} + +struct curl_hash_element * +Curl_hash_next_element(struct curl_hash_iterator *iter) +{ + struct curl_hash *h = iter->hash; + + /* Get the next element in the current list, if any */ + if(iter->current_element) + iter->current_element = iter->current_element->next; + + /* If we have reached the end of the list, find the next one */ + if(!iter->current_element) { + int i; + for(i = iter->slot_index; i < h->slots; i++) { + if(h->table[i].head) { + iter->current_element = h->table[i].head; + iter->slot_index = i + 1; + break; + } + } + } + + if(iter->current_element) { + struct curl_hash_element *he = iter->current_element->ptr; + return he; + } + iter->current_element = NULL; + return NULL; +} + +#if 0 /* useful function for debugging hashes and their contents */ +void Curl_hash_print(struct curl_hash *h, + void (*func)(void *)) +{ + struct curl_hash_iterator iter; + struct curl_hash_element *he; + int last_index = -1; + + if(!h) + return; + + fprintf(stderr, "=Hash dump=\n"); + + Curl_hash_start_iterate(h, &iter); + + he = Curl_hash_next_element(&iter); + while(he) { + if(iter.slot_index != last_index) { + fprintf(stderr, "index %d:", iter.slot_index); + if(last_index >= 0) { + fprintf(stderr, "\n"); + } + last_index = iter.slot_index; + } + + if(func) + func(he->ptr); + else + fprintf(stderr, " [%p]", (void *)he->ptr); + + he = Curl_hash_next_element(&iter); + } + fprintf(stderr, "\n"); +} +#endif diff --git a/dependencies/cmcurl/lib/hash.h b/dependencies/cmcurl/lib/hash.h new file mode 100644 index 0000000..90a25d1 --- /dev/null +++ b/dependencies/cmcurl/lib/hash.h @@ -0,0 +1,100 @@ +#ifndef HEADER_CURL_HASH_H +#define HEADER_CURL_HASH_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "llist.h" + +/* Hash function prototype */ +typedef size_t (*hash_function) (void *key, + size_t key_length, + size_t slots_num); + +/* + Comparator function prototype. Compares two keys. +*/ +typedef size_t (*comp_function) (void *key1, + size_t key1_len, + void *key2, + size_t key2_len); + +typedef void (*curl_hash_dtor)(void *); + +struct curl_hash { + struct curl_llist *table; + + /* Hash function to be used for this hash table */ + hash_function hash_func; + + /* Comparator function to compare keys */ + comp_function comp_func; + curl_hash_dtor dtor; + int slots; + size_t size; +}; + +struct curl_hash_element { + struct curl_llist_element list; + void *ptr; + size_t key_len; + char key[1]; /* allocated memory following the struct */ +}; + +struct curl_hash_iterator { + struct curl_hash *hash; + int slot_index; + struct curl_llist_element *current_element; +}; + +int Curl_hash_init(struct curl_hash *h, + int slots, + hash_function hfunc, + comp_function comparator, + curl_hash_dtor dtor); + +void *Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p); +int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len); +void *Curl_hash_pick(struct curl_hash *, void *key, size_t key_len); +void Curl_hash_apply(struct curl_hash *h, void *user, + void (*cb)(void *user, void *ptr)); +int Curl_hash_count(struct curl_hash *h); +void Curl_hash_destroy(struct curl_hash *h); +void Curl_hash_clean(struct curl_hash *h); +void Curl_hash_clean_with_criterium(struct curl_hash *h, void *user, + int (*comp)(void *, void *)); +size_t Curl_hash_str(void *key, size_t key_length, size_t slots_num); +size_t Curl_str_key_compare(void *k1, size_t key1_len, void *k2, + size_t key2_len); +void Curl_hash_start_iterate(struct curl_hash *hash, + struct curl_hash_iterator *iter); +struct curl_hash_element * +Curl_hash_next_element(struct curl_hash_iterator *iter); + +void Curl_hash_print(struct curl_hash *h, + void (*func)(void *)); + + +#endif /* HEADER_CURL_HASH_H */ diff --git a/dependencies/cmcurl/lib/hmac.c b/dependencies/cmcurl/lib/hmac.c new file mode 100644 index 0000000..bf49ebe --- /dev/null +++ b/dependencies/cmcurl/lib/hmac.c @@ -0,0 +1,132 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC2104 Keyed-Hashing for Message Authentication + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_CRYPTO_AUTH + +#include + +#include "curl_hmac.h" +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * Generic HMAC algorithm. + * + * This module computes HMAC digests based on any hash function. Parameters + * and computing procedures are set-up dynamically at HMAC computation + * context initialisation. + */ + +static const unsigned char hmac_ipad = 0x36; +static const unsigned char hmac_opad = 0x5C; + + + +HMAC_context * +Curl_HMAC_init(const HMAC_params * hashparams, + const unsigned char *key, + unsigned int keylen) +{ + size_t i; + HMAC_context *ctxt; + unsigned char *hkey; + unsigned char b; + + /* Create HMAC context. */ + i = sizeof(*ctxt) + 2 * hashparams->hmac_ctxtsize + + hashparams->hmac_resultlen; + ctxt = malloc(i); + + if(!ctxt) + return ctxt; + + ctxt->hmac_hash = hashparams; + ctxt->hmac_hashctxt1 = (void *) (ctxt + 1); + ctxt->hmac_hashctxt2 = (void *) ((char *) ctxt->hmac_hashctxt1 + + hashparams->hmac_ctxtsize); + + /* If the key is too long, replace it by its hash digest. */ + if(keylen > hashparams->hmac_maxkeylen) { + (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt1); + (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, key, keylen); + hkey = (unsigned char *) ctxt->hmac_hashctxt2 + hashparams->hmac_ctxtsize; + (*hashparams->hmac_hfinal)(hkey, ctxt->hmac_hashctxt1); + key = hkey; + keylen = hashparams->hmac_resultlen; + } + + /* Prime the two hash contexts with the modified key. */ + (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt1); + (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt2); + + for(i = 0; i < keylen; i++) { + b = (unsigned char)(*key ^ hmac_ipad); + (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, &b, 1); + b = (unsigned char)(*key++ ^ hmac_opad); + (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, &b, 1); + } + + for(; i < hashparams->hmac_maxkeylen; i++) { + (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, &hmac_ipad, 1); + (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, &hmac_opad, 1); + } + + /* Done, return pointer to HMAC context. */ + return ctxt; +} + +int Curl_HMAC_update(HMAC_context * ctxt, + const unsigned char *data, + unsigned int len) +{ + /* Update first hash calculation. */ + (*ctxt->hmac_hash->hmac_hupdate)(ctxt->hmac_hashctxt1, data, len); + return 0; +} + + +int Curl_HMAC_final(HMAC_context *ctxt, unsigned char *result) +{ + const HMAC_params * hashparams = ctxt->hmac_hash; + + /* Do not get result if called with a null parameter: only release + storage. */ + + if(!result) + result = (unsigned char *) ctxt->hmac_hashctxt2 + + ctxt->hmac_hash->hmac_ctxtsize; + + (*hashparams->hmac_hfinal)(result, ctxt->hmac_hashctxt1); + (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, + result, hashparams->hmac_resultlen); + (*hashparams->hmac_hfinal)(result, ctxt->hmac_hashctxt2); + free((char *) ctxt); + return 0; +} + +#endif /* CURL_DISABLE_CRYPTO_AUTH */ diff --git a/dependencies/cmcurl/lib/hostasyn.c b/dependencies/cmcurl/lib/hostasyn.c new file mode 100644 index 0000000..99d872b --- /dev/null +++ b/dependencies/cmcurl/lib/hostasyn.c @@ -0,0 +1,128 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +/*********************************************************************** + * Only for builds using asynchronous name resolves + **********************************************************************/ +#ifdef CURLRES_ASYNCH + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#ifdef HAVE_PROCESS_H +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "hash.h" +#include "share.h" +#include "strerror.h" +#include "url.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * Curl_addrinfo_callback() gets called by ares, gethostbyname_thread() + * or getaddrinfo_thread() when we got the name resolved (or not!). + * + * If the status argument is CURL_ASYNC_SUCCESS, this function takes + * ownership of the Curl_addrinfo passed, storing the resolved data + * in the DNS cache. + * + * The storage operation locks and unlocks the DNS cache. + */ +CURLcode Curl_addrinfo_callback(struct connectdata *conn, + int status, + struct Curl_addrinfo *ai) +{ + struct Curl_dns_entry *dns = NULL; + CURLcode result = CURLE_OK; + + conn->async.status = status; + + if(CURL_ASYNC_SUCCESS == status) { + if(ai) { + struct Curl_easy *data = conn->data; + + if(data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + dns = Curl_cache_addr(data, ai, + conn->async.hostname, + conn->async.port); + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + + if(!dns) { + /* failed to store, cleanup and return error */ + Curl_freeaddrinfo(ai); + result = CURLE_OUT_OF_MEMORY; + } + } + else { + result = CURLE_OUT_OF_MEMORY; + } + } + + conn->async.dns = dns; + + /* Set async.done TRUE last in this function since it may be used multi- + threaded and once this is TRUE the other thread may read fields from the + async struct */ + conn->async.done = TRUE; + + /* IPv4: The input hostent struct will be freed by ares when we return from + this function */ + return result; +} + +/* + * Curl_getaddrinfo() is the generic low-level name resolve API within this + * source file. There are several versions of this function - for different + * name resolve layers (selected at build-time). They all take this same set + * of arguments + */ +Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, + const char *hostname, + int port, + int *waitp) +{ + return Curl_resolver_getaddrinfo(conn, hostname, port, waitp); +} + +#endif /* CURLRES_ASYNCH */ diff --git a/dependencies/cmcurl/lib/hostcheck.c b/dependencies/cmcurl/lib/hostcheck.c new file mode 100644 index 0000000..115d24b --- /dev/null +++ b/dependencies/cmcurl/lib/hostcheck.c @@ -0,0 +1,150 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_OPENSSL) \ + || defined(USE_GSKIT) \ + || defined(USE_SCHANNEL) +/* these backends use functions from this file */ + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_IN6_H +#include +#endif + +#include "hostcheck.h" +#include "strcase.h" +#include "inet_pton.h" + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * Match a hostname against a wildcard pattern. + * E.g. + * "foo.host.com" matches "*.host.com". + * + * We use the matching rule described in RFC6125, section 6.4.3. + * https://tools.ietf.org/html/rfc6125#section-6.4.3 + * + * In addition: ignore trailing dots in the host names and wildcards, so that + * the names are used normalized. This is what the browsers do. + * + * Do not allow wildcard matching on IP numbers. There are apparently + * certificates being used with an IP address in the CN field, thus making no + * apparent distinction between a name and an IP. We need to detect the use of + * an IP address and not wildcard match on such names. + * + * NOTE: hostmatch() gets called with copied buffers so that it can modify the + * contents at will. + */ + +static int hostmatch(char *hostname, char *pattern) +{ + const char *pattern_label_end, *pattern_wildcard, *hostname_label_end; + int wildcard_enabled; + size_t prefixlen, suffixlen; + struct in_addr ignored; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 si6; +#endif + + /* normalize pattern and hostname by stripping off trailing dots */ + size_t len = strlen(hostname); + if(hostname[len-1]=='.') + hostname[len-1] = 0; + len = strlen(pattern); + if(pattern[len-1]=='.') + pattern[len-1] = 0; + + pattern_wildcard = strchr(pattern, '*'); + if(pattern_wildcard == NULL) + return strcasecompare(pattern, hostname) ? + CURL_HOST_MATCH : CURL_HOST_NOMATCH; + + /* detect IP address as hostname and fail the match if so */ + if(Curl_inet_pton(AF_INET, hostname, &ignored) > 0) + return CURL_HOST_NOMATCH; +#ifdef ENABLE_IPV6 + if(Curl_inet_pton(AF_INET6, hostname, &si6.sin6_addr) > 0) + return CURL_HOST_NOMATCH; +#endif + + /* We require at least 2 dots in pattern to avoid too wide wildcard + match. */ + wildcard_enabled = 1; + pattern_label_end = strchr(pattern, '.'); + if(pattern_label_end == NULL || strchr(pattern_label_end + 1, '.') == NULL || + pattern_wildcard > pattern_label_end || + strncasecompare(pattern, "xn--", 4)) { + wildcard_enabled = 0; + } + if(!wildcard_enabled) + return strcasecompare(pattern, hostname) ? + CURL_HOST_MATCH : CURL_HOST_NOMATCH; + + hostname_label_end = strchr(hostname, '.'); + if(hostname_label_end == NULL || + !strcasecompare(pattern_label_end, hostname_label_end)) + return CURL_HOST_NOMATCH; + + /* The wildcard must match at least one character, so the left-most + label of the hostname is at least as large as the left-most label + of the pattern. */ + if(hostname_label_end - hostname < pattern_label_end - pattern) + return CURL_HOST_NOMATCH; + + prefixlen = pattern_wildcard - pattern; + suffixlen = pattern_label_end - (pattern_wildcard + 1); + return strncasecompare(pattern, hostname, prefixlen) && + strncasecompare(pattern_wildcard + 1, hostname_label_end - suffixlen, + suffixlen) ? + CURL_HOST_MATCH : CURL_HOST_NOMATCH; +} + +int Curl_cert_hostcheck(const char *match_pattern, const char *hostname) +{ + int res = 0; + if(!match_pattern || !*match_pattern || + !hostname || !*hostname) /* sanity check */ + ; + else { + char *matchp = strdup(match_pattern); + if(matchp) { + char *hostp = strdup(hostname); + if(hostp) { + if(hostmatch(hostp, matchp) == CURL_HOST_MATCH) + res = 1; + free(hostp); + } + free(matchp); + } + } + + return res; +} + +#endif /* OPENSSL, GSKIT or schannel+wince */ diff --git a/dependencies/cmcurl/lib/hostcheck.h b/dependencies/cmcurl/lib/hostcheck.h new file mode 100644 index 0000000..f562df9 --- /dev/null +++ b/dependencies/cmcurl/lib/hostcheck.h @@ -0,0 +1,31 @@ +#ifndef HEADER_CURL_HOSTCHECK_H +#define HEADER_CURL_HOSTCHECK_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +#define CURL_HOST_NOMATCH 0 +#define CURL_HOST_MATCH 1 +int Curl_cert_hostcheck(const char *match_pattern, const char *hostname); + +#endif /* HEADER_CURL_HOSTCHECK_H */ diff --git a/dependencies/cmcurl/lib/hostip.c b/dependencies/cmcurl/lib/hostip.c new file mode 100644 index 0000000..cf33ed8 --- /dev/null +++ b/dependencies/cmcurl/lib/hostip.c @@ -0,0 +1,1070 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_IN6_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#ifdef HAVE_SETJMP_H +#include +#endif +#ifdef HAVE_SIGNAL_H +#include +#endif + +#ifdef HAVE_PROCESS_H +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "hash.h" +#include "rand.h" +#include "share.h" +#include "strerror.h" +#include "url.h" +#include "inet_ntop.h" +#include "multiif.h" +#include "doh.h" +#include "warnless.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#if defined(CURLRES_SYNCH) && \ + defined(HAVE_ALARM) && defined(SIGALRM) && defined(HAVE_SIGSETJMP) +/* alarm-based timeouts can only be used with all the dependencies satisfied */ +#define USE_ALARM_TIMEOUT +#endif + +#define MAX_HOSTCACHE_LEN (255 + 7) /* max FQDN + colon + port number + zero */ + +/* + * hostip.c explained + * ================== + * + * The main COMPILE-TIME DEFINES to keep in mind when reading the host*.c + * source file are these: + * + * CURLRES_IPV6 - this host has getaddrinfo() and family, and thus we use + * that. The host may not be able to resolve IPv6, but we don't really have to + * take that into account. Hosts that aren't IPv6-enabled have CURLRES_IPV4 + * defined. + * + * CURLRES_ARES - is defined if libcurl is built to use c-ares for + * asynchronous name resolves. This can be Windows or *nix. + * + * CURLRES_THREADED - is defined if libcurl is built to run under (native) + * Windows, and then the name resolve will be done in a new thread, and the + * supported API will be the same as for ares-builds. + * + * If any of the two previous are defined, CURLRES_ASYNCH is defined too. If + * libcurl is not built to use an asynchronous resolver, CURLRES_SYNCH is + * defined. + * + * The host*.c sources files are split up like this: + * + * hostip.c - method-independent resolver functions and utility functions + * hostasyn.c - functions for asynchronous name resolves + * hostsyn.c - functions for synchronous name resolves + * hostip4.c - IPv4 specific functions + * hostip6.c - IPv6 specific functions + * + * The two asynchronous name resolver backends are implemented in: + * asyn-ares.c - functions for ares-using name resolves + * asyn-thread.c - functions for threaded name resolves + + * The hostip.h is the united header file for all this. It defines the + * CURLRES_* defines based on the config*.h and curl_setup.h defines. + */ + +static void freednsentry(void *freethis); + +/* + * Return # of addresses in a Curl_addrinfo struct + */ +int Curl_num_addresses(const Curl_addrinfo *addr) +{ + int i = 0; + while(addr) { + addr = addr->ai_next; + i++; + } + return i; +} + +/* + * Curl_printable_address() returns a printable version of the 1st address + * given in the 'ai' argument. The result will be stored in the buf that is + * bufsize bytes big. + * + * If the conversion fails, it returns NULL. + */ +const char * +Curl_printable_address(const Curl_addrinfo *ai, char *buf, size_t bufsize) +{ + const struct sockaddr_in *sa4; + const struct in_addr *ipaddr4; +#ifdef ENABLE_IPV6 + const struct sockaddr_in6 *sa6; + const struct in6_addr *ipaddr6; +#endif + + switch(ai->ai_family) { + case AF_INET: + sa4 = (const void *)ai->ai_addr; + ipaddr4 = &sa4->sin_addr; + return Curl_inet_ntop(ai->ai_family, (const void *)ipaddr4, buf, + bufsize); +#ifdef ENABLE_IPV6 + case AF_INET6: + sa6 = (const void *)ai->ai_addr; + ipaddr6 = &sa6->sin6_addr; + return Curl_inet_ntop(ai->ai_family, (const void *)ipaddr6, buf, + bufsize); +#endif + default: + break; + } + return NULL; +} + +/* + * Create a hostcache id string for the provided host + port, to be used by + * the DNS caching. Without alloc. + */ +static void +create_hostcache_id(const char *name, int port, char *ptr, size_t buflen) +{ + size_t len = strlen(name); + if(len > (buflen - 7)) + len = buflen - 7; + /* store and lower case the name */ + while(len--) + *ptr++ = (char)TOLOWER(*name++); + msnprintf(ptr, 7, ":%u", port); +} + +struct hostcache_prune_data { + long cache_timeout; + time_t now; +}; + +/* + * This function is set as a callback to be called for every entry in the DNS + * cache when we want to prune old unused entries. + * + * Returning non-zero means remove the entry, return 0 to keep it in the + * cache. + */ +static int +hostcache_timestamp_remove(void *datap, void *hc) +{ + struct hostcache_prune_data *data = + (struct hostcache_prune_data *) datap; + struct Curl_dns_entry *c = (struct Curl_dns_entry *) hc; + + return (0 != c->timestamp) + && (data->now - c->timestamp >= data->cache_timeout); +} + +/* + * Prune the DNS cache. This assumes that a lock has already been taken. + */ +static void +hostcache_prune(struct curl_hash *hostcache, long cache_timeout, time_t now) +{ + struct hostcache_prune_data user; + + user.cache_timeout = cache_timeout; + user.now = now; + + Curl_hash_clean_with_criterium(hostcache, + (void *) &user, + hostcache_timestamp_remove); +} + +/* + * Library-wide function for pruning the DNS cache. This function takes and + * returns the appropriate locks. + */ +void Curl_hostcache_prune(struct Curl_easy *data) +{ + time_t now; + + if((data->set.dns_cache_timeout == -1) || !data->dns.hostcache) + /* cache forever means never prune, and NULL hostcache means + we can't do it */ + return; + + if(data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + time(&now); + + /* Remove outdated and unused entries from the hostcache */ + hostcache_prune(data->dns.hostcache, + data->set.dns_cache_timeout, + now); + + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); +} + +#ifdef HAVE_SIGSETJMP +/* Beware this is a global and unique instance. This is used to store the + return address that we can jump back to from inside a signal handler. This + is not thread-safe stuff. */ +sigjmp_buf curl_jmpenv; +#endif + +/* lookup address, returns entry if found and not stale */ +static struct Curl_dns_entry * +fetch_addr(struct connectdata *conn, + const char *hostname, + int port) +{ + struct Curl_dns_entry *dns = NULL; + size_t entry_len; + struct Curl_easy *data = conn->data; + char entry_id[MAX_HOSTCACHE_LEN]; + + /* Create an entry id, based upon the hostname and port */ + create_hostcache_id(hostname, port, entry_id, sizeof(entry_id)); + entry_len = strlen(entry_id); + + /* See if its already in our dns cache */ + dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1); + + /* No entry found in cache, check if we might have a wildcard entry */ + if(!dns && data->change.wildcard_resolve) { + create_hostcache_id("*", port, entry_id, sizeof(entry_id)); + entry_len = strlen(entry_id); + + /* See if it's already in our dns cache */ + dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1); + } + + if(dns && (data->set.dns_cache_timeout != -1)) { + /* See whether the returned entry is stale. Done before we release lock */ + struct hostcache_prune_data user; + + time(&user.now); + user.cache_timeout = data->set.dns_cache_timeout; + + if(hostcache_timestamp_remove(&user, dns)) { + infof(data, "Hostname in DNS cache was stale, zapped\n"); + dns = NULL; /* the memory deallocation is being handled by the hash */ + Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1); + } + } + + return dns; +} + +/* + * Curl_fetch_addr() fetches a 'Curl_dns_entry' already in the DNS cache. + * + * Curl_resolv() checks initially and multi_runsingle() checks each time + * it discovers the handle in the state WAITRESOLVE whether the hostname + * has already been resolved and the address has already been stored in + * the DNS cache. This short circuits waiting for a lot of pending + * lookups for the same hostname requested by different handles. + * + * Returns the Curl_dns_entry entry pointer or NULL if not in the cache. + * + * The returned data *MUST* be "unlocked" with Curl_resolv_unlock() after + * use, or we'll leak memory! + */ +struct Curl_dns_entry * +Curl_fetch_addr(struct connectdata *conn, + const char *hostname, + int port) +{ + struct Curl_easy *data = conn->data; + struct Curl_dns_entry *dns = NULL; + + if(data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + dns = fetch_addr(conn, hostname, port); + + if(dns) + dns->inuse++; /* we use it! */ + + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + + return dns; +} + +#ifndef CURL_DISABLE_SHUFFLE_DNS +UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data, + Curl_addrinfo **addr); +/* + * Curl_shuffle_addr() shuffles the order of addresses in a 'Curl_addrinfo' + * struct by re-linking its linked list. + * + * The addr argument should be the address of a pointer to the head node of a + * `Curl_addrinfo` list and it will be modified to point to the new head after + * shuffling. + * + * Not declared static only to make it easy to use in a unit test! + * + * @unittest: 1608 + */ +UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data, + Curl_addrinfo **addr) +{ + CURLcode result = CURLE_OK; + const int num_addrs = Curl_num_addresses(*addr); + + if(num_addrs > 1) { + Curl_addrinfo **nodes; + infof(data, "Shuffling %i addresses", num_addrs); + + nodes = malloc(num_addrs*sizeof(*nodes)); + if(nodes) { + int i; + unsigned int *rnd; + const size_t rnd_size = num_addrs * sizeof(*rnd); + + /* build a plain array of Curl_addrinfo pointers */ + nodes[0] = *addr; + for(i = 1; i < num_addrs; i++) { + nodes[i] = nodes[i-1]->ai_next; + } + + rnd = malloc(rnd_size); + if(rnd) { + /* Fisher-Yates shuffle */ + if(Curl_rand(data, (unsigned char *)rnd, rnd_size) == CURLE_OK) { + Curl_addrinfo *swap_tmp; + for(i = num_addrs - 1; i > 0; i--) { + swap_tmp = nodes[rnd[i] % (i + 1)]; + nodes[rnd[i] % (i + 1)] = nodes[i]; + nodes[i] = swap_tmp; + } + + /* relink list in the new order */ + for(i = 1; i < num_addrs; i++) { + nodes[i-1]->ai_next = nodes[i]; + } + + nodes[num_addrs-1]->ai_next = NULL; + *addr = nodes[0]; + } + free(rnd); + } + else + result = CURLE_OUT_OF_MEMORY; + free(nodes); + } + else + result = CURLE_OUT_OF_MEMORY; + } + return result; +} +#endif + +/* + * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache. + * + * When calling Curl_resolv() has resulted in a response with a returned + * address, we call this function to store the information in the dns + * cache etc + * + * Returns the Curl_dns_entry entry pointer or NULL if the storage failed. + */ +struct Curl_dns_entry * +Curl_cache_addr(struct Curl_easy *data, + Curl_addrinfo *addr, + const char *hostname, + int port) +{ + char entry_id[MAX_HOSTCACHE_LEN]; + size_t entry_len; + struct Curl_dns_entry *dns; + struct Curl_dns_entry *dns2; + +#ifndef CURL_DISABLE_SHUFFLE_DNS + /* shuffle addresses if requested */ + if(data->set.dns_shuffle_addresses) { + CURLcode result = Curl_shuffle_addr(data, &addr); + if(result) + return NULL; + } +#endif + + /* Create a new cache entry */ + dns = calloc(1, sizeof(struct Curl_dns_entry)); + if(!dns) { + return NULL; + } + + /* Create an entry id, based upon the hostname and port */ + create_hostcache_id(hostname, port, entry_id, sizeof(entry_id)); + entry_len = strlen(entry_id); + + dns->inuse = 1; /* the cache has the first reference */ + dns->addr = addr; /* this is the address(es) */ + time(&dns->timestamp); + if(dns->timestamp == 0) + dns->timestamp = 1; /* zero indicates CURLOPT_RESOLVE entry */ + + /* Store the resolved data in our DNS cache. */ + dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len + 1, + (void *)dns); + if(!dns2) { + free(dns); + return NULL; + } + + dns = dns2; + dns->inuse++; /* mark entry as in-use */ + return dns; +} + +/* + * Curl_resolv() is the main name resolve function within libcurl. It resolves + * a name and returns a pointer to the entry in the 'entry' argument (if one + * is provided). This function might return immediately if we're using asynch + * resolves. See the return codes. + * + * The cache entry we return will get its 'inuse' counter increased when this + * function is used. You MUST call Curl_resolv_unlock() later (when you're + * done using this struct) to decrease the counter again. + * + * In debug mode, we specifically test for an interface name "LocalHost" + * and resolve "localhost" instead as a means to permit test cases + * to connect to a local test server with any host name. + * + * Return codes: + * + * CURLRESOLV_ERROR (-1) = error, no pointer + * CURLRESOLV_RESOLVED (0) = OK, pointer provided + * CURLRESOLV_PENDING (1) = waiting for response, no pointer + */ + +int Curl_resolv(struct connectdata *conn, + const char *hostname, + int port, + bool allowDOH, + struct Curl_dns_entry **entry) +{ + struct Curl_dns_entry *dns = NULL; + struct Curl_easy *data = conn->data; + CURLcode result; + int rc = CURLRESOLV_ERROR; /* default to failure */ + + *entry = NULL; + + if(data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + dns = fetch_addr(conn, hostname, port); + + if(dns) { + infof(data, "Hostname %s was found in DNS cache\n", hostname); + dns->inuse++; /* we use it! */ + rc = CURLRESOLV_RESOLVED; + } + + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + + if(!dns) { + /* The entry was not in the cache. Resolve it to IP address */ + + Curl_addrinfo *addr; + int respwait = 0; + + /* Check what IP specifics the app has requested and if we can provide it. + * If not, bail out. */ + if(!Curl_ipvalid(conn)) + return CURLRESOLV_ERROR; + + /* notify the resolver start callback */ + if(data->set.resolver_start) { + int st; + Curl_set_in_callback(data, true); + st = data->set.resolver_start(data->state.resolver, NULL, + data->set.resolver_start_client); + Curl_set_in_callback(data, false); + if(st) + return CURLRESOLV_ERROR; + } + + if(allowDOH && data->set.doh) { + addr = Curl_doh(conn, hostname, port, &respwait); + } + else { + /* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a + non-zero value indicating that we need to wait for the response to the + resolve call */ + addr = Curl_getaddrinfo(conn, +#ifdef DEBUGBUILD + (data->set.str[STRING_DEVICE] + && !strcmp(data->set.str[STRING_DEVICE], + "LocalHost"))?"localhost": +#endif + hostname, port, &respwait); + } + if(!addr) { + if(respwait) { + /* the response to our resolve call will come asynchronously at + a later time, good or bad */ + /* First, check that we haven't received the info by now */ + result = Curl_resolv_check(conn, &dns); + if(result) /* error detected */ + return CURLRESOLV_ERROR; + if(dns) + rc = CURLRESOLV_RESOLVED; /* pointer provided */ + else + rc = CURLRESOLV_PENDING; /* no info yet */ + } + } + else { + if(data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + /* we got a response, store it in the cache */ + dns = Curl_cache_addr(data, addr, hostname, port); + + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + + if(!dns) + /* returned failure, bail out nicely */ + Curl_freeaddrinfo(addr); + else + rc = CURLRESOLV_RESOLVED; + } + } + + *entry = dns; + + return rc; +} + +#ifdef USE_ALARM_TIMEOUT +/* + * This signal handler jumps back into the main libcurl code and continues + * execution. This effectively causes the remainder of the application to run + * within a signal handler which is nonportable and could lead to problems. + */ +static +RETSIGTYPE alarmfunc(int sig) +{ + /* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */ + (void)sig; + siglongjmp(curl_jmpenv, 1); +} +#endif /* USE_ALARM_TIMEOUT */ + +/* + * Curl_resolv_timeout() is the same as Curl_resolv() but specifies a + * timeout. This function might return immediately if we're using asynch + * resolves. See the return codes. + * + * The cache entry we return will get its 'inuse' counter increased when this + * function is used. You MUST call Curl_resolv_unlock() later (when you're + * done using this struct) to decrease the counter again. + * + * If built with a synchronous resolver and use of signals is not + * disabled by the application, then a nonzero timeout will cause a + * timeout after the specified number of milliseconds. Otherwise, timeout + * is ignored. + * + * Return codes: + * + * CURLRESOLV_TIMEDOUT(-2) = warning, time too short or previous alarm expired + * CURLRESOLV_ERROR (-1) = error, no pointer + * CURLRESOLV_RESOLVED (0) = OK, pointer provided + * CURLRESOLV_PENDING (1) = waiting for response, no pointer + */ + +int Curl_resolv_timeout(struct connectdata *conn, + const char *hostname, + int port, + struct Curl_dns_entry **entry, + time_t timeoutms) +{ +#ifdef USE_ALARM_TIMEOUT +#ifdef HAVE_SIGACTION + struct sigaction keep_sigact; /* store the old struct here */ + volatile bool keep_copysig = FALSE; /* whether old sigact has been saved */ + struct sigaction sigact; +#else +#ifdef HAVE_SIGNAL + void (*keep_sigact)(int); /* store the old handler here */ +#endif /* HAVE_SIGNAL */ +#endif /* HAVE_SIGACTION */ + volatile long timeout; + volatile unsigned int prev_alarm = 0; + struct Curl_easy *data = conn->data; +#endif /* USE_ALARM_TIMEOUT */ + int rc; + + *entry = NULL; + + if(timeoutms < 0) + /* got an already expired timeout */ + return CURLRESOLV_TIMEDOUT; + +#ifdef USE_ALARM_TIMEOUT + if(data->set.no_signal) + /* Ignore the timeout when signals are disabled */ + timeout = 0; + else + timeout = (timeoutms > LONG_MAX) ? LONG_MAX : (long)timeoutms; + + if(!timeout) + /* USE_ALARM_TIMEOUT defined, but no timeout actually requested */ + return Curl_resolv(conn, hostname, port, TRUE, entry); + + if(timeout < 1000) { + /* The alarm() function only provides integer second resolution, so if + we want to wait less than one second we must bail out already now. */ + failf(data, + "remaining timeout of %ld too small to resolve via SIGALRM method", + timeout); + return CURLRESOLV_TIMEDOUT; + } + /* This allows us to time-out from the name resolver, as the timeout + will generate a signal and we will siglongjmp() from that here. + This technique has problems (see alarmfunc). + This should be the last thing we do before calling Curl_resolv(), + as otherwise we'd have to worry about variables that get modified + before we invoke Curl_resolv() (and thus use "volatile"). */ + if(sigsetjmp(curl_jmpenv, 1)) { + /* this is coming from a siglongjmp() after an alarm signal */ + failf(data, "name lookup timed out"); + rc = CURLRESOLV_ERROR; + goto clean_up; + } + else { + /************************************************************* + * Set signal handler to catch SIGALRM + * Store the old value to be able to set it back later! + *************************************************************/ +#ifdef HAVE_SIGACTION + sigaction(SIGALRM, NULL, &sigact); + keep_sigact = sigact; + keep_copysig = TRUE; /* yes, we have a copy */ + sigact.sa_handler = alarmfunc; +#ifdef SA_RESTART + /* HPUX doesn't have SA_RESTART but defaults to that behaviour! */ + sigact.sa_flags &= ~SA_RESTART; +#endif + /* now set the new struct */ + sigaction(SIGALRM, &sigact, NULL); +#else /* HAVE_SIGACTION */ + /* no sigaction(), revert to the much lamer signal() */ +#ifdef HAVE_SIGNAL + keep_sigact = signal(SIGALRM, alarmfunc); +#endif +#endif /* HAVE_SIGACTION */ + + /* alarm() makes a signal get sent when the timeout fires off, and that + will abort system calls */ + prev_alarm = alarm(curlx_sltoui(timeout/1000L)); + } + +#else +#ifndef CURLRES_ASYNCH + if(timeoutms) + infof(conn->data, "timeout on name lookup is not supported\n"); +#else + (void)timeoutms; /* timeoutms not used with an async resolver */ +#endif +#endif /* USE_ALARM_TIMEOUT */ + + /* Perform the actual name resolution. This might be interrupted by an + * alarm if it takes too long. + */ + rc = Curl_resolv(conn, hostname, port, TRUE, entry); + +#ifdef USE_ALARM_TIMEOUT +clean_up: + + if(!prev_alarm) + /* deactivate a possibly active alarm before uninstalling the handler */ + alarm(0); + +#ifdef HAVE_SIGACTION + if(keep_copysig) { + /* we got a struct as it looked before, now put that one back nice + and clean */ + sigaction(SIGALRM, &keep_sigact, NULL); /* put it back */ + } +#else +#ifdef HAVE_SIGNAL + /* restore the previous SIGALRM handler */ + signal(SIGALRM, keep_sigact); +#endif +#endif /* HAVE_SIGACTION */ + + /* switch back the alarm() to either zero or to what it was before minus + the time we spent until now! */ + if(prev_alarm) { + /* there was an alarm() set before us, now put it back */ + timediff_t elapsed_secs = Curl_timediff(Curl_now(), + conn->created) / 1000; + + /* the alarm period is counted in even number of seconds */ + unsigned long alarm_set = prev_alarm - elapsed_secs; + + if(!alarm_set || + ((alarm_set >= 0x80000000) && (prev_alarm < 0x80000000)) ) { + /* if the alarm time-left reached zero or turned "negative" (counted + with unsigned values), we should fire off a SIGALRM here, but we + won't, and zero would be to switch it off so we never set it to + less than 1! */ + alarm(1); + rc = CURLRESOLV_TIMEDOUT; + failf(data, "Previous alarm fired off!"); + } + else + alarm((unsigned int)alarm_set); + } +#endif /* USE_ALARM_TIMEOUT */ + + return rc; +} + +/* + * Curl_resolv_unlock() unlocks the given cached DNS entry. When this has been + * made, the struct may be destroyed due to pruning. It is important that only + * one unlock is made for each Curl_resolv() call. + * + * May be called with 'data' == NULL for global cache. + */ +void Curl_resolv_unlock(struct Curl_easy *data, struct Curl_dns_entry *dns) +{ + if(data && data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + freednsentry(dns); + + if(data && data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); +} + +/* + * File-internal: release cache dns entry reference, free if inuse drops to 0 + */ +static void freednsentry(void *freethis) +{ + struct Curl_dns_entry *dns = (struct Curl_dns_entry *) freethis; + DEBUGASSERT(dns && (dns->inuse>0)); + + dns->inuse--; + if(dns->inuse == 0) { + Curl_freeaddrinfo(dns->addr); + free(dns); + } +} + +/* + * Curl_mk_dnscache() inits a new DNS cache and returns success/failure. + */ +int Curl_mk_dnscache(struct curl_hash *hash) +{ + return Curl_hash_init(hash, 7, Curl_hash_str, Curl_str_key_compare, + freednsentry); +} + +/* + * Curl_hostcache_clean() + * + * This _can_ be called with 'data' == NULL but then of course no locking + * can be done! + */ + +void Curl_hostcache_clean(struct Curl_easy *data, + struct curl_hash *hash) +{ + if(data && data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + Curl_hash_clean(hash); + + if(data && data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); +} + + +CURLcode Curl_loadhostpairs(struct Curl_easy *data) +{ + struct curl_slist *hostp; + char hostname[256]; + int port = 0; + + /* Default is no wildcard found */ + data->change.wildcard_resolve = false; + + for(hostp = data->change.resolve; hostp; hostp = hostp->next) { + char entry_id[MAX_HOSTCACHE_LEN]; + if(!hostp->data) + continue; + if(hostp->data[0] == '-') { + size_t entry_len; + + if(2 != sscanf(hostp->data + 1, "%255[^:]:%d", hostname, &port)) { + infof(data, "Couldn't parse CURLOPT_RESOLVE removal entry '%s'!\n", + hostp->data); + continue; + } + + /* Create an entry id, based upon the hostname and port */ + create_hostcache_id(hostname, port, entry_id, sizeof(entry_id)); + entry_len = strlen(entry_id); + + if(data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + /* delete entry, ignore if it didn't exist */ + Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1); + + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + } + else { + struct Curl_dns_entry *dns; + Curl_addrinfo *head = NULL, *tail = NULL; + size_t entry_len; + char address[64]; +#if !defined(CURL_DISABLE_VERBOSE_STRINGS) + char *addresses = NULL; +#endif + char *addr_begin; + char *addr_end; + char *port_ptr; + char *end_ptr; + char *host_end; + unsigned long tmp_port; + bool error = true; + + host_end = strchr(hostp->data, ':'); + if(!host_end || + ((host_end - hostp->data) >= (ptrdiff_t)sizeof(hostname))) + goto err; + + memcpy(hostname, hostp->data, host_end - hostp->data); + hostname[host_end - hostp->data] = '\0'; + + port_ptr = host_end + 1; + tmp_port = strtoul(port_ptr, &end_ptr, 10); + if(tmp_port > USHRT_MAX || end_ptr == port_ptr || *end_ptr != ':') + goto err; + + port = (int)tmp_port; +#if !defined(CURL_DISABLE_VERBOSE_STRINGS) + addresses = end_ptr + 1; +#endif + + while(*end_ptr) { + size_t alen; + Curl_addrinfo *ai; + + addr_begin = end_ptr + 1; + addr_end = strchr(addr_begin, ','); + if(!addr_end) + addr_end = addr_begin + strlen(addr_begin); + end_ptr = addr_end; + + /* allow IP(v6) address within [brackets] */ + if(*addr_begin == '[') { + if(addr_end == addr_begin || *(addr_end - 1) != ']') + goto err; + ++addr_begin; + --addr_end; + } + + alen = addr_end - addr_begin; + if(!alen) + continue; + + if(alen >= sizeof(address)) + goto err; + + memcpy(address, addr_begin, alen); + address[alen] = '\0'; + +#ifndef ENABLE_IPV6 + if(strchr(address, ':')) { + infof(data, "Ignoring resolve address '%s', missing IPv6 support.\n", + address); + continue; + } +#endif + + ai = Curl_str2addr(address, port); + if(!ai) { + infof(data, "Resolve address '%s' found illegal!\n", address); + goto err; + } + + if(tail) { + tail->ai_next = ai; + tail = tail->ai_next; + } + else { + head = tail = ai; + } + } + + if(!head) + goto err; + + error = false; + err: + if(error) { + infof(data, "Couldn't parse CURLOPT_RESOLVE entry '%s'!\n", + hostp->data); + Curl_freeaddrinfo(head); + continue; + } + + /* Create an entry id, based upon the hostname and port */ + create_hostcache_id(hostname, port, entry_id, sizeof(entry_id)); + entry_len = strlen(entry_id); + + if(data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + /* See if its already in our dns cache */ + dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1); + + if(dns) { + infof(data, "RESOLVE %s:%d is - old addresses discarded!\n", + hostname, port); + /* delete old entry entry, there are two reasons for this + 1. old entry may have different addresses. + 2. even if entry with correct addresses is already in the cache, + but if it is close to expire, then by the time next http + request is made, it can get expired and pruned because old + entry is not necessarily marked as added by CURLOPT_RESOLVE. */ + + Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1); + } + + /* put this new host in the cache */ + dns = Curl_cache_addr(data, head, hostname, port); + if(dns) { + dns->timestamp = 0; /* mark as added by CURLOPT_RESOLVE */ + /* release the returned reference; the cache itself will keep the + * entry alive: */ + dns->inuse--; + } + + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + + if(!dns) { + Curl_freeaddrinfo(head); + return CURLE_OUT_OF_MEMORY; + } + infof(data, "Added %s:%d:%s to DNS cache\n", + hostname, port, addresses); + + /* Wildcard hostname */ + if(hostname[0] == '*' && hostname[1] == '\0') { + infof(data, "RESOLVE %s:%d is wildcard, enabling wildcard checks\n", + hostname, port); + data->change.wildcard_resolve = true; + } + } + } + data->change.resolve = NULL; /* dealt with now */ + + return CURLE_OK; +} + +CURLcode Curl_resolv_check(struct connectdata *conn, + struct Curl_dns_entry **dns) +{ + if(conn->data->set.doh) + return Curl_doh_is_resolved(conn, dns); + return Curl_resolver_is_resolved(conn, dns); +} + +int Curl_resolv_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ +#ifdef CURLRES_ASYNCH + if(conn->data->set.doh) + /* nothing to wait for during DOH resolve, those handles have their own + sockets */ + return GETSOCK_BLANK; + return Curl_resolver_getsock(conn, socks, numsocks); +#else + (void)conn; + (void)socks; + (void)numsocks; + return GETSOCK_BLANK; +#endif +} + +/* Call this function after Curl_connect() has returned async=TRUE and + then a successful name resolve has been received. + + Note: this function disconnects and frees the conn data in case of + resolve failure */ +CURLcode Curl_once_resolved(struct connectdata *conn, + bool *protocol_done) +{ + CURLcode result; + + if(conn->async.dns) { + conn->dns_entry = conn->async.dns; + conn->async.dns = NULL; + } + + result = Curl_setup_conn(conn, protocol_done); + + if(result) + /* We're not allowed to return failure with memory left allocated + in the connectdata struct, free those here */ + Curl_disconnect(conn->data, conn, TRUE); /* close the connection */ + + return result; +} diff --git a/dependencies/cmcurl/lib/hostip.h b/dependencies/cmcurl/lib/hostip.h new file mode 100644 index 0000000..9dc0d5a --- /dev/null +++ b/dependencies/cmcurl/lib/hostip.h @@ -0,0 +1,255 @@ +#ifndef HEADER_CURL_HOSTIP_H +#define HEADER_CURL_HOSTIP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include "hash.h" +#include "curl_addrinfo.h" +#include "asyn.h" + +#ifdef HAVE_SETJMP_H +#include +#endif + +#ifdef NETWARE +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +/* Allocate enough memory to hold the full name information structs and + * everything. OSF1 is known to require at least 8872 bytes. The buffer + * required for storing all possible aliases and IP numbers is according to + * Stevens' Unix Network Programming 2nd edition, p. 304: 8192 bytes! + */ +#define CURL_HOSTENT_SIZE 9000 + +#define CURL_TIMEOUT_RESOLVE 300 /* when using asynch methods, we allow this + many seconds for a name resolve */ + +#define CURL_ASYNC_SUCCESS CURLE_OK + +struct addrinfo; +struct hostent; +struct Curl_easy; +struct connectdata; + +/* + * Curl_global_host_cache_init() initializes and sets up a global DNS cache. + * Global DNS cache is general badness. Do not use. This will be removed in + * a future version. Use the share interface instead! + * + * Returns a struct curl_hash pointer on success, NULL on failure. + */ +struct curl_hash *Curl_global_host_cache_init(void); +void Curl_global_host_cache_dtor(void); + +struct Curl_dns_entry { + Curl_addrinfo *addr; + /* timestamp == 0 -- CURLOPT_RESOLVE entry, doesn't timeout */ + time_t timestamp; + /* use-counter, use Curl_resolv_unlock to release reference */ + long inuse; +}; + +/* + * Curl_resolv() returns an entry with the info for the specified host + * and port. + * + * The returned data *MUST* be "unlocked" with Curl_resolv_unlock() after + * use, or we'll leak memory! + */ +/* return codes */ +#define CURLRESOLV_TIMEDOUT -2 +#define CURLRESOLV_ERROR -1 +#define CURLRESOLV_RESOLVED 0 +#define CURLRESOLV_PENDING 1 +int Curl_resolv(struct connectdata *conn, + const char *hostname, + int port, + bool allowDOH, + struct Curl_dns_entry **dnsentry); +int Curl_resolv_timeout(struct connectdata *conn, const char *hostname, + int port, struct Curl_dns_entry **dnsentry, + time_t timeoutms); + +#ifdef CURLRES_IPV6 +/* + * Curl_ipv6works() returns TRUE if IPv6 seems to work. + */ +bool Curl_ipv6works(void); +#else +#define Curl_ipv6works() FALSE +#endif + +/* + * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've + * been set and returns TRUE if they are OK. + */ +bool Curl_ipvalid(struct connectdata *conn); + + +/* + * Curl_getaddrinfo() is the generic low-level name resolve API within this + * source file. There are several versions of this function - for different + * name resolve layers (selected at build-time). They all take this same set + * of arguments + */ +Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, + const char *hostname, + int port, + int *waitp); + + +/* unlock a previously resolved dns entry */ +void Curl_resolv_unlock(struct Curl_easy *data, + struct Curl_dns_entry *dns); + +/* for debugging purposes only: */ +void Curl_scan_cache_used(void *user, void *ptr); + +/* init a new dns cache and return success */ +int Curl_mk_dnscache(struct curl_hash *hash); + +/* prune old entries from the DNS cache */ +void Curl_hostcache_prune(struct Curl_easy *data); + +/* Return # of addresses in a Curl_addrinfo struct */ +int Curl_num_addresses(const Curl_addrinfo *addr); + +#if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO) +int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa, + GETNAMEINFO_TYPE_ARG2 salen, + char *host, GETNAMEINFO_TYPE_ARG46 hostlen, + char *serv, GETNAMEINFO_TYPE_ARG46 servlen, + GETNAMEINFO_TYPE_ARG7 flags, + int line, const char *source); +#endif + +/* IPv4 threadsafe resolve function used for synch and asynch builds */ +Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port); + +CURLcode Curl_once_resolved(struct connectdata *conn, bool *protocol_connect); + +/* + * Curl_addrinfo_callback() is used when we build with any asynch specialty. + * Handles end of async request processing. Inserts ai into hostcache when + * status is CURL_ASYNC_SUCCESS. Twiddles fields in conn to indicate async + * request completed whether successful or failed. + */ +CURLcode Curl_addrinfo_callback(struct connectdata *conn, + int status, + Curl_addrinfo *ai); + +/* + * Curl_printable_address() returns a printable version of the 1st address + * given in the 'ip' argument. The result will be stored in the buf that is + * bufsize bytes big. + */ +const char *Curl_printable_address(const Curl_addrinfo *ip, + char *buf, size_t bufsize); + +/* + * Curl_fetch_addr() fetches a 'Curl_dns_entry' already in the DNS cache. + * + * Returns the Curl_dns_entry entry pointer or NULL if not in the cache. + * + * The returned data *MUST* be "unlocked" with Curl_resolv_unlock() after + * use, or we'll leak memory! + */ +struct Curl_dns_entry * +Curl_fetch_addr(struct connectdata *conn, + const char *hostname, + int port); + +/* + * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache. + * + * Returns the Curl_dns_entry entry pointer or NULL if the storage failed. + */ +struct Curl_dns_entry * +Curl_cache_addr(struct Curl_easy *data, Curl_addrinfo *addr, + const char *hostname, int port); + +#ifndef INADDR_NONE +#define CURL_INADDR_NONE (in_addr_t) ~0 +#else +#define CURL_INADDR_NONE INADDR_NONE +#endif + +#ifdef HAVE_SIGSETJMP +/* Forward-declaration of variable defined in hostip.c. Beware this + * is a global and unique instance. This is used to store the return + * address that we can jump back to from inside a signal handler. + * This is not thread-safe stuff. + */ +extern sigjmp_buf curl_jmpenv; +#endif + +/* + * Function provided by the resolver backend to set DNS servers to use. + */ +CURLcode Curl_set_dns_servers(struct Curl_easy *data, char *servers); + +/* + * Function provided by the resolver backend to set + * outgoing interface to use for DNS requests + */ +CURLcode Curl_set_dns_interface(struct Curl_easy *data, + const char *interf); + +/* + * Function provided by the resolver backend to set + * local IPv4 address to use as source address for DNS requests + */ +CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data, + const char *local_ip4); + +/* + * Function provided by the resolver backend to set + * local IPv6 address to use as source address for DNS requests + */ +CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data, + const char *local_ip6); + +/* + * Clean off entries from the cache + */ +void Curl_hostcache_clean(struct Curl_easy *data, struct curl_hash *hash); + +/* + * Destroy the hostcache of this handle. + */ +void Curl_hostcache_destroy(struct Curl_easy *data); + +/* + * Populate the cache with specified entries from CURLOPT_RESOLVE. + */ +CURLcode Curl_loadhostpairs(struct Curl_easy *data); + +CURLcode Curl_resolv_check(struct connectdata *conn, + struct Curl_dns_entry **dns); +int Curl_resolv_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); + +#endif /* HEADER_CURL_HOSTIP_H */ diff --git a/dependencies/cmcurl/lib/hostip4.c b/dependencies/cmcurl/lib/hostip4.c new file mode 100644 index 0000000..e6ba710 --- /dev/null +++ b/dependencies/cmcurl/lib/hostip4.c @@ -0,0 +1,308 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +/*********************************************************************** + * Only for plain IPv4 builds + **********************************************************************/ +#ifdef CURLRES_IPV4 /* plain IPv4 code coming up */ + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#ifdef HAVE_PROCESS_H +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "hash.h" +#include "share.h" +#include "strerror.h" +#include "url.h" +#include "inet_pton.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've + * been set and returns TRUE if they are OK. + */ +bool Curl_ipvalid(struct connectdata *conn) +{ + if(conn->ip_version == CURL_IPRESOLVE_V6) + /* An IPv6 address was requested and we can't get/use one */ + return FALSE; + + return TRUE; /* OK, proceed */ +} + +#ifdef CURLRES_SYNCH + +/* + * Curl_getaddrinfo() - the IPv4 synchronous version. + * + * The original code to this function was from the Dancer source code, written + * by Bjorn Reese, it has since been patched and modified considerably. + * + * gethostbyname_r() is the thread-safe version of the gethostbyname() + * function. When we build for plain IPv4, we attempt to use this + * function. There are _three_ different gethostbyname_r() versions, and we + * detect which one this platform supports in the configure script and set up + * the HAVE_GETHOSTBYNAME_R_3, HAVE_GETHOSTBYNAME_R_5 or + * HAVE_GETHOSTBYNAME_R_6 defines accordingly. Note that HAVE_GETADDRBYNAME + * has the corresponding rules. This is primarily on *nix. Note that some unix + * flavours have thread-safe versions of the plain gethostbyname() etc. + * + */ +Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, + const char *hostname, + int port, + int *waitp) +{ + Curl_addrinfo *ai = NULL; + +#ifdef CURL_DISABLE_VERBOSE_STRINGS + (void)conn; +#endif + + *waitp = 0; /* synchronous response only */ + + ai = Curl_ipv4_resolve_r(hostname, port); + if(!ai) + infof(conn->data, "Curl_ipv4_resolve_r failed for %s\n", hostname); + + return ai; +} +#endif /* CURLRES_SYNCH */ +#endif /* CURLRES_IPV4 */ + +#if defined(CURLRES_IPV4) && !defined(CURLRES_ARES) + +/* + * Curl_ipv4_resolve_r() - ipv4 threadsafe resolver function. + * + * This is used for both synchronous and asynchronous resolver builds, + * implying that only threadsafe code and function calls may be used. + * + */ +Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, + int port) +{ +#if !defined(HAVE_GETADDRINFO_THREADSAFE) && defined(HAVE_GETHOSTBYNAME_R_3) + int res; +#endif + Curl_addrinfo *ai = NULL; + struct hostent *h = NULL; + struct in_addr in; + struct hostent *buf = NULL; + + if(Curl_inet_pton(AF_INET, hostname, &in) > 0) + /* This is a dotted IP address 123.123.123.123-style */ + return Curl_ip2addr(AF_INET, &in, hostname, port); + +#if defined(HAVE_GETADDRINFO_THREADSAFE) + else { + struct addrinfo hints; + char sbuf[12]; + char *sbufptr = NULL; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_INET; + hints.ai_socktype = SOCK_STREAM; + if(port) { + msnprintf(sbuf, sizeof(sbuf), "%d", port); + sbufptr = sbuf; + } + + (void)Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &ai); + +#elif defined(HAVE_GETHOSTBYNAME_R) + /* + * gethostbyname_r() is the preferred resolve function for many platforms. + * Since there are three different versions of it, the following code is + * somewhat #ifdef-ridden. + */ + else { + int h_errnop; + + buf = calloc(1, CURL_HOSTENT_SIZE); + if(!buf) + return NULL; /* major failure */ + /* + * The clearing of the buffer is a workaround for a gethostbyname_r bug in + * qnx nto and it is also _required_ for some of these functions on some + * platforms. + */ + +#if defined(HAVE_GETHOSTBYNAME_R_5) + /* Solaris, IRIX and more */ + h = gethostbyname_r(hostname, + (struct hostent *)buf, + (char *)buf + sizeof(struct hostent), + CURL_HOSTENT_SIZE - sizeof(struct hostent), + &h_errnop); + + /* If the buffer is too small, it returns NULL and sets errno to + * ERANGE. The errno is thread safe if this is compiled with + * -D_REENTRANT as then the 'errno' variable is a macro defined to get + * used properly for threads. + */ + + if(h) { + ; + } + else +#elif defined(HAVE_GETHOSTBYNAME_R_6) + /* Linux */ + + (void)gethostbyname_r(hostname, + (struct hostent *)buf, + (char *)buf + sizeof(struct hostent), + CURL_HOSTENT_SIZE - sizeof(struct hostent), + &h, /* DIFFERENCE */ + &h_errnop); + /* Redhat 8, using glibc 2.2.93 changed the behavior. Now all of a + * sudden this function returns EAGAIN if the given buffer size is too + * small. Previous versions are known to return ERANGE for the same + * problem. + * + * This wouldn't be such a big problem if older versions wouldn't + * sometimes return EAGAIN on a common failure case. Alas, we can't + * assume that EAGAIN *or* ERANGE means ERANGE for any given version of + * glibc. + * + * For now, we do that and thus we may call the function repeatedly and + * fail for older glibc versions that return EAGAIN, until we run out of + * buffer size (step_size grows beyond CURL_HOSTENT_SIZE). + * + * If anyone has a better fix, please tell us! + * + * ------------------------------------------------------------------- + * + * On October 23rd 2003, Dan C dug up more details on the mysteries of + * gethostbyname_r() in glibc: + * + * In glibc 2.2.5 the interface is different (this has also been + * discovered in glibc 2.1.1-6 as shipped by Redhat 6). What I can't + * explain, is that tests performed on glibc 2.2.4-34 and 2.2.4-32 + * (shipped/upgraded by Redhat 7.2) don't show this behavior! + * + * In this "buggy" version, the return code is -1 on error and 'errno' + * is set to the ERANGE or EAGAIN code. Note that 'errno' is not a + * thread-safe variable. + */ + + if(!h) /* failure */ +#elif defined(HAVE_GETHOSTBYNAME_R_3) + /* AIX, Digital Unix/Tru64, HPUX 10, more? */ + + /* For AIX 4.3 or later, we don't use gethostbyname_r() at all, because of + * the plain fact that it does not return unique full buffers on each + * call, but instead several of the pointers in the hostent structs will + * point to the same actual data! This have the unfortunate down-side that + * our caching system breaks down horribly. Luckily for us though, AIX 4.3 + * and more recent versions have a "completely thread-safe"[*] libc where + * all the data is stored in thread-specific memory areas making calls to + * the plain old gethostbyname() work fine even for multi-threaded + * programs. + * + * This AIX 4.3 or later detection is all made in the configure script. + * + * Troels Walsted Hansen helped us work this out on March 3rd, 2003. + * + * [*] = much later we've found out that it isn't at all "completely + * thread-safe", but at least the gethostbyname() function is. + */ + + if(CURL_HOSTENT_SIZE >= + (sizeof(struct hostent) + sizeof(struct hostent_data))) { + + /* August 22nd, 2000: Albert Chin-A-Young brought an updated version + * that should work! September 20: Richard Prescott worked on the buffer + * size dilemma. + */ + + res = gethostbyname_r(hostname, + (struct hostent *)buf, + (struct hostent_data *)((char *)buf + + sizeof(struct hostent))); + h_errnop = SOCKERRNO; /* we don't deal with this, but set it anyway */ + } + else + res = -1; /* failure, too smallish buffer size */ + + if(!res) { /* success */ + + h = buf; /* result expected in h */ + + /* This is the worst kind of the different gethostbyname_r() interfaces. + * Since we don't know how big buffer this particular lookup required, + * we can't realloc down the huge alloc without doing closer analysis of + * the returned data. Thus, we always use CURL_HOSTENT_SIZE for every + * name lookup. Fixing this would require an extra malloc() and then + * calling Curl_addrinfo_copy() that subsequent realloc()s down the new + * memory area to the actually used amount. + */ + } + else +#endif /* HAVE_...BYNAME_R_5 || HAVE_...BYNAME_R_6 || HAVE_...BYNAME_R_3 */ + { + h = NULL; /* set return code to NULL */ + free(buf); + } +#else /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */ + /* + * Here is code for platforms that don't have a thread safe + * getaddrinfo() nor gethostbyname_r() function or for which + * gethostbyname() is the preferred one. + */ + else { + h = gethostbyname((void *)hostname); +#endif /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */ + } + + if(h) { + ai = Curl_he2ai(h, port); + + if(buf) /* used a *_r() function */ + free(buf); + } + + return ai; +} +#endif /* defined(CURLRES_IPV4) && !defined(CURLRES_ARES) */ diff --git a/dependencies/cmcurl/lib/hostip6.c b/dependencies/cmcurl/lib/hostip6.c new file mode 100644 index 0000000..5511f1a --- /dev/null +++ b/dependencies/cmcurl/lib/hostip6.c @@ -0,0 +1,203 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +/*********************************************************************** + * Only for IPv6-enabled builds + **********************************************************************/ +#ifdef CURLRES_IPV6 + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#ifdef HAVE_PROCESS_H +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "hash.h" +#include "share.h" +#include "strerror.h" +#include "url.h" +#include "inet_pton.h" +#include "connect.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Curl_ipv6works() returns TRUE if IPv6 seems to work. + */ +bool Curl_ipv6works(void) +{ + /* the nature of most system is that IPv6 status doesn't come and go + during a program's lifetime so we only probe the first time and then we + have the info kept for fast re-use */ + static int ipv6_works = -1; + if(-1 == ipv6_works) { + /* probe to see if we have a working IPv6 stack */ + curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0); + if(s == CURL_SOCKET_BAD) + /* an IPv6 address was requested but we can't get/use one */ + ipv6_works = 0; + else { + ipv6_works = 1; + Curl_closesocket(NULL, s); + } + } + return (ipv6_works>0)?TRUE:FALSE; +} + +/* + * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've + * been set and returns TRUE if they are OK. + */ +bool Curl_ipvalid(struct connectdata *conn) +{ + if(conn->ip_version == CURL_IPRESOLVE_V6) + return Curl_ipv6works(); + + return TRUE; +} + +#if defined(CURLRES_SYNCH) + +#ifdef DEBUG_ADDRINFO +static void dump_addrinfo(struct connectdata *conn, const Curl_addrinfo *ai) +{ + printf("dump_addrinfo:\n"); + for(; ai; ai = ai->ai_next) { + char buf[INET6_ADDRSTRLEN]; + printf(" fam %2d, CNAME %s, ", + ai->ai_family, ai->ai_canonname ? ai->ai_canonname : ""); + if(Curl_printable_address(ai, buf, sizeof(buf))) + printf("%s\n", buf); + else { + char buffer[STRERROR_LEN]; + printf("failed; %s\n", + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + } + } +} +#else +#define dump_addrinfo(x,y) Curl_nop_stmt +#endif + +/* + * Curl_getaddrinfo() when built IPv6-enabled (non-threading and + * non-ares version). + * + * Returns name information about the given hostname and port number. If + * successful, the 'addrinfo' is returned and the forth argument will point to + * memory we need to free after use. That memory *MUST* be freed with + * Curl_freeaddrinfo(), nothing else. + */ +Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, + const char *hostname, + int port, + int *waitp) +{ + struct addrinfo hints; + Curl_addrinfo *res; + int error; + char sbuf[12]; + char *sbufptr = NULL; +#ifndef USE_RESOLVE_ON_IPS + char addrbuf[128]; +#endif + int pf; +#if !defined(CURL_DISABLE_VERBOSE_STRINGS) + struct Curl_easy *data = conn->data; +#endif + + *waitp = 0; /* synchronous response only */ + + /* Check if a limited name resolve has been requested */ + switch(conn->ip_version) { + case CURL_IPRESOLVE_V4: + pf = PF_INET; + break; + case CURL_IPRESOLVE_V6: + pf = PF_INET6; + break; + default: + pf = PF_UNSPEC; + break; + } + + if((pf != PF_INET) && !Curl_ipv6works()) + /* The stack seems to be a non-IPv6 one */ + pf = PF_INET; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = pf; + hints.ai_socktype = conn->socktype; + +#ifndef USE_RESOLVE_ON_IPS + /* + * The AI_NUMERICHOST must not be set to get synthesized IPv6 address from + * an IPv4 address on iOS and Mac OS X. + */ + if((1 == Curl_inet_pton(AF_INET, hostname, addrbuf)) || + (1 == Curl_inet_pton(AF_INET6, hostname, addrbuf))) { + /* the given address is numerical only, prevent a reverse lookup */ + hints.ai_flags = AI_NUMERICHOST; + } +#endif + + if(port) { + msnprintf(sbuf, sizeof(sbuf), "%d", port); + sbufptr = sbuf; + } + + error = Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &res); + if(error) { + infof(data, "getaddrinfo(3) failed for %s:%d\n", hostname, port); + return NULL; + } + + if(port) { + Curl_addrinfo_set_port(res, port); + } + + dump_addrinfo(conn, res); + + return res; +} +#endif /* CURLRES_SYNCH */ + +#endif /* CURLRES_IPV6 */ diff --git a/dependencies/cmcurl/lib/hostsyn.c b/dependencies/cmcurl/lib/hostsyn.c new file mode 100644 index 0000000..3de6746 --- /dev/null +++ b/dependencies/cmcurl/lib/hostsyn.c @@ -0,0 +1,107 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +/*********************************************************************** + * Only for builds using synchronous name resolves + **********************************************************************/ +#ifdef CURLRES_SYNCH + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#ifdef HAVE_PROCESS_H +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "hash.h" +#include "share.h" +#include "strerror.h" +#include "url.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * Function provided by the resolver backend to set DNS servers to use. + */ +CURLcode Curl_set_dns_servers(struct Curl_easy *data, + char *servers) +{ + (void)data; + (void)servers; + return CURLE_NOT_BUILT_IN; + +} + +/* + * Function provided by the resolver backend to set + * outgoing interface to use for DNS requests + */ +CURLcode Curl_set_dns_interface(struct Curl_easy *data, + const char *interf) +{ + (void)data; + (void)interf; + return CURLE_NOT_BUILT_IN; +} + +/* + * Function provided by the resolver backend to set + * local IPv4 address to use as source address for DNS requests + */ +CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data, + const char *local_ip4) +{ + (void)data; + (void)local_ip4; + return CURLE_NOT_BUILT_IN; +} + +/* + * Function provided by the resolver backend to set + * local IPv6 address to use as source address for DNS requests + */ +CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data, + const char *local_ip6) +{ + (void)data; + (void)local_ip6; + return CURLE_NOT_BUILT_IN; +} + +#endif /* truly sync */ diff --git a/dependencies/cmcurl/lib/http.c b/dependencies/cmcurl/lib/http.c new file mode 100644 index 0000000..338c59a --- /dev/null +++ b/dependencies/cmcurl/lib/http.c @@ -0,0 +1,4099 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_HTTP + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#include "urldata.h" +#include +#include "transfer.h" +#include "sendf.h" +#include "formdata.h" +#include "mime.h" +#include "progress.h" +#include "curl_base64.h" +#include "cookie.h" +#include "vauth/vauth.h" +#include "vtls/vtls.h" +#include "http_digest.h" +#include "http_ntlm.h" +#include "curl_ntlm_wb.h" +#include "http_negotiate.h" +#include "url.h" +#include "share.h" +#include "hostip.h" +#include "http.h" +#include "select.h" +#include "parsedate.h" /* for the week day and month names */ +#include "strtoofft.h" +#include "multiif.h" +#include "strcase.h" +#include "content_encoding.h" +#include "http_proxy.h" +#include "warnless.h" +#include "non-ascii.h" +#include "http2.h" +#include "connect.h" +#include "strdup.h" +#include "altsvc.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Forward declarations. + */ + +static int http_getsock_do(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); +static int http_should_fail(struct connectdata *conn); + +#ifndef CURL_DISABLE_PROXY +static CURLcode add_haproxy_protocol_header(struct connectdata *conn); +#endif + +#ifdef USE_SSL +static CURLcode https_connecting(struct connectdata *conn, bool *done); +static int https_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); +#else +#define https_connecting(x,y) CURLE_COULDNT_CONNECT +#endif +static CURLcode http_setup_conn(struct connectdata *conn); + +/* + * HTTP handler interface. + */ +const struct Curl_handler Curl_handler_http = { + "HTTP", /* scheme */ + http_setup_conn, /* setup_connection */ + Curl_http, /* do_it */ + Curl_http_done, /* done */ + ZERO_NULL, /* do_more */ + Curl_http_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + http_getsock_do, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_HTTP, /* defport */ + CURLPROTO_HTTP, /* protocol */ + PROTOPT_CREDSPERREQUEST /* flags */ +}; + +#ifdef USE_SSL +/* + * HTTPS handler interface. + */ +const struct Curl_handler Curl_handler_https = { + "HTTPS", /* scheme */ + http_setup_conn, /* setup_connection */ + Curl_http, /* do_it */ + Curl_http_done, /* done */ + ZERO_NULL, /* do_more */ + Curl_http_connect, /* connect_it */ + https_connecting, /* connecting */ + ZERO_NULL, /* doing */ + https_getsock, /* proto_getsock */ + http_getsock_do, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_HTTPS, /* defport */ + CURLPROTO_HTTPS, /* protocol */ + PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN_NPN /* flags */ +}; +#endif + +static CURLcode http_setup_conn(struct connectdata *conn) +{ + /* allocate the HTTP-specific struct for the Curl_easy, only to survive + during this request */ + struct HTTP *http; + struct Curl_easy *data = conn->data; + DEBUGASSERT(data->req.protop == NULL); + + http = calloc(1, sizeof(struct HTTP)); + if(!http) + return CURLE_OUT_OF_MEMORY; + + Curl_mime_initpart(&http->form, conn->data); + data->req.protop = http; + + if(!CONN_INUSE(conn)) + /* if not already multi-using, setup connection details */ + Curl_http2_setup_conn(conn); + Curl_http2_setup_req(data); + return CURLE_OK; +} + +#ifndef CURL_DISABLE_PROXY +/* + * checkProxyHeaders() checks the linked list of custom proxy headers + * if proxy headers are not available, then it will lookup into http header + * link list + * + * It takes a connectdata struct as input instead of the Curl_easy simply to + * know if this is a proxy request or not, as it then might check a different + * header list. Provide the header prefix without colon!. + */ +char *Curl_checkProxyheaders(const struct connectdata *conn, + const char *thisheader) +{ + struct curl_slist *head; + size_t thislen = strlen(thisheader); + struct Curl_easy *data = conn->data; + + for(head = (conn->bits.proxy && data->set.sep_headers) ? + data->set.proxyheaders : data->set.headers; + head; head = head->next) { + if(strncasecompare(head->data, thisheader, thislen) && + Curl_headersep(head->data[thislen])) + return head->data; + } + + return NULL; +} +#else +/* disabled */ +#define Curl_checkProxyheaders(x,y) NULL +#endif + +/* + * Strip off leading and trailing whitespace from the value in the + * given HTTP header line and return a strdupped copy. Returns NULL in + * case of allocation failure. Returns an empty string if the header value + * consists entirely of whitespace. + */ +char *Curl_copy_header_value(const char *header) +{ + const char *start; + const char *end; + char *value; + size_t len; + + /* Find the end of the header name */ + while(*header && (*header != ':')) + ++header; + + if(*header) + /* Skip over colon */ + ++header; + + /* Find the first non-space letter */ + start = header; + while(*start && ISSPACE(*start)) + start++; + + /* data is in the host encoding so + use '\r' and '\n' instead of 0x0d and 0x0a */ + end = strchr(start, '\r'); + if(!end) + end = strchr(start, '\n'); + if(!end) + end = strchr(start, '\0'); + if(!end) + return NULL; + + /* skip all trailing space letters */ + while((end > start) && ISSPACE(*end)) + end--; + + /* get length of the type */ + len = end - start + 1; + + value = malloc(len + 1); + if(!value) + return NULL; + + memcpy(value, start, len); + value[len] = 0; /* zero terminate */ + + return value; +} + +#ifndef CURL_DISABLE_HTTP_AUTH +/* + * http_output_basic() sets up an Authorization: header (or the proxy version) + * for HTTP Basic authentication. + * + * Returns CURLcode. + */ +static CURLcode http_output_basic(struct connectdata *conn, bool proxy) +{ + size_t size = 0; + char *authorization = NULL; + struct Curl_easy *data = conn->data; + char **userp; + const char *user; + const char *pwd; + CURLcode result; + char *out; + + if(proxy) { + userp = &conn->allocptr.proxyuserpwd; + user = conn->http_proxy.user; + pwd = conn->http_proxy.passwd; + } + else { + userp = &conn->allocptr.userpwd; + user = conn->user; + pwd = conn->passwd; + } + + out = aprintf("%s:%s", user, pwd); + if(!out) + return CURLE_OUT_OF_MEMORY; + + result = Curl_base64_encode(data, out, strlen(out), &authorization, &size); + if(result) + goto fail; + + if(!authorization) { + result = CURLE_REMOTE_ACCESS_DENIED; + goto fail; + } + + free(*userp); + *userp = aprintf("%sAuthorization: Basic %s\r\n", + proxy ? "Proxy-" : "", + authorization); + free(authorization); + if(!*userp) { + result = CURLE_OUT_OF_MEMORY; + goto fail; + } + + fail: + free(out); + return result; +} + +/* + * http_output_bearer() sets up an Authorization: header + * for HTTP Bearer authentication. + * + * Returns CURLcode. + */ +static CURLcode http_output_bearer(struct connectdata *conn) +{ + char **userp; + CURLcode result = CURLE_OK; + + userp = &conn->allocptr.userpwd; + free(*userp); + *userp = aprintf("Authorization: Bearer %s\r\n", + conn->oauth_bearer); + + if(!*userp) { + result = CURLE_OUT_OF_MEMORY; + goto fail; + } + + fail: + return result; +} + +#endif + +/* pickoneauth() selects the most favourable authentication method from the + * ones available and the ones we want. + * + * return TRUE if one was picked + */ +static bool pickoneauth(struct auth *pick, unsigned long mask) +{ + bool picked; + /* only deal with authentication we want */ + unsigned long avail = pick->avail & pick->want & mask; + picked = TRUE; + + /* The order of these checks is highly relevant, as this will be the order + of preference in case of the existence of multiple accepted types. */ + if(avail & CURLAUTH_NEGOTIATE) + pick->picked = CURLAUTH_NEGOTIATE; + else if(avail & CURLAUTH_BEARER) + pick->picked = CURLAUTH_BEARER; + else if(avail & CURLAUTH_DIGEST) + pick->picked = CURLAUTH_DIGEST; + else if(avail & CURLAUTH_NTLM) + pick->picked = CURLAUTH_NTLM; + else if(avail & CURLAUTH_NTLM_WB) + pick->picked = CURLAUTH_NTLM_WB; + else if(avail & CURLAUTH_BASIC) + pick->picked = CURLAUTH_BASIC; + else { + pick->picked = CURLAUTH_PICKNONE; /* we select to use nothing */ + picked = FALSE; + } + pick->avail = CURLAUTH_NONE; /* clear it here */ + + return picked; +} + +/* + * Curl_http_perhapsrewind() + * + * If we are doing POST or PUT { + * If we have more data to send { + * If we are doing NTLM { + * Keep sending since we must not disconnect + * } + * else { + * If there is more than just a little data left to send, close + * the current connection by force. + * } + * } + * If we have sent any data { + * If we don't have track of all the data { + * call app to tell it to rewind + * } + * else { + * rewind internally so that the operation can restart fine + * } + * } + * } + */ +static CURLcode http_perhapsrewind(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + struct HTTP *http = data->req.protop; + curl_off_t bytessent; + curl_off_t expectsend = -1; /* default is unknown */ + + if(!http) + /* If this is still NULL, we have not reach very far and we can safely + skip this rewinding stuff */ + return CURLE_OK; + + switch(data->set.httpreq) { + case HTTPREQ_GET: + case HTTPREQ_HEAD: + return CURLE_OK; + default: + break; + } + + bytessent = data->req.writebytecount; + + if(conn->bits.authneg) { + /* This is a state where we are known to be negotiating and we don't send + any data then. */ + expectsend = 0; + } + else if(!conn->bits.protoconnstart) { + /* HTTP CONNECT in progress: there is no body */ + expectsend = 0; + } + else { + /* figure out how much data we are expected to send */ + switch(data->set.httpreq) { + case HTTPREQ_POST: + if(data->state.infilesize != -1) + expectsend = data->state.infilesize; + break; + case HTTPREQ_PUT: + if(data->state.infilesize != -1) + expectsend = data->state.infilesize; + break; + case HTTPREQ_POST_FORM: + case HTTPREQ_POST_MIME: + expectsend = http->postsize; + break; + default: + break; + } + } + + conn->bits.rewindaftersend = FALSE; /* default */ + + if((expectsend == -1) || (expectsend > bytessent)) { +#if defined(USE_NTLM) + /* There is still data left to send */ + if((data->state.authproxy.picked == CURLAUTH_NTLM) || + (data->state.authhost.picked == CURLAUTH_NTLM) || + (data->state.authproxy.picked == CURLAUTH_NTLM_WB) || + (data->state.authhost.picked == CURLAUTH_NTLM_WB)) { + if(((expectsend - bytessent) < 2000) || + (conn->http_ntlm_state != NTLMSTATE_NONE) || + (conn->proxy_ntlm_state != NTLMSTATE_NONE)) { + /* The NTLM-negotiation has started *OR* there is just a little (<2K) + data left to send, keep on sending. */ + + /* rewind data when completely done sending! */ + if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) { + conn->bits.rewindaftersend = TRUE; + infof(data, "Rewind stream after send\n"); + } + + return CURLE_OK; + } + + if(conn->bits.close) + /* this is already marked to get closed */ + return CURLE_OK; + + infof(data, "NTLM send, close instead of sending %" + CURL_FORMAT_CURL_OFF_T " bytes\n", + (curl_off_t)(expectsend - bytessent)); + } +#endif +#if defined(USE_SPNEGO) + /* There is still data left to send */ + if((data->state.authproxy.picked == CURLAUTH_NEGOTIATE) || + (data->state.authhost.picked == CURLAUTH_NEGOTIATE)) { + if(((expectsend - bytessent) < 2000) || + (conn->http_negotiate_state != GSS_AUTHNONE) || + (conn->proxy_negotiate_state != GSS_AUTHNONE)) { + /* The NEGOTIATE-negotiation has started *OR* + there is just a little (<2K) data left to send, keep on sending. */ + + /* rewind data when completely done sending! */ + if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) { + conn->bits.rewindaftersend = TRUE; + infof(data, "Rewind stream after send\n"); + } + + return CURLE_OK; + } + + if(conn->bits.close) + /* this is already marked to get closed */ + return CURLE_OK; + + infof(data, "NEGOTIATE send, close instead of sending %" + CURL_FORMAT_CURL_OFF_T " bytes\n", + (curl_off_t)(expectsend - bytessent)); + } +#endif + + /* This is not NEGOTIATE/NTLM or many bytes left to send: close */ + streamclose(conn, "Mid-auth HTTP and much data left to send"); + data->req.size = 0; /* don't download any more than 0 bytes */ + + /* There still is data left to send, but this connection is marked for + closure so we can safely do the rewind right now */ + } + + if(bytessent) + /* we rewind now at once since if we already sent something */ + return Curl_readrewind(conn); + + return CURLE_OK; +} + +/* + * Curl_http_auth_act() gets called when all HTTP headers have been received + * and it checks what authentication methods that are available and decides + * which one (if any) to use. It will set 'newurl' if an auth method was + * picked. + */ + +CURLcode Curl_http_auth_act(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + bool pickhost = FALSE; + bool pickproxy = FALSE; + CURLcode result = CURLE_OK; + unsigned long authmask = ~0ul; + + if(!conn->oauth_bearer) + authmask &= (unsigned long)~CURLAUTH_BEARER; + + if(100 <= data->req.httpcode && 199 >= data->req.httpcode) + /* this is a transient response code, ignore */ + return CURLE_OK; + + if(data->state.authproblem) + return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK; + + if((conn->bits.user_passwd || conn->oauth_bearer) && + ((data->req.httpcode == 401) || + (conn->bits.authneg && data->req.httpcode < 300))) { + pickhost = pickoneauth(&data->state.authhost, authmask); + if(!pickhost) + data->state.authproblem = TRUE; + if(data->state.authhost.picked == CURLAUTH_NTLM && + conn->httpversion > 11) { + infof(data, "Forcing HTTP/1.1 for NTLM"); + connclose(conn, "Force HTTP/1.1 connection"); + conn->data->set.httpversion = CURL_HTTP_VERSION_1_1; + } + } + if(conn->bits.proxy_user_passwd && + ((data->req.httpcode == 407) || + (conn->bits.authneg && data->req.httpcode < 300))) { + pickproxy = pickoneauth(&data->state.authproxy, + authmask & ~CURLAUTH_BEARER); + if(!pickproxy) + data->state.authproblem = TRUE; + } + + if(pickhost || pickproxy) { + if((data->set.httpreq != HTTPREQ_GET) && + (data->set.httpreq != HTTPREQ_HEAD) && + !conn->bits.rewindaftersend) { + result = http_perhapsrewind(conn); + if(result) + return result; + } + /* In case this is GSS auth, the newurl field is already allocated so + we must make sure to free it before allocating a new one. As figured + out in bug #2284386 */ + Curl_safefree(data->req.newurl); + data->req.newurl = strdup(data->change.url); /* clone URL */ + if(!data->req.newurl) + return CURLE_OUT_OF_MEMORY; + } + else if((data->req.httpcode < 300) && + (!data->state.authhost.done) && + conn->bits.authneg) { + /* no (known) authentication available, + authentication is not "done" yet and + no authentication seems to be required and + we didn't try HEAD or GET */ + if((data->set.httpreq != HTTPREQ_GET) && + (data->set.httpreq != HTTPREQ_HEAD)) { + data->req.newurl = strdup(data->change.url); /* clone URL */ + if(!data->req.newurl) + return CURLE_OUT_OF_MEMORY; + data->state.authhost.done = TRUE; + } + } + if(http_should_fail(conn)) { + failf(data, "The requested URL returned error: %d", + data->req.httpcode); + result = CURLE_HTTP_RETURNED_ERROR; + } + + return result; +} + +#ifndef CURL_DISABLE_HTTP_AUTH +/* + * Output the correct authentication header depending on the auth type + * and whether or not it is to a proxy. + */ +static CURLcode +output_auth_headers(struct connectdata *conn, + struct auth *authstatus, + const char *request, + const char *path, + bool proxy) +{ + const char *auth = NULL; + CURLcode result = CURLE_OK; +#if !defined(CURL_DISABLE_VERBOSE_STRINGS) || defined(USE_SPNEGO) + struct Curl_easy *data = conn->data; +#endif + +#ifdef CURL_DISABLE_CRYPTO_AUTH + (void)request; + (void)path; +#endif + +#ifdef USE_SPNEGO + if((authstatus->picked == CURLAUTH_NEGOTIATE)) { + auth = "Negotiate"; + result = Curl_output_negotiate(conn, proxy); + if(result) + return result; + } + else +#endif +#ifdef USE_NTLM + if(authstatus->picked == CURLAUTH_NTLM) { + auth = "NTLM"; + result = Curl_output_ntlm(conn, proxy); + if(result) + return result; + } + else +#endif +#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED) + if(authstatus->picked == CURLAUTH_NTLM_WB) { + auth = "NTLM_WB"; + result = Curl_output_ntlm_wb(conn, proxy); + if(result) + return result; + } + else +#endif +#ifndef CURL_DISABLE_CRYPTO_AUTH + if(authstatus->picked == CURLAUTH_DIGEST) { + auth = "Digest"; + result = Curl_output_digest(conn, + proxy, + (const unsigned char *)request, + (const unsigned char *)path); + if(result) + return result; + } + else +#endif + if(authstatus->picked == CURLAUTH_BASIC) { + /* Basic */ + if((proxy && conn->bits.proxy_user_passwd && + !Curl_checkProxyheaders(conn, "Proxy-authorization")) || + (!proxy && conn->bits.user_passwd && + !Curl_checkheaders(conn, "Authorization"))) { + auth = "Basic"; + result = http_output_basic(conn, proxy); + if(result) + return result; + } + + /* NOTE: this function should set 'done' TRUE, as the other auth + functions work that way */ + authstatus->done = TRUE; + } + if(authstatus->picked == CURLAUTH_BEARER) { + /* Bearer */ + if((!proxy && conn->oauth_bearer && + !Curl_checkheaders(conn, "Authorization:"))) { + auth = "Bearer"; + result = http_output_bearer(conn); + if(result) + return result; + } + + /* NOTE: this function should set 'done' TRUE, as the other auth + functions work that way */ + authstatus->done = TRUE; + } + + if(auth) { + infof(data, "%s auth using %s with user '%s'\n", + proxy ? "Proxy" : "Server", auth, + proxy ? (conn->http_proxy.user ? conn->http_proxy.user : "") : + (conn->user ? conn->user : "")); + authstatus->multipass = (!authstatus->done) ? TRUE : FALSE; + } + else + authstatus->multipass = FALSE; + + return CURLE_OK; +} + +/** + * Curl_http_output_auth() setups the authentication headers for the + * host/proxy and the correct authentication + * method. conn->data->state.authdone is set to TRUE when authentication is + * done. + * + * @param conn all information about the current connection + * @param request pointer to the request keyword + * @param path pointer to the requested path; should include query part + * @param proxytunnel boolean if this is the request setting up a "proxy + * tunnel" + * + * @returns CURLcode + */ +CURLcode +Curl_http_output_auth(struct connectdata *conn, + const char *request, + const char *path, + bool proxytunnel) /* TRUE if this is the request setting + up the proxy tunnel */ +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct auth *authhost; + struct auth *authproxy; + + DEBUGASSERT(data); + + authhost = &data->state.authhost; + authproxy = &data->state.authproxy; + + if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) || + conn->bits.user_passwd || conn->oauth_bearer) + /* continue please */; + else { + authhost->done = TRUE; + authproxy->done = TRUE; + return CURLE_OK; /* no authentication with no user or password */ + } + + if(authhost->want && !authhost->picked) + /* The app has selected one or more methods, but none has been picked + so far by a server round-trip. Then we set the picked one to the + want one, and if this is one single bit it'll be used instantly. */ + authhost->picked = authhost->want; + + if(authproxy->want && !authproxy->picked) + /* The app has selected one or more methods, but none has been picked so + far by a proxy round-trip. Then we set the picked one to the want one, + and if this is one single bit it'll be used instantly. */ + authproxy->picked = authproxy->want; + +#ifndef CURL_DISABLE_PROXY + /* Send proxy authentication header if needed */ + if(conn->bits.httpproxy && + (conn->bits.tunnel_proxy == (bit)proxytunnel)) { + result = output_auth_headers(conn, authproxy, request, path, TRUE); + if(result) + return result; + } + else +#else + (void)proxytunnel; +#endif /* CURL_DISABLE_PROXY */ + /* we have no proxy so let's pretend we're done authenticating + with it */ + authproxy->done = TRUE; + + /* To prevent the user+password to get sent to other than the original + host due to a location-follow, we do some weirdo checks here */ + if(!data->state.this_is_a_follow || + conn->bits.netrc || + !data->state.first_host || + data->set.allow_auth_to_other_hosts || + strcasecompare(data->state.first_host, conn->host.name)) { + result = output_auth_headers(conn, authhost, request, path, FALSE); + } + else + authhost->done = TRUE; + + return result; +} + +#else +/* when disabled */ +CURLcode +Curl_http_output_auth(struct connectdata *conn, + const char *request, + const char *path, + bool proxytunnel) +{ + (void)conn; + (void)request; + (void)path; + (void)proxytunnel; + return CURLE_OK; +} +#endif + +/* + * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate: + * headers. They are dealt with both in the transfer.c main loop and in the + * proxy CONNECT loop. + */ + +CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, + const char *auth) /* the first non-space */ +{ + /* + * This resource requires authentication + */ + struct Curl_easy *data = conn->data; + +#ifdef USE_SPNEGO + curlnegotiate *negstate = proxy ? &conn->proxy_negotiate_state : + &conn->http_negotiate_state; +#endif + unsigned long *availp; + struct auth *authp; + + if(proxy) { + availp = &data->info.proxyauthavail; + authp = &data->state.authproxy; + } + else { + availp = &data->info.httpauthavail; + authp = &data->state.authhost; + } + + /* + * Here we check if we want the specific single authentication (using ==) and + * if we do, we initiate usage of it. + * + * If the provided authentication is wanted as one out of several accepted + * types (using &), we OR this authentication type to the authavail + * variable. + * + * Note: + * + * ->picked is first set to the 'want' value (one or more bits) before the + * request is sent, and then it is again set _after_ all response 401/407 + * headers have been received but then only to a single preferred method + * (bit). + */ + + while(*auth) { +#ifdef USE_SPNEGO + if(checkprefix("Negotiate", auth)) { + if((authp->avail & CURLAUTH_NEGOTIATE) || + Curl_auth_is_spnego_supported()) { + *availp |= CURLAUTH_NEGOTIATE; + authp->avail |= CURLAUTH_NEGOTIATE; + + if(authp->picked == CURLAUTH_NEGOTIATE) { + CURLcode result = Curl_input_negotiate(conn, proxy, auth); + if(!result) { + DEBUGASSERT(!data->req.newurl); + data->req.newurl = strdup(data->change.url); + if(!data->req.newurl) + return CURLE_OUT_OF_MEMORY; + data->state.authproblem = FALSE; + /* we received a GSS auth token and we dealt with it fine */ + *negstate = GSS_AUTHRECV; + } + else + data->state.authproblem = TRUE; + } + } + } + else +#endif +#ifdef USE_NTLM + /* NTLM support requires the SSL crypto libs */ + if(checkprefix("NTLM", auth)) { + if((authp->avail & CURLAUTH_NTLM) || + (authp->avail & CURLAUTH_NTLM_WB) || + Curl_auth_is_ntlm_supported()) { + *availp |= CURLAUTH_NTLM; + authp->avail |= CURLAUTH_NTLM; + + if(authp->picked == CURLAUTH_NTLM || + authp->picked == CURLAUTH_NTLM_WB) { + /* NTLM authentication is picked and activated */ + CURLcode result = Curl_input_ntlm(conn, proxy, auth); + if(!result) { + data->state.authproblem = FALSE; +#ifdef NTLM_WB_ENABLED + if(authp->picked == CURLAUTH_NTLM_WB) { + *availp &= ~CURLAUTH_NTLM; + authp->avail &= ~CURLAUTH_NTLM; + *availp |= CURLAUTH_NTLM_WB; + authp->avail |= CURLAUTH_NTLM_WB; + + result = Curl_input_ntlm_wb(conn, proxy, auth); + if(result) { + infof(data, "Authentication problem. Ignoring this.\n"); + data->state.authproblem = TRUE; + } + } +#endif + } + else { + infof(data, "Authentication problem. Ignoring this.\n"); + data->state.authproblem = TRUE; + } + } + } + } + else +#endif +#ifndef CURL_DISABLE_CRYPTO_AUTH + if(checkprefix("Digest", auth)) { + if((authp->avail & CURLAUTH_DIGEST) != 0) + infof(data, "Ignoring duplicate digest auth header.\n"); + else if(Curl_auth_is_digest_supported()) { + CURLcode result; + + *availp |= CURLAUTH_DIGEST; + authp->avail |= CURLAUTH_DIGEST; + + /* We call this function on input Digest headers even if Digest + * authentication isn't activated yet, as we need to store the + * incoming data from this header in case we are going to use + * Digest */ + result = Curl_input_digest(conn, proxy, auth); + if(result) { + infof(data, "Authentication problem. Ignoring this.\n"); + data->state.authproblem = TRUE; + } + } + } + else +#endif + if(checkprefix("Basic", auth)) { + *availp |= CURLAUTH_BASIC; + authp->avail |= CURLAUTH_BASIC; + if(authp->picked == CURLAUTH_BASIC) { + /* We asked for Basic authentication but got a 40X back + anyway, which basically means our name+password isn't + valid. */ + authp->avail = CURLAUTH_NONE; + infof(data, "Authentication problem. Ignoring this.\n"); + data->state.authproblem = TRUE; + } + } + else + if(checkprefix("Bearer", auth)) { + *availp |= CURLAUTH_BEARER; + authp->avail |= CURLAUTH_BEARER; + if(authp->picked == CURLAUTH_BEARER) { + /* We asked for Bearer authentication but got a 40X back + anyway, which basically means our token isn't valid. */ + authp->avail = CURLAUTH_NONE; + infof(data, "Authentication problem. Ignoring this.\n"); + data->state.authproblem = TRUE; + } + } + + /* there may be multiple methods on one line, so keep reading */ + while(*auth && *auth != ',') /* read up to the next comma */ + auth++; + if(*auth == ',') /* if we're on a comma, skip it */ + auth++; + while(*auth && ISSPACE(*auth)) + auth++; + } + + return CURLE_OK; +} + +/** + * http_should_fail() determines whether an HTTP response has gotten us + * into an error state or not. + * + * @param conn all information about the current connection + * + * @retval 0 communications should continue + * + * @retval 1 communications should not continue + */ +static int http_should_fail(struct connectdata *conn) +{ + struct Curl_easy *data; + int httpcode; + + DEBUGASSERT(conn); + data = conn->data; + DEBUGASSERT(data); + + httpcode = data->req.httpcode; + + /* + ** If we haven't been asked to fail on error, + ** don't fail. + */ + if(!data->set.http_fail_on_error) + return 0; + + /* + ** Any code < 400 is never terminal. + */ + if(httpcode < 400) + return 0; + + /* + ** Any code >= 400 that's not 401 or 407 is always + ** a terminal error + */ + if((httpcode != 401) && (httpcode != 407)) + return 1; + + /* + ** All we have left to deal with is 401 and 407 + */ + DEBUGASSERT((httpcode == 401) || (httpcode == 407)); + + /* + ** Examine the current authentication state to see if this + ** is an error. The idea is for this function to get + ** called after processing all the headers in a response + ** message. So, if we've been to asked to authenticate a + ** particular stage, and we've done it, we're OK. But, if + ** we're already completely authenticated, it's not OK to + ** get another 401 or 407. + ** + ** It is possible for authentication to go stale such that + ** the client needs to reauthenticate. Once that info is + ** available, use it here. + */ + + /* + ** Either we're not authenticating, or we're supposed to + ** be authenticating something else. This is an error. + */ + if((httpcode == 401) && !conn->bits.user_passwd) + return TRUE; + if((httpcode == 407) && !conn->bits.proxy_user_passwd) + return TRUE; + + return data->state.authproblem; +} + +/* + * readmoredata() is a "fread() emulation" to provide POST and/or request + * data. It is used when a huge POST is to be made and the entire chunk wasn't + * sent in the first send(). This function will then be called from the + * transfer.c loop when more data is to be sent to the peer. + * + * Returns the amount of bytes it filled the buffer with. + */ +static size_t readmoredata(char *buffer, + size_t size, + size_t nitems, + void *userp) +{ + struct connectdata *conn = (struct connectdata *)userp; + struct HTTP *http = conn->data->req.protop; + size_t fullsize = size * nitems; + + if(!http->postsize) + /* nothing to return */ + return 0; + + /* make sure that a HTTP request is never sent away chunked! */ + conn->data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE; + + if(http->postsize <= (curl_off_t)fullsize) { + memcpy(buffer, http->postdata, (size_t)http->postsize); + fullsize = (size_t)http->postsize; + + if(http->backup.postsize) { + /* move backup data into focus and continue on that */ + http->postdata = http->backup.postdata; + http->postsize = http->backup.postsize; + conn->data->state.fread_func = http->backup.fread_func; + conn->data->state.in = http->backup.fread_in; + + http->sending++; /* move one step up */ + + http->backup.postsize = 0; + } + else + http->postsize = 0; + + return fullsize; + } + + memcpy(buffer, http->postdata, fullsize); + http->postdata += fullsize; + http->postsize -= fullsize; + + return fullsize; +} + +/* ------------------------------------------------------------------------- */ +/* add_buffer functions */ + +/* + * Curl_add_buffer_init() sets up and returns a fine buffer struct + */ +Curl_send_buffer *Curl_add_buffer_init(void) +{ + return calloc(1, sizeof(Curl_send_buffer)); +} + +/* + * Curl_add_buffer_free() frees all associated resources. + */ +void Curl_add_buffer_free(Curl_send_buffer **inp) +{ + Curl_send_buffer *in = *inp; + if(in) /* deal with NULL input */ + free(in->buffer); + free(in); + *inp = NULL; +} + +/* + * Curl_add_buffer_send() sends a header buffer and frees all associated + * memory. Body data may be appended to the header data if desired. + * + * Returns CURLcode + */ +CURLcode Curl_add_buffer_send(Curl_send_buffer **inp, + struct connectdata *conn, + + /* add the number of sent bytes to this + counter */ + curl_off_t *bytes_written, + + /* how much of the buffer contains body data */ + size_t included_body_bytes, + int socketindex) +{ + ssize_t amount; + CURLcode result; + char *ptr; + size_t size; + struct Curl_easy *data = conn->data; + struct HTTP *http = data->req.protop; + size_t sendsize; + curl_socket_t sockfd; + size_t headersize; + Curl_send_buffer *in = *inp; + + DEBUGASSERT(socketindex <= SECONDARYSOCKET); + + sockfd = conn->sock[socketindex]; + + /* The looping below is required since we use non-blocking sockets, but due + to the circumstances we will just loop and try again and again etc */ + + ptr = in->buffer; + size = in->size_used; + + headersize = size - included_body_bytes; /* the initial part that isn't body + is header */ + + DEBUGASSERT(size > included_body_bytes); + + result = Curl_convert_to_network(data, ptr, headersize); + /* Curl_convert_to_network calls failf if unsuccessful */ + if(result) { + /* conversion failed, free memory and return to the caller */ + Curl_add_buffer_free(inp); + return result; + } + + if((conn->handler->flags & PROTOPT_SSL || + conn->http_proxy.proxytype == CURLPROXY_HTTPS) + && conn->httpversion != 20) { + /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk + when we speak HTTPS, as if only a fraction of it is sent now, this data + needs to fit into the normal read-callback buffer later on and that + buffer is using this size. + */ + + sendsize = CURLMIN(size, CURL_MAX_WRITE_SIZE); + + /* OpenSSL is very picky and we must send the SAME buffer pointer to the + library when we attempt to re-send this buffer. Sending the same data + is not enough, we must use the exact same address. For this reason, we + must copy the data to the uploadbuffer first, since that is the buffer + we will be using if this send is retried later. + */ + result = Curl_get_upload_buffer(data); + if(result) { + /* malloc failed, free memory and return to the caller */ + Curl_add_buffer_free(&in); + return result; + } + memcpy(data->state.ulbuf, ptr, sendsize); + ptr = data->state.ulbuf; + } + else + sendsize = size; + + result = Curl_write(conn, sockfd, ptr, sendsize, &amount); + + if(!result) { + /* + * Note that we may not send the entire chunk at once, and we have a set + * number of data bytes at the end of the big buffer (out of which we may + * only send away a part). + */ + /* how much of the header that was sent */ + size_t headlen = (size_t)amount>headersize ? headersize : (size_t)amount; + size_t bodylen = amount - headlen; + + if(data->set.verbose) { + /* this data _may_ contain binary stuff */ + Curl_debug(data, CURLINFO_HEADER_OUT, ptr, headlen); + if(bodylen) { + /* there was body data sent beyond the initial header part, pass that + on to the debug callback too */ + Curl_debug(data, CURLINFO_DATA_OUT, + ptr + headlen, bodylen); + } + } + + /* 'amount' can never be a very large value here so typecasting it so a + signed 31 bit value should not cause problems even if ssize_t is + 64bit */ + *bytes_written += (long)amount; + + if(http) { + /* if we sent a piece of the body here, up the byte counter for it + accordingly */ + data->req.writebytecount += bodylen; + Curl_pgrsSetUploadCounter(data, data->req.writebytecount); + + if((size_t)amount != size) { + /* The whole request could not be sent in one system call. We must + queue it up and send it later when we get the chance. We must not + loop here and wait until it might work again. */ + + size -= amount; + + ptr = in->buffer + amount; + + /* backup the currently set pointers */ + http->backup.fread_func = data->state.fread_func; + http->backup.fread_in = data->state.in; + http->backup.postdata = http->postdata; + http->backup.postsize = http->postsize; + + /* set the new pointers for the request-sending */ + data->state.fread_func = (curl_read_callback)readmoredata; + data->state.in = (void *)conn; + http->postdata = ptr; + http->postsize = (curl_off_t)size; + + http->send_buffer = in; + http->sending = HTTPSEND_REQUEST; + + return CURLE_OK; + } + http->sending = HTTPSEND_BODY; + /* the full buffer was sent, clean up and return */ + } + else { + if((size_t)amount != size) + /* We have no continue-send mechanism now, fail. This can only happen + when this function is used from the CONNECT sending function. We + currently (stupidly) assume that the whole request is always sent + away in the first single chunk. + + This needs FIXing. + */ + return CURLE_SEND_ERROR; + } + } + Curl_add_buffer_free(&in); + + return result; +} + + +/* + * add_bufferf() add the formatted input to the buffer. + */ +CURLcode Curl_add_bufferf(Curl_send_buffer **inp, const char *fmt, ...) +{ + char *s; + va_list ap; + Curl_send_buffer *in = *inp; + va_start(ap, fmt); + s = vaprintf(fmt, ap); /* this allocs a new string to append */ + va_end(ap); + + if(s) { + CURLcode result = Curl_add_buffer(inp, s, strlen(s)); + free(s); + return result; + } + /* If we failed, we cleanup the whole buffer and return error */ + free(in->buffer); + free(in); + *inp = NULL; + return CURLE_OUT_OF_MEMORY; +} + +/* + * Curl_add_buffer() appends a memory chunk to the existing buffer + */ +CURLcode Curl_add_buffer(Curl_send_buffer **inp, const void *inptr, + size_t size) +{ + char *new_rb; + Curl_send_buffer *in = *inp; + + if(~size < in->size_used) { + /* If resulting used size of send buffer would wrap size_t, cleanup + the whole buffer and return error. Otherwise the required buffer + size will fit into a single allocatable memory chunk */ + Curl_safefree(in->buffer); + free(in); + *inp = NULL; + return CURLE_OUT_OF_MEMORY; + } + + if(!in->buffer || + ((in->size_used + size) > (in->size_max - 1))) { + /* If current buffer size isn't enough to hold the result, use a + buffer size that doubles the required size. If this new size + would wrap size_t, then just use the largest possible one */ + size_t new_size; + + if((size > (size_t)-1 / 2) || (in->size_used > (size_t)-1 / 2) || + (~(size * 2) < (in->size_used * 2))) + new_size = (size_t)-1; + else + new_size = (in->size_used + size) * 2; + + if(in->buffer) + /* we have a buffer, enlarge the existing one */ + new_rb = Curl_saferealloc(in->buffer, new_size); + else + /* create a new buffer */ + new_rb = malloc(new_size); + + if(!new_rb) { + /* If we failed, we cleanup the whole buffer and return error */ + free(in); + *inp = NULL; + return CURLE_OUT_OF_MEMORY; + } + + in->buffer = new_rb; + in->size_max = new_size; + } + memcpy(&in->buffer[in->size_used], inptr, size); + + in->size_used += size; + + return CURLE_OK; +} + +/* end of the add_buffer functions */ +/* ------------------------------------------------------------------------- */ + + + +/* + * Curl_compareheader() + * + * Returns TRUE if 'headerline' contains the 'header' with given 'content'. + * Pass headers WITH the colon. + */ +bool +Curl_compareheader(const char *headerline, /* line to check */ + const char *header, /* header keyword _with_ colon */ + const char *content) /* content string to find */ +{ + /* RFC2616, section 4.2 says: "Each header field consists of a name followed + * by a colon (":") and the field value. Field names are case-insensitive. + * The field value MAY be preceded by any amount of LWS, though a single SP + * is preferred." */ + + size_t hlen = strlen(header); + size_t clen; + size_t len; + const char *start; + const char *end; + + if(!strncasecompare(headerline, header, hlen)) + return FALSE; /* doesn't start with header */ + + /* pass the header */ + start = &headerline[hlen]; + + /* pass all white spaces */ + while(*start && ISSPACE(*start)) + start++; + + /* find the end of the header line */ + end = strchr(start, '\r'); /* lines end with CRLF */ + if(!end) { + /* in case there's a non-standard compliant line here */ + end = strchr(start, '\n'); + + if(!end) + /* hm, there's no line ending here, use the zero byte! */ + end = strchr(start, '\0'); + } + + len = end-start; /* length of the content part of the input line */ + clen = strlen(content); /* length of the word to find */ + + /* find the content string in the rest of the line */ + for(; len >= clen; len--, start++) { + if(strncasecompare(start, content, clen)) + return TRUE; /* match! */ + } + + return FALSE; /* no match */ +} + +/* + * Curl_http_connect() performs HTTP stuff to do at connect-time, called from + * the generic Curl_connect(). + */ +CURLcode Curl_http_connect(struct connectdata *conn, bool *done) +{ + CURLcode result; + + /* We default to persistent connections. We set this already in this connect + function to make the re-use checks properly be able to check this bit. */ + connkeep(conn, "HTTP default"); + + /* the CONNECT procedure might not have been completed */ + result = Curl_proxy_connect(conn, FIRSTSOCKET); + if(result) + return result; + + if(conn->bits.proxy_connect_closed) + /* this is not an error, just part of the connection negotiation */ + return CURLE_OK; + + if(CONNECT_FIRSTSOCKET_PROXY_SSL()) + return CURLE_OK; /* wait for HTTPS proxy SSL initialization to complete */ + + if(Curl_connect_ongoing(conn)) + /* nothing else to do except wait right now - we're not done here. */ + return CURLE_OK; + +#ifndef CURL_DISABLE_PROXY + if(conn->data->set.haproxyprotocol) { + /* add HAProxy PROXY protocol header */ + result = add_haproxy_protocol_header(conn); + if(result) + return result; + } +#endif + + if(conn->given->protocol & CURLPROTO_HTTPS) { + /* perform SSL initialization */ + result = https_connecting(conn, done); + if(result) + return result; + } + else + *done = TRUE; + + return CURLE_OK; +} + +/* this returns the socket to wait for in the DO and DOING state for the multi + interface and then we're always _sending_ a request and thus we wait for + the single socket to become writable only */ +static int http_getsock_do(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + /* write mode */ + (void)numsocks; /* unused, we trust it to be at least 1 */ + socks[0] = conn->sock[FIRSTSOCKET]; + return GETSOCK_WRITESOCK(0); +} + +#ifndef CURL_DISABLE_PROXY +static CURLcode add_haproxy_protocol_header(struct connectdata *conn) +{ + char proxy_header[128]; + Curl_send_buffer *req_buffer; + CURLcode result; + char tcp_version[5]; + + /* Emit the correct prefix for IPv6 */ + if(conn->bits.ipv6) { + strcpy(tcp_version, "TCP6"); + } + else { + strcpy(tcp_version, "TCP4"); + } + + msnprintf(proxy_header, + sizeof(proxy_header), + "PROXY %s %s %s %li %li\r\n", + tcp_version, + conn->data->info.conn_local_ip, + conn->data->info.conn_primary_ip, + conn->data->info.conn_local_port, + conn->data->info.conn_primary_port); + + req_buffer = Curl_add_buffer_init(); + if(!req_buffer) + return CURLE_OUT_OF_MEMORY; + + result = Curl_add_bufferf(&req_buffer, proxy_header); + if(result) + return result; + + result = Curl_add_buffer_send(&req_buffer, + conn, + &conn->data->info.request_size, + 0, + FIRSTSOCKET); + + return result; +} +#endif + +#ifdef USE_SSL +static CURLcode https_connecting(struct connectdata *conn, bool *done) +{ + CURLcode result; + DEBUGASSERT((conn) && (conn->handler->flags & PROTOPT_SSL)); + + /* perform SSL initialization for this socket */ + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done); + if(result) + connclose(conn, "Failed HTTPS connection"); + + return result; +} + +static int https_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + if(conn->handler->flags & PROTOPT_SSL) + return Curl_ssl_getsock(conn, socks, numsocks); + return GETSOCK_BLANK; +} +#endif /* USE_SSL */ + +/* + * Curl_http_done() gets called after a single HTTP request has been + * performed. + */ + +CURLcode Curl_http_done(struct connectdata *conn, + CURLcode status, bool premature) +{ + struct Curl_easy *data = conn->data; + struct HTTP *http = data->req.protop; + + /* Clear multipass flag. If authentication isn't done yet, then it will get + * a chance to be set back to true when we output the next auth header */ + data->state.authhost.multipass = FALSE; + data->state.authproxy.multipass = FALSE; + + Curl_unencode_cleanup(conn); + + /* set the proper values (possibly modified on POST) */ + conn->seek_func = data->set.seek_func; /* restore */ + conn->seek_client = data->set.seek_client; /* restore */ + + if(!http) + return CURLE_OK; + + if(http->send_buffer) { + Curl_add_buffer_free(&http->send_buffer); + } + + Curl_http2_done(conn, premature); + + Curl_mime_cleanpart(&http->form); + + if(status) + return status; + + if(!premature && /* this check is pointless when DONE is called before the + entire operation is complete */ + !conn->bits.retry && + !data->set.connect_only && + (data->req.bytecount + + data->req.headerbytecount - + data->req.deductheadercount) <= 0) { + /* If this connection isn't simply closed to be retried, AND nothing was + read from the HTTP server (that counts), this can't be right so we + return an error here */ + failf(data, "Empty reply from server"); + return CURLE_GOT_NOTHING; + } + + return CURLE_OK; +} + +/* + * Determine if we should use HTTP 1.1 (OR BETTER) for this request. Reasons + * to avoid it include: + * + * - if the user specifically requested HTTP 1.0 + * - if the server we are connected to only supports 1.0 + * - if any server previously contacted to handle this request only supports + * 1.0. + */ +static bool use_http_1_1plus(const struct Curl_easy *data, + const struct connectdata *conn) +{ + if((data->state.httpversion == 10) || (conn->httpversion == 10)) + return FALSE; + if((data->set.httpversion == CURL_HTTP_VERSION_1_0) && + (conn->httpversion <= 10)) + return FALSE; + return ((data->set.httpversion == CURL_HTTP_VERSION_NONE) || + (data->set.httpversion >= CURL_HTTP_VERSION_1_1)); +} + +static const char *get_http_string(const struct Curl_easy *data, + const struct connectdata *conn) +{ +#ifdef USE_NGHTTP2 + if(conn->proto.httpc.h2) + return "2"; +#endif + + if(use_http_1_1plus(data, conn)) + return "1.1"; + + return "1.0"; +} + +/* check and possibly add an Expect: header */ +static CURLcode expect100(struct Curl_easy *data, + struct connectdata *conn, + Curl_send_buffer *req_buffer) +{ + CURLcode result = CURLE_OK; + data->state.expect100header = FALSE; /* default to false unless it is set + to TRUE below */ + if(use_http_1_1plus(data, conn) && + (conn->httpversion != 20)) { + /* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an + Expect: 100-continue to the headers which actually speeds up post + operations (as there is one packet coming back from the web server) */ + const char *ptr = Curl_checkheaders(conn, "Expect"); + if(ptr) { + data->state.expect100header = + Curl_compareheader(ptr, "Expect:", "100-continue"); + } + else { + result = Curl_add_bufferf(&req_buffer, + "Expect: 100-continue\r\n"); + if(!result) + data->state.expect100header = TRUE; + } + } + + return result; +} + +enum proxy_use { + HEADER_SERVER, /* direct to server */ + HEADER_PROXY, /* regular request to proxy */ + HEADER_CONNECT /* sending CONNECT to a proxy */ +}; + +/* used to compile the provided trailers into one buffer + will return an error code if one of the headers is + not formatted correctly */ +CURLcode Curl_http_compile_trailers(struct curl_slist *trailers, + Curl_send_buffer *buffer, + struct Curl_easy *handle) +{ + char *ptr = NULL; + CURLcode result = CURLE_OK; + const char *endofline_native = NULL; + const char *endofline_network = NULL; + + if( +#ifdef CURL_DO_LINEEND_CONV + (handle->set.prefer_ascii) || +#endif + (handle->set.crlf)) { + /* \n will become \r\n later on */ + endofline_native = "\n"; + endofline_network = "\x0a"; + } + else { + endofline_native = "\r\n"; + endofline_network = "\x0d\x0a"; + } + + while(trailers) { + /* only add correctly formatted trailers */ + ptr = strchr(trailers->data, ':'); + if(ptr && *(ptr + 1) == ' ') { + result = Curl_add_bufferf(&buffer, "%s%s", trailers->data, + endofline_native); + if(result) + return result; + } + else + infof(handle, "Malformatted trailing header ! Skipping trailer."); + trailers = trailers->next; + } + result = Curl_add_buffer(&buffer, endofline_network, + strlen(endofline_network)); + return result; +} + +CURLcode Curl_add_custom_headers(struct connectdata *conn, + bool is_connect, + Curl_send_buffer *req_buffer) +{ + char *ptr; + struct curl_slist *h[2]; + struct curl_slist *headers; + int numlists = 1; /* by default */ + struct Curl_easy *data = conn->data; + int i; + + enum proxy_use proxy; + + if(is_connect) + proxy = HEADER_CONNECT; + else + proxy = conn->bits.httpproxy && !conn->bits.tunnel_proxy? + HEADER_PROXY:HEADER_SERVER; + + switch(proxy) { + case HEADER_SERVER: + h[0] = data->set.headers; + break; + case HEADER_PROXY: + h[0] = data->set.headers; + if(data->set.sep_headers) { + h[1] = data->set.proxyheaders; + numlists++; + } + break; + case HEADER_CONNECT: + if(data->set.sep_headers) + h[0] = data->set.proxyheaders; + else + h[0] = data->set.headers; + break; + } + + /* loop through one or two lists */ + for(i = 0; i < numlists; i++) { + headers = h[i]; + + while(headers) { + char *semicolonp = NULL; + ptr = strchr(headers->data, ':'); + if(!ptr) { + char *optr; + /* no colon, semicolon? */ + ptr = strchr(headers->data, ';'); + if(ptr) { + optr = ptr; + ptr++; /* pass the semicolon */ + while(*ptr && ISSPACE(*ptr)) + ptr++; + + if(*ptr) { + /* this may be used for something else in the future */ + optr = NULL; + } + else { + if(*(--ptr) == ';') { + /* copy the source */ + semicolonp = strdup(headers->data); + if(!semicolonp) { + Curl_add_buffer_free(&req_buffer); + return CURLE_OUT_OF_MEMORY; + } + /* put a colon where the semicolon is */ + semicolonp[ptr - headers->data] = ':'; + /* point at the colon */ + optr = &semicolonp [ptr - headers->data]; + } + } + ptr = optr; + } + } + if(ptr) { + /* we require a colon for this to be a true header */ + + ptr++; /* pass the colon */ + while(*ptr && ISSPACE(*ptr)) + ptr++; + + if(*ptr || semicolonp) { + /* only send this if the contents was non-blank or done special */ + CURLcode result = CURLE_OK; + char *compare = semicolonp ? semicolonp : headers->data; + + if(conn->allocptr.host && + /* a Host: header was sent already, don't pass on any custom Host: + header as that will produce *two* in the same request! */ + checkprefix("Host:", compare)) + ; + else if(data->set.httpreq == HTTPREQ_POST_FORM && + /* this header (extended by formdata.c) is sent later */ + checkprefix("Content-Type:", compare)) + ; + else if(data->set.httpreq == HTTPREQ_POST_MIME && + /* this header is sent later */ + checkprefix("Content-Type:", compare)) + ; + else if(conn->bits.authneg && + /* while doing auth neg, don't allow the custom length since + we will force length zero then */ + checkprefix("Content-Length:", compare)) + ; + else if(conn->allocptr.te && + /* when asking for Transfer-Encoding, don't pass on a custom + Connection: */ + checkprefix("Connection:", compare)) + ; + else if((conn->httpversion == 20) && + checkprefix("Transfer-Encoding:", compare)) + /* HTTP/2 doesn't support chunked requests */ + ; + else if((checkprefix("Authorization:", compare) || + checkprefix("Cookie:", compare)) && + /* be careful of sending this potentially sensitive header to + other hosts */ + (data->state.this_is_a_follow && + data->state.first_host && + !data->set.allow_auth_to_other_hosts && + !strcasecompare(data->state.first_host, conn->host.name))) + ; + else { + result = Curl_add_bufferf(&req_buffer, "%s\r\n", compare); + } + if(semicolonp) + free(semicolonp); + if(result) + return result; + } + } + headers = headers->next; + } + } + + return CURLE_OK; +} + +#ifndef CURL_DISABLE_PARSEDATE +CURLcode Curl_add_timecondition(struct Curl_easy *data, + Curl_send_buffer *req_buffer) +{ + const struct tm *tm; + struct tm keeptime; + CURLcode result; + char datestr[80]; + const char *condp; + + if(data->set.timecondition == CURL_TIMECOND_NONE) + /* no condition was asked for */ + return CURLE_OK; + + result = Curl_gmtime(data->set.timevalue, &keeptime); + if(result) { + failf(data, "Invalid TIMEVALUE"); + return result; + } + tm = &keeptime; + + switch(data->set.timecondition) { + default: + return CURLE_BAD_FUNCTION_ARGUMENT; + + case CURL_TIMECOND_IFMODSINCE: + condp = "If-Modified-Since"; + break; + case CURL_TIMECOND_IFUNMODSINCE: + condp = "If-Unmodified-Since"; + break; + case CURL_TIMECOND_LASTMOD: + condp = "Last-Modified"; + break; + } + + /* The If-Modified-Since header family should have their times set in + * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be + * represented in Greenwich Mean Time (GMT), without exception. For the + * purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal + * Time)." (see page 20 of RFC2616). + */ + + /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ + msnprintf(datestr, sizeof(datestr), + "%s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n", + condp, + Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], + tm->tm_mday, + Curl_month[tm->tm_mon], + tm->tm_year + 1900, + tm->tm_hour, + tm->tm_min, + tm->tm_sec); + + result = Curl_add_buffer(&req_buffer, datestr, strlen(datestr)); + + return result; +} +#else +/* disabled */ +CURLcode Curl_add_timecondition(struct Curl_easy *data, + Curl_send_buffer *req_buffer) +{ + (void)data; + (void)req_buffer; + return CURLE_OK; +} +#endif + +/* + * Curl_http() gets called from the generic multi_do() function when a HTTP + * request is to be performed. This creates and sends a properly constructed + * HTTP request. + */ +CURLcode Curl_http(struct connectdata *conn, bool *done) +{ + struct Curl_easy *data = conn->data; + CURLcode result = CURLE_OK; + struct HTTP *http; + const char *path = data->state.up.path; + const char *query = data->state.up.query; + bool paste_ftp_userpwd = FALSE; + char ftp_typecode[sizeof("/;type=?")] = ""; + const char *host = conn->host.name; + const char *te = ""; /* transfer-encoding */ + const char *ptr; + const char *request; + Curl_HttpReq httpreq = data->set.httpreq; +#if !defined(CURL_DISABLE_COOKIES) + char *addcookies = NULL; +#endif + curl_off_t included_body = 0; + const char *httpstring; + Curl_send_buffer *req_buffer; + curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */ + + /* Always consider the DO phase done after this function call, even if there + may be parts of the request that is not yet sent, since we can deal with + the rest of the request in the PERFORM phase. */ + *done = TRUE; + + if(conn->httpversion < 20) { /* unless the connection is re-used and already + http2 */ + switch(conn->negnpn) { + case CURL_HTTP_VERSION_2: + conn->httpversion = 20; /* we know we're on HTTP/2 now */ + + result = Curl_http2_switched(conn, NULL, 0); + if(result) + return result; + break; + case CURL_HTTP_VERSION_1_1: + /* continue with HTTP/1.1 when explicitly requested */ + break; + default: + /* Check if user wants to use HTTP/2 with clear TCP*/ +#ifdef USE_NGHTTP2 + if(conn->data->set.httpversion == + CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) { + if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) { + /* We don't support HTTP/2 proxies yet. Also it's debatable whether + or not this setting should apply to HTTP/2 proxies. */ + infof(data, "Ignoring HTTP/2 prior knowledge due to proxy\n"); + break; + } + + DEBUGF(infof(data, "HTTP/2 over clean TCP\n")); + conn->httpversion = 20; + + result = Curl_http2_switched(conn, NULL, 0); + if(result) + return result; + } +#endif + break; + } + } + else { + /* prepare for a http2 request */ + result = Curl_http2_setup(conn); + if(result) + return result; + } + + http = data->req.protop; + DEBUGASSERT(http); + + if(!data->state.this_is_a_follow) { + /* Free to avoid leaking memory on multiple requests*/ + free(data->state.first_host); + + data->state.first_host = strdup(conn->host.name); + if(!data->state.first_host) + return CURLE_OUT_OF_MEMORY; + + data->state.first_remote_port = conn->remote_port; + } + + if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) && + data->set.upload) { + httpreq = HTTPREQ_PUT; + } + + /* Now set the 'request' pointer to the proper request string */ + if(data->set.str[STRING_CUSTOMREQUEST]) + request = data->set.str[STRING_CUSTOMREQUEST]; + else { + if(data->set.opt_no_body) + request = "HEAD"; + else { + DEBUGASSERT((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST)); + switch(httpreq) { + case HTTPREQ_POST: + case HTTPREQ_POST_FORM: + case HTTPREQ_POST_MIME: + request = "POST"; + break; + case HTTPREQ_PUT: + request = "PUT"; + break; + case HTTPREQ_OPTIONS: + request = "OPTIONS"; + break; + default: /* this should never happen */ + case HTTPREQ_GET: + request = "GET"; + break; + case HTTPREQ_HEAD: + request = "HEAD"; + break; + } + } + } + + /* The User-Agent string might have been allocated in url.c already, because + it might have been used in the proxy connect, but if we have got a header + with the user-agent string specified, we erase the previously made string + here. */ + if(Curl_checkheaders(conn, "User-Agent")) { + free(conn->allocptr.uagent); + conn->allocptr.uagent = NULL; + } + + /* setup the authentication headers */ + { + char *pq = NULL; + if(query && *query) { + pq = aprintf("%s?%s", path, query); + if(!pq) + return CURLE_OUT_OF_MEMORY; + } + result = Curl_http_output_auth(conn, request, (pq ? pq : path), FALSE); + free(pq); + if(result) + return result; + } + + if(((data->state.authhost.multipass && !data->state.authhost.done) + || (data->state.authproxy.multipass && !data->state.authproxy.done)) && + (httpreq != HTTPREQ_GET) && + (httpreq != HTTPREQ_HEAD)) { + /* Auth is required and we are not authenticated yet. Make a PUT or POST + with content-length zero as a "probe". */ + conn->bits.authneg = TRUE; + } + else + conn->bits.authneg = FALSE; + + Curl_safefree(conn->allocptr.ref); + if(data->change.referer && !Curl_checkheaders(conn, "Referer")) { + conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer); + if(!conn->allocptr.ref) + return CURLE_OUT_OF_MEMORY; + } + else + conn->allocptr.ref = NULL; + +#if !defined(CURL_DISABLE_COOKIES) + if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(conn, "Cookie")) + addcookies = data->set.str[STRING_COOKIE]; +#endif + + if(!Curl_checkheaders(conn, "Accept-Encoding") && + data->set.str[STRING_ENCODING]) { + Curl_safefree(conn->allocptr.accept_encoding); + conn->allocptr.accept_encoding = + aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]); + if(!conn->allocptr.accept_encoding) + return CURLE_OUT_OF_MEMORY; + } + else { + Curl_safefree(conn->allocptr.accept_encoding); + conn->allocptr.accept_encoding = NULL; + } + +#ifdef HAVE_LIBZ + /* we only consider transfer-encoding magic if libz support is built-in */ + + if(!Curl_checkheaders(conn, "TE") && + data->set.http_transfer_encoding) { + /* When we are to insert a TE: header in the request, we must also insert + TE in a Connection: header, so we need to merge the custom provided + Connection: header and prevent the original to get sent. Note that if + the user has inserted his/hers own TE: header we don't do this magic + but then assume that the user will handle it all! */ + char *cptr = Curl_checkheaders(conn, "Connection"); +#define TE_HEADER "TE: gzip\r\n" + + Curl_safefree(conn->allocptr.te); + + if(cptr) { + cptr = Curl_copy_header_value(cptr); + if(!cptr) + return CURLE_OUT_OF_MEMORY; + } + + /* Create the (updated) Connection: header */ + conn->allocptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER, + cptr ? cptr : "", (cptr && *cptr) ? ", ":""); + + free(cptr); + if(!conn->allocptr.te) + return CURLE_OUT_OF_MEMORY; + } +#endif + + switch(httpreq) { + case HTTPREQ_POST_MIME: + http->sendit = &data->set.mimepost; + break; + case HTTPREQ_POST_FORM: + /* Convert the form structure into a mime structure. */ + Curl_mime_cleanpart(&http->form); + result = Curl_getformdata(data, &http->form, data->set.httppost, + data->state.fread_func); + if(result) + return result; + http->sendit = &http->form; + break; + default: + http->sendit = NULL; + } + +#ifndef CURL_DISABLE_MIME + if(http->sendit) { + const char *cthdr = Curl_checkheaders(conn, "Content-Type"); + + /* Read and seek body only. */ + http->sendit->flags |= MIME_BODY_ONLY; + + /* Prepare the mime structure headers & set content type. */ + + if(cthdr) + for(cthdr += 13; *cthdr == ' '; cthdr++) + ; + else if(http->sendit->kind == MIMEKIND_MULTIPART) + cthdr = "multipart/form-data"; + + curl_mime_headers(http->sendit, data->set.headers, 0); + result = Curl_mime_prepare_headers(http->sendit, cthdr, + NULL, MIMESTRATEGY_FORM); + curl_mime_headers(http->sendit, NULL, 0); + if(!result) + result = Curl_mime_rewind(http->sendit); + if(result) + return result; + http->postsize = Curl_mime_size(http->sendit); + } +#endif + + ptr = Curl_checkheaders(conn, "Transfer-Encoding"); + if(ptr) { + /* Some kind of TE is requested, check if 'chunked' is chosen */ + data->req.upload_chunky = + Curl_compareheader(ptr, "Transfer-Encoding:", "chunked"); + } + else { + if((conn->handler->protocol & PROTO_FAMILY_HTTP) && + (((httpreq == HTTPREQ_POST_MIME || httpreq == HTTPREQ_POST_FORM) && + http->postsize < 0) || + (data->set.upload && data->state.infilesize == -1))) { + if(conn->bits.authneg) + /* don't enable chunked during auth neg */ + ; + else if(use_http_1_1plus(data, conn)) { + /* HTTP, upload, unknown file size and not HTTP 1.0 */ + data->req.upload_chunky = TRUE; + } + else { + failf(data, "Chunky upload is not supported by HTTP 1.0"); + return CURLE_UPLOAD_FAILED; + } + } + else { + /* else, no chunky upload */ + data->req.upload_chunky = FALSE; + } + + if(data->req.upload_chunky) + te = "Transfer-Encoding: chunked\r\n"; + } + + Curl_safefree(conn->allocptr.host); + + ptr = Curl_checkheaders(conn, "Host"); + if(ptr && (!data->state.this_is_a_follow || + strcasecompare(data->state.first_host, conn->host.name))) { +#if !defined(CURL_DISABLE_COOKIES) + /* If we have a given custom Host: header, we extract the host name in + order to possibly use it for cookie reasons later on. We only allow the + custom Host: header if this is NOT a redirect, as setting Host: in the + redirected request is being out on thin ice. Except if the host name + is the same as the first one! */ + char *cookiehost = Curl_copy_header_value(ptr); + if(!cookiehost) + return CURLE_OUT_OF_MEMORY; + if(!*cookiehost) + /* ignore empty data */ + free(cookiehost); + else { + /* If the host begins with '[', we start searching for the port after + the bracket has been closed */ + if(*cookiehost == '[') { + char *closingbracket; + /* since the 'cookiehost' is an allocated memory area that will be + freed later we cannot simply increment the pointer */ + memmove(cookiehost, cookiehost + 1, strlen(cookiehost) - 1); + closingbracket = strchr(cookiehost, ']'); + if(closingbracket) + *closingbracket = 0; + } + else { + int startsearch = 0; + char *colon = strchr(cookiehost + startsearch, ':'); + if(colon) + *colon = 0; /* The host must not include an embedded port number */ + } + Curl_safefree(conn->allocptr.cookiehost); + conn->allocptr.cookiehost = cookiehost; + } +#endif + + if(strcmp("Host:", ptr)) { + conn->allocptr.host = aprintf("Host:%s\r\n", &ptr[5]); + if(!conn->allocptr.host) + return CURLE_OUT_OF_MEMORY; + } + else + /* when clearing the header */ + conn->allocptr.host = NULL; + } + else { + /* When building Host: headers, we must put the host name within + [brackets] if the host name is a plain IPv6-address. RFC2732-style. */ + + if(((conn->given->protocol&CURLPROTO_HTTPS) && + (conn->remote_port == PORT_HTTPS)) || + ((conn->given->protocol&CURLPROTO_HTTP) && + (conn->remote_port == PORT_HTTP)) ) + /* if(HTTPS on port 443) OR (HTTP on port 80) then don't include + the port number in the host string */ + conn->allocptr.host = aprintf("Host: %s%s%s\r\n", + conn->bits.ipv6_ip?"[":"", + host, + conn->bits.ipv6_ip?"]":""); + else + conn->allocptr.host = aprintf("Host: %s%s%s:%d\r\n", + conn->bits.ipv6_ip?"[":"", + host, + conn->bits.ipv6_ip?"]":"", + conn->remote_port); + + if(!conn->allocptr.host) + /* without Host: we can't make a nice request */ + return CURLE_OUT_OF_MEMORY; + } + +#ifndef CURL_DISABLE_PROXY + if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) { + /* Using a proxy but does not tunnel through it */ + + /* The path sent to the proxy is in fact the entire URL. But if the remote + host is a IDN-name, we must make sure that the request we produce only + uses the encoded host name! */ + + /* and no fragment part */ + CURLUcode uc; + char *url; + CURLU *h = curl_url_dup(data->state.uh); + if(!h) + return CURLE_OUT_OF_MEMORY; + + if(conn->host.dispname != conn->host.name) { + uc = curl_url_set(h, CURLUPART_HOST, conn->host.name, 0); + if(uc) { + curl_url_cleanup(h); + return CURLE_OUT_OF_MEMORY; + } + } + uc = curl_url_set(h, CURLUPART_FRAGMENT, NULL, 0); + if(uc) { + curl_url_cleanup(h); + return CURLE_OUT_OF_MEMORY; + } + + if(strcasecompare("http", data->state.up.scheme)) { + /* when getting HTTP, we don't want the userinfo the URL */ + uc = curl_url_set(h, CURLUPART_USER, NULL, 0); + if(uc) { + curl_url_cleanup(h); + return CURLE_OUT_OF_MEMORY; + } + uc = curl_url_set(h, CURLUPART_PASSWORD, NULL, 0); + if(uc) { + curl_url_cleanup(h); + return CURLE_OUT_OF_MEMORY; + } + } + /* now extract the new version of the URL */ + uc = curl_url_get(h, CURLUPART_URL, &url, 0); + if(uc) { + curl_url_cleanup(h); + return CURLE_OUT_OF_MEMORY; + } + + if(data->change.url_alloc) + free(data->change.url); + + data->change.url = url; + data->change.url_alloc = TRUE; + + curl_url_cleanup(h); + + if(strcasecompare("ftp", data->state.up.scheme)) { + if(data->set.proxy_transfer_mode) { + /* when doing ftp, append ;type= if not present */ + char *type = strstr(path, ";type="); + if(type && type[6] && type[7] == 0) { + switch(Curl_raw_toupper(type[6])) { + case 'A': + case 'D': + case 'I': + break; + default: + type = NULL; + } + } + if(!type) { + char *p = ftp_typecode; + /* avoid sending invalid URLs like ftp://example.com;type=i if the + * user specified ftp://example.com without the slash */ + if(!*data->state.up.path && path[strlen(path) - 1] != '/') { + *p++ = '/'; + } + msnprintf(p, sizeof(ftp_typecode) - 1, ";type=%c", + data->set.prefer_ascii ? 'a' : 'i'); + } + } + if(conn->bits.user_passwd && !conn->bits.userpwd_in_url) + paste_ftp_userpwd = TRUE; + } + } +#endif /* CURL_DISABLE_PROXY */ + + http->p_accept = Curl_checkheaders(conn, "Accept")?NULL:"Accept: */*\r\n"; + + if((HTTPREQ_POST == httpreq || HTTPREQ_PUT == httpreq) && + data->state.resume_from) { + /********************************************************************** + * Resuming upload in HTTP means that we PUT or POST and that we have + * got a resume_from value set. The resume value has already created + * a Range: header that will be passed along. We need to "fast forward" + * the file the given number of bytes and decrease the assume upload + * file size before we continue this venture in the dark lands of HTTP. + * Resuming mime/form posting at an offset > 0 has no sense and is ignored. + *********************************************************************/ + + if(data->state.resume_from < 0) { + /* + * This is meant to get the size of the present remote-file by itself. + * We don't support this now. Bail out! + */ + data->state.resume_from = 0; + } + + if(data->state.resume_from && !data->state.this_is_a_follow) { + /* do we still game? */ + + /* Now, let's read off the proper amount of bytes from the + input. */ + int seekerr = CURL_SEEKFUNC_CANTSEEK; + if(conn->seek_func) { + Curl_set_in_callback(data, true); + seekerr = conn->seek_func(conn->seek_client, data->state.resume_from, + SEEK_SET); + Curl_set_in_callback(data, false); + } + + if(seekerr != CURL_SEEKFUNC_OK) { + curl_off_t passed = 0; + + if(seekerr != CURL_SEEKFUNC_CANTSEEK) { + failf(data, "Could not seek stream"); + return CURLE_READ_ERROR; + } + /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ + do { + size_t readthisamountnow = + (data->state.resume_from - passed > data->set.buffer_size) ? + (size_t)data->set.buffer_size : + curlx_sotouz(data->state.resume_from - passed); + + size_t actuallyread = + data->state.fread_func(data->state.buffer, 1, readthisamountnow, + data->state.in); + + passed += actuallyread; + if((actuallyread == 0) || (actuallyread > readthisamountnow)) { + /* this checks for greater-than only to make sure that the + CURL_READFUNC_ABORT return code still aborts */ + failf(data, "Could only read %" CURL_FORMAT_CURL_OFF_T + " bytes from the input", passed); + return CURLE_READ_ERROR; + } + } while(passed < data->state.resume_from); + } + + /* now, decrease the size of the read */ + if(data->state.infilesize>0) { + data->state.infilesize -= data->state.resume_from; + + if(data->state.infilesize <= 0) { + failf(data, "File already completely uploaded"); + return CURLE_PARTIAL_FILE; + } + } + /* we've passed, proceed as normal */ + } + } + if(data->state.use_range) { + /* + * A range is selected. We use different headers whether we're downloading + * or uploading and we always let customized headers override our internal + * ones if any such are specified. + */ + if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) && + !Curl_checkheaders(conn, "Range")) { + /* if a line like this was already allocated, free the previous one */ + free(conn->allocptr.rangeline); + conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", + data->state.range); + } + else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) && + !Curl_checkheaders(conn, "Content-Range")) { + + /* if a line like this was already allocated, free the previous one */ + free(conn->allocptr.rangeline); + + if(data->set.set_resume_from < 0) { + /* Upload resume was asked for, but we don't know the size of the + remote part so we tell the server (and act accordingly) that we + upload the whole file (again) */ + conn->allocptr.rangeline = + aprintf("Content-Range: bytes 0-%" CURL_FORMAT_CURL_OFF_T + "/%" CURL_FORMAT_CURL_OFF_T "\r\n", + data->state.infilesize - 1, data->state.infilesize); + + } + else if(data->state.resume_from) { + /* This is because "resume" was selected */ + curl_off_t total_expected_size = + data->state.resume_from + data->state.infilesize; + conn->allocptr.rangeline = + aprintf("Content-Range: bytes %s%" CURL_FORMAT_CURL_OFF_T + "/%" CURL_FORMAT_CURL_OFF_T "\r\n", + data->state.range, total_expected_size-1, + total_expected_size); + } + else { + /* Range was selected and then we just pass the incoming range and + append total size */ + conn->allocptr.rangeline = + aprintf("Content-Range: bytes %s/%" CURL_FORMAT_CURL_OFF_T "\r\n", + data->state.range, data->state.infilesize); + } + if(!conn->allocptr.rangeline) + return CURLE_OUT_OF_MEMORY; + } + } + + httpstring = get_http_string(data, conn); + + /* initialize a dynamic send-buffer */ + req_buffer = Curl_add_buffer_init(); + + if(!req_buffer) + return CURLE_OUT_OF_MEMORY; + + /* add the main request stuff */ + /* GET/HEAD/POST/PUT */ + result = Curl_add_bufferf(&req_buffer, "%s ", request); + if(result) + return result; + + if(data->set.str[STRING_TARGET]) { + path = data->set.str[STRING_TARGET]; + query = NULL; + } + + /* url */ + if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) { + char *url = data->change.url; + result = Curl_add_buffer(&req_buffer, url, strlen(url)); + } + else if(paste_ftp_userpwd) + result = Curl_add_bufferf(&req_buffer, "ftp://%s:%s@%s", + conn->user, conn->passwd, + path + sizeof("ftp://") - 1); + else { + result = Curl_add_buffer(&req_buffer, path, strlen(path)); + if(result) + return result; + if(query) + result = Curl_add_bufferf(&req_buffer, "?%s", query); + } + if(result) + return result; + + result = + Curl_add_bufferf(&req_buffer, + "%s" /* ftp typecode (;type=x) */ + " HTTP/%s\r\n" /* HTTP version */ + "%s" /* host */ + "%s" /* proxyuserpwd */ + "%s" /* userpwd */ + "%s" /* range */ + "%s" /* user agent */ + "%s" /* accept */ + "%s" /* TE: */ + "%s" /* accept-encoding */ + "%s" /* referer */ + "%s" /* Proxy-Connection */ + "%s",/* transfer-encoding */ + + ftp_typecode, + httpstring, + (conn->allocptr.host?conn->allocptr.host:""), + conn->allocptr.proxyuserpwd? + conn->allocptr.proxyuserpwd:"", + conn->allocptr.userpwd?conn->allocptr.userpwd:"", + (data->state.use_range && conn->allocptr.rangeline)? + conn->allocptr.rangeline:"", + (data->set.str[STRING_USERAGENT] && + *data->set.str[STRING_USERAGENT] && + conn->allocptr.uagent)? + conn->allocptr.uagent:"", + http->p_accept?http->p_accept:"", + conn->allocptr.te?conn->allocptr.te:"", + (data->set.str[STRING_ENCODING] && + *data->set.str[STRING_ENCODING] && + conn->allocptr.accept_encoding)? + conn->allocptr.accept_encoding:"", + (data->change.referer && conn->allocptr.ref)? + conn->allocptr.ref:"" /* Referer: */, + (conn->bits.httpproxy && + !conn->bits.tunnel_proxy && + !Curl_checkProxyheaders(conn, "Proxy-Connection"))? + "Proxy-Connection: Keep-Alive\r\n":"", + te + ); + + /* clear userpwd and proxyuserpwd to avoid re-using old credentials + * from re-used connections */ + Curl_safefree(conn->allocptr.userpwd); + Curl_safefree(conn->allocptr.proxyuserpwd); + + if(result) + return result; + + if(!(conn->handler->flags&PROTOPT_SSL) && + conn->httpversion != 20 && + (data->set.httpversion == CURL_HTTP_VERSION_2)) { + /* append HTTP2 upgrade magic stuff to the HTTP request if it isn't done + over SSL */ + result = Curl_http2_request_upgrade(req_buffer, conn); + if(result) + return result; + } + +#if !defined(CURL_DISABLE_COOKIES) + if(data->cookies || addcookies) { + struct Cookie *co = NULL; /* no cookies from start */ + int count = 0; + + if(data->cookies) { + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + co = Curl_cookie_getlist(data->cookies, + conn->allocptr.cookiehost? + conn->allocptr.cookiehost:host, + data->state.up.path, + (conn->handler->protocol&CURLPROTO_HTTPS)? + TRUE:FALSE); + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + } + if(co) { + struct Cookie *store = co; + /* now loop through all cookies that matched */ + while(co) { + if(co->value) { + if(0 == count) { + result = Curl_add_bufferf(&req_buffer, "Cookie: "); + if(result) + break; + } + result = Curl_add_bufferf(&req_buffer, + "%s%s=%s", count?"; ":"", + co->name, co->value); + if(result) + break; + count++; + } + co = co->next; /* next cookie please */ + } + Curl_cookie_freelist(store); + } + if(addcookies && !result) { + if(!count) + result = Curl_add_bufferf(&req_buffer, "Cookie: "); + if(!result) { + result = Curl_add_bufferf(&req_buffer, "%s%s", count?"; ":"", + addcookies); + count++; + } + } + if(count && !result) + result = Curl_add_buffer(&req_buffer, "\r\n", 2); + + if(result) + return result; + } +#endif + + result = Curl_add_timecondition(data, req_buffer); + if(result) + return result; + + result = Curl_add_custom_headers(conn, FALSE, req_buffer); + if(result) + return result; + + http->postdata = NULL; /* nothing to post at this point */ + Curl_pgrsSetUploadSize(data, -1); /* upload size is unknown atm */ + + /* If 'authdone' is FALSE, we must not set the write socket index to the + Curl_transfer() call below, as we're not ready to actually upload any + data yet. */ + + switch(httpreq) { + + case HTTPREQ_PUT: /* Let's PUT the data to the server! */ + + if(conn->bits.authneg) + postsize = 0; + else + postsize = data->state.infilesize; + + if((postsize != -1) && !data->req.upload_chunky && + (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) { + /* only add Content-Length if not uploading chunked */ + result = Curl_add_bufferf(&req_buffer, + "Content-Length: %" CURL_FORMAT_CURL_OFF_T + "\r\n", postsize); + if(result) + return result; + } + + if(postsize != 0) { + result = expect100(data, conn, req_buffer); + if(result) + return result; + } + + result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers */ + if(result) + return result; + + /* set the upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, postsize); + + /* this sends the buffer and frees all the buffer resources */ + result = Curl_add_buffer_send(&req_buffer, conn, + &data->info.request_size, 0, FIRSTSOCKET); + if(result) + failf(data, "Failed sending PUT request"); + else + /* prepare for transfer */ + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, + postsize?FIRSTSOCKET:-1); + if(result) + return result; + break; + + case HTTPREQ_POST_FORM: + case HTTPREQ_POST_MIME: + /* This is form posting using mime data. */ + if(conn->bits.authneg) { + /* nothing to post! */ + result = Curl_add_bufferf(&req_buffer, "Content-Length: 0\r\n\r\n"); + if(result) + return result; + + result = Curl_add_buffer_send(&req_buffer, conn, + &data->info.request_size, 0, FIRSTSOCKET); + if(result) + failf(data, "Failed sending POST request"); + else + /* setup variables for the upcoming transfer */ + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1); + break; + } + + data->state.infilesize = postsize = http->postsize; + + /* We only set Content-Length and allow a custom Content-Length if + we don't upload data chunked, as RFC2616 forbids us to set both + kinds of headers (Transfer-Encoding: chunked and Content-Length) */ + if(postsize != -1 && !data->req.upload_chunky && + (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) { + /* we allow replacing this header if not during auth negotiation, + although it isn't very wise to actually set your own */ + result = Curl_add_bufferf(&req_buffer, + "Content-Length: %" CURL_FORMAT_CURL_OFF_T + "\r\n", postsize); + if(result) + return result; + } + +#ifndef CURL_DISABLE_MIME + /* Output mime-generated headers. */ + { + struct curl_slist *hdr; + + for(hdr = http->sendit->curlheaders; hdr; hdr = hdr->next) { + result = Curl_add_bufferf(&req_buffer, "%s\r\n", hdr->data); + if(result) + return result; + } + } +#endif + + /* For really small posts we don't use Expect: headers at all, and for + the somewhat bigger ones we allow the app to disable it. Just make + sure that the expect100header is always set to the preferred value + here. */ + ptr = Curl_checkheaders(conn, "Expect"); + if(ptr) { + data->state.expect100header = + Curl_compareheader(ptr, "Expect:", "100-continue"); + } + else if(postsize > EXPECT_100_THRESHOLD || postsize < 0) { + result = expect100(data, conn, req_buffer); + if(result) + return result; + } + else + data->state.expect100header = FALSE; + + /* make the request end in a true CRLF */ + result = Curl_add_buffer(&req_buffer, "\r\n", 2); + if(result) + return result; + + /* set the upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, postsize); + + /* Read from mime structure. */ + data->state.fread_func = (curl_read_callback) Curl_mime_read; + data->state.in = (void *) http->sendit; + http->sending = HTTPSEND_BODY; + + /* this sends the buffer and frees all the buffer resources */ + result = Curl_add_buffer_send(&req_buffer, conn, + &data->info.request_size, 0, FIRSTSOCKET); + if(result) + failf(data, "Failed sending POST request"); + else + /* prepare for transfer */ + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, + postsize?FIRSTSOCKET:-1); + if(result) + return result; + + break; + + case HTTPREQ_POST: + /* this is the simple POST, using x-www-form-urlencoded style */ + + if(conn->bits.authneg) + postsize = 0; + else + /* the size of the post body */ + postsize = data->state.infilesize; + + /* We only set Content-Length and allow a custom Content-Length if + we don't upload data chunked, as RFC2616 forbids us to set both + kinds of headers (Transfer-Encoding: chunked and Content-Length) */ + if((postsize != -1) && !data->req.upload_chunky && + (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) { + /* we allow replacing this header if not during auth negotiation, + although it isn't very wise to actually set your own */ + result = Curl_add_bufferf(&req_buffer, + "Content-Length: %" CURL_FORMAT_CURL_OFF_T + "\r\n", postsize); + if(result) + return result; + } + + if(!Curl_checkheaders(conn, "Content-Type")) { + result = Curl_add_bufferf(&req_buffer, + "Content-Type: application/" + "x-www-form-urlencoded\r\n"); + if(result) + return result; + } + + /* For really small posts we don't use Expect: headers at all, and for + the somewhat bigger ones we allow the app to disable it. Just make + sure that the expect100header is always set to the preferred value + here. */ + ptr = Curl_checkheaders(conn, "Expect"); + if(ptr) { + data->state.expect100header = + Curl_compareheader(ptr, "Expect:", "100-continue"); + } + else if(postsize > EXPECT_100_THRESHOLD || postsize < 0) { + result = expect100(data, conn, req_buffer); + if(result) + return result; + } + else + data->state.expect100header = FALSE; + + if(data->set.postfields) { + + /* In HTTP2, we send request body in DATA frame regardless of + its size. */ + if(conn->httpversion != 20 && + !data->state.expect100header && + (postsize < MAX_INITIAL_POST_SIZE)) { + /* if we don't use expect: 100 AND + postsize is less than MAX_INITIAL_POST_SIZE + + then append the post data to the HTTP request header. This limit + is no magic limit but only set to prevent really huge POSTs to + get the data duplicated with malloc() and family. */ + + result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers! */ + if(result) + return result; + + if(!data->req.upload_chunky) { + /* We're not sending it 'chunked', append it to the request + already now to reduce the number if send() calls */ + result = Curl_add_buffer(&req_buffer, data->set.postfields, + (size_t)postsize); + included_body = postsize; + } + else { + if(postsize) { + /* Append the POST data chunky-style */ + result = Curl_add_bufferf(&req_buffer, "%x\r\n", (int)postsize); + if(!result) { + result = Curl_add_buffer(&req_buffer, data->set.postfields, + (size_t)postsize); + if(!result) + result = Curl_add_buffer(&req_buffer, "\r\n", 2); + included_body = postsize + 2; + } + } + if(!result) + result = Curl_add_buffer(&req_buffer, "\x30\x0d\x0a\x0d\x0a", 5); + /* 0 CR LF CR LF */ + included_body += 5; + } + if(result) + return result; + /* Make sure the progress information is accurate */ + Curl_pgrsSetUploadSize(data, postsize); + } + else { + /* A huge POST coming up, do data separate from the request */ + http->postsize = postsize; + http->postdata = data->set.postfields; + + http->sending = HTTPSEND_BODY; + + data->state.fread_func = (curl_read_callback)readmoredata; + data->state.in = (void *)conn; + + /* set the upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, http->postsize); + + result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers! */ + if(result) + return result; + } + } + else { + result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers! */ + if(result) + return result; + + if(data->req.upload_chunky && conn->bits.authneg) { + /* Chunky upload is selected and we're negotiating auth still, send + end-of-data only */ + result = Curl_add_buffer(&req_buffer, + "\x30\x0d\x0a\x0d\x0a", 5); + /* 0 CR LF CR LF */ + if(result) + return result; + } + + else if(data->state.infilesize) { + /* set the upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, postsize?postsize:-1); + + /* set the pointer to mark that we will send the post body using the + read callback, but only if we're not in authenticate + negotiation */ + if(!conn->bits.authneg) { + http->postdata = (char *)&http->postdata; + http->postsize = postsize; + } + } + } + /* issue the request */ + result = Curl_add_buffer_send(&req_buffer, conn, &data->info.request_size, + (size_t)included_body, FIRSTSOCKET); + + if(result) + failf(data, "Failed sending HTTP POST request"); + else + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, + http->postdata?FIRSTSOCKET:-1); + break; + + default: + result = Curl_add_buffer(&req_buffer, "\r\n", 2); + if(result) + return result; + + /* issue the request */ + result = Curl_add_buffer_send(&req_buffer, conn, + &data->info.request_size, 0, FIRSTSOCKET); + + if(result) + failf(data, "Failed sending HTTP request"); + else + /* HTTP GET/HEAD download: */ + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, + http->postdata?FIRSTSOCKET:-1); + } + if(result) + return result; + + if(data->req.writebytecount) { + /* if a request-body has been sent off, we make sure this progress is noted + properly */ + Curl_pgrsSetUploadCounter(data, data->req.writebytecount); + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + + if(data->req.writebytecount >= postsize) { + /* already sent the entire request body, mark the "upload" as + complete */ + infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T + " out of %" CURL_FORMAT_CURL_OFF_T " bytes\n", + data->req.writebytecount, postsize); + data->req.upload_done = TRUE; + data->req.keepon &= ~KEEP_SEND; /* we're done writing */ + data->req.exp100 = EXP100_SEND_DATA; /* already sent */ + Curl_expire_done(data, EXPIRE_100_TIMEOUT); + } + } + + if((conn->httpversion == 20) && data->req.upload_chunky) + /* upload_chunky was set above to set up the request in a chunky fashion, + but is disabled here again to avoid that the chunked encoded version is + actually used when sending the request body over h2 */ + data->req.upload_chunky = FALSE; + return result; +} + +typedef enum { + STATUS_UNKNOWN, /* not enough data to tell yet */ + STATUS_DONE, /* a status line was read */ + STATUS_BAD /* not a status line */ +} statusline; + + +/* Check a string for a prefix. Check no more than 'len' bytes */ +static bool checkprefixmax(const char *prefix, const char *buffer, size_t len) +{ + size_t ch = CURLMIN(strlen(prefix), len); + return curl_strnequal(prefix, buffer, ch); +} + +/* + * checkhttpprefix() + * + * Returns TRUE if member of the list matches prefix of string + */ +static statusline +checkhttpprefix(struct Curl_easy *data, + const char *s, size_t len) +{ + struct curl_slist *head = data->set.http200aliases; + statusline rc = STATUS_BAD; + statusline onmatch = len >= 5? STATUS_DONE : STATUS_UNKNOWN; +#ifdef CURL_DOES_CONVERSIONS + /* convert from the network encoding using a scratch area */ + char *scratch = strdup(s); + if(NULL == scratch) { + failf(data, "Failed to allocate memory for conversion!"); + return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */ + } + if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s) + 1)) { + /* Curl_convert_from_network calls failf if unsuccessful */ + free(scratch); + return FALSE; /* can't return CURLE_foobar so return FALSE */ + } + s = scratch; +#endif /* CURL_DOES_CONVERSIONS */ + + while(head) { + if(checkprefixmax(head->data, s, len)) { + rc = onmatch; + break; + } + head = head->next; + } + + if((rc != STATUS_DONE) && (checkprefixmax("HTTP/", s, len))) + rc = onmatch; + +#ifdef CURL_DOES_CONVERSIONS + free(scratch); +#endif /* CURL_DOES_CONVERSIONS */ + return rc; +} + +#ifndef CURL_DISABLE_RTSP +static statusline +checkrtspprefix(struct Curl_easy *data, + const char *s, size_t len) +{ + statusline result = STATUS_BAD; + statusline onmatch = len >= 5? STATUS_DONE : STATUS_UNKNOWN; + +#ifdef CURL_DOES_CONVERSIONS + /* convert from the network encoding using a scratch area */ + char *scratch = strdup(s); + if(NULL == scratch) { + failf(data, "Failed to allocate memory for conversion!"); + return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */ + } + if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s) + 1)) { + /* Curl_convert_from_network calls failf if unsuccessful */ + result = FALSE; /* can't return CURLE_foobar so return FALSE */ + } + else if(checkprefixmax("RTSP/", scratch, len)) + result = onmatch; + free(scratch); +#else + (void)data; /* unused */ + if(checkprefixmax("RTSP/", s, len)) + result = onmatch; +#endif /* CURL_DOES_CONVERSIONS */ + + return result; +} +#endif /* CURL_DISABLE_RTSP */ + +static statusline +checkprotoprefix(struct Curl_easy *data, struct connectdata *conn, + const char *s, size_t len) +{ +#ifndef CURL_DISABLE_RTSP + if(conn->handler->protocol & CURLPROTO_RTSP) + return checkrtspprefix(data, s, len); +#else + (void)conn; +#endif /* CURL_DISABLE_RTSP */ + + return checkhttpprefix(data, s, len); +} + +/* + * header_append() copies a chunk of data to the end of the already received + * header. We make sure that the full string fit in the allocated header + * buffer, or else we enlarge it. + */ +static CURLcode header_append(struct Curl_easy *data, + struct SingleRequest *k, + size_t length) +{ + size_t newsize = k->hbuflen + length; + if(newsize > CURL_MAX_HTTP_HEADER) { + /* The reason to have a max limit for this is to avoid the risk of a bad + server feeding libcurl with a never-ending header that will cause + reallocs infinitely */ + failf(data, "Rejected %zu bytes header (max is %d)!", newsize, + CURL_MAX_HTTP_HEADER); + return CURLE_OUT_OF_MEMORY; + } + if(newsize >= data->state.headersize) { + /* We enlarge the header buffer as it is too small */ + char *newbuff; + size_t hbufp_index; + + newsize = CURLMAX((k->hbuflen + length) * 3 / 2, data->state.headersize*2); + hbufp_index = k->hbufp - data->state.headerbuff; + newbuff = realloc(data->state.headerbuff, newsize); + if(!newbuff) { + failf(data, "Failed to alloc memory for big header!"); + return CURLE_OUT_OF_MEMORY; + } + data->state.headersize = newsize; + data->state.headerbuff = newbuff; + k->hbufp = data->state.headerbuff + hbufp_index; + } + memcpy(k->hbufp, k->str_start, length); + k->hbufp += length; + k->hbuflen += length; + *k->hbufp = 0; + + return CURLE_OK; +} + +static void print_http_error(struct Curl_easy *data) +{ + struct SingleRequest *k = &data->req; + char *beg = k->p; + + /* make sure that data->req.p points to the HTTP status line */ + if(!strncmp(beg, "HTTP", 4)) { + + /* skip to HTTP status code */ + beg = strchr(beg, ' '); + if(beg && *++beg) { + + /* find trailing CR */ + char end_char = '\r'; + char *end = strchr(beg, end_char); + if(!end) { + /* try to find LF (workaround for non-compliant HTTP servers) */ + end_char = '\n'; + end = strchr(beg, end_char); + } + + if(end) { + /* temporarily replace CR or LF by NUL and print the error message */ + *end = '\0'; + failf(data, "The requested URL returned error: %s", beg); + + /* restore the previously replaced CR or LF */ + *end = end_char; + return; + } + } + } + + /* fall-back to printing the HTTP status code only */ + failf(data, "The requested URL returned error: %d", k->httpcode); +} + +/* + * Read any HTTP header lines from the server and pass them to the client app. + */ +CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, + struct connectdata *conn, + ssize_t *nread, + bool *stop_reading) +{ + CURLcode result; + struct SingleRequest *k = &data->req; + ssize_t onread = *nread; + char *ostr = k->str; + + /* header line within buffer loop */ + do { + size_t rest_length; + size_t full_length; + int writetype; + + /* str_start is start of line within buf */ + k->str_start = k->str; + + /* data is in network encoding so use 0x0a instead of '\n' */ + k->end_ptr = memchr(k->str_start, 0x0a, *nread); + + if(!k->end_ptr) { + /* Not a complete header line within buffer, append the data to + the end of the headerbuff. */ + result = header_append(data, k, *nread); + if(result) + return result; + + if(!k->headerline) { + /* check if this looks like a protocol header */ + statusline st = checkprotoprefix(data, conn, data->state.headerbuff, + k->hbuflen); + if(st == STATUS_BAD) { + /* this is not the beginning of a protocol first header line */ + k->header = FALSE; + k->badheader = HEADER_ALLBAD; + streamclose(conn, "bad HTTP: No end-of-message indicator"); + if(!data->set.http09_allowed) { + failf(data, "Received HTTP/0.9 when not allowed\n"); + return CURLE_UNSUPPORTED_PROTOCOL; + } + break; + } + } + + break; /* read more and try again */ + } + + /* decrease the size of the remaining (supposed) header line */ + rest_length = (k->end_ptr - k->str) + 1; + *nread -= (ssize_t)rest_length; + + k->str = k->end_ptr + 1; /* move past new line */ + + full_length = k->str - k->str_start; + + result = header_append(data, k, full_length); + if(result) + return result; + + k->end_ptr = k->hbufp; + k->p = data->state.headerbuff; + + /**** + * We now have a FULL header line that p points to + *****/ + + if(!k->headerline) { + /* the first read header */ + statusline st = checkprotoprefix(data, conn, data->state.headerbuff, + k->hbuflen); + if(st == STATUS_BAD) { + streamclose(conn, "bad HTTP: No end-of-message indicator"); + /* this is not the beginning of a protocol first header line */ + if(!data->set.http09_allowed) { + failf(data, "Received HTTP/0.9 when not allowed\n"); + return CURLE_UNSUPPORTED_PROTOCOL; + } + k->header = FALSE; + if(*nread) + /* since there's more, this is a partial bad header */ + k->badheader = HEADER_PARTHEADER; + else { + /* this was all we read so it's all a bad header */ + k->badheader = HEADER_ALLBAD; + *nread = onread; + k->str = ostr; + return CURLE_OK; + } + break; + } + } + + /* headers are in network encoding so + use 0x0a and 0x0d instead of '\n' and '\r' */ + if((0x0a == *k->p) || (0x0d == *k->p)) { + size_t headerlen; + /* Zero-length header line means end of headers! */ + +#ifdef CURL_DOES_CONVERSIONS + if(0x0d == *k->p) { + *k->p = '\r'; /* replace with CR in host encoding */ + k->p++; /* pass the CR byte */ + } + if(0x0a == *k->p) { + *k->p = '\n'; /* replace with LF in host encoding */ + k->p++; /* pass the LF byte */ + } +#else + if('\r' == *k->p) + k->p++; /* pass the \r byte */ + if('\n' == *k->p) + k->p++; /* pass the \n byte */ +#endif /* CURL_DOES_CONVERSIONS */ + + if(100 <= k->httpcode && 199 >= k->httpcode) { + /* "A user agent MAY ignore unexpected 1xx status responses." */ + switch(k->httpcode) { + case 100: + /* + * We have made a HTTP PUT or POST and this is 1.1-lingo + * that tells us that the server is OK with this and ready + * to receive the data. + * However, we'll get more headers now so we must get + * back into the header-parsing state! + */ + k->header = TRUE; + k->headerline = 0; /* restart the header line counter */ + + /* if we did wait for this do enable write now! */ + if(k->exp100 > EXP100_SEND_DATA) { + k->exp100 = EXP100_SEND_DATA; + k->keepon |= KEEP_SEND; + Curl_expire_done(data, EXPIRE_100_TIMEOUT); + } + break; + case 101: + /* Switching Protocols */ + if(k->upgr101 == UPGR101_REQUESTED) { + /* Switching to HTTP/2 */ + infof(data, "Received 101\n"); + k->upgr101 = UPGR101_RECEIVED; + + /* we'll get more headers (HTTP/2 response) */ + k->header = TRUE; + k->headerline = 0; /* restart the header line counter */ + + /* switch to http2 now. The bytes after response headers + are also processed here, otherwise they are lost. */ + result = Curl_http2_switched(conn, k->str, *nread); + if(result) + return result; + *nread = 0; + } + else { + /* Switching to another protocol (e.g. WebSocket) */ + k->header = FALSE; /* no more header to parse! */ + } + break; + default: + /* the status code 1xx indicates a provisional response, so + we'll get another set of headers */ + k->header = TRUE; + k->headerline = 0; /* restart the header line counter */ + break; + } + } + else { + k->header = FALSE; /* no more header to parse! */ + + if((k->size == -1) && !k->chunk && !conn->bits.close && + (conn->httpversion == 11) && + !(conn->handler->protocol & CURLPROTO_RTSP) && + data->set.httpreq != HTTPREQ_HEAD) { + /* On HTTP 1.1, when connection is not to get closed, but no + Content-Length nor Transfer-Encoding chunked have been + received, according to RFC2616 section 4.4 point 5, we + assume that the server will close the connection to + signal the end of the document. */ + infof(data, "no chunk, no close, no size. Assume close to " + "signal end\n"); + streamclose(conn, "HTTP: No end-of-message indicator"); + } + } + + /* At this point we have some idea about the fate of the connection. + If we are closing the connection it may result auth failure. */ +#if defined(USE_NTLM) + if(conn->bits.close && + (((data->req.httpcode == 401) && + (conn->http_ntlm_state == NTLMSTATE_TYPE2)) || + ((data->req.httpcode == 407) && + (conn->proxy_ntlm_state == NTLMSTATE_TYPE2)))) { + infof(data, "Connection closure while negotiating auth (HTTP 1.0?)\n"); + data->state.authproblem = TRUE; + } +#endif +#if defined(USE_SPNEGO) + if(conn->bits.close && + (((data->req.httpcode == 401) && + (conn->http_negotiate_state == GSS_AUTHRECV)) || + ((data->req.httpcode == 407) && + (conn->proxy_negotiate_state == GSS_AUTHRECV)))) { + infof(data, "Connection closure while negotiating auth (HTTP 1.0?)\n"); + data->state.authproblem = TRUE; + } + if((conn->http_negotiate_state == GSS_AUTHDONE) && + (data->req.httpcode != 401)) { + conn->http_negotiate_state = GSS_AUTHSUCC; + } + if((conn->proxy_negotiate_state == GSS_AUTHDONE) && + (data->req.httpcode != 407)) { + conn->proxy_negotiate_state = GSS_AUTHSUCC; + } +#endif + /* + * When all the headers have been parsed, see if we should give + * up and return an error. + */ + if(http_should_fail(conn)) { + failf(data, "The requested URL returned error: %d", + k->httpcode); + return CURLE_HTTP_RETURNED_ERROR; + } + + /* now, only output this if the header AND body are requested: + */ + writetype = CLIENTWRITE_HEADER; + if(data->set.include_header) + writetype |= CLIENTWRITE_BODY; + + headerlen = k->p - data->state.headerbuff; + + result = Curl_client_write(conn, writetype, + data->state.headerbuff, + headerlen); + if(result) + return result; + + data->info.header_size += (long)headerlen; + data->req.headerbytecount += (long)headerlen; + + data->req.deductheadercount = + (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0; + + /* Curl_http_auth_act() checks what authentication methods + * that are available and decides which one (if any) to + * use. It will set 'newurl' if an auth method was picked. */ + result = Curl_http_auth_act(conn); + + if(result) + return result; + + if(k->httpcode >= 300) { + if((!conn->bits.authneg) && !conn->bits.close && + !conn->bits.rewindaftersend) { + /* + * General treatment of errors when about to send data. Including : + * "417 Expectation Failed", while waiting for 100-continue. + * + * The check for close above is done simply because of something + * else has already deemed the connection to get closed then + * something else should've considered the big picture and we + * avoid this check. + * + * rewindaftersend indicates that something has told libcurl to + * continue sending even if it gets discarded + */ + + switch(data->set.httpreq) { + case HTTPREQ_PUT: + case HTTPREQ_POST: + case HTTPREQ_POST_FORM: + case HTTPREQ_POST_MIME: + /* We got an error response. If this happened before the whole + * request body has been sent we stop sending and mark the + * connection for closure after we've read the entire response. + */ + Curl_expire_done(data, EXPIRE_100_TIMEOUT); + if(!k->upload_done) { + if(data->set.http_keep_sending_on_error) { + infof(data, "HTTP error before end of send, keep sending\n"); + if(k->exp100 > EXP100_SEND_DATA) { + k->exp100 = EXP100_SEND_DATA; + k->keepon |= KEEP_SEND; + } + } + else { + infof(data, "HTTP error before end of send, stop sending\n"); + streamclose(conn, "Stop sending data before everything sent"); + k->upload_done = TRUE; + k->keepon &= ~KEEP_SEND; /* don't send */ + if(data->state.expect100header) + k->exp100 = EXP100_FAILED; + } + } + break; + + default: /* default label present to avoid compiler warnings */ + break; + } + } + + if(conn->bits.rewindaftersend) { + /* We rewind after a complete send, so thus we continue + sending now */ + infof(data, "Keep sending data to get tossed away!\n"); + k->keepon |= KEEP_SEND; + } + } + + if(!k->header) { + /* + * really end-of-headers. + * + * If we requested a "no body", this is a good time to get + * out and return home. + */ + if(data->set.opt_no_body) + *stop_reading = TRUE; +#ifndef CURL_DISABLE_RTSP + else if((conn->handler->protocol & CURLPROTO_RTSP) && + (data->set.rtspreq == RTSPREQ_DESCRIBE) && + (k->size <= -1)) + /* Respect section 4.4 of rfc2326: If the Content-Length header is + absent, a length 0 must be assumed. It will prevent libcurl from + hanging on DESCRIBE request that got refused for whatever + reason */ + *stop_reading = TRUE; +#endif + else { + /* If we know the expected size of this document, we set the + maximum download size to the size of the expected + document or else, we won't know when to stop reading! + + Note that we set the download maximum even if we read a + "Connection: close" header, to make sure that + "Content-Length: 0" still prevents us from attempting to + read the (missing) response-body. + */ + /* According to RFC2616 section 4.4, we MUST ignore + Content-Length: headers if we are now receiving data + using chunked Transfer-Encoding. + */ + if(k->chunk) + k->maxdownload = k->size = -1; + } + if(-1 != k->size) { + /* We do this operation even if no_body is true, since this + data might be retrieved later with curl_easy_getinfo() + and its CURLINFO_CONTENT_LENGTH_DOWNLOAD option. */ + + Curl_pgrsSetDownloadSize(data, k->size); + k->maxdownload = k->size; + } + + /* If max download size is *zero* (nothing) we already have + nothing and can safely return ok now! But for HTTP/2, we'd + like to call http2_handle_stream_close to properly close a + stream. In order to do this, we keep reading until we + close the stream. */ + if(0 == k->maxdownload +#if defined(USE_NGHTTP2) + && !((conn->handler->protocol & PROTO_FAMILY_HTTP) && + conn->httpversion == 20) +#endif + ) + *stop_reading = TRUE; + + if(*stop_reading) { + /* we make sure that this socket isn't read more now */ + k->keepon &= ~KEEP_RECV; + } + + if(data->set.verbose) + Curl_debug(data, CURLINFO_HEADER_IN, + k->str_start, headerlen); + break; /* exit header line loop */ + } + + /* We continue reading headers, so reset the line-based + header parsing variables hbufp && hbuflen */ + k->hbufp = data->state.headerbuff; + k->hbuflen = 0; + continue; + } + + /* + * Checks for special headers coming up. + */ + + if(!k->headerline++) { + /* This is the first header, it MUST be the error code line + or else we consider this to be the body right away! */ + int httpversion_major; + int rtspversion_major; + int nc = 0; +#ifdef CURL_DOES_CONVERSIONS +#define HEADER1 scratch +#define SCRATCHSIZE 21 + CURLcode res; + char scratch[SCRATCHSIZE + 1]; /* "HTTP/major.minor 123" */ + /* We can't really convert this yet because we + don't know if it's the 1st header line or the body. + So we do a partial conversion into a scratch area, + leaving the data at k->p as-is. + */ + strncpy(&scratch[0], k->p, SCRATCHSIZE); + scratch[SCRATCHSIZE] = 0; /* null terminate */ + res = Curl_convert_from_network(data, + &scratch[0], + SCRATCHSIZE); + if(res) + /* Curl_convert_from_network calls failf if unsuccessful */ + return res; +#else +#define HEADER1 k->p /* no conversion needed, just use k->p */ +#endif /* CURL_DOES_CONVERSIONS */ + + if(conn->handler->protocol & PROTO_FAMILY_HTTP) { + /* + * https://tools.ietf.org/html/rfc7230#section-3.1.2 + * + * The response code is always a three-digit number in HTTP as the spec + * says. We try to allow any number here, but we cannot make + * guarantees on future behaviors since it isn't within the protocol. + */ + char separator; + nc = sscanf(HEADER1, + " HTTP/%1d.%1d%c%3d", + &httpversion_major, + &conn->httpversion, + &separator, + &k->httpcode); + + if(nc == 1 && httpversion_major == 2 && + 1 == sscanf(HEADER1, " HTTP/2 %d", &k->httpcode)) { + conn->httpversion = 0; + nc = 4; + separator = ' '; + } + + if((nc == 4) && (' ' == separator)) { + conn->httpversion += 10 * httpversion_major; + + if(k->upgr101 == UPGR101_RECEIVED) { + /* supposedly upgraded to http2 now */ + if(conn->httpversion != 20) + infof(data, "Lying server, not serving HTTP/2\n"); + } + if(conn->httpversion < 20) { + conn->bundle->multiuse = BUNDLE_NO_MULTIUSE; + infof(data, "Mark bundle as not supporting multiuse\n"); + } + } + else if(!nc) { + /* this is the real world, not a Nirvana + NCSA 1.5.x returns this crap when asked for HTTP/1.1 + */ + nc = sscanf(HEADER1, " HTTP %3d", &k->httpcode); + conn->httpversion = 10; + + /* If user has set option HTTP200ALIASES, + compare header line against list of aliases + */ + if(!nc) { + if(checkhttpprefix(data, k->p, k->hbuflen) == STATUS_DONE) { + nc = 1; + k->httpcode = 200; + conn->httpversion = 10; + } + } + } + else { + failf(data, "Unsupported HTTP version in response\n"); + return CURLE_UNSUPPORTED_PROTOCOL; + } + } + else if(conn->handler->protocol & CURLPROTO_RTSP) { + char separator; + nc = sscanf(HEADER1, + " RTSP/%1d.%1d%c%3d", + &rtspversion_major, + &conn->rtspversion, + &separator, + &k->httpcode); + if((nc == 4) && (' ' == separator)) { + conn->rtspversion += 10 * rtspversion_major; + conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */ + } + else { + nc = 0; + } + } + + if(nc) { + data->info.httpcode = k->httpcode; + + data->info.httpversion = conn->httpversion; + if(!data->state.httpversion || + data->state.httpversion > conn->httpversion) + /* store the lowest server version we encounter */ + data->state.httpversion = conn->httpversion; + + /* + * This code executes as part of processing the header. As a + * result, it's not totally clear how to interpret the + * response code yet as that depends on what other headers may + * be present. 401 and 407 may be errors, but may be OK + * depending on how authentication is working. Other codes + * are definitely errors, so give up here. + */ + if(data->state.resume_from && data->set.httpreq == HTTPREQ_GET && + k->httpcode == 416) { + /* "Requested Range Not Satisfiable", just proceed and + pretend this is no error */ + k->ignorebody = TRUE; /* Avoid appending error msg to good data. */ + } + else if(data->set.http_fail_on_error && (k->httpcode >= 400) && + ((k->httpcode != 401) || !conn->bits.user_passwd) && + ((k->httpcode != 407) || !conn->bits.proxy_user_passwd) ) { + /* serious error, go home! */ + print_http_error(data); + return CURLE_HTTP_RETURNED_ERROR; + } + + if(conn->httpversion == 10) { + /* Default action for HTTP/1.0 must be to close, unless + we get one of those fancy headers that tell us the + server keeps it open for us! */ + infof(data, "HTTP 1.0, assume close after body\n"); + connclose(conn, "HTTP/1.0 close after body"); + } + else if(conn->httpversion == 20 || + (k->upgr101 == UPGR101_REQUESTED && k->httpcode == 101)) { + DEBUGF(infof(data, "HTTP/2 found, allow multiplexing\n")); + + /* HTTP/2 cannot blacklist multiplexing since it is a core + functionality of the protocol */ + conn->bundle->multiuse = BUNDLE_MULTIPLEX; + } + else if(conn->httpversion >= 11 && + !conn->bits.close) { + /* If HTTP version is >= 1.1 and connection is persistent */ + DEBUGF(infof(data, + "HTTP 1.1 or later with persistent connection\n")); + } + + switch(k->httpcode) { + case 304: + /* (quote from RFC2616, section 10.3.5): The 304 response + * MUST NOT contain a message-body, and thus is always + * terminated by the first empty line after the header + * fields. */ + if(data->set.timecondition) + data->info.timecond = TRUE; + /* FALLTHROUGH */ + case 204: + /* (quote from RFC2616, section 10.2.5): The server has + * fulfilled the request but does not need to return an + * entity-body ... The 204 response MUST NOT include a + * message-body, and thus is always terminated by the first + * empty line after the header fields. */ + k->size = 0; + k->maxdownload = 0; + k->ignorecl = TRUE; /* ignore Content-Length headers */ + break; + default: + /* nothing */ + break; + } + } + else { + k->header = FALSE; /* this is not a header line */ + break; + } + } + + result = Curl_convert_from_network(data, k->p, strlen(k->p)); + /* Curl_convert_from_network calls failf if unsuccessful */ + if(result) + return result; + + /* Check for Content-Length: header lines to get size */ + if(!k->ignorecl && !data->set.ignorecl && + checkprefix("Content-Length:", k->p)) { + curl_off_t contentlength; + CURLofft offt = curlx_strtoofft(k->p + 15, NULL, 10, &contentlength); + + if(offt == CURL_OFFT_OK) { + if(data->set.max_filesize && + contentlength > data->set.max_filesize) { + failf(data, "Maximum file size exceeded"); + return CURLE_FILESIZE_EXCEEDED; + } + k->size = contentlength; + k->maxdownload = k->size; + /* we set the progress download size already at this point + just to make it easier for apps/callbacks to extract this + info as soon as possible */ + Curl_pgrsSetDownloadSize(data, k->size); + } + else if(offt == CURL_OFFT_FLOW) { + /* out of range */ + if(data->set.max_filesize) { + failf(data, "Maximum file size exceeded"); + return CURLE_FILESIZE_EXCEEDED; + } + streamclose(conn, "overflow content-length"); + infof(data, "Overflow Content-Length: value!\n"); + } + else { + /* negative or just rubbish - bad HTTP */ + failf(data, "Invalid Content-Length: value"); + return CURLE_WEIRD_SERVER_REPLY; + } + } + /* check for Content-Type: header lines to get the MIME-type */ + else if(checkprefix("Content-Type:", k->p)) { + char *contenttype = Curl_copy_header_value(k->p); + if(!contenttype) + return CURLE_OUT_OF_MEMORY; + if(!*contenttype) + /* ignore empty data */ + free(contenttype); + else { + Curl_safefree(data->info.contenttype); + data->info.contenttype = contenttype; + } + } + else if((conn->httpversion == 10) && + conn->bits.httpproxy && + Curl_compareheader(k->p, + "Proxy-Connection:", "keep-alive")) { + /* + * When a HTTP/1.0 reply comes when using a proxy, the + * 'Proxy-Connection: keep-alive' line tells us the + * connection will be kept alive for our pleasure. + * Default action for 1.0 is to close. + */ + connkeep(conn, "Proxy-Connection keep-alive"); /* don't close */ + infof(data, "HTTP/1.0 proxy connection set to keep alive!\n"); + } + else if((conn->httpversion == 11) && + conn->bits.httpproxy && + Curl_compareheader(k->p, + "Proxy-Connection:", "close")) { + /* + * We get a HTTP/1.1 response from a proxy and it says it'll + * close down after this transfer. + */ + connclose(conn, "Proxy-Connection: asked to close after done"); + infof(data, "HTTP/1.1 proxy connection set close!\n"); + } + else if((conn->httpversion == 10) && + Curl_compareheader(k->p, "Connection:", "keep-alive")) { + /* + * A HTTP/1.0 reply with the 'Connection: keep-alive' line + * tells us the connection will be kept alive for our + * pleasure. Default action for 1.0 is to close. + * + * [RFC2068, section 19.7.1] */ + connkeep(conn, "Connection keep-alive"); + infof(data, "HTTP/1.0 connection set to keep alive!\n"); + } + else if(Curl_compareheader(k->p, "Connection:", "close")) { + /* + * [RFC 2616, section 8.1.2.1] + * "Connection: close" is HTTP/1.1 language and means that + * the connection will close when this request has been + * served. + */ + streamclose(conn, "Connection: close used"); + } + else if(checkprefix("Transfer-Encoding:", k->p)) { + /* One or more encodings. We check for chunked and/or a compression + algorithm. */ + /* + * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding + * means that the server will send a series of "chunks". Each + * chunk starts with line with info (including size of the + * coming block) (terminated with CRLF), then a block of data + * with the previously mentioned size. There can be any amount + * of chunks, and a chunk-data set to zero signals the + * end-of-chunks. */ + + result = Curl_build_unencoding_stack(conn, k->p + 18, TRUE); + if(result) + return result; + } + else if(checkprefix("Content-Encoding:", k->p) && + data->set.str[STRING_ENCODING]) { + /* + * Process Content-Encoding. Look for the values: identity, + * gzip, deflate, compress, x-gzip and x-compress. x-gzip and + * x-compress are the same as gzip and compress. (Sec 3.5 RFC + * 2616). zlib cannot handle compress. However, errors are + * handled further down when the response body is processed + */ + result = Curl_build_unencoding_stack(conn, k->p + 17, FALSE); + if(result) + return result; + } + else if(checkprefix("Content-Range:", k->p)) { + /* Content-Range: bytes [num]- + Content-Range: bytes: [num]- + Content-Range: [num]- + Content-Range: [asterisk]/[total] + + The second format was added since Sun's webserver + JavaWebServer/1.1.1 obviously sends the header this way! + The third added since some servers use that! + The forth means the requested range was unsatisfied. + */ + + char *ptr = k->p + 14; + + /* Move forward until first digit or asterisk */ + while(*ptr && !ISDIGIT(*ptr) && *ptr != '*') + ptr++; + + /* if it truly stopped on a digit */ + if(ISDIGIT(*ptr)) { + if(!curlx_strtoofft(ptr, NULL, 10, &k->offset)) { + if(data->state.resume_from == k->offset) + /* we asked for a resume and we got it */ + k->content_range = TRUE; + } + } + else + data->state.resume_from = 0; /* get everything */ + } +#if !defined(CURL_DISABLE_COOKIES) + else if(data->cookies && + checkprefix("Set-Cookie:", k->p)) { + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, + CURL_LOCK_ACCESS_SINGLE); + Curl_cookie_add(data, + data->cookies, TRUE, FALSE, k->p + 11, + /* If there is a custom-set Host: name, use it + here, or else use real peer host name. */ + conn->allocptr.cookiehost? + conn->allocptr.cookiehost:conn->host.name, + data->state.up.path, + (conn->handler->protocol&CURLPROTO_HTTPS)? + TRUE:FALSE); + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + } +#endif + else if(checkprefix("Last-Modified:", k->p) && + (data->set.timecondition || data->set.get_filetime) ) { + time_t secs = time(NULL); + k->timeofdoc = curl_getdate(k->p + strlen("Last-Modified:"), + &secs); + if(data->set.get_filetime) + data->info.filetime = k->timeofdoc; + } + else if((checkprefix("WWW-Authenticate:", k->p) && + (401 == k->httpcode)) || + (checkprefix("Proxy-authenticate:", k->p) && + (407 == k->httpcode))) { + + bool proxy = (k->httpcode == 407) ? TRUE : FALSE; + char *auth = Curl_copy_header_value(k->p); + if(!auth) + return CURLE_OUT_OF_MEMORY; + + result = Curl_http_input_auth(conn, proxy, auth); + + free(auth); + + if(result) + return result; + } + #ifdef USE_SPNEGO + else if(checkprefix("Persistent-Auth", k->p)) { + struct negotiatedata *negdata = &conn->negotiate; + struct auth *authp = &data->state.authhost; + if(authp->picked == CURLAUTH_NEGOTIATE) { + char *persistentauth = Curl_copy_header_value(k->p); + if(!persistentauth) + return CURLE_OUT_OF_MEMORY; + negdata->noauthpersist = checkprefix("false", persistentauth); + negdata->havenoauthpersist = TRUE; + infof(data, "Negotiate: noauthpersist -> %d, header part: %s", + negdata->noauthpersist, persistentauth); + free(persistentauth); + } + } + #endif + else if((k->httpcode >= 300 && k->httpcode < 400) && + checkprefix("Location:", k->p) && + !data->req.location) { + /* this is the URL that the server advises us to use instead */ + char *location = Curl_copy_header_value(k->p); + if(!location) + return CURLE_OUT_OF_MEMORY; + if(!*location) + /* ignore empty data */ + free(location); + else { + data->req.location = location; + + if(data->set.http_follow_location) { + DEBUGASSERT(!data->req.newurl); + data->req.newurl = strdup(data->req.location); /* clone */ + if(!data->req.newurl) + return CURLE_OUT_OF_MEMORY; + + /* some cases of POST and PUT etc needs to rewind the data + stream at this point */ + result = http_perhapsrewind(conn); + if(result) + return result; + } + } + } +#ifdef USE_ALTSVC + /* If enabled, the header is incoming and this is over HTTPS */ + else if(data->asi && checkprefix("Alt-Svc:", k->p) && + ((conn->handler->flags & PROTOPT_SSL) || +#ifdef CURLDEBUG + /* allow debug builds to circumvent the HTTPS restriction */ + getenv("CURL_ALTSVC_HTTP") +#else + 0 +#endif + )) { + /* the ALPN of the current request */ + enum alpnid id = (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1; + result = Curl_altsvc_parse(data, data->asi, + &k->p[ strlen("Alt-Svc:") ], + id, conn->host.name, + curlx_uitous(conn->remote_port)); + if(result) + return result; + } +#endif + else if(conn->handler->protocol & CURLPROTO_RTSP) { + result = Curl_rtsp_parseheader(conn, k->p); + if(result) + return result; + } + + /* + * End of header-checks. Write them to the client. + */ + + writetype = CLIENTWRITE_HEADER; + if(data->set.include_header) + writetype |= CLIENTWRITE_BODY; + + if(data->set.verbose) + Curl_debug(data, CURLINFO_HEADER_IN, k->p, (size_t)k->hbuflen); + + result = Curl_client_write(conn, writetype, k->p, k->hbuflen); + if(result) + return result; + + data->info.header_size += (long)k->hbuflen; + data->req.headerbytecount += (long)k->hbuflen; + + /* reset hbufp pointer && hbuflen */ + k->hbufp = data->state.headerbuff; + k->hbuflen = 0; + } + while(*k->str); /* header line within buffer */ + + /* We might have reached the end of the header part here, but + there might be a non-header part left in the end of the read + buffer. */ + + return CURLE_OK; +} + +#endif /* CURL_DISABLE_HTTP */ diff --git a/dependencies/cmcurl/lib/http.h b/dependencies/cmcurl/lib/http.h new file mode 100644 index 0000000..a59fe7a --- /dev/null +++ b/dependencies/cmcurl/lib/http.h @@ -0,0 +1,260 @@ +#ifndef HEADER_CURL_HTTP_H +#define HEADER_CURL_HTTP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifndef CURL_DISABLE_HTTP + +#ifdef USE_NGHTTP2 +#include +#endif + +extern const struct Curl_handler Curl_handler_http; + +#ifdef USE_SSL +extern const struct Curl_handler Curl_handler_https; +#endif + +/* Header specific functions */ +bool Curl_compareheader(const char *headerline, /* line to check */ + const char *header, /* header keyword _with_ colon */ + const char *content); /* content string to find */ + +char *Curl_copy_header_value(const char *header); + +char *Curl_checkProxyheaders(const struct connectdata *conn, + const char *thisheader); +/* ------------------------------------------------------------------------- */ +/* + * The add_buffer series of functions are used to build one large memory chunk + * from repeated function invokes. Used so that the entire HTTP request can + * be sent in one go. + */ +struct Curl_send_buffer { + char *buffer; + size_t size_max; + size_t size_used; +}; +typedef struct Curl_send_buffer Curl_send_buffer; + +Curl_send_buffer *Curl_add_buffer_init(void); +void Curl_add_buffer_free(Curl_send_buffer **inp); +CURLcode Curl_add_bufferf(Curl_send_buffer **inp, const char *fmt, ...) + WARN_UNUSED_RESULT; +CURLcode Curl_add_buffer(Curl_send_buffer **inp, const void *inptr, + size_t size) WARN_UNUSED_RESULT; +CURLcode Curl_add_buffer_send(Curl_send_buffer **inp, + struct connectdata *conn, + curl_off_t *bytes_written, + size_t included_body_bytes, + int socketindex); + +CURLcode Curl_add_timecondition(struct Curl_easy *data, + Curl_send_buffer *buf); +CURLcode Curl_add_custom_headers(struct connectdata *conn, + bool is_connect, + Curl_send_buffer *req_buffer); +CURLcode Curl_http_compile_trailers(struct curl_slist *trailers, + Curl_send_buffer *buffer, + struct Curl_easy *handle); + +/* protocol-specific functions set up to be called by the main engine */ +CURLcode Curl_http(struct connectdata *conn, bool *done); +CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature); +CURLcode Curl_http_connect(struct connectdata *conn, bool *done); +CURLcode Curl_http_setup_conn(struct connectdata *conn); + +/* The following functions are defined in http_chunks.c */ +void Curl_httpchunk_init(struct connectdata *conn); +CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap, + ssize_t length, ssize_t *wrote); + +/* These functions are in http.c */ +void Curl_http_auth_stage(struct Curl_easy *data, int stage); +CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, + const char *auth); +CURLcode Curl_http_auth_act(struct connectdata *conn); +CURLcode Curl_http_perhapsrewind(struct connectdata *conn); + +/* If only the PICKNONE bit is set, there has been a round-trip and we + selected to use no auth at all. Ie, we actively select no auth, as opposed + to not having one selected. The other CURLAUTH_* defines are present in the + public curl/curl.h header. */ +#define CURLAUTH_PICKNONE (1<<30) /* don't use auth */ + +/* MAX_INITIAL_POST_SIZE indicates the number of bytes that will make the POST + data get included in the initial data chunk sent to the server. If the + data is larger than this, it will automatically get split up in multiple + system calls. + + This value used to be fairly big (100K), but we must take into account that + if the server rejects the POST due for authentication reasons, this data + will always be unconditionally sent and thus it may not be larger than can + always be afforded to send twice. + + It must not be greater than 64K to work on VMS. +*/ +#ifndef MAX_INITIAL_POST_SIZE +#define MAX_INITIAL_POST_SIZE (64*1024) +#endif + +/* EXPECT_100_THRESHOLD is the request body size limit for when libcurl will + * automatically add an "Expect: 100-continue" header in HTTP requests. When + * the size is unknown, it will always add it. + * + */ +#ifndef EXPECT_100_THRESHOLD +#define EXPECT_100_THRESHOLD 1024 +#endif + +#endif /* CURL_DISABLE_HTTP */ + +/**************************************************************************** + * HTTP unique setup + ***************************************************************************/ +struct HTTP { + curl_mimepart *sendit; + curl_off_t postsize; /* off_t to handle large file sizes */ + const char *postdata; + + const char *p_pragma; /* Pragma: string */ + const char *p_accept; /* Accept: string */ + + /* For FORM posting */ + curl_mimepart form; + + struct back { + curl_read_callback fread_func; /* backup storage for fread pointer */ + void *fread_in; /* backup storage for fread_in pointer */ + const char *postdata; + curl_off_t postsize; + } backup; + + enum { + HTTPSEND_NADA, /* init */ + HTTPSEND_REQUEST, /* sending a request */ + HTTPSEND_BODY, /* sending body */ + HTTPSEND_LAST /* never use this */ + } sending; + +#ifndef CURL_DISABLE_HTTP + Curl_send_buffer *send_buffer; /* used if the request couldn't be sent in + one chunk, points to an allocated + send_buffer struct */ +#endif +#ifdef USE_NGHTTP2 + /*********** for HTTP/2 we store stream-local data here *************/ + int32_t stream_id; /* stream we are interested in */ + + bool bodystarted; + /* We store non-final and final response headers here, per-stream */ + Curl_send_buffer *header_recvbuf; + size_t nread_header_recvbuf; /* number of bytes in header_recvbuf fed into + upper layer */ + Curl_send_buffer *trailer_recvbuf; + int status_code; /* HTTP status code */ + const uint8_t *pausedata; /* pointer to data received in on_data_chunk */ + size_t pauselen; /* the number of bytes left in data */ + bool closed; /* TRUE on HTTP2 stream close */ + bool close_handled; /* TRUE if stream closure is handled by libcurl */ + char *mem; /* points to a buffer in memory to store received data */ + size_t len; /* size of the buffer 'mem' points to */ + size_t memlen; /* size of data copied to mem */ + + const uint8_t *upload_mem; /* points to a buffer to read from */ + size_t upload_len; /* size of the buffer 'upload_mem' points to */ + curl_off_t upload_left; /* number of bytes left to upload */ + + char **push_headers; /* allocated array */ + size_t push_headers_used; /* number of entries filled in */ + size_t push_headers_alloc; /* number of entries allocated */ +#endif +}; + +#ifdef USE_NGHTTP2 +/* h2 settings for this connection */ +struct h2settings { + uint32_t max_concurrent_streams; + bool enable_push; +}; +#endif + +struct http_conn { +#ifdef USE_NGHTTP2 +#define H2_BINSETTINGS_LEN 80 + nghttp2_session *h2; + uint8_t binsettings[H2_BINSETTINGS_LEN]; + size_t binlen; /* length of the binsettings data */ + Curl_send *send_underlying; /* underlying send Curl_send callback */ + Curl_recv *recv_underlying; /* underlying recv Curl_recv callback */ + char *inbuf; /* buffer to receive data from underlying socket */ + size_t inbuflen; /* number of bytes filled in inbuf */ + size_t nread_inbuf; /* number of bytes read from in inbuf */ + /* We need separate buffer for transmission and reception because we + may call nghttp2_session_send() after the + nghttp2_session_mem_recv() but mem buffer is still not full. In + this case, we wrongly sends the content of mem buffer if we share + them for both cases. */ + int32_t pause_stream_id; /* stream ID which paused + nghttp2_session_mem_recv */ + size_t drain_total; /* sum of all stream's UrlState.drain */ + + /* this is a hash of all individual streams (Curl_easy structs) */ + struct h2settings settings; + + /* list of settings that will be sent */ + nghttp2_settings_entry local_settings[3]; + size_t local_settings_num; + uint32_t error_code; /* HTTP/2 error code */ +#else + int unused; /* prevent a compiler warning */ +#endif +}; + +CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, + struct connectdata *conn, + ssize_t *nread, + bool *stop_reading); + +/** + * Curl_http_output_auth() setups the authentication headers for the + * host/proxy and the correct authentication + * method. conn->data->state.authdone is set to TRUE when authentication is + * done. + * + * @param conn all information about the current connection + * @param request pointer to the request keyword + * @param path pointer to the requested path + * @param proxytunnel boolean if this is the request setting up a "proxy + * tunnel" + * + * @returns CURLcode + */ +CURLcode +Curl_http_output_auth(struct connectdata *conn, + const char *request, + const char *path, + bool proxytunnel); /* TRUE if this is the request setting + up the proxy tunnel */ + +#endif /* HEADER_CURL_HTTP_H */ diff --git a/dependencies/cmcurl/lib/http2.c b/dependencies/cmcurl/lib/http2.c new file mode 100644 index 0000000..8e7bc21 --- /dev/null +++ b/dependencies/cmcurl/lib/http2.c @@ -0,0 +1,2435 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_NGHTTP2 +#include +#include "urldata.h" +#include "http2.h" +#include "http.h" +#include "sendf.h" +#include "select.h" +#include "curl_base64.h" +#include "strcase.h" +#include "multiif.h" +#include "url.h" +#include "connect.h" +#include "strtoofft.h" +#include "strdup.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#define H2_BUFSIZE 32768 + +#if (NGHTTP2_VERSION_NUM < 0x010000) +#error too old nghttp2 version, upgrade! +#endif + +#if (NGHTTP2_VERSION_NUM > 0x010800) +#define NGHTTP2_HAS_HTTP2_STRERROR 1 +#endif + +#if (NGHTTP2_VERSION_NUM >= 0x010900) +/* nghttp2_session_callbacks_set_error_callback is present in nghttp2 1.9.0 or + later */ +#define NGHTTP2_HAS_ERROR_CALLBACK 1 +#else +#define nghttp2_session_callbacks_set_error_callback(x,y) +#endif + +#if (NGHTTP2_VERSION_NUM >= 0x010c00) +#define NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE 1 +#endif + +#define HTTP2_HUGE_WINDOW_SIZE (1 << 30) + +#ifdef DEBUG_HTTP2 +#define H2BUGF(x) x +#else +#define H2BUGF(x) do { } WHILE_FALSE +#endif + + +static ssize_t http2_recv(struct connectdata *conn, int sockindex, + char *mem, size_t len, CURLcode *err); +static bool http2_connisdead(struct connectdata *conn); +static int h2_session_send(struct Curl_easy *data, + nghttp2_session *h2); +static int h2_process_pending_input(struct connectdata *conn, + struct http_conn *httpc, + CURLcode *err); + +/* + * Curl_http2_init_state() is called when the easy handle is created and + * allows for HTTP/2 specific init of state. + */ +void Curl_http2_init_state(struct UrlState *state) +{ + state->stream_weight = NGHTTP2_DEFAULT_WEIGHT; +} + +/* + * Curl_http2_init_userset() is called when the easy handle is created and + * allows for HTTP/2 specific user-set fields. + */ +void Curl_http2_init_userset(struct UserDefined *set) +{ + set->stream_weight = NGHTTP2_DEFAULT_WEIGHT; +} + +static int http2_perform_getsock(const struct connectdata *conn, + curl_socket_t *sock, /* points to + numsocks + number of + sockets */ + int numsocks) +{ + const struct http_conn *c = &conn->proto.httpc; + struct SingleRequest *k = &conn->data->req; + int bitmap = GETSOCK_BLANK; + (void)numsocks; + + sock[0] = conn->sock[FIRSTSOCKET]; + + /* in a HTTP/2 connection we can basically always get a frame so we should + always be ready for one */ + bitmap |= GETSOCK_READSOCK(FIRSTSOCKET); + + /* we're still uploading or the HTTP/2 layer wants to send data */ + if(((k->keepon & (KEEP_SEND|KEEP_SEND_PAUSE)) == KEEP_SEND) || + nghttp2_session_want_write(c->h2)) + bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET); + + return bitmap; +} + +static int http2_getsock(struct connectdata *conn, + curl_socket_t *sock, /* points to numsocks + number of sockets */ + int numsocks) +{ + return http2_perform_getsock(conn, sock, numsocks); +} + +/* + * http2_stream_free() free HTTP2 stream related data + */ +static void http2_stream_free(struct HTTP *http) +{ + if(http) { + Curl_add_buffer_free(&http->header_recvbuf); + Curl_add_buffer_free(&http->trailer_recvbuf); + for(; http->push_headers_used > 0; --http->push_headers_used) { + free(http->push_headers[http->push_headers_used - 1]); + } + free(http->push_headers); + http->push_headers = NULL; + } +} + +/* + * Disconnects *a* connection used for HTTP/2. It might be an old one from the + * connection cache and not the "main" one. Don't touch the easy handle! + */ + +static CURLcode http2_disconnect(struct connectdata *conn, + bool dead_connection) +{ + struct http_conn *c = &conn->proto.httpc; + (void)dead_connection; + + H2BUGF(infof(conn->data, "HTTP/2 DISCONNECT starts now\n")); + + nghttp2_session_del(c->h2); + Curl_safefree(c->inbuf); + + H2BUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n")); + + return CURLE_OK; +} + +/* + * The server may send us data at any point (e.g. PING frames). Therefore, + * we cannot assume that an HTTP/2 socket is dead just because it is readable. + * + * Instead, if it is readable, run Curl_connalive() to peek at the socket + * and distinguish between closed and data. + */ +static bool http2_connisdead(struct connectdata *conn) +{ + int sval; + bool dead = TRUE; + + if(conn->bits.close) + return TRUE; + + sval = SOCKET_READABLE(conn->sock[FIRSTSOCKET], 0); + if(sval == 0) { + /* timeout */ + dead = FALSE; + } + else if(sval & CURL_CSELECT_ERR) { + /* socket is in an error state */ + dead = TRUE; + } + else if(sval & CURL_CSELECT_IN) { + /* readable with no error. could still be closed */ + dead = !Curl_connalive(conn); + if(!dead) { + /* This happens before we've sent off a request and the connection is + not in use by any other transfer, there shouldn't be any data here, + only "protocol frames" */ + CURLcode result; + struct http_conn *httpc = &conn->proto.httpc; + ssize_t nread = -1; + if(httpc->recv_underlying) + /* if called "too early", this pointer isn't setup yet! */ + nread = ((Curl_recv *)httpc->recv_underlying)( + conn, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result); + if(nread != -1) { + infof(conn->data, + "%d bytes stray data read before trying h2 connection\n", + (int)nread); + httpc->nread_inbuf = 0; + httpc->inbuflen = nread; + (void)h2_process_pending_input(conn, httpc, &result); + } + else + /* the read failed so let's say this is dead anyway */ + dead = TRUE; + } + } + + return dead; +} + +static unsigned int http2_conncheck(struct connectdata *check, + unsigned int checks_to_perform) +{ + unsigned int ret_val = CONNRESULT_NONE; + struct http_conn *c = &check->proto.httpc; + int rc; + bool send_frames = false; + + if(checks_to_perform & CONNCHECK_ISDEAD) { + if(http2_connisdead(check)) + ret_val |= CONNRESULT_DEAD; + } + + if(checks_to_perform & CONNCHECK_KEEPALIVE) { + struct curltime now = Curl_now(); + time_t elapsed = Curl_timediff(now, check->keepalive); + + if(elapsed > check->upkeep_interval_ms) { + /* Perform an HTTP/2 PING */ + rc = nghttp2_submit_ping(c->h2, 0, ZERO_NULL); + if(!rc) { + /* Successfully added a PING frame to the session. Need to flag this + so the frame is sent. */ + send_frames = true; + } + else { + failf(check->data, "nghttp2_submit_ping() failed: %s(%d)", + nghttp2_strerror(rc), rc); + } + + check->keepalive = now; + } + } + + if(send_frames) { + rc = nghttp2_session_send(c->h2); + if(rc) + failf(check->data, "nghttp2_session_send() failed: %s(%d)", + nghttp2_strerror(rc), rc); + } + + return ret_val; +} + +/* called from Curl_http_setup_conn */ +void Curl_http2_setup_req(struct Curl_easy *data) +{ + struct HTTP *http = data->req.protop; + + http->nread_header_recvbuf = 0; + http->bodystarted = FALSE; + http->status_code = -1; + http->pausedata = NULL; + http->pauselen = 0; + http->closed = FALSE; + http->close_handled = FALSE; + http->mem = data->state.buffer; + http->len = data->set.buffer_size; + http->memlen = 0; +} + +/* called from Curl_http_setup_conn */ +void Curl_http2_setup_conn(struct connectdata *conn) +{ + conn->proto.httpc.settings.max_concurrent_streams = + DEFAULT_MAX_CONCURRENT_STREAMS; + conn->proto.httpc.error_code = NGHTTP2_NO_ERROR; +} + +/* + * HTTP2 handler interface. This isn't added to the general list of protocols + * but will be used at run-time when the protocol is dynamically switched from + * HTTP to HTTP2. + */ +static const struct Curl_handler Curl_handler_http2 = { + "HTTP", /* scheme */ + ZERO_NULL, /* setup_connection */ + Curl_http, /* do_it */ + Curl_http_done, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + http2_getsock, /* proto_getsock */ + http2_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + http2_perform_getsock, /* perform_getsock */ + http2_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + http2_conncheck, /* connection_check */ + PORT_HTTP, /* defport */ + CURLPROTO_HTTP, /* protocol */ + PROTOPT_STREAM /* flags */ +}; + +static const struct Curl_handler Curl_handler_http2_ssl = { + "HTTPS", /* scheme */ + ZERO_NULL, /* setup_connection */ + Curl_http, /* do_it */ + Curl_http_done, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + http2_getsock, /* proto_getsock */ + http2_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + http2_perform_getsock, /* perform_getsock */ + http2_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + http2_conncheck, /* connection_check */ + PORT_HTTP, /* defport */ + CURLPROTO_HTTPS, /* protocol */ + PROTOPT_SSL | PROTOPT_STREAM /* flags */ +}; + +/* + * Store nghttp2 version info in this buffer, Prefix with a space. Return + * total length written. + */ +int Curl_http2_ver(char *p, size_t len) +{ + nghttp2_info *h2 = nghttp2_version(0); + return msnprintf(p, len, " nghttp2/%s", h2->version_str); +} + +/* HTTP/2 error code to name based on the Error Code Registry. +https://tools.ietf.org/html/rfc7540#page-77 +nghttp2_error_code enums are identical. +*/ +static const char *http2_strerror(uint32_t err) +{ +#ifndef NGHTTP2_HAS_HTTP2_STRERROR + const char *str[] = { + "NO_ERROR", /* 0x0 */ + "PROTOCOL_ERROR", /* 0x1 */ + "INTERNAL_ERROR", /* 0x2 */ + "FLOW_CONTROL_ERROR", /* 0x3 */ + "SETTINGS_TIMEOUT", /* 0x4 */ + "STREAM_CLOSED", /* 0x5 */ + "FRAME_SIZE_ERROR", /* 0x6 */ + "REFUSED_STREAM", /* 0x7 */ + "CANCEL", /* 0x8 */ + "COMPRESSION_ERROR", /* 0x9 */ + "CONNECT_ERROR", /* 0xA */ + "ENHANCE_YOUR_CALM", /* 0xB */ + "INADEQUATE_SECURITY", /* 0xC */ + "HTTP_1_1_REQUIRED" /* 0xD */ + }; + return (err < sizeof(str) / sizeof(str[0])) ? str[err] : "unknown"; +#else + return nghttp2_http2_strerror(err); +#endif +} + +/* + * The implementation of nghttp2_send_callback type. Here we write |data| with + * size |length| to the network and return the number of bytes actually + * written. See the documentation of nghttp2_send_callback for the details. + */ +static ssize_t send_callback(nghttp2_session *h2, + const uint8_t *data, size_t length, int flags, + void *userp) +{ + struct connectdata *conn = (struct connectdata *)userp; + struct http_conn *c = &conn->proto.httpc; + ssize_t written; + CURLcode result = CURLE_OK; + + (void)h2; + (void)flags; + + if(!c->send_underlying) + /* called before setup properly! */ + return NGHTTP2_ERR_CALLBACK_FAILURE; + + written = ((Curl_send*)c->send_underlying)(conn, FIRSTSOCKET, + data, length, &result); + + if(result == CURLE_AGAIN) { + return NGHTTP2_ERR_WOULDBLOCK; + } + + if(written == -1) { + failf(conn->data, "Failed sending HTTP2 data"); + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + + if(!written) + return NGHTTP2_ERR_WOULDBLOCK; + + return written; +} + + +/* We pass a pointer to this struct in the push callback, but the contents of + the struct are hidden from the user. */ +struct curl_pushheaders { + struct Curl_easy *data; + const nghttp2_push_promise *frame; +}; + +/* + * push header access function. Only to be used from within the push callback + */ +char *curl_pushheader_bynum(struct curl_pushheaders *h, size_t num) +{ + /* Verify that we got a good easy handle in the push header struct, mostly to + detect rubbish input fast(er). */ + if(!h || !GOOD_EASY_HANDLE(h->data)) + return NULL; + else { + struct HTTP *stream = h->data->req.protop; + if(num < stream->push_headers_used) + return stream->push_headers[num]; + } + return NULL; +} + +/* + * push header access function. Only to be used from within the push callback + */ +char *curl_pushheader_byname(struct curl_pushheaders *h, const char *header) +{ + /* Verify that we got a good easy handle in the push header struct, + mostly to detect rubbish input fast(er). Also empty header name + is just a rubbish too. We have to allow ":" at the beginning of + the header, but header == ":" must be rejected. If we have ':' in + the middle of header, it could be matched in middle of the value, + this is because we do prefix match.*/ + if(!h || !GOOD_EASY_HANDLE(h->data) || !header || !header[0] || + !strcmp(header, ":") || strchr(header + 1, ':')) + return NULL; + else { + struct HTTP *stream = h->data->req.protop; + size_t len = strlen(header); + size_t i; + for(i = 0; ipush_headers_used; i++) { + if(!strncmp(header, stream->push_headers[i], len)) { + /* sub-match, make sure that it is followed by a colon */ + if(stream->push_headers[i][len] != ':') + continue; + return &stream->push_headers[i][len + 1]; + } + } + } + return NULL; +} + +/* + * This specific transfer on this connection has been "drained". + */ +static void drained_transfer(struct Curl_easy *data, + struct http_conn *httpc) +{ + DEBUGASSERT(httpc->drain_total >= data->state.drain); + httpc->drain_total -= data->state.drain; + data->state.drain = 0; +} + +/* + * Mark this transfer to get "drained". + */ +static void drain_this(struct Curl_easy *data, + struct http_conn *httpc) +{ + data->state.drain++; + httpc->drain_total++; + DEBUGASSERT(httpc->drain_total >= data->state.drain); +} + +static struct Curl_easy *duphandle(struct Curl_easy *data) +{ + struct Curl_easy *second = curl_easy_duphandle(data); + if(second) { + /* setup the request struct */ + struct HTTP *http = calloc(1, sizeof(struct HTTP)); + if(!http) { + (void)Curl_close(second); + second = NULL; + } + else { + second->req.protop = http; + http->header_recvbuf = Curl_add_buffer_init(); + if(!http->header_recvbuf) { + free(http); + (void)Curl_close(second); + second = NULL; + } + else { + Curl_http2_setup_req(second); + second->state.stream_weight = data->state.stream_weight; + } + } + } + return second; +} + + +static int push_promise(struct Curl_easy *data, + struct connectdata *conn, + const nghttp2_push_promise *frame) +{ + int rv; + H2BUGF(infof(data, "PUSH_PROMISE received, stream %u!\n", + frame->promised_stream_id)); + if(data->multi->push_cb) { + struct HTTP *stream; + struct HTTP *newstream; + struct curl_pushheaders heads; + CURLMcode rc; + struct http_conn *httpc; + size_t i; + /* clone the parent */ + struct Curl_easy *newhandle = duphandle(data); + if(!newhandle) { + infof(data, "failed to duplicate handle\n"); + rv = 1; /* FAIL HARD */ + goto fail; + } + + heads.data = data; + heads.frame = frame; + /* ask the application */ + H2BUGF(infof(data, "Got PUSH_PROMISE, ask application!\n")); + + stream = data->req.protop; + if(!stream) { + failf(data, "Internal NULL stream!\n"); + (void)Curl_close(newhandle); + rv = 1; + goto fail; + } + + Curl_set_in_callback(data, true); + rv = data->multi->push_cb(data, newhandle, + stream->push_headers_used, &heads, + data->multi->push_userp); + Curl_set_in_callback(data, false); + + /* free the headers again */ + for(i = 0; ipush_headers_used; i++) + free(stream->push_headers[i]); + free(stream->push_headers); + stream->push_headers = NULL; + stream->push_headers_used = 0; + + if(rv) { + /* denied, kill off the new handle again */ + http2_stream_free(newhandle->req.protop); + newhandle->req.protop = NULL; + (void)Curl_close(newhandle); + goto fail; + } + + newstream = newhandle->req.protop; + newstream->stream_id = frame->promised_stream_id; + newhandle->req.maxdownload = -1; + newhandle->req.size = -1; + + /* approved, add to the multi handle and immediately switch to PERFORM + state with the given connection !*/ + rc = Curl_multi_add_perform(data->multi, newhandle, conn); + if(rc) { + infof(data, "failed to add handle to multi\n"); + http2_stream_free(newhandle->req.protop); + newhandle->req.protop = NULL; + Curl_close(newhandle); + rv = 1; + goto fail; + } + + httpc = &conn->proto.httpc; + rv = nghttp2_session_set_stream_user_data(httpc->h2, + frame->promised_stream_id, + newhandle); + if(rv) { + infof(data, "failed to set user_data for stream %d\n", + frame->promised_stream_id); + DEBUGASSERT(0); + goto fail; + } + } + else { + H2BUGF(infof(data, "Got PUSH_PROMISE, ignore it!\n")); + rv = 1; + } + fail: + return rv; +} + +/* + * multi_connchanged() is called to tell that there is a connection in + * this multi handle that has changed state (multiplexing become possible, the + * number of allowed streams changed or similar), and a subsequent use of this + * multi handle should move CONNECT_PEND handles back to CONNECT to have them + * retry. + */ +static void multi_connchanged(struct Curl_multi *multi) +{ + multi->recheckstate = TRUE; +} + +static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, + void *userp) +{ + struct connectdata *conn = (struct connectdata *)userp; + struct http_conn *httpc = &conn->proto.httpc; + struct Curl_easy *data_s = NULL; + struct HTTP *stream = NULL; + int rv; + size_t left, ncopy; + int32_t stream_id = frame->hd.stream_id; + CURLcode result; + + if(!stream_id) { + /* stream ID zero is for connection-oriented stuff */ + if(frame->hd.type == NGHTTP2_SETTINGS) { + uint32_t max_conn = httpc->settings.max_concurrent_streams; + H2BUGF(infof(conn->data, "Got SETTINGS\n")); + httpc->settings.max_concurrent_streams = + nghttp2_session_get_remote_settings( + session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS); + httpc->settings.enable_push = + nghttp2_session_get_remote_settings( + session, NGHTTP2_SETTINGS_ENABLE_PUSH); + H2BUGF(infof(conn->data, "MAX_CONCURRENT_STREAMS == %d\n", + httpc->settings.max_concurrent_streams)); + H2BUGF(infof(conn->data, "ENABLE_PUSH == %s\n", + httpc->settings.enable_push?"TRUE":"false")); + if(max_conn != httpc->settings.max_concurrent_streams) { + /* only signal change if the value actually changed */ + infof(conn->data, + "Connection state changed (MAX_CONCURRENT_STREAMS == %u)!\n", + httpc->settings.max_concurrent_streams); + multi_connchanged(conn->data->multi); + } + } + return 0; + } + data_s = nghttp2_session_get_stream_user_data(session, stream_id); + if(!data_s) { + H2BUGF(infof(conn->data, + "No Curl_easy associated with stream: %x\n", + stream_id)); + return 0; + } + + stream = data_s->req.protop; + if(!stream) { + H2BUGF(infof(data_s, "No proto pointer for stream: %x\n", + stream_id)); + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + + H2BUGF(infof(data_s, "on_frame_recv() header %x stream %x\n", + frame->hd.type, stream_id)); + + switch(frame->hd.type) { + case NGHTTP2_DATA: + /* If body started on this stream, then receiving DATA is illegal. */ + if(!stream->bodystarted) { + rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, + stream_id, NGHTTP2_PROTOCOL_ERROR); + + if(nghttp2_is_fatal(rv)) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + } + break; + case NGHTTP2_HEADERS: + if(stream->bodystarted) { + /* Only valid HEADERS after body started is trailer HEADERS. We + buffer them in on_header callback. */ + break; + } + + /* nghttp2 guarantees that :status is received, and we store it to + stream->status_code. Fuzzing has proven this can still be reached + without status code having been set. */ + if(stream->status_code == -1) + return NGHTTP2_ERR_CALLBACK_FAILURE; + + /* Only final status code signals the end of header */ + if(stream->status_code / 100 != 1) { + stream->bodystarted = TRUE; + stream->status_code = -1; + } + + result = Curl_add_buffer(&stream->header_recvbuf, "\r\n", 2); + if(result) + return NGHTTP2_ERR_CALLBACK_FAILURE; + + left = stream->header_recvbuf->size_used - stream->nread_header_recvbuf; + ncopy = CURLMIN(stream->len, left); + + memcpy(&stream->mem[stream->memlen], + stream->header_recvbuf->buffer + stream->nread_header_recvbuf, + ncopy); + stream->nread_header_recvbuf += ncopy; + + H2BUGF(infof(data_s, "Store %zu bytes headers from stream %u at %p\n", + ncopy, stream_id, stream->mem)); + + stream->len -= ncopy; + stream->memlen += ncopy; + + drain_this(data_s, httpc); + { + /* get the pointer from userp again since it was re-assigned above */ + struct connectdata *conn_s = (struct connectdata *)userp; + + /* if we receive data for another handle, wake that up */ + if(conn_s->data != data_s) + Curl_expire(data_s, 0, EXPIRE_RUN_NOW); + } + break; + case NGHTTP2_PUSH_PROMISE: + rv = push_promise(data_s, conn, &frame->push_promise); + if(rv) { /* deny! */ + rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, + frame->push_promise.promised_stream_id, + NGHTTP2_CANCEL); + if(nghttp2_is_fatal(rv)) { + return rv; + } + } + break; + default: + H2BUGF(infof(data_s, "Got frame type %x for stream %u!\n", + frame->hd.type, stream_id)); + break; + } + return 0; +} + +static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags, + int32_t stream_id, + const uint8_t *data, size_t len, void *userp) +{ + struct HTTP *stream; + struct Curl_easy *data_s; + size_t nread; + struct connectdata *conn = (struct connectdata *)userp; + (void)session; + (void)flags; + (void)data; + + DEBUGASSERT(stream_id); /* should never be a zero stream ID here */ + + /* get the stream from the hash based on Stream ID */ + data_s = nghttp2_session_get_stream_user_data(session, stream_id); + if(!data_s) + /* Receiving a Stream ID not in the hash should not happen, this is an + internal error more than anything else! */ + return NGHTTP2_ERR_CALLBACK_FAILURE; + + stream = data_s->req.protop; + if(!stream) + return NGHTTP2_ERR_CALLBACK_FAILURE; + + nread = CURLMIN(stream->len, len); + memcpy(&stream->mem[stream->memlen], data, nread); + + stream->len -= nread; + stream->memlen += nread; + + drain_this(data_s, &conn->proto.httpc); + + /* if we receive data for another handle, wake that up */ + if(conn->data != data_s) + Curl_expire(data_s, 0, EXPIRE_RUN_NOW); + + H2BUGF(infof(data_s, "%zu data received for stream %u " + "(%zu left in buffer %p, total %zu)\n", + nread, stream_id, + stream->len, stream->mem, + stream->memlen)); + + if(nread < len) { + stream->pausedata = data + nread; + stream->pauselen = len - nread; + H2BUGF(infof(data_s, "NGHTTP2_ERR_PAUSE - %zu bytes out of buffer" + ", stream %u\n", + len - nread, stream_id)); + data_s->conn->proto.httpc.pause_stream_id = stream_id; + + return NGHTTP2_ERR_PAUSE; + } + + /* pause execution of nghttp2 if we received data for another handle + in order to process them first. */ + if(conn->data != data_s) { + data_s->conn->proto.httpc.pause_stream_id = stream_id; + + return NGHTTP2_ERR_PAUSE; + } + + return 0; +} + +static int on_stream_close(nghttp2_session *session, int32_t stream_id, + uint32_t error_code, void *userp) +{ + struct Curl_easy *data_s; + struct HTTP *stream; + struct connectdata *conn = (struct connectdata *)userp; + int rv; + (void)session; + (void)stream_id; + + if(stream_id) { + struct http_conn *httpc; + /* get the stream from the hash based on Stream ID, stream ID zero is for + connection-oriented stuff */ + data_s = nghttp2_session_get_stream_user_data(session, stream_id); + if(!data_s) { + /* We could get stream ID not in the hash. For example, if we + decided to reject stream (e.g., PUSH_PROMISE). */ + return 0; + } + H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n", + http2_strerror(error_code), error_code, stream_id)); + stream = data_s->req.protop; + if(!stream) + return NGHTTP2_ERR_CALLBACK_FAILURE; + + stream->closed = TRUE; + httpc = &conn->proto.httpc; + drain_this(data_s, httpc); + httpc->error_code = error_code; + + /* remove the entry from the hash as the stream is now gone */ + rv = nghttp2_session_set_stream_user_data(session, stream_id, 0); + if(rv) { + infof(data_s, "http/2: failed to clear user_data for stream %d!\n", + stream_id); + DEBUGASSERT(0); + } + if(stream_id == httpc->pause_stream_id) { + H2BUGF(infof(data_s, "Stopped the pause stream!\n")); + httpc->pause_stream_id = 0; + } + H2BUGF(infof(data_s, "Removed stream %u hash!\n", stream_id)); + stream->stream_id = 0; /* cleared */ + } + return 0; +} + +static int on_begin_headers(nghttp2_session *session, + const nghttp2_frame *frame, void *userp) +{ + struct HTTP *stream; + struct Curl_easy *data_s = NULL; + (void)userp; + + data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id); + if(!data_s) { + return 0; + } + + H2BUGF(infof(data_s, "on_begin_headers() was called\n")); + + if(frame->hd.type != NGHTTP2_HEADERS) { + return 0; + } + + stream = data_s->req.protop; + if(!stream || !stream->bodystarted) { + return 0; + } + + if(!stream->trailer_recvbuf) { + stream->trailer_recvbuf = Curl_add_buffer_init(); + if(!stream->trailer_recvbuf) { + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + } + return 0; +} + +/* Decode HTTP status code. Returns -1 if no valid status code was + decoded. */ +static int decode_status_code(const uint8_t *value, size_t len) +{ + int i; + int res; + + if(len != 3) { + return -1; + } + + res = 0; + + for(i = 0; i < 3; ++i) { + char c = value[i]; + + if(c < '0' || c > '9') { + return -1; + } + + res *= 10; + res += c - '0'; + } + + return res; +} + +/* frame->hd.type is either NGHTTP2_HEADERS or NGHTTP2_PUSH_PROMISE */ +static int on_header(nghttp2_session *session, const nghttp2_frame *frame, + const uint8_t *name, size_t namelen, + const uint8_t *value, size_t valuelen, + uint8_t flags, + void *userp) +{ + struct HTTP *stream; + struct Curl_easy *data_s; + int32_t stream_id = frame->hd.stream_id; + struct connectdata *conn = (struct connectdata *)userp; + CURLcode result; + (void)flags; + + DEBUGASSERT(stream_id); /* should never be a zero stream ID here */ + + /* get the stream from the hash based on Stream ID */ + data_s = nghttp2_session_get_stream_user_data(session, stream_id); + if(!data_s) + /* Receiving a Stream ID not in the hash should not happen, this is an + internal error more than anything else! */ + return NGHTTP2_ERR_CALLBACK_FAILURE; + + stream = data_s->req.protop; + if(!stream) { + failf(data_s, "Internal NULL stream! 5\n"); + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + + /* Store received PUSH_PROMISE headers to be used when the subsequent + PUSH_PROMISE callback comes */ + if(frame->hd.type == NGHTTP2_PUSH_PROMISE) { + char *h; + + if(!strcmp(":authority", (const char *)name)) { + /* pseudo headers are lower case */ + int rc = 0; + char *check = aprintf("%s:%d", conn->host.name, conn->remote_port); + if(!check) + /* no memory */ + return NGHTTP2_ERR_CALLBACK_FAILURE; + if(!Curl_strcasecompare(check, (const char *)value)) { + /* This is push is not for the same authority that was asked for in + * the URL. RFC 7540 section 8.2 says: "A client MUST treat a + * PUSH_PROMISE for which the server is not authoritative as a stream + * error of type PROTOCOL_ERROR." + */ + (void)nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, + stream_id, NGHTTP2_PROTOCOL_ERROR); + rc = NGHTTP2_ERR_CALLBACK_FAILURE; + } + free(check); + if(rc) + return rc; + } + + if(!stream->push_headers) { + stream->push_headers_alloc = 10; + stream->push_headers = malloc(stream->push_headers_alloc * + sizeof(char *)); + if(!stream->push_headers) + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + stream->push_headers_used = 0; + } + else if(stream->push_headers_used == + stream->push_headers_alloc) { + char **headp; + stream->push_headers_alloc *= 2; + headp = Curl_saferealloc(stream->push_headers, + stream->push_headers_alloc * sizeof(char *)); + if(!headp) { + stream->push_headers = NULL; + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + stream->push_headers = headp; + } + h = aprintf("%s:%s", name, value); + if(h) + stream->push_headers[stream->push_headers_used++] = h; + return 0; + } + + if(stream->bodystarted) { + /* This is trailer fields. */ + /* 4 is for ": " and "\r\n". */ + uint32_t n = (uint32_t)(namelen + valuelen + 4); + + H2BUGF(infof(data_s, "h2 trailer: %.*s: %.*s\n", namelen, name, valuelen, + value)); + + result = Curl_add_buffer(&stream->trailer_recvbuf, &n, sizeof(n)); + if(result) + return NGHTTP2_ERR_CALLBACK_FAILURE; + result = Curl_add_buffer(&stream->trailer_recvbuf, name, namelen); + if(result) + return NGHTTP2_ERR_CALLBACK_FAILURE; + result = Curl_add_buffer(&stream->trailer_recvbuf, ": ", 2); + if(result) + return NGHTTP2_ERR_CALLBACK_FAILURE; + result = Curl_add_buffer(&stream->trailer_recvbuf, value, valuelen); + if(result) + return NGHTTP2_ERR_CALLBACK_FAILURE; + result = Curl_add_buffer(&stream->trailer_recvbuf, "\r\n\0", 3); + if(result) + return NGHTTP2_ERR_CALLBACK_FAILURE; + + return 0; + } + + if(namelen == sizeof(":status") - 1 && + memcmp(":status", name, namelen) == 0) { + /* nghttp2 guarantees :status is received first and only once, and + value is 3 digits status code, and decode_status_code always + succeeds. */ + stream->status_code = decode_status_code(value, valuelen); + DEBUGASSERT(stream->status_code != -1); + + result = Curl_add_buffer(&stream->header_recvbuf, "HTTP/2 ", 7); + if(result) + return NGHTTP2_ERR_CALLBACK_FAILURE; + result = Curl_add_buffer(&stream->header_recvbuf, value, valuelen); + if(result) + return NGHTTP2_ERR_CALLBACK_FAILURE; + /* the space character after the status code is mandatory */ + result = Curl_add_buffer(&stream->header_recvbuf, " \r\n", 3); + if(result) + return NGHTTP2_ERR_CALLBACK_FAILURE; + /* if we receive data for another handle, wake that up */ + if(conn->data != data_s) + Curl_expire(data_s, 0, EXPIRE_RUN_NOW); + + H2BUGF(infof(data_s, "h2 status: HTTP/2 %03d (easy %p)\n", + stream->status_code, data_s)); + return 0; + } + + /* nghttp2 guarantees that namelen > 0, and :status was already + received, and this is not pseudo-header field . */ + /* convert to a HTTP1-style header */ + result = Curl_add_buffer(&stream->header_recvbuf, name, namelen); + if(result) + return NGHTTP2_ERR_CALLBACK_FAILURE; + result = Curl_add_buffer(&stream->header_recvbuf, ": ", 2); + if(result) + return NGHTTP2_ERR_CALLBACK_FAILURE; + result = Curl_add_buffer(&stream->header_recvbuf, value, valuelen); + if(result) + return NGHTTP2_ERR_CALLBACK_FAILURE; + result = Curl_add_buffer(&stream->header_recvbuf, "\r\n", 2); + if(result) + return NGHTTP2_ERR_CALLBACK_FAILURE; + /* if we receive data for another handle, wake that up */ + if(conn->data != data_s) + Curl_expire(data_s, 0, EXPIRE_RUN_NOW); + + H2BUGF(infof(data_s, "h2 header: %.*s: %.*s\n", namelen, name, valuelen, + value)); + + return 0; /* 0 is successful */ +} + +static ssize_t data_source_read_callback(nghttp2_session *session, + int32_t stream_id, + uint8_t *buf, size_t length, + uint32_t *data_flags, + nghttp2_data_source *source, + void *userp) +{ + struct Curl_easy *data_s; + struct HTTP *stream = NULL; + size_t nread; + (void)source; + (void)userp; + + if(stream_id) { + /* get the stream from the hash based on Stream ID, stream ID zero is for + connection-oriented stuff */ + data_s = nghttp2_session_get_stream_user_data(session, stream_id); + if(!data_s) + /* Receiving a Stream ID not in the hash should not happen, this is an + internal error more than anything else! */ + return NGHTTP2_ERR_CALLBACK_FAILURE; + + stream = data_s->req.protop; + if(!stream) + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + else + return NGHTTP2_ERR_INVALID_ARGUMENT; + + nread = CURLMIN(stream->upload_len, length); + if(nread > 0) { + memcpy(buf, stream->upload_mem, nread); + stream->upload_mem += nread; + stream->upload_len -= nread; + if(data_s->state.infilesize != -1) + stream->upload_left -= nread; + } + + if(stream->upload_left == 0) + *data_flags = NGHTTP2_DATA_FLAG_EOF; + else if(nread == 0) + return NGHTTP2_ERR_DEFERRED; + + H2BUGF(infof(data_s, "data_source_read_callback: " + "returns %zu bytes stream %u\n", + nread, stream_id)); + + return nread; +} + +#if defined(NGHTTP2_HAS_ERROR_CALLBACK) && \ + !defined(CURL_DISABLE_VERBOSE_STRINGS) +static int error_callback(nghttp2_session *session, + const char *msg, + size_t len, + void *userp) +{ + struct connectdata *conn = (struct connectdata *)userp; + (void)session; + infof(conn->data, "http2 error: %.*s\n", len, msg); + return 0; +} +#endif + +static void populate_settings(struct connectdata *conn, + struct http_conn *httpc) +{ + nghttp2_settings_entry *iv = httpc->local_settings; + + iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; + iv[0].value = 100; + + iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; + iv[1].value = HTTP2_HUGE_WINDOW_SIZE; + + iv[2].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH; + iv[2].value = conn->data->multi->push_cb != NULL; + + httpc->local_settings_num = 3; +} + +void Curl_http2_done(struct connectdata *conn, bool premature) +{ + struct Curl_easy *data = conn->data; + struct HTTP *http = data->req.protop; + struct http_conn *httpc = &conn->proto.httpc; + + /* there might be allocated resources done before this got the 'h2' pointer + setup */ + if(http->header_recvbuf) { + Curl_add_buffer_free(&http->header_recvbuf); + Curl_add_buffer_free(&http->trailer_recvbuf); + if(http->push_headers) { + /* if they weren't used and then freed before */ + for(; http->push_headers_used > 0; --http->push_headers_used) { + free(http->push_headers[http->push_headers_used - 1]); + } + free(http->push_headers); + http->push_headers = NULL; + } + } + + if(!httpc->h2) /* not HTTP/2 ? */ + return; + + if(data->state.drain) + drained_transfer(data, httpc); + + if(premature) { + /* RST_STREAM */ + if(!nghttp2_submit_rst_stream(httpc->h2, NGHTTP2_FLAG_NONE, + http->stream_id, NGHTTP2_STREAM_CLOSED)) + (void)nghttp2_session_send(httpc->h2); + + if(http->stream_id == httpc->pause_stream_id) { + infof(data, "stopped the pause stream!\n"); + httpc->pause_stream_id = 0; + } + } + /* -1 means unassigned and 0 means cleared */ + if(http->stream_id > 0) { + int rv = nghttp2_session_set_stream_user_data(httpc->h2, + http->stream_id, 0); + if(rv) { + infof(data, "http/2: failed to clear user_data for stream %d!\n", + http->stream_id); + DEBUGASSERT(0); + } + http->stream_id = 0; + } +} + +/* + * Initialize nghttp2 for a Curl connection + */ +static CURLcode http2_init(struct connectdata *conn) +{ + if(!conn->proto.httpc.h2) { + int rc; + nghttp2_session_callbacks *callbacks; + + conn->proto.httpc.inbuf = malloc(H2_BUFSIZE); + if(conn->proto.httpc.inbuf == NULL) + return CURLE_OUT_OF_MEMORY; + + rc = nghttp2_session_callbacks_new(&callbacks); + + if(rc) { + failf(conn->data, "Couldn't initialize nghttp2 callbacks!"); + return CURLE_OUT_OF_MEMORY; /* most likely at least */ + } + + /* nghttp2_send_callback */ + nghttp2_session_callbacks_set_send_callback(callbacks, send_callback); + /* nghttp2_on_frame_recv_callback */ + nghttp2_session_callbacks_set_on_frame_recv_callback + (callbacks, on_frame_recv); + /* nghttp2_on_data_chunk_recv_callback */ + nghttp2_session_callbacks_set_on_data_chunk_recv_callback + (callbacks, on_data_chunk_recv); + /* nghttp2_on_stream_close_callback */ + nghttp2_session_callbacks_set_on_stream_close_callback + (callbacks, on_stream_close); + /* nghttp2_on_begin_headers_callback */ + nghttp2_session_callbacks_set_on_begin_headers_callback + (callbacks, on_begin_headers); + /* nghttp2_on_header_callback */ + nghttp2_session_callbacks_set_on_header_callback(callbacks, on_header); + +#ifndef CURL_DISABLE_VERBOSE_STRINGS + nghttp2_session_callbacks_set_error_callback(callbacks, error_callback); +#endif + + /* The nghttp2 session is not yet setup, do it */ + rc = nghttp2_session_client_new(&conn->proto.httpc.h2, callbacks, conn); + + nghttp2_session_callbacks_del(callbacks); + + if(rc) { + failf(conn->data, "Couldn't initialize nghttp2!"); + return CURLE_OUT_OF_MEMORY; /* most likely at least */ + } + } + return CURLE_OK; +} + +/* + * Append headers to ask for a HTTP1.1 to HTTP2 upgrade. + */ +CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req, + struct connectdata *conn) +{ + CURLcode result; + ssize_t binlen; + char *base64; + size_t blen; + struct SingleRequest *k = &conn->data->req; + uint8_t *binsettings = conn->proto.httpc.binsettings; + struct http_conn *httpc = &conn->proto.httpc; + + populate_settings(conn, httpc); + + /* this returns number of bytes it wrote */ + binlen = nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN, + httpc->local_settings, + httpc->local_settings_num); + if(!binlen) { + failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload"); + Curl_add_buffer_free(&req); + return CURLE_FAILED_INIT; + } + conn->proto.httpc.binlen = binlen; + + result = Curl_base64url_encode(conn->data, (const char *)binsettings, binlen, + &base64, &blen); + if(result) { + Curl_add_buffer_free(&req); + return result; + } + + result = Curl_add_bufferf(&req, + "Connection: Upgrade, HTTP2-Settings\r\n" + "Upgrade: %s\r\n" + "HTTP2-Settings: %s\r\n", + NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, base64); + free(base64); + + k->upgr101 = UPGR101_REQUESTED; + + return result; +} + +/* + * Returns nonzero if current HTTP/2 session should be closed. + */ +static int should_close_session(struct http_conn *httpc) +{ + return httpc->drain_total == 0 && !nghttp2_session_want_read(httpc->h2) && + !nghttp2_session_want_write(httpc->h2); +} + +/* + * h2_process_pending_input() processes pending input left in + * httpc->inbuf. Then, call h2_session_send() to send pending data. + * This function returns 0 if it succeeds, or -1 and error code will + * be assigned to *err. + */ +static int h2_process_pending_input(struct connectdata *conn, + struct http_conn *httpc, + CURLcode *err) +{ + ssize_t nread; + char *inbuf; + ssize_t rv; + struct Curl_easy *data = conn->data; + + nread = httpc->inbuflen - httpc->nread_inbuf; + inbuf = httpc->inbuf + httpc->nread_inbuf; + + rv = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)inbuf, nread); + if(rv < 0) { + failf(data, + "h2_process_pending_input: nghttp2_session_mem_recv() returned " + "%zd:%s\n", rv, nghttp2_strerror((int)rv)); + *err = CURLE_RECV_ERROR; + return -1; + } + + if(nread == rv) { + H2BUGF(infof(data, + "h2_process_pending_input: All data in connection buffer " + "processed\n")); + httpc->inbuflen = 0; + httpc->nread_inbuf = 0; + } + else { + httpc->nread_inbuf += rv; + H2BUGF(infof(data, + "h2_process_pending_input: %zu bytes left in connection " + "buffer\n", + httpc->inbuflen - httpc->nread_inbuf)); + } + + rv = h2_session_send(data, httpc->h2); + if(rv != 0) { + *err = CURLE_SEND_ERROR; + return -1; + } + + if(should_close_session(httpc)) { + H2BUGF(infof(data, + "h2_process_pending_input: nothing to do in this session\n")); + if(httpc->error_code) + *err = CURLE_HTTP2; + else { + /* not an error per se, but should still close the connection */ + connclose(conn, "GOAWAY received"); + *err = CURLE_OK; + } + return -1; + } + + return 0; +} + +/* + * Called from transfer.c:done_sending when we stop uploading. + */ +CURLcode Curl_http2_done_sending(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + if((conn->handler == &Curl_handler_http2_ssl) || + (conn->handler == &Curl_handler_http2)) { + /* make sure this is only attempted for HTTP/2 transfers */ + + struct HTTP *stream = conn->data->req.protop; + + if(stream->upload_left) { + /* If the stream still thinks there's data left to upload. */ + struct http_conn *httpc = &conn->proto.httpc; + nghttp2_session *h2 = httpc->h2; + + stream->upload_left = 0; /* DONE! */ + + /* resume sending here to trigger the callback to get called again so + that it can signal EOF to nghttp2 */ + (void)nghttp2_session_resume_data(h2, stream->stream_id); + + (void)h2_process_pending_input(conn, httpc, &result); + } + } + return result; +} + +static ssize_t http2_handle_stream_close(struct connectdata *conn, + struct Curl_easy *data, + struct HTTP *stream, CURLcode *err) +{ + char *trailer_pos, *trailer_end; + CURLcode result; + struct http_conn *httpc = &conn->proto.httpc; + + if(httpc->pause_stream_id == stream->stream_id) { + httpc->pause_stream_id = 0; + } + + drained_transfer(data, httpc); + + if(httpc->pause_stream_id == 0) { + if(h2_process_pending_input(conn, httpc, err) != 0) { + return -1; + } + } + + DEBUGASSERT(data->state.drain == 0); + + /* Reset to FALSE to prevent infinite loop in readwrite_data function. */ + stream->closed = FALSE; + if(httpc->error_code == NGHTTP2_REFUSED_STREAM) { + H2BUGF(infof(data, "REFUSED_STREAM (%d), try again on a new connection!\n", + stream->stream_id)); + connclose(conn, "REFUSED_STREAM"); /* don't use this anymore */ + data->state.refused_stream = TRUE; + *err = CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */ + return -1; + } + else if(httpc->error_code != NGHTTP2_NO_ERROR) { + failf(data, "HTTP/2 stream %d was not closed cleanly: %s (err %u)", + stream->stream_id, http2_strerror(httpc->error_code), + httpc->error_code); + *err = CURLE_HTTP2_STREAM; + return -1; + } + + if(!stream->bodystarted) { + failf(data, "HTTP/2 stream %d was closed cleanly, but before getting " + " all response header fields, treated as error", + stream->stream_id); + *err = CURLE_HTTP2_STREAM; + return -1; + } + + if(stream->trailer_recvbuf && stream->trailer_recvbuf->buffer) { + trailer_pos = stream->trailer_recvbuf->buffer; + trailer_end = trailer_pos + stream->trailer_recvbuf->size_used; + + for(; trailer_pos < trailer_end;) { + uint32_t n; + memcpy(&n, trailer_pos, sizeof(n)); + trailer_pos += sizeof(n); + + result = Curl_client_write(conn, CLIENTWRITE_HEADER, trailer_pos, n); + if(result) { + *err = result; + return -1; + } + + trailer_pos += n + 1; + } + } + + stream->close_handled = TRUE; + + H2BUGF(infof(data, "http2_recv returns 0, http2_handle_stream_close\n")); + return 0; +} + +/* + * h2_pri_spec() fills in the pri_spec struct, used by nghttp2 to send weight + * and dependency to the peer. It also stores the updated values in the state + * struct. + */ + +static void h2_pri_spec(struct Curl_easy *data, + nghttp2_priority_spec *pri_spec) +{ + struct HTTP *depstream = (data->set.stream_depends_on? + data->set.stream_depends_on->req.protop:NULL); + int32_t depstream_id = depstream? depstream->stream_id:0; + nghttp2_priority_spec_init(pri_spec, depstream_id, data->set.stream_weight, + data->set.stream_depends_e); + data->state.stream_weight = data->set.stream_weight; + data->state.stream_depends_e = data->set.stream_depends_e; + data->state.stream_depends_on = data->set.stream_depends_on; +} + +/* + * h2_session_send() checks if there's been an update in the priority / + * dependency settings and if so it submits a PRIORITY frame with the updated + * info. + */ +static int h2_session_send(struct Curl_easy *data, + nghttp2_session *h2) +{ + struct HTTP *stream = data->req.protop; + if((data->set.stream_weight != data->state.stream_weight) || + (data->set.stream_depends_e != data->state.stream_depends_e) || + (data->set.stream_depends_on != data->state.stream_depends_on) ) { + /* send new weight and/or dependency */ + nghttp2_priority_spec pri_spec; + int rv; + + h2_pri_spec(data, &pri_spec); + + H2BUGF(infof(data, "Queuing PRIORITY on stream %u (easy %p)\n", + stream->stream_id, data)); + rv = nghttp2_submit_priority(h2, NGHTTP2_FLAG_NONE, stream->stream_id, + &pri_spec); + if(rv) + return rv; + } + + return nghttp2_session_send(h2); +} + +static ssize_t http2_recv(struct connectdata *conn, int sockindex, + char *mem, size_t len, CURLcode *err) +{ + CURLcode result = CURLE_OK; + ssize_t rv; + ssize_t nread; + struct http_conn *httpc = &conn->proto.httpc; + struct Curl_easy *data = conn->data; + struct HTTP *stream = data->req.protop; + + (void)sockindex; /* we always do HTTP2 on sockindex 0 */ + + if(should_close_session(httpc)) { + H2BUGF(infof(data, + "http2_recv: nothing to do in this session\n")); + *err = CURLE_HTTP2; + return -1; + } + + /* Nullify here because we call nghttp2_session_send() and they + might refer to the old buffer. */ + stream->upload_mem = NULL; + stream->upload_len = 0; + + /* + * At this point 'stream' is just in the Curl_easy the connection + * identifies as its owner at this time. + */ + + if(stream->bodystarted && + stream->nread_header_recvbuf < stream->header_recvbuf->size_used) { + /* If there is body data pending for this stream to return, do that */ + size_t left = + stream->header_recvbuf->size_used - stream->nread_header_recvbuf; + size_t ncopy = CURLMIN(len, left); + memcpy(mem, stream->header_recvbuf->buffer + stream->nread_header_recvbuf, + ncopy); + stream->nread_header_recvbuf += ncopy; + + H2BUGF(infof(data, "http2_recv: Got %d bytes from header_recvbuf\n", + (int)ncopy)); + return ncopy; + } + + H2BUGF(infof(data, "http2_recv: easy %p (stream %u)\n", + data, stream->stream_id)); + + if((data->state.drain) && stream->memlen) { + H2BUGF(infof(data, "http2_recv: DRAIN %zu bytes stream %u!! (%p => %p)\n", + stream->memlen, stream->stream_id, + stream->mem, mem)); + if(mem != stream->mem) { + /* if we didn't get the same buffer this time, we must move the data to + the beginning */ + memmove(mem, stream->mem, stream->memlen); + stream->len = len - stream->memlen; + stream->mem = mem; + } + if(httpc->pause_stream_id == stream->stream_id && !stream->pausedata) { + /* We have paused nghttp2, but we have no pause data (see + on_data_chunk_recv). */ + httpc->pause_stream_id = 0; + if(h2_process_pending_input(conn, httpc, &result) != 0) { + *err = result; + return -1; + } + } + } + else if(stream->pausedata) { + DEBUGASSERT(httpc->pause_stream_id == stream->stream_id); + nread = CURLMIN(len, stream->pauselen); + memcpy(mem, stream->pausedata, nread); + + stream->pausedata += nread; + stream->pauselen -= nread; + + infof(data, "%zd data bytes written\n", nread); + if(stream->pauselen == 0) { + H2BUGF(infof(data, "Unpaused by stream %u\n", stream->stream_id)); + DEBUGASSERT(httpc->pause_stream_id == stream->stream_id); + httpc->pause_stream_id = 0; + + stream->pausedata = NULL; + stream->pauselen = 0; + + /* When NGHTTP2_ERR_PAUSE is returned from + data_source_read_callback, we might not process DATA frame + fully. Calling nghttp2_session_mem_recv() again will + continue to process DATA frame, but if there is no incoming + frames, then we have to call it again with 0-length data. + Without this, on_stream_close callback will not be called, + and stream could be hanged. */ + if(h2_process_pending_input(conn, httpc, &result) != 0) { + *err = result; + return -1; + } + } + H2BUGF(infof(data, "http2_recv: returns unpaused %zd bytes on stream %u\n", + nread, stream->stream_id)); + return nread; + } + else if(httpc->pause_stream_id) { + /* If a stream paused nghttp2_session_mem_recv previously, and has + not processed all data, it still refers to the buffer in + nghttp2_session. If we call nghttp2_session_mem_recv(), we may + overwrite that buffer. To avoid that situation, just return + here with CURLE_AGAIN. This could be busy loop since data in + socket is not read. But it seems that usually streams are + notified with its drain property, and socket is read again + quickly. */ + H2BUGF(infof(data, "stream %x is paused, pause id: %x\n", + stream->stream_id, httpc->pause_stream_id)); + *err = CURLE_AGAIN; + return -1; + } + else { + char *inbuf; + /* remember where to store incoming data for this stream and how big the + buffer is */ + stream->mem = mem; + stream->len = len; + stream->memlen = 0; + + if(httpc->inbuflen == 0) { + nread = ((Curl_recv *)httpc->recv_underlying)( + conn, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result); + + if(nread == -1) { + if(result != CURLE_AGAIN) + failf(data, "Failed receiving HTTP2 data"); + else if(stream->closed) + /* received when the stream was already closed! */ + return http2_handle_stream_close(conn, data, stream, err); + + *err = result; + return -1; + } + + if(nread == 0) { + H2BUGF(infof(data, "end of stream\n")); + *err = CURLE_OK; + return 0; + } + + H2BUGF(infof(data, "nread=%zd\n", nread)); + + httpc->inbuflen = nread; + inbuf = httpc->inbuf; + } + else { + nread = httpc->inbuflen - httpc->nread_inbuf; + inbuf = httpc->inbuf + httpc->nread_inbuf; + + H2BUGF(infof(data, "Use data left in connection buffer, nread=%zd\n", + nread)); + } + rv = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)inbuf, nread); + + if(nghttp2_is_fatal((int)rv)) { + failf(data, "nghttp2_session_mem_recv() returned %zd:%s\n", + rv, nghttp2_strerror((int)rv)); + *err = CURLE_RECV_ERROR; + return -1; + } + H2BUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", rv)); + if(nread == rv) { + H2BUGF(infof(data, "All data in connection buffer processed\n")); + httpc->inbuflen = 0; + httpc->nread_inbuf = 0; + } + else { + httpc->nread_inbuf += rv; + H2BUGF(infof(data, "%zu bytes left in connection buffer\n", + httpc->inbuflen - httpc->nread_inbuf)); + } + /* Always send pending frames in nghttp2 session, because + nghttp2_session_mem_recv() may queue new frame */ + rv = h2_session_send(data, httpc->h2); + if(rv != 0) { + *err = CURLE_SEND_ERROR; + return -1; + } + + if(should_close_session(httpc)) { + H2BUGF(infof(data, "http2_recv: nothing to do in this session\n")); + *err = CURLE_HTTP2; + return -1; + } + } + if(stream->memlen) { + ssize_t retlen = stream->memlen; + H2BUGF(infof(data, "http2_recv: returns %zd for stream %u\n", + retlen, stream->stream_id)); + stream->memlen = 0; + + if(httpc->pause_stream_id == stream->stream_id) { + /* data for this stream is returned now, but this stream caused a pause + already so we need it called again asap */ + H2BUGF(infof(data, "Data returned for PAUSED stream %u\n", + stream->stream_id)); + } + else if(!stream->closed) { + drained_transfer(data, httpc); + } + + return retlen; + } + /* If stream is closed, return 0 to signal the http routine to close + the connection */ + if(stream->closed) { + return http2_handle_stream_close(conn, data, stream, err); + } + *err = CURLE_AGAIN; + H2BUGF(infof(data, "http2_recv returns AGAIN for stream %u\n", + stream->stream_id)); + return -1; +} + +/* Index where :authority header field will appear in request header + field list. */ +#define AUTHORITY_DST_IDX 3 + +#define HEADER_OVERFLOW(x) \ + (x.namelen > (uint16_t)-1 || x.valuelen > (uint16_t)-1 - x.namelen) + +/* + * Check header memory for the token "trailers". + * Parse the tokens as separated by comma and surrounded by whitespace. + * Returns TRUE if found or FALSE if not. + */ +static bool contains_trailers(const char *p, size_t len) +{ + const char *end = p + len; + for(;;) { + for(; p != end && (*p == ' ' || *p == '\t'); ++p) + ; + if(p == end || (size_t)(end - p) < sizeof("trailers") - 1) + return FALSE; + if(strncasecompare("trailers", p, sizeof("trailers") - 1)) { + p += sizeof("trailers") - 1; + for(; p != end && (*p == ' ' || *p == '\t'); ++p) + ; + if(p == end || *p == ',') + return TRUE; + } + /* skip to next token */ + for(; p != end && *p != ','; ++p) + ; + if(p == end) + return FALSE; + ++p; + } +} + +typedef enum { + /* Send header to server */ + HEADERINST_FORWARD, + /* Don't send header to server */ + HEADERINST_IGNORE, + /* Discard header, and replace it with "te: trailers" */ + HEADERINST_TE_TRAILERS +} header_instruction; + +/* Decides how to treat given header field. */ +static header_instruction inspect_header(const char *name, size_t namelen, + const char *value, size_t valuelen) { + switch(namelen) { + case 2: + if(!strncasecompare("te", name, namelen)) + return HEADERINST_FORWARD; + + return contains_trailers(value, valuelen) ? + HEADERINST_TE_TRAILERS : HEADERINST_IGNORE; + case 7: + return strncasecompare("upgrade", name, namelen) ? + HEADERINST_IGNORE : HEADERINST_FORWARD; + case 10: + return (strncasecompare("connection", name, namelen) || + strncasecompare("keep-alive", name, namelen)) ? + HEADERINST_IGNORE : HEADERINST_FORWARD; + case 16: + return strncasecompare("proxy-connection", name, namelen) ? + HEADERINST_IGNORE : HEADERINST_FORWARD; + case 17: + return strncasecompare("transfer-encoding", name, namelen) ? + HEADERINST_IGNORE : HEADERINST_FORWARD; + default: + return HEADERINST_FORWARD; + } +} + +static ssize_t http2_send(struct connectdata *conn, int sockindex, + const void *mem, size_t len, CURLcode *err) +{ + /* + * Currently, we send request in this function, but this function is also + * used to send request body. It would be nice to add dedicated function for + * request. + */ + int rv; + struct http_conn *httpc = &conn->proto.httpc; + struct HTTP *stream = conn->data->req.protop; + nghttp2_nv *nva = NULL; + size_t nheader; + size_t i; + size_t authority_idx; + char *hdbuf = (char *)mem; + char *end, *line_end; + nghttp2_data_provider data_prd; + int32_t stream_id; + nghttp2_session *h2 = httpc->h2; + nghttp2_priority_spec pri_spec; + + (void)sockindex; + + H2BUGF(infof(conn->data, "http2_send len=%zu\n", len)); + + if(stream->stream_id != -1) { + if(stream->close_handled) { + infof(conn->data, "stream %d closed\n", stream->stream_id); + *err = CURLE_HTTP2_STREAM; + return -1; + } + else if(stream->closed) { + return http2_handle_stream_close(conn, conn->data, stream, err); + } + /* If stream_id != -1, we have dispatched request HEADERS, and now + are going to send or sending request body in DATA frame */ + stream->upload_mem = mem; + stream->upload_len = len; + nghttp2_session_resume_data(h2, stream->stream_id); + rv = h2_session_send(conn->data, h2); + if(nghttp2_is_fatal(rv)) { + *err = CURLE_SEND_ERROR; + return -1; + } + len -= stream->upload_len; + + /* Nullify here because we call nghttp2_session_send() and they + might refer to the old buffer. */ + stream->upload_mem = NULL; + stream->upload_len = 0; + + if(should_close_session(httpc)) { + H2BUGF(infof(conn->data, "http2_send: nothing to do in this session\n")); + *err = CURLE_HTTP2; + return -1; + } + + if(stream->upload_left) { + /* we are sure that we have more data to send here. Calling the + following API will make nghttp2_session_want_write() return + nonzero if remote window allows it, which then libcurl checks + socket is writable or not. See http2_perform_getsock(). */ + nghttp2_session_resume_data(h2, stream->stream_id); + } + + H2BUGF(infof(conn->data, "http2_send returns %zu for stream %u\n", len, + stream->stream_id)); + return len; + } + + /* Calculate number of headers contained in [mem, mem + len) */ + /* Here, we assume the curl http code generate *correct* HTTP header + field block */ + nheader = 0; + for(i = 1; i < len; ++i) { + if(hdbuf[i] == '\n' && hdbuf[i - 1] == '\r') { + ++nheader; + ++i; + } + } + if(nheader < 2) + goto fail; + + /* We counted additional 2 \r\n in the first and last line. We need 3 + new headers: :method, :path and :scheme. Therefore we need one + more space. */ + nheader += 1; + nva = malloc(sizeof(nghttp2_nv) * nheader); + if(nva == NULL) { + *err = CURLE_OUT_OF_MEMORY; + return -1; + } + + /* Extract :method, :path from request line + We do line endings with CRLF so checking for CR is enough */ + line_end = memchr(hdbuf, '\r', len); + if(!line_end) + goto fail; + + /* Method does not contain spaces */ + end = memchr(hdbuf, ' ', line_end - hdbuf); + if(!end || end == hdbuf) + goto fail; + nva[0].name = (unsigned char *)":method"; + nva[0].namelen = strlen((char *)nva[0].name); + nva[0].value = (unsigned char *)hdbuf; + nva[0].valuelen = (size_t)(end - hdbuf); + nva[0].flags = NGHTTP2_NV_FLAG_NONE; + if(HEADER_OVERFLOW(nva[0])) { + failf(conn->data, "Failed sending HTTP request: Header overflow"); + goto fail; + } + + hdbuf = end + 1; + + /* Path may contain spaces so scan backwards */ + end = NULL; + for(i = (size_t)(line_end - hdbuf); i; --i) { + if(hdbuf[i - 1] == ' ') { + end = &hdbuf[i - 1]; + break; + } + } + if(!end || end == hdbuf) + goto fail; + nva[1].name = (unsigned char *)":path"; + nva[1].namelen = strlen((char *)nva[1].name); + nva[1].value = (unsigned char *)hdbuf; + nva[1].valuelen = (size_t)(end - hdbuf); + nva[1].flags = NGHTTP2_NV_FLAG_NONE; + if(HEADER_OVERFLOW(nva[1])) { + failf(conn->data, "Failed sending HTTP request: Header overflow"); + goto fail; + } + + nva[2].name = (unsigned char *)":scheme"; + nva[2].namelen = strlen((char *)nva[2].name); + if(conn->handler->flags & PROTOPT_SSL) + nva[2].value = (unsigned char *)"https"; + else + nva[2].value = (unsigned char *)"http"; + nva[2].valuelen = strlen((char *)nva[2].value); + nva[2].flags = NGHTTP2_NV_FLAG_NONE; + if(HEADER_OVERFLOW(nva[2])) { + failf(conn->data, "Failed sending HTTP request: Header overflow"); + goto fail; + } + + authority_idx = 0; + i = 3; + while(i < nheader) { + size_t hlen; + + hdbuf = line_end + 2; + + /* check for next CR, but only within the piece of data left in the given + buffer */ + line_end = memchr(hdbuf, '\r', len - (hdbuf - (char *)mem)); + if(!line_end || (line_end == hdbuf)) + goto fail; + + /* header continuation lines are not supported */ + if(*hdbuf == ' ' || *hdbuf == '\t') + goto fail; + + for(end = hdbuf; end < line_end && *end != ':'; ++end) + ; + if(end == hdbuf || end == line_end) + goto fail; + hlen = end - hdbuf; + + if(hlen == 4 && strncasecompare("host", hdbuf, 4)) { + authority_idx = i; + nva[i].name = (unsigned char *)":authority"; + nva[i].namelen = strlen((char *)nva[i].name); + } + else { + nva[i].name = (unsigned char *)hdbuf; + nva[i].namelen = (size_t)(end - hdbuf); + } + hdbuf = end + 1; + while(*hdbuf == ' ' || *hdbuf == '\t') + ++hdbuf; + end = line_end; + + switch(inspect_header((const char *)nva[i].name, nva[i].namelen, hdbuf, + end - hdbuf)) { + case HEADERINST_IGNORE: + /* skip header fields prohibited by HTTP/2 specification. */ + --nheader; + continue; + case HEADERINST_TE_TRAILERS: + nva[i].value = (uint8_t*)"trailers"; + nva[i].valuelen = sizeof("trailers") - 1; + break; + default: + nva[i].value = (unsigned char *)hdbuf; + nva[i].valuelen = (size_t)(end - hdbuf); + } + + nva[i].flags = NGHTTP2_NV_FLAG_NONE; + if(HEADER_OVERFLOW(nva[i])) { + failf(conn->data, "Failed sending HTTP request: Header overflow"); + goto fail; + } + ++i; + } + + /* :authority must come before non-pseudo header fields */ + if(authority_idx != 0 && authority_idx != AUTHORITY_DST_IDX) { + nghttp2_nv authority = nva[authority_idx]; + for(i = authority_idx; i > AUTHORITY_DST_IDX; --i) { + nva[i] = nva[i - 1]; + } + nva[i] = authority; + } + + /* Warn stream may be rejected if cumulative length of headers is too large. + It appears nghttp2 will not send a header frame larger than 64KB. */ +#define MAX_ACC 60000 /* <64KB to account for some overhead */ + { + size_t acc = 0; + + for(i = 0; i < nheader; ++i) { + acc += nva[i].namelen + nva[i].valuelen; + + H2BUGF(infof(conn->data, "h2 header: %.*s:%.*s\n", + nva[i].namelen, nva[i].name, + nva[i].valuelen, nva[i].value)); + } + + if(acc > MAX_ACC) { + infof(conn->data, "http2_send: Warning: The cumulative length of all " + "headers exceeds %zu bytes and that could cause the " + "stream to be rejected.\n", MAX_ACC); + } + } + + h2_pri_spec(conn->data, &pri_spec); + + switch(conn->data->set.httpreq) { + case HTTPREQ_POST: + case HTTPREQ_POST_FORM: + case HTTPREQ_POST_MIME: + case HTTPREQ_PUT: + if(conn->data->state.infilesize != -1) + stream->upload_left = conn->data->state.infilesize; + else + /* data sending without specifying the data amount up front */ + stream->upload_left = -1; /* unknown, but not zero */ + + data_prd.read_callback = data_source_read_callback; + data_prd.source.ptr = NULL; + stream_id = nghttp2_submit_request(h2, &pri_spec, nva, nheader, + &data_prd, conn->data); + break; + default: + stream_id = nghttp2_submit_request(h2, &pri_spec, nva, nheader, + NULL, conn->data); + } + + Curl_safefree(nva); + + if(stream_id < 0) { + H2BUGF(infof(conn->data, "http2_send() send error\n")); + *err = CURLE_SEND_ERROR; + return -1; + } + + infof(conn->data, "Using Stream ID: %x (easy handle %p)\n", + stream_id, (void *)conn->data); + stream->stream_id = stream_id; + + /* this does not call h2_session_send() since there can not have been any + * priority upodate since the nghttp2_submit_request() call above */ + rv = nghttp2_session_send(h2); + + if(rv != 0) { + *err = CURLE_SEND_ERROR; + return -1; + } + + if(should_close_session(httpc)) { + H2BUGF(infof(conn->data, "http2_send: nothing to do in this session\n")); + *err = CURLE_HTTP2; + return -1; + } + + if(stream->stream_id != -1) { + /* If whole HEADERS frame was sent off to the underlying socket, + the nghttp2 library calls data_source_read_callback. But only + it found that no data available, so it deferred the DATA + transmission. Which means that nghttp2_session_want_write() + returns 0 on http2_perform_getsock(), which results that no + writable socket check is performed. To workaround this, we + issue nghttp2_session_resume_data() here to bring back DATA + transmission from deferred state. */ + nghttp2_session_resume_data(h2, stream->stream_id); + } + + return len; + +fail: + free(nva); + *err = CURLE_SEND_ERROR; + return -1; +} + +CURLcode Curl_http2_setup(struct connectdata *conn) +{ + CURLcode result; + struct http_conn *httpc = &conn->proto.httpc; + struct HTTP *stream = conn->data->req.protop; + + stream->stream_id = -1; + + if(!stream->header_recvbuf) { + stream->header_recvbuf = Curl_add_buffer_init(); + if(!stream->header_recvbuf) + return CURLE_OUT_OF_MEMORY; + } + + if((conn->handler == &Curl_handler_http2_ssl) || + (conn->handler == &Curl_handler_http2)) + return CURLE_OK; /* already done */ + + if(conn->handler->flags & PROTOPT_SSL) + conn->handler = &Curl_handler_http2_ssl; + else + conn->handler = &Curl_handler_http2; + + result = http2_init(conn); + if(result) { + Curl_add_buffer_free(&stream->header_recvbuf); + return result; + } + + infof(conn->data, "Using HTTP2, server supports multi-use\n"); + stream->upload_left = 0; + stream->upload_mem = NULL; + stream->upload_len = 0; + + httpc->inbuflen = 0; + httpc->nread_inbuf = 0; + + httpc->pause_stream_id = 0; + httpc->drain_total = 0; + + conn->bits.multiplex = TRUE; /* at least potentially multiplexed */ + conn->httpversion = 20; + conn->bundle->multiuse = BUNDLE_MULTIPLEX; + + infof(conn->data, "Connection state changed (HTTP/2 confirmed)\n"); + multi_connchanged(conn->data->multi); + + return CURLE_OK; +} + +CURLcode Curl_http2_switched(struct connectdata *conn, + const char *mem, size_t nread) +{ + CURLcode result; + struct http_conn *httpc = &conn->proto.httpc; + int rv; + ssize_t nproc; + struct Curl_easy *data = conn->data; + struct HTTP *stream = conn->data->req.protop; + + result = Curl_http2_setup(conn); + if(result) + return result; + + httpc->recv_underlying = conn->recv[FIRSTSOCKET]; + httpc->send_underlying = conn->send[FIRSTSOCKET]; + conn->recv[FIRSTSOCKET] = http2_recv; + conn->send[FIRSTSOCKET] = http2_send; + + if(conn->data->req.upgr101 == UPGR101_RECEIVED) { + /* stream 1 is opened implicitly on upgrade */ + stream->stream_id = 1; + /* queue SETTINGS frame (again) */ + rv = nghttp2_session_upgrade(httpc->h2, httpc->binsettings, + httpc->binlen, NULL); + if(rv != 0) { + failf(data, "nghttp2_session_upgrade() failed: %s(%d)", + nghttp2_strerror(rv), rv); + return CURLE_HTTP2; + } + + rv = nghttp2_session_set_stream_user_data(httpc->h2, + stream->stream_id, + data); + if(rv) { + infof(data, "http/2: failed to set user_data for stream %d!\n", + stream->stream_id); + DEBUGASSERT(0); + } + } + else { + populate_settings(conn, httpc); + + /* stream ID is unknown at this point */ + stream->stream_id = -1; + rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE, + httpc->local_settings, + httpc->local_settings_num); + if(rv != 0) { + failf(data, "nghttp2_submit_settings() failed: %s(%d)", + nghttp2_strerror(rv), rv); + return CURLE_HTTP2; + } + } + +#ifdef NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE + rv = nghttp2_session_set_local_window_size(httpc->h2, NGHTTP2_FLAG_NONE, 0, + HTTP2_HUGE_WINDOW_SIZE); + if(rv != 0) { + failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)", + nghttp2_strerror(rv), rv); + return CURLE_HTTP2; + } +#endif + + /* we are going to copy mem to httpc->inbuf. This is required since + mem is part of buffer pointed by stream->mem, and callbacks + called by nghttp2_session_mem_recv() will write stream specific + data into stream->mem, overwriting data already there. */ + if(H2_BUFSIZE < nread) { + failf(data, "connection buffer size is too small to store data following " + "HTTP Upgrade response header: buflen=%zu, datalen=%zu", + H2_BUFSIZE, nread); + return CURLE_HTTP2; + } + + infof(conn->data, "Copying HTTP/2 data in stream buffer to connection buffer" + " after upgrade: len=%zu\n", + nread); + + if(nread) + memcpy(httpc->inbuf, mem, nread); + httpc->inbuflen = nread; + + nproc = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)httpc->inbuf, + httpc->inbuflen); + + if(nghttp2_is_fatal((int)nproc)) { + failf(data, "nghttp2_session_mem_recv() failed: %s(%d)", + nghttp2_strerror((int)nproc), (int)nproc); + return CURLE_HTTP2; + } + + H2BUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", nproc)); + + if((ssize_t)nread == nproc) { + httpc->inbuflen = 0; + httpc->nread_inbuf = 0; + } + else { + httpc->nread_inbuf += nproc; + } + + /* Try to send some frames since we may read SETTINGS already. */ + rv = h2_session_send(data, httpc->h2); + + if(rv != 0) { + failf(data, "nghttp2_session_send() failed: %s(%d)", + nghttp2_strerror(rv), rv); + return CURLE_HTTP2; + } + + if(should_close_session(httpc)) { + H2BUGF(infof(data, + "nghttp2_session_send(): nothing to do in this session\n")); + return CURLE_HTTP2; + } + + return CURLE_OK; +} + +CURLcode Curl_http2_add_child(struct Curl_easy *parent, + struct Curl_easy *child, + bool exclusive) +{ + if(parent) { + struct Curl_http2_dep **tail; + struct Curl_http2_dep *dep = calloc(1, sizeof(struct Curl_http2_dep)); + if(!dep) + return CURLE_OUT_OF_MEMORY; + dep->data = child; + + if(parent->set.stream_dependents && exclusive) { + struct Curl_http2_dep *node = parent->set.stream_dependents; + while(node) { + node->data->set.stream_depends_on = child; + node = node->next; + } + + tail = &child->set.stream_dependents; + while(*tail) + tail = &(*tail)->next; + + DEBUGASSERT(!*tail); + *tail = parent->set.stream_dependents; + parent->set.stream_dependents = 0; + } + + tail = &parent->set.stream_dependents; + while(*tail) { + (*tail)->data->set.stream_depends_e = FALSE; + tail = &(*tail)->next; + } + + DEBUGASSERT(!*tail); + *tail = dep; + } + + child->set.stream_depends_on = parent; + child->set.stream_depends_e = exclusive; + return CURLE_OK; +} + +void Curl_http2_remove_child(struct Curl_easy *parent, struct Curl_easy *child) +{ + struct Curl_http2_dep *last = 0; + struct Curl_http2_dep *data = parent->set.stream_dependents; + DEBUGASSERT(child->set.stream_depends_on == parent); + + while(data && data->data != child) { + last = data; + data = data->next; + } + + DEBUGASSERT(data); + + if(data) { + if(last) { + last->next = data->next; + } + else { + parent->set.stream_dependents = data->next; + } + free(data); + } + + child->set.stream_depends_on = 0; + child->set.stream_depends_e = FALSE; +} + +void Curl_http2_cleanup_dependencies(struct Curl_easy *data) +{ + while(data->set.stream_dependents) { + struct Curl_easy *tmp = data->set.stream_dependents->data; + Curl_http2_remove_child(data, tmp); + if(data->set.stream_depends_on) + Curl_http2_add_child(data->set.stream_depends_on, tmp, FALSE); + } + + if(data->set.stream_depends_on) + Curl_http2_remove_child(data->set.stream_depends_on, data); +} + +/* Only call this function for a transfer that already got a HTTP/2 + CURLE_HTTP2_STREAM error! */ +bool Curl_h2_http_1_1_error(struct connectdata *conn) +{ + struct http_conn *httpc = &conn->proto.httpc; + return (httpc->error_code == NGHTTP2_HTTP_1_1_REQUIRED); +} + +#else /* !USE_NGHTTP2 */ + +/* Satisfy external references even if http2 is not compiled in. */ + +#define CURL_DISABLE_TYPECHECK +#include + +char *curl_pushheader_bynum(struct curl_pushheaders *h, size_t num) +{ + (void) h; + (void) num; + return NULL; +} + +char *curl_pushheader_byname(struct curl_pushheaders *h, const char *header) +{ + (void) h; + (void) header; + return NULL; +} + +#endif /* USE_NGHTTP2 */ diff --git a/dependencies/cmcurl/lib/http2.h b/dependencies/cmcurl/lib/http2.h new file mode 100644 index 0000000..db6217b --- /dev/null +++ b/dependencies/cmcurl/lib/http2.h @@ -0,0 +1,82 @@ +#ifndef HEADER_CURL_HTTP2_H +#define HEADER_CURL_HTTP2_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_NGHTTP2 +#include "http.h" + +/* value for MAX_CONCURRENT_STREAMS we use until we get an updated setting + from the peer */ +#define DEFAULT_MAX_CONCURRENT_STREAMS 13 + +/* + * Store nghttp2 version info in this buffer, Prefix with a space. Return + * total length written. + */ +int Curl_http2_ver(char *p, size_t len); + +const char *Curl_http2_strerror(uint32_t err); + +CURLcode Curl_http2_init(struct connectdata *conn); +void Curl_http2_init_state(struct UrlState *state); +void Curl_http2_init_userset(struct UserDefined *set); +CURLcode Curl_http2_send_request(struct connectdata *conn); +CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req, + struct connectdata *conn); +CURLcode Curl_http2_setup(struct connectdata *conn); +CURLcode Curl_http2_switched(struct connectdata *conn, + const char *data, size_t nread); +/* called from Curl_http_setup_conn */ +void Curl_http2_setup_conn(struct connectdata *conn); +void Curl_http2_setup_req(struct Curl_easy *data); +void Curl_http2_done(struct connectdata *conn, bool premature); +CURLcode Curl_http2_done_sending(struct connectdata *conn); +CURLcode Curl_http2_add_child(struct Curl_easy *parent, + struct Curl_easy *child, + bool exclusive); +void Curl_http2_remove_child(struct Curl_easy *parent, + struct Curl_easy *child); +void Curl_http2_cleanup_dependencies(struct Curl_easy *data); + +/* returns true if the HTTP/2 stream error was HTTP_1_1_REQUIRED */ +bool Curl_h2_http_1_1_error(struct connectdata *conn); +#else /* USE_NGHTTP2 */ +#define Curl_http2_send_request(x) CURLE_UNSUPPORTED_PROTOCOL +#define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL +#define Curl_http2_setup(x) CURLE_UNSUPPORTED_PROTOCOL +#define Curl_http2_switched(x,y,z) CURLE_UNSUPPORTED_PROTOCOL +#define Curl_http2_setup_conn(x) Curl_nop_stmt +#define Curl_http2_setup_req(x) +#define Curl_http2_init_state(x) +#define Curl_http2_init_userset(x) +#define Curl_http2_done(x,y) +#define Curl_http2_done_sending(x) +#define Curl_http2_add_child(x, y, z) +#define Curl_http2_remove_child(x, y) +#define Curl_http2_cleanup_dependencies(x) +#define Curl_h2_http_1_1_error(x) 0 +#endif + +#endif /* HEADER_CURL_HTTP2_H */ diff --git a/dependencies/cmcurl/lib/http_chunks.c b/dependencies/cmcurl/lib/http_chunks.c new file mode 100644 index 0000000..18dfcb2 --- /dev/null +++ b/dependencies/cmcurl/lib/http_chunks.c @@ -0,0 +1,351 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_HTTP + +#include "urldata.h" /* it includes http_chunks.h */ +#include "sendf.h" /* for the client write stuff */ + +#include "content_encoding.h" +#include "http.h" +#include "non-ascii.h" /* for Curl_convert_to_network prototype */ +#include "strtoofft.h" +#include "warnless.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Chunk format (simplified): + * + * [ chunk extension ] CRLF + * CRLF + * + * Highlights from RFC2616 section 3.6 say: + + The chunked encoding modifies the body of a message in order to + transfer it as a series of chunks, each with its own size indicator, + followed by an OPTIONAL trailer containing entity-header fields. This + allows dynamically produced content to be transferred along with the + information necessary for the recipient to verify that it has + received the full message. + + Chunked-Body = *chunk + last-chunk + trailer + CRLF + + chunk = chunk-size [ chunk-extension ] CRLF + chunk-data CRLF + chunk-size = 1*HEX + last-chunk = 1*("0") [ chunk-extension ] CRLF + + chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] ) + chunk-ext-name = token + chunk-ext-val = token | quoted-string + chunk-data = chunk-size(OCTET) + trailer = *(entity-header CRLF) + + The chunk-size field is a string of hex digits indicating the size of + the chunk. The chunked encoding is ended by any chunk whose size is + zero, followed by the trailer, which is terminated by an empty line. + + */ + +#ifdef CURL_DOES_CONVERSIONS +/* Check for an ASCII hex digit. + We avoid the use of ISXDIGIT to accommodate non-ASCII hosts. */ +static bool Curl_isxdigit_ascii(char digit) +{ + return (digit >= 0x30 && digit <= 0x39) /* 0-9 */ + || (digit >= 0x41 && digit <= 0x46) /* A-F */ + || (digit >= 0x61 && digit <= 0x66); /* a-f */ +} +#else +#define Curl_isxdigit_ascii(x) Curl_isxdigit(x) +#endif + +void Curl_httpchunk_init(struct connectdata *conn) +{ + struct Curl_chunker *chunk = &conn->chunk; + chunk->hexindex = 0; /* start at 0 */ + chunk->dataleft = 0; /* no data left yet! */ + chunk->state = CHUNK_HEX; /* we get hex first! */ +} + +/* + * chunk_read() returns a OK for normal operations, or a positive return code + * for errors. STOP means this sequence of chunks is complete. The 'wrote' + * argument is set to tell the caller how many bytes we actually passed to the + * client (for byte-counting and whatever). + * + * The states and the state-machine is further explained in the header file. + * + * This function always uses ASCII hex values to accommodate non-ASCII hosts. + * For example, 0x0d and 0x0a are used instead of '\r' and '\n'. + */ +CHUNKcode Curl_httpchunk_read(struct connectdata *conn, + char *datap, + ssize_t datalen, + ssize_t *wrotep) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct Curl_chunker *ch = &conn->chunk; + struct SingleRequest *k = &data->req; + size_t piece; + curl_off_t length = (curl_off_t)datalen; + size_t *wrote = (size_t *)wrotep; + + *wrote = 0; /* nothing's written yet */ + + /* the original data is written to the client, but we go on with the + chunk read process, to properly calculate the content length*/ + if(data->set.http_te_skip && !k->ignorebody) { + result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, datalen); + if(result) + return CHUNKE_WRITE_ERROR; + } + + while(length) { + switch(ch->state) { + case CHUNK_HEX: + if(Curl_isxdigit_ascii(*datap)) { + if(ch->hexindex < MAXNUM_SIZE) { + ch->hexbuffer[ch->hexindex] = *datap; + datap++; + length--; + ch->hexindex++; + } + else { + return CHUNKE_TOO_LONG_HEX; /* longer hex than we support */ + } + } + else { + char *endptr; + if(0 == ch->hexindex) + /* This is illegal data, we received junk where we expected + a hexadecimal digit. */ + return CHUNKE_ILLEGAL_HEX; + + /* length and datap are unmodified */ + ch->hexbuffer[ch->hexindex] = 0; + + /* convert to host encoding before calling strtoul */ + result = Curl_convert_from_network(conn->data, ch->hexbuffer, + ch->hexindex); + if(result) { + /* Curl_convert_from_network calls failf if unsuccessful */ + /* Treat it as a bad hex character */ + return CHUNKE_ILLEGAL_HEX; + } + + if(curlx_strtoofft(ch->hexbuffer, &endptr, 16, &ch->datasize)) + return CHUNKE_ILLEGAL_HEX; + ch->state = CHUNK_LF; /* now wait for the CRLF */ + } + break; + + case CHUNK_LF: + /* waiting for the LF after a chunk size */ + if(*datap == 0x0a) { + /* we're now expecting data to come, unless size was zero! */ + if(0 == ch->datasize) { + ch->state = CHUNK_TRAILER; /* now check for trailers */ + conn->trlPos = 0; + } + else + ch->state = CHUNK_DATA; + } + + datap++; + length--; + break; + + case CHUNK_DATA: + /* We expect 'datasize' of data. We have 'length' right now, it can be + more or less than 'datasize'. Get the smallest piece. + */ + piece = curlx_sotouz((ch->datasize >= length)?length:ch->datasize); + + /* Write the data portion available */ + if(!conn->data->set.http_te_skip && !k->ignorebody) { + if(!conn->data->set.http_ce_skip && k->writer_stack) + result = Curl_unencode_write(conn, k->writer_stack, datap, piece); + else + result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, piece); + + if(result) + return CHUNKE_WRITE_ERROR; + } + + *wrote += piece; + ch->datasize -= piece; /* decrease amount left to expect */ + datap += piece; /* move read pointer forward */ + length -= piece; /* decrease space left in this round */ + + if(0 == ch->datasize) + /* end of data this round, we now expect a trailing CRLF */ + ch->state = CHUNK_POSTLF; + break; + + case CHUNK_POSTLF: + if(*datap == 0x0a) { + /* The last one before we go back to hex state and start all over. */ + Curl_httpchunk_init(conn); /* sets state back to CHUNK_HEX */ + } + else if(*datap != 0x0d) + return CHUNKE_BAD_CHUNK; + datap++; + length--; + break; + + case CHUNK_TRAILER: + if((*datap == 0x0d) || (*datap == 0x0a)) { + /* this is the end of a trailer, but if the trailer was zero bytes + there was no trailer and we move on */ + + if(conn->trlPos) { + /* we allocate trailer with 3 bytes extra room to fit this */ + conn->trailer[conn->trlPos++] = 0x0d; + conn->trailer[conn->trlPos++] = 0x0a; + conn->trailer[conn->trlPos] = 0; + + /* Convert to host encoding before calling Curl_client_write */ + result = Curl_convert_from_network(conn->data, conn->trailer, + conn->trlPos); + if(result) + /* Curl_convert_from_network calls failf if unsuccessful */ + /* Treat it as a bad chunk */ + return CHUNKE_BAD_CHUNK; + + if(!data->set.http_te_skip) { + result = Curl_client_write(conn, CLIENTWRITE_HEADER, + conn->trailer, conn->trlPos); + if(result) + return CHUNKE_WRITE_ERROR; + } + conn->trlPos = 0; + ch->state = CHUNK_TRAILER_CR; + if(*datap == 0x0a) + /* already on the LF */ + break; + } + else { + /* no trailer, we're on the final CRLF pair */ + ch->state = CHUNK_TRAILER_POSTCR; + break; /* don't advance the pointer */ + } + } + else { + /* conn->trailer is assumed to be freed in url.c on a + connection basis */ + if(conn->trlPos >= conn->trlMax) { + /* we always allocate three extra bytes, just because when the full + header has been received we append CRLF\0 */ + char *ptr; + if(conn->trlMax) { + conn->trlMax *= 2; + ptr = realloc(conn->trailer, conn->trlMax + 3); + } + else { + conn->trlMax = 128; + ptr = malloc(conn->trlMax + 3); + } + if(!ptr) + return CHUNKE_OUT_OF_MEMORY; + conn->trailer = ptr; + } + conn->trailer[conn->trlPos++]=*datap; + } + datap++; + length--; + break; + + case CHUNK_TRAILER_CR: + if(*datap == 0x0a) { + ch->state = CHUNK_TRAILER_POSTCR; + datap++; + length--; + } + else + return CHUNKE_BAD_CHUNK; + break; + + case CHUNK_TRAILER_POSTCR: + /* We enter this state when a CR should arrive so we expect to + have to first pass a CR before we wait for LF */ + if((*datap != 0x0d) && (*datap != 0x0a)) { + /* not a CR then it must be another header in the trailer */ + ch->state = CHUNK_TRAILER; + break; + } + if(*datap == 0x0d) { + /* skip if CR */ + datap++; + length--; + } + /* now wait for the final LF */ + ch->state = CHUNK_STOP; + break; + + case CHUNK_STOP: + if(*datap == 0x0a) { + length--; + + /* Record the length of any data left in the end of the buffer + even if there's no more chunks to read */ + ch->dataleft = curlx_sotouz(length); + + return CHUNKE_STOP; /* return stop */ + } + else + return CHUNKE_BAD_CHUNK; + } + } + return CHUNKE_OK; +} + +const char *Curl_chunked_strerror(CHUNKcode code) +{ + switch(code) { + default: + return "OK"; + case CHUNKE_TOO_LONG_HEX: + return "Too long hexadecimal number"; + case CHUNKE_ILLEGAL_HEX: + return "Illegal or missing hexadecimal sequence"; + case CHUNKE_BAD_CHUNK: + return "Malformed encoding found"; + case CHUNKE_WRITE_ERROR: + return "Write error"; + case CHUNKE_BAD_ENCODING: + return "Bad content-encoding found"; + case CHUNKE_OUT_OF_MEMORY: + return "Out of memory"; + } +} + +#endif /* CURL_DISABLE_HTTP */ diff --git a/dependencies/cmcurl/lib/http_chunks.h b/dependencies/cmcurl/lib/http_chunks.h new file mode 100644 index 0000000..b969c55 --- /dev/null +++ b/dependencies/cmcurl/lib/http_chunks.h @@ -0,0 +1,90 @@ +#ifndef HEADER_CURL_HTTP_CHUNKS_H +#define HEADER_CURL_HTTP_CHUNKS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +/* + * The longest possible hexadecimal number we support in a chunked transfer. + * Weird enough, RFC2616 doesn't set a maximum size! Since we use strtoul() + * to convert it, we "only" support 2^32 bytes chunk data. + */ +#define MAXNUM_SIZE 16 + +typedef enum { + /* await and buffer all hexadecimal digits until we get one that isn't a + hexadecimal digit. When done, we go CHUNK_LF */ + CHUNK_HEX, + + /* wait for LF, ignore all else */ + CHUNK_LF, + + /* We eat the amount of data specified. When done, we move on to the + POST_CR state. */ + CHUNK_DATA, + + /* POSTLF should get a CR and then a LF and nothing else, then move back to + HEX as the CRLF combination marks the end of a chunk. A missing CR is no + big deal. */ + CHUNK_POSTLF, + + /* Used to mark that we're out of the game. NOTE: that there's a 'dataleft' + field in the struct that will tell how many bytes that were not passed to + the client in the end of the last buffer! */ + CHUNK_STOP, + + /* At this point optional trailer headers can be found, unless the next line + is CRLF */ + CHUNK_TRAILER, + + /* A trailer CR has been found - next state is CHUNK_TRAILER_POSTCR. + Next char must be a LF */ + CHUNK_TRAILER_CR, + + /* A trailer LF must be found now, otherwise CHUNKE_BAD_CHUNK will be + signalled If this is an empty trailer CHUNKE_STOP will be signalled. + Otherwise the trailer will be broadcasted via Curl_client_write() and the + next state will be CHUNK_TRAILER */ + CHUNK_TRAILER_POSTCR +} ChunkyState; + +typedef enum { + CHUNKE_STOP = -1, + CHUNKE_OK = 0, + CHUNKE_TOO_LONG_HEX = 1, + CHUNKE_ILLEGAL_HEX, + CHUNKE_BAD_CHUNK, + CHUNKE_WRITE_ERROR, + CHUNKE_BAD_ENCODING, + CHUNKE_OUT_OF_MEMORY, + CHUNKE_LAST +} CHUNKcode; + +const char *Curl_chunked_strerror(CHUNKcode code); + +struct Curl_chunker { + char hexbuffer[ MAXNUM_SIZE + 1]; + int hexindex; + ChunkyState state; + curl_off_t datasize; + size_t dataleft; /* untouched data amount at the end of the last buffer */ +}; + +#endif /* HEADER_CURL_HTTP_CHUNKS_H */ diff --git a/dependencies/cmcurl/lib/http_digest.c b/dependencies/cmcurl/lib/http_digest.c new file mode 100644 index 0000000..9616c30 --- /dev/null +++ b/dependencies/cmcurl/lib/http_digest.c @@ -0,0 +1,181 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) + +#include "urldata.h" +#include "strcase.h" +#include "vauth/vauth.h" +#include "http_digest.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* Test example headers: + +WWW-Authenticate: Digest realm="testrealm", nonce="1053604598" +Proxy-Authenticate: Digest realm="testrealm", nonce="1053604598" + +*/ + +CURLcode Curl_input_digest(struct connectdata *conn, + bool proxy, + const char *header) /* rest of the *-authenticate: + header */ +{ + struct Curl_easy *data = conn->data; + + /* Point to the correct struct with this */ + struct digestdata *digest; + + if(proxy) { + digest = &data->state.proxydigest; + } + else { + digest = &data->state.digest; + } + + if(!checkprefix("Digest", header)) + return CURLE_BAD_CONTENT_ENCODING; + + header += strlen("Digest"); + while(*header && ISSPACE(*header)) + header++; + + return Curl_auth_decode_digest_http_message(header, digest); +} + +CURLcode Curl_output_digest(struct connectdata *conn, + bool proxy, + const unsigned char *request, + const unsigned char *uripath) +{ + CURLcode result; + struct Curl_easy *data = conn->data; + unsigned char *path = NULL; + char *tmp = NULL; + char *response; + size_t len; + bool have_chlg; + + /* Point to the address of the pointer that holds the string to send to the + server, which is for a plain host or for a HTTP proxy */ + char **allocuserpwd; + + /* Point to the name and password for this */ + const char *userp; + const char *passwdp; + + /* Point to the correct struct with this */ + struct digestdata *digest; + struct auth *authp; + + if(proxy) { + digest = &data->state.proxydigest; + allocuserpwd = &conn->allocptr.proxyuserpwd; + userp = conn->http_proxy.user; + passwdp = conn->http_proxy.passwd; + authp = &data->state.authproxy; + } + else { + digest = &data->state.digest; + allocuserpwd = &conn->allocptr.userpwd; + userp = conn->user; + passwdp = conn->passwd; + authp = &data->state.authhost; + } + + Curl_safefree(*allocuserpwd); + + /* not set means empty */ + if(!userp) + userp = ""; + + if(!passwdp) + passwdp = ""; + +#if defined(USE_WINDOWS_SSPI) + have_chlg = digest->input_token ? TRUE : FALSE; +#else + have_chlg = digest->nonce ? TRUE : FALSE; +#endif + + if(!have_chlg) { + authp->done = FALSE; + return CURLE_OK; + } + + /* So IE browsers < v7 cut off the URI part at the query part when they + evaluate the MD5 and some (IIS?) servers work with them so we may need to + do the Digest IE-style. Note that the different ways cause different MD5 + sums to get sent. + + Apache servers can be set to do the Digest IE-style automatically using + the BrowserMatch feature: + https://httpd.apache.org/docs/2.2/mod/mod_auth_digest.html#msie + + Further details on Digest implementation differences: + http://www.fngtps.com/2006/09/http-authentication + */ + + if(authp->iestyle) { + tmp = strchr((char *)uripath, '?'); + if(tmp) { + size_t urilen = tmp - (char *)uripath; + path = (unsigned char *) aprintf("%.*s", urilen, uripath); + } + } + if(!tmp) + path = (unsigned char *) strdup((char *) uripath); + + if(!path) + return CURLE_OUT_OF_MEMORY; + + result = Curl_auth_create_digest_http_message(data, userp, passwdp, request, + path, digest, &response, &len); + free(path); + if(result) + return result; + + *allocuserpwd = aprintf("%sAuthorization: Digest %s\r\n", + proxy ? "Proxy-" : "", + response); + free(response); + if(!*allocuserpwd) + return CURLE_OUT_OF_MEMORY; + + authp->done = TRUE; + + return CURLE_OK; +} + +void Curl_http_auth_cleanup_digest(struct Curl_easy *data) +{ + Curl_auth_digest_cleanup(&data->state.digest); + Curl_auth_digest_cleanup(&data->state.proxydigest); +} + +#endif diff --git a/dependencies/cmcurl/lib/http_digest.h b/dependencies/cmcurl/lib/http_digest.h new file mode 100644 index 0000000..73410ae --- /dev/null +++ b/dependencies/cmcurl/lib/http_digest.h @@ -0,0 +1,42 @@ +#ifndef HEADER_CURL_HTTP_DIGEST_H +#define HEADER_CURL_HTTP_DIGEST_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) + +/* this is for digest header input */ +CURLcode Curl_input_digest(struct connectdata *conn, + bool proxy, const char *header); + +/* this is for creating digest header output */ +CURLcode Curl_output_digest(struct connectdata *conn, + bool proxy, + const unsigned char *request, + const unsigned char *uripath); + +void Curl_http_auth_cleanup_digest(struct Curl_easy *data); + +#endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_CRYPTO_AUTH */ + +#endif /* HEADER_CURL_HTTP_DIGEST_H */ diff --git a/dependencies/cmcurl/lib/http_negotiate.c b/dependencies/cmcurl/lib/http_negotiate.c new file mode 100644 index 0000000..c8f4064 --- /dev/null +++ b/dependencies/cmcurl/lib/http_negotiate.c @@ -0,0 +1,220 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO) + +#include "urldata.h" +#include "sendf.h" +#include "http_negotiate.h" +#include "vauth/vauth.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, + const char *header) +{ + CURLcode result; + struct Curl_easy *data = conn->data; + size_t len; + + /* Point to the username, password, service and host */ + const char *userp; + const char *passwdp; + const char *service; + const char *host; + + /* Point to the correct struct with this */ + struct negotiatedata *neg_ctx; + curlnegotiate state; + + if(proxy) { + userp = conn->http_proxy.user; + passwdp = conn->http_proxy.passwd; + service = data->set.str[STRING_PROXY_SERVICE_NAME] ? + data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP"; + host = conn->http_proxy.host.name; + neg_ctx = &conn->proxyneg; + state = conn->proxy_negotiate_state; + } + else { + userp = conn->user; + passwdp = conn->passwd; + service = data->set.str[STRING_SERVICE_NAME] ? + data->set.str[STRING_SERVICE_NAME] : "HTTP"; + host = conn->host.name; + neg_ctx = &conn->negotiate; + state = conn->http_negotiate_state; + } + + /* Not set means empty */ + if(!userp) + userp = ""; + + if(!passwdp) + passwdp = ""; + + /* Obtain the input token, if any */ + header += strlen("Negotiate"); + while(*header && ISSPACE(*header)) + header++; + + len = strlen(header); + neg_ctx->havenegdata = len != 0; + if(!len) { + if(state == GSS_AUTHSUCC) { + infof(conn->data, "Negotiate auth restarted\n"); + Curl_http_auth_cleanup_negotiate(conn); + } + else if(state != GSS_AUTHNONE) { + /* The server rejected our authentication and hasn't supplied any more + negotiation mechanisms */ + Curl_http_auth_cleanup_negotiate(conn); + return CURLE_LOGIN_DENIED; + } + } + + /* Supports SSL channel binding for Windows ISS extended protection */ +#if defined(USE_WINDOWS_SSPI) && defined(SECPKG_ATTR_ENDPOINT_BINDINGS) + neg_ctx->sslContext = conn->sslContext; +#endif + + /* Initialize the security context and decode our challenge */ + result = Curl_auth_decode_spnego_message(data, userp, passwdp, service, + host, header, neg_ctx); + + if(result) + Curl_http_auth_cleanup_negotiate(conn); + + return result; +} + +CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy) +{ + struct negotiatedata *neg_ctx = proxy ? &conn->proxyneg : + &conn->negotiate; + struct auth *authp = proxy ? &conn->data->state.authproxy : + &conn->data->state.authhost; + curlnegotiate *state = proxy ? &conn->proxy_negotiate_state : + &conn->http_negotiate_state; + char *base64 = NULL; + size_t len = 0; + char *userp; + CURLcode result; + + authp->done = FALSE; + + if(*state == GSS_AUTHRECV) { + if(neg_ctx->havenegdata) { + neg_ctx->havemultiplerequests = TRUE; + } + } + else if(*state == GSS_AUTHSUCC) { + if(!neg_ctx->havenoauthpersist) { + neg_ctx->noauthpersist = !neg_ctx->havemultiplerequests; + } + } + + if(neg_ctx->noauthpersist || + (*state != GSS_AUTHDONE && *state != GSS_AUTHSUCC)) { + + if(neg_ctx->noauthpersist && *state == GSS_AUTHSUCC) { + infof(conn->data, "Curl_output_negotiate, " + "no persistent authentication: cleanup existing context"); + Curl_http_auth_cleanup_negotiate(conn); + } + if(!neg_ctx->context) { + result = Curl_input_negotiate(conn, proxy, "Negotiate"); + if(result == CURLE_LOGIN_DENIED) { + /* negotiate auth failed, let's continue unauthenticated to stay + * compatible with the behavior before curl-7_64_0-158-g6c6035532 */ + conn->data->state.authproblem = TRUE; + return CURLE_OK; + } + else if(result) + return result; + } + + result = Curl_auth_create_spnego_message(conn->data, + neg_ctx, &base64, &len); + if(result) + return result; + + userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "", + base64); + + if(proxy) { + Curl_safefree(conn->allocptr.proxyuserpwd); + conn->allocptr.proxyuserpwd = userp; + } + else { + Curl_safefree(conn->allocptr.userpwd); + conn->allocptr.userpwd = userp; + } + + free(base64); + + if(userp == NULL) { + return CURLE_OUT_OF_MEMORY; + } + + *state = GSS_AUTHSENT; + #ifdef HAVE_GSSAPI + if(neg_ctx->status == GSS_S_COMPLETE || + neg_ctx->status == GSS_S_CONTINUE_NEEDED) { + *state = GSS_AUTHDONE; + } + #else + #ifdef USE_WINDOWS_SSPI + if(neg_ctx->status == SEC_E_OK || + neg_ctx->status == SEC_I_CONTINUE_NEEDED) { + *state = GSS_AUTHDONE; + } + #endif + #endif + } + + if(*state == GSS_AUTHDONE || *state == GSS_AUTHSUCC) { + /* connection is already authenticated, + * don't send a header in future requests */ + authp->done = TRUE; + } + + neg_ctx->havenegdata = FALSE; + + return CURLE_OK; +} + +void Curl_http_auth_cleanup_negotiate(struct connectdata *conn) +{ + conn->http_negotiate_state = GSS_AUTHNONE; + conn->proxy_negotiate_state = GSS_AUTHNONE; + + Curl_auth_cleanup_spnego(&conn->negotiate); + Curl_auth_cleanup_spnego(&conn->proxyneg); +} + +#endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */ diff --git a/dependencies/cmcurl/lib/http_negotiate.h b/dependencies/cmcurl/lib/http_negotiate.h new file mode 100644 index 0000000..4f0ac16 --- /dev/null +++ b/dependencies/cmcurl/lib/http_negotiate.h @@ -0,0 +1,38 @@ +#ifndef HEADER_CURL_HTTP_NEGOTIATE_H +#define HEADER_CURL_HTTP_NEGOTIATE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO) + +/* this is for Negotiate header input */ +CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, + const char *header); + +/* this is for creating Negotiate header output */ +CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy); + +void Curl_http_auth_cleanup_negotiate(struct connectdata *conn); + +#endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */ + +#endif /* HEADER_CURL_HTTP_NEGOTIATE_H */ diff --git a/dependencies/cmcurl/lib/http_ntlm.c b/dependencies/cmcurl/lib/http_ntlm.c new file mode 100644 index 0000000..e4a4fe0 --- /dev/null +++ b/dependencies/cmcurl/lib/http_ntlm.c @@ -0,0 +1,259 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) + +/* + * NTLM details: + * + * https://davenport.sourceforge.io/ntlm.html + * https://www.innovation.ch/java/ntlm.html + */ + +#define DEBUG_ME 0 + +#include "urldata.h" +#include "sendf.h" +#include "strcase.h" +#include "http_ntlm.h" +#include "curl_ntlm_core.h" +#include "curl_ntlm_wb.h" +#include "vauth/vauth.h" +#include "url.h" + +/* SSL backend-specific #if branches in this file must be kept in the order + documented in curl_ntlm_core. */ +#if defined(NTLM_NEEDS_NSS_INIT) +#include "vtls/nssg.h" +#elif defined(USE_WINDOWS_SSPI) +#include "curl_sspi.h" +#endif + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#if DEBUG_ME +# define DEBUG_OUT(x) x +#else +# define DEBUG_OUT(x) Curl_nop_stmt +#endif + +CURLcode Curl_input_ntlm(struct connectdata *conn, + bool proxy, /* if proxy or not */ + const char *header) /* rest of the www-authenticate: + header */ +{ + /* point to the correct struct with this */ + struct ntlmdata *ntlm; + curlntlm *state; + CURLcode result = CURLE_OK; + + ntlm = proxy ? &conn->proxyntlm : &conn->ntlm; + state = proxy ? &conn->proxy_ntlm_state : &conn->http_ntlm_state; + + if(checkprefix("NTLM", header)) { + header += strlen("NTLM"); + + while(*header && ISSPACE(*header)) + header++; + + if(*header) { + result = Curl_auth_decode_ntlm_type2_message(conn->data, header, ntlm); + if(result) + return result; + + *state = NTLMSTATE_TYPE2; /* We got a type-2 message */ + } + else { + if(*state == NTLMSTATE_LAST) { + infof(conn->data, "NTLM auth restarted\n"); + Curl_http_auth_cleanup_ntlm(conn); + } + else if(*state == NTLMSTATE_TYPE3) { + infof(conn->data, "NTLM handshake rejected\n"); + Curl_http_auth_cleanup_ntlm(conn); + *state = NTLMSTATE_NONE; + return CURLE_REMOTE_ACCESS_DENIED; + } + else if(*state >= NTLMSTATE_TYPE1) { + infof(conn->data, "NTLM handshake failure (internal error)\n"); + return CURLE_REMOTE_ACCESS_DENIED; + } + + *state = NTLMSTATE_TYPE1; /* We should send away a type-1 */ + } + } + + return result; +} + +/* + * This is for creating ntlm header output + */ +CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy) +{ + char *base64 = NULL; + size_t len = 0; + CURLcode result; + + /* point to the address of the pointer that holds the string to send to the + server, which is for a plain host or for a HTTP proxy */ + char **allocuserpwd; + + /* point to the username, password, service and host */ + const char *userp; + const char *passwdp; + const char *service = NULL; + const char *hostname = NULL; + + /* point to the correct struct with this */ + struct ntlmdata *ntlm; + curlntlm *state; + struct auth *authp; + + DEBUGASSERT(conn); + DEBUGASSERT(conn->data); + +#if defined(NTLM_NEEDS_NSS_INIT) + if(CURLE_OK != Curl_nss_force_init(conn->data)) + return CURLE_OUT_OF_MEMORY; +#endif + + if(proxy) { + allocuserpwd = &conn->allocptr.proxyuserpwd; + userp = conn->http_proxy.user; + passwdp = conn->http_proxy.passwd; + service = conn->data->set.str[STRING_PROXY_SERVICE_NAME] ? + conn->data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP"; + hostname = conn->http_proxy.host.name; + ntlm = &conn->proxyntlm; + state = &conn->proxy_ntlm_state; + authp = &conn->data->state.authproxy; + } + else { + allocuserpwd = &conn->allocptr.userpwd; + userp = conn->user; + passwdp = conn->passwd; + service = conn->data->set.str[STRING_SERVICE_NAME] ? + conn->data->set.str[STRING_SERVICE_NAME] : "HTTP"; + hostname = conn->host.name; + ntlm = &conn->ntlm; + state = &conn->http_ntlm_state; + authp = &conn->data->state.authhost; + } + authp->done = FALSE; + + /* not set means empty */ + if(!userp) + userp = ""; + + if(!passwdp) + passwdp = ""; + +#ifdef USE_WINDOWS_SSPI + if(s_hSecDll == NULL) { + /* not thread safe and leaks - use curl_global_init() to avoid */ + CURLcode err = Curl_sspi_global_init(); + if(s_hSecDll == NULL) + return err; + } +#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS + ntlm->sslContext = conn->sslContext; +#endif +#endif + + switch(*state) { + case NTLMSTATE_TYPE1: + default: /* for the weird cases we (re)start here */ + /* Create a type-1 message */ + result = Curl_auth_create_ntlm_type1_message(conn->data, userp, passwdp, + service, hostname, + ntlm, &base64, + &len); + if(result) + return result; + + if(base64) { + free(*allocuserpwd); + *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n", + proxy ? "Proxy-" : "", + base64); + free(base64); + if(!*allocuserpwd) + return CURLE_OUT_OF_MEMORY; + + DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd)); + } + break; + + case NTLMSTATE_TYPE2: + /* We already received the type-2 message, create a type-3 message */ + result = Curl_auth_create_ntlm_type3_message(conn->data, userp, passwdp, + ntlm, &base64, &len); + if(result) + return result; + + if(base64) { + free(*allocuserpwd); + *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n", + proxy ? "Proxy-" : "", + base64); + free(base64); + if(!*allocuserpwd) + return CURLE_OUT_OF_MEMORY; + + DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd)); + + *state = NTLMSTATE_TYPE3; /* we send a type-3 */ + authp->done = TRUE; + } + break; + + case NTLMSTATE_TYPE3: + /* connection is already authenticated, + * don't send a header in future requests */ + *state = NTLMSTATE_LAST; + /* FALLTHROUGH */ + case NTLMSTATE_LAST: + Curl_safefree(*allocuserpwd); + authp->done = TRUE; + break; + } + + return CURLE_OK; +} + +void Curl_http_auth_cleanup_ntlm(struct connectdata *conn) +{ + Curl_auth_cleanup_ntlm(&conn->ntlm); + Curl_auth_cleanup_ntlm(&conn->proxyntlm); + +#if defined(NTLM_WB_ENABLED) + Curl_http_auth_cleanup_ntlm_wb(conn); +#endif +} + +#endif /* !CURL_DISABLE_HTTP && USE_NTLM */ diff --git a/dependencies/cmcurl/lib/http_ntlm.h b/dependencies/cmcurl/lib/http_ntlm.h new file mode 100644 index 0000000..003714d --- /dev/null +++ b/dependencies/cmcurl/lib/http_ntlm.h @@ -0,0 +1,40 @@ +#ifndef HEADER_CURL_HTTP_NTLM_H +#define HEADER_CURL_HTTP_NTLM_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) + +/* this is for ntlm header input */ +CURLcode Curl_input_ntlm(struct connectdata *conn, bool proxy, + const char *header); + +/* this is for creating ntlm header output */ +CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy); + +void Curl_http_auth_cleanup_ntlm(struct connectdata *conn); + +#endif /* !CURL_DISABLE_HTTP && USE_NTLM */ + +#endif /* HEADER_CURL_HTTP_NTLM_H */ diff --git a/dependencies/cmcurl/lib/http_proxy.c b/dependencies/cmcurl/lib/http_proxy.c new file mode 100644 index 0000000..d7ed117 --- /dev/null +++ b/dependencies/cmcurl/lib/http_proxy.c @@ -0,0 +1,685 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "http_proxy.h" + +#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP) + +#include +#include "sendf.h" +#include "http.h" +#include "url.h" +#include "select.h" +#include "progress.h" +#include "non-ascii.h" +#include "connect.h" +#include "curlx.h" +#include "vtls/vtls.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Perform SSL initialization for HTTPS proxy. Sets + * proxy_ssl_connected connection bit when complete. Can be + * called multiple times. + */ +static CURLcode https_proxy_connect(struct connectdata *conn, int sockindex) +{ +#ifdef USE_SSL + CURLcode result = CURLE_OK; + DEBUGASSERT(conn->http_proxy.proxytype == CURLPROXY_HTTPS); + if(!conn->bits.proxy_ssl_connected[sockindex]) { + /* perform SSL initialization for this socket */ + result = + Curl_ssl_connect_nonblocking(conn, sockindex, + &conn->bits.proxy_ssl_connected[sockindex]); + if(result) + conn->bits.close = TRUE; /* a failed connection is marked for closure to + prevent (bad) re-use or similar */ + } + return result; +#else + (void) conn; + (void) sockindex; + return CURLE_NOT_BUILT_IN; +#endif +} + +CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex) +{ + if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) { + const CURLcode result = https_proxy_connect(conn, sockindex); + if(result) + return result; + if(!conn->bits.proxy_ssl_connected[sockindex]) + return result; /* wait for HTTPS proxy SSL initialization to complete */ + } + + if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { +#ifndef CURL_DISABLE_PROXY + /* for [protocol] tunneled through HTTP proxy */ + struct HTTP http_proxy; + void *prot_save; + const char *hostname; + int remote_port; + CURLcode result; + + /* BLOCKING */ + /* We want "seamless" operations through HTTP proxy tunnel */ + + /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the + * member conn->proto.http; we want [protocol] through HTTP and we have + * to change the member temporarily for connecting to the HTTP + * proxy. After Curl_proxyCONNECT we have to set back the member to the + * original pointer + * + * This function might be called several times in the multi interface case + * if the proxy's CONNECT response is not instant. + */ + prot_save = conn->data->req.protop; + memset(&http_proxy, 0, sizeof(http_proxy)); + conn->data->req.protop = &http_proxy; + connkeep(conn, "HTTP proxy CONNECT"); + + /* for the secondary socket (FTP), use the "connect to host" + * but ignore the "connect to port" (use the secondary port) + */ + + if(conn->bits.conn_to_host) + hostname = conn->conn_to_host.name; + else if(sockindex == SECONDARYSOCKET) + hostname = conn->secondaryhostname; + else + hostname = conn->host.name; + + if(sockindex == SECONDARYSOCKET) + remote_port = conn->secondary_port; + else if(conn->bits.conn_to_port) + remote_port = conn->conn_to_port; + else + remote_port = conn->remote_port; + result = Curl_proxyCONNECT(conn, sockindex, hostname, remote_port); + conn->data->req.protop = prot_save; + if(CURLE_OK != result) + return result; + Curl_safefree(conn->allocptr.proxyuserpwd); +#else + return CURLE_NOT_BUILT_IN; +#endif + } + /* no HTTP tunnel proxy, just return */ + return CURLE_OK; +} + +bool Curl_connect_complete(struct connectdata *conn) +{ + return !conn->connect_state || + (conn->connect_state->tunnel_state == TUNNEL_COMPLETE); +} + +bool Curl_connect_ongoing(struct connectdata *conn) +{ + return conn->connect_state && + (conn->connect_state->tunnel_state != TUNNEL_COMPLETE); +} + +static CURLcode connect_init(struct connectdata *conn, bool reinit) +{ + struct http_connect_state *s; + if(!reinit) { + DEBUGASSERT(!conn->connect_state); + s = calloc(1, sizeof(struct http_connect_state)); + if(!s) + return CURLE_OUT_OF_MEMORY; + infof(conn->data, "allocate connect buffer!\n"); + conn->connect_state = s; + } + else { + DEBUGASSERT(conn->connect_state); + s = conn->connect_state; + } + s->tunnel_state = TUNNEL_INIT; + s->keepon = TRUE; + s->line_start = s->connect_buffer; + s->ptr = s->line_start; + s->cl = 0; + s->close_connection = FALSE; + return CURLE_OK; +} + +static void connect_done(struct connectdata *conn) +{ + struct http_connect_state *s = conn->connect_state; + s->tunnel_state = TUNNEL_COMPLETE; + infof(conn->data, "CONNECT phase completed!\n"); +} + +static CURLcode CONNECT(struct connectdata *conn, + int sockindex, + const char *hostname, + int remote_port) +{ + int subversion = 0; + struct Curl_easy *data = conn->data; + struct SingleRequest *k = &data->req; + CURLcode result; + curl_socket_t tunnelsocket = conn->sock[sockindex]; + struct http_connect_state *s = conn->connect_state; + +#define SELECT_OK 0 +#define SELECT_ERROR 1 + + if(Curl_connect_complete(conn)) + return CURLE_OK; /* CONNECT is already completed */ + + conn->bits.proxy_connect_closed = FALSE; + + do { + timediff_t check; + if(TUNNEL_INIT == s->tunnel_state) { + /* BEGIN CONNECT PHASE */ + char *host_port; + Curl_send_buffer *req_buffer; + + infof(data, "Establish HTTP proxy tunnel to %s:%d\n", + hostname, remote_port); + + /* This only happens if we've looped here due to authentication + reasons, and we don't really use the newly cloned URL here + then. Just free() it. */ + free(data->req.newurl); + data->req.newurl = NULL; + + /* initialize a dynamic send-buffer */ + req_buffer = Curl_add_buffer_init(); + + if(!req_buffer) + return CURLE_OUT_OF_MEMORY; + + host_port = aprintf("%s:%d", hostname, remote_port); + if(!host_port) { + Curl_add_buffer_free(&req_buffer); + return CURLE_OUT_OF_MEMORY; + } + + /* Setup the proxy-authorization header, if any */ + result = Curl_http_output_auth(conn, "CONNECT", host_port, TRUE); + + free(host_port); + + if(!result) { + char *host = NULL; + const char *proxyconn = ""; + const char *useragent = ""; + const char *http = (conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ? + "1.0" : "1.1"; + bool ipv6_ip = conn->bits.ipv6_ip; + char *hostheader; + + /* the hostname may be different */ + if(hostname != conn->host.name) + ipv6_ip = (strchr(hostname, ':') != NULL); + hostheader = /* host:port with IPv6 support */ + aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"", + remote_port); + if(!hostheader) { + Curl_add_buffer_free(&req_buffer); + return CURLE_OUT_OF_MEMORY; + } + + if(!Curl_checkProxyheaders(conn, "Host")) { + host = aprintf("Host: %s\r\n", hostheader); + if(!host) { + free(hostheader); + Curl_add_buffer_free(&req_buffer); + return CURLE_OUT_OF_MEMORY; + } + } + if(!Curl_checkProxyheaders(conn, "Proxy-Connection")) + proxyconn = "Proxy-Connection: Keep-Alive\r\n"; + + if(!Curl_checkProxyheaders(conn, "User-Agent") && + data->set.str[STRING_USERAGENT]) + useragent = conn->allocptr.uagent; + + result = + Curl_add_bufferf(&req_buffer, + "CONNECT %s HTTP/%s\r\n" + "%s" /* Host: */ + "%s" /* Proxy-Authorization */ + "%s" /* User-Agent */ + "%s", /* Proxy-Connection */ + hostheader, + http, + host?host:"", + conn->allocptr.proxyuserpwd? + conn->allocptr.proxyuserpwd:"", + useragent, + proxyconn); + + if(host) + free(host); + free(hostheader); + + if(!result) + result = Curl_add_custom_headers(conn, TRUE, req_buffer); + + if(!result) + /* CRLF terminate the request */ + result = Curl_add_bufferf(&req_buffer, "\r\n"); + + if(!result) { + /* Send the connect request to the proxy */ + /* BLOCKING */ + result = + Curl_add_buffer_send(&req_buffer, conn, + &data->info.request_size, 0, sockindex); + } + req_buffer = NULL; + if(result) + failf(data, "Failed sending CONNECT to proxy"); + } + + Curl_add_buffer_free(&req_buffer); + if(result) + return result; + + s->tunnel_state = TUNNEL_CONNECT; + s->perline = 0; + } /* END CONNECT PHASE */ + + check = Curl_timeleft(data, NULL, TRUE); + if(check <= 0) { + failf(data, "Proxy CONNECT aborted due to timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + if(!Curl_conn_data_pending(conn, sockindex)) + /* return so we'll be called again polling-style */ + return CURLE_OK; + + /* at this point, the tunnel_connecting phase is over. */ + + { /* READING RESPONSE PHASE */ + int error = SELECT_OK; + + while(s->keepon && !error) { + ssize_t gotbytes; + + /* make sure we have space to read more data */ + if(s->ptr >= &s->connect_buffer[CONNECT_BUFFER_SIZE]) { + failf(data, "CONNECT response too large!"); + return CURLE_RECV_ERROR; + } + + /* Read one byte at a time to avoid a race condition. Wait at most one + second before looping to ensure continuous pgrsUpdates. */ + result = Curl_read(conn, tunnelsocket, s->ptr, 1, &gotbytes); + if(result == CURLE_AGAIN) + /* socket buffer drained, return */ + return CURLE_OK; + + if(Curl_pgrsUpdate(conn)) + return CURLE_ABORTED_BY_CALLBACK; + + if(result) { + s->keepon = FALSE; + break; + } + else if(gotbytes <= 0) { + if(data->set.proxyauth && data->state.authproxy.avail) { + /* proxy auth was requested and there was proxy auth available, + then deem this as "mere" proxy disconnect */ + conn->bits.proxy_connect_closed = TRUE; + infof(data, "Proxy CONNECT connection closed\n"); + } + else { + error = SELECT_ERROR; + failf(data, "Proxy CONNECT aborted"); + } + s->keepon = FALSE; + break; + } + + + if(s->keepon > TRUE) { + /* This means we are currently ignoring a response-body */ + + s->ptr = s->connect_buffer; + if(s->cl) { + /* A Content-Length based body: simply count down the counter + and make sure to break out of the loop when we're done! */ + s->cl--; + if(s->cl <= 0) { + s->keepon = FALSE; + s->tunnel_state = TUNNEL_COMPLETE; + break; + } + } + else { + /* chunked-encoded body, so we need to do the chunked dance + properly to know when the end of the body is reached */ + CHUNKcode r; + ssize_t tookcareof = 0; + + /* now parse the chunked piece of data so that we can + properly tell when the stream ends */ + r = Curl_httpchunk_read(conn, s->ptr, 1, &tookcareof); + if(r == CHUNKE_STOP) { + /* we're done reading chunks! */ + infof(data, "chunk reading DONE\n"); + s->keepon = FALSE; + /* we did the full CONNECT treatment, go COMPLETE */ + s->tunnel_state = TUNNEL_COMPLETE; + } + } + continue; + } + + s->perline++; /* amount of bytes in this line so far */ + + /* if this is not the end of a header line then continue */ + if(*s->ptr != 0x0a) { + s->ptr++; + continue; + } + + /* convert from the network encoding */ + result = Curl_convert_from_network(data, s->line_start, + (size_t)s->perline); + /* Curl_convert_from_network calls failf if unsuccessful */ + if(result) + return result; + + /* output debug if that is requested */ + if(data->set.verbose) + Curl_debug(data, CURLINFO_HEADER_IN, + s->line_start, (size_t)s->perline); + + if(!data->set.suppress_connect_headers) { + /* send the header to the callback */ + int writetype = CLIENTWRITE_HEADER; + if(data->set.include_header) + writetype |= CLIENTWRITE_BODY; + + result = Curl_client_write(conn, writetype, + s->line_start, s->perline); + if(result) + return result; + } + + data->info.header_size += (long)s->perline; + data->req.headerbytecount += (long)s->perline; + + /* Newlines are CRLF, so the CR is ignored as the line isn't + really terminated until the LF comes. Treat a following CR + as end-of-headers as well.*/ + + if(('\r' == s->line_start[0]) || + ('\n' == s->line_start[0])) { + /* end of response-headers from the proxy */ + s->ptr = s->connect_buffer; + if((407 == k->httpcode) && !data->state.authproblem) { + /* If we get a 407 response code with content length + when we have no auth problem, we must ignore the + whole response-body */ + s->keepon = 2; + + if(s->cl) { + infof(data, "Ignore %" CURL_FORMAT_CURL_OFF_T + " bytes of response-body\n", s->cl); + } + else if(s->chunked_encoding) { + CHUNKcode r; + + infof(data, "Ignore chunked response-body\n"); + + /* We set ignorebody true here since the chunked + decoder function will acknowledge that. Pay + attention so that this is cleared again when this + function returns! */ + k->ignorebody = TRUE; + + if(s->line_start[1] == '\n') { + /* this can only be a LF if the letter at index 0 + was a CR */ + s->line_start++; + } + + /* now parse the chunked piece of data so that we can + properly tell when the stream ends */ + r = Curl_httpchunk_read(conn, s->line_start + 1, 1, &gotbytes); + if(r == CHUNKE_STOP) { + /* we're done reading chunks! */ + infof(data, "chunk reading DONE\n"); + s->keepon = FALSE; + /* we did the full CONNECT treatment, go to COMPLETE */ + s->tunnel_state = TUNNEL_COMPLETE; + } + } + else { + /* without content-length or chunked encoding, we + can't keep the connection alive since the close is + the end signal so we bail out at once instead */ + s->keepon = FALSE; + } + } + else + s->keepon = FALSE; + if(!s->cl) + /* we did the full CONNECT treatment, go to COMPLETE */ + s->tunnel_state = TUNNEL_COMPLETE; + continue; + } + + s->line_start[s->perline] = 0; /* zero terminate the buffer */ + if((checkprefix("WWW-Authenticate:", s->line_start) && + (401 == k->httpcode)) || + (checkprefix("Proxy-authenticate:", s->line_start) && + (407 == k->httpcode))) { + + bool proxy = (k->httpcode == 407) ? TRUE : FALSE; + char *auth = Curl_copy_header_value(s->line_start); + if(!auth) + return CURLE_OUT_OF_MEMORY; + + result = Curl_http_input_auth(conn, proxy, auth); + + free(auth); + + if(result) + return result; + } + else if(checkprefix("Content-Length:", s->line_start)) { + if(k->httpcode/100 == 2) { + /* A client MUST ignore any Content-Length or Transfer-Encoding + header fields received in a successful response to CONNECT. + "Successful" described as: 2xx (Successful). RFC 7231 4.3.6 */ + infof(data, "Ignoring Content-Length in CONNECT %03d response\n", + k->httpcode); + } + else { + (void)curlx_strtoofft(s->line_start + + strlen("Content-Length:"), NULL, 10, &s->cl); + } + } + else if(Curl_compareheader(s->line_start, "Connection:", "close")) + s->close_connection = TRUE; + else if(checkprefix("Transfer-Encoding:", s->line_start)) { + if(k->httpcode/100 == 2) { + /* A client MUST ignore any Content-Length or Transfer-Encoding + header fields received in a successful response to CONNECT. + "Successful" described as: 2xx (Successful). RFC 7231 4.3.6 */ + infof(data, "Ignoring Transfer-Encoding in " + "CONNECT %03d response\n", k->httpcode); + } + else if(Curl_compareheader(s->line_start, + "Transfer-Encoding:", "chunked")) { + infof(data, "CONNECT responded chunked\n"); + s->chunked_encoding = TRUE; + /* init our chunky engine */ + Curl_httpchunk_init(conn); + } + } + else if(Curl_compareheader(s->line_start, + "Proxy-Connection:", "close")) + s->close_connection = TRUE; + else if(2 == sscanf(s->line_start, "HTTP/1.%d %d", + &subversion, + &k->httpcode)) { + /* store the HTTP code from the proxy */ + data->info.httpproxycode = k->httpcode; + } + + s->perline = 0; /* line starts over here */ + s->ptr = s->connect_buffer; + s->line_start = s->ptr; + } /* while there's buffer left and loop is requested */ + + if(Curl_pgrsUpdate(conn)) + return CURLE_ABORTED_BY_CALLBACK; + + if(error) + return CURLE_RECV_ERROR; + + if(data->info.httpproxycode/100 != 2) { + /* Deal with the possibly already received authenticate + headers. 'newurl' is set to a new URL if we must loop. */ + result = Curl_http_auth_act(conn); + if(result) + return result; + + if(conn->bits.close) + /* the connection has been marked for closure, most likely in the + Curl_http_auth_act() function and thus we can kill it at once + below */ + s->close_connection = TRUE; + } + + if(s->close_connection && data->req.newurl) { + /* Connection closed by server. Don't use it anymore */ + Curl_closesocket(conn, conn->sock[sockindex]); + conn->sock[sockindex] = CURL_SOCKET_BAD; + break; + } + } /* END READING RESPONSE PHASE */ + + /* If we are supposed to continue and request a new URL, which basically + * means the HTTP authentication is still going on so if the tunnel + * is complete we start over in INIT state */ + if(data->req.newurl && (TUNNEL_COMPLETE == s->tunnel_state)) { + connect_init(conn, TRUE); /* reinit */ + } + + } while(data->req.newurl); + + if(data->info.httpproxycode/100 != 2) { + if(s->close_connection && data->req.newurl) { + conn->bits.proxy_connect_closed = TRUE; + infof(data, "Connect me again please\n"); + connect_done(conn); + } + else { + free(data->req.newurl); + data->req.newurl = NULL; + /* failure, close this connection to avoid re-use */ + streamclose(conn, "proxy CONNECT failure"); + Curl_closesocket(conn, conn->sock[sockindex]); + conn->sock[sockindex] = CURL_SOCKET_BAD; + } + + /* to back to init state */ + s->tunnel_state = TUNNEL_INIT; + + if(conn->bits.proxy_connect_closed) + /* this is not an error, just part of the connection negotiation */ + return CURLE_OK; + failf(data, "Received HTTP code %d from proxy after CONNECT", + data->req.httpcode); + return CURLE_RECV_ERROR; + } + + s->tunnel_state = TUNNEL_COMPLETE; + + /* If a proxy-authorization header was used for the proxy, then we should + make sure that it isn't accidentally used for the document request + after we've connected. So let's free and clear it here. */ + Curl_safefree(conn->allocptr.proxyuserpwd); + conn->allocptr.proxyuserpwd = NULL; + + data->state.authproxy.done = TRUE; + + infof(data, "Proxy replied %d to CONNECT request\n", + data->info.httpproxycode); + data->req.ignorebody = FALSE; /* put it (back) to non-ignore state */ + conn->bits.rewindaftersend = FALSE; /* make sure this isn't set for the + document request */ + return CURLE_OK; +} + +void Curl_connect_free(struct Curl_easy *data) +{ + struct connectdata *conn = data->conn; + struct http_connect_state *s = conn->connect_state; + if(s) { + free(s); + conn->connect_state = NULL; + } +} + +/* + * Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This + * function will issue the necessary commands to get a seamless tunnel through + * this proxy. After that, the socket can be used just as a normal socket. + */ + +CURLcode Curl_proxyCONNECT(struct connectdata *conn, + int sockindex, + const char *hostname, + int remote_port) +{ + CURLcode result; + if(!conn->connect_state) { + result = connect_init(conn, FALSE); + if(result) + return result; + } + result = CONNECT(conn, sockindex, hostname, remote_port); + + if(result || Curl_connect_complete(conn)) + connect_done(conn); + + return result; +} + +#else +void Curl_connect_free(struct Curl_easy *data) +{ + (void)data; +} + +#endif /* CURL_DISABLE_PROXY */ diff --git a/dependencies/cmcurl/lib/http_proxy.h b/dependencies/cmcurl/lib/http_proxy.h new file mode 100644 index 0000000..e19fa85 --- /dev/null +++ b/dependencies/cmcurl/lib/http_proxy.h @@ -0,0 +1,51 @@ +#ifndef HEADER_CURL_HTTP_PROXY_H +#define HEADER_CURL_HTTP_PROXY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include "urldata.h" + +#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP) +/* ftp can use this as well */ +CURLcode Curl_proxyCONNECT(struct connectdata *conn, + int tunnelsocket, + const char *hostname, int remote_port); + +/* Default proxy timeout in milliseconds */ +#define PROXY_TIMEOUT (3600*1000) + +CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex); + +bool Curl_connect_complete(struct connectdata *conn); +bool Curl_connect_ongoing(struct connectdata *conn); + +#else +#define Curl_proxyCONNECT(x,y,z,w) CURLE_NOT_BUILT_IN +#define Curl_proxy_connect(x,y) CURLE_OK +#define Curl_connect_complete(x) CURLE_OK +#define Curl_connect_ongoing(x) FALSE +#endif + +void Curl_connect_free(struct Curl_easy *data); + +#endif /* HEADER_CURL_HTTP_PROXY_H */ diff --git a/dependencies/cmcurl/lib/idn_win32.c b/dependencies/cmcurl/lib/idn_win32.c new file mode 100644 index 0000000..8dc300b --- /dev/null +++ b/dependencies/cmcurl/lib/idn_win32.c @@ -0,0 +1,111 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + + /* + * IDN conversions using Windows kernel32 and normaliz libraries. + */ + +#include "curl_setup.h" + +#ifdef USE_WIN32_IDN + +#include "curl_multibyte.h" +#include "curl_memory.h" +#include "warnless.h" + + /* The last #include file should be: */ +#include "memdebug.h" + +#ifdef WANT_IDN_PROTOTYPES +# if defined(_SAL_VERSION) +WINNORMALIZEAPI int WINAPI +IdnToAscii(_In_ DWORD dwFlags, + _In_reads_(cchUnicodeChar) LPCWSTR lpUnicodeCharStr, + _In_ int cchUnicodeChar, + _Out_writes_opt_(cchASCIIChar) LPWSTR lpASCIICharStr, + _In_ int cchASCIIChar); +WINNORMALIZEAPI int WINAPI +IdnToUnicode(_In_ DWORD dwFlags, + _In_reads_(cchASCIIChar) LPCWSTR lpASCIICharStr, + _In_ int cchASCIIChar, + _Out_writes_opt_(cchUnicodeChar) LPWSTR lpUnicodeCharStr, + _In_ int cchUnicodeChar); +# else +WINBASEAPI int WINAPI IdnToAscii(DWORD dwFlags, + const WCHAR *lpUnicodeCharStr, + int cchUnicodeChar, + WCHAR *lpASCIICharStr, + int cchASCIIChar); +WINBASEAPI int WINAPI IdnToUnicode(DWORD dwFlags, + const WCHAR *lpASCIICharStr, + int cchASCIIChar, + WCHAR *lpUnicodeCharStr, + int cchUnicodeChar); +# endif +#endif + +#define IDN_MAX_LENGTH 255 + +bool curl_win32_idn_to_ascii(const char *in, char **out); +bool curl_win32_ascii_to_idn(const char *in, char **out); + +bool curl_win32_idn_to_ascii(const char *in, char **out) +{ + bool success = FALSE; + + wchar_t *in_w = Curl_convert_UTF8_to_wchar(in); + if(in_w) { + wchar_t punycode[IDN_MAX_LENGTH]; + int chars = IdnToAscii(0, in_w, -1, punycode, IDN_MAX_LENGTH); + free(in_w); + if(chars) { + *out = Curl_convert_wchar_to_UTF8(punycode); + if(*out) + success = TRUE; + } + } + + return success; +} + +bool curl_win32_ascii_to_idn(const char *in, char **out) +{ + bool success = FALSE; + + wchar_t *in_w = Curl_convert_UTF8_to_wchar(in); + if(in_w) { + size_t in_len = wcslen(in_w) + 1; + wchar_t unicode[IDN_MAX_LENGTH]; + int chars = IdnToUnicode(0, in_w, curlx_uztosi(in_len), + unicode, IDN_MAX_LENGTH); + free(in_w); + if(chars) { + *out = Curl_convert_wchar_to_UTF8(unicode); + if(*out) + success = TRUE; + } + } + + return success; +} + +#endif /* USE_WIN32_IDN */ diff --git a/dependencies/cmcurl/lib/if2ip.c b/dependencies/cmcurl/lib/if2ip.c new file mode 100644 index 0000000..d003de6 --- /dev/null +++ b/dependencies/cmcurl/lib/if2ip.c @@ -0,0 +1,243 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_ARPA_INET_H +# include +#endif +#ifdef HAVE_NET_IF_H +# include +#endif +#ifdef HAVE_SYS_IOCTL_H +# include +#endif +#ifdef HAVE_NETDB_H +# include +#endif +#ifdef HAVE_SYS_SOCKIO_H +# include +#endif +#ifdef HAVE_IFADDRS_H +# include +#endif +#ifdef HAVE_STROPTS_H +# include +#endif +#ifdef __VMS +# include +#endif + +#include "inet_ntop.h" +#include "strcase.h" +#include "if2ip.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* ------------------------------------------------------------------ */ + +/* Return the scope of the given address. */ +unsigned int Curl_ipv6_scope(const struct sockaddr *sa) +{ +#ifndef ENABLE_IPV6 + (void) sa; +#else + if(sa->sa_family == AF_INET6) { + const struct sockaddr_in6 * sa6 = (const struct sockaddr_in6 *)(void *) sa; + const unsigned char *b = sa6->sin6_addr.s6_addr; + unsigned short w = (unsigned short) ((b[0] << 8) | b[1]); + + if((b[0] & 0xFE) == 0xFC) /* Handle ULAs */ + return IPV6_SCOPE_UNIQUELOCAL; + switch(w & 0xFFC0) { + case 0xFE80: + return IPV6_SCOPE_LINKLOCAL; + case 0xFEC0: + return IPV6_SCOPE_SITELOCAL; + case 0x0000: + w = b[1] | b[2] | b[3] | b[4] | b[5] | b[6] | b[7] | b[8] | b[9] | + b[10] | b[11] | b[12] | b[13] | b[14]; + if(w || b[15] != 0x01) + break; + return IPV6_SCOPE_NODELOCAL; + default: + break; + } + } +#endif + + return IPV6_SCOPE_GLOBAL; +} + + +#if defined(HAVE_GETIFADDRS) + +if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope, + unsigned int local_scope_id, const char *interf, + char *buf, int buf_size) +{ + struct ifaddrs *iface, *head; + if2ip_result_t res = IF2IP_NOT_FOUND; + +#ifndef ENABLE_IPV6 + (void) remote_scope; +#endif + +#if !defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) || \ + !defined(ENABLE_IPV6) + (void) local_scope_id; +#endif + + if(getifaddrs(&head) >= 0) { + for(iface = head; iface != NULL; iface = iface->ifa_next) { + if(iface->ifa_addr != NULL) { + if(iface->ifa_addr->sa_family == af) { + if(strcasecompare(iface->ifa_name, interf)) { + void *addr; + char *ip; + char scope[12] = ""; + char ipstr[64]; +#ifdef ENABLE_IPV6 + if(af == AF_INET6) { +#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID + unsigned int scopeid = 0; +#endif + unsigned int ifscope = Curl_ipv6_scope(iface->ifa_addr); + + if(ifscope != remote_scope) { + /* We are interested only in interface addresses whose + scope matches the remote address we want to + connect to: global for global, link-local for + link-local, etc... */ + if(res == IF2IP_NOT_FOUND) res = IF2IP_AF_NOT_SUPPORTED; + continue; + } + + addr = + &((struct sockaddr_in6 *)(void *)iface->ifa_addr)->sin6_addr; +#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID + /* Include the scope of this interface as part of the address */ + scopeid = ((struct sockaddr_in6 *)(void *)iface->ifa_addr) + ->sin6_scope_id; + + /* If given, scope id should match. */ + if(local_scope_id && scopeid != local_scope_id) { + if(res == IF2IP_NOT_FOUND) + res = IF2IP_AF_NOT_SUPPORTED; + + continue; + } + + if(scopeid) + msnprintf(scope, sizeof(scope), "%%%u", scopeid); +#endif + } + else +#endif + addr = + &((struct sockaddr_in *)(void *)iface->ifa_addr)->sin_addr; + res = IF2IP_FOUND; + ip = (char *) Curl_inet_ntop(af, addr, ipstr, sizeof(ipstr)); + msnprintf(buf, buf_size, "%s%s", ip, scope); + break; + } + } + else if((res == IF2IP_NOT_FOUND) && + strcasecompare(iface->ifa_name, interf)) { + res = IF2IP_AF_NOT_SUPPORTED; + } + } + } + + freeifaddrs(head); + } + + return res; +} + +#elif defined(HAVE_IOCTL_SIOCGIFADDR) + +if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope, + unsigned int local_scope_id, const char *interf, + char *buf, int buf_size) +{ + struct ifreq req; + struct in_addr in; + struct sockaddr_in *s; + curl_socket_t dummy; + size_t len; + + (void)remote_scope; + (void)local_scope_id; + + if(!interf || (af != AF_INET)) + return IF2IP_NOT_FOUND; + + len = strlen(interf); + if(len >= sizeof(req.ifr_name)) + return IF2IP_NOT_FOUND; + + dummy = socket(AF_INET, SOCK_STREAM, 0); + if(CURL_SOCKET_BAD == dummy) + return IF2IP_NOT_FOUND; + + memset(&req, 0, sizeof(req)); + memcpy(req.ifr_name, interf, len + 1); + req.ifr_addr.sa_family = AF_INET; + + if(ioctl(dummy, SIOCGIFADDR, &req) < 0) { + sclose(dummy); + /* With SIOCGIFADDR, we cannot tell the difference between an interface + that does not exist and an interface that has no address of the + correct family. Assume the interface does not exist */ + return IF2IP_NOT_FOUND; + } + + s = (struct sockaddr_in *)(void *)&req.ifr_addr; + memcpy(&in, &s->sin_addr, sizeof(in)); + Curl_inet_ntop(s->sin_family, &in, buf, buf_size); + + sclose(dummy); + return IF2IP_FOUND; +} + +#else + +if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope, + unsigned int local_scope_id, const char *interf, + char *buf, int buf_size) +{ + (void) af; + (void) remote_scope; + (void) local_scope_id; + (void) interf; + (void) buf; + (void) buf_size; + return IF2IP_NOT_FOUND; +} + +#endif diff --git a/dependencies/cmcurl/lib/if2ip.h b/dependencies/cmcurl/lib/if2ip.h new file mode 100644 index 0000000..f193d42 --- /dev/null +++ b/dependencies/cmcurl/lib/if2ip.h @@ -0,0 +1,82 @@ +#ifndef HEADER_CURL_IF2IP_H +#define HEADER_CURL_IF2IP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +/* IPv6 address scopes. */ +#define IPV6_SCOPE_GLOBAL 0 /* Global scope. */ +#define IPV6_SCOPE_LINKLOCAL 1 /* Link-local scope. */ +#define IPV6_SCOPE_SITELOCAL 2 /* Site-local scope (deprecated). */ +#define IPV6_SCOPE_UNIQUELOCAL 3 /* Unique local */ +#define IPV6_SCOPE_NODELOCAL 4 /* Loopback. */ + +unsigned int Curl_ipv6_scope(const struct sockaddr *sa); + +typedef enum { + IF2IP_NOT_FOUND = 0, /* Interface not found */ + IF2IP_AF_NOT_SUPPORTED = 1, /* Int. exists but has no address for this af */ + IF2IP_FOUND = 2 /* The address has been stored in "buf" */ +} if2ip_result_t; + +if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope, + unsigned int local_scope_id, const char *interf, + char *buf, int buf_size); + +#ifdef __INTERIX + +/* Nedelcho Stanev's work-around for SFU 3.0 */ +struct ifreq { +#define IFNAMSIZ 16 +#define IFHWADDRLEN 6 + union { + char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + } ifr_ifrn; + + union { + struct sockaddr ifru_addr; + struct sockaddr ifru_broadaddr; + struct sockaddr ifru_netmask; + struct sockaddr ifru_hwaddr; + short ifru_flags; + int ifru_metric; + int ifru_mtu; + } ifr_ifru; +}; + +/* This define was added by Daniel to avoid an extra #ifdef INTERIX in the + C code. */ + +#define ifr_name ifr_ifrn.ifrn_name /* interface name */ +#define ifr_addr ifr_ifru.ifru_addr /* address */ +#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ +#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */ +#define ifr_flags ifr_ifru.ifru_flags /* flags */ +#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ +#define ifr_metric ifr_ifru.ifru_metric /* metric */ +#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ + +#define SIOCGIFADDR _IOW('s', 102, struct ifreq) /* Get if addr */ + +#endif /* __INTERIX */ + +#endif /* HEADER_CURL_IF2IP_H */ diff --git a/dependencies/cmcurl/lib/imap.c b/dependencies/cmcurl/lib/imap.c new file mode 100644 index 0000000..bdcc69c --- /dev/null +++ b/dependencies/cmcurl/lib/imap.c @@ -0,0 +1,2112 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC2195 CRAM-MD5 authentication + * RFC2595 Using TLS with IMAP, POP3 and ACAP + * RFC2831 DIGEST-MD5 authentication + * RFC3501 IMAPv4 protocol + * RFC4422 Simple Authentication and Security Layer (SASL) + * RFC4616 PLAIN authentication + * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism + * RFC4959 IMAP Extension for SASL Initial Client Response + * RFC5092 IMAP URL Scheme + * RFC6749 OAuth 2.0 Authorization Framework + * RFC8314 Use of TLS for Email Submission and Access + * Draft LOGIN SASL Mechanism + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_IMAP + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_UTSNAME_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +#include +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "progress.h" +#include "transfer.h" +#include "escape.h" +#include "http.h" /* for HTTP proxy tunnel stuff */ +#include "socks.h" +#include "imap.h" +#include "mime.h" +#include "strtoofft.h" +#include "strcase.h" +#include "vtls/vtls.h" +#include "connect.h" +#include "strerror.h" +#include "select.h" +#include "multiif.h" +#include "url.h" +#include "strcase.h" +#include "curl_sasl.h" +#include "warnless.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* Local API functions */ +static CURLcode imap_regular_transfer(struct connectdata *conn, bool *done); +static CURLcode imap_do(struct connectdata *conn, bool *done); +static CURLcode imap_done(struct connectdata *conn, CURLcode status, + bool premature); +static CURLcode imap_connect(struct connectdata *conn, bool *done); +static CURLcode imap_disconnect(struct connectdata *conn, bool dead); +static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done); +static int imap_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); +static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done); +static CURLcode imap_setup_connection(struct connectdata *conn); +static char *imap_atom(const char *str, bool escape_only); +static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...); +static CURLcode imap_parse_url_options(struct connectdata *conn); +static CURLcode imap_parse_url_path(struct connectdata *conn); +static CURLcode imap_parse_custom_request(struct connectdata *conn); +static CURLcode imap_perform_authenticate(struct connectdata *conn, + const char *mech, + const char *initresp); +static CURLcode imap_continue_authenticate(struct connectdata *conn, + const char *resp); +static void imap_get_message(char *buffer, char **outptr); + +/* + * IMAP protocol handler. + */ + +const struct Curl_handler Curl_handler_imap = { + "IMAP", /* scheme */ + imap_setup_connection, /* setup_connection */ + imap_do, /* do_it */ + imap_done, /* done */ + ZERO_NULL, /* do_more */ + imap_connect, /* connect_it */ + imap_multi_statemach, /* connecting */ + imap_doing, /* doing */ + imap_getsock, /* proto_getsock */ + imap_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + imap_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_IMAP, /* defport */ + CURLPROTO_IMAP, /* protocol */ + PROTOPT_CLOSEACTION| /* flags */ + PROTOPT_URLOPTIONS +}; + +#ifdef USE_SSL +/* + * IMAPS protocol handler. + */ + +const struct Curl_handler Curl_handler_imaps = { + "IMAPS", /* scheme */ + imap_setup_connection, /* setup_connection */ + imap_do, /* do_it */ + imap_done, /* done */ + ZERO_NULL, /* do_more */ + imap_connect, /* connect_it */ + imap_multi_statemach, /* connecting */ + imap_doing, /* doing */ + imap_getsock, /* proto_getsock */ + imap_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + imap_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_IMAPS, /* defport */ + CURLPROTO_IMAPS, /* protocol */ + PROTOPT_CLOSEACTION | PROTOPT_SSL | /* flags */ + PROTOPT_URLOPTIONS +}; +#endif + +#define IMAP_RESP_OK 1 +#define IMAP_RESP_NOT_OK 2 +#define IMAP_RESP_PREAUTH 3 + +/* SASL parameters for the imap protocol */ +static const struct SASLproto saslimap = { + "imap", /* The service name */ + '+', /* Code received when continuation is expected */ + IMAP_RESP_OK, /* Code to receive upon authentication success */ + 0, /* Maximum initial response length (no max) */ + imap_perform_authenticate, /* Send authentication command */ + imap_continue_authenticate, /* Send authentication continuation */ + imap_get_message /* Get SASL response message */ +}; + + +#ifdef USE_SSL +static void imap_to_imaps(struct connectdata *conn) +{ + /* Change the connection handler */ + conn->handler = &Curl_handler_imaps; + + /* Set the connection's upgraded to TLS flag */ + conn->tls_upgraded = TRUE; +} +#else +#define imap_to_imaps(x) Curl_nop_stmt +#endif + +/*********************************************************************** + * + * imap_matchresp() + * + * Determines whether the untagged response is related to the specified + * command by checking if it is in format "* ..." or + * "* ...". + * + * The "* " marker is assumed to have already been checked by the caller. + */ +static bool imap_matchresp(const char *line, size_t len, const char *cmd) +{ + const char *end = line + len; + size_t cmd_len = strlen(cmd); + + /* Skip the untagged response marker */ + line += 2; + + /* Do we have a number after the marker? */ + if(line < end && ISDIGIT(*line)) { + /* Skip the number */ + do + line++; + while(line < end && ISDIGIT(*line)); + + /* Do we have the space character? */ + if(line == end || *line != ' ') + return FALSE; + + line++; + } + + /* Does the command name match and is it followed by a space character or at + the end of line? */ + if(line + cmd_len <= end && strncasecompare(line, cmd, cmd_len) && + (line[cmd_len] == ' ' || line + cmd_len + 2 == end)) + return TRUE; + + return FALSE; +} + +/*********************************************************************** + * + * imap_endofresp() + * + * Checks whether the given string is a valid tagged, untagged or continuation + * response which can be processed by the response handler. + */ +static bool imap_endofresp(struct connectdata *conn, char *line, size_t len, + int *resp) +{ + struct IMAP *imap = conn->data->req.protop; + struct imap_conn *imapc = &conn->proto.imapc; + const char *id = imapc->resptag; + size_t id_len = strlen(id); + + /* Do we have a tagged command response? */ + if(len >= id_len + 1 && !memcmp(id, line, id_len) && line[id_len] == ' ') { + line += id_len + 1; + len -= id_len + 1; + + if(len >= 2 && !memcmp(line, "OK", 2)) + *resp = IMAP_RESP_OK; + else if(len >= 7 && !memcmp(line, "PREAUTH", 7)) + *resp = IMAP_RESP_PREAUTH; + else + *resp = IMAP_RESP_NOT_OK; + + return TRUE; + } + + /* Do we have an untagged command response? */ + if(len >= 2 && !memcmp("* ", line, 2)) { + switch(imapc->state) { + /* States which are interested in untagged responses */ + case IMAP_CAPABILITY: + if(!imap_matchresp(line, len, "CAPABILITY")) + return FALSE; + break; + + case IMAP_LIST: + if((!imap->custom && !imap_matchresp(line, len, "LIST")) || + (imap->custom && !imap_matchresp(line, len, imap->custom) && + (!strcasecompare(imap->custom, "STORE") || + !imap_matchresp(line, len, "FETCH")) && + !strcasecompare(imap->custom, "SELECT") && + !strcasecompare(imap->custom, "EXAMINE") && + !strcasecompare(imap->custom, "SEARCH") && + !strcasecompare(imap->custom, "EXPUNGE") && + !strcasecompare(imap->custom, "LSUB") && + !strcasecompare(imap->custom, "UID") && + !strcasecompare(imap->custom, "NOOP"))) + return FALSE; + break; + + case IMAP_SELECT: + /* SELECT is special in that its untagged responses do not have a + common prefix so accept anything! */ + break; + + case IMAP_FETCH: + if(!imap_matchresp(line, len, "FETCH")) + return FALSE; + break; + + case IMAP_SEARCH: + if(!imap_matchresp(line, len, "SEARCH")) + return FALSE; + break; + + /* Ignore other untagged responses */ + default: + return FALSE; + } + + *resp = '*'; + return TRUE; + } + + /* Do we have a continuation response? This should be a + symbol followed by + a space and optionally some text as per RFC-3501 for the AUTHENTICATE and + APPEND commands and as outlined in Section 4. Examples of RFC-4959 but + some e-mail servers ignore this and only send a single + instead. */ + if(imap && !imap->custom && ((len == 3 && line[0] == '+') || + (len >= 2 && !memcmp("+ ", line, 2)))) { + switch(imapc->state) { + /* States which are interested in continuation responses */ + case IMAP_AUTHENTICATE: + case IMAP_APPEND: + *resp = '+'; + break; + + default: + failf(conn->data, "Unexpected continuation response"); + *resp = -1; + break; + } + + return TRUE; + } + + return FALSE; /* Nothing for us */ +} + +/*********************************************************************** + * + * imap_get_message() + * + * Gets the authentication message from the response buffer. + */ +static void imap_get_message(char *buffer, char **outptr) +{ + size_t len = strlen(buffer); + char *message = NULL; + + if(len > 2) { + /* Find the start of the message */ + len -= 2; + for(message = buffer + 2; *message == ' ' || *message == '\t'; + message++, len--) + ; + + /* Find the end of the message */ + for(; len--;) + if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' && + message[len] != '\t') + break; + + /* Terminate the message */ + if(++len) { + message[len] = '\0'; + } + } + else + /* junk input => zero length output */ + message = &buffer[len]; + + *outptr = message; +} + +/*********************************************************************** + * + * state() + * + * This is the ONLY way to change IMAP state! + */ +static void state(struct connectdata *conn, imapstate newstate) +{ + struct imap_conn *imapc = &conn->proto.imapc; +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* for debug purposes */ + static const char * const names[]={ + "STOP", + "SERVERGREET", + "CAPABILITY", + "STARTTLS", + "UPGRADETLS", + "AUTHENTICATE", + "LOGIN", + "LIST", + "SELECT", + "FETCH", + "FETCH_FINAL", + "APPEND", + "APPEND_FINAL", + "SEARCH", + "LOGOUT", + /* LAST */ + }; + + if(imapc->state != newstate) + infof(conn->data, "IMAP %p state change from %s to %s\n", + (void *)imapc, names[imapc->state], names[newstate]); +#endif + + imapc->state = newstate; +} + +/*********************************************************************** + * + * imap_perform_capability() + * + * Sends the CAPABILITY command in order to obtain a list of server side + * supported capabilities. + */ +static CURLcode imap_perform_capability(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct imap_conn *imapc = &conn->proto.imapc; + imapc->sasl.authmechs = SASL_AUTH_NONE; /* No known auth. mechanisms yet */ + imapc->sasl.authused = SASL_AUTH_NONE; /* Clear the auth. mechanism used */ + imapc->tls_supported = FALSE; /* Clear the TLS capability */ + + /* Send the CAPABILITY command */ + result = imap_sendf(conn, "CAPABILITY"); + + if(!result) + state(conn, IMAP_CAPABILITY); + + return result; +} + +/*********************************************************************** + * + * imap_perform_starttls() + * + * Sends the STARTTLS command to start the upgrade to TLS. + */ +static CURLcode imap_perform_starttls(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + /* Send the STARTTLS command */ + result = imap_sendf(conn, "STARTTLS"); + + if(!result) + state(conn, IMAP_STARTTLS); + + return result; +} + +/*********************************************************************** + * + * imap_perform_upgrade_tls() + * + * Performs the upgrade to TLS. + */ +static CURLcode imap_perform_upgrade_tls(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct imap_conn *imapc = &conn->proto.imapc; + + /* Start the SSL connection */ + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &imapc->ssldone); + + if(!result) { + if(imapc->state != IMAP_UPGRADETLS) + state(conn, IMAP_UPGRADETLS); + + if(imapc->ssldone) { + imap_to_imaps(conn); + result = imap_perform_capability(conn); + } + } + + return result; +} + +/*********************************************************************** + * + * imap_perform_login() + * + * Sends a clear text LOGIN command to authenticate with. + */ +static CURLcode imap_perform_login(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + char *user; + char *passwd; + + /* Check we have a username and password to authenticate with and end the + connect phase if we don't */ + if(!conn->bits.user_passwd) { + state(conn, IMAP_STOP); + + return result; + } + + /* Make sure the username and password are in the correct atom format */ + user = imap_atom(conn->user, false); + passwd = imap_atom(conn->passwd, false); + + /* Send the LOGIN command */ + result = imap_sendf(conn, "LOGIN %s %s", user ? user : "", + passwd ? passwd : ""); + + free(user); + free(passwd); + + if(!result) + state(conn, IMAP_LOGIN); + + return result; +} + +/*********************************************************************** + * + * imap_perform_authenticate() + * + * Sends an AUTHENTICATE command allowing the client to login with the given + * SASL authentication mechanism. + */ +static CURLcode imap_perform_authenticate(struct connectdata *conn, + const char *mech, + const char *initresp) +{ + CURLcode result = CURLE_OK; + + if(initresp) { + /* Send the AUTHENTICATE command with the initial response */ + result = imap_sendf(conn, "AUTHENTICATE %s %s", mech, initresp); + } + else { + /* Send the AUTHENTICATE command */ + result = imap_sendf(conn, "AUTHENTICATE %s", mech); + } + + return result; +} + +/*********************************************************************** + * + * imap_continue_authenticate() + * + * Sends SASL continuation data or cancellation. + */ +static CURLcode imap_continue_authenticate(struct connectdata *conn, + const char *resp) +{ + struct imap_conn *imapc = &conn->proto.imapc; + + return Curl_pp_sendf(&imapc->pp, "%s", resp); +} + +/*********************************************************************** + * + * imap_perform_authentication() + * + * Initiates the authentication sequence, with the appropriate SASL + * authentication mechanism, falling back to clear text should a common + * mechanism not be available between the client and server. + */ +static CURLcode imap_perform_authentication(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct imap_conn *imapc = &conn->proto.imapc; + saslprogress progress; + + /* Check if already authenticated OR if there is enough data to authenticate + with and end the connect phase if we don't */ + if(imapc->preauth || + !Curl_sasl_can_authenticate(&imapc->sasl, conn)) { + state(conn, IMAP_STOP); + return result; + } + + /* Calculate the SASL login details */ + result = Curl_sasl_start(&imapc->sasl, conn, imapc->ir_supported, &progress); + + if(!result) { + if(progress == SASL_INPROGRESS) + state(conn, IMAP_AUTHENTICATE); + else if(!imapc->login_disabled && (imapc->preftype & IMAP_TYPE_CLEARTEXT)) + /* Perform clear text authentication */ + result = imap_perform_login(conn); + else { + /* Other mechanisms not supported */ + infof(conn->data, "No known authentication mechanisms supported!\n"); + result = CURLE_LOGIN_DENIED; + } + } + + return result; +} + +/*********************************************************************** + * + * imap_perform_list() + * + * Sends a LIST command or an alternative custom request. + */ +static CURLcode imap_perform_list(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct IMAP *imap = data->req.protop; + + if(imap->custom) + /* Send the custom request */ + result = imap_sendf(conn, "%s%s", imap->custom, + imap->custom_params ? imap->custom_params : ""); + else { + /* Make sure the mailbox is in the correct atom format if necessary */ + char *mailbox = imap->mailbox ? imap_atom(imap->mailbox, true) + : strdup(""); + if(!mailbox) + return CURLE_OUT_OF_MEMORY; + + /* Send the LIST command */ + result = imap_sendf(conn, "LIST \"%s\" *", mailbox); + + free(mailbox); + } + + if(!result) + state(conn, IMAP_LIST); + + return result; +} + +/*********************************************************************** + * + * imap_perform_select() + * + * Sends a SELECT command to ask the server to change the selected mailbox. + */ +static CURLcode imap_perform_select(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct IMAP *imap = data->req.protop; + struct imap_conn *imapc = &conn->proto.imapc; + char *mailbox; + + /* Invalidate old information as we are switching mailboxes */ + Curl_safefree(imapc->mailbox); + Curl_safefree(imapc->mailbox_uidvalidity); + + /* Check we have a mailbox */ + if(!imap->mailbox) { + failf(conn->data, "Cannot SELECT without a mailbox."); + return CURLE_URL_MALFORMAT; + } + + /* Make sure the mailbox is in the correct atom format */ + mailbox = imap_atom(imap->mailbox, false); + if(!mailbox) + return CURLE_OUT_OF_MEMORY; + + /* Send the SELECT command */ + result = imap_sendf(conn, "SELECT %s", mailbox); + + free(mailbox); + + if(!result) + state(conn, IMAP_SELECT); + + return result; +} + +/*********************************************************************** + * + * imap_perform_fetch() + * + * Sends a FETCH command to initiate the download of a message. + */ +static CURLcode imap_perform_fetch(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct IMAP *imap = conn->data->req.protop; + /* Check we have a UID */ + if(imap->uid) { + + /* Send the FETCH command */ + if(imap->partial) + result = imap_sendf(conn, "UID FETCH %s BODY[%s]<%s>", + imap->uid, + imap->section ? imap->section : "", + imap->partial); + else + result = imap_sendf(conn, "UID FETCH %s BODY[%s]", + imap->uid, + imap->section ? imap->section : ""); + } + else if(imap->mindex) { + + /* Send the FETCH command */ + if(imap->partial) + result = imap_sendf(conn, "FETCH %s BODY[%s]<%s>", + imap->mindex, + imap->section ? imap->section : "", + imap->partial); + else + result = imap_sendf(conn, "FETCH %s BODY[%s]", + imap->mindex, + imap->section ? imap->section : ""); + } + else { + failf(conn->data, "Cannot FETCH without a UID."); + return CURLE_URL_MALFORMAT; + } + if(!result) + state(conn, IMAP_FETCH); + + return result; +} + +/*********************************************************************** + * + * imap_perform_append() + * + * Sends an APPEND command to initiate the upload of a message. + */ +static CURLcode imap_perform_append(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct IMAP *imap = data->req.protop; + char *mailbox; + + /* Check we have a mailbox */ + if(!imap->mailbox) { + failf(data, "Cannot APPEND without a mailbox."); + return CURLE_URL_MALFORMAT; + } + + /* Prepare the mime data if some. */ + if(data->set.mimepost.kind != MIMEKIND_NONE) { + /* Use the whole structure as data. */ + data->set.mimepost.flags &= ~MIME_BODY_ONLY; + + /* Add external headers and mime version. */ + curl_mime_headers(&data->set.mimepost, data->set.headers, 0); + result = Curl_mime_prepare_headers(&data->set.mimepost, NULL, + NULL, MIMESTRATEGY_MAIL); + + if(!result) + if(!Curl_checkheaders(conn, "Mime-Version")) + result = Curl_mime_add_header(&data->set.mimepost.curlheaders, + "Mime-Version: 1.0"); + + /* Make sure we will read the entire mime structure. */ + if(!result) + result = Curl_mime_rewind(&data->set.mimepost); + + if(result) + return result; + + data->state.infilesize = Curl_mime_size(&data->set.mimepost); + + /* Read from mime structure. */ + data->state.fread_func = (curl_read_callback) Curl_mime_read; + data->state.in = (void *) &data->set.mimepost; + } + + /* Check we know the size of the upload */ + if(data->state.infilesize < 0) { + failf(data, "Cannot APPEND with unknown input file size\n"); + return CURLE_UPLOAD_FAILED; + } + + /* Make sure the mailbox is in the correct atom format */ + mailbox = imap_atom(imap->mailbox, false); + if(!mailbox) + return CURLE_OUT_OF_MEMORY; + + /* Send the APPEND command */ + result = imap_sendf(conn, "APPEND %s (\\Seen) {%" CURL_FORMAT_CURL_OFF_T "}", + mailbox, data->state.infilesize); + + free(mailbox); + + if(!result) + state(conn, IMAP_APPEND); + + return result; +} + +/*********************************************************************** + * + * imap_perform_search() + * + * Sends a SEARCH command. + */ +static CURLcode imap_perform_search(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct IMAP *imap = conn->data->req.protop; + + /* Check we have a query string */ + if(!imap->query) { + failf(conn->data, "Cannot SEARCH without a query string."); + return CURLE_URL_MALFORMAT; + } + + /* Send the SEARCH command */ + result = imap_sendf(conn, "SEARCH %s", imap->query); + + if(!result) + state(conn, IMAP_SEARCH); + + return result; +} + +/*********************************************************************** + * + * imap_perform_logout() + * + * Performs the logout action prior to sclose() being called. + */ +static CURLcode imap_perform_logout(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + /* Send the LOGOUT command */ + result = imap_sendf(conn, "LOGOUT"); + + if(!result) + state(conn, IMAP_LOGOUT); + + return result; +} + +/* For the initial server greeting */ +static CURLcode imap_state_servergreet_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + struct Curl_easy *data = conn->data; + (void)instate; /* no use for this yet */ + + if(imapcode == IMAP_RESP_PREAUTH) { + /* PREAUTH */ + struct imap_conn *imapc = &conn->proto.imapc; + imapc->preauth = TRUE; + infof(data, "PREAUTH connection, already authenticated!\n"); + } + else if(imapcode != IMAP_RESP_OK) { + failf(data, "Got unexpected imap-server response"); + return CURLE_WEIRD_SERVER_REPLY; + } + + return imap_perform_capability(conn); +} + +/* For CAPABILITY responses */ +static CURLcode imap_state_capability_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct imap_conn *imapc = &conn->proto.imapc; + const char *line = data->state.buffer; + + (void)instate; /* no use for this yet */ + + /* Do we have a untagged response? */ + if(imapcode == '*') { + line += 2; + + /* Loop through the data line */ + for(;;) { + size_t wordlen; + while(*line && + (*line == ' ' || *line == '\t' || + *line == '\r' || *line == '\n')) { + + line++; + } + + if(!*line) + break; + + /* Extract the word */ + for(wordlen = 0; line[wordlen] && line[wordlen] != ' ' && + line[wordlen] != '\t' && line[wordlen] != '\r' && + line[wordlen] != '\n';) + wordlen++; + + /* Does the server support the STARTTLS capability? */ + if(wordlen == 8 && !memcmp(line, "STARTTLS", 8)) + imapc->tls_supported = TRUE; + + /* Has the server explicitly disabled clear text authentication? */ + else if(wordlen == 13 && !memcmp(line, "LOGINDISABLED", 13)) + imapc->login_disabled = TRUE; + + /* Does the server support the SASL-IR capability? */ + else if(wordlen == 7 && !memcmp(line, "SASL-IR", 7)) + imapc->ir_supported = TRUE; + + /* Do we have a SASL based authentication mechanism? */ + else if(wordlen > 5 && !memcmp(line, "AUTH=", 5)) { + size_t llen; + unsigned int mechbit; + + line += 5; + wordlen -= 5; + + /* Test the word for a matching authentication mechanism */ + mechbit = Curl_sasl_decode_mech(line, wordlen, &llen); + if(mechbit && llen == wordlen) + imapc->sasl.authmechs |= mechbit; + } + + line += wordlen; + } + } + else if(imapcode == IMAP_RESP_OK) { + if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) { + /* We don't have a SSL/TLS connection yet, but SSL is requested */ + if(imapc->tls_supported) + /* Switch to TLS connection now */ + result = imap_perform_starttls(conn); + else if(data->set.use_ssl == CURLUSESSL_TRY) + /* Fallback and carry on with authentication */ + result = imap_perform_authentication(conn); + else { + failf(data, "STARTTLS not supported."); + result = CURLE_USE_SSL_FAILED; + } + } + else + result = imap_perform_authentication(conn); + } + else + result = imap_perform_authentication(conn); + + return result; +} + +/* For STARTTLS responses */ +static CURLcode imap_state_starttls_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(imapcode != IMAP_RESP_OK) { + if(data->set.use_ssl != CURLUSESSL_TRY) { + failf(data, "STARTTLS denied"); + result = CURLE_USE_SSL_FAILED; + } + else + result = imap_perform_authentication(conn); + } + else + result = imap_perform_upgrade_tls(conn); + + return result; +} + +/* For SASL authentication responses */ +static CURLcode imap_state_auth_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct imap_conn *imapc = &conn->proto.imapc; + saslprogress progress; + + (void)instate; /* no use for this yet */ + + result = Curl_sasl_continue(&imapc->sasl, conn, imapcode, &progress); + if(!result) + switch(progress) { + case SASL_DONE: + state(conn, IMAP_STOP); /* Authenticated */ + break; + case SASL_IDLE: /* No mechanism left after cancellation */ + if((!imapc->login_disabled) && (imapc->preftype & IMAP_TYPE_CLEARTEXT)) + /* Perform clear text authentication */ + result = imap_perform_login(conn); + else { + failf(data, "Authentication cancelled"); + result = CURLE_LOGIN_DENIED; + } + break; + default: + break; + } + + return result; +} + +/* For LOGIN responses */ +static CURLcode imap_state_login_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(imapcode != IMAP_RESP_OK) { + failf(data, "Access denied. %c", imapcode); + result = CURLE_LOGIN_DENIED; + } + else + /* End of connect phase */ + state(conn, IMAP_STOP); + + return result; +} + +/* For LIST and SEARCH responses */ +static CURLcode imap_state_listsearch_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + char *line = conn->data->state.buffer; + size_t len = strlen(line); + + (void)instate; /* No use for this yet */ + + if(imapcode == '*') { + /* Temporarily add the LF character back and send as body to the client */ + line[len] = '\n'; + result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1); + line[len] = '\0'; + } + else if(imapcode != IMAP_RESP_OK) + result = CURLE_QUOTE_ERROR; + else + /* End of DO phase */ + state(conn, IMAP_STOP); + + return result; +} + +/* For SELECT responses */ +static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct IMAP *imap = conn->data->req.protop; + struct imap_conn *imapc = &conn->proto.imapc; + const char *line = data->state.buffer; + + (void)instate; /* no use for this yet */ + + if(imapcode == '*') { + /* See if this is an UIDVALIDITY response */ + char tmp[20]; + if(sscanf(line + 2, "OK [UIDVALIDITY %19[0123456789]]", tmp) == 1) { + Curl_safefree(imapc->mailbox_uidvalidity); + imapc->mailbox_uidvalidity = strdup(tmp); + } + } + else if(imapcode == IMAP_RESP_OK) { + /* Check if the UIDVALIDITY has been specified and matches */ + if(imap->uidvalidity && imapc->mailbox_uidvalidity && + !strcasecompare(imap->uidvalidity, imapc->mailbox_uidvalidity)) { + failf(conn->data, "Mailbox UIDVALIDITY has changed"); + result = CURLE_REMOTE_FILE_NOT_FOUND; + } + else { + /* Note the currently opened mailbox on this connection */ + imapc->mailbox = strdup(imap->mailbox); + + if(imap->custom) + result = imap_perform_list(conn); + else if(imap->query) + result = imap_perform_search(conn); + else + result = imap_perform_fetch(conn); + } + } + else { + failf(data, "Select failed"); + result = CURLE_LOGIN_DENIED; + } + + return result; +} + +/* For the (first line of the) FETCH responses */ +static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct imap_conn *imapc = &conn->proto.imapc; + struct pingpong *pp = &imapc->pp; + const char *ptr = data->state.buffer; + bool parsed = FALSE; + curl_off_t size = 0; + + (void)instate; /* no use for this yet */ + + if(imapcode != '*') { + Curl_pgrsSetDownloadSize(data, -1); + state(conn, IMAP_STOP); + return CURLE_REMOTE_FILE_NOT_FOUND; + } + + /* Something like this is received "* 1 FETCH (BODY[TEXT] {2021}\r" so parse + the continuation data contained within the curly brackets */ + while(*ptr && (*ptr != '{')) + ptr++; + + if(*ptr == '{') { + char *endptr; + if(!curlx_strtoofft(ptr + 1, &endptr, 10, &size)) { + if(endptr - ptr > 1 && endptr[0] == '}' && + endptr[1] == '\r' && endptr[2] == '\0') + parsed = TRUE; + } + } + + if(parsed) { + infof(data, "Found %" CURL_FORMAT_CURL_OFF_T " bytes to download\n", + size); + Curl_pgrsSetDownloadSize(data, size); + + if(pp->cache) { + /* At this point there is a bunch of data in the header "cache" that is + actually body content, send it as body and then skip it. Do note + that there may even be additional "headers" after the body. */ + size_t chunk = pp->cache_size; + + if(chunk > (size_t)size) + /* The conversion from curl_off_t to size_t is always fine here */ + chunk = (size_t)size; + + if(!chunk) { + /* no size, we're done with the data */ + state(conn, IMAP_STOP); + return CURLE_OK; + } + result = Curl_client_write(conn, CLIENTWRITE_BODY, pp->cache, chunk); + if(result) + return result; + + data->req.bytecount += chunk; + + infof(data, "Written %zu bytes, %" CURL_FORMAT_CURL_OFF_TU + " bytes are left for transfer\n", chunk, size - chunk); + + /* Have we used the entire cache or just part of it?*/ + if(pp->cache_size > chunk) { + /* Only part of it so shrink the cache to fit the trailing data */ + memmove(pp->cache, pp->cache + chunk, pp->cache_size - chunk); + pp->cache_size -= chunk; + } + else { + /* Free the cache */ + Curl_safefree(pp->cache); + + /* Reset the cache size */ + pp->cache_size = 0; + } + } + + if(data->req.bytecount == size) + /* The entire data is already transferred! */ + Curl_setup_transfer(data, -1, -1, FALSE, -1); + else { + /* IMAP download */ + data->req.maxdownload = size; + Curl_setup_transfer(data, FIRSTSOCKET, size, FALSE, -1); + } + } + else { + /* We don't know how to parse this line */ + failf(pp->conn->data, "Failed to parse FETCH response."); + result = CURLE_WEIRD_SERVER_REPLY; + } + + /* End of DO phase */ + state(conn, IMAP_STOP); + + return result; +} + +/* For final FETCH responses performed after the download */ +static CURLcode imap_state_fetch_final_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + + (void)instate; /* No use for this yet */ + + if(imapcode != IMAP_RESP_OK) + result = CURLE_WEIRD_SERVER_REPLY; + else + /* End of DONE phase */ + state(conn, IMAP_STOP); + + return result; +} + +/* For APPEND responses */ +static CURLcode imap_state_append_resp(struct connectdata *conn, int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + (void)instate; /* No use for this yet */ + + if(imapcode != '+') { + result = CURLE_UPLOAD_FAILED; + } + else { + /* Set the progress upload size */ + Curl_pgrsSetUploadSize(data, data->state.infilesize); + + /* IMAP upload */ + Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); + + /* End of DO phase */ + state(conn, IMAP_STOP); + } + + return result; +} + +/* For final APPEND responses performed after the upload */ +static CURLcode imap_state_append_final_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + + (void)instate; /* No use for this yet */ + + if(imapcode != IMAP_RESP_OK) + result = CURLE_UPLOAD_FAILED; + else + /* End of DONE phase */ + state(conn, IMAP_STOP); + + return result; +} + +static CURLcode imap_statemach_act(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + int imapcode; + struct imap_conn *imapc = &conn->proto.imapc; + struct pingpong *pp = &imapc->pp; + size_t nread = 0; + + /* Busy upgrading the connection; right now all I/O is SSL/TLS, not IMAP */ + if(imapc->state == IMAP_UPGRADETLS) + return imap_perform_upgrade_tls(conn); + + /* Flush any data that needs to be sent */ + if(pp->sendleft) + return Curl_pp_flushsend(pp); + + do { + /* Read the response from the server */ + result = Curl_pp_readresp(sock, pp, &imapcode, &nread); + if(result) + return result; + + /* Was there an error parsing the response line? */ + if(imapcode == -1) + return CURLE_WEIRD_SERVER_REPLY; + + if(!imapcode) + break; + + /* We have now received a full IMAP server response */ + switch(imapc->state) { + case IMAP_SERVERGREET: + result = imap_state_servergreet_resp(conn, imapcode, imapc->state); + break; + + case IMAP_CAPABILITY: + result = imap_state_capability_resp(conn, imapcode, imapc->state); + break; + + case IMAP_STARTTLS: + result = imap_state_starttls_resp(conn, imapcode, imapc->state); + break; + + case IMAP_AUTHENTICATE: + result = imap_state_auth_resp(conn, imapcode, imapc->state); + break; + + case IMAP_LOGIN: + result = imap_state_login_resp(conn, imapcode, imapc->state); + break; + + case IMAP_LIST: + result = imap_state_listsearch_resp(conn, imapcode, imapc->state); + break; + + case IMAP_SELECT: + result = imap_state_select_resp(conn, imapcode, imapc->state); + break; + + case IMAP_FETCH: + result = imap_state_fetch_resp(conn, imapcode, imapc->state); + break; + + case IMAP_FETCH_FINAL: + result = imap_state_fetch_final_resp(conn, imapcode, imapc->state); + break; + + case IMAP_APPEND: + result = imap_state_append_resp(conn, imapcode, imapc->state); + break; + + case IMAP_APPEND_FINAL: + result = imap_state_append_final_resp(conn, imapcode, imapc->state); + break; + + case IMAP_SEARCH: + result = imap_state_listsearch_resp(conn, imapcode, imapc->state); + break; + + case IMAP_LOGOUT: + /* fallthrough, just stop! */ + default: + /* internal error */ + state(conn, IMAP_STOP); + break; + } + } while(!result && imapc->state != IMAP_STOP && Curl_pp_moredata(pp)); + + return result; +} + +/* Called repeatedly until done from multi.c */ +static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + struct imap_conn *imapc = &conn->proto.imapc; + + if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone) { + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &imapc->ssldone); + if(result || !imapc->ssldone) + return result; + } + + result = Curl_pp_statemach(&imapc->pp, FALSE, FALSE); + *done = (imapc->state == IMAP_STOP) ? TRUE : FALSE; + + return result; +} + +static CURLcode imap_block_statemach(struct connectdata *conn, + bool disconnecting) +{ + CURLcode result = CURLE_OK; + struct imap_conn *imapc = &conn->proto.imapc; + + while(imapc->state != IMAP_STOP && !result) + result = Curl_pp_statemach(&imapc->pp, TRUE, disconnecting); + + return result; +} + +/* Allocate and initialize the struct IMAP for the current Curl_easy if + required */ +static CURLcode imap_init(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct IMAP *imap; + + imap = data->req.protop = calloc(sizeof(struct IMAP), 1); + if(!imap) + result = CURLE_OUT_OF_MEMORY; + + return result; +} + +/* For the IMAP "protocol connect" and "doing" phases only */ +static int imap_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks) +{ + return Curl_pp_getsock(&conn->proto.imapc.pp, socks, numsocks); +} + +/*********************************************************************** + * + * imap_connect() + * + * This function should do everything that is to be considered a part of the + * connection phase. + * + * The variable 'done' points to will be TRUE if the protocol-layer connect + * phase is done when this function returns, or FALSE if not. + */ +static CURLcode imap_connect(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + struct imap_conn *imapc = &conn->proto.imapc; + struct pingpong *pp = &imapc->pp; + + *done = FALSE; /* default to not done yet */ + + /* We always support persistent connections in IMAP */ + connkeep(conn, "IMAP default"); + + /* Set the default response time-out */ + pp->response_time = RESP_TIMEOUT; + pp->statemach_act = imap_statemach_act; + pp->endofresp = imap_endofresp; + pp->conn = conn; + + /* Set the default preferred authentication type and mechanism */ + imapc->preftype = IMAP_TYPE_ANY; + Curl_sasl_init(&imapc->sasl, &saslimap); + + /* Initialise the pingpong layer */ + Curl_pp_init(pp); + + /* Parse the URL options */ + result = imap_parse_url_options(conn); + if(result) + return result; + + /* Start off waiting for the server greeting response */ + state(conn, IMAP_SERVERGREET); + + /* Start off with an response id of '*' */ + strcpy(imapc->resptag, "*"); + + result = imap_multi_statemach(conn, done); + + return result; +} + +/*********************************************************************** + * + * imap_done() + * + * The DONE function. This does what needs to be done after a single DO has + * performed. + * + * Input argument is already checked for validity. + */ +static CURLcode imap_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct IMAP *imap = data->req.protop; + + (void)premature; + + if(!imap) + return CURLE_OK; + + if(status) { + connclose(conn, "IMAP done with bad status"); /* marked for closure */ + result = status; /* use the already set error code */ + } + else if(!data->set.connect_only && !imap->custom && + (imap->uid || imap->mindex || data->set.upload || + data->set.mimepost.kind != MIMEKIND_NONE)) { + /* Handle responses after FETCH or APPEND transfer has finished */ + + if(!data->set.upload && data->set.mimepost.kind == MIMEKIND_NONE) + state(conn, IMAP_FETCH_FINAL); + else { + /* End the APPEND command first by sending an empty line */ + result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", ""); + if(!result) + state(conn, IMAP_APPEND_FINAL); + } + + /* Run the state-machine */ + if(!result) + result = imap_block_statemach(conn, FALSE); + } + + /* Cleanup our per-request based variables */ + Curl_safefree(imap->mailbox); + Curl_safefree(imap->uidvalidity); + Curl_safefree(imap->uid); + Curl_safefree(imap->mindex); + Curl_safefree(imap->section); + Curl_safefree(imap->partial); + Curl_safefree(imap->query); + Curl_safefree(imap->custom); + Curl_safefree(imap->custom_params); + + /* Clear the transfer mode for the next request */ + imap->transfer = FTPTRANSFER_BODY; + + return result; +} + +/*********************************************************************** + * + * imap_perform() + * + * This is the actual DO function for IMAP. Fetch or append a message, or do + * other things according to the options previously setup. + */ +static CURLcode imap_perform(struct connectdata *conn, bool *connected, + bool *dophase_done) +{ + /* This is IMAP and no proxy */ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct IMAP *imap = data->req.protop; + struct imap_conn *imapc = &conn->proto.imapc; + bool selected = FALSE; + + DEBUGF(infof(conn->data, "DO phase starts\n")); + + if(conn->data->set.opt_no_body) { + /* Requested no body means no transfer */ + imap->transfer = FTPTRANSFER_INFO; + } + + *dophase_done = FALSE; /* not done yet */ + + /* Determine if the requested mailbox (with the same UIDVALIDITY if set) + has already been selected on this connection */ + if(imap->mailbox && imapc->mailbox && + strcasecompare(imap->mailbox, imapc->mailbox) && + (!imap->uidvalidity || !imapc->mailbox_uidvalidity || + strcasecompare(imap->uidvalidity, imapc->mailbox_uidvalidity))) + selected = TRUE; + + /* Start the first command in the DO phase */ + if(conn->data->set.upload || data->set.mimepost.kind != MIMEKIND_NONE) + /* APPEND can be executed directly */ + result = imap_perform_append(conn); + else if(imap->custom && (selected || !imap->mailbox)) + /* Custom command using the same mailbox or no mailbox */ + result = imap_perform_list(conn); + else if(!imap->custom && selected && (imap->uid || imap->mindex)) + /* FETCH from the same mailbox */ + result = imap_perform_fetch(conn); + else if(!imap->custom && selected && imap->query) + /* SEARCH the current mailbox */ + result = imap_perform_search(conn); + else if(imap->mailbox && !selected && + (imap->custom || imap->uid || imap->mindex || imap->query)) + /* SELECT the mailbox */ + result = imap_perform_select(conn); + else + /* LIST */ + result = imap_perform_list(conn); + + if(result) + return result; + + /* Run the state-machine */ + result = imap_multi_statemach(conn, dophase_done); + + *connected = conn->bits.tcpconnect[FIRSTSOCKET]; + + if(*dophase_done) + DEBUGF(infof(conn->data, "DO phase is complete\n")); + + return result; +} + +/*********************************************************************** + * + * imap_do() + * + * This function is registered as 'curl_do' function. It decodes the path + * parts etc as a wrapper to the actual DO function (imap_perform). + * + * The input argument is already checked for validity. + */ +static CURLcode imap_do(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + + *done = FALSE; /* default to false */ + + /* Parse the URL path */ + result = imap_parse_url_path(conn); + if(result) + return result; + + /* Parse the custom request */ + result = imap_parse_custom_request(conn); + if(result) + return result; + + result = imap_regular_transfer(conn, done); + + return result; +} + +/*********************************************************************** + * + * imap_disconnect() + * + * Disconnect from an IMAP server. Cleanup protocol-specific per-connection + * resources. BLOCKING. + */ +static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection) +{ + struct imap_conn *imapc = &conn->proto.imapc; + + /* We cannot send quit unconditionally. If this connection is stale or + bad in any way, sending quit and waiting around here will make the + disconnect wait in vain and cause more problems than we need to. */ + + /* The IMAP session may or may not have been allocated/setup at this + point! */ + if(!dead_connection && imapc->pp.conn && imapc->pp.conn->bits.protoconnstart) + if(!imap_perform_logout(conn)) + (void)imap_block_statemach(conn, TRUE); /* ignore errors on LOGOUT */ + + /* Disconnect from the server */ + Curl_pp_disconnect(&imapc->pp); + + /* Cleanup the SASL module */ + Curl_sasl_cleanup(conn, imapc->sasl.authused); + + /* Cleanup our connection based variables */ + Curl_safefree(imapc->mailbox); + Curl_safefree(imapc->mailbox_uidvalidity); + + return CURLE_OK; +} + +/* Call this when the DO phase has completed */ +static CURLcode imap_dophase_done(struct connectdata *conn, bool connected) +{ + struct IMAP *imap = conn->data->req.protop; + + (void)connected; + + if(imap->transfer != FTPTRANSFER_BODY) + /* no data to transfer */ + Curl_setup_transfer(conn->data, -1, -1, FALSE, -1); + + return CURLE_OK; +} + +/* Called from multi.c while DOing */ +static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done) +{ + CURLcode result = imap_multi_statemach(conn, dophase_done); + + if(result) + DEBUGF(infof(conn->data, "DO phase failed\n")); + else if(*dophase_done) { + result = imap_dophase_done(conn, FALSE /* not connected */); + + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + + return result; +} + +/*********************************************************************** + * + * imap_regular_transfer() + * + * The input argument is already checked for validity. + * + * Performs all commands done before a regular transfer between a local and a + * remote host. + */ +static CURLcode imap_regular_transfer(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result = CURLE_OK; + bool connected = FALSE; + struct Curl_easy *data = conn->data; + + /* Make sure size is unknown at this point */ + data->req.size = -1; + + /* Set the progress data */ + Curl_pgrsSetUploadCounter(data, 0); + Curl_pgrsSetDownloadCounter(data, 0); + Curl_pgrsSetUploadSize(data, -1); + Curl_pgrsSetDownloadSize(data, -1); + + /* Carry out the perform */ + result = imap_perform(conn, &connected, dophase_done); + + /* Perform post DO phase operations if necessary */ + if(!result && *dophase_done) + result = imap_dophase_done(conn, connected); + + return result; +} + +static CURLcode imap_setup_connection(struct connectdata *conn) +{ + /* Initialise the IMAP layer */ + CURLcode result = imap_init(conn); + if(result) + return result; + + /* Clear the TLS upgraded flag */ + conn->tls_upgraded = FALSE; + + return CURLE_OK; +} + +/*********************************************************************** + * + * imap_sendf() + * + * Sends the formatted string as an IMAP command to the server. + * + * Designed to never block. + */ +static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...) +{ + CURLcode result = CURLE_OK; + struct imap_conn *imapc = &conn->proto.imapc; + char *taggedfmt; + va_list ap; + + DEBUGASSERT(fmt); + + /* Calculate the next command ID wrapping at 3 digits */ + imapc->cmdid = (imapc->cmdid + 1) % 1000; + + /* Calculate the tag based on the connection ID and command ID */ + msnprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d", + 'A' + curlx_sltosi(conn->connection_id % 26), imapc->cmdid); + + /* Prefix the format with the tag */ + taggedfmt = aprintf("%s %s", imapc->resptag, fmt); + if(!taggedfmt) + return CURLE_OUT_OF_MEMORY; + + /* Send the data with the tag */ + va_start(ap, fmt); + result = Curl_pp_vsendf(&imapc->pp, taggedfmt, ap); + va_end(ap); + + free(taggedfmt); + + return result; +} + +/*********************************************************************** + * + * imap_atom() + * + * Checks the input string for characters that need escaping and returns an + * atom ready for sending to the server. + * + * The returned string needs to be freed. + * + */ +static char *imap_atom(const char *str, bool escape_only) +{ + /* !checksrc! disable PARENBRACE 1 */ + const char atom_specials[] = "(){ %*]"; + const char *p1; + char *p2; + size_t backsp_count = 0; + size_t quote_count = 0; + bool others_exists = FALSE; + size_t newlen = 0; + char *newstr = NULL; + + if(!str) + return NULL; + + /* Look for "atom-specials", counting the backslash and quote characters as + these will need escaping */ + p1 = str; + while(*p1) { + if(*p1 == '\\') + backsp_count++; + else if(*p1 == '"') + quote_count++; + else if(!escape_only) { + const char *p3 = atom_specials; + + while(*p3 && !others_exists) { + if(*p1 == *p3) + others_exists = TRUE; + + p3++; + } + } + + p1++; + } + + /* Does the input contain any "atom-special" characters? */ + if(!backsp_count && !quote_count && !others_exists) + return strdup(str); + + /* Calculate the new string length */ + newlen = strlen(str) + backsp_count + quote_count + (escape_only ? 0 : 2); + + /* Allocate the new string */ + newstr = (char *) malloc((newlen + 1) * sizeof(char)); + if(!newstr) + return NULL; + + /* Surround the string in quotes if necessary */ + p2 = newstr; + if(!escape_only) { + newstr[0] = '"'; + newstr[newlen - 1] = '"'; + p2++; + } + + /* Copy the string, escaping backslash and quote characters along the way */ + p1 = str; + while(*p1) { + if(*p1 == '\\' || *p1 == '"') { + *p2 = '\\'; + p2++; + } + + *p2 = *p1; + + p1++; + p2++; + } + + /* Terminate the string */ + newstr[newlen] = '\0'; + + return newstr; +} + +/*********************************************************************** + * + * imap_is_bchar() + * + * Portable test of whether the specified char is a "bchar" as defined in the + * grammar of RFC-5092. + */ +static bool imap_is_bchar(char ch) +{ + switch(ch) { + /* bchar */ + case ':': case '@': case '/': + /* bchar -> achar */ + case '&': case '=': + /* bchar -> achar -> uchar -> unreserved */ + case '0': case '1': case '2': case '3': case '4': case '5': case '6': + case '7': case '8': case '9': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': + case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': + case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': + case 'V': case 'W': case 'X': case 'Y': case 'Z': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': + case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': + case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': + case 'v': case 'w': case 'x': case 'y': case 'z': + case '-': case '.': case '_': case '~': + /* bchar -> achar -> uchar -> sub-delims-sh */ + case '!': case '$': case '\'': case '(': case ')': case '*': + case '+': case ',': + /* bchar -> achar -> uchar -> pct-encoded */ + case '%': /* HEXDIG chars are already included above */ + return true; + + default: + return false; + } +} + +/*********************************************************************** + * + * imap_parse_url_options() + * + * Parse the URL login options. + */ +static CURLcode imap_parse_url_options(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct imap_conn *imapc = &conn->proto.imapc; + const char *ptr = conn->options; + + imapc->sasl.resetprefs = TRUE; + + while(!result && ptr && *ptr) { + const char *key = ptr; + const char *value; + + while(*ptr && *ptr != '=') + ptr++; + + value = ptr + 1; + + while(*ptr && *ptr != ';') + ptr++; + + if(strncasecompare(key, "AUTH=", 5)) + result = Curl_sasl_parse_url_auth_option(&imapc->sasl, + value, ptr - value); + else + result = CURLE_URL_MALFORMAT; + + if(*ptr == ';') + ptr++; + } + + switch(imapc->sasl.prefmech) { + case SASL_AUTH_NONE: + imapc->preftype = IMAP_TYPE_NONE; + break; + case SASL_AUTH_DEFAULT: + imapc->preftype = IMAP_TYPE_ANY; + break; + default: + imapc->preftype = IMAP_TYPE_SASL; + break; + } + + return result; +} + +/*********************************************************************** + * + * imap_parse_url_path() + * + * Parse the URL path into separate path components. + * + */ +static CURLcode imap_parse_url_path(struct connectdata *conn) +{ + /* The imap struct is already initialised in imap_connect() */ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct IMAP *imap = data->req.protop; + const char *begin = &data->state.up.path[1]; /* skip leading slash */ + const char *ptr = begin; + + /* See how much of the URL is a valid path and decode it */ + while(imap_is_bchar(*ptr)) + ptr++; + + if(ptr != begin) { + /* Remove the trailing slash if present */ + const char *end = ptr; + if(end > begin && end[-1] == '/') + end--; + + result = Curl_urldecode(data, begin, end - begin, &imap->mailbox, NULL, + TRUE); + if(result) + return result; + } + else + imap->mailbox = NULL; + + /* There can be any number of parameters in the form ";NAME=VALUE" */ + while(*ptr == ';') { + char *name; + char *value; + size_t valuelen; + + /* Find the length of the name parameter */ + begin = ++ptr; + while(*ptr && *ptr != '=') + ptr++; + + if(!*ptr) + return CURLE_URL_MALFORMAT; + + /* Decode the name parameter */ + result = Curl_urldecode(data, begin, ptr - begin, &name, NULL, TRUE); + if(result) + return result; + + /* Find the length of the value parameter */ + begin = ++ptr; + while(imap_is_bchar(*ptr)) + ptr++; + + /* Decode the value parameter */ + result = Curl_urldecode(data, begin, ptr - begin, &value, &valuelen, TRUE); + if(result) { + free(name); + return result; + } + + DEBUGF(infof(conn->data, "IMAP URL parameter '%s' = '%s'\n", name, value)); + + /* Process the known hierarchical parameters (UIDVALIDITY, UID, SECTION and + PARTIAL) stripping of the trailing slash character if it is present. + + Note: Unknown parameters trigger a URL_MALFORMAT error. */ + if(strcasecompare(name, "UIDVALIDITY") && !imap->uidvalidity) { + if(valuelen > 0 && value[valuelen - 1] == '/') + value[valuelen - 1] = '\0'; + + imap->uidvalidity = value; + value = NULL; + } + else if(strcasecompare(name, "UID") && !imap->uid) { + if(valuelen > 0 && value[valuelen - 1] == '/') + value[valuelen - 1] = '\0'; + + imap->uid = value; + value = NULL; + } + else if(strcasecompare(name, "MAILINDEX") && !imap->mindex) { + if(valuelen > 0 && value[valuelen - 1] == '/') + value[valuelen - 1] = '\0'; + + imap->mindex = value; + value = NULL; + } + else if(strcasecompare(name, "SECTION") && !imap->section) { + if(valuelen > 0 && value[valuelen - 1] == '/') + value[valuelen - 1] = '\0'; + + imap->section = value; + value = NULL; + } + else if(strcasecompare(name, "PARTIAL") && !imap->partial) { + if(valuelen > 0 && value[valuelen - 1] == '/') + value[valuelen - 1] = '\0'; + + imap->partial = value; + value = NULL; + } + else { + free(name); + free(value); + + return CURLE_URL_MALFORMAT; + } + + free(name); + free(value); + } + + /* Does the URL contain a query parameter? Only valid when we have a mailbox + and no UID as per RFC-5092 */ + if(imap->mailbox && !imap->uid && !imap->mindex) { + /* Get the query parameter, URL decoded */ + (void)curl_url_get(data->state.uh, CURLUPART_QUERY, &imap->query, + CURLU_URLDECODE); + } + + /* Any extra stuff at the end of the URL is an error */ + if(*ptr) + return CURLE_URL_MALFORMAT; + + return CURLE_OK; +} + +/*********************************************************************** + * + * imap_parse_custom_request() + * + * Parse the custom request. + */ +static CURLcode imap_parse_custom_request(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct IMAP *imap = data->req.protop; + const char *custom = data->set.str[STRING_CUSTOMREQUEST]; + + if(custom) { + /* URL decode the custom request */ + result = Curl_urldecode(data, custom, 0, &imap->custom, NULL, TRUE); + + /* Extract the parameters if specified */ + if(!result) { + const char *params = imap->custom; + + while(*params && *params != ' ') + params++; + + if(*params) { + imap->custom_params = strdup(params); + imap->custom[params - imap->custom] = '\0'; + + if(!imap->custom_params) + result = CURLE_OUT_OF_MEMORY; + } + } + } + + return result; +} + +#endif /* CURL_DISABLE_IMAP */ diff --git a/dependencies/cmcurl/lib/imap.h b/dependencies/cmcurl/lib/imap.h new file mode 100644 index 0000000..0efcfd2 --- /dev/null +++ b/dependencies/cmcurl/lib/imap.h @@ -0,0 +1,98 @@ +#ifndef HEADER_CURL_IMAP_H +#define HEADER_CURL_IMAP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2009 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "pingpong.h" +#include "curl_sasl.h" + +/**************************************************************************** + * IMAP unique setup + ***************************************************************************/ +typedef enum { + IMAP_STOP, /* do nothing state, stops the state machine */ + IMAP_SERVERGREET, /* waiting for the initial greeting immediately after + a connect */ + IMAP_CAPABILITY, + IMAP_STARTTLS, + IMAP_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS + (multi mode only) */ + IMAP_AUTHENTICATE, + IMAP_LOGIN, + IMAP_LIST, + IMAP_SELECT, + IMAP_FETCH, + IMAP_FETCH_FINAL, + IMAP_APPEND, + IMAP_APPEND_FINAL, + IMAP_SEARCH, + IMAP_LOGOUT, + IMAP_LAST /* never used */ +} imapstate; + +/* This IMAP struct is used in the Curl_easy. All IMAP data that is + connection-oriented must be in imap_conn to properly deal with the fact that + perhaps the Curl_easy is changed between the times the connection is + used. */ +struct IMAP { + curl_pp_transfer transfer; + char *mailbox; /* Mailbox to select */ + char *uidvalidity; /* UIDVALIDITY to check in select */ + char *uid; /* Message UID to fetch */ + char *mindex; /* Index in mail box of mail to fetch */ + char *section; /* Message SECTION to fetch */ + char *partial; /* Message PARTIAL to fetch */ + char *query; /* Query to search for */ + char *custom; /* Custom request */ + char *custom_params; /* Parameters for the custom request */ +}; + +/* imap_conn is used for struct connection-oriented data in the connectdata + struct */ +struct imap_conn { + struct pingpong pp; + imapstate state; /* Always use imap.c:state() to change state! */ + bool ssldone; /* Is connect() over SSL done? */ + bool preauth; /* Is this connection PREAUTH? */ + struct SASL sasl; /* SASL-related parameters */ + unsigned int preftype; /* Preferred authentication type */ + int cmdid; /* Last used command ID */ + char resptag[5]; /* Response tag to wait for */ + bool tls_supported; /* StartTLS capability supported by server */ + bool login_disabled; /* LOGIN command disabled by server */ + bool ir_supported; /* Initial response supported by server */ + char *mailbox; /* The last selected mailbox */ + char *mailbox_uidvalidity; /* UIDVALIDITY parsed from select response */ +}; + +extern const struct Curl_handler Curl_handler_imap; +extern const struct Curl_handler Curl_handler_imaps; + +/* Authentication type flags */ +#define IMAP_TYPE_CLEARTEXT (1 << 0) +#define IMAP_TYPE_SASL (1 << 1) + +/* Authentication type values */ +#define IMAP_TYPE_NONE 0 +#define IMAP_TYPE_ANY ~0U + +#endif /* HEADER_CURL_IMAP_H */ diff --git a/dependencies/cmcurl/lib/inet_ntop.c b/dependencies/cmcurl/lib/inet_ntop.c new file mode 100644 index 0000000..855981c --- /dev/null +++ b/dependencies/cmcurl/lib/inet_ntop.c @@ -0,0 +1,197 @@ +/* + * Copyright (C) 1996-2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Original code by Paul Vixie. "curlified" by Gisle Vanem. + */ + +#include "curl_setup.h" + +#ifndef HAVE_INET_NTOP + +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#include "inet_ntop.h" +#include "curl_printf.h" + +#define IN6ADDRSZ 16 +#define INADDRSZ 4 +#define INT16SZ 2 + +/* + * Format an IPv4 address, more or less like inet_ntoa(). + * + * Returns `dst' (as a const) + * Note: + * - uses no statics + * - takes a unsigned char* not an in_addr as input + */ +static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size) +{ + char tmp[sizeof("255.255.255.255")]; + size_t len; + + DEBUGASSERT(size >= 16); + + tmp[0] = '\0'; + (void)msnprintf(tmp, sizeof(tmp), "%d.%d.%d.%d", + ((int)((unsigned char)src[0])) & 0xff, + ((int)((unsigned char)src[1])) & 0xff, + ((int)((unsigned char)src[2])) & 0xff, + ((int)((unsigned char)src[3])) & 0xff); + + len = strlen(tmp); + if(len == 0 || len >= size) { + errno = ENOSPC; + return (NULL); + } + strcpy(dst, tmp); + return dst; +} + +#ifdef ENABLE_IPV6 +/* + * Convert IPv6 binary address into presentation (printable) format. + */ +static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size) +{ + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; + char *tp; + struct { + long base; + long len; + } best, cur; + unsigned long words[IN6ADDRSZ / INT16SZ]; + int i; + + /* Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, '\0', sizeof(words)); + for(i = 0; i < IN6ADDRSZ; i++) + words[i/2] |= (src[i] << ((1 - (i % 2)) << 3)); + + best.base = -1; + cur.base = -1; + best.len = 0; + cur.len = 0; + + for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { + if(words[i] == 0) { + if(cur.base == -1) + cur.base = i, cur.len = 1; + else + cur.len++; + } + else if(cur.base != -1) { + if(best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + if((cur.base != -1) && (best.base == -1 || cur.len > best.len)) + best = cur; + if(best.base != -1 && best.len < 2) + best.base = -1; + /* Format the result. */ + tp = tmp; + for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { + /* Are we inside the best run of 0x00's? */ + if(best.base != -1 && i >= best.base && i < (best.base + best.len)) { + if(i == best.base) + *tp++ = ':'; + continue; + } + + /* Are we following an initial run of 0x00s or any real hex? + */ + if(i != 0) + *tp++ = ':'; + + /* Is this address an encapsulated IPv4? + */ + if(i == 6 && best.base == 0 && + (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { + if(!inet_ntop4(src + 12, tp, sizeof(tmp) - (tp - tmp))) { + errno = ENOSPC; + return (NULL); + } + tp += strlen(tp); + break; + } + tp += msnprintf(tp, 5, "%lx", words[i]); + } + + /* Was it a trailing run of 0x00's? + */ + if(best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) + *tp++ = ':'; + *tp++ = '\0'; + + /* Check for overflow, copy, and we're done. + */ + if((size_t)(tp - tmp) > size) { + errno = ENOSPC; + return (NULL); + } + strcpy(dst, tmp); + return dst; +} +#endif /* ENABLE_IPV6 */ + +/* + * Convert a network format address to presentation format. + * + * Returns pointer to presentation format address (`buf'). + * Returns NULL on error and errno set with the specific + * error, EAFNOSUPPORT or ENOSPC. + * + * On Windows we store the error in the thread errno, not + * in the winsock error code. This is to avoid losing the + * actual last winsock error. So when this function returns + * NULL, check errno not SOCKERRNO. + */ +char *Curl_inet_ntop(int af, const void *src, char *buf, size_t size) +{ + switch(af) { + case AF_INET: + return inet_ntop4((const unsigned char *)src, buf, size); +#ifdef ENABLE_IPV6 + case AF_INET6: + return inet_ntop6((const unsigned char *)src, buf, size); +#endif + default: + errno = EAFNOSUPPORT; + return NULL; + } +} +#endif /* HAVE_INET_NTOP */ diff --git a/dependencies/cmcurl/lib/inet_ntop.h b/dependencies/cmcurl/lib/inet_ntop.h new file mode 100644 index 0000000..d150bb6 --- /dev/null +++ b/dependencies/cmcurl/lib/inet_ntop.h @@ -0,0 +1,37 @@ +#ifndef HEADER_CURL_INET_NTOP_H +#define HEADER_CURL_INET_NTOP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +char *Curl_inet_ntop(int af, const void *addr, char *buf, size_t size); + +#ifdef HAVE_INET_NTOP +#ifdef HAVE_ARPA_INET_H +#include +#endif +#define Curl_inet_ntop(af,addr,buf,size) \ + inet_ntop(af, addr, buf, (curl_socklen_t)size) +#endif + +#endif /* HEADER_CURL_INET_NTOP_H */ diff --git a/dependencies/cmcurl/lib/inet_pton.c b/dependencies/cmcurl/lib/inet_pton.c new file mode 100644 index 0000000..0d65ae0 --- /dev/null +++ b/dependencies/cmcurl/lib/inet_pton.c @@ -0,0 +1,237 @@ +/* This is from the BIND 4.9.4 release, modified to compile by itself */ + +/* Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include "curl_setup.h" + +#ifndef HAVE_INET_PTON + +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#include "inet_pton.h" + +#define IN6ADDRSZ 16 +#define INADDRSZ 4 +#define INT16SZ 2 + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static int inet_pton4(const char *src, unsigned char *dst); +#ifdef ENABLE_IPV6 +static int inet_pton6(const char *src, unsigned char *dst); +#endif + +/* int + * inet_pton(af, src, dst) + * convert from presentation format (which usually means ASCII printable) + * to network format (which is usually some kind of binary format). + * return: + * 1 if the address was valid for the specified address family + * 0 if the address wasn't valid (`dst' is untouched in this case) + * -1 if some other error occurred (`dst' is untouched in this case, too) + * notice: + * On Windows we store the error in the thread errno, not + * in the winsock error code. This is to avoid losing the + * actual last winsock error. So when this function returns + * -1, check errno not SOCKERRNO. + * author: + * Paul Vixie, 1996. + */ +int +Curl_inet_pton(int af, const char *src, void *dst) +{ + switch(af) { + case AF_INET: + return (inet_pton4(src, (unsigned char *)dst)); +#ifdef ENABLE_IPV6 + case AF_INET6: + return (inet_pton6(src, (unsigned char *)dst)); +#endif + default: + errno = EAFNOSUPPORT; + return (-1); + } + /* NOTREACHED */ +} + +/* int + * inet_pton4(src, dst) + * like inet_aton() but without all the hexadecimal and shorthand. + * return: + * 1 if `src' is a valid dotted quad, else 0. + * notice: + * does not touch `dst' unless it's returning 1. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton4(const char *src, unsigned char *dst) +{ + static const char digits[] = "0123456789"; + int saw_digit, octets, ch; + unsigned char tmp[INADDRSZ], *tp; + + saw_digit = 0; + octets = 0; + tp = tmp; + *tp = 0; + while((ch = *src++) != '\0') { + const char *pch; + + pch = strchr(digits, ch); + if(pch) { + unsigned int val = *tp * 10 + (unsigned int)(pch - digits); + + if(saw_digit && *tp == 0) + return (0); + if(val > 255) + return (0); + *tp = (unsigned char)val; + if(! saw_digit) { + if(++octets > 4) + return (0); + saw_digit = 1; + } + } + else if(ch == '.' && saw_digit) { + if(octets == 4) + return (0); + *++tp = 0; + saw_digit = 0; + } + else + return (0); + } + if(octets < 4) + return (0); + memcpy(dst, tmp, INADDRSZ); + return (1); +} + +#ifdef ENABLE_IPV6 +/* int + * inet_pton6(src, dst) + * convert presentation level address to network order binary form. + * return: + * 1 if `src' is a valid [RFC1884 2.2] address, else 0. + * notice: + * (1) does not touch `dst' unless it's returning 1. + * (2) :: in a full address is silently ignored. + * credit: + * inspired by Mark Andrews. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton6(const char *src, unsigned char *dst) +{ + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp; + const char *curtok; + int ch, saw_xdigit; + size_t val; + + memset((tp = tmp), 0, IN6ADDRSZ); + endp = tp + IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if(*src == ':') + if(*++src != ':') + return (0); + curtok = src; + saw_xdigit = 0; + val = 0; + while((ch = *src++) != '\0') { + const char *xdigits; + const char *pch; + + pch = strchr((xdigits = xdigits_l), ch); + if(!pch) + pch = strchr((xdigits = xdigits_u), ch); + if(pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if(++saw_xdigit > 4) + return (0); + continue; + } + if(ch == ':') { + curtok = src; + if(!saw_xdigit) { + if(colonp) + return (0); + colonp = tp; + continue; + } + if(tp + INT16SZ > endp) + return (0); + *tp++ = (unsigned char) ((val >> 8) & 0xff); + *tp++ = (unsigned char) (val & 0xff); + saw_xdigit = 0; + val = 0; + continue; + } + if(ch == '.' && ((tp + INADDRSZ) <= endp) && + inet_pton4(curtok, tp) > 0) { + tp += INADDRSZ; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + return (0); + } + if(saw_xdigit) { + if(tp + INT16SZ > endp) + return (0); + *tp++ = (unsigned char) ((val >> 8) & 0xff); + *tp++ = (unsigned char) (val & 0xff); + } + if(colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const ssize_t n = tp - colonp; + ssize_t i; + + if(tp == endp) + return (0); + for(i = 1; i <= n; i++) { + *(endp - i) = *(colonp + n - i); + *(colonp + n - i) = 0; + } + tp = endp; + } + if(tp != endp) + return (0); + memcpy(dst, tmp, IN6ADDRSZ); + return (1); +} +#endif /* ENABLE_IPV6 */ + +#endif /* HAVE_INET_PTON */ diff --git a/dependencies/cmcurl/lib/inet_pton.h b/dependencies/cmcurl/lib/inet_pton.h new file mode 100644 index 0000000..0209b9b --- /dev/null +++ b/dependencies/cmcurl/lib/inet_pton.h @@ -0,0 +1,39 @@ +#ifndef HEADER_CURL_INET_PTON_H +#define HEADER_CURL_INET_PTON_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +int Curl_inet_pton(int, const char *, void *); + +#ifdef HAVE_INET_PTON +#ifdef HAVE_ARPA_INET_H +#include +#elif defined(HAVE_WS2TCPIP_H) +/* inet_pton() exists in Vista or later */ +#include +#endif +#define Curl_inet_pton(x,y,z) inet_pton(x,y,z) +#endif + +#endif /* HEADER_CURL_INET_PTON_H */ diff --git a/dependencies/cmcurl/lib/krb5.c b/dependencies/cmcurl/lib/krb5.c new file mode 100644 index 0000000..147ab02 --- /dev/null +++ b/dependencies/cmcurl/lib/krb5.c @@ -0,0 +1,343 @@ +/* GSSAPI/krb5 support for FTP - loosely based on old krb4.c + * + * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * Copyright (c) 2004 - 2017 Daniel Stenberg + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ + +#include "curl_setup.h" + +#if defined(HAVE_GSSAPI) && !defined(CURL_DISABLE_FTP) + +#ifdef HAVE_NETDB_H +#include +#endif + +#include "urldata.h" +#include "curl_base64.h" +#include "ftp.h" +#include "curl_gssapi.h" +#include "sendf.h" +#include "curl_sec.h" +#include "warnless.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +static int +krb5_init(void *app_data) +{ + gss_ctx_id_t *context = app_data; + /* Make sure our context is initialized for krb5_end. */ + *context = GSS_C_NO_CONTEXT; + return 0; +} + +static int +krb5_check_prot(void *app_data, int level) +{ + (void)app_data; /* unused */ + if(level == PROT_CONFIDENTIAL) + return -1; + return 0; +} + +static int +krb5_decode(void *app_data, void *buf, int len, + int level UNUSED_PARAM, + struct connectdata *conn UNUSED_PARAM) +{ + gss_ctx_id_t *context = app_data; + OM_uint32 maj, min; + gss_buffer_desc enc, dec; + + (void)level; + (void)conn; + + enc.value = buf; + enc.length = len; + maj = gss_unwrap(&min, *context, &enc, &dec, NULL, NULL); + if(maj != GSS_S_COMPLETE) { + if(len >= 4) + strcpy(buf, "599 "); + return -1; + } + + memcpy(buf, dec.value, dec.length); + len = curlx_uztosi(dec.length); + gss_release_buffer(&min, &dec); + + return len; +} + +static int +krb5_overhead(void *app_data, int level, int len) +{ + /* no arguments are used */ + (void)app_data; + (void)level; + (void)len; + return 0; +} + +static int +krb5_encode(void *app_data, const void *from, int length, int level, void **to) +{ + gss_ctx_id_t *context = app_data; + gss_buffer_desc dec, enc; + OM_uint32 maj, min; + int state; + int len; + + /* NOTE that the cast is safe, neither of the krb5, gnu gss and heimdal + * libraries modify the input buffer in gss_wrap() + */ + dec.value = (void *)from; + dec.length = length; + maj = gss_wrap(&min, *context, + level == PROT_PRIVATE, + GSS_C_QOP_DEFAULT, + &dec, &state, &enc); + + if(maj != GSS_S_COMPLETE) + return -1; + + /* malloc a new buffer, in case gss_release_buffer doesn't work as + expected */ + *to = malloc(enc.length); + if(!*to) + return -1; + memcpy(*to, enc.value, enc.length); + len = curlx_uztosi(enc.length); + gss_release_buffer(&min, &enc); + return len; +} + +static int +krb5_auth(void *app_data, struct connectdata *conn) +{ + int ret = AUTH_OK; + char *p; + const char *host = conn->host.name; + ssize_t nread; + curl_socklen_t l = sizeof(conn->local_addr); + struct Curl_easy *data = conn->data; + CURLcode result; + const char *service = data->set.str[STRING_SERVICE_NAME] ? + data->set.str[STRING_SERVICE_NAME] : + "ftp"; + const char *srv_host = "host"; + gss_buffer_desc input_buffer, output_buffer, _gssresp, *gssresp; + OM_uint32 maj, min; + gss_name_t gssname; + gss_ctx_id_t *context = app_data; + struct gss_channel_bindings_struct chan; + size_t base64_sz = 0; + struct sockaddr_in **remote_addr = + (struct sockaddr_in **)&conn->ip_addr->ai_addr; + char *stringp; + + if(getsockname(conn->sock[FIRSTSOCKET], + (struct sockaddr *)&conn->local_addr, &l) < 0) + perror("getsockname()"); + + chan.initiator_addrtype = GSS_C_AF_INET; + chan.initiator_address.length = l - 4; + chan.initiator_address.value = &conn->local_addr.sin_addr.s_addr; + chan.acceptor_addrtype = GSS_C_AF_INET; + chan.acceptor_address.length = l - 4; + chan.acceptor_address.value = &(*remote_addr)->sin_addr.s_addr; + chan.application_data.length = 0; + chan.application_data.value = NULL; + + /* this loop will execute twice (once for service, once for host) */ + for(;;) { + /* this really shouldn't be repeated here, but can't help it */ + if(service == srv_host) { + result = Curl_ftpsend(conn, "AUTH GSSAPI"); + if(result) + return -2; + + if(Curl_GetFTPResponse(&nread, conn, NULL)) + return -1; + + if(data->state.buffer[0] != '3') + return -1; + } + + stringp = aprintf("%s@%s", service, host); + if(!stringp) + return -2; + + input_buffer.value = stringp; + input_buffer.length = strlen(stringp); + maj = gss_import_name(&min, &input_buffer, GSS_C_NT_HOSTBASED_SERVICE, + &gssname); + free(stringp); + if(maj != GSS_S_COMPLETE) { + gss_release_name(&min, &gssname); + if(service == srv_host) { + failf(data, "Error importing service name %s@%s", service, host); + return AUTH_ERROR; + } + service = srv_host; + continue; + } + /* We pass NULL as |output_name_type| to avoid a leak. */ + gss_display_name(&min, gssname, &output_buffer, NULL); + Curl_infof(data, "Trying against %s\n", output_buffer.value); + gssresp = GSS_C_NO_BUFFER; + *context = GSS_C_NO_CONTEXT; + + do { + /* Release the buffer at each iteration to avoid leaking: the first time + we are releasing the memory from gss_display_name. The last item is + taken care by a final gss_release_buffer. */ + gss_release_buffer(&min, &output_buffer); + ret = AUTH_OK; + maj = Curl_gss_init_sec_context(data, + &min, + context, + gssname, + &Curl_krb5_mech_oid, + &chan, + gssresp, + &output_buffer, + TRUE, + NULL); + + if(gssresp) { + free(_gssresp.value); + gssresp = NULL; + } + + if(GSS_ERROR(maj)) { + Curl_infof(data, "Error creating security context\n"); + ret = AUTH_ERROR; + break; + } + + if(output_buffer.length != 0) { + char *cmd; + + result = Curl_base64_encode(data, (char *)output_buffer.value, + output_buffer.length, &p, &base64_sz); + if(result) { + Curl_infof(data, "base64-encoding: %s\n", + curl_easy_strerror(result)); + ret = AUTH_ERROR; + break; + } + + cmd = aprintf("ADAT %s", p); + if(cmd) + result = Curl_ftpsend(conn, cmd); + else + result = CURLE_OUT_OF_MEMORY; + + free(p); + free(cmd); + + if(result) { + ret = -2; + break; + } + + if(Curl_GetFTPResponse(&nread, conn, NULL)) { + ret = -1; + break; + } + + if(data->state.buffer[0] != '2' && data->state.buffer[0] != '3') { + Curl_infof(data, "Server didn't accept auth data\n"); + ret = AUTH_ERROR; + break; + } + + _gssresp.value = NULL; /* make sure it is initialized */ + p = data->state.buffer + 4; + p = strstr(p, "ADAT="); + if(p) { + result = Curl_base64_decode(p + 5, + (unsigned char **)&_gssresp.value, + &_gssresp.length); + if(result) { + failf(data, "base64-decoding: %s", curl_easy_strerror(result)); + ret = AUTH_CONTINUE; + break; + } + } + + gssresp = &_gssresp; + } + } while(maj == GSS_S_CONTINUE_NEEDED); + + gss_release_name(&min, &gssname); + gss_release_buffer(&min, &output_buffer); + + if(gssresp) + free(_gssresp.value); + + if(ret == AUTH_OK || service == srv_host) + return ret; + + service = srv_host; + } + return ret; +} + +static void krb5_end(void *app_data) +{ + OM_uint32 min; + gss_ctx_id_t *context = app_data; + if(*context != GSS_C_NO_CONTEXT) { +#ifdef DEBUGBUILD + OM_uint32 maj = +#endif + gss_delete_sec_context(&min, context, GSS_C_NO_BUFFER); + DEBUGASSERT(maj == GSS_S_COMPLETE); + } +} + +struct Curl_sec_client_mech Curl_krb5_client_mech = { + "GSSAPI", + sizeof(gss_ctx_id_t), + krb5_init, + krb5_auth, + krb5_end, + krb5_check_prot, + krb5_overhead, + krb5_encode, + krb5_decode +}; + +#endif /* HAVE_GSSAPI && !CURL_DISABLE_FTP */ diff --git a/dependencies/cmcurl/lib/ldap.c b/dependencies/cmcurl/lib/ldap.c new file mode 100644 index 0000000..fd31faa --- /dev/null +++ b/dependencies/cmcurl/lib/ldap.c @@ -0,0 +1,1088 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_LDAP) && !defined(USE_OPENLDAP) + +/* + * Notice that USE_OPENLDAP is only a source code selection switch. When + * libcurl is built with USE_OPENLDAP defined the libcurl source code that + * gets compiled is the code from openldap.c, otherwise the code that gets + * compiled is the code from ldap.c. + * + * When USE_OPENLDAP is defined a recent version of the OpenLDAP library + * might be required for compilation and runtime. In order to use ancient + * OpenLDAP library versions, USE_OPENLDAP shall not be defined. + */ + +#ifdef USE_WIN32_LDAP /* Use Windows LDAP implementation. */ +# include +# ifndef LDAP_VENDOR_NAME +# error Your Platform SDK is NOT sufficient for LDAP support! \ + Update your Platform SDK, or disable LDAP support! +# else +# include +# endif +#else +# define LDAP_DEPRECATED 1 /* Be sure ldap_init() is defined. */ +# ifdef HAVE_LBER_H +# include +# endif +# include +# if (defined(HAVE_LDAP_SSL) && defined(HAVE_LDAP_SSL_H)) +# include +# endif /* HAVE_LDAP_SSL && HAVE_LDAP_SSL_H */ +#endif + +#include "urldata.h" +#include +#include "sendf.h" +#include "escape.h" +#include "progress.h" +#include "transfer.h" +#include "strcase.h" +#include "strtok.h" +#include "curl_ldap.h" +#include "curl_multibyte.h" +#include "curl_base64.h" +#include "connect.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#ifndef HAVE_LDAP_URL_PARSE + +/* Use our own implementation. */ + +typedef struct { + char *lud_host; + int lud_port; +#if defined(USE_WIN32_LDAP) + TCHAR *lud_dn; + TCHAR **lud_attrs; +#else + char *lud_dn; + char **lud_attrs; +#endif + int lud_scope; +#if defined(USE_WIN32_LDAP) + TCHAR *lud_filter; +#else + char *lud_filter; +#endif + char **lud_exts; + size_t lud_attrs_dups; /* how many were dup'ed, this field is not in the + "real" struct so can only be used in code + without HAVE_LDAP_URL_PARSE defined */ +} CURL_LDAPURLDesc; + +#undef LDAPURLDesc +#define LDAPURLDesc CURL_LDAPURLDesc + +static int _ldap_url_parse(const struct connectdata *conn, + LDAPURLDesc **ludp); +static void _ldap_free_urldesc(LDAPURLDesc *ludp); + +#undef ldap_free_urldesc +#define ldap_free_urldesc _ldap_free_urldesc +#endif + +#ifdef DEBUG_LDAP + #define LDAP_TRACE(x) do { \ + _ldap_trace("%u: ", __LINE__); \ + _ldap_trace x; \ + } WHILE_FALSE + + static void _ldap_trace(const char *fmt, ...); +#else + #define LDAP_TRACE(x) Curl_nop_stmt +#endif + + +static CURLcode Curl_ldap(struct connectdata *conn, bool *done); + +/* + * LDAP protocol handler. + */ + +const struct Curl_handler Curl_handler_ldap = { + "LDAP", /* scheme */ + ZERO_NULL, /* setup_connection */ + Curl_ldap, /* do_it */ + ZERO_NULL, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_LDAP, /* defport */ + CURLPROTO_LDAP, /* protocol */ + PROTOPT_NONE /* flags */ +}; + +#ifdef HAVE_LDAP_SSL +/* + * LDAPS protocol handler. + */ + +const struct Curl_handler Curl_handler_ldaps = { + "LDAPS", /* scheme */ + ZERO_NULL, /* setup_connection */ + Curl_ldap, /* do_it */ + ZERO_NULL, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_LDAPS, /* defport */ + CURLPROTO_LDAPS, /* protocol */ + PROTOPT_SSL /* flags */ +}; +#endif + +#if defined(USE_WIN32_LDAP) + +#if defined(USE_WINDOWS_SSPI) +static int ldap_win_bind_auth(LDAP *server, const char *user, + const char *passwd, unsigned long authflags) +{ + ULONG method = 0; + SEC_WINNT_AUTH_IDENTITY cred; + int rc = LDAP_AUTH_METHOD_NOT_SUPPORTED; + + memset(&cred, 0, sizeof(cred)); + +#if defined(USE_SPNEGO) + if(authflags & CURLAUTH_NEGOTIATE) { + method = LDAP_AUTH_NEGOTIATE; + } + else +#endif +#if defined(USE_NTLM) + if(authflags & CURLAUTH_NTLM) { + method = LDAP_AUTH_NTLM; + } + else +#endif +#if !defined(CURL_DISABLE_CRYPTO_AUTH) + if(authflags & CURLAUTH_DIGEST) { + method = LDAP_AUTH_DIGEST; + } + else +#endif + { + /* required anyway if one of upper preprocessor definitions enabled */ + } + + if(method && user && passwd) { + rc = Curl_create_sspi_identity(user, passwd, &cred); + if(!rc) { + rc = ldap_bind_s(server, NULL, (TCHAR *)&cred, method); + Curl_sspi_free_identity(&cred); + } + } + else { + /* proceed with current user credentials */ + method = LDAP_AUTH_NEGOTIATE; + rc = ldap_bind_s(server, NULL, NULL, method); + } + return rc; +} +#endif /* #if defined(USE_WINDOWS_SSPI) */ + +static int ldap_win_bind(struct connectdata *conn, LDAP *server, + const char *user, const char *passwd) +{ + int rc = LDAP_INVALID_CREDENTIALS; + + PTCHAR inuser = NULL; + PTCHAR inpass = NULL; + + if(user && passwd && (conn->data->set.httpauth & CURLAUTH_BASIC)) { + inuser = Curl_convert_UTF8_to_tchar((char *) user); + inpass = Curl_convert_UTF8_to_tchar((char *) passwd); + + rc = ldap_simple_bind_s(server, inuser, inpass); + + Curl_unicodefree(inuser); + Curl_unicodefree(inpass); + } +#if defined(USE_WINDOWS_SSPI) + else { + rc = ldap_win_bind_auth(server, user, passwd, conn->data->set.httpauth); + } +#endif + + return rc; +} +#endif /* #if defined(USE_WIN32_LDAP) */ + +static CURLcode Curl_ldap(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + int rc = 0; + LDAP *server = NULL; + LDAPURLDesc *ludp = NULL; + LDAPMessage *ldapmsg = NULL; + LDAPMessage *entryIterator; + int num = 0; + struct Curl_easy *data = conn->data; + int ldap_proto = LDAP_VERSION3; + int ldap_ssl = 0; + char *val_b64 = NULL; + size_t val_b64_sz = 0; + curl_off_t dlsize = 0; +#ifdef LDAP_OPT_NETWORK_TIMEOUT + struct timeval ldap_timeout = {10, 0}; /* 10 sec connection/search timeout */ +#endif +#if defined(USE_WIN32_LDAP) + TCHAR *host = NULL; +#else + char *host = NULL; +#endif + char *user = NULL; + char *passwd = NULL; + + *done = TRUE; /* unconditionally */ + infof(data, "LDAP local: LDAP Vendor = %s ; LDAP Version = %d\n", + LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION); + infof(data, "LDAP local: %s\n", data->change.url); + +#ifdef HAVE_LDAP_URL_PARSE + rc = ldap_url_parse(data->change.url, &ludp); +#else + rc = _ldap_url_parse(conn, &ludp); +#endif + if(rc != 0) { + failf(data, "LDAP local: %s", ldap_err2string(rc)); + result = CURLE_LDAP_INVALID_URL; + goto quit; + } + + /* Get the URL scheme (either ldap or ldaps) */ + if(conn->given->flags & PROTOPT_SSL) + ldap_ssl = 1; + infof(data, "LDAP local: trying to establish %s connection\n", + ldap_ssl ? "encrypted" : "cleartext"); + +#if defined(USE_WIN32_LDAP) + host = Curl_convert_UTF8_to_tchar(conn->host.name); + if(!host) { + result = CURLE_OUT_OF_MEMORY; + + goto quit; + } +#else + host = conn->host.name; +#endif + + if(conn->bits.user_passwd) { + user = conn->user; + passwd = conn->passwd; + } + +#ifdef LDAP_OPT_NETWORK_TIMEOUT + ldap_set_option(NULL, LDAP_OPT_NETWORK_TIMEOUT, &ldap_timeout); +#endif + ldap_set_option(NULL, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto); + + if(ldap_ssl) { +#ifdef HAVE_LDAP_SSL +#ifdef USE_WIN32_LDAP + /* Win32 LDAP SDK doesn't support insecure mode without CA! */ + server = ldap_sslinit(host, (int)conn->port, 1); + ldap_set_option(server, LDAP_OPT_SSL, LDAP_OPT_ON); +#else + int ldap_option; + char *ldap_ca = conn->ssl_config.CAfile; +#if defined(CURL_HAS_NOVELL_LDAPSDK) + rc = ldapssl_client_init(NULL, NULL); + if(rc != LDAP_SUCCESS) { + failf(data, "LDAP local: ldapssl_client_init %s", ldap_err2string(rc)); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } + if(conn->ssl_config.verifypeer) { + /* Novell SDK supports DER or BASE64 files. */ + int cert_type = LDAPSSL_CERT_FILETYPE_B64; + if((data->set.ssl.cert_type) && + (strcasecompare(data->set.ssl.cert_type, "DER"))) + cert_type = LDAPSSL_CERT_FILETYPE_DER; + if(!ldap_ca) { + failf(data, "LDAP local: ERROR %s CA cert not set!", + (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM")); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } + infof(data, "LDAP local: using %s CA cert '%s'\n", + (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"), + ldap_ca); + rc = ldapssl_add_trusted_cert(ldap_ca, cert_type); + if(rc != LDAP_SUCCESS) { + failf(data, "LDAP local: ERROR setting %s CA cert: %s", + (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"), + ldap_err2string(rc)); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } + ldap_option = LDAPSSL_VERIFY_SERVER; + } + else + ldap_option = LDAPSSL_VERIFY_NONE; + rc = ldapssl_set_verify_mode(ldap_option); + if(rc != LDAP_SUCCESS) { + failf(data, "LDAP local: ERROR setting cert verify mode: %s", + ldap_err2string(rc)); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } + server = ldapssl_init(host, (int)conn->port, 1); + if(server == NULL) { + failf(data, "LDAP local: Cannot connect to %s:%ld", + conn->host.dispname, conn->port); + result = CURLE_COULDNT_CONNECT; + goto quit; + } +#elif defined(LDAP_OPT_X_TLS) + if(conn->ssl_config.verifypeer) { + /* OpenLDAP SDK supports BASE64 files. */ + if((data->set.ssl.cert_type) && + (!strcasecompare(data->set.ssl.cert_type, "PEM"))) { + failf(data, "LDAP local: ERROR OpenLDAP only supports PEM cert-type!"); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } + if(!ldap_ca) { + failf(data, "LDAP local: ERROR PEM CA cert not set!"); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } + infof(data, "LDAP local: using PEM CA cert: %s\n", ldap_ca); + rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, ldap_ca); + if(rc != LDAP_SUCCESS) { + failf(data, "LDAP local: ERROR setting PEM CA cert: %s", + ldap_err2string(rc)); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } + ldap_option = LDAP_OPT_X_TLS_DEMAND; + } + else + ldap_option = LDAP_OPT_X_TLS_NEVER; + + rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &ldap_option); + if(rc != LDAP_SUCCESS) { + failf(data, "LDAP local: ERROR setting cert verify mode: %s", + ldap_err2string(rc)); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } + server = ldap_init(host, (int)conn->port); + if(server == NULL) { + failf(data, "LDAP local: Cannot connect to %s:%ld", + conn->host.dispname, conn->port); + result = CURLE_COULDNT_CONNECT; + goto quit; + } + ldap_option = LDAP_OPT_X_TLS_HARD; + rc = ldap_set_option(server, LDAP_OPT_X_TLS, &ldap_option); + if(rc != LDAP_SUCCESS) { + failf(data, "LDAP local: ERROR setting SSL/TLS mode: %s", + ldap_err2string(rc)); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } +/* + rc = ldap_start_tls_s(server, NULL, NULL); + if(rc != LDAP_SUCCESS) { + failf(data, "LDAP local: ERROR starting SSL/TLS mode: %s", + ldap_err2string(rc)); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } +*/ +#else + /* we should probably never come up to here since configure + should check in first place if we can support LDAP SSL/TLS */ + failf(data, "LDAP local: SSL/TLS not supported with this version " + "of the OpenLDAP toolkit\n"); + result = CURLE_SSL_CERTPROBLEM; + goto quit; +#endif +#endif +#endif /* CURL_LDAP_USE_SSL */ + } + else { + server = ldap_init(host, (int)conn->port); + if(server == NULL) { + failf(data, "LDAP local: Cannot connect to %s:%ld", + conn->host.dispname, conn->port); + result = CURLE_COULDNT_CONNECT; + goto quit; + } + } +#ifdef USE_WIN32_LDAP + ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto); +#endif + +#ifdef USE_WIN32_LDAP + rc = ldap_win_bind(conn, server, user, passwd); +#else + rc = ldap_simple_bind_s(server, user, passwd); +#endif + if(!ldap_ssl && rc != 0) { + ldap_proto = LDAP_VERSION2; + ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto); +#ifdef USE_WIN32_LDAP + rc = ldap_win_bind(conn, server, user, passwd); +#else + rc = ldap_simple_bind_s(server, user, passwd); +#endif + } + if(rc != 0) { +#ifdef USE_WIN32_LDAP + failf(data, "LDAP local: bind via ldap_win_bind %s", + ldap_err2string(rc)); +#else + failf(data, "LDAP local: bind via ldap_simple_bind_s %s", + ldap_err2string(rc)); +#endif + result = CURLE_LDAP_CANNOT_BIND; + goto quit; + } + + rc = ldap_search_s(server, ludp->lud_dn, ludp->lud_scope, + ludp->lud_filter, ludp->lud_attrs, 0, &ldapmsg); + + if(rc != 0 && rc != LDAP_SIZELIMIT_EXCEEDED) { + failf(data, "LDAP remote: %s", ldap_err2string(rc)); + result = CURLE_LDAP_SEARCH_FAILED; + goto quit; + } + + for(num = 0, entryIterator = ldap_first_entry(server, ldapmsg); + entryIterator; + entryIterator = ldap_next_entry(server, entryIterator), num++) { + BerElement *ber = NULL; +#if defined(USE_WIN32_LDAP) + TCHAR *attribute; +#else + char *attribute; /*! suspicious that this isn't 'const' */ +#endif + int i; + + /* Get the DN and write it to the client */ + { + char *name; + size_t name_len; +#if defined(USE_WIN32_LDAP) + TCHAR *dn = ldap_get_dn(server, entryIterator); + name = Curl_convert_tchar_to_UTF8(dn); + if(!name) { + ldap_memfree(dn); + + result = CURLE_OUT_OF_MEMORY; + + goto quit; + } +#else + char *dn = name = ldap_get_dn(server, entryIterator); +#endif + name_len = strlen(name); + + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4); + if(result) { +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(name); +#endif + ldap_memfree(dn); + + goto quit; + } + + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *) name, + name_len); + if(result) { +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(name); +#endif + ldap_memfree(dn); + + goto quit; + } + + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); + if(result) { +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(name); +#endif + ldap_memfree(dn); + + goto quit; + } + + dlsize += name_len + 5; + +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(name); +#endif + ldap_memfree(dn); + } + + /* Get the attributes and write them to the client */ + for(attribute = ldap_first_attribute(server, entryIterator, &ber); + attribute; + attribute = ldap_next_attribute(server, entryIterator, ber)) { + BerValue **vals; + size_t attr_len; +#if defined(USE_WIN32_LDAP) + char *attr = Curl_convert_tchar_to_UTF8(attribute); + if(!attr) { + if(ber) + ber_free(ber, 0); + + result = CURLE_OUT_OF_MEMORY; + + goto quit; + } +#else + char *attr = attribute; +#endif + attr_len = strlen(attr); + + vals = ldap_get_values_len(server, entryIterator, attribute); + if(vals != NULL) { + for(i = 0; (vals[i] != NULL); i++) { + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1); + if(result) { + ldap_value_free_len(vals); +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(attr); +#endif + ldap_memfree(attribute); + if(ber) + ber_free(ber, 0); + + goto quit; + } + + result = Curl_client_write(conn, CLIENTWRITE_BODY, + (char *) attr, attr_len); + if(result) { + ldap_value_free_len(vals); +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(attr); +#endif + ldap_memfree(attribute); + if(ber) + ber_free(ber, 0); + + goto quit; + } + + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2); + if(result) { + ldap_value_free_len(vals); +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(attr); +#endif + ldap_memfree(attribute); + if(ber) + ber_free(ber, 0); + + goto quit; + } + + dlsize += attr_len + 3; + + if((attr_len > 7) && + (strcmp(";binary", (char *) attr + (attr_len - 7)) == 0)) { + /* Binary attribute, encode to base64. */ + result = Curl_base64_encode(data, + vals[i]->bv_val, + vals[i]->bv_len, + &val_b64, + &val_b64_sz); + if(result) { + ldap_value_free_len(vals); +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(attr); +#endif + ldap_memfree(attribute); + if(ber) + ber_free(ber, 0); + + goto quit; + } + + if(val_b64_sz > 0) { + result = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64, + val_b64_sz); + free(val_b64); + if(result) { + ldap_value_free_len(vals); +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(attr); +#endif + ldap_memfree(attribute); + if(ber) + ber_free(ber, 0); + + goto quit; + } + + dlsize += val_b64_sz; + } + } + else { + result = Curl_client_write(conn, CLIENTWRITE_BODY, vals[i]->bv_val, + vals[i]->bv_len); + if(result) { + ldap_value_free_len(vals); +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(attr); +#endif + ldap_memfree(attribute); + if(ber) + ber_free(ber, 0); + + goto quit; + } + + dlsize += vals[i]->bv_len; + } + + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); + if(result) { + ldap_value_free_len(vals); +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(attr); +#endif + ldap_memfree(attribute); + if(ber) + ber_free(ber, 0); + + goto quit; + } + + dlsize++; + } + + /* Free memory used to store values */ + ldap_value_free_len(vals); + } + + /* Free the attribute as we are done with it */ +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(attr); +#endif + ldap_memfree(attribute); + + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); + if(result) + goto quit; + dlsize++; + Curl_pgrsSetDownloadCounter(data, dlsize); + } + + if(ber) + ber_free(ber, 0); + } + +quit: + if(ldapmsg) { + ldap_msgfree(ldapmsg); + LDAP_TRACE(("Received %d entries\n", num)); + } + if(rc == LDAP_SIZELIMIT_EXCEEDED) + infof(data, "There are more than %d entries\n", num); + if(ludp) + ldap_free_urldesc(ludp); + if(server) + ldap_unbind_s(server); +#if defined(HAVE_LDAP_SSL) && defined(CURL_HAS_NOVELL_LDAPSDK) + if(ldap_ssl) + ldapssl_client_deinit(); +#endif /* HAVE_LDAP_SSL && CURL_HAS_NOVELL_LDAPSDK */ + +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(host); +#endif + + /* no data to transfer */ + Curl_setup_transfer(data, -1, -1, FALSE, -1); + connclose(conn, "LDAP connection always disable re-use"); + + return result; +} + +#ifdef DEBUG_LDAP +static void _ldap_trace(const char *fmt, ...) +{ + static int do_trace = -1; + va_list args; + + if(do_trace == -1) { + const char *env = getenv("CURL_TRACE"); + do_trace = (env && strtol(env, NULL, 10) > 0); + } + if(!do_trace) + return; + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); +} +#endif + +#ifndef HAVE_LDAP_URL_PARSE + +/* + * Return scope-value for a scope-string. + */ +static int str2scope(const char *p) +{ + if(strcasecompare(p, "one")) + return LDAP_SCOPE_ONELEVEL; + if(strcasecompare(p, "onetree")) + return LDAP_SCOPE_ONELEVEL; + if(strcasecompare(p, "base")) + return LDAP_SCOPE_BASE; + if(strcasecompare(p, "sub")) + return LDAP_SCOPE_SUBTREE; + if(strcasecompare(p, "subtree")) + return LDAP_SCOPE_SUBTREE; + return (-1); +} + +/* + * Split 'str' into strings separated by commas. + * Note: out[] points into 'str'. + */ +static bool split_str(char *str, char ***out, size_t *count) +{ + char **res; + char *lasts; + char *s; + size_t i; + size_t items = 1; + + s = strchr(str, ','); + while(s) { + items++; + s = strchr(++s, ','); + } + + res = calloc(items, sizeof(char *)); + if(!res) + return FALSE; + + for(i = 0, s = strtok_r(str, ",", &lasts); s && i < items; + s = strtok_r(NULL, ",", &lasts), i++) + res[i] = s; + + *out = res; + *count = items; + + return TRUE; +} + +/* + * Break apart the pieces of an LDAP URL. + * Syntax: + * ldap://:/???? + * + * already known from 'conn->host.name'. + * already known from 'conn->remote_port'. + * extract the rest from 'conn->data->state.path+1'. All fields are optional. + * e.g. + * ldap://:/??? + * yields ludp->lud_dn = "". + * + * Defined in RFC4516 section 2. + */ +static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp) +{ + int rc = LDAP_SUCCESS; + char *path; + char *query; + char *p; + char *q; + size_t i; + + if(!conn->data || + !conn->data->state.up.path || + conn->data->state.up.path[0] != '/' || + !strncasecompare("LDAP", conn->data->state.up.scheme, 4)) + return LDAP_INVALID_SYNTAX; + + ludp->lud_scope = LDAP_SCOPE_BASE; + ludp->lud_port = conn->remote_port; + ludp->lud_host = conn->host.name; + + /* Duplicate the path */ + p = path = strdup(conn->data->state.up.path + 1); + if(!path) + return LDAP_NO_MEMORY; + + /* Duplicate the query */ + q = query = strdup(conn->data->state.up.query); + if(!query) { + free(path); + return LDAP_NO_MEMORY; + } + + /* Parse the DN (Distinguished Name) */ + if(*p) { + char *dn = p; + char *unescaped; + CURLcode result; + + LDAP_TRACE(("DN '%s'\n", dn)); + + /* Unescape the DN */ + result = Curl_urldecode(conn->data, dn, 0, &unescaped, NULL, FALSE); + if(result) { + rc = LDAP_NO_MEMORY; + + goto quit; + } + +#if defined(USE_WIN32_LDAP) + /* Convert the unescaped string to a tchar */ + ludp->lud_dn = Curl_convert_UTF8_to_tchar(unescaped); + + /* Free the unescaped string as we are done with it */ + Curl_unicodefree(unescaped); + + if(!ludp->lud_dn) { + rc = LDAP_NO_MEMORY; + + goto quit; + } +#else + ludp->lud_dn = unescaped; +#endif + } + + p = q; + if(!p) + goto quit; + + /* Parse the attributes. skip "??" */ + q = strchr(p, '?'); + if(q) + *q++ = '\0'; + + if(*p) { + char **attributes; + size_t count = 0; + + /* Split the string into an array of attributes */ + if(!split_str(p, &attributes, &count)) { + rc = LDAP_NO_MEMORY; + + goto quit; + } + + /* Allocate our array (+1 for the NULL entry) */ +#if defined(USE_WIN32_LDAP) + ludp->lud_attrs = calloc(count + 1, sizeof(TCHAR *)); +#else + ludp->lud_attrs = calloc(count + 1, sizeof(char *)); +#endif + if(!ludp->lud_attrs) { + free(attributes); + + rc = LDAP_NO_MEMORY; + + goto quit; + } + + for(i = 0; i < count; i++) { + char *unescaped; + CURLcode result; + + LDAP_TRACE(("attr[%d] '%s'\n", i, attributes[i])); + + /* Unescape the attribute */ + result = Curl_urldecode(conn->data, attributes[i], 0, &unescaped, NULL, + FALSE); + if(result) { + free(attributes); + + rc = LDAP_NO_MEMORY; + + goto quit; + } + +#if defined(USE_WIN32_LDAP) + /* Convert the unescaped string to a tchar */ + ludp->lud_attrs[i] = Curl_convert_UTF8_to_tchar(unescaped); + + /* Free the unescaped string as we are done with it */ + Curl_unicodefree(unescaped); + + if(!ludp->lud_attrs[i]) { + free(attributes); + + rc = LDAP_NO_MEMORY; + + goto quit; + } +#else + ludp->lud_attrs[i] = unescaped; +#endif + + ludp->lud_attrs_dups++; + } + + free(attributes); + } + + p = q; + if(!p) + goto quit; + + /* Parse the scope. skip "??" */ + q = strchr(p, '?'); + if(q) + *q++ = '\0'; + + if(*p) { + ludp->lud_scope = str2scope(p); + if(ludp->lud_scope == -1) { + rc = LDAP_INVALID_SYNTAX; + + goto quit; + } + LDAP_TRACE(("scope %d\n", ludp->lud_scope)); + } + + p = q; + if(!p) + goto quit; + + /* Parse the filter */ + q = strchr(p, '?'); + if(q) + *q++ = '\0'; + + if(*p) { + char *filter = p; + char *unescaped; + CURLcode result; + + LDAP_TRACE(("filter '%s'\n", filter)); + + /* Unescape the filter */ + result = Curl_urldecode(conn->data, filter, 0, &unescaped, NULL, FALSE); + if(result) { + rc = LDAP_NO_MEMORY; + + goto quit; + } + +#if defined(USE_WIN32_LDAP) + /* Convert the unescaped string to a tchar */ + ludp->lud_filter = Curl_convert_UTF8_to_tchar(unescaped); + + /* Free the unescaped string as we are done with it */ + Curl_unicodefree(unescaped); + + if(!ludp->lud_filter) { + rc = LDAP_NO_MEMORY; + + goto quit; + } +#else + ludp->lud_filter = unescaped; +#endif + } + + p = q; + if(p && !*p) { + rc = LDAP_INVALID_SYNTAX; + + goto quit; + } + +quit: + free(path); + free(query); + + return rc; +} + +static int _ldap_url_parse(const struct connectdata *conn, + LDAPURLDesc **ludpp) +{ + LDAPURLDesc *ludp = calloc(1, sizeof(*ludp)); + int rc; + + *ludpp = NULL; + if(!ludp) + return LDAP_NO_MEMORY; + + rc = _ldap_url_parse2(conn, ludp); + if(rc != LDAP_SUCCESS) { + _ldap_free_urldesc(ludp); + ludp = NULL; + } + *ludpp = ludp; + return (rc); +} + +static void _ldap_free_urldesc(LDAPURLDesc *ludp) +{ + if(!ludp) + return; + + free(ludp->lud_dn); + free(ludp->lud_filter); + + if(ludp->lud_attrs) { + size_t i; + for(i = 0; i < ludp->lud_attrs_dups; i++) + free(ludp->lud_attrs[i]); + free(ludp->lud_attrs); + } + + free(ludp); +} +#endif /* !HAVE_LDAP_URL_PARSE */ +#endif /* !CURL_DISABLE_LDAP && !USE_OPENLDAP */ diff --git a/dependencies/cmcurl/lib/libcurl.rc b/dependencies/cmcurl/lib/libcurl.rc new file mode 100644 index 0000000..4839d0a --- /dev/null +++ b/dependencies/cmcurl/lib/libcurl.rc @@ -0,0 +1,63 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include +#include "../include/curl/curlver.h" + +LANGUAGE 0, 0 + +#define RC_VERSION LIBCURL_VERSION_MAJOR, LIBCURL_VERSION_MINOR, LIBCURL_VERSION_PATCH, 0 + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RC_VERSION + PRODUCTVERSION RC_VERSION + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#if defined(DEBUGBUILD) || defined(_DEBUG) + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0L + +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "The curl library, https://curl.haxx.se/\0" + VALUE "FileDescription", "libcurl Shared Library\0" + VALUE "FileVersion", LIBCURL_VERSION "\0" + VALUE "InternalName", "libcurl\0" + VALUE "OriginalFilename", "libcurl.dll\0" + VALUE "ProductName", "The curl library\0" + VALUE "ProductVersion", LIBCURL_VERSION "\0" + VALUE "LegalCopyright", "\xa9 " LIBCURL_COPYRIGHT "\0" /* a9: Copyright symbol */ + VALUE "License", "https://curl.haxx.se/docs/copyright.html\0" + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/dependencies/cmcurl/lib/llist.c b/dependencies/cmcurl/lib/llist.c new file mode 100644 index 0000000..f8769c2 --- /dev/null +++ b/dependencies/cmcurl/lib/llist.c @@ -0,0 +1,197 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "llist.h" +#include "curl_memory.h" + +/* this must be the last include file */ +#include "memdebug.h" + +/* + * @unittest: 1300 + */ +void +Curl_llist_init(struct curl_llist *l, curl_llist_dtor dtor) +{ + l->size = 0; + l->dtor = dtor; + l->head = NULL; + l->tail = NULL; +} + +/* + * Curl_llist_insert_next() + * + * Inserts a new list element after the given one 'e'. If the given existing + * entry is NULL and the list already has elements, the new one will be + * inserted first in the list. + * + * The 'ne' argument should be a pointer into the object to store. + * + * @unittest: 1300 + */ +void +Curl_llist_insert_next(struct curl_llist *list, struct curl_llist_element *e, + const void *p, + struct curl_llist_element *ne) +{ + ne->ptr = (void *) p; + if(list->size == 0) { + list->head = ne; + list->head->prev = NULL; + list->head->next = NULL; + list->tail = ne; + } + else { + /* if 'e' is NULL here, we insert the new element first in the list */ + ne->next = e?e->next:list->head; + ne->prev = e; + if(!e) { + list->head->prev = ne; + list->head = ne; + } + else if(e->next) { + e->next->prev = ne; + } + else { + list->tail = ne; + } + if(e) + e->next = ne; + } + + ++list->size; +} + +/* + * @unittest: 1300 + */ +void +Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e, + void *user) +{ + void *ptr; + if(e == NULL || list->size == 0) + return; + + if(e == list->head) { + list->head = e->next; + + if(list->head == NULL) + list->tail = NULL; + else + e->next->prev = NULL; + } + else { + if(!e->prev) + list->head = e->next; + else + e->prev->next = e->next; + + if(!e->next) + list->tail = e->prev; + else + e->next->prev = e->prev; + } + + ptr = e->ptr; + + e->ptr = NULL; + e->prev = NULL; + e->next = NULL; + + --list->size; + + /* call the dtor() last for when it actually frees the 'e' memory itself */ + if(list->dtor) + list->dtor(user, ptr); +} + +void +Curl_llist_destroy(struct curl_llist *list, void *user) +{ + if(list) { + while(list->size > 0) + Curl_llist_remove(list, list->tail, user); + } +} + +size_t +Curl_llist_count(struct curl_llist *list) +{ + return list->size; +} + +/* + * @unittest: 1300 + */ +void Curl_llist_move(struct curl_llist *list, struct curl_llist_element *e, + struct curl_llist *to_list, + struct curl_llist_element *to_e) +{ + /* Remove element from list */ + if(e == NULL || list->size == 0) + return; + + if(e == list->head) { + list->head = e->next; + + if(list->head == NULL) + list->tail = NULL; + else + e->next->prev = NULL; + } + else { + e->prev->next = e->next; + if(!e->next) + list->tail = e->prev; + else + e->next->prev = e->prev; + } + + --list->size; + + /* Add element to to_list after to_e */ + if(to_list->size == 0) { + to_list->head = e; + to_list->head->prev = NULL; + to_list->head->next = NULL; + to_list->tail = e; + } + else { + e->next = to_e->next; + e->prev = to_e; + if(to_e->next) { + to_e->next->prev = e; + } + else { + to_list->tail = e; + } + to_e->next = e; + } + + ++to_list->size; +} diff --git a/dependencies/cmcurl/lib/llist.h b/dependencies/cmcurl/lib/llist.h new file mode 100644 index 0000000..b9d4c89 --- /dev/null +++ b/dependencies/cmcurl/lib/llist.h @@ -0,0 +1,53 @@ +#ifndef HEADER_CURL_LLIST_H +#define HEADER_CURL_LLIST_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include + +typedef void (*curl_llist_dtor)(void *, void *); + +struct curl_llist_element { + void *ptr; + struct curl_llist_element *prev; + struct curl_llist_element *next; +}; + +struct curl_llist { + struct curl_llist_element *head; + struct curl_llist_element *tail; + curl_llist_dtor dtor; + size_t size; +}; + +void Curl_llist_init(struct curl_llist *, curl_llist_dtor); +void Curl_llist_insert_next(struct curl_llist *, struct curl_llist_element *, + const void *, struct curl_llist_element *node); +void Curl_llist_remove(struct curl_llist *, struct curl_llist_element *, + void *); +size_t Curl_llist_count(struct curl_llist *); +void Curl_llist_destroy(struct curl_llist *, void *); +void Curl_llist_move(struct curl_llist *, struct curl_llist_element *, + struct curl_llist *, struct curl_llist_element *); + +#endif /* HEADER_CURL_LLIST_H */ diff --git a/dependencies/cmcurl/lib/md4.c b/dependencies/cmcurl/lib/md4.c new file mode 100644 index 0000000..e7c77bc --- /dev/null +++ b/dependencies/cmcurl/lib/md4.c @@ -0,0 +1,313 @@ +/* + * !checksrc! disable COPYRIGHT + * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. + * MD4 Message-Digest Algorithm (RFC 1320). + * + * Homepage: + https://openwall.info/wiki/people/solar/software/public-domain-source-code/md4 + * + * Author: + * Alexander Peslyak, better known as Solar Designer + * + * This software was written by Alexander Peslyak in 2001. No copyright is + * claimed, and the software is hereby placed in the public domain. In case + * this attempt to disclaim copyright and place the software in the public + * domain is deemed null and void, then the software is Copyright (c) 2001 + * Alexander Peslyak and it is hereby released to the general public under the + * following terms: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * (This is a heavily cut-down "BSD license".) + * + * This differs from Colin Plumb's older public domain implementation in that + * no exactly 32-bit integer data type is required (any 32-bit or wider + * unsigned integer data type will do), there's no compile-time endianness + * configuration, and the function prototypes match OpenSSL's. No code from + * Colin Plumb's implementation has been reused; this comment merely compares + * the properties of the two independent implementations. + * + * The primary goals of this implementation are portability and ease of use. + * It is meant to be fast, but not as fast as possible. Some known + * optimizations are not included to reduce source code size and avoid + * compile-time configuration. + */ + +#include "curl_setup.h" + +/* The NSS, OS/400, and when not included, OpenSSL and mbed TLS crypto + * libraries do not provide the MD4 hash algorithm, so we use this + * implementation of it */ +#if defined(USE_NSS) || defined(USE_OS400CRYPTO) || \ + (defined(USE_OPENSSL) && defined(OPENSSL_NO_MD4)) || \ + (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) + +#include "curl_md4.h" +#include "warnless.h" + +#ifndef HAVE_OPENSSL + +#include + +/* Any 32-bit or wider unsigned integer data type will do */ +typedef unsigned int MD4_u32plus; + +typedef struct { + MD4_u32plus lo, hi; + MD4_u32plus a, b, c, d; + unsigned char buffer[64]; + MD4_u32plus block[16]; +} MD4_CTX; + +static void MD4_Init(MD4_CTX *ctx); +static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size); +static void MD4_Final(unsigned char *result, MD4_CTX *ctx); + +/* + * The basic MD4 functions. + * + * F and G are optimized compared to their RFC 1320 definitions, with the + * optimization for F borrowed from Colin Plumb's MD5 implementation. + */ +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) (((x) & ((y) | (z))) | ((y) & (z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) + +/* + * The MD4 transformation for all three rounds. + */ +#define STEP(f, a, b, c, d, x, s) \ + (a) += f((b), (c), (d)) + (x); \ + (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); + +/* + * SET reads 4 input bytes in little-endian byte order and stores them + * in a properly aligned word in host byte order. + * + * The check for little-endian architectures that tolerate unaligned + * memory accesses is just an optimization. Nothing will break if it + * doesn't work. + */ +#if defined(__i386__) || defined(__x86_64__) || defined(__vax__) +#define SET(n) \ + (*(MD4_u32plus *)(void *)&ptr[(n) * 4]) +#define GET(n) \ + SET(n) +#else +#define SET(n) \ + (ctx->block[(n)] = \ + (MD4_u32plus)ptr[(n) * 4] | \ + ((MD4_u32plus)ptr[(n) * 4 + 1] << 8) | \ + ((MD4_u32plus)ptr[(n) * 4 + 2] << 16) | \ + ((MD4_u32plus)ptr[(n) * 4 + 3] << 24)) +#define GET(n) \ + (ctx->block[(n)]) +#endif + +/* + * This processes one or more 64-byte data blocks, but does NOT update + * the bit counters. There are no alignment requirements. + */ +static const void *body(MD4_CTX *ctx, const void *data, unsigned long size) +{ + const unsigned char *ptr; + MD4_u32plus a, b, c, d; + + ptr = (const unsigned char *)data; + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + + do { + MD4_u32plus saved_a, saved_b, saved_c, saved_d; + + saved_a = a; + saved_b = b; + saved_c = c; + saved_d = d; + +/* Round 1 */ + STEP(F, a, b, c, d, SET(0), 3) + STEP(F, d, a, b, c, SET(1), 7) + STEP(F, c, d, a, b, SET(2), 11) + STEP(F, b, c, d, a, SET(3), 19) + STEP(F, a, b, c, d, SET(4), 3) + STEP(F, d, a, b, c, SET(5), 7) + STEP(F, c, d, a, b, SET(6), 11) + STEP(F, b, c, d, a, SET(7), 19) + STEP(F, a, b, c, d, SET(8), 3) + STEP(F, d, a, b, c, SET(9), 7) + STEP(F, c, d, a, b, SET(10), 11) + STEP(F, b, c, d, a, SET(11), 19) + STEP(F, a, b, c, d, SET(12), 3) + STEP(F, d, a, b, c, SET(13), 7) + STEP(F, c, d, a, b, SET(14), 11) + STEP(F, b, c, d, a, SET(15), 19) + +/* Round 2 */ + STEP(G, a, b, c, d, GET(0) + 0x5a827999, 3) + STEP(G, d, a, b, c, GET(4) + 0x5a827999, 5) + STEP(G, c, d, a, b, GET(8) + 0x5a827999, 9) + STEP(G, b, c, d, a, GET(12) + 0x5a827999, 13) + STEP(G, a, b, c, d, GET(1) + 0x5a827999, 3) + STEP(G, d, a, b, c, GET(5) + 0x5a827999, 5) + STEP(G, c, d, a, b, GET(9) + 0x5a827999, 9) + STEP(G, b, c, d, a, GET(13) + 0x5a827999, 13) + STEP(G, a, b, c, d, GET(2) + 0x5a827999, 3) + STEP(G, d, a, b, c, GET(6) + 0x5a827999, 5) + STEP(G, c, d, a, b, GET(10) + 0x5a827999, 9) + STEP(G, b, c, d, a, GET(14) + 0x5a827999, 13) + STEP(G, a, b, c, d, GET(3) + 0x5a827999, 3) + STEP(G, d, a, b, c, GET(7) + 0x5a827999, 5) + STEP(G, c, d, a, b, GET(11) + 0x5a827999, 9) + STEP(G, b, c, d, a, GET(15) + 0x5a827999, 13) + +/* Round 3 */ + STEP(H, a, b, c, d, GET(0) + 0x6ed9eba1, 3) + STEP(H, d, a, b, c, GET(8) + 0x6ed9eba1, 9) + STEP(H, c, d, a, b, GET(4) + 0x6ed9eba1, 11) + STEP(H, b, c, d, a, GET(12) + 0x6ed9eba1, 15) + STEP(H, a, b, c, d, GET(2) + 0x6ed9eba1, 3) + STEP(H, d, a, b, c, GET(10) + 0x6ed9eba1, 9) + STEP(H, c, d, a, b, GET(6) + 0x6ed9eba1, 11) + STEP(H, b, c, d, a, GET(14) + 0x6ed9eba1, 15) + STEP(H, a, b, c, d, GET(1) + 0x6ed9eba1, 3) + STEP(H, d, a, b, c, GET(9) + 0x6ed9eba1, 9) + STEP(H, c, d, a, b, GET(5) + 0x6ed9eba1, 11) + STEP(H, b, c, d, a, GET(13) + 0x6ed9eba1, 15) + STEP(H, a, b, c, d, GET(3) + 0x6ed9eba1, 3) + STEP(H, d, a, b, c, GET(11) + 0x6ed9eba1, 9) + STEP(H, c, d, a, b, GET(7) + 0x6ed9eba1, 11) + STEP(H, b, c, d, a, GET(15) + 0x6ed9eba1, 15) + + a += saved_a; + b += saved_b; + c += saved_c; + d += saved_d; + + ptr += 64; + } while(size -= 64); + + ctx->a = a; + ctx->b = b; + ctx->c = c; + ctx->d = d; + + return ptr; +} + +static void MD4_Init(MD4_CTX *ctx) +{ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + + ctx->lo = 0; + ctx->hi = 0; +} + +static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size) +{ + MD4_u32plus saved_lo; + unsigned long used; + + saved_lo = ctx->lo; + ctx->lo = (saved_lo + size) & 0x1fffffff; + if(ctx->lo < saved_lo) + ctx->hi++; + ctx->hi += (MD4_u32plus)size >> 29; + + used = saved_lo & 0x3f; + + if(used) { + unsigned long available = 64 - used; + + if(size < available) { + memcpy(&ctx->buffer[used], data, size); + return; + } + + memcpy(&ctx->buffer[used], data, available); + data = (const unsigned char *)data + available; + size -= available; + body(ctx, ctx->buffer, 64); + } + + if(size >= 64) { + data = body(ctx, data, size & ~(unsigned long)0x3f); + size &= 0x3f; + } + + memcpy(ctx->buffer, data, size); +} + +static void MD4_Final(unsigned char *result, MD4_CTX *ctx) +{ + unsigned long used, available; + + used = ctx->lo & 0x3f; + + ctx->buffer[used++] = 0x80; + + available = 64 - used; + + if(available < 8) { + memset(&ctx->buffer[used], 0, available); + body(ctx, ctx->buffer, 64); + used = 0; + available = 64; + } + + memset(&ctx->buffer[used], 0, available - 8); + + ctx->lo <<= 3; + ctx->buffer[56] = curlx_ultouc((ctx->lo)&0xff); + ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8)&0xff); + ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16)&0xff); + ctx->buffer[59] = curlx_ultouc((ctx->lo >> 24)&0xff); + ctx->buffer[60] = curlx_ultouc((ctx->hi)&0xff); + ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8)&0xff); + ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16)&0xff); + ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24); + + body(ctx, ctx->buffer, 64); + + result[0] = curlx_ultouc((ctx->a)&0xff); + result[1] = curlx_ultouc((ctx->a >> 8)&0xff); + result[2] = curlx_ultouc((ctx->a >> 16)&0xff); + result[3] = curlx_ultouc(ctx->a >> 24); + result[4] = curlx_ultouc((ctx->b)&0xff); + result[5] = curlx_ultouc((ctx->b >> 8)&0xff); + result[6] = curlx_ultouc((ctx->b >> 16)&0xff); + result[7] = curlx_ultouc(ctx->b >> 24); + result[8] = curlx_ultouc((ctx->c)&0xff); + result[9] = curlx_ultouc((ctx->c >> 8)&0xff); + result[10] = curlx_ultouc((ctx->c >> 16)&0xff); + result[11] = curlx_ultouc(ctx->c >> 24); + result[12] = curlx_ultouc((ctx->d)&0xff); + result[13] = curlx_ultouc((ctx->d >> 8)&0xff); + result[14] = curlx_ultouc((ctx->d >> 16)&0xff); + result[15] = curlx_ultouc(ctx->d >> 24); + + memset(ctx, 0, sizeof(*ctx)); +} + +#endif + +void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len) +{ + MD4_CTX ctx; + MD4_Init(&ctx); + MD4_Update(&ctx, input, curlx_uztoui(len)); + MD4_Final(output, &ctx); +} + +#endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) || + (defined(USE_OPENSSL) && defined(OPENSSL_NO_MD4)) || + (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) */ diff --git a/dependencies/cmcurl/lib/md5.c b/dependencies/cmcurl/lib/md5.c new file mode 100644 index 0000000..2b81ca4 --- /dev/null +++ b/dependencies/cmcurl/lib/md5.c @@ -0,0 +1,568 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_CRYPTO_AUTH + +#include + +#include "curl_md5.h" +#include "curl_hmac.h" +#include "warnless.h" + +#if defined(USE_GNUTLS_NETTLE) + +#include +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +typedef struct md5_ctx MD5_CTX; + +static void MD5_Init(MD5_CTX *ctx) +{ + md5_init(ctx); +} + +static void MD5_Update(MD5_CTX *ctx, + const unsigned char *input, + unsigned int inputLen) +{ + md5_update(ctx, inputLen, input); +} + +static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) +{ + md5_digest(ctx, 16, digest); +} + +#elif defined(USE_GNUTLS) + +#include +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +typedef gcry_md_hd_t MD5_CTX; + +static void MD5_Init(MD5_CTX *ctx) +{ + gcry_md_open(ctx, GCRY_MD_MD5, 0); +} + +static void MD5_Update(MD5_CTX *ctx, + const unsigned char *input, + unsigned int inputLen) +{ + gcry_md_write(*ctx, input, inputLen); +} + +static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) +{ + memcpy(digest, gcry_md_read(*ctx, 0), 16); + gcry_md_close(*ctx); +} + +#elif defined(USE_OPENSSL) && !defined(USE_AMISSL) +/* When OpenSSL is available we use the MD5-function from OpenSSL */ +#include +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \ + (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \ + (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \ + (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000)) + +/* For Apple operating systems: CommonCrypto has the functions we need. + These functions are available on Tiger and later, as well as iOS 2.0 + and later. If you're building for an older cat, well, sorry. + + Declaring the functions as static like this seems to be a bit more + reliable than defining COMMON_DIGEST_FOR_OPENSSL on older cats. */ +# include +# define MD5_CTX CC_MD5_CTX +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +static void MD5_Init(MD5_CTX *ctx) +{ + CC_MD5_Init(ctx); +} + +static void MD5_Update(MD5_CTX *ctx, + const unsigned char *input, + unsigned int inputLen) +{ + CC_MD5_Update(ctx, input, inputLen); +} + +static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) +{ + CC_MD5_Final(digest, ctx); +} + +#elif defined(WIN32) && !defined(CURL_WINDOWS_APP) + +#include +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +typedef struct { + HCRYPTPROV hCryptProv; + HCRYPTHASH hHash; +} MD5_CTX; + +static void MD5_Init(MD5_CTX *ctx) +{ + if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, + PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { + CryptCreateHash(ctx->hCryptProv, CALG_MD5, 0, 0, &ctx->hHash); + } +} + +static void MD5_Update(MD5_CTX *ctx, + const unsigned char *input, + unsigned int inputLen) +{ + CryptHashData(ctx->hHash, (unsigned char *)input, inputLen, 0); +} + +static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) +{ + unsigned long length = 0; + CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0); + if(length == 16) + CryptGetHashParam(ctx->hHash, HP_HASHVAL, digest, &length, 0); + if(ctx->hHash) + CryptDestroyHash(ctx->hHash); + if(ctx->hCryptProv) + CryptReleaseContext(ctx->hCryptProv, 0); +} + +#else +/* When no other crypto library is available we use this code segment */ +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. + * MD5 Message-Digest Algorithm (RFC 1321). + * + * Homepage: + https://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 + * + * Author: + * Alexander Peslyak, better known as Solar Designer + * + * This software was written by Alexander Peslyak in 2001. No copyright is + * claimed, and the software is hereby placed in the public domain. + * In case this attempt to disclaim copyright and place the software in the + * public domain is deemed null and void, then the software is + * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the + * general public under the following terms: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * (This is a heavily cut-down "BSD license".) + * + * This differs from Colin Plumb's older public domain implementation in that + * no exactly 32-bit integer data type is required (any 32-bit or wider + * unsigned integer data type will do), there's no compile-time endianness + * configuration, and the function prototypes match OpenSSL's. No code from + * Colin Plumb's implementation has been reused; this comment merely compares + * the properties of the two independent implementations. + * + * The primary goals of this implementation are portability and ease of use. + * It is meant to be fast, but not as fast as possible. Some known + * optimizations are not included to reduce source code size and avoid + * compile-time configuration. + */ + +#include + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* Any 32-bit or wider unsigned integer data type will do */ +typedef unsigned int MD5_u32plus; + +typedef struct { + MD5_u32plus lo, hi; + MD5_u32plus a, b, c, d; + unsigned char buffer[64]; + MD5_u32plus block[16]; +} MD5_CTX; + +static void MD5_Init(MD5_CTX *ctx); +static void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size); +static void MD5_Final(unsigned char *result, MD5_CTX *ctx); + +/* + * The basic MD5 functions. + * + * F and G are optimized compared to their RFC 1321 definitions for + * architectures that lack an AND-NOT instruction, just like in Colin Plumb's + * implementation. + */ +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) +#define H(x, y, z) (((x) ^ (y)) ^ (z)) +#define H2(x, y, z) ((x) ^ ((y) ^ (z))) +#define I(x, y, z) ((y) ^ ((x) | ~(z))) + +/* + * The MD5 transformation for all four rounds. + */ +#define STEP(f, a, b, c, d, x, t, s) \ + (a) += f((b), (c), (d)) + (x) + (t); \ + (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ + (a) += (b); + +/* + * SET reads 4 input bytes in little-endian byte order and stores them + * in a properly aligned word in host byte order. + * + * The check for little-endian architectures that tolerate unaligned + * memory accesses is just an optimization. Nothing will break if it + * doesn't work. + */ +#if defined(__i386__) || defined(__x86_64__) || defined(__vax__) +#define SET(n) \ + (*(MD5_u32plus *)(void *)&ptr[(n) * 4]) +#define GET(n) \ + SET(n) +#else +#define SET(n) \ + (ctx->block[(n)] = \ + (MD5_u32plus)ptr[(n) * 4] | \ + ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \ + ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \ + ((MD5_u32plus)ptr[(n) * 4 + 3] << 24)) +#define GET(n) \ + (ctx->block[(n)]) +#endif + +/* + * This processes one or more 64-byte data blocks, but does NOT update + * the bit counters. There are no alignment requirements. + */ +static const void *body(MD5_CTX *ctx, const void *data, unsigned long size) +{ + const unsigned char *ptr; + MD5_u32plus a, b, c, d; + + ptr = (const unsigned char *)data; + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + + do { + MD5_u32plus saved_a, saved_b, saved_c, saved_d; + + saved_a = a; + saved_b = b; + saved_c = c; + saved_d = d; + +/* Round 1 */ + STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7) + STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12) + STEP(F, c, d, a, b, SET(2), 0x242070db, 17) + STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22) + STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7) + STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12) + STEP(F, c, d, a, b, SET(6), 0xa8304613, 17) + STEP(F, b, c, d, a, SET(7), 0xfd469501, 22) + STEP(F, a, b, c, d, SET(8), 0x698098d8, 7) + STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12) + STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17) + STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22) + STEP(F, a, b, c, d, SET(12), 0x6b901122, 7) + STEP(F, d, a, b, c, SET(13), 0xfd987193, 12) + STEP(F, c, d, a, b, SET(14), 0xa679438e, 17) + STEP(F, b, c, d, a, SET(15), 0x49b40821, 22) + +/* Round 2 */ + STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5) + STEP(G, d, a, b, c, GET(6), 0xc040b340, 9) + STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14) + STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20) + STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5) + STEP(G, d, a, b, c, GET(10), 0x02441453, 9) + STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14) + STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20) + STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5) + STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9) + STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14) + STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20) + STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5) + STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9) + STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14) + STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20) + +/* Round 3 */ + STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4) + STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11) + STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16) + STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23) + STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4) + STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11) + STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16) + STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23) + STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4) + STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11) + STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16) + STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23) + STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4) + STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11) + STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16) + STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23) + +/* Round 4 */ + STEP(I, a, b, c, d, GET(0), 0xf4292244, 6) + STEP(I, d, a, b, c, GET(7), 0x432aff97, 10) + STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15) + STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21) + STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6) + STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10) + STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15) + STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21) + STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6) + STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10) + STEP(I, c, d, a, b, GET(6), 0xa3014314, 15) + STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21) + STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6) + STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10) + STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15) + STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21) + + a += saved_a; + b += saved_b; + c += saved_c; + d += saved_d; + + ptr += 64; + } while(size -= 64); + + ctx->a = a; + ctx->b = b; + ctx->c = c; + ctx->d = d; + + return ptr; +} + +static void MD5_Init(MD5_CTX *ctx) +{ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + + ctx->lo = 0; + ctx->hi = 0; +} + +static void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size) +{ + MD5_u32plus saved_lo; + unsigned long used; + + saved_lo = ctx->lo; + ctx->lo = (saved_lo + size) & 0x1fffffff; + if(ctx->lo < saved_lo) + ctx->hi++; + ctx->hi += (MD5_u32plus)size >> 29; + + used = saved_lo & 0x3f; + + if(used) { + unsigned long available = 64 - used; + + if(size < available) { + memcpy(&ctx->buffer[used], data, size); + return; + } + + memcpy(&ctx->buffer[used], data, available); + data = (const unsigned char *)data + available; + size -= available; + body(ctx, ctx->buffer, 64); + } + + if(size >= 64) { + data = body(ctx, data, size & ~(unsigned long)0x3f); + size &= 0x3f; + } + + memcpy(ctx->buffer, data, size); +} + +static void MD5_Final(unsigned char *result, MD5_CTX *ctx) +{ + unsigned long used, available; + + used = ctx->lo & 0x3f; + + ctx->buffer[used++] = 0x80; + + available = 64 - used; + + if(available < 8) { + memset(&ctx->buffer[used], 0, available); + body(ctx, ctx->buffer, 64); + used = 0; + available = 64; + } + + memset(&ctx->buffer[used], 0, available - 8); + + ctx->lo <<= 3; + ctx->buffer[56] = curlx_ultouc((ctx->lo)&0xff); + ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8)&0xff); + ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16)&0xff); + ctx->buffer[59] = curlx_ultouc(ctx->lo >> 24); + ctx->buffer[60] = curlx_ultouc((ctx->hi)&0xff); + ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8)&0xff); + ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16)&0xff); + ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24); + + body(ctx, ctx->buffer, 64); + + result[0] = curlx_ultouc((ctx->a)&0xff); + result[1] = curlx_ultouc((ctx->a >> 8)&0xff); + result[2] = curlx_ultouc((ctx->a >> 16)&0xff); + result[3] = curlx_ultouc(ctx->a >> 24); + result[4] = curlx_ultouc((ctx->b)&0xff); + result[5] = curlx_ultouc((ctx->b >> 8)&0xff); + result[6] = curlx_ultouc((ctx->b >> 16)&0xff); + result[7] = curlx_ultouc(ctx->b >> 24); + result[8] = curlx_ultouc((ctx->c)&0xff); + result[9] = curlx_ultouc((ctx->c >> 8)&0xff); + result[10] = curlx_ultouc((ctx->c >> 16)&0xff); + result[11] = curlx_ultouc(ctx->c >> 24); + result[12] = curlx_ultouc((ctx->d)&0xff); + result[13] = curlx_ultouc((ctx->d >> 8)&0xff); + result[14] = curlx_ultouc((ctx->d >> 16)&0xff); + result[15] = curlx_ultouc(ctx->d >> 24); + + memset(ctx, 0, sizeof(*ctx)); +} + +#endif /* CRYPTO LIBS */ + +const HMAC_params Curl_HMAC_MD5[] = { + { + /* Hash initialization function. */ + CURLX_FUNCTION_CAST(HMAC_hinit_func, MD5_Init), + /* Hash update function. */ + CURLX_FUNCTION_CAST(HMAC_hupdate_func, MD5_Update), + /* Hash computation end function. */ + CURLX_FUNCTION_CAST(HMAC_hfinal_func, MD5_Final), + /* Size of hash context structure. */ + sizeof(MD5_CTX), + /* Maximum key length. */ + 64, + /* Result size. */ + 16 + } +}; + +const MD5_params Curl_DIGEST_MD5[] = { + { + /* Digest initialization function */ + CURLX_FUNCTION_CAST(Curl_MD5_init_func, MD5_Init), + /* Digest update function */ + CURLX_FUNCTION_CAST(Curl_MD5_update_func, MD5_Update), + /* Digest computation end function */ + CURLX_FUNCTION_CAST(Curl_MD5_final_func, MD5_Final), + /* Size of digest context struct */ + sizeof(MD5_CTX), + /* Result size */ + 16 + } +}; + +/* + * @unittest: 1601 + */ +void Curl_md5it(unsigned char *outbuffer, /* 16 bytes */ + const unsigned char *input) +{ + MD5_CTX ctx; + MD5_Init(&ctx); + MD5_Update(&ctx, input, curlx_uztoui(strlen((char *)input))); + MD5_Final(outbuffer, &ctx); +} + +MD5_context *Curl_MD5_init(const MD5_params *md5params) +{ + MD5_context *ctxt; + + /* Create MD5 context */ + ctxt = malloc(sizeof(*ctxt)); + + if(!ctxt) + return ctxt; + + ctxt->md5_hashctx = malloc(md5params->md5_ctxtsize); + + if(!ctxt->md5_hashctx) { + free(ctxt); + return NULL; + } + + ctxt->md5_hash = md5params; + + (*md5params->md5_init_func)(ctxt->md5_hashctx); + + return ctxt; +} + +CURLcode Curl_MD5_update(MD5_context *context, + const unsigned char *data, + unsigned int len) +{ + (*context->md5_hash->md5_update_func)(context->md5_hashctx, data, len); + + return CURLE_OK; +} + +CURLcode Curl_MD5_final(MD5_context *context, unsigned char *result) +{ + (*context->md5_hash->md5_final_func)(result, context->md5_hashctx); + + free(context->md5_hashctx); + free(context); + + return CURLE_OK; +} + +#endif /* CURL_DISABLE_CRYPTO_AUTH */ diff --git a/dependencies/cmcurl/lib/memdebug.c b/dependencies/cmcurl/lib/memdebug.c new file mode 100644 index 0000000..ede6009 --- /dev/null +++ b/dependencies/cmcurl/lib/memdebug.c @@ -0,0 +1,503 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef CURLDEBUG + +#include + +#include "urldata.h" + +#define MEMDEBUG_NODEFINES /* don't redefine the standard functions */ + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Until 2011-08-17 libcurl's Memory Tracking feature also performed + * automatic malloc and free filling operations using 0xA5 and 0x13 + * values. Our own preinitialization of dynamically allocated memory + * might be useful when not using third party memory debuggers, but + * on the other hand this would fool memory debuggers into thinking + * that all dynamically allocated memory is properly initialized. + * + * As a default setting, libcurl's Memory Tracking feature no longer + * performs preinitialization of dynamically allocated memory on its + * own. If you know what you are doing, and really want to retain old + * behavior, you can achieve this compiling with preprocessor symbols + * CURL_MT_MALLOC_FILL and CURL_MT_FREE_FILL defined with appropriate + * values. + */ + +#ifdef CURL_MT_MALLOC_FILL +# if (CURL_MT_MALLOC_FILL < 0) || (CURL_MT_MALLOC_FILL > 0xff) +# error "invalid CURL_MT_MALLOC_FILL or out of range" +# endif +#endif + +#ifdef CURL_MT_FREE_FILL +# if (CURL_MT_FREE_FILL < 0) || (CURL_MT_FREE_FILL > 0xff) +# error "invalid CURL_MT_FREE_FILL or out of range" +# endif +#endif + +#if defined(CURL_MT_MALLOC_FILL) && defined(CURL_MT_FREE_FILL) +# if (CURL_MT_MALLOC_FILL == CURL_MT_FREE_FILL) +# error "CURL_MT_MALLOC_FILL same as CURL_MT_FREE_FILL" +# endif +#endif + +#ifdef CURL_MT_MALLOC_FILL +# define mt_malloc_fill(buf,len) memset((buf), CURL_MT_MALLOC_FILL, (len)) +#else +# define mt_malloc_fill(buf,len) Curl_nop_stmt +#endif + +#ifdef CURL_MT_FREE_FILL +# define mt_free_fill(buf,len) memset((buf), CURL_MT_FREE_FILL, (len)) +#else +# define mt_free_fill(buf,len) Curl_nop_stmt +#endif + +struct memdebug { + size_t size; + union { + curl_off_t o; + double d; + void *p; + } mem[1]; + /* I'm hoping this is the thing with the strictest alignment + * requirements. That also means we waste some space :-( */ +}; + +/* + * Note that these debug functions are very simple and they are meant to + * remain so. For advanced analysis, record a log file and write perl scripts + * to analyze them! + * + * Don't use these with multithreaded test programs! + */ + +FILE *curl_dbg_logfile = NULL; +static bool memlimit = FALSE; /* enable memory limit */ +static long memsize = 0; /* set number of mallocs allowed */ + +/* this sets the log file name */ +void curl_dbg_memdebug(const char *logname) +{ + if(!curl_dbg_logfile) { + if(logname && *logname) + curl_dbg_logfile = fopen(logname, FOPEN_WRITETEXT); + else + curl_dbg_logfile = stderr; +#ifdef MEMDEBUG_LOG_SYNC + /* Flush the log file after every line so the log isn't lost in a crash */ + if(curl_dbg_logfile) + setbuf(curl_dbg_logfile, (char *)NULL); +#endif + } +} + +/* This function sets the number of malloc() calls that should return + successfully! */ +void curl_dbg_memlimit(long limit) +{ + if(!memlimit) { + memlimit = TRUE; + memsize = limit; + } +} + +/* returns TRUE if this isn't allowed! */ +static bool countcheck(const char *func, int line, const char *source) +{ + /* if source is NULL, then the call is made internally and this check + should not be made */ + if(memlimit && source) { + if(!memsize) { + if(source) { + /* log to file */ + curl_dbg_log("LIMIT %s:%d %s reached memlimit\n", + source, line, func); + /* log to stderr also */ + fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n", + source, line, func); + fflush(curl_dbg_logfile); /* because it might crash now */ + } + errno = ENOMEM; + return TRUE; /* RETURN ERROR! */ + } + else + memsize--; /* countdown */ + + + } + + return FALSE; /* allow this */ +} + +void *curl_dbg_malloc(size_t wantedsize, int line, const char *source) +{ + struct memdebug *mem; + size_t size; + + DEBUGASSERT(wantedsize != 0); + + if(countcheck("malloc", line, source)) + return NULL; + + /* alloc at least 64 bytes */ + size = sizeof(struct memdebug) + wantedsize; + + mem = (Curl_cmalloc)(size); + if(mem) { + /* fill memory with junk */ + mt_malloc_fill(mem->mem, wantedsize); + mem->size = wantedsize; + } + + if(source) + curl_dbg_log("MEM %s:%d malloc(%zu) = %p\n", + source, line, wantedsize, + mem ? (void *)mem->mem : (void *)0); + + return (mem ? mem->mem : NULL); +} + +void *curl_dbg_calloc(size_t wanted_elements, size_t wanted_size, + int line, const char *source) +{ + struct memdebug *mem; + size_t size, user_size; + + DEBUGASSERT(wanted_elements != 0); + DEBUGASSERT(wanted_size != 0); + + if(countcheck("calloc", line, source)) + return NULL; + + /* alloc at least 64 bytes */ + user_size = wanted_size * wanted_elements; + size = sizeof(struct memdebug) + user_size; + + mem = (Curl_ccalloc)(1, size); + if(mem) + mem->size = user_size; + + if(source) + curl_dbg_log("MEM %s:%d calloc(%zu,%zu) = %p\n", + source, line, wanted_elements, wanted_size, + mem ? (void *)mem->mem : (void *)0); + + return (mem ? mem->mem : NULL); +} + +char *curl_dbg_strdup(const char *str, int line, const char *source) +{ + char *mem; + size_t len; + + DEBUGASSERT(str != NULL); + + if(countcheck("strdup", line, source)) + return NULL; + + len = strlen(str) + 1; + + mem = curl_dbg_malloc(len, 0, NULL); /* NULL prevents logging */ + if(mem) + memcpy(mem, str, len); + + if(source) + curl_dbg_log("MEM %s:%d strdup(%p) (%zu) = %p\n", + source, line, (const void *)str, len, (const void *)mem); + + return mem; +} + +#if defined(WIN32) && defined(UNICODE) +wchar_t *curl_dbg_wcsdup(const wchar_t *str, int line, const char *source) +{ + wchar_t *mem; + size_t wsiz, bsiz; + + DEBUGASSERT(str != NULL); + + if(countcheck("wcsdup", line, source)) + return NULL; + + wsiz = wcslen(str) + 1; + bsiz = wsiz * sizeof(wchar_t); + + mem = curl_dbg_malloc(bsiz, 0, NULL); /* NULL prevents logging */ + if(mem) + memcpy(mem, str, bsiz); + + if(source) + curl_dbg_log("MEM %s:%d wcsdup(%p) (%zu) = %p\n", + source, line, (void *)str, bsiz, (void *)mem); + + return mem; +} +#endif + +/* We provide a realloc() that accepts a NULL as pointer, which then + performs a malloc(). In order to work with ares. */ +void *curl_dbg_realloc(void *ptr, size_t wantedsize, + int line, const char *source) +{ + struct memdebug *mem = NULL; + + size_t size = sizeof(struct memdebug) + wantedsize; + + DEBUGASSERT(wantedsize != 0); + + if(countcheck("realloc", line, source)) + return NULL; + +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:1684) + /* 1684: conversion from pointer to same-sized integral type */ +#endif + + if(ptr) + mem = (void *)((char *)ptr - offsetof(struct memdebug, mem)); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif + + mem = (Curl_crealloc)(mem, size); + if(source) + curl_dbg_log("MEM %s:%d realloc(%p, %zu) = %p\n", + source, line, (void *)ptr, wantedsize, + mem ? (void *)mem->mem : (void *)0); + + if(mem) { + mem->size = wantedsize; + return mem->mem; + } + + return NULL; +} + +void curl_dbg_free(void *ptr, int line, const char *source) +{ + if(ptr) { + struct memdebug *mem; + +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:1684) + /* 1684: conversion from pointer to same-sized integral type */ +#endif + + mem = (void *)((char *)ptr - offsetof(struct memdebug, mem)); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif + + /* destroy */ + mt_free_fill(mem->mem, mem->size); + + /* free for real */ + (Curl_cfree)(mem); + } + + if(source) + curl_dbg_log("MEM %s:%d free(%p)\n", source, line, (void *)ptr); +} + +curl_socket_t curl_dbg_socket(int domain, int type, int protocol, + int line, const char *source) +{ + const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? + "FD %s:%d socket() = %d\n" : + (sizeof(curl_socket_t) == sizeof(long)) ? + "FD %s:%d socket() = %ld\n" : + "FD %s:%d socket() = %zd\n"; + + curl_socket_t sockfd; + + if(countcheck("socket", line, source)) + return CURL_SOCKET_BAD; + + sockfd = socket(domain, type, protocol); + + if(source && (sockfd != CURL_SOCKET_BAD)) + curl_dbg_log(fmt, source, line, sockfd); + + return sockfd; +} + +SEND_TYPE_RETV curl_dbg_send(SEND_TYPE_ARG1 sockfd, + SEND_QUAL_ARG2 SEND_TYPE_ARG2 buf, + SEND_TYPE_ARG3 len, SEND_TYPE_ARG4 flags, int line, + const char *source) +{ + SEND_TYPE_RETV rc; + if(countcheck("send", line, source)) + return -1; + rc = send(sockfd, buf, len, flags); + if(source) + curl_dbg_log("SEND %s:%d send(%lu) = %ld\n", + source, line, (unsigned long)len, (long)rc); + return rc; +} + +RECV_TYPE_RETV curl_dbg_recv(RECV_TYPE_ARG1 sockfd, RECV_TYPE_ARG2 buf, + RECV_TYPE_ARG3 len, RECV_TYPE_ARG4 flags, int line, + const char *source) +{ + RECV_TYPE_RETV rc; + if(countcheck("recv", line, source)) + return -1; + rc = recv(sockfd, buf, len, flags); + if(source) + curl_dbg_log("RECV %s:%d recv(%lu) = %ld\n", + source, line, (unsigned long)len, (long)rc); + return rc; +} + +#ifdef HAVE_SOCKETPAIR +int curl_dbg_socketpair(int domain, int type, int protocol, + curl_socket_t socket_vector[2], + int line, const char *source) +{ + const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? + "FD %s:%d socketpair() = %d %d\n" : + (sizeof(curl_socket_t) == sizeof(long)) ? + "FD %s:%d socketpair() = %ld %ld\n" : + "FD %s:%d socketpair() = %zd %zd\n"; + + int res = socketpair(domain, type, protocol, socket_vector); + + if(source && (0 == res)) + curl_dbg_log(fmt, source, line, socket_vector[0], socket_vector[1]); + + return res; +} +#endif + +curl_socket_t curl_dbg_accept(curl_socket_t s, void *saddr, void *saddrlen, + int line, const char *source) +{ + const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? + "FD %s:%d accept() = %d\n" : + (sizeof(curl_socket_t) == sizeof(long)) ? + "FD %s:%d accept() = %ld\n" : + "FD %s:%d accept() = %zd\n"; + + struct sockaddr *addr = (struct sockaddr *)saddr; + curl_socklen_t *addrlen = (curl_socklen_t *)saddrlen; + + curl_socket_t sockfd = accept(s, addr, addrlen); + + if(source && (sockfd != CURL_SOCKET_BAD)) + curl_dbg_log(fmt, source, line, sockfd); + + return sockfd; +} + +/* separate function to allow libcurl to mark a "faked" close */ +void curl_dbg_mark_sclose(curl_socket_t sockfd, int line, const char *source) +{ + const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? + "FD %s:%d sclose(%d)\n": + (sizeof(curl_socket_t) == sizeof(long)) ? + "FD %s:%d sclose(%ld)\n": + "FD %s:%d sclose(%zd)\n"; + + if(source) + curl_dbg_log(fmt, source, line, sockfd); +} + +/* this is our own defined way to close sockets on *ALL* platforms */ +int curl_dbg_sclose(curl_socket_t sockfd, int line, const char *source) +{ + int res = sclose(sockfd); + curl_dbg_mark_sclose(sockfd, line, source); + return res; +} + +FILE *curl_dbg_fopen(const char *file, const char *mode, + int line, const char *source) +{ + FILE *res = fopen(file, mode); + + if(source) + curl_dbg_log("FILE %s:%d fopen(\"%s\",\"%s\") = %p\n", + source, line, file, mode, (void *)res); + + return res; +} + +int curl_dbg_fclose(FILE *file, int line, const char *source) +{ + int res; + + DEBUGASSERT(file != NULL); + + if(source) + curl_dbg_log("FILE %s:%d fclose(%p)\n", + source, line, (void *)file); + + res = fclose(file); + + return res; +} + +#define LOGLINE_BUFSIZE 1024 + +/* this does the writing to the memory tracking log file */ +void curl_dbg_log(const char *format, ...) +{ + char *buf; + int nchars; + va_list ap; + + if(!curl_dbg_logfile) + return; + + buf = (Curl_cmalloc)(LOGLINE_BUFSIZE); + if(!buf) + return; + + va_start(ap, format); + nchars = mvsnprintf(buf, LOGLINE_BUFSIZE, format, ap); + va_end(ap); + + if(nchars > LOGLINE_BUFSIZE - 1) + nchars = LOGLINE_BUFSIZE - 1; + + if(nchars > 0) + fwrite(buf, 1, (size_t)nchars, curl_dbg_logfile); + + (Curl_cfree)(buf); +} + +#endif /* CURLDEBUG */ diff --git a/dependencies/cmcurl/lib/memdebug.h b/dependencies/cmcurl/lib/memdebug.h new file mode 100644 index 0000000..5236f60 --- /dev/null +++ b/dependencies/cmcurl/lib/memdebug.h @@ -0,0 +1,174 @@ +#ifndef HEADER_CURL_MEMDEBUG_H +#define HEADER_CURL_MEMDEBUG_H +#ifdef CURLDEBUG +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * CAUTION: this header is designed to work when included by the app-side + * as well as the library. Do not mix with library internals! + */ + +#define CURL_MT_LOGFNAME_BUFSIZE 512 + +extern FILE *curl_dbg_logfile; + +/* memory functions */ +CURL_EXTERN void *curl_dbg_malloc(size_t size, int line, const char *source); +CURL_EXTERN void *curl_dbg_calloc(size_t elements, size_t size, int line, + const char *source); +CURL_EXTERN void *curl_dbg_realloc(void *ptr, size_t size, int line, + const char *source); +CURL_EXTERN void curl_dbg_free(void *ptr, int line, const char *source); +CURL_EXTERN char *curl_dbg_strdup(const char *str, int line, const char *src); +#if defined(WIN32) && defined(UNICODE) +CURL_EXTERN wchar_t *curl_dbg_wcsdup(const wchar_t *str, int line, + const char *source); +#endif + +CURL_EXTERN void curl_dbg_memdebug(const char *logname); +CURL_EXTERN void curl_dbg_memlimit(long limit); +CURL_EXTERN void curl_dbg_log(const char *format, ...); + +/* file descriptor manipulators */ +CURL_EXTERN curl_socket_t curl_dbg_socket(int domain, int type, int protocol, + int line, const char *source); +CURL_EXTERN void curl_dbg_mark_sclose(curl_socket_t sockfd, + int line, const char *source); +CURL_EXTERN int curl_dbg_sclose(curl_socket_t sockfd, + int line, const char *source); +CURL_EXTERN curl_socket_t curl_dbg_accept(curl_socket_t s, void *a, void *alen, + int line, const char *source); +#ifdef HAVE_SOCKETPAIR +CURL_EXTERN int curl_dbg_socketpair(int domain, int type, int protocol, + curl_socket_t socket_vector[2], + int line, const char *source); +#endif + +/* send/receive sockets */ +CURL_EXTERN SEND_TYPE_RETV curl_dbg_send(SEND_TYPE_ARG1 sockfd, + SEND_QUAL_ARG2 SEND_TYPE_ARG2 buf, + SEND_TYPE_ARG3 len, + SEND_TYPE_ARG4 flags, int line, + const char *source); +CURL_EXTERN RECV_TYPE_RETV curl_dbg_recv(RECV_TYPE_ARG1 sockfd, + RECV_TYPE_ARG2 buf, + RECV_TYPE_ARG3 len, + RECV_TYPE_ARG4 flags, int line, + const char *source); + +/* FILE functions */ +CURL_EXTERN FILE *curl_dbg_fopen(const char *file, const char *mode, int line, + const char *source); +CURL_EXTERN int curl_dbg_fclose(FILE *file, int line, const char *source); + +#ifndef MEMDEBUG_NODEFINES + +/* Set this symbol on the command-line, recompile all lib-sources */ +#undef strdup +#define strdup(ptr) curl_dbg_strdup(ptr, __LINE__, __FILE__) +#define malloc(size) curl_dbg_malloc(size, __LINE__, __FILE__) +#define calloc(nbelem,size) curl_dbg_calloc(nbelem, size, __LINE__, __FILE__) +#define realloc(ptr,size) curl_dbg_realloc(ptr, size, __LINE__, __FILE__) +#define free(ptr) curl_dbg_free(ptr, __LINE__, __FILE__) +#define send(a,b,c,d) curl_dbg_send(a,b,c,d, __LINE__, __FILE__) +#define recv(a,b,c,d) curl_dbg_recv(a,b,c,d, __LINE__, __FILE__) + +#ifdef WIN32 +# ifdef UNICODE +# undef wcsdup +# define wcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__) +# undef _wcsdup +# define _wcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__) +# undef _tcsdup +# define _tcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__) +# else +# undef _tcsdup +# define _tcsdup(ptr) curl_dbg_strdup(ptr, __LINE__, __FILE__) +# endif +#endif + +#undef socket +#define socket(domain,type,protocol)\ + curl_dbg_socket(domain, type, protocol, __LINE__, __FILE__) +#undef accept /* for those with accept as a macro */ +#define accept(sock,addr,len)\ + curl_dbg_accept(sock, addr, len, __LINE__, __FILE__) +#ifdef HAVE_SOCKETPAIR +#define socketpair(domain,type,protocol,socket_vector)\ + curl_dbg_socketpair(domain, type, protocol, socket_vector, __LINE__, __FILE__) +#endif + +#ifdef HAVE_GETADDRINFO +#if defined(getaddrinfo) && defined(__osf__) +/* OSF/1 and Tru64 have getaddrinfo as a define already, so we cannot define + our macro as for other platforms. Instead, we redefine the new name they + define getaddrinfo to become! */ +#define ogetaddrinfo(host,serv,hint,res) \ + curl_dbg_getaddrinfo(host, serv, hint, res, __LINE__, __FILE__) +#else +#undef getaddrinfo +#define getaddrinfo(host,serv,hint,res) \ + curl_dbg_getaddrinfo(host, serv, hint, res, __LINE__, __FILE__) +#endif +#endif /* HAVE_GETADDRINFO */ + +#ifdef HAVE_FREEADDRINFO +#undef freeaddrinfo +#define freeaddrinfo(data) \ + curl_dbg_freeaddrinfo(data, __LINE__, __FILE__) +#endif /* HAVE_FREEADDRINFO */ + +/* sclose is probably already defined, redefine it! */ +#undef sclose +#define sclose(sockfd) curl_dbg_sclose(sockfd,__LINE__,__FILE__) + +#define fake_sclose(sockfd) curl_dbg_mark_sclose(sockfd,__LINE__,__FILE__) + +#undef fopen +#define fopen(file,mode) curl_dbg_fopen(file,mode,__LINE__,__FILE__) +#undef fdopen +#define fdopen(file,mode) curl_dbg_fdopen(file,mode,__LINE__,__FILE__) +#define fclose(file) curl_dbg_fclose(file,__LINE__,__FILE__) + +#endif /* MEMDEBUG_NODEFINES */ + +#endif /* CURLDEBUG */ + +/* +** Following section applies even when CURLDEBUG is not defined. +*/ + +#ifndef fake_sclose +#define fake_sclose(x) Curl_nop_stmt +#endif + +/* + * Curl_safefree defined as a macro to allow MemoryTracking feature + * to log free() calls at same location where Curl_safefree is used. + * This macro also assigns NULL to given pointer when free'd. + */ + +#define Curl_safefree(ptr) \ + do { free((ptr)); (ptr) = NULL;} WHILE_FALSE + +#endif /* HEADER_CURL_MEMDEBUG_H */ diff --git a/dependencies/cmcurl/lib/mime.c b/dependencies/cmcurl/lib/mime.c new file mode 100644 index 0000000..2135f72 --- /dev/null +++ b/dependencies/cmcurl/lib/mime.c @@ -0,0 +1,1904 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "mime.h" +#include "non-ascii.h" +#include "urldata.h" +#include "sendf.h" + +#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)) || \ + !defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP) + +#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME) +#include +#endif + +#include "rand.h" +#include "slist.h" +#include "strcase.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#ifdef WIN32 +# ifndef R_OK +# define R_OK 4 +# endif +#endif + + +#define READ_ERROR ((size_t) -1) + +/* Encoders. */ +static size_t encoder_nop_read(char *buffer, size_t size, bool ateof, + curl_mimepart *part); +static curl_off_t encoder_nop_size(curl_mimepart *part); +static size_t encoder_7bit_read(char *buffer, size_t size, bool ateof, + curl_mimepart *part); +static size_t encoder_base64_read(char *buffer, size_t size, bool ateof, + curl_mimepart *part); +static curl_off_t encoder_base64_size(curl_mimepart *part); +static size_t encoder_qp_read(char *buffer, size_t size, bool ateof, + curl_mimepart *part); +static curl_off_t encoder_qp_size(curl_mimepart *part); + +static const mime_encoder encoders[] = { + {"binary", encoder_nop_read, encoder_nop_size}, + {"8bit", encoder_nop_read, encoder_nop_size}, + {"7bit", encoder_7bit_read, encoder_nop_size}, + {"base64", encoder_base64_read, encoder_base64_size}, + {"quoted-printable", encoder_qp_read, encoder_qp_size}, + {ZERO_NULL, ZERO_NULL, ZERO_NULL} +}; + +/* Base64 encoding table */ +static const char base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/* Quoted-printable character class table. + * + * We cannot rely on ctype functions since quoted-printable input data + * is assumed to be ascii-compatible, even on non-ascii platforms. */ +#define QP_OK 1 /* Can be represented by itself. */ +#define QP_SP 2 /* Space or tab. */ +#define QP_CR 3 /* Carriage return. */ +#define QP_LF 4 /* Line-feed. */ +static const unsigned char qp_class[] = { + 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 07 */ + 0, QP_SP, QP_LF, 0, 0, QP_CR, 0, 0, /* 08 - 0F */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 17 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 18 - 1F */ + QP_SP, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 20 - 27 */ + QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 28 - 2F */ + QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 30 - 37 */ + QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, 0 , QP_OK, QP_OK, /* 38 - 3F */ + QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 40 - 47 */ + QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 48 - 4F */ + QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 50 - 57 */ + QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 58 - 5F */ + QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 60 - 67 */ + QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 68 - 6F */ + QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 70 - 77 */ + QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, 0, /* 78 - 7F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* F0 - FF */ +}; + + +/* Binary --> hexadecimal ASCII table. */ +static const char aschex[] = + "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x41\x42\x43\x44\x45\x46"; + + + +#ifndef __VMS +#define filesize(name, stat_data) (stat_data.st_size) +#define fopen_read fopen + +#else + +#include +/* + * get_vms_file_size does what it takes to get the real size of the file + * + * For fixed files, find out the size of the EOF block and adjust. + * + * For all others, have to read the entire file in, discarding the contents. + * Most posted text files will be small, and binary files like zlib archives + * and CD/DVD images should be either a STREAM_LF format or a fixed format. + * + */ +curl_off_t VmsRealFileSize(const char *name, + const struct_stat *stat_buf) +{ + char buffer[8192]; + curl_off_t count; + int ret_stat; + FILE * file; + + file = fopen(name, FOPEN_READTEXT); /* VMS */ + if(file == NULL) + return 0; + + count = 0; + ret_stat = 1; + while(ret_stat > 0) { + ret_stat = fread(buffer, 1, sizeof(buffer), file); + if(ret_stat != 0) + count += ret_stat; + } + fclose(file); + + return count; +} + +/* + * + * VmsSpecialSize checks to see if the stat st_size can be trusted and + * if not to call a routine to get the correct size. + * + */ +static curl_off_t VmsSpecialSize(const char *name, + const struct_stat *stat_buf) +{ + switch(stat_buf->st_fab_rfm) { + case FAB$C_VAR: + case FAB$C_VFC: + return VmsRealFileSize(name, stat_buf); + break; + default: + return stat_buf->st_size; + } +} + +#define filesize(name, stat_data) VmsSpecialSize(name, &stat_data) + +/* + * vmsfopenread + * + * For upload to work as expected on VMS, different optional + * parameters must be added to the fopen command based on + * record format of the file. + * + */ +static FILE * vmsfopenread(const char *file, const char *mode) +{ + struct_stat statbuf; + int result; + + result = stat(file, &statbuf); + + switch(statbuf.st_fab_rfm) { + case FAB$C_VAR: + case FAB$C_VFC: + case FAB$C_STMCR: + return fopen(file, FOPEN_READTEXT); /* VMS */ + break; + default: + return fopen(file, FOPEN_READTEXT, "rfm=stmlf", "ctx=stm"); + } +} + +#define fopen_read vmsfopenread +#endif + + +#ifndef HAVE_BASENAME +/* + (Quote from The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004 + Edition) + + The basename() function shall take the pathname pointed to by path and + return a pointer to the final component of the pathname, deleting any + trailing '/' characters. + + If the string pointed to by path consists entirely of the '/' character, + basename() shall return a pointer to the string "/". If the string pointed + to by path is exactly "//", it is implementation-defined whether '/' or "//" + is returned. + + If path is a null pointer or points to an empty string, basename() shall + return a pointer to the string ".". + + The basename() function may modify the string pointed to by path, and may + return a pointer to static storage that may then be overwritten by a + subsequent call to basename(). + + The basename() function need not be reentrant. A function that is not + required to be reentrant is not required to be thread-safe. + +*/ +static char *Curl_basename(char *path) +{ + /* Ignore all the details above for now and make a quick and simple + implementation here */ + char *s1; + char *s2; + + s1 = strrchr(path, '/'); + s2 = strrchr(path, '\\'); + + if(s1 && s2) { + path = (s1 > s2? s1 : s2) + 1; + } + else if(s1) + path = s1 + 1; + else if(s2) + path = s2 + 1; + + return path; +} + +#define basename(x) Curl_basename((x)) +#endif + + +/* Set readback state. */ +static void mimesetstate(mime_state *state, enum mimestate tok, void *ptr) +{ + state->state = tok; + state->ptr = ptr; + state->offset = 0; +} + + +/* Escape header string into allocated memory. */ +static char *escape_string(const char *src) +{ + size_t bytecount = 0; + size_t i; + char *dst; + + for(i = 0; src[i]; i++) + if(src[i] == '"' || src[i] == '\\') + bytecount++; + + bytecount += i; + dst = malloc(bytecount + 1); + if(!dst) + return NULL; + + for(i = 0; *src; src++) { + if(*src == '"' || *src == '\\') + dst[i++] = '\\'; + dst[i++] = *src; + } + + dst[i] = '\0'; + return dst; +} + +/* Check if header matches. */ +static char *match_header(struct curl_slist *hdr, const char *lbl, size_t len) +{ + char *value = NULL; + + if(strncasecompare(hdr->data, lbl, len) && hdr->data[len] == ':') + for(value = hdr->data + len + 1; *value == ' '; value++) + ; + return value; +} + +/* Get a header from an slist. */ +static char *search_header(struct curl_slist *hdrlist, const char *hdr) +{ + size_t len = strlen(hdr); + char *value = NULL; + + for(; !value && hdrlist; hdrlist = hdrlist->next) + value = match_header(hdrlist, hdr, len); + + return value; +} + +static char *strippath(const char *fullfile) +{ + char *filename; + char *base; + filename = strdup(fullfile); /* duplicate since basename() may ruin the + buffer it works on */ + if(!filename) + return NULL; + base = strdup(basename(filename)); + + free(filename); /* free temporary buffer */ + + return base; /* returns an allocated string or NULL ! */ +} + +/* Initialize data encoder state. */ +static void cleanup_encoder_state(mime_encoder_state *p) +{ + p->pos = 0; + p->bufbeg = 0; + p->bufend = 0; +} + + +/* Dummy encoder. This is used for 8bit and binary content encodings. */ +static size_t encoder_nop_read(char *buffer, size_t size, bool ateof, + curl_mimepart *part) +{ + mime_encoder_state *st = &part->encstate; + size_t insize = st->bufend - st->bufbeg; + + (void) ateof; + + if(size > insize) + size = insize; + if(size) + memcpy(buffer, st->buf, size); + st->bufbeg += size; + return size; +} + +static curl_off_t encoder_nop_size(curl_mimepart *part) +{ + return part->datasize; +} + + +/* 7bit encoder: the encoder is just a data validity check. */ +static size_t encoder_7bit_read(char *buffer, size_t size, bool ateof, + curl_mimepart *part) +{ + mime_encoder_state *st = &part->encstate; + size_t cursize = st->bufend - st->bufbeg; + + (void) ateof; + + if(size > cursize) + size = cursize; + + for(cursize = 0; cursize < size; cursize++) { + *buffer = st->buf[st->bufbeg]; + if(*buffer++ & 0x80) + return cursize? cursize: READ_ERROR; + st->bufbeg++; + } + + return cursize; +} + + +/* Base64 content encoder. */ +static size_t encoder_base64_read(char *buffer, size_t size, bool ateof, + curl_mimepart *part) +{ + mime_encoder_state *st = &part->encstate; + size_t cursize = 0; + int i; + char *ptr = buffer; + + while(st->bufbeg < st->bufend) { + /* Line full ? */ + if(st->pos > MAX_ENCODED_LINE_LENGTH - 4) { + /* Yes, we need 2 characters for CRLF. */ + if(size < 2) + break; + *ptr++ = '\r'; + *ptr++ = '\n'; + st->pos = 0; + cursize += 2; + size -= 2; + } + + /* Be sure there is enough space and input data for a base64 group. */ + if(size < 4 || st->bufend - st->bufbeg < 3) + break; + + /* Encode three bytes as four characters. */ + i = st->buf[st->bufbeg++] & 0xFF; + i = (i << 8) | (st->buf[st->bufbeg++] & 0xFF); + i = (i << 8) | (st->buf[st->bufbeg++] & 0xFF); + *ptr++ = base64[(i >> 18) & 0x3F]; + *ptr++ = base64[(i >> 12) & 0x3F]; + *ptr++ = base64[(i >> 6) & 0x3F]; + *ptr++ = base64[i & 0x3F]; + cursize += 4; + st->pos += 4; + size -= 4; + } + + /* If at eof, we have to flush the buffered data. */ + if(ateof && size >= 4) { + /* Buffered data size can only be 0, 1 or 2. */ + ptr[2] = ptr[3] = '='; + i = 0; + switch(st->bufend - st->bufbeg) { + case 2: + i = (st->buf[st->bufbeg + 1] & 0xFF) << 8; + /* FALLTHROUGH */ + case 1: + i |= (st->buf[st->bufbeg] & 0xFF) << 16; + ptr[0] = base64[(i >> 18) & 0x3F]; + ptr[1] = base64[(i >> 12) & 0x3F]; + if(++st->bufbeg != st->bufend) { + ptr[2] = base64[(i >> 6) & 0x3F]; + st->bufbeg++; + } + cursize += 4; + st->pos += 4; + break; + } + } + +#ifdef CURL_DOES_CONVERSIONS + /* This is now textual data, Convert character codes. */ + if(part->easy && cursize) { + CURLcode result = Curl_convert_to_network(part->easy, buffer, cursize); + if(result) + return READ_ERROR; + } +#endif + + return cursize; +} + +static curl_off_t encoder_base64_size(curl_mimepart *part) +{ + curl_off_t size = part->datasize; + + if(size <= 0) + return size; /* Unknown size or no data. */ + + /* Compute base64 character count. */ + size = 4 * (1 + (size - 1) / 3); + + /* Effective character count must include CRLFs. */ + return size + 2 * ((size - 1) / MAX_ENCODED_LINE_LENGTH); +} + + +/* Quoted-printable lookahead. + * + * Check if a CRLF or end of data is in input buffer at current position + n. + * Return -1 if more data needed, 1 if CRLF or end of data, else 0. + */ +static int qp_lookahead_eol(mime_encoder_state *st, int ateof, size_t n) +{ + n += st->bufbeg; + if(n >= st->bufend && ateof) + return 1; + if(n + 2 > st->bufend) + return ateof? 0: -1; + if(qp_class[st->buf[n] & 0xFF] == QP_CR && + qp_class[st->buf[n + 1] & 0xFF] == QP_LF) + return 1; + return 0; +} + +/* Quoted-printable encoder. */ +static size_t encoder_qp_read(char *buffer, size_t size, bool ateof, + curl_mimepart *part) +{ + mime_encoder_state *st = &part->encstate; + char *ptr = buffer; + size_t cursize = 0; + int softlinebreak; + char buf[4]; + + /* On all platforms, input is supposed to be ASCII compatible: for this + reason, we use hexadecimal ASCII codes in this function rather than + character constants that can be interpreted as non-ascii on some + platforms. Preserve ASCII encoding on output too. */ + while(st->bufbeg < st->bufend) { + size_t len = 1; + size_t consumed = 1; + int i = st->buf[st->bufbeg]; + buf[0] = (char) i; + buf[1] = aschex[(i >> 4) & 0xF]; + buf[2] = aschex[i & 0xF]; + + switch(qp_class[st->buf[st->bufbeg] & 0xFF]) { + case QP_OK: /* Not a special character. */ + break; + case QP_SP: /* Space or tab. */ + /* Spacing must be escaped if followed by CRLF. */ + switch(qp_lookahead_eol(st, ateof, 1)) { + case -1: /* More input data needed. */ + return cursize; + case 0: /* No encoding needed. */ + break; + default: /* CRLF after space or tab. */ + buf[0] = '\x3D'; /* '=' */ + len = 3; + break; + } + break; + case QP_CR: /* Carriage return. */ + /* If followed by a line-feed, output the CRLF pair. + Else escape it. */ + switch(qp_lookahead_eol(st, ateof, 0)) { + case -1: /* Need more data. */ + return cursize; + case 1: /* CRLF found. */ + buf[len++] = '\x0A'; /* Append '\n'. */ + consumed = 2; + break; + default: /* Not followed by LF: escape. */ + buf[0] = '\x3D'; /* '=' */ + len = 3; + break; + } + break; + default: /* Character must be escaped. */ + buf[0] = '\x3D'; /* '=' */ + len = 3; + break; + } + + /* Be sure the encoded character fits within maximum line length. */ + if(buf[len - 1] != '\x0A') { /* '\n' */ + softlinebreak = st->pos + len > MAX_ENCODED_LINE_LENGTH; + if(!softlinebreak && st->pos + len == MAX_ENCODED_LINE_LENGTH) { + /* We may use the current line only if end of data or followed by + a CRLF. */ + switch(qp_lookahead_eol(st, ateof, consumed)) { + case -1: /* Need more data. */ + return cursize; + break; + case 0: /* Not followed by a CRLF. */ + softlinebreak = 1; + break; + } + } + if(softlinebreak) { + strcpy(buf, "\x3D\x0D\x0A"); /* "=\r\n" */ + len = 3; + consumed = 0; + } + } + + /* If the output buffer would overflow, do not store. */ + if(len > size) + break; + + /* Append to output buffer. */ + memcpy(ptr, buf, len); + cursize += len; + ptr += len; + size -= len; + st->pos += len; + if(buf[len - 1] == '\x0A') /* '\n' */ + st->pos = 0; + st->bufbeg += consumed; + } + + return cursize; +} + +static curl_off_t encoder_qp_size(curl_mimepart *part) +{ + /* Determining the size can only be done by reading the data: unless the + data size is 0, we return it as unknown (-1). */ + return part->datasize? -1: 0; +} + + +/* In-memory data callbacks. */ +/* Argument is a pointer to the mime part. */ +static size_t mime_mem_read(char *buffer, size_t size, size_t nitems, + void *instream) +{ + curl_mimepart *part = (curl_mimepart *) instream; + size_t sz = (size_t) part->datasize - part->state.offset; + (void) size; /* Always 1.*/ + + if(sz > nitems) + sz = nitems; + + if(sz) + memcpy(buffer, (char *) &part->data[part->state.offset], sz); + + part->state.offset += sz; + return sz; +} + +static int mime_mem_seek(void *instream, curl_off_t offset, int whence) +{ + curl_mimepart *part = (curl_mimepart *) instream; + + switch(whence) { + case SEEK_CUR: + offset += part->state.offset; + break; + case SEEK_END: + offset += part->datasize; + break; + } + + if(offset < 0 || offset > part->datasize) + return CURL_SEEKFUNC_FAIL; + + part->state.offset = (size_t) offset; + return CURL_SEEKFUNC_OK; +} + +static void mime_mem_free(void *ptr) +{ + Curl_safefree(((curl_mimepart *) ptr)->data); +} + + +/* Named file callbacks. */ +/* Argument is a pointer to the mime part. */ +static int mime_open_file(curl_mimepart * part) +{ + /* Open a MIMEKIND_FILE part. */ + + if(part->fp) + return 0; + part->fp = fopen_read(part->data, "rb"); + return part->fp? 0: -1; +} + +static size_t mime_file_read(char *buffer, size_t size, size_t nitems, + void *instream) +{ + curl_mimepart *part = (curl_mimepart *) instream; + + if(mime_open_file(part)) + return READ_ERROR; + + return fread(buffer, size, nitems, part->fp); +} + +static int mime_file_seek(void *instream, curl_off_t offset, int whence) +{ + curl_mimepart *part = (curl_mimepart *) instream; + + if(whence == SEEK_SET && !offset && !part->fp) + return CURL_SEEKFUNC_OK; /* Not open: implicitly already at BOF. */ + + if(mime_open_file(part)) + return CURL_SEEKFUNC_FAIL; + + return fseek(part->fp, (long) offset, whence)? + CURL_SEEKFUNC_CANTSEEK: CURL_SEEKFUNC_OK; +} + +static void mime_file_free(void *ptr) +{ + curl_mimepart *part = (curl_mimepart *) ptr; + + if(part->fp) { + fclose(part->fp); + part->fp = NULL; + } + Curl_safefree(part->data); + part->data = NULL; +} + + +/* Subparts callbacks. */ +/* Argument is a pointer to the mime structure. */ + +/* Readback a byte string segment. */ +static size_t readback_bytes(mime_state *state, + char *buffer, size_t bufsize, + const char *bytes, size_t numbytes, + const char *trail) +{ + size_t sz; + + if(numbytes > state->offset) { + sz = numbytes - state->offset; + bytes += state->offset; + } + else { + size_t tsz = strlen(trail); + + sz = state->offset - numbytes; + if(sz >= tsz) + return 0; + bytes = trail + sz; + sz = tsz - sz; + } + + if(sz > bufsize) + sz = bufsize; + + memcpy(buffer, bytes, sz); + state->offset += sz; + return sz; +} + +/* Read a non-encoded part content. */ +static size_t read_part_content(curl_mimepart *part, + char *buffer, size_t bufsize) +{ + size_t sz = 0; + + if(part->readfunc) + sz = part->readfunc(buffer, 1, bufsize, part->arg); + return sz; +} + +/* Read and encode part content. */ +static size_t read_encoded_part_content(curl_mimepart *part, + char *buffer, size_t bufsize) +{ + mime_encoder_state *st = &part->encstate; + size_t cursize = 0; + size_t sz; + bool ateof = FALSE; + + while(bufsize) { + if(st->bufbeg < st->bufend || ateof) { + /* Encode buffered data. */ + sz = part->encoder->encodefunc(buffer, bufsize, ateof, part); + switch(sz) { + case 0: + if(ateof) + return cursize; + break; + case CURL_READFUNC_ABORT: + case CURL_READFUNC_PAUSE: + case READ_ERROR: + return cursize? cursize: sz; + default: + cursize += sz; + buffer += sz; + bufsize -= sz; + continue; + } + } + + /* We need more data in input buffer. */ + if(st->bufbeg) { + size_t len = st->bufend - st->bufbeg; + + if(len) + memmove(st->buf, st->buf + st->bufbeg, len); + st->bufbeg = 0; + st->bufend = len; + } + if(st->bufend >= sizeof(st->buf)) + return cursize? cursize: READ_ERROR; /* Buffer full. */ + sz = read_part_content(part, st->buf + st->bufend, + sizeof(st->buf) - st->bufend); + switch(sz) { + case 0: + ateof = TRUE; + break; + case CURL_READFUNC_ABORT: + case CURL_READFUNC_PAUSE: + case READ_ERROR: + return cursize? cursize: sz; + default: + st->bufend += sz; + break; + } + } + + return cursize; +} + +/* Readback a mime part. */ +static size_t readback_part(curl_mimepart *part, + char *buffer, size_t bufsize) +{ + size_t cursize = 0; +#ifdef CURL_DOES_CONVERSIONS + char *convbuf = buffer; +#endif + + /* Readback from part. */ + + while(bufsize) { + size_t sz = 0; + struct curl_slist *hdr = (struct curl_slist *) part->state.ptr; + switch(part->state.state) { + case MIMESTATE_BEGIN: + mimesetstate(&part->state, + (part->flags & MIME_BODY_ONLY)? + MIMESTATE_BODY: MIMESTATE_CURLHEADERS, + part->curlheaders); + break; + case MIMESTATE_USERHEADERS: + if(!hdr) { + mimesetstate(&part->state, MIMESTATE_EOH, NULL); + break; + } + if(match_header(hdr, "Content-Type", 12)) { + mimesetstate(&part->state, MIMESTATE_USERHEADERS, hdr->next); + break; + } + /* FALLTHROUGH */ + case MIMESTATE_CURLHEADERS: + if(!hdr) + mimesetstate(&part->state, MIMESTATE_USERHEADERS, part->userheaders); + else { + sz = readback_bytes(&part->state, buffer, bufsize, + hdr->data, strlen(hdr->data), "\r\n"); + if(!sz) + mimesetstate(&part->state, part->state.state, hdr->next); + } + break; + case MIMESTATE_EOH: + sz = readback_bytes(&part->state, buffer, bufsize, "\r\n", 2, ""); + if(!sz) + mimesetstate(&part->state, MIMESTATE_BODY, NULL); + break; + case MIMESTATE_BODY: +#ifdef CURL_DOES_CONVERSIONS + if(part->easy && convbuf < buffer) { + CURLcode result = Curl_convert_to_network(part->easy, convbuf, + buffer - convbuf); + if(result) + return READ_ERROR; + convbuf = buffer; + } +#endif + cleanup_encoder_state(&part->encstate); + mimesetstate(&part->state, MIMESTATE_CONTENT, NULL); + break; + case MIMESTATE_CONTENT: + if(part->encoder) + sz = read_encoded_part_content(part, buffer, bufsize); + else + sz = read_part_content(part, buffer, bufsize); + switch(sz) { + case 0: + mimesetstate(&part->state, MIMESTATE_END, NULL); + /* Try sparing open file descriptors. */ + if(part->kind == MIMEKIND_FILE && part->fp) { + fclose(part->fp); + part->fp = NULL; + } + /* FALLTHROUGH */ + case CURL_READFUNC_ABORT: + case CURL_READFUNC_PAUSE: + case READ_ERROR: + return cursize? cursize: sz; + } + break; + case MIMESTATE_END: + return cursize; + default: + break; /* Other values not in part state. */ + } + + /* Bump buffer and counters according to read size. */ + cursize += sz; + buffer += sz; + bufsize -= sz; + } + +#ifdef CURL_DOES_CONVERSIONS + if(part->easy && convbuf < buffer && + part->state.state < MIMESTATE_BODY) { + CURLcode result = Curl_convert_to_network(part->easy, convbuf, + buffer - convbuf); + if(result) + return READ_ERROR; + } +#endif + + return cursize; +} + +/* Readback from mime. */ +static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems, + void *instream) +{ + curl_mime *mime = (curl_mime *) instream; + size_t cursize = 0; +#ifdef CURL_DOES_CONVERSIONS + char *convbuf = buffer; +#endif + + (void) size; /* Always 1. */ + + while(nitems) { + size_t sz = 0; + curl_mimepart *part = mime->state.ptr; + switch(mime->state.state) { + case MIMESTATE_BEGIN: + case MIMESTATE_BODY: +#ifdef CURL_DOES_CONVERSIONS + convbuf = buffer; +#endif + mimesetstate(&mime->state, MIMESTATE_BOUNDARY1, mime->firstpart); + /* The first boundary always follows the header termination empty line, + so is always preceded by a CRLK. We can then spare 2 characters + by skipping the leading CRLF in boundary. */ + mime->state.offset += 2; + break; + case MIMESTATE_BOUNDARY1: + sz = readback_bytes(&mime->state, buffer, nitems, "\r\n--", 4, ""); + if(!sz) + mimesetstate(&mime->state, MIMESTATE_BOUNDARY2, part); + break; + case MIMESTATE_BOUNDARY2: + sz = readback_bytes(&mime->state, buffer, nitems, mime->boundary, + strlen(mime->boundary), part? "\r\n": "--\r\n"); + if(!sz) { +#ifdef CURL_DOES_CONVERSIONS + if(mime->easy && convbuf < buffer) { + CURLcode result = Curl_convert_to_network(mime->easy, convbuf, + buffer - convbuf); + if(result) + return READ_ERROR; + convbuf = buffer; + } +#endif + mimesetstate(&mime->state, MIMESTATE_CONTENT, part); + } + break; + case MIMESTATE_CONTENT: + if(!part) { + mimesetstate(&mime->state, MIMESTATE_END, NULL); + break; + } + sz = readback_part(part, buffer, nitems); + switch(sz) { + case CURL_READFUNC_ABORT: + case CURL_READFUNC_PAUSE: + case READ_ERROR: + return cursize? cursize: sz; + case 0: +#ifdef CURL_DOES_CONVERSIONS + convbuf = buffer; +#endif + mimesetstate(&mime->state, MIMESTATE_BOUNDARY1, part->nextpart); + break; + } + break; + case MIMESTATE_END: + return cursize; + default: + break; /* other values not used in mime state. */ + } + + /* Bump buffer and counters according to read size. */ + cursize += sz; + buffer += sz; + nitems -= sz; + } + +#ifdef CURL_DOES_CONVERSIONS + if(mime->easy && convbuf < buffer && + mime->state.state <= MIMESTATE_CONTENT) { + CURLcode result = Curl_convert_to_network(mime->easy, convbuf, + buffer - convbuf); + if(result) + return READ_ERROR; + } +#endif + + return cursize; +} + +static int mime_part_rewind(curl_mimepart *part) +{ + int res = CURL_SEEKFUNC_OK; + enum mimestate targetstate = MIMESTATE_BEGIN; + + if(part->flags & MIME_BODY_ONLY) + targetstate = MIMESTATE_BODY; + cleanup_encoder_state(&part->encstate); + if(part->state.state > targetstate) { + res = CURL_SEEKFUNC_CANTSEEK; + if(part->seekfunc) { + res = part->seekfunc(part->arg, (curl_off_t) 0, SEEK_SET); + switch(res) { + case CURL_SEEKFUNC_OK: + case CURL_SEEKFUNC_FAIL: + case CURL_SEEKFUNC_CANTSEEK: + break; + case -1: /* For fseek() error. */ + res = CURL_SEEKFUNC_CANTSEEK; + break; + default: + res = CURL_SEEKFUNC_FAIL; + break; + } + } + } + + if(res == CURL_SEEKFUNC_OK) + mimesetstate(&part->state, targetstate, NULL); + + return res; +} + +static int mime_subparts_seek(void *instream, curl_off_t offset, int whence) +{ + curl_mime *mime = (curl_mime *) instream; + curl_mimepart *part; + int result = CURL_SEEKFUNC_OK; + + if(whence != SEEK_SET || offset) + return CURL_SEEKFUNC_CANTSEEK; /* Only support full rewind. */ + + if(mime->state.state == MIMESTATE_BEGIN) + return CURL_SEEKFUNC_OK; /* Already rewound. */ + + for(part = mime->firstpart; part; part = part->nextpart) { + int res = mime_part_rewind(part); + if(res != CURL_SEEKFUNC_OK) + result = res; + } + + if(result == CURL_SEEKFUNC_OK) + mimesetstate(&mime->state, MIMESTATE_BEGIN, NULL); + + return result; +} + +/* Release part content. */ +static void cleanup_part_content(curl_mimepart *part) +{ + if(part->freefunc) + part->freefunc(part->arg); + + part->readfunc = NULL; + part->seekfunc = NULL; + part->freefunc = NULL; + part->arg = (void *) part; /* Defaults to part itself. */ + part->data = NULL; + part->fp = NULL; + part->datasize = (curl_off_t) 0; /* No size yet. */ + cleanup_encoder_state(&part->encstate); + part->kind = MIMEKIND_NONE; +} + +static void mime_subparts_free(void *ptr) +{ + curl_mime *mime = (curl_mime *) ptr; + + if(mime && mime->parent) { + mime->parent->freefunc = NULL; /* Be sure we won't be called again. */ + cleanup_part_content(mime->parent); /* Avoid dangling pointer in part. */ + } + curl_mime_free(mime); +} + +/* Do not free subparts: unbind them. This is used for the top level only. */ +static void mime_subparts_unbind(void *ptr) +{ + curl_mime *mime = (curl_mime *) ptr; + + if(mime && mime->parent) { + mime->parent->freefunc = NULL; /* Be sure we won't be called again. */ + cleanup_part_content(mime->parent); /* Avoid dangling pointer in part. */ + mime->parent = NULL; + } +} + + +void Curl_mime_cleanpart(curl_mimepart *part) +{ + cleanup_part_content(part); + curl_slist_free_all(part->curlheaders); + if(part->flags & MIME_USERHEADERS_OWNER) + curl_slist_free_all(part->userheaders); + Curl_safefree(part->mimetype); + Curl_safefree(part->name); + Curl_safefree(part->filename); + Curl_mime_initpart(part, part->easy); +} + +/* Recursively delete a mime handle and its parts. */ +void curl_mime_free(curl_mime *mime) +{ + curl_mimepart *part; + + if(mime) { + mime_subparts_unbind(mime); /* Be sure it's not referenced anymore. */ + while(mime->firstpart) { + part = mime->firstpart; + mime->firstpart = part->nextpart; + Curl_mime_cleanpart(part); + free(part); + } + free(mime); + } +} + +CURLcode Curl_mime_duppart(curl_mimepart *dst, const curl_mimepart *src) +{ + curl_mime *mime; + curl_mimepart *d; + const curl_mimepart *s; + CURLcode res = CURLE_OK; + + /* Duplicate content. */ + switch(src->kind) { + case MIMEKIND_NONE: + break; + case MIMEKIND_DATA: + res = curl_mime_data(dst, src->data, (size_t) src->datasize); + break; + case MIMEKIND_FILE: + res = curl_mime_filedata(dst, src->data); + /* Do not abort duplication if file is not readable. */ + if(res == CURLE_READ_ERROR) + res = CURLE_OK; + break; + case MIMEKIND_CALLBACK: + res = curl_mime_data_cb(dst, src->datasize, src->readfunc, + src->seekfunc, src->freefunc, src->arg); + break; + case MIMEKIND_MULTIPART: + /* No one knows about the cloned subparts, thus always attach ownership + to the part. */ + mime = curl_mime_init(dst->easy); + res = mime? curl_mime_subparts(dst, mime): CURLE_OUT_OF_MEMORY; + + /* Duplicate subparts. */ + for(s = ((curl_mime *) src->arg)->firstpart; !res && s; s = s->nextpart) { + d = curl_mime_addpart(mime); + res = d? Curl_mime_duppart(d, s): CURLE_OUT_OF_MEMORY; + } + break; + default: /* Invalid kind: should not occur. */ + res = CURLE_BAD_FUNCTION_ARGUMENT; /* Internal error? */ + break; + } + + /* Duplicate headers. */ + if(!res && src->userheaders) { + struct curl_slist *hdrs = Curl_slist_duplicate(src->userheaders); + + if(!hdrs) + res = CURLE_OUT_OF_MEMORY; + else { + /* No one but this procedure knows about the new header list, + so always take ownership. */ + res = curl_mime_headers(dst, hdrs, TRUE); + if(res) + curl_slist_free_all(hdrs); + } + } + + /* Duplicate other fields. */ + if(dst != NULL) + dst->encoder = src->encoder; + else + res = CURLE_WRITE_ERROR; + if(!res) + res = curl_mime_type(dst, src->mimetype); + if(!res) + res = curl_mime_name(dst, src->name); + if(!res) + res = curl_mime_filename(dst, src->filename); + + /* If an error occurred, rollback. */ + if(res && dst) + Curl_mime_cleanpart(dst); + + return res; +} + +/* + * Mime build functions. + */ + +/* Create a mime handle. */ +curl_mime *curl_mime_init(struct Curl_easy *easy) +{ + curl_mime *mime; + + mime = (curl_mime *) malloc(sizeof(*mime)); + + if(mime) { + mime->easy = easy; + mime->parent = NULL; + mime->firstpart = NULL; + mime->lastpart = NULL; + + memset(mime->boundary, '-', 24); + if(Curl_rand_hex(easy, (unsigned char *) &mime->boundary[24], + MIME_RAND_BOUNDARY_CHARS + 1)) { + /* failed to get random separator, bail out */ + free(mime); + return NULL; + } + mimesetstate(&mime->state, MIMESTATE_BEGIN, NULL); + } + + return mime; +} + +/* Initialize a mime part. */ +void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy) +{ + memset((char *) part, 0, sizeof(*part)); + part->easy = easy; + mimesetstate(&part->state, MIMESTATE_BEGIN, NULL); +} + +/* Create a mime part and append it to a mime handle's part list. */ +curl_mimepart *curl_mime_addpart(curl_mime *mime) +{ + curl_mimepart *part; + + if(!mime) + return NULL; + + part = (curl_mimepart *) malloc(sizeof(*part)); + + if(part) { + Curl_mime_initpart(part, mime->easy); + part->parent = mime; + + if(mime->lastpart) + mime->lastpart->nextpart = part; + else + mime->firstpart = part; + + mime->lastpart = part; + } + + return part; +} + +/* Set mime part name. */ +CURLcode curl_mime_name(curl_mimepart *part, const char *name) +{ + if(!part) + return CURLE_BAD_FUNCTION_ARGUMENT; + + Curl_safefree(part->name); + part->name = NULL; + + if(name) { + part->name = strdup(name); + if(!part->name) + return CURLE_OUT_OF_MEMORY; + } + + return CURLE_OK; +} + +/* Set mime part remote file name. */ +CURLcode curl_mime_filename(curl_mimepart *part, const char *filename) +{ + if(!part) + return CURLE_BAD_FUNCTION_ARGUMENT; + + Curl_safefree(part->filename); + part->filename = NULL; + + if(filename) { + part->filename = strdup(filename); + if(!part->filename) + return CURLE_OUT_OF_MEMORY; + } + + return CURLE_OK; +} + +/* Set mime part content from memory data. */ +CURLcode curl_mime_data(curl_mimepart *part, + const char *data, size_t datasize) +{ + if(!part) + return CURLE_BAD_FUNCTION_ARGUMENT; + + cleanup_part_content(part); + + if(data) { + if(datasize == CURL_ZERO_TERMINATED) + datasize = strlen(data); + + part->data = malloc(datasize + 1); + if(!part->data) + return CURLE_OUT_OF_MEMORY; + + part->datasize = datasize; + + if(datasize) + memcpy(part->data, data, datasize); + part->data[datasize] = '\0'; /* Set a nul terminator as sentinel. */ + + part->readfunc = mime_mem_read; + part->seekfunc = mime_mem_seek; + part->freefunc = mime_mem_free; + part->kind = MIMEKIND_DATA; + } + + return CURLE_OK; +} + +/* Set mime part content from named local file. */ +CURLcode curl_mime_filedata(curl_mimepart *part, const char *filename) +{ + CURLcode result = CURLE_OK; + + if(!part) + return CURLE_BAD_FUNCTION_ARGUMENT; + + cleanup_part_content(part); + + if(filename) { + char *base; + struct_stat sbuf; + + if(stat(filename, &sbuf) || access(filename, R_OK)) + result = CURLE_READ_ERROR; + + part->data = strdup(filename); + if(!part->data) + result = CURLE_OUT_OF_MEMORY; + + part->datasize = -1; + if(!result && S_ISREG(sbuf.st_mode)) { + part->datasize = filesize(filename, sbuf); + part->seekfunc = mime_file_seek; + } + + part->readfunc = mime_file_read; + part->freefunc = mime_file_free; + part->kind = MIMEKIND_FILE; + + /* As a side effect, set the filename to the current file's base name. + It is possible to withdraw this by explicitly calling + curl_mime_filename() with a NULL filename argument after the current + call. */ + base = strippath(filename); + if(!base) + result = CURLE_OUT_OF_MEMORY; + else { + CURLcode res = curl_mime_filename(part, base); + + if(res) + result = res; + free(base); + } + } + return result; +} + +/* Set mime part type. */ +CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype) +{ + if(!part) + return CURLE_BAD_FUNCTION_ARGUMENT; + + Curl_safefree(part->mimetype); + part->mimetype = NULL; + + if(mimetype) { + part->mimetype = strdup(mimetype); + if(!part->mimetype) + return CURLE_OUT_OF_MEMORY; + } + + return CURLE_OK; +} + +/* Set mime data transfer encoder. */ +CURLcode curl_mime_encoder(curl_mimepart *part, const char *encoding) +{ + CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT; + const mime_encoder *mep; + + if(!part) + return result; + + part->encoder = NULL; + + if(!encoding) + return CURLE_OK; /* Removing current encoder. */ + + for(mep = encoders; mep->name; mep++) + if(strcasecompare(encoding, mep->name)) { + part->encoder = mep; + result = CURLE_OK; + } + + return result; +} + +/* Set mime part headers. */ +CURLcode curl_mime_headers(curl_mimepart *part, + struct curl_slist *headers, int take_ownership) +{ + if(!part) + return CURLE_BAD_FUNCTION_ARGUMENT; + + if(part->flags & MIME_USERHEADERS_OWNER) { + if(part->userheaders != headers) /* Allow setting twice the same list. */ + curl_slist_free_all(part->userheaders); + part->flags &= ~MIME_USERHEADERS_OWNER; + } + part->userheaders = headers; + if(headers && take_ownership) + part->flags |= MIME_USERHEADERS_OWNER; + return CURLE_OK; +} + +/* Set mime part content from callback. */ +CURLcode curl_mime_data_cb(curl_mimepart *part, curl_off_t datasize, + curl_read_callback readfunc, + curl_seek_callback seekfunc, + curl_free_callback freefunc, void *arg) +{ + if(!part) + return CURLE_BAD_FUNCTION_ARGUMENT; + + cleanup_part_content(part); + + if(readfunc) { + part->readfunc = readfunc; + part->seekfunc = seekfunc; + part->freefunc = freefunc; + part->arg = arg; + part->datasize = datasize; + part->kind = MIMEKIND_CALLBACK; + } + + return CURLE_OK; +} + +/* Set mime part content from subparts. */ +CURLcode Curl_mime_set_subparts(curl_mimepart *part, + curl_mime *subparts, int take_ownership) +{ + curl_mime *root; + + if(!part) + return CURLE_BAD_FUNCTION_ARGUMENT; + + /* Accept setting twice the same subparts. */ + if(part->kind == MIMEKIND_MULTIPART && part->arg == subparts) + return CURLE_OK; + + cleanup_part_content(part); + + if(subparts) { + /* Must belong to the same data handle. */ + if(part->easy && subparts->easy && part->easy != subparts->easy) + return CURLE_BAD_FUNCTION_ARGUMENT; + + /* Should not have been attached already. */ + if(subparts->parent) + return CURLE_BAD_FUNCTION_ARGUMENT; + + /* Should not be the part's root. */ + root = part->parent; + if(root) { + while(root->parent && root->parent->parent) + root = root->parent->parent; + if(subparts == root) { + if(part->easy) + failf(part->easy, "Can't add itself as a subpart!"); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + } + + subparts->parent = part; + part->readfunc = mime_subparts_read; + part->seekfunc = mime_subparts_seek; + part->freefunc = take_ownership? mime_subparts_free: mime_subparts_unbind; + part->arg = subparts; + part->datasize = -1; + part->kind = MIMEKIND_MULTIPART; + } + + return CURLE_OK; +} + +CURLcode curl_mime_subparts(curl_mimepart *part, curl_mime *subparts) +{ + return Curl_mime_set_subparts(part, subparts, TRUE); +} + + +/* Readback from top mime. */ +/* Argument is the dummy top part. */ +size_t Curl_mime_read(char *buffer, size_t size, size_t nitems, void *instream) +{ + curl_mimepart *part = (curl_mimepart *) instream; + + (void) size; /* Always 1. */ + return readback_part(part, buffer, nitems); +} + +/* Rewind mime stream. */ +CURLcode Curl_mime_rewind(curl_mimepart *part) +{ + return mime_part_rewind(part) == CURL_SEEKFUNC_OK? + CURLE_OK: CURLE_SEND_FAIL_REWIND; +} + +/* Compute header list size. */ +static size_t slist_size(struct curl_slist *s, + size_t overhead, const char *skip) +{ + size_t size = 0; + size_t skiplen = skip? strlen(skip): 0; + + for(; s; s = s->next) + if(!skip || !match_header(s, skip, skiplen)) + size += strlen(s->data) + overhead; + return size; +} + +/* Get/compute multipart size. */ +static curl_off_t multipart_size(curl_mime *mime) +{ + curl_off_t size; + size_t boundarysize; + curl_mimepart *part; + + if(!mime) + return 0; /* Not present -> empty. */ + + boundarysize = 4 + strlen(mime->boundary) + 2; + size = boundarysize; /* Final boundary - CRLF after headers. */ + + for(part = mime->firstpart; part; part = part->nextpart) { + curl_off_t sz = Curl_mime_size(part); + + if(sz < 0) + size = sz; + + if(size >= 0) + size += boundarysize + sz; + } + + return size; +} + +/* Get/compute mime size. */ +curl_off_t Curl_mime_size(curl_mimepart *part) +{ + curl_off_t size; + + if(part->kind == MIMEKIND_MULTIPART) + part->datasize = multipart_size(part->arg); + + size = part->datasize; + + if(part->encoder) + size = part->encoder->sizefunc(part); + + if(size >= 0 && !(part->flags & MIME_BODY_ONLY)) { + /* Compute total part size. */ + size += slist_size(part->curlheaders, 2, NULL); + size += slist_size(part->userheaders, 2, "Content-Type"); + size += 2; /* CRLF after headers. */ + } + return size; +} + +/* Add a header. */ +/* VARARGS2 */ +CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...) +{ + struct curl_slist *hdr = NULL; + char *s = NULL; + va_list ap; + + va_start(ap, fmt); + s = curl_mvaprintf(fmt, ap); + va_end(ap); + + if(s) { + hdr = Curl_slist_append_nodup(*slp, s); + if(hdr) + *slp = hdr; + else + free(s); + } + + return hdr? CURLE_OK: CURLE_OUT_OF_MEMORY; +} + +/* Add a content type header. */ +static CURLcode add_content_type(struct curl_slist **slp, + const char *type, const char *boundary) +{ + return Curl_mime_add_header(slp, "Content-Type: %s%s%s", type, + boundary? "; boundary=": "", + boundary? boundary: ""); +} + +const char *Curl_mime_contenttype(const char *filename) +{ + /* + * If no content type was specified, we scan through a few well-known + * extensions and pick the first we match! + */ + struct ContentType { + const char *extension; + const char *type; + }; + static const struct ContentType ctts[] = { + {".gif", "image/gif"}, + {".jpg", "image/jpeg"}, + {".jpeg", "image/jpeg"}, + {".png", "image/png"}, + {".svg", "image/svg+xml"}, + {".txt", "text/plain"}, + {".htm", "text/html"}, + {".html", "text/html"}, + {".pdf", "application/pdf"}, + {".xml", "application/xml"} + }; + + if(filename) { + size_t len1 = strlen(filename); + const char *nameend = filename + len1; + unsigned int i; + + for(i = 0; i < sizeof(ctts) / sizeof(ctts[0]); i++) { + size_t len2 = strlen(ctts[i].extension); + + if(len1 >= len2 && strcasecompare(nameend - len2, ctts[i].extension)) + return ctts[i].type; + } + } + return NULL; +} + +CURLcode Curl_mime_prepare_headers(curl_mimepart *part, + const char *contenttype, + const char *disposition, + enum mimestrategy strategy) +{ + curl_mime *mime = NULL; + const char *boundary = NULL; + char *customct; + const char *cte = NULL; + CURLcode ret = CURLE_OK; + + /* Get rid of previously prepared headers. */ + curl_slist_free_all(part->curlheaders); + part->curlheaders = NULL; + + /* Be sure we won't access old headers later. */ + if(part->state.state == MIMESTATE_CURLHEADERS) + mimesetstate(&part->state, MIMESTATE_CURLHEADERS, NULL); + + /* Check if content type is specified. */ + customct = part->mimetype; + if(!customct) + customct = search_header(part->userheaders, "Content-Type"); + if(customct) + contenttype = customct; + + /* If content type is not specified, try to determine it. */ + if(!contenttype) { + switch(part->kind) { + case MIMEKIND_MULTIPART: + contenttype = MULTIPART_CONTENTTYPE_DEFAULT; + break; + case MIMEKIND_FILE: + contenttype = Curl_mime_contenttype(part->filename); + if(!contenttype) + contenttype = Curl_mime_contenttype(part->data); + if(!contenttype && part->filename) + contenttype = FILE_CONTENTTYPE_DEFAULT; + break; + default: + contenttype = Curl_mime_contenttype(part->filename); + break; + } + } + + if(part->kind == MIMEKIND_MULTIPART) { + mime = (curl_mime *) part->arg; + if(mime) + boundary = mime->boundary; + } + else if(contenttype && !customct && + strcasecompare(contenttype, "text/plain")) + if(strategy == MIMESTRATEGY_MAIL || !part->filename) + contenttype = NULL; + + /* Issue content-disposition header only if not already set by caller. */ + if(!search_header(part->userheaders, "Content-Disposition")) { + if(!disposition) + if(part->filename || part->name || + (contenttype && !strncasecompare(contenttype, "multipart/", 10))) + disposition = DISPOSITION_DEFAULT; + if(disposition && curl_strequal(disposition, "attachment") && + !part->name && !part->filename) + disposition = NULL; + if(disposition) { + char *name = NULL; + char *filename = NULL; + + if(part->name) { + name = escape_string(part->name); + if(!name) + ret = CURLE_OUT_OF_MEMORY; + } + if(!ret && part->filename) { + filename = escape_string(part->filename); + if(!filename) + ret = CURLE_OUT_OF_MEMORY; + } + if(!ret) + ret = Curl_mime_add_header(&part->curlheaders, + "Content-Disposition: %s%s%s%s%s%s%s", + disposition, + name? "; name=\"": "", + name? name: "", + name? "\"": "", + filename? "; filename=\"": "", + filename? filename: "", + filename? "\"": ""); + Curl_safefree(name); + Curl_safefree(filename); + if(ret) + return ret; + } + } + + /* Issue Content-Type header. */ + if(contenttype) { + ret = add_content_type(&part->curlheaders, contenttype, boundary); + if(ret) + return ret; + } + + /* Content-Transfer-Encoding header. */ + if(!search_header(part->userheaders, "Content-Transfer-Encoding")) { + if(part->encoder) + cte = part->encoder->name; + else if(contenttype && strategy == MIMESTRATEGY_MAIL && + part->kind != MIMEKIND_MULTIPART) + cte = "8bit"; + if(cte) { + ret = Curl_mime_add_header(&part->curlheaders, + "Content-Transfer-Encoding: %s", cte); + if(ret) + return ret; + } + } + + /* If we were reading curl-generated headers, restart with new ones (this + should not occur). */ + if(part->state.state == MIMESTATE_CURLHEADERS) + mimesetstate(&part->state, MIMESTATE_CURLHEADERS, part->curlheaders); + + /* Process subparts. */ + if(part->kind == MIMEKIND_MULTIPART && mime) { + curl_mimepart *subpart; + + disposition = NULL; + if(strcasecompare(contenttype, "multipart/form-data")) + disposition = "form-data"; + for(subpart = mime->firstpart; subpart; subpart = subpart->nextpart) { + ret = Curl_mime_prepare_headers(subpart, NULL, disposition, strategy); + if(ret) + return ret; + } + } + return ret; +} + +#else /* !CURL_DISABLE_HTTP || !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP */ + +/* Mime not compiled in: define stubs for externally-referenced functions. */ +curl_mime *curl_mime_init(CURL *easy) +{ + (void) easy; + return NULL; +} + +void curl_mime_free(curl_mime *mime) +{ + (void) mime; +} + +curl_mimepart *curl_mime_addpart(curl_mime *mime) +{ + (void) mime; + return NULL; +} + +CURLcode curl_mime_name(curl_mimepart *part, const char *name) +{ + (void) part; + (void) name; + return CURLE_NOT_BUILT_IN; +} + +CURLcode curl_mime_filename(curl_mimepart *part, const char *filename) +{ + (void) part; + (void) filename; + return CURLE_NOT_BUILT_IN; +} + +CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype) +{ + (void) part; + (void) mimetype; + return CURLE_NOT_BUILT_IN; +} + +CURLcode curl_mime_encoder(curl_mimepart *part, const char *encoding) +{ + (void) part; + (void) encoding; + return CURLE_NOT_BUILT_IN; +} + +CURLcode curl_mime_data(curl_mimepart *part, + const char *data, size_t datasize) +{ + (void) part; + (void) data; + (void) datasize; + return CURLE_NOT_BUILT_IN; +} + +CURLcode curl_mime_filedata(curl_mimepart *part, const char *filename) +{ + (void) part; + (void) filename; + return CURLE_NOT_BUILT_IN; +} + +CURLcode curl_mime_data_cb(curl_mimepart *part, + curl_off_t datasize, + curl_read_callback readfunc, + curl_seek_callback seekfunc, + curl_free_callback freefunc, + void *arg) +{ + (void) part; + (void) datasize; + (void) readfunc; + (void) seekfunc; + (void) freefunc; + (void) arg; + return CURLE_NOT_BUILT_IN; +} + +CURLcode curl_mime_subparts(curl_mimepart *part, curl_mime *subparts) +{ + (void) part; + (void) subparts; + return CURLE_NOT_BUILT_IN; +} + +CURLcode curl_mime_headers(curl_mimepart *part, + struct curl_slist *headers, int take_ownership) +{ + (void) part; + (void) headers; + (void) take_ownership; + return CURLE_NOT_BUILT_IN; +} + +#endif /* if disabled */ diff --git a/dependencies/cmcurl/lib/mime.h b/dependencies/cmcurl/lib/mime.h new file mode 100644 index 0000000..4c9a5fb --- /dev/null +++ b/dependencies/cmcurl/lib/mime.h @@ -0,0 +1,164 @@ +#ifndef HEADER_CURL_MIME_H +#define HEADER_CURL_MIME_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#define MIME_RAND_BOUNDARY_CHARS 16 /* Nb. of random boundary chars. */ +#define MAX_ENCODED_LINE_LENGTH 76 /* Maximum encoded line length. */ +#define ENCODING_BUFFER_SIZE 256 /* Encoding temp buffers size. */ + +/* Part flags. */ +#define MIME_USERHEADERS_OWNER (1 << 0) +#define MIME_BODY_ONLY (1 << 1) + +#define FILE_CONTENTTYPE_DEFAULT "application/octet-stream" +#define MULTIPART_CONTENTTYPE_DEFAULT "multipart/mixed" +#define DISPOSITION_DEFAULT "attachment" + +/* Part source kinds. */ +enum mimekind { + MIMEKIND_NONE = 0, /* Part not set. */ + MIMEKIND_DATA, /* Allocated mime data. */ + MIMEKIND_FILE, /* Data from file. */ + MIMEKIND_CALLBACK, /* Data from `read' callback. */ + MIMEKIND_MULTIPART, /* Data is a mime subpart. */ + MIMEKIND_LAST +}; + +/* Readback state tokens. */ +enum mimestate { + MIMESTATE_BEGIN, /* Readback has not yet started. */ + MIMESTATE_CURLHEADERS, /* In curl-generated headers. */ + MIMESTATE_USERHEADERS, /* In caller's supplied headers. */ + MIMESTATE_EOH, /* End of headers. */ + MIMESTATE_BODY, /* Placeholder. */ + MIMESTATE_BOUNDARY1, /* In boundary prefix. */ + MIMESTATE_BOUNDARY2, /* In boundary. */ + MIMESTATE_CONTENT, /* In content. */ + MIMESTATE_END, /* End of part reached. */ + MIMESTATE_LAST +}; + +/* Mime headers strategies. */ +enum mimestrategy { + MIMESTRATEGY_MAIL, /* Mime mail. */ + MIMESTRATEGY_FORM, /* HTTP post form. */ + MIMESTRATEGY_LAST +}; + +/* Content transfer encoder. */ +typedef struct { + const char * name; /* Encoding name. */ + size_t (*encodefunc)(char *buffer, size_t size, bool ateof, + curl_mimepart *part); /* Encoded read. */ + curl_off_t (*sizefunc)(curl_mimepart *part); /* Encoded size. */ +} mime_encoder; + +/* Content transfer encoder state. */ +typedef struct { + size_t pos; /* Position on output line. */ + size_t bufbeg; /* Next data index in input buffer. */ + size_t bufend; /* First unused byte index in input buffer. */ + char buf[ENCODING_BUFFER_SIZE]; /* Input buffer. */ +} mime_encoder_state; + +/* Mime readback state. */ +typedef struct { + enum mimestate state; /* Current state token. */ + void *ptr; /* State-dependent pointer. */ + size_t offset; /* State-dependent offset. */ +} mime_state; + +/* minimum buffer size for the boundary string */ +#define MIME_BOUNDARY_LEN (24 + MIME_RAND_BOUNDARY_CHARS + 1) + +/* A mime multipart. */ +struct curl_mime_s { + struct Curl_easy *easy; /* The associated easy handle. */ + curl_mimepart *parent; /* Parent part. */ + curl_mimepart *firstpart; /* First part. */ + curl_mimepart *lastpart; /* Last part. */ + char boundary[MIME_BOUNDARY_LEN]; /* The part boundary. */ + mime_state state; /* Current readback state. */ +}; + +/* A mime part. */ +struct curl_mimepart_s { + struct Curl_easy *easy; /* The associated easy handle. */ + curl_mime *parent; /* Parent mime structure. */ + curl_mimepart *nextpart; /* Forward linked list. */ + enum mimekind kind; /* The part kind. */ + char *data; /* Memory data or file name. */ + curl_read_callback readfunc; /* Read function. */ + curl_seek_callback seekfunc; /* Seek function. */ + curl_free_callback freefunc; /* Argument free function. */ + void *arg; /* Argument to callback functions. */ + FILE *fp; /* File pointer. */ + struct curl_slist *curlheaders; /* Part headers. */ + struct curl_slist *userheaders; /* Part headers. */ + char *mimetype; /* Part mime type. */ + char *filename; /* Remote file name. */ + char *name; /* Data name. */ + curl_off_t datasize; /* Expected data size. */ + unsigned int flags; /* Flags. */ + mime_state state; /* Current readback state. */ + const mime_encoder *encoder; /* Content data encoder. */ + mime_encoder_state encstate; /* Data encoder state. */ +}; + +#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)) || \ + !defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP) + +/* Prototypes. */ +void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy); +void Curl_mime_cleanpart(curl_mimepart *part); +CURLcode Curl_mime_duppart(curl_mimepart *dst, const curl_mimepart *src); +CURLcode Curl_mime_set_subparts(curl_mimepart *part, + curl_mime *subparts, int take_ownership); +CURLcode Curl_mime_prepare_headers(curl_mimepart *part, + const char *contenttype, + const char *disposition, + enum mimestrategy strategy); +curl_off_t Curl_mime_size(curl_mimepart *part); +size_t Curl_mime_read(char *buffer, size_t size, size_t nitems, + void *instream); +CURLcode Curl_mime_rewind(curl_mimepart *part); +CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...); +const char *Curl_mime_contenttype(const char *filename); + +#else +/* if disabled */ +#define Curl_mime_initpart(x,y) +#define Curl_mime_cleanpart(x) +#define Curl_mime_duppart(x,y) CURLE_OK /* Nothing to duplicate. Succeed */ +#define Curl_mime_set_subparts(a,b,c) CURLE_NOT_BUILT_IN +#define Curl_mime_prepare_headers(a,b,c,d) CURLE_NOT_BUILT_IN +#define Curl_mime_size(x) (curl_off_t) -1 +#define Curl_mime_read NULL +#define Curl_mime_rewind(x) ((void)x, CURLE_NOT_BUILT_IN) +#define Curl_mime_add_header(x,y,...) CURLE_NOT_BUILT_IN +#endif + + +#endif /* HEADER_CURL_MIME_H */ diff --git a/dependencies/cmcurl/lib/mprintf.c b/dependencies/cmcurl/lib/mprintf.c new file mode 100644 index 0000000..e190936 --- /dev/null +++ b/dependencies/cmcurl/lib/mprintf.c @@ -0,0 +1,1173 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1999 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * + * Purpose: + * A merge of Bjorn Reese's format() function and Daniel's dsprintf() + * 1.0. A full blooded printf() clone with full support for $ + * everywhere (parameters, widths and precisions) including variabled + * sized parameters (like doubles, long longs, long doubles and even + * void * in 64-bit architectures). + * + * Current restrictions: + * - Max 128 parameters + * - No 'long double' support. + * + * If you ever want truly portable and good *printf() clones, the project that + * took on from here is named 'Trio' and you find more details on the trio web + * page at https://daniel.haxx.se/projects/trio/ + */ + +#include "curl_setup.h" +#include + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * If SIZEOF_SIZE_T has not been defined, default to the size of long. + */ + +#ifdef HAVE_LONGLONG +# define LONG_LONG_TYPE long long +# define HAVE_LONG_LONG_TYPE +#else +# if defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) +# define LONG_LONG_TYPE __int64 +# define HAVE_LONG_LONG_TYPE +# else +# undef LONG_LONG_TYPE +# undef HAVE_LONG_LONG_TYPE +# endif +#endif + +/* + * Non-ANSI integer extensions + */ + +#if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x520)) || \ + (defined(__WATCOMC__) && defined(__386__)) || \ + (defined(__POCC__) && defined(_MSC_VER)) || \ + (defined(_WIN32_WCE)) || \ + (defined(__MINGW32__)) || \ + (defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)) +# define MP_HAVE_INT_EXTENSIONS +#endif + +/* + * Max integer data types that mprintf.c is capable + */ + +#ifdef HAVE_LONG_LONG_TYPE +# define mp_intmax_t LONG_LONG_TYPE +# define mp_uintmax_t unsigned LONG_LONG_TYPE +#else +# define mp_intmax_t long +# define mp_uintmax_t unsigned long +#endif + +#define BUFFSIZE 326 /* buffer for long-to-str and float-to-str calcs, should + fit negative DBL_MAX (317 letters) */ +#define MAX_PARAMETERS 128 /* lame static limit */ + +#ifdef __AMIGA__ +# undef FORMAT_INT +#endif + +/* Lower-case digits. */ +static const char lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + +/* Upper-case digits. */ +static const char upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +#define OUTCHAR(x) \ + do{ \ + if(stream((unsigned char)(x), (FILE *)data) != -1) \ + done++; \ + else \ + return done; /* return immediately on failure */ \ + } WHILE_FALSE + +/* Data type to read from the arglist */ +typedef enum { + FORMAT_UNKNOWN = 0, + FORMAT_STRING, + FORMAT_PTR, + FORMAT_INT, + FORMAT_INTPTR, + FORMAT_LONG, + FORMAT_LONGLONG, + FORMAT_DOUBLE, + FORMAT_LONGDOUBLE, + FORMAT_WIDTH /* For internal use */ +} FormatType; + +/* conversion and display flags */ +enum { + FLAGS_NEW = 0, + FLAGS_SPACE = 1<<0, + FLAGS_SHOWSIGN = 1<<1, + FLAGS_LEFT = 1<<2, + FLAGS_ALT = 1<<3, + FLAGS_SHORT = 1<<4, + FLAGS_LONG = 1<<5, + FLAGS_LONGLONG = 1<<6, + FLAGS_LONGDOUBLE = 1<<7, + FLAGS_PAD_NIL = 1<<8, + FLAGS_UNSIGNED = 1<<9, + FLAGS_OCTAL = 1<<10, + FLAGS_HEX = 1<<11, + FLAGS_UPPER = 1<<12, + FLAGS_WIDTH = 1<<13, /* '*' or '*$' used */ + FLAGS_WIDTHPARAM = 1<<14, /* width PARAMETER was specified */ + FLAGS_PREC = 1<<15, /* precision was specified */ + FLAGS_PRECPARAM = 1<<16, /* precision PARAMETER was specified */ + FLAGS_CHAR = 1<<17, /* %c story */ + FLAGS_FLOATE = 1<<18, /* %e or %E */ + FLAGS_FLOATG = 1<<19 /* %g or %G */ +}; + +typedef struct { + FormatType type; + int flags; + long width; /* width OR width parameter number */ + long precision; /* precision OR precision parameter number */ + union { + char *str; + void *ptr; + union { + mp_intmax_t as_signed; + mp_uintmax_t as_unsigned; + } num; + double dnum; + } data; +} va_stack_t; + +struct nsprintf { + char *buffer; + size_t length; + size_t max; +}; + +struct asprintf { + char *buffer; /* allocated buffer */ + size_t len; /* length of string */ + size_t alloc; /* length of alloc */ + int fail; /* (!= 0) if an alloc has failed and thus + the output is not the complete data */ +}; + +static long dprintf_DollarString(char *input, char **end) +{ + int number = 0; + while(ISDIGIT(*input)) { + number *= 10; + number += *input-'0'; + input++; + } + if(number && ('$'==*input++)) { + *end = input; + return number; + } + return 0; +} + +static bool dprintf_IsQualifierNoDollar(const char *fmt) +{ +#if defined(MP_HAVE_INT_EXTENSIONS) + if(!strncmp(fmt, "I32", 3) || !strncmp(fmt, "I64", 3)) { + return TRUE; + } +#endif + + switch(*fmt) { + case '-': case '+': case ' ': case '#': case '.': + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case 'h': case 'l': case 'L': case 'z': case 'q': + case '*': case 'O': +#if defined(MP_HAVE_INT_EXTENSIONS) + case 'I': +#endif + return TRUE; + + default: + return FALSE; + } +} + +/****************************************************************** + * + * Pass 1: + * Create an index with the type of each parameter entry and its + * value (may vary in size) + * + * Returns zero on success. + * + ******************************************************************/ + +static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos, + va_list arglist) +{ + char *fmt = (char *)format; + int param_num = 0; + long this_param; + long width; + long precision; + int flags; + long max_param = 0; + long i; + + while(*fmt) { + if(*fmt++ == '%') { + if(*fmt == '%') { + fmt++; + continue; /* while */ + } + + flags = FLAGS_NEW; + + /* Handle the positional case (N$) */ + + param_num++; + + this_param = dprintf_DollarString(fmt, &fmt); + if(0 == this_param) + /* we got no positional, get the next counter */ + this_param = param_num; + + if(this_param > max_param) + max_param = this_param; + + /* + * The parameter with number 'i' should be used. Next, we need + * to get SIZE and TYPE of the parameter. Add the information + * to our array. + */ + + width = 0; + precision = 0; + + /* Handle the flags */ + + while(dprintf_IsQualifierNoDollar(fmt)) { +#if defined(MP_HAVE_INT_EXTENSIONS) + if(!strncmp(fmt, "I32", 3)) { + flags |= FLAGS_LONG; + fmt += 3; + } + else if(!strncmp(fmt, "I64", 3)) { + flags |= FLAGS_LONGLONG; + fmt += 3; + } + else +#endif + + switch(*fmt++) { + case ' ': + flags |= FLAGS_SPACE; + break; + case '+': + flags |= FLAGS_SHOWSIGN; + break; + case '-': + flags |= FLAGS_LEFT; + flags &= ~FLAGS_PAD_NIL; + break; + case '#': + flags |= FLAGS_ALT; + break; + case '.': + if('*' == *fmt) { + /* The precision is picked from a specified parameter */ + + flags |= FLAGS_PRECPARAM; + fmt++; + param_num++; + + i = dprintf_DollarString(fmt, &fmt); + if(i) + precision = i; + else + precision = param_num; + + if(precision > max_param) + max_param = precision; + } + else { + flags |= FLAGS_PREC; + precision = strtol(fmt, &fmt, 10); + } + break; + case 'h': + flags |= FLAGS_SHORT; + break; +#if defined(MP_HAVE_INT_EXTENSIONS) + case 'I': +#if (SIZEOF_CURL_OFF_T > SIZEOF_LONG) + flags |= FLAGS_LONGLONG; +#else + flags |= FLAGS_LONG; +#endif + break; +#endif + case 'l': + if(flags & FLAGS_LONG) + flags |= FLAGS_LONGLONG; + else + flags |= FLAGS_LONG; + break; + case 'L': + flags |= FLAGS_LONGDOUBLE; + break; + case 'q': + flags |= FLAGS_LONGLONG; + break; + case 'z': + /* the code below generates a warning if -Wunreachable-code is + used */ +#if (SIZEOF_SIZE_T > SIZEOF_LONG) + flags |= FLAGS_LONGLONG; +#else + flags |= FLAGS_LONG; +#endif + break; + case 'O': +#if (SIZEOF_CURL_OFF_T > SIZEOF_LONG) + flags |= FLAGS_LONGLONG; +#else + flags |= FLAGS_LONG; +#endif + break; + case '0': + if(!(flags & FLAGS_LEFT)) + flags |= FLAGS_PAD_NIL; + /* FALLTHROUGH */ + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + flags |= FLAGS_WIDTH; + width = strtol(fmt-1, &fmt, 10); + break; + case '*': /* Special case */ + flags |= FLAGS_WIDTHPARAM; + param_num++; + + i = dprintf_DollarString(fmt, &fmt); + if(i) + width = i; + else + width = param_num; + if(width > max_param) + max_param = width; + break; + default: + break; + } + } /* switch */ + + /* Handle the specifier */ + + i = this_param - 1; + + if((i < 0) || (i >= MAX_PARAMETERS)) + /* out of allowed range */ + return 1; + + switch (*fmt) { + case 'S': + flags |= FLAGS_ALT; + /* FALLTHROUGH */ + case 's': + vto[i].type = FORMAT_STRING; + break; + case 'n': + vto[i].type = FORMAT_INTPTR; + break; + case 'p': + vto[i].type = FORMAT_PTR; + break; + case 'd': case 'i': + vto[i].type = FORMAT_INT; + break; + case 'u': + vto[i].type = FORMAT_INT; + flags |= FLAGS_UNSIGNED; + break; + case 'o': + vto[i].type = FORMAT_INT; + flags |= FLAGS_OCTAL; + break; + case 'x': + vto[i].type = FORMAT_INT; + flags |= FLAGS_HEX|FLAGS_UNSIGNED; + break; + case 'X': + vto[i].type = FORMAT_INT; + flags |= FLAGS_HEX|FLAGS_UPPER|FLAGS_UNSIGNED; + break; + case 'c': + vto[i].type = FORMAT_INT; + flags |= FLAGS_CHAR; + break; + case 'f': + vto[i].type = FORMAT_DOUBLE; + break; + case 'e': + vto[i].type = FORMAT_DOUBLE; + flags |= FLAGS_FLOATE; + break; + case 'E': + vto[i].type = FORMAT_DOUBLE; + flags |= FLAGS_FLOATE|FLAGS_UPPER; + break; + case 'g': + vto[i].type = FORMAT_DOUBLE; + flags |= FLAGS_FLOATG; + break; + case 'G': + vto[i].type = FORMAT_DOUBLE; + flags |= FLAGS_FLOATG|FLAGS_UPPER; + break; + default: + vto[i].type = FORMAT_UNKNOWN; + break; + } /* switch */ + + vto[i].flags = flags; + vto[i].width = width; + vto[i].precision = precision; + + if(flags & FLAGS_WIDTHPARAM) { + /* we have the width specified from a parameter, so we make that + parameter's info setup properly */ + long k = width - 1; + vto[i].width = k; + vto[k].type = FORMAT_WIDTH; + vto[k].flags = FLAGS_NEW; + /* can't use width or precision of width! */ + vto[k].width = 0; + vto[k].precision = 0; + } + if(flags & FLAGS_PRECPARAM) { + /* we have the precision specified from a parameter, so we make that + parameter's info setup properly */ + long k = precision - 1; + vto[i].precision = k; + vto[k].type = FORMAT_WIDTH; + vto[k].flags = FLAGS_NEW; + /* can't use width or precision of width! */ + vto[k].width = 0; + vto[k].precision = 0; + } + *endpos++ = fmt + 1; /* end of this sequence */ + } + } + + /* Read the arg list parameters into our data list */ + for(i = 0; i$ sequence */ + param = dprintf_DollarString(f, &f); + + if(!param) + param = param_num; + else + --param; + + param_num++; /* increase this always to allow "%2$s %1$s %s" and then the + third %s will pick the 3rd argument */ + + p = &vto[param]; + + /* pick up the specified width */ + if(p->flags & FLAGS_WIDTHPARAM) { + width = (long)vto[p->width].data.num.as_signed; + param_num++; /* since the width is extracted from a parameter, we + must skip that to get to the next one properly */ + if(width < 0) { + /* "A negative field width is taken as a '-' flag followed by a + positive field width." */ + width = -width; + p->flags |= FLAGS_LEFT; + p->flags &= ~FLAGS_PAD_NIL; + } + } + else + width = p->width; + + /* pick up the specified precision */ + if(p->flags & FLAGS_PRECPARAM) { + prec = (long)vto[p->precision].data.num.as_signed; + param_num++; /* since the precision is extracted from a parameter, we + must skip that to get to the next one properly */ + if(prec < 0) + /* "A negative precision is taken as if the precision were + omitted." */ + prec = -1; + } + else if(p->flags & FLAGS_PREC) + prec = p->precision; + else + prec = -1; + + is_alt = (p->flags & FLAGS_ALT) ? 1 : 0; + + switch(p->type) { + case FORMAT_INT: + num = p->data.num.as_unsigned; + if(p->flags & FLAGS_CHAR) { + /* Character. */ + if(!(p->flags & FLAGS_LEFT)) + while(--width > 0) + OUTCHAR(' '); + OUTCHAR((char) num); + if(p->flags & FLAGS_LEFT) + while(--width > 0) + OUTCHAR(' '); + break; + } + if(p->flags & FLAGS_OCTAL) { + /* Octal unsigned integer. */ + base = 8; + goto unsigned_number; + } + else if(p->flags & FLAGS_HEX) { + /* Hexadecimal unsigned integer. */ + + digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits; + base = 16; + goto unsigned_number; + } + else if(p->flags & FLAGS_UNSIGNED) { + /* Decimal unsigned integer. */ + base = 10; + goto unsigned_number; + } + + /* Decimal integer. */ + base = 10; + + is_neg = (p->data.num.as_signed < (mp_intmax_t)0) ? 1 : 0; + if(is_neg) { + /* signed_num might fail to hold absolute negative minimum by 1 */ + signed_num = p->data.num.as_signed + (mp_intmax_t)1; + signed_num = -signed_num; + num = (mp_uintmax_t)signed_num; + num += (mp_uintmax_t)1; + } + + goto number; + + unsigned_number: + /* Unsigned number of base BASE. */ + is_neg = 0; + + number: + /* Number of base BASE. */ + + /* Supply a default precision if none was given. */ + if(prec == -1) + prec = 1; + + /* Put the number in WORK. */ + w = workend; + while(num > 0) { + *w-- = digits[num % base]; + num /= base; + } + width -= (long)(workend - w); + prec -= (long)(workend - w); + + if(is_alt && base == 8 && prec <= 0) { + *w-- = '0'; + --width; + } + + if(prec > 0) { + width -= prec; + while(prec-- > 0) + *w-- = '0'; + } + + if(is_alt && base == 16) + width -= 2; + + if(is_neg || (p->flags & FLAGS_SHOWSIGN) || (p->flags & FLAGS_SPACE)) + --width; + + if(!(p->flags & FLAGS_LEFT) && !(p->flags & FLAGS_PAD_NIL)) + while(width-- > 0) + OUTCHAR(' '); + + if(is_neg) + OUTCHAR('-'); + else if(p->flags & FLAGS_SHOWSIGN) + OUTCHAR('+'); + else if(p->flags & FLAGS_SPACE) + OUTCHAR(' '); + + if(is_alt && base == 16) { + OUTCHAR('0'); + if(p->flags & FLAGS_UPPER) + OUTCHAR('X'); + else + OUTCHAR('x'); + } + + if(!(p->flags & FLAGS_LEFT) && (p->flags & FLAGS_PAD_NIL)) + while(width-- > 0) + OUTCHAR('0'); + + /* Write the number. */ + while(++w <= workend) { + OUTCHAR(*w); + } + + if(p->flags & FLAGS_LEFT) + while(width-- > 0) + OUTCHAR(' '); + break; + + case FORMAT_STRING: + /* String. */ + { + static const char null[] = "(nil)"; + const char *str; + size_t len; + + str = (char *) p->data.str; + if(str == NULL) { + /* Write null[] if there's space. */ + if(prec == -1 || prec >= (long) sizeof(null) - 1) { + str = null; + len = sizeof(null) - 1; + /* Disable quotes around (nil) */ + p->flags &= (~FLAGS_ALT); + } + else { + str = ""; + len = 0; + } + } + else if(prec != -1) + len = (size_t)prec; + else + len = strlen(str); + + width -= (len > LONG_MAX) ? LONG_MAX : (long)len; + + if(p->flags & FLAGS_ALT) + OUTCHAR('"'); + + if(!(p->flags&FLAGS_LEFT)) + while(width-- > 0) + OUTCHAR(' '); + + for(; len && *str; len--) + OUTCHAR(*str++); + if(p->flags&FLAGS_LEFT) + while(width-- > 0) + OUTCHAR(' '); + + if(p->flags & FLAGS_ALT) + OUTCHAR('"'); + } + break; + + case FORMAT_PTR: + /* Generic pointer. */ + { + void *ptr; + ptr = (void *) p->data.ptr; + if(ptr != NULL) { + /* If the pointer is not NULL, write it as a %#x spec. */ + base = 16; + digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits; + is_alt = 1; + num = (size_t) ptr; + is_neg = 0; + goto number; + } + else { + /* Write "(nil)" for a nil pointer. */ + static const char strnil[] = "(nil)"; + const char *point; + + width -= (long)(sizeof(strnil) - 1); + if(p->flags & FLAGS_LEFT) + while(width-- > 0) + OUTCHAR(' '); + for(point = strnil; *point != '\0'; ++point) + OUTCHAR(*point); + if(! (p->flags & FLAGS_LEFT)) + while(width-- > 0) + OUTCHAR(' '); + } + } + break; + + case FORMAT_DOUBLE: + { + char formatbuf[32]="%"; + char *fptr = &formatbuf[1]; + size_t left = sizeof(formatbuf)-strlen(formatbuf); + int len; + + width = -1; + if(p->flags & FLAGS_WIDTH) + width = p->width; + else if(p->flags & FLAGS_WIDTHPARAM) + width = (long)vto[p->width].data.num.as_signed; + + prec = -1; + if(p->flags & FLAGS_PREC) + prec = p->precision; + else if(p->flags & FLAGS_PRECPARAM) + prec = (long)vto[p->precision].data.num.as_signed; + + if(p->flags & FLAGS_LEFT) + *fptr++ = '-'; + if(p->flags & FLAGS_SHOWSIGN) + *fptr++ = '+'; + if(p->flags & FLAGS_SPACE) + *fptr++ = ' '; + if(p->flags & FLAGS_ALT) + *fptr++ = '#'; + + *fptr = 0; + + if(width >= 0) { + if(width >= (long)sizeof(work)) + width = sizeof(work)-1; + /* RECURSIVE USAGE */ + len = curl_msnprintf(fptr, left, "%ld", width); + fptr += len; + left -= len; + } + if(prec >= 0) { + /* for each digit in the integer part, we can have one less + precision */ + size_t maxprec = sizeof(work) - 2; + double val = p->data.dnum; + while(val >= 10.0) { + val /= 10; + maxprec--; + } + + if(prec > (long)maxprec) + prec = (long)maxprec-1; + /* RECURSIVE USAGE */ + len = curl_msnprintf(fptr, left, ".%ld", prec); + fptr += len; + } + if(p->flags & FLAGS_LONG) + *fptr++ = 'l'; + + if(p->flags & FLAGS_FLOATE) + *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'E':'e'); + else if(p->flags & FLAGS_FLOATG) + *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'G' : 'g'); + else + *fptr++ = 'f'; + + *fptr = 0; /* and a final zero termination */ + + /* NOTE NOTE NOTE!! Not all sprintf implementations return number of + output characters */ + (sprintf)(work, formatbuf, p->data.dnum); + DEBUGASSERT(strlen(work) <= sizeof(work)); + for(fptr = work; *fptr; fptr++) + OUTCHAR(*fptr); + } + break; + + case FORMAT_INTPTR: + /* Answer the count of characters written. */ +#ifdef HAVE_LONG_LONG_TYPE + if(p->flags & FLAGS_LONGLONG) + *(LONG_LONG_TYPE *) p->data.ptr = (LONG_LONG_TYPE)done; + else +#endif + if(p->flags & FLAGS_LONG) + *(long *) p->data.ptr = (long)done; + else if(!(p->flags & FLAGS_SHORT)) + *(int *) p->data.ptr = (int)done; + else + *(short *) p->data.ptr = (short)done; + break; + + default: + break; + } + f = *end++; /* goto end of %-code */ + + } + return done; +} + +/* fputc() look-alike */ +static int addbyter(int output, FILE *data) +{ + struct nsprintf *infop = (struct nsprintf *)data; + unsigned char outc = (unsigned char)output; + + if(infop->length < infop->max) { + /* only do this if we haven't reached max length yet */ + infop->buffer[0] = outc; /* store */ + infop->buffer++; /* increase pointer */ + infop->length++; /* we are now one byte larger */ + return outc; /* fputc() returns like this on success */ + } + return -1; +} + +int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format, + va_list ap_save) +{ + int retcode; + struct nsprintf info; + + info.buffer = buffer; + info.length = 0; + info.max = maxlength; + + retcode = dprintf_formatf(&info, addbyter, format, ap_save); + if((retcode != -1) && info.max) { + /* we terminate this with a zero byte */ + if(info.max == info.length) + /* we're at maximum, scrap the last letter */ + info.buffer[-1] = 0; + else + info.buffer[0] = 0; + } + return retcode; +} + +int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...) +{ + int retcode; + va_list ap_save; /* argument pointer */ + va_start(ap_save, format); + retcode = curl_mvsnprintf(buffer, maxlength, format, ap_save); + va_end(ap_save); + return retcode; +} + +/* fputc() look-alike */ +static int alloc_addbyter(int output, FILE *data) +{ + struct asprintf *infop = (struct asprintf *)data; + unsigned char outc = (unsigned char)output; + + if(!infop->buffer) { + infop->buffer = malloc(32); + if(!infop->buffer) { + infop->fail = 1; + return -1; /* fail */ + } + infop->alloc = 32; + infop->len = 0; + } + else if(infop->len + 1 >= infop->alloc) { + char *newptr = NULL; + size_t newsize = infop->alloc*2; + + /* detect wrap-around or other overflow problems */ + if(newsize > infop->alloc) + newptr = realloc(infop->buffer, newsize); + + if(!newptr) { + infop->fail = 1; + return -1; /* fail */ + } + infop->buffer = newptr; + infop->alloc = newsize; + } + + infop->buffer[ infop->len ] = outc; + + infop->len++; + + return outc; /* fputc() returns like this on success */ +} + +char *curl_maprintf(const char *format, ...) +{ + va_list ap_save; /* argument pointer */ + int retcode; + struct asprintf info; + + info.buffer = NULL; + info.len = 0; + info.alloc = 0; + info.fail = 0; + + va_start(ap_save, format); + retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save); + va_end(ap_save); + if((-1 == retcode) || info.fail) { + if(info.alloc) + free(info.buffer); + return NULL; + } + if(info.alloc) { + info.buffer[info.len] = 0; /* we terminate this with a zero byte */ + return info.buffer; + } + return strdup(""); +} + +char *curl_mvaprintf(const char *format, va_list ap_save) +{ + int retcode; + struct asprintf info; + + info.buffer = NULL; + info.len = 0; + info.alloc = 0; + info.fail = 0; + + retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save); + if((-1 == retcode) || info.fail) { + if(info.alloc) + free(info.buffer); + return NULL; + } + + if(info.alloc) { + info.buffer[info.len] = 0; /* we terminate this with a zero byte */ + return info.buffer; + } + return strdup(""); +} + +static int storebuffer(int output, FILE *data) +{ + char **buffer = (char **)data; + unsigned char outc = (unsigned char)output; + **buffer = outc; + (*buffer)++; + return outc; /* act like fputc() ! */ +} + +int curl_msprintf(char *buffer, const char *format, ...) +{ + va_list ap_save; /* argument pointer */ + int retcode; + va_start(ap_save, format); + retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save); + va_end(ap_save); + *buffer = 0; /* we terminate this with a zero byte */ + return retcode; +} + +int curl_mprintf(const char *format, ...) +{ + int retcode; + va_list ap_save; /* argument pointer */ + va_start(ap_save, format); + + retcode = dprintf_formatf(stdout, fputc, format, ap_save); + va_end(ap_save); + return retcode; +} + +int curl_mfprintf(FILE *whereto, const char *format, ...) +{ + int retcode; + va_list ap_save; /* argument pointer */ + va_start(ap_save, format); + retcode = dprintf_formatf(whereto, fputc, format, ap_save); + va_end(ap_save); + return retcode; +} + +int curl_mvsprintf(char *buffer, const char *format, va_list ap_save) +{ + int retcode; + retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save); + *buffer = 0; /* we terminate this with a zero byte */ + return retcode; +} + +int curl_mvprintf(const char *format, va_list ap_save) +{ + return dprintf_formatf(stdout, fputc, format, ap_save); +} + +int curl_mvfprintf(FILE *whereto, const char *format, va_list ap_save) +{ + return dprintf_formatf(whereto, fputc, format, ap_save); +} diff --git a/dependencies/cmcurl/lib/multi.c b/dependencies/cmcurl/lib/multi.c new file mode 100644 index 0000000..c7c46ee --- /dev/null +++ b/dependencies/cmcurl/lib/multi.c @@ -0,0 +1,3070 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "urldata.h" +#include "transfer.h" +#include "url.h" +#include "connect.h" +#include "progress.h" +#include "easyif.h" +#include "share.h" +#include "psl.h" +#include "multiif.h" +#include "sendf.h" +#include "timeval.h" +#include "http.h" +#include "select.h" +#include "warnless.h" +#include "speedcheck.h" +#include "conncache.h" +#include "multihandle.h" +#include "sigpipe.h" +#include "vtls/vtls.h" +#include "connect.h" +#include "http_proxy.h" +#include "http2.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* + CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97 + to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every + CURL handle takes 45-50 K memory, therefore this 3K are not significant. +*/ +#ifndef CURL_SOCKET_HASH_TABLE_SIZE +#define CURL_SOCKET_HASH_TABLE_SIZE 911 +#endif + +#ifndef CURL_CONNECTION_HASH_SIZE +#define CURL_CONNECTION_HASH_SIZE 97 +#endif + +#define CURL_MULTI_HANDLE 0x000bab1e + +#define GOOD_MULTI_HANDLE(x) \ + ((x) && (x)->type == CURL_MULTI_HANDLE) + +static CURLMcode singlesocket(struct Curl_multi *multi, + struct Curl_easy *data); +static int update_timer(struct Curl_multi *multi); + +static CURLMcode add_next_timeout(struct curltime now, + struct Curl_multi *multi, + struct Curl_easy *d); +static CURLMcode multi_timeout(struct Curl_multi *multi, + long *timeout_ms); +static void process_pending_handles(struct Curl_multi *multi); +static void detach_connnection(struct Curl_easy *data); + +#ifdef DEBUGBUILD +static const char * const statename[]={ + "INIT", + "CONNECT_PEND", + "CONNECT", + "WAITRESOLVE", + "WAITCONNECT", + "WAITPROXYCONNECT", + "SENDPROTOCONNECT", + "PROTOCONNECT", + "DO", + "DOING", + "DO_MORE", + "DO_DONE", + "PERFORM", + "TOOFAST", + "DONE", + "COMPLETED", + "MSGSENT", +}; +#endif + +/* function pointer called once when switching TO a state */ +typedef void (*init_multistate_func)(struct Curl_easy *data); + +static void Curl_init_completed(struct Curl_easy *data) +{ + /* this is a completed transfer */ + + /* Important: reset the conn pointer so that we don't point to memory + that could be freed anytime */ + detach_connnection(data); + Curl_expire_clear(data); /* stop all timers */ +} + +/* always use this function to change state, to make debugging easier */ +static void mstate(struct Curl_easy *data, CURLMstate state +#ifdef DEBUGBUILD + , int lineno +#endif +) +{ + CURLMstate oldstate = data->mstate; + static const init_multistate_func finit[CURLM_STATE_LAST] = { + NULL, /* INIT */ + NULL, /* CONNECT_PEND */ + Curl_init_CONNECT, /* CONNECT */ + NULL, /* WAITRESOLVE */ + NULL, /* WAITCONNECT */ + NULL, /* WAITPROXYCONNECT */ + NULL, /* SENDPROTOCONNECT */ + NULL, /* PROTOCONNECT */ + Curl_connect_free, /* DO */ + NULL, /* DOING */ + NULL, /* DO_MORE */ + NULL, /* DO_DONE */ + NULL, /* PERFORM */ + NULL, /* TOOFAST */ + NULL, /* DONE */ + Curl_init_completed, /* COMPLETED */ + NULL /* MSGSENT */ + }; + +#if defined(DEBUGBUILD) && defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) lineno; +#endif + + if(oldstate == state) + /* don't bother when the new state is the same as the old state */ + return; + + data->mstate = state; + +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + if(data->mstate >= CURLM_STATE_CONNECT_PEND && + data->mstate < CURLM_STATE_COMPLETED) { + long connection_id = -5000; + + if(data->conn) + connection_id = data->conn->connection_id; + + infof(data, + "STATE: %s => %s handle %p; line %d (connection #%ld)\n", + statename[oldstate], statename[data->mstate], + (void *)data, lineno, connection_id); + } +#endif + + if(state == CURLM_STATE_COMPLETED) + /* changing to COMPLETED means there's one less easy handle 'alive' */ + data->multi->num_alive--; + + /* if this state has an init-function, run it */ + if(finit[state]) + finit[state](data); +} + +#ifndef DEBUGBUILD +#define multistate(x,y) mstate(x,y) +#else +#define multistate(x,y) mstate(x,y, __LINE__) +#endif + +/* + * We add one of these structs to the sockhash for each socket + */ + +struct Curl_sh_entry { + struct curl_llist list; /* list of easy handles using this socket */ + unsigned int action; /* what combined action READ/WRITE this socket waits + for */ + void *socketp; /* settable by users with curl_multi_assign() */ + unsigned int users; /* number of transfers using this */ + unsigned int readers; /* this many transfers want to read */ + unsigned int writers; /* this many transfers want to write */ +}; +/* bits for 'action' having no bits means this socket is not expecting any + action */ +#define SH_READ 1 +#define SH_WRITE 2 + +/* look up a given socket in the socket hash, skip invalid sockets */ +static struct Curl_sh_entry *sh_getentry(struct curl_hash *sh, + curl_socket_t s) +{ + if(s != CURL_SOCKET_BAD) + /* only look for proper sockets */ + return Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t)); + return NULL; +} + +/* make sure this socket is present in the hash for this handle */ +static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh, + curl_socket_t s) +{ + struct Curl_sh_entry *there = sh_getentry(sh, s); + struct Curl_sh_entry *check; + + if(there) + /* it is present, return fine */ + return there; + + /* not present, add it */ + check = calloc(1, sizeof(struct Curl_sh_entry)); + if(!check) + return NULL; /* major failure */ + + Curl_llist_init(&check->list, NULL); + + /* make/add new hash entry */ + if(!Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) { + free(check); + return NULL; /* major failure */ + } + + return check; /* things are good in sockhash land */ +} + + +/* delete the given socket + handle from the hash */ +static void sh_delentry(struct curl_hash *sh, curl_socket_t s) +{ + /* We remove the hash entry. This will end up in a call to + sh_freeentry(). */ + Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t)); +} + +/* + * free a sockhash entry + */ +static void sh_freeentry(void *freethis) +{ + struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis; + + free(p); +} + +static size_t fd_key_compare(void *k1, size_t k1_len, void *k2, size_t k2_len) +{ + (void) k1_len; (void) k2_len; + + return (*((curl_socket_t *) k1)) == (*((curl_socket_t *) k2)); +} + +static size_t hash_fd(void *key, size_t key_length, size_t slots_num) +{ + curl_socket_t fd = *((curl_socket_t *) key); + (void) key_length; + + return (fd % slots_num); +} + +/* + * sh_init() creates a new socket hash and returns the handle for it. + * + * Quote from README.multi_socket: + * + * "Some tests at 7000 and 9000 connections showed that the socket hash lookup + * is somewhat of a bottle neck. Its current implementation may be a bit too + * limiting. It simply has a fixed-size array, and on each entry in the array + * it has a linked list with entries. So the hash only checks which list to + * scan through. The code I had used so for used a list with merely 7 slots + * (as that is what the DNS hash uses) but with 7000 connections that would + * make an average of 1000 nodes in each list to run through. I upped that to + * 97 slots (I believe a prime is suitable) and noticed a significant speed + * increase. I need to reconsider the hash implementation or use a rather + * large default value like this. At 9000 connections I was still below 10us + * per call." + * + */ +static int sh_init(struct curl_hash *hash, int hashsize) +{ + return Curl_hash_init(hash, hashsize, hash_fd, fd_key_compare, + sh_freeentry); +} + +/* + * multi_addmsg() + * + * Called when a transfer is completed. Adds the given msg pointer to + * the list kept in the multi handle. + */ +static CURLMcode multi_addmsg(struct Curl_multi *multi, + struct Curl_message *msg) +{ + Curl_llist_insert_next(&multi->msglist, multi->msglist.tail, msg, + &msg->list); + return CURLM_OK; +} + +/* + * multi_freeamsg() + * + * Callback used by the llist system when a single list entry is destroyed. + */ +static void multi_freeamsg(void *a, void *b) +{ + (void)a; + (void)b; +} + +struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */ + int chashsize) /* connection hash */ +{ + struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi)); + + if(!multi) + return NULL; + + multi->type = CURL_MULTI_HANDLE; + + if(Curl_mk_dnscache(&multi->hostcache)) + goto error; + + if(sh_init(&multi->sockhash, hashsize)) + goto error; + + if(Curl_conncache_init(&multi->conn_cache, chashsize)) + goto error; + + Curl_llist_init(&multi->msglist, multi_freeamsg); + Curl_llist_init(&multi->pending, multi_freeamsg); + + /* -1 means it not set by user, use the default value */ + multi->maxconnects = -1; + return multi; + + error: + + Curl_hash_destroy(&multi->sockhash); + Curl_hash_destroy(&multi->hostcache); + Curl_conncache_destroy(&multi->conn_cache); + Curl_llist_destroy(&multi->msglist, NULL); + Curl_llist_destroy(&multi->pending, NULL); + + free(multi); + return NULL; +} + +struct Curl_multi *curl_multi_init(void) +{ + return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE, + CURL_CONNECTION_HASH_SIZE); +} + +CURLMcode curl_multi_add_handle(struct Curl_multi *multi, + struct Curl_easy *data) +{ + /* First, make some basic checks that the CURLM handle is a good handle */ + if(!GOOD_MULTI_HANDLE(multi)) + return CURLM_BAD_HANDLE; + + /* Verify that we got a somewhat good easy handle too */ + if(!GOOD_EASY_HANDLE(data)) + return CURLM_BAD_EASY_HANDLE; + + /* Prevent users from adding same easy handle more than once and prevent + adding to more than one multi stack */ + if(data->multi) + return CURLM_ADDED_ALREADY; + + if(multi->in_callback) + return CURLM_RECURSIVE_API_CALL; + + /* Initialize timeout list for this handle */ + Curl_llist_init(&data->state.timeoutlist, NULL); + + /* + * No failure allowed in this function beyond this point. And no + * modification of easy nor multi handle allowed before this except for + * potential multi's connection cache growing which won't be undone in this + * function no matter what. + */ + if(data->set.errorbuffer) + data->set.errorbuffer[0] = 0; + + /* set the easy handle */ + multistate(data, CURLM_STATE_INIT); + + /* for multi interface connections, we share DNS cache automatically if the + easy handle's one is currently not set. */ + if(!data->dns.hostcache || + (data->dns.hostcachetype == HCACHE_NONE)) { + data->dns.hostcache = &multi->hostcache; + data->dns.hostcachetype = HCACHE_MULTI; + } + + /* Point to the shared or multi handle connection cache */ + if(data->share && (data->share->specifier & (1<< CURL_LOCK_DATA_CONNECT))) + data->state.conn_cache = &data->share->conn_cache; + else + data->state.conn_cache = &multi->conn_cache; + +#ifdef USE_LIBPSL + /* Do the same for PSL. */ + if(data->share && (data->share->specifier & (1 << CURL_LOCK_DATA_PSL))) + data->psl = &data->share->psl; + else + data->psl = &multi->psl; +#endif + + /* We add the new entry last in the list. */ + data->next = NULL; /* end of the line */ + if(multi->easyp) { + struct Curl_easy *last = multi->easylp; + last->next = data; + data->prev = last; + multi->easylp = data; /* the new last node */ + } + else { + /* first node, make prev NULL! */ + data->prev = NULL; + multi->easylp = multi->easyp = data; /* both first and last */ + } + + /* make the Curl_easy refer back to this multi handle */ + data->multi = multi; + + /* Set the timeout for this handle to expire really soon so that it will + be taken care of even when this handle is added in the midst of operation + when only the curl_multi_socket() API is used. During that flow, only + sockets that time-out or have actions will be dealt with. Since this + handle has no action yet, we make sure it times out to get things to + happen. */ + Curl_expire(data, 0, EXPIRE_RUN_NOW); + + /* increase the node-counter */ + multi->num_easy++; + + /* increase the alive-counter */ + multi->num_alive++; + + /* A somewhat crude work-around for a little glitch in update_timer() that + happens if the lastcall time is set to the same time when the handle is + removed as when the next handle is added, as then the check in + update_timer() that prevents calling the application multiple times with + the same timer info will not trigger and then the new handle's timeout + will not be notified to the app. + + The work-around is thus simply to clear the 'lastcall' variable to force + update_timer() to always trigger a callback to the app when a new easy + handle is added */ + memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall)); + + /* The closure handle only ever has default timeouts set. To improve the + state somewhat we clone the timeouts from each added handle so that the + closure handle always has the same timeouts as the most recently added + easy handle. */ + data->state.conn_cache->closure_handle->set.timeout = data->set.timeout; + data->state.conn_cache->closure_handle->set.server_response_timeout = + data->set.server_response_timeout; + data->state.conn_cache->closure_handle->set.no_signal = + data->set.no_signal; + + update_timer(multi); + return CURLM_OK; +} + +#if 0 +/* Debug-function, used like this: + * + * Curl_hash_print(multi->sockhash, debug_print_sock_hash); + * + * Enable the hash print function first by editing hash.c + */ +static void debug_print_sock_hash(void *p) +{ + struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p; + + fprintf(stderr, " [easy %p/magic %x/socket %d]", + (void *)sh->data, sh->data->magic, (int)sh->socket); +} +#endif + +static CURLcode multi_done(struct Curl_easy *data, + CURLcode status, /* an error if this is called + after an error was detected */ + bool premature) +{ + CURLcode result; + struct connectdata *conn = data->conn; + unsigned int i; + + DEBUGF(infof(data, "multi_done\n")); + + if(data->state.done) + /* Stop if multi_done() has already been called */ + return CURLE_OK; + + /* Stop the resolver and free its own resources (but not dns_entry yet). */ + Curl_resolver_kill(conn); + + /* Cleanup possible redirect junk */ + Curl_safefree(data->req.newurl); + Curl_safefree(data->req.location); + + switch(status) { + case CURLE_ABORTED_BY_CALLBACK: + case CURLE_READ_ERROR: + case CURLE_WRITE_ERROR: + /* When we're aborted due to a callback return code it basically have to + be counted as premature as there is trouble ahead if we don't. We have + many callbacks and protocols work differently, we could potentially do + this more fine-grained in the future. */ + premature = TRUE; + default: + break; + } + + /* this calls the protocol-specific function pointer previously set */ + if(conn->handler->done) + result = conn->handler->done(conn, status, premature); + else + result = status; + + if(CURLE_ABORTED_BY_CALLBACK != result) { + /* avoid this if we already aborted by callback to avoid this calling + another callback */ + CURLcode rc = Curl_pgrsDone(conn); + if(!result && rc) + result = CURLE_ABORTED_BY_CALLBACK; + } + + process_pending_handles(data->multi); /* connection / multiplex */ + + detach_connnection(data); + if(CONN_INUSE(conn)) { + /* Stop if still used. */ + DEBUGF(infof(data, "Connection still in use %zu, " + "no more multi_done now!\n", + conn->easyq.size)); + return CURLE_OK; + } + + data->state.done = TRUE; /* called just now! */ + + if(conn->dns_entry) { + Curl_resolv_unlock(data, conn->dns_entry); /* done with this */ + conn->dns_entry = NULL; + } + Curl_hostcache_prune(data); + Curl_safefree(data->state.ulbuf); + + /* if the transfer was completed in a paused state there can be buffered + data left to free */ + for(i = 0; i < data->state.tempcount; i++) { + free(data->state.tempwrite[i].buf); + } + data->state.tempcount = 0; + + /* if data->set.reuse_forbid is TRUE, it means the libcurl client has + forced us to close this connection. This is ignored for requests taking + place in a NTLM/NEGOTIATE authentication handshake + + if conn->bits.close is TRUE, it means that the connection should be + closed in spite of all our efforts to be nice, due to protocol + restrictions in our or the server's end + + if premature is TRUE, it means this connection was said to be DONE before + the entire request operation is complete and thus we can't know in what + state it is for re-using, so we're forced to close it. In a perfect world + we can add code that keep track of if we really must close it here or not, + but currently we have no such detail knowledge. + */ + + if((data->set.reuse_forbid +#if defined(USE_NTLM) + && !(conn->http_ntlm_state == NTLMSTATE_TYPE2 || + conn->proxy_ntlm_state == NTLMSTATE_TYPE2) +#endif +#if defined(USE_SPNEGO) + && !(conn->http_negotiate_state == GSS_AUTHRECV || + conn->proxy_negotiate_state == GSS_AUTHRECV) +#endif + ) || conn->bits.close + || (premature && !(conn->handler->flags & PROTOPT_STREAM))) { + CURLcode res2 = Curl_disconnect(data, conn, premature); + + /* If we had an error already, make sure we return that one. But + if we got a new error, return that. */ + if(!result && res2) + result = res2; + } + else { + char buffer[256]; + /* create string before returning the connection */ + msnprintf(buffer, sizeof(buffer), + "Connection #%ld to host %s left intact", + conn->connection_id, + conn->bits.socksproxy ? conn->socks_proxy.host.dispname : + conn->bits.httpproxy ? conn->http_proxy.host.dispname : + conn->bits.conn_to_host ? conn->conn_to_host.dispname : + conn->host.dispname); + + /* the connection is no longer in use by this transfer */ + if(Curl_conncache_return_conn(conn)) { + /* remember the most recently used connection */ + data->state.lastconnect = conn; + infof(data, "%s\n", buffer); + } + else + data->state.lastconnect = NULL; + } + + Curl_free_request_state(data); + return result; +} + +CURLMcode curl_multi_remove_handle(struct Curl_multi *multi, + struct Curl_easy *data) +{ + struct Curl_easy *easy = data; + bool premature; + bool easy_owns_conn; + struct curl_llist_element *e; + + /* First, make some basic checks that the CURLM handle is a good handle */ + if(!GOOD_MULTI_HANDLE(multi)) + return CURLM_BAD_HANDLE; + + /* Verify that we got a somewhat good easy handle too */ + if(!GOOD_EASY_HANDLE(data)) + return CURLM_BAD_EASY_HANDLE; + + /* Prevent users from trying to remove same easy handle more than once */ + if(!data->multi) + return CURLM_OK; /* it is already removed so let's say it is fine! */ + + if(multi->in_callback) + return CURLM_RECURSIVE_API_CALL; + + premature = (data->mstate < CURLM_STATE_COMPLETED) ? TRUE : FALSE; + easy_owns_conn = (data->conn && (data->conn->data == easy)) ? + TRUE : FALSE; + + /* If the 'state' is not INIT or COMPLETED, we might need to do something + nice to put the easy_handle in a good known state when this returns. */ + if(premature) { + /* this handle is "alive" so we need to count down the total number of + alive connections when this is removed */ + multi->num_alive--; + } + + if(data->conn && + data->mstate > CURLM_STATE_DO && + data->mstate < CURLM_STATE_COMPLETED) { + /* Set connection owner so that the DONE function closes it. We can + safely do this here since connection is killed. */ + data->conn->data = easy; + streamclose(data->conn, "Removed with partial response"); + easy_owns_conn = TRUE; + } + + /* The timer must be shut down before data->multi is set to NULL, + else the timenode will remain in the splay tree after + curl_easy_cleanup is called. */ + Curl_expire_clear(data); + + if(data->conn) { + + /* we must call multi_done() here (if we still own the connection) so that + we don't leave a half-baked one around */ + if(easy_owns_conn) { + + /* multi_done() clears the conn->data field to lose the association + between the easy handle and the connection + + Note that this ignores the return code simply because there's + nothing really useful to do with it anyway! */ + (void)multi_done(data, data->result, premature); + } + } + + if(data->connect_queue.ptr) + /* the handle was in the pending list waiting for an available connection, + so go ahead and remove it */ + Curl_llist_remove(&multi->pending, &data->connect_queue, NULL); + + if(data->dns.hostcachetype == HCACHE_MULTI) { + /* stop using the multi handle's DNS cache, *after* the possible + multi_done() call above */ + data->dns.hostcache = NULL; + data->dns.hostcachetype = HCACHE_NONE; + } + + Curl_wildcard_dtor(&data->wildcard); + + /* destroy the timeout list that is held in the easy handle, do this *after* + multi_done() as that may actually call Curl_expire that uses this */ + Curl_llist_destroy(&data->state.timeoutlist, NULL); + + /* as this was using a shared connection cache we clear the pointer to that + since we're not part of that multi handle anymore */ + data->state.conn_cache = NULL; + + /* change state without using multistate(), only to make singlesocket() do + what we want */ + data->mstate = CURLM_STATE_COMPLETED; + singlesocket(multi, easy); /* to let the application know what sockets that + vanish with this handle */ + + /* Remove the association between the connection and the handle */ + if(data->conn) { + data->conn->data = NULL; + detach_connnection(data); + } + +#ifdef USE_LIBPSL + /* Remove the PSL association. */ + if(data->psl == &multi->psl) + data->psl = NULL; +#endif + + data->multi = NULL; /* clear the association to this multi handle */ + + /* make sure there's no pending message in the queue sent from this easy + handle */ + + for(e = multi->msglist.head; e; e = e->next) { + struct Curl_message *msg = e->ptr; + + if(msg->extmsg.easy_handle == easy) { + Curl_llist_remove(&multi->msglist, e, NULL); + /* there can only be one from this specific handle */ + break; + } + } + + /* make the previous node point to our next */ + if(data->prev) + data->prev->next = data->next; + else + multi->easyp = data->next; /* point to first node */ + + /* make our next point to our previous node */ + if(data->next) + data->next->prev = data->prev; + else + multi->easylp = data->prev; /* point to last node */ + + /* NOTE NOTE NOTE + We do not touch the easy handle here! */ + multi->num_easy--; /* one less to care about now */ + + update_timer(multi); + return CURLM_OK; +} + +/* Return TRUE if the application asked for multiplexing */ +bool Curl_multiplex_wanted(const struct Curl_multi *multi) +{ + return (multi && (multi->multiplexing)); +} + +/* This is the only function that should clear data->conn. This will + occasionally be called with the pointer already cleared. */ +static void detach_connnection(struct Curl_easy *data) +{ + struct connectdata *conn = data->conn; + if(conn) + Curl_llist_remove(&conn->easyq, &data->conn_queue, NULL); + data->conn = NULL; +} + +/* This is the only function that should assign data->conn */ +void Curl_attach_connnection(struct Curl_easy *data, + struct connectdata *conn) +{ + DEBUGASSERT(!data->conn); + DEBUGASSERT(conn); + data->conn = conn; + Curl_llist_insert_next(&conn->easyq, conn->easyq.tail, data, + &data->conn_queue); +} + +static int waitconnect_getsock(struct connectdata *conn, + curl_socket_t *sock, + int numsocks) +{ + int i; + int s = 0; + int rc = 0; + + if(!numsocks) + return GETSOCK_BLANK; + +#ifdef USE_SSL + if(CONNECT_FIRSTSOCKET_PROXY_SSL()) + return Curl_ssl_getsock(conn, sock, numsocks); +#endif + + for(i = 0; i<2; i++) { + if(conn->tempsock[i] != CURL_SOCKET_BAD) { + sock[s] = conn->tempsock[i]; + rc |= GETSOCK_WRITESOCK(s++); + } + } + + return rc; +} + +static int waitproxyconnect_getsock(struct connectdata *conn, + curl_socket_t *sock, + int numsocks) +{ + if(!numsocks) + return GETSOCK_BLANK; + + sock[0] = conn->sock[FIRSTSOCKET]; + + /* when we've sent a CONNECT to a proxy, we should rather wait for the + socket to become readable to be able to get the response headers */ + if(conn->connect_state) + return GETSOCK_READSOCK(0); + + return GETSOCK_WRITESOCK(0); +} + +static int domore_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + if(conn && conn->handler->domore_getsock) + return conn->handler->domore_getsock(conn, socks, numsocks); + return GETSOCK_BLANK; +} + +/* returns bitmapped flags for this handle and its sockets */ +static int multi_getsock(struct Curl_easy *data, + curl_socket_t *socks, /* points to numsocks number + of sockets */ + int numsocks) +{ + /* The no connection case can happen when this is called from + curl_multi_remove_handle() => singlesocket() => multi_getsock(). + */ + if(!data->conn) + return 0; + + if(data->mstate > CURLM_STATE_CONNECT && + data->mstate < CURLM_STATE_COMPLETED) { + /* Set up ownership correctly */ + data->conn->data = data; + } + + switch(data->mstate) { + default: +#if 0 /* switch back on these cases to get the compiler to check for all enums + to be present */ + case CURLM_STATE_TOOFAST: /* returns 0, so will not select. */ + case CURLM_STATE_COMPLETED: + case CURLM_STATE_MSGSENT: + case CURLM_STATE_INIT: + case CURLM_STATE_CONNECT: + case CURLM_STATE_WAITDO: + case CURLM_STATE_DONE: + case CURLM_STATE_LAST: + /* this will get called with CURLM_STATE_COMPLETED when a handle is + removed */ +#endif + return 0; + + case CURLM_STATE_WAITRESOLVE: + return Curl_resolv_getsock(data->conn, socks, numsocks); + + case CURLM_STATE_PROTOCONNECT: + case CURLM_STATE_SENDPROTOCONNECT: + return Curl_protocol_getsock(data->conn, socks, numsocks); + + case CURLM_STATE_DO: + case CURLM_STATE_DOING: + return Curl_doing_getsock(data->conn, socks, numsocks); + + case CURLM_STATE_WAITPROXYCONNECT: + return waitproxyconnect_getsock(data->conn, socks, numsocks); + + case CURLM_STATE_WAITCONNECT: + return waitconnect_getsock(data->conn, socks, numsocks); + + case CURLM_STATE_DO_MORE: + return domore_getsock(data->conn, socks, numsocks); + + case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch + to waiting for the same as the *PERFORM + states */ + case CURLM_STATE_PERFORM: + return Curl_single_getsock(data->conn, socks, numsocks); + } + +} + +CURLMcode curl_multi_fdset(struct Curl_multi *multi, + fd_set *read_fd_set, fd_set *write_fd_set, + fd_set *exc_fd_set, int *max_fd) +{ + /* Scan through all the easy handles to get the file descriptors set. + Some easy handles may not have connected to the remote host yet, + and then we must make sure that is done. */ + struct Curl_easy *data; + int this_max_fd = -1; + curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE]; + int i; + (void)exc_fd_set; /* not used */ + + if(!GOOD_MULTI_HANDLE(multi)) + return CURLM_BAD_HANDLE; + + if(multi->in_callback) + return CURLM_RECURSIVE_API_CALL; + + data = multi->easyp; + while(data) { + int bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE); + + for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) { + curl_socket_t s = CURL_SOCKET_BAD; + + if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) { + FD_SET(sockbunch[i], read_fd_set); + s = sockbunch[i]; + } + if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) { + FD_SET(sockbunch[i], write_fd_set); + s = sockbunch[i]; + } + if(s == CURL_SOCKET_BAD) + /* this socket is unused, break out of loop */ + break; + if((int)s > this_max_fd) + this_max_fd = (int)s; + } + + data = data->next; /* check next handle */ + } + + *max_fd = this_max_fd; + + return CURLM_OK; +} + +#define NUM_POLLS_ON_STACK 10 + +CURLMcode Curl_multi_wait(struct Curl_multi *multi, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret, + bool *gotsocket) /* if any socket was checked */ +{ + struct Curl_easy *data; + curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE]; + int bitmap; + unsigned int i; + unsigned int nfds = 0; + unsigned int curlfds; + bool ufds_malloc = FALSE; + long timeout_internal; + int retcode = 0; + struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK]; + struct pollfd *ufds = &a_few_on_stack[0]; + + if(gotsocket) + *gotsocket = FALSE; + + if(!GOOD_MULTI_HANDLE(multi)) + return CURLM_BAD_HANDLE; + + if(multi->in_callback) + return CURLM_RECURSIVE_API_CALL; + + /* Count up how many fds we have from the multi handle */ + data = multi->easyp; + while(data) { + bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE); + + for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) { + curl_socket_t s = CURL_SOCKET_BAD; + + if(bitmap & GETSOCK_READSOCK(i)) { + ++nfds; + s = sockbunch[i]; + } + if(bitmap & GETSOCK_WRITESOCK(i)) { + ++nfds; + s = sockbunch[i]; + } + if(s == CURL_SOCKET_BAD) { + break; + } + } + + data = data->next; /* check next handle */ + } + + /* If the internally desired timeout is actually shorter than requested from + the outside, then use the shorter time! But only if the internal timer + is actually larger than -1! */ + (void)multi_timeout(multi, &timeout_internal); + if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms)) + timeout_ms = (int)timeout_internal; + + curlfds = nfds; /* number of internal file descriptors */ + nfds += extra_nfds; /* add the externally provided ones */ + + if(nfds > NUM_POLLS_ON_STACK) { + /* 'nfds' is a 32 bit value and 'struct pollfd' is typically 8 bytes + big, so at 2^29 sockets this value might wrap. When a process gets + the capability to actually handle over 500 million sockets this + calculation needs a integer overflow check. */ + ufds = malloc(nfds * sizeof(struct pollfd)); + if(!ufds) + return CURLM_OUT_OF_MEMORY; + ufds_malloc = TRUE; + } + nfds = 0; + + /* only do the second loop if we found descriptors in the first stage run + above */ + + if(curlfds) { + /* Add the curl handles to our pollfds first */ + data = multi->easyp; + while(data) { + bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE); + + for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) { + curl_socket_t s = CURL_SOCKET_BAD; + + if(bitmap & GETSOCK_READSOCK(i)) { + ufds[nfds].fd = sockbunch[i]; + ufds[nfds].events = POLLIN; + ++nfds; + s = sockbunch[i]; + } + if(bitmap & GETSOCK_WRITESOCK(i)) { + ufds[nfds].fd = sockbunch[i]; + ufds[nfds].events = POLLOUT; + ++nfds; + s = sockbunch[i]; + } + if(s == CURL_SOCKET_BAD) { + break; + } + } + + data = data->next; /* check next handle */ + } + } + + /* Add external file descriptions from poll-like struct curl_waitfd */ + for(i = 0; i < extra_nfds; i++) { + ufds[nfds].fd = extra_fds[i].fd; + ufds[nfds].events = 0; + if(extra_fds[i].events & CURL_WAIT_POLLIN) + ufds[nfds].events |= POLLIN; + if(extra_fds[i].events & CURL_WAIT_POLLPRI) + ufds[nfds].events |= POLLPRI; + if(extra_fds[i].events & CURL_WAIT_POLLOUT) + ufds[nfds].events |= POLLOUT; + ++nfds; + } + + if(nfds) { + int pollrc; + /* wait... */ + pollrc = Curl_poll(ufds, nfds, timeout_ms); + + if(pollrc > 0) { + retcode = pollrc; + /* copy revents results from the poll to the curl_multi_wait poll + struct, the bit values of the actual underlying poll() implementation + may not be the same as the ones in the public libcurl API! */ + for(i = 0; i < extra_nfds; i++) { + unsigned short mask = 0; + unsigned r = ufds[curlfds + i].revents; + + if(r & POLLIN) + mask |= CURL_WAIT_POLLIN; + if(r & POLLOUT) + mask |= CURL_WAIT_POLLOUT; + if(r & POLLPRI) + mask |= CURL_WAIT_POLLPRI; + + extra_fds[i].revents = mask; + } + } + } + + if(ufds_malloc) + free(ufds); + if(ret) + *ret = retcode; + if(gotsocket && (extra_fds || curlfds)) + /* if any socket was checked */ + *gotsocket = TRUE; + + return CURLM_OK; +} + +CURLMcode curl_multi_wait(struct Curl_multi *multi, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret) +{ + return Curl_multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, NULL); +} + +/* + * multi_ischanged() is called + * + * Returns TRUE/FALSE whether the state is changed to trigger a CONNECT_PEND + * => CONNECT action. + * + * Set 'clear' to TRUE to have it also clear the state variable. + */ +static bool multi_ischanged(struct Curl_multi *multi, bool clear) +{ + bool retval = multi->recheckstate; + if(clear) + multi->recheckstate = FALSE; + return retval; +} + +CURLMcode Curl_multi_add_perform(struct Curl_multi *multi, + struct Curl_easy *data, + struct connectdata *conn) +{ + CURLMcode rc; + + if(multi->in_callback) + return CURLM_RECURSIVE_API_CALL; + + rc = curl_multi_add_handle(multi, data); + if(!rc) { + struct SingleRequest *k = &data->req; + + /* pass in NULL for 'conn' here since we don't want to init the + connection, only this transfer */ + Curl_init_do(data, NULL); + + /* take this handle to the perform state right away */ + multistate(data, CURLM_STATE_PERFORM); + Curl_attach_connnection(data, conn); + k->keepon |= KEEP_RECV; /* setup to receive! */ + } + return rc; +} + +/* + * do_complete is called when the DO actions are complete. + * + * We init chunking and trailer bits to their default values here immediately + * before receiving any header data for the current request. + */ +static void do_complete(struct connectdata *conn) +{ + conn->data->req.chunk = FALSE; + Curl_pgrsTime(conn->data, TIMER_PRETRANSFER); +} + +static CURLcode multi_do(struct Curl_easy *data, bool *done) +{ + CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; + + DEBUGASSERT(conn); + DEBUGASSERT(conn->handler); + + if(conn->handler->do_it) { + /* generic protocol-specific function pointer set in curl_connect() */ + result = conn->handler->do_it(conn, done); + + if(!result && *done) + /* do_complete must be called after the protocol-specific DO function */ + do_complete(conn); + } + return result; +} + +/* + * multi_do_more() is called during the DO_MORE multi state. It is basically a + * second stage DO state which (wrongly) was introduced to support FTP's + * second connection. + * + * 'complete' can return 0 for incomplete, 1 for done and -1 for go back to + * DOING state there's more work to do! + */ + +static CURLcode multi_do_more(struct connectdata *conn, int *complete) +{ + CURLcode result = CURLE_OK; + + *complete = 0; + + if(conn->handler->do_more) + result = conn->handler->do_more(conn, complete); + + if(!result && (*complete == 1)) + /* do_complete must be called after the protocol-specific DO function */ + do_complete(conn); + + return result; +} + +static CURLMcode multi_runsingle(struct Curl_multi *multi, + struct curltime now, + struct Curl_easy *data) +{ + struct Curl_message *msg = NULL; + bool connected; + bool async; + bool protocol_connect = FALSE; + bool dophase_done = FALSE; + bool done = FALSE; + CURLMcode rc; + CURLcode result = CURLE_OK; + timediff_t timeout_ms; + timediff_t recv_timeout_ms; + timediff_t send_timeout_ms; + int control; + + if(!GOOD_EASY_HANDLE(data)) + return CURLM_BAD_EASY_HANDLE; + + do { + /* A "stream" here is a logical stream if the protocol can handle that + (HTTP/2), or the full connection for older protocols */ + bool stream_error = FALSE; + rc = CURLM_OK; + + if(!data->conn && + data->mstate > CURLM_STATE_CONNECT && + data->mstate < CURLM_STATE_DONE) { + /* In all these states, the code will blindly access 'data->conn' + so this is precaution that it isn't NULL. And it silences static + analyzers. */ + failf(data, "In state %d with no conn, bail out!\n", data->mstate); + return CURLM_INTERNAL_ERROR; + } + + if(multi_ischanged(multi, TRUE)) { + DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue!\n")); + process_pending_handles(multi); /* multiplexed */ + } + + if(data->conn && data->mstate > CURLM_STATE_CONNECT && + data->mstate < CURLM_STATE_COMPLETED) { + /* Make sure we set the connection's current owner */ + data->conn->data = data; + } + + if(data->conn && + (data->mstate >= CURLM_STATE_CONNECT) && + (data->mstate < CURLM_STATE_COMPLETED)) { + /* we need to wait for the connect state as only then is the start time + stored, but we must not check already completed handles */ + timeout_ms = Curl_timeleft(data, &now, + (data->mstate <= CURLM_STATE_DO)? + TRUE:FALSE); + + if(timeout_ms < 0) { + /* Handle timed out */ + if(data->mstate == CURLM_STATE_WAITRESOLVE) + failf(data, "Resolving timed out after %" CURL_FORMAT_TIMEDIFF_T + " milliseconds", + Curl_timediff(now, data->progress.t_startsingle)); + else if(data->mstate == CURLM_STATE_WAITCONNECT) + failf(data, "Connection timed out after %" CURL_FORMAT_TIMEDIFF_T + " milliseconds", + Curl_timediff(now, data->progress.t_startsingle)); + else { + struct SingleRequest *k = &data->req; + if(k->size != -1) { + failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T + " milliseconds with %" CURL_FORMAT_CURL_OFF_T " out of %" + CURL_FORMAT_CURL_OFF_T " bytes received", + Curl_timediff(now, data->progress.t_startsingle), + k->bytecount, k->size); + } + else { + failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T + " milliseconds with %" CURL_FORMAT_CURL_OFF_T + " bytes received", + Curl_timediff(now, data->progress.t_startsingle), + k->bytecount); + } + } + + /* Force connection closed if the connection has indeed been used */ + if(data->mstate > CURLM_STATE_DO) { + streamclose(data->conn, "Disconnected with pending data"); + stream_error = TRUE; + } + result = CURLE_OPERATION_TIMEDOUT; + (void)multi_done(data, result, TRUE); + /* Skip the statemachine and go directly to error handling section. */ + goto statemachine_end; + } + } + + switch(data->mstate) { + case CURLM_STATE_INIT: + /* init this transfer. */ + result = Curl_pretransfer(data); + + if(!result) { + /* after init, go CONNECT */ + multistate(data, CURLM_STATE_CONNECT); + Curl_pgrsTime(data, TIMER_STARTOP); + rc = CURLM_CALL_MULTI_PERFORM; + } + break; + + case CURLM_STATE_CONNECT_PEND: + /* We will stay here until there is a connection available. Then + we try again in the CURLM_STATE_CONNECT state. */ + break; + + case CURLM_STATE_CONNECT: + /* Connect. We want to get a connection identifier filled in. */ + Curl_pgrsTime(data, TIMER_STARTSINGLE); + if(data->set.timeout) + Curl_expire(data, data->set.timeout, EXPIRE_TIMEOUT); + + if(data->set.connecttimeout) + Curl_expire(data, data->set.connecttimeout, EXPIRE_CONNECTTIMEOUT); + + result = Curl_connect(data, &async, &protocol_connect); + if(CURLE_NO_CONNECTION_AVAILABLE == result) { + /* There was no connection available. We will go to the pending + state and wait for an available connection. */ + multistate(data, CURLM_STATE_CONNECT_PEND); + + /* add this handle to the list of connect-pending handles */ + Curl_llist_insert_next(&multi->pending, multi->pending.tail, data, + &data->connect_queue); + result = CURLE_OK; + break; + } + else if(data->state.previouslypending) { + /* this transfer comes from the pending queue so try move another */ + infof(data, "Transfer was pending, now try another\n"); + process_pending_handles(data->multi); + } + + if(!result) { + if(async) + /* We're now waiting for an asynchronous name lookup */ + multistate(data, CURLM_STATE_WAITRESOLVE); + else { + /* after the connect has been sent off, go WAITCONNECT unless the + protocol connect is already done and we can go directly to + WAITDO or DO! */ + rc = CURLM_CALL_MULTI_PERFORM; + + if(protocol_connect) + multistate(data, CURLM_STATE_DO); + else { +#ifndef CURL_DISABLE_HTTP + if(Curl_connect_ongoing(data->conn)) + multistate(data, CURLM_STATE_WAITPROXYCONNECT); + else +#endif + multistate(data, CURLM_STATE_WAITCONNECT); + } + } + } + break; + + case CURLM_STATE_WAITRESOLVE: + /* awaiting an asynch name resolve to complete */ + { + struct Curl_dns_entry *dns = NULL; + struct connectdata *conn = data->conn; + const char *hostname; + + DEBUGASSERT(conn); + if(conn->bits.httpproxy) + hostname = conn->http_proxy.host.name; + else if(conn->bits.conn_to_host) + hostname = conn->conn_to_host.name; + else + hostname = conn->host.name; + + /* check if we have the name resolved by now */ + dns = Curl_fetch_addr(conn, hostname, (int)conn->port); + + if(dns) { +#ifdef CURLRES_ASYNCH + conn->async.dns = dns; + conn->async.done = TRUE; +#endif + result = CURLE_OK; + infof(data, "Hostname '%s' was found in DNS cache\n", hostname); + } + + if(!dns) + result = Curl_resolv_check(data->conn, &dns); + + /* Update sockets here, because the socket(s) may have been + closed and the application thus needs to be told, even if it + is likely that the same socket(s) will again be used further + down. If the name has not yet been resolved, it is likely + that new sockets have been opened in an attempt to contact + another resolver. */ + singlesocket(multi, data); + + if(dns) { + /* Perform the next step in the connection phase, and then move on + to the WAITCONNECT state */ + result = Curl_once_resolved(data->conn, &protocol_connect); + + if(result) + /* if Curl_once_resolved() returns failure, the connection struct + is already freed and gone */ + data->conn = NULL; /* no more connection */ + else { + /* call again please so that we get the next socket setup */ + rc = CURLM_CALL_MULTI_PERFORM; + if(protocol_connect) + multistate(data, CURLM_STATE_DO); + else { +#ifndef CURL_DISABLE_HTTP + if(Curl_connect_ongoing(data->conn)) + multistate(data, CURLM_STATE_WAITPROXYCONNECT); + else +#endif + multistate(data, CURLM_STATE_WAITCONNECT); + } + } + } + + if(result) { + /* failure detected */ + stream_error = TRUE; + break; + } + } + break; + +#ifndef CURL_DISABLE_HTTP + case CURLM_STATE_WAITPROXYCONNECT: + /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */ + DEBUGASSERT(data->conn); + result = Curl_http_connect(data->conn, &protocol_connect); + + if(data->conn->bits.proxy_connect_closed) { + rc = CURLM_CALL_MULTI_PERFORM; + /* connect back to proxy again */ + result = CURLE_OK; + multi_done(data, CURLE_OK, FALSE); + multistate(data, CURLM_STATE_CONNECT); + } + else if(!result) { + if((data->conn->http_proxy.proxytype != CURLPROXY_HTTPS || + data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) && + Curl_connect_complete(data->conn)) { + rc = CURLM_CALL_MULTI_PERFORM; + /* initiate protocol connect phase */ + multistate(data, CURLM_STATE_SENDPROTOCONNECT); + } + } + else if(result) + stream_error = TRUE; + break; +#endif + + case CURLM_STATE_WAITCONNECT: + /* awaiting a completion of an asynch TCP connect */ + DEBUGASSERT(data->conn); + result = Curl_is_connected(data->conn, FIRSTSOCKET, &connected); + if(connected && !result) { +#ifndef CURL_DISABLE_HTTP + if((data->conn->http_proxy.proxytype == CURLPROXY_HTTPS && + !data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) || + Curl_connect_ongoing(data->conn)) { + multistate(data, CURLM_STATE_WAITPROXYCONNECT); + break; + } +#endif + rc = CURLM_CALL_MULTI_PERFORM; + multistate(data, data->conn->bits.tunnel_proxy? + CURLM_STATE_WAITPROXYCONNECT: + CURLM_STATE_SENDPROTOCONNECT); + } + else if(result) { + /* failure detected */ + Curl_posttransfer(data); + multi_done(data, result, TRUE); + stream_error = TRUE; + break; + } + break; + + case CURLM_STATE_SENDPROTOCONNECT: + result = Curl_protocol_connect(data->conn, &protocol_connect); + if(!result && !protocol_connect) + /* switch to waiting state */ + multistate(data, CURLM_STATE_PROTOCONNECT); + else if(!result) { + /* protocol connect has completed, go WAITDO or DO */ + multistate(data, CURLM_STATE_DO); + rc = CURLM_CALL_MULTI_PERFORM; + } + else if(result) { + /* failure detected */ + Curl_posttransfer(data); + multi_done(data, result, TRUE); + stream_error = TRUE; + } + break; + + case CURLM_STATE_PROTOCONNECT: + /* protocol-specific connect phase */ + result = Curl_protocol_connecting(data->conn, &protocol_connect); + if(!result && protocol_connect) { + /* after the connect has completed, go WAITDO or DO */ + multistate(data, CURLM_STATE_DO); + rc = CURLM_CALL_MULTI_PERFORM; + } + else if(result) { + /* failure detected */ + Curl_posttransfer(data); + multi_done(data, result, TRUE); + stream_error = TRUE; + } + break; + + case CURLM_STATE_DO: + if(data->set.connect_only) { + /* keep connection open for application to use the socket */ + connkeep(data->conn, "CONNECT_ONLY"); + multistate(data, CURLM_STATE_DONE); + result = CURLE_OK; + rc = CURLM_CALL_MULTI_PERFORM; + } + else { + /* Perform the protocol's DO action */ + result = multi_do(data, &dophase_done); + + /* When multi_do() returns failure, data->conn might be NULL! */ + + if(!result) { + if(!dophase_done) { +#ifndef CURL_DISABLE_FTP + /* some steps needed for wildcard matching */ + if(data->state.wildcardmatch) { + struct WildcardData *wc = &data->wildcard; + if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) { + /* skip some states if it is important */ + multi_done(data, CURLE_OK, FALSE); + multistate(data, CURLM_STATE_DONE); + rc = CURLM_CALL_MULTI_PERFORM; + break; + } + } +#endif + /* DO was not completed in one function call, we must continue + DOING... */ + multistate(data, CURLM_STATE_DOING); + rc = CURLM_OK; + } + + /* after DO, go DO_DONE... or DO_MORE */ + else if(data->conn->bits.do_more) { + /* we're supposed to do more, but we need to sit down, relax + and wait a little while first */ + multistate(data, CURLM_STATE_DO_MORE); + rc = CURLM_OK; + } + else { + /* we're done with the DO, now DO_DONE */ + multistate(data, CURLM_STATE_DO_DONE); + rc = CURLM_CALL_MULTI_PERFORM; + } + } + else if((CURLE_SEND_ERROR == result) && + data->conn->bits.reuse) { + /* + * In this situation, a connection that we were trying to use + * may have unexpectedly died. If possible, send the connection + * back to the CONNECT phase so we can try again. + */ + char *newurl = NULL; + followtype follow = FOLLOW_NONE; + CURLcode drc; + + drc = Curl_retry_request(data->conn, &newurl); + if(drc) { + /* a failure here pretty much implies an out of memory */ + result = drc; + stream_error = TRUE; + } + + Curl_posttransfer(data); + drc = multi_done(data, result, FALSE); + + /* When set to retry the connection, we must to go back to + * the CONNECT state */ + if(newurl) { + if(!drc || (drc == CURLE_SEND_ERROR)) { + follow = FOLLOW_RETRY; + drc = Curl_follow(data, newurl, follow); + if(!drc) { + multistate(data, CURLM_STATE_CONNECT); + rc = CURLM_CALL_MULTI_PERFORM; + result = CURLE_OK; + } + else { + /* Follow failed */ + result = drc; + } + } + else { + /* done didn't return OK or SEND_ERROR */ + result = drc; + } + } + else { + /* Have error handler disconnect conn if we can't retry */ + stream_error = TRUE; + } + free(newurl); + } + else { + /* failure detected */ + Curl_posttransfer(data); + if(data->conn) + multi_done(data, result, FALSE); + stream_error = TRUE; + } + } + break; + + case CURLM_STATE_DOING: + /* we continue DOING until the DO phase is complete */ + DEBUGASSERT(data->conn); + result = Curl_protocol_doing(data->conn, + &dophase_done); + if(!result) { + if(dophase_done) { + /* after DO, go DO_DONE or DO_MORE */ + multistate(data, data->conn->bits.do_more? + CURLM_STATE_DO_MORE: + CURLM_STATE_DO_DONE); + rc = CURLM_CALL_MULTI_PERFORM; + } /* dophase_done */ + } + else { + /* failure detected */ + Curl_posttransfer(data); + multi_done(data, result, FALSE); + stream_error = TRUE; + } + break; + + case CURLM_STATE_DO_MORE: + /* + * When we are connected, DO MORE and then go DO_DONE + */ + DEBUGASSERT(data->conn); + result = multi_do_more(data->conn, &control); + + if(!result) { + if(control) { + /* if positive, advance to DO_DONE + if negative, go back to DOING */ + multistate(data, control == 1? + CURLM_STATE_DO_DONE: + CURLM_STATE_DOING); + rc = CURLM_CALL_MULTI_PERFORM; + } + else + /* stay in DO_MORE */ + rc = CURLM_OK; + } + else { + /* failure detected */ + Curl_posttransfer(data); + multi_done(data, result, FALSE); + stream_error = TRUE; + } + break; + + case CURLM_STATE_DO_DONE: + DEBUGASSERT(data->conn); + if(data->conn->bits.multiplex) + /* Check if we can move pending requests to send pipe */ + process_pending_handles(multi); /* multiplexed */ + + /* Only perform the transfer if there's a good socket to work with. + Having both BAD is a signal to skip immediately to DONE */ + if((data->conn->sockfd != CURL_SOCKET_BAD) || + (data->conn->writesockfd != CURL_SOCKET_BAD)) + multistate(data, CURLM_STATE_PERFORM); + else { +#ifndef CURL_DISABLE_FTP + if(data->state.wildcardmatch && + ((data->conn->handler->flags & PROTOPT_WILDCARD) == 0)) { + data->wildcard.state = CURLWC_DONE; + } +#endif + multistate(data, CURLM_STATE_DONE); + } + rc = CURLM_CALL_MULTI_PERFORM; + break; + + case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */ + DEBUGASSERT(data->conn); + /* if both rates are within spec, resume transfer */ + if(Curl_pgrsUpdate(data->conn)) + result = CURLE_ABORTED_BY_CALLBACK; + else + result = Curl_speedcheck(data, now); + + if(!result) { + send_timeout_ms = 0; + if(data->set.max_send_speed > 0) + send_timeout_ms = + Curl_pgrsLimitWaitTime(data->progress.uploaded, + data->progress.ul_limit_size, + data->set.max_send_speed, + data->progress.ul_limit_start, + now); + + recv_timeout_ms = 0; + if(data->set.max_recv_speed > 0) + recv_timeout_ms = + Curl_pgrsLimitWaitTime(data->progress.downloaded, + data->progress.dl_limit_size, + data->set.max_recv_speed, + data->progress.dl_limit_start, + now); + + if(!send_timeout_ms && !recv_timeout_ms) { + multistate(data, CURLM_STATE_PERFORM); + Curl_ratelimit(data, now); + } + else if(send_timeout_ms >= recv_timeout_ms) + Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST); + else + Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST); + } + break; + + case CURLM_STATE_PERFORM: + { + char *newurl = NULL; + bool retry = FALSE; + bool comeback = FALSE; + + /* check if over send speed */ + send_timeout_ms = 0; + if(data->set.max_send_speed > 0) + send_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded, + data->progress.ul_limit_size, + data->set.max_send_speed, + data->progress.ul_limit_start, + now); + + /* check if over recv speed */ + recv_timeout_ms = 0; + if(data->set.max_recv_speed > 0) + recv_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded, + data->progress.dl_limit_size, + data->set.max_recv_speed, + data->progress.dl_limit_start, + now); + + if(send_timeout_ms || recv_timeout_ms) { + Curl_ratelimit(data, now); + multistate(data, CURLM_STATE_TOOFAST); + if(send_timeout_ms >= recv_timeout_ms) + Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST); + else + Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST); + break; + } + + /* read/write data if it is ready to do so */ + result = Curl_readwrite(data->conn, data, &done, &comeback); + + if(done || (result == CURLE_RECV_ERROR)) { + /* If CURLE_RECV_ERROR happens early enough, we assume it was a race + * condition and the server closed the re-used connection exactly when + * we wanted to use it, so figure out if that is indeed the case. + */ + CURLcode ret = Curl_retry_request(data->conn, &newurl); + if(!ret) + retry = (newurl)?TRUE:FALSE; + else if(!result) + result = ret; + + if(retry) { + /* if we are to retry, set the result to OK and consider the + request as done */ + result = CURLE_OK; + done = TRUE; + } + } + else if((CURLE_HTTP2_STREAM == result) && + Curl_h2_http_1_1_error(data->conn)) { + CURLcode ret = Curl_retry_request(data->conn, &newurl); + + if(!ret) { + infof(data, "Downgrades to HTTP/1.1!\n"); + data->set.httpversion = CURL_HTTP_VERSION_1_1; + /* clear the error message bit too as we ignore the one we got */ + data->state.errorbuf = FALSE; + if(!newurl) + /* typically for HTTP_1_1_REQUIRED error on first flight */ + newurl = strdup(data->change.url); + /* if we are to retry, set the result to OK and consider the request + as done */ + retry = TRUE; + result = CURLE_OK; + done = TRUE; + } + else + result = ret; + } + + if(result) { + /* + * The transfer phase returned error, we mark the connection to get + * closed to prevent being re-used. This is because we can't possibly + * know if the connection is in a good shape or not now. Unless it is + * a protocol which uses two "channels" like FTP, as then the error + * happened in the data connection. + */ + + if(!(data->conn->handler->flags & PROTOPT_DUAL) && + result != CURLE_HTTP2_STREAM) + streamclose(data->conn, "Transfer returned error"); + + Curl_posttransfer(data); + multi_done(data, result, TRUE); + } + else if(done) { + followtype follow = FOLLOW_NONE; + + /* call this even if the readwrite function returned error */ + Curl_posttransfer(data); + + /* When we follow redirects or is set to retry the connection, we must + to go back to the CONNECT state */ + if(data->req.newurl || retry) { + if(!retry) { + /* if the URL is a follow-location and not just a retried request + then figure out the URL here */ + free(newurl); + newurl = data->req.newurl; + data->req.newurl = NULL; + follow = FOLLOW_REDIR; + } + else + follow = FOLLOW_RETRY; + (void)multi_done(data, CURLE_OK, FALSE); + /* multi_done() might return CURLE_GOT_NOTHING */ + result = Curl_follow(data, newurl, follow); + if(!result) { + multistate(data, CURLM_STATE_CONNECT); + rc = CURLM_CALL_MULTI_PERFORM; + } + free(newurl); + } + else { + /* after the transfer is done, go DONE */ + + /* but first check to see if we got a location info even though we're + not following redirects */ + if(data->req.location) { + free(newurl); + newurl = data->req.location; + data->req.location = NULL; + result = Curl_follow(data, newurl, FOLLOW_FAKE); + free(newurl); + if(result) { + stream_error = TRUE; + result = multi_done(data, result, TRUE); + } + } + + if(!result) { + multistate(data, CURLM_STATE_DONE); + rc = CURLM_CALL_MULTI_PERFORM; + } + } + } + else if(comeback) + rc = CURLM_CALL_MULTI_PERFORM; + break; + } + + case CURLM_STATE_DONE: + /* this state is highly transient, so run another loop after this */ + rc = CURLM_CALL_MULTI_PERFORM; + + if(data->conn) { + CURLcode res; + + if(data->conn->bits.multiplex) + /* Check if we can move pending requests to connection */ + process_pending_handles(multi); /* multiplexing */ + + /* post-transfer command */ + res = multi_done(data, result, FALSE); + + /* allow a previously set error code take precedence */ + if(!result) + result = res; + + /* + * If there are other handles on the connection, multi_done won't set + * conn to NULL. In such a case, curl_multi_remove_handle() can + * access free'd data, if the connection is free'd and the handle + * removed before we perform the processing in CURLM_STATE_COMPLETED + */ + if(data->conn) + detach_connnection(data); + } + +#ifndef CURL_DISABLE_FTP + if(data->state.wildcardmatch) { + if(data->wildcard.state != CURLWC_DONE) { + /* if a wildcard is set and we are not ending -> lets start again + with CURLM_STATE_INIT */ + multistate(data, CURLM_STATE_INIT); + break; + } + } +#endif + /* after we have DONE what we're supposed to do, go COMPLETED, and + it doesn't matter what the multi_done() returned! */ + multistate(data, CURLM_STATE_COMPLETED); + break; + + case CURLM_STATE_COMPLETED: + break; + + case CURLM_STATE_MSGSENT: + data->result = result; + return CURLM_OK; /* do nothing */ + + default: + return CURLM_INTERNAL_ERROR; + } + statemachine_end: + + if(data->mstate < CURLM_STATE_COMPLETED) { + if(result) { + /* + * If an error was returned, and we aren't in completed state now, + * then we go to completed and consider this transfer aborted. + */ + + /* NOTE: no attempt to disconnect connections must be made + in the case blocks above - cleanup happens only here */ + + /* Check if we can move pending requests to send pipe */ + process_pending_handles(multi); /* connection */ + + if(data->conn) { + if(stream_error) { + /* Don't attempt to send data over a connection that timed out */ + bool dead_connection = result == CURLE_OPERATION_TIMEDOUT; + /* disconnect properly */ + Curl_disconnect(data, data->conn, dead_connection); + + /* This is where we make sure that the conn pointer is reset. + We don't have to do this in every case block above where a + failure is detected */ + detach_connnection(data); + } + } + else if(data->mstate == CURLM_STATE_CONNECT) { + /* Curl_connect() failed */ + (void)Curl_posttransfer(data); + } + + multistate(data, CURLM_STATE_COMPLETED); + rc = CURLM_CALL_MULTI_PERFORM; + } + /* if there's still a connection to use, call the progress function */ + else if(data->conn && Curl_pgrsUpdate(data->conn)) { + /* aborted due to progress callback return code must close the + connection */ + result = CURLE_ABORTED_BY_CALLBACK; + streamclose(data->conn, "Aborted by callback"); + + /* if not yet in DONE state, go there, otherwise COMPLETED */ + multistate(data, (data->mstate < CURLM_STATE_DONE)? + CURLM_STATE_DONE: CURLM_STATE_COMPLETED); + rc = CURLM_CALL_MULTI_PERFORM; + } + } + + if(CURLM_STATE_COMPLETED == data->mstate) { + if(data->set.fmultidone) { + /* signal via callback instead */ + data->set.fmultidone(data, result); + } + else { + /* now fill in the Curl_message with this info */ + msg = &data->msg; + + msg->extmsg.msg = CURLMSG_DONE; + msg->extmsg.easy_handle = data; + msg->extmsg.data.result = result; + + rc = multi_addmsg(multi, msg); + DEBUGASSERT(!data->conn); + } + multistate(data, CURLM_STATE_MSGSENT); + } + } while((rc == CURLM_CALL_MULTI_PERFORM) || multi_ischanged(multi, FALSE)); + + data->result = result; + return rc; +} + + +CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles) +{ + struct Curl_easy *data; + CURLMcode returncode = CURLM_OK; + struct Curl_tree *t; + struct curltime now = Curl_now(); + + if(!GOOD_MULTI_HANDLE(multi)) + return CURLM_BAD_HANDLE; + + if(multi->in_callback) + return CURLM_RECURSIVE_API_CALL; + + data = multi->easyp; + while(data) { + CURLMcode result; + SIGPIPE_VARIABLE(pipe_st); + + sigpipe_ignore(data, &pipe_st); + result = multi_runsingle(multi, now, data); + sigpipe_restore(&pipe_st); + + if(result) + returncode = result; + + data = data->next; /* operate on next handle */ + } + + /* + * Simply remove all expired timers from the splay since handles are dealt + * with unconditionally by this function and curl_multi_timeout() requires + * that already passed/handled expire times are removed from the splay. + * + * It is important that the 'now' value is set at the entry of this function + * and not for the current time as it may have ticked a little while since + * then and then we risk this loop to remove timers that actually have not + * been handled! + */ + do { + multi->timetree = Curl_splaygetbest(now, multi->timetree, &t); + if(t) + /* the removed may have another timeout in queue */ + (void)add_next_timeout(now, multi, t->payload); + + } while(t); + + *running_handles = multi->num_alive; + + if(CURLM_OK >= returncode) + update_timer(multi); + + return returncode; +} + +CURLMcode curl_multi_cleanup(struct Curl_multi *multi) +{ + struct Curl_easy *data; + struct Curl_easy *nextdata; + + if(GOOD_MULTI_HANDLE(multi)) { + if(multi->in_callback) + return CURLM_RECURSIVE_API_CALL; + + multi->type = 0; /* not good anymore */ + + /* Firsrt remove all remaining easy handles */ + data = multi->easyp; + while(data) { + nextdata = data->next; + if(!data->state.done && data->conn) + /* if DONE was never called for this handle */ + (void)multi_done(data, CURLE_OK, TRUE); + if(data->dns.hostcachetype == HCACHE_MULTI) { + /* clear out the usage of the shared DNS cache */ + Curl_hostcache_clean(data, data->dns.hostcache); + data->dns.hostcache = NULL; + data->dns.hostcachetype = HCACHE_NONE; + } + + /* Clear the pointer to the connection cache */ + data->state.conn_cache = NULL; + data->multi = NULL; /* clear the association */ + +#ifdef USE_LIBPSL + if(data->psl == &multi->psl) + data->psl = NULL; +#endif + + data = nextdata; + } + + /* Close all the connections in the connection cache */ + Curl_conncache_close_all_connections(&multi->conn_cache); + + Curl_hash_destroy(&multi->sockhash); + Curl_conncache_destroy(&multi->conn_cache); + Curl_llist_destroy(&multi->msglist, NULL); + Curl_llist_destroy(&multi->pending, NULL); + + Curl_hash_destroy(&multi->hostcache); + Curl_psl_destroy(&multi->psl); + free(multi); + + return CURLM_OK; + } + return CURLM_BAD_HANDLE; +} + +/* + * curl_multi_info_read() + * + * This function is the primary way for a multi/multi_socket application to + * figure out if a transfer has ended. We MUST make this function as fast as + * possible as it will be polled frequently and we MUST NOT scan any lists in + * here to figure out things. We must scale fine to thousands of handles and + * beyond. The current design is fully O(1). + */ + +CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue) +{ + struct Curl_message *msg; + + *msgs_in_queue = 0; /* default to none */ + + if(GOOD_MULTI_HANDLE(multi) && + !multi->in_callback && + Curl_llist_count(&multi->msglist)) { + /* there is one or more messages in the list */ + struct curl_llist_element *e; + + /* extract the head of the list to return */ + e = multi->msglist.head; + + msg = e->ptr; + + /* remove the extracted entry */ + Curl_llist_remove(&multi->msglist, e, NULL); + + *msgs_in_queue = curlx_uztosi(Curl_llist_count(&multi->msglist)); + + return &msg->extmsg; + } + return NULL; +} + +/* + * singlesocket() checks what sockets we deal with and their "action state" + * and if we have a different state in any of those sockets from last time we + * call the callback accordingly. + */ +static CURLMcode singlesocket(struct Curl_multi *multi, + struct Curl_easy *data) +{ + curl_socket_t socks[MAX_SOCKSPEREASYHANDLE]; + int i; + struct Curl_sh_entry *entry; + curl_socket_t s; + int num; + unsigned int curraction; + int actions[MAX_SOCKSPEREASYHANDLE]; + + for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) + socks[i] = CURL_SOCKET_BAD; + + /* Fill in the 'current' struct with the state as it is now: what sockets to + supervise and for what actions */ + curraction = multi_getsock(data, socks, MAX_SOCKSPEREASYHANDLE); + + /* We have 0 .. N sockets already and we get to know about the 0 .. M + sockets we should have from now on. Detect the differences, remove no + longer supervised ones and add new ones */ + + /* walk over the sockets we got right now */ + for(i = 0; (i< MAX_SOCKSPEREASYHANDLE) && + (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i))); + i++) { + unsigned int action = CURL_POLL_NONE; + unsigned int prevaction = 0; + unsigned int comboaction; + bool sincebefore = FALSE; + + s = socks[i]; + + /* get it from the hash */ + entry = sh_getentry(&multi->sockhash, s); + + if(curraction & GETSOCK_READSOCK(i)) + action |= CURL_POLL_IN; + if(curraction & GETSOCK_WRITESOCK(i)) + action |= CURL_POLL_OUT; + + actions[i] = action; + if(entry) { + /* check if new for this transfer */ + for(i = 0; i< data->numsocks; i++) { + if(s == data->sockets[i]) { + prevaction = data->actions[i]; + sincebefore = TRUE; + break; + } + } + + } + else { + /* this is a socket we didn't have before, add it to the hash! */ + entry = sh_addentry(&multi->sockhash, s); + if(!entry) + /* fatal */ + return CURLM_OUT_OF_MEMORY; + } + if(sincebefore && (prevaction != action)) { + /* Socket was used already, but different action now */ + if(prevaction & CURL_POLL_IN) + entry->readers--; + if(prevaction & CURL_POLL_OUT) + entry->writers--; + if(action & CURL_POLL_IN) + entry->readers++; + if(action & CURL_POLL_OUT) + entry->writers++; + } + else if(!sincebefore) { + /* a new user */ + entry->users++; + if(action & CURL_POLL_IN) + entry->readers++; + if(action & CURL_POLL_OUT) + entry->writers++; + + /* add 'data' to the list of handles using this socket! */ + Curl_llist_insert_next(&entry->list, entry->list.tail, + data, &data->sh_queue); + } + + comboaction = (entry->writers? CURL_POLL_OUT : 0) | + (entry->readers ? CURL_POLL_IN : 0); + +#if 0 + infof(data, "--- Comboaction: %u readers %u writers\n", + entry->readers, entry->writers); +#endif + /* check if it has the same action set */ + if(entry->action == comboaction) + /* same, continue */ + continue; + + /* we know (entry != NULL) at this point, see the logic above */ + if(multi->socket_cb) + multi->socket_cb(data, + s, + comboaction, + multi->socket_userp, + entry->socketp); + + entry->action = comboaction; /* store the current action state */ + } + + num = i; /* number of sockets */ + + /* when we've walked over all the sockets we should have right now, we must + make sure to detect sockets that are removed */ + for(i = 0; i< data->numsocks; i++) { + int j; + bool stillused = FALSE; + s = data->sockets[i]; + for(j = 0; j < num; j++) { + if(s == socks[j]) { + /* this is still supervised */ + stillused = TRUE; + break; + } + } + if(stillused) + continue; + + entry = sh_getentry(&multi->sockhash, s); + /* if this is NULL here, the socket has been closed and notified so + already by Curl_multi_closed() */ + if(entry) { + int oldactions = data->actions[i]; + /* this socket has been removed. Decrease user count */ + entry->users--; + if(oldactions & CURL_POLL_OUT) + entry->writers--; + if(oldactions & CURL_POLL_IN) + entry->readers--; + if(!entry->users) { + if(multi->socket_cb) + multi->socket_cb(data, s, CURL_POLL_REMOVE, + multi->socket_userp, + entry->socketp); + sh_delentry(&multi->sockhash, s); + } + else { + /* remove this transfer as a user of this socket */ + Curl_llist_remove(&entry->list, &data->sh_queue, NULL); + } + } + } /* for loop over numsocks */ + + memcpy(data->sockets, socks, num*sizeof(curl_socket_t)); + memcpy(data->actions, actions, num*sizeof(int)); + data->numsocks = num; + return CURLM_OK; +} + +void Curl_updatesocket(struct Curl_easy *data) +{ + singlesocket(data->multi, data); +} + + +/* + * Curl_multi_closed() + * + * Used by the connect code to tell the multi_socket code that one of the + * sockets we were using is about to be closed. This function will then + * remove it from the sockethash for this handle to make the multi_socket API + * behave properly, especially for the case when libcurl will create another + * socket again and it gets the same file descriptor number. + */ + +void Curl_multi_closed(struct Curl_easy *data, curl_socket_t s) +{ + if(data) { + /* if there's still an easy handle associated with this connection */ + struct Curl_multi *multi = data->multi; + if(multi) { + /* this is set if this connection is part of a handle that is added to + a multi handle, and only then this is necessary */ + struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s); + + if(entry) { + if(multi->socket_cb) + multi->socket_cb(data, s, CURL_POLL_REMOVE, + multi->socket_userp, + entry->socketp); + + /* now remove it from the socket hash */ + sh_delentry(&multi->sockhash, s); + } + } + } +} + +/* + * add_next_timeout() + * + * Each Curl_easy has a list of timeouts. The add_next_timeout() is called + * when it has just been removed from the splay tree because the timeout has + * expired. This function is then to advance in the list to pick the next + * timeout to use (skip the already expired ones) and add this node back to + * the splay tree again. + * + * The splay tree only has each sessionhandle as a single node and the nearest + * timeout is used to sort it on. + */ +static CURLMcode add_next_timeout(struct curltime now, + struct Curl_multi *multi, + struct Curl_easy *d) +{ + struct curltime *tv = &d->state.expiretime; + struct curl_llist *list = &d->state.timeoutlist; + struct curl_llist_element *e; + struct time_node *node = NULL; + + /* move over the timeout list for this specific handle and remove all + timeouts that are now passed tense and store the next pending + timeout in *tv */ + for(e = list->head; e;) { + struct curl_llist_element *n = e->next; + timediff_t diff; + node = (struct time_node *)e->ptr; + diff = Curl_timediff(node->time, now); + if(diff <= 0) + /* remove outdated entry */ + Curl_llist_remove(list, e, NULL); + else + /* the list is sorted so get out on the first mismatch */ + break; + e = n; + } + e = list->head; + if(!e) { + /* clear the expire times within the handles that we remove from the + splay tree */ + tv->tv_sec = 0; + tv->tv_usec = 0; + } + else { + /* copy the first entry to 'tv' */ + memcpy(tv, &node->time, sizeof(*tv)); + + /* Insert this node again into the splay. Keep the timer in the list in + case we need to recompute future timers. */ + multi->timetree = Curl_splayinsert(*tv, multi->timetree, + &d->state.timenode); + } + return CURLM_OK; +} + +static CURLMcode multi_socket(struct Curl_multi *multi, + bool checkall, + curl_socket_t s, + int ev_bitmask, + int *running_handles) +{ + CURLMcode result = CURLM_OK; + struct Curl_easy *data = NULL; + struct Curl_tree *t; + struct curltime now = Curl_now(); + + if(checkall) { + /* *perform() deals with running_handles on its own */ + result = curl_multi_perform(multi, running_handles); + + /* walk through each easy handle and do the socket state change magic + and callbacks */ + if(result != CURLM_BAD_HANDLE) { + data = multi->easyp; + while(data && !result) { + result = singlesocket(multi, data); + data = data->next; + } + } + + /* or should we fall-through and do the timer-based stuff? */ + return result; + } + if(s != CURL_SOCKET_TIMEOUT) { + + struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s); + + if(!entry) + /* Unmatched socket, we can't act on it but we ignore this fact. In + real-world tests it has been proved that libevent can in fact give + the application actions even though the socket was just previously + asked to get removed, so thus we better survive stray socket actions + and just move on. */ + ; + else { + struct curl_llist *list = &entry->list; + struct curl_llist_element *e; + SIGPIPE_VARIABLE(pipe_st); + + /* the socket can be shared by many transfers, iterate */ + for(e = list->head; e; e = e->next) { + data = (struct Curl_easy *)e->ptr; + + if(data->magic != CURLEASY_MAGIC_NUMBER) + /* bad bad bad bad bad bad bad */ + return CURLM_INTERNAL_ERROR; + + if(data->conn && !(data->conn->handler->flags & PROTOPT_DIRLOCK)) + /* set socket event bitmask if they're not locked */ + data->conn->cselect_bits = ev_bitmask; + + sigpipe_ignore(data, &pipe_st); + result = multi_runsingle(multi, now, data); + sigpipe_restore(&pipe_st); + + if(data->conn && !(data->conn->handler->flags & PROTOPT_DIRLOCK)) + /* clear the bitmask only if not locked */ + data->conn->cselect_bits = 0; + + if(CURLM_OK >= result) { + /* get the socket(s) and check if the state has been changed since + last */ + result = singlesocket(multi, data); + if(result) + return result; + } + } + + /* Now we fall-through and do the timer-based stuff, since we don't want + to force the user to have to deal with timeouts as long as at least + one connection in fact has traffic. */ + + data = NULL; /* set data to NULL again to avoid calling + multi_runsingle() in case there's no need to */ + now = Curl_now(); /* get a newer time since the multi_runsingle() loop + may have taken some time */ + } + } + else { + /* Asked to run due to time-out. Clear the 'lastcall' variable to force + update_timer() to trigger a callback to the app again even if the same + timeout is still the one to run after this call. That handles the case + when the application asks libcurl to run the timeout prematurely. */ + memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall)); + } + + /* + * The loop following here will go on as long as there are expire-times left + * to process in the splay and 'data' will be re-assigned for every expired + * handle we deal with. + */ + do { + /* the first loop lap 'data' can be NULL */ + if(data) { + SIGPIPE_VARIABLE(pipe_st); + + sigpipe_ignore(data, &pipe_st); + result = multi_runsingle(multi, now, data); + sigpipe_restore(&pipe_st); + + if(CURLM_OK >= result) { + /* get the socket(s) and check if the state has been changed since + last */ + result = singlesocket(multi, data); + if(result) + return result; + } + } + + /* Check if there's one (more) expired timer to deal with! This function + extracts a matching node if there is one */ + + multi->timetree = Curl_splaygetbest(now, multi->timetree, &t); + if(t) { + data = t->payload; /* assign this for next loop */ + (void)add_next_timeout(now, multi, t->payload); + } + + } while(t); + + *running_handles = multi->num_alive; + return result; +} + +#undef curl_multi_setopt +CURLMcode curl_multi_setopt(struct Curl_multi *multi, + CURLMoption option, ...) +{ + CURLMcode res = CURLM_OK; + va_list param; + + if(!GOOD_MULTI_HANDLE(multi)) + return CURLM_BAD_HANDLE; + + if(multi->in_callback) + return CURLM_RECURSIVE_API_CALL; + + va_start(param, option); + + switch(option) { + case CURLMOPT_SOCKETFUNCTION: + multi->socket_cb = va_arg(param, curl_socket_callback); + break; + case CURLMOPT_SOCKETDATA: + multi->socket_userp = va_arg(param, void *); + break; + case CURLMOPT_PUSHFUNCTION: + multi->push_cb = va_arg(param, curl_push_callback); + break; + case CURLMOPT_PUSHDATA: + multi->push_userp = va_arg(param, void *); + break; + case CURLMOPT_PIPELINING: + multi->multiplexing = va_arg(param, long) & CURLPIPE_MULTIPLEX; + break; + case CURLMOPT_TIMERFUNCTION: + multi->timer_cb = va_arg(param, curl_multi_timer_callback); + break; + case CURLMOPT_TIMERDATA: + multi->timer_userp = va_arg(param, void *); + break; + case CURLMOPT_MAXCONNECTS: + multi->maxconnects = va_arg(param, long); + break; + case CURLMOPT_MAX_HOST_CONNECTIONS: + multi->max_host_connections = va_arg(param, long); + break; + case CURLMOPT_MAX_TOTAL_CONNECTIONS: + multi->max_total_connections = va_arg(param, long); + break; + /* options formerly used for pipelining */ + case CURLMOPT_MAX_PIPELINE_LENGTH: + break; + case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE: + break; + case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE: + break; + case CURLMOPT_PIPELINING_SITE_BL: + break; + case CURLMOPT_PIPELINING_SERVER_BL: + break; + default: + res = CURLM_UNKNOWN_OPTION; + break; + } + va_end(param); + return res; +} + +/* we define curl_multi_socket() in the public multi.h header */ +#undef curl_multi_socket + +CURLMcode curl_multi_socket(struct Curl_multi *multi, curl_socket_t s, + int *running_handles) +{ + CURLMcode result; + if(multi->in_callback) + return CURLM_RECURSIVE_API_CALL; + result = multi_socket(multi, FALSE, s, 0, running_handles); + if(CURLM_OK >= result) + update_timer(multi); + return result; +} + +CURLMcode curl_multi_socket_action(struct Curl_multi *multi, curl_socket_t s, + int ev_bitmask, int *running_handles) +{ + CURLMcode result; + if(multi->in_callback) + return CURLM_RECURSIVE_API_CALL; + result = multi_socket(multi, FALSE, s, ev_bitmask, running_handles); + if(CURLM_OK >= result) + update_timer(multi); + return result; +} + +CURLMcode curl_multi_socket_all(struct Curl_multi *multi, int *running_handles) + +{ + CURLMcode result; + if(multi->in_callback) + return CURLM_RECURSIVE_API_CALL; + result = multi_socket(multi, TRUE, CURL_SOCKET_BAD, 0, running_handles); + if(CURLM_OK >= result) + update_timer(multi); + return result; +} + +static CURLMcode multi_timeout(struct Curl_multi *multi, + long *timeout_ms) +{ + static struct curltime tv_zero = {0, 0}; + + if(multi->timetree) { + /* we have a tree of expire times */ + struct curltime now = Curl_now(); + + /* splay the lowest to the bottom */ + multi->timetree = Curl_splay(tv_zero, multi->timetree); + + if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) { + /* some time left before expiration */ + timediff_t diff = Curl_timediff(multi->timetree->key, now); + if(diff <= 0) + /* + * Since we only provide millisecond resolution on the returned value + * and the diff might be less than one millisecond here, we don't + * return zero as that may cause short bursts of busyloops on fast + * processors while the diff is still present but less than one + * millisecond! instead we return 1 until the time is ripe. + */ + *timeout_ms = 1; + else + /* this should be safe even on 64 bit archs, as we don't use that + overly long timeouts */ + *timeout_ms = (long)diff; + } + else + /* 0 means immediately */ + *timeout_ms = 0; + } + else + *timeout_ms = -1; + + return CURLM_OK; +} + +CURLMcode curl_multi_timeout(struct Curl_multi *multi, + long *timeout_ms) +{ + /* First, make some basic checks that the CURLM handle is a good handle */ + if(!GOOD_MULTI_HANDLE(multi)) + return CURLM_BAD_HANDLE; + + if(multi->in_callback) + return CURLM_RECURSIVE_API_CALL; + + return multi_timeout(multi, timeout_ms); +} + +/* + * Tell the application it should update its timers, if it subscribes to the + * update timer callback. + */ +static int update_timer(struct Curl_multi *multi) +{ + long timeout_ms; + + if(!multi->timer_cb) + return 0; + if(multi_timeout(multi, &timeout_ms)) { + return -1; + } + if(timeout_ms < 0) { + static const struct curltime none = {0, 0}; + if(Curl_splaycomparekeys(none, multi->timer_lastcall)) { + multi->timer_lastcall = none; + /* there's no timeout now but there was one previously, tell the app to + disable it */ + return multi->timer_cb(multi, -1, multi->timer_userp); + } + return 0; + } + + /* When multi_timeout() is done, multi->timetree points to the node with the + * timeout we got the (relative) time-out time for. We can thus easily check + * if this is the same (fixed) time as we got in a previous call and then + * avoid calling the callback again. */ + if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0) + return 0; + + multi->timer_lastcall = multi->timetree->key; + + return multi->timer_cb(multi, timeout_ms, multi->timer_userp); +} + +/* + * multi_deltimeout() + * + * Remove a given timestamp from the list of timeouts. + */ +static void +multi_deltimeout(struct Curl_easy *data, expire_id eid) +{ + struct curl_llist_element *e; + struct curl_llist *timeoutlist = &data->state.timeoutlist; + /* find and remove the specific node from the list */ + for(e = timeoutlist->head; e; e = e->next) { + struct time_node *n = (struct time_node *)e->ptr; + if(n->eid == eid) { + Curl_llist_remove(timeoutlist, e, NULL); + return; + } + } +} + +/* + * multi_addtimeout() + * + * Add a timestamp to the list of timeouts. Keep the list sorted so that head + * of list is always the timeout nearest in time. + * + */ +static CURLMcode +multi_addtimeout(struct Curl_easy *data, + struct curltime *stamp, + expire_id eid) +{ + struct curl_llist_element *e; + struct time_node *node; + struct curl_llist_element *prev = NULL; + size_t n; + struct curl_llist *timeoutlist = &data->state.timeoutlist; + + node = &data->state.expires[eid]; + + /* copy the timestamp and id */ + memcpy(&node->time, stamp, sizeof(*stamp)); + node->eid = eid; /* also marks it as in use */ + + n = Curl_llist_count(timeoutlist); + if(n) { + /* find the correct spot in the list */ + for(e = timeoutlist->head; e; e = e->next) { + struct time_node *check = (struct time_node *)e->ptr; + timediff_t diff = Curl_timediff(check->time, node->time); + if(diff > 0) + break; + prev = e; + } + + } + /* else + this is the first timeout on the list */ + + Curl_llist_insert_next(timeoutlist, prev, node, &node->list); + return CURLM_OK; +} + +/* + * Curl_expire() + * + * given a number of milliseconds from now to use to set the 'act before + * this'-time for the transfer, to be extracted by curl_multi_timeout() + * + * The timeout will be added to a queue of timeouts if it defines a moment in + * time that is later than the current head of queue. + * + * Expire replaces a former timeout using the same id if already set. + */ +void Curl_expire(struct Curl_easy *data, time_t milli, expire_id id) +{ + struct Curl_multi *multi = data->multi; + struct curltime *nowp = &data->state.expiretime; + struct curltime set; + + /* this is only interesting while there is still an associated multi struct + remaining! */ + if(!multi) + return; + + DEBUGASSERT(id < EXPIRE_LAST); + + set = Curl_now(); + set.tv_sec += milli/1000; + set.tv_usec += (unsigned int)(milli%1000)*1000; + + if(set.tv_usec >= 1000000) { + set.tv_sec++; + set.tv_usec -= 1000000; + } + + /* Remove any timer with the same id just in case. */ + multi_deltimeout(data, id); + + /* Add it to the timer list. It must stay in the list until it has expired + in case we need to recompute the minimum timer later. */ + multi_addtimeout(data, &set, id); + + if(nowp->tv_sec || nowp->tv_usec) { + /* This means that the struct is added as a node in the splay tree. + Compare if the new time is earlier, and only remove-old/add-new if it + is. */ + timediff_t diff = Curl_timediff(set, *nowp); + int rc; + + if(diff > 0) { + /* The current splay tree entry is sooner than this new expiry time. + We don't need to update our splay tree entry. */ + return; + } + + /* Since this is an updated time, we must remove the previous entry from + the splay tree first and then re-add the new value */ + rc = Curl_splayremovebyaddr(multi->timetree, + &data->state.timenode, + &multi->timetree); + if(rc) + infof(data, "Internal error removing splay node = %d\n", rc); + } + + /* Indicate that we are in the splay tree and insert the new timer expiry + value since it is our local minimum. */ + *nowp = set; + data->state.timenode.payload = data; + multi->timetree = Curl_splayinsert(*nowp, multi->timetree, + &data->state.timenode); +} + +/* + * Curl_expire_done() + * + * Removes the expire timer. Marks it as done. + * + */ +void Curl_expire_done(struct Curl_easy *data, expire_id id) +{ + /* remove the timer, if there */ + multi_deltimeout(data, id); +} + +/* + * Curl_expire_clear() + * + * Clear ALL timeout values for this handle. + */ +void Curl_expire_clear(struct Curl_easy *data) +{ + struct Curl_multi *multi = data->multi; + struct curltime *nowp = &data->state.expiretime; + + /* this is only interesting while there is still an associated multi struct + remaining! */ + if(!multi) + return; + + if(nowp->tv_sec || nowp->tv_usec) { + /* Since this is an cleared time, we must remove the previous entry from + the splay tree */ + struct curl_llist *list = &data->state.timeoutlist; + int rc; + + rc = Curl_splayremovebyaddr(multi->timetree, + &data->state.timenode, + &multi->timetree); + if(rc) + infof(data, "Internal error clearing splay node = %d\n", rc); + + /* flush the timeout list too */ + while(list->size > 0) { + Curl_llist_remove(list, list->tail, NULL); + } + +#ifdef DEBUGBUILD + infof(data, "Expire cleared (transfer %p)\n", data); +#endif + nowp->tv_sec = 0; + nowp->tv_usec = 0; + } +} + + + + +CURLMcode curl_multi_assign(struct Curl_multi *multi, curl_socket_t s, + void *hashp) +{ + struct Curl_sh_entry *there = NULL; + + if(multi->in_callback) + return CURLM_RECURSIVE_API_CALL; + + there = sh_getentry(&multi->sockhash, s); + + if(!there) + return CURLM_BAD_SOCKET; + + there->socketp = hashp; + + return CURLM_OK; +} + +size_t Curl_multi_max_host_connections(struct Curl_multi *multi) +{ + return multi ? multi->max_host_connections : 0; +} + +size_t Curl_multi_max_total_connections(struct Curl_multi *multi) +{ + return multi ? multi->max_total_connections : 0; +} + +/* + * When information about a connection has appeared, call this! + */ + +void Curl_multiuse_state(struct connectdata *conn, + int bundlestate) /* use BUNDLE_* defines */ +{ + DEBUGASSERT(conn); + DEBUGASSERT(conn->bundle); + DEBUGASSERT(conn->data); + DEBUGASSERT(conn->data->multi); + + conn->bundle->multiuse = bundlestate; + process_pending_handles(conn->data->multi); +} + +static void process_pending_handles(struct Curl_multi *multi) +{ + struct curl_llist_element *e = multi->pending.head; + if(e) { + struct Curl_easy *data = e->ptr; + + DEBUGASSERT(data->mstate == CURLM_STATE_CONNECT_PEND); + + multistate(data, CURLM_STATE_CONNECT); + + /* Remove this node from the list */ + Curl_llist_remove(&multi->pending, e, NULL); + + /* Make sure that the handle will be processed soonish. */ + Curl_expire(data, 0, EXPIRE_RUN_NOW); + + /* mark this as having been in the pending queue */ + data->state.previouslypending = TRUE; + } +} + +void Curl_set_in_callback(struct Curl_easy *data, bool value) +{ + /* might get called when there is no data pointer! */ + if(data) { + if(data->multi_easy) + data->multi_easy->in_callback = value; + else if(data->multi) + data->multi->in_callback = value; + } +} + +bool Curl_is_in_callback(struct Curl_easy *easy) +{ + return ((easy->multi && easy->multi->in_callback) || + (easy->multi_easy && easy->multi_easy->in_callback)); +} + +#ifdef DEBUGBUILD +void Curl_multi_dump(struct Curl_multi *multi) +{ + struct Curl_easy *data; + int i; + fprintf(stderr, "* Multi status: %d handles, %d alive\n", + multi->num_easy, multi->num_alive); + for(data = multi->easyp; data; data = data->next) { + if(data->mstate < CURLM_STATE_COMPLETED) { + /* only display handles that are not completed */ + fprintf(stderr, "handle %p, state %s, %d sockets\n", + (void *)data, + statename[data->mstate], data->numsocks); + for(i = 0; i < data->numsocks; i++) { + curl_socket_t s = data->sockets[i]; + struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s); + + fprintf(stderr, "%d ", (int)s); + if(!entry) { + fprintf(stderr, "INTERNAL CONFUSION\n"); + continue; + } + fprintf(stderr, "[%s %s] ", + (entry->action&CURL_POLL_IN)?"RECVING":"", + (entry->action&CURL_POLL_OUT)?"SENDING":""); + } + if(data->numsocks) + fprintf(stderr, "\n"); + } + } +} +#endif diff --git a/dependencies/cmcurl/lib/multihandle.h b/dependencies/cmcurl/lib/multihandle.h new file mode 100644 index 0000000..279379a --- /dev/null +++ b/dependencies/cmcurl/lib/multihandle.h @@ -0,0 +1,138 @@ +#ifndef HEADER_CURL_MULTIHANDLE_H +#define HEADER_CURL_MULTIHANDLE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "conncache.h" +#include "psl.h" + +struct Curl_message { + struct curl_llist_element list; + /* the 'CURLMsg' is the part that is visible to the external user */ + struct CURLMsg extmsg; +}; + +/* NOTE: if you add a state here, add the name to the statename[] array as + well! +*/ +typedef enum { + CURLM_STATE_INIT, /* 0 - start in this state */ + CURLM_STATE_CONNECT_PEND, /* 1 - no connections, waiting for one */ + CURLM_STATE_CONNECT, /* 2 - resolve/connect has been sent off */ + CURLM_STATE_WAITRESOLVE, /* 3 - awaiting the resolve to finalize */ + CURLM_STATE_WAITCONNECT, /* 4 - awaiting the TCP connect to finalize */ + CURLM_STATE_WAITPROXYCONNECT, /* 5 - awaiting HTTPS proxy SSL initialization + to complete and/or proxy CONNECT to + finalize */ + CURLM_STATE_SENDPROTOCONNECT, /* 6 - initiate protocol connect procedure */ + CURLM_STATE_PROTOCONNECT, /* 7 - completing the protocol-specific connect + phase */ + CURLM_STATE_DO, /* 8 - start send off the request (part 1) */ + CURLM_STATE_DOING, /* 9 - sending off the request (part 1) */ + CURLM_STATE_DO_MORE, /* 10 - send off the request (part 2) */ + CURLM_STATE_DO_DONE, /* 11 - done sending off request */ + CURLM_STATE_PERFORM, /* 12 - transfer data */ + CURLM_STATE_TOOFAST, /* 13 - wait because limit-rate exceeded */ + CURLM_STATE_DONE, /* 14 - post data transfer operation */ + CURLM_STATE_COMPLETED, /* 15 - operation complete */ + CURLM_STATE_MSGSENT, /* 16 - the operation complete message is sent */ + CURLM_STATE_LAST /* 17 - not a true state, never use this */ +} CURLMstate; + +/* we support N sockets per easy handle. Set the corresponding bit to what + action we should wait for */ +#define MAX_SOCKSPEREASYHANDLE 5 +#define GETSOCK_READABLE (0x00ff) +#define GETSOCK_WRITABLE (0xff00) + +#define CURLPIPE_ANY (CURLPIPE_MULTIPLEX) + +/* This is the struct known as CURLM on the outside */ +struct Curl_multi { + /* First a simple identifier to easier detect if a user mix up + this multi handle with an easy handle. Set this to CURL_MULTI_HANDLE. */ + long type; + + /* We have a doubly-linked circular list with easy handles */ + struct Curl_easy *easyp; + struct Curl_easy *easylp; /* last node */ + + int num_easy; /* amount of entries in the linked list above. */ + int num_alive; /* amount of easy handles that are added but have not yet + reached COMPLETE state */ + + struct curl_llist msglist; /* a list of messages from completed transfers */ + + struct curl_llist pending; /* Curl_easys that are in the + CURLM_STATE_CONNECT_PEND state */ + + /* callback function and user data pointer for the *socket() API */ + curl_socket_callback socket_cb; + void *socket_userp; + + /* callback function and user data pointer for server push */ + curl_push_callback push_cb; + void *push_userp; + + /* Hostname cache */ + struct curl_hash hostcache; + +#ifdef USE_LIBPSL + /* PSL cache. */ + struct PslCache psl; +#endif + + /* timetree points to the splay-tree of time nodes to figure out expire + times of all currently set timers */ + struct Curl_tree *timetree; + + /* 'sockhash' is the lookup hash for socket descriptor => easy handles (note + the pluralis form, there can be more than one easy handle waiting on the + same actual socket) */ + struct curl_hash sockhash; + + /* multiplexing wanted */ + bool multiplexing; + + bool recheckstate; /* see Curl_multi_connchanged */ + + /* Shared connection cache (bundles)*/ + struct conncache conn_cache; + + long maxconnects; /* if >0, a fixed limit of the maximum number of entries + we're allowed to grow the connection cache to */ + + long max_host_connections; /* if >0, a fixed limit of the maximum number + of connections per host */ + + long max_total_connections; /* if >0, a fixed limit of the maximum number + of connections in total */ + + /* timer callback and user data pointer for the *socket() API */ + curl_multi_timer_callback timer_cb; + void *timer_userp; + struct curltime timer_lastcall; /* the fixed time for the timeout for the + previous callback */ + bool in_callback; /* true while executing a callback */ +}; + +#endif /* HEADER_CURL_MULTIHANDLE_H */ diff --git a/dependencies/cmcurl/lib/multiif.h b/dependencies/cmcurl/lib/multiif.h new file mode 100644 index 0000000..e8a5e70 --- /dev/null +++ b/dependencies/cmcurl/lib/multiif.h @@ -0,0 +1,99 @@ +#ifndef HEADER_CURL_MULTIIF_H +#define HEADER_CURL_MULTIIF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Prototypes for library-wide functions provided by multi.c + */ + +void Curl_updatesocket(struct Curl_easy *data); +void Curl_expire(struct Curl_easy *data, time_t milli, expire_id); +void Curl_expire_clear(struct Curl_easy *data); +void Curl_expire_done(struct Curl_easy *data, expire_id id); +void Curl_detach_connnection(struct Curl_easy *data); +void Curl_attach_connnection(struct Curl_easy *data, + struct connectdata *conn); +bool Curl_multiplex_wanted(const struct Curl_multi *multi); +void Curl_set_in_callback(struct Curl_easy *data, bool value); +bool Curl_is_in_callback(struct Curl_easy *easy); + +/* Internal version of curl_multi_init() accepts size parameters for the + socket and connection hashes */ +struct Curl_multi *Curl_multi_handle(int hashsize, int chashsize); + +/* the write bits start at bit 16 for the *getsock() bitmap */ +#define GETSOCK_WRITEBITSTART 16 + +#define GETSOCK_BLANK 0 /* no bits set */ + +/* set the bit for the given sock number to make the bitmap for writable */ +#define GETSOCK_WRITESOCK(x) (1 << (GETSOCK_WRITEBITSTART + (x))) + +/* set the bit for the given sock number to make the bitmap for readable */ +#define GETSOCK_READSOCK(x) (1 << (x)) + +#ifdef DEBUGBUILD + /* + * Curl_multi_dump is not a stable public function, this is only meant to + * allow easier tracking of the internal handle's state and what sockets + * they use. Only for research and development DEBUGBUILD enabled builds. + */ +void Curl_multi_dump(struct Curl_multi *multi); +#endif + +/* Return the value of the CURLMOPT_MAX_HOST_CONNECTIONS option */ +size_t Curl_multi_max_host_connections(struct Curl_multi *multi); + +/* Return the value of the CURLMOPT_MAX_TOTAL_CONNECTIONS option */ +size_t Curl_multi_max_total_connections(struct Curl_multi *multi); + +void Curl_multiuse_state(struct connectdata *conn, + int bundlestate); /* use BUNDLE_* defines */ + +/* + * Curl_multi_closed() + * + * Used by the connect code to tell the multi_socket code that one of the + * sockets we were using is about to be closed. This function will then + * remove it from the sockethash for this handle to make the multi_socket API + * behave properly, especially for the case when libcurl will create another + * socket again and it gets the same file descriptor number. + */ + +void Curl_multi_closed(struct Curl_easy *data, curl_socket_t s); + +/* + * Add a handle and move it into PERFORM state at once. For pushed streams. + */ +CURLMcode Curl_multi_add_perform(struct Curl_multi *multi, + struct Curl_easy *data, + struct connectdata *conn); + +CURLMcode Curl_multi_wait(struct Curl_multi *multi, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret, + bool *gotsocket); /* if any socket was checked */ + +#endif /* HEADER_CURL_MULTIIF_H */ diff --git a/dependencies/cmcurl/lib/netrc.c b/dependencies/cmcurl/lib/netrc.c new file mode 100644 index 0000000..1bd998f --- /dev/null +++ b/dependencies/cmcurl/lib/netrc.c @@ -0,0 +1,245 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#ifndef CURL_DISABLE_NETRC + +#ifdef HAVE_PWD_H +#include +#endif + +#include +#include "netrc.h" +#include "strtok.h" +#include "strcase.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* Get user and password from .netrc when given a machine name */ + +enum host_lookup_state { + NOTHING, + HOSTFOUND, /* the 'machine' keyword was found */ + HOSTVALID /* this is "our" machine! */ +}; + +/* + * @unittest: 1304 + * + * *loginp and *passwordp MUST be allocated if they aren't NULL when passed + * in. + */ +int Curl_parsenetrc(const char *host, + char **loginp, + char **passwordp, + bool *login_changed, + bool *password_changed, + char *netrcfile) +{ + FILE *file; + int retcode = 1; + char *login = *loginp; + char *password = *passwordp; + bool specific_login = (login && *login != 0); + bool login_alloc = FALSE; + bool password_alloc = FALSE; + bool netrc_alloc = FALSE; + enum host_lookup_state state = NOTHING; + + char state_login = 0; /* Found a login keyword */ + char state_password = 0; /* Found a password keyword */ + int state_our_login = FALSE; /* With specific_login, found *our* login + name */ + +#define NETRC DOT_CHAR "netrc" + + if(!netrcfile) { + bool home_alloc = FALSE; + char *home = curl_getenv("HOME"); /* portable environment reader */ + if(home) { + home_alloc = TRUE; +#if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID) + } + else { + struct passwd pw, *pw_res; + char pwbuf[1024]; + if(!getpwuid_r(geteuid(), &pw, pwbuf, sizeof(pwbuf), &pw_res) + && pw_res) { + home = strdup(pw.pw_dir); + if(!home) + return CURLE_OUT_OF_MEMORY; + home_alloc = TRUE; + } +#elif defined(HAVE_GETPWUID) && defined(HAVE_GETEUID) + } + else { + struct passwd *pw; + pw = getpwuid(geteuid()); + if(pw) { + home = pw->pw_dir; + } +#endif + } + + if(!home) + return retcode; /* no home directory found (or possibly out of memory) */ + + netrcfile = curl_maprintf("%s%s%s", home, DIR_CHAR, NETRC); + if(home_alloc) + free(home); + if(!netrcfile) { + return -1; + } + netrc_alloc = TRUE; + } + + file = fopen(netrcfile, FOPEN_READTEXT); + if(netrc_alloc) + free(netrcfile); + if(file) { + char *tok; + char *tok_buf; + bool done = FALSE; + char netrcbuffer[4096]; + int netrcbuffsize = (int)sizeof(netrcbuffer); + + while(!done && fgets(netrcbuffer, netrcbuffsize, file)) { + tok = strtok_r(netrcbuffer, " \t\n", &tok_buf); + if(tok && *tok == '#') + /* treat an initial hash as a comment line */ + continue; + while(!done && tok) { + + if((login && *login) && (password && *password)) { + done = TRUE; + break; + } + + switch(state) { + case NOTHING: + if(strcasecompare("machine", tok)) { + /* the next tok is the machine name, this is in itself the + delimiter that starts the stuff entered for this machine, + after this we need to search for 'login' and + 'password'. */ + state = HOSTFOUND; + } + else if(strcasecompare("default", tok)) { + state = HOSTVALID; + retcode = 0; /* we did find our host */ + } + break; + case HOSTFOUND: + if(strcasecompare(host, tok)) { + /* and yes, this is our host! */ + state = HOSTVALID; + retcode = 0; /* we did find our host */ + } + else + /* not our host */ + state = NOTHING; + break; + case HOSTVALID: + /* we are now parsing sub-keywords concerning "our" host */ + if(state_login) { + if(specific_login) { + state_our_login = strcasecompare(login, tok); + } + else if(!login || strcmp(login, tok)) { + if(login_alloc) { + free(login); + login_alloc = FALSE; + } + login = strdup(tok); + if(!login) { + retcode = -1; /* allocation failed */ + goto out; + } + login_alloc = TRUE; + } + state_login = 0; + } + else if(state_password) { + if((state_our_login || !specific_login) + && (!password || strcmp(password, tok))) { + if(password_alloc) { + free(password); + password_alloc = FALSE; + } + password = strdup(tok); + if(!password) { + retcode = -1; /* allocation failed */ + goto out; + } + password_alloc = TRUE; + } + state_password = 0; + } + else if(strcasecompare("login", tok)) + state_login = 1; + else if(strcasecompare("password", tok)) + state_password = 1; + else if(strcasecompare("machine", tok)) { + /* ok, there's machine here go => */ + state = HOSTFOUND; + state_our_login = FALSE; + } + break; + } /* switch (state) */ + + tok = strtok_r(NULL, " \t\n", &tok_buf); + } /* while(tok) */ + } /* while fgets() */ + + out: + if(!retcode) { + *login_changed = FALSE; + *password_changed = FALSE; + if(login_alloc) { + if(*loginp) + free(*loginp); + *loginp = login; + *login_changed = TRUE; + } + if(password_alloc) { + if(*passwordp) + free(*passwordp); + *passwordp = password; + *password_changed = TRUE; + } + } + else { + if(login_alloc) + free(login); + if(password_alloc) + free(password); + } + fclose(file); + } + + return retcode; +} + +#endif diff --git a/dependencies/cmcurl/lib/netrc.h b/dependencies/cmcurl/lib/netrc.h new file mode 100644 index 0000000..7f56c4b --- /dev/null +++ b/dependencies/cmcurl/lib/netrc.h @@ -0,0 +1,45 @@ +#ifndef HEADER_CURL_NETRC_H +#define HEADER_CURL_NETRC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#ifndef CURL_DISABLE_NETRC + +/* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */ +int Curl_parsenetrc(const char *host, + char **loginp, + char **passwordp, + bool *login_changed, + bool *password_changed, + char *filename); + /* Assume: (*passwordp)[0]=0, host[0] != 0. + * If (*loginp)[0] = 0, search for login and password within a machine + * section in the netrc. + * If (*loginp)[0] != 0, search for password within machine and login. + */ +#else +/* disabled */ +#define Curl_parsenetrc(a,b,c,d,e,f) 1 +#endif + +#endif /* HEADER_CURL_NETRC_H */ diff --git a/dependencies/cmcurl/lib/non-ascii.c b/dependencies/cmcurl/lib/non-ascii.c new file mode 100644 index 0000000..42beaec --- /dev/null +++ b/dependencies/cmcurl/lib/non-ascii.c @@ -0,0 +1,332 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef CURL_DOES_CONVERSIONS + +#include + +#include "non-ascii.h" +#include "formdata.h" +#include "sendf.h" +#include "urldata.h" +#include "multiif.h" + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +#ifdef HAVE_ICONV +#include +/* set default codesets for iconv */ +#ifndef CURL_ICONV_CODESET_OF_NETWORK +#define CURL_ICONV_CODESET_OF_NETWORK "ISO8859-1" +#endif +#ifndef CURL_ICONV_CODESET_FOR_UTF8 +#define CURL_ICONV_CODESET_FOR_UTF8 "UTF-8" +#endif +#define ICONV_ERROR (size_t)-1 +#endif /* HAVE_ICONV */ + +/* + * Curl_convert_clone() returns a malloced copy of the source string (if + * returning CURLE_OK), with the data converted to network format. + */ +CURLcode Curl_convert_clone(struct Curl_easy *data, + const char *indata, + size_t insize, + char **outbuf) +{ + char *convbuf; + CURLcode result; + + convbuf = malloc(insize); + if(!convbuf) + return CURLE_OUT_OF_MEMORY; + + memcpy(convbuf, indata, insize); + result = Curl_convert_to_network(data, convbuf, insize); + if(result) { + free(convbuf); + return result; + } + + *outbuf = convbuf; /* return the converted buffer */ + + return CURLE_OK; +} + +/* + * Curl_convert_to_network() is an internal function for performing ASCII + * conversions on non-ASCII platforms. It converts the buffer _in place_. + */ +CURLcode Curl_convert_to_network(struct Curl_easy *data, + char *buffer, size_t length) +{ + if(data && data->set.convtonetwork) { + /* use translation callback */ + CURLcode result; + Curl_set_in_callback(data, true); + result = data->set.convtonetwork(buffer, length); + Curl_set_in_callback(data, false); + if(result) { + failf(data, + "CURLOPT_CONV_TO_NETWORK_FUNCTION callback returned %d: %s", + (int)result, curl_easy_strerror(result)); + } + + return result; + } + else { +#ifdef HAVE_ICONV + /* do the translation ourselves */ + iconv_t tmpcd = (iconv_t) -1; + iconv_t *cd = &tmpcd; + char *input_ptr, *output_ptr; + size_t in_bytes, out_bytes, rc; + + /* open an iconv conversion descriptor if necessary */ + if(data) + cd = &data->outbound_cd; + if(*cd == (iconv_t)-1) { + *cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK, + CURL_ICONV_CODESET_OF_HOST); + if(*cd == (iconv_t)-1) { + failf(data, + "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s", + CURL_ICONV_CODESET_OF_NETWORK, + CURL_ICONV_CODESET_OF_HOST, + errno, strerror(errno)); + return CURLE_CONV_FAILED; + } + } + /* call iconv */ + input_ptr = output_ptr = buffer; + in_bytes = out_bytes = length; + rc = iconv(*cd, &input_ptr, &in_bytes, + &output_ptr, &out_bytes); + if(!data) + iconv_close(tmpcd); + if((rc == ICONV_ERROR) || (in_bytes != 0)) { + failf(data, + "The Curl_convert_to_network iconv call failed with errno %i: %s", + errno, strerror(errno)); + return CURLE_CONV_FAILED; + } +#else + failf(data, "CURLOPT_CONV_TO_NETWORK_FUNCTION callback required"); + return CURLE_CONV_REQD; +#endif /* HAVE_ICONV */ + } + + return CURLE_OK; +} + +/* + * Curl_convert_from_network() is an internal function for performing ASCII + * conversions on non-ASCII platforms. It converts the buffer _in place_. + */ +CURLcode Curl_convert_from_network(struct Curl_easy *data, + char *buffer, size_t length) +{ + if(data && data->set.convfromnetwork) { + /* use translation callback */ + CURLcode result; + Curl_set_in_callback(data, true); + result = data->set.convfromnetwork(buffer, length); + Curl_set_in_callback(data, false); + if(result) { + failf(data, + "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback returned %d: %s", + (int)result, curl_easy_strerror(result)); + } + + return result; + } + else { +#ifdef HAVE_ICONV + /* do the translation ourselves */ + iconv_t tmpcd = (iconv_t) -1; + iconv_t *cd = &tmpcd; + char *input_ptr, *output_ptr; + size_t in_bytes, out_bytes, rc; + + /* open an iconv conversion descriptor if necessary */ + if(data) + cd = &data->inbound_cd; + if(*cd == (iconv_t)-1) { + *cd = iconv_open(CURL_ICONV_CODESET_OF_HOST, + CURL_ICONV_CODESET_OF_NETWORK); + if(*cd == (iconv_t)-1) { + failf(data, + "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s", + CURL_ICONV_CODESET_OF_HOST, + CURL_ICONV_CODESET_OF_NETWORK, + errno, strerror(errno)); + return CURLE_CONV_FAILED; + } + } + /* call iconv */ + input_ptr = output_ptr = buffer; + in_bytes = out_bytes = length; + rc = iconv(*cd, &input_ptr, &in_bytes, + &output_ptr, &out_bytes); + if(!data) + iconv_close(tmpcd); + if((rc == ICONV_ERROR) || (in_bytes != 0)) { + failf(data, + "Curl_convert_from_network iconv call failed with errno %i: %s", + errno, strerror(errno)); + return CURLE_CONV_FAILED; + } +#else + failf(data, "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback required"); + return CURLE_CONV_REQD; +#endif /* HAVE_ICONV */ + } + + return CURLE_OK; +} + +/* + * Curl_convert_from_utf8() is an internal function for performing UTF-8 + * conversions on non-ASCII platforms. + */ +CURLcode Curl_convert_from_utf8(struct Curl_easy *data, + char *buffer, size_t length) +{ + if(data && data->set.convfromutf8) { + /* use translation callback */ + CURLcode result; + Curl_set_in_callback(data, true); + result = data->set.convfromutf8(buffer, length); + Curl_set_in_callback(data, false); + if(result) { + failf(data, + "CURLOPT_CONV_FROM_UTF8_FUNCTION callback returned %d: %s", + (int)result, curl_easy_strerror(result)); + } + + return result; + } + else { +#ifdef HAVE_ICONV + /* do the translation ourselves */ + iconv_t tmpcd = (iconv_t) -1; + iconv_t *cd = &tmpcd; + char *input_ptr; + char *output_ptr; + size_t in_bytes, out_bytes, rc; + + /* open an iconv conversion descriptor if necessary */ + if(data) + cd = &data->utf8_cd; + if(*cd == (iconv_t)-1) { + *cd = iconv_open(CURL_ICONV_CODESET_OF_HOST, + CURL_ICONV_CODESET_FOR_UTF8); + if(*cd == (iconv_t)-1) { + failf(data, + "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s", + CURL_ICONV_CODESET_OF_HOST, + CURL_ICONV_CODESET_FOR_UTF8, + errno, strerror(errno)); + return CURLE_CONV_FAILED; + } + } + /* call iconv */ + input_ptr = output_ptr = buffer; + in_bytes = out_bytes = length; + rc = iconv(*cd, &input_ptr, &in_bytes, + &output_ptr, &out_bytes); + if(!data) + iconv_close(tmpcd); + if((rc == ICONV_ERROR) || (in_bytes != 0)) { + failf(data, + "The Curl_convert_from_utf8 iconv call failed with errno %i: %s", + errno, strerror(errno)); + return CURLE_CONV_FAILED; + } + if(output_ptr < input_ptr) { + /* null terminate the now shorter output string */ + *output_ptr = 0x00; + } +#else + failf(data, "CURLOPT_CONV_FROM_UTF8_FUNCTION callback required"); + return CURLE_CONV_REQD; +#endif /* HAVE_ICONV */ + } + + return CURLE_OK; +} + +/* + * Init conversion stuff for a Curl_easy + */ +void Curl_convert_init(struct Curl_easy *data) +{ +#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV) + /* conversion descriptors for iconv calls */ + data->outbound_cd = (iconv_t)-1; + data->inbound_cd = (iconv_t)-1; + data->utf8_cd = (iconv_t)-1; +#else + (void)data; +#endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */ +} + +/* + * Setup conversion stuff for a Curl_easy + */ +void Curl_convert_setup(struct Curl_easy *data) +{ + data->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST, + CURL_ICONV_CODESET_OF_NETWORK); + data->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK, + CURL_ICONV_CODESET_OF_HOST); + data->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST, + CURL_ICONV_CODESET_FOR_UTF8); +} + +/* + * Close conversion stuff for a Curl_easy + */ + +void Curl_convert_close(struct Curl_easy *data) +{ +#ifdef HAVE_ICONV + /* close iconv conversion descriptors */ + if(data->inbound_cd != (iconv_t)-1) { + iconv_close(data->inbound_cd); + } + if(data->outbound_cd != (iconv_t)-1) { + iconv_close(data->outbound_cd); + } + if(data->utf8_cd != (iconv_t)-1) { + iconv_close(data->utf8_cd); + } +#else + (void)data; +#endif /* HAVE_ICONV */ +} + +#endif /* CURL_DOES_CONVERSIONS */ diff --git a/dependencies/cmcurl/lib/non-ascii.h b/dependencies/cmcurl/lib/non-ascii.h new file mode 100644 index 0000000..5fb5771 --- /dev/null +++ b/dependencies/cmcurl/lib/non-ascii.h @@ -0,0 +1,61 @@ +#ifndef HEADER_CURL_NON_ASCII_H +#define HEADER_CURL_NON_ASCII_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef CURL_DOES_CONVERSIONS + +#include "urldata.h" + +/* + * Curl_convert_clone() returns a malloced copy of the source string (if + * returning CURLE_OK), with the data converted to network format. + * + * If no conversion was needed *outbuf may be NULL. + */ +CURLcode Curl_convert_clone(struct Curl_easy *data, + const char *indata, + size_t insize, + char **outbuf); + +void Curl_convert_init(struct Curl_easy *data); +void Curl_convert_setup(struct Curl_easy *data); +void Curl_convert_close(struct Curl_easy *data); + +CURLcode Curl_convert_to_network(struct Curl_easy *data, + char *buffer, size_t length); +CURLcode Curl_convert_from_network(struct Curl_easy *data, + char *buffer, size_t length); +CURLcode Curl_convert_from_utf8(struct Curl_easy *data, + char *buffer, size_t length); +#else +#define Curl_convert_clone(a,b,c,d) ((void)a, CURLE_OK) +#define Curl_convert_init(x) Curl_nop_stmt +#define Curl_convert_setup(x) Curl_nop_stmt +#define Curl_convert_close(x) Curl_nop_stmt +#define Curl_convert_to_network(a,b,c) ((void)a, CURLE_OK) +#define Curl_convert_from_network(a,b,c) ((void)a, CURLE_OK) +#define Curl_convert_from_utf8(a,b,c) ((void)a, CURLE_OK) +#endif + +#endif /* HEADER_CURL_NON_ASCII_H */ diff --git a/dependencies/cmcurl/lib/nonblock.c b/dependencies/cmcurl/lib/nonblock.c new file mode 100644 index 0000000..4d105c1 --- /dev/null +++ b/dependencies/cmcurl/lib/nonblock.c @@ -0,0 +1,91 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif + +#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE)) +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#include "nonblock.h" + +/* + * curlx_nonblock() set the given socket to either blocking or non-blocking + * mode based on the 'nonblock' boolean argument. This function is highly + * portable. + */ +int curlx_nonblock(curl_socket_t sockfd, /* operate on this */ + int nonblock /* TRUE or FALSE */) +{ +#if defined(USE_BLOCKING_SOCKETS) + (void)sockfd; + (void)nonblock; + return 0; /* returns success */ + +#elif defined(HAVE_FCNTL_O_NONBLOCK) + + /* most recent unix versions */ + int flags; + flags = sfcntl(sockfd, F_GETFL, 0); + if(nonblock) + return sfcntl(sockfd, F_SETFL, flags | O_NONBLOCK); + return sfcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK)); + +#elif defined(HAVE_IOCTL_FIONBIO) + + /* older unix versions */ + int flags = nonblock ? 1 : 0; + return ioctl(sockfd, FIONBIO, &flags); + +#elif defined(HAVE_IOCTLSOCKET_FIONBIO) + + /* Windows */ + unsigned long flags = nonblock ? 1UL : 0UL; + return ioctlsocket(sockfd, FIONBIO, &flags); + +#elif defined(HAVE_IOCTLSOCKET_CAMEL_FIONBIO) + + /* Amiga */ + long flags = nonblock ? 1L : 0L; + return IoctlSocket(sockfd, FIONBIO, (char *)&flags); + +#elif defined(HAVE_SETSOCKOPT_SO_NONBLOCK) + + /* BeOS */ + long b = nonblock ? 1L : 0L; + return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b)); + +#else +# error "no non-blocking method was found/used/set" +#endif +} diff --git a/dependencies/cmcurl/lib/nonblock.h b/dependencies/cmcurl/lib/nonblock.h new file mode 100644 index 0000000..eb18ea1 --- /dev/null +++ b/dependencies/cmcurl/lib/nonblock.h @@ -0,0 +1,30 @@ +#ifndef HEADER_CURL_NONBLOCK_H +#define HEADER_CURL_NONBLOCK_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include /* for curl_socket_t */ + +int curlx_nonblock(curl_socket_t sockfd, /* operate on this */ + int nonblock /* TRUE or FALSE */); + +#endif /* HEADER_CURL_NONBLOCK_H */ diff --git a/dependencies/cmcurl/lib/nwlib.c b/dependencies/cmcurl/lib/nwlib.c new file mode 100644 index 0000000..7bf5f51 --- /dev/null +++ b/dependencies/cmcurl/lib/nwlib.c @@ -0,0 +1,328 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef NETWARE /* Novell NetWare */ + +#ifdef __NOVELL_LIBC__ +/* For native LibC-based NLM we need to register as a real lib. */ +#include +#include +#include +#include +#include + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +typedef struct +{ + int _errno; + void *twentybytes; +} libthreaddata_t; + +typedef struct +{ + int x; + int y; + int z; + void *tenbytes; + NXKey_t perthreadkey; /* if -1, no key obtained... */ + NXMutex_t *lock; +} libdata_t; + +int gLibId = -1; +void *gLibHandle = (void *) NULL; +rtag_t gAllocTag = (rtag_t) NULL; +NXMutex_t *gLibLock = (NXMutex_t *) NULL; + +/* internal library function prototypes... */ +int DisposeLibraryData(void *); +void DisposeThreadData(void *); +int GetOrSetUpData(int id, libdata_t **data, libthreaddata_t **threaddata); + + +int _NonAppStart(void *NLMHandle, + void *errorScreen, + const char *cmdLine, + const char *loadDirPath, + size_t uninitializedDataLength, + void *NLMFileHandle, + int (*readRoutineP)(int conn, + void *fileHandle, size_t offset, + size_t nbytes, + size_t *bytesRead, + void *buffer), + size_t customDataOffset, + size_t customDataSize, + int messageCount, + const char **messages) +{ + NX_LOCK_INFO_ALLOC(liblock, "Per-Application Data Lock", 0); + +#ifndef __GNUC__ +#pragma unused(cmdLine) +#pragma unused(loadDirPath) +#pragma unused(uninitializedDataLength) +#pragma unused(NLMFileHandle) +#pragma unused(readRoutineP) +#pragma unused(customDataOffset) +#pragma unused(customDataSize) +#pragma unused(messageCount) +#pragma unused(messages) +#endif + + /* + * Here we process our command line, post errors (to the error screen), + * perform initializations and anything else we need to do before being able + * to accept calls into us. If we succeed, we return non-zero and the NetWare + * Loader will leave us up, otherwise we fail to load and get dumped. + */ + gAllocTag = AllocateResourceTag(NLMHandle, + " memory allocations", + AllocSignature); + + if(!gAllocTag) { + OutputToScreen(errorScreen, "Unable to allocate resource tag for " + "library memory allocations.\n"); + return -1; + } + + gLibId = register_library(DisposeLibraryData); + + if(gLibId < -1) { + OutputToScreen(errorScreen, "Unable to register library with kernel.\n"); + return -1; + } + + gLibHandle = NLMHandle; + + gLibLock = NXMutexAlloc(0, 0, &liblock); + + if(!gLibLock) { + OutputToScreen(errorScreen, "Unable to allocate library data lock.\n"); + return -1; + } + + return 0; +} + +/* + * Here we clean up any resources we allocated. Resource tags is a big part + * of what we created, but NetWare doesn't ask us to free those. + */ +void _NonAppStop(void) +{ + (void) unregister_library(gLibId); + NXMutexFree(gLibLock); +} + +/* + * This function cannot be the first in the file for if the file is linked + * first, then the check-unload function's offset will be nlmname.nlm+0 + * which is how to tell that there isn't one. When the check function is + * first in the linked objects, it is ambiguous. For this reason, we will + * put it inside this file after the stop function. + * + * Here we check to see if it's alright to ourselves to be unloaded. If not, + * we return a non-zero value. Right now, there isn't any reason not to allow + * it. + */ +int _NonAppCheckUnload(void) +{ + return 0; +} + +int GetOrSetUpData(int id, libdata_t **appData, + libthreaddata_t **threadData) +{ + int err; + libdata_t *app_data; + libthreaddata_t *thread_data; + NXKey_t key; + NX_LOCK_INFO_ALLOC(liblock, "Application Data Lock", 0); + + err = 0; + thread_data = (libthreaddata_t *) NULL; + + /* + * Attempt to get our data for the application calling us. This is where we + * store whatever application-specific information we need to carry in + * support of calling applications. + */ + app_data = (libdata_t *) get_app_data(id); + + if(!app_data) { + /* + * This application hasn't called us before; set up application AND + * per-thread data. Of course, just in case a thread from this same + * application is calling us simultaneously, we better lock our application + * data-creation mutex. We also need to recheck for data after we acquire + * the lock because WE might be that other thread that was too late to + * create the data and the first thread in will have created it. + */ + NXLock(gLibLock); + + app_data = (libdata_t *) get_app_data(id); + if(!app_data) { + app_data = calloc(1, sizeof(libdata_t)); + + if(app_data) { + app_data->tenbytes = malloc(10); + app_data->lock = NXMutexAlloc(0, 0, &liblock); + + if(!app_data->tenbytes || !app_data->lock) { + if(app_data->lock) + NXMutexFree(app_data->lock); + free(app_data->tenbytes); + free(app_data); + app_data = (libdata_t *) NULL; + err = ENOMEM; + } + + if(app_data) { + /* + * Here we burn in the application data that we were trying to get + * by calling get_app_data(). Next time we call the first function, + * we'll get this data we're just now setting. We also go on here to + * establish the per-thread data for the calling thread, something + * we'll have to do on each application thread the first time + * it calls us. + */ + err = set_app_data(gLibId, app_data); + + if(err) { + if(app_data->lock) + NXMutexFree(app_data->lock); + free(app_data->tenbytes); + free(app_data); + app_data = (libdata_t *) NULL; + err = ENOMEM; + } + else { + /* create key for thread-specific data... */ + err = NXKeyCreate(DisposeThreadData, (void *) NULL, &key); + + if(err) /* (no more keys left?) */ + key = -1; + + app_data->perthreadkey = key; + } + } + } + } + + NXUnlock(gLibLock); + } + + if(app_data) { + key = app_data->perthreadkey; + + if(key != -1 /* couldn't create a key? no thread data */ + && !(err = NXKeyGetValue(key, (void **) &thread_data)) + && !thread_data) { + /* + * Allocate the per-thread data for the calling thread. Regardless of + * whether there was already application data or not, this may be the + * first call by a new thread. The fact that we allocation 20 bytes on + * a pointer is not very important, this just helps to demonstrate that + * we can have arbitrarily complex per-thread data. + */ + thread_data = malloc(sizeof(libthreaddata_t)); + + if(thread_data) { + thread_data->_errno = 0; + thread_data->twentybytes = malloc(20); + + if(!thread_data->twentybytes) { + free(thread_data); + thread_data = (libthreaddata_t *) NULL; + err = ENOMEM; + } + + err = NXKeySetValue(key, thread_data); + if(err) { + free(thread_data->twentybytes); + free(thread_data); + thread_data = (libthreaddata_t *) NULL; + } + } + } + } + + if(appData) + *appData = app_data; + + if(threadData) + *threadData = thread_data; + + return err; +} + +int DisposeLibraryData(void *data) +{ + if(data) { + void *tenbytes = ((libdata_t *) data)->tenbytes; + + free(tenbytes); + free(data); + } + + return 0; +} + +void DisposeThreadData(void *data) +{ + if(data) { + void *twentybytes = ((libthreaddata_t *) data)->twentybytes; + + free(twentybytes); + free(data); + } +} + +#else /* __NOVELL_LIBC__ */ +/* For native CLib-based NLM seems we can do a bit more simple. */ +#include + +int main(void) +{ + /* initialize any globals here... */ + + /* do this if any global initializing was done + SynchronizeStart(); + */ + ExitThread(TSR_THREAD, 0); + return 0; +} + +#endif /* __NOVELL_LIBC__ */ + +#else /* NETWARE */ + +#ifdef __POCC__ +# pragma warn(disable:2024) /* Disable warning #2024: Empty input file */ +#endif + +#endif /* NETWARE */ diff --git a/dependencies/cmcurl/lib/nwos.c b/dependencies/cmcurl/lib/nwos.c new file mode 100644 index 0000000..c6c22cc --- /dev/null +++ b/dependencies/cmcurl/lib/nwos.c @@ -0,0 +1,88 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef NETWARE /* Novell NetWare */ + +#ifdef __NOVELL_LIBC__ +/* For native LibC-based NLM we need to do nothing. */ +int netware_init(void) +{ + return 0; +} + +#else /* __NOVELL_LIBC__ */ + +/* For native CLib-based NLM we need to initialize the LONG namespace. */ +#include +#include +#include +/* Make the CLIB Ctx stuff link */ +#include +NETDB_DEFINE_CONTEXT +/* Make the CLIB Inet stuff link */ +#include +#include +NETINET_DEFINE_CONTEXT + +int netware_init(void) +{ + int rc = 0; + unsigned int myHandle = GetNLMHandle(); + /* import UnAugmentAsterisk dynamically for NW4.x compatibility */ + void (*pUnAugmentAsterisk)(int) = (void(*)(int)) + ImportSymbol(myHandle, "UnAugmentAsterisk"); + /* import UseAccurateCaseForPaths dynamically for NW3.x compatibility */ + void (*pUseAccurateCaseForPaths)(int) = (void(*)(int)) + ImportSymbol(myHandle, "UseAccurateCaseForPaths"); + if(pUnAugmentAsterisk) + pUnAugmentAsterisk(1); + if(pUseAccurateCaseForPaths) + pUseAccurateCaseForPaths(1); + UnimportSymbol(myHandle, "UnAugmentAsterisk"); + UnimportSymbol(myHandle, "UseAccurateCaseForPaths"); + /* set long name space */ + if((SetCurrentNameSpace(4) == 255)) { + rc = 1; + } + if((SetTargetNameSpace(4) == 255)) { + rc = rc + 2; + } + return rc; +} + +/* dummy function to satisfy newer prelude */ +int __init_environment(void) +{ + return 0; +} + +/* dummy function to satisfy newer prelude */ +int __deinit_environment(void) +{ + return 0; +} + +#endif /* __NOVELL_LIBC__ */ + +#endif /* NETWARE */ diff --git a/dependencies/cmcurl/lib/openldap.c b/dependencies/cmcurl/lib/openldap.c new file mode 100644 index 0000000..eeab2c7 --- /dev/null +++ b/dependencies/cmcurl/lib/openldap.c @@ -0,0 +1,758 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010, Howard Chu, + * Copyright (C) 2011 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_LDAP) && defined(USE_OPENLDAP) + +/* + * Notice that USE_OPENLDAP is only a source code selection switch. When + * libcurl is built with USE_OPENLDAP defined the libcurl source code that + * gets compiled is the code from openldap.c, otherwise the code that gets + * compiled is the code from ldap.c. + * + * When USE_OPENLDAP is defined a recent version of the OpenLDAP library + * might be required for compilation and runtime. In order to use ancient + * OpenLDAP library versions, USE_OPENLDAP shall not be defined. + */ + +#include + +#include "urldata.h" +#include +#include "sendf.h" +#include "vtls/vtls.h" +#include "transfer.h" +#include "curl_ldap.h" +#include "curl_base64.h" +#include "connect.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Uncommenting this will enable the built-in debug logging of the openldap + * library. The debug log level can be set using the CURL_OPENLDAP_TRACE + * environment variable. The debug output is written to stderr. + * + * The library supports the following debug flags: + * LDAP_DEBUG_NONE 0x0000 + * LDAP_DEBUG_TRACE 0x0001 + * LDAP_DEBUG_CONSTRUCT 0x0002 + * LDAP_DEBUG_DESTROY 0x0004 + * LDAP_DEBUG_PARAMETER 0x0008 + * LDAP_DEBUG_ANY 0xffff + * + * For example, use CURL_OPENLDAP_TRACE=0 for no debug, + * CURL_OPENLDAP_TRACE=2 for LDAP_DEBUG_CONSTRUCT messages only, + * CURL_OPENLDAP_TRACE=65535 for all debug message levels. + */ +/* #define CURL_OPENLDAP_DEBUG */ + +#ifndef _LDAP_PVT_H +extern int ldap_pvt_url_scheme2proto(const char *); +extern int ldap_init_fd(ber_socket_t fd, int proto, const char *url, + LDAP **ld); +#endif + +static CURLcode ldap_setup_connection(struct connectdata *conn); +static CURLcode ldap_do(struct connectdata *conn, bool *done); +static CURLcode ldap_done(struct connectdata *conn, CURLcode, bool); +static CURLcode ldap_connect(struct connectdata *conn, bool *done); +static CURLcode ldap_connecting(struct connectdata *conn, bool *done); +static CURLcode ldap_disconnect(struct connectdata *conn, bool dead); + +static Curl_recv ldap_recv; + +/* + * LDAP protocol handler. + */ + +const struct Curl_handler Curl_handler_ldap = { + "LDAP", /* scheme */ + ldap_setup_connection, /* setup_connection */ + ldap_do, /* do_it */ + ldap_done, /* done */ + ZERO_NULL, /* do_more */ + ldap_connect, /* connect_it */ + ldap_connecting, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ldap_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_LDAP, /* defport */ + CURLPROTO_LDAP, /* protocol */ + PROTOPT_NONE /* flags */ +}; + +#ifdef USE_SSL +/* + * LDAPS protocol handler. + */ + +const struct Curl_handler Curl_handler_ldaps = { + "LDAPS", /* scheme */ + ldap_setup_connection, /* setup_connection */ + ldap_do, /* do_it */ + ldap_done, /* done */ + ZERO_NULL, /* do_more */ + ldap_connect, /* connect_it */ + ldap_connecting, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ldap_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_LDAPS, /* defport */ + CURLPROTO_LDAP, /* protocol */ + PROTOPT_SSL /* flags */ +}; +#endif + +static const char *url_errs[] = { + "success", + "out of memory", + "bad parameter", + "unrecognized scheme", + "unbalanced delimiter", + "bad URL", + "bad host or port", + "bad or missing attributes", + "bad or missing scope", + "bad or missing filter", + "bad or missing extensions" +}; + +typedef struct ldapconninfo { + LDAP *ld; + Curl_recv *recv; /* for stacking SSL handler */ + Curl_send *send; + int proto; + int msgid; + bool ssldone; + bool sslinst; + bool didbind; +} ldapconninfo; + +typedef struct ldapreqinfo { + int msgid; + int nument; +} ldapreqinfo; + +static CURLcode ldap_setup_connection(struct connectdata *conn) +{ + ldapconninfo *li; + LDAPURLDesc *lud; + struct Curl_easy *data = conn->data; + int rc, proto; + CURLcode status; + + rc = ldap_url_parse(data->change.url, &lud); + if(rc != LDAP_URL_SUCCESS) { + const char *msg = "url parsing problem"; + status = CURLE_URL_MALFORMAT; + if(rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) { + if(rc == LDAP_URL_ERR_MEM) + status = CURLE_OUT_OF_MEMORY; + msg = url_errs[rc]; + } + failf(conn->data, "LDAP local: %s", msg); + return status; + } + proto = ldap_pvt_url_scheme2proto(lud->lud_scheme); + ldap_free_urldesc(lud); + + li = calloc(1, sizeof(ldapconninfo)); + if(!li) + return CURLE_OUT_OF_MEMORY; + li->proto = proto; + conn->proto.generic = li; + connkeep(conn, "OpenLDAP default"); + return CURLE_OK; +} + +#ifdef USE_SSL +static Sockbuf_IO ldapsb_tls; +#endif + +static CURLcode ldap_connect(struct connectdata *conn, bool *done) +{ + ldapconninfo *li = conn->proto.generic; + struct Curl_easy *data = conn->data; + int rc, proto = LDAP_VERSION3; + char hosturl[1024]; + char *ptr; + + (void)done; + + strcpy(hosturl, "ldap"); + ptr = hosturl + 4; + if(conn->handler->flags & PROTOPT_SSL) + *ptr++ = 's'; + msnprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d", + conn->host.name, conn->remote_port); + +#ifdef CURL_OPENLDAP_DEBUG + static int do_trace = 0; + const char *env = getenv("CURL_OPENLDAP_TRACE"); + do_trace = (env && strtol(env, NULL, 10) > 0); + if(do_trace) { + ldap_set_option(li->ld, LDAP_OPT_DEBUG_LEVEL, &do_trace); + } +#endif + + rc = ldap_init_fd(conn->sock[FIRSTSOCKET], li->proto, hosturl, &li->ld); + if(rc) { + failf(data, "LDAP local: Cannot connect to %s, %s", + hosturl, ldap_err2string(rc)); + return CURLE_COULDNT_CONNECT; + } + + ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto); + +#ifdef USE_SSL + if(conn->handler->flags & PROTOPT_SSL) { + CURLcode result; + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &li->ssldone); + if(result) + return result; + } +#endif + + return CURLE_OK; +} + +static CURLcode ldap_connecting(struct connectdata *conn, bool *done) +{ + ldapconninfo *li = conn->proto.generic; + struct Curl_easy *data = conn->data; + LDAPMessage *msg = NULL; + struct timeval tv = {0, 1}, *tvp; + int rc, err; + char *info = NULL; + +#ifdef USE_SSL + if(conn->handler->flags & PROTOPT_SSL) { + /* Is the SSL handshake complete yet? */ + if(!li->ssldone) { + CURLcode result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, + &li->ssldone); + if(result || !li->ssldone) + return result; + } + + /* Have we installed the libcurl SSL handlers into the sockbuf yet? */ + if(!li->sslinst) { + Sockbuf *sb; + ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb); + ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, conn); + li->sslinst = TRUE; + li->recv = conn->recv[FIRSTSOCKET]; + li->send = conn->send[FIRSTSOCKET]; + } + } +#endif + + tvp = &tv; + + retry: + if(!li->didbind) { + char *binddn; + struct berval passwd; + + if(conn->bits.user_passwd) { + binddn = conn->user; + passwd.bv_val = conn->passwd; + passwd.bv_len = strlen(passwd.bv_val); + } + else { + binddn = NULL; + passwd.bv_val = NULL; + passwd.bv_len = 0; + } + rc = ldap_sasl_bind(li->ld, binddn, LDAP_SASL_SIMPLE, &passwd, + NULL, NULL, &li->msgid); + if(rc) + return CURLE_LDAP_CANNOT_BIND; + li->didbind = TRUE; + if(tvp) + return CURLE_OK; + } + + rc = ldap_result(li->ld, li->msgid, LDAP_MSG_ONE, tvp, &msg); + if(rc < 0) { + failf(data, "LDAP local: bind ldap_result %s", ldap_err2string(rc)); + return CURLE_LDAP_CANNOT_BIND; + } + if(rc == 0) { + /* timed out */ + return CURLE_OK; + } + + rc = ldap_parse_result(li->ld, msg, &err, NULL, &info, NULL, NULL, 1); + if(rc) { + failf(data, "LDAP local: bind ldap_parse_result %s", ldap_err2string(rc)); + return CURLE_LDAP_CANNOT_BIND; + } + + /* Try to fallback to LDAPv2? */ + if(err == LDAP_PROTOCOL_ERROR) { + int proto; + ldap_get_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto); + if(proto == LDAP_VERSION3) { + if(info) { + ldap_memfree(info); + info = NULL; + } + proto = LDAP_VERSION2; + ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto); + li->didbind = FALSE; + goto retry; + } + } + + if(err) { + failf(data, "LDAP remote: bind failed %s %s", ldap_err2string(rc), + info ? info : ""); + if(info) + ldap_memfree(info); + return CURLE_LOGIN_DENIED; + } + + if(info) + ldap_memfree(info); + conn->recv[FIRSTSOCKET] = ldap_recv; + *done = TRUE; + + return CURLE_OK; +} + +static CURLcode ldap_disconnect(struct connectdata *conn, bool dead_connection) +{ + ldapconninfo *li = conn->proto.generic; + (void) dead_connection; + + if(li) { + if(li->ld) { + ldap_unbind_ext(li->ld, NULL, NULL); + li->ld = NULL; + } + conn->proto.generic = NULL; + free(li); + } + return CURLE_OK; +} + +static CURLcode ldap_do(struct connectdata *conn, bool *done) +{ + ldapconninfo *li = conn->proto.generic; + ldapreqinfo *lr; + CURLcode status = CURLE_OK; + int rc = 0; + LDAPURLDesc *ludp = NULL; + int msgid; + struct Curl_easy *data = conn->data; + + connkeep(conn, "OpenLDAP do"); + + infof(data, "LDAP local: %s\n", data->change.url); + + rc = ldap_url_parse(data->change.url, &ludp); + if(rc != LDAP_URL_SUCCESS) { + const char *msg = "url parsing problem"; + status = CURLE_URL_MALFORMAT; + if(rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) { + if(rc == LDAP_URL_ERR_MEM) + status = CURLE_OUT_OF_MEMORY; + msg = url_errs[rc]; + } + failf(conn->data, "LDAP local: %s", msg); + return status; + } + + rc = ldap_search_ext(li->ld, ludp->lud_dn, ludp->lud_scope, + ludp->lud_filter, ludp->lud_attrs, 0, + NULL, NULL, NULL, 0, &msgid); + ldap_free_urldesc(ludp); + if(rc != LDAP_SUCCESS) { + failf(data, "LDAP local: ldap_search_ext %s", ldap_err2string(rc)); + return CURLE_LDAP_SEARCH_FAILED; + } + lr = calloc(1, sizeof(ldapreqinfo)); + if(!lr) + return CURLE_OUT_OF_MEMORY; + lr->msgid = msgid; + data->req.protop = lr; + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); + *done = TRUE; + return CURLE_OK; +} + +static CURLcode ldap_done(struct connectdata *conn, CURLcode res, + bool premature) +{ + ldapreqinfo *lr = conn->data->req.protop; + + (void)res; + (void)premature; + + if(lr) { + /* if there was a search in progress, abandon it */ + if(lr->msgid) { + ldapconninfo *li = conn->proto.generic; + ldap_abandon_ext(li->ld, lr->msgid, NULL, NULL); + lr->msgid = 0; + } + conn->data->req.protop = NULL; + free(lr); + } + + return CURLE_OK; +} + +static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, + size_t len, CURLcode *err) +{ + ldapconninfo *li = conn->proto.generic; + struct Curl_easy *data = conn->data; + ldapreqinfo *lr = data->req.protop; + int rc, ret; + LDAPMessage *msg = NULL; + LDAPMessage *ent; + BerElement *ber = NULL; + struct timeval tv = {0, 1}; + + (void)len; + (void)buf; + (void)sockindex; + + rc = ldap_result(li->ld, lr->msgid, LDAP_MSG_RECEIVED, &tv, &msg); + if(rc < 0) { + failf(data, "LDAP local: search ldap_result %s", ldap_err2string(rc)); + *err = CURLE_RECV_ERROR; + return -1; + } + + *err = CURLE_AGAIN; + ret = -1; + + /* timed out */ + if(!msg) + return ret; + + for(ent = ldap_first_message(li->ld, msg); ent; + ent = ldap_next_message(li->ld, ent)) { + struct berval bv, *bvals; + int binary = 0, msgtype; + CURLcode writeerr; + + msgtype = ldap_msgtype(ent); + if(msgtype == LDAP_RES_SEARCH_RESULT) { + int code; + char *info = NULL; + rc = ldap_parse_result(li->ld, ent, &code, NULL, &info, NULL, NULL, 0); + if(rc) { + failf(data, "LDAP local: search ldap_parse_result %s", + ldap_err2string(rc)); + *err = CURLE_LDAP_SEARCH_FAILED; + } + else if(code && code != LDAP_SIZELIMIT_EXCEEDED) { + failf(data, "LDAP remote: search failed %s %s", ldap_err2string(rc), + info ? info : ""); + *err = CURLE_LDAP_SEARCH_FAILED; + } + else { + /* successful */ + if(code == LDAP_SIZELIMIT_EXCEEDED) + infof(data, "There are more than %d entries\n", lr->nument); + data->req.size = data->req.bytecount; + *err = CURLE_OK; + ret = 0; + } + lr->msgid = 0; + ldap_memfree(info); + break; + } + else if(msgtype != LDAP_RES_SEARCH_ENTRY) + continue; + + lr->nument++; + rc = ldap_get_dn_ber(li->ld, ent, &ber, &bv); + if(rc < 0) { + *err = CURLE_RECV_ERROR; + return -1; + } + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4); + if(writeerr) { + *err = writeerr; + return -1; + } + + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, + bv.bv_len); + if(writeerr) { + *err = writeerr; + return -1; + } + + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); + if(writeerr) { + *err = writeerr; + return -1; + } + data->req.bytecount += bv.bv_len + 5; + + for(rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, &bvals); + rc == LDAP_SUCCESS; + rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, &bvals)) { + int i; + + if(bv.bv_val == NULL) + break; + + if(bv.bv_len > 7 && !strncmp(bv.bv_val + bv.bv_len - 7, ";binary", 7)) + binary = 1; + else + binary = 0; + + if(bvals == NULL) { + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1); + if(writeerr) { + *err = writeerr; + return -1; + } + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, + bv.bv_len); + if(writeerr) { + *err = writeerr; + return -1; + } + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":\n", 2); + if(writeerr) { + *err = writeerr; + return -1; + } + data->req.bytecount += bv.bv_len + 3; + continue; + } + + for(i = 0; bvals[i].bv_val != NULL; i++) { + int binval = 0; + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1); + if(writeerr) { + *err = writeerr; + return -1; + } + + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, + bv.bv_len); + if(writeerr) { + *err = writeerr; + return -1; + } + + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":", 1); + if(writeerr) { + *err = writeerr; + return -1; + } + data->req.bytecount += bv.bv_len + 2; + + if(!binary) { + /* check for leading or trailing whitespace */ + if(ISSPACE(bvals[i].bv_val[0]) || + ISSPACE(bvals[i].bv_val[bvals[i].bv_len-1])) + binval = 1; + else { + /* check for unprintable characters */ + unsigned int j; + for(j = 0; jreq.bytecount += 2; + if(val_b64_sz > 0) { + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64, + val_b64_sz); + if(writeerr) { + *err = writeerr; + return -1; + } + free(val_b64); + data->req.bytecount += val_b64_sz; + } + } + else { + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)" ", 1); + if(writeerr) { + *err = writeerr; + return -1; + } + + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, bvals[i].bv_val, + bvals[i].bv_len); + if(writeerr) { + *err = writeerr; + return -1; + } + + data->req.bytecount += bvals[i].bv_len + 1; + } + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); + if(writeerr) { + *err = writeerr; + return -1; + } + + data->req.bytecount++; + } + ber_memfree(bvals); + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); + if(writeerr) { + *err = writeerr; + return -1; + } + data->req.bytecount++; + } + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); + if(writeerr) { + *err = writeerr; + return -1; + } + data->req.bytecount++; + ber_free(ber, 0); + } + ldap_msgfree(msg); + return ret; +} + +#ifdef USE_SSL +static int +ldapsb_tls_setup(Sockbuf_IO_Desc *sbiod, void *arg) +{ + sbiod->sbiod_pvt = arg; + return 0; +} + +static int +ldapsb_tls_remove(Sockbuf_IO_Desc *sbiod) +{ + sbiod->sbiod_pvt = NULL; + return 0; +} + +/* We don't need to do anything because libcurl does it already */ +static int +ldapsb_tls_close(Sockbuf_IO_Desc *sbiod) +{ + (void)sbiod; + return 0; +} + +static int +ldapsb_tls_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg) +{ + (void)arg; + if(opt == LBER_SB_OPT_DATA_READY) { + struct connectdata *conn = sbiod->sbiod_pvt; + return Curl_ssl_data_pending(conn, FIRSTSOCKET); + } + return 0; +} + +static ber_slen_t +ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) +{ + struct connectdata *conn = sbiod->sbiod_pvt; + ldapconninfo *li = conn->proto.generic; + ber_slen_t ret; + CURLcode err = CURLE_RECV_ERROR; + + ret = (li->recv)(conn, FIRSTSOCKET, buf, len, &err); + if(ret < 0 && err == CURLE_AGAIN) { + SET_SOCKERRNO(EWOULDBLOCK); + } + return ret; +} + +static ber_slen_t +ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) +{ + struct connectdata *conn = sbiod->sbiod_pvt; + ldapconninfo *li = conn->proto.generic; + ber_slen_t ret; + CURLcode err = CURLE_SEND_ERROR; + + ret = (li->send)(conn, FIRSTSOCKET, buf, len, &err); + if(ret < 0 && err == CURLE_AGAIN) { + SET_SOCKERRNO(EWOULDBLOCK); + } + return ret; +} + +static Sockbuf_IO ldapsb_tls = +{ + ldapsb_tls_setup, + ldapsb_tls_remove, + ldapsb_tls_ctrl, + ldapsb_tls_read, + ldapsb_tls_write, + ldapsb_tls_close +}; +#endif /* USE_SSL */ + +#endif /* !CURL_DISABLE_LDAP && USE_OPENLDAP */ diff --git a/dependencies/cmcurl/lib/parsedate.c b/dependencies/cmcurl/lib/parsedate.c new file mode 100644 index 0000000..7ae5eb8 --- /dev/null +++ b/dependencies/cmcurl/lib/parsedate.c @@ -0,0 +1,607 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +/* + A brief summary of the date string formats this parser groks: + + RFC 2616 3.3.1 + + Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 + Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 + Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format + + we support dates without week day name: + + 06 Nov 1994 08:49:37 GMT + 06-Nov-94 08:49:37 GMT + Nov 6 08:49:37 1994 + + without the time zone: + + 06 Nov 1994 08:49:37 + 06-Nov-94 08:49:37 + + weird order: + + 1994 Nov 6 08:49:37 (GNU date fails) + GMT 08:49:37 06-Nov-94 Sunday + 94 6 Nov 08:49:37 (GNU date fails) + + time left out: + + 1994 Nov 6 + 06-Nov-94 + Sun Nov 6 94 + + unusual separators: + + 1994.Nov.6 + Sun/Nov/6/94/GMT + + commonly used time zone names: + + Sun, 06 Nov 1994 08:49:37 CET + 06 Nov 1994 08:49:37 EST + + time zones specified using RFC822 style: + + Sun, 12 Sep 2004 15:05:58 -0700 + Sat, 11 Sep 2004 21:32:11 +0200 + + compact numerical date strings: + + 20040912 15:05:58 -0700 + 20040911 +0200 + +*/ + +#include "curl_setup.h" + +#include + +#include +#include "strcase.h" +#include "warnless.h" +#include "parsedate.h" + +/* + * parsedate() + * + * Returns: + * + * PARSEDATE_OK - a fine conversion + * PARSEDATE_FAIL - failed to convert + * PARSEDATE_LATER - time overflow at the far end of time_t + * PARSEDATE_SOONER - time underflow at the low end of time_t + */ + +static int parsedate(const char *date, time_t *output); + +#define PARSEDATE_OK 0 +#define PARSEDATE_FAIL -1 +#define PARSEDATE_LATER 1 +#define PARSEDATE_SOONER 2 + +#ifndef CURL_DISABLE_PARSEDATE + +const char * const Curl_wkday[] = +{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; +static const char * const weekday[] = +{ "Monday", "Tuesday", "Wednesday", "Thursday", + "Friday", "Saturday", "Sunday" }; +const char * const Curl_month[]= +{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + +struct tzinfo { + char name[5]; + int offset; /* +/- in minutes */ +}; + +/* Here's a bunch of frequently used time zone names. These were supported + by the old getdate parser. */ +#define tDAYZONE -60 /* offset for daylight savings time */ +static const struct tzinfo tz[]= { + {"GMT", 0}, /* Greenwich Mean */ + {"UT", 0}, /* Universal Time */ + {"UTC", 0}, /* Universal (Coordinated) */ + {"WET", 0}, /* Western European */ + {"BST", 0 tDAYZONE}, /* British Summer */ + {"WAT", 60}, /* West Africa */ + {"AST", 240}, /* Atlantic Standard */ + {"ADT", 240 tDAYZONE}, /* Atlantic Daylight */ + {"EST", 300}, /* Eastern Standard */ + {"EDT", 300 tDAYZONE}, /* Eastern Daylight */ + {"CST", 360}, /* Central Standard */ + {"CDT", 360 tDAYZONE}, /* Central Daylight */ + {"MST", 420}, /* Mountain Standard */ + {"MDT", 420 tDAYZONE}, /* Mountain Daylight */ + {"PST", 480}, /* Pacific Standard */ + {"PDT", 480 tDAYZONE}, /* Pacific Daylight */ + {"YST", 540}, /* Yukon Standard */ + {"YDT", 540 tDAYZONE}, /* Yukon Daylight */ + {"HST", 600}, /* Hawaii Standard */ + {"HDT", 600 tDAYZONE}, /* Hawaii Daylight */ + {"CAT", 600}, /* Central Alaska */ + {"AHST", 600}, /* Alaska-Hawaii Standard */ + {"NT", 660}, /* Nome */ + {"IDLW", 720}, /* International Date Line West */ + {"CET", -60}, /* Central European */ + {"MET", -60}, /* Middle European */ + {"MEWT", -60}, /* Middle European Winter */ + {"MEST", -60 tDAYZONE}, /* Middle European Summer */ + {"CEST", -60 tDAYZONE}, /* Central European Summer */ + {"MESZ", -60 tDAYZONE}, /* Middle European Summer */ + {"FWT", -60}, /* French Winter */ + {"FST", -60 tDAYZONE}, /* French Summer */ + {"EET", -120}, /* Eastern Europe, USSR Zone 1 */ + {"WAST", -420}, /* West Australian Standard */ + {"WADT", -420 tDAYZONE}, /* West Australian Daylight */ + {"CCT", -480}, /* China Coast, USSR Zone 7 */ + {"JST", -540}, /* Japan Standard, USSR Zone 8 */ + {"EAST", -600}, /* Eastern Australian Standard */ + {"EADT", -600 tDAYZONE}, /* Eastern Australian Daylight */ + {"GST", -600}, /* Guam Standard, USSR Zone 9 */ + {"NZT", -720}, /* New Zealand */ + {"NZST", -720}, /* New Zealand Standard */ + {"NZDT", -720 tDAYZONE}, /* New Zealand Daylight */ + {"IDLE", -720}, /* International Date Line East */ + /* Next up: Military timezone names. RFC822 allowed these, but (as noted in + RFC 1123) had their signs wrong. Here we use the correct signs to match + actual military usage. + */ + {"A", 1 * 60}, /* Alpha */ + {"B", 2 * 60}, /* Bravo */ + {"C", 3 * 60}, /* Charlie */ + {"D", 4 * 60}, /* Delta */ + {"E", 5 * 60}, /* Echo */ + {"F", 6 * 60}, /* Foxtrot */ + {"G", 7 * 60}, /* Golf */ + {"H", 8 * 60}, /* Hotel */ + {"I", 9 * 60}, /* India */ + /* "J", Juliet is not used as a timezone, to indicate the observer's local + time */ + {"K", 10 * 60}, /* Kilo */ + {"L", 11 * 60}, /* Lima */ + {"M", 12 * 60}, /* Mike */ + {"N", -1 * 60}, /* November */ + {"O", -2 * 60}, /* Oscar */ + {"P", -3 * 60}, /* Papa */ + {"Q", -4 * 60}, /* Quebec */ + {"R", -5 * 60}, /* Romeo */ + {"S", -6 * 60}, /* Sierra */ + {"T", -7 * 60}, /* Tango */ + {"U", -8 * 60}, /* Uniform */ + {"V", -9 * 60}, /* Victor */ + {"W", -10 * 60}, /* Whiskey */ + {"X", -11 * 60}, /* X-ray */ + {"Y", -12 * 60}, /* Yankee */ + {"Z", 0}, /* Zulu, zero meridian, a.k.a. UTC */ +}; + +/* returns: + -1 no day + 0 monday - 6 sunday +*/ + +static int checkday(const char *check, size_t len) +{ + int i; + const char * const *what; + bool found = FALSE; + if(len > 3) + what = &weekday[0]; + else + what = &Curl_wkday[0]; + for(i = 0; i<7; i++) { + if(strcasecompare(check, what[0])) { + found = TRUE; + break; + } + what++; + } + return found?i:-1; +} + +static int checkmonth(const char *check) +{ + int i; + const char * const *what; + bool found = FALSE; + + what = &Curl_month[0]; + for(i = 0; i<12; i++) { + if(strcasecompare(check, what[0])) { + found = TRUE; + break; + } + what++; + } + return found?i:-1; /* return the offset or -1, no real offset is -1 */ +} + +/* return the time zone offset between GMT and the input one, in number + of seconds or -1 if the timezone wasn't found/legal */ + +static int checktz(const char *check) +{ + unsigned int i; + const struct tzinfo *what; + bool found = FALSE; + + what = tz; + for(i = 0; i< sizeof(tz)/sizeof(tz[0]); i++) { + if(strcasecompare(check, what->name)) { + found = TRUE; + break; + } + what++; + } + return found?what->offset*60:-1; +} + +static void skip(const char **date) +{ + /* skip everything that aren't letters or digits */ + while(**date && !ISALNUM(**date)) + (*date)++; +} + +enum assume { + DATE_MDAY, + DATE_YEAR, + DATE_TIME +}; + +/* this is a clone of 'struct tm' but with all fields we don't need or use + cut out */ +struct my_tm { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; /* full year */ +}; + +/* struct tm to time since epoch in GMT time zone. + * This is similar to the standard mktime function but for GMT only, and + * doesn't suffer from the various bugs and portability problems that + * some systems' implementations have. + * + * Returns 0 on success, otherwise non-zero. + */ +static void my_timegm(struct my_tm *tm, time_t *t) +{ + static const int month_days_cumulative [12] = + { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; + int month, year, leap_days; + + year = tm->tm_year; + month = tm->tm_mon; + if(month < 0) { + year += (11 - month) / 12; + month = 11 - (11 - month) % 12; + } + else if(month >= 12) { + year -= month / 12; + month = month % 12; + } + + leap_days = year - (tm->tm_mon <= 1); + leap_days = ((leap_days / 4) - (leap_days / 100) + (leap_days / 400) + - (1969 / 4) + (1969 / 100) - (1969 / 400)); + + *t = ((((time_t) (year - 1970) * 365 + + leap_days + month_days_cumulative[month] + tm->tm_mday - 1) * 24 + + tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec; +} + +/* + * parsedate() + * + * Returns: + * + * PARSEDATE_OK - a fine conversion + * PARSEDATE_FAIL - failed to convert + * PARSEDATE_LATER - time overflow at the far end of time_t + * PARSEDATE_SOONER - time underflow at the low end of time_t + */ + +static int parsedate(const char *date, time_t *output) +{ + time_t t = 0; + int wdaynum = -1; /* day of the week number, 0-6 (mon-sun) */ + int monnum = -1; /* month of the year number, 0-11 */ + int mdaynum = -1; /* day of month, 1 - 31 */ + int hournum = -1; + int minnum = -1; + int secnum = -1; + int yearnum = -1; + int tzoff = -1; + struct my_tm tm; + enum assume dignext = DATE_MDAY; + const char *indate = date; /* save the original pointer */ + int part = 0; /* max 6 parts */ + + while(*date && (part < 6)) { + bool found = FALSE; + + skip(&date); + + if(ISALPHA(*date)) { + /* a name coming up */ + char buf[32]=""; + size_t len; + if(sscanf(date, "%31[ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz]", buf)) + len = strlen(buf); + else + len = 0; + + if(wdaynum == -1) { + wdaynum = checkday(buf, len); + if(wdaynum != -1) + found = TRUE; + } + if(!found && (monnum == -1)) { + monnum = checkmonth(buf); + if(monnum != -1) + found = TRUE; + } + + if(!found && (tzoff == -1)) { + /* this just must be a time zone string */ + tzoff = checktz(buf); + if(tzoff != -1) + found = TRUE; + } + + if(!found) + return PARSEDATE_FAIL; /* bad string */ + + date += len; + } + else if(ISDIGIT(*date)) { + /* a digit */ + int val; + char *end; + int len = 0; + if((secnum == -1) && + (3 == sscanf(date, "%02d:%02d:%02d%n", + &hournum, &minnum, &secnum, &len))) { + /* time stamp! */ + date += len; + } + else if((secnum == -1) && + (2 == sscanf(date, "%02d:%02d%n", &hournum, &minnum, &len))) { + /* time stamp without seconds */ + date += len; + secnum = 0; + } + else { + long lval; + int error; + int old_errno; + + old_errno = errno; + errno = 0; + lval = strtol(date, &end, 10); + error = errno; + if(errno != old_errno) + errno = old_errno; + + if(error) + return PARSEDATE_FAIL; + +#if LONG_MAX != INT_MAX + if((lval > (long)INT_MAX) || (lval < (long)INT_MIN)) + return PARSEDATE_FAIL; +#endif + + val = curlx_sltosi(lval); + + if((tzoff == -1) && + ((end - date) == 4) && + (val <= 1400) && + (indate< date) && + ((date[-1] == '+' || date[-1] == '-'))) { + /* four digits and a value less than or equal to 1400 (to take into + account all sorts of funny time zone diffs) and it is preceded + with a plus or minus. This is a time zone indication. 1400 is + picked since +1300 is frequently used and +1400 is mentioned as + an edge number in the document "ISO C 200X Proposal: Timezone + Functions" at http://david.tribble.com/text/c0xtimezone.html If + anyone has a more authoritative source for the exact maximum time + zone offsets, please speak up! */ + found = TRUE; + tzoff = (val/100 * 60 + val%100)*60; + + /* the + and - prefix indicates the local time compared to GMT, + this we need their reversed math to get what we want */ + tzoff = date[-1]=='+'?-tzoff:tzoff; + } + + if(((end - date) == 8) && + (yearnum == -1) && + (monnum == -1) && + (mdaynum == -1)) { + /* 8 digits, no year, month or day yet. This is YYYYMMDD */ + found = TRUE; + yearnum = val/10000; + monnum = (val%10000)/100-1; /* month is 0 - 11 */ + mdaynum = val%100; + } + + if(!found && (dignext == DATE_MDAY) && (mdaynum == -1)) { + if((val > 0) && (val<32)) { + mdaynum = val; + found = TRUE; + } + dignext = DATE_YEAR; + } + + if(!found && (dignext == DATE_YEAR) && (yearnum == -1)) { + yearnum = val; + found = TRUE; + if(yearnum < 100) { + if(yearnum > 70) + yearnum += 1900; + else + yearnum += 2000; + } + if(mdaynum == -1) + dignext = DATE_MDAY; + } + + if(!found) + return PARSEDATE_FAIL; + + date = end; + } + } + + part++; + } + + if(-1 == secnum) + secnum = minnum = hournum = 0; /* no time, make it zero */ + + if((-1 == mdaynum) || + (-1 == monnum) || + (-1 == yearnum)) + /* lacks vital info, fail */ + return PARSEDATE_FAIL; + +#ifdef HAVE_TIME_T_UNSIGNED + if(yearnum < 1970) { + /* only positive numbers cannot return earlier */ + *output = TIME_T_MIN; + return PARSEDATE_SOONER; + } +#endif + +#if (SIZEOF_TIME_T < 5) + +#ifdef HAVE_TIME_T_UNSIGNED + /* an unsigned 32 bit time_t can only hold dates to 2106 */ + if(yearnum > 2105) { + *output = TIME_T_MAX; + return PARSEDATE_LATER; + } +#else + /* a signed 32 bit time_t can only hold dates to the beginning of 2038 */ + if(yearnum > 2037) { + *output = TIME_T_MAX; + return PARSEDATE_LATER; + } + if(yearnum < 1903) { + *output = TIME_T_MIN; + return PARSEDATE_SOONER; + } +#endif + +#else + /* The Gregorian calendar was introduced 1582 */ + if(yearnum < 1583) + return PARSEDATE_FAIL; +#endif + + if((mdaynum > 31) || (monnum > 11) || + (hournum > 23) || (minnum > 59) || (secnum > 60)) + return PARSEDATE_FAIL; /* clearly an illegal date */ + + tm.tm_sec = secnum; + tm.tm_min = minnum; + tm.tm_hour = hournum; + tm.tm_mday = mdaynum; + tm.tm_mon = monnum; + tm.tm_year = yearnum; + + /* my_timegm() returns a time_t. time_t is often 32 bits, sometimes even on + architectures that feature 64 bit 'long' but ultimately time_t is the + correct data type to use. + */ + my_timegm(&tm, &t); + + /* Add the time zone diff between local time zone and GMT. */ + if(tzoff == -1) + tzoff = 0; + + if((tzoff > 0) && (t > TIME_T_MAX - tzoff)) { + *output = TIME_T_MAX; + return PARSEDATE_LATER; /* time_t overflow */ + } + + t += tzoff; + + *output = t; + + return PARSEDATE_OK; +} +#else +/* disabled */ +static int parsedate(const char *date, time_t *output) +{ + (void)date; + *output = 0; + return PARSEDATE_OK; /* a lie */ +} +#endif + +time_t curl_getdate(const char *p, const time_t *now) +{ + time_t parsed = -1; + int rc = parsedate(p, &parsed); + (void)now; /* legacy argument from the past that we ignore */ + + if(rc == PARSEDATE_OK) { + if(parsed == -1) + /* avoid returning -1 for a working scenario */ + parsed++; + return parsed; + } + /* everything else is fail */ + return -1; +} + +/* + * Curl_gmtime() is a gmtime() replacement for portability. Do not use the + * gmtime_r() or gmtime() functions anywhere else but here. + * + */ + +CURLcode Curl_gmtime(time_t intime, struct tm *store) +{ + const struct tm *tm; +#ifdef HAVE_GMTIME_R + /* thread-safe version */ + tm = (struct tm *)gmtime_r(&intime, store); +#else + tm = gmtime(&intime); + if(tm) + *store = *tm; /* copy the pointed struct to the local copy */ +#endif + + if(!tm) + return CURLE_BAD_FUNCTION_ARGUMENT; + return CURLE_OK; +} diff --git a/dependencies/cmcurl/lib/parsedate.h b/dependencies/cmcurl/lib/parsedate.h new file mode 100644 index 0000000..8dc3b90 --- /dev/null +++ b/dependencies/cmcurl/lib/parsedate.h @@ -0,0 +1,30 @@ +#ifndef HEADER_CURL_PARSEDATE_H +#define HEADER_CURL_PARSEDATE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +extern const char * const Curl_wkday[7]; +extern const char * const Curl_month[12]; + +CURLcode Curl_gmtime(time_t intime, struct tm *store); + +#endif /* HEADER_CURL_PARSEDATE_H */ diff --git a/dependencies/cmcurl/lib/pingpong.c b/dependencies/cmcurl/lib/pingpong.c new file mode 100644 index 0000000..e9568ee --- /dev/null +++ b/dependencies/cmcurl/lib/pingpong.c @@ -0,0 +1,522 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * 'pingpong' is for generic back-and-forth support functions used by FTP, + * IMAP, POP3, SMTP and whatever more that likes them. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "urldata.h" +#include "sendf.h" +#include "select.h" +#include "progress.h" +#include "speedcheck.h" +#include "pingpong.h" +#include "multiif.h" +#include "non-ascii.h" +#include "vtls/vtls.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#ifdef USE_PINGPONG + +/* Returns timeout in ms. 0 or negative number means the timeout has already + triggered */ +time_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting) +{ + struct connectdata *conn = pp->conn; + struct Curl_easy *data = conn->data; + time_t timeout_ms; /* in milliseconds */ + long response_time = (data->set.server_response_timeout)? + data->set.server_response_timeout: pp->response_time; + + /* if CURLOPT_SERVER_RESPONSE_TIMEOUT is set, use that to determine + remaining time, or use pp->response because SERVER_RESPONSE_TIMEOUT is + supposed to govern the response for any given server response, not for + the time from connect to the given server response. */ + + /* Without a requested timeout, we only wait 'response_time' seconds for the + full response to arrive before we bail out */ + timeout_ms = response_time - + Curl_timediff(Curl_now(), pp->response); /* spent time */ + + if(data->set.timeout && !disconnecting) { + /* if timeout is requested, find out how much remaining time we have */ + time_t timeout2_ms = data->set.timeout - /* timeout time */ + Curl_timediff(Curl_now(), conn->now); /* spent time */ + + /* pick the lowest number */ + timeout_ms = CURLMIN(timeout_ms, timeout2_ms); + } + + return timeout_ms; +} + +/* + * Curl_pp_statemach() + */ +CURLcode Curl_pp_statemach(struct pingpong *pp, bool block, + bool disconnecting) +{ + struct connectdata *conn = pp->conn; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + int rc; + time_t interval_ms; + time_t timeout_ms = Curl_pp_state_timeout(pp, disconnecting); + struct Curl_easy *data = conn->data; + CURLcode result = CURLE_OK; + + if(timeout_ms <= 0) { + failf(data, "server response timeout"); + return CURLE_OPERATION_TIMEDOUT; /* already too little time */ + } + + if(block) { + interval_ms = 1000; /* use 1 second timeout intervals */ + if(timeout_ms < interval_ms) + interval_ms = timeout_ms; + } + else + interval_ms = 0; /* immediate */ + + if(Curl_ssl_data_pending(conn, FIRSTSOCKET)) + rc = 1; + else if(Curl_pp_moredata(pp)) + /* We are receiving and there is data in the cache so just read it */ + rc = 1; + else if(!pp->sendleft && Curl_ssl_data_pending(conn, FIRSTSOCKET)) + /* We are receiving and there is data ready in the SSL library */ + rc = 1; + else + rc = Curl_socket_check(pp->sendleft?CURL_SOCKET_BAD:sock, /* reading */ + CURL_SOCKET_BAD, + pp->sendleft?sock:CURL_SOCKET_BAD, /* writing */ + interval_ms); + + if(block) { + /* if we didn't wait, we don't have to spend time on this now */ + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + else + result = Curl_speedcheck(data, Curl_now()); + + if(result) + return result; + } + + if(rc == -1) { + failf(data, "select/poll error"); + result = CURLE_OUT_OF_MEMORY; + } + else if(rc) + result = pp->statemach_act(conn); + + return result; +} + +/* initialize stuff to prepare for reading a fresh new response */ +void Curl_pp_init(struct pingpong *pp) +{ + struct connectdata *conn = pp->conn; + pp->nread_resp = 0; + pp->linestart_resp = conn->data->state.buffer; + pp->pending_resp = TRUE; + pp->response = Curl_now(); /* start response time-out now! */ +} + + + +/*********************************************************************** + * + * Curl_pp_vsendf() + * + * Send the formatted string as a command to a pingpong server. Note that + * the string should not have any CRLF appended, as this function will + * append the necessary things itself. + * + * made to never block + */ +CURLcode Curl_pp_vsendf(struct pingpong *pp, + const char *fmt, + va_list args) +{ + ssize_t bytes_written; + size_t write_len; + char *fmt_crlf; + char *s; + CURLcode result; + struct connectdata *conn = pp->conn; + struct Curl_easy *data; + +#ifdef HAVE_GSSAPI + enum protection_level data_sec; +#endif + + DEBUGASSERT(pp->sendleft == 0); + DEBUGASSERT(pp->sendsize == 0); + DEBUGASSERT(pp->sendthis == NULL); + + if(!conn) + /* can't send without a connection! */ + return CURLE_SEND_ERROR; + + data = conn->data; + + fmt_crlf = aprintf("%s\r\n", fmt); /* append a trailing CRLF */ + if(!fmt_crlf) + return CURLE_OUT_OF_MEMORY; + + s = vaprintf(fmt_crlf, args); /* trailing CRLF appended */ + free(fmt_crlf); + if(!s) + return CURLE_OUT_OF_MEMORY; + + bytes_written = 0; + write_len = strlen(s); + + Curl_pp_init(pp); + + result = Curl_convert_to_network(data, s, write_len); + /* Curl_convert_to_network calls failf if unsuccessful */ + if(result) { + free(s); + return result; + } + +#ifdef HAVE_GSSAPI + conn->data_prot = PROT_CMD; +#endif + result = Curl_write(conn, conn->sock[FIRSTSOCKET], s, write_len, + &bytes_written); +#ifdef HAVE_GSSAPI + data_sec = conn->data_prot; + DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST); + conn->data_prot = data_sec; +#endif + + if(result) { + free(s); + return result; + } + + if(conn->data->set.verbose) + Curl_debug(conn->data, CURLINFO_HEADER_OUT, s, (size_t)bytes_written); + + if(bytes_written != (ssize_t)write_len) { + /* the whole chunk was not sent, keep it around and adjust sizes */ + pp->sendthis = s; + pp->sendsize = write_len; + pp->sendleft = write_len - bytes_written; + } + else { + free(s); + pp->sendthis = NULL; + pp->sendleft = pp->sendsize = 0; + pp->response = Curl_now(); + } + + return CURLE_OK; +} + + +/*********************************************************************** + * + * Curl_pp_sendf() + * + * Send the formatted string as a command to a pingpong server. Note that + * the string should not have any CRLF appended, as this function will + * append the necessary things itself. + * + * made to never block + */ +CURLcode Curl_pp_sendf(struct pingpong *pp, + const char *fmt, ...) +{ + CURLcode result; + va_list ap; + va_start(ap, fmt); + + result = Curl_pp_vsendf(pp, fmt, ap); + + va_end(ap); + + return result; +} + +/* + * Curl_pp_readresp() + * + * Reads a piece of a server response. + */ +CURLcode Curl_pp_readresp(curl_socket_t sockfd, + struct pingpong *pp, + int *code, /* return the server code if done */ + size_t *size) /* size of the response */ +{ + ssize_t perline; /* count bytes per line */ + bool keepon = TRUE; + ssize_t gotbytes; + char *ptr; + struct connectdata *conn = pp->conn; + struct Curl_easy *data = conn->data; + char * const buf = data->state.buffer; + CURLcode result = CURLE_OK; + + *code = 0; /* 0 for errors or not done */ + *size = 0; + + ptr = buf + pp->nread_resp; + + /* number of bytes in the current line, so far */ + perline = (ssize_t)(ptr-pp->linestart_resp); + + while((pp->nread_resp < (size_t)data->set.buffer_size) && + (keepon && !result)) { + + if(pp->cache) { + /* we had data in the "cache", copy that instead of doing an actual + * read + * + * pp->cache_size is cast to ssize_t here. This should be safe, because + * it would have been populated with something of size int to begin + * with, even though its datatype may be larger than an int. + */ + if((ptr + pp->cache_size) > (buf + data->set.buffer_size + 1)) { + failf(data, "cached response data too big to handle"); + return CURLE_RECV_ERROR; + } + memcpy(ptr, pp->cache, pp->cache_size); + gotbytes = (ssize_t)pp->cache_size; + free(pp->cache); /* free the cache */ + pp->cache = NULL; /* clear the pointer */ + pp->cache_size = 0; /* zero the size just in case */ + } + else { +#ifdef HAVE_GSSAPI + enum protection_level prot = conn->data_prot; + conn->data_prot = PROT_CLEAR; +#endif + DEBUGASSERT((ptr + data->set.buffer_size - pp->nread_resp) <= + (buf + data->set.buffer_size + 1)); + result = Curl_read(conn, sockfd, ptr, + data->set.buffer_size - pp->nread_resp, + &gotbytes); +#ifdef HAVE_GSSAPI + DEBUGASSERT(prot > PROT_NONE && prot < PROT_LAST); + conn->data_prot = prot; +#endif + if(result == CURLE_AGAIN) + return CURLE_OK; /* return */ + + if(!result && (gotbytes > 0)) + /* convert from the network encoding */ + result = Curl_convert_from_network(data, ptr, gotbytes); + /* Curl_convert_from_network calls failf if unsuccessful */ + + if(result) + /* Set outer result variable to this error. */ + keepon = FALSE; + } + + if(!keepon) + ; + else if(gotbytes <= 0) { + keepon = FALSE; + result = CURLE_RECV_ERROR; + failf(data, "response reading failed"); + } + else { + /* we got a whole chunk of data, which can be anything from one + * byte to a set of lines and possible just a piece of the last + * line */ + ssize_t i; + ssize_t clipamount = 0; + bool restart = FALSE; + + data->req.headerbytecount += (long)gotbytes; + + pp->nread_resp += gotbytes; + for(i = 0; i < gotbytes; ptr++, i++) { + perline++; + if(*ptr == '\n') { + /* a newline is CRLF in pp-talk, so the CR is ignored as + the line isn't really terminated until the LF comes */ + + /* output debug output if that is requested */ +#ifdef HAVE_GSSAPI + if(!conn->sec_complete) +#endif + if(data->set.verbose) + Curl_debug(data, CURLINFO_HEADER_IN, + pp->linestart_resp, (size_t)perline); + + /* + * We pass all response-lines to the callback function registered + * for "headers". The response lines can be seen as a kind of + * headers. + */ + result = Curl_client_write(conn, CLIENTWRITE_HEADER, + pp->linestart_resp, perline); + if(result) + return result; + + if(pp->endofresp(conn, pp->linestart_resp, perline, code)) { + /* This is the end of the last line, copy the last line to the + start of the buffer and zero terminate, for old times sake */ + size_t n = ptr - pp->linestart_resp; + memmove(buf, pp->linestart_resp, n); + buf[n] = 0; /* zero terminate */ + keepon = FALSE; + pp->linestart_resp = ptr + 1; /* advance pointer */ + i++; /* skip this before getting out */ + + *size = pp->nread_resp; /* size of the response */ + pp->nread_resp = 0; /* restart */ + break; + } + perline = 0; /* line starts over here */ + pp->linestart_resp = ptr + 1; + } + } + + if(!keepon && (i != gotbytes)) { + /* We found the end of the response lines, but we didn't parse the + full chunk of data we have read from the server. We therefore need + to store the rest of the data to be checked on the next invoke as + it may actually contain another end of response already! */ + clipamount = gotbytes - i; + restart = TRUE; + DEBUGF(infof(data, "Curl_pp_readresp_ %d bytes of trailing " + "server response left\n", + (int)clipamount)); + } + else if(keepon) { + + if((perline == gotbytes) && (gotbytes > data->set.buffer_size/2)) { + /* We got an excessive line without newlines and we need to deal + with it. We keep the first bytes of the line then we throw + away the rest. */ + infof(data, "Excessive server response line length received, " + "%zd bytes. Stripping\n", gotbytes); + restart = TRUE; + + /* we keep 40 bytes since all our pingpong protocols are only + interested in the first piece */ + clipamount = 40; + } + else if(pp->nread_resp > (size_t)data->set.buffer_size/2) { + /* We got a large chunk of data and there's potentially still + trailing data to take care of, so we put any such part in the + "cache", clear the buffer to make space and restart. */ + clipamount = perline; + restart = TRUE; + } + } + else if(i == gotbytes) + restart = TRUE; + + if(clipamount) { + pp->cache_size = clipamount; + pp->cache = malloc(pp->cache_size); + if(pp->cache) + memcpy(pp->cache, pp->linestart_resp, pp->cache_size); + else + return CURLE_OUT_OF_MEMORY; + } + if(restart) { + /* now reset a few variables to start over nicely from the start of + the big buffer */ + pp->nread_resp = 0; /* start over from scratch in the buffer */ + ptr = pp->linestart_resp = buf; + perline = 0; + } + + } /* there was data */ + + } /* while there's buffer left and loop is requested */ + + pp->pending_resp = FALSE; + + return result; +} + +int Curl_pp_getsock(struct pingpong *pp, + curl_socket_t *socks, + int numsocks) +{ + struct connectdata *conn = pp->conn; + + if(!numsocks) + return GETSOCK_BLANK; + + socks[0] = conn->sock[FIRSTSOCKET]; + + if(pp->sendleft) { + /* write mode */ + return GETSOCK_WRITESOCK(0); + } + + /* read mode */ + return GETSOCK_READSOCK(0); +} + +CURLcode Curl_pp_flushsend(struct pingpong *pp) +{ + /* we have a piece of a command still left to send */ + struct connectdata *conn = pp->conn; + ssize_t written; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + CURLcode result = Curl_write(conn, sock, pp->sendthis + pp->sendsize - + pp->sendleft, pp->sendleft, &written); + if(result) + return result; + + if(written != (ssize_t)pp->sendleft) { + /* only a fraction was sent */ + pp->sendleft -= written; + } + else { + free(pp->sendthis); + pp->sendthis = NULL; + pp->sendleft = pp->sendsize = 0; + pp->response = Curl_now(); + } + return CURLE_OK; +} + +CURLcode Curl_pp_disconnect(struct pingpong *pp) +{ + free(pp->cache); + pp->cache = NULL; + return CURLE_OK; +} + +bool Curl_pp_moredata(struct pingpong *pp) +{ + return (!pp->sendleft && pp->cache && pp->nread_resp < pp->cache_size) ? + TRUE : FALSE; +} + +#endif diff --git a/dependencies/cmcurl/lib/pingpong.h b/dependencies/cmcurl/lib/pingpong.h new file mode 100644 index 0000000..dbe1f8d --- /dev/null +++ b/dependencies/cmcurl/lib/pingpong.h @@ -0,0 +1,151 @@ +#ifndef HEADER_CURL_PINGPONG_H +#define HEADER_CURL_PINGPONG_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_FTP) || \ + !defined(CURL_DISABLE_POP3) || !defined(CURL_DISABLE_SMTP) +#define USE_PINGPONG +#endif + +/* forward-declaration, this is defined in urldata.h */ +struct connectdata; + +typedef enum { + FTPTRANSFER_BODY, /* yes do transfer a body */ + FTPTRANSFER_INFO, /* do still go through to get info/headers */ + FTPTRANSFER_NONE, /* don't get anything and don't get info */ + FTPTRANSFER_LAST /* end of list marker, never used */ +} curl_pp_transfer; + +/* + * 'pingpong' is the generic struct used for protocols doing server<->client + * conversations in a back-and-forth style such as FTP, IMAP, POP3, SMTP etc. + * + * It holds response cache and non-blocking sending data. + */ +struct pingpong { + char *cache; /* data cache between getresponse()-calls */ + size_t cache_size; /* size of cache in bytes */ + size_t nread_resp; /* number of bytes currently read of a server response */ + char *linestart_resp; /* line start pointer for the server response + reader function */ + bool pending_resp; /* set TRUE when a server response is pending or in + progress, and is cleared once the last response is + read */ + char *sendthis; /* allocated pointer to a buffer that is to be sent to the + server */ + size_t sendleft; /* number of bytes left to send from the sendthis buffer */ + size_t sendsize; /* total size of the sendthis buffer */ + struct curltime response; /* set to Curl_now() when a command has been sent + off, used to time-out response reading */ + long response_time; /* When no timeout is given, this is the amount of + milliseconds we await for a server response. */ + + struct connectdata *conn; /* points to the connectdata struct that this + belongs to */ + + /* Function pointers the protocols MUST implement and provide for the + pingpong layer to function */ + + CURLcode (*statemach_act)(struct connectdata *conn); + + bool (*endofresp)(struct connectdata *conn, char *ptr, size_t len, + int *code); +}; + +/* + * Curl_pp_statemach() + * + * called repeatedly until done. Set 'wait' to make it wait a while on the + * socket if there's no traffic. + */ +CURLcode Curl_pp_statemach(struct pingpong *pp, bool block, + bool disconnecting); + +/* initialize stuff to prepare for reading a fresh new response */ +void Curl_pp_init(struct pingpong *pp); + +/* Returns timeout in ms. 0 or negative number means the timeout has already + triggered */ +time_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting); + + +/*********************************************************************** + * + * Curl_pp_sendf() + * + * Send the formatted string as a command to a pingpong server. Note that + * the string should not have any CRLF appended, as this function will + * append the necessary things itself. + * + * made to never block + */ +CURLcode Curl_pp_sendf(struct pingpong *pp, + const char *fmt, ...); + +/*********************************************************************** + * + * Curl_pp_vsendf() + * + * Send the formatted string as a command to a pingpong server. Note that + * the string should not have any CRLF appended, as this function will + * append the necessary things itself. + * + * made to never block + */ +CURLcode Curl_pp_vsendf(struct pingpong *pp, + const char *fmt, + va_list args); + +/* + * Curl_pp_readresp() + * + * Reads a piece of a server response. + */ +CURLcode Curl_pp_readresp(curl_socket_t sockfd, + struct pingpong *pp, + int *code, /* return the server code if done */ + size_t *size); /* size of the response */ + + +CURLcode Curl_pp_flushsend(struct pingpong *pp); + +/* call this when a pingpong connection is disconnected */ +CURLcode Curl_pp_disconnect(struct pingpong *pp); + +int Curl_pp_getsock(struct pingpong *pp, curl_socket_t *socks, + int numsocks); + + +/*********************************************************************** + * + * Curl_pp_moredata() + * + * Returns whether there are still more data in the cache and so a call + * to Curl_pp_readresp() will not block. + */ +bool Curl_pp_moredata(struct pingpong *pp); + +#endif /* HEADER_CURL_PINGPONG_H */ diff --git a/dependencies/cmcurl/lib/pop3.c b/dependencies/cmcurl/lib/pop3.c new file mode 100644 index 0000000..c8f3965 --- /dev/null +++ b/dependencies/cmcurl/lib/pop3.c @@ -0,0 +1,1551 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC1734 POP3 Authentication + * RFC1939 POP3 protocol + * RFC2195 CRAM-MD5 authentication + * RFC2384 POP URL Scheme + * RFC2449 POP3 Extension Mechanism + * RFC2595 Using TLS with IMAP, POP3 and ACAP + * RFC2831 DIGEST-MD5 authentication + * RFC4422 Simple Authentication and Security Layer (SASL) + * RFC4616 PLAIN authentication + * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism + * RFC5034 POP3 SASL Authentication Mechanism + * RFC6749 OAuth 2.0 Authorization Framework + * RFC8314 Use of TLS for Email Submission and Access + * Draft LOGIN SASL Mechanism + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_POP3 + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_UTSNAME_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +#include +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "progress.h" +#include "transfer.h" +#include "escape.h" +#include "http.h" /* for HTTP proxy tunnel stuff */ +#include "socks.h" +#include "pop3.h" +#include "strtoofft.h" +#include "strcase.h" +#include "vtls/vtls.h" +#include "connect.h" +#include "strerror.h" +#include "select.h" +#include "multiif.h" +#include "url.h" +#include "curl_sasl.h" +#include "curl_md5.h" +#include "warnless.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* Local API functions */ +static CURLcode pop3_regular_transfer(struct connectdata *conn, bool *done); +static CURLcode pop3_do(struct connectdata *conn, bool *done); +static CURLcode pop3_done(struct connectdata *conn, CURLcode status, + bool premature); +static CURLcode pop3_connect(struct connectdata *conn, bool *done); +static CURLcode pop3_disconnect(struct connectdata *conn, bool dead); +static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done); +static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); +static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done); +static CURLcode pop3_setup_connection(struct connectdata *conn); +static CURLcode pop3_parse_url_options(struct connectdata *conn); +static CURLcode pop3_parse_url_path(struct connectdata *conn); +static CURLcode pop3_parse_custom_request(struct connectdata *conn); +static CURLcode pop3_perform_auth(struct connectdata *conn, const char *mech, + const char *initresp); +static CURLcode pop3_continue_auth(struct connectdata *conn, const char *resp); +static void pop3_get_message(char *buffer, char **outptr); + +/* + * POP3 protocol handler. + */ + +const struct Curl_handler Curl_handler_pop3 = { + "POP3", /* scheme */ + pop3_setup_connection, /* setup_connection */ + pop3_do, /* do_it */ + pop3_done, /* done */ + ZERO_NULL, /* do_more */ + pop3_connect, /* connect_it */ + pop3_multi_statemach, /* connecting */ + pop3_doing, /* doing */ + pop3_getsock, /* proto_getsock */ + pop3_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + pop3_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_POP3, /* defport */ + CURLPROTO_POP3, /* protocol */ + PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */ + PROTOPT_URLOPTIONS +}; + +#ifdef USE_SSL +/* + * POP3S protocol handler. + */ + +const struct Curl_handler Curl_handler_pop3s = { + "POP3S", /* scheme */ + pop3_setup_connection, /* setup_connection */ + pop3_do, /* do_it */ + pop3_done, /* done */ + ZERO_NULL, /* do_more */ + pop3_connect, /* connect_it */ + pop3_multi_statemach, /* connecting */ + pop3_doing, /* doing */ + pop3_getsock, /* proto_getsock */ + pop3_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + pop3_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_POP3S, /* defport */ + CURLPROTO_POP3S, /* protocol */ + PROTOPT_CLOSEACTION | PROTOPT_SSL + | PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS /* flags */ +}; +#endif + +/* SASL parameters for the pop3 protocol */ +static const struct SASLproto saslpop3 = { + "pop", /* The service name */ + '*', /* Code received when continuation is expected */ + '+', /* Code to receive upon authentication success */ + 255 - 8, /* Maximum initial response length (no max) */ + pop3_perform_auth, /* Send authentication command */ + pop3_continue_auth, /* Send authentication continuation */ + pop3_get_message /* Get SASL response message */ +}; + +#ifdef USE_SSL +static void pop3_to_pop3s(struct connectdata *conn) +{ + /* Change the connection handler */ + conn->handler = &Curl_handler_pop3s; + + /* Set the connection's upgraded to TLS flag */ + conn->tls_upgraded = TRUE; +} +#else +#define pop3_to_pop3s(x) Curl_nop_stmt +#endif + +/*********************************************************************** + * + * pop3_endofresp() + * + * Checks for an ending POP3 status code at the start of the given string, but + * also detects the APOP timestamp from the server greeting and various + * capabilities from the CAPA response including the supported authentication + * types and allowed SASL mechanisms. + */ +static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len, + int *resp) +{ + struct pop3_conn *pop3c = &conn->proto.pop3c; + + /* Do we have an error response? */ + if(len >= 4 && !memcmp("-ERR", line, 4)) { + *resp = '-'; + + return TRUE; + } + + /* Are we processing CAPA command responses? */ + if(pop3c->state == POP3_CAPA) { + /* Do we have the terminating line? */ + if(len >= 1 && line[0] == '.') + /* Treat the response as a success */ + *resp = '+'; + else + /* Treat the response as an untagged continuation */ + *resp = '*'; + + return TRUE; + } + + /* Do we have a success response? */ + if(len >= 3 && !memcmp("+OK", line, 3)) { + *resp = '+'; + + return TRUE; + } + + /* Do we have a continuation response? */ + if(len >= 1 && line[0] == '+') { + *resp = '*'; + + return TRUE; + } + + return FALSE; /* Nothing for us */ +} + +/*********************************************************************** + * + * pop3_get_message() + * + * Gets the authentication message from the response buffer. + */ +static void pop3_get_message(char *buffer, char **outptr) +{ + size_t len = strlen(buffer); + char *message = NULL; + + if(len > 2) { + /* Find the start of the message */ + len -= 2; + for(message = buffer + 2; *message == ' ' || *message == '\t'; + message++, len--) + ; + + /* Find the end of the message */ + for(; len--;) + if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' && + message[len] != '\t') + break; + + /* Terminate the message */ + if(++len) { + message[len] = '\0'; + } + } + else + /* junk input => zero length output */ + message = &buffer[len]; + + *outptr = message; +} + +/*********************************************************************** + * + * state() + * + * This is the ONLY way to change POP3 state! + */ +static void state(struct connectdata *conn, pop3state newstate) +{ + struct pop3_conn *pop3c = &conn->proto.pop3c; +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* for debug purposes */ + static const char * const names[] = { + "STOP", + "SERVERGREET", + "CAPA", + "STARTTLS", + "UPGRADETLS", + "AUTH", + "APOP", + "USER", + "PASS", + "COMMAND", + "QUIT", + /* LAST */ + }; + + if(pop3c->state != newstate) + infof(conn->data, "POP3 %p state change from %s to %s\n", + (void *)pop3c, names[pop3c->state], names[newstate]); +#endif + + pop3c->state = newstate; +} + +/*********************************************************************** + * + * pop3_perform_capa() + * + * Sends the CAPA command in order to obtain a list of server side supported + * capabilities. + */ +static CURLcode pop3_perform_capa(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct pop3_conn *pop3c = &conn->proto.pop3c; + + pop3c->sasl.authmechs = SASL_AUTH_NONE; /* No known auth. mechanisms yet */ + pop3c->sasl.authused = SASL_AUTH_NONE; /* Clear the auth. mechanism used */ + pop3c->tls_supported = FALSE; /* Clear the TLS capability */ + + /* Send the CAPA command */ + result = Curl_pp_sendf(&pop3c->pp, "%s", "CAPA"); + + if(!result) + state(conn, POP3_CAPA); + + return result; +} + +/*********************************************************************** + * + * pop3_perform_starttls() + * + * Sends the STLS command to start the upgrade to TLS. + */ +static CURLcode pop3_perform_starttls(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + /* Send the STLS command */ + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "STLS"); + + if(!result) + state(conn, POP3_STARTTLS); + + return result; +} + +/*********************************************************************** + * + * pop3_perform_upgrade_tls() + * + * Performs the upgrade to TLS. + */ +static CURLcode pop3_perform_upgrade_tls(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct pop3_conn *pop3c = &conn->proto.pop3c; + + /* Start the SSL connection */ + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &pop3c->ssldone); + + if(!result) { + if(pop3c->state != POP3_UPGRADETLS) + state(conn, POP3_UPGRADETLS); + + if(pop3c->ssldone) { + pop3_to_pop3s(conn); + result = pop3_perform_capa(conn); + } + } + + return result; +} + +/*********************************************************************** + * + * pop3_perform_user() + * + * Sends a clear text USER command to authenticate with. + */ +static CURLcode pop3_perform_user(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + /* Check we have a username and password to authenticate with and end the + connect phase if we don't */ + if(!conn->bits.user_passwd) { + state(conn, POP3_STOP); + + return result; + } + + /* Send the USER command */ + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "USER %s", + conn->user ? conn->user : ""); + if(!result) + state(conn, POP3_USER); + + return result; +} + +#ifndef CURL_DISABLE_CRYPTO_AUTH +/*********************************************************************** + * + * pop3_perform_apop() + * + * Sends an APOP command to authenticate with. + */ +static CURLcode pop3_perform_apop(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct pop3_conn *pop3c = &conn->proto.pop3c; + size_t i; + MD5_context *ctxt; + unsigned char digest[MD5_DIGEST_LEN]; + char secret[2 * MD5_DIGEST_LEN + 1]; + + /* Check we have a username and password to authenticate with and end the + connect phase if we don't */ + if(!conn->bits.user_passwd) { + state(conn, POP3_STOP); + + return result; + } + + /* Create the digest */ + ctxt = Curl_MD5_init(Curl_DIGEST_MD5); + if(!ctxt) + return CURLE_OUT_OF_MEMORY; + + Curl_MD5_update(ctxt, (const unsigned char *) pop3c->apoptimestamp, + curlx_uztoui(strlen(pop3c->apoptimestamp))); + + Curl_MD5_update(ctxt, (const unsigned char *) conn->passwd, + curlx_uztoui(strlen(conn->passwd))); + + /* Finalise the digest */ + Curl_MD5_final(ctxt, digest); + + /* Convert the calculated 16 octet digest into a 32 byte hex string */ + for(i = 0; i < MD5_DIGEST_LEN; i++) + msnprintf(&secret[2 * i], 3, "%02x", digest[i]); + + result = Curl_pp_sendf(&pop3c->pp, "APOP %s %s", conn->user, secret); + + if(!result) + state(conn, POP3_APOP); + + return result; +} +#endif + +/*********************************************************************** + * + * pop3_perform_auth() + * + * Sends an AUTH command allowing the client to login with the given SASL + * authentication mechanism. + */ +static CURLcode pop3_perform_auth(struct connectdata *conn, + const char *mech, + const char *initresp) +{ + CURLcode result = CURLE_OK; + struct pop3_conn *pop3c = &conn->proto.pop3c; + + if(initresp) { /* AUTH ... */ + /* Send the AUTH command with the initial response */ + result = Curl_pp_sendf(&pop3c->pp, "AUTH %s %s", mech, initresp); + } + else { + /* Send the AUTH command */ + result = Curl_pp_sendf(&pop3c->pp, "AUTH %s", mech); + } + + return result; +} + +/*********************************************************************** + * + * pop3_continue_auth() + * + * Sends SASL continuation data or cancellation. + */ +static CURLcode pop3_continue_auth(struct connectdata *conn, + const char *resp) +{ + struct pop3_conn *pop3c = &conn->proto.pop3c; + + return Curl_pp_sendf(&pop3c->pp, "%s", resp); +} + +/*********************************************************************** + * + * pop3_perform_authentication() + * + * Initiates the authentication sequence, with the appropriate SASL + * authentication mechanism, falling back to APOP and clear text should a + * common mechanism not be available between the client and server. + */ +static CURLcode pop3_perform_authentication(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct pop3_conn *pop3c = &conn->proto.pop3c; + saslprogress progress = SASL_IDLE; + + /* Check we have enough data to authenticate with and end the + connect phase if we don't */ + if(!Curl_sasl_can_authenticate(&pop3c->sasl, conn)) { + state(conn, POP3_STOP); + return result; + } + + if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_SASL) { + /* Calculate the SASL login details */ + result = Curl_sasl_start(&pop3c->sasl, conn, FALSE, &progress); + + if(!result) + if(progress == SASL_INPROGRESS) + state(conn, POP3_AUTH); + } + + if(!result && progress == SASL_IDLE) { +#ifndef CURL_DISABLE_CRYPTO_AUTH + if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_APOP) + /* Perform APOP authentication */ + result = pop3_perform_apop(conn); + else +#endif + if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_CLEARTEXT) + /* Perform clear text authentication */ + result = pop3_perform_user(conn); + else { + /* Other mechanisms not supported */ + infof(conn->data, "No known authentication mechanisms supported!\n"); + result = CURLE_LOGIN_DENIED; + } + } + + return result; +} + +/*********************************************************************** + * + * pop3_perform_command() + * + * Sends a POP3 based command. + */ +static CURLcode pop3_perform_command(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct POP3 *pop3 = data->req.protop; + const char *command = NULL; + + /* Calculate the default command */ + if(pop3->id[0] == '\0' || conn->data->set.ftp_list_only) { + command = "LIST"; + + if(pop3->id[0] != '\0') + /* Message specific LIST so skip the BODY transfer */ + pop3->transfer = FTPTRANSFER_INFO; + } + else + command = "RETR"; + + /* Send the command */ + if(pop3->id[0] != '\0') + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s %s", + (pop3->custom && pop3->custom[0] != '\0' ? + pop3->custom : command), pop3->id); + else + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", + (pop3->custom && pop3->custom[0] != '\0' ? + pop3->custom : command)); + + if(!result) + state(conn, POP3_COMMAND); + + return result; +} + +/*********************************************************************** + * + * pop3_perform_quit() + * + * Performs the quit action prior to sclose() be called. + */ +static CURLcode pop3_perform_quit(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + /* Send the QUIT command */ + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "QUIT"); + + if(!result) + state(conn, POP3_QUIT); + + return result; +} + +/* For the initial server greeting */ +static CURLcode pop3_state_servergreet_resp(struct connectdata *conn, + int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct pop3_conn *pop3c = &conn->proto.pop3c; + const char *line = data->state.buffer; + size_t len = strlen(line); + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + failf(data, "Got unexpected pop3-server response"); + result = CURLE_WEIRD_SERVER_REPLY; + } + else { + /* Does the server support APOP authentication? */ + if(len >= 4 && line[len - 2] == '>') { + /* Look for the APOP timestamp */ + size_t i; + for(i = 3; i < len - 2; ++i) { + if(line[i] == '<') { + /* Calculate the length of the timestamp */ + size_t timestamplen = len - 1 - i; + char *at; + if(!timestamplen) + break; + + /* Allocate some memory for the timestamp */ + pop3c->apoptimestamp = (char *)calloc(1, timestamplen + 1); + + if(!pop3c->apoptimestamp) + break; + + /* Copy the timestamp */ + memcpy(pop3c->apoptimestamp, line + i, timestamplen); + pop3c->apoptimestamp[timestamplen] = '\0'; + + /* If the timestamp does not contain '@' it is not (as required by + RFC-1939) conformant to the RFC-822 message id syntax, and we + therefore do not use APOP authentication. */ + at = strchr(pop3c->apoptimestamp, '@'); + if(!at) + Curl_safefree(pop3c->apoptimestamp); + else + /* Store the APOP capability */ + pop3c->authtypes |= POP3_TYPE_APOP; + break; + } + } + } + + result = pop3_perform_capa(conn); + } + + return result; +} + +/* For CAPA responses */ +static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct pop3_conn *pop3c = &conn->proto.pop3c; + const char *line = data->state.buffer; + size_t len = strlen(line); + + (void)instate; /* no use for this yet */ + + /* Do we have a untagged continuation response? */ + if(pop3code == '*') { + /* Does the server support the STLS capability? */ + if(len >= 4 && !memcmp(line, "STLS", 4)) + pop3c->tls_supported = TRUE; + + /* Does the server support clear text authentication? */ + else if(len >= 4 && !memcmp(line, "USER", 4)) + pop3c->authtypes |= POP3_TYPE_CLEARTEXT; + + /* Does the server support SASL based authentication? */ + else if(len >= 5 && !memcmp(line, "SASL ", 5)) { + pop3c->authtypes |= POP3_TYPE_SASL; + + /* Advance past the SASL keyword */ + line += 5; + len -= 5; + + /* Loop through the data line */ + for(;;) { + size_t llen; + size_t wordlen; + unsigned int mechbit; + + while(len && + (*line == ' ' || *line == '\t' || + *line == '\r' || *line == '\n')) { + + line++; + len--; + } + + if(!len) + break; + + /* Extract the word */ + for(wordlen = 0; wordlen < len && line[wordlen] != ' ' && + line[wordlen] != '\t' && line[wordlen] != '\r' && + line[wordlen] != '\n';) + wordlen++; + + /* Test the word for a matching authentication mechanism */ + mechbit = Curl_sasl_decode_mech(line, wordlen, &llen); + if(mechbit && llen == wordlen) + pop3c->sasl.authmechs |= mechbit; + + line += wordlen; + len -= wordlen; + } + } + } + else if(pop3code == '+') { + if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) { + /* We don't have a SSL/TLS connection yet, but SSL is requested */ + if(pop3c->tls_supported) + /* Switch to TLS connection now */ + result = pop3_perform_starttls(conn); + else if(data->set.use_ssl == CURLUSESSL_TRY) + /* Fallback and carry on with authentication */ + result = pop3_perform_authentication(conn); + else { + failf(data, "STLS not supported."); + result = CURLE_USE_SSL_FAILED; + } + } + else + result = pop3_perform_authentication(conn); + } + else { + /* Clear text is supported when CAPA isn't recognised */ + pop3c->authtypes |= POP3_TYPE_CLEARTEXT; + + result = pop3_perform_authentication(conn); + } + + return result; +} + +/* For STARTTLS responses */ +static CURLcode pop3_state_starttls_resp(struct connectdata *conn, + int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + if(data->set.use_ssl != CURLUSESSL_TRY) { + failf(data, "STARTTLS denied"); + result = CURLE_USE_SSL_FAILED; + } + else + result = pop3_perform_authentication(conn); + } + else + result = pop3_perform_upgrade_tls(conn); + + return result; +} + +/* For SASL authentication responses */ +static CURLcode pop3_state_auth_resp(struct connectdata *conn, + int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct pop3_conn *pop3c = &conn->proto.pop3c; + saslprogress progress; + + (void)instate; /* no use for this yet */ + + result = Curl_sasl_continue(&pop3c->sasl, conn, pop3code, &progress); + if(!result) + switch(progress) { + case SASL_DONE: + state(conn, POP3_STOP); /* Authenticated */ + break; + case SASL_IDLE: /* No mechanism left after cancellation */ +#ifndef CURL_DISABLE_CRYPTO_AUTH + if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_APOP) + /* Perform APOP authentication */ + result = pop3_perform_apop(conn); + else +#endif + if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_CLEARTEXT) + /* Perform clear text authentication */ + result = pop3_perform_user(conn); + else { + failf(data, "Authentication cancelled"); + result = CURLE_LOGIN_DENIED; + } + break; + default: + break; + } + + return result; +} + +#ifndef CURL_DISABLE_CRYPTO_AUTH +/* For APOP responses */ +static CURLcode pop3_state_apop_resp(struct connectdata *conn, int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + failf(data, "Authentication failed: %d", pop3code); + result = CURLE_LOGIN_DENIED; + } + else + /* End of connect phase */ + state(conn, POP3_STOP); + + return result; +} +#endif + +/* For USER responses */ +static CURLcode pop3_state_user_resp(struct connectdata *conn, int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + failf(data, "Access denied. %c", pop3code); + result = CURLE_LOGIN_DENIED; + } + else + /* Send the PASS command */ + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "PASS %s", + conn->passwd ? conn->passwd : ""); + if(!result) + state(conn, POP3_PASS); + + return result; +} + +/* For PASS responses */ +static CURLcode pop3_state_pass_resp(struct connectdata *conn, int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + failf(data, "Access denied. %c", pop3code); + result = CURLE_LOGIN_DENIED; + } + else + /* End of connect phase */ + state(conn, POP3_STOP); + + return result; +} + +/* For command responses */ +static CURLcode pop3_state_command_resp(struct connectdata *conn, + int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct POP3 *pop3 = data->req.protop; + struct pop3_conn *pop3c = &conn->proto.pop3c; + struct pingpong *pp = &pop3c->pp; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + state(conn, POP3_STOP); + return CURLE_RECV_ERROR; + } + + /* This 'OK' line ends with a CR LF pair which is the two first bytes of the + EOB string so count this is two matching bytes. This is necessary to make + the code detect the EOB if the only data than comes now is %2e CR LF like + when there is no body to return. */ + pop3c->eob = 2; + + /* But since this initial CR LF pair is not part of the actual body, we set + the strip counter here so that these bytes won't be delivered. */ + pop3c->strip = 2; + + if(pop3->transfer == FTPTRANSFER_BODY) { + /* POP3 download */ + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); + + if(pp->cache) { + /* The header "cache" contains a bunch of data that is actually body + content so send it as such. Note that there may even be additional + "headers" after the body */ + + if(!data->set.opt_no_body) { + result = Curl_pop3_write(conn, pp->cache, pp->cache_size); + if(result) + return result; + } + + /* Free the cache */ + Curl_safefree(pp->cache); + + /* Reset the cache size */ + pp->cache_size = 0; + } + } + + /* End of DO phase */ + state(conn, POP3_STOP); + + return result; +} + +static CURLcode pop3_statemach_act(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + int pop3code; + struct pop3_conn *pop3c = &conn->proto.pop3c; + struct pingpong *pp = &pop3c->pp; + size_t nread = 0; + + /* Busy upgrading the connection; right now all I/O is SSL/TLS, not POP3 */ + if(pop3c->state == POP3_UPGRADETLS) + return pop3_perform_upgrade_tls(conn); + + /* Flush any data that needs to be sent */ + if(pp->sendleft) + return Curl_pp_flushsend(pp); + + do { + /* Read the response from the server */ + result = Curl_pp_readresp(sock, pp, &pop3code, &nread); + if(result) + return result; + + if(!pop3code) + break; + + /* We have now received a full POP3 server response */ + switch(pop3c->state) { + case POP3_SERVERGREET: + result = pop3_state_servergreet_resp(conn, pop3code, pop3c->state); + break; + + case POP3_CAPA: + result = pop3_state_capa_resp(conn, pop3code, pop3c->state); + break; + + case POP3_STARTTLS: + result = pop3_state_starttls_resp(conn, pop3code, pop3c->state); + break; + + case POP3_AUTH: + result = pop3_state_auth_resp(conn, pop3code, pop3c->state); + break; + +#ifndef CURL_DISABLE_CRYPTO_AUTH + case POP3_APOP: + result = pop3_state_apop_resp(conn, pop3code, pop3c->state); + break; +#endif + + case POP3_USER: + result = pop3_state_user_resp(conn, pop3code, pop3c->state); + break; + + case POP3_PASS: + result = pop3_state_pass_resp(conn, pop3code, pop3c->state); + break; + + case POP3_COMMAND: + result = pop3_state_command_resp(conn, pop3code, pop3c->state); + break; + + case POP3_QUIT: + /* fallthrough, just stop! */ + default: + /* internal error */ + state(conn, POP3_STOP); + break; + } + } while(!result && pop3c->state != POP3_STOP && Curl_pp_moredata(pp)); + + return result; +} + +/* Called repeatedly until done from multi.c */ +static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + struct pop3_conn *pop3c = &conn->proto.pop3c; + + if((conn->handler->flags & PROTOPT_SSL) && !pop3c->ssldone) { + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &pop3c->ssldone); + if(result || !pop3c->ssldone) + return result; + } + + result = Curl_pp_statemach(&pop3c->pp, FALSE, FALSE); + *done = (pop3c->state == POP3_STOP) ? TRUE : FALSE; + + return result; +} + +static CURLcode pop3_block_statemach(struct connectdata *conn, + bool disconnecting) +{ + CURLcode result = CURLE_OK; + struct pop3_conn *pop3c = &conn->proto.pop3c; + + while(pop3c->state != POP3_STOP && !result) + result = Curl_pp_statemach(&pop3c->pp, TRUE, disconnecting); + + return result; +} + +/* Allocate and initialize the POP3 struct for the current Curl_easy if + required */ +static CURLcode pop3_init(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct POP3 *pop3; + + pop3 = data->req.protop = calloc(sizeof(struct POP3), 1); + if(!pop3) + result = CURLE_OUT_OF_MEMORY; + + return result; +} + +/* For the POP3 "protocol connect" and "doing" phases only */ +static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks) +{ + return Curl_pp_getsock(&conn->proto.pop3c.pp, socks, numsocks); +} + +/*********************************************************************** + * + * pop3_connect() + * + * This function should do everything that is to be considered a part of the + * connection phase. + * + * The variable 'done' points to will be TRUE if the protocol-layer connect + * phase is done when this function returns, or FALSE if not. + */ +static CURLcode pop3_connect(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + struct pop3_conn *pop3c = &conn->proto.pop3c; + struct pingpong *pp = &pop3c->pp; + + *done = FALSE; /* default to not done yet */ + + /* We always support persistent connections in POP3 */ + connkeep(conn, "POP3 default"); + + /* Set the default response time-out */ + pp->response_time = RESP_TIMEOUT; + pp->statemach_act = pop3_statemach_act; + pp->endofresp = pop3_endofresp; + pp->conn = conn; + + /* Set the default preferred authentication type and mechanism */ + pop3c->preftype = POP3_TYPE_ANY; + Curl_sasl_init(&pop3c->sasl, &saslpop3); + + /* Initialise the pingpong layer */ + Curl_pp_init(pp); + + /* Parse the URL options */ + result = pop3_parse_url_options(conn); + if(result) + return result; + + /* Start off waiting for the server greeting response */ + state(conn, POP3_SERVERGREET); + + result = pop3_multi_statemach(conn, done); + + return result; +} + +/*********************************************************************** + * + * pop3_done() + * + * The DONE function. This does what needs to be done after a single DO has + * performed. + * + * Input argument is already checked for validity. + */ +static CURLcode pop3_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct POP3 *pop3 = data->req.protop; + + (void)premature; + + if(!pop3) + return CURLE_OK; + + if(status) { + connclose(conn, "POP3 done with bad status"); + result = status; /* use the already set error code */ + } + + /* Cleanup our per-request based variables */ + Curl_safefree(pop3->id); + Curl_safefree(pop3->custom); + + /* Clear the transfer mode for the next request */ + pop3->transfer = FTPTRANSFER_BODY; + + return result; +} + +/*********************************************************************** + * + * pop3_perform() + * + * This is the actual DO function for POP3. Get a message/listing according to + * the options previously setup. + */ +static CURLcode pop3_perform(struct connectdata *conn, bool *connected, + bool *dophase_done) +{ + /* This is POP3 and no proxy */ + CURLcode result = CURLE_OK; + struct POP3 *pop3 = conn->data->req.protop; + + DEBUGF(infof(conn->data, "DO phase starts\n")); + + if(conn->data->set.opt_no_body) { + /* Requested no body means no transfer */ + pop3->transfer = FTPTRANSFER_INFO; + } + + *dophase_done = FALSE; /* not done yet */ + + /* Start the first command in the DO phase */ + result = pop3_perform_command(conn); + if(result) + return result; + + /* Run the state-machine */ + result = pop3_multi_statemach(conn, dophase_done); + + *connected = conn->bits.tcpconnect[FIRSTSOCKET]; + + if(*dophase_done) + DEBUGF(infof(conn->data, "DO phase is complete\n")); + + return result; +} + +/*********************************************************************** + * + * pop3_do() + * + * This function is registered as 'curl_do' function. It decodes the path + * parts etc as a wrapper to the actual DO function (pop3_perform). + * + * The input argument is already checked for validity. + */ +static CURLcode pop3_do(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + + *done = FALSE; /* default to false */ + + /* Parse the URL path */ + result = pop3_parse_url_path(conn); + if(result) + return result; + + /* Parse the custom request */ + result = pop3_parse_custom_request(conn); + if(result) + return result; + + result = pop3_regular_transfer(conn, done); + + return result; +} + +/*********************************************************************** + * + * pop3_disconnect() + * + * Disconnect from an POP3 server. Cleanup protocol-specific per-connection + * resources. BLOCKING. + */ +static CURLcode pop3_disconnect(struct connectdata *conn, bool dead_connection) +{ + struct pop3_conn *pop3c = &conn->proto.pop3c; + + /* We cannot send quit unconditionally. If this connection is stale or + bad in any way, sending quit and waiting around here will make the + disconnect wait in vain and cause more problems than we need to. */ + + /* The POP3 session may or may not have been allocated/setup at this + point! */ + if(!dead_connection && pop3c->pp.conn && pop3c->pp.conn->bits.protoconnstart) + if(!pop3_perform_quit(conn)) + (void)pop3_block_statemach(conn, TRUE); /* ignore errors on QUIT */ + + /* Disconnect from the server */ + Curl_pp_disconnect(&pop3c->pp); + + /* Cleanup the SASL module */ + Curl_sasl_cleanup(conn, pop3c->sasl.authused); + + /* Cleanup our connection based variables */ + Curl_safefree(pop3c->apoptimestamp); + + return CURLE_OK; +} + +/* Call this when the DO phase has completed */ +static CURLcode pop3_dophase_done(struct connectdata *conn, bool connected) +{ + (void)conn; + (void)connected; + + return CURLE_OK; +} + +/* Called from multi.c while DOing */ +static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done) +{ + CURLcode result = pop3_multi_statemach(conn, dophase_done); + + if(result) + DEBUGF(infof(conn->data, "DO phase failed\n")); + else if(*dophase_done) { + result = pop3_dophase_done(conn, FALSE /* not connected */); + + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + + return result; +} + +/*********************************************************************** + * + * pop3_regular_transfer() + * + * The input argument is already checked for validity. + * + * Performs all commands done before a regular transfer between a local and a + * remote host. + */ +static CURLcode pop3_regular_transfer(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result = CURLE_OK; + bool connected = FALSE; + struct Curl_easy *data = conn->data; + + /* Make sure size is unknown at this point */ + data->req.size = -1; + + /* Set the progress data */ + Curl_pgrsSetUploadCounter(data, 0); + Curl_pgrsSetDownloadCounter(data, 0); + Curl_pgrsSetUploadSize(data, -1); + Curl_pgrsSetDownloadSize(data, -1); + + /* Carry out the perform */ + result = pop3_perform(conn, &connected, dophase_done); + + /* Perform post DO phase operations if necessary */ + if(!result && *dophase_done) + result = pop3_dophase_done(conn, connected); + + return result; +} + +static CURLcode pop3_setup_connection(struct connectdata *conn) +{ + /* Initialise the POP3 layer */ + CURLcode result = pop3_init(conn); + if(result) + return result; + + /* Clear the TLS upgraded flag */ + conn->tls_upgraded = FALSE; + + return CURLE_OK; +} + +/*********************************************************************** + * + * pop3_parse_url_options() + * + * Parse the URL login options. + */ +static CURLcode pop3_parse_url_options(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct pop3_conn *pop3c = &conn->proto.pop3c; + const char *ptr = conn->options; + + pop3c->sasl.resetprefs = TRUE; + + while(!result && ptr && *ptr) { + const char *key = ptr; + const char *value; + + while(*ptr && *ptr != '=') + ptr++; + + value = ptr + 1; + + while(*ptr && *ptr != ';') + ptr++; + + if(strncasecompare(key, "AUTH=", 5)) { + result = Curl_sasl_parse_url_auth_option(&pop3c->sasl, + value, ptr - value); + + if(result && strncasecompare(value, "+APOP", ptr - value)) { + pop3c->preftype = POP3_TYPE_APOP; + pop3c->sasl.prefmech = SASL_AUTH_NONE; + result = CURLE_OK; + } + } + else + result = CURLE_URL_MALFORMAT; + + if(*ptr == ';') + ptr++; + } + + if(pop3c->preftype != POP3_TYPE_APOP) + switch(pop3c->sasl.prefmech) { + case SASL_AUTH_NONE: + pop3c->preftype = POP3_TYPE_NONE; + break; + case SASL_AUTH_DEFAULT: + pop3c->preftype = POP3_TYPE_ANY; + break; + default: + pop3c->preftype = POP3_TYPE_SASL; + break; + } + + return result; +} + +/*********************************************************************** + * + * pop3_parse_url_path() + * + * Parse the URL path into separate path components. + */ +static CURLcode pop3_parse_url_path(struct connectdata *conn) +{ + /* The POP3 struct is already initialised in pop3_connect() */ + struct Curl_easy *data = conn->data; + struct POP3 *pop3 = data->req.protop; + const char *path = &data->state.up.path[1]; /* skip leading path */ + + /* URL decode the path for the message ID */ + return Curl_urldecode(data, path, 0, &pop3->id, NULL, TRUE); +} + +/*********************************************************************** + * + * pop3_parse_custom_request() + * + * Parse the custom request. + */ +static CURLcode pop3_parse_custom_request(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct POP3 *pop3 = data->req.protop; + const char *custom = data->set.str[STRING_CUSTOMREQUEST]; + + /* URL decode the custom request */ + if(custom) + result = Curl_urldecode(data, custom, 0, &pop3->custom, NULL, TRUE); + + return result; +} + +/*********************************************************************** + * + * Curl_pop3_write() + * + * This function scans the body after the end-of-body and writes everything + * until the end is found. + */ +CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread) +{ + /* This code could be made into a special function in the handler struct */ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct SingleRequest *k = &data->req; + + struct pop3_conn *pop3c = &conn->proto.pop3c; + bool strip_dot = FALSE; + size_t last = 0; + size_t i; + + /* Search through the buffer looking for the end-of-body marker which is + 5 bytes (0d 0a 2e 0d 0a). Note that a line starting with a dot matches + the eob so the server will have prefixed it with an extra dot which we + need to strip out. Additionally the marker could of course be spread out + over 5 different data chunks. */ + for(i = 0; i < nread; i++) { + size_t prev = pop3c->eob; + + switch(str[i]) { + case 0x0d: + if(pop3c->eob == 0) { + pop3c->eob++; + + if(i) { + /* Write out the body part that didn't match */ + result = Curl_client_write(conn, CLIENTWRITE_BODY, &str[last], + i - last); + + if(result) + return result; + + last = i; + } + } + else if(pop3c->eob == 3) + pop3c->eob++; + else + /* If the character match wasn't at position 0 or 3 then restart the + pattern matching */ + pop3c->eob = 1; + break; + + case 0x0a: + if(pop3c->eob == 1 || pop3c->eob == 4) + pop3c->eob++; + else + /* If the character match wasn't at position 1 or 4 then start the + search again */ + pop3c->eob = 0; + break; + + case 0x2e: + if(pop3c->eob == 2) + pop3c->eob++; + else if(pop3c->eob == 3) { + /* We have an extra dot after the CRLF which we need to strip off */ + strip_dot = TRUE; + pop3c->eob = 0; + } + else + /* If the character match wasn't at position 2 then start the search + again */ + pop3c->eob = 0; + break; + + default: + pop3c->eob = 0; + break; + } + + /* Did we have a partial match which has subsequently failed? */ + if(prev && prev >= pop3c->eob) { + /* Strip can only be non-zero for the very first mismatch after CRLF + and then both prev and strip are equal and nothing will be output + below */ + while(prev && pop3c->strip) { + prev--; + pop3c->strip--; + } + + if(prev) { + /* If the partial match was the CRLF and dot then only write the CRLF + as the server would have inserted the dot */ + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)POP3_EOB, + strip_dot ? prev - 1 : prev); + + if(result) + return result; + + last = i; + strip_dot = FALSE; + } + } + } + + if(pop3c->eob == POP3_EOB_LEN) { + /* We have a full match so the transfer is done, however we must transfer + the CRLF at the start of the EOB as this is considered to be part of the + message as per RFC-1939, sect. 3 */ + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)POP3_EOB, 2); + + k->keepon &= ~KEEP_RECV; + pop3c->eob = 0; + + return result; + } + + if(pop3c->eob) + /* While EOB is matching nothing should be output */ + return CURLE_OK; + + if(nread - last) { + result = Curl_client_write(conn, CLIENTWRITE_BODY, &str[last], + nread - last); + } + + return result; +} + +#endif /* CURL_DISABLE_POP3 */ diff --git a/dependencies/cmcurl/lib/pop3.h b/dependencies/cmcurl/lib/pop3.h new file mode 100644 index 0000000..a8e697c --- /dev/null +++ b/dependencies/cmcurl/lib/pop3.h @@ -0,0 +1,95 @@ +#ifndef HEADER_CURL_POP3_H +#define HEADER_CURL_POP3_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2009 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "pingpong.h" +#include "curl_sasl.h" + +/**************************************************************************** + * POP3 unique setup + ***************************************************************************/ +typedef enum { + POP3_STOP, /* do nothing state, stops the state machine */ + POP3_SERVERGREET, /* waiting for the initial greeting immediately after + a connect */ + POP3_CAPA, + POP3_STARTTLS, + POP3_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS + (multi mode only) */ + POP3_AUTH, + POP3_APOP, + POP3_USER, + POP3_PASS, + POP3_COMMAND, + POP3_QUIT, + POP3_LAST /* never used */ +} pop3state; + +/* This POP3 struct is used in the Curl_easy. All POP3 data that is + connection-oriented must be in pop3_conn to properly deal with the fact that + perhaps the Curl_easy is changed between the times the connection is + used. */ +struct POP3 { + curl_pp_transfer transfer; + char *id; /* Message ID */ + char *custom; /* Custom Request */ +}; + +/* pop3_conn is used for struct connection-oriented data in the connectdata + struct */ +struct pop3_conn { + struct pingpong pp; + pop3state state; /* Always use pop3.c:state() to change state! */ + bool ssldone; /* Is connect() over SSL done? */ + size_t eob; /* Number of bytes of the EOB (End Of Body) that + have been received so far */ + size_t strip; /* Number of bytes from the start to ignore as + non-body */ + struct SASL sasl; /* SASL-related storage */ + unsigned int authtypes; /* Accepted authentication types */ + unsigned int preftype; /* Preferred authentication type */ + char *apoptimestamp; /* APOP timestamp from the server greeting */ + bool tls_supported; /* StartTLS capability supported by server */ +}; + +extern const struct Curl_handler Curl_handler_pop3; +extern const struct Curl_handler Curl_handler_pop3s; + +/* Authentication type flags */ +#define POP3_TYPE_CLEARTEXT (1 << 0) +#define POP3_TYPE_APOP (1 << 1) +#define POP3_TYPE_SASL (1 << 2) + +/* Authentication type values */ +#define POP3_TYPE_NONE 0 +#define POP3_TYPE_ANY ~0U + +/* This is the 5-bytes End-Of-Body marker for POP3 */ +#define POP3_EOB "\x0d\x0a\x2e\x0d\x0a" +#define POP3_EOB_LEN 5 + +/* This function scans the body after the end-of-body and writes everything + * until the end is found */ +CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread); + +#endif /* HEADER_CURL_POP3_H */ diff --git a/dependencies/cmcurl/lib/progress.c b/dependencies/cmcurl/lib/progress.c new file mode 100644 index 0000000..f586d59 --- /dev/null +++ b/dependencies/cmcurl/lib/progress.c @@ -0,0 +1,619 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "urldata.h" +#include "sendf.h" +#include "multiif.h" +#include "progress.h" +#include "curl_printf.h" + +/* check rate limits within this many recent milliseconds, at minimum. */ +#define MIN_RATE_LIMIT_PERIOD 3000 + +#ifndef CURL_DISABLE_PROGRESS_METER +/* Provide a string that is 2 + 1 + 2 + 1 + 2 = 8 letters long (plus the zero + byte) */ +static void time2str(char *r, curl_off_t seconds) +{ + curl_off_t h; + if(seconds <= 0) { + strcpy(r, "--:--:--"); + return; + } + h = seconds / CURL_OFF_T_C(3600); + if(h <= CURL_OFF_T_C(99)) { + curl_off_t m = (seconds - (h*CURL_OFF_T_C(3600))) / CURL_OFF_T_C(60); + curl_off_t s = (seconds - (h*CURL_OFF_T_C(3600))) - (m*CURL_OFF_T_C(60)); + msnprintf(r, 9, "%2" CURL_FORMAT_CURL_OFF_T ":%02" CURL_FORMAT_CURL_OFF_T + ":%02" CURL_FORMAT_CURL_OFF_T, h, m, s); + } + else { + /* this equals to more than 99 hours, switch to a more suitable output + format to fit within the limits. */ + curl_off_t d = seconds / CURL_OFF_T_C(86400); + h = (seconds - (d*CURL_OFF_T_C(86400))) / CURL_OFF_T_C(3600); + if(d <= CURL_OFF_T_C(999)) + msnprintf(r, 9, "%3" CURL_FORMAT_CURL_OFF_T + "d %02" CURL_FORMAT_CURL_OFF_T "h", d, h); + else + msnprintf(r, 9, "%7" CURL_FORMAT_CURL_OFF_T "d", d); + } +} + +/* The point of this function would be to return a string of the input data, + but never longer than 5 columns (+ one zero byte). + Add suffix k, M, G when suitable... */ +static char *max5data(curl_off_t bytes, char *max5) +{ +#define ONE_KILOBYTE CURL_OFF_T_C(1024) +#define ONE_MEGABYTE (CURL_OFF_T_C(1024) * ONE_KILOBYTE) +#define ONE_GIGABYTE (CURL_OFF_T_C(1024) * ONE_MEGABYTE) +#define ONE_TERABYTE (CURL_OFF_T_C(1024) * ONE_GIGABYTE) +#define ONE_PETABYTE (CURL_OFF_T_C(1024) * ONE_TERABYTE) + + if(bytes < CURL_OFF_T_C(100000)) + msnprintf(max5, 6, "%5" CURL_FORMAT_CURL_OFF_T, bytes); + + else if(bytes < CURL_OFF_T_C(10000) * ONE_KILOBYTE) + msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "k", bytes/ONE_KILOBYTE); + + else if(bytes < CURL_OFF_T_C(100) * ONE_MEGABYTE) + /* 'XX.XM' is good as long as we're less than 100 megs */ + msnprintf(max5, 6, "%2" CURL_FORMAT_CURL_OFF_T ".%0" + CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE, + (bytes%ONE_MEGABYTE) / (ONE_MEGABYTE/CURL_OFF_T_C(10)) ); + +#if (CURL_SIZEOF_CURL_OFF_T > 4) + + else if(bytes < CURL_OFF_T_C(10000) * ONE_MEGABYTE) + /* 'XXXXM' is good until we're at 10000MB or above */ + msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE); + + else if(bytes < CURL_OFF_T_C(100) * ONE_GIGABYTE) + /* 10000 MB - 100 GB, we show it as XX.XG */ + msnprintf(max5, 6, "%2" CURL_FORMAT_CURL_OFF_T ".%0" + CURL_FORMAT_CURL_OFF_T "G", bytes/ONE_GIGABYTE, + (bytes%ONE_GIGABYTE) / (ONE_GIGABYTE/CURL_OFF_T_C(10)) ); + + else if(bytes < CURL_OFF_T_C(10000) * ONE_GIGABYTE) + /* up to 10000GB, display without decimal: XXXXG */ + msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "G", bytes/ONE_GIGABYTE); + + else if(bytes < CURL_OFF_T_C(10000) * ONE_TERABYTE) + /* up to 10000TB, display without decimal: XXXXT */ + msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "T", bytes/ONE_TERABYTE); + + else + /* up to 10000PB, display without decimal: XXXXP */ + msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "P", bytes/ONE_PETABYTE); + + /* 16384 petabytes (16 exabytes) is the maximum a 64 bit unsigned number + can hold, but our data type is signed so 8192PB will be the maximum. */ + +#else + + else + msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE); + +#endif + + return max5; +} +#endif + +/* + + New proposed interface, 9th of February 2000: + + pgrsStartNow() - sets start time + pgrsSetDownloadSize(x) - known expected download size + pgrsSetUploadSize(x) - known expected upload size + pgrsSetDownloadCounter() - amount of data currently downloaded + pgrsSetUploadCounter() - amount of data currently uploaded + pgrsUpdate() - show progress + pgrsDone() - transfer complete + +*/ + +int Curl_pgrsDone(struct connectdata *conn) +{ + int rc; + struct Curl_easy *data = conn->data; + data->progress.lastshow = 0; + rc = Curl_pgrsUpdate(conn); /* the final (forced) update */ + if(rc) + return rc; + + if(!(data->progress.flags & PGRS_HIDE) && + !data->progress.callback) + /* only output if we don't use a progress callback and we're not + * hidden */ + fprintf(data->set.err, "\n"); + + data->progress.speeder_c = 0; /* reset the progress meter display */ + return 0; +} + +/* reset the known transfer sizes */ +void Curl_pgrsResetTransferSizes(struct Curl_easy *data) +{ + Curl_pgrsSetDownloadSize(data, -1); + Curl_pgrsSetUploadSize(data, -1); +} + +/* + * @unittest: 1399 + */ +void Curl_pgrsTime(struct Curl_easy *data, timerid timer) +{ + struct curltime now = Curl_now(); + time_t *delta = NULL; + + switch(timer) { + default: + case TIMER_NONE: + /* mistake filter */ + break; + case TIMER_STARTOP: + /* This is set at the start of a transfer */ + data->progress.t_startop = now; + break; + case TIMER_STARTSINGLE: + /* This is set at the start of each single fetch */ + data->progress.t_startsingle = now; + data->progress.is_t_startransfer_set = false; + break; + case TIMER_STARTACCEPT: + data->progress.t_acceptdata = now; + break; + case TIMER_NAMELOOKUP: + delta = &data->progress.t_nslookup; + break; + case TIMER_CONNECT: + delta = &data->progress.t_connect; + break; + case TIMER_APPCONNECT: + delta = &data->progress.t_appconnect; + break; + case TIMER_PRETRANSFER: + delta = &data->progress.t_pretransfer; + break; + case TIMER_STARTTRANSFER: + delta = &data->progress.t_starttransfer; + /* prevent updating t_starttransfer unless: + * 1) this is the first time we're setting t_starttransfer + * 2) a redirect has occurred since the last time t_starttransfer was set + * This prevents repeated invocations of the function from incorrectly + * changing the t_starttransfer time. + */ + if(data->progress.is_t_startransfer_set) { + return; + } + else { + data->progress.is_t_startransfer_set = true; + break; + } + case TIMER_POSTRANSFER: + /* this is the normal end-of-transfer thing */ + break; + case TIMER_REDIRECT: + data->progress.t_redirect = Curl_timediff_us(now, data->progress.start); + break; + } + if(delta) { + timediff_t us = Curl_timediff_us(now, data->progress.t_startsingle); + if(us < 1) + us = 1; /* make sure at least one microsecond passed */ + *delta += us; + } +} + +void Curl_pgrsStartNow(struct Curl_easy *data) +{ + data->progress.speeder_c = 0; /* reset the progress meter display */ + data->progress.start = Curl_now(); + data->progress.is_t_startransfer_set = false; + data->progress.ul_limit_start.tv_sec = 0; + data->progress.ul_limit_start.tv_usec = 0; + data->progress.dl_limit_start.tv_sec = 0; + data->progress.dl_limit_start.tv_usec = 0; + /* clear all bits except HIDE and HEADERS_OUT */ + data->progress.flags &= PGRS_HIDE|PGRS_HEADERS_OUT; + Curl_ratelimit(data, data->progress.start); +} + +/* + * This is used to handle speed limits, calculating how many milliseconds to + * wait until we're back under the speed limit, if needed. + * + * The way it works is by having a "starting point" (time & amount of data + * transferred by then) used in the speed computation, to be used instead of + * the start of the transfer. This starting point is regularly moved as + * transfer goes on, to keep getting accurate values (instead of average over + * the entire transfer). + * + * This function takes the current amount of data transferred, the amount at + * the starting point, the limit (in bytes/s), the time of the starting point + * and the current time. + * + * Returns 0 if no waiting is needed or when no waiting is needed but the + * starting point should be reset (to current); or the number of milliseconds + * to wait to get back under the speed limit. + */ +timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize, + curl_off_t startsize, + curl_off_t limit, + struct curltime start, + struct curltime now) +{ + curl_off_t size = cursize - startsize; + time_t minimum; + time_t actual; + + if(!limit || !size) + return 0; + + /* + * 'minimum' is the number of milliseconds 'size' should take to download to + * stay below 'limit'. + */ + if(size < CURL_OFF_T_MAX/1000) + minimum = (time_t) (CURL_OFF_T_C(1000) * size / limit); + else { + minimum = (time_t) (size / limit); + if(minimum < TIME_T_MAX/1000) + minimum *= 1000; + else + minimum = TIME_T_MAX; + } + + /* + * 'actual' is the time in milliseconds it took to actually download the + * last 'size' bytes. + */ + actual = Curl_timediff(now, start); + if(actual < minimum) { + /* if it downloaded the data faster than the limit, make it wait the + difference */ + return (minimum - actual); + } + + return 0; +} + +/* + * Set the number of downloaded bytes so far. + */ +void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size) +{ + data->progress.downloaded = size; +} + +/* + * Update the timestamp and sizestamp to use for rate limit calculations. + */ +void Curl_ratelimit(struct Curl_easy *data, struct curltime now) +{ + /* don't set a new stamp unless the time since last update is long enough */ + if(data->set.max_recv_speed > 0) { + if(Curl_timediff(now, data->progress.dl_limit_start) >= + MIN_RATE_LIMIT_PERIOD) { + data->progress.dl_limit_start = now; + data->progress.dl_limit_size = data->progress.downloaded; + } + } + if(data->set.max_send_speed > 0) { + if(Curl_timediff(now, data->progress.ul_limit_start) >= + MIN_RATE_LIMIT_PERIOD) { + data->progress.ul_limit_start = now; + data->progress.ul_limit_size = data->progress.uploaded; + } + } +} + +/* + * Set the number of uploaded bytes so far. + */ +void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size) +{ + data->progress.uploaded = size; +} + +void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size) +{ + if(size >= 0) { + data->progress.size_dl = size; + data->progress.flags |= PGRS_DL_SIZE_KNOWN; + } + else { + data->progress.size_dl = 0; + data->progress.flags &= ~PGRS_DL_SIZE_KNOWN; + } +} + +void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size) +{ + if(size >= 0) { + data->progress.size_ul = size; + data->progress.flags |= PGRS_UL_SIZE_KNOWN; + } + else { + data->progress.size_ul = 0; + data->progress.flags &= ~PGRS_UL_SIZE_KNOWN; + } +} + +#ifndef CURL_DISABLE_PROGRESS_METER +static void progress_meter(struct connectdata *conn) +{ + struct curltime now; + curl_off_t timespent; + curl_off_t timespent_ms; /* milliseconds */ + struct Curl_easy *data = conn->data; + bool shownow = FALSE; + curl_off_t dl = data->progress.downloaded; + curl_off_t ul = data->progress.uploaded; + + now = Curl_now(); /* what time is it */ + + /* The time spent so far (from the start) */ + data->progress.timespent = Curl_timediff_us(now, data->progress.start); + timespent = (curl_off_t)data->progress.timespent/1000000; /* seconds */ + timespent_ms = (curl_off_t)data->progress.timespent/1000; /* ms */ + + /* The average download speed this far */ + if(dl < CURL_OFF_T_MAX/1000) + data->progress.dlspeed = (dl * 1000 / (timespent_ms>0?timespent_ms:1)); + else + data->progress.dlspeed = (dl / (timespent>0?timespent:1)); + + /* The average upload speed this far */ + if(ul < CURL_OFF_T_MAX/1000) + data->progress.ulspeed = (ul * 1000 / (timespent_ms>0?timespent_ms:1)); + else + data->progress.ulspeed = (ul / (timespent>0?timespent:1)); + + /* Calculations done at most once a second, unless end is reached */ + if(data->progress.lastshow != now.tv_sec) { + int countindex; /* amount of seconds stored in the speeder array */ + int nowindex = data->progress.speeder_c% CURR_TIME; + if(!(data->progress.flags & PGRS_HIDE)) + shownow = TRUE; + + data->progress.lastshow = now.tv_sec; + + /* Let's do the "current speed" thing, with the dl + ul speeds + combined. Store the speed at entry 'nowindex'. */ + data->progress.speeder[ nowindex ] = + data->progress.downloaded + data->progress.uploaded; + + /* remember the exact time for this moment */ + data->progress.speeder_time [ nowindex ] = now; + + /* advance our speeder_c counter, which is increased every time we get + here and we expect it to never wrap as 2^32 is a lot of seconds! */ + data->progress.speeder_c++; + + /* figure out how many index entries of data we have stored in our speeder + array. With N_ENTRIES filled in, we have about N_ENTRIES-1 seconds of + transfer. Imagine, after one second we have filled in two entries, + after two seconds we've filled in three entries etc. */ + countindex = ((data->progress.speeder_c >= CURR_TIME)? + CURR_TIME:data->progress.speeder_c) - 1; + + /* first of all, we don't do this if there's no counted seconds yet */ + if(countindex) { + int checkindex; + timediff_t span_ms; + + /* Get the index position to compare with the 'nowindex' position. + Get the oldest entry possible. While we have less than CURR_TIME + entries, the first entry will remain the oldest. */ + checkindex = (data->progress.speeder_c >= CURR_TIME)? + data->progress.speeder_c%CURR_TIME:0; + + /* Figure out the exact time for the time span */ + span_ms = Curl_timediff(now, + data->progress.speeder_time[checkindex]); + if(0 == span_ms) + span_ms = 1; /* at least one millisecond MUST have passed */ + + /* Calculate the average speed the last 'span_ms' milliseconds */ + { + curl_off_t amount = data->progress.speeder[nowindex]- + data->progress.speeder[checkindex]; + + if(amount > CURL_OFF_T_C(4294967) /* 0xffffffff/1000 */) + /* the 'amount' value is bigger than would fit in 32 bits if + multiplied with 1000, so we use the double math for this */ + data->progress.current_speed = (curl_off_t) + ((double)amount/((double)span_ms/1000.0)); + else + /* the 'amount' value is small enough to fit within 32 bits even + when multiplied with 1000 */ + data->progress.current_speed = amount*CURL_OFF_T_C(1000)/span_ms; + } + } + else + /* the first second we use the average */ + data->progress.current_speed = + data->progress.ulspeed + data->progress.dlspeed; + + } /* Calculations end */ + if(!shownow) + /* only show the internal progress meter once per second */ + return; + else { + /* If there's no external callback set, use internal code to show + progress */ + /* progress meter has not been shut off */ + char max5[6][10]; + curl_off_t dlpercen = 0; + curl_off_t ulpercen = 0; + curl_off_t total_percen = 0; + curl_off_t total_transfer; + curl_off_t total_expected_transfer; + char time_left[10]; + char time_total[10]; + char time_spent[10]; + curl_off_t ulestimate = 0; + curl_off_t dlestimate = 0; + curl_off_t total_estimate; + + if(!(data->progress.flags & PGRS_HEADERS_OUT)) { + if(data->state.resume_from) { + fprintf(data->set.err, + "** Resuming transfer from byte position %" + CURL_FORMAT_CURL_OFF_T "\n", data->state.resume_from); + } + fprintf(data->set.err, + " %% Total %% Received %% Xferd Average Speed " + "Time Time Time Current\n" + " Dload Upload " + "Total Spent Left Speed\n"); + data->progress.flags |= PGRS_HEADERS_OUT; /* headers are shown */ + } + + /* Figure out the estimated time of arrival for the upload */ + if((data->progress.flags & PGRS_UL_SIZE_KNOWN) && + (data->progress.ulspeed > CURL_OFF_T_C(0))) { + ulestimate = data->progress.size_ul / data->progress.ulspeed; + + if(data->progress.size_ul > CURL_OFF_T_C(10000)) + ulpercen = data->progress.uploaded / + (data->progress.size_ul/CURL_OFF_T_C(100)); + else if(data->progress.size_ul > CURL_OFF_T_C(0)) + ulpercen = (data->progress.uploaded*100) / + data->progress.size_ul; + } + + /* ... and the download */ + if((data->progress.flags & PGRS_DL_SIZE_KNOWN) && + (data->progress.dlspeed > CURL_OFF_T_C(0))) { + dlestimate = data->progress.size_dl / data->progress.dlspeed; + + if(data->progress.size_dl > CURL_OFF_T_C(10000)) + dlpercen = data->progress.downloaded / + (data->progress.size_dl/CURL_OFF_T_C(100)); + else if(data->progress.size_dl > CURL_OFF_T_C(0)) + dlpercen = (data->progress.downloaded*100) / + data->progress.size_dl; + } + + /* Now figure out which of them is slower and use that one for the + total estimate! */ + total_estimate = ulestimate>dlestimate?ulestimate:dlestimate; + + /* create the three time strings */ + time2str(time_left, total_estimate > 0?(total_estimate - timespent):0); + time2str(time_total, total_estimate); + time2str(time_spent, timespent); + + /* Get the total amount of data expected to get transferred */ + total_expected_transfer = + ((data->progress.flags & PGRS_UL_SIZE_KNOWN)? + data->progress.size_ul:data->progress.uploaded)+ + ((data->progress.flags & PGRS_DL_SIZE_KNOWN)? + data->progress.size_dl:data->progress.downloaded); + + /* We have transferred this much so far */ + total_transfer = data->progress.downloaded + data->progress.uploaded; + + /* Get the percentage of data transferred so far */ + if(total_expected_transfer > CURL_OFF_T_C(10000)) + total_percen = total_transfer / + (total_expected_transfer/CURL_OFF_T_C(100)); + else if(total_expected_transfer > CURL_OFF_T_C(0)) + total_percen = (total_transfer*100) / total_expected_transfer; + + fprintf(data->set.err, + "\r" + "%3" CURL_FORMAT_CURL_OFF_T " %s " + "%3" CURL_FORMAT_CURL_OFF_T " %s " + "%3" CURL_FORMAT_CURL_OFF_T " %s %s %s %s %s %s %s", + total_percen, /* 3 letters */ /* total % */ + max5data(total_expected_transfer, max5[2]), /* total size */ + dlpercen, /* 3 letters */ /* rcvd % */ + max5data(data->progress.downloaded, max5[0]), /* rcvd size */ + ulpercen, /* 3 letters */ /* xfer % */ + max5data(data->progress.uploaded, max5[1]), /* xfer size */ + max5data(data->progress.dlspeed, max5[3]), /* avrg dl speed */ + max5data(data->progress.ulspeed, max5[4]), /* avrg ul speed */ + time_total, /* 8 letters */ /* total time */ + time_spent, /* 8 letters */ /* time spent */ + time_left, /* 8 letters */ /* time left */ + max5data(data->progress.current_speed, max5[5]) + ); + + /* we flush the output stream to make it appear as soon as possible */ + fflush(data->set.err); + } /* don't show now */ +} +#else + /* progress bar disabled */ +#define progress_meter(x) +#endif + + +/* + * Curl_pgrsUpdate() returns 0 for success or the value returned by the + * progress callback! + */ +int Curl_pgrsUpdate(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + if(!(data->progress.flags & PGRS_HIDE)) { + if(data->set.fxferinfo) { + int result; + /* There's a callback set, call that */ + Curl_set_in_callback(data, true); + result = data->set.fxferinfo(data->set.progress_client, + data->progress.size_dl, + data->progress.downloaded, + data->progress.size_ul, + data->progress.uploaded); + Curl_set_in_callback(data, false); + if(result) + failf(data, "Callback aborted"); + return result; + } + if(data->set.fprogress) { + int result; + /* The older deprecated callback is set, call that */ + Curl_set_in_callback(data, true); + result = data->set.fprogress(data->set.progress_client, + (double)data->progress.size_dl, + (double)data->progress.downloaded, + (double)data->progress.size_ul, + (double)data->progress.uploaded); + Curl_set_in_callback(data, false); + if(result) + failf(data, "Callback aborted"); + return result; + } + } + progress_meter(conn); + + return 0; +} diff --git a/dependencies/cmcurl/lib/progress.h b/dependencies/cmcurl/lib/progress.h new file mode 100644 index 0000000..3515ac6 --- /dev/null +++ b/dependencies/cmcurl/lib/progress.h @@ -0,0 +1,64 @@ +#ifndef HEADER_CURL_PROGRESS_H +#define HEADER_CURL_PROGRESS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "timeval.h" + + +typedef enum { + TIMER_NONE, + TIMER_STARTOP, + TIMER_STARTSINGLE, + TIMER_NAMELOOKUP, + TIMER_CONNECT, + TIMER_APPCONNECT, + TIMER_PRETRANSFER, + TIMER_STARTTRANSFER, + TIMER_POSTRANSFER, + TIMER_STARTACCEPT, + TIMER_REDIRECT, + TIMER_LAST /* must be last */ +} timerid; + +int Curl_pgrsDone(struct connectdata *); +void Curl_pgrsStartNow(struct Curl_easy *data); +void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size); +void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size); +void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size); +void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size); +void Curl_ratelimit(struct Curl_easy *data, struct curltime now); +int Curl_pgrsUpdate(struct connectdata *); +void Curl_pgrsResetTransferSizes(struct Curl_easy *data); +void Curl_pgrsTime(struct Curl_easy *data, timerid timer); +timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize, + curl_off_t startsize, + curl_off_t limit, + struct curltime start, + struct curltime now); + +#define PGRS_HIDE (1<<4) +#define PGRS_UL_SIZE_KNOWN (1<<5) +#define PGRS_DL_SIZE_KNOWN (1<<6) +#define PGRS_HEADERS_OUT (1<<7) /* set when the headers have been written */ + +#endif /* HEADER_CURL_PROGRESS_H */ diff --git a/dependencies/cmcurl/lib/psl.c b/dependencies/cmcurl/lib/psl.c new file mode 100644 index 0000000..568baff --- /dev/null +++ b/dependencies/cmcurl/lib/psl.c @@ -0,0 +1,111 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#ifdef USE_LIBPSL + +#include "psl.h" +#include "share.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +void Curl_psl_destroy(struct PslCache *pslcache) +{ + if(pslcache->psl) { + if(pslcache->dynamic) + psl_free((psl_ctx_t *) pslcache->psl); + pslcache->psl = NULL; + pslcache->dynamic = FALSE; + } +} + +static time_t now_seconds(void) +{ + struct curltime now = Curl_now(); + + return now.tv_sec; +} + +const psl_ctx_t *Curl_psl_use(struct Curl_easy *easy) +{ + struct PslCache *pslcache = easy->psl; + const psl_ctx_t *psl; + time_t now; + + if(!pslcache) + return NULL; + + Curl_share_lock(easy, CURL_LOCK_DATA_PSL, CURL_LOCK_ACCESS_SHARED); + now = now_seconds(); + if(!pslcache->psl || pslcache->expires <= now) { + /* Let a chance to other threads to do the job: avoids deadlock. */ + Curl_share_unlock(easy, CURL_LOCK_DATA_PSL); + + /* Update cache: this needs an exclusive lock. */ + Curl_share_lock(easy, CURL_LOCK_DATA_PSL, CURL_LOCK_ACCESS_SINGLE); + + /* Recheck in case another thread did the job. */ + now = now_seconds(); + if(!pslcache->psl || pslcache->expires <= now) { + bool dynamic = FALSE; + time_t expires = TIME_T_MAX; + +#if defined(PSL_VERSION_NUMBER) && PSL_VERSION_NUMBER >= 0x001000 + psl = psl_latest(NULL); + dynamic = psl != NULL; + /* Take care of possible time computation overflow. */ + expires = now < TIME_T_MAX - PSL_TTL? now + PSL_TTL: TIME_T_MAX; + + /* Only get the built-in PSL if we do not already have the "latest". */ + if(!psl && !pslcache->dynamic) +#endif + + psl = psl_builtin(); + + if(psl) { + Curl_psl_destroy(pslcache); + pslcache->psl = psl; + pslcache->dynamic = dynamic; + pslcache->expires = expires; + } + } + Curl_share_unlock(easy, CURL_LOCK_DATA_PSL); /* Release exclusive lock. */ + Curl_share_lock(easy, CURL_LOCK_DATA_PSL, CURL_LOCK_ACCESS_SHARED); + } + psl = pslcache->psl; + if(!psl) + Curl_share_unlock(easy, CURL_LOCK_DATA_PSL); + return psl; +} + +void Curl_psl_release(struct Curl_easy *easy) +{ + Curl_share_unlock(easy, CURL_LOCK_DATA_PSL); +} + +#endif /* USE_LIBPSL */ diff --git a/dependencies/cmcurl/lib/psl.h b/dependencies/cmcurl/lib/psl.h new file mode 100644 index 0000000..e9f99d0 --- /dev/null +++ b/dependencies/cmcurl/lib/psl.h @@ -0,0 +1,47 @@ +#ifndef HEADER_PSL_H +#define HEADER_PSL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifdef USE_LIBPSL +#include + +#define PSL_TTL (72 * 3600) /* PSL time to live before a refresh. */ + +struct PslCache { + const psl_ctx_t *psl; /* The PSL. */ + time_t expires; /* Time this PSL life expires. */ + bool dynamic; /* PSL should be released when no longer needed. */ +}; + +const psl_ctx_t *Curl_psl_use(struct Curl_easy *easy); +void Curl_psl_release(struct Curl_easy *easy); +void Curl_psl_destroy(struct PslCache *pslcache); + +#else + +#define Curl_psl_use(easy) NULL +#define Curl_psl_release(easy) +#define Curl_psl_destroy(pslcache) + +#endif /* USE_LIBPSL */ +#endif /* HEADER_PSL_H */ diff --git a/dependencies/cmcurl/lib/rand.c b/dependencies/cmcurl/lib/rand.c new file mode 100644 index 0000000..6ee45fe --- /dev/null +++ b/dependencies/cmcurl/lib/rand.c @@ -0,0 +1,187 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_FCNTL_H +#include +#endif + +#include +#include "vtls/vtls.h" +#include "sendf.h" +#include "rand.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +static CURLcode randit(struct Curl_easy *data, unsigned int *rnd) +{ + unsigned int r; + CURLcode result = CURLE_OK; + static unsigned int randseed; + static bool seeded = FALSE; + +#ifdef CURLDEBUG + char *force_entropy = getenv("CURL_ENTROPY"); + if(force_entropy) { + if(!seeded) { + unsigned int seed = 0; + size_t elen = strlen(force_entropy); + size_t clen = sizeof(seed); + size_t min = elen < clen ? elen : clen; + memcpy((char *)&seed, force_entropy, min); + randseed = ntohl(seed); + seeded = TRUE; + } + else + randseed++; + *rnd = randseed; + return CURLE_OK; + } +#endif + + /* data may be NULL! */ + result = Curl_ssl_random(data, (unsigned char *)rnd, sizeof(*rnd)); + if(result != CURLE_NOT_BUILT_IN) + /* only if there is no random function in the TLS backend do the non crypto + version, otherwise return result */ + return result; + + /* ---- non-cryptographic version following ---- */ + +#ifdef RANDOM_FILE + if(!seeded) { + /* if there's a random file to read a seed from, use it */ + int fd = open(RANDOM_FILE, O_RDONLY); + if(fd > -1) { + /* read random data into the randseed variable */ + ssize_t nread = read(fd, &randseed, sizeof(randseed)); + if(nread == sizeof(randseed)) + seeded = TRUE; + close(fd); + } + } +#endif + + if(!seeded) { + struct curltime now = Curl_now(); + infof(data, "WARNING: Using weak random seed\n"); + randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec; + randseed = randseed * 1103515245 + 12345; + randseed = randseed * 1103515245 + 12345; + randseed = randseed * 1103515245 + 12345; + seeded = TRUE; + } + + /* Return an unsigned 32-bit pseudo-random number. */ + r = randseed = randseed * 1103515245 + 12345; + *rnd = (r << 16) | ((r >> 16) & 0xFFFF); + return CURLE_OK; +} + +/* + * Curl_rand() stores 'num' number of random unsigned integers in the buffer + * 'rndptr' points to. + * + * If libcurl is built without TLS support or with a TLS backend that lacks a + * proper random API (Gskit, PolarSSL or mbedTLS), this function will use + * "weak" random. + * + * When built *with* TLS support and a backend that offers strong random, it + * will return error if it cannot provide strong random values. + * + * NOTE: 'data' may be passed in as NULL when coming from external API without + * easy handle! + * + */ + +CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num) +{ + CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT; + + DEBUGASSERT(num > 0); + + while(num) { + unsigned int r; + size_t left = num < sizeof(unsigned int) ? num : sizeof(unsigned int); + + result = randit(data, &r); + if(result) + return result; + + while(left) { + *rnd++ = (unsigned char)(r & 0xFF); + r >>= 8; + --num; + --left; + } + } + + return result; +} + +/* + * Curl_rand_hex() fills the 'rnd' buffer with a given 'num' size with random + * hexadecimal digits PLUS a zero terminating byte. It must be an odd number + * size. + */ + +CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd, + size_t num) +{ + CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT; + const char *hex = "0123456789abcdef"; + unsigned char buffer[128]; + unsigned char *bufp = buffer; + DEBUGASSERT(num > 1); + +#ifdef __clang_analyzer__ + /* This silences a scan-build warning about accessing this buffer with + uninitialized memory. */ + memset(buffer, 0, sizeof(buffer)); +#endif + + if((num/2 >= sizeof(buffer)) || !(num&1)) + /* make sure it fits in the local buffer and that it is an odd number! */ + return CURLE_BAD_FUNCTION_ARGUMENT; + + num--; /* save one for zero termination */ + + result = Curl_rand(data, buffer, num/2); + if(result) + return result; + + while(num) { + /* clang-tidy warns on this line without this comment: */ + /* NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult) */ + *rnd++ = hex[(*bufp & 0xF0)>>4]; + *rnd++ = hex[*bufp & 0x0F]; + bufp++; + num -= 2; + } + *rnd = 0; + + return result; +} diff --git a/dependencies/cmcurl/lib/rand.h b/dependencies/cmcurl/lib/rand.h new file mode 100644 index 0000000..5deb041 --- /dev/null +++ b/dependencies/cmcurl/lib/rand.h @@ -0,0 +1,50 @@ +#ifndef HEADER_CURL_RAND_H +#define HEADER_CURL_RAND_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Curl_rand() stores 'num' number of random unsigned characters in the buffer + * 'rnd' points to. + * + * If libcurl is built without TLS support or with a TLS backend that lacks a + * proper random API (Gskit, PolarSSL or mbedTLS), this function will use + * "weak" random. + * + * When built *with* TLS support and a backend that offers strong random, it + * will return error if it cannot provide strong random values. + * + * NOTE: 'data' may be passed in as NULL when coming from external API without + * easy handle! + * + */ +CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num); + +/* + * Curl_rand_hex() fills the 'rnd' buffer with a given 'num' size with random + * hexadecimal digits PLUS a zero terminating byte. It must be an odd number + * size. + */ +CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd, + size_t num); + +#endif /* HEADER_CURL_RAND_H */ diff --git a/dependencies/cmcurl/lib/rtsp.c b/dependencies/cmcurl/lib/rtsp.c new file mode 100644 index 0000000..74cf232 --- /dev/null +++ b/dependencies/cmcurl/lib/rtsp.c @@ -0,0 +1,827 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_RTSP + +#include "urldata.h" +#include +#include "transfer.h" +#include "sendf.h" +#include "multiif.h" +#include "http.h" +#include "url.h" +#include "progress.h" +#include "rtsp.h" +#include "strcase.h" +#include "select.h" +#include "connect.h" +#include "strdup.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#define RTP_PKT_CHANNEL(p) ((int)((unsigned char)((p)[1]))) + +#define RTP_PKT_LENGTH(p) ((((int)((unsigned char)((p)[2]))) << 8) | \ + ((int)((unsigned char)((p)[3])))) + +/* protocol-specific functions set up to be called by the main engine */ +static CURLcode rtsp_do(struct connectdata *conn, bool *done); +static CURLcode rtsp_done(struct connectdata *conn, CURLcode, bool premature); +static CURLcode rtsp_connect(struct connectdata *conn, bool *done); +static CURLcode rtsp_disconnect(struct connectdata *conn, bool dead); + +static int rtsp_getsock_do(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); + +/* + * Parse and write out any available RTP data. + * + * nread: amount of data left after k->str. will be modified if RTP + * data is parsed and k->str is moved up + * readmore: whether or not the RTP parser needs more data right away + */ +static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, + struct connectdata *conn, + ssize_t *nread, + bool *readmore); + +static CURLcode rtsp_setup_connection(struct connectdata *conn); +static unsigned int rtsp_conncheck(struct connectdata *check, + unsigned int checks_to_perform); + +/* this returns the socket to wait for in the DO and DOING state for the multi + interface and then we're always _sending_ a request and thus we wait for + the single socket to become writable only */ +static int rtsp_getsock_do(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + /* write mode */ + (void)numsocks; /* unused, we trust it to be at least 1 */ + socks[0] = conn->sock[FIRSTSOCKET]; + return GETSOCK_WRITESOCK(0); +} + +static +CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len); + + +/* + * RTSP handler interface. + */ +const struct Curl_handler Curl_handler_rtsp = { + "RTSP", /* scheme */ + rtsp_setup_connection, /* setup_connection */ + rtsp_do, /* do_it */ + rtsp_done, /* done */ + ZERO_NULL, /* do_more */ + rtsp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + rtsp_getsock_do, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + rtsp_disconnect, /* disconnect */ + rtsp_rtp_readwrite, /* readwrite */ + rtsp_conncheck, /* connection_check */ + PORT_RTSP, /* defport */ + CURLPROTO_RTSP, /* protocol */ + PROTOPT_NONE /* flags */ +}; + + +static CURLcode rtsp_setup_connection(struct connectdata *conn) +{ + struct RTSP *rtsp; + + conn->data->req.protop = rtsp = calloc(1, sizeof(struct RTSP)); + if(!rtsp) + return CURLE_OUT_OF_MEMORY; + + return CURLE_OK; +} + + +/* + * The server may send us RTP data at any point, and RTSPREQ_RECEIVE does not + * want to block the application forever while receiving a stream. Therefore, + * we cannot assume that an RTSP socket is dead just because it is readable. + * + * Instead, if it is readable, run Curl_connalive() to peek at the socket + * and distinguish between closed and data. + */ +static bool rtsp_connisdead(struct connectdata *check) +{ + int sval; + bool ret_val = TRUE; + + sval = SOCKET_READABLE(check->sock[FIRSTSOCKET], 0); + if(sval == 0) { + /* timeout */ + ret_val = FALSE; + } + else if(sval & CURL_CSELECT_ERR) { + /* socket is in an error state */ + ret_val = TRUE; + } + else if(sval & CURL_CSELECT_IN) { + /* readable with no error. could still be closed */ + ret_val = !Curl_connalive(check); + } + + return ret_val; +} + +/* + * Function to check on various aspects of a connection. + */ +static unsigned int rtsp_conncheck(struct connectdata *check, + unsigned int checks_to_perform) +{ + unsigned int ret_val = CONNRESULT_NONE; + + if(checks_to_perform & CONNCHECK_ISDEAD) { + if(rtsp_connisdead(check)) + ret_val |= CONNRESULT_DEAD; + } + + return ret_val; +} + + +static CURLcode rtsp_connect(struct connectdata *conn, bool *done) +{ + CURLcode httpStatus; + struct Curl_easy *data = conn->data; + + httpStatus = Curl_http_connect(conn, done); + + /* Initialize the CSeq if not already done */ + if(data->state.rtsp_next_client_CSeq == 0) + data->state.rtsp_next_client_CSeq = 1; + if(data->state.rtsp_next_server_CSeq == 0) + data->state.rtsp_next_server_CSeq = 1; + + conn->proto.rtspc.rtp_channel = -1; + + return httpStatus; +} + +static CURLcode rtsp_disconnect(struct connectdata *conn, bool dead) +{ + (void) dead; + Curl_safefree(conn->proto.rtspc.rtp_buf); + return CURLE_OK; +} + + +static CURLcode rtsp_done(struct connectdata *conn, + CURLcode status, bool premature) +{ + struct Curl_easy *data = conn->data; + struct RTSP *rtsp = data->req.protop; + CURLcode httpStatus; + + /* Bypass HTTP empty-reply checks on receive */ + if(data->set.rtspreq == RTSPREQ_RECEIVE) + premature = TRUE; + + httpStatus = Curl_http_done(conn, status, premature); + + if(rtsp) { + /* Check the sequence numbers */ + long CSeq_sent = rtsp->CSeq_sent; + long CSeq_recv = rtsp->CSeq_recv; + if((data->set.rtspreq != RTSPREQ_RECEIVE) && (CSeq_sent != CSeq_recv)) { + failf(data, + "The CSeq of this request %ld did not match the response %ld", + CSeq_sent, CSeq_recv); + return CURLE_RTSP_CSEQ_ERROR; + } + if(data->set.rtspreq == RTSPREQ_RECEIVE && + (conn->proto.rtspc.rtp_channel == -1)) { + infof(data, "Got an RTP Receive with a CSeq of %ld\n", CSeq_recv); + } + } + + return httpStatus; +} + +static CURLcode rtsp_do(struct connectdata *conn, bool *done) +{ + struct Curl_easy *data = conn->data; + CURLcode result = CURLE_OK; + Curl_RtspReq rtspreq = data->set.rtspreq; + struct RTSP *rtsp = data->req.protop; + Curl_send_buffer *req_buffer; + curl_off_t postsize = 0; /* for ANNOUNCE and SET_PARAMETER */ + curl_off_t putsize = 0; /* for ANNOUNCE and SET_PARAMETER */ + + const char *p_request = NULL; + const char *p_session_id = NULL; + const char *p_accept = NULL; + const char *p_accept_encoding = NULL; + const char *p_range = NULL; + const char *p_referrer = NULL; + const char *p_stream_uri = NULL; + const char *p_transport = NULL; + const char *p_uagent = NULL; + const char *p_proxyuserpwd = NULL; + const char *p_userpwd = NULL; + + *done = TRUE; + + rtsp->CSeq_sent = data->state.rtsp_next_client_CSeq; + rtsp->CSeq_recv = 0; + + /* Setup the 'p_request' pointer to the proper p_request string + * Since all RTSP requests are included here, there is no need to + * support custom requests like HTTP. + **/ + data->set.opt_no_body = TRUE; /* most requests don't contain a body */ + switch(rtspreq) { + default: + failf(data, "Got invalid RTSP request"); + return CURLE_BAD_FUNCTION_ARGUMENT; + case RTSPREQ_OPTIONS: + p_request = "OPTIONS"; + break; + case RTSPREQ_DESCRIBE: + p_request = "DESCRIBE"; + data->set.opt_no_body = FALSE; + break; + case RTSPREQ_ANNOUNCE: + p_request = "ANNOUNCE"; + break; + case RTSPREQ_SETUP: + p_request = "SETUP"; + break; + case RTSPREQ_PLAY: + p_request = "PLAY"; + break; + case RTSPREQ_PAUSE: + p_request = "PAUSE"; + break; + case RTSPREQ_TEARDOWN: + p_request = "TEARDOWN"; + break; + case RTSPREQ_GET_PARAMETER: + /* GET_PARAMETER's no_body status is determined later */ + p_request = "GET_PARAMETER"; + data->set.opt_no_body = FALSE; + break; + case RTSPREQ_SET_PARAMETER: + p_request = "SET_PARAMETER"; + break; + case RTSPREQ_RECORD: + p_request = "RECORD"; + break; + case RTSPREQ_RECEIVE: + p_request = ""; + /* Treat interleaved RTP as body*/ + data->set.opt_no_body = FALSE; + break; + case RTSPREQ_LAST: + failf(data, "Got invalid RTSP request: RTSPREQ_LAST"); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + + if(rtspreq == RTSPREQ_RECEIVE) { + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1); + + return result; + } + + p_session_id = data->set.str[STRING_RTSP_SESSION_ID]; + if(!p_session_id && + (rtspreq & ~(RTSPREQ_OPTIONS | RTSPREQ_DESCRIBE | RTSPREQ_SETUP))) { + failf(data, "Refusing to issue an RTSP request [%s] without a session ID.", + p_request); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + + /* Stream URI. Default to server '*' if not specified */ + if(data->set.str[STRING_RTSP_STREAM_URI]) { + p_stream_uri = data->set.str[STRING_RTSP_STREAM_URI]; + } + else { + p_stream_uri = "*"; + } + + /* Transport Header for SETUP requests */ + p_transport = Curl_checkheaders(conn, "Transport"); + if(rtspreq == RTSPREQ_SETUP && !p_transport) { + /* New Transport: setting? */ + if(data->set.str[STRING_RTSP_TRANSPORT]) { + Curl_safefree(conn->allocptr.rtsp_transport); + + conn->allocptr.rtsp_transport = + aprintf("Transport: %s\r\n", + data->set.str[STRING_RTSP_TRANSPORT]); + if(!conn->allocptr.rtsp_transport) + return CURLE_OUT_OF_MEMORY; + } + else { + failf(data, + "Refusing to issue an RTSP SETUP without a Transport: header."); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + + p_transport = conn->allocptr.rtsp_transport; + } + + /* Accept Headers for DESCRIBE requests */ + if(rtspreq == RTSPREQ_DESCRIBE) { + /* Accept Header */ + p_accept = Curl_checkheaders(conn, "Accept")? + NULL:"Accept: application/sdp\r\n"; + + /* Accept-Encoding header */ + if(!Curl_checkheaders(conn, "Accept-Encoding") && + data->set.str[STRING_ENCODING]) { + Curl_safefree(conn->allocptr.accept_encoding); + conn->allocptr.accept_encoding = + aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]); + + if(!conn->allocptr.accept_encoding) + return CURLE_OUT_OF_MEMORY; + + p_accept_encoding = conn->allocptr.accept_encoding; + } + } + + /* The User-Agent string might have been allocated in url.c already, because + it might have been used in the proxy connect, but if we have got a header + with the user-agent string specified, we erase the previously made string + here. */ + if(Curl_checkheaders(conn, "User-Agent") && conn->allocptr.uagent) { + Curl_safefree(conn->allocptr.uagent); + conn->allocptr.uagent = NULL; + } + else if(!Curl_checkheaders(conn, "User-Agent") && + data->set.str[STRING_USERAGENT]) { + p_uagent = conn->allocptr.uagent; + } + + /* setup the authentication headers */ + result = Curl_http_output_auth(conn, p_request, p_stream_uri, FALSE); + if(result) + return result; + + p_proxyuserpwd = conn->allocptr.proxyuserpwd; + p_userpwd = conn->allocptr.userpwd; + + /* Referrer */ + Curl_safefree(conn->allocptr.ref); + if(data->change.referer && !Curl_checkheaders(conn, "Referer")) + conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer); + else + conn->allocptr.ref = NULL; + + p_referrer = conn->allocptr.ref; + + /* + * Range Header + * Only applies to PLAY, PAUSE, RECORD + * + * Go ahead and use the Range stuff supplied for HTTP + */ + if(data->state.use_range && + (rtspreq & (RTSPREQ_PLAY | RTSPREQ_PAUSE | RTSPREQ_RECORD))) { + + /* Check to see if there is a range set in the custom headers */ + if(!Curl_checkheaders(conn, "Range") && data->state.range) { + Curl_safefree(conn->allocptr.rangeline); + conn->allocptr.rangeline = aprintf("Range: %s\r\n", data->state.range); + p_range = conn->allocptr.rangeline; + } + } + + /* + * Sanity check the custom headers + */ + if(Curl_checkheaders(conn, "CSeq")) { + failf(data, "CSeq cannot be set as a custom header."); + return CURLE_RTSP_CSEQ_ERROR; + } + if(Curl_checkheaders(conn, "Session")) { + failf(data, "Session ID cannot be set as a custom header."); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + + /* Initialize a dynamic send buffer */ + req_buffer = Curl_add_buffer_init(); + + if(!req_buffer) + return CURLE_OUT_OF_MEMORY; + + result = + Curl_add_bufferf(&req_buffer, + "%s %s RTSP/1.0\r\n" /* Request Stream-URI RTSP/1.0 */ + "CSeq: %ld\r\n", /* CSeq */ + p_request, p_stream_uri, rtsp->CSeq_sent); + if(result) + return result; + + /* + * Rather than do a normal alloc line, keep the session_id unformatted + * to make comparison easier + */ + if(p_session_id) { + result = Curl_add_bufferf(&req_buffer, "Session: %s\r\n", p_session_id); + if(result) + return result; + } + + /* + * Shared HTTP-like options + */ + result = Curl_add_bufferf(&req_buffer, + "%s" /* transport */ + "%s" /* accept */ + "%s" /* accept-encoding */ + "%s" /* range */ + "%s" /* referrer */ + "%s" /* user-agent */ + "%s" /* proxyuserpwd */ + "%s" /* userpwd */ + , + p_transport ? p_transport : "", + p_accept ? p_accept : "", + p_accept_encoding ? p_accept_encoding : "", + p_range ? p_range : "", + p_referrer ? p_referrer : "", + p_uagent ? p_uagent : "", + p_proxyuserpwd ? p_proxyuserpwd : "", + p_userpwd ? p_userpwd : ""); + + /* + * Free userpwd now --- cannot reuse this for Negotiate and possibly NTLM + * with basic and digest, it will be freed anyway by the next request + */ + Curl_safefree(conn->allocptr.userpwd); + conn->allocptr.userpwd = NULL; + + if(result) + return result; + + if((rtspreq == RTSPREQ_SETUP) || (rtspreq == RTSPREQ_DESCRIBE)) { + result = Curl_add_timecondition(data, req_buffer); + if(result) + return result; + } + + result = Curl_add_custom_headers(conn, FALSE, req_buffer); + if(result) + return result; + + if(rtspreq == RTSPREQ_ANNOUNCE || + rtspreq == RTSPREQ_SET_PARAMETER || + rtspreq == RTSPREQ_GET_PARAMETER) { + + if(data->set.upload) { + putsize = data->state.infilesize; + data->set.httpreq = HTTPREQ_PUT; + + } + else { + postsize = (data->state.infilesize != -1)? + data->state.infilesize: + (data->set.postfields? (curl_off_t)strlen(data->set.postfields):0); + data->set.httpreq = HTTPREQ_POST; + } + + if(putsize > 0 || postsize > 0) { + /* As stated in the http comments, it is probably not wise to + * actually set a custom Content-Length in the headers */ + if(!Curl_checkheaders(conn, "Content-Length")) { + result = + Curl_add_bufferf(&req_buffer, + "Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n", + (data->set.upload ? putsize : postsize)); + if(result) + return result; + } + + if(rtspreq == RTSPREQ_SET_PARAMETER || + rtspreq == RTSPREQ_GET_PARAMETER) { + if(!Curl_checkheaders(conn, "Content-Type")) { + result = Curl_add_bufferf(&req_buffer, + "Content-Type: text/parameters\r\n"); + if(result) + return result; + } + } + + if(rtspreq == RTSPREQ_ANNOUNCE) { + if(!Curl_checkheaders(conn, "Content-Type")) { + result = Curl_add_bufferf(&req_buffer, + "Content-Type: application/sdp\r\n"); + if(result) + return result; + } + } + + data->state.expect100header = FALSE; /* RTSP posts are simple/small */ + } + else if(rtspreq == RTSPREQ_GET_PARAMETER) { + /* Check for an empty GET_PARAMETER (heartbeat) request */ + data->set.httpreq = HTTPREQ_HEAD; + data->set.opt_no_body = TRUE; + } + } + + /* RTSP never allows chunked transfer */ + data->req.forbidchunk = TRUE; + /* Finish the request buffer */ + result = Curl_add_buffer(&req_buffer, "\r\n", 2); + if(result) + return result; + + if(postsize > 0) { + result = Curl_add_buffer(&req_buffer, data->set.postfields, + (size_t)postsize); + if(result) + return result; + } + + /* issue the request */ + result = Curl_add_buffer_send(&req_buffer, conn, + &data->info.request_size, 0, FIRSTSOCKET); + if(result) { + failf(data, "Failed sending RTSP request"); + return result; + } + + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, putsize?FIRSTSOCKET:-1); + + /* Increment the CSeq on success */ + data->state.rtsp_next_client_CSeq++; + + if(data->req.writebytecount) { + /* if a request-body has been sent off, we make sure this progress is + noted properly */ + Curl_pgrsSetUploadCounter(data, data->req.writebytecount); + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + } + + return result; +} + + +static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, + struct connectdata *conn, + ssize_t *nread, + bool *readmore) { + struct SingleRequest *k = &data->req; + struct rtsp_conn *rtspc = &(conn->proto.rtspc); + + char *rtp; /* moving pointer to rtp data */ + ssize_t rtp_dataleft; /* how much data left to parse in this round */ + char *scratch; + CURLcode result; + + if(rtspc->rtp_buf) { + /* There was some leftover data the last time. Merge buffers */ + char *newptr = Curl_saferealloc(rtspc->rtp_buf, + rtspc->rtp_bufsize + *nread); + if(!newptr) { + rtspc->rtp_buf = NULL; + rtspc->rtp_bufsize = 0; + return CURLE_OUT_OF_MEMORY; + } + rtspc->rtp_buf = newptr; + memcpy(rtspc->rtp_buf + rtspc->rtp_bufsize, k->str, *nread); + rtspc->rtp_bufsize += *nread; + rtp = rtspc->rtp_buf; + rtp_dataleft = rtspc->rtp_bufsize; + } + else { + /* Just parse the request buffer directly */ + rtp = k->str; + rtp_dataleft = *nread; + } + + while((rtp_dataleft > 0) && + (rtp[0] == '$')) { + if(rtp_dataleft > 4) { + int rtp_length; + + /* Parse the header */ + /* The channel identifier immediately follows and is 1 byte */ + rtspc->rtp_channel = RTP_PKT_CHANNEL(rtp); + + /* The length is two bytes */ + rtp_length = RTP_PKT_LENGTH(rtp); + + if(rtp_dataleft < rtp_length + 4) { + /* Need more - incomplete payload*/ + *readmore = TRUE; + break; + } + /* We have the full RTP interleaved packet + * Write out the header including the leading '$' */ + DEBUGF(infof(data, "RTP write channel %d rtp_length %d\n", + rtspc->rtp_channel, rtp_length)); + result = rtp_client_write(conn, &rtp[0], rtp_length + 4); + if(result) { + failf(data, "Got an error writing an RTP packet"); + *readmore = FALSE; + Curl_safefree(rtspc->rtp_buf); + rtspc->rtp_buf = NULL; + rtspc->rtp_bufsize = 0; + return result; + } + + /* Move forward in the buffer */ + rtp_dataleft -= rtp_length + 4; + rtp += rtp_length + 4; + + if(data->set.rtspreq == RTSPREQ_RECEIVE) { + /* If we are in a passive receive, give control back + * to the app as often as we can. + */ + k->keepon &= ~KEEP_RECV; + } + } + else { + /* Need more - incomplete header */ + *readmore = TRUE; + break; + } + } + + if(rtp_dataleft != 0 && rtp[0] == '$') { + DEBUGF(infof(data, "RTP Rewinding %zd %s\n", rtp_dataleft, + *readmore ? "(READMORE)" : "")); + + /* Store the incomplete RTP packet for a "rewind" */ + scratch = malloc(rtp_dataleft); + if(!scratch) { + Curl_safefree(rtspc->rtp_buf); + rtspc->rtp_buf = NULL; + rtspc->rtp_bufsize = 0; + return CURLE_OUT_OF_MEMORY; + } + memcpy(scratch, rtp, rtp_dataleft); + Curl_safefree(rtspc->rtp_buf); + rtspc->rtp_buf = scratch; + rtspc->rtp_bufsize = rtp_dataleft; + + /* As far as the transfer is concerned, this data is consumed */ + *nread = 0; + return CURLE_OK; + } + /* Fix up k->str to point just after the last RTP packet */ + k->str += *nread - rtp_dataleft; + + /* either all of the data has been read or... + * rtp now points at the next byte to parse + */ + if(rtp_dataleft > 0) + DEBUGASSERT(k->str[0] == rtp[0]); + + DEBUGASSERT(rtp_dataleft <= *nread); /* sanity check */ + + *nread = rtp_dataleft; + + /* If we get here, we have finished with the leftover/merge buffer */ + Curl_safefree(rtspc->rtp_buf); + rtspc->rtp_buf = NULL; + rtspc->rtp_bufsize = 0; + + return CURLE_OK; +} + +static +CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len) +{ + struct Curl_easy *data = conn->data; + size_t wrote; + curl_write_callback writeit; + void *user_ptr; + + if(len == 0) { + failf(data, "Cannot write a 0 size RTP packet."); + return CURLE_WRITE_ERROR; + } + + /* If the user has configured CURLOPT_INTERLEAVEFUNCTION then use that + function and any configured CURLOPT_INTERLEAVEDATA to write out the RTP + data. Otherwise, use the CURLOPT_WRITEFUNCTION with the CURLOPT_WRITEDATA + pointer to write out the RTP data. */ + if(data->set.fwrite_rtp) { + writeit = data->set.fwrite_rtp; + user_ptr = data->set.rtp_out; + } + else { + writeit = data->set.fwrite_func; + user_ptr = data->set.out; + } + + Curl_set_in_callback(data, true); + wrote = writeit(ptr, 1, len, user_ptr); + Curl_set_in_callback(data, false); + + if(CURL_WRITEFUNC_PAUSE == wrote) { + failf(data, "Cannot pause RTP"); + return CURLE_WRITE_ERROR; + } + + if(wrote != len) { + failf(data, "Failed writing RTP data"); + return CURLE_WRITE_ERROR; + } + + return CURLE_OK; +} + +CURLcode Curl_rtsp_parseheader(struct connectdata *conn, + char *header) +{ + struct Curl_easy *data = conn->data; + long CSeq = 0; + + if(checkprefix("CSeq:", header)) { + /* Store the received CSeq. Match is verified in rtsp_done */ + int nc = sscanf(&header[4], ": %ld", &CSeq); + if(nc == 1) { + struct RTSP *rtsp = data->req.protop; + rtsp->CSeq_recv = CSeq; /* mark the request */ + data->state.rtsp_CSeq_recv = CSeq; /* update the handle */ + } + else { + failf(data, "Unable to read the CSeq header: [%s]", header); + return CURLE_RTSP_CSEQ_ERROR; + } + } + else if(checkprefix("Session:", header)) { + char *start; + + /* Find the first non-space letter */ + start = header + 8; + while(*start && ISSPACE(*start)) + start++; + + if(!*start) { + failf(data, "Got a blank Session ID"); + } + else if(data->set.str[STRING_RTSP_SESSION_ID]) { + /* If the Session ID is set, then compare */ + if(strncmp(start, data->set.str[STRING_RTSP_SESSION_ID], + strlen(data->set.str[STRING_RTSP_SESSION_ID])) != 0) { + failf(data, "Got RTSP Session ID Line [%s], but wanted ID [%s]", + start, data->set.str[STRING_RTSP_SESSION_ID]); + return CURLE_RTSP_SESSION_ERROR; + } + } + else { + /* If the Session ID is not set, and we find it in a response, then set + * it. + * + * Allow any non whitespace content, up to the field separator or end of + * line. RFC 2326 isn't 100% clear on the session ID and for example + * gstreamer does url-encoded session ID's not covered by the standard. + */ + char *end = start; + while(*end && *end != ';' && !ISSPACE(*end)) + end++; + + /* Copy the id substring into a new buffer */ + data->set.str[STRING_RTSP_SESSION_ID] = malloc(end - start + 1); + if(data->set.str[STRING_RTSP_SESSION_ID] == NULL) + return CURLE_OUT_OF_MEMORY; + memcpy(data->set.str[STRING_RTSP_SESSION_ID], start, end - start); + (data->set.str[STRING_RTSP_SESSION_ID])[end - start] = '\0'; + } + } + return CURLE_OK; +} + +#endif /* CURL_DISABLE_RTSP */ diff --git a/dependencies/cmcurl/lib/rtsp.h b/dependencies/cmcurl/lib/rtsp.h new file mode 100644 index 0000000..2f9cc32 --- /dev/null +++ b/dependencies/cmcurl/lib/rtsp.h @@ -0,0 +1,66 @@ +#ifndef HEADER_CURL_RTSP_H +#define HEADER_CURL_RTSP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifndef CURL_DISABLE_RTSP + +extern const struct Curl_handler Curl_handler_rtsp; + +CURLcode Curl_rtsp_parseheader(struct connectdata *conn, char *header); + +#else +/* disabled */ +#define Curl_rtsp_parseheader(x,y) CURLE_NOT_BUILT_IN + +#endif /* CURL_DISABLE_RTSP */ + +/* + * RTSP Connection data + * + * Currently, only used for tracking incomplete RTP data reads + */ +struct rtsp_conn { + char *rtp_buf; + ssize_t rtp_bufsize; + int rtp_channel; +}; + +/**************************************************************************** + * RTSP unique setup + ***************************************************************************/ +struct RTSP { + /* + * http_wrapper MUST be the first element of this structure for the wrap + * logic to work. In this way, we get a cheap polymorphism because + * &(data->state.proto.rtsp) == &(data->state.proto.http) per the C spec + * + * HTTP functions can safely treat this as an HTTP struct, but RTSP aware + * functions can also index into the later elements. + */ + struct HTTP http_wrapper; /*wrap HTTP to do the heavy lifting */ + + long CSeq_sent; /* CSeq of this request */ + long CSeq_recv; /* CSeq received */ +}; + + +#endif /* HEADER_CURL_RTSP_H */ diff --git a/dependencies/cmcurl/lib/security.c b/dependencies/cmcurl/lib/security.c new file mode 100644 index 0000000..7695154 --- /dev/null +++ b/dependencies/cmcurl/lib/security.c @@ -0,0 +1,581 @@ +/* This source code was modified by Martin Hedenfalk for + * use in Curl. His latest changes were done 2000-09-18. + * + * It has since been patched and modified a lot by Daniel Stenberg + * to make it better applied to curl conditions, and to make + * it not use globals, pollute name space and more. This source code awaits a + * rewrite to work around the paragraph 2 in the BSD licenses as explained + * below. + * + * Copyright (c) 1998, 1999, 2017 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * + * Copyright (C) 2001 - 2019, Daniel Stenberg, , et al. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_FTP +#ifdef HAVE_GSSAPI + +#ifdef HAVE_NETDB_H +#include +#endif + +#include + +#include "urldata.h" +#include "curl_base64.h" +#include "curl_memory.h" +#include "curl_sec.h" +#include "ftp.h" +#include "sendf.h" +#include "strcase.h" +#include "warnless.h" +#include "strdup.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +static const struct { + enum protection_level level; + const char *name; +} level_names[] = { + { PROT_CLEAR, "clear" }, + { PROT_SAFE, "safe" }, + { PROT_CONFIDENTIAL, "confidential" }, + { PROT_PRIVATE, "private" } +}; + +static enum protection_level +name_to_level(const char *name) +{ + int i; + for(i = 0; i < (int)sizeof(level_names)/(int)sizeof(level_names[0]); i++) + if(checkprefix(name, level_names[i].name)) + return level_names[i].level; + return PROT_NONE; +} + +/* Convert a protocol |level| to its char representation. + We take an int to catch programming mistakes. */ +static char level_to_char(int level) +{ + switch(level) { + case PROT_CLEAR: + return 'C'; + case PROT_SAFE: + return 'S'; + case PROT_CONFIDENTIAL: + return 'E'; + case PROT_PRIVATE: + return 'P'; + case PROT_CMD: + /* Fall through */ + default: + /* Those 2 cases should not be reached! */ + break; + } + DEBUGASSERT(0); + /* Default to the most secure alternative. */ + return 'P'; +} + +/* Send an FTP command defined by |message| and the optional arguments. The + function returns the ftp_code. If an error occurs, -1 is returned. */ +static int ftp_send_command(struct connectdata *conn, const char *message, ...) +{ + int ftp_code; + ssize_t nread = 0; + va_list args; + char print_buffer[50]; + + va_start(args, message); + mvsnprintf(print_buffer, sizeof(print_buffer), message, args); + va_end(args); + + if(Curl_ftpsend(conn, print_buffer)) { + ftp_code = -1; + } + else { + if(Curl_GetFTPResponse(&nread, conn, &ftp_code)) + ftp_code = -1; + } + + (void)nread; /* Unused */ + return ftp_code; +} + +/* Read |len| from the socket |fd| and store it in |to|. Return a CURLcode + saying whether an error occurred or CURLE_OK if |len| was read. */ +static CURLcode +socket_read(curl_socket_t fd, void *to, size_t len) +{ + char *to_p = to; + CURLcode result; + ssize_t nread = 0; + + while(len > 0) { + result = Curl_read_plain(fd, to_p, len, &nread); + if(!result) { + len -= nread; + to_p += nread; + } + else { + if(result == CURLE_AGAIN) + continue; + return result; + } + } + return CURLE_OK; +} + + +/* Write |len| bytes from the buffer |to| to the socket |fd|. Return a + CURLcode saying whether an error occurred or CURLE_OK if |len| was + written. */ +static CURLcode +socket_write(struct connectdata *conn, curl_socket_t fd, const void *to, + size_t len) +{ + const char *to_p = to; + CURLcode result; + ssize_t written; + + while(len > 0) { + result = Curl_write_plain(conn, fd, to_p, len, &written); + if(!result) { + len -= written; + to_p += written; + } + else { + if(result == CURLE_AGAIN) + continue; + return result; + } + } + return CURLE_OK; +} + +static CURLcode read_data(struct connectdata *conn, + curl_socket_t fd, + struct krb5buffer *buf) +{ + int len; + void *tmp = NULL; + CURLcode result; + + result = socket_read(fd, &len, sizeof(len)); + if(result) + return result; + + if(len) { + /* only realloc if there was a length */ + len = ntohl(len); + tmp = Curl_saferealloc(buf->data, len); + } + if(tmp == NULL) + return CURLE_OUT_OF_MEMORY; + + buf->data = tmp; + result = socket_read(fd, buf->data, len); + if(result) + return result; + buf->size = conn->mech->decode(conn->app_data, buf->data, len, + conn->data_prot, conn); + buf->index = 0; + return CURLE_OK; +} + +static size_t +buffer_read(struct krb5buffer *buf, void *data, size_t len) +{ + if(buf->size - buf->index < len) + len = buf->size - buf->index; + memcpy(data, (char *)buf->data + buf->index, len); + buf->index += len; + return len; +} + +/* Matches Curl_recv signature */ +static ssize_t sec_recv(struct connectdata *conn, int sockindex, + char *buffer, size_t len, CURLcode *err) +{ + size_t bytes_read; + size_t total_read = 0; + curl_socket_t fd = conn->sock[sockindex]; + + *err = CURLE_OK; + + /* Handle clear text response. */ + if(conn->sec_complete == 0 || conn->data_prot == PROT_CLEAR) + return read(fd, buffer, len); + + if(conn->in_buffer.eof_flag) { + conn->in_buffer.eof_flag = 0; + return 0; + } + + bytes_read = buffer_read(&conn->in_buffer, buffer, len); + len -= bytes_read; + total_read += bytes_read; + buffer += bytes_read; + + while(len > 0) { + if(read_data(conn, fd, &conn->in_buffer)) + return -1; + if(conn->in_buffer.size == 0) { + if(bytes_read > 0) + conn->in_buffer.eof_flag = 1; + return bytes_read; + } + bytes_read = buffer_read(&conn->in_buffer, buffer, len); + len -= bytes_read; + total_read += bytes_read; + buffer += bytes_read; + } + return total_read; +} + +/* Send |length| bytes from |from| to the |fd| socket taking care of encoding + and negociating with the server. |from| can be NULL. */ +static void do_sec_send(struct connectdata *conn, curl_socket_t fd, + const char *from, int length) +{ + int bytes, htonl_bytes; /* 32-bit integers for htonl */ + char *buffer = NULL; + char *cmd_buffer; + size_t cmd_size = 0; + CURLcode error; + enum protection_level prot_level = conn->data_prot; + bool iscmd = (prot_level == PROT_CMD)?TRUE:FALSE; + + DEBUGASSERT(prot_level > PROT_NONE && prot_level < PROT_LAST); + + if(iscmd) { + if(!strncmp(from, "PASS ", 5) || !strncmp(from, "ACCT ", 5)) + prot_level = PROT_PRIVATE; + else + prot_level = conn->command_prot; + } + bytes = conn->mech->encode(conn->app_data, from, length, prot_level, + (void **)&buffer); + if(!buffer || bytes <= 0) + return; /* error */ + + if(iscmd) { + error = Curl_base64_encode(conn->data, buffer, curlx_sitouz(bytes), + &cmd_buffer, &cmd_size); + if(error) { + free(buffer); + return; /* error */ + } + if(cmd_size > 0) { + static const char *enc = "ENC "; + static const char *mic = "MIC "; + if(prot_level == PROT_PRIVATE) + socket_write(conn, fd, enc, 4); + else + socket_write(conn, fd, mic, 4); + + socket_write(conn, fd, cmd_buffer, cmd_size); + socket_write(conn, fd, "\r\n", 2); + infof(conn->data, "Send: %s%s\n", prot_level == PROT_PRIVATE?enc:mic, + cmd_buffer); + free(cmd_buffer); + } + } + else { + htonl_bytes = htonl(bytes); + socket_write(conn, fd, &htonl_bytes, sizeof(htonl_bytes)); + socket_write(conn, fd, buffer, curlx_sitouz(bytes)); + } + free(buffer); +} + +static ssize_t sec_write(struct connectdata *conn, curl_socket_t fd, + const char *buffer, size_t length) +{ + ssize_t tx = 0, len = conn->buffer_size; + + len -= conn->mech->overhead(conn->app_data, conn->data_prot, + curlx_sztosi(len)); + if(len <= 0) + len = length; + while(length) { + if(length < (size_t)len) + len = length; + + do_sec_send(conn, fd, buffer, curlx_sztosi(len)); + length -= len; + buffer += len; + tx += len; + } + return tx; +} + +/* Matches Curl_send signature */ +static ssize_t sec_send(struct connectdata *conn, int sockindex, + const void *buffer, size_t len, CURLcode *err) +{ + curl_socket_t fd = conn->sock[sockindex]; + *err = CURLE_OK; + return sec_write(conn, fd, buffer, len); +} + +int Curl_sec_read_msg(struct connectdata *conn, char *buffer, + enum protection_level level) +{ + /* decoded_len should be size_t or ssize_t but conn->mech->decode returns an + int */ + int decoded_len; + char *buf; + int ret_code = 0; + size_t decoded_sz = 0; + CURLcode error; + + if(!conn->mech) + /* not inititalized, return error */ + return -1; + + DEBUGASSERT(level > PROT_NONE && level < PROT_LAST); + + error = Curl_base64_decode(buffer + 4, (unsigned char **)&buf, &decoded_sz); + if(error || decoded_sz == 0) + return -1; + + if(decoded_sz > (size_t)INT_MAX) { + free(buf); + return -1; + } + decoded_len = curlx_uztosi(decoded_sz); + + decoded_len = conn->mech->decode(conn->app_data, buf, decoded_len, + level, conn); + if(decoded_len <= 0) { + free(buf); + return -1; + } + + if(conn->data->set.verbose) { + buf[decoded_len] = '\n'; + Curl_debug(conn->data, CURLINFO_HEADER_IN, buf, decoded_len + 1); + } + + buf[decoded_len] = '\0'; + if(decoded_len <= 3) + /* suspiciously short */ + return 0; + + if(buf[3] != '-') + /* safe to ignore return code */ + (void)sscanf(buf, "%d", &ret_code); + + if(buf[decoded_len - 1] == '\n') + buf[decoded_len - 1] = '\0'; + strcpy(buffer, buf); + free(buf); + return ret_code; +} + +static int sec_set_protection_level(struct connectdata *conn) +{ + int code; + enum protection_level level = conn->request_data_prot; + + DEBUGASSERT(level > PROT_NONE && level < PROT_LAST); + + if(!conn->sec_complete) { + infof(conn->data, "Trying to change the protection level after the" + " completion of the data exchange.\n"); + return -1; + } + + /* Bail out if we try to set up the same level */ + if(conn->data_prot == level) + return 0; + + if(level) { + char *pbsz; + static unsigned int buffer_size = 1 << 20; /* 1048576 */ + + code = ftp_send_command(conn, "PBSZ %u", buffer_size); + if(code < 0) + return -1; + + if(code/100 != 2) { + failf(conn->data, "Failed to set the protection's buffer size."); + return -1; + } + conn->buffer_size = buffer_size; + + pbsz = strstr(conn->data->state.buffer, "PBSZ="); + if(pbsz) { + /* ignore return code, use default value if it fails */ + (void)sscanf(pbsz, "PBSZ=%u", &buffer_size); + if(buffer_size < conn->buffer_size) + conn->buffer_size = buffer_size; + } + } + + /* Now try to negiociate the protection level. */ + code = ftp_send_command(conn, "PROT %c", level_to_char(level)); + + if(code < 0) + return -1; + + if(code/100 != 2) { + failf(conn->data, "Failed to set the protection level."); + return -1; + } + + conn->data_prot = level; + if(level == PROT_PRIVATE) + conn->command_prot = level; + + return 0; +} + +int +Curl_sec_request_prot(struct connectdata *conn, const char *level) +{ + enum protection_level l = name_to_level(level); + if(l == PROT_NONE) + return -1; + DEBUGASSERT(l > PROT_NONE && l < PROT_LAST); + conn->request_data_prot = l; + return 0; +} + +static CURLcode choose_mech(struct connectdata *conn) +{ + int ret; + struct Curl_easy *data = conn->data; + void *tmp_allocation; + const struct Curl_sec_client_mech *mech = &Curl_krb5_client_mech; + + tmp_allocation = realloc(conn->app_data, mech->size); + if(tmp_allocation == NULL) { + failf(data, "Failed realloc of size %zu", mech->size); + mech = NULL; + return CURLE_OUT_OF_MEMORY; + } + conn->app_data = tmp_allocation; + + if(mech->init) { + ret = mech->init(conn->app_data); + if(ret) { + infof(data, "Failed initialization for %s. Skipping it.\n", + mech->name); + return CURLE_FAILED_INIT; + } + } + + infof(data, "Trying mechanism %s...\n", mech->name); + ret = ftp_send_command(conn, "AUTH %s", mech->name); + if(ret < 0) + return CURLE_COULDNT_CONNECT; + + if(ret/100 != 3) { + switch(ret) { + case 504: + infof(data, "Mechanism %s is not supported by the server (server " + "returned ftp code: 504).\n", mech->name); + break; + case 534: + infof(data, "Mechanism %s was rejected by the server (server returned " + "ftp code: 534).\n", mech->name); + break; + default: + if(ret/100 == 5) { + infof(data, "server does not support the security extensions\n"); + return CURLE_USE_SSL_FAILED; + } + break; + } + return CURLE_LOGIN_DENIED; + } + + /* Authenticate */ + ret = mech->auth(conn->app_data, conn); + + if(ret != AUTH_CONTINUE) { + if(ret != AUTH_OK) { + /* Mechanism has dumped the error to stderr, don't error here. */ + return -1; + } + DEBUGASSERT(ret == AUTH_OK); + + conn->mech = mech; + conn->sec_complete = 1; + conn->recv[FIRSTSOCKET] = sec_recv; + conn->send[FIRSTSOCKET] = sec_send; + conn->recv[SECONDARYSOCKET] = sec_recv; + conn->send[SECONDARYSOCKET] = sec_send; + conn->command_prot = PROT_SAFE; + /* Set the requested protection level */ + /* BLOCKING */ + (void)sec_set_protection_level(conn); + } + + return CURLE_OK; +} + +CURLcode +Curl_sec_login(struct connectdata *conn) +{ + return choose_mech(conn); +} + + +void +Curl_sec_end(struct connectdata *conn) +{ + if(conn->mech != NULL && conn->mech->end) + conn->mech->end(conn->app_data); + free(conn->app_data); + conn->app_data = NULL; + if(conn->in_buffer.data) { + free(conn->in_buffer.data); + conn->in_buffer.data = NULL; + conn->in_buffer.size = 0; + conn->in_buffer.index = 0; + conn->in_buffer.eof_flag = 0; + } + conn->sec_complete = 0; + conn->data_prot = PROT_CLEAR; + conn->mech = NULL; +} + +#endif /* HAVE_GSSAPI */ + +#endif /* CURL_DISABLE_FTP */ diff --git a/dependencies/cmcurl/lib/select.c b/dependencies/cmcurl/lib/select.c new file mode 100644 index 0000000..6e73890 --- /dev/null +++ b/dependencies/cmcurl/lib/select.c @@ -0,0 +1,585 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_SYS_SELECT_H +#include +#endif + +#if !defined(HAVE_SELECT) && !defined(HAVE_POLL_FINE) +#error "We can't compile without select() or poll() support." +#endif + +#if defined(__BEOS__) +/* BeOS has FD_SET defined in socket.h */ +#include +#endif + +#ifdef MSDOS +#include /* delay() */ +#endif + +#ifdef __VXWORKS__ +#include /* bzero() in FD_SET */ +#endif + +#include + +#include "urldata.h" +#include "connect.h" +#include "select.h" +#include "warnless.h" + +/* Convenience local macros */ +#define ELAPSED_MS() (int)Curl_timediff(Curl_now(), initial_tv) + +int Curl_ack_eintr = 0; +#define ERROR_NOT_EINTR(error) (Curl_ack_eintr || error != EINTR) + +/* + * Internal function used for waiting a specific amount of ms + * in Curl_socket_check() and Curl_poll() when no file descriptor + * is provided to wait on, just being used to delay execution. + * WinSock select() and poll() timeout mechanisms need a valid + * socket descriptor in a not null file descriptor set to work. + * Waiting indefinitely with this function is not allowed, a + * zero or negative timeout value will return immediately. + * Timeout resolution, accuracy, as well as maximum supported + * value is system dependent, neither factor is a citical issue + * for the intended use of this function in the library. + * + * Return values: + * -1 = system call error, invalid timeout value, or interrupted + * 0 = specified timeout has elapsed + */ +int Curl_wait_ms(int timeout_ms) +{ +#if !defined(MSDOS) && !defined(USE_WINSOCK) +#ifndef HAVE_POLL_FINE + struct timeval pending_tv; +#endif + struct curltime initial_tv; + int pending_ms; +#endif + int r = 0; + + if(!timeout_ms) + return 0; + if(timeout_ms < 0) { + SET_SOCKERRNO(EINVAL); + return -1; + } +#if defined(MSDOS) + delay(timeout_ms); +#elif defined(USE_WINSOCK) + Sleep(timeout_ms); +#else + pending_ms = timeout_ms; + initial_tv = Curl_now(); + do { + int error; +#if defined(HAVE_POLL_FINE) + r = poll(NULL, 0, pending_ms); +#else + pending_tv.tv_sec = pending_ms / 1000; + pending_tv.tv_usec = (pending_ms % 1000) * 1000; + r = select(0, NULL, NULL, NULL, &pending_tv); +#endif /* HAVE_POLL_FINE */ + if(r != -1) + break; + error = SOCKERRNO; + if(error && ERROR_NOT_EINTR(error)) + break; + pending_ms = timeout_ms - ELAPSED_MS(); + if(pending_ms <= 0) { + r = 0; /* Simulate a "call timed out" case */ + break; + } + } while(r == -1); +#endif /* USE_WINSOCK */ + if(r) + r = -1; + return r; +} + +/* + * Wait for read or write events on a set of file descriptors. It uses poll() + * when a fine poll() is available, in order to avoid limits with FD_SETSIZE, + * otherwise select() is used. An error is returned if select() is being used + * and a file descriptor is too large for FD_SETSIZE. + * + * A negative timeout value makes this function wait indefinitely, + * unless no valid file descriptor is given, when this happens the + * negative timeout is ignored and the function times out immediately. + * + * Return values: + * -1 = system call error or fd >= FD_SETSIZE + * 0 = timeout + * [bitmask] = action as described below + * + * CURL_CSELECT_IN - first socket is readable + * CURL_CSELECT_IN2 - second socket is readable + * CURL_CSELECT_OUT - write socket is writable + * CURL_CSELECT_ERR - an error condition occurred + */ +int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ + curl_socket_t readfd1, + curl_socket_t writefd, /* socket to write to */ + time_t timeout_ms) /* milliseconds to wait */ +{ +#ifdef HAVE_POLL_FINE + struct pollfd pfd[3]; + int num; +#else + struct timeval pending_tv; + struct timeval *ptimeout; + fd_set fds_read; + fd_set fds_write; + fd_set fds_err; + curl_socket_t maxfd; +#endif + struct curltime initial_tv = {0, 0}; + int pending_ms = 0; + int r; + int ret; + +#if SIZEOF_TIME_T != SIZEOF_INT + /* wrap-around precaution */ + if(timeout_ms >= INT_MAX) + timeout_ms = INT_MAX; +#endif + + if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) && + (writefd == CURL_SOCKET_BAD)) { + /* no sockets, just wait */ + r = Curl_wait_ms((int)timeout_ms); + return r; + } + + /* Avoid initial timestamp, avoid Curl_now() call, when elapsed + time in this function does not need to be measured. This happens + when function is called with a zero timeout or a negative timeout + value indicating a blocking call should be performed. */ + + if(timeout_ms > 0) { + pending_ms = (int)timeout_ms; + initial_tv = Curl_now(); + } + +#ifdef HAVE_POLL_FINE + + num = 0; + if(readfd0 != CURL_SOCKET_BAD) { + pfd[num].fd = readfd0; + pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI; + pfd[num].revents = 0; + num++; + } + if(readfd1 != CURL_SOCKET_BAD) { + pfd[num].fd = readfd1; + pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI; + pfd[num].revents = 0; + num++; + } + if(writefd != CURL_SOCKET_BAD) { + pfd[num].fd = writefd; + pfd[num].events = POLLWRNORM|POLLOUT; + pfd[num].revents = 0; + num++; + } + + do { + int error; + if(timeout_ms < 0) + pending_ms = -1; + else if(!timeout_ms) + pending_ms = 0; + r = poll(pfd, num, pending_ms); + if(r != -1) + break; + error = SOCKERRNO; + if(error && ERROR_NOT_EINTR(error)) + break; + if(timeout_ms > 0) { + pending_ms = (int)(timeout_ms - ELAPSED_MS()); + if(pending_ms <= 0) { + r = 0; /* Simulate a "call timed out" case */ + break; + } + } + } while(r == -1); + + if(r < 0) + return -1; + if(r == 0) + return 0; + + ret = 0; + num = 0; + if(readfd0 != CURL_SOCKET_BAD) { + if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP)) + ret |= CURL_CSELECT_IN; + if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL)) + ret |= CURL_CSELECT_ERR; + num++; + } + if(readfd1 != CURL_SOCKET_BAD) { + if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP)) + ret |= CURL_CSELECT_IN2; + if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL)) + ret |= CURL_CSELECT_ERR; + num++; + } + if(writefd != CURL_SOCKET_BAD) { + if(pfd[num].revents & (POLLWRNORM|POLLOUT)) + ret |= CURL_CSELECT_OUT; + if(pfd[num].revents & (POLLERR|POLLHUP|POLLNVAL)) + ret |= CURL_CSELECT_ERR; + } + + return ret; + +#else /* HAVE_POLL_FINE */ + + FD_ZERO(&fds_err); + maxfd = (curl_socket_t)-1; + + FD_ZERO(&fds_read); + if(readfd0 != CURL_SOCKET_BAD) { + VERIFY_SOCK(readfd0); + FD_SET(readfd0, &fds_read); + FD_SET(readfd0, &fds_err); + maxfd = readfd0; + } + if(readfd1 != CURL_SOCKET_BAD) { + VERIFY_SOCK(readfd1); + FD_SET(readfd1, &fds_read); + FD_SET(readfd1, &fds_err); + if(readfd1 > maxfd) + maxfd = readfd1; + } + + FD_ZERO(&fds_write); + if(writefd != CURL_SOCKET_BAD) { + VERIFY_SOCK(writefd); + FD_SET(writefd, &fds_write); + FD_SET(writefd, &fds_err); + if(writefd > maxfd) + maxfd = writefd; + } + + ptimeout = (timeout_ms < 0) ? NULL : &pending_tv; + + do { + int error; + if(timeout_ms > 0) { + pending_tv.tv_sec = pending_ms / 1000; + pending_tv.tv_usec = (pending_ms % 1000) * 1000; + } + else if(!timeout_ms) { + pending_tv.tv_sec = 0; + pending_tv.tv_usec = 0; + } + + /* WinSock select() must not be called with an fd_set that contains zero + fd flags, or it will return WSAEINVAL. But, it also can't be called + with no fd_sets at all! From the documentation: + + Any two of the parameters, readfds, writefds, or exceptfds, can be + given as null. At least one must be non-null, and any non-null + descriptor set must contain at least one handle to a socket. + + We know that we have at least one bit set in at least two fd_sets in + this case, but we may have no bits set in either fds_read or fd_write, + so check for that and handle it. Luckily, with WinSock, we can _also_ + ask how many bits are set on an fd_set. + + It is unclear why WinSock doesn't just handle this for us instead of + calling this an error. + + Note also that WinSock ignores the first argument, so we don't worry + about the fact that maxfd is computed incorrectly with WinSock (since + curl_socket_t is unsigned in such cases and thus -1 is the largest + value). + */ +#ifdef USE_WINSOCK + r = select((int)maxfd + 1, + fds_read.fd_count ? &fds_read : NULL, + fds_write.fd_count ? &fds_write : NULL, + &fds_err, ptimeout); +#else + r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout); +#endif + + if(r != -1) + break; + error = SOCKERRNO; + if(error && ERROR_NOT_EINTR(error)) + break; + if(timeout_ms > 0) { + pending_ms = (int)(timeout_ms - ELAPSED_MS()); + if(pending_ms <= 0) { + r = 0; /* Simulate a "call timed out" case */ + break; + } + } + } while(r == -1); + + if(r < 0) + return -1; + if(r == 0) + return 0; + + ret = 0; + if(readfd0 != CURL_SOCKET_BAD) { + if(FD_ISSET(readfd0, &fds_read)) + ret |= CURL_CSELECT_IN; + if(FD_ISSET(readfd0, &fds_err)) + ret |= CURL_CSELECT_ERR; + } + if(readfd1 != CURL_SOCKET_BAD) { + if(FD_ISSET(readfd1, &fds_read)) + ret |= CURL_CSELECT_IN2; + if(FD_ISSET(readfd1, &fds_err)) + ret |= CURL_CSELECT_ERR; + } + if(writefd != CURL_SOCKET_BAD) { + if(FD_ISSET(writefd, &fds_write)) + ret |= CURL_CSELECT_OUT; + if(FD_ISSET(writefd, &fds_err)) + ret |= CURL_CSELECT_ERR; + } + + return ret; + +#endif /* HAVE_POLL_FINE */ + +} + +/* + * This is a wrapper around poll(). If poll() does not exist, then + * select() is used instead. An error is returned if select() is + * being used and a file descriptor is too large for FD_SETSIZE. + * A negative timeout value makes this function wait indefinitely, + * unless no valid file descriptor is given, when this happens the + * negative timeout is ignored and the function times out immediately. + * + * Return values: + * -1 = system call error or fd >= FD_SETSIZE + * 0 = timeout + * N = number of structures with non zero revent fields + */ +int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms) +{ +#ifndef HAVE_POLL_FINE + struct timeval pending_tv; + struct timeval *ptimeout; + fd_set fds_read; + fd_set fds_write; + fd_set fds_err; + curl_socket_t maxfd; +#endif + struct curltime initial_tv = {0, 0}; + bool fds_none = TRUE; + unsigned int i; + int pending_ms = 0; + int r; + + if(ufds) { + for(i = 0; i < nfds; i++) { + if(ufds[i].fd != CURL_SOCKET_BAD) { + fds_none = FALSE; + break; + } + } + } + if(fds_none) { + r = Curl_wait_ms(timeout_ms); + return r; + } + + /* Avoid initial timestamp, avoid Curl_now() call, when elapsed + time in this function does not need to be measured. This happens + when function is called with a zero timeout or a negative timeout + value indicating a blocking call should be performed. */ + + if(timeout_ms > 0) { + pending_ms = timeout_ms; + initial_tv = Curl_now(); + } + +#ifdef HAVE_POLL_FINE + + do { + int error; + if(timeout_ms < 0) + pending_ms = -1; + else if(!timeout_ms) + pending_ms = 0; + r = poll(ufds, nfds, pending_ms); + if(r != -1) + break; + error = SOCKERRNO; + if(error && ERROR_NOT_EINTR(error)) + break; + if(timeout_ms > 0) { + pending_ms = (int)(timeout_ms - ELAPSED_MS()); + if(pending_ms <= 0) { + r = 0; /* Simulate a "call timed out" case */ + break; + } + } + } while(r == -1); + + if(r < 0) + return -1; + if(r == 0) + return 0; + + for(i = 0; i < nfds; i++) { + if(ufds[i].fd == CURL_SOCKET_BAD) + continue; + if(ufds[i].revents & POLLHUP) + ufds[i].revents |= POLLIN; + if(ufds[i].revents & POLLERR) + ufds[i].revents |= (POLLIN|POLLOUT); + } + +#else /* HAVE_POLL_FINE */ + + FD_ZERO(&fds_read); + FD_ZERO(&fds_write); + FD_ZERO(&fds_err); + maxfd = (curl_socket_t)-1; + + for(i = 0; i < nfds; i++) { + ufds[i].revents = 0; + if(ufds[i].fd == CURL_SOCKET_BAD) + continue; + VERIFY_SOCK(ufds[i].fd); + if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI| + POLLRDNORM|POLLWRNORM|POLLRDBAND)) { + if(ufds[i].fd > maxfd) + maxfd = ufds[i].fd; + if(ufds[i].events & (POLLRDNORM|POLLIN)) + FD_SET(ufds[i].fd, &fds_read); + if(ufds[i].events & (POLLWRNORM|POLLOUT)) + FD_SET(ufds[i].fd, &fds_write); + if(ufds[i].events & (POLLRDBAND|POLLPRI)) + FD_SET(ufds[i].fd, &fds_err); + } + } + +#ifdef USE_WINSOCK + /* WinSock select() can't handle zero events. See the comment about this in + Curl_check_socket(). */ + if(fds_read.fd_count == 0 && fds_write.fd_count == 0 + && fds_err.fd_count == 0) { + r = Curl_wait_ms(timeout_ms); + return r; + } +#endif + + ptimeout = (timeout_ms < 0) ? NULL : &pending_tv; + + do { + int error; + if(timeout_ms > 0) { + pending_tv.tv_sec = pending_ms / 1000; + pending_tv.tv_usec = (pending_ms % 1000) * 1000; + } + else if(!timeout_ms) { + pending_tv.tv_sec = 0; + pending_tv.tv_usec = 0; + } + +#ifdef USE_WINSOCK + r = select((int)maxfd + 1, + /* WinSock select() can't handle fd_sets with zero bits set, so + don't give it such arguments. See the comment about this in + Curl_check_socket(). + */ + fds_read.fd_count ? &fds_read : NULL, + fds_write.fd_count ? &fds_write : NULL, + fds_err.fd_count ? &fds_err : NULL, ptimeout); +#else + r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout); +#endif + if(r != -1) + break; + error = SOCKERRNO; + if(error && ERROR_NOT_EINTR(error)) + break; + if(timeout_ms > 0) { + pending_ms = timeout_ms - ELAPSED_MS(); + if(pending_ms <= 0) { + r = 0; /* Simulate a "call timed out" case */ + break; + } + } + } while(r == -1); + + if(r < 0) + return -1; + if(r == 0) + return 0; + + r = 0; + for(i = 0; i < nfds; i++) { + ufds[i].revents = 0; + if(ufds[i].fd == CURL_SOCKET_BAD) + continue; + if(FD_ISSET(ufds[i].fd, &fds_read)) + ufds[i].revents |= POLLIN; + if(FD_ISSET(ufds[i].fd, &fds_write)) + ufds[i].revents |= POLLOUT; + if(FD_ISSET(ufds[i].fd, &fds_err)) + ufds[i].revents |= POLLPRI; + if(ufds[i].revents != 0) + r++; + } + +#endif /* HAVE_POLL_FINE */ + + return r; +} + +#ifdef TPF +/* + * This is a replacement for select() on the TPF platform. + * It is used whenever libcurl calls select(). + * The call below to tpf_process_signals() is required because + * TPF's select calls are not signal interruptible. + * + * Return values are the same as select's. + */ +int tpf_select_libcurl(int maxfds, fd_set *reads, fd_set *writes, + fd_set *excepts, struct timeval *tv) +{ + int rc; + + rc = tpf_select_bsd(maxfds, reads, writes, excepts, tv); + tpf_process_signals(); + return rc; +} +#endif /* TPF */ diff --git a/dependencies/cmcurl/lib/select.h b/dependencies/cmcurl/lib/select.h new file mode 100644 index 0000000..9a1ba45 --- /dev/null +++ b/dependencies/cmcurl/lib/select.h @@ -0,0 +1,115 @@ +#ifndef HEADER_CURL_SELECT_H +#define HEADER_CURL_SELECT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_POLL_H +#include +#elif defined(HAVE_SYS_POLL_H) +#include +#endif + +/* + * Definition of pollfd struct and constants for platforms lacking them. + */ + +#if !defined(HAVE_STRUCT_POLLFD) && \ + !defined(HAVE_SYS_POLL_H) && \ + !defined(HAVE_POLL_H) && \ + !defined(POLLIN) + +#define POLLIN 0x01 +#define POLLPRI 0x02 +#define POLLOUT 0x04 +#define POLLERR 0x08 +#define POLLHUP 0x10 +#define POLLNVAL 0x20 + +struct pollfd +{ + curl_socket_t fd; + short events; + short revents; +}; + +#endif + +#ifndef POLLRDNORM +#define POLLRDNORM POLLIN +#endif + +#ifndef POLLWRNORM +#define POLLWRNORM POLLOUT +#endif + +#ifndef POLLRDBAND +#define POLLRDBAND POLLPRI +#endif + +/* there are three CSELECT defines that are defined in the public header that + are exposed to users, but this *IN2 bit is only ever used internally and + therefore defined here */ +#define CURL_CSELECT_IN2 (CURL_CSELECT_ERR << 1) + +int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2, + curl_socket_t writefd, + time_t timeout_ms); + +#define SOCKET_READABLE(x,z) \ + Curl_socket_check(x, CURL_SOCKET_BAD, CURL_SOCKET_BAD, z) +#define SOCKET_WRITABLE(x,z) \ + Curl_socket_check(CURL_SOCKET_BAD, CURL_SOCKET_BAD, x, z) + +int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms); + +/* On non-DOS and non-Winsock platforms, when Curl_ack_eintr is set, + * EINTR condition is honored and function might exit early without + * awaiting full timeout. Otherwise EINTR will be ignored and full + * timeout will elapse. */ +extern int Curl_ack_eintr; + +int Curl_wait_ms(int timeout_ms); + +#ifdef TPF +int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes, + fd_set* excepts, struct timeval* tv); +#endif + +/* Winsock and TPF sockets are not in range [0..FD_SETSIZE-1], which + unfortunately makes it impossible for us to easily check if they're valid +*/ +#if defined(USE_WINSOCK) || defined(TPF) +#define VALID_SOCK(x) 1 +#define VERIFY_SOCK(x) Curl_nop_stmt +#else +#define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE)) +#define VERIFY_SOCK(x) do { \ + if(!VALID_SOCK(x)) { \ + SET_SOCKERRNO(EINVAL); \ + return -1; \ + } \ +} WHILE_FALSE +#endif + +#endif /* HEADER_CURL_SELECT_H */ diff --git a/dependencies/cmcurl/lib/sendf.c b/dependencies/cmcurl/lib/sendf.c new file mode 100644 index 0000000..5913ea4 --- /dev/null +++ b/dependencies/cmcurl/lib/sendf.c @@ -0,0 +1,821 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_LINUX_TCP_H +#include +#endif + +#include + +#include "urldata.h" +#include "sendf.h" +#include "connect.h" +#include "vtls/vtls.h" +#include "ssh.h" +#include "easyif.h" +#include "multiif.h" +#include "non-ascii.h" +#include "strerror.h" +#include "select.h" +#include "strdup.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#ifdef CURL_DO_LINEEND_CONV +/* + * convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF + * (\n), with special processing for CRLF sequences that are split between two + * blocks of data. Remaining, bare CRs are changed to LFs. The possibly new + * size of the data is returned. + */ +static size_t convert_lineends(struct Curl_easy *data, + char *startPtr, size_t size) +{ + char *inPtr, *outPtr; + + /* sanity check */ + if((startPtr == NULL) || (size < 1)) { + return size; + } + + if(data->state.prev_block_had_trailing_cr) { + /* The previous block of incoming data + had a trailing CR, which was turned into a LF. */ + if(*startPtr == '\n') { + /* This block of incoming data starts with the + previous block's LF so get rid of it */ + memmove(startPtr, startPtr + 1, size-1); + size--; + /* and it wasn't a bare CR but a CRLF conversion instead */ + data->state.crlf_conversions++; + } + data->state.prev_block_had_trailing_cr = FALSE; /* reset the flag */ + } + + /* find 1st CR, if any */ + inPtr = outPtr = memchr(startPtr, '\r', size); + if(inPtr) { + /* at least one CR, now look for CRLF */ + while(inPtr < (startPtr + size-1)) { + /* note that it's size-1, so we'll never look past the last byte */ + if(memcmp(inPtr, "\r\n", 2) == 0) { + /* CRLF found, bump past the CR and copy the NL */ + inPtr++; + *outPtr = *inPtr; + /* keep track of how many CRLFs we converted */ + data->state.crlf_conversions++; + } + else { + if(*inPtr == '\r') { + /* lone CR, move LF instead */ + *outPtr = '\n'; + } + else { + /* not a CRLF nor a CR, just copy whatever it is */ + *outPtr = *inPtr; + } + } + outPtr++; + inPtr++; + } /* end of while loop */ + + if(inPtr < startPtr + size) { + /* handle last byte */ + if(*inPtr == '\r') { + /* deal with a CR at the end of the buffer */ + *outPtr = '\n'; /* copy a NL instead */ + /* note that a CRLF might be split across two blocks */ + data->state.prev_block_had_trailing_cr = TRUE; + } + else { + /* copy last byte */ + *outPtr = *inPtr; + } + outPtr++; + } + if(outPtr < startPtr + size) + /* tidy up by null terminating the now shorter data */ + *outPtr = '\0'; + + return (outPtr - startPtr); + } + return size; +} +#endif /* CURL_DO_LINEEND_CONV */ + +#ifdef USE_RECV_BEFORE_SEND_WORKAROUND +bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex) +{ + struct postponed_data * const psnd = &(conn->postponed[sockindex]); + return psnd->buffer && psnd->allocated_size && + psnd->recv_size > psnd->recv_processed; +} + +static void pre_receive_plain(struct connectdata *conn, int num) +{ + const curl_socket_t sockfd = conn->sock[num]; + struct postponed_data * const psnd = &(conn->postponed[num]); + size_t bytestorecv = psnd->allocated_size - psnd->recv_size; + /* WinSock will destroy unread received data if send() is + failed. + To avoid lossage of received data, recv() must be + performed before every send() if any incoming data is + available. However, skip this, if buffer is already full. */ + if((conn->handler->protocol&PROTO_FAMILY_HTTP) != 0 && + conn->recv[num] == Curl_recv_plain && + (!psnd->buffer || bytestorecv)) { + const int readymask = Curl_socket_check(sockfd, CURL_SOCKET_BAD, + CURL_SOCKET_BAD, 0); + if(readymask != -1 && (readymask & CURL_CSELECT_IN) != 0) { + /* Have some incoming data */ + if(!psnd->buffer) { + /* Use buffer double default size for intermediate buffer */ + psnd->allocated_size = 2 * conn->data->set.buffer_size; + psnd->buffer = malloc(psnd->allocated_size); + psnd->recv_size = 0; + psnd->recv_processed = 0; +#ifdef DEBUGBUILD + psnd->bindsock = sockfd; /* Used only for DEBUGASSERT */ +#endif /* DEBUGBUILD */ + bytestorecv = psnd->allocated_size; + } + if(psnd->buffer) { + ssize_t recvedbytes; + DEBUGASSERT(psnd->bindsock == sockfd); + recvedbytes = sread(sockfd, psnd->buffer + psnd->recv_size, + bytestorecv); + if(recvedbytes > 0) + psnd->recv_size += recvedbytes; + } + else + psnd->allocated_size = 0; + } + } +} + +static ssize_t get_pre_recved(struct connectdata *conn, int num, char *buf, + size_t len) +{ + struct postponed_data * const psnd = &(conn->postponed[num]); + size_t copysize; + if(!psnd->buffer) + return 0; + + DEBUGASSERT(psnd->allocated_size > 0); + DEBUGASSERT(psnd->recv_size <= psnd->allocated_size); + DEBUGASSERT(psnd->recv_processed <= psnd->recv_size); + /* Check and process data that already received and storied in internal + intermediate buffer */ + if(psnd->recv_size > psnd->recv_processed) { + DEBUGASSERT(psnd->bindsock == conn->sock[num]); + copysize = CURLMIN(len, psnd->recv_size - psnd->recv_processed); + memcpy(buf, psnd->buffer + psnd->recv_processed, copysize); + psnd->recv_processed += copysize; + } + else + copysize = 0; /* buffer was allocated, but nothing was received */ + + /* Free intermediate buffer if it has no unprocessed data */ + if(psnd->recv_processed == psnd->recv_size) { + free(psnd->buffer); + psnd->buffer = NULL; + psnd->allocated_size = 0; + psnd->recv_size = 0; + psnd->recv_processed = 0; +#ifdef DEBUGBUILD + psnd->bindsock = CURL_SOCKET_BAD; +#endif /* DEBUGBUILD */ + } + return (ssize_t)copysize; +} +#else /* ! USE_RECV_BEFORE_SEND_WORKAROUND */ +/* Use "do-nothing" macros instead of functions when workaround not used */ +bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex) +{ + (void)conn; + (void)sockindex; + return false; +} +#define pre_receive_plain(c,n) do {} WHILE_FALSE +#define get_pre_recved(c,n,b,l) 0 +#endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */ + +/* Curl_infof() is for info message along the way */ + +void Curl_infof(struct Curl_easy *data, const char *fmt, ...) +{ + if(data && data->set.verbose) { + va_list ap; + size_t len; + char print_buffer[2048 + 1]; + va_start(ap, fmt); + len = mvsnprintf(print_buffer, sizeof(print_buffer), fmt, ap); + /* + * Indicate truncation of the input by replacing the last 3 characters + * with "...", and transfer the newline over in case the format had one. + */ + if(len >= sizeof(print_buffer)) { + len = strlen(fmt); + if(fmt[--len] == '\n') + msnprintf(print_buffer + (sizeof(print_buffer) - 5), 5, "...\n"); + else + msnprintf(print_buffer + (sizeof(print_buffer) - 4), 4, "..."); + } + va_end(ap); + len = strlen(print_buffer); + Curl_debug(data, CURLINFO_TEXT, print_buffer, len); + } +} + +/* Curl_failf() is for messages stating why we failed. + * The message SHALL NOT include any LF or CR. + */ + +void Curl_failf(struct Curl_easy *data, const char *fmt, ...) +{ + if(data->set.verbose || data->set.errorbuffer) { + va_list ap; + size_t len; + char error[CURL_ERROR_SIZE + 2]; + va_start(ap, fmt); + mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap); + len = strlen(error); + + if(data->set.errorbuffer && !data->state.errorbuf) { + strcpy(data->set.errorbuffer, error); + data->state.errorbuf = TRUE; /* wrote error string */ + } + if(data->set.verbose) { + error[len] = '\n'; + error[++len] = '\0'; + Curl_debug(data, CURLINFO_TEXT, error, len); + } + va_end(ap); + } +} + +/* Curl_sendf() sends formatted data to the server */ +CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn, + const char *fmt, ...) +{ + struct Curl_easy *data = conn->data; + ssize_t bytes_written; + size_t write_len; + CURLcode result = CURLE_OK; + char *s; + char *sptr; + va_list ap; + va_start(ap, fmt); + s = vaprintf(fmt, ap); /* returns an allocated string */ + va_end(ap); + if(!s) + return CURLE_OUT_OF_MEMORY; /* failure */ + + bytes_written = 0; + write_len = strlen(s); + sptr = s; + + for(;;) { + /* Write the buffer to the socket */ + result = Curl_write(conn, sockfd, sptr, write_len, &bytes_written); + + if(result) + break; + + if(data->set.verbose) + Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written); + + if((size_t)bytes_written != write_len) { + /* if not all was written at once, we must advance the pointer, decrease + the size left and try again! */ + write_len -= bytes_written; + sptr += bytes_written; + } + else + break; + } + + free(s); /* free the output string */ + + return result; +} + +/* + * Curl_write() is an internal write function that sends data to the + * server. Works with plain sockets, SCP, SSL or kerberos. + * + * If the write would block (CURLE_AGAIN), we return CURLE_OK and + * (*written == 0). Otherwise we return regular CURLcode value. + */ +CURLcode Curl_write(struct connectdata *conn, + curl_socket_t sockfd, + const void *mem, + size_t len, + ssize_t *written) +{ + ssize_t bytes_written; + CURLcode result = CURLE_OK; + int num = (sockfd == conn->sock[SECONDARYSOCKET]); + + bytes_written = conn->send[num](conn, num, mem, len, &result); + + *written = bytes_written; + if(bytes_written >= 0) + /* we completely ignore the curlcode value when subzero is not returned */ + return CURLE_OK; + + /* handle CURLE_AGAIN or a send failure */ + switch(result) { + case CURLE_AGAIN: + *written = 0; + return CURLE_OK; + + case CURLE_OK: + /* general send failure */ + return CURLE_SEND_ERROR; + + default: + /* we got a specific curlcode, forward it */ + return result; + } +} + +ssize_t Curl_send_plain(struct connectdata *conn, int num, + const void *mem, size_t len, CURLcode *code) +{ + curl_socket_t sockfd = conn->sock[num]; + ssize_t bytes_written; + /* WinSock will destroy unread received data if send() is + failed. + To avoid lossage of received data, recv() must be + performed before every send() if any incoming data is + available. */ + pre_receive_plain(conn, num); + +#if defined(MSG_FASTOPEN) && !defined(TCP_FASTOPEN_CONNECT) /* Linux */ + if(conn->bits.tcp_fastopen) { + bytes_written = sendto(sockfd, mem, len, MSG_FASTOPEN, + conn->ip_addr->ai_addr, conn->ip_addr->ai_addrlen); + conn->bits.tcp_fastopen = FALSE; + } + else +#endif + bytes_written = swrite(sockfd, mem, len); + + *code = CURLE_OK; + if(-1 == bytes_written) { + int err = SOCKERRNO; + + if( +#ifdef WSAEWOULDBLOCK + /* This is how Windows does it */ + (WSAEWOULDBLOCK == err) +#else + /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned + due to its inability to send off data without blocking. We therefore + treat both error codes the same here */ + (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err) || + (EINPROGRESS == err) +#endif + ) { + /* this is just a case of EWOULDBLOCK */ + bytes_written = 0; + *code = CURLE_AGAIN; + } + else { + char buffer[STRERROR_LEN]; + failf(conn->data, "Send failure: %s", + Curl_strerror(err, buffer, sizeof(buffer))); + conn->data->state.os_errno = err; + *code = CURLE_SEND_ERROR; + } + } + return bytes_written; +} + +/* + * Curl_write_plain() is an internal write function that sends data to the + * server using plain sockets only. Otherwise meant to have the exact same + * proto as Curl_write() + */ +CURLcode Curl_write_plain(struct connectdata *conn, + curl_socket_t sockfd, + const void *mem, + size_t len, + ssize_t *written) +{ + ssize_t bytes_written; + CURLcode result; + int num = (sockfd == conn->sock[SECONDARYSOCKET]); + + bytes_written = Curl_send_plain(conn, num, mem, len, &result); + + *written = bytes_written; + + return result; +} + +ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf, + size_t len, CURLcode *code) +{ + curl_socket_t sockfd = conn->sock[num]; + ssize_t nread; + /* Check and return data that already received and storied in internal + intermediate buffer */ + nread = get_pre_recved(conn, num, buf, len); + if(nread > 0) { + *code = CURLE_OK; + return nread; + } + + nread = sread(sockfd, buf, len); + + *code = CURLE_OK; + if(-1 == nread) { + int err = SOCKERRNO; + + if( +#ifdef WSAEWOULDBLOCK + /* This is how Windows does it */ + (WSAEWOULDBLOCK == err) +#else + /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned + due to its inability to send off data without blocking. We therefore + treat both error codes the same here */ + (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err) +#endif + ) { + /* this is just a case of EWOULDBLOCK */ + *code = CURLE_AGAIN; + } + else { + char buffer[STRERROR_LEN]; + failf(conn->data, "Recv failure: %s", + Curl_strerror(err, buffer, sizeof(buffer))); + conn->data->state.os_errno = err; + *code = CURLE_RECV_ERROR; + } + } + return nread; +} + +static CURLcode pausewrite(struct Curl_easy *data, + int type, /* what type of data */ + const char *ptr, + size_t len) +{ + /* signalled to pause sending on this connection, but since we have data + we want to send we need to dup it to save a copy for when the sending + is again enabled */ + struct SingleRequest *k = &data->req; + struct UrlState *s = &data->state; + char *dupl; + unsigned int i; + bool newtype = TRUE; + + if(s->tempcount) { + for(i = 0; i< s->tempcount; i++) { + if(s->tempwrite[i].type == type) { + /* data for this type exists */ + newtype = FALSE; + break; + } + } + DEBUGASSERT(i < 3); + } + else + i = 0; + + if(!newtype) { + /* append new data to old data */ + + /* figure out the new size of the data to save */ + size_t newlen = len + s->tempwrite[i].len; + /* allocate the new memory area */ + char *newptr = realloc(s->tempwrite[i].buf, newlen); + if(!newptr) + return CURLE_OUT_OF_MEMORY; + /* copy the new data to the end of the new area */ + memcpy(newptr + s->tempwrite[i].len, ptr, len); + + /* update the pointer and the size */ + s->tempwrite[i].buf = newptr; + s->tempwrite[i].len = newlen; + } + else { + dupl = Curl_memdup(ptr, len); + if(!dupl) + return CURLE_OUT_OF_MEMORY; + + /* store this information in the state struct for later use */ + s->tempwrite[i].buf = dupl; + s->tempwrite[i].len = len; + s->tempwrite[i].type = type; + + if(newtype) + s->tempcount++; + } + + /* mark the connection as RECV paused */ + k->keepon |= KEEP_RECV_PAUSE; + + DEBUGF(infof(data, "Paused %zu bytes in buffer for type %02x\n", + len, type)); + + return CURLE_OK; +} + + +/* chop_write() writes chunks of data not larger than CURL_MAX_WRITE_SIZE via + * client write callback(s) and takes care of pause requests from the + * callbacks. + */ +static CURLcode chop_write(struct connectdata *conn, + int type, + char *optr, + size_t olen) +{ + struct Curl_easy *data = conn->data; + curl_write_callback writeheader = NULL; + curl_write_callback writebody = NULL; + char *ptr = optr; + size_t len = olen; + + if(!len) + return CURLE_OK; + + /* If reading is paused, append this data to the already held data for this + type. */ + if(data->req.keepon & KEEP_RECV_PAUSE) + return pausewrite(data, type, ptr, len); + + /* Determine the callback(s) to use. */ + if(type & CLIENTWRITE_BODY) + writebody = data->set.fwrite_func; + if((type & CLIENTWRITE_HEADER) && + (data->set.fwrite_header || data->set.writeheader)) { + /* + * Write headers to the same callback or to the especially setup + * header callback function (added after version 7.7.1). + */ + writeheader = + data->set.fwrite_header? data->set.fwrite_header: data->set.fwrite_func; + } + + /* Chop data, write chunks. */ + while(len) { + size_t chunklen = len <= CURL_MAX_WRITE_SIZE? len: CURL_MAX_WRITE_SIZE; + + if(writebody) { + size_t wrote; + Curl_set_in_callback(data, true); + wrote = writebody(ptr, 1, chunklen, data->set.out); + Curl_set_in_callback(data, false); + + if(CURL_WRITEFUNC_PAUSE == wrote) { + if(conn->handler->flags & PROTOPT_NONETWORK) { + /* Protocols that work without network cannot be paused. This is + actually only FILE:// just now, and it can't pause since the + transfer isn't done using the "normal" procedure. */ + failf(data, "Write callback asked for PAUSE when not supported!"); + return CURLE_WRITE_ERROR; + } + return pausewrite(data, type, ptr, len); + } + if(wrote != chunklen) { + failf(data, "Failed writing body (%zu != %zu)", wrote, chunklen); + return CURLE_WRITE_ERROR; + } + } + + ptr += chunklen; + len -= chunklen; + } + + if(writeheader) { + size_t wrote; + ptr = optr; + len = olen; + Curl_set_in_callback(data, true); + wrote = writeheader(ptr, 1, len, data->set.writeheader); + Curl_set_in_callback(data, false); + + if(CURL_WRITEFUNC_PAUSE == wrote) + /* here we pass in the HEADER bit only since if this was body as well + then it was passed already and clearly that didn't trigger the + pause, so this is saved for later with the HEADER bit only */ + return pausewrite(data, CLIENTWRITE_HEADER, ptr, len); + + if(wrote != len) { + failf(data, "Failed writing header"); + return CURLE_WRITE_ERROR; + } + } + + return CURLE_OK; +} + + +/* Curl_client_write() sends data to the write callback(s) + + The bit pattern defines to what "streams" to write to. Body and/or header. + The defines are in sendf.h of course. + + If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the + local character encoding. This is a problem and should be changed in + the future to leave the original data alone. + */ +CURLcode Curl_client_write(struct connectdata *conn, + int type, + char *ptr, + size_t len) +{ + struct Curl_easy *data = conn->data; + + if(0 == len) + len = strlen(ptr); + + DEBUGASSERT(type <= 3); + + /* FTP data may need conversion. */ + if((type & CLIENTWRITE_BODY) && + (conn->handler->protocol & PROTO_FAMILY_FTP) && + conn->proto.ftpc.transfertype == 'A') { + /* convert from the network encoding */ + CURLcode result = Curl_convert_from_network(data, ptr, len); + /* Curl_convert_from_network calls failf if unsuccessful */ + if(result) + return result; + +#ifdef CURL_DO_LINEEND_CONV + /* convert end-of-line markers */ + len = convert_lineends(data, ptr, len); +#endif /* CURL_DO_LINEEND_CONV */ + } + + return chop_write(conn, type, ptr, len); +} + +CURLcode Curl_read_plain(curl_socket_t sockfd, + char *buf, + size_t bytesfromsocket, + ssize_t *n) +{ + ssize_t nread = sread(sockfd, buf, bytesfromsocket); + + if(-1 == nread) { + int err = SOCKERRNO; + int return_error; +#ifdef USE_WINSOCK + return_error = WSAEWOULDBLOCK == err; +#else + return_error = EWOULDBLOCK == err || EAGAIN == err || EINTR == err; +#endif + if(return_error) + return CURLE_AGAIN; + return CURLE_RECV_ERROR; + } + + /* we only return number of bytes read when we return OK */ + *n = nread; + return CURLE_OK; +} + +/* + * Internal read-from-socket function. This is meant to deal with plain + * sockets, SSL sockets and kerberos sockets. + * + * Returns a regular CURLcode value. + */ +CURLcode Curl_read(struct connectdata *conn, /* connection data */ + curl_socket_t sockfd, /* read from this socket */ + char *buf, /* store read data here */ + size_t sizerequested, /* max amount to read */ + ssize_t *n) /* amount bytes read */ +{ + CURLcode result = CURLE_RECV_ERROR; + ssize_t nread = 0; + size_t bytesfromsocket = 0; + char *buffertofill = NULL; + struct Curl_easy *data = conn->data; + + /* Set 'num' to 0 or 1, depending on which socket that has been sent here. + If it is the second socket, we set num to 1. Otherwise to 0. This lets + us use the correct ssl handle. */ + int num = (sockfd == conn->sock[SECONDARYSOCKET]); + + *n = 0; /* reset amount to zero */ + + bytesfromsocket = CURLMIN(sizerequested, (size_t)data->set.buffer_size); + buffertofill = buf; + + nread = conn->recv[num](conn, num, buffertofill, bytesfromsocket, &result); + if(nread < 0) + return result; + + *n += nread; + + return CURLE_OK; +} + +/* return 0 on success */ +int Curl_debug(struct Curl_easy *data, curl_infotype type, + char *ptr, size_t size) +{ + static const char s_infotype[CURLINFO_END][3] = { + "* ", "< ", "> ", "{ ", "} ", "{ ", "} " }; + int rc = 0; + +#ifdef CURL_DOES_CONVERSIONS + char *buf = NULL; + size_t conv_size = 0; + + switch(type) { + case CURLINFO_HEADER_OUT: + buf = Curl_memdup(ptr, size); + if(!buf) + return 1; + conv_size = size; + + /* Special processing is needed for this block if it + * contains both headers and data (separated by CRLFCRLF). + * We want to convert just the headers, leaving the data as-is. + */ + if(size > 4) { + size_t i; + for(i = 0; i < size-4; i++) { + if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) { + /* convert everything through this CRLFCRLF but no further */ + conv_size = i + 4; + break; + } + } + } + + Curl_convert_from_network(data, buf, conv_size); + /* Curl_convert_from_network calls failf if unsuccessful */ + /* we might as well continue even if it fails... */ + ptr = buf; /* switch pointer to use my buffer instead */ + break; + default: + /* leave everything else as-is */ + break; + } +#endif /* CURL_DOES_CONVERSIONS */ + + if(data->set.fdebug) { + Curl_set_in_callback(data, true); + rc = (*data->set.fdebug)(data, type, ptr, size, data->set.debugdata); + Curl_set_in_callback(data, false); + } + else { + switch(type) { + case CURLINFO_TEXT: + case CURLINFO_HEADER_OUT: + case CURLINFO_HEADER_IN: + fwrite(s_infotype[type], 2, 1, data->set.err); + fwrite(ptr, size, 1, data->set.err); +#ifdef CURL_DOES_CONVERSIONS + if(size != conv_size) { + /* we had untranslated data so we need an explicit newline */ + fwrite("\n", 1, 1, data->set.err); + } +#endif + break; + default: /* nada */ + break; + } + } +#ifdef CURL_DOES_CONVERSIONS + free(buf); +#endif + return rc; +} diff --git a/dependencies/cmcurl/lib/sendf.h b/dependencies/cmcurl/lib/sendf.h new file mode 100644 index 0000000..c68b017 --- /dev/null +++ b/dependencies/cmcurl/lib/sendf.h @@ -0,0 +1,91 @@ +#ifndef HEADER_CURL_SENDF_H +#define HEADER_CURL_SENDF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *, + const char *fmt, ...); +void Curl_infof(struct Curl_easy *, const char *fmt, ...); +void Curl_failf(struct Curl_easy *, const char *fmt, ...); + +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + +#if defined(HAVE_VARIADIC_MACROS_C99) +#define infof(...) Curl_nop_stmt +#elif defined(HAVE_VARIADIC_MACROS_GCC) +#define infof(x...) Curl_nop_stmt +#else +#error "missing VARIADIC macro define, fix and rebuild!" +#endif + +#else /* CURL_DISABLE_VERBOSE_STRINGS */ + +#define infof Curl_infof + +#endif /* CURL_DISABLE_VERBOSE_STRINGS */ + +#define failf Curl_failf + +#define CLIENTWRITE_BODY (1<<0) +#define CLIENTWRITE_HEADER (1<<1) +#define CLIENTWRITE_BOTH (CLIENTWRITE_BODY|CLIENTWRITE_HEADER) + +CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr, + size_t len) WARN_UNUSED_RESULT; + +bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex); + +/* internal read-function, does plain socket only */ +CURLcode Curl_read_plain(curl_socket_t sockfd, + char *buf, + size_t bytesfromsocket, + ssize_t *n); + +ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf, + size_t len, CURLcode *code); +ssize_t Curl_send_plain(struct connectdata *conn, int num, + const void *mem, size_t len, CURLcode *code); + +/* internal read-function, does plain socket, SSL and krb4 */ +CURLcode Curl_read(struct connectdata *conn, curl_socket_t sockfd, + char *buf, size_t buffersize, + ssize_t *n); +/* internal write-function, does plain socket, SSL, SCP, SFTP and krb4 */ +CURLcode Curl_write(struct connectdata *conn, + curl_socket_t sockfd, + const void *mem, size_t len, + ssize_t *written); + +/* internal write-function, does plain sockets ONLY */ +CURLcode Curl_write_plain(struct connectdata *conn, + curl_socket_t sockfd, + const void *mem, size_t len, + ssize_t *written); + +/* the function used to output verbose information */ +int Curl_debug(struct Curl_easy *data, curl_infotype type, + char *ptr, size_t size); + + +#endif /* HEADER_CURL_SENDF_H */ diff --git a/dependencies/cmcurl/lib/setopt.c b/dependencies/cmcurl/lib/setopt.c new file mode 100644 index 0000000..92cd5b2 --- /dev/null +++ b/dependencies/cmcurl/lib/setopt.c @@ -0,0 +1,2777 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_LINUX_TCP_H +#include +#endif + +#include "urldata.h" +#include "url.h" +#include "progress.h" +#include "content_encoding.h" +#include "strcase.h" +#include "share.h" +#include "vtls/vtls.h" +#include "warnless.h" +#include "sendf.h" +#include "http2.h" +#include "setopt.h" +#include "multiif.h" +#include "altsvc.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +CURLcode Curl_setstropt(char **charp, const char *s) +{ + /* Release the previous storage at `charp' and replace by a dynamic storage + copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */ + + Curl_safefree(*charp); + + if(s) { + char *str = strdup(s); + + if(str) { + size_t len = strlen(str); + if(len > CURL_MAX_INPUT_LENGTH) { + free(str); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + } + if(!str) + return CURLE_OUT_OF_MEMORY; + + *charp = str; + } + + return CURLE_OK; +} + +static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp) +{ + CURLcode result = CURLE_OK; + char *user = NULL; + char *passwd = NULL; + + /* Parse the login details if specified. It not then we treat NULL as a hint + to clear the existing data */ + if(option) { + result = Curl_parse_login_details(option, strlen(option), + (userp ? &user : NULL), + (passwdp ? &passwd : NULL), + NULL); + } + + if(!result) { + /* Store the username part of option if required */ + if(userp) { + if(!user && option && option[0] == ':') { + /* Allocate an empty string instead of returning NULL as user name */ + user = strdup(""); + if(!user) + result = CURLE_OUT_OF_MEMORY; + } + + Curl_safefree(*userp); + *userp = user; + } + + /* Store the password part of option if required */ + if(passwdp) { + Curl_safefree(*passwdp); + *passwdp = passwd; + } + } + + return result; +} + +#define C_SSLVERSION_VALUE(x) (x & 0xffff) +#define C_SSLVERSION_MAX_VALUE(x) (x & 0xffff0000) + +static CURLcode vsetopt(struct Curl_easy *data, CURLoption option, + va_list param) +{ + char *argptr; + CURLcode result = CURLE_OK; + long arg; + unsigned long uarg; + curl_off_t bigsize; + + switch(option) { + case CURLOPT_DNS_CACHE_TIMEOUT: + arg = va_arg(param, long); + if(arg < -1) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.dns_cache_timeout = arg; + break; + case CURLOPT_DNS_USE_GLOBAL_CACHE: + /* deprecated */ + break; + case CURLOPT_SSL_CIPHER_LIST: + /* set a list of cipher we want to use in the SSL connection */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_ORIG], + va_arg(param, char *)); + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_SSL_CIPHER_LIST: + /* set a list of cipher we want to use in the SSL connection for proxy */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_PROXY], + va_arg(param, char *)); + break; +#endif + case CURLOPT_TLS13_CIPHERS: + if(Curl_ssl_tls13_ciphersuites()) { + /* set preferred list of TLS 1.3 cipher suites */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST_ORIG], + va_arg(param, char *)); + } + else + return CURLE_NOT_BUILT_IN; + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_TLS13_CIPHERS: + if(Curl_ssl_tls13_ciphersuites()) { + /* set preferred list of TLS 1.3 cipher suites for proxy */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST_PROXY], + va_arg(param, char *)); + } + else + return CURLE_NOT_BUILT_IN; + break; +#endif + case CURLOPT_RANDOM_FILE: + /* + * This is the path name to a file that contains random data to seed + * the random SSL stuff with. The file is only used for reading. + */ + result = Curl_setstropt(&data->set.str[STRING_SSL_RANDOM_FILE], + va_arg(param, char *)); + break; + case CURLOPT_EGDSOCKET: + /* + * The Entropy Gathering Daemon socket pathname + */ + result = Curl_setstropt(&data->set.str[STRING_SSL_EGDSOCKET], + va_arg(param, char *)); + break; + case CURLOPT_MAXCONNECTS: + /* + * Set the absolute number of maximum simultaneous alive connection that + * libcurl is allowed to have. + */ + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.maxconnects = arg; + break; + case CURLOPT_FORBID_REUSE: + /* + * When this transfer is done, it must not be left to be reused by a + * subsequent transfer but shall be closed immediately. + */ + data->set.reuse_forbid = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_FRESH_CONNECT: + /* + * This transfer shall not use a previously cached connection but + * should be made with a fresh new connect! + */ + data->set.reuse_fresh = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_VERBOSE: + /* + * Verbose means infof() calls that give a lot of information about + * the connection and transfer procedures as well as internal choices. + */ + data->set.verbose = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_HEADER: + /* + * Set to include the header in the general data output stream. + */ + data->set.include_header = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_NOPROGRESS: + /* + * Shut off the internal supported progress meter + */ + data->set.hide_progress = (0 != va_arg(param, long)) ? TRUE : FALSE; + if(data->set.hide_progress) + data->progress.flags |= PGRS_HIDE; + else + data->progress.flags &= ~PGRS_HIDE; + break; + case CURLOPT_NOBODY: + /* + * Do not include the body part in the output data stream. + */ + data->set.opt_no_body = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_FAILONERROR: + /* + * Don't output the >=400 error code HTML-page, but instead only + * return error. + */ + data->set.http_fail_on_error = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_KEEP_SENDING_ON_ERROR: + data->set.http_keep_sending_on_error = (0 != va_arg(param, long)) ? + TRUE : FALSE; + break; + case CURLOPT_UPLOAD: + case CURLOPT_PUT: + /* + * We want to sent data to the remote host. If this is HTTP, that equals + * using the PUT request. + */ + data->set.upload = (0 != va_arg(param, long)) ? TRUE : FALSE; + if(data->set.upload) { + /* If this is HTTP, PUT is what's needed to "upload" */ + data->set.httpreq = HTTPREQ_PUT; + data->set.opt_no_body = FALSE; /* this is implied */ + } + else + /* In HTTP, the opposite of upload is GET (unless NOBODY is true as + then this can be changed to HEAD later on) */ + data->set.httpreq = HTTPREQ_GET; + break; + case CURLOPT_REQUEST_TARGET: + result = Curl_setstropt(&data->set.str[STRING_TARGET], + va_arg(param, char *)); + break; + case CURLOPT_FILETIME: + /* + * Try to get the file time of the remote document. The time will + * later (possibly) become available using curl_easy_getinfo(). + */ + data->set.get_filetime = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_SERVER_RESPONSE_TIMEOUT: + /* + * Option that specifies how quickly an server response must be obtained + * before it is considered failure. For pingpong protocols. + */ + arg = va_arg(param, long); + if((arg >= 0) && (arg <= (INT_MAX/1000))) + data->set.server_response_timeout = arg * 1000; + else + return CURLE_BAD_FUNCTION_ARGUMENT; + break; +#ifndef CURL_DISABLE_TFTP + case CURLOPT_TFTP_NO_OPTIONS: + /* + * Option that prevents libcurl from sending TFTP option requests to the + * server. + */ + data->set.tftp_no_options = va_arg(param, long) != 0; + break; + case CURLOPT_TFTP_BLKSIZE: + /* + * TFTP option that specifies the block size to use for data transmission. + */ + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.tftp_blksize = arg; + break; +#endif +#ifndef CURL_DISABLE_NETRC + case CURLOPT_NETRC: + /* + * Parse the $HOME/.netrc file + */ + arg = va_arg(param, long); + if((arg < CURL_NETRC_IGNORED) || (arg > CURL_NETRC_REQUIRED)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.use_netrc = (enum CURL_NETRC_OPTION)arg; + break; + case CURLOPT_NETRC_FILE: + /* + * Use this file instead of the $HOME/.netrc file + */ + result = Curl_setstropt(&data->set.str[STRING_NETRC_FILE], + va_arg(param, char *)); + break; +#endif + case CURLOPT_TRANSFERTEXT: + /* + * This option was previously named 'FTPASCII'. Renamed to work with + * more protocols than merely FTP. + * + * Transfer using ASCII (instead of BINARY). + */ + data->set.prefer_ascii = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_TIMECONDITION: + /* + * Set HTTP time condition. This must be one of the defines in the + * curl/curl.h header file. + */ + arg = va_arg(param, long); + if((arg < CURL_TIMECOND_NONE) || (arg > CURL_TIMECOND_LASTMOD)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.timecondition = (curl_TimeCond)arg; + break; + case CURLOPT_TIMEVALUE: + /* + * This is the value to compare with the remote document with the + * method set with CURLOPT_TIMECONDITION + */ + data->set.timevalue = (time_t)va_arg(param, long); + break; + + case CURLOPT_TIMEVALUE_LARGE: + /* + * This is the value to compare with the remote document with the + * method set with CURLOPT_TIMECONDITION + */ + data->set.timevalue = (time_t)va_arg(param, curl_off_t); + break; + + case CURLOPT_SSLVERSION: + case CURLOPT_PROXY_SSLVERSION: + /* + * Set explicit SSL version to try to connect with, as some SSL + * implementations are lame. + */ +#ifdef USE_SSL + { + long version, version_max; + struct ssl_primary_config *primary = (option == CURLOPT_SSLVERSION ? + &data->set.ssl.primary : + &data->set.proxy_ssl.primary); + + arg = va_arg(param, long); + + version = C_SSLVERSION_VALUE(arg); + version_max = C_SSLVERSION_MAX_VALUE(arg); + + if(version < CURL_SSLVERSION_DEFAULT || + version >= CURL_SSLVERSION_LAST || + version_max < CURL_SSLVERSION_MAX_NONE || + version_max >= CURL_SSLVERSION_MAX_LAST) + return CURLE_BAD_FUNCTION_ARGUMENT; + + primary->version = version; + primary->version_max = version_max; + } +#else + result = CURLE_UNKNOWN_OPTION; +#endif + break; + +#ifndef CURL_DISABLE_HTTP + case CURLOPT_AUTOREFERER: + /* + * Switch on automatic referer that gets set if curl follows locations. + */ + data->set.http_auto_referer = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_ACCEPT_ENCODING: + /* + * String to use at the value of Accept-Encoding header. + * + * If the encoding is set to "" we use an Accept-Encoding header that + * encompasses all the encodings we support. + * If the encoding is set to NULL we don't send an Accept-Encoding header + * and ignore an received Content-Encoding header. + * + */ + argptr = va_arg(param, char *); + if(argptr && !*argptr) { + argptr = Curl_all_content_encodings(); + if(!argptr) + result = CURLE_OUT_OF_MEMORY; + else { + result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr); + free(argptr); + } + } + else + result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr); + break; + + case CURLOPT_TRANSFER_ENCODING: + data->set.http_transfer_encoding = (0 != va_arg(param, long)) ? + TRUE : FALSE; + break; + + case CURLOPT_FOLLOWLOCATION: + /* + * Follow Location: header hints on a HTTP-server. + */ + data->set.http_follow_location = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_UNRESTRICTED_AUTH: + /* + * Send authentication (user+password) when following locations, even when + * hostname changed. + */ + data->set.allow_auth_to_other_hosts = + (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_MAXREDIRS: + /* + * The maximum amount of hops you allow curl to follow Location: + * headers. This should mostly be used to detect never-ending loops. + */ + arg = va_arg(param, long); + if(arg < -1) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.maxredirs = arg; + break; + + case CURLOPT_POSTREDIR: + /* + * Set the behaviour of POST when redirecting + * CURL_REDIR_GET_ALL - POST is changed to GET after 301 and 302 + * CURL_REDIR_POST_301 - POST is kept as POST after 301 + * CURL_REDIR_POST_302 - POST is kept as POST after 302 + * CURL_REDIR_POST_303 - POST is kept as POST after 303 + * CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303 + * other - POST is kept as POST after 301 and 302 + */ + arg = va_arg(param, long); + if(arg < CURL_REDIR_GET_ALL) + /* no return error on too high numbers since the bitmask could be + extended in a future */ + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.keep_post = arg & CURL_REDIR_POST_ALL; + break; + + case CURLOPT_POST: + /* Does this option serve a purpose anymore? Yes it does, when + CURLOPT_POSTFIELDS isn't used and the POST data is read off the + callback! */ + if(va_arg(param, long)) { + data->set.httpreq = HTTPREQ_POST; + data->set.opt_no_body = FALSE; /* this is implied */ + } + else + data->set.httpreq = HTTPREQ_GET; + break; + + case CURLOPT_COPYPOSTFIELDS: + /* + * A string with POST data. Makes curl HTTP POST. Even if it is NULL. + * If needed, CURLOPT_POSTFIELDSIZE must have been set prior to + * CURLOPT_COPYPOSTFIELDS and not altered later. + */ + argptr = va_arg(param, char *); + + if(!argptr || data->set.postfieldsize == -1) + result = Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], argptr); + else { + /* + * Check that requested length does not overflow the size_t type. + */ + + if((data->set.postfieldsize < 0) || + ((sizeof(curl_off_t) != sizeof(size_t)) && + (data->set.postfieldsize > (curl_off_t)((size_t)-1)))) + result = CURLE_OUT_OF_MEMORY; + else { + char *p; + + (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); + + /* Allocate even when size == 0. This satisfies the need of possible + later address compare to detect the COPYPOSTFIELDS mode, and + to mark that postfields is used rather than read function or + form data. + */ + p = malloc((size_t)(data->set.postfieldsize? + data->set.postfieldsize:1)); + + if(!p) + result = CURLE_OUT_OF_MEMORY; + else { + if(data->set.postfieldsize) + memcpy(p, argptr, (size_t)data->set.postfieldsize); + + data->set.str[STRING_COPYPOSTFIELDS] = p; + } + } + } + + data->set.postfields = data->set.str[STRING_COPYPOSTFIELDS]; + data->set.httpreq = HTTPREQ_POST; + break; + + case CURLOPT_POSTFIELDS: + /* + * Like above, but use static data instead of copying it. + */ + data->set.postfields = va_arg(param, void *); + /* Release old copied data. */ + (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); + data->set.httpreq = HTTPREQ_POST; + break; + + case CURLOPT_POSTFIELDSIZE: + /* + * The size of the POSTFIELD data to prevent libcurl to do strlen() to + * figure it out. Enables binary posts. + */ + bigsize = va_arg(param, long); + if(bigsize < -1) + return CURLE_BAD_FUNCTION_ARGUMENT; + + if(data->set.postfieldsize < bigsize && + data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) { + /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */ + (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); + data->set.postfields = NULL; + } + + data->set.postfieldsize = bigsize; + break; + + case CURLOPT_POSTFIELDSIZE_LARGE: + /* + * The size of the POSTFIELD data to prevent libcurl to do strlen() to + * figure it out. Enables binary posts. + */ + bigsize = va_arg(param, curl_off_t); + if(bigsize < -1) + return CURLE_BAD_FUNCTION_ARGUMENT; + + if(data->set.postfieldsize < bigsize && + data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) { + /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */ + (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); + data->set.postfields = NULL; + } + + data->set.postfieldsize = bigsize; + break; + + case CURLOPT_HTTPPOST: + /* + * Set to make us do HTTP POST + */ + data->set.httppost = va_arg(param, struct curl_httppost *); + data->set.httpreq = HTTPREQ_POST_FORM; + data->set.opt_no_body = FALSE; /* this is implied */ + break; +#endif /* CURL_DISABLE_HTTP */ + + case CURLOPT_MIMEPOST: + /* + * Set to make us do MIME/form POST + */ + result = Curl_mime_set_subparts(&data->set.mimepost, + va_arg(param, curl_mime *), FALSE); + if(!result) { + data->set.httpreq = HTTPREQ_POST_MIME; + data->set.opt_no_body = FALSE; /* this is implied */ + } + break; + + case CURLOPT_REFERER: + /* + * String to set in the HTTP Referer: field. + */ + if(data->change.referer_alloc) { + Curl_safefree(data->change.referer); + data->change.referer_alloc = FALSE; + } + result = Curl_setstropt(&data->set.str[STRING_SET_REFERER], + va_arg(param, char *)); + data->change.referer = data->set.str[STRING_SET_REFERER]; + break; + + case CURLOPT_USERAGENT: + /* + * String to use in the HTTP User-Agent field + */ + result = Curl_setstropt(&data->set.str[STRING_USERAGENT], + va_arg(param, char *)); + break; + + case CURLOPT_HTTPHEADER: + /* + * Set a list with HTTP headers to use (or replace internals with) + */ + data->set.headers = va_arg(param, struct curl_slist *); + break; + +#ifndef CURL_DISABLE_HTTP +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXYHEADER: + /* + * Set a list with proxy headers to use (or replace internals with) + * + * Since CURLOPT_HTTPHEADER was the only way to set HTTP headers for a + * long time we remain doing it this way until CURLOPT_PROXYHEADER is + * used. As soon as this option has been used, if set to anything but + * NULL, custom headers for proxies are only picked from this list. + * + * Set this option to NULL to restore the previous behavior. + */ + data->set.proxyheaders = va_arg(param, struct curl_slist *); + break; +#endif + case CURLOPT_HEADEROPT: + /* + * Set header option. + */ + arg = va_arg(param, long); + data->set.sep_headers = (bool)((arg & CURLHEADER_SEPARATE)? TRUE: FALSE); + break; + + case CURLOPT_HTTP200ALIASES: + /* + * Set a list of aliases for HTTP 200 in response header + */ + data->set.http200aliases = va_arg(param, struct curl_slist *); + break; + +#if !defined(CURL_DISABLE_COOKIES) + case CURLOPT_COOKIE: + /* + * Cookie string to send to the remote server in the request. + */ + result = Curl_setstropt(&data->set.str[STRING_COOKIE], + va_arg(param, char *)); + break; + + case CURLOPT_COOKIEFILE: + /* + * Set cookie file to read and parse. Can be used multiple times. + */ + argptr = (char *)va_arg(param, void *); + if(argptr) { + struct curl_slist *cl; + /* append the cookie file name to the list of file names, and deal with + them later */ + cl = curl_slist_append(data->change.cookielist, argptr); + if(!cl) { + curl_slist_free_all(data->change.cookielist); + data->change.cookielist = NULL; + return CURLE_OUT_OF_MEMORY; + } + data->change.cookielist = cl; /* store the list for later use */ + } + break; + + case CURLOPT_COOKIEJAR: + /* + * Set cookie file name to dump all cookies to when we're done. + */ + { + struct CookieInfo *newcookies; + result = Curl_setstropt(&data->set.str[STRING_COOKIEJAR], + va_arg(param, char *)); + + /* + * Activate the cookie parser. This may or may not already + * have been made. + */ + newcookies = Curl_cookie_init(data, NULL, data->cookies, + data->set.cookiesession); + if(!newcookies) + result = CURLE_OUT_OF_MEMORY; + data->cookies = newcookies; + } + break; + + case CURLOPT_COOKIESESSION: + /* + * Set this option to TRUE to start a new "cookie session". It will + * prevent the forthcoming read-cookies-from-file actions to accept + * cookies that are marked as being session cookies, as they belong to a + * previous session. + * + * In the original Netscape cookie spec, "session cookies" are cookies + * with no expire date set. RFC2109 describes the same action if no + * 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds + * a 'Discard' action that can enforce the discard even for cookies that + * have a Max-Age. + * + * We run mostly with the original cookie spec, as hardly anyone implements + * anything else. + */ + data->set.cookiesession = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_COOKIELIST: + argptr = va_arg(param, char *); + + if(argptr == NULL) + break; + + if(strcasecompare(argptr, "ALL")) { + /* clear all cookies */ + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + Curl_cookie_clearall(data->cookies); + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + } + else if(strcasecompare(argptr, "SESS")) { + /* clear session cookies */ + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + Curl_cookie_clearsess(data->cookies); + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + } + else if(strcasecompare(argptr, "FLUSH")) { + /* flush cookies to file, takes care of the locking */ + Curl_flush_cookies(data, 0); + } + else if(strcasecompare(argptr, "RELOAD")) { + /* reload cookies from file */ + Curl_cookie_loadfiles(data); + break; + } + else { + if(!data->cookies) + /* if cookie engine was not running, activate it */ + data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE); + + argptr = strdup(argptr); + if(!argptr || !data->cookies) { + result = CURLE_OUT_OF_MEMORY; + free(argptr); + } + else { + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + + if(checkprefix("Set-Cookie:", argptr)) + /* HTTP Header format line */ + Curl_cookie_add(data, data->cookies, TRUE, FALSE, argptr + 11, NULL, + NULL, TRUE); + + else + /* Netscape format line */ + Curl_cookie_add(data, data->cookies, FALSE, FALSE, argptr, NULL, + NULL, TRUE); + + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + free(argptr); + } + } + + break; +#endif /* !CURL_DISABLE_COOKIES */ + + case CURLOPT_HTTPGET: + /* + * Set to force us do HTTP GET + */ + if(va_arg(param, long)) { + data->set.httpreq = HTTPREQ_GET; + data->set.upload = FALSE; /* switch off upload */ + data->set.opt_no_body = FALSE; /* this is implied */ + } + break; + + case CURLOPT_HTTP_VERSION: + /* + * This sets a requested HTTP version to be used. The value is one of + * the listed enums in curl/curl.h. + */ + arg = va_arg(param, long); + if(arg < CURL_HTTP_VERSION_NONE) + return CURLE_BAD_FUNCTION_ARGUMENT; +#ifndef USE_NGHTTP2 + if(arg >= CURL_HTTP_VERSION_2) + return CURLE_UNSUPPORTED_PROTOCOL; +#else + if(arg > CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) + return CURLE_UNSUPPORTED_PROTOCOL; + if(arg == CURL_HTTP_VERSION_NONE) + arg = CURL_HTTP_VERSION_2TLS; +#endif + data->set.httpversion = arg; + break; + + case CURLOPT_EXPECT_100_TIMEOUT_MS: + /* + * Time to wait for a response to a HTTP request containing an + * Expect: 100-continue header before sending the data anyway. + */ + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.expect_100_timeout = arg; + break; + + case CURLOPT_HTTP09_ALLOWED: + arg = va_arg(param, unsigned long); + if(arg > 1L) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.http09_allowed = arg ? TRUE : FALSE; + break; +#endif /* CURL_DISABLE_HTTP */ + + case CURLOPT_HTTPAUTH: + /* + * Set HTTP Authentication type BITMASK. + */ + { + int bitcheck; + bool authbits; + unsigned long auth = va_arg(param, unsigned long); + + if(auth == CURLAUTH_NONE) { + data->set.httpauth = auth; + break; + } + + /* the DIGEST_IE bit is only used to set a special marker, for all the + rest we need to handle it as normal DIGEST */ + data->state.authhost.iestyle = + (bool)((auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE); + + if(auth & CURLAUTH_DIGEST_IE) { + auth |= CURLAUTH_DIGEST; /* set standard digest bit */ + auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */ + } + + /* switch off bits we can't support */ +#ifndef USE_NTLM + auth &= ~CURLAUTH_NTLM; /* no NTLM support */ + auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */ +#elif !defined(NTLM_WB_ENABLED) + auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */ +#endif +#ifndef USE_SPNEGO + auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without + GSS-API or SSPI */ +#endif + + /* check if any auth bit lower than CURLAUTH_ONLY is still set */ + bitcheck = 0; + authbits = FALSE; + while(bitcheck < 31) { + if(auth & (1UL << bitcheck++)) { + authbits = TRUE; + break; + } + } + if(!authbits) + return CURLE_NOT_BUILT_IN; /* no supported types left! */ + + data->set.httpauth = auth; + } + break; + + case CURLOPT_CUSTOMREQUEST: + /* + * Set a custom string to use as request + */ + result = Curl_setstropt(&data->set.str[STRING_CUSTOMREQUEST], + va_arg(param, char *)); + + /* we don't set + data->set.httpreq = HTTPREQ_CUSTOM; + here, we continue as if we were using the already set type + and this just changes the actual request keyword */ + break; + +#ifndef CURL_DISABLE_PROXY + case CURLOPT_HTTPPROXYTUNNEL: + /* + * Tunnel operations through the proxy instead of normal proxy use + */ + data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long)) ? + TRUE : FALSE; + break; + + case CURLOPT_PROXYPORT: + /* + * Explicitly set HTTP proxy port number. + */ + arg = va_arg(param, long); + if((arg < 0) || (arg > 65535)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.proxyport = arg; + break; + + case CURLOPT_PROXYAUTH: + /* + * Set HTTP Authentication type BITMASK. + */ + { + int bitcheck; + bool authbits; + unsigned long auth = va_arg(param, unsigned long); + + if(auth == CURLAUTH_NONE) { + data->set.proxyauth = auth; + break; + } + + /* the DIGEST_IE bit is only used to set a special marker, for all the + rest we need to handle it as normal DIGEST */ + data->state.authproxy.iestyle = + (bool)((auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE); + + if(auth & CURLAUTH_DIGEST_IE) { + auth |= CURLAUTH_DIGEST; /* set standard digest bit */ + auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */ + } + /* switch off bits we can't support */ +#ifndef USE_NTLM + auth &= ~CURLAUTH_NTLM; /* no NTLM support */ + auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */ +#elif !defined(NTLM_WB_ENABLED) + auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */ +#endif +#ifndef USE_SPNEGO + auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without + GSS-API or SSPI */ +#endif + + /* check if any auth bit lower than CURLAUTH_ONLY is still set */ + bitcheck = 0; + authbits = FALSE; + while(bitcheck < 31) { + if(auth & (1UL << bitcheck++)) { + authbits = TRUE; + break; + } + } + if(!authbits) + return CURLE_NOT_BUILT_IN; /* no supported types left! */ + + data->set.proxyauth = auth; + } + break; + + case CURLOPT_PROXY: + /* + * Set proxy server:port to use as proxy. + * + * If the proxy is set to "" (and CURLOPT_SOCKS_PROXY is set to "" or NULL) + * we explicitly say that we don't want to use a proxy + * (even though there might be environment variables saying so). + * + * Setting it to NULL, means no proxy but allows the environment variables + * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL). + */ + result = Curl_setstropt(&data->set.str[STRING_PROXY], + va_arg(param, char *)); + break; + + case CURLOPT_PRE_PROXY: + /* + * Set proxy server:port to use as SOCKS proxy. + * + * If the proxy is set to "" or NULL we explicitly say that we don't want + * to use the socks proxy. + */ + result = Curl_setstropt(&data->set.str[STRING_PRE_PROXY], + va_arg(param, char *)); + break; + + case CURLOPT_PROXYTYPE: + /* + * Set proxy type. HTTP/HTTP_1_0/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME + */ + arg = va_arg(param, long); + if((arg < CURLPROXY_HTTP) || (arg > CURLPROXY_SOCKS5_HOSTNAME)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.proxytype = (curl_proxytype)arg; + break; + + case CURLOPT_PROXY_TRANSFER_MODE: + /* + * set transfer mode (;type=) when doing FTP via an HTTP proxy + */ + switch(va_arg(param, long)) { + case 0: + data->set.proxy_transfer_mode = FALSE; + break; + case 1: + data->set.proxy_transfer_mode = TRUE; + break; + default: + /* reserve other values for future use */ + result = CURLE_UNKNOWN_OPTION; + break; + } + break; +#endif /* CURL_DISABLE_PROXY */ + + case CURLOPT_SOCKS5_AUTH: + data->set.socks5auth = va_arg(param, unsigned long); + if(data->set.socks5auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI)) + result = CURLE_NOT_BUILT_IN; + break; +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + case CURLOPT_SOCKS5_GSSAPI_NEC: + /* + * Set flag for NEC SOCK5 support + */ + data->set.socks5_gssapi_nec = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; +#endif +#ifndef CURL_DISABLE_PROXY + case CURLOPT_SOCKS5_GSSAPI_SERVICE: + case CURLOPT_PROXY_SERVICE_NAME: + /* + * Set proxy authentication service name for Kerberos 5 and SPNEGO + */ + result = Curl_setstropt(&data->set.str[STRING_PROXY_SERVICE_NAME], + va_arg(param, char *)); + break; +#endif + case CURLOPT_SERVICE_NAME: + /* + * Set authentication service name for DIGEST-MD5, Kerberos 5 and SPNEGO + */ + result = Curl_setstropt(&data->set.str[STRING_SERVICE_NAME], + va_arg(param, char *)); + break; + + case CURLOPT_HEADERDATA: + /* + * Custom pointer to pass the header write callback function + */ + data->set.writeheader = (void *)va_arg(param, void *); + break; + case CURLOPT_ERRORBUFFER: + /* + * Error buffer provided by the caller to get the human readable + * error string in. + */ + data->set.errorbuffer = va_arg(param, char *); + break; + case CURLOPT_WRITEDATA: + /* + * FILE pointer to write to. Or possibly + * used as argument to the write callback. + */ + data->set.out = va_arg(param, void *); + break; + + case CURLOPT_DIRLISTONLY: + /* + * An option that changes the command to one that asks for a list only, no + * file info details. Used for FTP, POP3 and SFTP. + */ + data->set.ftp_list_only = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_APPEND: + /* + * We want to upload and append to an existing file. Used for FTP and + * SFTP. + */ + data->set.ftp_append = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + +#ifndef CURL_DISABLE_FTP + case CURLOPT_FTP_FILEMETHOD: + /* + * How do access files over FTP. + */ + arg = va_arg(param, long); + if((arg < CURLFTPMETHOD_DEFAULT) || (arg > CURLFTPMETHOD_SINGLECWD)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.ftp_filemethod = (curl_ftpfile)arg; + break; + case CURLOPT_FTPPORT: + /* + * Use FTP PORT, this also specifies which IP address to use + */ + result = Curl_setstropt(&data->set.str[STRING_FTPPORT], + va_arg(param, char *)); + data->set.ftp_use_port = (data->set.str[STRING_FTPPORT]) ? TRUE : FALSE; + break; + + case CURLOPT_FTP_USE_EPRT: + data->set.ftp_use_eprt = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_FTP_USE_EPSV: + data->set.ftp_use_epsv = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_FTP_USE_PRET: + data->set.ftp_use_pret = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_FTP_SSL_CCC: + arg = va_arg(param, long); + if((arg < CURLFTPSSL_CCC_NONE) || (arg > CURLFTPSSL_CCC_ACTIVE)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.ftp_ccc = (curl_ftpccc)arg; + break; + + case CURLOPT_FTP_SKIP_PASV_IP: + /* + * Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the + * bypass of the IP address in PASV responses. + */ + data->set.ftp_skip_ip = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_FTP_ACCOUNT: + result = Curl_setstropt(&data->set.str[STRING_FTP_ACCOUNT], + va_arg(param, char *)); + break; + + case CURLOPT_FTP_ALTERNATIVE_TO_USER: + result = Curl_setstropt(&data->set.str[STRING_FTP_ALTERNATIVE_TO_USER], + va_arg(param, char *)); + break; + + case CURLOPT_FTPSSLAUTH: + /* + * Set a specific auth for FTP-SSL transfers. + */ + arg = va_arg(param, long); + if((arg < CURLFTPAUTH_DEFAULT) || (arg > CURLFTPAUTH_TLS)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.ftpsslauth = (curl_ftpauth)arg; + break; + case CURLOPT_KRBLEVEL: + /* + * A string that defines the kerberos security level. + */ + result = Curl_setstropt(&data->set.str[STRING_KRB_LEVEL], + va_arg(param, char *)); + data->set.krb = (data->set.str[STRING_KRB_LEVEL]) ? TRUE : FALSE; + break; +#endif + case CURLOPT_FTP_CREATE_MISSING_DIRS: + /* + * An FTP/SFTP option that modifies an upload to create missing + * directories on the server. + */ + switch(va_arg(param, long)) { + case 0: + data->set.ftp_create_missing_dirs = 0; + break; + case 1: + data->set.ftp_create_missing_dirs = 1; + break; + case 2: + data->set.ftp_create_missing_dirs = 2; + break; + default: + /* reserve other values for future use */ + result = CURLE_UNKNOWN_OPTION; + break; + } + break; + case CURLOPT_READDATA: + /* + * FILE pointer to read the file to be uploaded from. Or possibly + * used as argument to the read callback. + */ + data->set.in_set = va_arg(param, void *); + break; + case CURLOPT_INFILESIZE: + /* + * If known, this should inform curl about the file size of the + * to-be-uploaded file. + */ + arg = va_arg(param, long); + if(arg < -1) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.filesize = arg; + break; + case CURLOPT_INFILESIZE_LARGE: + /* + * If known, this should inform curl about the file size of the + * to-be-uploaded file. + */ + bigsize = va_arg(param, curl_off_t); + if(bigsize < -1) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.filesize = bigsize; + break; + case CURLOPT_LOW_SPEED_LIMIT: + /* + * The low speed limit that if transfers are below this for + * CURLOPT_LOW_SPEED_TIME, the transfer is aborted. + */ + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.low_speed_limit = arg; + break; + case CURLOPT_MAX_SEND_SPEED_LARGE: + /* + * When transfer uploads are faster then CURLOPT_MAX_SEND_SPEED_LARGE + * bytes per second the transfer is throttled.. + */ + bigsize = va_arg(param, curl_off_t); + if(bigsize < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.max_send_speed = bigsize; + break; + case CURLOPT_MAX_RECV_SPEED_LARGE: + /* + * When receiving data faster than CURLOPT_MAX_RECV_SPEED_LARGE bytes per + * second the transfer is throttled.. + */ + bigsize = va_arg(param, curl_off_t); + if(bigsize < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.max_recv_speed = bigsize; + break; + case CURLOPT_LOW_SPEED_TIME: + /* + * The low speed time that if transfers are below the set + * CURLOPT_LOW_SPEED_LIMIT during this time, the transfer is aborted. + */ + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.low_speed_time = arg; + break; + case CURLOPT_CURLU: + /* + * pass CURLU to set URL + */ + data->set.uh = va_arg(param, CURLU *); + break; + case CURLOPT_URL: + /* + * The URL to fetch. + */ + if(data->change.url_alloc) { + /* the already set URL is allocated, free it first! */ + Curl_safefree(data->change.url); + data->change.url_alloc = FALSE; + } + result = Curl_setstropt(&data->set.str[STRING_SET_URL], + va_arg(param, char *)); + data->change.url = data->set.str[STRING_SET_URL]; + break; + case CURLOPT_PORT: + /* + * The port number to use when getting the URL + */ + arg = va_arg(param, long); + if((arg < 0) || (arg > 65535)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.use_port = arg; + break; + case CURLOPT_TIMEOUT: + /* + * The maximum time you allow curl to use for a single transfer + * operation. + */ + arg = va_arg(param, long); + if((arg >= 0) && (arg <= (INT_MAX/1000))) + data->set.timeout = arg * 1000; + else + return CURLE_BAD_FUNCTION_ARGUMENT; + break; + + case CURLOPT_TIMEOUT_MS: + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.timeout = arg; + break; + + case CURLOPT_CONNECTTIMEOUT: + /* + * The maximum time you allow curl to use to connect. + */ + arg = va_arg(param, long); + if((arg >= 0) && (arg <= (INT_MAX/1000))) + data->set.connecttimeout = arg * 1000; + else + return CURLE_BAD_FUNCTION_ARGUMENT; + break; + + case CURLOPT_CONNECTTIMEOUT_MS: + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.connecttimeout = arg; + break; + + case CURLOPT_ACCEPTTIMEOUT_MS: + /* + * The maximum time you allow curl to wait for server connect + */ + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.accepttimeout = arg; + break; + + case CURLOPT_USERPWD: + /* + * user:password to use in the operation + */ + result = setstropt_userpwd(va_arg(param, char *), + &data->set.str[STRING_USERNAME], + &data->set.str[STRING_PASSWORD]); + break; + + case CURLOPT_USERNAME: + /* + * authentication user name to use in the operation + */ + result = Curl_setstropt(&data->set.str[STRING_USERNAME], + va_arg(param, char *)); + break; + + case CURLOPT_PASSWORD: + /* + * authentication password to use in the operation + */ + result = Curl_setstropt(&data->set.str[STRING_PASSWORD], + va_arg(param, char *)); + break; + + case CURLOPT_LOGIN_OPTIONS: + /* + * authentication options to use in the operation + */ + result = Curl_setstropt(&data->set.str[STRING_OPTIONS], + va_arg(param, char *)); + break; + + case CURLOPT_XOAUTH2_BEARER: + /* + * OAuth 2.0 bearer token to use in the operation + */ + result = Curl_setstropt(&data->set.str[STRING_BEARER], + va_arg(param, char *)); + break; + + case CURLOPT_POSTQUOTE: + /* + * List of RAW FTP commands to use after a transfer + */ + data->set.postquote = va_arg(param, struct curl_slist *); + break; + case CURLOPT_PREQUOTE: + /* + * List of RAW FTP commands to use prior to RETR (Wesley Laxton) + */ + data->set.prequote = va_arg(param, struct curl_slist *); + break; + case CURLOPT_QUOTE: + /* + * List of RAW FTP commands to use before a transfer + */ + data->set.quote = va_arg(param, struct curl_slist *); + break; + case CURLOPT_RESOLVE: + /* + * List of NAME:[address] names to populate the DNS cache with + * Prefix the NAME with dash (-) to _remove_ the name from the cache. + * + * Names added with this API will remain in the cache until explicitly + * removed or the handle is cleaned up. + * + * This API can remove any name from the DNS cache, but only entries + * that aren't actually in use right now will be pruned immediately. + */ + data->set.resolve = va_arg(param, struct curl_slist *); + data->change.resolve = data->set.resolve; + break; + case CURLOPT_PROGRESSFUNCTION: + /* + * Progress callback function + */ + data->set.fprogress = va_arg(param, curl_progress_callback); + if(data->set.fprogress) + data->progress.callback = TRUE; /* no longer internal */ + else + data->progress.callback = FALSE; /* NULL enforces internal */ + break; + + case CURLOPT_XFERINFOFUNCTION: + /* + * Transfer info callback function + */ + data->set.fxferinfo = va_arg(param, curl_xferinfo_callback); + if(data->set.fxferinfo) + data->progress.callback = TRUE; /* no longer internal */ + else + data->progress.callback = FALSE; /* NULL enforces internal */ + + break; + + case CURLOPT_PROGRESSDATA: + /* + * Custom client data to pass to the progress callback + */ + data->set.progress_client = va_arg(param, void *); + break; + +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXYUSERPWD: + /* + * user:password needed to use the proxy + */ + result = setstropt_userpwd(va_arg(param, char *), + &data->set.str[STRING_PROXYUSERNAME], + &data->set.str[STRING_PROXYPASSWORD]); + break; + case CURLOPT_PROXYUSERNAME: + /* + * authentication user name to use in the operation + */ + result = Curl_setstropt(&data->set.str[STRING_PROXYUSERNAME], + va_arg(param, char *)); + break; + case CURLOPT_PROXYPASSWORD: + /* + * authentication password to use in the operation + */ + result = Curl_setstropt(&data->set.str[STRING_PROXYPASSWORD], + va_arg(param, char *)); + break; + case CURLOPT_NOPROXY: + /* + * proxy exception list + */ + result = Curl_setstropt(&data->set.str[STRING_NOPROXY], + va_arg(param, char *)); + break; +#endif + + case CURLOPT_RANGE: + /* + * What range of the file you want to transfer + */ + result = Curl_setstropt(&data->set.str[STRING_SET_RANGE], + va_arg(param, char *)); + break; + case CURLOPT_RESUME_FROM: + /* + * Resume transfer at the given file position + */ + arg = va_arg(param, long); + if(arg < -1) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.set_resume_from = arg; + break; + case CURLOPT_RESUME_FROM_LARGE: + /* + * Resume transfer at the given file position + */ + bigsize = va_arg(param, curl_off_t); + if(bigsize < -1) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.set_resume_from = bigsize; + break; + case CURLOPT_DEBUGFUNCTION: + /* + * stderr write callback. + */ + data->set.fdebug = va_arg(param, curl_debug_callback); + /* + * if the callback provided is NULL, it'll use the default callback + */ + break; + case CURLOPT_DEBUGDATA: + /* + * Set to a void * that should receive all error writes. This + * defaults to CURLOPT_STDERR for normal operations. + */ + data->set.debugdata = va_arg(param, void *); + break; + case CURLOPT_STDERR: + /* + * Set to a FILE * that should receive all error writes. This + * defaults to stderr for normal operations. + */ + data->set.err = va_arg(param, FILE *); + if(!data->set.err) + data->set.err = stderr; + break; + case CURLOPT_HEADERFUNCTION: + /* + * Set header write callback + */ + data->set.fwrite_header = va_arg(param, curl_write_callback); + break; + case CURLOPT_WRITEFUNCTION: + /* + * Set data write callback + */ + data->set.fwrite_func = va_arg(param, curl_write_callback); + if(!data->set.fwrite_func) { + data->set.is_fwrite_set = 0; + /* When set to NULL, reset to our internal default function */ + data->set.fwrite_func = (curl_write_callback)fwrite; + } + else + data->set.is_fwrite_set = 1; + break; + case CURLOPT_READFUNCTION: + /* + * Read data callback + */ + data->set.fread_func_set = va_arg(param, curl_read_callback); + if(!data->set.fread_func_set) { + data->set.is_fread_set = 0; + /* When set to NULL, reset to our internal default function */ + data->set.fread_func_set = (curl_read_callback)fread; + } + else + data->set.is_fread_set = 1; + break; + case CURLOPT_SEEKFUNCTION: + /* + * Seek callback. Might be NULL. + */ + data->set.seek_func = va_arg(param, curl_seek_callback); + break; + case CURLOPT_SEEKDATA: + /* + * Seek control callback. Might be NULL. + */ + data->set.seek_client = va_arg(param, void *); + break; + case CURLOPT_CONV_FROM_NETWORK_FUNCTION: + /* + * "Convert from network encoding" callback + */ + data->set.convfromnetwork = va_arg(param, curl_conv_callback); + break; + case CURLOPT_CONV_TO_NETWORK_FUNCTION: + /* + * "Convert to network encoding" callback + */ + data->set.convtonetwork = va_arg(param, curl_conv_callback); + break; + case CURLOPT_CONV_FROM_UTF8_FUNCTION: + /* + * "Convert from UTF-8 encoding" callback + */ + data->set.convfromutf8 = va_arg(param, curl_conv_callback); + break; + case CURLOPT_IOCTLFUNCTION: + /* + * I/O control callback. Might be NULL. + */ + data->set.ioctl_func = va_arg(param, curl_ioctl_callback); + break; + case CURLOPT_IOCTLDATA: + /* + * I/O control data pointer. Might be NULL. + */ + data->set.ioctl_client = va_arg(param, void *); + break; + case CURLOPT_SSLCERT: + /* + * String that holds file name of the SSL certificate to use + */ + result = Curl_setstropt(&data->set.str[STRING_CERT_ORIG], + va_arg(param, char *)); + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_SSLCERT: + /* + * String that holds file name of the SSL certificate to use for proxy + */ + result = Curl_setstropt(&data->set.str[STRING_CERT_PROXY], + va_arg(param, char *)); + break; +#endif + case CURLOPT_SSLCERTTYPE: + /* + * String that holds file type of the SSL certificate to use + */ + result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE_ORIG], + va_arg(param, char *)); + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_SSLCERTTYPE: + /* + * String that holds file type of the SSL certificate to use for proxy + */ + result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE_PROXY], + va_arg(param, char *)); + break; +#endif + case CURLOPT_SSLKEY: + /* + * String that holds file name of the SSL key to use + */ + result = Curl_setstropt(&data->set.str[STRING_KEY_ORIG], + va_arg(param, char *)); + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_SSLKEY: + /* + * String that holds file name of the SSL key to use for proxy + */ + result = Curl_setstropt(&data->set.str[STRING_KEY_PROXY], + va_arg(param, char *)); + break; +#endif + case CURLOPT_SSLKEYTYPE: + /* + * String that holds file type of the SSL key to use + */ + result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE_ORIG], + va_arg(param, char *)); + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_SSLKEYTYPE: + /* + * String that holds file type of the SSL key to use for proxy + */ + result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE_PROXY], + va_arg(param, char *)); + break; +#endif + case CURLOPT_KEYPASSWD: + /* + * String that holds the SSL or SSH private key password. + */ + result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD_ORIG], + va_arg(param, char *)); + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_KEYPASSWD: + /* + * String that holds the SSL private key password for proxy. + */ + result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD_PROXY], + va_arg(param, char *)); + break; +#endif + case CURLOPT_SSLENGINE: + /* + * String that holds the SSL crypto engine. + */ + argptr = va_arg(param, char *); + if(argptr && argptr[0]) { + result = Curl_setstropt(&data->set.str[STRING_SSL_ENGINE], argptr); + if(!result) { + result = Curl_ssl_set_engine(data, argptr); + } + } + break; + + case CURLOPT_SSLENGINE_DEFAULT: + /* + * flag to set engine as default. + */ + Curl_setstropt(&data->set.str[STRING_SSL_ENGINE], NULL); + result = Curl_ssl_set_engine_default(data); + break; + case CURLOPT_CRLF: + /* + * Kludgy option to enable CRLF conversions. Subject for removal. + */ + data->set.crlf = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_HAPROXYPROTOCOL: + /* + * Set to send the HAProxy Proxy Protocol header + */ + data->set.haproxyprotocol = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; +#endif + case CURLOPT_INTERFACE: + /* + * Set what interface or address/hostname to bind the socket to when + * performing an operation and thus what from-IP your connection will use. + */ + result = Curl_setstropt(&data->set.str[STRING_DEVICE], + va_arg(param, char *)); + break; + case CURLOPT_LOCALPORT: + /* + * Set what local port to bind the socket to when performing an operation. + */ + arg = va_arg(param, long); + if((arg < 0) || (arg > 65535)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.localport = curlx_sltous(arg); + break; + case CURLOPT_LOCALPORTRANGE: + /* + * Set number of local ports to try, starting with CURLOPT_LOCALPORT. + */ + arg = va_arg(param, long); + if((arg < 0) || (arg > 65535)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.localportrange = curlx_sltosi(arg); + break; + case CURLOPT_GSSAPI_DELEGATION: + /* + * GSS-API credential delegation bitmask + */ + arg = va_arg(param, long); + if(arg < CURLGSSAPI_DELEGATION_NONE) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.gssapi_delegation = arg; + break; + case CURLOPT_SSL_VERIFYPEER: + /* + * Enable peer SSL verifying. + */ + data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)) ? + TRUE : FALSE; + + /* Update the current connection ssl_config. */ + if(data->conn) { + data->conn->ssl_config.verifypeer = + data->set.ssl.primary.verifypeer; + } + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_SSL_VERIFYPEER: + /* + * Enable peer SSL verifying for proxy. + */ + data->set.proxy_ssl.primary.verifypeer = + (0 != va_arg(param, long))?TRUE:FALSE; + + /* Update the current connection proxy_ssl_config. */ + if(data->conn) { + data->conn->proxy_ssl_config.verifypeer = + data->set.proxy_ssl.primary.verifypeer; + } + break; +#endif + case CURLOPT_SSL_VERIFYHOST: + /* + * Enable verification of the host name in the peer certificate + */ + arg = va_arg(param, long); + + /* Obviously people are not reading documentation and too many thought + this argument took a boolean when it wasn't and misused it. We thus ban + 1 as a sensible input and we warn about its use. Then we only have the + 2 action internally stored as TRUE. */ + + if(1 == arg) { + failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!"); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + + data->set.ssl.primary.verifyhost = (0 != arg) ? TRUE : FALSE; + + /* Update the current connection ssl_config. */ + if(data->conn) { + data->conn->ssl_config.verifyhost = + data->set.ssl.primary.verifyhost; + } + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_SSL_VERIFYHOST: + /* + * Enable verification of the host name in the peer certificate for proxy + */ + arg = va_arg(param, long); + + /* Obviously people are not reading documentation and too many thought + this argument took a boolean when it wasn't and misused it. We thus ban + 1 as a sensible input and we warn about its use. Then we only have the + 2 action internally stored as TRUE. */ + + if(1 == arg) { + failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!"); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + + data->set.proxy_ssl.primary.verifyhost = (0 != arg)?TRUE:FALSE; + + /* Update the current connection proxy_ssl_config. */ + if(data->conn) { + data->conn->proxy_ssl_config.verifyhost = + data->set.proxy_ssl.primary.verifyhost; + } + break; +#endif + case CURLOPT_SSL_VERIFYSTATUS: + /* + * Enable certificate status verifying. + */ + if(!Curl_ssl_cert_status_request()) { + result = CURLE_NOT_BUILT_IN; + break; + } + + data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)) ? + TRUE : FALSE; + + /* Update the current connection ssl_config. */ + if(data->conn) { + data->conn->ssl_config.verifystatus = + data->set.ssl.primary.verifystatus; + } + break; + case CURLOPT_SSL_CTX_FUNCTION: + /* + * Set a SSL_CTX callback + */ +#ifdef USE_SSL + if(Curl_ssl->supports & SSLSUPP_SSL_CTX) + data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback); + else +#endif + result = CURLE_NOT_BUILT_IN; + break; + case CURLOPT_SSL_CTX_DATA: + /* + * Set a SSL_CTX callback parameter pointer + */ +#ifdef USE_SSL + if(Curl_ssl->supports & SSLSUPP_SSL_CTX) + data->set.ssl.fsslctxp = va_arg(param, void *); + else +#endif + result = CURLE_NOT_BUILT_IN; + break; + case CURLOPT_SSL_FALSESTART: + /* + * Enable TLS false start. + */ + if(!Curl_ssl_false_start()) { + result = CURLE_NOT_BUILT_IN; + break; + } + + data->set.ssl.falsestart = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_CERTINFO: +#ifdef USE_SSL + if(Curl_ssl->supports & SSLSUPP_CERTINFO) + data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE; + else +#endif + result = CURLE_NOT_BUILT_IN; + break; + case CURLOPT_PINNEDPUBLICKEY: + /* + * Set pinned public key for SSL connection. + * Specify file name of the public key in DER format. + */ +#ifdef USE_SSL + if(Curl_ssl->supports & SSLSUPP_PINNEDPUBKEY) + result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG], + va_arg(param, char *)); + else +#endif + result = CURLE_NOT_BUILT_IN; + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_PINNEDPUBLICKEY: + /* + * Set pinned public key for SSL connection. + * Specify file name of the public key in DER format. + */ +#ifdef USE_SSL + if(Curl_ssl->supports & SSLSUPP_PINNEDPUBKEY) + result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY], + va_arg(param, char *)); + else +#endif + result = CURLE_NOT_BUILT_IN; + break; +#endif + case CURLOPT_CAINFO: + /* + * Set CA info for SSL connection. Specify file name of the CA certificate + */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_ORIG], + va_arg(param, char *)); + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_CAINFO: + /* + * Set CA info SSL connection for proxy. Specify file name of the + * CA certificate + */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY], + va_arg(param, char *)); + break; +#endif + case CURLOPT_CAPATH: + /* + * Set CA path info for SSL connection. Specify directory name of the CA + * certificates which have been prepared using openssl c_rehash utility. + */ +#ifdef USE_SSL + if(Curl_ssl->supports & SSLSUPP_CA_PATH) + /* This does not work on windows. */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG], + va_arg(param, char *)); + else +#endif + result = CURLE_NOT_BUILT_IN; + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_CAPATH: + /* + * Set CA path info for SSL connection proxy. Specify directory name of the + * CA certificates which have been prepared using openssl c_rehash utility. + */ +#ifdef USE_SSL + if(Curl_ssl->supports & SSLSUPP_CA_PATH) + /* This does not work on windows. */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY], + va_arg(param, char *)); + else +#endif + result = CURLE_NOT_BUILT_IN; + break; +#endif + case CURLOPT_CRLFILE: + /* + * Set CRL file info for SSL connection. Specify file name of the CRL + * to check certificates revocation + */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE_ORIG], + va_arg(param, char *)); + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_CRLFILE: + /* + * Set CRL file info for SSL connection for proxy. Specify file name of the + * CRL to check certificates revocation + */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE_PROXY], + va_arg(param, char *)); + break; +#endif + case CURLOPT_ISSUERCERT: + /* + * Set Issuer certificate file + * to check certificates issuer + */ + result = Curl_setstropt(&data->set.str[STRING_SSL_ISSUERCERT_ORIG], + va_arg(param, char *)); + break; +#ifndef CURL_DISABLE_TELNET + case CURLOPT_TELNETOPTIONS: + /* + * Set a linked list of telnet options + */ + data->set.telnet_options = va_arg(param, struct curl_slist *); + break; +#endif + case CURLOPT_BUFFERSIZE: + /* + * The application kindly asks for a differently sized receive buffer. + * If it seems reasonable, we'll use it. + */ + arg = va_arg(param, long); + + if(arg > READBUFFER_MAX) + arg = READBUFFER_MAX; + else if(arg < 1) + arg = READBUFFER_SIZE; + else if(arg < READBUFFER_MIN) + arg = READBUFFER_MIN; + + /* Resize if new size */ + if(arg != data->set.buffer_size) { + char *newbuff = realloc(data->state.buffer, arg + 1); + if(!newbuff) { + DEBUGF(fprintf(stderr, "Error: realloc of buffer failed\n")); + result = CURLE_OUT_OF_MEMORY; + } + else + data->state.buffer = newbuff; + } + data->set.buffer_size = arg; + + break; + + case CURLOPT_UPLOAD_BUFFERSIZE: + /* + * The application kindly asks for a differently sized upload buffer. + * Cap it to sensible. + */ + arg = va_arg(param, long); + + if(arg > UPLOADBUFFER_MAX) + arg = UPLOADBUFFER_MAX; + else if(arg < UPLOADBUFFER_MIN) + arg = UPLOADBUFFER_MIN; + + data->set.upload_buffer_size = arg; + Curl_safefree(data->state.ulbuf); /* force a realloc next opportunity */ + break; + + case CURLOPT_NOSIGNAL: + /* + * The application asks not to set any signal() or alarm() handlers, + * even when using a timeout. + */ + data->set.no_signal = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_SHARE: + { + struct Curl_share *set; + set = va_arg(param, struct Curl_share *); + + /* disconnect from old share, if any */ + if(data->share) { + Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE); + + if(data->dns.hostcachetype == HCACHE_SHARED) { + data->dns.hostcache = NULL; + data->dns.hostcachetype = HCACHE_NONE; + } + +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) + if(data->share->cookies == data->cookies) + data->cookies = NULL; +#endif + + if(data->share->sslsession == data->state.session) + data->state.session = NULL; + +#ifdef USE_LIBPSL + if(data->psl == &data->share->psl) + data->psl = data->multi? &data->multi->psl: NULL; +#endif + + data->share->dirty--; + + Curl_share_unlock(data, CURL_LOCK_DATA_SHARE); + data->share = NULL; + } + + /* use new share if it set */ + data->share = set; + if(data->share) { + + Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE); + + data->share->dirty++; + + if(data->share->specifier & (1<< CURL_LOCK_DATA_DNS)) { + /* use shared host cache */ + data->dns.hostcache = &data->share->hostcache; + data->dns.hostcachetype = HCACHE_SHARED; + } +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) + if(data->share->cookies) { + /* use shared cookie list, first free own one if any */ + Curl_cookie_cleanup(data->cookies); + /* enable cookies since we now use a share that uses cookies! */ + data->cookies = data->share->cookies; + } +#endif /* CURL_DISABLE_HTTP */ + if(data->share->sslsession) { + data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions; + data->state.session = data->share->sslsession; + } +#ifdef USE_LIBPSL + if(data->share->specifier & (1 << CURL_LOCK_DATA_PSL)) + data->psl = &data->share->psl; +#endif + + Curl_share_unlock(data, CURL_LOCK_DATA_SHARE); + } + /* check for host cache not needed, + * it will be done by curl_easy_perform */ + } + break; + + case CURLOPT_PRIVATE: + /* + * Set private data pointer. + */ + data->set.private_data = va_arg(param, void *); + break; + + case CURLOPT_MAXFILESIZE: + /* + * Set the maximum size of a file to download. + */ + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.max_filesize = arg; + break; + +#ifdef USE_SSL + case CURLOPT_USE_SSL: + /* + * Make transfers attempt to use SSL/TLS. + */ + arg = va_arg(param, long); + if((arg < CURLUSESSL_NONE) || (arg > CURLUSESSL_ALL)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.use_ssl = (curl_usessl)arg; + break; + + case CURLOPT_SSL_OPTIONS: + arg = va_arg(param, long); + data->set.ssl.enable_beast = + (bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE); + data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); + break; + +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_SSL_OPTIONS: + arg = va_arg(param, long); + data->set.proxy_ssl.enable_beast = + (bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE); + data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); + break; +#endif + +#endif + case CURLOPT_IPRESOLVE: + arg = va_arg(param, long); + if((arg < CURL_IPRESOLVE_WHATEVER) || (arg > CURL_IPRESOLVE_V6)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.ipver = arg; + break; + + case CURLOPT_MAXFILESIZE_LARGE: + /* + * Set the maximum size of a file to download. + */ + bigsize = va_arg(param, curl_off_t); + if(bigsize < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.max_filesize = bigsize; + break; + + case CURLOPT_TCP_NODELAY: + /* + * Enable or disable TCP_NODELAY, which will disable/enable the Nagle + * algorithm + */ + data->set.tcp_nodelay = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_IGNORE_CONTENT_LENGTH: + data->set.ignorecl = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_CONNECT_ONLY: + /* + * No data transfer, set up connection and let application use the socket + */ + data->set.connect_only = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_SOCKOPTFUNCTION: + /* + * socket callback function: called after socket() but before connect() + */ + data->set.fsockopt = va_arg(param, curl_sockopt_callback); + break; + + case CURLOPT_SOCKOPTDATA: + /* + * socket callback data pointer. Might be NULL. + */ + data->set.sockopt_client = va_arg(param, void *); + break; + + case CURLOPT_OPENSOCKETFUNCTION: + /* + * open/create socket callback function: called instead of socket(), + * before connect() + */ + data->set.fopensocket = va_arg(param, curl_opensocket_callback); + break; + + case CURLOPT_OPENSOCKETDATA: + /* + * socket callback data pointer. Might be NULL. + */ + data->set.opensocket_client = va_arg(param, void *); + break; + + case CURLOPT_CLOSESOCKETFUNCTION: + /* + * close socket callback function: called instead of close() + * when shutting down a connection + */ + data->set.fclosesocket = va_arg(param, curl_closesocket_callback); + break; + + case CURLOPT_RESOLVER_START_FUNCTION: + /* + * resolver start callback function: called before a new resolver request + * is started + */ + data->set.resolver_start = va_arg(param, curl_resolver_start_callback); + break; + + case CURLOPT_RESOLVER_START_DATA: + /* + * resolver start callback data pointer. Might be NULL. + */ + data->set.resolver_start_client = va_arg(param, void *); + break; + + case CURLOPT_CLOSESOCKETDATA: + /* + * socket callback data pointer. Might be NULL. + */ + data->set.closesocket_client = va_arg(param, void *); + break; + + case CURLOPT_SSL_SESSIONID_CACHE: + data->set.ssl.primary.sessionid = (0 != va_arg(param, long)) ? + TRUE : FALSE; + data->set.proxy_ssl.primary.sessionid = data->set.ssl.primary.sessionid; + break; + +#ifdef USE_SSH + /* we only include SSH options if explicitly built to support SSH */ + case CURLOPT_SSH_AUTH_TYPES: + data->set.ssh_auth_types = va_arg(param, long); + break; + + case CURLOPT_SSH_PUBLIC_KEYFILE: + /* + * Use this file instead of the $HOME/.ssh/id_dsa.pub file + */ + result = Curl_setstropt(&data->set.str[STRING_SSH_PUBLIC_KEY], + va_arg(param, char *)); + break; + + case CURLOPT_SSH_PRIVATE_KEYFILE: + /* + * Use this file instead of the $HOME/.ssh/id_dsa file + */ + result = Curl_setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY], + va_arg(param, char *)); + break; + case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5: + /* + * Option to allow for the MD5 of the host public key to be checked + * for validation purposes. + */ + result = Curl_setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5], + va_arg(param, char *)); + break; + + case CURLOPT_SSH_KNOWNHOSTS: + /* + * Store the file name to read known hosts from. + */ + result = Curl_setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS], + va_arg(param, char *)); + break; + + case CURLOPT_SSH_KEYFUNCTION: + /* setting to NULL is fine since the ssh.c functions themselves will + then rever to use the internal default */ + data->set.ssh_keyfunc = va_arg(param, curl_sshkeycallback); + break; + + case CURLOPT_SSH_KEYDATA: + /* + * Custom client data to pass to the SSH keyfunc callback + */ + data->set.ssh_keyfunc_userp = va_arg(param, void *); + break; + + case CURLOPT_SSH_COMPRESSION: + data->set.ssh_compression = (0 != va_arg(param, long))?TRUE:FALSE; + break; +#endif /* USE_SSH */ + + case CURLOPT_HTTP_TRANSFER_DECODING: + /* + * disable libcurl transfer encoding is used + */ + data->set.http_te_skip = (0 == va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_HTTP_CONTENT_DECODING: + /* + * raw data passed to the application when content encoding is used + */ + data->set.http_ce_skip = (0 == va_arg(param, long)) ? TRUE : FALSE; + break; + +#if !defined(CURL_DISABLE_FTP) || defined(USE_SSH) + case CURLOPT_NEW_FILE_PERMS: + /* + * Uses these permissions instead of 0644 + */ + arg = va_arg(param, long); + if((arg < 0) || (arg > 0777)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.new_file_perms = arg; + break; + + case CURLOPT_NEW_DIRECTORY_PERMS: + /* + * Uses these permissions instead of 0755 + */ + arg = va_arg(param, long); + if((arg < 0) || (arg > 0777)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.new_directory_perms = arg; + break; +#endif + + case CURLOPT_ADDRESS_SCOPE: + /* + * Use this scope id when using IPv6 + * We always get longs when passed plain numericals so we should check + * that the value fits into an unsigned 32 bit integer. + */ + uarg = va_arg(param, unsigned long); +#if SIZEOF_LONG > 4 + if(uarg > UINT_MAX) + return CURLE_BAD_FUNCTION_ARGUMENT; +#endif + data->set.scope_id = (unsigned int)uarg; + break; + + case CURLOPT_PROTOCOLS: + /* set the bitmask for the protocols that are allowed to be used for the + transfer, which thus helps the app which takes URLs from users or other + external inputs and want to restrict what protocol(s) to deal + with. Defaults to CURLPROTO_ALL. */ + data->set.allowed_protocols = va_arg(param, long); + break; + + case CURLOPT_REDIR_PROTOCOLS: + /* set the bitmask for the protocols that libcurl is allowed to follow to, + as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs + to be set in both bitmasks to be allowed to get redirected to. Defaults + to all protocols except FILE and SCP. */ + data->set.redir_protocols = va_arg(param, long); + break; + + case CURLOPT_DEFAULT_PROTOCOL: + /* Set the protocol to use when the URL doesn't include any protocol */ + result = Curl_setstropt(&data->set.str[STRING_DEFAULT_PROTOCOL], + va_arg(param, char *)); + break; +#ifndef CURL_DISABLE_SMTP + case CURLOPT_MAIL_FROM: + /* Set the SMTP mail originator */ + result = Curl_setstropt(&data->set.str[STRING_MAIL_FROM], + va_arg(param, char *)); + break; + + case CURLOPT_MAIL_AUTH: + /* Set the SMTP auth originator */ + result = Curl_setstropt(&data->set.str[STRING_MAIL_AUTH], + va_arg(param, char *)); + break; + + case CURLOPT_MAIL_RCPT: + /* Set the list of mail recipients */ + data->set.mail_rcpt = va_arg(param, struct curl_slist *); + break; +#endif + + case CURLOPT_SASL_IR: + /* Enable/disable SASL initial response */ + data->set.sasl_ir = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; +#ifndef CURL_DISABLE_RTSP + case CURLOPT_RTSP_REQUEST: + { + /* + * Set the RTSP request method (OPTIONS, SETUP, PLAY, etc...) + * Would this be better if the RTSPREQ_* were just moved into here? + */ + long curl_rtspreq = va_arg(param, long); + Curl_RtspReq rtspreq = RTSPREQ_NONE; + switch(curl_rtspreq) { + case CURL_RTSPREQ_OPTIONS: + rtspreq = RTSPREQ_OPTIONS; + break; + + case CURL_RTSPREQ_DESCRIBE: + rtspreq = RTSPREQ_DESCRIBE; + break; + + case CURL_RTSPREQ_ANNOUNCE: + rtspreq = RTSPREQ_ANNOUNCE; + break; + + case CURL_RTSPREQ_SETUP: + rtspreq = RTSPREQ_SETUP; + break; + + case CURL_RTSPREQ_PLAY: + rtspreq = RTSPREQ_PLAY; + break; + + case CURL_RTSPREQ_PAUSE: + rtspreq = RTSPREQ_PAUSE; + break; + + case CURL_RTSPREQ_TEARDOWN: + rtspreq = RTSPREQ_TEARDOWN; + break; + + case CURL_RTSPREQ_GET_PARAMETER: + rtspreq = RTSPREQ_GET_PARAMETER; + break; + + case CURL_RTSPREQ_SET_PARAMETER: + rtspreq = RTSPREQ_SET_PARAMETER; + break; + + case CURL_RTSPREQ_RECORD: + rtspreq = RTSPREQ_RECORD; + break; + + case CURL_RTSPREQ_RECEIVE: + rtspreq = RTSPREQ_RECEIVE; + break; + default: + rtspreq = RTSPREQ_NONE; + } + + data->set.rtspreq = rtspreq; + break; + } + + + case CURLOPT_RTSP_SESSION_ID: + /* + * Set the RTSP Session ID manually. Useful if the application is + * resuming a previously established RTSP session + */ + result = Curl_setstropt(&data->set.str[STRING_RTSP_SESSION_ID], + va_arg(param, char *)); + break; + + case CURLOPT_RTSP_STREAM_URI: + /* + * Set the Stream URI for the RTSP request. Unless the request is + * for generic server options, the application will need to set this. + */ + result = Curl_setstropt(&data->set.str[STRING_RTSP_STREAM_URI], + va_arg(param, char *)); + break; + + case CURLOPT_RTSP_TRANSPORT: + /* + * The content of the Transport: header for the RTSP request + */ + result = Curl_setstropt(&data->set.str[STRING_RTSP_TRANSPORT], + va_arg(param, char *)); + break; + + case CURLOPT_RTSP_CLIENT_CSEQ: + /* + * Set the CSEQ number to issue for the next RTSP request. Useful if the + * application is resuming a previously broken connection. The CSEQ + * will increment from this new number henceforth. + */ + data->state.rtsp_next_client_CSeq = va_arg(param, long); + break; + + case CURLOPT_RTSP_SERVER_CSEQ: + /* Same as the above, but for server-initiated requests */ + data->state.rtsp_next_client_CSeq = va_arg(param, long); + break; + + case CURLOPT_INTERLEAVEDATA: + data->set.rtp_out = va_arg(param, void *); + break; + case CURLOPT_INTERLEAVEFUNCTION: + /* Set the user defined RTP write function */ + data->set.fwrite_rtp = va_arg(param, curl_write_callback); + break; +#endif +#ifndef CURL_DISABLE_FTP + case CURLOPT_WILDCARDMATCH: + data->set.wildcard_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_CHUNK_BGN_FUNCTION: + data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback); + break; + case CURLOPT_CHUNK_END_FUNCTION: + data->set.chunk_end = va_arg(param, curl_chunk_end_callback); + break; + case CURLOPT_FNMATCH_FUNCTION: + data->set.fnmatch = va_arg(param, curl_fnmatch_callback); + break; + case CURLOPT_CHUNK_DATA: + data->wildcard.customptr = va_arg(param, void *); + break; + case CURLOPT_FNMATCH_DATA: + data->set.fnmatch_data = va_arg(param, void *); + break; +#endif +#ifdef USE_TLS_SRP + case CURLOPT_TLSAUTH_USERNAME: + result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_ORIG], + va_arg(param, char *)); + if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype) + data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + break; + case CURLOPT_PROXY_TLSAUTH_USERNAME: + result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY], + va_arg(param, char *)); + if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] && + !data->set.proxy_ssl.authtype) + data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + break; + case CURLOPT_TLSAUTH_PASSWORD: + result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_ORIG], + va_arg(param, char *)); + if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype) + data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + break; + case CURLOPT_PROXY_TLSAUTH_PASSWORD: + result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY], + va_arg(param, char *)); + if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] && + !data->set.proxy_ssl.authtype) + data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + break; + case CURLOPT_TLSAUTH_TYPE: + argptr = va_arg(param, char *); + if(!argptr || + strncasecompare(argptr, "SRP", strlen("SRP"))) + data->set.ssl.authtype = CURL_TLSAUTH_SRP; + else + data->set.ssl.authtype = CURL_TLSAUTH_NONE; + break; + case CURLOPT_PROXY_TLSAUTH_TYPE: + argptr = va_arg(param, char *); + if(!argptr || + strncasecompare(argptr, "SRP", strlen("SRP"))) + data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; + else + data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE; + break; +#endif +#ifdef USE_ARES + case CURLOPT_DNS_SERVERS: + result = Curl_set_dns_servers(data, va_arg(param, char *)); + break; + case CURLOPT_DNS_INTERFACE: + result = Curl_set_dns_interface(data, va_arg(param, char *)); + break; + case CURLOPT_DNS_LOCAL_IP4: + result = Curl_set_dns_local_ip4(data, va_arg(param, char *)); + break; + case CURLOPT_DNS_LOCAL_IP6: + result = Curl_set_dns_local_ip6(data, va_arg(param, char *)); + break; +#endif + case CURLOPT_TCP_KEEPALIVE: + data->set.tcp_keepalive = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_TCP_KEEPIDLE: + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.tcp_keepidle = arg; + break; + case CURLOPT_TCP_KEEPINTVL: + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.tcp_keepintvl = arg; + break; + case CURLOPT_TCP_FASTOPEN: +#if defined(CONNECT_DATA_IDEMPOTENT) || defined(MSG_FASTOPEN) || \ + defined(TCP_FASTOPEN_CONNECT) + data->set.tcp_fastopen = (0 != va_arg(param, long))?TRUE:FALSE; +#else + result = CURLE_NOT_BUILT_IN; +#endif + break; +#ifdef USE_NGHTTP2 + case CURLOPT_SSL_ENABLE_NPN: + data->set.ssl_enable_npn = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_SSL_ENABLE_ALPN: + data->set.ssl_enable_alpn = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; +#endif +#ifdef USE_UNIX_SOCKETS + case CURLOPT_UNIX_SOCKET_PATH: + data->set.abstract_unix_socket = FALSE; + result = Curl_setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH], + va_arg(param, char *)); + break; + case CURLOPT_ABSTRACT_UNIX_SOCKET: + data->set.abstract_unix_socket = TRUE; + result = Curl_setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH], + va_arg(param, char *)); + break; +#endif + + case CURLOPT_PATH_AS_IS: + data->set.path_as_is = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_PIPEWAIT: + data->set.pipewait = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_STREAM_WEIGHT: +#ifndef USE_NGHTTP2 + return CURLE_NOT_BUILT_IN; +#else + arg = va_arg(param, long); + if((arg >= 1) && (arg <= 256)) + data->set.stream_weight = (int)arg; + break; +#endif + case CURLOPT_STREAM_DEPENDS: + case CURLOPT_STREAM_DEPENDS_E: + { +#ifndef USE_NGHTTP2 + return CURLE_NOT_BUILT_IN; +#else + struct Curl_easy *dep = va_arg(param, struct Curl_easy *); + if(!dep || GOOD_EASY_HANDLE(dep)) { + if(data->set.stream_depends_on) { + Curl_http2_remove_child(data->set.stream_depends_on, data); + } + Curl_http2_add_child(dep, data, (option == CURLOPT_STREAM_DEPENDS_E)); + } + break; +#endif + } + case CURLOPT_CONNECT_TO: + data->set.connect_to = va_arg(param, struct curl_slist *); + break; + case CURLOPT_SUPPRESS_CONNECT_HEADERS: + data->set.suppress_connect_headers = (0 != va_arg(param, long))?TRUE:FALSE; + break; + case CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS: + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.happy_eyeballs_timeout = arg; + break; +#ifndef CURL_DISABLE_SHUFFLE_DNS + case CURLOPT_DNS_SHUFFLE_ADDRESSES: + data->set.dns_shuffle_addresses = (0 != va_arg(param, long)) ? TRUE:FALSE; + break; +#endif + case CURLOPT_DISALLOW_USERNAME_IN_URL: + data->set.disallow_username_in_url = + (0 != va_arg(param, long)) ? TRUE : FALSE; + break; +#ifndef CURL_DISABLE_DOH + case CURLOPT_DOH_URL: + result = Curl_setstropt(&data->set.str[STRING_DOH], + va_arg(param, char *)); + data->set.doh = data->set.str[STRING_DOH]?TRUE:FALSE; + break; +#endif + case CURLOPT_UPKEEP_INTERVAL_MS: + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.upkeep_interval_ms = arg; + break; + case CURLOPT_MAXAGE_CONN: + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.maxage_conn = arg; + break; + case CURLOPT_TRAILERFUNCTION: +#ifndef CURL_DISABLE_HTTP + data->set.trailer_callback = va_arg(param, curl_trailer_callback); +#endif + break; + case CURLOPT_TRAILERDATA: +#ifndef CURL_DISABLE_HTTP + data->set.trailer_data = va_arg(param, void *); +#endif + break; +#ifdef USE_ALTSVC + case CURLOPT_ALTSVC: + if(!data->asi) { + data->asi = Curl_altsvc_init(); + if(!data->asi) + return CURLE_OUT_OF_MEMORY; + } + argptr = va_arg(param, char *); + result = Curl_setstropt(&data->set.str[STRING_ALTSVC], argptr); + if(result) + return result; + (void)Curl_altsvc_load(data->asi, argptr); + break; + case CURLOPT_ALTSVC_CTRL: + if(!data->asi) { + data->asi = Curl_altsvc_init(); + if(!data->asi) + return CURLE_OUT_OF_MEMORY; + } + arg = va_arg(param, long); + result = Curl_altsvc_ctrl(data->asi, arg); + if(result) + return result; + break; +#endif + default: + /* unknown tag and its companion, just ignore: */ + result = CURLE_UNKNOWN_OPTION; + break; + } + + return result; +} + +/* + * curl_easy_setopt() is the external interface for setting options on an + * easy handle. + * + * NOTE: This is one of few API functions that are allowed to be called from + * within a callback. + */ + +#undef curl_easy_setopt +CURLcode curl_easy_setopt(struct Curl_easy *data, CURLoption tag, ...) +{ + va_list arg; + CURLcode result; + + if(!data) + return CURLE_BAD_FUNCTION_ARGUMENT; + + va_start(arg, tag); + + result = vsetopt(data, tag, arg); + + va_end(arg); + return result; +} diff --git a/dependencies/cmcurl/lib/setopt.h b/dependencies/cmcurl/lib/setopt.h new file mode 100644 index 0000000..c658e04 --- /dev/null +++ b/dependencies/cmcurl/lib/setopt.h @@ -0,0 +1,29 @@ +#ifndef HEADER_CURL_SETOPT_H +#define HEADER_CURL_SETOPT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +CURLcode Curl_setstropt(char **charp, const char *s); +CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, + va_list arg); + +#endif /* HEADER_CURL_SETOPT_H */ diff --git a/dependencies/cmcurl/lib/setup-os400.h b/dependencies/cmcurl/lib/setup-os400.h new file mode 100644 index 0000000..a3c2a7b --- /dev/null +++ b/dependencies/cmcurl/lib/setup-os400.h @@ -0,0 +1,223 @@ +#ifndef HEADER_CURL_SETUP_OS400_H +#define HEADER_CURL_SETUP_OS400_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + + +/* OS/400 netdb.h does not define NI_MAXHOST. */ +#define NI_MAXHOST 1025 + +/* OS/400 netdb.h does not define NI_MAXSERV. */ +#define NI_MAXSERV 32 + +/* No OS/400 header file defines u_int32_t. */ +typedef unsigned long u_int32_t; + + +/* System API wrapper prototypes & definitions to support ASCII parameters. */ + +#include +#include +#include +#include +#include + +extern int Curl_getaddrinfo_a(const char *nodename, + const char *servname, + const struct addrinfo *hints, + struct addrinfo **res); +#define getaddrinfo Curl_getaddrinfo_a + + +extern int Curl_getnameinfo_a(const struct sockaddr *sa, + curl_socklen_t salen, + char *nodename, curl_socklen_t nodenamelen, + char *servname, curl_socklen_t servnamelen, + int flags); +#define getnameinfo Curl_getnameinfo_a + + +/* GSKit wrappers. */ + +extern int Curl_gsk_environment_open(gsk_handle * my_env_handle); +#define gsk_environment_open Curl_gsk_environment_open + +extern int Curl_gsk_secure_soc_open(gsk_handle my_env_handle, + gsk_handle * my_session_handle); +#define gsk_secure_soc_open Curl_gsk_secure_soc_open + +extern int Curl_gsk_environment_close(gsk_handle * my_env_handle); +#define gsk_environment_close Curl_gsk_environment_close + +extern int Curl_gsk_secure_soc_close(gsk_handle * my_session_handle); +#define gsk_secure_soc_close Curl_gsk_secure_soc_close + +extern int Curl_gsk_environment_init(gsk_handle my_env_handle); +#define gsk_environment_init Curl_gsk_environment_init + +extern int Curl_gsk_secure_soc_init(gsk_handle my_session_handle); +#define gsk_secure_soc_init Curl_gsk_secure_soc_init + +extern int Curl_gsk_attribute_set_buffer_a(gsk_handle my_gsk_handle, + GSK_BUF_ID bufID, + const char *buffer, + int bufSize); +#define gsk_attribute_set_buffer Curl_gsk_attribute_set_buffer_a + +extern int Curl_gsk_attribute_set_enum(gsk_handle my_gsk_handle, + GSK_ENUM_ID enumID, + GSK_ENUM_VALUE enumValue); +#define gsk_attribute_set_enum Curl_gsk_attribute_set_enum + +extern int Curl_gsk_attribute_set_numeric_value(gsk_handle my_gsk_handle, + GSK_NUM_ID numID, + int numValue); +#define gsk_attribute_set_numeric_value Curl_gsk_attribute_set_numeric_value + +extern int Curl_gsk_attribute_set_callback(gsk_handle my_gsk_handle, + GSK_CALLBACK_ID callBackID, + void *callBackAreaPtr); +#define gsk_attribute_set_callback Curl_gsk_attribute_set_callback + +extern int Curl_gsk_attribute_get_buffer_a(gsk_handle my_gsk_handle, + GSK_BUF_ID bufID, + const char **buffer, + int *bufSize); +#define gsk_attribute_get_buffer Curl_gsk_attribute_get_buffer_a + +extern int Curl_gsk_attribute_get_enum(gsk_handle my_gsk_handle, + GSK_ENUM_ID enumID, + GSK_ENUM_VALUE *enumValue); +#define gsk_attribute_get_enum Curl_gsk_attribute_get_enum + +extern int Curl_gsk_attribute_get_numeric_value(gsk_handle my_gsk_handle, + GSK_NUM_ID numID, + int *numValue); +#define gsk_attribute_get_numeric_value Curl_gsk_attribute_get_numeric_value + +extern int Curl_gsk_attribute_get_cert_info(gsk_handle my_gsk_handle, + GSK_CERT_ID certID, + const gsk_cert_data_elem **certDataElem, + int *certDataElementCount); +#define gsk_attribute_get_cert_info Curl_gsk_attribute_get_cert_info + +extern int Curl_gsk_secure_soc_misc(gsk_handle my_session_handle, + GSK_MISC_ID miscID); +#define gsk_secure_soc_misc Curl_gsk_secure_soc_misc + +extern int Curl_gsk_secure_soc_read(gsk_handle my_session_handle, + char *readBuffer, + int readBufSize, int *amtRead); +#define gsk_secure_soc_read Curl_gsk_secure_soc_read + +extern int Curl_gsk_secure_soc_write(gsk_handle my_session_handle, + char *writeBuffer, + int writeBufSize, int *amtWritten); +#define gsk_secure_soc_write Curl_gsk_secure_soc_write + +extern const char * Curl_gsk_strerror_a(int gsk_return_value); +#define gsk_strerror Curl_gsk_strerror_a + +extern int Curl_gsk_secure_soc_startInit(gsk_handle my_session_handle, + int IOCompletionPort, + Qso_OverlappedIO_t * communicationsArea); +#define gsk_secure_soc_startInit Curl_gsk_secure_soc_startInit + + +/* GSSAPI wrappers. */ + +extern OM_uint32 Curl_gss_import_name_a(OM_uint32 * minor_status, + gss_buffer_t in_name, + gss_OID in_name_type, + gss_name_t * out_name); +#define gss_import_name Curl_gss_import_name_a + + +extern OM_uint32 Curl_gss_display_status_a(OM_uint32 * minor_status, + OM_uint32 status_value, + int status_type, gss_OID mech_type, + gss_msg_ctx_t * message_context, + gss_buffer_t status_string); +#define gss_display_status Curl_gss_display_status_a + + +extern OM_uint32 Curl_gss_init_sec_context_a(OM_uint32 * minor_status, + gss_cred_id_t cred_handle, + gss_ctx_id_t * context_handle, + gss_name_t target_name, + gss_OID mech_type, + gss_flags_t req_flags, + OM_uint32 time_req, + gss_channel_bindings_t + input_chan_bindings, + gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + gss_flags_t * ret_flags, + OM_uint32 * time_rec); +#define gss_init_sec_context Curl_gss_init_sec_context_a + + +extern OM_uint32 Curl_gss_delete_sec_context_a(OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_buffer_t output_token); +#define gss_delete_sec_context Curl_gss_delete_sec_context_a + + +/* LDAP wrappers. */ + +#define BerValue struct berval + +#define ldap_url_parse ldap_url_parse_utf8 +#define ldap_init Curl_ldap_init_a +#define ldap_simple_bind_s Curl_ldap_simple_bind_s_a +#define ldap_search_s Curl_ldap_search_s_a +#define ldap_get_values_len Curl_ldap_get_values_len_a +#define ldap_err2string Curl_ldap_err2string_a +#define ldap_get_dn Curl_ldap_get_dn_a +#define ldap_first_attribute Curl_ldap_first_attribute_a +#define ldap_next_attribute Curl_ldap_next_attribute_a + +/* Some socket functions must be wrapped to process textual addresses + like AF_UNIX. */ + +extern int Curl_os400_connect(int sd, struct sockaddr * destaddr, int addrlen); +extern int Curl_os400_bind(int sd, struct sockaddr * localaddr, int addrlen); +extern int Curl_os400_sendto(int sd, char *buffer, int buflen, int flags, + struct sockaddr * dstaddr, int addrlen); +extern int Curl_os400_recvfrom(int sd, char *buffer, int buflen, int flags, + struct sockaddr *fromaddr, int *addrlen); + +#define connect Curl_os400_connect +#define bind Curl_os400_bind +#define sendto Curl_os400_sendto +#define recvfrom Curl_os400_recvfrom + +#ifdef HAVE_LIBZ +#define zlibVersion Curl_os400_zlibVersion +#define inflateInit_ Curl_os400_inflateInit_ +#define inflateInit2_ Curl_os400_inflateInit2_ +#define inflate Curl_os400_inflate +#define inflateEnd Curl_os400_inflateEnd +#endif + +#endif /* HEADER_CURL_SETUP_OS400_H */ diff --git a/dependencies/cmcurl/lib/setup-vms.h b/dependencies/cmcurl/lib/setup-vms.h new file mode 100644 index 0000000..6c454ae --- /dev/null +++ b/dependencies/cmcurl/lib/setup-vms.h @@ -0,0 +1,443 @@ +#ifndef HEADER_CURL_SETUP_VMS_H +#define HEADER_CURL_SETUP_VMS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* */ +/* JEM, 12/30/12, VMS now generates config.h, so only define wrappers for */ +/* getenv(), getpwuid() and provide is_vms_shell() */ +/* Also need upper case symbols for system services, and */ +/* OpenSSL, and some Kerberos image */ + +#ifdef __DECC +#pragma message save +#pragma message disable dollarid +#endif + +/* Hide the stuff we are overriding */ +#define getenv decc_getenv +#ifdef __DECC +# if __INITIAL_POINTER_SIZE != 64 +# define getpwuid decc_getpwuid +# endif +#endif +#include +char *decc$getenv(const char *__name); +#include + +#include +#include + +#undef getenv +#undef getpwuid +#define getenv vms_getenv +#define getpwuid vms_getpwuid + +/* VAX needs these in upper case when compiling exact case */ +#define sys$assign SYS$ASSIGN +#define sys$dassgn SYS$DASSGN +#define sys$qiow SYS$QIOW + +#ifdef __DECC +# if __INITIAL_POINTER_SIZE +# pragma __pointer_size __save +# endif +#endif + +#if __USE_LONG_GID_T +# define decc_getpwuid DECC$__LONG_GID_GETPWUID +#else +# if __INITIAL_POINTER_SIZE +# define decc_getpwuid decc$__32_getpwuid +# else +# define decc_getpwuid decc$getpwuid +# endif +#endif + + struct passwd * decc_getpwuid(uid_t uid); + +#ifdef __DECC +# if __INITIAL_POINTER_SIZE == 32 +/* Translate the path, but only if the path is a VMS file specification */ +/* The translation is usually only needed for older versions of VMS */ +static char *vms_translate_path(const char *path) +{ + char *unix_path; + char *test_str; + + /* See if the result is in VMS format, if not, we are done */ + /* Assume that this is a PATH, not just some data */ + test_str = strpbrk(path, ":[<^"); + if(test_str == NULL) { + return (char *)path; + } + + unix_path = decc$translate_vms(path); + + if((int)unix_path <= 0) { + /* We can not translate it, so return the original string */ + return (char *)path; + } +} +# else + /* VMS translate path is actually not needed on the current 64 bit */ + /* VMS platforms, so instead of figuring out the pointer settings */ + /* Change it to a noop */ +# define vms_translate_path(__path) __path +# endif +#endif + +#ifdef __DECC +# if __INITIAL_POINTER_SIZE +# pragma __pointer_size __restore +# endif +#endif + +static char *vms_getenv(const char *envvar) +{ + char *result; + char *vms_path; + + /* first use the DECC getenv() function */ + result = decc$getenv(envvar); + if(result == NULL) { + return result; + } + + vms_path = result; + result = vms_translate_path(vms_path); + + /* note that if you backport this to use VAX C RTL, that the VAX C RTL */ + /* may do a malloc(2048) for each call to getenv(), so you will need */ + /* to add a free(vms_path) */ + /* Do not do a free() for DEC C RTL builds, which should be used for */ + /* VMS 5.5-2 and later, even if using GCC */ + + return result; +} + + +static struct passwd vms_passwd_cache; + +static struct passwd * vms_getpwuid(uid_t uid) +{ + struct passwd * my_passwd; + +/* Hack needed to support 64 bit builds, decc_getpwnam is 32 bit only */ +#ifdef __DECC +# if __INITIAL_POINTER_SIZE + __char_ptr32 unix_path; +# else + char *unix_path; +# endif +#else + char *unix_path; +#endif + + my_passwd = decc_getpwuid(uid); + if(my_passwd == NULL) { + return my_passwd; + } + + unix_path = vms_translate_path(my_passwd->pw_dir); + + if((long)unix_path <= 0) { + /* We can not translate it, so return the original string */ + return my_passwd; + } + + /* If no changes needed just return it */ + if(unix_path == my_passwd->pw_dir) { + return my_passwd; + } + + /* Need to copy the structure returned */ + /* Since curl is only using pw_dir, no need to fix up */ + /* the pw_shell when running under Bash */ + vms_passwd_cache.pw_name = my_passwd->pw_name; + vms_passwd_cache.pw_uid = my_passwd->pw_uid; + vms_passwd_cache.pw_gid = my_passwd->pw_uid; + vms_passwd_cache.pw_dir = unix_path; + vms_passwd_cache.pw_shell = my_passwd->pw_shell; + + return &vms_passwd_cache; +} + +#ifdef __DECC +#pragma message restore +#endif + +/* Bug - VMS OpenSSL and Kerberos universal symbols are in uppercase only */ +/* VMS libraries should have universal symbols in exact and uppercase */ + +#define ASN1_INTEGER_get ASN1_INTEGER_GET +#define ASN1_STRING_data ASN1_STRING_DATA +#define ASN1_STRING_length ASN1_STRING_LENGTH +#define ASN1_STRING_print ASN1_STRING_PRINT +#define ASN1_STRING_to_UTF8 ASN1_STRING_TO_UTF8 +#define ASN1_STRING_type ASN1_STRING_TYPE +#define BIO_ctrl BIO_CTRL +#define BIO_free BIO_FREE +#define BIO_new BIO_NEW +#define BIO_s_mem BIO_S_MEM +#define BN_bn2bin BN_BN2BIN +#define BN_num_bits BN_NUM_BITS +#define CRYPTO_cleanup_all_ex_data CRYPTO_CLEANUP_ALL_EX_DATA +#define CRYPTO_free CRYPTO_FREE +#define CRYPTO_malloc CRYPTO_MALLOC +#define CONF_modules_load_file CONF_MODULES_LOAD_FILE +#ifdef __VAX +# ifdef VMS_OLD_SSL + /* Ancient OpenSSL on VAX/VMS missing this constant */ +# define CONF_MFLAGS_IGNORE_MISSING_FILE 0x10 +# undef CONF_modules_load_file + static int CONF_modules_load_file(const char *filename, + const char *appname, + unsigned long flags) { + return 1; + } +# endif +#endif +#define DES_ecb_encrypt DES_ECB_ENCRYPT +#define DES_set_key DES_SET_KEY +#define DES_set_odd_parity DES_SET_ODD_PARITY +#define ENGINE_ctrl ENGINE_CTRL +#define ENGINE_ctrl_cmd ENGINE_CTRL_CMD +#define ENGINE_finish ENGINE_FINISH +#define ENGINE_free ENGINE_FREE +#define ENGINE_get_first ENGINE_GET_FIRST +#define ENGINE_get_id ENGINE_GET_ID +#define ENGINE_get_next ENGINE_GET_NEXT +#define ENGINE_init ENGINE_INIT +#define ENGINE_load_builtin_engines ENGINE_LOAD_BUILTIN_ENGINES +#define ENGINE_load_private_key ENGINE_LOAD_PRIVATE_KEY +#define ENGINE_set_default ENGINE_SET_DEFAULT +#define ERR_clear_error ERR_CLEAR_ERROR +#define ERR_error_string ERR_ERROR_STRING +#define ERR_error_string_n ERR_ERROR_STRING_N +#define ERR_free_strings ERR_FREE_STRINGS +#define ERR_get_error ERR_GET_ERROR +#define ERR_peek_error ERR_PEEK_ERROR +#define ERR_remove_state ERR_REMOVE_STATE +#define EVP_PKEY_copy_parameters EVP_PKEY_COPY_PARAMETERS +#define EVP_PKEY_free EVP_PKEY_FREE +#define EVP_cleanup EVP_CLEANUP +#define GENERAL_NAMES_free GENERAL_NAMES_FREE +#define i2d_X509_PUBKEY I2D_X509_PUBKEY +#define MD4_Final MD4_FINAL +#define MD4_Init MD4_INIT +#define MD4_Update MD4_UPDATE +#define MD5_Final MD5_FINAL +#define MD5_Init MD5_INIT +#define MD5_Update MD5_UPDATE +#define OPENSSL_add_all_algo_noconf OPENSSL_ADD_ALL_ALGO_NOCONF +#ifndef __VAX +#define OPENSSL_load_builtin_modules OPENSSL_LOAD_BUILTIN_MODULES +#endif +#define PEM_read_X509 PEM_READ_X509 +#define PEM_write_bio_X509 PEM_WRITE_BIO_X509 +#define PKCS12_PBE_add PKCS12_PBE_ADD +#define PKCS12_free PKCS12_FREE +#define PKCS12_parse PKCS12_PARSE +#define RAND_add RAND_ADD +#define RAND_bytes RAND_BYTES +#define RAND_egd RAND_EGD +#define RAND_file_name RAND_FILE_NAME +#define RAND_load_file RAND_LOAD_FILE +#define RAND_status RAND_STATUS +#define SSL_CIPHER_get_name SSL_CIPHER_GET_NAME +#define SSL_CTX_add_client_CA SSL_CTX_ADD_CLIENT_CA +#define SSL_CTX_callback_ctrl SSL_CTX_CALLBACK_CTRL +#define SSL_CTX_check_private_key SSL_CTX_CHECK_PRIVATE_KEY +#define SSL_CTX_ctrl SSL_CTX_CTRL +#define SSL_CTX_free SSL_CTX_FREE +#define SSL_CTX_get_cert_store SSL_CTX_GET_CERT_STORE +#define SSL_CTX_load_verify_locations SSL_CTX_LOAD_VERIFY_LOCATIONS +#define SSL_CTX_new SSL_CTX_NEW +#define SSL_CTX_set_cipher_list SSL_CTX_SET_CIPHER_LIST +#define SSL_CTX_set_def_passwd_cb_ud SSL_CTX_SET_DEF_PASSWD_CB_UD +#define SSL_CTX_set_default_passwd_cb SSL_CTX_SET_DEFAULT_PASSWD_CB +#define SSL_CTX_set_msg_callback SSL_CTX_SET_MSG_CALLBACK +#define SSL_CTX_set_verify SSL_CTX_SET_VERIFY +#define SSL_CTX_use_PrivateKey SSL_CTX_USE_PRIVATEKEY +#define SSL_CTX_use_PrivateKey_file SSL_CTX_USE_PRIVATEKEY_FILE +#define SSL_CTX_use_cert_chain_file SSL_CTX_USE_CERT_CHAIN_FILE +#define SSL_CTX_use_certificate SSL_CTX_USE_CERTIFICATE +#define SSL_CTX_use_certificate_file SSL_CTX_USE_CERTIFICATE_FILE +#define SSL_SESSION_free SSL_SESSION_FREE +#define SSL_connect SSL_CONNECT +#define SSL_free SSL_FREE +#define SSL_get1_session SSL_GET1_SESSION +#define SSL_get_certificate SSL_GET_CERTIFICATE +#define SSL_get_current_cipher SSL_GET_CURRENT_CIPHER +#define SSL_get_error SSL_GET_ERROR +#define SSL_get_peer_cert_chain SSL_GET_PEER_CERT_CHAIN +#define SSL_get_peer_certificate SSL_GET_PEER_CERTIFICATE +#define SSL_get_privatekey SSL_GET_PRIVATEKEY +#define SSL_get_session SSL_GET_SESSION +#define SSL_get_shutdown SSL_GET_SHUTDOWN +#define SSL_get_verify_result SSL_GET_VERIFY_RESULT +#define SSL_library_init SSL_LIBRARY_INIT +#define SSL_load_error_strings SSL_LOAD_ERROR_STRINGS +#define SSL_new SSL_NEW +#define SSL_peek SSL_PEEK +#define SSL_pending SSL_PENDING +#define SSL_read SSL_READ +#define SSL_set_connect_state SSL_SET_CONNECT_STATE +#define SSL_set_fd SSL_SET_FD +#define SSL_set_session SSL_SET_SESSION +#define SSL_shutdown SSL_SHUTDOWN +#define SSL_version SSL_VERSION +#define SSL_write SSL_WRITE +#define SSLeay SSLEAY +#define SSLv23_client_method SSLV23_CLIENT_METHOD +#define SSLv3_client_method SSLV3_CLIENT_METHOD +#define TLSv1_client_method TLSV1_CLIENT_METHOD +#define UI_create_method UI_CREATE_METHOD +#define UI_destroy_method UI_DESTROY_METHOD +#define UI_get0_user_data UI_GET0_USER_DATA +#define UI_get_input_flags UI_GET_INPUT_FLAGS +#define UI_get_string_type UI_GET_STRING_TYPE +#define UI_create_method UI_CREATE_METHOD +#define UI_destroy_method UI_DESTROY_METHOD +#define UI_method_get_closer UI_METHOD_GET_CLOSER +#define UI_method_get_opener UI_METHOD_GET_OPENER +#define UI_method_get_reader UI_METHOD_GET_READER +#define UI_method_get_writer UI_METHOD_GET_WRITER +#define UI_method_set_closer UI_METHOD_SET_CLOSER +#define UI_method_set_opener UI_METHOD_SET_OPENER +#define UI_method_set_reader UI_METHOD_SET_READER +#define UI_method_set_writer UI_METHOD_SET_WRITER +#define UI_OpenSSL UI_OPENSSL +#define UI_set_result UI_SET_RESULT +#define X509V3_EXT_print X509V3_EXT_PRINT +#define X509_EXTENSION_get_critical X509_EXTENSION_GET_CRITICAL +#define X509_EXTENSION_get_data X509_EXTENSION_GET_DATA +#define X509_EXTENSION_get_object X509_EXTENSION_GET_OBJECT +#define X509_LOOKUP_file X509_LOOKUP_FILE +#define X509_NAME_ENTRY_get_data X509_NAME_ENTRY_GET_DATA +#define X509_NAME_get_entry X509_NAME_GET_ENTRY +#define X509_NAME_get_index_by_NID X509_NAME_GET_INDEX_BY_NID +#define X509_NAME_print_ex X509_NAME_PRINT_EX +#define X509_STORE_CTX_get_current_cert X509_STORE_CTX_GET_CURRENT_CERT +#define X509_STORE_add_lookup X509_STORE_ADD_LOOKUP +#define X509_STORE_set_flags X509_STORE_SET_FLAGS +#define X509_check_issued X509_CHECK_ISSUED +#define X509_free X509_FREE +#define X509_get_ext_d2i X509_GET_EXT_D2I +#define X509_get_issuer_name X509_GET_ISSUER_NAME +#define X509_get_pubkey X509_GET_PUBKEY +#define X509_get_serialNumber X509_GET_SERIALNUMBER +#define X509_get_subject_name X509_GET_SUBJECT_NAME +#define X509_load_crl_file X509_LOAD_CRL_FILE +#define X509_verify_cert_error_string X509_VERIFY_CERT_ERROR_STRING +#define d2i_PKCS12_fp D2I_PKCS12_FP +#define i2t_ASN1_OBJECT I2T_ASN1_OBJECT +#define sk_num SK_NUM +#define sk_pop SK_POP +#define sk_pop_free SK_POP_FREE +#define sk_value SK_VALUE +#ifdef __VAX +#define OPENSSL_NO_SHA256 +#endif +#define SHA256_Final SHA256_FINAL +#define SHA256_Init SHA256_INIT +#define SHA256_Update SHA256_UPDATE + +#define USE_UPPERCASE_GSSAPI 1 +#define gss_seal GSS_SEAL +#define gss_unseal GSS_UNSEAL + +#define USE_UPPERCASE_KRBAPI 1 + +/* AI_NUMERICHOST needed for IP V6 support in Curl */ +#ifdef HAVE_NETDB_H +#include +#ifndef AI_NUMERICHOST +#ifdef ENABLE_IPV6 +#undef ENABLE_IPV6 +#endif +#endif +#endif + +/* VAX symbols are always in uppercase */ +#ifdef __VAX +#define inflate INFLATE +#define inflateEnd INFLATEEND +#define inflateInit2_ INFLATEINIT2_ +#define inflateInit_ INFLATEINIT_ +#define zlibVersion ZLIBVERSION +#endif + +/* Older VAX OpenSSL port defines these as Macros */ +/* Need to include the headers first and then redefine */ +/* that way a newer port will also work if some one has one */ +#ifdef __VAX + +# if (OPENSSL_VERSION_NUMBER < 0x00907001L) +# define des_set_odd_parity DES_SET_ODD_PARITY +# define des_set_key DES_SET_KEY +# define des_ecb_encrypt DES_ECB_ENCRYPT + +# endif +# include +# ifndef OpenSSL_add_all_algorithms +# define OpenSSL_add_all_algorithms OPENSSL_ADD_ALL_ALGORITHMS + void OPENSSL_ADD_ALL_ALGORITHMS(void); +# endif + + /* Curl defines these to lower case and VAX needs them in upper case */ + /* So we need static routines */ +# if (OPENSSL_VERSION_NUMBER < 0x00907001L) + +# undef des_set_odd_parity +# undef DES_set_odd_parity +# undef des_set_key +# undef DES_set_key +# undef des_ecb_encrypt +# undef DES_ecb_encrypt + + static void des_set_odd_parity(des_cblock *key) { + DES_SET_ODD_PARITY(key); + } + + static int des_set_key(const_des_cblock *key, + des_key_schedule schedule) { + return DES_SET_KEY(key, schedule); + } + + static void des_ecb_encrypt(const_des_cblock *input, + des_cblock *output, + des_key_schedule ks, int enc) { + DES_ECB_ENCRYPT(input, output, ks, enc); + } +#endif +/* Need this to stop a macro redefinition error */ +#if OPENSSL_VERSION_NUMBER < 0x00907000L +# ifdef X509_STORE_set_flags +# undef X509_STORE_set_flags +# define X509_STORE_set_flags(x,y) Curl_nop_stmt +# endif +#endif +#endif + +#endif /* HEADER_CURL_SETUP_VMS_H */ diff --git a/dependencies/cmcurl/lib/sha256.c b/dependencies/cmcurl/lib/sha256.c new file mode 100644 index 0000000..f9287af --- /dev/null +++ b/dependencies/cmcurl/lib/sha256.c @@ -0,0 +1,267 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Florin Petriuc, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_CRYPTO_AUTH + +#include "warnless.h" +#include "curl_sha256.h" + +#if defined(USE_OPENSSL) + +#include + +#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) +#define USE_OPENSSL_SHA256 +#endif + +#endif + +#ifdef USE_OPENSSL_SHA256 +/* When OpenSSL is available we use the SHA256-function from OpenSSL */ +#include +#else + +/* When no other crypto library is available we use this code segment */ + +/* ===== start - public domain SHA256 implementation ===== */ +/* This is based on SHA256 implementation in LibTomCrypt that was released into + * public domain by Tom St Denis. */ + +#define WPA_GET_BE32(a) ((((unsigned long)(a)[0]) << 24) | \ + (((unsigned long)(a)[1]) << 16) | \ + (((unsigned long)(a)[2]) << 8) | \ + ((unsigned long)(a)[3])) +#define WPA_PUT_BE32(a, val) \ +do { \ + (a)[0] = (unsigned char)((((unsigned long) (val)) >> 24) & 0xff); \ + (a)[1] = (unsigned char)((((unsigned long) (val)) >> 16) & 0xff); \ + (a)[2] = (unsigned char)((((unsigned long) (val)) >> 8) & 0xff); \ + (a)[3] = (unsigned char)(((unsigned long) (val)) & 0xff); \ +} while(0) + +#ifdef HAVE_LONGLONG +#define WPA_PUT_BE64(a, val) \ +do { \ + (a)[0] = (unsigned char)(((unsigned long long)(val)) >> 56); \ + (a)[1] = (unsigned char)(((unsigned long long)(val)) >> 48); \ + (a)[2] = (unsigned char)(((unsigned long long)(val)) >> 40); \ + (a)[3] = (unsigned char)(((unsigned long long)(val)) >> 32); \ + (a)[4] = (unsigned char)(((unsigned long long)(val)) >> 24); \ + (a)[5] = (unsigned char)(((unsigned long long)(val)) >> 16); \ + (a)[6] = (unsigned char)(((unsigned long long)(val)) >> 8); \ + (a)[7] = (unsigned char)(((unsigned long long)(val)) & 0xff); \ +} while(0) +#else +#define WPA_PUT_BE64(a, val) \ +do { \ + (a)[0] = (unsigned char)(((unsigned __int64)(val)) >> 56); \ + (a)[1] = (unsigned char)(((unsigned __int64)(val)) >> 48); \ + (a)[2] = (unsigned char)(((unsigned __int64)(val)) >> 40); \ + (a)[3] = (unsigned char)(((unsigned __int64)(val)) >> 32); \ + (a)[4] = (unsigned char)(((unsigned __int64)(val)) >> 24); \ + (a)[5] = (unsigned char)(((unsigned __int64)(val)) >> 16); \ + (a)[6] = (unsigned char)(((unsigned __int64)(val)) >> 8); \ + (a)[7] = (unsigned char)(((unsigned __int64)(val)) & 0xff); \ +} while(0) +#endif + +typedef struct sha256_state { +#ifdef HAVE_LONGLONG + unsigned long long length; +#else + unsigned __int64 length; +#endif + unsigned long state[8], curlen; + unsigned char buf[64]; +} SHA256_CTX; +/* the K array */ +static const unsigned long K[64] = { + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, + 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, + 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, + 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, + 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, + 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, + 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, + 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, + 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, + 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL +}; +/* Various logical functions */ +#define RORc(x, y) \ +(((((unsigned long)(x) & 0xFFFFFFFFUL) >> (unsigned long)((y) & 31)) | \ + ((unsigned long)(x) << (unsigned long)(32 - ((y) & 31)))) & 0xFFFFFFFFUL) +#define Ch(x,y,z) (z ^ (x & (y ^ z))) +#define Maj(x,y,z) (((x | y) & z) | (x & y)) +#define S(x, n) RORc((x), (n)) +#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) +#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) +#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) +#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) +#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) +/* compress 512-bits */ +static int sha256_compress(struct sha256_state *md, + unsigned char *buf) +{ + unsigned long S[8], W[64]; + int i; + /* copy state into S */ + for(i = 0; i < 8; i++) { + S[i] = md->state[i]; + } + /* copy the state into 512-bits into W[0..15] */ + for(i = 0; i < 16; i++) + W[i] = WPA_GET_BE32(buf + (4 * i)); + /* fill W[16..63] */ + for(i = 16; i < 64; i++) { + W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + + W[i - 16]; + } + /* Compress */ +#define RND(a,b,c,d,e,f,g,h,i) \ + unsigned long t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ + unsigned long t1 = Sigma0(a) + Maj(a, b, c); \ + d += t0; \ + h = t0 + t1; + for(i = 0; i < 64; ++i) { + unsigned long t; + RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i); + t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; + S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; + } + /* feedback */ + for(i = 0; i < 8; i++) { + md->state[i] = md->state[i] + S[i]; + } + return 0; +} +/* Initialize the hash state */ +static void SHA256_Init(struct sha256_state *md) +{ + md->curlen = 0; + md->length = 0; + md->state[0] = 0x6A09E667UL; + md->state[1] = 0xBB67AE85UL; + md->state[2] = 0x3C6EF372UL; + md->state[3] = 0xA54FF53AUL; + md->state[4] = 0x510E527FUL; + md->state[5] = 0x9B05688CUL; + md->state[6] = 0x1F83D9ABUL; + md->state[7] = 0x5BE0CD19UL; +} +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +static int SHA256_Update(struct sha256_state *md, + const unsigned char *in, + unsigned long inlen) +{ + unsigned long n; +#define block_size 64 + if(md->curlen > sizeof(md->buf)) + return -1; + while(inlen > 0) { + if(md->curlen == 0 && inlen >= block_size) { + if(sha256_compress(md, (unsigned char *)in) < 0) + return -1; + md->length += block_size * 8; + in += block_size; + inlen -= block_size; + } + else { + n = CURLMIN(inlen, (block_size - md->curlen)); + memcpy(md->buf + md->curlen, in, n); + md->curlen += n; + in += n; + inlen -= n; + if(md->curlen == block_size) { + if(sha256_compress(md, md->buf) < 0) + return -1; + md->length += 8 * block_size; + md->curlen = 0; + } + } + } + return 0; +} +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (32 bytes) + @return CRYPT_OK if successful +*/ +static int SHA256_Final(unsigned char *out, + struct sha256_state *md) +{ + int i; + if(md->curlen >= sizeof(md->buf)) + return -1; + /* increase the length of the message */ + md->length += md->curlen * 8; + /* append the '1' bit */ + md->buf[md->curlen++] = (unsigned char)0x80; + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if(md->curlen > 56) { + while(md->curlen < 64) { + md->buf[md->curlen++] = (unsigned char)0; + } + sha256_compress(md, md->buf); + md->curlen = 0; + } + /* pad up to 56 bytes of zeroes */ + while(md->curlen < 56) { + md->buf[md->curlen++] = (unsigned char)0; + } + /* store length */ + WPA_PUT_BE64(md->buf + 56, md->length); + sha256_compress(md, md->buf); + /* copy output */ + for(i = 0; i < 8; i++) + WPA_PUT_BE32(out + (4 * i), md->state[i]); + return 0; +} +/* ===== end - public domain SHA256 implementation ===== */ + +#endif + +void Curl_sha256it(unsigned char *outbuffer, /* 32 unsigned chars */ + const unsigned char *input) +{ + SHA256_CTX ctx; + SHA256_Init(&ctx); + SHA256_Update(&ctx, input, curlx_uztoui(strlen((char *)input))); + SHA256_Final(outbuffer, &ctx); +} + +#endif /* CURL_DISABLE_CRYPTO_AUTH */ diff --git a/dependencies/cmcurl/lib/share.c b/dependencies/cmcurl/lib/share.c new file mode 100644 index 0000000..3d51086 --- /dev/null +++ b/dependencies/cmcurl/lib/share.c @@ -0,0 +1,257 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include +#include "urldata.h" +#include "share.h" +#include "psl.h" +#include "vtls/vtls.h" +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +struct Curl_share * +curl_share_init(void) +{ + struct Curl_share *share = calloc(1, sizeof(struct Curl_share)); + if(share) { + share->specifier |= (1<hostcache)) { + free(share); + return NULL; + } + } + + return share; +} + +#undef curl_share_setopt +CURLSHcode +curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...) +{ + va_list param; + int type; + curl_lock_function lockfunc; + curl_unlock_function unlockfunc; + void *ptr; + CURLSHcode res = CURLSHE_OK; + + if(share->dirty) + /* don't allow setting options while one or more handles are already + using this share */ + return CURLSHE_IN_USE; + + va_start(param, option); + + switch(option) { + case CURLSHOPT_SHARE: + /* this is a type this share will share */ + type = va_arg(param, int); + share->specifier |= (1<cookies) { + share->cookies = Curl_cookie_init(NULL, NULL, NULL, TRUE); + if(!share->cookies) + res = CURLSHE_NOMEM; + } +#else /* CURL_DISABLE_HTTP */ + res = CURLSHE_NOT_BUILT_IN; +#endif + break; + + case CURL_LOCK_DATA_SSL_SESSION: +#ifdef USE_SSL + if(!share->sslsession) { + share->max_ssl_sessions = 8; + share->sslsession = calloc(share->max_ssl_sessions, + sizeof(struct curl_ssl_session)); + share->sessionage = 0; + if(!share->sslsession) + res = CURLSHE_NOMEM; + } +#else + res = CURLSHE_NOT_BUILT_IN; +#endif + break; + + case CURL_LOCK_DATA_CONNECT: /* not supported (yet) */ + if(Curl_conncache_init(&share->conn_cache, 103)) + res = CURLSHE_NOMEM; + break; + + case CURL_LOCK_DATA_PSL: +#ifndef USE_LIBPSL + res = CURLSHE_NOT_BUILT_IN; +#endif + break; + + default: + res = CURLSHE_BAD_OPTION; + } + break; + + case CURLSHOPT_UNSHARE: + /* this is a type this share will no longer share */ + type = va_arg(param, int); + share->specifier &= ~(1<cookies) { + Curl_cookie_cleanup(share->cookies); + share->cookies = NULL; + } +#else /* CURL_DISABLE_HTTP */ + res = CURLSHE_NOT_BUILT_IN; +#endif + break; + + case CURL_LOCK_DATA_SSL_SESSION: +#ifdef USE_SSL + Curl_safefree(share->sslsession); +#else + res = CURLSHE_NOT_BUILT_IN; +#endif + break; + + case CURL_LOCK_DATA_CONNECT: + break; + + default: + res = CURLSHE_BAD_OPTION; + break; + } + break; + + case CURLSHOPT_LOCKFUNC: + lockfunc = va_arg(param, curl_lock_function); + share->lockfunc = lockfunc; + break; + + case CURLSHOPT_UNLOCKFUNC: + unlockfunc = va_arg(param, curl_unlock_function); + share->unlockfunc = unlockfunc; + break; + + case CURLSHOPT_USERDATA: + ptr = va_arg(param, void *); + share->clientdata = ptr; + break; + + default: + res = CURLSHE_BAD_OPTION; + break; + } + + va_end(param); + + return res; +} + +CURLSHcode +curl_share_cleanup(struct Curl_share *share) +{ + if(share == NULL) + return CURLSHE_INVALID; + + if(share->lockfunc) + share->lockfunc(NULL, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE, + share->clientdata); + + if(share->dirty) { + if(share->unlockfunc) + share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata); + return CURLSHE_IN_USE; + } + + Curl_conncache_close_all_connections(&share->conn_cache); + Curl_conncache_destroy(&share->conn_cache); + Curl_hash_destroy(&share->hostcache); + +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) + Curl_cookie_cleanup(share->cookies); +#endif + +#ifdef USE_SSL + if(share->sslsession) { + size_t i; + for(i = 0; i < share->max_ssl_sessions; i++) + Curl_ssl_kill_session(&(share->sslsession[i])); + free(share->sslsession); + } +#endif + + Curl_psl_destroy(&share->psl); + + if(share->unlockfunc) + share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata); + free(share); + + return CURLSHE_OK; +} + + +CURLSHcode +Curl_share_lock(struct Curl_easy *data, curl_lock_data type, + curl_lock_access accesstype) +{ + struct Curl_share *share = data->share; + + if(share == NULL) + return CURLSHE_INVALID; + + if(share->specifier & (1<lockfunc) /* only call this if set! */ + share->lockfunc(data, type, accesstype, share->clientdata); + } + /* else if we don't share this, pretend successful lock */ + + return CURLSHE_OK; +} + +CURLSHcode +Curl_share_unlock(struct Curl_easy *data, curl_lock_data type) +{ + struct Curl_share *share = data->share; + + if(share == NULL) + return CURLSHE_INVALID; + + if(share->specifier & (1<unlockfunc) /* only call this if set! */ + share->unlockfunc (data, type, share->clientdata); + } + + return CURLSHE_OK; +} diff --git a/dependencies/cmcurl/lib/share.h b/dependencies/cmcurl/lib/share.h new file mode 100644 index 0000000..a7dea41 --- /dev/null +++ b/dependencies/cmcurl/lib/share.h @@ -0,0 +1,66 @@ +#ifndef HEADER_CURL_SHARE_H +#define HEADER_CURL_SHARE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include +#include "cookie.h" +#include "psl.h" +#include "urldata.h" +#include "conncache.h" + +/* SalfordC says "A structure member may not be volatile". Hence: + */ +#ifdef __SALFORDC__ +#define CURL_VOLATILE +#else +#define CURL_VOLATILE volatile +#endif + +/* this struct is libcurl-private, don't export details */ +struct Curl_share { + unsigned int specifier; + CURL_VOLATILE unsigned int dirty; + + curl_lock_function lockfunc; + curl_unlock_function unlockfunc; + void *clientdata; + struct conncache conn_cache; + struct curl_hash hostcache; +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) + struct CookieInfo *cookies; +#endif +#ifdef USE_LIBPSL + struct PslCache psl; +#endif + + struct curl_ssl_session *sslsession; + size_t max_ssl_sessions; + long sessionage; +}; + +CURLSHcode Curl_share_lock(struct Curl_easy *, curl_lock_data, + curl_lock_access); +CURLSHcode Curl_share_unlock(struct Curl_easy *, curl_lock_data); + +#endif /* HEADER_CURL_SHARE_H */ diff --git a/dependencies/cmcurl/lib/sigpipe.h b/dependencies/cmcurl/lib/sigpipe.h new file mode 100644 index 0000000..3960a13 --- /dev/null +++ b/dependencies/cmcurl/lib/sigpipe.h @@ -0,0 +1,79 @@ +#ifndef HEADER_CURL_SIGPIPE_H +#define HEADER_CURL_SIGPIPE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if defined(HAVE_SIGNAL_H) && defined(HAVE_SIGACTION) && \ + (defined(USE_OPENSSL) || defined(USE_MBEDTLS)) +#include + +struct sigpipe_ignore { + struct sigaction old_pipe_act; + bool no_signal; +}; + +#define SIGPIPE_VARIABLE(x) struct sigpipe_ignore x + +/* + * sigpipe_ignore() makes sure we ignore SIGPIPE while running libcurl + * internals, and then sigpipe_restore() will restore the situation when we + * return from libcurl again. + */ +static void sigpipe_ignore(struct Curl_easy *data, + struct sigpipe_ignore *ig) +{ + /* get a local copy of no_signal because the Curl_easy might not be + around when we restore */ + ig->no_signal = data->set.no_signal; + if(!data->set.no_signal) { + struct sigaction action; + /* first, extract the existing situation */ + memset(&ig->old_pipe_act, 0, sizeof(struct sigaction)); + sigaction(SIGPIPE, NULL, &ig->old_pipe_act); + action = ig->old_pipe_act; + /* ignore this signal */ + action.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &action, NULL); + } +} + +/* + * sigpipe_restore() puts back the outside world's opinion of signal handler + * and SIGPIPE handling. It MUST only be called after a corresponding + * sigpipe_ignore() was used. + */ +static void sigpipe_restore(struct sigpipe_ignore *ig) +{ + if(!ig->no_signal) + /* restore the outside state */ + sigaction(SIGPIPE, &ig->old_pipe_act, NULL); +} + +#else +/* for systems without sigaction */ +#define sigpipe_ignore(x,y) Curl_nop_stmt +#define sigpipe_restore(x) Curl_nop_stmt +#define SIGPIPE_VARIABLE(x) +#endif + +#endif /* HEADER_CURL_SIGPIPE_H */ diff --git a/dependencies/cmcurl/lib/slist.c b/dependencies/cmcurl/lib/slist.c new file mode 100644 index 0000000..392b84d --- /dev/null +++ b/dependencies/cmcurl/lib/slist.c @@ -0,0 +1,144 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "slist.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* returns last node in linked list */ +static struct curl_slist *slist_get_last(struct curl_slist *list) +{ + struct curl_slist *item; + + /* if caller passed us a NULL, return now */ + if(!list) + return NULL; + + /* loop through to find the last item */ + item = list; + while(item->next) { + item = item->next; + } + return item; +} + +/* + * Curl_slist_append_nodup() appends a string to the linked list. Rather than + * copying the string in dynamic storage, it takes its ownership. The string + * should have been malloc()ated. Curl_slist_append_nodup always returns + * the address of the first record, so that you can use this function as an + * initialization function as well as an append function. + * If an error occurs, NULL is returned and the string argument is NOT + * released. + */ +struct curl_slist *Curl_slist_append_nodup(struct curl_slist *list, char *data) +{ + struct curl_slist *last; + struct curl_slist *new_item; + + DEBUGASSERT(data); + + new_item = malloc(sizeof(struct curl_slist)); + if(!new_item) + return NULL; + + new_item->next = NULL; + new_item->data = data; + + /* if this is the first item, then new_item *is* the list */ + if(!list) + return new_item; + + last = slist_get_last(list); + last->next = new_item; + return list; +} + +/* + * curl_slist_append() appends a string to the linked list. It always returns + * the address of the first record, so that you can use this function as an + * initialization function as well as an append function. If you find this + * bothersome, then simply create a separate _init function and call it + * appropriately from within the program. + */ +struct curl_slist *curl_slist_append(struct curl_slist *list, + const char *data) +{ + char *dupdata = strdup(data); + + if(!dupdata) + return NULL; + + list = Curl_slist_append_nodup(list, dupdata); + if(!list) + free(dupdata); + + return list; +} + +/* + * Curl_slist_duplicate() duplicates a linked list. It always returns the + * address of the first record of the cloned list or NULL in case of an + * error (or if the input list was NULL). + */ +struct curl_slist *Curl_slist_duplicate(struct curl_slist *inlist) +{ + struct curl_slist *outlist = NULL; + struct curl_slist *tmp; + + while(inlist) { + tmp = curl_slist_append(outlist, inlist->data); + + if(!tmp) { + curl_slist_free_all(outlist); + return NULL; + } + + outlist = tmp; + inlist = inlist->next; + } + return outlist; +} + +/* be nice and clean up resources */ +void curl_slist_free_all(struct curl_slist *list) +{ + struct curl_slist *next; + struct curl_slist *item; + + if(!list) + return; + + item = list; + do { + next = item->next; + Curl_safefree(item->data); + free(item); + item = next; + } while(next); +} diff --git a/dependencies/cmcurl/lib/slist.h b/dependencies/cmcurl/lib/slist.h new file mode 100644 index 0000000..d73dbf6 --- /dev/null +++ b/dependencies/cmcurl/lib/slist.h @@ -0,0 +1,39 @@ +#ifndef HEADER_CURL_SLIST_H +#define HEADER_CURL_SLIST_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Curl_slist_duplicate() duplicates a linked list. It always returns the + * address of the first record of the cloned list or NULL in case of an + * error (or if the input list was NULL). + */ +struct curl_slist *Curl_slist_duplicate(struct curl_slist *inlist); + +/* + * Curl_slist_append_nodup() takes ownership of the given string and appends + * it to the list. + */ +struct curl_slist *Curl_slist_append_nodup(struct curl_slist *list, + char *data); + +#endif /* HEADER_CURL_SLIST_H */ diff --git a/dependencies/cmcurl/lib/smb.c b/dependencies/cmcurl/lib/smb.c new file mode 100644 index 0000000..76c99a2 --- /dev/null +++ b/dependencies/cmcurl/lib/smb.c @@ -0,0 +1,1002 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2014, Bill Nagel , Exacq Technologies + * Copyright (C) 2016-2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \ + (CURL_SIZEOF_CURL_OFF_T > 4) + +#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO) + +#define BUILDING_CURL_SMB_C + +#ifdef HAVE_PROCESS_H +#include +#ifdef CURL_WINDOWS_APP +#define getpid GetCurrentProcessId +#elif !defined(MSDOS) +#define getpid _getpid +#endif +#endif + +#include "smb.h" +#include "urldata.h" +#include "sendf.h" +#include "multiif.h" +#include "connect.h" +#include "progress.h" +#include "transfer.h" +#include "vtls/vtls.h" +#include "curl_ntlm_core.h" +#include "escape.h" +#include "curl_endian.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* Local API functions */ +static CURLcode smb_setup_connection(struct connectdata *conn); +static CURLcode smb_connect(struct connectdata *conn, bool *done); +static CURLcode smb_connection_state(struct connectdata *conn, bool *done); +static CURLcode smb_do(struct connectdata *conn, bool *done); +static CURLcode smb_request_state(struct connectdata *conn, bool *done); +static CURLcode smb_done(struct connectdata *conn, CURLcode status, + bool premature); +static CURLcode smb_disconnect(struct connectdata *conn, bool dead); +static int smb_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); +static CURLcode smb_parse_url_path(struct connectdata *conn); + +/* + * SMB handler interface + */ +const struct Curl_handler Curl_handler_smb = { + "SMB", /* scheme */ + smb_setup_connection, /* setup_connection */ + smb_do, /* do_it */ + smb_done, /* done */ + ZERO_NULL, /* do_more */ + smb_connect, /* connect_it */ + smb_connection_state, /* connecting */ + smb_request_state, /* doing */ + smb_getsock, /* proto_getsock */ + smb_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + smb_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_SMB, /* defport */ + CURLPROTO_SMB, /* protocol */ + PROTOPT_NONE /* flags */ +}; + +#ifdef USE_SSL +/* + * SMBS handler interface + */ +const struct Curl_handler Curl_handler_smbs = { + "SMBS", /* scheme */ + smb_setup_connection, /* setup_connection */ + smb_do, /* do_it */ + smb_done, /* done */ + ZERO_NULL, /* do_more */ + smb_connect, /* connect_it */ + smb_connection_state, /* connecting */ + smb_request_state, /* doing */ + smb_getsock, /* proto_getsock */ + smb_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + smb_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_SMBS, /* defport */ + CURLPROTO_SMBS, /* protocol */ + PROTOPT_SSL /* flags */ +}; +#endif + +#define MAX_PAYLOAD_SIZE 0x8000 +#define MAX_MESSAGE_SIZE (MAX_PAYLOAD_SIZE + 0x1000) +#define CLIENTNAME "curl" +#define SERVICENAME "?????" + +/* Append a string to an SMB message */ +#define MSGCAT(str) \ + strcpy(p, (str)); \ + p += strlen(str); + +/* Append a null-terminated string to an SMB message */ +#define MSGCATNULL(str) \ + strcpy(p, (str)); \ + p += strlen(str) + 1; + +/* SMB is mostly little endian */ +#if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \ + defined(__OS400__) +static unsigned short smb_swap16(unsigned short x) +{ + return (unsigned short) ((x << 8) | ((x >> 8) & 0xff)); +} + +static unsigned int smb_swap32(unsigned int x) +{ + return (x << 24) | ((x << 8) & 0xff0000) | ((x >> 8) & 0xff00) | + ((x >> 24) & 0xff); +} + +static curl_off_t smb_swap64(curl_off_t x) +{ + return ((curl_off_t) smb_swap32((unsigned int) x) << 32) | + smb_swap32((unsigned int) (x >> 32)); +} + +#else +# define smb_swap16(x) (x) +# define smb_swap32(x) (x) +# define smb_swap64(x) (x) +#endif + +/* SMB request state */ +enum smb_req_state { + SMB_REQUESTING, + SMB_TREE_CONNECT, + SMB_OPEN, + SMB_DOWNLOAD, + SMB_UPLOAD, + SMB_CLOSE, + SMB_TREE_DISCONNECT, + SMB_DONE +}; + +/* SMB request data */ +struct smb_request { + enum smb_req_state state; + char *path; + unsigned short tid; /* Even if we connect to the same tree as another */ + unsigned short fid; /* request, the tid will be different */ + CURLcode result; +}; + +static void conn_state(struct connectdata *conn, enum smb_conn_state newstate) +{ + struct smb_conn *smbc = &conn->proto.smbc; +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* For debug purposes */ + static const char * const names[] = { + "SMB_NOT_CONNECTED", + "SMB_CONNECTING", + "SMB_NEGOTIATE", + "SMB_SETUP", + "SMB_CONNECTED", + /* LAST */ + }; + + if(smbc->state != newstate) + infof(conn->data, "SMB conn %p state change from %s to %s\n", + (void *)smbc, names[smbc->state], names[newstate]); +#endif + + smbc->state = newstate; +} + +static void request_state(struct connectdata *conn, + enum smb_req_state newstate) +{ + struct smb_request *req = conn->data->req.protop; +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* For debug purposes */ + static const char * const names[] = { + "SMB_REQUESTING", + "SMB_TREE_CONNECT", + "SMB_OPEN", + "SMB_DOWNLOAD", + "SMB_UPLOAD", + "SMB_CLOSE", + "SMB_TREE_DISCONNECT", + "SMB_DONE", + /* LAST */ + }; + + if(req->state != newstate) + infof(conn->data, "SMB request %p state change from %s to %s\n", + (void *)req, names[req->state], names[newstate]); +#endif + + req->state = newstate; +} + +/* this should setup things in the connection, not in the easy + handle */ +static CURLcode smb_setup_connection(struct connectdata *conn) +{ + struct smb_request *req; + + /* Initialize the request state */ + conn->data->req.protop = req = calloc(1, sizeof(struct smb_request)); + if(!req) + return CURLE_OUT_OF_MEMORY; + + /* Parse the URL path */ + return smb_parse_url_path(conn); +} + +static CURLcode smb_connect(struct connectdata *conn, bool *done) +{ + struct smb_conn *smbc = &conn->proto.smbc; + char *slash; + + (void) done; + + /* Check we have a username and password to authenticate with */ + if(!conn->bits.user_passwd) + return CURLE_LOGIN_DENIED; + + /* Initialize the connection state */ + smbc->state = SMB_CONNECTING; + smbc->recv_buf = malloc(MAX_MESSAGE_SIZE); + if(!smbc->recv_buf) + return CURLE_OUT_OF_MEMORY; + + /* Multiple requests are allowed with this connection */ + connkeep(conn, "SMB default"); + + /* Parse the username, domain, and password */ + slash = strchr(conn->user, '/'); + if(!slash) + slash = strchr(conn->user, '\\'); + + if(slash) { + smbc->user = slash + 1; + smbc->domain = strdup(conn->user); + if(!smbc->domain) + return CURLE_OUT_OF_MEMORY; + smbc->domain[slash - conn->user] = 0; + } + else { + smbc->user = conn->user; + smbc->domain = strdup(conn->host.name); + if(!smbc->domain) + return CURLE_OUT_OF_MEMORY; + } + + return CURLE_OK; +} + +static CURLcode smb_recv_message(struct connectdata *conn, void **msg) +{ + struct smb_conn *smbc = &conn->proto.smbc; + char *buf = smbc->recv_buf; + ssize_t bytes_read; + size_t nbt_size; + size_t msg_size; + size_t len = MAX_MESSAGE_SIZE - smbc->got; + CURLcode result; + + result = Curl_read(conn, FIRSTSOCKET, buf + smbc->got, len, &bytes_read); + if(result) + return result; + + if(!bytes_read) + return CURLE_OK; + + smbc->got += bytes_read; + + /* Check for a 32-bit nbt header */ + if(smbc->got < sizeof(unsigned int)) + return CURLE_OK; + + nbt_size = Curl_read16_be((const unsigned char *) + (buf + sizeof(unsigned short))) + + sizeof(unsigned int); + if(smbc->got < nbt_size) + return CURLE_OK; + + msg_size = sizeof(struct smb_header); + if(nbt_size >= msg_size + 1) { + /* Add the word count */ + msg_size += 1 + ((unsigned char) buf[msg_size]) * sizeof(unsigned short); + if(nbt_size >= msg_size + sizeof(unsigned short)) { + /* Add the byte count */ + msg_size += sizeof(unsigned short) + + Curl_read16_le((const unsigned char *)&buf[msg_size]); + if(nbt_size < msg_size) + return CURLE_READ_ERROR; + } + } + + *msg = buf; + + return CURLE_OK; +} + +static void smb_pop_message(struct connectdata *conn) +{ + struct smb_conn *smbc = &conn->proto.smbc; + + smbc->got = 0; +} + +static void smb_format_message(struct connectdata *conn, struct smb_header *h, + unsigned char cmd, size_t len) +{ + struct smb_conn *smbc = &conn->proto.smbc; + struct smb_request *req = conn->data->req.protop; + unsigned int pid; + + memset(h, 0, sizeof(*h)); + h->nbt_length = htons((unsigned short) (sizeof(*h) - sizeof(unsigned int) + + len)); + memcpy((char *)h->magic, "\xffSMB", 4); + h->command = cmd; + h->flags = SMB_FLAGS_CANONICAL_PATHNAMES | SMB_FLAGS_CASELESS_PATHNAMES; + h->flags2 = smb_swap16(SMB_FLAGS2_IS_LONG_NAME | SMB_FLAGS2_KNOWS_LONG_NAME); + h->uid = smb_swap16(smbc->uid); + h->tid = smb_swap16(req->tid); + pid = getpid(); + h->pid_high = smb_swap16((unsigned short)(pid >> 16)); + h->pid = smb_swap16((unsigned short) pid); +} + +static CURLcode smb_send(struct connectdata *conn, ssize_t len, + size_t upload_size) +{ + struct smb_conn *smbc = &conn->proto.smbc; + ssize_t bytes_written; + CURLcode result; + + result = Curl_write(conn, FIRSTSOCKET, conn->data->state.ulbuf, + len, &bytes_written); + if(result) + return result; + + if(bytes_written != len) { + smbc->send_size = len; + smbc->sent = bytes_written; + } + + smbc->upload_size = upload_size; + + return CURLE_OK; +} + +static CURLcode smb_flush(struct connectdata *conn) +{ + struct smb_conn *smbc = &conn->proto.smbc; + ssize_t bytes_written; + ssize_t len = smbc->send_size - smbc->sent; + CURLcode result; + + if(!smbc->send_size) + return CURLE_OK; + + result = Curl_write(conn, FIRSTSOCKET, + conn->data->state.ulbuf + smbc->sent, + len, &bytes_written); + if(result) + return result; + + if(bytes_written != len) + smbc->sent += bytes_written; + else + smbc->send_size = 0; + + return CURLE_OK; +} + +static CURLcode smb_send_message(struct connectdata *conn, unsigned char cmd, + const void *msg, size_t msg_len) +{ + CURLcode result = Curl_get_upload_buffer(conn->data); + if(result) + return result; + smb_format_message(conn, (struct smb_header *)conn->data->state.ulbuf, + cmd, msg_len); + memcpy(conn->data->state.ulbuf + sizeof(struct smb_header), + msg, msg_len); + + return smb_send(conn, sizeof(struct smb_header) + msg_len, 0); +} + +static CURLcode smb_send_negotiate(struct connectdata *conn) +{ + const char *msg = "\x00\x0c\x00\x02NT LM 0.12"; + + return smb_send_message(conn, SMB_COM_NEGOTIATE, msg, 15); +} + +static CURLcode smb_send_setup(struct connectdata *conn) +{ + struct smb_conn *smbc = &conn->proto.smbc; + struct smb_setup msg; + char *p = msg.bytes; + unsigned char lm_hash[21]; + unsigned char lm[24]; + unsigned char nt_hash[21]; + unsigned char nt[24]; + + size_t byte_count = sizeof(lm) + sizeof(nt); + byte_count += strlen(smbc->user) + strlen(smbc->domain); + byte_count += strlen(OS) + strlen(CLIENTNAME) + 4; /* 4 null chars */ + if(byte_count > sizeof(msg.bytes)) + return CURLE_FILESIZE_EXCEEDED; + + Curl_ntlm_core_mk_lm_hash(conn->data, conn->passwd, lm_hash); + Curl_ntlm_core_lm_resp(lm_hash, smbc->challenge, lm); +#ifdef USE_NTRESPONSES + Curl_ntlm_core_mk_nt_hash(conn->data, conn->passwd, nt_hash); + Curl_ntlm_core_lm_resp(nt_hash, smbc->challenge, nt); +#else + memset(nt, 0, sizeof(nt)); +#endif + + memset(&msg, 0, sizeof(msg)); + msg.word_count = SMB_WC_SETUP_ANDX; + msg.andx.command = SMB_COM_NO_ANDX_COMMAND; + msg.max_buffer_size = smb_swap16(MAX_MESSAGE_SIZE); + msg.max_mpx_count = smb_swap16(1); + msg.vc_number = smb_swap16(1); + msg.session_key = smb_swap32(smbc->session_key); + msg.capabilities = smb_swap32(SMB_CAP_LARGE_FILES); + msg.lengths[0] = smb_swap16(sizeof(lm)); + msg.lengths[1] = smb_swap16(sizeof(nt)); + memcpy(p, lm, sizeof(lm)); + p += sizeof(lm); + memcpy(p, nt, sizeof(nt)); + p += sizeof(nt); + MSGCATNULL(smbc->user); + MSGCATNULL(smbc->domain); + MSGCATNULL(OS); + MSGCATNULL(CLIENTNAME); + byte_count = p - msg.bytes; + msg.byte_count = smb_swap16((unsigned short)byte_count); + + return smb_send_message(conn, SMB_COM_SETUP_ANDX, &msg, + sizeof(msg) - sizeof(msg.bytes) + byte_count); +} + +static CURLcode smb_send_tree_connect(struct connectdata *conn) +{ + struct smb_tree_connect msg; + struct smb_conn *smbc = &conn->proto.smbc; + char *p = msg.bytes; + + size_t byte_count = strlen(conn->host.name) + strlen(smbc->share); + byte_count += strlen(SERVICENAME) + 5; /* 2 nulls and 3 backslashes */ + if(byte_count > sizeof(msg.bytes)) + return CURLE_FILESIZE_EXCEEDED; + + memset(&msg, 0, sizeof(msg)); + msg.word_count = SMB_WC_TREE_CONNECT_ANDX; + msg.andx.command = SMB_COM_NO_ANDX_COMMAND; + msg.pw_len = 0; + MSGCAT("\\\\"); + MSGCAT(conn->host.name); + MSGCAT("\\"); + MSGCATNULL(smbc->share); + MSGCATNULL(SERVICENAME); /* Match any type of service */ + byte_count = p - msg.bytes; + msg.byte_count = smb_swap16((unsigned short)byte_count); + + return smb_send_message(conn, SMB_COM_TREE_CONNECT_ANDX, &msg, + sizeof(msg) - sizeof(msg.bytes) + byte_count); +} + +static CURLcode smb_send_open(struct connectdata *conn) +{ + struct smb_request *req = conn->data->req.protop; + struct smb_nt_create msg; + size_t byte_count; + + if((strlen(req->path) + 1) > sizeof(msg.bytes)) + return CURLE_FILESIZE_EXCEEDED; + + memset(&msg, 0, sizeof(msg)); + msg.word_count = SMB_WC_NT_CREATE_ANDX; + msg.andx.command = SMB_COM_NO_ANDX_COMMAND; + byte_count = strlen(req->path); + msg.name_length = smb_swap16((unsigned short)byte_count); + msg.share_access = smb_swap32(SMB_FILE_SHARE_ALL); + if(conn->data->set.upload) { + msg.access = smb_swap32(SMB_GENERIC_READ | SMB_GENERIC_WRITE); + msg.create_disposition = smb_swap32(SMB_FILE_OVERWRITE_IF); + } + else { + msg.access = smb_swap32(SMB_GENERIC_READ); + msg.create_disposition = smb_swap32(SMB_FILE_OPEN); + } + msg.byte_count = smb_swap16((unsigned short) ++byte_count); + strcpy(msg.bytes, req->path); + + return smb_send_message(conn, SMB_COM_NT_CREATE_ANDX, &msg, + sizeof(msg) - sizeof(msg.bytes) + byte_count); +} + +static CURLcode smb_send_close(struct connectdata *conn) +{ + struct smb_request *req = conn->data->req.protop; + struct smb_close msg; + + memset(&msg, 0, sizeof(msg)); + msg.word_count = SMB_WC_CLOSE; + msg.fid = smb_swap16(req->fid); + + return smb_send_message(conn, SMB_COM_CLOSE, &msg, sizeof(msg)); +} + +static CURLcode smb_send_tree_disconnect(struct connectdata *conn) +{ + struct smb_tree_disconnect msg; + + memset(&msg, 0, sizeof(msg)); + + return smb_send_message(conn, SMB_COM_TREE_DISCONNECT, &msg, sizeof(msg)); +} + +static CURLcode smb_send_read(struct connectdata *conn) +{ + struct smb_request *req = conn->data->req.protop; + curl_off_t offset = conn->data->req.offset; + struct smb_read msg; + + memset(&msg, 0, sizeof(msg)); + msg.word_count = SMB_WC_READ_ANDX; + msg.andx.command = SMB_COM_NO_ANDX_COMMAND; + msg.fid = smb_swap16(req->fid); + msg.offset = smb_swap32((unsigned int) offset); + msg.offset_high = smb_swap32((unsigned int) (offset >> 32)); + msg.min_bytes = smb_swap16(MAX_PAYLOAD_SIZE); + msg.max_bytes = smb_swap16(MAX_PAYLOAD_SIZE); + + return smb_send_message(conn, SMB_COM_READ_ANDX, &msg, sizeof(msg)); +} + +static CURLcode smb_send_write(struct connectdata *conn) +{ + struct smb_write *msg; + struct smb_request *req = conn->data->req.protop; + curl_off_t offset = conn->data->req.offset; + curl_off_t upload_size = conn->data->req.size - conn->data->req.bytecount; + CURLcode result = Curl_get_upload_buffer(conn->data); + if(result) + return result; + msg = (struct smb_write *)conn->data->state.ulbuf; + + if(upload_size >= MAX_PAYLOAD_SIZE - 1) /* There is one byte of padding */ + upload_size = MAX_PAYLOAD_SIZE - 1; + + memset(msg, 0, sizeof(*msg)); + msg->word_count = SMB_WC_WRITE_ANDX; + msg->andx.command = SMB_COM_NO_ANDX_COMMAND; + msg->fid = smb_swap16(req->fid); + msg->offset = smb_swap32((unsigned int) offset); + msg->offset_high = smb_swap32((unsigned int) (offset >> 32)); + msg->data_length = smb_swap16((unsigned short) upload_size); + msg->data_offset = smb_swap16(sizeof(*msg) - sizeof(unsigned int)); + msg->byte_count = smb_swap16((unsigned short) (upload_size + 1)); + + smb_format_message(conn, &msg->h, SMB_COM_WRITE_ANDX, + sizeof(*msg) - sizeof(msg->h) + (size_t) upload_size); + + return smb_send(conn, sizeof(*msg), (size_t) upload_size); +} + +static CURLcode smb_send_and_recv(struct connectdata *conn, void **msg) +{ + struct smb_conn *smbc = &conn->proto.smbc; + CURLcode result; + + /* Check if there is data in the transfer buffer */ + if(!smbc->send_size && smbc->upload_size) { + size_t nread = smbc->upload_size > conn->data->set.upload_buffer_size ? + conn->data->set.upload_buffer_size : + smbc->upload_size; + conn->data->req.upload_fromhere = conn->data->state.ulbuf; + result = Curl_fillreadbuffer(conn, nread, &nread); + if(result && result != CURLE_AGAIN) + return result; + if(!nread) + return CURLE_OK; + + smbc->upload_size -= nread; + smbc->send_size = nread; + smbc->sent = 0; + } + + /* Check if there is data to send */ + if(smbc->send_size) { + result = smb_flush(conn); + if(result) + return result; + } + + /* Check if there is still data to be sent */ + if(smbc->send_size || smbc->upload_size) + return CURLE_AGAIN; + + return smb_recv_message(conn, msg); +} + +static CURLcode smb_connection_state(struct connectdata *conn, bool *done) +{ + struct smb_conn *smbc = &conn->proto.smbc; + struct smb_negotiate_response *nrsp; + struct smb_header *h; + CURLcode result; + void *msg = NULL; + + if(smbc->state == SMB_CONNECTING) { +#ifdef USE_SSL + if((conn->handler->flags & PROTOPT_SSL)) { + bool ssl_done = FALSE; + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &ssl_done); + if(result && result != CURLE_AGAIN) + return result; + if(!ssl_done) + return CURLE_OK; + } +#endif + + result = smb_send_negotiate(conn); + if(result) { + connclose(conn, "SMB: failed to send negotiate message"); + return result; + } + + conn_state(conn, SMB_NEGOTIATE); + } + + /* Send the previous message and check for a response */ + result = smb_send_and_recv(conn, &msg); + if(result && result != CURLE_AGAIN) { + connclose(conn, "SMB: failed to communicate"); + return result; + } + + if(!msg) + return CURLE_OK; + + h = msg; + + switch(smbc->state) { + case SMB_NEGOTIATE: + if(h->status || smbc->got < sizeof(*nrsp) + sizeof(smbc->challenge) - 1) { + connclose(conn, "SMB: negotiation failed"); + return CURLE_COULDNT_CONNECT; + } + nrsp = msg; + memcpy(smbc->challenge, nrsp->bytes, sizeof(smbc->challenge)); + smbc->session_key = smb_swap32(nrsp->session_key); + result = smb_send_setup(conn); + if(result) { + connclose(conn, "SMB: failed to send setup message"); + return result; + } + conn_state(conn, SMB_SETUP); + break; + + case SMB_SETUP: + if(h->status) { + connclose(conn, "SMB: authentication failed"); + return CURLE_LOGIN_DENIED; + } + smbc->uid = smb_swap16(h->uid); + conn_state(conn, SMB_CONNECTED); + *done = true; + break; + + default: + smb_pop_message(conn); + return CURLE_OK; /* ignore */ + } + + smb_pop_message(conn); + + return CURLE_OK; +} + +/* + * Convert a timestamp from the Windows world (100 nsec units from 1 Jan 1601) + * to Posix time. Cap the output to fit within a time_t. + */ +static void get_posix_time(time_t *out, curl_off_t timestamp) +{ + timestamp -= 116444736000000000; + timestamp /= 10000000; +#if SIZEOF_TIME_T < SIZEOF_CURL_OFF_T + if(timestamp > TIME_T_MAX) + *out = TIME_T_MAX; + else if(timestamp < TIME_T_MIN) + *out = TIME_T_MIN; + else +#endif + *out = (time_t) timestamp; +} + +static CURLcode smb_request_state(struct connectdata *conn, bool *done) +{ + struct smb_request *req = conn->data->req.protop; + struct smb_header *h; + struct smb_conn *smbc = &conn->proto.smbc; + enum smb_req_state next_state = SMB_DONE; + unsigned short len; + unsigned short off; + CURLcode result; + void *msg = NULL; + const struct smb_nt_create_response *smb_m; + + /* Start the request */ + if(req->state == SMB_REQUESTING) { + result = smb_send_tree_connect(conn); + if(result) { + connclose(conn, "SMB: failed to send tree connect message"); + return result; + } + + request_state(conn, SMB_TREE_CONNECT); + } + + /* Send the previous message and check for a response */ + result = smb_send_and_recv(conn, &msg); + if(result && result != CURLE_AGAIN) { + connclose(conn, "SMB: failed to communicate"); + return result; + } + + if(!msg) + return CURLE_OK; + + h = msg; + + switch(req->state) { + case SMB_TREE_CONNECT: + if(h->status) { + req->result = CURLE_REMOTE_FILE_NOT_FOUND; + if(h->status == smb_swap32(SMB_ERR_NOACCESS)) + req->result = CURLE_REMOTE_ACCESS_DENIED; + break; + } + req->tid = smb_swap16(h->tid); + next_state = SMB_OPEN; + break; + + case SMB_OPEN: + if(h->status || smbc->got < sizeof(struct smb_nt_create_response)) { + req->result = CURLE_REMOTE_FILE_NOT_FOUND; + next_state = SMB_TREE_DISCONNECT; + break; + } + smb_m = (const struct smb_nt_create_response*) msg; + req->fid = smb_swap16(smb_m->fid); + conn->data->req.offset = 0; + if(conn->data->set.upload) { + conn->data->req.size = conn->data->state.infilesize; + Curl_pgrsSetUploadSize(conn->data, conn->data->req.size); + next_state = SMB_UPLOAD; + } + else { + smb_m = (const struct smb_nt_create_response*) msg; + conn->data->req.size = smb_swap64(smb_m->end_of_file); + if(conn->data->req.size < 0) { + req->result = CURLE_WEIRD_SERVER_REPLY; + next_state = SMB_CLOSE; + } + else { + Curl_pgrsSetDownloadSize(conn->data, conn->data->req.size); + if(conn->data->set.get_filetime) + get_posix_time(&conn->data->info.filetime, smb_m->last_change_time); + next_state = SMB_DOWNLOAD; + } + } + break; + + case SMB_DOWNLOAD: + if(h->status || smbc->got < sizeof(struct smb_header) + 14) { + req->result = CURLE_RECV_ERROR; + next_state = SMB_CLOSE; + break; + } + len = Curl_read16_le(((const unsigned char *) msg) + + sizeof(struct smb_header) + 11); + off = Curl_read16_le(((const unsigned char *) msg) + + sizeof(struct smb_header) + 13); + if(len > 0) { + if(off + sizeof(unsigned int) + len > smbc->got) { + failf(conn->data, "Invalid input packet"); + result = CURLE_RECV_ERROR; + } + else + result = Curl_client_write(conn, CLIENTWRITE_BODY, + (char *)msg + off + sizeof(unsigned int), + len); + if(result) { + req->result = result; + next_state = SMB_CLOSE; + break; + } + } + conn->data->req.bytecount += len; + conn->data->req.offset += len; + Curl_pgrsSetDownloadCounter(conn->data, conn->data->req.bytecount); + next_state = (len < MAX_PAYLOAD_SIZE) ? SMB_CLOSE : SMB_DOWNLOAD; + break; + + case SMB_UPLOAD: + if(h->status || smbc->got < sizeof(struct smb_header) + 6) { + req->result = CURLE_UPLOAD_FAILED; + next_state = SMB_CLOSE; + break; + } + len = Curl_read16_le(((const unsigned char *) msg) + + sizeof(struct smb_header) + 5); + conn->data->req.bytecount += len; + conn->data->req.offset += len; + Curl_pgrsSetUploadCounter(conn->data, conn->data->req.bytecount); + if(conn->data->req.bytecount >= conn->data->req.size) + next_state = SMB_CLOSE; + else + next_state = SMB_UPLOAD; + break; + + case SMB_CLOSE: + /* We don't care if the close failed, proceed to tree disconnect anyway */ + next_state = SMB_TREE_DISCONNECT; + break; + + case SMB_TREE_DISCONNECT: + next_state = SMB_DONE; + break; + + default: + smb_pop_message(conn); + return CURLE_OK; /* ignore */ + } + + smb_pop_message(conn); + + switch(next_state) { + case SMB_OPEN: + result = smb_send_open(conn); + break; + + case SMB_DOWNLOAD: + result = smb_send_read(conn); + break; + + case SMB_UPLOAD: + result = smb_send_write(conn); + break; + + case SMB_CLOSE: + result = smb_send_close(conn); + break; + + case SMB_TREE_DISCONNECT: + result = smb_send_tree_disconnect(conn); + break; + + case SMB_DONE: + result = req->result; + *done = true; + break; + + default: + break; + } + + if(result) { + connclose(conn, "SMB: failed to send message"); + return result; + } + + request_state(conn, next_state); + + return CURLE_OK; +} + +static CURLcode smb_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + (void) premature; + Curl_safefree(conn->data->req.protop); + return status; +} + +static CURLcode smb_disconnect(struct connectdata *conn, bool dead) +{ + struct smb_conn *smbc = &conn->proto.smbc; + (void) dead; + Curl_safefree(smbc->share); + Curl_safefree(smbc->domain); + Curl_safefree(smbc->recv_buf); + return CURLE_OK; +} + +static int smb_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks) +{ + if(!numsocks) + return GETSOCK_BLANK; + + socks[0] = conn->sock[FIRSTSOCKET]; + return GETSOCK_READSOCK(0) | GETSOCK_WRITESOCK(0); +} + +static CURLcode smb_do(struct connectdata *conn, bool *done) +{ + struct smb_conn *smbc = &conn->proto.smbc; + + *done = FALSE; + if(smbc->share) { + return CURLE_OK; + } + return CURLE_URL_MALFORMAT; +} + +static CURLcode smb_parse_url_path(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct smb_request *req = data->req.protop; + struct smb_conn *smbc = &conn->proto.smbc; + char *path; + char *slash; + + /* URL decode the path */ + result = Curl_urldecode(data, data->state.up.path, 0, &path, NULL, TRUE); + if(result) + return result; + + /* Parse the path for the share */ + smbc->share = strdup((*path == '/' || *path == '\\') ? path + 1 : path); + free(path); + if(!smbc->share) + return CURLE_OUT_OF_MEMORY; + + slash = strchr(smbc->share, '/'); + if(!slash) + slash = strchr(smbc->share, '\\'); + + /* The share must be present */ + if(!slash) { + Curl_safefree(smbc->share); + return CURLE_URL_MALFORMAT; + } + + /* Parse the path for the file path converting any forward slashes into + backslashes */ + *slash++ = 0; + req->path = slash; + + for(; *slash; slash++) { + if(*slash == '/') + *slash = '\\'; + } + return CURLE_OK; +} + +#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */ + +#endif /* CURL_DISABLE_SMB && USE_NTLM && CURL_SIZEOF_CURL_OFF_T > 4 */ diff --git a/dependencies/cmcurl/lib/smb.h b/dependencies/cmcurl/lib/smb.h new file mode 100644 index 0000000..9ce6b56 --- /dev/null +++ b/dependencies/cmcurl/lib/smb.h @@ -0,0 +1,259 @@ +#ifndef HEADER_CURL_SMB_H +#define HEADER_CURL_SMB_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2014, Bill Nagel , Exacq Technologies + * Copyright (C) 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +enum smb_conn_state { + SMB_NOT_CONNECTED = 0, + SMB_CONNECTING, + SMB_NEGOTIATE, + SMB_SETUP, + SMB_CONNECTED +}; + +struct smb_conn { + enum smb_conn_state state; + char *user; + char *domain; + char *share; + unsigned char challenge[8]; + unsigned int session_key; + unsigned short uid; + char *recv_buf; + size_t upload_size; + size_t send_size; + size_t sent; + size_t got; +}; + +/* + * Definitions for SMB protocol data structures + */ +#ifdef BUILDING_CURL_SMB_C + +#if defined(_MSC_VER) || defined(__ILEC400__) +# define PACK +# pragma pack(push) +# pragma pack(1) +#elif defined(__GNUC__) +# define PACK __attribute__((packed)) +#else +# define PACK +#endif + +#define SMB_COM_CLOSE 0x04 +#define SMB_COM_READ_ANDX 0x2e +#define SMB_COM_WRITE_ANDX 0x2f +#define SMB_COM_TREE_DISCONNECT 0x71 +#define SMB_COM_NEGOTIATE 0x72 +#define SMB_COM_SETUP_ANDX 0x73 +#define SMB_COM_TREE_CONNECT_ANDX 0x75 +#define SMB_COM_NT_CREATE_ANDX 0xa2 +#define SMB_COM_NO_ANDX_COMMAND 0xff + +#define SMB_WC_CLOSE 0x03 +#define SMB_WC_READ_ANDX 0x0c +#define SMB_WC_WRITE_ANDX 0x0e +#define SMB_WC_SETUP_ANDX 0x0d +#define SMB_WC_TREE_CONNECT_ANDX 0x04 +#define SMB_WC_NT_CREATE_ANDX 0x18 + +#define SMB_FLAGS_CANONICAL_PATHNAMES 0x10 +#define SMB_FLAGS_CASELESS_PATHNAMES 0x08 +#define SMB_FLAGS2_UNICODE_STRINGS 0x8000 +#define SMB_FLAGS2_IS_LONG_NAME 0x0040 +#define SMB_FLAGS2_KNOWS_LONG_NAME 0x0001 + +#define SMB_CAP_LARGE_FILES 0x08 +#define SMB_GENERIC_WRITE 0x40000000 +#define SMB_GENERIC_READ 0x80000000 +#define SMB_FILE_SHARE_ALL 0x07 +#define SMB_FILE_OPEN 0x01 +#define SMB_FILE_OVERWRITE_IF 0x05 + +#define SMB_ERR_NOACCESS 0x00050001 + +struct smb_header { + unsigned char nbt_type; + unsigned char nbt_flags; + unsigned short nbt_length; + unsigned char magic[4]; + unsigned char command; + unsigned int status; + unsigned char flags; + unsigned short flags2; + unsigned short pid_high; + unsigned char signature[8]; + unsigned short pad; + unsigned short tid; + unsigned short pid; + unsigned short uid; + unsigned short mid; +} PACK; + +struct smb_negotiate_response { + struct smb_header h; + unsigned char word_count; + unsigned short dialect_index; + unsigned char security_mode; + unsigned short max_mpx_count; + unsigned short max_number_vcs; + unsigned int max_buffer_size; + unsigned int max_raw_size; + unsigned int session_key; + unsigned int capabilities; + unsigned int system_time_low; + unsigned int system_time_high; + unsigned short server_time_zone; + unsigned char encryption_key_length; + unsigned short byte_count; + char bytes[1]; +} PACK; + +struct andx { + unsigned char command; + unsigned char pad; + unsigned short offset; +} PACK; + +struct smb_setup { + unsigned char word_count; + struct andx andx; + unsigned short max_buffer_size; + unsigned short max_mpx_count; + unsigned short vc_number; + unsigned int session_key; + unsigned short lengths[2]; + unsigned int pad; + unsigned int capabilities; + unsigned short byte_count; + char bytes[1024]; +} PACK; + +struct smb_tree_connect { + unsigned char word_count; + struct andx andx; + unsigned short flags; + unsigned short pw_len; + unsigned short byte_count; + char bytes[1024]; +} PACK; + +struct smb_nt_create { + unsigned char word_count; + struct andx andx; + unsigned char pad; + unsigned short name_length; + unsigned int flags; + unsigned int root_fid; + unsigned int access; + curl_off_t allocation_size; + unsigned int ext_file_attributes; + unsigned int share_access; + unsigned int create_disposition; + unsigned int create_options; + unsigned int impersonation_level; + unsigned char security_flags; + unsigned short byte_count; + char bytes[1024]; +} PACK; + +struct smb_nt_create_response { + struct smb_header h; + unsigned char word_count; + struct andx andx; + unsigned char op_lock_level; + unsigned short fid; + unsigned int create_disposition; + + curl_off_t create_time; + curl_off_t last_access_time; + curl_off_t last_write_time; + curl_off_t last_change_time; + unsigned int ext_file_attributes; + curl_off_t allocation_size; + curl_off_t end_of_file; + +} PACK; + +struct smb_read { + unsigned char word_count; + struct andx andx; + unsigned short fid; + unsigned int offset; + unsigned short max_bytes; + unsigned short min_bytes; + unsigned int timeout; + unsigned short remaining; + unsigned int offset_high; + unsigned short byte_count; +} PACK; + +struct smb_write { + struct smb_header h; + unsigned char word_count; + struct andx andx; + unsigned short fid; + unsigned int offset; + unsigned int timeout; + unsigned short write_mode; + unsigned short remaining; + unsigned short pad; + unsigned short data_length; + unsigned short data_offset; + unsigned int offset_high; + unsigned short byte_count; + unsigned char pad2; +} PACK; + +struct smb_close { + unsigned char word_count; + unsigned short fid; + unsigned int last_mtime; + unsigned short byte_count; +} PACK; + +struct smb_tree_disconnect { + unsigned char word_count; + unsigned short byte_count; +} PACK; + +#if defined(_MSC_VER) || defined(__ILEC400__) +# pragma pack(pop) +#endif + +#endif /* BUILDING_CURL_SMB_C */ + +#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \ + (CURL_SIZEOF_CURL_OFF_T > 4) + +#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO) + +extern const struct Curl_handler Curl_handler_smb; +extern const struct Curl_handler Curl_handler_smbs; + +#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */ + +#endif /* CURL_DISABLE_SMB && USE_NTLM && CURL_SIZEOF_CURL_OFF_T > 4 */ + +#endif /* HEADER_CURL_SMB_H */ diff --git a/dependencies/cmcurl/lib/smtp.c b/dependencies/cmcurl/lib/smtp.c new file mode 100644 index 0000000..4a3462b --- /dev/null +++ b/dependencies/cmcurl/lib/smtp.c @@ -0,0 +1,1644 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC1870 SMTP Service Extension for Message Size + * RFC2195 CRAM-MD5 authentication + * RFC2831 DIGEST-MD5 authentication + * RFC3207 SMTP over TLS + * RFC4422 Simple Authentication and Security Layer (SASL) + * RFC4616 PLAIN authentication + * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism + * RFC4954 SMTP Authentication + * RFC5321 SMTP protocol + * RFC6749 OAuth 2.0 Authorization Framework + * RFC8314 Use of TLS for Email Submission and Access + * Draft SMTP URL Interface + * Draft LOGIN SASL Mechanism + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_SMTP + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_UTSNAME_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +#include +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "progress.h" +#include "transfer.h" +#include "escape.h" +#include "http.h" /* for HTTP proxy tunnel stuff */ +#include "mime.h" +#include "socks.h" +#include "smtp.h" +#include "strtoofft.h" +#include "strcase.h" +#include "vtls/vtls.h" +#include "connect.h" +#include "strerror.h" +#include "select.h" +#include "multiif.h" +#include "url.h" +#include "curl_gethostname.h" +#include "curl_sasl.h" +#include "warnless.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* Local API functions */ +static CURLcode smtp_regular_transfer(struct connectdata *conn, bool *done); +static CURLcode smtp_do(struct connectdata *conn, bool *done); +static CURLcode smtp_done(struct connectdata *conn, CURLcode status, + bool premature); +static CURLcode smtp_connect(struct connectdata *conn, bool *done); +static CURLcode smtp_disconnect(struct connectdata *conn, bool dead); +static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done); +static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); +static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done); +static CURLcode smtp_setup_connection(struct connectdata *conn); +static CURLcode smtp_parse_url_options(struct connectdata *conn); +static CURLcode smtp_parse_url_path(struct connectdata *conn); +static CURLcode smtp_parse_custom_request(struct connectdata *conn); +static CURLcode smtp_perform_auth(struct connectdata *conn, const char *mech, + const char *initresp); +static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp); +static void smtp_get_message(char *buffer, char **outptr); + +/* + * SMTP protocol handler. + */ + +const struct Curl_handler Curl_handler_smtp = { + "SMTP", /* scheme */ + smtp_setup_connection, /* setup_connection */ + smtp_do, /* do_it */ + smtp_done, /* done */ + ZERO_NULL, /* do_more */ + smtp_connect, /* connect_it */ + smtp_multi_statemach, /* connecting */ + smtp_doing, /* doing */ + smtp_getsock, /* proto_getsock */ + smtp_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + smtp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_SMTP, /* defport */ + CURLPROTO_SMTP, /* protocol */ + PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */ + PROTOPT_URLOPTIONS +}; + +#ifdef USE_SSL +/* + * SMTPS protocol handler. + */ + +const struct Curl_handler Curl_handler_smtps = { + "SMTPS", /* scheme */ + smtp_setup_connection, /* setup_connection */ + smtp_do, /* do_it */ + smtp_done, /* done */ + ZERO_NULL, /* do_more */ + smtp_connect, /* connect_it */ + smtp_multi_statemach, /* connecting */ + smtp_doing, /* doing */ + smtp_getsock, /* proto_getsock */ + smtp_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + smtp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_SMTPS, /* defport */ + CURLPROTO_SMTPS, /* protocol */ + PROTOPT_CLOSEACTION | PROTOPT_SSL + | PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS /* flags */ +}; +#endif + +/* SASL parameters for the smtp protocol */ +static const struct SASLproto saslsmtp = { + "smtp", /* The service name */ + 334, /* Code received when continuation is expected */ + 235, /* Code to receive upon authentication success */ + 512 - 8, /* Maximum initial response length (no max) */ + smtp_perform_auth, /* Send authentication command */ + smtp_continue_auth, /* Send authentication continuation */ + smtp_get_message /* Get SASL response message */ +}; + +#ifdef USE_SSL +static void smtp_to_smtps(struct connectdata *conn) +{ + /* Change the connection handler */ + conn->handler = &Curl_handler_smtps; + + /* Set the connection's upgraded to TLS flag */ + conn->tls_upgraded = TRUE; +} +#else +#define smtp_to_smtps(x) Curl_nop_stmt +#endif + +/*********************************************************************** + * + * smtp_endofresp() + * + * Checks for an ending SMTP status code at the start of the given string, but + * also detects various capabilities from the EHLO response including the + * supported authentication mechanisms. + */ +static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len, + int *resp) +{ + struct smtp_conn *smtpc = &conn->proto.smtpc; + bool result = FALSE; + + /* Nothing for us */ + if(len < 4 || !ISDIGIT(line[0]) || !ISDIGIT(line[1]) || !ISDIGIT(line[2])) + return FALSE; + + /* Do we have a command response? This should be the response code followed + by a space and optionally some text as per RFC-5321 and as outlined in + Section 4. Examples of RFC-4954 but some e-mail servers ignore this and + only send the response code instead as per Section 4.2. */ + if(line[3] == ' ' || len == 5) { + char tmpline[6]; + + result = TRUE; + memset(tmpline, '\0', sizeof(tmpline)); + memcpy(tmpline, line, (len == 5 ? 5 : 3)); + *resp = curlx_sltosi(strtol(tmpline, NULL, 10)); + + /* Make sure real server never sends internal value */ + if(*resp == 1) + *resp = 0; + } + /* Do we have a multiline (continuation) response? */ + else if(line[3] == '-' && + (smtpc->state == SMTP_EHLO || smtpc->state == SMTP_COMMAND)) { + result = TRUE; + *resp = 1; /* Internal response code */ + } + + return result; +} + +/*********************************************************************** + * + * smtp_get_message() + * + * Gets the authentication message from the response buffer. + */ +static void smtp_get_message(char *buffer, char **outptr) +{ + size_t len = strlen(buffer); + char *message = NULL; + + if(len > 4) { + /* Find the start of the message */ + len -= 4; + for(message = buffer + 4; *message == ' ' || *message == '\t'; + message++, len--) + ; + + /* Find the end of the message */ + for(; len--;) + if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' && + message[len] != '\t') + break; + + /* Terminate the message */ + if(++len) { + message[len] = '\0'; + } + } + else + /* junk input => zero length output */ + message = &buffer[len]; + + *outptr = message; +} + +/*********************************************************************** + * + * state() + * + * This is the ONLY way to change SMTP state! + */ +static void state(struct connectdata *conn, smtpstate newstate) +{ + struct smtp_conn *smtpc = &conn->proto.smtpc; +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* for debug purposes */ + static const char * const names[] = { + "STOP", + "SERVERGREET", + "EHLO", + "HELO", + "STARTTLS", + "UPGRADETLS", + "AUTH", + "COMMAND", + "MAIL", + "RCPT", + "DATA", + "POSTDATA", + "QUIT", + /* LAST */ + }; + + if(smtpc->state != newstate) + infof(conn->data, "SMTP %p state change from %s to %s\n", + (void *)smtpc, names[smtpc->state], names[newstate]); +#endif + + smtpc->state = newstate; +} + +/*********************************************************************** + * + * smtp_perform_ehlo() + * + * Sends the EHLO command to not only initialise communication with the ESMTP + * server but to also obtain a list of server side supported capabilities. + */ +static CURLcode smtp_perform_ehlo(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + + smtpc->sasl.authmechs = SASL_AUTH_NONE; /* No known auth. mechanism yet */ + smtpc->sasl.authused = SASL_AUTH_NONE; /* Clear the authentication mechanism + used for esmtp connections */ + smtpc->tls_supported = FALSE; /* Clear the TLS capability */ + smtpc->auth_supported = FALSE; /* Clear the AUTH capability */ + + /* Send the EHLO command */ + result = Curl_pp_sendf(&smtpc->pp, "EHLO %s", smtpc->domain); + + if(!result) + state(conn, SMTP_EHLO); + + return result; +} + +/*********************************************************************** + * + * smtp_perform_helo() + * + * Sends the HELO command to initialise communication with the SMTP server. + */ +static CURLcode smtp_perform_helo(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + + smtpc->sasl.authused = SASL_AUTH_NONE; /* No authentication mechanism used + in smtp connections */ + + /* Send the HELO command */ + result = Curl_pp_sendf(&smtpc->pp, "HELO %s", smtpc->domain); + + if(!result) + state(conn, SMTP_HELO); + + return result; +} + +/*********************************************************************** + * + * smtp_perform_starttls() + * + * Sends the STLS command to start the upgrade to TLS. + */ +static CURLcode smtp_perform_starttls(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + /* Send the STARTTLS command */ + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "STARTTLS"); + + if(!result) + state(conn, SMTP_STARTTLS); + + return result; +} + +/*********************************************************************** + * + * smtp_perform_upgrade_tls() + * + * Performs the upgrade to TLS. + */ +static CURLcode smtp_perform_upgrade_tls(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + + /* Start the SSL connection */ + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &smtpc->ssldone); + + if(!result) { + if(smtpc->state != SMTP_UPGRADETLS) + state(conn, SMTP_UPGRADETLS); + + if(smtpc->ssldone) { + smtp_to_smtps(conn); + result = smtp_perform_ehlo(conn); + } + } + + return result; +} + +/*********************************************************************** + * + * smtp_perform_auth() + * + * Sends an AUTH command allowing the client to login with the given SASL + * authentication mechanism. + */ +static CURLcode smtp_perform_auth(struct connectdata *conn, + const char *mech, + const char *initresp) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + + if(initresp) { /* AUTH ... */ + /* Send the AUTH command with the initial response */ + result = Curl_pp_sendf(&smtpc->pp, "AUTH %s %s", mech, initresp); + } + else { + /* Send the AUTH command */ + result = Curl_pp_sendf(&smtpc->pp, "AUTH %s", mech); + } + + return result; +} + +/*********************************************************************** + * + * smtp_continue_auth() + * + * Sends SASL continuation data or cancellation. + */ +static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp) +{ + struct smtp_conn *smtpc = &conn->proto.smtpc; + + return Curl_pp_sendf(&smtpc->pp, "%s", resp); +} + +/*********************************************************************** + * + * smtp_perform_authentication() + * + * Initiates the authentication sequence, with the appropriate SASL + * authentication mechanism. + */ +static CURLcode smtp_perform_authentication(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + saslprogress progress; + + /* Check we have enough data to authenticate with, and the + server supports authentiation, and end the connect phase if not */ + if(!smtpc->auth_supported || + !Curl_sasl_can_authenticate(&smtpc->sasl, conn)) { + state(conn, SMTP_STOP); + return result; + } + + /* Calculate the SASL login details */ + result = Curl_sasl_start(&smtpc->sasl, conn, FALSE, &progress); + + if(!result) { + if(progress == SASL_INPROGRESS) + state(conn, SMTP_AUTH); + else { + /* Other mechanisms not supported */ + infof(conn->data, "No known authentication mechanisms supported!\n"); + result = CURLE_LOGIN_DENIED; + } + } + + return result; +} + +/*********************************************************************** + * + * smtp_perform_command() + * + * Sends a SMTP based command. + */ +static CURLcode smtp_perform_command(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct SMTP *smtp = data->req.protop; + + /* Send the command */ + if(smtp->rcpt) + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s %s", + smtp->custom && smtp->custom[0] != '\0' ? + smtp->custom : "VRFY", + smtp->rcpt->data); + else + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", + smtp->custom && smtp->custom[0] != '\0' ? + smtp->custom : "HELP"); + + if(!result) + state(conn, SMTP_COMMAND); + + return result; +} + +/*********************************************************************** + * + * smtp_perform_mail() + * + * Sends an MAIL command to initiate the upload of a message. + */ +static CURLcode smtp_perform_mail(struct connectdata *conn) +{ + char *from = NULL; + char *auth = NULL; + char *size = NULL; + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + /* Calculate the FROM parameter */ + if(!data->set.str[STRING_MAIL_FROM]) + /* Null reverse-path, RFC-5321, sect. 3.6.3 */ + from = strdup("<>"); + else if(data->set.str[STRING_MAIL_FROM][0] == '<') + from = aprintf("%s", data->set.str[STRING_MAIL_FROM]); + else + from = aprintf("<%s>", data->set.str[STRING_MAIL_FROM]); + + if(!from) + return CURLE_OUT_OF_MEMORY; + + /* Calculate the optional AUTH parameter */ + if(data->set.str[STRING_MAIL_AUTH] && conn->proto.smtpc.sasl.authused) { + if(data->set.str[STRING_MAIL_AUTH][0] != '\0') + auth = aprintf("%s", data->set.str[STRING_MAIL_AUTH]); + else + /* Empty AUTH, RFC-2554, sect. 5 */ + auth = strdup("<>"); + + if(!auth) { + free(from); + + return CURLE_OUT_OF_MEMORY; + } + } + + /* Prepare the mime data if some. */ + if(data->set.mimepost.kind != MIMEKIND_NONE) { + /* Use the whole structure as data. */ + data->set.mimepost.flags &= ~MIME_BODY_ONLY; + + /* Add external headers and mime version. */ + curl_mime_headers(&data->set.mimepost, data->set.headers, 0); + result = Curl_mime_prepare_headers(&data->set.mimepost, NULL, + NULL, MIMESTRATEGY_MAIL); + + if(!result) + if(!Curl_checkheaders(conn, "Mime-Version")) + result = Curl_mime_add_header(&data->set.mimepost.curlheaders, + "Mime-Version: 1.0"); + + /* Make sure we will read the entire mime structure. */ + if(!result) + result = Curl_mime_rewind(&data->set.mimepost); + + if(result) { + free(from); + free(auth); + return result; + } + + data->state.infilesize = Curl_mime_size(&data->set.mimepost); + + /* Read from mime structure. */ + data->state.fread_func = (curl_read_callback) Curl_mime_read; + data->state.in = (void *) &data->set.mimepost; + } + + /* Calculate the optional SIZE parameter */ + if(conn->proto.smtpc.size_supported && data->state.infilesize > 0) { + size = aprintf("%" CURL_FORMAT_CURL_OFF_T, data->state.infilesize); + + if(!size) { + free(from); + free(auth); + + return CURLE_OUT_OF_MEMORY; + } + } + + /* Send the MAIL command */ + if(!auth && !size) + result = Curl_pp_sendf(&conn->proto.smtpc.pp, + "MAIL FROM:%s", from); + else if(auth && !size) + result = Curl_pp_sendf(&conn->proto.smtpc.pp, + "MAIL FROM:%s AUTH=%s", from, auth); + else if(auth && size) + result = Curl_pp_sendf(&conn->proto.smtpc.pp, + "MAIL FROM:%s AUTH=%s SIZE=%s", from, auth, size); + else + result = Curl_pp_sendf(&conn->proto.smtpc.pp, + "MAIL FROM:%s SIZE=%s", from, size); + + free(from); + free(auth); + free(size); + + if(!result) + state(conn, SMTP_MAIL); + + return result; +} + +/*********************************************************************** + * + * smtp_perform_rcpt_to() + * + * Sends a RCPT TO command for a given recipient as part of the message upload + * process. + */ +static CURLcode smtp_perform_rcpt_to(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct SMTP *smtp = data->req.protop; + + /* Send the RCPT TO command */ + if(smtp->rcpt->data[0] == '<') + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:%s", + smtp->rcpt->data); + else + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s>", + smtp->rcpt->data); + if(!result) + state(conn, SMTP_RCPT); + + return result; +} + +/*********************************************************************** + * + * smtp_perform_quit() + * + * Performs the quit action prior to sclose() being called. + */ +static CURLcode smtp_perform_quit(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + /* Send the QUIT command */ + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "QUIT"); + + if(!result) + state(conn, SMTP_QUIT); + + return result; +} + +/* For the initial server greeting */ +static CURLcode smtp_state_servergreet_resp(struct connectdata *conn, + int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(smtpcode/100 != 2) { + failf(data, "Got unexpected smtp-server response: %d", smtpcode); + result = CURLE_WEIRD_SERVER_REPLY; + } + else + result = smtp_perform_ehlo(conn); + + return result; +} + +/* For STARTTLS responses */ +static CURLcode smtp_state_starttls_resp(struct connectdata *conn, + int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(smtpcode != 220) { + if(data->set.use_ssl != CURLUSESSL_TRY) { + failf(data, "STARTTLS denied, code %d", smtpcode); + result = CURLE_USE_SSL_FAILED; + } + else + result = smtp_perform_authentication(conn); + } + else + result = smtp_perform_upgrade_tls(conn); + + return result; +} + +/* For EHLO responses */ +static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct smtp_conn *smtpc = &conn->proto.smtpc; + const char *line = data->state.buffer; + size_t len = strlen(line); + + (void)instate; /* no use for this yet */ + + if(smtpcode/100 != 2 && smtpcode != 1) { + if(data->set.use_ssl <= CURLUSESSL_TRY || conn->ssl[FIRSTSOCKET].use) + result = smtp_perform_helo(conn); + else { + failf(data, "Remote access denied: %d", smtpcode); + result = CURLE_REMOTE_ACCESS_DENIED; + } + } + else { + line += 4; + len -= 4; + + /* Does the server support the STARTTLS capability? */ + if(len >= 8 && !memcmp(line, "STARTTLS", 8)) + smtpc->tls_supported = TRUE; + + /* Does the server support the SIZE capability? */ + else if(len >= 4 && !memcmp(line, "SIZE", 4)) + smtpc->size_supported = TRUE; + + /* Does the server support authentication? */ + else if(len >= 5 && !memcmp(line, "AUTH ", 5)) { + smtpc->auth_supported = TRUE; + + /* Advance past the AUTH keyword */ + line += 5; + len -= 5; + + /* Loop through the data line */ + for(;;) { + size_t llen; + size_t wordlen; + unsigned int mechbit; + + while(len && + (*line == ' ' || *line == '\t' || + *line == '\r' || *line == '\n')) { + + line++; + len--; + } + + if(!len) + break; + + /* Extract the word */ + for(wordlen = 0; wordlen < len && line[wordlen] != ' ' && + line[wordlen] != '\t' && line[wordlen] != '\r' && + line[wordlen] != '\n';) + wordlen++; + + /* Test the word for a matching authentication mechanism */ + mechbit = Curl_sasl_decode_mech(line, wordlen, &llen); + if(mechbit && llen == wordlen) + smtpc->sasl.authmechs |= mechbit; + + line += wordlen; + len -= wordlen; + } + } + + if(smtpcode != 1) { + if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) { + /* We don't have a SSL/TLS connection yet, but SSL is requested */ + if(smtpc->tls_supported) + /* Switch to TLS connection now */ + result = smtp_perform_starttls(conn); + else if(data->set.use_ssl == CURLUSESSL_TRY) + /* Fallback and carry on with authentication */ + result = smtp_perform_authentication(conn); + else { + failf(data, "STARTTLS not supported."); + result = CURLE_USE_SSL_FAILED; + } + } + else + result = smtp_perform_authentication(conn); + } + } + + return result; +} + +/* For HELO responses */ +static CURLcode smtp_state_helo_resp(struct connectdata *conn, int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(smtpcode/100 != 2) { + failf(data, "Remote access denied: %d", smtpcode); + result = CURLE_REMOTE_ACCESS_DENIED; + } + else + /* End of connect phase */ + state(conn, SMTP_STOP); + + return result; +} + +/* For SASL authentication responses */ +static CURLcode smtp_state_auth_resp(struct connectdata *conn, + int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct smtp_conn *smtpc = &conn->proto.smtpc; + saslprogress progress; + + (void)instate; /* no use for this yet */ + + result = Curl_sasl_continue(&smtpc->sasl, conn, smtpcode, &progress); + if(!result) + switch(progress) { + case SASL_DONE: + state(conn, SMTP_STOP); /* Authenticated */ + break; + case SASL_IDLE: /* No mechanism left after cancellation */ + failf(data, "Authentication cancelled"); + result = CURLE_LOGIN_DENIED; + break; + default: + break; + } + + return result; +} + +/* For command responses */ +static CURLcode smtp_state_command_resp(struct connectdata *conn, int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct SMTP *smtp = data->req.protop; + char *line = data->state.buffer; + size_t len = strlen(line); + + (void)instate; /* no use for this yet */ + + if((smtp->rcpt && smtpcode/100 != 2 && smtpcode != 553 && smtpcode != 1) || + (!smtp->rcpt && smtpcode/100 != 2 && smtpcode != 1)) { + failf(data, "Command failed: %d", smtpcode); + result = CURLE_RECV_ERROR; + } + else { + /* Temporarily add the LF character back and send as body to the client */ + if(!data->set.opt_no_body) { + line[len] = '\n'; + result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1); + line[len] = '\0'; + } + + if(smtpcode != 1) { + if(smtp->rcpt) { + smtp->rcpt = smtp->rcpt->next; + + if(smtp->rcpt) { + /* Send the next command */ + result = smtp_perform_command(conn); + } + else + /* End of DO phase */ + state(conn, SMTP_STOP); + } + else + /* End of DO phase */ + state(conn, SMTP_STOP); + } + } + + return result; +} + +/* For MAIL responses */ +static CURLcode smtp_state_mail_resp(struct connectdata *conn, int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(smtpcode/100 != 2) { + failf(data, "MAIL failed: %d", smtpcode); + result = CURLE_SEND_ERROR; + } + else + /* Start the RCPT TO command */ + result = smtp_perform_rcpt_to(conn); + + return result; +} + +/* For RCPT responses */ +static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct SMTP *smtp = data->req.protop; + + (void)instate; /* no use for this yet */ + + if(smtpcode/100 != 2) { + failf(data, "RCPT failed: %d", smtpcode); + result = CURLE_SEND_ERROR; + } + else { + smtp->rcpt = smtp->rcpt->next; + + if(smtp->rcpt) + /* Send the next RCPT TO command */ + result = smtp_perform_rcpt_to(conn); + else { + /* Send the DATA command */ + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "DATA"); + + if(!result) + state(conn, SMTP_DATA); + } + } + + return result; +} + +/* For DATA response */ +static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(smtpcode != 354) { + failf(data, "DATA failed: %d", smtpcode); + result = CURLE_SEND_ERROR; + } + else { + /* Set the progress upload size */ + Curl_pgrsSetUploadSize(data, data->state.infilesize); + + /* SMTP upload */ + Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); + + /* End of DO phase */ + state(conn, SMTP_STOP); + } + + return result; +} + +/* For POSTDATA responses, which are received after the entire DATA + part has been sent to the server */ +static CURLcode smtp_state_postdata_resp(struct connectdata *conn, + int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + + (void)instate; /* no use for this yet */ + + if(smtpcode != 250) + result = CURLE_RECV_ERROR; + + /* End of DONE phase */ + state(conn, SMTP_STOP); + + return result; +} + +static CURLcode smtp_statemach_act(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + struct Curl_easy *data = conn->data; + int smtpcode; + struct smtp_conn *smtpc = &conn->proto.smtpc; + struct pingpong *pp = &smtpc->pp; + size_t nread = 0; + + /* Busy upgrading the connection; right now all I/O is SSL/TLS, not SMTP */ + if(smtpc->state == SMTP_UPGRADETLS) + return smtp_perform_upgrade_tls(conn); + + /* Flush any data that needs to be sent */ + if(pp->sendleft) + return Curl_pp_flushsend(pp); + + do { + /* Read the response from the server */ + result = Curl_pp_readresp(sock, pp, &smtpcode, &nread); + if(result) + return result; + + /* Store the latest response for later retrieval if necessary */ + if(smtpc->state != SMTP_QUIT && smtpcode != 1) + data->info.httpcode = smtpcode; + + if(!smtpcode) + break; + + /* We have now received a full SMTP server response */ + switch(smtpc->state) { + case SMTP_SERVERGREET: + result = smtp_state_servergreet_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_EHLO: + result = smtp_state_ehlo_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_HELO: + result = smtp_state_helo_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_STARTTLS: + result = smtp_state_starttls_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_AUTH: + result = smtp_state_auth_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_COMMAND: + result = smtp_state_command_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_MAIL: + result = smtp_state_mail_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_RCPT: + result = smtp_state_rcpt_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_DATA: + result = smtp_state_data_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_POSTDATA: + result = smtp_state_postdata_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_QUIT: + /* fallthrough, just stop! */ + default: + /* internal error */ + state(conn, SMTP_STOP); + break; + } + } while(!result && smtpc->state != SMTP_STOP && Curl_pp_moredata(pp)); + + return result; +} + +/* Called repeatedly until done from multi.c */ +static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + + if((conn->handler->flags & PROTOPT_SSL) && !smtpc->ssldone) { + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &smtpc->ssldone); + if(result || !smtpc->ssldone) + return result; + } + + result = Curl_pp_statemach(&smtpc->pp, FALSE, FALSE); + *done = (smtpc->state == SMTP_STOP) ? TRUE : FALSE; + + return result; +} + +static CURLcode smtp_block_statemach(struct connectdata *conn, + bool disconnecting) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + + while(smtpc->state != SMTP_STOP && !result) + result = Curl_pp_statemach(&smtpc->pp, TRUE, disconnecting); + + return result; +} + +/* Allocate and initialize the SMTP struct for the current Curl_easy if + required */ +static CURLcode smtp_init(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct SMTP *smtp; + + smtp = data->req.protop = calloc(sizeof(struct SMTP), 1); + if(!smtp) + result = CURLE_OUT_OF_MEMORY; + + return result; +} + +/* For the SMTP "protocol connect" and "doing" phases only */ +static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks) +{ + return Curl_pp_getsock(&conn->proto.smtpc.pp, socks, numsocks); +} + +/*********************************************************************** + * + * smtp_connect() + * + * This function should do everything that is to be considered a part of + * the connection phase. + * + * The variable pointed to by 'done' will be TRUE if the protocol-layer + * connect phase is done when this function returns, or FALSE if not. + */ +static CURLcode smtp_connect(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + struct pingpong *pp = &smtpc->pp; + + *done = FALSE; /* default to not done yet */ + + /* We always support persistent connections in SMTP */ + connkeep(conn, "SMTP default"); + + /* Set the default response time-out */ + pp->response_time = RESP_TIMEOUT; + pp->statemach_act = smtp_statemach_act; + pp->endofresp = smtp_endofresp; + pp->conn = conn; + + /* Initialize the SASL storage */ + Curl_sasl_init(&smtpc->sasl, &saslsmtp); + + /* Initialise the pingpong layer */ + Curl_pp_init(pp); + + /* Parse the URL options */ + result = smtp_parse_url_options(conn); + if(result) + return result; + + /* Parse the URL path */ + result = smtp_parse_url_path(conn); + if(result) + return result; + + /* Start off waiting for the server greeting response */ + state(conn, SMTP_SERVERGREET); + + result = smtp_multi_statemach(conn, done); + + return result; +} + +/*********************************************************************** + * + * smtp_done() + * + * The DONE function. This does what needs to be done after a single DO has + * performed. + * + * Input argument is already checked for validity. + */ +static CURLcode smtp_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct SMTP *smtp = data->req.protop; + struct pingpong *pp = &conn->proto.smtpc.pp; + char *eob; + ssize_t len; + ssize_t bytes_written; + + (void)premature; + + if(!smtp || !pp->conn) + return CURLE_OK; + + /* Cleanup our per-request based variables */ + Curl_safefree(smtp->custom); + + if(status) { + connclose(conn, "SMTP done with bad status"); /* marked for closure */ + result = status; /* use the already set error code */ + } + else if(!data->set.connect_only && data->set.mail_rcpt && + (data->set.upload || data->set.mimepost.kind)) { + /* Calculate the EOB taking into account any terminating CRLF from the + previous line of the email or the CRLF of the DATA command when there + is "no mail data". RFC-5321, sect. 4.1.1.4. + + Note: As some SSL backends, such as OpenSSL, will cause Curl_write() to + fail when using a different pointer following a previous write, that + returned CURLE_AGAIN, we duplicate the EOB now rather than when the + bytes written doesn't equal len. */ + if(smtp->trailing_crlf || !conn->data->state.infilesize) { + eob = strdup(&SMTP_EOB[2]); + len = SMTP_EOB_LEN - 2; + } + else { + eob = strdup(SMTP_EOB); + len = SMTP_EOB_LEN; + } + + if(!eob) + return CURLE_OUT_OF_MEMORY; + + /* Send the end of block data */ + result = Curl_write(conn, conn->writesockfd, eob, len, &bytes_written); + if(result) { + free(eob); + return result; + } + + if(bytes_written != len) { + /* The whole chunk was not sent so keep it around and adjust the + pingpong structure accordingly */ + pp->sendthis = eob; + pp->sendsize = len; + pp->sendleft = len - bytes_written; + } + else { + /* Successfully sent so adjust the response timeout relative to now */ + pp->response = Curl_now(); + + free(eob); + } + + state(conn, SMTP_POSTDATA); + + /* Run the state-machine */ + result = smtp_block_statemach(conn, FALSE); + } + + /* Clear the transfer mode for the next request */ + smtp->transfer = FTPTRANSFER_BODY; + + return result; +} + +/*********************************************************************** + * + * smtp_perform() + * + * This is the actual DO function for SMTP. Transfer a mail, send a command + * or get some data according to the options previously setup. + */ +static CURLcode smtp_perform(struct connectdata *conn, bool *connected, + bool *dophase_done) +{ + /* This is SMTP and no proxy */ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct SMTP *smtp = data->req.protop; + + DEBUGF(infof(conn->data, "DO phase starts\n")); + + if(data->set.opt_no_body) { + /* Requested no body means no transfer */ + smtp->transfer = FTPTRANSFER_INFO; + } + + *dophase_done = FALSE; /* not done yet */ + + /* Store the first recipient (or NULL if not specified) */ + smtp->rcpt = data->set.mail_rcpt; + + /* Initial data character is the first character in line: it is implicitly + preceded by a virtual CRLF. */ + smtp->trailing_crlf = TRUE; + smtp->eob = 2; + + /* Start the first command in the DO phase */ + if((data->set.upload || data->set.mimepost.kind) && data->set.mail_rcpt) + /* MAIL transfer */ + result = smtp_perform_mail(conn); + else + /* SMTP based command (VRFY, EXPN, NOOP, RSET or HELP) */ + result = smtp_perform_command(conn); + + if(result) + return result; + + /* Run the state-machine */ + result = smtp_multi_statemach(conn, dophase_done); + + *connected = conn->bits.tcpconnect[FIRSTSOCKET]; + + if(*dophase_done) + DEBUGF(infof(conn->data, "DO phase is complete\n")); + + return result; +} + +/*********************************************************************** + * + * smtp_do() + * + * This function is registered as 'curl_do' function. It decodes the path + * parts etc as a wrapper to the actual DO function (smtp_perform). + * + * The input argument is already checked for validity. + */ +static CURLcode smtp_do(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + + *done = FALSE; /* default to false */ + + /* Parse the custom request */ + result = smtp_parse_custom_request(conn); + if(result) + return result; + + result = smtp_regular_transfer(conn, done); + + return result; +} + +/*********************************************************************** + * + * smtp_disconnect() + * + * Disconnect from an SMTP server. Cleanup protocol-specific per-connection + * resources. BLOCKING. + */ +static CURLcode smtp_disconnect(struct connectdata *conn, bool dead_connection) +{ + struct smtp_conn *smtpc = &conn->proto.smtpc; + + /* We cannot send quit unconditionally. If this connection is stale or + bad in any way, sending quit and waiting around here will make the + disconnect wait in vain and cause more problems than we need to. */ + + /* The SMTP session may or may not have been allocated/setup at this + point! */ + if(!dead_connection && smtpc->pp.conn && smtpc->pp.conn->bits.protoconnstart) + if(!smtp_perform_quit(conn)) + (void)smtp_block_statemach(conn, TRUE); /* ignore errors on QUIT */ + + /* Disconnect from the server */ + Curl_pp_disconnect(&smtpc->pp); + + /* Cleanup the SASL module */ + Curl_sasl_cleanup(conn, smtpc->sasl.authused); + + /* Cleanup our connection based variables */ + Curl_safefree(smtpc->domain); + + return CURLE_OK; +} + +/* Call this when the DO phase has completed */ +static CURLcode smtp_dophase_done(struct connectdata *conn, bool connected) +{ + struct SMTP *smtp = conn->data->req.protop; + + (void)connected; + + if(smtp->transfer != FTPTRANSFER_BODY) + /* no data to transfer */ + Curl_setup_transfer(conn->data, -1, -1, FALSE, -1); + + return CURLE_OK; +} + +/* Called from multi.c while DOing */ +static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done) +{ + CURLcode result = smtp_multi_statemach(conn, dophase_done); + + if(result) + DEBUGF(infof(conn->data, "DO phase failed\n")); + else if(*dophase_done) { + result = smtp_dophase_done(conn, FALSE /* not connected */); + + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + + return result; +} + +/*********************************************************************** + * + * smtp_regular_transfer() + * + * The input argument is already checked for validity. + * + * Performs all commands done before a regular transfer between a local and a + * remote host. + */ +static CURLcode smtp_regular_transfer(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result = CURLE_OK; + bool connected = FALSE; + struct Curl_easy *data = conn->data; + + /* Make sure size is unknown at this point */ + data->req.size = -1; + + /* Set the progress data */ + Curl_pgrsSetUploadCounter(data, 0); + Curl_pgrsSetDownloadCounter(data, 0); + Curl_pgrsSetUploadSize(data, -1); + Curl_pgrsSetDownloadSize(data, -1); + + /* Carry out the perform */ + result = smtp_perform(conn, &connected, dophase_done); + + /* Perform post DO phase operations if necessary */ + if(!result && *dophase_done) + result = smtp_dophase_done(conn, connected); + + return result; +} + +static CURLcode smtp_setup_connection(struct connectdata *conn) +{ + CURLcode result; + + /* Clear the TLS upgraded flag */ + conn->tls_upgraded = FALSE; + + /* Initialise the SMTP layer */ + result = smtp_init(conn); + if(result) + return result; + + return CURLE_OK; +} + +/*********************************************************************** + * + * smtp_parse_url_options() + * + * Parse the URL login options. + */ +static CURLcode smtp_parse_url_options(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + const char *ptr = conn->options; + + smtpc->sasl.resetprefs = TRUE; + + while(!result && ptr && *ptr) { + const char *key = ptr; + const char *value; + + while(*ptr && *ptr != '=') + ptr++; + + value = ptr + 1; + + while(*ptr && *ptr != ';') + ptr++; + + if(strncasecompare(key, "AUTH=", 5)) + result = Curl_sasl_parse_url_auth_option(&smtpc->sasl, + value, ptr - value); + else + result = CURLE_URL_MALFORMAT; + + if(*ptr == ';') + ptr++; + } + + return result; +} + +/*********************************************************************** + * + * smtp_parse_url_path() + * + * Parse the URL path into separate path components. + */ +static CURLcode smtp_parse_url_path(struct connectdata *conn) +{ + /* The SMTP struct is already initialised in smtp_connect() */ + struct Curl_easy *data = conn->data; + struct smtp_conn *smtpc = &conn->proto.smtpc; + const char *path = &data->state.up.path[1]; /* skip leading path */ + char localhost[HOSTNAME_MAX + 1]; + + /* Calculate the path if necessary */ + if(!*path) { + if(!Curl_gethostname(localhost, sizeof(localhost))) + path = localhost; + else + path = "localhost"; + } + + /* URL decode the path and use it as the domain in our EHLO */ + return Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL, TRUE); +} + +/*********************************************************************** + * + * smtp_parse_custom_request() + * + * Parse the custom request. + */ +static CURLcode smtp_parse_custom_request(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct SMTP *smtp = data->req.protop; + const char *custom = data->set.str[STRING_CUSTOMREQUEST]; + + /* URL decode the custom request */ + if(custom) + result = Curl_urldecode(data, custom, 0, &smtp->custom, NULL, TRUE); + + return result; +} + +CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread) +{ + /* When sending a SMTP payload we must detect CRLF. sequences making sure + they are sent as CRLF.. instead, as a . on the beginning of a line will + be deleted by the server when not part of an EOB terminator and a + genuine CRLF.CRLF which isn't escaped will wrongly be detected as end of + data by the server + */ + ssize_t i; + ssize_t si; + struct Curl_easy *data = conn->data; + struct SMTP *smtp = data->req.protop; + char *scratch = data->state.scratch; + char *newscratch = NULL; + char *oldscratch = NULL; + size_t eob_sent; + + /* Do we need to allocate a scratch buffer? */ + if(!scratch || data->set.crlf) { + oldscratch = scratch; + + scratch = newscratch = malloc(2 * data->set.upload_buffer_size); + if(!newscratch) { + failf(data, "Failed to alloc scratch buffer!"); + + return CURLE_OUT_OF_MEMORY; + } + } + DEBUGASSERT(data->set.upload_buffer_size >= (size_t)nread); + + /* Have we already sent part of the EOB? */ + eob_sent = smtp->eob; + + /* This loop can be improved by some kind of Boyer-Moore style of + approach but that is saved for later... */ + for(i = 0, si = 0; i < nread; i++) { + if(SMTP_EOB[smtp->eob] == data->req.upload_fromhere[i]) { + smtp->eob++; + + /* Is the EOB potentially the terminating CRLF? */ + if(2 == smtp->eob || SMTP_EOB_LEN == smtp->eob) + smtp->trailing_crlf = TRUE; + else + smtp->trailing_crlf = FALSE; + } + else if(smtp->eob) { + /* A previous substring matched so output that first */ + memcpy(&scratch[si], &SMTP_EOB[eob_sent], smtp->eob - eob_sent); + si += smtp->eob - eob_sent; + + /* Then compare the first byte */ + if(SMTP_EOB[0] == data->req.upload_fromhere[i]) + smtp->eob = 1; + else + smtp->eob = 0; + + eob_sent = 0; + + /* Reset the trailing CRLF flag as there was more data */ + smtp->trailing_crlf = FALSE; + } + + /* Do we have a match for CRLF. as per RFC-5321, sect. 4.5.2 */ + if(SMTP_EOB_FIND_LEN == smtp->eob) { + /* Copy the replacement data to the target buffer */ + memcpy(&scratch[si], &SMTP_EOB_REPL[eob_sent], + SMTP_EOB_REPL_LEN - eob_sent); + si += SMTP_EOB_REPL_LEN - eob_sent; + smtp->eob = 0; + eob_sent = 0; + } + else if(!smtp->eob) + scratch[si++] = data->req.upload_fromhere[i]; + } + + if(smtp->eob - eob_sent) { + /* A substring matched before processing ended so output that now */ + memcpy(&scratch[si], &SMTP_EOB[eob_sent], smtp->eob - eob_sent); + si += smtp->eob - eob_sent; + } + + /* Only use the new buffer if we replaced something */ + if(si != nread) { + /* Upload from the new (replaced) buffer instead */ + data->req.upload_fromhere = scratch; + + /* Save the buffer so it can be freed later */ + data->state.scratch = scratch; + + /* Free the old scratch buffer */ + free(oldscratch); + + /* Set the new amount too */ + data->req.upload_present = si; + } + else + free(newscratch); + + return CURLE_OK; +} + +#endif /* CURL_DISABLE_SMTP */ diff --git a/dependencies/cmcurl/lib/smtp.h b/dependencies/cmcurl/lib/smtp.h new file mode 100644 index 0000000..b67340a --- /dev/null +++ b/dependencies/cmcurl/lib/smtp.h @@ -0,0 +1,91 @@ +#ifndef HEADER_CURL_SMTP_H +#define HEADER_CURL_SMTP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2009 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "pingpong.h" +#include "curl_sasl.h" + +/**************************************************************************** + * SMTP unique setup + ***************************************************************************/ +typedef enum { + SMTP_STOP, /* do nothing state, stops the state machine */ + SMTP_SERVERGREET, /* waiting for the initial greeting immediately after + a connect */ + SMTP_EHLO, + SMTP_HELO, + SMTP_STARTTLS, + SMTP_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS + (multi mode only) */ + SMTP_AUTH, + SMTP_COMMAND, /* VRFY, EXPN, NOOP, RSET and HELP */ + SMTP_MAIL, /* MAIL FROM */ + SMTP_RCPT, /* RCPT TO */ + SMTP_DATA, + SMTP_POSTDATA, + SMTP_QUIT, + SMTP_LAST /* never used */ +} smtpstate; + +/* This SMTP struct is used in the Curl_easy. All SMTP data that is + connection-oriented must be in smtp_conn to properly deal with the fact that + perhaps the Curl_easy is changed between the times the connection is + used. */ +struct SMTP { + curl_pp_transfer transfer; + char *custom; /* Custom Request */ + struct curl_slist *rcpt; /* Recipient list */ + size_t eob; /* Number of bytes of the EOB (End Of Body) that + have been received so far */ + bool trailing_crlf; /* Specifies if the tailing CRLF is present */ +}; + +/* smtp_conn is used for struct connection-oriented data in the connectdata + struct */ +struct smtp_conn { + struct pingpong pp; + smtpstate state; /* Always use smtp.c:state() to change state! */ + bool ssldone; /* Is connect() over SSL done? */ + char *domain; /* Client address/name to send in the EHLO */ + struct SASL sasl; /* SASL-related storage */ + bool tls_supported; /* StartTLS capability supported by server */ + bool size_supported; /* If server supports SIZE extension according to + RFC 1870 */ + bool auth_supported; /* AUTH capability supported by server */ +}; + +extern const struct Curl_handler Curl_handler_smtp; +extern const struct Curl_handler Curl_handler_smtps; + +/* this is the 5-bytes End-Of-Body marker for SMTP */ +#define SMTP_EOB "\x0d\x0a\x2e\x0d\x0a" +#define SMTP_EOB_LEN 5 +#define SMTP_EOB_FIND_LEN 3 + +/* if found in data, replace it with this string instead */ +#define SMTP_EOB_REPL "\x0d\x0a\x2e\x2e" +#define SMTP_EOB_REPL_LEN 4 + +CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread); + +#endif /* HEADER_CURL_SMTP_H */ diff --git a/dependencies/cmcurl/lib/sockaddr.h b/dependencies/cmcurl/lib/sockaddr.h new file mode 100644 index 0000000..db14680 --- /dev/null +++ b/dependencies/cmcurl/lib/sockaddr.h @@ -0,0 +1,42 @@ +#ifndef HEADER_CURL_SOCKADDR_H +#define HEADER_CURL_SOCKADDR_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +struct Curl_sockaddr_storage { + union { + struct sockaddr sa; + struct sockaddr_in sa_in; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 sa_in6; +#endif +#ifdef HAVE_STRUCT_SOCKADDR_STORAGE + struct sockaddr_storage sa_stor; +#else + char cbuf[256]; /* this should be big enough to fit a lot */ +#endif + } buffer; +}; + +#endif /* HEADER_CURL_SOCKADDR_H */ diff --git a/dependencies/cmcurl/lib/socks.c b/dependencies/cmcurl/lib/socks.c new file mode 100644 index 0000000..d8fcc3b --- /dev/null +++ b/dependencies/cmcurl/lib/socks.c @@ -0,0 +1,803 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_PROXY) + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "select.h" +#include "connect.h" +#include "timeval.h" +#include "socks.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * Helper read-from-socket functions. Does the same as Curl_read() but it + * blocks until all bytes amount of buffersize will be read. No more, no less. + * + * This is STUPID BLOCKING behaviour which we frown upon, but right now this + * is what we have... + */ +int Curl_blockread_all(struct connectdata *conn, /* connection data */ + curl_socket_t sockfd, /* read from this socket */ + char *buf, /* store read data here */ + ssize_t buffersize, /* max amount to read */ + ssize_t *n) /* amount bytes read */ +{ + ssize_t nread = 0; + ssize_t allread = 0; + int result; + *n = 0; + for(;;) { + timediff_t timeleft = Curl_timeleft(conn->data, NULL, TRUE); + if(timeleft < 0) { + /* we already got the timeout */ + result = CURLE_OPERATION_TIMEDOUT; + break; + } + if(SOCKET_READABLE(sockfd, timeleft) <= 0) { + result = ~CURLE_OK; + break; + } + result = Curl_read_plain(sockfd, buf, buffersize, &nread); + if(CURLE_AGAIN == result) + continue; + if(result) + break; + + if(buffersize == nread) { + allread += nread; + *n = allread; + result = CURLE_OK; + break; + } + if(!nread) { + result = ~CURLE_OK; + break; + } + + buffersize -= nread; + buf += nread; + allread += nread; + } + return result; +} + +/* +* This function logs in to a SOCKS4 proxy and sends the specifics to the final +* destination server. +* +* Reference : +* https://www.openssh.com/txt/socks4.protocol +* +* Note : +* Set protocol4a=true for "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)" +* Nonsupport "Identification Protocol (RFC1413)" +*/ +CURLcode Curl_SOCKS4(const char *proxy_user, + const char *hostname, + int remote_port, + int sockindex, + struct connectdata *conn) +{ + const bool protocol4a = + (conn->socks_proxy.proxytype == CURLPROXY_SOCKS4A) ? TRUE : FALSE; +#define SOCKS4REQLEN 262 + unsigned char socksreq[SOCKS4REQLEN]; /* room for SOCKS4 request incl. user + id */ + CURLcode code; + curl_socket_t sock = conn->sock[sockindex]; + struct Curl_easy *data = conn->data; + + if(Curl_timeleft(data, NULL, TRUE) < 0) { + /* time-out, bail out, go home */ + failf(data, "Connection time-out"); + return CURLE_OPERATION_TIMEDOUT; + } + + if(conn->bits.httpproxy) + infof(conn->data, "SOCKS4%s: connecting to HTTP proxy %s port %d\n", + protocol4a ? "a" : "", hostname, remote_port); + + (void)curlx_nonblock(sock, FALSE); + + infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port); + + /* + * Compose socks4 request + * + * Request format + * + * +----+----+----+----+----+----+----+----+----+----+....+----+ + * | VN | CD | DSTPORT | DSTIP | USERID |NULL| + * +----+----+----+----+----+----+----+----+----+----+....+----+ + * # of bytes: 1 1 2 4 variable 1 + */ + + socksreq[0] = 4; /* version (SOCKS4) */ + socksreq[1] = 1; /* connect */ + socksreq[2] = (unsigned char)((remote_port >> 8) & 0xff); /* PORT MSB */ + socksreq[3] = (unsigned char)(remote_port & 0xff); /* PORT LSB */ + + /* DNS resolve only for SOCKS4, not SOCKS4a */ + if(!protocol4a) { + struct Curl_dns_entry *dns; + Curl_addrinfo *hp = NULL; + int rc; + + rc = Curl_resolv(conn, hostname, remote_port, FALSE, &dns); + + if(rc == CURLRESOLV_ERROR) + return CURLE_COULDNT_RESOLVE_PROXY; + + if(rc == CURLRESOLV_PENDING) + /* ignores the return code, but 'dns' remains NULL on failure */ + (void)Curl_resolver_wait_resolv(conn, &dns); + + /* + * We cannot use 'hostent' as a struct that Curl_resolv() returns. It + * returns a Curl_addrinfo pointer that may not always look the same. + */ + if(dns) + hp = dns->addr; + if(hp) { + char buf[64]; + Curl_printable_address(hp, buf, sizeof(buf)); + + if(hp->ai_family == AF_INET) { + struct sockaddr_in *saddr_in; + + saddr_in = (struct sockaddr_in *)(void *)hp->ai_addr; + socksreq[4] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[0]; + socksreq[5] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[1]; + socksreq[6] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[2]; + socksreq[7] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[3]; + + infof(data, "SOCKS4 connect to IPv4 %s (locally resolved)\n", buf); + } + else { + hp = NULL; /* fail! */ + + failf(data, "SOCKS4 connection to %s not supported\n", buf); + } + + Curl_resolv_unlock(data, dns); /* not used anymore from now on */ + } + if(!hp) { + failf(data, "Failed to resolve \"%s\" for SOCKS4 connect.", + hostname); + return CURLE_COULDNT_RESOLVE_HOST; + } + } + + /* + * This is currently not supporting "Identification Protocol (RFC1413)". + */ + socksreq[8] = 0; /* ensure empty userid is NUL-terminated */ + if(proxy_user) { + size_t plen = strlen(proxy_user); + if(plen >= sizeof(socksreq) - 8) { + failf(data, "Too long SOCKS proxy name, can't use!\n"); + return CURLE_COULDNT_CONNECT; + } + /* copy the proxy name WITH trailing zero */ + memcpy(socksreq + 8, proxy_user, plen + 1); + } + + /* + * Make connection + */ + { + int result; + ssize_t actualread; + ssize_t written; + ssize_t hostnamelen = 0; + ssize_t packetsize = 9 + + strlen((char *)socksreq + 8); /* size including NUL */ + + /* If SOCKS4a, set special invalid IP address 0.0.0.x */ + if(protocol4a) { + socksreq[4] = 0; + socksreq[5] = 0; + socksreq[6] = 0; + socksreq[7] = 1; + /* If still enough room in buffer, also append hostname */ + hostnamelen = (ssize_t)strlen(hostname) + 1; /* length including NUL */ + if(packetsize + hostnamelen <= SOCKS4REQLEN) + strcpy((char *)socksreq + packetsize, hostname); + else + hostnamelen = 0; /* Flag: hostname did not fit in buffer */ + } + + /* Send request */ + code = Curl_write_plain(conn, sock, (char *)socksreq, + packetsize + hostnamelen, + &written); + if(code || (written != packetsize + hostnamelen)) { + failf(data, "Failed to send SOCKS4 connect request."); + return CURLE_COULDNT_CONNECT; + } + if(protocol4a && hostnamelen == 0) { + /* SOCKS4a with very long hostname - send that name separately */ + hostnamelen = (ssize_t)strlen(hostname) + 1; + code = Curl_write_plain(conn, sock, (char *)hostname, hostnamelen, + &written); + if(code || (written != hostnamelen)) { + failf(data, "Failed to send SOCKS4 connect request."); + return CURLE_COULDNT_CONNECT; + } + } + + packetsize = 8; /* receive data size */ + + /* Receive response */ + result = Curl_blockread_all(conn, sock, (char *)socksreq, packetsize, + &actualread); + if(result || (actualread != packetsize)) { + failf(data, "Failed to receive SOCKS4 connect request ack."); + return CURLE_COULDNT_CONNECT; + } + + /* + * Response format + * + * +----+----+----+----+----+----+----+----+ + * | VN | CD | DSTPORT | DSTIP | + * +----+----+----+----+----+----+----+----+ + * # of bytes: 1 1 2 4 + * + * VN is the version of the reply code and should be 0. CD is the result + * code with one of the following values: + * + * 90: request granted + * 91: request rejected or failed + * 92: request rejected because SOCKS server cannot connect to + * identd on the client + * 93: request rejected because the client program and identd + * report different user-ids + */ + + /* wrong version ? */ + if(socksreq[0] != 0) { + failf(data, + "SOCKS4 reply has wrong version, version should be 0."); + return CURLE_COULDNT_CONNECT; + } + + /* Result */ + switch(socksreq[1]) { + case 90: + infof(data, "SOCKS4%s request granted.\n", protocol4a?"a":""); + break; + case 91: + failf(data, + "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" + ", request rejected or failed.", + (unsigned char)socksreq[4], (unsigned char)socksreq[5], + (unsigned char)socksreq[6], (unsigned char)socksreq[7], + (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]), + (unsigned char)socksreq[1]); + return CURLE_COULDNT_CONNECT; + case 92: + failf(data, + "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" + ", request rejected because SOCKS server cannot connect to " + "identd on the client.", + (unsigned char)socksreq[4], (unsigned char)socksreq[5], + (unsigned char)socksreq[6], (unsigned char)socksreq[7], + (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]), + (unsigned char)socksreq[1]); + return CURLE_COULDNT_CONNECT; + case 93: + failf(data, + "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" + ", request rejected because the client program and identd " + "report different user-ids.", + (unsigned char)socksreq[4], (unsigned char)socksreq[5], + (unsigned char)socksreq[6], (unsigned char)socksreq[7], + (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]), + (unsigned char)socksreq[1]); + return CURLE_COULDNT_CONNECT; + default: + failf(data, + "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" + ", Unknown.", + (unsigned char)socksreq[4], (unsigned char)socksreq[5], + (unsigned char)socksreq[6], (unsigned char)socksreq[7], + (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]), + (unsigned char)socksreq[1]); + return CURLE_COULDNT_CONNECT; + } + } + + (void)curlx_nonblock(sock, TRUE); + + return CURLE_OK; /* Proxy was successful! */ +} + +/* + * This function logs in to a SOCKS5 proxy and sends the specifics to the final + * destination server. + */ +CURLcode Curl_SOCKS5(const char *proxy_user, + const char *proxy_password, + const char *hostname, + int remote_port, + int sockindex, + struct connectdata *conn) +{ + /* + According to the RFC1928, section "6. Replies". This is what a SOCK5 + replies: + + +----+-----+-------+------+----------+----------+ + |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | + +----+-----+-------+------+----------+----------+ + | 1 | 1 | X'00' | 1 | Variable | 2 | + +----+-----+-------+------+----------+----------+ + + Where: + + o VER protocol version: X'05' + o REP Reply field: + o X'00' succeeded + */ + + unsigned char socksreq[600]; /* room for large user/pw (255 max each) */ + int idx; + ssize_t actualread; + ssize_t written; + int result; + CURLcode code; + curl_socket_t sock = conn->sock[sockindex]; + struct Curl_easy *data = conn->data; + timediff_t timeout; + bool socks5_resolve_local = + (conn->socks_proxy.proxytype == CURLPROXY_SOCKS5) ? TRUE : FALSE; + const size_t hostname_len = strlen(hostname); + ssize_t len = 0; + const unsigned long auth = data->set.socks5auth; + bool allow_gssapi = FALSE; + + if(conn->bits.httpproxy) + infof(conn->data, "SOCKS5: connecting to HTTP proxy %s port %d\n", + hostname, remote_port); + + /* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */ + if(!socks5_resolve_local && hostname_len > 255) { + infof(conn->data, "SOCKS5: server resolving disabled for hostnames of " + "length > 255 [actual len=%zu]\n", hostname_len); + socks5_resolve_local = TRUE; + } + + /* get timeout */ + timeout = Curl_timeleft(data, NULL, TRUE); + + if(timeout < 0) { + /* time-out, bail out, go home */ + failf(data, "Connection time-out"); + return CURLE_OPERATION_TIMEDOUT; + } + + (void)curlx_nonblock(sock, TRUE); + + /* wait until socket gets connected */ + result = SOCKET_WRITABLE(sock, timeout); + + if(-1 == result) { + failf(conn->data, "SOCKS5: no connection here"); + return CURLE_COULDNT_CONNECT; + } + if(0 == result) { + failf(conn->data, "SOCKS5: connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + if(result & CURL_CSELECT_ERR) { + failf(conn->data, "SOCKS5: error occurred during connection"); + return CURLE_COULDNT_CONNECT; + } + + if(auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI)) + infof(conn->data, + "warning: unsupported value passed to CURLOPT_SOCKS5_AUTH: %lu\n", + auth); + if(!(auth & CURLAUTH_BASIC)) + /* disable username/password auth */ + proxy_user = NULL; +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + if(auth & CURLAUTH_GSSAPI) + allow_gssapi = TRUE; +#endif + + idx = 0; + socksreq[idx++] = 5; /* version */ + idx++; /* reserve for the number of authentication methods */ + socksreq[idx++] = 0; /* no authentication */ + if(allow_gssapi) + socksreq[idx++] = 1; /* GSS-API */ + if(proxy_user) + socksreq[idx++] = 2; /* username/password */ + /* write the number of authentication methods */ + socksreq[1] = (unsigned char) (idx - 2); + + (void)curlx_nonblock(sock, FALSE); + + infof(data, "SOCKS5 communication to %s:%d\n", hostname, remote_port); + + code = Curl_write_plain(conn, sock, (char *)socksreq, (2 + (int)socksreq[1]), + &written); + if(code || (written != (2 + (int)socksreq[1]))) { + failf(data, "Unable to send initial SOCKS5 request."); + return CURLE_COULDNT_CONNECT; + } + + (void)curlx_nonblock(sock, TRUE); + + result = SOCKET_READABLE(sock, timeout); + + if(-1 == result) { + failf(conn->data, "SOCKS5 nothing to read"); + return CURLE_COULDNT_CONNECT; + } + if(0 == result) { + failf(conn->data, "SOCKS5 read timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + if(result & CURL_CSELECT_ERR) { + failf(conn->data, "SOCKS5 read error occurred"); + return CURLE_RECV_ERROR; + } + + (void)curlx_nonblock(sock, FALSE); + + result = Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread); + if(result || (actualread != 2)) { + failf(data, "Unable to receive initial SOCKS5 response."); + return CURLE_COULDNT_CONNECT; + } + + if(socksreq[0] != 5) { + failf(data, "Received invalid version in initial SOCKS5 response."); + return CURLE_COULDNT_CONNECT; + } + if(socksreq[1] == 0) { + /* Nothing to do, no authentication needed */ + ; + } +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + else if(allow_gssapi && (socksreq[1] == 1)) { + code = Curl_SOCKS5_gssapi_negotiate(sockindex, conn); + if(code) { + failf(data, "Unable to negotiate SOCKS5 GSS-API context."); + return CURLE_COULDNT_CONNECT; + } + } +#endif + else if(socksreq[1] == 2) { + /* Needs user name and password */ + size_t proxy_user_len, proxy_password_len; + if(proxy_user && proxy_password) { + proxy_user_len = strlen(proxy_user); + proxy_password_len = strlen(proxy_password); + } + else { + proxy_user_len = 0; + proxy_password_len = 0; + } + + /* username/password request looks like + * +----+------+----------+------+----------+ + * |VER | ULEN | UNAME | PLEN | PASSWD | + * +----+------+----------+------+----------+ + * | 1 | 1 | 1 to 255 | 1 | 1 to 255 | + * +----+------+----------+------+----------+ + */ + len = 0; + socksreq[len++] = 1; /* username/pw subnegotiation version */ + socksreq[len++] = (unsigned char) proxy_user_len; + if(proxy_user && proxy_user_len) { + /* the length must fit in a single byte */ + if(proxy_user_len >= 255) { + failf(data, "Excessive user name length for proxy auth"); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + memcpy(socksreq + len, proxy_user, proxy_user_len); + } + len += proxy_user_len; + socksreq[len++] = (unsigned char) proxy_password_len; + if(proxy_password && proxy_password_len) { + /* the length must fit in a single byte */ + if(proxy_password_len > 255) { + failf(data, "Excessive password length for proxy auth"); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + memcpy(socksreq + len, proxy_password, proxy_password_len); + } + len += proxy_password_len; + + code = Curl_write_plain(conn, sock, (char *)socksreq, len, &written); + if(code || (len != written)) { + failf(data, "Failed to send SOCKS5 sub-negotiation request."); + return CURLE_COULDNT_CONNECT; + } + + result = Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread); + if(result || (actualread != 2)) { + failf(data, "Unable to receive SOCKS5 sub-negotiation response."); + return CURLE_COULDNT_CONNECT; + } + + /* ignore the first (VER) byte */ + if(socksreq[1] != 0) { /* status */ + failf(data, "User was rejected by the SOCKS5 server (%d %d).", + socksreq[0], socksreq[1]); + return CURLE_COULDNT_CONNECT; + } + + /* Everything is good so far, user was authenticated! */ + } + else { + /* error */ + if(!allow_gssapi && (socksreq[1] == 1)) { + failf(data, + "SOCKS5 GSSAPI per-message authentication is not supported."); + return CURLE_COULDNT_CONNECT; + } + if(socksreq[1] == 255) { + if(!proxy_user || !*proxy_user) { + failf(data, + "No authentication method was acceptable. (It is quite likely" + " that the SOCKS5 server wanted a username/password, since none" + " was supplied to the server on this connection.)"); + } + else { + failf(data, "No authentication method was acceptable."); + } + return CURLE_COULDNT_CONNECT; + } + else { + failf(data, + "Undocumented SOCKS5 mode attempted to be used by server."); + return CURLE_COULDNT_CONNECT; + } + } + + /* Authentication is complete, now specify destination to the proxy */ + len = 0; + socksreq[len++] = 5; /* version (SOCKS5) */ + socksreq[len++] = 1; /* connect */ + socksreq[len++] = 0; /* must be zero */ + + if(!socks5_resolve_local) { + socksreq[len++] = 3; /* ATYP: domain name = 3 */ + socksreq[len++] = (char) hostname_len; /* address length */ + memcpy(&socksreq[len], hostname, hostname_len); /* address str w/o NULL */ + len += hostname_len; + } + else { + struct Curl_dns_entry *dns; + Curl_addrinfo *hp = NULL; + int rc = Curl_resolv(conn, hostname, remote_port, FALSE, &dns); + + if(rc == CURLRESOLV_ERROR) + return CURLE_COULDNT_RESOLVE_HOST; + + if(rc == CURLRESOLV_PENDING) { + /* this requires that we're in "wait for resolve" state */ + code = Curl_resolver_wait_resolv(conn, &dns); + if(code) + return code; + } + + /* + * We cannot use 'hostent' as a struct that Curl_resolv() returns. It + * returns a Curl_addrinfo pointer that may not always look the same. + */ + if(dns) + hp = dns->addr; + if(hp) { + char buf[64]; + Curl_printable_address(hp, buf, sizeof(buf)); + + if(hp->ai_family == AF_INET) { + int i; + struct sockaddr_in *saddr_in; + socksreq[len++] = 1; /* ATYP: IPv4 = 1 */ + + saddr_in = (struct sockaddr_in *)(void *)hp->ai_addr; + for(i = 0; i < 4; i++) { + socksreq[len++] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[i]; + } + + infof(data, "SOCKS5 connect to IPv4 %s (locally resolved)\n", buf); + } +#ifdef ENABLE_IPV6 + else if(hp->ai_family == AF_INET6) { + int i; + struct sockaddr_in6 *saddr_in6; + socksreq[len++] = 4; /* ATYP: IPv6 = 4 */ + + saddr_in6 = (struct sockaddr_in6 *)(void *)hp->ai_addr; + for(i = 0; i < 16; i++) { + socksreq[len++] = + ((unsigned char *)&saddr_in6->sin6_addr.s6_addr)[i]; + } + + infof(data, "SOCKS5 connect to IPv6 %s (locally resolved)\n", buf); + } +#endif + else { + hp = NULL; /* fail! */ + + failf(data, "SOCKS5 connection to %s not supported\n", buf); + } + + Curl_resolv_unlock(data, dns); /* not used anymore from now on */ + } + if(!hp) { + failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.", + hostname); + return CURLE_COULDNT_RESOLVE_HOST; + } + } + + socksreq[len++] = (unsigned char)((remote_port >> 8) & 0xff); /* PORT MSB */ + socksreq[len++] = (unsigned char)(remote_port & 0xff); /* PORT LSB */ + +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + if(conn->socks5_gssapi_enctype) { + failf(data, "SOCKS5 GSS-API protection not yet implemented."); + } + else +#endif + code = Curl_write_plain(conn, sock, (char *)socksreq, len, &written); + + if(code || (len != written)) { + failf(data, "Failed to send SOCKS5 connect request."); + return CURLE_COULDNT_CONNECT; + } + + len = 10; /* minimum packet size is 10 */ + +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + if(conn->socks5_gssapi_enctype) { + failf(data, "SOCKS5 GSS-API protection not yet implemented."); + } + else +#endif + result = Curl_blockread_all(conn, sock, (char *)socksreq, + len, &actualread); + + if(result || (len != actualread)) { + failf(data, "Failed to receive SOCKS5 connect request ack."); + return CURLE_COULDNT_CONNECT; + } + + if(socksreq[0] != 5) { /* version */ + failf(data, + "SOCKS5 reply has wrong version, version should be 5."); + return CURLE_COULDNT_CONNECT; + } + + /* Fix: in general, returned BND.ADDR is variable length parameter by RFC + 1928, so the reply packet should be read until the end to avoid errors at + subsequent protocol level. + + +----+-----+-------+------+----------+----------+ + |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | + +----+-----+-------+------+----------+----------+ + | 1 | 1 | X'00' | 1 | Variable | 2 | + +----+-----+-------+------+----------+----------+ + + ATYP: + o IP v4 address: X'01', BND.ADDR = 4 byte + o domain name: X'03', BND.ADDR = [ 1 byte length, string ] + o IP v6 address: X'04', BND.ADDR = 16 byte + */ + + /* Calculate real packet size */ + if(socksreq[3] == 3) { + /* domain name */ + int addrlen = (int) socksreq[4]; + len = 5 + addrlen + 2; + } + else if(socksreq[3] == 4) { + /* IPv6 */ + len = 4 + 16 + 2; + } + + /* At this point we already read first 10 bytes */ +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + if(!conn->socks5_gssapi_enctype) { + /* decrypt_gssapi_blockread already read the whole packet */ +#endif + if(len > 10) { + result = Curl_blockread_all(conn, sock, (char *)&socksreq[10], + len - 10, &actualread); + if(result || ((len - 10) != actualread)) { + failf(data, "Failed to receive SOCKS5 connect request ack."); + return CURLE_COULDNT_CONNECT; + } + } +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + } +#endif + + if(socksreq[1] != 0) { /* Anything besides 0 is an error */ + if(socksreq[3] == 1) { + failf(data, + "Can't complete SOCKS5 connection to %d.%d.%d.%d:%d. (%d)", + (unsigned char)socksreq[4], (unsigned char)socksreq[5], + (unsigned char)socksreq[6], (unsigned char)socksreq[7], + (((unsigned char)socksreq[8] << 8) | + (unsigned char)socksreq[9]), + (unsigned char)socksreq[1]); + } + else if(socksreq[3] == 3) { + unsigned char port_upper = (unsigned char)socksreq[len - 2]; + socksreq[len - 2] = 0; + failf(data, + "Can't complete SOCKS5 connection to %s:%d. (%d)", + (char *)&socksreq[5], + ((port_upper << 8) | + (unsigned char)socksreq[len - 1]), + (unsigned char)socksreq[1]); + socksreq[len - 2] = port_upper; + } + else if(socksreq[3] == 4) { + failf(data, + "Can't complete SOCKS5 connection to %02x%02x:%02x%02x:" + "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%d. (%d)", + (unsigned char)socksreq[4], (unsigned char)socksreq[5], + (unsigned char)socksreq[6], (unsigned char)socksreq[7], + (unsigned char)socksreq[8], (unsigned char)socksreq[9], + (unsigned char)socksreq[10], (unsigned char)socksreq[11], + (unsigned char)socksreq[12], (unsigned char)socksreq[13], + (unsigned char)socksreq[14], (unsigned char)socksreq[15], + (unsigned char)socksreq[16], (unsigned char)socksreq[17], + (unsigned char)socksreq[18], (unsigned char)socksreq[19], + (((unsigned char)socksreq[20] << 8) | + (unsigned char)socksreq[21]), + (unsigned char)socksreq[1]); + } + return CURLE_COULDNT_CONNECT; + } + infof(data, "SOCKS5 request granted.\n"); + + (void)curlx_nonblock(sock, TRUE); + return CURLE_OK; /* Proxy was successful! */ +} + +#endif /* CURL_DISABLE_PROXY */ diff --git a/dependencies/cmcurl/lib/socks.h b/dependencies/cmcurl/lib/socks.h new file mode 100644 index 0000000..daa07c1 --- /dev/null +++ b/dependencies/cmcurl/lib/socks.h @@ -0,0 +1,75 @@ +#ifndef HEADER_CURL_SOCKS_H +#define HEADER_CURL_SOCKS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef CURL_DISABLE_PROXY +#define Curl_SOCKS4(a,b,c,d,e) CURLE_NOT_BUILT_IN +#define Curl_SOCKS5(a,b,c,d,e,f) CURLE_NOT_BUILT_IN +#else +/* + * Helper read-from-socket functions. Does the same as Curl_read() but it + * blocks until all bytes amount of buffersize will be read. No more, no less. + * + * This is STUPID BLOCKING behaviour which we frown upon, but right now this + * is what we have... + */ +int Curl_blockread_all(struct connectdata *conn, + curl_socket_t sockfd, + char *buf, + ssize_t buffersize, + ssize_t *n); + +/* + * This function logs in to a SOCKS4(a) proxy and sends the specifics to the + * final destination server. + */ +CURLcode Curl_SOCKS4(const char *proxy_name, + const char *hostname, + int remote_port, + int sockindex, + struct connectdata *conn); + +/* + * This function logs in to a SOCKS5 proxy and sends the specifics to the + * final destination server. + */ +CURLcode Curl_SOCKS5(const char *proxy_name, + const char *proxy_password, + const char *hostname, + int remote_port, + int sockindex, + struct connectdata *conn); + +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) +/* + * This function handles the SOCKS5 GSS-API negotiation and initialisation + */ +CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, + struct connectdata *conn); +#endif + +#endif /* CURL_DISABLE_PROXY */ + +#endif /* HEADER_CURL_SOCKS_H */ diff --git a/dependencies/cmcurl/lib/socks_gssapi.c b/dependencies/cmcurl/lib/socks_gssapi.c new file mode 100644 index 0000000..65294bb --- /dev/null +++ b/dependencies/cmcurl/lib/socks_gssapi.c @@ -0,0 +1,527 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2009, Markus Moeller, + * Copyright (C) 2012 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(HAVE_GSSAPI) && !defined(CURL_DISABLE_PROXY) + +#include "curl_gssapi.h" +#include "urldata.h" +#include "sendf.h" +#include "connect.h" +#include "timeval.h" +#include "socks.h" +#include "warnless.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +static gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT; + +/* + * Helper GSS-API error functions. + */ +static int check_gss_err(struct Curl_easy *data, + OM_uint32 major_status, + OM_uint32 minor_status, + const char *function) +{ + if(GSS_ERROR(major_status)) { + OM_uint32 maj_stat, min_stat; + OM_uint32 msg_ctx = 0; + gss_buffer_desc status_string; + char buf[1024]; + size_t len; + + len = 0; + msg_ctx = 0; + while(!msg_ctx) { + /* convert major status code (GSS-API error) to text */ + maj_stat = gss_display_status(&min_stat, major_status, + GSS_C_GSS_CODE, + GSS_C_NULL_OID, + &msg_ctx, &status_string); + if(maj_stat == GSS_S_COMPLETE) { + if(sizeof(buf) > len + status_string.length + 1) { + strcpy(buf + len, (char *) status_string.value); + len += status_string.length; + } + gss_release_buffer(&min_stat, &status_string); + break; + } + gss_release_buffer(&min_stat, &status_string); + } + if(sizeof(buf) > len + 3) { + strcpy(buf + len, ".\n"); + len += 2; + } + msg_ctx = 0; + while(!msg_ctx) { + /* convert minor status code (underlying routine error) to text */ + maj_stat = gss_display_status(&min_stat, minor_status, + GSS_C_MECH_CODE, + GSS_C_NULL_OID, + &msg_ctx, &status_string); + if(maj_stat == GSS_S_COMPLETE) { + if(sizeof(buf) > len + status_string.length) + strcpy(buf + len, (char *) status_string.value); + gss_release_buffer(&min_stat, &status_string); + break; + } + gss_release_buffer(&min_stat, &status_string); + } + failf(data, "GSS-API error: %s failed:\n%s", function, buf); + return 1; + } + + return 0; +} + +CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, + struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + curl_socket_t sock = conn->sock[sockindex]; + CURLcode code; + ssize_t actualread; + ssize_t written; + int result; + OM_uint32 gss_major_status, gss_minor_status, gss_status; + OM_uint32 gss_ret_flags; + int gss_conf_state, gss_enc; + gss_buffer_desc service = GSS_C_EMPTY_BUFFER; + gss_buffer_desc gss_send_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc gss_recv_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc gss_w_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc* gss_token = GSS_C_NO_BUFFER; + gss_name_t server = GSS_C_NO_NAME; + gss_name_t gss_client_name = GSS_C_NO_NAME; + unsigned short us_length; + char *user = NULL; + unsigned char socksreq[4]; /* room for GSS-API exchange header only */ + const char *serviceptr = data->set.str[STRING_PROXY_SERVICE_NAME] ? + data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd"; + const size_t serviceptr_length = strlen(serviceptr); + + /* GSS-API request looks like + * +----+------+-----+----------------+ + * |VER | MTYP | LEN | TOKEN | + * +----+------+----------------------+ + * | 1 | 1 | 2 | up to 2^16 - 1 | + * +----+------+-----+----------------+ + */ + + /* prepare service name */ + if(strchr(serviceptr, '/')) { + service.length = serviceptr_length; + service.value = malloc(service.length); + if(!service.value) + return CURLE_OUT_OF_MEMORY; + memcpy(service.value, serviceptr, service.length); + + gss_major_status = gss_import_name(&gss_minor_status, &service, + (gss_OID) GSS_C_NULL_OID, &server); + } + else { + service.value = malloc(serviceptr_length + + strlen(conn->socks_proxy.host.name) + 2); + if(!service.value) + return CURLE_OUT_OF_MEMORY; + service.length = serviceptr_length + + strlen(conn->socks_proxy.host.name) + 1; + msnprintf(service.value, service.length + 1, "%s@%s", + serviceptr, conn->socks_proxy.host.name); + + gss_major_status = gss_import_name(&gss_minor_status, &service, + GSS_C_NT_HOSTBASED_SERVICE, &server); + } + + gss_release_buffer(&gss_status, &service); /* clear allocated memory */ + + if(check_gss_err(data, gss_major_status, + gss_minor_status, "gss_import_name()")) { + failf(data, "Failed to create service name."); + gss_release_name(&gss_status, &server); + return CURLE_COULDNT_CONNECT; + } + + /* As long as we need to keep sending some context info, and there's no */ + /* errors, keep sending it... */ + for(;;) { + gss_major_status = Curl_gss_init_sec_context(data, + &gss_minor_status, + &gss_context, + server, + &Curl_krb5_mech_oid, + NULL, + gss_token, + &gss_send_token, + TRUE, + &gss_ret_flags); + + if(gss_token != GSS_C_NO_BUFFER) + gss_release_buffer(&gss_status, &gss_recv_token); + if(check_gss_err(data, gss_major_status, + gss_minor_status, "gss_init_sec_context")) { + gss_release_name(&gss_status, &server); + gss_release_buffer(&gss_status, &gss_recv_token); + gss_release_buffer(&gss_status, &gss_send_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + failf(data, "Failed to initial GSS-API token."); + return CURLE_COULDNT_CONNECT; + } + + if(gss_send_token.length != 0) { + socksreq[0] = 1; /* GSS-API subnegotiation version */ + socksreq[1] = 1; /* authentication message type */ + us_length = htons((short)gss_send_token.length); + memcpy(socksreq + 2, &us_length, sizeof(short)); + + code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); + if(code || (4 != written)) { + failf(data, "Failed to send GSS-API authentication request."); + gss_release_name(&gss_status, &server); + gss_release_buffer(&gss_status, &gss_recv_token); + gss_release_buffer(&gss_status, &gss_send_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + code = Curl_write_plain(conn, sock, (char *)gss_send_token.value, + gss_send_token.length, &written); + + if(code || ((ssize_t)gss_send_token.length != written)) { + failf(data, "Failed to send GSS-API authentication token."); + gss_release_name(&gss_status, &server); + gss_release_buffer(&gss_status, &gss_recv_token); + gss_release_buffer(&gss_status, &gss_send_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + } + + gss_release_buffer(&gss_status, &gss_send_token); + gss_release_buffer(&gss_status, &gss_recv_token); + if(gss_major_status != GSS_S_CONTINUE_NEEDED) break; + + /* analyse response */ + + /* GSS-API response looks like + * +----+------+-----+----------------+ + * |VER | MTYP | LEN | TOKEN | + * +----+------+----------------------+ + * | 1 | 1 | 2 | up to 2^16 - 1 | + * +----+------+-----+----------------+ + */ + + result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread); + if(result || (actualread != 4)) { + failf(data, "Failed to receive GSS-API authentication response."); + gss_release_name(&gss_status, &server); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + /* ignore the first (VER) byte */ + if(socksreq[1] == 255) { /* status / message type */ + failf(data, "User was rejected by the SOCKS5 server (%d %d).", + socksreq[0], socksreq[1]); + gss_release_name(&gss_status, &server); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + if(socksreq[1] != 1) { /* status / messgae type */ + failf(data, "Invalid GSS-API authentication response type (%d %d).", + socksreq[0], socksreq[1]); + gss_release_name(&gss_status, &server); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + memcpy(&us_length, socksreq + 2, sizeof(short)); + us_length = ntohs(us_length); + + gss_recv_token.length = us_length; + gss_recv_token.value = malloc(us_length); + if(!gss_recv_token.value) { + failf(data, + "Could not allocate memory for GSS-API authentication " + "response token."); + gss_release_name(&gss_status, &server); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_OUT_OF_MEMORY; + } + + result = Curl_blockread_all(conn, sock, (char *)gss_recv_token.value, + gss_recv_token.length, &actualread); + + if(result || (actualread != us_length)) { + failf(data, "Failed to receive GSS-API authentication token."); + gss_release_name(&gss_status, &server); + gss_release_buffer(&gss_status, &gss_recv_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + gss_token = &gss_recv_token; + } + + gss_release_name(&gss_status, &server); + + /* Everything is good so far, user was authenticated! */ + gss_major_status = gss_inquire_context(&gss_minor_status, gss_context, + &gss_client_name, NULL, NULL, NULL, + NULL, NULL, NULL); + if(check_gss_err(data, gss_major_status, + gss_minor_status, "gss_inquire_context")) { + gss_delete_sec_context(&gss_status, &gss_context, NULL); + gss_release_name(&gss_status, &gss_client_name); + failf(data, "Failed to determine user name."); + return CURLE_COULDNT_CONNECT; + } + gss_major_status = gss_display_name(&gss_minor_status, gss_client_name, + &gss_send_token, NULL); + if(check_gss_err(data, gss_major_status, + gss_minor_status, "gss_display_name")) { + gss_delete_sec_context(&gss_status, &gss_context, NULL); + gss_release_name(&gss_status, &gss_client_name); + gss_release_buffer(&gss_status, &gss_send_token); + failf(data, "Failed to determine user name."); + return CURLE_COULDNT_CONNECT; + } + user = malloc(gss_send_token.length + 1); + if(!user) { + gss_delete_sec_context(&gss_status, &gss_context, NULL); + gss_release_name(&gss_status, &gss_client_name); + gss_release_buffer(&gss_status, &gss_send_token); + return CURLE_OUT_OF_MEMORY; + } + + memcpy(user, gss_send_token.value, gss_send_token.length); + user[gss_send_token.length] = '\0'; + gss_release_name(&gss_status, &gss_client_name); + gss_release_buffer(&gss_status, &gss_send_token); + infof(data, "SOCKS5 server authencticated user %s with GSS-API.\n",user); + free(user); + user = NULL; + + /* Do encryption */ + socksreq[0] = 1; /* GSS-API subnegotiation version */ + socksreq[1] = 2; /* encryption message type */ + + gss_enc = 0; /* no data protection */ + /* do confidentiality protection if supported */ + if(gss_ret_flags & GSS_C_CONF_FLAG) + gss_enc = 2; + /* else do integrity protection */ + else if(gss_ret_flags & GSS_C_INTEG_FLAG) + gss_enc = 1; + + infof(data, "SOCKS5 server supports GSS-API %s data protection.\n", + (gss_enc == 0)?"no":((gss_enc==1)?"integrity":"confidentiality")); + /* force for the moment to no data protection */ + gss_enc = 0; + /* + * Sending the encryption type in clear seems wrong. It should be + * protected with gss_seal()/gss_wrap(). See RFC1961 extract below + * The NEC reference implementations on which this is based is + * therefore at fault + * + * +------+------+------+.......................+ + * + ver | mtyp | len | token | + * +------+------+------+.......................+ + * + 0x01 | 0x02 | 0x02 | up to 2^16 - 1 octets | + * +------+------+------+.......................+ + * + * Where: + * + * - "ver" is the protocol version number, here 1 to represent the + * first version of the SOCKS/GSS-API protocol + * + * - "mtyp" is the message type, here 2 to represent a protection + * -level negotiation message + * + * - "len" is the length of the "token" field in octets + * + * - "token" is the GSS-API encapsulated protection level + * + * The token is produced by encapsulating an octet containing the + * required protection level using gss_seal()/gss_wrap() with conf_req + * set to FALSE. The token is verified using gss_unseal()/ + * gss_unwrap(). + * + */ + if(data->set.socks5_gssapi_nec) { + us_length = htons((short)1); + memcpy(socksreq + 2, &us_length, sizeof(short)); + } + else { + gss_send_token.length = 1; + gss_send_token.value = malloc(1); + if(!gss_send_token.value) { + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_OUT_OF_MEMORY; + } + memcpy(gss_send_token.value, &gss_enc, 1); + + gss_major_status = gss_wrap(&gss_minor_status, gss_context, 0, + GSS_C_QOP_DEFAULT, &gss_send_token, + &gss_conf_state, &gss_w_token); + + if(check_gss_err(data, gss_major_status, gss_minor_status, "gss_wrap")) { + gss_release_buffer(&gss_status, &gss_send_token); + gss_release_buffer(&gss_status, &gss_w_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + failf(data, "Failed to wrap GSS-API encryption value into token."); + return CURLE_COULDNT_CONNECT; + } + gss_release_buffer(&gss_status, &gss_send_token); + + us_length = htons((short)gss_w_token.length); + memcpy(socksreq + 2, &us_length, sizeof(short)); + } + + code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); + if(code || (4 != written)) { + failf(data, "Failed to send GSS-API encryption request."); + gss_release_buffer(&gss_status, &gss_w_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + if(data->set.socks5_gssapi_nec) { + memcpy(socksreq, &gss_enc, 1); + code = Curl_write_plain(conn, sock, socksreq, 1, &written); + if(code || ( 1 != written)) { + failf(data, "Failed to send GSS-API encryption type."); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + } + else { + code = Curl_write_plain(conn, sock, (char *)gss_w_token.value, + gss_w_token.length, &written); + if(code || ((ssize_t)gss_w_token.length != written)) { + failf(data, "Failed to send GSS-API encryption type."); + gss_release_buffer(&gss_status, &gss_w_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + gss_release_buffer(&gss_status, &gss_w_token); + } + + result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread); + if(result || (actualread != 4)) { + failf(data, "Failed to receive GSS-API encryption response."); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + /* ignore the first (VER) byte */ + if(socksreq[1] == 255) { /* status / message type */ + failf(data, "User was rejected by the SOCKS5 server (%d %d).", + socksreq[0], socksreq[1]); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + if(socksreq[1] != 2) { /* status / messgae type */ + failf(data, "Invalid GSS-API encryption response type (%d %d).", + socksreq[0], socksreq[1]); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + memcpy(&us_length, socksreq + 2, sizeof(short)); + us_length = ntohs(us_length); + + gss_recv_token.length = us_length; + gss_recv_token.value = malloc(gss_recv_token.length); + if(!gss_recv_token.value) { + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_OUT_OF_MEMORY; + } + result = Curl_blockread_all(conn, sock, (char *)gss_recv_token.value, + gss_recv_token.length, &actualread); + + if(result || (actualread != us_length)) { + failf(data, "Failed to receive GSS-API encryptrion type."); + gss_release_buffer(&gss_status, &gss_recv_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + if(!data->set.socks5_gssapi_nec) { + gss_major_status = gss_unwrap(&gss_minor_status, gss_context, + &gss_recv_token, &gss_w_token, + 0, GSS_C_QOP_DEFAULT); + + if(check_gss_err(data, gss_major_status, gss_minor_status, "gss_unwrap")) { + gss_release_buffer(&gss_status, &gss_recv_token); + gss_release_buffer(&gss_status, &gss_w_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + failf(data, "Failed to unwrap GSS-API encryption value into token."); + return CURLE_COULDNT_CONNECT; + } + gss_release_buffer(&gss_status, &gss_recv_token); + + if(gss_w_token.length != 1) { + failf(data, "Invalid GSS-API encryption response length (%d).", + gss_w_token.length); + gss_release_buffer(&gss_status, &gss_w_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + memcpy(socksreq, gss_w_token.value, gss_w_token.length); + gss_release_buffer(&gss_status, &gss_w_token); + } + else { + if(gss_recv_token.length != 1) { + failf(data, "Invalid GSS-API encryption response length (%d).", + gss_recv_token.length); + gss_release_buffer(&gss_status, &gss_recv_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + memcpy(socksreq, gss_recv_token.value, gss_recv_token.length); + gss_release_buffer(&gss_status, &gss_recv_token); + } + + infof(data, "SOCKS5 access with%s protection granted.\n", + (socksreq[0] == 0)?"out GSS-API data": + ((socksreq[0] == 1)?" GSS-API integrity":" GSS-API confidentiality")); + + conn->socks5_gssapi_enctype = socksreq[0]; + if(socksreq[0] == 0) + gss_delete_sec_context(&gss_status, &gss_context, NULL); + + return CURLE_OK; +} + +#endif /* HAVE_GSSAPI && !CURL_DISABLE_PROXY */ diff --git a/dependencies/cmcurl/lib/socks_sspi.c b/dependencies/cmcurl/lib/socks_sspi.c new file mode 100644 index 0000000..57027ef --- /dev/null +++ b/dependencies/cmcurl/lib/socks_sspi.c @@ -0,0 +1,606 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2019, Daniel Stenberg, , et al. + * Copyright (C) 2009, 2011, Markus Moeller, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_WINDOWS_SSPI) && !defined(CURL_DISABLE_PROXY) + +#include "urldata.h" +#include "sendf.h" +#include "connect.h" +#include "strerror.h" +#include "timeval.h" +#include "socks.h" +#include "curl_sspi.h" +#include "curl_multibyte.h" +#include "warnless.h" +#include "strdup.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Helper sspi error functions. + */ +static int check_sspi_err(struct connectdata *conn, + SECURITY_STATUS status, + const char *function) +{ + if(status != SEC_E_OK && + status != SEC_I_COMPLETE_AND_CONTINUE && + status != SEC_I_COMPLETE_NEEDED && + status != SEC_I_CONTINUE_NEEDED) { + char buffer[STRERROR_LEN]; + failf(conn->data, "SSPI error: %s failed: %s", function, + Curl_sspi_strerror(status, buffer, sizeof(buffer))); + return 1; + } + return 0; +} + +/* This is the SSPI-using version of this function */ +CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, + struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + curl_socket_t sock = conn->sock[sockindex]; + CURLcode code; + ssize_t actualread; + ssize_t written; + int result; + /* Needs GSS-API authentication */ + SECURITY_STATUS status; + unsigned long sspi_ret_flags = 0; + unsigned char gss_enc; + SecBuffer sspi_send_token, sspi_recv_token, sspi_w_token[3]; + SecBufferDesc input_desc, output_desc, wrap_desc; + SecPkgContext_Sizes sspi_sizes; + CredHandle cred_handle; + CtxtHandle sspi_context; + PCtxtHandle context_handle = NULL; + SecPkgCredentials_Names names; + TimeStamp expiry; + char *service_name = NULL; + unsigned short us_length; + unsigned long qop; + unsigned char socksreq[4]; /* room for GSS-API exchange header only */ + const char *service = data->set.str[STRING_PROXY_SERVICE_NAME] ? + data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd"; + const size_t service_length = strlen(service); + + /* GSS-API request looks like + * +----+------+-----+----------------+ + * |VER | MTYP | LEN | TOKEN | + * +----+------+----------------------+ + * | 1 | 1 | 2 | up to 2^16 - 1 | + * +----+------+-----+----------------+ + */ + + /* prepare service name */ + if(strchr(service, '/')) { + service_name = strdup(service); + if(!service_name) + return CURLE_OUT_OF_MEMORY; + } + else { + service_name = malloc(service_length + + strlen(conn->socks_proxy.host.name) + 2); + if(!service_name) + return CURLE_OUT_OF_MEMORY; + msnprintf(service_name, service_length + + strlen(conn->socks_proxy.host.name) + 2, "%s/%s", + service, conn->socks_proxy.host.name); + } + + input_desc.cBuffers = 1; + input_desc.pBuffers = &sspi_recv_token; + input_desc.ulVersion = SECBUFFER_VERSION; + + sspi_recv_token.BufferType = SECBUFFER_TOKEN; + sspi_recv_token.cbBuffer = 0; + sspi_recv_token.pvBuffer = NULL; + + output_desc.cBuffers = 1; + output_desc.pBuffers = &sspi_send_token; + output_desc.ulVersion = SECBUFFER_VERSION; + + sspi_send_token.BufferType = SECBUFFER_TOKEN; + sspi_send_token.cbBuffer = 0; + sspi_send_token.pvBuffer = NULL; + + wrap_desc.cBuffers = 3; + wrap_desc.pBuffers = sspi_w_token; + wrap_desc.ulVersion = SECBUFFER_VERSION; + + cred_handle.dwLower = 0; + cred_handle.dwUpper = 0; + + status = s_pSecFn->AcquireCredentialsHandle(NULL, + (TCHAR *) TEXT("Kerberos"), + SECPKG_CRED_OUTBOUND, + NULL, + NULL, + NULL, + NULL, + &cred_handle, + &expiry); + + if(check_sspi_err(conn, status, "AcquireCredentialsHandle")) { + failf(data, "Failed to acquire credentials."); + free(service_name); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + return CURLE_COULDNT_CONNECT; + } + + /* As long as we need to keep sending some context info, and there's no */ + /* errors, keep sending it... */ + for(;;) { + TCHAR *sname; + + sname = Curl_convert_UTF8_to_tchar(service_name); + if(!sname) + return CURLE_OUT_OF_MEMORY; + + status = s_pSecFn->InitializeSecurityContext(&cred_handle, + context_handle, + sname, + ISC_REQ_MUTUAL_AUTH | + ISC_REQ_ALLOCATE_MEMORY | + ISC_REQ_CONFIDENTIALITY | + ISC_REQ_REPLAY_DETECT, + 0, + SECURITY_NATIVE_DREP, + &input_desc, + 0, + &sspi_context, + &output_desc, + &sspi_ret_flags, + &expiry); + + Curl_unicodefree(sname); + + if(sspi_recv_token.pvBuffer) { + s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); + sspi_recv_token.pvBuffer = NULL; + sspi_recv_token.cbBuffer = 0; + } + + if(check_sspi_err(conn, status, "InitializeSecurityContext")) { + free(service_name); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + s_pSecFn->DeleteSecurityContext(&sspi_context); + if(sspi_recv_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); + failf(data, "Failed to initialise security context."); + return CURLE_COULDNT_CONNECT; + } + + if(sspi_send_token.cbBuffer != 0) { + socksreq[0] = 1; /* GSS-API subnegotiation version */ + socksreq[1] = 1; /* authentication message type */ + us_length = htons((short)sspi_send_token.cbBuffer); + memcpy(socksreq + 2, &us_length, sizeof(short)); + + code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); + if(code || (4 != written)) { + failf(data, "Failed to send SSPI authentication request."); + free(service_name); + if(sspi_send_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); + if(sspi_recv_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer, + sspi_send_token.cbBuffer, &written); + if(code || (sspi_send_token.cbBuffer != (size_t)written)) { + failf(data, "Failed to send SSPI authentication token."); + free(service_name); + if(sspi_send_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); + if(sspi_recv_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + } + + if(sspi_send_token.pvBuffer) { + s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); + sspi_send_token.pvBuffer = NULL; + } + sspi_send_token.cbBuffer = 0; + + if(sspi_recv_token.pvBuffer) { + s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); + sspi_recv_token.pvBuffer = NULL; + } + sspi_recv_token.cbBuffer = 0; + + if(status != SEC_I_CONTINUE_NEEDED) + break; + + /* analyse response */ + + /* GSS-API response looks like + * +----+------+-----+----------------+ + * |VER | MTYP | LEN | TOKEN | + * +----+------+----------------------+ + * | 1 | 1 | 2 | up to 2^16 - 1 | + * +----+------+-----+----------------+ + */ + + result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread); + if(result || (actualread != 4)) { + failf(data, "Failed to receive SSPI authentication response."); + free(service_name); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + /* ignore the first (VER) byte */ + if(socksreq[1] == 255) { /* status / message type */ + failf(data, "User was rejected by the SOCKS5 server (%u %u).", + (unsigned int)socksreq[0], (unsigned int)socksreq[1]); + free(service_name); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + if(socksreq[1] != 1) { /* status / messgae type */ + failf(data, "Invalid SSPI authentication response type (%u %u).", + (unsigned int)socksreq[0], (unsigned int)socksreq[1]); + free(service_name); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + memcpy(&us_length, socksreq + 2, sizeof(short)); + us_length = ntohs(us_length); + + sspi_recv_token.cbBuffer = us_length; + sspi_recv_token.pvBuffer = malloc(us_length); + + if(!sspi_recv_token.pvBuffer) { + free(service_name); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_OUT_OF_MEMORY; + } + result = Curl_blockread_all(conn, sock, (char *)sspi_recv_token.pvBuffer, + sspi_recv_token.cbBuffer, &actualread); + + if(result || (actualread != us_length)) { + failf(data, "Failed to receive SSPI authentication token."); + free(service_name); + if(sspi_recv_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + context_handle = &sspi_context; + } + + free(service_name); + + /* Everything is good so far, user was authenticated! */ + status = s_pSecFn->QueryCredentialsAttributes(&cred_handle, + SECPKG_CRED_ATTR_NAMES, + &names); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + if(check_sspi_err(conn, status, "QueryCredentialAttributes")) { + s_pSecFn->DeleteSecurityContext(&sspi_context); + s_pSecFn->FreeContextBuffer(names.sUserName); + failf(data, "Failed to determine user name."); + return CURLE_COULDNT_CONNECT; + } + infof(data, "SOCKS5 server authencticated user %s with GSS-API.\n", + names.sUserName); + s_pSecFn->FreeContextBuffer(names.sUserName); + + /* Do encryption */ + socksreq[0] = 1; /* GSS-API subnegotiation version */ + socksreq[1] = 2; /* encryption message type */ + + gss_enc = 0; /* no data protection */ + /* do confidentiality protection if supported */ + if(sspi_ret_flags & ISC_REQ_CONFIDENTIALITY) + gss_enc = 2; + /* else do integrity protection */ + else if(sspi_ret_flags & ISC_REQ_INTEGRITY) + gss_enc = 1; + + infof(data, "SOCKS5 server supports GSS-API %s data protection.\n", + (gss_enc == 0)?"no":((gss_enc == 1)?"integrity":"confidentiality") ); + /* force to no data protection, avoid encryption/decryption for now */ + gss_enc = 0; + /* + * Sending the encryption type in clear seems wrong. It should be + * protected with gss_seal()/gss_wrap(). See RFC1961 extract below + * The NEC reference implementations on which this is based is + * therefore at fault + * + * +------+------+------+.......................+ + * + ver | mtyp | len | token | + * +------+------+------+.......................+ + * + 0x01 | 0x02 | 0x02 | up to 2^16 - 1 octets | + * +------+------+------+.......................+ + * + * Where: + * + * - "ver" is the protocol version number, here 1 to represent the + * first version of the SOCKS/GSS-API protocol + * + * - "mtyp" is the message type, here 2 to represent a protection + * -level negotiation message + * + * - "len" is the length of the "token" field in octets + * + * - "token" is the GSS-API encapsulated protection level + * + * The token is produced by encapsulating an octet containing the + * required protection level using gss_seal()/gss_wrap() with conf_req + * set to FALSE. The token is verified using gss_unseal()/ + * gss_unwrap(). + * + */ + + if(data->set.socks5_gssapi_nec) { + us_length = htons((short)1); + memcpy(socksreq + 2, &us_length, sizeof(short)); + } + else { + status = s_pSecFn->QueryContextAttributes(&sspi_context, + SECPKG_ATTR_SIZES, + &sspi_sizes); + if(check_sspi_err(conn, status, "QueryContextAttributes")) { + s_pSecFn->DeleteSecurityContext(&sspi_context); + failf(data, "Failed to query security context attributes."); + return CURLE_COULDNT_CONNECT; + } + + sspi_w_token[0].cbBuffer = sspi_sizes.cbSecurityTrailer; + sspi_w_token[0].BufferType = SECBUFFER_TOKEN; + sspi_w_token[0].pvBuffer = malloc(sspi_sizes.cbSecurityTrailer); + + if(!sspi_w_token[0].pvBuffer) { + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_OUT_OF_MEMORY; + } + + sspi_w_token[1].cbBuffer = 1; + sspi_w_token[1].pvBuffer = malloc(1); + if(!sspi_w_token[1].pvBuffer) { + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_OUT_OF_MEMORY; + } + + memcpy(sspi_w_token[1].pvBuffer, &gss_enc, 1); + sspi_w_token[2].BufferType = SECBUFFER_PADDING; + sspi_w_token[2].cbBuffer = sspi_sizes.cbBlockSize; + sspi_w_token[2].pvBuffer = malloc(sspi_sizes.cbBlockSize); + if(!sspi_w_token[2].pvBuffer) { + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_OUT_OF_MEMORY; + } + status = s_pSecFn->EncryptMessage(&sspi_context, + KERB_WRAP_NO_ENCRYPT, + &wrap_desc, + 0); + if(check_sspi_err(conn, status, "EncryptMessage")) { + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + failf(data, "Failed to query security context attributes."); + return CURLE_COULDNT_CONNECT; + } + sspi_send_token.cbBuffer = sspi_w_token[0].cbBuffer + + sspi_w_token[1].cbBuffer + + sspi_w_token[2].cbBuffer; + sspi_send_token.pvBuffer = malloc(sspi_send_token.cbBuffer); + if(!sspi_send_token.pvBuffer) { + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_OUT_OF_MEMORY; + } + + memcpy(sspi_send_token.pvBuffer, sspi_w_token[0].pvBuffer, + sspi_w_token[0].cbBuffer); + memcpy((PUCHAR) sspi_send_token.pvBuffer +(int)sspi_w_token[0].cbBuffer, + sspi_w_token[1].pvBuffer, sspi_w_token[1].cbBuffer); + memcpy((PUCHAR) sspi_send_token.pvBuffer + + sspi_w_token[0].cbBuffer + + sspi_w_token[1].cbBuffer, + sspi_w_token[2].pvBuffer, sspi_w_token[2].cbBuffer); + + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + sspi_w_token[0].pvBuffer = NULL; + sspi_w_token[0].cbBuffer = 0; + s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); + sspi_w_token[1].pvBuffer = NULL; + sspi_w_token[1].cbBuffer = 0; + s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer); + sspi_w_token[2].pvBuffer = NULL; + sspi_w_token[2].cbBuffer = 0; + + us_length = htons((short)sspi_send_token.cbBuffer); + memcpy(socksreq + 2, &us_length, sizeof(short)); + } + + code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); + if(code || (4 != written)) { + failf(data, "Failed to send SSPI encryption request."); + if(sspi_send_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + if(data->set.socks5_gssapi_nec) { + memcpy(socksreq, &gss_enc, 1); + code = Curl_write_plain(conn, sock, (char *)socksreq, 1, &written); + if(code || (1 != written)) { + failf(data, "Failed to send SSPI encryption type."); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + } + else { + code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer, + sspi_send_token.cbBuffer, &written); + if(code || (sspi_send_token.cbBuffer != (size_t)written)) { + failf(data, "Failed to send SSPI encryption type."); + if(sspi_send_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + if(sspi_send_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); + } + + result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread); + if(result || (actualread != 4)) { + failf(data, "Failed to receive SSPI encryption response."); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + /* ignore the first (VER) byte */ + if(socksreq[1] == 255) { /* status / message type */ + failf(data, "User was rejected by the SOCKS5 server (%u %u).", + (unsigned int)socksreq[0], (unsigned int)socksreq[1]); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + if(socksreq[1] != 2) { /* status / message type */ + failf(data, "Invalid SSPI encryption response type (%u %u).", + (unsigned int)socksreq[0], (unsigned int)socksreq[1]); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + memcpy(&us_length, socksreq + 2, sizeof(short)); + us_length = ntohs(us_length); + + sspi_w_token[0].cbBuffer = us_length; + sspi_w_token[0].pvBuffer = malloc(us_length); + if(!sspi_w_token[0].pvBuffer) { + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_OUT_OF_MEMORY; + } + + result = Curl_blockread_all(conn, sock, (char *)sspi_w_token[0].pvBuffer, + sspi_w_token[0].cbBuffer, &actualread); + + if(result || (actualread != us_length)) { + failf(data, "Failed to receive SSPI encryption type."); + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + + if(!data->set.socks5_gssapi_nec) { + wrap_desc.cBuffers = 2; + sspi_w_token[0].BufferType = SECBUFFER_STREAM; + sspi_w_token[1].BufferType = SECBUFFER_DATA; + sspi_w_token[1].cbBuffer = 0; + sspi_w_token[1].pvBuffer = NULL; + + status = s_pSecFn->DecryptMessage(&sspi_context, + &wrap_desc, + 0, + &qop); + + if(check_sspi_err(conn, status, "DecryptMessage")) { + if(sspi_w_token[0].pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + if(sspi_w_token[1].pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + failf(data, "Failed to query security context attributes."); + return CURLE_COULDNT_CONNECT; + } + + if(sspi_w_token[1].cbBuffer != 1) { + failf(data, "Invalid SSPI encryption response length (%lu).", + (unsigned long)sspi_w_token[1].cbBuffer); + if(sspi_w_token[0].pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + if(sspi_w_token[1].pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + memcpy(socksreq, sspi_w_token[1].pvBuffer, sspi_w_token[1].cbBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); + } + else { + if(sspi_w_token[0].cbBuffer != 1) { + failf(data, "Invalid SSPI encryption response length (%lu).", + (unsigned long)sspi_w_token[0].cbBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + memcpy(socksreq, sspi_w_token[0].pvBuffer, sspi_w_token[0].cbBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + } + + infof(data, "SOCKS5 access with%s protection granted.\n", + (socksreq[0] == 0)?"out GSS-API data": + ((socksreq[0] == 1)?" GSS-API integrity":" GSS-API confidentiality")); + + /* For later use if encryption is required + conn->socks5_gssapi_enctype = socksreq[0]; + if(socksreq[0] != 0) + conn->socks5_sspi_context = sspi_context; + else { + s_pSecFn->DeleteSecurityContext(&sspi_context); + conn->socks5_sspi_context = sspi_context; + } + */ + return CURLE_OK; +} +#endif diff --git a/dependencies/cmcurl/lib/speedcheck.c b/dependencies/cmcurl/lib/speedcheck.c new file mode 100644 index 0000000..3aeea91 --- /dev/null +++ b/dependencies/cmcurl/lib/speedcheck.c @@ -0,0 +1,73 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include +#include "urldata.h" +#include "sendf.h" +#include "multiif.h" +#include "speedcheck.h" + +void Curl_speedinit(struct Curl_easy *data) +{ + memset(&data->state.keeps_speed, 0, sizeof(struct curltime)); +} + +/* + * @unittest: 1606 + */ +CURLcode Curl_speedcheck(struct Curl_easy *data, + struct curltime now) +{ + if((data->progress.current_speed >= 0) && data->set.low_speed_time) { + if(data->progress.current_speed < data->set.low_speed_limit) { + if(!data->state.keeps_speed.tv_sec) + /* under the limit at this very moment */ + data->state.keeps_speed = now; + else { + /* how long has it been under the limit */ + timediff_t howlong = Curl_timediff(now, data->state.keeps_speed); + + if(howlong >= data->set.low_speed_time * 1000) { + /* too long */ + failf(data, + "Operation too slow. " + "Less than %ld bytes/sec transferred the last %ld seconds", + data->set.low_speed_limit, + data->set.low_speed_time); + return CURLE_OPERATION_TIMEDOUT; + } + } + } + else + /* faster right now */ + data->state.keeps_speed.tv_sec = 0; + } + + if(data->set.low_speed_limit) + /* if low speed limit is enabled, set the expire timer to make this + connection's speed get checked again in a second */ + Curl_expire(data, 1000, EXPIRE_SPEEDCHECK); + + return CURLE_OK; +} diff --git a/dependencies/cmcurl/lib/speedcheck.h b/dependencies/cmcurl/lib/speedcheck.h new file mode 100644 index 0000000..5c2dc9a --- /dev/null +++ b/dependencies/cmcurl/lib/speedcheck.h @@ -0,0 +1,33 @@ +#ifndef HEADER_CURL_SPEEDCHECK_H +#define HEADER_CURL_SPEEDCHECK_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "timeval.h" + +void Curl_speedinit(struct Curl_easy *data); +CURLcode Curl_speedcheck(struct Curl_easy *data, + struct curltime now); + +#endif /* HEADER_CURL_SPEEDCHECK_H */ diff --git a/dependencies/cmcurl/lib/splay.c b/dependencies/cmcurl/lib/splay.c new file mode 100644 index 0000000..0f5fcd1 --- /dev/null +++ b/dependencies/cmcurl/lib/splay.c @@ -0,0 +1,276 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1997 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "splay.h" + +/* + * This macro compares two node keys i and j and returns: + * + * negative value: when i is smaller than j + * zero : when i is equal to j + * positive when : when i is larger than j + */ +#define compare(i,j) Curl_splaycomparekeys((i),(j)) + +/* + * Splay using the key i (which may or may not be in the tree.) The starting + * root is t. + */ +struct Curl_tree *Curl_splay(struct curltime i, + struct Curl_tree *t) +{ + struct Curl_tree N, *l, *r, *y; + + if(t == NULL) + return t; + N.smaller = N.larger = NULL; + l = r = &N; + + for(;;) { + long comp = compare(i, t->key); + if(comp < 0) { + if(t->smaller == NULL) + break; + if(compare(i, t->smaller->key) < 0) { + y = t->smaller; /* rotate smaller */ + t->smaller = y->larger; + y->larger = t; + t = y; + if(t->smaller == NULL) + break; + } + r->smaller = t; /* link smaller */ + r = t; + t = t->smaller; + } + else if(comp > 0) { + if(t->larger == NULL) + break; + if(compare(i, t->larger->key) > 0) { + y = t->larger; /* rotate larger */ + t->larger = y->smaller; + y->smaller = t; + t = y; + if(t->larger == NULL) + break; + } + l->larger = t; /* link larger */ + l = t; + t = t->larger; + } + else + break; + } + + l->larger = t->smaller; /* assemble */ + r->smaller = t->larger; + t->smaller = N.larger; + t->larger = N.smaller; + + return t; +} + +/* Insert key i into the tree t. Return a pointer to the resulting tree or + * NULL if something went wrong. + * + * @unittest: 1309 + */ +struct Curl_tree *Curl_splayinsert(struct curltime i, + struct Curl_tree *t, + struct Curl_tree *node) +{ + static const struct curltime KEY_NOTUSED = { + (time_t)-1, (unsigned int)-1 + }; /* will *NEVER* appear */ + + if(node == NULL) + return t; + + if(t != NULL) { + t = Curl_splay(i, t); + if(compare(i, t->key) == 0) { + /* There already exists a node in the tree with the very same key. Build + a doubly-linked circular list of nodes. We add the new 'node' struct + to the end of this list. */ + + node->key = KEY_NOTUSED; /* we set the key in the sub node to NOTUSED + to quickly identify this node as a subnode */ + node->samen = t; + node->samep = t->samep; + t->samep->samen = node; + t->samep = node; + + return t; /* the root node always stays the same */ + } + } + + if(t == NULL) { + node->smaller = node->larger = NULL; + } + else if(compare(i, t->key) < 0) { + node->smaller = t->smaller; + node->larger = t; + t->smaller = NULL; + + } + else { + node->larger = t->larger; + node->smaller = t; + t->larger = NULL; + } + node->key = i; + + /* no identical nodes (yet), we are the only one in the list of nodes */ + node->samen = node; + node->samep = node; + return node; +} + +/* Finds and deletes the best-fit node from the tree. Return a pointer to the + resulting tree. best-fit means the smallest node if it is not larger than + the key */ +struct Curl_tree *Curl_splaygetbest(struct curltime i, + struct Curl_tree *t, + struct Curl_tree **removed) +{ + static struct curltime tv_zero = {0, 0}; + struct Curl_tree *x; + + if(!t) { + *removed = NULL; /* none removed since there was no root */ + return NULL; + } + + /* find smallest */ + t = Curl_splay(tv_zero, t); + if(compare(i, t->key) < 0) { + /* even the smallest is too big */ + *removed = NULL; + return t; + } + + /* FIRST! Check if there is a list with identical keys */ + x = t->samen; + if(x != t) { + /* there is, pick one from the list */ + + /* 'x' is the new root node */ + + x->key = t->key; + x->larger = t->larger; + x->smaller = t->smaller; + x->samep = t->samep; + t->samep->samen = x; + + *removed = t; + return x; /* new root */ + } + + /* we splayed the tree to the smallest element, there is no smaller */ + x = t->larger; + *removed = t; + + return x; +} + + +/* Deletes the very node we point out from the tree if it's there. Stores a + * pointer to the new resulting tree in 'newroot'. + * + * Returns zero on success and non-zero on errors! + * When returning error, it does not touch the 'newroot' pointer. + * + * NOTE: when the last node of the tree is removed, there's no tree left so + * 'newroot' will be made to point to NULL. + * + * @unittest: 1309 + */ +int Curl_splayremovebyaddr(struct Curl_tree *t, + struct Curl_tree *removenode, + struct Curl_tree **newroot) +{ + static const struct curltime KEY_NOTUSED = { + (time_t)-1, (unsigned int)-1 + }; /* will *NEVER* appear */ + struct Curl_tree *x; + + if(!t || !removenode) + return 1; + + if(compare(KEY_NOTUSED, removenode->key) == 0) { + /* Key set to NOTUSED means it is a subnode within a 'same' linked list + and thus we can unlink it easily. */ + if(removenode->samen == removenode) + /* A non-subnode should never be set to KEY_NOTUSED */ + return 3; + + removenode->samep->samen = removenode->samen; + removenode->samen->samep = removenode->samep; + + /* Ensures that double-remove gets caught. */ + removenode->samen = removenode; + + *newroot = t; /* return the same root */ + return 0; + } + + t = Curl_splay(removenode->key, t); + + /* First make sure that we got the same root node as the one we want + to remove, as otherwise we might be trying to remove a node that + isn't actually in the tree. + + We cannot just compare the keys here as a double remove in quick + succession of a node with key != KEY_NOTUSED && same != NULL + could return the same key but a different node. */ + if(t != removenode) + return 2; + + /* Check if there is a list with identical sizes, as then we're trying to + remove the root node of a list of nodes with identical keys. */ + x = t->samen; + if(x != t) { + /* 'x' is the new root node, we just make it use the root node's + smaller/larger links */ + + x->key = t->key; + x->larger = t->larger; + x->smaller = t->smaller; + x->samep = t->samep; + t->samep->samen = x; + } + else { + /* Remove the root node */ + if(t->smaller == NULL) + x = t->larger; + else { + x = Curl_splay(removenode->key, t->smaller); + x->larger = t->larger; + } + } + + *newroot = x; /* store new root pointer */ + + return 0; +} diff --git a/dependencies/cmcurl/lib/splay.h b/dependencies/cmcurl/lib/splay.h new file mode 100644 index 0000000..4612ec2 --- /dev/null +++ b/dependencies/cmcurl/lib/splay.h @@ -0,0 +1,68 @@ +#ifndef HEADER_CURL_SPLAY_H +#define HEADER_CURL_SPLAY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1997 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" +#include "timeval.h" + +struct Curl_tree { + struct Curl_tree *smaller; /* smaller node */ + struct Curl_tree *larger; /* larger node */ + struct Curl_tree *samen; /* points to the next node with identical key */ + struct Curl_tree *samep; /* points to the prev node with identical key */ + struct curltime key; /* this node's "sort" key */ + void *payload; /* data the splay code doesn't care about */ +}; + +struct Curl_tree *Curl_splay(struct curltime i, + struct Curl_tree *t); + +struct Curl_tree *Curl_splayinsert(struct curltime key, + struct Curl_tree *t, + struct Curl_tree *newnode); + +#if 0 +struct Curl_tree *Curl_splayremove(struct curltime key, + struct Curl_tree *t, + struct Curl_tree **removed); +#endif + +struct Curl_tree *Curl_splaygetbest(struct curltime key, + struct Curl_tree *t, + struct Curl_tree **removed); + +int Curl_splayremovebyaddr(struct Curl_tree *t, + struct Curl_tree *removenode, + struct Curl_tree **newroot); + +#define Curl_splaycomparekeys(i,j) ( ((i.tv_sec) < (j.tv_sec)) ? -1 : \ + ( ((i.tv_sec) > (j.tv_sec)) ? 1 : \ + ( ((i.tv_usec) < (j.tv_usec)) ? -1 : \ + ( ((i.tv_usec) > (j.tv_usec)) ? 1 : 0)))) + +#ifdef DEBUGBUILD +void Curl_splayprint(struct Curl_tree * t, int d, char output); +#else +#define Curl_splayprint(x,y,z) Curl_nop_stmt +#endif + +#endif /* HEADER_CURL_SPLAY_H */ diff --git a/dependencies/cmcurl/lib/ssh-libssh.c b/dependencies/cmcurl/lib/ssh-libssh.c new file mode 100644 index 0000000..6cfd6bd --- /dev/null +++ b/dependencies/cmcurl/lib/ssh-libssh.c @@ -0,0 +1,2740 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2017 - 2019 Red Hat, Inc. + * + * Authors: Nikos Mavrogiannopoulos, Tomas Mraz, Stanislav Zidek, + * Robert Kolcun, Andreas Schneider + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_LIBSSH + +#include + +#include +#include + +#ifdef HAVE_FCNTL_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_UTSNAME_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +#include +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "progress.h" +#include "transfer.h" +#include "escape.h" +#include "http.h" /* for HTTP proxy tunnel stuff */ +#include "ssh.h" +#include "url.h" +#include "speedcheck.h" +#include "getinfo.h" +#include "strdup.h" +#include "strcase.h" +#include "vtls/vtls.h" +#include "connect.h" +#include "strerror.h" +#include "inet_ntop.h" +#include "parsedate.h" /* for the week day and month names */ +#include "sockaddr.h" /* required for Curl_sockaddr_storage */ +#include "strtoofft.h" +#include "multiif.h" +#include "select.h" +#include "warnless.h" + +/* for permission and open flags */ +#include +#include +#include +#include + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" +#include "curl_path.h" + +/* A recent macro provided by libssh. Or make our own. */ +#ifndef SSH_STRING_FREE_CHAR +/* !checksrc! disable ASSIGNWITHINCONDITION 1 */ +#define SSH_STRING_FREE_CHAR(x) \ + do { if((x) != NULL) { ssh_string_free_char(x); x = NULL; } } while(0) +#endif + +/* Local functions: */ +static CURLcode myssh_connect(struct connectdata *conn, bool *done); +static CURLcode myssh_multi_statemach(struct connectdata *conn, + bool *done); +static CURLcode myssh_do_it(struct connectdata *conn, bool *done); + +static CURLcode scp_done(struct connectdata *conn, + CURLcode, bool premature); +static CURLcode scp_doing(struct connectdata *conn, bool *dophase_done); +static CURLcode scp_disconnect(struct connectdata *conn, + bool dead_connection); + +static CURLcode sftp_done(struct connectdata *conn, + CURLcode, bool premature); +static CURLcode sftp_doing(struct connectdata *conn, + bool *dophase_done); +static CURLcode sftp_disconnect(struct connectdata *conn, bool dead); +static +CURLcode sftp_perform(struct connectdata *conn, + bool *connected, + bool *dophase_done); + +static void sftp_quote(struct connectdata *conn); +static void sftp_quote_stat(struct connectdata *conn); + +static int myssh_getsock(struct connectdata *conn, curl_socket_t *sock, + int numsocks); + +static int myssh_perform_getsock(const struct connectdata *conn, + curl_socket_t *sock, + int numsocks); + +static CURLcode myssh_setup_connection(struct connectdata *conn); + +/* + * SCP protocol handler. + */ + +const struct Curl_handler Curl_handler_scp = { + "SCP", /* scheme */ + myssh_setup_connection, /* setup_connection */ + myssh_do_it, /* do_it */ + scp_done, /* done */ + ZERO_NULL, /* do_more */ + myssh_connect, /* connect_it */ + myssh_multi_statemach, /* connecting */ + scp_doing, /* doing */ + myssh_getsock, /* proto_getsock */ + myssh_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + myssh_perform_getsock, /* perform_getsock */ + scp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_SSH, /* defport */ + CURLPROTO_SCP, /* protocol */ + PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY /* flags */ +}; + +/* + * SFTP protocol handler. + */ + +const struct Curl_handler Curl_handler_sftp = { + "SFTP", /* scheme */ + myssh_setup_connection, /* setup_connection */ + myssh_do_it, /* do_it */ + sftp_done, /* done */ + ZERO_NULL, /* do_more */ + myssh_connect, /* connect_it */ + myssh_multi_statemach, /* connecting */ + sftp_doing, /* doing */ + myssh_getsock, /* proto_getsock */ + myssh_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + myssh_perform_getsock, /* perform_getsock */ + sftp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_SSH, /* defport */ + CURLPROTO_SFTP, /* protocol */ + PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION + | PROTOPT_NOURLQUERY /* flags */ +}; + +static CURLcode sftp_error_to_CURLE(int err) +{ + switch(err) { + case SSH_FX_OK: + return CURLE_OK; + + case SSH_FX_NO_SUCH_FILE: + case SSH_FX_NO_SUCH_PATH: + return CURLE_REMOTE_FILE_NOT_FOUND; + + case SSH_FX_PERMISSION_DENIED: + case SSH_FX_WRITE_PROTECT: + return CURLE_REMOTE_ACCESS_DENIED; + + case SSH_FX_FILE_ALREADY_EXISTS: + return CURLE_REMOTE_FILE_EXISTS; + + default: + break; + } + + return CURLE_SSH; +} + +#ifndef DEBUGBUILD +#define state(x,y) mystate(x,y) +#else +#define state(x,y) mystate(x,y, __LINE__) +#endif + +/* + * SSH State machine related code + */ +/* This is the ONLY way to change SSH state! */ +static void mystate(struct connectdata *conn, sshstate nowstate +#ifdef DEBUGBUILD + , int lineno +#endif + ) +{ + struct ssh_conn *sshc = &conn->proto.sshc; +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* for debug purposes */ + static const char *const names[] = { + "SSH_STOP", + "SSH_INIT", + "SSH_S_STARTUP", + "SSH_HOSTKEY", + "SSH_AUTHLIST", + "SSH_AUTH_PKEY_INIT", + "SSH_AUTH_PKEY", + "SSH_AUTH_PASS_INIT", + "SSH_AUTH_PASS", + "SSH_AUTH_AGENT_INIT", + "SSH_AUTH_AGENT_LIST", + "SSH_AUTH_AGENT", + "SSH_AUTH_HOST_INIT", + "SSH_AUTH_HOST", + "SSH_AUTH_KEY_INIT", + "SSH_AUTH_KEY", + "SSH_AUTH_GSSAPI", + "SSH_AUTH_DONE", + "SSH_SFTP_INIT", + "SSH_SFTP_REALPATH", + "SSH_SFTP_QUOTE_INIT", + "SSH_SFTP_POSTQUOTE_INIT", + "SSH_SFTP_QUOTE", + "SSH_SFTP_NEXT_QUOTE", + "SSH_SFTP_QUOTE_STAT", + "SSH_SFTP_QUOTE_SETSTAT", + "SSH_SFTP_QUOTE_SYMLINK", + "SSH_SFTP_QUOTE_MKDIR", + "SSH_SFTP_QUOTE_RENAME", + "SSH_SFTP_QUOTE_RMDIR", + "SSH_SFTP_QUOTE_UNLINK", + "SSH_SFTP_QUOTE_STATVFS", + "SSH_SFTP_GETINFO", + "SSH_SFTP_FILETIME", + "SSH_SFTP_TRANS_INIT", + "SSH_SFTP_UPLOAD_INIT", + "SSH_SFTP_CREATE_DIRS_INIT", + "SSH_SFTP_CREATE_DIRS", + "SSH_SFTP_CREATE_DIRS_MKDIR", + "SSH_SFTP_READDIR_INIT", + "SSH_SFTP_READDIR", + "SSH_SFTP_READDIR_LINK", + "SSH_SFTP_READDIR_BOTTOM", + "SSH_SFTP_READDIR_DONE", + "SSH_SFTP_DOWNLOAD_INIT", + "SSH_SFTP_DOWNLOAD_STAT", + "SSH_SFTP_CLOSE", + "SSH_SFTP_SHUTDOWN", + "SSH_SCP_TRANS_INIT", + "SSH_SCP_UPLOAD_INIT", + "SSH_SCP_DOWNLOAD_INIT", + "SSH_SCP_DOWNLOAD", + "SSH_SCP_DONE", + "SSH_SCP_SEND_EOF", + "SSH_SCP_WAIT_EOF", + "SSH_SCP_WAIT_CLOSE", + "SSH_SCP_CHANNEL_FREE", + "SSH_SESSION_DISCONNECT", + "SSH_SESSION_FREE", + "QUIT" + }; + + + if(sshc->state != nowstate) { + infof(conn->data, "SSH %p state change from %s to %s (line %d)\n", + (void *) sshc, names[sshc->state], names[nowstate], + lineno); + } +#endif + + sshc->state = nowstate; +} + +/* Multiple options: + * 1. data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5] is set with an MD5 + * hash (90s style auth, not sure we should have it here) + * 2. data->set.ssh_keyfunc callback is set. Then we do trust on first + * use. We even save on knownhosts if CURLKHSTAT_FINE_ADD_TO_FILE + * is returned by it. + * 3. none of the above. We only accept if it is present on known hosts. + * + * Returns SSH_OK or SSH_ERROR. + */ +static int myssh_is_known(struct connectdata *conn) +{ + int rc; + struct Curl_easy *data = conn->data; + struct ssh_conn *sshc = &conn->proto.sshc; + ssh_key pubkey; + size_t hlen; + unsigned char *hash = NULL; + char *base64 = NULL; + int vstate; + enum curl_khmatch keymatch; + struct curl_khkey foundkey; + curl_sshkeycallback func = + data->set.ssh_keyfunc; + + rc = ssh_get_publickey(sshc->ssh_session, &pubkey); + if(rc != SSH_OK) + return rc; + + if(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) { + rc = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_MD5, + &hash, &hlen); + if(rc != SSH_OK) + goto cleanup; + + if(hlen != strlen(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) || + memcmp(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5], hash, hlen)) { + rc = SSH_ERROR; + goto cleanup; + } + + rc = SSH_OK; + goto cleanup; + } + + if(data->set.ssl.primary.verifyhost != TRUE) { + rc = SSH_OK; + goto cleanup; + } + + vstate = ssh_is_server_known(sshc->ssh_session); + switch(vstate) { + case SSH_SERVER_KNOWN_OK: + keymatch = CURLKHMATCH_OK; + break; + case SSH_SERVER_FILE_NOT_FOUND: + /* fallthrough */ + case SSH_SERVER_NOT_KNOWN: + keymatch = CURLKHMATCH_MISSING; + break; + default: + keymatch = CURLKHMATCH_MISMATCH; + break; + } + + if(func) { /* use callback to determine action */ + rc = ssh_pki_export_pubkey_base64(pubkey, &base64); + if(rc != SSH_OK) + goto cleanup; + + foundkey.key = base64; + foundkey.len = strlen(base64); + + switch(ssh_key_type(pubkey)) { + case SSH_KEYTYPE_RSA: + foundkey.keytype = CURLKHTYPE_RSA; + break; + case SSH_KEYTYPE_RSA1: + foundkey.keytype = CURLKHTYPE_RSA1; + break; + case SSH_KEYTYPE_ECDSA: + foundkey.keytype = CURLKHTYPE_ECDSA; + break; +#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,7,0) + case SSH_KEYTYPE_ED25519: + foundkey.keytype = CURLKHTYPE_ED25519; + break; +#endif + case SSH_KEYTYPE_DSS: + foundkey.keytype = CURLKHTYPE_DSS; + break; + default: + rc = SSH_ERROR; + goto cleanup; + } + + /* we don't have anything equivalent to knownkey. Always NULL */ + Curl_set_in_callback(data, true); + rc = func(data, NULL, &foundkey, /* from the remote host */ + keymatch, data->set.ssh_keyfunc_userp); + Curl_set_in_callback(data, false); + + switch(rc) { + case CURLKHSTAT_FINE_ADD_TO_FILE: + rc = ssh_write_knownhost(sshc->ssh_session); + if(rc != SSH_OK) { + goto cleanup; + } + break; + case CURLKHSTAT_FINE: + break; + default: /* REJECT/DEFER */ + rc = SSH_ERROR; + goto cleanup; + } + } + else { + if(keymatch != CURLKHMATCH_OK) { + rc = SSH_ERROR; + goto cleanup; + } + } + rc = SSH_OK; + +cleanup: + if(hash) + ssh_clean_pubkey_hash(&hash); + ssh_key_free(pubkey); + return rc; +} + +#define MOVE_TO_ERROR_STATE(_r) { \ + state(conn, SSH_SESSION_DISCONNECT); \ + sshc->actualcode = _r; \ + rc = SSH_ERROR; \ + break; \ +} + +#define MOVE_TO_SFTP_CLOSE_STATE() { \ + state(conn, SSH_SFTP_CLOSE); \ + sshc->actualcode = sftp_error_to_CURLE(sftp_get_error(sshc->sftp_session)); \ + rc = SSH_ERROR; \ + break; \ +} + +#define MOVE_TO_LAST_AUTH \ + if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) { \ + rc = SSH_OK; \ + state(conn, SSH_AUTH_PASS_INIT); \ + break; \ + } \ + else { \ + MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); \ + } + +#define MOVE_TO_TERTIARY_AUTH \ + if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { \ + rc = SSH_OK; \ + state(conn, SSH_AUTH_KEY_INIT); \ + break; \ + } \ + else { \ + MOVE_TO_LAST_AUTH; \ + } + +#define MOVE_TO_SECONDARY_AUTH \ + if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { \ + rc = SSH_OK; \ + state(conn, SSH_AUTH_GSSAPI); \ + break; \ + } \ + else { \ + MOVE_TO_TERTIARY_AUTH; \ + } + +static +int myssh_auth_interactive(struct connectdata *conn) +{ + int rc; + struct ssh_conn *sshc = &conn->proto.sshc; + int nprompts; + +restart: + switch(sshc->kbd_state) { + case 0: + rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL); + if(rc == SSH_AUTH_AGAIN) + return SSH_AGAIN; + + if(rc != SSH_AUTH_INFO) + return SSH_ERROR; + + nprompts = ssh_userauth_kbdint_getnprompts(sshc->ssh_session); + if(nprompts == SSH_ERROR || nprompts != 1) + return SSH_ERROR; + + rc = ssh_userauth_kbdint_setanswer(sshc->ssh_session, 0, conn->passwd); + if(rc < 0) + return SSH_ERROR; + + /* FALLTHROUGH */ + case 1: + sshc->kbd_state = 1; + + rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL); + if(rc == SSH_AUTH_AGAIN) + return SSH_AGAIN; + else if(rc == SSH_AUTH_SUCCESS) + rc = SSH_OK; + else if(rc == SSH_AUTH_INFO) { + nprompts = ssh_userauth_kbdint_getnprompts(sshc->ssh_session); + if(nprompts != 0) + return SSH_ERROR; + + sshc->kbd_state = 2; + goto restart; + } + else + rc = SSH_ERROR; + break; + case 2: + sshc->kbd_state = 2; + + rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL); + if(rc == SSH_AUTH_AGAIN) + return SSH_AGAIN; + else if(rc == SSH_AUTH_SUCCESS) + rc = SSH_OK; + else + rc = SSH_ERROR; + + break; + default: + return SSH_ERROR; + } + + sshc->kbd_state = 0; + return rc; +} + +/* + * ssh_statemach_act() runs the SSH state machine as far as it can without + * blocking and without reaching the end. The data the pointer 'block' points + * to will be set to TRUE if the libssh function returns SSH_AGAIN + * meaning it wants to be called again when the socket is ready + */ +static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct SSHPROTO *protop = data->req.protop; + struct ssh_conn *sshc = &conn->proto.sshc; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + int rc = SSH_NO_ERROR, err; + char *new_readdir_line; + int seekerr = CURL_SEEKFUNC_OK; + const char *err_msg; + *block = 0; /* we're not blocking by default */ + + do { + + switch(sshc->state) { + case SSH_INIT: + sshc->secondCreateDirs = 0; + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_OK; + +#if 0 + ssh_set_log_level(SSH_LOG_PROTOCOL); +#endif + + /* Set libssh to non-blocking, since everything internally is + non-blocking */ + ssh_set_blocking(sshc->ssh_session, 0); + + state(conn, SSH_S_STARTUP); + /* FALLTHROUGH */ + + case SSH_S_STARTUP: + rc = ssh_connect(sshc->ssh_session); + if(rc == SSH_AGAIN) + break; + + if(rc != SSH_OK) { + failf(data, "Failure establishing ssh session"); + MOVE_TO_ERROR_STATE(CURLE_FAILED_INIT); + } + + state(conn, SSH_HOSTKEY); + + /* FALLTHROUGH */ + case SSH_HOSTKEY: + + rc = myssh_is_known(conn); + if(rc != SSH_OK) { + MOVE_TO_ERROR_STATE(CURLE_PEER_FAILED_VERIFICATION); + } + + state(conn, SSH_AUTHLIST); + /* FALLTHROUGH */ + case SSH_AUTHLIST:{ + sshc->authed = FALSE; + + rc = ssh_userauth_none(sshc->ssh_session, NULL); + if(rc == SSH_AUTH_AGAIN) { + rc = SSH_AGAIN; + break; + } + + if(rc == SSH_AUTH_SUCCESS) { + sshc->authed = TRUE; + infof(data, "Authenticated with none\n"); + state(conn, SSH_AUTH_DONE); + break; + } + else if(rc == SSH_AUTH_ERROR) { + MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); + } + + sshc->auth_methods = ssh_userauth_list(sshc->ssh_session, NULL); + if(sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) { + state(conn, SSH_AUTH_PKEY_INIT); + infof(data, "Authentication using SSH public key file\n"); + } + else if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { + state(conn, SSH_AUTH_GSSAPI); + } + else if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { + state(conn, SSH_AUTH_KEY_INIT); + } + else if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) { + state(conn, SSH_AUTH_PASS_INIT); + } + else { /* unsupported authentication method */ + MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); + } + + break; + } + case SSH_AUTH_PKEY_INIT: + if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY)) { + MOVE_TO_SECONDARY_AUTH; + } + + /* Two choices, (1) private key was given on CMD, + * (2) use the "default" keys. */ + if(data->set.str[STRING_SSH_PRIVATE_KEY]) { + if(sshc->pubkey && !data->set.ssl.key_passwd) { + rc = ssh_userauth_try_publickey(sshc->ssh_session, NULL, + sshc->pubkey); + if(rc == SSH_AUTH_AGAIN) { + rc = SSH_AGAIN; + break; + } + + if(rc != SSH_OK) { + MOVE_TO_SECONDARY_AUTH; + } + } + + rc = ssh_pki_import_privkey_file(data-> + set.str[STRING_SSH_PRIVATE_KEY], + data->set.ssl.key_passwd, NULL, + NULL, &sshc->privkey); + if(rc != SSH_OK) { + failf(data, "Could not load private key file %s", + data->set.str[STRING_SSH_PRIVATE_KEY]); + MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); + break; + } + + state(conn, SSH_AUTH_PKEY); + break; + + } + else { + rc = ssh_userauth_publickey_auto(sshc->ssh_session, NULL, + data->set.ssl.key_passwd); + if(rc == SSH_AUTH_AGAIN) { + rc = SSH_AGAIN; + break; + } + if(rc == SSH_AUTH_SUCCESS) { + rc = SSH_OK; + sshc->authed = TRUE; + infof(data, "Completed public key authentication\n"); + state(conn, SSH_AUTH_DONE); + break; + } + + MOVE_TO_SECONDARY_AUTH; + } + break; + case SSH_AUTH_PKEY: + rc = ssh_userauth_publickey(sshc->ssh_session, NULL, sshc->privkey); + if(rc == SSH_AUTH_AGAIN) { + rc = SSH_AGAIN; + break; + } + + if(rc == SSH_AUTH_SUCCESS) { + sshc->authed = TRUE; + infof(data, "Completed public key authentication\n"); + state(conn, SSH_AUTH_DONE); + break; + } + else { + infof(data, "Failed public key authentication (rc: %d)\n", rc); + MOVE_TO_SECONDARY_AUTH; + } + break; + + case SSH_AUTH_GSSAPI: + if(!(data->set.ssh_auth_types & CURLSSH_AUTH_GSSAPI)) { + MOVE_TO_TERTIARY_AUTH; + } + + rc = ssh_userauth_gssapi(sshc->ssh_session); + if(rc == SSH_AUTH_AGAIN) { + rc = SSH_AGAIN; + break; + } + + if(rc == SSH_AUTH_SUCCESS) { + rc = SSH_OK; + sshc->authed = TRUE; + infof(data, "Completed gssapi authentication\n"); + state(conn, SSH_AUTH_DONE); + break; + } + + MOVE_TO_TERTIARY_AUTH; + break; + + case SSH_AUTH_KEY_INIT: + if(data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) { + state(conn, SSH_AUTH_KEY); + } + else { + MOVE_TO_LAST_AUTH; + } + break; + + case SSH_AUTH_KEY: + + /* Authentication failed. Continue with keyboard-interactive now. */ + rc = myssh_auth_interactive(conn); + if(rc == SSH_AGAIN) { + break; + } + if(rc == SSH_OK) { + sshc->authed = TRUE; + infof(data, "completed keyboard interactive authentication\n"); + } + state(conn, SSH_AUTH_DONE); + break; + + case SSH_AUTH_PASS_INIT: + if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD)) { + /* Host key authentication is intentionally not implemented */ + MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); + } + state(conn, SSH_AUTH_PASS); + /* FALLTHROUGH */ + + case SSH_AUTH_PASS: + rc = ssh_userauth_password(sshc->ssh_session, NULL, conn->passwd); + if(rc == SSH_AUTH_AGAIN) { + rc = SSH_AGAIN; + break; + } + + if(rc == SSH_AUTH_SUCCESS) { + sshc->authed = TRUE; + infof(data, "Completed password authentication\n"); + state(conn, SSH_AUTH_DONE); + } + else { + MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); + } + break; + + case SSH_AUTH_DONE: + if(!sshc->authed) { + failf(data, "Authentication failure"); + MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); + break; + } + + /* + * At this point we have an authenticated ssh session. + */ + infof(data, "Authentication complete\n"); + + Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSH is connected */ + + conn->sockfd = sock; + conn->writesockfd = CURL_SOCKET_BAD; + + if(conn->handler->protocol == CURLPROTO_SFTP) { + state(conn, SSH_SFTP_INIT); + break; + } + infof(data, "SSH CONNECT phase done\n"); + state(conn, SSH_STOP); + break; + + case SSH_SFTP_INIT: + ssh_set_blocking(sshc->ssh_session, 1); + + sshc->sftp_session = sftp_new(sshc->ssh_session); + if(!sshc->sftp_session) { + failf(data, "Failure initializing sftp session: %s", + ssh_get_error(sshc->ssh_session)); + MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT); + break; + } + + rc = sftp_init(sshc->sftp_session); + if(rc != SSH_OK) { + rc = sftp_get_error(sshc->sftp_session); + failf(data, "Failure initializing sftp session: %s", + ssh_get_error(sshc->ssh_session)); + MOVE_TO_ERROR_STATE(sftp_error_to_CURLE(rc)); + break; + } + state(conn, SSH_SFTP_REALPATH); + /* FALLTHROUGH */ + case SSH_SFTP_REALPATH: + /* + * Get the "home" directory + */ + sshc->homedir = sftp_canonicalize_path(sshc->sftp_session, "."); + if(sshc->homedir == NULL) { + MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT); + } + conn->data->state.most_recent_ftp_entrypath = sshc->homedir; + + /* This is the last step in the SFTP connect phase. Do note that while + we get the homedir here, we get the "workingpath" in the DO action + since the homedir will remain the same between request but the + working path will not. */ + DEBUGF(infof(data, "SSH CONNECT phase done\n")); + state(conn, SSH_STOP); + break; + + case SSH_SFTP_QUOTE_INIT: + + result = Curl_getworkingpath(conn, sshc->homedir, &protop->path); + if(result) { + sshc->actualcode = result; + state(conn, SSH_STOP); + break; + } + + if(data->set.quote) { + infof(data, "Sending quote commands\n"); + sshc->quote_item = data->set.quote; + state(conn, SSH_SFTP_QUOTE); + } + else { + state(conn, SSH_SFTP_GETINFO); + } + break; + + case SSH_SFTP_POSTQUOTE_INIT: + if(data->set.postquote) { + infof(data, "Sending quote commands\n"); + sshc->quote_item = data->set.postquote; + state(conn, SSH_SFTP_QUOTE); + } + else { + state(conn, SSH_STOP); + } + break; + + case SSH_SFTP_QUOTE: + /* Send any quote commands */ + sftp_quote(conn); + break; + + case SSH_SFTP_NEXT_QUOTE: + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + + sshc->quote_item = sshc->quote_item->next; + + if(sshc->quote_item) { + state(conn, SSH_SFTP_QUOTE); + } + else { + if(sshc->nextstate != SSH_NO_STATE) { + state(conn, sshc->nextstate); + sshc->nextstate = SSH_NO_STATE; + } + else { + state(conn, SSH_SFTP_GETINFO); + } + } + break; + + case SSH_SFTP_QUOTE_STAT: + sftp_quote_stat(conn); + break; + + case SSH_SFTP_QUOTE_SETSTAT: + rc = sftp_setstat(sshc->sftp_session, sshc->quote_path2, + sshc->quote_attrs); + if(rc != 0 && !sshc->acceptfail) { + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "Attempt to set SFTP stats failed: %s", + ssh_get_error(sshc->ssh_session)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + /* sshc->actualcode = sftp_error_to_CURLE(err); + * we do not send the actual error; we return + * the error the libssh2 backend is returning */ + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_SYMLINK: + rc = sftp_symlink(sshc->sftp_session, sshc->quote_path2, + sshc->quote_path1); + if(rc != 0 && !sshc->acceptfail) { + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "symlink command failed: %s", + ssh_get_error(sshc->ssh_session)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_MKDIR: + rc = sftp_mkdir(sshc->sftp_session, sshc->quote_path1, + (mode_t)data->set.new_directory_perms); + if(rc != 0 && !sshc->acceptfail) { + Curl_safefree(sshc->quote_path1); + failf(data, "mkdir command failed: %s", + ssh_get_error(sshc->ssh_session)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_RENAME: + rc = sftp_rename(sshc->sftp_session, sshc->quote_path1, + sshc->quote_path2); + if(rc != 0 && !sshc->acceptfail) { + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "rename command failed: %s", + ssh_get_error(sshc->ssh_session)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_RMDIR: + rc = sftp_rmdir(sshc->sftp_session, sshc->quote_path1); + if(rc != 0 && !sshc->acceptfail) { + Curl_safefree(sshc->quote_path1); + failf(data, "rmdir command failed: %s", + ssh_get_error(sshc->ssh_session)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_UNLINK: + rc = sftp_unlink(sshc->sftp_session, sshc->quote_path1); + if(rc != 0 && !sshc->acceptfail) { + Curl_safefree(sshc->quote_path1); + failf(data, "rm command failed: %s", + ssh_get_error(sshc->ssh_session)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_STATVFS: + { + sftp_statvfs_t statvfs; + + statvfs = sftp_statvfs(sshc->sftp_session, sshc->quote_path1); + if(!statvfs && !sshc->acceptfail) { + Curl_safefree(sshc->quote_path1); + failf(data, "statvfs command failed: %s", + ssh_get_error(sshc->ssh_session)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + else if(statvfs) { + char *tmp = aprintf("statvfs:\n" + "f_bsize: %llu\n" "f_frsize: %llu\n" + "f_blocks: %llu\n" "f_bfree: %llu\n" + "f_bavail: %llu\n" "f_files: %llu\n" + "f_ffree: %llu\n" "f_favail: %llu\n" + "f_fsid: %llu\n" "f_flag: %llu\n" + "f_namemax: %llu\n", + statvfs->f_bsize, statvfs->f_frsize, + statvfs->f_blocks, statvfs->f_bfree, + statvfs->f_bavail, statvfs->f_files, + statvfs->f_ffree, statvfs->f_favail, + statvfs->f_fsid, statvfs->f_flag, + statvfs->f_namemax); + sftp_statvfs_free(statvfs); + + if(!tmp) { + result = CURLE_OUT_OF_MEMORY; + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + break; + } + + result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp)); + free(tmp); + if(result) { + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + } + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + } + + case SSH_SFTP_GETINFO: + if(data->set.get_filetime) { + state(conn, SSH_SFTP_FILETIME); + } + else { + state(conn, SSH_SFTP_TRANS_INIT); + } + break; + + case SSH_SFTP_FILETIME: + { + sftp_attributes attrs; + + attrs = sftp_stat(sshc->sftp_session, protop->path); + if(attrs != 0) { + data->info.filetime = attrs->mtime; + sftp_attributes_free(attrs); + } + + state(conn, SSH_SFTP_TRANS_INIT); + break; + } + + case SSH_SFTP_TRANS_INIT: + if(data->set.upload) + state(conn, SSH_SFTP_UPLOAD_INIT); + else { + if(protop->path[strlen(protop->path)-1] == '/') + state(conn, SSH_SFTP_READDIR_INIT); + else + state(conn, SSH_SFTP_DOWNLOAD_INIT); + } + break; + + case SSH_SFTP_UPLOAD_INIT: + { + int flags; + + if(data->state.resume_from != 0) { + sftp_attributes attrs; + + if(data->state.resume_from < 0) { + attrs = sftp_stat(sshc->sftp_session, protop->path); + if(attrs != 0) { + curl_off_t size = attrs->size; + if(size < 0) { + failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size); + MOVE_TO_ERROR_STATE(CURLE_BAD_DOWNLOAD_RESUME); + } + data->state.resume_from = attrs->size; + + sftp_attributes_free(attrs); + } + else { + data->state.resume_from = 0; + } + } + } + + if(data->set.ftp_append) + /* Try to open for append, but create if nonexisting */ + flags = O_WRONLY|O_CREAT|O_APPEND; + else if(data->state.resume_from > 0) + /* If we have restart position then open for append */ + flags = O_WRONLY|O_APPEND; + else + /* Clear file before writing (normal behaviour) */ + flags = O_WRONLY|O_APPEND|O_CREAT|O_TRUNC; + + if(sshc->sftp_file) + sftp_close(sshc->sftp_file); + sshc->sftp_file = + sftp_open(sshc->sftp_session, protop->path, + flags, (mode_t)data->set.new_file_perms); + if(!sshc->sftp_file) { + err = sftp_get_error(sshc->sftp_session); + + if(((err == SSH_FX_NO_SUCH_FILE || err == SSH_FX_FAILURE || + err == SSH_FX_NO_SUCH_PATH)) && + (data->set.ftp_create_missing_dirs && + (strlen(protop->path) > 1))) { + /* try to create the path remotely */ + rc = 0; + sshc->secondCreateDirs = 1; + state(conn, SSH_SFTP_CREATE_DIRS_INIT); + break; + } + else { + MOVE_TO_SFTP_CLOSE_STATE(); + } + } + + /* If we have a restart point then we need to seek to the correct + position. */ + if(data->state.resume_from > 0) { + /* Let's read off the proper amount of bytes from the input. */ + if(conn->seek_func) { + Curl_set_in_callback(data, true); + seekerr = conn->seek_func(conn->seek_client, data->state.resume_from, + SEEK_SET); + Curl_set_in_callback(data, false); + } + + if(seekerr != CURL_SEEKFUNC_OK) { + curl_off_t passed = 0; + + if(seekerr != CURL_SEEKFUNC_CANTSEEK) { + failf(data, "Could not seek stream"); + return CURLE_FTP_COULDNT_USE_REST; + } + /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ + do { + size_t readthisamountnow = + (data->state.resume_from - passed > data->set.buffer_size) ? + (size_t)data->set.buffer_size : + curlx_sotouz(data->state.resume_from - passed); + + size_t actuallyread = + data->state.fread_func(data->state.buffer, 1, + readthisamountnow, data->state.in); + + passed += actuallyread; + if((actuallyread == 0) || (actuallyread > readthisamountnow)) { + /* this checks for greater-than only to make sure that the + CURL_READFUNC_ABORT return code still aborts */ + failf(data, "Failed to read data"); + MOVE_TO_ERROR_STATE(CURLE_FTP_COULDNT_USE_REST); + } + } while(passed < data->state.resume_from); + } + + /* now, decrease the size of the read */ + if(data->state.infilesize > 0) { + data->state.infilesize -= data->state.resume_from; + data->req.size = data->state.infilesize; + Curl_pgrsSetUploadSize(data, data->state.infilesize); + } + + rc = sftp_seek64(sshc->sftp_file, data->state.resume_from); + if(rc != 0) { + MOVE_TO_SFTP_CLOSE_STATE(); + } + } + if(data->state.infilesize > 0) { + data->req.size = data->state.infilesize; + Curl_pgrsSetUploadSize(data, data->state.infilesize); + } + /* upload data */ + Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); + + /* not set by Curl_setup_transfer to preserve keepon bits */ + conn->sockfd = conn->writesockfd; + + /* store this original bitmask setup to use later on if we can't + figure out a "real" bitmask */ + sshc->orig_waitfor = data->req.keepon; + + /* we want to use the _sending_ function even when the socket turns + out readable as the underlying libssh sftp send function will deal + with both accordingly */ + conn->cselect_bits = CURL_CSELECT_OUT; + + /* since we don't really wait for anything at this point, we want the + state machine to move on as soon as possible so we set a very short + timeout here */ + Curl_expire(data, 0, EXPIRE_RUN_NOW); + + state(conn, SSH_STOP); + break; + } + + case SSH_SFTP_CREATE_DIRS_INIT: + if(strlen(protop->path) > 1) { + sshc->slash_pos = protop->path + 1; /* ignore the leading '/' */ + state(conn, SSH_SFTP_CREATE_DIRS); + } + else { + state(conn, SSH_SFTP_UPLOAD_INIT); + } + break; + + case SSH_SFTP_CREATE_DIRS: + sshc->slash_pos = strchr(sshc->slash_pos, '/'); + if(sshc->slash_pos) { + *sshc->slash_pos = 0; + + infof(data, "Creating directory '%s'\n", protop->path); + state(conn, SSH_SFTP_CREATE_DIRS_MKDIR); + break; + } + state(conn, SSH_SFTP_UPLOAD_INIT); + break; + + case SSH_SFTP_CREATE_DIRS_MKDIR: + /* 'mode' - parameter is preliminary - default to 0644 */ + rc = sftp_mkdir(sshc->sftp_session, protop->path, + (mode_t)data->set.new_directory_perms); + *sshc->slash_pos = '/'; + ++sshc->slash_pos; + if(rc < 0) { + /* + * Abort if failure wasn't that the dir already exists or the + * permission was denied (creation might succeed further down the + * path) - retry on unspecific FAILURE also + */ + err = sftp_get_error(sshc->sftp_session); + if((err != SSH_FX_FILE_ALREADY_EXISTS) && + (err != SSH_FX_FAILURE) && + (err != SSH_FX_PERMISSION_DENIED)) { + MOVE_TO_SFTP_CLOSE_STATE(); + } + rc = 0; /* clear rc and continue */ + } + state(conn, SSH_SFTP_CREATE_DIRS); + break; + + case SSH_SFTP_READDIR_INIT: + Curl_pgrsSetDownloadSize(data, -1); + if(data->set.opt_no_body) { + state(conn, SSH_STOP); + break; + } + + /* + * This is a directory that we are trying to get, so produce a directory + * listing + */ + sshc->sftp_dir = sftp_opendir(sshc->sftp_session, + protop->path); + if(!sshc->sftp_dir) { + failf(data, "Could not open directory for reading: %s", + ssh_get_error(sshc->ssh_session)); + MOVE_TO_SFTP_CLOSE_STATE(); + } + state(conn, SSH_SFTP_READDIR); + break; + + case SSH_SFTP_READDIR: + + if(sshc->readdir_attrs) + sftp_attributes_free(sshc->readdir_attrs); + + sshc->readdir_attrs = sftp_readdir(sshc->sftp_session, sshc->sftp_dir); + if(sshc->readdir_attrs) { + sshc->readdir_filename = sshc->readdir_attrs->name; + sshc->readdir_longentry = sshc->readdir_attrs->longname; + sshc->readdir_len = strlen(sshc->readdir_filename); + + if(data->set.ftp_list_only) { + char *tmpLine; + + tmpLine = aprintf("%s\n", sshc->readdir_filename); + if(tmpLine == NULL) { + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + result = Curl_client_write(conn, CLIENTWRITE_BODY, + tmpLine, sshc->readdir_len + 1); + free(tmpLine); + + if(result) { + state(conn, SSH_STOP); + break; + } + /* since this counts what we send to the client, we include the + newline in this counter */ + data->req.bytecount += sshc->readdir_len + 1; + + /* output debug output if that is requested */ + if(data->set.verbose) { + Curl_debug(data, CURLINFO_DATA_OUT, + (char *)sshc->readdir_filename, + sshc->readdir_len); + } + } + else { + sshc->readdir_currLen = strlen(sshc->readdir_longentry); + sshc->readdir_totalLen = 80 + sshc->readdir_currLen; + sshc->readdir_line = calloc(sshc->readdir_totalLen, 1); + if(!sshc->readdir_line) { + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + + memcpy(sshc->readdir_line, sshc->readdir_longentry, + sshc->readdir_currLen); + if((sshc->readdir_attrs->flags & SSH_FILEXFER_ATTR_PERMISSIONS) && + ((sshc->readdir_attrs->permissions & S_IFMT) == + S_IFLNK)) { + sshc->readdir_linkPath = malloc(PATH_MAX + 1); + if(sshc->readdir_linkPath == NULL) { + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + + msnprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", protop->path, + sshc->readdir_filename); + + state(conn, SSH_SFTP_READDIR_LINK); + break; + } + state(conn, SSH_SFTP_READDIR_BOTTOM); + break; + } + } + else if(sshc->readdir_attrs == NULL && sftp_dir_eof(sshc->sftp_dir)) { + state(conn, SSH_SFTP_READDIR_DONE); + break; + } + else { + failf(data, "Could not open remote file for reading: %s", + ssh_get_error(sshc->ssh_session)); + MOVE_TO_SFTP_CLOSE_STATE(); + break; + } + break; + + case SSH_SFTP_READDIR_LINK: + if(sshc->readdir_link_attrs) + sftp_attributes_free(sshc->readdir_link_attrs); + + sshc->readdir_link_attrs = sftp_lstat(sshc->sftp_session, + sshc->readdir_linkPath); + if(sshc->readdir_link_attrs == 0) { + failf(data, "Could not read symlink for reading: %s", + ssh_get_error(sshc->ssh_session)); + MOVE_TO_SFTP_CLOSE_STATE(); + } + + if(sshc->readdir_link_attrs->name == NULL) { + sshc->readdir_tmp = sftp_readlink(sshc->sftp_session, + sshc->readdir_linkPath); + if(sshc->readdir_filename == NULL) + sshc->readdir_len = 0; + else + sshc->readdir_len = strlen(sshc->readdir_tmp); + sshc->readdir_longentry = NULL; + sshc->readdir_filename = sshc->readdir_tmp; + } + else { + sshc->readdir_len = strlen(sshc->readdir_link_attrs->name); + sshc->readdir_filename = sshc->readdir_link_attrs->name; + sshc->readdir_longentry = sshc->readdir_link_attrs->longname; + } + + Curl_safefree(sshc->readdir_linkPath); + + /* get room for the filename and extra output */ + sshc->readdir_totalLen += 4 + sshc->readdir_len; + new_readdir_line = Curl_saferealloc(sshc->readdir_line, + sshc->readdir_totalLen); + if(!new_readdir_line) { + sshc->readdir_line = NULL; + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + sshc->readdir_line = new_readdir_line; + + sshc->readdir_currLen += msnprintf(sshc->readdir_line + + sshc->readdir_currLen, + sshc->readdir_totalLen - + sshc->readdir_currLen, + " -> %s", + sshc->readdir_filename); + + sftp_attributes_free(sshc->readdir_link_attrs); + sshc->readdir_link_attrs = NULL; + sshc->readdir_filename = NULL; + sshc->readdir_longentry = NULL; + + state(conn, SSH_SFTP_READDIR_BOTTOM); + /* FALLTHROUGH */ + case SSH_SFTP_READDIR_BOTTOM: + sshc->readdir_currLen += msnprintf(sshc->readdir_line + + sshc->readdir_currLen, + sshc->readdir_totalLen - + sshc->readdir_currLen, "\n"); + result = Curl_client_write(conn, CLIENTWRITE_BODY, + sshc->readdir_line, + sshc->readdir_currLen); + + if(!result) { + + /* output debug output if that is requested */ + if(data->set.verbose) { + Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line, + sshc->readdir_currLen); + } + data->req.bytecount += sshc->readdir_currLen; + } + Curl_safefree(sshc->readdir_line); + ssh_string_free_char(sshc->readdir_tmp); + sshc->readdir_tmp = NULL; + + if(result) { + state(conn, SSH_STOP); + } + else + state(conn, SSH_SFTP_READDIR); + break; + + case SSH_SFTP_READDIR_DONE: + sftp_closedir(sshc->sftp_dir); + sshc->sftp_dir = NULL; + + /* no data to transfer */ + Curl_setup_transfer(data, -1, -1, FALSE, -1); + state(conn, SSH_STOP); + break; + + case SSH_SFTP_DOWNLOAD_INIT: + /* + * Work on getting the specified file + */ + if(sshc->sftp_file) + sftp_close(sshc->sftp_file); + + sshc->sftp_file = sftp_open(sshc->sftp_session, protop->path, + O_RDONLY, (mode_t)data->set.new_file_perms); + if(!sshc->sftp_file) { + failf(data, "Could not open remote file for reading: %s", + ssh_get_error(sshc->ssh_session)); + + MOVE_TO_SFTP_CLOSE_STATE(); + } + + state(conn, SSH_SFTP_DOWNLOAD_STAT); + break; + + case SSH_SFTP_DOWNLOAD_STAT: + { + sftp_attributes attrs; + curl_off_t size; + + attrs = sftp_fstat(sshc->sftp_file); + if(!attrs || + !(attrs->flags & SSH_FILEXFER_ATTR_SIZE) || + (attrs->size == 0)) { + /* + * sftp_fstat didn't return an error, so maybe the server + * just doesn't support stat() + * OR the server doesn't return a file size with a stat() + * OR file size is 0 + */ + data->req.size = -1; + data->req.maxdownload = -1; + Curl_pgrsSetDownloadSize(data, -1); + size = 0; + } + else { + size = attrs->size; + + sftp_attributes_free(attrs); + + if(size < 0) { + failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size); + return CURLE_BAD_DOWNLOAD_RESUME; + } + if(conn->data->state.use_range) { + curl_off_t from, to; + char *ptr; + char *ptr2; + CURLofft to_t; + CURLofft from_t; + + from_t = curlx_strtoofft(conn->data->state.range, &ptr, 0, &from); + if(from_t == CURL_OFFT_FLOW) { + return CURLE_RANGE_ERROR; + } + while(*ptr && (ISSPACE(*ptr) || (*ptr == '-'))) + ptr++; + to_t = curlx_strtoofft(ptr, &ptr2, 0, &to); + if(to_t == CURL_OFFT_FLOW) { + return CURLE_RANGE_ERROR; + } + if((to_t == CURL_OFFT_INVAL) /* no "to" value given */ + || (to >= size)) { + to = size - 1; + } + if(from_t) { + /* from is relative to end of file */ + from = size - to; + to = size - 1; + } + if(from > size) { + failf(data, "Offset (%" + CURL_FORMAT_CURL_OFF_T ") was beyond file size (%" + CURL_FORMAT_CURL_OFF_T ")", from, size); + return CURLE_BAD_DOWNLOAD_RESUME; + } + if(from > to) { + from = to; + size = 0; + } + else { + size = to - from + 1; + } + + rc = sftp_seek64(sshc->sftp_file, from); + if(rc != 0) { + MOVE_TO_SFTP_CLOSE_STATE(); + } + } + data->req.size = size; + data->req.maxdownload = size; + Curl_pgrsSetDownloadSize(data, size); + } + + /* We can resume if we can seek to the resume position */ + if(data->state.resume_from) { + if(data->state.resume_from < 0) { + /* We're supposed to download the last abs(from) bytes */ + if((curl_off_t)size < -data->state.resume_from) { + failf(data, "Offset (%" + CURL_FORMAT_CURL_OFF_T ") was beyond file size (%" + CURL_FORMAT_CURL_OFF_T ")", + data->state.resume_from, size); + return CURLE_BAD_DOWNLOAD_RESUME; + } + /* download from where? */ + data->state.resume_from += size; + } + else { + if((curl_off_t)size < data->state.resume_from) { + failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T + ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")", + data->state.resume_from, size); + return CURLE_BAD_DOWNLOAD_RESUME; + } + } + /* Does a completed file need to be seeked and started or closed ? */ + /* Now store the number of bytes we are expected to download */ + data->req.size = size - data->state.resume_from; + data->req.maxdownload = size - data->state.resume_from; + Curl_pgrsSetDownloadSize(data, + size - data->state.resume_from); + + rc = sftp_seek64(sshc->sftp_file, data->state.resume_from); + if(rc != 0) { + MOVE_TO_SFTP_CLOSE_STATE(); + } + } + } + + /* Setup the actual download */ + if(data->req.size == 0) { + /* no data to transfer */ + Curl_setup_transfer(data, -1, -1, FALSE, -1); + infof(data, "File already completely downloaded\n"); + state(conn, SSH_STOP); + break; + } + Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1); + + /* not set by Curl_setup_transfer to preserve keepon bits */ + conn->writesockfd = conn->sockfd; + + /* we want to use the _receiving_ function even when the socket turns + out writableable as the underlying libssh recv function will deal + with both accordingly */ + conn->cselect_bits = CURL_CSELECT_IN; + + if(result) { + /* this should never occur; the close state should be entered + at the time the error occurs */ + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = result; + } + else { + sshc->sftp_recv_state = 0; + state(conn, SSH_STOP); + } + break; + + case SSH_SFTP_CLOSE: + if(sshc->sftp_file) { + sftp_close(sshc->sftp_file); + sshc->sftp_file = NULL; + } + Curl_safefree(protop->path); + + DEBUGF(infof(data, "SFTP DONE done\n")); + + /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT + After nextstate is executed, the control should come back to + SSH_SFTP_CLOSE to pass the correct result back */ + if(sshc->nextstate != SSH_NO_STATE && + sshc->nextstate != SSH_SFTP_CLOSE) { + state(conn, sshc->nextstate); + sshc->nextstate = SSH_SFTP_CLOSE; + } + else { + state(conn, SSH_STOP); + result = sshc->actualcode; + } + break; + + case SSH_SFTP_SHUTDOWN: + /* during times we get here due to a broken transfer and then the + sftp_handle might not have been taken down so make sure that is done + before we proceed */ + + if(sshc->sftp_file) { + sftp_close(sshc->sftp_file); + sshc->sftp_file = NULL; + } + + if(sshc->sftp_session) { + sftp_free(sshc->sftp_session); + sshc->sftp_session = NULL; + } + + SSH_STRING_FREE_CHAR(sshc->homedir); + conn->data->state.most_recent_ftp_entrypath = NULL; + + state(conn, SSH_SESSION_DISCONNECT); + break; + + + case SSH_SCP_TRANS_INIT: + result = Curl_getworkingpath(conn, sshc->homedir, &protop->path); + if(result) { + sshc->actualcode = result; + state(conn, SSH_STOP); + break; + } + + /* Functions from the SCP subsystem cannot handle/return SSH_AGAIN */ + ssh_set_blocking(sshc->ssh_session, 1); + + if(data->set.upload) { + if(data->state.infilesize < 0) { + failf(data, "SCP requires a known file size for upload"); + sshc->actualcode = CURLE_UPLOAD_FAILED; + MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED); + } + + sshc->scp_session = + ssh_scp_new(sshc->ssh_session, SSH_SCP_WRITE, protop->path); + state(conn, SSH_SCP_UPLOAD_INIT); + } + else { + sshc->scp_session = + ssh_scp_new(sshc->ssh_session, SSH_SCP_READ, protop->path); + state(conn, SSH_SCP_DOWNLOAD_INIT); + } + + if(!sshc->scp_session) { + err_msg = ssh_get_error(sshc->ssh_session); + failf(conn->data, "%s", err_msg); + MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED); + } + + break; + + case SSH_SCP_UPLOAD_INIT: + + rc = ssh_scp_init(sshc->scp_session); + if(rc != SSH_OK) { + err_msg = ssh_get_error(sshc->ssh_session); + failf(conn->data, "%s", err_msg); + MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED); + } + + rc = ssh_scp_push_file(sshc->scp_session, protop->path, + data->state.infilesize, + (int)data->set.new_file_perms); + if(rc != SSH_OK) { + err_msg = ssh_get_error(sshc->ssh_session); + failf(conn->data, "%s", err_msg); + MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED); + } + + /* upload data */ + Curl_setup_transfer(data, -1, data->req.size, FALSE, FIRSTSOCKET); + + /* not set by Curl_setup_transfer to preserve keepon bits */ + conn->sockfd = conn->writesockfd; + + /* store this original bitmask setup to use later on if we can't + figure out a "real" bitmask */ + sshc->orig_waitfor = data->req.keepon; + + /* we want to use the _sending_ function even when the socket turns + out readable as the underlying libssh scp send function will deal + with both accordingly */ + conn->cselect_bits = CURL_CSELECT_OUT; + + state(conn, SSH_STOP); + + break; + + case SSH_SCP_DOWNLOAD_INIT: + + rc = ssh_scp_init(sshc->scp_session); + if(rc != SSH_OK) { + err_msg = ssh_get_error(sshc->ssh_session); + failf(conn->data, "%s", err_msg); + MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT); + } + state(conn, SSH_SCP_DOWNLOAD); + /* FALLTHROUGH */ + + case SSH_SCP_DOWNLOAD:{ + curl_off_t bytecount; + + rc = ssh_scp_pull_request(sshc->scp_session); + if(rc != SSH_SCP_REQUEST_NEWFILE) { + err_msg = ssh_get_error(sshc->ssh_session); + failf(conn->data, "%s", err_msg); + MOVE_TO_ERROR_STATE(CURLE_REMOTE_FILE_NOT_FOUND); + break; + } + + /* download data */ + bytecount = ssh_scp_request_get_size(sshc->scp_session); + data->req.maxdownload = (curl_off_t) bytecount; + Curl_setup_transfer(data, FIRSTSOCKET, bytecount, FALSE, -1); + + /* not set by Curl_setup_transfer to preserve keepon bits */ + conn->writesockfd = conn->sockfd; + + /* we want to use the _receiving_ function even when the socket turns + out writableable as the underlying libssh recv function will deal + with both accordingly */ + conn->cselect_bits = CURL_CSELECT_IN; + + state(conn, SSH_STOP); + break; + } + case SSH_SCP_DONE: + if(data->set.upload) + state(conn, SSH_SCP_SEND_EOF); + else + state(conn, SSH_SCP_CHANNEL_FREE); + break; + + case SSH_SCP_SEND_EOF: + if(sshc->scp_session) { + rc = ssh_scp_close(sshc->scp_session); + if(rc == SSH_AGAIN) { + /* Currently the ssh_scp_close handles waiting for EOF in + * blocking way. + */ + break; + } + if(rc != SSH_OK) { + infof(data, "Failed to close libssh scp channel: %s\n", + ssh_get_error(sshc->ssh_session)); + } + } + + state(conn, SSH_SCP_CHANNEL_FREE); + break; + + case SSH_SCP_CHANNEL_FREE: + if(sshc->scp_session) { + ssh_scp_free(sshc->scp_session); + sshc->scp_session = NULL; + } + DEBUGF(infof(data, "SCP DONE phase complete\n")); + + ssh_set_blocking(sshc->ssh_session, 0); + + state(conn, SSH_SESSION_DISCONNECT); + /* FALLTHROUGH */ + + case SSH_SESSION_DISCONNECT: + /* during weird times when we've been prematurely aborted, the channel + is still alive when we reach this state and we MUST kill the channel + properly first */ + if(sshc->scp_session) { + ssh_scp_free(sshc->scp_session); + sshc->scp_session = NULL; + } + + ssh_disconnect(sshc->ssh_session); + + SSH_STRING_FREE_CHAR(sshc->homedir); + conn->data->state.most_recent_ftp_entrypath = NULL; + + state(conn, SSH_SESSION_FREE); + /* FALLTHROUGH */ + case SSH_SESSION_FREE: + if(sshc->ssh_session) { + ssh_free(sshc->ssh_session); + sshc->ssh_session = NULL; + } + + /* worst-case scenario cleanup */ + + DEBUGASSERT(sshc->ssh_session == NULL); + DEBUGASSERT(sshc->scp_session == NULL); + + if(sshc->readdir_tmp) { + ssh_string_free_char(sshc->readdir_tmp); + sshc->readdir_tmp = NULL; + } + + if(sshc->quote_attrs) + sftp_attributes_free(sshc->quote_attrs); + + if(sshc->readdir_attrs) + sftp_attributes_free(sshc->readdir_attrs); + + if(sshc->readdir_link_attrs) + sftp_attributes_free(sshc->readdir_link_attrs); + + if(sshc->privkey) + ssh_key_free(sshc->privkey); + if(sshc->pubkey) + ssh_key_free(sshc->pubkey); + + Curl_safefree(sshc->rsa_pub); + Curl_safefree(sshc->rsa); + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + Curl_safefree(sshc->readdir_line); + Curl_safefree(sshc->readdir_linkPath); + SSH_STRING_FREE_CHAR(sshc->homedir); + + /* the code we are about to return */ + result = sshc->actualcode; + + memset(sshc, 0, sizeof(struct ssh_conn)); + + connclose(conn, "SSH session free"); + sshc->state = SSH_SESSION_FREE; /* current */ + sshc->nextstate = SSH_NO_STATE; + state(conn, SSH_STOP); + break; + + case SSH_QUIT: + /* fallthrough, just stop! */ + default: + /* internal error */ + sshc->nextstate = SSH_NO_STATE; + state(conn, SSH_STOP); + break; + + } + } while(!rc && (sshc->state != SSH_STOP)); + + + if(rc == SSH_AGAIN) { + /* we would block, we need to wait for the socket to be ready (in the + right direction too)! */ + *block = TRUE; + } + + return result; +} + + +/* called by the multi interface to figure out what socket(s) to wait for and + for what actions in the DO_DONE, PERFORM and WAITPERFORM states */ +static int myssh_perform_getsock(const struct connectdata *conn, + curl_socket_t *sock, /* points to numsocks + number of sockets */ + int numsocks) +{ + int bitmap = GETSOCK_BLANK; + (void) numsocks; + + sock[0] = conn->sock[FIRSTSOCKET]; + + if(conn->waitfor & KEEP_RECV) + bitmap |= GETSOCK_READSOCK(FIRSTSOCKET); + + if(conn->waitfor & KEEP_SEND) + bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET); + + return bitmap; +} + +/* Generic function called by the multi interface to figure out what socket(s) + to wait for and for what actions during the DOING and PROTOCONNECT states*/ +static int myssh_getsock(struct connectdata *conn, + curl_socket_t *sock, /* points to numsocks + number of sockets */ + int numsocks) +{ + /* if we know the direction we can use the generic *_getsock() function even + for the protocol_connect and doing states */ + return myssh_perform_getsock(conn, sock, numsocks); +} + +static void myssh_block2waitfor(struct connectdata *conn, bool block) +{ + struct ssh_conn *sshc = &conn->proto.sshc; + + /* If it didn't block, or nothing was returned by ssh_get_poll_flags + * have the original set */ + conn->waitfor = sshc->orig_waitfor; + + if(block) { + int dir = ssh_get_poll_flags(sshc->ssh_session); + if(dir & SSH_READ_PENDING) { + /* translate the libssh define bits into our own bit defines */ + conn->waitfor = KEEP_RECV; + } + else if(dir & SSH_WRITE_PENDING) { + conn->waitfor = KEEP_SEND; + } + } +} + +/* called repeatedly until done from multi.c */ +static CURLcode myssh_multi_statemach(struct connectdata *conn, + bool *done) +{ + struct ssh_conn *sshc = &conn->proto.sshc; + CURLcode result = CURLE_OK; + bool block; /* we store the status and use that to provide a ssh_getsock() + implementation */ + + result = myssh_statemach_act(conn, &block); + *done = (sshc->state == SSH_STOP) ? TRUE : FALSE; + myssh_block2waitfor(conn, block); + + return result; +} + +static CURLcode myssh_block_statemach(struct connectdata *conn, + bool disconnect) +{ + struct ssh_conn *sshc = &conn->proto.sshc; + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + while((sshc->state != SSH_STOP) && !result) { + bool block; + timediff_t left = 1000; + struct curltime now = Curl_now(); + + result = myssh_statemach_act(conn, &block); + if(result) + break; + + if(!disconnect) { + if(Curl_pgrsUpdate(conn)) + return CURLE_ABORTED_BY_CALLBACK; + + result = Curl_speedcheck(data, now); + if(result) + break; + + left = Curl_timeleft(data, NULL, FALSE); + if(left < 0) { + failf(data, "Operation timed out"); + return CURLE_OPERATION_TIMEDOUT; + } + } + + if(!result && block) { + curl_socket_t fd_read = conn->sock[FIRSTSOCKET]; + /* wait for the socket to become ready */ + (void) Curl_socket_check(fd_read, CURL_SOCKET_BAD, + CURL_SOCKET_BAD, left > 1000 ? 1000 : left); + } + + } + + return result; +} + +/* + * SSH setup connection + */ +static CURLcode myssh_setup_connection(struct connectdata *conn) +{ + struct SSHPROTO *ssh; + + conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO)); + if(!ssh) + return CURLE_OUT_OF_MEMORY; + + return CURLE_OK; +} + +static Curl_recv scp_recv, sftp_recv; +static Curl_send scp_send, sftp_send; + +/* + * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to + * do protocol-specific actions at connect-time. + */ +static CURLcode myssh_connect(struct connectdata *conn, bool *done) +{ + struct ssh_conn *ssh; + CURLcode result; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + struct Curl_easy *data = conn->data; + + /* initialize per-handle data if not already */ + if(!data->req.protop) + myssh_setup_connection(conn); + + /* We default to persistent connections. We set this already in this connect + function to make the re-use checks properly be able to check this bit. */ + connkeep(conn, "SSH default"); + + if(conn->handler->protocol & CURLPROTO_SCP) { + conn->recv[FIRSTSOCKET] = scp_recv; + conn->send[FIRSTSOCKET] = scp_send; + } + else { + conn->recv[FIRSTSOCKET] = sftp_recv; + conn->send[FIRSTSOCKET] = sftp_send; + } + + ssh = &conn->proto.sshc; + + ssh->ssh_session = ssh_new(); + if(ssh->ssh_session == NULL) { + failf(data, "Failure initialising ssh session"); + return CURLE_FAILED_INIT; + } + + ssh_options_set(ssh->ssh_session, SSH_OPTIONS_FD, &sock); + + if(conn->user) { + infof(data, "User: %s\n", conn->user); + ssh_options_set(ssh->ssh_session, SSH_OPTIONS_USER, conn->user); + } + + if(data->set.str[STRING_SSH_KNOWNHOSTS]) { + infof(data, "Known hosts: %s\n", data->set.str[STRING_SSH_KNOWNHOSTS]); + ssh_options_set(ssh->ssh_session, SSH_OPTIONS_KNOWNHOSTS, + data->set.str[STRING_SSH_KNOWNHOSTS]); + } + + ssh_options_set(ssh->ssh_session, SSH_OPTIONS_HOST, conn->host.name); + if(conn->remote_port) + ssh_options_set(ssh->ssh_session, SSH_OPTIONS_PORT, + &conn->remote_port); + + if(data->set.ssh_compression) { + ssh_options_set(ssh->ssh_session, SSH_OPTIONS_COMPRESSION, + "zlib,zlib@openssh.com,none"); + } + + ssh->privkey = NULL; + ssh->pubkey = NULL; + + if(data->set.str[STRING_SSH_PUBLIC_KEY]) { + int rc = ssh_pki_import_pubkey_file(data->set.str[STRING_SSH_PUBLIC_KEY], + &ssh->pubkey); + if(rc != SSH_OK) { + failf(data, "Could not load public key file"); + /* ignore */ + } + } + + /* we do not verify here, we do it at the state machine, + * after connection */ + + state(conn, SSH_INIT); + + result = myssh_multi_statemach(conn, done); + + return result; +} + +/* called from multi.c while DOing */ +static CURLcode scp_doing(struct connectdata *conn, bool *dophase_done) +{ + CURLcode result; + + result = myssh_multi_statemach(conn, dophase_done); + + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + return result; +} + +/* + *********************************************************************** + * + * scp_perform() + * + * This is the actual DO function for SCP. Get a file according to + * the options previously setup. + */ + +static +CURLcode scp_perform(struct connectdata *conn, + bool *connected, bool *dophase_done) +{ + CURLcode result = CURLE_OK; + + DEBUGF(infof(conn->data, "DO phase starts\n")); + + *dophase_done = FALSE; /* not done yet */ + + /* start the first command in the DO phase */ + state(conn, SSH_SCP_TRANS_INIT); + + result = myssh_multi_statemach(conn, dophase_done); + + *connected = conn->bits.tcpconnect[FIRSTSOCKET]; + + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + + return result; +} + +static CURLcode myssh_do_it(struct connectdata *conn, bool *done) +{ + CURLcode result; + bool connected = 0; + struct Curl_easy *data = conn->data; + struct ssh_conn *sshc = &conn->proto.sshc; + + *done = FALSE; /* default to false */ + + data->req.size = -1; /* make sure this is unknown at this point */ + + sshc->actualcode = CURLE_OK; /* reset error code */ + sshc->secondCreateDirs = 0; /* reset the create dir attempt state + variable */ + + Curl_pgrsSetUploadCounter(data, 0); + Curl_pgrsSetDownloadCounter(data, 0); + Curl_pgrsSetUploadSize(data, -1); + Curl_pgrsSetDownloadSize(data, -1); + + if(conn->handler->protocol & CURLPROTO_SCP) + result = scp_perform(conn, &connected, done); + else + result = sftp_perform(conn, &connected, done); + + return result; +} + +/* BLOCKING, but the function is using the state machine so the only reason + this is still blocking is that the multi interface code has no support for + disconnecting operations that takes a while */ +static CURLcode scp_disconnect(struct connectdata *conn, + bool dead_connection) +{ + CURLcode result = CURLE_OK; + struct ssh_conn *ssh = &conn->proto.sshc; + (void) dead_connection; + + if(ssh->ssh_session) { + /* only if there's a session still around to use! */ + + state(conn, SSH_SESSION_DISCONNECT); + + result = myssh_block_statemach(conn, TRUE); + } + + return result; +} + +/* generic done function for both SCP and SFTP called from their specific + done functions */ +static CURLcode myssh_done(struct connectdata *conn, CURLcode status) +{ + CURLcode result = CURLE_OK; + struct SSHPROTO *protop = conn->data->req.protop; + + if(!status) { + /* run the state-machine */ + result = myssh_block_statemach(conn, FALSE); + } + else + result = status; + + if(protop) + Curl_safefree(protop->path); + if(Curl_pgrsDone(conn)) + return CURLE_ABORTED_BY_CALLBACK; + + conn->data->req.keepon = 0; /* clear all bits */ + return result; +} + + +static CURLcode scp_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + (void) premature; /* not used */ + + if(!status) + state(conn, SSH_SCP_DONE); + + return myssh_done(conn, status); + +} + +static ssize_t scp_send(struct connectdata *conn, int sockindex, + const void *mem, size_t len, CURLcode *err) +{ + int rc; + (void) sockindex; /* we only support SCP on the fixed known primary socket */ + (void) err; + + rc = ssh_scp_write(conn->proto.sshc.scp_session, mem, len); + +#if 0 + /* The following code is misleading, mostly added as wishful thinking + * that libssh at some point will implement non-blocking ssh_scp_write/read. + * Currently rc can only be number of bytes read or SSH_ERROR. */ + myssh_block2waitfor(conn, (rc == SSH_AGAIN) ? TRUE : FALSE); + + if(rc == SSH_AGAIN) { + *err = CURLE_AGAIN; + return 0; + } + else +#endif + if(rc != SSH_OK) { + *err = CURLE_SSH; + return -1; + } + + return len; +} + +static ssize_t scp_recv(struct connectdata *conn, int sockindex, + char *mem, size_t len, CURLcode *err) +{ + ssize_t nread; + (void) err; + (void) sockindex; /* we only support SCP on the fixed known primary socket */ + + /* libssh returns int */ + nread = ssh_scp_read(conn->proto.sshc.scp_session, mem, len); + +#if 0 + /* The following code is misleading, mostly added as wishful thinking + * that libssh at some point will implement non-blocking ssh_scp_write/read. + * Currently rc can only be SSH_OK or SSH_ERROR. */ + + myssh_block2waitfor(conn, (nread == SSH_AGAIN) ? TRUE : FALSE); + if(nread == SSH_AGAIN) { + *err = CURLE_AGAIN; + nread = -1; + } +#endif + + return nread; +} + +/* + * =============== SFTP =============== + */ + +/* + *********************************************************************** + * + * sftp_perform() + * + * This is the actual DO function for SFTP. Get a file/directory according to + * the options previously setup. + */ + +static +CURLcode sftp_perform(struct connectdata *conn, + bool *connected, + bool *dophase_done) +{ + CURLcode result = CURLE_OK; + + DEBUGF(infof(conn->data, "DO phase starts\n")); + + *dophase_done = FALSE; /* not done yet */ + + /* start the first command in the DO phase */ + state(conn, SSH_SFTP_QUOTE_INIT); + + /* run the state-machine */ + result = myssh_multi_statemach(conn, dophase_done); + + *connected = conn->bits.tcpconnect[FIRSTSOCKET]; + + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + + return result; +} + +/* called from multi.c while DOing */ +static CURLcode sftp_doing(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result = myssh_multi_statemach(conn, dophase_done); + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + return result; +} + +/* BLOCKING, but the function is using the state machine so the only reason + this is still blocking is that the multi interface code has no support for + disconnecting operations that takes a while */ +static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection) +{ + CURLcode result = CURLE_OK; + (void) dead_connection; + + DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n")); + + if(conn->proto.sshc.ssh_session) { + /* only if there's a session still around to use! */ + state(conn, SSH_SFTP_SHUTDOWN); + result = myssh_block_statemach(conn, TRUE); + } + + DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n")); + + return result; + +} + +static CURLcode sftp_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + struct ssh_conn *sshc = &conn->proto.sshc; + + if(!status) { + /* Post quote commands are executed after the SFTP_CLOSE state to avoid + errors that could happen due to open file handles during POSTQUOTE + operation */ + if(!premature && conn->data->set.postquote && !conn->bits.retry) + sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT; + state(conn, SSH_SFTP_CLOSE); + } + return myssh_done(conn, status); +} + +/* return number of sent bytes */ +static ssize_t sftp_send(struct connectdata *conn, int sockindex, + const void *mem, size_t len, CURLcode *err) +{ + ssize_t nwrite; + (void)sockindex; + + nwrite = sftp_write(conn->proto.sshc.sftp_file, mem, len); + + myssh_block2waitfor(conn, FALSE); + +#if 0 /* not returned by libssh on write */ + if(nwrite == SSH_AGAIN) { + *err = CURLE_AGAIN; + nwrite = 0; + } + else +#endif + if(nwrite < 0) { + *err = CURLE_SSH; + nwrite = -1; + } + + return nwrite; +} + +/* + * Return number of received (decrypted) bytes + * or <0 on error + */ +static ssize_t sftp_recv(struct connectdata *conn, int sockindex, + char *mem, size_t len, CURLcode *err) +{ + ssize_t nread; + (void)sockindex; + + DEBUGASSERT(len < CURL_MAX_READ_SIZE); + + switch(conn->proto.sshc.sftp_recv_state) { + case 0: + conn->proto.sshc.sftp_file_index = + sftp_async_read_begin(conn->proto.sshc.sftp_file, + (uint32_t)len); + if(conn->proto.sshc.sftp_file_index < 0) { + *err = CURLE_RECV_ERROR; + return -1; + } + + /* FALLTHROUGH */ + case 1: + conn->proto.sshc.sftp_recv_state = 1; + + nread = sftp_async_read(conn->proto.sshc.sftp_file, + mem, (uint32_t)len, + conn->proto.sshc.sftp_file_index); + + myssh_block2waitfor(conn, (nread == SSH_AGAIN)?TRUE:FALSE); + + if(nread == SSH_AGAIN) { + *err = CURLE_AGAIN; + return -1; + } + else if(nread < 0) { + *err = CURLE_RECV_ERROR; + return -1; + } + + conn->proto.sshc.sftp_recv_state = 0; + return nread; + + default: + /* we never reach here */ + return -1; + } +} + +static void sftp_quote(struct connectdata *conn) +{ + const char *cp; + struct Curl_easy *data = conn->data; + struct SSHPROTO *protop = data->req.protop; + struct ssh_conn *sshc = &conn->proto.sshc; + CURLcode result; + + /* + * Support some of the "FTP" commands + */ + char *cmd = sshc->quote_item->data; + sshc->acceptfail = FALSE; + + /* if a command starts with an asterisk, which a legal SFTP command never + can, the command will be allowed to fail without it causing any + aborts or cancels etc. It will cause libcurl to act as if the command + is successful, whatever the server reponds. */ + + if(cmd[0] == '*') { + cmd++; + sshc->acceptfail = TRUE; + } + + if(strcasecompare("pwd", cmd)) { + /* output debug output if that is requested */ + char *tmp = aprintf("257 \"%s\" is current directory.\n", + protop->path); + if(!tmp) { + sshc->actualcode = CURLE_OUT_OF_MEMORY; + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + return; + } + if(data->set.verbose) { + Curl_debug(data, CURLINFO_HEADER_OUT, (char *) "PWD\n", 4); + Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp)); + } + /* this sends an FTP-like "header" to the header callback so that the + current directory can be read very similar to how it is read when + using ordinary FTP. */ + result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp)); + free(tmp); + if(result) { + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + } + else + state(conn, SSH_SFTP_NEXT_QUOTE); + return; + } + + /* + * the arguments following the command must be separated from the + * command with a space so we can check for it unconditionally + */ + cp = strchr(cmd, ' '); + if(cp == NULL) { + failf(data, "Syntax error in SFTP command. Supply parameter(s)!"); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + return; + } + + /* + * also, every command takes at least one argument so we get that + * first argument right now + */ + result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, "Syntax error: Bad first parameter"); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + return; + } + + /* + * SFTP is a binary protocol, so we don't send text commands + * to the server. Instead, we scan for commands used by + * OpenSSH's sftp program and call the appropriate libssh + * functions. + */ + if(strncasecompare(cmd, "chgrp ", 6) || + strncasecompare(cmd, "chmod ", 6) || + strncasecompare(cmd, "chown ", 6)) { + /* attribute change */ + + /* sshc->quote_path1 contains the mode to set */ + /* get the destination */ + result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, "Syntax error in chgrp/chmod/chown: " + "Bad second parameter"); + Curl_safefree(sshc->quote_path1); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + return; + } + sshc->quote_attrs = NULL; + state(conn, SSH_SFTP_QUOTE_STAT); + return; + } + if(strncasecompare(cmd, "ln ", 3) || + strncasecompare(cmd, "symlink ", 8)) { + /* symbolic linking */ + /* sshc->quote_path1 is the source */ + /* get the destination */ + result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, "Syntax error in ln/symlink: Bad second parameter"); + Curl_safefree(sshc->quote_path1); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + return; + } + state(conn, SSH_SFTP_QUOTE_SYMLINK); + return; + } + else if(strncasecompare(cmd, "mkdir ", 6)) { + /* create dir */ + state(conn, SSH_SFTP_QUOTE_MKDIR); + return; + } + else if(strncasecompare(cmd, "rename ", 7)) { + /* rename file */ + /* first param is the source path */ + /* second param is the dest. path */ + result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, "Syntax error in rename: Bad second parameter"); + Curl_safefree(sshc->quote_path1); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + return; + } + state(conn, SSH_SFTP_QUOTE_RENAME); + return; + } + else if(strncasecompare(cmd, "rmdir ", 6)) { + /* delete dir */ + state(conn, SSH_SFTP_QUOTE_RMDIR); + return; + } + else if(strncasecompare(cmd, "rm ", 3)) { + state(conn, SSH_SFTP_QUOTE_UNLINK); + return; + } +#ifdef HAS_STATVFS_SUPPORT + else if(strncasecompare(cmd, "statvfs ", 8)) { + state(conn, SSH_SFTP_QUOTE_STATVFS); + return; + } +#endif + + failf(data, "Unknown SFTP command"); + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; +} + +static void sftp_quote_stat(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + struct ssh_conn *sshc = &conn->proto.sshc; + char *cmd = sshc->quote_item->data; + sshc->acceptfail = FALSE; + + /* if a command starts with an asterisk, which a legal SFTP command never + can, the command will be allowed to fail without it causing any + aborts or cancels etc. It will cause libcurl to act as if the command + is successful, whatever the server reponds. */ + + if(cmd[0] == '*') { + cmd++; + sshc->acceptfail = TRUE; + } + + /* We read the file attributes, store them in sshc->quote_attrs + * and modify them accordingly to command. Then we switch to + * QUOTE_SETSTAT state to write new ones. + */ + + if(sshc->quote_attrs) + sftp_attributes_free(sshc->quote_attrs); + sshc->quote_attrs = sftp_stat(sshc->sftp_session, sshc->quote_path2); + if(sshc->quote_attrs == NULL) { + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "Attempt to get SFTP stats failed: %d", + sftp_get_error(sshc->sftp_session)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + return; + } + + /* Now set the new attributes... */ + if(strncasecompare(cmd, "chgrp", 5)) { + sshc->quote_attrs->gid = (uint32_t)strtoul(sshc->quote_path1, NULL, 10); + if(sshc->quote_attrs->gid == 0 && !ISDIGIT(sshc->quote_path1[0]) && + !sshc->acceptfail) { + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "Syntax error: chgrp gid not a number"); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + return; + } + sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID; + } + else if(strncasecompare(cmd, "chmod", 5)) { + mode_t perms; + perms = (mode_t)strtoul(sshc->quote_path1, NULL, 8); + /* permissions are octal */ + if(perms == 0 && !ISDIGIT(sshc->quote_path1[0])) { + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "Syntax error: chmod permissions not a number"); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + return; + } + sshc->quote_attrs->permissions = perms; + sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_PERMISSIONS; + } + else if(strncasecompare(cmd, "chown", 5)) { + sshc->quote_attrs->uid = (uint32_t)strtoul(sshc->quote_path1, NULL, 10); + if(sshc->quote_attrs->uid == 0 && !ISDIGIT(sshc->quote_path1[0]) && + !sshc->acceptfail) { + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "Syntax error: chown uid not a number"); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + return; + } + sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID; + } + + /* Now send the completed structure... */ + state(conn, SSH_SFTP_QUOTE_SETSTAT); + return; +} + + +#endif /* USE_LIBSSH */ diff --git a/dependencies/cmcurl/lib/ssh.c b/dependencies/cmcurl/lib/ssh.c new file mode 100644 index 0000000..a265c3c --- /dev/null +++ b/dependencies/cmcurl/lib/ssh.c @@ -0,0 +1,3337 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* #define CURL_LIBSSH2_DEBUG */ + +#include "curl_setup.h" + +#ifdef USE_LIBSSH2 + +#include + +#include +#include + +#ifdef HAVE_FCNTL_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_UTSNAME_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +#include +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "progress.h" +#include "transfer.h" +#include "escape.h" +#include "http.h" /* for HTTP proxy tunnel stuff */ +#include "ssh.h" +#include "url.h" +#include "speedcheck.h" +#include "getinfo.h" +#include "strdup.h" +#include "strcase.h" +#include "vtls/vtls.h" +#include "connect.h" +#include "strerror.h" +#include "inet_ntop.h" +#include "parsedate.h" /* for the week day and month names */ +#include "sockaddr.h" /* required for Curl_sockaddr_storage */ +#include "strtoofft.h" +#include "multiif.h" +#include "select.h" +#include "warnless.h" +#include "curl_path.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#if LIBSSH2_VERSION_NUM >= 0x010206 +/* libssh2_sftp_statvfs and friends were added in 1.2.6 */ +#define HAS_STATVFS_SUPPORT 1 +#endif + +#define sftp_libssh2_last_error(s) curlx_ultosi(libssh2_sftp_last_error(s)) + +#define sftp_libssh2_realpath(s,p,t,m) \ + libssh2_sftp_symlink_ex((s), (p), curlx_uztoui(strlen(p)), \ + (t), (m), LIBSSH2_SFTP_REALPATH) + + +/* Local functions: */ +static const char *sftp_libssh2_strerror(int err); +static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc); +static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc); +static LIBSSH2_FREE_FUNC(my_libssh2_free); + +static CURLcode ssh_connect(struct connectdata *conn, bool *done); +static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done); +static CURLcode ssh_do(struct connectdata *conn, bool *done); + +static CURLcode scp_done(struct connectdata *conn, + CURLcode, bool premature); +static CURLcode scp_doing(struct connectdata *conn, + bool *dophase_done); +static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection); + +static CURLcode sftp_done(struct connectdata *conn, + CURLcode, bool premature); +static CURLcode sftp_doing(struct connectdata *conn, + bool *dophase_done); +static CURLcode sftp_disconnect(struct connectdata *conn, bool dead); +static +CURLcode sftp_perform(struct connectdata *conn, + bool *connected, + bool *dophase_done); + +static int ssh_getsock(struct connectdata *conn, + curl_socket_t *sock, /* points to numsocks number + of sockets */ + int numsocks); + +static int ssh_perform_getsock(const struct connectdata *conn, + curl_socket_t *sock, /* points to numsocks + number of sockets */ + int numsocks); + +static CURLcode ssh_setup_connection(struct connectdata *conn); + +/* + * SCP protocol handler. + */ + +const struct Curl_handler Curl_handler_scp = { + "SCP", /* scheme */ + ssh_setup_connection, /* setup_connection */ + ssh_do, /* do_it */ + scp_done, /* done */ + ZERO_NULL, /* do_more */ + ssh_connect, /* connect_it */ + ssh_multi_statemach, /* connecting */ + scp_doing, /* doing */ + ssh_getsock, /* proto_getsock */ + ssh_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ssh_perform_getsock, /* perform_getsock */ + scp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_SSH, /* defport */ + CURLPROTO_SCP, /* protocol */ + PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION + | PROTOPT_NOURLQUERY /* flags */ +}; + + +/* + * SFTP protocol handler. + */ + +const struct Curl_handler Curl_handler_sftp = { + "SFTP", /* scheme */ + ssh_setup_connection, /* setup_connection */ + ssh_do, /* do_it */ + sftp_done, /* done */ + ZERO_NULL, /* do_more */ + ssh_connect, /* connect_it */ + ssh_multi_statemach, /* connecting */ + sftp_doing, /* doing */ + ssh_getsock, /* proto_getsock */ + ssh_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ssh_perform_getsock, /* perform_getsock */ + sftp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_SSH, /* defport */ + CURLPROTO_SFTP, /* protocol */ + PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION + | PROTOPT_NOURLQUERY /* flags */ +}; + +static void +kbd_callback(const char *name, int name_len, const char *instruction, + int instruction_len, int num_prompts, + const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts, + LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses, + void **abstract) +{ + struct connectdata *conn = (struct connectdata *)*abstract; + +#ifdef CURL_LIBSSH2_DEBUG + fprintf(stderr, "name=%s\n", name); + fprintf(stderr, "name_len=%d\n", name_len); + fprintf(stderr, "instruction=%s\n", instruction); + fprintf(stderr, "instruction_len=%d\n", instruction_len); + fprintf(stderr, "num_prompts=%d\n", num_prompts); +#else + (void)name; + (void)name_len; + (void)instruction; + (void)instruction_len; +#endif /* CURL_LIBSSH2_DEBUG */ + if(num_prompts == 1) { + responses[0].text = strdup(conn->passwd); + responses[0].length = curlx_uztoui(strlen(conn->passwd)); + } + (void)prompts; + (void)abstract; +} /* kbd_callback */ + +static CURLcode sftp_libssh2_error_to_CURLE(int err) +{ + switch(err) { + case LIBSSH2_FX_OK: + return CURLE_OK; + + case LIBSSH2_FX_NO_SUCH_FILE: + case LIBSSH2_FX_NO_SUCH_PATH: + return CURLE_REMOTE_FILE_NOT_FOUND; + + case LIBSSH2_FX_PERMISSION_DENIED: + case LIBSSH2_FX_WRITE_PROTECT: + case LIBSSH2_FX_LOCK_CONFlICT: + return CURLE_REMOTE_ACCESS_DENIED; + + case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM: + case LIBSSH2_FX_QUOTA_EXCEEDED: + return CURLE_REMOTE_DISK_FULL; + + case LIBSSH2_FX_FILE_ALREADY_EXISTS: + return CURLE_REMOTE_FILE_EXISTS; + + case LIBSSH2_FX_DIR_NOT_EMPTY: + return CURLE_QUOTE_ERROR; + + default: + break; + } + + return CURLE_SSH; +} + +static CURLcode libssh2_session_error_to_CURLE(int err) +{ + switch(err) { + /* Ordered by order of appearance in libssh2.h */ + case LIBSSH2_ERROR_NONE: + return CURLE_OK; + + /* This is the error returned by libssh2_scp_recv2 + * on unknown file */ + case LIBSSH2_ERROR_SCP_PROTOCOL: + return CURLE_REMOTE_FILE_NOT_FOUND; + + case LIBSSH2_ERROR_SOCKET_NONE: + return CURLE_COULDNT_CONNECT; + + case LIBSSH2_ERROR_ALLOC: + return CURLE_OUT_OF_MEMORY; + + case LIBSSH2_ERROR_SOCKET_SEND: + return CURLE_SEND_ERROR; + + case LIBSSH2_ERROR_HOSTKEY_INIT: + case LIBSSH2_ERROR_HOSTKEY_SIGN: + case LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED: + case LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED: + return CURLE_PEER_FAILED_VERIFICATION; + + case LIBSSH2_ERROR_PASSWORD_EXPIRED: + return CURLE_LOGIN_DENIED; + + case LIBSSH2_ERROR_SOCKET_TIMEOUT: + case LIBSSH2_ERROR_TIMEOUT: + return CURLE_OPERATION_TIMEDOUT; + + case LIBSSH2_ERROR_EAGAIN: + return CURLE_AGAIN; + } + + return CURLE_SSH; +} + +static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc) +{ + (void)abstract; /* arg not used */ + return malloc(count); +} + +static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc) +{ + (void)abstract; /* arg not used */ + return realloc(ptr, count); +} + +static LIBSSH2_FREE_FUNC(my_libssh2_free) +{ + (void)abstract; /* arg not used */ + if(ptr) /* ssh2 agent sometimes call free with null ptr */ + free(ptr); +} + +/* + * SSH State machine related code + */ +/* This is the ONLY way to change SSH state! */ +static void state(struct connectdata *conn, sshstate nowstate) +{ + struct ssh_conn *sshc = &conn->proto.sshc; +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* for debug purposes */ + static const char * const names[] = { + "SSH_STOP", + "SSH_INIT", + "SSH_S_STARTUP", + "SSH_HOSTKEY", + "SSH_AUTHLIST", + "SSH_AUTH_PKEY_INIT", + "SSH_AUTH_PKEY", + "SSH_AUTH_PASS_INIT", + "SSH_AUTH_PASS", + "SSH_AUTH_AGENT_INIT", + "SSH_AUTH_AGENT_LIST", + "SSH_AUTH_AGENT", + "SSH_AUTH_HOST_INIT", + "SSH_AUTH_HOST", + "SSH_AUTH_KEY_INIT", + "SSH_AUTH_KEY", + "SSH_AUTH_GSSAPI", + "SSH_AUTH_DONE", + "SSH_SFTP_INIT", + "SSH_SFTP_REALPATH", + "SSH_SFTP_QUOTE_INIT", + "SSH_SFTP_POSTQUOTE_INIT", + "SSH_SFTP_QUOTE", + "SSH_SFTP_NEXT_QUOTE", + "SSH_SFTP_QUOTE_STAT", + "SSH_SFTP_QUOTE_SETSTAT", + "SSH_SFTP_QUOTE_SYMLINK", + "SSH_SFTP_QUOTE_MKDIR", + "SSH_SFTP_QUOTE_RENAME", + "SSH_SFTP_QUOTE_RMDIR", + "SSH_SFTP_QUOTE_UNLINK", + "SSH_SFTP_QUOTE_STATVFS", + "SSH_SFTP_GETINFO", + "SSH_SFTP_FILETIME", + "SSH_SFTP_TRANS_INIT", + "SSH_SFTP_UPLOAD_INIT", + "SSH_SFTP_CREATE_DIRS_INIT", + "SSH_SFTP_CREATE_DIRS", + "SSH_SFTP_CREATE_DIRS_MKDIR", + "SSH_SFTP_READDIR_INIT", + "SSH_SFTP_READDIR", + "SSH_SFTP_READDIR_LINK", + "SSH_SFTP_READDIR_BOTTOM", + "SSH_SFTP_READDIR_DONE", + "SSH_SFTP_DOWNLOAD_INIT", + "SSH_SFTP_DOWNLOAD_STAT", + "SSH_SFTP_CLOSE", + "SSH_SFTP_SHUTDOWN", + "SSH_SCP_TRANS_INIT", + "SSH_SCP_UPLOAD_INIT", + "SSH_SCP_DOWNLOAD_INIT", + "SSH_SCP_DOWNLOAD", + "SSH_SCP_DONE", + "SSH_SCP_SEND_EOF", + "SSH_SCP_WAIT_EOF", + "SSH_SCP_WAIT_CLOSE", + "SSH_SCP_CHANNEL_FREE", + "SSH_SESSION_DISCONNECT", + "SSH_SESSION_FREE", + "QUIT" + }; + + /* a precaution to make sure the lists are in sync */ + DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST); + + if(sshc->state != nowstate) { + infof(conn->data, "SFTP %p state change from %s to %s\n", + (void *)sshc, names[sshc->state], names[nowstate]); + } +#endif + + sshc->state = nowstate; +} + + +#ifdef HAVE_LIBSSH2_KNOWNHOST_API +static int sshkeycallback(struct Curl_easy *easy, + const struct curl_khkey *knownkey, /* known */ + const struct curl_khkey *foundkey, /* found */ + enum curl_khmatch match, + void *clientp) +{ + (void)easy; + (void)knownkey; + (void)foundkey; + (void)clientp; + + /* we only allow perfect matches, and we reject everything else */ + return (match != CURLKHMATCH_OK)?CURLKHSTAT_REJECT:CURLKHSTAT_FINE; +} +#endif + +/* + * Earlier libssh2 versions didn't have the ability to seek to 64bit positions + * with 32bit size_t. + */ +#ifdef HAVE_LIBSSH2_SFTP_SEEK64 +#define SFTP_SEEK(x,y) libssh2_sftp_seek64(x, (libssh2_uint64_t)y) +#else +#define SFTP_SEEK(x,y) libssh2_sftp_seek(x, (size_t)y) +#endif + +/* + * Earlier libssh2 versions didn't do SCP properly beyond 32bit sizes on 32bit + * architectures so we check of the necessary function is present. + */ +#ifndef HAVE_LIBSSH2_SCP_SEND64 +#define SCP_SEND(a,b,c,d) libssh2_scp_send_ex(a, b, (int)(c), (size_t)d, 0, 0) +#else +#define SCP_SEND(a,b,c,d) libssh2_scp_send64(a, b, (int)(c), \ + (libssh2_uint64_t)d, 0, 0) +#endif + +/* + * libssh2 1.2.8 fixed the problem with 32bit ints used for sockets on win64. + */ +#ifdef HAVE_LIBSSH2_SESSION_HANDSHAKE +#define libssh2_session_startup(x,y) libssh2_session_handshake(x,y) +#endif + +static CURLcode ssh_knownhost(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + +#ifdef HAVE_LIBSSH2_KNOWNHOST_API + struct Curl_easy *data = conn->data; + + if(data->set.str[STRING_SSH_KNOWNHOSTS]) { + /* we're asked to verify the host against a file */ + struct ssh_conn *sshc = &conn->proto.sshc; + int rc; + int keytype; + size_t keylen; + const char *remotekey = libssh2_session_hostkey(sshc->ssh_session, + &keylen, &keytype); + int keycheck = LIBSSH2_KNOWNHOST_CHECK_FAILURE; + int keybit = 0; + + if(remotekey) { + /* + * A subject to figure out is what host name we need to pass in here. + * What host name does OpenSSH store in its file if an IDN name is + * used? + */ + struct libssh2_knownhost *host; + enum curl_khmatch keymatch; + curl_sshkeycallback func = + data->set.ssh_keyfunc?data->set.ssh_keyfunc:sshkeycallback; + struct curl_khkey knownkey; + struct curl_khkey *knownkeyp = NULL; + struct curl_khkey foundkey; + + keybit = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)? + LIBSSH2_KNOWNHOST_KEY_SSHRSA:LIBSSH2_KNOWNHOST_KEY_SSHDSS; + +#ifdef HAVE_LIBSSH2_KNOWNHOST_CHECKP + keycheck = libssh2_knownhost_checkp(sshc->kh, + conn->host.name, + (conn->remote_port != PORT_SSH)? + conn->remote_port:-1, + remotekey, keylen, + LIBSSH2_KNOWNHOST_TYPE_PLAIN| + LIBSSH2_KNOWNHOST_KEYENC_RAW| + keybit, + &host); +#else + keycheck = libssh2_knownhost_check(sshc->kh, + conn->host.name, + remotekey, keylen, + LIBSSH2_KNOWNHOST_TYPE_PLAIN| + LIBSSH2_KNOWNHOST_KEYENC_RAW| + keybit, + &host); +#endif + + infof(data, "SSH host check: %d, key: %s\n", keycheck, + (keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)? + host->key:""); + + /* setup 'knownkey' */ + if(keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH) { + knownkey.key = host->key; + knownkey.len = 0; + knownkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)? + CURLKHTYPE_RSA : CURLKHTYPE_DSS; + knownkeyp = &knownkey; + } + + /* setup 'foundkey' */ + foundkey.key = remotekey; + foundkey.len = keylen; + foundkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)? + CURLKHTYPE_RSA : CURLKHTYPE_DSS; + + /* + * if any of the LIBSSH2_KNOWNHOST_CHECK_* defines and the + * curl_khmatch enum are ever modified, we need to introduce a + * translation table here! + */ + keymatch = (enum curl_khmatch)keycheck; + + /* Ask the callback how to behave */ + Curl_set_in_callback(data, true); + rc = func(data, knownkeyp, /* from the knownhosts file */ + &foundkey, /* from the remote host */ + keymatch, data->set.ssh_keyfunc_userp); + Curl_set_in_callback(data, false); + } + else + /* no remotekey means failure! */ + rc = CURLKHSTAT_REJECT; + + switch(rc) { + default: /* unknown return codes will equal reject */ + /* FALLTHROUGH */ + case CURLKHSTAT_REJECT: + state(conn, SSH_SESSION_FREE); + /* FALLTHROUGH */ + case CURLKHSTAT_DEFER: + /* DEFER means bail out but keep the SSH_HOSTKEY state */ + result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; + break; + case CURLKHSTAT_FINE: + case CURLKHSTAT_FINE_ADD_TO_FILE: + /* proceed */ + if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) { + /* the found host+key didn't match but has been told to be fine + anyway so we add it in memory */ + int addrc = libssh2_knownhost_add(sshc->kh, + conn->host.name, NULL, + remotekey, keylen, + LIBSSH2_KNOWNHOST_TYPE_PLAIN| + LIBSSH2_KNOWNHOST_KEYENC_RAW| + keybit, NULL); + if(addrc) + infof(data, "Warning adding the known host %s failed!\n", + conn->host.name); + else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE) { + /* now we write the entire in-memory list of known hosts to the + known_hosts file */ + int wrc = + libssh2_knownhost_writefile(sshc->kh, + data->set.str[STRING_SSH_KNOWNHOSTS], + LIBSSH2_KNOWNHOST_FILE_OPENSSH); + if(wrc) { + infof(data, "Warning, writing %s failed!\n", + data->set.str[STRING_SSH_KNOWNHOSTS]); + } + } + } + break; + } + } +#else /* HAVE_LIBSSH2_KNOWNHOST_API */ + (void)conn; +#endif + return result; +} + +static CURLcode ssh_check_fingerprint(struct connectdata *conn) +{ + struct ssh_conn *sshc = &conn->proto.sshc; + struct Curl_easy *data = conn->data; + const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]; + char md5buffer[33]; + + const char *fingerprint = libssh2_hostkey_hash(sshc->ssh_session, + LIBSSH2_HOSTKEY_HASH_MD5); + + if(fingerprint) { + /* The fingerprint points to static storage (!), don't free() it. */ + int i; + for(i = 0; i < 16; i++) + msnprintf(&md5buffer[i*2], 3, "%02x", (unsigned char) fingerprint[i]); + infof(data, "SSH MD5 fingerprint: %s\n", md5buffer); + } + + /* Before we authenticate we check the hostkey's MD5 fingerprint + * against a known fingerprint, if available. + */ + if(pubkey_md5 && strlen(pubkey_md5) == 32) { + if(!fingerprint || !strcasecompare(md5buffer, pubkey_md5)) { + if(fingerprint) + failf(data, + "Denied establishing ssh session: mismatch md5 fingerprint. " + "Remote %s is not equal to %s", md5buffer, pubkey_md5); + else + failf(data, + "Denied establishing ssh session: md5 fingerprint not available"); + state(conn, SSH_SESSION_FREE); + sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; + return sshc->actualcode; + } + infof(data, "MD5 checksum match!\n"); + /* as we already matched, we skip the check for known hosts */ + return CURLE_OK; + } + return ssh_knownhost(conn); +} + +/* + * ssh_statemach_act() runs the SSH state machine as far as it can without + * blocking and without reaching the end. The data the pointer 'block' points + * to will be set to TRUE if the libssh2 function returns LIBSSH2_ERROR_EAGAIN + * meaning it wants to be called again when the socket is ready + */ + +static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct SSHPROTO *sftp_scp = data->req.protop; + struct ssh_conn *sshc = &conn->proto.sshc; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + char *new_readdir_line; + int rc = LIBSSH2_ERROR_NONE; + int err; + int seekerr = CURL_SEEKFUNC_OK; + *block = 0; /* we're not blocking by default */ + + do { + + switch(sshc->state) { + case SSH_INIT: + sshc->secondCreateDirs = 0; + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_OK; + + /* Set libssh2 to non-blocking, since everything internally is + non-blocking */ + libssh2_session_set_blocking(sshc->ssh_session, 0); + + state(conn, SSH_S_STARTUP); + /* FALLTHROUGH */ + + case SSH_S_STARTUP: + rc = libssh2_session_startup(sshc->ssh_session, (int)sock); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc) { + char *err_msg = NULL; + (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); + failf(data, "Failure establishing ssh session: %d, %s", rc, err_msg); + + state(conn, SSH_SESSION_FREE); + sshc->actualcode = CURLE_FAILED_INIT; + break; + } + + state(conn, SSH_HOSTKEY); + + /* FALLTHROUGH */ + case SSH_HOSTKEY: + /* + * Before we authenticate we should check the hostkey's fingerprint + * against our known hosts. How that is handled (reading from file, + * whatever) is up to us. + */ + result = ssh_check_fingerprint(conn); + if(!result) + state(conn, SSH_AUTHLIST); + /* ssh_check_fingerprint sets state appropriately on error */ + break; + + case SSH_AUTHLIST: + /* + * Figure out authentication methods + * NB: As soon as we have provided a username to an openssh server we + * must never change it later. Thus, always specify the correct username + * here, even though the libssh2 docs kind of indicate that it should be + * possible to get a 'generic' list (not user-specific) of authentication + * methods, presumably with a blank username. That won't work in my + * experience. + * So always specify it here. + */ + sshc->authlist = libssh2_userauth_list(sshc->ssh_session, + conn->user, + curlx_uztoui(strlen(conn->user))); + + if(!sshc->authlist) { + if(libssh2_userauth_authenticated(sshc->ssh_session)) { + sshc->authed = TRUE; + infof(data, "SSH user accepted with no authentication\n"); + state(conn, SSH_AUTH_DONE); + break; + } + err = libssh2_session_last_errno(sshc->ssh_session); + if(err == LIBSSH2_ERROR_EAGAIN) + rc = LIBSSH2_ERROR_EAGAIN; + else { + state(conn, SSH_SESSION_FREE); + sshc->actualcode = libssh2_session_error_to_CURLE(err); + } + break; + } + infof(data, "SSH authentication methods available: %s\n", + sshc->authlist); + + state(conn, SSH_AUTH_PKEY_INIT); + break; + + case SSH_AUTH_PKEY_INIT: + /* + * Check the supported auth types in the order I feel is most secure + * with the requested type of authentication + */ + sshc->authed = FALSE; + + if((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) && + (strstr(sshc->authlist, "publickey") != NULL)) { + bool out_of_memory = FALSE; + + sshc->rsa_pub = sshc->rsa = NULL; + + if(data->set.str[STRING_SSH_PRIVATE_KEY]) + sshc->rsa = strdup(data->set.str[STRING_SSH_PRIVATE_KEY]); + else { + /* To ponder about: should really the lib be messing about with the + HOME environment variable etc? */ + char *home = curl_getenv("HOME"); + + /* If no private key file is specified, try some common paths. */ + if(home) { + /* Try ~/.ssh first. */ + sshc->rsa = aprintf("%s/.ssh/id_rsa", home); + if(!sshc->rsa) + out_of_memory = TRUE; + else if(access(sshc->rsa, R_OK) != 0) { + Curl_safefree(sshc->rsa); + sshc->rsa = aprintf("%s/.ssh/id_dsa", home); + if(!sshc->rsa) + out_of_memory = TRUE; + else if(access(sshc->rsa, R_OK) != 0) { + Curl_safefree(sshc->rsa); + } + } + free(home); + } + if(!out_of_memory && !sshc->rsa) { + /* Nothing found; try the current dir. */ + sshc->rsa = strdup("id_rsa"); + if(sshc->rsa && access(sshc->rsa, R_OK) != 0) { + Curl_safefree(sshc->rsa); + sshc->rsa = strdup("id_dsa"); + if(sshc->rsa && access(sshc->rsa, R_OK) != 0) { + Curl_safefree(sshc->rsa); + /* Out of guesses. Set to the empty string to avoid + * surprising info messages. */ + sshc->rsa = strdup(""); + } + } + } + } + + /* + * Unless the user explicitly specifies a public key file, let + * libssh2 extract the public key from the private key file. + * This is done by simply passing sshc->rsa_pub = NULL. + */ + if(data->set.str[STRING_SSH_PUBLIC_KEY] + /* treat empty string the same way as NULL */ + && data->set.str[STRING_SSH_PUBLIC_KEY][0]) { + sshc->rsa_pub = strdup(data->set.str[STRING_SSH_PUBLIC_KEY]); + if(!sshc->rsa_pub) + out_of_memory = TRUE; + } + + if(out_of_memory || sshc->rsa == NULL) { + Curl_safefree(sshc->rsa); + Curl_safefree(sshc->rsa_pub); + state(conn, SSH_SESSION_FREE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + + sshc->passphrase = data->set.ssl.key_passwd; + if(!sshc->passphrase) + sshc->passphrase = ""; + + if(sshc->rsa_pub) + infof(data, "Using SSH public key file '%s'\n", sshc->rsa_pub); + infof(data, "Using SSH private key file '%s'\n", sshc->rsa); + + state(conn, SSH_AUTH_PKEY); + } + else { + state(conn, SSH_AUTH_PASS_INIT); + } + break; + + case SSH_AUTH_PKEY: + /* The function below checks if the files exists, no need to stat() here. + */ + rc = libssh2_userauth_publickey_fromfile_ex(sshc->ssh_session, + conn->user, + curlx_uztoui( + strlen(conn->user)), + sshc->rsa_pub, + sshc->rsa, sshc->passphrase); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + + Curl_safefree(sshc->rsa_pub); + Curl_safefree(sshc->rsa); + + if(rc == 0) { + sshc->authed = TRUE; + infof(data, "Initialized SSH public key authentication\n"); + state(conn, SSH_AUTH_DONE); + } + else { + char *err_msg = NULL; + (void)libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0); + infof(data, "SSH public key authentication failed: %s\n", err_msg); + state(conn, SSH_AUTH_PASS_INIT); + rc = 0; /* clear rc and continue */ + } + break; + + case SSH_AUTH_PASS_INIT: + if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) && + (strstr(sshc->authlist, "password") != NULL)) { + state(conn, SSH_AUTH_PASS); + } + else { + state(conn, SSH_AUTH_HOST_INIT); + rc = 0; /* clear rc and continue */ + } + break; + + case SSH_AUTH_PASS: + rc = libssh2_userauth_password_ex(sshc->ssh_session, conn->user, + curlx_uztoui(strlen(conn->user)), + conn->passwd, + curlx_uztoui(strlen(conn->passwd)), + NULL); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc == 0) { + sshc->authed = TRUE; + infof(data, "Initialized password authentication\n"); + state(conn, SSH_AUTH_DONE); + } + else { + state(conn, SSH_AUTH_HOST_INIT); + rc = 0; /* clear rc and continue */ + } + break; + + case SSH_AUTH_HOST_INIT: + if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) && + (strstr(sshc->authlist, "hostbased") != NULL)) { + state(conn, SSH_AUTH_HOST); + } + else { + state(conn, SSH_AUTH_AGENT_INIT); + } + break; + + case SSH_AUTH_HOST: + state(conn, SSH_AUTH_AGENT_INIT); + break; + + case SSH_AUTH_AGENT_INIT: +#ifdef HAVE_LIBSSH2_AGENT_API + if((data->set.ssh_auth_types & CURLSSH_AUTH_AGENT) + && (strstr(sshc->authlist, "publickey") != NULL)) { + + /* Connect to the ssh-agent */ + /* The agent could be shared by a curl thread i believe + but nothing obvious as keys can be added/removed at any time */ + if(!sshc->ssh_agent) { + sshc->ssh_agent = libssh2_agent_init(sshc->ssh_session); + if(!sshc->ssh_agent) { + infof(data, "Could not create agent object\n"); + + state(conn, SSH_AUTH_KEY_INIT); + break; + } + } + + rc = libssh2_agent_connect(sshc->ssh_agent); + if(rc == LIBSSH2_ERROR_EAGAIN) + break; + if(rc < 0) { + infof(data, "Failure connecting to agent\n"); + state(conn, SSH_AUTH_KEY_INIT); + rc = 0; /* clear rc and continue */ + } + else { + state(conn, SSH_AUTH_AGENT_LIST); + } + } + else +#endif /* HAVE_LIBSSH2_AGENT_API */ + state(conn, SSH_AUTH_KEY_INIT); + break; + + case SSH_AUTH_AGENT_LIST: +#ifdef HAVE_LIBSSH2_AGENT_API + rc = libssh2_agent_list_identities(sshc->ssh_agent); + + if(rc == LIBSSH2_ERROR_EAGAIN) + break; + if(rc < 0) { + infof(data, "Failure requesting identities to agent\n"); + state(conn, SSH_AUTH_KEY_INIT); + rc = 0; /* clear rc and continue */ + } + else { + state(conn, SSH_AUTH_AGENT); + sshc->sshagent_prev_identity = NULL; + } +#endif + break; + + case SSH_AUTH_AGENT: +#ifdef HAVE_LIBSSH2_AGENT_API + /* as prev_identity evolves only after an identity user auth finished we + can safely request it again as long as EAGAIN is returned here or by + libssh2_agent_userauth */ + rc = libssh2_agent_get_identity(sshc->ssh_agent, + &sshc->sshagent_identity, + sshc->sshagent_prev_identity); + if(rc == LIBSSH2_ERROR_EAGAIN) + break; + + if(rc == 0) { + rc = libssh2_agent_userauth(sshc->ssh_agent, conn->user, + sshc->sshagent_identity); + + if(rc < 0) { + if(rc != LIBSSH2_ERROR_EAGAIN) { + /* tried and failed? go to next identity */ + sshc->sshagent_prev_identity = sshc->sshagent_identity; + } + break; + } + } + + if(rc < 0) + infof(data, "Failure requesting identities to agent\n"); + else if(rc == 1) + infof(data, "No identity would match\n"); + + if(rc == LIBSSH2_ERROR_NONE) { + sshc->authed = TRUE; + infof(data, "Agent based authentication successful\n"); + state(conn, SSH_AUTH_DONE); + } + else { + state(conn, SSH_AUTH_KEY_INIT); + rc = 0; /* clear rc and continue */ + } +#endif + break; + + case SSH_AUTH_KEY_INIT: + if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) + && (strstr(sshc->authlist, "keyboard-interactive") != NULL)) { + state(conn, SSH_AUTH_KEY); + } + else { + state(conn, SSH_AUTH_DONE); + } + break; + + case SSH_AUTH_KEY: + /* Authentication failed. Continue with keyboard-interactive now. */ + rc = libssh2_userauth_keyboard_interactive_ex(sshc->ssh_session, + conn->user, + curlx_uztoui( + strlen(conn->user)), + &kbd_callback); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc == 0) { + sshc->authed = TRUE; + infof(data, "Initialized keyboard interactive authentication\n"); + } + state(conn, SSH_AUTH_DONE); + break; + + case SSH_AUTH_DONE: + if(!sshc->authed) { + failf(data, "Authentication failure"); + state(conn, SSH_SESSION_FREE); + sshc->actualcode = CURLE_LOGIN_DENIED; + break; + } + + /* + * At this point we have an authenticated ssh session. + */ + infof(data, "Authentication complete\n"); + + Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSH is connected */ + + conn->sockfd = sock; + conn->writesockfd = CURL_SOCKET_BAD; + + if(conn->handler->protocol == CURLPROTO_SFTP) { + state(conn, SSH_SFTP_INIT); + break; + } + infof(data, "SSH CONNECT phase done\n"); + state(conn, SSH_STOP); + break; + + case SSH_SFTP_INIT: + /* + * Start the libssh2 sftp session + */ + sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session); + if(!sshc->sftp_session) { + char *err_msg = NULL; + if(libssh2_session_last_errno(sshc->ssh_session) == + LIBSSH2_ERROR_EAGAIN) { + rc = LIBSSH2_ERROR_EAGAIN; + break; + } + + (void)libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0); + failf(data, "Failure initializing sftp session: %s", err_msg); + state(conn, SSH_SESSION_FREE); + sshc->actualcode = CURLE_FAILED_INIT; + break; + } + state(conn, SSH_SFTP_REALPATH); + break; + + case SSH_SFTP_REALPATH: + { + char tempHome[PATH_MAX]; + + /* + * Get the "home" directory + */ + rc = sftp_libssh2_realpath(sshc->sftp_session, ".", + tempHome, PATH_MAX-1); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc > 0) { + /* It seems that this string is not always NULL terminated */ + tempHome[rc] = '\0'; + sshc->homedir = strdup(tempHome); + if(!sshc->homedir) { + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + conn->data->state.most_recent_ftp_entrypath = sshc->homedir; + } + else { + /* Return the error type */ + err = sftp_libssh2_last_error(sshc->sftp_session); + if(err) + result = sftp_libssh2_error_to_CURLE(err); + else + /* in this case, the error wasn't in the SFTP level but for example + a time-out or similar */ + result = CURLE_SSH; + sshc->actualcode = result; + DEBUGF(infof(data, "error = %d makes libcurl = %d\n", + err, (int)result)); + state(conn, SSH_STOP); + break; + } + } + /* This is the last step in the SFTP connect phase. Do note that while + we get the homedir here, we get the "workingpath" in the DO action + since the homedir will remain the same between request but the + working path will not. */ + DEBUGF(infof(data, "SSH CONNECT phase done\n")); + state(conn, SSH_STOP); + break; + + case SSH_SFTP_QUOTE_INIT: + + result = Curl_getworkingpath(conn, sshc->homedir, &sftp_scp->path); + if(result) { + sshc->actualcode = result; + state(conn, SSH_STOP); + break; + } + + if(data->set.quote) { + infof(data, "Sending quote commands\n"); + sshc->quote_item = data->set.quote; + state(conn, SSH_SFTP_QUOTE); + } + else { + state(conn, SSH_SFTP_GETINFO); + } + break; + + case SSH_SFTP_POSTQUOTE_INIT: + if(data->set.postquote) { + infof(data, "Sending quote commands\n"); + sshc->quote_item = data->set.postquote; + state(conn, SSH_SFTP_QUOTE); + } + else { + state(conn, SSH_STOP); + } + break; + + case SSH_SFTP_QUOTE: + /* Send any quote commands */ + { + const char *cp; + + /* + * Support some of the "FTP" commands + * + * 'sshc->quote_item' is already verified to be non-NULL before it + * switched to this state. + */ + char *cmd = sshc->quote_item->data; + sshc->acceptfail = FALSE; + + /* if a command starts with an asterisk, which a legal SFTP command never + can, the command will be allowed to fail without it causing any + aborts or cancels etc. It will cause libcurl to act as if the command + is successful, whatever the server reponds. */ + + if(cmd[0] == '*') { + cmd++; + sshc->acceptfail = TRUE; + } + + if(strcasecompare("pwd", cmd)) { + /* output debug output if that is requested */ + char *tmp = aprintf("257 \"%s\" is current directory.\n", + sftp_scp->path); + if(!tmp) { + result = CURLE_OUT_OF_MEMORY; + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + break; + } + if(data->set.verbose) { + Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4); + Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp)); + } + /* this sends an FTP-like "header" to the header callback so that the + current directory can be read very similar to how it is read when + using ordinary FTP. */ + result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp)); + free(tmp); + if(result) { + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + } + else + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + } + { + /* + * the arguments following the command must be separated from the + * command with a space so we can check for it unconditionally + */ + cp = strchr(cmd, ' '); + if(cp == NULL) { + failf(data, "Syntax error in SFTP command. Supply parameter(s)!"); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + + /* + * also, every command takes at least one argument so we get that + * first argument right now + */ + result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, "Syntax error: Bad first parameter"); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + break; + } + + /* + * SFTP is a binary protocol, so we don't send text commands + * to the server. Instead, we scan for commands used by + * OpenSSH's sftp program and call the appropriate libssh2 + * functions. + */ + if(strncasecompare(cmd, "chgrp ", 6) || + strncasecompare(cmd, "chmod ", 6) || + strncasecompare(cmd, "chown ", 6) ) { + /* attribute change */ + + /* sshc->quote_path1 contains the mode to set */ + /* get the destination */ + result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, "Syntax error in chgrp/chmod/chown: " + "Bad second parameter"); + Curl_safefree(sshc->quote_path1); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + break; + } + memset(&sshc->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES)); + state(conn, SSH_SFTP_QUOTE_STAT); + break; + } + if(strncasecompare(cmd, "ln ", 3) || + strncasecompare(cmd, "symlink ", 8)) { + /* symbolic linking */ + /* sshc->quote_path1 is the source */ + /* get the destination */ + result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, + "Syntax error in ln/symlink: Bad second parameter"); + Curl_safefree(sshc->quote_path1); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + break; + } + state(conn, SSH_SFTP_QUOTE_SYMLINK); + break; + } + else if(strncasecompare(cmd, "mkdir ", 6)) { + /* create dir */ + state(conn, SSH_SFTP_QUOTE_MKDIR); + break; + } + else if(strncasecompare(cmd, "rename ", 7)) { + /* rename file */ + /* first param is the source path */ + /* second param is the dest. path */ + result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, "Syntax error in rename: Bad second parameter"); + Curl_safefree(sshc->quote_path1); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + break; + } + state(conn, SSH_SFTP_QUOTE_RENAME); + break; + } + else if(strncasecompare(cmd, "rmdir ", 6)) { + /* delete dir */ + state(conn, SSH_SFTP_QUOTE_RMDIR); + break; + } + else if(strncasecompare(cmd, "rm ", 3)) { + state(conn, SSH_SFTP_QUOTE_UNLINK); + break; + } +#ifdef HAS_STATVFS_SUPPORT + else if(strncasecompare(cmd, "statvfs ", 8)) { + state(conn, SSH_SFTP_QUOTE_STATVFS); + break; + } +#endif + + failf(data, "Unknown SFTP command"); + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + } + break; + + case SSH_SFTP_NEXT_QUOTE: + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + + sshc->quote_item = sshc->quote_item->next; + + if(sshc->quote_item) { + state(conn, SSH_SFTP_QUOTE); + } + else { + if(sshc->nextstate != SSH_NO_STATE) { + state(conn, sshc->nextstate); + sshc->nextstate = SSH_NO_STATE; + } + else { + state(conn, SSH_SFTP_GETINFO); + } + } + break; + + case SSH_SFTP_QUOTE_STAT: + { + char *cmd = sshc->quote_item->data; + sshc->acceptfail = FALSE; + + /* if a command starts with an asterisk, which a legal SFTP command never + can, the command will be allowed to fail without it causing any + aborts or cancels etc. It will cause libcurl to act as if the command + is successful, whatever the server reponds. */ + + if(cmd[0] == '*') { + cmd++; + sshc->acceptfail = TRUE; + } + + if(!strncasecompare(cmd, "chmod", 5)) { + /* Since chown and chgrp only set owner OR group but libssh2 wants to + * set them both at once, we need to obtain the current ownership + * first. This takes an extra protocol round trip. + */ + rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2, + curlx_uztoui(strlen(sshc->quote_path2)), + LIBSSH2_SFTP_STAT, + &sshc->quote_attrs); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc != 0 && !sshc->acceptfail) { /* get those attributes */ + err = sftp_libssh2_last_error(sshc->sftp_session); + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "Attempt to get SFTP stats failed: %s", + sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + } + + /* Now set the new attributes... */ + if(strncasecompare(cmd, "chgrp", 5)) { + sshc->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10); + sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID; + if(sshc->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) && + !sshc->acceptfail) { + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "Syntax error: chgrp gid not a number"); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + } + else if(strncasecompare(cmd, "chmod", 5)) { + sshc->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8); + sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS; + /* permissions are octal */ + if(sshc->quote_attrs.permissions == 0 && + !ISDIGIT(sshc->quote_path1[0])) { + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "Syntax error: chmod permissions not a number"); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + } + else if(strncasecompare(cmd, "chown", 5)) { + sshc->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10); + sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID; + if(sshc->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) && + !sshc->acceptfail) { + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "Syntax error: chown uid not a number"); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + } + + /* Now send the completed structure... */ + state(conn, SSH_SFTP_QUOTE_SETSTAT); + break; + } + + case SSH_SFTP_QUOTE_SETSTAT: + rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2, + curlx_uztoui(strlen(sshc->quote_path2)), + LIBSSH2_SFTP_SETSTAT, + &sshc->quote_attrs); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc != 0 && !sshc->acceptfail) { + err = sftp_libssh2_last_error(sshc->sftp_session); + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "Attempt to set SFTP stats failed: %s", + sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_SYMLINK: + rc = libssh2_sftp_symlink_ex(sshc->sftp_session, sshc->quote_path1, + curlx_uztoui(strlen(sshc->quote_path1)), + sshc->quote_path2, + curlx_uztoui(strlen(sshc->quote_path2)), + LIBSSH2_SFTP_SYMLINK); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc != 0 && !sshc->acceptfail) { + err = sftp_libssh2_last_error(sshc->sftp_session); + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "symlink command failed: %s", + sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_MKDIR: + rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshc->quote_path1, + curlx_uztoui(strlen(sshc->quote_path1)), + data->set.new_directory_perms); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc != 0 && !sshc->acceptfail) { + err = sftp_libssh2_last_error(sshc->sftp_session); + Curl_safefree(sshc->quote_path1); + failf(data, "mkdir command failed: %s", sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_RENAME: + rc = libssh2_sftp_rename_ex(sshc->sftp_session, sshc->quote_path1, + curlx_uztoui(strlen(sshc->quote_path1)), + sshc->quote_path2, + curlx_uztoui(strlen(sshc->quote_path2)), + LIBSSH2_SFTP_RENAME_OVERWRITE | + LIBSSH2_SFTP_RENAME_ATOMIC | + LIBSSH2_SFTP_RENAME_NATIVE); + + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc != 0 && !sshc->acceptfail) { + err = sftp_libssh2_last_error(sshc->sftp_session); + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "rename command failed: %s", sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_RMDIR: + rc = libssh2_sftp_rmdir_ex(sshc->sftp_session, sshc->quote_path1, + curlx_uztoui(strlen(sshc->quote_path1))); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc != 0 && !sshc->acceptfail) { + err = sftp_libssh2_last_error(sshc->sftp_session); + Curl_safefree(sshc->quote_path1); + failf(data, "rmdir command failed: %s", sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_UNLINK: + rc = libssh2_sftp_unlink_ex(sshc->sftp_session, sshc->quote_path1, + curlx_uztoui(strlen(sshc->quote_path1))); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc != 0 && !sshc->acceptfail) { + err = sftp_libssh2_last_error(sshc->sftp_session); + Curl_safefree(sshc->quote_path1); + failf(data, "rm command failed: %s", sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + +#ifdef HAS_STATVFS_SUPPORT + case SSH_SFTP_QUOTE_STATVFS: + { + LIBSSH2_SFTP_STATVFS statvfs; + rc = libssh2_sftp_statvfs(sshc->sftp_session, sshc->quote_path1, + curlx_uztoui(strlen(sshc->quote_path1)), + &statvfs); + + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc != 0 && !sshc->acceptfail) { + err = sftp_libssh2_last_error(sshc->sftp_session); + Curl_safefree(sshc->quote_path1); + failf(data, "statvfs command failed: %s", sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + else if(rc == 0) { + char *tmp = aprintf("statvfs:\n" + "f_bsize: %llu\n" "f_frsize: %llu\n" + "f_blocks: %llu\n" "f_bfree: %llu\n" + "f_bavail: %llu\n" "f_files: %llu\n" + "f_ffree: %llu\n" "f_favail: %llu\n" + "f_fsid: %llu\n" "f_flag: %llu\n" + "f_namemax: %llu\n", + statvfs.f_bsize, statvfs.f_frsize, + statvfs.f_blocks, statvfs.f_bfree, + statvfs.f_bavail, statvfs.f_files, + statvfs.f_ffree, statvfs.f_favail, + statvfs.f_fsid, statvfs.f_flag, + statvfs.f_namemax); + if(!tmp) { + result = CURLE_OUT_OF_MEMORY; + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + break; + } + + result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp)); + free(tmp); + if(result) { + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + } + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + } +#endif + case SSH_SFTP_GETINFO: + { + if(data->set.get_filetime) { + state(conn, SSH_SFTP_FILETIME); + } + else { + state(conn, SSH_SFTP_TRANS_INIT); + } + break; + } + + case SSH_SFTP_FILETIME: + { + LIBSSH2_SFTP_ATTRIBUTES attrs; + + rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path, + curlx_uztoui(strlen(sftp_scp->path)), + LIBSSH2_SFTP_STAT, &attrs); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc == 0) { + data->info.filetime = attrs.mtime; + } + + state(conn, SSH_SFTP_TRANS_INIT); + break; + } + + case SSH_SFTP_TRANS_INIT: + if(data->set.upload) + state(conn, SSH_SFTP_UPLOAD_INIT); + else { + if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/') + state(conn, SSH_SFTP_READDIR_INIT); + else + state(conn, SSH_SFTP_DOWNLOAD_INIT); + } + break; + + case SSH_SFTP_UPLOAD_INIT: + { + unsigned long flags; + /* + * NOTE!!! libssh2 requires that the destination path is a full path + * that includes the destination file and name OR ends in a "/" + * If this is not done the destination file will be named the + * same name as the last directory in the path. + */ + + if(data->state.resume_from != 0) { + LIBSSH2_SFTP_ATTRIBUTES attrs; + if(data->state.resume_from < 0) { + rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path, + curlx_uztoui(strlen(sftp_scp->path)), + LIBSSH2_SFTP_STAT, &attrs); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc) { + data->state.resume_from = 0; + } + else { + curl_off_t size = attrs.filesize; + if(size < 0) { + failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size); + return CURLE_BAD_DOWNLOAD_RESUME; + } + data->state.resume_from = attrs.filesize; + } + } + } + + if(data->set.ftp_append) + /* Try to open for append, but create if nonexisting */ + flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_APPEND; + else if(data->state.resume_from > 0) + /* If we have restart position then open for append */ + flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_APPEND; + else + /* Clear file before writing (normal behaviour) */ + flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC; + + sshc->sftp_handle = + libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path, + curlx_uztoui(strlen(sftp_scp->path)), + flags, data->set.new_file_perms, + LIBSSH2_SFTP_OPENFILE); + + if(!sshc->sftp_handle) { + rc = libssh2_session_last_errno(sshc->ssh_session); + + if(LIBSSH2_ERROR_EAGAIN == rc) + break; + + if(LIBSSH2_ERROR_SFTP_PROTOCOL == rc) + /* only when there was an SFTP protocol error can we extract + the sftp error! */ + err = sftp_libssh2_last_error(sshc->sftp_session); + else + err = -1; /* not an sftp error at all */ + + if(sshc->secondCreateDirs) { + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = err>= LIBSSH2_FX_OK? + sftp_libssh2_error_to_CURLE(err):CURLE_SSH; + failf(data, "Creating the dir/file failed: %s", + sftp_libssh2_strerror(err)); + break; + } + if(((err == LIBSSH2_FX_NO_SUCH_FILE) || + (err == LIBSSH2_FX_FAILURE) || + (err == LIBSSH2_FX_NO_SUCH_PATH)) && + (data->set.ftp_create_missing_dirs && + (strlen(sftp_scp->path) > 1))) { + /* try to create the path remotely */ + rc = 0; /* clear rc and continue */ + sshc->secondCreateDirs = 1; + state(conn, SSH_SFTP_CREATE_DIRS_INIT); + break; + } + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = err>= LIBSSH2_FX_OK? + sftp_libssh2_error_to_CURLE(err):CURLE_SSH; + if(!sshc->actualcode) { + /* Sometimes, for some reason libssh2_sftp_last_error() returns + zero even though libssh2_sftp_open() failed previously! We need + to work around that! */ + sshc->actualcode = CURLE_SSH; + err = -1; + } + failf(data, "Upload failed: %s (%d/%d)", + err>= LIBSSH2_FX_OK?sftp_libssh2_strerror(err):"ssh error", + err, rc); + break; + } + + /* If we have a restart point then we need to seek to the correct + position. */ + if(data->state.resume_from > 0) { + /* Let's read off the proper amount of bytes from the input. */ + if(conn->seek_func) { + Curl_set_in_callback(data, true); + seekerr = conn->seek_func(conn->seek_client, data->state.resume_from, + SEEK_SET); + Curl_set_in_callback(data, false); + } + + if(seekerr != CURL_SEEKFUNC_OK) { + curl_off_t passed = 0; + + if(seekerr != CURL_SEEKFUNC_CANTSEEK) { + failf(data, "Could not seek stream"); + return CURLE_FTP_COULDNT_USE_REST; + } + /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ + do { + size_t readthisamountnow = + (data->state.resume_from - passed > data->set.buffer_size) ? + (size_t)data->set.buffer_size : + curlx_sotouz(data->state.resume_from - passed); + + size_t actuallyread; + Curl_set_in_callback(data, true); + actuallyread = data->state.fread_func(data->state.buffer, 1, + readthisamountnow, + data->state.in); + Curl_set_in_callback(data, false); + + passed += actuallyread; + if((actuallyread == 0) || (actuallyread > readthisamountnow)) { + /* this checks for greater-than only to make sure that the + CURL_READFUNC_ABORT return code still aborts */ + failf(data, "Failed to read data"); + return CURLE_FTP_COULDNT_USE_REST; + } + } while(passed < data->state.resume_from); + } + + /* now, decrease the size of the read */ + if(data->state.infilesize > 0) { + data->state.infilesize -= data->state.resume_from; + data->req.size = data->state.infilesize; + Curl_pgrsSetUploadSize(data, data->state.infilesize); + } + + SFTP_SEEK(sshc->sftp_handle, data->state.resume_from); + } + if(data->state.infilesize > 0) { + data->req.size = data->state.infilesize; + Curl_pgrsSetUploadSize(data, data->state.infilesize); + } + /* upload data */ + Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); + + /* not set by Curl_setup_transfer to preserve keepon bits */ + conn->sockfd = conn->writesockfd; + + if(result) { + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = result; + } + else { + /* store this original bitmask setup to use later on if we can't + figure out a "real" bitmask */ + sshc->orig_waitfor = data->req.keepon; + + /* we want to use the _sending_ function even when the socket turns + out readable as the underlying libssh2 sftp send function will deal + with both accordingly */ + conn->cselect_bits = CURL_CSELECT_OUT; + + /* since we don't really wait for anything at this point, we want the + state machine to move on as soon as possible so we set a very short + timeout here */ + Curl_expire(data, 0, EXPIRE_RUN_NOW); + + state(conn, SSH_STOP); + } + break; + } + + case SSH_SFTP_CREATE_DIRS_INIT: + if(strlen(sftp_scp->path) > 1) { + sshc->slash_pos = sftp_scp->path + 1; /* ignore the leading '/' */ + state(conn, SSH_SFTP_CREATE_DIRS); + } + else { + state(conn, SSH_SFTP_UPLOAD_INIT); + } + break; + + case SSH_SFTP_CREATE_DIRS: + sshc->slash_pos = strchr(sshc->slash_pos, '/'); + if(sshc->slash_pos) { + *sshc->slash_pos = 0; + + infof(data, "Creating directory '%s'\n", sftp_scp->path); + state(conn, SSH_SFTP_CREATE_DIRS_MKDIR); + break; + } + state(conn, SSH_SFTP_UPLOAD_INIT); + break; + + case SSH_SFTP_CREATE_DIRS_MKDIR: + /* 'mode' - parameter is preliminary - default to 0644 */ + rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sftp_scp->path, + curlx_uztoui(strlen(sftp_scp->path)), + data->set.new_directory_perms); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + *sshc->slash_pos = '/'; + ++sshc->slash_pos; + if(rc < 0) { + /* + * Abort if failure wasn't that the dir already exists or the + * permission was denied (creation might succeed further down the + * path) - retry on unspecific FAILURE also + */ + err = sftp_libssh2_last_error(sshc->sftp_session); + if((err != LIBSSH2_FX_FILE_ALREADY_EXISTS) && + (err != LIBSSH2_FX_FAILURE) && + (err != LIBSSH2_FX_PERMISSION_DENIED)) { + result = sftp_libssh2_error_to_CURLE(err); + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = result?result:CURLE_SSH; + break; + } + rc = 0; /* clear rc and continue */ + } + state(conn, SSH_SFTP_CREATE_DIRS); + break; + + case SSH_SFTP_READDIR_INIT: + Curl_pgrsSetDownloadSize(data, -1); + if(data->set.opt_no_body) { + state(conn, SSH_STOP); + break; + } + + /* + * This is a directory that we are trying to get, so produce a directory + * listing + */ + sshc->sftp_handle = libssh2_sftp_open_ex(sshc->sftp_session, + sftp_scp->path, + curlx_uztoui( + strlen(sftp_scp->path)), + 0, 0, LIBSSH2_SFTP_OPENDIR); + if(!sshc->sftp_handle) { + if(libssh2_session_last_errno(sshc->ssh_session) == + LIBSSH2_ERROR_EAGAIN) { + rc = LIBSSH2_ERROR_EAGAIN; + break; + } + err = sftp_libssh2_last_error(sshc->sftp_session); + failf(data, "Could not open directory for reading: %s", + sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + result = sftp_libssh2_error_to_CURLE(err); + sshc->actualcode = result?result:CURLE_SSH; + break; + } + sshc->readdir_filename = malloc(PATH_MAX + 1); + if(!sshc->readdir_filename) { + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + sshc->readdir_longentry = malloc(PATH_MAX + 1); + if(!sshc->readdir_longentry) { + Curl_safefree(sshc->readdir_filename); + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + state(conn, SSH_SFTP_READDIR); + break; + + case SSH_SFTP_READDIR: + rc = libssh2_sftp_readdir_ex(sshc->sftp_handle, + sshc->readdir_filename, + PATH_MAX, + sshc->readdir_longentry, + PATH_MAX, + &sshc->readdir_attrs); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc > 0) { + sshc->readdir_len = (size_t) rc; + sshc->readdir_filename[sshc->readdir_len] = '\0'; + + if(data->set.ftp_list_only) { + char *tmpLine; + + tmpLine = aprintf("%s\n", sshc->readdir_filename); + if(tmpLine == NULL) { + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + result = Curl_client_write(conn, CLIENTWRITE_BODY, + tmpLine, sshc->readdir_len + 1); + free(tmpLine); + + if(result) { + state(conn, SSH_STOP); + break; + } + /* since this counts what we send to the client, we include the + newline in this counter */ + data->req.bytecount += sshc->readdir_len + 1; + + /* output debug output if that is requested */ + if(data->set.verbose) { + Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_filename, + sshc->readdir_len); + } + } + else { + sshc->readdir_currLen = strlen(sshc->readdir_longentry); + sshc->readdir_totalLen = 80 + sshc->readdir_currLen; + sshc->readdir_line = calloc(sshc->readdir_totalLen, 1); + if(!sshc->readdir_line) { + Curl_safefree(sshc->readdir_filename); + Curl_safefree(sshc->readdir_longentry); + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + + memcpy(sshc->readdir_line, sshc->readdir_longentry, + sshc->readdir_currLen); + if((sshc->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) && + ((sshc->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) == + LIBSSH2_SFTP_S_IFLNK)) { + sshc->readdir_linkPath = malloc(PATH_MAX + 1); + if(sshc->readdir_linkPath == NULL) { + Curl_safefree(sshc->readdir_filename); + Curl_safefree(sshc->readdir_longentry); + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + + msnprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", sftp_scp->path, + sshc->readdir_filename); + state(conn, SSH_SFTP_READDIR_LINK); + break; + } + state(conn, SSH_SFTP_READDIR_BOTTOM); + break; + } + } + else if(rc == 0) { + Curl_safefree(sshc->readdir_filename); + Curl_safefree(sshc->readdir_longentry); + state(conn, SSH_SFTP_READDIR_DONE); + break; + } + else if(rc < 0) { + err = sftp_libssh2_last_error(sshc->sftp_session); + result = sftp_libssh2_error_to_CURLE(err); + sshc->actualcode = result?result:CURLE_SSH; + failf(data, "Could not open remote file for reading: %s :: %d", + sftp_libssh2_strerror(err), + libssh2_session_last_errno(sshc->ssh_session)); + Curl_safefree(sshc->readdir_filename); + Curl_safefree(sshc->readdir_longentry); + state(conn, SSH_SFTP_CLOSE); + break; + } + break; + + case SSH_SFTP_READDIR_LINK: + rc = + libssh2_sftp_symlink_ex(sshc->sftp_session, + sshc->readdir_linkPath, + curlx_uztoui(strlen(sshc->readdir_linkPath)), + sshc->readdir_filename, + PATH_MAX, LIBSSH2_SFTP_READLINK); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + sshc->readdir_len = (size_t) rc; + Curl_safefree(sshc->readdir_linkPath); + + /* get room for the filename and extra output */ + sshc->readdir_totalLen += 4 + sshc->readdir_len; + new_readdir_line = Curl_saferealloc(sshc->readdir_line, + sshc->readdir_totalLen); + if(!new_readdir_line) { + sshc->readdir_line = NULL; + Curl_safefree(sshc->readdir_filename); + Curl_safefree(sshc->readdir_longentry); + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + sshc->readdir_line = new_readdir_line; + + sshc->readdir_currLen += msnprintf(sshc->readdir_line + + sshc->readdir_currLen, + sshc->readdir_totalLen - + sshc->readdir_currLen, + " -> %s", + sshc->readdir_filename); + + state(conn, SSH_SFTP_READDIR_BOTTOM); + break; + + case SSH_SFTP_READDIR_BOTTOM: + sshc->readdir_currLen += msnprintf(sshc->readdir_line + + sshc->readdir_currLen, + sshc->readdir_totalLen - + sshc->readdir_currLen, "\n"); + result = Curl_client_write(conn, CLIENTWRITE_BODY, + sshc->readdir_line, + sshc->readdir_currLen); + + if(!result) { + + /* output debug output if that is requested */ + if(data->set.verbose) { + Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line, + sshc->readdir_currLen); + } + data->req.bytecount += sshc->readdir_currLen; + } + Curl_safefree(sshc->readdir_line); + if(result) { + state(conn, SSH_STOP); + } + else + state(conn, SSH_SFTP_READDIR); + break; + + case SSH_SFTP_READDIR_DONE: + if(libssh2_sftp_closedir(sshc->sftp_handle) == + LIBSSH2_ERROR_EAGAIN) { + rc = LIBSSH2_ERROR_EAGAIN; + break; + } + sshc->sftp_handle = NULL; + Curl_safefree(sshc->readdir_filename); + Curl_safefree(sshc->readdir_longentry); + + /* no data to transfer */ + Curl_setup_transfer(data, -1, -1, FALSE, -1); + state(conn, SSH_STOP); + break; + + case SSH_SFTP_DOWNLOAD_INIT: + /* + * Work on getting the specified file + */ + sshc->sftp_handle = + libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path, + curlx_uztoui(strlen(sftp_scp->path)), + LIBSSH2_FXF_READ, data->set.new_file_perms, + LIBSSH2_SFTP_OPENFILE); + if(!sshc->sftp_handle) { + if(libssh2_session_last_errno(sshc->ssh_session) == + LIBSSH2_ERROR_EAGAIN) { + rc = LIBSSH2_ERROR_EAGAIN; + break; + } + err = sftp_libssh2_last_error(sshc->sftp_session); + failf(data, "Could not open remote file for reading: %s", + sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + result = sftp_libssh2_error_to_CURLE(err); + sshc->actualcode = result?result:CURLE_SSH; + break; + } + state(conn, SSH_SFTP_DOWNLOAD_STAT); + break; + + case SSH_SFTP_DOWNLOAD_STAT: + { + LIBSSH2_SFTP_ATTRIBUTES attrs; + + rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path, + curlx_uztoui(strlen(sftp_scp->path)), + LIBSSH2_SFTP_STAT, &attrs); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc || + !(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) || + (attrs.filesize == 0)) { + /* + * libssh2_sftp_open() didn't return an error, so maybe the server + * just doesn't support stat() + * OR the server doesn't return a file size with a stat() + * OR file size is 0 + */ + data->req.size = -1; + data->req.maxdownload = -1; + Curl_pgrsSetDownloadSize(data, -1); + } + else { + curl_off_t size = attrs.filesize; + + if(size < 0) { + failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size); + return CURLE_BAD_DOWNLOAD_RESUME; + } + if(conn->data->state.use_range) { + curl_off_t from, to; + char *ptr; + char *ptr2; + CURLofft to_t; + CURLofft from_t; + + from_t = curlx_strtoofft(conn->data->state.range, &ptr, 0, &from); + if(from_t == CURL_OFFT_FLOW) + return CURLE_RANGE_ERROR; + while(*ptr && (ISSPACE(*ptr) || (*ptr == '-'))) + ptr++; + to_t = curlx_strtoofft(ptr, &ptr2, 0, &to); + if(to_t == CURL_OFFT_FLOW) + return CURLE_RANGE_ERROR; + if((to_t == CURL_OFFT_INVAL) /* no "to" value given */ + || (to >= size)) { + to = size - 1; + } + if(from_t) { + /* from is relative to end of file */ + from = size - to; + to = size - 1; + } + if(from > size) { + failf(data, "Offset (%" + CURL_FORMAT_CURL_OFF_T ") was beyond file size (%" + CURL_FORMAT_CURL_OFF_T ")", from, attrs.filesize); + return CURLE_BAD_DOWNLOAD_RESUME; + } + if(from > to) { + from = to; + size = 0; + } + else { + size = to - from + 1; + } + + SFTP_SEEK(conn->proto.sshc.sftp_handle, from); + } + data->req.size = size; + data->req.maxdownload = size; + Curl_pgrsSetDownloadSize(data, size); + } + + /* We can resume if we can seek to the resume position */ + if(data->state.resume_from) { + if(data->state.resume_from < 0) { + /* We're supposed to download the last abs(from) bytes */ + if((curl_off_t)attrs.filesize < -data->state.resume_from) { + failf(data, "Offset (%" + CURL_FORMAT_CURL_OFF_T ") was beyond file size (%" + CURL_FORMAT_CURL_OFF_T ")", + data->state.resume_from, attrs.filesize); + return CURLE_BAD_DOWNLOAD_RESUME; + } + /* download from where? */ + data->state.resume_from += attrs.filesize; + } + else { + if((curl_off_t)attrs.filesize < data->state.resume_from) { + failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T + ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")", + data->state.resume_from, attrs.filesize); + return CURLE_BAD_DOWNLOAD_RESUME; + } + } + /* Does a completed file need to be seeked and started or closed ? */ + /* Now store the number of bytes we are expected to download */ + data->req.size = attrs.filesize - data->state.resume_from; + data->req.maxdownload = attrs.filesize - data->state.resume_from; + Curl_pgrsSetDownloadSize(data, + attrs.filesize - data->state.resume_from); + SFTP_SEEK(sshc->sftp_handle, data->state.resume_from); + } + } + + /* Setup the actual download */ + if(data->req.size == 0) { + /* no data to transfer */ + Curl_setup_transfer(data, -1, -1, FALSE, -1); + infof(data, "File already completely downloaded\n"); + state(conn, SSH_STOP); + break; + } + Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1); + + /* not set by Curl_setup_transfer to preserve keepon bits */ + conn->writesockfd = conn->sockfd; + + /* we want to use the _receiving_ function even when the socket turns + out writableable as the underlying libssh2 recv function will deal + with both accordingly */ + conn->cselect_bits = CURL_CSELECT_IN; + + if(result) { + /* this should never occur; the close state should be entered + at the time the error occurs */ + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = result; + } + else { + state(conn, SSH_STOP); + } + break; + + case SSH_SFTP_CLOSE: + if(sshc->sftp_handle) { + rc = libssh2_sftp_close(sshc->sftp_handle); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc < 0) { + char *err_msg = NULL; + (void)libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0); + infof(data, "Failed to close libssh2 file: %d %s\n", rc, err_msg); + } + sshc->sftp_handle = NULL; + } + + Curl_safefree(sftp_scp->path); + + DEBUGF(infof(data, "SFTP DONE done\n")); + + /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT + After nextstate is executed, the control should come back to + SSH_SFTP_CLOSE to pass the correct result back */ + if(sshc->nextstate != SSH_NO_STATE && + sshc->nextstate != SSH_SFTP_CLOSE) { + state(conn, sshc->nextstate); + sshc->nextstate = SSH_SFTP_CLOSE; + } + else { + state(conn, SSH_STOP); + result = sshc->actualcode; + } + break; + + case SSH_SFTP_SHUTDOWN: + /* during times we get here due to a broken transfer and then the + sftp_handle might not have been taken down so make sure that is done + before we proceed */ + + if(sshc->sftp_handle) { + rc = libssh2_sftp_close(sshc->sftp_handle); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc < 0) { + char *err_msg = NULL; + (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, + NULL, 0); + infof(data, "Failed to close libssh2 file: %d %s\n", rc, err_msg); + } + sshc->sftp_handle = NULL; + } + if(sshc->sftp_session) { + rc = libssh2_sftp_shutdown(sshc->sftp_session); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc < 0) { + infof(data, "Failed to stop libssh2 sftp subsystem\n"); + } + sshc->sftp_session = NULL; + } + + Curl_safefree(sshc->homedir); + conn->data->state.most_recent_ftp_entrypath = NULL; + + state(conn, SSH_SESSION_DISCONNECT); + break; + + case SSH_SCP_TRANS_INIT: + result = Curl_getworkingpath(conn, sshc->homedir, &sftp_scp->path); + if(result) { + sshc->actualcode = result; + state(conn, SSH_STOP); + break; + } + + if(data->set.upload) { + if(data->state.infilesize < 0) { + failf(data, "SCP requires a known file size for upload"); + sshc->actualcode = CURLE_UPLOAD_FAILED; + state(conn, SSH_SCP_CHANNEL_FREE); + break; + } + state(conn, SSH_SCP_UPLOAD_INIT); + } + else { + state(conn, SSH_SCP_DOWNLOAD_INIT); + } + break; + + case SSH_SCP_UPLOAD_INIT: + /* + * libssh2 requires that the destination path is a full path that + * includes the destination file and name OR ends in a "/" . If this is + * not done the destination file will be named the same name as the last + * directory in the path. + */ + sshc->ssh_channel = + SCP_SEND(sshc->ssh_session, sftp_scp->path, data->set.new_file_perms, + data->state.infilesize); + if(!sshc->ssh_channel) { + int ssh_err; + char *err_msg = NULL; + + if(libssh2_session_last_errno(sshc->ssh_session) == + LIBSSH2_ERROR_EAGAIN) { + rc = LIBSSH2_ERROR_EAGAIN; + break; + } + + ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0)); + failf(conn->data, "%s", err_msg); + state(conn, SSH_SCP_CHANNEL_FREE); + sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err); + /* Map generic errors to upload failed */ + if(sshc->actualcode == CURLE_SSH || + sshc->actualcode == CURLE_REMOTE_FILE_NOT_FOUND) + sshc->actualcode = CURLE_UPLOAD_FAILED; + break; + } + + /* upload data */ + Curl_setup_transfer(data, -1, data->req.size, FALSE, FIRSTSOCKET); + + /* not set by Curl_setup_transfer to preserve keepon bits */ + conn->sockfd = conn->writesockfd; + + if(result) { + state(conn, SSH_SCP_CHANNEL_FREE); + sshc->actualcode = result; + } + else { + /* store this original bitmask setup to use later on if we can't + figure out a "real" bitmask */ + sshc->orig_waitfor = data->req.keepon; + + /* we want to use the _sending_ function even when the socket turns + out readable as the underlying libssh2 scp send function will deal + with both accordingly */ + conn->cselect_bits = CURL_CSELECT_OUT; + + state(conn, SSH_STOP); + } + break; + + case SSH_SCP_DOWNLOAD_INIT: + { + curl_off_t bytecount; + + /* + * We must check the remote file; if it is a directory no values will + * be set in sb + */ + + /* + * If support for >2GB files exists, use it. + */ + + /* get a fresh new channel from the ssh layer */ +#if LIBSSH2_VERSION_NUM < 0x010700 + struct stat sb; + memset(&sb, 0, sizeof(struct stat)); + sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session, + sftp_scp->path, &sb); +#else + libssh2_struct_stat sb; + memset(&sb, 0, sizeof(libssh2_struct_stat)); + sshc->ssh_channel = libssh2_scp_recv2(sshc->ssh_session, + sftp_scp->path, &sb); +#endif + + if(!sshc->ssh_channel) { + int ssh_err; + char *err_msg = NULL; + + if(libssh2_session_last_errno(sshc->ssh_session) == + LIBSSH2_ERROR_EAGAIN) { + rc = LIBSSH2_ERROR_EAGAIN; + break; + } + + + ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0)); + failf(conn->data, "%s", err_msg); + state(conn, SSH_SCP_CHANNEL_FREE); + sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err); + break; + } + + /* download data */ + bytecount = (curl_off_t)sb.st_size; + data->req.maxdownload = (curl_off_t)sb.st_size; + Curl_setup_transfer(data, FIRSTSOCKET, bytecount, FALSE, -1); + + /* not set by Curl_setup_transfer to preserve keepon bits */ + conn->writesockfd = conn->sockfd; + + /* we want to use the _receiving_ function even when the socket turns + out writableable as the underlying libssh2 recv function will deal + with both accordingly */ + conn->cselect_bits = CURL_CSELECT_IN; + + if(result) { + state(conn, SSH_SCP_CHANNEL_FREE); + sshc->actualcode = result; + } + else + state(conn, SSH_STOP); + } + break; + + case SSH_SCP_DONE: + if(data->set.upload) + state(conn, SSH_SCP_SEND_EOF); + else + state(conn, SSH_SCP_CHANNEL_FREE); + break; + + case SSH_SCP_SEND_EOF: + if(sshc->ssh_channel) { + rc = libssh2_channel_send_eof(sshc->ssh_channel); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc) { + char *err_msg = NULL; + (void)libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0); + infof(data, "Failed to send libssh2 channel EOF: %d %s\n", + rc, err_msg); + } + } + state(conn, SSH_SCP_WAIT_EOF); + break; + + case SSH_SCP_WAIT_EOF: + if(sshc->ssh_channel) { + rc = libssh2_channel_wait_eof(sshc->ssh_channel); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc) { + char *err_msg = NULL; + (void)libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0); + infof(data, "Failed to get channel EOF: %d %s\n", rc, err_msg); + } + } + state(conn, SSH_SCP_WAIT_CLOSE); + break; + + case SSH_SCP_WAIT_CLOSE: + if(sshc->ssh_channel) { + rc = libssh2_channel_wait_closed(sshc->ssh_channel); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc) { + char *err_msg = NULL; + (void)libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0); + infof(data, "Channel failed to close: %d %s\n", rc, err_msg); + } + } + state(conn, SSH_SCP_CHANNEL_FREE); + break; + + case SSH_SCP_CHANNEL_FREE: + if(sshc->ssh_channel) { + rc = libssh2_channel_free(sshc->ssh_channel); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc < 0) { + char *err_msg = NULL; + (void)libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0); + infof(data, "Failed to free libssh2 scp subsystem: %d %s\n", + rc, err_msg); + } + sshc->ssh_channel = NULL; + } + DEBUGF(infof(data, "SCP DONE phase complete\n")); +#if 0 /* PREV */ + state(conn, SSH_SESSION_DISCONNECT); +#endif + state(conn, SSH_STOP); + result = sshc->actualcode; + break; + + case SSH_SESSION_DISCONNECT: + /* during weird times when we've been prematurely aborted, the channel + is still alive when we reach this state and we MUST kill the channel + properly first */ + if(sshc->ssh_channel) { + rc = libssh2_channel_free(sshc->ssh_channel); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc < 0) { + char *err_msg = NULL; + (void)libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0); + infof(data, "Failed to free libssh2 scp subsystem: %d %s\n", + rc, err_msg); + } + sshc->ssh_channel = NULL; + } + + if(sshc->ssh_session) { + rc = libssh2_session_disconnect(sshc->ssh_session, "Shutdown"); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc < 0) { + char *err_msg = NULL; + (void)libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0); + infof(data, "Failed to disconnect libssh2 session: %d %s\n", + rc, err_msg); + } + } + + Curl_safefree(sshc->homedir); + conn->data->state.most_recent_ftp_entrypath = NULL; + + state(conn, SSH_SESSION_FREE); + break; + + case SSH_SESSION_FREE: +#ifdef HAVE_LIBSSH2_KNOWNHOST_API + if(sshc->kh) { + libssh2_knownhost_free(sshc->kh); + sshc->kh = NULL; + } +#endif + +#ifdef HAVE_LIBSSH2_AGENT_API + if(sshc->ssh_agent) { + rc = libssh2_agent_disconnect(sshc->ssh_agent); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc < 0) { + char *err_msg = NULL; + (void)libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0); + infof(data, "Failed to disconnect from libssh2 agent: %d %s\n", + rc, err_msg); + } + libssh2_agent_free(sshc->ssh_agent); + sshc->ssh_agent = NULL; + + /* NB: there is no need to free identities, they are part of internal + agent stuff */ + sshc->sshagent_identity = NULL; + sshc->sshagent_prev_identity = NULL; + } +#endif + + if(sshc->ssh_session) { + rc = libssh2_session_free(sshc->ssh_session); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc < 0) { + char *err_msg = NULL; + (void)libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0); + infof(data, "Failed to free libssh2 session: %d %s\n", rc, err_msg); + } + sshc->ssh_session = NULL; + } + + /* worst-case scenario cleanup */ + + DEBUGASSERT(sshc->ssh_session == NULL); + DEBUGASSERT(sshc->ssh_channel == NULL); + DEBUGASSERT(sshc->sftp_session == NULL); + DEBUGASSERT(sshc->sftp_handle == NULL); +#ifdef HAVE_LIBSSH2_KNOWNHOST_API + DEBUGASSERT(sshc->kh == NULL); +#endif +#ifdef HAVE_LIBSSH2_AGENT_API + DEBUGASSERT(sshc->ssh_agent == NULL); +#endif + + Curl_safefree(sshc->rsa_pub); + Curl_safefree(sshc->rsa); + + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + + Curl_safefree(sshc->homedir); + + Curl_safefree(sshc->readdir_filename); + Curl_safefree(sshc->readdir_longentry); + Curl_safefree(sshc->readdir_line); + Curl_safefree(sshc->readdir_linkPath); + + /* the code we are about to return */ + result = sshc->actualcode; + + memset(sshc, 0, sizeof(struct ssh_conn)); + + connclose(conn, "SSH session free"); + sshc->state = SSH_SESSION_FREE; /* current */ + sshc->nextstate = SSH_NO_STATE; + state(conn, SSH_STOP); + break; + + case SSH_QUIT: + /* fallthrough, just stop! */ + default: + /* internal error */ + sshc->nextstate = SSH_NO_STATE; + state(conn, SSH_STOP); + break; + } + + } while(!rc && (sshc->state != SSH_STOP)); + + if(rc == LIBSSH2_ERROR_EAGAIN) { + /* we would block, we need to wait for the socket to be ready (in the + right direction too)! */ + *block = TRUE; + } + + return result; +} + +/* called by the multi interface to figure out what socket(s) to wait for and + for what actions in the DO_DONE, PERFORM and WAITPERFORM states */ +static int ssh_perform_getsock(const struct connectdata *conn, + curl_socket_t *sock, /* points to numsocks + number of sockets */ + int numsocks) +{ +#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION + int bitmap = GETSOCK_BLANK; + (void)numsocks; + + sock[0] = conn->sock[FIRSTSOCKET]; + + if(conn->waitfor & KEEP_RECV) + bitmap |= GETSOCK_READSOCK(FIRSTSOCKET); + + if(conn->waitfor & KEEP_SEND) + bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET); + + return bitmap; +#else + /* if we don't know the direction we can use the generic *_getsock() + function even for the protocol_connect and doing states */ + return Curl_single_getsock(conn, sock, numsocks); +#endif +} + +/* Generic function called by the multi interface to figure out what socket(s) + to wait for and for what actions during the DOING and PROTOCONNECT states*/ +static int ssh_getsock(struct connectdata *conn, + curl_socket_t *sock, /* points to numsocks number + of sockets */ + int numsocks) +{ +#ifndef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION + (void)conn; + (void)sock; + (void)numsocks; + /* if we don't know any direction we can just play along as we used to and + not provide any sensible info */ + return GETSOCK_BLANK; +#else + /* if we know the direction we can use the generic *_getsock() function even + for the protocol_connect and doing states */ + return ssh_perform_getsock(conn, sock, numsocks); +#endif +} + +#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION +/* + * When one of the libssh2 functions has returned LIBSSH2_ERROR_EAGAIN this + * function is used to figure out in what direction and stores this info so + * that the multi interface can take advantage of it. Make sure to call this + * function in all cases so that when it _doesn't_ return EAGAIN we can + * restore the default wait bits. + */ +static void ssh_block2waitfor(struct connectdata *conn, bool block) +{ + struct ssh_conn *sshc = &conn->proto.sshc; + int dir = 0; + if(block) { + dir = libssh2_session_block_directions(sshc->ssh_session); + if(dir) { + /* translate the libssh2 define bits into our own bit defines */ + conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) | + ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0); + } + } + if(!dir) + /* It didn't block or libssh2 didn't reveal in which direction, put back + the original set */ + conn->waitfor = sshc->orig_waitfor; +} +#else + /* no libssh2 directional support so we simply don't know */ +#define ssh_block2waitfor(x,y) Curl_nop_stmt +#endif + +/* called repeatedly until done from multi.c */ +static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done) +{ + struct ssh_conn *sshc = &conn->proto.sshc; + CURLcode result = CURLE_OK; + bool block; /* we store the status and use that to provide a ssh_getsock() + implementation */ + do { + result = ssh_statemach_act(conn, &block); + *done = (sshc->state == SSH_STOP) ? TRUE : FALSE; + /* if there's no error, it isn't done and it didn't EWOULDBLOCK, then + try again */ + } while(!result && !*done && !block); + ssh_block2waitfor(conn, block); + + return result; +} + +static CURLcode ssh_block_statemach(struct connectdata *conn, + bool disconnect) +{ + struct ssh_conn *sshc = &conn->proto.sshc; + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + while((sshc->state != SSH_STOP) && !result) { + bool block; + timediff_t left = 1000; + struct curltime now = Curl_now(); + + result = ssh_statemach_act(conn, &block); + if(result) + break; + + if(!disconnect) { + if(Curl_pgrsUpdate(conn)) + return CURLE_ABORTED_BY_CALLBACK; + + result = Curl_speedcheck(data, now); + if(result) + break; + + left = Curl_timeleft(data, NULL, FALSE); + if(left < 0) { + failf(data, "Operation timed out"); + return CURLE_OPERATION_TIMEDOUT; + } + } + +#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION + if(!result && block) { + int dir = libssh2_session_block_directions(sshc->ssh_session); + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + curl_socket_t fd_read = CURL_SOCKET_BAD; + curl_socket_t fd_write = CURL_SOCKET_BAD; + if(LIBSSH2_SESSION_BLOCK_INBOUND & dir) + fd_read = sock; + if(LIBSSH2_SESSION_BLOCK_OUTBOUND & dir) + fd_write = sock; + /* wait for the socket to become ready */ + (void)Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write, + left>1000?1000:left); /* ignore result */ + } +#endif + + } + + return result; +} + +/* + * SSH setup and connection + */ +static CURLcode ssh_setup_connection(struct connectdata *conn) +{ + struct SSHPROTO *ssh; + + conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO)); + if(!ssh) + return CURLE_OUT_OF_MEMORY; + + return CURLE_OK; +} + +static Curl_recv scp_recv, sftp_recv; +static Curl_send scp_send, sftp_send; + +/* + * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to + * do protocol-specific actions at connect-time. + */ +static CURLcode ssh_connect(struct connectdata *conn, bool *done) +{ +#ifdef CURL_LIBSSH2_DEBUG + curl_socket_t sock; +#endif + struct ssh_conn *ssh; + CURLcode result; + struct Curl_easy *data = conn->data; + + /* initialize per-handle data if not already */ + if(!data->req.protop) + ssh_setup_connection(conn); + + /* We default to persistent connections. We set this already in this connect + function to make the re-use checks properly be able to check this bit. */ + connkeep(conn, "SSH default"); + + if(conn->handler->protocol & CURLPROTO_SCP) { + conn->recv[FIRSTSOCKET] = scp_recv; + conn->send[FIRSTSOCKET] = scp_send; + } + else { + conn->recv[FIRSTSOCKET] = sftp_recv; + conn->send[FIRSTSOCKET] = sftp_send; + } + ssh = &conn->proto.sshc; + +#ifdef CURL_LIBSSH2_DEBUG + if(conn->user) { + infof(data, "User: %s\n", conn->user); + } + if(conn->passwd) { + infof(data, "Password: %s\n", conn->passwd); + } + sock = conn->sock[FIRSTSOCKET]; +#endif /* CURL_LIBSSH2_DEBUG */ + + ssh->ssh_session = libssh2_session_init_ex(my_libssh2_malloc, + my_libssh2_free, + my_libssh2_realloc, conn); + if(ssh->ssh_session == NULL) { + failf(data, "Failure initialising ssh session"); + return CURLE_FAILED_INIT; + } + + if(data->set.ssh_compression) { +#if LIBSSH2_VERSION_NUM >= 0x010208 + if(libssh2_session_flag(ssh->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0) +#endif + infof(data, "Failed to enable compression for ssh session\n"); + } + +#ifdef HAVE_LIBSSH2_KNOWNHOST_API + if(data->set.str[STRING_SSH_KNOWNHOSTS]) { + int rc; + ssh->kh = libssh2_knownhost_init(ssh->ssh_session); + if(!ssh->kh) { + libssh2_session_free(ssh->ssh_session); + return CURLE_FAILED_INIT; + } + + /* read all known hosts from there */ + rc = libssh2_knownhost_readfile(ssh->kh, + data->set.str[STRING_SSH_KNOWNHOSTS], + LIBSSH2_KNOWNHOST_FILE_OPENSSH); + if(rc < 0) + infof(data, "Failed to read known hosts from %s\n", + data->set.str[STRING_SSH_KNOWNHOSTS]); + } +#endif /* HAVE_LIBSSH2_KNOWNHOST_API */ + +#ifdef CURL_LIBSSH2_DEBUG + libssh2_trace(ssh->ssh_session, ~0); + infof(data, "SSH socket: %d\n", (int)sock); +#endif /* CURL_LIBSSH2_DEBUG */ + + state(conn, SSH_INIT); + + result = ssh_multi_statemach(conn, done); + + return result; +} + +/* + *********************************************************************** + * + * scp_perform() + * + * This is the actual DO function for SCP. Get a file according to + * the options previously setup. + */ + +static +CURLcode scp_perform(struct connectdata *conn, + bool *connected, + bool *dophase_done) +{ + CURLcode result = CURLE_OK; + + DEBUGF(infof(conn->data, "DO phase starts\n")); + + *dophase_done = FALSE; /* not done yet */ + + /* start the first command in the DO phase */ + state(conn, SSH_SCP_TRANS_INIT); + + /* run the state-machine */ + result = ssh_multi_statemach(conn, dophase_done); + + *connected = conn->bits.tcpconnect[FIRSTSOCKET]; + + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + + return result; +} + +/* called from multi.c while DOing */ +static CURLcode scp_doing(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result; + result = ssh_multi_statemach(conn, dophase_done); + + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + return result; +} + +/* + * The DO function is generic for both protocols. There was previously two + * separate ones but this way means less duplicated code. + */ + +static CURLcode ssh_do(struct connectdata *conn, bool *done) +{ + CURLcode result; + bool connected = 0; + struct Curl_easy *data = conn->data; + struct ssh_conn *sshc = &conn->proto.sshc; + + *done = FALSE; /* default to false */ + + data->req.size = -1; /* make sure this is unknown at this point */ + + sshc->actualcode = CURLE_OK; /* reset error code */ + sshc->secondCreateDirs = 0; /* reset the create dir attempt state + variable */ + + Curl_pgrsSetUploadCounter(data, 0); + Curl_pgrsSetDownloadCounter(data, 0); + Curl_pgrsSetUploadSize(data, -1); + Curl_pgrsSetDownloadSize(data, -1); + + if(conn->handler->protocol & CURLPROTO_SCP) + result = scp_perform(conn, &connected, done); + else + result = sftp_perform(conn, &connected, done); + + return result; +} + +/* BLOCKING, but the function is using the state machine so the only reason + this is still blocking is that the multi interface code has no support for + disconnecting operations that takes a while */ +static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection) +{ + CURLcode result = CURLE_OK; + struct ssh_conn *ssh = &conn->proto.sshc; + (void) dead_connection; + + if(ssh->ssh_session) { + /* only if there's a session still around to use! */ + + state(conn, SSH_SESSION_DISCONNECT); + + result = ssh_block_statemach(conn, TRUE); + } + + return result; +} + +/* generic done function for both SCP and SFTP called from their specific + done functions */ +static CURLcode ssh_done(struct connectdata *conn, CURLcode status) +{ + CURLcode result = CURLE_OK; + struct SSHPROTO *sftp_scp = conn->data->req.protop; + + if(!status) { + /* run the state-machine */ + result = ssh_block_statemach(conn, FALSE); + } + else + result = status; + + if(sftp_scp) + Curl_safefree(sftp_scp->path); + if(Curl_pgrsDone(conn)) + return CURLE_ABORTED_BY_CALLBACK; + + conn->data->req.keepon = 0; /* clear all bits */ + return result; +} + + +static CURLcode scp_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + (void)premature; /* not used */ + + if(!status) + state(conn, SSH_SCP_DONE); + + return ssh_done(conn, status); + +} + +static ssize_t scp_send(struct connectdata *conn, int sockindex, + const void *mem, size_t len, CURLcode *err) +{ + ssize_t nwrite; + (void)sockindex; /* we only support SCP on the fixed known primary socket */ + + /* libssh2_channel_write() returns int! */ + nwrite = (ssize_t) + libssh2_channel_write(conn->proto.sshc.ssh_channel, mem, len); + + ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); + + if(nwrite == LIBSSH2_ERROR_EAGAIN) { + *err = CURLE_AGAIN; + nwrite = 0; + } + else if(nwrite < LIBSSH2_ERROR_NONE) { + *err = libssh2_session_error_to_CURLE((int)nwrite); + nwrite = -1; + } + + return nwrite; +} + +static ssize_t scp_recv(struct connectdata *conn, int sockindex, + char *mem, size_t len, CURLcode *err) +{ + ssize_t nread; + (void)sockindex; /* we only support SCP on the fixed known primary socket */ + + /* libssh2_channel_read() returns int */ + nread = (ssize_t) + libssh2_channel_read(conn->proto.sshc.ssh_channel, mem, len); + + ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); + if(nread == LIBSSH2_ERROR_EAGAIN) { + *err = CURLE_AGAIN; + nread = -1; + } + + return nread; +} + +/* + * =============== SFTP =============== + */ + +/* + *********************************************************************** + * + * sftp_perform() + * + * This is the actual DO function for SFTP. Get a file/directory according to + * the options previously setup. + */ + +static +CURLcode sftp_perform(struct connectdata *conn, + bool *connected, + bool *dophase_done) +{ + CURLcode result = CURLE_OK; + + DEBUGF(infof(conn->data, "DO phase starts\n")); + + *dophase_done = FALSE; /* not done yet */ + + /* start the first command in the DO phase */ + state(conn, SSH_SFTP_QUOTE_INIT); + + /* run the state-machine */ + result = ssh_multi_statemach(conn, dophase_done); + + *connected = conn->bits.tcpconnect[FIRSTSOCKET]; + + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + + return result; +} + +/* called from multi.c while DOing */ +static CURLcode sftp_doing(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result = ssh_multi_statemach(conn, dophase_done); + + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + return result; +} + +/* BLOCKING, but the function is using the state machine so the only reason + this is still blocking is that the multi interface code has no support for + disconnecting operations that takes a while */ +static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection) +{ + CURLcode result = CURLE_OK; + (void) dead_connection; + + DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n")); + + if(conn->proto.sshc.ssh_session) { + /* only if there's a session still around to use! */ + state(conn, SSH_SFTP_SHUTDOWN); + result = ssh_block_statemach(conn, TRUE); + } + + DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n")); + + return result; + +} + +static CURLcode sftp_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + struct ssh_conn *sshc = &conn->proto.sshc; + + if(!status) { + /* Post quote commands are executed after the SFTP_CLOSE state to avoid + errors that could happen due to open file handles during POSTQUOTE + operation */ + if(!premature && conn->data->set.postquote && !conn->bits.retry) + sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT; + state(conn, SSH_SFTP_CLOSE); + } + return ssh_done(conn, status); +} + +/* return number of sent bytes */ +static ssize_t sftp_send(struct connectdata *conn, int sockindex, + const void *mem, size_t len, CURLcode *err) +{ + ssize_t nwrite; /* libssh2_sftp_write() used to return size_t in 0.14 + but is changed to ssize_t in 0.15. These days we don't + support libssh2 0.15*/ + (void)sockindex; + + nwrite = libssh2_sftp_write(conn->proto.sshc.sftp_handle, mem, len); + + ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); + + if(nwrite == LIBSSH2_ERROR_EAGAIN) { + *err = CURLE_AGAIN; + nwrite = 0; + } + else if(nwrite < LIBSSH2_ERROR_NONE) { + *err = libssh2_session_error_to_CURLE((int)nwrite); + nwrite = -1; + } + + return nwrite; +} + +/* + * Return number of received (decrypted) bytes + * or <0 on error + */ +static ssize_t sftp_recv(struct connectdata *conn, int sockindex, + char *mem, size_t len, CURLcode *err) +{ + ssize_t nread; + (void)sockindex; + + nread = libssh2_sftp_read(conn->proto.sshc.sftp_handle, mem, len); + + ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); + + if(nread == LIBSSH2_ERROR_EAGAIN) { + *err = CURLE_AGAIN; + nread = -1; + + } + else if(nread < 0) { + *err = libssh2_session_error_to_CURLE((int)nread); + } + return nread; +} + +static const char *sftp_libssh2_strerror(int err) +{ + switch(err) { + case LIBSSH2_FX_NO_SUCH_FILE: + return "No such file or directory"; + + case LIBSSH2_FX_PERMISSION_DENIED: + return "Permission denied"; + + case LIBSSH2_FX_FAILURE: + return "Operation failed"; + + case LIBSSH2_FX_BAD_MESSAGE: + return "Bad message from SFTP server"; + + case LIBSSH2_FX_NO_CONNECTION: + return "Not connected to SFTP server"; + + case LIBSSH2_FX_CONNECTION_LOST: + return "Connection to SFTP server lost"; + + case LIBSSH2_FX_OP_UNSUPPORTED: + return "Operation not supported by SFTP server"; + + case LIBSSH2_FX_INVALID_HANDLE: + return "Invalid handle"; + + case LIBSSH2_FX_NO_SUCH_PATH: + return "No such file or directory"; + + case LIBSSH2_FX_FILE_ALREADY_EXISTS: + return "File already exists"; + + case LIBSSH2_FX_WRITE_PROTECT: + return "File is write protected"; + + case LIBSSH2_FX_NO_MEDIA: + return "No media"; + + case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM: + return "Disk full"; + + case LIBSSH2_FX_QUOTA_EXCEEDED: + return "User quota exceeded"; + + case LIBSSH2_FX_UNKNOWN_PRINCIPLE: + return "Unknown principle"; + + case LIBSSH2_FX_LOCK_CONFlICT: + return "File lock conflict"; + + case LIBSSH2_FX_DIR_NOT_EMPTY: + return "Directory not empty"; + + case LIBSSH2_FX_NOT_A_DIRECTORY: + return "Not a directory"; + + case LIBSSH2_FX_INVALID_FILENAME: + return "Invalid filename"; + + case LIBSSH2_FX_LINK_LOOP: + return "Link points to itself"; + } + return "Unknown error in libssh2"; +} + +#endif /* USE_LIBSSH2 */ diff --git a/dependencies/cmcurl/lib/ssh.h b/dependencies/cmcurl/lib/ssh.h new file mode 100644 index 0000000..0620aac --- /dev/null +++ b/dependencies/cmcurl/lib/ssh.h @@ -0,0 +1,245 @@ +#ifndef HEADER_CURL_SSH_H +#define HEADER_CURL_SSH_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(HAVE_LIBSSH2_H) +#include +#include +#elif defined(HAVE_LIBSSH_LIBSSH_H) +#include +#include +#endif /* HAVE_LIBSSH2_H */ + +/**************************************************************************** + * SSH unique setup + ***************************************************************************/ +typedef enum { + SSH_NO_STATE = -1, /* Used for "nextState" so say there is none */ + SSH_STOP = 0, /* do nothing state, stops the state machine */ + + SSH_INIT, /* First state in SSH-CONNECT */ + SSH_S_STARTUP, /* Session startup */ + SSH_HOSTKEY, /* verify hostkey */ + SSH_AUTHLIST, + SSH_AUTH_PKEY_INIT, + SSH_AUTH_PKEY, + SSH_AUTH_PASS_INIT, + SSH_AUTH_PASS, + SSH_AUTH_AGENT_INIT, /* initialize then wait for connection to agent */ + SSH_AUTH_AGENT_LIST, /* ask for list then wait for entire list to come */ + SSH_AUTH_AGENT, /* attempt one key at a time */ + SSH_AUTH_HOST_INIT, + SSH_AUTH_HOST, + SSH_AUTH_KEY_INIT, + SSH_AUTH_KEY, + SSH_AUTH_GSSAPI, + SSH_AUTH_DONE, + SSH_SFTP_INIT, + SSH_SFTP_REALPATH, /* Last state in SSH-CONNECT */ + + SSH_SFTP_QUOTE_INIT, /* First state in SFTP-DO */ + SSH_SFTP_POSTQUOTE_INIT, /* (Possibly) First state in SFTP-DONE */ + SSH_SFTP_QUOTE, + SSH_SFTP_NEXT_QUOTE, + SSH_SFTP_QUOTE_STAT, + SSH_SFTP_QUOTE_SETSTAT, + SSH_SFTP_QUOTE_SYMLINK, + SSH_SFTP_QUOTE_MKDIR, + SSH_SFTP_QUOTE_RENAME, + SSH_SFTP_QUOTE_RMDIR, + SSH_SFTP_QUOTE_UNLINK, + SSH_SFTP_QUOTE_STATVFS, + SSH_SFTP_GETINFO, + SSH_SFTP_FILETIME, + SSH_SFTP_TRANS_INIT, + SSH_SFTP_UPLOAD_INIT, + SSH_SFTP_CREATE_DIRS_INIT, + SSH_SFTP_CREATE_DIRS, + SSH_SFTP_CREATE_DIRS_MKDIR, + SSH_SFTP_READDIR_INIT, + SSH_SFTP_READDIR, + SSH_SFTP_READDIR_LINK, + SSH_SFTP_READDIR_BOTTOM, + SSH_SFTP_READDIR_DONE, + SSH_SFTP_DOWNLOAD_INIT, + SSH_SFTP_DOWNLOAD_STAT, /* Last state in SFTP-DO */ + SSH_SFTP_CLOSE, /* Last state in SFTP-DONE */ + SSH_SFTP_SHUTDOWN, /* First state in SFTP-DISCONNECT */ + SSH_SCP_TRANS_INIT, /* First state in SCP-DO */ + SSH_SCP_UPLOAD_INIT, + SSH_SCP_DOWNLOAD_INIT, + SSH_SCP_DOWNLOAD, + SSH_SCP_DONE, + SSH_SCP_SEND_EOF, + SSH_SCP_WAIT_EOF, + SSH_SCP_WAIT_CLOSE, + SSH_SCP_CHANNEL_FREE, /* Last state in SCP-DONE */ + SSH_SESSION_DISCONNECT, /* First state in SCP-DISCONNECT */ + SSH_SESSION_FREE, /* Last state in SCP/SFTP-DISCONNECT */ + SSH_QUIT, + SSH_LAST /* never used */ +} sshstate; + +/* this struct is used in the HandleData struct which is part of the + Curl_easy, which means this is used on a per-easy handle basis. + Everything that is strictly related to a connection is banned from this + struct. */ +struct SSHPROTO { + char *path; /* the path we operate on */ +}; + +/* ssh_conn is used for struct connection-oriented data in the connectdata + struct */ +struct ssh_conn { + const char *authlist; /* List of auth. methods, managed by libssh2 */ + + /* common */ + const char *passphrase; /* pass-phrase to use */ + char *rsa_pub; /* path name */ + char *rsa; /* path name */ + bool authed; /* the connection has been authenticated fine */ + sshstate state; /* always use ssh.c:state() to change state! */ + sshstate nextstate; /* the state to goto after stopping */ + CURLcode actualcode; /* the actual error code */ + struct curl_slist *quote_item; /* for the quote option */ + char *quote_path1; /* two generic pointers for the QUOTE stuff */ + char *quote_path2; + + bool acceptfail; /* used by the SFTP_QUOTE (continue if + quote command fails) */ + char *homedir; /* when doing SFTP we figure out home dir in the + connect phase */ + size_t readdir_len, readdir_totalLen, readdir_currLen; + char *readdir_line; + char *readdir_linkPath; + /* end of READDIR stuff */ + + int secondCreateDirs; /* counter use by the code to see if the + second attempt has been made to change + to/create a directory */ + char *slash_pos; /* used by the SFTP_CREATE_DIRS state */ + + int orig_waitfor; /* default READ/WRITE bits wait for */ + +#if defined(USE_LIBSSH) +/* our variables */ + unsigned kbd_state; /* 0 or 1 */ + ssh_key privkey; + ssh_key pubkey; + int auth_methods; + ssh_session ssh_session; + ssh_scp scp_session; + sftp_session sftp_session; + sftp_file sftp_file; + sftp_dir sftp_dir; + + unsigned sftp_recv_state; /* 0 or 1 */ + int sftp_file_index; /* for async read */ + sftp_attributes readdir_attrs; /* used by the SFTP readdir actions */ + sftp_attributes readdir_link_attrs; /* used by the SFTP readdir actions */ + sftp_attributes quote_attrs; /* used by the SFTP_QUOTE state */ + + const char *readdir_filename; /* points within readdir_attrs */ + const char *readdir_longentry; + char *readdir_tmp; +#elif defined(USE_LIBSSH2) + char *readdir_filename; + char *readdir_longentry; + + LIBSSH2_SFTP_ATTRIBUTES quote_attrs; /* used by the SFTP_QUOTE state */ + + /* Here's a set of struct members used by the SFTP_READDIR state */ + LIBSSH2_SFTP_ATTRIBUTES readdir_attrs; + LIBSSH2_SESSION *ssh_session; /* Secure Shell session */ + LIBSSH2_CHANNEL *ssh_channel; /* Secure Shell channel handle */ + LIBSSH2_SFTP *sftp_session; /* SFTP handle */ + LIBSSH2_SFTP_HANDLE *sftp_handle; + +#ifdef HAVE_LIBSSH2_AGENT_API + LIBSSH2_AGENT *ssh_agent; /* proxy to ssh-agent/pageant */ + struct libssh2_agent_publickey *sshagent_identity, + *sshagent_prev_identity; +#endif + + /* note that HAVE_LIBSSH2_KNOWNHOST_API is a define set in the libssh2.h + header */ +#ifdef HAVE_LIBSSH2_KNOWNHOST_API + LIBSSH2_KNOWNHOSTS *kh; +#endif +#endif /* USE_LIBSSH */ +}; + +#if defined(USE_LIBSSH) + +#define CURL_LIBSSH_VERSION ssh_version(0) + +extern const struct Curl_handler Curl_handler_scp; +extern const struct Curl_handler Curl_handler_sftp; + +#elif defined(USE_LIBSSH2) + +/* Feature detection based on version numbers to better work with + non-configure platforms */ + +#if !defined(LIBSSH2_VERSION_NUM) || (LIBSSH2_VERSION_NUM < 0x001000) +# error "SCP/SFTP protocols require libssh2 0.16 or later" +#endif + +#if LIBSSH2_VERSION_NUM >= 0x010000 +#define HAVE_LIBSSH2_SFTP_SEEK64 1 +#endif + +#if LIBSSH2_VERSION_NUM >= 0x010100 +#define HAVE_LIBSSH2_VERSION 1 +#endif + +#if LIBSSH2_VERSION_NUM >= 0x010205 +#define HAVE_LIBSSH2_INIT 1 +#define HAVE_LIBSSH2_EXIT 1 +#endif + +#if LIBSSH2_VERSION_NUM >= 0x010206 +#define HAVE_LIBSSH2_KNOWNHOST_CHECKP 1 +#define HAVE_LIBSSH2_SCP_SEND64 1 +#endif + +#if LIBSSH2_VERSION_NUM >= 0x010208 +#define HAVE_LIBSSH2_SESSION_HANDSHAKE 1 +#endif + +#ifdef HAVE_LIBSSH2_VERSION +/* get it run-time if possible */ +#define CURL_LIBSSH2_VERSION libssh2_version(0) +#else +/* use build-time if run-time not possible */ +#define CURL_LIBSSH2_VERSION LIBSSH2_VERSION +#endif + +extern const struct Curl_handler Curl_handler_scp; +extern const struct Curl_handler Curl_handler_sftp; + +#endif /* USE_LIBSSH2 */ + +#endif /* HEADER_CURL_SSH_H */ diff --git a/dependencies/cmcurl/lib/strcase.c b/dependencies/cmcurl/lib/strcase.c new file mode 100644 index 0000000..24bcca9 --- /dev/null +++ b/dependencies/cmcurl/lib/strcase.c @@ -0,0 +1,177 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "strcase.h" + +/* Portable, consistent toupper (remember EBCDIC). Do not use toupper() because + its behavior is altered by the current locale. */ +char Curl_raw_toupper(char in) +{ +#if !defined(CURL_DOES_CONVERSIONS) + if(in >= 'a' && in <= 'z') + return (char)('A' + in - 'a'); +#else + switch(in) { + case 'a': + return 'A'; + case 'b': + return 'B'; + case 'c': + return 'C'; + case 'd': + return 'D'; + case 'e': + return 'E'; + case 'f': + return 'F'; + case 'g': + return 'G'; + case 'h': + return 'H'; + case 'i': + return 'I'; + case 'j': + return 'J'; + case 'k': + return 'K'; + case 'l': + return 'L'; + case 'm': + return 'M'; + case 'n': + return 'N'; + case 'o': + return 'O'; + case 'p': + return 'P'; + case 'q': + return 'Q'; + case 'r': + return 'R'; + case 's': + return 'S'; + case 't': + return 'T'; + case 'u': + return 'U'; + case 'v': + return 'V'; + case 'w': + return 'W'; + case 'x': + return 'X'; + case 'y': + return 'Y'; + case 'z': + return 'Z'; + } +#endif + + return in; +} + +/* + * Curl_strcasecompare() is for doing "raw" case insensitive strings. This is + * meant to be locale independent and only compare strings we know are safe + * for this. See + * https://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for some + * further explanation to why this function is necessary. + * + * The function is capable of comparing a-z case insensitively even for + * non-ascii. + * + * @unittest: 1301 + */ + +int Curl_strcasecompare(const char *first, const char *second) +{ + while(*first && *second) { + if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) + /* get out of the loop as soon as they don't match */ + break; + first++; + second++; + } + /* we do the comparison here (possibly again), just to make sure that if the + loop above is skipped because one of the strings reached zero, we must not + return this as a successful match */ + return (Curl_raw_toupper(*first) == Curl_raw_toupper(*second)); +} + +int Curl_safe_strcasecompare(const char *first, const char *second) +{ + if(first && second) + /* both pointers point to something then compare them */ + return Curl_strcasecompare(first, second); + + /* if both pointers are NULL then treat them as equal */ + return (NULL == first && NULL == second); +} + +/* + * @unittest: 1301 + */ +int Curl_strncasecompare(const char *first, const char *second, size_t max) +{ + while(*first && *second && max) { + if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) { + break; + } + max--; + first++; + second++; + } + if(0 == max) + return 1; /* they are equal this far */ + + return Curl_raw_toupper(*first) == Curl_raw_toupper(*second); +} + +/* Copy an upper case version of the string from src to dest. The + * strings may overlap. No more than n characters of the string are copied + * (including any NUL) and the destination string will NOT be + * NUL-terminated if that limit is reached. + */ +void Curl_strntoupper(char *dest, const char *src, size_t n) +{ + if(n < 1) + return; + + do { + *dest++ = Curl_raw_toupper(*src); + } while(*src++ && --n); +} + +/* --- public functions --- */ + +int curl_strequal(const char *first, const char *second) +{ + return Curl_strcasecompare(first, second); +} +int curl_strnequal(const char *first, const char *second, size_t max) +{ + return Curl_strncasecompare(first, second, max); +} diff --git a/dependencies/cmcurl/lib/strcase.h b/dependencies/cmcurl/lib/strcase.h new file mode 100644 index 0000000..6fee384 --- /dev/null +++ b/dependencies/cmcurl/lib/strcase.h @@ -0,0 +1,50 @@ +#ifndef HEADER_CURL_STRCASE_H +#define HEADER_CURL_STRCASE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +/* + * Only "raw" case insensitive strings. This is meant to be locale independent + * and only compare strings we know are safe for this. + * + * The function is capable of comparing a-z case insensitively even for + * non-ascii. + */ + +#define strcasecompare(a,b) Curl_strcasecompare(a,b) +#define strncasecompare(a,b,c) Curl_strncasecompare(a,b,c) + +int Curl_strcasecompare(const char *first, const char *second); +int Curl_safe_strcasecompare(const char *first, const char *second); +int Curl_strncasecompare(const char *first, const char *second, size_t max); + +char Curl_raw_toupper(char in); + +/* checkprefix() is a shorter version of the above, used when the first + argument is zero-byte terminated */ +#define checkprefix(a,b) curl_strnequal(a,b,strlen(a)) + +void Curl_strntoupper(char *dest, const char *src, size_t n); + +#endif /* HEADER_CURL_STRCASE_H */ diff --git a/dependencies/cmcurl/lib/strdup.c b/dependencies/cmcurl/lib/strdup.c new file mode 100644 index 0000000..51e7978 --- /dev/null +++ b/dependencies/cmcurl/lib/strdup.c @@ -0,0 +1,100 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "strdup.h" +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +#ifndef HAVE_STRDUP +char *curlx_strdup(const char *str) +{ + size_t len; + char *newstr; + + if(!str) + return (char *)NULL; + + len = strlen(str); + + if(len >= ((size_t)-1) / sizeof(char)) + return (char *)NULL; + + newstr = malloc((len + 1)*sizeof(char)); + if(!newstr) + return (char *)NULL; + + memcpy(newstr, str, (len + 1)*sizeof(char)); + + return newstr; + +} +#endif + +/*************************************************************************** + * + * Curl_memdup(source, length) + * + * Copies the 'source' data to a newly allocated buffer (that is + * returned). Copies 'length' bytes. + * + * Returns the new pointer or NULL on failure. + * + ***************************************************************************/ +void *Curl_memdup(const void *src, size_t length) +{ + void *buffer = malloc(length); + if(!buffer) + return NULL; /* fail */ + + memcpy(buffer, src, length); + + return buffer; +} + +/*************************************************************************** + * + * Curl_saferealloc(ptr, size) + * + * Does a normal realloc(), but will free the data pointer if the realloc + * fails. If 'size' is non-zero, it will free the data and return a failure. + * + * This convenience function is provided and used to help us avoid a common + * mistake pattern when we could pass in a zero, catch the NULL return and end + * up free'ing the memory twice. + * + * Returns the new pointer or NULL on failure. + * + ***************************************************************************/ +void *Curl_saferealloc(void *ptr, size_t size) +{ + void *datap = realloc(ptr, size); + if(size && !datap) + /* only free 'ptr' if size was non-zero */ + free(ptr); + return datap; +} diff --git a/dependencies/cmcurl/lib/strdup.h b/dependencies/cmcurl/lib/strdup.h new file mode 100644 index 0000000..ae3d5d0 --- /dev/null +++ b/dependencies/cmcurl/lib/strdup.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_STRDUP_H +#define HEADER_CURL_STRDUP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifndef HAVE_STRDUP +extern char *curlx_strdup(const char *str); +#endif +void *Curl_memdup(const void *src, size_t buffer_length); +void *Curl_saferealloc(void *ptr, size_t size); + +#endif /* HEADER_CURL_STRDUP_H */ diff --git a/dependencies/cmcurl/lib/strerror.c b/dependencies/cmcurl/lib/strerror.c new file mode 100644 index 0000000..e273f37 --- /dev/null +++ b/dependencies/cmcurl/lib/strerror.c @@ -0,0 +1,1102 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2004 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_STRERROR_R +# if (!defined(HAVE_POSIX_STRERROR_R) && \ + !defined(HAVE_GLIBC_STRERROR_R) && \ + !defined(HAVE_VXWORKS_STRERROR_R)) || \ + (defined(HAVE_POSIX_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)) || \ + (defined(HAVE_GLIBC_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)) || \ + (defined(HAVE_POSIX_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R)) +# error "strerror_r MUST be either POSIX, glibc or vxworks-style" +# endif +#endif + +#include + +#ifdef USE_LIBIDN2 +#include +#endif + +#ifdef USE_WINDOWS_SSPI +#include "curl_sspi.h" +#endif + +#include "strerror.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#if defined(WIN32) || defined(_WIN32_WCE) +#define PRESERVE_WINDOWS_ERROR_CODE +#endif + +const char * +curl_easy_strerror(CURLcode error) +{ +#ifndef CURL_DISABLE_VERBOSE_STRINGS + switch(error) { + case CURLE_OK: + return "No error"; + + case CURLE_UNSUPPORTED_PROTOCOL: + return "Unsupported protocol"; + + case CURLE_FAILED_INIT: + return "Failed initialization"; + + case CURLE_URL_MALFORMAT: + return "URL using bad/illegal format or missing URL"; + + case CURLE_NOT_BUILT_IN: + return "A requested feature, protocol or option was not found built-in in" + " this libcurl due to a build-time decision."; + + case CURLE_COULDNT_RESOLVE_PROXY: + return "Couldn't resolve proxy name"; + + case CURLE_COULDNT_RESOLVE_HOST: + return "Couldn't resolve host name"; + + case CURLE_COULDNT_CONNECT: + return "Couldn't connect to server"; + + case CURLE_WEIRD_SERVER_REPLY: + return "Weird server reply"; + + case CURLE_REMOTE_ACCESS_DENIED: + return "Access denied to remote resource"; + + case CURLE_FTP_ACCEPT_FAILED: + return "FTP: The server failed to connect to data port"; + + case CURLE_FTP_ACCEPT_TIMEOUT: + return "FTP: Accepting server connect has timed out"; + + case CURLE_FTP_PRET_FAILED: + return "FTP: The server did not accept the PRET command."; + + case CURLE_FTP_WEIRD_PASS_REPLY: + return "FTP: unknown PASS reply"; + + case CURLE_FTP_WEIRD_PASV_REPLY: + return "FTP: unknown PASV reply"; + + case CURLE_FTP_WEIRD_227_FORMAT: + return "FTP: unknown 227 response format"; + + case CURLE_FTP_CANT_GET_HOST: + return "FTP: can't figure out the host in the PASV response"; + + case CURLE_HTTP2: + return "Error in the HTTP2 framing layer"; + + case CURLE_FTP_COULDNT_SET_TYPE: + return "FTP: couldn't set file type"; + + case CURLE_PARTIAL_FILE: + return "Transferred a partial file"; + + case CURLE_FTP_COULDNT_RETR_FILE: + return "FTP: couldn't retrieve (RETR failed) the specified file"; + + case CURLE_QUOTE_ERROR: + return "Quote command returned error"; + + case CURLE_HTTP_RETURNED_ERROR: + return "HTTP response code said error"; + + case CURLE_WRITE_ERROR: + return "Failed writing received data to disk/application"; + + case CURLE_UPLOAD_FAILED: + return "Upload failed (at start/before it took off)"; + + case CURLE_READ_ERROR: + return "Failed to open/read local data from file/application"; + + case CURLE_OUT_OF_MEMORY: + return "Out of memory"; + + case CURLE_OPERATION_TIMEDOUT: + return "Timeout was reached"; + + case CURLE_FTP_PORT_FAILED: + return "FTP: command PORT failed"; + + case CURLE_FTP_COULDNT_USE_REST: + return "FTP: command REST failed"; + + case CURLE_RANGE_ERROR: + return "Requested range was not delivered by the server"; + + case CURLE_HTTP_POST_ERROR: + return "Internal problem setting up the POST"; + + case CURLE_SSL_CONNECT_ERROR: + return "SSL connect error"; + + case CURLE_BAD_DOWNLOAD_RESUME: + return "Couldn't resume download"; + + case CURLE_FILE_COULDNT_READ_FILE: + return "Couldn't read a file:// file"; + + case CURLE_LDAP_CANNOT_BIND: + return "LDAP: cannot bind"; + + case CURLE_LDAP_SEARCH_FAILED: + return "LDAP: search failed"; + + case CURLE_FUNCTION_NOT_FOUND: + return "A required function in the library was not found"; + + case CURLE_ABORTED_BY_CALLBACK: + return "Operation was aborted by an application callback"; + + case CURLE_BAD_FUNCTION_ARGUMENT: + return "A libcurl function was given a bad argument"; + + case CURLE_INTERFACE_FAILED: + return "Failed binding local connection end"; + + case CURLE_TOO_MANY_REDIRECTS : + return "Number of redirects hit maximum amount"; + + case CURLE_UNKNOWN_OPTION: + return "An unknown option was passed in to libcurl"; + + case CURLE_TELNET_OPTION_SYNTAX : + return "Malformed telnet option"; + + case CURLE_GOT_NOTHING: + return "Server returned nothing (no headers, no data)"; + + case CURLE_SSL_ENGINE_NOTFOUND: + return "SSL crypto engine not found"; + + case CURLE_SSL_ENGINE_SETFAILED: + return "Can not set SSL crypto engine as default"; + + case CURLE_SSL_ENGINE_INITFAILED: + return "Failed to initialise SSL crypto engine"; + + case CURLE_SEND_ERROR: + return "Failed sending data to the peer"; + + case CURLE_RECV_ERROR: + return "Failure when receiving data from the peer"; + + case CURLE_SSL_CERTPROBLEM: + return "Problem with the local SSL certificate"; + + case CURLE_SSL_CIPHER: + return "Couldn't use specified SSL cipher"; + + case CURLE_PEER_FAILED_VERIFICATION: + return "SSL peer certificate or SSH remote key was not OK"; + + case CURLE_SSL_CACERT_BADFILE: + return "Problem with the SSL CA cert (path? access rights?)"; + + case CURLE_BAD_CONTENT_ENCODING: + return "Unrecognized or bad HTTP Content or Transfer-Encoding"; + + case CURLE_LDAP_INVALID_URL: + return "Invalid LDAP URL"; + + case CURLE_FILESIZE_EXCEEDED: + return "Maximum file size exceeded"; + + case CURLE_USE_SSL_FAILED: + return "Requested SSL level failed"; + + case CURLE_SSL_SHUTDOWN_FAILED: + return "Failed to shut down the SSL connection"; + + case CURLE_SSL_CRL_BADFILE: + return "Failed to load CRL file (path? access rights?, format?)"; + + case CURLE_SSL_ISSUER_ERROR: + return "Issuer check against peer certificate failed"; + + case CURLE_SEND_FAIL_REWIND: + return "Send failed since rewinding of the data stream failed"; + + case CURLE_LOGIN_DENIED: + return "Login denied"; + + case CURLE_TFTP_NOTFOUND: + return "TFTP: File Not Found"; + + case CURLE_TFTP_PERM: + return "TFTP: Access Violation"; + + case CURLE_REMOTE_DISK_FULL: + return "Disk full or allocation exceeded"; + + case CURLE_TFTP_ILLEGAL: + return "TFTP: Illegal operation"; + + case CURLE_TFTP_UNKNOWNID: + return "TFTP: Unknown transfer ID"; + + case CURLE_REMOTE_FILE_EXISTS: + return "Remote file already exists"; + + case CURLE_TFTP_NOSUCHUSER: + return "TFTP: No such user"; + + case CURLE_CONV_FAILED: + return "Conversion failed"; + + case CURLE_CONV_REQD: + return "Caller must register CURLOPT_CONV_ callback options"; + + case CURLE_REMOTE_FILE_NOT_FOUND: + return "Remote file not found"; + + case CURLE_SSH: + return "Error in the SSH layer"; + + case CURLE_AGAIN: + return "Socket not ready for send/recv"; + + case CURLE_RTSP_CSEQ_ERROR: + return "RTSP CSeq mismatch or invalid CSeq"; + + case CURLE_RTSP_SESSION_ERROR: + return "RTSP session error"; + + case CURLE_FTP_BAD_FILE_LIST: + return "Unable to parse FTP file list"; + + case CURLE_CHUNK_FAILED: + return "Chunk callback failed"; + + case CURLE_NO_CONNECTION_AVAILABLE: + return "The max connection limit is reached"; + + case CURLE_SSL_PINNEDPUBKEYNOTMATCH: + return "SSL public key does not match pinned public key"; + + case CURLE_SSL_INVALIDCERTSTATUS: + return "SSL server certificate status verification FAILED"; + + case CURLE_HTTP2_STREAM: + return "Stream error in the HTTP/2 framing layer"; + + case CURLE_RECURSIVE_API_CALL: + return "API function called from within callback"; + + /* error codes not used by current libcurl */ + case CURLE_OBSOLETE20: + case CURLE_OBSOLETE24: + case CURLE_OBSOLETE29: + case CURLE_OBSOLETE32: + case CURLE_OBSOLETE40: + case CURLE_OBSOLETE44: + case CURLE_OBSOLETE46: + case CURLE_OBSOLETE50: + case CURLE_OBSOLETE51: + case CURLE_OBSOLETE57: + case CURL_LAST: + break; + } + /* + * By using a switch, gcc -Wall will complain about enum values + * which do not appear, helping keep this function up-to-date. + * By using gcc -Wall -Werror, you can't forget. + * + * A table would not have the same benefit. Most compilers will + * generate code very similar to a table in any case, so there + * is little performance gain from a table. And something is broken + * for the user's application, anyways, so does it matter how fast + * it _doesn't_ work? + * + * The line number for the error will be near this comment, which + * is why it is here, and not at the start of the switch. + */ + return "Unknown error"; +#else + if(!error) + return "No error"; + else + return "Error"; +#endif +} + +const char * +curl_multi_strerror(CURLMcode error) +{ +#ifndef CURL_DISABLE_VERBOSE_STRINGS + switch(error) { + case CURLM_CALL_MULTI_PERFORM: + return "Please call curl_multi_perform() soon"; + + case CURLM_OK: + return "No error"; + + case CURLM_BAD_HANDLE: + return "Invalid multi handle"; + + case CURLM_BAD_EASY_HANDLE: + return "Invalid easy handle"; + + case CURLM_OUT_OF_MEMORY: + return "Out of memory"; + + case CURLM_INTERNAL_ERROR: + return "Internal error"; + + case CURLM_BAD_SOCKET: + return "Invalid socket argument"; + + case CURLM_UNKNOWN_OPTION: + return "Unknown option"; + + case CURLM_ADDED_ALREADY: + return "The easy handle is already added to a multi handle"; + + case CURLM_RECURSIVE_API_CALL: + return "API function called from within callback"; + + case CURLM_LAST: + break; + } + + return "Unknown error"; +#else + if(error == CURLM_OK) + return "No error"; + else + return "Error"; +#endif +} + +const char * +curl_share_strerror(CURLSHcode error) +{ +#ifndef CURL_DISABLE_VERBOSE_STRINGS + switch(error) { + case CURLSHE_OK: + return "No error"; + + case CURLSHE_BAD_OPTION: + return "Unknown share option"; + + case CURLSHE_IN_USE: + return "Share currently in use"; + + case CURLSHE_INVALID: + return "Invalid share handle"; + + case CURLSHE_NOMEM: + return "Out of memory"; + + case CURLSHE_NOT_BUILT_IN: + return "Feature not enabled in this library"; + + case CURLSHE_LAST: + break; + } + + return "CURLSHcode unknown"; +#else + if(error == CURLSHE_OK) + return "No error"; + else + return "Error"; +#endif +} + +#ifdef USE_WINSOCK + +/* This function handles most / all (?) Winsock errors curl is able to produce. + */ +static const char * +get_winsock_error (int err, char *buf, size_t len) +{ +#ifdef PRESERVE_WINDOWS_ERROR_CODE + DWORD old_win_err = GetLastError(); +#endif + int old_errno = errno; + const char *p; + +#ifndef CURL_DISABLE_VERBOSE_STRINGS + switch(err) { + case WSAEINTR: + p = "Call interrupted"; + break; + case WSAEBADF: + p = "Bad file"; + break; + case WSAEACCES: + p = "Bad access"; + break; + case WSAEFAULT: + p = "Bad argument"; + break; + case WSAEINVAL: + p = "Invalid arguments"; + break; + case WSAEMFILE: + p = "Out of file descriptors"; + break; + case WSAEWOULDBLOCK: + p = "Call would block"; + break; + case WSAEINPROGRESS: + case WSAEALREADY: + p = "Blocking call in progress"; + break; + case WSAENOTSOCK: + p = "Descriptor is not a socket"; + break; + case WSAEDESTADDRREQ: + p = "Need destination address"; + break; + case WSAEMSGSIZE: + p = "Bad message size"; + break; + case WSAEPROTOTYPE: + p = "Bad protocol"; + break; + case WSAENOPROTOOPT: + p = "Protocol option is unsupported"; + break; + case WSAEPROTONOSUPPORT: + p = "Protocol is unsupported"; + break; + case WSAESOCKTNOSUPPORT: + p = "Socket is unsupported"; + break; + case WSAEOPNOTSUPP: + p = "Operation not supported"; + break; + case WSAEAFNOSUPPORT: + p = "Address family not supported"; + break; + case WSAEPFNOSUPPORT: + p = "Protocol family not supported"; + break; + case WSAEADDRINUSE: + p = "Address already in use"; + break; + case WSAEADDRNOTAVAIL: + p = "Address not available"; + break; + case WSAENETDOWN: + p = "Network down"; + break; + case WSAENETUNREACH: + p = "Network unreachable"; + break; + case WSAENETRESET: + p = "Network has been reset"; + break; + case WSAECONNABORTED: + p = "Connection was aborted"; + break; + case WSAECONNRESET: + p = "Connection was reset"; + break; + case WSAENOBUFS: + p = "No buffer space"; + break; + case WSAEISCONN: + p = "Socket is already connected"; + break; + case WSAENOTCONN: + p = "Socket is not connected"; + break; + case WSAESHUTDOWN: + p = "Socket has been shut down"; + break; + case WSAETOOMANYREFS: + p = "Too many references"; + break; + case WSAETIMEDOUT: + p = "Timed out"; + break; + case WSAECONNREFUSED: + p = "Connection refused"; + break; + case WSAELOOP: + p = "Loop??"; + break; + case WSAENAMETOOLONG: + p = "Name too long"; + break; + case WSAEHOSTDOWN: + p = "Host down"; + break; + case WSAEHOSTUNREACH: + p = "Host unreachable"; + break; + case WSAENOTEMPTY: + p = "Not empty"; + break; + case WSAEPROCLIM: + p = "Process limit reached"; + break; + case WSAEUSERS: + p = "Too many users"; + break; + case WSAEDQUOT: + p = "Bad quota"; + break; + case WSAESTALE: + p = "Something is stale"; + break; + case WSAEREMOTE: + p = "Remote error"; + break; +#ifdef WSAEDISCON /* missing in SalfordC! */ + case WSAEDISCON: + p = "Disconnected"; + break; +#endif + /* Extended Winsock errors */ + case WSASYSNOTREADY: + p = "Winsock library is not ready"; + break; + case WSANOTINITIALISED: + p = "Winsock library not initialised"; + break; + case WSAVERNOTSUPPORTED: + p = "Winsock version not supported"; + break; + + /* getXbyY() errors (already handled in herrmsg): + * Authoritative Answer: Host not found */ + case WSAHOST_NOT_FOUND: + p = "Host not found"; + break; + + /* Non-Authoritative: Host not found, or SERVERFAIL */ + case WSATRY_AGAIN: + p = "Host not found, try again"; + break; + + /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ + case WSANO_RECOVERY: + p = "Unrecoverable error in call to nameserver"; + break; + + /* Valid name, no data record of requested type */ + case WSANO_DATA: + p = "No data record of requested type"; + break; + + default: + return NULL; + } +#else + if(!err) + return NULL; + else + p = "error"; +#endif + strncpy(buf, p, len); + buf [len-1] = '\0'; + + if(errno != old_errno) + errno = old_errno; + +#ifdef PRESERVE_WINDOWS_ERROR_CODE + if(old_win_err != GetLastError()) + SetLastError(old_win_err); +#endif + + return buf; +} +#endif /* USE_WINSOCK */ + +/* + * Our thread-safe and smart strerror() replacement. + * + * The 'err' argument passed in to this function MUST be a true errno number + * as reported on this system. We do no range checking on the number before + * we pass it to the "number-to-message" conversion function and there might + * be systems that don't do proper range checking in there themselves. + * + * We don't do range checking (on systems other than Windows) since there is + * no good reliable and portable way to do it. + */ +const char *Curl_strerror(int err, char *buf, size_t buflen) +{ +#ifdef PRESERVE_WINDOWS_ERROR_CODE + DWORD old_win_err = GetLastError(); +#endif + int old_errno = errno; + char *p; + size_t max; + + DEBUGASSERT(err >= 0); + + max = buflen - 1; + *buf = '\0'; + +#ifdef USE_WINSOCK + +#ifdef _WIN32_WCE + { + wchar_t wbuf[256]; + wbuf[0] = L'\0'; + + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, + LANG_NEUTRAL, wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL); + wcstombs(buf, wbuf, max); + } +#else + /* 'sys_nerr' is the maximum errno number, it is not widely portable */ + if(err >= 0 && err < sys_nerr) + strncpy(buf, strerror(err), max); + else { + if(!get_winsock_error(err, buf, max) && + !FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, + LANG_NEUTRAL, buf, (DWORD)max, NULL)) + msnprintf(buf, max, "Unknown error %d (%#x)", err, err); + } +#endif + +#else /* not USE_WINSOCK coming up */ + +#if defined(HAVE_STRERROR_R) && defined(HAVE_POSIX_STRERROR_R) + /* + * The POSIX-style strerror_r() may set errno to ERANGE if insufficient + * storage is supplied via 'strerrbuf' and 'buflen' to hold the generated + * message string, or EINVAL if 'errnum' is not a valid error number. + */ + if(0 != strerror_r(err, buf, max)) { + if('\0' == buf[0]) + msnprintf(buf, max, "Unknown error %d", err); + } +#elif defined(HAVE_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R) + /* + * The glibc-style strerror_r() only *might* use the buffer we pass to + * the function, but it always returns the error message as a pointer, + * so we must copy that string unconditionally (if non-NULL). + */ + { + char buffer[256]; + char *msg = strerror_r(err, buffer, sizeof(buffer)); + if(msg) + strncpy(buf, msg, max); + else + msnprintf(buf, max, "Unknown error %d", err); + } +#elif defined(HAVE_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R) + /* + * The vxworks-style strerror_r() does use the buffer we pass to the function. + * The buffer size should be at least NAME_MAX (256) + */ + { + char buffer[256]; + if(OK == strerror_r(err, buffer)) + strncpy(buf, buffer, max); + else + msnprintf(buf, max, "Unknown error %d", err); + } +#else + { + char *msg = strerror(err); + if(msg) + strncpy(buf, msg, max); + else + msnprintf(buf, max, "Unknown error %d", err); + } +#endif + +#endif /* end of ! USE_WINSOCK */ + + buf[max] = '\0'; /* make sure the string is zero terminated */ + + /* strip trailing '\r\n' or '\n'. */ + p = strrchr(buf, '\n'); + if(p && (p - buf) >= 2) + *p = '\0'; + p = strrchr(buf, '\r'); + if(p && (p - buf) >= 1) + *p = '\0'; + + if(errno != old_errno) + errno = old_errno; + +#ifdef PRESERVE_WINDOWS_ERROR_CODE + if(old_win_err != GetLastError()) + SetLastError(old_win_err); +#endif + + return buf; +} + +#ifdef USE_WINDOWS_SSPI +const char *Curl_sspi_strerror(int err, char *buf, size_t buflen) +{ +#ifdef PRESERVE_WINDOWS_ERROR_CODE + DWORD old_win_err = GetLastError(); +#endif + int old_errno = errno; + const char *txt; + char *outbuf; + size_t outmax; +#ifndef CURL_DISABLE_VERBOSE_STRINGS + char txtbuf[80]; + char msgbuf[256]; + char *p, *str, *msg = NULL; + bool msg_formatted = FALSE; +#endif + + outbuf = buf; + outmax = buflen - 1; + *outbuf = '\0'; + +#ifndef CURL_DISABLE_VERBOSE_STRINGS + + switch(err) { + case SEC_E_OK: + txt = "No error"; + break; + case CRYPT_E_REVOKED: + txt = "CRYPT_E_REVOKED"; + break; + case SEC_E_ALGORITHM_MISMATCH: + txt = "SEC_E_ALGORITHM_MISMATCH"; + break; + case SEC_E_BAD_BINDINGS: + txt = "SEC_E_BAD_BINDINGS"; + break; + case SEC_E_BAD_PKGID: + txt = "SEC_E_BAD_PKGID"; + break; + case SEC_E_BUFFER_TOO_SMALL: + txt = "SEC_E_BUFFER_TOO_SMALL"; + break; + case SEC_E_CANNOT_INSTALL: + txt = "SEC_E_CANNOT_INSTALL"; + break; + case SEC_E_CANNOT_PACK: + txt = "SEC_E_CANNOT_PACK"; + break; + case SEC_E_CERT_EXPIRED: + txt = "SEC_E_CERT_EXPIRED"; + break; + case SEC_E_CERT_UNKNOWN: + txt = "SEC_E_CERT_UNKNOWN"; + break; + case SEC_E_CERT_WRONG_USAGE: + txt = "SEC_E_CERT_WRONG_USAGE"; + break; + case SEC_E_CONTEXT_EXPIRED: + txt = "SEC_E_CONTEXT_EXPIRED"; + break; + case SEC_E_CROSSREALM_DELEGATION_FAILURE: + txt = "SEC_E_CROSSREALM_DELEGATION_FAILURE"; + break; + case SEC_E_CRYPTO_SYSTEM_INVALID: + txt = "SEC_E_CRYPTO_SYSTEM_INVALID"; + break; + case SEC_E_DECRYPT_FAILURE: + txt = "SEC_E_DECRYPT_FAILURE"; + break; + case SEC_E_DELEGATION_POLICY: + txt = "SEC_E_DELEGATION_POLICY"; + break; + case SEC_E_DELEGATION_REQUIRED: + txt = "SEC_E_DELEGATION_REQUIRED"; + break; + case SEC_E_DOWNGRADE_DETECTED: + txt = "SEC_E_DOWNGRADE_DETECTED"; + break; + case SEC_E_ENCRYPT_FAILURE: + txt = "SEC_E_ENCRYPT_FAILURE"; + break; + case SEC_E_ILLEGAL_MESSAGE: + txt = "SEC_E_ILLEGAL_MESSAGE"; + break; + case SEC_E_INCOMPLETE_CREDENTIALS: + txt = "SEC_E_INCOMPLETE_CREDENTIALS"; + break; + case SEC_E_INCOMPLETE_MESSAGE: + txt = "SEC_E_INCOMPLETE_MESSAGE"; + break; + case SEC_E_INSUFFICIENT_MEMORY: + txt = "SEC_E_INSUFFICIENT_MEMORY"; + break; + case SEC_E_INTERNAL_ERROR: + txt = "SEC_E_INTERNAL_ERROR"; + break; + case SEC_E_INVALID_HANDLE: + txt = "SEC_E_INVALID_HANDLE"; + break; + case SEC_E_INVALID_PARAMETER: + txt = "SEC_E_INVALID_PARAMETER"; + break; + case SEC_E_INVALID_TOKEN: + txt = "SEC_E_INVALID_TOKEN"; + break; + case SEC_E_ISSUING_CA_UNTRUSTED: + txt = "SEC_E_ISSUING_CA_UNTRUSTED"; + break; + case SEC_E_ISSUING_CA_UNTRUSTED_KDC: + txt = "SEC_E_ISSUING_CA_UNTRUSTED_KDC"; + break; + case SEC_E_KDC_CERT_EXPIRED: + txt = "SEC_E_KDC_CERT_EXPIRED"; + break; + case SEC_E_KDC_CERT_REVOKED: + txt = "SEC_E_KDC_CERT_REVOKED"; + break; + case SEC_E_KDC_INVALID_REQUEST: + txt = "SEC_E_KDC_INVALID_REQUEST"; + break; + case SEC_E_KDC_UNABLE_TO_REFER: + txt = "SEC_E_KDC_UNABLE_TO_REFER"; + break; + case SEC_E_KDC_UNKNOWN_ETYPE: + txt = "SEC_E_KDC_UNKNOWN_ETYPE"; + break; + case SEC_E_LOGON_DENIED: + txt = "SEC_E_LOGON_DENIED"; + break; + case SEC_E_MAX_REFERRALS_EXCEEDED: + txt = "SEC_E_MAX_REFERRALS_EXCEEDED"; + break; + case SEC_E_MESSAGE_ALTERED: + txt = "SEC_E_MESSAGE_ALTERED"; + break; + case SEC_E_MULTIPLE_ACCOUNTS: + txt = "SEC_E_MULTIPLE_ACCOUNTS"; + break; + case SEC_E_MUST_BE_KDC: + txt = "SEC_E_MUST_BE_KDC"; + break; + case SEC_E_NOT_OWNER: + txt = "SEC_E_NOT_OWNER"; + break; + case SEC_E_NO_AUTHENTICATING_AUTHORITY: + txt = "SEC_E_NO_AUTHENTICATING_AUTHORITY"; + break; + case SEC_E_NO_CREDENTIALS: + txt = "SEC_E_NO_CREDENTIALS"; + break; + case SEC_E_NO_IMPERSONATION: + txt = "SEC_E_NO_IMPERSONATION"; + break; + case SEC_E_NO_IP_ADDRESSES: + txt = "SEC_E_NO_IP_ADDRESSES"; + break; + case SEC_E_NO_KERB_KEY: + txt = "SEC_E_NO_KERB_KEY"; + break; + case SEC_E_NO_PA_DATA: + txt = "SEC_E_NO_PA_DATA"; + break; + case SEC_E_NO_S4U_PROT_SUPPORT: + txt = "SEC_E_NO_S4U_PROT_SUPPORT"; + break; + case SEC_E_NO_TGT_REPLY: + txt = "SEC_E_NO_TGT_REPLY"; + break; + case SEC_E_OUT_OF_SEQUENCE: + txt = "SEC_E_OUT_OF_SEQUENCE"; + break; + case SEC_E_PKINIT_CLIENT_FAILURE: + txt = "SEC_E_PKINIT_CLIENT_FAILURE"; + break; + case SEC_E_PKINIT_NAME_MISMATCH: + txt = "SEC_E_PKINIT_NAME_MISMATCH"; + break; + case SEC_E_POLICY_NLTM_ONLY: + txt = "SEC_E_POLICY_NLTM_ONLY"; + break; + case SEC_E_QOP_NOT_SUPPORTED: + txt = "SEC_E_QOP_NOT_SUPPORTED"; + break; + case SEC_E_REVOCATION_OFFLINE_C: + txt = "SEC_E_REVOCATION_OFFLINE_C"; + break; + case SEC_E_REVOCATION_OFFLINE_KDC: + txt = "SEC_E_REVOCATION_OFFLINE_KDC"; + break; + case SEC_E_SECPKG_NOT_FOUND: + txt = "SEC_E_SECPKG_NOT_FOUND"; + break; + case SEC_E_SECURITY_QOS_FAILED: + txt = "SEC_E_SECURITY_QOS_FAILED"; + break; + case SEC_E_SHUTDOWN_IN_PROGRESS: + txt = "SEC_E_SHUTDOWN_IN_PROGRESS"; + break; + case SEC_E_SMARTCARD_CERT_EXPIRED: + txt = "SEC_E_SMARTCARD_CERT_EXPIRED"; + break; + case SEC_E_SMARTCARD_CERT_REVOKED: + txt = "SEC_E_SMARTCARD_CERT_REVOKED"; + break; + case SEC_E_SMARTCARD_LOGON_REQUIRED: + txt = "SEC_E_SMARTCARD_LOGON_REQUIRED"; + break; + case SEC_E_STRONG_CRYPTO_NOT_SUPPORTED: + txt = "SEC_E_STRONG_CRYPTO_NOT_SUPPORTED"; + break; + case SEC_E_TARGET_UNKNOWN: + txt = "SEC_E_TARGET_UNKNOWN"; + break; + case SEC_E_TIME_SKEW: + txt = "SEC_E_TIME_SKEW"; + break; + case SEC_E_TOO_MANY_PRINCIPALS: + txt = "SEC_E_TOO_MANY_PRINCIPALS"; + break; + case SEC_E_UNFINISHED_CONTEXT_DELETED: + txt = "SEC_E_UNFINISHED_CONTEXT_DELETED"; + break; + case SEC_E_UNKNOWN_CREDENTIALS: + txt = "SEC_E_UNKNOWN_CREDENTIALS"; + break; + case SEC_E_UNSUPPORTED_FUNCTION: + txt = "SEC_E_UNSUPPORTED_FUNCTION"; + break; + case SEC_E_UNSUPPORTED_PREAUTH: + txt = "SEC_E_UNSUPPORTED_PREAUTH"; + break; + case SEC_E_UNTRUSTED_ROOT: + txt = "SEC_E_UNTRUSTED_ROOT"; + break; + case SEC_E_WRONG_CREDENTIAL_HANDLE: + txt = "SEC_E_WRONG_CREDENTIAL_HANDLE"; + break; + case SEC_E_WRONG_PRINCIPAL: + txt = "SEC_E_WRONG_PRINCIPAL"; + break; + case SEC_I_COMPLETE_AND_CONTINUE: + txt = "SEC_I_COMPLETE_AND_CONTINUE"; + break; + case SEC_I_COMPLETE_NEEDED: + txt = "SEC_I_COMPLETE_NEEDED"; + break; + case SEC_I_CONTEXT_EXPIRED: + txt = "SEC_I_CONTEXT_EXPIRED"; + break; + case SEC_I_CONTINUE_NEEDED: + txt = "SEC_I_CONTINUE_NEEDED"; + break; + case SEC_I_INCOMPLETE_CREDENTIALS: + txt = "SEC_I_INCOMPLETE_CREDENTIALS"; + break; + case SEC_I_LOCAL_LOGON: + txt = "SEC_I_LOCAL_LOGON"; + break; + case SEC_I_NO_LSA_CONTEXT: + txt = "SEC_I_NO_LSA_CONTEXT"; + break; + case SEC_I_RENEGOTIATE: + txt = "SEC_I_RENEGOTIATE"; + break; + case SEC_I_SIGNATURE_NEEDED: + txt = "SEC_I_SIGNATURE_NEEDED"; + break; + default: + txt = "Unknown error"; + } + + if(err == SEC_E_OK) + strncpy(outbuf, txt, outmax); + else if(err == SEC_E_ILLEGAL_MESSAGE) + msnprintf(outbuf, outmax, + "SEC_E_ILLEGAL_MESSAGE (0x%08X) - This error usually occurs " + "when a fatal SSL/TLS alert is received (e.g. handshake failed)." + " More detail may be available in the Windows System event log.", + err); + else { + str = txtbuf; + msnprintf(txtbuf, sizeof(txtbuf), "%s (0x%08X)", txt, err); + txtbuf[sizeof(txtbuf)-1] = '\0'; + +#ifdef _WIN32_WCE + { + wchar_t wbuf[256]; + wbuf[0] = L'\0'; + + if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, err, LANG_NEUTRAL, + wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL)) { + wcstombs(msgbuf, wbuf, sizeof(msgbuf)-1); + msg_formatted = TRUE; + } + } +#else + if(FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, err, LANG_NEUTRAL, + msgbuf, sizeof(msgbuf)-1, NULL)) { + msg_formatted = TRUE; + } +#endif + if(msg_formatted) { + msgbuf[sizeof(msgbuf)-1] = '\0'; + /* strip trailing '\r\n' or '\n' */ + p = strrchr(msgbuf, '\n'); + if(p && (p - msgbuf) >= 2) + *p = '\0'; + p = strrchr(msgbuf, '\r'); + if(p && (p - msgbuf) >= 1) + *p = '\0'; + msg = msgbuf; + } + if(msg) + msnprintf(outbuf, outmax, "%s - %s", str, msg); + else + strncpy(outbuf, str, outmax); + } + +#else + + if(err == SEC_E_OK) + txt = "No error"; + else + txt = "Error"; + + strncpy(outbuf, txt, outmax); + +#endif + + outbuf[outmax] = '\0'; + + if(errno != old_errno) + errno = old_errno; + +#ifdef PRESERVE_WINDOWS_ERROR_CODE + if(old_win_err != GetLastError()) + SetLastError(old_win_err); +#endif + + return outbuf; +} +#endif /* USE_WINDOWS_SSPI */ diff --git a/dependencies/cmcurl/lib/strerror.h b/dependencies/cmcurl/lib/strerror.h new file mode 100644 index 0000000..683b5b4 --- /dev/null +++ b/dependencies/cmcurl/lib/strerror.h @@ -0,0 +1,34 @@ +#ifndef HEADER_CURL_STRERROR_H +#define HEADER_CURL_STRERROR_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "urldata.h" + +#define STRERROR_LEN 128 /* a suitable length */ + +const char *Curl_strerror(int err, char *buf, size_t buflen); +#ifdef USE_WINDOWS_SSPI +const char *Curl_sspi_strerror(int err, char *buf, size_t buflen); +#endif + +#endif /* HEADER_CURL_STRERROR_H */ diff --git a/dependencies/cmcurl/lib/strtok.c b/dependencies/cmcurl/lib/strtok.c new file mode 100644 index 0000000..460eb87 --- /dev/null +++ b/dependencies/cmcurl/lib/strtok.c @@ -0,0 +1,66 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef HAVE_STRTOK_R +#include + +#include "strtok.h" + +char * +Curl_strtok_r(char *ptr, const char *sep, char **end) +{ + if(!ptr) + /* we got NULL input so then we get our last position instead */ + ptr = *end; + + /* pass all letters that are including in the separator string */ + while(*ptr && strchr(sep, *ptr)) + ++ptr; + + if(*ptr) { + /* so this is where the next piece of string starts */ + char *start = ptr; + + /* set the end pointer to the first byte after the start */ + *end = start + 1; + + /* scan through the string to find where it ends, it ends on a + null byte or a character that exists in the separator string */ + while(**end && !strchr(sep, **end)) + ++*end; + + if(**end) { + /* the end is not a null byte */ + **end = '\0'; /* zero terminate it! */ + ++*end; /* advance the last pointer to beyond the null byte */ + } + + return start; /* return the position where the string starts */ + } + + /* we ended up on a null byte, there are no more strings to find! */ + return NULL; +} + +#endif /* this was only compiled if strtok_r wasn't present */ diff --git a/dependencies/cmcurl/lib/strtok.h b/dependencies/cmcurl/lib/strtok.h new file mode 100644 index 0000000..90b831e --- /dev/null +++ b/dependencies/cmcurl/lib/strtok.h @@ -0,0 +1,34 @@ +#ifndef HEADER_CURL_STRTOK_H +#define HEADER_CURL_STRTOK_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" +#include + +#ifndef HAVE_STRTOK_R +char *Curl_strtok_r(char *s, const char *delim, char **last); +#define strtok_r Curl_strtok_r +#else +#include +#endif + +#endif /* HEADER_CURL_STRTOK_H */ diff --git a/dependencies/cmcurl/lib/strtoofft.c b/dependencies/cmcurl/lib/strtoofft.c new file mode 100644 index 0000000..546a3ff --- /dev/null +++ b/dependencies/cmcurl/lib/strtoofft.c @@ -0,0 +1,242 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include +#include "curl_setup.h" + +#include "strtoofft.h" + +/* + * NOTE: + * + * In the ISO C standard (IEEE Std 1003.1), there is a strtoimax() function we + * could use in case strtoll() doesn't exist... See + * https://www.opengroup.org/onlinepubs/009695399/functions/strtoimax.html + */ + +#if (SIZEOF_CURL_OFF_T > SIZEOF_LONG) +# ifdef HAVE_STRTOLL +# define strtooff strtoll +# else +# if defined(_MSC_VER) && (_MSC_VER >= 1300) && (_INTEGRAL_MAX_BITS >= 64) +# if defined(_SAL_VERSION) + _Check_return_ _CRTIMP __int64 __cdecl _strtoi64( + _In_z_ const char *_String, + _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix); +# else + _CRTIMP __int64 __cdecl _strtoi64(const char *_String, + char **_EndPtr, int _Radix); +# endif +# define strtooff _strtoi64 +# else +# define PRIVATE_STRTOOFF 1 +# endif +# endif +#else +# define strtooff strtol +#endif + +#ifdef PRIVATE_STRTOOFF + +/* Range tests can be used for alphanum decoding if characters are consecutive, + like in ASCII. Else an array is scanned. Determine this condition now. */ + +#if('9' - '0') != 9 || ('Z' - 'A') != 25 || ('z' - 'a') != 25 + +#define NO_RANGE_TEST + +static const char valchars[] = + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; +#endif + +static int get_char(char c, int base); + +/** + * Custom version of the strtooff function. This extracts a curl_off_t + * value from the given input string and returns it. + */ +static curl_off_t strtooff(const char *nptr, char **endptr, int base) +{ + char *end; + int is_negative = 0; + int overflow; + int i; + curl_off_t value = 0; + curl_off_t newval; + + /* Skip leading whitespace. */ + end = (char *)nptr; + while(ISSPACE(end[0])) { + end++; + } + + /* Handle the sign, if any. */ + if(end[0] == '-') { + is_negative = 1; + end++; + } + else if(end[0] == '+') { + end++; + } + else if(end[0] == '\0') { + /* We had nothing but perhaps some whitespace -- there was no number. */ + if(endptr) { + *endptr = end; + } + return 0; + } + + /* Handle special beginnings, if present and allowed. */ + if(end[0] == '0' && end[1] == 'x') { + if(base == 16 || base == 0) { + end += 2; + base = 16; + } + } + else if(end[0] == '0') { + if(base == 8 || base == 0) { + end++; + base = 8; + } + } + + /* Matching strtol, if the base is 0 and it doesn't look like + * the number is octal or hex, we assume it's base 10. + */ + if(base == 0) { + base = 10; + } + + /* Loop handling digits. */ + value = 0; + overflow = 0; + for(i = get_char(end[0], base); + i != -1; + end++, i = get_char(end[0], base)) { + newval = base * value + i; + if(newval < value) { + /* We've overflowed. */ + overflow = 1; + break; + } + else + value = newval; + } + + if(!overflow) { + if(is_negative) { + /* Fix the sign. */ + value *= -1; + } + } + else { + if(is_negative) + value = CURL_OFF_T_MIN; + else + value = CURL_OFF_T_MAX; + + errno = ERANGE; + } + + if(endptr) + *endptr = end; + + return value; +} + +/** + * Returns the value of c in the given base, or -1 if c cannot + * be interpreted properly in that base (i.e., is out of range, + * is a null, etc.). + * + * @param c the character to interpret according to base + * @param base the base in which to interpret c + * + * @return the value of c in base, or -1 if c isn't in range + */ +static int get_char(char c, int base) +{ +#ifndef NO_RANGE_TEST + int value = -1; + if(c <= '9' && c >= '0') { + value = c - '0'; + } + else if(c <= 'Z' && c >= 'A') { + value = c - 'A' + 10; + } + else if(c <= 'z' && c >= 'a') { + value = c - 'a' + 10; + } +#else + const char *cp; + int value; + + cp = memchr(valchars, c, 10 + 26 + 26); + + if(!cp) + return -1; + + value = cp - valchars; + + if(value >= 10 + 26) + value -= 26; /* Lowercase. */ +#endif + + if(value >= base) { + value = -1; + } + + return value; +} +#endif /* Only present if we need strtoll, but don't have it. */ + +/* + * Parse a *positive* up to 64 bit number written in ascii. + */ +CURLofft curlx_strtoofft(const char *str, char **endp, int base, + curl_off_t *num) +{ + char *end; + curl_off_t number; + errno = 0; + *num = 0; /* clear by default */ + + while(*str && ISSPACE(*str)) + str++; + if('-' == *str) { + if(endp) + *endp = (char *)str; /* didn't actually move */ + return CURL_OFFT_INVAL; /* nothing parsed */ + } + number = strtooff(str, &end, base); + if(endp) + *endp = end; + if(errno == ERANGE) + /* overflow/underflow */ + return CURL_OFFT_FLOW; + else if(str == end) + /* nothing parsed */ + return CURL_OFFT_INVAL; + + *num = number; + return CURL_OFFT_OK; +} diff --git a/dependencies/cmcurl/lib/strtoofft.h b/dependencies/cmcurl/lib/strtoofft.h new file mode 100644 index 0000000..be19cd7 --- /dev/null +++ b/dependencies/cmcurl/lib/strtoofft.h @@ -0,0 +1,52 @@ +#ifndef HEADER_CURL_STRTOOFFT_H +#define HEADER_CURL_STRTOOFFT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +/* + * Determine which string to integral data type conversion function we use + * to implement string conversion to our curl_off_t integral data type. + * + * Notice that curl_off_t might be 64 or 32 bit wide, and that it might use + * an underlying data type which might be 'long', 'int64_t', 'long long' or + * '__int64' and more remotely other data types. + * + * On systems where the size of curl_off_t is greater than the size of 'long' + * the conversion function to use is strtoll() if it is available, otherwise, + * we emulate its functionality with our own clone. + * + * On systems where the size of curl_off_t is smaller or equal than the size + * of 'long' the conversion function to use is strtol(). + */ + +typedef enum { + CURL_OFFT_OK, /* parsed fine */ + CURL_OFFT_FLOW, /* over or underflow */ + CURL_OFFT_INVAL /* nothing was parsed */ +} CURLofft; + +CURLofft curlx_strtoofft(const char *str, char **endp, int base, + curl_off_t *num); + +#endif /* HEADER_CURL_STRTOOFFT_H */ diff --git a/dependencies/cmcurl/lib/system_win32.c b/dependencies/cmcurl/lib/system_win32.c new file mode 100644 index 0000000..f7f817d --- /dev/null +++ b/dependencies/cmcurl/lib/system_win32.c @@ -0,0 +1,416 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2016 - 2017, Steve Holme, . + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(WIN32) + +#include +#include "system_win32.h" +#include "curl_sspi.h" +#include "warnless.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +LARGE_INTEGER Curl_freq; +bool Curl_isVistaOrGreater; + +/* Curl_win32_init() performs win32 global initialization */ +CURLcode Curl_win32_init(long flags) +{ + /* CURL_GLOBAL_WIN32 controls the *optional* part of the initialization which + is just for Winsock at the moment. Any required win32 initialization + should take place after this block. */ + if(flags & CURL_GLOBAL_WIN32) { +#ifdef USE_WINSOCK + WORD wVersionRequested; + WSADATA wsaData; + int res; + +#if defined(ENABLE_IPV6) && (USE_WINSOCK < 2) +#error IPV6_requires_winsock2 +#endif + + wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK); + + res = WSAStartup(wVersionRequested, &wsaData); + + if(res != 0) + /* Tell the user that we couldn't find a usable */ + /* winsock.dll. */ + return CURLE_FAILED_INIT; + + /* Confirm that the Windows Sockets DLL supports what we need.*/ + /* Note that if the DLL supports versions greater */ + /* than wVersionRequested, it will still return */ + /* wVersionRequested in wVersion. wHighVersion contains the */ + /* highest supported version. */ + + if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) || + HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested) ) { + /* Tell the user that we couldn't find a usable */ + + /* winsock.dll. */ + WSACleanup(); + return CURLE_FAILED_INIT; + } + /* The Windows Sockets DLL is acceptable. Proceed. */ + #elif defined(USE_LWIPSOCK) + lwip_init(); + #endif + } /* CURL_GLOBAL_WIN32 */ + +#ifdef USE_WINDOWS_SSPI + { + CURLcode result = Curl_sspi_global_init(); + if(result) + return result; + } +#endif + + if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT, + VERSION_GREATER_THAN_EQUAL)) { + Curl_isVistaOrGreater = TRUE; + QueryPerformanceFrequency(&Curl_freq); + } + else + Curl_isVistaOrGreater = FALSE; + + return CURLE_OK; +} + +/* Curl_win32_cleanup() is the opposite of Curl_win32_init() */ +void Curl_win32_cleanup(long init_flags) +{ +#ifdef USE_WINDOWS_SSPI + Curl_sspi_global_cleanup(); +#endif + + if(init_flags & CURL_GLOBAL_WIN32) { +#ifdef USE_WINSOCK + WSACleanup(); +#endif + } +} + +#if defined(USE_WINDOWS_SSPI) || (!defined(CURL_DISABLE_TELNET) && \ + defined(USE_WINSOCK)) + + +#if !defined(LOAD_WITH_ALTERED_SEARCH_PATH) +#define LOAD_WITH_ALTERED_SEARCH_PATH 0x00000008 +#endif + +#if !defined(LOAD_LIBRARY_SEARCH_SYSTEM32) +#define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800 +#endif + +/* We use our own typedef here since some headers might lack these */ +typedef HMODULE (APIENTRY *LOADLIBRARYEX_FN)(LPCTSTR, HANDLE, DWORD); + +/* See function definitions in winbase.h */ +#ifdef UNICODE +# ifdef _WIN32_WCE +# define LOADLIBARYEX L"LoadLibraryExW" +# else +# define LOADLIBARYEX "LoadLibraryExW" +# endif +#else +# define LOADLIBARYEX "LoadLibraryExA" +#endif + +#endif /* USE_WINDOWS_SSPI || (!CURL_DISABLE_TELNET && USE_WINSOCK) */ + +/* + * Curl_verify_windows_version() + * + * This is used to verify if we are running on a specific windows version. + * + * Parameters: + * + * majorVersion [in] - The major version number. + * minorVersion [in] - The minor version number. + * platform [in] - The optional platform identifier. + * condition [in] - The test condition used to specifier whether we are + * checking a version less then, equal to or greater than + * what is specified in the major and minor version + * numbers. + * + * Returns TRUE if matched; otherwise FALSE. + */ +bool Curl_verify_windows_version(const unsigned int majorVersion, + const unsigned int minorVersion, + const PlatformIdentifier platform, + const VersionCondition condition) +{ + bool matched = FALSE; + +#if defined(CURL_WINDOWS_APP) + /* We have no way to determine the Windows version from Windows apps, + so let's assume we're running on the target Windows version. */ + const WORD fullVersion = MAKEWORD(minorVersion, majorVersion); + const WORD targetVersion = (WORD)_WIN32_WINNT; + + switch(condition) { + case VERSION_LESS_THAN: + matched = targetVersion < fullVersion; + break; + + case VERSION_LESS_THAN_EQUAL: + matched = targetVersion <= fullVersion; + break; + + case VERSION_EQUAL: + matched = targetVersion == fullVersion; + break; + + case VERSION_GREATER_THAN_EQUAL: + matched = targetVersion >= fullVersion; + break; + + case VERSION_GREATER_THAN: + matched = targetVersion > fullVersion; + break; + } + + if(matched && (platform == PLATFORM_WINDOWS)) { + /* we're always running on PLATFORM_WINNT */ + matched = FALSE; + } +#elif !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \ + (_WIN32_WINNT < _WIN32_WINNT_WIN2K) + OSVERSIONINFO osver; + + memset(&osver, 0, sizeof(osver)); + osver.dwOSVersionInfoSize = sizeof(osver); + + /* Find out Windows version */ + if(GetVersionEx(&osver)) { + /* Verify the Operating System version number */ + switch(condition) { + case VERSION_LESS_THAN: + if(osver.dwMajorVersion < majorVersion || + (osver.dwMajorVersion == majorVersion && + osver.dwMinorVersion < minorVersion)) + matched = TRUE; + break; + + case VERSION_LESS_THAN_EQUAL: + if(osver.dwMajorVersion < majorVersion || + (osver.dwMajorVersion == majorVersion && + osver.dwMinorVersion <= minorVersion)) + matched = TRUE; + break; + + case VERSION_EQUAL: + if(osver.dwMajorVersion == majorVersion && + osver.dwMinorVersion == minorVersion) + matched = TRUE; + break; + + case VERSION_GREATER_THAN_EQUAL: + if(osver.dwMajorVersion > majorVersion || + (osver.dwMajorVersion == majorVersion && + osver.dwMinorVersion >= minorVersion)) + matched = TRUE; + break; + + case VERSION_GREATER_THAN: + if(osver.dwMajorVersion > majorVersion || + (osver.dwMajorVersion == majorVersion && + osver.dwMinorVersion > minorVersion)) + matched = TRUE; + break; + } + + /* Verify the platform identifier (if necessary) */ + if(matched) { + switch(platform) { + case PLATFORM_WINDOWS: + if(osver.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) + matched = FALSE; + break; + + case PLATFORM_WINNT: + if(osver.dwPlatformId != VER_PLATFORM_WIN32_NT) + matched = FALSE; + + default: /* like platform == PLATFORM_DONT_CARE */ + break; + } + } + } +#else + ULONGLONG cm = 0; + OSVERSIONINFOEX osver; + BYTE majorCondition; + BYTE minorCondition; + BYTE spMajorCondition; + BYTE spMinorCondition; + + switch(condition) { + case VERSION_LESS_THAN: + majorCondition = VER_LESS; + minorCondition = VER_LESS; + spMajorCondition = VER_LESS_EQUAL; + spMinorCondition = VER_LESS_EQUAL; + break; + + case VERSION_LESS_THAN_EQUAL: + majorCondition = VER_LESS_EQUAL; + minorCondition = VER_LESS_EQUAL; + spMajorCondition = VER_LESS_EQUAL; + spMinorCondition = VER_LESS_EQUAL; + break; + + case VERSION_EQUAL: + majorCondition = VER_EQUAL; + minorCondition = VER_EQUAL; + spMajorCondition = VER_GREATER_EQUAL; + spMinorCondition = VER_GREATER_EQUAL; + break; + + case VERSION_GREATER_THAN_EQUAL: + majorCondition = VER_GREATER_EQUAL; + minorCondition = VER_GREATER_EQUAL; + spMajorCondition = VER_GREATER_EQUAL; + spMinorCondition = VER_GREATER_EQUAL; + break; + + case VERSION_GREATER_THAN: + majorCondition = VER_GREATER; + minorCondition = VER_GREATER; + spMajorCondition = VER_GREATER_EQUAL; + spMinorCondition = VER_GREATER_EQUAL; + break; + + default: + return FALSE; + } + + memset(&osver, 0, sizeof(osver)); + osver.dwOSVersionInfoSize = sizeof(osver); + osver.dwMajorVersion = majorVersion; + osver.dwMinorVersion = minorVersion; + if(platform == PLATFORM_WINDOWS) + osver.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS; + else if(platform == PLATFORM_WINNT) + osver.dwPlatformId = VER_PLATFORM_WIN32_NT; + + cm = VerSetConditionMask(cm, VER_MAJORVERSION, majorCondition); + cm = VerSetConditionMask(cm, VER_MINORVERSION, minorCondition); + cm = VerSetConditionMask(cm, VER_SERVICEPACKMAJOR, spMajorCondition); + cm = VerSetConditionMask(cm, VER_SERVICEPACKMINOR, spMinorCondition); + if(platform != PLATFORM_DONT_CARE) + cm = VerSetConditionMask(cm, VER_PLATFORMID, VER_EQUAL); + + if(VerifyVersionInfo(&osver, (VER_MAJORVERSION | VER_MINORVERSION | + VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR), + cm)) + matched = TRUE; +#endif + + return matched; +} + +#if defined(USE_WINDOWS_SSPI) || (!defined(CURL_DISABLE_TELNET) && \ + defined(USE_WINSOCK)) + +/* + * Curl_load_library() + * + * This is used to dynamically load DLLs using the most secure method available + * for the version of Windows that we are running on. + * + * Parameters: + * + * filename [in] - The filename or full path of the DLL to load. If only the + * filename is passed then the DLL will be loaded from the + * Windows system directory. + * + * Returns the handle of the module on success; otherwise NULL. + */ +HMODULE Curl_load_library(LPCTSTR filename) +{ + HMODULE hModule = NULL; + LOADLIBRARYEX_FN pLoadLibraryEx = NULL; + + /* Get a handle to kernel32 so we can access it's functions at runtime */ + HMODULE hKernel32 = GetModuleHandle(TEXT("kernel32")); + if(!hKernel32) + return NULL; + + /* Attempt to find LoadLibraryEx() which is only available on Windows 2000 + and above */ + pLoadLibraryEx = + CURLX_FUNCTION_CAST(LOADLIBRARYEX_FN, + (GetProcAddress(hKernel32, LOADLIBARYEX))); + + /* Detect if there's already a path in the filename and load the library if + there is. Note: Both back slashes and forward slashes have been supported + since the earlier days of DOS at an API level although they are not + supported by command prompt */ + if(_tcspbrk(filename, TEXT("\\/"))) { + /** !checksrc! disable BANNEDFUNC 1 **/ + hModule = pLoadLibraryEx ? + pLoadLibraryEx(filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) : + LoadLibrary(filename); + } + /* Detect if KB2533623 is installed, as LOAD_LIBARY_SEARCH_SYSTEM32 is only + supported on Windows Vista, Windows Server 2008, Windows 7 and Windows + Server 2008 R2 with this patch or natively on Windows 8 and above */ + else if(pLoadLibraryEx && GetProcAddress(hKernel32, "AddDllDirectory")) { + /* Load the DLL from the Windows system directory */ + hModule = pLoadLibraryEx(filename, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); + } + else { + /* Attempt to get the Windows system path */ + UINT systemdirlen = GetSystemDirectory(NULL, 0); + if(systemdirlen) { + /* Allocate space for the full DLL path (Room for the null terminator + is included in systemdirlen) */ + size_t filenamelen = _tcslen(filename); + TCHAR *path = malloc(sizeof(TCHAR) * (systemdirlen + 1 + filenamelen)); + if(path && GetSystemDirectory(path, systemdirlen)) { + /* Calculate the full DLL path */ + _tcscpy(path + _tcslen(path), TEXT("\\")); + _tcscpy(path + _tcslen(path), filename); + + /* Load the DLL from the Windows system directory */ + /** !checksrc! disable BANNEDFUNC 1 **/ + hModule = pLoadLibraryEx ? + pLoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) : + LoadLibrary(path); + + } + free(path); + } + } + + return hModule; +} + +#endif /* USE_WINDOWS_SSPI || (!CURL_DISABLE_TELNET && USE_WINSOCK) */ + +#endif /* WIN32 */ diff --git a/dependencies/cmcurl/lib/system_win32.h b/dependencies/cmcurl/lib/system_win32.h new file mode 100644 index 0000000..926328a --- /dev/null +++ b/dependencies/cmcurl/lib/system_win32.h @@ -0,0 +1,67 @@ +#ifndef HEADER_CURL_SYSTEM_WIN32_H +#define HEADER_CURL_SYSTEM_WIN32_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2016, Steve Holme, . + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(WIN32) + +extern LARGE_INTEGER Curl_freq; +extern bool Curl_isVistaOrGreater; + +CURLcode Curl_win32_init(long flags); +void Curl_win32_cleanup(long init_flags); + +/* Version condition */ +typedef enum { + VERSION_LESS_THAN, + VERSION_LESS_THAN_EQUAL, + VERSION_EQUAL, + VERSION_GREATER_THAN_EQUAL, + VERSION_GREATER_THAN +} VersionCondition; + +/* Platform identifier */ +typedef enum { + PLATFORM_DONT_CARE, + PLATFORM_WINDOWS, + PLATFORM_WINNT +} PlatformIdentifier; + +/* This is used to verify if we are running on a specific windows version */ +bool Curl_verify_windows_version(const unsigned int majorVersion, + const unsigned int minorVersion, + const PlatformIdentifier platform, + const VersionCondition condition); + +#if defined(USE_WINDOWS_SSPI) || (!defined(CURL_DISABLE_TELNET) && \ + defined(USE_WINSOCK)) + +/* This is used to dynamically load DLLs */ +HMODULE Curl_load_library(LPCTSTR filename); + +#endif /* USE_WINDOWS_SSPI || (!CURL_DISABLE_TELNET && USE_WINSOCK) */ + +#endif /* WIN32 */ + +#endif /* HEADER_CURL_SYSTEM_WIN32_H */ diff --git a/dependencies/cmcurl/lib/telnet.c b/dependencies/cmcurl/lib/telnet.c new file mode 100644 index 0000000..955255c --- /dev/null +++ b/dependencies/cmcurl/lib/telnet.c @@ -0,0 +1,1699 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_TELNET + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#include "urldata.h" +#include +#include "transfer.h" +#include "sendf.h" +#include "telnet.h" +#include "connect.h" +#include "progress.h" +#include "system_win32.h" +#include "arpa_telnet.h" +#include "select.h" +#include "strcase.h" +#include "warnless.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#define SUBBUFSIZE 512 + +#define CURL_SB_CLEAR(x) x->subpointer = x->subbuffer +#define CURL_SB_TERM(x) \ + do { \ + x->subend = x->subpointer; \ + CURL_SB_CLEAR(x); \ + } WHILE_FALSE +#define CURL_SB_ACCUM(x,c) \ + do { \ + if(x->subpointer < (x->subbuffer + sizeof(x->subbuffer))) \ + *x->subpointer++ = (c); \ + } WHILE_FALSE + +#define CURL_SB_GET(x) ((*x->subpointer++)&0xff) +#define CURL_SB_LEN(x) (x->subend - x->subpointer) + +/* For posterity: +#define CURL_SB_PEEK(x) ((*x->subpointer)&0xff) +#define CURL_SB_EOF(x) (x->subpointer >= x->subend) */ + +#ifdef CURL_DISABLE_VERBOSE_STRINGS +#define printoption(a,b,c,d) Curl_nop_stmt +#endif + +#ifdef USE_WINSOCK +typedef WSAEVENT (WINAPI *WSOCK2_EVENT)(void); +typedef FARPROC WSOCK2_FUNC; +static CURLcode check_wsock2(struct Curl_easy *data); +#endif + +static +CURLcode telrcv(struct connectdata *, + const unsigned char *inbuf, /* Data received from socket */ + ssize_t count); /* Number of bytes received */ + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static void printoption(struct Curl_easy *data, + const char *direction, + int cmd, int option); +#endif + +static void negotiate(struct connectdata *); +static void send_negotiation(struct connectdata *, int cmd, int option); +static void set_local_option(struct connectdata *conn, + int option, int newstate); +static void set_remote_option(struct connectdata *conn, + int option, int newstate); + +static void printsub(struct Curl_easy *data, + int direction, unsigned char *pointer, + size_t length); +static void suboption(struct connectdata *); +static void sendsuboption(struct connectdata *conn, int option); + +static CURLcode telnet_do(struct connectdata *conn, bool *done); +static CURLcode telnet_done(struct connectdata *conn, + CURLcode, bool premature); +static CURLcode send_telnet_data(struct connectdata *conn, + char *buffer, ssize_t nread); + +/* For negotiation compliant to RFC 1143 */ +#define CURL_NO 0 +#define CURL_YES 1 +#define CURL_WANTYES 2 +#define CURL_WANTNO 3 + +#define CURL_EMPTY 0 +#define CURL_OPPOSITE 1 + +/* + * Telnet receiver states for fsm + */ +typedef enum +{ + CURL_TS_DATA = 0, + CURL_TS_IAC, + CURL_TS_WILL, + CURL_TS_WONT, + CURL_TS_DO, + CURL_TS_DONT, + CURL_TS_CR, + CURL_TS_SB, /* sub-option collection */ + CURL_TS_SE /* looking for sub-option end */ +} TelnetReceive; + +struct TELNET { + int please_negotiate; + int already_negotiated; + int us[256]; + int usq[256]; + int us_preferred[256]; + int him[256]; + int himq[256]; + int him_preferred[256]; + int subnegotiation[256]; + char subopt_ttype[32]; /* Set with suboption TTYPE */ + char subopt_xdisploc[128]; /* Set with suboption XDISPLOC */ + unsigned short subopt_wsx; /* Set with suboption NAWS */ + unsigned short subopt_wsy; /* Set with suboption NAWS */ + struct curl_slist *telnet_vars; /* Environment variables */ + + /* suboptions */ + unsigned char subbuffer[SUBBUFSIZE]; + unsigned char *subpointer, *subend; /* buffer for sub-options */ + + TelnetReceive telrcv_state; +}; + + +/* + * TELNET protocol handler. + */ + +const struct Curl_handler Curl_handler_telnet = { + "TELNET", /* scheme */ + ZERO_NULL, /* setup_connection */ + telnet_do, /* do_it */ + telnet_done, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_TELNET, /* defport */ + CURLPROTO_TELNET, /* protocol */ + PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */ +}; + + +#ifdef USE_WINSOCK +static CURLcode +check_wsock2(struct Curl_easy *data) +{ + int err; + WORD wVersionRequested; + WSADATA wsaData; + + DEBUGASSERT(data); + + /* telnet requires at least WinSock 2.0 so ask for it. */ + wVersionRequested = MAKEWORD(2, 0); + + err = WSAStartup(wVersionRequested, &wsaData); + + /* We must've called this once already, so this call */ + /* should always succeed. But, just in case... */ + if(err != 0) { + failf(data,"WSAStartup failed (%d)",err); + return CURLE_FAILED_INIT; + } + + /* We have to have a WSACleanup call for every successful */ + /* WSAStartup call. */ + WSACleanup(); + + /* Check that our version is supported */ + if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) || + HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested)) { + /* Our version isn't supported */ + failf(data, "insufficient winsock version to support " + "telnet"); + return CURLE_FAILED_INIT; + } + + /* Our version is supported */ + return CURLE_OK; +} +#endif + +static +CURLcode init_telnet(struct connectdata *conn) +{ + struct TELNET *tn; + + tn = calloc(1, sizeof(struct TELNET)); + if(!tn) + return CURLE_OUT_OF_MEMORY; + + conn->data->req.protop = tn; /* make us known */ + + tn->telrcv_state = CURL_TS_DATA; + + /* Init suboptions */ + CURL_SB_CLEAR(tn); + + /* Set the options we want by default */ + tn->us_preferred[CURL_TELOPT_SGA] = CURL_YES; + tn->him_preferred[CURL_TELOPT_SGA] = CURL_YES; + + /* To be compliant with previous releases of libcurl + we enable this option by default. This behaviour + can be changed thanks to the "BINARY" option in + CURLOPT_TELNETOPTIONS + */ + tn->us_preferred[CURL_TELOPT_BINARY] = CURL_YES; + tn->him_preferred[CURL_TELOPT_BINARY] = CURL_YES; + + /* We must allow the server to echo what we sent + but it is not necessary to request the server + to do so (it might forces the server to close + the connection). Hence, we ignore ECHO in the + negotiate function + */ + tn->him_preferred[CURL_TELOPT_ECHO] = CURL_YES; + + /* Set the subnegotiation fields to send information + just after negotiation passed (do/will) + + Default values are (0,0) initialized by calloc. + According to the RFC1013 it is valid: + A value equal to zero is acceptable for the width (or height), + and means that no character width (or height) is being sent. + In this case, the width (or height) that will be assumed by the + Telnet server is operating system specific (it will probably be + based upon the terminal type information that may have been sent + using the TERMINAL TYPE Telnet option). */ + tn->subnegotiation[CURL_TELOPT_NAWS] = CURL_YES; + return CURLE_OK; +} + +static void negotiate(struct connectdata *conn) +{ + int i; + struct TELNET *tn = (struct TELNET *) conn->data->req.protop; + + for(i = 0; i < CURL_NTELOPTS; i++) { + if(i == CURL_TELOPT_ECHO) + continue; + + if(tn->us_preferred[i] == CURL_YES) + set_local_option(conn, i, CURL_YES); + + if(tn->him_preferred[i] == CURL_YES) + set_remote_option(conn, i, CURL_YES); + } +} + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static void printoption(struct Curl_easy *data, + const char *direction, int cmd, int option) +{ + if(data->set.verbose) { + if(cmd == CURL_IAC) { + if(CURL_TELCMD_OK(option)) + infof(data, "%s IAC %s\n", direction, CURL_TELCMD(option)); + else + infof(data, "%s IAC %d\n", direction, option); + } + else { + const char *fmt = (cmd == CURL_WILL) ? "WILL" : + (cmd == CURL_WONT) ? "WONT" : + (cmd == CURL_DO) ? "DO" : + (cmd == CURL_DONT) ? "DONT" : 0; + if(fmt) { + const char *opt; + if(CURL_TELOPT_OK(option)) + opt = CURL_TELOPT(option); + else if(option == CURL_TELOPT_EXOPL) + opt = "EXOPL"; + else + opt = NULL; + + if(opt) + infof(data, "%s %s %s\n", direction, fmt, opt); + else + infof(data, "%s %s %d\n", direction, fmt, option); + } + else + infof(data, "%s %d %d\n", direction, cmd, option); + } + } +} +#endif + +static void send_negotiation(struct connectdata *conn, int cmd, int option) +{ + unsigned char buf[3]; + ssize_t bytes_written; + struct Curl_easy *data = conn->data; + + buf[0] = CURL_IAC; + buf[1] = (unsigned char)cmd; + buf[2] = (unsigned char)option; + + bytes_written = swrite(conn->sock[FIRSTSOCKET], buf, 3); + if(bytes_written < 0) { + int err = SOCKERRNO; + failf(data,"Sending data failed (%d)",err); + } + + printoption(conn->data, "SENT", cmd, option); +} + +static +void set_remote_option(struct connectdata *conn, int option, int newstate) +{ + struct TELNET *tn = (struct TELNET *)conn->data->req.protop; + if(newstate == CURL_YES) { + switch(tn->him[option]) { + case CURL_NO: + tn->him[option] = CURL_WANTYES; + send_negotiation(conn, CURL_DO, option); + break; + + case CURL_YES: + /* Already enabled */ + break; + + case CURL_WANTNO: + switch(tn->himq[option]) { + case CURL_EMPTY: + /* Already negotiating for CURL_YES, queue the request */ + tn->himq[option] = CURL_OPPOSITE; + break; + case CURL_OPPOSITE: + /* Error: already queued an enable request */ + break; + } + break; + + case CURL_WANTYES: + switch(tn->himq[option]) { + case CURL_EMPTY: + /* Error: already negotiating for enable */ + break; + case CURL_OPPOSITE: + tn->himq[option] = CURL_EMPTY; + break; + } + break; + } + } + else { /* NO */ + switch(tn->him[option]) { + case CURL_NO: + /* Already disabled */ + break; + + case CURL_YES: + tn->him[option] = CURL_WANTNO; + send_negotiation(conn, CURL_DONT, option); + break; + + case CURL_WANTNO: + switch(tn->himq[option]) { + case CURL_EMPTY: + /* Already negotiating for NO */ + break; + case CURL_OPPOSITE: + tn->himq[option] = CURL_EMPTY; + break; + } + break; + + case CURL_WANTYES: + switch(tn->himq[option]) { + case CURL_EMPTY: + tn->himq[option] = CURL_OPPOSITE; + break; + case CURL_OPPOSITE: + break; + } + break; + } + } +} + +static +void rec_will(struct connectdata *conn, int option) +{ + struct TELNET *tn = (struct TELNET *)conn->data->req.protop; + switch(tn->him[option]) { + case CURL_NO: + if(tn->him_preferred[option] == CURL_YES) { + tn->him[option] = CURL_YES; + send_negotiation(conn, CURL_DO, option); + } + else + send_negotiation(conn, CURL_DONT, option); + + break; + + case CURL_YES: + /* Already enabled */ + break; + + case CURL_WANTNO: + switch(tn->himq[option]) { + case CURL_EMPTY: + /* Error: DONT answered by WILL */ + tn->him[option] = CURL_NO; + break; + case CURL_OPPOSITE: + /* Error: DONT answered by WILL */ + tn->him[option] = CURL_YES; + tn->himq[option] = CURL_EMPTY; + break; + } + break; + + case CURL_WANTYES: + switch(tn->himq[option]) { + case CURL_EMPTY: + tn->him[option] = CURL_YES; + break; + case CURL_OPPOSITE: + tn->him[option] = CURL_WANTNO; + tn->himq[option] = CURL_EMPTY; + send_negotiation(conn, CURL_DONT, option); + break; + } + break; + } +} + +static +void rec_wont(struct connectdata *conn, int option) +{ + struct TELNET *tn = (struct TELNET *)conn->data->req.protop; + switch(tn->him[option]) { + case CURL_NO: + /* Already disabled */ + break; + + case CURL_YES: + tn->him[option] = CURL_NO; + send_negotiation(conn, CURL_DONT, option); + break; + + case CURL_WANTNO: + switch(tn->himq[option]) { + case CURL_EMPTY: + tn->him[option] = CURL_NO; + break; + + case CURL_OPPOSITE: + tn->him[option] = CURL_WANTYES; + tn->himq[option] = CURL_EMPTY; + send_negotiation(conn, CURL_DO, option); + break; + } + break; + + case CURL_WANTYES: + switch(tn->himq[option]) { + case CURL_EMPTY: + tn->him[option] = CURL_NO; + break; + case CURL_OPPOSITE: + tn->him[option] = CURL_NO; + tn->himq[option] = CURL_EMPTY; + break; + } + break; + } +} + +static void +set_local_option(struct connectdata *conn, int option, int newstate) +{ + struct TELNET *tn = (struct TELNET *)conn->data->req.protop; + if(newstate == CURL_YES) { + switch(tn->us[option]) { + case CURL_NO: + tn->us[option] = CURL_WANTYES; + send_negotiation(conn, CURL_WILL, option); + break; + + case CURL_YES: + /* Already enabled */ + break; + + case CURL_WANTNO: + switch(tn->usq[option]) { + case CURL_EMPTY: + /* Already negotiating for CURL_YES, queue the request */ + tn->usq[option] = CURL_OPPOSITE; + break; + case CURL_OPPOSITE: + /* Error: already queued an enable request */ + break; + } + break; + + case CURL_WANTYES: + switch(tn->usq[option]) { + case CURL_EMPTY: + /* Error: already negotiating for enable */ + break; + case CURL_OPPOSITE: + tn->usq[option] = CURL_EMPTY; + break; + } + break; + } + } + else { /* NO */ + switch(tn->us[option]) { + case CURL_NO: + /* Already disabled */ + break; + + case CURL_YES: + tn->us[option] = CURL_WANTNO; + send_negotiation(conn, CURL_WONT, option); + break; + + case CURL_WANTNO: + switch(tn->usq[option]) { + case CURL_EMPTY: + /* Already negotiating for NO */ + break; + case CURL_OPPOSITE: + tn->usq[option] = CURL_EMPTY; + break; + } + break; + + case CURL_WANTYES: + switch(tn->usq[option]) { + case CURL_EMPTY: + tn->usq[option] = CURL_OPPOSITE; + break; + case CURL_OPPOSITE: + break; + } + break; + } + } +} + +static +void rec_do(struct connectdata *conn, int option) +{ + struct TELNET *tn = (struct TELNET *)conn->data->req.protop; + switch(tn->us[option]) { + case CURL_NO: + if(tn->us_preferred[option] == CURL_YES) { + tn->us[option] = CURL_YES; + send_negotiation(conn, CURL_WILL, option); + if(tn->subnegotiation[option] == CURL_YES) + /* transmission of data option */ + sendsuboption(conn, option); + } + else if(tn->subnegotiation[option] == CURL_YES) { + /* send information to achieve this option*/ + tn->us[option] = CURL_YES; + send_negotiation(conn, CURL_WILL, option); + sendsuboption(conn, option); + } + else + send_negotiation(conn, CURL_WONT, option); + break; + + case CURL_YES: + /* Already enabled */ + break; + + case CURL_WANTNO: + switch(tn->usq[option]) { + case CURL_EMPTY: + /* Error: DONT answered by WILL */ + tn->us[option] = CURL_NO; + break; + case CURL_OPPOSITE: + /* Error: DONT answered by WILL */ + tn->us[option] = CURL_YES; + tn->usq[option] = CURL_EMPTY; + break; + } + break; + + case CURL_WANTYES: + switch(tn->usq[option]) { + case CURL_EMPTY: + tn->us[option] = CURL_YES; + if(tn->subnegotiation[option] == CURL_YES) { + /* transmission of data option */ + sendsuboption(conn, option); + } + break; + case CURL_OPPOSITE: + tn->us[option] = CURL_WANTNO; + tn->himq[option] = CURL_EMPTY; + send_negotiation(conn, CURL_WONT, option); + break; + } + break; + } +} + +static +void rec_dont(struct connectdata *conn, int option) +{ + struct TELNET *tn = (struct TELNET *)conn->data->req.protop; + switch(tn->us[option]) { + case CURL_NO: + /* Already disabled */ + break; + + case CURL_YES: + tn->us[option] = CURL_NO; + send_negotiation(conn, CURL_WONT, option); + break; + + case CURL_WANTNO: + switch(tn->usq[option]) { + case CURL_EMPTY: + tn->us[option] = CURL_NO; + break; + + case CURL_OPPOSITE: + tn->us[option] = CURL_WANTYES; + tn->usq[option] = CURL_EMPTY; + send_negotiation(conn, CURL_WILL, option); + break; + } + break; + + case CURL_WANTYES: + switch(tn->usq[option]) { + case CURL_EMPTY: + tn->us[option] = CURL_NO; + break; + case CURL_OPPOSITE: + tn->us[option] = CURL_NO; + tn->usq[option] = CURL_EMPTY; + break; + } + break; + } +} + + +static void printsub(struct Curl_easy *data, + int direction, /* '<' or '>' */ + unsigned char *pointer, /* where suboption data is */ + size_t length) /* length of suboption data */ +{ + if(data->set.verbose) { + unsigned int i = 0; + if(direction) { + infof(data, "%s IAC SB ", (direction == '<')? "RCVD":"SENT"); + if(length >= 3) { + int j; + + i = pointer[length-2]; + j = pointer[length-1]; + + if(i != CURL_IAC || j != CURL_SE) { + infof(data, "(terminated by "); + if(CURL_TELOPT_OK(i)) + infof(data, "%s ", CURL_TELOPT(i)); + else if(CURL_TELCMD_OK(i)) + infof(data, "%s ", CURL_TELCMD(i)); + else + infof(data, "%u ", i); + if(CURL_TELOPT_OK(j)) + infof(data, "%s", CURL_TELOPT(j)); + else if(CURL_TELCMD_OK(j)) + infof(data, "%s", CURL_TELCMD(j)); + else + infof(data, "%d", j); + infof(data, ", not IAC SE!) "); + } + } + length -= 2; + } + if(length < 1) { + infof(data, "(Empty suboption?)"); + return; + } + + if(CURL_TELOPT_OK(pointer[0])) { + switch(pointer[0]) { + case CURL_TELOPT_TTYPE: + case CURL_TELOPT_XDISPLOC: + case CURL_TELOPT_NEW_ENVIRON: + case CURL_TELOPT_NAWS: + infof(data, "%s", CURL_TELOPT(pointer[0])); + break; + default: + infof(data, "%s (unsupported)", CURL_TELOPT(pointer[0])); + break; + } + } + else + infof(data, "%d (unknown)", pointer[i]); + + switch(pointer[0]) { + case CURL_TELOPT_NAWS: + if(length > 4) + infof(data, "Width: %d ; Height: %d", (pointer[1]<<8) | pointer[2], + (pointer[3]<<8) | pointer[4]); + break; + default: + switch(pointer[1]) { + case CURL_TELQUAL_IS: + infof(data, " IS"); + break; + case CURL_TELQUAL_SEND: + infof(data, " SEND"); + break; + case CURL_TELQUAL_INFO: + infof(data, " INFO/REPLY"); + break; + case CURL_TELQUAL_NAME: + infof(data, " NAME"); + break; + } + + switch(pointer[0]) { + case CURL_TELOPT_TTYPE: + case CURL_TELOPT_XDISPLOC: + pointer[length] = 0; + infof(data, " \"%s\"", &pointer[2]); + break; + case CURL_TELOPT_NEW_ENVIRON: + if(pointer[1] == CURL_TELQUAL_IS) { + infof(data, " "); + for(i = 3; i < length; i++) { + switch(pointer[i]) { + case CURL_NEW_ENV_VAR: + infof(data, ", "); + break; + case CURL_NEW_ENV_VALUE: + infof(data, " = "); + break; + default: + infof(data, "%c", pointer[i]); + break; + } + } + } + break; + default: + for(i = 2; i < length; i++) + infof(data, " %.2x", pointer[i]); + break; + } + } + if(direction) + infof(data, "\n"); + } +} + +static CURLcode check_telnet_options(struct connectdata *conn) +{ + struct curl_slist *head; + struct curl_slist *beg; + char option_keyword[128] = ""; + char option_arg[256] = ""; + struct Curl_easy *data = conn->data; + struct TELNET *tn = (struct TELNET *)conn->data->req.protop; + CURLcode result = CURLE_OK; + int binary_option; + + /* Add the user name as an environment variable if it + was given on the command line */ + if(conn->bits.user_passwd) { + msnprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user); + beg = curl_slist_append(tn->telnet_vars, option_arg); + if(!beg) { + curl_slist_free_all(tn->telnet_vars); + tn->telnet_vars = NULL; + return CURLE_OUT_OF_MEMORY; + } + tn->telnet_vars = beg; + tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES; + } + + for(head = data->set.telnet_options; head; head = head->next) { + if(sscanf(head->data, "%127[^= ]%*[ =]%255s", + option_keyword, option_arg) == 2) { + + /* Terminal type */ + if(strcasecompare(option_keyword, "TTYPE")) { + strncpy(tn->subopt_ttype, option_arg, 31); + tn->subopt_ttype[31] = 0; /* String termination */ + tn->us_preferred[CURL_TELOPT_TTYPE] = CURL_YES; + continue; + } + + /* Display variable */ + if(strcasecompare(option_keyword, "XDISPLOC")) { + strncpy(tn->subopt_xdisploc, option_arg, 127); + tn->subopt_xdisploc[127] = 0; /* String termination */ + tn->us_preferred[CURL_TELOPT_XDISPLOC] = CURL_YES; + continue; + } + + /* Environment variable */ + if(strcasecompare(option_keyword, "NEW_ENV")) { + beg = curl_slist_append(tn->telnet_vars, option_arg); + if(!beg) { + result = CURLE_OUT_OF_MEMORY; + break; + } + tn->telnet_vars = beg; + tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES; + continue; + } + + /* Window Size */ + if(strcasecompare(option_keyword, "WS")) { + if(sscanf(option_arg, "%hu%*[xX]%hu", + &tn->subopt_wsx, &tn->subopt_wsy) == 2) + tn->us_preferred[CURL_TELOPT_NAWS] = CURL_YES; + else { + failf(data, "Syntax error in telnet option: %s", head->data); + result = CURLE_TELNET_OPTION_SYNTAX; + break; + } + continue; + } + + /* To take care or not of the 8th bit in data exchange */ + if(strcasecompare(option_keyword, "BINARY")) { + binary_option = atoi(option_arg); + if(binary_option != 1) { + tn->us_preferred[CURL_TELOPT_BINARY] = CURL_NO; + tn->him_preferred[CURL_TELOPT_BINARY] = CURL_NO; + } + continue; + } + + failf(data, "Unknown telnet option %s", head->data); + result = CURLE_UNKNOWN_OPTION; + break; + } + failf(data, "Syntax error in telnet option: %s", head->data); + result = CURLE_TELNET_OPTION_SYNTAX; + break; + } + + if(result) { + curl_slist_free_all(tn->telnet_vars); + tn->telnet_vars = NULL; + } + + return result; +} + +/* + * suboption() + * + * Look at the sub-option buffer, and try to be helpful to the other + * side. + */ + +static void suboption(struct connectdata *conn) +{ + struct curl_slist *v; + unsigned char temp[2048]; + ssize_t bytes_written; + size_t len; + int err; + char varname[128] = ""; + char varval[128] = ""; + struct Curl_easy *data = conn->data; + struct TELNET *tn = (struct TELNET *)data->req.protop; + + printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn) + 2); + switch(CURL_SB_GET(tn)) { + case CURL_TELOPT_TTYPE: + len = strlen(tn->subopt_ttype) + 4 + 2; + msnprintf((char *)temp, sizeof(temp), + "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_TTYPE, + CURL_TELQUAL_IS, tn->subopt_ttype, CURL_IAC, CURL_SE); + bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len); + if(bytes_written < 0) { + err = SOCKERRNO; + failf(data,"Sending data failed (%d)",err); + } + printsub(data, '>', &temp[2], len-2); + break; + case CURL_TELOPT_XDISPLOC: + len = strlen(tn->subopt_xdisploc) + 4 + 2; + msnprintf((char *)temp, sizeof(temp), + "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_XDISPLOC, + CURL_TELQUAL_IS, tn->subopt_xdisploc, CURL_IAC, CURL_SE); + bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len); + if(bytes_written < 0) { + err = SOCKERRNO; + failf(data,"Sending data failed (%d)",err); + } + printsub(data, '>', &temp[2], len-2); + break; + case CURL_TELOPT_NEW_ENVIRON: + msnprintf((char *)temp, sizeof(temp), + "%c%c%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_NEW_ENVIRON, + CURL_TELQUAL_IS); + len = 4; + + for(v = tn->telnet_vars; v; v = v->next) { + size_t tmplen = (strlen(v->data) + 1); + /* Add the variable only if it fits */ + if(len + tmplen < (int)sizeof(temp)-6) { + if(sscanf(v->data, "%127[^,],%127s", varname, varval)) { + msnprintf((char *)&temp[len], sizeof(temp) - len, + "%c%s%c%s", CURL_NEW_ENV_VAR, varname, + CURL_NEW_ENV_VALUE, varval); + len += tmplen; + } + } + } + msnprintf((char *)&temp[len], sizeof(temp) - len, + "%c%c", CURL_IAC, CURL_SE); + len += 2; + bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len); + if(bytes_written < 0) { + err = SOCKERRNO; + failf(data,"Sending data failed (%d)",err); + } + printsub(data, '>', &temp[2], len-2); + break; + } + return; +} + + +/* + * sendsuboption() + * + * Send suboption information to the server side. + */ + +static void sendsuboption(struct connectdata *conn, int option) +{ + ssize_t bytes_written; + int err; + unsigned short x, y; + unsigned char *uc1, *uc2; + + struct Curl_easy *data = conn->data; + struct TELNET *tn = (struct TELNET *)data->req.protop; + + switch(option) { + case CURL_TELOPT_NAWS: + /* We prepare data to be sent */ + CURL_SB_CLEAR(tn); + CURL_SB_ACCUM(tn, CURL_IAC); + CURL_SB_ACCUM(tn, CURL_SB); + CURL_SB_ACCUM(tn, CURL_TELOPT_NAWS); + /* We must deal either with little or big endian processors */ + /* Window size must be sent according to the 'network order' */ + x = htons(tn->subopt_wsx); + y = htons(tn->subopt_wsy); + uc1 = (unsigned char *)&x; + uc2 = (unsigned char *)&y; + CURL_SB_ACCUM(tn, uc1[0]); + CURL_SB_ACCUM(tn, uc1[1]); + CURL_SB_ACCUM(tn, uc2[0]); + CURL_SB_ACCUM(tn, uc2[1]); + + CURL_SB_ACCUM(tn, CURL_IAC); + CURL_SB_ACCUM(tn, CURL_SE); + CURL_SB_TERM(tn); + /* data suboption is now ready */ + + printsub(data, '>', (unsigned char *)tn->subbuffer + 2, + CURL_SB_LEN(tn)-2); + + /* we send the header of the suboption... */ + bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer, 3); + if(bytes_written < 0) { + err = SOCKERRNO; + failf(data, "Sending data failed (%d)", err); + } + /* ... then the window size with the send_telnet_data() function + to deal with 0xFF cases ... */ + send_telnet_data(conn, (char *)tn->subbuffer + 3, 4); + /* ... and the footer */ + bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer + 7, 2); + if(bytes_written < 0) { + err = SOCKERRNO; + failf(data, "Sending data failed (%d)", err); + } + break; + } +} + + +static +CURLcode telrcv(struct connectdata *conn, + const unsigned char *inbuf, /* Data received from socket */ + ssize_t count) /* Number of bytes received */ +{ + unsigned char c; + CURLcode result; + int in = 0; + int startwrite = -1; + struct Curl_easy *data = conn->data; + struct TELNET *tn = (struct TELNET *)data->req.protop; + +#define startskipping() \ + if(startwrite >= 0) { \ + result = Curl_client_write(conn, \ + CLIENTWRITE_BODY, \ + (char *)&inbuf[startwrite], \ + in-startwrite); \ + if(result) \ + return result; \ + } \ + startwrite = -1 + +#define writebyte() \ + if(startwrite < 0) \ + startwrite = in + +#define bufferflush() startskipping() + + while(count--) { + c = inbuf[in]; + + switch(tn->telrcv_state) { + case CURL_TS_CR: + tn->telrcv_state = CURL_TS_DATA; + if(c == '\0') { + startskipping(); + break; /* Ignore \0 after CR */ + } + writebyte(); + break; + + case CURL_TS_DATA: + if(c == CURL_IAC) { + tn->telrcv_state = CURL_TS_IAC; + startskipping(); + break; + } + else if(c == '\r') + tn->telrcv_state = CURL_TS_CR; + writebyte(); + break; + + case CURL_TS_IAC: + process_iac: + DEBUGASSERT(startwrite < 0); + switch(c) { + case CURL_WILL: + tn->telrcv_state = CURL_TS_WILL; + break; + case CURL_WONT: + tn->telrcv_state = CURL_TS_WONT; + break; + case CURL_DO: + tn->telrcv_state = CURL_TS_DO; + break; + case CURL_DONT: + tn->telrcv_state = CURL_TS_DONT; + break; + case CURL_SB: + CURL_SB_CLEAR(tn); + tn->telrcv_state = CURL_TS_SB; + break; + case CURL_IAC: + tn->telrcv_state = CURL_TS_DATA; + writebyte(); + break; + case CURL_DM: + case CURL_NOP: + case CURL_GA: + default: + tn->telrcv_state = CURL_TS_DATA; + printoption(data, "RCVD", CURL_IAC, c); + break; + } + break; + + case CURL_TS_WILL: + printoption(data, "RCVD", CURL_WILL, c); + tn->please_negotiate = 1; + rec_will(conn, c); + tn->telrcv_state = CURL_TS_DATA; + break; + + case CURL_TS_WONT: + printoption(data, "RCVD", CURL_WONT, c); + tn->please_negotiate = 1; + rec_wont(conn, c); + tn->telrcv_state = CURL_TS_DATA; + break; + + case CURL_TS_DO: + printoption(data, "RCVD", CURL_DO, c); + tn->please_negotiate = 1; + rec_do(conn, c); + tn->telrcv_state = CURL_TS_DATA; + break; + + case CURL_TS_DONT: + printoption(data, "RCVD", CURL_DONT, c); + tn->please_negotiate = 1; + rec_dont(conn, c); + tn->telrcv_state = CURL_TS_DATA; + break; + + case CURL_TS_SB: + if(c == CURL_IAC) + tn->telrcv_state = CURL_TS_SE; + else + CURL_SB_ACCUM(tn, c); + break; + + case CURL_TS_SE: + if(c != CURL_SE) { + if(c != CURL_IAC) { + /* + * This is an error. We only expect to get "IAC IAC" or "IAC SE". + * Several things may have happened. An IAC was not doubled, the + * IAC SE was left off, or another option got inserted into the + * suboption are all possibilities. If we assume that the IAC was + * not doubled, and really the IAC SE was left off, we could get + * into an infinite loop here. So, instead, we terminate the + * suboption, and process the partial suboption if we can. + */ + CURL_SB_ACCUM(tn, CURL_IAC); + CURL_SB_ACCUM(tn, c); + tn->subpointer -= 2; + CURL_SB_TERM(tn); + + printoption(data, "In SUBOPTION processing, RCVD", CURL_IAC, c); + suboption(conn); /* handle sub-option */ + tn->telrcv_state = CURL_TS_IAC; + goto process_iac; + } + CURL_SB_ACCUM(tn, c); + tn->telrcv_state = CURL_TS_SB; + } + else { + CURL_SB_ACCUM(tn, CURL_IAC); + CURL_SB_ACCUM(tn, CURL_SE); + tn->subpointer -= 2; + CURL_SB_TERM(tn); + suboption(conn); /* handle sub-option */ + tn->telrcv_state = CURL_TS_DATA; + } + break; + } + ++in; + } + bufferflush(); + return CURLE_OK; +} + +/* Escape and send a telnet data block */ +static CURLcode send_telnet_data(struct connectdata *conn, + char *buffer, ssize_t nread) +{ + ssize_t escapes, i, outlen; + unsigned char *outbuf = NULL; + CURLcode result = CURLE_OK; + ssize_t bytes_written, total_written; + + /* Determine size of new buffer after escaping */ + escapes = 0; + for(i = 0; i < nread; i++) + if((unsigned char)buffer[i] == CURL_IAC) + escapes++; + outlen = nread + escapes; + + if(outlen == nread) + outbuf = (unsigned char *)buffer; + else { + ssize_t j; + outbuf = malloc(nread + escapes + 1); + if(!outbuf) + return CURLE_OUT_OF_MEMORY; + + j = 0; + for(i = 0; i < nread; i++) { + outbuf[j++] = buffer[i]; + if((unsigned char)buffer[i] == CURL_IAC) + outbuf[j++] = CURL_IAC; + } + outbuf[j] = '\0'; + } + + total_written = 0; + while(!result && total_written < outlen) { + /* Make sure socket is writable to avoid EWOULDBLOCK condition */ + struct pollfd pfd[1]; + pfd[0].fd = conn->sock[FIRSTSOCKET]; + pfd[0].events = POLLOUT; + switch(Curl_poll(pfd, 1, -1)) { + case -1: /* error, abort writing */ + case 0: /* timeout (will never happen) */ + result = CURLE_SEND_ERROR; + break; + default: /* write! */ + bytes_written = 0; + result = Curl_write(conn, conn->sock[FIRSTSOCKET], + outbuf + total_written, + outlen - total_written, + &bytes_written); + total_written += bytes_written; + break; + } + } + + /* Free malloc copy if escaped */ + if(outbuf != (unsigned char *)buffer) + free(outbuf); + + return result; +} + +static CURLcode telnet_done(struct connectdata *conn, + CURLcode status, bool premature) +{ + struct TELNET *tn = (struct TELNET *)conn->data->req.protop; + (void)status; /* unused */ + (void)premature; /* not used */ + + if(!tn) + return CURLE_OK; + + curl_slist_free_all(tn->telnet_vars); + tn->telnet_vars = NULL; + + Curl_safefree(conn->data->req.protop); + + return CURLE_OK; +} + +static CURLcode telnet_do(struct connectdata *conn, bool *done) +{ + CURLcode result; + struct Curl_easy *data = conn->data; + curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; +#ifdef USE_WINSOCK + HMODULE wsock2; + WSOCK2_FUNC close_event_func; + WSOCK2_EVENT create_event_func; + WSOCK2_FUNC event_select_func; + WSOCK2_FUNC enum_netevents_func; + WSAEVENT event_handle; + WSANETWORKEVENTS events; + HANDLE stdin_handle; + HANDLE objs[2]; + DWORD obj_count; + DWORD wait_timeout; + DWORD readfile_read; + int err; +#else + int interval_ms; + struct pollfd pfd[2]; + int poll_cnt; + curl_off_t total_dl = 0; + curl_off_t total_ul = 0; +#endif + ssize_t nread; + struct curltime now; + bool keepon = TRUE; + char *buf = data->state.buffer; + struct TELNET *tn; + + *done = TRUE; /* unconditionally */ + + result = init_telnet(conn); + if(result) + return result; + + tn = (struct TELNET *)data->req.protop; + + result = check_telnet_options(conn); + if(result) + return result; + +#ifdef USE_WINSOCK + /* + ** This functionality only works with WinSock >= 2.0. So, + ** make sure we have it. + */ + result = check_wsock2(data); + if(result) + return result; + + /* OK, so we have WinSock 2.0. We need to dynamically */ + /* load ws2_32.dll and get the function pointers we need. */ + wsock2 = Curl_load_library(TEXT("WS2_32.DLL")); + if(wsock2 == NULL) { + failf(data, "failed to load WS2_32.DLL (%u)", GetLastError()); + return CURLE_FAILED_INIT; + } + + /* Grab a pointer to WSACreateEvent */ + create_event_func = + CURLX_FUNCTION_CAST(WSOCK2_EVENT, + (GetProcAddress(wsock2, "WSACreateEvent"))); + if(create_event_func == NULL) { + failf(data, "failed to find WSACreateEvent function (%u)", GetLastError()); + FreeLibrary(wsock2); + return CURLE_FAILED_INIT; + } + + /* And WSACloseEvent */ + close_event_func = GetProcAddress(wsock2, "WSACloseEvent"); + if(close_event_func == NULL) { + failf(data, "failed to find WSACloseEvent function (%u)", GetLastError()); + FreeLibrary(wsock2); + return CURLE_FAILED_INIT; + } + + /* And WSAEventSelect */ + event_select_func = GetProcAddress(wsock2, "WSAEventSelect"); + if(event_select_func == NULL) { + failf(data, "failed to find WSAEventSelect function (%u)", GetLastError()); + FreeLibrary(wsock2); + return CURLE_FAILED_INIT; + } + + /* And WSAEnumNetworkEvents */ + enum_netevents_func = GetProcAddress(wsock2, "WSAEnumNetworkEvents"); + if(enum_netevents_func == NULL) { + failf(data, "failed to find WSAEnumNetworkEvents function (%u)", + GetLastError()); + FreeLibrary(wsock2); + return CURLE_FAILED_INIT; + } + + /* We want to wait for both stdin and the socket. Since + ** the select() function in winsock only works on sockets + ** we have to use the WaitForMultipleObjects() call. + */ + + /* First, create a sockets event object */ + event_handle = (WSAEVENT)create_event_func(); + if(event_handle == WSA_INVALID_EVENT) { + failf(data, "WSACreateEvent failed (%d)", SOCKERRNO); + FreeLibrary(wsock2); + return CURLE_FAILED_INIT; + } + + /* Tell winsock what events we want to listen to */ + if(event_select_func(sockfd, event_handle, FD_READ|FD_CLOSE) == + SOCKET_ERROR) { + close_event_func(event_handle); + FreeLibrary(wsock2); + return CURLE_OK; + } + + /* The get the Windows file handle for stdin */ + stdin_handle = GetStdHandle(STD_INPUT_HANDLE); + + /* Create the list of objects to wait for */ + objs[0] = event_handle; + objs[1] = stdin_handle; + + /* If stdin_handle is a pipe, use PeekNamedPipe() method to check it, + else use the old WaitForMultipleObjects() way */ + if(GetFileType(stdin_handle) == FILE_TYPE_PIPE || + data->set.is_fread_set) { + /* Don't wait for stdin_handle, just wait for event_handle */ + obj_count = 1; + /* Check stdin_handle per 100 milliseconds */ + wait_timeout = 100; + } + else { + obj_count = 2; + wait_timeout = 1000; + } + + /* Keep on listening and act on events */ + while(keepon) { + const DWORD buf_size = (DWORD)data->set.buffer_size; + DWORD waitret = WaitForMultipleObjects(obj_count, objs, + FALSE, wait_timeout); + switch(waitret) { + case WAIT_TIMEOUT: + { + for(;;) { + if(data->set.is_fread_set) { + size_t n; + /* read from user-supplied method */ + n = data->state.fread_func(buf, 1, buf_size, data->state.in); + if(n == CURL_READFUNC_ABORT) { + keepon = FALSE; + result = CURLE_READ_ERROR; + break; + } + + if(n == CURL_READFUNC_PAUSE) + break; + + if(n == 0) /* no bytes */ + break; + + /* fall through with number of bytes read */ + readfile_read = (DWORD)n; + } + else { + /* read from stdin */ + if(!PeekNamedPipe(stdin_handle, NULL, 0, NULL, + &readfile_read, NULL)) { + keepon = FALSE; + result = CURLE_READ_ERROR; + break; + } + + if(!readfile_read) + break; + + if(!ReadFile(stdin_handle, buf, buf_size, + &readfile_read, NULL)) { + keepon = FALSE; + result = CURLE_READ_ERROR; + break; + } + } + + result = send_telnet_data(conn, buf, readfile_read); + if(result) { + keepon = FALSE; + break; + } + } + } + break; + + case WAIT_OBJECT_0 + 1: + { + if(!ReadFile(stdin_handle, buf, buf_size, + &readfile_read, NULL)) { + keepon = FALSE; + result = CURLE_READ_ERROR; + break; + } + + result = send_telnet_data(conn, buf, readfile_read); + if(result) { + keepon = FALSE; + break; + } + } + break; + + case WAIT_OBJECT_0: + + events.lNetworkEvents = 0; + if(SOCKET_ERROR == enum_netevents_func(sockfd, event_handle, &events)) { + err = SOCKERRNO; + if(err != EINPROGRESS) { + infof(data, "WSAEnumNetworkEvents failed (%d)", err); + keepon = FALSE; + result = CURLE_READ_ERROR; + } + break; + } + if(events.lNetworkEvents & FD_READ) { + /* read data from network */ + result = Curl_read(conn, sockfd, buf, data->set.buffer_size, &nread); + /* read would've blocked. Loop again */ + if(result == CURLE_AGAIN) + break; + /* returned not-zero, this an error */ + else if(result) { + keepon = FALSE; + break; + } + /* returned zero but actually received 0 or less here, + the server closed the connection and we bail out */ + else if(nread <= 0) { + keepon = FALSE; + break; + } + + result = telrcv(conn, (unsigned char *) buf, nread); + if(result) { + keepon = FALSE; + break; + } + + /* Negotiate if the peer has started negotiating, + otherwise don't. We don't want to speak telnet with + non-telnet servers, like POP or SMTP. */ + if(tn->please_negotiate && !tn->already_negotiated) { + negotiate(conn); + tn->already_negotiated = 1; + } + } + if(events.lNetworkEvents & FD_CLOSE) { + keepon = FALSE; + } + break; + + } + + if(data->set.timeout) { + now = Curl_now(); + if(Curl_timediff(now, conn->created) >= data->set.timeout) { + failf(data, "Time-out"); + result = CURLE_OPERATION_TIMEDOUT; + keepon = FALSE; + } + } + } + + /* We called WSACreateEvent, so call WSACloseEvent */ + if(!close_event_func(event_handle)) { + infof(data, "WSACloseEvent failed (%d)", SOCKERRNO); + } + + /* "Forget" pointers into the library we're about to free */ + create_event_func = NULL; + close_event_func = NULL; + event_select_func = NULL; + enum_netevents_func = NULL; + + /* We called LoadLibrary, so call FreeLibrary */ + if(!FreeLibrary(wsock2)) + infof(data, "FreeLibrary(wsock2) failed (%u)", GetLastError()); +#else + pfd[0].fd = sockfd; + pfd[0].events = POLLIN; + + if(data->set.is_fread_set) { + poll_cnt = 1; + interval_ms = 100; /* poll user-supplied read function */ + } + else { + /* really using fread, so infile is a FILE* */ + pfd[1].fd = fileno((FILE *)data->state.in); + pfd[1].events = POLLIN; + poll_cnt = 2; + interval_ms = 1 * 1000; + } + + while(keepon) { + switch(Curl_poll(pfd, poll_cnt, interval_ms)) { + case -1: /* error, stop reading */ + keepon = FALSE; + continue; + case 0: /* timeout */ + pfd[0].revents = 0; + pfd[1].revents = 0; + /* FALLTHROUGH */ + default: /* read! */ + if(pfd[0].revents & POLLIN) { + /* read data from network */ + result = Curl_read(conn, sockfd, buf, data->set.buffer_size, &nread); + /* read would've blocked. Loop again */ + if(result == CURLE_AGAIN) + break; + /* returned not-zero, this an error */ + if(result) { + keepon = FALSE; + break; + } + /* returned zero but actually received 0 or less here, + the server closed the connection and we bail out */ + else if(nread <= 0) { + keepon = FALSE; + break; + } + + total_dl += nread; + Curl_pgrsSetDownloadCounter(data, total_dl); + result = telrcv(conn, (unsigned char *)buf, nread); + if(result) { + keepon = FALSE; + break; + } + + /* Negotiate if the peer has started negotiating, + otherwise don't. We don't want to speak telnet with + non-telnet servers, like POP or SMTP. */ + if(tn->please_negotiate && !tn->already_negotiated) { + negotiate(conn); + tn->already_negotiated = 1; + } + } + + nread = 0; + if(poll_cnt == 2) { + if(pfd[1].revents & POLLIN) { /* read from in file */ + nread = read(pfd[1].fd, buf, data->set.buffer_size); + } + } + else { + /* read from user-supplied method */ + nread = (int)data->state.fread_func(buf, 1, data->set.buffer_size, + data->state.in); + if(nread == CURL_READFUNC_ABORT) { + keepon = FALSE; + break; + } + if(nread == CURL_READFUNC_PAUSE) + break; + } + + if(nread > 0) { + result = send_telnet_data(conn, buf, nread); + if(result) { + keepon = FALSE; + break; + } + total_ul += nread; + Curl_pgrsSetUploadCounter(data, total_ul); + } + else if(nread < 0) + keepon = FALSE; + + break; + } /* poll switch statement */ + + if(data->set.timeout) { + now = Curl_now(); + if(Curl_timediff(now, conn->created) >= data->set.timeout) { + failf(data, "Time-out"); + result = CURLE_OPERATION_TIMEDOUT; + keepon = FALSE; + } + } + + if(Curl_pgrsUpdate(conn)) { + result = CURLE_ABORTED_BY_CALLBACK; + break; + } + } +#endif + /* mark this as "no further transfer wanted" */ + Curl_setup_transfer(data, -1, -1, FALSE, -1); + + return result; +} +#endif diff --git a/dependencies/cmcurl/lib/telnet.h b/dependencies/cmcurl/lib/telnet.h new file mode 100644 index 0000000..668a78a --- /dev/null +++ b/dependencies/cmcurl/lib/telnet.h @@ -0,0 +1,28 @@ +#ifndef HEADER_CURL_TELNET_H +#define HEADER_CURL_TELNET_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifndef CURL_DISABLE_TELNET +extern const struct Curl_handler Curl_handler_telnet; +#endif + +#endif /* HEADER_CURL_TELNET_H */ diff --git a/dependencies/cmcurl/lib/tftp.c b/dependencies/cmcurl/lib/tftp.c new file mode 100644 index 0000000..289cda2 --- /dev/null +++ b/dependencies/cmcurl/lib/tftp.c @@ -0,0 +1,1410 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_TFTP + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#include "urldata.h" +#include +#include "transfer.h" +#include "sendf.h" +#include "tftp.h" +#include "progress.h" +#include "connect.h" +#include "strerror.h" +#include "sockaddr.h" /* required for Curl_sockaddr_storage */ +#include "multiif.h" +#include "url.h" +#include "strcase.h" +#include "speedcheck.h" +#include "select.h" +#include "escape.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* RFC2348 allows the block size to be negotiated */ +#define TFTP_BLKSIZE_DEFAULT 512 +#define TFTP_BLKSIZE_MIN 8 +#define TFTP_BLKSIZE_MAX 65464 +#define TFTP_OPTION_BLKSIZE "blksize" + +/* from RFC2349: */ +#define TFTP_OPTION_TSIZE "tsize" +#define TFTP_OPTION_INTERVAL "timeout" + +typedef enum { + TFTP_MODE_NETASCII = 0, + TFTP_MODE_OCTET +} tftp_mode_t; + +typedef enum { + TFTP_STATE_START = 0, + TFTP_STATE_RX, + TFTP_STATE_TX, + TFTP_STATE_FIN +} tftp_state_t; + +typedef enum { + TFTP_EVENT_NONE = -1, + TFTP_EVENT_INIT = 0, + TFTP_EVENT_RRQ = 1, + TFTP_EVENT_WRQ = 2, + TFTP_EVENT_DATA = 3, + TFTP_EVENT_ACK = 4, + TFTP_EVENT_ERROR = 5, + TFTP_EVENT_OACK = 6, + TFTP_EVENT_TIMEOUT +} tftp_event_t; + +typedef enum { + TFTP_ERR_UNDEF = 0, + TFTP_ERR_NOTFOUND, + TFTP_ERR_PERM, + TFTP_ERR_DISKFULL, + TFTP_ERR_ILLEGAL, + TFTP_ERR_UNKNOWNID, + TFTP_ERR_EXISTS, + TFTP_ERR_NOSUCHUSER, /* This will never be triggered by this code */ + + /* The remaining error codes are internal to curl */ + TFTP_ERR_NONE = -100, + TFTP_ERR_TIMEOUT, + TFTP_ERR_NORESPONSE +} tftp_error_t; + +typedef struct tftp_packet { + unsigned char *data; +} tftp_packet_t; + +typedef struct tftp_state_data { + tftp_state_t state; + tftp_mode_t mode; + tftp_error_t error; + tftp_event_t event; + struct connectdata *conn; + curl_socket_t sockfd; + int retries; + int retry_time; + int retry_max; + time_t start_time; + time_t max_time; + time_t rx_time; + unsigned short block; + struct Curl_sockaddr_storage local_addr; + struct Curl_sockaddr_storage remote_addr; + curl_socklen_t remote_addrlen; + int rbytes; + int sbytes; + int blksize; + int requested_blksize; + tftp_packet_t rpacket; + tftp_packet_t spacket; +} tftp_state_data_t; + + +/* Forward declarations */ +static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event); +static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event); +static CURLcode tftp_connect(struct connectdata *conn, bool *done); +static CURLcode tftp_disconnect(struct connectdata *conn, + bool dead_connection); +static CURLcode tftp_do(struct connectdata *conn, bool *done); +static CURLcode tftp_done(struct connectdata *conn, + CURLcode, bool premature); +static CURLcode tftp_setup_connection(struct connectdata * conn); +static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done); +static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done); +static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); +static CURLcode tftp_translate_code(tftp_error_t error); + + +/* + * TFTP protocol handler. + */ + +const struct Curl_handler Curl_handler_tftp = { + "TFTP", /* scheme */ + tftp_setup_connection, /* setup_connection */ + tftp_do, /* do_it */ + tftp_done, /* done */ + ZERO_NULL, /* do_more */ + tftp_connect, /* connect_it */ + tftp_multi_statemach, /* connecting */ + tftp_doing, /* doing */ + tftp_getsock, /* proto_getsock */ + tftp_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + tftp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_TFTP, /* defport */ + CURLPROTO_TFTP, /* protocol */ + PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */ +}; + +/********************************************************** + * + * tftp_set_timeouts - + * + * Set timeouts based on state machine state. + * Use user provided connect timeouts until DATA or ACK + * packet is received, then use user-provided transfer timeouts + * + * + **********************************************************/ +static CURLcode tftp_set_timeouts(tftp_state_data_t *state) +{ + time_t maxtime, timeout; + timediff_t timeout_ms; + bool start = (state->state == TFTP_STATE_START) ? TRUE : FALSE; + + time(&state->start_time); + + /* Compute drop-dead time */ + timeout_ms = Curl_timeleft(state->conn->data, NULL, start); + + if(timeout_ms < 0) { + /* time-out, bail out, go home */ + failf(state->conn->data, "Connection time-out"); + return CURLE_OPERATION_TIMEDOUT; + } + + if(start) { + + maxtime = (time_t)(timeout_ms + 500) / 1000; + state->max_time = state->start_time + maxtime; + + /* Set per-block timeout to total */ + timeout = maxtime; + + /* Average restart after 5 seconds */ + state->retry_max = (int)timeout/5; + + if(state->retry_max < 1) + /* avoid division by zero below */ + state->retry_max = 1; + + /* Compute the re-start interval to suit the timeout */ + state->retry_time = (int)timeout/state->retry_max; + if(state->retry_time<1) + state->retry_time = 1; + + } + else { + if(timeout_ms > 0) + maxtime = (time_t)(timeout_ms + 500) / 1000; + else + maxtime = 3600; + + state->max_time = state->start_time + maxtime; + + /* Set per-block timeout to total */ + timeout = maxtime; + + /* Average reposting an ACK after 5 seconds */ + state->retry_max = (int)timeout/5; + } + /* But bound the total number */ + if(state->retry_max<3) + state->retry_max = 3; + + if(state->retry_max>50) + state->retry_max = 50; + + /* Compute the re-ACK interval to suit the timeout */ + state->retry_time = (int)(timeout/state->retry_max); + if(state->retry_time<1) + state->retry_time = 1; + + infof(state->conn->data, + "set timeouts for state %d; Total %ld, retry %d maxtry %d\n", + (int)state->state, (long)(state->max_time-state->start_time), + state->retry_time, state->retry_max); + + /* init RX time */ + time(&state->rx_time); + + return CURLE_OK; +} + +/********************************************************** + * + * tftp_set_send_first + * + * Event handler for the START state + * + **********************************************************/ + +static void setpacketevent(tftp_packet_t *packet, unsigned short num) +{ + packet->data[0] = (unsigned char)(num >> 8); + packet->data[1] = (unsigned char)(num & 0xff); +} + + +static void setpacketblock(tftp_packet_t *packet, unsigned short num) +{ + packet->data[2] = (unsigned char)(num >> 8); + packet->data[3] = (unsigned char)(num & 0xff); +} + +static unsigned short getrpacketevent(const tftp_packet_t *packet) +{ + return (unsigned short)((packet->data[0] << 8) | packet->data[1]); +} + +static unsigned short getrpacketblock(const tftp_packet_t *packet) +{ + return (unsigned short)((packet->data[2] << 8) | packet->data[3]); +} + +static size_t Curl_strnlen(const char *string, size_t maxlen) +{ + const char *end = memchr(string, '\0', maxlen); + return end ? (size_t) (end - string) : maxlen; +} + +static const char *tftp_option_get(const char *buf, size_t len, + const char **option, const char **value) +{ + size_t loc; + + loc = Curl_strnlen(buf, len); + loc++; /* NULL term */ + + if(loc >= len) + return NULL; + *option = buf; + + loc += Curl_strnlen(buf + loc, len-loc); + loc++; /* NULL term */ + + if(loc > len) + return NULL; + *value = &buf[strlen(*option) + 1]; + + return &buf[loc]; +} + +static CURLcode tftp_parse_option_ack(tftp_state_data_t *state, + const char *ptr, int len) +{ + const char *tmp = ptr; + struct Curl_easy *data = state->conn->data; + + /* if OACK doesn't contain blksize option, the default (512) must be used */ + state->blksize = TFTP_BLKSIZE_DEFAULT; + + while(tmp < ptr + len) { + const char *option, *value; + + tmp = tftp_option_get(tmp, ptr + len - tmp, &option, &value); + if(tmp == NULL) { + failf(data, "Malformed ACK packet, rejecting"); + return CURLE_TFTP_ILLEGAL; + } + + infof(data, "got option=(%s) value=(%s)\n", option, value); + + if(checkprefix(option, TFTP_OPTION_BLKSIZE)) { + long blksize; + + blksize = strtol(value, NULL, 10); + + if(!blksize) { + failf(data, "invalid blocksize value in OACK packet"); + return CURLE_TFTP_ILLEGAL; + } + if(blksize > TFTP_BLKSIZE_MAX) { + failf(data, "%s (%d)", "blksize is larger than max supported", + TFTP_BLKSIZE_MAX); + return CURLE_TFTP_ILLEGAL; + } + else if(blksize < TFTP_BLKSIZE_MIN) { + failf(data, "%s (%d)", "blksize is smaller than min supported", + TFTP_BLKSIZE_MIN); + return CURLE_TFTP_ILLEGAL; + } + else if(blksize > state->requested_blksize) { + /* could realloc pkt buffers here, but the spec doesn't call out + * support for the server requesting a bigger blksize than the client + * requests */ + failf(data, "%s (%ld)", + "server requested blksize larger than allocated", blksize); + return CURLE_TFTP_ILLEGAL; + } + + state->blksize = (int)blksize; + infof(data, "%s (%d) %s (%d)\n", "blksize parsed from OACK", + state->blksize, "requested", state->requested_blksize); + } + else if(checkprefix(option, TFTP_OPTION_TSIZE)) { + long tsize = 0; + + tsize = strtol(value, NULL, 10); + infof(data, "%s (%ld)\n", "tsize parsed from OACK", tsize); + + /* tsize should be ignored on upload: Who cares about the size of the + remote file? */ + if(!data->set.upload) { + if(!tsize) { + failf(data, "invalid tsize -:%s:- value in OACK packet", value); + return CURLE_TFTP_ILLEGAL; + } + Curl_pgrsSetDownloadSize(data, tsize); + } + } + } + + return CURLE_OK; +} + +static size_t tftp_option_add(tftp_state_data_t *state, size_t csize, + char *buf, const char *option) +{ + if(( strlen(option) + csize + 1) > (size_t)state->blksize) + return 0; + strcpy(buf, option); + return strlen(option) + 1; +} + +static CURLcode tftp_connect_for_tx(tftp_state_data_t *state, + tftp_event_t event) +{ + CURLcode result; +#ifndef CURL_DISABLE_VERBOSE_STRINGS + struct Curl_easy *data = state->conn->data; + + infof(data, "%s\n", "Connected for transmit"); +#endif + state->state = TFTP_STATE_TX; + result = tftp_set_timeouts(state); + if(result) + return result; + return tftp_tx(state, event); +} + +static CURLcode tftp_connect_for_rx(tftp_state_data_t *state, + tftp_event_t event) +{ + CURLcode result; +#ifndef CURL_DISABLE_VERBOSE_STRINGS + struct Curl_easy *data = state->conn->data; + + infof(data, "%s\n", "Connected for receive"); +#endif + state->state = TFTP_STATE_RX; + result = tftp_set_timeouts(state); + if(result) + return result; + return tftp_rx(state, event); +} + +static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event) +{ + size_t sbytes; + ssize_t senddata; + const char *mode = "octet"; + char *filename; + struct Curl_easy *data = state->conn->data; + CURLcode result = CURLE_OK; + + /* Set ascii mode if -B flag was used */ + if(data->set.prefer_ascii) + mode = "netascii"; + + switch(event) { + + case TFTP_EVENT_INIT: /* Send the first packet out */ + case TFTP_EVENT_TIMEOUT: /* Resend the first packet out */ + /* Increment the retry counter, quit if over the limit */ + state->retries++; + if(state->retries>state->retry_max) { + state->error = TFTP_ERR_NORESPONSE; + state->state = TFTP_STATE_FIN; + return result; + } + + if(data->set.upload) { + /* If we are uploading, send an WRQ */ + setpacketevent(&state->spacket, TFTP_EVENT_WRQ); + state->conn->data->req.upload_fromhere = + (char *)state->spacket.data + 4; + if(data->state.infilesize != -1) + Curl_pgrsSetUploadSize(data, data->state.infilesize); + } + else { + /* If we are downloading, send an RRQ */ + setpacketevent(&state->spacket, TFTP_EVENT_RRQ); + } + /* As RFC3617 describes the separator slash is not actually part of the + file name so we skip the always-present first letter of the path + string. */ + result = Curl_urldecode(data, &state->conn->data->state.up.path[1], 0, + &filename, NULL, FALSE); + if(result) + return result; + + if(strlen(filename) > (state->blksize - strlen(mode) - 4)) { + failf(data, "TFTP file name too long\n"); + free(filename); + return CURLE_TFTP_ILLEGAL; /* too long file name field */ + } + + msnprintf((char *)state->spacket.data + 2, + state->blksize, + "%s%c%s%c", filename, '\0', mode, '\0'); + sbytes = 4 + strlen(filename) + strlen(mode); + + /* optional addition of TFTP options */ + if(!data->set.tftp_no_options) { + char buf[64]; + /* add tsize option */ + if(data->set.upload && (data->state.infilesize != -1)) + msnprintf(buf, sizeof(buf), "%" CURL_FORMAT_CURL_OFF_T, + data->state.infilesize); + else + strcpy(buf, "0"); /* the destination is large enough */ + + sbytes += tftp_option_add(state, sbytes, + (char *)state->spacket.data + sbytes, + TFTP_OPTION_TSIZE); + sbytes += tftp_option_add(state, sbytes, + (char *)state->spacket.data + sbytes, buf); + /* add blksize option */ + msnprintf(buf, sizeof(buf), "%d", state->requested_blksize); + sbytes += tftp_option_add(state, sbytes, + (char *)state->spacket.data + sbytes, + TFTP_OPTION_BLKSIZE); + sbytes += tftp_option_add(state, sbytes, + (char *)state->spacket.data + sbytes, buf); + + /* add timeout option */ + msnprintf(buf, sizeof(buf), "%d", state->retry_time); + sbytes += tftp_option_add(state, sbytes, + (char *)state->spacket.data + sbytes, + TFTP_OPTION_INTERVAL); + sbytes += tftp_option_add(state, sbytes, + (char *)state->spacket.data + sbytes, buf); + } + + /* the typecase for the 3rd argument is mostly for systems that do + not have a size_t argument, like older unixes that want an 'int' */ + senddata = sendto(state->sockfd, (void *)state->spacket.data, + (SEND_TYPE_ARG3)sbytes, 0, + state->conn->ip_addr->ai_addr, + state->conn->ip_addr->ai_addrlen); + if(senddata != (ssize_t)sbytes) { + char buffer[STRERROR_LEN]; + failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + } + free(filename); + break; + + case TFTP_EVENT_OACK: + if(data->set.upload) { + result = tftp_connect_for_tx(state, event); + } + else { + result = tftp_connect_for_rx(state, event); + } + break; + + case TFTP_EVENT_ACK: /* Connected for transmit */ + result = tftp_connect_for_tx(state, event); + break; + + case TFTP_EVENT_DATA: /* Connected for receive */ + result = tftp_connect_for_rx(state, event); + break; + + case TFTP_EVENT_ERROR: + state->state = TFTP_STATE_FIN; + break; + + default: + failf(state->conn->data, "tftp_send_first: internal error"); + break; + } + + return result; +} + +/* the next blocknum is x + 1 but it needs to wrap at an unsigned 16bit + boundary */ +#define NEXT_BLOCKNUM(x) (((x) + 1)&0xffff) + +/********************************************************** + * + * tftp_rx + * + * Event handler for the RX state + * + **********************************************************/ +static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event) +{ + ssize_t sbytes; + int rblock; + struct Curl_easy *data = state->conn->data; + char buffer[STRERROR_LEN]; + + switch(event) { + + case TFTP_EVENT_DATA: + /* Is this the block we expect? */ + rblock = getrpacketblock(&state->rpacket); + if(NEXT_BLOCKNUM(state->block) == rblock) { + /* This is the expected block. Reset counters and ACK it. */ + state->retries = 0; + } + else if(state->block == rblock) { + /* This is the last recently received block again. Log it and ACK it + again. */ + infof(data, "Received last DATA packet block %d again.\n", rblock); + } + else { + /* totally unexpected, just log it */ + infof(data, + "Received unexpected DATA packet block %d, expecting block %d\n", + rblock, NEXT_BLOCKNUM(state->block)); + break; + } + + /* ACK this block. */ + state->block = (unsigned short)rblock; + setpacketevent(&state->spacket, TFTP_EVENT_ACK); + setpacketblock(&state->spacket, state->block); + sbytes = sendto(state->sockfd, (void *)state->spacket.data, + 4, SEND_4TH_ARG, + (struct sockaddr *)&state->remote_addr, + state->remote_addrlen); + if(sbytes < 0) { + failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + return CURLE_SEND_ERROR; + } + + /* Check if completed (That is, a less than full packet is received) */ + if(state->rbytes < (ssize_t)state->blksize + 4) { + state->state = TFTP_STATE_FIN; + } + else { + state->state = TFTP_STATE_RX; + } + time(&state->rx_time); + break; + + case TFTP_EVENT_OACK: + /* ACK option acknowledgement so we can move on to data */ + state->block = 0; + state->retries = 0; + setpacketevent(&state->spacket, TFTP_EVENT_ACK); + setpacketblock(&state->spacket, state->block); + sbytes = sendto(state->sockfd, (void *)state->spacket.data, + 4, SEND_4TH_ARG, + (struct sockaddr *)&state->remote_addr, + state->remote_addrlen); + if(sbytes < 0) { + failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + return CURLE_SEND_ERROR; + } + + /* we're ready to RX data */ + state->state = TFTP_STATE_RX; + time(&state->rx_time); + break; + + case TFTP_EVENT_TIMEOUT: + /* Increment the retry count and fail if over the limit */ + state->retries++; + infof(data, + "Timeout waiting for block %d ACK. Retries = %d\n", + NEXT_BLOCKNUM(state->block), state->retries); + if(state->retries > state->retry_max) { + state->error = TFTP_ERR_TIMEOUT; + state->state = TFTP_STATE_FIN; + } + else { + /* Resend the previous ACK */ + sbytes = sendto(state->sockfd, (void *)state->spacket.data, + 4, SEND_4TH_ARG, + (struct sockaddr *)&state->remote_addr, + state->remote_addrlen); + if(sbytes<0) { + failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + return CURLE_SEND_ERROR; + } + } + break; + + case TFTP_EVENT_ERROR: + setpacketevent(&state->spacket, TFTP_EVENT_ERROR); + setpacketblock(&state->spacket, state->block); + (void)sendto(state->sockfd, (void *)state->spacket.data, + 4, SEND_4TH_ARG, + (struct sockaddr *)&state->remote_addr, + state->remote_addrlen); + /* don't bother with the return code, but if the socket is still up we + * should be a good TFTP client and let the server know we're done */ + state->state = TFTP_STATE_FIN; + break; + + default: + failf(data, "%s", "tftp_rx: internal error"); + return CURLE_TFTP_ILLEGAL; /* not really the perfect return code for + this */ + } + return CURLE_OK; +} + +/********************************************************** + * + * tftp_tx + * + * Event handler for the TX state + * + **********************************************************/ +static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) +{ + struct Curl_easy *data = state->conn->data; + ssize_t sbytes; + CURLcode result = CURLE_OK; + struct SingleRequest *k = &data->req; + size_t cb; /* Bytes currently read */ + char buffer[STRERROR_LEN]; + + switch(event) { + + case TFTP_EVENT_ACK: + case TFTP_EVENT_OACK: + if(event == TFTP_EVENT_ACK) { + /* Ack the packet */ + int rblock = getrpacketblock(&state->rpacket); + + if(rblock != state->block && + /* There's a bug in tftpd-hpa that causes it to send us an ack for + * 65535 when the block number wraps to 0. So when we're expecting + * 0, also accept 65535. See + * http://syslinux.zytor.com/archives/2010-September/015253.html + * */ + !(state->block == 0 && rblock == 65535)) { + /* This isn't the expected block. Log it and up the retry counter */ + infof(data, "Received ACK for block %d, expecting %d\n", + rblock, state->block); + state->retries++; + /* Bail out if over the maximum */ + if(state->retries>state->retry_max) { + failf(data, "tftp_tx: giving up waiting for block %d ack", + state->block); + result = CURLE_SEND_ERROR; + } + else { + /* Re-send the data packet */ + sbytes = sendto(state->sockfd, (void *)state->spacket.data, + 4 + state->sbytes, SEND_4TH_ARG, + (struct sockaddr *)&state->remote_addr, + state->remote_addrlen); + /* Check all sbytes were sent */ + if(sbytes<0) { + failf(data, "%s", Curl_strerror(SOCKERRNO, + buffer, sizeof(buffer))); + result = CURLE_SEND_ERROR; + } + } + + return result; + } + /* This is the expected packet. Reset the counters and send the next + block */ + time(&state->rx_time); + state->block++; + } + else + state->block = 1; /* first data block is 1 when using OACK */ + + state->retries = 0; + setpacketevent(&state->spacket, TFTP_EVENT_DATA); + setpacketblock(&state->spacket, state->block); + if(state->block > 1 && state->sbytes < state->blksize) { + state->state = TFTP_STATE_FIN; + return CURLE_OK; + } + + /* TFTP considers data block size < 512 bytes as an end of session. So + * in some cases we must wait for additional data to build full (512 bytes) + * data block. + * */ + state->sbytes = 0; + state->conn->data->req.upload_fromhere = (char *)state->spacket.data + 4; + do { + result = Curl_fillreadbuffer(state->conn, state->blksize - state->sbytes, + &cb); + if(result) + return result; + state->sbytes += (int)cb; + state->conn->data->req.upload_fromhere += cb; + } while(state->sbytes < state->blksize && cb != 0); + + sbytes = sendto(state->sockfd, (void *) state->spacket.data, + 4 + state->sbytes, SEND_4TH_ARG, + (struct sockaddr *)&state->remote_addr, + state->remote_addrlen); + /* Check all sbytes were sent */ + if(sbytes<0) { + failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + return CURLE_SEND_ERROR; + } + /* Update the progress meter */ + k->writebytecount += state->sbytes; + Curl_pgrsSetUploadCounter(data, k->writebytecount); + break; + + case TFTP_EVENT_TIMEOUT: + /* Increment the retry counter and log the timeout */ + state->retries++; + infof(data, "Timeout waiting for block %d ACK. " + " Retries = %d\n", NEXT_BLOCKNUM(state->block), state->retries); + /* Decide if we've had enough */ + if(state->retries > state->retry_max) { + state->error = TFTP_ERR_TIMEOUT; + state->state = TFTP_STATE_FIN; + } + else { + /* Re-send the data packet */ + sbytes = sendto(state->sockfd, (void *)state->spacket.data, + 4 + state->sbytes, SEND_4TH_ARG, + (struct sockaddr *)&state->remote_addr, + state->remote_addrlen); + /* Check all sbytes were sent */ + if(sbytes<0) { + failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + return CURLE_SEND_ERROR; + } + /* since this was a re-send, we remain at the still byte position */ + Curl_pgrsSetUploadCounter(data, k->writebytecount); + } + break; + + case TFTP_EVENT_ERROR: + state->state = TFTP_STATE_FIN; + setpacketevent(&state->spacket, TFTP_EVENT_ERROR); + setpacketblock(&state->spacket, state->block); + (void)sendto(state->sockfd, (void *)state->spacket.data, 4, SEND_4TH_ARG, + (struct sockaddr *)&state->remote_addr, + state->remote_addrlen); + /* don't bother with the return code, but if the socket is still up we + * should be a good TFTP client and let the server know we're done */ + state->state = TFTP_STATE_FIN; + break; + + default: + failf(data, "tftp_tx: internal error, event: %i", (int)(event)); + break; + } + + return result; +} + +/********************************************************** + * + * tftp_translate_code + * + * Translate internal error codes to CURL error codes + * + **********************************************************/ +static CURLcode tftp_translate_code(tftp_error_t error) +{ + CURLcode result = CURLE_OK; + + if(error != TFTP_ERR_NONE) { + switch(error) { + case TFTP_ERR_NOTFOUND: + result = CURLE_TFTP_NOTFOUND; + break; + case TFTP_ERR_PERM: + result = CURLE_TFTP_PERM; + break; + case TFTP_ERR_DISKFULL: + result = CURLE_REMOTE_DISK_FULL; + break; + case TFTP_ERR_UNDEF: + case TFTP_ERR_ILLEGAL: + result = CURLE_TFTP_ILLEGAL; + break; + case TFTP_ERR_UNKNOWNID: + result = CURLE_TFTP_UNKNOWNID; + break; + case TFTP_ERR_EXISTS: + result = CURLE_REMOTE_FILE_EXISTS; + break; + case TFTP_ERR_NOSUCHUSER: + result = CURLE_TFTP_NOSUCHUSER; + break; + case TFTP_ERR_TIMEOUT: + result = CURLE_OPERATION_TIMEDOUT; + break; + case TFTP_ERR_NORESPONSE: + result = CURLE_COULDNT_CONNECT; + break; + default: + result = CURLE_ABORTED_BY_CALLBACK; + break; + } + } + else + result = CURLE_OK; + + return result; +} + +/********************************************************** + * + * tftp_state_machine + * + * The tftp state machine event dispatcher + * + **********************************************************/ +static CURLcode tftp_state_machine(tftp_state_data_t *state, + tftp_event_t event) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = state->conn->data; + + switch(state->state) { + case TFTP_STATE_START: + DEBUGF(infof(data, "TFTP_STATE_START\n")); + result = tftp_send_first(state, event); + break; + case TFTP_STATE_RX: + DEBUGF(infof(data, "TFTP_STATE_RX\n")); + result = tftp_rx(state, event); + break; + case TFTP_STATE_TX: + DEBUGF(infof(data, "TFTP_STATE_TX\n")); + result = tftp_tx(state, event); + break; + case TFTP_STATE_FIN: + infof(data, "%s\n", "TFTP finished"); + break; + default: + DEBUGF(infof(data, "STATE: %d\n", state->state)); + failf(data, "%s", "Internal state machine error"); + result = CURLE_TFTP_ILLEGAL; + break; + } + + return result; +} + +/********************************************************** + * + * tftp_disconnect + * + * The disconnect callback + * + **********************************************************/ +static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection) +{ + tftp_state_data_t *state = conn->proto.tftpc; + (void) dead_connection; + + /* done, free dynamically allocated pkt buffers */ + if(state) { + Curl_safefree(state->rpacket.data); + Curl_safefree(state->spacket.data); + free(state); + } + + return CURLE_OK; +} + +/********************************************************** + * + * tftp_connect + * + * The connect callback + * + **********************************************************/ +static CURLcode tftp_connect(struct connectdata *conn, bool *done) +{ + tftp_state_data_t *state; + int blksize; + + blksize = TFTP_BLKSIZE_DEFAULT; + + state = conn->proto.tftpc = calloc(1, sizeof(tftp_state_data_t)); + if(!state) + return CURLE_OUT_OF_MEMORY; + + /* alloc pkt buffers based on specified blksize */ + if(conn->data->set.tftp_blksize) { + blksize = (int)conn->data->set.tftp_blksize; + if(blksize > TFTP_BLKSIZE_MAX || blksize < TFTP_BLKSIZE_MIN) + return CURLE_TFTP_ILLEGAL; + } + + if(!state->rpacket.data) { + state->rpacket.data = calloc(1, blksize + 2 + 2); + + if(!state->rpacket.data) + return CURLE_OUT_OF_MEMORY; + } + + if(!state->spacket.data) { + state->spacket.data = calloc(1, blksize + 2 + 2); + + if(!state->spacket.data) + return CURLE_OUT_OF_MEMORY; + } + + /* we don't keep TFTP connections up basically because there's none or very + * little gain for UDP */ + connclose(conn, "TFTP"); + + state->conn = conn; + state->sockfd = state->conn->sock[FIRSTSOCKET]; + state->state = TFTP_STATE_START; + state->error = TFTP_ERR_NONE; + state->blksize = blksize; + state->requested_blksize = blksize; + + ((struct sockaddr *)&state->local_addr)->sa_family = + (CURL_SA_FAMILY_T)(conn->ip_addr->ai_family); + + tftp_set_timeouts(state); + + if(!conn->bits.bound) { + /* If not already bound, bind to any interface, random UDP port. If it is + * reused or a custom local port was desired, this has already been done! + * + * We once used the size of the local_addr struct as the third argument + * for bind() to better work with IPv6 or whatever size the struct could + * have, but we learned that at least Tru64, AIX and IRIX *requires* the + * size of that argument to match the exact size of a 'sockaddr_in' struct + * when running IPv4-only. + * + * Therefore we use the size from the address we connected to, which we + * assume uses the same IP version and thus hopefully this works for both + * IPv4 and IPv6... + */ + int rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr, + conn->ip_addr->ai_addrlen); + if(rc) { + char buffer[STRERROR_LEN]; + failf(conn->data, "bind() failed; %s", + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + return CURLE_COULDNT_CONNECT; + } + conn->bits.bound = TRUE; + } + + Curl_pgrsStartNow(conn->data); + + *done = TRUE; + + return CURLE_OK; +} + +/********************************************************** + * + * tftp_done + * + * The done callback + * + **********************************************************/ +static CURLcode tftp_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + CURLcode result = CURLE_OK; + tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc; + + (void)status; /* unused */ + (void)premature; /* not used */ + + if(Curl_pgrsDone(conn)) + return CURLE_ABORTED_BY_CALLBACK; + + /* If we have encountered an error */ + if(state) + result = tftp_translate_code(state->error); + + return result; +} + +/********************************************************** + * + * tftp_getsock + * + * The getsock callback + * + **********************************************************/ +static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks) +{ + if(!numsocks) + return GETSOCK_BLANK; + + socks[0] = conn->sock[FIRSTSOCKET]; + + return GETSOCK_READSOCK(0); +} + +/********************************************************** + * + * tftp_receive_packet + * + * Called once select fires and data is ready on the socket + * + **********************************************************/ +static CURLcode tftp_receive_packet(struct connectdata *conn) +{ + struct Curl_sockaddr_storage fromaddr; + curl_socklen_t fromlen; + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc; + struct SingleRequest *k = &data->req; + + /* Receive the packet */ + fromlen = sizeof(fromaddr); + state->rbytes = (int)recvfrom(state->sockfd, + (void *)state->rpacket.data, + state->blksize + 4, + 0, + (struct sockaddr *)&fromaddr, + &fromlen); + if(state->remote_addrlen == 0) { + memcpy(&state->remote_addr, &fromaddr, fromlen); + state->remote_addrlen = fromlen; + } + + /* Sanity check packet length */ + if(state->rbytes < 4) { + failf(data, "Received too short packet"); + /* Not a timeout, but how best to handle it? */ + state->event = TFTP_EVENT_TIMEOUT; + } + else { + /* The event is given by the TFTP packet time */ + unsigned short event = getrpacketevent(&state->rpacket); + state->event = (tftp_event_t)event; + + switch(state->event) { + case TFTP_EVENT_DATA: + /* Don't pass to the client empty or retransmitted packets */ + if(state->rbytes > 4 && + (NEXT_BLOCKNUM(state->block) == getrpacketblock(&state->rpacket))) { + result = Curl_client_write(conn, CLIENTWRITE_BODY, + (char *)state->rpacket.data + 4, + state->rbytes-4); + if(result) { + tftp_state_machine(state, TFTP_EVENT_ERROR); + return result; + } + k->bytecount += state->rbytes-4; + Curl_pgrsSetDownloadCounter(data, (curl_off_t) k->bytecount); + } + break; + case TFTP_EVENT_ERROR: + { + unsigned short error = getrpacketblock(&state->rpacket); + char *str = (char *)state->rpacket.data + 4; + size_t strn = state->rbytes - 4; + state->error = (tftp_error_t)error; + if(Curl_strnlen(str, strn) < strn) + infof(data, "TFTP error: %s\n", str); + break; + } + case TFTP_EVENT_ACK: + break; + case TFTP_EVENT_OACK: + result = tftp_parse_option_ack(state, + (const char *)state->rpacket.data + 2, + state->rbytes-2); + if(result) + return result; + break; + case TFTP_EVENT_RRQ: + case TFTP_EVENT_WRQ: + default: + failf(data, "%s", "Internal error: Unexpected packet"); + break; + } + + /* Update the progress meter */ + if(Curl_pgrsUpdate(conn)) { + tftp_state_machine(state, TFTP_EVENT_ERROR); + return CURLE_ABORTED_BY_CALLBACK; + } + } + return result; +} + +/********************************************************** + * + * tftp_state_timeout + * + * Check if timeouts have been reached + * + **********************************************************/ +static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event) +{ + time_t current; + tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc; + + if(event) + *event = TFTP_EVENT_NONE; + + time(¤t); + if(current > state->max_time) { + DEBUGF(infof(conn->data, "timeout: %ld > %ld\n", + (long)current, (long)state->max_time)); + state->error = TFTP_ERR_TIMEOUT; + state->state = TFTP_STATE_FIN; + return 0; + } + if(current > state->rx_time + state->retry_time) { + if(event) + *event = TFTP_EVENT_TIMEOUT; + time(&state->rx_time); /* update even though we received nothing */ + } + + /* there's a typecast below here since 'time_t' may in fact be larger than + 'long', but we estimate that a 'long' will still be able to hold number + of seconds even if "only" 32 bit */ + return (long)(state->max_time - current); +} + +/********************************************************** + * + * tftp_multi_statemach + * + * Handle single RX socket event and return + * + **********************************************************/ +static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done) +{ + tftp_event_t event; + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc; + long timeout_ms = tftp_state_timeout(conn, &event); + + *done = FALSE; + + if(timeout_ms <= 0) { + failf(data, "TFTP response timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + if(event != TFTP_EVENT_NONE) { + result = tftp_state_machine(state, event); + if(result) + return result; + *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE; + if(*done) + /* Tell curl we're done */ + Curl_setup_transfer(data, -1, -1, FALSE, -1); + } + else { + /* no timeouts to handle, check our socket */ + int rc = SOCKET_READABLE(state->sockfd, 0); + + if(rc == -1) { + /* bail out */ + int error = SOCKERRNO; + char buffer[STRERROR_LEN]; + failf(data, "%s", Curl_strerror(error, buffer, sizeof(buffer))); + state->event = TFTP_EVENT_ERROR; + } + else if(rc != 0) { + result = tftp_receive_packet(conn); + if(result) + return result; + result = tftp_state_machine(state, state->event); + if(result) + return result; + *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE; + if(*done) + /* Tell curl we're done */ + Curl_setup_transfer(data, -1, -1, FALSE, -1); + } + /* if rc == 0, then select() timed out */ + } + + return result; +} + +/********************************************************** + * + * tftp_doing + * + * Called from multi.c while DOing + * + **********************************************************/ +static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done) +{ + CURLcode result; + result = tftp_multi_statemach(conn, dophase_done); + + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + else if(!result) { + /* The multi code doesn't have this logic for the DOING state so we + provide it for TFTP since it may do the entire transfer in this + state. */ + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + else + result = Curl_speedcheck(conn->data, Curl_now()); + } + return result; +} + +/********************************************************** + * + * tftp_peform + * + * Entry point for transfer from tftp_do, sarts state mach + * + **********************************************************/ +static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done) +{ + CURLcode result = CURLE_OK; + tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc; + + *dophase_done = FALSE; + + result = tftp_state_machine(state, TFTP_EVENT_INIT); + + if((state->state == TFTP_STATE_FIN) || result) + return result; + + tftp_multi_statemach(conn, dophase_done); + + if(*dophase_done) + DEBUGF(infof(conn->data, "DO phase is complete\n")); + + return result; +} + + +/********************************************************** + * + * tftp_do + * + * The do callback + * + * This callback initiates the TFTP transfer + * + **********************************************************/ + +static CURLcode tftp_do(struct connectdata *conn, bool *done) +{ + tftp_state_data_t *state; + CURLcode result; + + *done = FALSE; + + if(!conn->proto.tftpc) { + result = tftp_connect(conn, done); + if(result) + return result; + } + + state = (tftp_state_data_t *)conn->proto.tftpc; + if(!state) + return CURLE_TFTP_ILLEGAL; + + result = tftp_perform(conn, done); + + /* If tftp_perform() returned an error, use that for return code. If it + was OK, see if tftp_translate_code() has an error. */ + if(!result) + /* If we have encountered an internal tftp error, translate it. */ + result = tftp_translate_code(state->error); + + return result; +} + +static CURLcode tftp_setup_connection(struct connectdata * conn) +{ + struct Curl_easy *data = conn->data; + char *type; + + conn->socktype = SOCK_DGRAM; /* UDP datagram based */ + + /* TFTP URLs support an extension like ";mode=" that + * we'll try to get now! */ + type = strstr(data->state.up.path, ";mode="); + + if(!type) + type = strstr(conn->host.rawalloc, ";mode="); + + if(type) { + char command; + *type = 0; /* it was in the middle of the hostname */ + command = Curl_raw_toupper(type[6]); + + switch(command) { + case 'A': /* ASCII mode */ + case 'N': /* NETASCII mode */ + data->set.prefer_ascii = TRUE; + break; + + case 'O': /* octet mode */ + case 'I': /* binary mode */ + default: + /* switch off ASCII */ + data->set.prefer_ascii = FALSE; + break; + } + } + + return CURLE_OK; +} +#endif diff --git a/dependencies/cmcurl/lib/tftp.h b/dependencies/cmcurl/lib/tftp.h new file mode 100644 index 0000000..1335f64 --- /dev/null +++ b/dependencies/cmcurl/lib/tftp.h @@ -0,0 +1,28 @@ +#ifndef HEADER_CURL_TFTP_H +#define HEADER_CURL_TFTP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifndef CURL_DISABLE_TFTP +extern const struct Curl_handler Curl_handler_tftp; +#endif + +#endif /* HEADER_CURL_TFTP_H */ diff --git a/dependencies/cmcurl/lib/timeval.c b/dependencies/cmcurl/lib/timeval.c new file mode 100644 index 0000000..e2bd7fd --- /dev/null +++ b/dependencies/cmcurl/lib/timeval.c @@ -0,0 +1,213 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "timeval.h" + +#if defined(WIN32) && !defined(MSDOS) + +/* set in win32_init() */ +extern LARGE_INTEGER Curl_freq; +extern bool Curl_isVistaOrGreater; + +struct curltime Curl_now(void) +{ + struct curltime now; + if(Curl_isVistaOrGreater) { /* QPC timer might have issues pre-Vista */ + LARGE_INTEGER count; + QueryPerformanceCounter(&count); + now.tv_sec = (time_t)(count.QuadPart / Curl_freq.QuadPart); + now.tv_usec = (int)((count.QuadPart % Curl_freq.QuadPart) * 1000000 / + Curl_freq.QuadPart); + } + else { + /* Disable /analyze warning that GetTickCount64 is preferred */ +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:28159) +#endif + DWORD milliseconds = GetTickCount(); +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + + now.tv_sec = milliseconds / 1000; + now.tv_usec = (milliseconds % 1000) * 1000; + } + return now; +} + +#elif defined(HAVE_CLOCK_GETTIME_MONOTONIC) + +struct curltime Curl_now(void) +{ + /* + ** clock_gettime() is granted to be increased monotonically when the + ** monotonic clock is queried. Time starting point is unspecified, it + ** could be the system start-up time, the Epoch, or something else, + ** in any case the time starting point does not change once that the + ** system has started up. + */ +#ifdef HAVE_GETTIMEOFDAY + struct timeval now; +#endif + struct curltime cnow; + struct timespec tsnow; + + /* + ** clock_gettime() may be defined by Apple's SDK as weak symbol thus + ** code compiles but fails during run-time if clock_gettime() is + ** called on unsupported OS version. + */ +#if defined(__APPLE__) && (HAVE_BUILTIN_AVAILABLE == 1) + bool have_clock_gettime = FALSE; + if(__builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *)) + have_clock_gettime = TRUE; +#endif + + if( +#if defined(__APPLE__) && (HAVE_BUILTIN_AVAILABLE == 1) + have_clock_gettime && +#endif + (0 == clock_gettime(CLOCK_MONOTONIC, &tsnow))) { + cnow.tv_sec = tsnow.tv_sec; + cnow.tv_usec = (unsigned int)(tsnow.tv_nsec / 1000); + } + /* + ** Even when the configure process has truly detected monotonic clock + ** availability, it might happen that it is not actually available at + ** run-time. When this occurs simply fallback to other time source. + */ +#ifdef HAVE_GETTIMEOFDAY + else { + (void)gettimeofday(&now, NULL); + cnow.tv_sec = now.tv_sec; + cnow.tv_usec = (unsigned int)now.tv_usec; + } +#else + else { + cnow.tv_sec = time(NULL); + cnow.tv_usec = 0; + } +#endif + return cnow; +} + +#elif defined(HAVE_MACH_ABSOLUTE_TIME) + +#include +#include + +struct curltime Curl_now(void) +{ + /* + ** Monotonic timer on Mac OS is provided by mach_absolute_time(), which + ** returns time in Mach "absolute time units," which are platform-dependent. + ** To convert to nanoseconds, one must use conversion factors specified by + ** mach_timebase_info(). + */ + static mach_timebase_info_data_t timebase; + struct curltime cnow; + uint64_t usecs; + + if(0 == timebase.denom) + (void) mach_timebase_info(&timebase); + + usecs = mach_absolute_time(); + usecs *= timebase.numer; + usecs /= timebase.denom; + usecs /= 1000; + + cnow.tv_sec = usecs / 1000000; + cnow.tv_usec = (int)(usecs % 1000000); + + return cnow; +} + +#elif defined(HAVE_GETTIMEOFDAY) + +struct curltime Curl_now(void) +{ + /* + ** gettimeofday() is not granted to be increased monotonically, due to + ** clock drifting and external source time synchronization it can jump + ** forward or backward in time. + */ + struct timeval now; + struct curltime ret; + (void)gettimeofday(&now, NULL); + ret.tv_sec = now.tv_sec; + ret.tv_usec = (int)now.tv_usec; + return ret; +} + +#else + +struct curltime Curl_now(void) +{ + /* + ** time() returns the value of time in seconds since the Epoch. + */ + struct curltime now; + now.tv_sec = time(NULL); + now.tv_usec = 0; + return now; +} + +#endif + +#if SIZEOF_TIME_T < 8 +#define TIME_MAX INT_MAX +#define TIME_MIN INT_MIN +#else +#define TIME_MAX 9223372036854775807LL +#define TIME_MIN -9223372036854775807LL +#endif + +/* + * Returns: time difference in number of milliseconds. For too large diffs it + * returns max value. + * + * @unittest: 1323 + */ +timediff_t Curl_timediff(struct curltime newer, struct curltime older) +{ + timediff_t diff = (timediff_t)newer.tv_sec-older.tv_sec; + if(diff >= (TIME_MAX/1000)) + return TIME_MAX; + else if(diff <= (TIME_MIN/1000)) + return TIME_MIN; + return diff * 1000 + (newer.tv_usec-older.tv_usec)/1000; +} + +/* + * Returns: time difference in number of microseconds. For too large diffs it + * returns max value. + */ +timediff_t Curl_timediff_us(struct curltime newer, struct curltime older) +{ + timediff_t diff = (timediff_t)newer.tv_sec-older.tv_sec; + if(diff >= (TIME_MAX/1000000)) + return TIME_MAX; + else if(diff <= (TIME_MIN/1000000)) + return TIME_MIN; + return diff * 1000000 + newer.tv_usec-older.tv_usec; +} diff --git a/dependencies/cmcurl/lib/timeval.h b/dependencies/cmcurl/lib/timeval.h new file mode 100644 index 0000000..96867d7 --- /dev/null +++ b/dependencies/cmcurl/lib/timeval.h @@ -0,0 +1,58 @@ +#ifndef HEADER_CURL_TIMEVAL_H +#define HEADER_CURL_TIMEVAL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if SIZEOF_TIME_T < 8 +typedef int timediff_t; +#define CURL_FORMAT_TIMEDIFF_T "d" +#else +typedef curl_off_t timediff_t; +#define CURL_FORMAT_TIMEDIFF_T CURL_FORMAT_CURL_OFF_T +#endif + +struct curltime { + time_t tv_sec; /* seconds */ + int tv_usec; /* microseconds */ +}; + +struct curltime Curl_now(void); + +/* + * Make sure that the first argument (t1) is the more recent time and t2 is + * the older time, as otherwise you get a weird negative time-diff back... + * + * Returns: the time difference in number of milliseconds. + */ +timediff_t Curl_timediff(struct curltime t1, struct curltime t2); + +/* + * Make sure that the first argument (t1) is the more recent time and t2 is + * the older time, as otherwise you get a weird negative time-diff back... + * + * Returns: the time difference in number of microseconds. + */ +timediff_t Curl_timediff_us(struct curltime newer, struct curltime older); + +#endif /* HEADER_CURL_TIMEVAL_H */ diff --git a/dependencies/cmcurl/lib/transfer.c b/dependencies/cmcurl/lib/transfer.c new file mode 100644 index 0000000..514330e --- /dev/null +++ b/dependencies/cmcurl/lib/transfer.c @@ -0,0 +1,1893 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include "strtoofft.h" + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_SIGNAL_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#ifdef HAVE_SYS_SELECT_H +#include +#endif + +#ifndef HAVE_SOCKET +#error "We can't compile without socket() support!" +#endif + +#include "urldata.h" +#include +#include "netrc.h" + +#include "content_encoding.h" +#include "hostip.h" +#include "transfer.h" +#include "sendf.h" +#include "speedcheck.h" +#include "progress.h" +#include "http.h" +#include "url.h" +#include "getinfo.h" +#include "vtls/vtls.h" +#include "select.h" +#include "multiif.h" +#include "connect.h" +#include "non-ascii.h" +#include "http2.h" +#include "mime.h" +#include "strcase.h" +#include "urlapi-int.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \ + !defined(CURL_DISABLE_IMAP) +/* + * checkheaders() checks the linked list of custom headers for a + * particular header (prefix). Provide the prefix without colon! + * + * Returns a pointer to the first matching header or NULL if none matched. + */ +char *Curl_checkheaders(const struct connectdata *conn, + const char *thisheader) +{ + struct curl_slist *head; + size_t thislen = strlen(thisheader); + struct Curl_easy *data = conn->data; + + for(head = data->set.headers; head; head = head->next) { + if(strncasecompare(head->data, thisheader, thislen) && + Curl_headersep(head->data[thislen]) ) + return head->data; + } + + return NULL; +} +#endif + +CURLcode Curl_get_upload_buffer(struct Curl_easy *data) +{ + if(!data->state.ulbuf) { + data->state.ulbuf = malloc(data->set.upload_buffer_size); + if(!data->state.ulbuf) + return CURLE_OUT_OF_MEMORY; + } + return CURLE_OK; +} + +#ifndef CURL_DISABLE_HTTP +/* + * This function will be called to loop through the trailers buffer + * until no more data is available for sending. + */ +static size_t Curl_trailers_read(char *buffer, size_t size, size_t nitems, + void *raw) +{ + struct Curl_easy *data = (struct Curl_easy *)raw; + Curl_send_buffer *trailers_buf = data->state.trailers_buf; + size_t bytes_left = trailers_buf->size_used-data->state.trailers_bytes_sent; + size_t to_copy = (size*nitems < bytes_left) ? size*nitems : bytes_left; + if(to_copy) { + memcpy(buffer, + &trailers_buf->buffer[data->state.trailers_bytes_sent], + to_copy); + data->state.trailers_bytes_sent += to_copy; + } + return to_copy; +} + +static size_t Curl_trailers_left(void *raw) +{ + struct Curl_easy *data = (struct Curl_easy *)raw; + Curl_send_buffer *trailers_buf = data->state.trailers_buf; + return trailers_buf->size_used - data->state.trailers_bytes_sent; +} +#endif + +/* + * This function will call the read callback to fill our buffer with data + * to upload. + */ +CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes, + size_t *nreadp) +{ + struct Curl_easy *data = conn->data; + size_t buffersize = bytes; + size_t nread; + + curl_read_callback readfunc = NULL; + void *extra_data = NULL; + +#ifdef CURL_DOES_CONVERSIONS + bool sending_http_headers = FALSE; + + if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) { + const struct HTTP *http = data->req.protop; + + if(http->sending == HTTPSEND_REQUEST) + /* We're sending the HTTP request headers, not the data. + Remember that so we don't re-translate them into garbage. */ + sending_http_headers = TRUE; + } +#endif + +#ifndef CURL_DISABLE_HTTP + if(data->state.trailers_state == TRAILERS_INITIALIZED) { + struct curl_slist *trailers = NULL; + CURLcode c; + int trailers_ret_code; + + /* at this point we already verified that the callback exists + so we compile and store the trailers buffer, then proceed */ + infof(data, + "Moving trailers state machine from initialized to sending.\n"); + data->state.trailers_state = TRAILERS_SENDING; + data->state.trailers_buf = Curl_add_buffer_init(); + if(!data->state.trailers_buf) { + failf(data, "Unable to allocate trailing headers buffer !"); + return CURLE_OUT_OF_MEMORY; + } + data->state.trailers_bytes_sent = 0; + Curl_set_in_callback(data, true); + trailers_ret_code = data->set.trailer_callback(&trailers, + data->set.trailer_data); + Curl_set_in_callback(data, false); + if(trailers_ret_code == CURL_TRAILERFUNC_OK) { + c = Curl_http_compile_trailers(trailers, data->state.trailers_buf, data); + } + else { + failf(data, "operation aborted by trailing headers callback"); + *nreadp = 0; + c = CURLE_ABORTED_BY_CALLBACK; + } + if(c != CURLE_OK) { + Curl_add_buffer_free(&data->state.trailers_buf); + curl_slist_free_all(trailers); + return c; + } + infof(data, "Successfully compiled trailers.\r\n"); + curl_slist_free_all(trailers); + } +#endif + + /* if we are transmitting trailing data, we don't need to write + a chunk size so we skip this */ + if(data->req.upload_chunky && + data->state.trailers_state == TRAILERS_NONE) { + /* if chunked Transfer-Encoding */ + buffersize -= (8 + 2 + 2); /* 32bit hex + CRLF + CRLF */ + data->req.upload_fromhere += (8 + 2); /* 32bit hex + CRLF */ + } + +#ifndef CURL_DISABLE_HTTP + if(data->state.trailers_state == TRAILERS_SENDING) { + /* if we're here then that means that we already sent the last empty chunk + but we didn't send a final CR LF, so we sent 0 CR LF. We then start + pulling trailing data until we ²have no more at which point we + simply return to the previous point in the state machine as if + nothing happened. + */ + readfunc = Curl_trailers_read; + extra_data = (void *)data; + } + else +#endif + { + readfunc = data->state.fread_func; + extra_data = data->state.in; + } + + Curl_set_in_callback(data, true); + nread = readfunc(data->req.upload_fromhere, 1, + buffersize, extra_data); + Curl_set_in_callback(data, false); + + if(nread == CURL_READFUNC_ABORT) { + failf(data, "operation aborted by callback"); + *nreadp = 0; + return CURLE_ABORTED_BY_CALLBACK; + } + if(nread == CURL_READFUNC_PAUSE) { + struct SingleRequest *k = &data->req; + + if(conn->handler->flags & PROTOPT_NONETWORK) { + /* protocols that work without network cannot be paused. This is + actually only FILE:// just now, and it can't pause since the transfer + isn't done using the "normal" procedure. */ + failf(data, "Read callback asked for PAUSE when not supported!"); + return CURLE_READ_ERROR; + } + + /* CURL_READFUNC_PAUSE pauses read callbacks that feed socket writes */ + k->keepon |= KEEP_SEND_PAUSE; /* mark socket send as paused */ + if(data->req.upload_chunky) { + /* Back out the preallocation done above */ + data->req.upload_fromhere -= (8 + 2); + } + *nreadp = 0; + + return CURLE_OK; /* nothing was read */ + } + else if(nread > buffersize) { + /* the read function returned a too large value */ + *nreadp = 0; + failf(data, "read function returned funny value"); + return CURLE_READ_ERROR; + } + + if(!data->req.forbidchunk && data->req.upload_chunky) { + /* if chunked Transfer-Encoding + * build chunk: + * + * CRLF + * CRLF + */ + /* On non-ASCII platforms the may or may not be + translated based on set.prefer_ascii while the protocol + portion must always be translated to the network encoding. + To further complicate matters, line end conversion might be + done later on, so we need to prevent CRLFs from becoming + CRCRLFs if that's the case. To do this we use bare LFs + here, knowing they'll become CRLFs later on. + */ + + bool added_crlf = FALSE; + int hexlen = 0; + const char *endofline_native; + const char *endofline_network; + + if( +#ifdef CURL_DO_LINEEND_CONV + (data->set.prefer_ascii) || +#endif + (data->set.crlf)) { + /* \n will become \r\n later on */ + endofline_native = "\n"; + endofline_network = "\x0a"; + } + else { + endofline_native = "\r\n"; + endofline_network = "\x0d\x0a"; + } + + /* if we're not handling trailing data, proceed as usual */ + if(data->state.trailers_state != TRAILERS_SENDING) { + char hexbuffer[11] = ""; + hexlen = msnprintf(hexbuffer, sizeof(hexbuffer), + "%zx%s", nread, endofline_native); + + /* move buffer pointer */ + data->req.upload_fromhere -= hexlen; + nread += hexlen; + + /* copy the prefix to the buffer, leaving out the NUL */ + memcpy(data->req.upload_fromhere, hexbuffer, hexlen); + + /* always append ASCII CRLF to the data unless + we have a valid trailer callback */ +#ifndef CURL_DISABLE_HTTP + if((nread-hexlen) == 0 && + data->set.trailer_callback != NULL && + data->state.trailers_state == TRAILERS_NONE) { + data->state.trailers_state = TRAILERS_INITIALIZED; + } + else +#endif + { + memcpy(data->req.upload_fromhere + nread, + endofline_network, + strlen(endofline_network)); + added_crlf = TRUE; + } + } + +#ifdef CURL_DOES_CONVERSIONS + { + CURLcode result; + size_t length; + if(data->set.prefer_ascii) + /* translate the protocol and data */ + length = nread; + else + /* just translate the protocol portion */ + length = hexlen; + if(length) { + result = Curl_convert_to_network(data, data->req.upload_fromhere, + length); + /* Curl_convert_to_network calls failf if unsuccessful */ + if(result) + return result; + } + } +#endif /* CURL_DOES_CONVERSIONS */ + +#ifndef CURL_DISABLE_HTTP + if(data->state.trailers_state == TRAILERS_SENDING && + !Curl_trailers_left(data)) { + Curl_add_buffer_free(&data->state.trailers_buf); + data->state.trailers_state = TRAILERS_DONE; + data->set.trailer_data = NULL; + data->set.trailer_callback = NULL; + /* mark the transfer as done */ + data->req.upload_done = TRUE; + infof(data, "Signaling end of chunked upload after trailers.\n"); + } + else +#endif + if((nread - hexlen) == 0 && + data->state.trailers_state != TRAILERS_INITIALIZED) { + /* mark this as done once this chunk is transferred */ + data->req.upload_done = TRUE; + infof(data, + "Signaling end of chunked upload via terminating chunk.\n"); + } + + if(added_crlf) + nread += strlen(endofline_network); /* for the added end of line */ + } +#ifdef CURL_DOES_CONVERSIONS + else if((data->set.prefer_ascii) && (!sending_http_headers)) { + CURLcode result; + result = Curl_convert_to_network(data, data->req.upload_fromhere, nread); + /* Curl_convert_to_network calls failf if unsuccessful */ + if(result) + return result; + } +#endif /* CURL_DOES_CONVERSIONS */ + + *nreadp = nread; + + return CURLE_OK; +} + + +/* + * Curl_readrewind() rewinds the read stream. This is typically used for HTTP + * POST/PUT with multi-pass authentication when a sending was denied and a + * resend is necessary. + */ +CURLcode Curl_readrewind(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + curl_mimepart *mimepart = &data->set.mimepost; + + conn->bits.rewindaftersend = FALSE; /* we rewind now */ + + /* explicitly switch off sending data on this connection now since we are + about to restart a new transfer and thus we want to avoid inadvertently + sending more data on the existing connection until the next transfer + starts */ + data->req.keepon &= ~KEEP_SEND; + + /* We have sent away data. If not using CURLOPT_POSTFIELDS or + CURLOPT_HTTPPOST, call app to rewind + */ + if(conn->handler->protocol & PROTO_FAMILY_HTTP) { + struct HTTP *http = data->req.protop; + + if(http->sendit) + mimepart = http->sendit; + } + if(data->set.postfields) + ; /* do nothing */ + else if(data->set.httpreq == HTTPREQ_POST_MIME || + data->set.httpreq == HTTPREQ_POST_FORM) { + if(Curl_mime_rewind(mimepart)) { + failf(data, "Cannot rewind mime/post data"); + return CURLE_SEND_FAIL_REWIND; + } + } + else { + if(data->set.seek_func) { + int err; + + Curl_set_in_callback(data, true); + err = (data->set.seek_func)(data->set.seek_client, 0, SEEK_SET); + Curl_set_in_callback(data, false); + if(err) { + failf(data, "seek callback returned error %d", (int)err); + return CURLE_SEND_FAIL_REWIND; + } + } + else if(data->set.ioctl_func) { + curlioerr err; + + Curl_set_in_callback(data, true); + err = (data->set.ioctl_func)(data, CURLIOCMD_RESTARTREAD, + data->set.ioctl_client); + Curl_set_in_callback(data, false); + infof(data, "the ioctl callback returned %d\n", (int)err); + + if(err) { + failf(data, "ioctl callback returned error %d", (int)err); + return CURLE_SEND_FAIL_REWIND; + } + } + else { + /* If no CURLOPT_READFUNCTION is used, we know that we operate on a + given FILE * stream and we can actually attempt to rewind that + ourselves with fseek() */ + if(data->state.fread_func == (curl_read_callback)fread) { + if(-1 != fseek(data->state.in, 0, SEEK_SET)) + /* successful rewind */ + return CURLE_OK; + } + + /* no callback set or failure above, makes us fail at once */ + failf(data, "necessary data rewind wasn't possible"); + return CURLE_SEND_FAIL_REWIND; + } + } + return CURLE_OK; +} + +static int data_pending(const struct connectdata *conn) +{ + /* in the case of libssh2, we can never be really sure that we have emptied + its internal buffers so we MUST always try until we get EAGAIN back */ + return conn->handler->protocol&(CURLPROTO_SCP|CURLPROTO_SFTP) || +#if defined(USE_NGHTTP2) + Curl_ssl_data_pending(conn, FIRSTSOCKET) || + /* For HTTP/2, we may read up everything including response body + with header fields in Curl_http_readwrite_headers. If no + content-length is provided, curl waits for the connection + close, which we emulate it using conn->proto.httpc.closed = + TRUE. The thing is if we read everything, then http2_recv won't + be called and we cannot signal the HTTP/2 stream has closed. As + a workaround, we return nonzero here to call http2_recv. */ + ((conn->handler->protocol&PROTO_FAMILY_HTTP) && conn->httpversion == 20); +#else + Curl_ssl_data_pending(conn, FIRSTSOCKET); +#endif +} + +/* + * Check to see if CURLOPT_TIMECONDITION was met by comparing the time of the + * remote document with the time provided by CURLOPT_TIMEVAL + */ +bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc) +{ + if((timeofdoc == 0) || (data->set.timevalue == 0)) + return TRUE; + + switch(data->set.timecondition) { + case CURL_TIMECOND_IFMODSINCE: + default: + if(timeofdoc <= data->set.timevalue) { + infof(data, + "The requested document is not new enough\n"); + data->info.timecond = TRUE; + return FALSE; + } + break; + case CURL_TIMECOND_IFUNMODSINCE: + if(timeofdoc >= data->set.timevalue) { + infof(data, + "The requested document is not old enough\n"); + data->info.timecond = TRUE; + return FALSE; + } + break; + } + + return TRUE; +} + +/* + * Go ahead and do a read if we have a readable socket or if + * the stream was rewound (in which case we have data in a + * buffer) + * + * return '*comeback' TRUE if we didn't properly drain the socket so this + * function should get called again without select() or similar in between! + */ +static CURLcode readwrite_data(struct Curl_easy *data, + struct connectdata *conn, + struct SingleRequest *k, + int *didwhat, bool *done, + bool *comeback) +{ + CURLcode result = CURLE_OK; + ssize_t nread; /* number of bytes read */ + size_t excess = 0; /* excess bytes read */ + bool readmore = FALSE; /* used by RTP to signal for more data */ + int maxloops = 100; + + *done = FALSE; + *comeback = FALSE; + + /* This is where we loop until we have read everything there is to + read or we get a CURLE_AGAIN */ + do { + bool is_empty_data = FALSE; + size_t buffersize = data->set.buffer_size; + size_t bytestoread = buffersize; + + if( +#if defined(USE_NGHTTP2) + /* For HTTP/2, read data without caring about the content + length. This is safe because body in HTTP/2 is always + segmented thanks to its framing layer. Meanwhile, we have to + call Curl_read to ensure that http2_handle_stream_close is + called when we read all incoming bytes for a particular + stream. */ + !((conn->handler->protocol & PROTO_FAMILY_HTTP) && + conn->httpversion == 20) && +#endif + k->size != -1 && !k->header) { + /* make sure we don't read too much */ + curl_off_t totalleft = k->size - k->bytecount; + if(totalleft < (curl_off_t)bytestoread) + bytestoread = (size_t)totalleft; + } + + if(bytestoread) { + /* receive data from the network! */ + result = Curl_read(conn, conn->sockfd, k->buf, bytestoread, &nread); + + /* read would've blocked */ + if(CURLE_AGAIN == result) + break; /* get out of loop */ + + if(result>0) + return result; + } + else { + /* read nothing but since we wanted nothing we consider this an OK + situation to proceed from */ + DEBUGF(infof(data, "readwrite_data: we're done!\n")); + nread = 0; + } + + if((k->bytecount == 0) && (k->writebytecount == 0)) { + Curl_pgrsTime(data, TIMER_STARTTRANSFER); + if(k->exp100 > EXP100_SEND_DATA) + /* set time stamp to compare with when waiting for the 100 */ + k->start100 = Curl_now(); + } + + *didwhat |= KEEP_RECV; + /* indicates data of zero size, i.e. empty file */ + is_empty_data = ((nread == 0) && (k->bodywrites == 0)) ? TRUE : FALSE; + + /* NUL terminate, allowing string ops to be used */ + if(0 < nread || is_empty_data) { + k->buf[nread] = 0; + } + else { + /* if we receive 0 or less here, the server closed the connection + and we bail out from this! */ + DEBUGF(infof(data, "nread <= 0, server closed connection, bailing\n")); + k->keepon &= ~KEEP_RECV; + break; + } + + /* Default buffer to use when we write the buffer, it may be changed + in the flow below before the actual storing is done. */ + k->str = k->buf; + + if(conn->handler->readwrite) { + result = conn->handler->readwrite(data, conn, &nread, &readmore); + if(result) + return result; + if(readmore) + break; + } + +#ifndef CURL_DISABLE_HTTP + /* Since this is a two-state thing, we check if we are parsing + headers at the moment or not. */ + if(k->header) { + /* we are in parse-the-header-mode */ + bool stop_reading = FALSE; + result = Curl_http_readwrite_headers(data, conn, &nread, &stop_reading); + if(result) + return result; + + if(conn->handler->readwrite && + (k->maxdownload <= 0 && nread > 0)) { + result = conn->handler->readwrite(data, conn, &nread, &readmore); + if(result) + return result; + if(readmore) + break; + } + + if(stop_reading) { + /* We've stopped dealing with input, get out of the do-while loop */ + + if(nread > 0) { + infof(data, + "Excess found:" + " excess = %zd" + " url = %s (zero-length body)\n", + nread, data->state.up.path); + } + + break; + } + } +#endif /* CURL_DISABLE_HTTP */ + + + /* This is not an 'else if' since it may be a rest from the header + parsing, where the beginning of the buffer is headers and the end + is non-headers. */ + if(k->str && !k->header && (nread > 0 || is_empty_data)) { + + if(data->set.opt_no_body) { + /* data arrives although we want none, bail out */ + streamclose(conn, "ignoring body"); + *done = TRUE; + return CURLE_WEIRD_SERVER_REPLY; + } + +#ifndef CURL_DISABLE_HTTP + if(0 == k->bodywrites && !is_empty_data) { + /* These checks are only made the first time we are about to + write a piece of the body */ + if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) { + /* HTTP-only checks */ + + if(data->req.newurl) { + if(conn->bits.close) { + /* Abort after the headers if "follow Location" is set + and we're set to close anyway. */ + k->keepon &= ~KEEP_RECV; + *done = TRUE; + return CURLE_OK; + } + /* We have a new url to load, but since we want to be able + to re-use this connection properly, we read the full + response in "ignore more" */ + k->ignorebody = TRUE; + infof(data, "Ignoring the response-body\n"); + } + if(data->state.resume_from && !k->content_range && + (data->set.httpreq == HTTPREQ_GET) && + !k->ignorebody) { + + if(k->size == data->state.resume_from) { + /* The resume point is at the end of file, consider this fine + even if it doesn't allow resume from here. */ + infof(data, "The entire document is already downloaded"); + connclose(conn, "already downloaded"); + /* Abort download */ + k->keepon &= ~KEEP_RECV; + *done = TRUE; + return CURLE_OK; + } + + /* we wanted to resume a download, although the server doesn't + * seem to support this and we did this with a GET (if it + * wasn't a GET we did a POST or PUT resume) */ + failf(data, "HTTP server doesn't seem to support " + "byte ranges. Cannot resume."); + return CURLE_RANGE_ERROR; + } + + if(data->set.timecondition && !data->state.range) { + /* A time condition has been set AND no ranges have been + requested. This seems to be what chapter 13.3.4 of + RFC 2616 defines to be the correct action for a + HTTP/1.1 client */ + + if(!Curl_meets_timecondition(data, k->timeofdoc)) { + *done = TRUE; + /* We're simulating a http 304 from server so we return + what should have been returned from the server */ + data->info.httpcode = 304; + infof(data, "Simulate a HTTP 304 response!\n"); + /* we abort the transfer before it is completed == we ruin the + re-use ability. Close the connection */ + connclose(conn, "Simulated 304 handling"); + return CURLE_OK; + } + } /* we have a time condition */ + + } /* this is HTTP or RTSP */ + } /* this is the first time we write a body part */ +#endif /* CURL_DISABLE_HTTP */ + + k->bodywrites++; + + /* pass data to the debug function before it gets "dechunked" */ + if(data->set.verbose) { + if(k->badheader) { + Curl_debug(data, CURLINFO_DATA_IN, data->state.headerbuff, + (size_t)k->hbuflen); + if(k->badheader == HEADER_PARTHEADER) + Curl_debug(data, CURLINFO_DATA_IN, + k->str, (size_t)nread); + } + else + Curl_debug(data, CURLINFO_DATA_IN, + k->str, (size_t)nread); + } + +#ifndef CURL_DISABLE_HTTP + if(k->chunk) { + /* + * Here comes a chunked transfer flying and we need to decode this + * properly. While the name says read, this function both reads + * and writes away the data. The returned 'nread' holds the number + * of actual data it wrote to the client. + */ + + CHUNKcode res = + Curl_httpchunk_read(conn, k->str, nread, &nread); + + if(CHUNKE_OK < res) { + if(CHUNKE_WRITE_ERROR == res) { + failf(data, "Failed writing data"); + return CURLE_WRITE_ERROR; + } + failf(data, "%s in chunked-encoding", Curl_chunked_strerror(res)); + return CURLE_RECV_ERROR; + } + if(CHUNKE_STOP == res) { + size_t dataleft; + /* we're done reading chunks! */ + k->keepon &= ~KEEP_RECV; /* read no more */ + + /* There are now possibly N number of bytes at the end of the + str buffer that weren't written to the client. + Push it back to be read on the next pass. */ + + dataleft = conn->chunk.dataleft; + if(dataleft != 0) { + infof(conn->data, "Leftovers after chunking: %zu bytes\n", + dataleft); + } + } + /* If it returned OK, we just keep going */ + } +#endif /* CURL_DISABLE_HTTP */ + + /* Account for body content stored in the header buffer */ + if((k->badheader == HEADER_PARTHEADER) && !k->ignorebody) { + DEBUGF(infof(data, "Increasing bytecount by %zu from hbuflen\n", + k->hbuflen)); + k->bytecount += k->hbuflen; + } + + if((-1 != k->maxdownload) && + (k->bytecount + nread >= k->maxdownload)) { + + excess = (size_t)(k->bytecount + nread - k->maxdownload); + if(excess > 0 && !k->ignorebody) { + infof(data, + "Excess found in a read:" + " excess = %zu" + ", size = %" CURL_FORMAT_CURL_OFF_T + ", maxdownload = %" CURL_FORMAT_CURL_OFF_T + ", bytecount = %" CURL_FORMAT_CURL_OFF_T "\n", + excess, k->size, k->maxdownload, k->bytecount); + } + + nread = (ssize_t) (k->maxdownload - k->bytecount); + if(nread < 0) /* this should be unusual */ + nread = 0; + + k->keepon &= ~KEEP_RECV; /* we're done reading */ + } + + k->bytecount += nread; + + Curl_pgrsSetDownloadCounter(data, k->bytecount); + + if(!k->chunk && (nread || k->badheader || is_empty_data)) { + /* If this is chunky transfer, it was already written */ + + if(k->badheader && !k->ignorebody) { + /* we parsed a piece of data wrongly assuming it was a header + and now we output it as body instead */ + + /* Don't let excess data pollute body writes */ + if(k->maxdownload == -1 || (curl_off_t)k->hbuflen <= k->maxdownload) + result = Curl_client_write(conn, CLIENTWRITE_BODY, + data->state.headerbuff, + k->hbuflen); + else + result = Curl_client_write(conn, CLIENTWRITE_BODY, + data->state.headerbuff, + (size_t)k->maxdownload); + + if(result) + return result; + } + if(k->badheader < HEADER_ALLBAD) { + /* This switch handles various content encodings. If there's an + error here, be sure to check over the almost identical code + in http_chunks.c. + Make sure that ALL_CONTENT_ENCODINGS contains all the + encodings handled here. */ + if(conn->data->set.http_ce_skip || !k->writer_stack) { + if(!k->ignorebody) { +#ifndef CURL_DISABLE_POP3 + if(conn->handler->protocol & PROTO_FAMILY_POP3) + result = Curl_pop3_write(conn, k->str, nread); + else +#endif /* CURL_DISABLE_POP3 */ + result = Curl_client_write(conn, CLIENTWRITE_BODY, k->str, + nread); + } + } + else if(!k->ignorebody) + result = Curl_unencode_write(conn, k->writer_stack, k->str, nread); + } + k->badheader = HEADER_NORMAL; /* taken care of now */ + + if(result) + return result; + } + + } /* if(!header and data to read) */ + + if(conn->handler->readwrite && excess && !conn->bits.stream_was_rewound) { + /* Parse the excess data */ + k->str += nread; + + if(&k->str[excess] > &k->buf[data->set.buffer_size]) { + /* the excess amount was too excessive(!), make sure + it doesn't read out of buffer */ + excess = &k->buf[data->set.buffer_size] - k->str; + } + nread = (ssize_t)excess; + + result = conn->handler->readwrite(data, conn, &nread, &readmore); + if(result) + return result; + + if(readmore) + k->keepon |= KEEP_RECV; /* we're not done reading */ + break; + } + + if(is_empty_data) { + /* if we received nothing, the server closed the connection and we + are done */ + k->keepon &= ~KEEP_RECV; + } + + if(k->keepon & KEEP_RECV_PAUSE) { + /* this is a paused transfer */ + break; + } + + } while(data_pending(conn) && maxloops--); + + if(maxloops <= 0) { + /* we mark it as read-again-please */ + conn->cselect_bits = CURL_CSELECT_IN; + *comeback = TRUE; + } + + if(((k->keepon & (KEEP_RECV|KEEP_SEND)) == KEEP_SEND) && + conn->bits.close) { + /* When we've read the entire thing and the close bit is set, the server + may now close the connection. If there's now any kind of sending going + on from our side, we need to stop that immediately. */ + infof(data, "we are done reading and this is set to close, stop send\n"); + k->keepon &= ~KEEP_SEND; /* no writing anymore either */ + } + + return CURLE_OK; +} + +static CURLcode done_sending(struct connectdata *conn, + struct SingleRequest *k) +{ + k->keepon &= ~KEEP_SEND; /* we're done writing */ + + Curl_http2_done_sending(conn); + + if(conn->bits.rewindaftersend) { + CURLcode result = Curl_readrewind(conn); + if(result) + return result; + } + return CURLE_OK; +} + +#if defined(WIN32) && !defined(USE_LWIPSOCK) +#ifndef SIO_IDEAL_SEND_BACKLOG_QUERY +#define SIO_IDEAL_SEND_BACKLOG_QUERY 0x4004747B +#endif + +static void win_update_buffer_size(curl_socket_t sockfd) +{ + int result; + ULONG ideal; + DWORD ideallen; + result = WSAIoctl(sockfd, SIO_IDEAL_SEND_BACKLOG_QUERY, 0, 0, + &ideal, sizeof(ideal), &ideallen, 0, 0); + if(result == 0) { + setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, + (const char *)&ideal, sizeof(ideal)); + } +} +#else +#define win_update_buffer_size(x) +#endif + +/* + * Send data to upload to the server, when the socket is writable. + */ +static CURLcode readwrite_upload(struct Curl_easy *data, + struct connectdata *conn, + int *didwhat) +{ + ssize_t i, si; + ssize_t bytes_written; + CURLcode result; + ssize_t nread; /* number of bytes read */ + bool sending_http_headers = FALSE; + struct SingleRequest *k = &data->req; + + if((k->bytecount == 0) && (k->writebytecount == 0)) + Curl_pgrsTime(data, TIMER_STARTTRANSFER); + + *didwhat |= KEEP_SEND; + + do { + /* only read more data if there's no upload data already + present in the upload buffer */ + if(0 == k->upload_present) { + result = Curl_get_upload_buffer(data); + if(result) + return result; + /* init the "upload from here" pointer */ + k->upload_fromhere = data->state.ulbuf; + + if(!k->upload_done) { + /* HTTP pollution, this should be written nicer to become more + protocol agnostic. */ + size_t fillcount; + struct HTTP *http = k->protop; + + if((k->exp100 == EXP100_SENDING_REQUEST) && + (http->sending == HTTPSEND_BODY)) { + /* If this call is to send body data, we must take some action: + We have sent off the full HTTP 1.1 request, and we shall now + go into the Expect: 100 state and await such a header */ + k->exp100 = EXP100_AWAITING_CONTINUE; /* wait for the header */ + k->keepon &= ~KEEP_SEND; /* disable writing */ + k->start100 = Curl_now(); /* timeout count starts now */ + *didwhat &= ~KEEP_SEND; /* we didn't write anything actually */ + /* set a timeout for the multi interface */ + Curl_expire(data, data->set.expect_100_timeout, EXPIRE_100_TIMEOUT); + break; + } + + if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) { + if(http->sending == HTTPSEND_REQUEST) + /* We're sending the HTTP request headers, not the data. + Remember that so we don't change the line endings. */ + sending_http_headers = TRUE; + else + sending_http_headers = FALSE; + } + + result = Curl_fillreadbuffer(conn, data->set.upload_buffer_size, + &fillcount); + if(result) + return result; + + nread = fillcount; + } + else + nread = 0; /* we're done uploading/reading */ + + if(!nread && (k->keepon & KEEP_SEND_PAUSE)) { + /* this is a paused transfer */ + break; + } + if(nread <= 0) { + result = done_sending(conn, k); + if(result) + return result; + break; + } + + /* store number of bytes available for upload */ + k->upload_present = nread; + + /* convert LF to CRLF if so asked */ + if((!sending_http_headers) && ( +#ifdef CURL_DO_LINEEND_CONV + /* always convert if we're FTPing in ASCII mode */ + (data->set.prefer_ascii) || +#endif + (data->set.crlf))) { + /* Do we need to allocate a scratch buffer? */ + if(!data->state.scratch) { + data->state.scratch = malloc(2 * data->set.upload_buffer_size); + if(!data->state.scratch) { + failf(data, "Failed to alloc scratch buffer!"); + + return CURLE_OUT_OF_MEMORY; + } + } + + /* + * ASCII/EBCDIC Note: This is presumably a text (not binary) + * transfer so the data should already be in ASCII. + * That means the hex values for ASCII CR (0x0d) & LF (0x0a) + * must be used instead of the escape sequences \r & \n. + */ + for(i = 0, si = 0; i < nread; i++, si++) { + if(k->upload_fromhere[i] == 0x0a) { + data->state.scratch[si++] = 0x0d; + data->state.scratch[si] = 0x0a; + if(!data->set.crlf) { + /* we're here only because FTP is in ASCII mode... + bump infilesize for the LF we just added */ + if(data->state.infilesize != -1) + data->state.infilesize++; + } + } + else + data->state.scratch[si] = k->upload_fromhere[i]; + } + + if(si != nread) { + /* only perform the special operation if we really did replace + anything */ + nread = si; + + /* upload from the new (replaced) buffer instead */ + k->upload_fromhere = data->state.scratch; + + /* set the new amount too */ + k->upload_present = nread; + } + } + +#ifndef CURL_DISABLE_SMTP + if(conn->handler->protocol & PROTO_FAMILY_SMTP) { + result = Curl_smtp_escape_eob(conn, nread); + if(result) + return result; + } +#endif /* CURL_DISABLE_SMTP */ + } /* if 0 == k->upload_present */ + else { + /* We have a partial buffer left from a previous "round". Use + that instead of reading more data */ + } + + /* write to socket (send away data) */ + result = Curl_write(conn, + conn->writesockfd, /* socket to send to */ + k->upload_fromhere, /* buffer pointer */ + k->upload_present, /* buffer size */ + &bytes_written); /* actually sent */ + if(result) + return result; + + win_update_buffer_size(conn->writesockfd); + + if(data->set.verbose) + /* show the data before we change the pointer upload_fromhere */ + Curl_debug(data, CURLINFO_DATA_OUT, k->upload_fromhere, + (size_t)bytes_written); + + k->writebytecount += bytes_written; + Curl_pgrsSetUploadCounter(data, k->writebytecount); + + if((!k->upload_chunky || k->forbidchunk) && + (k->writebytecount == data->state.infilesize)) { + /* we have sent all data we were supposed to */ + k->upload_done = TRUE; + infof(data, "We are completely uploaded and fine\n"); + } + + if(k->upload_present != bytes_written) { + /* we only wrote a part of the buffer (if anything), deal with it! */ + + /* store the amount of bytes left in the buffer to write */ + k->upload_present -= bytes_written; + + /* advance the pointer where to find the buffer when the next send + is to happen */ + k->upload_fromhere += bytes_written; + } + else { + /* we've uploaded that buffer now */ + result = Curl_get_upload_buffer(data); + if(result) + return result; + k->upload_fromhere = data->state.ulbuf; + k->upload_present = 0; /* no more bytes left */ + + if(k->upload_done) { + result = done_sending(conn, k); + if(result) + return result; + } + } + + + } WHILE_FALSE; /* just to break out from! */ + + return CURLE_OK; +} + +/* + * Curl_readwrite() is the low-level function to be called when data is to + * be read and written to/from the connection. + * + * return '*comeback' TRUE if we didn't properly drain the socket so this + * function should get called again without select() or similar in between! + */ +CURLcode Curl_readwrite(struct connectdata *conn, + struct Curl_easy *data, + bool *done, + bool *comeback) +{ + struct SingleRequest *k = &data->req; + CURLcode result; + int didwhat = 0; + + curl_socket_t fd_read; + curl_socket_t fd_write; + int select_res = conn->cselect_bits; + + conn->cselect_bits = 0; + + /* only use the proper socket if the *_HOLD bit is not set simultaneously as + then we are in rate limiting state in that transfer direction */ + + if((k->keepon & KEEP_RECVBITS) == KEEP_RECV) + fd_read = conn->sockfd; + else + fd_read = CURL_SOCKET_BAD; + + if((k->keepon & KEEP_SENDBITS) == KEEP_SEND) + fd_write = conn->writesockfd; + else + fd_write = CURL_SOCKET_BAD; + + if(conn->data->state.drain) { + select_res |= CURL_CSELECT_IN; + DEBUGF(infof(data, "Curl_readwrite: forcibly told to drain data\n")); + } + + if(!select_res) /* Call for select()/poll() only, if read/write/error + status is not known. */ + select_res = Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write, 0); + + if(select_res == CURL_CSELECT_ERR) { + failf(data, "select/poll returned error"); + return CURLE_SEND_ERROR; + } + + /* We go ahead and do a read if we have a readable socket or if + the stream was rewound (in which case we have data in a + buffer) */ + if((k->keepon & KEEP_RECV) && + ((select_res & CURL_CSELECT_IN) || conn->bits.stream_was_rewound)) { + + result = readwrite_data(data, conn, k, &didwhat, done, comeback); + if(result || *done) + return result; + } + + /* If we still have writing to do, we check if we have a writable socket. */ + if((k->keepon & KEEP_SEND) && (select_res & CURL_CSELECT_OUT)) { + /* write */ + + result = readwrite_upload(data, conn, &didwhat); + if(result) + return result; + } + + k->now = Curl_now(); + if(didwhat) { + ; + } + else { + /* no read no write, this is a timeout? */ + if(k->exp100 == EXP100_AWAITING_CONTINUE) { + /* This should allow some time for the header to arrive, but only a + very short time as otherwise it'll be too much wasted time too + often. */ + + /* Quoting RFC2616, section "8.2.3 Use of the 100 (Continue) Status": + + Therefore, when a client sends this header field to an origin server + (possibly via a proxy) from which it has never seen a 100 (Continue) + status, the client SHOULD NOT wait for an indefinite period before + sending the request body. + + */ + + timediff_t ms = Curl_timediff(k->now, k->start100); + if(ms >= data->set.expect_100_timeout) { + /* we've waited long enough, continue anyway */ + k->exp100 = EXP100_SEND_DATA; + k->keepon |= KEEP_SEND; + Curl_expire_done(data, EXPIRE_100_TIMEOUT); + infof(data, "Done waiting for 100-continue\n"); + } + } + } + + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + else + result = Curl_speedcheck(data, k->now); + if(result) + return result; + + if(k->keepon) { + if(0 > Curl_timeleft(data, &k->now, FALSE)) { + if(k->size != -1) { + failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T + " milliseconds with %" CURL_FORMAT_CURL_OFF_T " out of %" + CURL_FORMAT_CURL_OFF_T " bytes received", + Curl_timediff(k->now, data->progress.t_startsingle), + k->bytecount, k->size); + } + else { + failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T + " milliseconds with %" CURL_FORMAT_CURL_OFF_T " bytes received", + Curl_timediff(k->now, data->progress.t_startsingle), + k->bytecount); + } + return CURLE_OPERATION_TIMEDOUT; + } + } + else { + /* + * The transfer has been performed. Just make some general checks before + * returning. + */ + + if(!(data->set.opt_no_body) && (k->size != -1) && + (k->bytecount != k->size) && +#ifdef CURL_DO_LINEEND_CONV + /* Most FTP servers don't adjust their file SIZE response for CRLFs, + so we'll check to see if the discrepancy can be explained + by the number of CRLFs we've changed to LFs. + */ + (k->bytecount != (k->size + data->state.crlf_conversions)) && +#endif /* CURL_DO_LINEEND_CONV */ + !k->newurl) { + failf(data, "transfer closed with %" CURL_FORMAT_CURL_OFF_T + " bytes remaining to read", k->size - k->bytecount); + return CURLE_PARTIAL_FILE; + } + if(!(data->set.opt_no_body) && k->chunk && + (conn->chunk.state != CHUNK_STOP)) { + /* + * In chunked mode, return an error if the connection is closed prior to + * the empty (terminating) chunk is read. + * + * The condition above used to check for + * conn->proto.http->chunk.datasize != 0 which is true after reading + * *any* chunk, not just the empty chunk. + * + */ + failf(data, "transfer closed with outstanding read data remaining"); + return CURLE_PARTIAL_FILE; + } + if(Curl_pgrsUpdate(conn)) + return CURLE_ABORTED_BY_CALLBACK; + } + + /* Now update the "done" boolean we return */ + *done = (0 == (k->keepon&(KEEP_RECV|KEEP_SEND| + KEEP_RECV_PAUSE|KEEP_SEND_PAUSE))) ? TRUE : FALSE; + + return CURLE_OK; +} + +/* + * Curl_single_getsock() gets called by the multi interface code when the app + * has requested to get the sockets for the current connection. This function + * will then be called once for every connection that the multi interface + * keeps track of. This function will only be called for connections that are + * in the proper state to have this information available. + */ +int Curl_single_getsock(const struct connectdata *conn, + curl_socket_t *sock, /* points to numsocks number + of sockets */ + int numsocks) +{ + const struct Curl_easy *data = conn->data; + int bitmap = GETSOCK_BLANK; + unsigned sockindex = 0; + + if(conn->handler->perform_getsock) + return conn->handler->perform_getsock(conn, sock, numsocks); + + if(numsocks < 2) + /* simple check but we might need two slots */ + return GETSOCK_BLANK; + + /* don't include HOLD and PAUSE connections */ + if((data->req.keepon & KEEP_RECVBITS) == KEEP_RECV) { + + DEBUGASSERT(conn->sockfd != CURL_SOCKET_BAD); + + bitmap |= GETSOCK_READSOCK(sockindex); + sock[sockindex] = conn->sockfd; + } + + /* don't include HOLD and PAUSE connections */ + if((data->req.keepon & KEEP_SENDBITS) == KEEP_SEND) { + + if((conn->sockfd != conn->writesockfd) || + bitmap == GETSOCK_BLANK) { + /* only if they are not the same socket and we have a readable + one, we increase index */ + if(bitmap != GETSOCK_BLANK) + sockindex++; /* increase index if we need two entries */ + + DEBUGASSERT(conn->writesockfd != CURL_SOCKET_BAD); + + sock[sockindex] = conn->writesockfd; + } + + bitmap |= GETSOCK_WRITESOCK(sockindex); + } + + return bitmap; +} + +/* Curl_init_CONNECT() gets called each time the handle switches to CONNECT + which means this gets called once for each subsequent redirect etc */ +void Curl_init_CONNECT(struct Curl_easy *data) +{ + data->state.fread_func = data->set.fread_func_set; + data->state.in = data->set.in_set; +} + +/* + * Curl_pretransfer() is called immediately before a transfer starts, and only + * once for one transfer no matter if it has redirects or do multi-pass + * authentication etc. + */ +CURLcode Curl_pretransfer(struct Curl_easy *data) +{ + CURLcode result; + + if(!data->change.url && !data->set.uh) { + /* we can't do anything without URL */ + failf(data, "No URL set!"); + return CURLE_URL_MALFORMAT; + } + + /* since the URL may have been redirected in a previous use of this handle */ + if(data->change.url_alloc) { + /* the already set URL is allocated, free it first! */ + Curl_safefree(data->change.url); + data->change.url_alloc = FALSE; + } + + if(!data->change.url && data->set.uh) { + CURLUcode uc; + uc = curl_url_get(data->set.uh, + CURLUPART_URL, &data->set.str[STRING_SET_URL], 0); + if(uc) { + failf(data, "No URL set!"); + return CURLE_URL_MALFORMAT; + } + } + + data->change.url = data->set.str[STRING_SET_URL]; + + /* Init the SSL session ID cache here. We do it here since we want to do it + after the *_setopt() calls (that could specify the size of the cache) but + before any transfer takes place. */ + result = Curl_ssl_initsessions(data, data->set.general_ssl.max_ssl_sessions); + if(result) + return result; + + data->state.wildcardmatch = data->set.wildcard_enabled; + data->set.followlocation = 0; /* reset the location-follow counter */ + data->state.this_is_a_follow = FALSE; /* reset this */ + data->state.errorbuf = FALSE; /* no error has occurred */ + data->state.httpversion = 0; /* don't assume any particular server version */ + + data->state.authproblem = FALSE; + data->state.authhost.want = data->set.httpauth; + data->state.authproxy.want = data->set.proxyauth; + Curl_safefree(data->info.wouldredirect); + data->info.wouldredirect = NULL; + + if(data->set.httpreq == HTTPREQ_PUT) + data->state.infilesize = data->set.filesize; + else if((data->set.httpreq != HTTPREQ_GET) && + (data->set.httpreq != HTTPREQ_HEAD)) { + data->state.infilesize = data->set.postfieldsize; + if(data->set.postfields && (data->state.infilesize == -1)) + data->state.infilesize = (curl_off_t)strlen(data->set.postfields); + } + else + data->state.infilesize = 0; + + /* If there is a list of cookie files to read, do it now! */ + if(data->change.cookielist) + Curl_cookie_loadfiles(data); + + /* If there is a list of host pairs to deal with */ + if(data->change.resolve) + result = Curl_loadhostpairs(data); + + if(!result) { + /* Allow data->set.use_port to set which port to use. This needs to be + * disabled for example when we follow Location: headers to URLs using + * different ports! */ + data->state.allow_port = TRUE; + +#if defined(HAVE_SIGNAL) && defined(SIGPIPE) && !defined(HAVE_MSG_NOSIGNAL) + /************************************************************* + * Tell signal handler to ignore SIGPIPE + *************************************************************/ + if(!data->set.no_signal) + data->state.prev_signal = signal(SIGPIPE, SIG_IGN); +#endif + + Curl_initinfo(data); /* reset session-specific information "variables" */ + Curl_pgrsResetTransferSizes(data); + Curl_pgrsStartNow(data); + + /* In case the handle is re-used and an authentication method was picked + in the session we need to make sure we only use the one(s) we now + consider to be fine */ + data->state.authhost.picked &= data->state.authhost.want; + data->state.authproxy.picked &= data->state.authproxy.want; + +#ifndef CURL_DISABLE_FTP + if(data->state.wildcardmatch) { + struct WildcardData *wc = &data->wildcard; + if(wc->state < CURLWC_INIT) { + result = Curl_wildcard_init(wc); /* init wildcard structures */ + if(result) + return CURLE_OUT_OF_MEMORY; + } + } +#endif + } + + return result; +} + +/* + * Curl_posttransfer() is called immediately after a transfer ends + */ +CURLcode Curl_posttransfer(struct Curl_easy *data) +{ +#if defined(HAVE_SIGNAL) && defined(SIGPIPE) && !defined(HAVE_MSG_NOSIGNAL) + /* restore the signal handler for SIGPIPE before we get back */ + if(!data->set.no_signal) + signal(SIGPIPE, data->state.prev_signal); +#else + (void)data; /* unused parameter */ +#endif + + return CURLE_OK; +} + +/* + * Curl_follow() handles the URL redirect magic. Pass in the 'newurl' string + * as given by the remote server and set up the new URL to request. + * + * This function DOES NOT FREE the given url. + */ +CURLcode Curl_follow(struct Curl_easy *data, + char *newurl, /* the Location: string */ + followtype type) /* see transfer.h */ +{ +#ifdef CURL_DISABLE_HTTP + (void)data; + (void)newurl; + (void)type; + /* Location: following will not happen when HTTP is disabled */ + return CURLE_TOO_MANY_REDIRECTS; +#else + + /* Location: redirect */ + bool disallowport = FALSE; + bool reachedmax = FALSE; + CURLUcode uc; + + if(type == FOLLOW_REDIR) { + if((data->set.maxredirs != -1) && + (data->set.followlocation >= data->set.maxredirs)) { + reachedmax = TRUE; + type = FOLLOW_FAKE; /* switch to fake to store the would-be-redirected + to URL */ + } + else { + /* mark the next request as a followed location: */ + data->state.this_is_a_follow = TRUE; + + data->set.followlocation++; /* count location-followers */ + + if(data->set.http_auto_referer) { + /* We are asked to automatically set the previous URL as the referer + when we get the next URL. We pick the ->url field, which may or may + not be 100% correct */ + + if(data->change.referer_alloc) { + Curl_safefree(data->change.referer); + data->change.referer_alloc = FALSE; + } + + data->change.referer = strdup(data->change.url); + if(!data->change.referer) + return CURLE_OUT_OF_MEMORY; + data->change.referer_alloc = TRUE; /* yes, free this later */ + } + } + } + + if(Curl_is_absolute_url(newurl, NULL, MAX_SCHEME_LEN)) + /* This is an absolute URL, don't allow the custom port number */ + disallowport = TRUE; + + DEBUGASSERT(data->state.uh); + uc = curl_url_set(data->state.uh, CURLUPART_URL, newurl, + (type == FOLLOW_FAKE) ? CURLU_NON_SUPPORT_SCHEME : 0); + if(uc) { + if(type != FOLLOW_FAKE) + return Curl_uc_to_curlcode(uc); + + /* the URL could not be parsed for some reason, but since this is FAKE + mode, just duplicate the field as-is */ + newurl = strdup(newurl); + if(!newurl) + return CURLE_OUT_OF_MEMORY; + } + else { + + uc = curl_url_get(data->state.uh, CURLUPART_URL, &newurl, 0); + if(uc) + return Curl_uc_to_curlcode(uc); + } + + if(type == FOLLOW_FAKE) { + /* we're only figuring out the new url if we would've followed locations + but now we're done so we can get out! */ + data->info.wouldredirect = newurl; + + if(reachedmax) { + failf(data, "Maximum (%ld) redirects followed", data->set.maxredirs); + return CURLE_TOO_MANY_REDIRECTS; + } + return CURLE_OK; + } + + if(disallowport) + data->state.allow_port = FALSE; + + if(data->change.url_alloc) + Curl_safefree(data->change.url); + + data->change.url = newurl; + data->change.url_alloc = TRUE; + + infof(data, "Issue another request to this URL: '%s'\n", data->change.url); + + /* + * We get here when the HTTP code is 300-399 (and 401). We need to perform + * differently based on exactly what return code there was. + * + * News from 7.10.6: we can also get here on a 401 or 407, in case we act on + * a HTTP (proxy-) authentication scheme other than Basic. + */ + switch(data->info.httpcode) { + /* 401 - Act on a WWW-Authenticate, we keep on moving and do the + Authorization: XXXX header in the HTTP request code snippet */ + /* 407 - Act on a Proxy-Authenticate, we keep on moving and do the + Proxy-Authorization: XXXX header in the HTTP request code snippet */ + /* 300 - Multiple Choices */ + /* 306 - Not used */ + /* 307 - Temporary Redirect */ + default: /* for all above (and the unknown ones) */ + /* Some codes are explicitly mentioned since I've checked RFC2616 and they + * seem to be OK to POST to. + */ + break; + case 301: /* Moved Permanently */ + /* (quote from RFC7231, section 6.4.2) + * + * Note: For historical reasons, a user agent MAY change the request + * method from POST to GET for the subsequent request. If this + * behavior is undesired, the 307 (Temporary Redirect) status code + * can be used instead. + * + * ---- + * + * Many webservers expect this, so these servers often answers to a POST + * request with an error page. To be sure that libcurl gets the page that + * most user agents would get, libcurl has to force GET. + * + * This behaviour is forbidden by RFC1945 and the obsolete RFC2616, and + * can be overridden with CURLOPT_POSTREDIR. + */ + if((data->set.httpreq == HTTPREQ_POST + || data->set.httpreq == HTTPREQ_POST_FORM + || data->set.httpreq == HTTPREQ_POST_MIME) + && !(data->set.keep_post & CURL_REDIR_POST_301)) { + infof(data, "Switch from POST to GET\n"); + data->set.httpreq = HTTPREQ_GET; + } + break; + case 302: /* Found */ + /* (quote from RFC7231, section 6.4.3) + * + * Note: For historical reasons, a user agent MAY change the request + * method from POST to GET for the subsequent request. If this + * behavior is undesired, the 307 (Temporary Redirect) status code + * can be used instead. + * + * ---- + * + * Many webservers expect this, so these servers often answers to a POST + * request with an error page. To be sure that libcurl gets the page that + * most user agents would get, libcurl has to force GET. + * + * This behaviour is forbidden by RFC1945 and the obsolete RFC2616, and + * can be overridden with CURLOPT_POSTREDIR. + */ + if((data->set.httpreq == HTTPREQ_POST + || data->set.httpreq == HTTPREQ_POST_FORM + || data->set.httpreq == HTTPREQ_POST_MIME) + && !(data->set.keep_post & CURL_REDIR_POST_302)) { + infof(data, "Switch from POST to GET\n"); + data->set.httpreq = HTTPREQ_GET; + } + break; + + case 303: /* See Other */ + /* Disable both types of POSTs, unless the user explicitly + asks for POST after POST */ + if(data->set.httpreq != HTTPREQ_GET + && !(data->set.keep_post & CURL_REDIR_POST_303)) { + data->set.httpreq = HTTPREQ_GET; /* enforce GET request */ + infof(data, "Disables POST, goes with %s\n", + data->set.opt_no_body?"HEAD":"GET"); + } + break; + case 304: /* Not Modified */ + /* 304 means we did a conditional request and it was "Not modified". + * We shouldn't get any Location: header in this response! + */ + break; + case 305: /* Use Proxy */ + /* (quote from RFC2616, section 10.3.6): + * "The requested resource MUST be accessed through the proxy given + * by the Location field. The Location field gives the URI of the + * proxy. The recipient is expected to repeat this single request + * via the proxy. 305 responses MUST only be generated by origin + * servers." + */ + break; + } + Curl_pgrsTime(data, TIMER_REDIRECT); + Curl_pgrsResetTransferSizes(data); + + return CURLE_OK; +#endif /* CURL_DISABLE_HTTP */ +} + +/* Returns CURLE_OK *and* sets '*url' if a request retry is wanted. + + NOTE: that the *url is malloc()ed. */ +CURLcode Curl_retry_request(struct connectdata *conn, + char **url) +{ + struct Curl_easy *data = conn->data; + bool retry = FALSE; + *url = NULL; + + /* if we're talking upload, we can't do the checks below, unless the protocol + is HTTP as when uploading over HTTP we will still get a response */ + if(data->set.upload && + !(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP))) + return CURLE_OK; + + if((data->req.bytecount + data->req.headerbytecount == 0) && + conn->bits.reuse && + (!data->set.opt_no_body + || (conn->handler->protocol & PROTO_FAMILY_HTTP)) && + (data->set.rtspreq != RTSPREQ_RECEIVE)) + /* We got no data, we attempted to re-use a connection. For HTTP this + can be a retry so we try again regardless if we expected a body. + For other protocols we only try again only if we expected a body. + + This might happen if the connection was left alive when we were + done using it before, but that was closed when we wanted to read from + it again. Bad luck. Retry the same request on a fresh connect! */ + retry = TRUE; + else if(data->state.refused_stream && + (data->req.bytecount + data->req.headerbytecount == 0) ) { + /* This was sent on a refused stream, safe to rerun. A refused stream + error can typically only happen on HTTP/2 level if the stream is safe + to issue again, but the nghttp2 API can deliver the message to other + streams as well, which is why this adds the check the data counters + too. */ + infof(conn->data, "REFUSED_STREAM, retrying a fresh connect\n"); + data->state.refused_stream = FALSE; /* clear again */ + retry = TRUE; + } + if(retry) { + infof(conn->data, "Connection died, retrying a fresh connect\n"); + *url = strdup(conn->data->change.url); + if(!*url) + return CURLE_OUT_OF_MEMORY; + + connclose(conn, "retry"); /* close this connection */ + conn->bits.retry = TRUE; /* mark this as a connection we're about + to retry. Marking it this way should + prevent i.e HTTP transfers to return + error just because nothing has been + transferred! */ + + + if(conn->handler->protocol&PROTO_FAMILY_HTTP) { + if(data->req.writebytecount) { + CURLcode result = Curl_readrewind(conn); + if(result) { + Curl_safefree(*url); + return result; + } + } + } + } + return CURLE_OK; +} + +/* + * Curl_setup_transfer() is called to setup some basic properties for the + * upcoming transfer. + */ +void +Curl_setup_transfer( + struct Curl_easy *data, /* transfer */ + int sockindex, /* socket index to read from or -1 */ + curl_off_t size, /* -1 if unknown at this point */ + bool getheader, /* TRUE if header parsing is wanted */ + int writesockindex /* socket index to write to, it may very well be + the same we read from. -1 disables */ + ) +{ + struct SingleRequest *k = &data->req; + struct connectdata *conn = data->conn; + DEBUGASSERT(conn != NULL); + DEBUGASSERT((sockindex <= 1) && (sockindex >= -1)); + + if(conn->bits.multiplex || conn->httpversion == 20) { + /* when multiplexing, the read/write sockets need to be the same! */ + conn->sockfd = sockindex == -1 ? + ((writesockindex == -1 ? CURL_SOCKET_BAD : conn->sock[writesockindex])) : + conn->sock[sockindex]; + conn->writesockfd = conn->sockfd; + } + else { + conn->sockfd = sockindex == -1 ? + CURL_SOCKET_BAD : conn->sock[sockindex]; + conn->writesockfd = writesockindex == -1 ? + CURL_SOCKET_BAD:conn->sock[writesockindex]; + } + k->getheader = getheader; + + k->size = size; + + /* The code sequence below is placed in this function just because all + necessary input is not always known in do_complete() as this function may + be called after that */ + + if(!k->getheader) { + k->header = FALSE; + if(size > 0) + Curl_pgrsSetDownloadSize(data, size); + } + /* we want header and/or body, if neither then don't do this! */ + if(k->getheader || !data->set.opt_no_body) { + + if(sockindex != -1) + k->keepon |= KEEP_RECV; + + if(writesockindex != -1) { + struct HTTP *http = data->req.protop; + /* HTTP 1.1 magic: + + Even if we require a 100-return code before uploading data, we might + need to write data before that since the REQUEST may not have been + finished sent off just yet. + + Thus, we must check if the request has been sent before we set the + state info where we wait for the 100-return code + */ + if((data->state.expect100header) && + (conn->handler->protocol&PROTO_FAMILY_HTTP) && + (http->sending == HTTPSEND_BODY)) { + /* wait with write until we either got 100-continue or a timeout */ + k->exp100 = EXP100_AWAITING_CONTINUE; + k->start100 = Curl_now(); + + /* Set a timeout for the multi interface. Add the inaccuracy margin so + that we don't fire slightly too early and get denied to run. */ + Curl_expire(data, data->set.expect_100_timeout, EXPIRE_100_TIMEOUT); + } + else { + if(data->state.expect100header) + /* when we've sent off the rest of the headers, we must await a + 100-continue but first finish sending the request */ + k->exp100 = EXP100_SENDING_REQUEST; + + /* enable the write bit when we're not waiting for continue */ + k->keepon |= KEEP_SEND; + } + } /* if(writesockindex != -1) */ + } /* if(k->getheader || !data->set.opt_no_body) */ + +} diff --git a/dependencies/cmcurl/lib/transfer.h b/dependencies/cmcurl/lib/transfer.h new file mode 100644 index 0000000..a9bff63 --- /dev/null +++ b/dependencies/cmcurl/lib/transfer.h @@ -0,0 +1,71 @@ +#ifndef HEADER_CURL_TRANSFER_H +#define HEADER_CURL_TRANSFER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#define Curl_headersep(x) ((((x)==':') || ((x)==';'))) +char *Curl_checkheaders(const struct connectdata *conn, + const char *thisheader); + +void Curl_init_CONNECT(struct Curl_easy *data); + +CURLcode Curl_pretransfer(struct Curl_easy *data); +CURLcode Curl_second_connect(struct connectdata *conn); +CURLcode Curl_posttransfer(struct Curl_easy *data); + +typedef enum { + FOLLOW_NONE, /* not used within the function, just a placeholder to + allow initing to this */ + FOLLOW_FAKE, /* only records stuff, not actually following */ + FOLLOW_RETRY, /* set if this is a request retry as opposed to a real + redirect following */ + FOLLOW_REDIR, /* a full true redirect */ + FOLLOW_LAST /* never used */ +} followtype; + +CURLcode Curl_follow(struct Curl_easy *data, char *newurl, + followtype type); +CURLcode Curl_readwrite(struct connectdata *conn, + struct Curl_easy *data, bool *done, + bool *comeback); +int Curl_single_getsock(const struct connectdata *conn, + curl_socket_t *socks, + int numsocks); +CURLcode Curl_readrewind(struct connectdata *conn); +CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes, + size_t *nreadp); +CURLcode Curl_retry_request(struct connectdata *conn, char **url); +bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc); +CURLcode Curl_get_upload_buffer(struct Curl_easy *data); + +/* This sets up a forthcoming transfer */ +void +Curl_setup_transfer (struct Curl_easy *data, + int sockindex, /* socket index to read from or -1 */ + curl_off_t size, /* -1 if unknown at this point */ + bool getheader, /* TRUE if header parsing is wanted */ + int writesockindex /* socket index to write to. May be + the same we read from. -1 + disables */ + ); + +#endif /* HEADER_CURL_TRANSFER_H */ diff --git a/dependencies/cmcurl/lib/url.c b/dependencies/cmcurl/lib/url.c new file mode 100644 index 0000000..c441ae7 --- /dev/null +++ b/dependencies/cmcurl/lib/url.c @@ -0,0 +1,4180 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#ifdef __VMS +#include +#include +#endif + +#ifdef HAVE_SYS_UN_H +#include +#endif + +#ifndef HAVE_SOCKET +#error "We can't compile without socket() support!" +#endif + +#include + +#ifdef USE_LIBIDN2 +#include + +#elif defined(USE_WIN32_IDN) +/* prototype for curl_win32_idn_to_ascii() */ +bool curl_win32_idn_to_ascii(const char *in, char **out); +#endif /* USE_LIBIDN2 */ + +#include "urldata.h" +#include "netrc.h" + +#include "formdata.h" +#include "mime.h" +#include "vtls/vtls.h" +#include "hostip.h" +#include "transfer.h" +#include "sendf.h" +#include "progress.h" +#include "cookie.h" +#include "strcase.h" +#include "strerror.h" +#include "escape.h" +#include "strtok.h" +#include "share.h" +#include "content_encoding.h" +#include "http_digest.h" +#include "http_negotiate.h" +#include "select.h" +#include "multiif.h" +#include "easyif.h" +#include "speedcheck.h" +#include "warnless.h" +#include "non-ascii.h" +#include "inet_pton.h" +#include "getinfo.h" +#include "urlapi-int.h" + +/* And now for the protocols */ +#include "ftp.h" +#include "dict.h" +#include "telnet.h" +#include "tftp.h" +#include "http.h" +#include "http2.h" +#include "file.h" +#include "curl_ldap.h" +#include "ssh.h" +#include "imap.h" +#include "url.h" +#include "connect.h" +#include "inet_ntop.h" +#include "http_ntlm.h" +#include "socks.h" +#include "curl_rtmp.h" +#include "gopher.h" +#include "http_proxy.h" +#include "conncache.h" +#include "multihandle.h" +#include "dotdot.h" +#include "strdup.h" +#include "setopt.h" +#include "altsvc.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +static void conn_free(struct connectdata *conn); +static void free_idnconverted_hostname(struct hostname *host); +static unsigned int get_protocol_family(unsigned int protocol); + +/* Some parts of the code (e.g. chunked encoding) assume this buffer has at + * more than just a few bytes to play with. Don't let it become too small or + * bad things will happen. + */ +#if READBUFFER_SIZE < READBUFFER_MIN +# error READBUFFER_SIZE is too small +#endif + + +/* + * Protocol table. + */ + +static const struct Curl_handler * const protocols[] = { + +#ifndef CURL_DISABLE_HTTP + &Curl_handler_http, +#endif + +#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP) + &Curl_handler_https, +#endif + +#ifndef CURL_DISABLE_FTP + &Curl_handler_ftp, +#endif + +#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP) + &Curl_handler_ftps, +#endif + +#ifndef CURL_DISABLE_TELNET + &Curl_handler_telnet, +#endif + +#ifndef CURL_DISABLE_DICT + &Curl_handler_dict, +#endif + +#ifndef CURL_DISABLE_LDAP + &Curl_handler_ldap, +#if !defined(CURL_DISABLE_LDAPS) && \ + ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ + (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) + &Curl_handler_ldaps, +#endif +#endif + +#ifndef CURL_DISABLE_FILE + &Curl_handler_file, +#endif + +#ifndef CURL_DISABLE_TFTP + &Curl_handler_tftp, +#endif + +#if defined(USE_SSH) + &Curl_handler_scp, +#endif + +#if defined(USE_SSH) + &Curl_handler_sftp, +#endif + +#ifndef CURL_DISABLE_IMAP + &Curl_handler_imap, +#ifdef USE_SSL + &Curl_handler_imaps, +#endif +#endif + +#ifndef CURL_DISABLE_POP3 + &Curl_handler_pop3, +#ifdef USE_SSL + &Curl_handler_pop3s, +#endif +#endif + +#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \ + (CURL_SIZEOF_CURL_OFF_T > 4) && \ + (!defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)) + &Curl_handler_smb, +#ifdef USE_SSL + &Curl_handler_smbs, +#endif +#endif + +#ifndef CURL_DISABLE_SMTP + &Curl_handler_smtp, +#ifdef USE_SSL + &Curl_handler_smtps, +#endif +#endif + +#ifndef CURL_DISABLE_RTSP + &Curl_handler_rtsp, +#endif + +#ifndef CURL_DISABLE_GOPHER + &Curl_handler_gopher, +#endif + +#ifdef USE_LIBRTMP + &Curl_handler_rtmp, + &Curl_handler_rtmpt, + &Curl_handler_rtmpe, + &Curl_handler_rtmpte, + &Curl_handler_rtmps, + &Curl_handler_rtmpts, +#endif + + (struct Curl_handler *) NULL +}; + +/* + * Dummy handler for undefined protocol schemes. + */ + +static const struct Curl_handler Curl_handler_dummy = { + "", /* scheme */ + ZERO_NULL, /* setup_connection */ + ZERO_NULL, /* do_it */ + ZERO_NULL, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + 0, /* defport */ + 0, /* protocol */ + PROTOPT_NONE /* flags */ +}; + +void Curl_freeset(struct Curl_easy *data) +{ + /* Free all dynamic strings stored in the data->set substructure. */ + enum dupstring i; + for(i = (enum dupstring)0; i < STRING_LAST; i++) { + Curl_safefree(data->set.str[i]); + } + + if(data->change.referer_alloc) { + Curl_safefree(data->change.referer); + data->change.referer_alloc = FALSE; + } + data->change.referer = NULL; + if(data->change.url_alloc) { + Curl_safefree(data->change.url); + data->change.url_alloc = FALSE; + } + data->change.url = NULL; + + Curl_mime_cleanpart(&data->set.mimepost); +} + +/* free the URL pieces */ +static void up_free(struct Curl_easy *data) +{ + struct urlpieces *up = &data->state.up; + Curl_safefree(up->scheme); + Curl_safefree(up->hostname); + Curl_safefree(up->port); + Curl_safefree(up->user); + Curl_safefree(up->password); + Curl_safefree(up->options); + Curl_safefree(up->path); + Curl_safefree(up->query); + curl_url_cleanup(data->state.uh); + data->state.uh = NULL; +} + +/* + * This is the internal function curl_easy_cleanup() calls. This should + * cleanup and free all resources associated with this sessionhandle. + * + * NOTE: if we ever add something that attempts to write to a socket or + * similar here, we must ignore SIGPIPE first. It is currently only done + * when curl_easy_perform() is invoked. + */ + +CURLcode Curl_close(struct Curl_easy *data) +{ + struct Curl_multi *m; + + if(!data) + return CURLE_OK; + + Curl_expire_clear(data); /* shut off timers */ + + m = data->multi; + if(m) + /* This handle is still part of a multi handle, take care of this first + and detach this handle from there. */ + curl_multi_remove_handle(data->multi, data); + + if(data->multi_easy) { + /* when curl_easy_perform() is used, it creates its own multi handle to + use and this is the one */ + curl_multi_cleanup(data->multi_easy); + data->multi_easy = NULL; + } + + /* Destroy the timeout list that is held in the easy handle. It is + /normally/ done by curl_multi_remove_handle() but this is "just in + case" */ + Curl_llist_destroy(&data->state.timeoutlist, NULL); + + data->magic = 0; /* force a clear AFTER the possibly enforced removal from + the multi handle, since that function uses the magic + field! */ + + if(data->state.rangestringalloc) + free(data->state.range); + + /* freed here just in case DONE wasn't called */ + Curl_free_request_state(data); + + /* Close down all open SSL info and sessions */ + Curl_ssl_close_all(data); + Curl_safefree(data->state.first_host); + Curl_safefree(data->state.scratch); + Curl_ssl_free_certinfo(data); + + /* Cleanup possible redirect junk */ + free(data->req.newurl); + data->req.newurl = NULL; + + if(data->change.referer_alloc) { + Curl_safefree(data->change.referer); + data->change.referer_alloc = FALSE; + } + data->change.referer = NULL; + + up_free(data); + Curl_safefree(data->state.buffer); + Curl_safefree(data->state.headerbuff); + Curl_safefree(data->state.ulbuf); + Curl_flush_cookies(data, 1); +#ifdef USE_ALTSVC + Curl_altsvc_save(data->asi, data->set.str[STRING_ALTSVC]); + Curl_altsvc_cleanup(data->asi); + data->asi = NULL; +#endif +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) + Curl_http_auth_cleanup_digest(data); +#endif + Curl_safefree(data->info.contenttype); + Curl_safefree(data->info.wouldredirect); + + /* this destroys the channel and we cannot use it anymore after this */ + Curl_resolver_cleanup(data->state.resolver); + + Curl_http2_cleanup_dependencies(data); + Curl_convert_close(data); + + /* No longer a dirty share, if it exists */ + if(data->share) { + Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE); + data->share->dirty--; + Curl_share_unlock(data, CURL_LOCK_DATA_SHARE); + } + + /* destruct wildcard structures if it is needed */ + Curl_wildcard_dtor(&data->wildcard); + Curl_freeset(data); + free(data); + return CURLE_OK; +} + +/* + * Initialize the UserDefined fields within a Curl_easy. + * This may be safely called on a new or existing Curl_easy. + */ +CURLcode Curl_init_userdefined(struct Curl_easy *data) +{ + struct UserDefined *set = &data->set; + CURLcode result = CURLE_OK; + + set->out = stdout; /* default output to stdout */ + set->in_set = stdin; /* default input from stdin */ + set->err = stderr; /* default stderr to stderr */ + + /* use fwrite as default function to store output */ + set->fwrite_func = (curl_write_callback)fwrite; + + /* use fread as default function to read input */ + set->fread_func_set = (curl_read_callback)fread; + set->is_fread_set = 0; + set->is_fwrite_set = 0; + + set->seek_func = ZERO_NULL; + set->seek_client = ZERO_NULL; + + /* conversion callbacks for non-ASCII hosts */ + set->convfromnetwork = ZERO_NULL; + set->convtonetwork = ZERO_NULL; + set->convfromutf8 = ZERO_NULL; + + set->filesize = -1; /* we don't know the size */ + set->postfieldsize = -1; /* unknown size */ + set->maxredirs = -1; /* allow any amount by default */ + + set->httpreq = HTTPREQ_GET; /* Default HTTP request */ + set->rtspreq = RTSPREQ_OPTIONS; /* Default RTSP request */ +#ifndef CURL_DISABLE_FILE + set->ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */ + set->ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */ + set->ftp_use_pret = FALSE; /* mainly useful for drftpd servers */ + set->ftp_filemethod = FTPFILE_MULTICWD; +#endif + set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */ + + /* Set the default size of the SSL session ID cache */ + set->general_ssl.max_ssl_sessions = 5; + + set->proxyport = 0; + set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */ + set->httpauth = CURLAUTH_BASIC; /* defaults to basic */ + set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */ + + /* SOCKS5 proxy auth defaults to username/password + GSS-API */ + set->socks5auth = CURLAUTH_BASIC | CURLAUTH_GSSAPI; + + /* make libcurl quiet by default: */ + set->hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */ + + Curl_mime_initpart(&set->mimepost, data); + + /* + * libcurl 7.10 introduced SSL verification *by default*! This needs to be + * switched off unless wanted. + */ + set->ssl.primary.verifypeer = TRUE; + set->ssl.primary.verifyhost = TRUE; +#ifdef USE_TLS_SRP + set->ssl.authtype = CURL_TLSAUTH_NONE; +#endif + set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth + type */ + set->ssl.primary.sessionid = TRUE; /* session ID caching enabled by + default */ + set->proxy_ssl = set->ssl; + + set->new_file_perms = 0644; /* Default permissions */ + set->new_directory_perms = 0755; /* Default permissions */ + + /* for the *protocols fields we don't use the CURLPROTO_ALL convenience + define since we internally only use the lower 16 bits for the passed + in bitmask to not conflict with the private bits */ + set->allowed_protocols = CURLPROTO_ALL; + set->redir_protocols = CURLPROTO_ALL & /* All except FILE, SCP and SMB */ + ~(CURLPROTO_FILE | CURLPROTO_SCP | CURLPROTO_SMB | + CURLPROTO_SMBS); + +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + /* + * disallow unprotected protection negotiation NEC reference implementation + * seem not to follow rfc1961 section 4.3/4.4 + */ + set->socks5_gssapi_nec = FALSE; +#endif + + /* Set the default CA cert bundle/path detected/specified at build time. + * + * If Schannel is the selected SSL backend then these locations are + * ignored. We allow setting CA location for schannel only when explicitly + * specified by the user via CURLOPT_CAINFO / --cacert. + */ + if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) { +#if defined(CURL_CA_BUNDLE) + result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE); + if(result) + return result; + + result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_PROXY], + CURL_CA_BUNDLE); + if(result) + return result; +#endif +#if defined(CURL_CA_PATH) + result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH); + if(result) + return result; + + result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_PROXY], CURL_CA_PATH); + if(result) + return result; +#endif + } + + set->wildcard_enabled = FALSE; + set->chunk_bgn = ZERO_NULL; + set->chunk_end = ZERO_NULL; + set->tcp_keepalive = FALSE; + set->tcp_keepintvl = 60; + set->tcp_keepidle = 60; + set->tcp_fastopen = FALSE; + set->tcp_nodelay = TRUE; + set->ssl_enable_npn = TRUE; + set->ssl_enable_alpn = TRUE; + set->expect_100_timeout = 1000L; /* Wait for a second by default. */ + set->sep_headers = TRUE; /* separated header lists by default */ + set->buffer_size = READBUFFER_SIZE; + set->upload_buffer_size = UPLOADBUFFER_DEFAULT; + set->happy_eyeballs_timeout = CURL_HET_DEFAULT; + set->fnmatch = ZERO_NULL; + set->upkeep_interval_ms = CURL_UPKEEP_INTERVAL_DEFAULT; + set->maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */ + set->maxage_conn = 118; + set->http09_allowed = TRUE; + set->httpversion = +#ifdef USE_NGHTTP2 + CURL_HTTP_VERSION_2TLS +#else + CURL_HTTP_VERSION_1_1 +#endif + ; + Curl_http2_init_userset(set); + return result; +} + +/** + * Curl_open() + * + * @param curl is a pointer to a sessionhandle pointer that gets set by this + * function. + * @return CURLcode + */ + +CURLcode Curl_open(struct Curl_easy **curl) +{ + CURLcode result; + struct Curl_easy *data; + + /* Very simple start-up: alloc the struct, init it with zeroes and return */ + data = calloc(1, sizeof(struct Curl_easy)); + if(!data) { + /* this is a very serious error */ + DEBUGF(fprintf(stderr, "Error: calloc of Curl_easy failed\n")); + return CURLE_OUT_OF_MEMORY; + } + + data->magic = CURLEASY_MAGIC_NUMBER; + + result = Curl_resolver_init(data, &data->state.resolver); + if(result) { + DEBUGF(fprintf(stderr, "Error: resolver_init failed\n")); + free(data); + return result; + } + + /* We do some initial setup here, all those fields that can't be just 0 */ + + data->state.buffer = malloc(READBUFFER_SIZE + 1); + if(!data->state.buffer) { + DEBUGF(fprintf(stderr, "Error: malloc of buffer failed\n")); + result = CURLE_OUT_OF_MEMORY; + } + else { + data->state.headerbuff = malloc(HEADERSIZE); + if(!data->state.headerbuff) { + DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n")); + result = CURLE_OUT_OF_MEMORY; + } + else { + result = Curl_init_userdefined(data); + + data->state.headersize = HEADERSIZE; + Curl_convert_init(data); + Curl_initinfo(data); + + /* most recent connection is not yet defined */ + data->state.lastconnect = NULL; + + data->progress.flags |= PGRS_HIDE; + data->state.current_speed = -1; /* init to negative == impossible */ + + Curl_http2_init_state(&data->state); + } + } + + if(result) { + Curl_resolver_cleanup(data->state.resolver); + free(data->state.buffer); + free(data->state.headerbuff); + Curl_freeset(data); + free(data); + data = NULL; + } + else + *curl = data; + + return result; +} + +#ifdef USE_RECV_BEFORE_SEND_WORKAROUND +static void conn_reset_postponed_data(struct connectdata *conn, int num) +{ + struct postponed_data * const psnd = &(conn->postponed[num]); + if(psnd->buffer) { + DEBUGASSERT(psnd->allocated_size > 0); + DEBUGASSERT(psnd->recv_size <= psnd->allocated_size); + DEBUGASSERT(psnd->recv_size ? + (psnd->recv_processed < psnd->recv_size) : + (psnd->recv_processed == 0)); + DEBUGASSERT(psnd->bindsock != CURL_SOCKET_BAD); + free(psnd->buffer); + psnd->buffer = NULL; + psnd->allocated_size = 0; + psnd->recv_size = 0; + psnd->recv_processed = 0; +#ifdef DEBUGBUILD + psnd->bindsock = CURL_SOCKET_BAD; /* used only for DEBUGASSERT */ +#endif /* DEBUGBUILD */ + } + else { + DEBUGASSERT(psnd->allocated_size == 0); + DEBUGASSERT(psnd->recv_size == 0); + DEBUGASSERT(psnd->recv_processed == 0); + DEBUGASSERT(psnd->bindsock == CURL_SOCKET_BAD); + } +} + +static void conn_reset_all_postponed_data(struct connectdata *conn) +{ + conn_reset_postponed_data(conn, 0); + conn_reset_postponed_data(conn, 1); +} +#else /* ! USE_RECV_BEFORE_SEND_WORKAROUND */ +/* Use "do-nothing" macro instead of function when workaround not used */ +#define conn_reset_all_postponed_data(c) do {} WHILE_FALSE +#endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */ + + +static void conn_shutdown(struct connectdata *conn) +{ + if(!conn) + return; + + infof(conn->data, "Closing connection %ld\n", conn->connection_id); + DEBUGASSERT(conn->data); + + /* possible left-overs from the async name resolvers */ + Curl_resolver_cancel(conn); + + /* close the SSL stuff before we close any sockets since they will/may + write to the sockets */ + Curl_ssl_close(conn, FIRSTSOCKET); + Curl_ssl_close(conn, SECONDARYSOCKET); + + /* close possibly still open sockets */ + if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) + Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]); + if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET]) + Curl_closesocket(conn, conn->sock[FIRSTSOCKET]); + if(CURL_SOCKET_BAD != conn->tempsock[0]) + Curl_closesocket(conn, conn->tempsock[0]); + if(CURL_SOCKET_BAD != conn->tempsock[1]) + Curl_closesocket(conn, conn->tempsock[1]); + + /* unlink ourselves. this should be called last since other shutdown + procedures need a valid conn->data and this may clear it. */ + Curl_conncache_remove_conn(conn->data, conn, TRUE); +} + +static void conn_free(struct connectdata *conn) +{ + if(!conn) + return; + + free_idnconverted_hostname(&conn->host); + free_idnconverted_hostname(&conn->conn_to_host); + free_idnconverted_hostname(&conn->http_proxy.host); + free_idnconverted_hostname(&conn->socks_proxy.host); + + Curl_safefree(conn->user); + Curl_safefree(conn->passwd); + Curl_safefree(conn->oauth_bearer); + Curl_safefree(conn->options); + Curl_safefree(conn->http_proxy.user); + Curl_safefree(conn->socks_proxy.user); + Curl_safefree(conn->http_proxy.passwd); + Curl_safefree(conn->socks_proxy.passwd); + Curl_safefree(conn->allocptr.proxyuserpwd); + Curl_safefree(conn->allocptr.uagent); + Curl_safefree(conn->allocptr.userpwd); + Curl_safefree(conn->allocptr.accept_encoding); + Curl_safefree(conn->allocptr.te); + Curl_safefree(conn->allocptr.rangeline); + Curl_safefree(conn->allocptr.ref); + Curl_safefree(conn->allocptr.host); + Curl_safefree(conn->allocptr.cookiehost); + Curl_safefree(conn->allocptr.rtsp_transport); + Curl_safefree(conn->trailer); + Curl_safefree(conn->host.rawalloc); /* host name buffer */ + Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */ + Curl_safefree(conn->hostname_resolve); + Curl_safefree(conn->secondaryhostname); + Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */ + Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */ + Curl_safefree(conn->connect_state); + + conn_reset_all_postponed_data(conn); + Curl_llist_destroy(&conn->easyq, NULL); + Curl_safefree(conn->localdev); + Curl_free_primary_ssl_config(&conn->ssl_config); + Curl_free_primary_ssl_config(&conn->proxy_ssl_config); + +#ifdef USE_UNIX_SOCKETS + Curl_safefree(conn->unix_domain_socket); +#endif + +#ifdef USE_SSL + Curl_safefree(conn->ssl_extra); +#endif + free(conn); /* free all the connection oriented data */ +} + +/* + * Disconnects the given connection. Note the connection may not be the + * primary connection, like when freeing room in the connection cache or + * killing of a dead old connection. + * + * A connection needs an easy handle when closing down. We support this passed + * in separately since the connection to get closed here is often already + * disassociated from an easy handle. + * + * This function MUST NOT reset state in the Curl_easy struct if that + * isn't strictly bound to the life-time of *this* particular connection. + * + */ + +CURLcode Curl_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead_connection) +{ + if(!conn) + return CURLE_OK; /* this is closed and fine already */ + + if(!data) { + DEBUGF(infof(data, "DISCONNECT without easy handle, ignoring\n")); + return CURLE_OK; + } + + /* + * If this connection isn't marked to force-close, leave it open if there + * are other users of it + */ + if(CONN_INUSE(conn) && !dead_connection) { + DEBUGF(infof(data, "Curl_disconnect when inuse: %zu\n", CONN_INUSE(conn))); + return CURLE_OK; + } + + if(conn->dns_entry != NULL) { + Curl_resolv_unlock(data, conn->dns_entry); + conn->dns_entry = NULL; + } + + Curl_hostcache_prune(data); /* kill old DNS cache entries */ + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) + /* Cleanup NTLM connection-related data */ + Curl_http_auth_cleanup_ntlm(conn); +#endif +#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO) + /* Cleanup NEGOTIATE connection-related data */ + Curl_http_auth_cleanup_negotiate(conn); +#endif + + /* the protocol specific disconnect handler and conn_shutdown need a transfer + for the connection! */ + conn->data = data; + + if(conn->bits.connect_only) + /* treat the connection as dead in CONNECT_ONLY situations */ + dead_connection = TRUE; + + if(conn->handler->disconnect) + /* This is set if protocol-specific cleanups should be made */ + conn->handler->disconnect(conn, dead_connection); + + conn_shutdown(conn); + conn_free(conn); + return CURLE_OK; +} + +/* + * This function should return TRUE if the socket is to be assumed to + * be dead. Most commonly this happens when the server has closed the + * connection due to inactivity. + */ +static bool SocketIsDead(curl_socket_t sock) +{ + int sval; + bool ret_val = TRUE; + + sval = SOCKET_READABLE(sock, 0); + if(sval == 0) + /* timeout */ + ret_val = FALSE; + + return ret_val; +} + +/* + * IsMultiplexingPossible() + * + * Return a bitmask with the available multiplexing options for the given + * requested connection. + */ +static int IsMultiplexingPossible(const struct Curl_easy *handle, + const struct connectdata *conn) +{ + int avail = 0; + + /* If a HTTP protocol and multiplexing is enabled */ + if((conn->handler->protocol & PROTO_FAMILY_HTTP) && + (!conn->bits.protoconnstart || !conn->bits.close)) { + + if(Curl_multiplex_wanted(handle->multi) && + (handle->set.httpversion >= CURL_HTTP_VERSION_2)) + /* allows HTTP/2 */ + avail |= CURLPIPE_MULTIPLEX; + } + return avail; +} + +#ifndef CURL_DISABLE_PROXY +static bool +proxy_info_matches(const struct proxy_info* data, + const struct proxy_info* needle) +{ + if((data->proxytype == needle->proxytype) && + (data->port == needle->port) && + Curl_safe_strcasecompare(data->host.name, needle->host.name)) + return TRUE; + + return FALSE; +} +#else +/* disabled, won't get called */ +#define proxy_info_matches(x,y) FALSE +#endif + +/* + * This function checks if the given connection is dead and extracts it from + * the connection cache if so. + * + * When this is called as a Curl_conncache_foreach() callback, the connection + * cache lock is held! + * + * Returns TRUE if the connection was dead and extracted. + */ +static bool extract_if_dead(struct connectdata *conn, + struct Curl_easy *data) +{ + if(!CONN_INUSE(conn) && !conn->data) { + /* The check for a dead socket makes sense only if the connection isn't in + use */ + bool dead; + if(conn->handler->connection_check) { + /* The protocol has a special method for checking the state of the + connection. Use it to check if the connection is dead. */ + unsigned int state; + struct Curl_easy *olddata = conn->data; + conn->data = data; /* use this transfer for now */ + state = conn->handler->connection_check(conn, CONNCHECK_ISDEAD); + conn->data = olddata; + dead = (state & CONNRESULT_DEAD); + } + else { + /* Use the general method for determining the death of a connection */ + dead = SocketIsDead(conn->sock[FIRSTSOCKET]); + } + + if(dead) { + infof(data, "Connection %ld seems to be dead!\n", conn->connection_id); + Curl_conncache_remove_conn(data, conn, FALSE); + return TRUE; + } + } + return FALSE; +} + +struct prunedead { + struct Curl_easy *data; + struct connectdata *extracted; +}; + +/* + * Wrapper to use extract_if_dead() function in Curl_conncache_foreach() + * + */ +static int call_extract_if_dead(struct connectdata *conn, void *param) +{ + struct prunedead *p = (struct prunedead *)param; + if(extract_if_dead(conn, p->data)) { + /* stop the iteration here, pass back the connection that was extracted */ + p->extracted = conn; + return 1; + } + return 0; /* continue iteration */ +} + +/* + * This function scans the connection cache for half-open/dead connections, + * closes and removes them. + * The cleanup is done at most once per second. + */ +static void prune_dead_connections(struct Curl_easy *data) +{ + struct curltime now = Curl_now(); + time_t elapsed = Curl_timediff(now, data->state.conn_cache->last_cleanup); + + if(elapsed >= 1000L) { + struct prunedead prune; + prune.data = data; + prune.extracted = NULL; + while(Curl_conncache_foreach(data, data->state.conn_cache, &prune, + call_extract_if_dead)) { + /* disconnect it */ + (void)Curl_disconnect(data, prune.extracted, /* dead_connection */TRUE); + } + data->state.conn_cache->last_cleanup = now; + } +} + +/* A connection has to have been idle for a shorter time than 'maxage_conn' to + be subject for reuse. The success rate is just too low after this. */ + +static bool conn_maxage(struct Curl_easy *data, + struct connectdata *conn, + struct curltime now) +{ + if(!conn->data) { + timediff_t idletime = Curl_timediff(now, conn->lastused); + idletime /= 1000; /* integer seconds is fine */ + + if(idletime/1000 > data->set.maxage_conn) { + infof(data, "Too old connection (%ld seconds), disconnect it\n", + idletime); + return TRUE; + } + } + return FALSE; +} +/* + * Given one filled in connection struct (named needle), this function should + * detect if there already is one that has all the significant details + * exactly the same and thus should be used instead. + * + * If there is a match, this function returns TRUE - and has marked the + * connection as 'in-use'. It must later be called with ConnectionDone() to + * return back to 'idle' (unused) state. + * + * The force_reuse flag is set if the connection must be used. + */ +static bool +ConnectionExists(struct Curl_easy *data, + struct connectdata *needle, + struct connectdata **usethis, + bool *force_reuse, + bool *waitpipe) +{ + struct connectdata *check; + struct connectdata *chosen = 0; + bool foundPendingCandidate = FALSE; + bool canmultiplex = IsMultiplexingPossible(data, needle); + struct connectbundle *bundle; + struct curltime now = Curl_now(); + +#ifdef USE_NTLM + bool wantNTLMhttp = ((data->state.authhost.want & + (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) && + (needle->handler->protocol & PROTO_FAMILY_HTTP)); + bool wantProxyNTLMhttp = (needle->bits.proxy_user_passwd && + ((data->state.authproxy.want & + (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) && + (needle->handler->protocol & PROTO_FAMILY_HTTP))); +#endif + + *force_reuse = FALSE; + *waitpipe = FALSE; + + /* Look up the bundle with all the connections to this particular host. + Locks the connection cache, beware of early returns! */ + bundle = Curl_conncache_find_bundle(needle, data->state.conn_cache); + if(bundle) { + /* Max pipe length is zero (unlimited) for multiplexed connections */ + struct curl_llist_element *curr; + + infof(data, "Found bundle for host %s: %p [%s]\n", + (needle->bits.conn_to_host ? needle->conn_to_host.name : + needle->host.name), (void *)bundle, + (bundle->multiuse == BUNDLE_MULTIPLEX ? + "can multiplex" : "serially")); + + /* We can't multiplex if we don't know anything about the server */ + if(canmultiplex) { + if(bundle->multiuse == BUNDLE_UNKNOWN) { + if((bundle->multiuse == BUNDLE_UNKNOWN) && data->set.pipewait) { + infof(data, "Server doesn't support multiplex yet, wait\n"); + *waitpipe = TRUE; + Curl_conncache_unlock(data); + return FALSE; /* no re-use */ + } + + infof(data, "Server doesn't support multiplex (yet)\n"); + canmultiplex = FALSE; + } + if((bundle->multiuse == BUNDLE_MULTIPLEX) && + !Curl_multiplex_wanted(data->multi)) { + infof(data, "Could multiplex, but not asked to!\n"); + canmultiplex = FALSE; + } + if(bundle->multiuse == BUNDLE_NO_MULTIUSE) { + infof(data, "Can not multiplex, even if we wanted to!\n"); + canmultiplex = FALSE; + } + } + + curr = bundle->conn_list.head; + while(curr) { + bool match = FALSE; + size_t multiplexed; + + /* + * Note that if we use a HTTP proxy in normal mode (no tunneling), we + * check connections to that proxy and not to the actual remote server. + */ + check = curr->ptr; + curr = curr->next; + + if(check->bits.connect_only) + /* connect-only connections will not be reused */ + continue; + + if(conn_maxage(data, check, now) || extract_if_dead(check, data)) { + /* disconnect it */ + (void)Curl_disconnect(data, check, /* dead_connection */TRUE); + continue; + } + + multiplexed = CONN_INUSE(check) && + (bundle->multiuse == BUNDLE_MULTIPLEX); + + if(canmultiplex) { + if(check->bits.protoconnstart && check->bits.close) + continue; + } + else { + if(multiplexed) { + /* can only happen within multi handles, and means that another easy + handle is using this connection */ + continue; + } + + if(Curl_resolver_asynch()) { + /* ip_addr_str[0] is NUL only if the resolving of the name hasn't + completed yet and until then we don't re-use this connection */ + if(!check->ip_addr_str[0]) { + infof(data, + "Connection #%ld is still name resolving, can't reuse\n", + check->connection_id); + continue; + } + } + + if((check->sock[FIRSTSOCKET] == CURL_SOCKET_BAD) || + check->bits.close) { + if(!check->bits.close) + foundPendingCandidate = TRUE; + /* Don't pick a connection that hasn't connected yet or that is going + to get closed. */ + infof(data, "Connection #%ld isn't open enough, can't reuse\n", + check->connection_id); + continue; + } + } + +#ifdef USE_UNIX_SOCKETS + if(needle->unix_domain_socket) { + if(!check->unix_domain_socket) + continue; + if(strcmp(needle->unix_domain_socket, check->unix_domain_socket)) + continue; + if(needle->abstract_unix_socket != check->abstract_unix_socket) + continue; + } + else if(check->unix_domain_socket) + continue; +#endif + + if((needle->handler->flags&PROTOPT_SSL) != + (check->handler->flags&PROTOPT_SSL)) + /* don't do mixed SSL and non-SSL connections */ + if(get_protocol_family(check->handler->protocol) != + needle->handler->protocol || !check->tls_upgraded) + /* except protocols that have been upgraded via TLS */ + continue; + + if(needle->bits.httpproxy != check->bits.httpproxy || + needle->bits.socksproxy != check->bits.socksproxy) + continue; + + if(needle->bits.socksproxy && !proxy_info_matches(&needle->socks_proxy, + &check->socks_proxy)) + continue; + + if(needle->bits.conn_to_host != check->bits.conn_to_host) + /* don't mix connections that use the "connect to host" feature and + * connections that don't use this feature */ + continue; + + if(needle->bits.conn_to_port != check->bits.conn_to_port) + /* don't mix connections that use the "connect to port" feature and + * connections that don't use this feature */ + continue; + + if(needle->bits.httpproxy) { + if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy)) + continue; + + if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy) + continue; + + if(needle->http_proxy.proxytype == CURLPROXY_HTTPS) { + /* use https proxy */ + if(needle->handler->flags&PROTOPT_SSL) { + /* use double layer ssl */ + if(!Curl_ssl_config_matches(&needle->proxy_ssl_config, + &check->proxy_ssl_config)) + continue; + if(check->proxy_ssl[FIRSTSOCKET].state != ssl_connection_complete) + continue; + } + else { + if(!Curl_ssl_config_matches(&needle->ssl_config, + &check->ssl_config)) + continue; + if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete) + continue; + } + } + } + + if(!canmultiplex && check->data) + /* this request can't be multiplexed but the checked connection is + already in use so we skip it */ + continue; + + if(CONN_INUSE(check) && check->data && + (check->data->multi != needle->data->multi)) + /* this could be subject for multiplex use, but only if they belong to + * the same multi handle */ + continue; + + if(needle->localdev || needle->localport) { + /* If we are bound to a specific local end (IP+port), we must not + re-use a random other one, although if we didn't ask for a + particular one we can reuse one that was bound. + + This comparison is a bit rough and too strict. Since the input + parameters can be specified in numerous ways and still end up the + same it would take a lot of processing to make it really accurate. + Instead, this matching will assume that re-uses of bound connections + will most likely also re-use the exact same binding parameters and + missing out a few edge cases shouldn't hurt anyone very much. + */ + if((check->localport != needle->localport) || + (check->localportrange != needle->localportrange) || + (needle->localdev && + (!check->localdev || strcmp(check->localdev, needle->localdev)))) + continue; + } + + if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) { + /* This protocol requires credentials per connection, + so verify that we're using the same name and password as well */ + if(strcmp(needle->user, check->user) || + strcmp(needle->passwd, check->passwd)) { + /* one of them was different */ + continue; + } + } + + if(!needle->bits.httpproxy || (needle->handler->flags&PROTOPT_SSL) || + needle->bits.tunnel_proxy) { + /* The requested connection does not use a HTTP proxy or it uses SSL or + it is a non-SSL protocol tunneled or it is a non-SSL protocol which + is allowed to be upgraded via TLS */ + + if((strcasecompare(needle->handler->scheme, check->handler->scheme) || + (get_protocol_family(check->handler->protocol) == + needle->handler->protocol && check->tls_upgraded)) && + (!needle->bits.conn_to_host || strcasecompare( + needle->conn_to_host.name, check->conn_to_host.name)) && + (!needle->bits.conn_to_port || + needle->conn_to_port == check->conn_to_port) && + strcasecompare(needle->host.name, check->host.name) && + needle->remote_port == check->remote_port) { + /* The schemes match or the the protocol family is the same and the + previous connection was TLS upgraded, and the hostname and host + port match */ + if(needle->handler->flags & PROTOPT_SSL) { + /* This is a SSL connection so verify that we're using the same + SSL options as well */ + if(!Curl_ssl_config_matches(&needle->ssl_config, + &check->ssl_config)) { + DEBUGF(infof(data, + "Connection #%ld has different SSL parameters, " + "can't reuse\n", + check->connection_id)); + continue; + } + if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete) { + foundPendingCandidate = TRUE; + DEBUGF(infof(data, + "Connection #%ld has not started SSL connect, " + "can't reuse\n", + check->connection_id)); + continue; + } + } + match = TRUE; + } + } + else { + /* The requested connection is using the same HTTP proxy in normal + mode (no tunneling) */ + match = TRUE; + } + + if(match) { +#if defined(USE_NTLM) + /* If we are looking for an HTTP+NTLM connection, check if this is + already authenticating with the right credentials. If not, keep + looking so that we can reuse NTLM connections if + possible. (Especially we must not reuse the same connection if + partway through a handshake!) */ + if(wantNTLMhttp) { + if(strcmp(needle->user, check->user) || + strcmp(needle->passwd, check->passwd)) + continue; + } + else if(check->http_ntlm_state != NTLMSTATE_NONE) { + /* Connection is using NTLM auth but we don't want NTLM */ + continue; + } + + /* Same for Proxy NTLM authentication */ + if(wantProxyNTLMhttp) { + /* Both check->http_proxy.user and check->http_proxy.passwd can be + * NULL */ + if(!check->http_proxy.user || !check->http_proxy.passwd) + continue; + + if(strcmp(needle->http_proxy.user, check->http_proxy.user) || + strcmp(needle->http_proxy.passwd, check->http_proxy.passwd)) + continue; + } + else if(check->proxy_ntlm_state != NTLMSTATE_NONE) { + /* Proxy connection is using NTLM auth but we don't want NTLM */ + continue; + } + + if(wantNTLMhttp || wantProxyNTLMhttp) { + /* Credentials are already checked, we can use this connection */ + chosen = check; + + if((wantNTLMhttp && + (check->http_ntlm_state != NTLMSTATE_NONE)) || + (wantProxyNTLMhttp && + (check->proxy_ntlm_state != NTLMSTATE_NONE))) { + /* We must use this connection, no other */ + *force_reuse = TRUE; + break; + } + + /* Continue look up for a better connection */ + continue; + } +#endif + if(canmultiplex) { + /* We can multiplex if we want to. Let's continue looking for + the optimal connection to use. */ + + if(!multiplexed) { + /* We have the optimal connection. Let's stop looking. */ + chosen = check; + break; + } + +#ifdef USE_NGHTTP2 + /* If multiplexed, make sure we don't go over concurrency limit */ + if(check->bits.multiplex) { + /* Multiplexed connections can only be HTTP/2 for now */ + struct http_conn *httpc = &check->proto.httpc; + if(multiplexed >= httpc->settings.max_concurrent_streams) { + infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)\n", + multiplexed); + continue; + } + } +#endif + /* When not multiplexed, we have a match here! */ + chosen = check; + infof(data, "Multiplexed connection found!\n"); + break; + } + else { + /* We have found a connection. Let's stop searching. */ + chosen = check; + break; + } + } + } + } + + if(chosen) { + /* mark it as used before releasing the lock */ + chosen->data = data; /* own it! */ + Curl_conncache_unlock(data); + *usethis = chosen; + return TRUE; /* yes, we found one to use! */ + } + Curl_conncache_unlock(data); + + if(foundPendingCandidate && data->set.pipewait) { + infof(data, + "Found pending candidate for reuse and CURLOPT_PIPEWAIT is set\n"); + *waitpipe = TRUE; + } + + return FALSE; /* no matching connecting exists */ +} + +/* after a TCP connection to the proxy has been verified, this function does + the next magic step. + + Note: this function's sub-functions call failf() + +*/ +CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex) +{ + CURLcode result = CURLE_OK; + + if(conn->bits.socksproxy) { +#ifndef CURL_DISABLE_PROXY + /* for the secondary socket (FTP), use the "connect to host" + * but ignore the "connect to port" (use the secondary port) + */ + const char * const host = conn->bits.httpproxy ? + conn->http_proxy.host.name : + conn->bits.conn_to_host ? + conn->conn_to_host.name : + sockindex == SECONDARYSOCKET ? + conn->secondaryhostname : conn->host.name; + const int port = conn->bits.httpproxy ? (int)conn->http_proxy.port : + sockindex == SECONDARYSOCKET ? conn->secondary_port : + conn->bits.conn_to_port ? conn->conn_to_port : + conn->remote_port; + conn->bits.socksproxy_connecting = TRUE; + switch(conn->socks_proxy.proxytype) { + case CURLPROXY_SOCKS5: + case CURLPROXY_SOCKS5_HOSTNAME: + result = Curl_SOCKS5(conn->socks_proxy.user, conn->socks_proxy.passwd, + host, port, sockindex, conn); + break; + + case CURLPROXY_SOCKS4: + case CURLPROXY_SOCKS4A: + result = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex, + conn); + break; + + default: + failf(conn->data, "unknown proxytype option given"); + result = CURLE_COULDNT_CONNECT; + } /* switch proxytype */ + conn->bits.socksproxy_connecting = FALSE; +#else + (void)sockindex; +#endif /* CURL_DISABLE_PROXY */ + } + + return result; +} + +/* + * verboseconnect() displays verbose information after a connect + */ +#ifndef CURL_DISABLE_VERBOSE_STRINGS +void Curl_verboseconnect(struct connectdata *conn) +{ + if(conn->data->set.verbose) + infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n", + conn->bits.socksproxy ? conn->socks_proxy.host.dispname : + conn->bits.httpproxy ? conn->http_proxy.host.dispname : + conn->bits.conn_to_host ? conn->conn_to_host.dispname : + conn->host.dispname, + conn->ip_addr_str, conn->port, conn->connection_id); +} +#endif + +int Curl_protocol_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + if(conn->handler->proto_getsock) + return conn->handler->proto_getsock(conn, socks, numsocks); + /* Backup getsock logic. Since there is a live socket in use, we must wait + for it or it will be removed from watching when the multi_socket API is + used. */ + socks[0] = conn->sock[FIRSTSOCKET]; + return GETSOCK_READSOCK(0) | GETSOCK_WRITESOCK(0); +} + +int Curl_doing_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + if(conn && conn->handler->doing_getsock) + return conn->handler->doing_getsock(conn, socks, numsocks); + return GETSOCK_BLANK; +} + +/* + * We are doing protocol-specific connecting and this is being called over and + * over from the multi interface until the connection phase is done on + * protocol layer. + */ + +CURLcode Curl_protocol_connecting(struct connectdata *conn, + bool *done) +{ + CURLcode result = CURLE_OK; + + if(conn && conn->handler->connecting) { + *done = FALSE; + result = conn->handler->connecting(conn, done); + } + else + *done = TRUE; + + return result; +} + +/* + * We are DOING this is being called over and over from the multi interface + * until the DOING phase is done on protocol layer. + */ + +CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + + if(conn && conn->handler->doing) { + *done = FALSE; + result = conn->handler->doing(conn, done); + } + else + *done = TRUE; + + return result; +} + +/* + * We have discovered that the TCP connection has been successful, we can now + * proceed with some action. + * + */ +CURLcode Curl_protocol_connect(struct connectdata *conn, + bool *protocol_done) +{ + CURLcode result = CURLE_OK; + + *protocol_done = FALSE; + + if(conn->bits.tcpconnect[FIRSTSOCKET] && conn->bits.protoconnstart) { + /* We already are connected, get back. This may happen when the connect + worked fine in the first call, like when we connect to a local server + or proxy. Note that we don't know if the protocol is actually done. + + Unless this protocol doesn't have any protocol-connect callback, as + then we know we're done. */ + if(!conn->handler->connecting) + *protocol_done = TRUE; + + return CURLE_OK; + } + + if(!conn->bits.protoconnstart) { + + result = Curl_proxy_connect(conn, FIRSTSOCKET); + if(result) + return result; + + if(CONNECT_FIRSTSOCKET_PROXY_SSL()) + /* wait for HTTPS proxy SSL initialization to complete */ + return CURLE_OK; + + if(conn->bits.tunnel_proxy && conn->bits.httpproxy && + Curl_connect_ongoing(conn)) + /* when using an HTTP tunnel proxy, await complete tunnel establishment + before proceeding further. Return CURLE_OK so we'll be called again */ + return CURLE_OK; + + if(conn->handler->connect_it) { + /* is there a protocol-specific connect() procedure? */ + + /* Call the protocol-specific connect function */ + result = conn->handler->connect_it(conn, protocol_done); + } + else + *protocol_done = TRUE; + + /* it has started, possibly even completed but that knowledge isn't stored + in this bit! */ + if(!result) + conn->bits.protoconnstart = TRUE; + } + + return result; /* pass back status */ +} + +/* + * Helpers for IDNA conversions. + */ +static bool is_ASCII_name(const char *hostname) +{ + const unsigned char *ch = (const unsigned char *)hostname; + + while(*ch) { + if(*ch++ & 0x80) + return FALSE; + } + return TRUE; +} + +/* + * Strip single trailing dot in the hostname, + * primarily for SNI and http host header. + */ +static void strip_trailing_dot(struct hostname *host) +{ + size_t len; + if(!host || !host->name) + return; + len = strlen(host->name); + if(len && (host->name[len-1] == '.')) + host->name[len-1] = 0; +} + +/* + * Perform any necessary IDN conversion of hostname + */ +static CURLcode idnconvert_hostname(struct connectdata *conn, + struct hostname *host) +{ + struct Curl_easy *data = conn->data; + +#ifndef USE_LIBIDN2 + (void)data; + (void)conn; +#elif defined(CURL_DISABLE_VERBOSE_STRINGS) + (void)conn; +#endif + + /* set the name we use to display the host name */ + host->dispname = host->name; + + /* Check name for non-ASCII and convert hostname to ACE form if we can */ + if(!is_ASCII_name(host->name)) { +#ifdef USE_LIBIDN2 + if(idn2_check_version(IDN2_VERSION)) { + char *ace_hostname = NULL; +#if IDN2_VERSION_NUMBER >= 0x00140000 + /* IDN2_NFC_INPUT: Normalize input string using normalization form C. + IDN2_NONTRANSITIONAL: Perform Unicode TR46 non-transitional + processing. */ + int flags = IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL; +#else + int flags = IDN2_NFC_INPUT; +#endif + int rc = idn2_lookup_ul((const char *)host->name, &ace_hostname, flags); + if(rc == IDN2_OK) { + host->encalloc = (char *)ace_hostname; + /* change the name pointer to point to the encoded hostname */ + host->name = host->encalloc; + } + else { + failf(data, "Failed to convert %s to ACE; %s\n", host->name, + idn2_strerror(rc)); + return CURLE_URL_MALFORMAT; + } + } +#elif defined(USE_WIN32_IDN) + char *ace_hostname = NULL; + + if(curl_win32_idn_to_ascii(host->name, &ace_hostname)) { + host->encalloc = ace_hostname; + /* change the name pointer to point to the encoded hostname */ + host->name = host->encalloc; + } + else { + failf(data, "Failed to convert %s to ACE;\n", host->name); + return CURLE_URL_MALFORMAT; + } +#else + infof(data, "IDN support not present, can't parse Unicode domains\n"); +#endif + } + return CURLE_OK; +} + +/* + * Frees data allocated by idnconvert_hostname() + */ +static void free_idnconverted_hostname(struct hostname *host) +{ +#if defined(USE_LIBIDN2) + if(host->encalloc) { + idn2_free(host->encalloc); /* must be freed with idn2_free() since this was + allocated by libidn */ + host->encalloc = NULL; + } +#elif defined(USE_WIN32_IDN) + free(host->encalloc); /* must be freed with free() since this was + allocated by curl_win32_idn_to_ascii */ + host->encalloc = NULL; +#else + (void)host; +#endif +} + +static void llist_dtor(void *user, void *element) +{ + (void)user; + (void)element; + /* Do nothing */ +} + +/* + * Allocate and initialize a new connectdata object. + */ +static struct connectdata *allocate_conn(struct Curl_easy *data) +{ + struct connectdata *conn = calloc(1, sizeof(struct connectdata)); + if(!conn) + return NULL; + +#ifdef USE_SSL + /* The SSL backend-specific data (ssl_backend_data) objects are allocated as + a separate array to ensure suitable alignment. + Note that these backend pointers can be swapped by vtls (eg ssl backend + data becomes proxy backend data). */ + { + size_t sslsize = Curl_ssl->sizeof_ssl_backend_data; + char *ssl = calloc(4, sslsize); + if(!ssl) { + free(conn); + return NULL; + } + conn->ssl_extra = ssl; + conn->ssl[0].backend = (void *)ssl; + conn->ssl[1].backend = (void *)(ssl + sslsize); + conn->proxy_ssl[0].backend = (void *)(ssl + 2 * sslsize); + conn->proxy_ssl[1].backend = (void *)(ssl + 3 * sslsize); + } +#endif + + conn->handler = &Curl_handler_dummy; /* Be sure we have a handler defined + already from start to avoid NULL + situations and checks */ + + /* and we setup a few fields in case we end up actually using this struct */ + + conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */ + conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */ + conn->tempsock[0] = CURL_SOCKET_BAD; /* no file descriptor */ + conn->tempsock[1] = CURL_SOCKET_BAD; /* no file descriptor */ + conn->connection_id = -1; /* no ID */ + conn->port = -1; /* unknown at this point */ + conn->remote_port = -1; /* unknown at this point */ +#if defined(USE_RECV_BEFORE_SEND_WORKAROUND) && defined(DEBUGBUILD) + conn->postponed[0].bindsock = CURL_SOCKET_BAD; /* no file descriptor */ + conn->postponed[1].bindsock = CURL_SOCKET_BAD; /* no file descriptor */ +#endif /* USE_RECV_BEFORE_SEND_WORKAROUND && DEBUGBUILD */ + + /* Default protocol-independent behavior doesn't support persistent + connections, so we set this to force-close. Protocols that support + this need to set this to FALSE in their "curl_do" functions. */ + connclose(conn, "Default to force-close"); + + /* Store creation time to help future close decision making */ + conn->created = Curl_now(); + + /* Store current time to give a baseline to keepalive connection times. */ + conn->keepalive = Curl_now(); + + /* Store off the configured connection upkeep time. */ + conn->upkeep_interval_ms = data->set.upkeep_interval_ms; + + conn->data = data; /* Setup the association between this connection + and the Curl_easy */ + + conn->http_proxy.proxytype = data->set.proxytype; + conn->socks_proxy.proxytype = CURLPROXY_SOCKS4; + +#if !defined(CURL_DISABLE_PROXY) + /* note that these two proxy bits are now just on what looks to be + requested, they may be altered down the road */ + conn->bits.proxy = (data->set.str[STRING_PROXY] && + *data->set.str[STRING_PROXY]) ? TRUE : FALSE; + conn->bits.httpproxy = (conn->bits.proxy && + (conn->http_proxy.proxytype == CURLPROXY_HTTP || + conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0 || + conn->http_proxy.proxytype == CURLPROXY_HTTPS)) ? + TRUE : FALSE; + conn->bits.socksproxy = (conn->bits.proxy && + !conn->bits.httpproxy) ? TRUE : FALSE; + + if(data->set.str[STRING_PRE_PROXY] && *data->set.str[STRING_PRE_PROXY]) { + conn->bits.proxy = TRUE; + conn->bits.socksproxy = TRUE; + } + + conn->bits.proxy_user_passwd = + (data->set.str[STRING_PROXYUSERNAME]) ? TRUE : FALSE; + conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy; +#endif /* CURL_DISABLE_PROXY */ + + conn->bits.user_passwd = (data->set.str[STRING_USERNAME]) ? TRUE : FALSE; +#ifndef CURL_DISABLE_FTP + conn->bits.ftp_use_epsv = data->set.ftp_use_epsv; + conn->bits.ftp_use_eprt = data->set.ftp_use_eprt; +#endif + conn->ssl_config.verifystatus = data->set.ssl.primary.verifystatus; + conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer; + conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost; + conn->proxy_ssl_config.verifystatus = + data->set.proxy_ssl.primary.verifystatus; + conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer; + conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost; + conn->ip_version = data->set.ipver; + conn->bits.connect_only = data->set.connect_only; + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \ + defined(NTLM_WB_ENABLED) + conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD; +#endif + + /* Initialize the easy handle list */ + Curl_llist_init(&conn->easyq, (curl_llist_dtor) llist_dtor); + +#ifdef HAVE_GSSAPI + conn->data_prot = PROT_CLEAR; +#endif + + /* Store the local bind parameters that will be used for this connection */ + if(data->set.str[STRING_DEVICE]) { + conn->localdev = strdup(data->set.str[STRING_DEVICE]); + if(!conn->localdev) + goto error; + } + conn->localportrange = data->set.localportrange; + conn->localport = data->set.localport; + + /* the close socket stuff needs to be copied to the connection struct as + it may live on without (this specific) Curl_easy */ + conn->fclosesocket = data->set.fclosesocket; + conn->closesocket_client = data->set.closesocket_client; + + return conn; + error: + + Curl_llist_destroy(&conn->easyq, NULL); + free(conn->localdev); +#ifdef USE_SSL + free(conn->ssl_extra); +#endif + free(conn); + return NULL; +} + +/* returns the handler if the given scheme is built-in */ +const struct Curl_handler *Curl_builtin_scheme(const char *scheme) +{ + const struct Curl_handler * const *pp; + const struct Curl_handler *p; + /* Scan protocol handler table and match against 'scheme'. The handler may + be changed later when the protocol specific setup function is called. */ + for(pp = protocols; (p = *pp) != NULL; pp++) + if(strcasecompare(p->scheme, scheme)) + /* Protocol found in table. Check if allowed */ + return p; + return NULL; /* not found */ +} + + +static CURLcode findprotocol(struct Curl_easy *data, + struct connectdata *conn, + const char *protostr) +{ + const struct Curl_handler *p = Curl_builtin_scheme(protostr); + + if(p && /* Protocol found in table. Check if allowed */ + (data->set.allowed_protocols & p->protocol)) { + + /* it is allowed for "normal" request, now do an extra check if this is + the result of a redirect */ + if(data->state.this_is_a_follow && + !(data->set.redir_protocols & p->protocol)) + /* nope, get out */ + ; + else { + /* Perform setup complement if some. */ + conn->handler = conn->given = p; + + /* 'port' and 'remote_port' are set in setup_connection_internals() */ + return CURLE_OK; + } + } + + /* The protocol was not found in the table, but we don't have to assign it + to anything since it is already assigned to a dummy-struct in the + create_conn() function when the connectdata struct is allocated. */ + failf(data, "Protocol \"%s\" not supported or disabled in " LIBCURL_NAME, + protostr); + + return CURLE_UNSUPPORTED_PROTOCOL; +} + + +CURLcode Curl_uc_to_curlcode(CURLUcode uc) +{ + switch(uc) { + default: + return CURLE_URL_MALFORMAT; + case CURLUE_UNSUPPORTED_SCHEME: + return CURLE_UNSUPPORTED_PROTOCOL; + case CURLUE_OUT_OF_MEMORY: + return CURLE_OUT_OF_MEMORY; + case CURLUE_USER_NOT_ALLOWED: + return CURLE_LOGIN_DENIED; + } +} + +/* + * Parse URL and fill in the relevant members of the connection struct. + */ +static CURLcode parseurlandfillconn(struct Curl_easy *data, + struct connectdata *conn) +{ + CURLcode result; + CURLU *uh; + CURLUcode uc; + char *hostname; + + up_free(data); /* cleanup previous leftovers first */ + + /* parse the URL */ + if(data->set.uh) { + uh = data->state.uh = curl_url_dup(data->set.uh); + } + else { + uh = data->state.uh = curl_url(); + } + + if(!uh) + return CURLE_OUT_OF_MEMORY; + + if(data->set.str[STRING_DEFAULT_PROTOCOL] && + !Curl_is_absolute_url(data->change.url, NULL, MAX_SCHEME_LEN)) { + char *url; + if(data->change.url_alloc) + free(data->change.url); + url = aprintf("%s://%s", data->set.str[STRING_DEFAULT_PROTOCOL], + data->change.url); + if(!url) + return CURLE_OUT_OF_MEMORY; + data->change.url = url; + data->change.url_alloc = TRUE; + } + + if(!data->set.uh) { + uc = curl_url_set(uh, CURLUPART_URL, data->change.url, + CURLU_GUESS_SCHEME | + CURLU_NON_SUPPORT_SCHEME | + (data->set.disallow_username_in_url ? + CURLU_DISALLOW_USER : 0) | + (data->set.path_as_is ? CURLU_PATH_AS_IS : 0)); + if(uc) { + DEBUGF(infof(data, "curl_url_set rejected %s\n", data->change.url)); + return Curl_uc_to_curlcode(uc); + } + } + + uc = curl_url_get(uh, CURLUPART_SCHEME, &data->state.up.scheme, 0); + if(uc) + return Curl_uc_to_curlcode(uc); + + result = findprotocol(data, conn, data->state.up.scheme); + if(result) + return result; + + uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user, + CURLU_URLDECODE); + if(!uc) { + conn->user = strdup(data->state.up.user); + if(!conn->user) + return CURLE_OUT_OF_MEMORY; + conn->bits.user_passwd = TRUE; + } + else if(uc != CURLUE_NO_USER) + return Curl_uc_to_curlcode(uc); + + uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, + CURLU_URLDECODE); + if(!uc) { + conn->passwd = strdup(data->state.up.password); + if(!conn->passwd) + return CURLE_OUT_OF_MEMORY; + conn->bits.user_passwd = TRUE; + } + else if(uc != CURLUE_NO_PASSWORD) + return Curl_uc_to_curlcode(uc); + + uc = curl_url_get(uh, CURLUPART_OPTIONS, &data->state.up.options, + CURLU_URLDECODE); + if(!uc) { + conn->options = strdup(data->state.up.options); + if(!conn->options) + return CURLE_OUT_OF_MEMORY; + } + else if(uc != CURLUE_NO_OPTIONS) + return Curl_uc_to_curlcode(uc); + + uc = curl_url_get(uh, CURLUPART_HOST, &data->state.up.hostname, 0); + if(uc) { + if(!strcasecompare("file", data->state.up.scheme)) + return CURLE_OUT_OF_MEMORY; + } + + uc = curl_url_get(uh, CURLUPART_PATH, &data->state.up.path, 0); + if(uc) + return Curl_uc_to_curlcode(uc); + + uc = curl_url_get(uh, CURLUPART_PORT, &data->state.up.port, + CURLU_DEFAULT_PORT); + if(uc) { + if(!strcasecompare("file", data->state.up.scheme)) + return CURLE_OUT_OF_MEMORY; + } + else { + unsigned long port = strtoul(data->state.up.port, NULL, 10); + conn->remote_port = curlx_ultous(port); + } + + (void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0); + + hostname = data->state.up.hostname; + if(!hostname) + /* this is for file:// transfers, get a dummy made */ + hostname = (char *)""; + + if(hostname[0] == '[') { + /* This looks like an IPv6 address literal. See if there is an address + scope. */ + char *zoneid; + size_t hlen; + uc = curl_url_get(uh, CURLUPART_ZONEID, &zoneid, 0); + conn->bits.ipv6_ip = TRUE; + + /* cut off the brackets! */ + hostname++; + hlen = strlen(hostname); + hostname[hlen - 1] = 0; + if(!uc && zoneid) { + char *endp; + unsigned long scope; + scope = strtoul(zoneid, &endp, 10); + if(!*endp && (scope < UINT_MAX)) { + /* A plain number, use it direcly as a scope id. */ + conn->scope_id = (unsigned int)scope; + } +#ifdef HAVE_IF_NAMETOINDEX + else { + /* Zone identifier is not numeric */ + unsigned int scopeidx = 0; + scopeidx = if_nametoindex(zoneid); + if(!scopeidx) + infof(data, "Invalid zoneid id: %s; %s\n", zoneid, + strerror(errno)); + else + conn->scope_id = scopeidx; + + } +#endif /* HAVE_IF_NAMETOINDEX */ + free(zoneid); + } + } + + /* make sure the connect struct gets its own copy of the host name */ + conn->host.rawalloc = strdup(hostname); + if(!conn->host.rawalloc) + return CURLE_OUT_OF_MEMORY; + conn->host.name = conn->host.rawalloc; + + if(data->set.scope_id) + /* Override any scope that was set above. */ + conn->scope_id = data->set.scope_id; + + return CURLE_OK; +} + + +/* + * If we're doing a resumed transfer, we need to setup our stuff + * properly. + */ +static CURLcode setup_range(struct Curl_easy *data) +{ + struct UrlState *s = &data->state; + s->resume_from = data->set.set_resume_from; + if(s->resume_from || data->set.str[STRING_SET_RANGE]) { + if(s->rangestringalloc) + free(s->range); + + if(s->resume_from) + s->range = aprintf("%" CURL_FORMAT_CURL_OFF_T "-", s->resume_from); + else + s->range = strdup(data->set.str[STRING_SET_RANGE]); + + s->rangestringalloc = (s->range) ? TRUE : FALSE; + + if(!s->range) + return CURLE_OUT_OF_MEMORY; + + /* tell ourselves to fetch this range */ + s->use_range = TRUE; /* enable range download */ + } + else + s->use_range = FALSE; /* disable range download */ + + return CURLE_OK; +} + + +/* + * setup_connection_internals() - + * + * Setup connection internals specific to the requested protocol in the + * Curl_easy. This is inited and setup before the connection is made but + * is about the particular protocol that is to be used. + * + * This MUST get called after proxy magic has been figured out. + */ +static CURLcode setup_connection_internals(struct connectdata *conn) +{ + const struct Curl_handler * p; + CURLcode result; + conn->socktype = SOCK_STREAM; /* most of them are TCP streams */ + + /* Perform setup complement if some. */ + p = conn->handler; + + if(p->setup_connection) { + result = (*p->setup_connection)(conn); + + if(result) + return result; + + p = conn->handler; /* May have changed. */ + } + + if(conn->port < 0) + /* we check for -1 here since if proxy was detected already, this + was very likely already set to the proxy port */ + conn->port = p->defport; + + return CURLE_OK; +} + +/* + * Curl_free_request_state() should free temp data that was allocated in the + * Curl_easy for this single request. + */ + +void Curl_free_request_state(struct Curl_easy *data) +{ + Curl_safefree(data->req.protop); + Curl_safefree(data->req.newurl); +} + + +#ifndef CURL_DISABLE_PROXY +/**************************************************************** +* Checks if the host is in the noproxy list. returns true if it matches +* and therefore the proxy should NOT be used. +****************************************************************/ +static bool check_noproxy(const char *name, const char *no_proxy) +{ + /* no_proxy=domain1.dom,host.domain2.dom + * (a comma-separated list of hosts which should + * not be proxied, or an asterisk to override + * all proxy variables) + */ + if(no_proxy && no_proxy[0]) { + size_t tok_start; + size_t tok_end; + const char *separator = ", "; + size_t no_proxy_len; + size_t namelen; + char *endptr; + if(strcasecompare("*", no_proxy)) { + return TRUE; + } + + /* NO_PROXY was specified and it wasn't just an asterisk */ + + no_proxy_len = strlen(no_proxy); + if(name[0] == '[') { + /* IPv6 numerical address */ + endptr = strchr(name, ']'); + if(!endptr) + return FALSE; + name++; + namelen = endptr - name; + } + else + namelen = strlen(name); + + for(tok_start = 0; tok_start < no_proxy_len; tok_start = tok_end + 1) { + while(tok_start < no_proxy_len && + strchr(separator, no_proxy[tok_start]) != NULL) { + /* Look for the beginning of the token. */ + ++tok_start; + } + + if(tok_start == no_proxy_len) + break; /* It was all trailing separator chars, no more tokens. */ + + for(tok_end = tok_start; tok_end < no_proxy_len && + strchr(separator, no_proxy[tok_end]) == NULL; ++tok_end) + /* Look for the end of the token. */ + ; + + /* To match previous behaviour, where it was necessary to specify + * ".local.com" to prevent matching "notlocal.com", we will leave + * the '.' off. + */ + if(no_proxy[tok_start] == '.') + ++tok_start; + + if((tok_end - tok_start) <= namelen) { + /* Match the last part of the name to the domain we are checking. */ + const char *checkn = name + namelen - (tok_end - tok_start); + if(strncasecompare(no_proxy + tok_start, checkn, + tok_end - tok_start)) { + if((tok_end - tok_start) == namelen || *(checkn - 1) == '.') { + /* We either have an exact match, or the previous character is a . + * so it is within the same domain, so no proxy for this host. + */ + return TRUE; + } + } + } /* if((tok_end - tok_start) <= namelen) */ + } /* for(tok_start = 0; tok_start < no_proxy_len; + tok_start = tok_end + 1) */ + } /* NO_PROXY was specified and it wasn't just an asterisk */ + + return FALSE; +} + +#ifndef CURL_DISABLE_HTTP +/**************************************************************** +* Detect what (if any) proxy to use. Remember that this selects a host +* name and is not limited to HTTP proxies only. +* The returned pointer must be freed by the caller (unless NULL) +****************************************************************/ +static char *detect_proxy(struct connectdata *conn) +{ + char *proxy = NULL; + + /* If proxy was not specified, we check for default proxy environment + * variables, to enable i.e Lynx compliance: + * + * http_proxy=http://some.server.dom:port/ + * https_proxy=http://some.server.dom:port/ + * ftp_proxy=http://some.server.dom:port/ + * no_proxy=domain1.dom,host.domain2.dom + * (a comma-separated list of hosts which should + * not be proxied, or an asterisk to override + * all proxy variables) + * all_proxy=http://some.server.dom:port/ + * (seems to exist for the CERN www lib. Probably + * the first to check for.) + * + * For compatibility, the all-uppercase versions of these variables are + * checked if the lowercase versions don't exist. + */ + char proxy_env[128]; + const char *protop = conn->handler->scheme; + char *envp = proxy_env; + char *prox; + + /* Now, build _proxy and check for such a one to use */ + while(*protop) + *envp++ = (char)tolower((int)*protop++); + + /* append _proxy */ + strcpy(envp, "_proxy"); + + /* read the protocol proxy: */ + prox = curl_getenv(proxy_env); + + /* + * We don't try the uppercase version of HTTP_PROXY because of + * security reasons: + * + * When curl is used in a webserver application + * environment (cgi or php), this environment variable can + * be controlled by the web server user by setting the + * http header 'Proxy:' to some value. + * + * This can cause 'internal' http/ftp requests to be + * arbitrarily redirected by any external attacker. + */ + if(!prox && !strcasecompare("http_proxy", proxy_env)) { + /* There was no lowercase variable, try the uppercase version: */ + Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env)); + prox = curl_getenv(proxy_env); + } + + envp = proxy_env; + if(prox) { + proxy = prox; /* use this */ + } + else { + envp = (char *)"all_proxy"; + proxy = curl_getenv(envp); /* default proxy to use */ + if(!proxy) { + envp = (char *)"ALL_PROXY"; + proxy = curl_getenv(envp); + } + } + if(proxy) + infof(conn->data, "Uses proxy env variable %s == '%s'\n", envp, proxy); + + return proxy; +} +#endif /* CURL_DISABLE_HTTP */ + +/* + * If this is supposed to use a proxy, we need to figure out the proxy + * host name, so that we can re-use an existing connection + * that may exist registered to the same proxy host. + */ +static CURLcode parse_proxy(struct Curl_easy *data, + struct connectdata *conn, char *proxy, + curl_proxytype proxytype) +{ + char *portptr; + long port = -1; + char *proxyuser = NULL; + char *proxypasswd = NULL; + char *host; + bool sockstype; + CURLUcode uc; + struct proxy_info *proxyinfo; + CURLU *uhp = curl_url(); + CURLcode result = CURLE_OK; + char *scheme = NULL; + + /* When parsing the proxy, allowing non-supported schemes since we have + these made up ones for proxies. Guess scheme for URLs without it. */ + uc = curl_url_set(uhp, CURLUPART_URL, proxy, + CURLU_NON_SUPPORT_SCHEME|CURLU_GUESS_SCHEME); + if(!uc) { + /* parsed okay as a URL */ + uc = curl_url_get(uhp, CURLUPART_SCHEME, &scheme, 0); + if(uc) { + result = CURLE_OUT_OF_MEMORY; + goto error; + } + + if(strcasecompare("https", scheme)) + proxytype = CURLPROXY_HTTPS; + else if(strcasecompare("socks5h", scheme)) + proxytype = CURLPROXY_SOCKS5_HOSTNAME; + else if(strcasecompare("socks5", scheme)) + proxytype = CURLPROXY_SOCKS5; + else if(strcasecompare("socks4a", scheme)) + proxytype = CURLPROXY_SOCKS4A; + else if(strcasecompare("socks4", scheme) || + strcasecompare("socks", scheme)) + proxytype = CURLPROXY_SOCKS4; + else if(strcasecompare("http", scheme)) + ; /* leave it as HTTP or HTTP/1.0 */ + else { + /* Any other xxx:// reject! */ + failf(data, "Unsupported proxy scheme for \'%s\'", proxy); + result = CURLE_COULDNT_CONNECT; + goto error; + } + } + else { + failf(data, "Unsupported proxy syntax in \'%s\'", proxy); + result = CURLE_COULDNT_RESOLVE_PROXY; + goto error; + } + +#ifdef USE_SSL + if(!(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY)) +#endif + if(proxytype == CURLPROXY_HTTPS) { + failf(data, "Unsupported proxy \'%s\', libcurl is built without the " + "HTTPS-proxy support.", proxy); + result = CURLE_NOT_BUILT_IN; + goto error; + } + + sockstype = + proxytype == CURLPROXY_SOCKS5_HOSTNAME || + proxytype == CURLPROXY_SOCKS5 || + proxytype == CURLPROXY_SOCKS4A || + proxytype == CURLPROXY_SOCKS4; + + proxyinfo = sockstype ? &conn->socks_proxy : &conn->http_proxy; + proxyinfo->proxytype = proxytype; + + /* Is there a username and password given in this proxy url? */ + curl_url_get(uhp, CURLUPART_USER, &proxyuser, CURLU_URLDECODE); + curl_url_get(uhp, CURLUPART_PASSWORD, &proxypasswd, CURLU_URLDECODE); + if(proxyuser || proxypasswd) { + Curl_safefree(proxyinfo->user); + proxyinfo->user = proxyuser; + Curl_safefree(proxyinfo->passwd); + if(!proxypasswd) { + proxypasswd = strdup(""); + if(!proxypasswd) { + result = CURLE_OUT_OF_MEMORY; + goto error; + } + } + proxyinfo->passwd = proxypasswd; + conn->bits.proxy_user_passwd = TRUE; /* enable it */ + } + + curl_url_get(uhp, CURLUPART_PORT, &portptr, 0); + + if(portptr) { + port = strtol(portptr, NULL, 10); + free(portptr); + } + else { + if(data->set.proxyport) + /* None given in the proxy string, then get the default one if it is + given */ + port = data->set.proxyport; + else { + if(proxytype == CURLPROXY_HTTPS) + port = CURL_DEFAULT_HTTPS_PROXY_PORT; + else + port = CURL_DEFAULT_PROXY_PORT; + } + } + if(port >= 0) { + proxyinfo->port = port; + if(conn->port < 0 || sockstype || !conn->socks_proxy.host.rawalloc) + conn->port = port; + } + + /* now, clone the proxy host name */ + uc = curl_url_get(uhp, CURLUPART_HOST, &host, CURLU_URLDECODE); + if(uc) { + result = CURLE_OUT_OF_MEMORY; + goto error; + } + Curl_safefree(proxyinfo->host.rawalloc); + proxyinfo->host.rawalloc = host; + if(host[0] == '[') { + /* this is a numerical IPv6, strip off the brackets */ + size_t len = strlen(host); + host[len-1] = 0; /* clear the trailing bracket */ + host++; + } + proxyinfo->host.name = host; + + error: + free(scheme); + curl_url_cleanup(uhp); + return result; +} + +/* + * Extract the user and password from the authentication string + */ +static CURLcode parse_proxy_auth(struct Curl_easy *data, + struct connectdata *conn) +{ + char proxyuser[MAX_CURL_USER_LENGTH]=""; + char proxypasswd[MAX_CURL_PASSWORD_LENGTH]=""; + CURLcode result; + + if(data->set.str[STRING_PROXYUSERNAME] != NULL) { + strncpy(proxyuser, data->set.str[STRING_PROXYUSERNAME], + MAX_CURL_USER_LENGTH); + proxyuser[MAX_CURL_USER_LENGTH-1] = '\0'; /*To be on safe side*/ + } + if(data->set.str[STRING_PROXYPASSWORD] != NULL) { + strncpy(proxypasswd, data->set.str[STRING_PROXYPASSWORD], + MAX_CURL_PASSWORD_LENGTH); + proxypasswd[MAX_CURL_PASSWORD_LENGTH-1] = '\0'; /*To be on safe side*/ + } + + result = Curl_urldecode(data, proxyuser, 0, &conn->http_proxy.user, NULL, + FALSE); + if(!result) + result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd, + NULL, FALSE); + return result; +} + +/* create_conn helper to parse and init proxy values. to be called after unix + socket init but before any proxy vars are evaluated. */ +static CURLcode create_conn_helper_init_proxy(struct connectdata *conn) +{ + char *proxy = NULL; + char *socksproxy = NULL; + char *no_proxy = NULL; + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + /************************************************************* + * Extract the user and password from the authentication string + *************************************************************/ + if(conn->bits.proxy_user_passwd) { + result = parse_proxy_auth(data, conn); + if(result) + goto out; + } + + /************************************************************* + * Detect what (if any) proxy to use + *************************************************************/ + if(data->set.str[STRING_PROXY]) { + proxy = strdup(data->set.str[STRING_PROXY]); + /* if global proxy is set, this is it */ + if(NULL == proxy) { + failf(data, "memory shortage"); + result = CURLE_OUT_OF_MEMORY; + goto out; + } + } + + if(data->set.str[STRING_PRE_PROXY]) { + socksproxy = strdup(data->set.str[STRING_PRE_PROXY]); + /* if global socks proxy is set, this is it */ + if(NULL == socksproxy) { + failf(data, "memory shortage"); + result = CURLE_OUT_OF_MEMORY; + goto out; + } + } + + if(!data->set.str[STRING_NOPROXY]) { + const char *p = "no_proxy"; + no_proxy = curl_getenv(p); + if(!no_proxy) { + p = "NO_PROXY"; + no_proxy = curl_getenv(p); + } + if(no_proxy) { + infof(conn->data, "Uses proxy env variable %s == '%s'\n", p, no_proxy); + } + } + + if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY] ? + data->set.str[STRING_NOPROXY] : no_proxy)) { + Curl_safefree(proxy); + Curl_safefree(socksproxy); + } +#ifndef CURL_DISABLE_HTTP + else if(!proxy && !socksproxy) + /* if the host is not in the noproxy list, detect proxy. */ + proxy = detect_proxy(conn); +#endif /* CURL_DISABLE_HTTP */ + + Curl_safefree(no_proxy); + +#ifdef USE_UNIX_SOCKETS + /* For the time being do not mix proxy and unix domain sockets. See #1274 */ + if(proxy && conn->unix_domain_socket) { + free(proxy); + proxy = NULL; + } +#endif + + if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) { + free(proxy); /* Don't bother with an empty proxy string or if the + protocol doesn't work with network */ + proxy = NULL; + } + if(socksproxy && (!*socksproxy || + (conn->handler->flags & PROTOPT_NONETWORK))) { + free(socksproxy); /* Don't bother with an empty socks proxy string or if + the protocol doesn't work with network */ + socksproxy = NULL; + } + + /*********************************************************************** + * If this is supposed to use a proxy, we need to figure out the proxy host + * name, proxy type and port number, so that we can re-use an existing + * connection that may exist registered to the same proxy host. + ***********************************************************************/ + if(proxy || socksproxy) { + if(proxy) { + result = parse_proxy(data, conn, proxy, conn->http_proxy.proxytype); + Curl_safefree(proxy); /* parse_proxy copies the proxy string */ + if(result) + goto out; + } + + if(socksproxy) { + result = parse_proxy(data, conn, socksproxy, + conn->socks_proxy.proxytype); + /* parse_proxy copies the socks proxy string */ + Curl_safefree(socksproxy); + if(result) + goto out; + } + + if(conn->http_proxy.host.rawalloc) { +#ifdef CURL_DISABLE_HTTP + /* asking for a HTTP proxy is a bit funny when HTTP is disabled... */ + result = CURLE_UNSUPPORTED_PROTOCOL; + goto out; +#else + /* force this connection's protocol to become HTTP if compatible */ + if(!(conn->handler->protocol & PROTO_FAMILY_HTTP)) { + if((conn->handler->flags & PROTOPT_PROXY_AS_HTTP) && + !conn->bits.tunnel_proxy) + conn->handler = &Curl_handler_http; + else + /* if not converting to HTTP over the proxy, enforce tunneling */ + conn->bits.tunnel_proxy = TRUE; + } + conn->bits.httpproxy = TRUE; +#endif + } + else { + conn->bits.httpproxy = FALSE; /* not a HTTP proxy */ + conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */ + } + + if(conn->socks_proxy.host.rawalloc) { + if(!conn->http_proxy.host.rawalloc) { + /* once a socks proxy */ + if(!conn->socks_proxy.user) { + conn->socks_proxy.user = conn->http_proxy.user; + conn->http_proxy.user = NULL; + Curl_safefree(conn->socks_proxy.passwd); + conn->socks_proxy.passwd = conn->http_proxy.passwd; + conn->http_proxy.passwd = NULL; + } + } + conn->bits.socksproxy = TRUE; + } + else + conn->bits.socksproxy = FALSE; /* not a socks proxy */ + } + else { + conn->bits.socksproxy = FALSE; + conn->bits.httpproxy = FALSE; + } + conn->bits.proxy = conn->bits.httpproxy || conn->bits.socksproxy; + + if(!conn->bits.proxy) { + /* we aren't using the proxy after all... */ + conn->bits.proxy = FALSE; + conn->bits.httpproxy = FALSE; + conn->bits.socksproxy = FALSE; + conn->bits.proxy_user_passwd = FALSE; + conn->bits.tunnel_proxy = FALSE; + } + +out: + + free(socksproxy); + free(proxy); + return result; +} +#endif /* CURL_DISABLE_PROXY */ + +/* + * Curl_parse_login_details() + * + * This is used to parse a login string for user name, password and options in + * the following formats: + * + * user + * user:password + * user:password;options + * user;options + * user;options:password + * :password + * :password;options + * ;options + * ;options:password + * + * Parameters: + * + * login [in] - The login string. + * len [in] - The length of the login string. + * userp [in/out] - The address where a pointer to newly allocated memory + * holding the user will be stored upon completion. + * passwdp [in/out] - The address where a pointer to newly allocated memory + * holding the password will be stored upon completion. + * optionsp [in/out] - The address where a pointer to newly allocated memory + * holding the options will be stored upon completion. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_parse_login_details(const char *login, const size_t len, + char **userp, char **passwdp, + char **optionsp) +{ + CURLcode result = CURLE_OK; + char *ubuf = NULL; + char *pbuf = NULL; + char *obuf = NULL; + const char *psep = NULL; + const char *osep = NULL; + size_t ulen; + size_t plen; + size_t olen; + + /* Attempt to find the password separator */ + if(passwdp) { + psep = strchr(login, ':'); + + /* Within the constraint of the login string */ + if(psep >= login + len) + psep = NULL; + } + + /* Attempt to find the options separator */ + if(optionsp) { + osep = strchr(login, ';'); + + /* Within the constraint of the login string */ + if(osep >= login + len) + osep = NULL; + } + + /* Calculate the portion lengths */ + ulen = (psep ? + (size_t)(osep && psep > osep ? osep - login : psep - login) : + (osep ? (size_t)(osep - login) : len)); + plen = (psep ? + (osep && osep > psep ? (size_t)(osep - psep) : + (size_t)(login + len - psep)) - 1 : 0); + olen = (osep ? + (psep && psep > osep ? (size_t)(psep - osep) : + (size_t)(login + len - osep)) - 1 : 0); + + /* Allocate the user portion buffer */ + if(userp && ulen) { + ubuf = malloc(ulen + 1); + if(!ubuf) + result = CURLE_OUT_OF_MEMORY; + } + + /* Allocate the password portion buffer */ + if(!result && passwdp && plen) { + pbuf = malloc(plen + 1); + if(!pbuf) { + free(ubuf); + result = CURLE_OUT_OF_MEMORY; + } + } + + /* Allocate the options portion buffer */ + if(!result && optionsp && olen) { + obuf = malloc(olen + 1); + if(!obuf) { + free(pbuf); + free(ubuf); + result = CURLE_OUT_OF_MEMORY; + } + } + + if(!result) { + /* Store the user portion if necessary */ + if(ubuf) { + memcpy(ubuf, login, ulen); + ubuf[ulen] = '\0'; + Curl_safefree(*userp); + *userp = ubuf; + } + + /* Store the password portion if necessary */ + if(pbuf) { + memcpy(pbuf, psep + 1, plen); + pbuf[plen] = '\0'; + Curl_safefree(*passwdp); + *passwdp = pbuf; + } + + /* Store the options portion if necessary */ + if(obuf) { + memcpy(obuf, osep + 1, olen); + obuf[olen] = '\0'; + Curl_safefree(*optionsp); + *optionsp = obuf; + } + } + + return result; +} + +/************************************************************* + * Figure out the remote port number and fix it in the URL + * + * No matter if we use a proxy or not, we have to figure out the remote + * port number of various reasons. + * + * The port number embedded in the URL is replaced, if necessary. + *************************************************************/ +static CURLcode parse_remote_port(struct Curl_easy *data, + struct connectdata *conn) +{ + + if(data->set.use_port && data->state.allow_port) { + /* if set, we use this instead of the port possibly given in the URL */ + char portbuf[16]; + CURLUcode uc; + conn->remote_port = (unsigned short)data->set.use_port; + msnprintf(portbuf, sizeof(portbuf), "%d", conn->remote_port); + uc = curl_url_set(data->state.uh, CURLUPART_PORT, portbuf, 0); + if(uc) + return CURLE_OUT_OF_MEMORY; + } + + return CURLE_OK; +} + +/* + * Override the login details from the URL with that in the CURLOPT_USERPWD + * option or a .netrc file, if applicable. + */ +static CURLcode override_login(struct Curl_easy *data, + struct connectdata *conn, + char **userp, char **passwdp, char **optionsp) +{ + bool user_changed = FALSE; + bool passwd_changed = FALSE; + CURLUcode uc; + + if(data->set.use_netrc == CURL_NETRC_REQUIRED && conn->bits.user_passwd) { + /* ignore user+password in the URL */ + if(*userp) { + Curl_safefree(*userp); + user_changed = TRUE; + } + if(*passwdp) { + Curl_safefree(*passwdp); + passwd_changed = TRUE; + } + conn->bits.user_passwd = FALSE; /* disable user+password */ + } + + if(data->set.str[STRING_USERNAME]) { + free(*userp); + *userp = strdup(data->set.str[STRING_USERNAME]); + if(!*userp) + return CURLE_OUT_OF_MEMORY; + conn->bits.user_passwd = TRUE; /* enable user+password */ + user_changed = TRUE; + } + + if(data->set.str[STRING_PASSWORD]) { + free(*passwdp); + *passwdp = strdup(data->set.str[STRING_PASSWORD]); + if(!*passwdp) + return CURLE_OUT_OF_MEMORY; + conn->bits.user_passwd = TRUE; /* enable user+password */ + passwd_changed = TRUE; + } + + if(data->set.str[STRING_OPTIONS]) { + free(*optionsp); + *optionsp = strdup(data->set.str[STRING_OPTIONS]); + if(!*optionsp) + return CURLE_OUT_OF_MEMORY; + } + + conn->bits.netrc = FALSE; + if(data->set.use_netrc != CURL_NETRC_IGNORED && + (!*userp || !**userp || !*passwdp || !**passwdp)) { + bool netrc_user_changed = FALSE; + bool netrc_passwd_changed = FALSE; + int ret; + + ret = Curl_parsenetrc(conn->host.name, + userp, passwdp, + &netrc_user_changed, &netrc_passwd_changed, + data->set.str[STRING_NETRC_FILE]); + if(ret > 0) { + infof(data, "Couldn't find host %s in the " + DOT_CHAR "netrc file; using defaults\n", + conn->host.name); + } + else if(ret < 0) { + return CURLE_OUT_OF_MEMORY; + } + else { + /* set bits.netrc TRUE to remember that we got the name from a .netrc + file, so that it is safe to use even if we followed a Location: to a + different host or similar. */ + conn->bits.netrc = TRUE; + conn->bits.user_passwd = TRUE; /* enable user+password */ + + if(netrc_user_changed) { + user_changed = TRUE; + } + if(netrc_passwd_changed) { + passwd_changed = TRUE; + } + } + } + + /* for updated strings, we update them in the URL */ + if(user_changed) { + uc = curl_url_set(data->state.uh, CURLUPART_USER, *userp, 0); + if(uc) + return Curl_uc_to_curlcode(uc); + } + if(passwd_changed) { + uc = curl_url_set(data->state.uh, CURLUPART_PASSWORD, *passwdp, 0); + if(uc) + return Curl_uc_to_curlcode(uc); + } + return CURLE_OK; +} + +/* + * Set the login details so they're available in the connection + */ +static CURLcode set_login(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + const char *setuser = CURL_DEFAULT_USER; + const char *setpasswd = CURL_DEFAULT_PASSWORD; + + /* If our protocol needs a password and we have none, use the defaults */ + if((conn->handler->flags & PROTOPT_NEEDSPWD) && !conn->bits.user_passwd) + ; + else { + setuser = ""; + setpasswd = ""; + } + /* Store the default user */ + if(!conn->user) { + conn->user = strdup(setuser); + if(!conn->user) + return CURLE_OUT_OF_MEMORY; + } + + /* Store the default password */ + if(!conn->passwd) { + conn->passwd = strdup(setpasswd); + if(!conn->passwd) + result = CURLE_OUT_OF_MEMORY; + } + + /* if there's a user without password, consider password blank */ + if(conn->user && !conn->passwd) { + conn->passwd = strdup(""); + if(!conn->passwd) + result = CURLE_OUT_OF_MEMORY; + } + + return result; +} + +/* + * Parses a "host:port" string to connect to. + * The hostname and the port may be empty; in this case, NULL is returned for + * the hostname and -1 for the port. + */ +static CURLcode parse_connect_to_host_port(struct Curl_easy *data, + const char *host, + char **hostname_result, + int *port_result) +{ + char *host_dup; + char *hostptr; + char *host_portno; + char *portptr; + int port = -1; + +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) data; +#endif + + *hostname_result = NULL; + *port_result = -1; + + if(!host || !*host) + return CURLE_OK; + + host_dup = strdup(host); + if(!host_dup) + return CURLE_OUT_OF_MEMORY; + + hostptr = host_dup; + + /* start scanning for port number at this point */ + portptr = hostptr; + + /* detect and extract RFC6874-style IPv6-addresses */ + if(*hostptr == '[') { +#ifdef ENABLE_IPV6 + char *ptr = ++hostptr; /* advance beyond the initial bracket */ + while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':') || (*ptr == '.'))) + ptr++; + if(*ptr == '%') { + /* There might be a zone identifier */ + if(strncmp("%25", ptr, 3)) + infof(data, "Please URL encode %% as %%25, see RFC 6874.\n"); + ptr++; + /* Allow unreserved characters as defined in RFC 3986 */ + while(*ptr && (ISALPHA(*ptr) || ISXDIGIT(*ptr) || (*ptr == '-') || + (*ptr == '.') || (*ptr == '_') || (*ptr == '~'))) + ptr++; + } + if(*ptr == ']') + /* yeps, it ended nicely with a bracket as well */ + *ptr++ = '\0'; + else + infof(data, "Invalid IPv6 address format\n"); + portptr = ptr; + /* Note that if this didn't end with a bracket, we still advanced the + * hostptr first, but I can't see anything wrong with that as no host + * name nor a numeric can legally start with a bracket. + */ +#else + failf(data, "Use of IPv6 in *_CONNECT_TO without IPv6 support built-in!"); + free(host_dup); + return CURLE_NOT_BUILT_IN; +#endif + } + + /* Get port number off server.com:1080 */ + host_portno = strchr(portptr, ':'); + if(host_portno) { + char *endp = NULL; + *host_portno = '\0'; /* cut off number from host name */ + host_portno++; + if(*host_portno) { + long portparse = strtol(host_portno, &endp, 10); + if((endp && *endp) || (portparse < 0) || (portparse > 65535)) { + infof(data, "No valid port number in connect to host string (%s)\n", + host_portno); + hostptr = NULL; + port = -1; + } + else + port = (int)portparse; /* we know it will fit */ + } + } + + /* now, clone the cleaned host name */ + if(hostptr) { + *hostname_result = strdup(hostptr); + if(!*hostname_result) { + free(host_dup); + return CURLE_OUT_OF_MEMORY; + } + } + + *port_result = port; + + free(host_dup); + return CURLE_OK; +} + +/* + * Parses one "connect to" string in the form: + * "HOST:PORT:CONNECT-TO-HOST:CONNECT-TO-PORT". + */ +static CURLcode parse_connect_to_string(struct Curl_easy *data, + struct connectdata *conn, + const char *conn_to_host, + char **host_result, + int *port_result) +{ + CURLcode result = CURLE_OK; + const char *ptr = conn_to_host; + int host_match = FALSE; + int port_match = FALSE; + + *host_result = NULL; + *port_result = -1; + + if(*ptr == ':') { + /* an empty hostname always matches */ + host_match = TRUE; + ptr++; + } + else { + /* check whether the URL's hostname matches */ + size_t hostname_to_match_len; + char *hostname_to_match = aprintf("%s%s%s", + conn->bits.ipv6_ip ? "[" : "", + conn->host.name, + conn->bits.ipv6_ip ? "]" : ""); + if(!hostname_to_match) + return CURLE_OUT_OF_MEMORY; + hostname_to_match_len = strlen(hostname_to_match); + host_match = strncasecompare(ptr, hostname_to_match, + hostname_to_match_len); + free(hostname_to_match); + ptr += hostname_to_match_len; + + host_match = host_match && *ptr == ':'; + ptr++; + } + + if(host_match) { + if(*ptr == ':') { + /* an empty port always matches */ + port_match = TRUE; + ptr++; + } + else { + /* check whether the URL's port matches */ + char *ptr_next = strchr(ptr, ':'); + if(ptr_next) { + char *endp = NULL; + long port_to_match = strtol(ptr, &endp, 10); + if((endp == ptr_next) && (port_to_match == conn->remote_port)) { + port_match = TRUE; + ptr = ptr_next + 1; + } + } + } + } + + if(host_match && port_match) { + /* parse the hostname and port to connect to */ + result = parse_connect_to_host_port(data, ptr, host_result, port_result); + } + + return result; +} + +/* + * Processes all strings in the "connect to" slist, and uses the "connect + * to host" and "connect to port" of the first string that matches. + */ +static CURLcode parse_connect_to_slist(struct Curl_easy *data, + struct connectdata *conn, + struct curl_slist *conn_to_host) +{ + CURLcode result = CURLE_OK; + char *host = NULL; + int port = -1; + + while(conn_to_host && !host && port == -1) { + result = parse_connect_to_string(data, conn, conn_to_host->data, + &host, &port); + if(result) + return result; + + if(host && *host) { + conn->conn_to_host.rawalloc = host; + conn->conn_to_host.name = host; + conn->bits.conn_to_host = TRUE; + + infof(data, "Connecting to hostname: %s\n", host); + } + else { + /* no "connect to host" */ + conn->bits.conn_to_host = FALSE; + Curl_safefree(host); + } + + if(port >= 0) { + conn->conn_to_port = port; + conn->bits.conn_to_port = TRUE; + infof(data, "Connecting to port: %d\n", port); + } + else { + /* no "connect to port" */ + conn->bits.conn_to_port = FALSE; + port = -1; + } + + conn_to_host = conn_to_host->next; + } + +#ifdef USE_ALTSVC + if(data->asi && !host && (port == -1) && + (conn->handler->protocol == CURLPROTO_HTTPS)) { + /* no connect_to match, try alt-svc! */ + const char *nhost; + int nport; + enum alpnid nalpnid; + bool hit; + host = conn->host.rawalloc; + hit = Curl_altsvc_lookup(data->asi, + ALPN_h1, host, conn->remote_port, /* from */ + &nalpnid, &nhost, &nport /* to */); + if(hit) { + char *hostd = strdup((char *)nhost); + if(!hostd) + return CURLE_OUT_OF_MEMORY; + conn->conn_to_host.rawalloc = hostd; + conn->conn_to_host.name = hostd; + conn->bits.conn_to_host = TRUE; + conn->conn_to_port = nport; + conn->bits.conn_to_port = TRUE; + infof(data, "Alt-svc connecting from [%s]%s:%d to [%s]%s:%d\n", + Curl_alpnid2str(ALPN_h1), host, conn->remote_port, + Curl_alpnid2str(nalpnid), hostd, nport); + } + } +#endif + + return result; +} + +/************************************************************* + * Resolve the address of the server or proxy + *************************************************************/ +static CURLcode resolve_server(struct Curl_easy *data, + struct connectdata *conn, + bool *async) +{ + CURLcode result = CURLE_OK; + timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE); + + DEBUGASSERT(conn); + DEBUGASSERT(data); + /************************************************************* + * Resolve the name of the server or proxy + *************************************************************/ + if(conn->bits.reuse) + /* We're reusing the connection - no need to resolve anything, and + idnconvert_hostname() was called already in create_conn() for the re-use + case. */ + *async = FALSE; + + else { + /* this is a fresh connect */ + int rc; + struct Curl_dns_entry *hostaddr; + +#ifdef USE_UNIX_SOCKETS + if(conn->unix_domain_socket) { + /* Unix domain sockets are local. The host gets ignored, just use the + * specified domain socket address. Do not cache "DNS entries". There is + * no DNS involved and we already have the filesystem path available */ + const char *path = conn->unix_domain_socket; + + hostaddr = calloc(1, sizeof(struct Curl_dns_entry)); + if(!hostaddr) + result = CURLE_OUT_OF_MEMORY; + else { + bool longpath = FALSE; + hostaddr->addr = Curl_unix2addr(path, &longpath, + conn->abstract_unix_socket); + if(hostaddr->addr) + hostaddr->inuse++; + else { + /* Long paths are not supported for now */ + if(longpath) { + failf(data, "Unix socket path too long: '%s'", path); + result = CURLE_COULDNT_RESOLVE_HOST; + } + else + result = CURLE_OUT_OF_MEMORY; + free(hostaddr); + hostaddr = NULL; + } + } + } + else +#endif + if(!conn->bits.proxy) { + struct hostname *connhost; + if(conn->bits.conn_to_host) + connhost = &conn->conn_to_host; + else + connhost = &conn->host; + + /* If not connecting via a proxy, extract the port from the URL, if it is + * there, thus overriding any defaults that might have been set above. */ + if(conn->bits.conn_to_port) + conn->port = conn->conn_to_port; + else + conn->port = conn->remote_port; + + /* Resolve target host right on */ + conn->hostname_resolve = strdup(connhost->name); + if(!conn->hostname_resolve) + return CURLE_OUT_OF_MEMORY; + rc = Curl_resolv_timeout(conn, conn->hostname_resolve, (int)conn->port, + &hostaddr, timeout_ms); + if(rc == CURLRESOLV_PENDING) + *async = TRUE; + + else if(rc == CURLRESOLV_TIMEDOUT) + result = CURLE_OPERATION_TIMEDOUT; + + else if(!hostaddr) { + failf(data, "Couldn't resolve host '%s'", connhost->dispname); + result = CURLE_COULDNT_RESOLVE_HOST; + /* don't return yet, we need to clean up the timeout first */ + } + } + else { + /* This is a proxy that hasn't been resolved yet. */ + + struct hostname * const host = conn->bits.socksproxy ? + &conn->socks_proxy.host : &conn->http_proxy.host; + + /* resolve proxy */ + conn->hostname_resolve = strdup(host->name); + if(!conn->hostname_resolve) + return CURLE_OUT_OF_MEMORY; + rc = Curl_resolv_timeout(conn, conn->hostname_resolve, (int)conn->port, + &hostaddr, timeout_ms); + + if(rc == CURLRESOLV_PENDING) + *async = TRUE; + + else if(rc == CURLRESOLV_TIMEDOUT) + result = CURLE_OPERATION_TIMEDOUT; + + else if(!hostaddr) { + failf(data, "Couldn't resolve proxy '%s'", host->dispname); + result = CURLE_COULDNT_RESOLVE_PROXY; + /* don't return yet, we need to clean up the timeout first */ + } + } + DEBUGASSERT(conn->dns_entry == NULL); + conn->dns_entry = hostaddr; + } + + return result; +} + +/* + * Cleanup the connection just allocated before we can move along and use the + * previously existing one. All relevant data is copied over and old_conn is + * ready for freeing once this function returns. + */ +static void reuse_conn(struct connectdata *old_conn, + struct connectdata *conn) +{ + free_idnconverted_hostname(&old_conn->http_proxy.host); + free_idnconverted_hostname(&old_conn->socks_proxy.host); + + free(old_conn->http_proxy.host.rawalloc); + free(old_conn->socks_proxy.host.rawalloc); + + /* free the SSL config struct from this connection struct as this was + allocated in vain and is targeted for destruction */ + Curl_free_primary_ssl_config(&old_conn->ssl_config); + Curl_free_primary_ssl_config(&old_conn->proxy_ssl_config); + + conn->data = old_conn->data; + + /* get the user+password information from the old_conn struct since it may + * be new for this request even when we re-use an existing connection */ + conn->bits.user_passwd = old_conn->bits.user_passwd; + if(conn->bits.user_passwd) { + /* use the new user name and password though */ + Curl_safefree(conn->user); + Curl_safefree(conn->passwd); + conn->user = old_conn->user; + conn->passwd = old_conn->passwd; + old_conn->user = NULL; + old_conn->passwd = NULL; + } + + conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd; + if(conn->bits.proxy_user_passwd) { + /* use the new proxy user name and proxy password though */ + Curl_safefree(conn->http_proxy.user); + Curl_safefree(conn->socks_proxy.user); + Curl_safefree(conn->http_proxy.passwd); + Curl_safefree(conn->socks_proxy.passwd); + conn->http_proxy.user = old_conn->http_proxy.user; + conn->socks_proxy.user = old_conn->socks_proxy.user; + conn->http_proxy.passwd = old_conn->http_proxy.passwd; + conn->socks_proxy.passwd = old_conn->socks_proxy.passwd; + old_conn->http_proxy.user = NULL; + old_conn->socks_proxy.user = NULL; + old_conn->http_proxy.passwd = NULL; + old_conn->socks_proxy.passwd = NULL; + } + + /* host can change, when doing keepalive with a proxy or if the case is + different this time etc */ + free_idnconverted_hostname(&conn->host); + free_idnconverted_hostname(&conn->conn_to_host); + Curl_safefree(conn->host.rawalloc); + Curl_safefree(conn->conn_to_host.rawalloc); + conn->host = old_conn->host; + conn->conn_to_host = old_conn->conn_to_host; + conn->conn_to_port = old_conn->conn_to_port; + conn->remote_port = old_conn->remote_port; + Curl_safefree(conn->hostname_resolve); + + conn->hostname_resolve = old_conn->hostname_resolve; + old_conn->hostname_resolve = NULL; + + /* persist connection info in session handle */ + Curl_persistconninfo(conn); + + conn_reset_all_postponed_data(old_conn); /* free buffers */ + + /* re-use init */ + conn->bits.reuse = TRUE; /* yes, we're re-using here */ + + Curl_safefree(old_conn->user); + Curl_safefree(old_conn->passwd); + Curl_safefree(old_conn->options); + Curl_safefree(old_conn->http_proxy.user); + Curl_safefree(old_conn->socks_proxy.user); + Curl_safefree(old_conn->http_proxy.passwd); + Curl_safefree(old_conn->socks_proxy.passwd); + Curl_safefree(old_conn->localdev); + Curl_llist_destroy(&old_conn->easyq, NULL); + +#ifdef USE_UNIX_SOCKETS + Curl_safefree(old_conn->unix_domain_socket); +#endif +} + +/** + * create_conn() sets up a new connectdata struct, or re-uses an already + * existing one, and resolves host name. + * + * if this function returns CURLE_OK and *async is set to TRUE, the resolve + * response will be coming asynchronously. If *async is FALSE, the name is + * already resolved. + * + * @param data The sessionhandle pointer + * @param in_connect is set to the next connection data pointer + * @param async is set TRUE when an async DNS resolution is pending + * @see Curl_setup_conn() + * + * *NOTE* this function assigns the conn->data pointer! + */ + +static CURLcode create_conn(struct Curl_easy *data, + struct connectdata **in_connect, + bool *async) +{ + CURLcode result = CURLE_OK; + struct connectdata *conn; + struct connectdata *conn_temp = NULL; + bool reuse; + bool connections_available = TRUE; + bool force_reuse = FALSE; + bool waitpipe = FALSE; + size_t max_host_connections = Curl_multi_max_host_connections(data->multi); + size_t max_total_connections = Curl_multi_max_total_connections(data->multi); + + *async = FALSE; + *in_connect = NULL; + + /************************************************************* + * Check input data + *************************************************************/ + if(!data->change.url) { + result = CURLE_URL_MALFORMAT; + goto out; + } + + /* First, split up the current URL in parts so that we can use the + parts for checking against the already present connections. In order + to not have to modify everything at once, we allocate a temporary + connection data struct and fill in for comparison purposes. */ + conn = allocate_conn(data); + + if(!conn) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } + + /* We must set the return variable as soon as possible, so that our + parent can cleanup any possible allocs we may have done before + any failure */ + *in_connect = conn; + + result = parseurlandfillconn(data, conn); + if(result) + goto out; + + if(data->set.str[STRING_BEARER]) { + conn->oauth_bearer = strdup(data->set.str[STRING_BEARER]); + if(!conn->oauth_bearer) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } + } + +#ifdef USE_UNIX_SOCKETS + if(data->set.str[STRING_UNIX_SOCKET_PATH]) { + conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]); + if(conn->unix_domain_socket == NULL) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } + conn->abstract_unix_socket = data->set.abstract_unix_socket; + } +#endif + + /* After the unix socket init but before the proxy vars are used, parse and + initialize the proxy vars */ +#ifndef CURL_DISABLE_PROXY + result = create_conn_helper_init_proxy(conn); + if(result) + goto out; +#endif + + /************************************************************* + * If the protocol is using SSL and HTTP proxy is used, we set + * the tunnel_proxy bit. + *************************************************************/ + if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy) + conn->bits.tunnel_proxy = TRUE; + + /************************************************************* + * Figure out the remote port number and fix it in the URL + *************************************************************/ + result = parse_remote_port(data, conn); + if(result) + goto out; + + /* Check for overridden login details and set them accordingly so they + they are known when protocol->setup_connection is called! */ + result = override_login(data, conn, &conn->user, &conn->passwd, + &conn->options); + if(result) + goto out; + + result = set_login(conn); /* default credentials */ + if(result) + goto out; + + /************************************************************* + * Process the "connect to" linked list of hostname/port mappings. + * Do this after the remote port number has been fixed in the URL. + *************************************************************/ + result = parse_connect_to_slist(data, conn, data->set.connect_to); + if(result) + goto out; + + /************************************************************* + * IDN-convert the hostnames + *************************************************************/ + result = idnconvert_hostname(conn, &conn->host); + if(result) + goto out; + if(conn->bits.conn_to_host) { + result = idnconvert_hostname(conn, &conn->conn_to_host); + if(result) + goto out; + } + if(conn->bits.httpproxy) { + result = idnconvert_hostname(conn, &conn->http_proxy.host); + if(result) + goto out; + } + if(conn->bits.socksproxy) { + result = idnconvert_hostname(conn, &conn->socks_proxy.host); + if(result) + goto out; + } + + /************************************************************* + * Check whether the host and the "connect to host" are equal. + * Do this after the hostnames have been IDN-converted. + *************************************************************/ + if(conn->bits.conn_to_host && + strcasecompare(conn->conn_to_host.name, conn->host.name)) { + conn->bits.conn_to_host = FALSE; + } + + /************************************************************* + * Check whether the port and the "connect to port" are equal. + * Do this after the remote port number has been fixed in the URL. + *************************************************************/ + if(conn->bits.conn_to_port && conn->conn_to_port == conn->remote_port) { + conn->bits.conn_to_port = FALSE; + } + + /************************************************************* + * If the "connect to" feature is used with an HTTP proxy, + * we set the tunnel_proxy bit. + *************************************************************/ + if((conn->bits.conn_to_host || conn->bits.conn_to_port) && + conn->bits.httpproxy) + conn->bits.tunnel_proxy = TRUE; + + /************************************************************* + * Setup internals depending on protocol. Needs to be done after + * we figured out what/if proxy to use. + *************************************************************/ + result = setup_connection_internals(conn); + if(result) + goto out; + + conn->recv[FIRSTSOCKET] = Curl_recv_plain; + conn->send[FIRSTSOCKET] = Curl_send_plain; + conn->recv[SECONDARYSOCKET] = Curl_recv_plain; + conn->send[SECONDARYSOCKET] = Curl_send_plain; + + conn->bits.tcp_fastopen = data->set.tcp_fastopen; + + /*********************************************************************** + * file: is a special case in that it doesn't need a network connection + ***********************************************************************/ +#ifndef CURL_DISABLE_FILE + if(conn->handler->flags & PROTOPT_NONETWORK) { + bool done; + /* this is supposed to be the connect function so we better at least check + that the file is present here! */ + DEBUGASSERT(conn->handler->connect_it); + Curl_persistconninfo(conn); + result = conn->handler->connect_it(conn, &done); + + /* Setup a "faked" transfer that'll do nothing */ + if(!result) { + conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */ + + result = Curl_conncache_add_conn(data->state.conn_cache, conn); + if(result) + goto out; + + /* + * Setup whatever necessary for a resumed transfer + */ + result = setup_range(data); + if(result) { + DEBUGASSERT(conn->handler->done); + /* we ignore the return code for the protocol-specific DONE */ + (void)conn->handler->done(conn, result, FALSE); + goto out; + } + Curl_attach_connnection(data, conn); + Curl_setup_transfer(data, -1, -1, FALSE, -1); + } + + /* since we skip do_init() */ + Curl_init_do(data, conn); + + goto out; + } +#endif + + /* Get a cloned copy of the SSL config situation stored in the + connection struct. But to get this going nicely, we must first make + sure that the strings in the master copy are pointing to the correct + strings in the session handle strings array! + + Keep in mind that the pointers in the master copy are pointing to strings + that will be freed as part of the Curl_easy struct, but all cloned + copies will be separately allocated. + */ + data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_ORIG]; + data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY]; + data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_ORIG]; + data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY]; + data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE]; + data->set.proxy_ssl.primary.random_file = + data->set.str[STRING_SSL_RANDOM_FILE]; + data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET]; + data->set.proxy_ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET]; + data->set.ssl.primary.cipher_list = + data->set.str[STRING_SSL_CIPHER_LIST_ORIG]; + data->set.proxy_ssl.primary.cipher_list = + data->set.str[STRING_SSL_CIPHER_LIST_PROXY]; + data->set.ssl.primary.cipher_list13 = + data->set.str[STRING_SSL_CIPHER13_LIST_ORIG]; + data->set.proxy_ssl.primary.cipher_list13 = + data->set.str[STRING_SSL_CIPHER13_LIST_PROXY]; + + data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_ORIG]; + data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY]; + data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_ORIG]; + data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY]; + data->set.ssl.cert = data->set.str[STRING_CERT_ORIG]; + data->set.proxy_ssl.cert = data->set.str[STRING_CERT_PROXY]; + data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE_ORIG]; + data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY]; + data->set.ssl.key = data->set.str[STRING_KEY_ORIG]; + data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY]; + data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE_ORIG]; + data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY]; + data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_ORIG]; + data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY]; + data->set.ssl.primary.clientcert = data->set.str[STRING_CERT_ORIG]; + data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY]; +#ifdef USE_TLS_SRP + data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_ORIG]; + data->set.proxy_ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY]; + data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_ORIG]; + data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY]; +#endif + + if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary, + &conn->ssl_config)) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } + + if(!Curl_clone_primary_ssl_config(&data->set.proxy_ssl.primary, + &conn->proxy_ssl_config)) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } + + prune_dead_connections(data); + + /************************************************************* + * Check the current list of connections to see if we can + * re-use an already existing one or if we have to create a + * new one. + *************************************************************/ + + DEBUGASSERT(conn->user); + DEBUGASSERT(conn->passwd); + + /* reuse_fresh is TRUE if we are told to use a new connection by force, but + we only acknowledge this option if this is not a re-used connection + already (which happens due to follow-location or during a HTTP + authentication phase). CONNECT_ONLY transfers also refuse reuse. */ + if((data->set.reuse_fresh && !data->state.this_is_a_follow) || + data->set.connect_only) + reuse = FALSE; + else + reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse, &waitpipe); + + /* If we found a reusable connection that is now marked as in use, we may + still want to open a new connection if we are multiplexing. */ + if(reuse && !force_reuse && IsMultiplexingPossible(data, conn_temp)) { + size_t multiplexed = CONN_INUSE(conn_temp); + if(multiplexed > 0) { + infof(data, "Found connection %ld, with %zu requests on it\n", + conn_temp->connection_id, multiplexed); + + if(Curl_conncache_bundle_size(conn_temp) < max_host_connections && + Curl_conncache_size(data) < max_total_connections) { + /* We want a new connection anyway */ + reuse = FALSE; + + infof(data, "We can reuse, but we want a new connection anyway\n"); + Curl_conncache_return_conn(conn_temp); + } + } + } + + if(reuse) { + /* + * We already have a connection for this, we got the former connection + * in the conn_temp variable and thus we need to cleanup the one we + * just allocated before we can move along and use the previously + * existing one. + */ + reuse_conn(conn, conn_temp); +#ifdef USE_SSL + free(conn->ssl_extra); +#endif + free(conn); /* we don't need this anymore */ + conn = conn_temp; + *in_connect = conn; + + infof(data, "Re-using existing connection! (#%ld) with %s %s\n", + conn->connection_id, + conn->bits.proxy?"proxy":"host", + conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname : + conn->http_proxy.host.name ? conn->http_proxy.host.dispname : + conn->host.dispname); + } + else { + /* We have decided that we want a new connection. However, we may not + be able to do that if we have reached the limit of how many + connections we are allowed to open. */ + + if(conn->handler->flags & PROTOPT_ALPN_NPN) { + /* The protocol wants it, so set the bits if enabled in the easy handle + (default) */ + if(data->set.ssl_enable_alpn) + conn->bits.tls_enable_alpn = TRUE; + if(data->set.ssl_enable_npn) + conn->bits.tls_enable_npn = TRUE; + } + + if(waitpipe) + /* There is a connection that *might* become usable for multiplexing + "soon", and we wait for that */ + connections_available = FALSE; + else { + /* this gets a lock on the conncache */ + struct connectbundle *bundle = + Curl_conncache_find_bundle(conn, data->state.conn_cache); + + if(max_host_connections > 0 && bundle && + (bundle->num_connections >= max_host_connections)) { + struct connectdata *conn_candidate; + + /* The bundle is full. Extract the oldest connection. */ + conn_candidate = Curl_conncache_extract_bundle(data, bundle); + Curl_conncache_unlock(data); + + if(conn_candidate) + (void)Curl_disconnect(data, conn_candidate, + /* dead_connection */ FALSE); + else { + infof(data, "No more connections allowed to host: %zu\n", + max_host_connections); + connections_available = FALSE; + } + } + else + Curl_conncache_unlock(data); + + } + + if(connections_available && + (max_total_connections > 0) && + (Curl_conncache_size(data) >= max_total_connections)) { + struct connectdata *conn_candidate; + + /* The cache is full. Let's see if we can kill a connection. */ + conn_candidate = Curl_conncache_extract_oldest(data); + if(conn_candidate) + (void)Curl_disconnect(data, conn_candidate, + /* dead_connection */ FALSE); + else { + infof(data, "No connections available in cache\n"); + connections_available = FALSE; + } + } + + if(!connections_available) { + infof(data, "No connections available.\n"); + + conn_free(conn); + *in_connect = NULL; + + result = CURLE_NO_CONNECTION_AVAILABLE; + goto out; + } + else { + /* + * This is a brand new connection, so let's store it in the connection + * cache of ours! + */ + result = Curl_conncache_add_conn(data->state.conn_cache, conn); + if(result) + goto out; + } + +#if defined(USE_NTLM) + /* If NTLM is requested in a part of this connection, make sure we don't + assume the state is fine as this is a fresh connection and NTLM is + connection based. */ + if((data->state.authhost.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) && + data->state.authhost.done) { + infof(data, "NTLM picked AND auth done set, clear picked!\n"); + data->state.authhost.picked = CURLAUTH_NONE; + data->state.authhost.done = FALSE; + } + + if((data->state.authproxy.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) && + data->state.authproxy.done) { + infof(data, "NTLM-proxy picked AND auth done set, clear picked!\n"); + data->state.authproxy.picked = CURLAUTH_NONE; + data->state.authproxy.done = FALSE; + } +#endif + } + + /* Setup and init stuff before DO starts, in preparing for the transfer. */ + Curl_init_do(data, conn); + + /* + * Setup whatever necessary for a resumed transfer + */ + result = setup_range(data); + if(result) + goto out; + + /* Continue connectdata initialization here. */ + + /* + * Inherit the proper values from the urldata struct AFTER we have arranged + * the persistent connection stuff + */ + conn->seek_func = data->set.seek_func; + conn->seek_client = data->set.seek_client; + + /************************************************************* + * Resolve the address of the server or proxy + *************************************************************/ + result = resolve_server(data, conn, async); + + /* Strip trailing dots. resolve_server copied the name. */ + strip_trailing_dot(&conn->host); + if(conn->bits.httpproxy) + strip_trailing_dot(&conn->http_proxy.host); + if(conn->bits.socksproxy) + strip_trailing_dot(&conn->socks_proxy.host); + if(conn->bits.conn_to_host) + strip_trailing_dot(&conn->conn_to_host); + +out: + return result; +} + +/* Curl_setup_conn() is called after the name resolve initiated in + * create_conn() is all done. + * + * Curl_setup_conn() also handles reused connections + * + * conn->data MUST already have been setup fine (in create_conn) + */ + +CURLcode Curl_setup_conn(struct connectdata *conn, + bool *protocol_done) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + Curl_pgrsTime(data, TIMER_NAMELOOKUP); + + if(conn->handler->flags & PROTOPT_NONETWORK) { + /* nothing to setup when not using a network */ + *protocol_done = TRUE; + return result; + } + *protocol_done = FALSE; /* default to not done */ + + /* set proxy_connect_closed to false unconditionally already here since it + is used strictly to provide extra information to a parent function in the + case of proxy CONNECT failures and we must make sure we don't have it + lingering set from a previous invoke */ + conn->bits.proxy_connect_closed = FALSE; + + /* + * Set user-agent. Used for HTTP, but since we can attempt to tunnel + * basically anything through a http proxy we can't limit this based on + * protocol. + */ + if(data->set.str[STRING_USERAGENT]) { + Curl_safefree(conn->allocptr.uagent); + conn->allocptr.uagent = + aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]); + if(!conn->allocptr.uagent) + return CURLE_OUT_OF_MEMORY; + } + + data->req.headerbytecount = 0; + +#ifdef CURL_DO_LINEEND_CONV + data->state.crlf_conversions = 0; /* reset CRLF conversion counter */ +#endif /* CURL_DO_LINEEND_CONV */ + + /* set start time here for timeout purposes in the connect procedure, it + is later set again for the progress meter purpose */ + conn->now = Curl_now(); + + if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) { + conn->bits.tcpconnect[FIRSTSOCKET] = FALSE; + result = Curl_connecthost(conn, conn->dns_entry); + if(result) + return result; + } + else { + Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */ + Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */ + conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; + *protocol_done = TRUE; + Curl_updateconninfo(conn, conn->sock[FIRSTSOCKET]); + Curl_verboseconnect(conn); + } + + conn->now = Curl_now(); /* time this *after* the connect is done, we set + this here perhaps a second time */ + return result; +} + +CURLcode Curl_connect(struct Curl_easy *data, + bool *asyncp, + bool *protocol_done) +{ + CURLcode result; + struct connectdata *conn; + + *asyncp = FALSE; /* assume synchronous resolves by default */ + + /* init the single-transfer specific data */ + Curl_free_request_state(data); + memset(&data->req, 0, sizeof(struct SingleRequest)); + data->req.maxdownload = -1; + + /* call the stuff that needs to be called */ + result = create_conn(data, &conn, asyncp); + + if(!result) { + if(CONN_INUSE(conn)) + /* multiplexed */ + *protocol_done = TRUE; + else if(!*asyncp) { + /* DNS resolution is done: that's either because this is a reused + connection, in which case DNS was unnecessary, or because DNS + really did finish already (synch resolver/fast async resolve) */ + result = Curl_setup_conn(conn, protocol_done); + } + } + + if(result == CURLE_NO_CONNECTION_AVAILABLE) { + return result; + } + else if(result && conn) { + /* We're not allowed to return failure with memory left allocated in the + connectdata struct, free those here */ + Curl_disconnect(data, conn, TRUE); + } + else if(!result && !data->conn) + /* FILE: transfers already have the connection attached */ + Curl_attach_connnection(data, conn); + + return result; +} + +/* + * Curl_init_do() inits the readwrite session. This is inited each time (in + * the DO function before the protocol-specific DO functions are invoked) for + * a transfer, sometimes multiple times on the same Curl_easy. Make sure + * nothing in here depends on stuff that are setup dynamically for the + * transfer. + * + * Allow this function to get called with 'conn' set to NULL. + */ + +CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn) +{ + struct SingleRequest *k = &data->req; + + if(conn) { + conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to + use */ + /* if the protocol used doesn't support wildcards, switch it off */ + if(data->state.wildcardmatch && + !(conn->handler->flags & PROTOPT_WILDCARD)) + data->state.wildcardmatch = FALSE; + } + + data->state.done = FALSE; /* *_done() is not called yet */ + data->state.expect100header = FALSE; + + + if(data->set.opt_no_body) + /* in HTTP lingo, no body means using the HEAD request... */ + data->set.httpreq = HTTPREQ_HEAD; + else if(HTTPREQ_HEAD == data->set.httpreq) + /* ... but if unset there really is no perfect method that is the + "opposite" of HEAD but in reality most people probably think GET + then. The important thing is that we can't let it remain HEAD if the + opt_no_body is set FALSE since then we'll behave wrong when getting + HTTP. */ + data->set.httpreq = HTTPREQ_GET; + + k->start = Curl_now(); /* start time */ + k->now = k->start; /* current time is now */ + k->header = TRUE; /* assume header */ + + k->bytecount = 0; + + k->buf = data->state.buffer; + k->hbufp = data->state.headerbuff; + k->ignorebody = FALSE; + + Curl_speedinit(data); + + Curl_pgrsSetUploadCounter(data, 0); + Curl_pgrsSetDownloadCounter(data, 0); + + return CURLE_OK; +} + +/* +* get_protocol_family() +* +* This is used to return the protocol family for a given protocol. +* +* Parameters: +* +* protocol [in] - A single bit protocol identifier such as HTTP or HTTPS. +* +* Returns the family as a single bit protocol identifier. +*/ + +static unsigned int get_protocol_family(unsigned int protocol) +{ + unsigned int family; + + switch(protocol) { + case CURLPROTO_HTTP: + case CURLPROTO_HTTPS: + family = CURLPROTO_HTTP; + break; + + case CURLPROTO_FTP: + case CURLPROTO_FTPS: + family = CURLPROTO_FTP; + break; + + case CURLPROTO_SCP: + family = CURLPROTO_SCP; + break; + + case CURLPROTO_SFTP: + family = CURLPROTO_SFTP; + break; + + case CURLPROTO_TELNET: + family = CURLPROTO_TELNET; + break; + + case CURLPROTO_LDAP: + case CURLPROTO_LDAPS: + family = CURLPROTO_LDAP; + break; + + case CURLPROTO_DICT: + family = CURLPROTO_DICT; + break; + + case CURLPROTO_FILE: + family = CURLPROTO_FILE; + break; + + case CURLPROTO_TFTP: + family = CURLPROTO_TFTP; + break; + + case CURLPROTO_IMAP: + case CURLPROTO_IMAPS: + family = CURLPROTO_IMAP; + break; + + case CURLPROTO_POP3: + case CURLPROTO_POP3S: + family = CURLPROTO_POP3; + break; + + case CURLPROTO_SMTP: + case CURLPROTO_SMTPS: + family = CURLPROTO_SMTP; + break; + + case CURLPROTO_RTSP: + family = CURLPROTO_RTSP; + break; + + case CURLPROTO_RTMP: + case CURLPROTO_RTMPS: + family = CURLPROTO_RTMP; + break; + + case CURLPROTO_RTMPT: + case CURLPROTO_RTMPTS: + family = CURLPROTO_RTMPT; + break; + + case CURLPROTO_RTMPE: + family = CURLPROTO_RTMPE; + break; + + case CURLPROTO_RTMPTE: + family = CURLPROTO_RTMPTE; + break; + + case CURLPROTO_GOPHER: + family = CURLPROTO_GOPHER; + break; + + case CURLPROTO_SMB: + case CURLPROTO_SMBS: + family = CURLPROTO_SMB; + break; + + default: + family = 0; + break; + } + + return family; +} + + +/* + * Wrapper to call functions in Curl_conncache_foreach() + * + * Returns always 0. + */ +static int conn_upkeep(struct connectdata *conn, + void *param) +{ + /* Param is unused. */ + (void)param; + + if(conn->handler->connection_check) { + /* Do a protocol-specific keepalive check on the connection. */ + conn->handler->connection_check(conn, CONNCHECK_KEEPALIVE); + } + + return 0; /* continue iteration */ +} + +CURLcode Curl_upkeep(struct conncache *conn_cache, + void *data) +{ + /* Loop over every connection and make connection alive. */ + Curl_conncache_foreach(data, + conn_cache, + data, + conn_upkeep); + return CURLE_OK; +} diff --git a/dependencies/cmcurl/lib/url.h b/dependencies/cmcurl/lib/url.h new file mode 100644 index 0000000..4db9e86 --- /dev/null +++ b/dependencies/cmcurl/lib/url.h @@ -0,0 +1,103 @@ +#ifndef HEADER_CURL_URL_H +#define HEADER_CURL_URL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#define READBUFFER_SIZE CURL_MAX_WRITE_SIZE +#define READBUFFER_MAX CURL_MAX_READ_SIZE +#define READBUFFER_MIN 1024 + +/* The default upload buffer size, should not be smaller than + CURL_MAX_WRITE_SIZE, as it needs to hold a full buffer as could be sent in + a write callback. + + The size was 16KB for many years but was bumped to 64KB because it makes + libcurl able to do significantly faster uploads in some circumstances. Even + larger buffers can help further, but this is deemed a fair memory/speed + compromise. */ +#define UPLOADBUFFER_DEFAULT 65536 +#define UPLOADBUFFER_MAX (2*1024*1024) +#define UPLOADBUFFER_MIN CURL_MAX_WRITE_SIZE + +/* + * Prototypes for library-wide functions provided by url.c + */ + +CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn); +CURLcode Curl_open(struct Curl_easy **curl); +CURLcode Curl_init_userdefined(struct Curl_easy *data); + +void Curl_freeset(struct Curl_easy * data); +/* free the URL pieces */ +void Curl_up_free(struct Curl_easy *data); +CURLcode Curl_uc_to_curlcode(CURLUcode uc); +CURLcode Curl_close(struct Curl_easy *data); /* opposite of curl_open() */ +CURLcode Curl_connect(struct Curl_easy *, bool *async, bool *protocol_connect); +CURLcode Curl_disconnect(struct Curl_easy *data, + struct connectdata *, bool dead_connection); +CURLcode Curl_protocol_connect(struct connectdata *conn, bool *done); +CURLcode Curl_protocol_connecting(struct connectdata *conn, bool *done); +CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done); +CURLcode Curl_setup_conn(struct connectdata *conn, + bool *protocol_done); +void Curl_free_request_state(struct Curl_easy *data); + +int Curl_protocol_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); +int Curl_doing_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); +CURLcode Curl_parse_login_details(const char *login, const size_t len, + char **userptr, char **passwdptr, + char **optionsptr); +void Curl_close_connections(struct Curl_easy *data); +CURLcode Curl_upkeep(struct conncache *conn_cache, void *data); + +const struct Curl_handler *Curl_builtin_scheme(const char *scheme); + +#define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */ +#define CURL_DEFAULT_HTTPS_PROXY_PORT 443 /* default https proxy port unless + specified */ + +CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex); + +#ifdef CURL_DISABLE_VERBOSE_STRINGS +#define Curl_verboseconnect(x) Curl_nop_stmt +#else +void Curl_verboseconnect(struct connectdata *conn); +#endif + +#define CONNECT_PROXY_SSL()\ + (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\ + !conn->bits.proxy_ssl_connected[sockindex]) + +#define CONNECT_FIRSTSOCKET_PROXY_SSL()\ + (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\ + !conn->bits.proxy_ssl_connected[FIRSTSOCKET]) + +#define CONNECT_SECONDARYSOCKET_PROXY_SSL()\ + (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\ + !conn->bits.proxy_ssl_connected[SECONDARYSOCKET]) + +#endif /* HEADER_CURL_URL_H */ diff --git a/dependencies/cmcurl/lib/urlapi-int.h b/dependencies/cmcurl/lib/urlapi-int.h new file mode 100644 index 0000000..5f059c2 --- /dev/null +++ b/dependencies/cmcurl/lib/urlapi-int.h @@ -0,0 +1,37 @@ +#ifndef HEADER_CURL_URLAPI_INT_H +#define HEADER_CURL_URLAPI_INT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" +/* scheme is not URL encoded, the longest libcurl supported ones are... */ +#define MAX_SCHEME_LEN 40 + +bool Curl_is_absolute_url(const char *url, char *scheme, size_t buflen); +char *Curl_concat_url(const char *base, const char *relurl); +size_t Curl_strlen_url(const char *url, bool relative); +void Curl_strcpy_url(char *output, const char *url, bool relative); + +#ifdef DEBUGBUILD +CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname); +#endif + +#endif /* HEADER_CURL_URLAPI_INT_H */ diff --git a/dependencies/cmcurl/lib/urlapi.c b/dependencies/cmcurl/lib/urlapi.c new file mode 100644 index 0000000..d07e4f5 --- /dev/null +++ b/dependencies/cmcurl/lib/urlapi.c @@ -0,0 +1,1440 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "urldata.h" +#include "urlapi-int.h" +#include "strcase.h" +#include "dotdot.h" +#include "url.h" +#include "escape.h" +#include "curl_ctype.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + + /* MSDOS/Windows style drive prefix, eg c: in c:foo */ +#define STARTS_WITH_DRIVE_PREFIX(str) \ + ((('a' <= str[0] && str[0] <= 'z') || \ + ('A' <= str[0] && str[0] <= 'Z')) && \ + (str[1] == ':')) + + /* MSDOS/Windows style drive prefix, optionally with + * a '|' instead of ':', followed by a slash or NUL */ +#define STARTS_WITH_URL_DRIVE_PREFIX(str) \ + ((('a' <= (str)[0] && (str)[0] <= 'z') || \ + ('A' <= (str)[0] && (str)[0] <= 'Z')) && \ + ((str)[1] == ':' || (str)[1] == '|') && \ + ((str)[2] == '/' || (str)[2] == '\\' || (str)[2] == 0)) + +/* Internal representation of CURLU. Point to URL-encoded strings. */ +struct Curl_URL { + char *scheme; + char *user; + char *password; + char *options; /* IMAP only? */ + char *host; + char *zoneid; /* for numerical IPv6 addresses */ + char *port; + char *path; + char *query; + char *fragment; + + char *scratch; /* temporary scratch area */ + long portnum; /* the numerical version */ +}; + +#define DEFAULT_SCHEME "https" + +static void free_urlhandle(struct Curl_URL *u) +{ + free(u->scheme); + free(u->user); + free(u->password); + free(u->options); + free(u->host); + free(u->zoneid); + free(u->port); + free(u->path); + free(u->query); + free(u->fragment); + free(u->scratch); +} + +/* move the full contents of one handle onto another and + free the original */ +static void mv_urlhandle(struct Curl_URL *from, + struct Curl_URL *to) +{ + free_urlhandle(to); + *to = *from; + free(from); +} + +/* + * Find the separator at the end of the host name, or the '?' in cases like + * http://www.url.com?id=2380 + */ +static const char *find_host_sep(const char *url) +{ + const char *sep; + const char *query; + + /* Find the start of the hostname */ + sep = strstr(url, "//"); + if(!sep) + sep = url; + else + sep += 2; + + query = strchr(sep, '?'); + sep = strchr(sep, '/'); + + if(!sep) + sep = url + strlen(url); + + if(!query) + query = url + strlen(url); + + return sep < query ? sep : query; +} + +/* + * Decide in an encoding-independent manner whether a character in an + * URL must be escaped. The same criterion must be used in strlen_url() + * and strcpy_url(). + */ +static bool urlchar_needs_escaping(int c) +{ + return !(ISCNTRL(c) || ISSPACE(c) || ISGRAPH(c)); +} + +/* + * strlen_url() returns the length of the given URL if the spaces within the + * URL were properly URL encoded. + * URL encoding should be skipped for host names, otherwise IDN resolution + * will fail. + */ +static size_t strlen_url(const char *url, bool relative) +{ + const unsigned char *ptr; + size_t newlen = 0; + bool left = TRUE; /* left side of the ? */ + const unsigned char *host_sep = (const unsigned char *) url; + + if(!relative) + host_sep = (const unsigned char *) find_host_sep(url); + + for(ptr = (unsigned char *)url; *ptr; ptr++) { + + if(ptr < host_sep) { + ++newlen; + continue; + } + + switch(*ptr) { + case '?': + left = FALSE; + /* FALLTHROUGH */ + default: + if(urlchar_needs_escaping(*ptr)) + newlen += 2; + newlen++; + break; + case ' ': + if(left) + newlen += 3; + else + newlen++; + break; + } + } + return newlen; +} + +/* strcpy_url() copies a url to a output buffer and URL-encodes the spaces in + * the source URL accordingly. + * URL encoding should be skipped for host names, otherwise IDN resolution + * will fail. + */ +static void strcpy_url(char *output, const char *url, bool relative) +{ + /* we must add this with whitespace-replacing */ + bool left = TRUE; + const unsigned char *iptr; + char *optr = output; + const unsigned char *host_sep = (const unsigned char *) url; + + if(!relative) + host_sep = (const unsigned char *) find_host_sep(url); + + for(iptr = (unsigned char *)url; /* read from here */ + *iptr; /* until zero byte */ + iptr++) { + + if(iptr < host_sep) { + *optr++ = *iptr; + continue; + } + + switch(*iptr) { + case '?': + left = FALSE; + /* FALLTHROUGH */ + default: + if(urlchar_needs_escaping(*iptr)) { + msnprintf(optr, 4, "%%%02x", *iptr); + optr += 3; + } + else + *optr++=*iptr; + break; + case ' ': + if(left) { + *optr++='%'; /* add a '%' */ + *optr++='2'; /* add a '2' */ + *optr++='0'; /* add a '0' */ + } + else + *optr++='+'; /* add a '+' here */ + break; + } + } + *optr = 0; /* zero terminate output buffer */ + +} + +/* + * Returns true if the given URL is absolute (as opposed to relative) within + * the buffer size. Returns the scheme in the buffer if TRUE and 'buf' is + * non-NULL. + */ +bool Curl_is_absolute_url(const char *url, char *buf, size_t buflen) +{ + size_t i; +#ifdef WIN32 + if(STARTS_WITH_DRIVE_PREFIX(url)) + return FALSE; +#endif + for(i = 0; i < buflen && url[i]; ++i) { + char s = url[i]; + if((s == ':') && (url[i + 1] == '/')) { + if(buf) + buf[i] = 0; + return TRUE; + } + /* RFC 3986 3.1 explains: + scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + */ + else if(ISALNUM(s) || (s == '+') || (s == '-') || (s == '.') ) { + if(buf) + buf[i] = (char)TOLOWER(s); + } + else + break; + } + return FALSE; +} + +/* + * Concatenate a relative URL to a base URL making it absolute. + * URL-encodes any spaces. + * The returned pointer must be freed by the caller unless NULL + * (returns NULL on out of memory). + */ +static char *concat_url(const char *base, const char *relurl) +{ + /*** + TRY to append this new path to the old URL + to the right of the host part. Oh crap, this is doomed to cause + problems in the future... + */ + char *newest; + char *protsep; + char *pathsep; + size_t newlen; + bool host_changed = FALSE; + + const char *useurl = relurl; + size_t urllen; + + /* we must make our own copy of the URL to play with, as it may + point to read-only data */ + char *url_clone = strdup(base); + + if(!url_clone) + return NULL; /* skip out of this NOW */ + + /* protsep points to the start of the host name */ + protsep = strstr(url_clone, "//"); + if(!protsep) + protsep = url_clone; + else + protsep += 2; /* pass the slashes */ + + if('/' != relurl[0]) { + int level = 0; + + /* First we need to find out if there's a ?-letter in the URL, + and cut it and the right-side of that off */ + pathsep = strchr(protsep, '?'); + if(pathsep) + *pathsep = 0; + + /* we have a relative path to append to the last slash if there's one + available, or if the new URL is just a query string (starts with a + '?') we append the new one at the end of the entire currently worked + out URL */ + if(useurl[0] != '?') { + pathsep = strrchr(protsep, '/'); + if(pathsep) + *pathsep = 0; + } + + /* Check if there's any slash after the host name, and if so, remember + that position instead */ + pathsep = strchr(protsep, '/'); + if(pathsep) + protsep = pathsep + 1; + else + protsep = NULL; + + /* now deal with one "./" or any amount of "../" in the newurl + and act accordingly */ + + if((useurl[0] == '.') && (useurl[1] == '/')) + useurl += 2; /* just skip the "./" */ + + while((useurl[0] == '.') && + (useurl[1] == '.') && + (useurl[2] == '/')) { + level++; + useurl += 3; /* pass the "../" */ + } + + if(protsep) { + while(level--) { + /* cut off one more level from the right of the original URL */ + pathsep = strrchr(protsep, '/'); + if(pathsep) + *pathsep = 0; + else { + *protsep = 0; + break; + } + } + } + } + else { + /* We got a new absolute path for this server */ + + if((relurl[0] == '/') && (relurl[1] == '/')) { + /* the new URL starts with //, just keep the protocol part from the + original one */ + *protsep = 0; + useurl = &relurl[2]; /* we keep the slashes from the original, so we + skip the new ones */ + host_changed = TRUE; + } + else { + /* cut off the original URL from the first slash, or deal with URLs + without slash */ + pathsep = strchr(protsep, '/'); + if(pathsep) { + /* When people use badly formatted URLs, such as + "http://www.url.com?dir=/home/daniel" we must not use the first + slash, if there's a ?-letter before it! */ + char *sep = strchr(protsep, '?'); + if(sep && (sep < pathsep)) + pathsep = sep; + *pathsep = 0; + } + else { + /* There was no slash. Now, since we might be operating on a badly + formatted URL, such as "http://www.url.com?id=2380" which doesn't + use a slash separator as it is supposed to, we need to check for a + ?-letter as well! */ + pathsep = strchr(protsep, '?'); + if(pathsep) + *pathsep = 0; + } + } + } + + /* If the new part contains a space, this is a mighty stupid redirect + but we still make an effort to do "right". To the left of a '?' + letter we replace each space with %20 while it is replaced with '+' + on the right side of the '?' letter. + */ + newlen = strlen_url(useurl, !host_changed); + + urllen = strlen(url_clone); + + newest = malloc(urllen + 1 + /* possible slash */ + newlen + 1 /* zero byte */); + + if(!newest) { + free(url_clone); /* don't leak this */ + return NULL; + } + + /* copy over the root url part */ + memcpy(newest, url_clone, urllen); + + /* check if we need to append a slash */ + if(('/' == useurl[0]) || (protsep && !*protsep) || ('?' == useurl[0])) + ; + else + newest[urllen++]='/'; + + /* then append the new piece on the right side */ + strcpy_url(&newest[urllen], useurl, !host_changed); + + free(url_clone); + + return newest; +} + +/* + * parse_hostname_login() + * + * Parse the login details (user name, password and options) from the URL and + * strip them out of the host name + * + */ +static CURLUcode parse_hostname_login(struct Curl_URL *u, + const struct Curl_handler *h, + char **hostname, + unsigned int flags) +{ + CURLUcode result = CURLUE_OK; + CURLcode ccode; + char *userp = NULL; + char *passwdp = NULL; + char *optionsp = NULL; + + /* At this point, we're hoping all the other special cases have + * been taken care of, so conn->host.name is at most + * [user[:password][;options]]@]hostname + * + * We need somewhere to put the embedded details, so do that first. + */ + + char *ptr = strchr(*hostname, '@'); + char *login = *hostname; + + if(!ptr) + goto out; + + /* We will now try to extract the + * possible login information in a string like: + * ftp://user:password@ftp.my.site:8021/README */ + *hostname = ++ptr; + + /* We could use the login information in the URL so extract it. Only parse + options if the handler says we should. Note that 'h' might be NULL! */ + ccode = Curl_parse_login_details(login, ptr - login - 1, + &userp, &passwdp, + (h && (h->flags & PROTOPT_URLOPTIONS)) ? + &optionsp:NULL); + if(ccode) { + result = CURLUE_MALFORMED_INPUT; + goto out; + } + + if(userp) { + if(flags & CURLU_DISALLOW_USER) { + /* Option DISALLOW_USER is set and url contains username. */ + result = CURLUE_USER_NOT_ALLOWED; + goto out; + } + + u->user = userp; + } + + if(passwdp) + u->password = passwdp; + + if(optionsp) + u->options = optionsp; + + return CURLUE_OK; + out: + + free(userp); + free(passwdp); + free(optionsp); + + return result; +} + +UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname) +{ + char *portptr = NULL; + char endbracket; + int len; + + /* + * Find the end of an IPv6 address, either on the ']' ending bracket or + * a percent-encoded zone index. + */ + if(1 == sscanf(hostname, "[%*45[0123456789abcdefABCDEF:.]%c%n", + &endbracket, &len)) { + if(']' == endbracket) + portptr = &hostname[len]; + else if('%' == endbracket) { + int zonelen = len; + if(1 == sscanf(hostname + zonelen, "%*[^]]%c%n", &endbracket, &len)) { + if(']' != endbracket) + return CURLUE_MALFORMED_INPUT; + portptr = &hostname[--zonelen + len + 1]; + } + else + return CURLUE_MALFORMED_INPUT; + } + else + return CURLUE_MALFORMED_INPUT; + + /* this is a RFC2732-style specified IP-address */ + if(portptr && *portptr) { + if(*portptr != ':') + return CURLUE_MALFORMED_INPUT; + } + else + portptr = NULL; + } + else + portptr = strchr(hostname, ':'); + + if(portptr) { + char *rest; + long port; + char portbuf[7]; + + /* Browser behavior adaptation. If there's a colon with no digits after, + just cut off the name there which makes us ignore the colon and just + use the default port. Firefox, Chrome and Safari all do that. */ + if(!portptr[1]) { + *portptr = '\0'; + return CURLUE_OK; + } + + if(!ISDIGIT(portptr[1])) + return CURLUE_BAD_PORT_NUMBER; + + port = strtol(portptr + 1, &rest, 10); /* Port number must be decimal */ + + if((port <= 0) || (port > 0xffff)) + /* Single unix standard says port numbers are 16 bits long, but we don't + treat port zero as OK. */ + return CURLUE_BAD_PORT_NUMBER; + + if(rest[0]) + return CURLUE_BAD_PORT_NUMBER; + + *portptr++ = '\0'; /* cut off the name there */ + *rest = 0; + /* generate a new port number string to get rid of leading zeroes etc */ + msnprintf(portbuf, sizeof(portbuf), "%ld", port); + u->portnum = port; + u->port = strdup(portbuf); + if(!u->port) + return CURLUE_OUT_OF_MEMORY; + } + + return CURLUE_OK; +} + +/* scan for byte values < 31 or 127 */ +static CURLUcode junkscan(char *part) +{ + if(part) { + static const char badbytes[]={ + /* */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x7f, + 0x00 /* zero terminate */ + }; + size_t n = strlen(part); + size_t nfine = strcspn(part, badbytes); + if(nfine != n) + /* since we don't know which part is scanned, return a generic error + code */ + return CURLUE_MALFORMED_INPUT; + } + return CURLUE_OK; +} + +static CURLUcode hostname_check(struct Curl_URL *u, char *hostname) +{ + const char *l = NULL; /* accepted characters */ + size_t len; + size_t hlen = strlen(hostname); + + if(hostname[0] == '[') { + hostname++; + l = "0123456789abcdefABCDEF::."; + hlen -= 2; + } + + if(l) { + /* only valid letters are ok */ + len = strspn(hostname, l); + if(hlen != len) { + if(hostname[len] == '%') { + /* this could now be '%[zone id]' */ + char zoneid[16]; + int i = 0; + char *h = &hostname[len + 1]; + /* pass '25' if present and is a url encoded percent sign */ + if(!strncmp(h, "25", 2) && h[2] && (h[2] != ']')) + h += 2; + while(*h && (*h != ']') && (i < 15)) + zoneid[i++] = *h++; + if(!i || (']' != *h)) + return CURLUE_MALFORMED_INPUT; + zoneid[i] = 0; + u->zoneid = strdup(zoneid); + if(!u->zoneid) + return CURLUE_OUT_OF_MEMORY; + hostname[len] = ']'; /* insert end bracket */ + hostname[len + 1] = 0; /* terminate the hostname */ + } + else + return CURLUE_MALFORMED_INPUT; + /* hostname is fine */ + } + } + else { + /* letters from the second string is not ok */ + len = strcspn(hostname, " "); + if(hlen != len) + /* hostname with bad content */ + return CURLUE_MALFORMED_INPUT; + } + if(!hostname[0]) + return CURLUE_NO_HOST; + return CURLUE_OK; +} + +#define HOSTNAME_END(x) (((x) == '/') || ((x) == '?') || ((x) == '#')) + +static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) +{ + char *path; + bool path_alloced = FALSE; + char *hostname; + char *query = NULL; + char *fragment = NULL; + CURLUcode result; + bool url_has_scheme = FALSE; + char schemebuf[MAX_SCHEME_LEN + 1]; + char *schemep = NULL; + size_t schemelen = 0; + size_t urllen; + const struct Curl_handler *h = NULL; + + if(!url) + return CURLUE_MALFORMED_INPUT; + + /************************************************************* + * Parse the URL. + ************************************************************/ + /* allocate scratch area */ + urllen = strlen(url); + if(urllen > CURL_MAX_INPUT_LENGTH) + /* excessive input length */ + return CURLUE_MALFORMED_INPUT; + + path = u->scratch = malloc(urllen * 2 + 2); + if(!path) + return CURLUE_OUT_OF_MEMORY; + + hostname = &path[urllen + 1]; + hostname[0] = 0; + + if(Curl_is_absolute_url(url, schemebuf, sizeof(schemebuf))) { + url_has_scheme = TRUE; + schemelen = strlen(schemebuf); + } + + /* handle the file: scheme */ + if(url_has_scheme && strcasecompare(schemebuf, "file")) { + /* path has been allocated large enough to hold this */ + strcpy(path, &url[5]); + + hostname = NULL; /* no host for file: URLs */ + u->scheme = strdup("file"); + if(!u->scheme) + return CURLUE_OUT_OF_MEMORY; + + /* Extra handling URLs with an authority component (i.e. that start with + * "file://") + * + * We allow omitted hostname (e.g. file:/) -- valid according to + * RFC 8089, but not the (current) WHAT-WG URL spec. + */ + if(path[0] == '/' && path[1] == '/') { + /* swallow the two slashes */ + char *ptr = &path[2]; + + /* + * According to RFC 8089, a file: URL can be reliably dereferenced if: + * + * o it has no/blank hostname, or + * + * o the hostname matches "localhost" (case-insensitively), or + * + * o the hostname is a FQDN that resolves to this machine. + * + * For brevity, we only consider URLs with empty, "localhost", or + * "127.0.0.1" hostnames as local. + * + * Additionally, there is an exception for URLs with a Windows drive + * letter in the authority (which was accidentally omitted from RFC 8089 + * Appendix E, but believe me, it was meant to be there. --MK) + */ + if(ptr[0] != '/' && !STARTS_WITH_URL_DRIVE_PREFIX(ptr)) { + /* the URL includes a host name, it must match "localhost" or + "127.0.0.1" to be valid */ + if(!checkprefix("localhost/", ptr) && + !checkprefix("127.0.0.1/", ptr)) { + /* Invalid file://hostname/, expected localhost or 127.0.0.1 or + none */ + return CURLUE_MALFORMED_INPUT; + } + ptr += 9; /* now points to the slash after the host */ + } + + path = ptr; + } + +#if !defined(MSDOS) && !defined(WIN32) && !defined(__CYGWIN__) + /* Don't allow Windows drive letters when not in Windows. + * This catches both "file:/c:" and "file:c:" */ + if(('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) || + STARTS_WITH_URL_DRIVE_PREFIX(path)) { + /* File drive letters are only accepted in MSDOS/Windows */ + return CURLUE_MALFORMED_INPUT; + } +#else + /* If the path starts with a slash and a drive letter, ditch the slash */ + if('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) { + /* This cannot be done with strcpy, as the memory chunks overlap! */ + memmove(path, &path[1], strlen(&path[1]) + 1); + } +#endif + + } + else { + /* clear path */ + const char *p; + const char *hostp; + size_t len; + path[0] = 0; + + if(url_has_scheme) { + int i = 0; + p = &url[schemelen + 1]; + while(p && (*p == '/') && (i < 4)) { + p++; + i++; + } + if((i < 1) || (i>3)) + /* less than one or more than three slashes */ + return CURLUE_MALFORMED_INPUT; + + schemep = schemebuf; + if(!Curl_builtin_scheme(schemep) && + !(flags & CURLU_NON_SUPPORT_SCHEME)) + return CURLUE_UNSUPPORTED_SCHEME; + + if(junkscan(schemep)) + return CURLUE_MALFORMED_INPUT; + } + else { + /* no scheme! */ + + if(!(flags & (CURLU_DEFAULT_SCHEME|CURLU_GUESS_SCHEME))) + return CURLUE_MALFORMED_INPUT; + if(flags & CURLU_DEFAULT_SCHEME) + schemep = (char *) DEFAULT_SCHEME; + + /* + * The URL was badly formatted, let's try without scheme specified. + */ + p = url; + } + hostp = p; /* host name starts here */ + + while(*p && !HOSTNAME_END(*p)) /* find end of host name */ + p++; + + len = p - hostp; + if(!len) + return CURLUE_MALFORMED_INPUT; + + memcpy(hostname, hostp, len); + hostname[len] = 0; + + if((flags & CURLU_GUESS_SCHEME) && !schemep) { + /* legacy curl-style guess based on host name */ + if(checkprefix("ftp.", hostname)) + schemep = (char *)"ftp"; + else if(checkprefix("dict.", hostname)) + schemep = (char *)"dict"; + else if(checkprefix("ldap.", hostname)) + schemep = (char *)"ldap"; + else if(checkprefix("imap.", hostname)) + schemep = (char *)"imap"; + else if(checkprefix("smtp.", hostname)) + schemep = (char *)"smtp"; + else if(checkprefix("pop3.", hostname)) + schemep = (char *)"pop3"; + else + schemep = (char *)"http"; + } + + len = strlen(p); + memcpy(path, p, len); + path[len] = 0; + + u->scheme = strdup(schemep); + if(!u->scheme) + return CURLUE_OUT_OF_MEMORY; + } + + /* if this is a known scheme, get some details */ + h = Curl_builtin_scheme(u->scheme); + + if(junkscan(path)) + return CURLUE_MALFORMED_INPUT; + + query = strchr(path, '?'); + if(query) + *query++ = 0; + + fragment = strchr(query?query:path, '#'); + if(fragment) + *fragment++ = 0; + + if(!path[0]) + /* if there's no path set, unset */ + path = NULL; + else if(!(flags & CURLU_PATH_AS_IS)) { + /* sanitise paths and remove ../ and ./ sequences according to RFC3986 */ + char *newp = Curl_dedotdotify(path); + if(!newp) + return CURLUE_OUT_OF_MEMORY; + + if(strcmp(newp, path)) { + /* if we got a new version */ + path = newp; + path_alloced = TRUE; + } + else + free(newp); + } + if(path) { + u->path = path_alloced?path:strdup(path); + if(!u->path) + return CURLUE_OUT_OF_MEMORY; + } + + if(hostname) { + /* + * Parse the login details and strip them out of the host name. + */ + if(junkscan(hostname)) + return CURLUE_MALFORMED_INPUT; + + result = parse_hostname_login(u, h, &hostname, flags); + if(result) + return result; + + result = Curl_parse_port(u, hostname); + if(result) + return result; + + result = hostname_check(u, hostname); + if(result) + return result; + + u->host = strdup(hostname); + if(!u->host) + return CURLUE_OUT_OF_MEMORY; + } + + if(query) { + u->query = strdup(query); + if(!u->query) + return CURLUE_OUT_OF_MEMORY; + } + if(fragment && fragment[0]) { + u->fragment = strdup(fragment); + if(!u->fragment) + return CURLUE_OUT_OF_MEMORY; + } + + free(u->scratch); + u->scratch = NULL; + + return CURLUE_OK; +} + +/* + * Parse the URL and set the relevant members of the Curl_URL struct. + */ +static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags) +{ + CURLUcode result = seturl(url, u, flags); + if(result) { + free_urlhandle(u); + memset(u, 0, sizeof(struct Curl_URL)); + } + return result; +} + +/* + */ +CURLU *curl_url(void) +{ + return calloc(sizeof(struct Curl_URL), 1); +} + +void curl_url_cleanup(CURLU *u) +{ + if(u) { + free_urlhandle(u); + free(u); + } +} + +#define DUP(dest, src, name) \ + if(src->name) { \ + dest->name = strdup(src->name); \ + if(!dest->name) \ + goto fail; \ + } + +CURLU *curl_url_dup(CURLU *in) +{ + struct Curl_URL *u = calloc(sizeof(struct Curl_URL), 1); + if(u) { + DUP(u, in, scheme); + DUP(u, in, user); + DUP(u, in, password); + DUP(u, in, options); + DUP(u, in, host); + DUP(u, in, port); + DUP(u, in, path); + DUP(u, in, query); + DUP(u, in, fragment); + u->portnum = in->portnum; + } + return u; + fail: + curl_url_cleanup(u); + return NULL; +} + +CURLUcode curl_url_get(CURLU *u, CURLUPart what, + char **part, unsigned int flags) +{ + char *ptr; + CURLUcode ifmissing = CURLUE_UNKNOWN_PART; + char portbuf[7]; + bool urldecode = (flags & CURLU_URLDECODE)?1:0; + bool plusdecode = FALSE; + (void)flags; + if(!u) + return CURLUE_BAD_HANDLE; + if(!part) + return CURLUE_BAD_PARTPOINTER; + *part = NULL; + + switch(what) { + case CURLUPART_SCHEME: + ptr = u->scheme; + ifmissing = CURLUE_NO_SCHEME; + urldecode = FALSE; /* never for schemes */ + break; + case CURLUPART_USER: + ptr = u->user; + ifmissing = CURLUE_NO_USER; + break; + case CURLUPART_PASSWORD: + ptr = u->password; + ifmissing = CURLUE_NO_PASSWORD; + break; + case CURLUPART_OPTIONS: + ptr = u->options; + ifmissing = CURLUE_NO_OPTIONS; + break; + case CURLUPART_HOST: + ptr = u->host; + ifmissing = CURLUE_NO_HOST; + break; + case CURLUPART_ZONEID: + ptr = u->zoneid; + break; + case CURLUPART_PORT: + ptr = u->port; + ifmissing = CURLUE_NO_PORT; + urldecode = FALSE; /* never for port */ + if(!ptr && (flags & CURLU_DEFAULT_PORT) && u->scheme) { + /* there's no stored port number, but asked to deliver + a default one for the scheme */ + const struct Curl_handler *h = + Curl_builtin_scheme(u->scheme); + if(h) { + msnprintf(portbuf, sizeof(portbuf), "%ld", h->defport); + ptr = portbuf; + } + } + else if(ptr && u->scheme) { + /* there is a stored port number, but ask to inhibit if + it matches the default one for the scheme */ + const struct Curl_handler *h = + Curl_builtin_scheme(u->scheme); + if(h && (h->defport == u->portnum) && + (flags & CURLU_NO_DEFAULT_PORT)) + ptr = NULL; + } + break; + case CURLUPART_PATH: + ptr = u->path; + if(!ptr) { + ptr = u->path = strdup("/"); + if(!u->path) + return CURLUE_OUT_OF_MEMORY; + } + break; + case CURLUPART_QUERY: + ptr = u->query; + ifmissing = CURLUE_NO_QUERY; + plusdecode = urldecode; + break; + case CURLUPART_FRAGMENT: + ptr = u->fragment; + ifmissing = CURLUE_NO_FRAGMENT; + break; + case CURLUPART_URL: { + char *url; + char *scheme; + char *options = u->options; + char *port = u->port; + char *allochost = NULL; + if(u->scheme && strcasecompare("file", u->scheme)) { + url = aprintf("file://%s%s%s", + u->path, + u->fragment? "#": "", + u->fragment? u->fragment : ""); + } + else if(!u->host) + return CURLUE_NO_HOST; + else { + const struct Curl_handler *h = NULL; + if(u->scheme) + scheme = u->scheme; + else if(flags & CURLU_DEFAULT_SCHEME) + scheme = (char *) DEFAULT_SCHEME; + else + return CURLUE_NO_SCHEME; + + if(scheme) { + h = Curl_builtin_scheme(scheme); + if(!port && (flags & CURLU_DEFAULT_PORT)) { + /* there's no stored port number, but asked to deliver + a default one for the scheme */ + if(h) { + msnprintf(portbuf, sizeof(portbuf), "%ld", h->defport); + port = portbuf; + } + } + else if(port) { + /* there is a stored port number, but asked to inhibit if it matches + the default one for the scheme */ + if(h && (h->defport == u->portnum) && + (flags & CURLU_NO_DEFAULT_PORT)) + port = NULL; + } + } + if(h && !(h->flags & PROTOPT_URLOPTIONS)) + options = NULL; + + if((u->host[0] == '[') && u->zoneid) { + /* make it '[ host %25 zoneid ]' */ + size_t hostlen = strlen(u->host); + size_t alen = hostlen + 3 + strlen(u->zoneid) + 1; + allochost = malloc(alen); + if(!allochost) + return CURLUE_OUT_OF_MEMORY; + memcpy(allochost, u->host, hostlen - 1); + msnprintf(&allochost[hostlen - 1], alen - hostlen + 1, + "%%25%s]", u->zoneid); + } + + url = aprintf("%s://%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + scheme, + u->user ? u->user : "", + u->password ? ":": "", + u->password ? u->password : "", + options ? ";" : "", + options ? options : "", + (u->user || u->password || options) ? "@": "", + allochost ? allochost : u->host, + port ? ":": "", + port ? port : "", + (u->path && (u->path[0] != '/')) ? "/": "", + u->path ? u->path : "/", + (u->query && u->query[0]) ? "?": "", + (u->query && u->query[0]) ? u->query : "", + u->fragment? "#": "", + u->fragment? u->fragment : ""); + free(allochost); + } + if(!url) + return CURLUE_OUT_OF_MEMORY; + *part = url; + return CURLUE_OK; + } + default: + ptr = NULL; + break; + } + if(ptr) { + *part = strdup(ptr); + if(!*part) + return CURLUE_OUT_OF_MEMORY; + if(plusdecode) { + /* convert + to space */ + char *plus; + for(plus = *part; *plus; ++plus) { + if(*plus == '+') + *plus = ' '; + } + } + if(urldecode) { + char *decoded; + size_t dlen; + CURLcode res = Curl_urldecode(NULL, *part, 0, &decoded, &dlen, TRUE); + free(*part); + if(res) { + *part = NULL; + return CURLUE_URLDECODE; + } + *part = decoded; + } + return CURLUE_OK; + } + else + return ifmissing; +} + +CURLUcode curl_url_set(CURLU *u, CURLUPart what, + const char *part, unsigned int flags) +{ + char **storep = NULL; + long port = 0; + bool urlencode = (flags & CURLU_URLENCODE)? 1 : 0; + bool plusencode = FALSE; + bool urlskipslash = FALSE; + bool appendquery = FALSE; + bool equalsencode = FALSE; + + if(!u) + return CURLUE_BAD_HANDLE; + if(!part) { + /* setting a part to NULL clears it */ + switch(what) { + case CURLUPART_URL: + break; + case CURLUPART_SCHEME: + storep = &u->scheme; + break; + case CURLUPART_USER: + storep = &u->user; + break; + case CURLUPART_PASSWORD: + storep = &u->password; + break; + case CURLUPART_OPTIONS: + storep = &u->options; + break; + case CURLUPART_HOST: + storep = &u->host; + break; + case CURLUPART_ZONEID: + storep = &u->zoneid; + break; + case CURLUPART_PORT: + u->portnum = 0; + storep = &u->port; + break; + case CURLUPART_PATH: + storep = &u->path; + break; + case CURLUPART_QUERY: + storep = &u->query; + break; + case CURLUPART_FRAGMENT: + storep = &u->fragment; + break; + default: + return CURLUE_UNKNOWN_PART; + } + if(storep && *storep) { + free(*storep); + *storep = NULL; + } + return CURLUE_OK; + } + + switch(what) { + case CURLUPART_SCHEME: + if(strlen(part) > MAX_SCHEME_LEN) + /* too long */ + return CURLUE_MALFORMED_INPUT; + if(!(flags & CURLU_NON_SUPPORT_SCHEME) && + /* verify that it is a fine scheme */ + !Curl_builtin_scheme(part)) + return CURLUE_UNSUPPORTED_SCHEME; + storep = &u->scheme; + urlencode = FALSE; /* never */ + break; + case CURLUPART_USER: + storep = &u->user; + break; + case CURLUPART_PASSWORD: + storep = &u->password; + break; + case CURLUPART_OPTIONS: + storep = &u->options; + break; + case CURLUPART_HOST: + storep = &u->host; + free(u->zoneid); + u->zoneid = NULL; + break; + case CURLUPART_ZONEID: + storep = &u->zoneid; + break; + case CURLUPART_PORT: + { + char *endp; + urlencode = FALSE; /* never */ + port = strtol(part, &endp, 10); /* Port number must be decimal */ + if((port <= 0) || (port > 0xffff)) + return CURLUE_BAD_PORT_NUMBER; + if(*endp) + /* weirdly provided number, not good! */ + return CURLUE_MALFORMED_INPUT; + storep = &u->port; + } + break; + case CURLUPART_PATH: + urlskipslash = TRUE; + storep = &u->path; + break; + case CURLUPART_QUERY: + plusencode = urlencode; + appendquery = (flags & CURLU_APPENDQUERY)?1:0; + equalsencode = appendquery; + storep = &u->query; + break; + case CURLUPART_FRAGMENT: + storep = &u->fragment; + break; + case CURLUPART_URL: { + /* + * Allow a new URL to replace the existing (if any) contents. + * + * If the existing contents is enough for a URL, allow a relative URL to + * replace it. + */ + CURLUcode result; + char *oldurl; + char *redired_url; + CURLU *handle2; + + if(Curl_is_absolute_url(part, NULL, MAX_SCHEME_LEN + 1)) { + handle2 = curl_url(); + if(!handle2) + return CURLUE_OUT_OF_MEMORY; + result = parseurl(part, handle2, flags); + if(!result) + mv_urlhandle(handle2, u); + else + curl_url_cleanup(handle2); + return result; + } + /* extract the full "old" URL to do the redirect on */ + result = curl_url_get(u, CURLUPART_URL, &oldurl, flags); + if(result) { + /* couldn't get the old URL, just use the new! */ + handle2 = curl_url(); + if(!handle2) + return CURLUE_OUT_OF_MEMORY; + result = parseurl(part, handle2, flags); + if(!result) + mv_urlhandle(handle2, u); + else + curl_url_cleanup(handle2); + return result; + } + + /* apply the relative part to create a new URL */ + redired_url = concat_url(oldurl, part); + free(oldurl); + if(!redired_url) + return CURLUE_OUT_OF_MEMORY; + + /* now parse the new URL */ + handle2 = curl_url(); + if(!handle2) { + free(redired_url); + return CURLUE_OUT_OF_MEMORY; + } + result = parseurl(redired_url, handle2, flags); + free(redired_url); + if(!result) + mv_urlhandle(handle2, u); + else + curl_url_cleanup(handle2); + return result; + } + default: + return CURLUE_UNKNOWN_PART; + } + if(storep) { + const char *newp = part; + size_t nalloc = strlen(part); + + if(nalloc > CURL_MAX_INPUT_LENGTH) + /* excessive input length */ + return CURLUE_MALFORMED_INPUT; + + if(urlencode) { + const unsigned char *i; + char *o; + bool free_part = FALSE; + char *enc = malloc(nalloc * 3 + 1); /* for worst case! */ + if(!enc) + return CURLUE_OUT_OF_MEMORY; + if(plusencode) { + /* space to plus */ + i = (const unsigned char *)part; + for(o = enc; *i; ++o, ++i) + *o = (*i == ' ') ? '+' : *i; + *o = 0; /* zero terminate */ + part = strdup(enc); + if(!part) { + free(enc); + return CURLUE_OUT_OF_MEMORY; + } + free_part = TRUE; + } + for(i = (const unsigned char *)part, o = enc; *i; i++) { + if(Curl_isunreserved(*i) || + ((*i == '/') && urlskipslash) || + ((*i == '=') && equalsencode) || + ((*i == '+') && plusencode)) { + if((*i == '=') && equalsencode) + /* only skip the first equals sign */ + equalsencode = FALSE; + *o = *i; + o++; + } + else { + msnprintf(o, 4, "%%%02x", *i); + o += 3; + } + } + *o = 0; /* zero terminate */ + newp = enc; + if(free_part) + free((char *)part); + } + else { + char *p; + newp = strdup(part); + if(!newp) + return CURLUE_OUT_OF_MEMORY; + p = (char *)newp; + while(*p) { + /* make sure percent encoded are lower case */ + if((*p == '%') && ISXDIGIT(p[1]) && ISXDIGIT(p[2]) && + (ISUPPER(p[1]) || ISUPPER(p[2]))) { + p[1] = (char)TOLOWER(p[1]); + p[2] = (char)TOLOWER(p[2]); + p += 3; + } + else + p++; + } + } + + if(appendquery) { + /* Append the string onto the old query. Add a '&' separator if none is + present at the end of the exsting query already */ + size_t querylen = u->query ? strlen(u->query) : 0; + bool addamperand = querylen && (u->query[querylen -1] != '&'); + if(querylen) { + size_t newplen = strlen(newp); + char *p = malloc(querylen + addamperand + newplen + 1); + if(!p) { + free((char *)newp); + return CURLUE_OUT_OF_MEMORY; + } + strcpy(p, u->query); /* original query */ + if(addamperand) + p[querylen] = '&'; /* ampersand */ + strcpy(&p[querylen + addamperand], newp); /* new suffix */ + free((char *)newp); + free(*storep); + *storep = p; + return CURLUE_OK; + } + } + + if(what == CURLUPART_HOST) { + if(hostname_check(u, (char *)newp)) { + free((char *)newp); + return CURLUE_MALFORMED_INPUT; + } + } + + free(*storep); + *storep = (char *)newp; + } + /* set after the string, to make it not assigned if the allocation above + fails */ + if(port) + u->portnum = port; + return CURLUE_OK; +} diff --git a/dependencies/cmcurl/lib/urldata.h b/dependencies/cmcurl/lib/urldata.h new file mode 100644 index 0000000..d759592 --- /dev/null +++ b/dependencies/cmcurl/lib/urldata.h @@ -0,0 +1,1837 @@ +#ifndef HEADER_CURL_URLDATA_H +#define HEADER_CURL_URLDATA_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* This file is for lib internal stuff */ + +#include "curl_setup.h" + +#define PORT_FTP 21 +#define PORT_FTPS 990 +#define PORT_TELNET 23 +#define PORT_HTTP 80 +#define PORT_HTTPS 443 +#define PORT_DICT 2628 +#define PORT_LDAP 389 +#define PORT_LDAPS 636 +#define PORT_TFTP 69 +#define PORT_SSH 22 +#define PORT_IMAP 143 +#define PORT_IMAPS 993 +#define PORT_POP3 110 +#define PORT_POP3S 995 +#define PORT_SMB 445 +#define PORT_SMBS 445 +#define PORT_SMTP 25 +#define PORT_SMTPS 465 /* sometimes called SSMTP */ +#define PORT_RTSP 554 +#define PORT_RTMP 1935 +#define PORT_RTMPT PORT_HTTP +#define PORT_RTMPS PORT_HTTPS +#define PORT_GOPHER 70 + +#define DICT_MATCH "/MATCH:" +#define DICT_MATCH2 "/M:" +#define DICT_MATCH3 "/FIND:" +#define DICT_DEFINE "/DEFINE:" +#define DICT_DEFINE2 "/D:" +#define DICT_DEFINE3 "/LOOKUP:" + +#define CURL_DEFAULT_USER "anonymous" +#define CURL_DEFAULT_PASSWORD "ftp@example.com" + +/* Convenience defines for checking protocols or their SSL based version. Each + protocol handler should only ever have a single CURLPROTO_ in its protocol + field. */ +#define PROTO_FAMILY_HTTP (CURLPROTO_HTTP|CURLPROTO_HTTPS) +#define PROTO_FAMILY_FTP (CURLPROTO_FTP|CURLPROTO_FTPS) +#define PROTO_FAMILY_POP3 (CURLPROTO_POP3|CURLPROTO_POP3S) +#define PROTO_FAMILY_SMB (CURLPROTO_SMB|CURLPROTO_SMBS) +#define PROTO_FAMILY_SMTP (CURLPROTO_SMTP|CURLPROTO_SMTPS) + +#define DEFAULT_CONNCACHE_SIZE 5 + +/* length of longest IPv6 address string including the trailing null */ +#define MAX_IPADR_LEN sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") + +/* Default FTP/IMAP etc response timeout in milliseconds. + Symbian OS panics when given a timeout much greater than 1/2 hour. +*/ +#define RESP_TIMEOUT (120*1000) + +/* Max string intput length is a precaution against abuse and to detect junk + input easier and better. */ +#define CURL_MAX_INPUT_LENGTH 8000000 + +#include "cookie.h" +#include "psl.h" +#include "formdata.h" + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_IN6_H +#include +#endif + +#include "timeval.h" + +#include + +#include "http_chunks.h" /* for the structs and enum stuff */ +#include "hostip.h" +#include "hash.h" +#include "splay.h" + +/* return the count of bytes sent, or -1 on error */ +typedef ssize_t (Curl_send)(struct connectdata *conn, /* connection data */ + int sockindex, /* socketindex */ + const void *buf, /* data to write */ + size_t len, /* max amount to write */ + CURLcode *err); /* error to return */ + +/* return the count of bytes read, or -1 on error */ +typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */ + int sockindex, /* socketindex */ + char *buf, /* store data here */ + size_t len, /* max amount to read */ + CURLcode *err); /* error to return */ + +#include "mime.h" +#include "imap.h" +#include "pop3.h" +#include "smtp.h" +#include "ftp.h" +#include "file.h" +#include "ssh.h" +#include "http.h" +#include "rtsp.h" +#include "smb.h" +#include "wildcard.h" +#include "multihandle.h" + +#ifdef HAVE_GSSAPI +# ifdef HAVE_GSSGNU +# include +# elif defined HAVE_GSSAPI_GSSAPI_H +# include +# else +# include +# endif +# ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H +# include +# endif +#endif + +#ifdef HAVE_LIBSSH2_H +#include +#include +#endif /* HAVE_LIBSSH2_H */ + +/* Initial size of the buffer to store headers in, it'll be enlarged in case + of need. */ +#define HEADERSIZE 256 + +#define CURLEASY_MAGIC_NUMBER 0xc0dedbadU +#define GOOD_EASY_HANDLE(x) \ + ((x) && ((x)->magic == CURLEASY_MAGIC_NUMBER)) + +/* the type we use for storing a single boolean bit */ +typedef unsigned int bit; + +#ifdef HAVE_GSSAPI +/* Types needed for krb5-ftp connections */ +struct krb5buffer { + void *data; + size_t size; + size_t index; + bit eof_flag:1; +}; + +enum protection_level { + PROT_NONE, /* first in list */ + PROT_CLEAR, + PROT_SAFE, + PROT_CONFIDENTIAL, + PROT_PRIVATE, + PROT_CMD, + PROT_LAST /* last in list */ +}; +#endif + +/* enum for the nonblocking SSL connection state machine */ +typedef enum { + ssl_connect_1, + ssl_connect_2, + ssl_connect_2_reading, + ssl_connect_2_writing, + ssl_connect_3, + ssl_connect_done +} ssl_connect_state; + +typedef enum { + ssl_connection_none, + ssl_connection_negotiating, + ssl_connection_complete +} ssl_connection_state; + +/* SSL backend-specific data; declared differently by each SSL backend */ +struct ssl_backend_data; + +/* struct for data related to each SSL connection */ +struct ssl_connect_data { + /* Use ssl encrypted communications TRUE/FALSE, not necessarily using it atm + but at least asked to or meaning to use it. See 'state' for the exact + current state of the connection. */ + ssl_connection_state state; + ssl_connect_state connecting_state; +#if defined(USE_SSL) + struct ssl_backend_data *backend; +#endif + bit use:1; +}; + +struct ssl_primary_config { + long version; /* what version the client wants to use */ + long version_max; /* max supported version the client wants to use*/ + char *CApath; /* certificate dir (doesn't work on windows) */ + char *CAfile; /* certificate to verify peer against */ + char *clientcert; + char *random_file; /* path to file containing "random" data */ + char *egdsocket; /* path to file containing the EGD daemon socket */ + char *cipher_list; /* list of ciphers to use */ + char *cipher_list13; /* list of TLS 1.3 cipher suites to use */ + bit verifypeer:1; /* set TRUE if this is desired */ + bit verifyhost:1; /* set TRUE if CN/SAN must match hostname */ + bit verifystatus:1; /* set TRUE if certificate status must be checked */ + bit sessionid:1; /* cache session IDs or not */ +}; + +struct ssl_config_data { + struct ssl_primary_config primary; + long certverifyresult; /* result from the certificate verification */ + char *CRLfile; /* CRL to check certificate revocation */ + char *issuercert;/* optional issuer certificate filename */ + curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */ + void *fsslctxp; /* parameter for call back */ + char *cert; /* client certificate file name */ + char *cert_type; /* format for certificate (default: PEM)*/ + char *key; /* private key file name */ + char *key_type; /* format for private key (default: PEM) */ + char *key_passwd; /* plain text private key password */ +#ifdef USE_TLS_SRP + char *username; /* TLS username (for, e.g., SRP) */ + char *password; /* TLS password (for, e.g., SRP) */ + enum CURL_TLSAUTH authtype; /* TLS authentication type (default SRP) */ +#endif + bit certinfo:1; /* gather lots of certificate info */ + bit falsestart:1; + bit enable_beast:1; /* allow this flaw for interoperability's sake*/ + bit no_revoke:1; /* disable SSL certificate revocation checks */ +}; + +struct ssl_general_config { + size_t max_ssl_sessions; /* SSL session id cache size */ +}; + +/* information stored about one single SSL session */ +struct curl_ssl_session { + char *name; /* host name for which this ID was used */ + char *conn_to_host; /* host name for the connection (may be NULL) */ + const char *scheme; /* protocol scheme used */ + void *sessionid; /* as returned from the SSL layer */ + size_t idsize; /* if known, otherwise 0 */ + long age; /* just a number, the higher the more recent */ + int remote_port; /* remote port */ + int conn_to_port; /* remote port for the connection (may be -1) */ + struct ssl_primary_config ssl_config; /* setup for this session */ +}; + +#ifdef USE_WINDOWS_SSPI +#include "curl_sspi.h" +#endif + +/* Struct used for Digest challenge-response authentication */ +struct digestdata { +#if defined(USE_WINDOWS_SSPI) + BYTE *input_token; + size_t input_token_len; + CtxtHandle *http_context; + /* copy of user/passwd used to make the identity for http_context. + either may be NULL. */ + char *user; + char *passwd; +#else + char *nonce; + char *cnonce; + char *realm; + int algo; + char *opaque; + char *qop; + char *algorithm; + int nc; /* nounce count */ + bit stale:1; /* set true for re-negotiation */ + bit userhash:1; +#endif +}; + +typedef enum { + NTLMSTATE_NONE, + NTLMSTATE_TYPE1, + NTLMSTATE_TYPE2, + NTLMSTATE_TYPE3, + NTLMSTATE_LAST +} curlntlm; + +typedef enum { + GSS_AUTHNONE, + GSS_AUTHRECV, + GSS_AUTHSENT, + GSS_AUTHDONE, + GSS_AUTHSUCC +} curlnegotiate; + +#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV) +#include +#endif + +/* Struct used for GSSAPI (Kerberos V5) authentication */ +#if defined(USE_KERBEROS5) +struct kerberos5data { +#if defined(USE_WINDOWS_SSPI) + CredHandle *credentials; + CtxtHandle *context; + TCHAR *spn; + SEC_WINNT_AUTH_IDENTITY identity; + SEC_WINNT_AUTH_IDENTITY *p_identity; + size_t token_max; + BYTE *output_token; +#else + gss_ctx_id_t context; + gss_name_t spn; +#endif +}; +#endif + +/* Struct used for NTLM challenge-response authentication */ +#if defined(USE_NTLM) +struct ntlmdata { +#ifdef USE_WINDOWS_SSPI +/* The sslContext is used for the Schannel bindings. The + * api is available on the Windows 7 SDK and later. + */ +#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS + CtxtHandle *sslContext; +#endif + CredHandle *credentials; + CtxtHandle *context; + SEC_WINNT_AUTH_IDENTITY identity; + SEC_WINNT_AUTH_IDENTITY *p_identity; + size_t token_max; + BYTE *output_token; + BYTE *input_token; + size_t input_token_len; + TCHAR *spn; +#else + unsigned int flags; + unsigned char nonce[8]; + void *target_info; /* TargetInfo received in the ntlm type-2 message */ + unsigned int target_info_len; +#endif +}; +#endif + +/* Struct used for Negotiate (SPNEGO) authentication */ +#ifdef USE_SPNEGO +struct negotiatedata { +#ifdef HAVE_GSSAPI + OM_uint32 status; + gss_ctx_id_t context; + gss_name_t spn; + gss_buffer_desc output_token; +#else +#ifdef USE_WINDOWS_SSPI +#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS + CtxtHandle *sslContext; +#endif + DWORD status; + CredHandle *credentials; + CtxtHandle *context; + SEC_WINNT_AUTH_IDENTITY identity; + SEC_WINNT_AUTH_IDENTITY *p_identity; + TCHAR *spn; + size_t token_max; + BYTE *output_token; + size_t output_token_length; +#endif +#endif + bool noauthpersist; + bool havenoauthpersist; + bool havenegdata; + bool havemultiplerequests; +}; +#endif + + +/* + * Boolean values that concerns this connection. + */ +struct ConnectBits { + /* always modify bits.close with the connclose() and connkeep() macros! */ + bool proxy_ssl_connected[2]; /* TRUE when SSL initialization for HTTPS proxy + is complete */ + bool tcpconnect[2]; /* the TCP layer (or similar) is connected, this is set + the first time on the first connect function call */ + bit close:1; /* if set, we close the connection after this request */ + bit reuse:1; /* if set, this is a re-used connection */ + bit conn_to_host:1; /* if set, this connection has a "connect to host" + that overrides the host in the URL */ + bit conn_to_port:1; /* if set, this connection has a "connect to port" + that overrides the port in the URL (remote port) */ + bit proxy:1; /* if set, this transfer is done through a proxy - any type */ + bit httpproxy:1; /* if set, this transfer is done through a http proxy */ + bit socksproxy:1; /* if set, this transfer is done through a socks proxy */ + bit user_passwd:1; /* do we use user+password for this connection? */ + bit proxy_user_passwd:1; /* user+password for the proxy? */ + bit ipv6_ip:1; /* we communicate with a remote site specified with pure IPv6 + IP address */ + bit ipv6:1; /* we communicate with a site using an IPv6 address */ + bit do_more:1; /* this is set TRUE if the ->curl_do_more() function is + supposed to be called, after ->curl_do() */ + bit protoconnstart:1;/* the protocol layer has STARTED its operation after + the TCP layer connect */ + bit retry:1; /* this connection is about to get closed and then + re-attempted at another connection. */ + bit tunnel_proxy:1; /* if CONNECT is used to "tunnel" through the proxy. + This is implicit when SSL-protocols are used through + proxies, but can also be enabled explicitly by + apps */ + bit authneg:1; /* TRUE when the auth phase has started, which means + that we are creating a request with an auth header, + but it is not the final request in the auth + negotiation. */ + bit rewindaftersend:1;/* TRUE when the sending couldn't be stopped even + though it will be discarded. When the whole send + operation is done, we must call the data rewind + callback. */ +#ifndef CURL_DISABLE_FTP + bit ftp_use_epsv:1; /* As set with CURLOPT_FTP_USE_EPSV, but if we find out + EPSV doesn't work we disable it for the forthcoming + requests */ + bit ftp_use_eprt:1; /* As set with CURLOPT_FTP_USE_EPRT, but if we find out + EPRT doesn't work we disable it for the forthcoming + requests */ + bit ftp_use_data_ssl:1; /* Enabled SSL for the data connection */ +#endif + bit netrc:1; /* name+password provided by netrc */ + bit userpwd_in_url:1; /* name+password found in url */ + bit stream_was_rewound:1; /* The stream was rewound after a request read + past the end of its response byte boundary */ + bit proxy_connect_closed:1; /* TRUE if a proxy disconnected the connection + in a CONNECT request with auth, so that + libcurl should reconnect and continue. */ + bit bound:1; /* set true if bind() has already been done on this socket/ + connection */ + bit type_set:1; /* type= was used in the URL */ + bit multiplex:1; /* connection is multiplexed */ + bit tcp_fastopen:1; /* use TCP Fast Open */ + bit tls_enable_npn:1; /* TLS NPN extension? */ + bit tls_enable_alpn:1; /* TLS ALPN extension? */ + bit socksproxy_connecting:1; /* connecting through a socks proxy */ + bit connect_only:1; +}; + +struct hostname { + char *rawalloc; /* allocated "raw" version of the name */ + char *encalloc; /* allocated IDN-encoded version of the name */ + char *name; /* name to use internally, might be encoded, might be raw */ + const char *dispname; /* name to display, as 'name' might be encoded */ +}; + +/* + * Flags on the keepon member of the Curl_transfer_keeper + */ + +#define KEEP_NONE 0 +#define KEEP_RECV (1<<0) /* there is or may be data to read */ +#define KEEP_SEND (1<<1) /* there is or may be data to write */ +#define KEEP_RECV_HOLD (1<<2) /* when set, no reading should be done but there + might still be data to read */ +#define KEEP_SEND_HOLD (1<<3) /* when set, no writing should be done but there + might still be data to write */ +#define KEEP_RECV_PAUSE (1<<4) /* reading is paused */ +#define KEEP_SEND_PAUSE (1<<5) /* writing is paused */ + +#define KEEP_RECVBITS (KEEP_RECV | KEEP_RECV_HOLD | KEEP_RECV_PAUSE) +#define KEEP_SENDBITS (KEEP_SEND | KEEP_SEND_HOLD | KEEP_SEND_PAUSE) + +struct Curl_async { + char *hostname; + int port; + struct Curl_dns_entry *dns; + int status; /* if done is TRUE, this is the status from the callback */ + void *os_specific; /* 'struct thread_data' for Windows */ + bit done:1; /* set TRUE when the lookup is complete */ +}; + +#define FIRSTSOCKET 0 +#define SECONDARYSOCKET 1 + +/* These function pointer types are here only to allow easier typecasting + within the source when we need to cast between data pointers (such as NULL) + and function pointers. */ +typedef CURLcode (*Curl_do_more_func)(struct connectdata *, int *); +typedef CURLcode (*Curl_done_func)(struct connectdata *, CURLcode, bool); + +enum expect100 { + EXP100_SEND_DATA, /* enough waiting, just send the body now */ + EXP100_AWAITING_CONTINUE, /* waiting for the 100 Continue header */ + EXP100_SENDING_REQUEST, /* still sending the request but will wait for + the 100 header once done with the request */ + EXP100_FAILED /* used on 417 Expectation Failed */ +}; + +enum upgrade101 { + UPGR101_INIT, /* default state */ + UPGR101_REQUESTED, /* upgrade requested */ + UPGR101_RECEIVED, /* response received */ + UPGR101_WORKING /* talking upgraded protocol */ +}; + +struct dohresponse { + unsigned char *memory; + size_t size; +}; + +/* one of these for each DoH request */ +struct dnsprobe { + CURL *easy; + int dnstype; + unsigned char dohbuffer[512]; + size_t dohlen; + struct dohresponse serverdoh; +}; + +struct dohdata { + struct curl_slist *headers; + struct dnsprobe probe[2]; + unsigned int pending; /* still outstanding requests */ + const char *host; + int port; +}; + +/* + * Request specific data in the easy handle (Curl_easy). Previously, + * these members were on the connectdata struct but since a conn struct may + * now be shared between different Curl_easys, we store connection-specific + * data here. This struct only keeps stuff that's interesting for *this* + * request, as it will be cleared between multiple ones + */ +struct SingleRequest { + curl_off_t size; /* -1 if unknown at this point */ + curl_off_t maxdownload; /* in bytes, the maximum amount of data to fetch, + -1 means unlimited */ + curl_off_t bytecount; /* total number of bytes read */ + curl_off_t writebytecount; /* number of bytes written */ + + curl_off_t headerbytecount; /* only count received headers */ + curl_off_t deductheadercount; /* this amount of bytes doesn't count when we + check if anything has been transferred at + the end of a connection. We use this + counter to make only a 100 reply (without a + following second response code) result in a + CURLE_GOT_NOTHING error code */ + + struct curltime start; /* transfer started at this time */ + struct curltime now; /* current time */ + enum { + HEADER_NORMAL, /* no bad header at all */ + HEADER_PARTHEADER, /* part of the chunk is a bad header, the rest + is normal data */ + HEADER_ALLBAD /* all was believed to be header */ + } badheader; /* the header was deemed bad and will be + written as body */ + int headerline; /* counts header lines to better track the + first one */ + char *hbufp; /* points at *end* of header line */ + size_t hbuflen; + char *str; /* within buf */ + char *str_start; /* within buf */ + char *end_ptr; /* within buf */ + char *p; /* within headerbuff */ + curl_off_t offset; /* possible resume offset read from the + Content-Range: header */ + int httpcode; /* error code from the 'HTTP/1.? XXX' or + 'RTSP/1.? XXX' line */ + struct curltime start100; /* time stamp to wait for the 100 code from */ + enum expect100 exp100; /* expect 100 continue state */ + enum upgrade101 upgr101; /* 101 upgrade state */ + + struct contenc_writer_s *writer_stack; /* Content unencoding stack. */ + /* See sec 3.5, RFC2616. */ + time_t timeofdoc; + long bodywrites; + char *buf; + int keepon; + char *location; /* This points to an allocated version of the Location: + header data */ + char *newurl; /* Set to the new URL to use when a redirect or a retry is + wanted */ + + /* 'upload_present' is used to keep a byte counter of how much data there is + still left in the buffer, aimed for upload. */ + ssize_t upload_present; + + /* 'upload_fromhere' is used as a read-pointer when we uploaded parts of a + buffer, so the next read should read from where this pointer points to, + and the 'upload_present' contains the number of bytes available at this + position */ + char *upload_fromhere; + void *protop; /* Allocated protocol-specific data. Each protocol + handler makes sure this points to data it needs. */ +#ifndef CURL_DISABLE_DOH + struct dohdata doh; /* DoH specific data for this request */ +#endif + bit header:1; /* incoming data has HTTP header */ + bit content_range:1; /* set TRUE if Content-Range: was found */ + bit upload_done:1; /* set to TRUE when doing chunked transfer-encoding + upload and we're uploading the last chunk */ + bit ignorebody:1; /* we read a response-body but we ignore it! */ + bit ignorecl:1; /* This HTTP response has no body so we ignore the + Content-Length: header */ + bit chunk:1; /* if set, this is a chunked transfer-encoding */ + bit upload_chunky:1; /* set TRUE if we are doing chunked transfer-encoding + on upload */ + bit getheader:1; /* TRUE if header parsing is wanted */ + bit forbidchunk:1; /* used only to explicitly forbid chunk-upload for + specific upload buffers. See readmoredata() in http.c + for details. */ +}; + +/* + * Specific protocol handler. + */ + +struct Curl_handler { + const char *scheme; /* URL scheme name. */ + + /* Complement to setup_connection_internals(). */ + CURLcode (*setup_connection)(struct connectdata *); + + /* These two functions MUST be set to be protocol dependent */ + CURLcode (*do_it)(struct connectdata *, bool *done); + Curl_done_func done; + + /* If the curl_do() function is better made in two halves, this + * curl_do_more() function will be called afterwards, if set. For example + * for doing the FTP stuff after the PASV/PORT command. + */ + Curl_do_more_func do_more; + + /* This function *MAY* be set to a protocol-dependent function that is run + * after the connect() and everything is done, as a step in the connection. + * The 'done' pointer points to a bool that should be set to TRUE if the + * function completes before return. If it doesn't complete, the caller + * should call the curl_connecting() function until it is. + */ + CURLcode (*connect_it)(struct connectdata *, bool *done); + + /* See above. */ + CURLcode (*connecting)(struct connectdata *, bool *done); + CURLcode (*doing)(struct connectdata *, bool *done); + + /* Called from the multi interface during the PROTOCONNECT phase, and it + should then return a proper fd set */ + int (*proto_getsock)(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); + + /* Called from the multi interface during the DOING phase, and it should + then return a proper fd set */ + int (*doing_getsock)(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); + + /* Called from the multi interface during the DO_MORE phase, and it should + then return a proper fd set */ + int (*domore_getsock)(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); + + /* Called from the multi interface during the DO_DONE, PERFORM and + WAITPERFORM phases, and it should then return a proper fd set. Not setting + this will make libcurl use the generic default one. */ + int (*perform_getsock)(const struct connectdata *conn, + curl_socket_t *socks, + int numsocks); + + /* This function *MAY* be set to a protocol-dependent function that is run + * by the curl_disconnect(), as a step in the disconnection. If the handler + * is called because the connection has been considered dead, dead_connection + * is set to TRUE. + */ + CURLcode (*disconnect)(struct connectdata *, bool dead_connection); + + /* If used, this function gets called from transfer.c:readwrite_data() to + allow the protocol to do extra reads/writes */ + CURLcode (*readwrite)(struct Curl_easy *data, struct connectdata *conn, + ssize_t *nread, bool *readmore); + + /* This function can perform various checks on the connection. See + CONNCHECK_* for more information about the checks that can be performed, + and CONNRESULT_* for the results that can be returned. */ + unsigned int (*connection_check)(struct connectdata *conn, + unsigned int checks_to_perform); + + long defport; /* Default port. */ + unsigned int protocol; /* See CURLPROTO_* - this needs to be the single + specific protocol bit */ + unsigned int flags; /* Extra particular characteristics, see PROTOPT_* */ +}; + +#define PROTOPT_NONE 0 /* nothing extra */ +#define PROTOPT_SSL (1<<0) /* uses SSL */ +#define PROTOPT_DUAL (1<<1) /* this protocol uses two connections */ +#define PROTOPT_CLOSEACTION (1<<2) /* need action before socket close */ +/* some protocols will have to call the underlying functions without regard to + what exact state the socket signals. IE even if the socket says "readable", + the send function might need to be called while uploading, or vice versa. +*/ +#define PROTOPT_DIRLOCK (1<<3) +#define PROTOPT_NONETWORK (1<<4) /* protocol doesn't use the network! */ +#define PROTOPT_NEEDSPWD (1<<5) /* needs a password, and if none is set it + gets a default */ +#define PROTOPT_NOURLQUERY (1<<6) /* protocol can't handle + url query strings (?foo=bar) ! */ +#define PROTOPT_CREDSPERREQUEST (1<<7) /* requires login credentials per + request instead of per connection */ +#define PROTOPT_ALPN_NPN (1<<8) /* set ALPN and/or NPN for this */ +#define PROTOPT_STREAM (1<<9) /* a protocol with individual logical streams */ +#define PROTOPT_URLOPTIONS (1<<10) /* allow options part in the userinfo field + of the URL */ +#define PROTOPT_PROXY_AS_HTTP (1<<11) /* allow this non-HTTP scheme over a + HTTP proxy as HTTP proxies may know + this protocol and act as a gateway */ +#define PROTOPT_WILDCARD (1<<12) /* protocol supports wildcard matching */ + +#define CONNCHECK_NONE 0 /* No checks */ +#define CONNCHECK_ISDEAD (1<<0) /* Check if the connection is dead. */ +#define CONNCHECK_KEEPALIVE (1<<1) /* Perform any keepalive function. */ + +#define CONNRESULT_NONE 0 /* No extra information. */ +#define CONNRESULT_DEAD (1<<0) /* The connection is dead. */ + +#ifdef USE_RECV_BEFORE_SEND_WORKAROUND +struct postponed_data { + char *buffer; /* Temporal store for received data during + sending, must be freed */ + size_t allocated_size; /* Size of temporal store */ + size_t recv_size; /* Size of received data during sending */ + size_t recv_processed; /* Size of processed part of postponed data */ +#ifdef DEBUGBUILD + curl_socket_t bindsock;/* Structure must be bound to specific socket, + used only for DEBUGASSERT */ +#endif /* DEBUGBUILD */ +}; +#endif /* USE_RECV_BEFORE_SEND_WORKAROUND */ + +struct proxy_info { + struct hostname host; + long port; + curl_proxytype proxytype; /* what kind of proxy that is in use */ + char *user; /* proxy user name string, allocated */ + char *passwd; /* proxy password string, allocated */ +}; + +#define CONNECT_BUFFER_SIZE 16384 + +/* struct for HTTP CONNECT state data */ +struct http_connect_state { + char connect_buffer[CONNECT_BUFFER_SIZE]; + int perline; /* count bytes per line */ + int keepon; + char *line_start; + char *ptr; /* where to store more data */ + curl_off_t cl; /* size of content to read and ignore */ + enum { + TUNNEL_INIT, /* init/default/no tunnel state */ + TUNNEL_CONNECT, /* CONNECT has been sent off */ + TUNNEL_COMPLETE /* CONNECT response received completely */ + } tunnel_state; + bit chunked_encoding:1; + bit close_connection:1; +}; + +/* + * The connectdata struct contains all fields and variables that should be + * unique for an entire connection. + */ +struct connectdata { + /* 'data' is the CURRENT Curl_easy using this connection -- take great + caution that this might very well vary between different times this + connection is used! */ + struct Curl_easy *data; + + struct curl_llist_element bundle_node; /* conncache */ + + /* chunk is for HTTP chunked encoding, but is in the general connectdata + struct only because we can do just about any protocol through a HTTP proxy + and a HTTP proxy may in fact respond using chunked encoding */ + struct Curl_chunker chunk; + + curl_closesocket_callback fclosesocket; /* function closing the socket(s) */ + void *closesocket_client; + + /* This is used by the connection cache logic. If this returns TRUE, this + handle is still used by one or more easy handles and can only used by any + other easy handle without careful consideration (== only for + multiplexing) and it cannot be used by another multi handle! */ +#define CONN_INUSE(c) ((c)->easyq.size) + + /**** Fields set when inited and not modified again */ + long connection_id; /* Contains a unique number to make it easier to + track the connections in the log output */ + + /* 'dns_entry' is the particular host we use. This points to an entry in the + DNS cache and it will not get pruned while locked. It gets unlocked in + Curl_done(). This entry will be NULL if the connection is re-used as then + there is no name resolve done. */ + struct Curl_dns_entry *dns_entry; + + /* 'ip_addr' is the particular IP we connected to. It points to a struct + within the DNS cache, so this pointer is only valid as long as the DNS + cache entry remains locked. It gets unlocked in Curl_done() */ + Curl_addrinfo *ip_addr; + Curl_addrinfo *tempaddr[2]; /* for happy eyeballs */ + + /* 'ip_addr_str' is the ip_addr data as a human readable string. + It remains available as long as the connection does, which is longer than + the ip_addr itself. */ + char ip_addr_str[MAX_IPADR_LEN]; + + unsigned int scope_id; /* Scope id for IPv6 */ + + int socktype; /* SOCK_STREAM or SOCK_DGRAM */ + + struct hostname host; + char *hostname_resolve; /* host name to resolve to address, allocated */ + char *secondaryhostname; /* secondary socket host name (ftp) */ + struct hostname conn_to_host; /* the host to connect to. valid only if + bits.conn_to_host is set */ + + struct proxy_info socks_proxy; + struct proxy_info http_proxy; + + long port; /* which port to use locally */ + int remote_port; /* the remote port, not the proxy port! */ + int conn_to_port; /* the remote port to connect to. valid only if + bits.conn_to_port is set */ + unsigned short secondary_port; /* secondary socket remote port to connect to + (ftp) */ + + /* 'primary_ip' and 'primary_port' get filled with peer's numerical + ip address and port number whenever an outgoing connection is + *attempted* from the primary socket to a remote address. When more + than one address is tried for a connection these will hold data + for the last attempt. When the connection is actually established + these are updated with data which comes directly from the socket. */ + + char primary_ip[MAX_IPADR_LEN]; + long primary_port; + + /* 'local_ip' and 'local_port' get filled with local's numerical + ip address and port number whenever an outgoing connection is + **established** from the primary socket to a remote address. */ + + char local_ip[MAX_IPADR_LEN]; + long local_port; + + char *user; /* user name string, allocated */ + char *passwd; /* password string, allocated */ + char *options; /* options string, allocated */ + + char *oauth_bearer; /* bearer token for OAuth 2.0, allocated */ + + int httpversion; /* the HTTP version*10 reported by the server */ + int rtspversion; /* the RTSP version*10 reported by the server */ + + struct curltime now; /* "current" time */ + struct curltime created; /* creation time */ + struct curltime lastused; /* when returned to the connection cache */ + curl_socket_t sock[2]; /* two sockets, the second is used for the data + transfer when doing FTP */ + curl_socket_t tempsock[2]; /* temporary sockets for happy eyeballs */ + bool sock_accepted[2]; /* TRUE if the socket on this index was created with + accept() */ + Curl_recv *recv[2]; + Curl_send *send[2]; + +#ifdef USE_RECV_BEFORE_SEND_WORKAROUND + struct postponed_data postponed[2]; /* two buffers for two sockets */ +#endif /* USE_RECV_BEFORE_SEND_WORKAROUND */ + struct ssl_connect_data ssl[2]; /* this is for ssl-stuff */ + struct ssl_connect_data proxy_ssl[2]; /* this is for proxy ssl-stuff */ +#ifdef USE_SSL + void *ssl_extra; /* separately allocated backend-specific data */ +#endif + struct ssl_primary_config ssl_config; + struct ssl_primary_config proxy_ssl_config; + struct ConnectBits bits; /* various state-flags for this connection */ + + /* connecttime: when connect() is called on the current IP address. Used to + be able to track when to move on to try next IP - but only when the multi + interface is used. */ + struct curltime connecttime; + /* The two fields below get set in Curl_connecthost */ + int num_addr; /* number of addresses to try to connect to */ + time_t timeoutms_per_addr; /* how long time in milliseconds to spend on + trying to connect to each IP address */ + + const struct Curl_handler *handler; /* Connection's protocol handler */ + const struct Curl_handler *given; /* The protocol first given */ + + long ip_version; /* copied from the Curl_easy at creation time */ + + /* Protocols can use a custom keepalive mechanism to keep connections alive. + This allows those protocols to track the last time the keepalive mechanism + was used on this connection. */ + struct curltime keepalive; + + long upkeep_interval_ms; /* Time between calls for connection upkeep. */ + + /**** curl_get() phase fields */ + + curl_socket_t sockfd; /* socket to read from or CURL_SOCKET_BAD */ + curl_socket_t writesockfd; /* socket to write to, it may very + well be the same we read from. + CURL_SOCKET_BAD disables */ + + /** Dynamically allocated strings, MUST be freed before this **/ + /** struct is killed. **/ + struct dynamically_allocated_data { + char *proxyuserpwd; + char *uagent; + char *accept_encoding; + char *userpwd; + char *rangeline; + char *ref; + char *host; + char *cookiehost; + char *rtsp_transport; + char *te; /* TE: request header */ + } allocptr; + +#ifdef HAVE_GSSAPI + bit sec_complete:1; /* if Kerberos is enabled for this connection */ + enum protection_level command_prot; + enum protection_level data_prot; + enum protection_level request_data_prot; + size_t buffer_size; + struct krb5buffer in_buffer; + void *app_data; + const struct Curl_sec_client_mech *mech; + struct sockaddr_in local_addr; +#endif + +#if defined(USE_KERBEROS5) /* Consider moving some of the above GSS-API */ + struct kerberos5data krb5; /* variables into the structure definition, */ +#endif /* however, some of them are ftp specific. */ + + struct curl_llist easyq; /* List of easy handles using this connection */ + curl_seek_callback seek_func; /* function that seeks the input */ + void *seek_client; /* pointer to pass to the seek() above */ + + /*************** Request - specific items ************/ +#if defined(USE_WINDOWS_SSPI) && defined(SECPKG_ATTR_ENDPOINT_BINDINGS) + CtxtHandle *sslContext; +#endif + +#if defined(USE_NTLM) + curlntlm http_ntlm_state; + curlntlm proxy_ntlm_state; + + struct ntlmdata ntlm; /* NTLM differs from other authentication schemes + because it authenticates connections, not + single requests! */ + struct ntlmdata proxyntlm; /* NTLM data for proxy */ + +#if defined(NTLM_WB_ENABLED) + /* used for communication with Samba's winbind daemon helper ntlm_auth */ + curl_socket_t ntlm_auth_hlpr_socket; + pid_t ntlm_auth_hlpr_pid; + char *challenge_header; + char *response_header; +#endif +#endif + +#ifdef USE_SPNEGO + curlnegotiate http_negotiate_state; + curlnegotiate proxy_negotiate_state; + + struct negotiatedata negotiate; /* state data for host Negotiate auth */ + struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */ +#endif + + /* data used for the asynch name resolve callback */ + struct Curl_async async; + + /* These three are used for chunked-encoding trailer support */ + char *trailer; /* allocated buffer to store trailer in */ + int trlMax; /* allocated buffer size */ + int trlPos; /* index of where to store data */ + + union { + struct ftp_conn ftpc; + struct http_conn httpc; + struct ssh_conn sshc; + struct tftp_state_data *tftpc; + struct imap_conn imapc; + struct pop3_conn pop3c; + struct smtp_conn smtpc; + struct rtsp_conn rtspc; + struct smb_conn smbc; + void *generic; /* RTMP and LDAP use this */ + } proto; + + int cselect_bits; /* bitmask of socket events */ + int waitfor; /* current READ/WRITE bits to wait for */ + +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + int socks5_gssapi_enctype; +#endif + + /* When this connection is created, store the conditions for the local end + bind. This is stored before the actual bind and before any connection is + made and will serve the purpose of being used for comparison reasons so + that subsequent bound-requested connections aren't accidentally re-using + wrong connections. */ + char *localdev; + unsigned short localport; + int localportrange; + struct http_connect_state *connect_state; /* for HTTP CONNECT */ + struct connectbundle *bundle; /* The bundle we are member of */ + int negnpn; /* APLN or NPN TLS negotiated protocol, CURL_HTTP_VERSION* */ + +#ifdef USE_UNIX_SOCKETS + char *unix_domain_socket; + bit abstract_unix_socket:1; +#endif + bit tls_upgraded:1; + /* the two following *_inuse fields are only flags, not counters in any way. + If TRUE it means the channel is in use, and if FALSE it means the channel + is up for grabs by one. */ + bit readchannel_inuse:1; /* whether the read channel is in use by an easy + handle */ + bit writechannel_inuse:1; /* whether the write channel is in use by an easy + handle */ +}; + +/* The end of connectdata. */ + +/* + * Struct to keep statistical and informational data. + * All variables in this struct must be initialized/reset in Curl_initinfo(). + */ +struct PureInfo { + int httpcode; /* Recent HTTP, FTP, RTSP or SMTP response code */ + int httpproxycode; /* response code from proxy when received separate */ + int httpversion; /* the http version number X.Y = X*10+Y */ + time_t filetime; /* If requested, this is might get set. Set to -1 if the + time was unretrievable. */ + curl_off_t header_size; /* size of read header(s) in bytes */ + curl_off_t request_size; /* the amount of bytes sent in the request(s) */ + unsigned long proxyauthavail; /* what proxy auth types were announced */ + unsigned long httpauthavail; /* what host auth types were announced */ + long numconnects; /* how many new connection did libcurl created */ + char *contenttype; /* the content type of the object */ + char *wouldredirect; /* URL this would've been redirected to if asked to */ + + /* PureInfo members 'conn_primary_ip', 'conn_primary_port', 'conn_local_ip' + and, 'conn_local_port' are copied over from the connectdata struct in + order to allow curl_easy_getinfo() to return this information even when + the session handle is no longer associated with a connection, and also + allow curl_easy_reset() to clear this information from the session handle + without disturbing information which is still alive, and that might be + reused, in the connection cache. */ + + char conn_primary_ip[MAX_IPADR_LEN]; + long conn_primary_port; + char conn_local_ip[MAX_IPADR_LEN]; + long conn_local_port; + const char *conn_scheme; + unsigned int conn_protocol; + struct curl_certinfo certs; /* info about the certs, only populated in + OpenSSL builds. Asked for with + CURLOPT_CERTINFO / CURLINFO_CERTINFO */ + + bit timecond:1; /* set to TRUE if the time condition didn't match, which + thus made the document NOT get fetched */ +}; + + +struct Progress { + time_t lastshow; /* time() of the last displayed progress meter or NULL to + force redraw at next call */ + curl_off_t size_dl; /* total expected size */ + curl_off_t size_ul; /* total expected size */ + curl_off_t downloaded; /* transferred so far */ + curl_off_t uploaded; /* transferred so far */ + + curl_off_t current_speed; /* uses the currently fastest transfer */ + + int width; /* screen width at download start */ + int flags; /* see progress.h */ + + time_t timespent; + + curl_off_t dlspeed; + curl_off_t ulspeed; + + time_t t_nslookup; + time_t t_connect; + time_t t_appconnect; + time_t t_pretransfer; + time_t t_starttransfer; + time_t t_redirect; + + struct curltime start; + struct curltime t_startsingle; + struct curltime t_startop; + struct curltime t_acceptdata; + + + /* upload speed limit */ + struct curltime ul_limit_start; + curl_off_t ul_limit_size; + /* download speed limit */ + struct curltime dl_limit_start; + curl_off_t dl_limit_size; + +#define CURR_TIME (5 + 1) /* 6 entries for 5 seconds */ + + curl_off_t speeder[ CURR_TIME ]; + struct curltime speeder_time[ CURR_TIME ]; + int speeder_c; + bit callback:1; /* set when progress callback is used */ + bit is_t_startransfer_set:1; +}; + +typedef enum { + HTTPREQ_NONE, /* first in list */ + HTTPREQ_GET, + HTTPREQ_POST, + HTTPREQ_POST_FORM, /* we make a difference internally */ + HTTPREQ_POST_MIME, /* we make a difference internally */ + HTTPREQ_PUT, + HTTPREQ_HEAD, + HTTPREQ_OPTIONS, + HTTPREQ_LAST /* last in list */ +} Curl_HttpReq; + +typedef enum { + RTSPREQ_NONE, /* first in list */ + RTSPREQ_OPTIONS, + RTSPREQ_DESCRIBE, + RTSPREQ_ANNOUNCE, + RTSPREQ_SETUP, + RTSPREQ_PLAY, + RTSPREQ_PAUSE, + RTSPREQ_TEARDOWN, + RTSPREQ_GET_PARAMETER, + RTSPREQ_SET_PARAMETER, + RTSPREQ_RECORD, + RTSPREQ_RECEIVE, + RTSPREQ_LAST /* last in list */ +} Curl_RtspReq; + +/* + * Values that are generated, temporary or calculated internally for a + * "session handle" must be defined within the 'struct UrlState'. This struct + * will be used within the Curl_easy struct. When the 'Curl_easy' + * struct is cloned, this data MUST NOT be copied. + * + * Remember that any "state" information goes globally for the curl handle. + * Session-data MUST be put in the connectdata struct and here. */ +#define MAX_CURL_USER_LENGTH 256 +#define MAX_CURL_PASSWORD_LENGTH 256 + +struct auth { + unsigned long want; /* Bitmask set to the authentication methods wanted by + app (with CURLOPT_HTTPAUTH or CURLOPT_PROXYAUTH). */ + unsigned long picked; + unsigned long avail; /* Bitmask for what the server reports to support for + this resource */ + bit done:1; /* TRUE when the auth phase is done and ready to do the + *actual* request */ + bit multipass:1; /* TRUE if this is not yet authenticated but within the + auth multipass negotiation */ + bit iestyle:1; /* TRUE if digest should be done IE-style or FALSE if it + should be RFC compliant */ +}; + +struct Curl_http2_dep { + struct Curl_http2_dep *next; + struct Curl_easy *data; +}; + +/* + * This struct is for holding data that was attempted to get sent to the user's + * callback but is held due to pausing. One instance per type (BOTH, HEADER, + * BODY). + */ +struct tempbuf { + char *buf; /* allocated buffer to keep data in when a write callback + returns to make the connection paused */ + size_t len; /* size of the 'tempwrite' allocated buffer */ + int type; /* type of the 'tempwrite' buffer as a bitmask that is used with + Curl_client_write() */ +}; + +/* Timers */ +typedef enum { + EXPIRE_100_TIMEOUT, + EXPIRE_ASYNC_NAME, + EXPIRE_CONNECTTIMEOUT, + EXPIRE_DNS_PER_NAME, + EXPIRE_HAPPY_EYEBALLS_DNS, /* See asyn-ares.c */ + EXPIRE_HAPPY_EYEBALLS, + EXPIRE_MULTI_PENDING, + EXPIRE_RUN_NOW, + EXPIRE_SPEEDCHECK, + EXPIRE_TIMEOUT, + EXPIRE_TOOFAST, + EXPIRE_LAST /* not an actual timer, used as a marker only */ +} expire_id; + + +typedef enum { + TRAILERS_NONE, + TRAILERS_INITIALIZED, + TRAILERS_SENDING, + TRAILERS_DONE +} trailers_state; + + +/* + * One instance for each timeout an easy handle can set. + */ +struct time_node { + struct curl_llist_element list; + struct curltime time; + expire_id eid; +}; + +/* individual pieces of the URL */ +struct urlpieces { + char *scheme; + char *hostname; + char *port; + char *user; + char *password; + char *options; + char *path; + char *query; +}; + +struct UrlState { + + /* Points to the connection cache */ + struct conncache *conn_cache; + + /* buffers to store authentication data in, as parsed from input options */ + struct curltime keeps_speed; /* for the progress meter really */ + + struct connectdata *lastconnect; /* The last connection, NULL if undefined */ + + char *headerbuff; /* allocated buffer to store headers in */ + size_t headersize; /* size of the allocation */ + + char *buffer; /* download buffer */ + char *ulbuf; /* allocated upload buffer or NULL */ + curl_off_t current_speed; /* the ProgressShow() function sets this, + bytes / second */ + char *first_host; /* host name of the first (not followed) request. + if set, this should be the host name that we will + sent authorization to, no else. Used to make Location: + following not keep sending user+password... This is + strdup() data. + */ + int first_remote_port; /* remote port of the first (not followed) request */ + struct curl_ssl_session *session; /* array of 'max_ssl_sessions' size */ + long sessionage; /* number of the most recent session */ + unsigned int tempcount; /* number of entries in use in tempwrite, 0 - 3 */ + struct tempbuf tempwrite[3]; /* BOTH, HEADER, BODY */ + char *scratch; /* huge buffer[set.buffer_size*2] for upload CRLF replacing */ + int os_errno; /* filled in with errno whenever an error occurs */ +#ifdef HAVE_SIGNAL + /* storage for the previous bag^H^H^HSIGPIPE signal handler :-) */ + void (*prev_signal)(int sig); +#endif + struct digestdata digest; /* state data for host Digest auth */ + struct digestdata proxydigest; /* state data for proxy Digest auth */ + + struct auth authhost; /* auth details for host */ + struct auth authproxy; /* auth details for proxy */ + void *resolver; /* resolver state, if it is used in the URL state - + ares_channel f.e. */ + +#if defined(USE_OPENSSL) + /* void instead of ENGINE to avoid bleeding OpenSSL into this header */ + void *engine; +#endif /* USE_OPENSSL */ + struct curltime expiretime; /* set this with Curl_expire() only */ + struct Curl_tree timenode; /* for the splay stuff */ + struct curl_llist timeoutlist; /* list of pending timeouts */ + struct time_node expires[EXPIRE_LAST]; /* nodes for each expire type */ + + /* a place to store the most recently set FTP entrypath */ + char *most_recent_ftp_entrypath; + + int httpversion; /* the lowest HTTP version*10 reported by any server + involved in this request */ + +#if !defined(WIN32) && !defined(MSDOS) && !defined(__EMX__) && \ + !defined(__SYMBIAN32__) +/* do FTP line-end conversions on most platforms */ +#define CURL_DO_LINEEND_CONV + /* for FTP downloads: track CRLF sequences that span blocks */ + bit prev_block_had_trailing_cr:1; + /* for FTP downloads: how many CRLFs did we converted to LFs? */ + curl_off_t crlf_conversions; +#endif + char *range; /* range, if used. See README for detailed specification on + this syntax. */ + curl_off_t resume_from; /* continue [ftp] transfer from here */ + + /* This RTSP state information survives requests and connections */ + long rtsp_next_client_CSeq; /* the session's next client CSeq */ + long rtsp_next_server_CSeq; /* the session's next server CSeq */ + long rtsp_CSeq_recv; /* most recent CSeq received */ + + curl_off_t infilesize; /* size of file to upload, -1 means unknown. + Copied from set.filesize at start of operation */ + + size_t drain; /* Increased when this stream has data to read, even if its + socket is not necessarily is readable. Decreased when + checked. */ + + curl_read_callback fread_func; /* read callback/function */ + void *in; /* CURLOPT_READDATA */ + + struct Curl_easy *stream_depends_on; + int stream_weight; + CURLU *uh; /* URL handle for the current parsed URL */ + struct urlpieces up; +#ifndef CURL_DISABLE_HTTP + size_t trailers_bytes_sent; + Curl_send_buffer *trailers_buf; /* a buffer containing the compiled trailing + headers */ +#endif + trailers_state trailers_state; /* whether we are sending trailers + and what stage are we at */ +#ifdef CURLDEBUG + bit conncache_lock:1; +#endif + /* when curl_easy_perform() is called, the multi handle is "owned" by + the easy handle so curl_easy_cleanup() on such an easy handle will + also close the multi handle! */ + bit multi_owned_by_easy:1; + + bit this_is_a_follow:1; /* this is a followed Location: request */ + bit refused_stream:1; /* this was refused, try again */ + bit errorbuf:1; /* Set to TRUE if the error buffer is already filled in. + This must be set to FALSE every time _easy_perform() is + called. */ + bit allow_port:1; /* Is set.use_port allowed to take effect or not. This + is always set TRUE when curl_easy_perform() is called. */ + bit authproblem:1; /* TRUE if there's some problem authenticating */ + /* set after initial USER failure, to prevent an authentication loop */ + bit ftp_trying_alternative:1; + bit wildcardmatch:1; /* enable wildcard matching */ + bit expect100header:1; /* TRUE if we added Expect: 100-continue */ + bit use_range:1; + bit rangestringalloc:1; /* the range string is malloc()'ed */ + bit done:1; /* set to FALSE when Curl_init_do() is called and set to TRUE + when multi_done() is called, to prevent multi_done() to get + invoked twice when the multi interface is used. */ + bit stream_depends_e:1; /* set or don't set the Exclusive bit */ + bit previouslypending:1; /* this transfer WAS in the multi->pending queue */ +}; + + +/* + * This 'DynamicStatic' struct defines dynamic states that actually change + * values in the 'UserDefined' area, which MUST be taken into consideration + * if the UserDefined struct is cloned or similar. You can probably just + * copy these, but each one indicate a special action on other data. + */ + +struct DynamicStatic { + char *url; /* work URL, copied from UserDefined */ + char *referer; /* referer string */ + struct curl_slist *cookielist; /* list of cookie files set by + curl_easy_setopt(COOKIEFILE) calls */ + struct curl_slist *resolve; /* set to point to the set.resolve list when + this should be dealt with in pretransfer */ + bit url_alloc:1; /* URL string is malloc()'ed */ + bit referer_alloc:1; /* referer string is malloc()ed */ + bit wildcard_resolve:1; /* Set to true if any resolve change is a + wildcard */ +}; + +/* + * This 'UserDefined' struct must only contain data that is set once to go + * for many (perhaps) independent connections. Values that are generated or + * calculated internally for the "session handle" MUST be defined within the + * 'struct UrlState' instead. The only exceptions MUST note the changes in + * the 'DynamicStatic' struct. + * Character pointer fields point to dynamic storage, unless otherwise stated. + */ + +struct Curl_multi; /* declared and used only in multi.c */ + +enum dupstring { + STRING_CERT_ORIG, /* client certificate file name */ + STRING_CERT_PROXY, /* client certificate file name */ + STRING_CERT_TYPE_ORIG, /* format for certificate (default: PEM)*/ + STRING_CERT_TYPE_PROXY, /* format for certificate (default: PEM)*/ + STRING_COOKIE, /* HTTP cookie string to send */ + STRING_COOKIEJAR, /* dump all cookies to this file */ + STRING_CUSTOMREQUEST, /* HTTP/FTP/RTSP request/method to use */ + STRING_DEFAULT_PROTOCOL, /* Protocol to use when the URL doesn't specify */ + STRING_DEVICE, /* local network interface/address to use */ + STRING_ENCODING, /* Accept-Encoding string */ + STRING_FTP_ACCOUNT, /* ftp account data */ + STRING_FTP_ALTERNATIVE_TO_USER, /* command to send if USER/PASS fails */ + STRING_FTPPORT, /* port to send with the FTP PORT command */ + STRING_KEY_ORIG, /* private key file name */ + STRING_KEY_PROXY, /* private key file name */ + STRING_KEY_PASSWD_ORIG, /* plain text private key password */ + STRING_KEY_PASSWD_PROXY, /* plain text private key password */ + STRING_KEY_TYPE_ORIG, /* format for private key (default: PEM) */ + STRING_KEY_TYPE_PROXY, /* format for private key (default: PEM) */ + STRING_KRB_LEVEL, /* krb security level */ + STRING_NETRC_FILE, /* if not NULL, use this instead of trying to find + $HOME/.netrc */ + STRING_PROXY, /* proxy to use */ + STRING_PRE_PROXY, /* pre socks proxy to use */ + STRING_SET_RANGE, /* range, if used */ + STRING_SET_REFERER, /* custom string for the HTTP referer field */ + STRING_SET_URL, /* what original URL to work on */ + STRING_SSL_CAPATH_ORIG, /* CA directory name (doesn't work on windows) */ + STRING_SSL_CAPATH_PROXY, /* CA directory name (doesn't work on windows) */ + STRING_SSL_CAFILE_ORIG, /* certificate file to verify peer against */ + STRING_SSL_CAFILE_PROXY, /* certificate file to verify peer against */ + STRING_SSL_PINNEDPUBLICKEY_ORIG, /* public key file to verify peer against */ + STRING_SSL_PINNEDPUBLICKEY_PROXY, /* public key file to verify proxy */ + STRING_SSL_CIPHER_LIST_ORIG, /* list of ciphers to use */ + STRING_SSL_CIPHER_LIST_PROXY, /* list of ciphers to use */ + STRING_SSL_CIPHER13_LIST_ORIG, /* list of TLS 1.3 ciphers to use */ + STRING_SSL_CIPHER13_LIST_PROXY, /* list of TLS 1.3 ciphers to use */ + STRING_SSL_EGDSOCKET, /* path to file containing the EGD daemon socket */ + STRING_SSL_RANDOM_FILE, /* path to file containing "random" data */ + STRING_USERAGENT, /* User-Agent string */ + STRING_SSL_CRLFILE_ORIG, /* crl file to check certificate */ + STRING_SSL_CRLFILE_PROXY, /* crl file to check certificate */ + STRING_SSL_ISSUERCERT_ORIG, /* issuer cert file to check certificate */ + STRING_SSL_ISSUERCERT_PROXY, /* issuer cert file to check certificate */ + STRING_SSL_ENGINE, /* name of ssl engine */ + STRING_USERNAME, /* , if used */ + STRING_PASSWORD, /* , if used */ + STRING_OPTIONS, /* , if used */ + STRING_PROXYUSERNAME, /* Proxy , if used */ + STRING_PROXYPASSWORD, /* Proxy , if used */ + STRING_NOPROXY, /* List of hosts which should not use the proxy, if + used */ + STRING_RTSP_SESSION_ID, /* Session ID to use */ + STRING_RTSP_STREAM_URI, /* Stream URI for this request */ + STRING_RTSP_TRANSPORT, /* Transport for this session */ +#ifdef USE_SSH + STRING_SSH_PRIVATE_KEY, /* path to the private key file for auth */ + STRING_SSH_PUBLIC_KEY, /* path to the public key file for auth */ + STRING_SSH_HOST_PUBLIC_KEY_MD5, /* md5 of host public key in ascii hex */ + STRING_SSH_KNOWNHOSTS, /* file name of knownhosts file */ +#endif + STRING_PROXY_SERVICE_NAME, /* Proxy service name */ + STRING_SERVICE_NAME, /* Service name */ + STRING_MAIL_FROM, + STRING_MAIL_AUTH, + +#ifdef USE_TLS_SRP + STRING_TLSAUTH_USERNAME_ORIG, /* TLS auth */ + STRING_TLSAUTH_USERNAME_PROXY, /* TLS auth */ + STRING_TLSAUTH_PASSWORD_ORIG, /* TLS auth */ + STRING_TLSAUTH_PASSWORD_PROXY, /* TLS auth */ +#endif + STRING_BEARER, /* , if used */ +#ifdef USE_UNIX_SOCKETS + STRING_UNIX_SOCKET_PATH, /* path to Unix socket, if used */ +#endif + STRING_TARGET, /* CURLOPT_REQUEST_TARGET */ + STRING_DOH, /* CURLOPT_DOH_URL */ +#ifdef USE_ALTSVC + STRING_ALTSVC, /* CURLOPT_ALTSVC */ +#endif + /* -- end of zero-terminated strings -- */ + + STRING_LASTZEROTERMINATED, + + /* -- below this are pointers to binary data that cannot be strdup'ed. --- */ + + STRING_COPYPOSTFIELDS, /* if POST, set the fields' values here */ + + STRING_LAST /* not used, just an end-of-list marker */ +}; + +/* callback that gets called when this easy handle is completed within a multi + handle. Only used for internally created transfers, like for example + DoH. */ +typedef int (*multidone_func)(struct Curl_easy *easy, CURLcode result); + +struct UserDefined { + FILE *err; /* the stderr user data goes here */ + void *debugdata; /* the data that will be passed to fdebug */ + char *errorbuffer; /* (Static) store failure messages in here */ + long proxyport; /* If non-zero, use this port number by default. If the + proxy string features a ":[port]" that one will override + this. */ + void *out; /* CURLOPT_WRITEDATA */ + void *in_set; /* CURLOPT_READDATA */ + void *writeheader; /* write the header to this if non-NULL */ + void *rtp_out; /* write RTP to this if non-NULL */ + long use_port; /* which port to use (when not using default) */ + unsigned long httpauth; /* kind of HTTP authentication to use (bitmask) */ + unsigned long proxyauth; /* kind of proxy authentication to use (bitmask) */ + unsigned long socks5auth;/* kind of SOCKS5 authentication to use (bitmask) */ + long followlocation; /* as in HTTP Location: */ + long maxredirs; /* maximum no. of http(s) redirects to follow, set to -1 + for infinity */ + + int keep_post; /* keep POSTs as POSTs after a 30x request; each + bit represents a request, from 301 to 303 */ + void *postfields; /* if POST, set the fields' values here */ + curl_seek_callback seek_func; /* function that seeks the input */ + curl_off_t postfieldsize; /* if POST, this might have a size to use instead + of strlen(), and then the data *may* be binary + (contain zero bytes) */ + unsigned short localport; /* local port number to bind to */ + int localportrange; /* number of additional port numbers to test in case the + 'localport' one can't be bind()ed */ + curl_write_callback fwrite_func; /* function that stores the output */ + curl_write_callback fwrite_header; /* function that stores headers */ + curl_write_callback fwrite_rtp; /* function that stores interleaved RTP */ + curl_read_callback fread_func_set; /* function that reads the input */ + curl_progress_callback fprogress; /* OLD and deprecated progress callback */ + curl_xferinfo_callback fxferinfo; /* progress callback */ + curl_debug_callback fdebug; /* function that write informational data */ + curl_ioctl_callback ioctl_func; /* function for I/O control */ + curl_sockopt_callback fsockopt; /* function for setting socket options */ + void *sockopt_client; /* pointer to pass to the socket options callback */ + curl_opensocket_callback fopensocket; /* function for checking/translating + the address and opening the + socket */ + void *opensocket_client; + curl_closesocket_callback fclosesocket; /* function for closing the + socket */ + void *closesocket_client; + + void *seek_client; /* pointer to pass to the seek callback */ + /* the 3 curl_conv_callback functions below are used on non-ASCII hosts */ + /* function to convert from the network encoding: */ + curl_conv_callback convfromnetwork; + /* function to convert to the network encoding: */ + curl_conv_callback convtonetwork; + /* function to convert from UTF-8 encoding: */ + curl_conv_callback convfromutf8; + + void *progress_client; /* pointer to pass to the progress callback */ + void *ioctl_client; /* pointer to pass to the ioctl callback */ + long timeout; /* in milliseconds, 0 means no timeout */ + long connecttimeout; /* in milliseconds, 0 means no timeout */ + long accepttimeout; /* in milliseconds, 0 means no timeout */ + long happy_eyeballs_timeout; /* in milliseconds, 0 is a valid value */ + long server_response_timeout; /* in milliseconds, 0 means no timeout */ + long maxage_conn; /* in seconds, max idle time to allow a connection that + is to be reused */ + long tftp_blksize; /* in bytes, 0 means use default */ + curl_off_t filesize; /* size of file to upload, -1 means unknown */ + long low_speed_limit; /* bytes/second */ + long low_speed_time; /* number of seconds */ + curl_off_t max_send_speed; /* high speed limit in bytes/second for upload */ + curl_off_t max_recv_speed; /* high speed limit in bytes/second for + download */ + curl_off_t set_resume_from; /* continue [ftp] transfer from here */ + struct curl_slist *headers; /* linked list of extra headers */ + struct curl_slist *proxyheaders; /* linked list of extra CONNECT headers */ + struct curl_httppost *httppost; /* linked list of old POST data */ + curl_mimepart mimepost; /* MIME/POST data. */ + struct curl_slist *quote; /* after connection is established */ + struct curl_slist *postquote; /* after the transfer */ + struct curl_slist *prequote; /* before the transfer, after type */ + struct curl_slist *source_quote; /* 3rd party quote */ + struct curl_slist *source_prequote; /* in 3rd party transfer mode - before + the transfer on source host */ + struct curl_slist *source_postquote; /* in 3rd party transfer mode - after + the transfer on source host */ + struct curl_slist *telnet_options; /* linked list of telnet options */ + struct curl_slist *resolve; /* list of names to add/remove from + DNS cache */ + struct curl_slist *connect_to; /* list of host:port mappings to override + the hostname and port to connect to */ + curl_TimeCond timecondition; /* kind of time/date comparison */ + time_t timevalue; /* what time to compare with */ + Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */ + long httpversion; /* when non-zero, a specific HTTP version requested to + be used in the library's request(s) */ + struct ssl_config_data ssl; /* user defined SSL stuff */ + struct ssl_config_data proxy_ssl; /* user defined SSL stuff for proxy */ + struct ssl_general_config general_ssl; /* general user defined SSL stuff */ + curl_proxytype proxytype; /* what kind of proxy that is in use */ + long dns_cache_timeout; /* DNS cache timeout */ + long buffer_size; /* size of receive buffer to use */ + size_t upload_buffer_size; /* size of upload buffer to use, + keep it >= CURL_MAX_WRITE_SIZE */ + void *private_data; /* application-private data */ + struct curl_slist *http200aliases; /* linked list of aliases for http200 */ + long ipver; /* the CURL_IPRESOLVE_* defines in the public header file + 0 - whatever, 1 - v2, 2 - v6 */ + curl_off_t max_filesize; /* Maximum file size to download */ +#ifndef CURL_DISABLE_FTP + curl_ftpfile ftp_filemethod; /* how to get to a file when FTP is used */ + curl_ftpauth ftpsslauth; /* what AUTH XXX to be attempted */ + curl_ftpccc ftp_ccc; /* FTP CCC options */ +#endif + int ftp_create_missing_dirs; /* 1 - create directories that don't exist + 2 - the same but also allow MKD to fail once + */ + curl_sshkeycallback ssh_keyfunc; /* key matching callback */ + void *ssh_keyfunc_userp; /* custom pointer to callback */ + enum CURL_NETRC_OPTION + use_netrc; /* defined in include/curl.h */ + curl_usessl use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or + IMAP or POP3 or others! */ + long new_file_perms; /* Permissions to use when creating remote files */ + long new_directory_perms; /* Permissions to use when creating remote dirs */ + long ssh_auth_types; /* allowed SSH auth types */ + char *str[STRING_LAST]; /* array of strings, pointing to allocated memory */ + unsigned int scope_id; /* Scope id for IPv6 */ + long allowed_protocols; + long redir_protocols; + struct curl_slist *mail_rcpt; /* linked list of mail recipients */ + /* Common RTSP header options */ + Curl_RtspReq rtspreq; /* RTSP request type */ + long rtspversion; /* like httpversion, for RTSP */ + curl_chunk_bgn_callback chunk_bgn; /* called before part of transfer + starts */ + curl_chunk_end_callback chunk_end; /* called after part transferring + stopped */ + curl_fnmatch_callback fnmatch; /* callback to decide which file corresponds + to pattern (e.g. if WILDCARDMATCH is on) */ + void *fnmatch_data; + + long gssapi_delegation; /* GSS-API credential delegation, see the + documentation of CURLOPT_GSSAPI_DELEGATION */ + + long tcp_keepidle; /* seconds in idle before sending keepalive probe */ + long tcp_keepintvl; /* seconds between TCP keepalive probes */ + + size_t maxconnects; /* Max idle connections in the connection cache */ + + long expect_100_timeout; /* in milliseconds */ + struct Curl_easy *stream_depends_on; + int stream_weight; + struct Curl_http2_dep *stream_dependents; + + curl_resolver_start_callback resolver_start; /* optional callback called + before resolver start */ + void *resolver_start_client; /* pointer to pass to resolver start callback */ + long upkeep_interval_ms; /* Time between calls for connection upkeep. */ + multidone_func fmultidone; + struct Curl_easy *dohfor; /* this is a DoH request for that transfer */ + CURLU *uh; /* URL handle for the current parsed URL */ + void *trailer_data; /* pointer to pass to trailer data callback */ + curl_trailer_callback trailer_callback; /* trailing data callback */ + bit is_fread_set:1; /* has read callback been set to non-NULL? */ + bit is_fwrite_set:1; /* has write callback been set to non-NULL? */ + bit free_referer:1; /* set TRUE if 'referer' points to a string we + allocated */ + bit tftp_no_options:1; /* do not send TFTP options requests */ + bit sep_headers:1; /* handle host and proxy headers separately */ + bit cookiesession:1; /* new cookie session? */ + bit crlf:1; /* convert crlf on ftp upload(?) */ + bit strip_path_slash:1; /* strip off initial slash from path */ + bit ssh_compression:1; /* enable SSH compression */ + +/* Here follows boolean settings that define how to behave during + this session. They are STATIC, set by libcurl users or at least initially + and they don't change during operations. */ + bit get_filetime:1; /* get the time and get of the remote file */ + bit tunnel_thru_httpproxy:1; /* use CONNECT through a HTTP proxy */ + bit prefer_ascii:1; /* ASCII rather than binary */ + bit ftp_append:1; /* append, not overwrite, on upload */ + bit ftp_list_only:1; /* switch FTP command for listing directories */ +#ifndef CURL_DISABLE_FTP + bit ftp_use_port:1; /* use the FTP PORT command */ + bit ftp_use_epsv:1; /* if EPSV is to be attempted or not */ + bit ftp_use_eprt:1; /* if EPRT is to be attempted or not */ + bit ftp_use_pret:1; /* if PRET is to be used before PASV or not */ + bit ftp_skip_ip:1; /* skip the IP address the FTP server passes on to + us */ +#endif + bit hide_progress:1; /* don't use the progress meter */ + bit http_fail_on_error:1; /* fail on HTTP error codes >= 400 */ + bit http_keep_sending_on_error:1; /* for HTTP status codes >= 300 */ + bit http_follow_location:1; /* follow HTTP redirects */ + bit http_transfer_encoding:1; /* request compressed HTTP + transfer-encoding */ + bit allow_auth_to_other_hosts:1; + bit include_header:1; /* include received protocol headers in data output */ + bit http_set_referer:1; /* is a custom referer used */ + bit http_auto_referer:1; /* set "correct" referer when following + location: */ + bit opt_no_body:1; /* as set with CURLOPT_NOBODY */ + bit upload:1; /* upload request */ + bit verbose:1; /* output verbosity */ + bit krb:1; /* Kerberos connection requested */ + bit reuse_forbid:1; /* forbidden to be reused, close after use */ + bit reuse_fresh:1; /* do not re-use an existing connection */ + + bit no_signal:1; /* do not use any signal/alarm handler */ + bit tcp_nodelay:1; /* whether to enable TCP_NODELAY or not */ + bit ignorecl:1; /* ignore content length */ + bit connect_only:1; /* make connection, let application use the socket */ + bit http_te_skip:1; /* pass the raw body data to the user, even when + transfer-encoded (chunked, compressed) */ + bit http_ce_skip:1; /* pass the raw body data to the user, even when + content-encoded (chunked, compressed) */ + bit proxy_transfer_mode:1; /* set transfer mode (;type=) when doing + FTP via an HTTP proxy */ +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + bit socks5_gssapi_nec:1; /* Flag to support NEC SOCKS5 server */ +#endif + bit sasl_ir:1; /* Enable/disable SASL initial response */ + bit wildcard_enabled:1; /* enable wildcard matching */ + bit tcp_keepalive:1; /* use TCP keepalives */ + bit tcp_fastopen:1; /* use TCP Fast Open */ + bit ssl_enable_npn:1; /* TLS NPN extension? */ + bit ssl_enable_alpn:1;/* TLS ALPN extension? */ + bit path_as_is:1; /* allow dotdots? */ + bit pipewait:1; /* wait for multiplex status before starting a new + connection */ + bit suppress_connect_headers:1; /* suppress proxy CONNECT response headers + from user callbacks */ + bit dns_shuffle_addresses:1; /* whether to shuffle addresses before use */ + bit stream_depends_e:1; /* set or don't set the Exclusive bit */ + bit haproxyprotocol:1; /* whether to send HAProxy PROXY protocol v1 + header */ + bit abstract_unix_socket:1; + bit disallow_username_in_url:1; /* disallow username in url */ + bit doh:1; /* DNS-over-HTTPS enabled */ + bit doh_get:1; /* use GET for DoH requests, instead of POST */ + bit http09_allowed:1; /* allow HTTP/0.9 responses */ +}; + +struct Names { + struct curl_hash *hostcache; + enum { + HCACHE_NONE, /* not pointing to anything */ + HCACHE_MULTI, /* points to a shared one in the multi handle */ + HCACHE_SHARED /* points to a shared one in a shared object */ + } hostcachetype; +}; + +/* + * The 'connectdata' struct MUST have all the connection oriented stuff as we + * may have several simultaneous connections and connection structs in memory. + * + * The 'struct UserDefined' must only contain data that is set once to go for + * many (perhaps) independent connections. Values that are generated or + * calculated internally for the "session handle" must be defined within the + * 'struct UrlState' instead. + */ + +struct Curl_easy { + /* first, two fields for the linked list of these */ + struct Curl_easy *next; + struct Curl_easy *prev; + + struct connectdata *conn; + struct curl_llist_element connect_queue; + struct curl_llist_element sh_queue; /* list per Curl_sh_entry */ + struct curl_llist_element conn_queue; /* list per connectdata */ + + CURLMstate mstate; /* the handle's state */ + CURLcode result; /* previous result */ + + struct Curl_message msg; /* A single posted message. */ + + /* Array with the plain socket numbers this handle takes care of, in no + particular order. Note that all sockets are added to the sockhash, where + the state etc are also kept. This array is mostly used to detect when a + socket is to be removed from the hash. See singlesocket(). */ + curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE]; + int actions[MAX_SOCKSPEREASYHANDLE]; /* action for each socket in + sockets[] */ + int numsocks; + + struct Names dns; + struct Curl_multi *multi; /* if non-NULL, points to the multi handle + struct to which this "belongs" when used by + the multi interface */ + struct Curl_multi *multi_easy; /* if non-NULL, points to the multi handle + struct to which this "belongs" when used + by the easy interface */ + struct Curl_share *share; /* Share, handles global variable mutexing */ +#ifdef USE_LIBPSL + struct PslCache *psl; /* The associated PSL cache. */ +#endif + struct SingleRequest req; /* Request-specific data */ + struct UserDefined set; /* values set by the libcurl user */ + struct DynamicStatic change; /* possibly modified userdefined data */ + struct CookieInfo *cookies; /* the cookies, read from files and servers. + NOTE that the 'cookie' field in the + UserDefined struct defines if the "engine" + is to be used or not. */ +#ifdef USE_ALTSVC + struct altsvcinfo *asi; /* the alt-svc cache */ +#endif + struct Progress progress; /* for all the progress meter data */ + struct UrlState state; /* struct for fields used for state info and + other dynamic purposes */ +#ifndef CURL_DISABLE_FTP + struct WildcardData wildcard; /* wildcard download state info */ +#endif + struct PureInfo info; /* stats, reports and info data */ + struct curl_tlssessioninfo tsi; /* Information about the TLS session, only + valid after a client has asked for it */ +#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV) + iconv_t outbound_cd; /* for translating to the network encoding */ + iconv_t inbound_cd; /* for translating from the network encoding */ + iconv_t utf8_cd; /* for translating to UTF8 */ +#endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */ + unsigned int magic; /* set to a CURLEASY_MAGIC_NUMBER */ +}; + +#define LIBCURL_NAME "libcurl" + +#endif /* HEADER_CURL_URLDATA_H */ diff --git a/dependencies/cmcurl/lib/vauth/cleartext.c b/dependencies/cmcurl/lib/vauth/cleartext.c new file mode 100644 index 0000000..6f452c1 --- /dev/null +++ b/dependencies/cmcurl/lib/vauth/cleartext.c @@ -0,0 +1,169 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC4616 PLAIN authentication + * Draft LOGIN SASL Mechanism + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_SMTP) || \ + !defined(CURL_DISABLE_POP3) + +#include +#include "urldata.h" + +#include "vauth/vauth.h" +#include "curl_base64.h" +#include "curl_md5.h" +#include "warnless.h" +#include "strtok.h" +#include "sendf.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Curl_auth_create_plain_message() + * + * This is used to generate an already encoded PLAIN message ready + * for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * authzid [in] - The authorization identity. + * authcid [in] - The authentication identity. + * passwd [in] - The password. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_plain_message(struct Curl_easy *data, + const char *authzid, + const char *authcid, + const char *passwd, + char **outptr, size_t *outlen) +{ + CURLcode result; + char *plainauth; + size_t zlen; + size_t clen; + size_t plen; + size_t plainlen; + + *outlen = 0; + *outptr = NULL; + zlen = (authzid == NULL ? 0 : strlen(authzid)); + clen = strlen(authcid); + plen = strlen(passwd); + + /* Compute binary message length. Check for overflows. */ + if(((zlen + clen) > SIZE_T_MAX/4) || (plen > (SIZE_T_MAX/2 - 2))) + return CURLE_OUT_OF_MEMORY; + plainlen = zlen + clen + plen + 2; + + plainauth = malloc(plainlen); + if(!plainauth) + return CURLE_OUT_OF_MEMORY; + + /* Calculate the reply */ + if(zlen != 0) + memcpy(plainauth, authzid, zlen); + plainauth[zlen] = '\0'; + memcpy(plainauth + zlen + 1, authcid, clen); + plainauth[zlen + clen + 1] = '\0'; + memcpy(plainauth + zlen + clen + 2, passwd, plen); + + /* Base64 encode the reply */ + result = Curl_base64_encode(data, plainauth, plainlen, outptr, outlen); + free(plainauth); + + return result; +} + +/* + * Curl_auth_create_login_message() + * + * This is used to generate an already encoded LOGIN message containing the + * user name or password ready for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * valuep [in] - The user name or user's password. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_login_message(struct Curl_easy *data, + const char *valuep, char **outptr, + size_t *outlen) +{ + size_t vlen = strlen(valuep); + + if(!vlen) { + /* Calculate an empty reply */ + *outptr = strdup("="); + if(*outptr) { + *outlen = (size_t) 1; + return CURLE_OK; + } + + *outlen = 0; + return CURLE_OUT_OF_MEMORY; + } + + /* Base64 encode the value */ + return Curl_base64_encode(data, valuep, vlen, outptr, outlen); +} + +/* + * Curl_auth_create_external_message() + * + * This is used to generate an already encoded EXTERNAL message containing + * the user name ready for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * user [in] - The user name. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_external_message(struct Curl_easy *data, + const char *user, char **outptr, + size_t *outlen) +{ + /* This is the same formatting as the login message */ + return Curl_auth_create_login_message(data, user, outptr, outlen); +} + +#endif /* if no users */ diff --git a/dependencies/cmcurl/lib/vauth/cram.c b/dependencies/cmcurl/lib/vauth/cram.c new file mode 100644 index 0000000..d148618 --- /dev/null +++ b/dependencies/cmcurl/lib/vauth/cram.c @@ -0,0 +1,138 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC2195 CRAM-MD5 authentication + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_CRYPTO_AUTH) + +#include +#include "urldata.h" + +#include "vauth/vauth.h" +#include "curl_base64.h" +#include "curl_hmac.h" +#include "curl_md5.h" +#include "warnless.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Curl_auth_decode_cram_md5_message() + * + * This is used to decode an already encoded CRAM-MD5 challenge message. + * + * Parameters: + * + * chlg64 [in] - The base64 encoded challenge message. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_decode_cram_md5_message(const char *chlg64, char **outptr, + size_t *outlen) +{ + CURLcode result = CURLE_OK; + size_t chlg64len = strlen(chlg64); + + *outptr = NULL; + *outlen = 0; + + /* Decode the challenge if necessary */ + if(chlg64len && *chlg64 != '=') + result = Curl_base64_decode(chlg64, (unsigned char **) outptr, outlen); + + return result; +} + +/* + * Curl_auth_create_cram_md5_message() + * + * This is used to generate an already encoded CRAM-MD5 response message ready + * for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * chlg [in] - The challenge. + * userp [in] - The user name. + * passwdp [in] - The user's password. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_cram_md5_message(struct Curl_easy *data, + const char *chlg, + const char *userp, + const char *passwdp, + char **outptr, size_t *outlen) +{ + CURLcode result = CURLE_OK; + size_t chlglen = 0; + HMAC_context *ctxt; + unsigned char digest[MD5_DIGEST_LEN]; + char *response; + + if(chlg) + chlglen = strlen(chlg); + + /* Compute the digest using the password as the key */ + ctxt = Curl_HMAC_init(Curl_HMAC_MD5, + (const unsigned char *) passwdp, + curlx_uztoui(strlen(passwdp))); + if(!ctxt) + return CURLE_OUT_OF_MEMORY; + + /* Update the digest with the given challenge */ + if(chlglen > 0) + Curl_HMAC_update(ctxt, (const unsigned char *) chlg, + curlx_uztoui(chlglen)); + + /* Finalise the digest */ + Curl_HMAC_final(ctxt, digest); + + /* Generate the response */ + response = aprintf( + "%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + userp, digest[0], digest[1], digest[2], digest[3], digest[4], + digest[5], digest[6], digest[7], digest[8], digest[9], digest[10], + digest[11], digest[12], digest[13], digest[14], digest[15]); + if(!response) + return CURLE_OUT_OF_MEMORY; + + /* Base64 encode the response */ + result = Curl_base64_encode(data, response, 0, outptr, outlen); + + free(response); + + return result; +} + +#endif /* !CURL_DISABLE_CRYPTO_AUTH */ diff --git a/dependencies/cmcurl/lib/vauth/digest.c b/dependencies/cmcurl/lib/vauth/digest.c new file mode 100644 index 0000000..f9cdc9d --- /dev/null +++ b/dependencies/cmcurl/lib/vauth/digest.c @@ -0,0 +1,1004 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC2831 DIGEST-MD5 authentication + * RFC7616 DIGEST-SHA256, DIGEST-SHA512-256 authentication + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_CRYPTO_AUTH) + +#include + +#include "vauth/vauth.h" +#include "vauth/digest.h" +#include "urldata.h" +#include "curl_base64.h" +#include "curl_hmac.h" +#include "curl_md5.h" +#include "curl_sha256.h" +#include "vtls/vtls.h" +#include "warnless.h" +#include "strtok.h" +#include "strcase.h" +#include "non-ascii.h" /* included for Curl_convert_... prototypes */ +#include "curl_printf.h" +#include "rand.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#if !defined(USE_WINDOWS_SSPI) +#define DIGEST_QOP_VALUE_AUTH (1 << 0) +#define DIGEST_QOP_VALUE_AUTH_INT (1 << 1) +#define DIGEST_QOP_VALUE_AUTH_CONF (1 << 2) + +#define DIGEST_QOP_VALUE_STRING_AUTH "auth" +#define DIGEST_QOP_VALUE_STRING_AUTH_INT "auth-int" +#define DIGEST_QOP_VALUE_STRING_AUTH_CONF "auth-conf" + +/* The CURL_OUTPUT_DIGEST_CONV macro below is for non-ASCII machines. + It converts digest text to ASCII so the MD5 will be correct for + what ultimately goes over the network. +*/ +#define CURL_OUTPUT_DIGEST_CONV(a, b) \ + result = Curl_convert_to_network(a, (char *)b, strlen((const char *)b)); \ + if(result) { \ + free(b); \ + return result; \ + } +#endif /* !USE_WINDOWS_SSPI */ + +bool Curl_auth_digest_get_pair(const char *str, char *value, char *content, + const char **endptr) +{ + int c; + bool starts_with_quote = FALSE; + bool escape = FALSE; + + for(c = DIGEST_MAX_VALUE_LENGTH - 1; (*str && (*str != '=') && c--);) + *value++ = *str++; + *value = 0; + + if('=' != *str++) + /* eek, no match */ + return FALSE; + + if('\"' == *str) { + /* This starts with a quote so it must end with one as well! */ + str++; + starts_with_quote = TRUE; + } + + for(c = DIGEST_MAX_CONTENT_LENGTH - 1; *str && c--; str++) { + switch(*str) { + case '\\': + if(!escape) { + /* possibly the start of an escaped quote */ + escape = TRUE; + *content++ = '\\'; /* Even though this is an escape character, we still + store it as-is in the target buffer */ + continue; + } + break; + + case ',': + if(!starts_with_quote) { + /* This signals the end of the content if we didn't get a starting + quote and then we do "sloppy" parsing */ + c = 0; /* the end */ + continue; + } + break; + + case '\r': + case '\n': + /* end of string */ + c = 0; + continue; + + case '\"': + if(!escape && starts_with_quote) { + /* end of string */ + c = 0; + continue; + } + break; + } + + escape = FALSE; + *content++ = *str; + } + + *content = 0; + *endptr = str; + + return TRUE; +} + +#if !defined(USE_WINDOWS_SSPI) +/* Convert md5 chunk to RFC2617 (section 3.1.3) -suitable ascii string*/ +static void auth_digest_md5_to_ascii(unsigned char *source, /* 16 bytes */ + unsigned char *dest) /* 33 bytes */ +{ + int i; + for(i = 0; i < 16; i++) + msnprintf((char *) &dest[i * 2], 3, "%02x", source[i]); +} + +/* Convert sha256 chunk to RFC7616 -suitable ascii string*/ +static void auth_digest_sha256_to_ascii(unsigned char *source, /* 32 bytes */ + unsigned char *dest) /* 65 bytes */ +{ + int i; + for(i = 0; i < 32; i++) + msnprintf((char *) &dest[i * 2], 3, "%02x", source[i]); +} + +/* Perform quoted-string escaping as described in RFC2616 and its errata */ +static char *auth_digest_string_quoted(const char *source) +{ + char *dest; + const char *s = source; + size_t n = 1; /* null terminator */ + + /* Calculate size needed */ + while(*s) { + ++n; + if(*s == '"' || *s == '\\') { + ++n; + } + ++s; + } + + dest = malloc(n); + if(dest) { + char *d = dest; + s = source; + while(*s) { + if(*s == '"' || *s == '\\') { + *d++ = '\\'; + } + *d++ = *s++; + } + *d = 0; + } + + return dest; +} + +/* Retrieves the value for a corresponding key from the challenge string + * returns TRUE if the key could be found, FALSE if it does not exists + */ +static bool auth_digest_get_key_value(const char *chlg, + const char *key, + char *value, + size_t max_val_len, + char end_char) +{ + char *find_pos; + size_t i; + + find_pos = strstr(chlg, key); + if(!find_pos) + return FALSE; + + find_pos += strlen(key); + + for(i = 0; *find_pos && *find_pos != end_char && i < max_val_len - 1; ++i) + value[i] = *find_pos++; + value[i] = '\0'; + + return TRUE; +} + +static CURLcode auth_digest_get_qop_values(const char *options, int *value) +{ + char *tmp; + char *token; + char *tok_buf = NULL; + + /* Initialise the output */ + *value = 0; + + /* Tokenise the list of qop values. Use a temporary clone of the buffer since + strtok_r() ruins it. */ + tmp = strdup(options); + if(!tmp) + return CURLE_OUT_OF_MEMORY; + + token = strtok_r(tmp, ",", &tok_buf); + while(token != NULL) { + if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH)) + *value |= DIGEST_QOP_VALUE_AUTH; + else if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH_INT)) + *value |= DIGEST_QOP_VALUE_AUTH_INT; + else if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH_CONF)) + *value |= DIGEST_QOP_VALUE_AUTH_CONF; + + token = strtok_r(NULL, ",", &tok_buf); + } + + free(tmp); + + return CURLE_OK; +} + +/* + * auth_decode_digest_md5_message() + * + * This is used internally to decode an already encoded DIGEST-MD5 challenge + * message into the separate attributes. + * + * Parameters: + * + * chlg64 [in] - The base64 encoded challenge message. + * nonce [in/out] - The buffer where the nonce will be stored. + * nlen [in] - The length of the nonce buffer. + * realm [in/out] - The buffer where the realm will be stored. + * rlen [in] - The length of the realm buffer. + * alg [in/out] - The buffer where the algorithm will be stored. + * alen [in] - The length of the algorithm buffer. + * qop [in/out] - The buffer where the qop-options will be stored. + * qlen [in] - The length of the qop buffer. + * + * Returns CURLE_OK on success. + */ +static CURLcode auth_decode_digest_md5_message(const char *chlg64, + char *nonce, size_t nlen, + char *realm, size_t rlen, + char *alg, size_t alen, + char *qop, size_t qlen) +{ + CURLcode result = CURLE_OK; + unsigned char *chlg = NULL; + size_t chlglen = 0; + size_t chlg64len = strlen(chlg64); + + /* Decode the base-64 encoded challenge message */ + if(chlg64len && *chlg64 != '=') { + result = Curl_base64_decode(chlg64, &chlg, &chlglen); + if(result) + return result; + } + + /* Ensure we have a valid challenge message */ + if(!chlg) + return CURLE_BAD_CONTENT_ENCODING; + + /* Retrieve nonce string from the challenge */ + if(!auth_digest_get_key_value((char *) chlg, "nonce=\"", nonce, nlen, + '\"')) { + free(chlg); + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Retrieve realm string from the challenge */ + if(!auth_digest_get_key_value((char *) chlg, "realm=\"", realm, rlen, + '\"')) { + /* Challenge does not have a realm, set empty string [RFC2831] page 6 */ + strcpy(realm, ""); + } + + /* Retrieve algorithm string from the challenge */ + if(!auth_digest_get_key_value((char *) chlg, "algorithm=", alg, alen, ',')) { + free(chlg); + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Retrieve qop-options string from the challenge */ + if(!auth_digest_get_key_value((char *) chlg, "qop=\"", qop, qlen, '\"')) { + free(chlg); + return CURLE_BAD_CONTENT_ENCODING; + } + + free(chlg); + + return CURLE_OK; +} + +/* + * Curl_auth_is_digest_supported() + * + * This is used to evaluate if DIGEST is supported. + * + * Parameters: None + * + * Returns TRUE as DIGEST as handled by libcurl. + */ +bool Curl_auth_is_digest_supported(void) +{ + return TRUE; +} + +/* + * Curl_auth_create_digest_md5_message() + * + * This is used to generate an already encoded DIGEST-MD5 response message + * ready for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * chlg64 [in] - The base64 encoded challenge message. + * userp [in] - The user name. + * passwdp [in] - The user's password. + * service [in] - The service type such as http, smtp, pop or imap. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, + const char *chlg64, + const char *userp, + const char *passwdp, + const char *service, + char **outptr, size_t *outlen) +{ + CURLcode result = CURLE_OK; + size_t i; + MD5_context *ctxt; + char *response = NULL; + unsigned char digest[MD5_DIGEST_LEN]; + char HA1_hex[2 * MD5_DIGEST_LEN + 1]; + char HA2_hex[2 * MD5_DIGEST_LEN + 1]; + char resp_hash_hex[2 * MD5_DIGEST_LEN + 1]; + char nonce[64]; + char realm[128]; + char algorithm[64]; + char qop_options[64]; + int qop_values; + char cnonce[33]; + char nonceCount[] = "00000001"; + char method[] = "AUTHENTICATE"; + char qop[] = DIGEST_QOP_VALUE_STRING_AUTH; + char *spn = NULL; + + /* Decode the challenge message */ + result = auth_decode_digest_md5_message(chlg64, nonce, sizeof(nonce), + realm, sizeof(realm), + algorithm, sizeof(algorithm), + qop_options, sizeof(qop_options)); + if(result) + return result; + + /* We only support md5 sessions */ + if(strcmp(algorithm, "md5-sess") != 0) + return CURLE_BAD_CONTENT_ENCODING; + + /* Get the qop-values from the qop-options */ + result = auth_digest_get_qop_values(qop_options, &qop_values); + if(result) + return result; + + /* We only support auth quality-of-protection */ + if(!(qop_values & DIGEST_QOP_VALUE_AUTH)) + return CURLE_BAD_CONTENT_ENCODING; + + /* Generate 32 random hex chars, 32 bytes + 1 zero termination */ + result = Curl_rand_hex(data, (unsigned char *)cnonce, sizeof(cnonce)); + if(result) + return result; + + /* So far so good, now calculate A1 and H(A1) according to RFC 2831 */ + ctxt = Curl_MD5_init(Curl_DIGEST_MD5); + if(!ctxt) + return CURLE_OUT_OF_MEMORY; + + Curl_MD5_update(ctxt, (const unsigned char *) userp, + curlx_uztoui(strlen(userp))); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + Curl_MD5_update(ctxt, (const unsigned char *) realm, + curlx_uztoui(strlen(realm))); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + Curl_MD5_update(ctxt, (const unsigned char *) passwdp, + curlx_uztoui(strlen(passwdp))); + Curl_MD5_final(ctxt, digest); + + ctxt = Curl_MD5_init(Curl_DIGEST_MD5); + if(!ctxt) + return CURLE_OUT_OF_MEMORY; + + Curl_MD5_update(ctxt, (const unsigned char *) digest, MD5_DIGEST_LEN); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + Curl_MD5_update(ctxt, (const unsigned char *) nonce, + curlx_uztoui(strlen(nonce))); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + Curl_MD5_update(ctxt, (const unsigned char *) cnonce, + curlx_uztoui(strlen(cnonce))); + Curl_MD5_final(ctxt, digest); + + /* Convert calculated 16 octet hex into 32 bytes string */ + for(i = 0; i < MD5_DIGEST_LEN; i++) + msnprintf(&HA1_hex[2 * i], 3, "%02x", digest[i]); + + /* Generate our SPN */ + spn = Curl_auth_build_spn(service, realm, NULL); + if(!spn) + return CURLE_OUT_OF_MEMORY; + + /* Calculate H(A2) */ + ctxt = Curl_MD5_init(Curl_DIGEST_MD5); + if(!ctxt) { + free(spn); + + return CURLE_OUT_OF_MEMORY; + } + + Curl_MD5_update(ctxt, (const unsigned char *) method, + curlx_uztoui(strlen(method))); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + Curl_MD5_update(ctxt, (const unsigned char *) spn, + curlx_uztoui(strlen(spn))); + Curl_MD5_final(ctxt, digest); + + for(i = 0; i < MD5_DIGEST_LEN; i++) + msnprintf(&HA2_hex[2 * i], 3, "%02x", digest[i]); + + /* Now calculate the response hash */ + ctxt = Curl_MD5_init(Curl_DIGEST_MD5); + if(!ctxt) { + free(spn); + + return CURLE_OUT_OF_MEMORY; + } + + Curl_MD5_update(ctxt, (const unsigned char *) HA1_hex, 2 * MD5_DIGEST_LEN); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + Curl_MD5_update(ctxt, (const unsigned char *) nonce, + curlx_uztoui(strlen(nonce))); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + + Curl_MD5_update(ctxt, (const unsigned char *) nonceCount, + curlx_uztoui(strlen(nonceCount))); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + Curl_MD5_update(ctxt, (const unsigned char *) cnonce, + curlx_uztoui(strlen(cnonce))); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + Curl_MD5_update(ctxt, (const unsigned char *) qop, + curlx_uztoui(strlen(qop))); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + + Curl_MD5_update(ctxt, (const unsigned char *) HA2_hex, 2 * MD5_DIGEST_LEN); + Curl_MD5_final(ctxt, digest); + + for(i = 0; i < MD5_DIGEST_LEN; i++) + msnprintf(&resp_hash_hex[2 * i], 3, "%02x", digest[i]); + + /* Generate the response */ + response = aprintf("username=\"%s\",realm=\"%s\",nonce=\"%s\"," + "cnonce=\"%s\",nc=\"%s\",digest-uri=\"%s\",response=%s," + "qop=%s", + userp, realm, nonce, + cnonce, nonceCount, spn, resp_hash_hex, qop); + free(spn); + if(!response) + return CURLE_OUT_OF_MEMORY; + + /* Base64 encode the response */ + result = Curl_base64_encode(data, response, 0, outptr, outlen); + + free(response); + + return result; +} + +/* + * Curl_auth_decode_digest_http_message() + * + * This is used to decode a HTTP DIGEST challenge message into the separate + * attributes. + * + * Parameters: + * + * chlg [in] - The challenge message. + * digest [in/out] - The digest data struct being used and modified. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_decode_digest_http_message(const char *chlg, + struct digestdata *digest) +{ + bool before = FALSE; /* got a nonce before */ + bool foundAuth = FALSE; + bool foundAuthInt = FALSE; + char *token = NULL; + char *tmp = NULL; + + /* If we already have received a nonce, keep that in mind */ + if(digest->nonce) + before = TRUE; + + /* Clean up any former leftovers and initialise to defaults */ + Curl_auth_digest_cleanup(digest); + + for(;;) { + char value[DIGEST_MAX_VALUE_LENGTH]; + char content[DIGEST_MAX_CONTENT_LENGTH]; + + /* Pass all additional spaces here */ + while(*chlg && ISSPACE(*chlg)) + chlg++; + + /* Extract a value=content pair */ + if(Curl_auth_digest_get_pair(chlg, value, content, &chlg)) { + if(strcasecompare(value, "nonce")) { + free(digest->nonce); + digest->nonce = strdup(content); + if(!digest->nonce) + return CURLE_OUT_OF_MEMORY; + } + else if(strcasecompare(value, "stale")) { + if(strcasecompare(content, "true")) { + digest->stale = TRUE; + digest->nc = 1; /* we make a new nonce now */ + } + } + else if(strcasecompare(value, "realm")) { + free(digest->realm); + digest->realm = strdup(content); + if(!digest->realm) + return CURLE_OUT_OF_MEMORY; + } + else if(strcasecompare(value, "opaque")) { + free(digest->opaque); + digest->opaque = strdup(content); + if(!digest->opaque) + return CURLE_OUT_OF_MEMORY; + } + else if(strcasecompare(value, "qop")) { + char *tok_buf = NULL; + /* Tokenize the list and choose auth if possible, use a temporary + clone of the buffer since strtok_r() ruins it */ + tmp = strdup(content); + if(!tmp) + return CURLE_OUT_OF_MEMORY; + + token = strtok_r(tmp, ",", &tok_buf); + while(token != NULL) { + if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH)) { + foundAuth = TRUE; + } + else if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH_INT)) { + foundAuthInt = TRUE; + } + token = strtok_r(NULL, ",", &tok_buf); + } + + free(tmp); + + /* Select only auth or auth-int. Otherwise, ignore */ + if(foundAuth) { + free(digest->qop); + digest->qop = strdup(DIGEST_QOP_VALUE_STRING_AUTH); + if(!digest->qop) + return CURLE_OUT_OF_MEMORY; + } + else if(foundAuthInt) { + free(digest->qop); + digest->qop = strdup(DIGEST_QOP_VALUE_STRING_AUTH_INT); + if(!digest->qop) + return CURLE_OUT_OF_MEMORY; + } + } + else if(strcasecompare(value, "algorithm")) { + free(digest->algorithm); + digest->algorithm = strdup(content); + if(!digest->algorithm) + return CURLE_OUT_OF_MEMORY; + + if(strcasecompare(content, "MD5-sess")) + digest->algo = CURLDIGESTALGO_MD5SESS; + else if(strcasecompare(content, "MD5")) + digest->algo = CURLDIGESTALGO_MD5; + else if(strcasecompare(content, "SHA-256")) + digest->algo = CURLDIGESTALGO_SHA256; + else if(strcasecompare(content, "SHA-256-SESS")) + digest->algo = CURLDIGESTALGO_SHA256SESS; + else if(strcasecompare(content, "SHA-512-256")) + digest->algo = CURLDIGESTALGO_SHA512_256; + else if(strcasecompare(content, "SHA-512-256-SESS")) + digest->algo = CURLDIGESTALGO_SHA512_256SESS; + else + return CURLE_BAD_CONTENT_ENCODING; + } + else if(strcasecompare(value, "userhash")) { + if(strcasecompare(content, "true")) { + digest->userhash = TRUE; + } + } + else { + /* Unknown specifier, ignore it! */ + } + } + else + break; /* We're done here */ + + /* Pass all additional spaces here */ + while(*chlg && ISSPACE(*chlg)) + chlg++; + + /* Allow the list to be comma-separated */ + if(',' == *chlg) + chlg++; + } + + /* We had a nonce since before, and we got another one now without + 'stale=true'. This means we provided bad credentials in the previous + request */ + if(before && !digest->stale) + return CURLE_BAD_CONTENT_ENCODING; + + /* We got this header without a nonce, that's a bad Digest line! */ + if(!digest->nonce) + return CURLE_BAD_CONTENT_ENCODING; + + return CURLE_OK; +} + +/* + * _Curl_auth_create_digest_http_message() + * + * This is used to generate a HTTP DIGEST response message ready for sending + * to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * userp [in] - The user name. + * passwdp [in] - The user's password. + * request [in] - The HTTP request. + * uripath [in] - The path of the HTTP uri. + * digest [in/out] - The digest data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +static CURLcode _Curl_auth_create_digest_http_message( + struct Curl_easy *data, + const char *userp, + const char *passwdp, + const unsigned char *request, + const unsigned char *uripath, + struct digestdata *digest, + char **outptr, size_t *outlen, + void (*convert_to_ascii)(unsigned char *, unsigned char *), + void (*hash)(unsigned char *, const unsigned char *)) +{ + CURLcode result; + unsigned char hashbuf[32]; /* 32 bytes/256 bits */ + unsigned char request_digest[65]; + unsigned char *hashthis; + unsigned char ha1[65]; /* 64 digits and 1 zero byte */ + unsigned char ha2[65]; /* 64 digits and 1 zero byte */ + char userh[65]; + char *cnonce = NULL; + size_t cnonce_sz = 0; + char *userp_quoted; + char *response = NULL; + char *tmp = NULL; + + if(!digest->nc) + digest->nc = 1; + + if(!digest->cnonce) { + char cnoncebuf[33]; + result = Curl_rand_hex(data, (unsigned char *)cnoncebuf, + sizeof(cnoncebuf)); + if(result) + return result; + + result = Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf), + &cnonce, &cnonce_sz); + if(result) + return result; + + digest->cnonce = cnonce; + } + + if(digest->userhash) { + hashthis = (unsigned char *) aprintf("%s:%s", userp, digest->realm); + if(!hashthis) + return CURLE_OUT_OF_MEMORY; + + CURL_OUTPUT_DIGEST_CONV(data, hashthis); + hash(hashbuf, hashthis); + free(hashthis); + convert_to_ascii(hashbuf, (unsigned char *)userh); + } + + /* + If the algorithm is "MD5" or unspecified (which then defaults to MD5): + + A1 = unq(username-value) ":" unq(realm-value) ":" passwd + + If the algorithm is "MD5-sess" then: + + A1 = H(unq(username-value) ":" unq(realm-value) ":" passwd) ":" + unq(nonce-value) ":" unq(cnonce-value) + */ + + hashthis = (unsigned char *) + aprintf("%s:%s:%s", digest->userhash ? userh : userp, + digest->realm, passwdp); + if(!hashthis) + return CURLE_OUT_OF_MEMORY; + + CURL_OUTPUT_DIGEST_CONV(data, hashthis); /* convert on non-ASCII machines */ + hash(hashbuf, hashthis); + free(hashthis); + convert_to_ascii(hashbuf, ha1); + + if(digest->algo == CURLDIGESTALGO_MD5SESS || + digest->algo == CURLDIGESTALGO_SHA256SESS || + digest->algo == CURLDIGESTALGO_SHA512_256SESS) { + /* nonce and cnonce are OUTSIDE the hash */ + tmp = aprintf("%s:%s:%s", ha1, digest->nonce, digest->cnonce); + if(!tmp) + return CURLE_OUT_OF_MEMORY; + + CURL_OUTPUT_DIGEST_CONV(data, tmp); /* Convert on non-ASCII machines */ + hash(hashbuf, (unsigned char *) tmp); + free(tmp); + convert_to_ascii(hashbuf, ha1); + } + + /* + If the "qop" directive's value is "auth" or is unspecified, then A2 is: + + A2 = Method ":" digest-uri-value + + If the "qop" value is "auth-int", then A2 is: + + A2 = Method ":" digest-uri-value ":" H(entity-body) + + (The "Method" value is the HTTP request method as specified in section + 5.1.1 of RFC 2616) + */ + + hashthis = (unsigned char *) aprintf("%s:%s", request, uripath); + if(!hashthis) + return CURLE_OUT_OF_MEMORY; + + if(digest->qop && strcasecompare(digest->qop, "auth-int")) { + /* We don't support auth-int for PUT or POST */ + char hashed[65]; + unsigned char *hashthis2; + + hash(hashbuf, (const unsigned char *)""); + convert_to_ascii(hashbuf, (unsigned char *)hashed); + + hashthis2 = (unsigned char *)aprintf("%s:%s", hashthis, hashed); + free(hashthis); + hashthis = hashthis2; + } + + if(!hashthis) + return CURLE_OUT_OF_MEMORY; + + CURL_OUTPUT_DIGEST_CONV(data, hashthis); /* convert on non-ASCII machines */ + hash(hashbuf, hashthis); + free(hashthis); + convert_to_ascii(hashbuf, ha2); + + if(digest->qop) { + hashthis = (unsigned char *) aprintf("%s:%s:%08x:%s:%s:%s", + ha1, + digest->nonce, + digest->nc, + digest->cnonce, + digest->qop, + ha2); + } + else { + hashthis = (unsigned char *) aprintf("%s:%s:%s", + ha1, + digest->nonce, + ha2); + } + + if(!hashthis) + return CURLE_OUT_OF_MEMORY; + + CURL_OUTPUT_DIGEST_CONV(data, hashthis); /* convert on non-ASCII machines */ + hash(hashbuf, hashthis); + free(hashthis); + convert_to_ascii(hashbuf, request_digest); + + /* For test case 64 (snooped from a Mozilla 1.3a request) + + Authorization: Digest username="testuser", realm="testrealm", \ + nonce="1053604145", uri="/64", response="c55f7f30d83d774a3d2dcacf725abaca" + + Digest parameters are all quoted strings. Username which is provided by + the user will need double quotes and backslashes within it escaped. For + the other fields, this shouldn't be an issue. realm, nonce, and opaque + are copied as is from the server, escapes and all. cnonce is generated + with web-safe characters. uri is already percent encoded. nc is 8 hex + characters. algorithm and qop with standard values only contain web-safe + characters. + */ + userp_quoted = auth_digest_string_quoted(digest->userhash ? userh : userp); + if(!userp_quoted) + return CURLE_OUT_OF_MEMORY; + + if(digest->qop) { + response = aprintf("username=\"%s\", " + "realm=\"%s\", " + "nonce=\"%s\", " + "uri=\"%s\", " + "cnonce=\"%s\", " + "nc=%08x, " + "qop=%s, " + "response=\"%s\"", + userp_quoted, + digest->realm, + digest->nonce, + uripath, + digest->cnonce, + digest->nc, + digest->qop, + request_digest); + + if(strcasecompare(digest->qop, "auth")) + digest->nc++; /* The nc (from RFC) has to be a 8 hex digit number 0 + padded which tells to the server how many times you are + using the same nonce in the qop=auth mode */ + } + else { + response = aprintf("username=\"%s\", " + "realm=\"%s\", " + "nonce=\"%s\", " + "uri=\"%s\", " + "response=\"%s\"", + userp_quoted, + digest->realm, + digest->nonce, + uripath, + request_digest); + } + free(userp_quoted); + if(!response) + return CURLE_OUT_OF_MEMORY; + + /* Add the optional fields */ + if(digest->opaque) { + /* Append the opaque */ + tmp = aprintf("%s, opaque=\"%s\"", response, digest->opaque); + free(response); + if(!tmp) + return CURLE_OUT_OF_MEMORY; + + response = tmp; + } + + if(digest->algorithm) { + /* Append the algorithm */ + tmp = aprintf("%s, algorithm=\"%s\"", response, digest->algorithm); + free(response); + if(!tmp) + return CURLE_OUT_OF_MEMORY; + + response = tmp; + } + + if(digest->userhash) { + /* Append the userhash */ + tmp = aprintf("%s, userhash=true", response); + free(response); + if(!tmp) + return CURLE_OUT_OF_MEMORY; + + response = tmp; + } + + /* Return the output */ + *outptr = response; + *outlen = strlen(response); + + return CURLE_OK; +} + +/* + * Curl_auth_create_digest_http_message() + * + * This is used to generate a HTTP DIGEST response message ready for sending + * to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * userp [in] - The user name. + * passwdp [in] - The user's password. + * request [in] - The HTTP request. + * uripath [in] - The path of the HTTP uri. + * digest [in/out] - The digest data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + const unsigned char *request, + const unsigned char *uripath, + struct digestdata *digest, + char **outptr, size_t *outlen) +{ + switch(digest->algo) { + case CURLDIGESTALGO_MD5: + case CURLDIGESTALGO_MD5SESS: + return _Curl_auth_create_digest_http_message(data, userp, passwdp, + request, uripath, digest, + outptr, outlen, + auth_digest_md5_to_ascii, + Curl_md5it); + + case CURLDIGESTALGO_SHA256: + case CURLDIGESTALGO_SHA256SESS: + case CURLDIGESTALGO_SHA512_256: + case CURLDIGESTALGO_SHA512_256SESS: + return _Curl_auth_create_digest_http_message(data, userp, passwdp, + request, uripath, digest, + outptr, outlen, + auth_digest_sha256_to_ascii, + Curl_sha256it); + + default: + return CURLE_UNSUPPORTED_PROTOCOL; + } +} + +/* + * Curl_auth_digest_cleanup() + * + * This is used to clean up the digest specific data. + * + * Parameters: + * + * digest [in/out] - The digest data struct being cleaned up. + * + */ +void Curl_auth_digest_cleanup(struct digestdata *digest) +{ + Curl_safefree(digest->nonce); + Curl_safefree(digest->cnonce); + Curl_safefree(digest->realm); + Curl_safefree(digest->opaque); + Curl_safefree(digest->qop); + Curl_safefree(digest->algorithm); + + digest->nc = 0; + digest->algo = CURLDIGESTALGO_MD5; /* default algorithm */ + digest->stale = FALSE; /* default means normal, not stale */ + digest->userhash = FALSE; +} +#endif /* !USE_WINDOWS_SSPI */ + +#endif /* CURL_DISABLE_CRYPTO_AUTH */ diff --git a/dependencies/cmcurl/lib/vauth/digest.h b/dependencies/cmcurl/lib/vauth/digest.h new file mode 100644 index 0000000..8686c44 --- /dev/null +++ b/dependencies/cmcurl/lib/vauth/digest.h @@ -0,0 +1,47 @@ +#ifndef HEADER_CURL_DIGEST_H +#define HEADER_CURL_DIGEST_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +#if !defined(CURL_DISABLE_CRYPTO_AUTH) + +#define DIGEST_MAX_VALUE_LENGTH 256 +#define DIGEST_MAX_CONTENT_LENGTH 1024 + +enum { + CURLDIGESTALGO_MD5, + CURLDIGESTALGO_MD5SESS, + CURLDIGESTALGO_SHA256, + CURLDIGESTALGO_SHA256SESS, + CURLDIGESTALGO_SHA512_256, + CURLDIGESTALGO_SHA512_256SESS +}; + +/* This is used to extract the realm from a challenge message */ +bool Curl_auth_digest_get_pair(const char *str, char *value, char *content, + const char **endptr); + +#endif + +#endif /* HEADER_CURL_DIGEST_H */ diff --git a/dependencies/cmcurl/lib/vauth/digest_sspi.c b/dependencies/cmcurl/lib/vauth/digest_sspi.c new file mode 100644 index 0000000..fe8093e --- /dev/null +++ b/dependencies/cmcurl/lib/vauth/digest_sspi.c @@ -0,0 +1,669 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2014 - 2016, Steve Holme, . + * Copyright (C) 2015 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC2831 DIGEST-MD5 authentication + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_WINDOWS_SSPI) && !defined(CURL_DISABLE_CRYPTO_AUTH) + +#include + +#include "vauth/vauth.h" +#include "vauth/digest.h" +#include "urldata.h" +#include "curl_base64.h" +#include "warnless.h" +#include "curl_multibyte.h" +#include "sendf.h" +#include "strdup.h" +#include "strcase.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* +* Curl_auth_is_digest_supported() +* +* This is used to evaluate if DIGEST is supported. +* +* Parameters: None +* +* Returns TRUE if DIGEST is supported by Windows SSPI. +*/ +bool Curl_auth_is_digest_supported(void) +{ + PSecPkgInfo SecurityPackage; + SECURITY_STATUS status; + + /* Query the security package for Digest */ + status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST), + &SecurityPackage); + + return (status == SEC_E_OK ? TRUE : FALSE); +} + +/* + * Curl_auth_create_digest_md5_message() + * + * This is used to generate an already encoded DIGEST-MD5 response message + * ready for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * chlg64 [in] - The base64 encoded challenge message. + * userp [in] - The user name in the format User or Domain\User. + * passwdp [in] - The user's password. + * service [in] - The service type such as http, smtp, pop or imap. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, + const char *chlg64, + const char *userp, + const char *passwdp, + const char *service, + char **outptr, size_t *outlen) +{ + CURLcode result = CURLE_OK; + TCHAR *spn = NULL; + size_t chlglen = 0; + size_t token_max = 0; + unsigned char *input_token = NULL; + unsigned char *output_token = NULL; + CredHandle credentials; + CtxtHandle context; + PSecPkgInfo SecurityPackage; + SEC_WINNT_AUTH_IDENTITY identity; + SEC_WINNT_AUTH_IDENTITY *p_identity; + SecBuffer chlg_buf; + SecBuffer resp_buf; + SecBufferDesc chlg_desc; + SecBufferDesc resp_desc; + SECURITY_STATUS status; + unsigned long attrs; + TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */ + + /* Decode the base-64 encoded challenge message */ + if(strlen(chlg64) && *chlg64 != '=') { + result = Curl_base64_decode(chlg64, &input_token, &chlglen); + if(result) + return result; + } + + /* Ensure we have a valid challenge message */ + if(!input_token) { + infof(data, "DIGEST-MD5 handshake failure (empty challenge message)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Query the security package for DigestSSP */ + status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST), + &SecurityPackage); + if(status != SEC_E_OK) { + free(input_token); + + return CURLE_NOT_BUILT_IN; + } + + token_max = SecurityPackage->cbMaxToken; + + /* Release the package buffer as it is not required anymore */ + s_pSecFn->FreeContextBuffer(SecurityPackage); + + /* Allocate our response buffer */ + output_token = malloc(token_max); + if(!output_token) { + free(input_token); + + return CURLE_OUT_OF_MEMORY; + } + + /* Generate our SPN */ + spn = Curl_auth_build_spn(service, data->conn->host.name, NULL); + if(!spn) { + free(output_token); + free(input_token); + + return CURLE_OUT_OF_MEMORY; + } + + if(userp && *userp) { + /* Populate our identity structure */ + result = Curl_create_sspi_identity(userp, passwdp, &identity); + if(result) { + free(spn); + free(output_token); + free(input_token); + + return result; + } + + /* Allow proper cleanup of the identity structure */ + p_identity = &identity; + } + else + /* Use the current Windows user */ + p_identity = NULL; + + /* Acquire our credentials handle */ + status = s_pSecFn->AcquireCredentialsHandle(NULL, + (TCHAR *) TEXT(SP_NAME_DIGEST), + SECPKG_CRED_OUTBOUND, NULL, + p_identity, NULL, NULL, + &credentials, &expiry); + + if(status != SEC_E_OK) { + Curl_sspi_free_identity(p_identity); + free(spn); + free(output_token); + free(input_token); + + return CURLE_LOGIN_DENIED; + } + + /* Setup the challenge "input" security buffer */ + chlg_desc.ulVersion = SECBUFFER_VERSION; + chlg_desc.cBuffers = 1; + chlg_desc.pBuffers = &chlg_buf; + chlg_buf.BufferType = SECBUFFER_TOKEN; + chlg_buf.pvBuffer = input_token; + chlg_buf.cbBuffer = curlx_uztoul(chlglen); + + /* Setup the response "output" security buffer */ + resp_desc.ulVersion = SECBUFFER_VERSION; + resp_desc.cBuffers = 1; + resp_desc.pBuffers = &resp_buf; + resp_buf.BufferType = SECBUFFER_TOKEN; + resp_buf.pvBuffer = output_token; + resp_buf.cbBuffer = curlx_uztoul(token_max); + + /* Generate our response message */ + status = s_pSecFn->InitializeSecurityContext(&credentials, NULL, spn, + 0, 0, 0, &chlg_desc, 0, + &context, &resp_desc, &attrs, + &expiry); + + if(status == SEC_I_COMPLETE_NEEDED || + status == SEC_I_COMPLETE_AND_CONTINUE) + s_pSecFn->CompleteAuthToken(&credentials, &resp_desc); + else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) { + s_pSecFn->FreeCredentialsHandle(&credentials); + Curl_sspi_free_identity(p_identity); + free(spn); + free(output_token); + free(input_token); + + return CURLE_RECV_ERROR; + } + + /* Base64 encode the response */ + result = Curl_base64_encode(data, (char *) output_token, resp_buf.cbBuffer, + outptr, outlen); + + /* Free our handles */ + s_pSecFn->DeleteSecurityContext(&context); + s_pSecFn->FreeCredentialsHandle(&credentials); + + /* Free the identity structure */ + Curl_sspi_free_identity(p_identity); + + /* Free the SPN */ + free(spn); + + /* Free the response buffer */ + free(output_token); + + /* Free the decoded challenge message */ + free(input_token); + + return result; +} + +/* + * Curl_override_sspi_http_realm() + * + * This is used to populate the domain in a SSPI identity structure + * The realm is extracted from the challenge message and used as the + * domain if it is not already explicitly set. + * + * Parameters: + * + * chlg [in] - The challenge message. + * identity [in/out] - The identity structure. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_override_sspi_http_realm(const char *chlg, + SEC_WINNT_AUTH_IDENTITY *identity) +{ + xcharp_u domain, dup_domain; + + /* If domain is blank or unset, check challenge message for realm */ + if(!identity->Domain || !identity->DomainLength) { + for(;;) { + char value[DIGEST_MAX_VALUE_LENGTH]; + char content[DIGEST_MAX_CONTENT_LENGTH]; + + /* Pass all additional spaces here */ + while(*chlg && ISSPACE(*chlg)) + chlg++; + + /* Extract a value=content pair */ + if(Curl_auth_digest_get_pair(chlg, value, content, &chlg)) { + if(strcasecompare(value, "realm")) { + + /* Setup identity's domain and length */ + domain.tchar_ptr = Curl_convert_UTF8_to_tchar((char *) content); + if(!domain.tchar_ptr) + return CURLE_OUT_OF_MEMORY; + + dup_domain.tchar_ptr = _tcsdup(domain.tchar_ptr); + if(!dup_domain.tchar_ptr) { + Curl_unicodefree(domain.tchar_ptr); + return CURLE_OUT_OF_MEMORY; + } + + free(identity->Domain); + identity->Domain = dup_domain.tbyte_ptr; + identity->DomainLength = curlx_uztoul(_tcslen(dup_domain.tchar_ptr)); + dup_domain.tchar_ptr = NULL; + + Curl_unicodefree(domain.tchar_ptr); + } + else { + /* Unknown specifier, ignore it! */ + } + } + else + break; /* We're done here */ + + /* Pass all additional spaces here */ + while(*chlg && ISSPACE(*chlg)) + chlg++; + + /* Allow the list to be comma-separated */ + if(',' == *chlg) + chlg++; + } + } + + return CURLE_OK; +} + +/* + * Curl_auth_decode_digest_http_message() + * + * This is used to decode a HTTP DIGEST challenge message into the separate + * attributes. + * + * Parameters: + * + * chlg [in] - The challenge message. + * digest [in/out] - The digest data struct being used and modified. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_decode_digest_http_message(const char *chlg, + struct digestdata *digest) +{ + size_t chlglen = strlen(chlg); + + /* We had an input token before so if there's another one now that means we + provided bad credentials in the previous request or it's stale. */ + if(digest->input_token) { + bool stale = false; + const char *p = chlg; + + /* Check for the 'stale' directive */ + for(;;) { + char value[DIGEST_MAX_VALUE_LENGTH]; + char content[DIGEST_MAX_CONTENT_LENGTH]; + + while(*p && ISSPACE(*p)) + p++; + + if(!Curl_auth_digest_get_pair(p, value, content, &p)) + break; + + if(strcasecompare(value, "stale") && + strcasecompare(content, "true")) { + stale = true; + break; + } + + while(*p && ISSPACE(*p)) + p++; + + if(',' == *p) + p++; + } + + if(stale) + Curl_auth_digest_cleanup(digest); + else + return CURLE_LOGIN_DENIED; + } + + /* Store the challenge for use later */ + digest->input_token = (BYTE *) Curl_memdup(chlg, chlglen + 1); + if(!digest->input_token) + return CURLE_OUT_OF_MEMORY; + + digest->input_token_len = chlglen; + + return CURLE_OK; +} + +/* + * Curl_auth_create_digest_http_message() + * + * This is used to generate a HTTP DIGEST response message ready for sending + * to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * userp [in] - The user name in the format User or Domain\User. + * passwdp [in] - The user's password. + * request [in] - The HTTP request. + * uripath [in] - The path of the HTTP uri. + * digest [in/out] - The digest data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + const unsigned char *request, + const unsigned char *uripath, + struct digestdata *digest, + char **outptr, size_t *outlen) +{ + size_t token_max; + char *resp; + BYTE *output_token; + size_t output_token_len = 0; + PSecPkgInfo SecurityPackage; + SecBuffer chlg_buf[5]; + SecBufferDesc chlg_desc; + SECURITY_STATUS status; + + (void) data; + + /* Query the security package for DigestSSP */ + status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST), + &SecurityPackage); + if(status != SEC_E_OK) + return CURLE_NOT_BUILT_IN; + + token_max = SecurityPackage->cbMaxToken; + + /* Release the package buffer as it is not required anymore */ + s_pSecFn->FreeContextBuffer(SecurityPackage); + + /* Allocate the output buffer according to the max token size as indicated + by the security package */ + output_token = malloc(token_max); + if(!output_token) { + return CURLE_OUT_OF_MEMORY; + } + + /* If the user/passwd that was used to make the identity for http_context + has changed then delete that context. */ + if((userp && !digest->user) || (!userp && digest->user) || + (passwdp && !digest->passwd) || (!passwdp && digest->passwd) || + (userp && digest->user && strcmp(userp, digest->user)) || + (passwdp && digest->passwd && strcmp(passwdp, digest->passwd))) { + if(digest->http_context) { + s_pSecFn->DeleteSecurityContext(digest->http_context); + Curl_safefree(digest->http_context); + } + Curl_safefree(digest->user); + Curl_safefree(digest->passwd); + } + + if(digest->http_context) { + chlg_desc.ulVersion = SECBUFFER_VERSION; + chlg_desc.cBuffers = 5; + chlg_desc.pBuffers = chlg_buf; + chlg_buf[0].BufferType = SECBUFFER_TOKEN; + chlg_buf[0].pvBuffer = NULL; + chlg_buf[0].cbBuffer = 0; + chlg_buf[1].BufferType = SECBUFFER_PKG_PARAMS; + chlg_buf[1].pvBuffer = (void *) request; + chlg_buf[1].cbBuffer = curlx_uztoul(strlen((const char *) request)); + chlg_buf[2].BufferType = SECBUFFER_PKG_PARAMS; + chlg_buf[2].pvBuffer = (void *) uripath; + chlg_buf[2].cbBuffer = curlx_uztoul(strlen((const char *) uripath)); + chlg_buf[3].BufferType = SECBUFFER_PKG_PARAMS; + chlg_buf[3].pvBuffer = NULL; + chlg_buf[3].cbBuffer = 0; + chlg_buf[4].BufferType = SECBUFFER_PADDING; + chlg_buf[4].pvBuffer = output_token; + chlg_buf[4].cbBuffer = curlx_uztoul(token_max); + + status = s_pSecFn->MakeSignature(digest->http_context, 0, &chlg_desc, 0); + if(status == SEC_E_OK) + output_token_len = chlg_buf[4].cbBuffer; + else { /* delete the context so a new one can be made */ + infof(data, "digest_sspi: MakeSignature failed, error 0x%08lx\n", + (long)status); + s_pSecFn->DeleteSecurityContext(digest->http_context); + Curl_safefree(digest->http_context); + } + } + + if(!digest->http_context) { + CredHandle credentials; + SEC_WINNT_AUTH_IDENTITY identity; + SEC_WINNT_AUTH_IDENTITY *p_identity; + SecBuffer resp_buf; + SecBufferDesc resp_desc; + unsigned long attrs; + TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */ + TCHAR *spn; + + /* free the copy of user/passwd used to make the previous identity */ + Curl_safefree(digest->user); + Curl_safefree(digest->passwd); + + if(userp && *userp) { + /* Populate our identity structure */ + if(Curl_create_sspi_identity(userp, passwdp, &identity)) { + free(output_token); + return CURLE_OUT_OF_MEMORY; + } + + /* Populate our identity domain */ + if(Curl_override_sspi_http_realm((const char *) digest->input_token, + &identity)) { + free(output_token); + return CURLE_OUT_OF_MEMORY; + } + + /* Allow proper cleanup of the identity structure */ + p_identity = &identity; + } + else + /* Use the current Windows user */ + p_identity = NULL; + + if(userp) { + digest->user = strdup(userp); + + if(!digest->user) { + free(output_token); + return CURLE_OUT_OF_MEMORY; + } + } + + if(passwdp) { + digest->passwd = strdup(passwdp); + + if(!digest->passwd) { + free(output_token); + Curl_safefree(digest->user); + return CURLE_OUT_OF_MEMORY; + } + } + + /* Acquire our credentials handle */ + status = s_pSecFn->AcquireCredentialsHandle(NULL, + (TCHAR *) TEXT(SP_NAME_DIGEST), + SECPKG_CRED_OUTBOUND, NULL, + p_identity, NULL, NULL, + &credentials, &expiry); + if(status != SEC_E_OK) { + Curl_sspi_free_identity(p_identity); + free(output_token); + + return CURLE_LOGIN_DENIED; + } + + /* Setup the challenge "input" security buffer if present */ + chlg_desc.ulVersion = SECBUFFER_VERSION; + chlg_desc.cBuffers = 3; + chlg_desc.pBuffers = chlg_buf; + chlg_buf[0].BufferType = SECBUFFER_TOKEN; + chlg_buf[0].pvBuffer = digest->input_token; + chlg_buf[0].cbBuffer = curlx_uztoul(digest->input_token_len); + chlg_buf[1].BufferType = SECBUFFER_PKG_PARAMS; + chlg_buf[1].pvBuffer = (void *) request; + chlg_buf[1].cbBuffer = curlx_uztoul(strlen((const char *) request)); + chlg_buf[2].BufferType = SECBUFFER_PKG_PARAMS; + chlg_buf[2].pvBuffer = NULL; + chlg_buf[2].cbBuffer = 0; + + /* Setup the response "output" security buffer */ + resp_desc.ulVersion = SECBUFFER_VERSION; + resp_desc.cBuffers = 1; + resp_desc.pBuffers = &resp_buf; + resp_buf.BufferType = SECBUFFER_TOKEN; + resp_buf.pvBuffer = output_token; + resp_buf.cbBuffer = curlx_uztoul(token_max); + + spn = Curl_convert_UTF8_to_tchar((char *) uripath); + if(!spn) { + s_pSecFn->FreeCredentialsHandle(&credentials); + + Curl_sspi_free_identity(p_identity); + free(output_token); + + return CURLE_OUT_OF_MEMORY; + } + + /* Allocate our new context handle */ + digest->http_context = calloc(1, sizeof(CtxtHandle)); + if(!digest->http_context) + return CURLE_OUT_OF_MEMORY; + + /* Generate our response message */ + status = s_pSecFn->InitializeSecurityContext(&credentials, NULL, + spn, + ISC_REQ_USE_HTTP_STYLE, 0, 0, + &chlg_desc, 0, + digest->http_context, + &resp_desc, &attrs, &expiry); + Curl_unicodefree(spn); + + if(status == SEC_I_COMPLETE_NEEDED || + status == SEC_I_COMPLETE_AND_CONTINUE) + s_pSecFn->CompleteAuthToken(&credentials, &resp_desc); + else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) { + s_pSecFn->FreeCredentialsHandle(&credentials); + + Curl_sspi_free_identity(p_identity); + free(output_token); + + Curl_safefree(digest->http_context); + + return CURLE_OUT_OF_MEMORY; + } + + output_token_len = resp_buf.cbBuffer; + + s_pSecFn->FreeCredentialsHandle(&credentials); + Curl_sspi_free_identity(p_identity); + } + + resp = malloc(output_token_len + 1); + if(!resp) { + free(output_token); + + return CURLE_OUT_OF_MEMORY; + } + + /* Copy the generated response */ + memcpy(resp, output_token, output_token_len); + resp[output_token_len] = 0; + + /* Return the response */ + *outptr = resp; + *outlen = output_token_len; + + /* Free the response buffer */ + free(output_token); + + return CURLE_OK; +} + +/* + * Curl_auth_digest_cleanup() + * + * This is used to clean up the digest specific data. + * + * Parameters: + * + * digest [in/out] - The digest data struct being cleaned up. + * + */ +void Curl_auth_digest_cleanup(struct digestdata *digest) +{ + /* Free the input token */ + Curl_safefree(digest->input_token); + + /* Reset any variables */ + digest->input_token_len = 0; + + /* Delete security context */ + if(digest->http_context) { + s_pSecFn->DeleteSecurityContext(digest->http_context); + Curl_safefree(digest->http_context); + } + + /* Free the copy of user/passwd used to make the identity for http_context */ + Curl_safefree(digest->user); + Curl_safefree(digest->passwd); +} + +#endif /* USE_WINDOWS_SSPI && !CURL_DISABLE_CRYPTO_AUTH */ diff --git a/dependencies/cmcurl/lib/vauth/krb5_gssapi.c b/dependencies/cmcurl/lib/vauth/krb5_gssapi.c new file mode 100644 index 0000000..ea0a5f1 --- /dev/null +++ b/dependencies/cmcurl/lib/vauth/krb5_gssapi.c @@ -0,0 +1,401 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2014 - 2019, Steve Holme, . + * Copyright (C) 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(HAVE_GSSAPI) && defined(USE_KERBEROS5) + +#include + +#include "vauth/vauth.h" +#include "curl_sasl.h" +#include "urldata.h" +#include "curl_base64.h" +#include "curl_gssapi.h" +#include "sendf.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Curl_auth_is_gssapi_supported() + * + * This is used to evaluate if GSSAPI (Kerberos V5) is supported. + * + * Parameters: None + * + * Returns TRUE if Kerberos V5 is supported by the GSS-API library. + */ +bool Curl_auth_is_gssapi_supported(void) +{ + return TRUE; +} + +/* + * Curl_auth_create_gssapi_user_message() + * + * This is used to generate an already encoded GSSAPI (Kerberos V5) user token + * message ready for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * userp [in] - The user name. + * passwdp [in] - The user's password. + * service [in] - The service type such as http, smtp, pop or imap. + * host [in[ - The host name. + * mutual_auth [in] - Flag specifying whether or not mutual authentication + * is enabled. + * chlg64 [in] - Pointer to the optional base64 encoded challenge + * message. + * krb5 [in/out] - The Kerberos 5 data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + const char *service, + const char *host, + const bool mutual_auth, + const char *chlg64, + struct kerberos5data *krb5, + char **outptr, size_t *outlen) +{ + CURLcode result = CURLE_OK; + size_t chlglen = 0; + unsigned char *chlg = NULL; + OM_uint32 major_status; + OM_uint32 minor_status; + OM_uint32 unused_status; + gss_buffer_desc spn_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + + (void) userp; + (void) passwdp; + + if(!krb5->spn) { + /* Generate our SPN */ + char *spn = Curl_auth_build_spn(service, NULL, host); + if(!spn) + return CURLE_OUT_OF_MEMORY; + + /* Populate the SPN structure */ + spn_token.value = spn; + spn_token.length = strlen(spn); + + /* Import the SPN */ + major_status = gss_import_name(&minor_status, &spn_token, + GSS_C_NT_HOSTBASED_SERVICE, &krb5->spn); + if(GSS_ERROR(major_status)) { + Curl_gss_log_error(data, "gss_import_name() failed: ", + major_status, minor_status); + + free(spn); + + return CURLE_OUT_OF_MEMORY; + } + + free(spn); + } + + if(chlg64 && *chlg64) { + /* Decode the base-64 encoded challenge message */ + if(*chlg64 != '=') { + result = Curl_base64_decode(chlg64, &chlg, &chlglen); + if(result) + return result; + } + + /* Ensure we have a valid challenge message */ + if(!chlg) { + infof(data, "GSSAPI handshake failure (empty challenge message)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Setup the challenge "input" security buffer */ + input_token.value = chlg; + input_token.length = chlglen; + } + + major_status = Curl_gss_init_sec_context(data, + &minor_status, + &krb5->context, + krb5->spn, + &Curl_krb5_mech_oid, + GSS_C_NO_CHANNEL_BINDINGS, + &input_token, + &output_token, + mutual_auth, + NULL); + + /* Free the decoded challenge as it is not required anymore */ + free(input_token.value); + + if(GSS_ERROR(major_status)) { + if(output_token.value) + gss_release_buffer(&unused_status, &output_token); + + Curl_gss_log_error(data, "gss_init_sec_context() failed: ", + major_status, minor_status); + + return CURLE_RECV_ERROR; + } + + if(output_token.value && output_token.length) { + /* Base64 encode the response */ + result = Curl_base64_encode(data, (char *) output_token.value, + output_token.length, outptr, outlen); + + gss_release_buffer(&unused_status, &output_token); + } + else if(mutual_auth) { + *outptr = strdup(""); + if(!*outptr) + result = CURLE_OUT_OF_MEMORY; + } + + return result; +} + +/* + * Curl_auth_create_gssapi_security_message() + * + * This is used to generate an already encoded GSSAPI (Kerberos V5) security + * token message ready for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * chlg64 [in] - Pointer to the optional base64 encoded challenge message. + * krb5 [in/out] - The Kerberos 5 data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, + const char *chlg64, + struct kerberos5data *krb5, + char **outptr, + size_t *outlen) +{ + CURLcode result = CURLE_OK; + size_t chlglen = 0; + size_t messagelen = 0; + unsigned char *chlg = NULL; + unsigned char *message = NULL; + OM_uint32 major_status; + OM_uint32 minor_status; + OM_uint32 unused_status; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + unsigned int indata = 0; + unsigned int outdata = 0; + gss_qop_t qop = GSS_C_QOP_DEFAULT; + unsigned int sec_layer = 0; + unsigned int max_size = 0; + gss_name_t username = GSS_C_NO_NAME; + gss_buffer_desc username_token; + + /* Decode the base-64 encoded input message */ + if(strlen(chlg64) && *chlg64 != '=') { + result = Curl_base64_decode(chlg64, &chlg, &chlglen); + if(result) + return result; + } + + /* Ensure we have a valid challenge message */ + if(!chlg) { + infof(data, "GSSAPI handshake failure (empty security message)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Get the fully qualified username back from the context */ + major_status = gss_inquire_context(&minor_status, krb5->context, + &username, NULL, NULL, NULL, NULL, + NULL, NULL); + if(GSS_ERROR(major_status)) { + Curl_gss_log_error(data, "gss_inquire_context() failed: ", + major_status, minor_status); + + free(chlg); + + return CURLE_OUT_OF_MEMORY; + } + + /* Convert the username from internal format to a displayable token */ + major_status = gss_display_name(&minor_status, username, + &username_token, NULL); + if(GSS_ERROR(major_status)) { + Curl_gss_log_error(data, "gss_display_name() failed: ", + major_status, minor_status); + + free(chlg); + + return CURLE_OUT_OF_MEMORY; + } + + /* Setup the challenge "input" security buffer */ + input_token.value = chlg; + input_token.length = chlglen; + + /* Decrypt the inbound challenge and obtain the qop */ + major_status = gss_unwrap(&minor_status, krb5->context, &input_token, + &output_token, NULL, &qop); + if(GSS_ERROR(major_status)) { + Curl_gss_log_error(data, "gss_unwrap() failed: ", + major_status, minor_status); + + gss_release_buffer(&unused_status, &username_token); + free(chlg); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Not 4 octets long so fail as per RFC4752 Section 3.1 */ + if(output_token.length != 4) { + infof(data, "GSSAPI handshake failure (invalid security data)\n"); + + gss_release_buffer(&unused_status, &username_token); + free(chlg); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Copy the data out and free the challenge as it is not required anymore */ + memcpy(&indata, output_token.value, 4); + gss_release_buffer(&unused_status, &output_token); + free(chlg); + + /* Extract the security layer */ + sec_layer = indata & 0x000000FF; + if(!(sec_layer & GSSAUTH_P_NONE)) { + infof(data, "GSSAPI handshake failure (invalid security layer)\n"); + + gss_release_buffer(&unused_status, &username_token); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Extract the maximum message size the server can receive */ + max_size = ntohl(indata & 0xFFFFFF00); + if(max_size > 0) { + /* The server has told us it supports a maximum receive buffer, however, as + we don't require one unless we are encrypting data, we tell the server + our receive buffer is zero. */ + max_size = 0; + } + + /* Allocate our message */ + messagelen = sizeof(outdata) + username_token.length + 1; + message = malloc(messagelen); + if(!message) { + gss_release_buffer(&unused_status, &username_token); + + return CURLE_OUT_OF_MEMORY; + } + + /* Populate the message with the security layer, client supported receive + message size and authorization identity including the 0x00 based + terminator. Note: Despite RFC4752 Section 3.1 stating "The authorization + identity is not terminated with the zero-valued (%x00) octet." it seems + necessary to include it. */ + outdata = htonl(max_size) | sec_layer; + memcpy(message, &outdata, sizeof(outdata)); + memcpy(message + sizeof(outdata), username_token.value, + username_token.length); + message[messagelen - 1] = '\0'; + + /* Free the username token as it is not required anymore */ + gss_release_buffer(&unused_status, &username_token); + + /* Setup the "authentication data" security buffer */ + input_token.value = message; + input_token.length = messagelen; + + /* Encrypt the data */ + major_status = gss_wrap(&minor_status, krb5->context, 0, + GSS_C_QOP_DEFAULT, &input_token, NULL, + &output_token); + if(GSS_ERROR(major_status)) { + Curl_gss_log_error(data, "gss_wrap() failed: ", + major_status, minor_status); + + free(message); + + return CURLE_OUT_OF_MEMORY; + } + + /* Base64 encode the response */ + result = Curl_base64_encode(data, (char *) output_token.value, + output_token.length, outptr, outlen); + + /* Free the output buffer */ + gss_release_buffer(&unused_status, &output_token); + + /* Free the message buffer */ + free(message); + + return result; +} + +/* + * Curl_auth_cleanup_gssapi() + * + * This is used to clean up the GSSAPI (Kerberos V5) specific data. + * + * Parameters: + * + * krb5 [in/out] - The Kerberos 5 data struct being cleaned up. + * + */ +void Curl_auth_cleanup_gssapi(struct kerberos5data *krb5) +{ + OM_uint32 minor_status; + + /* Free our security context */ + if(krb5->context != GSS_C_NO_CONTEXT) { + gss_delete_sec_context(&minor_status, &krb5->context, GSS_C_NO_BUFFER); + krb5->context = GSS_C_NO_CONTEXT; + } + + /* Free the SPN */ + if(krb5->spn != GSS_C_NO_NAME) { + gss_release_name(&minor_status, &krb5->spn); + krb5->spn = GSS_C_NO_NAME; + } +} + +#endif /* HAVE_GSSAPI && USE_KERBEROS5 */ diff --git a/dependencies/cmcurl/lib/vauth/krb5_sspi.c b/dependencies/cmcurl/lib/vauth/krb5_sspi.c new file mode 100644 index 0000000..1f6e462 --- /dev/null +++ b/dependencies/cmcurl/lib/vauth/krb5_sspi.c @@ -0,0 +1,514 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2014 - 2019, Steve Holme, . + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_WINDOWS_SSPI) && defined(USE_KERBEROS5) + +#include + +#include "vauth/vauth.h" +#include "urldata.h" +#include "curl_base64.h" +#include "warnless.h" +#include "curl_multibyte.h" +#include "sendf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Curl_auth_is_gssapi_supported() + * + * This is used to evaluate if GSSAPI (Kerberos V5) is supported. + * + * Parameters: None + * + * Returns TRUE if Kerberos V5 is supported by Windows SSPI. + */ +bool Curl_auth_is_gssapi_supported(void) +{ + PSecPkgInfo SecurityPackage; + SECURITY_STATUS status; + + /* Query the security package for Kerberos */ + status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) + TEXT(SP_NAME_KERBEROS), + &SecurityPackage); + + return (status == SEC_E_OK ? TRUE : FALSE); +} + +/* + * Curl_auth_create_gssapi_user_message() + * + * This is used to generate an already encoded GSSAPI (Kerberos V5) user token + * message ready for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * userp [in] - The user name in the format User or Domain\User. + * passwdp [in] - The user's password. + * service [in] - The service type such as http, smtp, pop or imap. + * host [in] - The host name. + * mutual_auth [in] - Flag specifying whether or not mutual authentication + * is enabled. + * chlg64 [in] - The optional base64 encoded challenge message. + * krb5 [in/out] - The Kerberos 5 data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + const char *service, + const char *host, + const bool mutual_auth, + const char *chlg64, + struct kerberos5data *krb5, + char **outptr, size_t *outlen) +{ + CURLcode result = CURLE_OK; + size_t chlglen = 0; + unsigned char *chlg = NULL; + CtxtHandle context; + PSecPkgInfo SecurityPackage; + SecBuffer chlg_buf; + SecBuffer resp_buf; + SecBufferDesc chlg_desc; + SecBufferDesc resp_desc; + SECURITY_STATUS status; + unsigned long attrs; + TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */ + + if(!krb5->spn) { + /* Generate our SPN */ + krb5->spn = Curl_auth_build_spn(service, host, NULL); + if(!krb5->spn) + return CURLE_OUT_OF_MEMORY; + } + + if(!krb5->output_token) { + /* Query the security package for Kerberos */ + status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) + TEXT(SP_NAME_KERBEROS), + &SecurityPackage); + if(status != SEC_E_OK) { + return CURLE_NOT_BUILT_IN; + } + + krb5->token_max = SecurityPackage->cbMaxToken; + + /* Release the package buffer as it is not required anymore */ + s_pSecFn->FreeContextBuffer(SecurityPackage); + + /* Allocate our response buffer */ + krb5->output_token = malloc(krb5->token_max); + if(!krb5->output_token) + return CURLE_OUT_OF_MEMORY; + } + + if(!krb5->credentials) { + /* Do we have credentials to use or are we using single sign-on? */ + if(userp && *userp) { + /* Populate our identity structure */ + result = Curl_create_sspi_identity(userp, passwdp, &krb5->identity); + if(result) + return result; + + /* Allow proper cleanup of the identity structure */ + krb5->p_identity = &krb5->identity; + } + else + /* Use the current Windows user */ + krb5->p_identity = NULL; + + /* Allocate our credentials handle */ + krb5->credentials = calloc(1, sizeof(CredHandle)); + if(!krb5->credentials) + return CURLE_OUT_OF_MEMORY; + + /* Acquire our credentials handle */ + status = s_pSecFn->AcquireCredentialsHandle(NULL, + (TCHAR *) + TEXT(SP_NAME_KERBEROS), + SECPKG_CRED_OUTBOUND, NULL, + krb5->p_identity, NULL, NULL, + krb5->credentials, &expiry); + if(status != SEC_E_OK) + return CURLE_LOGIN_DENIED; + + /* Allocate our new context handle */ + krb5->context = calloc(1, sizeof(CtxtHandle)); + if(!krb5->context) + return CURLE_OUT_OF_MEMORY; + } + + if(chlg64 && *chlg64) { + /* Decode the base-64 encoded challenge message */ + if(*chlg64 != '=') { + result = Curl_base64_decode(chlg64, &chlg, &chlglen); + if(result) + return result; + } + + /* Ensure we have a valid challenge message */ + if(!chlg) { + infof(data, "GSSAPI handshake failure (empty challenge message)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Setup the challenge "input" security buffer */ + chlg_desc.ulVersion = SECBUFFER_VERSION; + chlg_desc.cBuffers = 1; + chlg_desc.pBuffers = &chlg_buf; + chlg_buf.BufferType = SECBUFFER_TOKEN; + chlg_buf.pvBuffer = chlg; + chlg_buf.cbBuffer = curlx_uztoul(chlglen); + } + + /* Setup the response "output" security buffer */ + resp_desc.ulVersion = SECBUFFER_VERSION; + resp_desc.cBuffers = 1; + resp_desc.pBuffers = &resp_buf; + resp_buf.BufferType = SECBUFFER_TOKEN; + resp_buf.pvBuffer = krb5->output_token; + resp_buf.cbBuffer = curlx_uztoul(krb5->token_max); + + /* Generate our challenge-response message */ + status = s_pSecFn->InitializeSecurityContext(krb5->credentials, + chlg ? krb5->context : NULL, + krb5->spn, + (mutual_auth ? + ISC_REQ_MUTUAL_AUTH : 0), + 0, SECURITY_NATIVE_DREP, + chlg ? &chlg_desc : NULL, 0, + &context, + &resp_desc, &attrs, + &expiry); + + /* Free the decoded challenge as it is not required anymore */ + free(chlg); + + if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) { + return CURLE_RECV_ERROR; + } + + if(memcmp(&context, krb5->context, sizeof(context))) { + s_pSecFn->DeleteSecurityContext(krb5->context); + + memcpy(krb5->context, &context, sizeof(context)); + } + + if(resp_buf.cbBuffer) { + /* Base64 encode the response */ + result = Curl_base64_encode(data, (char *) resp_buf.pvBuffer, + resp_buf.cbBuffer, outptr, outlen); + } + else if(mutual_auth) { + *outptr = strdup(""); + if(!*outptr) + result = CURLE_OUT_OF_MEMORY; + } + + return result; +} + +/* + * Curl_auth_create_gssapi_security_message() + * + * This is used to generate an already encoded GSSAPI (Kerberos V5) security + * token message ready for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * chlg64 [in] - The optional base64 encoded challenge message. + * krb5 [in/out] - The Kerberos 5 data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, + const char *chlg64, + struct kerberos5data *krb5, + char **outptr, + size_t *outlen) +{ + CURLcode result = CURLE_OK; + size_t offset = 0; + size_t chlglen = 0; + size_t messagelen = 0; + size_t appdatalen = 0; + unsigned char *chlg = NULL; + unsigned char *trailer = NULL; + unsigned char *message = NULL; + unsigned char *padding = NULL; + unsigned char *appdata = NULL; + SecBuffer input_buf[2]; + SecBuffer wrap_buf[3]; + SecBufferDesc input_desc; + SecBufferDesc wrap_desc; + unsigned long indata = 0; + unsigned long outdata = 0; + unsigned long qop = 0; + unsigned long sec_layer = 0; + unsigned long max_size = 0; + SecPkgContext_Sizes sizes; + SecPkgCredentials_Names names; + SECURITY_STATUS status; + char *user_name; + + /* Decode the base-64 encoded input message */ + if(strlen(chlg64) && *chlg64 != '=') { + result = Curl_base64_decode(chlg64, &chlg, &chlglen); + if(result) + return result; + } + + /* Ensure we have a valid challenge message */ + if(!chlg) { + infof(data, "GSSAPI handshake failure (empty security message)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Get our response size information */ + status = s_pSecFn->QueryContextAttributes(krb5->context, + SECPKG_ATTR_SIZES, + &sizes); + if(status != SEC_E_OK) { + free(chlg); + + return CURLE_OUT_OF_MEMORY; + } + + /* Get the fully qualified username back from the context */ + status = s_pSecFn->QueryCredentialsAttributes(krb5->credentials, + SECPKG_CRED_ATTR_NAMES, + &names); + if(status != SEC_E_OK) { + free(chlg); + + return CURLE_RECV_ERROR; + } + + /* Setup the "input" security buffer */ + input_desc.ulVersion = SECBUFFER_VERSION; + input_desc.cBuffers = 2; + input_desc.pBuffers = input_buf; + input_buf[0].BufferType = SECBUFFER_STREAM; + input_buf[0].pvBuffer = chlg; + input_buf[0].cbBuffer = curlx_uztoul(chlglen); + input_buf[1].BufferType = SECBUFFER_DATA; + input_buf[1].pvBuffer = NULL; + input_buf[1].cbBuffer = 0; + + /* Decrypt the inbound challenge and obtain the qop */ + status = s_pSecFn->DecryptMessage(krb5->context, &input_desc, 0, &qop); + if(status != SEC_E_OK) { + infof(data, "GSSAPI handshake failure (empty security message)\n"); + + free(chlg); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Not 4 octets long so fail as per RFC4752 Section 3.1 */ + if(input_buf[1].cbBuffer != 4) { + infof(data, "GSSAPI handshake failure (invalid security data)\n"); + + free(chlg); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Copy the data out and free the challenge as it is not required anymore */ + memcpy(&indata, input_buf[1].pvBuffer, 4); + s_pSecFn->FreeContextBuffer(input_buf[1].pvBuffer); + free(chlg); + + /* Extract the security layer */ + sec_layer = indata & 0x000000FF; + if(!(sec_layer & KERB_WRAP_NO_ENCRYPT)) { + infof(data, "GSSAPI handshake failure (invalid security layer)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Extract the maximum message size the server can receive */ + max_size = ntohl(indata & 0xFFFFFF00); + if(max_size > 0) { + /* The server has told us it supports a maximum receive buffer, however, as + we don't require one unless we are encrypting data, we tell the server + our receive buffer is zero. */ + max_size = 0; + } + + /* Allocate the trailer */ + trailer = malloc(sizes.cbSecurityTrailer); + if(!trailer) + return CURLE_OUT_OF_MEMORY; + + /* Convert the user name to UTF8 when operating with Unicode */ + user_name = Curl_convert_tchar_to_UTF8(names.sUserName); + if(!user_name) { + free(trailer); + + return CURLE_OUT_OF_MEMORY; + } + + /* Allocate our message */ + messagelen = sizeof(outdata) + strlen(user_name) + 1; + message = malloc(messagelen); + if(!message) { + free(trailer); + Curl_unicodefree(user_name); + + return CURLE_OUT_OF_MEMORY; + } + + /* Populate the message with the security layer, client supported receive + message size and authorization identity including the 0x00 based + terminator. Note: Despite RFC4752 Section 3.1 stating "The authorization + identity is not terminated with the zero-valued (%x00) octet." it seems + necessary to include it. */ + outdata = htonl(max_size) | sec_layer; + memcpy(message, &outdata, sizeof(outdata)); + strcpy((char *) message + sizeof(outdata), user_name); + Curl_unicodefree(user_name); + + /* Allocate the padding */ + padding = malloc(sizes.cbBlockSize); + if(!padding) { + free(message); + free(trailer); + + return CURLE_OUT_OF_MEMORY; + } + + /* Setup the "authentication data" security buffer */ + wrap_desc.ulVersion = SECBUFFER_VERSION; + wrap_desc.cBuffers = 3; + wrap_desc.pBuffers = wrap_buf; + wrap_buf[0].BufferType = SECBUFFER_TOKEN; + wrap_buf[0].pvBuffer = trailer; + wrap_buf[0].cbBuffer = sizes.cbSecurityTrailer; + wrap_buf[1].BufferType = SECBUFFER_DATA; + wrap_buf[1].pvBuffer = message; + wrap_buf[1].cbBuffer = curlx_uztoul(messagelen); + wrap_buf[2].BufferType = SECBUFFER_PADDING; + wrap_buf[2].pvBuffer = padding; + wrap_buf[2].cbBuffer = sizes.cbBlockSize; + + /* Encrypt the data */ + status = s_pSecFn->EncryptMessage(krb5->context, KERB_WRAP_NO_ENCRYPT, + &wrap_desc, 0); + if(status != SEC_E_OK) { + free(padding); + free(message); + free(trailer); + + return CURLE_OUT_OF_MEMORY; + } + + /* Allocate the encryption (wrap) buffer */ + appdatalen = wrap_buf[0].cbBuffer + wrap_buf[1].cbBuffer + + wrap_buf[2].cbBuffer; + appdata = malloc(appdatalen); + if(!appdata) { + free(padding); + free(message); + free(trailer); + + return CURLE_OUT_OF_MEMORY; + } + + /* Populate the encryption buffer */ + memcpy(appdata, wrap_buf[0].pvBuffer, wrap_buf[0].cbBuffer); + offset += wrap_buf[0].cbBuffer; + memcpy(appdata + offset, wrap_buf[1].pvBuffer, wrap_buf[1].cbBuffer); + offset += wrap_buf[1].cbBuffer; + memcpy(appdata + offset, wrap_buf[2].pvBuffer, wrap_buf[2].cbBuffer); + + /* Base64 encode the response */ + result = Curl_base64_encode(data, (char *) appdata, appdatalen, outptr, + outlen); + + /* Free all of our local buffers */ + free(appdata); + free(padding); + free(message); + free(trailer); + + return result; +} + +/* + * Curl_auth_cleanup_gssapi() + * + * This is used to clean up the GSSAPI (Kerberos V5) specific data. + * + * Parameters: + * + * krb5 [in/out] - The Kerberos 5 data struct being cleaned up. + * + */ +void Curl_auth_cleanup_gssapi(struct kerberos5data *krb5) +{ + /* Free our security context */ + if(krb5->context) { + s_pSecFn->DeleteSecurityContext(krb5->context); + free(krb5->context); + krb5->context = NULL; + } + + /* Free our credentials handle */ + if(krb5->credentials) { + s_pSecFn->FreeCredentialsHandle(krb5->credentials); + free(krb5->credentials); + krb5->credentials = NULL; + } + + /* Free our identity */ + Curl_sspi_free_identity(krb5->p_identity); + krb5->p_identity = NULL; + + /* Free the SPN and output token */ + Curl_safefree(krb5->spn); + Curl_safefree(krb5->output_token); + + /* Reset any variables */ + krb5->token_max = 0; +} + +#endif /* USE_WINDOWS_SSPI && USE_KERBEROS5*/ diff --git a/dependencies/cmcurl/lib/vauth/ntlm.c b/dependencies/cmcurl/lib/vauth/ntlm.c new file mode 100644 index 0000000..047c2b5 --- /dev/null +++ b/dependencies/cmcurl/lib/vauth/ntlm.c @@ -0,0 +1,871 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_NTLM) && !defined(USE_WINDOWS_SSPI) + +/* + * NTLM details: + * + * https://davenport.sourceforge.io/ntlm.html + * https://www.innovation.ch/java/ntlm.html + */ + +#define DEBUG_ME 0 + +#include "urldata.h" +#include "non-ascii.h" +#include "sendf.h" +#include "curl_base64.h" +#include "curl_ntlm_core.h" +#include "curl_gethostname.h" +#include "curl_multibyte.h" +#include "warnless.h" +#include "rand.h" +#include "vtls/vtls.h" + +/* SSL backend-specific #if branches in this file must be kept in the order + documented in curl_ntlm_core. */ +#if defined(NTLM_NEEDS_NSS_INIT) +#include "vtls/nssg.h" /* for Curl_nss_force_init() */ +#endif + +#define BUILDING_CURL_NTLM_MSGS_C +#include "vauth/vauth.h" +#include "vauth/ntlm.h" +#include "curl_endian.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* "NTLMSSP" signature is always in ASCII regardless of the platform */ +#define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50" + +#define SHORTPAIR(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff)) +#define LONGQUARTET(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff)), \ + ((int)(((x) >> 16) & 0xff)), ((int)(((x) >> 24) & 0xff)) + +#if DEBUG_ME +# define DEBUG_OUT(x) x +static void ntlm_print_flags(FILE *handle, unsigned long flags) +{ + if(flags & NTLMFLAG_NEGOTIATE_UNICODE) + fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE "); + if(flags & NTLMFLAG_NEGOTIATE_OEM) + fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM "); + if(flags & NTLMFLAG_REQUEST_TARGET) + fprintf(handle, "NTLMFLAG_REQUEST_TARGET "); + if(flags & (1<<3)) + fprintf(handle, "NTLMFLAG_UNKNOWN_3 "); + if(flags & NTLMFLAG_NEGOTIATE_SIGN) + fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN "); + if(flags & NTLMFLAG_NEGOTIATE_SEAL) + fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL "); + if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE) + fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE "); + if(flags & NTLMFLAG_NEGOTIATE_LM_KEY) + fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY "); + if(flags & NTLMFLAG_NEGOTIATE_NETWARE) + fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE "); + if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY) + fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY "); + if(flags & (1<<10)) + fprintf(handle, "NTLMFLAG_UNKNOWN_10 "); + if(flags & NTLMFLAG_NEGOTIATE_ANONYMOUS) + fprintf(handle, "NTLMFLAG_NEGOTIATE_ANONYMOUS "); + if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED) + fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED "); + if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED) + fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED "); + if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL) + fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL "); + if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN) + fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN "); + if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN) + fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN "); + if(flags & NTLMFLAG_TARGET_TYPE_SERVER) + fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER "); + if(flags & NTLMFLAG_TARGET_TYPE_SHARE) + fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE "); + if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) + fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY "); + if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE) + fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE "); + if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE) + fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE "); + if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY) + fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY "); + if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) + fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO "); + if(flags & (1<<24)) + fprintf(handle, "NTLMFLAG_UNKNOWN_24 "); + if(flags & (1<<25)) + fprintf(handle, "NTLMFLAG_UNKNOWN_25 "); + if(flags & (1<<26)) + fprintf(handle, "NTLMFLAG_UNKNOWN_26 "); + if(flags & (1<<27)) + fprintf(handle, "NTLMFLAG_UNKNOWN_27 "); + if(flags & (1<<28)) + fprintf(handle, "NTLMFLAG_UNKNOWN_28 "); + if(flags & NTLMFLAG_NEGOTIATE_128) + fprintf(handle, "NTLMFLAG_NEGOTIATE_128 "); + if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE) + fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE "); + if(flags & NTLMFLAG_NEGOTIATE_56) + fprintf(handle, "NTLMFLAG_NEGOTIATE_56 "); +} + +static void ntlm_print_hex(FILE *handle, const char *buf, size_t len) +{ + const char *p = buf; + + (void) handle; + + fprintf(stderr, "0x"); + while(len-- > 0) + fprintf(stderr, "%02.2x", (unsigned int)*p++); +} +#else +# define DEBUG_OUT(x) Curl_nop_stmt +#endif + +/* + * ntlm_decode_type2_target() + * + * This is used to decode the "target info" in the NTLM type-2 message + * received. + * + * Parameters: + * + * data [in] - The session handle. + * buffer [in] - The decoded type-2 message. + * size [in] - The input buffer size, at least 32 bytes. + * ntlm [in/out] - The NTLM data struct being used and modified. + * + * Returns CURLE_OK on success. + */ +static CURLcode ntlm_decode_type2_target(struct Curl_easy *data, + unsigned char *buffer, + size_t size, + struct ntlmdata *ntlm) +{ + unsigned short target_info_len = 0; + unsigned int target_info_offset = 0; + +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) data; +#endif + + if(size >= 48) { + target_info_len = Curl_read16_le(&buffer[40]); + target_info_offset = Curl_read32_le(&buffer[44]); + if(target_info_len > 0) { + if((target_info_offset >= size) || + ((target_info_offset + target_info_len) > size) || + (target_info_offset < 48)) { + infof(data, "NTLM handshake failure (bad type-2 message). " + "Target Info Offset Len is set incorrect by the peer\n"); + return CURLE_BAD_CONTENT_ENCODING; + } + + ntlm->target_info = malloc(target_info_len); + if(!ntlm->target_info) + return CURLE_OUT_OF_MEMORY; + + memcpy(ntlm->target_info, &buffer[target_info_offset], target_info_len); + } + } + + ntlm->target_info_len = target_info_len; + + return CURLE_OK; +} + +/* + NTLM message structure notes: + + A 'short' is a 'network short', a little-endian 16-bit unsigned value. + + A 'long' is a 'network long', a little-endian, 32-bit unsigned value. + + A 'security buffer' represents a triplet used to point to a buffer, + consisting of two shorts and one long: + + 1. A 'short' containing the length of the buffer content in bytes. + 2. A 'short' containing the allocated space for the buffer in bytes. + 3. A 'long' containing the offset to the start of the buffer in bytes, + from the beginning of the NTLM message. +*/ + +/* + * Curl_auth_is_ntlm_supported() + * + * This is used to evaluate if NTLM is supported. + * + * Parameters: None + * + * Returns TRUE as NTLM as handled by libcurl. + */ +bool Curl_auth_is_ntlm_supported(void) +{ + return TRUE; +} + +/* + * Curl_auth_decode_ntlm_type2_message() + * + * This is used to decode an already encoded NTLM type-2 message. The message + * is first decoded from a base64 string into a raw NTLM message and checked + * for validity before the appropriate data for creating a type-3 message is + * written to the given NTLM data structure. + * + * Parameters: + * + * data [in] - The session handle. + * type2msg [in] - The base64 encoded type-2 message. + * ntlm [in/out] - The NTLM data struct being used and modified. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, + const char *type2msg, + struct ntlmdata *ntlm) +{ + static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 }; + + /* NTLM type-2 message structure: + + Index Description Content + 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" + (0x4e544c4d53535000) + 8 NTLM Message Type long (0x02000000) + 12 Target Name security buffer + 20 Flags long + 24 Challenge 8 bytes + (32) Context 8 bytes (two consecutive longs) (*) + (40) Target Information security buffer (*) + (48) OS Version Structure 8 bytes (*) + 32 (48) (56) Start of data block (*) + (*) -> Optional + */ + + CURLcode result = CURLE_OK; + unsigned char *type2 = NULL; + size_t type2_len = 0; + +#if defined(NTLM_NEEDS_NSS_INIT) + /* Make sure the crypto backend is initialized */ + result = Curl_nss_force_init(data); + if(result) + return result; +#elif defined(CURL_DISABLE_VERBOSE_STRINGS) + (void)data; +#endif + + /* Decode the base-64 encoded type-2 message */ + if(strlen(type2msg) && *type2msg != '=') { + result = Curl_base64_decode(type2msg, &type2, &type2_len); + if(result) + return result; + } + + /* Ensure we have a valid type-2 message */ + if(!type2) { + infof(data, "NTLM handshake failure (empty type-2 message)\n"); + return CURLE_BAD_CONTENT_ENCODING; + } + + ntlm->flags = 0; + + if((type2_len < 32) || + (memcmp(type2, NTLMSSP_SIGNATURE, 8) != 0) || + (memcmp(type2 + 8, type2_marker, sizeof(type2_marker)) != 0)) { + /* This was not a good enough type-2 message */ + free(type2); + infof(data, "NTLM handshake failure (bad type-2 message)\n"); + return CURLE_BAD_CONTENT_ENCODING; + } + + ntlm->flags = Curl_read32_le(&type2[20]); + memcpy(ntlm->nonce, &type2[24], 8); + + if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) { + result = ntlm_decode_type2_target(data, type2, type2_len, ntlm); + if(result) { + free(type2); + infof(data, "NTLM handshake failure (bad type-2 message)\n"); + return result; + } + } + + DEBUG_OUT({ + fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags); + ntlm_print_flags(stderr, ntlm->flags); + fprintf(stderr, "\n nonce="); + ntlm_print_hex(stderr, (char *)ntlm->nonce, 8); + fprintf(stderr, "\n****\n"); + fprintf(stderr, "**** Header %s\n ", header); + }); + + free(type2); + + return result; +} + +/* copy the source to the destination and fill in zeroes in every + other destination byte! */ +static void unicodecpy(unsigned char *dest, const char *src, size_t length) +{ + size_t i; + for(i = 0; i < length; i++) { + dest[2 * i] = (unsigned char)src[i]; + dest[2 * i + 1] = '\0'; + } +} + +/* + * Curl_auth_create_ntlm_type1_message() + * + * This is used to generate an already encoded NTLM type-1 message ready for + * sending to the recipient using the appropriate compile time crypto API. + * + * Parameters: + * + * data [in] - The session handle. + * userp [in] - The user name in the format User or Domain\User. + * passwdp [in] - The user's password. + * service [in] - The service type such as http, smtp, pop or imap. + * host [in] - The host name. + * ntlm [in/out] - The NTLM data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + const char *service, + const char *hostname, + struct ntlmdata *ntlm, + char **outptr, size_t *outlen) +{ + /* NTLM type-1 message structure: + + Index Description Content + 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" + (0x4e544c4d53535000) + 8 NTLM Message Type long (0x01000000) + 12 Flags long + (16) Supplied Domain security buffer (*) + (24) Supplied Workstation security buffer (*) + (32) OS Version Structure 8 bytes (*) + (32) (40) Start of data block (*) + (*) -> Optional + */ + + size_t size; + + unsigned char ntlmbuf[NTLM_BUFSIZE]; + const char *host = ""; /* empty */ + const char *domain = ""; /* empty */ + size_t hostlen = 0; + size_t domlen = 0; + size_t hostoff = 0; + size_t domoff = hostoff + hostlen; /* This is 0: remember that host and + domain are empty */ + (void)userp; + (void)passwdp; + (void)service, + (void)hostname, + + /* Clean up any former leftovers and initialise to defaults */ + Curl_auth_cleanup_ntlm(ntlm); + +#if defined(USE_NTRESPONSES) && defined(USE_NTLM2SESSION) +#define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY +#else +#define NTLM2FLAG 0 +#endif + msnprintf((char *)ntlmbuf, NTLM_BUFSIZE, + NTLMSSP_SIGNATURE "%c" + "\x01%c%c%c" /* 32-bit type = 1 */ + "%c%c%c%c" /* 32-bit NTLM flag field */ + "%c%c" /* domain length */ + "%c%c" /* domain allocated space */ + "%c%c" /* domain name offset */ + "%c%c" /* 2 zeroes */ + "%c%c" /* host length */ + "%c%c" /* host allocated space */ + "%c%c" /* host name offset */ + "%c%c" /* 2 zeroes */ + "%s" /* host name */ + "%s", /* domain string */ + 0, /* trailing zero */ + 0, 0, 0, /* part of type-1 long */ + + LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM | + NTLMFLAG_REQUEST_TARGET | + NTLMFLAG_NEGOTIATE_NTLM_KEY | + NTLM2FLAG | + NTLMFLAG_NEGOTIATE_ALWAYS_SIGN), + SHORTPAIR(domlen), + SHORTPAIR(domlen), + SHORTPAIR(domoff), + 0, 0, + SHORTPAIR(hostlen), + SHORTPAIR(hostlen), + SHORTPAIR(hostoff), + 0, 0, + host, /* this is empty */ + domain /* this is empty */); + + /* Initial packet length */ + size = 32 + hostlen + domlen; + + DEBUG_OUT({ + fprintf(stderr, "* TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x " + "0x%08.8x ", + LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM | + NTLMFLAG_REQUEST_TARGET | + NTLMFLAG_NEGOTIATE_NTLM_KEY | + NTLM2FLAG | + NTLMFLAG_NEGOTIATE_ALWAYS_SIGN), + NTLMFLAG_NEGOTIATE_OEM | + NTLMFLAG_REQUEST_TARGET | + NTLMFLAG_NEGOTIATE_NTLM_KEY | + NTLM2FLAG | + NTLMFLAG_NEGOTIATE_ALWAYS_SIGN); + ntlm_print_flags(stderr, + NTLMFLAG_NEGOTIATE_OEM | + NTLMFLAG_REQUEST_TARGET | + NTLMFLAG_NEGOTIATE_NTLM_KEY | + NTLM2FLAG | + NTLMFLAG_NEGOTIATE_ALWAYS_SIGN); + fprintf(stderr, "\n****\n"); + }); + + /* Return with binary blob encoded into base64 */ + return Curl_base64_encode(data, (char *)ntlmbuf, size, outptr, outlen); +} + +/* + * Curl_auth_create_ntlm_type3_message() + * + * This is used to generate an already encoded NTLM type-3 message ready for + * sending to the recipient using the appropriate compile time crypto API. + * + * Parameters: + * + * data [in] - The session handle. + * userp [in] - The user name in the format User or Domain\User. + * passwdp [in] - The user's password. + * ntlm [in/out] - The NTLM data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + struct ntlmdata *ntlm, + char **outptr, size_t *outlen) + +{ + /* NTLM type-3 message structure: + + Index Description Content + 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" + (0x4e544c4d53535000) + 8 NTLM Message Type long (0x03000000) + 12 LM/LMv2 Response security buffer + 20 NTLM/NTLMv2 Response security buffer + 28 Target Name security buffer + 36 User Name security buffer + 44 Workstation Name security buffer + (52) Session Key security buffer (*) + (60) Flags long (*) + (64) OS Version Structure 8 bytes (*) + 52 (64) (72) Start of data block + (*) -> Optional + */ + + CURLcode result = CURLE_OK; + size_t size; + unsigned char ntlmbuf[NTLM_BUFSIZE]; + int lmrespoff; + unsigned char lmresp[24]; /* fixed-size */ +#ifdef USE_NTRESPONSES + int ntrespoff; + unsigned int ntresplen = 24; + unsigned char ntresp[24]; /* fixed-size */ + unsigned char *ptr_ntresp = &ntresp[0]; + unsigned char *ntlmv2resp = NULL; +#endif + bool unicode = (ntlm->flags & NTLMFLAG_NEGOTIATE_UNICODE) ? TRUE : FALSE; + char host[HOSTNAME_MAX + 1] = ""; + const char *user; + const char *domain = ""; + size_t hostoff = 0; + size_t useroff = 0; + size_t domoff = 0; + size_t hostlen = 0; + size_t userlen = 0; + size_t domlen = 0; + + user = strchr(userp, '\\'); + if(!user) + user = strchr(userp, '/'); + + if(user) { + domain = userp; + domlen = (user - domain); + user++; + } + else + user = userp; + + userlen = strlen(user); + + /* Get the machine's un-qualified host name as NTLM doesn't like the fully + qualified domain name */ + if(Curl_gethostname(host, sizeof(host))) { + infof(data, "gethostname() failed, continuing without!\n"); + hostlen = 0; + } + else { + hostlen = strlen(host); + } + +#if defined(USE_NTRESPONSES) && defined(USE_NTLM_V2) + if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) { + unsigned char ntbuffer[0x18]; + unsigned char entropy[8]; + unsigned char ntlmv2hash[0x18]; + + result = Curl_rand(data, entropy, 8); + if(result) + return result; + + result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer); + if(result) + return result; + + result = Curl_ntlm_core_mk_ntlmv2_hash(user, userlen, domain, domlen, + ntbuffer, ntlmv2hash); + if(result) + return result; + + /* LMv2 response */ + result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash, entropy, + &ntlm->nonce[0], lmresp); + if(result) + return result; + + /* NTLMv2 response */ + result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash, entropy, + ntlm, &ntlmv2resp, &ntresplen); + if(result) + return result; + + ptr_ntresp = ntlmv2resp; + } + else +#endif + +#if defined(USE_NTRESPONSES) && defined(USE_NTLM2SESSION) + /* We don't support NTLM2 if we don't have USE_NTRESPONSES */ + if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM_KEY) { + unsigned char ntbuffer[0x18]; + unsigned char tmp[0x18]; + unsigned char md5sum[MD5_DIGEST_LENGTH]; + unsigned char entropy[8]; + + /* Need to create 8 bytes random data */ + result = Curl_rand(data, entropy, 8); + if(result) + return result; + + /* 8 bytes random data as challenge in lmresp */ + memcpy(lmresp, entropy, 8); + + /* Pad with zeros */ + memset(lmresp + 8, 0, 0x10); + + /* Fill tmp with challenge(nonce?) + entropy */ + memcpy(tmp, &ntlm->nonce[0], 8); + memcpy(tmp + 8, entropy, 8); + + result = Curl_ssl_md5sum(tmp, 16, md5sum, MD5_DIGEST_LENGTH); + if(!result) + /* We shall only use the first 8 bytes of md5sum, but the des code in + Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */ + result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer); + if(result) + return result; + + Curl_ntlm_core_lm_resp(ntbuffer, md5sum, ntresp); + + /* End of NTLM2 Session code */ + /* NTLM v2 session security is a misnomer because it is not NTLM v2. + It is NTLM v1 using the extended session security that is also + in NTLM v2 */ + } + else +#endif + { + +#ifdef USE_NTRESPONSES + unsigned char ntbuffer[0x18]; +#endif + unsigned char lmbuffer[0x18]; + +#ifdef USE_NTRESPONSES + result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer); + if(result) + return result; + + Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], ntresp); +#endif + + result = Curl_ntlm_core_mk_lm_hash(data, passwdp, lmbuffer); + if(result) + return result; + + Curl_ntlm_core_lm_resp(lmbuffer, &ntlm->nonce[0], lmresp); + + /* A safer but less compatible alternative is: + * Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp); + * See https://davenport.sourceforge.io/ntlm.html#ntlmVersion2 */ + } + + if(unicode) { + domlen = domlen * 2; + userlen = userlen * 2; + hostlen = hostlen * 2; + } + + lmrespoff = 64; /* size of the message header */ +#ifdef USE_NTRESPONSES + ntrespoff = lmrespoff + 0x18; + domoff = ntrespoff + ntresplen; +#else + domoff = lmrespoff + 0x18; +#endif + useroff = domoff + domlen; + hostoff = useroff + userlen; + + /* Create the big type-3 message binary blob */ + size = msnprintf((char *)ntlmbuf, NTLM_BUFSIZE, + NTLMSSP_SIGNATURE "%c" + "\x03%c%c%c" /* 32-bit type = 3 */ + + "%c%c" /* LanManager length */ + "%c%c" /* LanManager allocated space */ + "%c%c" /* LanManager offset */ + "%c%c" /* 2 zeroes */ + + "%c%c" /* NT-response length */ + "%c%c" /* NT-response allocated space */ + "%c%c" /* NT-response offset */ + "%c%c" /* 2 zeroes */ + + "%c%c" /* domain length */ + "%c%c" /* domain allocated space */ + "%c%c" /* domain name offset */ + "%c%c" /* 2 zeroes */ + + "%c%c" /* user length */ + "%c%c" /* user allocated space */ + "%c%c" /* user offset */ + "%c%c" /* 2 zeroes */ + + "%c%c" /* host length */ + "%c%c" /* host allocated space */ + "%c%c" /* host offset */ + "%c%c" /* 2 zeroes */ + + "%c%c" /* session key length (unknown purpose) */ + "%c%c" /* session key allocated space (unknown purpose) */ + "%c%c" /* session key offset (unknown purpose) */ + "%c%c" /* 2 zeroes */ + + "%c%c%c%c", /* flags */ + + /* domain string */ + /* user string */ + /* host string */ + /* LanManager response */ + /* NT response */ + + 0, /* zero termination */ + 0, 0, 0, /* type-3 long, the 24 upper bits */ + + SHORTPAIR(0x18), /* LanManager response length, twice */ + SHORTPAIR(0x18), + SHORTPAIR(lmrespoff), + 0x0, 0x0, + +#ifdef USE_NTRESPONSES + SHORTPAIR(ntresplen), /* NT-response length, twice */ + SHORTPAIR(ntresplen), + SHORTPAIR(ntrespoff), + 0x0, 0x0, +#else + 0x0, 0x0, + 0x0, 0x0, + 0x0, 0x0, + 0x0, 0x0, +#endif + SHORTPAIR(domlen), + SHORTPAIR(domlen), + SHORTPAIR(domoff), + 0x0, 0x0, + + SHORTPAIR(userlen), + SHORTPAIR(userlen), + SHORTPAIR(useroff), + 0x0, 0x0, + + SHORTPAIR(hostlen), + SHORTPAIR(hostlen), + SHORTPAIR(hostoff), + 0x0, 0x0, + + 0x0, 0x0, + 0x0, 0x0, + 0x0, 0x0, + 0x0, 0x0, + + LONGQUARTET(ntlm->flags)); + + DEBUGASSERT(size == 64); + DEBUGASSERT(size == (size_t)lmrespoff); + + /* We append the binary hashes */ + if(size < (NTLM_BUFSIZE - 0x18)) { + memcpy(&ntlmbuf[size], lmresp, 0x18); + size += 0x18; + } + + DEBUG_OUT({ + fprintf(stderr, "**** TYPE3 header lmresp="); + ntlm_print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18); + }); + +#ifdef USE_NTRESPONSES + /* ntresplen + size should not be risking an integer overflow here */ + if(ntresplen + size > sizeof(ntlmbuf)) { + failf(data, "incoming NTLM message too big"); + return CURLE_OUT_OF_MEMORY; + } + DEBUGASSERT(size == (size_t)ntrespoff); + memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen); + size += ntresplen; + + DEBUG_OUT({ + fprintf(stderr, "\n ntresp="); + ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], ntresplen); + }); + + free(ntlmv2resp);/* Free the dynamic buffer allocated for NTLMv2 */ + +#endif + + DEBUG_OUT({ + fprintf(stderr, "\n flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ", + LONGQUARTET(ntlm->flags), ntlm->flags); + ntlm_print_flags(stderr, ntlm->flags); + fprintf(stderr, "\n****\n"); + }); + + /* Make sure that the domain, user and host strings fit in the + buffer before we copy them there. */ + if(size + userlen + domlen + hostlen >= NTLM_BUFSIZE) { + failf(data, "user + domain + host name too big"); + return CURLE_OUT_OF_MEMORY; + } + + DEBUGASSERT(size == domoff); + if(unicode) + unicodecpy(&ntlmbuf[size], domain, domlen / 2); + else + memcpy(&ntlmbuf[size], domain, domlen); + + size += domlen; + + DEBUGASSERT(size == useroff); + if(unicode) + unicodecpy(&ntlmbuf[size], user, userlen / 2); + else + memcpy(&ntlmbuf[size], user, userlen); + + size += userlen; + + DEBUGASSERT(size == hostoff); + if(unicode) + unicodecpy(&ntlmbuf[size], host, hostlen / 2); + else + memcpy(&ntlmbuf[size], host, hostlen); + + size += hostlen; + + /* Convert domain, user, and host to ASCII but leave the rest as-is */ + result = Curl_convert_to_network(data, (char *)&ntlmbuf[domoff], + size - domoff); + if(result) + return CURLE_CONV_FAILED; + + /* Return with binary blob encoded into base64 */ + result = Curl_base64_encode(data, (char *)ntlmbuf, size, outptr, outlen); + + Curl_auth_cleanup_ntlm(ntlm); + + return result; +} + +/* + * Curl_auth_cleanup_ntlm() + * + * This is used to clean up the NTLM specific data. + * + * Parameters: + * + * ntlm [in/out] - The NTLM data struct being cleaned up. + * + */ +void Curl_auth_cleanup_ntlm(struct ntlmdata *ntlm) +{ + /* Free the target info */ + Curl_safefree(ntlm->target_info); + + /* Reset any variables */ + ntlm->target_info_len = 0; +} + +#endif /* USE_NTLM && !USE_WINDOWS_SSPI */ diff --git a/dependencies/cmcurl/lib/vauth/ntlm.h b/dependencies/cmcurl/lib/vauth/ntlm.h new file mode 100644 index 0000000..1136b0f --- /dev/null +++ b/dependencies/cmcurl/lib/vauth/ntlm.h @@ -0,0 +1,143 @@ +#ifndef HEADER_VAUTH_NTLM_H +#define HEADER_VAUTH_NTLM_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_NTLM + +/* NTLM buffer fixed size, large enough for long user + host + domain */ +#define NTLM_BUFSIZE 1024 + +/* Stuff only required for curl_ntlm_msgs.c */ +#ifdef BUILDING_CURL_NTLM_MSGS_C + +/* Flag bits definitions based on https://davenport.sourceforge.io/ntlm.html */ + +#define NTLMFLAG_NEGOTIATE_UNICODE (1<<0) +/* Indicates that Unicode strings are supported for use in security buffer + data. */ + +#define NTLMFLAG_NEGOTIATE_OEM (1<<1) +/* Indicates that OEM strings are supported for use in security buffer data. */ + +#define NTLMFLAG_REQUEST_TARGET (1<<2) +/* Requests that the server's authentication realm be included in the Type 2 + message. */ + +/* unknown (1<<3) */ +#define NTLMFLAG_NEGOTIATE_SIGN (1<<4) +/* Specifies that authenticated communication between the client and server + should carry a digital signature (message integrity). */ + +#define NTLMFLAG_NEGOTIATE_SEAL (1<<5) +/* Specifies that authenticated communication between the client and server + should be encrypted (message confidentiality). */ + +#define NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE (1<<6) +/* Indicates that datagram authentication is being used. */ + +#define NTLMFLAG_NEGOTIATE_LM_KEY (1<<7) +/* Indicates that the LAN Manager session key should be used for signing and + sealing authenticated communications. */ + +#define NTLMFLAG_NEGOTIATE_NETWARE (1<<8) +/* unknown purpose */ + +#define NTLMFLAG_NEGOTIATE_NTLM_KEY (1<<9) +/* Indicates that NTLM authentication is being used. */ + +/* unknown (1<<10) */ + +#define NTLMFLAG_NEGOTIATE_ANONYMOUS (1<<11) +/* Sent by the client in the Type 3 message to indicate that an anonymous + context has been established. This also affects the response fields. */ + +#define NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED (1<<12) +/* Sent by the client in the Type 1 message to indicate that a desired + authentication realm is included in the message. */ + +#define NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED (1<<13) +/* Sent by the client in the Type 1 message to indicate that the client + workstation's name is included in the message. */ + +#define NTLMFLAG_NEGOTIATE_LOCAL_CALL (1<<14) +/* Sent by the server to indicate that the server and client are on the same + machine. Implies that the client may use a pre-established local security + context rather than responding to the challenge. */ + +#define NTLMFLAG_NEGOTIATE_ALWAYS_SIGN (1<<15) +/* Indicates that authenticated communication between the client and server + should be signed with a "dummy" signature. */ + +#define NTLMFLAG_TARGET_TYPE_DOMAIN (1<<16) +/* Sent by the server in the Type 2 message to indicate that the target + authentication realm is a domain. */ + +#define NTLMFLAG_TARGET_TYPE_SERVER (1<<17) +/* Sent by the server in the Type 2 message to indicate that the target + authentication realm is a server. */ + +#define NTLMFLAG_TARGET_TYPE_SHARE (1<<18) +/* Sent by the server in the Type 2 message to indicate that the target + authentication realm is a share. Presumably, this is for share-level + authentication. Usage is unclear. */ + +#define NTLMFLAG_NEGOTIATE_NTLM2_KEY (1<<19) +/* Indicates that the NTLM2 signing and sealing scheme should be used for + protecting authenticated communications. */ + +#define NTLMFLAG_REQUEST_INIT_RESPONSE (1<<20) +/* unknown purpose */ + +#define NTLMFLAG_REQUEST_ACCEPT_RESPONSE (1<<21) +/* unknown purpose */ + +#define NTLMFLAG_REQUEST_NONNT_SESSION_KEY (1<<22) +/* unknown purpose */ + +#define NTLMFLAG_NEGOTIATE_TARGET_INFO (1<<23) +/* Sent by the server in the Type 2 message to indicate that it is including a + Target Information block in the message. */ + +/* unknown (1<24) */ +/* unknown (1<25) */ +/* unknown (1<26) */ +/* unknown (1<27) */ +/* unknown (1<28) */ + +#define NTLMFLAG_NEGOTIATE_128 (1<<29) +/* Indicates that 128-bit encryption is supported. */ + +#define NTLMFLAG_NEGOTIATE_KEY_EXCHANGE (1<<30) +/* Indicates that the client will provide an encrypted master key in + the "Session Key" field of the Type 3 message. */ + +#define NTLMFLAG_NEGOTIATE_56 (1<<31) +/* Indicates that 56-bit encryption is supported. */ + +#endif /* BUILDING_CURL_NTLM_MSGS_C */ + +#endif /* USE_NTLM */ + +#endif /* HEADER_VAUTH_NTLM_H */ diff --git a/dependencies/cmcurl/lib/vauth/ntlm_sspi.c b/dependencies/cmcurl/lib/vauth/ntlm_sspi.c new file mode 100644 index 0000000..589cca1 --- /dev/null +++ b/dependencies/cmcurl/lib/vauth/ntlm_sspi.c @@ -0,0 +1,371 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_WINDOWS_SSPI) && defined(USE_NTLM) + +#include + +#include "vauth/vauth.h" +#include "urldata.h" +#include "curl_base64.h" +#include "curl_ntlm_core.h" +#include "warnless.h" +#include "curl_multibyte.h" +#include "sendf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Curl_auth_is_ntlm_supported() + * + * This is used to evaluate if NTLM is supported. + * + * Parameters: None + * + * Returns TRUE if NTLM is supported by Windows SSPI. + */ +bool Curl_auth_is_ntlm_supported(void) +{ + PSecPkgInfo SecurityPackage; + SECURITY_STATUS status; + + /* Query the security package for NTLM */ + status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_NTLM), + &SecurityPackage); + + return (status == SEC_E_OK ? TRUE : FALSE); +} + +/* + * Curl_auth_create_ntlm_type1_message() + * + * This is used to generate an already encoded NTLM type-1 message ready for + * sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * userp [in] - The user name in the format User or Domain\User. + * passwdp [in] - The user's password. + * service [in] - The service type such as http, smtp, pop or imap. + * host [in] - The host name. + * ntlm [in/out] - The NTLM data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + const char *service, + const char *host, + struct ntlmdata *ntlm, + char **outptr, size_t *outlen) +{ + PSecPkgInfo SecurityPackage; + SecBuffer type_1_buf; + SecBufferDesc type_1_desc; + SECURITY_STATUS status; + unsigned long attrs; + TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */ + + /* Clean up any former leftovers and initialise to defaults */ + Curl_auth_cleanup_ntlm(ntlm); + + /* Query the security package for NTLM */ + status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_NTLM), + &SecurityPackage); + if(status != SEC_E_OK) + return CURLE_NOT_BUILT_IN; + + ntlm->token_max = SecurityPackage->cbMaxToken; + + /* Release the package buffer as it is not required anymore */ + s_pSecFn->FreeContextBuffer(SecurityPackage); + + /* Allocate our output buffer */ + ntlm->output_token = malloc(ntlm->token_max); + if(!ntlm->output_token) + return CURLE_OUT_OF_MEMORY; + + if(userp && *userp) { + CURLcode result; + + /* Populate our identity structure */ + result = Curl_create_sspi_identity(userp, passwdp, &ntlm->identity); + if(result) + return result; + + /* Allow proper cleanup of the identity structure */ + ntlm->p_identity = &ntlm->identity; + } + else + /* Use the current Windows user */ + ntlm->p_identity = NULL; + + /* Allocate our credentials handle */ + ntlm->credentials = calloc(1, sizeof(CredHandle)); + if(!ntlm->credentials) + return CURLE_OUT_OF_MEMORY; + + /* Acquire our credentials handle */ + status = s_pSecFn->AcquireCredentialsHandle(NULL, + (TCHAR *) TEXT(SP_NAME_NTLM), + SECPKG_CRED_OUTBOUND, NULL, + ntlm->p_identity, NULL, NULL, + ntlm->credentials, &expiry); + if(status != SEC_E_OK) + return CURLE_LOGIN_DENIED; + + /* Allocate our new context handle */ + ntlm->context = calloc(1, sizeof(CtxtHandle)); + if(!ntlm->context) + return CURLE_OUT_OF_MEMORY; + + ntlm->spn = Curl_auth_build_spn(service, host, NULL); + if(!ntlm->spn) + return CURLE_OUT_OF_MEMORY; + + /* Setup the type-1 "output" security buffer */ + type_1_desc.ulVersion = SECBUFFER_VERSION; + type_1_desc.cBuffers = 1; + type_1_desc.pBuffers = &type_1_buf; + type_1_buf.BufferType = SECBUFFER_TOKEN; + type_1_buf.pvBuffer = ntlm->output_token; + type_1_buf.cbBuffer = curlx_uztoul(ntlm->token_max); + + /* Generate our type-1 message */ + status = s_pSecFn->InitializeSecurityContext(ntlm->credentials, NULL, + ntlm->spn, + 0, 0, SECURITY_NETWORK_DREP, + NULL, 0, + ntlm->context, &type_1_desc, + &attrs, &expiry); + if(status == SEC_I_COMPLETE_NEEDED || + status == SEC_I_COMPLETE_AND_CONTINUE) + s_pSecFn->CompleteAuthToken(ntlm->context, &type_1_desc); + else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) + return CURLE_RECV_ERROR; + + /* Base64 encode the response */ + return Curl_base64_encode(data, (char *) ntlm->output_token, + type_1_buf.cbBuffer, outptr, outlen); +} + +/* + * Curl_auth_decode_ntlm_type2_message() + * + * This is used to decode an already encoded NTLM type-2 message. + * + * Parameters: + * + * data [in] - The session handle. + * type2msg [in] - The base64 encoded type-2 message. + * ntlm [in/out] - The NTLM data struct being used and modified. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, + const char *type2msg, + struct ntlmdata *ntlm) +{ + CURLcode result = CURLE_OK; + unsigned char *type2 = NULL; + size_t type2_len = 0; + +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) data; +#endif + + /* Decode the base-64 encoded type-2 message */ + if(strlen(type2msg) && *type2msg != '=') { + result = Curl_base64_decode(type2msg, &type2, &type2_len); + if(result) + return result; + } + + /* Ensure we have a valid type-2 message */ + if(!type2) { + infof(data, "NTLM handshake failure (empty type-2 message)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Simply store the challenge for use later */ + ntlm->input_token = type2; + ntlm->input_token_len = type2_len; + + return result; +} + +/* +* Curl_auth_create_ntlm_type3_message() + * Curl_auth_create_ntlm_type3_message() + * + * This is used to generate an already encoded NTLM type-3 message ready for + * sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * userp [in] - The user name in the format User or Domain\User. + * passwdp [in] - The user's password. + * ntlm [in/out] - The NTLM data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + struct ntlmdata *ntlm, + char **outptr, size_t *outlen) +{ + CURLcode result = CURLE_OK; + SecBuffer type_2_bufs[2]; + SecBuffer type_3_buf; + SecBufferDesc type_2_desc; + SecBufferDesc type_3_desc; + SECURITY_STATUS status; + unsigned long attrs; + TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */ + + (void) passwdp; + (void) userp; + + /* Setup the type-2 "input" security buffer */ + type_2_desc.ulVersion = SECBUFFER_VERSION; + type_2_desc.cBuffers = 1; + type_2_desc.pBuffers = &type_2_bufs[0]; + type_2_bufs[0].BufferType = SECBUFFER_TOKEN; + type_2_bufs[0].pvBuffer = ntlm->input_token; + type_2_bufs[0].cbBuffer = curlx_uztoul(ntlm->input_token_len); + +#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS + /* ssl context comes from schannel. + * When extended protection is used in IIS server, + * we have to pass a second SecBuffer to the SecBufferDesc + * otherwise IIS will not pass the authentication (401 response). + * Minimum supported version is Windows 7. + * https://docs.microsoft.com/en-us/security-updates + * /SecurityAdvisories/2009/973811 + */ + if(ntlm->sslContext) { + SEC_CHANNEL_BINDINGS channelBindings; + SecPkgContext_Bindings pkgBindings; + pkgBindings.Bindings = &channelBindings; + status = s_pSecFn->QueryContextAttributes( + ntlm->sslContext, + SECPKG_ATTR_ENDPOINT_BINDINGS, + &pkgBindings + ); + if(status == SEC_E_OK) { + type_2_desc.cBuffers++; + type_2_bufs[1].BufferType = SECBUFFER_CHANNEL_BINDINGS; + type_2_bufs[1].cbBuffer = pkgBindings.BindingsLength; + type_2_bufs[1].pvBuffer = pkgBindings.Bindings; + } + } +#endif + + /* Setup the type-3 "output" security buffer */ + type_3_desc.ulVersion = SECBUFFER_VERSION; + type_3_desc.cBuffers = 1; + type_3_desc.pBuffers = &type_3_buf; + type_3_buf.BufferType = SECBUFFER_TOKEN; + type_3_buf.pvBuffer = ntlm->output_token; + type_3_buf.cbBuffer = curlx_uztoul(ntlm->token_max); + + /* Generate our type-3 message */ + status = s_pSecFn->InitializeSecurityContext(ntlm->credentials, + ntlm->context, + ntlm->spn, + 0, 0, SECURITY_NETWORK_DREP, + &type_2_desc, + 0, ntlm->context, + &type_3_desc, + &attrs, &expiry); + if(status != SEC_E_OK) { + infof(data, "NTLM handshake failure (type-3 message): Status=%x\n", + status); + + return CURLE_RECV_ERROR; + } + + /* Base64 encode the response */ + result = Curl_base64_encode(data, (char *) ntlm->output_token, + type_3_buf.cbBuffer, outptr, outlen); + + Curl_auth_cleanup_ntlm(ntlm); + + return result; +} + +/* + * Curl_auth_cleanup_ntlm() + * + * This is used to clean up the NTLM specific data. + * + * Parameters: + * + * ntlm [in/out] - The NTLM data struct being cleaned up. + * + */ +void Curl_auth_cleanup_ntlm(struct ntlmdata *ntlm) +{ + /* Free our security context */ + if(ntlm->context) { + s_pSecFn->DeleteSecurityContext(ntlm->context); + free(ntlm->context); + ntlm->context = NULL; + } + + /* Free our credentials handle */ + if(ntlm->credentials) { + s_pSecFn->FreeCredentialsHandle(ntlm->credentials); + free(ntlm->credentials); + ntlm->credentials = NULL; + } + + /* Free our identity */ + Curl_sspi_free_identity(ntlm->p_identity); + ntlm->p_identity = NULL; + + /* Free the input and output tokens */ + Curl_safefree(ntlm->input_token); + Curl_safefree(ntlm->output_token); + + /* Reset any variables */ + ntlm->token_max = 0; + + Curl_safefree(ntlm->spn); +} + +#endif /* USE_WINDOWS_SSPI && USE_NTLM */ diff --git a/dependencies/cmcurl/lib/vauth/oauth2.c b/dependencies/cmcurl/lib/vauth/oauth2.c new file mode 100644 index 0000000..b4e9f8e --- /dev/null +++ b/dependencies/cmcurl/lib/vauth/oauth2.c @@ -0,0 +1,126 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC6749 OAuth 2.0 Authorization Framework + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_SMTP) || \ + !defined(CURL_DISABLE_POP3) + +#include +#include "urldata.h" + +#include "vauth/vauth.h" +#include "curl_base64.h" +#include "warnless.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Curl_auth_create_oauth_bearer_message() + * + * This is used to generate an already encoded OAuth 2.0 message ready for + * sending to the recipient. + * + * Parameters: + * + * data[in] - The session handle. + * user[in] - The user name. + * host[in] - The host name. + * port[in] - The port(when not Port 80). + * bearer[in] - The bearer token. + * outptr[in / out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen[out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_oauth_bearer_message(struct Curl_easy *data, + const char *user, + const char *host, + const long port, + const char *bearer, + char **outptr, size_t *outlen) +{ + CURLcode result = CURLE_OK; + char *oauth = NULL; + + /* Generate the message */ + if(port == 0 || port == 80) + oauth = aprintf("n,a=%s,\1host=%s\1auth=Bearer %s\1\1", user, host, + bearer); + else + oauth = aprintf("n,a=%s,\1host=%s\1port=%ld\1auth=Bearer %s\1\1", user, + host, port, bearer); + if(!oauth) + return CURLE_OUT_OF_MEMORY; + + /* Base64 encode the reply */ + result = Curl_base64_encode(data, oauth, strlen(oauth), outptr, outlen); + + free(oauth); + + return result; +} + +/* + * Curl_auth_create_xoauth_bearer_message() + * + * This is used to generate an already encoded XOAuth 2.0 message ready for + * sending to the recipient. + * + * Parameters: + * + * data[in] - The session handle. + * user[in] - The user name. + * bearer[in] - The bearer token. + * outptr[in / out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen[out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_xoauth_bearer_message(struct Curl_easy *data, + const char *user, + const char *bearer, + char **outptr, size_t *outlen) +{ + CURLcode result = CURLE_OK; + + /* Generate the message */ + char *xoauth = aprintf("user=%s\1auth=Bearer %s\1\1", user, bearer); + if(!xoauth) + return CURLE_OUT_OF_MEMORY; + + /* Base64 encode the reply */ + result = Curl_base64_encode(data, xoauth, strlen(xoauth), outptr, outlen); + + free(xoauth); + + return result; +} +#endif /* disabled, no users */ + diff --git a/dependencies/cmcurl/lib/vauth/spnego_gssapi.c b/dependencies/cmcurl/lib/vauth/spnego_gssapi.c new file mode 100644 index 0000000..5d43e11 --- /dev/null +++ b/dependencies/cmcurl/lib/vauth/spnego_gssapi.c @@ -0,0 +1,282 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC4178 Simple and Protected GSS-API Negotiation Mechanism + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(HAVE_GSSAPI) && defined(USE_SPNEGO) + +#include + +#include "vauth/vauth.h" +#include "urldata.h" +#include "curl_base64.h" +#include "curl_gssapi.h" +#include "warnless.h" +#include "curl_multibyte.h" +#include "sendf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Curl_auth_is_spnego_supported() + * + * This is used to evaluate if SPNEGO (Negotiate) is supported. + * + * Parameters: None + * + * Returns TRUE if Negotiate supported by the GSS-API library. + */ +bool Curl_auth_is_spnego_supported(void) +{ + return TRUE; +} + +/* + * Curl_auth_decode_spnego_message() + * + * This is used to decode an already encoded SPNEGO (Negotiate) challenge + * message. + * + * Parameters: + * + * data [in] - The session handle. + * userp [in] - The user name in the format User or Domain\User. + * passwdp [in] - The user's password. + * service [in] - The service type such as http, smtp, pop or imap. + * host [in] - The host name. + * chlg64 [in] - The optional base64 encoded challenge message. + * nego [in/out] - The Negotiate data struct being used and modified. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data, + const char *user, + const char *password, + const char *service, + const char *host, + const char *chlg64, + struct negotiatedata *nego) +{ + CURLcode result = CURLE_OK; + size_t chlglen = 0; + unsigned char *chlg = NULL; + OM_uint32 major_status; + OM_uint32 minor_status; + OM_uint32 unused_status; + gss_buffer_desc spn_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + + (void) user; + (void) password; + + if(nego->context && nego->status == GSS_S_COMPLETE) { + /* We finished successfully our part of authentication, but server + * rejected it (since we're again here). Exit with an error since we + * can't invent anything better */ + Curl_auth_cleanup_spnego(nego); + return CURLE_LOGIN_DENIED; + } + + if(!nego->spn) { + /* Generate our SPN */ + char *spn = Curl_auth_build_spn(service, NULL, host); + if(!spn) + return CURLE_OUT_OF_MEMORY; + + /* Populate the SPN structure */ + spn_token.value = spn; + spn_token.length = strlen(spn); + + /* Import the SPN */ + major_status = gss_import_name(&minor_status, &spn_token, + GSS_C_NT_HOSTBASED_SERVICE, + &nego->spn); + if(GSS_ERROR(major_status)) { + Curl_gss_log_error(data, "gss_import_name() failed: ", + major_status, minor_status); + + free(spn); + + return CURLE_OUT_OF_MEMORY; + } + + free(spn); + } + + if(chlg64 && *chlg64) { + /* Decode the base-64 encoded challenge message */ + if(*chlg64 != '=') { + result = Curl_base64_decode(chlg64, &chlg, &chlglen); + if(result) + return result; + } + + /* Ensure we have a valid challenge message */ + if(!chlg) { + infof(data, "SPNEGO handshake failure (empty challenge message)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Setup the challenge "input" security buffer */ + input_token.value = chlg; + input_token.length = chlglen; + } + + /* Generate our challenge-response message */ + major_status = Curl_gss_init_sec_context(data, + &minor_status, + &nego->context, + nego->spn, + &Curl_spnego_mech_oid, + GSS_C_NO_CHANNEL_BINDINGS, + &input_token, + &output_token, + TRUE, + NULL); + + /* Free the decoded challenge as it is not required anymore */ + Curl_safefree(input_token.value); + + nego->status = major_status; + if(GSS_ERROR(major_status)) { + if(output_token.value) + gss_release_buffer(&unused_status, &output_token); + + Curl_gss_log_error(data, "gss_init_sec_context() failed: ", + major_status, minor_status); + + return CURLE_LOGIN_DENIED; + } + + if(!output_token.value || !output_token.length) { + if(output_token.value) + gss_release_buffer(&unused_status, &output_token); + + return CURLE_OUT_OF_MEMORY; + } + + /* Free previous token */ + if(nego->output_token.length && nego->output_token.value) + gss_release_buffer(&unused_status, &nego->output_token); + + nego->output_token = output_token; + + return CURLE_OK; +} + +/* + * Curl_auth_create_spnego_message() + * + * This is used to generate an already encoded SPNEGO (Negotiate) response + * message ready for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * nego [in/out] - The Negotiate data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_spnego_message(struct Curl_easy *data, + struct negotiatedata *nego, + char **outptr, size_t *outlen) +{ + CURLcode result; + OM_uint32 minor_status; + + /* Base64 encode the already generated response */ + result = Curl_base64_encode(data, + nego->output_token.value, + nego->output_token.length, + outptr, outlen); + + if(result) { + gss_release_buffer(&minor_status, &nego->output_token); + nego->output_token.value = NULL; + nego->output_token.length = 0; + + return result; + } + + if(!*outptr || !*outlen) { + gss_release_buffer(&minor_status, &nego->output_token); + nego->output_token.value = NULL; + nego->output_token.length = 0; + + return CURLE_REMOTE_ACCESS_DENIED; + } + + return CURLE_OK; +} + +/* + * Curl_auth_cleanup_spnego() + * + * This is used to clean up the SPNEGO (Negotiate) specific data. + * + * Parameters: + * + * nego [in/out] - The Negotiate data struct being cleaned up. + * + */ +void Curl_auth_cleanup_spnego(struct negotiatedata *nego) +{ + OM_uint32 minor_status; + + /* Free our security context */ + if(nego->context != GSS_C_NO_CONTEXT) { + gss_delete_sec_context(&minor_status, &nego->context, GSS_C_NO_BUFFER); + nego->context = GSS_C_NO_CONTEXT; + } + + /* Free the output token */ + if(nego->output_token.value) { + gss_release_buffer(&minor_status, &nego->output_token); + nego->output_token.value = NULL; + nego->output_token.length = 0; + + } + + /* Free the SPN */ + if(nego->spn != GSS_C_NO_NAME) { + gss_release_name(&minor_status, &nego->spn); + nego->spn = GSS_C_NO_NAME; + } + + /* Reset any variables */ + nego->status = 0; + nego->noauthpersist = FALSE; + nego->havenoauthpersist = FALSE; + nego->havenegdata = FALSE; + nego->havemultiplerequests = FALSE; +} + +#endif /* HAVE_GSSAPI && USE_SPNEGO */ diff --git a/dependencies/cmcurl/lib/vauth/spnego_sspi.c b/dependencies/cmcurl/lib/vauth/spnego_sspi.c new file mode 100644 index 0000000..4b21cc7 --- /dev/null +++ b/dependencies/cmcurl/lib/vauth/spnego_sspi.c @@ -0,0 +1,352 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC4178 Simple and Protected GSS-API Negotiation Mechanism + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_WINDOWS_SSPI) && defined(USE_SPNEGO) + +#include + +#include "vauth/vauth.h" +#include "urldata.h" +#include "curl_base64.h" +#include "warnless.h" +#include "curl_multibyte.h" +#include "sendf.h" +#include "strerror.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Curl_auth_is_spnego_supported() + * + * This is used to evaluate if SPNEGO (Negotiate) is supported. + * + * Parameters: None + * + * Returns TRUE if Negotiate is supported by Windows SSPI. + */ +bool Curl_auth_is_spnego_supported(void) +{ + PSecPkgInfo SecurityPackage; + SECURITY_STATUS status; + + /* Query the security package for Negotiate */ + status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) + TEXT(SP_NAME_NEGOTIATE), + &SecurityPackage); + + return (status == SEC_E_OK ? TRUE : FALSE); +} + +/* + * Curl_auth_decode_spnego_message() + * + * This is used to decode an already encoded SPNEGO (Negotiate) challenge + * message. + * + * Parameters: + * + * data [in] - The session handle. + * user [in] - The user name in the format User or Domain\User. + * password [in] - The user's password. + * service [in] - The service type such as http, smtp, pop or imap. + * host [in] - The host name. + * chlg64 [in] - The optional base64 encoded challenge message. + * nego [in/out] - The Negotiate data struct being used and modified. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data, + const char *user, + const char *password, + const char *service, + const char *host, + const char *chlg64, + struct negotiatedata *nego) +{ + CURLcode result = CURLE_OK; + size_t chlglen = 0; + unsigned char *chlg = NULL; + PSecPkgInfo SecurityPackage; + SecBuffer chlg_buf[2]; + SecBuffer resp_buf; + SecBufferDesc chlg_desc; + SecBufferDesc resp_desc; + unsigned long attrs; + TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */ + +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) data; +#endif + + if(nego->context && nego->status == SEC_E_OK) { + /* We finished successfully our part of authentication, but server + * rejected it (since we're again here). Exit with an error since we + * can't invent anything better */ + Curl_auth_cleanup_spnego(nego); + return CURLE_LOGIN_DENIED; + } + + if(!nego->spn) { + /* Generate our SPN */ + nego->spn = Curl_auth_build_spn(service, host, NULL); + if(!nego->spn) + return CURLE_OUT_OF_MEMORY; + } + + if(!nego->output_token) { + /* Query the security package for Negotiate */ + nego->status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) + TEXT(SP_NAME_NEGOTIATE), + &SecurityPackage); + if(nego->status != SEC_E_OK) + return CURLE_NOT_BUILT_IN; + + nego->token_max = SecurityPackage->cbMaxToken; + + /* Release the package buffer as it is not required anymore */ + s_pSecFn->FreeContextBuffer(SecurityPackage); + + /* Allocate our output buffer */ + nego->output_token = malloc(nego->token_max); + if(!nego->output_token) + return CURLE_OUT_OF_MEMORY; + } + + if(!nego->credentials) { + /* Do we have credentials to use or are we using single sign-on? */ + if(user && *user) { + /* Populate our identity structure */ + result = Curl_create_sspi_identity(user, password, &nego->identity); + if(result) + return result; + + /* Allow proper cleanup of the identity structure */ + nego->p_identity = &nego->identity; + } + else + /* Use the current Windows user */ + nego->p_identity = NULL; + + /* Allocate our credentials handle */ + nego->credentials = calloc(1, sizeof(CredHandle)); + if(!nego->credentials) + return CURLE_OUT_OF_MEMORY; + + /* Acquire our credentials handle */ + nego->status = + s_pSecFn->AcquireCredentialsHandle(NULL, + (TCHAR *)TEXT(SP_NAME_NEGOTIATE), + SECPKG_CRED_OUTBOUND, NULL, + nego->p_identity, NULL, NULL, + nego->credentials, &expiry); + if(nego->status != SEC_E_OK) + return CURLE_LOGIN_DENIED; + + /* Allocate our new context handle */ + nego->context = calloc(1, sizeof(CtxtHandle)); + if(!nego->context) + return CURLE_OUT_OF_MEMORY; + } + + if(chlg64 && *chlg64) { + /* Decode the base-64 encoded challenge message */ + if(*chlg64 != '=') { + result = Curl_base64_decode(chlg64, &chlg, &chlglen); + if(result) + return result; + } + + /* Ensure we have a valid challenge message */ + if(!chlg) { + infof(data, "SPNEGO handshake failure (empty challenge message)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Setup the challenge "input" security buffer */ + chlg_desc.ulVersion = SECBUFFER_VERSION; + chlg_desc.cBuffers = 1; + chlg_desc.pBuffers = &chlg_buf[0]; + chlg_buf[0].BufferType = SECBUFFER_TOKEN; + chlg_buf[0].pvBuffer = chlg; + chlg_buf[0].cbBuffer = curlx_uztoul(chlglen); + +#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS + /* ssl context comes from Schannel. + * When extended protection is used in IIS server, + * we have to pass a second SecBuffer to the SecBufferDesc + * otherwise IIS will not pass the authentication (401 response). + * Minimum supported version is Windows 7. + * https://docs.microsoft.com/en-us/security-updates + * /SecurityAdvisories/2009/973811 + */ + if(nego->sslContext) { + SEC_CHANNEL_BINDINGS channelBindings; + SecPkgContext_Bindings pkgBindings; + pkgBindings.Bindings = &channelBindings; + nego->status = s_pSecFn->QueryContextAttributes( + nego->sslContext, + SECPKG_ATTR_ENDPOINT_BINDINGS, + &pkgBindings + ); + if(nego->status == SEC_E_OK) { + chlg_desc.cBuffers++; + chlg_buf[1].BufferType = SECBUFFER_CHANNEL_BINDINGS; + chlg_buf[1].cbBuffer = pkgBindings.BindingsLength; + chlg_buf[1].pvBuffer = pkgBindings.Bindings; + } + } +#endif + } + + /* Setup the response "output" security buffer */ + resp_desc.ulVersion = SECBUFFER_VERSION; + resp_desc.cBuffers = 1; + resp_desc.pBuffers = &resp_buf; + resp_buf.BufferType = SECBUFFER_TOKEN; + resp_buf.pvBuffer = nego->output_token; + resp_buf.cbBuffer = curlx_uztoul(nego->token_max); + + /* Generate our challenge-response message */ + nego->status = s_pSecFn->InitializeSecurityContext(nego->credentials, + chlg ? nego->context : + NULL, + nego->spn, + ISC_REQ_CONFIDENTIALITY, + 0, SECURITY_NATIVE_DREP, + chlg ? &chlg_desc : NULL, + 0, nego->context, + &resp_desc, &attrs, + &expiry); + + /* Free the decoded challenge as it is not required anymore */ + free(chlg); + + if(GSS_ERROR(nego->status)) { + char buffer[STRERROR_LEN]; + failf(data, "InitializeSecurityContext failed: %s", + Curl_sspi_strerror(nego->status, buffer, sizeof(buffer))); + return CURLE_OUT_OF_MEMORY; + } + + if(nego->status == SEC_I_COMPLETE_NEEDED || + nego->status == SEC_I_COMPLETE_AND_CONTINUE) { + nego->status = s_pSecFn->CompleteAuthToken(nego->context, &resp_desc); + if(GSS_ERROR(nego->status)) { + return CURLE_RECV_ERROR; + } + } + + nego->output_token_length = resp_buf.cbBuffer; + + return result; +} + +/* + * Curl_auth_create_spnego_message() + * + * This is used to generate an already encoded SPNEGO (Negotiate) response + * message ready for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * nego [in/out] - The Negotiate data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_spnego_message(struct Curl_easy *data, + struct negotiatedata *nego, + char **outptr, size_t *outlen) +{ + CURLcode result; + + /* Base64 encode the already generated response */ + result = Curl_base64_encode(data, + (const char *) nego->output_token, + nego->output_token_length, + outptr, outlen); + + if(result) + return result; + + if(!*outptr || !*outlen) { + free(*outptr); + return CURLE_REMOTE_ACCESS_DENIED; + } + + return CURLE_OK; +} + +/* + * Curl_auth_cleanup_spnego() + * + * This is used to clean up the SPNEGO (Negotiate) specific data. + * + * Parameters: + * + * nego [in/out] - The Negotiate data struct being cleaned up. + * + */ +void Curl_auth_cleanup_spnego(struct negotiatedata *nego) +{ + /* Free our security context */ + if(nego->context) { + s_pSecFn->DeleteSecurityContext(nego->context); + free(nego->context); + nego->context = NULL; + } + + /* Free our credentials handle */ + if(nego->credentials) { + s_pSecFn->FreeCredentialsHandle(nego->credentials); + free(nego->credentials); + nego->credentials = NULL; + } + + /* Free our identity */ + Curl_sspi_free_identity(nego->p_identity); + nego->p_identity = NULL; + + /* Free the SPN and output token */ + Curl_safefree(nego->spn); + Curl_safefree(nego->output_token); + + /* Reset any variables */ + nego->status = 0; + nego->token_max = 0; + nego->noauthpersist = FALSE; + nego->havenoauthpersist = FALSE; + nego->havenegdata = FALSE; + nego->havemultiplerequests = FALSE; +} + +#endif /* USE_WINDOWS_SSPI && USE_SPNEGO */ diff --git a/dependencies/cmcurl/lib/vauth/vauth.c b/dependencies/cmcurl/lib/vauth/vauth.c new file mode 100644 index 0000000..a9c5c9c --- /dev/null +++ b/dependencies/cmcurl/lib/vauth/vauth.c @@ -0,0 +1,147 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2014 - 2019, Steve Holme, . + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "vauth.h" +#include "curl_multibyte.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Curl_auth_build_spn() + * + * This is used to build a SPN string in the following formats: + * + * service/host@realm (Not currently used) + * service/host (Not used by GSS-API) + * service@realm (Not used by Windows SSPI) + * + * Parameters: + * + * service [in] - The service type such as http, smtp, pop or imap. + * host [in] - The host name. + * realm [in] - The realm. + * + * Returns a pointer to the newly allocated SPN. + */ +#if !defined(USE_WINDOWS_SSPI) +char *Curl_auth_build_spn(const char *service, const char *host, + const char *realm) +{ + char *spn = NULL; + + /* Generate our SPN */ + if(host && realm) + spn = aprintf("%s/%s@%s", service, host, realm); + else if(host) + spn = aprintf("%s/%s", service, host); + else if(realm) + spn = aprintf("%s@%s", service, realm); + + /* Return our newly allocated SPN */ + return spn; +} +#else +TCHAR *Curl_auth_build_spn(const char *service, const char *host, + const char *realm) +{ + char *utf8_spn = NULL; + TCHAR *tchar_spn = NULL; + + (void) realm; + + /* Note: We could use DsMakeSPN() or DsClientMakeSpnForTargetServer() rather + than doing this ourselves but the first is only available in Windows XP + and Windows Server 2003 and the latter is only available in Windows 2000 + but not Windows95/98/ME or Windows NT4.0 unless the Active Directory + Client Extensions are installed. As such it is far simpler for us to + formulate the SPN instead. */ + + /* Generate our UTF8 based SPN */ + utf8_spn = aprintf("%s/%s", service, host); + if(!utf8_spn) { + return NULL; + } + + /* Allocate our TCHAR based SPN */ + tchar_spn = Curl_convert_UTF8_to_tchar(utf8_spn); + if(!tchar_spn) { + free(utf8_spn); + + return NULL; + } + + /* Release the UTF8 variant when operating with Unicode */ + Curl_unicodefree(utf8_spn); + + /* Return our newly allocated SPN */ + return tchar_spn; +} +#endif /* USE_WINDOWS_SSPI */ + +/* + * Curl_auth_user_contains_domain() + * + * This is used to test if the specified user contains a Windows domain name as + * follows: + * + * Domain\User (Down-level Logon Name) + * Domain/User (curl Down-level format - for compatibility with existing code) + * User@Domain (User Principal Name) + * + * Note: The user name may be empty when using a GSS-API library or Windows + * SSPI as the user and domain are either obtained from the credentials cache + * when using GSS-API or via the currently logged in user's credentials when + * using Windows SSPI. + * + * Parameters: + * + * user [in] - The user name. + * + * Returns TRUE on success; otherwise FALSE. + */ +bool Curl_auth_user_contains_domain(const char *user) +{ + bool valid = FALSE; + + if(user && *user) { + /* Check we have a domain name or UPN present */ + char *p = strpbrk(user, "\\/@"); + + valid = (p != NULL && p > user && p < user + strlen(user) - 1 ? TRUE : + FALSE); + } +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + else + /* User and domain are obtained from the GSS-API credentials cache or the + currently logged in user from Windows */ + valid = TRUE; +#endif + + return valid; +} diff --git a/dependencies/cmcurl/lib/vauth/vauth.h b/dependencies/cmcurl/lib/vauth/vauth.h new file mode 100644 index 0000000..73bd25e --- /dev/null +++ b/dependencies/cmcurl/lib/vauth/vauth.h @@ -0,0 +1,215 @@ +#ifndef HEADER_CURL_VAUTH_H +#define HEADER_CURL_VAUTH_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2014 - 2019, Steve Holme, . + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +struct Curl_easy; + +#if !defined(CURL_DISABLE_CRYPTO_AUTH) +struct digestdata; +#endif + +#if defined(USE_NTLM) +struct ntlmdata; +#endif + +#if defined(USE_KERBEROS5) +struct kerberos5data; +#endif + +#if (defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)) && defined(USE_SPNEGO) +struct negotiatedata; +#endif + +#if defined(USE_WINDOWS_SSPI) +#define GSS_ERROR(status) (status & 0x80000000) +#endif + +/* This is used to build a SPN string */ +#if !defined(USE_WINDOWS_SSPI) +char *Curl_auth_build_spn(const char *service, const char *host, + const char *realm); +#else +TCHAR *Curl_auth_build_spn(const char *service, const char *host, + const char *realm); +#endif + +/* This is used to test if the user contains a Windows domain name */ +bool Curl_auth_user_contains_domain(const char *user); + +/* This is used to generate a base64 encoded PLAIN cleartext message */ +CURLcode Curl_auth_create_plain_message(struct Curl_easy *data, + const char *authzid, + const char *authcid, + const char *passwd, + char **outptr, size_t *outlen); + +/* This is used to generate a base64 encoded LOGIN cleartext message */ +CURLcode Curl_auth_create_login_message(struct Curl_easy *data, + const char *valuep, char **outptr, + size_t *outlen); + +/* This is used to generate a base64 encoded EXTERNAL cleartext message */ +CURLcode Curl_auth_create_external_message(struct Curl_easy *data, + const char *user, char **outptr, + size_t *outlen); + +#if !defined(CURL_DISABLE_CRYPTO_AUTH) +/* This is used to decode a CRAM-MD5 challenge message */ +CURLcode Curl_auth_decode_cram_md5_message(const char *chlg64, char **outptr, + size_t *outlen); + +/* This is used to generate a CRAM-MD5 response message */ +CURLcode Curl_auth_create_cram_md5_message(struct Curl_easy *data, + const char *chlg, + const char *userp, + const char *passwdp, + char **outptr, size_t *outlen); + +/* This is used to evaluate if DIGEST is supported */ +bool Curl_auth_is_digest_supported(void); + +/* This is used to generate a base64 encoded DIGEST-MD5 response message */ +CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, + const char *chlg64, + const char *userp, + const char *passwdp, + const char *service, + char **outptr, size_t *outlen); + +/* This is used to decode a HTTP DIGEST challenge message */ +CURLcode Curl_auth_decode_digest_http_message(const char *chlg, + struct digestdata *digest); + +/* This is used to generate a HTTP DIGEST response message */ +CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + const unsigned char *request, + const unsigned char *uri, + struct digestdata *digest, + char **outptr, size_t *outlen); + +/* This is used to clean up the digest specific data */ +void Curl_auth_digest_cleanup(struct digestdata *digest); +#endif /* !CURL_DISABLE_CRYPTO_AUTH */ + +#if defined(USE_NTLM) +/* This is used to evaluate if NTLM is supported */ +bool Curl_auth_is_ntlm_supported(void); + +/* This is used to generate a base64 encoded NTLM type-1 message */ +CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + const char *service, + const char *host, + struct ntlmdata *ntlm, + char **outptr, + size_t *outlen); + +/* This is used to decode a base64 encoded NTLM type-2 message */ +CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, + const char *type2msg, + struct ntlmdata *ntlm); + +/* This is used to generate a base64 encoded NTLM type-3 message */ +CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + struct ntlmdata *ntlm, + char **outptr, size_t *outlen); + +/* This is used to clean up the NTLM specific data */ +void Curl_auth_cleanup_ntlm(struct ntlmdata *ntlm); +#endif /* USE_NTLM */ + +/* This is used to generate a base64 encoded OAuth 2.0 message */ +CURLcode Curl_auth_create_oauth_bearer_message(struct Curl_easy *data, + const char *user, + const char *host, + const long port, + const char *bearer, + char **outptr, size_t *outlen); + +/* This is used to generate a base64 encoded XOAuth 2.0 message */ +CURLcode Curl_auth_create_xoauth_bearer_message(struct Curl_easy *data, + const char *user, + const char *bearer, + char **outptr, size_t *outlen); + +#if defined(USE_KERBEROS5) +/* This is used to evaluate if GSSAPI (Kerberos V5) is supported */ +bool Curl_auth_is_gssapi_supported(void); + +/* This is used to generate a base64 encoded GSSAPI (Kerberos V5) user token + message */ +CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + const char *service, + const char *host, + const bool mutual, + const char *chlg64, + struct kerberos5data *krb5, + char **outptr, size_t *outlen); + +/* This is used to generate a base64 encoded GSSAPI (Kerberos V5) security + token message */ +CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, + const char *input, + struct kerberos5data *krb5, + char **outptr, + size_t *outlen); + +/* This is used to clean up the GSSAPI specific data */ +void Curl_auth_cleanup_gssapi(struct kerberos5data *krb5); +#endif /* USE_KERBEROS5 */ + +#if defined(USE_SPNEGO) +/* This is used to evaluate if SPNEGO (Negotiate) is supported */ +bool Curl_auth_is_spnego_supported(void); + +/* This is used to decode a base64 encoded SPNEGO (Negotiate) challenge + message */ +CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data, + const char *user, + const char *passwood, + const char *service, + const char *host, + const char *chlg64, + struct negotiatedata *nego); + +/* This is used to generate a base64 encoded SPNEGO (Negotiate) response + message */ +CURLcode Curl_auth_create_spnego_message(struct Curl_easy *data, + struct negotiatedata *nego, + char **outptr, size_t *outlen); + +/* This is used to clean up the SPNEGO specifiec data */ +void Curl_auth_cleanup_spnego(struct negotiatedata *nego); + +#endif /* USE_SPNEGO */ + +#endif /* HEADER_CURL_VAUTH_H */ diff --git a/dependencies/cmcurl/lib/version.c b/dependencies/cmcurl/lib/version.c new file mode 100644 index 0000000..14b0531 --- /dev/null +++ b/dependencies/cmcurl/lib/version.c @@ -0,0 +1,467 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include +#include "urldata.h" +#include "vtls/vtls.h" +#include "http2.h" +#include "ssh.h" +#include "curl_printf.h" + +#ifdef USE_ARES +# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \ + (defined(WIN32) || defined(__SYMBIAN32__)) +# define CARES_STATICLIB +# endif +# include +#endif + +#ifdef USE_LIBIDN2 +#include +#endif + +#ifdef USE_LIBPSL +#include +#endif + +#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS) +#include +#endif + +#ifdef USE_LIBRTMP +#include +#endif + +#ifdef USE_LIBSSH2 +#include +#endif + +#ifdef HAVE_LIBSSH2_VERSION +/* get it run-time if possible */ +#define CURL_LIBSSH2_VERSION libssh2_version(0) +#else +/* use build-time if run-time not possible */ +#define CURL_LIBSSH2_VERSION LIBSSH2_VERSION +#endif + +#ifdef HAVE_ZLIB_H +#include +#ifdef __SYMBIAN32__ +/* zlib pollutes the namespace with this definition */ +#undef WIN32 +#endif +#endif + +#ifdef HAVE_BROTLI +#include +#endif + +void Curl_version_init(void); + +/* For thread safety purposes this function is called by global_init so that + the static data in both version functions is initialized. */ +void Curl_version_init(void) +{ + curl_version(); + curl_version_info(CURLVERSION_NOW); +} + +#ifdef HAVE_BROTLI +static size_t brotli_version(char *buf, size_t bufsz) +{ + uint32_t brotli_version = BrotliDecoderVersion(); + unsigned int major = brotli_version >> 24; + unsigned int minor = (brotli_version & 0x00FFFFFF) >> 12; + unsigned int patch = brotli_version & 0x00000FFF; + + return msnprintf(buf, bufsz, "%u.%u.%u", major, minor, patch); +} +#endif + +char *curl_version(void) +{ + static bool initialized; + static char version[200]; + char *ptr = version; + size_t len; + size_t left = sizeof(version); + + if(initialized) + return version; + + strcpy(ptr, LIBCURL_NAME "/" LIBCURL_VERSION); + len = strlen(ptr); + left -= len; + ptr += len; + + if(left > 1) { + len = Curl_ssl_version(ptr + 1, left - 1); + + if(len > 0) { + *ptr = ' '; + left -= ++len; + ptr += len; + } + } + +#ifdef HAVE_LIBZ + len = msnprintf(ptr, left, " zlib/%s", zlibVersion()); + left -= len; + ptr += len; +#endif +#ifdef HAVE_BROTLI + len = msnprintf(ptr, left, "%s", " brotli/"); + left -= len; + ptr += len; + len = brotli_version(ptr, left); + left -= len; + ptr += len; +#endif +#ifdef USE_ARES + /* this function is only present in c-ares, not in the original ares */ + len = msnprintf(ptr, left, " c-ares/%s", ares_version(NULL)); + left -= len; + ptr += len; +#endif +#ifdef USE_LIBIDN2 + if(idn2_check_version(IDN2_VERSION)) { + len = msnprintf(ptr, left, " libidn2/%s", idn2_check_version(NULL)); + left -= len; + ptr += len; + } +#endif +#ifdef USE_LIBPSL + len = msnprintf(ptr, left, " libpsl/%s", psl_get_version()); + left -= len; + ptr += len; +#endif +#ifdef USE_WIN32_IDN + len = msnprintf(ptr, left, " WinIDN"); + left -= len; + ptr += len; +#endif +#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS) +#ifdef _LIBICONV_VERSION + len = msnprintf(ptr, left, " iconv/%d.%d", + _LIBICONV_VERSION >> 8, _LIBICONV_VERSION & 255); +#else + /* version unknown */ + len = msnprintf(ptr, left, " iconv"); +#endif /* _LIBICONV_VERSION */ + left -= len; + ptr += len; +#endif +#ifdef USE_LIBSSH2 + len = msnprintf(ptr, left, " libssh2/%s", CURL_LIBSSH2_VERSION); + left -= len; + ptr += len; +#endif +#ifdef USE_LIBSSH + len = msnprintf(ptr, left, " libssh/%s", CURL_LIBSSH_VERSION); + left -= len; + ptr += len; +#endif +#ifdef USE_NGHTTP2 + len = Curl_http2_ver(ptr, left); + left -= len; + ptr += len; +#endif +#ifdef USE_LIBRTMP + { + char suff[2]; + if(RTMP_LIB_VERSION & 0xff) { + suff[0] = (RTMP_LIB_VERSION & 0xff) + 'a' - 1; + suff[1] = '\0'; + } + else + suff[0] = '\0'; + + msnprintf(ptr, left, " librtmp/%d.%d%s", + RTMP_LIB_VERSION >> 16, (RTMP_LIB_VERSION >> 8) & 0xff, + suff); +/* + If another lib version is added below this one, this code would + also have to do: + + len = what msnprintf() returned + + left -= len; + ptr += len; +*/ + } +#endif + + /* Silent scan-build even if librtmp is not enabled. */ + (void) left; + (void) ptr; + + initialized = true; + return version; +} + +/* data for curl_version_info + + Keep the list sorted alphabetically. It is also written so that each + protocol line has its own #if line to make things easier on the eye. + */ + +static const char * const protocols[] = { +#ifndef CURL_DISABLE_DICT + "dict", +#endif +#ifndef CURL_DISABLE_FILE + "file", +#endif +#ifndef CURL_DISABLE_FTP + "ftp", +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP) + "ftps", +#endif +#ifndef CURL_DISABLE_GOPHER + "gopher", +#endif +#ifndef CURL_DISABLE_HTTP + "http", +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP) + "https", +#endif +#ifndef CURL_DISABLE_IMAP + "imap", +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP) + "imaps", +#endif +#ifndef CURL_DISABLE_LDAP + "ldap", +#if !defined(CURL_DISABLE_LDAPS) && \ + ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ + (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) + "ldaps", +#endif +#endif +#ifndef CURL_DISABLE_POP3 + "pop3", +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_POP3) + "pop3s", +#endif +#ifdef USE_LIBRTMP + "rtmp", +#endif +#ifndef CURL_DISABLE_RTSP + "rtsp", +#endif +#if defined(USE_SSH) + "scp", + "sftp", +#endif +#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \ + (CURL_SIZEOF_CURL_OFF_T > 4) && \ + (!defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)) + "smb", +# ifdef USE_SSL + "smbs", +# endif +#endif +#ifndef CURL_DISABLE_SMTP + "smtp", +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP) + "smtps", +#endif +#ifndef CURL_DISABLE_TELNET + "telnet", +#endif +#ifndef CURL_DISABLE_TFTP + "tftp", +#endif + + NULL +}; + +static curl_version_info_data version_info = { + CURLVERSION_NOW, + LIBCURL_VERSION, + LIBCURL_VERSION_NUM, + OS, /* as found by configure or set by hand at build-time */ + 0 /* features is 0 by default */ +#ifdef ENABLE_IPV6 + | CURL_VERSION_IPV6 +#endif +#ifdef USE_SSL + | CURL_VERSION_SSL +#endif +#ifdef USE_NTLM + | CURL_VERSION_NTLM +#endif +#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \ + defined(NTLM_WB_ENABLED) + | CURL_VERSION_NTLM_WB +#endif +#ifdef USE_SPNEGO + | CURL_VERSION_SPNEGO +#endif +#ifdef USE_KERBEROS5 + | CURL_VERSION_KERBEROS5 +#endif +#ifdef HAVE_GSSAPI + | CURL_VERSION_GSSAPI +#endif +#ifdef USE_WINDOWS_SSPI + | CURL_VERSION_SSPI +#endif +#ifdef HAVE_LIBZ + | CURL_VERSION_LIBZ +#endif +#ifdef DEBUGBUILD + | CURL_VERSION_DEBUG +#endif +#ifdef CURLDEBUG + | CURL_VERSION_CURLDEBUG +#endif +#ifdef CURLRES_ASYNCH + | CURL_VERSION_ASYNCHDNS +#endif +#if (CURL_SIZEOF_CURL_OFF_T > 4) && \ + ( (SIZEOF_OFF_T > 4) || defined(USE_WIN32_LARGE_FILES) ) + | CURL_VERSION_LARGEFILE +#endif +#if defined(CURL_DOES_CONVERSIONS) + | CURL_VERSION_CONV +#endif +#if defined(USE_TLS_SRP) + | CURL_VERSION_TLSAUTH_SRP +#endif +#if defined(USE_NGHTTP2) + | CURL_VERSION_HTTP2 +#endif +#if defined(USE_UNIX_SOCKETS) + | CURL_VERSION_UNIX_SOCKETS +#endif +#if defined(USE_LIBPSL) + | CURL_VERSION_PSL +#endif +#if defined(CURL_WITH_MULTI_SSL) + | CURL_VERSION_MULTI_SSL +#endif +#if defined(HAVE_BROTLI) + | CURL_VERSION_BROTLI +#endif +#if defined(USE_ALTSVC) + | CURL_VERSION_ALTSVC +#endif + , + NULL, /* ssl_version */ + 0, /* ssl_version_num, this is kept at zero */ + NULL, /* zlib_version */ + protocols, + NULL, /* c-ares version */ + 0, /* c-ares version numerical */ + NULL, /* libidn version */ + 0, /* iconv version */ + NULL, /* ssh lib version */ + 0, /* brotli_ver_num */ + NULL, /* brotli version */ +}; + +curl_version_info_data *curl_version_info(CURLversion stamp) +{ + static bool initialized; +#if defined(USE_SSH) + static char ssh_buffer[80]; +#endif +#ifdef USE_SSL +#ifdef CURL_WITH_MULTI_SSL + static char ssl_buffer[200]; +#else + static char ssl_buffer[80]; +#endif +#endif +#ifdef HAVE_BROTLI + static char brotli_buffer[80]; +#endif + + if(initialized) + return &version_info; + +#ifdef USE_SSL + Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer)); + version_info.ssl_version = ssl_buffer; + if(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY) + version_info.features |= CURL_VERSION_HTTPS_PROXY; + else + version_info.features &= ~CURL_VERSION_HTTPS_PROXY; +#endif + +#ifdef HAVE_LIBZ + version_info.libz_version = zlibVersion(); + /* libz left NULL if non-existing */ +#endif +#ifdef USE_ARES + { + int aresnum; + version_info.ares = ares_version(&aresnum); + version_info.ares_num = aresnum; + } +#endif +#ifdef USE_LIBIDN2 + /* This returns a version string if we use the given version or later, + otherwise it returns NULL */ + version_info.libidn = idn2_check_version(IDN2_VERSION); + if(version_info.libidn) + version_info.features |= CURL_VERSION_IDN; +#elif defined(USE_WIN32_IDN) + version_info.features |= CURL_VERSION_IDN; +#endif + +#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS) +#ifdef _LIBICONV_VERSION + version_info.iconv_ver_num = _LIBICONV_VERSION; +#else + /* version unknown */ + version_info.iconv_ver_num = -1; +#endif /* _LIBICONV_VERSION */ +#endif + +#if defined(USE_LIBSSH2) + msnprintf(ssh_buffer, sizeof(ssh_buffer), "libssh2/%s", LIBSSH2_VERSION); + version_info.libssh_version = ssh_buffer; +#elif defined(USE_LIBSSH) + msnprintf(ssh_buffer, sizeof(ssh_buffer), "libssh/%s", CURL_LIBSSH_VERSION); + version_info.libssh_version = ssh_buffer; +#endif + +#ifdef HAVE_BROTLI + version_info.brotli_ver_num = BrotliDecoderVersion(); + brotli_version(brotli_buffer, sizeof(brotli_buffer)); + version_info.brotli_version = brotli_buffer; +#endif + + (void)stamp; /* avoid compiler warnings, we don't use this */ + + initialized = true; + return &version_info; +} diff --git a/dependencies/cmcurl/lib/vtls/cyassl.c b/dependencies/cmcurl/lib/vtls/cyassl.c new file mode 100644 index 0000000..44a2bdd --- /dev/null +++ b/dependencies/cmcurl/lib/vtls/cyassl.c @@ -0,0 +1,1018 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all CyaSSL-specific code for the TLS/SSL layer. No code + * but vtls.c should ever call or use these functions. + * + */ + +#include "curl_setup.h" + +#ifdef USE_CYASSL + +#define WOLFSSL_OPTIONS_IGNORE_SYS +/* CyaSSL's version.h, which should contain only the version, should come +before all other CyaSSL includes and be immediately followed by build config +aka options.h. https://curl.haxx.se/mail/lib-2015-04/0069.html */ +#include +#if defined(HAVE_CYASSL_OPTIONS_H) && (LIBCYASSL_VERSION_HEX > 0x03004008) +#if defined(CYASSL_API) || defined(WOLFSSL_API) +/* Safety measure. If either is defined some API include was already included +and that's a problem since options.h hasn't been included yet. */ +#error "CyaSSL API was included before the CyaSSL build options." +#endif +#include +#endif + +/* To determine what functions are available we rely on one or both of: + - the user's options.h generated by CyaSSL/wolfSSL + - the symbols detected by curl's configure + Since they are markedly different from one another, and one or the other may + not be available, we do some checking below to bring things in sync. */ + +/* HAVE_ALPN is wolfSSL's build time symbol for enabling ALPN in options.h. */ +#ifndef HAVE_ALPN +#ifdef HAVE_WOLFSSL_USEALPN +#define HAVE_ALPN +#endif +#endif + +/* WOLFSSL_ALLOW_SSLV3 is wolfSSL's build time symbol for enabling SSLv3 in + options.h, but is only seen in >= 3.6.6 since that's when they started + disabling SSLv3 by default. */ +#ifndef WOLFSSL_ALLOW_SSLV3 +#if (LIBCYASSL_VERSION_HEX < 0x03006006) || \ + defined(HAVE_WOLFSSLV3_CLIENT_METHOD) +#define WOLFSSL_ALLOW_SSLV3 +#endif +#endif + +#include + +#include "urldata.h" +#include "sendf.h" +#include "inet_pton.h" +#include "vtls.h" +#include "parsedate.h" +#include "connect.h" /* for the connect timeout */ +#include "select.h" +#include "strcase.h" +#include "x509asn1.h" +#include "curl_printf.h" +#include "multiif.h" + +#include +#include +#ifdef HAVE_CYASSL_ERROR_SSL_H +#include +#else +#include +#endif +#include +#include + +#include "cyassl.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#if LIBCYASSL_VERSION_HEX < 0x02007002 /* < 2.7.2 */ +#define CYASSL_MAX_ERROR_SZ 80 +#endif + +/* KEEP_PEER_CERT is a product of the presence of build time symbol + OPENSSL_EXTRA without NO_CERTS, depending on the version. KEEP_PEER_CERT is + in wolfSSL's settings.h, and the latter two are build time symbols in + options.h. */ +#ifndef KEEP_PEER_CERT +#if defined(HAVE_CYASSL_GET_PEER_CERTIFICATE) || \ + defined(HAVE_WOLFSSL_GET_PEER_CERTIFICATE) || \ + (defined(OPENSSL_EXTRA) && !defined(NO_CERTS)) +#define KEEP_PEER_CERT +#endif +#endif + +struct ssl_backend_data { + SSL_CTX* ctx; + SSL* handle; +}; + +#define BACKEND connssl->backend + +static Curl_recv cyassl_recv; +static Curl_send cyassl_send; + + +static int do_file_type(const char *type) +{ + if(!type || !type[0]) + return SSL_FILETYPE_PEM; + if(strcasecompare(type, "PEM")) + return SSL_FILETYPE_PEM; + if(strcasecompare(type, "DER")) + return SSL_FILETYPE_ASN1; + return -1; +} + +/* + * This function loads all the client/CA certificates and CRLs. Setup the TLS + * layer and do all necessary magic. + */ +static CURLcode +cyassl_connect_step1(struct connectdata *conn, + int sockindex) +{ + char *ciphers; + struct Curl_easy *data = conn->data; + struct ssl_connect_data* connssl = &conn->ssl[sockindex]; + SSL_METHOD* req_method = NULL; + curl_socket_t sockfd = conn->sock[sockindex]; +#ifdef HAVE_SNI + bool sni = FALSE; +#define use_sni(x) sni = (x) +#else +#define use_sni(x) Curl_nop_stmt +#endif + + if(connssl->state == ssl_connection_complete) + return CURLE_OK; + + if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) { + failf(data, "CyaSSL does not support to set maximum SSL/TLS version"); + return CURLE_SSL_CONNECT_ERROR; + } + + /* check to see if we've been told to use an explicit SSL/TLS version */ + switch(SSL_CONN_CONFIG(version)) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: +#if LIBCYASSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */ + /* minimum protocol version is set later after the CTX object is created */ + req_method = SSLv23_client_method(); +#else + infof(data, "CyaSSL <3.3.0 cannot be configured to use TLS 1.0-1.2, " + "TLS 1.0 is used exclusively\n"); + req_method = TLSv1_client_method(); +#endif + use_sni(TRUE); + break; + case CURL_SSLVERSION_TLSv1_0: +#ifdef WOLFSSL_ALLOW_TLSV10 + req_method = TLSv1_client_method(); + use_sni(TRUE); +#else + failf(data, "CyaSSL does not support TLS 1.0"); + return CURLE_NOT_BUILT_IN; +#endif + break; + case CURL_SSLVERSION_TLSv1_1: + req_method = TLSv1_1_client_method(); + use_sni(TRUE); + break; + case CURL_SSLVERSION_TLSv1_2: + req_method = TLSv1_2_client_method(); + use_sni(TRUE); + break; + case CURL_SSLVERSION_TLSv1_3: +#ifdef WOLFSSL_TLS13 + req_method = wolfTLSv1_3_client_method(); + use_sni(TRUE); + break; +#else + failf(data, "CyaSSL: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; +#endif + case CURL_SSLVERSION_SSLv3: +#ifdef WOLFSSL_ALLOW_SSLV3 + req_method = SSLv3_client_method(); + use_sni(FALSE); +#else + failf(data, "CyaSSL does not support SSLv3"); + return CURLE_NOT_BUILT_IN; +#endif + break; + case CURL_SSLVERSION_SSLv2: + failf(data, "CyaSSL does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + + if(!req_method) { + failf(data, "SSL: couldn't create a method!"); + return CURLE_OUT_OF_MEMORY; + } + + if(BACKEND->ctx) + SSL_CTX_free(BACKEND->ctx); + BACKEND->ctx = SSL_CTX_new(req_method); + + if(!BACKEND->ctx) { + failf(data, "SSL: couldn't create a context!"); + return CURLE_OUT_OF_MEMORY; + } + + switch(SSL_CONN_CONFIG(version)) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: +#if LIBCYASSL_VERSION_HEX > 0x03004006 /* > 3.4.6 */ + /* Versions 3.3.0 to 3.4.6 we know the minimum protocol version is whatever + minimum version of TLS was built in and at least TLS 1.0. For later library + versions that could change (eg TLS 1.0 built in but defaults to TLS 1.1) so + we have this short circuit evaluation to find the minimum supported TLS + version. We use wolfSSL_CTX_SetMinVersion and not CyaSSL_SetMinVersion + because only the former will work before the user's CTX callback is called. + */ + if((wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1) != 1) && + (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_1) != 1) && + (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_2) != 1) +#ifdef WOLFSSL_TLS13 + && (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_3) != 1) +#endif + ) { + failf(data, "SSL: couldn't set the minimum protocol version"); + return CURLE_SSL_CONNECT_ERROR; + } +#endif + break; + } + + ciphers = SSL_CONN_CONFIG(cipher_list); + if(ciphers) { + if(!SSL_CTX_set_cipher_list(BACKEND->ctx, ciphers)) { + failf(data, "failed setting cipher list: %s", ciphers); + return CURLE_SSL_CIPHER; + } + infof(data, "Cipher selection: %s\n", ciphers); + } + +#ifndef NO_FILESYSTEM + /* load trusted cacert */ + if(SSL_CONN_CONFIG(CAfile)) { + if(1 != SSL_CTX_load_verify_locations(BACKEND->ctx, + SSL_CONN_CONFIG(CAfile), + SSL_CONN_CONFIG(CApath))) { + if(SSL_CONN_CONFIG(verifypeer)) { + /* Fail if we insist on successfully verifying the server. */ + failf(data, "error setting certificate verify locations:\n" + " CAfile: %s\n CApath: %s", + SSL_CONN_CONFIG(CAfile)? + SSL_CONN_CONFIG(CAfile): "none", + SSL_CONN_CONFIG(CApath)? + SSL_CONN_CONFIG(CApath) : "none"); + return CURLE_SSL_CACERT_BADFILE; + } + else { + /* Just continue with a warning if no strict certificate + verification is required. */ + infof(data, "error setting certificate verify locations," + " continuing anyway:\n"); + } + } + else { + /* Everything is fine. */ + infof(data, "successfully set certificate verify locations:\n"); + } + infof(data, + " CAfile: %s\n" + " CApath: %s\n", + SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile): + "none", + SSL_CONN_CONFIG(CApath) ? SSL_CONN_CONFIG(CApath): + "none"); + } + + /* Load the client certificate, and private key */ + if(SSL_SET_OPTION(cert) && SSL_SET_OPTION(key)) { + int file_type = do_file_type(SSL_SET_OPTION(cert_type)); + + if(SSL_CTX_use_certificate_file(BACKEND->ctx, SSL_SET_OPTION(cert), + file_type) != 1) { + failf(data, "unable to use client certificate (no key or wrong pass" + " phrase?)"); + return CURLE_SSL_CONNECT_ERROR; + } + + file_type = do_file_type(SSL_SET_OPTION(key_type)); + if(SSL_CTX_use_PrivateKey_file(BACKEND->ctx, SSL_SET_OPTION(key), + file_type) != 1) { + failf(data, "unable to set private key"); + return CURLE_SSL_CONNECT_ERROR; + } + } +#endif /* !NO_FILESYSTEM */ + + /* SSL always tries to verify the peer, this only says whether it should + * fail to connect if the verification fails, or if it should continue + * anyway. In the latter case the result of the verification is checked with + * SSL_get_verify_result() below. */ + SSL_CTX_set_verify(BACKEND->ctx, + SSL_CONN_CONFIG(verifypeer)?SSL_VERIFY_PEER: + SSL_VERIFY_NONE, + NULL); + +#ifdef HAVE_SNI + if(sni) { + struct in_addr addr4; +#ifdef ENABLE_IPV6 + struct in6_addr addr6; +#endif + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + size_t hostname_len = strlen(hostname); + if((hostname_len < USHRT_MAX) && + (0 == Curl_inet_pton(AF_INET, hostname, &addr4)) && +#ifdef ENABLE_IPV6 + (0 == Curl_inet_pton(AF_INET6, hostname, &addr6)) && +#endif + (CyaSSL_CTX_UseSNI(BACKEND->ctx, CYASSL_SNI_HOST_NAME, hostname, + (unsigned short)hostname_len) != 1)) { + infof(data, "WARNING: failed to configure server name indication (SNI) " + "TLS extension\n"); + } + } +#endif + + /* give application a chance to interfere with SSL set up. */ + if(data->set.ssl.fsslctx) { + CURLcode result = CURLE_OK; + result = (*data->set.ssl.fsslctx)(data, BACKEND->ctx, + data->set.ssl.fsslctxp); + if(result) { + failf(data, "error signaled by ssl ctx callback"); + return result; + } + } +#ifdef NO_FILESYSTEM + else if(SSL_CONN_CONFIG(verifypeer)) { + failf(data, "SSL: Certificates couldn't be loaded because CyaSSL was built" + " with \"no filesystem\". Either disable peer verification" + " (insecure) or if you are building an application with libcurl you" + " can load certificates via CURLOPT_SSL_CTX_FUNCTION."); + return CURLE_SSL_CONNECT_ERROR; + } +#endif + + /* Let's make an SSL structure */ + if(BACKEND->handle) + SSL_free(BACKEND->handle); + BACKEND->handle = SSL_new(BACKEND->ctx); + if(!BACKEND->handle) { + failf(data, "SSL: couldn't create a context (handle)!"); + return CURLE_OUT_OF_MEMORY; + } + +#ifdef HAVE_ALPN + if(conn->bits.tls_enable_alpn) { + char protocols[128]; + *protocols = '\0'; + + /* wolfSSL's ALPN protocol name list format is a comma separated string of + protocols in descending order of preference, eg: "h2,http/1.1" */ + +#ifdef USE_NGHTTP2 + if(data->set.httpversion >= CURL_HTTP_VERSION_2) { + strcpy(protocols + strlen(protocols), NGHTTP2_PROTO_VERSION_ID ","); + infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + } +#endif + + strcpy(protocols + strlen(protocols), ALPN_HTTP_1_1); + infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); + + if(wolfSSL_UseALPN(BACKEND->handle, protocols, + (unsigned)strlen(protocols), + WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != SSL_SUCCESS) { + failf(data, "SSL: failed setting ALPN protocols"); + return CURLE_SSL_CONNECT_ERROR; + } + } +#endif /* HAVE_ALPN */ + + /* Check if there's a cached ID we can/should use here! */ + if(SSL_SET_OPTION(primary.sessionid)) { + void *ssl_sessionid = NULL; + + Curl_ssl_sessionid_lock(conn); + if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) { + /* we got a session id, use it! */ + if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) { + char error_buffer[CYASSL_MAX_ERROR_SZ]; + Curl_ssl_sessionid_unlock(conn); + failf(data, "SSL: SSL_set_session failed: %s", + ERR_error_string(SSL_get_error(BACKEND->handle, 0), + error_buffer)); + return CURLE_SSL_CONNECT_ERROR; + } + /* Informational message */ + infof(data, "SSL re-using session ID\n"); + } + Curl_ssl_sessionid_unlock(conn); + } + + /* pass the raw socket into the SSL layer */ + if(!SSL_set_fd(BACKEND->handle, (int)sockfd)) { + failf(data, "SSL: SSL_set_fd failed"); + return CURLE_SSL_CONNECT_ERROR; + } + + connssl->connecting_state = ssl_connect_2; + return CURLE_OK; +} + + +static CURLcode +cyassl_connect_step2(struct connectdata *conn, + int sockindex) +{ + int ret = -1; + struct Curl_easy *data = conn->data; + struct ssl_connect_data* connssl = &conn->ssl[sockindex]; + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const char * const dispname = SSL_IS_PROXY() ? + conn->http_proxy.host.dispname : conn->host.dispname; + const char * const pinnedpubkey = SSL_IS_PROXY() ? + data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + + conn->recv[sockindex] = cyassl_recv; + conn->send[sockindex] = cyassl_send; + + /* Enable RFC2818 checks */ + if(SSL_CONN_CONFIG(verifyhost)) { + ret = CyaSSL_check_domain_name(BACKEND->handle, hostname); + if(ret == SSL_FAILURE) + return CURLE_OUT_OF_MEMORY; + } + + ret = SSL_connect(BACKEND->handle); + if(ret != 1) { + char error_buffer[CYASSL_MAX_ERROR_SZ]; + int detail = SSL_get_error(BACKEND->handle, ret); + + if(SSL_ERROR_WANT_READ == detail) { + connssl->connecting_state = ssl_connect_2_reading; + return CURLE_OK; + } + else if(SSL_ERROR_WANT_WRITE == detail) { + connssl->connecting_state = ssl_connect_2_writing; + return CURLE_OK; + } + /* There is no easy way to override only the CN matching. + * This will enable the override of both mismatching SubjectAltNames + * as also mismatching CN fields */ + else if(DOMAIN_NAME_MISMATCH == detail) { +#if 1 + failf(data, "\tsubject alt name(s) or common name do not match \"%s\"\n", + dispname); + return CURLE_PEER_FAILED_VERIFICATION; +#else + /* When the CyaSSL_check_domain_name() is used and you desire to continue + * on a DOMAIN_NAME_MISMATCH, i.e. 'conn->ssl_config.verifyhost == 0', + * CyaSSL version 2.4.0 will fail with an INCOMPLETE_DATA error. The only + * way to do this is currently to switch the CyaSSL_check_domain_name() + * in and out based on the 'conn->ssl_config.verifyhost' value. */ + if(SSL_CONN_CONFIG(verifyhost)) { + failf(data, + "\tsubject alt name(s) or common name do not match \"%s\"\n", + dispname); + return CURLE_PEER_FAILED_VERIFICATION; + } + else { + infof(data, + "\tsubject alt name(s) and/or common name do not match \"%s\"\n", + dispname); + return CURLE_OK; + } +#endif + } +#if LIBCYASSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */ + else if(ASN_NO_SIGNER_E == detail) { + if(SSL_CONN_CONFIG(verifypeer)) { + failf(data, "\tCA signer not available for verification\n"); + return CURLE_SSL_CACERT_BADFILE; + } + else { + /* Just continue with a warning if no strict certificate + verification is required. */ + infof(data, "CA signer not available for verification, " + "continuing anyway\n"); + } + } +#endif + else { + failf(data, "SSL_connect failed with error %d: %s", detail, + ERR_error_string(detail, error_buffer)); + return CURLE_SSL_CONNECT_ERROR; + } + } + + if(pinnedpubkey) { +#ifdef KEEP_PEER_CERT + X509 *x509; + const char *x509_der; + int x509_der_len; + curl_X509certificate x509_parsed; + curl_asn1Element *pubkey; + CURLcode result; + + x509 = SSL_get_peer_certificate(BACKEND->handle); + if(!x509) { + failf(data, "SSL: failed retrieving server certificate"); + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + } + + x509_der = (const char *)CyaSSL_X509_get_der(x509, &x509_der_len); + if(!x509_der) { + failf(data, "SSL: failed retrieving ASN.1 server certificate"); + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + } + + memset(&x509_parsed, 0, sizeof(x509_parsed)); + if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len)) + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + + pubkey = &x509_parsed.subjectPublicKeyInfo; + if(!pubkey->header || pubkey->end <= pubkey->header) { + failf(data, "SSL: failed retrieving public key from server certificate"); + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + } + + result = Curl_pin_peer_pubkey(data, + pinnedpubkey, + (const unsigned char *)pubkey->header, + (size_t)(pubkey->end - pubkey->header)); + if(result) { + failf(data, "SSL: public key does not match pinned public key!"); + return result; + } +#else + failf(data, "Library lacks pinning support built-in"); + return CURLE_NOT_BUILT_IN; +#endif + } + +#ifdef HAVE_ALPN + if(conn->bits.tls_enable_alpn) { + int rc; + char *protocol = NULL; + unsigned short protocol_len = 0; + + rc = wolfSSL_ALPN_GetProtocol(BACKEND->handle, &protocol, &protocol_len); + + if(rc == SSL_SUCCESS) { + infof(data, "ALPN, server accepted to use %.*s\n", protocol_len, + protocol); + + if(protocol_len == ALPN_HTTP_1_1_LENGTH && + !memcmp(protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH)) + conn->negnpn = CURL_HTTP_VERSION_1_1; +#ifdef USE_NGHTTP2 + else if(data->set.httpversion >= CURL_HTTP_VERSION_2 && + protocol_len == NGHTTP2_PROTO_VERSION_ID_LEN && + !memcmp(protocol, NGHTTP2_PROTO_VERSION_ID, + NGHTTP2_PROTO_VERSION_ID_LEN)) + conn->negnpn = CURL_HTTP_VERSION_2; +#endif + else + infof(data, "ALPN, unrecognized protocol %.*s\n", protocol_len, + protocol); + Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); + } + else if(rc == SSL_ALPN_NOT_FOUND) + infof(data, "ALPN, server did not agree to a protocol\n"); + else { + failf(data, "ALPN, failure getting protocol, error %d", rc); + return CURLE_SSL_CONNECT_ERROR; + } + } +#endif /* HAVE_ALPN */ + + connssl->connecting_state = ssl_connect_3; +#if (LIBCYASSL_VERSION_HEX >= 0x03009010) + infof(data, "SSL connection using %s / %s\n", + wolfSSL_get_version(BACKEND->handle), + wolfSSL_get_cipher_name(BACKEND->handle)); +#else + infof(data, "SSL connected\n"); +#endif + + return CURLE_OK; +} + + +static CURLcode +cyassl_connect_step3(struct connectdata *conn, + int sockindex) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); + + if(SSL_SET_OPTION(primary.sessionid)) { + bool incache; + SSL_SESSION *our_ssl_sessionid; + void *old_ssl_sessionid = NULL; + + our_ssl_sessionid = SSL_get_session(BACKEND->handle); + + Curl_ssl_sessionid_lock(conn); + incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, + sockindex)); + if(incache) { + if(old_ssl_sessionid != our_ssl_sessionid) { + infof(data, "old SSL session ID is stale, removing\n"); + Curl_ssl_delsessionid(conn, old_ssl_sessionid); + incache = FALSE; + } + } + + if(!incache) { + result = Curl_ssl_addsessionid(conn, our_ssl_sessionid, + 0 /* unknown size */, sockindex); + if(result) { + Curl_ssl_sessionid_unlock(conn); + failf(data, "failed to store ssl session"); + return result; + } + } + Curl_ssl_sessionid_unlock(conn); + } + + connssl->connecting_state = ssl_connect_done; + + return result; +} + + +static ssize_t cyassl_send(struct connectdata *conn, + int sockindex, + const void *mem, + size_t len, + CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + char error_buffer[CYASSL_MAX_ERROR_SZ]; + int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; + int rc = SSL_write(BACKEND->handle, mem, memlen); + + if(rc < 0) { + int err = SSL_get_error(BACKEND->handle, rc); + + switch(err) { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + /* there's data pending, re-invoke SSL_write() */ + *curlcode = CURLE_AGAIN; + return -1; + default: + failf(conn->data, "SSL write: %s, errno %d", + ERR_error_string(err, error_buffer), + SOCKERRNO); + *curlcode = CURLE_SEND_ERROR; + return -1; + } + } + return rc; +} + +static void Curl_cyassl_close(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + if(BACKEND->handle) { + (void)SSL_shutdown(BACKEND->handle); + SSL_free(BACKEND->handle); + BACKEND->handle = NULL; + } + if(BACKEND->ctx) { + SSL_CTX_free(BACKEND->ctx); + BACKEND->ctx = NULL; + } +} + +static ssize_t cyassl_recv(struct connectdata *conn, + int num, + char *buf, + size_t buffersize, + CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[num]; + char error_buffer[CYASSL_MAX_ERROR_SZ]; + int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; + int nread = SSL_read(BACKEND->handle, buf, buffsize); + + if(nread < 0) { + int err = SSL_get_error(BACKEND->handle, nread); + + switch(err) { + case SSL_ERROR_ZERO_RETURN: /* no more data */ + break; + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + /* there's data pending, re-invoke SSL_read() */ + *curlcode = CURLE_AGAIN; + return -1; + default: + failf(conn->data, "SSL read: %s, errno %d", + ERR_error_string(err, error_buffer), + SOCKERRNO); + *curlcode = CURLE_RECV_ERROR; + return -1; + } + } + return nread; +} + + +static void Curl_cyassl_session_free(void *ptr) +{ + (void)ptr; + /* CyaSSL reuses sessions on own, no free */ +} + + +static size_t Curl_cyassl_version(char *buffer, size_t size) +{ +#if LIBCYASSL_VERSION_HEX >= 0x03006000 + return msnprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version()); +#elif defined(WOLFSSL_VERSION) + return msnprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION); +#elif defined(CYASSL_VERSION) + return msnprintf(buffer, size, "CyaSSL/%s", CYASSL_VERSION); +#else + return msnprintf(buffer, size, "CyaSSL/%s", "<1.8.8"); +#endif +} + + +static int Curl_cyassl_init(void) +{ + return (CyaSSL_Init() == SSL_SUCCESS); +} + + +static void Curl_cyassl_cleanup(void) +{ + CyaSSL_Cleanup(); +} + + +static bool Curl_cyassl_data_pending(const struct connectdata* conn, + int connindex) +{ + const struct ssl_connect_data *connssl = &conn->ssl[connindex]; + if(BACKEND->handle) /* SSL is in use */ + return (0 != SSL_pending(BACKEND->handle)) ? TRUE : FALSE; + else + return FALSE; +} + + +/* + * This function is called to shut down the SSL layer but keep the + * socket open (CCC - Clear Command Channel) + */ +static int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex) +{ + int retval = 0; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + if(BACKEND->handle) { + SSL_free(BACKEND->handle); + BACKEND->handle = NULL; + } + return retval; +} + + +static CURLcode +cyassl_connect_common(struct connectdata *conn, + int sockindex, + bool nonblocking, + bool *done) +{ + CURLcode result; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + time_t timeout_ms; + int what; + + /* check if the connection has already been established */ + if(ssl_connection_complete == connssl->state) { + *done = TRUE; + return CURLE_OK; + } + + if(ssl_connect_1 == connssl->connecting_state) { + /* Find out how much more time we're allowed */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + result = cyassl_connect_step1(conn, sockindex); + if(result) + return result; + } + + while(ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state) { + + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* if ssl is expecting something, check if it's available. */ + if(connssl->connecting_state == ssl_connect_2_reading + || connssl->connecting_state == ssl_connect_2_writing) { + + curl_socket_t writefd = ssl_connect_2_writing == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + curl_socket_t readfd = ssl_connect_2_reading == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + + what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, + nonblocking?0:timeout_ms); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + else if(0 == what) { + if(nonblocking) { + *done = FALSE; + return CURLE_OK; + } + else { + /* timeout */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + } + /* socket is readable or writable */ + } + + /* Run transaction, and return to the caller if it failed or if + * this connection is part of a multi handle and this loop would + * execute again. This permits the owner of a multi handle to + * abort a connection attempt before step2 has completed while + * ensuring that a client using select() or epoll() will always + * have a valid fdset to wait on. + */ + result = cyassl_connect_step2(conn, sockindex); + if(result || (nonblocking && + (ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state))) + return result; + } /* repeat step2 until all transactions are done. */ + + if(ssl_connect_3 == connssl->connecting_state) { + result = cyassl_connect_step3(conn, sockindex); + if(result) + return result; + } + + if(ssl_connect_done == connssl->connecting_state) { + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = cyassl_recv; + conn->send[sockindex] = cyassl_send; + *done = TRUE; + } + else + *done = FALSE; + + /* Reset our connect state machine */ + connssl->connecting_state = ssl_connect_1; + + return CURLE_OK; +} + + +static CURLcode Curl_cyassl_connect_nonblocking(struct connectdata *conn, + int sockindex, bool *done) +{ + return cyassl_connect_common(conn, sockindex, TRUE, done); +} + + +static CURLcode Curl_cyassl_connect(struct connectdata *conn, int sockindex) +{ + CURLcode result; + bool done = FALSE; + + result = cyassl_connect_common(conn, sockindex, FALSE, &done); + if(result) + return result; + + DEBUGASSERT(done); + + return CURLE_OK; +} + +static CURLcode Curl_cyassl_random(struct Curl_easy *data, + unsigned char *entropy, size_t length) +{ + RNG rng; + (void)data; + if(InitRng(&rng)) + return CURLE_FAILED_INIT; + if(length > UINT_MAX) + return CURLE_FAILED_INIT; + if(RNG_GenerateBlock(&rng, entropy, (unsigned)length)) + return CURLE_FAILED_INIT; + if(FreeRng(&rng)) + return CURLE_FAILED_INIT; + return CURLE_OK; +} + +static CURLcode Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *sha256sum /* output */, + size_t unused) +{ + Sha256 SHA256pw; + (void)unused; + InitSha256(&SHA256pw); + Sha256Update(&SHA256pw, tmp, (word32)tmplen); + Sha256Final(&SHA256pw, sha256sum); + return CURLE_OK; +} + +static void *Curl_cyassl_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) +{ + (void)info; + return BACKEND->handle; +} + +const struct Curl_ssl Curl_ssl_cyassl = { + { CURLSSLBACKEND_WOLFSSL, "WolfSSL" }, /* info */ + +#ifdef KEEP_PEER_CERT + SSLSUPP_PINNEDPUBKEY | +#endif + SSLSUPP_SSL_CTX, + + sizeof(struct ssl_backend_data), + + Curl_cyassl_init, /* init */ + Curl_cyassl_cleanup, /* cleanup */ + Curl_cyassl_version, /* version */ + Curl_none_check_cxn, /* check_cxn */ + Curl_cyassl_shutdown, /* shutdown */ + Curl_cyassl_data_pending, /* data_pending */ + Curl_cyassl_random, /* random */ + Curl_none_cert_status_request, /* cert_status_request */ + Curl_cyassl_connect, /* connect */ + Curl_cyassl_connect_nonblocking, /* connect_nonblocking */ + Curl_cyassl_get_internals, /* get_internals */ + Curl_cyassl_close, /* close_one */ + Curl_none_close_all, /* close_all */ + Curl_cyassl_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ + Curl_none_md5sum, /* md5sum */ + Curl_cyassl_sha256sum /* sha256sum */ +}; + +#endif diff --git a/dependencies/cmcurl/lib/vtls/cyassl.h b/dependencies/cmcurl/lib/vtls/cyassl.h new file mode 100644 index 0000000..01e11cc --- /dev/null +++ b/dependencies/cmcurl/lib/vtls/cyassl.h @@ -0,0 +1,31 @@ +#ifndef HEADER_CURL_CYASSL_H +#define HEADER_CURL_CYASSL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_CYASSL + +extern const struct Curl_ssl Curl_ssl_cyassl; + +#endif /* USE_CYASSL */ +#endif /* HEADER_CURL_CYASSL_H */ diff --git a/dependencies/cmcurl/lib/vtls/gskit.c b/dependencies/cmcurl/lib/vtls/gskit.c new file mode 100644 index 0000000..b93ff5d --- /dev/null +++ b/dependencies/cmcurl/lib/vtls/gskit.c @@ -0,0 +1,1381 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_GSKIT + +#include +#include + +/* Some symbols are undefined/unsupported on OS400 versions < V7R1. */ +#ifndef GSK_SSL_EXTN_SERVERNAME_REQUEST +#define GSK_SSL_EXTN_SERVERNAME_REQUEST 230 +#endif + +#ifndef GSK_TLSV10_CIPHER_SPECS +#define GSK_TLSV10_CIPHER_SPECS 236 +#endif + +#ifndef GSK_TLSV11_CIPHER_SPECS +#define GSK_TLSV11_CIPHER_SPECS 237 +#endif + +#ifndef GSK_TLSV12_CIPHER_SPECS +#define GSK_TLSV12_CIPHER_SPECS 238 +#endif + +#ifndef GSK_PROTOCOL_TLSV11 +#define GSK_PROTOCOL_TLSV11 437 +#endif + +#ifndef GSK_PROTOCOL_TLSV12 +#define GSK_PROTOCOL_TLSV12 438 +#endif + +#ifndef GSK_FALSE +#define GSK_FALSE 0 +#endif + +#ifndef GSK_TRUE +#define GSK_TRUE 1 +#endif + + +#include + +#include +#include "urldata.h" +#include "sendf.h" +#include "gskit.h" +#include "vtls.h" +#include "connect.h" /* for the connect timeout */ +#include "select.h" +#include "strcase.h" +#include "x509asn1.h" +#include "curl_printf.h" + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + + +/* Directions. */ +#define SOS_READ 0x01 +#define SOS_WRITE 0x02 + +/* SSL version flags. */ +#define CURL_GSKPROTO_SSLV2 0 +#define CURL_GSKPROTO_SSLV2_MASK (1 << CURL_GSKPROTO_SSLV2) +#define CURL_GSKPROTO_SSLV3 1 +#define CURL_GSKPROTO_SSLV3_MASK (1 << CURL_GSKPROTO_SSLV3) +#define CURL_GSKPROTO_TLSV10 2 +#define CURL_GSKPROTO_TLSV10_MASK (1 << CURL_GSKPROTO_TLSV10) +#define CURL_GSKPROTO_TLSV11 3 +#define CURL_GSKPROTO_TLSV11_MASK (1 << CURL_GSKPROTO_TLSV11) +#define CURL_GSKPROTO_TLSV12 4 +#define CURL_GSKPROTO_TLSV12_MASK (1 << CURL_GSKPROTO_TLSV12) +#define CURL_GSKPROTO_LAST 5 + +struct ssl_backend_data { + gsk_handle handle; + int iocport; + int localfd; + int remotefd; +}; + +#define BACKEND connssl->backend + +/* Supported ciphers. */ +typedef struct { + const char *name; /* Cipher name. */ + const char *gsktoken; /* Corresponding token for GSKit String. */ + unsigned int versions; /* SSL version flags. */ +} gskit_cipher; + +static const gskit_cipher ciphertable[] = { + { "null-md5", "01", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, + { "null-sha", "02", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, + { "exp-rc4-md5", "03", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK }, + { "rc4-md5", "04", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, + { "rc4-sha", "05", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, + { "exp-rc2-cbc-md5", "06", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK }, + { "exp-des-cbc-sha", "09", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK }, + { "des-cbc3-sha", "0A", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, + { "aes128-sha", "2F", + CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK | + CURL_GSKPROTO_TLSV12_MASK }, + { "aes256-sha", "35", + CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK | + CURL_GSKPROTO_TLSV12_MASK }, + { "null-sha256", "3B", CURL_GSKPROTO_TLSV12_MASK }, + { "aes128-sha256", "3C", CURL_GSKPROTO_TLSV12_MASK }, + { "aes256-sha256", "3D", CURL_GSKPROTO_TLSV12_MASK }, + { "aes128-gcm-sha256", + "9C", CURL_GSKPROTO_TLSV12_MASK }, + { "aes256-gcm-sha384", + "9D", CURL_GSKPROTO_TLSV12_MASK }, + { "rc4-md5", "1", CURL_GSKPROTO_SSLV2_MASK }, + { "exp-rc4-md5", "2", CURL_GSKPROTO_SSLV2_MASK }, + { "rc2-md5", "3", CURL_GSKPROTO_SSLV2_MASK }, + { "exp-rc2-md5", "4", CURL_GSKPROTO_SSLV2_MASK }, + { "des-cbc-md5", "6", CURL_GSKPROTO_SSLV2_MASK }, + { "des-cbc3-md5", "7", CURL_GSKPROTO_SSLV2_MASK }, + { (const char *) NULL, (const char *) NULL, 0 } +}; + + +static bool is_separator(char c) +{ + /* Return whether character is a cipher list separator. */ + switch(c) { + case ' ': + case '\t': + case ':': + case ',': + case ';': + return true; + } + return false; +} + + +static CURLcode gskit_status(struct Curl_easy *data, int rc, + const char *procname, CURLcode defcode) +{ + /* Process GSKit status and map it to a CURLcode. */ + switch(rc) { + case GSK_OK: + case GSK_OS400_ASYNCHRONOUS_SOC_INIT: + return CURLE_OK; + case GSK_KEYRING_OPEN_ERROR: + case GSK_OS400_ERROR_NO_ACCESS: + return CURLE_SSL_CACERT_BADFILE; + case GSK_INSUFFICIENT_STORAGE: + return CURLE_OUT_OF_MEMORY; + case GSK_ERROR_BAD_V2_CIPHER: + case GSK_ERROR_BAD_V3_CIPHER: + case GSK_ERROR_NO_CIPHERS: + return CURLE_SSL_CIPHER; + case GSK_OS400_ERROR_NOT_TRUSTED_ROOT: + case GSK_ERROR_CERT_VALIDATION: + return CURLE_PEER_FAILED_VERIFICATION; + case GSK_OS400_ERROR_TIMED_OUT: + return CURLE_OPERATION_TIMEDOUT; + case GSK_WOULD_BLOCK: + return CURLE_AGAIN; + case GSK_OS400_ERROR_NOT_REGISTERED: + break; + case GSK_ERROR_IO: + switch(errno) { + case ENOMEM: + return CURLE_OUT_OF_MEMORY; + default: + failf(data, "%s I/O error: %s", procname, strerror(errno)); + break; + } + break; + default: + failf(data, "%s: %s", procname, gsk_strerror(rc)); + break; + } + return defcode; +} + + +static CURLcode set_enum(struct Curl_easy *data, gsk_handle h, + GSK_ENUM_ID id, GSK_ENUM_VALUE value, bool unsupported_ok) +{ + int rc = gsk_attribute_set_enum(h, id, value); + + switch(rc) { + case GSK_OK: + return CURLE_OK; + case GSK_ERROR_IO: + failf(data, "gsk_attribute_set_enum() I/O error: %s", strerror(errno)); + break; + case GSK_ATTRIBUTE_INVALID_ID: + if(unsupported_ok) + return CURLE_UNSUPPORTED_PROTOCOL; + default: + failf(data, "gsk_attribute_set_enum(): %s", gsk_strerror(rc)); + break; + } + return CURLE_SSL_CONNECT_ERROR; +} + + +static CURLcode set_buffer(struct Curl_easy *data, gsk_handle h, + GSK_BUF_ID id, const char *buffer, bool unsupported_ok) +{ + int rc = gsk_attribute_set_buffer(h, id, buffer, 0); + + switch(rc) { + case GSK_OK: + return CURLE_OK; + case GSK_ERROR_IO: + failf(data, "gsk_attribute_set_buffer() I/O error: %s", strerror(errno)); + break; + case GSK_ATTRIBUTE_INVALID_ID: + if(unsupported_ok) + return CURLE_UNSUPPORTED_PROTOCOL; + default: + failf(data, "gsk_attribute_set_buffer(): %s", gsk_strerror(rc)); + break; + } + return CURLE_SSL_CONNECT_ERROR; +} + + +static CURLcode set_numeric(struct Curl_easy *data, + gsk_handle h, GSK_NUM_ID id, int value) +{ + int rc = gsk_attribute_set_numeric_value(h, id, value); + + switch(rc) { + case GSK_OK: + return CURLE_OK; + case GSK_ERROR_IO: + failf(data, "gsk_attribute_set_numeric_value() I/O error: %s", + strerror(errno)); + break; + default: + failf(data, "gsk_attribute_set_numeric_value(): %s", gsk_strerror(rc)); + break; + } + return CURLE_SSL_CONNECT_ERROR; +} + + +static CURLcode set_callback(struct Curl_easy *data, + gsk_handle h, GSK_CALLBACK_ID id, void *info) +{ + int rc = gsk_attribute_set_callback(h, id, info); + + switch(rc) { + case GSK_OK: + return CURLE_OK; + case GSK_ERROR_IO: + failf(data, "gsk_attribute_set_callback() I/O error: %s", strerror(errno)); + break; + default: + failf(data, "gsk_attribute_set_callback(): %s", gsk_strerror(rc)); + break; + } + return CURLE_SSL_CONNECT_ERROR; +} + + +static CURLcode set_ciphers(struct connectdata *conn, + gsk_handle h, unsigned int *protoflags) +{ + struct Curl_easy *data = conn->data; + const char *cipherlist = SSL_CONN_CONFIG(cipher_list); + const char *clp; + const gskit_cipher *ctp; + int i; + int l; + bool unsupported; + CURLcode result; + struct { + char *buf; + char *ptr; + } ciphers[CURL_GSKPROTO_LAST]; + + /* Compile cipher list into GSKit-compatible cipher lists. */ + + if(!cipherlist) + return CURLE_OK; + while(is_separator(*cipherlist)) /* Skip initial separators. */ + cipherlist++; + if(!*cipherlist) + return CURLE_OK; + + /* We allocate GSKit buffers of the same size as the input string: since + GSKit tokens are always shorter than their cipher names, allocated buffers + will always be large enough to accommodate the result. */ + l = strlen(cipherlist) + 1; + memset((char *) ciphers, 0, sizeof(ciphers)); + for(i = 0; i < CURL_GSKPROTO_LAST; i++) { + ciphers[i].buf = malloc(l); + if(!ciphers[i].buf) { + while(i--) + free(ciphers[i].buf); + return CURLE_OUT_OF_MEMORY; + } + ciphers[i].ptr = ciphers[i].buf; + *ciphers[i].ptr = '\0'; + } + + /* Process each cipher in input string. */ + unsupported = FALSE; + result = CURLE_OK; + for(;;) { + for(clp = cipherlist; *cipherlist && !is_separator(*cipherlist);) + cipherlist++; + l = cipherlist - clp; + if(!l) + break; + /* Search the cipher in our table. */ + for(ctp = ciphertable; ctp->name; ctp++) + if(strncasecompare(ctp->name, clp, l) && !ctp->name[l]) + break; + if(!ctp->name) { + failf(data, "Unknown cipher %.*s", l, clp); + result = CURLE_SSL_CIPHER; + } + else { + unsupported |= !(ctp->versions & (CURL_GSKPROTO_SSLV2_MASK | + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK)); + for(i = 0; i < CURL_GSKPROTO_LAST; i++) { + if(ctp->versions & (1 << i)) { + strcpy(ciphers[i].ptr, ctp->gsktoken); + ciphers[i].ptr += strlen(ctp->gsktoken); + } + } + } + + /* Advance to next cipher name or end of string. */ + while(is_separator(*cipherlist)) + cipherlist++; + } + + /* Disable protocols with empty cipher lists. */ + for(i = 0; i < CURL_GSKPROTO_LAST; i++) { + if(!(*protoflags & (1 << i)) || !ciphers[i].buf[0]) { + *protoflags &= ~(1 << i); + ciphers[i].buf[0] = '\0'; + } + } + + /* Try to set-up TLSv1.1 and TLSv2.1 ciphers. */ + if(*protoflags & CURL_GSKPROTO_TLSV11_MASK) { + result = set_buffer(data, h, GSK_TLSV11_CIPHER_SPECS, + ciphers[CURL_GSKPROTO_TLSV11].buf, TRUE); + if(result == CURLE_UNSUPPORTED_PROTOCOL) { + result = CURLE_OK; + if(unsupported) { + failf(data, "TLSv1.1-only ciphers are not yet supported"); + result = CURLE_SSL_CIPHER; + } + } + } + if(!result && (*protoflags & CURL_GSKPROTO_TLSV12_MASK)) { + result = set_buffer(data, h, GSK_TLSV12_CIPHER_SPECS, + ciphers[CURL_GSKPROTO_TLSV12].buf, TRUE); + if(result == CURLE_UNSUPPORTED_PROTOCOL) { + result = CURLE_OK; + if(unsupported) { + failf(data, "TLSv1.2-only ciphers are not yet supported"); + result = CURLE_SSL_CIPHER; + } + } + } + + /* Try to set-up TLSv1.0 ciphers. If not successful, concatenate them to + the SSLv3 ciphers. OS/400 prior to version 7.1 will understand it. */ + if(!result && (*protoflags & CURL_GSKPROTO_TLSV10_MASK)) { + result = set_buffer(data, h, GSK_TLSV10_CIPHER_SPECS, + ciphers[CURL_GSKPROTO_TLSV10].buf, TRUE); + if(result == CURLE_UNSUPPORTED_PROTOCOL) { + result = CURLE_OK; + strcpy(ciphers[CURL_GSKPROTO_SSLV3].ptr, + ciphers[CURL_GSKPROTO_TLSV10].ptr); + } + } + + /* Set-up other ciphers. */ + if(!result && (*protoflags & CURL_GSKPROTO_SSLV3_MASK)) + result = set_buffer(data, h, GSK_V3_CIPHER_SPECS, + ciphers[CURL_GSKPROTO_SSLV3].buf, FALSE); + if(!result && (*protoflags & CURL_GSKPROTO_SSLV2_MASK)) + result = set_buffer(data, h, GSK_V2_CIPHER_SPECS, + ciphers[CURL_GSKPROTO_SSLV2].buf, FALSE); + + /* Clean-up. */ + for(i = 0; i < CURL_GSKPROTO_LAST; i++) + free(ciphers[i].buf); + + return result; +} + + +static int Curl_gskit_init(void) +{ + /* No initialisation needed. */ + + return 1; +} + + +static void Curl_gskit_cleanup(void) +{ + /* Nothing to do. */ +} + + +static CURLcode init_environment(struct Curl_easy *data, + gsk_handle *envir, const char *appid, + const char *file, const char *label, + const char *password) +{ + int rc; + CURLcode result; + gsk_handle h; + + /* Creates the GSKit environment. */ + + rc = gsk_environment_open(&h); + switch(rc) { + case GSK_OK: + break; + case GSK_INSUFFICIENT_STORAGE: + return CURLE_OUT_OF_MEMORY; + default: + failf(data, "gsk_environment_open(): %s", gsk_strerror(rc)); + return CURLE_SSL_CONNECT_ERROR; + } + + result = set_enum(data, h, GSK_SESSION_TYPE, GSK_CLIENT_SESSION, FALSE); + if(!result && appid) + result = set_buffer(data, h, GSK_OS400_APPLICATION_ID, appid, FALSE); + if(!result && file) + result = set_buffer(data, h, GSK_KEYRING_FILE, file, FALSE); + if(!result && label) + result = set_buffer(data, h, GSK_KEYRING_LABEL, label, FALSE); + if(!result && password) + result = set_buffer(data, h, GSK_KEYRING_PW, password, FALSE); + + if(!result) { + /* Locate CAs, Client certificate and key according to our settings. + Note: this call may be blocking for some tenths of seconds. */ + result = gskit_status(data, gsk_environment_init(h), + "gsk_environment_init()", CURLE_SSL_CERTPROBLEM); + if(!result) { + *envir = h; + return result; + } + } + /* Error: rollback. */ + gsk_environment_close(&h); + return result; +} + + +static void cancel_async_handshake(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + Qso_OverlappedIO_t cstat; + + if(QsoCancelOperation(conn->sock[sockindex], 0) > 0) + QsoWaitForIOCompletion(BACKEND->iocport, &cstat, (struct timeval *) NULL); +} + + +static void close_async_handshake(struct ssl_connect_data *connssl) +{ + QsoDestroyIOCompletionPort(BACKEND->iocport); + BACKEND->iocport = -1; +} + +/* SSL over SSL + * Problems: + * 1) GSKit can only perform SSL on an AF_INET or AF_INET6 stream socket. To + * pipe an SSL stream into another, it is therefore needed to have a pair + * of such communicating sockets and handle the pipelining explicitly. + * 2) OS/400 socketpair() is only implemented for domain AF_UNIX, thus cannot + * be used to produce the pipeline. + * The solution is to simulate socketpair() for AF_INET with low-level API + * listen(), bind() and connect(). + */ + +static int +inetsocketpair(int sv[2]) +{ + int lfd; /* Listening socket. */ + int sfd; /* Server socket. */ + int cfd; /* Client socket. */ + int len; + struct sockaddr_in addr1; + struct sockaddr_in addr2; + + /* Create listening socket on a local dynamic port. */ + lfd = socket(AF_INET, SOCK_STREAM, 0); + if(lfd < 0) + return -1; + memset((char *) &addr1, 0, sizeof(addr1)); + addr1.sin_family = AF_INET; + addr1.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr1.sin_port = 0; + if(bind(lfd, (struct sockaddr *) &addr1, sizeof(addr1)) || + listen(lfd, 2) < 0) { + close(lfd); + return -1; + } + + /* Get the allocated port. */ + len = sizeof(addr1); + if(getsockname(lfd, (struct sockaddr *) &addr1, &len) < 0) { + close(lfd); + return -1; + } + + /* Create the client socket. */ + cfd = socket(AF_INET, SOCK_STREAM, 0); + if(cfd < 0) { + close(lfd); + return -1; + } + + /* Request unblocking connection to the listening socket. */ + curlx_nonblock(cfd, TRUE); + if(connect(cfd, (struct sockaddr *) &addr1, sizeof(addr1)) < 0 && + errno != EINPROGRESS) { + close(lfd); + close(cfd); + return -1; + } + + /* Get the client dynamic port for intrusion check below. */ + len = sizeof(addr2); + if(getsockname(cfd, (struct sockaddr *) &addr2, &len) < 0) { + close(lfd); + close(cfd); + return -1; + } + + /* Accept the incoming connection and get the server socket. */ + curlx_nonblock(lfd, TRUE); + for(;;) { + len = sizeof(addr1); + sfd = accept(lfd, (struct sockaddr *) &addr1, &len); + if(sfd < 0) { + close(lfd); + close(cfd); + return -1; + } + + /* Check for possible intrusion from an external process. */ + if(addr1.sin_addr.s_addr == addr2.sin_addr.s_addr && + addr1.sin_port == addr2.sin_port) + break; + + /* Intrusion: reject incoming connection. */ + close(sfd); + } + + /* Done, return sockets and succeed. */ + close(lfd); + curlx_nonblock(cfd, FALSE); + sv[0] = cfd; + sv[1] = sfd; + return 0; +} + +static int pipe_ssloverssl(struct connectdata *conn, int sockindex, + int directions) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_connect_data *connproxyssl = &conn->proxy_ssl[sockindex]; + fd_set fds_read; + fd_set fds_write; + int n; + int m; + int i; + int ret = 0; + struct timeval tv = {0, 0}; + char buf[CURL_MAX_WRITE_SIZE]; + + if(!connssl->use || !connproxyssl->use) + return 0; /* No SSL over SSL: OK. */ + + FD_ZERO(&fds_read); + FD_ZERO(&fds_write); + n = -1; + if(directions & SOS_READ) { + FD_SET(BACKEND->remotefd, &fds_write); + n = BACKEND->remotefd; + } + if(directions & SOS_WRITE) { + FD_SET(BACKEND->remotefd, &fds_read); + n = BACKEND->remotefd; + FD_SET(conn->sock[sockindex], &fds_write); + if(n < conn->sock[sockindex]) + n = conn->sock[sockindex]; + } + i = select(n + 1, &fds_read, &fds_write, NULL, &tv); + if(i < 0) + return -1; /* Select error. */ + + if(FD_ISSET(BACKEND->remotefd, &fds_write)) { + /* Try getting data from HTTPS proxy and pipe it upstream. */ + n = 0; + i = gsk_secure_soc_read(connproxyssl->backend->handle, + buf, sizeof(buf), &n); + switch(i) { + case GSK_OK: + if(n) { + i = write(BACKEND->remotefd, buf, n); + if(i < 0) + return -1; + ret = 1; + } + break; + case GSK_OS400_ERROR_TIMED_OUT: + case GSK_WOULD_BLOCK: + break; + default: + return -1; + } + } + + if(FD_ISSET(BACKEND->remotefd, &fds_read) && + FD_ISSET(conn->sock[sockindex], &fds_write)) { + /* Pipe data to HTTPS proxy. */ + n = read(BACKEND->remotefd, buf, sizeof(buf)); + if(n < 0) + return -1; + if(n) { + i = gsk_secure_soc_write(connproxyssl->backend->handle, buf, n, &m); + if(i != GSK_OK || n != m) + return -1; + ret = 1; + } + } + + return ret; /* OK */ +} + + +static void close_one(struct ssl_connect_data *connssl, + struct connectdata *conn, int sockindex) +{ + if(BACKEND->handle) { + gskit_status(conn->data, gsk_secure_soc_close(&BACKEND->handle), + "gsk_secure_soc_close()", 0); + /* Last chance to drain output. */ + while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0) + ; + BACKEND->handle = (gsk_handle) NULL; + if(BACKEND->localfd >= 0) { + close(BACKEND->localfd); + BACKEND->localfd = -1; + } + if(BACKEND->remotefd >= 0) { + close(BACKEND->remotefd); + BACKEND->remotefd = -1; + } + } + if(BACKEND->iocport >= 0) + close_async_handshake(connssl); +} + + +static ssize_t gskit_send(struct connectdata *conn, int sockindex, + const void *mem, size_t len, CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct Curl_easy *data = conn->data; + CURLcode cc = CURLE_SEND_ERROR; + int written; + + if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) >= 0) { + cc = gskit_status(data, + gsk_secure_soc_write(BACKEND->handle, + (char *) mem, (int) len, &written), + "gsk_secure_soc_write()", CURLE_SEND_ERROR); + if(cc == CURLE_OK) + if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) < 0) + cc = CURLE_SEND_ERROR; + } + if(cc != CURLE_OK) { + *curlcode = cc; + written = -1; + } + return (ssize_t) written; /* number of bytes */ +} + + +static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf, + size_t buffersize, CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[num]; + struct Curl_easy *data = conn->data; + int nread; + CURLcode cc = CURLE_RECV_ERROR; + + if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) { + int buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize; + cc = gskit_status(data, gsk_secure_soc_read(BACKEND->handle, + buf, buffsize, &nread), + "gsk_secure_soc_read()", CURLE_RECV_ERROR); + } + switch(cc) { + case CURLE_OK: + break; + case CURLE_OPERATION_TIMEDOUT: + cc = CURLE_AGAIN; + default: + *curlcode = cc; + nread = -1; + break; + } + return (ssize_t) nread; +} + +static CURLcode +set_ssl_version_min_max(unsigned int *protoflags, struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + long ssl_version = SSL_CONN_CONFIG(version); + long ssl_version_max = SSL_CONN_CONFIG(version_max); + long i = ssl_version; + switch(ssl_version_max) { + case CURL_SSLVERSION_MAX_NONE: + case CURL_SSLVERSION_MAX_DEFAULT: + ssl_version_max = CURL_SSLVERSION_TLSv1_2; + break; + } + for(; i <= (ssl_version_max >> 16); ++i) { + switch(i) { + case CURL_SSLVERSION_TLSv1_0: + *protoflags |= CURL_GSKPROTO_TLSV10_MASK; + break; + case CURL_SSLVERSION_TLSv1_1: + *protoflags |= CURL_GSKPROTO_TLSV11_MASK; + break; + case CURL_SSLVERSION_TLSv1_2: + *protoflags |= CURL_GSKPROTO_TLSV11_MASK; + break; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "GSKit: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; + } + } + + return CURLE_OK; +} + +static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + gsk_handle envir; + CURLcode result; + int rc; + const char * const keyringfile = SSL_CONN_CONFIG(CAfile); + const char * const keyringpwd = SSL_SET_OPTION(key_passwd); + const char * const keyringlabel = SSL_SET_OPTION(cert); + const long int ssl_version = SSL_CONN_CONFIG(version); + const bool verifypeer = SSL_CONN_CONFIG(verifypeer); + const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name: + conn->host.name; + const char *sni; + unsigned int protoflags = 0; + Qso_OverlappedIO_t commarea; + int sockpair[2]; + static const int sobufsize = CURL_MAX_WRITE_SIZE; + + /* Create SSL environment, start (preferably asynchronous) handshake. */ + + BACKEND->handle = (gsk_handle) NULL; + BACKEND->iocport = -1; + BACKEND->localfd = -1; + BACKEND->remotefd = -1; + + /* GSKit supports two ways of specifying an SSL context: either by + * application identifier (that should have been defined at the system + * level) or by keyring file, password and certificate label. + * Local certificate name (CURLOPT_SSLCERT) is used to hold either the + * application identifier of the certificate label. + * Key password (CURLOPT_KEYPASSWD) holds the keyring password. + * It is not possible to have different keyrings for the CAs and the + * local certificate. We thus use the CA file (CURLOPT_CAINFO) to identify + * the keyring file. + * If no key password is given and the keyring is the system keyring, + * application identifier mode is tried first, as recommended in IBM doc. + */ + + envir = (gsk_handle) NULL; + + if(keyringlabel && *keyringlabel && !keyringpwd && + !strcmp(keyringfile, CURL_CA_BUNDLE)) { + /* Try application identifier mode. */ + init_environment(data, &envir, keyringlabel, (const char *) NULL, + (const char *) NULL, (const char *) NULL); + } + + if(!envir) { + /* Use keyring mode. */ + result = init_environment(data, &envir, (const char *) NULL, + keyringfile, keyringlabel, keyringpwd); + if(result) + return result; + } + + /* Create secure session. */ + result = gskit_status(data, gsk_secure_soc_open(envir, &BACKEND->handle), + "gsk_secure_soc_open()", CURLE_SSL_CONNECT_ERROR); + gsk_environment_close(&envir); + if(result) + return result; + + /* Establish a pipelining socket pair for SSL over SSL. */ + if(conn->proxy_ssl[sockindex].use) { + if(inetsocketpair(sockpair)) + return CURLE_SSL_CONNECT_ERROR; + BACKEND->localfd = sockpair[0]; + BACKEND->remotefd = sockpair[1]; + setsockopt(BACKEND->localfd, SOL_SOCKET, SO_RCVBUF, + (void *) sobufsize, sizeof(sobufsize)); + setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_RCVBUF, + (void *) sobufsize, sizeof(sobufsize)); + setsockopt(BACKEND->localfd, SOL_SOCKET, SO_SNDBUF, + (void *) sobufsize, sizeof(sobufsize)); + setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_SNDBUF, + (void *) sobufsize, sizeof(sobufsize)); + curlx_nonblock(BACKEND->localfd, TRUE); + curlx_nonblock(BACKEND->remotefd, TRUE); + } + + /* Determine which SSL/TLS version should be enabled. */ + sni = hostname; + switch(ssl_version) { + case CURL_SSLVERSION_SSLv2: + protoflags = CURL_GSKPROTO_SSLV2_MASK; + sni = NULL; + break; + case CURL_SSLVERSION_SSLv3: + protoflags = CURL_GSKPROTO_SSLV3_MASK; + sni = NULL; + break; + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + protoflags = CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK; + break; + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: + result = set_ssl_version_min_max(&protoflags, conn); + if(result != CURLE_OK) + return result; + break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + + /* Process SNI. Ignore if not supported (on OS400 < V7R1). */ + if(sni) { + result = set_buffer(data, BACKEND->handle, + GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, TRUE); + if(result == CURLE_UNSUPPORTED_PROTOCOL) + result = CURLE_OK; + } + + /* Set session parameters. */ + if(!result) { + /* Compute the handshake timeout. Since GSKit granularity is 1 second, + we round up the required value. */ + long timeout = Curl_timeleft(data, NULL, TRUE); + if(timeout < 0) + result = CURLE_OPERATION_TIMEDOUT; + else + result = set_numeric(data, BACKEND->handle, GSK_HANDSHAKE_TIMEOUT, + (timeout + 999) / 1000); + } + if(!result) + result = set_numeric(data, BACKEND->handle, GSK_OS400_READ_TIMEOUT, 1); + if(!result) + result = set_numeric(data, BACKEND->handle, GSK_FD, BACKEND->localfd >= 0? + BACKEND->localfd: conn->sock[sockindex]); + if(!result) + result = set_ciphers(conn, BACKEND->handle, &protoflags); + if(!protoflags) { + failf(data, "No SSL protocol/cipher combination enabled"); + result = CURLE_SSL_CIPHER; + } + if(!result) + result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_SSLV2, + (protoflags & CURL_GSKPROTO_SSLV2_MASK)? + GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE); + if(!result) + result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_SSLV3, + (protoflags & CURL_GSKPROTO_SSLV3_MASK)? + GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE); + if(!result) + result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV1, + (protoflags & CURL_GSKPROTO_TLSV10_MASK)? + GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF, FALSE); + if(!result) { + result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV11, + (protoflags & CURL_GSKPROTO_TLSV11_MASK)? + GSK_TRUE: GSK_FALSE, TRUE); + if(result == CURLE_UNSUPPORTED_PROTOCOL) { + result = CURLE_OK; + if(protoflags == CURL_GSKPROTO_TLSV11_MASK) { + failf(data, "TLS 1.1 not yet supported"); + result = CURLE_SSL_CIPHER; + } + } + } + if(!result) { + result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV12, + (protoflags & CURL_GSKPROTO_TLSV12_MASK)? + GSK_TRUE: GSK_FALSE, TRUE); + if(result == CURLE_UNSUPPORTED_PROTOCOL) { + result = CURLE_OK; + if(protoflags == CURL_GSKPROTO_TLSV12_MASK) { + failf(data, "TLS 1.2 not yet supported"); + result = CURLE_SSL_CIPHER; + } + } + } + if(!result) + result = set_enum(data, BACKEND->handle, GSK_SERVER_AUTH_TYPE, + verifypeer? GSK_SERVER_AUTH_FULL: + GSK_SERVER_AUTH_PASSTHRU, FALSE); + + if(!result) { + /* Start handshake. Try asynchronous first. */ + memset(&commarea, 0, sizeof(commarea)); + BACKEND->iocport = QsoCreateIOCompletionPort(); + if(BACKEND->iocport != -1) { + result = gskit_status(data, + gsk_secure_soc_startInit(BACKEND->handle, + BACKEND->iocport, + &commarea), + "gsk_secure_soc_startInit()", + CURLE_SSL_CONNECT_ERROR); + if(!result) { + connssl->connecting_state = ssl_connect_2; + return CURLE_OK; + } + else + close_async_handshake(connssl); + } + else if(errno != ENOBUFS) + result = gskit_status(data, GSK_ERROR_IO, + "QsoCreateIOCompletionPort()", 0); + else if(conn->proxy_ssl[sockindex].use) { + /* Cannot pipeline while handshaking synchronously. */ + result = CURLE_SSL_CONNECT_ERROR; + } + else { + /* No more completion port available. Use synchronous IO. */ + result = gskit_status(data, gsk_secure_soc_init(BACKEND->handle), + "gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR); + if(!result) { + connssl->connecting_state = ssl_connect_3; + return CURLE_OK; + } + } + } + + /* Error: rollback. */ + close_one(connssl, conn, sockindex); + return result; +} + + +static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex, + bool nonblocking) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + Qso_OverlappedIO_t cstat; + struct timeval stmv; + CURLcode result; + + /* Poll or wait for end of SSL asynchronous handshake. */ + + for(;;) { + long timeout_ms = nonblocking? 0: Curl_timeleft(data, NULL, TRUE); + if(timeout_ms < 0) + timeout_ms = 0; + stmv.tv_sec = timeout_ms / 1000; + stmv.tv_usec = (timeout_ms - stmv.tv_sec * 1000) * 1000; + switch(QsoWaitForIOCompletion(BACKEND->iocport, &cstat, &stmv)) { + case 1: /* Operation complete. */ + break; + case -1: /* An error occurred: handshake still in progress. */ + if(errno == EINTR) { + if(nonblocking) + return CURLE_OK; + continue; /* Retry. */ + } + if(errno != ETIME) { + failf(data, "QsoWaitForIOCompletion() I/O error: %s", strerror(errno)); + cancel_async_handshake(conn, sockindex); + close_async_handshake(connssl); + return CURLE_SSL_CONNECT_ERROR; + } + /* FALL INTO... */ + case 0: /* Handshake in progress, timeout occurred. */ + if(nonblocking) + return CURLE_OK; + cancel_async_handshake(conn, sockindex); + close_async_handshake(connssl); + return CURLE_OPERATION_TIMEDOUT; + } + break; + } + result = gskit_status(data, cstat.returnValue, "SSL handshake", + CURLE_SSL_CONNECT_ERROR); + if(!result) + connssl->connecting_state = ssl_connect_3; + close_async_handshake(connssl); + return result; +} + + +static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + const gsk_cert_data_elem *cdev; + int cdec; + const gsk_cert_data_elem *p; + const char *cert = (const char *) NULL; + const char *certend; + const char *ptr; + CURLcode result; + + /* SSL handshake done: gather certificate info and verify host. */ + + if(gskit_status(data, gsk_attribute_get_cert_info(BACKEND->handle, + GSK_PARTNER_CERT_INFO, + &cdev, &cdec), + "gsk_attribute_get_cert_info()", CURLE_SSL_CONNECT_ERROR) == + CURLE_OK) { + int i; + + infof(data, "Server certificate:\n"); + p = cdev; + for(i = 0; i++ < cdec; p++) + switch(p->cert_data_id) { + case CERT_BODY_DER: + cert = p->cert_data_p; + certend = cert + cdev->cert_data_l; + break; + case CERT_DN_PRINTABLE: + infof(data, "\t subject: %.*s\n", p->cert_data_l, p->cert_data_p); + break; + case CERT_ISSUER_DN_PRINTABLE: + infof(data, "\t issuer: %.*s\n", p->cert_data_l, p->cert_data_p); + break; + case CERT_VALID_FROM: + infof(data, "\t start date: %.*s\n", p->cert_data_l, p->cert_data_p); + break; + case CERT_VALID_TO: + infof(data, "\t expire date: %.*s\n", p->cert_data_l, p->cert_data_p); + break; + } + } + + /* Verify host. */ + result = Curl_verifyhost(conn, cert, certend); + if(result) + return result; + + /* The only place GSKit can get the whole CA chain is a validation + callback where no user data pointer is available. Therefore it's not + possible to copy this chain into our structures for CAINFO. + However the server certificate may be available, thus we can return + info about it. */ + if(data->set.ssl.certinfo) { + result = Curl_ssl_init_certinfo(data, 1); + if(result) + return result; + + if(cert) { + result = Curl_extract_certinfo(conn, 0, cert, certend); + if(result) + return result; + } + } + + /* Check pinned public key. */ + ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + if(!result && ptr) { + curl_X509certificate x509; + curl_asn1Element *p; + + if(Curl_parseX509(&x509, cert, certend)) + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + p = &x509.subjectPublicKeyInfo; + result = Curl_pin_peer_pubkey(data, ptr, p->header, p->end - p->header); + if(result) { + failf(data, "SSL: public key does not match pinned public key!"); + return result; + } + } + + connssl->connecting_state = ssl_connect_done; + return CURLE_OK; +} + + +static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex, + bool nonblocking, bool *done) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + long timeout_ms; + CURLcode result = CURLE_OK; + + *done = connssl->state == ssl_connection_complete; + if(*done) + return CURLE_OK; + + /* Step 1: create session, start handshake. */ + if(connssl->connecting_state == ssl_connect_1) { + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + result = CURLE_OPERATION_TIMEDOUT; + } + else + result = gskit_connect_step1(conn, sockindex); + } + + /* Handle handshake pipelining. */ + if(!result) + if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0) + result = CURLE_SSL_CONNECT_ERROR; + + /* Step 2: check if handshake is over. */ + if(!result && connssl->connecting_state == ssl_connect_2) { + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + result = CURLE_OPERATION_TIMEDOUT; + } + else + result = gskit_connect_step2(conn, sockindex, nonblocking); + } + + /* Handle handshake pipelining. */ + if(!result) + if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0) + result = CURLE_SSL_CONNECT_ERROR; + + /* Step 3: gather certificate info, verify host. */ + if(!result && connssl->connecting_state == ssl_connect_3) + result = gskit_connect_step3(conn, sockindex); + + if(result) + close_one(connssl, conn, sockindex); + else if(connssl->connecting_state == ssl_connect_done) { + connssl->state = ssl_connection_complete; + connssl->connecting_state = ssl_connect_1; + conn->recv[sockindex] = gskit_recv; + conn->send[sockindex] = gskit_send; + *done = TRUE; + } + + return result; +} + + +static CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn, + int sockindex, bool *done) +{ + CURLcode result; + + result = gskit_connect_common(conn, sockindex, TRUE, done); + if(*done || result) + conn->ssl[sockindex].connecting_state = ssl_connect_1; + return result; +} + + +static CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex) +{ + CURLcode result; + bool done; + + conn->ssl[sockindex].connecting_state = ssl_connect_1; + result = gskit_connect_common(conn, sockindex, FALSE, &done); + if(result) + return result; + + DEBUGASSERT(done); + + return CURLE_OK; +} + + +static void Curl_gskit_close(struct connectdata *conn, int sockindex) +{ + close_one(&conn->ssl[sockindex], conn, sockindex); + close_one(&conn->proxy_ssl[sockindex], conn, sockindex); +} + + +static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct Curl_easy *data = conn->data; + int what; + int rc; + char buf[120]; + + if(!BACKEND->handle) + return 0; + +#ifndef CURL_DISABLE_FTP + if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE) + return 0; +#endif + + close_one(connssl, conn, sockindex); + rc = 0; + what = SOCKET_READABLE(conn->sock[sockindex], + SSL_SHUTDOWN_TIMEOUT); + + for(;;) { + ssize_t nread; + + if(what < 0) { + /* anything that gets here is fatally bad */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + rc = -1; + break; + } + + if(!what) { /* timeout */ + failf(data, "SSL shutdown timeout"); + break; + } + + /* Something to read, let's do it and hope that it is the close + notify alert from the server. No way to gsk_secure_soc_read() now, so + use read(). */ + + nread = read(conn->sock[sockindex], buf, sizeof(buf)); + + if(nread < 0) { + failf(data, "read: %s", strerror(errno)); + rc = -1; + } + + if(nread <= 0) + break; + + what = SOCKET_READABLE(conn->sock[sockindex], 0); + } + + return rc; +} + + +static size_t Curl_gskit_version(char *buffer, size_t size) +{ + return msnprintf(buffer, size, "GSKit"); +} + + +static int Curl_gskit_check_cxn(struct connectdata *cxn) +{ + struct ssl_connect_data *connssl = &cxn->ssl[FIRSTSOCKET]; + int err; + int errlen; + + /* The only thing that can be tested here is at the socket level. */ + + if(!BACKEND->handle) + return 0; /* connection has been closed */ + + err = 0; + errlen = sizeof(err); + + if(getsockopt(cxn->sock[FIRSTSOCKET], SOL_SOCKET, SO_ERROR, + (unsigned char *) &err, &errlen) || + errlen != sizeof(err) || err) + return 0; /* connection has been closed */ + + return -1; /* connection status unknown */ +} + +static void *Curl_gskit_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) +{ + (void)info; + return BACKEND->handle; +} + +const struct Curl_ssl Curl_ssl_gskit = { + { CURLSSLBACKEND_GSKIT, "gskit" }, /* info */ + + SSLSUPP_CERTINFO | + SSLSUPP_PINNEDPUBKEY, + + sizeof(struct ssl_backend_data), + + Curl_gskit_init, /* init */ + Curl_gskit_cleanup, /* cleanup */ + Curl_gskit_version, /* version */ + Curl_gskit_check_cxn, /* check_cxn */ + Curl_gskit_shutdown, /* shutdown */ + Curl_none_data_pending, /* data_pending */ + Curl_none_random, /* random */ + Curl_none_cert_status_request, /* cert_status_request */ + Curl_gskit_connect, /* connect */ + Curl_gskit_connect_nonblocking, /* connect_nonblocking */ + Curl_gskit_get_internals, /* get_internals */ + Curl_gskit_close, /* close_one */ + Curl_none_close_all, /* close_all */ + /* No session handling for GSKit */ + Curl_none_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ + Curl_none_md5sum, /* md5sum */ + NULL /* sha256sum */ +}; + +#endif /* USE_GSKIT */ diff --git a/dependencies/cmcurl/lib/vtls/gskit.h b/dependencies/cmcurl/lib/vtls/gskit.h new file mode 100644 index 0000000..466ee4d --- /dev/null +++ b/dependencies/cmcurl/lib/vtls/gskit.h @@ -0,0 +1,38 @@ +#ifndef HEADER_CURL_GSKIT_H +#define HEADER_CURL_GSKIT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +/* + * This header should only be needed to get included by vtls.c and gskit.c + */ + +#include "urldata.h" + +#ifdef USE_GSKIT + +extern const struct Curl_ssl Curl_ssl_gskit; + +#endif /* USE_GSKIT */ + +#endif /* HEADER_CURL_GSKIT_H */ diff --git a/dependencies/cmcurl/lib/vtls/gtls.c b/dependencies/cmcurl/lib/vtls/gtls.c new file mode 100644 index 0000000..8693cdc --- /dev/null +++ b/dependencies/cmcurl/lib/vtls/gtls.c @@ -0,0 +1,1881 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all GnuTLS-specific code for the TLS/SSL layer. No code + * but vtls.c should ever call or use these functions. + * + * Note: don't use the GnuTLS' *_t variable type names in this source code, + * since they were not present in 1.0.X. + */ + +#include "curl_setup.h" + +#ifdef USE_GNUTLS + +#include +#include +#include + +#ifdef USE_GNUTLS_NETTLE +#include +#include +#include +#else +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "inet_pton.h" +#include "gtls.h" +#include "vtls.h" +#include "parsedate.h" +#include "connect.h" /* for the connect timeout */ +#include "select.h" +#include "strcase.h" +#include "warnless.h" +#include "x509asn1.h" +#include "multiif.h" +#include "curl_printf.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* Enable GnuTLS debugging by defining GTLSDEBUG */ +/*#define GTLSDEBUG */ + +#ifdef GTLSDEBUG +static void tls_log_func(int level, const char *str) +{ + fprintf(stderr, "|<%d>| %s", level, str); +} +#endif +static bool gtls_inited = FALSE; + +#if defined(GNUTLS_VERSION_NUMBER) +# if (GNUTLS_VERSION_NUMBER >= 0x020c00) +# undef gnutls_transport_set_lowat +# define gnutls_transport_set_lowat(A,B) Curl_nop_stmt +# define USE_GNUTLS_PRIORITY_SET_DIRECT 1 +# endif +# if (GNUTLS_VERSION_NUMBER >= 0x020c03) +# define GNUTLS_MAPS_WINSOCK_ERRORS 1 +# endif + +# if HAVE_GNUTLS_ALPN_SET_PROTOCOLS +# define HAS_ALPN +# endif + +# if HAVE_GNUTLS_OCSP_REQ_INIT +# define HAS_OCSP +# endif + +# if (GNUTLS_VERSION_NUMBER >= 0x030306) +# define HAS_CAPATH +# endif +#endif + +#if (GNUTLS_VERSION_NUMBER >= 0x030603) +#define HAS_TLS13 +#endif + +#ifdef HAS_OCSP +# include +#endif + +struct ssl_backend_data { + gnutls_session_t session; + gnutls_certificate_credentials_t cred; +#ifdef USE_TLS_SRP + gnutls_srp_client_credentials_t srp_client_cred; +#endif +}; + +#define BACKEND connssl->backend + +/* + * Custom push and pull callback functions used by GNU TLS to read and write + * to the socket. These functions are simple wrappers to send() and recv() + * (although here using the sread/swrite macros as defined by + * curl_setup_once.h). + * We use custom functions rather than the GNU TLS defaults because it allows + * us to get specific about the fourth "flags" argument, and to use arbitrary + * private data with gnutls_transport_set_ptr if we wish. + * + * When these custom push and pull callbacks fail, GNU TLS checks its own + * session-specific error variable, and when not set also its own global + * errno variable, in order to take appropriate action. GNU TLS does not + * require that the transport is actually a socket. This implies that for + * Windows builds these callbacks should ideally set the session-specific + * error variable using function gnutls_transport_set_errno or as a last + * resort global errno variable using gnutls_transport_set_global_errno, + * with a transport agnostic error value. This implies that some winsock + * error translation must take place in these callbacks. + * + * Paragraph above applies to GNU TLS versions older than 2.12.3, since + * this version GNU TLS does its own internal winsock error translation + * using system_errno() function. + */ + +#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS) +# define gtls_EINTR 4 +# define gtls_EIO 5 +# define gtls_EAGAIN 11 +static int gtls_mapped_sockerrno(void) +{ + switch(SOCKERRNO) { + case WSAEWOULDBLOCK: + return gtls_EAGAIN; + case WSAEINTR: + return gtls_EINTR; + default: + break; + } + return gtls_EIO; +} +#endif + +static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len) +{ + curl_socket_t sock = *(curl_socket_t *)s; + ssize_t ret = swrite(sock, buf, len); +#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS) + if(ret < 0) + gnutls_transport_set_global_errno(gtls_mapped_sockerrno()); +#endif + return ret; +} + +static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len) +{ + curl_socket_t sock = *(curl_socket_t *)s; + ssize_t ret = sread(sock, buf, len); +#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS) + if(ret < 0) + gnutls_transport_set_global_errno(gtls_mapped_sockerrno()); +#endif + return ret; +} + +static ssize_t Curl_gtls_push_ssl(void *s, const void *buf, size_t len) +{ + return gnutls_record_send((gnutls_session_t) s, buf, len); +} + +static ssize_t Curl_gtls_pull_ssl(void *s, void *buf, size_t len) +{ + return gnutls_record_recv((gnutls_session_t) s, buf, len); +} + +/* Curl_gtls_init() + * + * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that + * are not thread-safe and thus this function itself is not thread-safe and + * must only be called from within curl_global_init() to keep the thread + * situation under control! + */ +static int Curl_gtls_init(void) +{ + int ret = 1; + if(!gtls_inited) { + ret = gnutls_global_init()?0:1; +#ifdef GTLSDEBUG + gnutls_global_set_log_function(tls_log_func); + gnutls_global_set_log_level(2); +#endif + gtls_inited = TRUE; + } + return ret; +} + +static void Curl_gtls_cleanup(void) +{ + if(gtls_inited) { + gnutls_global_deinit(); + gtls_inited = FALSE; + } +} + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static void showtime(struct Curl_easy *data, + const char *text, + time_t stamp) +{ + struct tm buffer; + const struct tm *tm = &buffer; + char str[96]; + CURLcode result = Curl_gmtime(stamp, &buffer); + if(result) + return; + + msnprintf(str, + sizeof(str), + "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT", + text, + Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], + tm->tm_mday, + Curl_month[tm->tm_mon], + tm->tm_year + 1900, + tm->tm_hour, + tm->tm_min, + tm->tm_sec); + infof(data, "%s\n", str); +} +#endif + +static gnutls_datum_t load_file(const char *file) +{ + FILE *f; + gnutls_datum_t loaded_file = { NULL, 0 }; + long filelen; + void *ptr; + + f = fopen(file, "rb"); + if(!f) + return loaded_file; + if(fseek(f, 0, SEEK_END) != 0 + || (filelen = ftell(f)) < 0 + || fseek(f, 0, SEEK_SET) != 0 + || !(ptr = malloc((size_t)filelen))) + goto out; + if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) { + free(ptr); + goto out; + } + + loaded_file.data = ptr; + loaded_file.size = (unsigned int)filelen; +out: + fclose(f); + return loaded_file; +} + +static void unload_file(gnutls_datum_t data) +{ + free(data.data); +} + + +/* this function does a SSL/TLS (re-)handshake */ +static CURLcode handshake(struct connectdata *conn, + int sockindex, + bool duringconnect, + bool nonblocking) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + gnutls_session_t session = BACKEND->session; + curl_socket_t sockfd = conn->sock[sockindex]; + + for(;;) { + time_t timeout_ms; + int rc; + + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, duringconnect); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* if ssl is expecting something, check if it's available. */ + if(connssl->connecting_state == ssl_connect_2_reading + || connssl->connecting_state == ssl_connect_2_writing) { + int what; + curl_socket_t writefd = ssl_connect_2_writing == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + curl_socket_t readfd = ssl_connect_2_reading == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + + what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, + nonblocking?0: + timeout_ms?timeout_ms:1000); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + else if(0 == what) { + if(nonblocking) + return CURLE_OK; + else if(timeout_ms) { + /* timeout */ + failf(data, "SSL connection timeout at %ld", (long)timeout_ms); + return CURLE_OPERATION_TIMEDOUT; + } + } + /* socket is readable or writable */ + } + + rc = gnutls_handshake(session); + + if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) { + connssl->connecting_state = + gnutls_record_get_direction(session)? + ssl_connect_2_writing:ssl_connect_2_reading; + continue; + } + else if((rc < 0) && !gnutls_error_is_fatal(rc)) { + const char *strerr = NULL; + + if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) { + int alert = gnutls_alert_get(session); + strerr = gnutls_alert_get_name(alert); + } + + if(strerr == NULL) + strerr = gnutls_strerror(rc); + + infof(data, "gnutls_handshake() warning: %s\n", strerr); + continue; + } + else if(rc < 0) { + const char *strerr = NULL; + + if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) { + int alert = gnutls_alert_get(session); + strerr = gnutls_alert_get_name(alert); + } + + if(strerr == NULL) + strerr = gnutls_strerror(rc); + + failf(data, "gnutls_handshake() failed: %s", strerr); + return CURLE_SSL_CONNECT_ERROR; + } + + /* Reset our connect state machine */ + connssl->connecting_state = ssl_connect_1; + return CURLE_OK; + } +} + +static gnutls_x509_crt_fmt_t do_file_type(const char *type) +{ + if(!type || !type[0]) + return GNUTLS_X509_FMT_PEM; + if(strcasecompare(type, "PEM")) + return GNUTLS_X509_FMT_PEM; + if(strcasecompare(type, "DER")) + return GNUTLS_X509_FMT_DER; + return -1; +} + +#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT +static CURLcode +set_ssl_version_min_max(int *list, size_t list_size, struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + long ssl_version = SSL_CONN_CONFIG(version); + long ssl_version_max = SSL_CONN_CONFIG(version_max); + long i = ssl_version; + long protocol_priority_idx = 0; + + switch(ssl_version_max) { + case CURL_SSLVERSION_MAX_NONE: + case CURL_SSLVERSION_MAX_DEFAULT: +#ifdef HAS_TLS13 + ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_3; +#endif + ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; + break; + } + + for(; i <= (ssl_version_max >> 16) && + protocol_priority_idx < list_size; ++i) { + switch(i) { + case CURL_SSLVERSION_TLSv1_0: + protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_0; + break; + case CURL_SSLVERSION_TLSv1_1: + protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_1; + break; + case CURL_SSLVERSION_TLSv1_2: + protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_2; + break; + case CURL_SSLVERSION_TLSv1_3: +#ifdef HAS_TLS13 + protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_3; + break; +#else + failf(data, "GnuTLS: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; +#endif + } + } + return CURLE_OK; +} +#else +#define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509" +/* If GnuTLS was compiled without support for SRP it will error out if SRP is + requested in the priority string, so treat it specially + */ +#define GNUTLS_SRP "+SRP" + +static CURLcode +set_ssl_version_min_max(const char **prioritylist, struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + long ssl_version = SSL_CONN_CONFIG(version); + long ssl_version_max = SSL_CONN_CONFIG(version_max); + + if(ssl_version_max == CURL_SSLVERSION_MAX_NONE) { + ssl_version_max = CURL_SSLVERSION_MAX_DEFAULT; + } + switch(ssl_version | ssl_version_max) { + case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.0:" GNUTLS_SRP; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_1: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.0:+VERS-TLS1.1:" GNUTLS_SRP; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_2: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2:" GNUTLS_SRP; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_1: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.1:" GNUTLS_SRP; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_2: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.1:+VERS-TLS1.2:" GNUTLS_SRP; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.2:" GNUTLS_SRP; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_TLSv1_3: +#ifdef HAS_TLS13 + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.3:" GNUTLS_SRP; + return CURLE_OK; +#else + failf(data, "GnuTLS: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; +#endif + case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_DEFAULT: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2:" +#ifdef HAS_TLS13 + "+VERS-TLS1.3:" +#endif + GNUTLS_SRP; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_DEFAULT: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.1:+VERS-TLS1.2:" +#ifdef HAS_TLS13 + "+VERS-TLS1.3:" +#endif + GNUTLS_SRP; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_DEFAULT: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.2:" +#ifdef HAS_TLS13 + "+VERS-TLS1.3:" +#endif + GNUTLS_SRP; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_DEFAULT: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.2:" +#ifdef HAS_TLS13 + "+VERS-TLS1.3:" +#endif + GNUTLS_SRP; + return CURLE_OK; + } + + failf(data, "GnuTLS: cannot set ssl protocol"); + return CURLE_SSL_CONNECT_ERROR; +} +#endif + +static CURLcode +gtls_connect_step1(struct connectdata *conn, + int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + unsigned int init_flags; + gnutls_session_t session; + int rc; + bool sni = TRUE; /* default is SNI enabled */ + void *transport_ptr = NULL; + gnutls_push_func gnutls_transport_push = NULL; + gnutls_pull_func gnutls_transport_pull = NULL; +#ifdef ENABLE_IPV6 + struct in6_addr addr; +#else + struct in_addr addr; +#endif +#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT + static const int cipher_priority[] = { + /* These two ciphers were added to GnuTLS as late as ver. 3.0.1, + but this code path is only ever used for ver. < 2.12.0. + GNUTLS_CIPHER_AES_128_GCM, + GNUTLS_CIPHER_AES_256_GCM, + */ + GNUTLS_CIPHER_AES_128_CBC, + GNUTLS_CIPHER_AES_256_CBC, + GNUTLS_CIPHER_CAMELLIA_128_CBC, + GNUTLS_CIPHER_CAMELLIA_256_CBC, + GNUTLS_CIPHER_3DES_CBC, + }; + static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 }; + int protocol_priority[] = { 0, 0, 0, 0 }; +#else + const char *prioritylist; + const char *err = NULL; +#endif + + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + + if(connssl->state == ssl_connection_complete) + /* to make us tolerant against being called more than once for the + same connection */ + return CURLE_OK; + + if(!gtls_inited) + Curl_gtls_init(); + + if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) { + failf(data, "GnuTLS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + else if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3) + sni = FALSE; /* SSLv3 has no SNI */ + + /* allocate a cred struct */ + rc = gnutls_certificate_allocate_credentials(&BACKEND->cred); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc)); + return CURLE_SSL_CONNECT_ERROR; + } + +#ifdef USE_TLS_SRP + if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) { + infof(data, "Using TLS-SRP username: %s\n", SSL_SET_OPTION(username)); + + rc = gnutls_srp_allocate_client_credentials( + &BACKEND->srp_client_cred); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "gnutls_srp_allocate_client_cred() failed: %s", + gnutls_strerror(rc)); + return CURLE_OUT_OF_MEMORY; + } + + rc = gnutls_srp_set_client_credentials(BACKEND->srp_client_cred, + SSL_SET_OPTION(username), + SSL_SET_OPTION(password)); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "gnutls_srp_set_client_cred() failed: %s", + gnutls_strerror(rc)); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + } +#endif + + if(SSL_CONN_CONFIG(CAfile)) { + /* set the trusted CA cert bundle file */ + gnutls_certificate_set_verify_flags(BACKEND->cred, + GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT); + + rc = gnutls_certificate_set_x509_trust_file(BACKEND->cred, + SSL_CONN_CONFIG(CAfile), + GNUTLS_X509_FMT_PEM); + if(rc < 0) { + infof(data, "error reading ca cert file %s (%s)\n", + SSL_CONN_CONFIG(CAfile), gnutls_strerror(rc)); + if(SSL_CONN_CONFIG(verifypeer)) + return CURLE_SSL_CACERT_BADFILE; + } + else + infof(data, "found %d certificates in %s\n", rc, + SSL_CONN_CONFIG(CAfile)); + } + +#ifdef HAS_CAPATH + if(SSL_CONN_CONFIG(CApath)) { + /* set the trusted CA cert directory */ + rc = gnutls_certificate_set_x509_trust_dir(BACKEND->cred, + SSL_CONN_CONFIG(CApath), + GNUTLS_X509_FMT_PEM); + if(rc < 0) { + infof(data, "error reading ca cert file %s (%s)\n", + SSL_CONN_CONFIG(CApath), gnutls_strerror(rc)); + if(SSL_CONN_CONFIG(verifypeer)) + return CURLE_SSL_CACERT_BADFILE; + } + else + infof(data, "found %d certificates in %s\n", + rc, SSL_CONN_CONFIG(CApath)); + } +#endif + +#ifdef CURL_CA_FALLBACK + /* use system ca certificate store as fallback */ + if(SSL_CONN_CONFIG(verifypeer) && + !(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(CApath))) { + gnutls_certificate_set_x509_system_trust(BACKEND->cred); + } +#endif + + if(SSL_SET_OPTION(CRLfile)) { + /* set the CRL list file */ + rc = gnutls_certificate_set_x509_crl_file(BACKEND->cred, + SSL_SET_OPTION(CRLfile), + GNUTLS_X509_FMT_PEM); + if(rc < 0) { + failf(data, "error reading crl file %s (%s)", + SSL_SET_OPTION(CRLfile), gnutls_strerror(rc)); + return CURLE_SSL_CRL_BADFILE; + } + else + infof(data, "found %d CRL in %s\n", + rc, SSL_SET_OPTION(CRLfile)); + } + + /* Initialize TLS session as a client */ + init_flags = GNUTLS_CLIENT; + +#if defined(GNUTLS_NO_TICKETS) + /* Disable TLS session tickets */ + init_flags |= GNUTLS_NO_TICKETS; +#endif + + rc = gnutls_init(&BACKEND->session, init_flags); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "gnutls_init() failed: %d", rc); + return CURLE_SSL_CONNECT_ERROR; + } + + /* convenient assign */ + session = BACKEND->session; + + if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) && +#ifdef ENABLE_IPV6 + (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) && +#endif + sni && + (gnutls_server_name_set(session, GNUTLS_NAME_DNS, hostname, + strlen(hostname)) < 0)) + infof(data, "WARNING: failed to configure server name indication (SNI) " + "TLS extension\n"); + + /* Use default priorities */ + rc = gnutls_set_default_priority(session); + if(rc != GNUTLS_E_SUCCESS) + return CURLE_SSL_CONNECT_ERROR; + +#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT + rc = gnutls_cipher_set_priority(session, cipher_priority); + if(rc != GNUTLS_E_SUCCESS) + return CURLE_SSL_CONNECT_ERROR; + + /* Sets the priority on the certificate types supported by gnutls. Priority + is higher for types specified before others. After specifying the types + you want, you must append a 0. */ + rc = gnutls_certificate_type_set_priority(session, cert_type_priority); + if(rc != GNUTLS_E_SUCCESS) + return CURLE_SSL_CONNECT_ERROR; + + if(SSL_CONN_CONFIG(cipher_list) != NULL) { + failf(data, "can't pass a custom cipher list to older GnuTLS" + " versions"); + return CURLE_SSL_CONNECT_ERROR; + } + + switch(SSL_CONN_CONFIG(version)) { + case CURL_SSLVERSION_SSLv3: + protocol_priority[0] = GNUTLS_SSL3; + break; + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + protocol_priority[0] = GNUTLS_TLS1_0; + protocol_priority[1] = GNUTLS_TLS1_1; + protocol_priority[2] = GNUTLS_TLS1_2; +#ifdef HAS_TLS13 + protocol_priority[3] = GNUTLS_TLS1_3; +#endif + break; + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: + { + CURLcode result = set_ssl_version_min_max(protocol_priority, + sizeof(protocol_priority)/sizeof(protocol_priority[0]), conn); + if(result != CURLE_OK) + return result; + break; + } + case CURL_SSLVERSION_SSLv2: + failf(data, "GnuTLS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + rc = gnutls_protocol_set_priority(session, protocol_priority); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "Did you pass a valid GnuTLS cipher list?"); + return CURLE_SSL_CONNECT_ERROR; + } + +#else + /* Ensure +SRP comes at the *end* of all relevant strings so that it can be + * removed if a run-time error indicates that SRP is not supported by this + * GnuTLS version */ + switch(SSL_CONN_CONFIG(version)) { + case CURL_SSLVERSION_SSLv3: + prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0"; + break; + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:" +#ifdef HAS_TLS13 + "+VERS-TLS1.3:" +#endif + GNUTLS_SRP; + break; + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: + { + CURLcode result = set_ssl_version_min_max(&prioritylist, conn); + if(result != CURLE_OK) + return result; + break; + } + case CURL_SSLVERSION_SSLv2: + failf(data, "GnuTLS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + rc = gnutls_priority_set_direct(session, prioritylist, &err); + if((rc == GNUTLS_E_INVALID_REQUEST) && err) { + if(!strcmp(err, GNUTLS_SRP)) { + /* This GnuTLS was probably compiled without support for SRP. + * Note that fact and try again without it. */ + int validprioritylen = curlx_uztosi(err - prioritylist); + char *prioritycopy = strdup(prioritylist); + if(!prioritycopy) + return CURLE_OUT_OF_MEMORY; + + infof(data, "This GnuTLS does not support SRP\n"); + if(validprioritylen) + /* Remove the :+SRP */ + prioritycopy[validprioritylen - 1] = 0; + rc = gnutls_priority_set_direct(session, prioritycopy, &err); + free(prioritycopy); + } + } + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "Error %d setting GnuTLS cipher list starting with %s", + rc, err); + return CURLE_SSL_CONNECT_ERROR; + } +#endif + +#ifdef HAS_ALPN + if(conn->bits.tls_enable_alpn) { + int cur = 0; + gnutls_datum_t protocols[2]; + +#ifdef USE_NGHTTP2 + if(data->set.httpversion >= CURL_HTTP_VERSION_2 && + (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) { + protocols[cur].data = (unsigned char *)NGHTTP2_PROTO_VERSION_ID; + protocols[cur].size = NGHTTP2_PROTO_VERSION_ID_LEN; + cur++; + infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + } +#endif + + protocols[cur].data = (unsigned char *)ALPN_HTTP_1_1; + protocols[cur].size = ALPN_HTTP_1_1_LENGTH; + cur++; + infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); + + gnutls_alpn_set_protocols(session, protocols, cur, 0); + } +#endif + + if(SSL_SET_OPTION(cert)) { + if(SSL_SET_OPTION(key_passwd)) { +#if HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2 + const unsigned int supported_key_encryption_algorithms = + GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR | + GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES | + GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 | + GNUTLS_PKCS_USE_PBES2_AES_256; + rc = gnutls_certificate_set_x509_key_file2( + BACKEND->cred, + SSL_SET_OPTION(cert), + SSL_SET_OPTION(key) ? + SSL_SET_OPTION(key) : SSL_SET_OPTION(cert), + do_file_type(SSL_SET_OPTION(cert_type)), + SSL_SET_OPTION(key_passwd), + supported_key_encryption_algorithms); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, + "error reading X.509 potentially-encrypted key file: %s", + gnutls_strerror(rc)); + return CURLE_SSL_CONNECT_ERROR; + } +#else + failf(data, "gnutls lacks support for encrypted key files"); + return CURLE_SSL_CONNECT_ERROR; +#endif + } + else { + if(gnutls_certificate_set_x509_key_file( + BACKEND->cred, + SSL_SET_OPTION(cert), + SSL_SET_OPTION(key) ? + SSL_SET_OPTION(key) : SSL_SET_OPTION(cert), + do_file_type(SSL_SET_OPTION(cert_type)) ) != + GNUTLS_E_SUCCESS) { + failf(data, "error reading X.509 key or certificate file"); + return CURLE_SSL_CONNECT_ERROR; + } + } + } + +#ifdef USE_TLS_SRP + /* put the credentials to the current session */ + if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) { + rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP, + BACKEND->srp_client_cred); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc)); + return CURLE_SSL_CONNECT_ERROR; + } + } + else +#endif + { + rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, + BACKEND->cred); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc)); + return CURLE_SSL_CONNECT_ERROR; + } + } + + if(conn->proxy_ssl[sockindex].use) { + transport_ptr = conn->proxy_ssl[sockindex].backend->session; + gnutls_transport_push = Curl_gtls_push_ssl; + gnutls_transport_pull = Curl_gtls_pull_ssl; + } + else { + /* file descriptor for the socket */ + transport_ptr = &conn->sock[sockindex]; + gnutls_transport_push = Curl_gtls_push; + gnutls_transport_pull = Curl_gtls_pull; + } + + /* set the connection handle */ + gnutls_transport_set_ptr(session, transport_ptr); + + /* register callback functions to send and receive data. */ + gnutls_transport_set_push_function(session, gnutls_transport_push); + gnutls_transport_set_pull_function(session, gnutls_transport_pull); + + /* lowat must be set to zero when using custom push and pull functions. */ + gnutls_transport_set_lowat(session, 0); + +#ifdef HAS_OCSP + if(SSL_CONN_CONFIG(verifystatus)) { + rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc); + return CURLE_SSL_CONNECT_ERROR; + } + } +#endif + + /* This might be a reconnect, so we check for a session ID in the cache + to speed up things */ + if(SSL_SET_OPTION(primary.sessionid)) { + void *ssl_sessionid; + size_t ssl_idsize; + + Curl_ssl_sessionid_lock(conn); + if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize, sockindex)) { + /* we got a session id, use it! */ + gnutls_session_set_data(session, ssl_sessionid, ssl_idsize); + + /* Informational message */ + infof(data, "SSL re-using session ID\n"); + } + Curl_ssl_sessionid_unlock(conn); + } + + return CURLE_OK; +} + +static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, + gnutls_x509_crt_t cert, + const char *pinnedpubkey) +{ + /* Scratch */ + size_t len1 = 0, len2 = 0; + unsigned char *buff1 = NULL; + + gnutls_pubkey_t key = NULL; + + /* Result is returned to caller */ + CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; + + /* if a path wasn't specified, don't pin */ + if(NULL == pinnedpubkey) + return CURLE_OK; + + if(NULL == cert) + return result; + + do { + int ret; + + /* Begin Gyrations to get the public key */ + gnutls_pubkey_init(&key); + + ret = gnutls_pubkey_import_x509(key, cert, 0); + if(ret < 0) + break; /* failed */ + + ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, NULL, &len1); + if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0) + break; /* failed */ + + buff1 = malloc(len1); + if(NULL == buff1) + break; /* failed */ + + len2 = len1; + + ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, buff1, &len2); + if(ret < 0 || len1 != len2) + break; /* failed */ + + /* End Gyrations */ + + /* The one good exit point */ + result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1); + } while(0); + + if(NULL != key) + gnutls_pubkey_deinit(key); + + Curl_safefree(buff1); + + return result; +} + +static Curl_recv gtls_recv; +static Curl_send gtls_send; + +static CURLcode +gtls_connect_step3(struct connectdata *conn, + int sockindex) +{ + unsigned int cert_list_size; + const gnutls_datum_t *chainp; + unsigned int verify_status = 0; + gnutls_x509_crt_t x509_cert, x509_issuer; + gnutls_datum_t issuerp; + char certbuf[256] = ""; /* big enough? */ + size_t size; + time_t certclock; + const char *ptr; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + gnutls_session_t session = BACKEND->session; + int rc; +#ifdef HAS_ALPN + gnutls_datum_t proto; +#endif + CURLcode result = CURLE_OK; +#ifndef CURL_DISABLE_VERBOSE_STRINGS + unsigned int algo; + unsigned int bits; + gnutls_protocol_t version = gnutls_protocol_get_version(session); +#endif + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + + /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */ + ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session), + gnutls_cipher_get(session), + gnutls_mac_get(session)); + + infof(data, "SSL connection using %s / %s\n", + gnutls_protocol_get_name(version), ptr); + + /* This function will return the peer's raw certificate (chain) as sent by + the peer. These certificates are in raw format (DER encoded for + X.509). In case of a X.509 then a certificate list may be present. The + first certificate in the list is the peer's certificate, following the + issuer's certificate, then the issuer's issuer etc. */ + + chainp = gnutls_certificate_get_peers(session, &cert_list_size); + if(!chainp) { + if(SSL_CONN_CONFIG(verifypeer) || + SSL_CONN_CONFIG(verifyhost) || + SSL_SET_OPTION(issuercert)) { +#ifdef USE_TLS_SRP + if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP + && SSL_SET_OPTION(username) != NULL + && !SSL_CONN_CONFIG(verifypeer) + && gnutls_cipher_get(session)) { + /* no peer cert, but auth is ok if we have SRP user and cipher and no + peer verify */ + } + else { +#endif + failf(data, "failed to get server cert"); + return CURLE_PEER_FAILED_VERIFICATION; +#ifdef USE_TLS_SRP + } +#endif + } + infof(data, "\t common name: WARNING couldn't obtain\n"); + } + + if(data->set.ssl.certinfo && chainp) { + unsigned int i; + + result = Curl_ssl_init_certinfo(data, cert_list_size); + if(result) + return result; + + for(i = 0; i < cert_list_size; i++) { + const char *beg = (const char *) chainp[i].data; + const char *end = beg + chainp[i].size; + + result = Curl_extract_certinfo(conn, i, beg, end); + if(result) + return result; + } + } + + if(SSL_CONN_CONFIG(verifypeer)) { + /* This function will try to verify the peer's certificate and return its + status (trusted, invalid etc.). The value of status should be one or + more of the gnutls_certificate_status_t enumerated elements bitwise + or'd. To avoid denial of service attacks some default upper limits + regarding the certificate key size and chain size are set. To override + them use gnutls_certificate_set_verify_limits(). */ + + rc = gnutls_certificate_verify_peers2(session, &verify_status); + if(rc < 0) { + failf(data, "server cert verify failed: %d", rc); + return CURLE_SSL_CONNECT_ERROR; + } + + /* verify_status is a bitmask of gnutls_certificate_status bits */ + if(verify_status & GNUTLS_CERT_INVALID) { + if(SSL_CONN_CONFIG(verifypeer)) { + failf(data, "server certificate verification failed. CAfile: %s " + "CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile): + "none", + SSL_SET_OPTION(CRLfile)?SSL_SET_OPTION(CRLfile):"none"); + return CURLE_PEER_FAILED_VERIFICATION; + } + else + infof(data, "\t server certificate verification FAILED\n"); + } + else + infof(data, "\t server certificate verification OK\n"); + } + else + infof(data, "\t server certificate verification SKIPPED\n"); + +#ifdef HAS_OCSP + if(SSL_CONN_CONFIG(verifystatus)) { + if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) { + gnutls_datum_t status_request; + gnutls_ocsp_resp_t ocsp_resp; + + gnutls_ocsp_cert_status_t status; + gnutls_x509_crl_reason_t reason; + + rc = gnutls_ocsp_status_request_get(session, &status_request); + + infof(data, "\t server certificate status verification FAILED\n"); + + if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { + failf(data, "No OCSP response received"); + return CURLE_SSL_INVALIDCERTSTATUS; + } + + if(rc < 0) { + failf(data, "Invalid OCSP response received"); + return CURLE_SSL_INVALIDCERTSTATUS; + } + + gnutls_ocsp_resp_init(&ocsp_resp); + + rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request); + if(rc < 0) { + failf(data, "Invalid OCSP response received"); + return CURLE_SSL_INVALIDCERTSTATUS; + } + + (void)gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL, + &status, NULL, NULL, NULL, &reason); + + switch(status) { + case GNUTLS_OCSP_CERT_GOOD: + break; + + case GNUTLS_OCSP_CERT_REVOKED: { + const char *crl_reason; + + switch(reason) { + default: + case GNUTLS_X509_CRLREASON_UNSPECIFIED: + crl_reason = "unspecified reason"; + break; + + case GNUTLS_X509_CRLREASON_KEYCOMPROMISE: + crl_reason = "private key compromised"; + break; + + case GNUTLS_X509_CRLREASON_CACOMPROMISE: + crl_reason = "CA compromised"; + break; + + case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED: + crl_reason = "affiliation has changed"; + break; + + case GNUTLS_X509_CRLREASON_SUPERSEDED: + crl_reason = "certificate superseded"; + break; + + case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION: + crl_reason = "operation has ceased"; + break; + + case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD: + crl_reason = "certificate is on hold"; + break; + + case GNUTLS_X509_CRLREASON_REMOVEFROMCRL: + crl_reason = "will be removed from delta CRL"; + break; + + case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN: + crl_reason = "privilege withdrawn"; + break; + + case GNUTLS_X509_CRLREASON_AACOMPROMISE: + crl_reason = "AA compromised"; + break; + } + + failf(data, "Server certificate was revoked: %s", crl_reason); + break; + } + + default: + case GNUTLS_OCSP_CERT_UNKNOWN: + failf(data, "Server certificate status is unknown"); + break; + } + + gnutls_ocsp_resp_deinit(ocsp_resp); + + return CURLE_SSL_INVALIDCERTSTATUS; + } + else + infof(data, "\t server certificate status verification OK\n"); + } + else + infof(data, "\t server certificate status verification SKIPPED\n"); +#endif + + /* initialize an X.509 certificate structure. */ + gnutls_x509_crt_init(&x509_cert); + + if(chainp) + /* convert the given DER or PEM encoded Certificate to the native + gnutls_x509_crt_t format */ + gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER); + + if(SSL_SET_OPTION(issuercert)) { + gnutls_x509_crt_init(&x509_issuer); + issuerp = load_file(SSL_SET_OPTION(issuercert)); + gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM); + rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer); + gnutls_x509_crt_deinit(x509_issuer); + unload_file(issuerp); + if(rc <= 0) { + failf(data, "server certificate issuer check failed (IssuerCert: %s)", + SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none"); + gnutls_x509_crt_deinit(x509_cert); + return CURLE_SSL_ISSUER_ERROR; + } + infof(data, "\t server certificate issuer check OK (Issuer Cert: %s)\n", + SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none"); + } + + size = sizeof(certbuf); + rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME, + 0, /* the first and only one */ + FALSE, + certbuf, + &size); + if(rc) { + infof(data, "error fetching CN from cert:%s\n", + gnutls_strerror(rc)); + } + + /* This function will check if the given certificate's subject matches the + given hostname. This is a basic implementation of the matching described + in RFC2818 (HTTPS), which takes into account wildcards, and the subject + alternative name PKIX extension. Returns non zero on success, and zero on + failure. */ + rc = gnutls_x509_crt_check_hostname(x509_cert, hostname); +#if GNUTLS_VERSION_NUMBER < 0x030306 + /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP + addresses. */ + if(!rc) { +#ifdef ENABLE_IPV6 + #define use_addr in6_addr +#else + #define use_addr in_addr +#endif + unsigned char addrbuf[sizeof(struct use_addr)]; + size_t addrlen = 0; + + if(Curl_inet_pton(AF_INET, hostname, addrbuf) > 0) + addrlen = 4; +#ifdef ENABLE_IPV6 + else if(Curl_inet_pton(AF_INET6, hostname, addrbuf) > 0) + addrlen = 16; +#endif + + if(addrlen) { + unsigned char certaddr[sizeof(struct use_addr)]; + int i; + + for(i = 0; ; i++) { + size_t certaddrlen = sizeof(certaddr); + int ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr, + &certaddrlen, NULL); + /* If this happens, it wasn't an IP address. */ + if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER) + continue; + if(ret < 0) + break; + if(ret != GNUTLS_SAN_IPADDRESS) + continue; + if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) { + rc = 1; + break; + } + } + } + } +#endif + if(!rc) { + const char * const dispname = SSL_IS_PROXY() ? + conn->http_proxy.host.dispname : conn->host.dispname; + + if(SSL_CONN_CONFIG(verifyhost)) { + failf(data, "SSL: certificate subject name (%s) does not match " + "target host name '%s'", certbuf, dispname); + gnutls_x509_crt_deinit(x509_cert); + return CURLE_PEER_FAILED_VERIFICATION; + } + else + infof(data, "\t common name: %s (does not match '%s')\n", + certbuf, dispname); + } + else + infof(data, "\t common name: %s (matched)\n", certbuf); + + /* Check for time-based validity */ + certclock = gnutls_x509_crt_get_expiration_time(x509_cert); + + if(certclock == (time_t)-1) { + if(SSL_CONN_CONFIG(verifypeer)) { + failf(data, "server cert expiration date verify failed"); + gnutls_x509_crt_deinit(x509_cert); + return CURLE_SSL_CONNECT_ERROR; + } + else + infof(data, "\t server certificate expiration date verify FAILED\n"); + } + else { + if(certclock < time(NULL)) { + if(SSL_CONN_CONFIG(verifypeer)) { + failf(data, "server certificate expiration date has passed."); + gnutls_x509_crt_deinit(x509_cert); + return CURLE_PEER_FAILED_VERIFICATION; + } + else + infof(data, "\t server certificate expiration date FAILED\n"); + } + else + infof(data, "\t server certificate expiration date OK\n"); + } + + certclock = gnutls_x509_crt_get_activation_time(x509_cert); + + if(certclock == (time_t)-1) { + if(SSL_CONN_CONFIG(verifypeer)) { + failf(data, "server cert activation date verify failed"); + gnutls_x509_crt_deinit(x509_cert); + return CURLE_SSL_CONNECT_ERROR; + } + else + infof(data, "\t server certificate activation date verify FAILED\n"); + } + else { + if(certclock > time(NULL)) { + if(SSL_CONN_CONFIG(verifypeer)) { + failf(data, "server certificate not activated yet."); + gnutls_x509_crt_deinit(x509_cert); + return CURLE_PEER_FAILED_VERIFICATION; + } + else + infof(data, "\t server certificate activation date FAILED\n"); + } + else + infof(data, "\t server certificate activation date OK\n"); + } + + ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + if(ptr) { + result = pkp_pin_peer_pubkey(data, x509_cert, ptr); + if(result != CURLE_OK) { + failf(data, "SSL: public key does not match pinned public key!"); + gnutls_x509_crt_deinit(x509_cert); + return result; + } + } + + /* Show: + + - subject + - start date + - expire date + - common name + - issuer + + */ + +#ifndef CURL_DISABLE_VERBOSE_STRINGS + /* public key algorithm's parameters */ + algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits); + infof(data, "\t certificate public key: %s\n", + gnutls_pk_algorithm_get_name(algo)); + + /* version of the X.509 certificate. */ + infof(data, "\t certificate version: #%d\n", + gnutls_x509_crt_get_version(x509_cert)); + + + size = sizeof(certbuf); + gnutls_x509_crt_get_dn(x509_cert, certbuf, &size); + infof(data, "\t subject: %s\n", certbuf); + + certclock = gnutls_x509_crt_get_activation_time(x509_cert); + showtime(data, "start date", certclock); + + certclock = gnutls_x509_crt_get_expiration_time(x509_cert); + showtime(data, "expire date", certclock); + + size = sizeof(certbuf); + gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size); + infof(data, "\t issuer: %s\n", certbuf); +#endif + + gnutls_x509_crt_deinit(x509_cert); + +#ifdef HAS_ALPN + if(conn->bits.tls_enable_alpn) { + rc = gnutls_alpn_get_selected_protocol(session, &proto); + if(rc == 0) { + infof(data, "ALPN, server accepted to use %.*s\n", proto.size, + proto.data); + +#ifdef USE_NGHTTP2 + if(proto.size == NGHTTP2_PROTO_VERSION_ID_LEN && + !memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data, + NGHTTP2_PROTO_VERSION_ID_LEN)) { + conn->negnpn = CURL_HTTP_VERSION_2; + } + else +#endif + if(proto.size == ALPN_HTTP_1_1_LENGTH && + !memcmp(ALPN_HTTP_1_1, proto.data, ALPN_HTTP_1_1_LENGTH)) { + conn->negnpn = CURL_HTTP_VERSION_1_1; + } + } + else + infof(data, "ALPN, server did not agree to a protocol\n"); + + Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); + } +#endif + + conn->ssl[sockindex].state = ssl_connection_complete; + conn->recv[sockindex] = gtls_recv; + conn->send[sockindex] = gtls_send; + + if(SSL_SET_OPTION(primary.sessionid)) { + /* we always unconditionally get the session id here, as even if we + already got it from the cache and asked to use it in the connection, it + might've been rejected and then a new one is in use now and we need to + detect that. */ + void *connect_sessionid; + size_t connect_idsize = 0; + + /* get the session ID data size */ + gnutls_session_get_data(session, NULL, &connect_idsize); + connect_sessionid = malloc(connect_idsize); /* get a buffer for it */ + + if(connect_sessionid) { + bool incache; + void *ssl_sessionid; + + /* extract session ID to the allocated buffer */ + gnutls_session_get_data(session, connect_sessionid, &connect_idsize); + + Curl_ssl_sessionid_lock(conn); + incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, + sockindex)); + if(incache) { + /* there was one before in the cache, so instead of risking that the + previous one was rejected, we just kill that and store the new */ + Curl_ssl_delsessionid(conn, ssl_sessionid); + } + + /* store this session id */ + result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize, + sockindex); + Curl_ssl_sessionid_unlock(conn); + if(result) { + free(connect_sessionid); + result = CURLE_OUT_OF_MEMORY; + } + } + else + result = CURLE_OUT_OF_MEMORY; + } + + return result; +} + + +/* + * This function is called after the TCP connect has completed. Setup the TLS + * layer and do all necessary magic. + */ +/* We use connssl->connecting_state to keep track of the connection status; + there are three states: 'ssl_connect_1' (not started yet or complete), + 'ssl_connect_2_reading' (waiting for data from server), and + 'ssl_connect_2_writing' (waiting to be able to write). + */ +static CURLcode +gtls_connect_common(struct connectdata *conn, + int sockindex, + bool nonblocking, + bool *done) +{ + int rc; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + /* Initiate the connection, if not already done */ + if(ssl_connect_1 == connssl->connecting_state) { + rc = gtls_connect_step1(conn, sockindex); + if(rc) + return rc; + } + + rc = handshake(conn, sockindex, TRUE, nonblocking); + if(rc) + /* handshake() sets its own error message with failf() */ + return rc; + + /* Finish connecting once the handshake is done */ + if(ssl_connect_1 == connssl->connecting_state) { + rc = gtls_connect_step3(conn, sockindex); + if(rc) + return rc; + } + + *done = ssl_connect_1 == connssl->connecting_state; + + return CURLE_OK; +} + +static CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn, + int sockindex, bool *done) +{ + return gtls_connect_common(conn, sockindex, TRUE, done); +} + +static CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex) +{ + CURLcode result; + bool done = FALSE; + + result = gtls_connect_common(conn, sockindex, FALSE, &done); + if(result) + return result; + + DEBUGASSERT(done); + + return CURLE_OK; +} + +static bool Curl_gtls_data_pending(const struct connectdata *conn, + int connindex) +{ + const struct ssl_connect_data *connssl = &conn->ssl[connindex]; + bool res = FALSE; + if(BACKEND->session && + 0 != gnutls_record_check_pending(BACKEND->session)) + res = TRUE; + + connssl = &conn->proxy_ssl[connindex]; + if(BACKEND->session && + 0 != gnutls_record_check_pending(BACKEND->session)) + res = TRUE; + + return res; +} + +static ssize_t gtls_send(struct connectdata *conn, + int sockindex, + const void *mem, + size_t len, + CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + ssize_t rc = gnutls_record_send(BACKEND->session, mem, len); + + if(rc < 0) { + *curlcode = (rc == GNUTLS_E_AGAIN) + ? CURLE_AGAIN + : CURLE_SEND_ERROR; + + rc = -1; + } + + return rc; +} + +static void close_one(struct ssl_connect_data *connssl) +{ + if(BACKEND->session) { + gnutls_bye(BACKEND->session, GNUTLS_SHUT_RDWR); + gnutls_deinit(BACKEND->session); + BACKEND->session = NULL; + } + if(BACKEND->cred) { + gnutls_certificate_free_credentials(BACKEND->cred); + BACKEND->cred = NULL; + } +#ifdef USE_TLS_SRP + if(BACKEND->srp_client_cred) { + gnutls_srp_free_client_credentials(BACKEND->srp_client_cred); + BACKEND->srp_client_cred = NULL; + } +#endif +} + +static void Curl_gtls_close(struct connectdata *conn, int sockindex) +{ + close_one(&conn->ssl[sockindex]); + close_one(&conn->proxy_ssl[sockindex]); +} + +/* + * This function is called to shut down the SSL layer but keep the + * socket open (CCC - Clear Command Channel) + */ +static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + int retval = 0; + struct Curl_easy *data = conn->data; + +#ifndef CURL_DISABLE_FTP + /* This has only been tested on the proftpd server, and the mod_tls code + sends a close notify alert without waiting for a close notify alert in + response. Thus we wait for a close notify alert from the server, but + we do not send one. Let's hope other servers do the same... */ + + if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) + gnutls_bye(BACKEND->session, GNUTLS_SHUT_WR); +#endif + + if(BACKEND->session) { + ssize_t result; + bool done = FALSE; + char buf[120]; + + while(!done) { + int what = SOCKET_READABLE(conn->sock[sockindex], + SSL_SHUTDOWN_TIMEOUT); + if(what > 0) { + /* Something to read, let's do it and hope that it is the close + notify alert from the server */ + result = gnutls_record_recv(BACKEND->session, + buf, sizeof(buf)); + switch(result) { + case 0: + /* This is the expected response. There was no data but only + the close notify alert */ + done = TRUE; + break; + case GNUTLS_E_AGAIN: + case GNUTLS_E_INTERRUPTED: + infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n"); + break; + default: + retval = -1; + done = TRUE; + break; + } + } + else if(0 == what) { + /* timeout */ + failf(data, "SSL shutdown timeout"); + done = TRUE; + } + else { + /* anything that gets here is fatally bad */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + retval = -1; + done = TRUE; + } + } + gnutls_deinit(BACKEND->session); + } + gnutls_certificate_free_credentials(BACKEND->cred); + +#ifdef USE_TLS_SRP + if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP + && SSL_SET_OPTION(username) != NULL) + gnutls_srp_free_client_credentials(BACKEND->srp_client_cred); +#endif + + BACKEND->cred = NULL; + BACKEND->session = NULL; + + return retval; +} + +static ssize_t gtls_recv(struct connectdata *conn, /* connection data */ + int num, /* socketindex */ + char *buf, /* store read data here */ + size_t buffersize, /* max amount to read */ + CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[num]; + ssize_t ret; + + ret = gnutls_record_recv(BACKEND->session, buf, buffersize); + if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) { + *curlcode = CURLE_AGAIN; + return -1; + } + + if(ret == GNUTLS_E_REHANDSHAKE) { + /* BLOCKING call, this is bad but a work-around for now. Fixing this "the + proper way" takes a whole lot of work. */ + CURLcode result = handshake(conn, num, FALSE, FALSE); + if(result) + /* handshake() writes error message on its own */ + *curlcode = result; + else + *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */ + return -1; + } + + if(ret < 0) { + failf(conn->data, "GnuTLS recv error (%d): %s", + + (int)ret, gnutls_strerror((int)ret)); + *curlcode = CURLE_RECV_ERROR; + return -1; + } + + return ret; +} + +static void Curl_gtls_session_free(void *ptr) +{ + free(ptr); +} + +static size_t Curl_gtls_version(char *buffer, size_t size) +{ + return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL)); +} + +#ifndef USE_GNUTLS_NETTLE +static int Curl_gtls_seed(struct Curl_easy *data) +{ + /* we have the "SSL is seeded" boolean static to prevent multiple + time-consuming seedings in vain */ + static bool ssl_seeded = FALSE; + + /* Quickly add a bit of entropy */ + gcry_fast_random_poll(); + + if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] || + data->set.str[STRING_SSL_EGDSOCKET]) { + ssl_seeded = TRUE; + } + return 0; +} +#endif + +/* data might be NULL! */ +static CURLcode Curl_gtls_random(struct Curl_easy *data, + unsigned char *entropy, size_t length) +{ +#if defined(USE_GNUTLS_NETTLE) + int rc; + (void)data; + rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length); + return rc?CURLE_FAILED_INIT:CURLE_OK; +#elif defined(USE_GNUTLS) + if(data) + Curl_gtls_seed(data); /* Initiate the seed if not already done */ + gcry_randomize(entropy, length, GCRY_STRONG_RANDOM); +#endif + return CURLE_OK; +} + +static CURLcode Curl_gtls_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len) +{ +#if defined(USE_GNUTLS_NETTLE) + struct md5_ctx MD5pw; + md5_init(&MD5pw); + md5_update(&MD5pw, (unsigned int)tmplen, tmp); + md5_digest(&MD5pw, (unsigned int)md5len, md5sum); +#elif defined(USE_GNUTLS) + gcry_md_hd_t MD5pw; + gcry_md_open(&MD5pw, GCRY_MD_MD5, 0); + gcry_md_write(MD5pw, tmp, tmplen); + memcpy(md5sum, gcry_md_read(MD5pw, 0), md5len); + gcry_md_close(MD5pw); +#endif + return CURLE_OK; +} + +static CURLcode Curl_gtls_sha256sum(const unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *sha256sum, /* output */ + size_t sha256len) +{ +#if defined(USE_GNUTLS_NETTLE) + struct sha256_ctx SHA256pw; + sha256_init(&SHA256pw); + sha256_update(&SHA256pw, (unsigned int)tmplen, tmp); + sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum); +#elif defined(USE_GNUTLS) + gcry_md_hd_t SHA256pw; + gcry_md_open(&SHA256pw, GCRY_MD_SHA256, 0); + gcry_md_write(SHA256pw, tmp, tmplen); + memcpy(sha256sum, gcry_md_read(SHA256pw, 0), sha256len); + gcry_md_close(SHA256pw); +#endif + return CURLE_OK; +} + +static bool Curl_gtls_cert_status_request(void) +{ +#ifdef HAS_OCSP + return TRUE; +#else + return FALSE; +#endif +} + +static void *Curl_gtls_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) +{ + (void)info; + return BACKEND->session; +} + +const struct Curl_ssl Curl_ssl_gnutls = { + { CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */ + + SSLSUPP_CA_PATH | + SSLSUPP_CERTINFO | + SSLSUPP_PINNEDPUBKEY | + SSLSUPP_HTTPS_PROXY, + + sizeof(struct ssl_backend_data), + + Curl_gtls_init, /* init */ + Curl_gtls_cleanup, /* cleanup */ + Curl_gtls_version, /* version */ + Curl_none_check_cxn, /* check_cxn */ + Curl_gtls_shutdown, /* shutdown */ + Curl_gtls_data_pending, /* data_pending */ + Curl_gtls_random, /* random */ + Curl_gtls_cert_status_request, /* cert_status_request */ + Curl_gtls_connect, /* connect */ + Curl_gtls_connect_nonblocking, /* connect_nonblocking */ + Curl_gtls_get_internals, /* get_internals */ + Curl_gtls_close, /* close_one */ + Curl_none_close_all, /* close_all */ + Curl_gtls_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ + Curl_gtls_md5sum, /* md5sum */ + Curl_gtls_sha256sum /* sha256sum */ +}; + +#endif /* USE_GNUTLS */ diff --git a/dependencies/cmcurl/lib/vtls/gtls.h b/dependencies/cmcurl/lib/vtls/gtls.h new file mode 100644 index 0000000..780fc10 --- /dev/null +++ b/dependencies/cmcurl/lib/vtls/gtls.h @@ -0,0 +1,34 @@ +#ifndef HEADER_CURL_GTLS_H +#define HEADER_CURL_GTLS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_GNUTLS + +#include "urldata.h" + +extern const struct Curl_ssl Curl_ssl_gnutls; + +#endif /* USE_GNUTLS */ +#endif /* HEADER_CURL_GTLS_H */ diff --git a/dependencies/cmcurl/lib/vtls/mbedtls.c b/dependencies/cmcurl/lib/vtls/mbedtls.c new file mode 100644 index 0000000..63d1f4c --- /dev/null +++ b/dependencies/cmcurl/lib/vtls/mbedtls.c @@ -0,0 +1,1086 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010 - 2011, Hoi-Ho Chan, + * Copyright (C) 2012 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all mbedTLS-specific code for the TLS/SSL layer. No code + * but vtls.c should ever call or use these functions. + * + */ + +#include "curl_setup.h" + +#ifdef USE_MBEDTLS + +#include +#if MBEDTLS_VERSION_NUMBER >= 0x02040000 +#include +#else +#include +#endif +#include +#include +#include + +#include +#include +#include +#include + +#include "urldata.h" +#include "sendf.h" +#include "inet_pton.h" +#include "mbedtls.h" +#include "vtls.h" +#include "parsedate.h" +#include "connect.h" /* for the connect timeout */ +#include "select.h" +#include "multiif.h" +#include "polarssl_threadlock.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +struct ssl_backend_data { + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_entropy_context entropy; + mbedtls_ssl_context ssl; + int server_fd; + mbedtls_x509_crt cacert; + mbedtls_x509_crt clicert; + mbedtls_x509_crl crl; + mbedtls_pk_context pk; + mbedtls_ssl_config config; + const char *protocols[3]; +}; + +#define BACKEND connssl->backend + +/* apply threading? */ +#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) +#define THREADING_SUPPORT +#endif + +#if defined(THREADING_SUPPORT) +static mbedtls_entropy_context ts_entropy; + +static int entropy_init_initialized = 0; + +/* start of entropy_init_mutex() */ +static void entropy_init_mutex(mbedtls_entropy_context *ctx) +{ + /* lock 0 = entropy_init_mutex() */ + Curl_polarsslthreadlock_lock_function(0); + if(entropy_init_initialized == 0) { + mbedtls_entropy_init(ctx); + entropy_init_initialized = 1; + } + Curl_polarsslthreadlock_unlock_function(0); +} +/* end of entropy_init_mutex() */ + +/* start of entropy_func_mutex() */ +static int entropy_func_mutex(void *data, unsigned char *output, size_t len) +{ + int ret; + /* lock 1 = entropy_func_mutex() */ + Curl_polarsslthreadlock_lock_function(1); + ret = mbedtls_entropy_func(data, output, len); + Curl_polarsslthreadlock_unlock_function(1); + + return ret; +} +/* end of entropy_func_mutex() */ + +#endif /* THREADING_SUPPORT */ + +/* Define this to enable lots of debugging for mbedTLS */ +#undef MBEDTLS_DEBUG + +#ifdef MBEDTLS_DEBUG +static void mbed_debug(void *context, int level, const char *f_name, + int line_nb, const char *line) +{ + struct Curl_easy *data = NULL; + + if(!context) + return; + + data = (struct Curl_easy *)context; + + infof(data, "%s", line); + (void) level; +} +#else +#endif + +/* ALPN for http2? */ +#ifdef USE_NGHTTP2 +# undef HAS_ALPN +# ifdef MBEDTLS_SSL_ALPN +# define HAS_ALPN +# endif +#endif + + +/* + * profile + */ +static const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr = +{ + /* Hashes from SHA-1 and above */ + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_RIPEMD160) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA224) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512), + 0xFFFFFFF, /* Any PK alg */ + 0xFFFFFFF, /* Any curve */ + 1024, /* RSA min key len */ +}; + +/* See https://tls.mbed.org/discussions/generic/ + howto-determine-exact-buffer-len-for-mbedtls_pk_write_pubkey_der +*/ +#define RSA_PUB_DER_MAX_BYTES (38 + 2 * MBEDTLS_MPI_MAX_SIZE) +#define ECP_PUB_DER_MAX_BYTES (30 + 2 * MBEDTLS_ECP_MAX_BYTES) + +#define PUB_DER_MAX_BYTES (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ + RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES) + +static Curl_recv mbed_recv; +static Curl_send mbed_send; + +static CURLcode mbedtls_version_from_curl(int *mbedver, long version) +{ + switch(version) { + case CURL_SSLVERSION_TLSv1_0: + *mbedver = MBEDTLS_SSL_MINOR_VERSION_1; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_1: + *mbedver = MBEDTLS_SSL_MINOR_VERSION_2; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_2: + *mbedver = MBEDTLS_SSL_MINOR_VERSION_3; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_3: + break; + } + return CURLE_SSL_CONNECT_ERROR; +} + +static CURLcode +set_ssl_version_min_max(struct connectdata *conn, int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_1; + int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_1; + long ssl_version = SSL_CONN_CONFIG(version); + long ssl_version_max = SSL_CONN_CONFIG(version_max); + CURLcode result = CURLE_OK; + + switch(ssl_version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + ssl_version = CURL_SSLVERSION_TLSv1_0; + break; + } + + switch(ssl_version_max) { + case CURL_SSLVERSION_MAX_NONE: + case CURL_SSLVERSION_MAX_DEFAULT: + ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; + break; + } + + result = mbedtls_version_from_curl(&mbedtls_ver_min, ssl_version); + if(result) { + failf(data, "unsupported min version passed via CURLOPT_SSLVERSION"); + return result; + } + result = mbedtls_version_from_curl(&mbedtls_ver_max, ssl_version_max >> 16); + if(result) { + failf(data, "unsupported max version passed via CURLOPT_SSLVERSION"); + return result; + } + + mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3, + mbedtls_ver_min); + mbedtls_ssl_conf_max_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3, + mbedtls_ver_max); + + return result; +} + +static CURLcode +mbed_connect_step1(struct connectdata *conn, + int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data* connssl = &conn->ssl[sockindex]; + const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); + const bool verifypeer = SSL_CONN_CONFIG(verifypeer); + const char * const ssl_capath = SSL_CONN_CONFIG(CApath); + char * const ssl_cert = SSL_SET_OPTION(cert); + const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile); + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; + int ret = -1; + char errorbuf[128]; + errorbuf[0] = 0; + + /* mbedTLS only supports SSLv3 and TLSv1 */ + if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) { + failf(data, "mbedTLS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + +#ifdef THREADING_SUPPORT + entropy_init_mutex(&ts_entropy); + mbedtls_ctr_drbg_init(&BACKEND->ctr_drbg); + + ret = mbedtls_ctr_drbg_seed(&BACKEND->ctr_drbg, entropy_func_mutex, + &ts_entropy, NULL, 0); + if(ret) { +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* MBEDTLS_ERROR_C */ + failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n", + -ret, errorbuf); + } +#else + mbedtls_entropy_init(&BACKEND->entropy); + mbedtls_ctr_drbg_init(&BACKEND->ctr_drbg); + + ret = mbedtls_ctr_drbg_seed(&BACKEND->ctr_drbg, mbedtls_entropy_func, + &BACKEND->entropy, NULL, 0); + if(ret) { +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* MBEDTLS_ERROR_C */ + failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n", + -ret, errorbuf); + } +#endif /* THREADING_SUPPORT */ + + /* Load the trusted CA */ + mbedtls_x509_crt_init(&BACKEND->cacert); + + if(ssl_cafile) { + ret = mbedtls_x509_crt_parse_file(&BACKEND->cacert, ssl_cafile); + + if(ret<0) { +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* MBEDTLS_ERROR_C */ + failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s", + ssl_cafile, -ret, errorbuf); + + if(verifypeer) + return CURLE_SSL_CACERT_BADFILE; + } + } + + if(ssl_capath) { + ret = mbedtls_x509_crt_parse_path(&BACKEND->cacert, ssl_capath); + + if(ret<0) { +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* MBEDTLS_ERROR_C */ + failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s", + ssl_capath, -ret, errorbuf); + + if(verifypeer) + return CURLE_SSL_CACERT_BADFILE; + } + } + + /* Load the client certificate */ + mbedtls_x509_crt_init(&BACKEND->clicert); + + if(ssl_cert) { + ret = mbedtls_x509_crt_parse_file(&BACKEND->clicert, ssl_cert); + + if(ret) { +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* MBEDTLS_ERROR_C */ + failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s", + ssl_cert, -ret, errorbuf); + + return CURLE_SSL_CERTPROBLEM; + } + } + + /* Load the client private key */ + mbedtls_pk_init(&BACKEND->pk); + + if(SSL_SET_OPTION(key)) { + ret = mbedtls_pk_parse_keyfile(&BACKEND->pk, SSL_SET_OPTION(key), + SSL_SET_OPTION(key_passwd)); + if(ret == 0 && !(mbedtls_pk_can_do(&BACKEND->pk, MBEDTLS_PK_RSA) || + mbedtls_pk_can_do(&BACKEND->pk, MBEDTLS_PK_ECKEY))) + ret = MBEDTLS_ERR_PK_TYPE_MISMATCH; + + if(ret) { +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* MBEDTLS_ERROR_C */ + failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s", + SSL_SET_OPTION(key), -ret, errorbuf); + + return CURLE_SSL_CERTPROBLEM; + } + } + + /* Load the CRL */ + mbedtls_x509_crl_init(&BACKEND->crl); + + if(ssl_crlfile) { + ret = mbedtls_x509_crl_parse_file(&BACKEND->crl, ssl_crlfile); + + if(ret) { +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* MBEDTLS_ERROR_C */ + failf(data, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s", + ssl_crlfile, -ret, errorbuf); + + return CURLE_SSL_CRL_BADFILE; + } + } + + infof(data, "mbedTLS: Connecting to %s:%ld\n", hostname, port); + + mbedtls_ssl_config_init(&BACKEND->config); + + mbedtls_ssl_init(&BACKEND->ssl); + if(mbedtls_ssl_setup(&BACKEND->ssl, &BACKEND->config)) { + failf(data, "mbedTLS: ssl_init failed"); + return CURLE_SSL_CONNECT_ERROR; + } + ret = mbedtls_ssl_config_defaults(&BACKEND->config, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT); + if(ret) { + failf(data, "mbedTLS: ssl_config failed"); + return CURLE_SSL_CONNECT_ERROR; + } + + /* new profile with RSA min key len = 1024 ... */ + mbedtls_ssl_conf_cert_profile(&BACKEND->config, + &mbedtls_x509_crt_profile_fr); + + switch(SSL_CONN_CONFIG(version)) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3, + MBEDTLS_SSL_MINOR_VERSION_1); + infof(data, "mbedTLS: Set min SSL version to TLS 1.0\n"); + break; + case CURL_SSLVERSION_SSLv3: + mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3, + MBEDTLS_SSL_MINOR_VERSION_0); + mbedtls_ssl_conf_max_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3, + MBEDTLS_SSL_MINOR_VERSION_0); + infof(data, "mbedTLS: Set SSL version to SSLv3\n"); + break; + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: + { + CURLcode result = set_ssl_version_min_max(conn, sockindex); + if(result != CURLE_OK) + return result; + break; + } + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + + mbedtls_ssl_conf_authmode(&BACKEND->config, MBEDTLS_SSL_VERIFY_OPTIONAL); + + mbedtls_ssl_conf_rng(&BACKEND->config, mbedtls_ctr_drbg_random, + &BACKEND->ctr_drbg); + mbedtls_ssl_set_bio(&BACKEND->ssl, &conn->sock[sockindex], + mbedtls_net_send, + mbedtls_net_recv, + NULL /* rev_timeout() */); + + mbedtls_ssl_conf_ciphersuites(&BACKEND->config, + mbedtls_ssl_list_ciphersuites()); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + mbedtls_ssl_conf_renegotiation(&BACKEND->config, + MBEDTLS_SSL_RENEGOTIATION_ENABLED); +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + mbedtls_ssl_conf_session_tickets(&BACKEND->config, + MBEDTLS_SSL_SESSION_TICKETS_DISABLED); +#endif + + /* Check if there's a cached ID we can/should use here! */ + if(SSL_SET_OPTION(primary.sessionid)) { + void *old_session = NULL; + + Curl_ssl_sessionid_lock(conn); + if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) { + ret = mbedtls_ssl_set_session(&BACKEND->ssl, old_session); + if(ret) { + Curl_ssl_sessionid_unlock(conn); + failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret); + return CURLE_SSL_CONNECT_ERROR; + } + infof(data, "mbedTLS re-using session\n"); + } + Curl_ssl_sessionid_unlock(conn); + } + + mbedtls_ssl_conf_ca_chain(&BACKEND->config, + &BACKEND->cacert, + &BACKEND->crl); + + if(SSL_SET_OPTION(key)) { + mbedtls_ssl_conf_own_cert(&BACKEND->config, + &BACKEND->clicert, &BACKEND->pk); + } + if(mbedtls_ssl_set_hostname(&BACKEND->ssl, hostname)) { + /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks *and* + the name to set in the SNI extension. So even if curl connects to a + host specified as an IP address, this function must be used. */ + failf(data, "couldn't set hostname in mbedTLS"); + return CURLE_SSL_CONNECT_ERROR; + } + +#ifdef HAS_ALPN + if(conn->bits.tls_enable_alpn) { + const char **p = &BACKEND->protocols[0]; +#ifdef USE_NGHTTP2 + if(data->set.httpversion >= CURL_HTTP_VERSION_2) + *p++ = NGHTTP2_PROTO_VERSION_ID; +#endif + *p++ = ALPN_HTTP_1_1; + *p = NULL; + /* this function doesn't clone the protocols array, which is why we need + to keep it around */ + if(mbedtls_ssl_conf_alpn_protocols(&BACKEND->config, + &BACKEND->protocols[0])) { + failf(data, "Failed setting ALPN protocols"); + return CURLE_SSL_CONNECT_ERROR; + } + for(p = &BACKEND->protocols[0]; *p; ++p) + infof(data, "ALPN, offering %s\n", *p); + } +#endif + +#ifdef MBEDTLS_DEBUG + /* In order to make that work in mbedtls MBEDTLS_DEBUG_C must be defined. */ + mbedtls_ssl_conf_dbg(&BACKEND->config, mbed_debug, data); + /* - 0 No debug + * - 1 Error + * - 2 State change + * - 3 Informational + * - 4 Verbose + */ + mbedtls_debug_set_threshold(4); +#endif + + /* give application a chance to interfere with mbedTLS set up. */ + if(data->set.ssl.fsslctx) { + ret = (*data->set.ssl.fsslctx)(data, &BACKEND->config, + data->set.ssl.fsslctxp); + if(ret) { + failf(data, "error signaled by ssl ctx callback"); + return ret; + } + } + + connssl->connecting_state = ssl_connect_2; + + return CURLE_OK; +} + +static CURLcode +mbed_connect_step2(struct connectdata *conn, + int sockindex) +{ + int ret; + struct Curl_easy *data = conn->data; + struct ssl_connect_data* connssl = &conn->ssl[sockindex]; + const mbedtls_x509_crt *peercert; + const char * const pinnedpubkey = SSL_IS_PROXY() ? + data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + + conn->recv[sockindex] = mbed_recv; + conn->send[sockindex] = mbed_send; + + ret = mbedtls_ssl_handshake(&BACKEND->ssl); + + if(ret == MBEDTLS_ERR_SSL_WANT_READ) { + connssl->connecting_state = ssl_connect_2_reading; + return CURLE_OK; + } + else if(ret == MBEDTLS_ERR_SSL_WANT_WRITE) { + connssl->connecting_state = ssl_connect_2_writing; + return CURLE_OK; + } + else if(ret) { + char errorbuf[128]; + errorbuf[0] = 0; +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* MBEDTLS_ERROR_C */ + failf(data, "ssl_handshake returned - mbedTLS: (-0x%04X) %s", + -ret, errorbuf); + return CURLE_SSL_CONNECT_ERROR; + } + + infof(data, "mbedTLS: Handshake complete, cipher is %s\n", + mbedtls_ssl_get_ciphersuite(&BACKEND->ssl) + ); + + ret = mbedtls_ssl_get_verify_result(&BACKEND->ssl); + + if(!SSL_CONN_CONFIG(verifyhost)) + /* Ignore hostname errors if verifyhost is disabled */ + ret &= ~MBEDTLS_X509_BADCERT_CN_MISMATCH; + + if(ret && SSL_CONN_CONFIG(verifypeer)) { + if(ret & MBEDTLS_X509_BADCERT_EXPIRED) + failf(data, "Cert verify failed: BADCERT_EXPIRED"); + + else if(ret & MBEDTLS_X509_BADCERT_REVOKED) + failf(data, "Cert verify failed: BADCERT_REVOKED"); + + else if(ret & MBEDTLS_X509_BADCERT_CN_MISMATCH) + failf(data, "Cert verify failed: BADCERT_CN_MISMATCH"); + + else if(ret & MBEDTLS_X509_BADCERT_NOT_TRUSTED) + failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED"); + + return CURLE_PEER_FAILED_VERIFICATION; + } + + peercert = mbedtls_ssl_get_peer_cert(&BACKEND->ssl); + + if(peercert && data->set.verbose) { + const size_t bufsize = 16384; + char *buffer = malloc(bufsize); + + if(!buffer) + return CURLE_OUT_OF_MEMORY; + + if(mbedtls_x509_crt_info(buffer, bufsize, "* ", peercert) > 0) + infof(data, "Dumping cert info:\n%s\n", buffer); + else + infof(data, "Unable to dump certificate information.\n"); + + free(buffer); + } + + if(pinnedpubkey) { + int size; + CURLcode result; + mbedtls_x509_crt *p; + unsigned char pubkey[PUB_DER_MAX_BYTES]; + + if(!peercert || !peercert->raw.p || !peercert->raw.len) { + failf(data, "Failed due to missing peer certificate"); + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + } + + p = calloc(1, sizeof(*p)); + + if(!p) + return CURLE_OUT_OF_MEMORY; + + mbedtls_x509_crt_init(p); + + /* Make a copy of our const peercert because mbedtls_pk_write_pubkey_der + needs a non-const key, for now. + https://github.com/ARMmbed/mbedtls/issues/396 */ + if(mbedtls_x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) { + failf(data, "Failed copying peer certificate"); + mbedtls_x509_crt_free(p); + free(p); + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + } + + size = mbedtls_pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES); + + if(size <= 0) { + failf(data, "Failed copying public key from peer certificate"); + mbedtls_x509_crt_free(p); + free(p); + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + } + + /* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */ + result = Curl_pin_peer_pubkey(data, + pinnedpubkey, + &pubkey[PUB_DER_MAX_BYTES - size], size); + if(result) { + mbedtls_x509_crt_free(p); + free(p); + return result; + } + + mbedtls_x509_crt_free(p); + free(p); + } + +#ifdef HAS_ALPN + if(conn->bits.tls_enable_alpn) { + const char *next_protocol = mbedtls_ssl_get_alpn_protocol(&BACKEND->ssl); + + if(next_protocol) { + infof(data, "ALPN, server accepted to use %s\n", next_protocol); +#ifdef USE_NGHTTP2 + if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID, + NGHTTP2_PROTO_VERSION_ID_LEN) && + !next_protocol[NGHTTP2_PROTO_VERSION_ID_LEN]) { + conn->negnpn = CURL_HTTP_VERSION_2; + } + else +#endif + if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH) && + !next_protocol[ALPN_HTTP_1_1_LENGTH]) { + conn->negnpn = CURL_HTTP_VERSION_1_1; + } + } + else { + infof(data, "ALPN, server did not agree to a protocol\n"); + } + Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); + } +#endif + + connssl->connecting_state = ssl_connect_3; + infof(data, "SSL connected\n"); + + return CURLE_OK; +} + +static CURLcode +mbed_connect_step3(struct connectdata *conn, + int sockindex) +{ + CURLcode retcode = CURLE_OK; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct Curl_easy *data = conn->data; + + DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); + + if(SSL_SET_OPTION(primary.sessionid)) { + int ret; + mbedtls_ssl_session *our_ssl_sessionid; + void *old_ssl_sessionid = NULL; + + our_ssl_sessionid = malloc(sizeof(mbedtls_ssl_session)); + if(!our_ssl_sessionid) + return CURLE_OUT_OF_MEMORY; + + mbedtls_ssl_session_init(our_ssl_sessionid); + + ret = mbedtls_ssl_get_session(&BACKEND->ssl, our_ssl_sessionid); + if(ret) { + if(ret != MBEDTLS_ERR_SSL_ALLOC_FAILED) + mbedtls_ssl_session_free(our_ssl_sessionid); + free(our_ssl_sessionid); + failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret); + return CURLE_SSL_CONNECT_ERROR; + } + + /* If there's already a matching session in the cache, delete it */ + Curl_ssl_sessionid_lock(conn); + if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex)) + Curl_ssl_delsessionid(conn, old_ssl_sessionid); + + retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex); + Curl_ssl_sessionid_unlock(conn); + if(retcode) { + mbedtls_ssl_session_free(our_ssl_sessionid); + free(our_ssl_sessionid); + failf(data, "failed to store ssl session"); + return retcode; + } + } + + connssl->connecting_state = ssl_connect_done; + + return CURLE_OK; +} + +static ssize_t mbed_send(struct connectdata *conn, int sockindex, + const void *mem, size_t len, + CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + int ret = -1; + + ret = mbedtls_ssl_write(&BACKEND->ssl, + (unsigned char *)mem, len); + + if(ret < 0) { + *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_WRITE) ? + CURLE_AGAIN : CURLE_SEND_ERROR; + ret = -1; + } + + return ret; +} + +static void Curl_mbedtls_close_all(struct Curl_easy *data) +{ + (void)data; +} + +static void Curl_mbedtls_close(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + mbedtls_pk_free(&BACKEND->pk); + mbedtls_x509_crt_free(&BACKEND->clicert); + mbedtls_x509_crt_free(&BACKEND->cacert); + mbedtls_x509_crl_free(&BACKEND->crl); + mbedtls_ssl_config_free(&BACKEND->config); + mbedtls_ssl_free(&BACKEND->ssl); + mbedtls_ctr_drbg_free(&BACKEND->ctr_drbg); +#ifndef THREADING_SUPPORT + mbedtls_entropy_free(&BACKEND->entropy); +#endif /* THREADING_SUPPORT */ +} + +static ssize_t mbed_recv(struct connectdata *conn, int num, + char *buf, size_t buffersize, + CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[num]; + int ret = -1; + ssize_t len = -1; + + memset(buf, 0, buffersize); + ret = mbedtls_ssl_read(&BACKEND->ssl, (unsigned char *)buf, + buffersize); + + if(ret <= 0) { + if(ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) + return 0; + + *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_READ) ? + CURLE_AGAIN : CURLE_RECV_ERROR; + return -1; + } + + len = ret; + + return len; +} + +static void Curl_mbedtls_session_free(void *ptr) +{ + mbedtls_ssl_session_free(ptr); + free(ptr); +} + +static size_t Curl_mbedtls_version(char *buffer, size_t size) +{ +#ifdef MBEDTLS_VERSION_C + /* if mbedtls_version_get_number() is available it is better */ + unsigned int version = mbedtls_version_get_number(); + return msnprintf(buffer, size, "mbedTLS/%u.%u.%u", version>>24, + (version>>16)&0xff, (version>>8)&0xff); +#else + return msnprintf(buffer, size, "mbedTLS/%s", MBEDTLS_VERSION_STRING); +#endif +} + +static CURLcode Curl_mbedtls_random(struct Curl_easy *data, + unsigned char *entropy, size_t length) +{ +#if defined(MBEDTLS_CTR_DRBG_C) + int ret = -1; + char errorbuf[128]; + mbedtls_entropy_context ctr_entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_entropy_init(&ctr_entropy); + mbedtls_ctr_drbg_init(&ctr_drbg); + errorbuf[0] = 0; + + ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, + &ctr_entropy, NULL, 0); + + if(ret) { +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* MBEDTLS_ERROR_C */ + failf(data, "Failed - mbedTLS: ctr_drbg_seed returned (-0x%04X) %s\n", + -ret, errorbuf); + } + else { + ret = mbedtls_ctr_drbg_random(&ctr_drbg, entropy, length); + + if(ret) { +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* MBEDTLS_ERROR_C */ + failf(data, "mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n", + -ret, errorbuf); + } + } + + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&ctr_entropy); + + return ret == 0 ? CURLE_OK : CURLE_FAILED_INIT; +#elif defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_state hs; + mbedtls_havege_init(&hs); + mbedtls_havege_random(&hs, entropy, length); + mbedtls_havege_free(&hs); + return CURLE_OK; +#else + return CURLE_NOT_BUILT_IN; +#endif +} + +static CURLcode +mbed_connect_common(struct connectdata *conn, + int sockindex, + bool nonblocking, + bool *done) +{ + CURLcode retcode; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + long timeout_ms; + int what; + + /* check if the connection has already been established */ + if(ssl_connection_complete == connssl->state) { + *done = TRUE; + return CURLE_OK; + } + + if(ssl_connect_1 == connssl->connecting_state) { + /* Find out how much more time we're allowed */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + retcode = mbed_connect_step1(conn, sockindex); + if(retcode) + return retcode; + } + + while(ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state) { + + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* if ssl is expecting something, check if it's available. */ + if(connssl->connecting_state == ssl_connect_2_reading + || connssl->connecting_state == ssl_connect_2_writing) { + + curl_socket_t writefd = ssl_connect_2_writing == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + curl_socket_t readfd = ssl_connect_2_reading == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + + what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, + nonblocking ? 0 : timeout_ms); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + else if(0 == what) { + if(nonblocking) { + *done = FALSE; + return CURLE_OK; + } + else { + /* timeout */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + } + /* socket is readable or writable */ + } + + /* Run transaction, and return to the caller if it failed or if + * this connection is part of a multi handle and this loop would + * execute again. This permits the owner of a multi handle to + * abort a connection attempt before step2 has completed while + * ensuring that a client using select() or epoll() will always + * have a valid fdset to wait on. + */ + retcode = mbed_connect_step2(conn, sockindex); + if(retcode || (nonblocking && + (ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state))) + return retcode; + + } /* repeat step2 until all transactions are done. */ + + if(ssl_connect_3 == connssl->connecting_state) { + retcode = mbed_connect_step3(conn, sockindex); + if(retcode) + return retcode; + } + + if(ssl_connect_done == connssl->connecting_state) { + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = mbed_recv; + conn->send[sockindex] = mbed_send; + *done = TRUE; + } + else + *done = FALSE; + + /* Reset our connect state machine */ + connssl->connecting_state = ssl_connect_1; + + return CURLE_OK; +} + +static CURLcode Curl_mbedtls_connect_nonblocking(struct connectdata *conn, + int sockindex, bool *done) +{ + return mbed_connect_common(conn, sockindex, TRUE, done); +} + + +static CURLcode Curl_mbedtls_connect(struct connectdata *conn, int sockindex) +{ + CURLcode retcode; + bool done = FALSE; + + retcode = mbed_connect_common(conn, sockindex, FALSE, &done); + if(retcode) + return retcode; + + DEBUGASSERT(done); + + return CURLE_OK; +} + +/* + * return 0 error initializing SSL + * return 1 SSL initialized successfully + */ +static int Curl_mbedtls_init(void) +{ + return Curl_polarsslthreadlock_thread_setup(); +} + +static void Curl_mbedtls_cleanup(void) +{ + (void)Curl_polarsslthreadlock_thread_cleanup(); +} + +static bool Curl_mbedtls_data_pending(const struct connectdata *conn, + int sockindex) +{ + const struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + return mbedtls_ssl_get_bytes_avail(&BACKEND->ssl) != 0; +} + +static CURLcode Curl_mbedtls_sha256sum(const unsigned char *input, + size_t inputlen, + unsigned char *sha256sum, + size_t sha256len UNUSED_PARAM) +{ + (void)sha256len; +#if MBEDTLS_VERSION_NUMBER < 0x02070000 + mbedtls_sha256(input, inputlen, sha256sum, 0); +#else + /* returns 0 on success, otherwise failure */ + if(mbedtls_sha256_ret(input, inputlen, sha256sum, 0) != 0) + return CURLE_BAD_FUNCTION_ARGUMENT; +#endif + return CURLE_OK; +} + +static void *Curl_mbedtls_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) +{ + (void)info; + return &BACKEND->ssl; +} + +const struct Curl_ssl Curl_ssl_mbedtls = { + { CURLSSLBACKEND_MBEDTLS, "mbedtls" }, /* info */ + + SSLSUPP_CA_PATH | + SSLSUPP_PINNEDPUBKEY | + SSLSUPP_SSL_CTX, + + sizeof(struct ssl_backend_data), + + Curl_mbedtls_init, /* init */ + Curl_mbedtls_cleanup, /* cleanup */ + Curl_mbedtls_version, /* version */ + Curl_none_check_cxn, /* check_cxn */ + Curl_none_shutdown, /* shutdown */ + Curl_mbedtls_data_pending, /* data_pending */ + Curl_mbedtls_random, /* random */ + Curl_none_cert_status_request, /* cert_status_request */ + Curl_mbedtls_connect, /* connect */ + Curl_mbedtls_connect_nonblocking, /* connect_nonblocking */ + Curl_mbedtls_get_internals, /* get_internals */ + Curl_mbedtls_close, /* close_one */ + Curl_mbedtls_close_all, /* close_all */ + Curl_mbedtls_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ + Curl_none_md5sum, /* md5sum */ + Curl_mbedtls_sha256sum /* sha256sum */ +}; + +#endif /* USE_MBEDTLS */ diff --git a/dependencies/cmcurl/lib/vtls/mbedtls.h b/dependencies/cmcurl/lib/vtls/mbedtls.h new file mode 100644 index 0000000..4a93860 --- /dev/null +++ b/dependencies/cmcurl/lib/vtls/mbedtls.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_MBEDTLS_H +#define HEADER_CURL_MBEDTLS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 2010, Hoi-Ho Chan, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_MBEDTLS + +extern const struct Curl_ssl Curl_ssl_mbedtls; + +#endif /* USE_MBEDTLS */ +#endif /* HEADER_CURL_MBEDTLS_H */ diff --git a/dependencies/cmcurl/lib/vtls/mesalink.c b/dependencies/cmcurl/lib/vtls/mesalink.c new file mode 100644 index 0000000..718c282 --- /dev/null +++ b/dependencies/cmcurl/lib/vtls/mesalink.c @@ -0,0 +1,627 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2017 - 2018, Yiming Jing, + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all MesaLink-specific code for the TLS/SSL layer. No code + * but vtls.c should ever call or use these functions. + * + */ + +/* + * Based upon the CyaSSL implementation in cyassl.c and cyassl.h: + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * Thanks for code and inspiration! + */ + +#include "curl_setup.h" + +#ifdef USE_MESALINK + +#include +#include + +#include "urldata.h" +#include "sendf.h" +#include "inet_pton.h" +#include "vtls.h" +#include "parsedate.h" +#include "connect.h" /* for the connect timeout */ +#include "select.h" +#include "strcase.h" +#include "x509asn1.h" +#include "curl_printf.h" + +#include "mesalink.h" +#include +#include + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#define MESALINK_MAX_ERROR_SZ 80 + +struct ssl_backend_data +{ + SSL_CTX *ctx; + SSL *handle; +}; + +#define BACKEND connssl->backend + +static Curl_recv mesalink_recv; +static Curl_send mesalink_send; + +/* + * This function loads all the client/CA certificates and CRLs. Setup the TLS + * layer and do all necessary magic. + */ +static CURLcode +mesalink_connect_step1(struct connectdata *conn, int sockindex) +{ + char *ciphers; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + const bool verifypeer = SSL_CONN_CONFIG(verifypeer); + const char *const ssl_cafile = SSL_CONN_CONFIG(CAfile); + const char *const ssl_capath = SSL_CONN_CONFIG(CApath); + struct in_addr addr4; +#ifdef ENABLE_IPV6 + struct in6_addr addr6; +#endif + const char *const hostname = + SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; + size_t hostname_len = strlen(hostname); + + SSL_METHOD *req_method = NULL; + curl_socket_t sockfd = conn->sock[sockindex]; + + if(connssl->state == ssl_connection_complete) + return CURLE_OK; + + if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) { + failf(data, "MesaLink does not support to set maximum SSL/TLS version"); + return CURLE_SSL_CONNECT_ERROR; + } + + switch(SSL_CONN_CONFIG(version)) { + case CURL_SSLVERSION_SSLv3: + case CURL_SSLVERSION_TLSv1: + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + failf(data, "MesaLink does not support SSL 3.0, TLS 1.0, or TLS 1.1"); + return CURLE_NOT_BUILT_IN; + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1_2: + req_method = TLSv1_2_client_method(); + break; + case CURL_SSLVERSION_TLSv1_3: + req_method = TLSv1_3_client_method(); + break; + case CURL_SSLVERSION_SSLv2: + failf(data, "MesaLink does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + + if(!req_method) { + failf(data, "SSL: couldn't create a method!"); + return CURLE_OUT_OF_MEMORY; + } + + if(BACKEND->ctx) + SSL_CTX_free(BACKEND->ctx); + BACKEND->ctx = SSL_CTX_new(req_method); + + if(!BACKEND->ctx) { + failf(data, "SSL: couldn't create a context!"); + return CURLE_OUT_OF_MEMORY; + } + + SSL_CTX_set_verify( + BACKEND->ctx, verifypeer ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL); + + if(ssl_cafile || ssl_capath) { + if(!SSL_CTX_load_verify_locations(BACKEND->ctx, ssl_cafile, ssl_capath)) { + if(verifypeer) { + failf(data, + "error setting certificate verify locations:\n" + " CAfile: %s\n CApath: %s", + ssl_cafile ? ssl_cafile : "none", + ssl_capath ? ssl_capath : "none"); + return CURLE_SSL_CACERT_BADFILE; + } + infof(data, + "error setting certificate verify locations," + " continuing anyway:\n"); + } + else { + infof(data, "successfully set certificate verify locations:\n"); + } + infof(data, + " CAfile: %s\n" + " CApath: %s\n", + ssl_cafile ? ssl_cafile : "none", + ssl_capath ? ssl_capath : "none"); + } + + ciphers = SSL_CONN_CONFIG(cipher_list); + if(ciphers) { +#ifdef MESALINK_HAVE_CIPHER + if(!SSL_CTX_set_cipher_list(BACKEND->ctx, ciphers)) { + failf(data, "failed setting cipher list: %s", ciphers); + return CURLE_SSL_CIPHER; + } +#endif + infof(data, "Cipher selection: %s\n", ciphers); + } + + if(BACKEND->handle) + SSL_free(BACKEND->handle); + BACKEND->handle = SSL_new(BACKEND->ctx); + if(!BACKEND->handle) { + failf(data, "SSL: couldn't create a context (handle)!"); + return CURLE_OUT_OF_MEMORY; + } + + if((hostname_len < USHRT_MAX) && + (0 == Curl_inet_pton(AF_INET, hostname, &addr4)) +#ifdef ENABLE_IPV6 + && (0 == Curl_inet_pton(AF_INET6, hostname, &addr6)) +#endif + ) { + /* hostname is not a valid IP address */ + if(SSL_set_tlsext_host_name(BACKEND->handle, hostname) != SSL_SUCCESS) { + failf(data, + "WARNING: failed to configure server name indication (SNI) " + "TLS extension\n"); + return CURLE_SSL_CONNECT_ERROR; + } + } + else { +#ifdef CURLDEBUG + /* Check if the hostname is 127.0.0.1 or [::1]; + * otherwise reject because MesaLink always wants a valid DNS Name + * specified in RFC 5280 Section 7.2 */ + if(strncmp(hostname, "127.0.0.1", 9) == 0 +#ifdef ENABLE_IPV6 + || strncmp(hostname, "[::1]", 5) == 0 +#endif + ) { + SSL_set_tlsext_host_name(BACKEND->handle, "localhost"); + } + else +#endif + { + failf(data, + "ERROR: MesaLink does not accept an IP address as a hostname\n"); + return CURLE_SSL_CONNECT_ERROR; + } + } + +#ifdef MESALINK_HAVE_SESSION + if(SSL_SET_OPTION(primary.sessionid)) { + void *ssl_sessionid = NULL; + + Curl_ssl_sessionid_lock(conn); + if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) { + /* we got a session id, use it! */ + if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) { + Curl_ssl_sessionid_unlock(conn); + failf( + data, + "SSL: SSL_set_session failed: %s", + ERR_error_string(SSL_get_error(BACKEND->handle, 0), error_buffer)); + return CURLE_SSL_CONNECT_ERROR; + } + /* Informational message */ + infof(data, "SSL re-using session ID\n"); + } + Curl_ssl_sessionid_unlock(conn); + } +#endif /* MESALINK_HAVE_SESSION */ + + if(SSL_set_fd(BACKEND->handle, (int)sockfd) != SSL_SUCCESS) { + failf(data, "SSL: SSL_set_fd failed"); + return CURLE_SSL_CONNECT_ERROR; + } + + connssl->connecting_state = ssl_connect_2; + return CURLE_OK; +} + +static CURLcode +mesalink_connect_step2(struct connectdata *conn, int sockindex) +{ + int ret = -1; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + conn->recv[sockindex] = mesalink_recv; + conn->send[sockindex] = mesalink_send; + + ret = SSL_connect(BACKEND->handle); + if(ret != SSL_SUCCESS) { + char error_buffer[MESALINK_MAX_ERROR_SZ]; + int detail = SSL_get_error(BACKEND->handle, ret); + + if(SSL_ERROR_WANT_CONNECT == detail || SSL_ERROR_WANT_READ == detail) { + connssl->connecting_state = ssl_connect_2_reading; + return CURLE_OK; + } + else { + failf(data, + "SSL_connect failed with error %d: %s", + detail, + ERR_error_string_n(detail, error_buffer, sizeof(error_buffer))); + ERR_print_errors_fp(stderr); + if(detail && SSL_CONN_CONFIG(verifypeer)) { + detail &= ~0xFF; + if(detail == TLS_ERROR_WEBPKI_ERRORS) { + failf(data, "Cert verify failed"); + return CURLE_PEER_FAILED_VERIFICATION; + } + } + return CURLE_SSL_CONNECT_ERROR; + } + } + + connssl->connecting_state = ssl_connect_3; + infof(data, + "SSL connection using %s / %s\n", + SSL_get_version(BACKEND->handle), + SSL_get_cipher_name(BACKEND->handle)); + + return CURLE_OK; +} + +static CURLcode +mesalink_connect_step3(struct connectdata *conn, int sockindex) +{ + CURLcode result = CURLE_OK; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); + +#ifdef MESALINK_HAVE_SESSION + if(SSL_SET_OPTION(primary.sessionid)) { + bool incache; + SSL_SESSION *our_ssl_sessionid; + void *old_ssl_sessionid = NULL; + + our_ssl_sessionid = SSL_get_session(BACKEND->handle); + + Curl_ssl_sessionid_lock(conn); + incache = + !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex)); + if(incache) { + if(old_ssl_sessionid != our_ssl_sessionid) { + infof(data, "old SSL session ID is stale, removing\n"); + Curl_ssl_delsessionid(conn, old_ssl_sessionid); + incache = FALSE; + } + } + + if(!incache) { + result = Curl_ssl_addsessionid( + conn, our_ssl_sessionid, 0 /* unknown size */, sockindex); + if(result) { + Curl_ssl_sessionid_unlock(conn); + failf(data, "failed to store ssl session"); + return result; + } + } + Curl_ssl_sessionid_unlock(conn); + } +#endif /* MESALINK_HAVE_SESSION */ + + connssl->connecting_state = ssl_connect_done; + + return result; +} + +static ssize_t +mesalink_send(struct connectdata *conn, int sockindex, const void *mem, + size_t len, CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + char error_buffer[MESALINK_MAX_ERROR_SZ]; + int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; + int rc = SSL_write(BACKEND->handle, mem, memlen); + + if(rc < 0) { + int err = SSL_get_error(BACKEND->handle, rc); + switch(err) { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + /* there's data pending, re-invoke SSL_write() */ + *curlcode = CURLE_AGAIN; + return -1; + default: + failf(conn->data, + "SSL write: %s, errno %d", + ERR_error_string_n(err, error_buffer, sizeof(error_buffer)), + SOCKERRNO); + *curlcode = CURLE_SEND_ERROR; + return -1; + } + } + return rc; +} + +static void +Curl_mesalink_close(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + if(BACKEND->handle) { + (void)SSL_shutdown(BACKEND->handle); + SSL_free(BACKEND->handle); + BACKEND->handle = NULL; + } + if(BACKEND->ctx) { + SSL_CTX_free(BACKEND->ctx); + BACKEND->ctx = NULL; + } +} + +static ssize_t +mesalink_recv(struct connectdata *conn, int num, char *buf, size_t buffersize, + CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[num]; + char error_buffer[MESALINK_MAX_ERROR_SZ]; + int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; + int nread = SSL_read(BACKEND->handle, buf, buffsize); + + if(nread <= 0) { + int err = SSL_get_error(BACKEND->handle, nread); + + switch(err) { + case SSL_ERROR_ZERO_RETURN: /* no more data */ + case IO_ERROR_CONNECTION_ABORTED: + break; + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + /* there's data pending, re-invoke SSL_read() */ + *curlcode = CURLE_AGAIN; + return -1; + default: + failf(conn->data, + "SSL read: %s, errno %d", + ERR_error_string_n(err, error_buffer, sizeof(error_buffer)), + SOCKERRNO); + *curlcode = CURLE_RECV_ERROR; + return -1; + } + } + return nread; +} + +static size_t +Curl_mesalink_version(char *buffer, size_t size) +{ + return msnprintf(buffer, size, "MesaLink/%s", MESALINK_VERSION_STRING); +} + +static int +Curl_mesalink_init(void) +{ + return (SSL_library_init() == SSL_SUCCESS); +} + +/* + * This function is called to shut down the SSL layer but keep the + * socket open (CCC - Clear Command Channel) + */ +static int +Curl_mesalink_shutdown(struct connectdata *conn, int sockindex) +{ + int retval = 0; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + if(BACKEND->handle) { + SSL_free(BACKEND->handle); + BACKEND->handle = NULL; + } + return retval; +} + +static CURLcode +mesalink_connect_common(struct connectdata *conn, int sockindex, + bool nonblocking, bool *done) +{ + CURLcode result; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + time_t timeout_ms; + int what; + + /* check if the connection has already been established */ + if(ssl_connection_complete == connssl->state) { + *done = TRUE; + return CURLE_OK; + } + + if(ssl_connect_1 == connssl->connecting_state) { + /* Find out how much more time we're allowed */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + result = mesalink_connect_step1(conn, sockindex); + if(result) + return result; + } + + while(ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state) { + + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* if ssl is expecting something, check if it's available. */ + if(connssl->connecting_state == ssl_connect_2_reading || + connssl->connecting_state == ssl_connect_2_writing) { + + curl_socket_t writefd = + ssl_connect_2_writing == connssl->connecting_state ? sockfd + : CURL_SOCKET_BAD; + curl_socket_t readfd = ssl_connect_2_reading == connssl->connecting_state + ? sockfd + : CURL_SOCKET_BAD; + + what = Curl_socket_check( + readfd, CURL_SOCKET_BAD, writefd, nonblocking ? 0 : timeout_ms); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + else if(0 == what) { + if(nonblocking) { + *done = FALSE; + return CURLE_OK; + } + else { + /* timeout */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + } + /* socket is readable or writable */ + } + + /* Run transaction, and return to the caller if it failed or if + * this connection is part of a multi handle and this loop would + * execute again. This permits the owner of a multi handle to + * abort a connection attempt before step2 has completed while + * ensuring that a client using select() or epoll() will always + * have a valid fdset to wait on. + */ + result = mesalink_connect_step2(conn, sockindex); + + if(result || + (nonblocking && (ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state))) { + return result; + } + } /* repeat step2 until all transactions are done. */ + + if(ssl_connect_3 == connssl->connecting_state) { + result = mesalink_connect_step3(conn, sockindex); + if(result) + return result; + } + + if(ssl_connect_done == connssl->connecting_state) { + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = mesalink_recv; + conn->send[sockindex] = mesalink_send; + *done = TRUE; + } + else + *done = FALSE; + + /* Reset our connect state machine */ + connssl->connecting_state = ssl_connect_1; + + return CURLE_OK; +} + +static CURLcode +Curl_mesalink_connect_nonblocking(struct connectdata *conn, int sockindex, + bool *done) +{ + return mesalink_connect_common(conn, sockindex, TRUE, done); +} + +static CURLcode +Curl_mesalink_connect(struct connectdata *conn, int sockindex) +{ + CURLcode result; + bool done = FALSE; + + result = mesalink_connect_common(conn, sockindex, FALSE, &done); + if(result) + return result; + + DEBUGASSERT(done); + + return CURLE_OK; +} + +static void * +Curl_mesalink_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) +{ + (void)info; + return BACKEND->handle; +} + +const struct Curl_ssl Curl_ssl_mesalink = { + { CURLSSLBACKEND_MESALINK, "MesaLink" }, /* info */ + + SSLSUPP_SSL_CTX, + + sizeof(struct ssl_backend_data), + + Curl_mesalink_init, /* init */ + Curl_none_cleanup, /* cleanup */ + Curl_mesalink_version, /* version */ + Curl_none_check_cxn, /* check_cxn */ + Curl_mesalink_shutdown, /* shutdown */ + Curl_none_data_pending, /* data_pending */ + Curl_none_random, /* random */ + Curl_none_cert_status_request, /* cert_status_request */ + Curl_mesalink_connect, /* connect */ + Curl_mesalink_connect_nonblocking, /* connect_nonblocking */ + Curl_mesalink_get_internals, /* get_internals */ + Curl_mesalink_close, /* close_one */ + Curl_none_close_all, /* close_all */ + Curl_none_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ + Curl_none_md5sum, /* md5sum */ + NULL /* sha256sum */ +}; + +#endif diff --git a/dependencies/cmcurl/lib/vtls/mesalink.h b/dependencies/cmcurl/lib/vtls/mesalink.h new file mode 100644 index 0000000..54cb94a --- /dev/null +++ b/dependencies/cmcurl/lib/vtls/mesalink.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_MESALINK_H +#define HEADER_CURL_MESALINK_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2017-2018, Yiming Jing, + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_MESALINK + +extern const struct Curl_ssl Curl_ssl_mesalink; + +#endif /* USE_MESALINK */ +#endif /* HEADER_CURL_MESALINK_H */ diff --git a/dependencies/cmcurl/lib/vtls/nss.c b/dependencies/cmcurl/lib/vtls/nss.c new file mode 100644 index 0000000..491def1 --- /dev/null +++ b/dependencies/cmcurl/lib/vtls/nss.c @@ -0,0 +1,2439 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all NSS-specific code for the TLS/SSL layer. No code + * but vtls.c should ever call or use these functions. + */ + +#include "curl_setup.h" + +#ifdef USE_NSS + +#include "urldata.h" +#include "sendf.h" +#include "formdata.h" /* for the boundary function */ +#include "url.h" /* for the ssl config check function */ +#include "connect.h" +#include "strcase.h" +#include "select.h" +#include "vtls.h" +#include "llist.h" +#include "multiif.h" +#include "curl_printf.h" +#include "nssg.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for SECKEY_DestroyPublicKey() */ +#include /* for PR_ImportTCPSocket */ + +#define NSSVERNUM ((NSS_VMAJOR<<16)|(NSS_VMINOR<<8)|NSS_VPATCH) + +#if NSSVERNUM >= 0x030f00 /* 3.15.0 */ +#include +#endif + +#include "strcase.h" +#include "warnless.h" +#include "x509asn1.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#define SSL_DIR "/etc/pki/nssdb" + +/* enough to fit the string "PEM Token #[0|1]" */ +#define SLOTSIZE 13 + +struct ssl_backend_data { + PRFileDesc *handle; + char *client_nickname; + struct Curl_easy *data; + struct curl_llist obj_list; + PK11GenericObject *obj_clicert; +}; + +#define BACKEND connssl->backend + +static PRLock *nss_initlock = NULL; +static PRLock *nss_crllock = NULL; +static PRLock *nss_findslot_lock = NULL; +static PRLock *nss_trustload_lock = NULL; +static struct curl_llist nss_crl_list; +static NSSInitContext *nss_context = NULL; +static volatile int initialized = 0; + +/* type used to wrap pointers as list nodes */ +struct ptr_list_wrap { + void *ptr; + struct curl_llist_element node; +}; + +typedef struct { + const char *name; + int num; +} cipher_s; + +#define PK11_SETATTRS(_attr, _idx, _type, _val, _len) do { \ + CK_ATTRIBUTE *ptr = (_attr) + ((_idx)++); \ + ptr->type = (_type); \ + ptr->pValue = (_val); \ + ptr->ulValueLen = (_len); \ +} WHILE_FALSE + +#define CERT_NewTempCertificate __CERT_NewTempCertificate + +#define NUM_OF_CIPHERS sizeof(cipherlist)/sizeof(cipherlist[0]) +static const cipher_s cipherlist[] = { + /* SSL2 cipher suites */ + {"rc4", SSL_EN_RC4_128_WITH_MD5}, + {"rc4-md5", SSL_EN_RC4_128_WITH_MD5}, + {"rc4export", SSL_EN_RC4_128_EXPORT40_WITH_MD5}, + {"rc2", SSL_EN_RC2_128_CBC_WITH_MD5}, + {"rc2export", SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5}, + {"des", SSL_EN_DES_64_CBC_WITH_MD5}, + {"desede3", SSL_EN_DES_192_EDE3_CBC_WITH_MD5}, + /* SSL3/TLS cipher suites */ + {"rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5}, + {"rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA}, + {"rsa_3des_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA}, + {"rsa_des_sha", SSL_RSA_WITH_DES_CBC_SHA}, + {"rsa_rc4_40_md5", SSL_RSA_EXPORT_WITH_RC4_40_MD5}, + {"rsa_rc2_40_md5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5}, + {"rsa_null_md5", SSL_RSA_WITH_NULL_MD5}, + {"rsa_null_sha", SSL_RSA_WITH_NULL_SHA}, + {"fips_3des_sha", SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA}, + {"fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA}, + {"fortezza", SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA}, + {"fortezza_rc4_128_sha", SSL_FORTEZZA_DMS_WITH_RC4_128_SHA}, + {"fortezza_null", SSL_FORTEZZA_DMS_WITH_NULL_SHA}, + /* TLS 1.0: Exportable 56-bit Cipher Suites. */ + {"rsa_des_56_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA}, + {"rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA}, + /* AES ciphers. */ + {"dhe_dss_aes_128_cbc_sha", TLS_DHE_DSS_WITH_AES_128_CBC_SHA}, + {"dhe_dss_aes_256_cbc_sha", TLS_DHE_DSS_WITH_AES_256_CBC_SHA}, + {"dhe_rsa_aes_128_cbc_sha", TLS_DHE_RSA_WITH_AES_128_CBC_SHA}, + {"dhe_rsa_aes_256_cbc_sha", TLS_DHE_RSA_WITH_AES_256_CBC_SHA}, + {"rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA}, + {"rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA}, + /* ECC ciphers. */ + {"ecdh_ecdsa_null_sha", TLS_ECDH_ECDSA_WITH_NULL_SHA}, + {"ecdh_ecdsa_rc4_128_sha", TLS_ECDH_ECDSA_WITH_RC4_128_SHA}, + {"ecdh_ecdsa_3des_sha", TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA}, + {"ecdh_ecdsa_aes_128_sha", TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA}, + {"ecdh_ecdsa_aes_256_sha", TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA}, + {"ecdhe_ecdsa_null_sha", TLS_ECDHE_ECDSA_WITH_NULL_SHA}, + {"ecdhe_ecdsa_rc4_128_sha", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA}, + {"ecdhe_ecdsa_3des_sha", TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA}, + {"ecdhe_ecdsa_aes_128_sha", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA}, + {"ecdhe_ecdsa_aes_256_sha", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA}, + {"ecdh_rsa_null_sha", TLS_ECDH_RSA_WITH_NULL_SHA}, + {"ecdh_rsa_128_sha", TLS_ECDH_RSA_WITH_RC4_128_SHA}, + {"ecdh_rsa_3des_sha", TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA}, + {"ecdh_rsa_aes_128_sha", TLS_ECDH_RSA_WITH_AES_128_CBC_SHA}, + {"ecdh_rsa_aes_256_sha", TLS_ECDH_RSA_WITH_AES_256_CBC_SHA}, + {"ecdhe_rsa_null", TLS_ECDHE_RSA_WITH_NULL_SHA}, + {"ecdhe_rsa_rc4_128_sha", TLS_ECDHE_RSA_WITH_RC4_128_SHA}, + {"ecdhe_rsa_3des_sha", TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA}, + {"ecdhe_rsa_aes_128_sha", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}, + {"ecdhe_rsa_aes_256_sha", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, + {"ecdh_anon_null_sha", TLS_ECDH_anon_WITH_NULL_SHA}, + {"ecdh_anon_rc4_128sha", TLS_ECDH_anon_WITH_RC4_128_SHA}, + {"ecdh_anon_3des_sha", TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA}, + {"ecdh_anon_aes_128_sha", TLS_ECDH_anon_WITH_AES_128_CBC_SHA}, + {"ecdh_anon_aes_256_sha", TLS_ECDH_anon_WITH_AES_256_CBC_SHA}, +#ifdef TLS_RSA_WITH_NULL_SHA256 + /* new HMAC-SHA256 cipher suites specified in RFC */ + {"rsa_null_sha_256", TLS_RSA_WITH_NULL_SHA256}, + {"rsa_aes_128_cbc_sha_256", TLS_RSA_WITH_AES_128_CBC_SHA256}, + {"rsa_aes_256_cbc_sha_256", TLS_RSA_WITH_AES_256_CBC_SHA256}, + {"dhe_rsa_aes_128_cbc_sha_256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256}, + {"dhe_rsa_aes_256_cbc_sha_256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256}, + {"ecdhe_ecdsa_aes_128_cbc_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256}, + {"ecdhe_rsa_aes_128_cbc_sha_256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256}, +#endif +#ifdef TLS_RSA_WITH_AES_128_GCM_SHA256 + /* AES GCM cipher suites in RFC 5288 and RFC 5289 */ + {"rsa_aes_128_gcm_sha_256", TLS_RSA_WITH_AES_128_GCM_SHA256}, + {"dhe_rsa_aes_128_gcm_sha_256", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256}, + {"dhe_dss_aes_128_gcm_sha_256", TLS_DHE_DSS_WITH_AES_128_GCM_SHA256}, + {"ecdhe_ecdsa_aes_128_gcm_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + {"ecdh_ecdsa_aes_128_gcm_sha_256", TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256}, + {"ecdhe_rsa_aes_128_gcm_sha_256", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, + {"ecdh_rsa_aes_128_gcm_sha_256", TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256}, +#endif +#ifdef TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + /* cipher suites using SHA384 */ + {"rsa_aes_256_gcm_sha_384", TLS_RSA_WITH_AES_256_GCM_SHA384}, + {"dhe_rsa_aes_256_gcm_sha_384", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384}, + {"dhe_dss_aes_256_gcm_sha_384", TLS_DHE_DSS_WITH_AES_256_GCM_SHA384}, + {"ecdhe_ecdsa_aes_256_sha_384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384}, + {"ecdhe_rsa_aes_256_sha_384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384}, + {"ecdhe_ecdsa_aes_256_gcm_sha_384", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384}, + {"ecdhe_rsa_aes_256_gcm_sha_384", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384}, +#endif +#ifdef TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + /* chacha20-poly1305 cipher suites */ + {"ecdhe_rsa_chacha20_poly1305_sha_256", + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256}, + {"ecdhe_ecdsa_chacha20_poly1305_sha_256", + TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256}, + {"dhe_rsa_chacha20_poly1305_sha_256", + TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256}, +#endif +}; + +#ifdef WIN32 +static const char *pem_library = "nsspem.dll"; +static const char *trust_library = "nssckbi.dll"; +#else +static const char *pem_library = "libnsspem.so"; +static const char *trust_library = "libnssckbi.so"; +#endif + +static SECMODModule *pem_module = NULL; +static SECMODModule *trust_module = NULL; + +/* NSPR I/O layer we use to detect blocking direction during SSL handshake */ +static PRDescIdentity nspr_io_identity = PR_INVALID_IO_LAYER; +static PRIOMethods nspr_io_methods; + +static const char *nss_error_to_name(PRErrorCode code) +{ + const char *name = PR_ErrorToName(code); + if(name) + return name; + + return "unknown error"; +} + +static void nss_print_error_message(struct Curl_easy *data, PRUint32 err) +{ + failf(data, "%s", PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT)); +} + +static char *nss_sslver_to_name(PRUint16 nssver) +{ + switch(nssver) { + case SSL_LIBRARY_VERSION_2: + return strdup("SSLv2"); + case SSL_LIBRARY_VERSION_3_0: + return strdup("SSLv3"); + case SSL_LIBRARY_VERSION_TLS_1_0: + return strdup("TLSv1.0"); +#ifdef SSL_LIBRARY_VERSION_TLS_1_1 + case SSL_LIBRARY_VERSION_TLS_1_1: + return strdup("TLSv1.1"); +#endif +#ifdef SSL_LIBRARY_VERSION_TLS_1_2 + case SSL_LIBRARY_VERSION_TLS_1_2: + return strdup("TLSv1.2"); +#endif +#ifdef SSL_LIBRARY_VERSION_TLS_1_3 + case SSL_LIBRARY_VERSION_TLS_1_3: + return strdup("TLSv1.3"); +#endif + default: + return curl_maprintf("0x%04x", nssver); + } +} + +static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc * model, + char *cipher_list) +{ + unsigned int i; + PRBool cipher_state[NUM_OF_CIPHERS]; + PRBool found; + char *cipher; + + /* use accessors to avoid dynamic linking issues after an update of NSS */ + const PRUint16 num_implemented_ciphers = SSL_GetNumImplementedCiphers(); + const PRUint16 *implemented_ciphers = SSL_GetImplementedCiphers(); + if(!implemented_ciphers) + return SECFailure; + + /* First disable all ciphers. This uses a different max value in case + * NSS adds more ciphers later we don't want them available by + * accident + */ + for(i = 0; i < num_implemented_ciphers; i++) { + SSL_CipherPrefSet(model, implemented_ciphers[i], PR_FALSE); + } + + /* Set every entry in our list to false */ + for(i = 0; i < NUM_OF_CIPHERS; i++) { + cipher_state[i] = PR_FALSE; + } + + cipher = cipher_list; + + while(cipher_list && (cipher_list[0])) { + while((*cipher) && (ISSPACE(*cipher))) + ++cipher; + + cipher_list = strchr(cipher, ','); + if(cipher_list) { + *cipher_list++ = '\0'; + } + + found = PR_FALSE; + + for(i = 0; i. + */ +static PK11SlotInfo* nss_find_slot_by_name(const char *slot_name) +{ + PK11SlotInfo *slot; + PR_Lock(nss_findslot_lock); + slot = PK11_FindSlotByName(slot_name); + PR_Unlock(nss_findslot_lock); + return slot; +} + +/* wrap 'ptr' as list node and tail-insert into 'list' */ +static CURLcode insert_wrapped_ptr(struct curl_llist *list, void *ptr) +{ + struct ptr_list_wrap *wrap = malloc(sizeof(*wrap)); + if(!wrap) + return CURLE_OUT_OF_MEMORY; + + wrap->ptr = ptr; + Curl_llist_insert_next(list, list->tail, wrap, &wrap->node); + return CURLE_OK; +} + +/* Call PK11_CreateGenericObject() with the given obj_class and filename. If + * the call succeeds, append the object handle to the list of objects so that + * the object can be destroyed in Curl_nss_close(). */ +static CURLcode nss_create_object(struct ssl_connect_data *connssl, + CK_OBJECT_CLASS obj_class, + const char *filename, bool cacert) +{ + PK11SlotInfo *slot; + PK11GenericObject *obj; + CK_BBOOL cktrue = CK_TRUE; + CK_BBOOL ckfalse = CK_FALSE; + CK_ATTRIBUTE attrs[/* max count of attributes */ 4]; + int attr_cnt = 0; + CURLcode result = (cacert) + ? CURLE_SSL_CACERT_BADFILE + : CURLE_SSL_CERTPROBLEM; + + const int slot_id = (cacert) ? 0 : 1; + char *slot_name = aprintf("PEM Token #%d", slot_id); + if(!slot_name) + return CURLE_OUT_OF_MEMORY; + + slot = nss_find_slot_by_name(slot_name); + free(slot_name); + if(!slot) + return result; + + PK11_SETATTRS(attrs, attr_cnt, CKA_CLASS, &obj_class, sizeof(obj_class)); + PK11_SETATTRS(attrs, attr_cnt, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); + PK11_SETATTRS(attrs, attr_cnt, CKA_LABEL, (unsigned char *)filename, + (CK_ULONG)strlen(filename) + 1); + + if(CKO_CERTIFICATE == obj_class) { + CK_BBOOL *pval = (cacert) ? (&cktrue) : (&ckfalse); + PK11_SETATTRS(attrs, attr_cnt, CKA_TRUST, pval, sizeof(*pval)); + } + + /* PK11_CreateManagedGenericObject() was introduced in NSS 3.34 because + * PK11_DestroyGenericObject() does not release resources allocated by + * PK11_CreateGenericObject() early enough. */ + obj = +#ifdef HAVE_PK11_CREATEMANAGEDGENERICOBJECT + PK11_CreateManagedGenericObject +#else + PK11_CreateGenericObject +#endif + (slot, attrs, attr_cnt, PR_FALSE); + + PK11_FreeSlot(slot); + if(!obj) + return result; + + if(insert_wrapped_ptr(&BACKEND->obj_list, obj) != CURLE_OK) { + PK11_DestroyGenericObject(obj); + return CURLE_OUT_OF_MEMORY; + } + + if(!cacert && CKO_CERTIFICATE == obj_class) + /* store reference to a client certificate */ + BACKEND->obj_clicert = obj; + + return CURLE_OK; +} + +/* Destroy the NSS object whose handle is given by ptr. This function is + * a callback of Curl_llist_alloc() used by Curl_llist_destroy() to destroy + * NSS objects in Curl_nss_close() */ +static void nss_destroy_object(void *user, void *ptr) +{ + struct ptr_list_wrap *wrap = (struct ptr_list_wrap *) ptr; + PK11GenericObject *obj = (PK11GenericObject *) wrap->ptr; + (void) user; + PK11_DestroyGenericObject(obj); + free(wrap); +} + +/* same as nss_destroy_object() but for CRL items */ +static void nss_destroy_crl_item(void *user, void *ptr) +{ + struct ptr_list_wrap *wrap = (struct ptr_list_wrap *) ptr; + SECItem *crl_der = (SECItem *) wrap->ptr; + (void) user; + SECITEM_FreeItem(crl_der, PR_TRUE); + free(wrap); +} + +static CURLcode nss_load_cert(struct ssl_connect_data *ssl, + const char *filename, PRBool cacert) +{ + CURLcode result = (cacert) + ? CURLE_SSL_CACERT_BADFILE + : CURLE_SSL_CERTPROBLEM; + + /* libnsspem.so leaks memory if the requested file does not exist. For more + * details, go to . */ + if(is_file(filename)) + result = nss_create_object(ssl, CKO_CERTIFICATE, filename, cacert); + + if(!result && !cacert) { + /* we have successfully loaded a client certificate */ + CERTCertificate *cert; + char *nickname = NULL; + char *n = strrchr(filename, '/'); + if(n) + n++; + + /* The following undocumented magic helps to avoid a SIGSEGV on call + * of PK11_ReadRawAttribute() from SelectClientCert() when using an + * immature version of libnsspem.so. For more details, go to + * . */ + nickname = aprintf("PEM Token #1:%s", n); + if(nickname) { + cert = PK11_FindCertFromNickname(nickname, NULL); + if(cert) + CERT_DestroyCertificate(cert); + + free(nickname); + } + } + + return result; +} + +/* add given CRL to cache if it is not already there */ +static CURLcode nss_cache_crl(SECItem *crl_der) +{ + CERTCertDBHandle *db = CERT_GetDefaultCertDB(); + CERTSignedCrl *crl = SEC_FindCrlByDERCert(db, crl_der, 0); + if(crl) { + /* CRL already cached */ + SEC_DestroyCrl(crl); + SECITEM_FreeItem(crl_der, PR_TRUE); + return CURLE_OK; + } + + /* acquire lock before call of CERT_CacheCRL() and accessing nss_crl_list */ + PR_Lock(nss_crllock); + + /* store the CRL item so that we can free it in Curl_nss_cleanup() */ + if(insert_wrapped_ptr(&nss_crl_list, crl_der) != CURLE_OK) { + SECITEM_FreeItem(crl_der, PR_TRUE); + PR_Unlock(nss_crllock); + return CURLE_OUT_OF_MEMORY; + } + + if(SECSuccess != CERT_CacheCRL(db, crl_der)) { + /* unable to cache CRL */ + PR_Unlock(nss_crllock); + return CURLE_SSL_CRL_BADFILE; + } + + /* we need to clear session cache, so that the CRL could take effect */ + SSL_ClearSessionCache(); + PR_Unlock(nss_crllock); + return CURLE_OK; +} + +static CURLcode nss_load_crl(const char *crlfilename) +{ + PRFileDesc *infile; + PRFileInfo info; + SECItem filedata = { 0, NULL, 0 }; + SECItem *crl_der = NULL; + char *body; + + infile = PR_Open(crlfilename, PR_RDONLY, 0); + if(!infile) + return CURLE_SSL_CRL_BADFILE; + + if(PR_SUCCESS != PR_GetOpenFileInfo(infile, &info)) + goto fail; + + if(!SECITEM_AllocItem(NULL, &filedata, info.size + /* zero ended */ 1)) + goto fail; + + if(info.size != PR_Read(infile, filedata.data, info.size)) + goto fail; + + crl_der = SECITEM_AllocItem(NULL, NULL, 0U); + if(!crl_der) + goto fail; + + /* place a trailing zero right after the visible data */ + body = (char *)filedata.data; + body[--filedata.len] = '\0'; + + body = strstr(body, "-----BEGIN"); + if(body) { + /* assume ASCII */ + char *trailer; + char *begin = PORT_Strchr(body, '\n'); + if(!begin) + begin = PORT_Strchr(body, '\r'); + if(!begin) + goto fail; + + trailer = strstr(++begin, "-----END"); + if(!trailer) + goto fail; + + /* retrieve DER from ASCII */ + *trailer = '\0'; + if(ATOB_ConvertAsciiToItem(crl_der, begin)) + goto fail; + + SECITEM_FreeItem(&filedata, PR_FALSE); + } + else + /* assume DER */ + *crl_der = filedata; + + PR_Close(infile); + return nss_cache_crl(crl_der); + +fail: + PR_Close(infile); + SECITEM_FreeItem(crl_der, PR_TRUE); + SECITEM_FreeItem(&filedata, PR_FALSE); + return CURLE_SSL_CRL_BADFILE; +} + +static CURLcode nss_load_key(struct connectdata *conn, int sockindex, + char *key_file) +{ + PK11SlotInfo *slot, *tmp; + SECStatus status; + CURLcode result; + struct ssl_connect_data *ssl = conn->ssl; + struct Curl_easy *data = conn->data; + + (void)sockindex; /* unused */ + + result = nss_create_object(ssl, CKO_PRIVATE_KEY, key_file, FALSE); + if(result) { + PR_SetError(SEC_ERROR_BAD_KEY, 0); + return result; + } + + slot = nss_find_slot_by_name("PEM Token #1"); + if(!slot) + return CURLE_SSL_CERTPROBLEM; + + /* This will force the token to be seen as re-inserted */ + tmp = SECMOD_WaitForAnyTokenEvent(pem_module, 0, 0); + if(tmp) + PK11_FreeSlot(tmp); + PK11_IsPresent(slot); + + status = PK11_Authenticate(slot, PR_TRUE, SSL_SET_OPTION(key_passwd)); + PK11_FreeSlot(slot); + + return (SECSuccess == status) ? CURLE_OK : CURLE_SSL_CERTPROBLEM; +} + +static int display_error(struct connectdata *conn, PRInt32 err, + const char *filename) +{ + switch(err) { + case SEC_ERROR_BAD_PASSWORD: + failf(conn->data, "Unable to load client key: Incorrect password"); + return 1; + case SEC_ERROR_UNKNOWN_CERT: + failf(conn->data, "Unable to load certificate %s", filename); + return 1; + default: + break; + } + return 0; /* The caller will print a generic error */ +} + +static CURLcode cert_stuff(struct connectdata *conn, int sockindex, + char *cert_file, char *key_file) +{ + struct Curl_easy *data = conn->data; + CURLcode result; + + if(cert_file) { + result = nss_load_cert(&conn->ssl[sockindex], cert_file, PR_FALSE); + if(result) { + const PRErrorCode err = PR_GetError(); + if(!display_error(conn, err, cert_file)) { + const char *err_name = nss_error_to_name(err); + failf(data, "unable to load client cert: %d (%s)", err, err_name); + } + + return result; + } + } + + if(key_file || (is_file(cert_file))) { + if(key_file) + result = nss_load_key(conn, sockindex, key_file); + else + /* In case the cert file also has the key */ + result = nss_load_key(conn, sockindex, cert_file); + if(result) { + const PRErrorCode err = PR_GetError(); + if(!display_error(conn, err, key_file)) { + const char *err_name = nss_error_to_name(err); + failf(data, "unable to load client key: %d (%s)", err, err_name); + } + + return result; + } + } + + return CURLE_OK; +} + +static char *nss_get_password(PK11SlotInfo *slot, PRBool retry, void *arg) +{ + (void)slot; /* unused */ + + if(retry || NULL == arg) + return NULL; + else + return (char *)PORT_Strdup((char *)arg); +} + +/* bypass the default SSL_AuthCertificate() hook in case we do not want to + * verify peer */ +static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig, + PRBool isServer) +{ + struct connectdata *conn = (struct connectdata *)arg; + +#ifdef SSL_ENABLE_OCSP_STAPLING + if(SSL_CONN_CONFIG(verifystatus)) { + SECStatus cacheResult; + + const SECItemArray *csa = SSL_PeerStapledOCSPResponses(fd); + if(!csa) { + failf(conn->data, "Invalid OCSP response"); + return SECFailure; + } + + if(csa->len == 0) { + failf(conn->data, "No OCSP response received"); + return SECFailure; + } + + cacheResult = CERT_CacheOCSPResponseFromSideChannel( + CERT_GetDefaultCertDB(), SSL_PeerCertificate(fd), + PR_Now(), &csa->items[0], arg + ); + + if(cacheResult != SECSuccess) { + failf(conn->data, "Invalid OCSP response"); + return cacheResult; + } + } +#endif + + if(!SSL_CONN_CONFIG(verifypeer)) { + infof(conn->data, "skipping SSL peer certificate verification\n"); + return SECSuccess; + } + + return SSL_AuthCertificate(CERT_GetDefaultCertDB(), fd, checksig, isServer); +} + +/** + * Inform the application that the handshake is complete. + */ +static void HandshakeCallback(PRFileDesc *sock, void *arg) +{ + struct connectdata *conn = (struct connectdata*) arg; + unsigned int buflenmax = 50; + unsigned char buf[50]; + unsigned int buflen; + SSLNextProtoState state; + + if(!conn->bits.tls_enable_npn && !conn->bits.tls_enable_alpn) { + return; + } + + if(SSL_GetNextProto(sock, &state, buf, &buflen, buflenmax) == SECSuccess) { + + switch(state) { +#if NSSVERNUM >= 0x031a00 /* 3.26.0 */ + /* used by NSS internally to implement 0-RTT */ + case SSL_NEXT_PROTO_EARLY_VALUE: + /* fall through! */ +#endif + case SSL_NEXT_PROTO_NO_SUPPORT: + case SSL_NEXT_PROTO_NO_OVERLAP: + infof(conn->data, "ALPN/NPN, server did not agree to a protocol\n"); + return; +#ifdef SSL_ENABLE_ALPN + case SSL_NEXT_PROTO_SELECTED: + infof(conn->data, "ALPN, server accepted to use %.*s\n", buflen, buf); + break; +#endif + case SSL_NEXT_PROTO_NEGOTIATED: + infof(conn->data, "NPN, server accepted to use %.*s\n", buflen, buf); + break; + } + +#ifdef USE_NGHTTP2 + if(buflen == NGHTTP2_PROTO_VERSION_ID_LEN && + !memcmp(NGHTTP2_PROTO_VERSION_ID, buf, NGHTTP2_PROTO_VERSION_ID_LEN)) { + conn->negnpn = CURL_HTTP_VERSION_2; + } + else +#endif + if(buflen == ALPN_HTTP_1_1_LENGTH && + !memcmp(ALPN_HTTP_1_1, buf, ALPN_HTTP_1_1_LENGTH)) { + conn->negnpn = CURL_HTTP_VERSION_1_1; + } + Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); + } +} + +#if NSSVERNUM >= 0x030f04 /* 3.15.4 */ +static SECStatus CanFalseStartCallback(PRFileDesc *sock, void *client_data, + PRBool *canFalseStart) +{ + struct connectdata *conn = client_data; + struct Curl_easy *data = conn->data; + + SSLChannelInfo channelInfo; + SSLCipherSuiteInfo cipherInfo; + + SECStatus rv; + PRBool negotiatedExtension; + + *canFalseStart = PR_FALSE; + + if(SSL_GetChannelInfo(sock, &channelInfo, sizeof(channelInfo)) != SECSuccess) + return SECFailure; + + if(SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo, + sizeof(cipherInfo)) != SECSuccess) + return SECFailure; + + /* Prevent version downgrade attacks from TLS 1.2, and avoid False Start for + * TLS 1.3 and later. See https://bugzilla.mozilla.org/show_bug.cgi?id=861310 + */ + if(channelInfo.protocolVersion != SSL_LIBRARY_VERSION_TLS_1_2) + goto end; + + /* Only allow ECDHE key exchange algorithm. + * See https://bugzilla.mozilla.org/show_bug.cgi?id=952863 */ + if(cipherInfo.keaType != ssl_kea_ecdh) + goto end; + + /* Prevent downgrade attacks on the symmetric cipher. We do not allow CBC + * mode due to BEAST, POODLE, and other attacks on the MAC-then-Encrypt + * design. See https://bugzilla.mozilla.org/show_bug.cgi?id=1109766 */ + if(cipherInfo.symCipher != ssl_calg_aes_gcm) + goto end; + + /* Enforce ALPN or NPN to do False Start, as an indicator of server + * compatibility. */ + rv = SSL_HandshakeNegotiatedExtension(sock, ssl_app_layer_protocol_xtn, + &negotiatedExtension); + if(rv != SECSuccess || !negotiatedExtension) { + rv = SSL_HandshakeNegotiatedExtension(sock, ssl_next_proto_nego_xtn, + &negotiatedExtension); + } + + if(rv != SECSuccess || !negotiatedExtension) + goto end; + + *canFalseStart = PR_TRUE; + + infof(data, "Trying TLS False Start\n"); + +end: + return SECSuccess; +} +#endif + +static void display_cert_info(struct Curl_easy *data, + CERTCertificate *cert) +{ + char *subject, *issuer, *common_name; + PRExplodedTime printableTime; + char timeString[256]; + PRTime notBefore, notAfter; + + subject = CERT_NameToAscii(&cert->subject); + issuer = CERT_NameToAscii(&cert->issuer); + common_name = CERT_GetCommonName(&cert->subject); + infof(data, "\tsubject: %s\n", subject); + + CERT_GetCertTimes(cert, ¬Before, ¬After); + PR_ExplodeTime(notBefore, PR_GMTParameters, &printableTime); + PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime); + infof(data, "\tstart date: %s\n", timeString); + PR_ExplodeTime(notAfter, PR_GMTParameters, &printableTime); + PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime); + infof(data, "\texpire date: %s\n", timeString); + infof(data, "\tcommon name: %s\n", common_name); + infof(data, "\tissuer: %s\n", issuer); + + PR_Free(subject); + PR_Free(issuer); + PR_Free(common_name); +} + +static CURLcode display_conn_info(struct connectdata *conn, PRFileDesc *sock) +{ + CURLcode result = CURLE_OK; + SSLChannelInfo channel; + SSLCipherSuiteInfo suite; + CERTCertificate *cert; + CERTCertificate *cert2; + CERTCertificate *cert3; + PRTime now; + int i; + + if(SSL_GetChannelInfo(sock, &channel, sizeof(channel)) == + SECSuccess && channel.length == sizeof(channel) && + channel.cipherSuite) { + if(SSL_GetCipherSuiteInfo(channel.cipherSuite, + &suite, sizeof(suite)) == SECSuccess) { + infof(conn->data, "SSL connection using %s\n", suite.cipherSuiteName); + } + } + + cert = SSL_PeerCertificate(sock); + if(cert) { + infof(conn->data, "Server certificate:\n"); + + if(!conn->data->set.ssl.certinfo) { + display_cert_info(conn->data, cert); + CERT_DestroyCertificate(cert); + } + else { + /* Count certificates in chain. */ + now = PR_Now(); + i = 1; + if(!cert->isRoot) { + cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA); + while(cert2) { + i++; + if(cert2->isRoot) { + CERT_DestroyCertificate(cert2); + break; + } + cert3 = CERT_FindCertIssuer(cert2, now, certUsageSSLCA); + CERT_DestroyCertificate(cert2); + cert2 = cert3; + } + } + + result = Curl_ssl_init_certinfo(conn->data, i); + if(!result) { + for(i = 0; cert; cert = cert2) { + result = Curl_extract_certinfo(conn, i++, (char *)cert->derCert.data, + (char *)cert->derCert.data + + cert->derCert.len); + if(result) + break; + + if(cert->isRoot) { + CERT_DestroyCertificate(cert); + break; + } + + cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA); + CERT_DestroyCertificate(cert); + } + } + } + } + + return result; +} + +static SECStatus BadCertHandler(void *arg, PRFileDesc *sock) +{ + struct connectdata *conn = (struct connectdata *)arg; + struct Curl_easy *data = conn->data; + PRErrorCode err = PR_GetError(); + CERTCertificate *cert; + + /* remember the cert verification result */ + if(SSL_IS_PROXY()) + data->set.proxy_ssl.certverifyresult = err; + else + data->set.ssl.certverifyresult = err; + + if(err == SSL_ERROR_BAD_CERT_DOMAIN && !SSL_CONN_CONFIG(verifyhost)) + /* we are asked not to verify the host name */ + return SECSuccess; + + /* print only info about the cert, the error is printed off the callback */ + cert = SSL_PeerCertificate(sock); + if(cert) { + infof(data, "Server certificate:\n"); + display_cert_info(data, cert); + CERT_DestroyCertificate(cert); + } + + return SECFailure; +} + +/** + * + * Check that the Peer certificate's issuer certificate matches the one found + * by issuer_nickname. This is not exactly the way OpenSSL and GNU TLS do the + * issuer check, so we provide comments that mimic the OpenSSL + * X509_check_issued function (in x509v3/v3_purp.c) + */ +static SECStatus check_issuer_cert(PRFileDesc *sock, + char *issuer_nickname) +{ + CERTCertificate *cert, *cert_issuer, *issuer; + SECStatus res = SECSuccess; + void *proto_win = NULL; + + cert = SSL_PeerCertificate(sock); + cert_issuer = CERT_FindCertIssuer(cert, PR_Now(), certUsageObjectSigner); + + proto_win = SSL_RevealPinArg(sock); + issuer = PK11_FindCertFromNickname(issuer_nickname, proto_win); + + if((!cert_issuer) || (!issuer)) + res = SECFailure; + else if(SECITEM_CompareItem(&cert_issuer->derCert, + &issuer->derCert) != SECEqual) + res = SECFailure; + + CERT_DestroyCertificate(cert); + CERT_DestroyCertificate(issuer); + CERT_DestroyCertificate(cert_issuer); + return res; +} + +static CURLcode cmp_peer_pubkey(struct ssl_connect_data *connssl, + const char *pinnedpubkey) +{ + CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; + struct Curl_easy *data = BACKEND->data; + CERTCertificate *cert; + + if(!pinnedpubkey) + /* no pinned public key specified */ + return CURLE_OK; + + /* get peer certificate */ + cert = SSL_PeerCertificate(BACKEND->handle); + if(cert) { + /* extract public key from peer certificate */ + SECKEYPublicKey *pubkey = CERT_ExtractPublicKey(cert); + if(pubkey) { + /* encode the public key as DER */ + SECItem *cert_der = PK11_DEREncodePublicKey(pubkey); + if(cert_der) { + /* compare the public key with the pinned public key */ + result = Curl_pin_peer_pubkey(data, pinnedpubkey, cert_der->data, + cert_der->len); + SECITEM_FreeItem(cert_der, PR_TRUE); + } + SECKEY_DestroyPublicKey(pubkey); + } + CERT_DestroyCertificate(cert); + } + + /* report the resulting status */ + switch(result) { + case CURLE_OK: + infof(data, "pinned public key verified successfully!\n"); + break; + case CURLE_SSL_PINNEDPUBKEYNOTMATCH: + failf(data, "failed to verify pinned public key"); + break; + default: + /* OOM, etc. */ + break; + } + + return result; +} + +/** + * + * Callback to pick the SSL client certificate. + */ +static SECStatus SelectClientCert(void *arg, PRFileDesc *sock, + struct CERTDistNamesStr *caNames, + struct CERTCertificateStr **pRetCert, + struct SECKEYPrivateKeyStr **pRetKey) +{ + struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg; + struct Curl_easy *data = BACKEND->data; + const char *nickname = BACKEND->client_nickname; + static const char pem_slotname[] = "PEM Token #1"; + + if(BACKEND->obj_clicert) { + /* use the cert/key provided by PEM reader */ + SECItem cert_der = { 0, NULL, 0 }; + void *proto_win = SSL_RevealPinArg(sock); + struct CERTCertificateStr *cert; + struct SECKEYPrivateKeyStr *key; + + PK11SlotInfo *slot = nss_find_slot_by_name(pem_slotname); + if(NULL == slot) { + failf(data, "NSS: PK11 slot not found: %s", pem_slotname); + return SECFailure; + } + + if(PK11_ReadRawAttribute(PK11_TypeGeneric, BACKEND->obj_clicert, CKA_VALUE, + &cert_der) != SECSuccess) { + failf(data, "NSS: CKA_VALUE not found in PK11 generic object"); + PK11_FreeSlot(slot); + return SECFailure; + } + + cert = PK11_FindCertFromDERCertItem(slot, &cert_der, proto_win); + SECITEM_FreeItem(&cert_der, PR_FALSE); + if(NULL == cert) { + failf(data, "NSS: client certificate from file not found"); + PK11_FreeSlot(slot); + return SECFailure; + } + + key = PK11_FindPrivateKeyFromCert(slot, cert, NULL); + PK11_FreeSlot(slot); + if(NULL == key) { + failf(data, "NSS: private key from file not found"); + CERT_DestroyCertificate(cert); + return SECFailure; + } + + infof(data, "NSS: client certificate from file\n"); + display_cert_info(data, cert); + + *pRetCert = cert; + *pRetKey = key; + return SECSuccess; + } + + /* use the default NSS hook */ + if(SECSuccess != NSS_GetClientAuthData((void *)nickname, sock, caNames, + pRetCert, pRetKey) + || NULL == *pRetCert) { + + if(NULL == nickname) + failf(data, "NSS: client certificate not found (nickname not " + "specified)"); + else + failf(data, "NSS: client certificate not found: %s", nickname); + + return SECFailure; + } + + /* get certificate nickname if any */ + nickname = (*pRetCert)->nickname; + if(NULL == nickname) + nickname = "[unknown]"; + + if(!strncmp(nickname, pem_slotname, sizeof(pem_slotname) - 1U)) { + failf(data, "NSS: refusing previously loaded certificate from file: %s", + nickname); + return SECFailure; + } + + if(NULL == *pRetKey) { + failf(data, "NSS: private key not found for certificate: %s", nickname); + return SECFailure; + } + + infof(data, "NSS: using client certificate: %s\n", nickname); + display_cert_info(data, *pRetCert); + return SECSuccess; +} + +/* update blocking direction in case of PR_WOULD_BLOCK_ERROR */ +static void nss_update_connecting_state(ssl_connect_state state, void *secret) +{ + struct ssl_connect_data *connssl = (struct ssl_connect_data *)secret; + if(PR_GetError() != PR_WOULD_BLOCK_ERROR) + /* an unrelated error is passing by */ + return; + + switch(connssl->connecting_state) { + case ssl_connect_2: + case ssl_connect_2_reading: + case ssl_connect_2_writing: + break; + default: + /* we are not called from an SSL handshake */ + return; + } + + /* update the state accordingly */ + connssl->connecting_state = state; +} + +/* recv() wrapper we use to detect blocking direction during SSL handshake */ +static PRInt32 nspr_io_recv(PRFileDesc *fd, void *buf, PRInt32 amount, + PRIntn flags, PRIntervalTime timeout) +{ + const PRRecvFN recv_fn = fd->lower->methods->recv; + const PRInt32 rv = recv_fn(fd->lower, buf, amount, flags, timeout); + if(rv < 0) + /* check for PR_WOULD_BLOCK_ERROR and update blocking direction */ + nss_update_connecting_state(ssl_connect_2_reading, fd->secret); + return rv; +} + +/* send() wrapper we use to detect blocking direction during SSL handshake */ +static PRInt32 nspr_io_send(PRFileDesc *fd, const void *buf, PRInt32 amount, + PRIntn flags, PRIntervalTime timeout) +{ + const PRSendFN send_fn = fd->lower->methods->send; + const PRInt32 rv = send_fn(fd->lower, buf, amount, flags, timeout); + if(rv < 0) + /* check for PR_WOULD_BLOCK_ERROR and update blocking direction */ + nss_update_connecting_state(ssl_connect_2_writing, fd->secret); + return rv; +} + +/* close() wrapper to avoid assertion failure due to fd->secret != NULL */ +static PRStatus nspr_io_close(PRFileDesc *fd) +{ + const PRCloseFN close_fn = PR_GetDefaultIOMethods()->close; + fd->secret = NULL; + return close_fn(fd); +} + +/* load a PKCS #11 module */ +static CURLcode nss_load_module(SECMODModule **pmod, const char *library, + const char *name) +{ + char *config_string; + SECMODModule *module = *pmod; + if(module) + /* already loaded */ + return CURLE_OK; + + config_string = aprintf("library=%s name=%s", library, name); + if(!config_string) + return CURLE_OUT_OF_MEMORY; + + module = SECMOD_LoadUserModule(config_string, NULL, PR_FALSE); + free(config_string); + + if(module && module->loaded) { + /* loaded successfully */ + *pmod = module; + return CURLE_OK; + } + + if(module) + SECMOD_DestroyModule(module); + return CURLE_FAILED_INIT; +} + +/* unload a PKCS #11 module */ +static void nss_unload_module(SECMODModule **pmod) +{ + SECMODModule *module = *pmod; + if(!module) + /* not loaded */ + return; + + if(SECMOD_UnloadUserModule(module) != SECSuccess) + /* unload failed */ + return; + + SECMOD_DestroyModule(module); + *pmod = NULL; +} + +/* data might be NULL */ +static CURLcode nss_init_core(struct Curl_easy *data, const char *cert_dir) +{ + NSSInitParameters initparams; + PRErrorCode err; + const char *err_name; + + if(nss_context != NULL) + return CURLE_OK; + + memset((void *) &initparams, '\0', sizeof(initparams)); + initparams.length = sizeof(initparams); + + if(cert_dir) { + char *certpath = aprintf("sql:%s", cert_dir); + if(!certpath) + return CURLE_OUT_OF_MEMORY; + + infof(data, "Initializing NSS with certpath: %s\n", certpath); + nss_context = NSS_InitContext(certpath, "", "", "", &initparams, + NSS_INIT_READONLY | NSS_INIT_PK11RELOAD); + free(certpath); + + if(nss_context != NULL) + return CURLE_OK; + + err = PR_GetError(); + err_name = nss_error_to_name(err); + infof(data, "Unable to initialize NSS database: %d (%s)\n", err, err_name); + } + + infof(data, "Initializing NSS with certpath: none\n"); + nss_context = NSS_InitContext("", "", "", "", &initparams, NSS_INIT_READONLY + | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN + | NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD); + if(nss_context != NULL) + return CURLE_OK; + + err = PR_GetError(); + err_name = nss_error_to_name(err); + failf(data, "Unable to initialize NSS: %d (%s)", err, err_name); + return CURLE_SSL_CACERT_BADFILE; +} + +/* data might be NULL */ +static CURLcode nss_init(struct Curl_easy *data) +{ + char *cert_dir; + struct_stat st; + CURLcode result; + + if(initialized) + return CURLE_OK; + + /* list of all CRL items we need to destroy in Curl_nss_cleanup() */ + Curl_llist_init(&nss_crl_list, nss_destroy_crl_item); + + /* First we check if $SSL_DIR points to a valid dir */ + cert_dir = getenv("SSL_DIR"); + if(cert_dir) { + if((stat(cert_dir, &st) != 0) || + (!S_ISDIR(st.st_mode))) { + cert_dir = NULL; + } + } + + /* Now we check if the default location is a valid dir */ + if(!cert_dir) { + if((stat(SSL_DIR, &st) == 0) && + (S_ISDIR(st.st_mode))) { + cert_dir = (char *)SSL_DIR; + } + } + + if(nspr_io_identity == PR_INVALID_IO_LAYER) { + /* allocate an identity for our own NSPR I/O layer */ + nspr_io_identity = PR_GetUniqueIdentity("libcurl"); + if(nspr_io_identity == PR_INVALID_IO_LAYER) + return CURLE_OUT_OF_MEMORY; + + /* the default methods just call down to the lower I/O layer */ + memcpy(&nspr_io_methods, PR_GetDefaultIOMethods(), + sizeof(nspr_io_methods)); + + /* override certain methods in the table by our wrappers */ + nspr_io_methods.recv = nspr_io_recv; + nspr_io_methods.send = nspr_io_send; + nspr_io_methods.close = nspr_io_close; + } + + result = nss_init_core(data, cert_dir); + if(result) + return result; + + if(!any_cipher_enabled()) + NSS_SetDomesticPolicy(); + + initialized = 1; + + return CURLE_OK; +} + +/** + * Global SSL init + * + * @retval 0 error initializing SSL + * @retval 1 SSL initialized successfully + */ +static int Curl_nss_init(void) +{ + /* curl_global_init() is not thread-safe so this test is ok */ + if(nss_initlock == NULL) { + PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 256); + nss_initlock = PR_NewLock(); + nss_crllock = PR_NewLock(); + nss_findslot_lock = PR_NewLock(); + nss_trustload_lock = PR_NewLock(); + } + + /* We will actually initialize NSS later */ + + return 1; +} + +/* data might be NULL */ +CURLcode Curl_nss_force_init(struct Curl_easy *data) +{ + CURLcode result; + if(!nss_initlock) { + if(data) + failf(data, "unable to initialize NSS, curl_global_init() should have " + "been called with CURL_GLOBAL_SSL or CURL_GLOBAL_ALL"); + return CURLE_FAILED_INIT; + } + + PR_Lock(nss_initlock); + result = nss_init(data); + PR_Unlock(nss_initlock); + + return result; +} + +/* Global cleanup */ +static void Curl_nss_cleanup(void) +{ + /* This function isn't required to be threadsafe and this is only done + * as a safety feature. + */ + PR_Lock(nss_initlock); + if(initialized) { + /* Free references to client certificates held in the SSL session cache. + * Omitting this hampers destruction of the security module owning + * the certificates. */ + SSL_ClearSessionCache(); + + nss_unload_module(&pem_module); + nss_unload_module(&trust_module); + NSS_ShutdownContext(nss_context); + nss_context = NULL; + } + + /* destroy all CRL items */ + Curl_llist_destroy(&nss_crl_list, NULL); + + PR_Unlock(nss_initlock); + + PR_DestroyLock(nss_initlock); + PR_DestroyLock(nss_crllock); + PR_DestroyLock(nss_findslot_lock); + PR_DestroyLock(nss_trustload_lock); + nss_initlock = NULL; + + initialized = 0; +} + +/* + * This function uses SSL_peek to determine connection status. + * + * Return codes: + * 1 means the connection is still in place + * 0 means the connection has been closed + * -1 means the connection status is unknown + */ +static int Curl_nss_check_cxn(struct connectdata *conn) +{ + struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; + int rc; + char buf; + + rc = + PR_Recv(BACKEND->handle, (void *)&buf, 1, PR_MSG_PEEK, + PR_SecondsToInterval(1)); + if(rc > 0) + return 1; /* connection still in place */ + + if(rc == 0) + return 0; /* connection has been closed */ + + return -1; /* connection status unknown */ +} + +static void nss_close(struct ssl_connect_data *connssl) +{ + /* before the cleanup, check whether we are using a client certificate */ + const bool client_cert = (BACKEND->client_nickname != NULL) + || (BACKEND->obj_clicert != NULL); + + free(BACKEND->client_nickname); + BACKEND->client_nickname = NULL; + + /* destroy all NSS objects in order to avoid failure of NSS shutdown */ + Curl_llist_destroy(&BACKEND->obj_list, NULL); + BACKEND->obj_clicert = NULL; + + if(BACKEND->handle) { + if(client_cert) + /* A server might require different authentication based on the + * particular path being requested by the client. To support this + * scenario, we must ensure that a connection will never reuse the + * authentication data from a previous connection. */ + SSL_InvalidateSession(BACKEND->handle); + + PR_Close(BACKEND->handle); + BACKEND->handle = NULL; + } +} + +/* + * This function is called when an SSL connection is closed. + */ +static void Curl_nss_close(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_connect_data *connssl_proxy = &conn->proxy_ssl[sockindex]; + + if(BACKEND->handle || connssl_proxy->backend->handle) { + /* NSS closes the socket we previously handed to it, so we must mark it + as closed to avoid double close */ + fake_sclose(conn->sock[sockindex]); + conn->sock[sockindex] = CURL_SOCKET_BAD; + } + + if(BACKEND->handle) + /* nss_close(connssl) will transitively close also + connssl_proxy->backend->handle if both are used. Clear it to avoid + a double close leading to crash. */ + connssl_proxy->backend->handle = NULL; + + nss_close(connssl); + nss_close(connssl_proxy); +} + +/* return true if NSS can provide error code (and possibly msg) for the + error */ +static bool is_nss_error(CURLcode err) +{ + switch(err) { + case CURLE_PEER_FAILED_VERIFICATION: + case CURLE_SSL_CERTPROBLEM: + case CURLE_SSL_CONNECT_ERROR: + case CURLE_SSL_ISSUER_ERROR: + return true; + + default: + return false; + } +} + +/* return true if the given error code is related to a client certificate */ +static bool is_cc_error(PRInt32 err) +{ + switch(err) { + case SSL_ERROR_BAD_CERT_ALERT: + case SSL_ERROR_EXPIRED_CERT_ALERT: + case SSL_ERROR_REVOKED_CERT_ALERT: + return true; + + default: + return false; + } +} + +static Curl_recv nss_recv; +static Curl_send nss_send; + +static CURLcode nss_load_ca_certificates(struct connectdata *conn, + int sockindex) +{ + struct Curl_easy *data = conn->data; + const char *cafile = SSL_CONN_CONFIG(CAfile); + const char *capath = SSL_CONN_CONFIG(CApath); + bool use_trust_module; + CURLcode result = CURLE_OK; + + /* treat empty string as unset */ + if(cafile && !cafile[0]) + cafile = NULL; + if(capath && !capath[0]) + capath = NULL; + + infof(data, " CAfile: %s\n CApath: %s\n", + cafile ? cafile : "none", + capath ? capath : "none"); + + /* load libnssckbi.so if no other trust roots were specified */ + use_trust_module = !cafile && !capath; + + PR_Lock(nss_trustload_lock); + if(use_trust_module && !trust_module) { + /* libnssckbi.so needed but not yet loaded --> load it! */ + result = nss_load_module(&trust_module, trust_library, "trust"); + infof(data, "%s %s\n", (result) ? "failed to load" : "loaded", + trust_library); + if(result == CURLE_FAILED_INIT) + /* If libnssckbi.so is not available (or fails to load), one can still + use CA certificates stored in NSS database. Ignore the failure. */ + result = CURLE_OK; + } + else if(!use_trust_module && trust_module) { + /* libnssckbi.so not needed but already loaded --> unload it! */ + infof(data, "unloading %s\n", trust_library); + nss_unload_module(&trust_module); + } + PR_Unlock(nss_trustload_lock); + + if(cafile) + result = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE); + + if(result) + return result; + + if(capath) { + struct_stat st; + if(stat(capath, &st) == -1) + return CURLE_SSL_CACERT_BADFILE; + + if(S_ISDIR(st.st_mode)) { + PRDirEntry *entry; + PRDir *dir = PR_OpenDir(capath); + if(!dir) + return CURLE_SSL_CACERT_BADFILE; + + while((entry = PR_ReadDir(dir, PR_SKIP_BOTH | PR_SKIP_HIDDEN))) { + char *fullpath = aprintf("%s/%s", capath, entry->name); + if(!fullpath) { + PR_CloseDir(dir); + return CURLE_OUT_OF_MEMORY; + } + + if(CURLE_OK != nss_load_cert(&conn->ssl[sockindex], fullpath, PR_TRUE)) + /* This is purposefully tolerant of errors so non-PEM files can + * be in the same directory */ + infof(data, "failed to load '%s' from CURLOPT_CAPATH\n", fullpath); + + free(fullpath); + } + + PR_CloseDir(dir); + } + else + infof(data, "warning: CURLOPT_CAPATH not a directory (%s)\n", capath); + } + + return CURLE_OK; +} + +static CURLcode nss_sslver_from_curl(PRUint16 *nssver, long version) +{ + switch(version) { + case CURL_SSLVERSION_SSLv2: + *nssver = SSL_LIBRARY_VERSION_2; + return CURLE_OK; + + case CURL_SSLVERSION_SSLv3: + *nssver = SSL_LIBRARY_VERSION_3_0; + return CURLE_OK; + + case CURL_SSLVERSION_TLSv1_0: + *nssver = SSL_LIBRARY_VERSION_TLS_1_0; + return CURLE_OK; + + case CURL_SSLVERSION_TLSv1_1: +#ifdef SSL_LIBRARY_VERSION_TLS_1_1 + *nssver = SSL_LIBRARY_VERSION_TLS_1_1; + return CURLE_OK; +#else + return CURLE_SSL_CONNECT_ERROR; +#endif + + case CURL_SSLVERSION_TLSv1_2: +#ifdef SSL_LIBRARY_VERSION_TLS_1_2 + *nssver = SSL_LIBRARY_VERSION_TLS_1_2; + return CURLE_OK; +#else + return CURLE_SSL_CONNECT_ERROR; +#endif + + case CURL_SSLVERSION_TLSv1_3: +#ifdef SSL_LIBRARY_VERSION_TLS_1_3 + *nssver = SSL_LIBRARY_VERSION_TLS_1_3; + return CURLE_OK; +#else + return CURLE_SSL_CONNECT_ERROR; +#endif + + default: + return CURLE_SSL_CONNECT_ERROR; + } +} + +static CURLcode nss_init_sslver(SSLVersionRange *sslver, + struct Curl_easy *data, + struct connectdata *conn) +{ + CURLcode result; + const long min = SSL_CONN_CONFIG(version); + const long max = SSL_CONN_CONFIG(version_max); + + /* map CURL_SSLVERSION_DEFAULT to NSS default */ + if(min == CURL_SSLVERSION_DEFAULT || max == CURL_SSLVERSION_MAX_DEFAULT) { + /* map CURL_SSLVERSION_DEFAULT to NSS default */ + if(SSL_VersionRangeGetDefault(ssl_variant_stream, sslver) != SECSuccess) + return CURLE_SSL_CONNECT_ERROR; + /* ... but make sure we use at least TLSv1.0 according to libcurl API */ + if(sslver->min < SSL_LIBRARY_VERSION_TLS_1_0) + sslver->min = SSL_LIBRARY_VERSION_TLS_1_0; + } + + switch(min) { + case CURL_SSLVERSION_TLSv1: + case CURL_SSLVERSION_DEFAULT: + break; + default: + result = nss_sslver_from_curl(&sslver->min, min); + if(result) { + failf(data, "unsupported min version passed via CURLOPT_SSLVERSION"); + return result; + } + } + + switch(max) { + case CURL_SSLVERSION_MAX_NONE: + case CURL_SSLVERSION_MAX_DEFAULT: + break; + default: + result = nss_sslver_from_curl(&sslver->max, max >> 16); + if(result) { + failf(data, "unsupported max version passed via CURLOPT_SSLVERSION"); + return result; + } + } + + return CURLE_OK; +} + +static CURLcode nss_fail_connect(struct ssl_connect_data *connssl, + struct Curl_easy *data, + CURLcode curlerr) +{ + PRErrorCode err = 0; + + if(is_nss_error(curlerr)) { + /* read NSPR error code */ + err = PR_GetError(); + if(is_cc_error(err)) + curlerr = CURLE_SSL_CERTPROBLEM; + + /* print the error number and error string */ + infof(data, "NSS error %d (%s)\n", err, nss_error_to_name(err)); + + /* print a human-readable message describing the error if available */ + nss_print_error_message(data, err); + } + + /* cleanup on connection failure */ + Curl_llist_destroy(&BACKEND->obj_list, NULL); + + return curlerr; +} + +/* Switch the SSL socket into blocking or non-blocking mode. */ +static CURLcode nss_set_blocking(struct ssl_connect_data *connssl, + struct Curl_easy *data, + bool blocking) +{ + static PRSocketOptionData sock_opt; + sock_opt.option = PR_SockOpt_Nonblocking; + sock_opt.value.non_blocking = !blocking; + + if(PR_SetSocketOption(BACKEND->handle, &sock_opt) != PR_SUCCESS) + return nss_fail_connect(connssl, data, CURLE_SSL_CONNECT_ERROR); + + return CURLE_OK; +} + +static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) +{ + PRFileDesc *model = NULL; + PRFileDesc *nspr_io = NULL; + PRFileDesc *nspr_io_stub = NULL; + PRBool ssl_no_cache; + PRBool ssl_cbc_random_iv; + struct Curl_easy *data = conn->data; + curl_socket_t sockfd = conn->sock[sockindex]; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + CURLcode result; + bool second_layer = FALSE; + SSLVersionRange sslver_supported; + + SSLVersionRange sslver = { + SSL_LIBRARY_VERSION_TLS_1_0, /* min */ +#ifdef SSL_LIBRARY_VERSION_TLS_1_3 + SSL_LIBRARY_VERSION_TLS_1_3 /* max */ +#elif defined SSL_LIBRARY_VERSION_TLS_1_2 + SSL_LIBRARY_VERSION_TLS_1_2 +#elif defined SSL_LIBRARY_VERSION_TLS_1_1 + SSL_LIBRARY_VERSION_TLS_1_1 +#else + SSL_LIBRARY_VERSION_TLS_1_0 +#endif + }; + + BACKEND->data = data; + + /* list of all NSS objects we need to destroy in Curl_nss_close() */ + Curl_llist_init(&BACKEND->obj_list, nss_destroy_object); + + PR_Lock(nss_initlock); + result = nss_init(conn->data); + if(result) { + PR_Unlock(nss_initlock); + goto error; + } + + PK11_SetPasswordFunc(nss_get_password); + + result = nss_load_module(&pem_module, pem_library, "PEM"); + PR_Unlock(nss_initlock); + if(result == CURLE_FAILED_INIT) + infof(data, "WARNING: failed to load NSS PEM library %s. Using " + "OpenSSL PEM certificates will not work.\n", pem_library); + else if(result) + goto error; + + result = CURLE_SSL_CONNECT_ERROR; + + model = PR_NewTCPSocket(); + if(!model) + goto error; + model = SSL_ImportFD(NULL, model); + + if(SSL_OptionSet(model, SSL_SECURITY, PR_TRUE) != SECSuccess) + goto error; + if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) != SECSuccess) + goto error; + if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != SECSuccess) + goto error; + + /* do not use SSL cache if disabled or we are not going to verify peer */ + ssl_no_cache = (SSL_SET_OPTION(primary.sessionid) + && SSL_CONN_CONFIG(verifypeer)) ? PR_FALSE : PR_TRUE; + if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess) + goto error; + + /* enable/disable the requested SSL version(s) */ + if(nss_init_sslver(&sslver, data, conn) != CURLE_OK) + goto error; + if(SSL_VersionRangeGetSupported(ssl_variant_stream, + &sslver_supported) != SECSuccess) + goto error; + if(sslver_supported.max < sslver.max && sslver_supported.max >= sslver.min) { + char *sslver_req_str, *sslver_supp_str; + sslver_req_str = nss_sslver_to_name(sslver.max); + sslver_supp_str = nss_sslver_to_name(sslver_supported.max); + if(sslver_req_str && sslver_supp_str) + infof(data, "Falling back from %s to max supported SSL version (%s)\n", + sslver_req_str, sslver_supp_str); + free(sslver_req_str); + free(sslver_supp_str); + sslver.max = sslver_supported.max; + } + if(SSL_VersionRangeSet(model, &sslver) != SECSuccess) + goto error; + + ssl_cbc_random_iv = !SSL_SET_OPTION(enable_beast); +#ifdef SSL_CBC_RANDOM_IV + /* unless the user explicitly asks to allow the protocol vulnerability, we + use the work-around */ + if(SSL_OptionSet(model, SSL_CBC_RANDOM_IV, ssl_cbc_random_iv) != SECSuccess) + infof(data, "warning: failed to set SSL_CBC_RANDOM_IV = %d\n", + ssl_cbc_random_iv); +#else + if(ssl_cbc_random_iv) + infof(data, "warning: support for SSL_CBC_RANDOM_IV not compiled in\n"); +#endif + + if(SSL_CONN_CONFIG(cipher_list)) { + if(set_ciphers(data, model, SSL_CONN_CONFIG(cipher_list)) != SECSuccess) { + result = CURLE_SSL_CIPHER; + goto error; + } + } + + if(!SSL_CONN_CONFIG(verifypeer) && SSL_CONN_CONFIG(verifyhost)) + infof(data, "warning: ignoring value of ssl.verifyhost\n"); + + /* bypass the default SSL_AuthCertificate() hook in case we do not want to + * verify peer */ + if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, conn) != SECSuccess) + goto error; + + /* not checked yet */ + if(SSL_IS_PROXY()) + data->set.proxy_ssl.certverifyresult = 0; + else + data->set.ssl.certverifyresult = 0; + + if(SSL_BadCertHook(model, BadCertHandler, conn) != SECSuccess) + goto error; + + if(SSL_HandshakeCallback(model, HandshakeCallback, conn) != SECSuccess) + goto error; + + { + const CURLcode rv = nss_load_ca_certificates(conn, sockindex); + if((rv == CURLE_SSL_CACERT_BADFILE) && !SSL_CONN_CONFIG(verifypeer)) + /* not a fatal error because we are not going to verify the peer */ + infof(data, "warning: CA certificates failed to load\n"); + else if(rv) { + result = rv; + goto error; + } + } + + if(SSL_SET_OPTION(CRLfile)) { + const CURLcode rv = nss_load_crl(SSL_SET_OPTION(CRLfile)); + if(rv) { + result = rv; + goto error; + } + infof(data, " CRLfile: %s\n", SSL_SET_OPTION(CRLfile)); + } + + if(SSL_SET_OPTION(cert)) { + char *nickname = dup_nickname(data, SSL_SET_OPTION(cert)); + if(nickname) { + /* we are not going to use libnsspem.so to read the client cert */ + BACKEND->obj_clicert = NULL; + } + else { + CURLcode rv = cert_stuff(conn, sockindex, SSL_SET_OPTION(cert), + SSL_SET_OPTION(key)); + if(rv) { + /* failf() is already done in cert_stuff() */ + result = rv; + goto error; + } + } + + /* store the nickname for SelectClientCert() called during handshake */ + BACKEND->client_nickname = nickname; + } + else + BACKEND->client_nickname = NULL; + + if(SSL_GetClientAuthDataHook(model, SelectClientCert, + (void *)connssl) != SECSuccess) { + result = CURLE_SSL_CERTPROBLEM; + goto error; + } + + if(conn->proxy_ssl[sockindex].use) { + DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state); + DEBUGASSERT(conn->proxy_ssl[sockindex].backend->handle != NULL); + nspr_io = conn->proxy_ssl[sockindex].backend->handle; + second_layer = TRUE; + } + else { + /* wrap OS file descriptor by NSPR's file descriptor abstraction */ + nspr_io = PR_ImportTCPSocket(sockfd); + if(!nspr_io) + goto error; + } + + /* create our own NSPR I/O layer */ + nspr_io_stub = PR_CreateIOLayerStub(nspr_io_identity, &nspr_io_methods); + if(!nspr_io_stub) { + if(!second_layer) + PR_Close(nspr_io); + goto error; + } + + /* make the per-connection data accessible from NSPR I/O callbacks */ + nspr_io_stub->secret = (void *)connssl; + + /* push our new layer to the NSPR I/O stack */ + if(PR_PushIOLayer(nspr_io, PR_TOP_IO_LAYER, nspr_io_stub) != PR_SUCCESS) { + if(!second_layer) + PR_Close(nspr_io); + PR_Close(nspr_io_stub); + goto error; + } + + /* import our model socket onto the current I/O stack */ + BACKEND->handle = SSL_ImportFD(model, nspr_io); + if(!BACKEND->handle) { + if(!second_layer) + PR_Close(nspr_io); + goto error; + } + + PR_Close(model); /* We don't need this any more */ + model = NULL; + + /* This is the password associated with the cert that we're using */ + if(SSL_SET_OPTION(key_passwd)) { + SSL_SetPKCS11PinArg(BACKEND->handle, SSL_SET_OPTION(key_passwd)); + } + +#ifdef SSL_ENABLE_OCSP_STAPLING + if(SSL_CONN_CONFIG(verifystatus)) { + if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE) + != SECSuccess) + goto error; + } +#endif + +#ifdef SSL_ENABLE_NPN + if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_NPN, conn->bits.tls_enable_npn + ? PR_TRUE : PR_FALSE) != SECSuccess) + goto error; +#endif + +#ifdef SSL_ENABLE_ALPN + if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_ALPN, conn->bits.tls_enable_alpn + ? PR_TRUE : PR_FALSE) != SECSuccess) + goto error; +#endif + +#if NSSVERNUM >= 0x030f04 /* 3.15.4 */ + if(data->set.ssl.falsestart) { + if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_FALSE_START, PR_TRUE) + != SECSuccess) + goto error; + + if(SSL_SetCanFalseStartCallback(BACKEND->handle, CanFalseStartCallback, + conn) != SECSuccess) + goto error; + } +#endif + +#if defined(SSL_ENABLE_NPN) || defined(SSL_ENABLE_ALPN) + if(conn->bits.tls_enable_npn || conn->bits.tls_enable_alpn) { + int cur = 0; + unsigned char protocols[128]; + +#ifdef USE_NGHTTP2 + if(data->set.httpversion >= CURL_HTTP_VERSION_2 && + (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) { + protocols[cur++] = NGHTTP2_PROTO_VERSION_ID_LEN; + memcpy(&protocols[cur], NGHTTP2_PROTO_VERSION_ID, + NGHTTP2_PROTO_VERSION_ID_LEN); + cur += NGHTTP2_PROTO_VERSION_ID_LEN; + } +#endif + protocols[cur++] = ALPN_HTTP_1_1_LENGTH; + memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH); + cur += ALPN_HTTP_1_1_LENGTH; + + if(SSL_SetNextProtoNego(BACKEND->handle, protocols, cur) != SECSuccess) + goto error; + } +#endif + + + /* Force handshake on next I/O */ + if(SSL_ResetHandshake(BACKEND->handle, /* asServer */ PR_FALSE) + != SECSuccess) + goto error; + + /* propagate hostname to the TLS layer */ + if(SSL_SetURL(BACKEND->handle, SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name) != SECSuccess) + goto error; + + /* prevent NSS from re-using the session for a different hostname */ + if(SSL_SetSockPeerID(BACKEND->handle, SSL_IS_PROXY() ? + conn->http_proxy.host.name : conn->host.name) + != SECSuccess) + goto error; + + return CURLE_OK; + +error: + if(model) + PR_Close(model); + + return nss_fail_connect(connssl, data, result); +} + +static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct Curl_easy *data = conn->data; + CURLcode result = CURLE_SSL_CONNECT_ERROR; + PRUint32 timeout; + long * const certverifyresult = SSL_IS_PROXY() ? + &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult; + const char * const pinnedpubkey = SSL_IS_PROXY() ? + data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + + + /* check timeout situation */ + const time_t time_left = Curl_timeleft(data, NULL, TRUE); + if(time_left < 0) { + failf(data, "timed out before SSL handshake"); + result = CURLE_OPERATION_TIMEDOUT; + goto error; + } + + /* Force the handshake now */ + timeout = PR_MillisecondsToInterval((PRUint32) time_left); + if(SSL_ForceHandshakeWithTimeout(BACKEND->handle, timeout) != SECSuccess) { + if(PR_GetError() == PR_WOULD_BLOCK_ERROR) + /* blocking direction is updated by nss_update_connecting_state() */ + return CURLE_AGAIN; + else if(*certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN) + result = CURLE_PEER_FAILED_VERIFICATION; + else if(*certverifyresult != 0) + result = CURLE_PEER_FAILED_VERIFICATION; + goto error; + } + + result = display_conn_info(conn, BACKEND->handle); + if(result) + goto error; + + if(SSL_SET_OPTION(issuercert)) { + SECStatus ret = SECFailure; + char *nickname = dup_nickname(data, SSL_SET_OPTION(issuercert)); + if(nickname) { + /* we support only nicknames in case of issuercert for now */ + ret = check_issuer_cert(BACKEND->handle, nickname); + free(nickname); + } + + if(SECFailure == ret) { + infof(data, "SSL certificate issuer check failed\n"); + result = CURLE_SSL_ISSUER_ERROR; + goto error; + } + else { + infof(data, "SSL certificate issuer check ok\n"); + } + } + + result = cmp_peer_pubkey(connssl, pinnedpubkey); + if(result) + /* status already printed */ + goto error; + + return CURLE_OK; + +error: + return nss_fail_connect(connssl, data, result); +} + +static CURLcode nss_connect_common(struct connectdata *conn, int sockindex, + bool *done) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct Curl_easy *data = conn->data; + const bool blocking = (done == NULL); + CURLcode result; + + if(connssl->state == ssl_connection_complete) { + if(!blocking) + *done = TRUE; + return CURLE_OK; + } + + if(connssl->connecting_state == ssl_connect_1) { + result = nss_setup_connect(conn, sockindex); + if(result) + /* we do not expect CURLE_AGAIN from nss_setup_connect() */ + return result; + + connssl->connecting_state = ssl_connect_2; + } + + /* enable/disable blocking mode before handshake */ + result = nss_set_blocking(connssl, data, blocking); + if(result) + return result; + + result = nss_do_connect(conn, sockindex); + switch(result) { + case CURLE_OK: + break; + case CURLE_AGAIN: + if(!blocking) + /* CURLE_AGAIN in non-blocking mode is not an error */ + return CURLE_OK; + /* FALLTHROUGH */ + default: + return result; + } + + if(blocking) { + /* in blocking mode, set NSS non-blocking mode _after_ SSL handshake */ + result = nss_set_blocking(connssl, data, /* blocking */ FALSE); + if(result) + return result; + } + else + /* signal completed SSL handshake */ + *done = TRUE; + + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = nss_recv; + conn->send[sockindex] = nss_send; + + /* ssl_connect_done is never used outside, go back to the initial state */ + connssl->connecting_state = ssl_connect_1; + + return CURLE_OK; +} + +static CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) +{ + return nss_connect_common(conn, sockindex, /* blocking */ NULL); +} + +static CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn, + int sockindex, bool *done) +{ + return nss_connect_common(conn, sockindex, done); +} + +static ssize_t nss_send(struct connectdata *conn, /* connection data */ + int sockindex, /* socketindex */ + const void *mem, /* send this data */ + size_t len, /* amount to write */ + CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + ssize_t rc; + + /* The SelectClientCert() hook uses this for infof() and failf() but the + handle stored in nss_setup_connect() could have already been freed. */ + BACKEND->data = conn->data; + + rc = PR_Send(BACKEND->handle, mem, (int)len, 0, PR_INTERVAL_NO_WAIT); + if(rc < 0) { + PRInt32 err = PR_GetError(); + if(err == PR_WOULD_BLOCK_ERROR) + *curlcode = CURLE_AGAIN; + else { + /* print the error number and error string */ + const char *err_name = nss_error_to_name(err); + infof(conn->data, "SSL write: error %d (%s)\n", err, err_name); + + /* print a human-readable message describing the error if available */ + nss_print_error_message(conn->data, err); + + *curlcode = (is_cc_error(err)) + ? CURLE_SSL_CERTPROBLEM + : CURLE_SEND_ERROR; + } + + return -1; + } + + return rc; /* number of bytes */ +} + +static ssize_t nss_recv(struct connectdata *conn, /* connection data */ + int sockindex, /* socketindex */ + char *buf, /* store read data here */ + size_t buffersize, /* max amount to read */ + CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + ssize_t nread; + + /* The SelectClientCert() hook uses this for infof() and failf() but the + handle stored in nss_setup_connect() could have already been freed. */ + BACKEND->data = conn->data; + + nread = PR_Recv(BACKEND->handle, buf, (int)buffersize, 0, + PR_INTERVAL_NO_WAIT); + if(nread < 0) { + /* failed SSL read */ + PRInt32 err = PR_GetError(); + + if(err == PR_WOULD_BLOCK_ERROR) + *curlcode = CURLE_AGAIN; + else { + /* print the error number and error string */ + const char *err_name = nss_error_to_name(err); + infof(conn->data, "SSL read: errno %d (%s)\n", err, err_name); + + /* print a human-readable message describing the error if available */ + nss_print_error_message(conn->data, err); + + *curlcode = (is_cc_error(err)) + ? CURLE_SSL_CERTPROBLEM + : CURLE_RECV_ERROR; + } + + return -1; + } + + return nread; +} + +static size_t Curl_nss_version(char *buffer, size_t size) +{ + return msnprintf(buffer, size, "NSS/%s", NSS_VERSION); +} + +/* data might be NULL */ +static int Curl_nss_seed(struct Curl_easy *data) +{ + /* make sure that NSS is initialized */ + return !!Curl_nss_force_init(data); +} + +/* data might be NULL */ +static CURLcode Curl_nss_random(struct Curl_easy *data, + unsigned char *entropy, + size_t length) +{ + Curl_nss_seed(data); /* Initiate the seed if not already done */ + + if(SECSuccess != PK11_GenerateRandom(entropy, curlx_uztosi(length))) + /* signal a failure */ + return CURLE_FAILED_INIT; + + return CURLE_OK; +} + +static CURLcode Curl_nss_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len) +{ + PK11Context *MD5pw = PK11_CreateDigestContext(SEC_OID_MD5); + unsigned int MD5out; + + PK11_DigestOp(MD5pw, tmp, curlx_uztoui(tmplen)); + PK11_DigestFinal(MD5pw, md5sum, &MD5out, curlx_uztoui(md5len)); + PK11_DestroyContext(MD5pw, PR_TRUE); + + return CURLE_OK; +} + +static CURLcode Curl_nss_sha256sum(const unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *sha256sum, /* output */ + size_t sha256len) +{ + PK11Context *SHA256pw = PK11_CreateDigestContext(SEC_OID_SHA256); + unsigned int SHA256out; + + PK11_DigestOp(SHA256pw, tmp, curlx_uztoui(tmplen)); + PK11_DigestFinal(SHA256pw, sha256sum, &SHA256out, curlx_uztoui(sha256len)); + PK11_DestroyContext(SHA256pw, PR_TRUE); + + return CURLE_OK; +} + +static bool Curl_nss_cert_status_request(void) +{ +#ifdef SSL_ENABLE_OCSP_STAPLING + return TRUE; +#else + return FALSE; +#endif +} + +static bool Curl_nss_false_start(void) +{ +#if NSSVERNUM >= 0x030f04 /* 3.15.4 */ + return TRUE; +#else + return FALSE; +#endif +} + +static void *Curl_nss_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) +{ + (void)info; + return BACKEND->handle; +} + +const struct Curl_ssl Curl_ssl_nss = { + { CURLSSLBACKEND_NSS, "nss" }, /* info */ + + SSLSUPP_CA_PATH | + SSLSUPP_CERTINFO | + SSLSUPP_PINNEDPUBKEY | + SSLSUPP_HTTPS_PROXY, + + sizeof(struct ssl_backend_data), + + Curl_nss_init, /* init */ + Curl_nss_cleanup, /* cleanup */ + Curl_nss_version, /* version */ + Curl_nss_check_cxn, /* check_cxn */ + /* NSS has no shutdown function provided and thus always fail */ + Curl_none_shutdown, /* shutdown */ + Curl_none_data_pending, /* data_pending */ + Curl_nss_random, /* random */ + Curl_nss_cert_status_request, /* cert_status_request */ + Curl_nss_connect, /* connect */ + Curl_nss_connect_nonblocking, /* connect_nonblocking */ + Curl_nss_get_internals, /* get_internals */ + Curl_nss_close, /* close_one */ + Curl_none_close_all, /* close_all */ + /* NSS has its own session ID cache */ + Curl_none_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_nss_false_start, /* false_start */ + Curl_nss_md5sum, /* md5sum */ + Curl_nss_sha256sum /* sha256sum */ +}; + +#endif /* USE_NSS */ diff --git a/dependencies/cmcurl/lib/vtls/nssg.h b/dependencies/cmcurl/lib/vtls/nssg.h new file mode 100644 index 0000000..41e51b0 --- /dev/null +++ b/dependencies/cmcurl/lib/vtls/nssg.h @@ -0,0 +1,39 @@ +#ifndef HEADER_CURL_NSSG_H +#define HEADER_CURL_NSSG_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_NSS +/* + * This header should only be needed to get included by vtls.c and nss.c + */ + +#include "urldata.h" + +/* initialize NSS library if not already */ +CURLcode Curl_nss_force_init(struct Curl_easy *data); + +extern const struct Curl_ssl Curl_ssl_nss; + +#endif /* USE_NSS */ +#endif /* HEADER_CURL_NSSG_H */ diff --git a/dependencies/cmcurl/lib/vtls/openssl.c b/dependencies/cmcurl/lib/vtls/openssl.c new file mode 100644 index 0000000..85e9be6 --- /dev/null +++ b/dependencies/cmcurl/lib/vtls/openssl.c @@ -0,0 +1,3951 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all OpenSSL-specific code for the TLS/SSL layer. No code + * but vtls.c should ever call or use these functions. + */ + +/* + * The original SSLeay-using code for curl was written by Linas Vepstas and + * Sampo Kellomaki 1998. + */ + +#include "curl_setup.h" + +#ifdef USE_OPENSSL + +#include + +#include "urldata.h" +#include "sendf.h" +#include "formdata.h" /* for the boundary function */ +#include "url.h" /* for the ssl config check function */ +#include "inet_pton.h" +#include "openssl.h" +#include "connect.h" +#include "slist.h" +#include "select.h" +#include "vtls.h" +#include "strcase.h" +#include "hostcheck.h" +#include "multiif.h" +#include "curl_printf.h" +#include +#include +#include +#ifndef OPENSSL_NO_DSA +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef USE_AMISSL +#include "amigaos.h" +#endif + +#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_OCSP) +#include +#endif + +#if (OPENSSL_VERSION_NUMBER >= 0x0090700fL) && /* 0.9.7 or later */ \ + !defined(OPENSSL_NO_ENGINE) +#define USE_OPENSSL_ENGINE +#include +#endif + +#include "warnless.h" +#include "non-ascii.h" /* for Curl_convert_from_utf8 prototype */ + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* Uncomment the ALLOW_RENEG line to a real #define if you want to allow TLS + renegotiations when built with BoringSSL. Renegotiating is non-compliant + with HTTP/2 and "an extremely dangerous protocol feature". Beware. + +#define ALLOW_RENEG 1 + */ + +#ifndef OPENSSL_VERSION_NUMBER +#error "OPENSSL_VERSION_NUMBER not defined" +#endif + +#ifdef USE_OPENSSL_ENGINE +#include +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x00909000L +#define SSL_METHOD_QUAL const +#else +#define SSL_METHOD_QUAL +#endif + +#if (OPENSSL_VERSION_NUMBER >= 0x10000000L) +#define HAVE_ERR_REMOVE_THREAD_STATE 1 +#endif + +#if !defined(HAVE_SSLV2_CLIENT_METHOD) || \ + OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0+ has no SSLv2 */ +#undef OPENSSL_NO_SSL2 /* undef first to avoid compiler warnings */ +#define OPENSSL_NO_SSL2 +#endif + +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && /* OpenSSL 1.1.0+ */ \ + !(defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x20700000L) +#define SSLEAY_VERSION_NUMBER OPENSSL_VERSION_NUMBER +#define HAVE_X509_GET0_EXTENSIONS 1 /* added in 1.1.0 -pre1 */ +#define HAVE_OPAQUE_EVP_PKEY 1 /* since 1.1.0 -pre3 */ +#define HAVE_OPAQUE_RSA_DSA_DH 1 /* since 1.1.0 -pre5 */ +#define CONST_EXTS const +#define HAVE_ERR_REMOVE_THREAD_STATE_DEPRECATED 1 + +/* funny typecast define due to difference in API */ +#ifdef LIBRESSL_VERSION_NUMBER +#define ARG2_X509_signature_print (X509_ALGOR *) +#else +#define ARG2_X509_signature_print +#endif + +#else +/* For OpenSSL before 1.1.0 */ +#define ASN1_STRING_get0_data(x) ASN1_STRING_data(x) +#define X509_get0_notBefore(x) X509_get_notBefore(x) +#define X509_get0_notAfter(x) X509_get_notAfter(x) +#define CONST_EXTS /* nope */ +#ifndef LIBRESSL_VERSION_NUMBER +#define OpenSSL_version_num() SSLeay() +#endif +#endif + +#ifdef LIBRESSL_VERSION_NUMBER +#define OpenSSL_version_num() LIBRESSL_VERSION_NUMBER +#endif + +#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && /* 1.0.2 or later */ \ + !(defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x20700000L) +#define HAVE_X509_GET0_SIGNATURE 1 +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x10002003L && \ + OPENSSL_VERSION_NUMBER <= 0x10002FFFL && \ + !defined(OPENSSL_NO_COMP) +#define HAVE_SSL_COMP_FREE_COMPRESSION_METHODS 1 +#endif + +#if (OPENSSL_VERSION_NUMBER < 0x0090808fL) +/* not present in older OpenSSL */ +#define OPENSSL_load_builtin_modules(x) +#endif + +/* + * Whether SSL_CTX_set_keylog_callback is available. + * OpenSSL: supported since 1.1.1 https://github.com/openssl/openssl/pull/2287 + * BoringSSL: supported since d28f59c27bac (committed 2015-11-19) + * LibreSSL: unsupported in at least 2.7.2 (explicitly check for it since it + * lies and pretends to be OpenSSL 2.0.0). + */ +#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && \ + !defined(LIBRESSL_VERSION_NUMBER)) || \ + defined(OPENSSL_IS_BORINGSSL) +#define HAVE_KEYLOG_CALLBACK +#endif + +/* Whether SSL_CTX_set_ciphersuites is available. + * OpenSSL: supported since 1.1.1 (commit a53b5be6a05) + * BoringSSL: no + * LibreSSL: no + */ +#if ((OPENSSL_VERSION_NUMBER >= 0x10101000L) && \ + !defined(LIBRESSL_VERSION_NUMBER) && \ + !defined(OPENSSL_IS_BORINGSSL)) +#define HAVE_SSL_CTX_SET_CIPHERSUITES +#define HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH +#endif + +#if defined(LIBRESSL_VERSION_NUMBER) +#define OSSL_PACKAGE "LibreSSL" +#elif defined(OPENSSL_IS_BORINGSSL) +#define OSSL_PACKAGE "BoringSSL" +#else +#define OSSL_PACKAGE "OpenSSL" +#endif + +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) +/* up2date versions of OpenSSL maintain the default reasonably secure without + * breaking compatibility, so it is better not to override the default by curl + */ +#define DEFAULT_CIPHER_SELECTION NULL +#else +/* ... but it is not the case with old versions of OpenSSL */ +#define DEFAULT_CIPHER_SELECTION \ + "ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH" +#endif + +#define ENABLE_SSLKEYLOGFILE + +#ifdef ENABLE_SSLKEYLOGFILE +typedef struct ssl_tap_state { + int master_key_length; + unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH]; + unsigned char client_random[SSL3_RANDOM_SIZE]; +} ssl_tap_state_t; +#endif /* ENABLE_SSLKEYLOGFILE */ + +struct ssl_backend_data { + /* these ones requires specific SSL-types */ + SSL_CTX* ctx; + SSL* handle; + X509* server_cert; +#ifdef ENABLE_SSLKEYLOGFILE + /* tap_state holds the last seen master key if we're logging them */ + ssl_tap_state_t tap_state; +#endif +}; + +#define BACKEND connssl->backend + +/* + * Number of bytes to read from the random number seed file. This must be + * a finite value (because some entropy "files" like /dev/urandom have + * an infinite length), but must be large enough to provide enough + * entropy to properly seed OpenSSL's PRNG. + */ +#define RAND_LOAD_LENGTH 1024 + +#ifdef ENABLE_SSLKEYLOGFILE +/* The fp for the open SSLKEYLOGFILE, or NULL if not open */ +static FILE *keylog_file_fp; + +#ifdef HAVE_KEYLOG_CALLBACK +static void ossl_keylog_callback(const SSL *ssl, const char *line) +{ + (void)ssl; + + /* Using fputs here instead of fprintf since libcurl's fprintf replacement + may not be thread-safe. */ + if(keylog_file_fp && line && *line) { + char stackbuf[256]; + char *buf; + size_t linelen = strlen(line); + + if(linelen <= sizeof(stackbuf) - 2) + buf = stackbuf; + else { + buf = malloc(linelen + 2); + if(!buf) + return; + } + memcpy(buf, line, linelen); + buf[linelen] = '\n'; + buf[linelen + 1] = '\0'; + + fputs(buf, keylog_file_fp); + if(buf != stackbuf) + free(buf); + } +} +#else +#define KEYLOG_PREFIX "CLIENT_RANDOM " +#define KEYLOG_PREFIX_LEN (sizeof(KEYLOG_PREFIX) - 1) +/* + * tap_ssl_key is called by libcurl to make the CLIENT_RANDOMs if the OpenSSL + * being used doesn't have native support for doing that. + */ +static void tap_ssl_key(const SSL *ssl, ssl_tap_state_t *state) +{ + const char *hex = "0123456789ABCDEF"; + int pos, i; + char line[KEYLOG_PREFIX_LEN + 2 * SSL3_RANDOM_SIZE + 1 + + 2 * SSL_MAX_MASTER_KEY_LENGTH + 1 + 1]; + const SSL_SESSION *session = SSL_get_session(ssl); + unsigned char client_random[SSL3_RANDOM_SIZE]; + unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH]; + int master_key_length = 0; + + if(!session || !keylog_file_fp) + return; + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ + !(defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x20700000L) + /* ssl->s3 is not checked in openssl 1.1.0-pre6, but let's assume that + * we have a valid SSL context if we have a non-NULL session. */ + SSL_get_client_random(ssl, client_random, SSL3_RANDOM_SIZE); + master_key_length = (int) + SSL_SESSION_get_master_key(session, master_key, SSL_MAX_MASTER_KEY_LENGTH); +#else + if(ssl->s3 && session->master_key_length > 0) { + master_key_length = session->master_key_length; + memcpy(master_key, session->master_key, session->master_key_length); + memcpy(client_random, ssl->s3->client_random, SSL3_RANDOM_SIZE); + } +#endif + + if(master_key_length <= 0) + return; + + /* Skip writing keys if there is no key or it did not change. */ + if(state->master_key_length == master_key_length && + !memcmp(state->master_key, master_key, master_key_length) && + !memcmp(state->client_random, client_random, SSL3_RANDOM_SIZE)) { + return; + } + + state->master_key_length = master_key_length; + memcpy(state->master_key, master_key, master_key_length); + memcpy(state->client_random, client_random, SSL3_RANDOM_SIZE); + + memcpy(line, KEYLOG_PREFIX, KEYLOG_PREFIX_LEN); + pos = KEYLOG_PREFIX_LEN; + + /* Client Random for SSLv3/TLS */ + for(i = 0; i < SSL3_RANDOM_SIZE; i++) { + line[pos++] = hex[client_random[i] >> 4]; + line[pos++] = hex[client_random[i] & 0xF]; + } + line[pos++] = ' '; + + /* Master Secret (size is at most SSL_MAX_MASTER_KEY_LENGTH) */ + for(i = 0; i < master_key_length; i++) { + line[pos++] = hex[master_key[i] >> 4]; + line[pos++] = hex[master_key[i] & 0xF]; + } + line[pos++] = '\n'; + line[pos] = '\0'; + + /* Using fputs here instead of fprintf since libcurl's fprintf replacement + may not be thread-safe. */ + fputs(line, keylog_file_fp); +} +#endif /* !HAVE_KEYLOG_CALLBACK */ +#endif /* ENABLE_SSLKEYLOGFILE */ + +static const char *SSL_ERROR_to_str(int err) +{ + switch(err) { + case SSL_ERROR_NONE: + return "SSL_ERROR_NONE"; + case SSL_ERROR_SSL: + return "SSL_ERROR_SSL"; + case SSL_ERROR_WANT_READ: + return "SSL_ERROR_WANT_READ"; + case SSL_ERROR_WANT_WRITE: + return "SSL_ERROR_WANT_WRITE"; + case SSL_ERROR_WANT_X509_LOOKUP: + return "SSL_ERROR_WANT_X509_LOOKUP"; + case SSL_ERROR_SYSCALL: + return "SSL_ERROR_SYSCALL"; + case SSL_ERROR_ZERO_RETURN: + return "SSL_ERROR_ZERO_RETURN"; + case SSL_ERROR_WANT_CONNECT: + return "SSL_ERROR_WANT_CONNECT"; + case SSL_ERROR_WANT_ACCEPT: + return "SSL_ERROR_WANT_ACCEPT"; +#if defined(SSL_ERROR_WANT_ASYNC) + case SSL_ERROR_WANT_ASYNC: + return "SSL_ERROR_WANT_ASYNC"; +#endif +#if defined(SSL_ERROR_WANT_ASYNC_JOB) + case SSL_ERROR_WANT_ASYNC_JOB: + return "SSL_ERROR_WANT_ASYNC_JOB"; +#endif +#if defined(SSL_ERROR_WANT_EARLY) + case SSL_ERROR_WANT_EARLY: + return "SSL_ERROR_WANT_EARLY"; +#endif + default: + return "SSL_ERROR unknown"; + } +} + +/* Return error string for last OpenSSL error + */ +static char *ossl_strerror(unsigned long error, char *buf, size_t size) +{ + ERR_error_string_n(error, buf, size); + return buf; +} + +/* Return an extra data index for the connection data. + * This index can be used with SSL_get_ex_data() and SSL_set_ex_data(). + */ +static int ossl_get_ssl_conn_index(void) +{ + static int ssl_ex_data_conn_index = -1; + if(ssl_ex_data_conn_index < 0) { + ssl_ex_data_conn_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); + } + return ssl_ex_data_conn_index; +} + +/* Return an extra data index for the sockindex. + * This index can be used with SSL_get_ex_data() and SSL_set_ex_data(). + */ +static int ossl_get_ssl_sockindex_index(void) +{ + static int ssl_ex_data_sockindex_index = -1; + if(ssl_ex_data_sockindex_index < 0) { + ssl_ex_data_sockindex_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, + NULL); + } + return ssl_ex_data_sockindex_index; +} + +static int passwd_callback(char *buf, int num, int encrypting, + void *global_passwd) +{ + DEBUGASSERT(0 == encrypting); + + if(!encrypting) { + int klen = curlx_uztosi(strlen((char *)global_passwd)); + if(num > klen) { + memcpy(buf, global_passwd, klen + 1); + return klen; + } + } + return 0; +} + +/* + * rand_enough() returns TRUE if we have seeded the random engine properly. + */ +static bool rand_enough(void) +{ + return (0 != RAND_status()) ? TRUE : FALSE; +} + +static CURLcode Curl_ossl_seed(struct Curl_easy *data) +{ + /* we have the "SSL is seeded" boolean static to prevent multiple + time-consuming seedings in vain */ + static bool ssl_seeded = FALSE; + char fname[256]; + + if(ssl_seeded) + return CURLE_OK; + + if(rand_enough()) { + /* OpenSSL 1.1.0+ will return here */ + ssl_seeded = TRUE; + return CURLE_OK; + } + +#ifndef RANDOM_FILE + /* if RANDOM_FILE isn't defined, we only perform this if an option tells + us to! */ + if(data->set.str[STRING_SSL_RANDOM_FILE]) +#define RANDOM_FILE "" /* doesn't matter won't be used */ +#endif + { + /* let the option override the define */ + RAND_load_file((data->set.str[STRING_SSL_RANDOM_FILE]? + data->set.str[STRING_SSL_RANDOM_FILE]: + RANDOM_FILE), + RAND_LOAD_LENGTH); + if(rand_enough()) + return CURLE_OK; + } + +#if defined(HAVE_RAND_EGD) + /* only available in OpenSSL 0.9.5 and later */ + /* EGD_SOCKET is set at configure time or not at all */ +#ifndef EGD_SOCKET + /* If we don't have the define set, we only do this if the egd-option + is set */ + if(data->set.str[STRING_SSL_EGDSOCKET]) +#define EGD_SOCKET "" /* doesn't matter won't be used */ +#endif + { + /* If there's an option and a define, the option overrides the + define */ + int ret = RAND_egd(data->set.str[STRING_SSL_EGDSOCKET]? + data->set.str[STRING_SSL_EGDSOCKET]:EGD_SOCKET); + if(-1 != ret) { + if(rand_enough()) + return CURLE_OK; + } + } +#endif + + /* fallback to a custom seeding of the PRNG using a hash based on a current + time */ + do { + unsigned char randb[64]; + size_t len = sizeof(randb); + size_t i, i_max; + for(i = 0, i_max = len / sizeof(struct curltime); i < i_max; ++i) { + struct curltime tv = Curl_now(); + Curl_wait_ms(1); + tv.tv_sec *= i + 1; + tv.tv_usec *= (unsigned int)i + 2; + tv.tv_sec ^= ((Curl_now().tv_sec + Curl_now().tv_usec) * + (i + 3)) << 8; + tv.tv_usec ^= (unsigned int) ((Curl_now().tv_sec + + Curl_now().tv_usec) * + (i + 4)) << 16; + memcpy(&randb[i * sizeof(struct curltime)], &tv, + sizeof(struct curltime)); + } + RAND_add(randb, (int)len, (double)len/2); + } while(!rand_enough()); + + /* generates a default path for the random seed file */ + fname[0] = 0; /* blank it first */ + RAND_file_name(fname, sizeof(fname)); + if(fname[0]) { + /* we got a file name to try */ + RAND_load_file(fname, RAND_LOAD_LENGTH); + if(rand_enough()) + return CURLE_OK; + } + + infof(data, "libcurl is now using a weak random seed!\n"); + return (rand_enough() ? CURLE_OK : + CURLE_SSL_CONNECT_ERROR /* confusing error code */); +} + +#ifndef SSL_FILETYPE_ENGINE +#define SSL_FILETYPE_ENGINE 42 +#endif +#ifndef SSL_FILETYPE_PKCS12 +#define SSL_FILETYPE_PKCS12 43 +#endif +static int do_file_type(const char *type) +{ + if(!type || !type[0]) + return SSL_FILETYPE_PEM; + if(strcasecompare(type, "PEM")) + return SSL_FILETYPE_PEM; + if(strcasecompare(type, "DER")) + return SSL_FILETYPE_ASN1; + if(strcasecompare(type, "ENG")) + return SSL_FILETYPE_ENGINE; + if(strcasecompare(type, "P12")) + return SSL_FILETYPE_PKCS12; + return -1; +} + +#ifdef USE_OPENSSL_ENGINE +/* + * Supply default password to the engine user interface conversation. + * The password is passed by OpenSSL engine from ENGINE_load_private_key() + * last argument to the ui and can be obtained by UI_get0_user_data(ui) here. + */ +static int ssl_ui_reader(UI *ui, UI_STRING *uis) +{ + const char *password; + switch(UI_get_string_type(uis)) { + case UIT_PROMPT: + case UIT_VERIFY: + password = (const char *)UI_get0_user_data(ui); + if(password && (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD)) { + UI_set_result(ui, uis, password); + return 1; + } + default: + break; + } + return (UI_method_get_reader(UI_OpenSSL()))(ui, uis); +} + +/* + * Suppress interactive request for a default password if available. + */ +static int ssl_ui_writer(UI *ui, UI_STRING *uis) +{ + switch(UI_get_string_type(uis)) { + case UIT_PROMPT: + case UIT_VERIFY: + if(UI_get0_user_data(ui) && + (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD)) { + return 1; + } + default: + break; + } + return (UI_method_get_writer(UI_OpenSSL()))(ui, uis); +} + +/* + * Check if a given string is a PKCS#11 URI + */ +static bool is_pkcs11_uri(const char *string) +{ + return (string && strncasecompare(string, "pkcs11:", 7)); +} + +#endif + +static CURLcode Curl_ossl_set_engine(struct Curl_easy *data, + const char *engine); + +static +int cert_stuff(struct connectdata *conn, + SSL_CTX* ctx, + char *cert_file, + const char *cert_type, + char *key_file, + const char *key_type, + char *key_passwd) +{ + struct Curl_easy *data = conn->data; + char error_buffer[256]; + bool check_privkey = TRUE; + + int file_type = do_file_type(cert_type); + + if(cert_file || (file_type == SSL_FILETYPE_ENGINE)) { + SSL *ssl; + X509 *x509; + int cert_done = 0; + + if(key_passwd) { + /* set the password in the callback userdata */ + SSL_CTX_set_default_passwd_cb_userdata(ctx, key_passwd); + /* Set passwd callback: */ + SSL_CTX_set_default_passwd_cb(ctx, passwd_callback); + } + + + switch(file_type) { + case SSL_FILETYPE_PEM: + /* SSL_CTX_use_certificate_chain_file() only works on PEM files */ + if(SSL_CTX_use_certificate_chain_file(ctx, + cert_file) != 1) { + failf(data, + "could not load PEM client certificate, " OSSL_PACKAGE + " error %s, " + "(no key found, wrong pass phrase, or wrong file format?)", + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer)) ); + return 0; + } + break; + + case SSL_FILETYPE_ASN1: + /* SSL_CTX_use_certificate_file() works with either PEM or ASN1, but + we use the case above for PEM so this can only be performed with + ASN1 files. */ + if(SSL_CTX_use_certificate_file(ctx, + cert_file, + file_type) != 1) { + failf(data, + "could not load ASN1 client certificate, " OSSL_PACKAGE + " error %s, " + "(no key found, wrong pass phrase, or wrong file format?)", + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer)) ); + return 0; + } + break; + case SSL_FILETYPE_ENGINE: +#if defined(USE_OPENSSL_ENGINE) && defined(ENGINE_CTRL_GET_CMD_FROM_NAME) + { + /* Implicitly use pkcs11 engine if none was provided and the + * cert_file is a PKCS#11 URI */ + if(!data->state.engine) { + if(is_pkcs11_uri(cert_file)) { + if(Curl_ossl_set_engine(data, "pkcs11") != CURLE_OK) { + return 0; + } + } + } + + if(data->state.engine) { + const char *cmd_name = "LOAD_CERT_CTRL"; + struct { + const char *cert_id; + X509 *cert; + } params; + + params.cert_id = cert_file; + params.cert = NULL; + + /* Does the engine supports LOAD_CERT_CTRL ? */ + if(!ENGINE_ctrl(data->state.engine, ENGINE_CTRL_GET_CMD_FROM_NAME, + 0, (void *)cmd_name, NULL)) { + failf(data, "ssl engine does not support loading certificates"); + return 0; + } + + /* Load the certificate from the engine */ + if(!ENGINE_ctrl_cmd(data->state.engine, cmd_name, + 0, ¶ms, NULL, 1)) { + failf(data, "ssl engine cannot load client cert with id" + " '%s' [%s]", cert_file, + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer))); + return 0; + } + + if(!params.cert) { + failf(data, "ssl engine didn't initialized the certificate " + "properly."); + return 0; + } + + if(SSL_CTX_use_certificate(ctx, params.cert) != 1) { + failf(data, "unable to set client certificate"); + X509_free(params.cert); + return 0; + } + X509_free(params.cert); /* we don't need the handle any more... */ + } + else { + failf(data, "crypto engine not set, can't load certificate"); + return 0; + } + } + break; +#else + failf(data, "file type ENG for certificate not implemented"); + return 0; +#endif + + case SSL_FILETYPE_PKCS12: + { + BIO *fp = NULL; + PKCS12 *p12 = NULL; + EVP_PKEY *pri; + STACK_OF(X509) *ca = NULL; + + fp = BIO_new(BIO_s_file()); + if(fp == NULL) { + failf(data, + "BIO_new return NULL, " OSSL_PACKAGE + " error %s", + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer)) ); + return 0; + } + + if(BIO_read_filename(fp, cert_file) <= 0) { + failf(data, "could not open PKCS12 file '%s'", cert_file); + BIO_free(fp); + return 0; + } + p12 = d2i_PKCS12_bio(fp, NULL); + BIO_free(fp); + + if(!p12) { + failf(data, "error reading PKCS12 file '%s'", cert_file); + return 0; + } + + PKCS12_PBE_add(); + + if(!PKCS12_parse(p12, key_passwd, &pri, &x509, + &ca)) { + failf(data, + "could not parse PKCS12 file, check password, " OSSL_PACKAGE + " error %s", + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer)) ); + PKCS12_free(p12); + return 0; + } + + PKCS12_free(p12); + + if(SSL_CTX_use_certificate(ctx, x509) != 1) { + failf(data, + "could not load PKCS12 client certificate, " OSSL_PACKAGE + " error %s", + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer)) ); + goto fail; + } + + if(SSL_CTX_use_PrivateKey(ctx, pri) != 1) { + failf(data, "unable to use private key from PKCS12 file '%s'", + cert_file); + goto fail; + } + + if(!SSL_CTX_check_private_key (ctx)) { + failf(data, "private key from PKCS12 file '%s' " + "does not match certificate in same file", cert_file); + goto fail; + } + /* Set Certificate Verification chain */ + if(ca) { + while(sk_X509_num(ca)) { + /* + * Note that sk_X509_pop() is used below to make sure the cert is + * removed from the stack properly before getting passed to + * SSL_CTX_add_extra_chain_cert(), which takes ownership. Previously + * we used sk_X509_value() instead, but then we'd clean it in the + * subsequent sk_X509_pop_free() call. + */ + X509 *x = sk_X509_pop(ca); + if(!SSL_CTX_add_client_CA(ctx, x)) { + X509_free(x); + failf(data, "cannot add certificate to client CA list"); + goto fail; + } + if(!SSL_CTX_add_extra_chain_cert(ctx, x)) { + X509_free(x); + failf(data, "cannot add certificate to certificate chain"); + goto fail; + } + } + } + + cert_done = 1; + fail: + EVP_PKEY_free(pri); + X509_free(x509); +#ifdef USE_AMISSL + sk_X509_pop_free(ca, Curl_amiga_X509_free); +#else + sk_X509_pop_free(ca, X509_free); +#endif + if(!cert_done) + return 0; /* failure! */ + break; + } + default: + failf(data, "not supported file type '%s' for certificate", cert_type); + return 0; + } + + if(!key_file) + key_file = cert_file; + else + file_type = do_file_type(key_type); + + switch(file_type) { + case SSL_FILETYPE_PEM: + if(cert_done) + break; + /* FALLTHROUGH */ + case SSL_FILETYPE_ASN1: + if(SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type) != 1) { + failf(data, "unable to set private key file: '%s' type %s", + key_file, key_type?key_type:"PEM"); + return 0; + } + break; + case SSL_FILETYPE_ENGINE: +#ifdef USE_OPENSSL_ENGINE + { /* XXXX still needs some work */ + EVP_PKEY *priv_key = NULL; + + /* Implicitly use pkcs11 engine if none was provided and the + * key_file is a PKCS#11 URI */ + if(!data->state.engine) { + if(is_pkcs11_uri(key_file)) { + if(Curl_ossl_set_engine(data, "pkcs11") != CURLE_OK) { + return 0; + } + } + } + + if(data->state.engine) { + UI_METHOD *ui_method = + UI_create_method((char *)"curl user interface"); + if(!ui_method) { + failf(data, "unable do create " OSSL_PACKAGE + " user-interface method"); + return 0; + } + UI_method_set_opener(ui_method, UI_method_get_opener(UI_OpenSSL())); + UI_method_set_closer(ui_method, UI_method_get_closer(UI_OpenSSL())); + UI_method_set_reader(ui_method, ssl_ui_reader); + UI_method_set_writer(ui_method, ssl_ui_writer); + /* the typecast below was added to please mingw32 */ + priv_key = (EVP_PKEY *) + ENGINE_load_private_key(data->state.engine, key_file, + ui_method, + key_passwd); + UI_destroy_method(ui_method); + if(!priv_key) { + failf(data, "failed to load private key from crypto engine"); + return 0; + } + if(SSL_CTX_use_PrivateKey(ctx, priv_key) != 1) { + failf(data, "unable to set private key"); + EVP_PKEY_free(priv_key); + return 0; + } + EVP_PKEY_free(priv_key); /* we don't need the handle any more... */ + } + else { + failf(data, "crypto engine not set, can't load private key"); + return 0; + } + } + break; +#else + failf(data, "file type ENG for private key not supported"); + return 0; +#endif + case SSL_FILETYPE_PKCS12: + if(!cert_done) { + failf(data, "file type P12 for private key not supported"); + return 0; + } + break; + default: + failf(data, "not supported file type for private key"); + return 0; + } + + ssl = SSL_new(ctx); + if(!ssl) { + failf(data, "unable to create an SSL structure"); + return 0; + } + + x509 = SSL_get_certificate(ssl); + + /* This version was provided by Evan Jordan and is supposed to not + leak memory as the previous version: */ + if(x509) { + EVP_PKEY *pktmp = X509_get_pubkey(x509); + EVP_PKEY_copy_parameters(pktmp, SSL_get_privatekey(ssl)); + EVP_PKEY_free(pktmp); + } + +#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_IS_BORINGSSL) + { + /* If RSA is used, don't check the private key if its flags indicate + * it doesn't support it. */ + EVP_PKEY *priv_key = SSL_get_privatekey(ssl); + int pktype; +#ifdef HAVE_OPAQUE_EVP_PKEY + pktype = EVP_PKEY_id(priv_key); +#else + pktype = priv_key->type; +#endif + if(pktype == EVP_PKEY_RSA) { + RSA *rsa = EVP_PKEY_get1_RSA(priv_key); + if(RSA_flags(rsa) & RSA_METHOD_FLAG_NO_CHECK) + check_privkey = FALSE; + RSA_free(rsa); /* Decrement reference count */ + } + } +#endif + + SSL_free(ssl); + + /* If we are using DSA, we can copy the parameters from + * the private key */ + + if(check_privkey == TRUE) { + /* Now we know that a key and cert have been set against + * the SSL context */ + if(!SSL_CTX_check_private_key(ctx)) { + failf(data, "Private key does not match the certificate public key"); + return 0; + } + } + } + return 1; +} + +/* returns non-zero on failure */ +static int x509_name_oneline(X509_NAME *a, char *buf, size_t size) +{ +#if 0 + return X509_NAME_oneline(a, buf, size); +#else + BIO *bio_out = BIO_new(BIO_s_mem()); + BUF_MEM *biomem; + int rc; + + if(!bio_out) + return 1; /* alloc failed! */ + + rc = X509_NAME_print_ex(bio_out, a, 0, XN_FLAG_SEP_SPLUS_SPC); + BIO_get_mem_ptr(bio_out, &biomem); + + if((size_t)biomem->length < size) + size = biomem->length; + else + size--; /* don't overwrite the buffer end */ + + memcpy(buf, biomem->data, size); + buf[size] = 0; + + BIO_free(bio_out); + + return !rc; +#endif +} + +/** + * Global SSL init + * + * @retval 0 error initializing SSL + * @retval 1 SSL initialized successfully + */ +static int Curl_ossl_init(void) +{ +#ifdef ENABLE_SSLKEYLOGFILE + char *keylog_file_name; +#endif + + OPENSSL_load_builtin_modules(); + +#ifdef USE_OPENSSL_ENGINE + ENGINE_load_builtin_engines(); +#endif + + /* OPENSSL_config(NULL); is "strongly recommended" to use but unfortunately + that function makes an exit() call on wrongly formatted config files + which makes it hard to use in some situations. OPENSSL_config() itself + calls CONF_modules_load_file() and we use that instead and we ignore + its return code! */ + + /* CONF_MFLAGS_DEFAULT_SECTION introduced some time between 0.9.8b and + 0.9.8e */ +#ifndef CONF_MFLAGS_DEFAULT_SECTION +#define CONF_MFLAGS_DEFAULT_SECTION 0x0 +#endif + +#ifndef CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG + CONF_modules_load_file(NULL, NULL, + CONF_MFLAGS_DEFAULT_SECTION| + CONF_MFLAGS_IGNORE_MISSING_FILE); +#endif + +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \ + !defined(LIBRESSL_VERSION_NUMBER) + /* OpenSSL 1.1.0+ takes care of initialization itself */ +#else + /* Lets get nice error messages */ + SSL_load_error_strings(); + + /* Init the global ciphers and digests */ + if(!SSLeay_add_ssl_algorithms()) + return 0; + + OpenSSL_add_all_algorithms(); +#endif + +#ifdef ENABLE_SSLKEYLOGFILE + if(!keylog_file_fp) { + keylog_file_name = curl_getenv("SSLKEYLOGFILE"); + if(keylog_file_name) { + keylog_file_fp = fopen(keylog_file_name, FOPEN_APPENDTEXT); + if(keylog_file_fp) { +#ifdef WIN32 + if(setvbuf(keylog_file_fp, NULL, _IONBF, 0)) +#else + if(setvbuf(keylog_file_fp, NULL, _IOLBF, 4096)) +#endif + { + fclose(keylog_file_fp); + keylog_file_fp = NULL; + } + } + Curl_safefree(keylog_file_name); + } + } +#endif + + /* Initialize the extra data indexes */ + if(ossl_get_ssl_conn_index() < 0 || ossl_get_ssl_sockindex_index() < 0) + return 0; + + return 1; +} + +/* Global cleanup */ +static void Curl_ossl_cleanup(void) +{ +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \ + !defined(LIBRESSL_VERSION_NUMBER) + /* OpenSSL 1.1 deprecates all these cleanup functions and + turns them into no-ops in OpenSSL 1.0 compatibility mode */ +#else + /* Free ciphers and digests lists */ + EVP_cleanup(); + +#ifdef USE_OPENSSL_ENGINE + /* Free engine list */ + ENGINE_cleanup(); +#endif + + /* Free OpenSSL error strings */ + ERR_free_strings(); + + /* Free thread local error state, destroying hash upon zero refcount */ +#ifdef HAVE_ERR_REMOVE_THREAD_STATE + ERR_remove_thread_state(NULL); +#else + ERR_remove_state(0); +#endif + + /* Free all memory allocated by all configuration modules */ + CONF_modules_free(); + +#ifdef HAVE_SSL_COMP_FREE_COMPRESSION_METHODS + SSL_COMP_free_compression_methods(); +#endif +#endif + +#ifdef ENABLE_SSLKEYLOGFILE + if(keylog_file_fp) { + fclose(keylog_file_fp); + keylog_file_fp = NULL; + } +#endif +} + +/* + * This function is used to determine connection status. + * + * Return codes: + * 1 means the connection is still in place + * 0 means the connection has been closed + * -1 means the connection status is unknown + */ +static int Curl_ossl_check_cxn(struct connectdata *conn) +{ + /* SSL_peek takes data out of the raw recv buffer without peeking so we use + recv MSG_PEEK instead. Bug #795 */ +#ifdef MSG_PEEK + char buf; + ssize_t nread; + nread = recv((RECV_TYPE_ARG1)conn->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf, + (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK); + if(nread == 0) + return 0; /* connection has been closed */ + if(nread == 1) + return 1; /* connection still in place */ + else if(nread == -1) { + int err = SOCKERRNO; + if(err == EINPROGRESS || +#if defined(EAGAIN) && (EAGAIN != EWOULDBLOCK) + err == EAGAIN || +#endif + err == EWOULDBLOCK) + return 1; /* connection still in place */ + if(err == ECONNRESET || +#ifdef ECONNABORTED + err == ECONNABORTED || +#endif +#ifdef ENETDOWN + err == ENETDOWN || +#endif +#ifdef ENETRESET + err == ENETRESET || +#endif +#ifdef ESHUTDOWN + err == ESHUTDOWN || +#endif +#ifdef ETIMEDOUT + err == ETIMEDOUT || +#endif + err == ENOTCONN) + return 0; /* connection has been closed */ + } +#endif + return -1; /* connection status unknown */ +} + +/* Selects an OpenSSL crypto engine + */ +static CURLcode Curl_ossl_set_engine(struct Curl_easy *data, + const char *engine) +{ +#ifdef USE_OPENSSL_ENGINE + ENGINE *e; + +#if OPENSSL_VERSION_NUMBER >= 0x00909000L + e = ENGINE_by_id(engine); +#else + /* avoid memory leak */ + for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) { + const char *e_id = ENGINE_get_id(e); + if(!strcmp(engine, e_id)) + break; + } +#endif + + if(!e) { + failf(data, "SSL Engine '%s' not found", engine); + return CURLE_SSL_ENGINE_NOTFOUND; + } + + if(data->state.engine) { + ENGINE_finish(data->state.engine); + ENGINE_free(data->state.engine); + data->state.engine = NULL; + } + if(!ENGINE_init(e)) { + char buf[256]; + + ENGINE_free(e); + failf(data, "Failed to initialise SSL Engine '%s':\n%s", + engine, ossl_strerror(ERR_get_error(), buf, sizeof(buf))); + return CURLE_SSL_ENGINE_INITFAILED; + } + data->state.engine = e; + return CURLE_OK; +#else + (void)engine; + failf(data, "SSL Engine not supported"); + return CURLE_SSL_ENGINE_NOTFOUND; +#endif +} + +/* Sets engine as default for all SSL operations + */ +static CURLcode Curl_ossl_set_engine_default(struct Curl_easy *data) +{ +#ifdef USE_OPENSSL_ENGINE + if(data->state.engine) { + if(ENGINE_set_default(data->state.engine, ENGINE_METHOD_ALL) > 0) { + infof(data, "set default crypto engine '%s'\n", + ENGINE_get_id(data->state.engine)); + } + else { + failf(data, "set default crypto engine '%s' failed", + ENGINE_get_id(data->state.engine)); + return CURLE_SSL_ENGINE_SETFAILED; + } + } +#else + (void) data; +#endif + return CURLE_OK; +} + +/* Return list of OpenSSL crypto engine names. + */ +static struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data) +{ + struct curl_slist *list = NULL; +#ifdef USE_OPENSSL_ENGINE + struct curl_slist *beg; + ENGINE *e; + + for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) { + beg = curl_slist_append(list, ENGINE_get_id(e)); + if(!beg) { + curl_slist_free_all(list); + return NULL; + } + list = beg; + } +#endif + (void) data; + return list; +} + + +static void ossl_close(struct ssl_connect_data *connssl) +{ + if(BACKEND->handle) { + (void)SSL_shutdown(BACKEND->handle); + SSL_set_connect_state(BACKEND->handle); + + SSL_free(BACKEND->handle); + BACKEND->handle = NULL; + } + if(BACKEND->ctx) { + SSL_CTX_free(BACKEND->ctx); + BACKEND->ctx = NULL; + } +} + +/* + * This function is called when an SSL connection is closed. + */ +static void Curl_ossl_close(struct connectdata *conn, int sockindex) +{ + ossl_close(&conn->ssl[sockindex]); + ossl_close(&conn->proxy_ssl[sockindex]); +} + +/* + * This function is called to shut down the SSL layer but keep the + * socket open (CCC - Clear Command Channel) + */ +static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex) +{ + int retval = 0; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct Curl_easy *data = conn->data; + char buf[256]; /* We will use this for the OpenSSL error buffer, so it has + to be at least 256 bytes long. */ + unsigned long sslerror; + ssize_t nread; + int buffsize; + int err; + bool done = FALSE; + +#ifndef CURL_DISABLE_FTP + /* This has only been tested on the proftpd server, and the mod_tls code + sends a close notify alert without waiting for a close notify alert in + response. Thus we wait for a close notify alert from the server, but + we do not send one. Let's hope other servers do the same... */ + + if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) + (void)SSL_shutdown(BACKEND->handle); +#endif + + if(BACKEND->handle) { + buffsize = (int)sizeof(buf); + while(!done) { + int what = SOCKET_READABLE(conn->sock[sockindex], + SSL_SHUTDOWN_TIMEOUT); + if(what > 0) { + ERR_clear_error(); + + /* Something to read, let's do it and hope that it is the close + notify alert from the server */ + nread = (ssize_t)SSL_read(BACKEND->handle, buf, buffsize); + err = SSL_get_error(BACKEND->handle, (int)nread); + + switch(err) { + case SSL_ERROR_NONE: /* this is not an error */ + case SSL_ERROR_ZERO_RETURN: /* no more data */ + /* This is the expected response. There was no data but only + the close notify alert */ + done = TRUE; + break; + case SSL_ERROR_WANT_READ: + /* there's data pending, re-invoke SSL_read() */ + infof(data, "SSL_ERROR_WANT_READ\n"); + break; + case SSL_ERROR_WANT_WRITE: + /* SSL wants a write. Really odd. Let's bail out. */ + infof(data, "SSL_ERROR_WANT_WRITE\n"); + done = TRUE; + break; + default: + /* openssl/ssl.h says "look at error stack/return value/errno" */ + sslerror = ERR_get_error(); + failf(conn->data, OSSL_PACKAGE " SSL_read on shutdown: %s, errno %d", + (sslerror ? + ossl_strerror(sslerror, buf, sizeof(buf)) : + SSL_ERROR_to_str(err)), + SOCKERRNO); + done = TRUE; + break; + } + } + else if(0 == what) { + /* timeout */ + failf(data, "SSL shutdown timeout"); + done = TRUE; + } + else { + /* anything that gets here is fatally bad */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + retval = -1; + done = TRUE; + } + } /* while()-loop for the select() */ + + if(data->set.verbose) { +#ifdef HAVE_SSL_GET_SHUTDOWN + switch(SSL_get_shutdown(BACKEND->handle)) { + case SSL_SENT_SHUTDOWN: + infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN\n"); + break; + case SSL_RECEIVED_SHUTDOWN: + infof(data, "SSL_get_shutdown() returned SSL_RECEIVED_SHUTDOWN\n"); + break; + case SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN: + infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN|" + "SSL_RECEIVED__SHUTDOWN\n"); + break; + } +#endif + } + + SSL_free(BACKEND->handle); + BACKEND->handle = NULL; + } + return retval; +} + +static void Curl_ossl_session_free(void *ptr) +{ + /* free the ID */ + SSL_SESSION_free(ptr); +} + +/* + * This function is called when the 'data' struct is going away. Close + * down everything and free all resources! + */ +static void Curl_ossl_close_all(struct Curl_easy *data) +{ +#ifdef USE_OPENSSL_ENGINE + if(data->state.engine) { + ENGINE_finish(data->state.engine); + ENGINE_free(data->state.engine); + data->state.engine = NULL; + } +#else + (void)data; +#endif +#if !defined(HAVE_ERR_REMOVE_THREAD_STATE_DEPRECATED) && \ + defined(HAVE_ERR_REMOVE_THREAD_STATE) + /* OpenSSL 1.0.1 and 1.0.2 build an error queue that is stored per-thread + so we need to clean it here in case the thread will be killed. All OpenSSL + code should extract the error in association with the error so clearing + this queue here should be harmless at worst. */ + ERR_remove_thread_state(NULL); +#endif +} + +/* ====================================================== */ + +/* + * Match subjectAltName against the host name. This requires a conversion + * in CURL_DOES_CONVERSIONS builds. + */ +static bool subj_alt_hostcheck(struct Curl_easy *data, + const char *match_pattern, const char *hostname, + const char *dispname) +#ifdef CURL_DOES_CONVERSIONS +{ + bool res = FALSE; + + /* Curl_cert_hostcheck uses host encoding, but we get ASCII from + OpenSSl. + */ + char *match_pattern2 = strdup(match_pattern); + + if(match_pattern2) { + if(Curl_convert_from_network(data, match_pattern2, + strlen(match_pattern2)) == CURLE_OK) { + if(Curl_cert_hostcheck(match_pattern2, hostname)) { + res = TRUE; + infof(data, + " subjectAltName: host \"%s\" matched cert's \"%s\"\n", + dispname, match_pattern2); + } + } + free(match_pattern2); + } + else { + failf(data, + "SSL: out of memory when allocating temporary for subjectAltName"); + } + return res; +} +#else +{ +#ifdef CURL_DISABLE_VERBOSE_STRINGS + (void)dispname; + (void)data; +#endif + if(Curl_cert_hostcheck(match_pattern, hostname)) { + infof(data, " subjectAltName: host \"%s\" matched cert's \"%s\"\n", + dispname, match_pattern); + return TRUE; + } + return FALSE; +} +#endif + + +/* Quote from RFC2818 section 3.1 "Server Identity" + + If a subjectAltName extension of type dNSName is present, that MUST + be used as the identity. Otherwise, the (most specific) Common Name + field in the Subject field of the certificate MUST be used. Although + the use of the Common Name is existing practice, it is deprecated and + Certification Authorities are encouraged to use the dNSName instead. + + Matching is performed using the matching rules specified by + [RFC2459]. If more than one identity of a given type is present in + the certificate (e.g., more than one dNSName name, a match in any one + of the set is considered acceptable.) Names may contain the wildcard + character * which is considered to match any single domain name + component or component fragment. E.g., *.a.com matches foo.a.com but + not bar.foo.a.com. f*.com matches foo.com but not bar.com. + + In some cases, the URI is specified as an IP address rather than a + hostname. In this case, the iPAddress subjectAltName must be present + in the certificate and must exactly match the IP in the URI. + +*/ +static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) +{ + bool matched = FALSE; + int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */ + size_t addrlen = 0; + struct Curl_easy *data = conn->data; + STACK_OF(GENERAL_NAME) *altnames; +#ifdef ENABLE_IPV6 + struct in6_addr addr; +#else + struct in_addr addr; +#endif + CURLcode result = CURLE_OK; + bool dNSName = FALSE; /* if a dNSName field exists in the cert */ + bool iPAddress = FALSE; /* if a iPAddress field exists in the cert */ + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const char * const dispname = SSL_IS_PROXY() ? + conn->http_proxy.host.dispname : conn->host.dispname; + +#ifdef ENABLE_IPV6 + if(conn->bits.ipv6_ip && + Curl_inet_pton(AF_INET6, hostname, &addr)) { + target = GEN_IPADD; + addrlen = sizeof(struct in6_addr); + } + else +#endif + if(Curl_inet_pton(AF_INET, hostname, &addr)) { + target = GEN_IPADD; + addrlen = sizeof(struct in_addr); + } + + /* get a "list" of alternative names */ + altnames = X509_get_ext_d2i(server_cert, NID_subject_alt_name, NULL, NULL); + + if(altnames) { + int numalts; + int i; + bool dnsmatched = FALSE; + bool ipmatched = FALSE; + + /* get amount of alternatives, RFC2459 claims there MUST be at least + one, but we don't depend on it... */ + numalts = sk_GENERAL_NAME_num(altnames); + + /* loop through all alternatives - until a dnsmatch */ + for(i = 0; (i < numalts) && !dnsmatched; i++) { + /* get a handle to alternative name number i */ + const GENERAL_NAME *check = sk_GENERAL_NAME_value(altnames, i); + + if(check->type == GEN_DNS) + dNSName = TRUE; + else if(check->type == GEN_IPADD) + iPAddress = TRUE; + + /* only check alternatives of the same type the target is */ + if(check->type == target) { + /* get data and length */ + const char *altptr = (char *)ASN1_STRING_get0_data(check->d.ia5); + size_t altlen = (size_t) ASN1_STRING_length(check->d.ia5); + + switch(target) { + case GEN_DNS: /* name/pattern comparison */ + /* The OpenSSL man page explicitly says: "In general it cannot be + assumed that the data returned by ASN1_STRING_data() is null + terminated or does not contain embedded nulls." But also that + "The actual format of the data will depend on the actual string + type itself: for example for and IA5String the data will be ASCII" + + Gisle researched the OpenSSL sources: + "I checked the 0.9.6 and 0.9.8 sources before my patch and + it always 0-terminates an IA5String." + */ + if((altlen == strlen(altptr)) && + /* if this isn't true, there was an embedded zero in the name + string and we cannot match it. */ + subj_alt_hostcheck(data, altptr, hostname, dispname)) { + dnsmatched = TRUE; + } + break; + + case GEN_IPADD: /* IP address comparison */ + /* compare alternative IP address if the data chunk is the same size + our server IP address is */ + if((altlen == addrlen) && !memcmp(altptr, &addr, altlen)) { + ipmatched = TRUE; + infof(data, + " subjectAltName: host \"%s\" matched cert's IP address!\n", + dispname); + } + break; + } + } + } + GENERAL_NAMES_free(altnames); + + if(dnsmatched || ipmatched) + matched = TRUE; + } + + if(matched) + /* an alternative name matched */ + ; + else if(dNSName || iPAddress) { + infof(data, " subjectAltName does not match %s\n", dispname); + failf(data, "SSL: no alternative certificate subject name matches " + "target host name '%s'", dispname); + result = CURLE_PEER_FAILED_VERIFICATION; + } + else { + /* we have to look to the last occurrence of a commonName in the + distinguished one to get the most significant one. */ + int j, i = -1; + + /* The following is done because of a bug in 0.9.6b */ + + unsigned char *nulstr = (unsigned char *)""; + unsigned char *peer_CN = nulstr; + + X509_NAME *name = X509_get_subject_name(server_cert); + if(name) + while((j = X509_NAME_get_index_by_NID(name, NID_commonName, i)) >= 0) + i = j; + + /* we have the name entry and we will now convert this to a string + that we can use for comparison. Doing this we support BMPstring, + UTF8 etc. */ + + if(i >= 0) { + ASN1_STRING *tmp = + X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i)); + + /* In OpenSSL 0.9.7d and earlier, ASN1_STRING_to_UTF8 fails if the input + is already UTF-8 encoded. We check for this case and copy the raw + string manually to avoid the problem. This code can be made + conditional in the future when OpenSSL has been fixed. Work-around + brought by Alexis S. L. Carvalho. */ + if(tmp) { + if(ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) { + j = ASN1_STRING_length(tmp); + if(j >= 0) { + peer_CN = OPENSSL_malloc(j + 1); + if(peer_CN) { + memcpy(peer_CN, ASN1_STRING_get0_data(tmp), j); + peer_CN[j] = '\0'; + } + } + } + else /* not a UTF8 name */ + j = ASN1_STRING_to_UTF8(&peer_CN, tmp); + + if(peer_CN && (curlx_uztosi(strlen((char *)peer_CN)) != j)) { + /* there was a terminating zero before the end of string, this + cannot match and we return failure! */ + failf(data, "SSL: illegal cert name field"); + result = CURLE_PEER_FAILED_VERIFICATION; + } + } + } + + if(peer_CN == nulstr) + peer_CN = NULL; + else { + /* convert peer_CN from UTF8 */ + CURLcode rc = Curl_convert_from_utf8(data, (char *)peer_CN, + strlen((char *)peer_CN)); + /* Curl_convert_from_utf8 calls failf if unsuccessful */ + if(rc) { + OPENSSL_free(peer_CN); + return rc; + } + } + + if(result) + /* error already detected, pass through */ + ; + else if(!peer_CN) { + failf(data, + "SSL: unable to obtain common name from peer certificate"); + result = CURLE_PEER_FAILED_VERIFICATION; + } + else if(!Curl_cert_hostcheck((const char *)peer_CN, hostname)) { + failf(data, "SSL: certificate subject name '%s' does not match " + "target host name '%s'", peer_CN, dispname); + result = CURLE_PEER_FAILED_VERIFICATION; + } + else { + infof(data, " common name: %s (matched)\n", peer_CN); + } + if(peer_CN) + OPENSSL_free(peer_CN); + } + + return result; +} + +#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ + !defined(OPENSSL_NO_OCSP) +static CURLcode verifystatus(struct connectdata *conn, + struct ssl_connect_data *connssl) +{ + int i, ocsp_status; + unsigned char *status; + const unsigned char *p; + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + OCSP_RESPONSE *rsp = NULL; + OCSP_BASICRESP *br = NULL; + X509_STORE *st = NULL; + STACK_OF(X509) *ch = NULL; + + long len = SSL_get_tlsext_status_ocsp_resp(BACKEND->handle, &status); + + if(!status) { + failf(data, "No OCSP response received"); + result = CURLE_SSL_INVALIDCERTSTATUS; + goto end; + } + p = status; + rsp = d2i_OCSP_RESPONSE(NULL, &p, len); + if(!rsp) { + failf(data, "Invalid OCSP response"); + result = CURLE_SSL_INVALIDCERTSTATUS; + goto end; + } + + ocsp_status = OCSP_response_status(rsp); + if(ocsp_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { + failf(data, "Invalid OCSP response status: %s (%d)", + OCSP_response_status_str(ocsp_status), ocsp_status); + result = CURLE_SSL_INVALIDCERTSTATUS; + goto end; + } + + br = OCSP_response_get1_basic(rsp); + if(!br) { + failf(data, "Invalid OCSP response"); + result = CURLE_SSL_INVALIDCERTSTATUS; + goto end; + } + + ch = SSL_get_peer_cert_chain(BACKEND->handle); + st = SSL_CTX_get_cert_store(BACKEND->ctx); + +#if ((OPENSSL_VERSION_NUMBER <= 0x1000201fL) /* Fixed after 1.0.2a */ || \ + (defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER <= 0x2040200fL)) + /* The authorized responder cert in the OCSP response MUST be signed by the + peer cert's issuer (see RFC6960 section 4.2.2.2). If that's a root cert, + no problem, but if it's an intermediate cert OpenSSL has a bug where it + expects this issuer to be present in the chain embedded in the OCSP + response. So we add it if necessary. */ + + /* First make sure the peer cert chain includes both a peer and an issuer, + and the OCSP response contains a responder cert. */ + if(sk_X509_num(ch) >= 2 && sk_X509_num(br->certs) >= 1) { + X509 *responder = sk_X509_value(br->certs, sk_X509_num(br->certs) - 1); + + /* Find issuer of responder cert and add it to the OCSP response chain */ + for(i = 0; i < sk_X509_num(ch); i++) { + X509 *issuer = sk_X509_value(ch, i); + if(X509_check_issued(issuer, responder) == X509_V_OK) { + if(!OCSP_basic_add1_cert(br, issuer)) { + failf(data, "Could not add issuer cert to OCSP response"); + result = CURLE_SSL_INVALIDCERTSTATUS; + goto end; + } + } + } + } +#endif + + if(OCSP_basic_verify(br, ch, st, 0) <= 0) { + failf(data, "OCSP response verification failed"); + result = CURLE_SSL_INVALIDCERTSTATUS; + goto end; + } + + for(i = 0; i < OCSP_resp_count(br); i++) { + int cert_status, crl_reason; + OCSP_SINGLERESP *single = NULL; + + ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; + + single = OCSP_resp_get0(br, i); + if(!single) + continue; + + cert_status = OCSP_single_get0_status(single, &crl_reason, &rev, + &thisupd, &nextupd); + + if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) { + failf(data, "OCSP response has expired"); + result = CURLE_SSL_INVALIDCERTSTATUS; + goto end; + } + + infof(data, "SSL certificate status: %s (%d)\n", + OCSP_cert_status_str(cert_status), cert_status); + + switch(cert_status) { + case V_OCSP_CERTSTATUS_GOOD: + break; + + case V_OCSP_CERTSTATUS_REVOKED: + result = CURLE_SSL_INVALIDCERTSTATUS; + + failf(data, "SSL certificate revocation reason: %s (%d)", + OCSP_crl_reason_str(crl_reason), crl_reason); + goto end; + + case V_OCSP_CERTSTATUS_UNKNOWN: + result = CURLE_SSL_INVALIDCERTSTATUS; + goto end; + } + } + +end: + if(br) OCSP_BASICRESP_free(br); + OCSP_RESPONSE_free(rsp); + + return result; +} +#endif + +#endif /* USE_OPENSSL */ + +/* The SSL_CTRL_SET_MSG_CALLBACK doesn't exist in ancient OpenSSL versions + and thus this cannot be done there. */ +#ifdef SSL_CTRL_SET_MSG_CALLBACK + +static const char *ssl_msg_type(int ssl_ver, int msg) +{ +#ifdef SSL2_VERSION_MAJOR + if(ssl_ver == SSL2_VERSION_MAJOR) { + switch(msg) { + case SSL2_MT_ERROR: + return "Error"; + case SSL2_MT_CLIENT_HELLO: + return "Client hello"; + case SSL2_MT_CLIENT_MASTER_KEY: + return "Client key"; + case SSL2_MT_CLIENT_FINISHED: + return "Client finished"; + case SSL2_MT_SERVER_HELLO: + return "Server hello"; + case SSL2_MT_SERVER_VERIFY: + return "Server verify"; + case SSL2_MT_SERVER_FINISHED: + return "Server finished"; + case SSL2_MT_REQUEST_CERTIFICATE: + return "Request CERT"; + case SSL2_MT_CLIENT_CERTIFICATE: + return "Client CERT"; + } + } + else +#endif + if(ssl_ver == SSL3_VERSION_MAJOR) { + switch(msg) { + case SSL3_MT_HELLO_REQUEST: + return "Hello request"; + case SSL3_MT_CLIENT_HELLO: + return "Client hello"; + case SSL3_MT_SERVER_HELLO: + return "Server hello"; +#ifdef SSL3_MT_NEWSESSION_TICKET + case SSL3_MT_NEWSESSION_TICKET: + return "Newsession Ticket"; +#endif + case SSL3_MT_CERTIFICATE: + return "Certificate"; + case SSL3_MT_SERVER_KEY_EXCHANGE: + return "Server key exchange"; + case SSL3_MT_CLIENT_KEY_EXCHANGE: + return "Client key exchange"; + case SSL3_MT_CERTIFICATE_REQUEST: + return "Request CERT"; + case SSL3_MT_SERVER_DONE: + return "Server finished"; + case SSL3_MT_CERTIFICATE_VERIFY: + return "CERT verify"; + case SSL3_MT_FINISHED: + return "Finished"; +#ifdef SSL3_MT_CERTIFICATE_STATUS + case SSL3_MT_CERTIFICATE_STATUS: + return "Certificate Status"; +#endif +#ifdef SSL3_MT_ENCRYPTED_EXTENSIONS + case SSL3_MT_ENCRYPTED_EXTENSIONS: + return "Encrypted Extensions"; +#endif +#ifdef SSL3_MT_END_OF_EARLY_DATA + case SSL3_MT_END_OF_EARLY_DATA: + return "End of early data"; +#endif +#ifdef SSL3_MT_KEY_UPDATE + case SSL3_MT_KEY_UPDATE: + return "Key update"; +#endif +#ifdef SSL3_MT_NEXT_PROTO + case SSL3_MT_NEXT_PROTO: + return "Next protocol"; +#endif +#ifdef SSL3_MT_MESSAGE_HASH + case SSL3_MT_MESSAGE_HASH: + return "Message hash"; +#endif + } + } + return "Unknown"; +} + +static const char *tls_rt_type(int type) +{ + switch(type) { +#ifdef SSL3_RT_HEADER + case SSL3_RT_HEADER: + return "TLS header"; +#endif + case SSL3_RT_CHANGE_CIPHER_SPEC: + return "TLS change cipher"; + case SSL3_RT_ALERT: + return "TLS alert"; + case SSL3_RT_HANDSHAKE: + return "TLS handshake"; + case SSL3_RT_APPLICATION_DATA: + return "TLS app data"; + default: + return "TLS Unknown"; + } +} + + +/* + * Our callback from the SSL/TLS layers. + */ +static void ssl_tls_trace(int direction, int ssl_ver, int content_type, + const void *buf, size_t len, SSL *ssl, + void *userp) +{ + struct Curl_easy *data; + char unknown[32]; + const char *verstr = NULL; + struct connectdata *conn = userp; + + if(!conn || !conn->data || !conn->data->set.fdebug || + (direction != 0 && direction != 1)) + return; + + data = conn->data; + + switch(ssl_ver) { +#ifdef SSL2_VERSION /* removed in recent versions */ + case SSL2_VERSION: + verstr = "SSLv2"; + break; +#endif +#ifdef SSL3_VERSION + case SSL3_VERSION: + verstr = "SSLv3"; + break; +#endif + case TLS1_VERSION: + verstr = "TLSv1.0"; + break; +#ifdef TLS1_1_VERSION + case TLS1_1_VERSION: + verstr = "TLSv1.1"; + break; +#endif +#ifdef TLS1_2_VERSION + case TLS1_2_VERSION: + verstr = "TLSv1.2"; + break; +#endif +#ifdef TLS1_3_VERSION + case TLS1_3_VERSION: + verstr = "TLSv1.3"; + break; +#endif + case 0: + break; + default: + msnprintf(unknown, sizeof(unknown), "(%x)", ssl_ver); + verstr = unknown; + break; + } + + /* Log progress for interesting records only (like Handshake or Alert), skip + * all raw record headers (content_type == SSL3_RT_HEADER or ssl_ver == 0). + * For TLS 1.3, skip notification of the decrypted inner Content Type. + */ + if(ssl_ver +#ifdef SSL3_RT_INNER_CONTENT_TYPE + && content_type != SSL3_RT_INNER_CONTENT_TYPE +#endif + ) { + const char *msg_name, *tls_rt_name; + char ssl_buf[1024]; + int msg_type, txt_len; + + /* the info given when the version is zero is not that useful for us */ + + ssl_ver >>= 8; /* check the upper 8 bits only below */ + + /* SSLv2 doesn't seem to have TLS record-type headers, so OpenSSL + * always pass-up content-type as 0. But the interesting message-type + * is at 'buf[0]'. + */ + if(ssl_ver == SSL3_VERSION_MAJOR && content_type) + tls_rt_name = tls_rt_type(content_type); + else + tls_rt_name = ""; + + if(content_type == SSL3_RT_CHANGE_CIPHER_SPEC) { + msg_type = *(char *)buf; + msg_name = "Change cipher spec"; + } + else if(content_type == SSL3_RT_ALERT) { + msg_type = (((char *)buf)[0] << 8) + ((char *)buf)[1]; + msg_name = SSL_alert_desc_string_long(msg_type); + } + else { + msg_type = *(char *)buf; + msg_name = ssl_msg_type(ssl_ver, msg_type); + } + + txt_len = msnprintf(ssl_buf, sizeof(ssl_buf), "%s (%s), %s, %s (%d):\n", + verstr, direction?"OUT":"IN", + tls_rt_name, msg_name, msg_type); + if(0 <= txt_len && (unsigned)txt_len < sizeof(ssl_buf)) { + Curl_debug(data, CURLINFO_TEXT, ssl_buf, (size_t)txt_len); + } + } + + Curl_debug(data, (direction == 1) ? CURLINFO_SSL_DATA_OUT : + CURLINFO_SSL_DATA_IN, (char *)buf, len); + (void) ssl; +} +#endif + +#ifdef USE_OPENSSL +/* ====================================================== */ + +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME +# define use_sni(x) sni = (x) +#else +# define use_sni(x) Curl_nop_stmt +#endif + +/* Check for OpenSSL 1.0.2 which has ALPN support. */ +#undef HAS_ALPN +#if OPENSSL_VERSION_NUMBER >= 0x10002000L \ + && !defined(OPENSSL_NO_TLSEXT) +# define HAS_ALPN 1 +#endif + +/* Check for OpenSSL 1.0.1 which has NPN support. */ +#undef HAS_NPN +#if OPENSSL_VERSION_NUMBER >= 0x10001000L \ + && !defined(OPENSSL_NO_TLSEXT) \ + && !defined(OPENSSL_NO_NEXTPROTONEG) +# define HAS_NPN 1 +#endif + +#ifdef HAS_NPN + +/* + * in is a list of length prefixed strings. this function has to select + * the protocol we want to use from the list and write its string into out. + */ + +static int +select_next_protocol(unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, + const char *key, unsigned int keylen) +{ + unsigned int i; + for(i = 0; i + keylen <= inlen; i += in[i] + 1) { + if(memcmp(&in[i + 1], key, keylen) == 0) { + *out = (unsigned char *) &in[i + 1]; + *outlen = in[i]; + return 0; + } + } + return -1; +} + +static int +select_next_proto_cb(SSL *ssl, + unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, + void *arg) +{ + struct connectdata *conn = (struct connectdata*) arg; + + (void)ssl; + +#ifdef USE_NGHTTP2 + if(conn->data->set.httpversion >= CURL_HTTP_VERSION_2 && + !select_next_protocol(out, outlen, in, inlen, NGHTTP2_PROTO_VERSION_ID, + NGHTTP2_PROTO_VERSION_ID_LEN)) { + infof(conn->data, "NPN, negotiated HTTP2 (%s)\n", + NGHTTP2_PROTO_VERSION_ID); + conn->negnpn = CURL_HTTP_VERSION_2; + return SSL_TLSEXT_ERR_OK; + } +#endif + + if(!select_next_protocol(out, outlen, in, inlen, ALPN_HTTP_1_1, + ALPN_HTTP_1_1_LENGTH)) { + infof(conn->data, "NPN, negotiated HTTP1.1\n"); + conn->negnpn = CURL_HTTP_VERSION_1_1; + return SSL_TLSEXT_ERR_OK; + } + + infof(conn->data, "NPN, no overlap, use HTTP1.1\n"); + *out = (unsigned char *)ALPN_HTTP_1_1; + *outlen = ALPN_HTTP_1_1_LENGTH; + conn->negnpn = CURL_HTTP_VERSION_1_1; + + return SSL_TLSEXT_ERR_OK; +} +#endif /* HAS_NPN */ + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static const char * +get_ssl_version_txt(SSL *ssl) +{ + if(!ssl) + return ""; + + switch(SSL_version(ssl)) { +#ifdef TLS1_3_VERSION + case TLS1_3_VERSION: + return "TLSv1.3"; +#endif +#if OPENSSL_VERSION_NUMBER >= 0x1000100FL + case TLS1_2_VERSION: + return "TLSv1.2"; + case TLS1_1_VERSION: + return "TLSv1.1"; +#endif + case TLS1_VERSION: + return "TLSv1.0"; + case SSL3_VERSION: + return "SSLv3"; + case SSL2_VERSION: + return "SSLv2"; + } + return "unknown"; +} +#endif + +static CURLcode +set_ssl_version_min_max(long *ctx_options, struct connectdata *conn, + int sockindex) +{ +#if (OPENSSL_VERSION_NUMBER < 0x1000100FL) || !defined(TLS1_3_VERSION) + /* convoluted #if condition just to avoid compiler warnings on unused + variable */ + struct Curl_easy *data = conn->data; +#endif + long ssl_version = SSL_CONN_CONFIG(version); + long ssl_version_max = SSL_CONN_CONFIG(version_max); + + switch(ssl_version) { + case CURL_SSLVERSION_TLSv1_3: +#ifdef TLS1_3_VERSION + { + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + SSL_CTX_set_max_proto_version(BACKEND->ctx, TLS1_3_VERSION); + *ctx_options |= SSL_OP_NO_TLSv1_2; + } +#else + (void)sockindex; + (void)ctx_options; + failf(data, OSSL_PACKAGE " was built without TLS 1.3 support"); + return CURLE_NOT_BUILT_IN; +#endif + /* FALLTHROUGH */ + case CURL_SSLVERSION_TLSv1_2: +#if OPENSSL_VERSION_NUMBER >= 0x1000100FL + *ctx_options |= SSL_OP_NO_TLSv1_1; +#else + failf(data, OSSL_PACKAGE " was built without TLS 1.2 support"); + return CURLE_NOT_BUILT_IN; +#endif + /* FALLTHROUGH */ + case CURL_SSLVERSION_TLSv1_1: +#if OPENSSL_VERSION_NUMBER >= 0x1000100FL + *ctx_options |= SSL_OP_NO_TLSv1; +#else + failf(data, OSSL_PACKAGE " was built without TLS 1.1 support"); + return CURLE_NOT_BUILT_IN; +#endif + /* FALLTHROUGH */ + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1: + break; + } + + switch(ssl_version_max) { + case CURL_SSLVERSION_MAX_TLSv1_0: +#if OPENSSL_VERSION_NUMBER >= 0x1000100FL + *ctx_options |= SSL_OP_NO_TLSv1_1; +#endif + /* FALLTHROUGH */ + case CURL_SSLVERSION_MAX_TLSv1_1: +#if OPENSSL_VERSION_NUMBER >= 0x1000100FL + *ctx_options |= SSL_OP_NO_TLSv1_2; +#endif + /* FALLTHROUGH */ + case CURL_SSLVERSION_MAX_TLSv1_2: +#ifdef TLS1_3_VERSION + *ctx_options |= SSL_OP_NO_TLSv1_3; +#endif + break; + case CURL_SSLVERSION_MAX_TLSv1_3: +#ifdef TLS1_3_VERSION + break; +#else + failf(data, OSSL_PACKAGE " was built without TLS 1.3 support"); + return CURLE_NOT_BUILT_IN; +#endif + } + return CURLE_OK; +} + +/* The "new session" callback must return zero if the session can be removed + * or non-zero if the session has been put into the session cache. + */ +static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid) +{ + int res = 0; + struct connectdata *conn; + struct Curl_easy *data; + int sockindex; + curl_socket_t *sockindex_ptr; + int connectdata_idx = ossl_get_ssl_conn_index(); + int sockindex_idx = ossl_get_ssl_sockindex_index(); + + if(connectdata_idx < 0 || sockindex_idx < 0) + return 0; + + conn = (struct connectdata*) SSL_get_ex_data(ssl, connectdata_idx); + if(!conn) + return 0; + + data = conn->data; + + /* The sockindex has been stored as a pointer to an array element */ + sockindex_ptr = (curl_socket_t*) SSL_get_ex_data(ssl, sockindex_idx); + sockindex = (int)(sockindex_ptr - conn->sock); + + if(SSL_SET_OPTION(primary.sessionid)) { + bool incache; + void *old_ssl_sessionid = NULL; + + Curl_ssl_sessionid_lock(conn); + incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, + sockindex)); + if(incache) { + if(old_ssl_sessionid != ssl_sessionid) { + infof(data, "old SSL session ID is stale, removing\n"); + Curl_ssl_delsessionid(conn, old_ssl_sessionid); + incache = FALSE; + } + } + + if(!incache) { + if(!Curl_ssl_addsessionid(conn, ssl_sessionid, + 0 /* unknown size */, sockindex)) { + /* the session has been put into the session cache */ + res = 1; + } + else + failf(data, "failed to store ssl session"); + } + Curl_ssl_sessionid_unlock(conn); + } + + return res; +} + +static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) +{ + CURLcode result = CURLE_OK; + char *ciphers; + struct Curl_easy *data = conn->data; + SSL_METHOD_QUAL SSL_METHOD *req_method = NULL; + X509_LOOKUP *lookup = NULL; + curl_socket_t sockfd = conn->sock[sockindex]; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + long ctx_options = 0; +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + bool sni; + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; +#ifdef ENABLE_IPV6 + struct in6_addr addr; +#else + struct in_addr addr; +#endif +#endif + long * const certverifyresult = SSL_IS_PROXY() ? + &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult; + const long int ssl_version = SSL_CONN_CONFIG(version); +#ifdef USE_TLS_SRP + const enum CURL_TLSAUTH ssl_authtype = SSL_SET_OPTION(authtype); +#endif + char * const ssl_cert = SSL_SET_OPTION(cert); + const char * const ssl_cert_type = SSL_SET_OPTION(cert_type); + const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); + const char * const ssl_capath = SSL_CONN_CONFIG(CApath); + const bool verifypeer = SSL_CONN_CONFIG(verifypeer); + const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile); + char error_buffer[256]; + + DEBUGASSERT(ssl_connect_1 == connssl->connecting_state); + + /* Make funny stuff to get random input */ + result = Curl_ossl_seed(data); + if(result) + return result; + + *certverifyresult = !X509_V_OK; + + /* check to see if we've been told to use an explicit SSL/TLS version */ + + switch(ssl_version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: + /* it will be handled later with the context options */ +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) + req_method = TLS_client_method(); +#else + req_method = SSLv23_client_method(); +#endif + use_sni(TRUE); + break; + case CURL_SSLVERSION_SSLv2: +#ifdef OPENSSL_NO_SSL2 + failf(data, OSSL_PACKAGE " was built without SSLv2 support"); + return CURLE_NOT_BUILT_IN; +#else +#ifdef USE_TLS_SRP + if(ssl_authtype == CURL_TLSAUTH_SRP) + return CURLE_SSL_CONNECT_ERROR; +#endif + req_method = SSLv2_client_method(); + use_sni(FALSE); + break; +#endif + case CURL_SSLVERSION_SSLv3: +#ifdef OPENSSL_NO_SSL3_METHOD + failf(data, OSSL_PACKAGE " was built without SSLv3 support"); + return CURLE_NOT_BUILT_IN; +#else +#ifdef USE_TLS_SRP + if(ssl_authtype == CURL_TLSAUTH_SRP) + return CURLE_SSL_CONNECT_ERROR; +#endif + req_method = SSLv3_client_method(); + use_sni(FALSE); + break; +#endif + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + + if(BACKEND->ctx) + SSL_CTX_free(BACKEND->ctx); + BACKEND->ctx = SSL_CTX_new(req_method); + + if(!BACKEND->ctx) { + failf(data, "SSL: couldn't create a context: %s", + ossl_strerror(ERR_peek_error(), error_buffer, sizeof(error_buffer))); + return CURLE_OUT_OF_MEMORY; + } + +#ifdef SSL_MODE_RELEASE_BUFFERS + SSL_CTX_set_mode(BACKEND->ctx, SSL_MODE_RELEASE_BUFFERS); +#endif + +#ifdef SSL_CTRL_SET_MSG_CALLBACK + if(data->set.fdebug && data->set.verbose) { + /* the SSL trace callback is only used for verbose logging */ + SSL_CTX_set_msg_callback(BACKEND->ctx, ssl_tls_trace); + SSL_CTX_set_msg_callback_arg(BACKEND->ctx, conn); + } +#endif + + /* OpenSSL contains code to work-around lots of bugs and flaws in various + SSL-implementations. SSL_CTX_set_options() is used to enabled those + work-arounds. The man page for this option states that SSL_OP_ALL enables + all the work-arounds and that "It is usually safe to use SSL_OP_ALL to + enable the bug workaround options if compatibility with somewhat broken + implementations is desired." + + The "-no_ticket" option was introduced in Openssl0.9.8j. It's a flag to + disable "rfc4507bis session ticket support". rfc4507bis was later turned + into the proper RFC5077 it seems: https://tools.ietf.org/html/rfc5077 + + The enabled extension concerns the session management. I wonder how often + libcurl stops a connection and then resumes a TLS session. also, sending + the session data is some overhead. .I suggest that you just use your + proposed patch (which explicitly disables TICKET). + + If someone writes an application with libcurl and openssl who wants to + enable the feature, one can do this in the SSL callback. + + SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG option enabling allowed proper + interoperability with web server Netscape Enterprise Server 2.0.1 which + was released back in 1996. + + Due to CVE-2010-4180, option SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG has + become ineffective as of OpenSSL 0.9.8q and 1.0.0c. In order to mitigate + CVE-2010-4180 when using previous OpenSSL versions we no longer enable + this option regardless of OpenSSL version and SSL_OP_ALL definition. + + OpenSSL added a work-around for a SSL 3.0/TLS 1.0 CBC vulnerability + (https://www.openssl.org/~bodo/tls-cbc.txt). In 0.9.6e they added a bit to + SSL_OP_ALL that _disables_ that work-around despite the fact that + SSL_OP_ALL is documented to do "rather harmless" workarounds. In order to + keep the secure work-around, the SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS bit + must not be set. + */ + + ctx_options = SSL_OP_ALL; + +#ifdef SSL_OP_NO_TICKET + ctx_options |= SSL_OP_NO_TICKET; +#endif + +#ifdef SSL_OP_NO_COMPRESSION + ctx_options |= SSL_OP_NO_COMPRESSION; +#endif + +#ifdef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG + /* mitigate CVE-2010-4180 */ + ctx_options &= ~SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG; +#endif + +#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS + /* unless the user explicitly ask to allow the protocol vulnerability we + use the work-around */ + if(!SSL_SET_OPTION(enable_beast)) + ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; +#endif + + switch(ssl_version) { + case CURL_SSLVERSION_SSLv3: + ctx_options |= SSL_OP_NO_SSLv2; + ctx_options |= SSL_OP_NO_TLSv1; +#if OPENSSL_VERSION_NUMBER >= 0x1000100FL + ctx_options |= SSL_OP_NO_TLSv1_1; + ctx_options |= SSL_OP_NO_TLSv1_2; +#ifdef TLS1_3_VERSION + ctx_options |= SSL_OP_NO_TLSv1_3; +#endif +#endif + break; + + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: + /* asking for any TLS version as the minimum, means no SSL versions + allowed */ + ctx_options |= SSL_OP_NO_SSLv2; + ctx_options |= SSL_OP_NO_SSLv3; + result = set_ssl_version_min_max(&ctx_options, conn, sockindex); + if(result != CURLE_OK) + return result; + break; + + case CURL_SSLVERSION_SSLv2: + ctx_options |= SSL_OP_NO_SSLv3; + ctx_options |= SSL_OP_NO_TLSv1; +#if OPENSSL_VERSION_NUMBER >= 0x1000100FL + ctx_options |= SSL_OP_NO_TLSv1_1; + ctx_options |= SSL_OP_NO_TLSv1_2; +#ifdef TLS1_3_VERSION + ctx_options |= SSL_OP_NO_TLSv1_3; +#endif +#endif + break; + + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + + SSL_CTX_set_options(BACKEND->ctx, ctx_options); + +#ifdef HAS_NPN + if(conn->bits.tls_enable_npn) + SSL_CTX_set_next_proto_select_cb(BACKEND->ctx, select_next_proto_cb, conn); +#endif + +#ifdef HAS_ALPN + if(conn->bits.tls_enable_alpn) { + int cur = 0; + unsigned char protocols[128]; + +#ifdef USE_NGHTTP2 + if(data->set.httpversion >= CURL_HTTP_VERSION_2 && + (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) { + protocols[cur++] = NGHTTP2_PROTO_VERSION_ID_LEN; + + memcpy(&protocols[cur], NGHTTP2_PROTO_VERSION_ID, + NGHTTP2_PROTO_VERSION_ID_LEN); + cur += NGHTTP2_PROTO_VERSION_ID_LEN; + infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + } +#endif + + protocols[cur++] = ALPN_HTTP_1_1_LENGTH; + memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH); + cur += ALPN_HTTP_1_1_LENGTH; + infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); + + /* expects length prefixed preference ordered list of protocols in wire + * format + */ + SSL_CTX_set_alpn_protos(BACKEND->ctx, protocols, cur); + } +#endif + + if(ssl_cert || ssl_cert_type) { + if(!cert_stuff(conn, BACKEND->ctx, ssl_cert, ssl_cert_type, + SSL_SET_OPTION(key), SSL_SET_OPTION(key_type), + SSL_SET_OPTION(key_passwd))) { + /* failf() is already done in cert_stuff() */ + return CURLE_SSL_CERTPROBLEM; + } + } + + ciphers = SSL_CONN_CONFIG(cipher_list); + if(!ciphers) + ciphers = (char *)DEFAULT_CIPHER_SELECTION; + if(ciphers) { + if(!SSL_CTX_set_cipher_list(BACKEND->ctx, ciphers)) { + failf(data, "failed setting cipher list: %s", ciphers); + return CURLE_SSL_CIPHER; + } + infof(data, "Cipher selection: %s\n", ciphers); + } + +#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES + { + char *ciphers13 = SSL_CONN_CONFIG(cipher_list13); + if(ciphers13) { + if(!SSL_CTX_set_ciphersuites(BACKEND->ctx, ciphers13)) { + failf(data, "failed setting TLS 1.3 cipher suite: %s", ciphers13); + return CURLE_SSL_CIPHER; + } + infof(data, "TLS 1.3 cipher selection: %s\n", ciphers13); + } + } +#endif + +#ifdef HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH + /* OpenSSL 1.1.1 requires clients to opt-in for PHA */ + SSL_CTX_set_post_handshake_auth(BACKEND->ctx, 1); +#endif + +#ifdef USE_TLS_SRP + if(ssl_authtype == CURL_TLSAUTH_SRP) { + char * const ssl_username = SSL_SET_OPTION(username); + + infof(data, "Using TLS-SRP username: %s\n", ssl_username); + + if(!SSL_CTX_set_srp_username(BACKEND->ctx, ssl_username)) { + failf(data, "Unable to set SRP user name"); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + if(!SSL_CTX_set_srp_password(BACKEND->ctx, SSL_SET_OPTION(password))) { + failf(data, "failed setting SRP password"); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + if(!SSL_CONN_CONFIG(cipher_list)) { + infof(data, "Setting cipher list SRP\n"); + + if(!SSL_CTX_set_cipher_list(BACKEND->ctx, "SRP")) { + failf(data, "failed setting SRP cipher list"); + return CURLE_SSL_CIPHER; + } + } + } +#endif + + if(ssl_cafile || ssl_capath) { + /* tell SSL where to find CA certificates that are used to verify + the servers certificate. */ + if(!SSL_CTX_load_verify_locations(BACKEND->ctx, ssl_cafile, ssl_capath)) { + if(verifypeer) { + /* Fail if we insist on successfully verifying the server. */ + failf(data, "error setting certificate verify locations:\n" + " CAfile: %s\n CApath: %s", + ssl_cafile ? ssl_cafile : "none", + ssl_capath ? ssl_capath : "none"); + return CURLE_SSL_CACERT_BADFILE; + } + /* Just continue with a warning if no strict certificate verification + is required. */ + infof(data, "error setting certificate verify locations," + " continuing anyway:\n"); + } + else { + /* Everything is fine. */ + infof(data, "successfully set certificate verify locations:\n"); + } + infof(data, + " CAfile: %s\n" + " CApath: %s\n", + ssl_cafile ? ssl_cafile : "none", + ssl_capath ? ssl_capath : "none"); + } +#ifdef CURL_CA_FALLBACK + else if(verifypeer) { + /* verifying the peer without any CA certificates won't + work so use openssl's built in default as fallback */ + SSL_CTX_set_default_verify_paths(BACKEND->ctx); + } +#endif + + if(ssl_crlfile) { + /* tell SSL where to find CRL file that is used to check certificate + * revocation */ + lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(BACKEND->ctx), + X509_LOOKUP_file()); + if(!lookup || + (!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM)) ) { + failf(data, "error loading CRL file: %s", ssl_crlfile); + return CURLE_SSL_CRL_BADFILE; + } + /* Everything is fine. */ + infof(data, "successfully load CRL file:\n"); + X509_STORE_set_flags(SSL_CTX_get_cert_store(BACKEND->ctx), + X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); + + infof(data, " CRLfile: %s\n", ssl_crlfile); + } + + /* Try building a chain using issuers in the trusted store first to avoid + problems with server-sent legacy intermediates. + Newer versions of OpenSSL do alternate chain checking by default which + gives us the same fix without as much of a performance hit (slight), so we + prefer that if available. + https://rt.openssl.org/Ticket/Display.html?id=3621&user=guest&pass=guest + */ +#if defined(X509_V_FLAG_TRUSTED_FIRST) && !defined(X509_V_FLAG_NO_ALT_CHAINS) + if(verifypeer) { + X509_STORE_set_flags(SSL_CTX_get_cert_store(BACKEND->ctx), + X509_V_FLAG_TRUSTED_FIRST); + } +#endif + + /* SSL always tries to verify the peer, this only says whether it should + * fail to connect if the verification fails, or if it should continue + * anyway. In the latter case the result of the verification is checked with + * SSL_get_verify_result() below. */ + SSL_CTX_set_verify(BACKEND->ctx, + verifypeer ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL); + + /* Enable logging of secrets to the file specified in env SSLKEYLOGFILE. */ +#if defined(ENABLE_SSLKEYLOGFILE) && defined(HAVE_KEYLOG_CALLBACK) + if(keylog_file_fp) { + SSL_CTX_set_keylog_callback(BACKEND->ctx, ossl_keylog_callback); + } +#endif + + /* Enable the session cache because it's a prerequisite for the "new session" + * callback. Use the "external storage" mode to avoid that OpenSSL creates + * an internal session cache. + */ + SSL_CTX_set_session_cache_mode(BACKEND->ctx, + SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL); + SSL_CTX_sess_set_new_cb(BACKEND->ctx, ossl_new_session_cb); + + /* give application a chance to interfere with SSL set up. */ + if(data->set.ssl.fsslctx) { + result = (*data->set.ssl.fsslctx)(data, BACKEND->ctx, + data->set.ssl.fsslctxp); + if(result) { + failf(data, "error signaled by ssl ctx callback"); + return result; + } + } + + /* Lets make an SSL structure */ + if(BACKEND->handle) + SSL_free(BACKEND->handle); + BACKEND->handle = SSL_new(BACKEND->ctx); + if(!BACKEND->handle) { + failf(data, "SSL: couldn't create a context (handle)!"); + return CURLE_OUT_OF_MEMORY; + } + +#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ + !defined(OPENSSL_NO_OCSP) + if(SSL_CONN_CONFIG(verifystatus)) + SSL_set_tlsext_status_type(BACKEND->handle, TLSEXT_STATUSTYPE_ocsp); +#endif + +#if defined(OPENSSL_IS_BORINGSSL) && defined(ALLOW_RENEG) + SSL_set_renegotiate_mode(BACKEND->handle, ssl_renegotiate_freely); +#endif + + SSL_set_connect_state(BACKEND->handle); + + BACKEND->server_cert = 0x0; +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) && +#ifdef ENABLE_IPV6 + (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) && +#endif + sni && + !SSL_set_tlsext_host_name(BACKEND->handle, hostname)) + infof(data, "WARNING: failed to configure server name indication (SNI) " + "TLS extension\n"); +#endif + + /* Check if there's a cached ID we can/should use here! */ + if(SSL_SET_OPTION(primary.sessionid)) { + void *ssl_sessionid = NULL; + int connectdata_idx = ossl_get_ssl_conn_index(); + int sockindex_idx = ossl_get_ssl_sockindex_index(); + + if(connectdata_idx >= 0 && sockindex_idx >= 0) { + /* Store the data needed for the "new session" callback. + * The sockindex is stored as a pointer to an array element. */ + SSL_set_ex_data(BACKEND->handle, connectdata_idx, conn); + SSL_set_ex_data(BACKEND->handle, sockindex_idx, conn->sock + sockindex); + } + + Curl_ssl_sessionid_lock(conn); + if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) { + /* we got a session id, use it! */ + if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) { + Curl_ssl_sessionid_unlock(conn); + failf(data, "SSL: SSL_set_session failed: %s", + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer))); + return CURLE_SSL_CONNECT_ERROR; + } + /* Informational message */ + infof(data, "SSL re-using session ID\n"); + } + Curl_ssl_sessionid_unlock(conn); + } + + if(conn->proxy_ssl[sockindex].use) { + BIO *const bio = BIO_new(BIO_f_ssl()); + SSL *handle = conn->proxy_ssl[sockindex].backend->handle; + DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state); + DEBUGASSERT(handle != NULL); + DEBUGASSERT(bio != NULL); + BIO_set_ssl(bio, handle, FALSE); + SSL_set_bio(BACKEND->handle, bio, bio); + } + else if(!SSL_set_fd(BACKEND->handle, (int)sockfd)) { + /* pass the raw socket into the SSL layers */ + failf(data, "SSL: SSL_set_fd failed: %s", + ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer))); + return CURLE_SSL_CONNECT_ERROR; + } + + connssl->connecting_state = ssl_connect_2; + + return CURLE_OK; +} + +static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) +{ + struct Curl_easy *data = conn->data; + int err; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + long * const certverifyresult = SSL_IS_PROXY() ? + &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult; + DEBUGASSERT(ssl_connect_2 == connssl->connecting_state + || ssl_connect_2_reading == connssl->connecting_state + || ssl_connect_2_writing == connssl->connecting_state); + + ERR_clear_error(); + + err = SSL_connect(BACKEND->handle); + /* If keylogging is enabled but the keylog callback is not supported then log + secrets here, immediately after SSL_connect by using tap_ssl_key. */ +#if defined(ENABLE_SSLKEYLOGFILE) && !defined(HAVE_KEYLOG_CALLBACK) + tap_ssl_key(BACKEND->handle, &BACKEND->tap_state); +#endif + + /* 1 is fine + 0 is "not successful but was shut down controlled" + <0 is "handshake was not successful, because a fatal error occurred" */ + if(1 != err) { + int detail = SSL_get_error(BACKEND->handle, err); + + if(SSL_ERROR_WANT_READ == detail) { + connssl->connecting_state = ssl_connect_2_reading; + return CURLE_OK; + } + if(SSL_ERROR_WANT_WRITE == detail) { + connssl->connecting_state = ssl_connect_2_writing; + return CURLE_OK; + } +#ifdef SSL_ERROR_WANT_ASYNC + if(SSL_ERROR_WANT_ASYNC == detail) { + connssl->connecting_state = ssl_connect_2; + return CURLE_OK; + } +#endif + else { + /* untreated error */ + unsigned long errdetail; + char error_buffer[256]=""; + CURLcode result; + long lerr; + int lib; + int reason; + + /* the connection failed, we're not waiting for anything else. */ + connssl->connecting_state = ssl_connect_2; + + /* Get the earliest error code from the thread's error queue and removes + the entry. */ + errdetail = ERR_get_error(); + + /* Extract which lib and reason */ + lib = ERR_GET_LIB(errdetail); + reason = ERR_GET_REASON(errdetail); + + if((lib == ERR_LIB_SSL) && + (reason == SSL_R_CERTIFICATE_VERIFY_FAILED)) { + result = CURLE_PEER_FAILED_VERIFICATION; + + lerr = SSL_get_verify_result(BACKEND->handle); + if(lerr != X509_V_OK) { + *certverifyresult = lerr; + msnprintf(error_buffer, sizeof(error_buffer), + "SSL certificate problem: %s", + X509_verify_cert_error_string(lerr)); + } + else + /* strcpy() is fine here as long as the string fits within + error_buffer */ + strcpy(error_buffer, "SSL certificate verification failed"); + } + else { + result = CURLE_SSL_CONNECT_ERROR; + ossl_strerror(errdetail, error_buffer, sizeof(error_buffer)); + } + + /* detail is already set to the SSL error above */ + + /* If we e.g. use SSLv2 request-method and the server doesn't like us + * (RST connection etc.), OpenSSL gives no explanation whatsoever and + * the SO_ERROR is also lost. + */ + if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) { + const char * const hostname = SSL_IS_PROXY() ? + conn->http_proxy.host.name : conn->host.name; + const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; + failf(data, OSSL_PACKAGE " SSL_connect: %s in connection to %s:%ld ", + SSL_ERROR_to_str(detail), hostname, port); + return result; + } + + /* Could be a CERT problem */ + failf(data, "%s", error_buffer); + + return result; + } + } + else { + /* we have been connected fine, we're not waiting for anything else. */ + connssl->connecting_state = ssl_connect_3; + + /* Informational message */ + infof(data, "SSL connection using %s / %s\n", + get_ssl_version_txt(BACKEND->handle), + SSL_get_cipher(BACKEND->handle)); + +#ifdef HAS_ALPN + /* Sets data and len to negotiated protocol, len is 0 if no protocol was + * negotiated + */ + if(conn->bits.tls_enable_alpn) { + const unsigned char *neg_protocol; + unsigned int len; + SSL_get0_alpn_selected(BACKEND->handle, &neg_protocol, &len); + if(len != 0) { + infof(data, "ALPN, server accepted to use %.*s\n", len, neg_protocol); + +#ifdef USE_NGHTTP2 + if(len == NGHTTP2_PROTO_VERSION_ID_LEN && + !memcmp(NGHTTP2_PROTO_VERSION_ID, neg_protocol, len)) { + conn->negnpn = CURL_HTTP_VERSION_2; + } + else +#endif + if(len == ALPN_HTTP_1_1_LENGTH && + !memcmp(ALPN_HTTP_1_1, neg_protocol, ALPN_HTTP_1_1_LENGTH)) { + conn->negnpn = CURL_HTTP_VERSION_1_1; + } + } + else + infof(data, "ALPN, server did not agree to a protocol\n"); + + Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); + } +#endif + + return CURLE_OK; + } +} + +static int asn1_object_dump(ASN1_OBJECT *a, char *buf, size_t len) +{ + int i, ilen; + + ilen = (int)len; + if(ilen < 0) + return 1; /* buffer too big */ + + i = i2t_ASN1_OBJECT(buf, ilen, a); + + if(i >= ilen) + return 1; /* buffer too small */ + + return 0; +} + +#define push_certinfo(_label, _num) \ +do { \ + long info_len = BIO_get_mem_data(mem, &ptr); \ + Curl_ssl_push_certinfo_len(data, _num, _label, ptr, info_len); \ + if(1 != BIO_reset(mem)) \ + break; \ +} WHILE_FALSE + +static void pubkey_show(struct Curl_easy *data, + BIO *mem, + int num, + const char *type, + const char *name, +#ifdef HAVE_OPAQUE_RSA_DSA_DH + const +#endif + BIGNUM *bn) +{ + char *ptr; + char namebuf[32]; + + msnprintf(namebuf, sizeof(namebuf), "%s(%s)", type, name); + + if(bn) + BN_print(mem, bn); + push_certinfo(namebuf, num); +} + +#ifdef HAVE_OPAQUE_RSA_DSA_DH +#define print_pubkey_BN(_type, _name, _num) \ + pubkey_show(data, mem, _num, #_type, #_name, _name) + +#else +#define print_pubkey_BN(_type, _name, _num) \ +do { \ + if(_type->_name) { \ + pubkey_show(data, mem, _num, #_type, #_name, _type->_name); \ + } \ +} WHILE_FALSE +#endif + +static int X509V3_ext(struct Curl_easy *data, + int certnum, + CONST_EXTS STACK_OF(X509_EXTENSION) *exts) +{ + int i; + size_t j; + + if((int)sk_X509_EXTENSION_num(exts) <= 0) + /* no extensions, bail out */ + return 1; + + for(i = 0; i < (int)sk_X509_EXTENSION_num(exts); i++) { + ASN1_OBJECT *obj; + X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i); + BUF_MEM *biomem; + char buf[512]; + char *ptr = buf; + char namebuf[128]; + BIO *bio_out = BIO_new(BIO_s_mem()); + + if(!bio_out) + return 1; + + obj = X509_EXTENSION_get_object(ext); + + asn1_object_dump(obj, namebuf, sizeof(namebuf)); + + if(!X509V3_EXT_print(bio_out, ext, 0, 0)) + ASN1_STRING_print(bio_out, (ASN1_STRING *)X509_EXTENSION_get_data(ext)); + + BIO_get_mem_ptr(bio_out, &biomem); + + for(j = 0; j < (size_t)biomem->length; j++) { + const char *sep = ""; + if(biomem->data[j] == '\n') { + sep = ", "; + j++; /* skip the newline */ + }; + while((j<(size_t)biomem->length) && (biomem->data[j] == ' ')) + j++; + if(j<(size_t)biomem->length) + ptr += msnprintf(ptr, sizeof(buf)-(ptr-buf), "%s%c", sep, + biomem->data[j]); + } + + Curl_ssl_push_certinfo(data, certnum, namebuf, buf); + + BIO_free(bio_out); + + } + return 0; /* all is fine */ +} + +static CURLcode get_cert_chain(struct connectdata *conn, + struct ssl_connect_data *connssl) + +{ + CURLcode result; + STACK_OF(X509) *sk; + int i; + struct Curl_easy *data = conn->data; + int numcerts; + BIO *mem; + + sk = SSL_get_peer_cert_chain(BACKEND->handle); + if(!sk) { + return CURLE_OUT_OF_MEMORY; + } + + numcerts = sk_X509_num(sk); + + result = Curl_ssl_init_certinfo(data, numcerts); + if(result) { + return result; + } + + mem = BIO_new(BIO_s_mem()); + + for(i = 0; i < numcerts; i++) { + ASN1_INTEGER *num; + X509 *x = sk_X509_value(sk, i); + EVP_PKEY *pubkey = NULL; + int j; + char *ptr; + const ASN1_BIT_STRING *psig = NULL; + + X509_NAME_print_ex(mem, X509_get_subject_name(x), 0, XN_FLAG_ONELINE); + push_certinfo("Subject", i); + + X509_NAME_print_ex(mem, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE); + push_certinfo("Issuer", i); + + BIO_printf(mem, "%lx", X509_get_version(x)); + push_certinfo("Version", i); + + num = X509_get_serialNumber(x); + if(num->type == V_ASN1_NEG_INTEGER) + BIO_puts(mem, "-"); + for(j = 0; j < num->length; j++) + BIO_printf(mem, "%02x", num->data[j]); + push_certinfo("Serial Number", i); + +#if defined(HAVE_X509_GET0_SIGNATURE) && defined(HAVE_X509_GET0_EXTENSIONS) + { + const X509_ALGOR *palg = NULL; + ASN1_STRING *a = ASN1_STRING_new(); + if(a) { + X509_get0_signature(&psig, &palg, x); + X509_signature_print(mem, ARG2_X509_signature_print palg, a); + ASN1_STRING_free(a); + + if(palg) { + i2a_ASN1_OBJECT(mem, palg->algorithm); + push_certinfo("Public Key Algorithm", i); + } + } + X509V3_ext(data, i, X509_get0_extensions(x)); + } +#else + { + /* before OpenSSL 1.0.2 */ + X509_CINF *cinf = x->cert_info; + + i2a_ASN1_OBJECT(mem, cinf->signature->algorithm); + push_certinfo("Signature Algorithm", i); + + i2a_ASN1_OBJECT(mem, cinf->key->algor->algorithm); + push_certinfo("Public Key Algorithm", i); + + X509V3_ext(data, i, cinf->extensions); + + psig = x->signature; + } +#endif + + ASN1_TIME_print(mem, X509_get0_notBefore(x)); + push_certinfo("Start date", i); + + ASN1_TIME_print(mem, X509_get0_notAfter(x)); + push_certinfo("Expire date", i); + + pubkey = X509_get_pubkey(x); + if(!pubkey) + infof(data, " Unable to load public key\n"); + else { + int pktype; +#ifdef HAVE_OPAQUE_EVP_PKEY + pktype = EVP_PKEY_id(pubkey); +#else + pktype = pubkey->type; +#endif + switch(pktype) { + case EVP_PKEY_RSA: + { + RSA *rsa; +#ifdef HAVE_OPAQUE_EVP_PKEY + rsa = EVP_PKEY_get0_RSA(pubkey); +#else + rsa = pubkey->pkey.rsa; +#endif + +#ifdef HAVE_OPAQUE_RSA_DSA_DH + { + const BIGNUM *n; + const BIGNUM *e; + + RSA_get0_key(rsa, &n, &e, NULL); + BN_print(mem, n); + push_certinfo("RSA Public Key", i); + print_pubkey_BN(rsa, n, i); + print_pubkey_BN(rsa, e, i); + } +#else + BIO_printf(mem, "%d", BN_num_bits(rsa->n)); + push_certinfo("RSA Public Key", i); + print_pubkey_BN(rsa, n, i); + print_pubkey_BN(rsa, e, i); +#endif + + break; + } + case EVP_PKEY_DSA: + { +#ifndef OPENSSL_NO_DSA + DSA *dsa; +#ifdef HAVE_OPAQUE_EVP_PKEY + dsa = EVP_PKEY_get0_DSA(pubkey); +#else + dsa = pubkey->pkey.dsa; +#endif +#ifdef HAVE_OPAQUE_RSA_DSA_DH + { + const BIGNUM *p; + const BIGNUM *q; + const BIGNUM *g; + const BIGNUM *pub_key; + + DSA_get0_pqg(dsa, &p, &q, &g); + DSA_get0_key(dsa, &pub_key, NULL); + + print_pubkey_BN(dsa, p, i); + print_pubkey_BN(dsa, q, i); + print_pubkey_BN(dsa, g, i); + print_pubkey_BN(dsa, pub_key, i); + } +#else + print_pubkey_BN(dsa, p, i); + print_pubkey_BN(dsa, q, i); + print_pubkey_BN(dsa, g, i); + print_pubkey_BN(dsa, pub_key, i); +#endif +#endif /* !OPENSSL_NO_DSA */ + break; + } + case EVP_PKEY_DH: + { + DH *dh; +#ifdef HAVE_OPAQUE_EVP_PKEY + dh = EVP_PKEY_get0_DH(pubkey); +#else + dh = pubkey->pkey.dh; +#endif +#ifdef HAVE_OPAQUE_RSA_DSA_DH + { + const BIGNUM *p; + const BIGNUM *q; + const BIGNUM *g; + const BIGNUM *pub_key; + DH_get0_pqg(dh, &p, &q, &g); + DH_get0_key(dh, &pub_key, NULL); + print_pubkey_BN(dh, p, i); + print_pubkey_BN(dh, q, i); + print_pubkey_BN(dh, g, i); + print_pubkey_BN(dh, pub_key, i); + } +#else + print_pubkey_BN(dh, p, i); + print_pubkey_BN(dh, g, i); + print_pubkey_BN(dh, pub_key, i); +#endif + break; + } + } + EVP_PKEY_free(pubkey); + } + + if(psig) { + for(j = 0; j < psig->length; j++) + BIO_printf(mem, "%02x:", psig->data[j]); + push_certinfo("Signature", i); + } + + PEM_write_bio_X509(mem, x); + push_certinfo("Cert", i); + } + + BIO_free(mem); + + return CURLE_OK; +} + +/* + * Heavily modified from: + * https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning#OpenSSL + */ +static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert, + const char *pinnedpubkey) +{ + /* Scratch */ + int len1 = 0, len2 = 0; + unsigned char *buff1 = NULL, *temp = NULL; + + /* Result is returned to caller */ + CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; + + /* if a path wasn't specified, don't pin */ + if(!pinnedpubkey) + return CURLE_OK; + + if(!cert) + return result; + + do { + /* Begin Gyrations to get the subjectPublicKeyInfo */ + /* Thanks to Viktor Dukhovni on the OpenSSL mailing list */ + + /* https://groups.google.com/group/mailing.openssl.users/browse_thread + /thread/d61858dae102c6c7 */ + len1 = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), NULL); + if(len1 < 1) + break; /* failed */ + + /* https://www.openssl.org/docs/crypto/buffer.html */ + buff1 = temp = malloc(len1); + if(!buff1) + break; /* failed */ + + /* https://www.openssl.org/docs/crypto/d2i_X509.html */ + len2 = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), &temp); + + /* + * These checks are verifying we got back the same values as when we + * sized the buffer. It's pretty weak since they should always be the + * same. But it gives us something to test. + */ + if((len1 != len2) || !temp || ((temp - buff1) != len1)) + break; /* failed */ + + /* End Gyrations */ + + /* The one good exit point */ + result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1); + } while(0); + + /* https://www.openssl.org/docs/crypto/buffer.html */ + if(buff1) + free(buff1); + + return result; +} + +/* + * Get the server cert, verify it and show it etc, only call failf() if the + * 'strict' argument is TRUE as otherwise all this is for informational + * purposes only! + * + * We check certificates to authenticate the server; otherwise we risk + * man-in-the-middle attack. + */ +static CURLcode servercert(struct connectdata *conn, + struct ssl_connect_data *connssl, + bool strict) +{ + CURLcode result = CURLE_OK; + int rc; + long lerr; + struct Curl_easy *data = conn->data; + X509 *issuer; + BIO *fp = NULL; + char error_buffer[256]=""; + char buffer[2048]; + const char *ptr; + long * const certverifyresult = SSL_IS_PROXY() ? + &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult; + BIO *mem = BIO_new(BIO_s_mem()); + + if(data->set.ssl.certinfo) + /* we've been asked to gather certificate info! */ + (void)get_cert_chain(conn, connssl); + + BACKEND->server_cert = SSL_get_peer_certificate(BACKEND->handle); + if(!BACKEND->server_cert) { + BIO_free(mem); + if(!strict) + return CURLE_OK; + + failf(data, "SSL: couldn't get peer certificate!"); + return CURLE_PEER_FAILED_VERIFICATION; + } + + infof(data, "%s certificate:\n", SSL_IS_PROXY() ? "Proxy" : "Server"); + + rc = x509_name_oneline(X509_get_subject_name(BACKEND->server_cert), + buffer, sizeof(buffer)); + infof(data, " subject: %s\n", rc?"[NONE]":buffer); + +#ifndef CURL_DISABLE_VERBOSE_STRINGS + { + long len; + ASN1_TIME_print(mem, X509_get0_notBefore(BACKEND->server_cert)); + len = BIO_get_mem_data(mem, (char **) &ptr); + infof(data, " start date: %.*s\n", len, ptr); + (void)BIO_reset(mem); + + ASN1_TIME_print(mem, X509_get0_notAfter(BACKEND->server_cert)); + len = BIO_get_mem_data(mem, (char **) &ptr); + infof(data, " expire date: %.*s\n", len, ptr); + (void)BIO_reset(mem); + } +#endif + + BIO_free(mem); + + if(SSL_CONN_CONFIG(verifyhost)) { + result = verifyhost(conn, BACKEND->server_cert); + if(result) { + X509_free(BACKEND->server_cert); + BACKEND->server_cert = NULL; + return result; + } + } + + rc = x509_name_oneline(X509_get_issuer_name(BACKEND->server_cert), + buffer, sizeof(buffer)); + if(rc) { + if(strict) + failf(data, "SSL: couldn't get X509-issuer name!"); + result = CURLE_PEER_FAILED_VERIFICATION; + } + else { + infof(data, " issuer: %s\n", buffer); + + /* We could do all sorts of certificate verification stuff here before + deallocating the certificate. */ + + /* e.g. match issuer name with provided issuer certificate */ + if(SSL_SET_OPTION(issuercert)) { + fp = BIO_new(BIO_s_file()); + if(fp == NULL) { + failf(data, + "BIO_new return NULL, " OSSL_PACKAGE + " error %s", + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer)) ); + X509_free(BACKEND->server_cert); + BACKEND->server_cert = NULL; + return CURLE_OUT_OF_MEMORY; + } + + if(BIO_read_filename(fp, SSL_SET_OPTION(issuercert)) <= 0) { + if(strict) + failf(data, "SSL: Unable to open issuer cert (%s)", + SSL_SET_OPTION(issuercert)); + BIO_free(fp); + X509_free(BACKEND->server_cert); + BACKEND->server_cert = NULL; + return CURLE_SSL_ISSUER_ERROR; + } + + issuer = PEM_read_bio_X509(fp, NULL, ZERO_NULL, NULL); + if(!issuer) { + if(strict) + failf(data, "SSL: Unable to read issuer cert (%s)", + SSL_SET_OPTION(issuercert)); + BIO_free(fp); + X509_free(issuer); + X509_free(BACKEND->server_cert); + BACKEND->server_cert = NULL; + return CURLE_SSL_ISSUER_ERROR; + } + + if(X509_check_issued(issuer, BACKEND->server_cert) != X509_V_OK) { + if(strict) + failf(data, "SSL: Certificate issuer check failed (%s)", + SSL_SET_OPTION(issuercert)); + BIO_free(fp); + X509_free(issuer); + X509_free(BACKEND->server_cert); + BACKEND->server_cert = NULL; + return CURLE_SSL_ISSUER_ERROR; + } + + infof(data, " SSL certificate issuer check ok (%s)\n", + SSL_SET_OPTION(issuercert)); + BIO_free(fp); + X509_free(issuer); + } + + lerr = *certverifyresult = SSL_get_verify_result(BACKEND->handle); + + if(*certverifyresult != X509_V_OK) { + if(SSL_CONN_CONFIG(verifypeer)) { + /* We probably never reach this, because SSL_connect() will fail + and we return earlier if verifypeer is set? */ + if(strict) + failf(data, "SSL certificate verify result: %s (%ld)", + X509_verify_cert_error_string(lerr), lerr); + result = CURLE_PEER_FAILED_VERIFICATION; + } + else + infof(data, " SSL certificate verify result: %s (%ld)," + " continuing anyway.\n", + X509_verify_cert_error_string(lerr), lerr); + } + else + infof(data, " SSL certificate verify ok.\n"); + } + +#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ + !defined(OPENSSL_NO_OCSP) + if(SSL_CONN_CONFIG(verifystatus)) { + result = verifystatus(conn, connssl); + if(result) { + X509_free(BACKEND->server_cert); + BACKEND->server_cert = NULL; + return result; + } + } +#endif + + if(!strict) + /* when not strict, we don't bother about the verify cert problems */ + result = CURLE_OK; + + ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + if(!result && ptr) { + result = pkp_pin_peer_pubkey(data, BACKEND->server_cert, ptr); + if(result) + failf(data, "SSL: public key does not match pinned public key!"); + } + + X509_free(BACKEND->server_cert); + BACKEND->server_cert = NULL; + connssl->connecting_state = ssl_connect_done; + + return result; +} + +static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex) +{ + CURLcode result = CURLE_OK; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); + + /* + * We check certificates to authenticate the server; otherwise we risk + * man-in-the-middle attack; NEVERTHELESS, if we're told explicitly not to + * verify the peer ignore faults and failures from the server cert + * operations. + */ + + result = servercert(conn, connssl, (SSL_CONN_CONFIG(verifypeer) || + SSL_CONN_CONFIG(verifyhost))); + + if(!result) + connssl->connecting_state = ssl_connect_done; + + return result; +} + +static Curl_recv ossl_recv; +static Curl_send ossl_send; + +static CURLcode ossl_connect_common(struct connectdata *conn, + int sockindex, + bool nonblocking, + bool *done) +{ + CURLcode result; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + time_t timeout_ms; + int what; + + /* check if the connection has already been established */ + if(ssl_connection_complete == connssl->state) { + *done = TRUE; + return CURLE_OK; + } + + if(ssl_connect_1 == connssl->connecting_state) { + /* Find out how much more time we're allowed */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + result = ossl_connect_step1(conn, sockindex); + if(result) + return result; + } + + while(ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state) { + + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* if ssl is expecting something, check if it's available. */ + if(connssl->connecting_state == ssl_connect_2_reading || + connssl->connecting_state == ssl_connect_2_writing) { + + curl_socket_t writefd = ssl_connect_2_writing == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + curl_socket_t readfd = ssl_connect_2_reading == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + + what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, + nonblocking?0:timeout_ms); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + if(0 == what) { + if(nonblocking) { + *done = FALSE; + return CURLE_OK; + } + /* timeout */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + /* socket is readable or writable */ + } + + /* Run transaction, and return to the caller if it failed or if this + * connection is done nonblocking and this loop would execute again. This + * permits the owner of a multi handle to abort a connection attempt + * before step2 has completed while ensuring that a client using select() + * or epoll() will always have a valid fdset to wait on. + */ + result = ossl_connect_step2(conn, sockindex); + if(result || (nonblocking && + (ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state))) + return result; + + } /* repeat step2 until all transactions are done. */ + + if(ssl_connect_3 == connssl->connecting_state) { + result = ossl_connect_step3(conn, sockindex); + if(result) + return result; + } + + if(ssl_connect_done == connssl->connecting_state) { + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = ossl_recv; + conn->send[sockindex] = ossl_send; + *done = TRUE; + } + else + *done = FALSE; + + /* Reset our connect state machine */ + connssl->connecting_state = ssl_connect_1; + + return CURLE_OK; +} + +static CURLcode Curl_ossl_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done) +{ + return ossl_connect_common(conn, sockindex, TRUE, done); +} + +static CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex) +{ + CURLcode result; + bool done = FALSE; + + result = ossl_connect_common(conn, sockindex, FALSE, &done); + if(result) + return result; + + DEBUGASSERT(done); + + return CURLE_OK; +} + +static bool Curl_ossl_data_pending(const struct connectdata *conn, + int connindex) +{ + const struct ssl_connect_data *connssl = &conn->ssl[connindex]; + const struct ssl_connect_data *proxyssl = &conn->proxy_ssl[connindex]; + + if(connssl->backend->handle && SSL_pending(connssl->backend->handle)) + return TRUE; + + if(proxyssl->backend->handle && SSL_pending(proxyssl->backend->handle)) + return TRUE; + + return FALSE; +} + +static size_t Curl_ossl_version(char *buffer, size_t size); + +static ssize_t ossl_send(struct connectdata *conn, + int sockindex, + const void *mem, + size_t len, + CURLcode *curlcode) +{ + /* SSL_write() is said to return 'int' while write() and send() returns + 'size_t' */ + int err; + char error_buffer[256]; + unsigned long sslerror; + int memlen; + int rc; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + ERR_clear_error(); + + memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; + rc = SSL_write(BACKEND->handle, mem, memlen); + + if(rc <= 0) { + err = SSL_get_error(BACKEND->handle, rc); + + switch(err) { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + /* The operation did not complete; the same TLS/SSL I/O function + should be called again later. This is basically an EWOULDBLOCK + equivalent. */ + *curlcode = CURLE_AGAIN; + return -1; + case SSL_ERROR_SYSCALL: + failf(conn->data, "SSL_write() returned SYSCALL, errno = %d", + SOCKERRNO); + *curlcode = CURLE_SEND_ERROR; + return -1; + case SSL_ERROR_SSL: + /* A failure in the SSL library occurred, usually a protocol error. + The OpenSSL error queue contains more information on the error. */ + sslerror = ERR_get_error(); + if(ERR_GET_LIB(sslerror) == ERR_LIB_SSL && + ERR_GET_REASON(sslerror) == SSL_R_BIO_NOT_SET && + conn->ssl[sockindex].state == ssl_connection_complete && + conn->proxy_ssl[sockindex].state == ssl_connection_complete) { + char ver[120]; + Curl_ossl_version(ver, 120); + failf(conn->data, "Error: %s does not support double SSL tunneling.", + ver); + } + else + failf(conn->data, "SSL_write() error: %s", + ossl_strerror(sslerror, error_buffer, sizeof(error_buffer))); + *curlcode = CURLE_SEND_ERROR; + return -1; + } + /* a true error */ + failf(conn->data, OSSL_PACKAGE " SSL_write: %s, errno %d", + SSL_ERROR_to_str(err), SOCKERRNO); + *curlcode = CURLE_SEND_ERROR; + return -1; + } + *curlcode = CURLE_OK; + return (ssize_t)rc; /* number of bytes */ +} + +static ssize_t ossl_recv(struct connectdata *conn, /* connection data */ + int num, /* socketindex */ + char *buf, /* store read data here */ + size_t buffersize, /* max amount to read */ + CURLcode *curlcode) +{ + char error_buffer[256]; + unsigned long sslerror; + ssize_t nread; + int buffsize; + struct ssl_connect_data *connssl = &conn->ssl[num]; + + ERR_clear_error(); + + buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; + nread = (ssize_t)SSL_read(BACKEND->handle, buf, buffsize); + if(nread <= 0) { + /* failed SSL_read */ + int err = SSL_get_error(BACKEND->handle, (int)nread); + + switch(err) { + case SSL_ERROR_NONE: /* this is not an error */ + break; + case SSL_ERROR_ZERO_RETURN: /* no more data */ + /* close_notify alert */ + connclose(conn, "TLS close_notify"); + break; + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + /* there's data pending, re-invoke SSL_read() */ + *curlcode = CURLE_AGAIN; + return -1; + default: + /* openssl/ssl.h for SSL_ERROR_SYSCALL says "look at error stack/return + value/errno" */ + /* https://www.openssl.org/docs/crypto/ERR_get_error.html */ + sslerror = ERR_get_error(); + if((nread < 0) || sslerror) { + /* If the return code was negative or there actually is an error in the + queue */ + failf(conn->data, OSSL_PACKAGE " SSL_read: %s, errno %d", + (sslerror ? + ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)) : + SSL_ERROR_to_str(err)), + SOCKERRNO); + *curlcode = CURLE_RECV_ERROR; + return -1; + } + } + } + return nread; +} + +static size_t Curl_ossl_version(char *buffer, size_t size) +{ +#ifdef OPENSSL_IS_BORINGSSL + return msnprintf(buffer, size, OSSL_PACKAGE); +#elif defined(HAVE_OPENSSL_VERSION) && defined(OPENSSL_VERSION_STRING) + return msnprintf(buffer, size, "%s/%s", + OSSL_PACKAGE, OpenSSL_version(OPENSSL_VERSION_STRING)); +#else + /* not BoringSSL and not using OpenSSL_version */ + + char sub[3]; + unsigned long ssleay_value; + sub[2]='\0'; + sub[1]='\0'; + ssleay_value = OpenSSL_version_num(); + if(ssleay_value < 0x906000) { + ssleay_value = SSLEAY_VERSION_NUMBER; + sub[0]='\0'; + } + else { + if(ssleay_value&0xff0) { + int minor_ver = (ssleay_value >> 4) & 0xff; + if(minor_ver > 26) { + /* handle extended version introduced for 0.9.8za */ + sub[1] = (char) ((minor_ver - 1) % 26 + 'a' + 1); + sub[0] = 'z'; + } + else { + sub[0] = (char) (minor_ver + 'a' - 1); + } + } + else + sub[0]='\0'; + } + + return msnprintf(buffer, size, "%s/%lx.%lx.%lx%s" +#ifdef OPENSSL_FIPS + "-fips" +#endif + , + OSSL_PACKAGE, + (ssleay_value>>28)&0xf, + (ssleay_value>>20)&0xff, + (ssleay_value>>12)&0xff, + sub); +#endif /* OPENSSL_IS_BORINGSSL */ +} + +/* can be called with data == NULL */ +static CURLcode Curl_ossl_random(struct Curl_easy *data, + unsigned char *entropy, size_t length) +{ + int rc; + if(data) { + if(Curl_ossl_seed(data)) /* Initiate the seed if not already done */ + return CURLE_FAILED_INIT; /* couldn't seed for some reason */ + } + else { + if(!rand_enough()) + return CURLE_FAILED_INIT; + } + /* RAND_bytes() returns 1 on success, 0 otherwise. */ + rc = RAND_bytes(entropy, curlx_uztosi(length)); + return (rc == 1 ? CURLE_OK : CURLE_FAILED_INIT); +} + +static CURLcode Curl_ossl_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum /* output */, + size_t unused) +{ + EVP_MD_CTX *mdctx; + unsigned int len = 0; + (void) unused; + + mdctx = EVP_MD_CTX_create(); + EVP_DigestInit_ex(mdctx, EVP_md5(), NULL); + EVP_DigestUpdate(mdctx, tmp, tmplen); + EVP_DigestFinal_ex(mdctx, md5sum, &len); + EVP_MD_CTX_destroy(mdctx); + return CURLE_OK; +} + +#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256) +static CURLcode Curl_ossl_sha256sum(const unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *sha256sum /* output */, + size_t unused) +{ + EVP_MD_CTX *mdctx; + unsigned int len = 0; + (void) unused; + + mdctx = EVP_MD_CTX_create(); + EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL); + EVP_DigestUpdate(mdctx, tmp, tmplen); + EVP_DigestFinal_ex(mdctx, sha256sum, &len); + EVP_MD_CTX_destroy(mdctx); + return CURLE_OK; +} +#endif + +static bool Curl_ossl_cert_status_request(void) +{ +#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ + !defined(OPENSSL_NO_OCSP) + return TRUE; +#else + return FALSE; +#endif +} + +static void *Curl_ossl_get_internals(struct ssl_connect_data *connssl, + CURLINFO info) +{ + /* Legacy: CURLINFO_TLS_SESSION must return an SSL_CTX pointer. */ + return info == CURLINFO_TLS_SESSION ? + (void *)BACKEND->ctx : (void *)BACKEND->handle; +} + +const struct Curl_ssl Curl_ssl_openssl = { + { CURLSSLBACKEND_OPENSSL, "openssl" }, /* info */ + + SSLSUPP_CA_PATH | + SSLSUPP_CERTINFO | + SSLSUPP_PINNEDPUBKEY | + SSLSUPP_SSL_CTX | +#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES + SSLSUPP_TLS13_CIPHERSUITES | +#endif + SSLSUPP_HTTPS_PROXY, + + sizeof(struct ssl_backend_data), + + Curl_ossl_init, /* init */ + Curl_ossl_cleanup, /* cleanup */ + Curl_ossl_version, /* version */ + Curl_ossl_check_cxn, /* check_cxn */ + Curl_ossl_shutdown, /* shutdown */ + Curl_ossl_data_pending, /* data_pending */ + Curl_ossl_random, /* random */ + Curl_ossl_cert_status_request, /* cert_status_request */ + Curl_ossl_connect, /* connect */ + Curl_ossl_connect_nonblocking, /* connect_nonblocking */ + Curl_ossl_get_internals, /* get_internals */ + Curl_ossl_close, /* close_one */ + Curl_ossl_close_all, /* close_all */ + Curl_ossl_session_free, /* session_free */ + Curl_ossl_set_engine, /* set_engine */ + Curl_ossl_set_engine_default, /* set_engine_default */ + Curl_ossl_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ + Curl_ossl_md5sum, /* md5sum */ +#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256) + Curl_ossl_sha256sum /* sha256sum */ +#else + NULL /* sha256sum */ +#endif +}; + +#endif /* USE_OPENSSL */ diff --git a/dependencies/cmcurl/lib/vtls/openssl.h b/dependencies/cmcurl/lib/vtls/openssl.h new file mode 100644 index 0000000..114dc4b --- /dev/null +++ b/dependencies/cmcurl/lib/vtls/openssl.h @@ -0,0 +1,37 @@ +#ifndef HEADER_CURL_SSLUSE_H +#define HEADER_CURL_SSLUSE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_OPENSSL +/* + * This header should only be needed to get included by vtls.c and openssl.c + */ + +#include "urldata.h" + +extern const struct Curl_ssl Curl_ssl_openssl; + +#endif /* USE_OPENSSL */ +#endif /* HEADER_CURL_SSLUSE_H */ diff --git a/dependencies/cmcurl/lib/vtls/polarssl.c b/dependencies/cmcurl/lib/vtls/polarssl.c new file mode 100644 index 0000000..7ea26b4 --- /dev/null +++ b/dependencies/cmcurl/lib/vtls/polarssl.c @@ -0,0 +1,931 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2019, Daniel Stenberg, , et al. + * Copyright (C) 2010 - 2011, Hoi-Ho Chan, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all PolarSSL-specific code for the TLS/SSL layer. No code + * but vtls.c should ever call or use these functions. + * + */ + +#include "curl_setup.h" + +#ifdef USE_POLARSSL +#include +#include +#include +#include +#include +#include + +#if POLARSSL_VERSION_NUMBER < 0x01030000 +#error too old PolarSSL +#endif + +#include +#include +#include + +#include "urldata.h" +#include "sendf.h" +#include "inet_pton.h" +#include "polarssl.h" +#include "vtls.h" +#include "parsedate.h" +#include "connect.h" /* for the connect timeout */ +#include "select.h" +#include "strcase.h" +#include "polarssl_threadlock.h" +#include "multiif.h" +#include "curl_printf.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* See https://tls.mbed.org/discussions/generic/ + howto-determine-exact-buffer-len-for-mbedtls_pk_write_pubkey_der +*/ +#define RSA_PUB_DER_MAX_BYTES (38 + 2 * POLARSSL_MPI_MAX_SIZE) +#define ECP_PUB_DER_MAX_BYTES (30 + 2 * POLARSSL_ECP_MAX_BYTES) + +#define PUB_DER_MAX_BYTES (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ + RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES) + +struct ssl_backend_data { + ctr_drbg_context ctr_drbg; + entropy_context entropy; + ssl_context ssl; + int server_fd; + x509_crt cacert; + x509_crt clicert; + x509_crl crl; + rsa_context rsa; +}; + +#define BACKEND connssl->backend + +/* apply threading? */ +#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) +#define THREADING_SUPPORT +#endif + +#ifndef POLARSSL_ERROR_C +#define error_strerror(x,y,z) +#endif /* POLARSSL_ERROR_C */ + + +#if defined(THREADING_SUPPORT) +static entropy_context entropy; + +static int entropy_init_initialized = 0; + +/* start of entropy_init_mutex() */ +static void entropy_init_mutex(entropy_context *ctx) +{ + /* lock 0 = entropy_init_mutex() */ + Curl_polarsslthreadlock_lock_function(0); + if(entropy_init_initialized == 0) { + entropy_init(ctx); + entropy_init_initialized = 1; + } + Curl_polarsslthreadlock_unlock_function(0); +} +/* end of entropy_init_mutex() */ + +/* start of entropy_func_mutex() */ +static int entropy_func_mutex(void *data, unsigned char *output, size_t len) +{ + int ret; + /* lock 1 = entropy_func_mutex() */ + Curl_polarsslthreadlock_lock_function(1); + ret = entropy_func(data, output, len); + Curl_polarsslthreadlock_unlock_function(1); + + return ret; +} +/* end of entropy_func_mutex() */ + +#endif /* THREADING_SUPPORT */ + +/* Define this to enable lots of debugging for PolarSSL */ +#undef POLARSSL_DEBUG + +#ifdef POLARSSL_DEBUG +static void polarssl_debug(void *context, int level, const char *line) +{ + struct Curl_easy *data = NULL; + + if(!context) + return; + + data = (struct Curl_easy *)context; + + infof(data, "%s", line); + (void) level; +} +#else +#endif + +/* ALPN for http2? */ +#ifdef POLARSSL_SSL_ALPN +# define HAS_ALPN +#endif + +static Curl_recv polarssl_recv; +static Curl_send polarssl_send; + +static CURLcode polarssl_version_from_curl(int *polarver, long ssl_version) +{ + switch(ssl_version) { + case CURL_SSLVERSION_TLSv1_0: + *polarver = SSL_MINOR_VERSION_1; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_1: + *polarver = SSL_MINOR_VERSION_2; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_2: + *polarver = SSL_MINOR_VERSION_3; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_3: + break; + } + return CURLE_SSL_CONNECT_ERROR; +} + +static CURLcode +set_ssl_version_min_max(struct connectdata *conn, int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data* connssl = &conn->ssl[sockindex]; + long ssl_version = SSL_CONN_CONFIG(version); + long ssl_version_max = SSL_CONN_CONFIG(version_max); + int ssl_min_ver = SSL_MINOR_VERSION_1; + int ssl_max_ver = SSL_MINOR_VERSION_1; + CURLcode result = CURLE_OK; + + switch(ssl_version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + ssl_version = CURL_SSLVERSION_TLSv1_0; + break; + } + + switch(ssl_version_max) { + case CURL_SSLVERSION_MAX_NONE: + case CURL_SSLVERSION_MAX_DEFAULT: + ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; + break; + } + + result = polarssl_version_from_curl(&ssl_min_ver, ssl_version); + if(result) { + failf(data, "unsupported min version passed via CURLOPT_SSLVERSION"); + return result; + } + result = polarssl_version_from_curl(&ssl_max_ver, ssl_version_max >> 16); + if(result) { + failf(data, "unsupported max version passed via CURLOPT_SSLVERSION"); + return result; + } + + ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, ssl_min_ver); + ssl_set_max_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, ssl_max_ver); + + return result; +} + +static CURLcode +polarssl_connect_step1(struct connectdata *conn, + int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data* connssl = &conn->ssl[sockindex]; + const char *capath = SSL_CONN_CONFIG(CApath); + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; + int ret = -1; + char errorbuf[128]; + errorbuf[0] = 0; + + /* PolarSSL only supports SSLv3 and TLSv1 */ + if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) { + failf(data, "PolarSSL does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + +#ifdef THREADING_SUPPORT + entropy_init_mutex(&entropy); + + if((ret = ctr_drbg_init(&BACKEND->ctr_drbg, entropy_func_mutex, &entropy, + NULL, 0)) != 0) { + error_strerror(ret, errorbuf, sizeof(errorbuf)); + failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n", + -ret, errorbuf); + } +#else + entropy_init(&BACKEND->entropy); + + if((ret = ctr_drbg_init(&BACKEND->ctr_drbg, entropy_func, &BACKEND->entropy, + NULL, 0)) != 0) { + error_strerror(ret, errorbuf, sizeof(errorbuf)); + failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n", + -ret, errorbuf); + } +#endif /* THREADING_SUPPORT */ + + /* Load the trusted CA */ + memset(&BACKEND->cacert, 0, sizeof(x509_crt)); + + if(SSL_CONN_CONFIG(CAfile)) { + ret = x509_crt_parse_file(&BACKEND->cacert, + SSL_CONN_CONFIG(CAfile)); + + if(ret<0) { + error_strerror(ret, errorbuf, sizeof(errorbuf)); + failf(data, "Error reading ca cert file %s - PolarSSL: (-0x%04X) %s", + SSL_CONN_CONFIG(CAfile), -ret, errorbuf); + + if(SSL_CONN_CONFIG(verifypeer)) + return CURLE_SSL_CACERT_BADFILE; + } + } + + if(capath) { + ret = x509_crt_parse_path(&BACKEND->cacert, capath); + + if(ret<0) { + error_strerror(ret, errorbuf, sizeof(errorbuf)); + failf(data, "Error reading ca cert path %s - PolarSSL: (-0x%04X) %s", + capath, -ret, errorbuf); + + if(SSL_CONN_CONFIG(verifypeer)) + return CURLE_SSL_CACERT_BADFILE; + } + } + + /* Load the client certificate */ + memset(&BACKEND->clicert, 0, sizeof(x509_crt)); + + if(SSL_SET_OPTION(cert)) { + ret = x509_crt_parse_file(&BACKEND->clicert, + SSL_SET_OPTION(cert)); + + if(ret) { + error_strerror(ret, errorbuf, sizeof(errorbuf)); + failf(data, "Error reading client cert file %s - PolarSSL: (-0x%04X) %s", + SSL_SET_OPTION(cert), -ret, errorbuf); + + return CURLE_SSL_CERTPROBLEM; + } + } + + /* Load the client private key */ + if(SSL_SET_OPTION(key)) { + pk_context pk; + pk_init(&pk); + ret = pk_parse_keyfile(&pk, SSL_SET_OPTION(key), + SSL_SET_OPTION(key_passwd)); + if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA)) + ret = POLARSSL_ERR_PK_TYPE_MISMATCH; + if(ret == 0) + rsa_copy(&BACKEND->rsa, pk_rsa(pk)); + else + rsa_free(&BACKEND->rsa); + pk_free(&pk); + + if(ret) { + error_strerror(ret, errorbuf, sizeof(errorbuf)); + failf(data, "Error reading private key %s - PolarSSL: (-0x%04X) %s", + SSL_SET_OPTION(key), -ret, errorbuf); + + return CURLE_SSL_CERTPROBLEM; + } + } + + /* Load the CRL */ + memset(&BACKEND->crl, 0, sizeof(x509_crl)); + + if(SSL_SET_OPTION(CRLfile)) { + ret = x509_crl_parse_file(&BACKEND->crl, + SSL_SET_OPTION(CRLfile)); + + if(ret) { + error_strerror(ret, errorbuf, sizeof(errorbuf)); + failf(data, "Error reading CRL file %s - PolarSSL: (-0x%04X) %s", + SSL_SET_OPTION(CRLfile), -ret, errorbuf); + + return CURLE_SSL_CRL_BADFILE; + } + } + + infof(data, "PolarSSL: Connecting to %s:%d\n", hostname, port); + + if(ssl_init(&BACKEND->ssl)) { + failf(data, "PolarSSL: ssl_init failed"); + return CURLE_SSL_CONNECT_ERROR; + } + + switch(SSL_CONN_CONFIG(version)) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, + SSL_MINOR_VERSION_1); + break; + case CURL_SSLVERSION_SSLv3: + ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, + SSL_MINOR_VERSION_0); + ssl_set_max_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, + SSL_MINOR_VERSION_0); + infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n"); + break; + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: + { + CURLcode result = set_ssl_version_min_max(conn, sockindex); + if(result != CURLE_OK) + return result; + break; + } + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + + ssl_set_endpoint(&BACKEND->ssl, SSL_IS_CLIENT); + ssl_set_authmode(&BACKEND->ssl, SSL_VERIFY_OPTIONAL); + + ssl_set_rng(&BACKEND->ssl, ctr_drbg_random, + &BACKEND->ctr_drbg); + ssl_set_bio(&BACKEND->ssl, + net_recv, &conn->sock[sockindex], + net_send, &conn->sock[sockindex]); + + ssl_set_ciphersuites(&BACKEND->ssl, ssl_list_ciphersuites()); + + /* Check if there's a cached ID we can/should use here! */ + if(SSL_SET_OPTION(primary.sessionid)) { + void *old_session = NULL; + + Curl_ssl_sessionid_lock(conn); + if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) { + ret = ssl_set_session(&BACKEND->ssl, old_session); + if(ret) { + Curl_ssl_sessionid_unlock(conn); + failf(data, "ssl_set_session returned -0x%x", -ret); + return CURLE_SSL_CONNECT_ERROR; + } + infof(data, "PolarSSL re-using session\n"); + } + Curl_ssl_sessionid_unlock(conn); + } + + ssl_set_ca_chain(&BACKEND->ssl, + &BACKEND->cacert, + &BACKEND->crl, + hostname); + + ssl_set_own_cert_rsa(&BACKEND->ssl, + &BACKEND->clicert, &BACKEND->rsa); + + if(ssl_set_hostname(&BACKEND->ssl, hostname)) { + /* ssl_set_hostname() sets the name to use in CN/SAN checks *and* the name + to set in the SNI extension. So even if curl connects to a host + specified as an IP address, this function must be used. */ + failf(data, "couldn't set hostname in PolarSSL"); + return CURLE_SSL_CONNECT_ERROR; + } + +#ifdef HAS_ALPN + if(conn->bits.tls_enable_alpn) { + static const char *protocols[3]; + int cur = 0; + +#ifdef USE_NGHTTP2 + if(data->set.httpversion >= CURL_HTTP_VERSION_2) { + protocols[cur++] = NGHTTP2_PROTO_VERSION_ID; + infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + } +#endif + + protocols[cur++] = ALPN_HTTP_1_1; + infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); + + protocols[cur] = NULL; + + ssl_set_alpn_protocols(&BACKEND->ssl, protocols); + } +#endif + +#ifdef POLARSSL_DEBUG + ssl_set_dbg(&BACKEND->ssl, polarssl_debug, data); +#endif + + connssl->connecting_state = ssl_connect_2; + + return CURLE_OK; +} + +static CURLcode +polarssl_connect_step2(struct connectdata *conn, + int sockindex) +{ + int ret; + struct Curl_easy *data = conn->data; + struct ssl_connect_data* connssl = &conn->ssl[sockindex]; + char buffer[1024]; + const char * const pinnedpubkey = SSL_IS_PROXY() ? + data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + + + char errorbuf[128]; + errorbuf[0] = 0; + + conn->recv[sockindex] = polarssl_recv; + conn->send[sockindex] = polarssl_send; + + ret = ssl_handshake(&BACKEND->ssl); + + switch(ret) { + case 0: + break; + + case POLARSSL_ERR_NET_WANT_READ: + connssl->connecting_state = ssl_connect_2_reading; + return CURLE_OK; + + case POLARSSL_ERR_NET_WANT_WRITE: + connssl->connecting_state = ssl_connect_2_writing; + return CURLE_OK; + + default: + error_strerror(ret, errorbuf, sizeof(errorbuf)); + failf(data, "ssl_handshake returned - PolarSSL: (-0x%04X) %s", + -ret, errorbuf); + return CURLE_SSL_CONNECT_ERROR; + } + + infof(data, "PolarSSL: Handshake complete, cipher is %s\n", + ssl_get_ciphersuite(&BACKEND->ssl) ); + + ret = ssl_get_verify_result(&BACKEND->ssl); + + if(ret && SSL_CONN_CONFIG(verifypeer)) { + if(ret & BADCERT_EXPIRED) + failf(data, "Cert verify failed: BADCERT_EXPIRED"); + + if(ret & BADCERT_REVOKED) { + failf(data, "Cert verify failed: BADCERT_REVOKED"); + return CURLE_PEER_FAILED_VERIFICATION; + } + + if(ret & BADCERT_CN_MISMATCH) + failf(data, "Cert verify failed: BADCERT_CN_MISMATCH"); + + if(ret & BADCERT_NOT_TRUSTED) + failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED"); + + return CURLE_PEER_FAILED_VERIFICATION; + } + + if(ssl_get_peer_cert(&(BACKEND->ssl))) { + /* If the session was resumed, there will be no peer certs */ + memset(buffer, 0, sizeof(buffer)); + + if(x509_crt_info(buffer, sizeof(buffer), (char *)"* ", + ssl_get_peer_cert(&(BACKEND->ssl))) != -1) + infof(data, "Dumping cert info:\n%s\n", buffer); + } + + /* adapted from mbedtls.c */ + if(pinnedpubkey) { + int size; + CURLcode result; + x509_crt *p; + unsigned char pubkey[PUB_DER_MAX_BYTES]; + const x509_crt *peercert; + + peercert = ssl_get_peer_cert(&BACKEND->ssl); + + if(!peercert || !peercert->raw.p || !peercert->raw.len) { + failf(data, "Failed due to missing peer certificate"); + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + } + + p = calloc(1, sizeof(*p)); + + if(!p) + return CURLE_OUT_OF_MEMORY; + + x509_crt_init(p); + + /* Make a copy of our const peercert because pk_write_pubkey_der + needs a non-const key, for now. + https://github.com/ARMmbed/mbedtls/issues/396 */ + if(x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) { + failf(data, "Failed copying peer certificate"); + x509_crt_free(p); + free(p); + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + } + + size = pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES); + + if(size <= 0) { + failf(data, "Failed copying public key from peer certificate"); + x509_crt_free(p); + free(p); + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + } + + /* pk_write_pubkey_der writes data at the end of the buffer. */ + result = Curl_pin_peer_pubkey(data, + pinnedpubkey, + &pubkey[PUB_DER_MAX_BYTES - size], size); + if(result) { + x509_crt_free(p); + free(p); + return result; + } + + x509_crt_free(p); + free(p); + } + +#ifdef HAS_ALPN + if(conn->bits.tls_enable_alpn) { + const char *next_protocol = ssl_get_alpn_protocol(&BACKEND->ssl); + + if(next_protocol != NULL) { + infof(data, "ALPN, server accepted to use %s\n", next_protocol); + +#ifdef USE_NGHTTP2 + if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID, + NGHTTP2_PROTO_VERSION_ID_LEN)) { + conn->negnpn = CURL_HTTP_VERSION_2; + } + else +#endif + if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH)) { + conn->negnpn = CURL_HTTP_VERSION_1_1; + } + } + else + infof(data, "ALPN, server did not agree to a protocol\n"); + Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); + } +#endif + + connssl->connecting_state = ssl_connect_3; + infof(data, "SSL connected\n"); + + return CURLE_OK; +} + +static CURLcode +polarssl_connect_step3(struct connectdata *conn, + int sockindex) +{ + CURLcode retcode = CURLE_OK; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct Curl_easy *data = conn->data; + + DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); + + if(SSL_SET_OPTION(primary.sessionid)) { + int ret; + ssl_session *our_ssl_sessionid; + void *old_ssl_sessionid = NULL; + + our_ssl_sessionid = calloc(1, sizeof(ssl_session)); + if(!our_ssl_sessionid) + return CURLE_OUT_OF_MEMORY; + + ret = ssl_get_session(&BACKEND->ssl, our_ssl_sessionid); + if(ret) { + failf(data, "ssl_get_session returned -0x%x", -ret); + return CURLE_SSL_CONNECT_ERROR; + } + + /* If there's already a matching session in the cache, delete it */ + Curl_ssl_sessionid_lock(conn); + if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex)) + Curl_ssl_delsessionid(conn, old_ssl_sessionid); + + retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex); + Curl_ssl_sessionid_unlock(conn); + if(retcode) { + free(our_ssl_sessionid); + failf(data, "failed to store ssl session"); + return retcode; + } + } + + connssl->connecting_state = ssl_connect_done; + + return CURLE_OK; +} + +static ssize_t polarssl_send(struct connectdata *conn, + int sockindex, + const void *mem, + size_t len, + CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + int ret = -1; + + ret = ssl_write(&BACKEND->ssl, + (unsigned char *)mem, len); + + if(ret < 0) { + *curlcode = (ret == POLARSSL_ERR_NET_WANT_WRITE) ? + CURLE_AGAIN : CURLE_SEND_ERROR; + ret = -1; + } + + return ret; +} + +static void Curl_polarssl_close(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + rsa_free(&BACKEND->rsa); + x509_crt_free(&BACKEND->clicert); + x509_crt_free(&BACKEND->cacert); + x509_crl_free(&BACKEND->crl); + ssl_free(&BACKEND->ssl); +} + +static ssize_t polarssl_recv(struct connectdata *conn, + int num, + char *buf, + size_t buffersize, + CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[num]; + int ret = -1; + ssize_t len = -1; + + memset(buf, 0, buffersize); + ret = ssl_read(&BACKEND->ssl, (unsigned char *)buf, buffersize); + + if(ret <= 0) { + if(ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY) + return 0; + + *curlcode = (ret == POLARSSL_ERR_NET_WANT_READ) ? + CURLE_AGAIN : CURLE_RECV_ERROR; + return -1; + } + + len = ret; + + return len; +} + +static void Curl_polarssl_session_free(void *ptr) +{ + ssl_session_free(ptr); + free(ptr); +} + +/* 1.3.10 was the first rebranded version. All new releases (in 1.3 branch and + higher) will be mbed TLS branded.. */ + +static size_t Curl_polarssl_version(char *buffer, size_t size) +{ + unsigned int version = version_get_number(); + return msnprintf(buffer, size, "%s/%d.%d.%d", + version >= 0x01030A00?"mbedTLS":"PolarSSL", + version>>24, (version>>16)&0xff, (version>>8)&0xff); +} + +static CURLcode +polarssl_connect_common(struct connectdata *conn, + int sockindex, + bool nonblocking, + bool *done) +{ + CURLcode result; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + long timeout_ms; + int what; + + /* check if the connection has already been established */ + if(ssl_connection_complete == connssl->state) { + *done = TRUE; + return CURLE_OK; + } + + if(ssl_connect_1 == connssl->connecting_state) { + /* Find out how much more time we're allowed */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + result = polarssl_connect_step1(conn, sockindex); + if(result) + return result; + } + + while(ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state) { + + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* if ssl is expecting something, check if it's available. */ + if(connssl->connecting_state == ssl_connect_2_reading || + connssl->connecting_state == ssl_connect_2_writing) { + + curl_socket_t writefd = ssl_connect_2_writing == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + curl_socket_t readfd = ssl_connect_2_reading == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + + what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, + nonblocking?0:timeout_ms); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + else if(0 == what) { + if(nonblocking) { + *done = FALSE; + return CURLE_OK; + } + else { + /* timeout */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + } + /* socket is readable or writable */ + } + + /* Run transaction, and return to the caller if it failed or if + * this connection is part of a multi handle and this loop would + * execute again. This permits the owner of a multi handle to + * abort a connection attempt before step2 has completed while + * ensuring that a client using select() or epoll() will always + * have a valid fdset to wait on. + */ + result = polarssl_connect_step2(conn, sockindex); + if(result || (nonblocking && + (ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state))) + return result; + + } /* repeat step2 until all transactions are done. */ + + if(ssl_connect_3 == connssl->connecting_state) { + result = polarssl_connect_step3(conn, sockindex); + if(result) + return result; + } + + if(ssl_connect_done == connssl->connecting_state) { + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = polarssl_recv; + conn->send[sockindex] = polarssl_send; + *done = TRUE; + } + else + *done = FALSE; + + /* Reset our connect state machine */ + connssl->connecting_state = ssl_connect_1; + + return CURLE_OK; +} + +static CURLcode Curl_polarssl_connect_nonblocking(struct connectdata *conn, + int sockindex, bool *done) +{ + return polarssl_connect_common(conn, sockindex, TRUE, done); +} + + +static CURLcode Curl_polarssl_connect(struct connectdata *conn, int sockindex) +{ + CURLcode result; + bool done = FALSE; + + result = polarssl_connect_common(conn, sockindex, FALSE, &done); + if(result) + return result; + + DEBUGASSERT(done); + + return CURLE_OK; +} + +/* + * return 0 error initializing SSL + * return 1 SSL initialized successfully + */ +static int Curl_polarssl_init(void) +{ + return Curl_polarsslthreadlock_thread_setup(); +} + +static void Curl_polarssl_cleanup(void) +{ + (void)Curl_polarsslthreadlock_thread_cleanup(); +} + +static bool Curl_polarssl_data_pending(const struct connectdata *conn, + int sockindex) +{ + const struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + return ssl_get_bytes_avail(&BACKEND->ssl) != 0; +} + +static CURLcode Curl_polarssl_sha256sum(const unsigned char *input, + size_t inputlen, + unsigned char *sha256sum, + size_t sha256len UNUSED_PARAM) +{ + (void)sha256len; + sha256(input, inputlen, sha256sum, 0); + return CURLE_OK; +} + +static void *Curl_polarssl_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) +{ + (void)info; + return &BACKEND->ssl; +} + +const struct Curl_ssl Curl_ssl_polarssl = { + { CURLSSLBACKEND_POLARSSL, "polarssl" }, /* info */ + + SSLSUPP_CA_PATH | + SSLSUPP_PINNEDPUBKEY, + + sizeof(struct ssl_backend_data), + + Curl_polarssl_init, /* init */ + Curl_polarssl_cleanup, /* cleanup */ + Curl_polarssl_version, /* version */ + Curl_none_check_cxn, /* check_cxn */ + Curl_none_shutdown, /* shutdown */ + Curl_polarssl_data_pending, /* data_pending */ + /* This might cause libcurl to use a weeker random! */ + Curl_none_random, /* random */ + Curl_none_cert_status_request, /* cert_status_request */ + Curl_polarssl_connect, /* connect */ + Curl_polarssl_connect_nonblocking, /* connect_nonblocking */ + Curl_polarssl_get_internals, /* get_internals */ + Curl_polarssl_close, /* close_one */ + Curl_none_close_all, /* close_all */ + Curl_polarssl_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ + Curl_none_md5sum, /* md5sum */ + Curl_polarssl_sha256sum /* sha256sum */ +}; + +#endif /* USE_POLARSSL */ diff --git a/dependencies/cmcurl/lib/vtls/polarssl.h b/dependencies/cmcurl/lib/vtls/polarssl.h new file mode 100644 index 0000000..23c3636 --- /dev/null +++ b/dependencies/cmcurl/lib/vtls/polarssl.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_POLARSSL_H +#define HEADER_CURL_POLARSSL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 2010, Hoi-Ho Chan, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_POLARSSL + +extern const struct Curl_ssl Curl_ssl_polarssl; + +#endif /* USE_POLARSSL */ +#endif /* HEADER_CURL_POLARSSL_H */ diff --git a/dependencies/cmcurl/lib/vtls/polarssl_threadlock.c b/dependencies/cmcurl/lib/vtls/polarssl_threadlock.c new file mode 100644 index 0000000..27c94b1 --- /dev/null +++ b/dependencies/cmcurl/lib/vtls/polarssl_threadlock.c @@ -0,0 +1,144 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2013-2017, Daniel Stenberg, , et al. + * Copyright (C) 2010, 2011, Hoi-Ho Chan, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if (defined(USE_POLARSSL) || defined(USE_MBEDTLS)) && \ + ((defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \ + (defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H))) + +#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) +# include +# define POLARSSL_MUTEX_T pthread_mutex_t +#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) +# include +# define POLARSSL_MUTEX_T HANDLE +#endif + +#include "polarssl_threadlock.h" +#include "curl_printf.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* number of thread locks */ +#define NUMT 2 + +/* This array will store all of the mutexes available to PolarSSL. */ +static POLARSSL_MUTEX_T *mutex_buf = NULL; + +int Curl_polarsslthreadlock_thread_setup(void) +{ + int i; + + mutex_buf = calloc(NUMT * sizeof(POLARSSL_MUTEX_T), 1); + if(!mutex_buf) + return 0; /* error, no number of threads defined */ + + for(i = 0; i < NUMT; i++) { + int ret; +#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) + ret = pthread_mutex_init(&mutex_buf[i], NULL); + if(ret) + return 0; /* pthread_mutex_init failed */ +#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) + mutex_buf[i] = CreateMutex(0, FALSE, 0); + if(mutex_buf[i] == 0) + return 0; /* CreateMutex failed */ +#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */ + } + + return 1; /* OK */ +} + +int Curl_polarsslthreadlock_thread_cleanup(void) +{ + int i; + + if(!mutex_buf) + return 0; /* error, no threads locks defined */ + + for(i = 0; i < NUMT; i++) { + int ret; +#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) + ret = pthread_mutex_destroy(&mutex_buf[i]); + if(ret) + return 0; /* pthread_mutex_destroy failed */ +#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) + ret = CloseHandle(mutex_buf[i]); + if(!ret) + return 0; /* CloseHandle failed */ +#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */ + } + free(mutex_buf); + mutex_buf = NULL; + + return 1; /* OK */ +} + +int Curl_polarsslthreadlock_lock_function(int n) +{ + if(n < NUMT) { + int ret; +#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) + ret = pthread_mutex_lock(&mutex_buf[n]); + if(ret) { + DEBUGF(fprintf(stderr, + "Error: polarsslthreadlock_lock_function failed\n")); + return 0; /* pthread_mutex_lock failed */ + } +#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) + ret = (WaitForSingleObject(mutex_buf[n], INFINITE) == WAIT_FAILED?1:0); + if(ret) { + DEBUGF(fprintf(stderr, + "Error: polarsslthreadlock_lock_function failed\n")); + return 0; /* pthread_mutex_lock failed */ + } +#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */ + } + return 1; /* OK */ +} + +int Curl_polarsslthreadlock_unlock_function(int n) +{ + if(n < NUMT) { + int ret; +#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) + ret = pthread_mutex_unlock(&mutex_buf[n]); + if(ret) { + DEBUGF(fprintf(stderr, + "Error: polarsslthreadlock_unlock_function failed\n")); + return 0; /* pthread_mutex_unlock failed */ + } +#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) + ret = ReleaseMutex(mutex_buf[n]); + if(!ret) { + DEBUGF(fprintf(stderr, + "Error: polarsslthreadlock_unlock_function failed\n")); + return 0; /* pthread_mutex_lock failed */ + } +#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */ + } + return 1; /* OK */ +} + +#endif /* USE_POLARSSL || USE_MBEDTLS */ diff --git a/dependencies/cmcurl/lib/vtls/polarssl_threadlock.h b/dependencies/cmcurl/lib/vtls/polarssl_threadlock.h new file mode 100644 index 0000000..1226475 --- /dev/null +++ b/dependencies/cmcurl/lib/vtls/polarssl_threadlock.h @@ -0,0 +1,48 @@ +#ifndef HEADER_CURL_POLARSSL_THREADLOCK_H +#define HEADER_CURL_POLARSSL_THREADLOCK_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2013-2015, Daniel Stenberg, , et al. + * Copyright (C) 2010, Hoi-Ho Chan, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if (defined USE_POLARSSL) || (defined USE_MBEDTLS) + +#if (defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \ + (defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)) + +int Curl_polarsslthreadlock_thread_setup(void); +int Curl_polarsslthreadlock_thread_cleanup(void); +int Curl_polarsslthreadlock_lock_function(int n); +int Curl_polarsslthreadlock_unlock_function(int n); + +#else + +#define Curl_polarsslthreadlock_thread_setup() 1 +#define Curl_polarsslthreadlock_thread_cleanup() 1 +#define Curl_polarsslthreadlock_lock_function(x) 1 +#define Curl_polarsslthreadlock_unlock_function(x) 1 + +#endif /* USE_THREADS_POSIX || USE_THREADS_WIN32 */ + +#endif /* USE_POLARSSL */ + +#endif /* HEADER_CURL_POLARSSL_THREADLOCK_H */ diff --git a/dependencies/cmcurl/lib/vtls/schannel.c b/dependencies/cmcurl/lib/vtls/schannel.c new file mode 100644 index 0000000..0f6f734 --- /dev/null +++ b/dependencies/cmcurl/lib/vtls/schannel.c @@ -0,0 +1,2302 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2016, Marc Hoersken, + * Copyright (C) 2012, Mark Salisbury, + * Copyright (C) 2012 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all Schannel-specific code for the TLS/SSL layer. No code + * but vtls.c should ever call or use these functions. + */ + +/* + * Based upon the PolarSSL implementation in polarssl.c and polarssl.h: + * Copyright (C) 2010, 2011, Hoi-Ho Chan, + * + * Based upon the CyaSSL implementation in cyassl.c and cyassl.h: + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * Thanks for code and inspiration! + */ + +#include "curl_setup.h" + +#ifdef USE_SCHANNEL + +#define EXPOSE_SCHANNEL_INTERNAL_STRUCTS + +#ifndef USE_WINDOWS_SSPI +# error "Can't compile SCHANNEL support without SSPI." +#endif + +#include "schannel.h" +#include "vtls.h" +#include "sendf.h" +#include "connect.h" /* for the connect timeout */ +#include "strerror.h" +#include "select.h" /* for the socket readyness */ +#include "inet_pton.h" /* for IP addr SNI check */ +#include "curl_multibyte.h" +#include "warnless.h" +#include "x509asn1.h" +#include "curl_printf.h" +#include "multiif.h" +#include "system_win32.h" + + /* The last #include file should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* ALPN requires version 8.1 of the Windows SDK, which was + shipped with Visual Studio 2013, aka _MSC_VER 1800: + + https://technet.microsoft.com/en-us/library/hh831771%28v=ws.11%29.aspx +*/ +#if defined(_MSC_VER) && (_MSC_VER >= 1800) && !defined(_USING_V110_SDK71_) +# define HAS_ALPN 1 +#endif + +#ifndef UNISP_NAME_A +#define UNISP_NAME_A "Microsoft Unified Security Protocol Provider" +#endif + +#ifndef UNISP_NAME_W +#define UNISP_NAME_W L"Microsoft Unified Security Protocol Provider" +#endif + +#ifndef UNISP_NAME +#ifdef UNICODE +#define UNISP_NAME UNISP_NAME_W +#else +#define UNISP_NAME UNISP_NAME_A +#endif +#endif + +#if defined(CryptStringToBinary) && defined(CRYPT_STRING_HEX) +#define HAS_CLIENT_CERT_PATH +#endif + +#ifdef HAS_CLIENT_CERT_PATH +#ifdef UNICODE +#define CURL_CERT_STORE_PROV_SYSTEM CERT_STORE_PROV_SYSTEM_W +#else +#define CURL_CERT_STORE_PROV_SYSTEM CERT_STORE_PROV_SYSTEM_A +#endif +#endif + +#ifndef SP_PROT_SSL2_CLIENT +#define SP_PROT_SSL2_CLIENT 0x00000008 +#endif + +#ifndef SP_PROT_SSL3_CLIENT +#define SP_PROT_SSL3_CLIENT 0x00000008 +#endif + +#ifndef SP_PROT_TLS1_CLIENT +#define SP_PROT_TLS1_CLIENT 0x00000080 +#endif + +#ifndef SP_PROT_TLS1_0_CLIENT +#define SP_PROT_TLS1_0_CLIENT SP_PROT_TLS1_CLIENT +#endif + +#ifndef SP_PROT_TLS1_1_CLIENT +#define SP_PROT_TLS1_1_CLIENT 0x00000200 +#endif + +#ifndef SP_PROT_TLS1_2_CLIENT +#define SP_PROT_TLS1_2_CLIENT 0x00000800 +#endif + +#ifndef SECBUFFER_ALERT +#define SECBUFFER_ALERT 17 +#endif + +/* Both schannel buffer sizes must be > 0 */ +#define CURL_SCHANNEL_BUFFER_INIT_SIZE 4096 +#define CURL_SCHANNEL_BUFFER_FREE_SIZE 1024 + +#define CERT_THUMBPRINT_STR_LEN 40 +#define CERT_THUMBPRINT_DATA_LEN 20 + +/* Uncomment to force verbose output + * #define infof(x, y, ...) printf(y, __VA_ARGS__) + * #define failf(x, y, ...) printf(y, __VA_ARGS__) + */ + +#ifndef CALG_SHA_256 +# define CALG_SHA_256 0x0000800c +#endif + +#define BACKEND connssl->backend + +static Curl_recv schannel_recv; +static Curl_send schannel_send; + +static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex, + const char *pinnedpubkey); + +static void InitSecBuffer(SecBuffer *buffer, unsigned long BufType, + void *BufDataPtr, unsigned long BufByteSize) +{ + buffer->cbBuffer = BufByteSize; + buffer->BufferType = BufType; + buffer->pvBuffer = BufDataPtr; +} + +static void InitSecBufferDesc(SecBufferDesc *desc, SecBuffer *BufArr, + unsigned long NumArrElem) +{ + desc->ulVersion = SECBUFFER_VERSION; + desc->pBuffers = BufArr; + desc->cBuffers = NumArrElem; +} + +static CURLcode +set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + long ssl_version = SSL_CONN_CONFIG(version); + long ssl_version_max = SSL_CONN_CONFIG(version_max); + long i = ssl_version; + + switch(ssl_version_max) { + case CURL_SSLVERSION_MAX_NONE: + case CURL_SSLVERSION_MAX_DEFAULT: + ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; + break; + } + for(; i <= (ssl_version_max >> 16); ++i) { + switch(i) { + case CURL_SSLVERSION_TLSv1_0: + schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_0_CLIENT; + break; + case CURL_SSLVERSION_TLSv1_1: + schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_1_CLIENT; + break; + case CURL_SSLVERSION_TLSv1_2: + schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_2_CLIENT; + break; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "schannel: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; + } + } + return CURLE_OK; +} + +/*longest is 26, buffer is slightly bigger*/ +#define LONGEST_ALG_ID 32 +#define CIPHEROPTION(X) \ +if(strcmp(#X, tmp) == 0) \ + return X + +static int +get_alg_id_by_name(char *name) +{ + char tmp[LONGEST_ALG_ID] = { 0 }; + char *nameEnd = strchr(name, ':'); + size_t n = nameEnd ? min((size_t)(nameEnd - name), LONGEST_ALG_ID - 1) : \ + min(strlen(name), LONGEST_ALG_ID - 1); + strncpy(tmp, name, n); + tmp[n] = 0; + CIPHEROPTION(CALG_MD2); + CIPHEROPTION(CALG_MD4); + CIPHEROPTION(CALG_MD5); + CIPHEROPTION(CALG_SHA); + CIPHEROPTION(CALG_SHA1); + CIPHEROPTION(CALG_MAC); + CIPHEROPTION(CALG_RSA_SIGN); + CIPHEROPTION(CALG_DSS_SIGN); +/*ifdefs for the options that are defined conditionally in wincrypt.h*/ +#ifdef CALG_NO_SIGN + CIPHEROPTION(CALG_NO_SIGN); +#endif + CIPHEROPTION(CALG_RSA_KEYX); + CIPHEROPTION(CALG_DES); +#ifdef CALG_3DES_112 + CIPHEROPTION(CALG_3DES_112); +#endif + CIPHEROPTION(CALG_3DES); + CIPHEROPTION(CALG_DESX); + CIPHEROPTION(CALG_RC2); + CIPHEROPTION(CALG_RC4); + CIPHEROPTION(CALG_SEAL); +#ifdef CALG_DH_SF + CIPHEROPTION(CALG_DH_SF); +#endif + CIPHEROPTION(CALG_DH_EPHEM); +#ifdef CALG_AGREEDKEY_ANY + CIPHEROPTION(CALG_AGREEDKEY_ANY); +#endif +#ifdef CALG_HUGHES_MD5 + CIPHEROPTION(CALG_HUGHES_MD5); +#endif + CIPHEROPTION(CALG_SKIPJACK); +#ifdef CALG_TEK + CIPHEROPTION(CALG_TEK); +#endif + CIPHEROPTION(CALG_CYLINK_MEK); + CIPHEROPTION(CALG_SSL3_SHAMD5); +#ifdef CALG_SSL3_MASTER + CIPHEROPTION(CALG_SSL3_MASTER); +#endif +#ifdef CALG_SCHANNEL_MASTER_HASH + CIPHEROPTION(CALG_SCHANNEL_MASTER_HASH); +#endif +#ifdef CALG_SCHANNEL_MAC_KEY + CIPHEROPTION(CALG_SCHANNEL_MAC_KEY); +#endif +#ifdef CALG_SCHANNEL_ENC_KEY + CIPHEROPTION(CALG_SCHANNEL_ENC_KEY); +#endif +#ifdef CALG_PCT1_MASTER + CIPHEROPTION(CALG_PCT1_MASTER); +#endif +#ifdef CALG_SSL2_MASTER + CIPHEROPTION(CALG_SSL2_MASTER); +#endif +#ifdef CALG_TLS1_MASTER + CIPHEROPTION(CALG_TLS1_MASTER); +#endif +#ifdef CALG_RC5 + CIPHEROPTION(CALG_RC5); +#endif +#ifdef CALG_HMAC + CIPHEROPTION(CALG_HMAC); +#endif +#if !defined(__W32API_MAJOR_VERSION) || \ + !defined(__W32API_MINOR_VERSION) || \ + defined(__MINGW64_VERSION_MAJOR) || \ + (__W32API_MAJOR_VERSION > 5) || \ + ((__W32API_MAJOR_VERSION == 5) && (__W32API_MINOR_VERSION > 0)) + /* CALG_TLS1PRF has a syntax error in MinGW's w32api up to version 5.0, + see https://osdn.net/projects/mingw/ticket/38391 */ + CIPHEROPTION(CALG_TLS1PRF); +#endif +#ifdef CALG_HASH_REPLACE_OWF + CIPHEROPTION(CALG_HASH_REPLACE_OWF); +#endif +#ifdef CALG_AES_128 + CIPHEROPTION(CALG_AES_128); +#endif +#ifdef CALG_AES_192 + CIPHEROPTION(CALG_AES_192); +#endif +#ifdef CALG_AES_256 + CIPHEROPTION(CALG_AES_256); +#endif +#ifdef CALG_AES + CIPHEROPTION(CALG_AES); +#endif +#ifdef CALG_SHA_256 + CIPHEROPTION(CALG_SHA_256); +#endif +#ifdef CALG_SHA_384 + CIPHEROPTION(CALG_SHA_384); +#endif +#ifdef CALG_SHA_512 + CIPHEROPTION(CALG_SHA_512); +#endif +#ifdef CALG_ECDH + CIPHEROPTION(CALG_ECDH); +#endif +#ifdef CALG_ECMQV + CIPHEROPTION(CALG_ECMQV); +#endif +#ifdef CALG_ECDSA + CIPHEROPTION(CALG_ECDSA); +#endif +#ifdef CALG_ECDH_EPHEM + CIPHEROPTION(CALG_ECDH_EPHEM); +#endif + return 0; +} + +static CURLcode +set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers) +{ + char *startCur = ciphers; + int algCount = 0; + static ALG_ID algIds[45]; /*There are 45 listed in the MS headers*/ + while(startCur && (0 != *startCur) && (algCount < 45)) { + long alg = strtol(startCur, 0, 0); + if(!alg) + alg = get_alg_id_by_name(startCur); + if(alg) + algIds[algCount++] = alg; + else + return CURLE_SSL_CIPHER; + startCur = strchr(startCur, ':'); + if(startCur) + startCur++; + } + schannel_cred->palgSupportedAlgs = algIds; + schannel_cred->cSupportedAlgs = algCount; + return CURLE_OK; +} + +#ifdef HAS_CLIENT_CERT_PATH +static CURLcode +get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path, + TCHAR **thumbprint) +{ + TCHAR *sep; + TCHAR *store_path_start; + size_t store_name_len; + + sep = _tcschr(path, TEXT('\\')); + if(sep == NULL) + return CURLE_SSL_CERTPROBLEM; + + store_name_len = sep - path; + + if(_tcsnccmp(path, TEXT("CurrentUser"), store_name_len) == 0) + *store_name = CERT_SYSTEM_STORE_CURRENT_USER; + else if(_tcsnccmp(path, TEXT("LocalMachine"), store_name_len) == 0) + *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE; + else if(_tcsnccmp(path, TEXT("CurrentService"), store_name_len) == 0) + *store_name = CERT_SYSTEM_STORE_CURRENT_SERVICE; + else if(_tcsnccmp(path, TEXT("Services"), store_name_len) == 0) + *store_name = CERT_SYSTEM_STORE_SERVICES; + else if(_tcsnccmp(path, TEXT("Users"), store_name_len) == 0) + *store_name = CERT_SYSTEM_STORE_USERS; + else if(_tcsnccmp(path, TEXT("CurrentUserGroupPolicy"), + store_name_len) == 0) + *store_name = CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY; + else if(_tcsnccmp(path, TEXT("LocalMachineGroupPolicy"), + store_name_len) == 0) + *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY; + else if(_tcsnccmp(path, TEXT("LocalMachineEnterprise"), + store_name_len) == 0) + *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE; + else + return CURLE_SSL_CERTPROBLEM; + + store_path_start = sep + 1; + + sep = _tcschr(store_path_start, TEXT('\\')); + if(sep == NULL) + return CURLE_SSL_CERTPROBLEM; + + *sep = TEXT('\0'); + *store_path = _tcsdup(store_path_start); + *sep = TEXT('\\'); + if(*store_path == NULL) + return CURLE_OUT_OF_MEMORY; + + *thumbprint = sep + 1; + if(_tcslen(*thumbprint) != CERT_THUMBPRINT_STR_LEN) + return CURLE_SSL_CERTPROBLEM; + + return CURLE_OK; +} +#endif + +static CURLcode +schannel_connect_step1(struct connectdata *conn, int sockindex) +{ + ssize_t written = -1; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + SecBuffer outbuf; + SecBufferDesc outbuf_desc; + SecBuffer inbuf; + SecBufferDesc inbuf_desc; +#ifdef HAS_ALPN + unsigned char alpn_buffer[128]; +#endif + SCHANNEL_CRED schannel_cred; + PCCERT_CONTEXT client_certs[1] = { NULL }; + SECURITY_STATUS sspi_status = SEC_E_OK; + struct curl_schannel_cred *old_cred = NULL; + struct in_addr addr; +#ifdef ENABLE_IPV6 + struct in6_addr addr6; +#endif + TCHAR *host_name; + CURLcode result; + char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + + DEBUGF(infof(data, + "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n", + hostname, conn->remote_port)); + + if(Curl_verify_windows_version(5, 1, PLATFORM_WINNT, + VERSION_LESS_THAN_EQUAL)) { + /* Schannel in Windows XP (OS version 5.1) uses legacy handshakes and + algorithms that may not be supported by all servers. */ + infof(data, "schannel: Windows version is old and may not be able to " + "connect to some servers due to lack of SNI, algorithms, etc.\n"); + } + +#ifdef HAS_ALPN + /* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above. + Also it doesn't seem to be supported for Wine, see curl bug #983. */ + BACKEND->use_alpn = conn->bits.tls_enable_alpn && + !GetProcAddress(GetModuleHandleA("ntdll"), + "wine_get_version") && + Curl_verify_windows_version(6, 3, PLATFORM_WINNT, + VERSION_GREATER_THAN_EQUAL); +#else + BACKEND->use_alpn = false; +#endif + +#ifdef _WIN32_WCE +#ifdef HAS_MANUAL_VERIFY_API + /* certificate validation on CE doesn't seem to work right; we'll + * do it following a more manual process. */ + BACKEND->use_manual_cred_validation = true; +#else +#error "compiler too old to support requisite manual cert verify for Win CE" +#endif +#else +#ifdef HAS_MANUAL_VERIFY_API + if(SSL_CONN_CONFIG(CAfile)) { + if(Curl_verify_windows_version(6, 1, PLATFORM_WINNT, + VERSION_GREATER_THAN_EQUAL)) { + BACKEND->use_manual_cred_validation = true; + } + else { + failf(data, "schannel: this version of Windows is too old to support " + "certificate verification via CA bundle file."); + return CURLE_SSL_CACERT_BADFILE; + } + } + else + BACKEND->use_manual_cred_validation = false; +#else + if(SSL_CONN_CONFIG(CAfile)) { + failf(data, "schannel: CA cert support not built in"); + return CURLE_NOT_BUILT_IN; + } +#endif +#endif + + BACKEND->cred = NULL; + + /* check for an existing re-usable credential handle */ + if(SSL_SET_OPTION(primary.sessionid)) { + Curl_ssl_sessionid_lock(conn); + if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, sockindex)) { + BACKEND->cred = old_cred; + DEBUGF(infof(data, "schannel: re-using existing credential handle\n")); + + /* increment the reference counter of the credential/session handle */ + BACKEND->cred->refcount++; + DEBUGF(infof(data, + "schannel: incremented credential handle refcount = %d\n", + BACKEND->cred->refcount)); + } + Curl_ssl_sessionid_unlock(conn); + } + + if(!BACKEND->cred) { + /* setup Schannel API options */ + memset(&schannel_cred, 0, sizeof(schannel_cred)); + schannel_cred.dwVersion = SCHANNEL_CRED_VERSION; + + if(conn->ssl_config.verifypeer) { +#ifdef HAS_MANUAL_VERIFY_API + if(BACKEND->use_manual_cred_validation) + schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION; + else +#endif + schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION; + + if(data->set.ssl.no_revoke) { + schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK | + SCH_CRED_IGNORE_REVOCATION_OFFLINE; + + DEBUGF(infof(data, "schannel: disabled server certificate revocation " + "checks\n")); + } + else { + schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN; + DEBUGF(infof(data, + "schannel: checking server certificate revocation\n")); + } + } + else { + schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION | + SCH_CRED_IGNORE_NO_REVOCATION_CHECK | + SCH_CRED_IGNORE_REVOCATION_OFFLINE; + DEBUGF(infof(data, + "schannel: disabled server cert revocation checks\n")); + } + + if(!conn->ssl_config.verifyhost) { + schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; + DEBUGF(infof(data, "schannel: verifyhost setting prevents Schannel from " + "comparing the supplied target name with the subject " + "names in server certificates.\n")); + } + + switch(conn->ssl_config.version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT | + SP_PROT_TLS1_1_CLIENT | + SP_PROT_TLS1_2_CLIENT; + break; + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: + { + result = set_ssl_version_min_max(&schannel_cred, conn); + if(result != CURLE_OK) + return result; + break; + } + case CURL_SSLVERSION_SSLv3: + schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT; + break; + case CURL_SSLVERSION_SSLv2: + schannel_cred.grbitEnabledProtocols = SP_PROT_SSL2_CLIENT; + break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + + if(SSL_CONN_CONFIG(cipher_list)) { + result = set_ssl_ciphers(&schannel_cred, SSL_CONN_CONFIG(cipher_list)); + if(CURLE_OK != result) { + failf(data, "Unable to set ciphers to passed via SSL_CONN_CONFIG"); + return result; + } + } + + +#ifdef HAS_CLIENT_CERT_PATH + /* client certificate */ + if(data->set.ssl.cert) { + DWORD cert_store_name; + TCHAR *cert_store_path; + TCHAR *cert_thumbprint_str; + CRYPT_HASH_BLOB cert_thumbprint; + BYTE cert_thumbprint_data[CERT_THUMBPRINT_DATA_LEN]; + HCERTSTORE cert_store; + + TCHAR *cert_path = Curl_convert_UTF8_to_tchar(data->set.ssl.cert); + if(!cert_path) + return CURLE_OUT_OF_MEMORY; + + result = get_cert_location(cert_path, &cert_store_name, + &cert_store_path, &cert_thumbprint_str); + if(result != CURLE_OK) { + failf(data, "schannel: Failed to get certificate location for %s", + cert_path); + Curl_unicodefree(cert_path); + return result; + } + + cert_store = + CertOpenStore(CURL_CERT_STORE_PROV_SYSTEM, 0, + (HCRYPTPROV)NULL, + CERT_STORE_OPEN_EXISTING_FLAG | cert_store_name, + cert_store_path); + if(!cert_store) { + failf(data, "schannel: Failed to open cert store %x %s, " + "last error is %x", + cert_store_name, cert_store_path, GetLastError()); + free(cert_store_path); + Curl_unicodefree(cert_path); + return CURLE_SSL_CERTPROBLEM; + } + free(cert_store_path); + + cert_thumbprint.pbData = cert_thumbprint_data; + cert_thumbprint.cbData = CERT_THUMBPRINT_DATA_LEN; + + if(!CryptStringToBinary(cert_thumbprint_str, CERT_THUMBPRINT_STR_LEN, + CRYPT_STRING_HEX, + cert_thumbprint_data, &cert_thumbprint.cbData, + NULL, NULL)) { + Curl_unicodefree(cert_path); + return CURLE_SSL_CERTPROBLEM; + } + + client_certs[0] = CertFindCertificateInStore( + cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, + CERT_FIND_HASH, &cert_thumbprint, NULL); + + Curl_unicodefree(cert_path); + + if(client_certs[0]) { + schannel_cred.cCreds = 1; + schannel_cred.paCred = client_certs; + } + else { + /* CRYPT_E_NOT_FOUND / E_INVALIDARG */ + return CURLE_SSL_CERTPROBLEM; + } + + CertCloseStore(cert_store, 0); + } +#else + if(data->set.ssl.cert) { + failf(data, "schannel: client cert support not built in"); + return CURLE_NOT_BUILT_IN; + } +#endif + + /* allocate memory for the re-usable credential handle */ + BACKEND->cred = (struct curl_schannel_cred *) + calloc(1, sizeof(struct curl_schannel_cred)); + if(!BACKEND->cred) { + failf(data, "schannel: unable to allocate memory"); + + if(client_certs[0]) + CertFreeCertificateContext(client_certs[0]); + + return CURLE_OUT_OF_MEMORY; + } + BACKEND->cred->refcount = 1; + + /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx + */ + sspi_status = + s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME, + SECPKG_CRED_OUTBOUND, NULL, + &schannel_cred, NULL, NULL, + &BACKEND->cred->cred_handle, + &BACKEND->cred->time_stamp); + + if(client_certs[0]) + CertFreeCertificateContext(client_certs[0]); + + if(sspi_status != SEC_E_OK) { + char buffer[STRERROR_LEN]; + failf(data, "schannel: AcquireCredentialsHandle failed: %s", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + Curl_safefree(BACKEND->cred); + switch(sspi_status) { + case SEC_E_INSUFFICIENT_MEMORY: + return CURLE_OUT_OF_MEMORY; + case SEC_E_NO_CREDENTIALS: + case SEC_E_SECPKG_NOT_FOUND: + case SEC_E_NOT_OWNER: + case SEC_E_UNKNOWN_CREDENTIALS: + case SEC_E_INTERNAL_ERROR: + default: + return CURLE_SSL_CONNECT_ERROR; + } + } + } + + /* Warn if SNI is disabled due to use of an IP address */ + if(Curl_inet_pton(AF_INET, hostname, &addr) +#ifdef ENABLE_IPV6 + || Curl_inet_pton(AF_INET6, hostname, &addr6) +#endif + ) { + infof(data, "schannel: using IP address, SNI is not supported by OS.\n"); + } + +#ifdef HAS_ALPN + if(BACKEND->use_alpn) { + int cur = 0; + int list_start_index = 0; + unsigned int *extension_len = NULL; + unsigned short* list_len = NULL; + + /* The first four bytes will be an unsigned int indicating number + of bytes of data in the rest of the the buffer. */ + extension_len = (unsigned int *)(&alpn_buffer[cur]); + cur += sizeof(unsigned int); + + /* The next four bytes are an indicator that this buffer will contain + ALPN data, as opposed to NPN, for example. */ + *(unsigned int *)&alpn_buffer[cur] = + SecApplicationProtocolNegotiationExt_ALPN; + cur += sizeof(unsigned int); + + /* The next two bytes will be an unsigned short indicating the number + of bytes used to list the preferred protocols. */ + list_len = (unsigned short*)(&alpn_buffer[cur]); + cur += sizeof(unsigned short); + + list_start_index = cur; + +#ifdef USE_NGHTTP2 + if(data->set.httpversion >= CURL_HTTP_VERSION_2) { + memcpy(&alpn_buffer[cur], NGHTTP2_PROTO_ALPN, NGHTTP2_PROTO_ALPN_LEN); + cur += NGHTTP2_PROTO_ALPN_LEN; + infof(data, "schannel: ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + } +#endif + + alpn_buffer[cur++] = ALPN_HTTP_1_1_LENGTH; + memcpy(&alpn_buffer[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH); + cur += ALPN_HTTP_1_1_LENGTH; + infof(data, "schannel: ALPN, offering %s\n", ALPN_HTTP_1_1); + + *list_len = curlx_uitous(cur - list_start_index); + *extension_len = *list_len + sizeof(unsigned int) + sizeof(unsigned short); + + InitSecBuffer(&inbuf, SECBUFFER_APPLICATION_PROTOCOLS, alpn_buffer, cur); + InitSecBufferDesc(&inbuf_desc, &inbuf, 1); + } + else { + InitSecBuffer(&inbuf, SECBUFFER_EMPTY, NULL, 0); + InitSecBufferDesc(&inbuf_desc, &inbuf, 1); + } +#else /* HAS_ALPN */ + InitSecBuffer(&inbuf, SECBUFFER_EMPTY, NULL, 0); + InitSecBufferDesc(&inbuf_desc, &inbuf, 1); +#endif + + /* setup output buffer */ + InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0); + InitSecBufferDesc(&outbuf_desc, &outbuf, 1); + + /* setup request flags */ + BACKEND->req_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | + ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY | + ISC_REQ_STREAM; + + /* allocate memory for the security context handle */ + BACKEND->ctxt = (struct curl_schannel_ctxt *) + calloc(1, sizeof(struct curl_schannel_ctxt)); + if(!BACKEND->ctxt) { + failf(data, "schannel: unable to allocate memory"); + return CURLE_OUT_OF_MEMORY; + } + + host_name = Curl_convert_UTF8_to_tchar(hostname); + if(!host_name) + return CURLE_OUT_OF_MEMORY; + + /* Schannel InitializeSecurityContext: + https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx + + At the moment we don't pass inbuf unless we're using ALPN since we only + use it for that, and Wine (for which we currently disable ALPN) is giving + us problems with inbuf regardless. https://github.com/curl/curl/issues/983 + */ + sspi_status = s_pSecFn->InitializeSecurityContext( + &BACKEND->cred->cred_handle, NULL, host_name, BACKEND->req_flags, 0, 0, + (BACKEND->use_alpn ? &inbuf_desc : NULL), + 0, &BACKEND->ctxt->ctxt_handle, + &outbuf_desc, &BACKEND->ret_flags, &BACKEND->ctxt->time_stamp); + + Curl_unicodefree(host_name); + + if(sspi_status != SEC_I_CONTINUE_NEEDED) { + char buffer[STRERROR_LEN]; + Curl_safefree(BACKEND->ctxt); + switch(sspi_status) { + case SEC_E_INSUFFICIENT_MEMORY: + failf(data, "schannel: initial InitializeSecurityContext failed: %s", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + return CURLE_OUT_OF_MEMORY; + case SEC_E_WRONG_PRINCIPAL: + failf(data, "schannel: SNI or certificate check failed: %s", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + return CURLE_PEER_FAILED_VERIFICATION; + /* + case SEC_E_INVALID_HANDLE: + case SEC_E_INVALID_TOKEN: + case SEC_E_LOGON_DENIED: + case SEC_E_TARGET_UNKNOWN: + case SEC_E_NO_AUTHENTICATING_AUTHORITY: + case SEC_E_INTERNAL_ERROR: + case SEC_E_NO_CREDENTIALS: + case SEC_E_UNSUPPORTED_FUNCTION: + case SEC_E_APPLICATION_PROTOCOL_MISMATCH: + */ + default: + failf(data, "schannel: initial InitializeSecurityContext failed: %s", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + return CURLE_SSL_CONNECT_ERROR; + } + } + + DEBUGF(infof(data, "schannel: sending initial handshake data: " + "sending %lu bytes...\n", outbuf.cbBuffer)); + + /* send initial handshake data which is now stored in output buffer */ + result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer, + outbuf.cbBuffer, &written); + s_pSecFn->FreeContextBuffer(outbuf.pvBuffer); + if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) { + failf(data, "schannel: failed to send initial handshake data: " + "sent %zd of %lu bytes", written, outbuf.cbBuffer); + return CURLE_SSL_CONNECT_ERROR; + } + + DEBUGF(infof(data, "schannel: sent initial handshake data: " + "sent %zd bytes\n", written)); + + BACKEND->recv_unrecoverable_err = CURLE_OK; + BACKEND->recv_sspi_close_notify = false; + BACKEND->recv_connection_closed = false; + BACKEND->encdata_is_incomplete = false; + + /* continue to second handshake step */ + connssl->connecting_state = ssl_connect_2; + + return CURLE_OK; +} + +static CURLcode +schannel_connect_step2(struct connectdata *conn, int sockindex) +{ + int i; + ssize_t nread = -1, written = -1; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + unsigned char *reallocated_buffer; + SecBuffer outbuf[3]; + SecBufferDesc outbuf_desc; + SecBuffer inbuf[2]; + SecBufferDesc inbuf_desc; + SECURITY_STATUS sspi_status = SEC_E_OK; + CURLcode result; + bool doread; + char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const char *pubkey_ptr; + + doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE; + + DEBUGF(infof(data, + "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n", + hostname, conn->remote_port)); + + if(!BACKEND->cred || !BACKEND->ctxt) + return CURLE_SSL_CONNECT_ERROR; + + /* buffer to store previously received and decrypted data */ + if(BACKEND->decdata_buffer == NULL) { + BACKEND->decdata_offset = 0; + BACKEND->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; + BACKEND->decdata_buffer = malloc(BACKEND->decdata_length); + if(BACKEND->decdata_buffer == NULL) { + failf(data, "schannel: unable to allocate memory"); + return CURLE_OUT_OF_MEMORY; + } + } + + /* buffer to store previously received and encrypted data */ + if(BACKEND->encdata_buffer == NULL) { + BACKEND->encdata_is_incomplete = false; + BACKEND->encdata_offset = 0; + BACKEND->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; + BACKEND->encdata_buffer = malloc(BACKEND->encdata_length); + if(BACKEND->encdata_buffer == NULL) { + failf(data, "schannel: unable to allocate memory"); + return CURLE_OUT_OF_MEMORY; + } + } + + /* if we need a bigger buffer to read a full message, increase buffer now */ + if(BACKEND->encdata_length - BACKEND->encdata_offset < + CURL_SCHANNEL_BUFFER_FREE_SIZE) { + /* increase internal encrypted data buffer */ + size_t reallocated_length = BACKEND->encdata_offset + + CURL_SCHANNEL_BUFFER_FREE_SIZE; + reallocated_buffer = realloc(BACKEND->encdata_buffer, + reallocated_length); + + if(reallocated_buffer == NULL) { + failf(data, "schannel: unable to re-allocate memory"); + return CURLE_OUT_OF_MEMORY; + } + else { + BACKEND->encdata_buffer = reallocated_buffer; + BACKEND->encdata_length = reallocated_length; + } + } + + for(;;) { + TCHAR *host_name; + if(doread) { + /* read encrypted handshake data from socket */ + result = Curl_read_plain(conn->sock[sockindex], + (char *) (BACKEND->encdata_buffer + + BACKEND->encdata_offset), + BACKEND->encdata_length - + BACKEND->encdata_offset, + &nread); + if(result == CURLE_AGAIN) { + if(connssl->connecting_state != ssl_connect_2_writing) + connssl->connecting_state = ssl_connect_2_reading; + DEBUGF(infof(data, "schannel: failed to receive handshake, " + "need more data\n")); + return CURLE_OK; + } + else if((result != CURLE_OK) || (nread == 0)) { + failf(data, "schannel: failed to receive handshake, " + "SSL/TLS connection failed"); + return CURLE_SSL_CONNECT_ERROR; + } + + /* increase encrypted data buffer offset */ + BACKEND->encdata_offset += nread; + BACKEND->encdata_is_incomplete = false; + DEBUGF(infof(data, "schannel: encrypted data got %zd\n", nread)); + } + + DEBUGF(infof(data, + "schannel: encrypted data buffer: offset %zu length %zu\n", + BACKEND->encdata_offset, BACKEND->encdata_length)); + + /* setup input buffers */ + InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(BACKEND->encdata_offset), + curlx_uztoul(BACKEND->encdata_offset)); + InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0); + InitSecBufferDesc(&inbuf_desc, inbuf, 2); + + /* setup output buffers */ + InitSecBuffer(&outbuf[0], SECBUFFER_TOKEN, NULL, 0); + InitSecBuffer(&outbuf[1], SECBUFFER_ALERT, NULL, 0); + InitSecBuffer(&outbuf[2], SECBUFFER_EMPTY, NULL, 0); + InitSecBufferDesc(&outbuf_desc, outbuf, 3); + + if(inbuf[0].pvBuffer == NULL) { + failf(data, "schannel: unable to allocate memory"); + return CURLE_OUT_OF_MEMORY; + } + + /* copy received handshake data into input buffer */ + memcpy(inbuf[0].pvBuffer, BACKEND->encdata_buffer, + BACKEND->encdata_offset); + + host_name = Curl_convert_UTF8_to_tchar(hostname); + if(!host_name) + return CURLE_OUT_OF_MEMORY; + + /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx + */ + sspi_status = s_pSecFn->InitializeSecurityContext( + &BACKEND->cred->cred_handle, &BACKEND->ctxt->ctxt_handle, + host_name, BACKEND->req_flags, 0, 0, &inbuf_desc, 0, NULL, + &outbuf_desc, &BACKEND->ret_flags, &BACKEND->ctxt->time_stamp); + + Curl_unicodefree(host_name); + + /* free buffer for received handshake data */ + Curl_safefree(inbuf[0].pvBuffer); + + /* check if the handshake was incomplete */ + if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) { + BACKEND->encdata_is_incomplete = true; + connssl->connecting_state = ssl_connect_2_reading; + DEBUGF(infof(data, + "schannel: received incomplete message, need more data\n")); + return CURLE_OK; + } + + /* If the server has requested a client certificate, attempt to continue + the handshake without one. This will allow connections to servers which + request a client certificate but do not require it. */ + if(sspi_status == SEC_I_INCOMPLETE_CREDENTIALS && + !(BACKEND->req_flags & ISC_REQ_USE_SUPPLIED_CREDS)) { + BACKEND->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS; + connssl->connecting_state = ssl_connect_2_writing; + DEBUGF(infof(data, + "schannel: a client certificate has been requested\n")); + return CURLE_OK; + } + + /* check if the handshake needs to be continued */ + if(sspi_status == SEC_I_CONTINUE_NEEDED || sspi_status == SEC_E_OK) { + for(i = 0; i < 3; i++) { + /* search for handshake tokens that need to be send */ + if(outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) { + DEBUGF(infof(data, "schannel: sending next handshake data: " + "sending %lu bytes...\n", outbuf[i].cbBuffer)); + + /* send handshake token to server */ + result = Curl_write_plain(conn, conn->sock[sockindex], + outbuf[i].pvBuffer, outbuf[i].cbBuffer, + &written); + if((result != CURLE_OK) || + (outbuf[i].cbBuffer != (size_t) written)) { + failf(data, "schannel: failed to send next handshake data: " + "sent %zd of %lu bytes", written, outbuf[i].cbBuffer); + return CURLE_SSL_CONNECT_ERROR; + } + } + + /* free obsolete buffer */ + if(outbuf[i].pvBuffer != NULL) { + s_pSecFn->FreeContextBuffer(outbuf[i].pvBuffer); + } + } + } + else { + char buffer[STRERROR_LEN]; + switch(sspi_status) { + case SEC_E_INSUFFICIENT_MEMORY: + failf(data, "schannel: next InitializeSecurityContext failed: %s", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + return CURLE_OUT_OF_MEMORY; + case SEC_E_WRONG_PRINCIPAL: + failf(data, "schannel: SNI or certificate check failed: %s", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + return CURLE_PEER_FAILED_VERIFICATION; + /* + case SEC_E_INVALID_HANDLE: + case SEC_E_INVALID_TOKEN: + case SEC_E_LOGON_DENIED: + case SEC_E_TARGET_UNKNOWN: + case SEC_E_NO_AUTHENTICATING_AUTHORITY: + case SEC_E_INTERNAL_ERROR: + case SEC_E_NO_CREDENTIALS: + case SEC_E_UNSUPPORTED_FUNCTION: + case SEC_E_APPLICATION_PROTOCOL_MISMATCH: + */ + default: + failf(data, "schannel: next InitializeSecurityContext failed: %s", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + return CURLE_SSL_CONNECT_ERROR; + } + } + + /* check if there was additional remaining encrypted data */ + if(inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) { + DEBUGF(infof(data, "schannel: encrypted data length: %lu\n", + inbuf[1].cbBuffer)); + /* + There are two cases where we could be getting extra data here: + 1) If we're renegotiating a connection and the handshake is already + complete (from the server perspective), it can encrypted app data + (not handshake data) in an extra buffer at this point. + 2) (sspi_status == SEC_I_CONTINUE_NEEDED) We are negotiating a + connection and this extra data is part of the handshake. + We should process the data immediately; waiting for the socket to + be ready may fail since the server is done sending handshake data. + */ + /* check if the remaining data is less than the total amount + and therefore begins after the already processed data */ + if(BACKEND->encdata_offset > inbuf[1].cbBuffer) { + memmove(BACKEND->encdata_buffer, + (BACKEND->encdata_buffer + BACKEND->encdata_offset) - + inbuf[1].cbBuffer, inbuf[1].cbBuffer); + BACKEND->encdata_offset = inbuf[1].cbBuffer; + if(sspi_status == SEC_I_CONTINUE_NEEDED) { + doread = FALSE; + continue; + } + } + } + else { + BACKEND->encdata_offset = 0; + } + break; + } + + /* check if the handshake needs to be continued */ + if(sspi_status == SEC_I_CONTINUE_NEEDED) { + connssl->connecting_state = ssl_connect_2_reading; + return CURLE_OK; + } + + /* check if the handshake is complete */ + if(sspi_status == SEC_E_OK) { + connssl->connecting_state = ssl_connect_3; + DEBUGF(infof(data, "schannel: SSL/TLS handshake complete\n")); + } + + pubkey_ptr = SSL_IS_PROXY() ? + data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + if(pubkey_ptr) { + result = pkp_pin_peer_pubkey(conn, sockindex, pubkey_ptr); + if(result) { + failf(data, "SSL: public key does not match pinned public key!"); + return result; + } + } + +#ifdef HAS_MANUAL_VERIFY_API + if(conn->ssl_config.verifypeer && BACKEND->use_manual_cred_validation) { + return Curl_verify_certificate(conn, sockindex); + } +#endif + + return CURLE_OK; +} + +static bool +valid_cert_encoding(const CERT_CONTEXT *cert_context) +{ + return (cert_context != NULL) && + ((cert_context->dwCertEncodingType & X509_ASN_ENCODING) != 0) && + (cert_context->pbCertEncoded != NULL) && + (cert_context->cbCertEncoded > 0); +} + +typedef bool(*Read_crt_func)(const CERT_CONTEXT *ccert_context, void *arg); + +static void +traverse_cert_store(const CERT_CONTEXT *context, Read_crt_func func, + void *arg) +{ + const CERT_CONTEXT *current_context = NULL; + bool should_continue = true; + while(should_continue && + (current_context = CertEnumCertificatesInStore( + context->hCertStore, + current_context)) != NULL) + should_continue = func(current_context, arg); + + if(current_context) + CertFreeCertificateContext(current_context); +} + +static bool +cert_counter_callback(const CERT_CONTEXT *ccert_context, void *certs_count) +{ + if(valid_cert_encoding(ccert_context)) + (*(int *)certs_count)++; + return true; +} + +struct Adder_args +{ + struct connectdata *conn; + CURLcode result; + int idx; +}; + +static bool +add_cert_to_certinfo(const CERT_CONTEXT *ccert_context, void *raw_arg) +{ + struct Adder_args *args = (struct Adder_args*)raw_arg; + args->result = CURLE_OK; + if(valid_cert_encoding(ccert_context)) { + const char *beg = (const char *) ccert_context->pbCertEncoded; + const char *end = beg + ccert_context->cbCertEncoded; + args->result = Curl_extract_certinfo(args->conn, (args->idx)++, beg, end); + } + return args->result == CURLE_OK; +} + +static CURLcode +schannel_connect_step3(struct connectdata *conn, int sockindex) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + SECURITY_STATUS sspi_status = SEC_E_OK; + CERT_CONTEXT *ccert_context = NULL; +#ifdef DEBUGBUILD + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; +#endif +#ifdef HAS_ALPN + SecPkgContext_ApplicationProtocol alpn_result; +#endif + + DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); + + DEBUGF(infof(data, + "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n", + hostname, conn->remote_port)); + + if(!BACKEND->cred) + return CURLE_SSL_CONNECT_ERROR; + + /* check if the required context attributes are met */ + if(BACKEND->ret_flags != BACKEND->req_flags) { + if(!(BACKEND->ret_flags & ISC_RET_SEQUENCE_DETECT)) + failf(data, "schannel: failed to setup sequence detection"); + if(!(BACKEND->ret_flags & ISC_RET_REPLAY_DETECT)) + failf(data, "schannel: failed to setup replay detection"); + if(!(BACKEND->ret_flags & ISC_RET_CONFIDENTIALITY)) + failf(data, "schannel: failed to setup confidentiality"); + if(!(BACKEND->ret_flags & ISC_RET_ALLOCATED_MEMORY)) + failf(data, "schannel: failed to setup memory allocation"); + if(!(BACKEND->ret_flags & ISC_RET_STREAM)) + failf(data, "schannel: failed to setup stream orientation"); + return CURLE_SSL_CONNECT_ERROR; + } + +#ifdef HAS_ALPN + if(BACKEND->use_alpn) { + sspi_status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, + SECPKG_ATTR_APPLICATION_PROTOCOL, &alpn_result); + + if(sspi_status != SEC_E_OK) { + failf(data, "schannel: failed to retrieve ALPN result"); + return CURLE_SSL_CONNECT_ERROR; + } + + if(alpn_result.ProtoNegoStatus == + SecApplicationProtocolNegotiationStatus_Success) { + + infof(data, "schannel: ALPN, server accepted to use %.*s\n", + alpn_result.ProtocolIdSize, alpn_result.ProtocolId); + +#ifdef USE_NGHTTP2 + if(alpn_result.ProtocolIdSize == NGHTTP2_PROTO_VERSION_ID_LEN && + !memcmp(NGHTTP2_PROTO_VERSION_ID, alpn_result.ProtocolId, + NGHTTP2_PROTO_VERSION_ID_LEN)) { + conn->negnpn = CURL_HTTP_VERSION_2; + } + else +#endif + if(alpn_result.ProtocolIdSize == ALPN_HTTP_1_1_LENGTH && + !memcmp(ALPN_HTTP_1_1, alpn_result.ProtocolId, + ALPN_HTTP_1_1_LENGTH)) { + conn->negnpn = CURL_HTTP_VERSION_1_1; + } + } + else + infof(data, "ALPN, server did not agree to a protocol\n"); + Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); + } +#endif + + /* save the current session data for possible re-use */ + if(SSL_SET_OPTION(primary.sessionid)) { + bool incache; + struct curl_schannel_cred *old_cred = NULL; + + Curl_ssl_sessionid_lock(conn); + incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, + sockindex)); + if(incache) { + if(old_cred != BACKEND->cred) { + DEBUGF(infof(data, + "schannel: old credential handle is stale, removing\n")); + /* we're not taking old_cred ownership here, no refcount++ is needed */ + Curl_ssl_delsessionid(conn, (void *)old_cred); + incache = FALSE; + } + } + if(!incache) { + result = Curl_ssl_addsessionid(conn, (void *)BACKEND->cred, + sizeof(struct curl_schannel_cred), + sockindex); + if(result) { + Curl_ssl_sessionid_unlock(conn); + failf(data, "schannel: failed to store credential handle"); + return result; + } + else { + /* this cred session is now also referenced by sessionid cache */ + BACKEND->cred->refcount++; + DEBUGF(infof(data, + "schannel: stored credential handle in session cache\n")); + } + } + Curl_ssl_sessionid_unlock(conn); + } + + if(data->set.ssl.certinfo) { + int certs_count = 0; + sspi_status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, + SECPKG_ATTR_REMOTE_CERT_CONTEXT, &ccert_context); + + if((sspi_status != SEC_E_OK) || (ccert_context == NULL)) { + failf(data, "schannel: failed to retrieve remote cert context"); + return CURLE_PEER_FAILED_VERIFICATION; + } + + traverse_cert_store(ccert_context, cert_counter_callback, &certs_count); + + result = Curl_ssl_init_certinfo(data, certs_count); + if(!result) { + struct Adder_args args; + args.conn = conn; + args.idx = 0; + traverse_cert_store(ccert_context, add_cert_to_certinfo, &args); + result = args.result; + } + CertFreeCertificateContext(ccert_context); + if(result) + return result; + } + + connssl->connecting_state = ssl_connect_done; + + return CURLE_OK; +} + +static CURLcode +schannel_connect_common(struct connectdata *conn, int sockindex, + bool nonblocking, bool *done) +{ + CURLcode result; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + time_t timeout_ms; + int what; + + /* check if the connection has already been established */ + if(ssl_connection_complete == connssl->state) { + *done = TRUE; + return CURLE_OK; + } + + if(ssl_connect_1 == connssl->connecting_state) { + /* check out how much more time we're allowed */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL/TLS connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + result = schannel_connect_step1(conn, sockindex); + if(result) + return result; + } + + while(ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state) { + + /* check out how much more time we're allowed */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL/TLS connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* if ssl is expecting something, check if it's available. */ + if(connssl->connecting_state == ssl_connect_2_reading + || connssl->connecting_state == ssl_connect_2_writing) { + + curl_socket_t writefd = ssl_connect_2_writing == + connssl->connecting_state ? sockfd : CURL_SOCKET_BAD; + curl_socket_t readfd = ssl_connect_2_reading == + connssl->connecting_state ? sockfd : CURL_SOCKET_BAD; + + what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, + nonblocking ? 0 : timeout_ms); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL/TLS socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + else if(0 == what) { + if(nonblocking) { + *done = FALSE; + return CURLE_OK; + } + else { + /* timeout */ + failf(data, "SSL/TLS connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + } + /* socket is readable or writable */ + } + + /* Run transaction, and return to the caller if it failed or if + * this connection is part of a multi handle and this loop would + * execute again. This permits the owner of a multi handle to + * abort a connection attempt before step2 has completed while + * ensuring that a client using select() or epoll() will always + * have a valid fdset to wait on. + */ + result = schannel_connect_step2(conn, sockindex); + if(result || (nonblocking && + (ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state))) + return result; + + } /* repeat step2 until all transactions are done. */ + + if(ssl_connect_3 == connssl->connecting_state) { + result = schannel_connect_step3(conn, sockindex); + if(result) + return result; + } + + if(ssl_connect_done == connssl->connecting_state) { + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = schannel_recv; + conn->send[sockindex] = schannel_send; + +#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS + /* When SSPI is used in combination with Schannel + * we need the Schannel context to create the Schannel + * binding to pass the IIS extended protection checks. + * Available on Windows 7 or later. + */ + conn->sslContext = &BACKEND->ctxt->ctxt_handle; +#endif + + *done = TRUE; + } + else + *done = FALSE; + + /* reset our connection state machine */ + connssl->connecting_state = ssl_connect_1; + + return CURLE_OK; +} + +static ssize_t +schannel_send(struct connectdata *conn, int sockindex, + const void *buf, size_t len, CURLcode *err) +{ + ssize_t written = -1; + size_t data_len = 0; + unsigned char *data = NULL; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + SecBuffer outbuf[4]; + SecBufferDesc outbuf_desc; + SECURITY_STATUS sspi_status = SEC_E_OK; + CURLcode result; + + /* check if the maximum stream sizes were queried */ + if(BACKEND->stream_sizes.cbMaximumMessage == 0) { + sspi_status = s_pSecFn->QueryContextAttributes( + &BACKEND->ctxt->ctxt_handle, + SECPKG_ATTR_STREAM_SIZES, + &BACKEND->stream_sizes); + if(sspi_status != SEC_E_OK) { + *err = CURLE_SEND_ERROR; + return -1; + } + } + + /* check if the buffer is longer than the maximum message length */ + if(len > BACKEND->stream_sizes.cbMaximumMessage) { + len = BACKEND->stream_sizes.cbMaximumMessage; + } + + /* calculate the complete message length and allocate a buffer for it */ + data_len = BACKEND->stream_sizes.cbHeader + len + + BACKEND->stream_sizes.cbTrailer; + data = (unsigned char *) malloc(data_len); + if(data == NULL) { + *err = CURLE_OUT_OF_MEMORY; + return -1; + } + + /* setup output buffers (header, data, trailer, empty) */ + InitSecBuffer(&outbuf[0], SECBUFFER_STREAM_HEADER, + data, BACKEND->stream_sizes.cbHeader); + InitSecBuffer(&outbuf[1], SECBUFFER_DATA, + data + BACKEND->stream_sizes.cbHeader, curlx_uztoul(len)); + InitSecBuffer(&outbuf[2], SECBUFFER_STREAM_TRAILER, + data + BACKEND->stream_sizes.cbHeader + len, + BACKEND->stream_sizes.cbTrailer); + InitSecBuffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0); + InitSecBufferDesc(&outbuf_desc, outbuf, 4); + + /* copy data into output buffer */ + memcpy(outbuf[1].pvBuffer, buf, len); + + /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375390.aspx */ + sspi_status = s_pSecFn->EncryptMessage(&BACKEND->ctxt->ctxt_handle, 0, + &outbuf_desc, 0); + + /* check if the message was encrypted */ + if(sspi_status == SEC_E_OK) { + written = 0; + + /* send the encrypted message including header, data and trailer */ + len = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer; + + /* + It's important to send the full message which includes the header, + encrypted payload, and trailer. Until the client receives all the + data a coherent message has not been delivered and the client + can't read any of it. + + If we wanted to buffer the unwritten encrypted bytes, we would + tell the client that all data it has requested to be sent has been + sent. The unwritten encrypted bytes would be the first bytes to + send on the next invocation. + Here's the catch with this - if we tell the client that all the + bytes have been sent, will the client call this method again to + send the buffered data? Looking at who calls this function, it + seems the answer is NO. + */ + + /* send entire message or fail */ + while(len > (size_t)written) { + ssize_t this_write; + time_t timeleft; + int what; + + this_write = 0; + + timeleft = Curl_timeleft(conn->data, NULL, FALSE); + if(timeleft < 0) { + /* we already got the timeout */ + failf(conn->data, "schannel: timed out sending data " + "(bytes sent: %zd)", written); + *err = CURLE_OPERATION_TIMEDOUT; + written = -1; + break; + } + + what = SOCKET_WRITABLE(conn->sock[sockindex], timeleft); + if(what < 0) { + /* fatal error */ + failf(conn->data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + *err = CURLE_SEND_ERROR; + written = -1; + break; + } + else if(0 == what) { + failf(conn->data, "schannel: timed out sending data " + "(bytes sent: %zd)", written); + *err = CURLE_OPERATION_TIMEDOUT; + written = -1; + break; + } + /* socket is writable */ + + result = Curl_write_plain(conn, conn->sock[sockindex], data + written, + len - written, &this_write); + if(result == CURLE_AGAIN) + continue; + else if(result != CURLE_OK) { + *err = result; + written = -1; + break; + } + + written += this_write; + } + } + else if(sspi_status == SEC_E_INSUFFICIENT_MEMORY) { + *err = CURLE_OUT_OF_MEMORY; + } + else{ + *err = CURLE_SEND_ERROR; + } + + Curl_safefree(data); + + if(len == (size_t)written) + /* Encrypted message including header, data and trailer entirely sent. + The return value is the number of unencrypted bytes that were sent. */ + written = outbuf[1].cbBuffer; + + return written; +} + +static ssize_t +schannel_recv(struct connectdata *conn, int sockindex, + char *buf, size_t len, CURLcode *err) +{ + size_t size = 0; + ssize_t nread = -1; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + unsigned char *reallocated_buffer; + size_t reallocated_length; + bool done = FALSE; + SecBuffer inbuf[4]; + SecBufferDesc inbuf_desc; + SECURITY_STATUS sspi_status = SEC_E_OK; + /* we want the length of the encrypted buffer to be at least large enough + that it can hold all the bytes requested and some TLS record overhead. */ + size_t min_encdata_length = len + CURL_SCHANNEL_BUFFER_FREE_SIZE; + + /**************************************************************************** + * Don't return or set BACKEND->recv_unrecoverable_err unless in the cleanup. + * The pattern for return error is set *err, optional infof, goto cleanup. + * + * Our priority is to always return as much decrypted data to the caller as + * possible, even if an error occurs. The state of the decrypted buffer must + * always be valid. Transfer of decrypted data to the caller's buffer is + * handled in the cleanup. + */ + + DEBUGF(infof(data, "schannel: client wants to read %zu bytes\n", len)); + *err = CURLE_OK; + + if(len && len <= BACKEND->decdata_offset) { + infof(data, "schannel: enough decrypted data is already available\n"); + goto cleanup; + } + else if(BACKEND->recv_unrecoverable_err) { + *err = BACKEND->recv_unrecoverable_err; + infof(data, "schannel: an unrecoverable error occurred in a prior call\n"); + goto cleanup; + } + else if(BACKEND->recv_sspi_close_notify) { + /* once a server has indicated shutdown there is no more encrypted data */ + infof(data, "schannel: server indicated shutdown in a prior call\n"); + goto cleanup; + } + else if(!len) { + /* It's debatable what to return when !len. Regardless we can't return + immediately because there may be data to decrypt (in the case we want to + decrypt all encrypted cached data) so handle !len later in cleanup. + */ + ; /* do nothing */ + } + else if(!BACKEND->recv_connection_closed) { + /* increase enc buffer in order to fit the requested amount of data */ + size = BACKEND->encdata_length - BACKEND->encdata_offset; + if(size < CURL_SCHANNEL_BUFFER_FREE_SIZE || + BACKEND->encdata_length < min_encdata_length) { + reallocated_length = BACKEND->encdata_offset + + CURL_SCHANNEL_BUFFER_FREE_SIZE; + if(reallocated_length < min_encdata_length) { + reallocated_length = min_encdata_length; + } + reallocated_buffer = realloc(BACKEND->encdata_buffer, + reallocated_length); + if(reallocated_buffer == NULL) { + *err = CURLE_OUT_OF_MEMORY; + failf(data, "schannel: unable to re-allocate memory"); + goto cleanup; + } + + BACKEND->encdata_buffer = reallocated_buffer; + BACKEND->encdata_length = reallocated_length; + size = BACKEND->encdata_length - BACKEND->encdata_offset; + DEBUGF(infof(data, "schannel: encdata_buffer resized %zu\n", + BACKEND->encdata_length)); + } + + DEBUGF(infof(data, + "schannel: encrypted data buffer: offset %zu length %zu\n", + BACKEND->encdata_offset, BACKEND->encdata_length)); + + /* read encrypted data from socket */ + *err = Curl_read_plain(conn->sock[sockindex], + (char *)(BACKEND->encdata_buffer + + BACKEND->encdata_offset), + size, &nread); + if(*err) { + nread = -1; + if(*err == CURLE_AGAIN) + DEBUGF(infof(data, + "schannel: Curl_read_plain returned CURLE_AGAIN\n")); + else if(*err == CURLE_RECV_ERROR) + infof(data, "schannel: Curl_read_plain returned CURLE_RECV_ERROR\n"); + else + infof(data, "schannel: Curl_read_plain returned error %d\n", *err); + } + else if(nread == 0) { + BACKEND->recv_connection_closed = true; + DEBUGF(infof(data, "schannel: server closed the connection\n")); + } + else if(nread > 0) { + BACKEND->encdata_offset += (size_t)nread; + BACKEND->encdata_is_incomplete = false; + DEBUGF(infof(data, "schannel: encrypted data got %zd\n", nread)); + } + } + + DEBUGF(infof(data, + "schannel: encrypted data buffer: offset %zu length %zu\n", + BACKEND->encdata_offset, BACKEND->encdata_length)); + + /* decrypt loop */ + while(BACKEND->encdata_offset > 0 && sspi_status == SEC_E_OK && + (!len || BACKEND->decdata_offset < len || + BACKEND->recv_connection_closed)) { + /* prepare data buffer for DecryptMessage call */ + InitSecBuffer(&inbuf[0], SECBUFFER_DATA, BACKEND->encdata_buffer, + curlx_uztoul(BACKEND->encdata_offset)); + + /* we need 3 more empty input buffers for possible output */ + InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0); + InitSecBuffer(&inbuf[2], SECBUFFER_EMPTY, NULL, 0); + InitSecBuffer(&inbuf[3], SECBUFFER_EMPTY, NULL, 0); + InitSecBufferDesc(&inbuf_desc, inbuf, 4); + + /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375348.aspx + */ + sspi_status = s_pSecFn->DecryptMessage(&BACKEND->ctxt->ctxt_handle, + &inbuf_desc, 0, NULL); + + /* check if everything went fine (server may want to renegotiate + or shutdown the connection context) */ + if(sspi_status == SEC_E_OK || sspi_status == SEC_I_RENEGOTIATE || + sspi_status == SEC_I_CONTEXT_EXPIRED) { + /* check for successfully decrypted data, even before actual + renegotiation or shutdown of the connection context */ + if(inbuf[1].BufferType == SECBUFFER_DATA) { + DEBUGF(infof(data, "schannel: decrypted data length: %lu\n", + inbuf[1].cbBuffer)); + + /* increase buffer in order to fit the received amount of data */ + size = inbuf[1].cbBuffer > CURL_SCHANNEL_BUFFER_FREE_SIZE ? + inbuf[1].cbBuffer : CURL_SCHANNEL_BUFFER_FREE_SIZE; + if(BACKEND->decdata_length - BACKEND->decdata_offset < size || + BACKEND->decdata_length < len) { + /* increase internal decrypted data buffer */ + reallocated_length = BACKEND->decdata_offset + size; + /* make sure that the requested amount of data fits */ + if(reallocated_length < len) { + reallocated_length = len; + } + reallocated_buffer = realloc(BACKEND->decdata_buffer, + reallocated_length); + if(reallocated_buffer == NULL) { + *err = CURLE_OUT_OF_MEMORY; + failf(data, "schannel: unable to re-allocate memory"); + goto cleanup; + } + BACKEND->decdata_buffer = reallocated_buffer; + BACKEND->decdata_length = reallocated_length; + } + + /* copy decrypted data to internal buffer */ + size = inbuf[1].cbBuffer; + if(size) { + memcpy(BACKEND->decdata_buffer + BACKEND->decdata_offset, + inbuf[1].pvBuffer, size); + BACKEND->decdata_offset += size; + } + + DEBUGF(infof(data, "schannel: decrypted data added: %zu\n", size)); + DEBUGF(infof(data, + "schannel: decrypted cached: offset %zu length %zu\n", + BACKEND->decdata_offset, BACKEND->decdata_length)); + } + + /* check for remaining encrypted data */ + if(inbuf[3].BufferType == SECBUFFER_EXTRA && inbuf[3].cbBuffer > 0) { + DEBUGF(infof(data, "schannel: encrypted data length: %lu\n", + inbuf[3].cbBuffer)); + + /* check if the remaining data is less than the total amount + * and therefore begins after the already processed data + */ + if(BACKEND->encdata_offset > inbuf[3].cbBuffer) { + /* move remaining encrypted data forward to the beginning of + buffer */ + memmove(BACKEND->encdata_buffer, + (BACKEND->encdata_buffer + BACKEND->encdata_offset) - + inbuf[3].cbBuffer, inbuf[3].cbBuffer); + BACKEND->encdata_offset = inbuf[3].cbBuffer; + } + + DEBUGF(infof(data, + "schannel: encrypted cached: offset %zu length %zu\n", + BACKEND->encdata_offset, BACKEND->encdata_length)); + } + else { + /* reset encrypted buffer offset, because there is no data remaining */ + BACKEND->encdata_offset = 0; + } + + /* check if server wants to renegotiate the connection context */ + if(sspi_status == SEC_I_RENEGOTIATE) { + infof(data, "schannel: remote party requests renegotiation\n"); + if(*err && *err != CURLE_AGAIN) { + infof(data, "schannel: can't renogotiate, an error is pending\n"); + goto cleanup; + } + if(BACKEND->encdata_offset) { + *err = CURLE_RECV_ERROR; + infof(data, "schannel: can't renogotiate, " + "encrypted data available\n"); + goto cleanup; + } + /* begin renegotiation */ + infof(data, "schannel: renegotiating SSL/TLS connection\n"); + connssl->state = ssl_connection_negotiating; + connssl->connecting_state = ssl_connect_2_writing; + *err = schannel_connect_common(conn, sockindex, FALSE, &done); + if(*err) { + infof(data, "schannel: renegotiation failed\n"); + goto cleanup; + } + /* now retry receiving data */ + sspi_status = SEC_E_OK; + infof(data, "schannel: SSL/TLS connection renegotiated\n"); + continue; + } + /* check if the server closed the connection */ + else if(sspi_status == SEC_I_CONTEXT_EXPIRED) { + /* In Windows 2000 SEC_I_CONTEXT_EXPIRED (close_notify) is not + returned so we have to work around that in cleanup. */ + BACKEND->recv_sspi_close_notify = true; + if(!BACKEND->recv_connection_closed) { + BACKEND->recv_connection_closed = true; + infof(data, "schannel: server closed the connection\n"); + } + goto cleanup; + } + } + else if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) { + BACKEND->encdata_is_incomplete = true; + if(!*err) + *err = CURLE_AGAIN; + infof(data, "schannel: failed to decrypt data, need more data\n"); + goto cleanup; + } + else { + char buffer[STRERROR_LEN]; + *err = CURLE_RECV_ERROR; + infof(data, "schannel: failed to read data from server: %s\n", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + goto cleanup; + } + } + + DEBUGF(infof(data, + "schannel: encrypted data buffer: offset %zu length %zu\n", + BACKEND->encdata_offset, BACKEND->encdata_length)); + + DEBUGF(infof(data, + "schannel: decrypted data buffer: offset %zu length %zu\n", + BACKEND->decdata_offset, BACKEND->decdata_length)); + +cleanup: + /* Warning- there is no guarantee the encdata state is valid at this point */ + DEBUGF(infof(data, "schannel: schannel_recv cleanup\n")); + + /* Error if the connection has closed without a close_notify. + Behavior here is a matter of debate. We don't want to be vulnerable to a + truncation attack however there's some browser precedent for ignoring the + close_notify for compatibility reasons. + Additionally, Windows 2000 (v5.0) is a special case since it seems it doesn't + return close_notify. In that case if the connection was closed we assume it + was graceful (close_notify) since there doesn't seem to be a way to tell. + */ + if(len && !BACKEND->decdata_offset && BACKEND->recv_connection_closed && + !BACKEND->recv_sspi_close_notify) { + bool isWin2k = Curl_verify_windows_version(5, 0, PLATFORM_WINNT, + VERSION_EQUAL); + + if(isWin2k && sspi_status == SEC_E_OK) + BACKEND->recv_sspi_close_notify = true; + else { + *err = CURLE_RECV_ERROR; + infof(data, "schannel: server closed abruptly (missing close_notify)\n"); + } + } + + /* Any error other than CURLE_AGAIN is an unrecoverable error. */ + if(*err && *err != CURLE_AGAIN) + BACKEND->recv_unrecoverable_err = *err; + + size = len < BACKEND->decdata_offset ? len : BACKEND->decdata_offset; + if(size) { + memcpy(buf, BACKEND->decdata_buffer, size); + memmove(BACKEND->decdata_buffer, BACKEND->decdata_buffer + size, + BACKEND->decdata_offset - size); + BACKEND->decdata_offset -= size; + DEBUGF(infof(data, "schannel: decrypted data returned %zu\n", size)); + DEBUGF(infof(data, + "schannel: decrypted data buffer: offset %zu length %zu\n", + BACKEND->decdata_offset, BACKEND->decdata_length)); + *err = CURLE_OK; + return (ssize_t)size; + } + + if(!*err && !BACKEND->recv_connection_closed) + *err = CURLE_AGAIN; + + /* It's debatable what to return when !len. We could return whatever error we + got from decryption but instead we override here so the return is consistent. + */ + if(!len) + *err = CURLE_OK; + + return *err ? -1 : 0; +} + +static CURLcode Curl_schannel_connect_nonblocking(struct connectdata *conn, + int sockindex, bool *done) +{ + return schannel_connect_common(conn, sockindex, TRUE, done); +} + +static CURLcode Curl_schannel_connect(struct connectdata *conn, int sockindex) +{ + CURLcode result; + bool done = FALSE; + + result = schannel_connect_common(conn, sockindex, FALSE, &done); + if(result) + return result; + + DEBUGASSERT(done); + + return CURLE_OK; +} + +static bool Curl_schannel_data_pending(const struct connectdata *conn, + int sockindex) +{ + const struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + if(connssl->use) /* SSL/TLS is in use */ + return (BACKEND->decdata_offset > 0 || + (BACKEND->encdata_offset > 0 && !BACKEND->encdata_is_incomplete)); + else + return FALSE; +} + +static void Curl_schannel_close(struct connectdata *conn, int sockindex) +{ + if(conn->ssl[sockindex].use) + /* if the SSL/TLS channel hasn't been shut down yet, do that now. */ + Curl_ssl_shutdown(conn, sockindex); +} + +static void Curl_schannel_session_free(void *ptr) +{ + /* this is expected to be called under sessionid lock */ + struct curl_schannel_cred *cred = ptr; + + cred->refcount--; + if(cred->refcount == 0) { + s_pSecFn->FreeCredentialsHandle(&cred->cred_handle); + Curl_safefree(cred); + } +} + +static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) +{ + /* See https://msdn.microsoft.com/en-us/library/windows/desktop/aa380138.aspx + * Shutting Down an Schannel Connection + */ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + + DEBUGASSERT(data); + + infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n", + hostname, conn->remote_port); + + if(BACKEND->cred && BACKEND->ctxt) { + SecBufferDesc BuffDesc; + SecBuffer Buffer; + SECURITY_STATUS sspi_status; + SecBuffer outbuf; + SecBufferDesc outbuf_desc; + CURLcode result; + TCHAR *host_name; + DWORD dwshut = SCHANNEL_SHUTDOWN; + + InitSecBuffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut)); + InitSecBufferDesc(&BuffDesc, &Buffer, 1); + + sspi_status = s_pSecFn->ApplyControlToken(&BACKEND->ctxt->ctxt_handle, + &BuffDesc); + + if(sspi_status != SEC_E_OK) { + char buffer[STRERROR_LEN]; + failf(data, "schannel: ApplyControlToken failure: %s", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + } + + host_name = Curl_convert_UTF8_to_tchar(hostname); + if(!host_name) + return CURLE_OUT_OF_MEMORY; + + /* setup output buffer */ + InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0); + InitSecBufferDesc(&outbuf_desc, &outbuf, 1); + + sspi_status = s_pSecFn->InitializeSecurityContext( + &BACKEND->cred->cred_handle, + &BACKEND->ctxt->ctxt_handle, + host_name, + BACKEND->req_flags, + 0, + 0, + NULL, + 0, + &BACKEND->ctxt->ctxt_handle, + &outbuf_desc, + &BACKEND->ret_flags, + &BACKEND->ctxt->time_stamp); + + Curl_unicodefree(host_name); + + if((sspi_status == SEC_E_OK) || (sspi_status == SEC_I_CONTEXT_EXPIRED)) { + /* send close message which is in output buffer */ + ssize_t written; + result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer, + outbuf.cbBuffer, &written); + + s_pSecFn->FreeContextBuffer(outbuf.pvBuffer); + if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) { + infof(data, "schannel: failed to send close msg: %s" + " (bytes written: %zd)\n", curl_easy_strerror(result), written); + } + } + } + + /* free SSPI Schannel API security context handle */ + if(BACKEND->ctxt) { + DEBUGF(infof(data, "schannel: clear security context handle\n")); + s_pSecFn->DeleteSecurityContext(&BACKEND->ctxt->ctxt_handle); + Curl_safefree(BACKEND->ctxt); + } + + /* free SSPI Schannel API credential handle */ + if(BACKEND->cred) { + /* + * When this function is called from Curl_schannel_close() the connection + * might not have an associated transfer so the check for conn->data is + * necessary. + */ + Curl_ssl_sessionid_lock(conn); + Curl_schannel_session_free(BACKEND->cred); + Curl_ssl_sessionid_unlock(conn); + BACKEND->cred = NULL; + } + + /* free internal buffer for received encrypted data */ + if(BACKEND->encdata_buffer != NULL) { + Curl_safefree(BACKEND->encdata_buffer); + BACKEND->encdata_length = 0; + BACKEND->encdata_offset = 0; + BACKEND->encdata_is_incomplete = false; + } + + /* free internal buffer for received decrypted data */ + if(BACKEND->decdata_buffer != NULL) { + Curl_safefree(BACKEND->decdata_buffer); + BACKEND->decdata_length = 0; + BACKEND->decdata_offset = 0; + } + + return CURLE_OK; +} + +static int Curl_schannel_init(void) +{ + return (Curl_sspi_global_init() == CURLE_OK ? 1 : 0); +} + +static void Curl_schannel_cleanup(void) +{ + Curl_sspi_global_cleanup(); +} + +static size_t Curl_schannel_version(char *buffer, size_t size) +{ + size = msnprintf(buffer, size, "Schannel"); + + return size; +} + +static CURLcode Curl_schannel_random(struct Curl_easy *data UNUSED_PARAM, + unsigned char *entropy, size_t length) +{ + HCRYPTPROV hCryptProv = 0; + + (void)data; + + if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) + return CURLE_FAILED_INIT; + + if(!CryptGenRandom(hCryptProv, (DWORD)length, entropy)) { + CryptReleaseContext(hCryptProv, 0UL); + return CURLE_FAILED_INIT; + } + + CryptReleaseContext(hCryptProv, 0UL); + return CURLE_OK; +} + +static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex, + const char *pinnedpubkey) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + CERT_CONTEXT *pCertContextServer = NULL; + + /* Result is returned to caller */ + CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; + + /* if a path wasn't specified, don't pin */ + if(!pinnedpubkey) + return CURLE_OK; + + do { + SECURITY_STATUS sspi_status; + const char *x509_der; + DWORD x509_der_len; + curl_X509certificate x509_parsed; + curl_asn1Element *pubkey; + + sspi_status = + s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, + SECPKG_ATTR_REMOTE_CERT_CONTEXT, + &pCertContextServer); + + if((sspi_status != SEC_E_OK) || (pCertContextServer == NULL)) { + char buffer[STRERROR_LEN]; + failf(data, "schannel: Failed to read remote certificate context: %s", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + break; /* failed */ + } + + + if(!(((pCertContextServer->dwCertEncodingType & X509_ASN_ENCODING) != 0) && + (pCertContextServer->cbCertEncoded > 0))) + break; + + x509_der = (const char *)pCertContextServer->pbCertEncoded; + x509_der_len = pCertContextServer->cbCertEncoded; + memset(&x509_parsed, 0, sizeof(x509_parsed)); + if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len)) + break; + + pubkey = &x509_parsed.subjectPublicKeyInfo; + if(!pubkey->header || pubkey->end <= pubkey->header) { + failf(data, "SSL: failed retrieving public key from server certificate"); + break; + } + + result = Curl_pin_peer_pubkey(data, + pinnedpubkey, + (const unsigned char *)pubkey->header, + (size_t)(pubkey->end - pubkey->header)); + if(result) { + failf(data, "SSL: public key does not match pinned public key!"); + } + } while(0); + + if(pCertContextServer) + CertFreeCertificateContext(pCertContextServer); + + return result; +} + +static void Curl_schannel_checksum(const unsigned char *input, + size_t inputlen, + unsigned char *checksum, + size_t checksumlen, + DWORD provType, + const unsigned int algId) +{ + HCRYPTPROV hProv = 0; + HCRYPTHASH hHash = 0; + DWORD cbHashSize = 0; + DWORD dwHashSizeLen = (DWORD)sizeof(cbHashSize); + DWORD dwChecksumLen = (DWORD)checksumlen; + + /* since this can fail in multiple ways, zero memory first so we never + * return old data + */ + memset(checksum, 0, checksumlen); + + if(!CryptAcquireContext(&hProv, NULL, NULL, provType, + CRYPT_VERIFYCONTEXT)) + return; /* failed */ + + do { + if(!CryptCreateHash(hProv, algId, 0, 0, &hHash)) + break; /* failed */ + + /* workaround for original MinGW, should be (const BYTE*) */ + if(!CryptHashData(hHash, (BYTE*)input, (DWORD)inputlen, 0)) + break; /* failed */ + + /* get hash size */ + if(!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *)&cbHashSize, + &dwHashSizeLen, 0)) + break; /* failed */ + + /* check hash size */ + if(checksumlen < cbHashSize) + break; /* failed */ + + if(CryptGetHashParam(hHash, HP_HASHVAL, checksum, &dwChecksumLen, 0)) + break; /* failed */ + } while(0); + + if(hHash) + CryptDestroyHash(hHash); + + if(hProv) + CryptReleaseContext(hProv, 0); +} + +static CURLcode Curl_schannel_md5sum(unsigned char *input, + size_t inputlen, + unsigned char *md5sum, + size_t md5len) +{ + Curl_schannel_checksum(input, inputlen, md5sum, md5len, + PROV_RSA_FULL, CALG_MD5); + return CURLE_OK; +} + +static CURLcode Curl_schannel_sha256sum(const unsigned char *input, + size_t inputlen, + unsigned char *sha256sum, + size_t sha256len) +{ + Curl_schannel_checksum(input, inputlen, sha256sum, sha256len, + PROV_RSA_AES, CALG_SHA_256); + return CURLE_OK; +} + +static void *Curl_schannel_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) +{ + (void)info; + return &BACKEND->ctxt->ctxt_handle; +} + +const struct Curl_ssl Curl_ssl_schannel = { + { CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */ + + SSLSUPP_CERTINFO | + SSLSUPP_PINNEDPUBKEY, + + sizeof(struct ssl_backend_data), + + Curl_schannel_init, /* init */ + Curl_schannel_cleanup, /* cleanup */ + Curl_schannel_version, /* version */ + Curl_none_check_cxn, /* check_cxn */ + Curl_schannel_shutdown, /* shutdown */ + Curl_schannel_data_pending, /* data_pending */ + Curl_schannel_random, /* random */ + Curl_none_cert_status_request, /* cert_status_request */ + Curl_schannel_connect, /* connect */ + Curl_schannel_connect_nonblocking, /* connect_nonblocking */ + Curl_schannel_get_internals, /* get_internals */ + Curl_schannel_close, /* close_one */ + Curl_none_close_all, /* close_all */ + Curl_schannel_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ + Curl_schannel_md5sum, /* md5sum */ + Curl_schannel_sha256sum /* sha256sum */ +}; + +#endif /* USE_SCHANNEL */ diff --git a/dependencies/cmcurl/lib/vtls/schannel.h b/dependencies/cmcurl/lib/vtls/schannel.h new file mode 100644 index 0000000..ee8d7d4 --- /dev/null +++ b/dependencies/cmcurl/lib/vtls/schannel.h @@ -0,0 +1,108 @@ +#ifndef HEADER_CURL_SCHANNEL_H +#define HEADER_CURL_SCHANNEL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012, Marc Hoersken, , et al. + * Copyright (C) 2012 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_SCHANNEL + +#include +#include +#include "curl_sspi.h" + +#include "urldata.h" + +/* has been included via the above . + * Or in case of ldap.c, it was included via . + * And since has this: + * #define X509_NAME ((LPCSTR) 7) + * + * And in BoringSSL's there is: + * typedef struct X509_name_st X509_NAME; + * etc. + * + * this will cause all kinds of C-preprocessing paste errors in + * BoringSSL's : So just undefine those defines here + * (and only here). + */ +#if defined(HAVE_BORINGSSL) || defined(OPENSSL_IS_BORINGSSL) +# undef X509_NAME +# undef X509_CERT_PAIR +# undef X509_EXTENSIONS +#endif + +extern const struct Curl_ssl Curl_ssl_schannel; + +CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex); + +/* structs to expose only in schannel.c and schannel_verify.c */ +#ifdef EXPOSE_SCHANNEL_INTERNAL_STRUCTS + +#ifdef __MINGW32__ +#include <_mingw.h> +#ifdef __MINGW64_VERSION_MAJOR +#define HAS_MANUAL_VERIFY_API +#endif +#else +#include +#ifdef CERT_CHAIN_REVOCATION_CHECK_CHAIN +#define HAS_MANUAL_VERIFY_API +#endif +#endif + +struct curl_schannel_cred { + CredHandle cred_handle; + TimeStamp time_stamp; + int refcount; +}; + +struct curl_schannel_ctxt { + CtxtHandle ctxt_handle; + TimeStamp time_stamp; +}; + +struct ssl_backend_data { + struct curl_schannel_cred *cred; + struct curl_schannel_ctxt *ctxt; + SecPkgContext_StreamSizes stream_sizes; + size_t encdata_length, decdata_length; + size_t encdata_offset, decdata_offset; + unsigned char *encdata_buffer, *decdata_buffer; + /* encdata_is_incomplete: if encdata contains only a partial record that + can't be decrypted without another Curl_read_plain (that is, status is + SEC_E_INCOMPLETE_MESSAGE) then set this true. after Curl_read_plain writes + more bytes into encdata then set this back to false. */ + bool encdata_is_incomplete; + unsigned long req_flags, ret_flags; + CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */ + bool recv_sspi_close_notify; /* true if connection closed by close_notify */ + bool recv_connection_closed; /* true if connection closed, regardless how */ + bool use_alpn; /* true if ALPN is used for this connection */ +#ifdef HAS_MANUAL_VERIFY_API + bool use_manual_cred_validation; /* true if manual cred validation is used */ +#endif +}; +#endif /* EXPOSE_SCHANNEL_INTERNAL_STRUCTS */ + +#endif /* USE_SCHANNEL */ +#endif /* HEADER_CURL_SCHANNEL_H */ diff --git a/dependencies/cmcurl/lib/vtls/schannel_verify.c b/dependencies/cmcurl/lib/vtls/schannel_verify.c new file mode 100644 index 0000000..5a09e96 --- /dev/null +++ b/dependencies/cmcurl/lib/vtls/schannel_verify.c @@ -0,0 +1,572 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2016, Marc Hoersken, + * Copyright (C) 2012, Mark Salisbury, + * Copyright (C) 2012 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for Schannel-specific certificate verification. This code should + * only be invoked by code in schannel.c. + */ + +#include "curl_setup.h" + +#ifdef USE_SCHANNEL +#ifndef USE_WINDOWS_SSPI +# error "Can't compile SCHANNEL support without SSPI." +#endif + +#define EXPOSE_SCHANNEL_INTERNAL_STRUCTS +#include "schannel.h" + +#ifdef HAS_MANUAL_VERIFY_API + +#include "vtls.h" +#include "sendf.h" +#include "strerror.h" +#include "curl_multibyte.h" +#include "curl_printf.h" +#include "hostcheck.h" +#include "system_win32.h" + +/* The last #include file should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#define BACKEND connssl->backend + +#define MAX_CAFILE_SIZE 1048576 /* 1 MiB */ +#define BEGIN_CERT "-----BEGIN CERTIFICATE-----" +#define END_CERT "\n-----END CERTIFICATE-----" + +typedef struct { + DWORD cbSize; + HCERTSTORE hRestrictedRoot; + HCERTSTORE hRestrictedTrust; + HCERTSTORE hRestrictedOther; + DWORD cAdditionalStore; + HCERTSTORE *rghAdditionalStore; + DWORD dwFlags; + DWORD dwUrlRetrievalTimeout; + DWORD MaximumCachedCertificates; + DWORD CycleDetectionModulus; + HCERTSTORE hExclusiveRoot; + HCERTSTORE hExclusiveTrustedPeople; +} CERT_CHAIN_ENGINE_CONFIG_WIN7, *PCERT_CHAIN_ENGINE_CONFIG_WIN7; + +static int is_cr_or_lf(char c) +{ + return c == '\r' || c == '\n'; +} + +static CURLcode add_certs_to_store(HCERTSTORE trust_store, + const char *ca_file, + struct connectdata *conn) +{ + CURLcode result; + struct Curl_easy *data = conn->data; + HANDLE ca_file_handle = INVALID_HANDLE_VALUE; + LARGE_INTEGER file_size; + char *ca_file_buffer = NULL; + char *current_ca_file_ptr = NULL; + TCHAR *ca_file_tstr = NULL; + size_t ca_file_bufsize = 0; + DWORD total_bytes_read = 0; + bool more_certs = 0; + int num_certs = 0; + size_t END_CERT_LEN; + + ca_file_tstr = Curl_convert_UTF8_to_tchar((char *)ca_file); + if(!ca_file_tstr) { + char buffer[STRERROR_LEN]; + failf(data, + "schannel: invalid path name for CA file '%s': %s", + ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer))); + result = CURLE_SSL_CACERT_BADFILE; + goto cleanup; + } + + /* + * Read the CA file completely into memory before parsing it. This + * optimizes for the common case where the CA file will be relatively + * small ( < 1 MiB ). + */ + ca_file_handle = CreateFile(ca_file_tstr, + GENERIC_READ, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if(ca_file_handle == INVALID_HANDLE_VALUE) { + char buffer[STRERROR_LEN]; + failf(data, + "schannel: failed to open CA file '%s': %s", + ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer))); + result = CURLE_SSL_CACERT_BADFILE; + goto cleanup; + } + + if(!GetFileSizeEx(ca_file_handle, &file_size)) { + char buffer[STRERROR_LEN]; + failf(data, + "schannel: failed to determine size of CA file '%s': %s", + ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer))); + result = CURLE_SSL_CACERT_BADFILE; + goto cleanup; + } + + if(file_size.QuadPart > MAX_CAFILE_SIZE) { + failf(data, + "schannel: CA file exceeds max size of %u bytes", + MAX_CAFILE_SIZE); + result = CURLE_SSL_CACERT_BADFILE; + goto cleanup; + } + + ca_file_bufsize = (size_t)file_size.QuadPart; + ca_file_buffer = (char *)malloc(ca_file_bufsize + 1); + if(!ca_file_buffer) { + result = CURLE_OUT_OF_MEMORY; + goto cleanup; + } + + result = CURLE_OK; + while(total_bytes_read < ca_file_bufsize) { + DWORD bytes_to_read = (DWORD)(ca_file_bufsize - total_bytes_read); + DWORD bytes_read = 0; + + if(!ReadFile(ca_file_handle, ca_file_buffer + total_bytes_read, + bytes_to_read, &bytes_read, NULL)) { + char buffer[STRERROR_LEN]; + failf(data, + "schannel: failed to read from CA file '%s': %s", + ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer))); + result = CURLE_SSL_CACERT_BADFILE; + goto cleanup; + } + if(bytes_read == 0) { + /* Premature EOF -- adjust the bufsize to the new value */ + ca_file_bufsize = total_bytes_read; + } + else { + total_bytes_read += bytes_read; + } + } + + /* Null terminate the buffer */ + ca_file_buffer[ca_file_bufsize] = '\0'; + + if(result != CURLE_OK) { + goto cleanup; + } + + END_CERT_LEN = strlen(END_CERT); + + more_certs = 1; + current_ca_file_ptr = ca_file_buffer; + while(more_certs && *current_ca_file_ptr != '\0') { + char *begin_cert_ptr = strstr(current_ca_file_ptr, BEGIN_CERT); + if(!begin_cert_ptr || !is_cr_or_lf(begin_cert_ptr[strlen(BEGIN_CERT)])) { + more_certs = 0; + } + else { + char *end_cert_ptr = strstr(begin_cert_ptr, END_CERT); + if(!end_cert_ptr) { + failf(data, + "schannel: CA file '%s' is not correctly formatted", + ca_file); + result = CURLE_SSL_CACERT_BADFILE; + more_certs = 0; + } + else { + CERT_BLOB cert_blob; + CERT_CONTEXT *cert_context = NULL; + BOOL add_cert_result = FALSE; + DWORD actual_content_type = 0; + DWORD cert_size = (DWORD) + ((end_cert_ptr + END_CERT_LEN) - begin_cert_ptr); + + cert_blob.pbData = (BYTE *)begin_cert_ptr; + cert_blob.cbData = cert_size; + if(!CryptQueryObject(CERT_QUERY_OBJECT_BLOB, + &cert_blob, + CERT_QUERY_CONTENT_FLAG_CERT, + CERT_QUERY_FORMAT_FLAG_ALL, + 0, + NULL, + &actual_content_type, + NULL, + NULL, + NULL, + (const void **)&cert_context)) { + char buffer[STRERROR_LEN]; + failf(data, + "schannel: failed to extract certificate from CA file " + "'%s': %s", + ca_file, + Curl_strerror(GetLastError(), buffer, sizeof(buffer))); + result = CURLE_SSL_CACERT_BADFILE; + more_certs = 0; + } + else { + current_ca_file_ptr = begin_cert_ptr + cert_size; + + /* Sanity check that the cert_context object is the right type */ + if(CERT_QUERY_CONTENT_CERT != actual_content_type) { + failf(data, + "schannel: unexpected content type '%d' when extracting " + "certificate from CA file '%s'", + actual_content_type, ca_file); + result = CURLE_SSL_CACERT_BADFILE; + more_certs = 0; + } + else { + add_cert_result = + CertAddCertificateContextToStore(trust_store, + cert_context, + CERT_STORE_ADD_ALWAYS, + NULL); + CertFreeCertificateContext(cert_context); + if(!add_cert_result) { + char buffer[STRERROR_LEN]; + failf(data, + "schannel: failed to add certificate from CA file '%s' " + "to certificate store: %s", + ca_file, + Curl_strerror(GetLastError(), buffer, sizeof(buffer))); + result = CURLE_SSL_CACERT_BADFILE; + more_certs = 0; + } + else { + num_certs++; + } + } + } + } + } + } + + if(result == CURLE_OK) { + if(!num_certs) { + infof(data, + "schannel: did not add any certificates from CA file '%s'\n", + ca_file); + } + else { + infof(data, + "schannel: added %d certificate(s) from CA file '%s'\n", + num_certs, ca_file); + } + } + +cleanup: + if(ca_file_handle != INVALID_HANDLE_VALUE) { + CloseHandle(ca_file_handle); + } + Curl_safefree(ca_file_buffer); + Curl_unicodefree(ca_file_tstr); + + return result; +} + +static CURLcode verify_host(struct Curl_easy *data, + CERT_CONTEXT *pCertContextServer, + const char * const conn_hostname) +{ + CURLcode result = CURLE_PEER_FAILED_VERIFICATION; + TCHAR *cert_hostname_buff = NULL; + size_t cert_hostname_buff_index = 0; + DWORD len = 0; + DWORD actual_len = 0; + + /* CertGetNameString will provide the 8-bit character string without + * any decoding */ + DWORD name_flags = CERT_NAME_DISABLE_IE4_UTF8_FLAG; + +#ifdef CERT_NAME_SEARCH_ALL_NAMES_FLAG + name_flags |= CERT_NAME_SEARCH_ALL_NAMES_FLAG; +#endif + + /* Determine the size of the string needed for the cert hostname */ + len = CertGetNameString(pCertContextServer, + CERT_NAME_DNS_TYPE, + name_flags, + NULL, + NULL, + 0); + if(len == 0) { + failf(data, + "schannel: CertGetNameString() returned no " + "certificate name information"); + result = CURLE_PEER_FAILED_VERIFICATION; + goto cleanup; + } + + /* CertGetNameString guarantees that the returned name will not contain + * embedded null bytes. This appears to be undocumented behavior. + */ + cert_hostname_buff = (LPTSTR)malloc(len * sizeof(TCHAR)); + if(!cert_hostname_buff) { + result = CURLE_OUT_OF_MEMORY; + goto cleanup; + } + actual_len = CertGetNameString(pCertContextServer, + CERT_NAME_DNS_TYPE, + name_flags, + NULL, + (LPTSTR) cert_hostname_buff, + len); + + /* Sanity check */ + if(actual_len != len) { + failf(data, + "schannel: CertGetNameString() returned certificate " + "name information of unexpected size"); + result = CURLE_PEER_FAILED_VERIFICATION; + goto cleanup; + } + + /* If HAVE_CERT_NAME_SEARCH_ALL_NAMES is available, the output + * will contain all DNS names, where each name is null-terminated + * and the last DNS name is double null-terminated. Due to this + * encoding, use the length of the buffer to iterate over all names. + */ + result = CURLE_PEER_FAILED_VERIFICATION; + while(cert_hostname_buff_index < len && + cert_hostname_buff[cert_hostname_buff_index] != TEXT('\0') && + result == CURLE_PEER_FAILED_VERIFICATION) { + + char *cert_hostname; + + /* Comparing the cert name and the connection hostname encoded as UTF-8 + * is acceptable since both values are assumed to use ASCII + * (or some equivalent) encoding + */ + cert_hostname = Curl_convert_tchar_to_UTF8( + &cert_hostname_buff[cert_hostname_buff_index]); + if(!cert_hostname) { + result = CURLE_OUT_OF_MEMORY; + } + else { + int match_result; + + match_result = Curl_cert_hostcheck(cert_hostname, conn_hostname); + if(match_result == CURL_HOST_MATCH) { + infof(data, + "schannel: connection hostname (%s) validated " + "against certificate name (%s)\n", + conn_hostname, cert_hostname); + result = CURLE_OK; + } + else { + size_t cert_hostname_len; + + infof(data, + "schannel: connection hostname (%s) did not match " + "against certificate name (%s)\n", + conn_hostname, cert_hostname); + + cert_hostname_len = _tcslen( + &cert_hostname_buff[cert_hostname_buff_index]); + + /* Move on to next cert name */ + cert_hostname_buff_index += cert_hostname_len + 1; + + result = CURLE_PEER_FAILED_VERIFICATION; + } + Curl_unicodefree(cert_hostname); + } + } + + if(result == CURLE_PEER_FAILED_VERIFICATION) { + failf(data, + "schannel: CertGetNameString() failed to match " + "connection hostname (%s) against server certificate names", + conn_hostname); + } + else if(result != CURLE_OK) + failf(data, "schannel: server certificate name verification failed"); + +cleanup: + Curl_unicodefree(cert_hostname_buff); + + return result; +} + +CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex) +{ + SECURITY_STATUS sspi_status; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + CURLcode result = CURLE_OK; + CERT_CONTEXT *pCertContextServer = NULL; + const CERT_CHAIN_CONTEXT *pChainContext = NULL; + HCERTCHAINENGINE cert_chain_engine = NULL; + HCERTSTORE trust_store = NULL; + const char * const conn_hostname = SSL_IS_PROXY() ? + conn->http_proxy.host.name : + conn->host.name; + + sspi_status = + s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, + SECPKG_ATTR_REMOTE_CERT_CONTEXT, + &pCertContextServer); + + if((sspi_status != SEC_E_OK) || (pCertContextServer == NULL)) { + char buffer[STRERROR_LEN]; + failf(data, "schannel: Failed to read remote certificate context: %s", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + result = CURLE_PEER_FAILED_VERIFICATION; + } + + if(result == CURLE_OK && SSL_CONN_CONFIG(CAfile) && + BACKEND->use_manual_cred_validation) { + /* + * Create a chain engine that uses the certificates in the CA file as + * trusted certificates. This is only supported on Windows 7+. + */ + + if(Curl_verify_windows_version(6, 1, PLATFORM_WINNT, VERSION_LESS_THAN)) { + failf(data, "schannel: this version of Windows is too old to support " + "certificate verification via CA bundle file."); + result = CURLE_SSL_CACERT_BADFILE; + } + else { + /* Open the certificate store */ + trust_store = CertOpenStore(CERT_STORE_PROV_MEMORY, + 0, + (HCRYPTPROV)NULL, + CERT_STORE_CREATE_NEW_FLAG, + NULL); + if(!trust_store) { + char buffer[STRERROR_LEN]; + failf(data, "schannel: failed to create certificate store: %s", + Curl_strerror(GetLastError(), buffer, sizeof(buffer))); + result = CURLE_SSL_CACERT_BADFILE; + } + else { + result = add_certs_to_store(trust_store, SSL_CONN_CONFIG(CAfile), + conn); + } + } + + if(result == CURLE_OK) { + CERT_CHAIN_ENGINE_CONFIG_WIN7 engine_config; + BOOL create_engine_result; + + memset(&engine_config, 0, sizeof(engine_config)); + engine_config.cbSize = sizeof(engine_config); + engine_config.hExclusiveRoot = trust_store; + + /* CertCreateCertificateChainEngine will check the expected size of the + * CERT_CHAIN_ENGINE_CONFIG structure and fail if the specified size + * does not match the expected size. When this occurs, it indicates that + * CAINFO is not supported on the version of Windows in use. + */ + create_engine_result = + CertCreateCertificateChainEngine( + (CERT_CHAIN_ENGINE_CONFIG *)&engine_config, &cert_chain_engine); + if(!create_engine_result) { + char buffer[STRERROR_LEN]; + failf(data, + "schannel: failed to create certificate chain engine: %s", + Curl_strerror(GetLastError(), buffer, sizeof(buffer))); + result = CURLE_SSL_CACERT_BADFILE; + } + } + } + + if(result == CURLE_OK) { + CERT_CHAIN_PARA ChainPara; + + memset(&ChainPara, 0, sizeof(ChainPara)); + ChainPara.cbSize = sizeof(ChainPara); + + if(!CertGetCertificateChain(cert_chain_engine, + pCertContextServer, + NULL, + pCertContextServer->hCertStore, + &ChainPara, + (data->set.ssl.no_revoke ? 0 : + CERT_CHAIN_REVOCATION_CHECK_CHAIN), + NULL, + &pChainContext)) { + char buffer[STRERROR_LEN]; + failf(data, "schannel: CertGetCertificateChain failed: %s", + Curl_strerror(GetLastError(), buffer, sizeof(buffer))); + pChainContext = NULL; + result = CURLE_PEER_FAILED_VERIFICATION; + } + + if(result == CURLE_OK) { + CERT_SIMPLE_CHAIN *pSimpleChain = pChainContext->rgpChain[0]; + DWORD dwTrustErrorMask = ~(DWORD)(CERT_TRUST_IS_NOT_TIME_NESTED); + dwTrustErrorMask &= pSimpleChain->TrustStatus.dwErrorStatus; + if(dwTrustErrorMask) { + if(dwTrustErrorMask & CERT_TRUST_IS_REVOKED) + failf(data, "schannel: CertGetCertificateChain trust error" + " CERT_TRUST_IS_REVOKED"); + else if(dwTrustErrorMask & CERT_TRUST_IS_PARTIAL_CHAIN) + failf(data, "schannel: CertGetCertificateChain trust error" + " CERT_TRUST_IS_PARTIAL_CHAIN"); + else if(dwTrustErrorMask & CERT_TRUST_IS_UNTRUSTED_ROOT) + failf(data, "schannel: CertGetCertificateChain trust error" + " CERT_TRUST_IS_UNTRUSTED_ROOT"); + else if(dwTrustErrorMask & CERT_TRUST_IS_NOT_TIME_VALID) + failf(data, "schannel: CertGetCertificateChain trust error" + " CERT_TRUST_IS_NOT_TIME_VALID"); + else if(dwTrustErrorMask & CERT_TRUST_REVOCATION_STATUS_UNKNOWN) + failf(data, "schannel: CertGetCertificateChain trust error" + " CERT_TRUST_REVOCATION_STATUS_UNKNOWN"); + else + failf(data, "schannel: CertGetCertificateChain error mask: 0x%08x", + dwTrustErrorMask); + result = CURLE_PEER_FAILED_VERIFICATION; + } + } + } + + if(result == CURLE_OK) { + if(SSL_CONN_CONFIG(verifyhost)) { + result = verify_host(conn->data, pCertContextServer, conn_hostname); + } + } + + if(cert_chain_engine) { + CertFreeCertificateChainEngine(cert_chain_engine); + } + + if(trust_store) { + CertCloseStore(trust_store, 0); + } + + if(pChainContext) + CertFreeCertificateChain(pChainContext); + + if(pCertContextServer) + CertFreeCertificateContext(pCertContextServer); + + return result; +} + +#endif /* HAS_MANUAL_VERIFY_API */ +#endif /* USE_SCHANNEL */ diff --git a/dependencies/cmcurl/lib/vtls/sectransp.c b/dependencies/cmcurl/lib/vtls/sectransp.c new file mode 100644 index 0000000..2fdf662 --- /dev/null +++ b/dependencies/cmcurl/lib/vtls/sectransp.c @@ -0,0 +1,3264 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2017, Nick Zitzmann, . + * Copyright (C) 2012 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all iOS and macOS SecureTransport-specific code for the + * TLS/SSL layer. No code but vtls.c should ever call or use these functions. + */ + +#include "curl_setup.h" + +#include "urldata.h" /* for the Curl_easy definition */ +#include "curl_base64.h" +#include "strtok.h" +#include "multiif.h" + +#ifdef USE_SECTRANSP + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wtautological-pointer-compare" +#endif /* __clang__ */ + +#include + +#include +/* For some reason, when building for iOS, the omnibus header above does + * not include SecureTransport.h as of iOS SDK 5.1. */ +#include +#include +#include + +/* The Security framework has changed greatly between iOS and different macOS + versions, and we will try to support as many of them as we can (back to + Leopard and iOS 5) by using macros and weak-linking. + + In general, you want to build this using the most recent OS SDK, since some + features require curl to be built against the latest SDK. TLS 1.1 and 1.2 + support, for instance, require the macOS 10.8 SDK or later. TLS 1.3 + requires the macOS 10.13 or iOS 11 SDK or later. */ +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) + +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1050 +#error "The Secure Transport back-end requires Leopard or later." +#endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1050 */ + +#define CURL_BUILD_IOS 0 +#define CURL_BUILD_IOS_7 0 +#define CURL_BUILD_IOS_9 0 +#define CURL_BUILD_IOS_11 0 +#define CURL_BUILD_MAC 1 +/* This is the maximum API level we are allowed to use when building: */ +#define CURL_BUILD_MAC_10_5 MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 +#define CURL_BUILD_MAC_10_6 MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 +#define CURL_BUILD_MAC_10_7 MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 +#define CURL_BUILD_MAC_10_8 MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 +#define CURL_BUILD_MAC_10_9 MAC_OS_X_VERSION_MAX_ALLOWED >= 1090 +#define CURL_BUILD_MAC_10_11 MAC_OS_X_VERSION_MAX_ALLOWED >= 101100 +#define CURL_BUILD_MAC_10_13 MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 +/* These macros mean "the following code is present to allow runtime backward + compatibility with at least this cat or earlier": + (You set this at build-time using the compiler command line option + "-mmacos-version-min.") */ +#define CURL_SUPPORT_MAC_10_5 MAC_OS_X_VERSION_MIN_REQUIRED <= 1050 +#define CURL_SUPPORT_MAC_10_6 MAC_OS_X_VERSION_MIN_REQUIRED <= 1060 +#define CURL_SUPPORT_MAC_10_7 MAC_OS_X_VERSION_MIN_REQUIRED <= 1070 +#define CURL_SUPPORT_MAC_10_8 MAC_OS_X_VERSION_MIN_REQUIRED <= 1080 +#define CURL_SUPPORT_MAC_10_9 MAC_OS_X_VERSION_MIN_REQUIRED <= 1090 + +#elif TARGET_OS_EMBEDDED || TARGET_OS_IPHONE +#define CURL_BUILD_IOS 1 +#define CURL_BUILD_IOS_7 __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 +#define CURL_BUILD_IOS_9 __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000 +#define CURL_BUILD_IOS_11 __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 +#define CURL_BUILD_MAC 0 +#define CURL_BUILD_MAC_10_5 0 +#define CURL_BUILD_MAC_10_6 0 +#define CURL_BUILD_MAC_10_7 0 +#define CURL_BUILD_MAC_10_8 0 +#define CURL_BUILD_MAC_10_9 0 +#define CURL_BUILD_MAC_10_11 0 +#define CURL_BUILD_MAC_10_13 0 +#define CURL_SUPPORT_MAC_10_5 0 +#define CURL_SUPPORT_MAC_10_6 0 +#define CURL_SUPPORT_MAC_10_7 0 +#define CURL_SUPPORT_MAC_10_8 0 +#define CURL_SUPPORT_MAC_10_9 0 + +#else +#error "The Secure Transport back-end requires iOS or macOS." +#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */ + +#if CURL_BUILD_MAC +#include +#endif /* CURL_BUILD_MAC */ + +#include "urldata.h" +#include "sendf.h" +#include "inet_pton.h" +#include "connect.h" +#include "select.h" +#include "vtls.h" +#include "sectransp.h" +#include "curl_printf.h" +#include "strdup.h" + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* From MacTypes.h (which we can't include because it isn't present in iOS: */ +#define ioErr -36 +#define paramErr -50 + +struct ssl_backend_data { + SSLContextRef ssl_ctx; + curl_socket_t ssl_sockfd; + bool ssl_direction; /* true if writing, false if reading */ + size_t ssl_write_buffered_length; +}; + +#define BACKEND connssl->backend + +/* pinned public key support tests */ + +/* version 1 supports macOS 10.12+ and iOS 10+ */ +#if ((TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || \ + (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)) +#define SECTRANSP_PINNEDPUBKEY_V1 1 +#endif + +/* version 2 supports MacOSX 10.7+ */ +#if (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) +#define SECTRANSP_PINNEDPUBKEY_V2 1 +#endif + +#if defined(SECTRANSP_PINNEDPUBKEY_V1) || defined(SECTRANSP_PINNEDPUBKEY_V2) +/* this backend supports CURLOPT_PINNEDPUBLICKEY */ +#define SECTRANSP_PINNEDPUBKEY 1 +#endif /* SECTRANSP_PINNEDPUBKEY */ + +#ifdef SECTRANSP_PINNEDPUBKEY +/* both new and old APIs return rsa keys missing the spki header (not DER) */ +static const unsigned char rsa4096SpkiHeader[] = { + 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, + 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00}; + +static const unsigned char rsa2048SpkiHeader[] = { + 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, + 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00}; +#ifdef SECTRANSP_PINNEDPUBKEY_V1 +/* the *new* version doesn't return DER encoded ecdsa certs like the old... */ +static const unsigned char ecDsaSecp256r1SpkiHeader[] = { + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00}; + +static const unsigned char ecDsaSecp384r1SpkiHeader[] = { + 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, + 0x00, 0x22, 0x03, 0x62, 0x00}; +#endif /* SECTRANSP_PINNEDPUBKEY_V1 */ +#endif /* SECTRANSP_PINNEDPUBKEY */ + +/* The following two functions were ripped from Apple sample code, + * with some modifications: */ +static OSStatus SocketRead(SSLConnectionRef connection, + void *data, /* owned by + * caller, data + * RETURNED */ + size_t *dataLength) /* IN/OUT */ +{ + size_t bytesToGo = *dataLength; + size_t initLen = bytesToGo; + UInt8 *currData = (UInt8 *)data; + /*int sock = *(int *)connection;*/ + struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection; + int sock = BACKEND->ssl_sockfd; + OSStatus rtn = noErr; + size_t bytesRead; + ssize_t rrtn; + int theErr; + + *dataLength = 0; + + for(;;) { + bytesRead = 0; + rrtn = read(sock, currData, bytesToGo); + if(rrtn <= 0) { + /* this is guesswork... */ + theErr = errno; + if(rrtn == 0) { /* EOF = server hung up */ + /* the framework will turn this into errSSLClosedNoNotify */ + rtn = errSSLClosedGraceful; + } + else /* do the switch */ + switch(theErr) { + case ENOENT: + /* connection closed */ + rtn = errSSLClosedGraceful; + break; + case ECONNRESET: + rtn = errSSLClosedAbort; + break; + case EAGAIN: + rtn = errSSLWouldBlock; + BACKEND->ssl_direction = false; + break; + default: + rtn = ioErr; + break; + } + break; + } + else { + bytesRead = rrtn; + } + bytesToGo -= bytesRead; + currData += bytesRead; + + if(bytesToGo == 0) { + /* filled buffer with incoming data, done */ + break; + } + } + *dataLength = initLen - bytesToGo; + + return rtn; +} + +static OSStatus SocketWrite(SSLConnectionRef connection, + const void *data, + size_t *dataLength) /* IN/OUT */ +{ + size_t bytesSent = 0; + /*int sock = *(int *)connection;*/ + struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection; + int sock = BACKEND->ssl_sockfd; + ssize_t length; + size_t dataLen = *dataLength; + const UInt8 *dataPtr = (UInt8 *)data; + OSStatus ortn; + int theErr; + + *dataLength = 0; + + do { + length = write(sock, + (char *)dataPtr + bytesSent, + dataLen - bytesSent); + } while((length > 0) && + ( (bytesSent += length) < dataLen) ); + + if(length <= 0) { + theErr = errno; + if(theErr == EAGAIN) { + ortn = errSSLWouldBlock; + BACKEND->ssl_direction = true; + } + else { + ortn = ioErr; + } + } + else { + ortn = noErr; + } + *dataLength = bytesSent; + return ortn; +} + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) +{ + switch(cipher) { + /* SSL version 3.0 */ + case SSL_RSA_WITH_NULL_MD5: + return "SSL_RSA_WITH_NULL_MD5"; + break; + case SSL_RSA_WITH_NULL_SHA: + return "SSL_RSA_WITH_NULL_SHA"; + break; + case SSL_RSA_EXPORT_WITH_RC4_40_MD5: + return "SSL_RSA_EXPORT_WITH_RC4_40_MD5"; + break; + case SSL_RSA_WITH_RC4_128_MD5: + return "SSL_RSA_WITH_RC4_128_MD5"; + break; + case SSL_RSA_WITH_RC4_128_SHA: + return "SSL_RSA_WITH_RC4_128_SHA"; + break; + case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: + return "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5"; + break; + case SSL_RSA_WITH_IDEA_CBC_SHA: + return "SSL_RSA_WITH_IDEA_CBC_SHA"; + break; + case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_RSA_WITH_DES_CBC_SHA: + return "SSL_RSA_WITH_DES_CBC_SHA"; + break; + case SSL_RSA_WITH_3DES_EDE_CBC_SHA: + return "SSL_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_DH_DSS_WITH_DES_CBC_SHA: + return "SSL_DH_DSS_WITH_DES_CBC_SHA"; + break; + case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA: + return "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_DH_RSA_WITH_DES_CBC_SHA: + return "SSL_DH_RSA_WITH_DES_CBC_SHA"; + break; + case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA: + return "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_DHE_DSS_WITH_DES_CBC_SHA: + return "SSL_DHE_DSS_WITH_DES_CBC_SHA"; + break; + case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA: + return "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_DHE_RSA_WITH_DES_CBC_SHA: + return "SSL_DHE_RSA_WITH_DES_CBC_SHA"; + break; + case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA: + return "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: + return "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5"; + break; + case SSL_DH_anon_WITH_RC4_128_MD5: + return "SSL_DH_anon_WITH_RC4_128_MD5"; + break; + case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_DH_anon_WITH_DES_CBC_SHA: + return "SSL_DH_anon_WITH_DES_CBC_SHA"; + break; + case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: + return "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_FORTEZZA_DMS_WITH_NULL_SHA: + return "SSL_FORTEZZA_DMS_WITH_NULL_SHA"; + break; + case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA: + return "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA"; + break; + /* TLS 1.0 with AES (RFC 3268) + (Apparently these are used in SSLv3 implementations as well.) */ + case TLS_RSA_WITH_AES_128_CBC_SHA: + return "TLS_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_DSS_WITH_AES_128_CBC_SHA: + return "TLS_DH_DSS_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_RSA_WITH_AES_128_CBC_SHA: + return "TLS_DH_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: + return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"; + break; + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: + return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_anon_WITH_AES_128_CBC_SHA: + return "TLS_DH_anon_WITH_AES_128_CBC_SHA"; + break; + case TLS_RSA_WITH_AES_256_CBC_SHA: + return "TLS_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_DSS_WITH_AES_256_CBC_SHA: + return "TLS_DH_DSS_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_RSA_WITH_AES_256_CBC_SHA: + return "TLS_DH_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: + return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"; + break; + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: + return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_anon_WITH_AES_256_CBC_SHA: + return "TLS_DH_anon_WITH_AES_256_CBC_SHA"; + break; + /* SSL version 2.0 */ + case SSL_RSA_WITH_RC2_CBC_MD5: + return "SSL_RSA_WITH_RC2_CBC_MD5"; + break; + case SSL_RSA_WITH_IDEA_CBC_MD5: + return "SSL_RSA_WITH_IDEA_CBC_MD5"; + break; + case SSL_RSA_WITH_DES_CBC_MD5: + return "SSL_RSA_WITH_DES_CBC_MD5"; + break; + case SSL_RSA_WITH_3DES_EDE_CBC_MD5: + return "SSL_RSA_WITH_3DES_EDE_CBC_MD5"; + break; + } + return "SSL_NULL_WITH_NULL_NULL"; +} + +CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) +{ + switch(cipher) { + /* TLS 1.0 with AES (RFC 3268) */ + case TLS_RSA_WITH_AES_128_CBC_SHA: + return "TLS_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_DSS_WITH_AES_128_CBC_SHA: + return "TLS_DH_DSS_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_RSA_WITH_AES_128_CBC_SHA: + return "TLS_DH_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: + return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"; + break; + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: + return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_anon_WITH_AES_128_CBC_SHA: + return "TLS_DH_anon_WITH_AES_128_CBC_SHA"; + break; + case TLS_RSA_WITH_AES_256_CBC_SHA: + return "TLS_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_DSS_WITH_AES_256_CBC_SHA: + return "TLS_DH_DSS_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_RSA_WITH_AES_256_CBC_SHA: + return "TLS_DH_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: + return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"; + break; + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: + return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_anon_WITH_AES_256_CBC_SHA: + return "TLS_DH_anon_WITH_AES_256_CBC_SHA"; + break; +#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS + /* TLS 1.0 with ECDSA (RFC 4492) */ + case TLS_ECDH_ECDSA_WITH_NULL_SHA: + return "TLS_ECDH_ECDSA_WITH_NULL_SHA"; + break; + case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: + return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA"; + break; + case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: + return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: + return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_ECDHE_ECDSA_WITH_NULL_SHA: + return "TLS_ECDHE_ECDSA_WITH_NULL_SHA"; + break; + case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: + return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"; + break; + case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: + return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: + return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_ECDH_RSA_WITH_NULL_SHA: + return "TLS_ECDH_RSA_WITH_NULL_SHA"; + break; + case TLS_ECDH_RSA_WITH_RC4_128_SHA: + return "TLS_ECDH_RSA_WITH_RC4_128_SHA"; + break; + case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: + return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: + return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_ECDHE_RSA_WITH_NULL_SHA: + return "TLS_ECDHE_RSA_WITH_NULL_SHA"; + break; + case TLS_ECDHE_RSA_WITH_RC4_128_SHA: + return "TLS_ECDHE_RSA_WITH_RC4_128_SHA"; + break; + case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: + return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: + return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_ECDH_anon_WITH_NULL_SHA: + return "TLS_ECDH_anon_WITH_NULL_SHA"; + break; + case TLS_ECDH_anon_WITH_RC4_128_SHA: + return "TLS_ECDH_anon_WITH_RC4_128_SHA"; + break; + case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: + return "TLS_ECDH_anon_WITH_AES_128_CBC_SHA"; + break; + case TLS_ECDH_anon_WITH_AES_256_CBC_SHA: + return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA"; + break; +#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */ +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + /* TLS 1.2 (RFC 5246) */ + case TLS_RSA_WITH_NULL_MD5: + return "TLS_RSA_WITH_NULL_MD5"; + break; + case TLS_RSA_WITH_NULL_SHA: + return "TLS_RSA_WITH_NULL_SHA"; + break; + case TLS_RSA_WITH_RC4_128_MD5: + return "TLS_RSA_WITH_RC4_128_MD5"; + break; + case TLS_RSA_WITH_RC4_128_SHA: + return "TLS_RSA_WITH_RC4_128_SHA"; + break; + case TLS_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_RSA_WITH_NULL_SHA256: + return "TLS_RSA_WITH_NULL_SHA256"; + break; + case TLS_RSA_WITH_AES_128_CBC_SHA256: + return "TLS_RSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_RSA_WITH_AES_256_CBC_SHA256: + return "TLS_RSA_WITH_AES_256_CBC_SHA256"; + break; + case TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: + return "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: + return "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DH_DSS_WITH_AES_128_CBC_SHA256: + return "TLS_DH_DSS_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DH_RSA_WITH_AES_128_CBC_SHA256: + return "TLS_DH_RSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: + return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: + return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DH_DSS_WITH_AES_256_CBC_SHA256: + return "TLS_DH_DSS_WITH_AES_256_CBC_SHA256"; + break; + case TLS_DH_RSA_WITH_AES_256_CBC_SHA256: + return "TLS_DH_RSA_WITH_AES_256_CBC_SHA256"; + break; + case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: + return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"; + break; + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: + return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"; + break; + case TLS_DH_anon_WITH_RC4_128_MD5: + return "TLS_DH_anon_WITH_RC4_128_MD5"; + break; + case TLS_DH_anon_WITH_3DES_EDE_CBC_SHA: + return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DH_anon_WITH_AES_128_CBC_SHA256: + return "TLS_DH_anon_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DH_anon_WITH_AES_256_CBC_SHA256: + return "TLS_DH_anon_WITH_AES_256_CBC_SHA256"; + break; + /* TLS 1.2 with AES GCM (RFC 5288) */ + case TLS_RSA_WITH_AES_128_GCM_SHA256: + return "TLS_RSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_RSA_WITH_AES_256_GCM_SHA384: + return "TLS_RSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: + return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: + return "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DH_RSA_WITH_AES_128_GCM_SHA256: + return "TLS_DH_RSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DH_RSA_WITH_AES_256_GCM_SHA384: + return "TLS_DH_RSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: + return "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: + return "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DH_DSS_WITH_AES_128_GCM_SHA256: + return "TLS_DH_DSS_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DH_DSS_WITH_AES_256_GCM_SHA384: + return "TLS_DH_DSS_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DH_anon_WITH_AES_128_GCM_SHA256: + return "TLS_DH_anon_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DH_anon_WITH_AES_256_GCM_SHA384: + return "TLS_DH_anon_WITH_AES_256_GCM_SHA384"; + break; + /* TLS 1.2 with elliptic curve ciphers (RFC 5289) */ + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: + return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: + return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"; + break; + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: + return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: + return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384"; + break; + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: + return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"; + break; + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: + return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: + return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384"; + break; + case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: + return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: + return "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: + return "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: + return "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + return "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: + return "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: + return "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_EMPTY_RENEGOTIATION_INFO_SCSV: + return "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"; + break; +#else + case SSL_RSA_WITH_NULL_MD5: + return "TLS_RSA_WITH_NULL_MD5"; + break; + case SSL_RSA_WITH_NULL_SHA: + return "TLS_RSA_WITH_NULL_SHA"; + break; + case SSL_RSA_WITH_RC4_128_MD5: + return "TLS_RSA_WITH_RC4_128_MD5"; + break; + case SSL_RSA_WITH_RC4_128_SHA: + return "TLS_RSA_WITH_RC4_128_SHA"; + break; + case SSL_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DH_anon_WITH_RC4_128_MD5: + return "TLS_DH_anon_WITH_RC4_128_MD5"; + break; + case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: + return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"; + break; +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ +#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 + /* TLS PSK (RFC 4279): */ + case TLS_PSK_WITH_RC4_128_SHA: + return "TLS_PSK_WITH_RC4_128_SHA"; + break; + case TLS_PSK_WITH_3DES_EDE_CBC_SHA: + return "TLS_PSK_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_PSK_WITH_AES_128_CBC_SHA: + return "TLS_PSK_WITH_AES_128_CBC_SHA"; + break; + case TLS_PSK_WITH_AES_256_CBC_SHA: + return "TLS_PSK_WITH_AES_256_CBC_SHA"; + break; + case TLS_DHE_PSK_WITH_RC4_128_SHA: + return "TLS_DHE_PSK_WITH_RC4_128_SHA"; + break; + case TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: + return "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DHE_PSK_WITH_AES_128_CBC_SHA: + return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA"; + break; + case TLS_DHE_PSK_WITH_AES_256_CBC_SHA: + return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA"; + break; + case TLS_RSA_PSK_WITH_RC4_128_SHA: + return "TLS_RSA_PSK_WITH_RC4_128_SHA"; + break; + case TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: + return "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_RSA_PSK_WITH_AES_128_CBC_SHA: + return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA"; + break; + case TLS_RSA_PSK_WITH_AES_256_CBC_SHA: + return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA"; + break; + /* More TLS PSK (RFC 4785): */ + case TLS_PSK_WITH_NULL_SHA: + return "TLS_PSK_WITH_NULL_SHA"; + break; + case TLS_DHE_PSK_WITH_NULL_SHA: + return "TLS_DHE_PSK_WITH_NULL_SHA"; + break; + case TLS_RSA_PSK_WITH_NULL_SHA: + return "TLS_RSA_PSK_WITH_NULL_SHA"; + break; + /* Even more TLS PSK (RFC 5487): */ + case TLS_PSK_WITH_AES_128_GCM_SHA256: + return "TLS_PSK_WITH_AES_128_GCM_SHA256"; + break; + case TLS_PSK_WITH_AES_256_GCM_SHA384: + return "TLS_PSK_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: + return "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: + return "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384"; + break; + case TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: + return "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256"; + break; + case TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: + return "TLS_PSK_WITH_AES_256_GCM_SHA384"; + break; + case TLS_PSK_WITH_AES_128_CBC_SHA256: + return "TLS_PSK_WITH_AES_128_CBC_SHA256"; + break; + case TLS_PSK_WITH_AES_256_CBC_SHA384: + return "TLS_PSK_WITH_AES_256_CBC_SHA384"; + break; + case TLS_PSK_WITH_NULL_SHA256: + return "TLS_PSK_WITH_NULL_SHA256"; + break; + case TLS_PSK_WITH_NULL_SHA384: + return "TLS_PSK_WITH_NULL_SHA384"; + break; + case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: + return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: + return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384"; + break; + case TLS_DHE_PSK_WITH_NULL_SHA256: + return "TLS_DHE_PSK_WITH_NULL_SHA256"; + break; + case TLS_DHE_PSK_WITH_NULL_SHA384: + return "TLS_RSA_PSK_WITH_NULL_SHA384"; + break; + case TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: + return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256"; + break; + case TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: + return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384"; + break; + case TLS_RSA_PSK_WITH_NULL_SHA256: + return "TLS_RSA_PSK_WITH_NULL_SHA256"; + break; + case TLS_RSA_PSK_WITH_NULL_SHA384: + return "TLS_RSA_PSK_WITH_NULL_SHA384"; + break; +#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ +#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 + /* New ChaCha20+Poly1305 cipher-suites used by TLS 1.3: */ + case TLS_AES_128_GCM_SHA256: + return "TLS_AES_128_GCM_SHA256"; + break; + case TLS_AES_256_GCM_SHA384: + return "TLS_AES_256_GCM_SHA384"; + break; + case TLS_CHACHA20_POLY1305_SHA256: + return "TLS_CHACHA20_POLY1305_SHA256"; + break; + case TLS_AES_128_CCM_SHA256: + return "TLS_AES_128_CCM_SHA256"; + break; + case TLS_AES_128_CCM_8_SHA256: + return "TLS_AES_128_CCM_8_SHA256"; + break; + case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + return "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"; + break; + case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: + return "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"; + break; +#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */ + } + return "TLS_NULL_WITH_NULL_NULL"; +} +#endif /* !CURL_DISABLE_VERBOSE_STRINGS */ + +#if CURL_BUILD_MAC +CF_INLINE void GetDarwinVersionNumber(int *major, int *minor) +{ + int mib[2]; + char *os_version; + size_t os_version_len; + char *os_version_major, *os_version_minor; + char *tok_buf; + + /* Get the Darwin kernel version from the kernel using sysctl(): */ + mib[0] = CTL_KERN; + mib[1] = KERN_OSRELEASE; + if(sysctl(mib, 2, NULL, &os_version_len, NULL, 0) == -1) + return; + os_version = malloc(os_version_len*sizeof(char)); + if(!os_version) + return; + if(sysctl(mib, 2, os_version, &os_version_len, NULL, 0) == -1) { + free(os_version); + return; + } + + /* Parse the version: */ + os_version_major = strtok_r(os_version, ".", &tok_buf); + os_version_minor = strtok_r(NULL, ".", &tok_buf); + *major = atoi(os_version_major); + *minor = atoi(os_version_minor); + free(os_version); +} +#endif /* CURL_BUILD_MAC */ + +/* Apple provides a myriad of ways of getting information about a certificate + into a string. Some aren't available under iOS or newer cats. So here's + a unified function for getting a string describing the certificate that + ought to work in all cats starting with Leopard. */ +CF_INLINE CFStringRef getsubject(SecCertificateRef cert) +{ + CFStringRef server_cert_summary = CFSTR("(null)"); + +#if CURL_BUILD_IOS + /* iOS: There's only one way to do this. */ + server_cert_summary = SecCertificateCopySubjectSummary(cert); +#else +#if CURL_BUILD_MAC_10_7 + /* Lion & later: Get the long description if we can. */ + if(SecCertificateCopyLongDescription != NULL) + server_cert_summary = + SecCertificateCopyLongDescription(NULL, cert, NULL); + else +#endif /* CURL_BUILD_MAC_10_7 */ +#if CURL_BUILD_MAC_10_6 + /* Snow Leopard: Get the certificate summary. */ + if(SecCertificateCopySubjectSummary != NULL) + server_cert_summary = SecCertificateCopySubjectSummary(cert); + else +#endif /* CURL_BUILD_MAC_10_6 */ + /* Leopard is as far back as we go... */ + (void)SecCertificateCopyCommonName(cert, &server_cert_summary); +#endif /* CURL_BUILD_IOS */ + return server_cert_summary; +} + +static CURLcode CopyCertSubject(struct Curl_easy *data, + SecCertificateRef cert, char **certp) +{ + CFStringRef c = getsubject(cert); + CURLcode result = CURLE_OK; + const char *direct; + char *cbuf = NULL; + *certp = NULL; + + if(!c) { + failf(data, "SSL: invalid CA certificate subject"); + return CURLE_PEER_FAILED_VERIFICATION; + } + + /* If the subject is already available as UTF-8 encoded (ie 'direct') then + use that, else convert it. */ + direct = CFStringGetCStringPtr(c, kCFStringEncodingUTF8); + if(direct) { + *certp = strdup(direct); + if(!*certp) { + failf(data, "SSL: out of memory"); + result = CURLE_OUT_OF_MEMORY; + } + } + else { + size_t cbuf_size = ((size_t)CFStringGetLength(c) * 4) + 1; + cbuf = calloc(cbuf_size, 1); + if(cbuf) { + if(!CFStringGetCString(c, cbuf, cbuf_size, + kCFStringEncodingUTF8)) { + failf(data, "SSL: invalid CA certificate subject"); + result = CURLE_PEER_FAILED_VERIFICATION; + } + else + /* pass back the buffer */ + *certp = cbuf; + } + else { + failf(data, "SSL: couldn't allocate %zu bytes of memory", cbuf_size); + result = CURLE_OUT_OF_MEMORY; + } + } + if(result) + free(cbuf); + CFRelease(c); + return result; +} + +#if CURL_SUPPORT_MAC_10_6 +/* The SecKeychainSearch API was deprecated in Lion, and using it will raise + deprecation warnings, so let's not compile this unless it's necessary: */ +static OSStatus CopyIdentityWithLabelOldSchool(char *label, + SecIdentityRef *out_c_a_k) +{ + OSStatus status = errSecItemNotFound; + SecKeychainAttributeList attr_list; + SecKeychainAttribute attr; + SecKeychainSearchRef search = NULL; + SecCertificateRef cert = NULL; + + /* Set up the attribute list: */ + attr_list.count = 1L; + attr_list.attr = &attr; + + /* Set up our lone search criterion: */ + attr.tag = kSecLabelItemAttr; + attr.data = label; + attr.length = (UInt32)strlen(label); + + /* Start searching: */ + status = SecKeychainSearchCreateFromAttributes(NULL, + kSecCertificateItemClass, + &attr_list, + &search); + if(status == noErr) { + status = SecKeychainSearchCopyNext(search, + (SecKeychainItemRef *)&cert); + if(status == noErr && cert) { + /* If we found a certificate, does it have a private key? */ + status = SecIdentityCreateWithCertificate(NULL, cert, out_c_a_k); + CFRelease(cert); + } + } + + if(search) + CFRelease(search); + return status; +} +#endif /* CURL_SUPPORT_MAC_10_6 */ + +static OSStatus CopyIdentityWithLabel(char *label, + SecIdentityRef *out_cert_and_key) +{ + OSStatus status = errSecItemNotFound; + +#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS + CFArrayRef keys_list; + CFIndex keys_list_count; + CFIndex i; + CFStringRef common_name; + + /* SecItemCopyMatching() was introduced in iOS and Snow Leopard. + kSecClassIdentity was introduced in Lion. If both exist, let's use them + to find the certificate. */ + if(SecItemCopyMatching != NULL && kSecClassIdentity != NULL) { + CFTypeRef keys[5]; + CFTypeRef values[5]; + CFDictionaryRef query_dict; + CFStringRef label_cf = CFStringCreateWithCString(NULL, label, + kCFStringEncodingUTF8); + + /* Set up our search criteria and expected results: */ + values[0] = kSecClassIdentity; /* we want a certificate and a key */ + keys[0] = kSecClass; + values[1] = kCFBooleanTrue; /* we want a reference */ + keys[1] = kSecReturnRef; + values[2] = kSecMatchLimitAll; /* kSecMatchLimitOne would be better if the + * label matching below worked correctly */ + keys[2] = kSecMatchLimit; + /* identity searches need a SecPolicyRef in order to work */ + values[3] = SecPolicyCreateSSL(false, NULL); + keys[3] = kSecMatchPolicy; + /* match the name of the certificate (doesn't work in macOS 10.12.1) */ + values[4] = label_cf; + keys[4] = kSecAttrLabel; + query_dict = CFDictionaryCreate(NULL, (const void **)keys, + (const void **)values, 5L, + &kCFCopyStringDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFRelease(values[3]); + + /* Do we have a match? */ + status = SecItemCopyMatching(query_dict, (CFTypeRef *) &keys_list); + + /* Because kSecAttrLabel matching doesn't work with kSecClassIdentity, + * we need to find the correct identity ourselves */ + if(status == noErr) { + keys_list_count = CFArrayGetCount(keys_list); + *out_cert_and_key = NULL; + status = 1; + for(i = 0; idata; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + long ssl_version = SSL_CONN_CONFIG(version); + long ssl_version_max = SSL_CONN_CONFIG(version_max); + long max_supported_version_by_os; + + /* macOS 10.5-10.7 supported TLS 1.0 only. + macOS 10.8 and later, and iOS 5 and later, added TLS 1.1 and 1.2. + macOS 10.13 and later, and iOS 11 and later, added TLS 1.3. */ +#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 + if(__builtin_available(macOS 10.13, iOS 11.0, *)) { + max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_3; + } + else { + max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_2; + } +#else + max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_2; +#endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && + HAVE_BUILTIN_AVAILABLE == 1 */ + + switch(ssl_version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + ssl_version = CURL_SSLVERSION_TLSv1_0; + break; + } + + switch(ssl_version_max) { + case CURL_SSLVERSION_MAX_NONE: + case CURL_SSLVERSION_MAX_DEFAULT: + ssl_version_max = max_supported_version_by_os; + break; + } + +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + if(SSLSetProtocolVersionMax != NULL) { + SSLProtocol darwin_ver_min = kTLSProtocol1; + SSLProtocol darwin_ver_max = kTLSProtocol1; + CURLcode result = sectransp_version_from_curl(&darwin_ver_min, + ssl_version); + if(result) { + failf(data, "unsupported min version passed via CURLOPT_SSLVERSION"); + return result; + } + result = sectransp_version_from_curl(&darwin_ver_max, + ssl_version_max >> 16); + if(result) { + failf(data, "unsupported max version passed via CURLOPT_SSLVERSION"); + return result; + } + + (void)SSLSetProtocolVersionMin(BACKEND->ssl_ctx, darwin_ver_min); + (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, darwin_ver_max); + return result; + } + else { +#if CURL_SUPPORT_MAC_10_8 + long i = ssl_version; + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kSSLProtocolAll, + false); + for(; i <= (ssl_version_max >> 16); i++) { + switch(i) { + case CURL_SSLVERSION_TLSv1_0: + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kTLSProtocol1, + true); + break; + case CURL_SSLVERSION_TLSv1_1: + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kTLSProtocol11, + true); + break; + case CURL_SSLVERSION_TLSv1_2: + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kTLSProtocol12, + true); + break; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "Your version of the OS does not support TLSv1.3"); + return CURLE_SSL_CONNECT_ERROR; + } + } + return CURLE_OK; +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ + failf(data, "Secure Transport: cannot set SSL protocol"); + return CURLE_SSL_CONNECT_ERROR; +} + + +static CURLcode sectransp_connect_step1(struct connectdata *conn, + int sockindex) +{ + struct Curl_easy *data = conn->data; + curl_socket_t sockfd = conn->sock[sockindex]; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); + const bool verifypeer = SSL_CONN_CONFIG(verifypeer); + char * const ssl_cert = SSL_SET_OPTION(cert); + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; +#ifdef ENABLE_IPV6 + struct in6_addr addr; +#else + struct in_addr addr; +#endif /* ENABLE_IPV6 */ + size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i; + SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL; + OSStatus err = noErr; +#if CURL_BUILD_MAC + int darwinver_maj = 0, darwinver_min = 0; + + GetDarwinVersionNumber(&darwinver_maj, &darwinver_min); +#endif /* CURL_BUILD_MAC */ + +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + if(SSLCreateContext != NULL) { /* use the newer API if available */ + if(BACKEND->ssl_ctx) + CFRelease(BACKEND->ssl_ctx); + BACKEND->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType); + if(!BACKEND->ssl_ctx) { + failf(data, "SSL: couldn't create a context!"); + return CURLE_OUT_OF_MEMORY; + } + } + else { + /* The old ST API does not exist under iOS, so don't compile it: */ +#if CURL_SUPPORT_MAC_10_8 + if(BACKEND->ssl_ctx) + (void)SSLDisposeContext(BACKEND->ssl_ctx); + err = SSLNewContext(false, &(BACKEND->ssl_ctx)); + if(err != noErr) { + failf(data, "SSL: couldn't create a context: OSStatus %d", err); + return CURLE_OUT_OF_MEMORY; + } +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#else + if(BACKEND->ssl_ctx) + (void)SSLDisposeContext(BACKEND->ssl_ctx); + err = SSLNewContext(false, &(BACKEND->ssl_ctx)); + if(err != noErr) { + failf(data, "SSL: couldn't create a context: OSStatus %d", err); + return CURLE_OUT_OF_MEMORY; + } +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ + BACKEND->ssl_write_buffered_length = 0UL; /* reset buffered write length */ + + /* check to see if we've been told to use an explicit SSL/TLS version */ +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + if(SSLSetProtocolVersionMax != NULL) { + switch(conn->ssl_config.version) { + case CURL_SSLVERSION_TLSv1: + (void)SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kTLSProtocol1); +#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 + if(__builtin_available(macOS 10.13, iOS 11.0, *)) { + (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol13); + } + else { + (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol12); + } +#else + (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol12); +#endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && + HAVE_BUILTIN_AVAILABLE == 1 */ + break; + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: + { + CURLcode result = set_ssl_version_min_max(conn, sockindex); + if(result != CURLE_OK) + return result; + break; + } + case CURL_SSLVERSION_SSLv3: + err = SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kSSLProtocol3); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv3"); + return CURLE_SSL_CONNECT_ERROR; + } + (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kSSLProtocol3); + break; + case CURL_SSLVERSION_SSLv2: + err = SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kSSLProtocol2); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kSSLProtocol2); + break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + } + else { +#if CURL_SUPPORT_MAC_10_8 + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kSSLProtocolAll, + false); + switch(conn->ssl_config.version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kTLSProtocol1, + true); + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kTLSProtocol11, + true); + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kTLSProtocol12, + true); + break; + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: + { + CURLcode result = set_ssl_version_min_max(conn, sockindex); + if(result != CURLE_OK) + return result; + break; + } + case CURL_SSLVERSION_SSLv3: + err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kSSLProtocol3, + true); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv3"); + return CURLE_SSL_CONNECT_ERROR; + } + break; + case CURL_SSLVERSION_SSLv2: + err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kSSLProtocol2, + true); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#else + if(conn->ssl_config.version_max != CURL_SSLVERSION_MAX_NONE) { + failf(data, "Your version of the OS does not support to set maximum" + " SSL/TLS version"); + return CURLE_SSL_CONNECT_ERROR; + } + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, kSSLProtocolAll, false); + switch(conn->ssl_config.version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + case CURL_SSLVERSION_TLSv1_0: + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kTLSProtocol1, + true); + break; + case CURL_SSLVERSION_TLSv1_1: + failf(data, "Your version of the OS does not support TLSv1.1"); + return CURLE_SSL_CONNECT_ERROR; + case CURL_SSLVERSION_TLSv1_2: + failf(data, "Your version of the OS does not support TLSv1.2"); + return CURLE_SSL_CONNECT_ERROR; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "Your version of the OS does not support TLSv1.3"); + return CURLE_SSL_CONNECT_ERROR; + case CURL_SSLVERSION_SSLv2: + err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kSSLProtocol2, + true); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + break; + case CURL_SSLVERSION_SSLv3: + err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kSSLProtocol3, + true); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv3"); + return CURLE_SSL_CONNECT_ERROR; + } + break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ + +#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 + if(conn->bits.tls_enable_alpn) { + if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) { + CFMutableArrayRef alpnArr = CFArrayCreateMutable(NULL, 0, + &kCFTypeArrayCallBacks); + +#ifdef USE_NGHTTP2 + if(data->set.httpversion >= CURL_HTTP_VERSION_2 && + (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) { + CFArrayAppendValue(alpnArr, CFSTR(NGHTTP2_PROTO_VERSION_ID)); + infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + } +#endif + + CFArrayAppendValue(alpnArr, CFSTR(ALPN_HTTP_1_1)); + infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); + + /* expects length prefixed preference ordered list of protocols in wire + * format + */ + err = SSLSetALPNProtocols(BACKEND->ssl_ctx, alpnArr); + if(err != noErr) + infof(data, "WARNING: failed to set ALPN protocols; OSStatus %d\n", + err); + CFRelease(alpnArr); + } + } +#endif + + if(SSL_SET_OPTION(key)) { + infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure " + "Transport. The private key must be in the Keychain.\n"); + } + + if(ssl_cert) { + SecIdentityRef cert_and_key = NULL; + bool is_cert_file = is_file(ssl_cert); + + /* User wants to authenticate with a client cert. Look for it: + If we detect that this is a file on disk, then let's load it. + Otherwise, assume that the user wants to use an identity loaded + from the Keychain. */ + if(is_cert_file) { + if(!SSL_SET_OPTION(cert_type)) + infof(data, "WARNING: SSL: Certificate type not set, assuming " + "PKCS#12 format.\n"); + else if(strncmp(SSL_SET_OPTION(cert_type), "P12", + strlen(SSL_SET_OPTION(cert_type))) != 0) + infof(data, "WARNING: SSL: The Security framework only supports " + "loading identities that are in PKCS#12 format.\n"); + + err = CopyIdentityFromPKCS12File(ssl_cert, + SSL_SET_OPTION(key_passwd), &cert_and_key); + } + else + err = CopyIdentityWithLabel(ssl_cert, &cert_and_key); + + if(err == noErr && cert_and_key) { + SecCertificateRef cert = NULL; + CFTypeRef certs_c[1]; + CFArrayRef certs; + + /* If we found one, print it out: */ + err = SecIdentityCopyCertificate(cert_and_key, &cert); + if(err == noErr) { + char *certp; + CURLcode result = CopyCertSubject(data, cert, &certp); + if(!result) { + infof(data, "Client certificate: %s\n", certp); + free(certp); + } + + CFRelease(cert); + if(result == CURLE_PEER_FAILED_VERIFICATION) + return CURLE_SSL_CERTPROBLEM; + if(result) + return result; + } + certs_c[0] = cert_and_key; + certs = CFArrayCreate(NULL, (const void **)certs_c, 1L, + &kCFTypeArrayCallBacks); + err = SSLSetCertificate(BACKEND->ssl_ctx, certs); + if(certs) + CFRelease(certs); + if(err != noErr) { + failf(data, "SSL: SSLSetCertificate() failed: OSStatus %d", err); + return CURLE_SSL_CERTPROBLEM; + } + CFRelease(cert_and_key); + } + else { + switch(err) { + case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */ + failf(data, "SSL: Incorrect password for the certificate \"%s\" " + "and its private key.", ssl_cert); + break; + case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */ + failf(data, "SSL: Couldn't make sense of the data in the " + "certificate \"%s\" and its private key.", + ssl_cert); + break; + case -25260: /* errSecPassphraseRequired */ + failf(data, "SSL The certificate \"%s\" requires a password.", + ssl_cert); + break; + case errSecItemNotFound: + failf(data, "SSL: Can't find the certificate \"%s\" and its private " + "key in the Keychain.", ssl_cert); + break; + default: + failf(data, "SSL: Can't load the certificate \"%s\" and its private " + "key: OSStatus %d", ssl_cert, err); + break; + } + return CURLE_SSL_CERTPROBLEM; + } + } + + /* SSL always tries to verify the peer, this only says whether it should + * fail to connect if the verification fails, or if it should continue + * anyway. In the latter case the result of the verification is checked with + * SSL_get_verify_result() below. */ +#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS + /* Snow Leopard introduced the SSLSetSessionOption() function, but due to + a library bug with the way the kSSLSessionOptionBreakOnServerAuth flag + works, it doesn't work as expected under Snow Leopard, Lion or + Mountain Lion. + So we need to call SSLSetEnableCertVerify() on those older cats in order + to disable certificate validation if the user turned that off. + (SecureTransport will always validate the certificate chain by + default.) + Note: + Darwin 11.x.x is Lion (10.7) + Darwin 12.x.x is Mountain Lion (10.8) + Darwin 13.x.x is Mavericks (10.9) + Darwin 14.x.x is Yosemite (10.10) + Darwin 15.x.x is El Capitan (10.11) + */ +#if CURL_BUILD_MAC + if(SSLSetSessionOption != NULL && darwinver_maj >= 13) { +#else + if(SSLSetSessionOption != NULL) { +#endif /* CURL_BUILD_MAC */ + bool break_on_auth = !conn->ssl_config.verifypeer || ssl_cafile; + err = SSLSetSessionOption(BACKEND->ssl_ctx, + kSSLSessionOptionBreakOnServerAuth, + break_on_auth); + if(err != noErr) { + failf(data, "SSL: SSLSetSessionOption() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + } + else { +#if CURL_SUPPORT_MAC_10_8 + err = SSLSetEnableCertVerify(BACKEND->ssl_ctx, + conn->ssl_config.verifypeer?true:false); + if(err != noErr) { + failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#else + err = SSLSetEnableCertVerify(BACKEND->ssl_ctx, + conn->ssl_config.verifypeer?true:false); + if(err != noErr) { + failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } +#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */ + + if(ssl_cafile && verifypeer) { + bool is_cert_file = is_file(ssl_cafile); + + if(!is_cert_file) { + failf(data, "SSL: can't load CA certificate file %s", ssl_cafile); + return CURLE_SSL_CACERT_BADFILE; + } + } + + /* Configure hostname check. SNI is used if available. + * Both hostname check and SNI require SSLSetPeerDomainName(). + * Also: the verifyhost setting influences SNI usage */ + if(conn->ssl_config.verifyhost) { + err = SSLSetPeerDomainName(BACKEND->ssl_ctx, hostname, + strlen(hostname)); + + if(err != noErr) { + infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d\n", + err); + } + + if((Curl_inet_pton(AF_INET, hostname, &addr)) + #ifdef ENABLE_IPV6 + || (Curl_inet_pton(AF_INET6, hostname, &addr)) + #endif + ) { + infof(data, "WARNING: using IP address, SNI is being disabled by " + "the OS.\n"); + } + } + else { + infof(data, "WARNING: disabling hostname validation also disables SNI.\n"); + } + + /* Disable cipher suites that ST supports but are not safe. These ciphers + are unlikely to be used in any case since ST gives other ciphers a much + higher priority, but it's probably better that we not connect at all than + to give the user a false sense of security if the server only supports + insecure ciphers. (Note: We don't care about SSLv2-only ciphers.) */ + err = SSLGetNumberSupportedCiphers(BACKEND->ssl_ctx, &all_ciphers_count); + if(err != noErr) { + failf(data, "SSL: SSLGetNumberSupportedCiphers() failed: OSStatus %d", + err); + return CURLE_SSL_CIPHER; + } + all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite)); + if(!all_ciphers) { + failf(data, "SSL: Failed to allocate memory for all ciphers"); + return CURLE_OUT_OF_MEMORY; + } + allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite)); + if(!allowed_ciphers) { + Curl_safefree(all_ciphers); + failf(data, "SSL: Failed to allocate memory for allowed ciphers"); + return CURLE_OUT_OF_MEMORY; + } + err = SSLGetSupportedCiphers(BACKEND->ssl_ctx, all_ciphers, + &all_ciphers_count); + if(err != noErr) { + Curl_safefree(all_ciphers); + Curl_safefree(allowed_ciphers); + return CURLE_SSL_CIPHER; + } + for(i = 0UL ; i < all_ciphers_count ; i++) { +#if CURL_BUILD_MAC + /* There's a known bug in early versions of Mountain Lion where ST's ECC + ciphers (cipher suite 0xC001 through 0xC032) simply do not work. + Work around the problem here by disabling those ciphers if we are + running in an affected version of OS X. */ + if(darwinver_maj == 12 && darwinver_min <= 3 && + all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) { + continue; + } +#endif /* CURL_BUILD_MAC */ + switch(all_ciphers[i]) { + /* Disable NULL ciphersuites: */ + case SSL_NULL_WITH_NULL_NULL: + case SSL_RSA_WITH_NULL_MD5: + case SSL_RSA_WITH_NULL_SHA: + case 0x003B: /* TLS_RSA_WITH_NULL_SHA256 */ + case SSL_FORTEZZA_DMS_WITH_NULL_SHA: + case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */ + case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */ + case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */ + case 0xC010: /* TLS_ECDHE_RSA_WITH_NULL_SHA */ + case 0x002C: /* TLS_PSK_WITH_NULL_SHA */ + case 0x002D: /* TLS_DHE_PSK_WITH_NULL_SHA */ + case 0x002E: /* TLS_RSA_PSK_WITH_NULL_SHA */ + case 0x00B0: /* TLS_PSK_WITH_NULL_SHA256 */ + case 0x00B1: /* TLS_PSK_WITH_NULL_SHA384 */ + case 0x00B4: /* TLS_DHE_PSK_WITH_NULL_SHA256 */ + case 0x00B5: /* TLS_DHE_PSK_WITH_NULL_SHA384 */ + case 0x00B8: /* TLS_RSA_PSK_WITH_NULL_SHA256 */ + case 0x00B9: /* TLS_RSA_PSK_WITH_NULL_SHA384 */ + /* Disable anonymous ciphersuites: */ + case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: + case SSL_DH_anon_WITH_RC4_128_MD5: + case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: + case SSL_DH_anon_WITH_DES_CBC_SHA: + case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: + case TLS_DH_anon_WITH_AES_128_CBC_SHA: + case TLS_DH_anon_WITH_AES_256_CBC_SHA: + case 0xC015: /* TLS_ECDH_anon_WITH_NULL_SHA */ + case 0xC016: /* TLS_ECDH_anon_WITH_RC4_128_SHA */ + case 0xC017: /* TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA */ + case 0xC018: /* TLS_ECDH_anon_WITH_AES_128_CBC_SHA */ + case 0xC019: /* TLS_ECDH_anon_WITH_AES_256_CBC_SHA */ + case 0x006C: /* TLS_DH_anon_WITH_AES_128_CBC_SHA256 */ + case 0x006D: /* TLS_DH_anon_WITH_AES_256_CBC_SHA256 */ + case 0x00A6: /* TLS_DH_anon_WITH_AES_128_GCM_SHA256 */ + case 0x00A7: /* TLS_DH_anon_WITH_AES_256_GCM_SHA384 */ + /* Disable weak key ciphersuites: */ + case SSL_RSA_EXPORT_WITH_RC4_40_MD5: + case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: + case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: + case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: + case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: + case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: + case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: + case SSL_RSA_WITH_DES_CBC_SHA: + case SSL_DH_DSS_WITH_DES_CBC_SHA: + case SSL_DH_RSA_WITH_DES_CBC_SHA: + case SSL_DHE_DSS_WITH_DES_CBC_SHA: + case SSL_DHE_RSA_WITH_DES_CBC_SHA: + /* Disable IDEA: */ + case SSL_RSA_WITH_IDEA_CBC_SHA: + case SSL_RSA_WITH_IDEA_CBC_MD5: + /* Disable RC4: */ + case SSL_RSA_WITH_RC4_128_MD5: + case SSL_RSA_WITH_RC4_128_SHA: + case 0xC002: /* TLS_ECDH_ECDSA_WITH_RC4_128_SHA */ + case 0xC007: /* TLS_ECDHE_ECDSA_WITH_RC4_128_SHA*/ + case 0xC00C: /* TLS_ECDH_RSA_WITH_RC4_128_SHA */ + case 0xC011: /* TLS_ECDHE_RSA_WITH_RC4_128_SHA */ + case 0x008A: /* TLS_PSK_WITH_RC4_128_SHA */ + case 0x008E: /* TLS_DHE_PSK_WITH_RC4_128_SHA */ + case 0x0092: /* TLS_RSA_PSK_WITH_RC4_128_SHA */ + break; + default: /* enable everything else */ + allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i]; + break; + } + } + err = SSLSetEnabledCiphers(BACKEND->ssl_ctx, allowed_ciphers, + allowed_ciphers_count); + Curl_safefree(all_ciphers); + Curl_safefree(allowed_ciphers); + if(err != noErr) { + failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err); + return CURLE_SSL_CIPHER; + } + +#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 + /* We want to enable 1/n-1 when using a CBC cipher unless the user + specifically doesn't want us doing that: */ + if(SSLSetSessionOption != NULL) { + SSLSetSessionOption(BACKEND->ssl_ctx, kSSLSessionOptionSendOneByteRecord, + !data->set.ssl.enable_beast); + SSLSetSessionOption(BACKEND->ssl_ctx, kSSLSessionOptionFalseStart, + data->set.ssl.falsestart); /* false start support */ + } +#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ + + /* Check if there's a cached ID we can/should use here! */ + if(SSL_SET_OPTION(primary.sessionid)) { + char *ssl_sessionid; + size_t ssl_sessionid_len; + + Curl_ssl_sessionid_lock(conn); + if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid, + &ssl_sessionid_len, sockindex)) { + /* we got a session id, use it! */ + err = SSLSetPeerID(BACKEND->ssl_ctx, ssl_sessionid, ssl_sessionid_len); + Curl_ssl_sessionid_unlock(conn); + if(err != noErr) { + failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + /* Informational message */ + infof(data, "SSL re-using session ID\n"); + } + /* If there isn't one, then let's make one up! This has to be done prior + to starting the handshake. */ + else { + CURLcode result; + ssl_sessionid = + aprintf("%s:%d:%d:%s:%hu", ssl_cafile, + verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port); + ssl_sessionid_len = strlen(ssl_sessionid); + + err = SSLSetPeerID(BACKEND->ssl_ctx, ssl_sessionid, ssl_sessionid_len); + if(err != noErr) { + Curl_ssl_sessionid_unlock(conn); + failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + + result = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len, + sockindex); + Curl_ssl_sessionid_unlock(conn); + if(result) { + failf(data, "failed to store ssl session"); + return result; + } + } + } + + err = SSLSetIOFuncs(BACKEND->ssl_ctx, SocketRead, SocketWrite); + if(err != noErr) { + failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + + /* pass the raw socket into the SSL layers */ + /* We need to store the FD in a constant memory address, because + * SSLSetConnection() will not copy that address. I've found that + * conn->sock[sockindex] may change on its own. */ + BACKEND->ssl_sockfd = sockfd; + err = SSLSetConnection(BACKEND->ssl_ctx, connssl); + if(err != noErr) { + failf(data, "SSL: SSLSetConnection() failed: %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + + connssl->connecting_state = ssl_connect_2; + return CURLE_OK; +} + +static long pem_to_der(const char *in, unsigned char **out, size_t *outlen) +{ + char *sep_start, *sep_end, *cert_start, *cert_end; + size_t i, j, err; + size_t len; + unsigned char *b64; + + /* Jump through the separators at the beginning of the certificate. */ + sep_start = strstr(in, "-----"); + if(sep_start == NULL) + return 0; + cert_start = strstr(sep_start + 1, "-----"); + if(cert_start == NULL) + return -1; + + cert_start += 5; + + /* Find separator after the end of the certificate. */ + cert_end = strstr(cert_start, "-----"); + if(cert_end == NULL) + return -1; + + sep_end = strstr(cert_end + 1, "-----"); + if(sep_end == NULL) + return -1; + sep_end += 5; + + len = cert_end - cert_start; + b64 = malloc(len + 1); + if(!b64) + return -1; + + /* Create base64 string without linefeeds. */ + for(i = 0, j = 0; i < len; i++) { + if(cert_start[i] != '\r' && cert_start[i] != '\n') + b64[j++] = cert_start[i]; + } + b64[j] = '\0'; + + err = Curl_base64_decode((const char *)b64, out, outlen); + free(b64); + if(err) { + free(*out); + return -1; + } + + return sep_end - in; +} + +static int read_cert(const char *file, unsigned char **out, size_t *outlen) +{ + int fd; + ssize_t n, len = 0, cap = 512; + unsigned char buf[512], *data; + + fd = open(file, 0); + if(fd < 0) + return -1; + + data = malloc(cap); + if(!data) { + close(fd); + return -1; + } + + for(;;) { + n = read(fd, buf, sizeof(buf)); + if(n < 0) { + close(fd); + free(data); + return -1; + } + else if(n == 0) { + close(fd); + break; + } + + if(len + n >= cap) { + cap *= 2; + data = Curl_saferealloc(data, cap); + if(!data) { + close(fd); + return -1; + } + } + + memcpy(data + len, buf, n); + len += n; + } + data[len] = '\0'; + + *out = data; + *outlen = len; + + return 0; +} + +static int append_cert_to_array(struct Curl_easy *data, + unsigned char *buf, size_t buflen, + CFMutableArrayRef array) +{ + CFDataRef certdata = CFDataCreate(kCFAllocatorDefault, buf, buflen); + char *certp; + CURLcode result; + if(!certdata) { + failf(data, "SSL: failed to allocate array for CA certificate"); + return CURLE_OUT_OF_MEMORY; + } + + SecCertificateRef cacert = + SecCertificateCreateWithData(kCFAllocatorDefault, certdata); + CFRelease(certdata); + if(!cacert) { + failf(data, "SSL: failed to create SecCertificate from CA certificate"); + return CURLE_SSL_CACERT_BADFILE; + } + + /* Check if cacert is valid. */ + result = CopyCertSubject(data, cacert, &certp); + switch(result) { + case CURLE_OK: + break; + case CURLE_PEER_FAILED_VERIFICATION: + return CURLE_SSL_CACERT_BADFILE; + case CURLE_OUT_OF_MEMORY: + default: + return result; + } + free(certp); + + CFArrayAppendValue(array, cacert); + CFRelease(cacert); + + return CURLE_OK; +} + +static int verify_cert(const char *cafile, struct Curl_easy *data, + SSLContextRef ctx) +{ + int n = 0, rc; + long res; + unsigned char *certbuf, *der; + size_t buflen, derlen, offset = 0; + + if(read_cert(cafile, &certbuf, &buflen) < 0) { + failf(data, "SSL: failed to read or invalid CA certificate"); + return CURLE_SSL_CACERT_BADFILE; + } + + /* + * Certbuf now contains the contents of the certificate file, which can be + * - a single DER certificate, + * - a single PEM certificate or + * - a bunch of PEM certificates (certificate bundle). + * + * Go through certbuf, and convert any PEM certificate in it into DER + * format. + */ + CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeArrayCallBacks); + if(array == NULL) { + free(certbuf); + failf(data, "SSL: out of memory creating CA certificate array"); + return CURLE_OUT_OF_MEMORY; + } + + while(offset < buflen) { + n++; + + /* + * Check if the certificate is in PEM format, and convert it to DER. If + * this fails, we assume the certificate is in DER format. + */ + res = pem_to_der((const char *)certbuf + offset, &der, &derlen); + if(res < 0) { + free(certbuf); + CFRelease(array); + failf(data, "SSL: invalid CA certificate #%d (offset %d) in bundle", + n, offset); + return CURLE_SSL_CACERT_BADFILE; + } + offset += res; + + if(res == 0 && offset == 0) { + /* This is not a PEM file, probably a certificate in DER format. */ + rc = append_cert_to_array(data, certbuf, buflen, array); + free(certbuf); + if(rc != CURLE_OK) { + CFRelease(array); + return rc; + } + break; + } + else if(res == 0) { + /* No more certificates in the bundle. */ + free(certbuf); + break; + } + + rc = append_cert_to_array(data, der, derlen, array); + free(der); + if(rc != CURLE_OK) { + free(certbuf); + CFRelease(array); + return rc; + } + } + + SecTrustRef trust; + OSStatus ret = SSLCopyPeerTrust(ctx, &trust); + if(trust == NULL) { + failf(data, "SSL: error getting certificate chain"); + CFRelease(array); + return CURLE_PEER_FAILED_VERIFICATION; + } + else if(ret != noErr) { + CFRelease(array); + failf(data, "SSLCopyPeerTrust() returned error %d", ret); + return CURLE_PEER_FAILED_VERIFICATION; + } + + ret = SecTrustSetAnchorCertificates(trust, array); + if(ret != noErr) { + CFRelease(array); + CFRelease(trust); + failf(data, "SecTrustSetAnchorCertificates() returned error %d", ret); + return CURLE_PEER_FAILED_VERIFICATION; + } + ret = SecTrustSetAnchorCertificatesOnly(trust, true); + if(ret != noErr) { + CFRelease(array); + CFRelease(trust); + failf(data, "SecTrustSetAnchorCertificatesOnly() returned error %d", ret); + return CURLE_PEER_FAILED_VERIFICATION; + } + + SecTrustResultType trust_eval = 0; + ret = SecTrustEvaluate(trust, &trust_eval); + CFRelease(array); + CFRelease(trust); + if(ret != noErr) { + failf(data, "SecTrustEvaluate() returned error %d", ret); + return CURLE_PEER_FAILED_VERIFICATION; + } + + switch(trust_eval) { + case kSecTrustResultUnspecified: + case kSecTrustResultProceed: + return CURLE_OK; + + case kSecTrustResultRecoverableTrustFailure: + case kSecTrustResultDeny: + default: + failf(data, "SSL: certificate verification failed (result: %d)", + trust_eval); + return CURLE_PEER_FAILED_VERIFICATION; + } +} + +#ifdef SECTRANSP_PINNEDPUBKEY +static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, + SSLContextRef ctx, + const char *pinnedpubkey) +{ /* Scratch */ + size_t pubkeylen, realpubkeylen, spkiHeaderLength = 24; + unsigned char *pubkey = NULL, *realpubkey = NULL; + const unsigned char *spkiHeader = NULL; + CFDataRef publicKeyBits = NULL; + + /* Result is returned to caller */ + CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; + + /* if a path wasn't specified, don't pin */ + if(!pinnedpubkey) + return CURLE_OK; + + + if(!ctx) + return result; + + do { + SecTrustRef trust; + OSStatus ret = SSLCopyPeerTrust(ctx, &trust); + if(ret != noErr || trust == NULL) + break; + + SecKeyRef keyRef = SecTrustCopyPublicKey(trust); + CFRelease(trust); + if(keyRef == NULL) + break; + +#ifdef SECTRANSP_PINNEDPUBKEY_V1 + + publicKeyBits = SecKeyCopyExternalRepresentation(keyRef, NULL); + CFRelease(keyRef); + if(publicKeyBits == NULL) + break; + +#elif SECTRANSP_PINNEDPUBKEY_V2 + + OSStatus success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL, + &publicKeyBits); + CFRelease(keyRef); + if(success != errSecSuccess || publicKeyBits == NULL) + break; + +#endif /* SECTRANSP_PINNEDPUBKEY_V2 */ + + pubkeylen = CFDataGetLength(publicKeyBits); + pubkey = (unsigned char *)CFDataGetBytePtr(publicKeyBits); + + switch(pubkeylen) { + case 526: + /* 4096 bit RSA pubkeylen == 526 */ + spkiHeader = rsa4096SpkiHeader; + break; + case 270: + /* 2048 bit RSA pubkeylen == 270 */ + spkiHeader = rsa2048SpkiHeader; + break; +#ifdef SECTRANSP_PINNEDPUBKEY_V1 + case 65: + /* ecDSA secp256r1 pubkeylen == 65 */ + spkiHeader = ecDsaSecp256r1SpkiHeader; + spkiHeaderLength = 26; + break; + case 97: + /* ecDSA secp384r1 pubkeylen == 97 */ + spkiHeader = ecDsaSecp384r1SpkiHeader; + spkiHeaderLength = 23; + break; + default: + infof(data, "SSL: unhandled public key length: %d\n", pubkeylen); +#elif SECTRANSP_PINNEDPUBKEY_V2 + default: + /* ecDSA secp256r1 pubkeylen == 91 header already included? + * ecDSA secp384r1 header already included too + * we assume rest of algorithms do same, so do nothing + */ + result = Curl_pin_peer_pubkey(data, pinnedpubkey, pubkey, + pubkeylen); +#endif /* SECTRANSP_PINNEDPUBKEY_V2 */ + continue; /* break from loop */ + } + + realpubkeylen = pubkeylen + spkiHeaderLength; + realpubkey = malloc(realpubkeylen); + if(!realpubkey) + break; + + memcpy(realpubkey, spkiHeader, spkiHeaderLength); + memcpy(realpubkey + spkiHeaderLength, pubkey, pubkeylen); + + result = Curl_pin_peer_pubkey(data, pinnedpubkey, realpubkey, + realpubkeylen); + + } while(0); + + Curl_safefree(realpubkey); + if(publicKeyBits != NULL) + CFRelease(publicKeyBits); + + return result; +} +#endif /* SECTRANSP_PINNEDPUBKEY */ + +static CURLcode +sectransp_connect_step2(struct connectdata *conn, int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + OSStatus err; + SSLCipherSuite cipher; + SSLProtocol protocol = 0; + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + + DEBUGASSERT(ssl_connect_2 == connssl->connecting_state + || ssl_connect_2_reading == connssl->connecting_state + || ssl_connect_2_writing == connssl->connecting_state); + + /* Here goes nothing: */ + err = SSLHandshake(BACKEND->ssl_ctx); + + if(err != noErr) { + switch(err) { + case errSSLWouldBlock: /* they're not done with us yet */ + connssl->connecting_state = BACKEND->ssl_direction ? + ssl_connect_2_writing : ssl_connect_2_reading; + return CURLE_OK; + + /* The below is errSSLServerAuthCompleted; it's not defined in + Leopard's headers */ + case -9841: + if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) { + int res = verify_cert(SSL_CONN_CONFIG(CAfile), data, + BACKEND->ssl_ctx); + if(res != CURLE_OK) + return res; + } + /* the documentation says we need to call SSLHandshake() again */ + return sectransp_connect_step2(conn, sockindex); + + /* Problem with encrypt / decrypt */ + case errSSLPeerDecodeError: + failf(data, "Decode failed"); + break; + case errSSLDecryptionFail: + case errSSLPeerDecryptionFail: + failf(data, "Decryption failed"); + break; + case errSSLPeerDecryptError: + failf(data, "A decryption error occurred"); + break; + case errSSLBadCipherSuite: + failf(data, "A bad SSL cipher suite was encountered"); + break; + case errSSLCrypto: + failf(data, "An underlying cryptographic error was encountered"); + break; +#if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9 + case errSSLWeakPeerEphemeralDHKey: + failf(data, "Indicates a weak ephemeral Diffie-Hellman key"); + break; +#endif + + /* Problem with the message record validation */ + case errSSLBadRecordMac: + case errSSLPeerBadRecordMac: + failf(data, "A record with a bad message authentication code (MAC) " + "was encountered"); + break; + case errSSLRecordOverflow: + case errSSLPeerRecordOverflow: + failf(data, "A record overflow occurred"); + break; + + /* Problem with zlib decompression */ + case errSSLPeerDecompressFail: + failf(data, "Decompression failed"); + break; + + /* Problem with access */ + case errSSLPeerAccessDenied: + failf(data, "Access was denied"); + break; + case errSSLPeerInsufficientSecurity: + failf(data, "There is insufficient security for this operation"); + break; + + /* These are all certificate problems with the server: */ + case errSSLXCertChainInvalid: + failf(data, "SSL certificate problem: Invalid certificate chain"); + return CURLE_PEER_FAILED_VERIFICATION; + case errSSLUnknownRootCert: + failf(data, "SSL certificate problem: Untrusted root certificate"); + return CURLE_PEER_FAILED_VERIFICATION; + case errSSLNoRootCert: + failf(data, "SSL certificate problem: No root certificate"); + return CURLE_PEER_FAILED_VERIFICATION; + case errSSLCertNotYetValid: + failf(data, "SSL certificate problem: The certificate chain had a " + "certificate that is not yet valid"); + return CURLE_PEER_FAILED_VERIFICATION; + case errSSLCertExpired: + case errSSLPeerCertExpired: + failf(data, "SSL certificate problem: Certificate chain had an " + "expired certificate"); + return CURLE_PEER_FAILED_VERIFICATION; + case errSSLBadCert: + case errSSLPeerBadCert: + failf(data, "SSL certificate problem: Couldn't understand the server " + "certificate format"); + return CURLE_PEER_FAILED_VERIFICATION; + case errSSLPeerUnsupportedCert: + failf(data, "SSL certificate problem: An unsupported certificate " + "format was encountered"); + return CURLE_PEER_FAILED_VERIFICATION; + case errSSLPeerCertRevoked: + failf(data, "SSL certificate problem: The certificate was revoked"); + return CURLE_PEER_FAILED_VERIFICATION; + case errSSLPeerCertUnknown: + failf(data, "SSL certificate problem: The certificate is unknown"); + return CURLE_PEER_FAILED_VERIFICATION; + + /* These are all certificate problems with the client: */ + case errSecAuthFailed: + failf(data, "SSL authentication failed"); + break; + case errSSLPeerHandshakeFail: + failf(data, "SSL peer handshake failed, the server most likely " + "requires a client certificate to connect"); + break; + case errSSLPeerUnknownCA: + failf(data, "SSL server rejected the client certificate due to " + "the certificate being signed by an unknown certificate " + "authority"); + break; + + /* This error is raised if the server's cert didn't match the server's + host name: */ + case errSSLHostNameMismatch: + failf(data, "SSL certificate peer verification failed, the " + "certificate did not match \"%s\"\n", conn->host.dispname); + return CURLE_PEER_FAILED_VERIFICATION; + + /* Problem with SSL / TLS negotiation */ + case errSSLNegotiation: + failf(data, "Could not negotiate an SSL cipher suite with the server"); + break; + case errSSLBadConfiguration: + failf(data, "A configuration error occurred"); + break; + case errSSLProtocol: + failf(data, "SSL protocol error"); + break; + case errSSLPeerProtocolVersion: + failf(data, "A bad protocol version was encountered"); + break; + case errSSLPeerNoRenegotiation: + failf(data, "No renegotiation is allowed"); + break; + + /* Generic handshake errors: */ + case errSSLConnectionRefused: + failf(data, "Server dropped the connection during the SSL handshake"); + break; + case errSSLClosedAbort: + failf(data, "Server aborted the SSL handshake"); + break; + case errSSLClosedGraceful: + failf(data, "The connection closed gracefully"); + break; + case errSSLClosedNoNotify: + failf(data, "The server closed the session with no notification"); + break; + /* Sometimes paramErr happens with buggy ciphers: */ + case paramErr: + case errSSLInternal: + case errSSLPeerInternalError: + failf(data, "Internal SSL engine error encountered during the " + "SSL handshake"); + break; + case errSSLFatalAlert: + failf(data, "Fatal SSL engine error encountered during the SSL " + "handshake"); + break; + /* Unclassified error */ + case errSSLBufferOverflow: + failf(data, "An insufficient buffer was provided"); + break; + case errSSLIllegalParam: + failf(data, "An illegal parameter was encountered"); + break; + case errSSLModuleAttach: + failf(data, "Module attach failure"); + break; + case errSSLSessionNotFound: + failf(data, "An attempt to restore an unknown session failed"); + break; + case errSSLPeerExportRestriction: + failf(data, "An export restriction occurred"); + break; + case errSSLPeerUserCancelled: + failf(data, "The user canceled the operation"); + break; + case errSSLPeerUnexpectedMsg: + failf(data, "Peer rejected unexpected message"); + break; +#if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9 + /* Treaing non-fatal error as fatal like before */ + case errSSLClientHelloReceived: + failf(data, "A non-fatal result for providing a server name " + "indication"); + break; +#endif + + /* Error codes defined in the enum but should never be returned. + We list them here just in case. */ +#if CURL_BUILD_MAC_10_6 + /* Only returned when kSSLSessionOptionBreakOnCertRequested is set */ + case errSSLClientCertRequested: + failf(data, "The server has requested a client certificate"); + break; +#endif +#if CURL_BUILD_MAC_10_9 + /* Alias for errSSLLast, end of error range */ + case errSSLUnexpectedRecord: + failf(data, "Unexpected (skipped) record in DTLS"); + break; +#endif + default: + /* May also return codes listed in Security Framework Result Codes */ + failf(data, "Unknown SSL protocol error in connection to %s:%d", + hostname, err); + break; + } + return CURLE_SSL_CONNECT_ERROR; + } + else { + /* we have been connected fine, we're not waiting for anything else. */ + connssl->connecting_state = ssl_connect_3; + +#ifdef SECTRANSP_PINNEDPUBKEY + if(data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]) { + CURLcode result = pkp_pin_peer_pubkey(data, BACKEND->ssl_ctx, + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]); + if(result) { + failf(data, "SSL: public key does not match pinned public key!"); + return result; + } + } +#endif /* SECTRANSP_PINNEDPUBKEY */ + + /* Informational message */ + (void)SSLGetNegotiatedCipher(BACKEND->ssl_ctx, &cipher); + (void)SSLGetNegotiatedProtocolVersion(BACKEND->ssl_ctx, &protocol); + switch(protocol) { + case kSSLProtocol2: + infof(data, "SSL 2.0 connection using %s\n", + SSLCipherNameForNumber(cipher)); + break; + case kSSLProtocol3: + infof(data, "SSL 3.0 connection using %s\n", + SSLCipherNameForNumber(cipher)); + break; + case kTLSProtocol1: + infof(data, "TLS 1.0 connection using %s\n", + TLSCipherNameForNumber(cipher)); + break; +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + case kTLSProtocol11: + infof(data, "TLS 1.1 connection using %s\n", + TLSCipherNameForNumber(cipher)); + break; + case kTLSProtocol12: + infof(data, "TLS 1.2 connection using %s\n", + TLSCipherNameForNumber(cipher)); + break; +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ +#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 + case kTLSProtocol13: + infof(data, "TLS 1.3 connection using %s\n", + TLSCipherNameForNumber(cipher)); + break; +#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */ + default: + infof(data, "Unknown protocol connection\n"); + break; + } + +#if(CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 + if(conn->bits.tls_enable_alpn) { + if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) { + CFArrayRef alpnArr = NULL; + CFStringRef chosenProtocol = NULL; + err = SSLCopyALPNProtocols(BACKEND->ssl_ctx, &alpnArr); + + if(err == noErr && alpnArr && CFArrayGetCount(alpnArr) >= 1) + chosenProtocol = CFArrayGetValueAtIndex(alpnArr, 0); + +#ifdef USE_NGHTTP2 + if(chosenProtocol && + !CFStringCompare(chosenProtocol, CFSTR(NGHTTP2_PROTO_VERSION_ID), + 0)) { + conn->negnpn = CURL_HTTP_VERSION_2; + } + else +#endif + if(chosenProtocol && + !CFStringCompare(chosenProtocol, CFSTR(ALPN_HTTP_1_1), 0)) { + conn->negnpn = CURL_HTTP_VERSION_1_1; + } + else + infof(data, "ALPN, server did not agree to a protocol\n"); + + Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); + + /* chosenProtocol is a reference to the string within alpnArr + and doesn't need to be freed separately */ + if(alpnArr) + CFRelease(alpnArr); + } + } +#endif + + return CURLE_OK; + } +} + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +/* This should be called during step3 of the connection at the earliest */ +static void +show_verbose_server_cert(struct connectdata *conn, + int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + CFArrayRef server_certs = NULL; + SecCertificateRef server_cert; + OSStatus err; + CFIndex i, count; + SecTrustRef trust = NULL; + + if(!BACKEND->ssl_ctx) + return; + +#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS +#if CURL_BUILD_IOS +#pragma unused(server_certs) + err = SSLCopyPeerTrust(BACKEND->ssl_ctx, &trust); + /* For some reason, SSLCopyPeerTrust() can return noErr and yet return + a null trust, so be on guard for that: */ + if(err == noErr && trust) { + count = SecTrustGetCertificateCount(trust); + for(i = 0L ; i < count ; i++) { + CURLcode result; + char *certp; + server_cert = SecTrustGetCertificateAtIndex(trust, i); + result = CopyCertSubject(data, server_cert, &certp); + if(!result) { + infof(data, "Server certificate: %s\n", certp); + free(certp); + } + } + CFRelease(trust); + } +#else + /* SSLCopyPeerCertificates() is deprecated as of Mountain Lion. + The function SecTrustGetCertificateAtIndex() is officially present + in Lion, but it is unfortunately also present in Snow Leopard as + private API and doesn't work as expected. So we have to look for + a different symbol to make sure this code is only executed under + Lion or later. */ + if(SecTrustEvaluateAsync != NULL) { +#pragma unused(server_certs) + err = SSLCopyPeerTrust(BACKEND->ssl_ctx, &trust); + /* For some reason, SSLCopyPeerTrust() can return noErr and yet return + a null trust, so be on guard for that: */ + if(err == noErr && trust) { + count = SecTrustGetCertificateCount(trust); + for(i = 0L ; i < count ; i++) { + char *certp; + CURLcode result; + server_cert = SecTrustGetCertificateAtIndex(trust, i); + result = CopyCertSubject(data, server_cert, &certp); + if(!result) { + infof(data, "Server certificate: %s\n", certp); + free(certp); + } + } + CFRelease(trust); + } + } + else { +#if CURL_SUPPORT_MAC_10_8 + err = SSLCopyPeerCertificates(BACKEND->ssl_ctx, &server_certs); + /* Just in case SSLCopyPeerCertificates() returns null too... */ + if(err == noErr && server_certs) { + count = CFArrayGetCount(server_certs); + for(i = 0L ; i < count ; i++) { + char *certp; + CURLcode result; + server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, + i); + result = CopyCertSubject(data, server_cert, &certp); + if(!result) { + infof(data, "Server certificate: %s\n", certp); + free(certp); + } + } + CFRelease(server_certs); + } +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#endif /* CURL_BUILD_IOS */ +#else +#pragma unused(trust) + err = SSLCopyPeerCertificates(BACKEND->ssl_ctx, &server_certs); + if(err == noErr) { + count = CFArrayGetCount(server_certs); + for(i = 0L ; i < count ; i++) { + CURLcode result; + char *certp; + server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i); + result = CopyCertSubject(data, server_cert, &certp); + if(!result) { + infof(data, "Server certificate: %s\n", certp); + free(certp); + } + } + CFRelease(server_certs); + } +#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */ +} +#endif /* !CURL_DISABLE_VERBOSE_STRINGS */ + +static CURLcode +sectransp_connect_step3(struct connectdata *conn, + int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + /* There is no step 3! + * Well, okay, if verbose mode is on, let's print the details of the + * server certificates. */ +#ifndef CURL_DISABLE_VERBOSE_STRINGS + if(data->set.verbose) + show_verbose_server_cert(conn, sockindex); +#endif + + connssl->connecting_state = ssl_connect_done; + return CURLE_OK; +} + +static Curl_recv sectransp_recv; +static Curl_send sectransp_send; + +static CURLcode +sectransp_connect_common(struct connectdata *conn, + int sockindex, + bool nonblocking, + bool *done) +{ + CURLcode result; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + long timeout_ms; + int what; + + /* check if the connection has already been established */ + if(ssl_connection_complete == connssl->state) { + *done = TRUE; + return CURLE_OK; + } + + if(ssl_connect_1 == connssl->connecting_state) { + /* Find out how much more time we're allowed */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + result = sectransp_connect_step1(conn, sockindex); + if(result) + return result; + } + + while(ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state) { + + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* if ssl is expecting something, check if it's available. */ + if(connssl->connecting_state == ssl_connect_2_reading || + connssl->connecting_state == ssl_connect_2_writing) { + + curl_socket_t writefd = ssl_connect_2_writing == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + curl_socket_t readfd = ssl_connect_2_reading == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + + what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, + nonblocking?0:timeout_ms); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + else if(0 == what) { + if(nonblocking) { + *done = FALSE; + return CURLE_OK; + } + else { + /* timeout */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + } + /* socket is readable or writable */ + } + + /* Run transaction, and return to the caller if it failed or if this + * connection is done nonblocking and this loop would execute again. This + * permits the owner of a multi handle to abort a connection attempt + * before step2 has completed while ensuring that a client using select() + * or epoll() will always have a valid fdset to wait on. + */ + result = sectransp_connect_step2(conn, sockindex); + if(result || (nonblocking && + (ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state))) + return result; + + } /* repeat step2 until all transactions are done. */ + + + if(ssl_connect_3 == connssl->connecting_state) { + result = sectransp_connect_step3(conn, sockindex); + if(result) + return result; + } + + if(ssl_connect_done == connssl->connecting_state) { + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = sectransp_recv; + conn->send[sockindex] = sectransp_send; + *done = TRUE; + } + else + *done = FALSE; + + /* Reset our connect state machine */ + connssl->connecting_state = ssl_connect_1; + + return CURLE_OK; +} + +static CURLcode Curl_sectransp_connect_nonblocking(struct connectdata *conn, + int sockindex, bool *done) +{ + return sectransp_connect_common(conn, sockindex, TRUE, done); +} + +static CURLcode Curl_sectransp_connect(struct connectdata *conn, int sockindex) +{ + CURLcode result; + bool done = FALSE; + + result = sectransp_connect_common(conn, sockindex, FALSE, &done); + + if(result) + return result; + + DEBUGASSERT(done); + + return CURLE_OK; +} + +static void Curl_sectransp_close(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + if(BACKEND->ssl_ctx) { + (void)SSLClose(BACKEND->ssl_ctx); +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + if(SSLCreateContext != NULL) + CFRelease(BACKEND->ssl_ctx); +#if CURL_SUPPORT_MAC_10_8 + else + (void)SSLDisposeContext(BACKEND->ssl_ctx); +#endif /* CURL_SUPPORT_MAC_10_8 */ +#else + (void)SSLDisposeContext(BACKEND->ssl_ctx); +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ + BACKEND->ssl_ctx = NULL; + } + BACKEND->ssl_sockfd = 0; +} + +static int Curl_sectransp_shutdown(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct Curl_easy *data = conn->data; + ssize_t nread; + int what; + int rc; + char buf[120]; + + if(!BACKEND->ssl_ctx) + return 0; + +#ifndef CURL_DISABLE_FTP + if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE) + return 0; +#endif + + Curl_sectransp_close(conn, sockindex); + + rc = 0; + + what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT); + + for(;;) { + if(what < 0) { + /* anything that gets here is fatally bad */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + rc = -1; + break; + } + + if(!what) { /* timeout */ + failf(data, "SSL shutdown timeout"); + break; + } + + /* Something to read, let's do it and hope that it is the close + notify alert from the server. No way to SSL_Read now, so use read(). */ + + nread = read(conn->sock[sockindex], buf, sizeof(buf)); + + if(nread < 0) { + failf(data, "read: %s", strerror(errno)); + rc = -1; + } + + if(nread <= 0) + break; + + what = SOCKET_READABLE(conn->sock[sockindex], 0); + } + + return rc; +} + +static void Curl_sectransp_session_free(void *ptr) +{ + /* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a + cached session ID inside the Security framework. There is a private + function that does this, but I don't want to have to explain to you why I + got your application rejected from the App Store due to the use of a + private API, so the best we can do is free up our own char array that we + created way back in sectransp_connect_step1... */ + Curl_safefree(ptr); +} + +static size_t Curl_sectransp_version(char *buffer, size_t size) +{ + return msnprintf(buffer, size, "SecureTransport"); +} + +/* + * This function uses SSLGetSessionState to determine connection status. + * + * Return codes: + * 1 means the connection is still in place + * 0 means the connection has been closed + * -1 means the connection status is unknown + */ +static int Curl_sectransp_check_cxn(struct connectdata *conn) +{ + struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; + OSStatus err; + SSLSessionState state; + + if(BACKEND->ssl_ctx) { + err = SSLGetSessionState(BACKEND->ssl_ctx, &state); + if(err == noErr) + return state == kSSLConnected || state == kSSLHandshake; + return -1; + } + return 0; +} + +static bool Curl_sectransp_data_pending(const struct connectdata *conn, + int connindex) +{ + const struct ssl_connect_data *connssl = &conn->ssl[connindex]; + OSStatus err; + size_t buffer; + + if(BACKEND->ssl_ctx) { /* SSL is in use */ + err = SSLGetBufferedReadSize(BACKEND->ssl_ctx, &buffer); + if(err == noErr) + return buffer > 0UL; + return false; + } + else + return false; +} + +static CURLcode Curl_sectransp_random(struct Curl_easy *data UNUSED_PARAM, + unsigned char *entropy, size_t length) +{ + /* arc4random_buf() isn't available on cats older than Lion, so let's + do this manually for the benefit of the older cats. */ + size_t i; + u_int32_t random_number = 0; + + (void)data; + + for(i = 0 ; i < length ; i++) { + if(i % sizeof(u_int32_t) == 0) + random_number = arc4random(); + entropy[i] = random_number & 0xFF; + random_number >>= 8; + } + i = random_number = 0; + return CURLE_OK; +} + +static CURLcode Curl_sectransp_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len) +{ + (void)md5len; + (void)CC_MD5(tmp, (CC_LONG)tmplen, md5sum); + return CURLE_OK; +} + +static CURLcode Curl_sectransp_sha256sum(const unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *sha256sum, /* output */ + size_t sha256len) +{ + assert(sha256len >= CURL_SHA256_DIGEST_LENGTH); + (void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum); + return CURLE_OK; +} + +static bool Curl_sectransp_false_start(void) +{ +#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 + if(SSLSetSessionOption != NULL) + return TRUE; +#endif + return FALSE; +} + +static ssize_t sectransp_send(struct connectdata *conn, + int sockindex, + const void *mem, + size_t len, + CURLcode *curlcode) +{ + /*struct Curl_easy *data = conn->data;*/ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + size_t processed = 0UL; + OSStatus err; + + /* The SSLWrite() function works a little differently than expected. The + fourth argument (processed) is currently documented in Apple's + documentation as: "On return, the length, in bytes, of the data actually + written." + + Now, one could interpret that as "written to the socket," but actually, + it returns the amount of data that was written to a buffer internal to + the SSLContextRef instead. So it's possible for SSLWrite() to return + errSSLWouldBlock and a number of bytes "written" because those bytes were + encrypted and written to a buffer, not to the socket. + + So if this happens, then we need to keep calling SSLWrite() over and + over again with no new data until it quits returning errSSLWouldBlock. */ + + /* Do we have buffered data to write from the last time we were called? */ + if(BACKEND->ssl_write_buffered_length) { + /* Write the buffered data: */ + err = SSLWrite(BACKEND->ssl_ctx, NULL, 0UL, &processed); + switch(err) { + case noErr: + /* processed is always going to be 0 because we didn't write to + the buffer, so return how much was written to the socket */ + processed = BACKEND->ssl_write_buffered_length; + BACKEND->ssl_write_buffered_length = 0UL; + break; + case errSSLWouldBlock: /* argh, try again */ + *curlcode = CURLE_AGAIN; + return -1L; + default: + failf(conn->data, "SSLWrite() returned error %d", err); + *curlcode = CURLE_SEND_ERROR; + return -1L; + } + } + else { + /* We've got new data to write: */ + err = SSLWrite(BACKEND->ssl_ctx, mem, len, &processed); + if(err != noErr) { + switch(err) { + case errSSLWouldBlock: + /* Data was buffered but not sent, we have to tell the caller + to try sending again, and remember how much was buffered */ + BACKEND->ssl_write_buffered_length = len; + *curlcode = CURLE_AGAIN; + return -1L; + default: + failf(conn->data, "SSLWrite() returned error %d", err); + *curlcode = CURLE_SEND_ERROR; + return -1L; + } + } + } + return (ssize_t)processed; +} + +static ssize_t sectransp_recv(struct connectdata *conn, + int num, + char *buf, + size_t buffersize, + CURLcode *curlcode) +{ + /*struct Curl_easy *data = conn->data;*/ + struct ssl_connect_data *connssl = &conn->ssl[num]; + size_t processed = 0UL; + OSStatus err = SSLRead(BACKEND->ssl_ctx, buf, buffersize, &processed); + + if(err != noErr) { + switch(err) { + case errSSLWouldBlock: /* return how much we read (if anything) */ + if(processed) + return (ssize_t)processed; + *curlcode = CURLE_AGAIN; + return -1L; + break; + + /* errSSLClosedGraceful - server gracefully shut down the SSL session + errSSLClosedNoNotify - server hung up on us instead of sending a + closure alert notice, read() is returning 0 + Either way, inform the caller that the server disconnected. */ + case errSSLClosedGraceful: + case errSSLClosedNoNotify: + *curlcode = CURLE_OK; + return -1L; + break; + + default: + failf(conn->data, "SSLRead() return error %d", err); + *curlcode = CURLE_RECV_ERROR; + return -1L; + break; + } + } + return (ssize_t)processed; +} + +static void *Curl_sectransp_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) +{ + (void)info; + return BACKEND->ssl_ctx; +} + +const struct Curl_ssl Curl_ssl_sectransp = { + { CURLSSLBACKEND_SECURETRANSPORT, "secure-transport" }, /* info */ + +#ifdef SECTRANSP_PINNEDPUBKEY + SSLSUPP_PINNEDPUBKEY, +#else + 0, +#endif /* SECTRANSP_PINNEDPUBKEY */ + + sizeof(struct ssl_backend_data), + + Curl_none_init, /* init */ + Curl_none_cleanup, /* cleanup */ + Curl_sectransp_version, /* version */ + Curl_sectransp_check_cxn, /* check_cxn */ + Curl_sectransp_shutdown, /* shutdown */ + Curl_sectransp_data_pending, /* data_pending */ + Curl_sectransp_random, /* random */ + Curl_none_cert_status_request, /* cert_status_request */ + Curl_sectransp_connect, /* connect */ + Curl_sectransp_connect_nonblocking, /* connect_nonblocking */ + Curl_sectransp_get_internals, /* get_internals */ + Curl_sectransp_close, /* close_one */ + Curl_none_close_all, /* close_all */ + Curl_sectransp_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_sectransp_false_start, /* false_start */ + Curl_sectransp_md5sum, /* md5sum */ + Curl_sectransp_sha256sum /* sha256sum */ +}; + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif /* USE_SECTRANSP */ diff --git a/dependencies/cmcurl/lib/vtls/sectransp.h b/dependencies/cmcurl/lib/vtls/sectransp.h new file mode 100644 index 0000000..5cec797 --- /dev/null +++ b/dependencies/cmcurl/lib/vtls/sectransp.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_SECTRANSP_H +#define HEADER_CURL_SECTRANSP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2014, Nick Zitzmann, . + * Copyright (C) 2012 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_SECTRANSP + +extern const struct Curl_ssl Curl_ssl_sectransp; + +#endif /* USE_SECTRANSP */ +#endif /* HEADER_CURL_SECTRANSP_H */ diff --git a/dependencies/cmcurl/lib/vtls/vtls.c b/dependencies/cmcurl/lib/vtls/vtls.c new file mode 100644 index 0000000..a7452dc --- /dev/null +++ b/dependencies/cmcurl/lib/vtls/vtls.c @@ -0,0 +1,1349 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* This file is for implementing all "generic" SSL functions that all libcurl + internals should use. It is then responsible for calling the proper + "backend" function. + + SSL-functions in libcurl should call functions in this source file, and not + to any specific SSL-layer. + + Curl_ssl_ - prefix for generic ones + + Note that this source code uses the functions of the configured SSL + backend via the global Curl_ssl instance. + + "SSL/TLS Strong Encryption: An Introduction" + https://httpd.apache.org/docs/2.0/ssl/ssl_intro.html +*/ + +#include "curl_setup.h" + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif + +#include "urldata.h" + +#include "vtls.h" /* generic SSL protos etc */ +#include "slist.h" +#include "sendf.h" +#include "strcase.h" +#include "url.h" +#include "progress.h" +#include "share.h" +#include "multiif.h" +#include "timeval.h" +#include "curl_md5.h" +#include "warnless.h" +#include "curl_base64.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* convenience macro to check if this handle is using a shared SSL session */ +#define SSLSESSION_SHARED(data) (data->share && \ + (data->share->specifier & \ + (1<var) { \ + dest->var = strdup(source->var); \ + if(!dest->var) \ + return FALSE; \ + } \ + else \ + dest->var = NULL; + +bool +Curl_ssl_config_matches(struct ssl_primary_config* data, + struct ssl_primary_config* needle) +{ + if((data->version == needle->version) && + (data->version_max == needle->version_max) && + (data->verifypeer == needle->verifypeer) && + (data->verifyhost == needle->verifyhost) && + (data->verifystatus == needle->verifystatus) && + Curl_safe_strcasecompare(data->CApath, needle->CApath) && + Curl_safe_strcasecompare(data->CAfile, needle->CAfile) && + Curl_safe_strcasecompare(data->clientcert, needle->clientcert) && + Curl_safe_strcasecompare(data->random_file, needle->random_file) && + Curl_safe_strcasecompare(data->egdsocket, needle->egdsocket) && + Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) && + Curl_safe_strcasecompare(data->cipher_list13, needle->cipher_list13)) + return TRUE; + + return FALSE; +} + +bool +Curl_clone_primary_ssl_config(struct ssl_primary_config *source, + struct ssl_primary_config *dest) +{ + dest->version = source->version; + dest->version_max = source->version_max; + dest->verifypeer = source->verifypeer; + dest->verifyhost = source->verifyhost; + dest->verifystatus = source->verifystatus; + dest->sessionid = source->sessionid; + + CLONE_STRING(CApath); + CLONE_STRING(CAfile); + CLONE_STRING(clientcert); + CLONE_STRING(random_file); + CLONE_STRING(egdsocket); + CLONE_STRING(cipher_list); + CLONE_STRING(cipher_list13); + + return TRUE; +} + +void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc) +{ + Curl_safefree(sslc->CApath); + Curl_safefree(sslc->CAfile); + Curl_safefree(sslc->clientcert); + Curl_safefree(sslc->random_file); + Curl_safefree(sslc->egdsocket); + Curl_safefree(sslc->cipher_list); + Curl_safefree(sslc->cipher_list13); +} + +#ifdef USE_SSL +static int multissl_init(const struct Curl_ssl *backend); +#endif + +int Curl_ssl_backend(void) +{ +#ifdef USE_SSL + multissl_init(NULL); + return Curl_ssl->info.id; +#else + return (int)CURLSSLBACKEND_NONE; +#endif +} + +#ifdef USE_SSL + +/* "global" init done? */ +static bool init_ssl = FALSE; + +/** + * Global SSL init + * + * @retval 0 error initializing SSL + * @retval 1 SSL initialized successfully + */ +int Curl_ssl_init(void) +{ + /* make sure this is only done once */ + if(init_ssl) + return 1; + init_ssl = TRUE; /* never again */ + + return Curl_ssl->init(); +} + + +/* Global cleanup */ +void Curl_ssl_cleanup(void) +{ + if(init_ssl) { + /* only cleanup if we did a previous init */ + Curl_ssl->cleanup(); + init_ssl = FALSE; + } +} + +static bool ssl_prefs_check(struct Curl_easy *data) +{ + /* check for CURLOPT_SSLVERSION invalid parameter value */ + const long sslver = data->set.ssl.primary.version; + if((sslver < 0) || (sslver >= CURL_SSLVERSION_LAST)) { + failf(data, "Unrecognized parameter value passed via CURLOPT_SSLVERSION"); + return FALSE; + } + + switch(data->set.ssl.primary.version_max) { + case CURL_SSLVERSION_MAX_NONE: + case CURL_SSLVERSION_MAX_DEFAULT: + break; + + default: + if((data->set.ssl.primary.version_max >> 16) < sslver) { + failf(data, "CURL_SSLVERSION_MAX incompatible with CURL_SSLVERSION"); + return FALSE; + } + } + + return TRUE; +} + +static CURLcode +ssl_connect_init_proxy(struct connectdata *conn, int sockindex) +{ + DEBUGASSERT(conn->bits.proxy_ssl_connected[sockindex]); + if(ssl_connection_complete == conn->ssl[sockindex].state && + !conn->proxy_ssl[sockindex].use) { + struct ssl_backend_data *pbdata; + + if(!(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY)) + return CURLE_NOT_BUILT_IN; + + /* The pointers to the ssl backend data, which is opaque here, are swapped + rather than move the contents. */ + pbdata = conn->proxy_ssl[sockindex].backend; + conn->proxy_ssl[sockindex] = conn->ssl[sockindex]; + + memset(&conn->ssl[sockindex], 0, sizeof(conn->ssl[sockindex])); + memset(pbdata, 0, Curl_ssl->sizeof_ssl_backend_data); + + conn->ssl[sockindex].backend = pbdata; + } + return CURLE_OK; +} + +CURLcode +Curl_ssl_connect(struct connectdata *conn, int sockindex) +{ + CURLcode result; + + if(conn->bits.proxy_ssl_connected[sockindex]) { + result = ssl_connect_init_proxy(conn, sockindex); + if(result) + return result; + } + + if(!ssl_prefs_check(conn->data)) + return CURLE_SSL_CONNECT_ERROR; + + /* mark this is being ssl-enabled from here on. */ + conn->ssl[sockindex].use = TRUE; + conn->ssl[sockindex].state = ssl_connection_negotiating; + + result = Curl_ssl->connect_blocking(conn, sockindex); + + if(!result) + Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */ + + return result; +} + +CURLcode +Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex, + bool *done) +{ + CURLcode result; + if(conn->bits.proxy_ssl_connected[sockindex]) { + result = ssl_connect_init_proxy(conn, sockindex); + if(result) + return result; + } + + if(!ssl_prefs_check(conn->data)) + return CURLE_SSL_CONNECT_ERROR; + + /* mark this is being ssl requested from here on. */ + conn->ssl[sockindex].use = TRUE; + result = Curl_ssl->connect_nonblocking(conn, sockindex, done); + if(!result && *done) + Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */ + return result; +} + +/* + * Lock shared SSL session data + */ +void Curl_ssl_sessionid_lock(struct connectdata *conn) +{ + if(SSLSESSION_SHARED(conn->data)) + Curl_share_lock(conn->data, + CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE); +} + +/* + * Unlock shared SSL session data + */ +void Curl_ssl_sessionid_unlock(struct connectdata *conn) +{ + if(SSLSESSION_SHARED(conn->data)) + Curl_share_unlock(conn->data, CURL_LOCK_DATA_SSL_SESSION); +} + +/* + * Check if there's a session ID for the given connection in the cache, and if + * there's one suitable, it is provided. Returns TRUE when no entry matched. + */ +bool Curl_ssl_getsessionid(struct connectdata *conn, + void **ssl_sessionid, + size_t *idsize, /* set 0 if unknown */ + int sockindex) +{ + struct curl_ssl_session *check; + struct Curl_easy *data = conn->data; + size_t i; + long *general_age; + bool no_match = TRUE; + + const bool isProxy = CONNECT_PROXY_SSL(); + struct ssl_primary_config * const ssl_config = isProxy ? + &conn->proxy_ssl_config : + &conn->ssl_config; + const char * const name = isProxy ? conn->http_proxy.host.name : + conn->host.name; + int port = isProxy ? (int)conn->port : conn->remote_port; + *ssl_sessionid = NULL; + + DEBUGASSERT(SSL_SET_OPTION(primary.sessionid)); + + if(!SSL_SET_OPTION(primary.sessionid)) + /* session ID re-use is disabled */ + return TRUE; + + /* Lock if shared */ + if(SSLSESSION_SHARED(data)) + general_age = &data->share->sessionage; + else + general_age = &data->state.sessionage; + + for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) { + check = &data->state.session[i]; + if(!check->sessionid) + /* not session ID means blank entry */ + continue; + if(strcasecompare(name, check->name) && + ((!conn->bits.conn_to_host && !check->conn_to_host) || + (conn->bits.conn_to_host && check->conn_to_host && + strcasecompare(conn->conn_to_host.name, check->conn_to_host))) && + ((!conn->bits.conn_to_port && check->conn_to_port == -1) || + (conn->bits.conn_to_port && check->conn_to_port != -1 && + conn->conn_to_port == check->conn_to_port)) && + (port == check->remote_port) && + strcasecompare(conn->handler->scheme, check->scheme) && + Curl_ssl_config_matches(ssl_config, &check->ssl_config)) { + /* yes, we have a session ID! */ + (*general_age)++; /* increase general age */ + check->age = *general_age; /* set this as used in this age */ + *ssl_sessionid = check->sessionid; + if(idsize) + *idsize = check->idsize; + no_match = FALSE; + break; + } + } + + return no_match; +} + +/* + * Kill a single session ID entry in the cache. + */ +void Curl_ssl_kill_session(struct curl_ssl_session *session) +{ + if(session->sessionid) { + /* defensive check */ + + /* free the ID the SSL-layer specific way */ + Curl_ssl->session_free(session->sessionid); + + session->sessionid = NULL; + session->age = 0; /* fresh */ + + Curl_free_primary_ssl_config(&session->ssl_config); + + Curl_safefree(session->name); + Curl_safefree(session->conn_to_host); + } +} + +/* + * Delete the given session ID from the cache. + */ +void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid) +{ + size_t i; + struct Curl_easy *data = conn->data; + + for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) { + struct curl_ssl_session *check = &data->state.session[i]; + + if(check->sessionid == ssl_sessionid) { + Curl_ssl_kill_session(check); + break; + } + } +} + +/* + * Store session id in the session cache. The ID passed on to this function + * must already have been extracted and allocated the proper way for the SSL + * layer. Curl_XXXX_session_free() will be called to free/kill the session ID + * later on. + */ +CURLcode Curl_ssl_addsessionid(struct connectdata *conn, + void *ssl_sessionid, + size_t idsize, + int sockindex) +{ + size_t i; + struct Curl_easy *data = conn->data; /* the mother of all structs */ + struct curl_ssl_session *store = &data->state.session[0]; + long oldest_age = data->state.session[0].age; /* zero if unused */ + char *clone_host; + char *clone_conn_to_host; + int conn_to_port; + long *general_age; + const bool isProxy = CONNECT_PROXY_SSL(); + struct ssl_primary_config * const ssl_config = isProxy ? + &conn->proxy_ssl_config : + &conn->ssl_config; + + DEBUGASSERT(SSL_SET_OPTION(primary.sessionid)); + + clone_host = strdup(isProxy ? conn->http_proxy.host.name : conn->host.name); + if(!clone_host) + return CURLE_OUT_OF_MEMORY; /* bail out */ + + if(conn->bits.conn_to_host) { + clone_conn_to_host = strdup(conn->conn_to_host.name); + if(!clone_conn_to_host) { + free(clone_host); + return CURLE_OUT_OF_MEMORY; /* bail out */ + } + } + else + clone_conn_to_host = NULL; + + if(conn->bits.conn_to_port) + conn_to_port = conn->conn_to_port; + else + conn_to_port = -1; + + /* Now we should add the session ID and the host name to the cache, (remove + the oldest if necessary) */ + + /* If using shared SSL session, lock! */ + if(SSLSESSION_SHARED(data)) { + general_age = &data->share->sessionage; + } + else { + general_age = &data->state.sessionage; + } + + /* find an empty slot for us, or find the oldest */ + for(i = 1; (i < data->set.general_ssl.max_ssl_sessions) && + data->state.session[i].sessionid; i++) { + if(data->state.session[i].age < oldest_age) { + oldest_age = data->state.session[i].age; + store = &data->state.session[i]; + } + } + if(i == data->set.general_ssl.max_ssl_sessions) + /* cache is full, we must "kill" the oldest entry! */ + Curl_ssl_kill_session(store); + else + store = &data->state.session[i]; /* use this slot */ + + /* now init the session struct wisely */ + store->sessionid = ssl_sessionid; + store->idsize = idsize; + store->age = *general_age; /* set current age */ + /* free it if there's one already present */ + free(store->name); + free(store->conn_to_host); + store->name = clone_host; /* clone host name */ + store->conn_to_host = clone_conn_to_host; /* clone connect to host name */ + store->conn_to_port = conn_to_port; /* connect to port number */ + /* port number */ + store->remote_port = isProxy ? (int)conn->port : conn->remote_port; + store->scheme = conn->handler->scheme; + + if(!Curl_clone_primary_ssl_config(ssl_config, &store->ssl_config)) { + store->sessionid = NULL; /* let caller free sessionid */ + free(clone_host); + free(clone_conn_to_host); + return CURLE_OUT_OF_MEMORY; + } + + return CURLE_OK; +} + + +void Curl_ssl_close_all(struct Curl_easy *data) +{ + /* kill the session ID cache if not shared */ + if(data->state.session && !SSLSESSION_SHARED(data)) { + size_t i; + for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) + /* the single-killer function handles empty table slots */ + Curl_ssl_kill_session(&data->state.session[i]); + + /* free the cache data */ + Curl_safefree(data->state.session); + } + + Curl_ssl->close_all(data); +} + +#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \ + defined(USE_SECTRANSP) || defined(USE_POLARSSL) || defined(USE_NSS) || \ + defined(USE_MBEDTLS) || defined(USE_CYASSL) +int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks) +{ + struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; + + if(!numsocks) + return GETSOCK_BLANK; + + if(connssl->connecting_state == ssl_connect_2_writing) { + /* write mode */ + socks[0] = conn->sock[FIRSTSOCKET]; + return GETSOCK_WRITESOCK(0); + } + if(connssl->connecting_state == ssl_connect_2_reading) { + /* read mode */ + socks[0] = conn->sock[FIRSTSOCKET]; + return GETSOCK_READSOCK(0); + } + + return GETSOCK_BLANK; +} +#else +int Curl_ssl_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + (void)conn; + (void)socks; + (void)numsocks; + return GETSOCK_BLANK; +} +/* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL || USE_SECTRANSP || USE_NSS */ +#endif + +void Curl_ssl_close(struct connectdata *conn, int sockindex) +{ + DEBUGASSERT((sockindex <= 1) && (sockindex >= -1)); + Curl_ssl->close_one(conn, sockindex); +} + +CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex) +{ + if(Curl_ssl->shut_down(conn, sockindex)) + return CURLE_SSL_SHUTDOWN_FAILED; + + conn->ssl[sockindex].use = FALSE; /* get back to ordinary socket usage */ + conn->ssl[sockindex].state = ssl_connection_none; + + conn->recv[sockindex] = Curl_recv_plain; + conn->send[sockindex] = Curl_send_plain; + + return CURLE_OK; +} + +/* Selects an SSL crypto engine + */ +CURLcode Curl_ssl_set_engine(struct Curl_easy *data, const char *engine) +{ + return Curl_ssl->set_engine(data, engine); +} + +/* Selects the default SSL crypto engine + */ +CURLcode Curl_ssl_set_engine_default(struct Curl_easy *data) +{ + return Curl_ssl->set_engine_default(data); +} + +/* Return list of OpenSSL crypto engine names. */ +struct curl_slist *Curl_ssl_engines_list(struct Curl_easy *data) +{ + return Curl_ssl->engines_list(data); +} + +/* + * This sets up a session ID cache to the specified size. Make sure this code + * is agnostic to what underlying SSL technology we use. + */ +CURLcode Curl_ssl_initsessions(struct Curl_easy *data, size_t amount) +{ + struct curl_ssl_session *session; + + if(data->state.session) + /* this is just a precaution to prevent multiple inits */ + return CURLE_OK; + + session = calloc(amount, sizeof(struct curl_ssl_session)); + if(!session) + return CURLE_OUT_OF_MEMORY; + + /* store the info in the SSL section */ + data->set.general_ssl.max_ssl_sessions = amount; + data->state.session = session; + data->state.sessionage = 1; /* this is brand new */ + return CURLE_OK; +} + +static size_t Curl_multissl_version(char *buffer, size_t size); + +size_t Curl_ssl_version(char *buffer, size_t size) +{ +#ifdef CURL_WITH_MULTI_SSL + return Curl_multissl_version(buffer, size); +#else + return Curl_ssl->version(buffer, size); +#endif +} + +/* + * This function tries to determine connection status. + * + * Return codes: + * 1 means the connection is still in place + * 0 means the connection has been closed + * -1 means the connection status is unknown + */ +int Curl_ssl_check_cxn(struct connectdata *conn) +{ + return Curl_ssl->check_cxn(conn); +} + +bool Curl_ssl_data_pending(const struct connectdata *conn, + int connindex) +{ + return Curl_ssl->data_pending(conn, connindex); +} + +void Curl_ssl_free_certinfo(struct Curl_easy *data) +{ + struct curl_certinfo *ci = &data->info.certs; + + if(ci->num_of_certs) { + /* free all individual lists used */ + int i; + for(i = 0; inum_of_certs; i++) { + curl_slist_free_all(ci->certinfo[i]); + ci->certinfo[i] = NULL; + } + + free(ci->certinfo); /* free the actual array too */ + ci->certinfo = NULL; + ci->num_of_certs = 0; + } +} + +CURLcode Curl_ssl_init_certinfo(struct Curl_easy *data, int num) +{ + struct curl_certinfo *ci = &data->info.certs; + struct curl_slist **table; + + /* Free any previous certificate information structures */ + Curl_ssl_free_certinfo(data); + + /* Allocate the required certificate information structures */ + table = calloc((size_t) num, sizeof(struct curl_slist *)); + if(!table) + return CURLE_OUT_OF_MEMORY; + + ci->num_of_certs = num; + ci->certinfo = table; + + return CURLE_OK; +} + +/* + * 'value' is NOT a zero terminated string + */ +CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data, + int certnum, + const char *label, + const char *value, + size_t valuelen) +{ + struct curl_certinfo *ci = &data->info.certs; + char *output; + struct curl_slist *nl; + CURLcode result = CURLE_OK; + size_t labellen = strlen(label); + size_t outlen = labellen + 1 + valuelen + 1; /* label:value\0 */ + + output = malloc(outlen); + if(!output) + return CURLE_OUT_OF_MEMORY; + + /* sprintf the label and colon */ + msnprintf(output, outlen, "%s:", label); + + /* memcpy the value (it might not be zero terminated) */ + memcpy(&output[labellen + 1], value, valuelen); + + /* zero terminate the output */ + output[labellen + 1 + valuelen] = 0; + + nl = Curl_slist_append_nodup(ci->certinfo[certnum], output); + if(!nl) { + free(output); + curl_slist_free_all(ci->certinfo[certnum]); + result = CURLE_OUT_OF_MEMORY; + } + + ci->certinfo[certnum] = nl; + return result; +} + +/* + * This is a convenience function for push_certinfo_len that takes a zero + * terminated value. + */ +CURLcode Curl_ssl_push_certinfo(struct Curl_easy *data, + int certnum, + const char *label, + const char *value) +{ + size_t valuelen = strlen(value); + + return Curl_ssl_push_certinfo_len(data, certnum, label, value, valuelen); +} + +CURLcode Curl_ssl_random(struct Curl_easy *data, + unsigned char *entropy, + size_t length) +{ + return Curl_ssl->random(data, entropy, length); +} + +/* + * Public key pem to der conversion + */ + +static CURLcode pubkey_pem_to_der(const char *pem, + unsigned char **der, size_t *der_len) +{ + char *stripped_pem, *begin_pos, *end_pos; + size_t pem_count, stripped_pem_count = 0, pem_len; + CURLcode result; + + /* if no pem, exit. */ + if(!pem) + return CURLE_BAD_CONTENT_ENCODING; + + begin_pos = strstr(pem, "-----BEGIN PUBLIC KEY-----"); + if(!begin_pos) + return CURLE_BAD_CONTENT_ENCODING; + + pem_count = begin_pos - pem; + /* Invalid if not at beginning AND not directly following \n */ + if(0 != pem_count && '\n' != pem[pem_count - 1]) + return CURLE_BAD_CONTENT_ENCODING; + + /* 26 is length of "-----BEGIN PUBLIC KEY-----" */ + pem_count += 26; + + /* Invalid if not directly following \n */ + end_pos = strstr(pem + pem_count, "\n-----END PUBLIC KEY-----"); + if(!end_pos) + return CURLE_BAD_CONTENT_ENCODING; + + pem_len = end_pos - pem; + + stripped_pem = malloc(pem_len - pem_count + 1); + if(!stripped_pem) + return CURLE_OUT_OF_MEMORY; + + /* + * Here we loop through the pem array one character at a time between the + * correct indices, and place each character that is not '\n' or '\r' + * into the stripped_pem array, which should represent the raw base64 string + */ + while(pem_count < pem_len) { + if('\n' != pem[pem_count] && '\r' != pem[pem_count]) + stripped_pem[stripped_pem_count++] = pem[pem_count]; + ++pem_count; + } + /* Place the null terminator in the correct place */ + stripped_pem[stripped_pem_count] = '\0'; + + result = Curl_base64_decode(stripped_pem, der, der_len); + + Curl_safefree(stripped_pem); + + return result; +} + +/* + * Generic pinned public key check. + */ + +CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data, + const char *pinnedpubkey, + const unsigned char *pubkey, size_t pubkeylen) +{ + FILE *fp; + unsigned char *buf = NULL, *pem_ptr = NULL; + CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; + + /* if a path wasn't specified, don't pin */ + if(!pinnedpubkey) + return CURLE_OK; + if(!pubkey || !pubkeylen) + return result; + + /* only do this if pinnedpubkey starts with "sha256//", length 8 */ + if(strncmp(pinnedpubkey, "sha256//", 8) == 0) { + CURLcode encode; + size_t encodedlen, pinkeylen; + char *encoded, *pinkeycopy, *begin_pos, *end_pos; + unsigned char *sha256sumdigest; + + if(!Curl_ssl->sha256sum) { + /* without sha256 support, this cannot match */ + return result; + } + + /* compute sha256sum of public key */ + sha256sumdigest = malloc(CURL_SHA256_DIGEST_LENGTH); + if(!sha256sumdigest) + return CURLE_OUT_OF_MEMORY; + encode = Curl_ssl->sha256sum(pubkey, pubkeylen, + sha256sumdigest, CURL_SHA256_DIGEST_LENGTH); + + if(encode != CURLE_OK) + return encode; + + encode = Curl_base64_encode(data, (char *)sha256sumdigest, + CURL_SHA256_DIGEST_LENGTH, &encoded, + &encodedlen); + Curl_safefree(sha256sumdigest); + + if(encode) + return encode; + + infof(data, "\t public key hash: sha256//%s\n", encoded); + + /* it starts with sha256//, copy so we can modify it */ + pinkeylen = strlen(pinnedpubkey) + 1; + pinkeycopy = malloc(pinkeylen); + if(!pinkeycopy) { + Curl_safefree(encoded); + return CURLE_OUT_OF_MEMORY; + } + memcpy(pinkeycopy, pinnedpubkey, pinkeylen); + /* point begin_pos to the copy, and start extracting keys */ + begin_pos = pinkeycopy; + do { + end_pos = strstr(begin_pos, ";sha256//"); + /* + * if there is an end_pos, null terminate, + * otherwise it'll go to the end of the original string + */ + if(end_pos) + end_pos[0] = '\0'; + + /* compare base64 sha256 digests, 8 is the length of "sha256//" */ + if(encodedlen == strlen(begin_pos + 8) && + !memcmp(encoded, begin_pos + 8, encodedlen)) { + result = CURLE_OK; + break; + } + + /* + * change back the null-terminator we changed earlier, + * and look for next begin + */ + if(end_pos) { + end_pos[0] = ';'; + begin_pos = strstr(end_pos, "sha256//"); + } + } while(end_pos && begin_pos); + Curl_safefree(encoded); + Curl_safefree(pinkeycopy); + return result; + } + + fp = fopen(pinnedpubkey, "rb"); + if(!fp) + return result; + + do { + long filesize; + size_t size, pem_len; + CURLcode pem_read; + + /* Determine the file's size */ + if(fseek(fp, 0, SEEK_END)) + break; + filesize = ftell(fp); + if(fseek(fp, 0, SEEK_SET)) + break; + if(filesize < 0 || filesize > MAX_PINNED_PUBKEY_SIZE) + break; + + /* + * if the size of our certificate is bigger than the file + * size then it can't match + */ + size = curlx_sotouz((curl_off_t) filesize); + if(pubkeylen > size) + break; + + /* + * Allocate buffer for the pinned key + * With 1 additional byte for null terminator in case of PEM key + */ + buf = malloc(size + 1); + if(!buf) + break; + + /* Returns number of elements read, which should be 1 */ + if((int) fread(buf, size, 1, fp) != 1) + break; + + /* If the sizes are the same, it can't be base64 encoded, must be der */ + if(pubkeylen == size) { + if(!memcmp(pubkey, buf, pubkeylen)) + result = CURLE_OK; + break; + } + + /* + * Otherwise we will assume it's PEM and try to decode it + * after placing null terminator + */ + buf[size] = '\0'; + pem_read = pubkey_pem_to_der((const char *)buf, &pem_ptr, &pem_len); + /* if it wasn't read successfully, exit */ + if(pem_read) + break; + + /* + * if the size of our certificate doesn't match the size of + * the decoded file, they can't be the same, otherwise compare + */ + if(pubkeylen == pem_len && !memcmp(pubkey, pem_ptr, pubkeylen)) + result = CURLE_OK; + } while(0); + + Curl_safefree(buf); + Curl_safefree(pem_ptr); + fclose(fp); + + return result; +} + +#ifndef CURL_DISABLE_CRYPTO_AUTH +CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len) +{ + return Curl_ssl->md5sum(tmp, tmplen, md5sum, md5len); +} +#endif + +/* + * Check whether the SSL backend supports the status_request extension. + */ +bool Curl_ssl_cert_status_request(void) +{ + return Curl_ssl->cert_status_request(); +} + +/* + * Check whether the SSL backend supports false start. + */ +bool Curl_ssl_false_start(void) +{ + return Curl_ssl->false_start(); +} + +/* + * Check whether the SSL backend supports setting TLS 1.3 cipher suites + */ +bool Curl_ssl_tls13_ciphersuites(void) +{ + return Curl_ssl->supports & SSLSUPP_TLS13_CIPHERSUITES; +} + +/* + * Default implementations for unsupported functions. + */ + +int Curl_none_init(void) +{ + return 1; +} + +void Curl_none_cleanup(void) +{ } + +int Curl_none_shutdown(struct connectdata *conn UNUSED_PARAM, + int sockindex UNUSED_PARAM) +{ + (void)conn; + (void)sockindex; + return 0; +} + +int Curl_none_check_cxn(struct connectdata *conn UNUSED_PARAM) +{ + (void)conn; + return -1; +} + +CURLcode Curl_none_random(struct Curl_easy *data UNUSED_PARAM, + unsigned char *entropy UNUSED_PARAM, + size_t length UNUSED_PARAM) +{ + (void)data; + (void)entropy; + (void)length; + return CURLE_NOT_BUILT_IN; +} + +void Curl_none_close_all(struct Curl_easy *data UNUSED_PARAM) +{ + (void)data; +} + +void Curl_none_session_free(void *ptr UNUSED_PARAM) +{ + (void)ptr; +} + +bool Curl_none_data_pending(const struct connectdata *conn UNUSED_PARAM, + int connindex UNUSED_PARAM) +{ + (void)conn; + (void)connindex; + return 0; +} + +bool Curl_none_cert_status_request(void) +{ + return FALSE; +} + +CURLcode Curl_none_set_engine(struct Curl_easy *data UNUSED_PARAM, + const char *engine UNUSED_PARAM) +{ + (void)data; + (void)engine; + return CURLE_NOT_BUILT_IN; +} + +CURLcode Curl_none_set_engine_default(struct Curl_easy *data UNUSED_PARAM) +{ + (void)data; + return CURLE_NOT_BUILT_IN; +} + +struct curl_slist *Curl_none_engines_list(struct Curl_easy *data UNUSED_PARAM) +{ + (void)data; + return (struct curl_slist *)NULL; +} + +bool Curl_none_false_start(void) +{ + return FALSE; +} + +#ifndef CURL_DISABLE_CRYPTO_AUTH +CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen, + unsigned char *md5sum, size_t md5len UNUSED_PARAM) +{ + MD5_context *MD5pw; + + (void)md5len; + + MD5pw = Curl_MD5_init(Curl_DIGEST_MD5); + if(!MD5pw) + return CURLE_OUT_OF_MEMORY; + Curl_MD5_update(MD5pw, input, curlx_uztoui(inputlen)); + Curl_MD5_final(MD5pw, md5sum); + return CURLE_OK; +} +#else +CURLcode Curl_none_md5sum(unsigned char *input UNUSED_PARAM, + size_t inputlen UNUSED_PARAM, + unsigned char *md5sum UNUSED_PARAM, + size_t md5len UNUSED_PARAM) +{ + (void)input; + (void)inputlen; + (void)md5sum; + (void)md5len; + return CURLE_NOT_BUILT_IN; +} +#endif + +static int Curl_multissl_init(void) +{ + if(multissl_init(NULL)) + return 1; + return Curl_ssl->init(); +} + +static CURLcode Curl_multissl_connect(struct connectdata *conn, int sockindex) +{ + if(multissl_init(NULL)) + return CURLE_FAILED_INIT; + return Curl_ssl->connect_blocking(conn, sockindex); +} + +static CURLcode Curl_multissl_connect_nonblocking(struct connectdata *conn, + int sockindex, bool *done) +{ + if(multissl_init(NULL)) + return CURLE_FAILED_INIT; + return Curl_ssl->connect_nonblocking(conn, sockindex, done); +} + +static void *Curl_multissl_get_internals(struct ssl_connect_data *connssl, + CURLINFO info) +{ + if(multissl_init(NULL)) + return NULL; + return Curl_ssl->get_internals(connssl, info); +} + +static void Curl_multissl_close(struct connectdata *conn, int sockindex) +{ + if(multissl_init(NULL)) + return; + Curl_ssl->close_one(conn, sockindex); +} + +static const struct Curl_ssl Curl_ssl_multi = { + { CURLSSLBACKEND_NONE, "multi" }, /* info */ + 0, /* supports nothing */ + (size_t)-1, /* something insanely large to be on the safe side */ + + Curl_multissl_init, /* init */ + Curl_none_cleanup, /* cleanup */ + Curl_multissl_version, /* version */ + Curl_none_check_cxn, /* check_cxn */ + Curl_none_shutdown, /* shutdown */ + Curl_none_data_pending, /* data_pending */ + Curl_none_random, /* random */ + Curl_none_cert_status_request, /* cert_status_request */ + Curl_multissl_connect, /* connect */ + Curl_multissl_connect_nonblocking, /* connect_nonblocking */ + Curl_multissl_get_internals, /* get_internals */ + Curl_multissl_close, /* close_one */ + Curl_none_close_all, /* close_all */ + Curl_none_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ + Curl_none_md5sum, /* md5sum */ + NULL /* sha256sum */ +}; + +const struct Curl_ssl *Curl_ssl = +#if defined(CURL_WITH_MULTI_SSL) + &Curl_ssl_multi; +#elif defined(USE_CYASSL) + &Curl_ssl_cyassl; +#elif defined(USE_SECTRANSP) + &Curl_ssl_sectransp; +#elif defined(USE_GNUTLS) + &Curl_ssl_gnutls; +#elif defined(USE_GSKIT) + &Curl_ssl_gskit; +#elif defined(USE_MBEDTLS) + &Curl_ssl_mbedtls; +#elif defined(USE_NSS) + &Curl_ssl_nss; +#elif defined(USE_OPENSSL) + &Curl_ssl_openssl; +#elif defined(USE_POLARSSL) + &Curl_ssl_polarssl; +#elif defined(USE_SCHANNEL) + &Curl_ssl_schannel; +#elif defined(USE_MESALINK) + &Curl_ssl_mesalink; +#else +#error "Missing struct Curl_ssl for selected SSL backend" +#endif + +static const struct Curl_ssl *available_backends[] = { +#if defined(USE_CYASSL) + &Curl_ssl_cyassl, +#endif +#if defined(USE_SECTRANSP) + &Curl_ssl_sectransp, +#endif +#if defined(USE_GNUTLS) + &Curl_ssl_gnutls, +#endif +#if defined(USE_GSKIT) + &Curl_ssl_gskit, +#endif +#if defined(USE_MBEDTLS) + &Curl_ssl_mbedtls, +#endif +#if defined(USE_NSS) + &Curl_ssl_nss, +#endif +#if defined(USE_OPENSSL) + &Curl_ssl_openssl, +#endif +#if defined(USE_POLARSSL) + &Curl_ssl_polarssl, +#endif +#if defined(USE_SCHANNEL) + &Curl_ssl_schannel, +#endif +#if defined(USE_MESALINK) + &Curl_ssl_mesalink, +#endif + NULL +}; + +static size_t Curl_multissl_version(char *buffer, size_t size) +{ + static const struct Curl_ssl *selected; + static char backends[200]; + static size_t total; + const struct Curl_ssl *current; + + current = Curl_ssl == &Curl_ssl_multi ? available_backends[0] : Curl_ssl; + + if(current != selected) { + char *p = backends; + char *end = backends + sizeof(backends); + int i; + + selected = current; + + for(i = 0; available_backends[i] && p < (end - 4); i++) { + if(i) + *(p++) = ' '; + if(selected != available_backends[i]) + *(p++) = '('; + p += available_backends[i]->version(p, end - p - 2); + if(selected != available_backends[i]) + *(p++) = ')'; + } + *p = '\0'; + total = p - backends; + } + + if(size > total) + memcpy(buffer, backends, total + 1); + else { + memcpy(buffer, backends, size - 1); + buffer[size - 1] = '\0'; + } + + return CURLMIN(size - 1, total); +} + +static int multissl_init(const struct Curl_ssl *backend) +{ + const char *env; + char *env_tmp; + + if(Curl_ssl != &Curl_ssl_multi) + return 1; + + if(backend) { + Curl_ssl = backend; + return 0; + } + + if(!available_backends[0]) + return 1; + + env = env_tmp = curl_getenv("CURL_SSL_BACKEND"); +#ifdef CURL_DEFAULT_SSL_BACKEND + if(!env) + env = CURL_DEFAULT_SSL_BACKEND; +#endif + if(env) { + int i; + for(i = 0; available_backends[i]; i++) { + if(strcasecompare(env, available_backends[i]->info.name)) { + Curl_ssl = available_backends[i]; + curl_free(env_tmp); + return 0; + } + } + } + + /* Fall back to first available backend */ + Curl_ssl = available_backends[0]; + curl_free(env_tmp); + return 0; +} + +CURLsslset curl_global_sslset(curl_sslbackend id, const char *name, + const curl_ssl_backend ***avail) +{ + int i; + + if(avail) + *avail = (const curl_ssl_backend **)&available_backends; + + if(Curl_ssl != &Curl_ssl_multi) + return id == Curl_ssl->info.id || + (name && strcasecompare(name, Curl_ssl->info.name)) ? + CURLSSLSET_OK : +#if defined(CURL_WITH_MULTI_SSL) + CURLSSLSET_TOO_LATE; +#else + CURLSSLSET_UNKNOWN_BACKEND; +#endif + + for(i = 0; available_backends[i]; i++) { + if(available_backends[i]->info.id == id || + (name && strcasecompare(available_backends[i]->info.name, name))) { + multissl_init(available_backends[i]); + return CURLSSLSET_OK; + } + } + + return CURLSSLSET_UNKNOWN_BACKEND; +} + +#else /* USE_SSL */ +CURLsslset curl_global_sslset(curl_sslbackend id, const char *name, + const curl_ssl_backend ***avail) +{ + (void)id; + (void)name; + (void)avail; + return CURLSSLSET_NO_BACKENDS; +} + +#endif /* !USE_SSL */ diff --git a/dependencies/cmcurl/lib/vtls/vtls.h b/dependencies/cmcurl/lib/vtls/vtls.h new file mode 100644 index 0000000..2a87ca1 --- /dev/null +++ b/dependencies/cmcurl/lib/vtls/vtls.h @@ -0,0 +1,278 @@ +#ifndef HEADER_CURL_VTLS_H +#define HEADER_CURL_VTLS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +struct connectdata; +struct ssl_connect_data; + +#define SSLSUPP_CA_PATH (1<<0) /* supports CAPATH */ +#define SSLSUPP_CERTINFO (1<<1) /* supports CURLOPT_CERTINFO */ +#define SSLSUPP_PINNEDPUBKEY (1<<2) /* supports CURLOPT_PINNEDPUBLICKEY */ +#define SSLSUPP_SSL_CTX (1<<3) /* supports CURLOPT_SSL_CTX */ +#define SSLSUPP_HTTPS_PROXY (1<<4) /* supports access via HTTPS proxies */ +#define SSLSUPP_TLS13_CIPHERSUITES (1<<5) /* supports TLS 1.3 ciphersuites */ + +struct Curl_ssl { + /* + * This *must* be the first entry to allow returning the list of available + * backends in curl_global_sslset(). + */ + curl_ssl_backend info; + unsigned int supports; /* bitfield, see above */ + size_t sizeof_ssl_backend_data; + + int (*init)(void); + void (*cleanup)(void); + + size_t (*version)(char *buffer, size_t size); + int (*check_cxn)(struct connectdata *cxn); + int (*shut_down)(struct connectdata *conn, int sockindex); + bool (*data_pending)(const struct connectdata *conn, + int connindex); + + /* return 0 if a find random is filled in */ + CURLcode (*random)(struct Curl_easy *data, unsigned char *entropy, + size_t length); + bool (*cert_status_request)(void); + + CURLcode (*connect_blocking)(struct connectdata *conn, int sockindex); + CURLcode (*connect_nonblocking)(struct connectdata *conn, int sockindex, + bool *done); + void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info); + void (*close_one)(struct connectdata *conn, int sockindex); + void (*close_all)(struct Curl_easy *data); + void (*session_free)(void *ptr); + + CURLcode (*set_engine)(struct Curl_easy *data, const char *engine); + CURLcode (*set_engine_default)(struct Curl_easy *data); + struct curl_slist *(*engines_list)(struct Curl_easy *data); + + bool (*false_start)(void); + + CURLcode (*md5sum)(unsigned char *input, size_t inputlen, + unsigned char *md5sum, size_t md5sumlen); + CURLcode (*sha256sum)(const unsigned char *input, size_t inputlen, + unsigned char *sha256sum, size_t sha256sumlen); +}; + +#ifdef USE_SSL +extern const struct Curl_ssl *Curl_ssl; +#endif + +int Curl_none_init(void); +void Curl_none_cleanup(void); +int Curl_none_shutdown(struct connectdata *conn, int sockindex); +int Curl_none_check_cxn(struct connectdata *conn); +CURLcode Curl_none_random(struct Curl_easy *data, unsigned char *entropy, + size_t length); +void Curl_none_close_all(struct Curl_easy *data); +void Curl_none_session_free(void *ptr); +bool Curl_none_data_pending(const struct connectdata *conn, int connindex); +bool Curl_none_cert_status_request(void); +CURLcode Curl_none_set_engine(struct Curl_easy *data, const char *engine); +CURLcode Curl_none_set_engine_default(struct Curl_easy *data); +struct curl_slist *Curl_none_engines_list(struct Curl_easy *data); +bool Curl_none_false_start(void); +bool Curl_ssl_tls13_ciphersuites(void); +CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen, + unsigned char *md5sum, size_t md5len); + +#include "openssl.h" /* OpenSSL versions */ +#include "gtls.h" /* GnuTLS versions */ +#include "nssg.h" /* NSS versions */ +#include "gskit.h" /* Global Secure ToolKit versions */ +#include "polarssl.h" /* PolarSSL versions */ +#include "cyassl.h" /* CyaSSL versions */ +#include "schannel.h" /* Schannel SSPI version */ +#include "sectransp.h" /* SecureTransport (Darwin) version */ +#include "mbedtls.h" /* mbedTLS versions */ +#include "mesalink.h" /* MesaLink versions */ + +#ifndef MAX_PINNED_PUBKEY_SIZE +#define MAX_PINNED_PUBKEY_SIZE 1048576 /* 1MB */ +#endif + +#ifndef MD5_DIGEST_LENGTH +#ifndef LIBWOLFSSL_VERSION_HEX /* because WolfSSL borks this */ +#define MD5_DIGEST_LENGTH 16 /* fixed size */ +#endif +#endif + +#ifndef CURL_SHA256_DIGEST_LENGTH +#define CURL_SHA256_DIGEST_LENGTH 32 /* fixed size */ +#endif + +/* see https://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-04 */ +#define ALPN_HTTP_1_1_LENGTH 8 +#define ALPN_HTTP_1_1 "http/1.1" + +/* set of helper macros for the backends to access the correct fields. For the + proxy or for the remote host - to properly support HTTPS proxy */ + +#define SSL_IS_PROXY() (CURLPROXY_HTTPS == conn->http_proxy.proxytype && \ + ssl_connection_complete != conn->proxy_ssl[conn->sock[SECONDARYSOCKET] == \ + CURL_SOCKET_BAD ? FIRSTSOCKET : SECONDARYSOCKET].state) +#define SSL_SET_OPTION(var) (SSL_IS_PROXY() ? data->set.proxy_ssl.var : \ + data->set.ssl.var) +#define SSL_CONN_CONFIG(var) (SSL_IS_PROXY() ? \ + conn->proxy_ssl_config.var : conn->ssl_config.var) + +bool Curl_ssl_config_matches(struct ssl_primary_config* data, + struct ssl_primary_config* needle); +bool Curl_clone_primary_ssl_config(struct ssl_primary_config *source, + struct ssl_primary_config *dest); +void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc); +int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); + +int Curl_ssl_backend(void); + +#ifdef USE_SSL +int Curl_ssl_init(void); +void Curl_ssl_cleanup(void); +CURLcode Curl_ssl_connect(struct connectdata *conn, int sockindex); +CURLcode Curl_ssl_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done); +/* tell the SSL stuff to close down all open information regarding + connections (and thus session ID caching etc) */ +void Curl_ssl_close_all(struct Curl_easy *data); +void Curl_ssl_close(struct connectdata *conn, int sockindex); +CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex); +CURLcode Curl_ssl_set_engine(struct Curl_easy *data, const char *engine); +/* Sets engine as default for all SSL operations */ +CURLcode Curl_ssl_set_engine_default(struct Curl_easy *data); +struct curl_slist *Curl_ssl_engines_list(struct Curl_easy *data); + +/* init the SSL session ID cache */ +CURLcode Curl_ssl_initsessions(struct Curl_easy *, size_t); +size_t Curl_ssl_version(char *buffer, size_t size); +bool Curl_ssl_data_pending(const struct connectdata *conn, + int connindex); +int Curl_ssl_check_cxn(struct connectdata *conn); + +/* Certificate information list handling. */ + +void Curl_ssl_free_certinfo(struct Curl_easy *data); +CURLcode Curl_ssl_init_certinfo(struct Curl_easy *data, int num); +CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data, int certnum, + const char *label, const char *value, + size_t valuelen); +CURLcode Curl_ssl_push_certinfo(struct Curl_easy *data, int certnum, + const char *label, const char *value); + +/* Functions to be used by SSL library adaptation functions */ + +/* Lock session cache mutex. + * Call this before calling other Curl_ssl_*session* functions + * Caller should unlock this mutex as soon as possible, as it may block + * other SSL connection from making progress. + * The purpose of explicitly locking SSL session cache data is to allow + * individual SSL engines to manage session lifetime in their specific way. + */ +void Curl_ssl_sessionid_lock(struct connectdata *conn); + +/* Unlock session cache mutex */ +void Curl_ssl_sessionid_unlock(struct connectdata *conn); + +/* extract a session ID + * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock). + * Caller must make sure that the ownership of returned sessionid object + * is properly taken (e.g. its refcount is incremented + * under sessionid mutex). + */ +bool Curl_ssl_getsessionid(struct connectdata *conn, + void **ssl_sessionid, + size_t *idsize, /* set 0 if unknown */ + int sockindex); +/* add a new session ID + * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock). + * Caller must ensure that it has properly shared ownership of this sessionid + * object with cache (e.g. incrementing refcount on success) + */ +CURLcode Curl_ssl_addsessionid(struct connectdata *conn, + void *ssl_sessionid, + size_t idsize, + int sockindex); +/* Kill a single session ID entry in the cache + * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock). + * This will call engine-specific curlssl_session_free function, which must + * take sessionid object ownership from sessionid cache + * (e.g. decrement refcount). + */ +void Curl_ssl_kill_session(struct curl_ssl_session *session); +/* delete a session from the cache + * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock). + * This will call engine-specific curlssl_session_free function, which must + * take sessionid object ownership from sessionid cache + * (e.g. decrement refcount). + */ +void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid); + +/* get N random bytes into the buffer */ +CURLcode Curl_ssl_random(struct Curl_easy *data, unsigned char *buffer, + size_t length); +CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len); +/* Check pinned public key. */ +CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data, + const char *pinnedpubkey, + const unsigned char *pubkey, size_t pubkeylen); + +bool Curl_ssl_cert_status_request(void); + +bool Curl_ssl_false_start(void); + +#define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */ + +#else /* if not USE_SSL */ + +/* When SSL support is not present, just define away these function calls */ +#define Curl_ssl_init() 1 +#define Curl_ssl_cleanup() Curl_nop_stmt +#define Curl_ssl_connect(x,y) CURLE_NOT_BUILT_IN +#define Curl_ssl_close_all(x) Curl_nop_stmt +#define Curl_ssl_close(x,y) Curl_nop_stmt +#define Curl_ssl_shutdown(x,y) CURLE_NOT_BUILT_IN +#define Curl_ssl_set_engine(x,y) CURLE_NOT_BUILT_IN +#define Curl_ssl_set_engine_default(x) CURLE_NOT_BUILT_IN +#define Curl_ssl_engines_list(x) NULL +#define Curl_ssl_send(a,b,c,d,e) -1 +#define Curl_ssl_recv(a,b,c,d,e) -1 +#define Curl_ssl_initsessions(x,y) CURLE_OK +#define Curl_ssl_version(x,y) 0 +#define Curl_ssl_data_pending(x,y) 0 +#define Curl_ssl_check_cxn(x) 0 +#define Curl_ssl_free_certinfo(x) Curl_nop_stmt +#define Curl_ssl_connect_nonblocking(x,y,z) CURLE_NOT_BUILT_IN +#define Curl_ssl_kill_session(x) Curl_nop_stmt +#define Curl_ssl_random(x,y,z) ((void)x, CURLE_NOT_BUILT_IN) +#define Curl_ssl_cert_status_request() FALSE +#define Curl_ssl_false_start() FALSE +#define Curl_ssl_tls13_ciphersuites() FALSE +#endif + +#endif /* HEADER_CURL_VTLS_H */ diff --git a/dependencies/cmcurl/lib/warnless.c b/dependencies/cmcurl/lib/warnless.c new file mode 100644 index 0000000..cfd5e8e --- /dev/null +++ b/dependencies/cmcurl/lib/warnless.c @@ -0,0 +1,508 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(__INTEL_COMPILER) && defined(__unix__) + +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_ARPA_INET_H +# include +#endif + +#endif /* __INTEL_COMPILER && __unix__ */ + +#define BUILDING_WARNLESS_C 1 + +#include "warnless.h" + +#define CURL_MASK_SCHAR 0x7F +#define CURL_MASK_UCHAR 0xFF + +#if (SIZEOF_SHORT == 2) +# define CURL_MASK_SSHORT 0x7FFF +# define CURL_MASK_USHORT 0xFFFF +#elif (SIZEOF_SHORT == 4) +# define CURL_MASK_SSHORT 0x7FFFFFFF +# define CURL_MASK_USHORT 0xFFFFFFFF +#elif (SIZEOF_SHORT == 8) +# define CURL_MASK_SSHORT 0x7FFFFFFFFFFFFFFF +# define CURL_MASK_USHORT 0xFFFFFFFFFFFFFFFF +#else +# error "SIZEOF_SHORT not defined" +#endif + +#if (SIZEOF_INT == 2) +# define CURL_MASK_SINT 0x7FFF +# define CURL_MASK_UINT 0xFFFF +#elif (SIZEOF_INT == 4) +# define CURL_MASK_SINT 0x7FFFFFFF +# define CURL_MASK_UINT 0xFFFFFFFF +#elif (SIZEOF_INT == 8) +# define CURL_MASK_SINT 0x7FFFFFFFFFFFFFFF +# define CURL_MASK_UINT 0xFFFFFFFFFFFFFFFF +#elif (SIZEOF_INT == 16) +# define CURL_MASK_SINT 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +# define CURL_MASK_UINT 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +#else +# error "SIZEOF_INT not defined" +#endif + +#if (SIZEOF_LONG == 2) +# define CURL_MASK_SLONG 0x7FFFL +# define CURL_MASK_ULONG 0xFFFFUL +#elif (SIZEOF_LONG == 4) +# define CURL_MASK_SLONG 0x7FFFFFFFL +# define CURL_MASK_ULONG 0xFFFFFFFFUL +#elif (SIZEOF_LONG == 8) +# define CURL_MASK_SLONG 0x7FFFFFFFFFFFFFFFL +# define CURL_MASK_ULONG 0xFFFFFFFFFFFFFFFFUL +#elif (SIZEOF_LONG == 16) +# define CURL_MASK_SLONG 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFL +# define CURL_MASK_ULONG 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFUL +#else +# error "SIZEOF_LONG not defined" +#endif + +#if (SIZEOF_CURL_OFF_T == 2) +# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFF) +# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFF) +#elif (SIZEOF_CURL_OFF_T == 4) +# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFFFFFF) +# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFFFFFF) +#elif (SIZEOF_CURL_OFF_T == 8) +# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFFFFFFFFFFFFFF) +# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFFFFFFFFFFFFFF) +#elif (SIZEOF_CURL_OFF_T == 16) +# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) +# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) +#else +# error "SIZEOF_CURL_OFF_T not defined" +#endif + +#if (SIZEOF_SIZE_T == SIZEOF_SHORT) +# define CURL_MASK_SSIZE_T CURL_MASK_SSHORT +# define CURL_MASK_USIZE_T CURL_MASK_USHORT +#elif (SIZEOF_SIZE_T == SIZEOF_INT) +# define CURL_MASK_SSIZE_T CURL_MASK_SINT +# define CURL_MASK_USIZE_T CURL_MASK_UINT +#elif (SIZEOF_SIZE_T == SIZEOF_LONG) +# define CURL_MASK_SSIZE_T CURL_MASK_SLONG +# define CURL_MASK_USIZE_T CURL_MASK_ULONG +#elif (SIZEOF_SIZE_T == SIZEOF_CURL_OFF_T) +# define CURL_MASK_SSIZE_T CURL_MASK_SCOFFT +# define CURL_MASK_USIZE_T CURL_MASK_UCOFFT +#else +# error "SIZEOF_SIZE_T not defined" +#endif + +/* +** unsigned long to unsigned short +*/ + +unsigned short curlx_ultous(unsigned long ulnum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(ulnum <= (unsigned long) CURL_MASK_USHORT); + return (unsigned short)(ulnum & (unsigned long) CURL_MASK_USHORT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** unsigned long to unsigned char +*/ + +unsigned char curlx_ultouc(unsigned long ulnum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(ulnum <= (unsigned long) CURL_MASK_UCHAR); + return (unsigned char)(ulnum & (unsigned long) CURL_MASK_UCHAR); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** unsigned long to signed int +*/ + +int curlx_ultosi(unsigned long ulnum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(ulnum <= (unsigned long) CURL_MASK_SINT); + return (int)(ulnum & (unsigned long) CURL_MASK_SINT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** unsigned size_t to signed curl_off_t +*/ + +curl_off_t curlx_uztoso(size_t uznum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#elif defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable:4310) /* cast truncates constant value */ +#endif + + DEBUGASSERT(uznum <= (size_t) CURL_MASK_SCOFFT); + return (curl_off_t)(uznum & (size_t) CURL_MASK_SCOFFT); + +#if defined(__INTEL_COMPILER) || defined(_MSC_VER) +# pragma warning(pop) +#endif +} + +/* +** unsigned size_t to signed int +*/ + +int curlx_uztosi(size_t uznum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(uznum <= (size_t) CURL_MASK_SINT); + return (int)(uznum & (size_t) CURL_MASK_SINT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** unsigned size_t to unsigned long +*/ + +unsigned long curlx_uztoul(size_t uznum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + +#if (SIZEOF_LONG < SIZEOF_SIZE_T) + DEBUGASSERT(uznum <= (size_t) CURL_MASK_ULONG); +#endif + return (unsigned long)(uznum & (size_t) CURL_MASK_ULONG); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** unsigned size_t to unsigned int +*/ + +unsigned int curlx_uztoui(size_t uznum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + +#if (SIZEOF_INT < SIZEOF_SIZE_T) + DEBUGASSERT(uznum <= (size_t) CURL_MASK_UINT); +#endif + return (unsigned int)(uznum & (size_t) CURL_MASK_UINT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** signed long to signed int +*/ + +int curlx_sltosi(long slnum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(slnum >= 0); +#if (SIZEOF_INT < SIZEOF_LONG) + DEBUGASSERT((unsigned long) slnum <= (unsigned long) CURL_MASK_SINT); +#endif + return (int)(slnum & (long) CURL_MASK_SINT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** signed long to unsigned int +*/ + +unsigned int curlx_sltoui(long slnum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(slnum >= 0); +#if (SIZEOF_INT < SIZEOF_LONG) + DEBUGASSERT((unsigned long) slnum <= (unsigned long) CURL_MASK_UINT); +#endif + return (unsigned int)(slnum & (long) CURL_MASK_UINT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** signed long to unsigned short +*/ + +unsigned short curlx_sltous(long slnum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(slnum >= 0); + DEBUGASSERT((unsigned long) slnum <= (unsigned long) CURL_MASK_USHORT); + return (unsigned short)(slnum & (long) CURL_MASK_USHORT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** unsigned size_t to signed ssize_t +*/ + +ssize_t curlx_uztosz(size_t uznum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(uznum <= (size_t) CURL_MASK_SSIZE_T); + return (ssize_t)(uznum & (size_t) CURL_MASK_SSIZE_T); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** signed curl_off_t to unsigned size_t +*/ + +size_t curlx_sotouz(curl_off_t sonum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(sonum >= 0); + return (size_t)(sonum & (curl_off_t) CURL_MASK_USIZE_T); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** signed ssize_t to signed int +*/ + +int curlx_sztosi(ssize_t sznum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(sznum >= 0); +#if (SIZEOF_INT < SIZEOF_SIZE_T) + DEBUGASSERT((size_t) sznum <= (size_t) CURL_MASK_SINT); +#endif + return (int)(sznum & (ssize_t) CURL_MASK_SINT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** unsigned int to unsigned short +*/ + +unsigned short curlx_uitous(unsigned int uinum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(uinum <= (unsigned int) CURL_MASK_USHORT); + return (unsigned short) (uinum & (unsigned int) CURL_MASK_USHORT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** signed int to unsigned size_t +*/ + +size_t curlx_sitouz(int sinum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(sinum >= 0); + return (size_t) sinum; + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +#ifdef USE_WINSOCK + +/* +** curl_socket_t to signed int +*/ + +int curlx_sktosi(curl_socket_t s) +{ + return (int)((ssize_t) s); +} + +/* +** signed int to curl_socket_t +*/ + +curl_socket_t curlx_sitosk(int i) +{ + return (curl_socket_t)((ssize_t) i); +} + +#endif /* USE_WINSOCK */ + +#if defined(WIN32) || defined(_WIN32) + +ssize_t curlx_read(int fd, void *buf, size_t count) +{ + return (ssize_t)read(fd, buf, curlx_uztoui(count)); +} + +ssize_t curlx_write(int fd, const void *buf, size_t count) +{ + return (ssize_t)write(fd, buf, curlx_uztoui(count)); +} + +#endif /* WIN32 || _WIN32 */ + +#if defined(__INTEL_COMPILER) && defined(__unix__) + +int curlx_FD_ISSET(int fd, fd_set *fdset) +{ + #pragma warning(push) + #pragma warning(disable:1469) /* clobber ignored */ + return FD_ISSET(fd, fdset); + #pragma warning(pop) +} + +void curlx_FD_SET(int fd, fd_set *fdset) +{ + #pragma warning(push) + #pragma warning(disable:1469) /* clobber ignored */ + FD_SET(fd, fdset); + #pragma warning(pop) +} + +void curlx_FD_ZERO(fd_set *fdset) +{ + #pragma warning(push) + #pragma warning(disable:593) /* variable was set but never used */ + FD_ZERO(fdset); + #pragma warning(pop) +} + +unsigned short curlx_htons(unsigned short usnum) +{ +#if (__INTEL_COMPILER == 910) && defined(__i386__) + return (unsigned short)(((usnum << 8) & 0xFF00) | ((usnum >> 8) & 0x00FF)); +#else + #pragma warning(push) + #pragma warning(disable:810) /* conversion may lose significant bits */ + return htons(usnum); + #pragma warning(pop) +#endif +} + +unsigned short curlx_ntohs(unsigned short usnum) +{ +#if (__INTEL_COMPILER == 910) && defined(__i386__) + return (unsigned short)(((usnum << 8) & 0xFF00) | ((usnum >> 8) & 0x00FF)); +#else + #pragma warning(push) + #pragma warning(disable:810) /* conversion may lose significant bits */ + return ntohs(usnum); + #pragma warning(pop) +#endif +} + +#endif /* __INTEL_COMPILER && __unix__ */ diff --git a/dependencies/cmcurl/lib/warnless.h b/dependencies/cmcurl/lib/warnless.h new file mode 100644 index 0000000..ea4c439 --- /dev/null +++ b/dependencies/cmcurl/lib/warnless.h @@ -0,0 +1,112 @@ +#ifndef HEADER_CURL_WARNLESS_H +#define HEADER_CURL_WARNLESS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifdef USE_WINSOCK +#include /* for curl_socket_t */ +#endif + +#define CURLX_FUNCTION_CAST(target_type, func) \ + (target_type)(void (*) (void))(func) + +unsigned short curlx_ultous(unsigned long ulnum); + +unsigned char curlx_ultouc(unsigned long ulnum); + +int curlx_ultosi(unsigned long ulnum); + +int curlx_uztosi(size_t uznum); + +curl_off_t curlx_uztoso(size_t uznum); + +unsigned long curlx_uztoul(size_t uznum); + +unsigned int curlx_uztoui(size_t uznum); + +int curlx_sltosi(long slnum); + +unsigned int curlx_sltoui(long slnum); + +unsigned short curlx_sltous(long slnum); + +ssize_t curlx_uztosz(size_t uznum); + +size_t curlx_sotouz(curl_off_t sonum); + +int curlx_sztosi(ssize_t sznum); + +unsigned short curlx_uitous(unsigned int uinum); + +size_t curlx_sitouz(int sinum); + +#ifdef USE_WINSOCK + +int curlx_sktosi(curl_socket_t s); + +curl_socket_t curlx_sitosk(int i); + +#endif /* USE_WINSOCK */ + +#if defined(WIN32) || defined(_WIN32) + +ssize_t curlx_read(int fd, void *buf, size_t count); + +ssize_t curlx_write(int fd, const void *buf, size_t count); + +#ifndef BUILDING_WARNLESS_C +# undef read +# define read(fd, buf, count) curlx_read(fd, buf, count) +# undef write +# define write(fd, buf, count) curlx_write(fd, buf, count) +#endif + +#endif /* WIN32 || _WIN32 */ + +#if defined(__INTEL_COMPILER) && defined(__unix__) + +int curlx_FD_ISSET(int fd, fd_set *fdset); + +void curlx_FD_SET(int fd, fd_set *fdset); + +void curlx_FD_ZERO(fd_set *fdset); + +unsigned short curlx_htons(unsigned short usnum); + +unsigned short curlx_ntohs(unsigned short usnum); + +#ifndef BUILDING_WARNLESS_C +# undef FD_ISSET +# define FD_ISSET(a,b) curlx_FD_ISSET((a),(b)) +# undef FD_SET +# define FD_SET(a,b) curlx_FD_SET((a),(b)) +# undef FD_ZERO +# define FD_ZERO(a) curlx_FD_ZERO((a)) +# undef htons +# define htons(a) curlx_htons((a)) +# undef ntohs +# define ntohs(a) curlx_ntohs((a)) +#endif + +#endif /* __INTEL_COMPILER && __unix__ */ + +#endif /* HEADER_CURL_WARNLESS_H */ diff --git a/dependencies/cmcurl/lib/wildcard.c b/dependencies/cmcurl/lib/wildcard.c new file mode 100644 index 0000000..e94d3c5 --- /dev/null +++ b/dependencies/cmcurl/lib/wildcard.c @@ -0,0 +1,73 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_FTP + +#include "wildcard.h" +#include "llist.h" +#include "fileinfo.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +static void fileinfo_dtor(void *user, void *element) +{ + (void)user; + Curl_fileinfo_cleanup(element); +} + +CURLcode Curl_wildcard_init(struct WildcardData *wc) +{ + Curl_llist_init(&wc->filelist, fileinfo_dtor); + wc->state = CURLWC_INIT; + + return CURLE_OK; +} + +void Curl_wildcard_dtor(struct WildcardData *wc) +{ + if(!wc) + return; + + if(wc->dtor) { + wc->dtor(wc->protdata); + wc->dtor = ZERO_NULL; + wc->protdata = NULL; + } + DEBUGASSERT(wc->protdata == NULL); + + Curl_llist_destroy(&wc->filelist, NULL); + + + free(wc->path); + wc->path = NULL; + free(wc->pattern); + wc->pattern = NULL; + + wc->customptr = NULL; + wc->state = CURLWC_INIT; +} + +#endif /* if disabled */ diff --git a/dependencies/cmcurl/lib/wildcard.h b/dependencies/cmcurl/lib/wildcard.h new file mode 100644 index 0000000..306c8c9 --- /dev/null +++ b/dependencies/cmcurl/lib/wildcard.h @@ -0,0 +1,67 @@ +#ifndef HEADER_CURL_WILDCARD_H +#define HEADER_CURL_WILDCARD_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_FTP +#include "llist.h" + +/* list of wildcard process states */ +typedef enum { + CURLWC_CLEAR = 0, + CURLWC_INIT = 1, + CURLWC_MATCHING, /* library is trying to get list of addresses for + downloading */ + CURLWC_DOWNLOADING, + CURLWC_CLEAN, /* deallocate resources and reset settings */ + CURLWC_SKIP, /* skip over concrete file */ + CURLWC_ERROR, /* error cases */ + CURLWC_DONE /* if is wildcard->state == CURLWC_DONE wildcard loop + will end */ +} curl_wildcard_states; + +typedef void (*curl_wildcard_dtor)(void *ptr); + +/* struct keeping information about wildcard download process */ +struct WildcardData { + curl_wildcard_states state; + char *path; /* path to the directory, where we trying wildcard-match */ + char *pattern; /* wildcard pattern */ + struct curl_llist filelist; /* llist with struct Curl_fileinfo */ + void *protdata; /* pointer to protocol specific temporary data */ + curl_wildcard_dtor dtor; + void *customptr; /* for CURLOPT_CHUNK_DATA pointer */ +}; + +CURLcode Curl_wildcard_init(struct WildcardData *wc); +void Curl_wildcard_dtor(struct WildcardData *wc); + +struct Curl_easy; + +#else +/* FTP is disabled */ +#define Curl_wildcard_dtor(x) +#endif + +#endif /* HEADER_CURL_WILDCARD_H */ diff --git a/dependencies/cmcurl/lib/x509asn1.c b/dependencies/cmcurl/lib/x509asn1.c new file mode 100644 index 0000000..0c1256b --- /dev/null +++ b/dependencies/cmcurl/lib/x509asn1.c @@ -0,0 +1,1283 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_GSKIT) || defined(USE_NSS) || defined(USE_GNUTLS) || \ + defined(USE_CYASSL) || defined(USE_SCHANNEL) + +#include +#include "urldata.h" +#include "strcase.h" +#include "hostcheck.h" +#include "vtls/vtls.h" +#include "sendf.h" +#include "inet_pton.h" +#include "curl_base64.h" +#include "x509asn1.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* ASN.1 OIDs. */ +static const char cnOID[] = "2.5.4.3"; /* Common name. */ +static const char sanOID[] = "2.5.29.17"; /* Subject alternative name. */ + +static const curl_OID OIDtable[] = { + { "1.2.840.10040.4.1", "dsa" }, + { "1.2.840.10040.4.3", "dsa-with-sha1" }, + { "1.2.840.10045.2.1", "ecPublicKey" }, + { "1.2.840.10045.3.0.1", "c2pnb163v1" }, + { "1.2.840.10045.4.1", "ecdsa-with-SHA1" }, + { "1.2.840.10046.2.1", "dhpublicnumber" }, + { "1.2.840.113549.1.1.1", "rsaEncryption" }, + { "1.2.840.113549.1.1.2", "md2WithRSAEncryption" }, + { "1.2.840.113549.1.1.4", "md5WithRSAEncryption" }, + { "1.2.840.113549.1.1.5", "sha1WithRSAEncryption" }, + { "1.2.840.113549.1.1.10", "RSASSA-PSS" }, + { "1.2.840.113549.1.1.14", "sha224WithRSAEncryption" }, + { "1.2.840.113549.1.1.11", "sha256WithRSAEncryption" }, + { "1.2.840.113549.1.1.12", "sha384WithRSAEncryption" }, + { "1.2.840.113549.1.1.13", "sha512WithRSAEncryption" }, + { "1.2.840.113549.2.2", "md2" }, + { "1.2.840.113549.2.5", "md5" }, + { "1.3.14.3.2.26", "sha1" }, + { cnOID, "CN" }, + { "2.5.4.4", "SN" }, + { "2.5.4.5", "serialNumber" }, + { "2.5.4.6", "C" }, + { "2.5.4.7", "L" }, + { "2.5.4.8", "ST" }, + { "2.5.4.9", "streetAddress" }, + { "2.5.4.10", "O" }, + { "2.5.4.11", "OU" }, + { "2.5.4.12", "title" }, + { "2.5.4.13", "description" }, + { "2.5.4.17", "postalCode" }, + { "2.5.4.41", "name" }, + { "2.5.4.42", "givenName" }, + { "2.5.4.43", "initials" }, + { "2.5.4.44", "generationQualifier" }, + { "2.5.4.45", "X500UniqueIdentifier" }, + { "2.5.4.46", "dnQualifier" }, + { "2.5.4.65", "pseudonym" }, + { "1.2.840.113549.1.9.1", "emailAddress" }, + { "2.5.4.72", "role" }, + { sanOID, "subjectAltName" }, + { "2.5.29.18", "issuerAltName" }, + { "2.5.29.19", "basicConstraints" }, + { "2.16.840.1.101.3.4.2.4", "sha224" }, + { "2.16.840.1.101.3.4.2.1", "sha256" }, + { "2.16.840.1.101.3.4.2.2", "sha384" }, + { "2.16.840.1.101.3.4.2.3", "sha512" }, + { (const char *) NULL, (const char *) NULL } +}; + +/* + * Lightweight ASN.1 parser. + * In particular, it does not check for syntactic/lexical errors. + * It is intended to support certificate information gathering for SSL backends + * that offer a mean to get certificates as a whole, but do not supply + * entry points to get particular certificate sub-fields. + * Please note there is no pretention here to rewrite a full SSL library. + */ + +static const char *getASN1Element(curl_asn1Element *elem, + const char *beg, const char *end) + WARN_UNUSED_RESULT; + +static const char *getASN1Element(curl_asn1Element *elem, + const char *beg, const char *end) +{ + unsigned char b; + unsigned long len; + curl_asn1Element lelem; + + /* Get a single ASN.1 element into `elem', parse ASN.1 string at `beg' + ending at `end'. + Returns a pointer in source string after the parsed element, or NULL + if an error occurs. */ + if(!beg || !end || beg >= end || !*beg || + (size_t)(end - beg) > CURL_ASN1_MAX) + return NULL; + + /* Process header byte. */ + elem->header = beg; + b = (unsigned char) *beg++; + elem->constructed = (b & 0x20) != 0; + elem->class = (b >> 6) & 3; + b &= 0x1F; + if(b == 0x1F) + return NULL; /* Long tag values not supported here. */ + elem->tag = b; + + /* Process length. */ + if(beg >= end) + return NULL; + b = (unsigned char) *beg++; + if(!(b & 0x80)) + len = b; + else if(!(b &= 0x7F)) { + /* Unspecified length. Since we have all the data, we can determine the + effective length by skipping element until an end element is found. */ + if(!elem->constructed) + return NULL; + elem->beg = beg; + while(beg < end && *beg) { + beg = getASN1Element(&lelem, beg, end); + if(!beg) + return NULL; + } + if(beg >= end) + return NULL; + elem->end = beg; + return beg + 1; + } + else if((unsigned)b > (size_t)(end - beg)) + return NULL; /* Does not fit in source. */ + else { + /* Get long length. */ + len = 0; + do { + if(len & 0xFF000000L) + return NULL; /* Lengths > 32 bits are not supported. */ + len = (len << 8) | (unsigned char) *beg++; + } while(--b); + } + if(len > (size_t)(end - beg)) + return NULL; /* Element data does not fit in source. */ + elem->beg = beg; + elem->end = beg + len; + return elem->end; +} + +/* + * Search the null terminated OID or OID identifier in local table. + * Return the table entry pointer or NULL if not found. + */ +static const curl_OID * searchOID(const char *oid) +{ + const curl_OID *op; + for(op = OIDtable; op->numoid; op++) + if(!strcmp(op->numoid, oid) || strcasecompare(op->textoid, oid)) + return op; + + return NULL; +} + +/* + * Convert an ASN.1 Boolean value into its string representation. Return the + * dynamically allocated string, or NULL if source is not an ASN.1 Boolean + * value. + */ + +static const char *bool2str(const char *beg, const char *end) +{ + if(end - beg != 1) + return NULL; + return strdup(*beg? "TRUE": "FALSE"); +} + +/* + * Convert an ASN.1 octet string to a printable string. + * Return the dynamically allocated string, or NULL if an error occurs. + */ +static const char *octet2str(const char *beg, const char *end) +{ + size_t n = end - beg; + char *buf = NULL; + + if(n <= (SIZE_T_MAX - 1) / 3) { + buf = malloc(3 * n + 1); + if(buf) + for(n = 0; beg < end; n += 3) + msnprintf(buf + n, 4, "%02x:", *(const unsigned char *) beg++); + } + return buf; +} + +static const char *bit2str(const char *beg, const char *end) +{ + /* Convert an ASN.1 bit string to a printable string. + Return the dynamically allocated string, or NULL if an error occurs. */ + + if(++beg > end) + return NULL; + return octet2str(beg, end); +} + +/* + * Convert an ASN.1 integer value into its string representation. + * Return the dynamically allocated string, or NULL if source is not an + * ASN.1 integer value. + */ +static const char *int2str(const char *beg, const char *end) +{ + unsigned long val = 0; + size_t n = end - beg; + + if(!n) + return NULL; + + if(n > 4) + return octet2str(beg, end); + + /* Represent integers <= 32-bit as a single value. */ + if(*beg & 0x80) + val = ~val; + + do + val = (val << 8) | *(const unsigned char *) beg++; + while(beg < end); + return curl_maprintf("%s%lx", val >= 10? "0x": "", val); +} + +/* + * Perform a lazy conversion from an ASN.1 typed string to UTF8. Allocate the + * destination buffer dynamically. The allocation size will normally be too + * large: this is to avoid buffer overflows. + * Terminate the string with a nul byte and return the converted + * string length. + */ +static ssize_t +utf8asn1str(char **to, int type, const char *from, const char *end) +{ + size_t inlength = end - from; + int size = 1; + size_t outlength; + char *buf; + + *to = NULL; + switch(type) { + case CURL_ASN1_BMP_STRING: + size = 2; + break; + case CURL_ASN1_UNIVERSAL_STRING: + size = 4; + break; + case CURL_ASN1_NUMERIC_STRING: + case CURL_ASN1_PRINTABLE_STRING: + case CURL_ASN1_TELETEX_STRING: + case CURL_ASN1_IA5_STRING: + case CURL_ASN1_VISIBLE_STRING: + case CURL_ASN1_UTF8_STRING: + break; + default: + return -1; /* Conversion not supported. */ + } + + if(inlength % size) + return -1; /* Length inconsistent with character size. */ + if(inlength / size > (SIZE_T_MAX - 1) / 4) + return -1; /* Too big. */ + buf = malloc(4 * (inlength / size) + 1); + if(!buf) + return -1; /* Not enough memory. */ + + if(type == CURL_ASN1_UTF8_STRING) { + /* Just copy. */ + outlength = inlength; + if(outlength) + memcpy(buf, from, outlength); + } + else { + for(outlength = 0; from < end;) { + int charsize; + unsigned int wc; + + wc = 0; + switch(size) { + case 4: + wc = (wc << 8) | *(const unsigned char *) from++; + wc = (wc << 8) | *(const unsigned char *) from++; + /* FALLTHROUGH */ + case 2: + wc = (wc << 8) | *(const unsigned char *) from++; + /* FALLTHROUGH */ + default: /* case 1: */ + wc = (wc << 8) | *(const unsigned char *) from++; + } + charsize = 1; + if(wc >= 0x00000080) { + if(wc >= 0x00000800) { + if(wc >= 0x00010000) { + if(wc >= 0x00200000) { + free(buf); + return -1; /* Invalid char. size for target encoding. */ + } + buf[outlength + 3] = (char) (0x80 | (wc & 0x3F)); + wc = (wc >> 6) | 0x00010000; + charsize++; + } + buf[outlength + 2] = (char) (0x80 | (wc & 0x3F)); + wc = (wc >> 6) | 0x00000800; + charsize++; + } + buf[outlength + 1] = (char) (0x80 | (wc & 0x3F)); + wc = (wc >> 6) | 0x000000C0; + charsize++; + } + buf[outlength] = (char) wc; + outlength += charsize; + } + } + buf[outlength] = '\0'; + *to = buf; + return outlength; +} + +/* + * Convert an ASN.1 String into its UTF-8 string representation. + * Return the dynamically allocated string, or NULL if an error occurs. + */ +static const char *string2str(int type, const char *beg, const char *end) +{ + char *buf; + if(utf8asn1str(&buf, type, beg, end) < 0) + return NULL; + return buf; +} + +/* + * Decimal ASCII encode unsigned integer `x' into the buflen sized buffer at + * buf. Return the total number of encoded digits, even if larger than + * `buflen'. + */ +static size_t encodeUint(char *buf, size_t buflen, unsigned int x) +{ + size_t i = 0; + unsigned int y = x / 10; + + if(y) { + i = encodeUint(buf, buflen, y); + x -= y * 10; + } + if(i < buflen) + buf[i] = (char) ('0' + x); + i++; + if(i < buflen) + buf[i] = '\0'; /* Store a terminator if possible. */ + return i; +} + +/* + * Convert an ASN.1 OID into its dotted string representation. + * Store the result in th `n'-byte buffer at `buf'. + * Return the converted string length, or 0 on errors. + */ +static size_t encodeOID(char *buf, size_t buflen, + const char *beg, const char *end) +{ + size_t i; + unsigned int x; + unsigned int y; + + /* Process the first two numbers. */ + y = *(const unsigned char *) beg++; + x = y / 40; + y -= x * 40; + i = encodeUint(buf, buflen, x); + if(i < buflen) + buf[i] = '.'; + i++; + if(i >= buflen) + i += encodeUint(NULL, 0, y); + else + i += encodeUint(buf + i, buflen - i, y); + + /* Process the trailing numbers. */ + while(beg < end) { + if(i < buflen) + buf[i] = '.'; + i++; + x = 0; + do { + if(x & 0xFF000000) + return 0; + y = *(const unsigned char *) beg++; + x = (x << 7) | (y & 0x7F); + } while(y & 0x80); + if(i >= buflen) + i += encodeUint(NULL, 0, x); + else + i += encodeUint(buf + i, buflen - i, x); + } + if(i < buflen) + buf[i] = '\0'; + return i; +} + +/* + * Convert an ASN.1 OID into its dotted or symbolic string representation. + * Return the dynamically allocated string, or NULL if an error occurs. + */ + +static const char *OID2str(const char *beg, const char *end, bool symbolic) +{ + char *buf = NULL; + if(beg < end) { + size_t buflen = encodeOID(NULL, 0, beg, end); + if(buflen) { + buf = malloc(buflen + 1); /* one extra for the zero byte */ + if(buf) { + encodeOID(buf, buflen, beg, end); + buf[buflen] = '\0'; + + if(symbolic) { + const curl_OID *op = searchOID(buf); + if(op) { + free(buf); + buf = strdup(op->textoid); + } + } + } + } + } + return buf; +} + +static const char *GTime2str(const char *beg, const char *end) +{ + const char *tzp; + const char *fracp; + char sec1, sec2; + size_t fracl; + size_t tzl; + const char *sep = ""; + + /* Convert an ASN.1 Generalized time to a printable string. + Return the dynamically allocated string, or NULL if an error occurs. */ + + for(fracp = beg; fracp < end && *fracp >= '0' && *fracp <= '9'; fracp++) + ; + + /* Get seconds digits. */ + sec1 = '0'; + switch(fracp - beg - 12) { + case 0: + sec2 = '0'; + break; + case 2: + sec1 = fracp[-2]; + /* FALLTHROUGH */ + case 1: + sec2 = fracp[-1]; + break; + default: + return NULL; + } + + /* Scan for timezone, measure fractional seconds. */ + tzp = fracp; + fracl = 0; + if(fracp < end && (*fracp == '.' || *fracp == ',')) { + fracp++; + do + tzp++; + while(tzp < end && *tzp >= '0' && *tzp <= '9'); + /* Strip leading zeroes in fractional seconds. */ + for(fracl = tzp - fracp - 1; fracl && fracp[fracl - 1] == '0'; fracl--) + ; + } + + /* Process timezone. */ + if(tzp >= end) + ; /* Nothing to do. */ + else if(*tzp == 'Z') { + tzp = " GMT"; + end = tzp + 4; + } + else { + sep = " "; + tzp++; + } + + tzl = end - tzp; + return curl_maprintf("%.4s-%.2s-%.2s %.2s:%.2s:%c%c%s%.*s%s%.*s", + beg, beg + 4, beg + 6, + beg + 8, beg + 10, sec1, sec2, + fracl? ".": "", fracl, fracp, + sep, tzl, tzp); +} + +/* + * Convert an ASN.1 UTC time to a printable string. + * Return the dynamically allocated string, or NULL if an error occurs. + */ +static const char *UTime2str(const char *beg, const char *end) +{ + const char *tzp; + size_t tzl; + const char *sec; + + for(tzp = beg; tzp < end && *tzp >= '0' && *tzp <= '9'; tzp++) + ; + /* Get the seconds. */ + sec = beg + 10; + switch(tzp - sec) { + case 0: + sec = "00"; + case 2: + break; + default: + return NULL; + } + + /* Process timezone. */ + if(tzp >= end) + return NULL; + if(*tzp == 'Z') { + tzp = "GMT"; + end = tzp + 3; + } + else + tzp++; + + tzl = end - tzp; + return curl_maprintf("%u%.2s-%.2s-%.2s %.2s:%.2s:%.2s %.*s", + 20 - (*beg >= '5'), beg, beg + 2, beg + 4, + beg + 6, beg + 8, sec, + tzl, tzp); +} + +/* + * Convert an ASN.1 element to a printable string. + * Return the dynamically allocated string, or NULL if an error occurs. + */ +static const char *ASN1tostr(curl_asn1Element *elem, int type) +{ + if(elem->constructed) + return NULL; /* No conversion of structured elements. */ + + if(!type) + type = elem->tag; /* Type not forced: use element tag as type. */ + + switch(type) { + case CURL_ASN1_BOOLEAN: + return bool2str(elem->beg, elem->end); + case CURL_ASN1_INTEGER: + case CURL_ASN1_ENUMERATED: + return int2str(elem->beg, elem->end); + case CURL_ASN1_BIT_STRING: + return bit2str(elem->beg, elem->end); + case CURL_ASN1_OCTET_STRING: + return octet2str(elem->beg, elem->end); + case CURL_ASN1_NULL: + return strdup(""); + case CURL_ASN1_OBJECT_IDENTIFIER: + return OID2str(elem->beg, elem->end, TRUE); + case CURL_ASN1_UTC_TIME: + return UTime2str(elem->beg, elem->end); + case CURL_ASN1_GENERALIZED_TIME: + return GTime2str(elem->beg, elem->end); + case CURL_ASN1_UTF8_STRING: + case CURL_ASN1_NUMERIC_STRING: + case CURL_ASN1_PRINTABLE_STRING: + case CURL_ASN1_TELETEX_STRING: + case CURL_ASN1_IA5_STRING: + case CURL_ASN1_VISIBLE_STRING: + case CURL_ASN1_UNIVERSAL_STRING: + case CURL_ASN1_BMP_STRING: + return string2str(type, elem->beg, elem->end); + } + + return NULL; /* Unsupported. */ +} + +/* + * ASCII encode distinguished name at `dn' into the `buflen'-sized buffer at + * `buf'. Return the total string length, even if larger than `buflen'. + */ +static ssize_t encodeDN(char *buf, size_t buflen, curl_asn1Element *dn) +{ + curl_asn1Element rdn; + curl_asn1Element atv; + curl_asn1Element oid; + curl_asn1Element value; + size_t l = 0; + const char *p1; + const char *p2; + const char *p3; + const char *str; + + for(p1 = dn->beg; p1 < dn->end;) { + p1 = getASN1Element(&rdn, p1, dn->end); + if(!p1) + return -1; + for(p2 = rdn.beg; p2 < rdn.end;) { + p2 = getASN1Element(&atv, p2, rdn.end); + if(!p2) + return -1; + p3 = getASN1Element(&oid, atv.beg, atv.end); + if(!p3) + return -1; + if(!getASN1Element(&value, p3, atv.end)) + return -1; + str = ASN1tostr(&oid, 0); + if(!str) + return -1; + + /* Encode delimiter. + If attribute has a short uppercase name, delimiter is ", ". */ + if(l) { + for(p3 = str; isupper(*p3); p3++) + ; + for(p3 = (*p3 || p3 - str > 2)? "/": ", "; *p3; p3++) { + if(l < buflen) + buf[l] = *p3; + l++; + } + } + + /* Encode attribute name. */ + for(p3 = str; *p3; p3++) { + if(l < buflen) + buf[l] = *p3; + l++; + } + free((char *) str); + + /* Generate equal sign. */ + if(l < buflen) + buf[l] = '='; + l++; + + /* Generate value. */ + str = ASN1tostr(&value, 0); + if(!str) + return -1; + for(p3 = str; *p3; p3++) { + if(l < buflen) + buf[l] = *p3; + l++; + } + free((char *) str); + } + } + + return l; +} + +/* + * Convert an ASN.1 distinguished name into a printable string. + * Return the dynamically allocated string, or NULL if an error occurs. + */ +static const char *DNtostr(curl_asn1Element *dn) +{ + char *buf = NULL; + ssize_t buflen = encodeDN(NULL, 0, dn); + + if(buflen >= 0) { + buf = malloc(buflen + 1); + if(buf) { + encodeDN(buf, buflen + 1, dn); + buf[buflen] = '\0'; + } + } + return buf; +} + +/* + * ASN.1 parse an X509 certificate into structure subfields. + * Syntax is assumed to have already been checked by the SSL backend. + * See RFC 5280. + */ +int Curl_parseX509(curl_X509certificate *cert, + const char *beg, const char *end) +{ + curl_asn1Element elem; + curl_asn1Element tbsCertificate; + const char *ccp; + static const char defaultVersion = 0; /* v1. */ + + cert->certificate.header = NULL; + cert->certificate.beg = beg; + cert->certificate.end = end; + + /* Get the sequence content. */ + if(!getASN1Element(&elem, beg, end)) + return -1; /* Invalid bounds/size. */ + beg = elem.beg; + end = elem.end; + + /* Get tbsCertificate. */ + beg = getASN1Element(&tbsCertificate, beg, end); + if(!beg) + return -1; + /* Skip the signatureAlgorithm. */ + beg = getASN1Element(&cert->signatureAlgorithm, beg, end); + if(!beg) + return -1; + /* Get the signatureValue. */ + if(!getASN1Element(&cert->signature, beg, end)) + return -1; + + /* Parse TBSCertificate. */ + beg = tbsCertificate.beg; + end = tbsCertificate.end; + /* Get optional version, get serialNumber. */ + cert->version.header = NULL; + cert->version.beg = &defaultVersion; + cert->version.end = &defaultVersion + sizeof(defaultVersion); + beg = getASN1Element(&elem, beg, end); + if(!beg) + return -1; + if(elem.tag == 0) { + if(!getASN1Element(&cert->version, elem.beg, elem.end)) + return -1; + beg = getASN1Element(&elem, beg, end); + if(!beg) + return -1; + } + cert->serialNumber = elem; + /* Get signature algorithm. */ + beg = getASN1Element(&cert->signatureAlgorithm, beg, end); + /* Get issuer. */ + beg = getASN1Element(&cert->issuer, beg, end); + if(!beg) + return -1; + /* Get notBefore and notAfter. */ + beg = getASN1Element(&elem, beg, end); + if(!beg) + return -1; + ccp = getASN1Element(&cert->notBefore, elem.beg, elem.end); + if(!ccp) + return -1; + if(!getASN1Element(&cert->notAfter, ccp, elem.end)) + return -1; + /* Get subject. */ + beg = getASN1Element(&cert->subject, beg, end); + if(!beg) + return -1; + /* Get subjectPublicKeyAlgorithm and subjectPublicKey. */ + beg = getASN1Element(&cert->subjectPublicKeyInfo, beg, end); + if(!beg) + return -1; + ccp = getASN1Element(&cert->subjectPublicKeyAlgorithm, + cert->subjectPublicKeyInfo.beg, + cert->subjectPublicKeyInfo.end); + if(!ccp) + return -1; + if(!getASN1Element(&cert->subjectPublicKey, ccp, + cert->subjectPublicKeyInfo.end)) + return -1; + /* Get optional issuerUiqueID, subjectUniqueID and extensions. */ + cert->issuerUniqueID.tag = cert->subjectUniqueID.tag = 0; + cert->extensions.tag = elem.tag = 0; + cert->issuerUniqueID.header = cert->subjectUniqueID.header = NULL; + cert->issuerUniqueID.beg = cert->issuerUniqueID.end = ""; + cert->subjectUniqueID.beg = cert->subjectUniqueID.end = ""; + cert->extensions.header = NULL; + cert->extensions.beg = cert->extensions.end = ""; + if(beg < end) { + beg = getASN1Element(&elem, beg, end); + if(!beg) + return -1; + } + if(elem.tag == 1) { + cert->issuerUniqueID = elem; + if(beg < end) { + beg = getASN1Element(&elem, beg, end); + if(!beg) + return -1; + } + } + if(elem.tag == 2) { + cert->subjectUniqueID = elem; + if(beg < end) { + beg = getASN1Element(&elem, beg, end); + if(!beg) + return -1; + } + } + if(elem.tag == 3) + if(!getASN1Element(&cert->extensions, elem.beg, elem.end)) + return -1; + return 0; +} + + +/* + * Copy at most 64-characters, terminate with a newline and returns the + * effective number of stored characters. + */ +static size_t copySubstring(char *to, const char *from) +{ + size_t i; + for(i = 0; i < 64; i++) { + to[i] = *from; + if(!*from++) + break; + } + + to[i++] = '\n'; + return i; +} + +static const char *dumpAlgo(curl_asn1Element *param, + const char *beg, const char *end) +{ + curl_asn1Element oid; + + /* Get algorithm parameters and return algorithm name. */ + + beg = getASN1Element(&oid, beg, end); + if(!beg) + return NULL; + param->header = NULL; + param->tag = 0; + param->beg = param->end = end; + if(beg < end) + if(!getASN1Element(param, beg, end)) + return NULL; + return OID2str(oid.beg, oid.end, TRUE); +} + +static void do_pubkey_field(struct Curl_easy *data, int certnum, + const char *label, curl_asn1Element *elem) +{ + const char *output; + + /* Generate a certificate information record for the public key. */ + + output = ASN1tostr(elem, 0); + if(output) { + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, label, output); + if(!certnum) + infof(data, " %s: %s\n", label, output); + free((char *) output); + } +} + +static void do_pubkey(struct Curl_easy *data, int certnum, + const char *algo, curl_asn1Element *param, + curl_asn1Element *pubkey) +{ + curl_asn1Element elem; + curl_asn1Element pk; + const char *p; + + /* Generate all information records for the public key. */ + + /* Get the public key (single element). */ + if(!getASN1Element(&pk, pubkey->beg + 1, pubkey->end)) + return; + + if(strcasecompare(algo, "rsaEncryption")) { + const char *q; + unsigned long len; + + p = getASN1Element(&elem, pk.beg, pk.end); + if(!p) + return; + + /* Compute key length. */ + for(q = elem.beg; !*q && q < elem.end; q++) + ; + len = (unsigned long)((elem.end - q) * 8); + if(len) { + unsigned int i; + for(i = *(unsigned char *) q; !(i & 0x80); i <<= 1) + len--; + } + if(len > 32) + elem.beg = q; /* Strip leading zero bytes. */ + if(!certnum) + infof(data, " RSA Public Key (%lu bits)\n", len); + if(data->set.ssl.certinfo) { + q = curl_maprintf("%lu", len); + if(q) { + Curl_ssl_push_certinfo(data, certnum, "RSA Public Key", q); + free((char *) q); + } + } + /* Generate coefficients. */ + do_pubkey_field(data, certnum, "rsa(n)", &elem); + if(!getASN1Element(&elem, p, pk.end)) + return; + do_pubkey_field(data, certnum, "rsa(e)", &elem); + } + else if(strcasecompare(algo, "dsa")) { + p = getASN1Element(&elem, param->beg, param->end); + if(p) { + do_pubkey_field(data, certnum, "dsa(p)", &elem); + p = getASN1Element(&elem, p, param->end); + if(p) { + do_pubkey_field(data, certnum, "dsa(q)", &elem); + if(getASN1Element(&elem, p, param->end)) { + do_pubkey_field(data, certnum, "dsa(g)", &elem); + do_pubkey_field(data, certnum, "dsa(pub_key)", &pk); + } + } + } + } + else if(strcasecompare(algo, "dhpublicnumber")) { + p = getASN1Element(&elem, param->beg, param->end); + if(p) { + do_pubkey_field(data, certnum, "dh(p)", &elem); + if(getASN1Element(&elem, param->beg, param->end)) { + do_pubkey_field(data, certnum, "dh(g)", &elem); + do_pubkey_field(data, certnum, "dh(pub_key)", &pk); + } + } + } +} + +CURLcode Curl_extract_certinfo(struct connectdata *conn, + int certnum, + const char *beg, + const char *end) +{ + curl_X509certificate cert; + struct Curl_easy *data = conn->data; + curl_asn1Element param; + const char *ccp; + char *cp1; + size_t cl1; + char *cp2; + CURLcode result; + unsigned long version; + size_t i; + size_t j; + + if(!data->set.ssl.certinfo) + if(certnum) + return CURLE_OK; + + /* Prepare the certificate information for curl_easy_getinfo(). */ + + /* Extract the certificate ASN.1 elements. */ + if(Curl_parseX509(&cert, beg, end)) + return CURLE_PEER_FAILED_VERIFICATION; + + /* Subject. */ + ccp = DNtostr(&cert.subject); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Subject", ccp); + if(!certnum) + infof(data, "%2d Subject: %s\n", certnum, ccp); + free((char *) ccp); + + /* Issuer. */ + ccp = DNtostr(&cert.issuer); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Issuer", ccp); + if(!certnum) + infof(data, " Issuer: %s\n", ccp); + free((char *) ccp); + + /* Version (always fits in less than 32 bits). */ + version = 0; + for(ccp = cert.version.beg; ccp < cert.version.end; ccp++) + version = (version << 8) | *(const unsigned char *) ccp; + if(data->set.ssl.certinfo) { + ccp = curl_maprintf("%lx", version); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + Curl_ssl_push_certinfo(data, certnum, "Version", ccp); + free((char *) ccp); + } + if(!certnum) + infof(data, " Version: %lu (0x%lx)\n", version + 1, version); + + /* Serial number. */ + ccp = ASN1tostr(&cert.serialNumber, 0); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Serial Number", ccp); + if(!certnum) + infof(data, " Serial Number: %s\n", ccp); + free((char *) ccp); + + /* Signature algorithm .*/ + ccp = dumpAlgo(¶m, cert.signatureAlgorithm.beg, + cert.signatureAlgorithm.end); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Signature Algorithm", ccp); + if(!certnum) + infof(data, " Signature Algorithm: %s\n", ccp); + free((char *) ccp); + + /* Start Date. */ + ccp = ASN1tostr(&cert.notBefore, 0); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Start Date", ccp); + if(!certnum) + infof(data, " Start Date: %s\n", ccp); + free((char *) ccp); + + /* Expire Date. */ + ccp = ASN1tostr(&cert.notAfter, 0); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Expire Date", ccp); + if(!certnum) + infof(data, " Expire Date: %s\n", ccp); + free((char *) ccp); + + /* Public Key Algorithm. */ + ccp = dumpAlgo(¶m, cert.subjectPublicKeyAlgorithm.beg, + cert.subjectPublicKeyAlgorithm.end); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Public Key Algorithm", ccp); + if(!certnum) + infof(data, " Public Key Algorithm: %s\n", ccp); + do_pubkey(data, certnum, ccp, ¶m, &cert.subjectPublicKey); + free((char *) ccp); + + /* Signature. */ + ccp = ASN1tostr(&cert.signature, 0); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Signature", ccp); + if(!certnum) + infof(data, " Signature: %s\n", ccp); + free((char *) ccp); + + /* Generate PEM certificate. */ + result = Curl_base64_encode(data, cert.certificate.beg, + cert.certificate.end - cert.certificate.beg, + &cp1, &cl1); + if(result) + return result; + /* Compute the number of characters in final certificate string. Format is: + -----BEGIN CERTIFICATE-----\n + \n + . + . + . + -----END CERTIFICATE-----\n + */ + i = 28 + cl1 + (cl1 + 64 - 1) / 64 + 26; + cp2 = malloc(i + 1); + if(!cp2) { + free(cp1); + return CURLE_OUT_OF_MEMORY; + } + /* Build the certificate string. */ + i = copySubstring(cp2, "-----BEGIN CERTIFICATE-----"); + for(j = 0; j < cl1; j += 64) + i += copySubstring(cp2 + i, cp1 + j); + i += copySubstring(cp2 + i, "-----END CERTIFICATE-----"); + cp2[i] = '\0'; + free(cp1); + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Cert", cp2); + if(!certnum) + infof(data, "%s\n", cp2); + free(cp2); + return CURLE_OK; +} + +#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_CYASSL or USE_SCHANNEL */ + +#if defined(USE_GSKIT) + +static const char *checkOID(const char *beg, const char *end, + const char *oid) +{ + curl_asn1Element e; + const char *ccp; + const char *p; + bool matched; + + /* Check if first ASN.1 element at `beg' is the given OID. + Return a pointer in the source after the OID if found, else NULL. */ + + ccp = getASN1Element(&e, beg, end); + if(!ccp || e.tag != CURL_ASN1_OBJECT_IDENTIFIER) + return NULL; + + p = OID2str(e.beg, e.end, FALSE); + if(!p) + return NULL; + + matched = !strcmp(p, oid); + free((char *) p); + return matched? ccp: NULL; +} + +CURLcode Curl_verifyhost(struct connectdata *conn, + const char *beg, const char *end) +{ + struct Curl_easy *data = conn->data; + curl_X509certificate cert; + curl_asn1Element dn; + curl_asn1Element elem; + curl_asn1Element ext; + curl_asn1Element name; + const char *p; + const char *q; + char *dnsname; + int matched = -1; + size_t addrlen = (size_t) -1; + ssize_t len; + const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name: + conn->host.name; + const char * const dispname = SSL_IS_PROXY()? + conn->http_proxy.host.dispname: + conn->host.dispname; +#ifdef ENABLE_IPV6 + struct in6_addr addr; +#else + struct in_addr addr; +#endif + + /* Verify that connection server matches info in X509 certificate at + `beg'..`end'. */ + + if(!SSL_CONN_CONFIG(verifyhost)) + return CURLE_OK; + + if(Curl_parseX509(&cert, beg, end)) + return CURLE_PEER_FAILED_VERIFICATION; + + /* Get the server IP address. */ +#ifdef ENABLE_IPV6 + if(conn->bits.ipv6_ip && Curl_inet_pton(AF_INET6, hostname, &addr)) + addrlen = sizeof(struct in6_addr); + else +#endif + if(Curl_inet_pton(AF_INET, hostname, &addr)) + addrlen = sizeof(struct in_addr); + + /* Process extensions. */ + for(p = cert.extensions.beg; p < cert.extensions.end && matched != 1;) { + p = getASN1Element(&ext, p, cert.extensions.end); + if(!p) + return CURLE_PEER_FAILED_VERIFICATION; + + /* Check if extension is a subjectAlternativeName. */ + ext.beg = checkOID(ext.beg, ext.end, sanOID); + if(ext.beg) { + ext.beg = getASN1Element(&elem, ext.beg, ext.end); + if(!ext.beg) + return CURLE_PEER_FAILED_VERIFICATION; + /* Skip critical if present. */ + if(elem.tag == CURL_ASN1_BOOLEAN) { + ext.beg = getASN1Element(&elem, ext.beg, ext.end); + if(!ext.beg) + return CURLE_PEER_FAILED_VERIFICATION; + } + /* Parse the octet string contents: is a single sequence. */ + if(!getASN1Element(&elem, elem.beg, elem.end)) + return CURLE_PEER_FAILED_VERIFICATION; + /* Check all GeneralNames. */ + for(q = elem.beg; matched != 1 && q < elem.end;) { + q = getASN1Element(&name, q, elem.end); + if(!q) + break; + switch(name.tag) { + case 2: /* DNS name. */ + len = utf8asn1str(&dnsname, CURL_ASN1_IA5_STRING, + name.beg, name.end); + if(len > 0 && (size_t)len == strlen(dnsname)) + matched = Curl_cert_hostcheck(dnsname, hostname); + else + matched = 0; + free(dnsname); + break; + + case 7: /* IP address. */ + matched = (size_t) (name.end - name.beg) == addrlen && + !memcmp(&addr, name.beg, addrlen); + break; + } + } + } + } + + switch(matched) { + case 1: + /* an alternative name matched the server hostname */ + infof(data, "\t subjectAltName: %s matched\n", dispname); + return CURLE_OK; + case 0: + /* an alternative name field existed, but didn't match and then + we MUST fail */ + infof(data, "\t subjectAltName does not match %s\n", dispname); + return CURLE_PEER_FAILED_VERIFICATION; + } + + /* Process subject. */ + name.header = NULL; + name.beg = name.end = ""; + q = cert.subject.beg; + /* we have to look to the last occurrence of a commonName in the + distinguished one to get the most significant one. */ + while(q < cert.subject.end) { + q = getASN1Element(&dn, q, cert.subject.end); + if(!q) + break; + for(p = dn.beg; p < dn.end;) { + p = getASN1Element(&elem, p, dn.end); + if(!p) + return CURLE_PEER_FAILED_VERIFICATION; + /* We have a DN's AttributeTypeAndValue: check it in case it's a CN. */ + elem.beg = checkOID(elem.beg, elem.end, cnOID); + if(elem.beg) + name = elem; /* Latch CN. */ + } + } + + /* Check the CN if found. */ + if(!getASN1Element(&elem, name.beg, name.end)) + failf(data, "SSL: unable to obtain common name from peer certificate"); + else { + len = utf8asn1str(&dnsname, elem.tag, elem.beg, elem.end); + if(len < 0) { + free(dnsname); + return CURLE_OUT_OF_MEMORY; + } + if(strlen(dnsname) != (size_t) len) /* Nul byte in string ? */ + failf(data, "SSL: illegal cert name field"); + else if(Curl_cert_hostcheck((const char *) dnsname, hostname)) { + infof(data, "\t common name: %s (matched)\n", dnsname); + free(dnsname); + return CURLE_OK; + } + else + failf(data, "SSL: certificate subject name '%s' does not match " + "target host name '%s'", dnsname, dispname); + free(dnsname); + } + + return CURLE_PEER_FAILED_VERIFICATION; +} + +#endif /* USE_GSKIT */ diff --git a/dependencies/cmcurl/lib/x509asn1.h b/dependencies/cmcurl/lib/x509asn1.h new file mode 100644 index 0000000..ce40297 --- /dev/null +++ b/dependencies/cmcurl/lib/x509asn1.h @@ -0,0 +1,134 @@ +#ifndef HEADER_CURL_X509ASN1_H +#define HEADER_CURL_X509ASN1_H + +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_GSKIT) || defined(USE_NSS) || defined(USE_GNUTLS) || \ + defined(USE_CYASSL) || defined(USE_SCHANNEL) + +#include "urldata.h" + +/* + * Constants. + */ + +/* Largest supported ASN.1 structure. */ +#define CURL_ASN1_MAX ((size_t) 0x40000) /* 256K */ + +/* ASN.1 classes. */ +#define CURL_ASN1_UNIVERSAL 0 +#define CURL_ASN1_APPLICATION 1 +#define CURL_ASN1_CONTEXT_SPECIFIC 2 +#define CURL_ASN1_PRIVATE 3 + +/* ASN.1 types. */ +#define CURL_ASN1_BOOLEAN 1 +#define CURL_ASN1_INTEGER 2 +#define CURL_ASN1_BIT_STRING 3 +#define CURL_ASN1_OCTET_STRING 4 +#define CURL_ASN1_NULL 5 +#define CURL_ASN1_OBJECT_IDENTIFIER 6 +#define CURL_ASN1_OBJECT_DESCRIPTOR 7 +#define CURL_ASN1_INSTANCE_OF 8 +#define CURL_ASN1_REAL 9 +#define CURL_ASN1_ENUMERATED 10 +#define CURL_ASN1_EMBEDDED 11 +#define CURL_ASN1_UTF8_STRING 12 +#define CURL_ASN1_RELATIVE_OID 13 +#define CURL_ASN1_SEQUENCE 16 +#define CURL_ASN1_SET 17 +#define CURL_ASN1_NUMERIC_STRING 18 +#define CURL_ASN1_PRINTABLE_STRING 19 +#define CURL_ASN1_TELETEX_STRING 20 +#define CURL_ASN1_VIDEOTEX_STRING 21 +#define CURL_ASN1_IA5_STRING 22 +#define CURL_ASN1_UTC_TIME 23 +#define CURL_ASN1_GENERALIZED_TIME 24 +#define CURL_ASN1_GRAPHIC_STRING 25 +#define CURL_ASN1_VISIBLE_STRING 26 +#define CURL_ASN1_GENERAL_STRING 27 +#define CURL_ASN1_UNIVERSAL_STRING 28 +#define CURL_ASN1_CHARACTER_STRING 29 +#define CURL_ASN1_BMP_STRING 30 + + +/* + * Types. + */ + +/* ASN.1 parsed element. */ +typedef struct { + const char * header; /* Pointer to header byte. */ + const char * beg; /* Pointer to element data. */ + const char * end; /* Pointer to 1st byte after element. */ + unsigned char class; /* ASN.1 element class. */ + unsigned char tag; /* ASN.1 element tag. */ + bool constructed; /* Element is constructed. */ +} curl_asn1Element; + + +/* ASN.1 OID table entry. */ +typedef struct { + const char * numoid; /* Dotted-numeric OID. */ + const char * textoid; /* OID name. */ +} curl_OID; + + +/* X509 certificate: RFC 5280. */ +typedef struct { + curl_asn1Element certificate; + curl_asn1Element version; + curl_asn1Element serialNumber; + curl_asn1Element signatureAlgorithm; + curl_asn1Element signature; + curl_asn1Element issuer; + curl_asn1Element notBefore; + curl_asn1Element notAfter; + curl_asn1Element subject; + curl_asn1Element subjectPublicKeyInfo; + curl_asn1Element subjectPublicKeyAlgorithm; + curl_asn1Element subjectPublicKey; + curl_asn1Element issuerUniqueID; + curl_asn1Element subjectUniqueID; + curl_asn1Element extensions; +} curl_X509certificate; + + +/* + * Prototypes. + */ + +const char *Curl_getASN1Element(curl_asn1Element *elem, + const char *beg, const char *end); +const char *Curl_ASN1tostr(curl_asn1Element *elem, int type); +const char *Curl_DNtostr(curl_asn1Element *dn); +int Curl_parseX509(curl_X509certificate *cert, + const char *beg, const char *end); +CURLcode Curl_extract_certinfo(struct connectdata *conn, int certnum, + const char *beg, const char *end); +CURLcode Curl_verifyhost(struct connectdata *conn, + const char *beg, const char *end); +#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_CYASSL or USE_SCHANNEL */ +#endif /* HEADER_CURL_X509ASN1_H */ diff --git a/dependencies/cmliblzma/CMakeLists.txt b/dependencies/cmliblzma/CMakeLists.txt new file mode 100644 index 0000000..b443fd6 --- /dev/null +++ b/dependencies/cmliblzma/CMakeLists.txt @@ -0,0 +1,204 @@ +PROJECT(CMLIBLZMA C) + +include(CheckCSourceCompiles) +include(CheckIncludeFile) +include(CheckSymbolExists) +include(CheckTypeSize) +include(TestBigEndian) + +CHECK_INCLUDE_FILE(byteswap.h HAVE_BYTESWAP_H) +CHECK_INCLUDE_FILE(inttypes.h HAVE_INTTYPES_H) +CHECK_INCLUDE_FILE(limits.h HAVE_LIMITS_H) +CHECK_INCLUDE_FILE(memory.h HAVE_MEMORY_H) +CHECK_INCLUDE_FILE(strings.h HAVE_STRINGS_H) +CHECK_INCLUDE_FILE(string.h HAVE_STRING_H) +CHECK_INCLUDE_FILE(sys/sysctl.h HAVE_SYS_SYSCTL_H) + +CHECK_INCLUDE_FILE(stdbool.h HAVE_STDBOOL_H) +if(NOT HAVE_STDBOOL_H) + CHECK_TYPE_SIZE(_Bool _BOOL) +endif() + +CHECK_C_SOURCE_COMPILES ( + "#include\nint main(void){bswap_16(0);return 0;}" + HAVE_BSWAP_16) +CHECK_C_SOURCE_COMPILES ( + "#include\nint main(void){bswap_32(0);return 0;}" + HAVE_BSWAP_32) +CHECK_C_SOURCE_COMPILES ( + "#include\nint main(void){bswap_64(0);return 0;}" + HAVE_BSWAP_64) + +TEST_BIG_ENDIAN(WORDS_BIGENDIAN) + +set(HAVE_CHECK_CRC64 1) +set(HAVE_CHECK_SHA256 1) + +set(HAVE_DECODER_ARM 1) +set(HAVE_DECODER_ARMTHUMB 1) +set(HAVE_DECODER_DELTA 1) +set(HAVE_DECODER_IA64 1) +set(HAVE_DECODER_LZMA1 1) +set(HAVE_DECODER_LZMA2 1) +set(HAVE_DECODER_POWERPC 1) +set(HAVE_DECODER_SPARC 1) +set(HAVE_DECODER_X86 1) + +set(HAVE_ENCODER_ARM 1) +set(HAVE_ENCODER_ARMTHUMB 1) +set(HAVE_ENCODER_DELTA 1) +set(HAVE_ENCODER_IA64 1) +set(HAVE_ENCODER_LZMA1 1) +set(HAVE_ENCODER_LZMA2 1) +set(HAVE_ENCODER_POWERPC 1) +set(HAVE_ENCODER_SPARC 1) +set(HAVE_ENCODER_X86 1) + +set(HAVE_MF_BT2 1) +set(HAVE_MF_BT3 1) +set(HAVE_MF_BT4 1) +set(HAVE_MF_HC3 1) +set(HAVE_MF_HC4 1) + +CHECK_TYPE_SIZE(int16_t INT16_T) +CHECK_TYPE_SIZE(int32_t INT32_T) +CHECK_TYPE_SIZE(int64_t INT64_T) +CHECK_TYPE_SIZE(intmax_t INTMAX_T) +CHECK_TYPE_SIZE(uint8_t UINT8_T) +CHECK_TYPE_SIZE(uint16_t UINT16_T) +CHECK_TYPE_SIZE(uint32_t UINT32_T) +CHECK_TYPE_SIZE(uint64_t UINT64_T) +CHECK_TYPE_SIZE(uintmax_t UINTMAX_T) + +CHECK_TYPE_SIZE("short" SIZE_OF_SHORT) +CHECK_TYPE_SIZE("int" SIZE_OF_INT) +CHECK_TYPE_SIZE("long" SIZE_OF_LONG) +CHECK_TYPE_SIZE("long long" SIZE_OF_LONG_LONG) + +CHECK_TYPE_SIZE("unsigned short" SIZE_OF_UNSIGNED_SHORT) +CHECK_TYPE_SIZE("unsigned" SIZE_OF_UNSIGNED) +CHECK_TYPE_SIZE("unsigned long" SIZE_OF_UNSIGNED_LONG) +CHECK_TYPE_SIZE("unsigned long long" SIZE_OF_UNSIGNED_LONG_LONG) +CHECK_TYPE_SIZE("size_t" SIZEOF_SIZE_T) + +CHECK_TYPE_SIZE("__int64" __INT64) +CHECK_TYPE_SIZE("unsigned __int64" UNSIGNED___INT64) + +CHECK_TYPE_SIZE(uintptr_t UINTPTR_T) +IF(NOT HAVE_UINTPTR_T) + IF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) + SET(uintptr_t "uint64_t") + ELSE() + SET(uintptr_t "uint32_t") + ENDIF() +ENDIF() + + +SET(LZMA_SRCS + common/sysdefs.h + common/tuklib_integer.h + liblzma/check/check.c + liblzma/check/crc32_fast.c + liblzma/check/crc32_table.c + liblzma/check/crc64_fast.c + liblzma/check/crc64_table.c + liblzma/check/sha256.c + liblzma/common/alone_decoder.c + liblzma/common/alone_encoder.c + liblzma/common/auto_decoder.c + liblzma/common/block_buffer_decoder.c + liblzma/common/block_buffer_encoder.c + liblzma/common/block_decoder.c + liblzma/common/block_encoder.c + liblzma/common/block_header_decoder.c + liblzma/common/block_header_encoder.c + liblzma/common/block_util.c + liblzma/common/common.c + liblzma/common/easy_buffer_encoder.c + liblzma/common/easy_decoder_memusage.c + liblzma/common/easy_encoder.c + liblzma/common/easy_encoder_memusage.c + liblzma/common/easy_preset.c + liblzma/common/filter_buffer_decoder.c + liblzma/common/filter_buffer_encoder.c + liblzma/common/filter_common.c + liblzma/common/filter_decoder.c + liblzma/common/filter_encoder.c + liblzma/common/filter_flags_decoder.c + liblzma/common/filter_flags_encoder.c + liblzma/common/index.c + liblzma/common/index_decoder.c + liblzma/common/index_encoder.c + liblzma/common/index_hash.c + liblzma/common/stream_buffer_decoder.c + liblzma/common/stream_buffer_encoder.c + liblzma/common/stream_decoder.c + liblzma/common/stream_encoder.c + liblzma/common/stream_flags_common.c + liblzma/common/stream_flags_decoder.c + liblzma/common/stream_flags_encoder.c + liblzma/common/vli_decoder.c + liblzma/common/vli_encoder.c + liblzma/common/vli_size.c + liblzma/delta/delta_common.c + liblzma/delta/delta_decoder.c + liblzma/delta/delta_encoder.c + liblzma/lz/lz_decoder.c + liblzma/lz/lz_encoder.c + liblzma/lz/lz_encoder_mf.c + liblzma/lzma/fastpos_table.c + liblzma/lzma/lzma2_decoder.c + liblzma/lzma/lzma2_encoder.c + liblzma/lzma/lzma_decoder.c + liblzma/lzma/lzma_encoder.c + liblzma/lzma/lzma_encoder_optimum_fast.c + liblzma/lzma/lzma_encoder_optimum_normal.c + liblzma/lzma/lzma_encoder_presets.c + liblzma/rangecoder/price_table.c + liblzma/simple/arm.c + liblzma/simple/armthumb.c + liblzma/simple/ia64.c + liblzma/simple/powerpc.c + liblzma/simple/simple_coder.c + liblzma/simple/simple_decoder.c + liblzma/simple/simple_encoder.c + liblzma/simple/sparc.c + liblzma/simple/x86.c + ) + +CONFIGURE_FILE(config.h.in config.h @ONLY) + +INCLUDE_DIRECTORIES( + "${CMLIBLZMA_SOURCE_DIR}/common" + "${CMLIBLZMA_SOURCE_DIR}/liblzma/api" + "${CMLIBLZMA_SOURCE_DIR}/liblzma/check" + "${CMLIBLZMA_SOURCE_DIR}/liblzma/common" + "${CMLIBLZMA_SOURCE_DIR}/liblzma/delta" + "${CMLIBLZMA_SOURCE_DIR}/liblzma/lz" + "${CMLIBLZMA_SOURCE_DIR}/liblzma/lzma" + "${CMLIBLZMA_SOURCE_DIR}/liblzma/rangecoder" + "${CMLIBLZMA_SOURCE_DIR}/liblzma/simple" + "${CMLIBLZMA_BINARY_DIR}" + ) + +# Disable warnings to avoid changing 3rd party code. +IF(CMAKE_C_COMPILER_ID MATCHES + "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel)$") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w") +ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "PathScale") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall") +ENDIF() + +ADD_LIBRARY(cmliblzma STATIC ${LZMA_SRCS}) + +IF(CMAKE_C_COMPILER_ID STREQUAL "XL") + # Disable the XL compiler optimizer because it causes crashes + # and other bad behavior in liblzma code. + SET_PROPERTY(TARGET cmliblzma PROPERTY COMPILE_FLAGS "-qnooptimize") +ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND + CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) + # Disable the old GNU compiler optimizer. + SET_PROPERTY(TARGET cmliblzma PROPERTY COMPILE_FLAGS "-O0") +ENDIF() + +INSTALL(FILES COPYING DESTINATION ${CMAKE_DOC_DIR}/cmliblzma) diff --git a/dependencies/cmliblzma/COPYING b/dependencies/cmliblzma/COPYING new file mode 100644 index 0000000..20e60d5 --- /dev/null +++ b/dependencies/cmliblzma/COPYING @@ -0,0 +1,65 @@ + +XZ Utils Licensing +================== + + Different licenses apply to different files in this package. Here + is a rough summary of which licenses apply to which parts of this + package (but check the individual files to be sure!): + + - liblzma is in the public domain. + + - xz, xzdec, and lzmadec command line tools are in the public + domain unless GNU getopt_long had to be compiled and linked + in from the lib directory. The getopt_long code is under + GNU LGPLv2.1+. + + - The scripts to grep, diff, and view compressed files have been + adapted from gzip. These scripts and their documentation are + under GNU GPLv2+. + + - All the documentation in the doc directory and most of the + XZ Utils specific documentation files in other directories + are in the public domain. + + - Translated messages are in the public domain. + + - The build system contains public domain files, and files that + are under GNU GPLv2+ or GNU GPLv3+. None of these files end up + in the binaries being built. + + - Test files and test code in the tests directory, and debugging + utilities in the debug directory are in the public domain. + + - The extra directory may contain public domain files, and files + that are under various free software licenses. + + You can do whatever you want with the files that have been put into + the public domain. If you find public domain legally problematic, + take the previous sentence as a license grant. If you still find + the lack of copyright legally problematic, you have too many + lawyers. + + As usual, this software is provided "as is", without any warranty. + + If you copy significant amounts of public domain code from XZ Utils + into your project, acknowledging this somewhere in your software is + polite (especially if it is proprietary, non-free software), but + naturally it is not legally required. Here is an example of a good + notice to put into "about box" or into documentation: + + This software includes code from XZ Utils . + + The following license texts are included in the following files: + - COPYING.LGPLv2.1: GNU Lesser General Public License version 2.1 + - COPYING.GPLv2: GNU General Public License version 2 + - COPYING.GPLv3: GNU General Public License version 3 + + Note that the toolchain (compiler, linker etc.) may add some code + pieces that are copyrighted. Thus, it is possible that e.g. liblzma + binary wouldn't actually be in the public domain in its entirety + even though it contains no copyrighted code from the XZ Utils source + package. + + If you have questions, don't hesitate to ask the author(s) for more + information. + diff --git a/dependencies/cmliblzma/common/common_w32res.rc b/dependencies/cmliblzma/common/common_w32res.rc new file mode 100644 index 0000000..a70de34 --- /dev/null +++ b/dependencies/cmliblzma/common/common_w32res.rc @@ -0,0 +1,50 @@ +/* + * Author: Lasse Collin + * + * This file has been put into the public domain. + * You can do whatever you want with this file. + */ + +#include +#include "config.h" +#define LZMA_H_INTERNAL +#define LZMA_H_INTERNAL_RC +#include "lzma/version.h" + +#ifndef MY_BUILD +# define MY_BUILD 0 +#endif +#define MY_VERSION LZMA_VERSION_MAJOR,LZMA_VERSION_MINOR,LZMA_VERSION_PATCH,MY_BUILD + +#define MY_FILENAME MY_NAME MY_SUFFIX +#define MY_COMPANY "The Tukaani Project " +#define MY_PRODUCT PACKAGE_NAME " <" PACKAGE_URL ">" + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +VS_VERSION_INFO VERSIONINFO + FILEVERSION MY_VERSION + PRODUCTVERSION MY_VERSION + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS 0 + FILEOS VOS_NT_WINDOWS32 + FILETYPE MY_TYPE + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", MY_COMPANY + VALUE "FileDescription", MY_DESC + VALUE "FileVersion", LZMA_VERSION_STRING + VALUE "InternalName", MY_NAME + VALUE "OriginalFilename", MY_FILENAME + VALUE "ProductName", MY_PRODUCT + VALUE "ProductVersion", LZMA_VERSION_STRING + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/dependencies/cmliblzma/common/sysdefs.h b/dependencies/cmliblzma/common/sysdefs.h new file mode 100644 index 0000000..22f487b --- /dev/null +++ b/dependencies/cmliblzma/common/sysdefs.h @@ -0,0 +1,213 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file sysdefs.h +/// \brief Common includes, definitions, system-specific things etc. +/// +/// This file is used also by the lzma command line tool, that's why this +/// file is separate from common.h. +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_SYSDEFS_H +#define LZMA_SYSDEFS_H + +#if defined(_MSC_VER) +# pragma warning(push,1) +# pragma warning(disable: 4028) /* formal parameter different from decl */ +# pragma warning(disable: 4142) /* benign redefinition of type */ +# pragma warning(disable: 4761) /* integral size mismatch in argument */ +#endif + +////////////// +// Includes // +////////////// + +#include "config.h" + +// Get standard-compliant stdio functions under MinGW and MinGW-w64. +#ifdef __MINGW32__ +# define __USE_MINGW_ANSI_STDIO 1 +#endif + +// size_t and NULL +#include + +#ifdef HAVE_INTTYPES_H +# include +#endif + +// C99 says that inttypes.h always includes stdint.h, but some systems +// don't do that, and require including stdint.h separately. +#ifdef HAVE_STDINT_H +# include +#endif + +// Some pre-C99 systems have SIZE_MAX in limits.h instead of stdint.h. The +// limits are also used to figure out some macros missing from pre-C99 systems. +#ifdef HAVE_LIMITS_H +# include +#endif + + +#if defined(_MSC_VER) && (_MSC_VER < 1310) +# define UINT64_C(n) n ## ui64 +#endif + + +// Be more compatible with systems that have non-conforming inttypes.h. +// We assume that int is 32-bit and that long is either 32-bit or 64-bit. +// Full Autoconf test could be more correct, but this should work well enough. +// Note that this duplicates some code from lzma.h, but this is better since +// we can work without inttypes.h thanks to Autoconf tests. +#ifndef UINT32_C +# if UINT_MAX != 4294967295U +# error UINT32_C is not defined and unsigned int is not 32-bit. +# endif +# define UINT32_C(n) n ## U +#endif +#ifndef UINT32_MAX +# define UINT32_MAX UINT32_C(4294967295) +#endif +#ifndef PRIu32 +# define PRIu32 "u" +#endif +#ifndef PRIx32 +# define PRIx32 "x" +#endif +#ifndef PRIX32 +# define PRIX32 "X" +#endif + +#if ULONG_MAX == 4294967295UL +# ifndef UINT64_C +# define UINT64_C(n) n ## ULL +# endif +# ifndef PRIu64 +# define PRIu64 "llu" +# endif +# ifndef PRIx64 +# define PRIx64 "llx" +# endif +# ifndef PRIX64 +# define PRIX64 "llX" +# endif +#else +# ifndef UINT64_C +# define UINT64_C(n) n ## UL +# endif +# ifndef PRIu64 +# define PRIu64 "lu" +# endif +# ifndef PRIx64 +# define PRIx64 "lx" +# endif +# ifndef PRIX64 +# define PRIX64 "lX" +# endif +#endif +#ifndef UINT64_MAX +# define UINT64_MAX UINT64_C(18446744073709551615) +#endif + +// Incorrect(?) SIZE_MAX: +// - Interix headers typedef size_t to unsigned long, +// but a few lines later define SIZE_MAX to INT32_MAX. +// - SCO OpenServer (x86) headers typedef size_t to unsigned int +// but define SIZE_MAX to INT32_MAX. +#if defined(__INTERIX) || defined(_SCO_DS) +# undef SIZE_MAX +#endif + +// The code currently assumes that size_t is either 32-bit or 64-bit. +#ifndef SIZE_MAX +# if SIZEOF_SIZE_T == 4 +# define SIZE_MAX UINT32_MAX +# elif SIZEOF_SIZE_T == 8 +# define SIZE_MAX UINT64_MAX +# else +# error size_t is not 32-bit or 64-bit +# endif +#endif +#if SIZE_MAX != UINT32_MAX && SIZE_MAX != UINT64_MAX +# error size_t is not 32-bit or 64-bit +#endif + +#include +#include + +// Pre-C99 systems lack stdbool.h. All the code in LZMA Utils must be written +// so that it works with fake bool type, for example: +// +// bool foo = (flags & 0x100) != 0; +// bool bar = !!(flags & 0x100); +// +// This works with the real C99 bool but breaks with fake bool: +// +// bool baz = (flags & 0x100); +// +#ifdef HAVE_STDBOOL_H +# include +#else +# if ! HAVE__BOOL +typedef unsigned char _Bool; +# endif +# define bool _Bool +# define false 0 +# define true 1 +# define __bool_true_false_are_defined 1 +#endif + +// string.h should be enough but let's include strings.h and memory.h too if +// they exists, since that shouldn't do any harm, but may improve portability. +#ifdef HAVE_STRING_H +# include +#endif + +#ifdef HAVE_STRINGS_H +# include +#endif + +#ifdef HAVE_MEMORY_H +# include +#endif + +// As of MSVC 2013, inline and restrict are supported with +// non-standard keywords. +#if defined(_WIN32) && defined(_MSC_VER) +# ifndef inline +# define inline __inline +# endif +# ifndef restrict +# define restrict __restrict +# endif +#endif + +//////////// +// Macros // +//////////// + +#undef memzero +#define memzero(s, n) memset(s, 0, n) + +// NOTE: Avoid using MIN() and MAX(), because even conditionally defining +// those macros can cause some portability trouble, since on some systems +// the system headers insist defining their own versions. +#define my_min(x, y) ((x) < (y) ? (x) : (y)) +#define my_max(x, y) ((x) > (y) ? (x) : (y)) + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) +#endif + +#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4 +# define lzma_attr_alloc_size(x) __attribute__((__alloc_size__(x))) +#else +# define lzma_attr_alloc_size(x) +#endif + +#endif diff --git a/dependencies/cmliblzma/common/tuklib_integer.h b/dependencies/cmliblzma/common/tuklib_integer.h new file mode 100644 index 0000000..5d82685 --- /dev/null +++ b/dependencies/cmliblzma/common/tuklib_integer.h @@ -0,0 +1,525 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file tuklib_integer.h +/// \brief Various integer and bit operations +/// +/// This file provides macros or functions to do some basic integer and bit +/// operations. +/// +/// Endianness related integer operations (XX = 16, 32, or 64; Y = b or l): +/// - Byte swapping: bswapXX(num) +/// - Byte order conversions to/from native: convXXYe(num) +/// - Aligned reads: readXXYe(ptr) +/// - Aligned writes: writeXXYe(ptr, num) +/// - Unaligned reads (16/32-bit only): unaligned_readXXYe(ptr) +/// - Unaligned writes (16/32-bit only): unaligned_writeXXYe(ptr, num) +/// +/// Since they can macros, the arguments should have no side effects since +/// they may be evaluated more than once. +/// +/// \todo PowerPC and possibly some other architectures support +/// byte swapping load and store instructions. This file +/// doesn't take advantage of those instructions. +/// +/// Bit scan operations for non-zero 32-bit integers: +/// - Bit scan reverse (find highest non-zero bit): bsr32(num) +/// - Count leading zeros: clz32(num) +/// - Count trailing zeros: ctz32(num) +/// - Bit scan forward (simply an alias for ctz32()): bsf32(num) +/// +/// The above bit scan operations return 0-31. If num is zero, +/// the result is undefined. +// +// Authors: Lasse Collin +// Joachim Henke +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef TUKLIB_INTEGER_H +#define TUKLIB_INTEGER_H + +#include "sysdefs.h" + +#if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define TUKLIB_GNUC_REQ(major, minor) \ + ((__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)) \ + || __GNUC__ > (major)) +#else +# define TUKLIB_GNUC_REQ(major, minor) 0 +#endif + + +//////////////////////////////////////// +// Operating system specific features // +//////////////////////////////////////// + +#if defined(HAVE_BYTESWAP_H) + // glibc, uClibc, dietlibc +# include +# ifdef HAVE_BSWAP_16 +# define bswap16(num) bswap_16(num) +# endif +# ifdef HAVE_BSWAP_32 +# define bswap32(num) bswap_32(num) +# endif +# ifdef HAVE_BSWAP_64 +# define bswap64(num) bswap_64(num) +# endif + +#elif defined(HAVE_SYS_ENDIAN_H) + // *BSDs and Darwin +# include + +#elif defined(HAVE_SYS_BYTEORDER_H) + // Solaris +# include +# ifdef BSWAP_16 +# define bswap16(num) BSWAP_16(num) +# endif +# ifdef BSWAP_32 +# define bswap32(num) BSWAP_32(num) +# endif +# ifdef BSWAP_64 +# define bswap64(num) BSWAP_64(num) +# endif +# ifdef BE_16 +# define conv16be(num) BE_16(num) +# endif +# ifdef BE_32 +# define conv32be(num) BE_32(num) +# endif +# ifdef BE_64 +# define conv64be(num) BE_64(num) +# endif +# ifdef LE_16 +# define conv16le(num) LE_16(num) +# endif +# ifdef LE_32 +# define conv32le(num) LE_32(num) +# endif +# ifdef LE_64 +# define conv64le(num) LE_64(num) +# endif +#endif + + +//////////////////////////////// +// Compiler-specific features // +//////////////////////////////// + +// Newer Intel C compilers require immintrin.h for _bit_scan_reverse() +// and such functions. +#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1500) +# include +#endif + + +/////////////////// +// Byte swapping // +/////////////////// + +#ifndef bswap16 +# define bswap16(num) \ + (((uint16_t)(num) << 8) | ((uint16_t)(num) >> 8)) +#endif + +#ifndef bswap32 +# define bswap32(num) \ + ( (((uint32_t)(num) << 24) ) \ + | (((uint32_t)(num) << 8) & UINT32_C(0x00FF0000)) \ + | (((uint32_t)(num) >> 8) & UINT32_C(0x0000FF00)) \ + | (((uint32_t)(num) >> 24) ) ) +#endif + +#ifndef bswap64 +# define bswap64(num) \ + ( (((uint64_t)(num) << 56) ) \ + | (((uint64_t)(num) << 40) & UINT64_C(0x00FF000000000000)) \ + | (((uint64_t)(num) << 24) & UINT64_C(0x0000FF0000000000)) \ + | (((uint64_t)(num) << 8) & UINT64_C(0x000000FF00000000)) \ + | (((uint64_t)(num) >> 8) & UINT64_C(0x00000000FF000000)) \ + | (((uint64_t)(num) >> 24) & UINT64_C(0x0000000000FF0000)) \ + | (((uint64_t)(num) >> 40) & UINT64_C(0x000000000000FF00)) \ + | (((uint64_t)(num) >> 56) ) ) +#endif + +// Define conversion macros using the basic byte swapping macros. +#ifdef WORDS_BIGENDIAN +# ifndef conv16be +# define conv16be(num) ((uint16_t)(num)) +# endif +# ifndef conv32be +# define conv32be(num) ((uint32_t)(num)) +# endif +# ifndef conv64be +# define conv64be(num) ((uint64_t)(num)) +# endif +# ifndef conv16le +# define conv16le(num) bswap16(num) +# endif +# ifndef conv32le +# define conv32le(num) bswap32(num) +# endif +# ifndef conv64le +# define conv64le(num) bswap64(num) +# endif +#else +# ifndef conv16be +# define conv16be(num) bswap16(num) +# endif +# ifndef conv32be +# define conv32be(num) bswap32(num) +# endif +# ifndef conv64be +# define conv64be(num) bswap64(num) +# endif +# ifndef conv16le +# define conv16le(num) ((uint16_t)(num)) +# endif +# ifndef conv32le +# define conv32le(num) ((uint32_t)(num)) +# endif +# ifndef conv64le +# define conv64le(num) ((uint64_t)(num)) +# endif +#endif + + +////////////////////////////// +// Aligned reads and writes // +////////////////////////////// + +static inline uint16_t +read16be(const uint8_t *buf) +{ + uint16_t num = *(const uint16_t *)buf; + return conv16be(num); +} + + +static inline uint16_t +read16le(const uint8_t *buf) +{ + uint16_t num = *(const uint16_t *)buf; + return conv16le(num); +} + + +static inline uint32_t +read32be(const uint8_t *buf) +{ + uint32_t num = *(const uint32_t *)buf; + return conv32be(num); +} + + +static inline uint32_t +read32le(const uint8_t *buf) +{ + uint32_t num = *(const uint32_t *)buf; + return conv32le(num); +} + + +static inline uint64_t +read64be(const uint8_t *buf) +{ + uint64_t num = *(const uint64_t *)buf; + return conv64be(num); +} + + +static inline uint64_t +read64le(const uint8_t *buf) +{ + uint64_t num = *(const uint64_t *)buf; + return conv64le(num); +} + + +// NOTE: Possible byte swapping must be done in a macro to allow GCC +// to optimize byte swapping of constants when using glibc's or *BSD's +// byte swapping macros. The actual write is done in an inline function +// to make type checking of the buf pointer possible similarly to readXXYe() +// functions. + +#define write16be(buf, num) write16ne((buf), conv16be(num)) +#define write16le(buf, num) write16ne((buf), conv16le(num)) +#define write32be(buf, num) write32ne((buf), conv32be(num)) +#define write32le(buf, num) write32ne((buf), conv32le(num)) +#define write64be(buf, num) write64ne((buf), conv64be(num)) +#define write64le(buf, num) write64ne((buf), conv64le(num)) + + +static inline void +write16ne(uint8_t *buf, uint16_t num) +{ + *(uint16_t *)buf = num; + return; +} + + +static inline void +write32ne(uint8_t *buf, uint32_t num) +{ + *(uint32_t *)buf = num; + return; +} + + +static inline void +write64ne(uint8_t *buf, uint64_t num) +{ + *(uint64_t *)buf = num; + return; +} + + +//////////////////////////////// +// Unaligned reads and writes // +//////////////////////////////// + +// NOTE: TUKLIB_FAST_UNALIGNED_ACCESS indicates only support for 16-bit and +// 32-bit unaligned integer loads and stores. It's possible that 64-bit +// unaligned access doesn't work or is slower than byte-by-byte access. +// Since unaligned 64-bit is probably not needed as often as 16-bit or +// 32-bit, we simply don't support 64-bit unaligned access for now. +#ifdef TUKLIB_FAST_UNALIGNED_ACCESS +# define unaligned_read16be read16be +# define unaligned_read16le read16le +# define unaligned_read32be read32be +# define unaligned_read32le read32le +# define unaligned_write16be write16be +# define unaligned_write16le write16le +# define unaligned_write32be write32be +# define unaligned_write32le write32le + +#else + +static inline uint16_t +unaligned_read16be(const uint8_t *buf) +{ + uint16_t num = ((uint16_t)buf[0] << 8) | (uint16_t)buf[1]; + return num; +} + + +static inline uint16_t +unaligned_read16le(const uint8_t *buf) +{ + uint16_t num = ((uint16_t)buf[0]) | ((uint16_t)buf[1] << 8); + return num; +} + + +static inline uint32_t +unaligned_read32be(const uint8_t *buf) +{ + uint32_t num = (uint32_t)buf[0] << 24; + num |= (uint32_t)buf[1] << 16; + num |= (uint32_t)buf[2] << 8; + num |= (uint32_t)buf[3]; + return num; +} + + +static inline uint32_t +unaligned_read32le(const uint8_t *buf) +{ + uint32_t num = (uint32_t)buf[0]; + num |= (uint32_t)buf[1] << 8; + num |= (uint32_t)buf[2] << 16; + num |= (uint32_t)buf[3] << 24; + return num; +} + + +static inline void +unaligned_write16be(uint8_t *buf, uint16_t num) +{ + buf[0] = (uint8_t)(num >> 8); + buf[1] = (uint8_t)num; + return; +} + + +static inline void +unaligned_write16le(uint8_t *buf, uint16_t num) +{ + buf[0] = (uint8_t)num; + buf[1] = (uint8_t)(num >> 8); + return; +} + + +static inline void +unaligned_write32be(uint8_t *buf, uint32_t num) +{ + buf[0] = (uint8_t)(num >> 24); + buf[1] = (uint8_t)(num >> 16); + buf[2] = (uint8_t)(num >> 8); + buf[3] = (uint8_t)num; + return; +} + + +static inline void +unaligned_write32le(uint8_t *buf, uint32_t num) +{ + buf[0] = (uint8_t)num; + buf[1] = (uint8_t)(num >> 8); + buf[2] = (uint8_t)(num >> 16); + buf[3] = (uint8_t)(num >> 24); + return; +} + +#endif + + +static inline uint32_t +bsr32(uint32_t n) +{ + // Check for ICC first, since it tends to define __GNUC__ too. +#if defined(__INTEL_COMPILER) + return _bit_scan_reverse(n); + +#elif TUKLIB_GNUC_REQ(3, 4) && UINT_MAX == UINT32_MAX + // GCC >= 3.4 has __builtin_clz(), which gives good results on + // multiple architectures. On x86, __builtin_clz() ^ 31U becomes + // either plain BSR (so the XOR gets optimized away) or LZCNT and + // XOR (if -march indicates that SSE4a instructions are supported). + return __builtin_clz(n) ^ 31U; + +#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + uint32_t i; + __asm__("bsrl %1, %0" : "=r" (i) : "rm" (n)); + return i; + +#else + uint32_t i = 31; + + if ((n & UINT32_C(0xFFFF0000)) == 0) { + n <<= 16; + i = 15; + } + + if ((n & UINT32_C(0xFF000000)) == 0) { + n <<= 8; + i -= 8; + } + + if ((n & UINT32_C(0xF0000000)) == 0) { + n <<= 4; + i -= 4; + } + + if ((n & UINT32_C(0xC0000000)) == 0) { + n <<= 2; + i -= 2; + } + + if ((n & UINT32_C(0x80000000)) == 0) + --i; + + return i; +#endif +} + + +static inline uint32_t +clz32(uint32_t n) +{ +#if defined(__INTEL_COMPILER) + return _bit_scan_reverse(n) ^ 31U; + +#elif TUKLIB_GNUC_REQ(3, 4) && UINT_MAX == UINT32_MAX + return __builtin_clz(n); + +#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + uint32_t i; + __asm__("bsrl %1, %0\n\t" + "xorl $31, %0" + : "=r" (i) : "rm" (n)); + return i; + +#else + uint32_t i = 0; + + if ((n & UINT32_C(0xFFFF0000)) == 0) { + n <<= 16; + i = 16; + } + + if ((n & UINT32_C(0xFF000000)) == 0) { + n <<= 8; + i += 8; + } + + if ((n & UINT32_C(0xF0000000)) == 0) { + n <<= 4; + i += 4; + } + + if ((n & UINT32_C(0xC0000000)) == 0) { + n <<= 2; + i += 2; + } + + if ((n & UINT32_C(0x80000000)) == 0) + ++i; + + return i; +#endif +} + + +static inline uint32_t +ctz32(uint32_t n) +{ +#if defined(__INTEL_COMPILER) + return _bit_scan_forward(n); + +#elif TUKLIB_GNUC_REQ(3, 4) && UINT_MAX >= UINT32_MAX + return __builtin_ctz(n); + +#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + uint32_t i; + __asm__("bsfl %1, %0" : "=r" (i) : "rm" (n)); + return i; + +#else + uint32_t i = 0; + + if ((n & UINT32_C(0x0000FFFF)) == 0) { + n >>= 16; + i = 16; + } + + if ((n & UINT32_C(0x000000FF)) == 0) { + n >>= 8; + i += 8; + } + + if ((n & UINT32_C(0x0000000F)) == 0) { + n >>= 4; + i += 4; + } + + if ((n & UINT32_C(0x00000003)) == 0) { + n >>= 2; + i += 2; + } + + if ((n & UINT32_C(0x00000001)) == 0) + ++i; + + return i; +#endif +} + +#define bsf32 ctz32 + +#endif diff --git a/dependencies/cmliblzma/config.h.in b/dependencies/cmliblzma/config.h.in new file mode 100644 index 0000000..06f7fcb --- /dev/null +++ b/dependencies/cmliblzma/config.h.in @@ -0,0 +1,263 @@ + +/* + * Ensure we have C99-style int64_t, etc, all defined. + */ + +/* First, we need to know if the system has already defined them. */ +#cmakedefine HAVE_INT16_T +#cmakedefine HAVE_INT32_T +#cmakedefine HAVE_INT64_T +#cmakedefine HAVE_INTMAX_T + +#cmakedefine HAVE_UINT8_T +#cmakedefine HAVE_UINT16_T +#cmakedefine HAVE_UINT32_T +#cmakedefine HAVE_UINT64_T +#cmakedefine HAVE_UINTMAX_T + +/* We might have the types we want under other spellings. */ +#cmakedefine HAVE___INT64 +#cmakedefine HAVE_U_INT64_T +#cmakedefine HAVE_UNSIGNED___INT64 + +/* The sizes of various standard integer types. */ +@SIZE_OF_SHORT_CODE@ +@SIZE_OF_INT_CODE@ +@SIZE_OF_LONG_CODE@ +@SIZE_OF_LONG_LONG_CODE@ +@SIZE_OF_UNSIGNED_SHORT_CODE@ +@SIZE_OF_UNSIGNED_CODE@ +@SIZE_OF_UNSIGNED_LONG_CODE@ +@SIZE_OF_UNSIGNED_LONG_LONG_CODE@ +@SIZEOF_SIZE_T_CODE@ + +/* + * If we lack int64_t, define it to the first of __int64, int, long, and long long + * that exists and is the right size. + */ +#if !defined(HAVE_INT64_T) && defined(HAVE___INT64) +typedef __int64 int64_t; +#define HAVE_INT64_T +#endif + +#if !defined(HAVE_INT64_T) && SIZE_OF_INT == 8 +typedef int int64_t; +#define HAVE_INT64_T +#endif + +#if !defined(HAVE_INT64_T) && SIZE_OF_LONG == 8 +typedef long int64_t; +#define HAVE_INT64_T +#endif + +#if !defined(HAVE_INT64_T) && SIZE_OF_LONG_LONG == 8 +typedef long long int64_t; +#define HAVE_INT64_T +#endif + +#if !defined(HAVE_INT64_T) +#error No 64-bit integer type was found. +#endif + +/* + * Similarly for int32_t + */ +#if !defined(HAVE_INT32_T) && SIZE_OF_INT == 4 +typedef int int32_t; +#define HAVE_INT32_T +#endif + +#if !defined(HAVE_INT32_T) && SIZE_OF_LONG == 4 +typedef long int32_t; +#define HAVE_INT32_T +#endif + +#if !defined(HAVE_INT32_T) +#error No 32-bit integer type was found. +#endif + +/* + * Similarly for int16_t + */ +#if !defined(HAVE_INT16_T) && SIZE_OF_INT == 2 +typedef int int16_t; +#define HAVE_INT16_T +#endif + +#if !defined(HAVE_INT16_T) && SIZE_OF_SHORT == 2 +typedef short int16_t; +#define HAVE_INT16_T +#endif + +#if !defined(HAVE_INT16_T) +#error No 16-bit integer type was found. +#endif + +/* + * Similarly for uint64_t + */ +#if !defined(HAVE_UINT64_T) && defined(HAVE_UNSIGNED___INT64) +typedef unsigned __int64 uint64_t; +#define HAVE_UINT64_T +#endif + +#if !defined(HAVE_UINT64_T) && SIZE_OF_UNSIGNED == 8 +typedef unsigned uint64_t; +#define HAVE_UINT64_T +#endif + +#if !defined(HAVE_UINT64_T) && SIZE_OF_UNSIGNED_LONG == 8 +typedef unsigned long uint64_t; +#define HAVE_UINT64_T +#endif + +#if !defined(HAVE_UINT64_T) && SIZE_OF_UNSIGNED_LONG_LONG == 8 +typedef unsigned long long uint64_t; +#define HAVE_UINT64_T +#endif + +#if !defined(HAVE_UINT64_T) +#error No 64-bit unsigned integer type was found. +#endif + +/* + * Similarly for uint32_t + */ +#if !defined(HAVE_UINT32_T) && SIZE_OF_UNSIGNED == 4 +typedef unsigned uint32_t; +#define HAVE_UINT32_T +#endif + +#if !defined(HAVE_UINT32_T) && SIZE_OF_UNSIGNED_LONG == 4 +typedef unsigned long uint32_t; +#define HAVE_UINT32_T +#endif + +#if !defined(HAVE_UINT32_T) +#error No 32-bit unsigned integer type was found. +#endif + +/* + * Similarly for uint16_t + */ +#if !defined(HAVE_UINT16_T) && SIZE_OF_UNSIGNED == 2 +typedef unsigned uint16_t; +#define HAVE_UINT16_T +#endif + +#if !defined(HAVE_UINT16_T) && SIZE_OF_UNSIGNED_SHORT == 2 +typedef unsigned short uint16_t; +#define HAVE_UINT16_T +#endif + +#if !defined(HAVE_UINT16_T) +#error No 16-bit unsigned integer type was found. +#endif + +/* + * Similarly for uint8_t + */ +#if !defined(HAVE_UINT8_T) +typedef unsigned char uint8_t; +#define HAVE_UINT8_T +#endif + +#if !defined(HAVE_UINT16_T) +#error No 8-bit unsigned integer type was found. +#endif + +/* Define intmax_t and uintmax_t if they are not already defined. */ +#if !defined(HAVE_INTMAX_T) +typedef int64_t intmax_t; +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#endif + +#if !defined(HAVE_UINTMAX_T) +typedef uint64_t uintmax_t; +#endif + + +#cmakedefine uintptr_t @uintptr_t@ + +#cmakedefine WORDS_BIGENDIAN 1 + +#cmakedefine HAVE_BYTESWAP_H 1 +#cmakedefine HAVE_BSWAP_16 1 +#cmakedefine HAVE_BSWAP_32 1 +#cmakedefine HAVE_BSWAP_64 1 + + +#define HAVE_CHECK_CRC32 1 +#define HAVE_CHECK_CRC64 1 +#define HAVE_CHECK_SHA256 1 + +#define HAVE_DECODER_ARM 1 +#define HAVE_DECODER_ARMTHUMB 1 +#define HAVE_DECODER_DELTA 1 +#define HAVE_DECODER_IA64 1 +#define HAVE_DECODER_LZMA1 1 +#define HAVE_DECODER_LZMA2 1 +#define HAVE_DECODER_POWERPC 1 +#define HAVE_DECODER_SPARC 1 +#define HAVE_DECODER_X86 1 + +#define HAVE_ENCODER_ARM 1 +#define HAVE_ENCODER_ARMTHUMB 1 +#define HAVE_ENCODER_DELTA 1 +#define HAVE_ENCODER_IA64 1 +#define HAVE_ENCODER_LZMA1 1 +#define HAVE_ENCODER_LZMA2 1 +#define HAVE_ENCODER_POWERPC 1 +#define HAVE_ENCODER_SPARC 1 +#define HAVE_ENCODER_X86 1 + +#define HAVE_MF_BT2 1 +#define HAVE_MF_BT3 1 +#define HAVE_MF_BT4 1 +#define HAVE_MF_HC3 1 +#define HAVE_MF_HC4 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LIMITS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MEMORY_H 1 + +/* Define to 1 if stdbool.h conforms to C99. */ +#cmakedefine HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_BYTEORDER_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_ENDIAN_H 1 + +/* Define to 1 or 0, depending whether the compiler supports simple visibility + declarations. */ +#cmakedefine HAVE_VISIBILITY 1 + +/* Define to 1 if the system has the type `_Bool'. */ +#cmakedefine HAVE__BOOL 1 + +/* Define to 1 if the system supports fast unaligned access to 16-bit and + 32-bit integers. */ +#if defined(__i386) || defined(__i386__) || defined(_M_IX86) \ + || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) \ + || defined(__amd64) || defined(__amd64__) \ + || defined(__powerpc) || defined(__powerpc__) \ + || defined(__ppc) || defined(__ppc__) || defined(__POWERPC__) +# define TUKLIB_FAST_UNALIGNED_ACCESS 1 +#endif diff --git a/dependencies/cmliblzma/liblzma/api/lzma.h b/dependencies/cmliblzma/liblzma/api/lzma.h new file mode 100644 index 0000000..aa88e42 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/api/lzma.h @@ -0,0 +1,325 @@ +/** + * \file api/lzma.h + * \brief The public API of liblzma data compression library + * + * liblzma is a public domain general-purpose data compression library with + * a zlib-like API. The native file format is .xz, but also the old .lzma + * format and raw (no headers) streams are supported. Multiple compression + * algorithms (filters) are supported. Currently LZMA2 is the primary filter. + * + * liblzma is part of XZ Utils . XZ Utils includes + * a gzip-like command line tool named xz and some other tools. XZ Utils + * is developed and maintained by Lasse Collin. + * + * Major parts of liblzma are based on Igor Pavlov's public domain LZMA SDK + * . + * + * The SHA-256 implementation is based on the public domain code found from + * 7-Zip , which has a modified version of the public + * domain SHA-256 code found from Crypto++ . + * The SHA-256 code in Crypto++ was written by Kevin Springle and Wei Dai. + */ + +/* + * Author: Lasse Collin + * + * This file has been put into the public domain. + * You can do whatever you want with this file. + */ + +#ifndef LZMA_H +#define LZMA_H + +/***************************** + * Required standard headers * + *****************************/ + +/* + * liblzma API headers need some standard types and macros. To allow + * including lzma.h without requiring the application to include other + * headers first, lzma.h includes the required standard headers unless + * they already seem to be included already or if LZMA_MANUAL_HEADERS + * has been defined. + * + * Here's what types and macros are needed and from which headers: + * - stddef.h: size_t, NULL + * - stdint.h: uint8_t, uint32_t, uint64_t, UINT32_C(n), uint64_C(n), + * UINT32_MAX, UINT64_MAX + * + * However, inttypes.h is a little more portable than stdint.h, although + * inttypes.h declares some unneeded things compared to plain stdint.h. + * + * The hacks below aren't perfect, specifically they assume that inttypes.h + * exists and that it typedefs at least uint8_t, uint32_t, and uint64_t, + * and that, in case of incomplete inttypes.h, unsigned int is 32-bit. + * If the application already takes care of setting up all the types and + * macros properly (for example by using gnulib's stdint.h or inttypes.h), + * we try to detect that the macros are already defined and don't include + * inttypes.h here again. However, you may define LZMA_MANUAL_HEADERS to + * force this file to never include any system headers. + * + * Some could argue that liblzma API should provide all the required types, + * for example lzma_uint64, LZMA_UINT64_C(n), and LZMA_UINT64_MAX. This was + * seen as an unnecessary mess, since most systems already provide all the + * necessary types and macros in the standard headers. + * + * Note that liblzma API still has lzma_bool, because using stdbool.h would + * break C89 and C++ programs on many systems. sizeof(bool) in C99 isn't + * necessarily the same as sizeof(bool) in C++. + */ + +#ifndef LZMA_MANUAL_HEADERS + /* + * I suppose this works portably also in C++. Note that in C++, + * we need to get size_t into the global namespace. + */ +# include + + /* + * Skip inttypes.h if we already have all the required macros. If we + * have the macros, we assume that we have the matching typedefs too. + */ +# if !defined(UINT32_C) || !defined(UINT64_C) \ + || !defined(UINT32_MAX) || !defined(UINT64_MAX) + /* + * MSVC versions older than 2013 have no C99 support, and + * thus they cannot be used to compile liblzma. Using an + * existing liblzma.dll with old MSVC can work though(*), + * but we need to define the required standard integer + * types here in a MSVC-specific way. + * + * (*) If you do this, the existing liblzma.dll probably uses + * a different runtime library than your MSVC-built + * application. Mixing runtimes is generally bad, but + * in this case it should work as long as you avoid + * the few rarely-needed liblzma functions that allocate + * memory and expect the caller to free it using free(). + */ +# if defined(_WIN32) && defined(_MSC_VER) && _MSC_VER < 1800 + typedef unsigned __int8 uint8_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; +# else + /* Use the standard inttypes.h. */ +# ifdef __cplusplus + /* + * C99 sections 7.18.2 and 7.18.4 specify + * that C++ implementations define the limit + * and constant macros only if specifically + * requested. Note that if you want the + * format macros (PRIu64 etc.) too, you need + * to define __STDC_FORMAT_MACROS before + * including lzma.h, since re-including + * inttypes.h with __STDC_FORMAT_MACROS + * defined doesn't necessarily work. + */ +# ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS 1 +# endif +# ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS 1 +# endif +# endif + +# include +# endif + + /* + * Some old systems have only the typedefs in inttypes.h, and + * lack all the macros. For those systems, we need a few more + * hacks. We assume that unsigned int is 32-bit and unsigned + * long is either 32-bit or 64-bit. If these hacks aren't + * enough, the application has to setup the types manually + * before including lzma.h. + */ +# ifndef UINT32_C +# if defined(_WIN32) && defined(_MSC_VER) +# define UINT32_C(n) n ## UI32 +# else +# define UINT32_C(n) n ## U +# endif +# endif + +# ifndef UINT64_C +# if defined(_WIN32) && defined(_MSC_VER) +# define UINT64_C(n) n ## UI64 +# else + /* Get ULONG_MAX. */ +# include +# if ULONG_MAX == 4294967295UL +# define UINT64_C(n) n ## ULL +# else +# define UINT64_C(n) n ## UL +# endif +# endif +# endif + +# ifndef UINT32_MAX +# define UINT32_MAX (UINT32_C(4294967295)) +# endif + +# ifndef UINT64_MAX +# define UINT64_MAX (UINT64_C(18446744073709551615)) +# endif +# endif +#endif /* ifdef LZMA_MANUAL_HEADERS */ + + +/****************** + * LZMA_API macro * + ******************/ + +/* + * Some systems require that the functions and function pointers are + * declared specially in the headers. LZMA_API_IMPORT is for importing + * symbols and LZMA_API_CALL is to specify the calling convention. + * + * By default it is assumed that the application will link dynamically + * against liblzma. #define LZMA_API_STATIC in your application if you + * want to link against static liblzma. If you don't care about portability + * to operating systems like Windows, or at least don't care about linking + * against static liblzma on them, don't worry about LZMA_API_STATIC. That + * is, most developers will never need to use LZMA_API_STATIC. + * + * The GCC variants are a special case on Windows (Cygwin and MinGW). + * We rely on GCC doing the right thing with its auto-import feature, + * and thus don't use __declspec(dllimport). This way developers don't + * need to worry about LZMA_API_STATIC. Also the calling convention is + * omitted on Cygwin but not on MinGW. + */ +#ifndef LZMA_API_IMPORT +# if !defined(LZMA_API_STATIC) && defined(_WIN32) && !defined(__GNUC__) +# define LZMA_API_IMPORT __declspec(dllimport) +# else +# define LZMA_API_IMPORT +# endif +#endif + +#ifndef LZMA_API_CALL +# if defined(_WIN32) && !defined(__CYGWIN__) +# define LZMA_API_CALL __cdecl +# else +# define LZMA_API_CALL +# endif +#endif + +#ifndef LZMA_API +# define LZMA_API(type) LZMA_API_IMPORT type LZMA_API_CALL +#endif + + +/*********** + * nothrow * + ***********/ + +/* + * None of the functions in liblzma may throw an exception. Even + * the functions that use callback functions won't throw exceptions, + * because liblzma would break if a callback function threw an exception. + */ +#ifndef lzma_nothrow +# if defined(__cplusplus) +# if __cplusplus >= 201103L +# define lzma_nothrow noexcept +# else +# define lzma_nothrow throw() +# endif +# elif __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) +# define lzma_nothrow __attribute__((__nothrow__)) +# else +# define lzma_nothrow +# endif +#endif + + +/******************** + * GNU C extensions * + ********************/ + +/* + * GNU C extensions are used conditionally in the public API. It doesn't + * break anything if these are sometimes enabled and sometimes not, only + * affects warnings and optimizations. + */ +#if __GNUC__ >= 3 +# ifndef lzma_attribute +# define lzma_attribute(attr) __attribute__(attr) +# endif + + /* warn_unused_result was added in GCC 3.4. */ +# ifndef lzma_attr_warn_unused_result +# if __GNUC__ == 3 && __GNUC_MINOR__ < 4 +# define lzma_attr_warn_unused_result +# endif +# endif + +#else +# ifndef lzma_attribute +# define lzma_attribute(attr) +# endif +#endif + + +#ifndef lzma_attr_pure +# define lzma_attr_pure lzma_attribute((__pure__)) +#endif + +#ifndef lzma_attr_const +# define lzma_attr_const lzma_attribute((__const__)) +#endif + +#ifndef lzma_attr_warn_unused_result +# define lzma_attr_warn_unused_result \ + lzma_attribute((__warn_unused_result__)) +#endif + + +/************** + * Subheaders * + **************/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Subheaders check that this is defined. It is to prevent including + * them directly from applications. + */ +#define LZMA_H_INTERNAL 1 + +/* Basic features */ +#include "lzma/version.h" +#include "lzma/base.h" +#include "lzma/vli.h" +#include "lzma/check.h" + +/* Filters */ +#include "lzma/filter.h" +#include "lzma/bcj.h" +#include "lzma/delta.h" +#include "lzma/lzma12.h" + +/* Container formats */ +#include "lzma/container.h" + +/* Advanced features */ +#include "lzma/stream_flags.h" +#include "lzma/block.h" +#include "lzma/index.h" +#include "lzma/index_hash.h" + +/* Hardware information */ +#include "lzma/hardware.h" + +/* + * All subheaders included. Undefine LZMA_H_INTERNAL to prevent applications + * re-including the subheaders. + */ +#undef LZMA_H_INTERNAL + +#ifdef __cplusplus +} +#endif + +#endif /* ifndef LZMA_H */ diff --git a/dependencies/cmliblzma/liblzma/api/lzma/base.h b/dependencies/cmliblzma/liblzma/api/lzma/base.h new file mode 100644 index 0000000..a6005ac --- /dev/null +++ b/dependencies/cmliblzma/liblzma/api/lzma/base.h @@ -0,0 +1,659 @@ +/** + * \file lzma/base.h + * \brief Data types and functions used in many places in liblzma API + */ + +/* + * Author: Lasse Collin + * + * This file has been put into the public domain. + * You can do whatever you want with this file. + * + * See ../lzma.h for information about liblzma as a whole. + */ + +#ifndef LZMA_H_INTERNAL +# error Never include this file directly. Use instead. +#endif + + +/** + * \brief Boolean + * + * This is here because C89 doesn't have stdbool.h. To set a value for + * variables having type lzma_bool, you can use + * - C99's `true' and `false' from stdbool.h; + * - C++'s internal `true' and `false'; or + * - integers one (true) and zero (false). + */ +typedef unsigned char lzma_bool; + + +/** + * \brief Type of reserved enumeration variable in structures + * + * To avoid breaking library ABI when new features are added, several + * structures contain extra variables that may be used in future. Since + * sizeof(enum) can be different than sizeof(int), and sizeof(enum) may + * even vary depending on the range of enumeration constants, we specify + * a separate type to be used for reserved enumeration variables. All + * enumeration constants in liblzma API will be non-negative and less + * than 128, which should guarantee that the ABI won't break even when + * new constants are added to existing enumerations. + */ +typedef enum { + LZMA_RESERVED_ENUM = 0 +} lzma_reserved_enum; + + +/** + * \brief Return values used by several functions in liblzma + * + * Check the descriptions of specific functions to find out which return + * values they can return. With some functions the return values may have + * more specific meanings than described here; those differences are + * described per-function basis. + */ +typedef enum { + LZMA_OK = 0, + /**< + * \brief Operation completed successfully + */ + + LZMA_STREAM_END = 1, + /**< + * \brief End of stream was reached + * + * In encoder, LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, or + * LZMA_FINISH was finished. In decoder, this indicates + * that all the data was successfully decoded. + * + * In all cases, when LZMA_STREAM_END is returned, the last + * output bytes should be picked from strm->next_out. + */ + + LZMA_NO_CHECK = 2, + /**< + * \brief Input stream has no integrity check + * + * This return value can be returned only if the + * LZMA_TELL_NO_CHECK flag was used when initializing + * the decoder. LZMA_NO_CHECK is just a warning, and + * the decoding can be continued normally. + * + * It is possible to call lzma_get_check() immediately after + * lzma_code has returned LZMA_NO_CHECK. The result will + * naturally be LZMA_CHECK_NONE, but the possibility to call + * lzma_get_check() may be convenient in some applications. + */ + + LZMA_UNSUPPORTED_CHECK = 3, + /**< + * \brief Cannot calculate the integrity check + * + * The usage of this return value is different in encoders + * and decoders. + * + * Encoders can return this value only from the initialization + * function. If initialization fails with this value, the + * encoding cannot be done, because there's no way to produce + * output with the correct integrity check. + * + * Decoders can return this value only from lzma_code() and + * only if the LZMA_TELL_UNSUPPORTED_CHECK flag was used when + * initializing the decoder. The decoding can still be + * continued normally even if the check type is unsupported, + * but naturally the check will not be validated, and possible + * errors may go undetected. + * + * With decoder, it is possible to call lzma_get_check() + * immediately after lzma_code() has returned + * LZMA_UNSUPPORTED_CHECK. This way it is possible to find + * out what the unsupported Check ID was. + */ + + LZMA_GET_CHECK = 4, + /**< + * \brief Integrity check type is now available + * + * This value can be returned only by the lzma_code() function + * and only if the decoder was initialized with the + * LZMA_TELL_ANY_CHECK flag. LZMA_GET_CHECK tells the + * application that it may now call lzma_get_check() to find + * out the Check ID. This can be used, for example, to + * implement a decoder that accepts only files that have + * strong enough integrity check. + */ + + LZMA_MEM_ERROR = 5, + /**< + * \brief Cannot allocate memory + * + * Memory allocation failed, or the size of the allocation + * would be greater than SIZE_MAX. + * + * Due to internal implementation reasons, the coding cannot + * be continued even if more memory were made available after + * LZMA_MEM_ERROR. + */ + + LZMA_MEMLIMIT_ERROR = 6, + /** + * \brief Memory usage limit was reached + * + * Decoder would need more memory than allowed by the + * specified memory usage limit. To continue decoding, + * the memory usage limit has to be increased with + * lzma_memlimit_set(). + */ + + LZMA_FORMAT_ERROR = 7, + /**< + * \brief File format not recognized + * + * The decoder did not recognize the input as supported file + * format. This error can occur, for example, when trying to + * decode .lzma format file with lzma_stream_decoder, + * because lzma_stream_decoder accepts only the .xz format. + */ + + LZMA_OPTIONS_ERROR = 8, + /**< + * \brief Invalid or unsupported options + * + * Invalid or unsupported options, for example + * - unsupported filter(s) or filter options; or + * - reserved bits set in headers (decoder only). + * + * Rebuilding liblzma with more features enabled, or + * upgrading to a newer version of liblzma may help. + */ + + LZMA_DATA_ERROR = 9, + /**< + * \brief Data is corrupt + * + * The usage of this return value is different in encoders + * and decoders. In both encoder and decoder, the coding + * cannot continue after this error. + * + * Encoders return this if size limits of the target file + * format would be exceeded. These limits are huge, thus + * getting this error from an encoder is mostly theoretical. + * For example, the maximum compressed and uncompressed + * size of a .xz Stream is roughly 8 EiB (2^63 bytes). + * + * Decoders return this error if the input data is corrupt. + * This can mean, for example, invalid CRC32 in headers + * or invalid check of uncompressed data. + */ + + LZMA_BUF_ERROR = 10, + /**< + * \brief No progress is possible + * + * This error code is returned when the coder cannot consume + * any new input and produce any new output. The most common + * reason for this error is that the input stream being + * decoded is truncated or corrupt. + * + * This error is not fatal. Coding can be continued normally + * by providing more input and/or more output space, if + * possible. + * + * Typically the first call to lzma_code() that can do no + * progress returns LZMA_OK instead of LZMA_BUF_ERROR. Only + * the second consecutive call doing no progress will return + * LZMA_BUF_ERROR. This is intentional. + * + * With zlib, Z_BUF_ERROR may be returned even if the + * application is doing nothing wrong, so apps will need + * to handle Z_BUF_ERROR specially. The above hack + * guarantees that liblzma never returns LZMA_BUF_ERROR + * to properly written applications unless the input file + * is truncated or corrupt. This should simplify the + * applications a little. + */ + + LZMA_PROG_ERROR = 11, + /**< + * \brief Programming error + * + * This indicates that the arguments given to the function are + * invalid or the internal state of the decoder is corrupt. + * - Function arguments are invalid or the structures + * pointed by the argument pointers are invalid + * e.g. if strm->next_out has been set to NULL and + * strm->avail_out > 0 when calling lzma_code(). + * - lzma_* functions have been called in wrong order + * e.g. lzma_code() was called right after lzma_end(). + * - If errors occur randomly, the reason might be flaky + * hardware. + * + * If you think that your code is correct, this error code + * can be a sign of a bug in liblzma. See the documentation + * how to report bugs. + */ +} lzma_ret; + + +/** + * \brief The `action' argument for lzma_code() + * + * After the first use of LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, LZMA_FULL_BARRIER, + * or LZMA_FINISH, the same `action' must is used until lzma_code() returns + * LZMA_STREAM_END. Also, the amount of input (that is, strm->avail_in) must + * not be modified by the application until lzma_code() returns + * LZMA_STREAM_END. Changing the `action' or modifying the amount of input + * will make lzma_code() return LZMA_PROG_ERROR. + */ +typedef enum { + LZMA_RUN = 0, + /**< + * \brief Continue coding + * + * Encoder: Encode as much input as possible. Some internal + * buffering will probably be done (depends on the filter + * chain in use), which causes latency: the input used won't + * usually be decodeable from the output of the same + * lzma_code() call. + * + * Decoder: Decode as much input as possible and produce as + * much output as possible. + */ + + LZMA_SYNC_FLUSH = 1, + /**< + * \brief Make all the input available at output + * + * Normally the encoder introduces some latency. + * LZMA_SYNC_FLUSH forces all the buffered data to be + * available at output without resetting the internal + * state of the encoder. This way it is possible to use + * compressed stream for example for communication over + * network. + * + * Only some filters support LZMA_SYNC_FLUSH. Trying to use + * LZMA_SYNC_FLUSH with filters that don't support it will + * make lzma_code() return LZMA_OPTIONS_ERROR. For example, + * LZMA1 doesn't support LZMA_SYNC_FLUSH but LZMA2 does. + * + * Using LZMA_SYNC_FLUSH very often can dramatically reduce + * the compression ratio. With some filters (for example, + * LZMA2), fine-tuning the compression options may help + * mitigate this problem significantly (for example, + * match finder with LZMA2). + * + * Decoders don't support LZMA_SYNC_FLUSH. + */ + + LZMA_FULL_FLUSH = 2, + /**< + * \brief Finish encoding of the current Block + * + * All the input data going to the current Block must have + * been given to the encoder (the last bytes can still be + * pending in *next_in). Call lzma_code() with LZMA_FULL_FLUSH + * until it returns LZMA_STREAM_END. Then continue normally + * with LZMA_RUN or finish the Stream with LZMA_FINISH. + * + * This action is currently supported only by Stream encoder + * and easy encoder (which uses Stream encoder). If there is + * no unfinished Block, no empty Block is created. + */ + + LZMA_FULL_BARRIER = 4, + /**< + * \brief Finish encoding of the current Block + * + * This is like LZMA_FULL_FLUSH except that this doesn't + * necessarily wait until all the input has been made + * available via the output buffer. That is, lzma_code() + * might return LZMA_STREAM_END as soon as all the input + * has been consumed (avail_in == 0). + * + * LZMA_FULL_BARRIER is useful with a threaded encoder if + * one wants to split the .xz Stream into Blocks at specific + * offsets but doesn't care if the output isn't flushed + * immediately. Using LZMA_FULL_BARRIER allows keeping + * the threads busy while LZMA_FULL_FLUSH would make + * lzma_code() wait until all the threads have finished + * until more data could be passed to the encoder. + * + * With a lzma_stream initialized with the single-threaded + * lzma_stream_encoder() or lzma_easy_encoder(), + * LZMA_FULL_BARRIER is an alias for LZMA_FULL_FLUSH. + */ + + LZMA_FINISH = 3 + /**< + * \brief Finish the coding operation + * + * All the input data must have been given to the encoder + * (the last bytes can still be pending in next_in). + * Call lzma_code() with LZMA_FINISH until it returns + * LZMA_STREAM_END. Once LZMA_FINISH has been used, + * the amount of input must no longer be changed by + * the application. + * + * When decoding, using LZMA_FINISH is optional unless the + * LZMA_CONCATENATED flag was used when the decoder was + * initialized. When LZMA_CONCATENATED was not used, the only + * effect of LZMA_FINISH is that the amount of input must not + * be changed just like in the encoder. + */ +} lzma_action; + + +/** + * \brief Custom functions for memory handling + * + * A pointer to lzma_allocator may be passed via lzma_stream structure + * to liblzma, and some advanced functions take a pointer to lzma_allocator + * as a separate function argument. The library will use the functions + * specified in lzma_allocator for memory handling instead of the default + * malloc() and free(). C++ users should note that the custom memory + * handling functions must not throw exceptions. + * + * Single-threaded mode only: liblzma doesn't make an internal copy of + * lzma_allocator. Thus, it is OK to change these function pointers in + * the middle of the coding process, but obviously it must be done + * carefully to make sure that the replacement `free' can deallocate + * memory allocated by the earlier `alloc' function(s). + * + * Multithreaded mode: liblzma might internally store pointers to the + * lzma_allocator given via the lzma_stream structure. The application + * must not change the allocator pointer in lzma_stream or the contents + * of the pointed lzma_allocator structure until lzma_end() has been used + * to free the memory associated with that lzma_stream. The allocation + * functions might be called simultaneously from multiple threads, and + * thus they must be thread safe. + */ +typedef struct { + /** + * \brief Pointer to a custom memory allocation function + * + * If you don't want a custom allocator, but still want + * custom free(), set this to NULL and liblzma will use + * the standard malloc(). + * + * \param opaque lzma_allocator.opaque (see below) + * \param nmemb Number of elements like in calloc(). liblzma + * will always set nmemb to 1, so it is safe to + * ignore nmemb in a custom allocator if you like. + * The nmemb argument exists only for + * compatibility with zlib and libbzip2. + * \param size Size of an element in bytes. + * liblzma never sets this to zero. + * + * \return Pointer to the beginning of a memory block of + * `size' bytes, or NULL if allocation fails + * for some reason. When allocation fails, functions + * of liblzma return LZMA_MEM_ERROR. + * + * The allocator should not waste time zeroing the allocated buffers. + * This is not only about speed, but also memory usage, since the + * operating system kernel doesn't necessarily allocate the requested + * memory in physical memory until it is actually used. With small + * input files, liblzma may actually need only a fraction of the + * memory that it requested for allocation. + * + * \note LZMA_MEM_ERROR is also used when the size of the + * allocation would be greater than SIZE_MAX. Thus, + * don't assume that the custom allocator must have + * returned NULL if some function from liblzma + * returns LZMA_MEM_ERROR. + */ + void *(LZMA_API_CALL *alloc)(void *opaque, size_t nmemb, size_t size); + + /** + * \brief Pointer to a custom memory freeing function + * + * If you don't want a custom freeing function, but still + * want a custom allocator, set this to NULL and liblzma + * will use the standard free(). + * + * \param opaque lzma_allocator.opaque (see below) + * \param ptr Pointer returned by lzma_allocator.alloc(), + * or when it is set to NULL, a pointer returned + * by the standard malloc(). + */ + void (LZMA_API_CALL *free)(void *opaque, void *ptr); + + /** + * \brief Pointer passed to .alloc() and .free() + * + * opaque is passed as the first argument to lzma_allocator.alloc() + * and lzma_allocator.free(). This intended to ease implementing + * custom memory allocation functions for use with liblzma. + * + * If you don't need this, you should set this to NULL. + */ + void *opaque; + +} lzma_allocator; + + +/** + * \brief Internal data structure + * + * The contents of this structure is not visible outside the library. + */ +typedef struct lzma_internal_s lzma_internal; + + +/** + * \brief Passing data to and from liblzma + * + * The lzma_stream structure is used for + * - passing pointers to input and output buffers to liblzma; + * - defining custom memory hander functions; and + * - holding a pointer to coder-specific internal data structures. + * + * Typical usage: + * + * - After allocating lzma_stream (on stack or with malloc()), it must be + * initialized to LZMA_STREAM_INIT (see LZMA_STREAM_INIT for details). + * + * - Initialize a coder to the lzma_stream, for example by using + * lzma_easy_encoder() or lzma_auto_decoder(). Some notes: + * - In contrast to zlib, strm->next_in and strm->next_out are + * ignored by all initialization functions, thus it is safe + * to not initialize them yet. + * - The initialization functions always set strm->total_in and + * strm->total_out to zero. + * - If the initialization function fails, no memory is left allocated + * that would require freeing with lzma_end() even if some memory was + * associated with the lzma_stream structure when the initialization + * function was called. + * + * - Use lzma_code() to do the actual work. + * + * - Once the coding has been finished, the existing lzma_stream can be + * reused. It is OK to reuse lzma_stream with different initialization + * function without calling lzma_end() first. Old allocations are + * automatically freed. + * + * - Finally, use lzma_end() to free the allocated memory. lzma_end() never + * frees the lzma_stream structure itself. + * + * Application may modify the values of total_in and total_out as it wants. + * They are updated by liblzma to match the amount of data read and + * written but aren't used for anything else except as a possible return + * values from lzma_get_progress(). + */ +typedef struct { + const uint8_t *next_in; /**< Pointer to the next input byte. */ + size_t avail_in; /**< Number of available input bytes in next_in. */ + uint64_t total_in; /**< Total number of bytes read by liblzma. */ + + uint8_t *next_out; /**< Pointer to the next output position. */ + size_t avail_out; /**< Amount of free space in next_out. */ + uint64_t total_out; /**< Total number of bytes written by liblzma. */ + + /** + * \brief Custom memory allocation functions + * + * In most cases this is NULL which makes liblzma use + * the standard malloc() and free(). + * + * \note In 5.0.x this is not a const pointer. + */ + const lzma_allocator *allocator; + + /** Internal state is not visible to applications. */ + lzma_internal *internal; + + /* + * Reserved space to allow possible future extensions without + * breaking the ABI. Excluding the initialization of this structure, + * you should not touch these, because the names of these variables + * may change. + */ + void *reserved_ptr1; + void *reserved_ptr2; + void *reserved_ptr3; + void *reserved_ptr4; + uint64_t reserved_int1; + uint64_t reserved_int2; + size_t reserved_int3; + size_t reserved_int4; + lzma_reserved_enum reserved_enum1; + lzma_reserved_enum reserved_enum2; + +} lzma_stream; + + +/** + * \brief Initialization for lzma_stream + * + * When you declare an instance of lzma_stream, you can immediately + * initialize it so that initialization functions know that no memory + * has been allocated yet: + * + * lzma_stream strm = LZMA_STREAM_INIT; + * + * If you need to initialize a dynamically allocated lzma_stream, you can use + * memset(strm_pointer, 0, sizeof(lzma_stream)). Strictly speaking, this + * violates the C standard since NULL may have different internal + * representation than zero, but it should be portable enough in practice. + * Anyway, for maximum portability, you can use something like this: + * + * lzma_stream tmp = LZMA_STREAM_INIT; + * *strm = tmp; + */ +#define LZMA_STREAM_INIT \ + { NULL, 0, 0, NULL, 0, 0, NULL, NULL, \ + NULL, NULL, NULL, NULL, 0, 0, 0, 0, \ + LZMA_RESERVED_ENUM, LZMA_RESERVED_ENUM } + + +/** + * \brief Encode or decode data + * + * Once the lzma_stream has been successfully initialized (e.g. with + * lzma_stream_encoder()), the actual encoding or decoding is done + * using this function. The application has to update strm->next_in, + * strm->avail_in, strm->next_out, and strm->avail_out to pass input + * to and get output from liblzma. + * + * See the description of the coder-specific initialization function to find + * out what `action' values are supported by the coder. + */ +extern LZMA_API(lzma_ret) lzma_code(lzma_stream *strm, lzma_action action) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Free memory allocated for the coder data structures + * + * \param strm Pointer to lzma_stream that is at least initialized + * with LZMA_STREAM_INIT. + * + * After lzma_end(strm), strm->internal is guaranteed to be NULL. No other + * members of the lzma_stream structure are touched. + * + * \note zlib indicates an error if application end()s unfinished + * stream structure. liblzma doesn't do this, and assumes that + * application knows what it is doing. + */ +extern LZMA_API(void) lzma_end(lzma_stream *strm) lzma_nothrow; + + +/** + * \brief Get progress information + * + * In single-threaded mode, applications can get progress information from + * strm->total_in and strm->total_out. In multi-threaded mode this is less + * useful because a significant amount of both input and output data gets + * buffered internally by liblzma. This makes total_in and total_out give + * misleading information and also makes the progress indicator updates + * non-smooth. + * + * This function gives realistic progress information also in multi-threaded + * mode by taking into account the progress made by each thread. In + * single-threaded mode *progress_in and *progress_out are set to + * strm->total_in and strm->total_out, respectively. + */ +extern LZMA_API(void) lzma_get_progress(lzma_stream *strm, + uint64_t *progress_in, uint64_t *progress_out) lzma_nothrow; + + +/** + * \brief Get the memory usage of decoder filter chain + * + * This function is currently supported only when *strm has been initialized + * with a function that takes a memlimit argument. With other functions, you + * should use e.g. lzma_raw_encoder_memusage() or lzma_raw_decoder_memusage() + * to estimate the memory requirements. + * + * This function is useful e.g. after LZMA_MEMLIMIT_ERROR to find out how big + * the memory usage limit should have been to decode the input. Note that + * this may give misleading information if decoding .xz Streams that have + * multiple Blocks, because each Block can have different memory requirements. + * + * \return How much memory is currently allocated for the filter + * decoders. If no filter chain is currently allocated, + * some non-zero value is still returned, which is less than + * or equal to what any filter chain would indicate as its + * memory requirement. + * + * If this function isn't supported by *strm or some other error + * occurs, zero is returned. + */ +extern LZMA_API(uint64_t) lzma_memusage(const lzma_stream *strm) + lzma_nothrow lzma_attr_pure; + + +/** + * \brief Get the current memory usage limit + * + * This function is supported only when *strm has been initialized with + * a function that takes a memlimit argument. + * + * \return On success, the current memory usage limit is returned + * (always non-zero). On error, zero is returned. + */ +extern LZMA_API(uint64_t) lzma_memlimit_get(const lzma_stream *strm) + lzma_nothrow lzma_attr_pure; + + +/** + * \brief Set the memory usage limit + * + * This function is supported only when *strm has been initialized with + * a function that takes a memlimit argument. + * + * liblzma 5.2.3 and earlier has a bug where memlimit value of 0 causes + * this function to do nothing (leaving the limit unchanged) and still + * return LZMA_OK. Later versions treat 0 as if 1 had been specified (so + * lzma_memlimit_get() will return 1 even if you specify 0 here). + * + * \return - LZMA_OK: New memory usage limit successfully set. + * - LZMA_MEMLIMIT_ERROR: The new limit is too small. + * The limit was not changed. + * - LZMA_PROG_ERROR: Invalid arguments, e.g. *strm doesn't + * support memory usage limit. + */ +extern LZMA_API(lzma_ret) lzma_memlimit_set( + lzma_stream *strm, uint64_t memlimit) lzma_nothrow; diff --git a/dependencies/cmliblzma/liblzma/api/lzma/bcj.h b/dependencies/cmliblzma/liblzma/api/lzma/bcj.h new file mode 100644 index 0000000..8e37538 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/api/lzma/bcj.h @@ -0,0 +1,90 @@ +/** + * \file lzma/bcj.h + * \brief Branch/Call/Jump conversion filters + */ + +/* + * Author: Lasse Collin + * + * This file has been put into the public domain. + * You can do whatever you want with this file. + * + * See ../lzma.h for information about liblzma as a whole. + */ + +#ifndef LZMA_H_INTERNAL +# error Never include this file directly. Use instead. +#endif + + +/* Filter IDs for lzma_filter.id */ + +#define LZMA_FILTER_X86 LZMA_VLI_C(0x04) + /**< + * Filter for x86 binaries + */ + +#define LZMA_FILTER_POWERPC LZMA_VLI_C(0x05) + /**< + * Filter for Big endian PowerPC binaries + */ + +#define LZMA_FILTER_IA64 LZMA_VLI_C(0x06) + /**< + * Filter for IA-64 (Itanium) binaries. + */ + +#define LZMA_FILTER_ARM LZMA_VLI_C(0x07) + /**< + * Filter for ARM binaries. + */ + +#define LZMA_FILTER_ARMTHUMB LZMA_VLI_C(0x08) + /**< + * Filter for ARM-Thumb binaries. + */ + +#define LZMA_FILTER_SPARC LZMA_VLI_C(0x09) + /**< + * Filter for SPARC binaries. + */ + + +/** + * \brief Options for BCJ filters + * + * The BCJ filters never change the size of the data. Specifying options + * for them is optional: if pointer to options is NULL, default value is + * used. You probably never need to specify options to BCJ filters, so just + * set the options pointer to NULL and be happy. + * + * If options with non-default values have been specified when encoding, + * the same options must also be specified when decoding. + * + * \note At the moment, none of the BCJ filters support + * LZMA_SYNC_FLUSH. If LZMA_SYNC_FLUSH is specified, + * LZMA_OPTIONS_ERROR will be returned. If there is need, + * partial support for LZMA_SYNC_FLUSH can be added in future. + * Partial means that flushing would be possible only at + * offsets that are multiple of 2, 4, or 16 depending on + * the filter, except x86 which cannot be made to support + * LZMA_SYNC_FLUSH predictably. + */ +typedef struct { + /** + * \brief Start offset for conversions + * + * This setting is useful only when the same filter is used + * _separately_ for multiple sections of the same executable file, + * and the sections contain cross-section branch/call/jump + * instructions. In that case it is beneficial to set the start + * offset of the non-first sections so that the relative addresses + * of the cross-section branch/call/jump instructions will use the + * same absolute addresses as in the first section. + * + * When the pointer to options is NULL, the default value (zero) + * is used. + */ + uint32_t start_offset; + +} lzma_options_bcj; diff --git a/dependencies/cmliblzma/liblzma/api/lzma/block.h b/dependencies/cmliblzma/liblzma/api/lzma/block.h new file mode 100644 index 0000000..7bdcfd7 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/api/lzma/block.h @@ -0,0 +1,581 @@ +/** + * \file lzma/block.h + * \brief .xz Block handling + */ + +/* + * Author: Lasse Collin + * + * This file has been put into the public domain. + * You can do whatever you want with this file. + * + * See ../lzma.h for information about liblzma as a whole. + */ + +#ifndef LZMA_H_INTERNAL +# error Never include this file directly. Use instead. +#endif + + +/** + * \brief Options for the Block and Block Header encoders and decoders + * + * Different Block handling functions use different parts of this structure. + * Some read some members, other functions write, and some do both. Only the + * members listed for reading need to be initialized when the specified + * functions are called. The members marked for writing will be assigned + * new values at some point either by calling the given function or by + * later calls to lzma_code(). + */ +typedef struct { + /** + * \brief Block format version + * + * To prevent API and ABI breakages when new features are needed, + * a version number is used to indicate which fields in this + * structure are in use: + * - liblzma >= 5.0.0: version = 0 is supported. + * - liblzma >= 5.1.4beta: Support for version = 1 was added, + * which adds the ignore_check field. + * + * If version is greater than one, most Block related functions + * will return LZMA_OPTIONS_ERROR (lzma_block_header_decode() works + * with any version value). + * + * Read by: + * - All functions that take pointer to lzma_block as argument, + * including lzma_block_header_decode(). + * + * Written by: + * - lzma_block_header_decode() + */ + uint32_t version; + + /** + * \brief Size of the Block Header field + * + * This is always a multiple of four. + * + * Read by: + * - lzma_block_header_encode() + * - lzma_block_header_decode() + * - lzma_block_compressed_size() + * - lzma_block_unpadded_size() + * - lzma_block_total_size() + * - lzma_block_decoder() + * - lzma_block_buffer_decode() + * + * Written by: + * - lzma_block_header_size() + * - lzma_block_buffer_encode() + */ + uint32_t header_size; +# define LZMA_BLOCK_HEADER_SIZE_MIN 8 +# define LZMA_BLOCK_HEADER_SIZE_MAX 1024 + + /** + * \brief Type of integrity Check + * + * The Check ID is not stored into the Block Header, thus its value + * must be provided also when decoding. + * + * Read by: + * - lzma_block_header_encode() + * - lzma_block_header_decode() + * - lzma_block_compressed_size() + * - lzma_block_unpadded_size() + * - lzma_block_total_size() + * - lzma_block_encoder() + * - lzma_block_decoder() + * - lzma_block_buffer_encode() + * - lzma_block_buffer_decode() + */ + lzma_check check; + + /** + * \brief Size of the Compressed Data in bytes + * + * Encoding: If this is not LZMA_VLI_UNKNOWN, Block Header encoder + * will store this value to the Block Header. Block encoder doesn't + * care about this value, but will set it once the encoding has been + * finished. + * + * Decoding: If this is not LZMA_VLI_UNKNOWN, Block decoder will + * verify that the size of the Compressed Data field matches + * compressed_size. + * + * Usually you don't know this value when encoding in streamed mode, + * and thus cannot write this field into the Block Header. + * + * In non-streamed mode you can reserve space for this field before + * encoding the actual Block. After encoding the data, finish the + * Block by encoding the Block Header. Steps in detail: + * + * - Set compressed_size to some big enough value. If you don't know + * better, use LZMA_VLI_MAX, but remember that bigger values take + * more space in Block Header. + * + * - Call lzma_block_header_size() to see how much space you need to + * reserve for the Block Header. + * + * - Encode the Block using lzma_block_encoder() and lzma_code(). + * It sets compressed_size to the correct value. + * + * - Use lzma_block_header_encode() to encode the Block Header. + * Because space was reserved in the first step, you don't need + * to call lzma_block_header_size() anymore, because due to + * reserving, header_size has to be big enough. If it is "too big", + * lzma_block_header_encode() will add enough Header Padding to + * make Block Header to match the size specified by header_size. + * + * Read by: + * - lzma_block_header_size() + * - lzma_block_header_encode() + * - lzma_block_compressed_size() + * - lzma_block_unpadded_size() + * - lzma_block_total_size() + * - lzma_block_decoder() + * - lzma_block_buffer_decode() + * + * Written by: + * - lzma_block_header_decode() + * - lzma_block_compressed_size() + * - lzma_block_encoder() + * - lzma_block_decoder() + * - lzma_block_buffer_encode() + * - lzma_block_buffer_decode() + */ + lzma_vli compressed_size; + + /** + * \brief Uncompressed Size in bytes + * + * This is handled very similarly to compressed_size above. + * + * uncompressed_size is needed by fewer functions than + * compressed_size. This is because uncompressed_size isn't + * needed to validate that Block stays within proper limits. + * + * Read by: + * - lzma_block_header_size() + * - lzma_block_header_encode() + * - lzma_block_decoder() + * - lzma_block_buffer_decode() + * + * Written by: + * - lzma_block_header_decode() + * - lzma_block_encoder() + * - lzma_block_decoder() + * - lzma_block_buffer_encode() + * - lzma_block_buffer_decode() + */ + lzma_vli uncompressed_size; + + /** + * \brief Array of filters + * + * There can be 1-4 filters. The end of the array is marked with + * .id = LZMA_VLI_UNKNOWN. + * + * Read by: + * - lzma_block_header_size() + * - lzma_block_header_encode() + * - lzma_block_encoder() + * - lzma_block_decoder() + * - lzma_block_buffer_encode() + * - lzma_block_buffer_decode() + * + * Written by: + * - lzma_block_header_decode(): Note that this does NOT free() + * the old filter options structures. All unused filters[] will + * have .id == LZMA_VLI_UNKNOWN and .options == NULL. If + * decoding fails, all filters[] are guaranteed to be + * LZMA_VLI_UNKNOWN and NULL. + * + * \note Because of the array is terminated with + * .id = LZMA_VLI_UNKNOWN, the actual array must + * have LZMA_FILTERS_MAX + 1 members or the Block + * Header decoder will overflow the buffer. + */ + lzma_filter *filters; + + /** + * \brief Raw value stored in the Check field + * + * After successful coding, the first lzma_check_size(check) bytes + * of this array contain the raw value stored in the Check field. + * + * Note that CRC32 and CRC64 are stored in little endian byte order. + * Take it into account if you display the Check values to the user. + * + * Written by: + * - lzma_block_encoder() + * - lzma_block_decoder() + * - lzma_block_buffer_encode() + * - lzma_block_buffer_decode() + */ + uint8_t raw_check[LZMA_CHECK_SIZE_MAX]; + + /* + * Reserved space to allow possible future extensions without + * breaking the ABI. You should not touch these, because the names + * of these variables may change. These are and will never be used + * with the currently supported options, so it is safe to leave these + * uninitialized. + */ + void *reserved_ptr1; + void *reserved_ptr2; + void *reserved_ptr3; + uint32_t reserved_int1; + uint32_t reserved_int2; + lzma_vli reserved_int3; + lzma_vli reserved_int4; + lzma_vli reserved_int5; + lzma_vli reserved_int6; + lzma_vli reserved_int7; + lzma_vli reserved_int8; + lzma_reserved_enum reserved_enum1; + lzma_reserved_enum reserved_enum2; + lzma_reserved_enum reserved_enum3; + lzma_reserved_enum reserved_enum4; + + /** + * \brief A flag to Block decoder to not verify the Check field + * + * This field is supported by liblzma >= 5.1.4beta if .version >= 1. + * + * If this is set to true, the integrity check won't be calculated + * and verified. Unless you know what you are doing, you should + * leave this to false. (A reason to set this to true is when the + * file integrity is verified externally anyway and you want to + * speed up the decompression, which matters mostly when using + * SHA-256 as the integrity check.) + * + * If .version >= 1, read by: + * - lzma_block_decoder() + * - lzma_block_buffer_decode() + * + * Written by (.version is ignored): + * - lzma_block_header_decode() always sets this to false + */ + lzma_bool ignore_check; + + lzma_bool reserved_bool2; + lzma_bool reserved_bool3; + lzma_bool reserved_bool4; + lzma_bool reserved_bool5; + lzma_bool reserved_bool6; + lzma_bool reserved_bool7; + lzma_bool reserved_bool8; + +} lzma_block; + + +/** + * \brief Decode the Block Header Size field + * + * To decode Block Header using lzma_block_header_decode(), the size of the + * Block Header has to be known and stored into lzma_block.header_size. + * The size can be calculated from the first byte of a Block using this macro. + * Note that if the first byte is 0x00, it indicates beginning of Index; use + * this macro only when the byte is not 0x00. + * + * There is no encoding macro, because Block Header encoder is enough for that. + */ +#define lzma_block_header_size_decode(b) (((uint32_t)(b) + 1) * 4) + + +/** + * \brief Calculate Block Header Size + * + * Calculate the minimum size needed for the Block Header field using the + * settings specified in the lzma_block structure. Note that it is OK to + * increase the calculated header_size value as long as it is a multiple of + * four and doesn't exceed LZMA_BLOCK_HEADER_SIZE_MAX. Increasing header_size + * just means that lzma_block_header_encode() will add Header Padding. + * + * \return - LZMA_OK: Size calculated successfully and stored to + * block->header_size. + * - LZMA_OPTIONS_ERROR: Unsupported version, filters or + * filter options. + * - LZMA_PROG_ERROR: Invalid values like compressed_size == 0. + * + * \note This doesn't check that all the options are valid i.e. this + * may return LZMA_OK even if lzma_block_header_encode() or + * lzma_block_encoder() would fail. If you want to validate the + * filter chain, consider using lzma_memlimit_encoder() which as + * a side-effect validates the filter chain. + */ +extern LZMA_API(lzma_ret) lzma_block_header_size(lzma_block *block) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Encode Block Header + * + * The caller must have calculated the size of the Block Header already with + * lzma_block_header_size(). If a value larger than the one calculated by + * lzma_block_header_size() is used, the Block Header will be padded to the + * specified size. + * + * \param out Beginning of the output buffer. This must be + * at least block->header_size bytes. + * \param block Block options to be encoded. + * + * \return - LZMA_OK: Encoding was successful. block->header_size + * bytes were written to output buffer. + * - LZMA_OPTIONS_ERROR: Invalid or unsupported options. + * - LZMA_PROG_ERROR: Invalid arguments, for example + * block->header_size is invalid or block->filters is NULL. + */ +extern LZMA_API(lzma_ret) lzma_block_header_encode( + const lzma_block *block, uint8_t *out) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Decode Block Header + * + * block->version should (usually) be set to the highest value supported + * by the application. If the application sets block->version to a value + * higher than supported by the current liblzma version, this function will + * downgrade block->version to the highest value supported by it. Thus one + * should check the value of block->version after calling this function if + * block->version was set to a non-zero value and the application doesn't + * otherwise know that the liblzma version being used is new enough to + * support the specified block->version. + * + * The size of the Block Header must have already been decoded with + * lzma_block_header_size_decode() macro and stored to block->header_size. + * + * The integrity check type from Stream Header must have been stored + * to block->check. + * + * block->filters must have been allocated, but they don't need to be + * initialized (possible existing filter options are not freed). + * + * \param block Destination for Block options. + * \param allocator lzma_allocator for custom allocator functions. + * Set to NULL to use malloc() (and also free() + * if an error occurs). + * \param in Beginning of the input buffer. This must be + * at least block->header_size bytes. + * + * \return - LZMA_OK: Decoding was successful. block->header_size + * bytes were read from the input buffer. + * - LZMA_OPTIONS_ERROR: The Block Header specifies some + * unsupported options such as unsupported filters. This can + * happen also if block->version was set to a too low value + * compared to what would be required to properly represent + * the information stored in the Block Header. + * - LZMA_DATA_ERROR: Block Header is corrupt, for example, + * the CRC32 doesn't match. + * - LZMA_PROG_ERROR: Invalid arguments, for example + * block->header_size is invalid or block->filters is NULL. + */ +extern LZMA_API(lzma_ret) lzma_block_header_decode(lzma_block *block, + const lzma_allocator *allocator, const uint8_t *in) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Validate and set Compressed Size according to Unpadded Size + * + * Block Header stores Compressed Size, but Index has Unpadded Size. If the + * application has already parsed the Index and is now decoding Blocks, + * it can calculate Compressed Size from Unpadded Size. This function does + * exactly that with error checking: + * + * - Compressed Size calculated from Unpadded Size must be positive integer, + * that is, Unpadded Size must be big enough that after Block Header and + * Check fields there's still at least one byte for Compressed Size. + * + * - If Compressed Size was present in Block Header, the new value + * calculated from Unpadded Size is compared against the value + * from Block Header. + * + * \note This function must be called _after_ decoding the Block Header + * field so that it can properly validate Compressed Size if it + * was present in Block Header. + * + * \return - LZMA_OK: block->compressed_size was set successfully. + * - LZMA_DATA_ERROR: unpadded_size is too small compared to + * block->header_size and lzma_check_size(block->check). + * - LZMA_PROG_ERROR: Some values are invalid. For example, + * block->header_size must be a multiple of four and + * between 8 and 1024 inclusive. + */ +extern LZMA_API(lzma_ret) lzma_block_compressed_size( + lzma_block *block, lzma_vli unpadded_size) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Calculate Unpadded Size + * + * The Index field stores Unpadded Size and Uncompressed Size. The latter + * can be taken directly from the lzma_block structure after coding a Block, + * but Unpadded Size needs to be calculated from Block Header Size, + * Compressed Size, and size of the Check field. This is where this function + * is needed. + * + * \return Unpadded Size on success, or zero on error. + */ +extern LZMA_API(lzma_vli) lzma_block_unpadded_size(const lzma_block *block) + lzma_nothrow lzma_attr_pure; + + +/** + * \brief Calculate the total encoded size of a Block + * + * This is equivalent to lzma_block_unpadded_size() except that the returned + * value includes the size of the Block Padding field. + * + * \return On success, total encoded size of the Block. On error, + * zero is returned. + */ +extern LZMA_API(lzma_vli) lzma_block_total_size(const lzma_block *block) + lzma_nothrow lzma_attr_pure; + + +/** + * \brief Initialize .xz Block encoder + * + * Valid actions for lzma_code() are LZMA_RUN, LZMA_SYNC_FLUSH (only if the + * filter chain supports it), and LZMA_FINISH. + * + * \return - LZMA_OK: All good, continue with lzma_code(). + * - LZMA_MEM_ERROR + * - LZMA_OPTIONS_ERROR + * - LZMA_UNSUPPORTED_CHECK: block->check specifies a Check ID + * that is not supported by this buid of liblzma. Initializing + * the encoder failed. + * - LZMA_PROG_ERROR + */ +extern LZMA_API(lzma_ret) lzma_block_encoder( + lzma_stream *strm, lzma_block *block) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Initialize .xz Block decoder + * + * Valid actions for lzma_code() are LZMA_RUN and LZMA_FINISH. Using + * LZMA_FINISH is not required. It is supported only for convenience. + * + * \return - LZMA_OK: All good, continue with lzma_code(). + * - LZMA_UNSUPPORTED_CHECK: Initialization was successful, but + * the given Check ID is not supported, thus Check will be + * ignored. + * - LZMA_PROG_ERROR + * - LZMA_MEM_ERROR + */ +extern LZMA_API(lzma_ret) lzma_block_decoder( + lzma_stream *strm, lzma_block *block) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Calculate maximum output size for single-call Block encoding + * + * This is equivalent to lzma_stream_buffer_bound() but for .xz Blocks. + * See the documentation of lzma_stream_buffer_bound(). + */ +extern LZMA_API(size_t) lzma_block_buffer_bound(size_t uncompressed_size) + lzma_nothrow; + + +/** + * \brief Single-call .xz Block encoder + * + * In contrast to the multi-call encoder initialized with + * lzma_block_encoder(), this function encodes also the Block Header. This + * is required to make it possible to write appropriate Block Header also + * in case the data isn't compressible, and different filter chain has to be + * used to encode the data in uncompressed form using uncompressed chunks + * of the LZMA2 filter. + * + * When the data isn't compressible, header_size, compressed_size, and + * uncompressed_size are set just like when the data was compressible, but + * it is possible that header_size is too small to hold the filter chain + * specified in block->filters, because that isn't necessarily the filter + * chain that was actually used to encode the data. lzma_block_unpadded_size() + * still works normally, because it doesn't read the filters array. + * + * \param block Block options: block->version, block->check, + * and block->filters must have been initialized. + * \param allocator lzma_allocator for custom allocator functions. + * Set to NULL to use malloc() and free(). + * \param in Beginning of the input buffer + * \param in_size Size of the input buffer + * \param out Beginning of the output buffer + * \param out_pos The next byte will be written to out[*out_pos]. + * *out_pos is updated only if encoding succeeds. + * \param out_size Size of the out buffer; the first byte into + * which no data is written to is out[out_size]. + * + * \return - LZMA_OK: Encoding was successful. + * - LZMA_BUF_ERROR: Not enough output buffer space. + * - LZMA_UNSUPPORTED_CHECK + * - LZMA_OPTIONS_ERROR + * - LZMA_MEM_ERROR + * - LZMA_DATA_ERROR + * - LZMA_PROG_ERROR + */ +extern LZMA_API(lzma_ret) lzma_block_buffer_encode( + lzma_block *block, const lzma_allocator *allocator, + const uint8_t *in, size_t in_size, + uint8_t *out, size_t *out_pos, size_t out_size) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Single-call uncompressed .xz Block encoder + * + * This is like lzma_block_buffer_encode() except this doesn't try to + * compress the data and instead encodes the data using LZMA2 uncompressed + * chunks. The required output buffer size can be determined with + * lzma_block_buffer_bound(). + * + * Since the data won't be compressed, this function ignores block->filters. + * This function doesn't take lzma_allocator because this function doesn't + * allocate any memory from the heap. + */ +extern LZMA_API(lzma_ret) lzma_block_uncomp_encode(lzma_block *block, + const uint8_t *in, size_t in_size, + uint8_t *out, size_t *out_pos, size_t out_size) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Single-call .xz Block decoder + * + * This is single-call equivalent of lzma_block_decoder(), and requires that + * the caller has already decoded Block Header and checked its memory usage. + * + * \param block Block options just like with lzma_block_decoder(). + * \param allocator lzma_allocator for custom allocator functions. + * Set to NULL to use malloc() and free(). + * \param in Beginning of the input buffer + * \param in_pos The next byte will be read from in[*in_pos]. + * *in_pos is updated only if decoding succeeds. + * \param in_size Size of the input buffer; the first byte that + * won't be read is in[in_size]. + * \param out Beginning of the output buffer + * \param out_pos The next byte will be written to out[*out_pos]. + * *out_pos is updated only if encoding succeeds. + * \param out_size Size of the out buffer; the first byte into + * which no data is written to is out[out_size]. + * + * \return - LZMA_OK: Decoding was successful. + * - LZMA_OPTIONS_ERROR + * - LZMA_DATA_ERROR + * - LZMA_MEM_ERROR + * - LZMA_BUF_ERROR: Output buffer was too small. + * - LZMA_PROG_ERROR + */ +extern LZMA_API(lzma_ret) lzma_block_buffer_decode( + lzma_block *block, const lzma_allocator *allocator, + const uint8_t *in, size_t *in_pos, size_t in_size, + uint8_t *out, size_t *out_pos, size_t out_size) + lzma_nothrow; diff --git a/dependencies/cmliblzma/liblzma/api/lzma/check.h b/dependencies/cmliblzma/liblzma/api/lzma/check.h new file mode 100644 index 0000000..6a243db --- /dev/null +++ b/dependencies/cmliblzma/liblzma/api/lzma/check.h @@ -0,0 +1,150 @@ +/** + * \file lzma/check.h + * \brief Integrity checks + */ + +/* + * Author: Lasse Collin + * + * This file has been put into the public domain. + * You can do whatever you want with this file. + * + * See ../lzma.h for information about liblzma as a whole. + */ + +#ifndef LZMA_H_INTERNAL +# error Never include this file directly. Use instead. +#endif + + +/** + * \brief Type of the integrity check (Check ID) + * + * The .xz format supports multiple types of checks that are calculated + * from the uncompressed data. They vary in both speed and ability to + * detect errors. + */ +typedef enum { + LZMA_CHECK_NONE = 0, + /**< + * No Check is calculated. + * + * Size of the Check field: 0 bytes + */ + + LZMA_CHECK_CRC32 = 1, + /**< + * CRC32 using the polynomial from the IEEE 802.3 standard + * + * Size of the Check field: 4 bytes + */ + + LZMA_CHECK_CRC64 = 4, + /**< + * CRC64 using the polynomial from the ECMA-182 standard + * + * Size of the Check field: 8 bytes + */ + + LZMA_CHECK_SHA256 = 10 + /**< + * SHA-256 + * + * Size of the Check field: 32 bytes + */ +} lzma_check; + + +/** + * \brief Maximum valid Check ID + * + * The .xz file format specification specifies 16 Check IDs (0-15). Some + * of them are only reserved, that is, no actual Check algorithm has been + * assigned. When decoding, liblzma still accepts unknown Check IDs for + * future compatibility. If a valid but unsupported Check ID is detected, + * liblzma can indicate a warning; see the flags LZMA_TELL_NO_CHECK, + * LZMA_TELL_UNSUPPORTED_CHECK, and LZMA_TELL_ANY_CHECK in container.h. + */ +#define LZMA_CHECK_ID_MAX 15 + + +/** + * \brief Test if the given Check ID is supported + * + * Return true if the given Check ID is supported by this liblzma build. + * Otherwise false is returned. It is safe to call this with a value that + * is not in the range [0, 15]; in that case the return value is always false. + * + * You can assume that LZMA_CHECK_NONE and LZMA_CHECK_CRC32 are always + * supported (even if liblzma is built with limited features). + */ +extern LZMA_API(lzma_bool) lzma_check_is_supported(lzma_check check) + lzma_nothrow lzma_attr_const; + + +/** + * \brief Get the size of the Check field with the given Check ID + * + * Although not all Check IDs have a check algorithm associated, the size of + * every Check is already frozen. This function returns the size (in bytes) of + * the Check field with the specified Check ID. The values are: + * { 0, 4, 4, 4, 8, 8, 8, 16, 16, 16, 32, 32, 32, 64, 64, 64 } + * + * If the argument is not in the range [0, 15], UINT32_MAX is returned. + */ +extern LZMA_API(uint32_t) lzma_check_size(lzma_check check) + lzma_nothrow lzma_attr_const; + + +/** + * \brief Maximum size of a Check field + */ +#define LZMA_CHECK_SIZE_MAX 64 + + +/** + * \brief Calculate CRC32 + * + * Calculate CRC32 using the polynomial from the IEEE 802.3 standard. + * + * \param buf Pointer to the input buffer + * \param size Size of the input buffer + * \param crc Previously returned CRC value. This is used to + * calculate the CRC of a big buffer in smaller chunks. + * Set to zero when starting a new calculation. + * + * \return Updated CRC value, which can be passed to this function + * again to continue CRC calculation. + */ +extern LZMA_API(uint32_t) lzma_crc32( + const uint8_t *buf, size_t size, uint32_t crc) + lzma_nothrow lzma_attr_pure; + + +/** + * \brief Calculate CRC64 + * + * Calculate CRC64 using the polynomial from the ECMA-182 standard. + * + * This function is used similarly to lzma_crc32(). See its documentation. + */ +extern LZMA_API(uint64_t) lzma_crc64( + const uint8_t *buf, size_t size, uint64_t crc) + lzma_nothrow lzma_attr_pure; + + +/* + * SHA-256 functions are currently not exported to public API. + * Contact Lasse Collin if you think it should be. + */ + + +/** + * \brief Get the type of the integrity check + * + * This function can be called only immediately after lzma_code() has + * returned LZMA_NO_CHECK, LZMA_UNSUPPORTED_CHECK, or LZMA_GET_CHECK. + * Calling this function in any other situation has undefined behavior. + */ +extern LZMA_API(lzma_check) lzma_get_check(const lzma_stream *strm) + lzma_nothrow; diff --git a/dependencies/cmliblzma/liblzma/api/lzma/container.h b/dependencies/cmliblzma/liblzma/api/lzma/container.h new file mode 100644 index 0000000..9fbf4df --- /dev/null +++ b/dependencies/cmliblzma/liblzma/api/lzma/container.h @@ -0,0 +1,632 @@ +/** + * \file lzma/container.h + * \brief File formats + */ + +/* + * Author: Lasse Collin + * + * This file has been put into the public domain. + * You can do whatever you want with this file. + * + * See ../lzma.h for information about liblzma as a whole. + */ + +#ifndef LZMA_H_INTERNAL +# error Never include this file directly. Use instead. +#endif + + +/************ + * Encoding * + ************/ + +/** + * \brief Default compression preset + * + * It's not straightforward to recommend a default preset, because in some + * cases keeping the resource usage relatively low is more important that + * getting the maximum compression ratio. + */ +#define LZMA_PRESET_DEFAULT UINT32_C(6) + + +/** + * \brief Mask for preset level + * + * This is useful only if you need to extract the level from the preset + * variable. That should be rare. + */ +#define LZMA_PRESET_LEVEL_MASK UINT32_C(0x1F) + + +/* + * Preset flags + * + * Currently only one flag is defined. + */ + +/** + * \brief Extreme compression preset + * + * This flag modifies the preset to make the encoding significantly slower + * while improving the compression ratio only marginally. This is useful + * when you don't mind wasting time to get as small result as possible. + * + * This flag doesn't affect the memory usage requirements of the decoder (at + * least not significantly). The memory usage of the encoder may be increased + * a little but only at the lowest preset levels (0-3). + */ +#define LZMA_PRESET_EXTREME (UINT32_C(1) << 31) + + +/** + * \brief Multithreading options + */ +typedef struct { + /** + * \brief Flags + * + * Set this to zero if no flags are wanted. + * + * No flags are currently supported. + */ + uint32_t flags; + + /** + * \brief Number of worker threads to use + */ + uint32_t threads; + + /** + * \brief Maximum uncompressed size of a Block + * + * The encoder will start a new .xz Block every block_size bytes. + * Using LZMA_FULL_FLUSH or LZMA_FULL_BARRIER with lzma_code() + * the caller may tell liblzma to start a new Block earlier. + * + * With LZMA2, a recommended block size is 2-4 times the LZMA2 + * dictionary size. With very small dictionaries, it is recommended + * to use at least 1 MiB block size for good compression ratio, even + * if this is more than four times the dictionary size. Note that + * these are only recommendations for typical use cases; feel free + * to use other values. Just keep in mind that using a block size + * less than the LZMA2 dictionary size is waste of RAM. + * + * Set this to 0 to let liblzma choose the block size depending + * on the compression options. For LZMA2 it will be 3*dict_size + * or 1 MiB, whichever is more. + * + * For each thread, about 3 * block_size bytes of memory will be + * allocated. This may change in later liblzma versions. If so, + * the memory usage will probably be reduced, not increased. + */ + uint64_t block_size; + + /** + * \brief Timeout to allow lzma_code() to return early + * + * Multithreading can make liblzma to consume input and produce + * output in a very bursty way: it may first read a lot of input + * to fill internal buffers, then no input or output occurs for + * a while. + * + * In single-threaded mode, lzma_code() won't return until it has + * either consumed all the input or filled the output buffer. If + * this is done in multithreaded mode, it may cause a call + * lzma_code() to take even tens of seconds, which isn't acceptable + * in all applications. + * + * To avoid very long blocking times in lzma_code(), a timeout + * (in milliseconds) may be set here. If lzma_code() would block + * longer than this number of milliseconds, it will return with + * LZMA_OK. Reasonable values are 100 ms or more. The xz command + * line tool uses 300 ms. + * + * If long blocking times are fine for you, set timeout to a special + * value of 0, which will disable the timeout mechanism and will make + * lzma_code() block until all the input is consumed or the output + * buffer has been filled. + * + * \note Even with a timeout, lzma_code() might sometimes take + * somewhat long time to return. No timing guarantees + * are made. + */ + uint32_t timeout; + + /** + * \brief Compression preset (level and possible flags) + * + * The preset is set just like with lzma_easy_encoder(). + * The preset is ignored if filters below is non-NULL. + */ + uint32_t preset; + + /** + * \brief Filter chain (alternative to a preset) + * + * If this is NULL, the preset above is used. Otherwise the preset + * is ignored and the filter chain specified here is used. + */ + const lzma_filter *filters; + + /** + * \brief Integrity check type + * + * See check.h for available checks. The xz command line tool + * defaults to LZMA_CHECK_CRC64, which is a good choice if you + * are unsure. + */ + lzma_check check; + + /* + * Reserved space to allow possible future extensions without + * breaking the ABI. You should not touch these, because the names + * of these variables may change. These are and will never be used + * with the currently supported options, so it is safe to leave these + * uninitialized. + */ + lzma_reserved_enum reserved_enum1; + lzma_reserved_enum reserved_enum2; + lzma_reserved_enum reserved_enum3; + uint32_t reserved_int1; + uint32_t reserved_int2; + uint32_t reserved_int3; + uint32_t reserved_int4; + uint64_t reserved_int5; + uint64_t reserved_int6; + uint64_t reserved_int7; + uint64_t reserved_int8; + void *reserved_ptr1; + void *reserved_ptr2; + void *reserved_ptr3; + void *reserved_ptr4; + +} lzma_mt; + + +/** + * \brief Calculate approximate memory usage of easy encoder + * + * This function is a wrapper for lzma_raw_encoder_memusage(). + * + * \param preset Compression preset (level and possible flags) + * + * \return Number of bytes of memory required for the given + * preset when encoding. If an error occurs, for example + * due to unsupported preset, UINT64_MAX is returned. + */ +extern LZMA_API(uint64_t) lzma_easy_encoder_memusage(uint32_t preset) + lzma_nothrow lzma_attr_pure; + + +/** + * \brief Calculate approximate decoder memory usage of a preset + * + * This function is a wrapper for lzma_raw_decoder_memusage(). + * + * \param preset Compression preset (level and possible flags) + * + * \return Number of bytes of memory required to decompress a file + * that was compressed using the given preset. If an error + * occurs, for example due to unsupported preset, UINT64_MAX + * is returned. + */ +extern LZMA_API(uint64_t) lzma_easy_decoder_memusage(uint32_t preset) + lzma_nothrow lzma_attr_pure; + + +/** + * \brief Initialize .xz Stream encoder using a preset number + * + * This function is intended for those who just want to use the basic features + * if liblzma (that is, most developers out there). + * + * \param strm Pointer to lzma_stream that is at least initialized + * with LZMA_STREAM_INIT. + * \param preset Compression preset to use. A preset consist of level + * number and zero or more flags. Usually flags aren't + * used, so preset is simply a number [0, 9] which match + * the options -0 ... -9 of the xz command line tool. + * Additional flags can be be set using bitwise-or with + * the preset level number, e.g. 6 | LZMA_PRESET_EXTREME. + * \param check Integrity check type to use. See check.h for available + * checks. The xz command line tool defaults to + * LZMA_CHECK_CRC64, which is a good choice if you are + * unsure. LZMA_CHECK_CRC32 is good too as long as the + * uncompressed file is not many gigabytes. + * + * \return - LZMA_OK: Initialization succeeded. Use lzma_code() to + * encode your data. + * - LZMA_MEM_ERROR: Memory allocation failed. + * - LZMA_OPTIONS_ERROR: The given compression preset is not + * supported by this build of liblzma. + * - LZMA_UNSUPPORTED_CHECK: The given check type is not + * supported by this liblzma build. + * - LZMA_PROG_ERROR: One or more of the parameters have values + * that will never be valid. For example, strm == NULL. + * + * If initialization fails (return value is not LZMA_OK), all the memory + * allocated for *strm by liblzma is always freed. Thus, there is no need + * to call lzma_end() after failed initialization. + * + * If initialization succeeds, use lzma_code() to do the actual encoding. + * Valid values for `action' (the second argument of lzma_code()) are + * LZMA_RUN, LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, and LZMA_FINISH. In future, + * there may be compression levels or flags that don't support LZMA_SYNC_FLUSH. + */ +extern LZMA_API(lzma_ret) lzma_easy_encoder( + lzma_stream *strm, uint32_t preset, lzma_check check) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Single-call .xz Stream encoding using a preset number + * + * The maximum required output buffer size can be calculated with + * lzma_stream_buffer_bound(). + * + * \param preset Compression preset to use. See the description + * in lzma_easy_encoder(). + * \param check Type of the integrity check to calculate from + * uncompressed data. + * \param allocator lzma_allocator for custom allocator functions. + * Set to NULL to use malloc() and free(). + * \param in Beginning of the input buffer + * \param in_size Size of the input buffer + * \param out Beginning of the output buffer + * \param out_pos The next byte will be written to out[*out_pos]. + * *out_pos is updated only if encoding succeeds. + * \param out_size Size of the out buffer; the first byte into + * which no data is written to is out[out_size]. + * + * \return - LZMA_OK: Encoding was successful. + * - LZMA_BUF_ERROR: Not enough output buffer space. + * - LZMA_UNSUPPORTED_CHECK + * - LZMA_OPTIONS_ERROR + * - LZMA_MEM_ERROR + * - LZMA_DATA_ERROR + * - LZMA_PROG_ERROR + */ +extern LZMA_API(lzma_ret) lzma_easy_buffer_encode( + uint32_t preset, lzma_check check, + const lzma_allocator *allocator, + const uint8_t *in, size_t in_size, + uint8_t *out, size_t *out_pos, size_t out_size) lzma_nothrow; + + +/** + * \brief Initialize .xz Stream encoder using a custom filter chain + * + * \param strm Pointer to properly prepared lzma_stream + * \param filters Array of filters. This must be terminated with + * filters[n].id = LZMA_VLI_UNKNOWN. See filter.h for + * more information. + * \param check Type of the integrity check to calculate from + * uncompressed data. + * + * \return - LZMA_OK: Initialization was successful. + * - LZMA_MEM_ERROR + * - LZMA_UNSUPPORTED_CHECK + * - LZMA_OPTIONS_ERROR + * - LZMA_PROG_ERROR + */ +extern LZMA_API(lzma_ret) lzma_stream_encoder(lzma_stream *strm, + const lzma_filter *filters, lzma_check check) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Calculate approximate memory usage of multithreaded .xz encoder + * + * Since doing the encoding in threaded mode doesn't affect the memory + * requirements of single-threaded decompressor, you can use + * lzma_easy_decoder_memusage(options->preset) or + * lzma_raw_decoder_memusage(options->filters) to calculate + * the decompressor memory requirements. + * + * \param options Compression options + * + * \return Number of bytes of memory required for encoding with the + * given options. If an error occurs, for example due to + * unsupported preset or filter chain, UINT64_MAX is returned. + */ +extern LZMA_API(uint64_t) lzma_stream_encoder_mt_memusage( + const lzma_mt *options) lzma_nothrow lzma_attr_pure; + + +/** + * \brief Initialize multithreaded .xz Stream encoder + * + * This provides the functionality of lzma_easy_encoder() and + * lzma_stream_encoder() as a single function for multithreaded use. + * + * The supported actions for lzma_code() are LZMA_RUN, LZMA_FULL_FLUSH, + * LZMA_FULL_BARRIER, and LZMA_FINISH. Support for LZMA_SYNC_FLUSH might be + * added in the future. + * + * \param strm Pointer to properly prepared lzma_stream + * \param options Pointer to multithreaded compression options + * + * \return - LZMA_OK + * - LZMA_MEM_ERROR + * - LZMA_UNSUPPORTED_CHECK + * - LZMA_OPTIONS_ERROR + * - LZMA_PROG_ERROR + */ +extern LZMA_API(lzma_ret) lzma_stream_encoder_mt( + lzma_stream *strm, const lzma_mt *options) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Initialize .lzma encoder (legacy file format) + * + * The .lzma format is sometimes called the LZMA_Alone format, which is the + * reason for the name of this function. The .lzma format supports only the + * LZMA1 filter. There is no support for integrity checks like CRC32. + * + * Use this function if and only if you need to create files readable by + * legacy LZMA tools such as LZMA Utils 4.32.x. Moving to the .xz format + * is strongly recommended. + * + * The valid action values for lzma_code() are LZMA_RUN and LZMA_FINISH. + * No kind of flushing is supported, because the file format doesn't make + * it possible. + * + * \return - LZMA_OK + * - LZMA_MEM_ERROR + * - LZMA_OPTIONS_ERROR + * - LZMA_PROG_ERROR + */ +extern LZMA_API(lzma_ret) lzma_alone_encoder( + lzma_stream *strm, const lzma_options_lzma *options) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Calculate output buffer size for single-call Stream encoder + * + * When trying to compress uncompressible data, the encoded size will be + * slightly bigger than the input data. This function calculates how much + * output buffer space is required to be sure that lzma_stream_buffer_encode() + * doesn't return LZMA_BUF_ERROR. + * + * The calculated value is not exact, but it is guaranteed to be big enough. + * The actual maximum output space required may be slightly smaller (up to + * about 100 bytes). This should not be a problem in practice. + * + * If the calculated maximum size doesn't fit into size_t or would make the + * Stream grow past LZMA_VLI_MAX (which should never happen in practice), + * zero is returned to indicate the error. + * + * \note The limit calculated by this function applies only to + * single-call encoding. Multi-call encoding may (and probably + * will) have larger maximum expansion when encoding + * uncompressible data. Currently there is no function to + * calculate the maximum expansion of multi-call encoding. + */ +extern LZMA_API(size_t) lzma_stream_buffer_bound(size_t uncompressed_size) + lzma_nothrow; + + +/** + * \brief Single-call .xz Stream encoder + * + * \param filters Array of filters. This must be terminated with + * filters[n].id = LZMA_VLI_UNKNOWN. See filter.h + * for more information. + * \param check Type of the integrity check to calculate from + * uncompressed data. + * \param allocator lzma_allocator for custom allocator functions. + * Set to NULL to use malloc() and free(). + * \param in Beginning of the input buffer + * \param in_size Size of the input buffer + * \param out Beginning of the output buffer + * \param out_pos The next byte will be written to out[*out_pos]. + * *out_pos is updated only if encoding succeeds. + * \param out_size Size of the out buffer; the first byte into + * which no data is written to is out[out_size]. + * + * \return - LZMA_OK: Encoding was successful. + * - LZMA_BUF_ERROR: Not enough output buffer space. + * - LZMA_UNSUPPORTED_CHECK + * - LZMA_OPTIONS_ERROR + * - LZMA_MEM_ERROR + * - LZMA_DATA_ERROR + * - LZMA_PROG_ERROR + */ +extern LZMA_API(lzma_ret) lzma_stream_buffer_encode( + lzma_filter *filters, lzma_check check, + const lzma_allocator *allocator, + const uint8_t *in, size_t in_size, + uint8_t *out, size_t *out_pos, size_t out_size) + lzma_nothrow lzma_attr_warn_unused_result; + + +/************ + * Decoding * + ************/ + +/** + * This flag makes lzma_code() return LZMA_NO_CHECK if the input stream + * being decoded has no integrity check. Note that when used with + * lzma_auto_decoder(), all .lzma files will trigger LZMA_NO_CHECK + * if LZMA_TELL_NO_CHECK is used. + */ +#define LZMA_TELL_NO_CHECK UINT32_C(0x01) + + +/** + * This flag makes lzma_code() return LZMA_UNSUPPORTED_CHECK if the input + * stream has an integrity check, but the type of the integrity check is not + * supported by this liblzma version or build. Such files can still be + * decoded, but the integrity check cannot be verified. + */ +#define LZMA_TELL_UNSUPPORTED_CHECK UINT32_C(0x02) + + +/** + * This flag makes lzma_code() return LZMA_GET_CHECK as soon as the type + * of the integrity check is known. The type can then be got with + * lzma_get_check(). + */ +#define LZMA_TELL_ANY_CHECK UINT32_C(0x04) + + +/** + * This flag makes lzma_code() not calculate and verify the integrity check + * of the compressed data in .xz files. This means that invalid integrity + * check values won't be detected and LZMA_DATA_ERROR won't be returned in + * such cases. + * + * This flag only affects the checks of the compressed data itself; the CRC32 + * values in the .xz headers will still be verified normally. + * + * Don't use this flag unless you know what you are doing. Possible reasons + * to use this flag: + * + * - Trying to recover data from a corrupt .xz file. + * + * - Speeding up decompression, which matters mostly with SHA-256 + * or with files that have compressed extremely well. It's recommended + * to not use this flag for this purpose unless the file integrity is + * verified externally in some other way. + * + * Support for this flag was added in liblzma 5.1.4beta. + */ +#define LZMA_IGNORE_CHECK UINT32_C(0x10) + + +/** + * This flag enables decoding of concatenated files with file formats that + * allow concatenating compressed files as is. From the formats currently + * supported by liblzma, only the .xz format allows concatenated files. + * Concatenated files are not allowed with the legacy .lzma format. + * + * This flag also affects the usage of the `action' argument for lzma_code(). + * When LZMA_CONCATENATED is used, lzma_code() won't return LZMA_STREAM_END + * unless LZMA_FINISH is used as `action'. Thus, the application has to set + * LZMA_FINISH in the same way as it does when encoding. + * + * If LZMA_CONCATENATED is not used, the decoders still accept LZMA_FINISH + * as `action' for lzma_code(), but the usage of LZMA_FINISH isn't required. + */ +#define LZMA_CONCATENATED UINT32_C(0x08) + + +/** + * \brief Initialize .xz Stream decoder + * + * \param strm Pointer to properly prepared lzma_stream + * \param memlimit Memory usage limit as bytes. Use UINT64_MAX + * to effectively disable the limiter. liblzma + * 5.2.3 and earlier don't allow 0 here and return + * LZMA_PROG_ERROR; later versions treat 0 as if 1 + * had been specified. + * \param flags Bitwise-or of zero or more of the decoder flags: + * LZMA_TELL_NO_CHECK, LZMA_TELL_UNSUPPORTED_CHECK, + * LZMA_TELL_ANY_CHECK, LZMA_CONCATENATED + * + * \return - LZMA_OK: Initialization was successful. + * - LZMA_MEM_ERROR: Cannot allocate memory. + * - LZMA_OPTIONS_ERROR: Unsupported flags + * - LZMA_PROG_ERROR + */ +extern LZMA_API(lzma_ret) lzma_stream_decoder( + lzma_stream *strm, uint64_t memlimit, uint32_t flags) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Decode .xz Streams and .lzma files with autodetection + * + * This decoder autodetects between the .xz and .lzma file formats, and + * calls lzma_stream_decoder() or lzma_alone_decoder() once the type + * of the input file has been detected. + * + * \param strm Pointer to properly prepared lzma_stream + * \param memlimit Memory usage limit as bytes. Use UINT64_MAX + * to effectively disable the limiter. liblzma + * 5.2.3 and earlier don't allow 0 here and return + * LZMA_PROG_ERROR; later versions treat 0 as if 1 + * had been specified. + * \param flags Bitwise-or of flags, or zero for no flags. + * + * \return - LZMA_OK: Initialization was successful. + * - LZMA_MEM_ERROR: Cannot allocate memory. + * - LZMA_OPTIONS_ERROR: Unsupported flags + * - LZMA_PROG_ERROR + */ +extern LZMA_API(lzma_ret) lzma_auto_decoder( + lzma_stream *strm, uint64_t memlimit, uint32_t flags) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Initialize .lzma decoder (legacy file format) + * + * \param strm Pointer to properly prepared lzma_stream + * \param memlimit Memory usage limit as bytes. Use UINT64_MAX + * to effectively disable the limiter. liblzma + * 5.2.3 and earlier don't allow 0 here and return + * LZMA_PROG_ERROR; later versions treat 0 as if 1 + * had been specified. + * + * Valid `action' arguments to lzma_code() are LZMA_RUN and LZMA_FINISH. + * There is no need to use LZMA_FINISH, but it's allowed because it may + * simplify certain types of applications. + * + * \return - LZMA_OK + * - LZMA_MEM_ERROR + * - LZMA_PROG_ERROR + */ +extern LZMA_API(lzma_ret) lzma_alone_decoder( + lzma_stream *strm, uint64_t memlimit) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Single-call .xz Stream decoder + * + * \param memlimit Pointer to how much memory the decoder is allowed + * to allocate. The value pointed by this pointer is + * modified if and only if LZMA_MEMLIMIT_ERROR is + * returned. + * \param flags Bitwise-or of zero or more of the decoder flags: + * LZMA_TELL_NO_CHECK, LZMA_TELL_UNSUPPORTED_CHECK, + * LZMA_CONCATENATED. Note that LZMA_TELL_ANY_CHECK + * is not allowed and will return LZMA_PROG_ERROR. + * \param allocator lzma_allocator for custom allocator functions. + * Set to NULL to use malloc() and free(). + * \param in Beginning of the input buffer + * \param in_pos The next byte will be read from in[*in_pos]. + * *in_pos is updated only if decoding succeeds. + * \param in_size Size of the input buffer; the first byte that + * won't be read is in[in_size]. + * \param out Beginning of the output buffer + * \param out_pos The next byte will be written to out[*out_pos]. + * *out_pos is updated only if decoding succeeds. + * \param out_size Size of the out buffer; the first byte into + * which no data is written to is out[out_size]. + * + * \return - LZMA_OK: Decoding was successful. + * - LZMA_FORMAT_ERROR + * - LZMA_OPTIONS_ERROR + * - LZMA_DATA_ERROR + * - LZMA_NO_CHECK: This can be returned only if using + * the LZMA_TELL_NO_CHECK flag. + * - LZMA_UNSUPPORTED_CHECK: This can be returned only if using + * the LZMA_TELL_UNSUPPORTED_CHECK flag. + * - LZMA_MEM_ERROR + * - LZMA_MEMLIMIT_ERROR: Memory usage limit was reached. + * The minimum required memlimit value was stored to *memlimit. + * - LZMA_BUF_ERROR: Output buffer was too small. + * - LZMA_PROG_ERROR + */ +extern LZMA_API(lzma_ret) lzma_stream_buffer_decode( + uint64_t *memlimit, uint32_t flags, + const lzma_allocator *allocator, + const uint8_t *in, size_t *in_pos, size_t in_size, + uint8_t *out, size_t *out_pos, size_t out_size) + lzma_nothrow lzma_attr_warn_unused_result; diff --git a/dependencies/cmliblzma/liblzma/api/lzma/delta.h b/dependencies/cmliblzma/liblzma/api/lzma/delta.h new file mode 100644 index 0000000..592fc4f --- /dev/null +++ b/dependencies/cmliblzma/liblzma/api/lzma/delta.h @@ -0,0 +1,77 @@ +/** + * \file lzma/delta.h + * \brief Delta filter + */ + +/* + * Author: Lasse Collin + * + * This file has been put into the public domain. + * You can do whatever you want with this file. + * + * See ../lzma.h for information about liblzma as a whole. + */ + +#ifndef LZMA_H_INTERNAL +# error Never include this file directly. Use instead. +#endif + + +/** + * \brief Filter ID + * + * Filter ID of the Delta filter. This is used as lzma_filter.id. + */ +#define LZMA_FILTER_DELTA LZMA_VLI_C(0x03) + + +/** + * \brief Type of the delta calculation + * + * Currently only byte-wise delta is supported. Other possible types could + * be, for example, delta of 16/32/64-bit little/big endian integers, but + * these are not currently planned since byte-wise delta is almost as good. + */ +typedef enum { + LZMA_DELTA_TYPE_BYTE +} lzma_delta_type; + + +/** + * \brief Options for the Delta filter + * + * These options are needed by both encoder and decoder. + */ +typedef struct { + /** For now, this must always be LZMA_DELTA_TYPE_BYTE. */ + lzma_delta_type type; + + /** + * \brief Delta distance + * + * With the only currently supported type, LZMA_DELTA_TYPE_BYTE, + * the distance is as bytes. + * + * Examples: + * - 16-bit stereo audio: distance = 4 bytes + * - 24-bit RGB image data: distance = 3 bytes + */ + uint32_t dist; +# define LZMA_DELTA_DIST_MIN 1 +# define LZMA_DELTA_DIST_MAX 256 + + /* + * Reserved space to allow possible future extensions without + * breaking the ABI. You should not touch these, because the names + * of these variables may change. These are and will never be used + * when type is LZMA_DELTA_TYPE_BYTE, so it is safe to leave these + * uninitialized. + */ + uint32_t reserved_int1; + uint32_t reserved_int2; + uint32_t reserved_int3; + uint32_t reserved_int4; + void *reserved_ptr1; + void *reserved_ptr2; + +} lzma_options_delta; diff --git a/dependencies/cmliblzma/liblzma/api/lzma/filter.h b/dependencies/cmliblzma/liblzma/api/lzma/filter.h new file mode 100644 index 0000000..4e78752 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/api/lzma/filter.h @@ -0,0 +1,425 @@ +/** + * \file lzma/filter.h + * \brief Common filter related types and functions + */ + +/* + * Author: Lasse Collin + * + * This file has been put into the public domain. + * You can do whatever you want with this file. + * + * See ../lzma.h for information about liblzma as a whole. + */ + +#ifndef LZMA_H_INTERNAL +# error Never include this file directly. Use instead. +#endif + + +/** + * \brief Maximum number of filters in a chain + * + * A filter chain can have 1-4 filters, of which three are allowed to change + * the size of the data. Usually only one or two filters are needed. + */ +#define LZMA_FILTERS_MAX 4 + + +/** + * \brief Filter options + * + * This structure is used to pass Filter ID and a pointer filter's + * options to liblzma. A few functions work with a single lzma_filter + * structure, while most functions expect a filter chain. + * + * A filter chain is indicated with an array of lzma_filter structures. + * The array is terminated with .id = LZMA_VLI_UNKNOWN. Thus, the filter + * array must have LZMA_FILTERS_MAX + 1 elements (that is, five) to + * be able to hold any arbitrary filter chain. This is important when + * using lzma_block_header_decode() from block.h, because too small + * array would make liblzma write past the end of the filters array. + */ +typedef struct { + /** + * \brief Filter ID + * + * Use constants whose name begin with `LZMA_FILTER_' to specify + * different filters. In an array of lzma_filter structures, use + * LZMA_VLI_UNKNOWN to indicate end of filters. + * + * \note This is not an enum, because on some systems enums + * cannot be 64-bit. + */ + lzma_vli id; + + /** + * \brief Pointer to filter-specific options structure + * + * If the filter doesn't need options, set this to NULL. If id is + * set to LZMA_VLI_UNKNOWN, options is ignored, and thus + * doesn't need be initialized. + */ + void *options; + +} lzma_filter; + + +/** + * \brief Test if the given Filter ID is supported for encoding + * + * Return true if the give Filter ID is supported for encoding by this + * liblzma build. Otherwise false is returned. + * + * There is no way to list which filters are available in this particular + * liblzma version and build. It would be useless, because the application + * couldn't know what kind of options the filter would need. + */ +extern LZMA_API(lzma_bool) lzma_filter_encoder_is_supported(lzma_vli id) + lzma_nothrow lzma_attr_const; + + +/** + * \brief Test if the given Filter ID is supported for decoding + * + * Return true if the give Filter ID is supported for decoding by this + * liblzma build. Otherwise false is returned. + */ +extern LZMA_API(lzma_bool) lzma_filter_decoder_is_supported(lzma_vli id) + lzma_nothrow lzma_attr_const; + + +/** + * \brief Copy the filters array + * + * Copy the Filter IDs and filter-specific options from src to dest. + * Up to LZMA_FILTERS_MAX filters are copied, plus the terminating + * .id == LZMA_VLI_UNKNOWN. Thus, dest should have at least + * LZMA_FILTERS_MAX + 1 elements space unless the caller knows that + * src is smaller than that. + * + * Unless the filter-specific options is NULL, the Filter ID has to be + * supported by liblzma, because liblzma needs to know the size of every + * filter-specific options structure. The filter-specific options are not + * validated. If options is NULL, any unsupported Filter IDs are copied + * without returning an error. + * + * Old filter-specific options in dest are not freed, so dest doesn't + * need to be initialized by the caller in any way. + * + * If an error occurs, memory possibly already allocated by this function + * is always freed. + * + * \return - LZMA_OK + * - LZMA_MEM_ERROR + * - LZMA_OPTIONS_ERROR: Unsupported Filter ID and its options + * is not NULL. + * - LZMA_PROG_ERROR: src or dest is NULL. + */ +extern LZMA_API(lzma_ret) lzma_filters_copy( + const lzma_filter *src, lzma_filter *dest, + const lzma_allocator *allocator) lzma_nothrow; + + +/** + * \brief Calculate approximate memory requirements for raw encoder + * + * This function can be used to calculate the memory requirements for + * Block and Stream encoders too because Block and Stream encoders don't + * need significantly more memory than raw encoder. + * + * \param filters Array of filters terminated with + * .id == LZMA_VLI_UNKNOWN. + * + * \return Number of bytes of memory required for the given + * filter chain when encoding. If an error occurs, + * for example due to unsupported filter chain, + * UINT64_MAX is returned. + */ +extern LZMA_API(uint64_t) lzma_raw_encoder_memusage(const lzma_filter *filters) + lzma_nothrow lzma_attr_pure; + + +/** + * \brief Calculate approximate memory requirements for raw decoder + * + * This function can be used to calculate the memory requirements for + * Block and Stream decoders too because Block and Stream decoders don't + * need significantly more memory than raw decoder. + * + * \param filters Array of filters terminated with + * .id == LZMA_VLI_UNKNOWN. + * + * \return Number of bytes of memory required for the given + * filter chain when decoding. If an error occurs, + * for example due to unsupported filter chain, + * UINT64_MAX is returned. + */ +extern LZMA_API(uint64_t) lzma_raw_decoder_memusage(const lzma_filter *filters) + lzma_nothrow lzma_attr_pure; + + +/** + * \brief Initialize raw encoder + * + * This function may be useful when implementing custom file formats. + * + * \param strm Pointer to properly prepared lzma_stream + * \param filters Array of lzma_filter structures. The end of the + * array must be marked with .id = LZMA_VLI_UNKNOWN. + * + * The `action' with lzma_code() can be LZMA_RUN, LZMA_SYNC_FLUSH (if the + * filter chain supports it), or LZMA_FINISH. + * + * \return - LZMA_OK + * - LZMA_MEM_ERROR + * - LZMA_OPTIONS_ERROR + * - LZMA_PROG_ERROR + */ +extern LZMA_API(lzma_ret) lzma_raw_encoder( + lzma_stream *strm, const lzma_filter *filters) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Initialize raw decoder + * + * The initialization of raw decoder goes similarly to raw encoder. + * + * The `action' with lzma_code() can be LZMA_RUN or LZMA_FINISH. Using + * LZMA_FINISH is not required, it is supported just for convenience. + * + * \return - LZMA_OK + * - LZMA_MEM_ERROR + * - LZMA_OPTIONS_ERROR + * - LZMA_PROG_ERROR + */ +extern LZMA_API(lzma_ret) lzma_raw_decoder( + lzma_stream *strm, const lzma_filter *filters) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Update the filter chain in the encoder + * + * This function is for advanced users only. This function has two slightly + * different purposes: + * + * - After LZMA_FULL_FLUSH when using Stream encoder: Set a new filter + * chain, which will be used starting from the next Block. + * + * - After LZMA_SYNC_FLUSH using Raw, Block, or Stream encoder: Change + * the filter-specific options in the middle of encoding. The actual + * filters in the chain (Filter IDs) cannot be changed. In the future, + * it might become possible to change the filter options without + * using LZMA_SYNC_FLUSH. + * + * While rarely useful, this function may be called also when no data has + * been compressed yet. In that case, this function will behave as if + * LZMA_FULL_FLUSH (Stream encoder) or LZMA_SYNC_FLUSH (Raw or Block + * encoder) had been used right before calling this function. + * + * \return - LZMA_OK + * - LZMA_MEM_ERROR + * - LZMA_MEMLIMIT_ERROR + * - LZMA_OPTIONS_ERROR + * - LZMA_PROG_ERROR + */ +extern LZMA_API(lzma_ret) lzma_filters_update( + lzma_stream *strm, const lzma_filter *filters) lzma_nothrow; + + +/** + * \brief Single-call raw encoder + * + * \param filters Array of lzma_filter structures. The end of the + * array must be marked with .id = LZMA_VLI_UNKNOWN. + * \param allocator lzma_allocator for custom allocator functions. + * Set to NULL to use malloc() and free(). + * \param in Beginning of the input buffer + * \param in_size Size of the input buffer + * \param out Beginning of the output buffer + * \param out_pos The next byte will be written to out[*out_pos]. + * *out_pos is updated only if encoding succeeds. + * \param out_size Size of the out buffer; the first byte into + * which no data is written to is out[out_size]. + * + * \return - LZMA_OK: Encoding was successful. + * - LZMA_BUF_ERROR: Not enough output buffer space. + * - LZMA_OPTIONS_ERROR + * - LZMA_MEM_ERROR + * - LZMA_DATA_ERROR + * - LZMA_PROG_ERROR + * + * \note There is no function to calculate how big output buffer + * would surely be big enough. (lzma_stream_buffer_bound() + * works only for lzma_stream_buffer_encode(); raw encoder + * won't necessarily meet that bound.) + */ +extern LZMA_API(lzma_ret) lzma_raw_buffer_encode( + const lzma_filter *filters, const lzma_allocator *allocator, + const uint8_t *in, size_t in_size, uint8_t *out, + size_t *out_pos, size_t out_size) lzma_nothrow; + + +/** + * \brief Single-call raw decoder + * + * \param filters Array of lzma_filter structures. The end of the + * array must be marked with .id = LZMA_VLI_UNKNOWN. + * \param allocator lzma_allocator for custom allocator functions. + * Set to NULL to use malloc() and free(). + * \param in Beginning of the input buffer + * \param in_pos The next byte will be read from in[*in_pos]. + * *in_pos is updated only if decoding succeeds. + * \param in_size Size of the input buffer; the first byte that + * won't be read is in[in_size]. + * \param out Beginning of the output buffer + * \param out_pos The next byte will be written to out[*out_pos]. + * *out_pos is updated only if encoding succeeds. + * \param out_size Size of the out buffer; the first byte into + * which no data is written to is out[out_size]. + */ +extern LZMA_API(lzma_ret) lzma_raw_buffer_decode( + const lzma_filter *filters, const lzma_allocator *allocator, + const uint8_t *in, size_t *in_pos, size_t in_size, + uint8_t *out, size_t *out_pos, size_t out_size) lzma_nothrow; + + +/** + * \brief Get the size of the Filter Properties field + * + * This function may be useful when implementing custom file formats + * using the raw encoder and decoder. + * + * \param size Pointer to uint32_t to hold the size of the properties + * \param filter Filter ID and options (the size of the properties may + * vary depending on the options) + * + * \return - LZMA_OK + * - LZMA_OPTIONS_ERROR + * - LZMA_PROG_ERROR + * + * \note This function validates the Filter ID, but does not + * necessarily validate the options. Thus, it is possible + * that this returns LZMA_OK while the following call to + * lzma_properties_encode() returns LZMA_OPTIONS_ERROR. + */ +extern LZMA_API(lzma_ret) lzma_properties_size( + uint32_t *size, const lzma_filter *filter) lzma_nothrow; + + +/** + * \brief Encode the Filter Properties field + * + * \param filter Filter ID and options + * \param props Buffer to hold the encoded options. The size of + * buffer must have been already determined with + * lzma_properties_size(). + * + * \return - LZMA_OK + * - LZMA_OPTIONS_ERROR + * - LZMA_PROG_ERROR + * + * \note Even this function won't validate more options than actually + * necessary. Thus, it is possible that encoding the properties + * succeeds but using the same options to initialize the encoder + * will fail. + * + * \note If lzma_properties_size() indicated that the size + * of the Filter Properties field is zero, calling + * lzma_properties_encode() is not required, but it + * won't do any harm either. + */ +extern LZMA_API(lzma_ret) lzma_properties_encode( + const lzma_filter *filter, uint8_t *props) lzma_nothrow; + + +/** + * \brief Decode the Filter Properties field + * + * \param filter filter->id must have been set to the correct + * Filter ID. filter->options doesn't need to be + * initialized (it's not freed by this function). The + * decoded options will be stored to filter->options. + * filter->options is set to NULL if there are no + * properties or if an error occurs. + * \param allocator Custom memory allocator used to allocate the + * options. Set to NULL to use the default malloc(), + * and in case of an error, also free(). + * \param props Input buffer containing the properties. + * \param props_size Size of the properties. This must be the exact + * size; giving too much or too little input will + * return LZMA_OPTIONS_ERROR. + * + * \return - LZMA_OK + * - LZMA_OPTIONS_ERROR + * - LZMA_MEM_ERROR + */ +extern LZMA_API(lzma_ret) lzma_properties_decode( + lzma_filter *filter, const lzma_allocator *allocator, + const uint8_t *props, size_t props_size) lzma_nothrow; + + +/** + * \brief Calculate encoded size of a Filter Flags field + * + * Knowing the size of Filter Flags is useful to know when allocating + * memory to hold the encoded Filter Flags. + * + * \param size Pointer to integer to hold the calculated size + * \param filter Filter ID and associated options whose encoded + * size is to be calculated + * + * \return - LZMA_OK: *size set successfully. Note that this doesn't + * guarantee that filter->options is valid, thus + * lzma_filter_flags_encode() may still fail. + * - LZMA_OPTIONS_ERROR: Unknown Filter ID or unsupported options. + * - LZMA_PROG_ERROR: Invalid options + * + * \note If you need to calculate size of List of Filter Flags, + * you need to loop over every lzma_filter entry. + */ +extern LZMA_API(lzma_ret) lzma_filter_flags_size( + uint32_t *size, const lzma_filter *filter) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Encode Filter Flags into given buffer + * + * In contrast to some functions, this doesn't allocate the needed buffer. + * This is due to how this function is used internally by liblzma. + * + * \param filter Filter ID and options to be encoded + * \param out Beginning of the output buffer + * \param out_pos out[*out_pos] is the next write position. This + * is updated by the encoder. + * \param out_size out[out_size] is the first byte to not write. + * + * \return - LZMA_OK: Encoding was successful. + * - LZMA_OPTIONS_ERROR: Invalid or unsupported options. + * - LZMA_PROG_ERROR: Invalid options or not enough output + * buffer space (you should have checked it with + * lzma_filter_flags_size()). + */ +extern LZMA_API(lzma_ret) lzma_filter_flags_encode(const lzma_filter *filter, + uint8_t *out, size_t *out_pos, size_t out_size) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Decode Filter Flags from given buffer + * + * The decoded result is stored into *filter. The old value of + * filter->options is not free()d. + * + * \return - LZMA_OK + * - LZMA_OPTIONS_ERROR + * - LZMA_MEM_ERROR + * - LZMA_PROG_ERROR + */ +extern LZMA_API(lzma_ret) lzma_filter_flags_decode( + lzma_filter *filter, const lzma_allocator *allocator, + const uint8_t *in, size_t *in_pos, size_t in_size) + lzma_nothrow lzma_attr_warn_unused_result; diff --git a/dependencies/cmliblzma/liblzma/api/lzma/hardware.h b/dependencies/cmliblzma/liblzma/api/lzma/hardware.h new file mode 100644 index 0000000..5321d9a --- /dev/null +++ b/dependencies/cmliblzma/liblzma/api/lzma/hardware.h @@ -0,0 +1,64 @@ +/** + * \file lzma/hardware.h + * \brief Hardware information + * + * Since liblzma can consume a lot of system resources, it also provides + * ways to limit the resource usage. Applications linking against liblzma + * need to do the actual decisions how much resources to let liblzma to use. + * To ease making these decisions, liblzma provides functions to find out + * the relevant capabilities of the underlaying hardware. Currently there + * is only a function to find out the amount of RAM, but in the future there + * will be also a function to detect how many concurrent threads the system + * can run. + * + * \note On some operating systems, these function may temporarily + * load a shared library or open file descriptor(s) to find out + * the requested hardware information. Unless the application + * assumes that specific file descriptors are not touched by + * other threads, this should have no effect on thread safety. + * Possible operations involving file descriptors will restart + * the syscalls if they return EINTR. + */ + +/* + * Author: Lasse Collin + * + * This file has been put into the public domain. + * You can do whatever you want with this file. + * + * See ../lzma.h for information about liblzma as a whole. + */ + +#ifndef LZMA_H_INTERNAL +# error Never include this file directly. Use instead. +#endif + + +/** + * \brief Get the total amount of physical memory (RAM) in bytes + * + * This function may be useful when determining a reasonable memory + * usage limit for decompressing or how much memory it is OK to use + * for compressing. + * + * \return On success, the total amount of physical memory in bytes + * is returned. If the amount of RAM cannot be determined, + * zero is returned. This can happen if an error occurs + * or if there is no code in liblzma to detect the amount + * of RAM on the specific operating system. + */ +extern LZMA_API(uint64_t) lzma_physmem(void) lzma_nothrow; + + +/** + * \brief Get the number of processor cores or threads + * + * This function may be useful when determining how many threads to use. + * If the hardware supports more than one thread per CPU core, the number + * of hardware threads is returned if that information is available. + * + * \brief On success, the number of available CPU threads or cores is + * returned. If this information isn't available or an error + * occurs, zero is returned. + */ +extern LZMA_API(uint32_t) lzma_cputhreads(void) lzma_nothrow; diff --git a/dependencies/cmliblzma/liblzma/api/lzma/index.h b/dependencies/cmliblzma/liblzma/api/lzma/index.h new file mode 100644 index 0000000..3dac6fb --- /dev/null +++ b/dependencies/cmliblzma/liblzma/api/lzma/index.h @@ -0,0 +1,686 @@ +/** + * \file lzma/index.h + * \brief Handling of .xz Index and related information + */ + +/* + * Author: Lasse Collin + * + * This file has been put into the public domain. + * You can do whatever you want with this file. + * + * See ../lzma.h for information about liblzma as a whole. + */ + +#ifndef LZMA_H_INTERNAL +# error Never include this file directly. Use instead. +#endif + + +/** + * \brief Opaque data type to hold the Index(es) and other information + * + * lzma_index often holds just one .xz Index and possibly the Stream Flags + * of the same Stream and size of the Stream Padding field. However, + * multiple lzma_indexes can be concatenated with lzma_index_cat() and then + * there may be information about multiple Streams in the same lzma_index. + * + * Notes about thread safety: Only one thread may modify lzma_index at + * a time. All functions that take non-const pointer to lzma_index + * modify it. As long as no thread is modifying the lzma_index, getting + * information from the same lzma_index can be done from multiple threads + * at the same time with functions that take a const pointer to + * lzma_index or use lzma_index_iter. The same iterator must be used + * only by one thread at a time, of course, but there can be as many + * iterators for the same lzma_index as needed. + */ +typedef struct lzma_index_s lzma_index; + + +/** + * \brief Iterator to get information about Blocks and Streams + */ +typedef struct { + struct { + /** + * \brief Pointer to Stream Flags + * + * This is NULL if Stream Flags have not been set for + * this Stream with lzma_index_stream_flags(). + */ + const lzma_stream_flags *flags; + + const void *reserved_ptr1; + const void *reserved_ptr2; + const void *reserved_ptr3; + + /** + * \brief Stream number in the lzma_index + * + * The first Stream is 1. + */ + lzma_vli number; + + /** + * \brief Number of Blocks in the Stream + * + * If this is zero, the block structure below has + * undefined values. + */ + lzma_vli block_count; + + /** + * \brief Compressed start offset of this Stream + * + * The offset is relative to the beginning of the lzma_index + * (i.e. usually the beginning of the .xz file). + */ + lzma_vli compressed_offset; + + /** + * \brief Uncompressed start offset of this Stream + * + * The offset is relative to the beginning of the lzma_index + * (i.e. usually the beginning of the .xz file). + */ + lzma_vli uncompressed_offset; + + /** + * \brief Compressed size of this Stream + * + * This includes all headers except the possible + * Stream Padding after this Stream. + */ + lzma_vli compressed_size; + + /** + * \brief Uncompressed size of this Stream + */ + lzma_vli uncompressed_size; + + /** + * \brief Size of Stream Padding after this Stream + * + * If it hasn't been set with lzma_index_stream_padding(), + * this defaults to zero. Stream Padding is always + * a multiple of four bytes. + */ + lzma_vli padding; + + lzma_vli reserved_vli1; + lzma_vli reserved_vli2; + lzma_vli reserved_vli3; + lzma_vli reserved_vli4; + } stream; + + struct { + /** + * \brief Block number in the file + * + * The first Block is 1. + */ + lzma_vli number_in_file; + + /** + * \brief Compressed start offset of this Block + * + * This offset is relative to the beginning of the + * lzma_index (i.e. usually the beginning of the .xz file). + * Normally this is where you should seek in the .xz file + * to start decompressing this Block. + */ + lzma_vli compressed_file_offset; + + /** + * \brief Uncompressed start offset of this Block + * + * This offset is relative to the beginning of the lzma_index + * (i.e. usually the beginning of the .xz file). + * + * When doing random-access reading, it is possible that + * the target offset is not exactly at Block boundary. One + * will need to compare the target offset against + * uncompressed_file_offset or uncompressed_stream_offset, + * and possibly decode and throw away some amount of data + * before reaching the target offset. + */ + lzma_vli uncompressed_file_offset; + + /** + * \brief Block number in this Stream + * + * The first Block is 1. + */ + lzma_vli number_in_stream; + + /** + * \brief Compressed start offset of this Block + * + * This offset is relative to the beginning of the Stream + * containing this Block. + */ + lzma_vli compressed_stream_offset; + + /** + * \brief Uncompressed start offset of this Block + * + * This offset is relative to the beginning of the Stream + * containing this Block. + */ + lzma_vli uncompressed_stream_offset; + + /** + * \brief Uncompressed size of this Block + * + * You should pass this to the Block decoder if you will + * decode this Block. It will allow the Block decoder to + * validate the uncompressed size. + */ + lzma_vli uncompressed_size; + + /** + * \brief Unpadded size of this Block + * + * You should pass this to the Block decoder if you will + * decode this Block. It will allow the Block decoder to + * validate the unpadded size. + */ + lzma_vli unpadded_size; + + /** + * \brief Total compressed size + * + * This includes all headers and padding in this Block. + * This is useful if you need to know how many bytes + * the Block decoder will actually read. + */ + lzma_vli total_size; + + lzma_vli reserved_vli1; + lzma_vli reserved_vli2; + lzma_vli reserved_vli3; + lzma_vli reserved_vli4; + + const void *reserved_ptr1; + const void *reserved_ptr2; + const void *reserved_ptr3; + const void *reserved_ptr4; + } block; + + /* + * Internal data which is used to store the state of the iterator. + * The exact format may vary between liblzma versions, so don't + * touch these in any way. + */ + union { + const void *p; + size_t s; + lzma_vli v; + } internal[6]; +} lzma_index_iter; + + +/** + * \brief Operation mode for lzma_index_iter_next() + */ +typedef enum { + LZMA_INDEX_ITER_ANY = 0, + /**< + * \brief Get the next Block or Stream + * + * Go to the next Block if the current Stream has at least + * one Block left. Otherwise go to the next Stream even if + * it has no Blocks. If the Stream has no Blocks + * (lzma_index_iter.stream.block_count == 0), + * lzma_index_iter.block will have undefined values. + */ + + LZMA_INDEX_ITER_STREAM = 1, + /**< + * \brief Get the next Stream + * + * Go to the next Stream even if the current Stream has + * unread Blocks left. If the next Stream has at least one + * Block, the iterator will point to the first Block. + * If there are no Blocks, lzma_index_iter.block will have + * undefined values. + */ + + LZMA_INDEX_ITER_BLOCK = 2, + /**< + * \brief Get the next Block + * + * Go to the next Block if the current Stream has at least + * one Block left. If the current Stream has no Blocks left, + * the next Stream with at least one Block is located and + * the iterator will be made to point to the first Block of + * that Stream. + */ + + LZMA_INDEX_ITER_NONEMPTY_BLOCK = 3 + /**< + * \brief Get the next non-empty Block + * + * This is like LZMA_INDEX_ITER_BLOCK except that it will + * skip Blocks whose Uncompressed Size is zero. + */ + +} lzma_index_iter_mode; + + +/** + * \brief Calculate memory usage of lzma_index + * + * On disk, the size of the Index field depends on both the number of Records + * stored and how big values the Records store (due to variable-length integer + * encoding). When the Index is kept in lzma_index structure, the memory usage + * depends only on the number of Records/Blocks stored in the Index(es), and + * in case of concatenated lzma_indexes, the number of Streams. The size in + * RAM is almost always significantly bigger than in the encoded form on disk. + * + * This function calculates an approximate amount of memory needed hold + * the given number of Streams and Blocks in lzma_index structure. This + * value may vary between CPU architectures and also between liblzma versions + * if the internal implementation is modified. + */ +extern LZMA_API(uint64_t) lzma_index_memusage( + lzma_vli streams, lzma_vli blocks) lzma_nothrow; + + +/** + * \brief Calculate the memory usage of an existing lzma_index + * + * This is a shorthand for lzma_index_memusage(lzma_index_stream_count(i), + * lzma_index_block_count(i)). + */ +extern LZMA_API(uint64_t) lzma_index_memused(const lzma_index *i) + lzma_nothrow; + + +/** + * \brief Allocate and initialize a new lzma_index structure + * + * \return On success, a pointer to an empty initialized lzma_index is + * returned. If allocation fails, NULL is returned. + */ +extern LZMA_API(lzma_index *) lzma_index_init(const lzma_allocator *allocator) + lzma_nothrow; + + +/** + * \brief Deallocate lzma_index + * + * If i is NULL, this does nothing. + */ +extern LZMA_API(void) lzma_index_end( + lzma_index *i, const lzma_allocator *allocator) lzma_nothrow; + + +/** + * \brief Add a new Block to lzma_index + * + * \param i Pointer to a lzma_index structure + * \param allocator Pointer to lzma_allocator, or NULL to + * use malloc() + * \param unpadded_size Unpadded Size of a Block. This can be + * calculated with lzma_block_unpadded_size() + * after encoding or decoding the Block. + * \param uncompressed_size Uncompressed Size of a Block. This can be + * taken directly from lzma_block structure + * after encoding or decoding the Block. + * + * Appending a new Block does not invalidate iterators. For example, + * if an iterator was pointing to the end of the lzma_index, after + * lzma_index_append() it is possible to read the next Block with + * an existing iterator. + * + * \return - LZMA_OK + * - LZMA_MEM_ERROR + * - LZMA_DATA_ERROR: Compressed or uncompressed size of the + * Stream or size of the Index field would grow too big. + * - LZMA_PROG_ERROR + */ +extern LZMA_API(lzma_ret) lzma_index_append( + lzma_index *i, const lzma_allocator *allocator, + lzma_vli unpadded_size, lzma_vli uncompressed_size) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Set the Stream Flags + * + * Set the Stream Flags of the last (and typically the only) Stream + * in lzma_index. This can be useful when reading information from the + * lzma_index, because to decode Blocks, knowing the integrity check type + * is needed. + * + * The given Stream Flags are copied into internal preallocated structure + * in the lzma_index, thus the caller doesn't need to keep the *stream_flags + * available after calling this function. + * + * \return - LZMA_OK + * - LZMA_OPTIONS_ERROR: Unsupported stream_flags->version. + * - LZMA_PROG_ERROR + */ +extern LZMA_API(lzma_ret) lzma_index_stream_flags( + lzma_index *i, const lzma_stream_flags *stream_flags) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Get the types of integrity Checks + * + * If lzma_index_stream_flags() is used to set the Stream Flags for + * every Stream, lzma_index_checks() can be used to get a bitmask to + * indicate which Check types have been used. It can be useful e.g. if + * showing the Check types to the user. + * + * The bitmask is 1 << check_id, e.g. CRC32 is 1 << 1 and SHA-256 is 1 << 10. + */ +extern LZMA_API(uint32_t) lzma_index_checks(const lzma_index *i) + lzma_nothrow lzma_attr_pure; + + +/** + * \brief Set the amount of Stream Padding + * + * Set the amount of Stream Padding of the last (and typically the only) + * Stream in the lzma_index. This is needed when planning to do random-access + * reading within multiple concatenated Streams. + * + * By default, the amount of Stream Padding is assumed to be zero bytes. + * + * \return - LZMA_OK + * - LZMA_DATA_ERROR: The file size would grow too big. + * - LZMA_PROG_ERROR + */ +extern LZMA_API(lzma_ret) lzma_index_stream_padding( + lzma_index *i, lzma_vli stream_padding) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Get the number of Streams + */ +extern LZMA_API(lzma_vli) lzma_index_stream_count(const lzma_index *i) + lzma_nothrow lzma_attr_pure; + + +/** + * \brief Get the number of Blocks + * + * This returns the total number of Blocks in lzma_index. To get number + * of Blocks in individual Streams, use lzma_index_iter. + */ +extern LZMA_API(lzma_vli) lzma_index_block_count(const lzma_index *i) + lzma_nothrow lzma_attr_pure; + + +/** + * \brief Get the size of the Index field as bytes + * + * This is needed to verify the Backward Size field in the Stream Footer. + */ +extern LZMA_API(lzma_vli) lzma_index_size(const lzma_index *i) + lzma_nothrow lzma_attr_pure; + + +/** + * \brief Get the total size of the Stream + * + * If multiple lzma_indexes have been combined, this works as if the Blocks + * were in a single Stream. This is useful if you are going to combine + * Blocks from multiple Streams into a single new Stream. + */ +extern LZMA_API(lzma_vli) lzma_index_stream_size(const lzma_index *i) + lzma_nothrow lzma_attr_pure; + + +/** + * \brief Get the total size of the Blocks + * + * This doesn't include the Stream Header, Stream Footer, Stream Padding, + * or Index fields. + */ +extern LZMA_API(lzma_vli) lzma_index_total_size(const lzma_index *i) + lzma_nothrow lzma_attr_pure; + + +/** + * \brief Get the total size of the file + * + * When no lzma_indexes have been combined with lzma_index_cat() and there is + * no Stream Padding, this function is identical to lzma_index_stream_size(). + * If multiple lzma_indexes have been combined, this includes also the headers + * of each separate Stream and the possible Stream Padding fields. + */ +extern LZMA_API(lzma_vli) lzma_index_file_size(const lzma_index *i) + lzma_nothrow lzma_attr_pure; + + +/** + * \brief Get the uncompressed size of the file + */ +extern LZMA_API(lzma_vli) lzma_index_uncompressed_size(const lzma_index *i) + lzma_nothrow lzma_attr_pure; + + +/** + * \brief Initialize an iterator + * + * \param iter Pointer to a lzma_index_iter structure + * \param i lzma_index to which the iterator will be associated + * + * This function associates the iterator with the given lzma_index, and calls + * lzma_index_iter_rewind() on the iterator. + * + * This function doesn't allocate any memory, thus there is no + * lzma_index_iter_end(). The iterator is valid as long as the + * associated lzma_index is valid, that is, until lzma_index_end() or + * using it as source in lzma_index_cat(). Specifically, lzma_index doesn't + * become invalid if new Blocks are added to it with lzma_index_append() or + * if it is used as the destination in lzma_index_cat(). + * + * It is safe to make copies of an initialized lzma_index_iter, for example, + * to easily restart reading at some particular position. + */ +extern LZMA_API(void) lzma_index_iter_init( + lzma_index_iter *iter, const lzma_index *i) lzma_nothrow; + + +/** + * \brief Rewind the iterator + * + * Rewind the iterator so that next call to lzma_index_iter_next() will + * return the first Block or Stream. + */ +extern LZMA_API(void) lzma_index_iter_rewind(lzma_index_iter *iter) + lzma_nothrow; + + +/** + * \brief Get the next Block or Stream + * + * \param iter Iterator initialized with lzma_index_iter_init() + * \param mode Specify what kind of information the caller wants + * to get. See lzma_index_iter_mode for details. + * + * \return If next Block or Stream matching the mode was found, *iter + * is updated and this function returns false. If no Block or + * Stream matching the mode is found, *iter is not modified + * and this function returns true. If mode is set to an unknown + * value, *iter is not modified and this function returns true. + */ +extern LZMA_API(lzma_bool) lzma_index_iter_next( + lzma_index_iter *iter, lzma_index_iter_mode mode) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Locate a Block + * + * If it is possible to seek in the .xz file, it is possible to parse + * the Index field(s) and use lzma_index_iter_locate() to do random-access + * reading with granularity of Block size. + * + * \param iter Iterator that was earlier initialized with + * lzma_index_iter_init(). + * \param target Uncompressed target offset which the caller would + * like to locate from the Stream + * + * If the target is smaller than the uncompressed size of the Stream (can be + * checked with lzma_index_uncompressed_size()): + * - Information about the Stream and Block containing the requested + * uncompressed offset is stored into *iter. + * - Internal state of the iterator is adjusted so that + * lzma_index_iter_next() can be used to read subsequent Blocks or Streams. + * - This function returns false. + * + * If target is greater than the uncompressed size of the Stream, *iter + * is not modified, and this function returns true. + */ +extern LZMA_API(lzma_bool) lzma_index_iter_locate( + lzma_index_iter *iter, lzma_vli target) lzma_nothrow; + + +/** + * \brief Concatenate lzma_indexes + * + * Concatenating lzma_indexes is useful when doing random-access reading in + * multi-Stream .xz file, or when combining multiple Streams into single + * Stream. + * + * \param dest lzma_index after which src is appended + * \param src lzma_index to be appended after dest. If this + * function succeeds, the memory allocated for src + * is freed or moved to be part of dest, and all + * iterators pointing to src will become invalid. + * \param allocator Custom memory allocator; can be NULL to use + * malloc() and free(). + * + * \return - LZMA_OK: lzma_indexes were concatenated successfully. + * src is now a dangling pointer. + * - LZMA_DATA_ERROR: *dest would grow too big. + * - LZMA_MEM_ERROR + * - LZMA_PROG_ERROR + */ +extern LZMA_API(lzma_ret) lzma_index_cat(lzma_index *dest, lzma_index *src, + const lzma_allocator *allocator) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Duplicate lzma_index + * + * \return A copy of the lzma_index, or NULL if memory allocation failed. + */ +extern LZMA_API(lzma_index *) lzma_index_dup( + const lzma_index *i, const lzma_allocator *allocator) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Initialize .xz Index encoder + * + * \param strm Pointer to properly prepared lzma_stream + * \param i Pointer to lzma_index which should be encoded. + * + * The valid `action' values for lzma_code() are LZMA_RUN and LZMA_FINISH. + * It is enough to use only one of them (you can choose freely). + * + * \return - LZMA_OK: Initialization succeeded, continue with lzma_code(). + * - LZMA_MEM_ERROR + * - LZMA_PROG_ERROR + */ +extern LZMA_API(lzma_ret) lzma_index_encoder( + lzma_stream *strm, const lzma_index *i) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Initialize .xz Index decoder + * + * \param strm Pointer to properly prepared lzma_stream + * \param i The decoded Index will be made available via + * this pointer. Initially this function will + * set *i to NULL (the old value is ignored). If + * decoding succeeds (lzma_code() returns + * LZMA_STREAM_END), *i will be set to point + * to a new lzma_index, which the application + * has to later free with lzma_index_end(). + * \param memlimit How much memory the resulting lzma_index is + * allowed to require. liblzma 5.2.3 and earlier + * don't allow 0 here and return LZMA_PROG_ERROR; + * later versions treat 0 as if 1 had been specified. + * + * Valid `action' arguments to lzma_code() are LZMA_RUN and LZMA_FINISH. + * There is no need to use LZMA_FINISH, but it's allowed because it may + * simplify certain types of applications. + * + * \return - LZMA_OK: Initialization succeeded, continue with lzma_code(). + * - LZMA_MEM_ERROR + * - LZMA_PROG_ERROR + * + * liblzma 5.2.3 and older list also LZMA_MEMLIMIT_ERROR here + * but that error code has never been possible from this + * initialization function. + */ +extern LZMA_API(lzma_ret) lzma_index_decoder( + lzma_stream *strm, lzma_index **i, uint64_t memlimit) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Single-call .xz Index encoder + * + * \param i lzma_index to be encoded + * \param out Beginning of the output buffer + * \param out_pos The next byte will be written to out[*out_pos]. + * *out_pos is updated only if encoding succeeds. + * \param out_size Size of the out buffer; the first byte into + * which no data is written to is out[out_size]. + * + * \return - LZMA_OK: Encoding was successful. + * - LZMA_BUF_ERROR: Output buffer is too small. Use + * lzma_index_size() to find out how much output + * space is needed. + * - LZMA_PROG_ERROR + * + * \note This function doesn't take allocator argument since all + * the internal data is allocated on stack. + */ +extern LZMA_API(lzma_ret) lzma_index_buffer_encode(const lzma_index *i, + uint8_t *out, size_t *out_pos, size_t out_size) lzma_nothrow; + + +/** + * \brief Single-call .xz Index decoder + * + * \param i If decoding succeeds, *i will point to a new + * lzma_index, which the application has to + * later free with lzma_index_end(). If an error + * occurs, *i will be NULL. The old value of *i + * is always ignored and thus doesn't need to be + * initialized by the caller. + * \param memlimit Pointer to how much memory the resulting + * lzma_index is allowed to require. The value + * pointed by this pointer is modified if and only + * if LZMA_MEMLIMIT_ERROR is returned. + * \param allocator Pointer to lzma_allocator, or NULL to use malloc() + * \param in Beginning of the input buffer + * \param in_pos The next byte will be read from in[*in_pos]. + * *in_pos is updated only if decoding succeeds. + * \param in_size Size of the input buffer; the first byte that + * won't be read is in[in_size]. + * + * \return - LZMA_OK: Decoding was successful. + * - LZMA_MEM_ERROR + * - LZMA_MEMLIMIT_ERROR: Memory usage limit was reached. + * The minimum required memlimit value was stored to *memlimit. + * - LZMA_DATA_ERROR + * - LZMA_PROG_ERROR + */ +extern LZMA_API(lzma_ret) lzma_index_buffer_decode(lzma_index **i, + uint64_t *memlimit, const lzma_allocator *allocator, + const uint8_t *in, size_t *in_pos, size_t in_size) + lzma_nothrow; diff --git a/dependencies/cmliblzma/liblzma/api/lzma/index_hash.h b/dependencies/cmliblzma/liblzma/api/lzma/index_hash.h new file mode 100644 index 0000000..9287f1d --- /dev/null +++ b/dependencies/cmliblzma/liblzma/api/lzma/index_hash.h @@ -0,0 +1,107 @@ +/** + * \file lzma/index_hash.h + * \brief Validate Index by using a hash function + * + * Hashing makes it possible to use constant amount of memory to validate + * Index of arbitrary size. + */ + +/* + * Author: Lasse Collin + * + * This file has been put into the public domain. + * You can do whatever you want with this file. + * + * See ../lzma.h for information about liblzma as a whole. + */ + +#ifndef LZMA_H_INTERNAL +# error Never include this file directly. Use instead. +#endif + +/** + * \brief Opaque data type to hold the Index hash + */ +typedef struct lzma_index_hash_s lzma_index_hash; + + +/** + * \brief Allocate and initialize a new lzma_index_hash structure + * + * If index_hash is NULL, a new lzma_index_hash structure is allocated, + * initialized, and a pointer to it returned. If allocation fails, NULL + * is returned. + * + * If index_hash is non-NULL, it is reinitialized and the same pointer + * returned. In this case, return value cannot be NULL or a different + * pointer than the index_hash that was given as an argument. + */ +extern LZMA_API(lzma_index_hash *) lzma_index_hash_init( + lzma_index_hash *index_hash, const lzma_allocator *allocator) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Deallocate lzma_index_hash structure + */ +extern LZMA_API(void) lzma_index_hash_end( + lzma_index_hash *index_hash, const lzma_allocator *allocator) + lzma_nothrow; + + +/** + * \brief Add a new Record to an Index hash + * + * \param index Pointer to a lzma_index_hash structure + * \param unpadded_size Unpadded Size of a Block + * \param uncompressed_size Uncompressed Size of a Block + * + * \return - LZMA_OK + * - LZMA_DATA_ERROR: Compressed or uncompressed size of the + * Stream or size of the Index field would grow too big. + * - LZMA_PROG_ERROR: Invalid arguments or this function is being + * used when lzma_index_hash_decode() has already been used. + */ +extern LZMA_API(lzma_ret) lzma_index_hash_append(lzma_index_hash *index_hash, + lzma_vli unpadded_size, lzma_vli uncompressed_size) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Decode and validate the Index field + * + * After telling the sizes of all Blocks with lzma_index_hash_append(), + * the actual Index field is decoded with this function. Specifically, + * once decoding of the Index field has been started, no more Records + * can be added using lzma_index_hash_append(). + * + * This function doesn't use lzma_stream structure to pass the input data. + * Instead, the input buffer is specified using three arguments. This is + * because it matches better the internal APIs of liblzma. + * + * \param index_hash Pointer to a lzma_index_hash structure + * \param in Pointer to the beginning of the input buffer + * \param in_pos in[*in_pos] is the next byte to process + * \param in_size in[in_size] is the first byte not to process + * + * \return - LZMA_OK: So far good, but more input is needed. + * - LZMA_STREAM_END: Index decoded successfully and it matches + * the Records given with lzma_index_hash_append(). + * - LZMA_DATA_ERROR: Index is corrupt or doesn't match the + * information given with lzma_index_hash_append(). + * - LZMA_BUF_ERROR: Cannot progress because *in_pos >= in_size. + * - LZMA_PROG_ERROR + */ +extern LZMA_API(lzma_ret) lzma_index_hash_decode(lzma_index_hash *index_hash, + const uint8_t *in, size_t *in_pos, size_t in_size) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Get the size of the Index field as bytes + * + * This is needed to verify the Backward Size field in the Stream Footer. + */ +extern LZMA_API(lzma_vli) lzma_index_hash_size( + const lzma_index_hash *index_hash) + lzma_nothrow lzma_attr_pure; diff --git a/dependencies/cmliblzma/liblzma/api/lzma/lzma12.h b/dependencies/cmliblzma/liblzma/api/lzma/lzma12.h new file mode 100644 index 0000000..4e32fa3 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/api/lzma/lzma12.h @@ -0,0 +1,420 @@ +/** + * \file lzma/lzma12.h + * \brief LZMA1 and LZMA2 filters + */ + +/* + * Author: Lasse Collin + * + * This file has been put into the public domain. + * You can do whatever you want with this file. + * + * See ../lzma.h for information about liblzma as a whole. + */ + +#ifndef LZMA_H_INTERNAL +# error Never include this file directly. Use instead. +#endif + + +/** + * \brief LZMA1 Filter ID + * + * LZMA1 is the very same thing as what was called just LZMA in LZMA Utils, + * 7-Zip, and LZMA SDK. It's called LZMA1 here to prevent developers from + * accidentally using LZMA when they actually want LZMA2. + * + * LZMA1 shouldn't be used for new applications unless you _really_ know + * what you are doing. LZMA2 is almost always a better choice. + */ +#define LZMA_FILTER_LZMA1 LZMA_VLI_C(0x4000000000000001) + +/** + * \brief LZMA2 Filter ID + * + * Usually you want this instead of LZMA1. Compared to LZMA1, LZMA2 adds + * support for LZMA_SYNC_FLUSH, uncompressed chunks (smaller expansion + * when trying to compress uncompressible data), possibility to change + * lc/lp/pb in the middle of encoding, and some other internal improvements. + */ +#define LZMA_FILTER_LZMA2 LZMA_VLI_C(0x21) + + +/** + * \brief Match finders + * + * Match finder has major effect on both speed and compression ratio. + * Usually hash chains are faster than binary trees. + * + * If you will use LZMA_SYNC_FLUSH often, the hash chains may be a better + * choice, because binary trees get much higher compression ratio penalty + * with LZMA_SYNC_FLUSH. + * + * The memory usage formulas are only rough estimates, which are closest to + * reality when dict_size is a power of two. The formulas are more complex + * in reality, and can also change a little between liblzma versions. Use + * lzma_raw_encoder_memusage() to get more accurate estimate of memory usage. + */ +typedef enum { + LZMA_MF_HC3 = 0x03, + /**< + * \brief Hash Chain with 2- and 3-byte hashing + * + * Minimum nice_len: 3 + * + * Memory usage: + * - dict_size <= 16 MiB: dict_size * 7.5 + * - dict_size > 16 MiB: dict_size * 5.5 + 64 MiB + */ + + LZMA_MF_HC4 = 0x04, + /**< + * \brief Hash Chain with 2-, 3-, and 4-byte hashing + * + * Minimum nice_len: 4 + * + * Memory usage: + * - dict_size <= 32 MiB: dict_size * 7.5 + * - dict_size > 32 MiB: dict_size * 6.5 + */ + + LZMA_MF_BT2 = 0x12, + /**< + * \brief Binary Tree with 2-byte hashing + * + * Minimum nice_len: 2 + * + * Memory usage: dict_size * 9.5 + */ + + LZMA_MF_BT3 = 0x13, + /**< + * \brief Binary Tree with 2- and 3-byte hashing + * + * Minimum nice_len: 3 + * + * Memory usage: + * - dict_size <= 16 MiB: dict_size * 11.5 + * - dict_size > 16 MiB: dict_size * 9.5 + 64 MiB + */ + + LZMA_MF_BT4 = 0x14 + /**< + * \brief Binary Tree with 2-, 3-, and 4-byte hashing + * + * Minimum nice_len: 4 + * + * Memory usage: + * - dict_size <= 32 MiB: dict_size * 11.5 + * - dict_size > 32 MiB: dict_size * 10.5 + */ +} lzma_match_finder; + + +/** + * \brief Test if given match finder is supported + * + * Return true if the given match finder is supported by this liblzma build. + * Otherwise false is returned. It is safe to call this with a value that + * isn't listed in lzma_match_finder enumeration; the return value will be + * false. + * + * There is no way to list which match finders are available in this + * particular liblzma version and build. It would be useless, because + * a new match finder, which the application developer wasn't aware, + * could require giving additional options to the encoder that the older + * match finders don't need. + */ +extern LZMA_API(lzma_bool) lzma_mf_is_supported(lzma_match_finder match_finder) + lzma_nothrow lzma_attr_const; + + +/** + * \brief Compression modes + * + * This selects the function used to analyze the data produced by the match + * finder. + */ +typedef enum { + LZMA_MODE_FAST = 1, + /**< + * \brief Fast compression + * + * Fast mode is usually at its best when combined with + * a hash chain match finder. + */ + + LZMA_MODE_NORMAL = 2 + /**< + * \brief Normal compression + * + * This is usually notably slower than fast mode. Use this + * together with binary tree match finders to expose the + * full potential of the LZMA1 or LZMA2 encoder. + */ +} lzma_mode; + + +/** + * \brief Test if given compression mode is supported + * + * Return true if the given compression mode is supported by this liblzma + * build. Otherwise false is returned. It is safe to call this with a value + * that isn't listed in lzma_mode enumeration; the return value will be false. + * + * There is no way to list which modes are available in this particular + * liblzma version and build. It would be useless, because a new compression + * mode, which the application developer wasn't aware, could require giving + * additional options to the encoder that the older modes don't need. + */ +extern LZMA_API(lzma_bool) lzma_mode_is_supported(lzma_mode mode) + lzma_nothrow lzma_attr_const; + + +/** + * \brief Options specific to the LZMA1 and LZMA2 filters + * + * Since LZMA1 and LZMA2 share most of the code, it's simplest to share + * the options structure too. For encoding, all but the reserved variables + * need to be initialized unless specifically mentioned otherwise. + * lzma_lzma_preset() can be used to get a good starting point. + * + * For raw decoding, both LZMA1 and LZMA2 need dict_size, preset_dict, and + * preset_dict_size (if preset_dict != NULL). LZMA1 needs also lc, lp, and pb. + */ +typedef struct { + /** + * \brief Dictionary size in bytes + * + * Dictionary size indicates how many bytes of the recently processed + * uncompressed data is kept in memory. One method to reduce size of + * the uncompressed data is to store distance-length pairs, which + * indicate what data to repeat from the dictionary buffer. Thus, + * the bigger the dictionary, the better the compression ratio + * usually is. + * + * Maximum size of the dictionary depends on multiple things: + * - Memory usage limit + * - Available address space (not a problem on 64-bit systems) + * - Selected match finder (encoder only) + * + * Currently the maximum dictionary size for encoding is 1.5 GiB + * (i.e. (UINT32_C(1) << 30) + (UINT32_C(1) << 29)) even on 64-bit + * systems for certain match finder implementation reasons. In the + * future, there may be match finders that support bigger + * dictionaries. + * + * Decoder already supports dictionaries up to 4 GiB - 1 B (i.e. + * UINT32_MAX), so increasing the maximum dictionary size of the + * encoder won't cause problems for old decoders. + * + * Because extremely small dictionaries sizes would have unneeded + * overhead in the decoder, the minimum dictionary size is 4096 bytes. + * + * \note When decoding, too big dictionary does no other harm + * than wasting memory. + */ + uint32_t dict_size; +# define LZMA_DICT_SIZE_MIN UINT32_C(4096) +# define LZMA_DICT_SIZE_DEFAULT (UINT32_C(1) << 23) + + /** + * \brief Pointer to an initial dictionary + * + * It is possible to initialize the LZ77 history window using + * a preset dictionary. It is useful when compressing many + * similar, relatively small chunks of data independently from + * each other. The preset dictionary should contain typical + * strings that occur in the files being compressed. The most + * probable strings should be near the end of the preset dictionary. + * + * This feature should be used only in special situations. For + * now, it works correctly only with raw encoding and decoding. + * Currently none of the container formats supported by + * liblzma allow preset dictionary when decoding, thus if + * you create a .xz or .lzma file with preset dictionary, it + * cannot be decoded with the regular decoder functions. In the + * future, the .xz format will likely get support for preset + * dictionary though. + */ + const uint8_t *preset_dict; + + /** + * \brief Size of the preset dictionary + * + * Specifies the size of the preset dictionary. If the size is + * bigger than dict_size, only the last dict_size bytes are + * processed. + * + * This variable is read only when preset_dict is not NULL. + * If preset_dict is not NULL but preset_dict_size is zero, + * no preset dictionary is used (identical to only setting + * preset_dict to NULL). + */ + uint32_t preset_dict_size; + + /** + * \brief Number of literal context bits + * + * How many of the highest bits of the previous uncompressed + * eight-bit byte (also known as `literal') are taken into + * account when predicting the bits of the next literal. + * + * E.g. in typical English text, an upper-case letter is + * often followed by a lower-case letter, and a lower-case + * letter is usually followed by another lower-case letter. + * In the US-ASCII character set, the highest three bits are 010 + * for upper-case letters and 011 for lower-case letters. + * When lc is at least 3, the literal coding can take advantage of + * this property in the uncompressed data. + * + * There is a limit that applies to literal context bits and literal + * position bits together: lc + lp <= 4. Without this limit the + * decoding could become very slow, which could have security related + * results in some cases like email servers doing virus scanning. + * This limit also simplifies the internal implementation in liblzma. + * + * There may be LZMA1 streams that have lc + lp > 4 (maximum possible + * lc would be 8). It is not possible to decode such streams with + * liblzma. + */ + uint32_t lc; +# define LZMA_LCLP_MIN 0 +# define LZMA_LCLP_MAX 4 +# define LZMA_LC_DEFAULT 3 + + /** + * \brief Number of literal position bits + * + * lp affects what kind of alignment in the uncompressed data is + * assumed when encoding literals. A literal is a single 8-bit byte. + * See pb below for more information about alignment. + */ + uint32_t lp; +# define LZMA_LP_DEFAULT 0 + + /** + * \brief Number of position bits + * + * pb affects what kind of alignment in the uncompressed data is + * assumed in general. The default means four-byte alignment + * (2^ pb =2^2=4), which is often a good choice when there's + * no better guess. + * + * When the aligment is known, setting pb accordingly may reduce + * the file size a little. E.g. with text files having one-byte + * alignment (US-ASCII, ISO-8859-*, UTF-8), setting pb=0 can + * improve compression slightly. For UTF-16 text, pb=1 is a good + * choice. If the alignment is an odd number like 3 bytes, pb=0 + * might be the best choice. + * + * Even though the assumed alignment can be adjusted with pb and + * lp, LZMA1 and LZMA2 still slightly favor 16-byte alignment. + * It might be worth taking into account when designing file formats + * that are likely to be often compressed with LZMA1 or LZMA2. + */ + uint32_t pb; +# define LZMA_PB_MIN 0 +# define LZMA_PB_MAX 4 +# define LZMA_PB_DEFAULT 2 + + /** Compression mode */ + lzma_mode mode; + + /** + * \brief Nice length of a match + * + * This determines how many bytes the encoder compares from the match + * candidates when looking for the best match. Once a match of at + * least nice_len bytes long is found, the encoder stops looking for + * better candidates and encodes the match. (Naturally, if the found + * match is actually longer than nice_len, the actual length is + * encoded; it's not truncated to nice_len.) + * + * Bigger values usually increase the compression ratio and + * compression time. For most files, 32 to 128 is a good value, + * which gives very good compression ratio at good speed. + * + * The exact minimum value depends on the match finder. The maximum + * is 273, which is the maximum length of a match that LZMA1 and + * LZMA2 can encode. + */ + uint32_t nice_len; + + /** Match finder ID */ + lzma_match_finder mf; + + /** + * \brief Maximum search depth in the match finder + * + * For every input byte, match finder searches through the hash chain + * or binary tree in a loop, each iteration going one step deeper in + * the chain or tree. The searching stops if + * - a match of at least nice_len bytes long is found; + * - all match candidates from the hash chain or binary tree have + * been checked; or + * - maximum search depth is reached. + * + * Maximum search depth is needed to prevent the match finder from + * wasting too much time in case there are lots of short match + * candidates. On the other hand, stopping the search before all + * candidates have been checked can reduce compression ratio. + * + * Setting depth to zero tells liblzma to use an automatic default + * value, that depends on the selected match finder and nice_len. + * The default is in the range [4, 200] or so (it may vary between + * liblzma versions). + * + * Using a bigger depth value than the default can increase + * compression ratio in some cases. There is no strict maximum value, + * but high values (thousands or millions) should be used with care: + * the encoder could remain fast enough with typical input, but + * malicious input could cause the match finder to slow down + * dramatically, possibly creating a denial of service attack. + */ + uint32_t depth; + + /* + * Reserved space to allow possible future extensions without + * breaking the ABI. You should not touch these, because the names + * of these variables may change. These are and will never be used + * with the currently supported options, so it is safe to leave these + * uninitialized. + */ + uint32_t reserved_int1; + uint32_t reserved_int2; + uint32_t reserved_int3; + uint32_t reserved_int4; + uint32_t reserved_int5; + uint32_t reserved_int6; + uint32_t reserved_int7; + uint32_t reserved_int8; + lzma_reserved_enum reserved_enum1; + lzma_reserved_enum reserved_enum2; + lzma_reserved_enum reserved_enum3; + lzma_reserved_enum reserved_enum4; + void *reserved_ptr1; + void *reserved_ptr2; + +} lzma_options_lzma; + + +/** + * \brief Set a compression preset to lzma_options_lzma structure + * + * 0 is the fastest and 9 is the slowest. These match the switches -0 .. -9 + * of the xz command line tool. In addition, it is possible to bitwise-or + * flags to the preset. Currently only LZMA_PRESET_EXTREME is supported. + * The flags are defined in container.h, because the flags are used also + * with lzma_easy_encoder(). + * + * The preset values are subject to changes between liblzma versions. + * + * This function is available only if LZMA1 or LZMA2 encoder has been enabled + * when building liblzma. + * + * \return On success, false is returned. If the preset is not + * supported, true is returned. + */ +extern LZMA_API(lzma_bool) lzma_lzma_preset( + lzma_options_lzma *options, uint32_t preset) lzma_nothrow; diff --git a/dependencies/cmliblzma/liblzma/api/lzma/stream_flags.h b/dependencies/cmliblzma/liblzma/api/lzma/stream_flags.h new file mode 100644 index 0000000..bbdd408 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/api/lzma/stream_flags.h @@ -0,0 +1,223 @@ +/** + * \file lzma/stream_flags.h + * \brief .xz Stream Header and Stream Footer encoder and decoder + */ + +/* + * Author: Lasse Collin + * + * This file has been put into the public domain. + * You can do whatever you want with this file. + * + * See ../lzma.h for information about liblzma as a whole. + */ + +#ifndef LZMA_H_INTERNAL +# error Never include this file directly. Use instead. +#endif + + +/** + * \brief Size of Stream Header and Stream Footer + * + * Stream Header and Stream Footer have the same size and they are not + * going to change even if a newer version of the .xz file format is + * developed in future. + */ +#define LZMA_STREAM_HEADER_SIZE 12 + + +/** + * \brief Options for encoding/decoding Stream Header and Stream Footer + */ +typedef struct { + /** + * \brief Stream Flags format version + * + * To prevent API and ABI breakages if new features are needed in + * Stream Header or Stream Footer, a version number is used to + * indicate which fields in this structure are in use. For now, + * version must always be zero. With non-zero version, the + * lzma_stream_header_encode() and lzma_stream_footer_encode() + * will return LZMA_OPTIONS_ERROR. + * + * lzma_stream_header_decode() and lzma_stream_footer_decode() + * will always set this to the lowest value that supports all the + * features indicated by the Stream Flags field. The application + * must check that the version number set by the decoding functions + * is supported by the application. Otherwise it is possible that + * the application will decode the Stream incorrectly. + */ + uint32_t version; + + /** + * \brief Backward Size + * + * Backward Size must be a multiple of four bytes. In this Stream + * format version, Backward Size is the size of the Index field. + * + * Backward Size isn't actually part of the Stream Flags field, but + * it is convenient to include in this structure anyway. Backward + * Size is present only in the Stream Footer. There is no need to + * initialize backward_size when encoding Stream Header. + * + * lzma_stream_header_decode() always sets backward_size to + * LZMA_VLI_UNKNOWN so that it is convenient to use + * lzma_stream_flags_compare() when both Stream Header and Stream + * Footer have been decoded. + */ + lzma_vli backward_size; +# define LZMA_BACKWARD_SIZE_MIN 4 +# define LZMA_BACKWARD_SIZE_MAX (LZMA_VLI_C(1) << 34) + + /** + * \brief Check ID + * + * This indicates the type of the integrity check calculated from + * uncompressed data. + */ + lzma_check check; + + /* + * Reserved space to allow possible future extensions without + * breaking the ABI. You should not touch these, because the + * names of these variables may change. + * + * (We will never be able to use all of these since Stream Flags + * is just two bytes plus Backward Size of four bytes. But it's + * nice to have the proper types when they are needed.) + */ + lzma_reserved_enum reserved_enum1; + lzma_reserved_enum reserved_enum2; + lzma_reserved_enum reserved_enum3; + lzma_reserved_enum reserved_enum4; + lzma_bool reserved_bool1; + lzma_bool reserved_bool2; + lzma_bool reserved_bool3; + lzma_bool reserved_bool4; + lzma_bool reserved_bool5; + lzma_bool reserved_bool6; + lzma_bool reserved_bool7; + lzma_bool reserved_bool8; + uint32_t reserved_int1; + uint32_t reserved_int2; + +} lzma_stream_flags; + + +/** + * \brief Encode Stream Header + * + * \param options Stream Header options to be encoded. + * options->backward_size is ignored and doesn't + * need to be initialized. + * \param out Beginning of the output buffer of + * LZMA_STREAM_HEADER_SIZE bytes. + * + * \return - LZMA_OK: Encoding was successful. + * - LZMA_OPTIONS_ERROR: options->version is not supported by + * this liblzma version. + * - LZMA_PROG_ERROR: Invalid options. + */ +extern LZMA_API(lzma_ret) lzma_stream_header_encode( + const lzma_stream_flags *options, uint8_t *out) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Encode Stream Footer + * + * \param options Stream Footer options to be encoded. + * \param out Beginning of the output buffer of + * LZMA_STREAM_HEADER_SIZE bytes. + * + * \return - LZMA_OK: Encoding was successful. + * - LZMA_OPTIONS_ERROR: options->version is not supported by + * this liblzma version. + * - LZMA_PROG_ERROR: Invalid options. + */ +extern LZMA_API(lzma_ret) lzma_stream_footer_encode( + const lzma_stream_flags *options, uint8_t *out) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Decode Stream Header + * + * \param options Target for the decoded Stream Header options. + * \param in Beginning of the input buffer of + * LZMA_STREAM_HEADER_SIZE bytes. + * + * options->backward_size is always set to LZMA_VLI_UNKNOWN. This is to + * help comparing Stream Flags from Stream Header and Stream Footer with + * lzma_stream_flags_compare(). + * + * \return - LZMA_OK: Decoding was successful. + * - LZMA_FORMAT_ERROR: Magic bytes don't match, thus the given + * buffer cannot be Stream Header. + * - LZMA_DATA_ERROR: CRC32 doesn't match, thus the header + * is corrupt. + * - LZMA_OPTIONS_ERROR: Unsupported options are present + * in the header. + * + * \note When decoding .xz files that contain multiple Streams, it may + * make sense to print "file format not recognized" only if + * decoding of the Stream Header of the _first_ Stream gives + * LZMA_FORMAT_ERROR. If non-first Stream Header gives + * LZMA_FORMAT_ERROR, the message used for LZMA_DATA_ERROR is + * probably more appropriate. + * + * For example, Stream decoder in liblzma uses LZMA_DATA_ERROR if + * LZMA_FORMAT_ERROR is returned by lzma_stream_header_decode() + * when decoding non-first Stream. + */ +extern LZMA_API(lzma_ret) lzma_stream_header_decode( + lzma_stream_flags *options, const uint8_t *in) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Decode Stream Footer + * + * \param options Target for the decoded Stream Header options. + * \param in Beginning of the input buffer of + * LZMA_STREAM_HEADER_SIZE bytes. + * + * \return - LZMA_OK: Decoding was successful. + * - LZMA_FORMAT_ERROR: Magic bytes don't match, thus the given + * buffer cannot be Stream Footer. + * - LZMA_DATA_ERROR: CRC32 doesn't match, thus the Stream Footer + * is corrupt. + * - LZMA_OPTIONS_ERROR: Unsupported options are present + * in Stream Footer. + * + * \note If Stream Header was already decoded successfully, but + * decoding Stream Footer returns LZMA_FORMAT_ERROR, the + * application should probably report some other error message + * than "file format not recognized", since the file more likely + * is corrupt (possibly truncated). Stream decoder in liblzma + * uses LZMA_DATA_ERROR in this situation. + */ +extern LZMA_API(lzma_ret) lzma_stream_footer_decode( + lzma_stream_flags *options, const uint8_t *in) + lzma_nothrow lzma_attr_warn_unused_result; + + +/** + * \brief Compare two lzma_stream_flags structures + * + * backward_size values are compared only if both are not + * LZMA_VLI_UNKNOWN. + * + * \return - LZMA_OK: Both are equal. If either had backward_size set + * to LZMA_VLI_UNKNOWN, backward_size values were not + * compared or validated. + * - LZMA_DATA_ERROR: The structures differ. + * - LZMA_OPTIONS_ERROR: version in either structure is greater + * than the maximum supported version (currently zero). + * - LZMA_PROG_ERROR: Invalid value, e.g. invalid check or + * backward_size. + */ +extern LZMA_API(lzma_ret) lzma_stream_flags_compare( + const lzma_stream_flags *a, const lzma_stream_flags *b) + lzma_nothrow lzma_attr_pure; diff --git a/dependencies/cmliblzma/liblzma/api/lzma/version.h b/dependencies/cmliblzma/liblzma/api/lzma/version.h new file mode 100644 index 0000000..143c7de --- /dev/null +++ b/dependencies/cmliblzma/liblzma/api/lzma/version.h @@ -0,0 +1,121 @@ +/** + * \file lzma/version.h + * \brief Version number + */ + +/* + * Author: Lasse Collin + * + * This file has been put into the public domain. + * You can do whatever you want with this file. + * + * See ../lzma.h for information about liblzma as a whole. + */ + +#ifndef LZMA_H_INTERNAL +# error Never include this file directly. Use instead. +#endif + + +/* + * Version number split into components + */ +#define LZMA_VERSION_MAJOR 5 +#define LZMA_VERSION_MINOR 2 +#define LZMA_VERSION_PATCH 4 +#define LZMA_VERSION_STABILITY LZMA_VERSION_STABILITY_STABLE + +#ifndef LZMA_VERSION_COMMIT +# define LZMA_VERSION_COMMIT "" +#endif + + +/* + * Map symbolic stability levels to integers. + */ +#define LZMA_VERSION_STABILITY_ALPHA 0 +#define LZMA_VERSION_STABILITY_BETA 1 +#define LZMA_VERSION_STABILITY_STABLE 2 + + +/** + * \brief Compile-time version number + * + * The version number is of format xyyyzzzs where + * - x = major + * - yyy = minor + * - zzz = revision + * - s indicates stability: 0 = alpha, 1 = beta, 2 = stable + * + * The same xyyyzzz triplet is never reused with different stability levels. + * For example, if 5.1.0alpha has been released, there will never be 5.1.0beta + * or 5.1.0 stable. + * + * \note The version number of liblzma has nothing to with + * the version number of Igor Pavlov's LZMA SDK. + */ +#define LZMA_VERSION (LZMA_VERSION_MAJOR * UINT32_C(10000000) \ + + LZMA_VERSION_MINOR * UINT32_C(10000) \ + + LZMA_VERSION_PATCH * UINT32_C(10) \ + + LZMA_VERSION_STABILITY) + + +/* + * Macros to construct the compile-time version string + */ +#if LZMA_VERSION_STABILITY == LZMA_VERSION_STABILITY_ALPHA +# define LZMA_VERSION_STABILITY_STRING "alpha" +#elif LZMA_VERSION_STABILITY == LZMA_VERSION_STABILITY_BETA +# define LZMA_VERSION_STABILITY_STRING "beta" +#elif LZMA_VERSION_STABILITY == LZMA_VERSION_STABILITY_STABLE +# define LZMA_VERSION_STABILITY_STRING "" +#else +# error Incorrect LZMA_VERSION_STABILITY +#endif + +#define LZMA_VERSION_STRING_C_(major, minor, patch, stability, commit) \ + #major "." #minor "." #patch stability commit + +#define LZMA_VERSION_STRING_C(major, minor, patch, stability, commit) \ + LZMA_VERSION_STRING_C_(major, minor, patch, stability, commit) + + +/** + * \brief Compile-time version as a string + * + * This can be for example "4.999.5alpha", "4.999.8beta", or "5.0.0" (stable + * versions don't have any "stable" suffix). In future, a snapshot built + * from source code repository may include an additional suffix, for example + * "4.999.8beta-21-g1d92". The commit ID won't be available in numeric form + * in LZMA_VERSION macro. + */ +#define LZMA_VERSION_STRING LZMA_VERSION_STRING_C( \ + LZMA_VERSION_MAJOR, LZMA_VERSION_MINOR, \ + LZMA_VERSION_PATCH, LZMA_VERSION_STABILITY_STRING, \ + LZMA_VERSION_COMMIT) + + +/* #ifndef is needed for use with windres (MinGW or Cygwin). */ +#ifndef LZMA_H_INTERNAL_RC + +/** + * \brief Run-time version number as an integer + * + * Return the value of LZMA_VERSION macro at the compile time of liblzma. + * This allows the application to compare if it was built against the same, + * older, or newer version of liblzma that is currently running. + */ +extern LZMA_API(uint32_t) lzma_version_number(void) + lzma_nothrow lzma_attr_const; + + +/** + * \brief Run-time version as a string + * + * This function may be useful if you want to display which version of + * liblzma your application is currently using. + */ +extern LZMA_API(const char *) lzma_version_string(void) + lzma_nothrow lzma_attr_const; + +#endif diff --git a/dependencies/cmliblzma/liblzma/api/lzma/vli.h b/dependencies/cmliblzma/liblzma/api/lzma/vli.h new file mode 100644 index 0000000..9ad13f2 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/api/lzma/vli.h @@ -0,0 +1,166 @@ +/** + * \file lzma/vli.h + * \brief Variable-length integer handling + * + * In the .xz format, most integers are encoded in a variable-length + * representation, which is sometimes called little endian base-128 encoding. + * This saves space when smaller values are more likely than bigger values. + * + * The encoding scheme encodes seven bits to every byte, using minimum + * number of bytes required to represent the given value. Encodings that use + * non-minimum number of bytes are invalid, thus every integer has exactly + * one encoded representation. The maximum number of bits in a VLI is 63, + * thus the vli argument must be less than or equal to UINT64_MAX / 2. You + * should use LZMA_VLI_MAX for clarity. + */ + +/* + * Author: Lasse Collin + * + * This file has been put into the public domain. + * You can do whatever you want with this file. + * + * See ../lzma.h for information about liblzma as a whole. + */ + +#ifndef LZMA_H_INTERNAL +# error Never include this file directly. Use instead. +#endif + + +/** + * \brief Maximum supported value of a variable-length integer + */ +#define LZMA_VLI_MAX (UINT64_MAX / 2) + +/** + * \brief VLI value to denote that the value is unknown + */ +#define LZMA_VLI_UNKNOWN UINT64_MAX + +/** + * \brief Maximum supported encoded length of variable length integers + */ +#define LZMA_VLI_BYTES_MAX 9 + +/** + * \brief VLI constant suffix + */ +#define LZMA_VLI_C(n) UINT64_C(n) + + +/** + * \brief Variable-length integer type + * + * Valid VLI values are in the range [0, LZMA_VLI_MAX]. Unknown value is + * indicated with LZMA_VLI_UNKNOWN, which is the maximum value of the + * underlaying integer type. + * + * lzma_vli will be uint64_t for the foreseeable future. If a bigger size + * is needed in the future, it is guaranteed that 2 * LZMA_VLI_MAX will + * not overflow lzma_vli. This simplifies integer overflow detection. + */ +typedef uint64_t lzma_vli; + + +/** + * \brief Validate a variable-length integer + * + * This is useful to test that application has given acceptable values + * for example in the uncompressed_size and compressed_size variables. + * + * \return True if the integer is representable as VLI or if it + * indicates unknown value. + */ +#define lzma_vli_is_valid(vli) \ + ((vli) <= LZMA_VLI_MAX || (vli) == LZMA_VLI_UNKNOWN) + + +/** + * \brief Encode a variable-length integer + * + * This function has two modes: single-call and multi-call. Single-call mode + * encodes the whole integer at once; it is an error if the output buffer is + * too small. Multi-call mode saves the position in *vli_pos, and thus it is + * possible to continue encoding if the buffer becomes full before the whole + * integer has been encoded. + * + * \param vli Integer to be encoded + * \param vli_pos How many VLI-encoded bytes have already been written + * out. When starting to encode a new integer in + * multi-call mode, *vli_pos must be set to zero. + * To use single-call encoding, set vli_pos to NULL. + * \param out Beginning of the output buffer + * \param out_pos The next byte will be written to out[*out_pos]. + * \param out_size Size of the out buffer; the first byte into + * which no data is written to is out[out_size]. + * + * \return Slightly different return values are used in multi-call and + * single-call modes. + * + * Single-call (vli_pos == NULL): + * - LZMA_OK: Integer successfully encoded. + * - LZMA_PROG_ERROR: Arguments are not sane. This can be due + * to too little output space; single-call mode doesn't use + * LZMA_BUF_ERROR, since the application should have checked + * the encoded size with lzma_vli_size(). + * + * Multi-call (vli_pos != NULL): + * - LZMA_OK: So far all OK, but the integer is not + * completely written out yet. + * - LZMA_STREAM_END: Integer successfully encoded. + * - LZMA_BUF_ERROR: No output space was provided. + * - LZMA_PROG_ERROR: Arguments are not sane. + */ +extern LZMA_API(lzma_ret) lzma_vli_encode(lzma_vli vli, size_t *vli_pos, + uint8_t *out, size_t *out_pos, size_t out_size) lzma_nothrow; + + +/** + * \brief Decode a variable-length integer + * + * Like lzma_vli_encode(), this function has single-call and multi-call modes. + * + * \param vli Pointer to decoded integer. The decoder will + * initialize it to zero when *vli_pos == 0, so + * application isn't required to initialize *vli. + * \param vli_pos How many bytes have already been decoded. When + * starting to decode a new integer in multi-call + * mode, *vli_pos must be initialized to zero. To + * use single-call decoding, set vli_pos to NULL. + * \param in Beginning of the input buffer + * \param in_pos The next byte will be read from in[*in_pos]. + * \param in_size Size of the input buffer; the first byte that + * won't be read is in[in_size]. + * + * \return Slightly different return values are used in multi-call and + * single-call modes. + * + * Single-call (vli_pos == NULL): + * - LZMA_OK: Integer successfully decoded. + * - LZMA_DATA_ERROR: Integer is corrupt. This includes hitting + * the end of the input buffer before the whole integer was + * decoded; providing no input at all will use LZMA_DATA_ERROR. + * - LZMA_PROG_ERROR: Arguments are not sane. + * + * Multi-call (vli_pos != NULL): + * - LZMA_OK: So far all OK, but the integer is not + * completely decoded yet. + * - LZMA_STREAM_END: Integer successfully decoded. + * - LZMA_DATA_ERROR: Integer is corrupt. + * - LZMA_BUF_ERROR: No input was provided. + * - LZMA_PROG_ERROR: Arguments are not sane. + */ +extern LZMA_API(lzma_ret) lzma_vli_decode(lzma_vli *vli, size_t *vli_pos, + const uint8_t *in, size_t *in_pos, size_t in_size) + lzma_nothrow; + + +/** + * \brief Get the number of bytes required to encode a VLI + * + * \return Number of bytes on success (1-9). If vli isn't valid, + * zero is returned. + */ +extern LZMA_API(uint32_t) lzma_vli_size(lzma_vli vli) + lzma_nothrow lzma_attr_pure; diff --git a/dependencies/cmliblzma/liblzma/check/check.c b/dependencies/cmliblzma/liblzma/check/check.c new file mode 100644 index 0000000..428ddae --- /dev/null +++ b/dependencies/cmliblzma/liblzma/check/check.c @@ -0,0 +1,174 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file check.c +/// \brief Single API to access different integrity checks +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "check.h" + + +extern LZMA_API(lzma_bool) +lzma_check_is_supported(lzma_check type) +{ + if ((unsigned int)(type) > LZMA_CHECK_ID_MAX) + return false; + + static const lzma_bool available_checks[LZMA_CHECK_ID_MAX + 1] = { + true, // LZMA_CHECK_NONE + +#ifdef HAVE_CHECK_CRC32 + true, +#else + false, +#endif + + false, // Reserved + false, // Reserved + +#ifdef HAVE_CHECK_CRC64 + true, +#else + false, +#endif + + false, // Reserved + false, // Reserved + false, // Reserved + false, // Reserved + false, // Reserved + +#ifdef HAVE_CHECK_SHA256 + true, +#else + false, +#endif + + false, // Reserved + false, // Reserved + false, // Reserved + false, // Reserved + false, // Reserved + }; + + return available_checks[(unsigned int)(type)]; +} + + +extern LZMA_API(uint32_t) +lzma_check_size(lzma_check type) +{ + if ((unsigned int)(type) > LZMA_CHECK_ID_MAX) + return UINT32_MAX; + + // See file-format.txt section 2.1.1.2. + static const uint8_t check_sizes[LZMA_CHECK_ID_MAX + 1] = { + 0, + 4, 4, 4, + 8, 8, 8, + 16, 16, 16, + 32, 32, 32, + 64, 64, 64 + }; + + return check_sizes[(unsigned int)(type)]; +} + + +extern void +lzma_check_init(lzma_check_state *check, lzma_check type) +{ + switch (type) { + case LZMA_CHECK_NONE: + break; + +#ifdef HAVE_CHECK_CRC32 + case LZMA_CHECK_CRC32: + check->state.crc32 = 0; + break; +#endif + +#ifdef HAVE_CHECK_CRC64 + case LZMA_CHECK_CRC64: + check->state.crc64 = 0; + break; +#endif + +#ifdef HAVE_CHECK_SHA256 + case LZMA_CHECK_SHA256: + lzma_sha256_init(check); + break; +#endif + + default: + break; + } + + return; +} + + +extern void +lzma_check_update(lzma_check_state *check, lzma_check type, + const uint8_t *buf, size_t size) +{ + switch (type) { +#ifdef HAVE_CHECK_CRC32 + case LZMA_CHECK_CRC32: + check->state.crc32 = lzma_crc32(buf, size, check->state.crc32); + break; +#endif + +#ifdef HAVE_CHECK_CRC64 + case LZMA_CHECK_CRC64: + check->state.crc64 = lzma_crc64(buf, size, check->state.crc64); + break; +#endif + +#ifdef HAVE_CHECK_SHA256 + case LZMA_CHECK_SHA256: + lzma_sha256_update(buf, size, check); + break; +#endif + + default: + break; + } + + return; +} + + +extern void +lzma_check_finish(lzma_check_state *check, lzma_check type) +{ + switch (type) { +#ifdef HAVE_CHECK_CRC32 + case LZMA_CHECK_CRC32: + check->buffer.u32[0] = conv32le(check->state.crc32); + break; +#endif + +#ifdef HAVE_CHECK_CRC64 + case LZMA_CHECK_CRC64: + check->buffer.u64[0] = conv64le(check->state.crc64); + break; +#endif + +#ifdef HAVE_CHECK_SHA256 + case LZMA_CHECK_SHA256: + lzma_sha256_finish(check); + break; +#endif + + default: + break; + } + + return; +} diff --git a/dependencies/cmliblzma/liblzma/check/check.h b/dependencies/cmliblzma/liblzma/check/check.h new file mode 100644 index 0000000..3007d88 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/check/check.h @@ -0,0 +1,172 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file check.h +/// \brief Internal API to different integrity check functions +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_CHECK_H +#define LZMA_CHECK_H + +#include "common.h" + +// If the function for external SHA-256 is missing, use the internal SHA-256 +// code. Due to how configure works, these defines can only get defined when +// both a usable header and a type have already been found. +#if !(defined(HAVE_CC_SHA256_INIT) \ + || defined(HAVE_SHA256_INIT) \ + || defined(HAVE_SHA256INIT)) +# define HAVE_INTERNAL_SHA256 1 +#endif + +#if defined(HAVE_INTERNAL_SHA256) +// Nothing +#elif defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H) +# include +#elif defined(HAVE_SHA256_H) +# include +# include +#elif defined(HAVE_SHA2_H) +# include +# include +#endif + +#if defined(HAVE_INTERNAL_SHA256) +/// State for the internal SHA-256 implementation +typedef struct { + /// Internal state + uint32_t state[8]; + + /// Size of the message excluding padding + uint64_t size; +} lzma_sha256_state; +#elif defined(HAVE_CC_SHA256_CTX) +typedef CC_SHA256_CTX lzma_sha256_state; +#elif defined(HAVE_SHA256_CTX) +typedef SHA256_CTX lzma_sha256_state; +#elif defined(HAVE_SHA2_CTX) +typedef SHA2_CTX lzma_sha256_state; +#endif + +#if defined(HAVE_INTERNAL_SHA256) +// Nothing +#elif defined(HAVE_CC_SHA256_INIT) +# define LZMA_SHA256FUNC(x) CC_SHA256_ ## x +#elif defined(HAVE_SHA256_INIT) +# define LZMA_SHA256FUNC(x) SHA256_ ## x +#elif defined(HAVE_SHA256INIT) +# define LZMA_SHA256FUNC(x) SHA256 ## x +#endif + +// Index hashing needs the best possible hash function (preferably +// a cryptographic hash) for maximum reliability. +#if defined(HAVE_CHECK_SHA256) +# define LZMA_CHECK_BEST LZMA_CHECK_SHA256 +#elif defined(HAVE_CHECK_CRC64) +# define LZMA_CHECK_BEST LZMA_CHECK_CRC64 +#else +# define LZMA_CHECK_BEST LZMA_CHECK_CRC32 +#endif + + +/// \brief Structure to hold internal state of the check being calculated +/// +/// \note This is not in the public API because this structure may +/// change in future if new integrity check algorithms are added. +typedef struct { + /// Buffer to hold the final result and a temporary buffer for SHA256. + union { + uint8_t u8[64]; + uint32_t u32[16]; + uint64_t u64[8]; + } buffer; + + /// Check-specific data + union { + uint32_t crc32; + uint64_t crc64; + lzma_sha256_state sha256; + } state; + +} lzma_check_state; + + +/// lzma_crc32_table[0] is needed by LZ encoder so we need to keep +/// the array two-dimensional. +#ifdef HAVE_SMALL +extern uint32_t lzma_crc32_table[1][256]; +extern void lzma_crc32_init(void); +#else +extern const uint32_t lzma_crc32_table[8][256]; +extern const uint64_t lzma_crc64_table[4][256]; +#endif + + +/// \brief Initialize *check depending on type +/// +/// \return LZMA_OK on success. LZMA_UNSUPPORTED_CHECK if the type is not +/// supported by the current version or build of liblzma. +/// LZMA_PROG_ERROR if type > LZMA_CHECK_ID_MAX. +extern void lzma_check_init(lzma_check_state *check, lzma_check type); + +/// Update the check state +extern void lzma_check_update(lzma_check_state *check, lzma_check type, + const uint8_t *buf, size_t size); + +/// Finish the check calculation and store the result to check->buffer.u8. +extern void lzma_check_finish(lzma_check_state *check, lzma_check type); + + +#ifndef LZMA_SHA256FUNC + +/// Prepare SHA-256 state for new input. +extern void lzma_sha256_init(lzma_check_state *check); + +/// Update the SHA-256 hash state +extern void lzma_sha256_update( + const uint8_t *buf, size_t size, lzma_check_state *check); + +/// Finish the SHA-256 calculation and store the result to check->buffer.u8. +extern void lzma_sha256_finish(lzma_check_state *check); + + +#else + +static inline void +lzma_sha256_init(lzma_check_state *check) +{ + LZMA_SHA256FUNC(Init)(&check->state.sha256); +} + + +static inline void +lzma_sha256_update(const uint8_t *buf, size_t size, lzma_check_state *check) +{ +#if defined(HAVE_CC_SHA256_INIT) && SIZE_MAX > UINT32_MAX + // Darwin's CC_SHA256_Update takes uint32_t as the buffer size, + // so use a loop to support size_t. + while (size > UINT32_MAX) { + LZMA_SHA256FUNC(Update)(&check->state.sha256, buf, UINT32_MAX); + buf += UINT32_MAX; + size -= UINT32_MAX; + } +#endif + + LZMA_SHA256FUNC(Update)(&check->state.sha256, buf, size); +} + + +static inline void +lzma_sha256_finish(lzma_check_state *check) +{ + LZMA_SHA256FUNC(Final)(check->buffer.u8, &check->state.sha256); +} + +#endif + +#endif diff --git a/dependencies/cmliblzma/liblzma/check/crc32_fast.c b/dependencies/cmliblzma/liblzma/check/crc32_fast.c new file mode 100644 index 0000000..3de0263 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/check/crc32_fast.c @@ -0,0 +1,82 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file crc32.c +/// \brief CRC32 calculation +/// +/// Calculate the CRC32 using the slice-by-eight algorithm. +/// It is explained in this document: +/// http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf +/// The code in this file is not the same as in Intel's paper, but +/// the basic principle is identical. +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "check.h" +#include "crc_macros.h" + + +// If you make any changes, do some benchmarking! Seemingly unrelated +// changes can very easily ruin the performance (and very probably is +// very compiler dependent). +extern LZMA_API(uint32_t) +lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc) +{ + crc = ~crc; + +#ifdef WORDS_BIGENDIAN + crc = bswap32(crc); +#endif + + if (size > 8) { + // Fix the alignment, if needed. The if statement above + // ensures that this won't read past the end of buf[]. + while ((uintptr_t)(buf) & 7) { + crc = lzma_crc32_table[0][*buf++ ^ A(crc)] ^ S8(crc); + --size; + } + + // Calculate the position where to stop. + const uint8_t *const limit = buf + (size & ~(size_t)(7)); + + // Calculate how many bytes must be calculated separately + // before returning the result. + size &= (size_t)(7); + + // Calculate the CRC32 using the slice-by-eight algorithm. + while (buf < limit) { + crc ^= *(const uint32_t *)(buf); + buf += 4; + + crc = lzma_crc32_table[7][A(crc)] + ^ lzma_crc32_table[6][B(crc)] + ^ lzma_crc32_table[5][C(crc)] + ^ lzma_crc32_table[4][D(crc)]; + + const uint32_t tmp = *(const uint32_t *)(buf); + buf += 4; + + // At least with some compilers, it is critical for + // performance, that the crc variable is XORed + // between the two table-lookup pairs. + crc = lzma_crc32_table[3][A(tmp)] + ^ lzma_crc32_table[2][B(tmp)] + ^ crc + ^ lzma_crc32_table[1][C(tmp)] + ^ lzma_crc32_table[0][D(tmp)]; + } + } + + while (size-- != 0) + crc = lzma_crc32_table[0][*buf++ ^ A(crc)] ^ S8(crc); + +#ifdef WORDS_BIGENDIAN + crc = bswap32(crc); +#endif + + return ~crc; +} diff --git a/dependencies/cmliblzma/liblzma/check/crc32_small.c b/dependencies/cmliblzma/liblzma/check/crc32_small.c new file mode 100644 index 0000000..5f8a328 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/check/crc32_small.c @@ -0,0 +1,61 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file crc32_small.c +/// \brief CRC32 calculation (size-optimized) +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "check.h" + + +uint32_t lzma_crc32_table[1][256]; + + +static void +crc32_init(void) +{ + static const uint32_t poly32 = UINT32_C(0xEDB88320); + + for (size_t b = 0; b < 256; ++b) { + uint32_t r = b; + for (size_t i = 0; i < 8; ++i) { + if (r & 1) + r = (r >> 1) ^ poly32; + else + r >>= 1; + } + + lzma_crc32_table[0][b] = r; + } + + return; +} + + +extern void +lzma_crc32_init(void) +{ + mythread_once(crc32_init); + return; +} + + +extern LZMA_API(uint32_t) +lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc) +{ + lzma_crc32_init(); + + crc = ~crc; + + while (size != 0) { + crc = lzma_crc32_table[0][*buf++ ^ (crc & 0xFF)] ^ (crc >> 8); + --size; + } + + return ~crc; +} diff --git a/dependencies/cmliblzma/liblzma/check/crc32_table.c b/dependencies/cmliblzma/liblzma/check/crc32_table.c new file mode 100644 index 0000000..368874e --- /dev/null +++ b/dependencies/cmliblzma/liblzma/check/crc32_table.c @@ -0,0 +1,19 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file crc32_table.c +/// \brief Precalculated CRC32 table with correct endianness +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "common.h" + +#ifdef WORDS_BIGENDIAN +# include "crc32_table_be.h" +#else +# include "crc32_table_le.h" +#endif diff --git a/dependencies/cmliblzma/liblzma/check/crc32_table_be.h b/dependencies/cmliblzma/liblzma/check/crc32_table_be.h new file mode 100644 index 0000000..c483cb6 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/check/crc32_table_be.h @@ -0,0 +1,525 @@ +/* This file has been automatically generated by crc32_tablegen.c. */ + +const uint32_t lzma_crc32_table[8][256] = { + { + 0x00000000, 0x96300777, 0x2C610EEE, 0xBA510999, + 0x19C46D07, 0x8FF46A70, 0x35A563E9, 0xA395649E, + 0x3288DB0E, 0xA4B8DC79, 0x1EE9D5E0, 0x88D9D297, + 0x2B4CB609, 0xBD7CB17E, 0x072DB8E7, 0x911DBF90, + 0x6410B71D, 0xF220B06A, 0x4871B9F3, 0xDE41BE84, + 0x7DD4DA1A, 0xEBE4DD6D, 0x51B5D4F4, 0xC785D383, + 0x56986C13, 0xC0A86B64, 0x7AF962FD, 0xECC9658A, + 0x4F5C0114, 0xD96C0663, 0x633D0FFA, 0xF50D088D, + 0xC8206E3B, 0x5E10694C, 0xE44160D5, 0x727167A2, + 0xD1E4033C, 0x47D4044B, 0xFD850DD2, 0x6BB50AA5, + 0xFAA8B535, 0x6C98B242, 0xD6C9BBDB, 0x40F9BCAC, + 0xE36CD832, 0x755CDF45, 0xCF0DD6DC, 0x593DD1AB, + 0xAC30D926, 0x3A00DE51, 0x8051D7C8, 0x1661D0BF, + 0xB5F4B421, 0x23C4B356, 0x9995BACF, 0x0FA5BDB8, + 0x9EB80228, 0x0888055F, 0xB2D90CC6, 0x24E90BB1, + 0x877C6F2F, 0x114C6858, 0xAB1D61C1, 0x3D2D66B6, + 0x9041DC76, 0x0671DB01, 0xBC20D298, 0x2A10D5EF, + 0x8985B171, 0x1FB5B606, 0xA5E4BF9F, 0x33D4B8E8, + 0xA2C90778, 0x34F9000F, 0x8EA80996, 0x18980EE1, + 0xBB0D6A7F, 0x2D3D6D08, 0x976C6491, 0x015C63E6, + 0xF4516B6B, 0x62616C1C, 0xD8306585, 0x4E0062F2, + 0xED95066C, 0x7BA5011B, 0xC1F40882, 0x57C40FF5, + 0xC6D9B065, 0x50E9B712, 0xEAB8BE8B, 0x7C88B9FC, + 0xDF1DDD62, 0x492DDA15, 0xF37CD38C, 0x654CD4FB, + 0x5861B24D, 0xCE51B53A, 0x7400BCA3, 0xE230BBD4, + 0x41A5DF4A, 0xD795D83D, 0x6DC4D1A4, 0xFBF4D6D3, + 0x6AE96943, 0xFCD96E34, 0x468867AD, 0xD0B860DA, + 0x732D0444, 0xE51D0333, 0x5F4C0AAA, 0xC97C0DDD, + 0x3C710550, 0xAA410227, 0x10100BBE, 0x86200CC9, + 0x25B56857, 0xB3856F20, 0x09D466B9, 0x9FE461CE, + 0x0EF9DE5E, 0x98C9D929, 0x2298D0B0, 0xB4A8D7C7, + 0x173DB359, 0x810DB42E, 0x3B5CBDB7, 0xAD6CBAC0, + 0x2083B8ED, 0xB6B3BF9A, 0x0CE2B603, 0x9AD2B174, + 0x3947D5EA, 0xAF77D29D, 0x1526DB04, 0x8316DC73, + 0x120B63E3, 0x843B6494, 0x3E6A6D0D, 0xA85A6A7A, + 0x0BCF0EE4, 0x9DFF0993, 0x27AE000A, 0xB19E077D, + 0x44930FF0, 0xD2A30887, 0x68F2011E, 0xFEC20669, + 0x5D5762F7, 0xCB676580, 0x71366C19, 0xE7066B6E, + 0x761BD4FE, 0xE02BD389, 0x5A7ADA10, 0xCC4ADD67, + 0x6FDFB9F9, 0xF9EFBE8E, 0x43BEB717, 0xD58EB060, + 0xE8A3D6D6, 0x7E93D1A1, 0xC4C2D838, 0x52F2DF4F, + 0xF167BBD1, 0x6757BCA6, 0xDD06B53F, 0x4B36B248, + 0xDA2B0DD8, 0x4C1B0AAF, 0xF64A0336, 0x607A0441, + 0xC3EF60DF, 0x55DF67A8, 0xEF8E6E31, 0x79BE6946, + 0x8CB361CB, 0x1A8366BC, 0xA0D26F25, 0x36E26852, + 0x95770CCC, 0x03470BBB, 0xB9160222, 0x2F260555, + 0xBE3BBAC5, 0x280BBDB2, 0x925AB42B, 0x046AB35C, + 0xA7FFD7C2, 0x31CFD0B5, 0x8B9ED92C, 0x1DAEDE5B, + 0xB0C2649B, 0x26F263EC, 0x9CA36A75, 0x0A936D02, + 0xA906099C, 0x3F360EEB, 0x85670772, 0x13570005, + 0x824ABF95, 0x147AB8E2, 0xAE2BB17B, 0x381BB60C, + 0x9B8ED292, 0x0DBED5E5, 0xB7EFDC7C, 0x21DFDB0B, + 0xD4D2D386, 0x42E2D4F1, 0xF8B3DD68, 0x6E83DA1F, + 0xCD16BE81, 0x5B26B9F6, 0xE177B06F, 0x7747B718, + 0xE65A0888, 0x706A0FFF, 0xCA3B0666, 0x5C0B0111, + 0xFF9E658F, 0x69AE62F8, 0xD3FF6B61, 0x45CF6C16, + 0x78E20AA0, 0xEED20DD7, 0x5483044E, 0xC2B30339, + 0x612667A7, 0xF71660D0, 0x4D476949, 0xDB776E3E, + 0x4A6AD1AE, 0xDC5AD6D9, 0x660BDF40, 0xF03BD837, + 0x53AEBCA9, 0xC59EBBDE, 0x7FCFB247, 0xE9FFB530, + 0x1CF2BDBD, 0x8AC2BACA, 0x3093B353, 0xA6A3B424, + 0x0536D0BA, 0x9306D7CD, 0x2957DE54, 0xBF67D923, + 0x2E7A66B3, 0xB84A61C4, 0x021B685D, 0x942B6F2A, + 0x37BE0BB4, 0xA18E0CC3, 0x1BDF055A, 0x8DEF022D + }, { + 0x00000000, 0x41311B19, 0x82623632, 0xC3532D2B, + 0x04C56C64, 0x45F4777D, 0x86A75A56, 0xC796414F, + 0x088AD9C8, 0x49BBC2D1, 0x8AE8EFFA, 0xCBD9F4E3, + 0x0C4FB5AC, 0x4D7EAEB5, 0x8E2D839E, 0xCF1C9887, + 0x5112C24A, 0x1023D953, 0xD370F478, 0x9241EF61, + 0x55D7AE2E, 0x14E6B537, 0xD7B5981C, 0x96848305, + 0x59981B82, 0x18A9009B, 0xDBFA2DB0, 0x9ACB36A9, + 0x5D5D77E6, 0x1C6C6CFF, 0xDF3F41D4, 0x9E0E5ACD, + 0xA2248495, 0xE3159F8C, 0x2046B2A7, 0x6177A9BE, + 0xA6E1E8F1, 0xE7D0F3E8, 0x2483DEC3, 0x65B2C5DA, + 0xAAAE5D5D, 0xEB9F4644, 0x28CC6B6F, 0x69FD7076, + 0xAE6B3139, 0xEF5A2A20, 0x2C09070B, 0x6D381C12, + 0xF33646DF, 0xB2075DC6, 0x715470ED, 0x30656BF4, + 0xF7F32ABB, 0xB6C231A2, 0x75911C89, 0x34A00790, + 0xFBBC9F17, 0xBA8D840E, 0x79DEA925, 0x38EFB23C, + 0xFF79F373, 0xBE48E86A, 0x7D1BC541, 0x3C2ADE58, + 0x054F79F0, 0x447E62E9, 0x872D4FC2, 0xC61C54DB, + 0x018A1594, 0x40BB0E8D, 0x83E823A6, 0xC2D938BF, + 0x0DC5A038, 0x4CF4BB21, 0x8FA7960A, 0xCE968D13, + 0x0900CC5C, 0x4831D745, 0x8B62FA6E, 0xCA53E177, + 0x545DBBBA, 0x156CA0A3, 0xD63F8D88, 0x970E9691, + 0x5098D7DE, 0x11A9CCC7, 0xD2FAE1EC, 0x93CBFAF5, + 0x5CD76272, 0x1DE6796B, 0xDEB55440, 0x9F844F59, + 0x58120E16, 0x1923150F, 0xDA703824, 0x9B41233D, + 0xA76BFD65, 0xE65AE67C, 0x2509CB57, 0x6438D04E, + 0xA3AE9101, 0xE29F8A18, 0x21CCA733, 0x60FDBC2A, + 0xAFE124AD, 0xEED03FB4, 0x2D83129F, 0x6CB20986, + 0xAB2448C9, 0xEA1553D0, 0x29467EFB, 0x687765E2, + 0xF6793F2F, 0xB7482436, 0x741B091D, 0x352A1204, + 0xF2BC534B, 0xB38D4852, 0x70DE6579, 0x31EF7E60, + 0xFEF3E6E7, 0xBFC2FDFE, 0x7C91D0D5, 0x3DA0CBCC, + 0xFA368A83, 0xBB07919A, 0x7854BCB1, 0x3965A7A8, + 0x4B98833B, 0x0AA99822, 0xC9FAB509, 0x88CBAE10, + 0x4F5DEF5F, 0x0E6CF446, 0xCD3FD96D, 0x8C0EC274, + 0x43125AF3, 0x022341EA, 0xC1706CC1, 0x804177D8, + 0x47D73697, 0x06E62D8E, 0xC5B500A5, 0x84841BBC, + 0x1A8A4171, 0x5BBB5A68, 0x98E87743, 0xD9D96C5A, + 0x1E4F2D15, 0x5F7E360C, 0x9C2D1B27, 0xDD1C003E, + 0x120098B9, 0x533183A0, 0x9062AE8B, 0xD153B592, + 0x16C5F4DD, 0x57F4EFC4, 0x94A7C2EF, 0xD596D9F6, + 0xE9BC07AE, 0xA88D1CB7, 0x6BDE319C, 0x2AEF2A85, + 0xED796BCA, 0xAC4870D3, 0x6F1B5DF8, 0x2E2A46E1, + 0xE136DE66, 0xA007C57F, 0x6354E854, 0x2265F34D, + 0xE5F3B202, 0xA4C2A91B, 0x67918430, 0x26A09F29, + 0xB8AEC5E4, 0xF99FDEFD, 0x3ACCF3D6, 0x7BFDE8CF, + 0xBC6BA980, 0xFD5AB299, 0x3E099FB2, 0x7F3884AB, + 0xB0241C2C, 0xF1150735, 0x32462A1E, 0x73773107, + 0xB4E17048, 0xF5D06B51, 0x3683467A, 0x77B25D63, + 0x4ED7FACB, 0x0FE6E1D2, 0xCCB5CCF9, 0x8D84D7E0, + 0x4A1296AF, 0x0B238DB6, 0xC870A09D, 0x8941BB84, + 0x465D2303, 0x076C381A, 0xC43F1531, 0x850E0E28, + 0x42984F67, 0x03A9547E, 0xC0FA7955, 0x81CB624C, + 0x1FC53881, 0x5EF42398, 0x9DA70EB3, 0xDC9615AA, + 0x1B0054E5, 0x5A314FFC, 0x996262D7, 0xD85379CE, + 0x174FE149, 0x567EFA50, 0x952DD77B, 0xD41CCC62, + 0x138A8D2D, 0x52BB9634, 0x91E8BB1F, 0xD0D9A006, + 0xECF37E5E, 0xADC26547, 0x6E91486C, 0x2FA05375, + 0xE836123A, 0xA9070923, 0x6A542408, 0x2B653F11, + 0xE479A796, 0xA548BC8F, 0x661B91A4, 0x272A8ABD, + 0xE0BCCBF2, 0xA18DD0EB, 0x62DEFDC0, 0x23EFE6D9, + 0xBDE1BC14, 0xFCD0A70D, 0x3F838A26, 0x7EB2913F, + 0xB924D070, 0xF815CB69, 0x3B46E642, 0x7A77FD5B, + 0xB56B65DC, 0xF45A7EC5, 0x370953EE, 0x763848F7, + 0xB1AE09B8, 0xF09F12A1, 0x33CC3F8A, 0x72FD2493 + }, { + 0x00000000, 0x376AC201, 0x6ED48403, 0x59BE4602, + 0xDCA80907, 0xEBC2CB06, 0xB27C8D04, 0x85164F05, + 0xB851130E, 0x8F3BD10F, 0xD685970D, 0xE1EF550C, + 0x64F91A09, 0x5393D808, 0x0A2D9E0A, 0x3D475C0B, + 0x70A3261C, 0x47C9E41D, 0x1E77A21F, 0x291D601E, + 0xAC0B2F1B, 0x9B61ED1A, 0xC2DFAB18, 0xF5B56919, + 0xC8F23512, 0xFF98F713, 0xA626B111, 0x914C7310, + 0x145A3C15, 0x2330FE14, 0x7A8EB816, 0x4DE47A17, + 0xE0464D38, 0xD72C8F39, 0x8E92C93B, 0xB9F80B3A, + 0x3CEE443F, 0x0B84863E, 0x523AC03C, 0x6550023D, + 0x58175E36, 0x6F7D9C37, 0x36C3DA35, 0x01A91834, + 0x84BF5731, 0xB3D59530, 0xEA6BD332, 0xDD011133, + 0x90E56B24, 0xA78FA925, 0xFE31EF27, 0xC95B2D26, + 0x4C4D6223, 0x7B27A022, 0x2299E620, 0x15F32421, + 0x28B4782A, 0x1FDEBA2B, 0x4660FC29, 0x710A3E28, + 0xF41C712D, 0xC376B32C, 0x9AC8F52E, 0xADA2372F, + 0xC08D9A70, 0xF7E75871, 0xAE591E73, 0x9933DC72, + 0x1C259377, 0x2B4F5176, 0x72F11774, 0x459BD575, + 0x78DC897E, 0x4FB64B7F, 0x16080D7D, 0x2162CF7C, + 0xA4748079, 0x931E4278, 0xCAA0047A, 0xFDCAC67B, + 0xB02EBC6C, 0x87447E6D, 0xDEFA386F, 0xE990FA6E, + 0x6C86B56B, 0x5BEC776A, 0x02523168, 0x3538F369, + 0x087FAF62, 0x3F156D63, 0x66AB2B61, 0x51C1E960, + 0xD4D7A665, 0xE3BD6464, 0xBA032266, 0x8D69E067, + 0x20CBD748, 0x17A11549, 0x4E1F534B, 0x7975914A, + 0xFC63DE4F, 0xCB091C4E, 0x92B75A4C, 0xA5DD984D, + 0x989AC446, 0xAFF00647, 0xF64E4045, 0xC1248244, + 0x4432CD41, 0x73580F40, 0x2AE64942, 0x1D8C8B43, + 0x5068F154, 0x67023355, 0x3EBC7557, 0x09D6B756, + 0x8CC0F853, 0xBBAA3A52, 0xE2147C50, 0xD57EBE51, + 0xE839E25A, 0xDF53205B, 0x86ED6659, 0xB187A458, + 0x3491EB5D, 0x03FB295C, 0x5A456F5E, 0x6D2FAD5F, + 0x801B35E1, 0xB771F7E0, 0xEECFB1E2, 0xD9A573E3, + 0x5CB33CE6, 0x6BD9FEE7, 0x3267B8E5, 0x050D7AE4, + 0x384A26EF, 0x0F20E4EE, 0x569EA2EC, 0x61F460ED, + 0xE4E22FE8, 0xD388EDE9, 0x8A36ABEB, 0xBD5C69EA, + 0xF0B813FD, 0xC7D2D1FC, 0x9E6C97FE, 0xA90655FF, + 0x2C101AFA, 0x1B7AD8FB, 0x42C49EF9, 0x75AE5CF8, + 0x48E900F3, 0x7F83C2F2, 0x263D84F0, 0x115746F1, + 0x944109F4, 0xA32BCBF5, 0xFA958DF7, 0xCDFF4FF6, + 0x605D78D9, 0x5737BAD8, 0x0E89FCDA, 0x39E33EDB, + 0xBCF571DE, 0x8B9FB3DF, 0xD221F5DD, 0xE54B37DC, + 0xD80C6BD7, 0xEF66A9D6, 0xB6D8EFD4, 0x81B22DD5, + 0x04A462D0, 0x33CEA0D1, 0x6A70E6D3, 0x5D1A24D2, + 0x10FE5EC5, 0x27949CC4, 0x7E2ADAC6, 0x494018C7, + 0xCC5657C2, 0xFB3C95C3, 0xA282D3C1, 0x95E811C0, + 0xA8AF4DCB, 0x9FC58FCA, 0xC67BC9C8, 0xF1110BC9, + 0x740744CC, 0x436D86CD, 0x1AD3C0CF, 0x2DB902CE, + 0x4096AF91, 0x77FC6D90, 0x2E422B92, 0x1928E993, + 0x9C3EA696, 0xAB546497, 0xF2EA2295, 0xC580E094, + 0xF8C7BC9F, 0xCFAD7E9E, 0x9613389C, 0xA179FA9D, + 0x246FB598, 0x13057799, 0x4ABB319B, 0x7DD1F39A, + 0x3035898D, 0x075F4B8C, 0x5EE10D8E, 0x698BCF8F, + 0xEC9D808A, 0xDBF7428B, 0x82490489, 0xB523C688, + 0x88649A83, 0xBF0E5882, 0xE6B01E80, 0xD1DADC81, + 0x54CC9384, 0x63A65185, 0x3A181787, 0x0D72D586, + 0xA0D0E2A9, 0x97BA20A8, 0xCE0466AA, 0xF96EA4AB, + 0x7C78EBAE, 0x4B1229AF, 0x12AC6FAD, 0x25C6ADAC, + 0x1881F1A7, 0x2FEB33A6, 0x765575A4, 0x413FB7A5, + 0xC429F8A0, 0xF3433AA1, 0xAAFD7CA3, 0x9D97BEA2, + 0xD073C4B5, 0xE71906B4, 0xBEA740B6, 0x89CD82B7, + 0x0CDBCDB2, 0x3BB10FB3, 0x620F49B1, 0x55658BB0, + 0x6822D7BB, 0x5F4815BA, 0x06F653B8, 0x319C91B9, + 0xB48ADEBC, 0x83E01CBD, 0xDA5E5ABF, 0xED3498BE + }, { + 0x00000000, 0x6567BCB8, 0x8BC809AA, 0xEEAFB512, + 0x5797628F, 0x32F0DE37, 0xDC5F6B25, 0xB938D79D, + 0xEF28B4C5, 0x8A4F087D, 0x64E0BD6F, 0x018701D7, + 0xB8BFD64A, 0xDDD86AF2, 0x3377DFE0, 0x56106358, + 0x9F571950, 0xFA30A5E8, 0x149F10FA, 0x71F8AC42, + 0xC8C07BDF, 0xADA7C767, 0x43087275, 0x266FCECD, + 0x707FAD95, 0x1518112D, 0xFBB7A43F, 0x9ED01887, + 0x27E8CF1A, 0x428F73A2, 0xAC20C6B0, 0xC9477A08, + 0x3EAF32A0, 0x5BC88E18, 0xB5673B0A, 0xD00087B2, + 0x6938502F, 0x0C5FEC97, 0xE2F05985, 0x8797E53D, + 0xD1878665, 0xB4E03ADD, 0x5A4F8FCF, 0x3F283377, + 0x8610E4EA, 0xE3775852, 0x0DD8ED40, 0x68BF51F8, + 0xA1F82BF0, 0xC49F9748, 0x2A30225A, 0x4F579EE2, + 0xF66F497F, 0x9308F5C7, 0x7DA740D5, 0x18C0FC6D, + 0x4ED09F35, 0x2BB7238D, 0xC518969F, 0xA07F2A27, + 0x1947FDBA, 0x7C204102, 0x928FF410, 0xF7E848A8, + 0x3D58149B, 0x583FA823, 0xB6901D31, 0xD3F7A189, + 0x6ACF7614, 0x0FA8CAAC, 0xE1077FBE, 0x8460C306, + 0xD270A05E, 0xB7171CE6, 0x59B8A9F4, 0x3CDF154C, + 0x85E7C2D1, 0xE0807E69, 0x0E2FCB7B, 0x6B4877C3, + 0xA20F0DCB, 0xC768B173, 0x29C70461, 0x4CA0B8D9, + 0xF5986F44, 0x90FFD3FC, 0x7E5066EE, 0x1B37DA56, + 0x4D27B90E, 0x284005B6, 0xC6EFB0A4, 0xA3880C1C, + 0x1AB0DB81, 0x7FD76739, 0x9178D22B, 0xF41F6E93, + 0x03F7263B, 0x66909A83, 0x883F2F91, 0xED589329, + 0x546044B4, 0x3107F80C, 0xDFA84D1E, 0xBACFF1A6, + 0xECDF92FE, 0x89B82E46, 0x67179B54, 0x027027EC, + 0xBB48F071, 0xDE2F4CC9, 0x3080F9DB, 0x55E74563, + 0x9CA03F6B, 0xF9C783D3, 0x176836C1, 0x720F8A79, + 0xCB375DE4, 0xAE50E15C, 0x40FF544E, 0x2598E8F6, + 0x73888BAE, 0x16EF3716, 0xF8408204, 0x9D273EBC, + 0x241FE921, 0x41785599, 0xAFD7E08B, 0xCAB05C33, + 0x3BB659ED, 0x5ED1E555, 0xB07E5047, 0xD519ECFF, + 0x6C213B62, 0x094687DA, 0xE7E932C8, 0x828E8E70, + 0xD49EED28, 0xB1F95190, 0x5F56E482, 0x3A31583A, + 0x83098FA7, 0xE66E331F, 0x08C1860D, 0x6DA63AB5, + 0xA4E140BD, 0xC186FC05, 0x2F294917, 0x4A4EF5AF, + 0xF3762232, 0x96119E8A, 0x78BE2B98, 0x1DD99720, + 0x4BC9F478, 0x2EAE48C0, 0xC001FDD2, 0xA566416A, + 0x1C5E96F7, 0x79392A4F, 0x97969F5D, 0xF2F123E5, + 0x05196B4D, 0x607ED7F5, 0x8ED162E7, 0xEBB6DE5F, + 0x528E09C2, 0x37E9B57A, 0xD9460068, 0xBC21BCD0, + 0xEA31DF88, 0x8F566330, 0x61F9D622, 0x049E6A9A, + 0xBDA6BD07, 0xD8C101BF, 0x366EB4AD, 0x53090815, + 0x9A4E721D, 0xFF29CEA5, 0x11867BB7, 0x74E1C70F, + 0xCDD91092, 0xA8BEAC2A, 0x46111938, 0x2376A580, + 0x7566C6D8, 0x10017A60, 0xFEAECF72, 0x9BC973CA, + 0x22F1A457, 0x479618EF, 0xA939ADFD, 0xCC5E1145, + 0x06EE4D76, 0x6389F1CE, 0x8D2644DC, 0xE841F864, + 0x51792FF9, 0x341E9341, 0xDAB12653, 0xBFD69AEB, + 0xE9C6F9B3, 0x8CA1450B, 0x620EF019, 0x07694CA1, + 0xBE519B3C, 0xDB362784, 0x35999296, 0x50FE2E2E, + 0x99B95426, 0xFCDEE89E, 0x12715D8C, 0x7716E134, + 0xCE2E36A9, 0xAB498A11, 0x45E63F03, 0x208183BB, + 0x7691E0E3, 0x13F65C5B, 0xFD59E949, 0x983E55F1, + 0x2106826C, 0x44613ED4, 0xAACE8BC6, 0xCFA9377E, + 0x38417FD6, 0x5D26C36E, 0xB389767C, 0xD6EECAC4, + 0x6FD61D59, 0x0AB1A1E1, 0xE41E14F3, 0x8179A84B, + 0xD769CB13, 0xB20E77AB, 0x5CA1C2B9, 0x39C67E01, + 0x80FEA99C, 0xE5991524, 0x0B36A036, 0x6E511C8E, + 0xA7166686, 0xC271DA3E, 0x2CDE6F2C, 0x49B9D394, + 0xF0810409, 0x95E6B8B1, 0x7B490DA3, 0x1E2EB11B, + 0x483ED243, 0x2D596EFB, 0xC3F6DBE9, 0xA6916751, + 0x1FA9B0CC, 0x7ACE0C74, 0x9461B966, 0xF10605DE + }, { + 0x00000000, 0xB029603D, 0x6053C07A, 0xD07AA047, + 0xC0A680F5, 0x708FE0C8, 0xA0F5408F, 0x10DC20B2, + 0xC14B7030, 0x7162100D, 0xA118B04A, 0x1131D077, + 0x01EDF0C5, 0xB1C490F8, 0x61BE30BF, 0xD1975082, + 0x8297E060, 0x32BE805D, 0xE2C4201A, 0x52ED4027, + 0x42316095, 0xF21800A8, 0x2262A0EF, 0x924BC0D2, + 0x43DC9050, 0xF3F5F06D, 0x238F502A, 0x93A63017, + 0x837A10A5, 0x33537098, 0xE329D0DF, 0x5300B0E2, + 0x042FC1C1, 0xB406A1FC, 0x647C01BB, 0xD4556186, + 0xC4894134, 0x74A02109, 0xA4DA814E, 0x14F3E173, + 0xC564B1F1, 0x754DD1CC, 0xA537718B, 0x151E11B6, + 0x05C23104, 0xB5EB5139, 0x6591F17E, 0xD5B89143, + 0x86B821A1, 0x3691419C, 0xE6EBE1DB, 0x56C281E6, + 0x461EA154, 0xF637C169, 0x264D612E, 0x96640113, + 0x47F35191, 0xF7DA31AC, 0x27A091EB, 0x9789F1D6, + 0x8755D164, 0x377CB159, 0xE706111E, 0x572F7123, + 0x4958F358, 0xF9719365, 0x290B3322, 0x9922531F, + 0x89FE73AD, 0x39D71390, 0xE9ADB3D7, 0x5984D3EA, + 0x88138368, 0x383AE355, 0xE8404312, 0x5869232F, + 0x48B5039D, 0xF89C63A0, 0x28E6C3E7, 0x98CFA3DA, + 0xCBCF1338, 0x7BE67305, 0xAB9CD342, 0x1BB5B37F, + 0x0B6993CD, 0xBB40F3F0, 0x6B3A53B7, 0xDB13338A, + 0x0A846308, 0xBAAD0335, 0x6AD7A372, 0xDAFEC34F, + 0xCA22E3FD, 0x7A0B83C0, 0xAA712387, 0x1A5843BA, + 0x4D773299, 0xFD5E52A4, 0x2D24F2E3, 0x9D0D92DE, + 0x8DD1B26C, 0x3DF8D251, 0xED827216, 0x5DAB122B, + 0x8C3C42A9, 0x3C152294, 0xEC6F82D3, 0x5C46E2EE, + 0x4C9AC25C, 0xFCB3A261, 0x2CC90226, 0x9CE0621B, + 0xCFE0D2F9, 0x7FC9B2C4, 0xAFB31283, 0x1F9A72BE, + 0x0F46520C, 0xBF6F3231, 0x6F159276, 0xDF3CF24B, + 0x0EABA2C9, 0xBE82C2F4, 0x6EF862B3, 0xDED1028E, + 0xCE0D223C, 0x7E244201, 0xAE5EE246, 0x1E77827B, + 0x92B0E6B1, 0x2299868C, 0xF2E326CB, 0x42CA46F6, + 0x52166644, 0xE23F0679, 0x3245A63E, 0x826CC603, + 0x53FB9681, 0xE3D2F6BC, 0x33A856FB, 0x838136C6, + 0x935D1674, 0x23747649, 0xF30ED60E, 0x4327B633, + 0x102706D1, 0xA00E66EC, 0x7074C6AB, 0xC05DA696, + 0xD0818624, 0x60A8E619, 0xB0D2465E, 0x00FB2663, + 0xD16C76E1, 0x614516DC, 0xB13FB69B, 0x0116D6A6, + 0x11CAF614, 0xA1E39629, 0x7199366E, 0xC1B05653, + 0x969F2770, 0x26B6474D, 0xF6CCE70A, 0x46E58737, + 0x5639A785, 0xE610C7B8, 0x366A67FF, 0x864307C2, + 0x57D45740, 0xE7FD377D, 0x3787973A, 0x87AEF707, + 0x9772D7B5, 0x275BB788, 0xF72117CF, 0x470877F2, + 0x1408C710, 0xA421A72D, 0x745B076A, 0xC4726757, + 0xD4AE47E5, 0x648727D8, 0xB4FD879F, 0x04D4E7A2, + 0xD543B720, 0x656AD71D, 0xB510775A, 0x05391767, + 0x15E537D5, 0xA5CC57E8, 0x75B6F7AF, 0xC59F9792, + 0xDBE815E9, 0x6BC175D4, 0xBBBBD593, 0x0B92B5AE, + 0x1B4E951C, 0xAB67F521, 0x7B1D5566, 0xCB34355B, + 0x1AA365D9, 0xAA8A05E4, 0x7AF0A5A3, 0xCAD9C59E, + 0xDA05E52C, 0x6A2C8511, 0xBA562556, 0x0A7F456B, + 0x597FF589, 0xE95695B4, 0x392C35F3, 0x890555CE, + 0x99D9757C, 0x29F01541, 0xF98AB506, 0x49A3D53B, + 0x983485B9, 0x281DE584, 0xF86745C3, 0x484E25FE, + 0x5892054C, 0xE8BB6571, 0x38C1C536, 0x88E8A50B, + 0xDFC7D428, 0x6FEEB415, 0xBF941452, 0x0FBD746F, + 0x1F6154DD, 0xAF4834E0, 0x7F3294A7, 0xCF1BF49A, + 0x1E8CA418, 0xAEA5C425, 0x7EDF6462, 0xCEF6045F, + 0xDE2A24ED, 0x6E0344D0, 0xBE79E497, 0x0E5084AA, + 0x5D503448, 0xED795475, 0x3D03F432, 0x8D2A940F, + 0x9DF6B4BD, 0x2DDFD480, 0xFDA574C7, 0x4D8C14FA, + 0x9C1B4478, 0x2C322445, 0xFC488402, 0x4C61E43F, + 0x5CBDC48D, 0xEC94A4B0, 0x3CEE04F7, 0x8CC764CA + }, { + 0x00000000, 0xA5D35CCB, 0x0BA1C84D, 0xAE729486, + 0x1642919B, 0xB391CD50, 0x1DE359D6, 0xB830051D, + 0x6D8253EC, 0xC8510F27, 0x66239BA1, 0xC3F0C76A, + 0x7BC0C277, 0xDE139EBC, 0x70610A3A, 0xD5B256F1, + 0x9B02D603, 0x3ED18AC8, 0x90A31E4E, 0x35704285, + 0x8D404798, 0x28931B53, 0x86E18FD5, 0x2332D31E, + 0xF68085EF, 0x5353D924, 0xFD214DA2, 0x58F21169, + 0xE0C21474, 0x451148BF, 0xEB63DC39, 0x4EB080F2, + 0x3605AC07, 0x93D6F0CC, 0x3DA4644A, 0x98773881, + 0x20473D9C, 0x85946157, 0x2BE6F5D1, 0x8E35A91A, + 0x5B87FFEB, 0xFE54A320, 0x502637A6, 0xF5F56B6D, + 0x4DC56E70, 0xE81632BB, 0x4664A63D, 0xE3B7FAF6, + 0xAD077A04, 0x08D426CF, 0xA6A6B249, 0x0375EE82, + 0xBB45EB9F, 0x1E96B754, 0xB0E423D2, 0x15377F19, + 0xC08529E8, 0x65567523, 0xCB24E1A5, 0x6EF7BD6E, + 0xD6C7B873, 0x7314E4B8, 0xDD66703E, 0x78B52CF5, + 0x6C0A580F, 0xC9D904C4, 0x67AB9042, 0xC278CC89, + 0x7A48C994, 0xDF9B955F, 0x71E901D9, 0xD43A5D12, + 0x01880BE3, 0xA45B5728, 0x0A29C3AE, 0xAFFA9F65, + 0x17CA9A78, 0xB219C6B3, 0x1C6B5235, 0xB9B80EFE, + 0xF7088E0C, 0x52DBD2C7, 0xFCA94641, 0x597A1A8A, + 0xE14A1F97, 0x4499435C, 0xEAEBD7DA, 0x4F388B11, + 0x9A8ADDE0, 0x3F59812B, 0x912B15AD, 0x34F84966, + 0x8CC84C7B, 0x291B10B0, 0x87698436, 0x22BAD8FD, + 0x5A0FF408, 0xFFDCA8C3, 0x51AE3C45, 0xF47D608E, + 0x4C4D6593, 0xE99E3958, 0x47ECADDE, 0xE23FF115, + 0x378DA7E4, 0x925EFB2F, 0x3C2C6FA9, 0x99FF3362, + 0x21CF367F, 0x841C6AB4, 0x2A6EFE32, 0x8FBDA2F9, + 0xC10D220B, 0x64DE7EC0, 0xCAACEA46, 0x6F7FB68D, + 0xD74FB390, 0x729CEF5B, 0xDCEE7BDD, 0x793D2716, + 0xAC8F71E7, 0x095C2D2C, 0xA72EB9AA, 0x02FDE561, + 0xBACDE07C, 0x1F1EBCB7, 0xB16C2831, 0x14BF74FA, + 0xD814B01E, 0x7DC7ECD5, 0xD3B57853, 0x76662498, + 0xCE562185, 0x6B857D4E, 0xC5F7E9C8, 0x6024B503, + 0xB596E3F2, 0x1045BF39, 0xBE372BBF, 0x1BE47774, + 0xA3D47269, 0x06072EA2, 0xA875BA24, 0x0DA6E6EF, + 0x4316661D, 0xE6C53AD6, 0x48B7AE50, 0xED64F29B, + 0x5554F786, 0xF087AB4D, 0x5EF53FCB, 0xFB266300, + 0x2E9435F1, 0x8B47693A, 0x2535FDBC, 0x80E6A177, + 0x38D6A46A, 0x9D05F8A1, 0x33776C27, 0x96A430EC, + 0xEE111C19, 0x4BC240D2, 0xE5B0D454, 0x4063889F, + 0xF8538D82, 0x5D80D149, 0xF3F245CF, 0x56211904, + 0x83934FF5, 0x2640133E, 0x883287B8, 0x2DE1DB73, + 0x95D1DE6E, 0x300282A5, 0x9E701623, 0x3BA34AE8, + 0x7513CA1A, 0xD0C096D1, 0x7EB20257, 0xDB615E9C, + 0x63515B81, 0xC682074A, 0x68F093CC, 0xCD23CF07, + 0x189199F6, 0xBD42C53D, 0x133051BB, 0xB6E30D70, + 0x0ED3086D, 0xAB0054A6, 0x0572C020, 0xA0A19CEB, + 0xB41EE811, 0x11CDB4DA, 0xBFBF205C, 0x1A6C7C97, + 0xA25C798A, 0x078F2541, 0xA9FDB1C7, 0x0C2EED0C, + 0xD99CBBFD, 0x7C4FE736, 0xD23D73B0, 0x77EE2F7B, + 0xCFDE2A66, 0x6A0D76AD, 0xC47FE22B, 0x61ACBEE0, + 0x2F1C3E12, 0x8ACF62D9, 0x24BDF65F, 0x816EAA94, + 0x395EAF89, 0x9C8DF342, 0x32FF67C4, 0x972C3B0F, + 0x429E6DFE, 0xE74D3135, 0x493FA5B3, 0xECECF978, + 0x54DCFC65, 0xF10FA0AE, 0x5F7D3428, 0xFAAE68E3, + 0x821B4416, 0x27C818DD, 0x89BA8C5B, 0x2C69D090, + 0x9459D58D, 0x318A8946, 0x9FF81DC0, 0x3A2B410B, + 0xEF9917FA, 0x4A4A4B31, 0xE438DFB7, 0x41EB837C, + 0xF9DB8661, 0x5C08DAAA, 0xF27A4E2C, 0x57A912E7, + 0x19199215, 0xBCCACEDE, 0x12B85A58, 0xB76B0693, + 0x0F5B038E, 0xAA885F45, 0x04FACBC3, 0xA1299708, + 0x749BC1F9, 0xD1489D32, 0x7F3A09B4, 0xDAE9557F, + 0x62D95062, 0xC70A0CA9, 0x6978982F, 0xCCABC4E4 + }, { + 0x00000000, 0xB40B77A6, 0x29119F97, 0x9D1AE831, + 0x13244FF4, 0xA72F3852, 0x3A35D063, 0x8E3EA7C5, + 0x674EEF33, 0xD3459895, 0x4E5F70A4, 0xFA540702, + 0x746AA0C7, 0xC061D761, 0x5D7B3F50, 0xE97048F6, + 0xCE9CDE67, 0x7A97A9C1, 0xE78D41F0, 0x53863656, + 0xDDB89193, 0x69B3E635, 0xF4A90E04, 0x40A279A2, + 0xA9D23154, 0x1DD946F2, 0x80C3AEC3, 0x34C8D965, + 0xBAF67EA0, 0x0EFD0906, 0x93E7E137, 0x27EC9691, + 0x9C39BDCF, 0x2832CA69, 0xB5282258, 0x012355FE, + 0x8F1DF23B, 0x3B16859D, 0xA60C6DAC, 0x12071A0A, + 0xFB7752FC, 0x4F7C255A, 0xD266CD6B, 0x666DBACD, + 0xE8531D08, 0x5C586AAE, 0xC142829F, 0x7549F539, + 0x52A563A8, 0xE6AE140E, 0x7BB4FC3F, 0xCFBF8B99, + 0x41812C5C, 0xF58A5BFA, 0x6890B3CB, 0xDC9BC46D, + 0x35EB8C9B, 0x81E0FB3D, 0x1CFA130C, 0xA8F164AA, + 0x26CFC36F, 0x92C4B4C9, 0x0FDE5CF8, 0xBBD52B5E, + 0x79750B44, 0xCD7E7CE2, 0x506494D3, 0xE46FE375, + 0x6A5144B0, 0xDE5A3316, 0x4340DB27, 0xF74BAC81, + 0x1E3BE477, 0xAA3093D1, 0x372A7BE0, 0x83210C46, + 0x0D1FAB83, 0xB914DC25, 0x240E3414, 0x900543B2, + 0xB7E9D523, 0x03E2A285, 0x9EF84AB4, 0x2AF33D12, + 0xA4CD9AD7, 0x10C6ED71, 0x8DDC0540, 0x39D772E6, + 0xD0A73A10, 0x64AC4DB6, 0xF9B6A587, 0x4DBDD221, + 0xC38375E4, 0x77880242, 0xEA92EA73, 0x5E999DD5, + 0xE54CB68B, 0x5147C12D, 0xCC5D291C, 0x78565EBA, + 0xF668F97F, 0x42638ED9, 0xDF7966E8, 0x6B72114E, + 0x820259B8, 0x36092E1E, 0xAB13C62F, 0x1F18B189, + 0x9126164C, 0x252D61EA, 0xB83789DB, 0x0C3CFE7D, + 0x2BD068EC, 0x9FDB1F4A, 0x02C1F77B, 0xB6CA80DD, + 0x38F42718, 0x8CFF50BE, 0x11E5B88F, 0xA5EECF29, + 0x4C9E87DF, 0xF895F079, 0x658F1848, 0xD1846FEE, + 0x5FBAC82B, 0xEBB1BF8D, 0x76AB57BC, 0xC2A0201A, + 0xF2EA1688, 0x46E1612E, 0xDBFB891F, 0x6FF0FEB9, + 0xE1CE597C, 0x55C52EDA, 0xC8DFC6EB, 0x7CD4B14D, + 0x95A4F9BB, 0x21AF8E1D, 0xBCB5662C, 0x08BE118A, + 0x8680B64F, 0x328BC1E9, 0xAF9129D8, 0x1B9A5E7E, + 0x3C76C8EF, 0x887DBF49, 0x15675778, 0xA16C20DE, + 0x2F52871B, 0x9B59F0BD, 0x0643188C, 0xB2486F2A, + 0x5B3827DC, 0xEF33507A, 0x7229B84B, 0xC622CFED, + 0x481C6828, 0xFC171F8E, 0x610DF7BF, 0xD5068019, + 0x6ED3AB47, 0xDAD8DCE1, 0x47C234D0, 0xF3C94376, + 0x7DF7E4B3, 0xC9FC9315, 0x54E67B24, 0xE0ED0C82, + 0x099D4474, 0xBD9633D2, 0x208CDBE3, 0x9487AC45, + 0x1AB90B80, 0xAEB27C26, 0x33A89417, 0x87A3E3B1, + 0xA04F7520, 0x14440286, 0x895EEAB7, 0x3D559D11, + 0xB36B3AD4, 0x07604D72, 0x9A7AA543, 0x2E71D2E5, + 0xC7019A13, 0x730AEDB5, 0xEE100584, 0x5A1B7222, + 0xD425D5E7, 0x602EA241, 0xFD344A70, 0x493F3DD6, + 0x8B9F1DCC, 0x3F946A6A, 0xA28E825B, 0x1685F5FD, + 0x98BB5238, 0x2CB0259E, 0xB1AACDAF, 0x05A1BA09, + 0xECD1F2FF, 0x58DA8559, 0xC5C06D68, 0x71CB1ACE, + 0xFFF5BD0B, 0x4BFECAAD, 0xD6E4229C, 0x62EF553A, + 0x4503C3AB, 0xF108B40D, 0x6C125C3C, 0xD8192B9A, + 0x56278C5F, 0xE22CFBF9, 0x7F3613C8, 0xCB3D646E, + 0x224D2C98, 0x96465B3E, 0x0B5CB30F, 0xBF57C4A9, + 0x3169636C, 0x856214CA, 0x1878FCFB, 0xAC738B5D, + 0x17A6A003, 0xA3ADD7A5, 0x3EB73F94, 0x8ABC4832, + 0x0482EFF7, 0xB0899851, 0x2D937060, 0x999807C6, + 0x70E84F30, 0xC4E33896, 0x59F9D0A7, 0xEDF2A701, + 0x63CC00C4, 0xD7C77762, 0x4ADD9F53, 0xFED6E8F5, + 0xD93A7E64, 0x6D3109C2, 0xF02BE1F3, 0x44209655, + 0xCA1E3190, 0x7E154636, 0xE30FAE07, 0x5704D9A1, + 0xBE749157, 0x0A7FE6F1, 0x97650EC0, 0x236E7966, + 0xAD50DEA3, 0x195BA905, 0x84414134, 0x304A3692 + }, { + 0x00000000, 0x9E00AACC, 0x7D072542, 0xE3078F8E, + 0xFA0E4A84, 0x640EE048, 0x87096FC6, 0x1909C50A, + 0xB51BE5D3, 0x2B1B4F1F, 0xC81CC091, 0x561C6A5D, + 0x4F15AF57, 0xD115059B, 0x32128A15, 0xAC1220D9, + 0x2B31BB7C, 0xB53111B0, 0x56369E3E, 0xC83634F2, + 0xD13FF1F8, 0x4F3F5B34, 0xAC38D4BA, 0x32387E76, + 0x9E2A5EAF, 0x002AF463, 0xE32D7BED, 0x7D2DD121, + 0x6424142B, 0xFA24BEE7, 0x19233169, 0x87239BA5, + 0x566276F9, 0xC862DC35, 0x2B6553BB, 0xB565F977, + 0xAC6C3C7D, 0x326C96B1, 0xD16B193F, 0x4F6BB3F3, + 0xE379932A, 0x7D7939E6, 0x9E7EB668, 0x007E1CA4, + 0x1977D9AE, 0x87777362, 0x6470FCEC, 0xFA705620, + 0x7D53CD85, 0xE3536749, 0x0054E8C7, 0x9E54420B, + 0x875D8701, 0x195D2DCD, 0xFA5AA243, 0x645A088F, + 0xC8482856, 0x5648829A, 0xB54F0D14, 0x2B4FA7D8, + 0x324662D2, 0xAC46C81E, 0x4F414790, 0xD141ED5C, + 0xEDC29D29, 0x73C237E5, 0x90C5B86B, 0x0EC512A7, + 0x17CCD7AD, 0x89CC7D61, 0x6ACBF2EF, 0xF4CB5823, + 0x58D978FA, 0xC6D9D236, 0x25DE5DB8, 0xBBDEF774, + 0xA2D7327E, 0x3CD798B2, 0xDFD0173C, 0x41D0BDF0, + 0xC6F32655, 0x58F38C99, 0xBBF40317, 0x25F4A9DB, + 0x3CFD6CD1, 0xA2FDC61D, 0x41FA4993, 0xDFFAE35F, + 0x73E8C386, 0xEDE8694A, 0x0EEFE6C4, 0x90EF4C08, + 0x89E68902, 0x17E623CE, 0xF4E1AC40, 0x6AE1068C, + 0xBBA0EBD0, 0x25A0411C, 0xC6A7CE92, 0x58A7645E, + 0x41AEA154, 0xDFAE0B98, 0x3CA98416, 0xA2A92EDA, + 0x0EBB0E03, 0x90BBA4CF, 0x73BC2B41, 0xEDBC818D, + 0xF4B54487, 0x6AB5EE4B, 0x89B261C5, 0x17B2CB09, + 0x909150AC, 0x0E91FA60, 0xED9675EE, 0x7396DF22, + 0x6A9F1A28, 0xF49FB0E4, 0x17983F6A, 0x899895A6, + 0x258AB57F, 0xBB8A1FB3, 0x588D903D, 0xC68D3AF1, + 0xDF84FFFB, 0x41845537, 0xA283DAB9, 0x3C837075, + 0xDA853B53, 0x4485919F, 0xA7821E11, 0x3982B4DD, + 0x208B71D7, 0xBE8BDB1B, 0x5D8C5495, 0xC38CFE59, + 0x6F9EDE80, 0xF19E744C, 0x1299FBC2, 0x8C99510E, + 0x95909404, 0x0B903EC8, 0xE897B146, 0x76971B8A, + 0xF1B4802F, 0x6FB42AE3, 0x8CB3A56D, 0x12B30FA1, + 0x0BBACAAB, 0x95BA6067, 0x76BDEFE9, 0xE8BD4525, + 0x44AF65FC, 0xDAAFCF30, 0x39A840BE, 0xA7A8EA72, + 0xBEA12F78, 0x20A185B4, 0xC3A60A3A, 0x5DA6A0F6, + 0x8CE74DAA, 0x12E7E766, 0xF1E068E8, 0x6FE0C224, + 0x76E9072E, 0xE8E9ADE2, 0x0BEE226C, 0x95EE88A0, + 0x39FCA879, 0xA7FC02B5, 0x44FB8D3B, 0xDAFB27F7, + 0xC3F2E2FD, 0x5DF24831, 0xBEF5C7BF, 0x20F56D73, + 0xA7D6F6D6, 0x39D65C1A, 0xDAD1D394, 0x44D17958, + 0x5DD8BC52, 0xC3D8169E, 0x20DF9910, 0xBEDF33DC, + 0x12CD1305, 0x8CCDB9C9, 0x6FCA3647, 0xF1CA9C8B, + 0xE8C35981, 0x76C3F34D, 0x95C47CC3, 0x0BC4D60F, + 0x3747A67A, 0xA9470CB6, 0x4A408338, 0xD44029F4, + 0xCD49ECFE, 0x53494632, 0xB04EC9BC, 0x2E4E6370, + 0x825C43A9, 0x1C5CE965, 0xFF5B66EB, 0x615BCC27, + 0x7852092D, 0xE652A3E1, 0x05552C6F, 0x9B5586A3, + 0x1C761D06, 0x8276B7CA, 0x61713844, 0xFF719288, + 0xE6785782, 0x7878FD4E, 0x9B7F72C0, 0x057FD80C, + 0xA96DF8D5, 0x376D5219, 0xD46ADD97, 0x4A6A775B, + 0x5363B251, 0xCD63189D, 0x2E649713, 0xB0643DDF, + 0x6125D083, 0xFF257A4F, 0x1C22F5C1, 0x82225F0D, + 0x9B2B9A07, 0x052B30CB, 0xE62CBF45, 0x782C1589, + 0xD43E3550, 0x4A3E9F9C, 0xA9391012, 0x3739BADE, + 0x2E307FD4, 0xB030D518, 0x53375A96, 0xCD37F05A, + 0x4A146BFF, 0xD414C133, 0x37134EBD, 0xA913E471, + 0xB01A217B, 0x2E1A8BB7, 0xCD1D0439, 0x531DAEF5, + 0xFF0F8E2C, 0x610F24E0, 0x8208AB6E, 0x1C0801A2, + 0x0501C4A8, 0x9B016E64, 0x7806E1EA, 0xE6064B26 + } +}; diff --git a/dependencies/cmliblzma/liblzma/check/crc32_table_le.h b/dependencies/cmliblzma/liblzma/check/crc32_table_le.h new file mode 100644 index 0000000..25f4fc4 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/check/crc32_table_le.h @@ -0,0 +1,525 @@ +/* This file has been automatically generated by crc32_tablegen.c. */ + +const uint32_t lzma_crc32_table[8][256] = { + { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, + 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, + 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, + 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, + 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, + 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, + 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, + 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, + 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, + 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, + 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, + 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, + 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, + 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, + 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, + 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, + 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, + 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, + 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, + 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, + 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, + 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, + 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, + 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, + 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, + 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, + 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, + 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + }, { + 0x00000000, 0x191B3141, 0x32366282, 0x2B2D53C3, + 0x646CC504, 0x7D77F445, 0x565AA786, 0x4F4196C7, + 0xC8D98A08, 0xD1C2BB49, 0xFAEFE88A, 0xE3F4D9CB, + 0xACB54F0C, 0xB5AE7E4D, 0x9E832D8E, 0x87981CCF, + 0x4AC21251, 0x53D92310, 0x78F470D3, 0x61EF4192, + 0x2EAED755, 0x37B5E614, 0x1C98B5D7, 0x05838496, + 0x821B9859, 0x9B00A918, 0xB02DFADB, 0xA936CB9A, + 0xE6775D5D, 0xFF6C6C1C, 0xD4413FDF, 0xCD5A0E9E, + 0x958424A2, 0x8C9F15E3, 0xA7B24620, 0xBEA97761, + 0xF1E8E1A6, 0xE8F3D0E7, 0xC3DE8324, 0xDAC5B265, + 0x5D5DAEAA, 0x44469FEB, 0x6F6BCC28, 0x7670FD69, + 0x39316BAE, 0x202A5AEF, 0x0B07092C, 0x121C386D, + 0xDF4636F3, 0xC65D07B2, 0xED705471, 0xF46B6530, + 0xBB2AF3F7, 0xA231C2B6, 0x891C9175, 0x9007A034, + 0x179FBCFB, 0x0E848DBA, 0x25A9DE79, 0x3CB2EF38, + 0x73F379FF, 0x6AE848BE, 0x41C51B7D, 0x58DE2A3C, + 0xF0794F05, 0xE9627E44, 0xC24F2D87, 0xDB541CC6, + 0x94158A01, 0x8D0EBB40, 0xA623E883, 0xBF38D9C2, + 0x38A0C50D, 0x21BBF44C, 0x0A96A78F, 0x138D96CE, + 0x5CCC0009, 0x45D73148, 0x6EFA628B, 0x77E153CA, + 0xBABB5D54, 0xA3A06C15, 0x888D3FD6, 0x91960E97, + 0xDED79850, 0xC7CCA911, 0xECE1FAD2, 0xF5FACB93, + 0x7262D75C, 0x6B79E61D, 0x4054B5DE, 0x594F849F, + 0x160E1258, 0x0F152319, 0x243870DA, 0x3D23419B, + 0x65FD6BA7, 0x7CE65AE6, 0x57CB0925, 0x4ED03864, + 0x0191AEA3, 0x188A9FE2, 0x33A7CC21, 0x2ABCFD60, + 0xAD24E1AF, 0xB43FD0EE, 0x9F12832D, 0x8609B26C, + 0xC94824AB, 0xD05315EA, 0xFB7E4629, 0xE2657768, + 0x2F3F79F6, 0x362448B7, 0x1D091B74, 0x04122A35, + 0x4B53BCF2, 0x52488DB3, 0x7965DE70, 0x607EEF31, + 0xE7E6F3FE, 0xFEFDC2BF, 0xD5D0917C, 0xCCCBA03D, + 0x838A36FA, 0x9A9107BB, 0xB1BC5478, 0xA8A76539, + 0x3B83984B, 0x2298A90A, 0x09B5FAC9, 0x10AECB88, + 0x5FEF5D4F, 0x46F46C0E, 0x6DD93FCD, 0x74C20E8C, + 0xF35A1243, 0xEA412302, 0xC16C70C1, 0xD8774180, + 0x9736D747, 0x8E2DE606, 0xA500B5C5, 0xBC1B8484, + 0x71418A1A, 0x685ABB5B, 0x4377E898, 0x5A6CD9D9, + 0x152D4F1E, 0x0C367E5F, 0x271B2D9C, 0x3E001CDD, + 0xB9980012, 0xA0833153, 0x8BAE6290, 0x92B553D1, + 0xDDF4C516, 0xC4EFF457, 0xEFC2A794, 0xF6D996D5, + 0xAE07BCE9, 0xB71C8DA8, 0x9C31DE6B, 0x852AEF2A, + 0xCA6B79ED, 0xD37048AC, 0xF85D1B6F, 0xE1462A2E, + 0x66DE36E1, 0x7FC507A0, 0x54E85463, 0x4DF36522, + 0x02B2F3E5, 0x1BA9C2A4, 0x30849167, 0x299FA026, + 0xE4C5AEB8, 0xFDDE9FF9, 0xD6F3CC3A, 0xCFE8FD7B, + 0x80A96BBC, 0x99B25AFD, 0xB29F093E, 0xAB84387F, + 0x2C1C24B0, 0x350715F1, 0x1E2A4632, 0x07317773, + 0x4870E1B4, 0x516BD0F5, 0x7A468336, 0x635DB277, + 0xCBFAD74E, 0xD2E1E60F, 0xF9CCB5CC, 0xE0D7848D, + 0xAF96124A, 0xB68D230B, 0x9DA070C8, 0x84BB4189, + 0x03235D46, 0x1A386C07, 0x31153FC4, 0x280E0E85, + 0x674F9842, 0x7E54A903, 0x5579FAC0, 0x4C62CB81, + 0x8138C51F, 0x9823F45E, 0xB30EA79D, 0xAA1596DC, + 0xE554001B, 0xFC4F315A, 0xD7626299, 0xCE7953D8, + 0x49E14F17, 0x50FA7E56, 0x7BD72D95, 0x62CC1CD4, + 0x2D8D8A13, 0x3496BB52, 0x1FBBE891, 0x06A0D9D0, + 0x5E7EF3EC, 0x4765C2AD, 0x6C48916E, 0x7553A02F, + 0x3A1236E8, 0x230907A9, 0x0824546A, 0x113F652B, + 0x96A779E4, 0x8FBC48A5, 0xA4911B66, 0xBD8A2A27, + 0xF2CBBCE0, 0xEBD08DA1, 0xC0FDDE62, 0xD9E6EF23, + 0x14BCE1BD, 0x0DA7D0FC, 0x268A833F, 0x3F91B27E, + 0x70D024B9, 0x69CB15F8, 0x42E6463B, 0x5BFD777A, + 0xDC656BB5, 0xC57E5AF4, 0xEE530937, 0xF7483876, + 0xB809AEB1, 0xA1129FF0, 0x8A3FCC33, 0x9324FD72 + }, { + 0x00000000, 0x01C26A37, 0x0384D46E, 0x0246BE59, + 0x0709A8DC, 0x06CBC2EB, 0x048D7CB2, 0x054F1685, + 0x0E1351B8, 0x0FD13B8F, 0x0D9785D6, 0x0C55EFE1, + 0x091AF964, 0x08D89353, 0x0A9E2D0A, 0x0B5C473D, + 0x1C26A370, 0x1DE4C947, 0x1FA2771E, 0x1E601D29, + 0x1B2F0BAC, 0x1AED619B, 0x18ABDFC2, 0x1969B5F5, + 0x1235F2C8, 0x13F798FF, 0x11B126A6, 0x10734C91, + 0x153C5A14, 0x14FE3023, 0x16B88E7A, 0x177AE44D, + 0x384D46E0, 0x398F2CD7, 0x3BC9928E, 0x3A0BF8B9, + 0x3F44EE3C, 0x3E86840B, 0x3CC03A52, 0x3D025065, + 0x365E1758, 0x379C7D6F, 0x35DAC336, 0x3418A901, + 0x3157BF84, 0x3095D5B3, 0x32D36BEA, 0x331101DD, + 0x246BE590, 0x25A98FA7, 0x27EF31FE, 0x262D5BC9, + 0x23624D4C, 0x22A0277B, 0x20E69922, 0x2124F315, + 0x2A78B428, 0x2BBADE1F, 0x29FC6046, 0x283E0A71, + 0x2D711CF4, 0x2CB376C3, 0x2EF5C89A, 0x2F37A2AD, + 0x709A8DC0, 0x7158E7F7, 0x731E59AE, 0x72DC3399, + 0x7793251C, 0x76514F2B, 0x7417F172, 0x75D59B45, + 0x7E89DC78, 0x7F4BB64F, 0x7D0D0816, 0x7CCF6221, + 0x798074A4, 0x78421E93, 0x7A04A0CA, 0x7BC6CAFD, + 0x6CBC2EB0, 0x6D7E4487, 0x6F38FADE, 0x6EFA90E9, + 0x6BB5866C, 0x6A77EC5B, 0x68315202, 0x69F33835, + 0x62AF7F08, 0x636D153F, 0x612BAB66, 0x60E9C151, + 0x65A6D7D4, 0x6464BDE3, 0x662203BA, 0x67E0698D, + 0x48D7CB20, 0x4915A117, 0x4B531F4E, 0x4A917579, + 0x4FDE63FC, 0x4E1C09CB, 0x4C5AB792, 0x4D98DDA5, + 0x46C49A98, 0x4706F0AF, 0x45404EF6, 0x448224C1, + 0x41CD3244, 0x400F5873, 0x4249E62A, 0x438B8C1D, + 0x54F16850, 0x55330267, 0x5775BC3E, 0x56B7D609, + 0x53F8C08C, 0x523AAABB, 0x507C14E2, 0x51BE7ED5, + 0x5AE239E8, 0x5B2053DF, 0x5966ED86, 0x58A487B1, + 0x5DEB9134, 0x5C29FB03, 0x5E6F455A, 0x5FAD2F6D, + 0xE1351B80, 0xE0F771B7, 0xE2B1CFEE, 0xE373A5D9, + 0xE63CB35C, 0xE7FED96B, 0xE5B86732, 0xE47A0D05, + 0xEF264A38, 0xEEE4200F, 0xECA29E56, 0xED60F461, + 0xE82FE2E4, 0xE9ED88D3, 0xEBAB368A, 0xEA695CBD, + 0xFD13B8F0, 0xFCD1D2C7, 0xFE976C9E, 0xFF5506A9, + 0xFA1A102C, 0xFBD87A1B, 0xF99EC442, 0xF85CAE75, + 0xF300E948, 0xF2C2837F, 0xF0843D26, 0xF1465711, + 0xF4094194, 0xF5CB2BA3, 0xF78D95FA, 0xF64FFFCD, + 0xD9785D60, 0xD8BA3757, 0xDAFC890E, 0xDB3EE339, + 0xDE71F5BC, 0xDFB39F8B, 0xDDF521D2, 0xDC374BE5, + 0xD76B0CD8, 0xD6A966EF, 0xD4EFD8B6, 0xD52DB281, + 0xD062A404, 0xD1A0CE33, 0xD3E6706A, 0xD2241A5D, + 0xC55EFE10, 0xC49C9427, 0xC6DA2A7E, 0xC7184049, + 0xC25756CC, 0xC3953CFB, 0xC1D382A2, 0xC011E895, + 0xCB4DAFA8, 0xCA8FC59F, 0xC8C97BC6, 0xC90B11F1, + 0xCC440774, 0xCD866D43, 0xCFC0D31A, 0xCE02B92D, + 0x91AF9640, 0x906DFC77, 0x922B422E, 0x93E92819, + 0x96A63E9C, 0x976454AB, 0x9522EAF2, 0x94E080C5, + 0x9FBCC7F8, 0x9E7EADCF, 0x9C381396, 0x9DFA79A1, + 0x98B56F24, 0x99770513, 0x9B31BB4A, 0x9AF3D17D, + 0x8D893530, 0x8C4B5F07, 0x8E0DE15E, 0x8FCF8B69, + 0x8A809DEC, 0x8B42F7DB, 0x89044982, 0x88C623B5, + 0x839A6488, 0x82580EBF, 0x801EB0E6, 0x81DCDAD1, + 0x8493CC54, 0x8551A663, 0x8717183A, 0x86D5720D, + 0xA9E2D0A0, 0xA820BA97, 0xAA6604CE, 0xABA46EF9, + 0xAEEB787C, 0xAF29124B, 0xAD6FAC12, 0xACADC625, + 0xA7F18118, 0xA633EB2F, 0xA4755576, 0xA5B73F41, + 0xA0F829C4, 0xA13A43F3, 0xA37CFDAA, 0xA2BE979D, + 0xB5C473D0, 0xB40619E7, 0xB640A7BE, 0xB782CD89, + 0xB2CDDB0C, 0xB30FB13B, 0xB1490F62, 0xB08B6555, + 0xBBD72268, 0xBA15485F, 0xB853F606, 0xB9919C31, + 0xBCDE8AB4, 0xBD1CE083, 0xBF5A5EDA, 0xBE9834ED + }, { + 0x00000000, 0xB8BC6765, 0xAA09C88B, 0x12B5AFEE, + 0x8F629757, 0x37DEF032, 0x256B5FDC, 0x9DD738B9, + 0xC5B428EF, 0x7D084F8A, 0x6FBDE064, 0xD7018701, + 0x4AD6BFB8, 0xF26AD8DD, 0xE0DF7733, 0x58631056, + 0x5019579F, 0xE8A530FA, 0xFA109F14, 0x42ACF871, + 0xDF7BC0C8, 0x67C7A7AD, 0x75720843, 0xCDCE6F26, + 0x95AD7F70, 0x2D111815, 0x3FA4B7FB, 0x8718D09E, + 0x1ACFE827, 0xA2738F42, 0xB0C620AC, 0x087A47C9, + 0xA032AF3E, 0x188EC85B, 0x0A3B67B5, 0xB28700D0, + 0x2F503869, 0x97EC5F0C, 0x8559F0E2, 0x3DE59787, + 0x658687D1, 0xDD3AE0B4, 0xCF8F4F5A, 0x7733283F, + 0xEAE41086, 0x525877E3, 0x40EDD80D, 0xF851BF68, + 0xF02BF8A1, 0x48979FC4, 0x5A22302A, 0xE29E574F, + 0x7F496FF6, 0xC7F50893, 0xD540A77D, 0x6DFCC018, + 0x359FD04E, 0x8D23B72B, 0x9F9618C5, 0x272A7FA0, + 0xBAFD4719, 0x0241207C, 0x10F48F92, 0xA848E8F7, + 0x9B14583D, 0x23A83F58, 0x311D90B6, 0x89A1F7D3, + 0x1476CF6A, 0xACCAA80F, 0xBE7F07E1, 0x06C36084, + 0x5EA070D2, 0xE61C17B7, 0xF4A9B859, 0x4C15DF3C, + 0xD1C2E785, 0x697E80E0, 0x7BCB2F0E, 0xC377486B, + 0xCB0D0FA2, 0x73B168C7, 0x6104C729, 0xD9B8A04C, + 0x446F98F5, 0xFCD3FF90, 0xEE66507E, 0x56DA371B, + 0x0EB9274D, 0xB6054028, 0xA4B0EFC6, 0x1C0C88A3, + 0x81DBB01A, 0x3967D77F, 0x2BD27891, 0x936E1FF4, + 0x3B26F703, 0x839A9066, 0x912F3F88, 0x299358ED, + 0xB4446054, 0x0CF80731, 0x1E4DA8DF, 0xA6F1CFBA, + 0xFE92DFEC, 0x462EB889, 0x549B1767, 0xEC277002, + 0x71F048BB, 0xC94C2FDE, 0xDBF98030, 0x6345E755, + 0x6B3FA09C, 0xD383C7F9, 0xC1366817, 0x798A0F72, + 0xE45D37CB, 0x5CE150AE, 0x4E54FF40, 0xF6E89825, + 0xAE8B8873, 0x1637EF16, 0x048240F8, 0xBC3E279D, + 0x21E91F24, 0x99557841, 0x8BE0D7AF, 0x335CB0CA, + 0xED59B63B, 0x55E5D15E, 0x47507EB0, 0xFFEC19D5, + 0x623B216C, 0xDA874609, 0xC832E9E7, 0x708E8E82, + 0x28ED9ED4, 0x9051F9B1, 0x82E4565F, 0x3A58313A, + 0xA78F0983, 0x1F336EE6, 0x0D86C108, 0xB53AA66D, + 0xBD40E1A4, 0x05FC86C1, 0x1749292F, 0xAFF54E4A, + 0x322276F3, 0x8A9E1196, 0x982BBE78, 0x2097D91D, + 0x78F4C94B, 0xC048AE2E, 0xD2FD01C0, 0x6A4166A5, + 0xF7965E1C, 0x4F2A3979, 0x5D9F9697, 0xE523F1F2, + 0x4D6B1905, 0xF5D77E60, 0xE762D18E, 0x5FDEB6EB, + 0xC2098E52, 0x7AB5E937, 0x680046D9, 0xD0BC21BC, + 0x88DF31EA, 0x3063568F, 0x22D6F961, 0x9A6A9E04, + 0x07BDA6BD, 0xBF01C1D8, 0xADB46E36, 0x15080953, + 0x1D724E9A, 0xA5CE29FF, 0xB77B8611, 0x0FC7E174, + 0x9210D9CD, 0x2AACBEA8, 0x38191146, 0x80A57623, + 0xD8C66675, 0x607A0110, 0x72CFAEFE, 0xCA73C99B, + 0x57A4F122, 0xEF189647, 0xFDAD39A9, 0x45115ECC, + 0x764DEE06, 0xCEF18963, 0xDC44268D, 0x64F841E8, + 0xF92F7951, 0x41931E34, 0x5326B1DA, 0xEB9AD6BF, + 0xB3F9C6E9, 0x0B45A18C, 0x19F00E62, 0xA14C6907, + 0x3C9B51BE, 0x842736DB, 0x96929935, 0x2E2EFE50, + 0x2654B999, 0x9EE8DEFC, 0x8C5D7112, 0x34E11677, + 0xA9362ECE, 0x118A49AB, 0x033FE645, 0xBB838120, + 0xE3E09176, 0x5B5CF613, 0x49E959FD, 0xF1553E98, + 0x6C820621, 0xD43E6144, 0xC68BCEAA, 0x7E37A9CF, + 0xD67F4138, 0x6EC3265D, 0x7C7689B3, 0xC4CAEED6, + 0x591DD66F, 0xE1A1B10A, 0xF3141EE4, 0x4BA87981, + 0x13CB69D7, 0xAB770EB2, 0xB9C2A15C, 0x017EC639, + 0x9CA9FE80, 0x241599E5, 0x36A0360B, 0x8E1C516E, + 0x866616A7, 0x3EDA71C2, 0x2C6FDE2C, 0x94D3B949, + 0x090481F0, 0xB1B8E695, 0xA30D497B, 0x1BB12E1E, + 0x43D23E48, 0xFB6E592D, 0xE9DBF6C3, 0x516791A6, + 0xCCB0A91F, 0x740CCE7A, 0x66B96194, 0xDE0506F1 + }, { + 0x00000000, 0x3D6029B0, 0x7AC05360, 0x47A07AD0, + 0xF580A6C0, 0xC8E08F70, 0x8F40F5A0, 0xB220DC10, + 0x30704BC1, 0x0D106271, 0x4AB018A1, 0x77D03111, + 0xC5F0ED01, 0xF890C4B1, 0xBF30BE61, 0x825097D1, + 0x60E09782, 0x5D80BE32, 0x1A20C4E2, 0x2740ED52, + 0x95603142, 0xA80018F2, 0xEFA06222, 0xD2C04B92, + 0x5090DC43, 0x6DF0F5F3, 0x2A508F23, 0x1730A693, + 0xA5107A83, 0x98705333, 0xDFD029E3, 0xE2B00053, + 0xC1C12F04, 0xFCA106B4, 0xBB017C64, 0x866155D4, + 0x344189C4, 0x0921A074, 0x4E81DAA4, 0x73E1F314, + 0xF1B164C5, 0xCCD14D75, 0x8B7137A5, 0xB6111E15, + 0x0431C205, 0x3951EBB5, 0x7EF19165, 0x4391B8D5, + 0xA121B886, 0x9C419136, 0xDBE1EBE6, 0xE681C256, + 0x54A11E46, 0x69C137F6, 0x2E614D26, 0x13016496, + 0x9151F347, 0xAC31DAF7, 0xEB91A027, 0xD6F18997, + 0x64D15587, 0x59B17C37, 0x1E1106E7, 0x23712F57, + 0x58F35849, 0x659371F9, 0x22330B29, 0x1F532299, + 0xAD73FE89, 0x9013D739, 0xD7B3ADE9, 0xEAD38459, + 0x68831388, 0x55E33A38, 0x124340E8, 0x2F236958, + 0x9D03B548, 0xA0639CF8, 0xE7C3E628, 0xDAA3CF98, + 0x3813CFCB, 0x0573E67B, 0x42D39CAB, 0x7FB3B51B, + 0xCD93690B, 0xF0F340BB, 0xB7533A6B, 0x8A3313DB, + 0x0863840A, 0x3503ADBA, 0x72A3D76A, 0x4FC3FEDA, + 0xFDE322CA, 0xC0830B7A, 0x872371AA, 0xBA43581A, + 0x9932774D, 0xA4525EFD, 0xE3F2242D, 0xDE920D9D, + 0x6CB2D18D, 0x51D2F83D, 0x167282ED, 0x2B12AB5D, + 0xA9423C8C, 0x9422153C, 0xD3826FEC, 0xEEE2465C, + 0x5CC29A4C, 0x61A2B3FC, 0x2602C92C, 0x1B62E09C, + 0xF9D2E0CF, 0xC4B2C97F, 0x8312B3AF, 0xBE729A1F, + 0x0C52460F, 0x31326FBF, 0x7692156F, 0x4BF23CDF, + 0xC9A2AB0E, 0xF4C282BE, 0xB362F86E, 0x8E02D1DE, + 0x3C220DCE, 0x0142247E, 0x46E25EAE, 0x7B82771E, + 0xB1E6B092, 0x8C869922, 0xCB26E3F2, 0xF646CA42, + 0x44661652, 0x79063FE2, 0x3EA64532, 0x03C66C82, + 0x8196FB53, 0xBCF6D2E3, 0xFB56A833, 0xC6368183, + 0x74165D93, 0x49767423, 0x0ED60EF3, 0x33B62743, + 0xD1062710, 0xEC660EA0, 0xABC67470, 0x96A65DC0, + 0x248681D0, 0x19E6A860, 0x5E46D2B0, 0x6326FB00, + 0xE1766CD1, 0xDC164561, 0x9BB63FB1, 0xA6D61601, + 0x14F6CA11, 0x2996E3A1, 0x6E369971, 0x5356B0C1, + 0x70279F96, 0x4D47B626, 0x0AE7CCF6, 0x3787E546, + 0x85A73956, 0xB8C710E6, 0xFF676A36, 0xC2074386, + 0x4057D457, 0x7D37FDE7, 0x3A978737, 0x07F7AE87, + 0xB5D77297, 0x88B75B27, 0xCF1721F7, 0xF2770847, + 0x10C70814, 0x2DA721A4, 0x6A075B74, 0x576772C4, + 0xE547AED4, 0xD8278764, 0x9F87FDB4, 0xA2E7D404, + 0x20B743D5, 0x1DD76A65, 0x5A7710B5, 0x67173905, + 0xD537E515, 0xE857CCA5, 0xAFF7B675, 0x92979FC5, + 0xE915E8DB, 0xD475C16B, 0x93D5BBBB, 0xAEB5920B, + 0x1C954E1B, 0x21F567AB, 0x66551D7B, 0x5B3534CB, + 0xD965A31A, 0xE4058AAA, 0xA3A5F07A, 0x9EC5D9CA, + 0x2CE505DA, 0x11852C6A, 0x562556BA, 0x6B457F0A, + 0x89F57F59, 0xB49556E9, 0xF3352C39, 0xCE550589, + 0x7C75D999, 0x4115F029, 0x06B58AF9, 0x3BD5A349, + 0xB9853498, 0x84E51D28, 0xC34567F8, 0xFE254E48, + 0x4C059258, 0x7165BBE8, 0x36C5C138, 0x0BA5E888, + 0x28D4C7DF, 0x15B4EE6F, 0x521494BF, 0x6F74BD0F, + 0xDD54611F, 0xE03448AF, 0xA794327F, 0x9AF41BCF, + 0x18A48C1E, 0x25C4A5AE, 0x6264DF7E, 0x5F04F6CE, + 0xED242ADE, 0xD044036E, 0x97E479BE, 0xAA84500E, + 0x4834505D, 0x755479ED, 0x32F4033D, 0x0F942A8D, + 0xBDB4F69D, 0x80D4DF2D, 0xC774A5FD, 0xFA148C4D, + 0x78441B9C, 0x4524322C, 0x028448FC, 0x3FE4614C, + 0x8DC4BD5C, 0xB0A494EC, 0xF704EE3C, 0xCA64C78C + }, { + 0x00000000, 0xCB5CD3A5, 0x4DC8A10B, 0x869472AE, + 0x9B914216, 0x50CD91B3, 0xD659E31D, 0x1D0530B8, + 0xEC53826D, 0x270F51C8, 0xA19B2366, 0x6AC7F0C3, + 0x77C2C07B, 0xBC9E13DE, 0x3A0A6170, 0xF156B2D5, + 0x03D6029B, 0xC88AD13E, 0x4E1EA390, 0x85427035, + 0x9847408D, 0x531B9328, 0xD58FE186, 0x1ED33223, + 0xEF8580F6, 0x24D95353, 0xA24D21FD, 0x6911F258, + 0x7414C2E0, 0xBF481145, 0x39DC63EB, 0xF280B04E, + 0x07AC0536, 0xCCF0D693, 0x4A64A43D, 0x81387798, + 0x9C3D4720, 0x57619485, 0xD1F5E62B, 0x1AA9358E, + 0xEBFF875B, 0x20A354FE, 0xA6372650, 0x6D6BF5F5, + 0x706EC54D, 0xBB3216E8, 0x3DA66446, 0xF6FAB7E3, + 0x047A07AD, 0xCF26D408, 0x49B2A6A6, 0x82EE7503, + 0x9FEB45BB, 0x54B7961E, 0xD223E4B0, 0x197F3715, + 0xE82985C0, 0x23755665, 0xA5E124CB, 0x6EBDF76E, + 0x73B8C7D6, 0xB8E41473, 0x3E7066DD, 0xF52CB578, + 0x0F580A6C, 0xC404D9C9, 0x4290AB67, 0x89CC78C2, + 0x94C9487A, 0x5F959BDF, 0xD901E971, 0x125D3AD4, + 0xE30B8801, 0x28575BA4, 0xAEC3290A, 0x659FFAAF, + 0x789ACA17, 0xB3C619B2, 0x35526B1C, 0xFE0EB8B9, + 0x0C8E08F7, 0xC7D2DB52, 0x4146A9FC, 0x8A1A7A59, + 0x971F4AE1, 0x5C439944, 0xDAD7EBEA, 0x118B384F, + 0xE0DD8A9A, 0x2B81593F, 0xAD152B91, 0x6649F834, + 0x7B4CC88C, 0xB0101B29, 0x36846987, 0xFDD8BA22, + 0x08F40F5A, 0xC3A8DCFF, 0x453CAE51, 0x8E607DF4, + 0x93654D4C, 0x58399EE9, 0xDEADEC47, 0x15F13FE2, + 0xE4A78D37, 0x2FFB5E92, 0xA96F2C3C, 0x6233FF99, + 0x7F36CF21, 0xB46A1C84, 0x32FE6E2A, 0xF9A2BD8F, + 0x0B220DC1, 0xC07EDE64, 0x46EAACCA, 0x8DB67F6F, + 0x90B34FD7, 0x5BEF9C72, 0xDD7BEEDC, 0x16273D79, + 0xE7718FAC, 0x2C2D5C09, 0xAAB92EA7, 0x61E5FD02, + 0x7CE0CDBA, 0xB7BC1E1F, 0x31286CB1, 0xFA74BF14, + 0x1EB014D8, 0xD5ECC77D, 0x5378B5D3, 0x98246676, + 0x852156CE, 0x4E7D856B, 0xC8E9F7C5, 0x03B52460, + 0xF2E396B5, 0x39BF4510, 0xBF2B37BE, 0x7477E41B, + 0x6972D4A3, 0xA22E0706, 0x24BA75A8, 0xEFE6A60D, + 0x1D661643, 0xD63AC5E6, 0x50AEB748, 0x9BF264ED, + 0x86F75455, 0x4DAB87F0, 0xCB3FF55E, 0x006326FB, + 0xF135942E, 0x3A69478B, 0xBCFD3525, 0x77A1E680, + 0x6AA4D638, 0xA1F8059D, 0x276C7733, 0xEC30A496, + 0x191C11EE, 0xD240C24B, 0x54D4B0E5, 0x9F886340, + 0x828D53F8, 0x49D1805D, 0xCF45F2F3, 0x04192156, + 0xF54F9383, 0x3E134026, 0xB8873288, 0x73DBE12D, + 0x6EDED195, 0xA5820230, 0x2316709E, 0xE84AA33B, + 0x1ACA1375, 0xD196C0D0, 0x5702B27E, 0x9C5E61DB, + 0x815B5163, 0x4A0782C6, 0xCC93F068, 0x07CF23CD, + 0xF6999118, 0x3DC542BD, 0xBB513013, 0x700DE3B6, + 0x6D08D30E, 0xA65400AB, 0x20C07205, 0xEB9CA1A0, + 0x11E81EB4, 0xDAB4CD11, 0x5C20BFBF, 0x977C6C1A, + 0x8A795CA2, 0x41258F07, 0xC7B1FDA9, 0x0CED2E0C, + 0xFDBB9CD9, 0x36E74F7C, 0xB0733DD2, 0x7B2FEE77, + 0x662ADECF, 0xAD760D6A, 0x2BE27FC4, 0xE0BEAC61, + 0x123E1C2F, 0xD962CF8A, 0x5FF6BD24, 0x94AA6E81, + 0x89AF5E39, 0x42F38D9C, 0xC467FF32, 0x0F3B2C97, + 0xFE6D9E42, 0x35314DE7, 0xB3A53F49, 0x78F9ECEC, + 0x65FCDC54, 0xAEA00FF1, 0x28347D5F, 0xE368AEFA, + 0x16441B82, 0xDD18C827, 0x5B8CBA89, 0x90D0692C, + 0x8DD55994, 0x46898A31, 0xC01DF89F, 0x0B412B3A, + 0xFA1799EF, 0x314B4A4A, 0xB7DF38E4, 0x7C83EB41, + 0x6186DBF9, 0xAADA085C, 0x2C4E7AF2, 0xE712A957, + 0x15921919, 0xDECECABC, 0x585AB812, 0x93066BB7, + 0x8E035B0F, 0x455F88AA, 0xC3CBFA04, 0x089729A1, + 0xF9C19B74, 0x329D48D1, 0xB4093A7F, 0x7F55E9DA, + 0x6250D962, 0xA90C0AC7, 0x2F987869, 0xE4C4ABCC + }, { + 0x00000000, 0xA6770BB4, 0x979F1129, 0x31E81A9D, + 0xF44F2413, 0x52382FA7, 0x63D0353A, 0xC5A73E8E, + 0x33EF4E67, 0x959845D3, 0xA4705F4E, 0x020754FA, + 0xC7A06A74, 0x61D761C0, 0x503F7B5D, 0xF64870E9, + 0x67DE9CCE, 0xC1A9977A, 0xF0418DE7, 0x56368653, + 0x9391B8DD, 0x35E6B369, 0x040EA9F4, 0xA279A240, + 0x5431D2A9, 0xF246D91D, 0xC3AEC380, 0x65D9C834, + 0xA07EF6BA, 0x0609FD0E, 0x37E1E793, 0x9196EC27, + 0xCFBD399C, 0x69CA3228, 0x582228B5, 0xFE552301, + 0x3BF21D8F, 0x9D85163B, 0xAC6D0CA6, 0x0A1A0712, + 0xFC5277FB, 0x5A257C4F, 0x6BCD66D2, 0xCDBA6D66, + 0x081D53E8, 0xAE6A585C, 0x9F8242C1, 0x39F54975, + 0xA863A552, 0x0E14AEE6, 0x3FFCB47B, 0x998BBFCF, + 0x5C2C8141, 0xFA5B8AF5, 0xCBB39068, 0x6DC49BDC, + 0x9B8CEB35, 0x3DFBE081, 0x0C13FA1C, 0xAA64F1A8, + 0x6FC3CF26, 0xC9B4C492, 0xF85CDE0F, 0x5E2BD5BB, + 0x440B7579, 0xE27C7ECD, 0xD3946450, 0x75E36FE4, + 0xB044516A, 0x16335ADE, 0x27DB4043, 0x81AC4BF7, + 0x77E43B1E, 0xD19330AA, 0xE07B2A37, 0x460C2183, + 0x83AB1F0D, 0x25DC14B9, 0x14340E24, 0xB2430590, + 0x23D5E9B7, 0x85A2E203, 0xB44AF89E, 0x123DF32A, + 0xD79ACDA4, 0x71EDC610, 0x4005DC8D, 0xE672D739, + 0x103AA7D0, 0xB64DAC64, 0x87A5B6F9, 0x21D2BD4D, + 0xE47583C3, 0x42028877, 0x73EA92EA, 0xD59D995E, + 0x8BB64CE5, 0x2DC14751, 0x1C295DCC, 0xBA5E5678, + 0x7FF968F6, 0xD98E6342, 0xE86679DF, 0x4E11726B, + 0xB8590282, 0x1E2E0936, 0x2FC613AB, 0x89B1181F, + 0x4C162691, 0xEA612D25, 0xDB8937B8, 0x7DFE3C0C, + 0xEC68D02B, 0x4A1FDB9F, 0x7BF7C102, 0xDD80CAB6, + 0x1827F438, 0xBE50FF8C, 0x8FB8E511, 0x29CFEEA5, + 0xDF879E4C, 0x79F095F8, 0x48188F65, 0xEE6F84D1, + 0x2BC8BA5F, 0x8DBFB1EB, 0xBC57AB76, 0x1A20A0C2, + 0x8816EAF2, 0x2E61E146, 0x1F89FBDB, 0xB9FEF06F, + 0x7C59CEE1, 0xDA2EC555, 0xEBC6DFC8, 0x4DB1D47C, + 0xBBF9A495, 0x1D8EAF21, 0x2C66B5BC, 0x8A11BE08, + 0x4FB68086, 0xE9C18B32, 0xD82991AF, 0x7E5E9A1B, + 0xEFC8763C, 0x49BF7D88, 0x78576715, 0xDE206CA1, + 0x1B87522F, 0xBDF0599B, 0x8C184306, 0x2A6F48B2, + 0xDC27385B, 0x7A5033EF, 0x4BB82972, 0xEDCF22C6, + 0x28681C48, 0x8E1F17FC, 0xBFF70D61, 0x198006D5, + 0x47ABD36E, 0xE1DCD8DA, 0xD034C247, 0x7643C9F3, + 0xB3E4F77D, 0x1593FCC9, 0x247BE654, 0x820CEDE0, + 0x74449D09, 0xD23396BD, 0xE3DB8C20, 0x45AC8794, + 0x800BB91A, 0x267CB2AE, 0x1794A833, 0xB1E3A387, + 0x20754FA0, 0x86024414, 0xB7EA5E89, 0x119D553D, + 0xD43A6BB3, 0x724D6007, 0x43A57A9A, 0xE5D2712E, + 0x139A01C7, 0xB5ED0A73, 0x840510EE, 0x22721B5A, + 0xE7D525D4, 0x41A22E60, 0x704A34FD, 0xD63D3F49, + 0xCC1D9F8B, 0x6A6A943F, 0x5B828EA2, 0xFDF58516, + 0x3852BB98, 0x9E25B02C, 0xAFCDAAB1, 0x09BAA105, + 0xFFF2D1EC, 0x5985DA58, 0x686DC0C5, 0xCE1ACB71, + 0x0BBDF5FF, 0xADCAFE4B, 0x9C22E4D6, 0x3A55EF62, + 0xABC30345, 0x0DB408F1, 0x3C5C126C, 0x9A2B19D8, + 0x5F8C2756, 0xF9FB2CE2, 0xC813367F, 0x6E643DCB, + 0x982C4D22, 0x3E5B4696, 0x0FB35C0B, 0xA9C457BF, + 0x6C636931, 0xCA146285, 0xFBFC7818, 0x5D8B73AC, + 0x03A0A617, 0xA5D7ADA3, 0x943FB73E, 0x3248BC8A, + 0xF7EF8204, 0x519889B0, 0x6070932D, 0xC6079899, + 0x304FE870, 0x9638E3C4, 0xA7D0F959, 0x01A7F2ED, + 0xC400CC63, 0x6277C7D7, 0x539FDD4A, 0xF5E8D6FE, + 0x647E3AD9, 0xC209316D, 0xF3E12BF0, 0x55962044, + 0x90311ECA, 0x3646157E, 0x07AE0FE3, 0xA1D90457, + 0x579174BE, 0xF1E67F0A, 0xC00E6597, 0x66796E23, + 0xA3DE50AD, 0x05A95B19, 0x34414184, 0x92364A30 + }, { + 0x00000000, 0xCCAA009E, 0x4225077D, 0x8E8F07E3, + 0x844A0EFA, 0x48E00E64, 0xC66F0987, 0x0AC50919, + 0xD3E51BB5, 0x1F4F1B2B, 0x91C01CC8, 0x5D6A1C56, + 0x57AF154F, 0x9B0515D1, 0x158A1232, 0xD92012AC, + 0x7CBB312B, 0xB01131B5, 0x3E9E3656, 0xF23436C8, + 0xF8F13FD1, 0x345B3F4F, 0xBAD438AC, 0x767E3832, + 0xAF5E2A9E, 0x63F42A00, 0xED7B2DE3, 0x21D12D7D, + 0x2B142464, 0xE7BE24FA, 0x69312319, 0xA59B2387, + 0xF9766256, 0x35DC62C8, 0xBB53652B, 0x77F965B5, + 0x7D3C6CAC, 0xB1966C32, 0x3F196BD1, 0xF3B36B4F, + 0x2A9379E3, 0xE639797D, 0x68B67E9E, 0xA41C7E00, + 0xAED97719, 0x62737787, 0xECFC7064, 0x205670FA, + 0x85CD537D, 0x496753E3, 0xC7E85400, 0x0B42549E, + 0x01875D87, 0xCD2D5D19, 0x43A25AFA, 0x8F085A64, + 0x562848C8, 0x9A824856, 0x140D4FB5, 0xD8A74F2B, + 0xD2624632, 0x1EC846AC, 0x9047414F, 0x5CED41D1, + 0x299DC2ED, 0xE537C273, 0x6BB8C590, 0xA712C50E, + 0xADD7CC17, 0x617DCC89, 0xEFF2CB6A, 0x2358CBF4, + 0xFA78D958, 0x36D2D9C6, 0xB85DDE25, 0x74F7DEBB, + 0x7E32D7A2, 0xB298D73C, 0x3C17D0DF, 0xF0BDD041, + 0x5526F3C6, 0x998CF358, 0x1703F4BB, 0xDBA9F425, + 0xD16CFD3C, 0x1DC6FDA2, 0x9349FA41, 0x5FE3FADF, + 0x86C3E873, 0x4A69E8ED, 0xC4E6EF0E, 0x084CEF90, + 0x0289E689, 0xCE23E617, 0x40ACE1F4, 0x8C06E16A, + 0xD0EBA0BB, 0x1C41A025, 0x92CEA7C6, 0x5E64A758, + 0x54A1AE41, 0x980BAEDF, 0x1684A93C, 0xDA2EA9A2, + 0x030EBB0E, 0xCFA4BB90, 0x412BBC73, 0x8D81BCED, + 0x8744B5F4, 0x4BEEB56A, 0xC561B289, 0x09CBB217, + 0xAC509190, 0x60FA910E, 0xEE7596ED, 0x22DF9673, + 0x281A9F6A, 0xE4B09FF4, 0x6A3F9817, 0xA6959889, + 0x7FB58A25, 0xB31F8ABB, 0x3D908D58, 0xF13A8DC6, + 0xFBFF84DF, 0x37558441, 0xB9DA83A2, 0x7570833C, + 0x533B85DA, 0x9F918544, 0x111E82A7, 0xDDB48239, + 0xD7718B20, 0x1BDB8BBE, 0x95548C5D, 0x59FE8CC3, + 0x80DE9E6F, 0x4C749EF1, 0xC2FB9912, 0x0E51998C, + 0x04949095, 0xC83E900B, 0x46B197E8, 0x8A1B9776, + 0x2F80B4F1, 0xE32AB46F, 0x6DA5B38C, 0xA10FB312, + 0xABCABA0B, 0x6760BA95, 0xE9EFBD76, 0x2545BDE8, + 0xFC65AF44, 0x30CFAFDA, 0xBE40A839, 0x72EAA8A7, + 0x782FA1BE, 0xB485A120, 0x3A0AA6C3, 0xF6A0A65D, + 0xAA4DE78C, 0x66E7E712, 0xE868E0F1, 0x24C2E06F, + 0x2E07E976, 0xE2ADE9E8, 0x6C22EE0B, 0xA088EE95, + 0x79A8FC39, 0xB502FCA7, 0x3B8DFB44, 0xF727FBDA, + 0xFDE2F2C3, 0x3148F25D, 0xBFC7F5BE, 0x736DF520, + 0xD6F6D6A7, 0x1A5CD639, 0x94D3D1DA, 0x5879D144, + 0x52BCD85D, 0x9E16D8C3, 0x1099DF20, 0xDC33DFBE, + 0x0513CD12, 0xC9B9CD8C, 0x4736CA6F, 0x8B9CCAF1, + 0x8159C3E8, 0x4DF3C376, 0xC37CC495, 0x0FD6C40B, + 0x7AA64737, 0xB60C47A9, 0x3883404A, 0xF42940D4, + 0xFEEC49CD, 0x32464953, 0xBCC94EB0, 0x70634E2E, + 0xA9435C82, 0x65E95C1C, 0xEB665BFF, 0x27CC5B61, + 0x2D095278, 0xE1A352E6, 0x6F2C5505, 0xA386559B, + 0x061D761C, 0xCAB77682, 0x44387161, 0x889271FF, + 0x825778E6, 0x4EFD7878, 0xC0727F9B, 0x0CD87F05, + 0xD5F86DA9, 0x19526D37, 0x97DD6AD4, 0x5B776A4A, + 0x51B26353, 0x9D1863CD, 0x1397642E, 0xDF3D64B0, + 0x83D02561, 0x4F7A25FF, 0xC1F5221C, 0x0D5F2282, + 0x079A2B9B, 0xCB302B05, 0x45BF2CE6, 0x89152C78, + 0x50353ED4, 0x9C9F3E4A, 0x121039A9, 0xDEBA3937, + 0xD47F302E, 0x18D530B0, 0x965A3753, 0x5AF037CD, + 0xFF6B144A, 0x33C114D4, 0xBD4E1337, 0x71E413A9, + 0x7B211AB0, 0xB78B1A2E, 0x39041DCD, 0xF5AE1D53, + 0x2C8E0FFF, 0xE0240F61, 0x6EAB0882, 0xA201081C, + 0xA8C40105, 0x646E019B, 0xEAE10678, 0x264B06E6 + } +}; diff --git a/dependencies/cmliblzma/liblzma/check/crc32_tablegen.c b/dependencies/cmliblzma/liblzma/check/crc32_tablegen.c new file mode 100644 index 0000000..31a4d27 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/check/crc32_tablegen.c @@ -0,0 +1,117 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file crc32_tablegen.c +/// \brief Generate crc32_table_le.h and crc32_table_be.h +/// +/// Compiling: gcc -std=c99 -o crc32_tablegen crc32_tablegen.c +/// Add -DWORDS_BIGENDIAN to generate big endian table. +/// Add -DLZ_HASH_TABLE to generate lz_encoder_hash_table.h (little endian). +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include "../../common/tuklib_integer.h" + + +static uint32_t crc32_table[8][256]; + + +static void +init_crc32_table(void) +{ + static const uint32_t poly32 = UINT32_C(0xEDB88320); + + for (size_t s = 0; s < 8; ++s) { + for (size_t b = 0; b < 256; ++b) { + uint32_t r = s == 0 ? b : crc32_table[s - 1][b]; + + for (size_t i = 0; i < 8; ++i) { + if (r & 1) + r = (r >> 1) ^ poly32; + else + r >>= 1; + } + + crc32_table[s][b] = r; + } + } + +#ifdef WORDS_BIGENDIAN + for (size_t s = 0; s < 8; ++s) + for (size_t b = 0; b < 256; ++b) + crc32_table[s][b] = bswap32(crc32_table[s][b]); +#endif + + return; +} + + +static void +print_crc32_table(void) +{ + printf("/* This file has been automatically generated by " + "crc32_tablegen.c. */\n\n" + "const uint32_t lzma_crc32_table[8][256] = {\n\t{"); + + for (size_t s = 0; s < 8; ++s) { + for (size_t b = 0; b < 256; ++b) { + if ((b % 4) == 0) + printf("\n\t\t"); + + printf("0x%08" PRIX32, crc32_table[s][b]); + + if (b != 255) + printf(",%s", (b+1) % 4 == 0 ? "" : " "); + } + + if (s == 7) + printf("\n\t}\n};\n"); + else + printf("\n\t}, {"); + } + + return; +} + + +static void +print_lz_table(void) +{ + printf("/* This file has been automatically generated by " + "crc32_tablegen.c. */\n\n" + "const uint32_t lzma_lz_hash_table[256] = {"); + + for (size_t b = 0; b < 256; ++b) { + if ((b % 4) == 0) + printf("\n\t"); + + printf("0x%08" PRIX32, crc32_table[0][b]); + + if (b != 255) + printf(",%s", (b+1) % 4 == 0 ? "" : " "); + } + + printf("\n};\n"); + + return; +} + + +int +main(void) +{ + init_crc32_table(); + +#ifdef LZ_HASH_TABLE + print_lz_table(); +#else + print_crc32_table(); +#endif + + return 0; +} diff --git a/dependencies/cmliblzma/liblzma/check/crc32_x86.S b/dependencies/cmliblzma/liblzma/check/crc32_x86.S new file mode 100644 index 0000000..67f68a4 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/check/crc32_x86.S @@ -0,0 +1,304 @@ +/* + * Speed-optimized CRC32 using slicing-by-eight algorithm + * + * This uses only i386 instructions, but it is optimized for i686 and later + * (including e.g. Pentium II/III/IV, Athlon XP, and Core 2). For i586 + * (e.g. Pentium), slicing-by-four would be better, and even the C version + * of slicing-by-eight built with gcc -march=i586 tends to be a little bit + * better than this. Very few probably run this code on i586 or older x86 + * so this shouldn't be a problem in practice. + * + * Authors: Igor Pavlov (original version) + * Lasse Collin (AT&T syntax, PIC support, better portability) + * + * This file has been put into the public domain. + * You can do whatever you want with this file. + * + * This code needs lzma_crc32_table, which can be created using the + * following C code: + +uint32_t lzma_crc32_table[8][256]; + +void +init_table(void) +{ + // IEEE-802.3 + static const uint32_t poly32 = UINT32_C(0xEDB88320); + + // Castagnoli + // static const uint32_t poly32 = UINT32_C(0x82F63B78); + + // Koopman + // static const uint32_t poly32 = UINT32_C(0xEB31D82E); + + for (size_t s = 0; s < 8; ++s) { + for (size_t b = 0; b < 256; ++b) { + uint32_t r = s == 0 ? b : lzma_crc32_table[s - 1][b]; + + for (size_t i = 0; i < 8; ++i) { + if (r & 1) + r = (r >> 1) ^ poly32; + else + r >>= 1; + } + + lzma_crc32_table[s][b] = r; + } + } +} + + * The prototype of the CRC32 function: + * extern uint32_t lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc); + */ + +/* + * On some systems, the functions need to be prefixed. The prefix is + * usually an underscore. + */ +#ifndef __USER_LABEL_PREFIX__ +# define __USER_LABEL_PREFIX__ +#endif +#define MAKE_SYM_CAT(prefix, sym) prefix ## sym +#define MAKE_SYM(prefix, sym) MAKE_SYM_CAT(prefix, sym) +#define LZMA_CRC32 MAKE_SYM(__USER_LABEL_PREFIX__, lzma_crc32) +#define LZMA_CRC32_TABLE MAKE_SYM(__USER_LABEL_PREFIX__, lzma_crc32_table) + +/* + * Solaris assembler doesn't have .p2align, and Darwin uses .align + * differently than GNU/Linux and Solaris. + */ +#if defined(__APPLE__) || defined(__MSDOS__) +# define ALIGN(pow2, abs) .align pow2 +#else +# define ALIGN(pow2, abs) .align abs +#endif + + .text + .globl LZMA_CRC32 + +#if !defined(__APPLE__) && !defined(_WIN32) && !defined(__CYGWIN__) \ + && !defined(__MSDOS__) + .type LZMA_CRC32, @function +#endif + + ALIGN(4, 16) +LZMA_CRC32: + /* + * Register usage: + * %eax crc + * %esi buf + * %edi size or buf + size + * %ebx lzma_crc32_table + * %ebp Table index + * %ecx Temporary + * %edx Temporary + */ + pushl %ebx + pushl %esi + pushl %edi + pushl %ebp + movl 0x14(%esp), %esi /* buf */ + movl 0x18(%esp), %edi /* size */ + movl 0x1C(%esp), %eax /* crc */ + + /* + * Store the address of lzma_crc32_table to %ebx. This is needed to + * get position-independent code (PIC). + * + * The PIC macro is defined by libtool, while __PIC__ is defined + * by GCC but only on some systems. Testing for both makes it simpler + * to test this code without libtool, and keeps the code working also + * when built with libtool but using something else than GCC. + * + * I understood that libtool may define PIC on Windows even though + * the code in Windows DLLs is not PIC in sense that it is in ELF + * binaries, so we need a separate check to always use the non-PIC + * code on Windows. + */ +#if (!defined(PIC) && !defined(__PIC__)) \ + || (defined(_WIN32) || defined(__CYGWIN__)) + /* Not PIC */ + movl $ LZMA_CRC32_TABLE, %ebx +#elif defined(__APPLE__) + /* Mach-O */ + call .L_get_pc +.L_pic: + leal .L_lzma_crc32_table$non_lazy_ptr-.L_pic(%ebx), %ebx + movl (%ebx), %ebx +#else + /* ELF */ + call .L_get_pc + addl $_GLOBAL_OFFSET_TABLE_, %ebx + movl LZMA_CRC32_TABLE@GOT(%ebx), %ebx +#endif + + /* Complement the initial value. */ + notl %eax + + ALIGN(4, 16) +.L_align: + /* + * Check if there is enough input to use slicing-by-eight. + * We need 16 bytes, because the loop pre-reads eight bytes. + */ + cmpl $16, %edi + jb .L_rest + + /* Check if we have reached alignment of eight bytes. */ + testl $7, %esi + jz .L_slice + + /* Calculate CRC of the next input byte. */ + movzbl (%esi), %ebp + incl %esi + movzbl %al, %ecx + xorl %ecx, %ebp + shrl $8, %eax + xorl (%ebx, %ebp, 4), %eax + decl %edi + jmp .L_align + + ALIGN(2, 4) +.L_slice: + /* + * If we get here, there's at least 16 bytes of aligned input + * available. Make %edi multiple of eight bytes. Store the possible + * remainder over the "size" variable in the argument stack. + */ + movl %edi, 0x18(%esp) + andl $-8, %edi + subl %edi, 0x18(%esp) + + /* + * Let %edi be buf + size - 8 while running the main loop. This way + * we can compare for equality to determine when exit the loop. + */ + addl %esi, %edi + subl $8, %edi + + /* Read in the first eight aligned bytes. */ + xorl (%esi), %eax + movl 4(%esi), %ecx + movzbl %cl, %ebp + +.L_loop: + movl 0x0C00(%ebx, %ebp, 4), %edx + movzbl %ch, %ebp + xorl 0x0800(%ebx, %ebp, 4), %edx + shrl $16, %ecx + xorl 8(%esi), %edx + movzbl %cl, %ebp + xorl 0x0400(%ebx, %ebp, 4), %edx + movzbl %ch, %ebp + xorl (%ebx, %ebp, 4), %edx + movzbl %al, %ebp + + /* + * Read the next four bytes, for which the CRC is calculated + * on the next interation of the loop. + */ + movl 12(%esi), %ecx + + xorl 0x1C00(%ebx, %ebp, 4), %edx + movzbl %ah, %ebp + shrl $16, %eax + xorl 0x1800(%ebx, %ebp, 4), %edx + movzbl %ah, %ebp + movzbl %al, %eax + movl 0x1400(%ebx, %eax, 4), %eax + addl $8, %esi + xorl %edx, %eax + xorl 0x1000(%ebx, %ebp, 4), %eax + + /* Check for end of aligned input. */ + cmpl %edi, %esi + movzbl %cl, %ebp + jne .L_loop + + /* + * Process the remaining eight bytes, which we have already + * copied to %ecx and %edx. + */ + movl 0x0C00(%ebx, %ebp, 4), %edx + movzbl %ch, %ebp + xorl 0x0800(%ebx, %ebp, 4), %edx + shrl $16, %ecx + movzbl %cl, %ebp + xorl 0x0400(%ebx, %ebp, 4), %edx + movzbl %ch, %ebp + xorl (%ebx, %ebp, 4), %edx + movzbl %al, %ebp + + xorl 0x1C00(%ebx, %ebp, 4), %edx + movzbl %ah, %ebp + shrl $16, %eax + xorl 0x1800(%ebx, %ebp, 4), %edx + movzbl %ah, %ebp + movzbl %al, %eax + movl 0x1400(%ebx, %eax, 4), %eax + addl $8, %esi + xorl %edx, %eax + xorl 0x1000(%ebx, %ebp, 4), %eax + + /* Copy the number of remaining bytes to %edi. */ + movl 0x18(%esp), %edi + +.L_rest: + /* Check for end of input. */ + testl %edi, %edi + jz .L_return + + /* Calculate CRC of the next input byte. */ + movzbl (%esi), %ebp + incl %esi + movzbl %al, %ecx + xorl %ecx, %ebp + shrl $8, %eax + xorl (%ebx, %ebp, 4), %eax + decl %edi + jmp .L_rest + +.L_return: + /* Complement the final value. */ + notl %eax + + popl %ebp + popl %edi + popl %esi + popl %ebx + ret + +#if defined(PIC) || defined(__PIC__) + ALIGN(4, 16) +.L_get_pc: + movl (%esp), %ebx + ret +#endif + +#if defined(__APPLE__) && (defined(PIC) || defined(__PIC__)) + /* Mach-O PIC */ + .section __IMPORT,__pointers,non_lazy_symbol_pointers +.L_lzma_crc32_table$non_lazy_ptr: + .indirect_symbol LZMA_CRC32_TABLE + .long 0 + +#elif defined(_WIN32) || defined(__CYGWIN__) +# ifdef DLL_EXPORT + /* This is equivalent of __declspec(dllexport). */ + .section .drectve + .ascii " -export:lzma_crc32" +# endif + +#elif !defined(__MSDOS__) + /* ELF */ + .size LZMA_CRC32, .-LZMA_CRC32 +#endif + +/* + * This is needed to support non-executable stack. It's ugly to + * use __linux__ here, but I don't know a way to detect when + * we are using GNU assembler. + */ +#if defined(__ELF__) && defined(__linux__) + .section .note.GNU-stack,"",@progbits +#endif diff --git a/dependencies/cmliblzma/liblzma/check/crc64_fast.c b/dependencies/cmliblzma/liblzma/check/crc64_fast.c new file mode 100644 index 0000000..52af29e --- /dev/null +++ b/dependencies/cmliblzma/liblzma/check/crc64_fast.c @@ -0,0 +1,72 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file crc64.c +/// \brief CRC64 calculation +/// +/// Calculate the CRC64 using the slice-by-four algorithm. This is the same +/// idea that is used in crc32_fast.c, but for CRC64 we use only four tables +/// instead of eight to avoid increasing CPU cache usage. +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "check.h" +#include "crc_macros.h" + + +#ifdef WORDS_BIGENDIAN +# define A1(x) ((x) >> 56) +#else +# define A1 A +#endif + + +// See the comments in crc32_fast.c. They aren't duplicated here. +extern LZMA_API(uint64_t) +lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc) +{ + crc = ~crc; + +#ifdef WORDS_BIGENDIAN + crc = bswap64(crc); +#endif + + if (size > 4) { + while ((uintptr_t)(buf) & 3) { + crc = lzma_crc64_table[0][*buf++ ^ A1(crc)] ^ S8(crc); + --size; + } + + const uint8_t *const limit = buf + (size & ~(size_t)(3)); + size &= (size_t)(3); + + while (buf < limit) { +#ifdef WORDS_BIGENDIAN + const uint32_t tmp = (crc >> 32) + ^ *(const uint32_t *)(buf); +#else + const uint32_t tmp = crc ^ *(const uint32_t *)(buf); +#endif + buf += 4; + + crc = lzma_crc64_table[3][A(tmp)] + ^ lzma_crc64_table[2][B(tmp)] + ^ S32(crc) + ^ lzma_crc64_table[1][C(tmp)] + ^ lzma_crc64_table[0][D(tmp)]; + } + } + + while (size-- != 0) + crc = lzma_crc64_table[0][*buf++ ^ A1(crc)] ^ S8(crc); + +#ifdef WORDS_BIGENDIAN + crc = bswap64(crc); +#endif + + return ~crc; +} diff --git a/dependencies/cmliblzma/liblzma/check/crc64_small.c b/dependencies/cmliblzma/liblzma/check/crc64_small.c new file mode 100644 index 0000000..55d7231 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/check/crc64_small.c @@ -0,0 +1,53 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file crc64_small.c +/// \brief CRC64 calculation (size-optimized) +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "check.h" + + +static uint64_t crc64_table[256]; + + +static void +crc64_init(void) +{ + static const uint64_t poly64 = UINT64_C(0xC96C5795D7870F42); + + for (size_t b = 0; b < 256; ++b) { + uint64_t r = b; + for (size_t i = 0; i < 8; ++i) { + if (r & 1) + r = (r >> 1) ^ poly64; + else + r >>= 1; + } + + crc64_table[b] = r; + } + + return; +} + + +extern LZMA_API(uint64_t) +lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc) +{ + mythread_once(crc64_init); + + crc = ~crc; + + while (size != 0) { + crc = crc64_table[*buf++ ^ (crc & 0xFF)] ^ (crc >> 8); + --size; + } + + return ~crc; +} diff --git a/dependencies/cmliblzma/liblzma/check/crc64_table.c b/dependencies/cmliblzma/liblzma/check/crc64_table.c new file mode 100644 index 0000000..1fbcd94 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/check/crc64_table.c @@ -0,0 +1,19 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file crc64_table.c +/// \brief Precalculated CRC64 table with correct endianness +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "common.h" + +#ifdef WORDS_BIGENDIAN +# include "crc64_table_be.h" +#else +# include "crc64_table_le.h" +#endif diff --git a/dependencies/cmliblzma/liblzma/check/crc64_table_be.h b/dependencies/cmliblzma/liblzma/check/crc64_table_be.h new file mode 100644 index 0000000..ea074f3 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/check/crc64_table_be.h @@ -0,0 +1,521 @@ +/* This file has been automatically generated by crc64_tablegen.c. */ + +const uint64_t lzma_crc64_table[4][256] = { + { + UINT64_C(0x0000000000000000), UINT64_C(0x6F5FA703BE4C2EB3), + UINT64_C(0x5BA040A8573684F4), UINT64_C(0x34FFE7ABE97AAA47), + UINT64_C(0x335E8FFF84C3D07B), UINT64_C(0x5C0128FC3A8FFEC8), + UINT64_C(0x68FECF57D3F5548F), UINT64_C(0x07A168546DB97A3C), + UINT64_C(0x66BC1EFF0987A1F7), UINT64_C(0x09E3B9FCB7CB8F44), + UINT64_C(0x3D1C5E575EB12503), UINT64_C(0x5243F954E0FD0BB0), + UINT64_C(0x55E291008D44718C), UINT64_C(0x3ABD360333085F3F), + UINT64_C(0x0E42D1A8DA72F578), UINT64_C(0x611D76AB643EDBCB), + UINT64_C(0x4966335138A19B7D), UINT64_C(0x2639945286EDB5CE), + UINT64_C(0x12C673F96F971F89), UINT64_C(0x7D99D4FAD1DB313A), + UINT64_C(0x7A38BCAEBC624B06), UINT64_C(0x15671BAD022E65B5), + UINT64_C(0x2198FC06EB54CFF2), UINT64_C(0x4EC75B055518E141), + UINT64_C(0x2FDA2DAE31263A8A), UINT64_C(0x40858AAD8F6A1439), + UINT64_C(0x747A6D066610BE7E), UINT64_C(0x1B25CA05D85C90CD), + UINT64_C(0x1C84A251B5E5EAF1), UINT64_C(0x73DB05520BA9C442), + UINT64_C(0x4724E2F9E2D36E05), UINT64_C(0x287B45FA5C9F40B6), + UINT64_C(0x92CC66A2704237FB), UINT64_C(0xFD93C1A1CE0E1948), + UINT64_C(0xC96C260A2774B30F), UINT64_C(0xA633810999389DBC), + UINT64_C(0xA192E95DF481E780), UINT64_C(0xCECD4E5E4ACDC933), + UINT64_C(0xFA32A9F5A3B76374), UINT64_C(0x956D0EF61DFB4DC7), + UINT64_C(0xF470785D79C5960C), UINT64_C(0x9B2FDF5EC789B8BF), + UINT64_C(0xAFD038F52EF312F8), UINT64_C(0xC08F9FF690BF3C4B), + UINT64_C(0xC72EF7A2FD064677), UINT64_C(0xA87150A1434A68C4), + UINT64_C(0x9C8EB70AAA30C283), UINT64_C(0xF3D11009147CEC30), + UINT64_C(0xDBAA55F348E3AC86), UINT64_C(0xB4F5F2F0F6AF8235), + UINT64_C(0x800A155B1FD52872), UINT64_C(0xEF55B258A19906C1), + UINT64_C(0xE8F4DA0CCC207CFD), UINT64_C(0x87AB7D0F726C524E), + UINT64_C(0xB3549AA49B16F809), UINT64_C(0xDC0B3DA7255AD6BA), + UINT64_C(0xBD164B0C41640D71), UINT64_C(0xD249EC0FFF2823C2), + UINT64_C(0xE6B60BA416528985), UINT64_C(0x89E9ACA7A81EA736), + UINT64_C(0x8E48C4F3C5A7DD0A), UINT64_C(0xE11763F07BEBF3B9), + UINT64_C(0xD5E8845B929159FE), UINT64_C(0xBAB723582CDD774D), + UINT64_C(0xA187C3EBCA2BB664), UINT64_C(0xCED864E8746798D7), + UINT64_C(0xFA2783439D1D3290), UINT64_C(0x9578244023511C23), + UINT64_C(0x92D94C144EE8661F), UINT64_C(0xFD86EB17F0A448AC), + UINT64_C(0xC9790CBC19DEE2EB), UINT64_C(0xA626ABBFA792CC58), + UINT64_C(0xC73BDD14C3AC1793), UINT64_C(0xA8647A177DE03920), + UINT64_C(0x9C9B9DBC949A9367), UINT64_C(0xF3C43ABF2AD6BDD4), + UINT64_C(0xF46552EB476FC7E8), UINT64_C(0x9B3AF5E8F923E95B), + UINT64_C(0xAFC512431059431C), UINT64_C(0xC09AB540AE156DAF), + UINT64_C(0xE8E1F0BAF28A2D19), UINT64_C(0x87BE57B94CC603AA), + UINT64_C(0xB341B012A5BCA9ED), UINT64_C(0xDC1E17111BF0875E), + UINT64_C(0xDBBF7F457649FD62), UINT64_C(0xB4E0D846C805D3D1), + UINT64_C(0x801F3FED217F7996), UINT64_C(0xEF4098EE9F335725), + UINT64_C(0x8E5DEE45FB0D8CEE), UINT64_C(0xE10249464541A25D), + UINT64_C(0xD5FDAEEDAC3B081A), UINT64_C(0xBAA209EE127726A9), + UINT64_C(0xBD0361BA7FCE5C95), UINT64_C(0xD25CC6B9C1827226), + UINT64_C(0xE6A3211228F8D861), UINT64_C(0x89FC861196B4F6D2), + UINT64_C(0x334BA549BA69819F), UINT64_C(0x5C14024A0425AF2C), + UINT64_C(0x68EBE5E1ED5F056B), UINT64_C(0x07B442E253132BD8), + UINT64_C(0x00152AB63EAA51E4), UINT64_C(0x6F4A8DB580E67F57), + UINT64_C(0x5BB56A1E699CD510), UINT64_C(0x34EACD1DD7D0FBA3), + UINT64_C(0x55F7BBB6B3EE2068), UINT64_C(0x3AA81CB50DA20EDB), + UINT64_C(0x0E57FB1EE4D8A49C), UINT64_C(0x61085C1D5A948A2F), + UINT64_C(0x66A93449372DF013), UINT64_C(0x09F6934A8961DEA0), + UINT64_C(0x3D0974E1601B74E7), UINT64_C(0x5256D3E2DE575A54), + UINT64_C(0x7A2D961882C81AE2), UINT64_C(0x1572311B3C843451), + UINT64_C(0x218DD6B0D5FE9E16), UINT64_C(0x4ED271B36BB2B0A5), + UINT64_C(0x497319E7060BCA99), UINT64_C(0x262CBEE4B847E42A), + UINT64_C(0x12D3594F513D4E6D), UINT64_C(0x7D8CFE4CEF7160DE), + UINT64_C(0x1C9188E78B4FBB15), UINT64_C(0x73CE2FE4350395A6), + UINT64_C(0x4731C84FDC793FE1), UINT64_C(0x286E6F4C62351152), + UINT64_C(0x2FCF07180F8C6B6E), UINT64_C(0x4090A01BB1C045DD), + UINT64_C(0x746F47B058BAEF9A), UINT64_C(0x1B30E0B3E6F6C129), + UINT64_C(0x420F87D795576CC9), UINT64_C(0x2D5020D42B1B427A), + UINT64_C(0x19AFC77FC261E83D), UINT64_C(0x76F0607C7C2DC68E), + UINT64_C(0x715108281194BCB2), UINT64_C(0x1E0EAF2BAFD89201), + UINT64_C(0x2AF1488046A23846), UINT64_C(0x45AEEF83F8EE16F5), + UINT64_C(0x24B399289CD0CD3E), UINT64_C(0x4BEC3E2B229CE38D), + UINT64_C(0x7F13D980CBE649CA), UINT64_C(0x104C7E8375AA6779), + UINT64_C(0x17ED16D718131D45), UINT64_C(0x78B2B1D4A65F33F6), + UINT64_C(0x4C4D567F4F2599B1), UINT64_C(0x2312F17CF169B702), + UINT64_C(0x0B69B486ADF6F7B4), UINT64_C(0x6436138513BAD907), + UINT64_C(0x50C9F42EFAC07340), UINT64_C(0x3F96532D448C5DF3), + UINT64_C(0x38373B79293527CF), UINT64_C(0x57689C7A9779097C), + UINT64_C(0x63977BD17E03A33B), UINT64_C(0x0CC8DCD2C04F8D88), + UINT64_C(0x6DD5AA79A4715643), UINT64_C(0x028A0D7A1A3D78F0), + UINT64_C(0x3675EAD1F347D2B7), UINT64_C(0x592A4DD24D0BFC04), + UINT64_C(0x5E8B258620B28638), UINT64_C(0x31D482859EFEA88B), + UINT64_C(0x052B652E778402CC), UINT64_C(0x6A74C22DC9C82C7F), + UINT64_C(0xD0C3E175E5155B32), UINT64_C(0xBF9C46765B597581), + UINT64_C(0x8B63A1DDB223DFC6), UINT64_C(0xE43C06DE0C6FF175), + UINT64_C(0xE39D6E8A61D68B49), UINT64_C(0x8CC2C989DF9AA5FA), + UINT64_C(0xB83D2E2236E00FBD), UINT64_C(0xD762892188AC210E), + UINT64_C(0xB67FFF8AEC92FAC5), UINT64_C(0xD920588952DED476), + UINT64_C(0xEDDFBF22BBA47E31), UINT64_C(0x8280182105E85082), + UINT64_C(0x8521707568512ABE), UINT64_C(0xEA7ED776D61D040D), + UINT64_C(0xDE8130DD3F67AE4A), UINT64_C(0xB1DE97DE812B80F9), + UINT64_C(0x99A5D224DDB4C04F), UINT64_C(0xF6FA752763F8EEFC), + UINT64_C(0xC205928C8A8244BB), UINT64_C(0xAD5A358F34CE6A08), + UINT64_C(0xAAFB5DDB59771034), UINT64_C(0xC5A4FAD8E73B3E87), + UINT64_C(0xF15B1D730E4194C0), UINT64_C(0x9E04BA70B00DBA73), + UINT64_C(0xFF19CCDBD43361B8), UINT64_C(0x90466BD86A7F4F0B), + UINT64_C(0xA4B98C738305E54C), UINT64_C(0xCBE62B703D49CBFF), + UINT64_C(0xCC47432450F0B1C3), UINT64_C(0xA318E427EEBC9F70), + UINT64_C(0x97E7038C07C63537), UINT64_C(0xF8B8A48FB98A1B84), + UINT64_C(0xE388443C5F7CDAAD), UINT64_C(0x8CD7E33FE130F41E), + UINT64_C(0xB8280494084A5E59), UINT64_C(0xD777A397B60670EA), + UINT64_C(0xD0D6CBC3DBBF0AD6), UINT64_C(0xBF896CC065F32465), + UINT64_C(0x8B768B6B8C898E22), UINT64_C(0xE4292C6832C5A091), + UINT64_C(0x85345AC356FB7B5A), UINT64_C(0xEA6BFDC0E8B755E9), + UINT64_C(0xDE941A6B01CDFFAE), UINT64_C(0xB1CBBD68BF81D11D), + UINT64_C(0xB66AD53CD238AB21), UINT64_C(0xD935723F6C748592), + UINT64_C(0xEDCA9594850E2FD5), UINT64_C(0x829532973B420166), + UINT64_C(0xAAEE776D67DD41D0), UINT64_C(0xC5B1D06ED9916F63), + UINT64_C(0xF14E37C530EBC524), UINT64_C(0x9E1190C68EA7EB97), + UINT64_C(0x99B0F892E31E91AB), UINT64_C(0xF6EF5F915D52BF18), + UINT64_C(0xC210B83AB428155F), UINT64_C(0xAD4F1F390A643BEC), + UINT64_C(0xCC5269926E5AE027), UINT64_C(0xA30DCE91D016CE94), + UINT64_C(0x97F2293A396C64D3), UINT64_C(0xF8AD8E3987204A60), + UINT64_C(0xFF0CE66DEA99305C), UINT64_C(0x9053416E54D51EEF), + UINT64_C(0xA4ACA6C5BDAFB4A8), UINT64_C(0xCBF301C603E39A1B), + UINT64_C(0x7144229E2F3EED56), UINT64_C(0x1E1B859D9172C3E5), + UINT64_C(0x2AE46236780869A2), UINT64_C(0x45BBC535C6444711), + UINT64_C(0x421AAD61ABFD3D2D), UINT64_C(0x2D450A6215B1139E), + UINT64_C(0x19BAEDC9FCCBB9D9), UINT64_C(0x76E54ACA4287976A), + UINT64_C(0x17F83C6126B94CA1), UINT64_C(0x78A79B6298F56212), + UINT64_C(0x4C587CC9718FC855), UINT64_C(0x2307DBCACFC3E6E6), + UINT64_C(0x24A6B39EA27A9CDA), UINT64_C(0x4BF9149D1C36B269), + UINT64_C(0x7F06F336F54C182E), UINT64_C(0x105954354B00369D), + UINT64_C(0x382211CF179F762B), UINT64_C(0x577DB6CCA9D35898), + UINT64_C(0x6382516740A9F2DF), UINT64_C(0x0CDDF664FEE5DC6C), + UINT64_C(0x0B7C9E30935CA650), UINT64_C(0x642339332D1088E3), + UINT64_C(0x50DCDE98C46A22A4), UINT64_C(0x3F83799B7A260C17), + UINT64_C(0x5E9E0F301E18D7DC), UINT64_C(0x31C1A833A054F96F), + UINT64_C(0x053E4F98492E5328), UINT64_C(0x6A61E89BF7627D9B), + UINT64_C(0x6DC080CF9ADB07A7), UINT64_C(0x029F27CC24972914), + UINT64_C(0x3660C067CDED8353), UINT64_C(0x593F676473A1ADE0) + }, { + UINT64_C(0x0000000000000000), UINT64_C(0x0DF1D05C9279E954), + UINT64_C(0x1AE2A1B924F3D2A9), UINT64_C(0x171371E5B68A3BFD), + UINT64_C(0xB1DA4DDC62497DC1), UINT64_C(0xBC2B9D80F0309495), + UINT64_C(0xAB38EC6546BAAF68), UINT64_C(0xA6C93C39D4C3463C), + UINT64_C(0xE7AB9517EE3D2210), UINT64_C(0xEA5A454B7C44CB44), + UINT64_C(0xFD4934AECACEF0B9), UINT64_C(0xF0B8E4F258B719ED), + UINT64_C(0x5671D8CB8C745FD1), UINT64_C(0x5B8008971E0DB685), + UINT64_C(0x4C937972A8878D78), UINT64_C(0x4162A92E3AFE642C), + UINT64_C(0xCE572B2FDC7B4420), UINT64_C(0xC3A6FB734E02AD74), + UINT64_C(0xD4B58A96F8889689), UINT64_C(0xD9445ACA6AF17FDD), + UINT64_C(0x7F8D66F3BE3239E1), UINT64_C(0x727CB6AF2C4BD0B5), + UINT64_C(0x656FC74A9AC1EB48), UINT64_C(0x689E171608B8021C), + UINT64_C(0x29FCBE3832466630), UINT64_C(0x240D6E64A03F8F64), + UINT64_C(0x331E1F8116B5B499), UINT64_C(0x3EEFCFDD84CC5DCD), + UINT64_C(0x9826F3E4500F1BF1), UINT64_C(0x95D723B8C276F2A5), + UINT64_C(0x82C4525D74FCC958), UINT64_C(0x8F358201E685200C), + UINT64_C(0x9CAF565EB8F78840), UINT64_C(0x915E86022A8E6114), + UINT64_C(0x864DF7E79C045AE9), UINT64_C(0x8BBC27BB0E7DB3BD), + UINT64_C(0x2D751B82DABEF581), UINT64_C(0x2084CBDE48C71CD5), + UINT64_C(0x3797BA3BFE4D2728), UINT64_C(0x3A666A676C34CE7C), + UINT64_C(0x7B04C34956CAAA50), UINT64_C(0x76F51315C4B34304), + UINT64_C(0x61E662F0723978F9), UINT64_C(0x6C17B2ACE04091AD), + UINT64_C(0xCADE8E953483D791), UINT64_C(0xC72F5EC9A6FA3EC5), + UINT64_C(0xD03C2F2C10700538), UINT64_C(0xDDCDFF708209EC6C), + UINT64_C(0x52F87D71648CCC60), UINT64_C(0x5F09AD2DF6F52534), + UINT64_C(0x481ADCC8407F1EC9), UINT64_C(0x45EB0C94D206F79D), + UINT64_C(0xE32230AD06C5B1A1), UINT64_C(0xEED3E0F194BC58F5), + UINT64_C(0xF9C0911422366308), UINT64_C(0xF4314148B04F8A5C), + UINT64_C(0xB553E8668AB1EE70), UINT64_C(0xB8A2383A18C80724), + UINT64_C(0xAFB149DFAE423CD9), UINT64_C(0xA24099833C3BD58D), + UINT64_C(0x0489A5BAE8F893B1), UINT64_C(0x097875E67A817AE5), + UINT64_C(0x1E6B0403CC0B4118), UINT64_C(0x139AD45F5E72A84C), + UINT64_C(0x385FADBC70EF1181), UINT64_C(0x35AE7DE0E296F8D5), + UINT64_C(0x22BD0C05541CC328), UINT64_C(0x2F4CDC59C6652A7C), + UINT64_C(0x8985E06012A66C40), UINT64_C(0x8474303C80DF8514), + UINT64_C(0x936741D93655BEE9), UINT64_C(0x9E969185A42C57BD), + UINT64_C(0xDFF438AB9ED23391), UINT64_C(0xD205E8F70CABDAC5), + UINT64_C(0xC5169912BA21E138), UINT64_C(0xC8E7494E2858086C), + UINT64_C(0x6E2E7577FC9B4E50), UINT64_C(0x63DFA52B6EE2A704), + UINT64_C(0x74CCD4CED8689CF9), UINT64_C(0x793D04924A1175AD), + UINT64_C(0xF6088693AC9455A1), UINT64_C(0xFBF956CF3EEDBCF5), + UINT64_C(0xECEA272A88678708), UINT64_C(0xE11BF7761A1E6E5C), + UINT64_C(0x47D2CB4FCEDD2860), UINT64_C(0x4A231B135CA4C134), + UINT64_C(0x5D306AF6EA2EFAC9), UINT64_C(0x50C1BAAA7857139D), + UINT64_C(0x11A3138442A977B1), UINT64_C(0x1C52C3D8D0D09EE5), + UINT64_C(0x0B41B23D665AA518), UINT64_C(0x06B06261F4234C4C), + UINT64_C(0xA0795E5820E00A70), UINT64_C(0xAD888E04B299E324), + UINT64_C(0xBA9BFFE10413D8D9), UINT64_C(0xB76A2FBD966A318D), + UINT64_C(0xA4F0FBE2C81899C1), UINT64_C(0xA9012BBE5A617095), + UINT64_C(0xBE125A5BECEB4B68), UINT64_C(0xB3E38A077E92A23C), + UINT64_C(0x152AB63EAA51E400), UINT64_C(0x18DB666238280D54), + UINT64_C(0x0FC817878EA236A9), UINT64_C(0x0239C7DB1CDBDFFD), + UINT64_C(0x435B6EF52625BBD1), UINT64_C(0x4EAABEA9B45C5285), + UINT64_C(0x59B9CF4C02D66978), UINT64_C(0x54481F1090AF802C), + UINT64_C(0xF2812329446CC610), UINT64_C(0xFF70F375D6152F44), + UINT64_C(0xE8638290609F14B9), UINT64_C(0xE59252CCF2E6FDED), + UINT64_C(0x6AA7D0CD1463DDE1), UINT64_C(0x67560091861A34B5), + UINT64_C(0x7045717430900F48), UINT64_C(0x7DB4A128A2E9E61C), + UINT64_C(0xDB7D9D11762AA020), UINT64_C(0xD68C4D4DE4534974), + UINT64_C(0xC19F3CA852D97289), UINT64_C(0xCC6EECF4C0A09BDD), + UINT64_C(0x8D0C45DAFA5EFFF1), UINT64_C(0x80FD9586682716A5), + UINT64_C(0x97EEE463DEAD2D58), UINT64_C(0x9A1F343F4CD4C40C), + UINT64_C(0x3CD6080698178230), UINT64_C(0x3127D85A0A6E6B64), + UINT64_C(0x2634A9BFBCE45099), UINT64_C(0x2BC579E32E9DB9CD), + UINT64_C(0xF5A054D6CA71FB90), UINT64_C(0xF851848A580812C4), + UINT64_C(0xEF42F56FEE822939), UINT64_C(0xE2B325337CFBC06D), + UINT64_C(0x447A190AA8388651), UINT64_C(0x498BC9563A416F05), + UINT64_C(0x5E98B8B38CCB54F8), UINT64_C(0x536968EF1EB2BDAC), + UINT64_C(0x120BC1C1244CD980), UINT64_C(0x1FFA119DB63530D4), + UINT64_C(0x08E9607800BF0B29), UINT64_C(0x0518B02492C6E27D), + UINT64_C(0xA3D18C1D4605A441), UINT64_C(0xAE205C41D47C4D15), + UINT64_C(0xB9332DA462F676E8), UINT64_C(0xB4C2FDF8F08F9FBC), + UINT64_C(0x3BF77FF9160ABFB0), UINT64_C(0x3606AFA5847356E4), + UINT64_C(0x2115DE4032F96D19), UINT64_C(0x2CE40E1CA080844D), + UINT64_C(0x8A2D32257443C271), UINT64_C(0x87DCE279E63A2B25), + UINT64_C(0x90CF939C50B010D8), UINT64_C(0x9D3E43C0C2C9F98C), + UINT64_C(0xDC5CEAEEF8379DA0), UINT64_C(0xD1AD3AB26A4E74F4), + UINT64_C(0xC6BE4B57DCC44F09), UINT64_C(0xCB4F9B0B4EBDA65D), + UINT64_C(0x6D86A7329A7EE061), UINT64_C(0x6077776E08070935), + UINT64_C(0x7764068BBE8D32C8), UINT64_C(0x7A95D6D72CF4DB9C), + UINT64_C(0x690F0288728673D0), UINT64_C(0x64FED2D4E0FF9A84), + UINT64_C(0x73EDA3315675A179), UINT64_C(0x7E1C736DC40C482D), + UINT64_C(0xD8D54F5410CF0E11), UINT64_C(0xD5249F0882B6E745), + UINT64_C(0xC237EEED343CDCB8), UINT64_C(0xCFC63EB1A64535EC), + UINT64_C(0x8EA4979F9CBB51C0), UINT64_C(0x835547C30EC2B894), + UINT64_C(0x94463626B8488369), UINT64_C(0x99B7E67A2A316A3D), + UINT64_C(0x3F7EDA43FEF22C01), UINT64_C(0x328F0A1F6C8BC555), + UINT64_C(0x259C7BFADA01FEA8), UINT64_C(0x286DABA6487817FC), + UINT64_C(0xA75829A7AEFD37F0), UINT64_C(0xAAA9F9FB3C84DEA4), + UINT64_C(0xBDBA881E8A0EE559), UINT64_C(0xB04B584218770C0D), + UINT64_C(0x1682647BCCB44A31), UINT64_C(0x1B73B4275ECDA365), + UINT64_C(0x0C60C5C2E8479898), UINT64_C(0x0191159E7A3E71CC), + UINT64_C(0x40F3BCB040C015E0), UINT64_C(0x4D026CECD2B9FCB4), + UINT64_C(0x5A111D096433C749), UINT64_C(0x57E0CD55F64A2E1D), + UINT64_C(0xF129F16C22896821), UINT64_C(0xFCD82130B0F08175), + UINT64_C(0xEBCB50D5067ABA88), UINT64_C(0xE63A8089940353DC), + UINT64_C(0xCDFFF96ABA9EEA11), UINT64_C(0xC00E293628E70345), + UINT64_C(0xD71D58D39E6D38B8), UINT64_C(0xDAEC888F0C14D1EC), + UINT64_C(0x7C25B4B6D8D797D0), UINT64_C(0x71D464EA4AAE7E84), + UINT64_C(0x66C7150FFC244579), UINT64_C(0x6B36C5536E5DAC2D), + UINT64_C(0x2A546C7D54A3C801), UINT64_C(0x27A5BC21C6DA2155), + UINT64_C(0x30B6CDC470501AA8), UINT64_C(0x3D471D98E229F3FC), + UINT64_C(0x9B8E21A136EAB5C0), UINT64_C(0x967FF1FDA4935C94), + UINT64_C(0x816C801812196769), UINT64_C(0x8C9D504480608E3D), + UINT64_C(0x03A8D24566E5AE31), UINT64_C(0x0E590219F49C4765), + UINT64_C(0x194A73FC42167C98), UINT64_C(0x14BBA3A0D06F95CC), + UINT64_C(0xB2729F9904ACD3F0), UINT64_C(0xBF834FC596D53AA4), + UINT64_C(0xA8903E20205F0159), UINT64_C(0xA561EE7CB226E80D), + UINT64_C(0xE403475288D88C21), UINT64_C(0xE9F2970E1AA16575), + UINT64_C(0xFEE1E6EBAC2B5E88), UINT64_C(0xF31036B73E52B7DC), + UINT64_C(0x55D90A8EEA91F1E0), UINT64_C(0x5828DAD278E818B4), + UINT64_C(0x4F3BAB37CE622349), UINT64_C(0x42CA7B6B5C1BCA1D), + UINT64_C(0x5150AF3402696251), UINT64_C(0x5CA17F6890108B05), + UINT64_C(0x4BB20E8D269AB0F8), UINT64_C(0x4643DED1B4E359AC), + UINT64_C(0xE08AE2E860201F90), UINT64_C(0xED7B32B4F259F6C4), + UINT64_C(0xFA68435144D3CD39), UINT64_C(0xF799930DD6AA246D), + UINT64_C(0xB6FB3A23EC544041), UINT64_C(0xBB0AEA7F7E2DA915), + UINT64_C(0xAC199B9AC8A792E8), UINT64_C(0xA1E84BC65ADE7BBC), + UINT64_C(0x072177FF8E1D3D80), UINT64_C(0x0AD0A7A31C64D4D4), + UINT64_C(0x1DC3D646AAEEEF29), UINT64_C(0x1032061A3897067D), + UINT64_C(0x9F07841BDE122671), UINT64_C(0x92F654474C6BCF25), + UINT64_C(0x85E525A2FAE1F4D8), UINT64_C(0x8814F5FE68981D8C), + UINT64_C(0x2EDDC9C7BC5B5BB0), UINT64_C(0x232C199B2E22B2E4), + UINT64_C(0x343F687E98A88919), UINT64_C(0x39CEB8220AD1604D), + UINT64_C(0x78AC110C302F0461), UINT64_C(0x755DC150A256ED35), + UINT64_C(0x624EB0B514DCD6C8), UINT64_C(0x6FBF60E986A53F9C), + UINT64_C(0xC9765CD0526679A0), UINT64_C(0xC4878C8CC01F90F4), + UINT64_C(0xD394FD697695AB09), UINT64_C(0xDE652D35E4EC425D) + }, { + UINT64_C(0x0000000000000000), UINT64_C(0xCB6D6A914AE10B3F), + UINT64_C(0x96DBD42295C2177E), UINT64_C(0x5DB6BEB3DF231C41), + UINT64_C(0x2CB7A9452A852FFC), UINT64_C(0xE7DAC3D4606424C3), + UINT64_C(0xBA6C7D67BF473882), UINT64_C(0x710117F6F5A633BD), + UINT64_C(0xDD705D247FA5876A), UINT64_C(0x161D37B535448C55), + UINT64_C(0x4BAB8906EA679014), UINT64_C(0x80C6E397A0869B2B), + UINT64_C(0xF1C7F4615520A896), UINT64_C(0x3AAA9EF01FC1A3A9), + UINT64_C(0x671C2043C0E2BFE8), UINT64_C(0xAC714AD28A03B4D7), + UINT64_C(0xBAE1BA48FE4A0FD5), UINT64_C(0x718CD0D9B4AB04EA), + UINT64_C(0x2C3A6E6A6B8818AB), UINT64_C(0xE75704FB21691394), + UINT64_C(0x9656130DD4CF2029), UINT64_C(0x5D3B799C9E2E2B16), + UINT64_C(0x008DC72F410D3757), UINT64_C(0xCBE0ADBE0BEC3C68), + UINT64_C(0x6791E76C81EF88BF), UINT64_C(0xACFC8DFDCB0E8380), + UINT64_C(0xF14A334E142D9FC1), UINT64_C(0x3A2759DF5ECC94FE), + UINT64_C(0x4B264E29AB6AA743), UINT64_C(0x804B24B8E18BAC7C), + UINT64_C(0xDDFD9A0B3EA8B03D), UINT64_C(0x1690F09A7449BB02), + UINT64_C(0xF1DD7B3ED73AC638), UINT64_C(0x3AB011AF9DDBCD07), + UINT64_C(0x6706AF1C42F8D146), UINT64_C(0xAC6BC58D0819DA79), + UINT64_C(0xDD6AD27BFDBFE9C4), UINT64_C(0x1607B8EAB75EE2FB), + UINT64_C(0x4BB10659687DFEBA), UINT64_C(0x80DC6CC8229CF585), + UINT64_C(0x2CAD261AA89F4152), UINT64_C(0xE7C04C8BE27E4A6D), + UINT64_C(0xBA76F2383D5D562C), UINT64_C(0x711B98A977BC5D13), + UINT64_C(0x001A8F5F821A6EAE), UINT64_C(0xCB77E5CEC8FB6591), + UINT64_C(0x96C15B7D17D879D0), UINT64_C(0x5DAC31EC5D3972EF), + UINT64_C(0x4B3CC1762970C9ED), UINT64_C(0x8051ABE76391C2D2), + UINT64_C(0xDDE71554BCB2DE93), UINT64_C(0x168A7FC5F653D5AC), + UINT64_C(0x678B683303F5E611), UINT64_C(0xACE602A24914ED2E), + UINT64_C(0xF150BC119637F16F), UINT64_C(0x3A3DD680DCD6FA50), + UINT64_C(0x964C9C5256D54E87), UINT64_C(0x5D21F6C31C3445B8), + UINT64_C(0x00974870C31759F9), UINT64_C(0xCBFA22E189F652C6), + UINT64_C(0xBAFB35177C50617B), UINT64_C(0x71965F8636B16A44), + UINT64_C(0x2C20E135E9927605), UINT64_C(0xE74D8BA4A3737D3A), + UINT64_C(0xE2BBF77CAE758C71), UINT64_C(0x29D69DEDE494874E), + UINT64_C(0x7460235E3BB79B0F), UINT64_C(0xBF0D49CF71569030), + UINT64_C(0xCE0C5E3984F0A38D), UINT64_C(0x056134A8CE11A8B2), + UINT64_C(0x58D78A1B1132B4F3), UINT64_C(0x93BAE08A5BD3BFCC), + UINT64_C(0x3FCBAA58D1D00B1B), UINT64_C(0xF4A6C0C99B310024), + UINT64_C(0xA9107E7A44121C65), UINT64_C(0x627D14EB0EF3175A), + UINT64_C(0x137C031DFB5524E7), UINT64_C(0xD811698CB1B42FD8), + UINT64_C(0x85A7D73F6E973399), UINT64_C(0x4ECABDAE247638A6), + UINT64_C(0x585A4D34503F83A4), UINT64_C(0x933727A51ADE889B), + UINT64_C(0xCE819916C5FD94DA), UINT64_C(0x05ECF3878F1C9FE5), + UINT64_C(0x74EDE4717ABAAC58), UINT64_C(0xBF808EE0305BA767), + UINT64_C(0xE2363053EF78BB26), UINT64_C(0x295B5AC2A599B019), + UINT64_C(0x852A10102F9A04CE), UINT64_C(0x4E477A81657B0FF1), + UINT64_C(0x13F1C432BA5813B0), UINT64_C(0xD89CAEA3F0B9188F), + UINT64_C(0xA99DB955051F2B32), UINT64_C(0x62F0D3C44FFE200D), + UINT64_C(0x3F466D7790DD3C4C), UINT64_C(0xF42B07E6DA3C3773), + UINT64_C(0x13668C42794F4A49), UINT64_C(0xD80BE6D333AE4176), + UINT64_C(0x85BD5860EC8D5D37), UINT64_C(0x4ED032F1A66C5608), + UINT64_C(0x3FD1250753CA65B5), UINT64_C(0xF4BC4F96192B6E8A), + UINT64_C(0xA90AF125C60872CB), UINT64_C(0x62679BB48CE979F4), + UINT64_C(0xCE16D16606EACD23), UINT64_C(0x057BBBF74C0BC61C), + UINT64_C(0x58CD05449328DA5D), UINT64_C(0x93A06FD5D9C9D162), + UINT64_C(0xE2A178232C6FE2DF), UINT64_C(0x29CC12B2668EE9E0), + UINT64_C(0x747AAC01B9ADF5A1), UINT64_C(0xBF17C690F34CFE9E), + UINT64_C(0xA987360A8705459C), UINT64_C(0x62EA5C9BCDE44EA3), + UINT64_C(0x3F5CE22812C752E2), UINT64_C(0xF43188B9582659DD), + UINT64_C(0x85309F4FAD806A60), UINT64_C(0x4E5DF5DEE761615F), + UINT64_C(0x13EB4B6D38427D1E), UINT64_C(0xD88621FC72A37621), + UINT64_C(0x74F76B2EF8A0C2F6), UINT64_C(0xBF9A01BFB241C9C9), + UINT64_C(0xE22CBF0C6D62D588), UINT64_C(0x2941D59D2783DEB7), + UINT64_C(0x5840C26BD225ED0A), UINT64_C(0x932DA8FA98C4E635), + UINT64_C(0xCE9B164947E7FA74), UINT64_C(0x05F67CD80D06F14B), + UINT64_C(0xC477EFF95CEB18E3), UINT64_C(0x0F1A8568160A13DC), + UINT64_C(0x52AC3BDBC9290F9D), UINT64_C(0x99C1514A83C804A2), + UINT64_C(0xE8C046BC766E371F), UINT64_C(0x23AD2C2D3C8F3C20), + UINT64_C(0x7E1B929EE3AC2061), UINT64_C(0xB576F80FA94D2B5E), + UINT64_C(0x1907B2DD234E9F89), UINT64_C(0xD26AD84C69AF94B6), + UINT64_C(0x8FDC66FFB68C88F7), UINT64_C(0x44B10C6EFC6D83C8), + UINT64_C(0x35B01B9809CBB075), UINT64_C(0xFEDD7109432ABB4A), + UINT64_C(0xA36BCFBA9C09A70B), UINT64_C(0x6806A52BD6E8AC34), + UINT64_C(0x7E9655B1A2A11736), UINT64_C(0xB5FB3F20E8401C09), + UINT64_C(0xE84D819337630048), UINT64_C(0x2320EB027D820B77), + UINT64_C(0x5221FCF4882438CA), UINT64_C(0x994C9665C2C533F5), + UINT64_C(0xC4FA28D61DE62FB4), UINT64_C(0x0F9742475707248B), + UINT64_C(0xA3E60895DD04905C), UINT64_C(0x688B620497E59B63), + UINT64_C(0x353DDCB748C68722), UINT64_C(0xFE50B62602278C1D), + UINT64_C(0x8F51A1D0F781BFA0), UINT64_C(0x443CCB41BD60B49F), + UINT64_C(0x198A75F26243A8DE), UINT64_C(0xD2E71F6328A2A3E1), + UINT64_C(0x35AA94C78BD1DEDB), UINT64_C(0xFEC7FE56C130D5E4), + UINT64_C(0xA37140E51E13C9A5), UINT64_C(0x681C2A7454F2C29A), + UINT64_C(0x191D3D82A154F127), UINT64_C(0xD2705713EBB5FA18), + UINT64_C(0x8FC6E9A03496E659), UINT64_C(0x44AB83317E77ED66), + UINT64_C(0xE8DAC9E3F47459B1), UINT64_C(0x23B7A372BE95528E), + UINT64_C(0x7E011DC161B64ECF), UINT64_C(0xB56C77502B5745F0), + UINT64_C(0xC46D60A6DEF1764D), UINT64_C(0x0F000A3794107D72), + UINT64_C(0x52B6B4844B336133), UINT64_C(0x99DBDE1501D26A0C), + UINT64_C(0x8F4B2E8F759BD10E), UINT64_C(0x4426441E3F7ADA31), + UINT64_C(0x1990FAADE059C670), UINT64_C(0xD2FD903CAAB8CD4F), + UINT64_C(0xA3FC87CA5F1EFEF2), UINT64_C(0x6891ED5B15FFF5CD), + UINT64_C(0x352753E8CADCE98C), UINT64_C(0xFE4A3979803DE2B3), + UINT64_C(0x523B73AB0A3E5664), UINT64_C(0x9956193A40DF5D5B), + UINT64_C(0xC4E0A7899FFC411A), UINT64_C(0x0F8DCD18D51D4A25), + UINT64_C(0x7E8CDAEE20BB7998), UINT64_C(0xB5E1B07F6A5A72A7), + UINT64_C(0xE8570ECCB5796EE6), UINT64_C(0x233A645DFF9865D9), + UINT64_C(0x26CC1885F29E9492), UINT64_C(0xEDA17214B87F9FAD), + UINT64_C(0xB017CCA7675C83EC), UINT64_C(0x7B7AA6362DBD88D3), + UINT64_C(0x0A7BB1C0D81BBB6E), UINT64_C(0xC116DB5192FAB051), + UINT64_C(0x9CA065E24DD9AC10), UINT64_C(0x57CD0F730738A72F), + UINT64_C(0xFBBC45A18D3B13F8), UINT64_C(0x30D12F30C7DA18C7), + UINT64_C(0x6D67918318F90486), UINT64_C(0xA60AFB1252180FB9), + UINT64_C(0xD70BECE4A7BE3C04), UINT64_C(0x1C668675ED5F373B), + UINT64_C(0x41D038C6327C2B7A), UINT64_C(0x8ABD5257789D2045), + UINT64_C(0x9C2DA2CD0CD49B47), UINT64_C(0x5740C85C46359078), + UINT64_C(0x0AF676EF99168C39), UINT64_C(0xC19B1C7ED3F78706), + UINT64_C(0xB09A0B882651B4BB), UINT64_C(0x7BF761196CB0BF84), + UINT64_C(0x2641DFAAB393A3C5), UINT64_C(0xED2CB53BF972A8FA), + UINT64_C(0x415DFFE973711C2D), UINT64_C(0x8A30957839901712), + UINT64_C(0xD7862BCBE6B30B53), UINT64_C(0x1CEB415AAC52006C), + UINT64_C(0x6DEA56AC59F433D1), UINT64_C(0xA6873C3D131538EE), + UINT64_C(0xFB31828ECC3624AF), UINT64_C(0x305CE81F86D72F90), + UINT64_C(0xD71163BB25A452AA), UINT64_C(0x1C7C092A6F455995), + UINT64_C(0x41CAB799B06645D4), UINT64_C(0x8AA7DD08FA874EEB), + UINT64_C(0xFBA6CAFE0F217D56), UINT64_C(0x30CBA06F45C07669), + UINT64_C(0x6D7D1EDC9AE36A28), UINT64_C(0xA610744DD0026117), + UINT64_C(0x0A613E9F5A01D5C0), UINT64_C(0xC10C540E10E0DEFF), + UINT64_C(0x9CBAEABDCFC3C2BE), UINT64_C(0x57D7802C8522C981), + UINT64_C(0x26D697DA7084FA3C), UINT64_C(0xEDBBFD4B3A65F103), + UINT64_C(0xB00D43F8E546ED42), UINT64_C(0x7B602969AFA7E67D), + UINT64_C(0x6DF0D9F3DBEE5D7F), UINT64_C(0xA69DB362910F5640), + UINT64_C(0xFB2B0DD14E2C4A01), UINT64_C(0x3046674004CD413E), + UINT64_C(0x414770B6F16B7283), UINT64_C(0x8A2A1A27BB8A79BC), + UINT64_C(0xD79CA49464A965FD), UINT64_C(0x1CF1CE052E486EC2), + UINT64_C(0xB08084D7A44BDA15), UINT64_C(0x7BEDEE46EEAAD12A), + UINT64_C(0x265B50F53189CD6B), UINT64_C(0xED363A647B68C654), + UINT64_C(0x9C372D928ECEF5E9), UINT64_C(0x575A4703C42FFED6), + UINT64_C(0x0AECF9B01B0CE297), UINT64_C(0xC181932151EDE9A8) + }, { + UINT64_C(0x0000000000000000), UINT64_C(0xDCA12C225E8AEE1D), + UINT64_C(0xB8435944BC14DD3B), UINT64_C(0x64E27566E29E3326), + UINT64_C(0x7087B2887829BA77), UINT64_C(0xAC269EAA26A3546A), + UINT64_C(0xC8C4EBCCC43D674C), UINT64_C(0x1465C7EE9AB78951), + UINT64_C(0xE00E6511F15274EF), UINT64_C(0x3CAF4933AFD89AF2), + UINT64_C(0x584D3C554D46A9D4), UINT64_C(0x84EC107713CC47C9), + UINT64_C(0x9089D799897BCE98), UINT64_C(0x4C28FBBBD7F12085), + UINT64_C(0x28CA8EDD356F13A3), UINT64_C(0xF46BA2FF6BE5FDBE), + UINT64_C(0x4503C48DC90A304C), UINT64_C(0x99A2E8AF9780DE51), + UINT64_C(0xFD409DC9751EED77), UINT64_C(0x21E1B1EB2B94036A), + UINT64_C(0x35847605B1238A3B), UINT64_C(0xE9255A27EFA96426), + UINT64_C(0x8DC72F410D375700), UINT64_C(0x5166036353BDB91D), + UINT64_C(0xA50DA19C385844A3), UINT64_C(0x79AC8DBE66D2AABE), + UINT64_C(0x1D4EF8D8844C9998), UINT64_C(0xC1EFD4FADAC67785), + UINT64_C(0xD58A13144071FED4), UINT64_C(0x092B3F361EFB10C9), + UINT64_C(0x6DC94A50FC6523EF), UINT64_C(0xB1686672A2EFCDF2), + UINT64_C(0x8A06881B93156098), UINT64_C(0x56A7A439CD9F8E85), + UINT64_C(0x3245D15F2F01BDA3), UINT64_C(0xEEE4FD7D718B53BE), + UINT64_C(0xFA813A93EB3CDAEF), UINT64_C(0x262016B1B5B634F2), + UINT64_C(0x42C263D7572807D4), UINT64_C(0x9E634FF509A2E9C9), + UINT64_C(0x6A08ED0A62471477), UINT64_C(0xB6A9C1283CCDFA6A), + UINT64_C(0xD24BB44EDE53C94C), UINT64_C(0x0EEA986C80D92751), + UINT64_C(0x1A8F5F821A6EAE00), UINT64_C(0xC62E73A044E4401D), + UINT64_C(0xA2CC06C6A67A733B), UINT64_C(0x7E6D2AE4F8F09D26), + UINT64_C(0xCF054C965A1F50D4), UINT64_C(0x13A460B40495BEC9), + UINT64_C(0x774615D2E60B8DEF), UINT64_C(0xABE739F0B88163F2), + UINT64_C(0xBF82FE1E2236EAA3), UINT64_C(0x6323D23C7CBC04BE), + UINT64_C(0x07C1A75A9E223798), UINT64_C(0xDB608B78C0A8D985), + UINT64_C(0x2F0B2987AB4D243B), UINT64_C(0xF3AA05A5F5C7CA26), + UINT64_C(0x974870C31759F900), UINT64_C(0x4BE95CE149D3171D), + UINT64_C(0x5F8C9B0FD3649E4C), UINT64_C(0x832DB72D8DEE7051), + UINT64_C(0xE7CFC24B6F704377), UINT64_C(0x3B6EEE6931FAAD6A), + UINT64_C(0x91131E980D8418A2), UINT64_C(0x4DB232BA530EF6BF), + UINT64_C(0x295047DCB190C599), UINT64_C(0xF5F16BFEEF1A2B84), + UINT64_C(0xE194AC1075ADA2D5), UINT64_C(0x3D3580322B274CC8), + UINT64_C(0x59D7F554C9B97FEE), UINT64_C(0x8576D976973391F3), + UINT64_C(0x711D7B89FCD66C4D), UINT64_C(0xADBC57ABA25C8250), + UINT64_C(0xC95E22CD40C2B176), UINT64_C(0x15FF0EEF1E485F6B), + UINT64_C(0x019AC90184FFD63A), UINT64_C(0xDD3BE523DA753827), + UINT64_C(0xB9D9904538EB0B01), UINT64_C(0x6578BC676661E51C), + UINT64_C(0xD410DA15C48E28EE), UINT64_C(0x08B1F6379A04C6F3), + UINT64_C(0x6C538351789AF5D5), UINT64_C(0xB0F2AF7326101BC8), + UINT64_C(0xA497689DBCA79299), UINT64_C(0x783644BFE22D7C84), + UINT64_C(0x1CD431D900B34FA2), UINT64_C(0xC0751DFB5E39A1BF), + UINT64_C(0x341EBF0435DC5C01), UINT64_C(0xE8BF93266B56B21C), + UINT64_C(0x8C5DE64089C8813A), UINT64_C(0x50FCCA62D7426F27), + UINT64_C(0x44990D8C4DF5E676), UINT64_C(0x983821AE137F086B), + UINT64_C(0xFCDA54C8F1E13B4D), UINT64_C(0x207B78EAAF6BD550), + UINT64_C(0x1B1596839E91783A), UINT64_C(0xC7B4BAA1C01B9627), + UINT64_C(0xA356CFC72285A501), UINT64_C(0x7FF7E3E57C0F4B1C), + UINT64_C(0x6B92240BE6B8C24D), UINT64_C(0xB7330829B8322C50), + UINT64_C(0xD3D17D4F5AAC1F76), UINT64_C(0x0F70516D0426F16B), + UINT64_C(0xFB1BF3926FC30CD5), UINT64_C(0x27BADFB03149E2C8), + UINT64_C(0x4358AAD6D3D7D1EE), UINT64_C(0x9FF986F48D5D3FF3), + UINT64_C(0x8B9C411A17EAB6A2), UINT64_C(0x573D6D38496058BF), + UINT64_C(0x33DF185EABFE6B99), UINT64_C(0xEF7E347CF5748584), + UINT64_C(0x5E16520E579B4876), UINT64_C(0x82B77E2C0911A66B), + UINT64_C(0xE6550B4AEB8F954D), UINT64_C(0x3AF42768B5057B50), + UINT64_C(0x2E91E0862FB2F201), UINT64_C(0xF230CCA471381C1C), + UINT64_C(0x96D2B9C293A62F3A), UINT64_C(0x4A7395E0CD2CC127), + UINT64_C(0xBE18371FA6C93C99), UINT64_C(0x62B91B3DF843D284), + UINT64_C(0x065B6E5B1ADDE1A2), UINT64_C(0xDAFA427944570FBF), + UINT64_C(0xCE9F8597DEE086EE), UINT64_C(0x123EA9B5806A68F3), + UINT64_C(0x76DCDCD362F45BD5), UINT64_C(0xAA7DF0F13C7EB5C8), + UINT64_C(0xA739329F30A7E9D6), UINT64_C(0x7B981EBD6E2D07CB), + UINT64_C(0x1F7A6BDB8CB334ED), UINT64_C(0xC3DB47F9D239DAF0), + UINT64_C(0xD7BE8017488E53A1), UINT64_C(0x0B1FAC351604BDBC), + UINT64_C(0x6FFDD953F49A8E9A), UINT64_C(0xB35CF571AA106087), + UINT64_C(0x4737578EC1F59D39), UINT64_C(0x9B967BAC9F7F7324), + UINT64_C(0xFF740ECA7DE14002), UINT64_C(0x23D522E8236BAE1F), + UINT64_C(0x37B0E506B9DC274E), UINT64_C(0xEB11C924E756C953), + UINT64_C(0x8FF3BC4205C8FA75), UINT64_C(0x535290605B421468), + UINT64_C(0xE23AF612F9ADD99A), UINT64_C(0x3E9BDA30A7273787), + UINT64_C(0x5A79AF5645B904A1), UINT64_C(0x86D883741B33EABC), + UINT64_C(0x92BD449A818463ED), UINT64_C(0x4E1C68B8DF0E8DF0), + UINT64_C(0x2AFE1DDE3D90BED6), UINT64_C(0xF65F31FC631A50CB), + UINT64_C(0x0234930308FFAD75), UINT64_C(0xDE95BF2156754368), + UINT64_C(0xBA77CA47B4EB704E), UINT64_C(0x66D6E665EA619E53), + UINT64_C(0x72B3218B70D61702), UINT64_C(0xAE120DA92E5CF91F), + UINT64_C(0xCAF078CFCCC2CA39), UINT64_C(0x165154ED92482424), + UINT64_C(0x2D3FBA84A3B2894E), UINT64_C(0xF19E96A6FD386753), + UINT64_C(0x957CE3C01FA65475), UINT64_C(0x49DDCFE2412CBA68), + UINT64_C(0x5DB8080CDB9B3339), UINT64_C(0x8119242E8511DD24), + UINT64_C(0xE5FB5148678FEE02), UINT64_C(0x395A7D6A3905001F), + UINT64_C(0xCD31DF9552E0FDA1), UINT64_C(0x1190F3B70C6A13BC), + UINT64_C(0x757286D1EEF4209A), UINT64_C(0xA9D3AAF3B07ECE87), + UINT64_C(0xBDB66D1D2AC947D6), UINT64_C(0x6117413F7443A9CB), + UINT64_C(0x05F5345996DD9AED), UINT64_C(0xD954187BC85774F0), + UINT64_C(0x683C7E096AB8B902), UINT64_C(0xB49D522B3432571F), + UINT64_C(0xD07F274DD6AC6439), UINT64_C(0x0CDE0B6F88268A24), + UINT64_C(0x18BBCC8112910375), UINT64_C(0xC41AE0A34C1BED68), + UINT64_C(0xA0F895C5AE85DE4E), UINT64_C(0x7C59B9E7F00F3053), + UINT64_C(0x88321B189BEACDED), UINT64_C(0x5493373AC56023F0), + UINT64_C(0x3071425C27FE10D6), UINT64_C(0xECD06E7E7974FECB), + UINT64_C(0xF8B5A990E3C3779A), UINT64_C(0x241485B2BD499987), + UINT64_C(0x40F6F0D45FD7AAA1), UINT64_C(0x9C57DCF6015D44BC), + UINT64_C(0x362A2C073D23F174), UINT64_C(0xEA8B002563A91F69), + UINT64_C(0x8E69754381372C4F), UINT64_C(0x52C85961DFBDC252), + UINT64_C(0x46AD9E8F450A4B03), UINT64_C(0x9A0CB2AD1B80A51E), + UINT64_C(0xFEEEC7CBF91E9638), UINT64_C(0x224FEBE9A7947825), + UINT64_C(0xD6244916CC71859B), UINT64_C(0x0A85653492FB6B86), + UINT64_C(0x6E671052706558A0), UINT64_C(0xB2C63C702EEFB6BD), + UINT64_C(0xA6A3FB9EB4583FEC), UINT64_C(0x7A02D7BCEAD2D1F1), + UINT64_C(0x1EE0A2DA084CE2D7), UINT64_C(0xC2418EF856C60CCA), + UINT64_C(0x7329E88AF429C138), UINT64_C(0xAF88C4A8AAA32F25), + UINT64_C(0xCB6AB1CE483D1C03), UINT64_C(0x17CB9DEC16B7F21E), + UINT64_C(0x03AE5A028C007B4F), UINT64_C(0xDF0F7620D28A9552), + UINT64_C(0xBBED03463014A674), UINT64_C(0x674C2F646E9E4869), + UINT64_C(0x93278D9B057BB5D7), UINT64_C(0x4F86A1B95BF15BCA), + UINT64_C(0x2B64D4DFB96F68EC), UINT64_C(0xF7C5F8FDE7E586F1), + UINT64_C(0xE3A03F137D520FA0), UINT64_C(0x3F01133123D8E1BD), + UINT64_C(0x5BE36657C146D29B), UINT64_C(0x87424A759FCC3C86), + UINT64_C(0xBC2CA41CAE3691EC), UINT64_C(0x608D883EF0BC7FF1), + UINT64_C(0x046FFD5812224CD7), UINT64_C(0xD8CED17A4CA8A2CA), + UINT64_C(0xCCAB1694D61F2B9B), UINT64_C(0x100A3AB68895C586), + UINT64_C(0x74E84FD06A0BF6A0), UINT64_C(0xA84963F2348118BD), + UINT64_C(0x5C22C10D5F64E503), UINT64_C(0x8083ED2F01EE0B1E), + UINT64_C(0xE4619849E3703838), UINT64_C(0x38C0B46BBDFAD625), + UINT64_C(0x2CA57385274D5F74), UINT64_C(0xF0045FA779C7B169), + UINT64_C(0x94E62AC19B59824F), UINT64_C(0x484706E3C5D36C52), + UINT64_C(0xF92F6091673CA1A0), UINT64_C(0x258E4CB339B64FBD), + UINT64_C(0x416C39D5DB287C9B), UINT64_C(0x9DCD15F785A29286), + UINT64_C(0x89A8D2191F151BD7), UINT64_C(0x5509FE3B419FF5CA), + UINT64_C(0x31EB8B5DA301C6EC), UINT64_C(0xED4AA77FFD8B28F1), + UINT64_C(0x19210580966ED54F), UINT64_C(0xC58029A2C8E43B52), + UINT64_C(0xA1625CC42A7A0874), UINT64_C(0x7DC370E674F0E669), + UINT64_C(0x69A6B708EE476F38), UINT64_C(0xB5079B2AB0CD8125), + UINT64_C(0xD1E5EE4C5253B203), UINT64_C(0x0D44C26E0CD95C1E) + } +}; diff --git a/dependencies/cmliblzma/liblzma/check/crc64_table_le.h b/dependencies/cmliblzma/liblzma/check/crc64_table_le.h new file mode 100644 index 0000000..1196b31 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/check/crc64_table_le.h @@ -0,0 +1,521 @@ +/* This file has been automatically generated by crc64_tablegen.c. */ + +const uint64_t lzma_crc64_table[4][256] = { + { + UINT64_C(0x0000000000000000), UINT64_C(0xB32E4CBE03A75F6F), + UINT64_C(0xF4843657A840A05B), UINT64_C(0x47AA7AE9ABE7FF34), + UINT64_C(0x7BD0C384FF8F5E33), UINT64_C(0xC8FE8F3AFC28015C), + UINT64_C(0x8F54F5D357CFFE68), UINT64_C(0x3C7AB96D5468A107), + UINT64_C(0xF7A18709FF1EBC66), UINT64_C(0x448FCBB7FCB9E309), + UINT64_C(0x0325B15E575E1C3D), UINT64_C(0xB00BFDE054F94352), + UINT64_C(0x8C71448D0091E255), UINT64_C(0x3F5F08330336BD3A), + UINT64_C(0x78F572DAA8D1420E), UINT64_C(0xCBDB3E64AB761D61), + UINT64_C(0x7D9BA13851336649), UINT64_C(0xCEB5ED8652943926), + UINT64_C(0x891F976FF973C612), UINT64_C(0x3A31DBD1FAD4997D), + UINT64_C(0x064B62BCAEBC387A), UINT64_C(0xB5652E02AD1B6715), + UINT64_C(0xF2CF54EB06FC9821), UINT64_C(0x41E11855055BC74E), + UINT64_C(0x8A3A2631AE2DDA2F), UINT64_C(0x39146A8FAD8A8540), + UINT64_C(0x7EBE1066066D7A74), UINT64_C(0xCD905CD805CA251B), + UINT64_C(0xF1EAE5B551A2841C), UINT64_C(0x42C4A90B5205DB73), + UINT64_C(0x056ED3E2F9E22447), UINT64_C(0xB6409F5CFA457B28), + UINT64_C(0xFB374270A266CC92), UINT64_C(0x48190ECEA1C193FD), + UINT64_C(0x0FB374270A266CC9), UINT64_C(0xBC9D3899098133A6), + UINT64_C(0x80E781F45DE992A1), UINT64_C(0x33C9CD4A5E4ECDCE), + UINT64_C(0x7463B7A3F5A932FA), UINT64_C(0xC74DFB1DF60E6D95), + UINT64_C(0x0C96C5795D7870F4), UINT64_C(0xBFB889C75EDF2F9B), + UINT64_C(0xF812F32EF538D0AF), UINT64_C(0x4B3CBF90F69F8FC0), + UINT64_C(0x774606FDA2F72EC7), UINT64_C(0xC4684A43A15071A8), + UINT64_C(0x83C230AA0AB78E9C), UINT64_C(0x30EC7C140910D1F3), + UINT64_C(0x86ACE348F355AADB), UINT64_C(0x3582AFF6F0F2F5B4), + UINT64_C(0x7228D51F5B150A80), UINT64_C(0xC10699A158B255EF), + UINT64_C(0xFD7C20CC0CDAF4E8), UINT64_C(0x4E526C720F7DAB87), + UINT64_C(0x09F8169BA49A54B3), UINT64_C(0xBAD65A25A73D0BDC), + UINT64_C(0x710D64410C4B16BD), UINT64_C(0xC22328FF0FEC49D2), + UINT64_C(0x85895216A40BB6E6), UINT64_C(0x36A71EA8A7ACE989), + UINT64_C(0x0ADDA7C5F3C4488E), UINT64_C(0xB9F3EB7BF06317E1), + UINT64_C(0xFE5991925B84E8D5), UINT64_C(0x4D77DD2C5823B7BA), + UINT64_C(0x64B62BCAEBC387A1), UINT64_C(0xD7986774E864D8CE), + UINT64_C(0x90321D9D438327FA), UINT64_C(0x231C512340247895), + UINT64_C(0x1F66E84E144CD992), UINT64_C(0xAC48A4F017EB86FD), + UINT64_C(0xEBE2DE19BC0C79C9), UINT64_C(0x58CC92A7BFAB26A6), + UINT64_C(0x9317ACC314DD3BC7), UINT64_C(0x2039E07D177A64A8), + UINT64_C(0x67939A94BC9D9B9C), UINT64_C(0xD4BDD62ABF3AC4F3), + UINT64_C(0xE8C76F47EB5265F4), UINT64_C(0x5BE923F9E8F53A9B), + UINT64_C(0x1C4359104312C5AF), UINT64_C(0xAF6D15AE40B59AC0), + UINT64_C(0x192D8AF2BAF0E1E8), UINT64_C(0xAA03C64CB957BE87), + UINT64_C(0xEDA9BCA512B041B3), UINT64_C(0x5E87F01B11171EDC), + UINT64_C(0x62FD4976457FBFDB), UINT64_C(0xD1D305C846D8E0B4), + UINT64_C(0x96797F21ED3F1F80), UINT64_C(0x2557339FEE9840EF), + UINT64_C(0xEE8C0DFB45EE5D8E), UINT64_C(0x5DA24145464902E1), + UINT64_C(0x1A083BACEDAEFDD5), UINT64_C(0xA9267712EE09A2BA), + UINT64_C(0x955CCE7FBA6103BD), UINT64_C(0x267282C1B9C65CD2), + UINT64_C(0x61D8F8281221A3E6), UINT64_C(0xD2F6B4961186FC89), + UINT64_C(0x9F8169BA49A54B33), UINT64_C(0x2CAF25044A02145C), + UINT64_C(0x6B055FEDE1E5EB68), UINT64_C(0xD82B1353E242B407), + UINT64_C(0xE451AA3EB62A1500), UINT64_C(0x577FE680B58D4A6F), + UINT64_C(0x10D59C691E6AB55B), UINT64_C(0xA3FBD0D71DCDEA34), + UINT64_C(0x6820EEB3B6BBF755), UINT64_C(0xDB0EA20DB51CA83A), + UINT64_C(0x9CA4D8E41EFB570E), UINT64_C(0x2F8A945A1D5C0861), + UINT64_C(0x13F02D374934A966), UINT64_C(0xA0DE61894A93F609), + UINT64_C(0xE7741B60E174093D), UINT64_C(0x545A57DEE2D35652), + UINT64_C(0xE21AC88218962D7A), UINT64_C(0x5134843C1B317215), + UINT64_C(0x169EFED5B0D68D21), UINT64_C(0xA5B0B26BB371D24E), + UINT64_C(0x99CA0B06E7197349), UINT64_C(0x2AE447B8E4BE2C26), + UINT64_C(0x6D4E3D514F59D312), UINT64_C(0xDE6071EF4CFE8C7D), + UINT64_C(0x15BB4F8BE788911C), UINT64_C(0xA6950335E42FCE73), + UINT64_C(0xE13F79DC4FC83147), UINT64_C(0x521135624C6F6E28), + UINT64_C(0x6E6B8C0F1807CF2F), UINT64_C(0xDD45C0B11BA09040), + UINT64_C(0x9AEFBA58B0476F74), UINT64_C(0x29C1F6E6B3E0301B), + UINT64_C(0xC96C5795D7870F42), UINT64_C(0x7A421B2BD420502D), + UINT64_C(0x3DE861C27FC7AF19), UINT64_C(0x8EC62D7C7C60F076), + UINT64_C(0xB2BC941128085171), UINT64_C(0x0192D8AF2BAF0E1E), + UINT64_C(0x4638A2468048F12A), UINT64_C(0xF516EEF883EFAE45), + UINT64_C(0x3ECDD09C2899B324), UINT64_C(0x8DE39C222B3EEC4B), + UINT64_C(0xCA49E6CB80D9137F), UINT64_C(0x7967AA75837E4C10), + UINT64_C(0x451D1318D716ED17), UINT64_C(0xF6335FA6D4B1B278), + UINT64_C(0xB199254F7F564D4C), UINT64_C(0x02B769F17CF11223), + UINT64_C(0xB4F7F6AD86B4690B), UINT64_C(0x07D9BA1385133664), + UINT64_C(0x4073C0FA2EF4C950), UINT64_C(0xF35D8C442D53963F), + UINT64_C(0xCF273529793B3738), UINT64_C(0x7C0979977A9C6857), + UINT64_C(0x3BA3037ED17B9763), UINT64_C(0x888D4FC0D2DCC80C), + UINT64_C(0x435671A479AAD56D), UINT64_C(0xF0783D1A7A0D8A02), + UINT64_C(0xB7D247F3D1EA7536), UINT64_C(0x04FC0B4DD24D2A59), + UINT64_C(0x3886B22086258B5E), UINT64_C(0x8BA8FE9E8582D431), + UINT64_C(0xCC0284772E652B05), UINT64_C(0x7F2CC8C92DC2746A), + UINT64_C(0x325B15E575E1C3D0), UINT64_C(0x8175595B76469CBF), + UINT64_C(0xC6DF23B2DDA1638B), UINT64_C(0x75F16F0CDE063CE4), + UINT64_C(0x498BD6618A6E9DE3), UINT64_C(0xFAA59ADF89C9C28C), + UINT64_C(0xBD0FE036222E3DB8), UINT64_C(0x0E21AC88218962D7), + UINT64_C(0xC5FA92EC8AFF7FB6), UINT64_C(0x76D4DE52895820D9), + UINT64_C(0x317EA4BB22BFDFED), UINT64_C(0x8250E80521188082), + UINT64_C(0xBE2A516875702185), UINT64_C(0x0D041DD676D77EEA), + UINT64_C(0x4AAE673FDD3081DE), UINT64_C(0xF9802B81DE97DEB1), + UINT64_C(0x4FC0B4DD24D2A599), UINT64_C(0xFCEEF8632775FAF6), + UINT64_C(0xBB44828A8C9205C2), UINT64_C(0x086ACE348F355AAD), + UINT64_C(0x34107759DB5DFBAA), UINT64_C(0x873E3BE7D8FAA4C5), + UINT64_C(0xC094410E731D5BF1), UINT64_C(0x73BA0DB070BA049E), + UINT64_C(0xB86133D4DBCC19FF), UINT64_C(0x0B4F7F6AD86B4690), + UINT64_C(0x4CE50583738CB9A4), UINT64_C(0xFFCB493D702BE6CB), + UINT64_C(0xC3B1F050244347CC), UINT64_C(0x709FBCEE27E418A3), + UINT64_C(0x3735C6078C03E797), UINT64_C(0x841B8AB98FA4B8F8), + UINT64_C(0xADDA7C5F3C4488E3), UINT64_C(0x1EF430E13FE3D78C), + UINT64_C(0x595E4A08940428B8), UINT64_C(0xEA7006B697A377D7), + UINT64_C(0xD60ABFDBC3CBD6D0), UINT64_C(0x6524F365C06C89BF), + UINT64_C(0x228E898C6B8B768B), UINT64_C(0x91A0C532682C29E4), + UINT64_C(0x5A7BFB56C35A3485), UINT64_C(0xE955B7E8C0FD6BEA), + UINT64_C(0xAEFFCD016B1A94DE), UINT64_C(0x1DD181BF68BDCBB1), + UINT64_C(0x21AB38D23CD56AB6), UINT64_C(0x9285746C3F7235D9), + UINT64_C(0xD52F0E859495CAED), UINT64_C(0x6601423B97329582), + UINT64_C(0xD041DD676D77EEAA), UINT64_C(0x636F91D96ED0B1C5), + UINT64_C(0x24C5EB30C5374EF1), UINT64_C(0x97EBA78EC690119E), + UINT64_C(0xAB911EE392F8B099), UINT64_C(0x18BF525D915FEFF6), + UINT64_C(0x5F1528B43AB810C2), UINT64_C(0xEC3B640A391F4FAD), + UINT64_C(0x27E05A6E926952CC), UINT64_C(0x94CE16D091CE0DA3), + UINT64_C(0xD3646C393A29F297), UINT64_C(0x604A2087398EADF8), + UINT64_C(0x5C3099EA6DE60CFF), UINT64_C(0xEF1ED5546E415390), + UINT64_C(0xA8B4AFBDC5A6ACA4), UINT64_C(0x1B9AE303C601F3CB), + UINT64_C(0x56ED3E2F9E224471), UINT64_C(0xE5C372919D851B1E), + UINT64_C(0xA26908783662E42A), UINT64_C(0x114744C635C5BB45), + UINT64_C(0x2D3DFDAB61AD1A42), UINT64_C(0x9E13B115620A452D), + UINT64_C(0xD9B9CBFCC9EDBA19), UINT64_C(0x6A978742CA4AE576), + UINT64_C(0xA14CB926613CF817), UINT64_C(0x1262F598629BA778), + UINT64_C(0x55C88F71C97C584C), UINT64_C(0xE6E6C3CFCADB0723), + UINT64_C(0xDA9C7AA29EB3A624), UINT64_C(0x69B2361C9D14F94B), + UINT64_C(0x2E184CF536F3067F), UINT64_C(0x9D36004B35545910), + UINT64_C(0x2B769F17CF112238), UINT64_C(0x9858D3A9CCB67D57), + UINT64_C(0xDFF2A94067518263), UINT64_C(0x6CDCE5FE64F6DD0C), + UINT64_C(0x50A65C93309E7C0B), UINT64_C(0xE388102D33392364), + UINT64_C(0xA4226AC498DEDC50), UINT64_C(0x170C267A9B79833F), + UINT64_C(0xDCD7181E300F9E5E), UINT64_C(0x6FF954A033A8C131), + UINT64_C(0x28532E49984F3E05), UINT64_C(0x9B7D62F79BE8616A), + UINT64_C(0xA707DB9ACF80C06D), UINT64_C(0x14299724CC279F02), + UINT64_C(0x5383EDCD67C06036), UINT64_C(0xE0ADA17364673F59) + }, { + UINT64_C(0x0000000000000000), UINT64_C(0x54E979925CD0F10D), + UINT64_C(0xA9D2F324B9A1E21A), UINT64_C(0xFD3B8AB6E5711317), + UINT64_C(0xC17D4962DC4DDAB1), UINT64_C(0x959430F0809D2BBC), + UINT64_C(0x68AFBA4665EC38AB), UINT64_C(0x3C46C3D4393CC9A6), + UINT64_C(0x10223DEE1795ABE7), UINT64_C(0x44CB447C4B455AEA), + UINT64_C(0xB9F0CECAAE3449FD), UINT64_C(0xED19B758F2E4B8F0), + UINT64_C(0xD15F748CCBD87156), UINT64_C(0x85B60D1E9708805B), + UINT64_C(0x788D87A87279934C), UINT64_C(0x2C64FE3A2EA96241), + UINT64_C(0x20447BDC2F2B57CE), UINT64_C(0x74AD024E73FBA6C3), + UINT64_C(0x899688F8968AB5D4), UINT64_C(0xDD7FF16ACA5A44D9), + UINT64_C(0xE13932BEF3668D7F), UINT64_C(0xB5D04B2CAFB67C72), + UINT64_C(0x48EBC19A4AC76F65), UINT64_C(0x1C02B80816179E68), + UINT64_C(0x3066463238BEFC29), UINT64_C(0x648F3FA0646E0D24), + UINT64_C(0x99B4B516811F1E33), UINT64_C(0xCD5DCC84DDCFEF3E), + UINT64_C(0xF11B0F50E4F32698), UINT64_C(0xA5F276C2B823D795), + UINT64_C(0x58C9FC745D52C482), UINT64_C(0x0C2085E60182358F), + UINT64_C(0x4088F7B85E56AF9C), UINT64_C(0x14618E2A02865E91), + UINT64_C(0xE95A049CE7F74D86), UINT64_C(0xBDB37D0EBB27BC8B), + UINT64_C(0x81F5BEDA821B752D), UINT64_C(0xD51CC748DECB8420), + UINT64_C(0x28274DFE3BBA9737), UINT64_C(0x7CCE346C676A663A), + UINT64_C(0x50AACA5649C3047B), UINT64_C(0x0443B3C41513F576), + UINT64_C(0xF9783972F062E661), UINT64_C(0xAD9140E0ACB2176C), + UINT64_C(0x91D78334958EDECA), UINT64_C(0xC53EFAA6C95E2FC7), + UINT64_C(0x380570102C2F3CD0), UINT64_C(0x6CEC098270FFCDDD), + UINT64_C(0x60CC8C64717DF852), UINT64_C(0x3425F5F62DAD095F), + UINT64_C(0xC91E7F40C8DC1A48), UINT64_C(0x9DF706D2940CEB45), + UINT64_C(0xA1B1C506AD3022E3), UINT64_C(0xF558BC94F1E0D3EE), + UINT64_C(0x086336221491C0F9), UINT64_C(0x5C8A4FB0484131F4), + UINT64_C(0x70EEB18A66E853B5), UINT64_C(0x2407C8183A38A2B8), + UINT64_C(0xD93C42AEDF49B1AF), UINT64_C(0x8DD53B3C839940A2), + UINT64_C(0xB193F8E8BAA58904), UINT64_C(0xE57A817AE6757809), + UINT64_C(0x18410BCC03046B1E), UINT64_C(0x4CA8725E5FD49A13), + UINT64_C(0x8111EF70BCAD5F38), UINT64_C(0xD5F896E2E07DAE35), + UINT64_C(0x28C31C54050CBD22), UINT64_C(0x7C2A65C659DC4C2F), + UINT64_C(0x406CA61260E08589), UINT64_C(0x1485DF803C307484), + UINT64_C(0xE9BE5536D9416793), UINT64_C(0xBD572CA48591969E), + UINT64_C(0x9133D29EAB38F4DF), UINT64_C(0xC5DAAB0CF7E805D2), + UINT64_C(0x38E121BA129916C5), UINT64_C(0x6C0858284E49E7C8), + UINT64_C(0x504E9BFC77752E6E), UINT64_C(0x04A7E26E2BA5DF63), + UINT64_C(0xF99C68D8CED4CC74), UINT64_C(0xAD75114A92043D79), + UINT64_C(0xA15594AC938608F6), UINT64_C(0xF5BCED3ECF56F9FB), + UINT64_C(0x088767882A27EAEC), UINT64_C(0x5C6E1E1A76F71BE1), + UINT64_C(0x6028DDCE4FCBD247), UINT64_C(0x34C1A45C131B234A), + UINT64_C(0xC9FA2EEAF66A305D), UINT64_C(0x9D135778AABAC150), + UINT64_C(0xB177A9428413A311), UINT64_C(0xE59ED0D0D8C3521C), + UINT64_C(0x18A55A663DB2410B), UINT64_C(0x4C4C23F46162B006), + UINT64_C(0x700AE020585E79A0), UINT64_C(0x24E399B2048E88AD), + UINT64_C(0xD9D81304E1FF9BBA), UINT64_C(0x8D316A96BD2F6AB7), + UINT64_C(0xC19918C8E2FBF0A4), UINT64_C(0x9570615ABE2B01A9), + UINT64_C(0x684BEBEC5B5A12BE), UINT64_C(0x3CA2927E078AE3B3), + UINT64_C(0x00E451AA3EB62A15), UINT64_C(0x540D28386266DB18), + UINT64_C(0xA936A28E8717C80F), UINT64_C(0xFDDFDB1CDBC73902), + UINT64_C(0xD1BB2526F56E5B43), UINT64_C(0x85525CB4A9BEAA4E), + UINT64_C(0x7869D6024CCFB959), UINT64_C(0x2C80AF90101F4854), + UINT64_C(0x10C66C44292381F2), UINT64_C(0x442F15D675F370FF), + UINT64_C(0xB9149F60908263E8), UINT64_C(0xEDFDE6F2CC5292E5), + UINT64_C(0xE1DD6314CDD0A76A), UINT64_C(0xB5341A8691005667), + UINT64_C(0x480F903074714570), UINT64_C(0x1CE6E9A228A1B47D), + UINT64_C(0x20A02A76119D7DDB), UINT64_C(0x744953E44D4D8CD6), + UINT64_C(0x8972D952A83C9FC1), UINT64_C(0xDD9BA0C0F4EC6ECC), + UINT64_C(0xF1FF5EFADA450C8D), UINT64_C(0xA51627688695FD80), + UINT64_C(0x582DADDE63E4EE97), UINT64_C(0x0CC4D44C3F341F9A), + UINT64_C(0x308217980608D63C), UINT64_C(0x646B6E0A5AD82731), + UINT64_C(0x9950E4BCBFA93426), UINT64_C(0xCDB99D2EE379C52B), + UINT64_C(0x90FB71CAD654A0F5), UINT64_C(0xC41208588A8451F8), + UINT64_C(0x392982EE6FF542EF), UINT64_C(0x6DC0FB7C3325B3E2), + UINT64_C(0x518638A80A197A44), UINT64_C(0x056F413A56C98B49), + UINT64_C(0xF854CB8CB3B8985E), UINT64_C(0xACBDB21EEF686953), + UINT64_C(0x80D94C24C1C10B12), UINT64_C(0xD43035B69D11FA1F), + UINT64_C(0x290BBF007860E908), UINT64_C(0x7DE2C69224B01805), + UINT64_C(0x41A405461D8CD1A3), UINT64_C(0x154D7CD4415C20AE), + UINT64_C(0xE876F662A42D33B9), UINT64_C(0xBC9F8FF0F8FDC2B4), + UINT64_C(0xB0BF0A16F97FF73B), UINT64_C(0xE4567384A5AF0636), + UINT64_C(0x196DF93240DE1521), UINT64_C(0x4D8480A01C0EE42C), + UINT64_C(0x71C2437425322D8A), UINT64_C(0x252B3AE679E2DC87), + UINT64_C(0xD810B0509C93CF90), UINT64_C(0x8CF9C9C2C0433E9D), + UINT64_C(0xA09D37F8EEEA5CDC), UINT64_C(0xF4744E6AB23AADD1), + UINT64_C(0x094FC4DC574BBEC6), UINT64_C(0x5DA6BD4E0B9B4FCB), + UINT64_C(0x61E07E9A32A7866D), UINT64_C(0x350907086E777760), + UINT64_C(0xC8328DBE8B066477), UINT64_C(0x9CDBF42CD7D6957A), + UINT64_C(0xD073867288020F69), UINT64_C(0x849AFFE0D4D2FE64), + UINT64_C(0x79A1755631A3ED73), UINT64_C(0x2D480CC46D731C7E), + UINT64_C(0x110ECF10544FD5D8), UINT64_C(0x45E7B682089F24D5), + UINT64_C(0xB8DC3C34EDEE37C2), UINT64_C(0xEC3545A6B13EC6CF), + UINT64_C(0xC051BB9C9F97A48E), UINT64_C(0x94B8C20EC3475583), + UINT64_C(0x698348B826364694), UINT64_C(0x3D6A312A7AE6B799), + UINT64_C(0x012CF2FE43DA7E3F), UINT64_C(0x55C58B6C1F0A8F32), + UINT64_C(0xA8FE01DAFA7B9C25), UINT64_C(0xFC177848A6AB6D28), + UINT64_C(0xF037FDAEA72958A7), UINT64_C(0xA4DE843CFBF9A9AA), + UINT64_C(0x59E50E8A1E88BABD), UINT64_C(0x0D0C771842584BB0), + UINT64_C(0x314AB4CC7B648216), UINT64_C(0x65A3CD5E27B4731B), + UINT64_C(0x989847E8C2C5600C), UINT64_C(0xCC713E7A9E159101), + UINT64_C(0xE015C040B0BCF340), UINT64_C(0xB4FCB9D2EC6C024D), + UINT64_C(0x49C73364091D115A), UINT64_C(0x1D2E4AF655CDE057), + UINT64_C(0x216889226CF129F1), UINT64_C(0x7581F0B03021D8FC), + UINT64_C(0x88BA7A06D550CBEB), UINT64_C(0xDC53039489803AE6), + UINT64_C(0x11EA9EBA6AF9FFCD), UINT64_C(0x4503E72836290EC0), + UINT64_C(0xB8386D9ED3581DD7), UINT64_C(0xECD1140C8F88ECDA), + UINT64_C(0xD097D7D8B6B4257C), UINT64_C(0x847EAE4AEA64D471), + UINT64_C(0x794524FC0F15C766), UINT64_C(0x2DAC5D6E53C5366B), + UINT64_C(0x01C8A3547D6C542A), UINT64_C(0x5521DAC621BCA527), + UINT64_C(0xA81A5070C4CDB630), UINT64_C(0xFCF329E2981D473D), + UINT64_C(0xC0B5EA36A1218E9B), UINT64_C(0x945C93A4FDF17F96), + UINT64_C(0x6967191218806C81), UINT64_C(0x3D8E608044509D8C), + UINT64_C(0x31AEE56645D2A803), UINT64_C(0x65479CF41902590E), + UINT64_C(0x987C1642FC734A19), UINT64_C(0xCC956FD0A0A3BB14), + UINT64_C(0xF0D3AC04999F72B2), UINT64_C(0xA43AD596C54F83BF), + UINT64_C(0x59015F20203E90A8), UINT64_C(0x0DE826B27CEE61A5), + UINT64_C(0x218CD888524703E4), UINT64_C(0x7565A11A0E97F2E9), + UINT64_C(0x885E2BACEBE6E1FE), UINT64_C(0xDCB7523EB73610F3), + UINT64_C(0xE0F191EA8E0AD955), UINT64_C(0xB418E878D2DA2858), + UINT64_C(0x492362CE37AB3B4F), UINT64_C(0x1DCA1B5C6B7BCA42), + UINT64_C(0x5162690234AF5051), UINT64_C(0x058B1090687FA15C), + UINT64_C(0xF8B09A268D0EB24B), UINT64_C(0xAC59E3B4D1DE4346), + UINT64_C(0x901F2060E8E28AE0), UINT64_C(0xC4F659F2B4327BED), + UINT64_C(0x39CDD344514368FA), UINT64_C(0x6D24AAD60D9399F7), + UINT64_C(0x414054EC233AFBB6), UINT64_C(0x15A92D7E7FEA0ABB), + UINT64_C(0xE892A7C89A9B19AC), UINT64_C(0xBC7BDE5AC64BE8A1), + UINT64_C(0x803D1D8EFF772107), UINT64_C(0xD4D4641CA3A7D00A), + UINT64_C(0x29EFEEAA46D6C31D), UINT64_C(0x7D0697381A063210), + UINT64_C(0x712612DE1B84079F), UINT64_C(0x25CF6B4C4754F692), + UINT64_C(0xD8F4E1FAA225E585), UINT64_C(0x8C1D9868FEF51488), + UINT64_C(0xB05B5BBCC7C9DD2E), UINT64_C(0xE4B2222E9B192C23), + UINT64_C(0x1989A8987E683F34), UINT64_C(0x4D60D10A22B8CE39), + UINT64_C(0x61042F300C11AC78), UINT64_C(0x35ED56A250C15D75), + UINT64_C(0xC8D6DC14B5B04E62), UINT64_C(0x9C3FA586E960BF6F), + UINT64_C(0xA0796652D05C76C9), UINT64_C(0xF4901FC08C8C87C4), + UINT64_C(0x09AB957669FD94D3), UINT64_C(0x5D42ECE4352D65DE) + }, { + UINT64_C(0x0000000000000000), UINT64_C(0x3F0BE14A916A6DCB), + UINT64_C(0x7E17C29522D4DB96), UINT64_C(0x411C23DFB3BEB65D), + UINT64_C(0xFC2F852A45A9B72C), UINT64_C(0xC3246460D4C3DAE7), + UINT64_C(0x823847BF677D6CBA), UINT64_C(0xBD33A6F5F6170171), + UINT64_C(0x6A87A57F245D70DD), UINT64_C(0x558C4435B5371D16), + UINT64_C(0x149067EA0689AB4B), UINT64_C(0x2B9B86A097E3C680), + UINT64_C(0x96A8205561F4C7F1), UINT64_C(0xA9A3C11FF09EAA3A), + UINT64_C(0xE8BFE2C043201C67), UINT64_C(0xD7B4038AD24A71AC), + UINT64_C(0xD50F4AFE48BAE1BA), UINT64_C(0xEA04ABB4D9D08C71), + UINT64_C(0xAB18886B6A6E3A2C), UINT64_C(0x94136921FB0457E7), + UINT64_C(0x2920CFD40D135696), UINT64_C(0x162B2E9E9C793B5D), + UINT64_C(0x57370D412FC78D00), UINT64_C(0x683CEC0BBEADE0CB), + UINT64_C(0xBF88EF816CE79167), UINT64_C(0x80830ECBFD8DFCAC), + UINT64_C(0xC19F2D144E334AF1), UINT64_C(0xFE94CC5EDF59273A), + UINT64_C(0x43A76AAB294E264B), UINT64_C(0x7CAC8BE1B8244B80), + UINT64_C(0x3DB0A83E0B9AFDDD), UINT64_C(0x02BB49749AF09016), + UINT64_C(0x38C63AD73E7BDDF1), UINT64_C(0x07CDDB9DAF11B03A), + UINT64_C(0x46D1F8421CAF0667), UINT64_C(0x79DA19088DC56BAC), + UINT64_C(0xC4E9BFFD7BD26ADD), UINT64_C(0xFBE25EB7EAB80716), + UINT64_C(0xBAFE7D685906B14B), UINT64_C(0x85F59C22C86CDC80), + UINT64_C(0x52419FA81A26AD2C), UINT64_C(0x6D4A7EE28B4CC0E7), + UINT64_C(0x2C565D3D38F276BA), UINT64_C(0x135DBC77A9981B71), + UINT64_C(0xAE6E1A825F8F1A00), UINT64_C(0x9165FBC8CEE577CB), + UINT64_C(0xD079D8177D5BC196), UINT64_C(0xEF72395DEC31AC5D), + UINT64_C(0xEDC9702976C13C4B), UINT64_C(0xD2C29163E7AB5180), + UINT64_C(0x93DEB2BC5415E7DD), UINT64_C(0xACD553F6C57F8A16), + UINT64_C(0x11E6F50333688B67), UINT64_C(0x2EED1449A202E6AC), + UINT64_C(0x6FF1379611BC50F1), UINT64_C(0x50FAD6DC80D63D3A), + UINT64_C(0x874ED556529C4C96), UINT64_C(0xB845341CC3F6215D), + UINT64_C(0xF95917C370489700), UINT64_C(0xC652F689E122FACB), + UINT64_C(0x7B61507C1735FBBA), UINT64_C(0x446AB136865F9671), + UINT64_C(0x057692E935E1202C), UINT64_C(0x3A7D73A3A48B4DE7), + UINT64_C(0x718C75AE7CF7BBE2), UINT64_C(0x4E8794E4ED9DD629), + UINT64_C(0x0F9BB73B5E236074), UINT64_C(0x30905671CF490DBF), + UINT64_C(0x8DA3F084395E0CCE), UINT64_C(0xB2A811CEA8346105), + UINT64_C(0xF3B432111B8AD758), UINT64_C(0xCCBFD35B8AE0BA93), + UINT64_C(0x1B0BD0D158AACB3F), UINT64_C(0x2400319BC9C0A6F4), + UINT64_C(0x651C12447A7E10A9), UINT64_C(0x5A17F30EEB147D62), + UINT64_C(0xE72455FB1D037C13), UINT64_C(0xD82FB4B18C6911D8), + UINT64_C(0x9933976E3FD7A785), UINT64_C(0xA6387624AEBDCA4E), + UINT64_C(0xA4833F50344D5A58), UINT64_C(0x9B88DE1AA5273793), + UINT64_C(0xDA94FDC5169981CE), UINT64_C(0xE59F1C8F87F3EC05), + UINT64_C(0x58ACBA7A71E4ED74), UINT64_C(0x67A75B30E08E80BF), + UINT64_C(0x26BB78EF533036E2), UINT64_C(0x19B099A5C25A5B29), + UINT64_C(0xCE049A2F10102A85), UINT64_C(0xF10F7B65817A474E), + UINT64_C(0xB01358BA32C4F113), UINT64_C(0x8F18B9F0A3AE9CD8), + UINT64_C(0x322B1F0555B99DA9), UINT64_C(0x0D20FE4FC4D3F062), + UINT64_C(0x4C3CDD90776D463F), UINT64_C(0x73373CDAE6072BF4), + UINT64_C(0x494A4F79428C6613), UINT64_C(0x7641AE33D3E60BD8), + UINT64_C(0x375D8DEC6058BD85), UINT64_C(0x08566CA6F132D04E), + UINT64_C(0xB565CA530725D13F), UINT64_C(0x8A6E2B19964FBCF4), + UINT64_C(0xCB7208C625F10AA9), UINT64_C(0xF479E98CB49B6762), + UINT64_C(0x23CDEA0666D116CE), UINT64_C(0x1CC60B4CF7BB7B05), + UINT64_C(0x5DDA28934405CD58), UINT64_C(0x62D1C9D9D56FA093), + UINT64_C(0xDFE26F2C2378A1E2), UINT64_C(0xE0E98E66B212CC29), + UINT64_C(0xA1F5ADB901AC7A74), UINT64_C(0x9EFE4CF390C617BF), + UINT64_C(0x9C4505870A3687A9), UINT64_C(0xA34EE4CD9B5CEA62), + UINT64_C(0xE252C71228E25C3F), UINT64_C(0xDD592658B98831F4), + UINT64_C(0x606A80AD4F9F3085), UINT64_C(0x5F6161E7DEF55D4E), + UINT64_C(0x1E7D42386D4BEB13), UINT64_C(0x2176A372FC2186D8), + UINT64_C(0xF6C2A0F82E6BF774), UINT64_C(0xC9C941B2BF019ABF), + UINT64_C(0x88D5626D0CBF2CE2), UINT64_C(0xB7DE83279DD54129), + UINT64_C(0x0AED25D26BC24058), UINT64_C(0x35E6C498FAA82D93), + UINT64_C(0x74FAE74749169BCE), UINT64_C(0x4BF1060DD87CF605), + UINT64_C(0xE318EB5CF9EF77C4), UINT64_C(0xDC130A1668851A0F), + UINT64_C(0x9D0F29C9DB3BAC52), UINT64_C(0xA204C8834A51C199), + UINT64_C(0x1F376E76BC46C0E8), UINT64_C(0x203C8F3C2D2CAD23), + UINT64_C(0x6120ACE39E921B7E), UINT64_C(0x5E2B4DA90FF876B5), + UINT64_C(0x899F4E23DDB20719), UINT64_C(0xB694AF694CD86AD2), + UINT64_C(0xF7888CB6FF66DC8F), UINT64_C(0xC8836DFC6E0CB144), + UINT64_C(0x75B0CB09981BB035), UINT64_C(0x4ABB2A430971DDFE), + UINT64_C(0x0BA7099CBACF6BA3), UINT64_C(0x34ACE8D62BA50668), + UINT64_C(0x3617A1A2B155967E), UINT64_C(0x091C40E8203FFBB5), + UINT64_C(0x4800633793814DE8), UINT64_C(0x770B827D02EB2023), + UINT64_C(0xCA382488F4FC2152), UINT64_C(0xF533C5C265964C99), + UINT64_C(0xB42FE61DD628FAC4), UINT64_C(0x8B2407574742970F), + UINT64_C(0x5C9004DD9508E6A3), UINT64_C(0x639BE59704628B68), + UINT64_C(0x2287C648B7DC3D35), UINT64_C(0x1D8C270226B650FE), + UINT64_C(0xA0BF81F7D0A1518F), UINT64_C(0x9FB460BD41CB3C44), + UINT64_C(0xDEA84362F2758A19), UINT64_C(0xE1A3A228631FE7D2), + UINT64_C(0xDBDED18BC794AA35), UINT64_C(0xE4D530C156FEC7FE), + UINT64_C(0xA5C9131EE54071A3), UINT64_C(0x9AC2F254742A1C68), + UINT64_C(0x27F154A1823D1D19), UINT64_C(0x18FAB5EB135770D2), + UINT64_C(0x59E69634A0E9C68F), UINT64_C(0x66ED777E3183AB44), + UINT64_C(0xB15974F4E3C9DAE8), UINT64_C(0x8E5295BE72A3B723), + UINT64_C(0xCF4EB661C11D017E), UINT64_C(0xF045572B50776CB5), + UINT64_C(0x4D76F1DEA6606DC4), UINT64_C(0x727D1094370A000F), + UINT64_C(0x3361334B84B4B652), UINT64_C(0x0C6AD20115DEDB99), + UINT64_C(0x0ED19B758F2E4B8F), UINT64_C(0x31DA7A3F1E442644), + UINT64_C(0x70C659E0ADFA9019), UINT64_C(0x4FCDB8AA3C90FDD2), + UINT64_C(0xF2FE1E5FCA87FCA3), UINT64_C(0xCDF5FF155BED9168), + UINT64_C(0x8CE9DCCAE8532735), UINT64_C(0xB3E23D8079394AFE), + UINT64_C(0x64563E0AAB733B52), UINT64_C(0x5B5DDF403A195699), + UINT64_C(0x1A41FC9F89A7E0C4), UINT64_C(0x254A1DD518CD8D0F), + UINT64_C(0x9879BB20EEDA8C7E), UINT64_C(0xA7725A6A7FB0E1B5), + UINT64_C(0xE66E79B5CC0E57E8), UINT64_C(0xD96598FF5D643A23), + UINT64_C(0x92949EF28518CC26), UINT64_C(0xAD9F7FB81472A1ED), + UINT64_C(0xEC835C67A7CC17B0), UINT64_C(0xD388BD2D36A67A7B), + UINT64_C(0x6EBB1BD8C0B17B0A), UINT64_C(0x51B0FA9251DB16C1), + UINT64_C(0x10ACD94DE265A09C), UINT64_C(0x2FA73807730FCD57), + UINT64_C(0xF8133B8DA145BCFB), UINT64_C(0xC718DAC7302FD130), + UINT64_C(0x8604F9188391676D), UINT64_C(0xB90F185212FB0AA6), + UINT64_C(0x043CBEA7E4EC0BD7), UINT64_C(0x3B375FED7586661C), + UINT64_C(0x7A2B7C32C638D041), UINT64_C(0x45209D785752BD8A), + UINT64_C(0x479BD40CCDA22D9C), UINT64_C(0x789035465CC84057), + UINT64_C(0x398C1699EF76F60A), UINT64_C(0x0687F7D37E1C9BC1), + UINT64_C(0xBBB45126880B9AB0), UINT64_C(0x84BFB06C1961F77B), + UINT64_C(0xC5A393B3AADF4126), UINT64_C(0xFAA872F93BB52CED), + UINT64_C(0x2D1C7173E9FF5D41), UINT64_C(0x121790397895308A), + UINT64_C(0x530BB3E6CB2B86D7), UINT64_C(0x6C0052AC5A41EB1C), + UINT64_C(0xD133F459AC56EA6D), UINT64_C(0xEE3815133D3C87A6), + UINT64_C(0xAF2436CC8E8231FB), UINT64_C(0x902FD7861FE85C30), + UINT64_C(0xAA52A425BB6311D7), UINT64_C(0x9559456F2A097C1C), + UINT64_C(0xD44566B099B7CA41), UINT64_C(0xEB4E87FA08DDA78A), + UINT64_C(0x567D210FFECAA6FB), UINT64_C(0x6976C0456FA0CB30), + UINT64_C(0x286AE39ADC1E7D6D), UINT64_C(0x176102D04D7410A6), + UINT64_C(0xC0D5015A9F3E610A), UINT64_C(0xFFDEE0100E540CC1), + UINT64_C(0xBEC2C3CFBDEABA9C), UINT64_C(0x81C922852C80D757), + UINT64_C(0x3CFA8470DA97D626), UINT64_C(0x03F1653A4BFDBBED), + UINT64_C(0x42ED46E5F8430DB0), UINT64_C(0x7DE6A7AF6929607B), + UINT64_C(0x7F5DEEDBF3D9F06D), UINT64_C(0x40560F9162B39DA6), + UINT64_C(0x014A2C4ED10D2BFB), UINT64_C(0x3E41CD0440674630), + UINT64_C(0x83726BF1B6704741), UINT64_C(0xBC798ABB271A2A8A), + UINT64_C(0xFD65A96494A49CD7), UINT64_C(0xC26E482E05CEF11C), + UINT64_C(0x15DA4BA4D78480B0), UINT64_C(0x2AD1AAEE46EEED7B), + UINT64_C(0x6BCD8931F5505B26), UINT64_C(0x54C6687B643A36ED), + UINT64_C(0xE9F5CE8E922D379C), UINT64_C(0xD6FE2FC403475A57), + UINT64_C(0x97E20C1BB0F9EC0A), UINT64_C(0xA8E9ED51219381C1) + }, { + UINT64_C(0x0000000000000000), UINT64_C(0x1DEE8A5E222CA1DC), + UINT64_C(0x3BDD14BC445943B8), UINT64_C(0x26339EE26675E264), + UINT64_C(0x77BA297888B28770), UINT64_C(0x6A54A326AA9E26AC), + UINT64_C(0x4C673DC4CCEBC4C8), UINT64_C(0x5189B79AEEC76514), + UINT64_C(0xEF7452F111650EE0), UINT64_C(0xF29AD8AF3349AF3C), + UINT64_C(0xD4A9464D553C4D58), UINT64_C(0xC947CC137710EC84), + UINT64_C(0x98CE7B8999D78990), UINT64_C(0x8520F1D7BBFB284C), + UINT64_C(0xA3136F35DD8ECA28), UINT64_C(0xBEFDE56BFFA26BF4), + UINT64_C(0x4C300AC98DC40345), UINT64_C(0x51DE8097AFE8A299), + UINT64_C(0x77ED1E75C99D40FD), UINT64_C(0x6A03942BEBB1E121), + UINT64_C(0x3B8A23B105768435), UINT64_C(0x2664A9EF275A25E9), + UINT64_C(0x0057370D412FC78D), UINT64_C(0x1DB9BD5363036651), + UINT64_C(0xA34458389CA10DA5), UINT64_C(0xBEAAD266BE8DAC79), + UINT64_C(0x98994C84D8F84E1D), UINT64_C(0x8577C6DAFAD4EFC1), + UINT64_C(0xD4FE714014138AD5), UINT64_C(0xC910FB1E363F2B09), + UINT64_C(0xEF2365FC504AC96D), UINT64_C(0xF2CDEFA2726668B1), + UINT64_C(0x986015931B88068A), UINT64_C(0x858E9FCD39A4A756), + UINT64_C(0xA3BD012F5FD14532), UINT64_C(0xBE538B717DFDE4EE), + UINT64_C(0xEFDA3CEB933A81FA), UINT64_C(0xF234B6B5B1162026), + UINT64_C(0xD4072857D763C242), UINT64_C(0xC9E9A209F54F639E), + UINT64_C(0x771447620AED086A), UINT64_C(0x6AFACD3C28C1A9B6), + UINT64_C(0x4CC953DE4EB44BD2), UINT64_C(0x5127D9806C98EA0E), + UINT64_C(0x00AE6E1A825F8F1A), UINT64_C(0x1D40E444A0732EC6), + UINT64_C(0x3B737AA6C606CCA2), UINT64_C(0x269DF0F8E42A6D7E), + UINT64_C(0xD4501F5A964C05CF), UINT64_C(0xC9BE9504B460A413), + UINT64_C(0xEF8D0BE6D2154677), UINT64_C(0xF26381B8F039E7AB), + UINT64_C(0xA3EA36221EFE82BF), UINT64_C(0xBE04BC7C3CD22363), + UINT64_C(0x9837229E5AA7C107), UINT64_C(0x85D9A8C0788B60DB), + UINT64_C(0x3B244DAB87290B2F), UINT64_C(0x26CAC7F5A505AAF3), + UINT64_C(0x00F95917C3704897), UINT64_C(0x1D17D349E15CE94B), + UINT64_C(0x4C9E64D30F9B8C5F), UINT64_C(0x5170EE8D2DB72D83), + UINT64_C(0x7743706F4BC2CFE7), UINT64_C(0x6AADFA3169EE6E3B), + UINT64_C(0xA218840D981E1391), UINT64_C(0xBFF60E53BA32B24D), + UINT64_C(0x99C590B1DC475029), UINT64_C(0x842B1AEFFE6BF1F5), + UINT64_C(0xD5A2AD7510AC94E1), UINT64_C(0xC84C272B3280353D), + UINT64_C(0xEE7FB9C954F5D759), UINT64_C(0xF391339776D97685), + UINT64_C(0x4D6CD6FC897B1D71), UINT64_C(0x50825CA2AB57BCAD), + UINT64_C(0x76B1C240CD225EC9), UINT64_C(0x6B5F481EEF0EFF15), + UINT64_C(0x3AD6FF8401C99A01), UINT64_C(0x273875DA23E53BDD), + UINT64_C(0x010BEB384590D9B9), UINT64_C(0x1CE5616667BC7865), + UINT64_C(0xEE288EC415DA10D4), UINT64_C(0xF3C6049A37F6B108), + UINT64_C(0xD5F59A785183536C), UINT64_C(0xC81B102673AFF2B0), + UINT64_C(0x9992A7BC9D6897A4), UINT64_C(0x847C2DE2BF443678), + UINT64_C(0xA24FB300D931D41C), UINT64_C(0xBFA1395EFB1D75C0), + UINT64_C(0x015CDC3504BF1E34), UINT64_C(0x1CB2566B2693BFE8), + UINT64_C(0x3A81C88940E65D8C), UINT64_C(0x276F42D762CAFC50), + UINT64_C(0x76E6F54D8C0D9944), UINT64_C(0x6B087F13AE213898), + UINT64_C(0x4D3BE1F1C854DAFC), UINT64_C(0x50D56BAFEA787B20), + UINT64_C(0x3A78919E8396151B), UINT64_C(0x27961BC0A1BAB4C7), + UINT64_C(0x01A58522C7CF56A3), UINT64_C(0x1C4B0F7CE5E3F77F), + UINT64_C(0x4DC2B8E60B24926B), UINT64_C(0x502C32B8290833B7), + UINT64_C(0x761FAC5A4F7DD1D3), UINT64_C(0x6BF126046D51700F), + UINT64_C(0xD50CC36F92F31BFB), UINT64_C(0xC8E24931B0DFBA27), + UINT64_C(0xEED1D7D3D6AA5843), UINT64_C(0xF33F5D8DF486F99F), + UINT64_C(0xA2B6EA171A419C8B), UINT64_C(0xBF586049386D3D57), + UINT64_C(0x996BFEAB5E18DF33), UINT64_C(0x848574F57C347EEF), + UINT64_C(0x76489B570E52165E), UINT64_C(0x6BA611092C7EB782), + UINT64_C(0x4D958FEB4A0B55E6), UINT64_C(0x507B05B56827F43A), + UINT64_C(0x01F2B22F86E0912E), UINT64_C(0x1C1C3871A4CC30F2), + UINT64_C(0x3A2FA693C2B9D296), UINT64_C(0x27C12CCDE095734A), + UINT64_C(0x993CC9A61F3718BE), UINT64_C(0x84D243F83D1BB962), + UINT64_C(0xA2E1DD1A5B6E5B06), UINT64_C(0xBF0F57447942FADA), + UINT64_C(0xEE86E0DE97859FCE), UINT64_C(0xF3686A80B5A93E12), + UINT64_C(0xD55BF462D3DCDC76), UINT64_C(0xC8B57E3CF1F07DAA), + UINT64_C(0xD6E9A7309F3239A7), UINT64_C(0xCB072D6EBD1E987B), + UINT64_C(0xED34B38CDB6B7A1F), UINT64_C(0xF0DA39D2F947DBC3), + UINT64_C(0xA1538E481780BED7), UINT64_C(0xBCBD041635AC1F0B), + UINT64_C(0x9A8E9AF453D9FD6F), UINT64_C(0x876010AA71F55CB3), + UINT64_C(0x399DF5C18E573747), UINT64_C(0x24737F9FAC7B969B), + UINT64_C(0x0240E17DCA0E74FF), UINT64_C(0x1FAE6B23E822D523), + UINT64_C(0x4E27DCB906E5B037), UINT64_C(0x53C956E724C911EB), + UINT64_C(0x75FAC80542BCF38F), UINT64_C(0x6814425B60905253), + UINT64_C(0x9AD9ADF912F63AE2), UINT64_C(0x873727A730DA9B3E), + UINT64_C(0xA104B94556AF795A), UINT64_C(0xBCEA331B7483D886), + UINT64_C(0xED6384819A44BD92), UINT64_C(0xF08D0EDFB8681C4E), + UINT64_C(0xD6BE903DDE1DFE2A), UINT64_C(0xCB501A63FC315FF6), + UINT64_C(0x75ADFF0803933402), UINT64_C(0x6843755621BF95DE), + UINT64_C(0x4E70EBB447CA77BA), UINT64_C(0x539E61EA65E6D666), + UINT64_C(0x0217D6708B21B372), UINT64_C(0x1FF95C2EA90D12AE), + UINT64_C(0x39CAC2CCCF78F0CA), UINT64_C(0x24244892ED545116), + UINT64_C(0x4E89B2A384BA3F2D), UINT64_C(0x536738FDA6969EF1), + UINT64_C(0x7554A61FC0E37C95), UINT64_C(0x68BA2C41E2CFDD49), + UINT64_C(0x39339BDB0C08B85D), UINT64_C(0x24DD11852E241981), + UINT64_C(0x02EE8F674851FBE5), UINT64_C(0x1F0005396A7D5A39), + UINT64_C(0xA1FDE05295DF31CD), UINT64_C(0xBC136A0CB7F39011), + UINT64_C(0x9A20F4EED1867275), UINT64_C(0x87CE7EB0F3AAD3A9), + UINT64_C(0xD647C92A1D6DB6BD), UINT64_C(0xCBA943743F411761), + UINT64_C(0xED9ADD965934F505), UINT64_C(0xF07457C87B1854D9), + UINT64_C(0x02B9B86A097E3C68), UINT64_C(0x1F5732342B529DB4), + UINT64_C(0x3964ACD64D277FD0), UINT64_C(0x248A26886F0BDE0C), + UINT64_C(0x7503911281CCBB18), UINT64_C(0x68ED1B4CA3E01AC4), + UINT64_C(0x4EDE85AEC595F8A0), UINT64_C(0x53300FF0E7B9597C), + UINT64_C(0xEDCDEA9B181B3288), UINT64_C(0xF02360C53A379354), + UINT64_C(0xD610FE275C427130), UINT64_C(0xCBFE74797E6ED0EC), + UINT64_C(0x9A77C3E390A9B5F8), UINT64_C(0x879949BDB2851424), + UINT64_C(0xA1AAD75FD4F0F640), UINT64_C(0xBC445D01F6DC579C), + UINT64_C(0x74F1233D072C2A36), UINT64_C(0x691FA96325008BEA), + UINT64_C(0x4F2C37814375698E), UINT64_C(0x52C2BDDF6159C852), + UINT64_C(0x034B0A458F9EAD46), UINT64_C(0x1EA5801BADB20C9A), + UINT64_C(0x38961EF9CBC7EEFE), UINT64_C(0x257894A7E9EB4F22), + UINT64_C(0x9B8571CC164924D6), UINT64_C(0x866BFB923465850A), + UINT64_C(0xA05865705210676E), UINT64_C(0xBDB6EF2E703CC6B2), + UINT64_C(0xEC3F58B49EFBA3A6), UINT64_C(0xF1D1D2EABCD7027A), + UINT64_C(0xD7E24C08DAA2E01E), UINT64_C(0xCA0CC656F88E41C2), + UINT64_C(0x38C129F48AE82973), UINT64_C(0x252FA3AAA8C488AF), + UINT64_C(0x031C3D48CEB16ACB), UINT64_C(0x1EF2B716EC9DCB17), + UINT64_C(0x4F7B008C025AAE03), UINT64_C(0x52958AD220760FDF), + UINT64_C(0x74A614304603EDBB), UINT64_C(0x69489E6E642F4C67), + UINT64_C(0xD7B57B059B8D2793), UINT64_C(0xCA5BF15BB9A1864F), + UINT64_C(0xEC686FB9DFD4642B), UINT64_C(0xF186E5E7FDF8C5F7), + UINT64_C(0xA00F527D133FA0E3), UINT64_C(0xBDE1D8233113013F), + UINT64_C(0x9BD246C15766E35B), UINT64_C(0x863CCC9F754A4287), + UINT64_C(0xEC9136AE1CA42CBC), UINT64_C(0xF17FBCF03E888D60), + UINT64_C(0xD74C221258FD6F04), UINT64_C(0xCAA2A84C7AD1CED8), + UINT64_C(0x9B2B1FD69416ABCC), UINT64_C(0x86C59588B63A0A10), + UINT64_C(0xA0F60B6AD04FE874), UINT64_C(0xBD188134F26349A8), + UINT64_C(0x03E5645F0DC1225C), UINT64_C(0x1E0BEE012FED8380), + UINT64_C(0x383870E3499861E4), UINT64_C(0x25D6FABD6BB4C038), + UINT64_C(0x745F4D278573A52C), UINT64_C(0x69B1C779A75F04F0), + UINT64_C(0x4F82599BC12AE694), UINT64_C(0x526CD3C5E3064748), + UINT64_C(0xA0A13C6791602FF9), UINT64_C(0xBD4FB639B34C8E25), + UINT64_C(0x9B7C28DBD5396C41), UINT64_C(0x8692A285F715CD9D), + UINT64_C(0xD71B151F19D2A889), UINT64_C(0xCAF59F413BFE0955), + UINT64_C(0xECC601A35D8BEB31), UINT64_C(0xF1288BFD7FA74AED), + UINT64_C(0x4FD56E9680052119), UINT64_C(0x523BE4C8A22980C5), + UINT64_C(0x74087A2AC45C62A1), UINT64_C(0x69E6F074E670C37D), + UINT64_C(0x386F47EE08B7A669), UINT64_C(0x2581CDB02A9B07B5), + UINT64_C(0x03B253524CEEE5D1), UINT64_C(0x1E5CD90C6EC2440D) + } +}; diff --git a/dependencies/cmliblzma/liblzma/check/crc64_tablegen.c b/dependencies/cmliblzma/liblzma/check/crc64_tablegen.c new file mode 100644 index 0000000..fddaa7e --- /dev/null +++ b/dependencies/cmliblzma/liblzma/check/crc64_tablegen.c @@ -0,0 +1,88 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file crc64_tablegen.c +/// \brief Generate crc64_table_le.h and crc64_table_be.h +/// +/// Compiling: gcc -std=c99 -o crc64_tablegen crc64_tablegen.c +/// Add -DWORDS_BIGENDIAN to generate big endian table. +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include "../../common/tuklib_integer.h" + + +static uint64_t crc64_table[4][256]; + + +extern void +init_crc64_table(void) +{ + static const uint64_t poly64 = UINT64_C(0xC96C5795D7870F42); + + for (size_t s = 0; s < 4; ++s) { + for (size_t b = 0; b < 256; ++b) { + uint64_t r = s == 0 ? b : crc64_table[s - 1][b]; + + for (size_t i = 0; i < 8; ++i) { + if (r & 1) + r = (r >> 1) ^ poly64; + else + r >>= 1; + } + + crc64_table[s][b] = r; + } + } + +#ifdef WORDS_BIGENDIAN + for (size_t s = 0; s < 4; ++s) + for (size_t b = 0; b < 256; ++b) + crc64_table[s][b] = bswap64(crc64_table[s][b]); +#endif + + return; +} + + +static void +print_crc64_table(void) +{ + printf("/* This file has been automatically generated by " + "crc64_tablegen.c. */\n\n" + "const uint64_t lzma_crc64_table[4][256] = {\n\t{"); + + for (size_t s = 0; s < 4; ++s) { + for (size_t b = 0; b < 256; ++b) { + if ((b % 2) == 0) + printf("\n\t\t"); + + printf("UINT64_C(0x%016" PRIX64 ")", + crc64_table[s][b]); + + if (b != 255) + printf(",%s", (b+1) % 2 == 0 ? "" : " "); + } + + if (s == 3) + printf("\n\t}\n};\n"); + else + printf("\n\t}, {"); + } + + return; +} + + +int +main(void) +{ + init_crc64_table(); + print_crc64_table(); + return 0; +} diff --git a/dependencies/cmliblzma/liblzma/check/crc64_x86.S b/dependencies/cmliblzma/liblzma/check/crc64_x86.S new file mode 100644 index 0000000..f5bb84b --- /dev/null +++ b/dependencies/cmliblzma/liblzma/check/crc64_x86.S @@ -0,0 +1,287 @@ +/* + * Speed-optimized CRC64 using slicing-by-four algorithm + * + * This uses only i386 instructions, but it is optimized for i686 and later + * (including e.g. Pentium II/III/IV, Athlon XP, and Core 2). + * + * Authors: Igor Pavlov (original CRC32 assembly code) + * Lasse Collin (CRC64 adaptation of the modified CRC32 code) + * + * This file has been put into the public domain. + * You can do whatever you want with this file. + * + * This code needs lzma_crc64_table, which can be created using the + * following C code: + +uint64_t lzma_crc64_table[4][256]; + +void +init_table(void) +{ + // ECMA-182 + static const uint64_t poly64 = UINT64_C(0xC96C5795D7870F42); + + for (size_t s = 0; s < 4; ++s) { + for (size_t b = 0; b < 256; ++b) { + uint64_t r = s == 0 ? b : lzma_crc64_table[s - 1][b]; + + for (size_t i = 0; i < 8; ++i) { + if (r & 1) + r = (r >> 1) ^ poly64; + else + r >>= 1; + } + + lzma_crc64_table[s][b] = r; + } + } +} + + * The prototype of the CRC64 function: + * extern uint64_t lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc); + */ + +/* + * On some systems, the functions need to be prefixed. The prefix is + * usually an underscore. + */ +#ifndef __USER_LABEL_PREFIX__ +# define __USER_LABEL_PREFIX__ +#endif +#define MAKE_SYM_CAT(prefix, sym) prefix ## sym +#define MAKE_SYM(prefix, sym) MAKE_SYM_CAT(prefix, sym) +#define LZMA_CRC64 MAKE_SYM(__USER_LABEL_PREFIX__, lzma_crc64) +#define LZMA_CRC64_TABLE MAKE_SYM(__USER_LABEL_PREFIX__, lzma_crc64_table) + +/* + * Solaris assembler doesn't have .p2align, and Darwin uses .align + * differently than GNU/Linux and Solaris. + */ +#if defined(__APPLE__) || defined(__MSDOS__) +# define ALIGN(pow2, abs) .align pow2 +#else +# define ALIGN(pow2, abs) .align abs +#endif + + .text + .globl LZMA_CRC64 + +#if !defined(__APPLE__) && !defined(_WIN32) && !defined(__CYGWIN__) \ + && !defined(__MSDOS__) + .type LZMA_CRC64, @function +#endif + + ALIGN(4, 16) +LZMA_CRC64: + /* + * Register usage: + * %eax crc LSB + * %edx crc MSB + * %esi buf + * %edi size or buf + size + * %ebx lzma_crc64_table + * %ebp Table index + * %ecx Temporary + */ + pushl %ebx + pushl %esi + pushl %edi + pushl %ebp + movl 0x14(%esp), %esi /* buf */ + movl 0x18(%esp), %edi /* size */ + movl 0x1C(%esp), %eax /* crc LSB */ + movl 0x20(%esp), %edx /* crc MSB */ + + /* + * Store the address of lzma_crc64_table to %ebx. This is needed to + * get position-independent code (PIC). + * + * The PIC macro is defined by libtool, while __PIC__ is defined + * by GCC but only on some systems. Testing for both makes it simpler + * to test this code without libtool, and keeps the code working also + * when built with libtool but using something else than GCC. + * + * I understood that libtool may define PIC on Windows even though + * the code in Windows DLLs is not PIC in sense that it is in ELF + * binaries, so we need a separate check to always use the non-PIC + * code on Windows. + */ +#if (!defined(PIC) && !defined(__PIC__)) \ + || (defined(_WIN32) || defined(__CYGWIN__)) + /* Not PIC */ + movl $ LZMA_CRC64_TABLE, %ebx +#elif defined(__APPLE__) + /* Mach-O */ + call .L_get_pc +.L_pic: + leal .L_lzma_crc64_table$non_lazy_ptr-.L_pic(%ebx), %ebx + movl (%ebx), %ebx +#else + /* ELF */ + call .L_get_pc + addl $_GLOBAL_OFFSET_TABLE_, %ebx + movl LZMA_CRC64_TABLE@GOT(%ebx), %ebx +#endif + + /* Complement the initial value. */ + notl %eax + notl %edx + +.L_align: + /* + * Check if there is enough input to use slicing-by-four. + * We need eight bytes, because the loop pre-reads four bytes. + */ + cmpl $8, %edi + jb .L_rest + + /* Check if we have reached alignment of four bytes. */ + testl $3, %esi + jz .L_slice + + /* Calculate CRC of the next input byte. */ + movzbl (%esi), %ebp + incl %esi + movzbl %al, %ecx + xorl %ecx, %ebp + shrdl $8, %edx, %eax + xorl (%ebx, %ebp, 8), %eax + shrl $8, %edx + xorl 4(%ebx, %ebp, 8), %edx + decl %edi + jmp .L_align + +.L_slice: + /* + * If we get here, there's at least eight bytes of aligned input + * available. Make %edi multiple of four bytes. Store the possible + * remainder over the "size" variable in the argument stack. + */ + movl %edi, 0x18(%esp) + andl $-4, %edi + subl %edi, 0x18(%esp) + + /* + * Let %edi be buf + size - 4 while running the main loop. This way + * we can compare for equality to determine when exit the loop. + */ + addl %esi, %edi + subl $4, %edi + + /* Read in the first four aligned bytes. */ + movl (%esi), %ecx + +.L_loop: + xorl %eax, %ecx + movzbl %cl, %ebp + movl 0x1800(%ebx, %ebp, 8), %eax + xorl %edx, %eax + movl 0x1804(%ebx, %ebp, 8), %edx + movzbl %ch, %ebp + xorl 0x1000(%ebx, %ebp, 8), %eax + xorl 0x1004(%ebx, %ebp, 8), %edx + shrl $16, %ecx + movzbl %cl, %ebp + xorl 0x0800(%ebx, %ebp, 8), %eax + xorl 0x0804(%ebx, %ebp, 8), %edx + movzbl %ch, %ebp + addl $4, %esi + xorl (%ebx, %ebp, 8), %eax + xorl 4(%ebx, %ebp, 8), %edx + + /* Check for end of aligned input. */ + cmpl %edi, %esi + + /* + * Copy the next input byte to %ecx. It is slightly faster to + * read it here than at the top of the loop. + */ + movl (%esi), %ecx + jb .L_loop + + /* + * Process the remaining four bytes, which we have already + * copied to %ecx. + */ + xorl %eax, %ecx + movzbl %cl, %ebp + movl 0x1800(%ebx, %ebp, 8), %eax + xorl %edx, %eax + movl 0x1804(%ebx, %ebp, 8), %edx + movzbl %ch, %ebp + xorl 0x1000(%ebx, %ebp, 8), %eax + xorl 0x1004(%ebx, %ebp, 8), %edx + shrl $16, %ecx + movzbl %cl, %ebp + xorl 0x0800(%ebx, %ebp, 8), %eax + xorl 0x0804(%ebx, %ebp, 8), %edx + movzbl %ch, %ebp + addl $4, %esi + xorl (%ebx, %ebp, 8), %eax + xorl 4(%ebx, %ebp, 8), %edx + + /* Copy the number of remaining bytes to %edi. */ + movl 0x18(%esp), %edi + +.L_rest: + /* Check for end of input. */ + testl %edi, %edi + jz .L_return + + /* Calculate CRC of the next input byte. */ + movzbl (%esi), %ebp + incl %esi + movzbl %al, %ecx + xorl %ecx, %ebp + shrdl $8, %edx, %eax + xorl (%ebx, %ebp, 8), %eax + shrl $8, %edx + xorl 4(%ebx, %ebp, 8), %edx + decl %edi + jmp .L_rest + +.L_return: + /* Complement the final value. */ + notl %eax + notl %edx + + popl %ebp + popl %edi + popl %esi + popl %ebx + ret + +#if defined(PIC) || defined(__PIC__) + ALIGN(4, 16) +.L_get_pc: + movl (%esp), %ebx + ret +#endif + +#if defined(__APPLE__) && (defined(PIC) || defined(__PIC__)) + /* Mach-O PIC */ + .section __IMPORT,__pointers,non_lazy_symbol_pointers +.L_lzma_crc64_table$non_lazy_ptr: + .indirect_symbol LZMA_CRC64_TABLE + .long 0 + +#elif defined(_WIN32) || defined(__CYGWIN__) +# ifdef DLL_EXPORT + /* This is equivalent of __declspec(dllexport). */ + .section .drectve + .ascii " -export:lzma_crc64" +# endif + +#elif !defined(__MSDOS__) + /* ELF */ + .size LZMA_CRC64, .-LZMA_CRC64 +#endif + +/* + * This is needed to support non-executable stack. It's ugly to + * use __linux__ here, but I don't know a way to detect when + * we are using GNU assembler. + */ +#if defined(__ELF__) && defined(__linux__) + .section .note.GNU-stack,"",@progbits +#endif diff --git a/dependencies/cmliblzma/liblzma/check/crc_macros.h b/dependencies/cmliblzma/liblzma/check/crc_macros.h new file mode 100644 index 0000000..a7c21b7 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/check/crc_macros.h @@ -0,0 +1,30 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file crc_macros.h +/// \brief Some endian-dependent macros for CRC32 and CRC64 +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifdef WORDS_BIGENDIAN +# define A(x) ((x) >> 24) +# define B(x) (((x) >> 16) & 0xFF) +# define C(x) (((x) >> 8) & 0xFF) +# define D(x) ((x) & 0xFF) + +# define S8(x) ((x) << 8) +# define S32(x) ((x) << 32) + +#else +# define A(x) ((x) & 0xFF) +# define B(x) (((x) >> 8) & 0xFF) +# define C(x) (((x) >> 16) & 0xFF) +# define D(x) ((x) >> 24) + +# define S8(x) ((x) >> 8) +# define S32(x) ((x) >> 32) +#endif diff --git a/dependencies/cmliblzma/liblzma/check/sha256.c b/dependencies/cmliblzma/liblzma/check/sha256.c new file mode 100644 index 0000000..5eede5c --- /dev/null +++ b/dependencies/cmliblzma/liblzma/check/sha256.c @@ -0,0 +1,196 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file sha256.c +/// \brief SHA-256 +/// +/// \todo Crypto++ has x86 ASM optimizations. They use SSE so if they +/// are imported to liblzma, SSE instructions need to be used +/// conditionally to keep the code working on older boxes. +// +// This code is based on the code found from 7-Zip, which has a modified +// version of the SHA-256 found from Crypto++ . +// The code was modified a little to fit into liblzma. +// +// Authors: Kevin Springle +// Wei Dai +// Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "check.h" + +// Rotate a uint32_t. GCC can optimize this to a rotate instruction +// at least on x86. +static inline uint32_t +rotr_32(uint32_t num, unsigned amount) +{ + return (num >> amount) | (num << (32 - amount)); +} + +#define blk0(i) (W[i] = conv32be(data[i])) +#define blk2(i) (W[i & 15] += s1(W[(i - 2) & 15]) + W[(i - 7) & 15] \ + + s0(W[(i - 15) & 15])) + +#define Ch(x, y, z) (z ^ (x & (y ^ z))) +#define Maj(x, y, z) ((x & (y ^ z)) + (y & z)) + +#define a(i) T[(0 - i) & 7] +#define b(i) T[(1 - i) & 7] +#define c(i) T[(2 - i) & 7] +#define d(i) T[(3 - i) & 7] +#define e(i) T[(4 - i) & 7] +#define f(i) T[(5 - i) & 7] +#define g(i) T[(6 - i) & 7] +#define h(i) T[(7 - i) & 7] + +#define R(i, j, blk) \ + h(i) += S1(e(i)) + Ch(e(i), f(i), g(i)) + SHA256_K[i + j] + blk; \ + d(i) += h(i); \ + h(i) += S0(a(i)) + Maj(a(i), b(i), c(i)) +#define R0(i) R(i, 0, blk0(i)) +#define R2(i) R(i, j, blk2(i)) + +#define S0(x) rotr_32(x ^ rotr_32(x ^ rotr_32(x, 9), 11), 2) +#define S1(x) rotr_32(x ^ rotr_32(x ^ rotr_32(x, 14), 5), 6) +#define s0(x) (rotr_32(x ^ rotr_32(x, 11), 7) ^ (x >> 3)) +#define s1(x) (rotr_32(x ^ rotr_32(x, 2), 17) ^ (x >> 10)) + + +static const uint32_t SHA256_K[64] = { + 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, + 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, + 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, + 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, + 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, + 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, + 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, + 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, + 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, + 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, + 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, + 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, + 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, + 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, + 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, + 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2, +}; + + +static void +transform(uint32_t state[8], const uint32_t data[16]) +{ + uint32_t W[16]; + uint32_t T[8]; + + // Copy state[] to working vars. + memcpy(T, state, sizeof(T)); + + // The first 16 operations unrolled + R0( 0); R0( 1); R0( 2); R0( 3); + R0( 4); R0( 5); R0( 6); R0( 7); + R0( 8); R0( 9); R0(10); R0(11); + R0(12); R0(13); R0(14); R0(15); + + // The remaining 48 operations partially unrolled + for (unsigned int j = 16; j < 64; j += 16) { + R2( 0); R2( 1); R2( 2); R2( 3); + R2( 4); R2( 5); R2( 6); R2( 7); + R2( 8); R2( 9); R2(10); R2(11); + R2(12); R2(13); R2(14); R2(15); + } + + // Add the working vars back into state[]. + state[0] += a(0); + state[1] += b(0); + state[2] += c(0); + state[3] += d(0); + state[4] += e(0); + state[5] += f(0); + state[6] += g(0); + state[7] += h(0); +} + + +static void +process(lzma_check_state *check) +{ + transform(check->state.sha256.state, check->buffer.u32); + return; +} + + +extern void +lzma_sha256_init(lzma_check_state *check) +{ + static const uint32_t s[8] = { + 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, + 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19, + }; + + memcpy(check->state.sha256.state, s, sizeof(s)); + check->state.sha256.size = 0; + + return; +} + + +extern void +lzma_sha256_update(const uint8_t *buf, size_t size, lzma_check_state *check) +{ + // Copy the input data into a properly aligned temporary buffer. + // This way we can be called with arbitrarily sized buffers + // (no need to be multiple of 64 bytes), and the code works also + // on architectures that don't allow unaligned memory access. + while (size > 0) { + const size_t copy_start = check->state.sha256.size & 0x3F; + size_t copy_size = 64 - copy_start; + if (copy_size > size) + copy_size = size; + + memcpy(check->buffer.u8 + copy_start, buf, copy_size); + + buf += copy_size; + size -= copy_size; + check->state.sha256.size += copy_size; + + if ((check->state.sha256.size & 0x3F) == 0) + process(check); + } + + return; +} + + +extern void +lzma_sha256_finish(lzma_check_state *check) +{ + // Add padding as described in RFC 3174 (it describes SHA-1 but + // the same padding style is used for SHA-256 too). + size_t pos = check->state.sha256.size & 0x3F; + check->buffer.u8[pos++] = 0x80; + + while (pos != 64 - 8) { + if (pos == 64) { + process(check); + pos = 0; + } + + check->buffer.u8[pos++] = 0x00; + } + + // Convert the message size from bytes to bits. + check->state.sha256.size *= 8; + + check->buffer.u64[(64 - 8) / 8] = conv64be(check->state.sha256.size); + + process(check); + + for (size_t i = 0; i < 8; ++i) + check->buffer.u32[i] = conv32be(check->state.sha256.state[i]); + + return; +} diff --git a/dependencies/cmliblzma/liblzma/common/alone_decoder.c b/dependencies/cmliblzma/liblzma/common/alone_decoder.c new file mode 100644 index 0000000..77d0a9b --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/alone_decoder.c @@ -0,0 +1,243 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file alone_decoder.c +/// \brief Decoder for LZMA_Alone files +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "alone_decoder.h" +#include "lzma_decoder.h" +#include "lz_decoder.h" + + +typedef struct { + lzma_next_coder next; + + enum { + SEQ_PROPERTIES, + SEQ_DICTIONARY_SIZE, + SEQ_UNCOMPRESSED_SIZE, + SEQ_CODER_INIT, + SEQ_CODE, + } sequence; + + /// If true, reject files that are unlikely to be .lzma files. + /// If false, more non-.lzma files get accepted and will give + /// LZMA_DATA_ERROR either immediately or after a few output bytes. + bool picky; + + /// Position in the header fields + size_t pos; + + /// Uncompressed size decoded from the header + lzma_vli uncompressed_size; + + /// Memory usage limit + uint64_t memlimit; + + /// Amount of memory actually needed (only an estimate) + uint64_t memusage; + + /// Options decoded from the header needed to initialize + /// the LZMA decoder + lzma_options_lzma options; +} lzma_alone_coder; + + +static lzma_ret +alone_decode(void *coder_ptr, + const lzma_allocator *allocator lzma_attribute((__unused__)), + const uint8_t *restrict in, size_t *restrict in_pos, + size_t in_size, uint8_t *restrict out, + size_t *restrict out_pos, size_t out_size, + lzma_action action) +{ + lzma_alone_coder *coder = coder_ptr; + + while (*out_pos < out_size + && (coder->sequence == SEQ_CODE || *in_pos < in_size)) + switch (coder->sequence) { + case SEQ_PROPERTIES: + if (lzma_lzma_lclppb_decode(&coder->options, in[*in_pos])) + return LZMA_FORMAT_ERROR; + + coder->sequence = SEQ_DICTIONARY_SIZE; + ++*in_pos; + break; + + case SEQ_DICTIONARY_SIZE: + coder->options.dict_size + |= (size_t)(in[*in_pos]) << (coder->pos * 8); + + if (++coder->pos == 4) { + if (coder->picky && coder->options.dict_size + != UINT32_MAX) { + // A hack to ditch tons of false positives: + // We allow only dictionary sizes that are + // 2^n or 2^n + 2^(n-1). LZMA_Alone created + // only files with 2^n, but accepts any + // dictionary size. + uint32_t d = coder->options.dict_size - 1; + d |= d >> 2; + d |= d >> 3; + d |= d >> 4; + d |= d >> 8; + d |= d >> 16; + ++d; + + if (d != coder->options.dict_size) + return LZMA_FORMAT_ERROR; + } + + coder->pos = 0; + coder->sequence = SEQ_UNCOMPRESSED_SIZE; + } + + ++*in_pos; + break; + + case SEQ_UNCOMPRESSED_SIZE: + coder->uncompressed_size + |= (lzma_vli)(in[*in_pos]) << (coder->pos * 8); + ++*in_pos; + if (++coder->pos < 8) + break; + + // Another hack to ditch false positives: Assume that + // if the uncompressed size is known, it must be less + // than 256 GiB. + if (coder->picky + && coder->uncompressed_size != LZMA_VLI_UNKNOWN + && coder->uncompressed_size + >= (LZMA_VLI_C(1) << 38)) + return LZMA_FORMAT_ERROR; + + // Calculate the memory usage so that it is ready + // for SEQ_CODER_INIT. + coder->memusage = lzma_lzma_decoder_memusage(&coder->options) + + LZMA_MEMUSAGE_BASE; + + coder->pos = 0; + coder->sequence = SEQ_CODER_INIT; + + // Fall through + + case SEQ_CODER_INIT: { + if (coder->memusage > coder->memlimit) + return LZMA_MEMLIMIT_ERROR; + + lzma_filter_info filters[2] = { + { + .init = &lzma_lzma_decoder_init, + .options = &coder->options, + }, { + .init = NULL, + } + }; + + const lzma_ret ret = lzma_next_filter_init(&coder->next, + allocator, filters); + if (ret != LZMA_OK) + return ret; + + // Use a hack to set the uncompressed size. + lzma_lz_decoder_uncompressed(coder->next.coder, + coder->uncompressed_size); + + coder->sequence = SEQ_CODE; + break; + } + + case SEQ_CODE: { + return coder->next.code(coder->next.coder, + allocator, in, in_pos, in_size, + out, out_pos, out_size, action); + } + + default: + return LZMA_PROG_ERROR; + } + + return LZMA_OK; +} + + +static void +alone_decoder_end(void *coder_ptr, const lzma_allocator *allocator) +{ + lzma_alone_coder *coder = coder_ptr; + lzma_next_end(&coder->next, allocator); + lzma_free(coder, allocator); + return; +} + + +static lzma_ret +alone_decoder_memconfig(void *coder_ptr, uint64_t *memusage, + uint64_t *old_memlimit, uint64_t new_memlimit) +{ + lzma_alone_coder *coder = coder_ptr; + + *memusage = coder->memusage; + *old_memlimit = coder->memlimit; + + if (new_memlimit != 0) { + if (new_memlimit < coder->memusage) + return LZMA_MEMLIMIT_ERROR; + + coder->memlimit = new_memlimit; + } + + return LZMA_OK; +} + + +extern lzma_ret +lzma_alone_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator, + uint64_t memlimit, bool picky) +{ + lzma_next_coder_init(&lzma_alone_decoder_init, next, allocator); + + lzma_alone_coder *coder = next->coder; + + if (coder == NULL) { + coder = lzma_alloc(sizeof(lzma_alone_coder), allocator); + if (coder == NULL) + return LZMA_MEM_ERROR; + + next->coder = coder; + next->code = &alone_decode; + next->end = &alone_decoder_end; + next->memconfig = &alone_decoder_memconfig; + coder->next = LZMA_NEXT_CODER_INIT; + } + + coder->sequence = SEQ_PROPERTIES; + coder->picky = picky; + coder->pos = 0; + coder->options.dict_size = 0; + coder->options.preset_dict = NULL; + coder->options.preset_dict_size = 0; + coder->uncompressed_size = 0; + coder->memlimit = my_max(1, memlimit); + coder->memusage = LZMA_MEMUSAGE_BASE; + + return LZMA_OK; +} + + +extern LZMA_API(lzma_ret) +lzma_alone_decoder(lzma_stream *strm, uint64_t memlimit) +{ + lzma_next_strm_init(lzma_alone_decoder_init, strm, memlimit, false); + + strm->internal->supported_actions[LZMA_RUN] = true; + strm->internal->supported_actions[LZMA_FINISH] = true; + + return LZMA_OK; +} diff --git a/dependencies/cmliblzma/liblzma/common/alone_decoder.h b/dependencies/cmliblzma/liblzma/common/alone_decoder.h new file mode 100644 index 0000000..dfa031a --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/alone_decoder.h @@ -0,0 +1,23 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file alone_decoder.h +/// \brief Decoder for LZMA_Alone files +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_ALONE_DECODER_H +#define LZMA_ALONE_DECODER_H + +#include "common.h" + + +extern lzma_ret lzma_alone_decoder_init( + lzma_next_coder *next, const lzma_allocator *allocator, + uint64_t memlimit, bool picky); + +#endif diff --git a/dependencies/cmliblzma/liblzma/common/alone_encoder.c b/dependencies/cmliblzma/liblzma/common/alone_encoder.c new file mode 100644 index 0000000..4853cfd --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/alone_encoder.c @@ -0,0 +1,163 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file alone_decoder.c +/// \brief Decoder for LZMA_Alone files +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "common.h" +#include "lzma_encoder.h" + + +#define ALONE_HEADER_SIZE (1 + 4 + 8) + + +typedef struct { + lzma_next_coder next; + + enum { + SEQ_HEADER, + SEQ_CODE, + } sequence; + + size_t header_pos; + uint8_t header[ALONE_HEADER_SIZE]; +} lzma_alone_coder; + + +static lzma_ret +alone_encode(void *coder_ptr, + const lzma_allocator *allocator lzma_attribute((__unused__)), + const uint8_t *restrict in, size_t *restrict in_pos, + size_t in_size, uint8_t *restrict out, + size_t *restrict out_pos, size_t out_size, + lzma_action action) +{ + lzma_alone_coder *coder = coder_ptr; + + while (*out_pos < out_size) + switch (coder->sequence) { + case SEQ_HEADER: + lzma_bufcpy(coder->header, &coder->header_pos, + ALONE_HEADER_SIZE, + out, out_pos, out_size); + if (coder->header_pos < ALONE_HEADER_SIZE) + return LZMA_OK; + + coder->sequence = SEQ_CODE; + break; + + case SEQ_CODE: + return coder->next.code(coder->next.coder, + allocator, in, in_pos, in_size, + out, out_pos, out_size, action); + + default: + assert(0); + return LZMA_PROG_ERROR; + } + + return LZMA_OK; +} + + +static void +alone_encoder_end(void *coder_ptr, const lzma_allocator *allocator) +{ + lzma_alone_coder *coder = coder_ptr; + lzma_next_end(&coder->next, allocator); + lzma_free(coder, allocator); + return; +} + + +// At least for now, this is not used by any internal function. +static lzma_ret +alone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_options_lzma *options) +{ + lzma_next_coder_init(&alone_encoder_init, next, allocator); + + lzma_alone_coder *coder = next->coder; + + if (coder == NULL) { + coder = lzma_alloc(sizeof(lzma_alone_coder), allocator); + if (coder == NULL) + return LZMA_MEM_ERROR; + + next->coder = coder; + next->code = &alone_encode; + next->end = &alone_encoder_end; + coder->next = LZMA_NEXT_CODER_INIT; + } + + // Basic initializations + coder->sequence = SEQ_HEADER; + coder->header_pos = 0; + + // Encode the header: + // - Properties (1 byte) + if (lzma_lzma_lclppb_encode(options, coder->header)) + return LZMA_OPTIONS_ERROR; + + // - Dictionary size (4 bytes) + if (options->dict_size < LZMA_DICT_SIZE_MIN) + return LZMA_OPTIONS_ERROR; + + // Round up to the next 2^n or 2^n + 2^(n - 1) depending on which + // one is the next unless it is UINT32_MAX. While the header would + // allow any 32-bit integer, we do this to keep the decoder of liblzma + // accepting the resulting files. + uint32_t d = options->dict_size - 1; + d |= d >> 2; + d |= d >> 3; + d |= d >> 4; + d |= d >> 8; + d |= d >> 16; + if (d != UINT32_MAX) + ++d; + + unaligned_write32le(coder->header + 1, d); + + // - Uncompressed size (always unknown and using EOPM) + memset(coder->header + 1 + 4, 0xFF, 8); + + // Initialize the LZMA encoder. + const lzma_filter_info filters[2] = { + { + .init = &lzma_lzma_encoder_init, + .options = (void *)(options), + }, { + .init = NULL, + } + }; + + return lzma_next_filter_init(&coder->next, allocator, filters); +} + + +/* +extern lzma_ret +lzma_alone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_options_alone *options) +{ + lzma_next_coder_init(&alone_encoder_init, next, allocator, options); +} +*/ + + +extern LZMA_API(lzma_ret) +lzma_alone_encoder(lzma_stream *strm, const lzma_options_lzma *options) +{ + lzma_next_strm_init(alone_encoder_init, strm, options); + + strm->internal->supported_actions[LZMA_RUN] = true; + strm->internal->supported_actions[LZMA_FINISH] = true; + + return LZMA_OK; +} diff --git a/dependencies/cmliblzma/liblzma/common/auto_decoder.c b/dependencies/cmliblzma/liblzma/common/auto_decoder.c new file mode 100644 index 0000000..6895c7c --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/auto_decoder.c @@ -0,0 +1,195 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file auto_decoder.c +/// \brief Autodetect between .xz Stream and .lzma (LZMA_Alone) formats +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "stream_decoder.h" +#include "alone_decoder.h" + + +typedef struct { + /// Stream decoder or LZMA_Alone decoder + lzma_next_coder next; + + uint64_t memlimit; + uint32_t flags; + + enum { + SEQ_INIT, + SEQ_CODE, + SEQ_FINISH, + } sequence; +} lzma_auto_coder; + + +static lzma_ret +auto_decode(void *coder_ptr, const lzma_allocator *allocator, + const uint8_t *restrict in, size_t *restrict in_pos, + size_t in_size, uint8_t *restrict out, + size_t *restrict out_pos, size_t out_size, lzma_action action) +{ + lzma_auto_coder *coder = coder_ptr; + + switch (coder->sequence) { + case SEQ_INIT: + if (*in_pos >= in_size) + return LZMA_OK; + + // Update the sequence now, because we want to continue from + // SEQ_CODE even if we return some LZMA_*_CHECK. + coder->sequence = SEQ_CODE; + + // Detect the file format. For now this is simple, since if + // it doesn't start with 0xFD (the first magic byte of the + // new format), it has to be LZMA_Alone, or something that + // we don't support at all. + if (in[*in_pos] == 0xFD) { + return_if_error(lzma_stream_decoder_init( + &coder->next, allocator, + coder->memlimit, coder->flags)); + } else { + return_if_error(lzma_alone_decoder_init(&coder->next, + allocator, coder->memlimit, true)); + + // If the application wants to know about missing + // integrity check or about the check in general, we + // need to handle it here, because LZMA_Alone decoder + // doesn't accept any flags. + if (coder->flags & LZMA_TELL_NO_CHECK) + return LZMA_NO_CHECK; + + if (coder->flags & LZMA_TELL_ANY_CHECK) + return LZMA_GET_CHECK; + } + + // Fall through + + case SEQ_CODE: { + const lzma_ret ret = coder->next.code( + coder->next.coder, allocator, + in, in_pos, in_size, + out, out_pos, out_size, action); + if (ret != LZMA_STREAM_END + || (coder->flags & LZMA_CONCATENATED) == 0) + return ret; + + coder->sequence = SEQ_FINISH; + } + + // Fall through + + case SEQ_FINISH: + // When LZMA_DECODE_CONCATENATED was used and we were decoding + // LZMA_Alone file, we need to check check that there is no + // trailing garbage and wait for LZMA_FINISH. + if (*in_pos < in_size) + return LZMA_DATA_ERROR; + + return action == LZMA_FINISH ? LZMA_STREAM_END : LZMA_OK; + + default: + assert(0); + return LZMA_PROG_ERROR; + } +} + + +static void +auto_decoder_end(void *coder_ptr, const lzma_allocator *allocator) +{ + lzma_auto_coder *coder = coder_ptr; + lzma_next_end(&coder->next, allocator); + lzma_free(coder, allocator); + return; +} + + +static lzma_check +auto_decoder_get_check(const void *coder_ptr) +{ + const lzma_auto_coder *coder = coder_ptr; + + // It is LZMA_Alone if get_check is NULL. + return coder->next.get_check == NULL ? LZMA_CHECK_NONE + : coder->next.get_check(coder->next.coder); +} + + +static lzma_ret +auto_decoder_memconfig(void *coder_ptr, uint64_t *memusage, + uint64_t *old_memlimit, uint64_t new_memlimit) +{ + lzma_auto_coder *coder = coder_ptr; + + lzma_ret ret; + + if (coder->next.memconfig != NULL) { + ret = coder->next.memconfig(coder->next.coder, + memusage, old_memlimit, new_memlimit); + assert(*old_memlimit == coder->memlimit); + } else { + // No coder is configured yet. Use the base value as + // the current memory usage. + *memusage = LZMA_MEMUSAGE_BASE; + *old_memlimit = coder->memlimit; + + ret = LZMA_OK; + if (new_memlimit != 0 && new_memlimit < *memusage) + ret = LZMA_MEMLIMIT_ERROR; + } + + if (ret == LZMA_OK && new_memlimit != 0) + coder->memlimit = new_memlimit; + + return ret; +} + + +static lzma_ret +auto_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator, + uint64_t memlimit, uint32_t flags) +{ + lzma_next_coder_init(&auto_decoder_init, next, allocator); + + if (flags & ~LZMA_SUPPORTED_FLAGS) + return LZMA_OPTIONS_ERROR; + + lzma_auto_coder *coder = next->coder; + if (coder == NULL) { + coder = lzma_alloc(sizeof(lzma_auto_coder), allocator); + if (coder == NULL) + return LZMA_MEM_ERROR; + + next->coder = coder; + next->code = &auto_decode; + next->end = &auto_decoder_end; + next->get_check = &auto_decoder_get_check; + next->memconfig = &auto_decoder_memconfig; + coder->next = LZMA_NEXT_CODER_INIT; + } + + coder->memlimit = my_max(1, memlimit); + coder->flags = flags; + coder->sequence = SEQ_INIT; + + return LZMA_OK; +} + + +extern LZMA_API(lzma_ret) +lzma_auto_decoder(lzma_stream *strm, uint64_t memlimit, uint32_t flags) +{ + lzma_next_strm_init(auto_decoder_init, strm, memlimit, flags); + + strm->internal->supported_actions[LZMA_RUN] = true; + strm->internal->supported_actions[LZMA_FINISH] = true; + + return LZMA_OK; +} diff --git a/dependencies/cmliblzma/liblzma/common/block_buffer_decoder.c b/dependencies/cmliblzma/liblzma/common/block_buffer_decoder.c new file mode 100644 index 0000000..b0ded90 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/block_buffer_decoder.c @@ -0,0 +1,80 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file block_buffer_decoder.c +/// \brief Single-call .xz Block decoder +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "block_decoder.h" + + +extern LZMA_API(lzma_ret) +lzma_block_buffer_decode(lzma_block *block, const lzma_allocator *allocator, + const uint8_t *in, size_t *in_pos, size_t in_size, + uint8_t *out, size_t *out_pos, size_t out_size) +{ + if (in_pos == NULL || (in == NULL && *in_pos != in_size) + || *in_pos > in_size || out_pos == NULL + || (out == NULL && *out_pos != out_size) + || *out_pos > out_size) + return LZMA_PROG_ERROR; + + // Initialize the Block decoder. + lzma_next_coder block_decoder = LZMA_NEXT_CODER_INIT; + lzma_ret ret = lzma_block_decoder_init( + &block_decoder, allocator, block); + + if (ret == LZMA_OK) { + // Save the positions so that we can restore them in case + // an error occurs. + const size_t in_start = *in_pos; + const size_t out_start = *out_pos; + + // Do the actual decoding. + ret = block_decoder.code(block_decoder.coder, allocator, + in, in_pos, in_size, out, out_pos, out_size, + LZMA_FINISH); + + if (ret == LZMA_STREAM_END) { + ret = LZMA_OK; + } else { + if (ret == LZMA_OK) { + // Either the input was truncated or the + // output buffer was too small. + assert(*in_pos == in_size + || *out_pos == out_size); + + // If all the input was consumed, then the + // input is truncated, even if the output + // buffer is also full. This is because + // processing the last byte of the Block + // never produces output. + // + // NOTE: This assumption may break when new + // filters are added, if the end marker of + // the filter doesn't consume at least one + // complete byte. + if (*in_pos == in_size) + ret = LZMA_DATA_ERROR; + else + ret = LZMA_BUF_ERROR; + } + + // Restore the positions. + *in_pos = in_start; + *out_pos = out_start; + } + } + + // Free the decoder memory. This needs to be done even if + // initialization fails, because the internal API doesn't + // require the initialization function to free its memory on error. + lzma_next_end(&block_decoder, allocator); + + return ret; +} diff --git a/dependencies/cmliblzma/liblzma/common/block_buffer_encoder.c b/dependencies/cmliblzma/liblzma/common/block_buffer_encoder.c new file mode 100644 index 0000000..39e263a --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/block_buffer_encoder.c @@ -0,0 +1,337 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file block_buffer_encoder.c +/// \brief Single-call .xz Block encoder +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "block_buffer_encoder.h" +#include "block_encoder.h" +#include "filter_encoder.h" +#include "lzma2_encoder.h" +#include "check.h" + + +/// Estimate the maximum size of the Block Header and Check fields for +/// a Block that uses LZMA2 uncompressed chunks. We could use +/// lzma_block_header_size() but this is simpler. +/// +/// Block Header Size + Block Flags + Compressed Size +/// + Uncompressed Size + Filter Flags for LZMA2 + CRC32 + Check +/// and round up to the next multiple of four to take Header Padding +/// into account. +#define HEADERS_BOUND ((1 + 1 + 2 * LZMA_VLI_BYTES_MAX + 3 + 4 \ + + LZMA_CHECK_SIZE_MAX + 3) & ~3) + + +static uint64_t +lzma2_bound(uint64_t uncompressed_size) +{ + // Prevent integer overflow in overhead calculation. + if (uncompressed_size > COMPRESSED_SIZE_MAX) + return 0; + + // Calculate the exact overhead of the LZMA2 headers: Round + // uncompressed_size up to the next multiple of LZMA2_CHUNK_MAX, + // multiply by the size of per-chunk header, and add one byte for + // the end marker. + const uint64_t overhead = ((uncompressed_size + LZMA2_CHUNK_MAX - 1) + / LZMA2_CHUNK_MAX) + * LZMA2_HEADER_UNCOMPRESSED + 1; + + // Catch the possible integer overflow. + if (COMPRESSED_SIZE_MAX - overhead < uncompressed_size) + return 0; + + return uncompressed_size + overhead; +} + + +extern uint64_t +lzma_block_buffer_bound64(uint64_t uncompressed_size) +{ + // If the data doesn't compress, we always use uncompressed + // LZMA2 chunks. + uint64_t lzma2_size = lzma2_bound(uncompressed_size); + if (lzma2_size == 0) + return 0; + + // Take Block Padding into account. + lzma2_size = (lzma2_size + 3) & ~UINT64_C(3); + + // No risk of integer overflow because lzma2_bound() already takes + // into account the size of the headers in the Block. + return HEADERS_BOUND + lzma2_size; +} + + +extern LZMA_API(size_t) +lzma_block_buffer_bound(size_t uncompressed_size) +{ + uint64_t ret = lzma_block_buffer_bound64(uncompressed_size); + +#if SIZE_MAX < UINT64_MAX + // Catch the possible integer overflow on 32-bit systems. + if (ret > SIZE_MAX) + return 0; +#endif + + return ret; +} + + +static lzma_ret +block_encode_uncompressed(lzma_block *block, const uint8_t *in, size_t in_size, + uint8_t *out, size_t *out_pos, size_t out_size) +{ + // Use LZMA2 uncompressed chunks. We wouldn't need a dictionary at + // all, but LZMA2 always requires a dictionary, so use the minimum + // value to minimize memory usage of the decoder. + lzma_options_lzma lzma2 = { + .dict_size = LZMA_DICT_SIZE_MIN, + }; + + lzma_filter filters[2]; + filters[0].id = LZMA_FILTER_LZMA2; + filters[0].options = &lzma2; + filters[1].id = LZMA_VLI_UNKNOWN; + + // Set the above filter options to *block temporarily so that we can + // encode the Block Header. + lzma_filter *filters_orig = block->filters; + block->filters = filters; + + if (lzma_block_header_size(block) != LZMA_OK) { + block->filters = filters_orig; + return LZMA_PROG_ERROR; + } + + // Check that there's enough output space. The caller has already + // set block->compressed_size to what lzma2_bound() has returned, + // so we can reuse that value. We know that compressed_size is a + // known valid VLI and header_size is a small value so their sum + // will never overflow. + assert(block->compressed_size == lzma2_bound(in_size)); + if (out_size - *out_pos + < block->header_size + block->compressed_size) { + block->filters = filters_orig; + return LZMA_BUF_ERROR; + } + + if (lzma_block_header_encode(block, out + *out_pos) != LZMA_OK) { + block->filters = filters_orig; + return LZMA_PROG_ERROR; + } + + block->filters = filters_orig; + *out_pos += block->header_size; + + // Encode the data using LZMA2 uncompressed chunks. + size_t in_pos = 0; + uint8_t control = 0x01; // Dictionary reset + + while (in_pos < in_size) { + // Control byte: Indicate uncompressed chunk, of which + // the first resets the dictionary. + out[(*out_pos)++] = control; + control = 0x02; // No dictionary reset + + // Size of the uncompressed chunk + const size_t copy_size + = my_min(in_size - in_pos, LZMA2_CHUNK_MAX); + out[(*out_pos)++] = (copy_size - 1) >> 8; + out[(*out_pos)++] = (copy_size - 1) & 0xFF; + + // The actual data + assert(*out_pos + copy_size <= out_size); + memcpy(out + *out_pos, in + in_pos, copy_size); + + in_pos += copy_size; + *out_pos += copy_size; + } + + // End marker + out[(*out_pos)++] = 0x00; + assert(*out_pos <= out_size); + + return LZMA_OK; +} + + +static lzma_ret +block_encode_normal(lzma_block *block, const lzma_allocator *allocator, + const uint8_t *in, size_t in_size, + uint8_t *out, size_t *out_pos, size_t out_size) +{ + // Find out the size of the Block Header. + return_if_error(lzma_block_header_size(block)); + + // Reserve space for the Block Header and skip it for now. + if (out_size - *out_pos <= block->header_size) + return LZMA_BUF_ERROR; + + const size_t out_start = *out_pos; + *out_pos += block->header_size; + + // Limit out_size so that we stop encoding if the output would grow + // bigger than what uncompressed Block would be. + if (out_size - *out_pos > block->compressed_size) + out_size = *out_pos + block->compressed_size; + + // TODO: In many common cases this could be optimized to use + // significantly less memory. + lzma_next_coder raw_encoder = LZMA_NEXT_CODER_INIT; + lzma_ret ret = lzma_raw_encoder_init( + &raw_encoder, allocator, block->filters); + + if (ret == LZMA_OK) { + size_t in_pos = 0; + ret = raw_encoder.code(raw_encoder.coder, allocator, + in, &in_pos, in_size, out, out_pos, out_size, + LZMA_FINISH); + } + + // NOTE: This needs to be run even if lzma_raw_encoder_init() failed. + lzma_next_end(&raw_encoder, allocator); + + if (ret == LZMA_STREAM_END) { + // Compression was successful. Write the Block Header. + block->compressed_size + = *out_pos - (out_start + block->header_size); + ret = lzma_block_header_encode(block, out + out_start); + if (ret != LZMA_OK) + ret = LZMA_PROG_ERROR; + + } else if (ret == LZMA_OK) { + // Output buffer became full. + ret = LZMA_BUF_ERROR; + } + + // Reset *out_pos if something went wrong. + if (ret != LZMA_OK) + *out_pos = out_start; + + return ret; +} + + +static lzma_ret +block_buffer_encode(lzma_block *block, const lzma_allocator *allocator, + const uint8_t *in, size_t in_size, + uint8_t *out, size_t *out_pos, size_t out_size, + bool try_to_compress) +{ + // Validate the arguments. + if (block == NULL || (in == NULL && in_size != 0) || out == NULL + || out_pos == NULL || *out_pos > out_size) + return LZMA_PROG_ERROR; + + // The contents of the structure may depend on the version so + // check the version before validating the contents of *block. + if (block->version > 1) + return LZMA_OPTIONS_ERROR; + + if ((unsigned int)(block->check) > LZMA_CHECK_ID_MAX + || (try_to_compress && block->filters == NULL)) + return LZMA_PROG_ERROR; + + if (!lzma_check_is_supported(block->check)) + return LZMA_UNSUPPORTED_CHECK; + + // Size of a Block has to be a multiple of four, so limit the size + // here already. This way we don't need to check it again when adding + // Block Padding. + out_size -= (out_size - *out_pos) & 3; + + // Get the size of the Check field. + const size_t check_size = lzma_check_size(block->check); + assert(check_size != UINT32_MAX); + + // Reserve space for the Check field. + if (out_size - *out_pos <= check_size) + return LZMA_BUF_ERROR; + + out_size -= check_size; + + // Initialize block->uncompressed_size and calculate the worst-case + // value for block->compressed_size. + block->uncompressed_size = in_size; + block->compressed_size = lzma2_bound(in_size); + if (block->compressed_size == 0) + return LZMA_DATA_ERROR; + + // Do the actual compression. + lzma_ret ret = LZMA_BUF_ERROR; + if (try_to_compress) + ret = block_encode_normal(block, allocator, + in, in_size, out, out_pos, out_size); + + if (ret != LZMA_OK) { + // If the error was something else than output buffer + // becoming full, return the error now. + if (ret != LZMA_BUF_ERROR) + return ret; + + // The data was uncompressible (at least with the options + // given to us) or the output buffer was too small. Use the + // uncompressed chunks of LZMA2 to wrap the data into a valid + // Block. If we haven't been given enough output space, even + // this may fail. + return_if_error(block_encode_uncompressed(block, in, in_size, + out, out_pos, out_size)); + } + + assert(*out_pos <= out_size); + + // Block Padding. No buffer overflow here, because we already adjusted + // out_size so that (out_size - out_start) is a multiple of four. + // Thus, if the buffer is full, the loop body can never run. + for (size_t i = (size_t)(block->compressed_size); i & 3; ++i) { + assert(*out_pos < out_size); + out[(*out_pos)++] = 0x00; + } + + // If there's no Check field, we are done now. + if (check_size > 0) { + // Calculate the integrity check. We reserved space for + // the Check field earlier so we don't need to check for + // available output space here. + lzma_check_state check; + lzma_check_init(&check, block->check); + lzma_check_update(&check, block->check, in, in_size); + lzma_check_finish(&check, block->check); + + memcpy(block->raw_check, check.buffer.u8, check_size); + memcpy(out + *out_pos, check.buffer.u8, check_size); + *out_pos += check_size; + } + + return LZMA_OK; +} + + +extern LZMA_API(lzma_ret) +lzma_block_buffer_encode(lzma_block *block, const lzma_allocator *allocator, + const uint8_t *in, size_t in_size, + uint8_t *out, size_t *out_pos, size_t out_size) +{ + return block_buffer_encode(block, allocator, + in, in_size, out, out_pos, out_size, true); +} + + +extern LZMA_API(lzma_ret) +lzma_block_uncomp_encode(lzma_block *block, + const uint8_t *in, size_t in_size, + uint8_t *out, size_t *out_pos, size_t out_size) +{ + // It won't allocate any memory from heap so no need + // for lzma_allocator. + return block_buffer_encode(block, NULL, + in, in_size, out, out_pos, out_size, false); +} diff --git a/dependencies/cmliblzma/liblzma/common/block_buffer_encoder.h b/dependencies/cmliblzma/liblzma/common/block_buffer_encoder.h new file mode 100644 index 0000000..653207f --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/block_buffer_encoder.h @@ -0,0 +1,24 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file block_buffer_encoder.h +/// \brief Single-call .xz Block encoder +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_BLOCK_BUFFER_ENCODER_H +#define LZMA_BLOCK_BUFFER_ENCODER_H + +#include "common.h" + + +/// uint64_t version of lzma_block_buffer_bound(). It is used by +/// stream_encoder_mt.c. Probably the original lzma_block_buffer_bound() +/// should have been 64-bit, but fixing it would break the ABI. +extern uint64_t lzma_block_buffer_bound64(uint64_t uncompressed_size); + +#endif diff --git a/dependencies/cmliblzma/liblzma/common/block_decoder.c b/dependencies/cmliblzma/liblzma/common/block_decoder.c new file mode 100644 index 0000000..075bd27 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/block_decoder.c @@ -0,0 +1,257 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file block_decoder.c +/// \brief Decodes .xz Blocks +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "block_decoder.h" +#include "filter_decoder.h" +#include "check.h" + + +typedef struct { + enum { + SEQ_CODE, + SEQ_PADDING, + SEQ_CHECK, + } sequence; + + /// The filters in the chain; initialized with lzma_raw_decoder_init(). + lzma_next_coder next; + + /// Decoding options; we also write Compressed Size and Uncompressed + /// Size back to this structure when the decoding has been finished. + lzma_block *block; + + /// Compressed Size calculated while decoding + lzma_vli compressed_size; + + /// Uncompressed Size calculated while decoding + lzma_vli uncompressed_size; + + /// Maximum allowed Compressed Size; this takes into account the + /// size of the Block Header and Check fields when Compressed Size + /// is unknown. + lzma_vli compressed_limit; + + /// Position when reading the Check field + size_t check_pos; + + /// Check of the uncompressed data + lzma_check_state check; + + /// True if the integrity check won't be calculated and verified. + bool ignore_check; +} lzma_block_coder; + + +static inline bool +update_size(lzma_vli *size, lzma_vli add, lzma_vli limit) +{ + if (limit > LZMA_VLI_MAX) + limit = LZMA_VLI_MAX; + + if (limit < *size || limit - *size < add) + return true; + + *size += add; + + return false; +} + + +static inline bool +is_size_valid(lzma_vli size, lzma_vli reference) +{ + return reference == LZMA_VLI_UNKNOWN || reference == size; +} + + +static lzma_ret +block_decode(void *coder_ptr, const lzma_allocator *allocator, + const uint8_t *restrict in, size_t *restrict in_pos, + size_t in_size, uint8_t *restrict out, + size_t *restrict out_pos, size_t out_size, lzma_action action) +{ + lzma_block_coder *coder = coder_ptr; + + switch (coder->sequence) { + case SEQ_CODE: { + const size_t in_start = *in_pos; + const size_t out_start = *out_pos; + + const lzma_ret ret = coder->next.code(coder->next.coder, + allocator, in, in_pos, in_size, + out, out_pos, out_size, action); + + const size_t in_used = *in_pos - in_start; + const size_t out_used = *out_pos - out_start; + + // NOTE: We compare to compressed_limit here, which prevents + // the total size of the Block growing past LZMA_VLI_MAX. + if (update_size(&coder->compressed_size, in_used, + coder->compressed_limit) + || update_size(&coder->uncompressed_size, + out_used, + coder->block->uncompressed_size)) + return LZMA_DATA_ERROR; + + if (!coder->ignore_check) + lzma_check_update(&coder->check, coder->block->check, + out + out_start, out_used); + + if (ret != LZMA_STREAM_END) + return ret; + + // Compressed and Uncompressed Sizes are now at their final + // values. Verify that they match the values given to us. + if (!is_size_valid(coder->compressed_size, + coder->block->compressed_size) + || !is_size_valid(coder->uncompressed_size, + coder->block->uncompressed_size)) + return LZMA_DATA_ERROR; + + // Copy the values into coder->block. The caller + // may use this information to construct Index. + coder->block->compressed_size = coder->compressed_size; + coder->block->uncompressed_size = coder->uncompressed_size; + + coder->sequence = SEQ_PADDING; + } + + // Fall through + + case SEQ_PADDING: + // Compressed Data is padded to a multiple of four bytes. + while (coder->compressed_size & 3) { + if (*in_pos >= in_size) + return LZMA_OK; + + // We use compressed_size here just get the Padding + // right. The actual Compressed Size was stored to + // coder->block already, and won't be modified by + // us anymore. + ++coder->compressed_size; + + if (in[(*in_pos)++] != 0x00) + return LZMA_DATA_ERROR; + } + + if (coder->block->check == LZMA_CHECK_NONE) + return LZMA_STREAM_END; + + if (!coder->ignore_check) + lzma_check_finish(&coder->check, coder->block->check); + + coder->sequence = SEQ_CHECK; + + // Fall through + + case SEQ_CHECK: { + const size_t check_size = lzma_check_size(coder->block->check); + lzma_bufcpy(in, in_pos, in_size, coder->block->raw_check, + &coder->check_pos, check_size); + if (coder->check_pos < check_size) + return LZMA_OK; + + // Validate the Check only if we support it. + // coder->check.buffer may be uninitialized + // when the Check ID is not supported. + if (!coder->ignore_check + && lzma_check_is_supported(coder->block->check) + && memcmp(coder->block->raw_check, + coder->check.buffer.u8, + check_size) != 0) + return LZMA_DATA_ERROR; + + return LZMA_STREAM_END; + } + } + + return LZMA_PROG_ERROR; +} + + +static void +block_decoder_end(void *coder_ptr, const lzma_allocator *allocator) +{ + lzma_block_coder *coder = coder_ptr; + lzma_next_end(&coder->next, allocator); + lzma_free(coder, allocator); + return; +} + + +extern lzma_ret +lzma_block_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator, + lzma_block *block) +{ + lzma_next_coder_init(&lzma_block_decoder_init, next, allocator); + + // Validate the options. lzma_block_unpadded_size() does that for us + // except for Uncompressed Size and filters. Filters are validated + // by the raw decoder. + if (lzma_block_unpadded_size(block) == 0 + || !lzma_vli_is_valid(block->uncompressed_size)) + return LZMA_PROG_ERROR; + + // Allocate *next->coder if needed. + lzma_block_coder *coder = next->coder; + if (coder == NULL) { + coder = lzma_alloc(sizeof(lzma_block_coder), allocator); + if (coder == NULL) + return LZMA_MEM_ERROR; + + next->coder = coder; + next->code = &block_decode; + next->end = &block_decoder_end; + coder->next = LZMA_NEXT_CODER_INIT; + } + + // Basic initializations + coder->sequence = SEQ_CODE; + coder->block = block; + coder->compressed_size = 0; + coder->uncompressed_size = 0; + + // If Compressed Size is not known, we calculate the maximum allowed + // value so that encoded size of the Block (including Block Padding) + // is still a valid VLI and a multiple of four. + coder->compressed_limit + = block->compressed_size == LZMA_VLI_UNKNOWN + ? (LZMA_VLI_MAX & ~LZMA_VLI_C(3)) + - block->header_size + - lzma_check_size(block->check) + : block->compressed_size; + + // Initialize the check. It's caller's problem if the Check ID is not + // supported, and the Block decoder cannot verify the Check field. + // Caller can test lzma_check_is_supported(block->check). + coder->check_pos = 0; + lzma_check_init(&coder->check, block->check); + + coder->ignore_check = block->version >= 1 + ? block->ignore_check : false; + + // Initialize the filter chain. + return lzma_raw_decoder_init(&coder->next, allocator, + block->filters); +} + + +extern LZMA_API(lzma_ret) +lzma_block_decoder(lzma_stream *strm, lzma_block *block) +{ + lzma_next_strm_init(lzma_block_decoder_init, strm, block); + + strm->internal->supported_actions[LZMA_RUN] = true; + strm->internal->supported_actions[LZMA_FINISH] = true; + + return LZMA_OK; +} diff --git a/dependencies/cmliblzma/liblzma/common/block_decoder.h b/dependencies/cmliblzma/liblzma/common/block_decoder.h new file mode 100644 index 0000000..718c5ce --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/block_decoder.h @@ -0,0 +1,22 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file block_decoder.h +/// \brief Decodes .xz Blocks +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_BLOCK_DECODER_H +#define LZMA_BLOCK_DECODER_H + +#include "common.h" + + +extern lzma_ret lzma_block_decoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, lzma_block *block); + +#endif diff --git a/dependencies/cmliblzma/liblzma/common/block_encoder.c b/dependencies/cmliblzma/liblzma/common/block_encoder.c new file mode 100644 index 0000000..168846a --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/block_encoder.c @@ -0,0 +1,223 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file block_encoder.c +/// \brief Encodes .xz Blocks +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "block_encoder.h" +#include "filter_encoder.h" +#include "check.h" + + +typedef struct { + /// The filters in the chain; initialized with lzma_raw_decoder_init(). + lzma_next_coder next; + + /// Encoding options; we also write Unpadded Size, Compressed Size, + /// and Uncompressed Size back to this structure when the encoding + /// has been finished. + lzma_block *block; + + enum { + SEQ_CODE, + SEQ_PADDING, + SEQ_CHECK, + } sequence; + + /// Compressed Size calculated while encoding + lzma_vli compressed_size; + + /// Uncompressed Size calculated while encoding + lzma_vli uncompressed_size; + + /// Position in the Check field + size_t pos; + + /// Check of the uncompressed data + lzma_check_state check; +} lzma_block_coder; + + +static lzma_ret +block_encode(void *coder_ptr, const lzma_allocator *allocator, + const uint8_t *restrict in, size_t *restrict in_pos, + size_t in_size, uint8_t *restrict out, + size_t *restrict out_pos, size_t out_size, lzma_action action) +{ + lzma_block_coder *coder = coder_ptr; + + // Check that our amount of input stays in proper limits. + if (LZMA_VLI_MAX - coder->uncompressed_size < in_size - *in_pos) + return LZMA_DATA_ERROR; + + switch (coder->sequence) { + case SEQ_CODE: { + const size_t in_start = *in_pos; + const size_t out_start = *out_pos; + + const lzma_ret ret = coder->next.code(coder->next.coder, + allocator, in, in_pos, in_size, + out, out_pos, out_size, action); + + const size_t in_used = *in_pos - in_start; + const size_t out_used = *out_pos - out_start; + + if (COMPRESSED_SIZE_MAX - coder->compressed_size < out_used) + return LZMA_DATA_ERROR; + + coder->compressed_size += out_used; + + // No need to check for overflow because we have already + // checked it at the beginning of this function. + coder->uncompressed_size += in_used; + + lzma_check_update(&coder->check, coder->block->check, + in + in_start, in_used); + + if (ret != LZMA_STREAM_END || action == LZMA_SYNC_FLUSH) + return ret; + + assert(*in_pos == in_size); + assert(action == LZMA_FINISH); + + // Copy the values into coder->block. The caller + // may use this information to construct Index. + coder->block->compressed_size = coder->compressed_size; + coder->block->uncompressed_size = coder->uncompressed_size; + + coder->sequence = SEQ_PADDING; + } + + // Fall through + + case SEQ_PADDING: + // Pad Compressed Data to a multiple of four bytes. We can + // use coder->compressed_size for this since we don't need + // it for anything else anymore. + while (coder->compressed_size & 3) { + if (*out_pos >= out_size) + return LZMA_OK; + + out[*out_pos] = 0x00; + ++*out_pos; + ++coder->compressed_size; + } + + if (coder->block->check == LZMA_CHECK_NONE) + return LZMA_STREAM_END; + + lzma_check_finish(&coder->check, coder->block->check); + + coder->sequence = SEQ_CHECK; + + // Fall through + + case SEQ_CHECK: { + const size_t check_size = lzma_check_size(coder->block->check); + lzma_bufcpy(coder->check.buffer.u8, &coder->pos, check_size, + out, out_pos, out_size); + if (coder->pos < check_size) + return LZMA_OK; + + memcpy(coder->block->raw_check, coder->check.buffer.u8, + check_size); + return LZMA_STREAM_END; + } + } + + return LZMA_PROG_ERROR; +} + + +static void +block_encoder_end(void *coder_ptr, const lzma_allocator *allocator) +{ + lzma_block_coder *coder = coder_ptr; + lzma_next_end(&coder->next, allocator); + lzma_free(coder, allocator); + return; +} + + +static lzma_ret +block_encoder_update(void *coder_ptr, const lzma_allocator *allocator, + const lzma_filter *filters lzma_attribute((__unused__)), + const lzma_filter *reversed_filters) +{ + lzma_block_coder *coder = coder_ptr; + + if (coder->sequence != SEQ_CODE) + return LZMA_PROG_ERROR; + + return lzma_next_filter_update( + &coder->next, allocator, reversed_filters); +} + + +extern lzma_ret +lzma_block_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator, + lzma_block *block) +{ + lzma_next_coder_init(&lzma_block_encoder_init, next, allocator); + + if (block == NULL) + return LZMA_PROG_ERROR; + + // The contents of the structure may depend on the version so + // check the version first. + if (block->version > 1) + return LZMA_OPTIONS_ERROR; + + // If the Check ID is not supported, we cannot calculate the check and + // thus not create a proper Block. + if ((unsigned int)(block->check) > LZMA_CHECK_ID_MAX) + return LZMA_PROG_ERROR; + + if (!lzma_check_is_supported(block->check)) + return LZMA_UNSUPPORTED_CHECK; + + // Allocate and initialize *next->coder if needed. + lzma_block_coder *coder = next->coder; + if (coder == NULL) { + coder = lzma_alloc(sizeof(lzma_block_coder), allocator); + if (coder == NULL) + return LZMA_MEM_ERROR; + + next->coder = coder; + next->code = &block_encode; + next->end = &block_encoder_end; + next->update = &block_encoder_update; + coder->next = LZMA_NEXT_CODER_INIT; + } + + // Basic initializations + coder->sequence = SEQ_CODE; + coder->block = block; + coder->compressed_size = 0; + coder->uncompressed_size = 0; + coder->pos = 0; + + // Initialize the check + lzma_check_init(&coder->check, block->check); + + // Initialize the requested filters. + return lzma_raw_encoder_init(&coder->next, allocator, block->filters); +} + + +extern LZMA_API(lzma_ret) +lzma_block_encoder(lzma_stream *strm, lzma_block *block) +{ + lzma_next_strm_init(lzma_block_encoder_init, strm, block); + + strm->internal->supported_actions[LZMA_RUN] = true; + strm->internal->supported_actions[LZMA_FINISH] = true; + + return LZMA_OK; +} diff --git a/dependencies/cmliblzma/liblzma/common/block_encoder.h b/dependencies/cmliblzma/liblzma/common/block_encoder.h new file mode 100644 index 0000000..bd97c18 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/block_encoder.h @@ -0,0 +1,47 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file block_encoder.h +/// \brief Encodes .xz Blocks +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_BLOCK_ENCODER_H +#define LZMA_BLOCK_ENCODER_H + +#include "common.h" + + +/// \brief Biggest Compressed Size value that the Block encoder supports +/// +/// The maximum size of a single Block is limited by the maximum size of +/// a Stream, which in theory is 2^63 - 3 bytes (i.e. LZMA_VLI_MAX - 3). +/// While the size is really big and no one should hit it in practice, we +/// take it into account in some places anyway to catch some errors e.g. if +/// application passes insanely big value to some function. +/// +/// We could take into account the headers etc. to determine the exact +/// maximum size of the Compressed Data field, but the complexity would give +/// us nothing useful. Instead, limit the size of Compressed Data so that +/// even with biggest possible Block Header and Check fields the total +/// encoded size of the Block stays as a valid VLI. This doesn't guarantee +/// that the size of the Stream doesn't grow too big, but that problem is +/// taken care outside the Block handling code. +/// +/// ~LZMA_VLI_C(3) is to guarantee that if we need padding at the end of +/// the Compressed Data field, it will still stay in the proper limit. +/// +/// This constant is in this file because it is needed in both +/// block_encoder.c and block_buffer_encoder.c. +#define COMPRESSED_SIZE_MAX ((LZMA_VLI_MAX - LZMA_BLOCK_HEADER_SIZE_MAX \ + - LZMA_CHECK_SIZE_MAX) & ~LZMA_VLI_C(3)) + + +extern lzma_ret lzma_block_encoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, lzma_block *block); + +#endif diff --git a/dependencies/cmliblzma/liblzma/common/block_header_decoder.c b/dependencies/cmliblzma/liblzma/common/block_header_decoder.c new file mode 100644 index 0000000..1dd982f --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/block_header_decoder.c @@ -0,0 +1,124 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file block_header_decoder.c +/// \brief Decodes Block Header from .xz files +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "common.h" +#include "check.h" + + +static void +free_properties(lzma_block *block, const lzma_allocator *allocator) +{ + // Free allocated filter options. The last array member is not + // touched after the initialization in the beginning of + // lzma_block_header_decode(), so we don't need to touch that here. + for (size_t i = 0; i < LZMA_FILTERS_MAX; ++i) { + lzma_free(block->filters[i].options, allocator); + block->filters[i].id = LZMA_VLI_UNKNOWN; + block->filters[i].options = NULL; + } + + return; +} + + +extern LZMA_API(lzma_ret) +lzma_block_header_decode(lzma_block *block, + const lzma_allocator *allocator, const uint8_t *in) +{ + // NOTE: We consider the header to be corrupt not only when the + // CRC32 doesn't match, but also when variable-length integers + // are invalid or over 63 bits, or if the header is too small + // to contain the claimed information. + + // Initialize the filter options array. This way the caller can + // safely free() the options even if an error occurs in this function. + for (size_t i = 0; i <= LZMA_FILTERS_MAX; ++i) { + block->filters[i].id = LZMA_VLI_UNKNOWN; + block->filters[i].options = NULL; + } + + // Versions 0 and 1 are supported. If a newer version was specified, + // we need to downgrade it. + if (block->version > 1) + block->version = 1; + + // This isn't a Block Header option, but since the decompressor will + // read it if version >= 1, it's better to initialize it here than + // to expect the caller to do it since in almost all cases this + // should be false. + block->ignore_check = false; + + // Validate Block Header Size and Check type. The caller must have + // already set these, so it is a programming error if this test fails. + if (lzma_block_header_size_decode(in[0]) != block->header_size + || (unsigned int)(block->check) > LZMA_CHECK_ID_MAX) + return LZMA_PROG_ERROR; + + // Exclude the CRC32 field. + const size_t in_size = block->header_size - 4; + + // Verify CRC32 + if (lzma_crc32(in, in_size, 0) != unaligned_read32le(in + in_size)) + return LZMA_DATA_ERROR; + + // Check for unsupported flags. + if (in[1] & 0x3C) + return LZMA_OPTIONS_ERROR; + + // Start after the Block Header Size and Block Flags fields. + size_t in_pos = 2; + + // Compressed Size + if (in[1] & 0x40) { + return_if_error(lzma_vli_decode(&block->compressed_size, + NULL, in, &in_pos, in_size)); + + // Validate Compressed Size. This checks that it isn't zero + // and that the total size of the Block is a valid VLI. + if (lzma_block_unpadded_size(block) == 0) + return LZMA_DATA_ERROR; + } else { + block->compressed_size = LZMA_VLI_UNKNOWN; + } + + // Uncompressed Size + if (in[1] & 0x80) + return_if_error(lzma_vli_decode(&block->uncompressed_size, + NULL, in, &in_pos, in_size)); + else + block->uncompressed_size = LZMA_VLI_UNKNOWN; + + // Filter Flags + const size_t filter_count = (in[1] & 3) + 1; + for (size_t i = 0; i < filter_count; ++i) { + const lzma_ret ret = lzma_filter_flags_decode( + &block->filters[i], allocator, + in, &in_pos, in_size); + if (ret != LZMA_OK) { + free_properties(block, allocator); + return ret; + } + } + + // Padding + while (in_pos < in_size) { + if (in[in_pos++] != 0x00) { + free_properties(block, allocator); + + // Possibly some new field present so use + // LZMA_OPTIONS_ERROR instead of LZMA_DATA_ERROR. + return LZMA_OPTIONS_ERROR; + } + } + + return LZMA_OK; +} diff --git a/dependencies/cmliblzma/liblzma/common/block_header_encoder.c b/dependencies/cmliblzma/liblzma/common/block_header_encoder.c new file mode 100644 index 0000000..5c5f542 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/block_header_encoder.c @@ -0,0 +1,132 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file block_header_encoder.c +/// \brief Encodes Block Header for .xz files +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "common.h" +#include "check.h" + + +extern LZMA_API(lzma_ret) +lzma_block_header_size(lzma_block *block) +{ + if (block->version > 1) + return LZMA_OPTIONS_ERROR; + + // Block Header Size + Block Flags + CRC32. + uint32_t size = 1 + 1 + 4; + + // Compressed Size + if (block->compressed_size != LZMA_VLI_UNKNOWN) { + const uint32_t add = lzma_vli_size(block->compressed_size); + if (add == 0 || block->compressed_size == 0) + return LZMA_PROG_ERROR; + + size += add; + } + + // Uncompressed Size + if (block->uncompressed_size != LZMA_VLI_UNKNOWN) { + const uint32_t add = lzma_vli_size(block->uncompressed_size); + if (add == 0) + return LZMA_PROG_ERROR; + + size += add; + } + + // List of Filter Flags + if (block->filters == NULL || block->filters[0].id == LZMA_VLI_UNKNOWN) + return LZMA_PROG_ERROR; + + for (size_t i = 0; block->filters[i].id != LZMA_VLI_UNKNOWN; ++i) { + // Don't allow too many filters. + if (i == LZMA_FILTERS_MAX) + return LZMA_PROG_ERROR; + + uint32_t add; + return_if_error(lzma_filter_flags_size(&add, + block->filters + i)); + + size += add; + } + + // Pad to a multiple of four bytes. + block->header_size = (size + 3) & ~UINT32_C(3); + + // NOTE: We don't verify that the encoded size of the Block stays + // within limits. This is because it is possible that we are called + // with exaggerated Compressed Size (e.g. LZMA_VLI_MAX) to reserve + // space for Block Header, and later called again with lower, + // real values. + + return LZMA_OK; +} + + +extern LZMA_API(lzma_ret) +lzma_block_header_encode(const lzma_block *block, uint8_t *out) +{ + // Validate everything but filters. + if (lzma_block_unpadded_size(block) == 0 + || !lzma_vli_is_valid(block->uncompressed_size)) + return LZMA_PROG_ERROR; + + // Indicate the size of the buffer _excluding_ the CRC32 field. + const size_t out_size = block->header_size - 4; + + // Store the Block Header Size. + out[0] = out_size / 4; + + // We write Block Flags in pieces. + out[1] = 0x00; + size_t out_pos = 2; + + // Compressed Size + if (block->compressed_size != LZMA_VLI_UNKNOWN) { + return_if_error(lzma_vli_encode(block->compressed_size, NULL, + out, &out_pos, out_size)); + + out[1] |= 0x40; + } + + // Uncompressed Size + if (block->uncompressed_size != LZMA_VLI_UNKNOWN) { + return_if_error(lzma_vli_encode(block->uncompressed_size, NULL, + out, &out_pos, out_size)); + + out[1] |= 0x80; + } + + // Filter Flags + if (block->filters == NULL || block->filters[0].id == LZMA_VLI_UNKNOWN) + return LZMA_PROG_ERROR; + + size_t filter_count = 0; + do { + // There can be a maximum of four filters. + if (filter_count == LZMA_FILTERS_MAX) + return LZMA_PROG_ERROR; + + return_if_error(lzma_filter_flags_encode( + block->filters + filter_count, + out, &out_pos, out_size)); + + } while (block->filters[++filter_count].id != LZMA_VLI_UNKNOWN); + + out[1] |= filter_count - 1; + + // Padding + memzero(out + out_pos, out_size - out_pos); + + // CRC32 + unaligned_write32le(out + out_size, lzma_crc32(out, out_size, 0)); + + return LZMA_OK; +} diff --git a/dependencies/cmliblzma/liblzma/common/block_util.c b/dependencies/cmliblzma/liblzma/common/block_util.c new file mode 100644 index 0000000..00c7fe8 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/block_util.c @@ -0,0 +1,90 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file block_header.c +/// \brief Utility functions to handle lzma_block +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "common.h" +#include "index.h" + + +extern LZMA_API(lzma_ret) +lzma_block_compressed_size(lzma_block *block, lzma_vli unpadded_size) +{ + // Validate everything but Uncompressed Size and filters. + if (lzma_block_unpadded_size(block) == 0) + return LZMA_PROG_ERROR; + + const uint32_t container_size = block->header_size + + lzma_check_size(block->check); + + // Validate that Compressed Size will be greater than zero. + if (unpadded_size <= container_size) + return LZMA_DATA_ERROR; + + // Calculate what Compressed Size is supposed to be. + // If Compressed Size was present in Block Header, + // compare that the new value matches it. + const lzma_vli compressed_size = unpadded_size - container_size; + if (block->compressed_size != LZMA_VLI_UNKNOWN + && block->compressed_size != compressed_size) + return LZMA_DATA_ERROR; + + block->compressed_size = compressed_size; + + return LZMA_OK; +} + + +extern LZMA_API(lzma_vli) +lzma_block_unpadded_size(const lzma_block *block) +{ + // Validate the values that we are interested in i.e. all but + // Uncompressed Size and the filters. + // + // NOTE: This function is used for validation too, so it is + // essential that these checks are always done even if + // Compressed Size is unknown. + if (block == NULL || block->version > 1 + || block->header_size < LZMA_BLOCK_HEADER_SIZE_MIN + || block->header_size > LZMA_BLOCK_HEADER_SIZE_MAX + || (block->header_size & 3) + || !lzma_vli_is_valid(block->compressed_size) + || block->compressed_size == 0 + || (unsigned int)(block->check) > LZMA_CHECK_ID_MAX) + return 0; + + // If Compressed Size is unknown, return that we cannot know + // size of the Block either. + if (block->compressed_size == LZMA_VLI_UNKNOWN) + return LZMA_VLI_UNKNOWN; + + // Calculate Unpadded Size and validate it. + const lzma_vli unpadded_size = block->compressed_size + + block->header_size + + lzma_check_size(block->check); + + assert(unpadded_size >= UNPADDED_SIZE_MIN); + if (unpadded_size > UNPADDED_SIZE_MAX) + return 0; + + return unpadded_size; +} + + +extern LZMA_API(lzma_vli) +lzma_block_total_size(const lzma_block *block) +{ + lzma_vli unpadded_size = lzma_block_unpadded_size(block); + + if (unpadded_size != LZMA_VLI_UNKNOWN) + unpadded_size = vli_ceil4(unpadded_size); + + return unpadded_size; +} diff --git a/dependencies/cmliblzma/liblzma/common/common.c b/dependencies/cmliblzma/liblzma/common/common.c new file mode 100644 index 0000000..57e3f8e --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/common.c @@ -0,0 +1,445 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file common.h +/// \brief Common functions needed in many places in liblzma +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "common.h" + + +///////////// +// Version // +///////////// + +extern LZMA_API(uint32_t) +lzma_version_number(void) +{ + return LZMA_VERSION; +} + + +extern LZMA_API(const char *) +lzma_version_string(void) +{ + return LZMA_VERSION_STRING; +} + + +/////////////////////// +// Memory allocation // +/////////////////////// + +extern void * lzma_attribute((__malloc__)) lzma_attr_alloc_size(1) +lzma_alloc(size_t size, const lzma_allocator *allocator) +{ + // Some malloc() variants return NULL if called with size == 0. + if (size == 0) + size = 1; + + void *ptr; + + if (allocator != NULL && allocator->alloc != NULL) + ptr = allocator->alloc(allocator->opaque, 1, size); + else + ptr = malloc(size); + + return ptr; +} + + +extern void * lzma_attribute((__malloc__)) lzma_attr_alloc_size(1) +lzma_alloc_zero(size_t size, const lzma_allocator *allocator) +{ + // Some calloc() variants return NULL if called with size == 0. + if (size == 0) + size = 1; + + void *ptr; + + if (allocator != NULL && allocator->alloc != NULL) { + ptr = allocator->alloc(allocator->opaque, 1, size); + if (ptr != NULL) + memzero(ptr, size); + } else { + ptr = calloc(1, size); + } + + return ptr; +} + + +extern void +lzma_free(void *ptr, const lzma_allocator *allocator) +{ + if (allocator != NULL && allocator->free != NULL) + allocator->free(allocator->opaque, ptr); + else + free(ptr); + + return; +} + + +////////// +// Misc // +////////// + +extern size_t +lzma_bufcpy(const uint8_t *restrict in, size_t *restrict in_pos, + size_t in_size, uint8_t *restrict out, + size_t *restrict out_pos, size_t out_size) +{ + const size_t in_avail = in_size - *in_pos; + const size_t out_avail = out_size - *out_pos; + const size_t copy_size = my_min(in_avail, out_avail); + + memcpy(out + *out_pos, in + *in_pos, copy_size); + + *in_pos += copy_size; + *out_pos += copy_size; + + return copy_size; +} + + +extern lzma_ret +lzma_next_filter_init(lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter_info *filters) +{ + lzma_next_coder_init(filters[0].init, next, allocator); + next->id = filters[0].id; + return filters[0].init == NULL + ? LZMA_OK : filters[0].init(next, allocator, filters); +} + + +extern lzma_ret +lzma_next_filter_update(lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter *reversed_filters) +{ + // Check that the application isn't trying to change the Filter ID. + // End of filters is indicated with LZMA_VLI_UNKNOWN in both + // reversed_filters[0].id and next->id. + if (reversed_filters[0].id != next->id) + return LZMA_PROG_ERROR; + + if (reversed_filters[0].id == LZMA_VLI_UNKNOWN) + return LZMA_OK; + + assert(next->update != NULL); + return next->update(next->coder, allocator, NULL, reversed_filters); +} + + +extern void +lzma_next_end(lzma_next_coder *next, const lzma_allocator *allocator) +{ + if (next->init != (uintptr_t)(NULL)) { + // To avoid tiny end functions that simply call + // lzma_free(coder, allocator), we allow leaving next->end + // NULL and call lzma_free() here. + if (next->end != NULL) + next->end(next->coder, allocator); + else + lzma_free(next->coder, allocator); + + // Reset the variables so the we don't accidentally think + // that it is an already initialized coder. + *next = LZMA_NEXT_CODER_INIT; + } + + return; +} + + +////////////////////////////////////// +// External to internal API wrapper // +////////////////////////////////////// + +extern lzma_ret +lzma_strm_init(lzma_stream *strm) +{ + if (strm == NULL) + return LZMA_PROG_ERROR; + + if (strm->internal == NULL) { + strm->internal = lzma_alloc(sizeof(lzma_internal), + strm->allocator); + if (strm->internal == NULL) + return LZMA_MEM_ERROR; + + strm->internal->next = LZMA_NEXT_CODER_INIT; + } + + memzero(strm->internal->supported_actions, + sizeof(strm->internal->supported_actions)); + strm->internal->sequence = ISEQ_RUN; + strm->internal->allow_buf_error = false; + + strm->total_in = 0; + strm->total_out = 0; + + return LZMA_OK; +} + + +extern LZMA_API(lzma_ret) +lzma_code(lzma_stream *strm, lzma_action action) +{ + // Sanity checks + if ((strm->next_in == NULL && strm->avail_in != 0) + || (strm->next_out == NULL && strm->avail_out != 0) + || strm->internal == NULL + || strm->internal->next.code == NULL + || (unsigned int)(action) > LZMA_ACTION_MAX + || !strm->internal->supported_actions[action]) + return LZMA_PROG_ERROR; + + // Check if unsupported members have been set to non-zero or non-NULL, + // which would indicate that some new feature is wanted. + if (strm->reserved_ptr1 != NULL + || strm->reserved_ptr2 != NULL + || strm->reserved_ptr3 != NULL + || strm->reserved_ptr4 != NULL + || strm->reserved_int1 != 0 + || strm->reserved_int2 != 0 + || strm->reserved_int3 != 0 + || strm->reserved_int4 != 0 + || strm->reserved_enum1 != LZMA_RESERVED_ENUM + || strm->reserved_enum2 != LZMA_RESERVED_ENUM) + return LZMA_OPTIONS_ERROR; + + switch (strm->internal->sequence) { + case ISEQ_RUN: + switch (action) { + case LZMA_RUN: + break; + + case LZMA_SYNC_FLUSH: + strm->internal->sequence = ISEQ_SYNC_FLUSH; + break; + + case LZMA_FULL_FLUSH: + strm->internal->sequence = ISEQ_FULL_FLUSH; + break; + + case LZMA_FINISH: + strm->internal->sequence = ISEQ_FINISH; + break; + + case LZMA_FULL_BARRIER: + strm->internal->sequence = ISEQ_FULL_BARRIER; + break; + } + + break; + + case ISEQ_SYNC_FLUSH: + // The same action must be used until we return + // LZMA_STREAM_END, and the amount of input must not change. + if (action != LZMA_SYNC_FLUSH + || strm->internal->avail_in != strm->avail_in) + return LZMA_PROG_ERROR; + + break; + + case ISEQ_FULL_FLUSH: + if (action != LZMA_FULL_FLUSH + || strm->internal->avail_in != strm->avail_in) + return LZMA_PROG_ERROR; + + break; + + case ISEQ_FINISH: + if (action != LZMA_FINISH + || strm->internal->avail_in != strm->avail_in) + return LZMA_PROG_ERROR; + + break; + + case ISEQ_FULL_BARRIER: + if (action != LZMA_FULL_BARRIER + || strm->internal->avail_in != strm->avail_in) + return LZMA_PROG_ERROR; + + break; + + case ISEQ_END: + return LZMA_STREAM_END; + + case ISEQ_ERROR: + default: + return LZMA_PROG_ERROR; + } + + size_t in_pos = 0; + size_t out_pos = 0; + lzma_ret ret = strm->internal->next.code( + strm->internal->next.coder, strm->allocator, + strm->next_in, &in_pos, strm->avail_in, + strm->next_out, &out_pos, strm->avail_out, action); + + strm->next_in += in_pos; + strm->avail_in -= in_pos; + strm->total_in += in_pos; + + strm->next_out += out_pos; + strm->avail_out -= out_pos; + strm->total_out += out_pos; + + strm->internal->avail_in = strm->avail_in; + + // Cast is needed to silence a warning about LZMA_TIMED_OUT, which + // isn't part of lzma_ret enumeration. + switch ((unsigned int)(ret)) { + case LZMA_OK: + // Don't return LZMA_BUF_ERROR when it happens the first time. + // This is to avoid returning LZMA_BUF_ERROR when avail_out + // was zero but still there was no more data left to written + // to next_out. + if (out_pos == 0 && in_pos == 0) { + if (strm->internal->allow_buf_error) + ret = LZMA_BUF_ERROR; + else + strm->internal->allow_buf_error = true; + } else { + strm->internal->allow_buf_error = false; + } + break; + + case LZMA_TIMED_OUT: + strm->internal->allow_buf_error = false; + ret = LZMA_OK; + break; + + case LZMA_STREAM_END: + if (strm->internal->sequence == ISEQ_SYNC_FLUSH + || strm->internal->sequence == ISEQ_FULL_FLUSH + || strm->internal->sequence + == ISEQ_FULL_BARRIER) + strm->internal->sequence = ISEQ_RUN; + else + strm->internal->sequence = ISEQ_END; + + // Fall through + + case LZMA_NO_CHECK: + case LZMA_UNSUPPORTED_CHECK: + case LZMA_GET_CHECK: + case LZMA_MEMLIMIT_ERROR: + // Something else than LZMA_OK, but not a fatal error, + // that is, coding may be continued (except if ISEQ_END). + strm->internal->allow_buf_error = false; + break; + + default: + // All the other errors are fatal; coding cannot be continued. + assert(ret != LZMA_BUF_ERROR); + strm->internal->sequence = ISEQ_ERROR; + break; + } + + return ret; +} + + +extern LZMA_API(void) +lzma_end(lzma_stream *strm) +{ + if (strm != NULL && strm->internal != NULL) { + lzma_next_end(&strm->internal->next, strm->allocator); + lzma_free(strm->internal, strm->allocator); + strm->internal = NULL; + } + + return; +} + + +extern LZMA_API(void) +lzma_get_progress(lzma_stream *strm, + uint64_t *progress_in, uint64_t *progress_out) +{ + if (strm->internal->next.get_progress != NULL) { + strm->internal->next.get_progress(strm->internal->next.coder, + progress_in, progress_out); + } else { + *progress_in = strm->total_in; + *progress_out = strm->total_out; + } + + return; +} + + +extern LZMA_API(lzma_check) +lzma_get_check(const lzma_stream *strm) +{ + // Return LZMA_CHECK_NONE if we cannot know the check type. + // It's a bug in the application if this happens. + if (strm->internal->next.get_check == NULL) + return LZMA_CHECK_NONE; + + return strm->internal->next.get_check(strm->internal->next.coder); +} + + +extern LZMA_API(uint64_t) +lzma_memusage(const lzma_stream *strm) +{ + uint64_t memusage; + uint64_t old_memlimit; + + if (strm == NULL || strm->internal == NULL + || strm->internal->next.memconfig == NULL + || strm->internal->next.memconfig( + strm->internal->next.coder, + &memusage, &old_memlimit, 0) != LZMA_OK) + return 0; + + return memusage; +} + + +extern LZMA_API(uint64_t) +lzma_memlimit_get(const lzma_stream *strm) +{ + uint64_t old_memlimit; + uint64_t memusage; + + if (strm == NULL || strm->internal == NULL + || strm->internal->next.memconfig == NULL + || strm->internal->next.memconfig( + strm->internal->next.coder, + &memusage, &old_memlimit, 0) != LZMA_OK) + return 0; + + return old_memlimit; +} + + +extern LZMA_API(lzma_ret) +lzma_memlimit_set(lzma_stream *strm, uint64_t new_memlimit) +{ + // Dummy variables to simplify memconfig functions + uint64_t old_memlimit; + uint64_t memusage; + + if (strm == NULL || strm->internal == NULL + || strm->internal->next.memconfig == NULL) + return LZMA_PROG_ERROR; + + // Zero is a special value that cannot be used as an actual limit. + // If 0 was specified, use 1 instead. + if (new_memlimit == 0) + new_memlimit = 1; + + return strm->internal->next.memconfig(strm->internal->next.coder, + &memusage, &old_memlimit, new_memlimit); +} diff --git a/dependencies/cmliblzma/liblzma/common/common.h b/dependencies/cmliblzma/liblzma/common/common.h new file mode 100644 index 0000000..dde3ae0 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/common.h @@ -0,0 +1,313 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file common.h +/// \brief Definitions common to the whole liblzma library +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_COMMON_H +#define LZMA_COMMON_H + +#include "sysdefs.h" +#include "tuklib_integer.h" + +#if defined(_WIN32) || defined(__CYGWIN__) +# ifdef DLL_EXPORT +# define LZMA_API_EXPORT __declspec(dllexport) +# else +# define LZMA_API_EXPORT +# endif +// Don't use ifdef or defined() below. +#elif HAVE_VISIBILITY +# define LZMA_API_EXPORT __attribute__((__visibility__("default"))) +#else +# define LZMA_API_EXPORT +#endif + +#define LZMA_API(type) LZMA_API_EXPORT type LZMA_API_CALL + +#include "lzma.h" + +// These allow helping the compiler in some often-executed branches, whose +// result is almost always the same. +#ifdef __GNUC__ +# define likely(expr) __builtin_expect(expr, true) +# define unlikely(expr) __builtin_expect(expr, false) +#else +# define likely(expr) (expr) +# define unlikely(expr) (expr) +#endif + + +/// Size of temporary buffers needed in some filters +#define LZMA_BUFFER_SIZE 4096 + + +/// Maximum number of worker threads within one multithreaded component. +/// The limit exists solely to make it simpler to prevent integer overflows +/// when allocating structures etc. This should be big enough for now... +/// the code won't scale anywhere close to this number anyway. +#define LZMA_THREADS_MAX 16384 + + +/// Starting value for memory usage estimates. Instead of calculating size +/// of _every_ structure and taking into account malloc() overhead etc., we +/// add a base size to all memory usage estimates. It's not very accurate +/// but should be easily good enough. +#define LZMA_MEMUSAGE_BASE (UINT64_C(1) << 15) + +/// Start of internal Filter ID space. These IDs must never be used +/// in Streams. +#define LZMA_FILTER_RESERVED_START (LZMA_VLI_C(1) << 62) + + +/// Supported flags that can be passed to lzma_stream_decoder() +/// or lzma_auto_decoder(). +#define LZMA_SUPPORTED_FLAGS \ + ( LZMA_TELL_NO_CHECK \ + | LZMA_TELL_UNSUPPORTED_CHECK \ + | LZMA_TELL_ANY_CHECK \ + | LZMA_IGNORE_CHECK \ + | LZMA_CONCATENATED ) + + +/// Largest valid lzma_action value as unsigned integer. +#define LZMA_ACTION_MAX ((unsigned int)(LZMA_FULL_BARRIER)) + + +/// Special return value (lzma_ret) to indicate that a timeout was reached +/// and lzma_code() must not return LZMA_BUF_ERROR. This is converted to +/// LZMA_OK in lzma_code(). This is not in the lzma_ret enumeration because +/// there's no need to have it in the public API. +#define LZMA_TIMED_OUT 32 + + +typedef struct lzma_next_coder_s lzma_next_coder; + +typedef struct lzma_filter_info_s lzma_filter_info; + + +/// Type of a function used to initialize a filter encoder or decoder +typedef lzma_ret (*lzma_init_function)( + lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter_info *filters); + +/// Type of a function to do some kind of coding work (filters, Stream, +/// Block encoders/decoders etc.). Some special coders use don't use both +/// input and output buffers, but for simplicity they still use this same +/// function prototype. +typedef lzma_ret (*lzma_code_function)( + void *coder, const lzma_allocator *allocator, + const uint8_t *restrict in, size_t *restrict in_pos, + size_t in_size, uint8_t *restrict out, + size_t *restrict out_pos, size_t out_size, + lzma_action action); + +/// Type of a function to free the memory allocated for the coder +typedef void (*lzma_end_function)( + void *coder, const lzma_allocator *allocator); + + +/// Raw coder validates and converts an array of lzma_filter structures to +/// an array of lzma_filter_info structures. This array is used with +/// lzma_next_filter_init to initialize the filter chain. +struct lzma_filter_info_s { + /// Filter ID. This is used only by the encoder + /// with lzma_filters_update(). + lzma_vli id; + + /// Pointer to function used to initialize the filter. + /// This is NULL to indicate end of array. + lzma_init_function init; + + /// Pointer to filter's options structure + void *options; +}; + + +/// Hold data and function pointers of the next filter in the chain. +struct lzma_next_coder_s { + /// Pointer to coder-specific data + void *coder; + + /// Filter ID. This is LZMA_VLI_UNKNOWN when this structure doesn't + /// point to a filter coder. + lzma_vli id; + + /// "Pointer" to init function. This is never called here. + /// We need only to detect if we are initializing a coder + /// that was allocated earlier. See lzma_next_coder_init and + /// lzma_next_strm_init macros in this file. + uintptr_t init; + + /// Pointer to function to do the actual coding + lzma_code_function code; + + /// Pointer to function to free lzma_next_coder.coder. This can + /// be NULL; in that case, lzma_free is called to free + /// lzma_next_coder.coder. + lzma_end_function end; + + /// Pointer to a function to get progress information. If this is NULL, + /// lzma_stream.total_in and .total_out are used instead. + void (*get_progress)(void *coder, + uint64_t *progress_in, uint64_t *progress_out); + + /// Pointer to function to return the type of the integrity check. + /// Most coders won't support this. + lzma_check (*get_check)(const void *coder); + + /// Pointer to function to get and/or change the memory usage limit. + /// If new_memlimit == 0, the limit is not changed. + lzma_ret (*memconfig)(void *coder, uint64_t *memusage, + uint64_t *old_memlimit, uint64_t new_memlimit); + + /// Update the filter-specific options or the whole filter chain + /// in the encoder. + lzma_ret (*update)(void *coder, const lzma_allocator *allocator, + const lzma_filter *filters, + const lzma_filter *reversed_filters); +}; + + +/// Macro to initialize lzma_next_coder structure +#define LZMA_NEXT_CODER_INIT \ + (lzma_next_coder){ \ + .coder = NULL, \ + .init = (uintptr_t)(NULL), \ + .id = LZMA_VLI_UNKNOWN, \ + .code = NULL, \ + .end = NULL, \ + .get_progress = NULL, \ + .get_check = NULL, \ + .memconfig = NULL, \ + .update = NULL, \ + } + + +/// Internal data for lzma_strm_init, lzma_code, and lzma_end. A pointer to +/// this is stored in lzma_stream. +struct lzma_internal_s { + /// The actual coder that should do something useful + lzma_next_coder next; + + /// Track the state of the coder. This is used to validate arguments + /// so that the actual coders can rely on e.g. that LZMA_SYNC_FLUSH + /// is used on every call to lzma_code until next.code has returned + /// LZMA_STREAM_END. + enum { + ISEQ_RUN, + ISEQ_SYNC_FLUSH, + ISEQ_FULL_FLUSH, + ISEQ_FINISH, + ISEQ_FULL_BARRIER, + ISEQ_END, + ISEQ_ERROR, + } sequence; + + /// A copy of lzma_stream avail_in. This is used to verify that the + /// amount of input doesn't change once e.g. LZMA_FINISH has been + /// used. + size_t avail_in; + + /// Indicates which lzma_action values are allowed by next.code. + bool supported_actions[LZMA_ACTION_MAX + 1]; + + /// If true, lzma_code will return LZMA_BUF_ERROR if no progress was + /// made (no input consumed and no output produced by next.code). + bool allow_buf_error; +}; + + +/// Allocates memory +extern void *lzma_alloc(size_t size, const lzma_allocator *allocator) + lzma_attribute((__malloc__)) lzma_attr_alloc_size(1); + +/// Allocates memory and zeroes it (like calloc()). This can be faster +/// than lzma_alloc() + memzero() while being backward compatible with +/// custom allocators. +extern void * lzma_attribute((__malloc__)) lzma_attr_alloc_size(1) + lzma_alloc_zero(size_t size, const lzma_allocator *allocator); + +/// Frees memory +extern void lzma_free(void *ptr, const lzma_allocator *allocator); + + +/// Allocates strm->internal if it is NULL, and initializes *strm and +/// strm->internal. This function is only called via lzma_next_strm_init macro. +extern lzma_ret lzma_strm_init(lzma_stream *strm); + +/// Initializes the next filter in the chain, if any. This takes care of +/// freeing the memory of previously initialized filter if it is different +/// than the filter being initialized now. This way the actual filter +/// initialization functions don't need to use lzma_next_coder_init macro. +extern lzma_ret lzma_next_filter_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters); + +/// Update the next filter in the chain, if any. This checks that +/// the application is not trying to change the Filter IDs. +extern lzma_ret lzma_next_filter_update( + lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter *reversed_filters); + +/// Frees the memory allocated for next->coder either using next->end or, +/// if next->end is NULL, using lzma_free. +extern void lzma_next_end(lzma_next_coder *next, + const lzma_allocator *allocator); + + +/// Copy as much data as possible from in[] to out[] and update *in_pos +/// and *out_pos accordingly. Returns the number of bytes copied. +extern size_t lzma_bufcpy(const uint8_t *restrict in, size_t *restrict in_pos, + size_t in_size, uint8_t *restrict out, + size_t *restrict out_pos, size_t out_size); + + +/// \brief Return if expression doesn't evaluate to LZMA_OK +/// +/// There are several situations where we want to return immediately +/// with the value of expr if it isn't LZMA_OK. This macro shortens +/// the code a little. +#define return_if_error(expr) \ +do { \ + const lzma_ret ret_ = (expr); \ + if (ret_ != LZMA_OK) \ + return ret_; \ +} while (0) + + +/// If next isn't already initialized, free the previous coder. Then mark +/// that next is _possibly_ initialized for the coder using this macro. +/// "Possibly" means that if e.g. allocation of next->coder fails, the +/// structure isn't actually initialized for this coder, but leaving +/// next->init to func is still OK. +#define lzma_next_coder_init(func, next, allocator) \ +do { \ + if ((uintptr_t)(func) != (next)->init) \ + lzma_next_end(next, allocator); \ + (next)->init = (uintptr_t)(func); \ +} while (0) + + +/// Initializes lzma_strm and calls func() to initialize strm->internal->next. +/// (The function being called will use lzma_next_coder_init()). If +/// initialization fails, memory that wasn't freed by func() is freed +/// along strm->internal. +#define lzma_next_strm_init(func, strm, ...) \ +do { \ + return_if_error(lzma_strm_init(strm)); \ + const lzma_ret ret_ = func(&(strm)->internal->next, \ + (strm)->allocator, __VA_ARGS__); \ + if (ret_ != LZMA_OK) { \ + lzma_end(strm); \ + return ret_; \ + } \ +} while (0) + +#endif diff --git a/dependencies/cmliblzma/liblzma/common/easy_buffer_encoder.c b/dependencies/cmliblzma/liblzma/common/easy_buffer_encoder.c new file mode 100644 index 0000000..48eb56f --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/easy_buffer_encoder.c @@ -0,0 +1,27 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file easy_buffer_encoder.c +/// \brief Easy single-call .xz Stream encoder +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "easy_preset.h" + + +extern LZMA_API(lzma_ret) +lzma_easy_buffer_encode(uint32_t preset, lzma_check check, + const lzma_allocator *allocator, const uint8_t *in, + size_t in_size, uint8_t *out, size_t *out_pos, size_t out_size) +{ + lzma_options_easy opt_easy; + if (lzma_easy_preset(&opt_easy, preset)) + return LZMA_OPTIONS_ERROR; + + return lzma_stream_buffer_encode(opt_easy.filters, check, + allocator, in, in_size, out, out_pos, out_size); +} diff --git a/dependencies/cmliblzma/liblzma/common/easy_decoder_memusage.c b/dependencies/cmliblzma/liblzma/common/easy_decoder_memusage.c new file mode 100644 index 0000000..20bcd5b --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/easy_decoder_memusage.c @@ -0,0 +1,24 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file easy_decoder_memusage.c +/// \brief Decoder memory usage calculation to match easy encoder presets +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "easy_preset.h" + + +extern LZMA_API(uint64_t) +lzma_easy_decoder_memusage(uint32_t preset) +{ + lzma_options_easy opt_easy; + if (lzma_easy_preset(&opt_easy, preset)) + return UINT32_MAX; + + return lzma_raw_decoder_memusage(opt_easy.filters); +} diff --git a/dependencies/cmliblzma/liblzma/common/easy_encoder.c b/dependencies/cmliblzma/liblzma/common/easy_encoder.c new file mode 100644 index 0000000..5cb492d --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/easy_encoder.c @@ -0,0 +1,24 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file easy_encoder.c +/// \brief Easy .xz Stream encoder initialization +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "easy_preset.h" + + +extern LZMA_API(lzma_ret) +lzma_easy_encoder(lzma_stream *strm, uint32_t preset, lzma_check check) +{ + lzma_options_easy opt_easy; + if (lzma_easy_preset(&opt_easy, preset)) + return LZMA_OPTIONS_ERROR; + + return lzma_stream_encoder(strm, opt_easy.filters, check); +} diff --git a/dependencies/cmliblzma/liblzma/common/easy_encoder_memusage.c b/dependencies/cmliblzma/liblzma/common/easy_encoder_memusage.c new file mode 100644 index 0000000..e910575 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/easy_encoder_memusage.c @@ -0,0 +1,24 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file easy_encoder_memusage.c +/// \brief Easy .xz Stream encoder memory usage calculation +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "easy_preset.h" + + +extern LZMA_API(uint64_t) +lzma_easy_encoder_memusage(uint32_t preset) +{ + lzma_options_easy opt_easy; + if (lzma_easy_preset(&opt_easy, preset)) + return UINT32_MAX; + + return lzma_raw_encoder_memusage(opt_easy.filters); +} diff --git a/dependencies/cmliblzma/liblzma/common/easy_preset.c b/dependencies/cmliblzma/liblzma/common/easy_preset.c new file mode 100644 index 0000000..2f98598 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/easy_preset.c @@ -0,0 +1,27 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file easy_preset.c +/// \brief Preset handling for easy encoder and decoder +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "easy_preset.h" + + +extern bool +lzma_easy_preset(lzma_options_easy *opt_easy, uint32_t preset) +{ + if (lzma_lzma_preset(&opt_easy->opt_lzma, preset)) + return true; + + opt_easy->filters[0].id = LZMA_FILTER_LZMA2; + opt_easy->filters[0].options = &opt_easy->opt_lzma; + opt_easy->filters[1].id = LZMA_VLI_UNKNOWN; + + return false; +} diff --git a/dependencies/cmliblzma/liblzma/common/easy_preset.h b/dependencies/cmliblzma/liblzma/common/easy_preset.h new file mode 100644 index 0000000..382ade8 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/easy_preset.h @@ -0,0 +1,32 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file easy_preset.h +/// \brief Preset handling for easy encoder and decoder +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "common.h" + + +typedef struct { + /// We need to keep the filters array available in case + /// LZMA_FULL_FLUSH is used. + lzma_filter filters[LZMA_FILTERS_MAX + 1]; + + /// Options for LZMA2 + lzma_options_lzma opt_lzma; + + // Options for more filters can be added later, so this struct + // is not ready to be put into the public API. + +} lzma_options_easy; + + +/// Set *easy to the settings given by the preset. Returns true on error, +/// false on success. +extern bool lzma_easy_preset(lzma_options_easy *easy, uint32_t preset); diff --git a/dependencies/cmliblzma/liblzma/common/filter_buffer_decoder.c b/dependencies/cmliblzma/liblzma/common/filter_buffer_decoder.c new file mode 100644 index 0000000..6620986 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/filter_buffer_decoder.c @@ -0,0 +1,88 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file filter_buffer_decoder.c +/// \brief Single-call raw decoding +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "filter_decoder.h" + + +extern LZMA_API(lzma_ret) +lzma_raw_buffer_decode( + const lzma_filter *filters, const lzma_allocator *allocator, + const uint8_t *in, size_t *in_pos, size_t in_size, + uint8_t *out, size_t *out_pos, size_t out_size) +{ + // Validate what isn't validated later in filter_common.c. + if (in == NULL || in_pos == NULL || *in_pos > in_size || out == NULL + || out_pos == NULL || *out_pos > out_size) + return LZMA_PROG_ERROR; + + // Initialize the decoer. + lzma_next_coder next = LZMA_NEXT_CODER_INIT; + return_if_error(lzma_raw_decoder_init(&next, allocator, filters)); + + // Store the positions so that we can restore them if something + // goes wrong. + const size_t in_start = *in_pos; + const size_t out_start = *out_pos; + + // Do the actual decoding and free decoder's memory. + lzma_ret ret = next.code(next.coder, allocator, in, in_pos, in_size, + out, out_pos, out_size, LZMA_FINISH); + + if (ret == LZMA_STREAM_END) { + ret = LZMA_OK; + } else { + if (ret == LZMA_OK) { + // Either the input was truncated or the + // output buffer was too small. + assert(*in_pos == in_size || *out_pos == out_size); + + if (*in_pos != in_size) { + // Since input wasn't consumed completely, + // the output buffer became full and is + // too small. + ret = LZMA_BUF_ERROR; + + } else if (*out_pos != out_size) { + // Since output didn't became full, the input + // has to be truncated. + ret = LZMA_DATA_ERROR; + + } else { + // All the input was consumed and output + // buffer is full. Now we don't immediately + // know the reason for the error. Try + // decoding one more byte. If it succeeds, + // then the output buffer was too small. If + // we cannot get a new output byte, the input + // is truncated. + uint8_t tmp[1]; + size_t tmp_pos = 0; + (void)next.code(next.coder, allocator, + in, in_pos, in_size, + tmp, &tmp_pos, 1, LZMA_FINISH); + + if (tmp_pos == 1) + ret = LZMA_BUF_ERROR; + else + ret = LZMA_DATA_ERROR; + } + } + + // Restore the positions. + *in_pos = in_start; + *out_pos = out_start; + } + + lzma_next_end(&next, allocator); + + return ret; +} diff --git a/dependencies/cmliblzma/liblzma/common/filter_buffer_encoder.c b/dependencies/cmliblzma/liblzma/common/filter_buffer_encoder.c new file mode 100644 index 0000000..dda18e3 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/filter_buffer_encoder.c @@ -0,0 +1,55 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file filter_buffer_encoder.c +/// \brief Single-call raw encoding +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "filter_encoder.h" + + +extern LZMA_API(lzma_ret) +lzma_raw_buffer_encode( + const lzma_filter *filters, const lzma_allocator *allocator, + const uint8_t *in, size_t in_size, + uint8_t *out, size_t *out_pos, size_t out_size) +{ + // Validate what isn't validated later in filter_common.c. + if ((in == NULL && in_size != 0) || out == NULL + || out_pos == NULL || *out_pos > out_size) + return LZMA_PROG_ERROR; + + // Initialize the encoder + lzma_next_coder next = LZMA_NEXT_CODER_INIT; + return_if_error(lzma_raw_encoder_init(&next, allocator, filters)); + + // Store the output position so that we can restore it if + // something goes wrong. + const size_t out_start = *out_pos; + + // Do the actual encoding and free coder's memory. + size_t in_pos = 0; + lzma_ret ret = next.code(next.coder, allocator, in, &in_pos, in_size, + out, out_pos, out_size, LZMA_FINISH); + lzma_next_end(&next, allocator); + + if (ret == LZMA_STREAM_END) { + ret = LZMA_OK; + } else { + if (ret == LZMA_OK) { + // Output buffer was too small. + assert(*out_pos == out_size); + ret = LZMA_BUF_ERROR; + } + + // Restore the output position. + *out_pos = out_start; + } + + return ret; +} diff --git a/dependencies/cmliblzma/liblzma/common/filter_common.c b/dependencies/cmliblzma/liblzma/common/filter_common.c new file mode 100644 index 0000000..9ad5d5d --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/filter_common.c @@ -0,0 +1,337 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file filter_common.c +/// \brief Filter-specific stuff common for both encoder and decoder +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "filter_common.h" + + +static const struct { + /// Filter ID + lzma_vli id; + + /// Size of the filter-specific options structure + size_t options_size; + + /// True if it is OK to use this filter as non-last filter in + /// the chain. + bool non_last_ok; + + /// True if it is OK to use this filter as the last filter in + /// the chain. + bool last_ok; + + /// True if the filter may change the size of the data (that is, the + /// amount of encoded output can be different than the amount of + /// uncompressed input). + bool changes_size; + +} features[] = { +#if defined (HAVE_ENCODER_LZMA1) || defined(HAVE_DECODER_LZMA1) + { + .id = LZMA_FILTER_LZMA1, + .options_size = sizeof(lzma_options_lzma), + .non_last_ok = false, + .last_ok = true, + .changes_size = true, + }, +#endif +#if defined(HAVE_ENCODER_LZMA2) || defined(HAVE_DECODER_LZMA2) + { + .id = LZMA_FILTER_LZMA2, + .options_size = sizeof(lzma_options_lzma), + .non_last_ok = false, + .last_ok = true, + .changes_size = true, + }, +#endif +#if defined(HAVE_ENCODER_X86) || defined(HAVE_DECODER_X86) + { + .id = LZMA_FILTER_X86, + .options_size = sizeof(lzma_options_bcj), + .non_last_ok = true, + .last_ok = false, + .changes_size = false, + }, +#endif +#if defined(HAVE_ENCODER_POWERPC) || defined(HAVE_DECODER_POWERPC) + { + .id = LZMA_FILTER_POWERPC, + .options_size = sizeof(lzma_options_bcj), + .non_last_ok = true, + .last_ok = false, + .changes_size = false, + }, +#endif +#if defined(HAVE_ENCODER_IA64) || defined(HAVE_DECODER_IA64) + { + .id = LZMA_FILTER_IA64, + .options_size = sizeof(lzma_options_bcj), + .non_last_ok = true, + .last_ok = false, + .changes_size = false, + }, +#endif +#if defined(HAVE_ENCODER_ARM) || defined(HAVE_DECODER_ARM) + { + .id = LZMA_FILTER_ARM, + .options_size = sizeof(lzma_options_bcj), + .non_last_ok = true, + .last_ok = false, + .changes_size = false, + }, +#endif +#if defined(HAVE_ENCODER_ARMTHUMB) || defined(HAVE_DECODER_ARMTHUMB) + { + .id = LZMA_FILTER_ARMTHUMB, + .options_size = sizeof(lzma_options_bcj), + .non_last_ok = true, + .last_ok = false, + .changes_size = false, + }, +#endif +#if defined(HAVE_ENCODER_SPARC) || defined(HAVE_DECODER_SPARC) + { + .id = LZMA_FILTER_SPARC, + .options_size = sizeof(lzma_options_bcj), + .non_last_ok = true, + .last_ok = false, + .changes_size = false, + }, +#endif +#if defined(HAVE_ENCODER_DELTA) || defined(HAVE_DECODER_DELTA) + { + .id = LZMA_FILTER_DELTA, + .options_size = sizeof(lzma_options_delta), + .non_last_ok = true, + .last_ok = false, + .changes_size = false, + }, +#endif + { + .id = LZMA_VLI_UNKNOWN + } +}; + + +extern LZMA_API(lzma_ret) +lzma_filters_copy(const lzma_filter *src, lzma_filter *dest, + const lzma_allocator *allocator) +{ + if (src == NULL || dest == NULL) + return LZMA_PROG_ERROR; + + lzma_ret ret; + size_t i; + for (i = 0; src[i].id != LZMA_VLI_UNKNOWN; ++i) { + // There must be a maximum of four filters plus + // the array terminator. + if (i == LZMA_FILTERS_MAX) { + ret = LZMA_OPTIONS_ERROR; + goto error; + } + + dest[i].id = src[i].id; + + if (src[i].options == NULL) { + dest[i].options = NULL; + } else { + // See if the filter is supported only when the + // options is not NULL. This might be convenient + // sometimes if the app is actually copying only + // a partial filter chain with a place holder ID. + // + // When options is not NULL, the Filter ID must be + // supported by us, because otherwise we don't know + // how big the options are. + size_t j; + for (j = 0; src[i].id != features[j].id; ++j) { + if (features[j].id == LZMA_VLI_UNKNOWN) { + ret = LZMA_OPTIONS_ERROR; + goto error; + } + } + + // Allocate and copy the options. + dest[i].options = lzma_alloc(features[j].options_size, + allocator); + if (dest[i].options == NULL) { + ret = LZMA_MEM_ERROR; + goto error; + } + + memcpy(dest[i].options, src[i].options, + features[j].options_size); + } + } + + // Terminate the filter array. + assert(i <= LZMA_FILTERS_MAX + 1); + dest[i].id = LZMA_VLI_UNKNOWN; + dest[i].options = NULL; + + return LZMA_OK; + +error: + // Free the options which we have already allocated. + while (i-- > 0) { + lzma_free(dest[i].options, allocator); + dest[i].options = NULL; + } + + return ret; +} + + +static lzma_ret +validate_chain(const lzma_filter *filters, size_t *count) +{ + // There must be at least one filter. + if (filters == NULL || filters[0].id == LZMA_VLI_UNKNOWN) + return LZMA_PROG_ERROR; + + // Number of non-last filters that may change the size of the data + // significantly (that is, more than 1-2 % or so). + size_t changes_size_count = 0; + + // True if it is OK to add a new filter after the current filter. + bool non_last_ok = true; + + // True if the last filter in the given chain is actually usable as + // the last filter. Only filters that support embedding End of Payload + // Marker can be used as the last filter in the chain. + bool last_ok = false; + + size_t i = 0; + do { + size_t j; + for (j = 0; filters[i].id != features[j].id; ++j) + if (features[j].id == LZMA_VLI_UNKNOWN) + return LZMA_OPTIONS_ERROR; + + // If the previous filter in the chain cannot be a non-last + // filter, the chain is invalid. + if (!non_last_ok) + return LZMA_OPTIONS_ERROR; + + non_last_ok = features[j].non_last_ok; + last_ok = features[j].last_ok; + changes_size_count += features[j].changes_size; + + } while (filters[++i].id != LZMA_VLI_UNKNOWN); + + // There must be 1-4 filters. The last filter must be usable as + // the last filter in the chain. A maximum of three filters are + // allowed to change the size of the data. + if (i > LZMA_FILTERS_MAX || !last_ok || changes_size_count > 3) + return LZMA_OPTIONS_ERROR; + + *count = i; + return LZMA_OK; +} + + +extern lzma_ret +lzma_raw_coder_init(lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter *options, + lzma_filter_find coder_find, bool is_encoder) +{ + // Do some basic validation and get the number of filters. + size_t count; + return_if_error(validate_chain(options, &count)); + + // Set the filter functions and copy the options pointer. + lzma_filter_info filters[LZMA_FILTERS_MAX + 1]; + if (is_encoder) { + for (size_t i = 0; i < count; ++i) { + // The order of the filters is reversed in the + // encoder. It allows more efficient handling + // of the uncompressed data. + const size_t j = count - i - 1; + + const lzma_filter_coder *const fc + = coder_find(options[i].id); + if (fc == NULL || fc->init == NULL) + return LZMA_OPTIONS_ERROR; + + filters[j].id = options[i].id; + filters[j].init = fc->init; + filters[j].options = options[i].options; + } + } else { + for (size_t i = 0; i < count; ++i) { + const lzma_filter_coder *const fc + = coder_find(options[i].id); + if (fc == NULL || fc->init == NULL) + return LZMA_OPTIONS_ERROR; + + filters[i].id = options[i].id; + filters[i].init = fc->init; + filters[i].options = options[i].options; + } + } + + // Terminate the array. + filters[count].id = LZMA_VLI_UNKNOWN; + filters[count].init = NULL; + + // Initialize the filters. + const lzma_ret ret = lzma_next_filter_init(next, allocator, filters); + if (ret != LZMA_OK) + lzma_next_end(next, allocator); + + return ret; +} + + +extern uint64_t +lzma_raw_coder_memusage(lzma_filter_find coder_find, + const lzma_filter *filters) +{ + // The chain has to have at least one filter. + { + size_t tmp; + if (validate_chain(filters, &tmp) != LZMA_OK) + return UINT64_MAX; + } + + uint64_t total = 0; + size_t i = 0; + + do { + const lzma_filter_coder *const fc + = coder_find(filters[i].id); + if (fc == NULL) + return UINT64_MAX; // Unsupported Filter ID + + if (fc->memusage == NULL) { + // This filter doesn't have a function to calculate + // the memory usage and validate the options. Such + // filters need only little memory, so we use 1 KiB + // as a good estimate. They also accept all possible + // options, so there's no need to worry about lack + // of validation. + total += 1024; + } else { + // Call the filter-specific memory usage calculation + // function. + const uint64_t usage + = fc->memusage(filters[i].options); + if (usage == UINT64_MAX) + return UINT64_MAX; // Invalid options + + total += usage; + } + } while (filters[++i].id != LZMA_VLI_UNKNOWN); + + // Add some fixed amount of extra. It's to compensate memory usage + // of Stream, Block etc. coders, malloc() overhead, stack etc. + return total + LZMA_MEMUSAGE_BASE; +} diff --git a/dependencies/cmliblzma/liblzma/common/filter_common.h b/dependencies/cmliblzma/liblzma/common/filter_common.h new file mode 100644 index 0000000..42a26a2 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/filter_common.h @@ -0,0 +1,48 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file filter_common.c +/// \brief Filter-specific stuff common for both encoder and decoder +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_FILTER_COMMON_H +#define LZMA_FILTER_COMMON_H + +#include "common.h" + + +/// Both lzma_filter_encoder and lzma_filter_decoder begin with these members. +typedef struct { + /// Filter ID + lzma_vli id; + + /// Initializes the filter encoder and calls lzma_next_filter_init() + /// for filters + 1. + lzma_init_function init; + + /// Calculates memory usage of the encoder. If the options are + /// invalid, UINT64_MAX is returned. + uint64_t (*memusage)(const void *options); + +} lzma_filter_coder; + + +typedef const lzma_filter_coder *(*lzma_filter_find)(lzma_vli id); + + +extern lzma_ret lzma_raw_coder_init( + lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter *filters, + lzma_filter_find coder_find, bool is_encoder); + + +extern uint64_t lzma_raw_coder_memusage(lzma_filter_find coder_find, + const lzma_filter *filters); + + +#endif diff --git a/dependencies/cmliblzma/liblzma/common/filter_decoder.c b/dependencies/cmliblzma/liblzma/common/filter_decoder.c new file mode 100644 index 0000000..c75b0a8 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/filter_decoder.c @@ -0,0 +1,184 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file filter_decoder.c +/// \brief Filter ID mapping to filter-specific functions +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "filter_decoder.h" +#include "filter_common.h" +#include "lzma_decoder.h" +#include "lzma2_decoder.h" +#include "simple_decoder.h" +#include "delta_decoder.h" + + +typedef struct { + /// Filter ID + lzma_vli id; + + /// Initializes the filter encoder and calls lzma_next_filter_init() + /// for filters + 1. + lzma_init_function init; + + /// Calculates memory usage of the encoder. If the options are + /// invalid, UINT64_MAX is returned. + uint64_t (*memusage)(const void *options); + + /// Decodes Filter Properties. + /// + /// \return - LZMA_OK: Properties decoded successfully. + /// - LZMA_OPTIONS_ERROR: Unsupported properties + /// - LZMA_MEM_ERROR: Memory allocation failed. + lzma_ret (*props_decode)( + void **options, const lzma_allocator *allocator, + const uint8_t *props, size_t props_size); + +} lzma_filter_decoder; + + +static const lzma_filter_decoder decoders[] = { +#ifdef HAVE_DECODER_LZMA1 + { + .id = LZMA_FILTER_LZMA1, + .init = &lzma_lzma_decoder_init, + .memusage = &lzma_lzma_decoder_memusage, + .props_decode = &lzma_lzma_props_decode, + }, +#endif +#ifdef HAVE_DECODER_LZMA2 + { + .id = LZMA_FILTER_LZMA2, + .init = &lzma_lzma2_decoder_init, + .memusage = &lzma_lzma2_decoder_memusage, + .props_decode = &lzma_lzma2_props_decode, + }, +#endif +#ifdef HAVE_DECODER_X86 + { + .id = LZMA_FILTER_X86, + .init = &lzma_simple_x86_decoder_init, + .memusage = NULL, + .props_decode = &lzma_simple_props_decode, + }, +#endif +#ifdef HAVE_DECODER_POWERPC + { + .id = LZMA_FILTER_POWERPC, + .init = &lzma_simple_powerpc_decoder_init, + .memusage = NULL, + .props_decode = &lzma_simple_props_decode, + }, +#endif +#ifdef HAVE_DECODER_IA64 + { + .id = LZMA_FILTER_IA64, + .init = &lzma_simple_ia64_decoder_init, + .memusage = NULL, + .props_decode = &lzma_simple_props_decode, + }, +#endif +#ifdef HAVE_DECODER_ARM + { + .id = LZMA_FILTER_ARM, + .init = &lzma_simple_arm_decoder_init, + .memusage = NULL, + .props_decode = &lzma_simple_props_decode, + }, +#endif +#ifdef HAVE_DECODER_ARMTHUMB + { + .id = LZMA_FILTER_ARMTHUMB, + .init = &lzma_simple_armthumb_decoder_init, + .memusage = NULL, + .props_decode = &lzma_simple_props_decode, + }, +#endif +#ifdef HAVE_DECODER_SPARC + { + .id = LZMA_FILTER_SPARC, + .init = &lzma_simple_sparc_decoder_init, + .memusage = NULL, + .props_decode = &lzma_simple_props_decode, + }, +#endif +#ifdef HAVE_DECODER_DELTA + { + .id = LZMA_FILTER_DELTA, + .init = &lzma_delta_decoder_init, + .memusage = &lzma_delta_coder_memusage, + .props_decode = &lzma_delta_props_decode, + }, +#endif +}; + + +static const lzma_filter_decoder * +decoder_find(lzma_vli id) +{ + for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i) + if (decoders[i].id == id) + return decoders + i; + + return NULL; +} + + +extern LZMA_API(lzma_bool) +lzma_filter_decoder_is_supported(lzma_vli id) +{ + return decoder_find(id) != NULL; +} + + +extern lzma_ret +lzma_raw_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter *options) +{ + return lzma_raw_coder_init(next, allocator, + options, (lzma_filter_find)(&decoder_find), false); +} + + +extern LZMA_API(lzma_ret) +lzma_raw_decoder(lzma_stream *strm, const lzma_filter *options) +{ + lzma_next_strm_init(lzma_raw_decoder_init, strm, options); + + strm->internal->supported_actions[LZMA_RUN] = true; + strm->internal->supported_actions[LZMA_FINISH] = true; + + return LZMA_OK; +} + + +extern LZMA_API(uint64_t) +lzma_raw_decoder_memusage(const lzma_filter *filters) +{ + return lzma_raw_coder_memusage( + (lzma_filter_find)(&decoder_find), filters); +} + + +extern LZMA_API(lzma_ret) +lzma_properties_decode(lzma_filter *filter, const lzma_allocator *allocator, + const uint8_t *props, size_t props_size) +{ + // Make it always NULL so that the caller can always safely free() it. + filter->options = NULL; + + const lzma_filter_decoder *const fd = decoder_find(filter->id); + if (fd == NULL) + return LZMA_OPTIONS_ERROR; + + if (fd->props_decode == NULL) + return props_size == 0 ? LZMA_OK : LZMA_OPTIONS_ERROR; + + return fd->props_decode( + &filter->options, allocator, props, props_size); +} diff --git a/dependencies/cmliblzma/liblzma/common/filter_decoder.h b/dependencies/cmliblzma/liblzma/common/filter_decoder.h new file mode 100644 index 0000000..a2e255f --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/filter_decoder.h @@ -0,0 +1,23 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file filter_decoder.c +/// \brief Filter ID mapping to filter-specific functions +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_FILTER_DECODER_H +#define LZMA_FILTER_DECODER_H + +#include "common.h" + + +extern lzma_ret lzma_raw_decoder_init( + lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter *options); + +#endif diff --git a/dependencies/cmliblzma/liblzma/common/filter_encoder.c b/dependencies/cmliblzma/liblzma/common/filter_encoder.c new file mode 100644 index 0000000..c5d8f39 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/filter_encoder.c @@ -0,0 +1,286 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file filter_decoder.c +/// \brief Filter ID mapping to filter-specific functions +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "filter_encoder.h" +#include "filter_common.h" +#include "lzma_encoder.h" +#include "lzma2_encoder.h" +#include "simple_encoder.h" +#include "delta_encoder.h" + + +typedef struct { + /// Filter ID + lzma_vli id; + + /// Initializes the filter encoder and calls lzma_next_filter_init() + /// for filters + 1. + lzma_init_function init; + + /// Calculates memory usage of the encoder. If the options are + /// invalid, UINT64_MAX is returned. + uint64_t (*memusage)(const void *options); + + /// Calculates the recommended Uncompressed Size for .xz Blocks to + /// which the input data can be split to make multithreaded + /// encoding possible. If this is NULL, it is assumed that + /// the encoder is fast enough with single thread. + uint64_t (*block_size)(const void *options); + + /// Tells the size of the Filter Properties field. If options are + /// invalid, UINT32_MAX is returned. If this is NULL, props_size_fixed + /// is used. + lzma_ret (*props_size_get)(uint32_t *size, const void *options); + uint32_t props_size_fixed; + + /// Encodes Filter Properties. + /// + /// \return - LZMA_OK: Properties encoded successfully. + /// - LZMA_OPTIONS_ERROR: Unsupported options + /// - LZMA_PROG_ERROR: Invalid options or not enough + /// output space + lzma_ret (*props_encode)(const void *options, uint8_t *out); + +} lzma_filter_encoder; + + +static const lzma_filter_encoder encoders[] = { +#ifdef HAVE_ENCODER_LZMA1 + { + .id = LZMA_FILTER_LZMA1, + .init = &lzma_lzma_encoder_init, + .memusage = &lzma_lzma_encoder_memusage, + .block_size = NULL, // FIXME + .props_size_get = NULL, + .props_size_fixed = 5, + .props_encode = &lzma_lzma_props_encode, + }, +#endif +#ifdef HAVE_ENCODER_LZMA2 + { + .id = LZMA_FILTER_LZMA2, + .init = &lzma_lzma2_encoder_init, + .memusage = &lzma_lzma2_encoder_memusage, + .block_size = &lzma_lzma2_block_size, // FIXME + .props_size_get = NULL, + .props_size_fixed = 1, + .props_encode = &lzma_lzma2_props_encode, + }, +#endif +#ifdef HAVE_ENCODER_X86 + { + .id = LZMA_FILTER_X86, + .init = &lzma_simple_x86_encoder_init, + .memusage = NULL, + .block_size = NULL, + .props_size_get = &lzma_simple_props_size, + .props_encode = &lzma_simple_props_encode, + }, +#endif +#ifdef HAVE_ENCODER_POWERPC + { + .id = LZMA_FILTER_POWERPC, + .init = &lzma_simple_powerpc_encoder_init, + .memusage = NULL, + .block_size = NULL, + .props_size_get = &lzma_simple_props_size, + .props_encode = &lzma_simple_props_encode, + }, +#endif +#ifdef HAVE_ENCODER_IA64 + { + .id = LZMA_FILTER_IA64, + .init = &lzma_simple_ia64_encoder_init, + .memusage = NULL, + .block_size = NULL, + .props_size_get = &lzma_simple_props_size, + .props_encode = &lzma_simple_props_encode, + }, +#endif +#ifdef HAVE_ENCODER_ARM + { + .id = LZMA_FILTER_ARM, + .init = &lzma_simple_arm_encoder_init, + .memusage = NULL, + .block_size = NULL, + .props_size_get = &lzma_simple_props_size, + .props_encode = &lzma_simple_props_encode, + }, +#endif +#ifdef HAVE_ENCODER_ARMTHUMB + { + .id = LZMA_FILTER_ARMTHUMB, + .init = &lzma_simple_armthumb_encoder_init, + .memusage = NULL, + .block_size = NULL, + .props_size_get = &lzma_simple_props_size, + .props_encode = &lzma_simple_props_encode, + }, +#endif +#ifdef HAVE_ENCODER_SPARC + { + .id = LZMA_FILTER_SPARC, + .init = &lzma_simple_sparc_encoder_init, + .memusage = NULL, + .block_size = NULL, + .props_size_get = &lzma_simple_props_size, + .props_encode = &lzma_simple_props_encode, + }, +#endif +#ifdef HAVE_ENCODER_DELTA + { + .id = LZMA_FILTER_DELTA, + .init = &lzma_delta_encoder_init, + .memusage = &lzma_delta_coder_memusage, + .block_size = NULL, + .props_size_get = NULL, + .props_size_fixed = 1, + .props_encode = &lzma_delta_props_encode, + }, +#endif +}; + + +static const lzma_filter_encoder * +encoder_find(lzma_vli id) +{ + for (size_t i = 0; i < ARRAY_SIZE(encoders); ++i) + if (encoders[i].id == id) + return encoders + i; + + return NULL; +} + + +extern LZMA_API(lzma_bool) +lzma_filter_encoder_is_supported(lzma_vli id) +{ + return encoder_find(id) != NULL; +} + + +extern LZMA_API(lzma_ret) +lzma_filters_update(lzma_stream *strm, const lzma_filter *filters) +{ + if (strm->internal->next.update == NULL) + return LZMA_PROG_ERROR; + + // Validate the filter chain. + if (lzma_raw_encoder_memusage(filters) == UINT64_MAX) + return LZMA_OPTIONS_ERROR; + + // The actual filter chain in the encoder is reversed. Some things + // still want the normal order chain, so we provide both. + size_t count = 1; + while (filters[count].id != LZMA_VLI_UNKNOWN) + ++count; + + lzma_filter reversed_filters[LZMA_FILTERS_MAX + 1]; + for (size_t i = 0; i < count; ++i) + reversed_filters[count - i - 1] = filters[i]; + + reversed_filters[count].id = LZMA_VLI_UNKNOWN; + + return strm->internal->next.update(strm->internal->next.coder, + strm->allocator, filters, reversed_filters); +} + + +extern lzma_ret +lzma_raw_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter *options) +{ + return lzma_raw_coder_init(next, allocator, + options, (lzma_filter_find)(&encoder_find), true); +} + + +extern LZMA_API(lzma_ret) +lzma_raw_encoder(lzma_stream *strm, const lzma_filter *options) +{ + lzma_next_strm_init(lzma_raw_coder_init, strm, options, + (lzma_filter_find)(&encoder_find), true); + + strm->internal->supported_actions[LZMA_RUN] = true; + strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true; + strm->internal->supported_actions[LZMA_FINISH] = true; + + return LZMA_OK; +} + + +extern LZMA_API(uint64_t) +lzma_raw_encoder_memusage(const lzma_filter *filters) +{ + return lzma_raw_coder_memusage( + (lzma_filter_find)(&encoder_find), filters); +} + + +extern uint64_t +lzma_mt_block_size(const lzma_filter *filters) +{ + uint64_t max = 0; + + for (size_t i = 0; filters[i].id != LZMA_VLI_UNKNOWN; ++i) { + const lzma_filter_encoder *const fe + = encoder_find(filters[i].id); + if (fe->block_size != NULL) { + const uint64_t size + = fe->block_size(filters[i].options); + if (size == 0) + return 0; + + if (size > max) + max = size; + } + } + + return max; +} + + +extern LZMA_API(lzma_ret) +lzma_properties_size(uint32_t *size, const lzma_filter *filter) +{ + const lzma_filter_encoder *const fe = encoder_find(filter->id); + if (fe == NULL) { + // Unknown filter - if the Filter ID is a proper VLI, + // return LZMA_OPTIONS_ERROR instead of LZMA_PROG_ERROR, + // because it's possible that we just don't have support + // compiled in for the requested filter. + return filter->id <= LZMA_VLI_MAX + ? LZMA_OPTIONS_ERROR : LZMA_PROG_ERROR; + } + + if (fe->props_size_get == NULL) { + // No props_size_get() function, use props_size_fixed. + *size = fe->props_size_fixed; + return LZMA_OK; + } + + return fe->props_size_get(size, filter->options); +} + + +extern LZMA_API(lzma_ret) +lzma_properties_encode(const lzma_filter *filter, uint8_t *props) +{ + const lzma_filter_encoder *const fe = encoder_find(filter->id); + if (fe == NULL) + return LZMA_PROG_ERROR; + + if (fe->props_encode == NULL) + return LZMA_OK; + + return fe->props_encode(filter->options, props); +} diff --git a/dependencies/cmliblzma/liblzma/common/filter_encoder.h b/dependencies/cmliblzma/liblzma/common/filter_encoder.h new file mode 100644 index 0000000..f1d5683 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/filter_encoder.h @@ -0,0 +1,27 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file filter_encoder.c +/// \brief Filter ID mapping to filter-specific functions +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_FILTER_ENCODER_H +#define LZMA_FILTER_ENCODER_H + +#include "common.h" + + +// FIXME: Might become a part of the public API. +extern uint64_t lzma_mt_block_size(const lzma_filter *filters); + + +extern lzma_ret lzma_raw_encoder_init( + lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter *filters); + +#endif diff --git a/dependencies/cmliblzma/liblzma/common/filter_flags_decoder.c b/dependencies/cmliblzma/liblzma/common/filter_flags_decoder.c new file mode 100644 index 0000000..ddfb085 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/filter_flags_decoder.c @@ -0,0 +1,46 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file filter_flags_decoder.c +/// \brief Decodes a Filter Flags field +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "filter_decoder.h" + + +extern LZMA_API(lzma_ret) +lzma_filter_flags_decode( + lzma_filter *filter, const lzma_allocator *allocator, + const uint8_t *in, size_t *in_pos, size_t in_size) +{ + // Set the pointer to NULL so the caller can always safely free it. + filter->options = NULL; + + // Filter ID + return_if_error(lzma_vli_decode(&filter->id, NULL, + in, in_pos, in_size)); + + if (filter->id >= LZMA_FILTER_RESERVED_START) + return LZMA_DATA_ERROR; + + // Size of Properties + lzma_vli props_size; + return_if_error(lzma_vli_decode(&props_size, NULL, + in, in_pos, in_size)); + + // Filter Properties + if (in_size - *in_pos < props_size) + return LZMA_DATA_ERROR; + + const lzma_ret ret = lzma_properties_decode( + filter, allocator, in + *in_pos, props_size); + + *in_pos += props_size; + + return ret; +} diff --git a/dependencies/cmliblzma/liblzma/common/filter_flags_encoder.c b/dependencies/cmliblzma/liblzma/common/filter_flags_encoder.c new file mode 100644 index 0000000..d110566 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/filter_flags_encoder.c @@ -0,0 +1,56 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file filter_flags_encoder.c +/// \brief Decodes a Filter Flags field +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "filter_encoder.h" + + +extern LZMA_API(lzma_ret) +lzma_filter_flags_size(uint32_t *size, const lzma_filter *filter) +{ + if (filter->id >= LZMA_FILTER_RESERVED_START) + return LZMA_PROG_ERROR; + + return_if_error(lzma_properties_size(size, filter)); + + *size += lzma_vli_size(filter->id) + lzma_vli_size(*size); + + return LZMA_OK; +} + + +extern LZMA_API(lzma_ret) +lzma_filter_flags_encode(const lzma_filter *filter, + uint8_t *out, size_t *out_pos, size_t out_size) +{ + // Filter ID + if (filter->id >= LZMA_FILTER_RESERVED_START) + return LZMA_PROG_ERROR; + + return_if_error(lzma_vli_encode(filter->id, NULL, + out, out_pos, out_size)); + + // Size of Properties + uint32_t props_size; + return_if_error(lzma_properties_size(&props_size, filter)); + return_if_error(lzma_vli_encode(props_size, NULL, + out, out_pos, out_size)); + + // Filter Properties + if (out_size - *out_pos < props_size) + return LZMA_PROG_ERROR; + + return_if_error(lzma_properties_encode(filter, out + *out_pos)); + + *out_pos += props_size; + + return LZMA_OK; +} diff --git a/dependencies/cmliblzma/liblzma/common/hardware_cputhreads.c b/dependencies/cmliblzma/liblzma/common/hardware_cputhreads.c new file mode 100644 index 0000000..f468366 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/hardware_cputhreads.c @@ -0,0 +1,22 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file hardware_cputhreads.c +/// \brief Get the number of CPU threads or cores +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "common.h" + +#include "tuklib_cpucores.h" + + +extern LZMA_API(uint32_t) +lzma_cputhreads(void) +{ + return tuklib_cpucores(); +} diff --git a/dependencies/cmliblzma/liblzma/common/hardware_physmem.c b/dependencies/cmliblzma/liblzma/common/hardware_physmem.c new file mode 100644 index 0000000..7405b65 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/hardware_physmem.c @@ -0,0 +1,25 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file hardware_physmem.c +/// \brief Get the total amount of physical memory (RAM) +// +// Author: Jonathan Nieder +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "common.h" + +#include "tuklib_physmem.h" + + +extern LZMA_API(uint64_t) +lzma_physmem(void) +{ + // It is simpler to make lzma_physmem() a wrapper for + // tuklib_physmem() than to hack appropriate symbol visiblity + // support for the tuklib modules. + return tuklib_physmem(); +} diff --git a/dependencies/cmliblzma/liblzma/common/index.c b/dependencies/cmliblzma/liblzma/common/index.c new file mode 100644 index 0000000..26e4e51 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/index.c @@ -0,0 +1,1250 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file index.c +/// \brief Handling of .xz Indexes and some other Stream information +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "index.h" +#include "stream_flags_common.h" + + +/// \brief How many Records to allocate at once +/// +/// This should be big enough to avoid making lots of tiny allocations +/// but small enough to avoid too much unused memory at once. +#define INDEX_GROUP_SIZE 512 + + +/// \brief How many Records can be allocated at once at maximum +#define PREALLOC_MAX ((SIZE_MAX - sizeof(index_group)) / sizeof(index_record)) + + +/// \brief Base structure for index_stream and index_group structures +typedef struct index_tree_node_s index_tree_node; +struct index_tree_node_s { + /// Uncompressed start offset of this Stream (relative to the + /// beginning of the file) or Block (relative to the beginning + /// of the Stream) + lzma_vli uncompressed_base; + + /// Compressed start offset of this Stream or Block + lzma_vli compressed_base; + + index_tree_node *parent; + index_tree_node *left; + index_tree_node *right; +}; + + +/// \brief AVL tree to hold index_stream or index_group structures +typedef struct { + /// Root node + index_tree_node *root; + + /// Leftmost node. Since the tree will be filled sequentially, + /// this won't change after the first node has been added to + /// the tree. + index_tree_node *leftmost; + + /// The rightmost node in the tree. Since the tree is filled + /// sequentially, this is always the node where to add the new data. + index_tree_node *rightmost; + + /// Number of nodes in the tree + uint32_t count; + +} index_tree; + + +typedef struct { + lzma_vli uncompressed_sum; + lzma_vli unpadded_sum; +} index_record; + + +typedef struct { + /// Every Record group is part of index_stream.groups tree. + index_tree_node node; + + /// Number of Blocks in this Stream before this group. + lzma_vli number_base; + + /// Number of Records that can be put in records[]. + size_t allocated; + + /// Index of the last Record in use. + size_t last; + + /// The sizes in this array are stored as cumulative sums relative + /// to the beginning of the Stream. This makes it possible to + /// use binary search in lzma_index_locate(). + /// + /// Note that the cumulative summing is done specially for + /// unpadded_sum: The previous value is rounded up to the next + /// multiple of four before adding the Unpadded Size of the new + /// Block. The total encoded size of the Blocks in the Stream + /// is records[last].unpadded_sum in the last Record group of + /// the Stream. + /// + /// For example, if the Unpadded Sizes are 39, 57, and 81, the + /// stored values are 39, 97 (40 + 57), and 181 (100 + 181). + /// The total encoded size of these Blocks is 184. + /// + /// This is a flexible array, because it makes easy to optimize + /// memory usage in case someone concatenates many Streams that + /// have only one or few Blocks. + index_record records[]; + +} index_group; + + +typedef struct { + /// Every index_stream is a node in the tree of Sreams. + index_tree_node node; + + /// Number of this Stream (first one is 1) + uint32_t number; + + /// Total number of Blocks before this Stream + lzma_vli block_number_base; + + /// Record groups of this Stream are stored in a tree. + /// It's a T-tree with AVL-tree balancing. There are + /// INDEX_GROUP_SIZE Records per node by default. + /// This keeps the number of memory allocations reasonable + /// and finding a Record is fast. + index_tree groups; + + /// Number of Records in this Stream + lzma_vli record_count; + + /// Size of the List of Records field in this Stream. This is used + /// together with record_count to calculate the size of the Index + /// field and thus the total size of the Stream. + lzma_vli index_list_size; + + /// Stream Flags of this Stream. This is meaningful only if + /// the Stream Flags have been told us with lzma_index_stream_flags(). + /// Initially stream_flags.version is set to UINT32_MAX to indicate + /// that the Stream Flags are unknown. + lzma_stream_flags stream_flags; + + /// Amount of Stream Padding after this Stream. This defaults to + /// zero and can be set with lzma_index_stream_padding(). + lzma_vli stream_padding; + +} index_stream; + + +struct lzma_index_s { + /// AVL-tree containing the Stream(s). Often there is just one + /// Stream, but using a tree keeps lookups fast even when there + /// are many concatenated Streams. + index_tree streams; + + /// Uncompressed size of all the Blocks in the Stream(s) + lzma_vli uncompressed_size; + + /// Total size of all the Blocks in the Stream(s) + lzma_vli total_size; + + /// Total number of Records in all Streams in this lzma_index + lzma_vli record_count; + + /// Size of the List of Records field if all the Streams in this + /// lzma_index were packed into a single Stream (makes it simpler to + /// take many .xz files and combine them into a single Stream). + /// + /// This value together with record_count is needed to calculate + /// Backward Size that is stored into Stream Footer. + lzma_vli index_list_size; + + /// How many Records to allocate at once in lzma_index_append(). + /// This defaults to INDEX_GROUP_SIZE but can be overriden with + /// lzma_index_prealloc(). + size_t prealloc; + + /// Bitmask indicating what integrity check types have been used + /// as set by lzma_index_stream_flags(). The bit of the last Stream + /// is not included here, since it is possible to change it by + /// calling lzma_index_stream_flags() again. + uint32_t checks; +}; + + +static void +index_tree_init(index_tree *tree) +{ + tree->root = NULL; + tree->leftmost = NULL; + tree->rightmost = NULL; + tree->count = 0; + return; +} + + +/// Helper for index_tree_end() +static void +index_tree_node_end(index_tree_node *node, const lzma_allocator *allocator, + void (*free_func)(void *node, const lzma_allocator *allocator)) +{ + // The tree won't ever be very huge, so recursion should be fine. + // 20 levels in the tree is likely quite a lot already in practice. + if (node->left != NULL) + index_tree_node_end(node->left, allocator, free_func); + + if (node->right != NULL) + index_tree_node_end(node->right, allocator, free_func); + + free_func(node, allocator); + return; +} + + +/// Free the memory allocated for a tree. Each node is freed using the +/// given free_func which is either &lzma_free or &index_stream_end. +/// The latter is used to free the Record groups from each index_stream +/// before freeing the index_stream itself. +static void +index_tree_end(index_tree *tree, const lzma_allocator *allocator, + void (*free_func)(void *node, const lzma_allocator *allocator)) +{ + assert(free_func != NULL); + + if (tree->root != NULL) + index_tree_node_end(tree->root, allocator, free_func); + + return; +} + + +/// Add a new node to the tree. node->uncompressed_base and +/// node->compressed_base must have been set by the caller already. +static void +index_tree_append(index_tree *tree, index_tree_node *node) +{ + node->parent = tree->rightmost; + node->left = NULL; + node->right = NULL; + + ++tree->count; + + // Handle the special case of adding the first node. + if (tree->root == NULL) { + tree->root = node; + tree->leftmost = node; + tree->rightmost = node; + return; + } + + // The tree is always filled sequentially. + assert(tree->rightmost->uncompressed_base <= node->uncompressed_base); + assert(tree->rightmost->compressed_base < node->compressed_base); + + // Add the new node after the rightmost node. It's the correct + // place due to the reason above. + tree->rightmost->right = node; + tree->rightmost = node; + + // Balance the AVL-tree if needed. We don't need to keep the balance + // factors in nodes, because we always fill the tree sequentially, + // and thus know the state of the tree just by looking at the node + // count. From the node count we can calculate how many steps to go + // up in the tree to find the rotation root. + uint32_t up = tree->count ^ (UINT32_C(1) << bsr32(tree->count)); + if (up != 0) { + // Locate the root node for the rotation. + up = ctz32(tree->count) + 2; + do { + node = node->parent; + } while (--up > 0); + + // Rotate left using node as the rotation root. + index_tree_node *pivot = node->right; + + if (node->parent == NULL) { + tree->root = pivot; + } else { + assert(node->parent->right == node); + node->parent->right = pivot; + } + + pivot->parent = node->parent; + + node->right = pivot->left; + if (node->right != NULL) + node->right->parent = node; + + pivot->left = node; + node->parent = pivot; + } + + return; +} + + +/// Get the next node in the tree. Return NULL if there are no more nodes. +static void * +index_tree_next(const index_tree_node *node) +{ + if (node->right != NULL) { + node = node->right; + while (node->left != NULL) + node = node->left; + + return (void *)(node); + } + + while (node->parent != NULL && node->parent->right == node) + node = node->parent; + + return (void *)(node->parent); +} + + +/// Locate a node that contains the given uncompressed offset. It is +/// caller's job to check that target is not bigger than the uncompressed +/// size of the tree (the last node would be returned in that case still). +static void * +index_tree_locate(const index_tree *tree, lzma_vli target) +{ + const index_tree_node *result = NULL; + const index_tree_node *node = tree->root; + + assert(tree->leftmost == NULL + || tree->leftmost->uncompressed_base == 0); + + // Consecutive nodes may have the same uncompressed_base. + // We must pick the rightmost one. + while (node != NULL) { + if (node->uncompressed_base > target) { + node = node->left; + } else { + result = node; + node = node->right; + } + } + + return (void *)(result); +} + + +/// Allocate and initialize a new Stream using the given base offsets. +static index_stream * +index_stream_init(lzma_vli compressed_base, lzma_vli uncompressed_base, + uint32_t stream_number, lzma_vli block_number_base, + const lzma_allocator *allocator) +{ + index_stream *s = lzma_alloc(sizeof(index_stream), allocator); + if (s == NULL) + return NULL; + + s->node.uncompressed_base = uncompressed_base; + s->node.compressed_base = compressed_base; + s->node.parent = NULL; + s->node.left = NULL; + s->node.right = NULL; + + s->number = stream_number; + s->block_number_base = block_number_base; + + index_tree_init(&s->groups); + + s->record_count = 0; + s->index_list_size = 0; + s->stream_flags.version = UINT32_MAX; + s->stream_padding = 0; + + return s; +} + + +/// Free the memory allocated for a Stream and its Record groups. +static void +index_stream_end(void *node, const lzma_allocator *allocator) +{ + index_stream *s = node; + index_tree_end(&s->groups, allocator, &lzma_free); + lzma_free(s, allocator); + return; +} + + +static lzma_index * +index_init_plain(const lzma_allocator *allocator) +{ + lzma_index *i = lzma_alloc(sizeof(lzma_index), allocator); + if (i != NULL) { + index_tree_init(&i->streams); + i->uncompressed_size = 0; + i->total_size = 0; + i->record_count = 0; + i->index_list_size = 0; + i->prealloc = INDEX_GROUP_SIZE; + i->checks = 0; + } + + return i; +} + + +extern LZMA_API(lzma_index *) +lzma_index_init(const lzma_allocator *allocator) +{ + lzma_index *i = index_init_plain(allocator); + if (i == NULL) + return NULL; + + index_stream *s = index_stream_init(0, 0, 1, 0, allocator); + if (s == NULL) { + lzma_free(i, allocator); + return NULL; + } + + index_tree_append(&i->streams, &s->node); + + return i; +} + + +extern LZMA_API(void) +lzma_index_end(lzma_index *i, const lzma_allocator *allocator) +{ + // NOTE: If you modify this function, check also the bottom + // of lzma_index_cat(). + if (i != NULL) { + index_tree_end(&i->streams, allocator, &index_stream_end); + lzma_free(i, allocator); + } + + return; +} + + +extern void +lzma_index_prealloc(lzma_index *i, lzma_vli records) +{ + if (records > PREALLOC_MAX) + records = PREALLOC_MAX; + + i->prealloc = (size_t)(records); + return; +} + + +extern LZMA_API(uint64_t) +lzma_index_memusage(lzma_vli streams, lzma_vli blocks) +{ + // This calculates an upper bound that is only a little bit + // bigger than the exact maximum memory usage with the given + // parameters. + + // Typical malloc() overhead is 2 * sizeof(void *) but we take + // a little bit extra just in case. Using LZMA_MEMUSAGE_BASE + // instead would give too inaccurate estimate. + const size_t alloc_overhead = 4 * sizeof(void *); + + // Amount of memory needed for each Stream base structures. + // We assume that every Stream has at least one Block and + // thus at least one group. + const size_t stream_base = sizeof(index_stream) + + sizeof(index_group) + 2 * alloc_overhead; + + // Amount of memory needed per group. + const size_t group_base = sizeof(index_group) + + INDEX_GROUP_SIZE * sizeof(index_record) + + alloc_overhead; + + // Number of groups. There may actually be more, but that overhead + // has been taken into account in stream_base already. + const lzma_vli groups + = (blocks + INDEX_GROUP_SIZE - 1) / INDEX_GROUP_SIZE; + + // Memory used by index_stream and index_group structures. + const uint64_t streams_mem = streams * stream_base; + const uint64_t groups_mem = groups * group_base; + + // Memory used by the base structure. + const uint64_t index_base = sizeof(lzma_index) + alloc_overhead; + + // Validate the arguments and catch integer overflows. + // Maximum number of Streams is "only" UINT32_MAX, because + // that limit is used by the tree containing the Streams. + const uint64_t limit = UINT64_MAX - index_base; + if (streams == 0 || streams > UINT32_MAX || blocks > LZMA_VLI_MAX + || streams > limit / stream_base + || groups > limit / group_base + || limit - streams_mem < groups_mem) + return UINT64_MAX; + + return index_base + streams_mem + groups_mem; +} + + +extern LZMA_API(uint64_t) +lzma_index_memused(const lzma_index *i) +{ + return lzma_index_memusage(i->streams.count, i->record_count); +} + + +extern LZMA_API(lzma_vli) +lzma_index_block_count(const lzma_index *i) +{ + return i->record_count; +} + + +extern LZMA_API(lzma_vli) +lzma_index_stream_count(const lzma_index *i) +{ + return i->streams.count; +} + + +extern LZMA_API(lzma_vli) +lzma_index_size(const lzma_index *i) +{ + return index_size(i->record_count, i->index_list_size); +} + + +extern LZMA_API(lzma_vli) +lzma_index_total_size(const lzma_index *i) +{ + return i->total_size; +} + + +extern LZMA_API(lzma_vli) +lzma_index_stream_size(const lzma_index *i) +{ + // Stream Header + Blocks + Index + Stream Footer + return LZMA_STREAM_HEADER_SIZE + i->total_size + + index_size(i->record_count, i->index_list_size) + + LZMA_STREAM_HEADER_SIZE; +} + + +static lzma_vli +index_file_size(lzma_vli compressed_base, lzma_vli unpadded_sum, + lzma_vli record_count, lzma_vli index_list_size, + lzma_vli stream_padding) +{ + // Earlier Streams and Stream Paddings + Stream Header + // + Blocks + Index + Stream Footer + Stream Padding + // + // This might go over LZMA_VLI_MAX due to too big unpadded_sum + // when this function is used in lzma_index_append(). + lzma_vli file_size = compressed_base + 2 * LZMA_STREAM_HEADER_SIZE + + stream_padding + vli_ceil4(unpadded_sum); + if (file_size > LZMA_VLI_MAX) + return LZMA_VLI_UNKNOWN; + + // The same applies here. + file_size += index_size(record_count, index_list_size); + if (file_size > LZMA_VLI_MAX) + return LZMA_VLI_UNKNOWN; + + return file_size; +} + + +extern LZMA_API(lzma_vli) +lzma_index_file_size(const lzma_index *i) +{ + const index_stream *s = (const index_stream *)(i->streams.rightmost); + const index_group *g = (const index_group *)(s->groups.rightmost); + return index_file_size(s->node.compressed_base, + g == NULL ? 0 : g->records[g->last].unpadded_sum, + s->record_count, s->index_list_size, + s->stream_padding); +} + + +extern LZMA_API(lzma_vli) +lzma_index_uncompressed_size(const lzma_index *i) +{ + return i->uncompressed_size; +} + + +extern LZMA_API(uint32_t) +lzma_index_checks(const lzma_index *i) +{ + uint32_t checks = i->checks; + + // Get the type of the Check of the last Stream too. + const index_stream *s = (const index_stream *)(i->streams.rightmost); + if (s->stream_flags.version != UINT32_MAX) + checks |= UINT32_C(1) << s->stream_flags.check; + + return checks; +} + + +extern uint32_t +lzma_index_padding_size(const lzma_index *i) +{ + return (LZMA_VLI_C(4) - index_size_unpadded( + i->record_count, i->index_list_size)) & 3; +} + + +extern LZMA_API(lzma_ret) +lzma_index_stream_flags(lzma_index *i, const lzma_stream_flags *stream_flags) +{ + if (i == NULL || stream_flags == NULL) + return LZMA_PROG_ERROR; + + // Validate the Stream Flags. + return_if_error(lzma_stream_flags_compare( + stream_flags, stream_flags)); + + index_stream *s = (index_stream *)(i->streams.rightmost); + s->stream_flags = *stream_flags; + + return LZMA_OK; +} + + +extern LZMA_API(lzma_ret) +lzma_index_stream_padding(lzma_index *i, lzma_vli stream_padding) +{ + if (i == NULL || stream_padding > LZMA_VLI_MAX + || (stream_padding & 3) != 0) + return LZMA_PROG_ERROR; + + index_stream *s = (index_stream *)(i->streams.rightmost); + + // Check that the new value won't make the file grow too big. + const lzma_vli old_stream_padding = s->stream_padding; + s->stream_padding = 0; + if (lzma_index_file_size(i) + stream_padding > LZMA_VLI_MAX) { + s->stream_padding = old_stream_padding; + return LZMA_DATA_ERROR; + } + + s->stream_padding = stream_padding; + return LZMA_OK; +} + + +extern LZMA_API(lzma_ret) +lzma_index_append(lzma_index *i, const lzma_allocator *allocator, + lzma_vli unpadded_size, lzma_vli uncompressed_size) +{ + // Validate. + if (i == NULL || unpadded_size < UNPADDED_SIZE_MIN + || unpadded_size > UNPADDED_SIZE_MAX + || uncompressed_size > LZMA_VLI_MAX) + return LZMA_PROG_ERROR; + + index_stream *s = (index_stream *)(i->streams.rightmost); + index_group *g = (index_group *)(s->groups.rightmost); + + const lzma_vli compressed_base = g == NULL ? 0 + : vli_ceil4(g->records[g->last].unpadded_sum); + const lzma_vli uncompressed_base = g == NULL ? 0 + : g->records[g->last].uncompressed_sum; + const uint32_t index_list_size_add = lzma_vli_size(unpadded_size) + + lzma_vli_size(uncompressed_size); + + // Check that the file size will stay within limits. + if (index_file_size(s->node.compressed_base, + compressed_base + unpadded_size, s->record_count + 1, + s->index_list_size + index_list_size_add, + s->stream_padding) == LZMA_VLI_UNKNOWN) + return LZMA_DATA_ERROR; + + // The size of the Index field must not exceed the maximum value + // that can be stored in the Backward Size field. + if (index_size(i->record_count + 1, + i->index_list_size + index_list_size_add) + > LZMA_BACKWARD_SIZE_MAX) + return LZMA_DATA_ERROR; + + if (g != NULL && g->last + 1 < g->allocated) { + // There is space in the last group at least for one Record. + ++g->last; + } else { + // We need to allocate a new group. + g = lzma_alloc(sizeof(index_group) + + i->prealloc * sizeof(index_record), + allocator); + if (g == NULL) + return LZMA_MEM_ERROR; + + g->last = 0; + g->allocated = i->prealloc; + + // Reset prealloc so that if the application happens to + // add new Records, the allocation size will be sane. + i->prealloc = INDEX_GROUP_SIZE; + + // Set the start offsets of this group. + g->node.uncompressed_base = uncompressed_base; + g->node.compressed_base = compressed_base; + g->number_base = s->record_count + 1; + + // Add the new group to the Stream. + index_tree_append(&s->groups, &g->node); + } + + // Add the new Record to the group. + g->records[g->last].uncompressed_sum + = uncompressed_base + uncompressed_size; + g->records[g->last].unpadded_sum + = compressed_base + unpadded_size; + + // Update the totals. + ++s->record_count; + s->index_list_size += index_list_size_add; + + i->total_size += vli_ceil4(unpadded_size); + i->uncompressed_size += uncompressed_size; + ++i->record_count; + i->index_list_size += index_list_size_add; + + return LZMA_OK; +} + + +/// Structure to pass info to index_cat_helper() +typedef struct { + /// Uncompressed size of the destination + lzma_vli uncompressed_size; + + /// Compressed file size of the destination + lzma_vli file_size; + + /// Same as above but for Block numbers + lzma_vli block_number_add; + + /// Number of Streams that were in the destination index before we + /// started appending new Streams from the source index. This is + /// used to fix the Stream numbering. + uint32_t stream_number_add; + + /// Destination index' Stream tree + index_tree *streams; + +} index_cat_info; + + +/// Add the Stream nodes from the source index to dest using recursion. +/// Simplest iterative traversal of the source tree wouldn't work, because +/// we update the pointers in nodes when moving them to the destination tree. +static void +index_cat_helper(const index_cat_info *info, index_stream *this) +{ + index_stream *left = (index_stream *)(this->node.left); + index_stream *right = (index_stream *)(this->node.right); + + if (left != NULL) + index_cat_helper(info, left); + + this->node.uncompressed_base += info->uncompressed_size; + this->node.compressed_base += info->file_size; + this->number += info->stream_number_add; + this->block_number_base += info->block_number_add; + index_tree_append(info->streams, &this->node); + + if (right != NULL) + index_cat_helper(info, right); + + return; +} + + +extern LZMA_API(lzma_ret) +lzma_index_cat(lzma_index *restrict dest, lzma_index *restrict src, + const lzma_allocator *allocator) +{ + const lzma_vli dest_file_size = lzma_index_file_size(dest); + + // Check that we don't exceed the file size limits. + if (dest_file_size + lzma_index_file_size(src) > LZMA_VLI_MAX + || dest->uncompressed_size + src->uncompressed_size + > LZMA_VLI_MAX) + return LZMA_DATA_ERROR; + + // Check that the encoded size of the combined lzma_indexes stays + // within limits. In theory, this should be done only if we know + // that the user plans to actually combine the Streams and thus + // construct a single Index (probably rare). However, exceeding + // this limit is quite theoretical, so we do this check always + // to simplify things elsewhere. + { + const lzma_vli dest_size = index_size_unpadded( + dest->record_count, dest->index_list_size); + const lzma_vli src_size = index_size_unpadded( + src->record_count, src->index_list_size); + if (vli_ceil4(dest_size + src_size) > LZMA_BACKWARD_SIZE_MAX) + return LZMA_DATA_ERROR; + } + + // Optimize the last group to minimize memory usage. Allocation has + // to be done before modifying dest or src. + { + index_stream *s = (index_stream *)(dest->streams.rightmost); + index_group *g = (index_group *)(s->groups.rightmost); + if (g != NULL && g->last + 1 < g->allocated) { + assert(g->node.left == NULL); + assert(g->node.right == NULL); + + index_group *newg = lzma_alloc(sizeof(index_group) + + (g->last + 1) + * sizeof(index_record), + allocator); + if (newg == NULL) + return LZMA_MEM_ERROR; + + newg->node = g->node; + newg->allocated = g->last + 1; + newg->last = g->last; + newg->number_base = g->number_base; + + memcpy(newg->records, g->records, newg->allocated + * sizeof(index_record)); + + if (g->node.parent != NULL) { + assert(g->node.parent->right == &g->node); + g->node.parent->right = &newg->node; + } + + if (s->groups.leftmost == &g->node) { + assert(s->groups.root == &g->node); + s->groups.leftmost = &newg->node; + s->groups.root = &newg->node; + } + + if (s->groups.rightmost == &g->node) + s->groups.rightmost = &newg->node; + + lzma_free(g, allocator); + + // NOTE: newg isn't leaked here because + // newg == (void *)&newg->node. + } + } + + // Add all the Streams from src to dest. Update the base offsets + // of each Stream from src. + const index_cat_info info = { + .uncompressed_size = dest->uncompressed_size, + .file_size = dest_file_size, + .stream_number_add = dest->streams.count, + .block_number_add = dest->record_count, + .streams = &dest->streams, + }; + index_cat_helper(&info, (index_stream *)(src->streams.root)); + + // Update info about all the combined Streams. + dest->uncompressed_size += src->uncompressed_size; + dest->total_size += src->total_size; + dest->record_count += src->record_count; + dest->index_list_size += src->index_list_size; + dest->checks = lzma_index_checks(dest) | src->checks; + + // There's nothing else left in src than the base structure. + lzma_free(src, allocator); + + return LZMA_OK; +} + + +/// Duplicate an index_stream. +static index_stream * +index_dup_stream(const index_stream *src, const lzma_allocator *allocator) +{ + // Catch a somewhat theoretical integer overflow. + if (src->record_count > PREALLOC_MAX) + return NULL; + + // Allocate and initialize a new Stream. + index_stream *dest = index_stream_init(src->node.compressed_base, + src->node.uncompressed_base, src->number, + src->block_number_base, allocator); + if (dest == NULL) + return NULL; + + // Copy the overall information. + dest->record_count = src->record_count; + dest->index_list_size = src->index_list_size; + dest->stream_flags = src->stream_flags; + dest->stream_padding = src->stream_padding; + + // Return if there are no groups to duplicate. + if (src->groups.leftmost == NULL) + return dest; + + // Allocate memory for the Records. We put all the Records into + // a single group. It's simplest and also tends to make + // lzma_index_locate() a little bit faster with very big Indexes. + index_group *destg = lzma_alloc(sizeof(index_group) + + src->record_count * sizeof(index_record), + allocator); + if (destg == NULL) { + index_stream_end(dest, allocator); + return NULL; + } + + // Initialize destg. + destg->node.uncompressed_base = 0; + destg->node.compressed_base = 0; + destg->number_base = 1; + destg->allocated = src->record_count; + destg->last = src->record_count - 1; + + // Go through all the groups in src and copy the Records into destg. + const index_group *srcg = (const index_group *)(src->groups.leftmost); + size_t i = 0; + do { + memcpy(destg->records + i, srcg->records, + (srcg->last + 1) * sizeof(index_record)); + i += srcg->last + 1; + srcg = index_tree_next(&srcg->node); + } while (srcg != NULL); + + assert(i == destg->allocated); + + // Add the group to the new Stream. + index_tree_append(&dest->groups, &destg->node); + + return dest; +} + + +extern LZMA_API(lzma_index *) +lzma_index_dup(const lzma_index *src, const lzma_allocator *allocator) +{ + // Allocate the base structure (no initial Stream). + lzma_index *dest = index_init_plain(allocator); + if (dest == NULL) + return NULL; + + // Copy the totals. + dest->uncompressed_size = src->uncompressed_size; + dest->total_size = src->total_size; + dest->record_count = src->record_count; + dest->index_list_size = src->index_list_size; + + // Copy the Streams and the groups in them. + const index_stream *srcstream + = (const index_stream *)(src->streams.leftmost); + do { + index_stream *deststream = index_dup_stream( + srcstream, allocator); + if (deststream == NULL) { + lzma_index_end(dest, allocator); + return NULL; + } + + index_tree_append(&dest->streams, &deststream->node); + + srcstream = index_tree_next(&srcstream->node); + } while (srcstream != NULL); + + return dest; +} + + +/// Indexing for lzma_index_iter.internal[] +enum { + ITER_INDEX, + ITER_STREAM, + ITER_GROUP, + ITER_RECORD, + ITER_METHOD, +}; + + +/// Values for lzma_index_iter.internal[ITER_METHOD].s +enum { + ITER_METHOD_NORMAL, + ITER_METHOD_NEXT, + ITER_METHOD_LEFTMOST, +}; + + +static void +iter_set_info(lzma_index_iter *iter) +{ + const lzma_index *i = iter->internal[ITER_INDEX].p; + const index_stream *stream = iter->internal[ITER_STREAM].p; + const index_group *group = iter->internal[ITER_GROUP].p; + const size_t record = iter->internal[ITER_RECORD].s; + + // lzma_index_iter.internal must not contain a pointer to the last + // group in the index, because that may be reallocated by + // lzma_index_cat(). + if (group == NULL) { + // There are no groups. + assert(stream->groups.root == NULL); + iter->internal[ITER_METHOD].s = ITER_METHOD_LEFTMOST; + + } else if (i->streams.rightmost != &stream->node + || stream->groups.rightmost != &group->node) { + // The group is not not the last group in the index. + iter->internal[ITER_METHOD].s = ITER_METHOD_NORMAL; + + } else if (stream->groups.leftmost != &group->node) { + // The group isn't the only group in the Stream, thus we + // know that it must have a parent group i.e. it's not + // the root node. + assert(stream->groups.root != &group->node); + assert(group->node.parent->right == &group->node); + iter->internal[ITER_METHOD].s = ITER_METHOD_NEXT; + iter->internal[ITER_GROUP].p = group->node.parent; + + } else { + // The Stream has only one group. + assert(stream->groups.root == &group->node); + assert(group->node.parent == NULL); + iter->internal[ITER_METHOD].s = ITER_METHOD_LEFTMOST; + iter->internal[ITER_GROUP].p = NULL; + } + + // NOTE: lzma_index_iter.stream.number is lzma_vli but we use uint32_t + // internally. + iter->stream.number = stream->number; + iter->stream.block_count = stream->record_count; + iter->stream.compressed_offset = stream->node.compressed_base; + iter->stream.uncompressed_offset = stream->node.uncompressed_base; + + // iter->stream.flags will be NULL if the Stream Flags haven't been + // set with lzma_index_stream_flags(). + iter->stream.flags = stream->stream_flags.version == UINT32_MAX + ? NULL : &stream->stream_flags; + iter->stream.padding = stream->stream_padding; + + if (stream->groups.rightmost == NULL) { + // Stream has no Blocks. + iter->stream.compressed_size = index_size(0, 0) + + 2 * LZMA_STREAM_HEADER_SIZE; + iter->stream.uncompressed_size = 0; + } else { + const index_group *g = (const index_group *)( + stream->groups.rightmost); + + // Stream Header + Stream Footer + Index + Blocks + iter->stream.compressed_size = 2 * LZMA_STREAM_HEADER_SIZE + + index_size(stream->record_count, + stream->index_list_size) + + vli_ceil4(g->records[g->last].unpadded_sum); + iter->stream.uncompressed_size + = g->records[g->last].uncompressed_sum; + } + + if (group != NULL) { + iter->block.number_in_stream = group->number_base + record; + iter->block.number_in_file = iter->block.number_in_stream + + stream->block_number_base; + + iter->block.compressed_stream_offset + = record == 0 ? group->node.compressed_base + : vli_ceil4(group->records[ + record - 1].unpadded_sum); + iter->block.uncompressed_stream_offset + = record == 0 ? group->node.uncompressed_base + : group->records[record - 1].uncompressed_sum; + + iter->block.uncompressed_size + = group->records[record].uncompressed_sum + - iter->block.uncompressed_stream_offset; + iter->block.unpadded_size + = group->records[record].unpadded_sum + - iter->block.compressed_stream_offset; + iter->block.total_size = vli_ceil4(iter->block.unpadded_size); + + iter->block.compressed_stream_offset + += LZMA_STREAM_HEADER_SIZE; + + iter->block.compressed_file_offset + = iter->block.compressed_stream_offset + + iter->stream.compressed_offset; + iter->block.uncompressed_file_offset + = iter->block.uncompressed_stream_offset + + iter->stream.uncompressed_offset; + } + + return; +} + + +extern LZMA_API(void) +lzma_index_iter_init(lzma_index_iter *iter, const lzma_index *i) +{ + iter->internal[ITER_INDEX].p = i; + lzma_index_iter_rewind(iter); + return; +} + + +extern LZMA_API(void) +lzma_index_iter_rewind(lzma_index_iter *iter) +{ + iter->internal[ITER_STREAM].p = NULL; + iter->internal[ITER_GROUP].p = NULL; + iter->internal[ITER_RECORD].s = 0; + iter->internal[ITER_METHOD].s = ITER_METHOD_NORMAL; + return; +} + + +extern LZMA_API(lzma_bool) +lzma_index_iter_next(lzma_index_iter *iter, lzma_index_iter_mode mode) +{ + // Catch unsupported mode values. + if ((unsigned int)(mode) > LZMA_INDEX_ITER_NONEMPTY_BLOCK) + return true; + + const lzma_index *i = iter->internal[ITER_INDEX].p; + const index_stream *stream = iter->internal[ITER_STREAM].p; + const index_group *group = NULL; + size_t record = iter->internal[ITER_RECORD].s; + + // If we are being asked for the next Stream, leave group to NULL + // so that the rest of the this function thinks that this Stream + // has no groups and will thus go to the next Stream. + if (mode != LZMA_INDEX_ITER_STREAM) { + // Get the pointer to the current group. See iter_set_inf() + // for explanation. + switch (iter->internal[ITER_METHOD].s) { + case ITER_METHOD_NORMAL: + group = iter->internal[ITER_GROUP].p; + break; + + case ITER_METHOD_NEXT: + group = index_tree_next(iter->internal[ITER_GROUP].p); + break; + + case ITER_METHOD_LEFTMOST: + group = (const index_group *)( + stream->groups.leftmost); + break; + } + } + +again: + if (stream == NULL) { + // We at the beginning of the lzma_index. + // Locate the first Stream. + stream = (const index_stream *)(i->streams.leftmost); + if (mode >= LZMA_INDEX_ITER_BLOCK) { + // Since we are being asked to return information + // about the first a Block, skip Streams that have + // no Blocks. + while (stream->groups.leftmost == NULL) { + stream = index_tree_next(&stream->node); + if (stream == NULL) + return true; + } + } + + // Start from the first Record in the Stream. + group = (const index_group *)(stream->groups.leftmost); + record = 0; + + } else if (group != NULL && record < group->last) { + // The next Record is in the same group. + ++record; + + } else { + // This group has no more Records or this Stream has + // no Blocks at all. + record = 0; + + // If group is not NULL, this Stream has at least one Block + // and thus at least one group. Find the next group. + if (group != NULL) + group = index_tree_next(&group->node); + + if (group == NULL) { + // This Stream has no more Records. Find the next + // Stream. If we are being asked to return information + // about a Block, we skip empty Streams. + do { + stream = index_tree_next(&stream->node); + if (stream == NULL) + return true; + } while (mode >= LZMA_INDEX_ITER_BLOCK + && stream->groups.leftmost == NULL); + + group = (const index_group *)( + stream->groups.leftmost); + } + } + + if (mode == LZMA_INDEX_ITER_NONEMPTY_BLOCK) { + // We need to look for the next Block again if this Block + // is empty. + if (record == 0) { + if (group->node.uncompressed_base + == group->records[0].uncompressed_sum) + goto again; + } else if (group->records[record - 1].uncompressed_sum + == group->records[record].uncompressed_sum) { + goto again; + } + } + + iter->internal[ITER_STREAM].p = stream; + iter->internal[ITER_GROUP].p = group; + iter->internal[ITER_RECORD].s = record; + + iter_set_info(iter); + + return false; +} + + +extern LZMA_API(lzma_bool) +lzma_index_iter_locate(lzma_index_iter *iter, lzma_vli target) +{ + const lzma_index *i = iter->internal[ITER_INDEX].p; + + // If the target is past the end of the file, return immediately. + if (i->uncompressed_size <= target) + return true; + + // Locate the Stream containing the target offset. + const index_stream *stream = index_tree_locate(&i->streams, target); + assert(stream != NULL); + target -= stream->node.uncompressed_base; + + // Locate the group containing the target offset. + const index_group *group = index_tree_locate(&stream->groups, target); + assert(group != NULL); + + // Use binary search to locate the exact Record. It is the first + // Record whose uncompressed_sum is greater than target. + // This is because we want the rightmost Record that fullfills the + // search criterion. It is possible that there are empty Blocks; + // we don't want to return them. + size_t left = 0; + size_t right = group->last; + + while (left < right) { + const size_t pos = left + (right - left) / 2; + if (group->records[pos].uncompressed_sum <= target) + left = pos + 1; + else + right = pos; + } + + iter->internal[ITER_STREAM].p = stream; + iter->internal[ITER_GROUP].p = group; + iter->internal[ITER_RECORD].s = left; + + iter_set_info(iter); + + return false; +} diff --git a/dependencies/cmliblzma/liblzma/common/index.h b/dependencies/cmliblzma/liblzma/common/index.h new file mode 100644 index 0000000..64e9724 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/index.h @@ -0,0 +1,73 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file index.h +/// \brief Handling of Index +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_INDEX_H +#define LZMA_INDEX_H + +#include "common.h" + + +/// Minimum Unpadded Size +#define UNPADDED_SIZE_MIN LZMA_VLI_C(5) + +/// Maximum Unpadded Size +#define UNPADDED_SIZE_MAX (LZMA_VLI_MAX & ~LZMA_VLI_C(3)) + + +/// Get the size of the Index Padding field. This is needed by Index encoder +/// and decoder, but applications should have no use for this. +extern uint32_t lzma_index_padding_size(const lzma_index *i); + + +/// Set for how many Records to allocate memory the next time +/// lzma_index_append() needs to allocate space for a new Record. +/// This is used only by the Index decoder. +extern void lzma_index_prealloc(lzma_index *i, lzma_vli records); + + +/// Round the variable-length integer to the next multiple of four. +static inline lzma_vli +vli_ceil4(lzma_vli vli) +{ + assert(vli <= LZMA_VLI_MAX); + return (vli + 3) & ~LZMA_VLI_C(3); +} + + +/// Calculate the size of the Index field excluding Index Padding +static inline lzma_vli +index_size_unpadded(lzma_vli count, lzma_vli index_list_size) +{ + // Index Indicator + Number of Records + List of Records + CRC32 + return 1 + lzma_vli_size(count) + index_list_size + 4; +} + + +/// Calculate the size of the Index field including Index Padding +static inline lzma_vli +index_size(lzma_vli count, lzma_vli index_list_size) +{ + return vli_ceil4(index_size_unpadded(count, index_list_size)); +} + + +/// Calculate the total size of the Stream +static inline lzma_vli +index_stream_size(lzma_vli blocks_size, + lzma_vli count, lzma_vli index_list_size) +{ + return LZMA_STREAM_HEADER_SIZE + blocks_size + + index_size(count, index_list_size) + + LZMA_STREAM_HEADER_SIZE; +} + +#endif diff --git a/dependencies/cmliblzma/liblzma/common/index_decoder.c b/dependencies/cmliblzma/liblzma/common/index_decoder.c new file mode 100644 index 0000000..cc07a1b --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/index_decoder.c @@ -0,0 +1,352 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file index_decoder.c +/// \brief Decodes the Index field +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "index.h" +#include "check.h" + + +typedef struct { + enum { + SEQ_INDICATOR, + SEQ_COUNT, + SEQ_MEMUSAGE, + SEQ_UNPADDED, + SEQ_UNCOMPRESSED, + SEQ_PADDING_INIT, + SEQ_PADDING, + SEQ_CRC32, + } sequence; + + /// Memory usage limit + uint64_t memlimit; + + /// Target Index + lzma_index *index; + + /// Pointer give by the application, which is set after + /// successful decoding. + lzma_index **index_ptr; + + /// Number of Records left to decode. + lzma_vli count; + + /// The most recent Unpadded Size field + lzma_vli unpadded_size; + + /// The most recent Uncompressed Size field + lzma_vli uncompressed_size; + + /// Position in integers + size_t pos; + + /// CRC32 of the List of Records field + uint32_t crc32; +} lzma_index_coder; + + +static lzma_ret +index_decode(void *coder_ptr, const lzma_allocator *allocator, + const uint8_t *restrict in, size_t *restrict in_pos, + size_t in_size, + uint8_t *restrict out lzma_attribute((__unused__)), + size_t *restrict out_pos lzma_attribute((__unused__)), + size_t out_size lzma_attribute((__unused__)), + lzma_action action lzma_attribute((__unused__))) +{ + lzma_index_coder *coder = coder_ptr; + + // Similar optimization as in index_encoder.c + const size_t in_start = *in_pos; + lzma_ret ret = LZMA_OK; + + while (*in_pos < in_size) + switch (coder->sequence) { + case SEQ_INDICATOR: + // Return LZMA_DATA_ERROR instead of e.g. LZMA_PROG_ERROR or + // LZMA_FORMAT_ERROR, because a typical usage case for Index + // decoder is when parsing the Stream backwards. If seeking + // backward from the Stream Footer gives us something that + // doesn't begin with Index Indicator, the file is considered + // corrupt, not "programming error" or "unrecognized file + // format". One could argue that the application should + // verify the Index Indicator before trying to decode the + // Index, but well, I suppose it is simpler this way. + if (in[(*in_pos)++] != 0x00) + return LZMA_DATA_ERROR; + + coder->sequence = SEQ_COUNT; + break; + + case SEQ_COUNT: + ret = lzma_vli_decode(&coder->count, &coder->pos, + in, in_pos, in_size); + if (ret != LZMA_STREAM_END) + goto out; + + coder->pos = 0; + coder->sequence = SEQ_MEMUSAGE; + + // Fall through + + case SEQ_MEMUSAGE: + if (lzma_index_memusage(1, coder->count) > coder->memlimit) { + ret = LZMA_MEMLIMIT_ERROR; + goto out; + } + + // Tell the Index handling code how many Records this + // Index has to allow it to allocate memory more efficiently. + lzma_index_prealloc(coder->index, coder->count); + + ret = LZMA_OK; + coder->sequence = coder->count == 0 + ? SEQ_PADDING_INIT : SEQ_UNPADDED; + break; + + case SEQ_UNPADDED: + case SEQ_UNCOMPRESSED: { + lzma_vli *size = coder->sequence == SEQ_UNPADDED + ? &coder->unpadded_size + : &coder->uncompressed_size; + + ret = lzma_vli_decode(size, &coder->pos, + in, in_pos, in_size); + if (ret != LZMA_STREAM_END) + goto out; + + ret = LZMA_OK; + coder->pos = 0; + + if (coder->sequence == SEQ_UNPADDED) { + // Validate that encoded Unpadded Size isn't too small + // or too big. + if (coder->unpadded_size < UNPADDED_SIZE_MIN + || coder->unpadded_size + > UNPADDED_SIZE_MAX) + return LZMA_DATA_ERROR; + + coder->sequence = SEQ_UNCOMPRESSED; + } else { + // Add the decoded Record to the Index. + return_if_error(lzma_index_append( + coder->index, allocator, + coder->unpadded_size, + coder->uncompressed_size)); + + // Check if this was the last Record. + coder->sequence = --coder->count == 0 + ? SEQ_PADDING_INIT + : SEQ_UNPADDED; + } + + break; + } + + case SEQ_PADDING_INIT: + coder->pos = lzma_index_padding_size(coder->index); + coder->sequence = SEQ_PADDING; + + // Fall through + + case SEQ_PADDING: + if (coder->pos > 0) { + --coder->pos; + if (in[(*in_pos)++] != 0x00) + return LZMA_DATA_ERROR; + + break; + } + + // Finish the CRC32 calculation. + coder->crc32 = lzma_crc32(in + in_start, + *in_pos - in_start, coder->crc32); + + coder->sequence = SEQ_CRC32; + + // Fall through + + case SEQ_CRC32: + do { + if (*in_pos == in_size) + return LZMA_OK; + + if (((coder->crc32 >> (coder->pos * 8)) & 0xFF) + != in[(*in_pos)++]) + return LZMA_DATA_ERROR; + + } while (++coder->pos < 4); + + // Decoding was successful, now we can let the application + // see the decoded Index. + *coder->index_ptr = coder->index; + + // Make index NULL so we don't free it unintentionally. + coder->index = NULL; + + return LZMA_STREAM_END; + + default: + assert(0); + return LZMA_PROG_ERROR; + } + +out: + // Update the CRC32, + coder->crc32 = lzma_crc32(in + in_start, + *in_pos - in_start, coder->crc32); + + return ret; +} + + +static void +index_decoder_end(void *coder_ptr, const lzma_allocator *allocator) +{ + lzma_index_coder *coder = coder_ptr; + lzma_index_end(coder->index, allocator); + lzma_free(coder, allocator); + return; +} + + +static lzma_ret +index_decoder_memconfig(void *coder_ptr, uint64_t *memusage, + uint64_t *old_memlimit, uint64_t new_memlimit) +{ + lzma_index_coder *coder = coder_ptr; + + *memusage = lzma_index_memusage(1, coder->count); + *old_memlimit = coder->memlimit; + + if (new_memlimit != 0) { + if (new_memlimit < *memusage) + return LZMA_MEMLIMIT_ERROR; + + coder->memlimit = new_memlimit; + } + + return LZMA_OK; +} + + +static lzma_ret +index_decoder_reset(lzma_index_coder *coder, const lzma_allocator *allocator, + lzma_index **i, uint64_t memlimit) +{ + // Remember the pointer given by the application. We will set it + // to point to the decoded Index only if decoding is successful. + // Before that, keep it NULL so that applications can always safely + // pass it to lzma_index_end() no matter did decoding succeed or not. + coder->index_ptr = i; + *i = NULL; + + // We always allocate a new lzma_index. + coder->index = lzma_index_init(allocator); + if (coder->index == NULL) + return LZMA_MEM_ERROR; + + // Initialize the rest. + coder->sequence = SEQ_INDICATOR; + coder->memlimit = my_max(1, memlimit); + coder->count = 0; // Needs to be initialized due to _memconfig(). + coder->pos = 0; + coder->crc32 = 0; + + return LZMA_OK; +} + + +static lzma_ret +index_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator, + lzma_index **i, uint64_t memlimit) +{ + lzma_next_coder_init(&index_decoder_init, next, allocator); + + if (i == NULL) + return LZMA_PROG_ERROR; + + lzma_index_coder *coder = next->coder; + if (coder == NULL) { + coder = lzma_alloc(sizeof(lzma_index_coder), allocator); + if (coder == NULL) + return LZMA_MEM_ERROR; + + next->coder = coder; + next->code = &index_decode; + next->end = &index_decoder_end; + next->memconfig = &index_decoder_memconfig; + coder->index = NULL; + } else { + lzma_index_end(coder->index, allocator); + } + + return index_decoder_reset(coder, allocator, i, memlimit); +} + + +extern LZMA_API(lzma_ret) +lzma_index_decoder(lzma_stream *strm, lzma_index **i, uint64_t memlimit) +{ + lzma_next_strm_init(index_decoder_init, strm, i, memlimit); + + strm->internal->supported_actions[LZMA_RUN] = true; + strm->internal->supported_actions[LZMA_FINISH] = true; + + return LZMA_OK; +} + + +extern LZMA_API(lzma_ret) +lzma_index_buffer_decode(lzma_index **i, uint64_t *memlimit, + const lzma_allocator *allocator, + const uint8_t *in, size_t *in_pos, size_t in_size) +{ + // Sanity checks + if (i == NULL || memlimit == NULL + || in == NULL || in_pos == NULL || *in_pos > in_size) + return LZMA_PROG_ERROR; + + // Initialize the decoder. + lzma_index_coder coder; + return_if_error(index_decoder_reset(&coder, allocator, i, *memlimit)); + + // Store the input start position so that we can restore it in case + // of an error. + const size_t in_start = *in_pos; + + // Do the actual decoding. + lzma_ret ret = index_decode(&coder, allocator, in, in_pos, in_size, + NULL, NULL, 0, LZMA_RUN); + + if (ret == LZMA_STREAM_END) { + ret = LZMA_OK; + } else { + // Something went wrong, free the Index structure and restore + // the input position. + lzma_index_end(coder.index, allocator); + *in_pos = in_start; + + if (ret == LZMA_OK) { + // The input is truncated or otherwise corrupt. + // Use LZMA_DATA_ERROR instead of LZMA_BUF_ERROR + // like lzma_vli_decode() does in single-call mode. + ret = LZMA_DATA_ERROR; + + } else if (ret == LZMA_MEMLIMIT_ERROR) { + // Tell the caller how much memory would have + // been needed. + *memlimit = lzma_index_memusage(1, coder.count); + } + } + + return ret; +} diff --git a/dependencies/cmliblzma/liblzma/common/index_encoder.c b/dependencies/cmliblzma/liblzma/common/index_encoder.c new file mode 100644 index 0000000..ac97d0c --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/index_encoder.c @@ -0,0 +1,256 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file index_encoder.c +/// \brief Encodes the Index field +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "index_encoder.h" +#include "index.h" +#include "check.h" + + +typedef struct { + enum { + SEQ_INDICATOR, + SEQ_COUNT, + SEQ_UNPADDED, + SEQ_UNCOMPRESSED, + SEQ_NEXT, + SEQ_PADDING, + SEQ_CRC32, + } sequence; + + /// Index being encoded + const lzma_index *index; + + /// Iterator for the Index being encoded + lzma_index_iter iter; + + /// Position in integers + size_t pos; + + /// CRC32 of the List of Records field + uint32_t crc32; +} lzma_index_coder; + + +static lzma_ret +index_encode(void *coder_ptr, + const lzma_allocator *allocator lzma_attribute((__unused__)), + const uint8_t *restrict in lzma_attribute((__unused__)), + size_t *restrict in_pos lzma_attribute((__unused__)), + size_t in_size lzma_attribute((__unused__)), + uint8_t *restrict out, size_t *restrict out_pos, + size_t out_size, + lzma_action action lzma_attribute((__unused__))) +{ + lzma_index_coder *coder = coder_ptr; + + // Position where to start calculating CRC32. The idea is that we + // need to call lzma_crc32() only once per call to index_encode(). + const size_t out_start = *out_pos; + + // Return value to use if we return at the end of this function. + // We use "goto out" to jump out of the while-switch construct + // instead of returning directly, because that way we don't need + // to copypaste the lzma_crc32() call to many places. + lzma_ret ret = LZMA_OK; + + while (*out_pos < out_size) + switch (coder->sequence) { + case SEQ_INDICATOR: + out[*out_pos] = 0x00; + ++*out_pos; + coder->sequence = SEQ_COUNT; + break; + + case SEQ_COUNT: { + const lzma_vli count = lzma_index_block_count(coder->index); + ret = lzma_vli_encode(count, &coder->pos, + out, out_pos, out_size); + if (ret != LZMA_STREAM_END) + goto out; + + ret = LZMA_OK; + coder->pos = 0; + coder->sequence = SEQ_NEXT; + break; + } + + case SEQ_NEXT: + if (lzma_index_iter_next( + &coder->iter, LZMA_INDEX_ITER_BLOCK)) { + // Get the size of the Index Padding field. + coder->pos = lzma_index_padding_size(coder->index); + assert(coder->pos <= 3); + coder->sequence = SEQ_PADDING; + break; + } + + coder->sequence = SEQ_UNPADDED; + + // Fall through + + case SEQ_UNPADDED: + case SEQ_UNCOMPRESSED: { + const lzma_vli size = coder->sequence == SEQ_UNPADDED + ? coder->iter.block.unpadded_size + : coder->iter.block.uncompressed_size; + + ret = lzma_vli_encode(size, &coder->pos, + out, out_pos, out_size); + if (ret != LZMA_STREAM_END) + goto out; + + ret = LZMA_OK; + coder->pos = 0; + + // Advance to SEQ_UNCOMPRESSED or SEQ_NEXT. + ++coder->sequence; + break; + } + + case SEQ_PADDING: + if (coder->pos > 0) { + --coder->pos; + out[(*out_pos)++] = 0x00; + break; + } + + // Finish the CRC32 calculation. + coder->crc32 = lzma_crc32(out + out_start, + *out_pos - out_start, coder->crc32); + + coder->sequence = SEQ_CRC32; + + // Fall through + + case SEQ_CRC32: + // We don't use the main loop, because we don't want + // coder->crc32 to be touched anymore. + do { + if (*out_pos == out_size) + return LZMA_OK; + + out[*out_pos] = (coder->crc32 >> (coder->pos * 8)) + & 0xFF; + ++*out_pos; + + } while (++coder->pos < 4); + + return LZMA_STREAM_END; + + default: + assert(0); + return LZMA_PROG_ERROR; + } + +out: + // Update the CRC32. + coder->crc32 = lzma_crc32(out + out_start, + *out_pos - out_start, coder->crc32); + + return ret; +} + + +static void +index_encoder_end(void *coder, const lzma_allocator *allocator) +{ + lzma_free(coder, allocator); + return; +} + + +static void +index_encoder_reset(lzma_index_coder *coder, const lzma_index *i) +{ + lzma_index_iter_init(&coder->iter, i); + + coder->sequence = SEQ_INDICATOR; + coder->index = i; + coder->pos = 0; + coder->crc32 = 0; + + return; +} + + +extern lzma_ret +lzma_index_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_index *i) +{ + lzma_next_coder_init(&lzma_index_encoder_init, next, allocator); + + if (i == NULL) + return LZMA_PROG_ERROR; + + if (next->coder == NULL) { + next->coder = lzma_alloc(sizeof(lzma_index_coder), allocator); + if (next->coder == NULL) + return LZMA_MEM_ERROR; + + next->code = &index_encode; + next->end = &index_encoder_end; + } + + index_encoder_reset(next->coder, i); + + return LZMA_OK; +} + + +extern LZMA_API(lzma_ret) +lzma_index_encoder(lzma_stream *strm, const lzma_index *i) +{ + lzma_next_strm_init(lzma_index_encoder_init, strm, i); + + strm->internal->supported_actions[LZMA_RUN] = true; + strm->internal->supported_actions[LZMA_FINISH] = true; + + return LZMA_OK; +} + + +extern LZMA_API(lzma_ret) +lzma_index_buffer_encode(const lzma_index *i, + uint8_t *out, size_t *out_pos, size_t out_size) +{ + // Validate the arguments. + if (i == NULL || out == NULL || out_pos == NULL || *out_pos > out_size) + return LZMA_PROG_ERROR; + + // Don't try to encode if there's not enough output space. + if (out_size - *out_pos < lzma_index_size(i)) + return LZMA_BUF_ERROR; + + // The Index encoder needs just one small data structure so we can + // allocate it on stack. + lzma_index_coder coder; + index_encoder_reset(&coder, i); + + // Do the actual encoding. This should never fail, but store + // the original *out_pos just in case. + const size_t out_start = *out_pos; + lzma_ret ret = index_encode(&coder, NULL, NULL, NULL, 0, + out, out_pos, out_size, LZMA_RUN); + + if (ret == LZMA_STREAM_END) { + ret = LZMA_OK; + } else { + // We should never get here, but just in case, restore the + // output position and set the error accordingly if something + // goes wrong and debugging isn't enabled. + assert(0); + *out_pos = out_start; + ret = LZMA_PROG_ERROR; + } + + return ret; +} diff --git a/dependencies/cmliblzma/liblzma/common/index_encoder.h b/dependencies/cmliblzma/liblzma/common/index_encoder.h new file mode 100644 index 0000000..4d55cd1 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/index_encoder.h @@ -0,0 +1,23 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file index_encoder.h +/// \brief Encodes the Index field +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_INDEX_ENCODER_H +#define LZMA_INDEX_ENCODER_H + +#include "common.h" + + +extern lzma_ret lzma_index_encoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, const lzma_index *i); + + +#endif diff --git a/dependencies/cmliblzma/liblzma/common/index_hash.c b/dependencies/cmliblzma/liblzma/common/index_hash.c new file mode 100644 index 0000000..d7a0344 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/index_hash.c @@ -0,0 +1,334 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file index_hash.c +/// \brief Validates Index by using a hash function +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "common.h" +#include "index.h" +#include "check.h" + + +typedef struct { + /// Sum of the Block sizes (including Block Padding) + lzma_vli blocks_size; + + /// Sum of the Uncompressed Size fields + lzma_vli uncompressed_size; + + /// Number of Records + lzma_vli count; + + /// Size of the List of Index Records as bytes + lzma_vli index_list_size; + + /// Check calculated from Unpadded Sizes and Uncompressed Sizes. + lzma_check_state check; + +} lzma_index_hash_info; + + +struct lzma_index_hash_s { + enum { + SEQ_BLOCK, + SEQ_COUNT, + SEQ_UNPADDED, + SEQ_UNCOMPRESSED, + SEQ_PADDING_INIT, + SEQ_PADDING, + SEQ_CRC32, + } sequence; + + /// Information collected while decoding the actual Blocks. + lzma_index_hash_info blocks; + + /// Information collected from the Index field. + lzma_index_hash_info records; + + /// Number of Records not fully decoded + lzma_vli remaining; + + /// Unpadded Size currently being read from an Index Record. + lzma_vli unpadded_size; + + /// Uncompressed Size currently being read from an Index Record. + lzma_vli uncompressed_size; + + /// Position in variable-length integers when decoding them from + /// the List of Records. + size_t pos; + + /// CRC32 of the Index + uint32_t crc32; +}; + + +extern LZMA_API(lzma_index_hash *) +lzma_index_hash_init(lzma_index_hash *index_hash, + const lzma_allocator *allocator) +{ + if (index_hash == NULL) { + index_hash = lzma_alloc(sizeof(lzma_index_hash), allocator); + if (index_hash == NULL) + return NULL; + } + + index_hash->sequence = SEQ_BLOCK; + index_hash->blocks.blocks_size = 0; + index_hash->blocks.uncompressed_size = 0; + index_hash->blocks.count = 0; + index_hash->blocks.index_list_size = 0; + index_hash->records.blocks_size = 0; + index_hash->records.uncompressed_size = 0; + index_hash->records.count = 0; + index_hash->records.index_list_size = 0; + index_hash->unpadded_size = 0; + index_hash->uncompressed_size = 0; + index_hash->pos = 0; + index_hash->crc32 = 0; + + // These cannot fail because LZMA_CHECK_BEST is known to be supported. + (void)lzma_check_init(&index_hash->blocks.check, LZMA_CHECK_BEST); + (void)lzma_check_init(&index_hash->records.check, LZMA_CHECK_BEST); + + return index_hash; +} + + +extern LZMA_API(void) +lzma_index_hash_end(lzma_index_hash *index_hash, + const lzma_allocator *allocator) +{ + lzma_free(index_hash, allocator); + return; +} + + +extern LZMA_API(lzma_vli) +lzma_index_hash_size(const lzma_index_hash *index_hash) +{ + // Get the size of the Index from ->blocks instead of ->records for + // cases where application wants to know the Index Size before + // decoding the Index. + return index_size(index_hash->blocks.count, + index_hash->blocks.index_list_size); +} + + +/// Updates the sizes and the hash without any validation. +static lzma_ret +hash_append(lzma_index_hash_info *info, lzma_vli unpadded_size, + lzma_vli uncompressed_size) +{ + info->blocks_size += vli_ceil4(unpadded_size); + info->uncompressed_size += uncompressed_size; + info->index_list_size += lzma_vli_size(unpadded_size) + + lzma_vli_size(uncompressed_size); + ++info->count; + + const lzma_vli sizes[2] = { unpadded_size, uncompressed_size }; + lzma_check_update(&info->check, LZMA_CHECK_BEST, + (const uint8_t *)(sizes), sizeof(sizes)); + + return LZMA_OK; +} + + +extern LZMA_API(lzma_ret) +lzma_index_hash_append(lzma_index_hash *index_hash, lzma_vli unpadded_size, + lzma_vli uncompressed_size) +{ + // Validate the arguments. + if (index_hash->sequence != SEQ_BLOCK + || unpadded_size < UNPADDED_SIZE_MIN + || unpadded_size > UNPADDED_SIZE_MAX + || uncompressed_size > LZMA_VLI_MAX) + return LZMA_PROG_ERROR; + + // Update the hash. + return_if_error(hash_append(&index_hash->blocks, + unpadded_size, uncompressed_size)); + + // Validate the properties of *info are still in allowed limits. + if (index_hash->blocks.blocks_size > LZMA_VLI_MAX + || index_hash->blocks.uncompressed_size > LZMA_VLI_MAX + || index_size(index_hash->blocks.count, + index_hash->blocks.index_list_size) + > LZMA_BACKWARD_SIZE_MAX + || index_stream_size(index_hash->blocks.blocks_size, + index_hash->blocks.count, + index_hash->blocks.index_list_size) + > LZMA_VLI_MAX) + return LZMA_DATA_ERROR; + + return LZMA_OK; +} + + +extern LZMA_API(lzma_ret) +lzma_index_hash_decode(lzma_index_hash *index_hash, const uint8_t *in, + size_t *in_pos, size_t in_size) +{ + // Catch zero input buffer here, because in contrast to Index encoder + // and decoder functions, applications call this function directly + // instead of via lzma_code(), which does the buffer checking. + if (*in_pos >= in_size) + return LZMA_BUF_ERROR; + + // NOTE: This function has many similarities to index_encode() and + // index_decode() functions found from index_encoder.c and + // index_decoder.c. See the comments especially in index_encoder.c. + const size_t in_start = *in_pos; + lzma_ret ret = LZMA_OK; + + while (*in_pos < in_size) + switch (index_hash->sequence) { + case SEQ_BLOCK: + // Check the Index Indicator is present. + if (in[(*in_pos)++] != 0x00) + return LZMA_DATA_ERROR; + + index_hash->sequence = SEQ_COUNT; + break; + + case SEQ_COUNT: { + ret = lzma_vli_decode(&index_hash->remaining, + &index_hash->pos, in, in_pos, in_size); + if (ret != LZMA_STREAM_END) + goto out; + + // The count must match the count of the Blocks decoded. + if (index_hash->remaining != index_hash->blocks.count) + return LZMA_DATA_ERROR; + + ret = LZMA_OK; + index_hash->pos = 0; + + // Handle the special case when there are no Blocks. + index_hash->sequence = index_hash->remaining == 0 + ? SEQ_PADDING_INIT : SEQ_UNPADDED; + break; + } + + case SEQ_UNPADDED: + case SEQ_UNCOMPRESSED: { + lzma_vli *size = index_hash->sequence == SEQ_UNPADDED + ? &index_hash->unpadded_size + : &index_hash->uncompressed_size; + + ret = lzma_vli_decode(size, &index_hash->pos, + in, in_pos, in_size); + if (ret != LZMA_STREAM_END) + goto out; + + ret = LZMA_OK; + index_hash->pos = 0; + + if (index_hash->sequence == SEQ_UNPADDED) { + if (index_hash->unpadded_size < UNPADDED_SIZE_MIN + || index_hash->unpadded_size + > UNPADDED_SIZE_MAX) + return LZMA_DATA_ERROR; + + index_hash->sequence = SEQ_UNCOMPRESSED; + } else { + // Update the hash. + return_if_error(hash_append(&index_hash->records, + index_hash->unpadded_size, + index_hash->uncompressed_size)); + + // Verify that we don't go over the known sizes. Note + // that this validation is simpler than the one used + // in lzma_index_hash_append(), because here we know + // that values in index_hash->blocks are already + // validated and we are fine as long as we don't + // exceed them in index_hash->records. + if (index_hash->blocks.blocks_size + < index_hash->records.blocks_size + || index_hash->blocks.uncompressed_size + < index_hash->records.uncompressed_size + || index_hash->blocks.index_list_size + < index_hash->records.index_list_size) + return LZMA_DATA_ERROR; + + // Check if this was the last Record. + index_hash->sequence = --index_hash->remaining == 0 + ? SEQ_PADDING_INIT : SEQ_UNPADDED; + } + + break; + } + + case SEQ_PADDING_INIT: + index_hash->pos = (LZMA_VLI_C(4) - index_size_unpadded( + index_hash->records.count, + index_hash->records.index_list_size)) & 3; + index_hash->sequence = SEQ_PADDING; + + // Fall through + + case SEQ_PADDING: + if (index_hash->pos > 0) { + --index_hash->pos; + if (in[(*in_pos)++] != 0x00) + return LZMA_DATA_ERROR; + + break; + } + + // Compare the sizes. + if (index_hash->blocks.blocks_size + != index_hash->records.blocks_size + || index_hash->blocks.uncompressed_size + != index_hash->records.uncompressed_size + || index_hash->blocks.index_list_size + != index_hash->records.index_list_size) + return LZMA_DATA_ERROR; + + // Finish the hashes and compare them. + lzma_check_finish(&index_hash->blocks.check, LZMA_CHECK_BEST); + lzma_check_finish(&index_hash->records.check, LZMA_CHECK_BEST); + if (memcmp(index_hash->blocks.check.buffer.u8, + index_hash->records.check.buffer.u8, + lzma_check_size(LZMA_CHECK_BEST)) != 0) + return LZMA_DATA_ERROR; + + // Finish the CRC32 calculation. + index_hash->crc32 = lzma_crc32(in + in_start, + *in_pos - in_start, index_hash->crc32); + + index_hash->sequence = SEQ_CRC32; + + // Fall through + + case SEQ_CRC32: + do { + if (*in_pos == in_size) + return LZMA_OK; + + if (((index_hash->crc32 >> (index_hash->pos * 8)) + & 0xFF) != in[(*in_pos)++]) + return LZMA_DATA_ERROR; + + } while (++index_hash->pos < 4); + + return LZMA_STREAM_END; + + default: + assert(0); + return LZMA_PROG_ERROR; + } + +out: + // Update the CRC32, + index_hash->crc32 = lzma_crc32(in + in_start, + *in_pos - in_start, index_hash->crc32); + + return ret; +} diff --git a/dependencies/cmliblzma/liblzma/common/memcmplen.h b/dependencies/cmliblzma/liblzma/common/memcmplen.h new file mode 100644 index 0000000..c1efc9e --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/memcmplen.h @@ -0,0 +1,175 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file memcmplen.h +/// \brief Optimized comparison of two buffers +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_MEMCMPLEN_H +#define LZMA_MEMCMPLEN_H + +#include "common.h" + +#ifdef HAVE_IMMINTRIN_H +# include +#endif + + +/// Find out how many equal bytes the two buffers have. +/// +/// \param buf1 First buffer +/// \param buf2 Second buffer +/// \param len How many bytes have already been compared and will +/// be assumed to match +/// \param limit How many bytes to compare at most, including the +/// already-compared bytes. This must be significantly +/// smaller than UINT32_MAX to avoid integer overflows. +/// Up to LZMA_MEMCMPLEN_EXTRA bytes may be read past +/// the specified limit from both buf1 and buf2. +/// +/// \return Number of equal bytes in the buffers is returned. +/// This is always at least len and at most limit. +/// +/// \note LZMA_MEMCMPLEN_EXTRA defines how many extra bytes may be read. +/// It's rounded up to 2^n. This extra amount needs to be +/// allocated in the buffers being used. It needs to be +/// initialized too to keep Valgrind quiet. +static inline uint32_t lzma_attribute((__always_inline__)) +lzma_memcmplen(const uint8_t *buf1, const uint8_t *buf2, + uint32_t len, uint32_t limit) +{ + assert(len <= limit); + assert(limit <= UINT32_MAX / 2); + +#if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \ + && ((TUKLIB_GNUC_REQ(3, 4) && defined(__x86_64__)) \ + || (defined(__INTEL_COMPILER) && defined(__x86_64__)) \ + || (defined(__INTEL_COMPILER) && defined(_M_X64)) \ + || (defined(_MSC_VER) && defined(_M_X64))) + // NOTE: This will use 64-bit unaligned access which + // TUKLIB_FAST_UNALIGNED_ACCESS wasn't meant to permit, but + // it's convenient here at least as long as it's x86-64 only. + // + // I keep this x86-64 only for now since that's where I know this + // to be a good method. This may be fine on other 64-bit CPUs too. + // On big endian one should use xor instead of subtraction and switch + // to __builtin_clzll(). +#define LZMA_MEMCMPLEN_EXTRA 8 + while (len < limit) { + const uint64_t x = *(const uint64_t *)(buf1 + len) + - *(const uint64_t *)(buf2 + len); + if (x != 0) { +# if defined(_M_X64) // MSVC or Intel C compiler on Windows + unsigned long tmp; + _BitScanForward64(&tmp, x); + len += (uint32_t)tmp >> 3; +# else // GCC, clang, or Intel C compiler + len += (uint32_t)__builtin_ctzll(x) >> 3; +# endif + return my_min(len, limit); + } + + len += 8; + } + + return limit; + +#elif defined(TUKLIB_FAST_UNALIGNED_ACCESS) \ + && defined(HAVE__MM_MOVEMASK_EPI8) \ + && ((defined(__GNUC__) && defined(__SSE2_MATH__)) \ + || (defined(__INTEL_COMPILER) && defined(__SSE2__)) \ + || (defined(_MSC_VER) && defined(_M_IX86_FP) \ + && _M_IX86_FP >= 2)) + // NOTE: Like above, this will use 128-bit unaligned access which + // TUKLIB_FAST_UNALIGNED_ACCESS wasn't meant to permit. + // + // SSE2 version for 32-bit and 64-bit x86. On x86-64 the above + // version is sometimes significantly faster and sometimes + // slightly slower than this SSE2 version, so this SSE2 + // version isn't used on x86-64. +# define LZMA_MEMCMPLEN_EXTRA 16 + while (len < limit) { + const uint32_t x = 0xFFFF ^ _mm_movemask_epi8(_mm_cmpeq_epi8( + _mm_loadu_si128((const __m128i *)(buf1 + len)), + _mm_loadu_si128((const __m128i *)(buf2 + len)))); + + if (x != 0) { +# if defined(__INTEL_COMPILER) + len += _bit_scan_forward(x); +# elif defined(_MSC_VER) + unsigned long tmp; + _BitScanForward(&tmp, x); + len += tmp; +# else + len += __builtin_ctz(x); +# endif + return my_min(len, limit); + } + + len += 16; + } + + return limit; + +#elif defined(TUKLIB_FAST_UNALIGNED_ACCESS) && !defined(WORDS_BIGENDIAN) + // Generic 32-bit little endian method +# define LZMA_MEMCMPLEN_EXTRA 4 + while (len < limit) { + uint32_t x = *(const uint32_t *)(buf1 + len) + - *(const uint32_t *)(buf2 + len); + if (x != 0) { + if ((x & 0xFFFF) == 0) { + len += 2; + x >>= 16; + } + + if ((x & 0xFF) == 0) + ++len; + + return my_min(len, limit); + } + + len += 4; + } + + return limit; + +#elif defined(TUKLIB_FAST_UNALIGNED_ACCESS) && defined(WORDS_BIGENDIAN) + // Generic 32-bit big endian method +# define LZMA_MEMCMPLEN_EXTRA 4 + while (len < limit) { + uint32_t x = *(const uint32_t *)(buf1 + len) + ^ *(const uint32_t *)(buf2 + len); + if (x != 0) { + if ((x & 0xFFFF0000) == 0) { + len += 2; + x <<= 16; + } + + if ((x & 0xFF000000) == 0) + ++len; + + return my_min(len, limit); + } + + len += 4; + } + + return limit; + +#else + // Simple portable version that doesn't use unaligned access. +# define LZMA_MEMCMPLEN_EXTRA 0 + while (len < limit && buf1[len] == buf2[len]) + ++len; + + return len; +#endif +} + +#endif diff --git a/dependencies/cmliblzma/liblzma/common/outqueue.c b/dependencies/cmliblzma/liblzma/common/outqueue.c new file mode 100644 index 0000000..2dc8a38 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/outqueue.c @@ -0,0 +1,184 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file outqueue.c +/// \brief Output queue handling in multithreaded coding +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "outqueue.h" + + +/// This is to ease integer overflow checking: We may allocate up to +/// 2 * LZMA_THREADS_MAX buffers and we need some extra memory for other +/// data structures (that's the second /2). +#define BUF_SIZE_MAX (UINT64_MAX / LZMA_THREADS_MAX / 2 / 2) + + +static lzma_ret +get_options(uint64_t *bufs_alloc_size, uint32_t *bufs_count, + uint64_t buf_size_max, uint32_t threads) +{ + if (threads > LZMA_THREADS_MAX || buf_size_max > BUF_SIZE_MAX) + return LZMA_OPTIONS_ERROR; + + // The number of buffers is twice the number of threads. + // This wastes RAM but keeps the threads busy when buffers + // finish out of order. + // + // NOTE: If this is changed, update BUF_SIZE_MAX too. + *bufs_count = threads * 2; + *bufs_alloc_size = *bufs_count * buf_size_max; + + return LZMA_OK; +} + + +extern uint64_t +lzma_outq_memusage(uint64_t buf_size_max, uint32_t threads) +{ + uint64_t bufs_alloc_size; + uint32_t bufs_count; + + if (get_options(&bufs_alloc_size, &bufs_count, buf_size_max, threads) + != LZMA_OK) + return UINT64_MAX; + + return sizeof(lzma_outq) + bufs_count * sizeof(lzma_outbuf) + + bufs_alloc_size; +} + + +extern lzma_ret +lzma_outq_init(lzma_outq *outq, const lzma_allocator *allocator, + uint64_t buf_size_max, uint32_t threads) +{ + uint64_t bufs_alloc_size; + uint32_t bufs_count; + + // Set bufs_count and bufs_alloc_size. + return_if_error(get_options(&bufs_alloc_size, &bufs_count, + buf_size_max, threads)); + + // Allocate memory if needed. + if (outq->buf_size_max != buf_size_max + || outq->bufs_allocated != bufs_count) { + lzma_outq_end(outq, allocator); + +#if SIZE_MAX < UINT64_MAX + if (bufs_alloc_size > SIZE_MAX) + return LZMA_MEM_ERROR; +#endif + + outq->bufs = lzma_alloc(bufs_count * sizeof(lzma_outbuf), + allocator); + outq->bufs_mem = lzma_alloc((size_t)(bufs_alloc_size), + allocator); + + if (outq->bufs == NULL || outq->bufs_mem == NULL) { + lzma_outq_end(outq, allocator); + return LZMA_MEM_ERROR; + } + } + + // Initialize the rest of the main structure. Initialization of + // outq->bufs[] is done when they are actually needed. + outq->buf_size_max = (size_t)(buf_size_max); + outq->bufs_allocated = bufs_count; + outq->bufs_pos = 0; + outq->bufs_used = 0; + outq->read_pos = 0; + + return LZMA_OK; +} + + +extern void +lzma_outq_end(lzma_outq *outq, const lzma_allocator *allocator) +{ + lzma_free(outq->bufs, allocator); + outq->bufs = NULL; + + lzma_free(outq->bufs_mem, allocator); + outq->bufs_mem = NULL; + + return; +} + + +extern lzma_outbuf * +lzma_outq_get_buf(lzma_outq *outq) +{ + // Caller must have checked it with lzma_outq_has_buf(). + assert(outq->bufs_used < outq->bufs_allocated); + + // Initialize the new buffer. + lzma_outbuf *buf = &outq->bufs[outq->bufs_pos]; + buf->buf = outq->bufs_mem + outq->bufs_pos * outq->buf_size_max; + buf->size = 0; + buf->finished = false; + + // Update the queue state. + if (++outq->bufs_pos == outq->bufs_allocated) + outq->bufs_pos = 0; + + ++outq->bufs_used; + + return buf; +} + + +extern bool +lzma_outq_is_readable(const lzma_outq *outq) +{ + uint32_t i = outq->bufs_pos - outq->bufs_used; + if (outq->bufs_pos < outq->bufs_used) + i += outq->bufs_allocated; + + return outq->bufs[i].finished; +} + + +extern lzma_ret +lzma_outq_read(lzma_outq *restrict outq, uint8_t *restrict out, + size_t *restrict out_pos, size_t out_size, + lzma_vli *restrict unpadded_size, + lzma_vli *restrict uncompressed_size) +{ + // There must be at least one buffer from which to read. + if (outq->bufs_used == 0) + return LZMA_OK; + + // Get the buffer. + uint32_t i = outq->bufs_pos - outq->bufs_used; + if (outq->bufs_pos < outq->bufs_used) + i += outq->bufs_allocated; + + lzma_outbuf *buf = &outq->bufs[i]; + + // If it isn't finished yet, we cannot read from it. + if (!buf->finished) + return LZMA_OK; + + // Copy from the buffer to output. + lzma_bufcpy(buf->buf, &outq->read_pos, buf->size, + out, out_pos, out_size); + + // Return if we didn't get all the data from the buffer. + if (outq->read_pos < buf->size) + return LZMA_OK; + + // The buffer was finished. Tell the caller its size information. + *unpadded_size = buf->unpadded_size; + *uncompressed_size = buf->uncompressed_size; + + // Free this buffer for further use. + --outq->bufs_used; + outq->read_pos = 0; + + return LZMA_STREAM_END; +} diff --git a/dependencies/cmliblzma/liblzma/common/outqueue.h b/dependencies/cmliblzma/liblzma/common/outqueue.h new file mode 100644 index 0000000..079634d --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/outqueue.h @@ -0,0 +1,156 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file outqueue.h +/// \brief Output queue handling in multithreaded coding +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "common.h" + + +/// Output buffer for a single thread +typedef struct { + /// Pointer to the output buffer of lzma_outq.buf_size_max bytes + uint8_t *buf; + + /// Amount of data written to buf + size_t size; + + /// Additional size information + lzma_vli unpadded_size; + lzma_vli uncompressed_size; + + /// True when no more data will be written into this buffer. + /// + /// \note This is read by another thread and thus access + /// to this variable needs a mutex. + bool finished; + +} lzma_outbuf; + + +typedef struct { + /// Array of buffers that are used cyclically. + lzma_outbuf *bufs; + + /// Memory allocated for all the buffers + uint8_t *bufs_mem; + + /// Amount of buffer space available in each buffer + size_t buf_size_max; + + /// Number of buffers allocated + uint32_t bufs_allocated; + + /// Position in the bufs array. The next buffer to be taken + /// into use is bufs[bufs_pos]. + uint32_t bufs_pos; + + /// Number of buffers in use + uint32_t bufs_used; + + /// Position in the buffer in lzma_outq_read() + size_t read_pos; + +} lzma_outq; + + +/** + * \brief Calculate the memory usage of an output queue + * + * \return Approximate memory usage in bytes or UINT64_MAX on error. + */ +extern uint64_t lzma_outq_memusage(uint64_t buf_size_max, uint32_t threads); + + +/// \brief Initialize an output queue +/// +/// \param outq Pointer to an output queue. Before calling +/// this function the first time, *outq should +/// have been zeroed with memzero() so that this +/// function knows that there are no previous +/// allocations to free. +/// \param allocator Pointer to allocator or NULL +/// \param buf_size_max Maximum amount of data that a single buffer +/// in the queue may need to store. +/// \param threads Number of buffers that may be in use +/// concurrently. Note that more than this number +/// of buffers will actually get allocated to +/// improve performance when buffers finish +/// out of order. +/// +/// \return - LZMA_OK +/// - LZMA_MEM_ERROR +/// +extern lzma_ret lzma_outq_init( + lzma_outq *outq, const lzma_allocator *allocator, + uint64_t buf_size_max, uint32_t threads); + + +/// \brief Free the memory associated with the output queue +extern void lzma_outq_end(lzma_outq *outq, const lzma_allocator *allocator); + + +/// \brief Get a new buffer +/// +/// lzma_outq_has_buf() must be used to check that there is a buffer +/// available before calling lzma_outq_get_buf(). +/// +extern lzma_outbuf *lzma_outq_get_buf(lzma_outq *outq); + + +/// \brief Test if there is data ready to be read +/// +/// Call to this function must be protected with the same mutex that +/// is used to protect lzma_outbuf.finished. +/// +extern bool lzma_outq_is_readable(const lzma_outq *outq); + + +/// \brief Read finished data +/// +/// \param outq Pointer to an output queue +/// \param out Beginning of the output buffer +/// \param out_pos The next byte will be written to +/// out[*out_pos]. +/// \param out_size Size of the out buffer; the first byte into +/// which no data is written to is out[out_size]. +/// \param unpadded_size Unpadded Size from the Block encoder +/// \param uncompressed_size Uncompressed Size from the Block encoder +/// +/// \return - LZMA: All OK. Either no data was available or the buffer +/// being read didn't become empty yet. +/// - LZMA_STREAM_END: The buffer being read was finished. +/// *unpadded_size and *uncompressed_size were set. +/// +/// \note This reads lzma_outbuf.finished variables and thus call +/// to this function needs to be protected with a mutex. +/// +extern lzma_ret lzma_outq_read(lzma_outq *restrict outq, + uint8_t *restrict out, size_t *restrict out_pos, + size_t out_size, lzma_vli *restrict unpadded_size, + lzma_vli *restrict uncompressed_size); + + +/// \brief Test if there is at least one buffer free +/// +/// This must be used before getting a new buffer with lzma_outq_get_buf(). +/// +static inline bool +lzma_outq_has_buf(const lzma_outq *outq) +{ + return outq->bufs_used < outq->bufs_allocated; +} + + +/// \brief Test if the queue is completely empty +static inline bool +lzma_outq_is_empty(const lzma_outq *outq) +{ + return outq->bufs_used == 0; +} diff --git a/dependencies/cmliblzma/liblzma/common/stream_buffer_decoder.c b/dependencies/cmliblzma/liblzma/common/stream_buffer_decoder.c new file mode 100644 index 0000000..b9745b5 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/stream_buffer_decoder.c @@ -0,0 +1,91 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file stream_buffer_decoder.c +/// \brief Single-call .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 "stream_decoder.h" + + +extern LZMA_API(lzma_ret) +lzma_stream_buffer_decode(uint64_t *memlimit, uint32_t flags, + const lzma_allocator *allocator, + const uint8_t *in, size_t *in_pos, size_t in_size, + uint8_t *out, size_t *out_pos, size_t out_size) +{ + // Sanity checks + if (in_pos == NULL || (in == NULL && *in_pos != in_size) + || *in_pos > in_size || out_pos == NULL + || (out == NULL && *out_pos != out_size) + || *out_pos > out_size) + return LZMA_PROG_ERROR; + + // Catch flags that are not allowed in buffer-to-buffer decoding. + if (flags & LZMA_TELL_ANY_CHECK) + return LZMA_PROG_ERROR; + + // Initialize the Stream decoder. + // TODO: We need something to tell the decoder that it can use the + // output buffer as workspace, and thus save significant amount of RAM. + lzma_next_coder stream_decoder = LZMA_NEXT_CODER_INIT; + lzma_ret ret = lzma_stream_decoder_init( + &stream_decoder, allocator, *memlimit, flags); + + if (ret == LZMA_OK) { + // Save the positions so that we can restore them in case + // an error occurs. + const size_t in_start = *in_pos; + const size_t out_start = *out_pos; + + // Do the actual decoding. + ret = stream_decoder.code(stream_decoder.coder, allocator, + in, in_pos, in_size, out, out_pos, out_size, + LZMA_FINISH); + + if (ret == LZMA_STREAM_END) { + ret = LZMA_OK; + } else { + // Something went wrong, restore the positions. + *in_pos = in_start; + *out_pos = out_start; + + if (ret == LZMA_OK) { + // Either the input was truncated or the + // output buffer was too small. + assert(*in_pos == in_size + || *out_pos == out_size); + + // If all the input was consumed, then the + // input is truncated, even if the output + // buffer is also full. This is because + // processing the last byte of the Stream + // never produces output. + if (*in_pos == in_size) + ret = LZMA_DATA_ERROR; + else + ret = LZMA_BUF_ERROR; + + } else if (ret == LZMA_MEMLIMIT_ERROR) { + // Let the caller know how much memory would + // have been needed. + uint64_t memusage; + (void)stream_decoder.memconfig( + stream_decoder.coder, + memlimit, &memusage, 0); + } + } + } + + // Free the decoder memory. This needs to be done even if + // initialization fails, because the internal API doesn't + // require the initialization function to free its memory on error. + lzma_next_end(&stream_decoder, allocator); + + return ret; +} diff --git a/dependencies/cmliblzma/liblzma/common/stream_buffer_encoder.c b/dependencies/cmliblzma/liblzma/common/stream_buffer_encoder.c new file mode 100644 index 0000000..af49554 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/stream_buffer_encoder.c @@ -0,0 +1,141 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file stream_buffer_encoder.c +/// \brief Single-call .xz Stream encoder +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "index.h" + + +/// Maximum size of Index that has exactly one Record. +/// Index Indicator + Number of Records + Record + CRC32 rounded up to +/// the next multiple of four. +#define INDEX_BOUND ((1 + 1 + 2 * LZMA_VLI_BYTES_MAX + 4 + 3) & ~3) + +/// Stream Header, Stream Footer, and Index +#define HEADERS_BOUND (2 * LZMA_STREAM_HEADER_SIZE + INDEX_BOUND) + + +extern LZMA_API(size_t) +lzma_stream_buffer_bound(size_t uncompressed_size) +{ + // Get the maximum possible size of a Block. + const size_t block_bound = lzma_block_buffer_bound(uncompressed_size); + if (block_bound == 0) + return 0; + + // Catch the possible integer overflow and also prevent the size of + // the Stream exceeding LZMA_VLI_MAX (theoretically possible on + // 64-bit systems). + if (my_min(SIZE_MAX, LZMA_VLI_MAX) - block_bound < HEADERS_BOUND) + return 0; + + return block_bound + HEADERS_BOUND; +} + + +extern LZMA_API(lzma_ret) +lzma_stream_buffer_encode(lzma_filter *filters, lzma_check check, + const lzma_allocator *allocator, + const uint8_t *in, size_t in_size, + uint8_t *out, size_t *out_pos_ptr, size_t out_size) +{ + // Sanity checks + if (filters == NULL || (unsigned int)(check) > LZMA_CHECK_ID_MAX + || (in == NULL && in_size != 0) || out == NULL + || out_pos_ptr == NULL || *out_pos_ptr > out_size) + return LZMA_PROG_ERROR; + + if (!lzma_check_is_supported(check)) + return LZMA_UNSUPPORTED_CHECK; + + // Note for the paranoids: Index encoder prevents the Stream from + // getting too big and still being accepted with LZMA_OK, and Block + // encoder catches if the input is too big. So we don't need to + // separately check if the buffers are too big. + + // Use a local copy. We update *out_pos_ptr only if everything + // succeeds. + size_t out_pos = *out_pos_ptr; + + // Check that there's enough space for both Stream Header and + // Stream Footer. + if (out_size - out_pos <= 2 * LZMA_STREAM_HEADER_SIZE) + return LZMA_BUF_ERROR; + + // Reserve space for Stream Footer so we don't need to check for + // available space again before encoding Stream Footer. + out_size -= LZMA_STREAM_HEADER_SIZE; + + // Encode the Stream Header. + lzma_stream_flags stream_flags = { + .version = 0, + .check = check, + }; + + if (lzma_stream_header_encode(&stream_flags, out + out_pos) + != LZMA_OK) + return LZMA_PROG_ERROR; + + out_pos += LZMA_STREAM_HEADER_SIZE; + + // Encode a Block but only if there is at least one byte of input. + lzma_block block = { + .version = 0, + .check = check, + .filters = filters, + }; + + if (in_size > 0) + return_if_error(lzma_block_buffer_encode(&block, allocator, + in, in_size, out, &out_pos, out_size)); + + // Index + { + // Create an Index. It will have one Record if there was + // at least one byte of input to encode. Otherwise the + // Index will be empty. + lzma_index *i = lzma_index_init(allocator); + if (i == NULL) + return LZMA_MEM_ERROR; + + lzma_ret ret = LZMA_OK; + + if (in_size > 0) + ret = lzma_index_append(i, allocator, + lzma_block_unpadded_size(&block), + block.uncompressed_size); + + // If adding the Record was successful, encode the Index + // and get its size which will be stored into Stream Footer. + if (ret == LZMA_OK) { + ret = lzma_index_buffer_encode( + i, out, &out_pos, out_size); + + stream_flags.backward_size = lzma_index_size(i); + } + + lzma_index_end(i, allocator); + + if (ret != LZMA_OK) + return ret; + } + + // Stream Footer. We have already reserved space for this. + if (lzma_stream_footer_encode(&stream_flags, out + out_pos) + != LZMA_OK) + return LZMA_PROG_ERROR; + + out_pos += LZMA_STREAM_HEADER_SIZE; + + // Everything went fine, make the new output position available + // to the application. + *out_pos_ptr = out_pos; + return LZMA_OK; +} diff --git a/dependencies/cmliblzma/liblzma/common/stream_decoder.c b/dependencies/cmliblzma/liblzma/common/stream_decoder.c new file mode 100644 index 0000000..fdd8ff2 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/stream_decoder.c @@ -0,0 +1,467 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file stream_decoder.c +/// \brief Decodes .xz Streams +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "stream_decoder.h" +#include "block_decoder.h" + + +typedef struct { + enum { + SEQ_STREAM_HEADER, + SEQ_BLOCK_HEADER, + SEQ_BLOCK, + SEQ_INDEX, + SEQ_STREAM_FOOTER, + SEQ_STREAM_PADDING, + } sequence; + + /// Block or Metadata decoder. This takes little memory and the same + /// data structure can be used to decode every Block Header, so it's + /// a good idea to have a separate lzma_next_coder structure for it. + lzma_next_coder block_decoder; + + /// Block options decoded by the Block Header decoder and used by + /// the Block decoder. + lzma_block block_options; + + /// Stream Flags from Stream Header + lzma_stream_flags stream_flags; + + /// Index is hashed so that it can be compared to the sizes of Blocks + /// with O(1) memory usage. + lzma_index_hash *index_hash; + + /// Memory usage limit + uint64_t memlimit; + + /// Amount of memory actually needed (only an estimate) + uint64_t memusage; + + /// If true, LZMA_NO_CHECK is returned if the Stream has + /// no integrity check. + bool tell_no_check; + + /// If true, LZMA_UNSUPPORTED_CHECK is returned if the Stream has + /// an integrity check that isn't supported by this liblzma build. + bool tell_unsupported_check; + + /// If true, LZMA_GET_CHECK is returned after decoding Stream Header. + bool tell_any_check; + + /// If true, we will tell the Block decoder to skip calculating + /// and verifying the integrity check. + bool ignore_check; + + /// If true, we will decode concatenated Streams that possibly have + /// Stream Padding between or after them. LZMA_STREAM_END is returned + /// once the application isn't giving us any new input, and we aren't + /// in the middle of a Stream, and possible Stream Padding is a + /// multiple of four bytes. + bool concatenated; + + /// When decoding concatenated Streams, this is true as long as we + /// are decoding the first Stream. This is needed to avoid misleading + /// LZMA_FORMAT_ERROR in case the later Streams don't have valid magic + /// bytes. + bool first_stream; + + /// Write position in buffer[] and position in Stream Padding + size_t pos; + + /// Buffer to hold Stream Header, Block Header, and Stream Footer. + /// Block Header has biggest maximum size. + uint8_t buffer[LZMA_BLOCK_HEADER_SIZE_MAX]; +} lzma_stream_coder; + + +static lzma_ret +stream_decoder_reset(lzma_stream_coder *coder, const lzma_allocator *allocator) +{ + // Initialize the Index hash used to verify the Index. + coder->index_hash = lzma_index_hash_init(coder->index_hash, allocator); + if (coder->index_hash == NULL) + return LZMA_MEM_ERROR; + + // Reset the rest of the variables. + coder->sequence = SEQ_STREAM_HEADER; + coder->pos = 0; + + return LZMA_OK; +} + + +static lzma_ret +stream_decode(void *coder_ptr, const lzma_allocator *allocator, + const uint8_t *restrict in, size_t *restrict in_pos, + size_t in_size, uint8_t *restrict out, + size_t *restrict out_pos, size_t out_size, lzma_action action) +{ + lzma_stream_coder *coder = coder_ptr; + + // When decoding the actual Block, it may be able to produce more + // output even if we don't give it any new input. + while (true) + switch (coder->sequence) { + case SEQ_STREAM_HEADER: { + // Copy the Stream Header to the internal buffer. + lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos, + LZMA_STREAM_HEADER_SIZE); + + // Return if we didn't get the whole Stream Header yet. + if (coder->pos < LZMA_STREAM_HEADER_SIZE) + return LZMA_OK; + + coder->pos = 0; + + // Decode the Stream Header. + const lzma_ret ret = lzma_stream_header_decode( + &coder->stream_flags, coder->buffer); + if (ret != LZMA_OK) + return ret == LZMA_FORMAT_ERROR && !coder->first_stream + ? LZMA_DATA_ERROR : ret; + + // If we are decoding concatenated Streams, and the later + // Streams have invalid Header Magic Bytes, we give + // LZMA_DATA_ERROR instead of LZMA_FORMAT_ERROR. + coder->first_stream = false; + + // Copy the type of the Check so that Block Header and Block + // decoders see it. + coder->block_options.check = coder->stream_flags.check; + + // Even if we return LZMA_*_CHECK below, we want + // to continue from Block Header decoding. + coder->sequence = SEQ_BLOCK_HEADER; + + // Detect if there's no integrity check or if it is + // unsupported if those were requested by the application. + if (coder->tell_no_check && coder->stream_flags.check + == LZMA_CHECK_NONE) + return LZMA_NO_CHECK; + + if (coder->tell_unsupported_check + && !lzma_check_is_supported( + coder->stream_flags.check)) + return LZMA_UNSUPPORTED_CHECK; + + if (coder->tell_any_check) + return LZMA_GET_CHECK; + } + + // Fall through + + case SEQ_BLOCK_HEADER: { + if (*in_pos >= in_size) + return LZMA_OK; + + if (coder->pos == 0) { + // Detect if it's Index. + if (in[*in_pos] == 0x00) { + coder->sequence = SEQ_INDEX; + break; + } + + // Calculate the size of the Block Header. Note that + // Block Header decoder wants to see this byte too + // so don't advance *in_pos. + coder->block_options.header_size + = lzma_block_header_size_decode( + in[*in_pos]); + } + + // Copy the Block Header to the internal buffer. + lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos, + coder->block_options.header_size); + + // Return if we didn't get the whole Block Header yet. + if (coder->pos < coder->block_options.header_size) + return LZMA_OK; + + coder->pos = 0; + + // Version 1 is needed to support the .ignore_check option. + coder->block_options.version = 1; + + // Set up a buffer to hold the filter chain. Block Header + // decoder will initialize all members of this array so + // we don't need to do it here. + lzma_filter filters[LZMA_FILTERS_MAX + 1]; + coder->block_options.filters = filters; + + // Decode the Block Header. + return_if_error(lzma_block_header_decode(&coder->block_options, + allocator, coder->buffer)); + + // If LZMA_IGNORE_CHECK was used, this flag needs to be set. + // It has to be set after lzma_block_header_decode() because + // it always resets this to false. + coder->block_options.ignore_check = coder->ignore_check; + + // Check the memory usage limit. + const uint64_t memusage = lzma_raw_decoder_memusage(filters); + lzma_ret ret; + + if (memusage == UINT64_MAX) { + // One or more unknown Filter IDs. + ret = LZMA_OPTIONS_ERROR; + } else { + // Now we can set coder->memusage since we know that + // the filter chain is valid. We don't want + // lzma_memusage() to return UINT64_MAX in case of + // invalid filter chain. + coder->memusage = memusage; + + if (memusage > coder->memlimit) { + // The chain would need too much memory. + ret = LZMA_MEMLIMIT_ERROR; + } else { + // Memory usage is OK. + // Initialize the Block decoder. + ret = lzma_block_decoder_init( + &coder->block_decoder, + allocator, + &coder->block_options); + } + } + + // Free the allocated filter options since they are needed + // only to initialize the Block decoder. + for (size_t i = 0; i < LZMA_FILTERS_MAX; ++i) + lzma_free(filters[i].options, allocator); + + coder->block_options.filters = NULL; + + // Check if memory usage calculation and Block enocoder + // initialization succeeded. + if (ret != LZMA_OK) + return ret; + + coder->sequence = SEQ_BLOCK; + } + + // Fall through + + case SEQ_BLOCK: { + const lzma_ret ret = coder->block_decoder.code( + coder->block_decoder.coder, allocator, + in, in_pos, in_size, out, out_pos, out_size, + action); + + if (ret != LZMA_STREAM_END) + return ret; + + // Block decoded successfully. Add the new size pair to + // the Index hash. + return_if_error(lzma_index_hash_append(coder->index_hash, + lzma_block_unpadded_size( + &coder->block_options), + coder->block_options.uncompressed_size)); + + coder->sequence = SEQ_BLOCK_HEADER; + break; + } + + case SEQ_INDEX: { + // If we don't have any input, don't call + // lzma_index_hash_decode() since it would return + // LZMA_BUF_ERROR, which we must not do here. + if (*in_pos >= in_size) + return LZMA_OK; + + // Decode the Index and compare it to the hash calculated + // from the sizes of the Blocks (if any). + const lzma_ret ret = lzma_index_hash_decode(coder->index_hash, + in, in_pos, in_size); + if (ret != LZMA_STREAM_END) + return ret; + + coder->sequence = SEQ_STREAM_FOOTER; + } + + // Fall through + + case SEQ_STREAM_FOOTER: { + // Copy the Stream Footer to the internal buffer. + lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos, + LZMA_STREAM_HEADER_SIZE); + + // Return if we didn't get the whole Stream Footer yet. + if (coder->pos < LZMA_STREAM_HEADER_SIZE) + return LZMA_OK; + + coder->pos = 0; + + // Decode the Stream Footer. The decoder gives + // LZMA_FORMAT_ERROR if the magic bytes don't match, + // so convert that return code to LZMA_DATA_ERROR. + lzma_stream_flags footer_flags; + const lzma_ret ret = lzma_stream_footer_decode( + &footer_flags, coder->buffer); + if (ret != LZMA_OK) + return ret == LZMA_FORMAT_ERROR + ? LZMA_DATA_ERROR : ret; + + // Check that Index Size stored in the Stream Footer matches + // the real size of the Index field. + if (lzma_index_hash_size(coder->index_hash) + != footer_flags.backward_size) + return LZMA_DATA_ERROR; + + // Compare that the Stream Flags fields are identical in + // both Stream Header and Stream Footer. + return_if_error(lzma_stream_flags_compare( + &coder->stream_flags, &footer_flags)); + + if (!coder->concatenated) + return LZMA_STREAM_END; + + coder->sequence = SEQ_STREAM_PADDING; + } + + // Fall through + + case SEQ_STREAM_PADDING: + assert(coder->concatenated); + + // Skip over possible Stream Padding. + while (true) { + if (*in_pos >= in_size) { + // Unless LZMA_FINISH was used, we cannot + // know if there's more input coming later. + if (action != LZMA_FINISH) + return LZMA_OK; + + // Stream Padding must be a multiple of + // four bytes. + return coder->pos == 0 + ? LZMA_STREAM_END + : LZMA_DATA_ERROR; + } + + // If the byte is not zero, it probably indicates + // beginning of a new Stream (or the file is corrupt). + if (in[*in_pos] != 0x00) + break; + + ++*in_pos; + coder->pos = (coder->pos + 1) & 3; + } + + // Stream Padding must be a multiple of four bytes (empty + // Stream Padding is OK). + if (coder->pos != 0) { + ++*in_pos; + return LZMA_DATA_ERROR; + } + + // Prepare to decode the next Stream. + return_if_error(stream_decoder_reset(coder, allocator)); + break; + + default: + assert(0); + return LZMA_PROG_ERROR; + } + + // Never reached +} + + +static void +stream_decoder_end(void *coder_ptr, const lzma_allocator *allocator) +{ + lzma_stream_coder *coder = coder_ptr; + lzma_next_end(&coder->block_decoder, allocator); + lzma_index_hash_end(coder->index_hash, allocator); + lzma_free(coder, allocator); + return; +} + + +static lzma_check +stream_decoder_get_check(const void *coder_ptr) +{ + const lzma_stream_coder *coder = coder_ptr; + return coder->stream_flags.check; +} + + +static lzma_ret +stream_decoder_memconfig(void *coder_ptr, uint64_t *memusage, + uint64_t *old_memlimit, uint64_t new_memlimit) +{ + lzma_stream_coder *coder = coder_ptr; + + *memusage = coder->memusage; + *old_memlimit = coder->memlimit; + + if (new_memlimit != 0) { + if (new_memlimit < coder->memusage) + return LZMA_MEMLIMIT_ERROR; + + coder->memlimit = new_memlimit; + } + + return LZMA_OK; +} + + +extern lzma_ret +lzma_stream_decoder_init( + lzma_next_coder *next, const lzma_allocator *allocator, + uint64_t memlimit, uint32_t flags) +{ + lzma_next_coder_init(&lzma_stream_decoder_init, next, allocator); + + if (flags & ~LZMA_SUPPORTED_FLAGS) + return LZMA_OPTIONS_ERROR; + + lzma_stream_coder *coder = next->coder; + if (coder == NULL) { + coder = lzma_alloc(sizeof(lzma_stream_coder), allocator); + if (coder == NULL) + return LZMA_MEM_ERROR; + + next->coder = coder; + next->code = &stream_decode; + next->end = &stream_decoder_end; + next->get_check = &stream_decoder_get_check; + next->memconfig = &stream_decoder_memconfig; + + coder->block_decoder = LZMA_NEXT_CODER_INIT; + coder->index_hash = NULL; + } + + coder->memlimit = my_max(1, memlimit); + coder->memusage = LZMA_MEMUSAGE_BASE; + coder->tell_no_check = (flags & LZMA_TELL_NO_CHECK) != 0; + coder->tell_unsupported_check + = (flags & LZMA_TELL_UNSUPPORTED_CHECK) != 0; + coder->tell_any_check = (flags & LZMA_TELL_ANY_CHECK) != 0; + coder->ignore_check = (flags & LZMA_IGNORE_CHECK) != 0; + coder->concatenated = (flags & LZMA_CONCATENATED) != 0; + coder->first_stream = true; + + return stream_decoder_reset(coder, allocator); +} + + +extern LZMA_API(lzma_ret) +lzma_stream_decoder(lzma_stream *strm, uint64_t memlimit, uint32_t flags) +{ + lzma_next_strm_init(lzma_stream_decoder_init, strm, memlimit, flags); + + strm->internal->supported_actions[LZMA_RUN] = true; + strm->internal->supported_actions[LZMA_FINISH] = true; + + return LZMA_OK; +} diff --git a/dependencies/cmliblzma/liblzma/common/stream_decoder.h b/dependencies/cmliblzma/liblzma/common/stream_decoder.h new file mode 100644 index 0000000..c13c6ba --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/stream_decoder.h @@ -0,0 +1,22 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file stream_decoder.h +/// \brief Decodes .xz Streams +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_STREAM_DECODER_H +#define LZMA_STREAM_DECODER_H + +#include "common.h" + +extern lzma_ret lzma_stream_decoder_init( + lzma_next_coder *next, const lzma_allocator *allocator, + uint64_t memlimit, uint32_t flags); + +#endif diff --git a/dependencies/cmliblzma/liblzma/common/stream_encoder.c b/dependencies/cmliblzma/liblzma/common/stream_encoder.c new file mode 100644 index 0000000..858cba4 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/stream_encoder.c @@ -0,0 +1,340 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file stream_encoder.c +/// \brief Encodes .xz Streams +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "block_encoder.h" +#include "index_encoder.h" + + +typedef struct { + enum { + SEQ_STREAM_HEADER, + SEQ_BLOCK_INIT, + SEQ_BLOCK_HEADER, + SEQ_BLOCK_ENCODE, + SEQ_INDEX_ENCODE, + SEQ_STREAM_FOOTER, + } sequence; + + /// True if Block encoder has been initialized by + /// stream_encoder_init() or stream_encoder_update() + /// and thus doesn't need to be initialized in stream_encode(). + bool block_encoder_is_initialized; + + /// Block + lzma_next_coder block_encoder; + + /// Options for the Block encoder + lzma_block block_options; + + /// The filter chain currently in use + lzma_filter filters[LZMA_FILTERS_MAX + 1]; + + /// Index encoder. This is separate from Block encoder, because this + /// doesn't take much memory, and when encoding multiple Streams + /// with the same encoding options we avoid reallocating memory. + lzma_next_coder index_encoder; + + /// Index to hold sizes of the Blocks + lzma_index *index; + + /// Read position in buffer[] + size_t buffer_pos; + + /// Total number of bytes in buffer[] + size_t buffer_size; + + /// Buffer to hold Stream Header, Block Header, and Stream Footer. + /// Block Header has biggest maximum size. + uint8_t buffer[LZMA_BLOCK_HEADER_SIZE_MAX]; +} lzma_stream_coder; + + +static lzma_ret +block_encoder_init(lzma_stream_coder *coder, const lzma_allocator *allocator) +{ + // Prepare the Block options. Even though Block encoder doesn't need + // compressed_size, uncompressed_size, and header_size to be + // initialized, it is a good idea to do it here, because this way + // we catch if someone gave us Filter ID that cannot be used in + // Blocks/Streams. + coder->block_options.compressed_size = LZMA_VLI_UNKNOWN; + coder->block_options.uncompressed_size = LZMA_VLI_UNKNOWN; + + return_if_error(lzma_block_header_size(&coder->block_options)); + + // Initialize the actual Block encoder. + return lzma_block_encoder_init(&coder->block_encoder, allocator, + &coder->block_options); +} + + +static lzma_ret +stream_encode(void *coder_ptr, const lzma_allocator *allocator, + const uint8_t *restrict in, size_t *restrict in_pos, + size_t in_size, uint8_t *restrict out, + size_t *restrict out_pos, size_t out_size, lzma_action action) +{ + lzma_stream_coder *coder = coder_ptr; + + // Main loop + while (*out_pos < out_size) + switch (coder->sequence) { + case SEQ_STREAM_HEADER: + case SEQ_BLOCK_HEADER: + case SEQ_STREAM_FOOTER: + lzma_bufcpy(coder->buffer, &coder->buffer_pos, + coder->buffer_size, out, out_pos, out_size); + if (coder->buffer_pos < coder->buffer_size) + return LZMA_OK; + + if (coder->sequence == SEQ_STREAM_FOOTER) + return LZMA_STREAM_END; + + coder->buffer_pos = 0; + ++coder->sequence; + break; + + case SEQ_BLOCK_INIT: { + if (*in_pos == in_size) { + // If we are requested to flush or finish the current + // Block, return LZMA_STREAM_END immediately since + // there's nothing to do. + if (action != LZMA_FINISH) + return action == LZMA_RUN + ? LZMA_OK : LZMA_STREAM_END; + + // The application had used LZMA_FULL_FLUSH to finish + // the previous Block, but now wants to finish without + // encoding new data, or it is simply creating an + // empty Stream with no Blocks. + // + // Initialize the Index encoder, and continue to + // actually encoding the Index. + return_if_error(lzma_index_encoder_init( + &coder->index_encoder, allocator, + coder->index)); + coder->sequence = SEQ_INDEX_ENCODE; + break; + } + + // Initialize the Block encoder unless it was already + // initialized by stream_encoder_init() or + // stream_encoder_update(). + if (!coder->block_encoder_is_initialized) + return_if_error(block_encoder_init(coder, allocator)); + + // Make it false so that we don't skip the initialization + // with the next Block. + coder->block_encoder_is_initialized = false; + + // Encode the Block Header. This shouldn't fail since we have + // already initialized the Block encoder. + if (lzma_block_header_encode(&coder->block_options, + coder->buffer) != LZMA_OK) + return LZMA_PROG_ERROR; + + coder->buffer_size = coder->block_options.header_size; + coder->sequence = SEQ_BLOCK_HEADER; + break; + } + + case SEQ_BLOCK_ENCODE: { + static const lzma_action convert[LZMA_ACTION_MAX + 1] = { + LZMA_RUN, + LZMA_SYNC_FLUSH, + LZMA_FINISH, + LZMA_FINISH, + LZMA_FINISH, + }; + + const lzma_ret ret = coder->block_encoder.code( + coder->block_encoder.coder, allocator, + in, in_pos, in_size, + out, out_pos, out_size, convert[action]); + if (ret != LZMA_STREAM_END || action == LZMA_SYNC_FLUSH) + return ret; + + // Add a new Index Record. + const lzma_vli unpadded_size = lzma_block_unpadded_size( + &coder->block_options); + assert(unpadded_size != 0); + return_if_error(lzma_index_append(coder->index, allocator, + unpadded_size, + coder->block_options.uncompressed_size)); + + coder->sequence = SEQ_BLOCK_INIT; + break; + } + + case SEQ_INDEX_ENCODE: { + // Call the Index encoder. It doesn't take any input, so + // those pointers can be NULL. + const lzma_ret ret = coder->index_encoder.code( + coder->index_encoder.coder, allocator, + NULL, NULL, 0, + out, out_pos, out_size, LZMA_RUN); + if (ret != LZMA_STREAM_END) + return ret; + + // Encode the Stream Footer into coder->buffer. + const lzma_stream_flags stream_flags = { + .version = 0, + .backward_size = lzma_index_size(coder->index), + .check = coder->block_options.check, + }; + + if (lzma_stream_footer_encode(&stream_flags, coder->buffer) + != LZMA_OK) + return LZMA_PROG_ERROR; + + coder->buffer_size = LZMA_STREAM_HEADER_SIZE; + coder->sequence = SEQ_STREAM_FOOTER; + break; + } + + default: + assert(0); + return LZMA_PROG_ERROR; + } + + return LZMA_OK; +} + + +static void +stream_encoder_end(void *coder_ptr, const lzma_allocator *allocator) +{ + lzma_stream_coder *coder = coder_ptr; + + lzma_next_end(&coder->block_encoder, allocator); + lzma_next_end(&coder->index_encoder, allocator); + lzma_index_end(coder->index, allocator); + + for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i) + lzma_free(coder->filters[i].options, allocator); + + lzma_free(coder, allocator); + return; +} + + +static lzma_ret +stream_encoder_update(void *coder_ptr, const lzma_allocator *allocator, + const lzma_filter *filters, + const lzma_filter *reversed_filters) +{ + lzma_stream_coder *coder = coder_ptr; + + if (coder->sequence <= SEQ_BLOCK_INIT) { + // There is no incomplete Block waiting to be finished, + // thus we can change the whole filter chain. Start by + // trying to initialize the Block encoder with the new + // chain. This way we detect if the chain is valid. + coder->block_encoder_is_initialized = false; + coder->block_options.filters = (lzma_filter *)(filters); + const lzma_ret ret = block_encoder_init(coder, allocator); + coder->block_options.filters = coder->filters; + if (ret != LZMA_OK) + return ret; + + coder->block_encoder_is_initialized = true; + + } else if (coder->sequence <= SEQ_BLOCK_ENCODE) { + // We are in the middle of a Block. Try to update only + // the filter-specific options. + return_if_error(coder->block_encoder.update( + coder->block_encoder.coder, allocator, + filters, reversed_filters)); + } else { + // Trying to update the filter chain when we are already + // encoding Index or Stream Footer. + return LZMA_PROG_ERROR; + } + + // Free the copy of the old chain and make a copy of the new chain. + for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i) + lzma_free(coder->filters[i].options, allocator); + + return lzma_filters_copy(filters, coder->filters, allocator); +} + + +static lzma_ret +stream_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter *filters, lzma_check check) +{ + lzma_next_coder_init(&stream_encoder_init, next, allocator); + + if (filters == NULL) + return LZMA_PROG_ERROR; + + lzma_stream_coder *coder = next->coder; + + if (coder == NULL) { + coder = lzma_alloc(sizeof(lzma_stream_coder), allocator); + if (coder == NULL) + return LZMA_MEM_ERROR; + + next->coder = coder; + next->code = &stream_encode; + next->end = &stream_encoder_end; + next->update = &stream_encoder_update; + + coder->filters[0].id = LZMA_VLI_UNKNOWN; + coder->block_encoder = LZMA_NEXT_CODER_INIT; + coder->index_encoder = LZMA_NEXT_CODER_INIT; + coder->index = NULL; + } + + // Basic initializations + coder->sequence = SEQ_STREAM_HEADER; + coder->block_options.version = 0; + coder->block_options.check = check; + + // Initialize the Index + lzma_index_end(coder->index, allocator); + coder->index = lzma_index_init(allocator); + if (coder->index == NULL) + return LZMA_MEM_ERROR; + + // Encode the Stream Header + lzma_stream_flags stream_flags = { + .version = 0, + .check = check, + }; + return_if_error(lzma_stream_header_encode( + &stream_flags, coder->buffer)); + + coder->buffer_pos = 0; + coder->buffer_size = LZMA_STREAM_HEADER_SIZE; + + // Initialize the Block encoder. This way we detect unsupported + // filter chains when initializing the Stream encoder instead of + // giving an error after Stream Header has already written out. + return stream_encoder_update(coder, allocator, filters, NULL); +} + + +extern LZMA_API(lzma_ret) +lzma_stream_encoder(lzma_stream *strm, + const lzma_filter *filters, lzma_check check) +{ + lzma_next_strm_init(stream_encoder_init, strm, filters, check); + + strm->internal->supported_actions[LZMA_RUN] = true; + strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true; + strm->internal->supported_actions[LZMA_FULL_FLUSH] = true; + strm->internal->supported_actions[LZMA_FULL_BARRIER] = true; + strm->internal->supported_actions[LZMA_FINISH] = true; + + return LZMA_OK; +} diff --git a/dependencies/cmliblzma/liblzma/common/stream_encoder_mt.c b/dependencies/cmliblzma/liblzma/common/stream_encoder_mt.c new file mode 100644 index 0000000..2efe44c --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/stream_encoder_mt.c @@ -0,0 +1,1143 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file stream_encoder_mt.c +/// \brief Multithreaded .xz Stream encoder +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "filter_encoder.h" +#include "easy_preset.h" +#include "block_encoder.h" +#include "block_buffer_encoder.h" +#include "index_encoder.h" +#include "outqueue.h" + + +/// Maximum supported block size. This makes it simpler to prevent integer +/// overflows if we are given unusually large block size. +#define BLOCK_SIZE_MAX (UINT64_MAX / LZMA_THREADS_MAX) + + +typedef enum { + /// Waiting for work. + THR_IDLE, + + /// Encoding is in progress. + THR_RUN, + + /// Encoding is in progress but no more input data will + /// be read. + THR_FINISH, + + /// The main thread wants the thread to stop whatever it was doing + /// but not exit. + THR_STOP, + + /// The main thread wants the thread to exit. We could use + /// cancellation but since there's stopped anyway, this is lazier. + THR_EXIT, + +} worker_state; + +typedef struct lzma_stream_coder_s lzma_stream_coder; + +typedef struct worker_thread_s worker_thread; +struct worker_thread_s { + worker_state state; + + /// Input buffer of coder->block_size bytes. The main thread will + /// put new input into this and update in_size accordingly. Once + /// no more input is coming, state will be set to THR_FINISH. + uint8_t *in; + + /// Amount of data available in the input buffer. This is modified + /// only by the main thread. + size_t in_size; + + /// Output buffer for this thread. This is set by the main + /// thread every time a new Block is started with this thread + /// structure. + lzma_outbuf *outbuf; + + /// Pointer to the main structure is needed when putting this + /// thread back to the stack of free threads. + lzma_stream_coder *coder; + + /// The allocator is set by the main thread. Since a copy of the + /// pointer is kept here, the application must not change the + /// allocator before calling lzma_end(). + const lzma_allocator *allocator; + + /// Amount of uncompressed data that has already been compressed. + uint64_t progress_in; + + /// Amount of compressed data that is ready. + uint64_t progress_out; + + /// Block encoder + lzma_next_coder block_encoder; + + /// Compression options for this Block + lzma_block block_options; + + /// Next structure in the stack of free worker threads. + worker_thread *next; + + mythread_mutex mutex; + mythread_cond cond; + + /// The ID of this thread is used to join the thread + /// when it's not needed anymore. + mythread thread_id; +}; + + +struct lzma_stream_coder_s { + enum { + SEQ_STREAM_HEADER, + SEQ_BLOCK, + SEQ_INDEX, + SEQ_STREAM_FOOTER, + } sequence; + + /// Start a new Block every block_size bytes of input unless + /// LZMA_FULL_FLUSH or LZMA_FULL_BARRIER is used earlier. + size_t block_size; + + /// The filter chain currently in use + lzma_filter filters[LZMA_FILTERS_MAX + 1]; + + + /// Index to hold sizes of the Blocks + lzma_index *index; + + /// Index encoder + lzma_next_coder index_encoder; + + + /// Stream Flags for encoding the Stream Header and Stream Footer. + lzma_stream_flags stream_flags; + + /// Buffer to hold Stream Header and Stream Footer. + uint8_t header[LZMA_STREAM_HEADER_SIZE]; + + /// Read position in header[] + size_t header_pos; + + + /// Output buffer queue for compressed data + lzma_outq outq; + + + /// Maximum wait time if cannot use all the input and cannot + /// fill the output buffer. This is in milliseconds. + uint32_t timeout; + + + /// Error code from a worker thread + lzma_ret thread_error; + + /// Array of allocated thread-specific structures + worker_thread *threads; + + /// Number of structures in "threads" above. This is also the + /// number of threads that will be created at maximum. + uint32_t threads_max; + + /// Number of thread structures that have been initialized, and + /// thus the number of worker threads actually created so far. + uint32_t threads_initialized; + + /// Stack of free threads. When a thread finishes, it puts itself + /// back into this stack. This starts as empty because threads + /// are created only when actually needed. + worker_thread *threads_free; + + /// The most recent worker thread to which the main thread writes + /// the new input from the application. + worker_thread *thr; + + + /// Amount of uncompressed data in Blocks that have already + /// been finished. + uint64_t progress_in; + + /// Amount of compressed data in Stream Header + Blocks that + /// have already been finished. + uint64_t progress_out; + + + mythread_mutex mutex; + mythread_cond cond; +}; + + +/// Tell the main thread that something has gone wrong. +static void +worker_error(worker_thread *thr, lzma_ret ret) +{ + assert(ret != LZMA_OK); + assert(ret != LZMA_STREAM_END); + + mythread_sync(thr->coder->mutex) { + if (thr->coder->thread_error == LZMA_OK) + thr->coder->thread_error = ret; + + mythread_cond_signal(&thr->coder->cond); + } + + return; +} + + +static worker_state +worker_encode(worker_thread *thr, worker_state state) +{ + assert(thr->progress_in == 0); + assert(thr->progress_out == 0); + + // Set the Block options. + thr->block_options = (lzma_block){ + .version = 0, + .check = thr->coder->stream_flags.check, + .compressed_size = thr->coder->outq.buf_size_max, + .uncompressed_size = thr->coder->block_size, + + // TODO: To allow changing the filter chain, the filters + // array must be copied to each worker_thread. + .filters = thr->coder->filters, + }; + + // Calculate maximum size of the Block Header. This amount is + // reserved in the beginning of the buffer so that Block Header + // along with Compressed Size and Uncompressed Size can be + // written there. + lzma_ret ret = lzma_block_header_size(&thr->block_options); + if (ret != LZMA_OK) { + worker_error(thr, ret); + return THR_STOP; + } + + // Initialize the Block encoder. + ret = lzma_block_encoder_init(&thr->block_encoder, + thr->allocator, &thr->block_options); + if (ret != LZMA_OK) { + worker_error(thr, ret); + return THR_STOP; + } + + size_t in_pos = 0; + size_t in_size = 0; + + thr->outbuf->size = thr->block_options.header_size; + const size_t out_size = thr->coder->outq.buf_size_max; + + do { + mythread_sync(thr->mutex) { + // Store in_pos and out_pos into *thr so that + // an application may read them via + // lzma_get_progress() to get progress information. + // + // NOTE: These aren't updated when the encoding + // finishes. Instead, the final values are taken + // later from thr->outbuf. + thr->progress_in = in_pos; + thr->progress_out = thr->outbuf->size; + + while (in_size == thr->in_size + && thr->state == THR_RUN) + mythread_cond_wait(&thr->cond, &thr->mutex); + + state = thr->state; + in_size = thr->in_size; + } + + // Return if we were asked to stop or exit. + if (state >= THR_STOP) + return state; + + lzma_action action = state == THR_FINISH + ? LZMA_FINISH : LZMA_RUN; + + // Limit the amount of input given to the Block encoder + // at once. This way this thread can react fairly quickly + // if the main thread wants us to stop or exit. + static const size_t in_chunk_max = 16384; + size_t in_limit = in_size; + if (in_size - in_pos > in_chunk_max) { + in_limit = in_pos + in_chunk_max; + action = LZMA_RUN; + } + + ret = thr->block_encoder.code( + thr->block_encoder.coder, thr->allocator, + thr->in, &in_pos, in_limit, thr->outbuf->buf, + &thr->outbuf->size, out_size, action); + } while (ret == LZMA_OK && thr->outbuf->size < out_size); + + switch (ret) { + case LZMA_STREAM_END: + assert(state == THR_FINISH); + + // Encode the Block Header. By doing it after + // the compression, we can store the Compressed Size + // and Uncompressed Size fields. + ret = lzma_block_header_encode(&thr->block_options, + thr->outbuf->buf); + if (ret != LZMA_OK) { + worker_error(thr, ret); + return THR_STOP; + } + + break; + + case LZMA_OK: + // The data was incompressible. Encode it using uncompressed + // LZMA2 chunks. + // + // First wait that we have gotten all the input. + mythread_sync(thr->mutex) { + while (thr->state == THR_RUN) + mythread_cond_wait(&thr->cond, &thr->mutex); + + state = thr->state; + in_size = thr->in_size; + } + + if (state >= THR_STOP) + return state; + + // Do the encoding. This takes care of the Block Header too. + thr->outbuf->size = 0; + ret = lzma_block_uncomp_encode(&thr->block_options, + thr->in, in_size, thr->outbuf->buf, + &thr->outbuf->size, out_size); + + // It shouldn't fail. + if (ret != LZMA_OK) { + worker_error(thr, LZMA_PROG_ERROR); + return THR_STOP; + } + + break; + + default: + worker_error(thr, ret); + return THR_STOP; + } + + // Set the size information that will be read by the main thread + // to write the Index field. + thr->outbuf->unpadded_size + = lzma_block_unpadded_size(&thr->block_options); + assert(thr->outbuf->unpadded_size != 0); + thr->outbuf->uncompressed_size = thr->block_options.uncompressed_size; + + return THR_FINISH; +} + + +static MYTHREAD_RET_TYPE +worker_start(void *thr_ptr) +{ + worker_thread *thr = thr_ptr; + worker_state state = THR_IDLE; // Init to silence a warning + + while (true) { + // Wait for work. + mythread_sync(thr->mutex) { + while (true) { + // The thread is already idle so if we are + // requested to stop, just set the state. + if (thr->state == THR_STOP) { + thr->state = THR_IDLE; + mythread_cond_signal(&thr->cond); + } + + state = thr->state; + if (state != THR_IDLE) + break; + + mythread_cond_wait(&thr->cond, &thr->mutex); + } + } + + assert(state != THR_IDLE); + assert(state != THR_STOP); + + if (state <= THR_FINISH) + state = worker_encode(thr, state); + + if (state == THR_EXIT) + break; + + // Mark the thread as idle unless the main thread has + // told us to exit. Signal is needed for the case + // where the main thread is waiting for the threads to stop. + mythread_sync(thr->mutex) { + if (thr->state != THR_EXIT) { + thr->state = THR_IDLE; + mythread_cond_signal(&thr->cond); + } + } + + mythread_sync(thr->coder->mutex) { + // Mark the output buffer as finished if + // no errors occurred. + thr->outbuf->finished = state == THR_FINISH; + + // Update the main progress info. + thr->coder->progress_in + += thr->outbuf->uncompressed_size; + thr->coder->progress_out += thr->outbuf->size; + thr->progress_in = 0; + thr->progress_out = 0; + + // Return this thread to the stack of free threads. + thr->next = thr->coder->threads_free; + thr->coder->threads_free = thr; + + mythread_cond_signal(&thr->coder->cond); + } + } + + // Exiting, free the resources. + mythread_mutex_destroy(&thr->mutex); + mythread_cond_destroy(&thr->cond); + + lzma_next_end(&thr->block_encoder, thr->allocator); + lzma_free(thr->in, thr->allocator); + return MYTHREAD_RET_VALUE; +} + + +/// Make the threads stop but not exit. Optionally wait for them to stop. +static void +threads_stop(lzma_stream_coder *coder, bool wait_for_threads) +{ + // Tell the threads to stop. + for (uint32_t i = 0; i < coder->threads_initialized; ++i) { + mythread_sync(coder->threads[i].mutex) { + coder->threads[i].state = THR_STOP; + mythread_cond_signal(&coder->threads[i].cond); + } + } + + if (!wait_for_threads) + return; + + // Wait for the threads to settle in the idle state. + for (uint32_t i = 0; i < coder->threads_initialized; ++i) { + mythread_sync(coder->threads[i].mutex) { + while (coder->threads[i].state != THR_IDLE) + mythread_cond_wait(&coder->threads[i].cond, + &coder->threads[i].mutex); + } + } + + return; +} + + +/// Stop the threads and free the resources associated with them. +/// Wait until the threads have exited. +static void +threads_end(lzma_stream_coder *coder, const lzma_allocator *allocator) +{ + for (uint32_t i = 0; i < coder->threads_initialized; ++i) { + mythread_sync(coder->threads[i].mutex) { + coder->threads[i].state = THR_EXIT; + mythread_cond_signal(&coder->threads[i].cond); + } + } + + for (uint32_t i = 0; i < coder->threads_initialized; ++i) { + int ret = mythread_join(coder->threads[i].thread_id); + assert(ret == 0); + (void)ret; + } + + lzma_free(coder->threads, allocator); + return; +} + + +/// Initialize a new worker_thread structure and create a new thread. +static lzma_ret +initialize_new_thread(lzma_stream_coder *coder, + const lzma_allocator *allocator) +{ + worker_thread *thr = &coder->threads[coder->threads_initialized]; + + thr->in = lzma_alloc(coder->block_size, allocator); + if (thr->in == NULL) + return LZMA_MEM_ERROR; + + if (mythread_mutex_init(&thr->mutex)) + goto error_mutex; + + if (mythread_cond_init(&thr->cond)) + goto error_cond; + + thr->state = THR_IDLE; + thr->allocator = allocator; + thr->coder = coder; + thr->progress_in = 0; + thr->progress_out = 0; + thr->block_encoder = LZMA_NEXT_CODER_INIT; + + if (mythread_create(&thr->thread_id, &worker_start, thr)) + goto error_thread; + + ++coder->threads_initialized; + coder->thr = thr; + + return LZMA_OK; + +error_thread: + mythread_cond_destroy(&thr->cond); + +error_cond: + mythread_mutex_destroy(&thr->mutex); + +error_mutex: + lzma_free(thr->in, allocator); + return LZMA_MEM_ERROR; +} + + +static lzma_ret +get_thread(lzma_stream_coder *coder, const lzma_allocator *allocator) +{ + // If there are no free output subqueues, there is no + // point to try getting a thread. + if (!lzma_outq_has_buf(&coder->outq)) + return LZMA_OK; + + // If there is a free structure on the stack, use it. + mythread_sync(coder->mutex) { + if (coder->threads_free != NULL) { + coder->thr = coder->threads_free; + coder->threads_free = coder->threads_free->next; + } + } + + if (coder->thr == NULL) { + // If there are no uninitialized structures left, return. + if (coder->threads_initialized == coder->threads_max) + return LZMA_OK; + + // Initialize a new thread. + return_if_error(initialize_new_thread(coder, allocator)); + } + + // Reset the parts of the thread state that have to be done + // in the main thread. + mythread_sync(coder->thr->mutex) { + coder->thr->state = THR_RUN; + coder->thr->in_size = 0; + coder->thr->outbuf = lzma_outq_get_buf(&coder->outq); + mythread_cond_signal(&coder->thr->cond); + } + + return LZMA_OK; +} + + +static lzma_ret +stream_encode_in(lzma_stream_coder *coder, const lzma_allocator *allocator, + const uint8_t *restrict in, size_t *restrict in_pos, + size_t in_size, lzma_action action) +{ + while (*in_pos < in_size + || (coder->thr != NULL && action != LZMA_RUN)) { + if (coder->thr == NULL) { + // Get a new thread. + const lzma_ret ret = get_thread(coder, allocator); + if (coder->thr == NULL) + return ret; + } + + // Copy the input data to thread's buffer. + size_t thr_in_size = coder->thr->in_size; + lzma_bufcpy(in, in_pos, in_size, coder->thr->in, + &thr_in_size, coder->block_size); + + // Tell the Block encoder to finish if + // - it has got block_size bytes of input; or + // - all input was used and LZMA_FINISH, LZMA_FULL_FLUSH, + // or LZMA_FULL_BARRIER was used. + // + // TODO: LZMA_SYNC_FLUSH and LZMA_SYNC_BARRIER. + const bool finish = thr_in_size == coder->block_size + || (*in_pos == in_size && action != LZMA_RUN); + + bool block_error = false; + + mythread_sync(coder->thr->mutex) { + if (coder->thr->state == THR_IDLE) { + // Something has gone wrong with the Block + // encoder. It has set coder->thread_error + // which we will read a few lines later. + block_error = true; + } else { + // Tell the Block encoder its new amount + // of input and update the state if needed. + coder->thr->in_size = thr_in_size; + + if (finish) + coder->thr->state = THR_FINISH; + + mythread_cond_signal(&coder->thr->cond); + } + } + + if (block_error) { + lzma_ret ret; + + mythread_sync(coder->mutex) { + ret = coder->thread_error; + } + + return ret; + } + + if (finish) + coder->thr = NULL; + } + + return LZMA_OK; +} + + +/// Wait until more input can be consumed, more output can be read, or +/// an optional timeout is reached. +static bool +wait_for_work(lzma_stream_coder *coder, mythread_condtime *wait_abs, + bool *has_blocked, bool has_input) +{ + if (coder->timeout != 0 && !*has_blocked) { + // Every time when stream_encode_mt() is called via + // lzma_code(), *has_blocked starts as false. We set it + // to true here and calculate the absolute time when + // we must return if there's nothing to do. + // + // The idea of *has_blocked is to avoid unneeded calls + // to mythread_condtime_set(), which may do a syscall + // depending on the operating system. + *has_blocked = true; + mythread_condtime_set(wait_abs, &coder->cond, coder->timeout); + } + + bool timed_out = false; + + mythread_sync(coder->mutex) { + // There are four things that we wait. If one of them + // becomes possible, we return. + // - If there is input left, we need to get a free + // worker thread and an output buffer for it. + // - Data ready to be read from the output queue. + // - A worker thread indicates an error. + // - Time out occurs. + while ((!has_input || coder->threads_free == NULL + || !lzma_outq_has_buf(&coder->outq)) + && !lzma_outq_is_readable(&coder->outq) + && coder->thread_error == LZMA_OK + && !timed_out) { + if (coder->timeout != 0) + timed_out = mythread_cond_timedwait( + &coder->cond, &coder->mutex, + wait_abs) != 0; + else + mythread_cond_wait(&coder->cond, + &coder->mutex); + } + } + + return timed_out; +} + + +static lzma_ret +stream_encode_mt(void *coder_ptr, const lzma_allocator *allocator, + const uint8_t *restrict in, size_t *restrict in_pos, + size_t in_size, uint8_t *restrict out, + size_t *restrict out_pos, size_t out_size, lzma_action action) +{ + lzma_stream_coder *coder = coder_ptr; + + switch (coder->sequence) { + case SEQ_STREAM_HEADER: + lzma_bufcpy(coder->header, &coder->header_pos, + sizeof(coder->header), + out, out_pos, out_size); + if (coder->header_pos < sizeof(coder->header)) + return LZMA_OK; + + coder->header_pos = 0; + coder->sequence = SEQ_BLOCK; + + // Fall through + + case SEQ_BLOCK: { + // Initialized to silence warnings. + lzma_vli unpadded_size = 0; + lzma_vli uncompressed_size = 0; + lzma_ret ret = LZMA_OK; + + // These are for wait_for_work(). + bool has_blocked = false; + mythread_condtime wait_abs; + + while (true) { + mythread_sync(coder->mutex) { + // Check for Block encoder errors. + ret = coder->thread_error; + if (ret != LZMA_OK) { + assert(ret != LZMA_STREAM_END); + break; + } + + // Try to read compressed data to out[]. + ret = lzma_outq_read(&coder->outq, + out, out_pos, out_size, + &unpadded_size, + &uncompressed_size); + } + + if (ret == LZMA_STREAM_END) { + // End of Block. Add it to the Index. + ret = lzma_index_append(coder->index, + allocator, unpadded_size, + uncompressed_size); + + // If we didn't fill the output buffer yet, + // try to read more data. Maybe the next + // outbuf has been finished already too. + if (*out_pos < out_size) + continue; + } + + if (ret != LZMA_OK) { + // coder->thread_error was set or + // lzma_index_append() failed. + threads_stop(coder, false); + return ret; + } + + // Try to give uncompressed data to a worker thread. + ret = stream_encode_in(coder, allocator, + in, in_pos, in_size, action); + if (ret != LZMA_OK) { + threads_stop(coder, false); + return ret; + } + + // See if we should wait or return. + // + // TODO: LZMA_SYNC_FLUSH and LZMA_SYNC_BARRIER. + if (*in_pos == in_size) { + // LZMA_RUN: More data is probably coming + // so return to let the caller fill the + // input buffer. + if (action == LZMA_RUN) + return LZMA_OK; + + // LZMA_FULL_BARRIER: The same as with + // LZMA_RUN but tell the caller that the + // barrier was completed. + if (action == LZMA_FULL_BARRIER) + return LZMA_STREAM_END; + + // Finishing or flushing isn't completed until + // all input data has been encoded and copied + // to the output buffer. + if (lzma_outq_is_empty(&coder->outq)) { + // LZMA_FINISH: Continue to encode + // the Index field. + if (action == LZMA_FINISH) + break; + + // LZMA_FULL_FLUSH: Return to tell + // the caller that flushing was + // completed. + if (action == LZMA_FULL_FLUSH) + return LZMA_STREAM_END; + } + } + + // Return if there is no output space left. + // This check must be done after testing the input + // buffer, because we might want to use a different + // return code. + if (*out_pos == out_size) + return LZMA_OK; + + // Neither in nor out has been used completely. + // Wait until there's something we can do. + if (wait_for_work(coder, &wait_abs, &has_blocked, + *in_pos < in_size)) + return LZMA_TIMED_OUT; + } + + // All Blocks have been encoded and the threads have stopped. + // Prepare to encode the Index field. + return_if_error(lzma_index_encoder_init( + &coder->index_encoder, allocator, + coder->index)); + coder->sequence = SEQ_INDEX; + + // Update the progress info to take the Index and + // Stream Footer into account. Those are very fast to encode + // so in terms of progress information they can be thought + // to be ready to be copied out. + coder->progress_out += lzma_index_size(coder->index) + + LZMA_STREAM_HEADER_SIZE; + } + + // Fall through + + case SEQ_INDEX: { + // Call the Index encoder. It doesn't take any input, so + // those pointers can be NULL. + const lzma_ret ret = coder->index_encoder.code( + coder->index_encoder.coder, allocator, + NULL, NULL, 0, + out, out_pos, out_size, LZMA_RUN); + if (ret != LZMA_STREAM_END) + return ret; + + // Encode the Stream Footer into coder->buffer. + coder->stream_flags.backward_size + = lzma_index_size(coder->index); + if (lzma_stream_footer_encode(&coder->stream_flags, + coder->header) != LZMA_OK) + return LZMA_PROG_ERROR; + + coder->sequence = SEQ_STREAM_FOOTER; + } + + // Fall through + + case SEQ_STREAM_FOOTER: + lzma_bufcpy(coder->header, &coder->header_pos, + sizeof(coder->header), + out, out_pos, out_size); + return coder->header_pos < sizeof(coder->header) + ? LZMA_OK : LZMA_STREAM_END; + } + + assert(0); + return LZMA_PROG_ERROR; +} + + +static void +stream_encoder_mt_end(void *coder_ptr, const lzma_allocator *allocator) +{ + lzma_stream_coder *coder = coder_ptr; + + // Threads must be killed before the output queue can be freed. + threads_end(coder, allocator); + lzma_outq_end(&coder->outq, allocator); + + for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i) + lzma_free(coder->filters[i].options, allocator); + + lzma_next_end(&coder->index_encoder, allocator); + lzma_index_end(coder->index, allocator); + + mythread_cond_destroy(&coder->cond); + mythread_mutex_destroy(&coder->mutex); + + lzma_free(coder, allocator); + return; +} + + +/// Options handling for lzma_stream_encoder_mt_init() and +/// lzma_stream_encoder_mt_memusage() +static lzma_ret +get_options(const lzma_mt *options, lzma_options_easy *opt_easy, + const lzma_filter **filters, uint64_t *block_size, + uint64_t *outbuf_size_max) +{ + // Validate some of the options. + if (options == NULL) + return LZMA_PROG_ERROR; + + if (options->flags != 0 || options->threads == 0 + || options->threads > LZMA_THREADS_MAX) + return LZMA_OPTIONS_ERROR; + + if (options->filters != NULL) { + // Filter chain was given, use it as is. + *filters = options->filters; + } else { + // Use a preset. + if (lzma_easy_preset(opt_easy, options->preset)) + return LZMA_OPTIONS_ERROR; + + *filters = opt_easy->filters; + } + + // Block size + if (options->block_size > 0) { + if (options->block_size > BLOCK_SIZE_MAX) + return LZMA_OPTIONS_ERROR; + + *block_size = options->block_size; + } else { + // Determine the Block size from the filter chain. + *block_size = lzma_mt_block_size(*filters); + if (*block_size == 0) + return LZMA_OPTIONS_ERROR; + + assert(*block_size <= BLOCK_SIZE_MAX); + } + + // Calculate the maximum amount output that a single output buffer + // may need to hold. This is the same as the maximum total size of + // a Block. + *outbuf_size_max = lzma_block_buffer_bound64(*block_size); + if (*outbuf_size_max == 0) + return LZMA_MEM_ERROR; + + return LZMA_OK; +} + + +static void +get_progress(void *coder_ptr, uint64_t *progress_in, uint64_t *progress_out) +{ + lzma_stream_coder *coder = coder_ptr; + + // Lock coder->mutex to prevent finishing threads from moving their + // progress info from the worker_thread structure to lzma_stream_coder. + mythread_sync(coder->mutex) { + *progress_in = coder->progress_in; + *progress_out = coder->progress_out; + + for (size_t i = 0; i < coder->threads_initialized; ++i) { + mythread_sync(coder->threads[i].mutex) { + *progress_in += coder->threads[i].progress_in; + *progress_out += coder->threads[i] + .progress_out; + } + } + } + + return; +} + + +static lzma_ret +stream_encoder_mt_init(lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_mt *options) +{ + lzma_next_coder_init(&stream_encoder_mt_init, next, allocator); + + // Get the filter chain. + lzma_options_easy easy; + const lzma_filter *filters; + uint64_t block_size; + uint64_t outbuf_size_max; + return_if_error(get_options(options, &easy, &filters, + &block_size, &outbuf_size_max)); + +#if SIZE_MAX < UINT64_MAX + if (block_size > SIZE_MAX) + return LZMA_MEM_ERROR; +#endif + + // Validate the filter chain so that we can give an error in this + // function instead of delaying it to the first call to lzma_code(). + // The memory usage calculation verifies the filter chain as + // a side effect so we take advatange of that. + if (lzma_raw_encoder_memusage(filters) == UINT64_MAX) + return LZMA_OPTIONS_ERROR; + + // Validate the Check ID. + if ((unsigned int)(options->check) > LZMA_CHECK_ID_MAX) + return LZMA_PROG_ERROR; + + if (!lzma_check_is_supported(options->check)) + return LZMA_UNSUPPORTED_CHECK; + + // Allocate and initialize the base structure if needed. + lzma_stream_coder *coder = next->coder; + if (coder == NULL) { + coder = lzma_alloc(sizeof(lzma_stream_coder), allocator); + if (coder == NULL) + return LZMA_MEM_ERROR; + + next->coder = coder; + + // For the mutex and condition variable initializations + // the error handling has to be done here because + // stream_encoder_mt_end() doesn't know if they have + // already been initialized or not. + if (mythread_mutex_init(&coder->mutex)) { + lzma_free(coder, allocator); + next->coder = NULL; + return LZMA_MEM_ERROR; + } + + if (mythread_cond_init(&coder->cond)) { + mythread_mutex_destroy(&coder->mutex); + lzma_free(coder, allocator); + next->coder = NULL; + return LZMA_MEM_ERROR; + } + + next->code = &stream_encode_mt; + next->end = &stream_encoder_mt_end; + next->get_progress = &get_progress; +// next->update = &stream_encoder_mt_update; + + coder->filters[0].id = LZMA_VLI_UNKNOWN; + coder->index_encoder = LZMA_NEXT_CODER_INIT; + coder->index = NULL; + memzero(&coder->outq, sizeof(coder->outq)); + coder->threads = NULL; + coder->threads_max = 0; + coder->threads_initialized = 0; + } + + // Basic initializations + coder->sequence = SEQ_STREAM_HEADER; + coder->block_size = (size_t)(block_size); + coder->thread_error = LZMA_OK; + coder->thr = NULL; + + // Allocate the thread-specific base structures. + assert(options->threads > 0); + if (coder->threads_max != options->threads) { + threads_end(coder, allocator); + + coder->threads = NULL; + coder->threads_max = 0; + + coder->threads_initialized = 0; + coder->threads_free = NULL; + + coder->threads = lzma_alloc( + options->threads * sizeof(worker_thread), + allocator); + if (coder->threads == NULL) + return LZMA_MEM_ERROR; + + coder->threads_max = options->threads; + } else { + // Reuse the old structures and threads. Tell the running + // threads to stop and wait until they have stopped. + threads_stop(coder, true); + } + + // Output queue + return_if_error(lzma_outq_init(&coder->outq, allocator, + outbuf_size_max, options->threads)); + + // Timeout + coder->timeout = options->timeout; + + // Free the old filter chain and copy the new one. + for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i) + lzma_free(coder->filters[i].options, allocator); + + return_if_error(lzma_filters_copy( + filters, coder->filters, allocator)); + + // Index + lzma_index_end(coder->index, allocator); + coder->index = lzma_index_init(allocator); + if (coder->index == NULL) + return LZMA_MEM_ERROR; + + // Stream Header + coder->stream_flags.version = 0; + coder->stream_flags.check = options->check; + return_if_error(lzma_stream_header_encode( + &coder->stream_flags, coder->header)); + + coder->header_pos = 0; + + // Progress info + coder->progress_in = 0; + coder->progress_out = LZMA_STREAM_HEADER_SIZE; + + return LZMA_OK; +} + + +extern LZMA_API(lzma_ret) +lzma_stream_encoder_mt(lzma_stream *strm, const lzma_mt *options) +{ + lzma_next_strm_init(stream_encoder_mt_init, strm, options); + + strm->internal->supported_actions[LZMA_RUN] = true; +// strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true; + strm->internal->supported_actions[LZMA_FULL_FLUSH] = true; + strm->internal->supported_actions[LZMA_FULL_BARRIER] = true; + strm->internal->supported_actions[LZMA_FINISH] = true; + + return LZMA_OK; +} + + +// This function name is a monster but it's consistent with the older +// monster names. :-( 31 chars is the max that C99 requires so in that +// sense it's not too long. ;-) +extern LZMA_API(uint64_t) +lzma_stream_encoder_mt_memusage(const lzma_mt *options) +{ + lzma_options_easy easy; + const lzma_filter *filters; + uint64_t block_size; + uint64_t outbuf_size_max; + + if (get_options(options, &easy, &filters, &block_size, + &outbuf_size_max) != LZMA_OK) + return UINT64_MAX; + + // Memory usage of the input buffers + const uint64_t inbuf_memusage = options->threads * block_size; + + // Memory usage of the filter encoders + uint64_t filters_memusage = lzma_raw_encoder_memusage(filters); + if (filters_memusage == UINT64_MAX) + return UINT64_MAX; + + filters_memusage *= options->threads; + + // Memory usage of the output queue + const uint64_t outq_memusage = lzma_outq_memusage( + outbuf_size_max, options->threads); + if (outq_memusage == UINT64_MAX) + return UINT64_MAX; + + // Sum them with overflow checking. + uint64_t total_memusage = LZMA_MEMUSAGE_BASE + + sizeof(lzma_stream_coder) + + options->threads * sizeof(worker_thread); + + if (UINT64_MAX - total_memusage < inbuf_memusage) + return UINT64_MAX; + + total_memusage += inbuf_memusage; + + if (UINT64_MAX - total_memusage < filters_memusage) + return UINT64_MAX; + + total_memusage += filters_memusage; + + if (UINT64_MAX - total_memusage < outq_memusage) + return UINT64_MAX; + + return total_memusage + outq_memusage; +} diff --git a/dependencies/cmliblzma/liblzma/common/stream_flags_common.c b/dependencies/cmliblzma/liblzma/common/stream_flags_common.c new file mode 100644 index 0000000..fbe8eb8 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/stream_flags_common.c @@ -0,0 +1,47 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file stream_flags_common.c +/// \brief Common stuff for Stream flags coders +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "stream_flags_common.h" + + +const uint8_t lzma_header_magic[6] = { 0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00 }; +const uint8_t lzma_footer_magic[2] = { 0x59, 0x5A }; + + +extern LZMA_API(lzma_ret) +lzma_stream_flags_compare( + const lzma_stream_flags *a, const lzma_stream_flags *b) +{ + // We can compare only version 0 structures. + if (a->version != 0 || b->version != 0) + return LZMA_OPTIONS_ERROR; + + // Check type + if ((unsigned int)(a->check) > LZMA_CHECK_ID_MAX + || (unsigned int)(b->check) > LZMA_CHECK_ID_MAX) + return LZMA_PROG_ERROR; + + if (a->check != b->check) + return LZMA_DATA_ERROR; + + // Backward Sizes are compared only if they are known in both. + if (a->backward_size != LZMA_VLI_UNKNOWN + && b->backward_size != LZMA_VLI_UNKNOWN) { + if (!is_backward_size_valid(a) || !is_backward_size_valid(b)) + return LZMA_PROG_ERROR; + + if (a->backward_size != b->backward_size) + return LZMA_DATA_ERROR; + } + + return LZMA_OK; +} diff --git a/dependencies/cmliblzma/liblzma/common/stream_flags_common.h b/dependencies/cmliblzma/liblzma/common/stream_flags_common.h new file mode 100644 index 0000000..9f3122a --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/stream_flags_common.h @@ -0,0 +1,33 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file stream_flags_common.h +/// \brief Common stuff for Stream flags coders +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_STREAM_FLAGS_COMMON_H +#define LZMA_STREAM_FLAGS_COMMON_H + +#include "common.h" + +/// Size of the Stream Flags field +#define LZMA_STREAM_FLAGS_SIZE 2 + +extern const uint8_t lzma_header_magic[6]; +extern const uint8_t lzma_footer_magic[2]; + + +static inline bool +is_backward_size_valid(const lzma_stream_flags *options) +{ + return options->backward_size >= LZMA_BACKWARD_SIZE_MIN + && options->backward_size <= LZMA_BACKWARD_SIZE_MAX + && (options->backward_size & 3) == 0; +} + +#endif diff --git a/dependencies/cmliblzma/liblzma/common/stream_flags_decoder.c b/dependencies/cmliblzma/liblzma/common/stream_flags_decoder.c new file mode 100644 index 0000000..1bc2f97 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/stream_flags_decoder.c @@ -0,0 +1,82 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file stream_flags_decoder.c +/// \brief Decodes Stream Header and Stream Footer from .xz files +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "stream_flags_common.h" + + +static bool +stream_flags_decode(lzma_stream_flags *options, const uint8_t *in) +{ + // Reserved bits must be unset. + if (in[0] != 0x00 || (in[1] & 0xF0)) + return true; + + options->version = 0; + options->check = in[1] & 0x0F; + + return false; +} + + +extern LZMA_API(lzma_ret) +lzma_stream_header_decode(lzma_stream_flags *options, const uint8_t *in) +{ + // Magic + if (memcmp(in, lzma_header_magic, sizeof(lzma_header_magic)) != 0) + return LZMA_FORMAT_ERROR; + + // Verify the CRC32 so we can distinguish between corrupt + // and unsupported files. + const uint32_t crc = lzma_crc32(in + sizeof(lzma_header_magic), + LZMA_STREAM_FLAGS_SIZE, 0); + if (crc != unaligned_read32le(in + sizeof(lzma_header_magic) + + LZMA_STREAM_FLAGS_SIZE)) + return LZMA_DATA_ERROR; + + // Stream Flags + if (stream_flags_decode(options, in + sizeof(lzma_header_magic))) + return LZMA_OPTIONS_ERROR; + + // Set Backward Size to indicate unknown value. That way + // lzma_stream_flags_compare() can be used to compare Stream Header + // and Stream Footer while keeping it useful also for comparing + // two Stream Footers. + options->backward_size = LZMA_VLI_UNKNOWN; + + return LZMA_OK; +} + + +extern LZMA_API(lzma_ret) +lzma_stream_footer_decode(lzma_stream_flags *options, const uint8_t *in) +{ + // Magic + if (memcmp(in + sizeof(uint32_t) * 2 + LZMA_STREAM_FLAGS_SIZE, + lzma_footer_magic, sizeof(lzma_footer_magic)) != 0) + return LZMA_FORMAT_ERROR; + + // CRC32 + const uint32_t crc = lzma_crc32(in + sizeof(uint32_t), + sizeof(uint32_t) + LZMA_STREAM_FLAGS_SIZE, 0); + if (crc != unaligned_read32le(in)) + return LZMA_DATA_ERROR; + + // Stream Flags + if (stream_flags_decode(options, in + sizeof(uint32_t) * 2)) + return LZMA_OPTIONS_ERROR; + + // Backward Size + options->backward_size = unaligned_read32le(in + sizeof(uint32_t)); + options->backward_size = (options->backward_size + 1) * 4; + + return LZMA_OK; +} diff --git a/dependencies/cmliblzma/liblzma/common/stream_flags_encoder.c b/dependencies/cmliblzma/liblzma/common/stream_flags_encoder.c new file mode 100644 index 0000000..4e71715 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/stream_flags_encoder.c @@ -0,0 +1,86 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file stream_flags_encoder.c +/// \brief Encodes Stream Header and Stream Footer for .xz files +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "stream_flags_common.h" + + +static bool +stream_flags_encode(const lzma_stream_flags *options, uint8_t *out) +{ + if ((unsigned int)(options->check) > LZMA_CHECK_ID_MAX) + return true; + + out[0] = 0x00; + out[1] = options->check; + + return false; +} + + +extern LZMA_API(lzma_ret) +lzma_stream_header_encode(const lzma_stream_flags *options, uint8_t *out) +{ + assert(sizeof(lzma_header_magic) + LZMA_STREAM_FLAGS_SIZE + + 4 == LZMA_STREAM_HEADER_SIZE); + + if (options->version != 0) + return LZMA_OPTIONS_ERROR; + + // Magic + memcpy(out, lzma_header_magic, sizeof(lzma_header_magic)); + + // Stream Flags + if (stream_flags_encode(options, out + sizeof(lzma_header_magic))) + return LZMA_PROG_ERROR; + + // CRC32 of the Stream Header + const uint32_t crc = lzma_crc32(out + sizeof(lzma_header_magic), + LZMA_STREAM_FLAGS_SIZE, 0); + + unaligned_write32le(out + sizeof(lzma_header_magic) + + LZMA_STREAM_FLAGS_SIZE, crc); + + return LZMA_OK; +} + + +extern LZMA_API(lzma_ret) +lzma_stream_footer_encode(const lzma_stream_flags *options, uint8_t *out) +{ + assert(2 * 4 + LZMA_STREAM_FLAGS_SIZE + sizeof(lzma_footer_magic) + == LZMA_STREAM_HEADER_SIZE); + + if (options->version != 0) + return LZMA_OPTIONS_ERROR; + + // Backward Size + if (!is_backward_size_valid(options)) + return LZMA_PROG_ERROR; + + unaligned_write32le(out + 4, options->backward_size / 4 - 1); + + // Stream Flags + if (stream_flags_encode(options, out + 2 * 4)) + return LZMA_PROG_ERROR; + + // CRC32 + const uint32_t crc = lzma_crc32( + out + 4, 4 + LZMA_STREAM_FLAGS_SIZE, 0); + + unaligned_write32le(out, crc); + + // Magic + memcpy(out + 2 * 4 + LZMA_STREAM_FLAGS_SIZE, + lzma_footer_magic, sizeof(lzma_footer_magic)); + + return LZMA_OK; +} diff --git a/dependencies/cmliblzma/liblzma/common/vli_decoder.c b/dependencies/cmliblzma/liblzma/common/vli_decoder.c new file mode 100644 index 0000000..c181828 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/vli_decoder.c @@ -0,0 +1,86 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file vli_decoder.c +/// \brief Decodes variable-length integers +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "common.h" + + +extern LZMA_API(lzma_ret) +lzma_vli_decode(lzma_vli *restrict vli, size_t *vli_pos, + const uint8_t *restrict in, size_t *restrict in_pos, + size_t in_size) +{ + // If we haven't been given vli_pos, work in single-call mode. + size_t vli_pos_internal = 0; + if (vli_pos == NULL) { + vli_pos = &vli_pos_internal; + *vli = 0; + + // If there's no input, use LZMA_DATA_ERROR. This way it is + // easy to decode VLIs from buffers that have known size, + // and get the correct error code in case the buffer is + // too short. + if (*in_pos >= in_size) + return LZMA_DATA_ERROR; + + } else { + // Initialize *vli when starting to decode a new integer. + if (*vli_pos == 0) + *vli = 0; + + // Validate the arguments. + if (*vli_pos >= LZMA_VLI_BYTES_MAX + || (*vli >> (*vli_pos * 7)) != 0) + return LZMA_PROG_ERROR;; + + if (*in_pos >= in_size) + return LZMA_BUF_ERROR; + } + + do { + // Read the next byte. Use a temporary variable so that we + // can update *in_pos immediately. + const uint8_t byte = in[*in_pos]; + ++*in_pos; + + // Add the newly read byte to *vli. + *vli += (lzma_vli)(byte & 0x7F) << (*vli_pos * 7); + ++*vli_pos; + + // Check if this is the last byte of a multibyte integer. + if ((byte & 0x80) == 0) { + // We don't allow using variable-length integers as + // padding i.e. the encoding must use the most the + // compact form. + if (byte == 0x00 && *vli_pos > 1) + return LZMA_DATA_ERROR; + + return vli_pos == &vli_pos_internal + ? LZMA_OK : LZMA_STREAM_END; + } + + // There is at least one more byte coming. If we have already + // read maximum number of bytes, the integer is considered + // corrupt. + // + // If we need bigger integers in future, old versions liblzma + // will confusingly indicate the file being corrupt istead of + // unsupported. I suppose it's still better this way, because + // in the foreseeable future (writing this in 2008) the only + // reason why files would appear having over 63-bit integers + // is that the files are simply corrupt. + if (*vli_pos == LZMA_VLI_BYTES_MAX) + return LZMA_DATA_ERROR; + + } while (*in_pos < in_size); + + return vli_pos == &vli_pos_internal ? LZMA_DATA_ERROR : LZMA_OK; +} diff --git a/dependencies/cmliblzma/liblzma/common/vli_encoder.c b/dependencies/cmliblzma/liblzma/common/vli_encoder.c new file mode 100644 index 0000000..f864269 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/vli_encoder.c @@ -0,0 +1,69 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file vli_encoder.c +/// \brief Encodes variable-length integers +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "common.h" + + +extern LZMA_API(lzma_ret) +lzma_vli_encode(lzma_vli vli, size_t *vli_pos, + uint8_t *restrict out, size_t *restrict out_pos, + size_t out_size) +{ + // If we haven't been given vli_pos, work in single-call mode. + size_t vli_pos_internal = 0; + if (vli_pos == NULL) { + vli_pos = &vli_pos_internal; + + // In single-call mode, we expect that the caller has + // reserved enough output space. + if (*out_pos >= out_size) + return LZMA_PROG_ERROR; + } else { + // This never happens when we are called by liblzma, but + // may happen if called directly from an application. + if (*out_pos >= out_size) + return LZMA_BUF_ERROR; + } + + // Validate the arguments. + if (*vli_pos >= LZMA_VLI_BYTES_MAX || vli > LZMA_VLI_MAX) + return LZMA_PROG_ERROR; + + // Shift vli so that the next bits to encode are the lowest. In + // single-call mode this never changes vli since *vli_pos is zero. + vli >>= *vli_pos * 7; + + // Write the non-last bytes in a loop. + while (vli >= 0x80) { + // We don't need *vli_pos during this function call anymore, + // but update it here so that it is ready if we need to + // return before the whole integer has been decoded. + ++*vli_pos; + assert(*vli_pos < LZMA_VLI_BYTES_MAX); + + // Write the next byte. + out[*out_pos] = (uint8_t)(vli) | 0x80; + vli >>= 7; + + if (++*out_pos == out_size) + return vli_pos == &vli_pos_internal + ? LZMA_PROG_ERROR : LZMA_OK; + } + + // Write the last byte. + out[*out_pos] = (uint8_t)(vli); + ++*out_pos; + ++*vli_pos; + + return vli_pos == &vli_pos_internal ? LZMA_OK : LZMA_STREAM_END; + +} diff --git a/dependencies/cmliblzma/liblzma/common/vli_size.c b/dependencies/cmliblzma/liblzma/common/vli_size.c new file mode 100644 index 0000000..ec1b4fa --- /dev/null +++ b/dependencies/cmliblzma/liblzma/common/vli_size.c @@ -0,0 +1,30 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file vli_size.c +/// \brief Calculates the encoded size of a variable-length integer +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "common.h" + + +extern LZMA_API(uint32_t) +lzma_vli_size(lzma_vli vli) +{ + if (vli > LZMA_VLI_MAX) + return 0; + + uint32_t i = 0; + do { + vli >>= 7; + ++i; + } while (vli != 0); + + assert(i <= LZMA_VLI_BYTES_MAX); + return i; +} diff --git a/dependencies/cmliblzma/liblzma/delta/delta_common.c b/dependencies/cmliblzma/liblzma/delta/delta_common.c new file mode 100644 index 0000000..4768201 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/delta/delta_common.c @@ -0,0 +1,73 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file delta_common.c +/// \brief Common stuff for Delta encoder and decoder +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "delta_common.h" +#include "delta_private.h" + + +static void +delta_coder_end(void *coder_ptr, const lzma_allocator *allocator) +{ + lzma_delta_coder *coder = coder_ptr; + lzma_next_end(&coder->next, allocator); + lzma_free(coder, allocator); + return; +} + + +extern lzma_ret +lzma_delta_coder_init(lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter_info *filters) +{ + // Allocate memory for the decoder if needed. + lzma_delta_coder *coder = next->coder; + if (coder == NULL) { + coder = lzma_alloc(sizeof(lzma_delta_coder), allocator); + if (coder == NULL) + return LZMA_MEM_ERROR; + + next->coder = coder; + + // End function is the same for encoder and decoder. + next->end = &delta_coder_end; + coder->next = LZMA_NEXT_CODER_INIT; + } + + // Validate the options. + if (lzma_delta_coder_memusage(filters[0].options) == UINT64_MAX) + return LZMA_OPTIONS_ERROR; + + // Set the delta distance. + const lzma_options_delta *opt = filters[0].options; + coder->distance = opt->dist; + + // Initialize the rest of the variables. + coder->pos = 0; + memzero(coder->history, LZMA_DELTA_DIST_MAX); + + // Initialize the next decoder in the chain, if any. + return lzma_next_filter_init(&coder->next, allocator, filters + 1); +} + + +extern uint64_t +lzma_delta_coder_memusage(const void *options) +{ + const lzma_options_delta *opt = options; + + if (opt == NULL || opt->type != LZMA_DELTA_TYPE_BYTE + || opt->dist < LZMA_DELTA_DIST_MIN + || opt->dist > LZMA_DELTA_DIST_MAX) + return UINT64_MAX; + + return sizeof(lzma_delta_coder); +} diff --git a/dependencies/cmliblzma/liblzma/delta/delta_common.h b/dependencies/cmliblzma/liblzma/delta/delta_common.h new file mode 100644 index 0000000..7e7e1ba --- /dev/null +++ b/dependencies/cmliblzma/liblzma/delta/delta_common.h @@ -0,0 +1,20 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file delta_common.h +/// \brief Common stuff for Delta encoder and decoder +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_DELTA_COMMON_H +#define LZMA_DELTA_COMMON_H + +#include "common.h" + +extern uint64_t lzma_delta_coder_memusage(const void *options); + +#endif diff --git a/dependencies/cmliblzma/liblzma/delta/delta_decoder.c b/dependencies/cmliblzma/liblzma/delta/delta_decoder.c new file mode 100644 index 0000000..6859afa --- /dev/null +++ b/dependencies/cmliblzma/liblzma/delta/delta_decoder.c @@ -0,0 +1,78 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file delta_decoder.c +/// \brief Delta filter decoder +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "delta_decoder.h" +#include "delta_private.h" + + +static void +decode_buffer(lzma_delta_coder *coder, uint8_t *buffer, size_t size) +{ + const size_t distance = coder->distance; + + for (size_t i = 0; i < size; ++i) { + buffer[i] += coder->history[(distance + coder->pos) & 0xFF]; + coder->history[coder->pos-- & 0xFF] = buffer[i]; + } +} + + +static lzma_ret +delta_decode(void *coder_ptr, const lzma_allocator *allocator, + const uint8_t *restrict in, size_t *restrict in_pos, + size_t in_size, uint8_t *restrict out, + size_t *restrict out_pos, size_t out_size, lzma_action action) +{ + lzma_delta_coder *coder = coder_ptr; + + assert(coder->next.code != NULL); + + const size_t out_start = *out_pos; + + const lzma_ret ret = coder->next.code(coder->next.coder, allocator, + in, in_pos, in_size, out, out_pos, out_size, + action); + + decode_buffer(coder, out + out_start, *out_pos - out_start); + + return ret; +} + + +extern lzma_ret +lzma_delta_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter_info *filters) +{ + next->code = &delta_decode; + return lzma_delta_coder_init(next, allocator, filters); +} + + +extern lzma_ret +lzma_delta_props_decode(void **options, const lzma_allocator *allocator, + const uint8_t *props, size_t props_size) +{ + if (props_size != 1) + return LZMA_OPTIONS_ERROR; + + lzma_options_delta *opt + = lzma_alloc(sizeof(lzma_options_delta), allocator); + if (opt == NULL) + return LZMA_MEM_ERROR; + + opt->type = LZMA_DELTA_TYPE_BYTE; + opt->dist = props[0] + 1; + + *options = opt; + + return LZMA_OK; +} diff --git a/dependencies/cmliblzma/liblzma/delta/delta_decoder.h b/dependencies/cmliblzma/liblzma/delta/delta_decoder.h new file mode 100644 index 0000000..ad89cc6 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/delta/delta_decoder.h @@ -0,0 +1,26 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file delta_decoder.h +/// \brief Delta filter decoder +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_DELTA_DECODER_H +#define LZMA_DELTA_DECODER_H + +#include "delta_common.h" + +extern lzma_ret lzma_delta_decoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters); + +extern lzma_ret lzma_delta_props_decode( + void **options, const lzma_allocator *allocator, + const uint8_t *props, size_t props_size); + +#endif diff --git a/dependencies/cmliblzma/liblzma/delta/delta_encoder.c b/dependencies/cmliblzma/liblzma/delta/delta_encoder.c new file mode 100644 index 0000000..3841651 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/delta/delta_encoder.c @@ -0,0 +1,125 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file delta_encoder.c +/// \brief Delta filter encoder +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "delta_encoder.h" +#include "delta_private.h" + + +/// Copies and encodes the data at the same time. This is used when Delta +/// is the first filter in the chain (and thus the last filter in the +/// encoder's filter stack). +static void +copy_and_encode(lzma_delta_coder *coder, + const uint8_t *restrict in, uint8_t *restrict out, size_t size) +{ + const size_t distance = coder->distance; + + for (size_t i = 0; i < size; ++i) { + const uint8_t tmp = coder->history[ + (distance + coder->pos) & 0xFF]; + coder->history[coder->pos-- & 0xFF] = in[i]; + out[i] = in[i] - tmp; + } +} + + +/// Encodes the data in place. This is used when we are the last filter +/// in the chain (and thus non-last filter in the encoder's filter stack). +static void +encode_in_place(lzma_delta_coder *coder, uint8_t *buffer, size_t size) +{ + const size_t distance = coder->distance; + + for (size_t i = 0; i < size; ++i) { + const uint8_t tmp = coder->history[ + (distance + coder->pos) & 0xFF]; + coder->history[coder->pos-- & 0xFF] = buffer[i]; + buffer[i] -= tmp; + } +} + + +static lzma_ret +delta_encode(void *coder_ptr, const lzma_allocator *allocator, + const uint8_t *restrict in, size_t *restrict in_pos, + size_t in_size, uint8_t *restrict out, + size_t *restrict out_pos, size_t out_size, lzma_action action) +{ + lzma_delta_coder *coder = coder_ptr; + + lzma_ret ret; + + if (coder->next.code == NULL) { + const size_t in_avail = in_size - *in_pos; + const size_t out_avail = out_size - *out_pos; + const size_t size = my_min(in_avail, out_avail); + + copy_and_encode(coder, in + *in_pos, out + *out_pos, size); + + *in_pos += size; + *out_pos += size; + + ret = action != LZMA_RUN && *in_pos == in_size + ? LZMA_STREAM_END : LZMA_OK; + + } else { + const size_t out_start = *out_pos; + + ret = coder->next.code(coder->next.coder, allocator, + in, in_pos, in_size, out, out_pos, out_size, + action); + + encode_in_place(coder, out + out_start, *out_pos - out_start); + } + + return ret; +} + + +static lzma_ret +delta_encoder_update(void *coder_ptr, const lzma_allocator *allocator, + const lzma_filter *filters_null lzma_attribute((__unused__)), + const lzma_filter *reversed_filters) +{ + lzma_delta_coder *coder = coder_ptr; + + // Delta doesn't and will never support changing the options in + // the middle of encoding. If the app tries to change them, we + // simply ignore them. + return lzma_next_filter_update( + &coder->next, allocator, reversed_filters + 1); +} + + +extern lzma_ret +lzma_delta_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter_info *filters) +{ + next->code = &delta_encode; + next->update = &delta_encoder_update; + return lzma_delta_coder_init(next, allocator, filters); +} + + +extern lzma_ret +lzma_delta_props_encode(const void *options, uint8_t *out) +{ + // The caller must have already validated the options, so it's + // LZMA_PROG_ERROR if they are invalid. + if (lzma_delta_coder_memusage(options) == UINT64_MAX) + return LZMA_PROG_ERROR; + + const lzma_options_delta *opt = options; + out[0] = opt->dist - LZMA_DELTA_DIST_MIN; + + return LZMA_OK; +} diff --git a/dependencies/cmliblzma/liblzma/delta/delta_encoder.h b/dependencies/cmliblzma/liblzma/delta/delta_encoder.h new file mode 100644 index 0000000..4ab9847 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/delta/delta_encoder.h @@ -0,0 +1,24 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file delta_encoder.h +/// \brief Delta filter encoder +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_DELTA_ENCODER_H +#define LZMA_DELTA_ENCODER_H + +#include "delta_common.h" + +extern lzma_ret lzma_delta_encoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters); + +extern lzma_ret lzma_delta_props_encode(const void *options, uint8_t *out); + +#endif diff --git a/dependencies/cmliblzma/liblzma/delta/delta_private.h b/dependencies/cmliblzma/liblzma/delta/delta_private.h new file mode 100644 index 0000000..0d6cb38 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/delta/delta_private.h @@ -0,0 +1,37 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file delta_private.h +/// \brief Private common stuff for Delta encoder and decoder +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_DELTA_PRIVATE_H +#define LZMA_DELTA_PRIVATE_H + +#include "delta_common.h" + +typedef struct { + /// Next coder in the chain + lzma_next_coder next; + + /// Delta distance + size_t distance; + + /// Position in history[] + uint8_t pos; + + /// Buffer to hold history of the original data + uint8_t history[LZMA_DELTA_DIST_MAX]; +} lzma_delta_coder; + + +extern lzma_ret lzma_delta_coder_init( + lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter_info *filters); + +#endif diff --git a/dependencies/cmliblzma/liblzma/liblzma.pc.in b/dependencies/cmliblzma/liblzma/liblzma.pc.in new file mode 100644 index 0000000..9fa4891 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/liblzma.pc.in @@ -0,0 +1,19 @@ +# +# Author: Lasse Collin +# +# This file has been put into the public domain. +# You can do whatever you want with this file. +# + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: liblzma +Description: General purpose data compression library +URL: @PACKAGE_URL@ +Version: @PACKAGE_VERSION@ +Cflags: -I${includedir} +Libs: -L${libdir} -llzma +Libs.private: @PTHREAD_CFLAGS@ @LIBS@ diff --git a/dependencies/cmliblzma/liblzma/liblzma_w32res.rc b/dependencies/cmliblzma/liblzma/liblzma_w32res.rc new file mode 100644 index 0000000..773caf8 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/liblzma_w32res.rc @@ -0,0 +1,14 @@ +/* + * Author: Lasse Collin + * + * This file has been put into the public domain. + * You can do whatever you want with this file. + */ + +#define MY_TYPE VFT_DLL +#define MY_NAME "liblzma" +#define MY_SUFFIX ".dll" +#define MY_DESC "liblzma data compression library" +#define PACKAGE_NAME "XZ Utils" +#define PACKAGE_URL "http://tukaani.org/xz/" +#include "common_w32res.rc" diff --git a/dependencies/cmliblzma/liblzma/lz/lz_decoder.c b/dependencies/cmliblzma/liblzma/lz/lz_decoder.c new file mode 100644 index 0000000..c708644 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/lz/lz_decoder.c @@ -0,0 +1,306 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file lz_decoder.c +/// \brief LZ out window +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +// liblzma supports multiple LZ77-based filters. The LZ part is shared +// between these filters. The LZ code takes care of dictionary handling +// and passing the data between filters in the chain. The filter-specific +// part decodes from the input buffer to the dictionary. + + +#include "lz_decoder.h" + + +typedef struct { + /// Dictionary (history buffer) + lzma_dict dict; + + /// The actual LZ-based decoder e.g. LZMA + lzma_lz_decoder lz; + + /// Next filter in the chain, if any. Note that LZMA and LZMA2 are + /// only allowed as the last filter, but the long-range filter in + /// future can be in the middle of the chain. + lzma_next_coder next; + + /// True if the next filter in the chain has returned LZMA_STREAM_END. + bool next_finished; + + /// True if the LZ decoder (e.g. LZMA) has detected end of payload + /// marker. This may become true before next_finished becomes true. + bool this_finished; + + /// Temporary buffer needed when the LZ-based filter is not the last + /// filter in the chain. The output of the next filter is first + /// decoded into buffer[], which is then used as input for the actual + /// LZ-based decoder. + struct { + size_t pos; + size_t size; + uint8_t buffer[LZMA_BUFFER_SIZE]; + } temp; +} lzma_coder; + + +static void +lz_decoder_reset(lzma_coder *coder) +{ + coder->dict.pos = 0; + coder->dict.full = 0; + coder->dict.buf[coder->dict.size - 1] = '\0'; + coder->dict.need_reset = false; + return; +} + + +static lzma_ret +decode_buffer(lzma_coder *coder, + const uint8_t *restrict in, size_t *restrict in_pos, + size_t in_size, uint8_t *restrict out, + size_t *restrict out_pos, size_t out_size) +{ + while (true) { + // Wrap the dictionary if needed. + if (coder->dict.pos == coder->dict.size) + coder->dict.pos = 0; + + // Store the current dictionary position. It is needed to know + // where to start copying to the out[] buffer. + const size_t dict_start = coder->dict.pos; + + // Calculate how much we allow coder->lz.code() to decode. + // It must not decode past the end of the dictionary + // buffer, and we don't want it to decode more than is + // actually needed to fill the out[] buffer. + coder->dict.limit = coder->dict.pos + + my_min(out_size - *out_pos, + coder->dict.size - coder->dict.pos); + + // Call the coder->lz.code() to do the actual decoding. + const lzma_ret ret = coder->lz.code( + coder->lz.coder, &coder->dict, + in, in_pos, in_size); + + // Copy the decoded data from the dictionary to the out[] + // buffer. + const size_t copy_size = coder->dict.pos - dict_start; + assert(copy_size <= out_size - *out_pos); + memcpy(out + *out_pos, coder->dict.buf + dict_start, + copy_size); + *out_pos += copy_size; + + // Reset the dictionary if so requested by coder->lz.code(). + if (coder->dict.need_reset) { + lz_decoder_reset(coder); + + // Since we reset dictionary, we don't check if + // dictionary became full. + if (ret != LZMA_OK || *out_pos == out_size) + return ret; + } else { + // Return if everything got decoded or an error + // occurred, or if there's no more data to decode. + // + // Note that detecting if there's something to decode + // is done by looking if dictionary become full + // instead of looking if *in_pos == in_size. This + // is because it is possible that all the input was + // consumed already but some data is pending to be + // written to the dictionary. + if (ret != LZMA_OK || *out_pos == out_size + || coder->dict.pos < coder->dict.size) + return ret; + } + } +} + + +static lzma_ret +lz_decode(void *coder_ptr, + const lzma_allocator *allocator lzma_attribute((__unused__)), + const uint8_t *restrict in, size_t *restrict in_pos, + size_t in_size, uint8_t *restrict out, + size_t *restrict out_pos, size_t out_size, + lzma_action action) +{ + lzma_coder *coder = coder_ptr; + + if (coder->next.code == NULL) + return decode_buffer(coder, in, in_pos, in_size, + out, out_pos, out_size); + + // We aren't the last coder in the chain, we need to decode + // our input to a temporary buffer. + while (*out_pos < out_size) { + // Fill the temporary buffer if it is empty. + if (!coder->next_finished + && coder->temp.pos == coder->temp.size) { + coder->temp.pos = 0; + coder->temp.size = 0; + + const lzma_ret ret = coder->next.code( + coder->next.coder, + allocator, in, in_pos, in_size, + coder->temp.buffer, &coder->temp.size, + LZMA_BUFFER_SIZE, action); + + if (ret == LZMA_STREAM_END) + coder->next_finished = true; + else if (ret != LZMA_OK || coder->temp.size == 0) + return ret; + } + + if (coder->this_finished) { + if (coder->temp.size != 0) + return LZMA_DATA_ERROR; + + if (coder->next_finished) + return LZMA_STREAM_END; + + return LZMA_OK; + } + + const lzma_ret ret = decode_buffer(coder, coder->temp.buffer, + &coder->temp.pos, coder->temp.size, + out, out_pos, out_size); + + if (ret == LZMA_STREAM_END) + coder->this_finished = true; + else if (ret != LZMA_OK) + return ret; + else if (coder->next_finished && *out_pos < out_size) + return LZMA_DATA_ERROR; + } + + return LZMA_OK; +} + + +static void +lz_decoder_end(void *coder_ptr, const lzma_allocator *allocator) +{ + lzma_coder *coder = coder_ptr; + + lzma_next_end(&coder->next, allocator); + lzma_free(coder->dict.buf, allocator); + + if (coder->lz.end != NULL) + coder->lz.end(coder->lz.coder, allocator); + else + lzma_free(coder->lz.coder, allocator); + + lzma_free(coder, allocator); + return; +} + + +extern lzma_ret +lzma_lz_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter_info *filters, + lzma_ret (*lz_init)(lzma_lz_decoder *lz, + const lzma_allocator *allocator, const void *options, + lzma_lz_options *lz_options)) +{ + // Allocate the base structure if it isn't already allocated. + lzma_coder *coder = next->coder; + if (coder == NULL) { + coder = lzma_alloc(sizeof(lzma_coder), allocator); + if (coder == NULL) + return LZMA_MEM_ERROR; + + next->coder = coder; + next->code = &lz_decode; + next->end = &lz_decoder_end; + + coder->dict.buf = NULL; + coder->dict.size = 0; + coder->lz = LZMA_LZ_DECODER_INIT; + coder->next = LZMA_NEXT_CODER_INIT; + } + + // Allocate and initialize the LZ-based decoder. It will also give + // us the dictionary size. + lzma_lz_options lz_options; + return_if_error(lz_init(&coder->lz, allocator, + filters[0].options, &lz_options)); + + // If the dictionary size is very small, increase it to 4096 bytes. + // This is to prevent constant wrapping of the dictionary, which + // would slow things down. The downside is that since we don't check + // separately for the real dictionary size, we may happily accept + // corrupt files. + if (lz_options.dict_size < 4096) + lz_options.dict_size = 4096; + + // Make dictionary size a multipe of 16. Some LZ-based decoders like + // LZMA use the lowest bits lzma_dict.pos to know the alignment of the + // data. Aligned buffer is also good when memcpying from the + // dictionary to the output buffer, since applications are + // recommended to give aligned buffers to liblzma. + // + // Avoid integer overflow. + if (lz_options.dict_size > SIZE_MAX - 15) + return LZMA_MEM_ERROR; + + lz_options.dict_size = (lz_options.dict_size + 15) & ~((size_t)(15)); + + // Allocate and initialize the dictionary. + if (coder->dict.size != lz_options.dict_size) { + lzma_free(coder->dict.buf, allocator); + coder->dict.buf + = lzma_alloc(lz_options.dict_size, allocator); + if (coder->dict.buf == NULL) + return LZMA_MEM_ERROR; + + coder->dict.size = lz_options.dict_size; + } + + lz_decoder_reset(next->coder); + + // Use the preset dictionary if it was given to us. + if (lz_options.preset_dict != NULL + && lz_options.preset_dict_size > 0) { + // If the preset dictionary is bigger than the actual + // dictionary, copy only the tail. + const size_t copy_size = my_min(lz_options.preset_dict_size, + lz_options.dict_size); + const size_t offset = lz_options.preset_dict_size - copy_size; + memcpy(coder->dict.buf, lz_options.preset_dict + offset, + copy_size); + coder->dict.pos = copy_size; + coder->dict.full = copy_size; + } + + // Miscellaneous initializations + coder->next_finished = false; + coder->this_finished = false; + coder->temp.pos = 0; + coder->temp.size = 0; + + // Initialize the next filter in the chain, if any. + return lzma_next_filter_init(&coder->next, allocator, filters + 1); +} + + +extern uint64_t +lzma_lz_decoder_memusage(size_t dictionary_size) +{ + return sizeof(lzma_coder) + (uint64_t)(dictionary_size); +} + + +extern void +lzma_lz_decoder_uncompressed(void *coder_ptr, lzma_vli uncompressed_size) +{ + lzma_coder *coder = coder_ptr; + coder->lz.set_uncompressed(coder->lz.coder, uncompressed_size); +} diff --git a/dependencies/cmliblzma/liblzma/lz/lz_decoder.h b/dependencies/cmliblzma/liblzma/lz/lz_decoder.h new file mode 100644 index 0000000..754ccf3 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/lz/lz_decoder.h @@ -0,0 +1,234 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file lz_decoder.h +/// \brief LZ out window +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_LZ_DECODER_H +#define LZMA_LZ_DECODER_H + +#include "common.h" + + +typedef struct { + /// Pointer to the dictionary buffer. It can be an allocated buffer + /// internal to liblzma, or it can a be a buffer given by the + /// application when in single-call mode (not implemented yet). + uint8_t *buf; + + /// Write position in dictionary. The next byte will be written to + /// buf[pos]. + size_t pos; + + /// Indicates how full the dictionary is. This is used by + /// dict_is_distance_valid() to detect corrupt files that would + /// read beyond the beginning of the dictionary. + size_t full; + + /// Write limit + size_t limit; + + /// Size of the dictionary + size_t size; + + /// True when dictionary should be reset before decoding more data. + bool need_reset; + +} lzma_dict; + + +typedef struct { + size_t dict_size; + const uint8_t *preset_dict; + size_t preset_dict_size; +} lzma_lz_options; + + +typedef struct { + /// Data specific to the LZ-based decoder + void *coder; + + /// Function to decode from in[] to *dict + lzma_ret (*code)(void *coder, + lzma_dict *restrict dict, const uint8_t *restrict in, + size_t *restrict in_pos, size_t in_size); + + void (*reset)(void *coder, const void *options); + + /// Set the uncompressed size + void (*set_uncompressed)(void *coder, lzma_vli uncompressed_size); + + /// Free allocated resources + void (*end)(void *coder, const lzma_allocator *allocator); + +} lzma_lz_decoder; + + +#define LZMA_LZ_DECODER_INIT \ + (lzma_lz_decoder){ \ + .coder = NULL, \ + .code = NULL, \ + .reset = NULL, \ + .set_uncompressed = NULL, \ + .end = NULL, \ + } + + +extern lzma_ret lzma_lz_decoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters, + lzma_ret (*lz_init)(lzma_lz_decoder *lz, + const lzma_allocator *allocator, const void *options, + lzma_lz_options *lz_options)); + +extern uint64_t lzma_lz_decoder_memusage(size_t dictionary_size); + +extern void lzma_lz_decoder_uncompressed( + void *coder, lzma_vli uncompressed_size); + + +////////////////////// +// Inline functions // +////////////////////// + +/// Get a byte from the history buffer. +static inline uint8_t +dict_get(const lzma_dict *const dict, const uint32_t distance) +{ + return dict->buf[dict->pos - distance - 1 + + (distance < dict->pos ? 0 : dict->size)]; +} + + +/// Test if dictionary is empty. +static inline bool +dict_is_empty(const lzma_dict *const dict) +{ + return dict->full == 0; +} + + +/// Validate the match distance +static inline bool +dict_is_distance_valid(const lzma_dict *const dict, const size_t distance) +{ + return dict->full > distance; +} + + +/// Repeat *len bytes at distance. +static inline bool +dict_repeat(lzma_dict *dict, uint32_t distance, uint32_t *len) +{ + // Don't write past the end of the dictionary. + const size_t dict_avail = dict->limit - dict->pos; + uint32_t left = my_min(dict_avail, *len); + *len -= left; + + // Repeat a block of data from the history. Because memcpy() is faster + // than copying byte by byte in a loop, the copying process gets split + // into three cases. + if (distance < left) { + // Source and target areas overlap, thus we can't use + // memcpy() nor even memmove() safely. + do { + dict->buf[dict->pos] = dict_get(dict, distance); + ++dict->pos; + } while (--left > 0); + + } else if (distance < dict->pos) { + // The easiest and fastest case + memcpy(dict->buf + dict->pos, + dict->buf + dict->pos - distance - 1, + left); + dict->pos += left; + + } else { + // The bigger the dictionary, the more rare this + // case occurs. We need to "wrap" the dict, thus + // we might need two memcpy() to copy all the data. + assert(dict->full == dict->size); + const uint32_t copy_pos + = dict->pos - distance - 1 + dict->size; + uint32_t copy_size = dict->size - copy_pos; + + if (copy_size < left) { + memmove(dict->buf + dict->pos, dict->buf + copy_pos, + copy_size); + dict->pos += copy_size; + copy_size = left - copy_size; + memcpy(dict->buf + dict->pos, dict->buf, copy_size); + dict->pos += copy_size; + } else { + memmove(dict->buf + dict->pos, dict->buf + copy_pos, + left); + dict->pos += left; + } + } + + // Update how full the dictionary is. + if (dict->full < dict->pos) + dict->full = dict->pos; + + return unlikely(*len != 0); +} + + +/// Puts one byte into the dictionary. Returns true if the dictionary was +/// already full and the byte couldn't be added. +static inline bool +dict_put(lzma_dict *dict, uint8_t byte) +{ + if (unlikely(dict->pos == dict->limit)) + return true; + + dict->buf[dict->pos++] = byte; + + if (dict->pos > dict->full) + dict->full = dict->pos; + + return false; +} + + +/// Copies arbitrary amount of data into the dictionary. +static inline void +dict_write(lzma_dict *restrict dict, const uint8_t *restrict in, + size_t *restrict in_pos, size_t in_size, + size_t *restrict left) +{ + // NOTE: If we are being given more data than the size of the + // dictionary, it could be possible to optimize the LZ decoder + // so that not everything needs to go through the dictionary. + // This shouldn't be very common thing in practice though, and + // the slowdown of one extra memcpy() isn't bad compared to how + // much time it would have taken if the data were compressed. + + if (in_size - *in_pos > *left) + in_size = *in_pos + *left; + + *left -= lzma_bufcpy(in, in_pos, in_size, + dict->buf, &dict->pos, dict->limit); + + if (dict->pos > dict->full) + dict->full = dict->pos; + + return; +} + + +static inline void +dict_reset(lzma_dict *dict) +{ + dict->need_reset = true; + return; +} + +#endif diff --git a/dependencies/cmliblzma/liblzma/lz/lz_encoder.c b/dependencies/cmliblzma/liblzma/lz/lz_encoder.c new file mode 100644 index 0000000..9a74b7c --- /dev/null +++ b/dependencies/cmliblzma/liblzma/lz/lz_encoder.c @@ -0,0 +1,616 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file lz_encoder.c +/// \brief LZ in window +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "lz_encoder.h" +#include "lz_encoder_hash.h" + +// See lz_encoder_hash.h. This is a bit hackish but avoids making +// endianness a conditional in makefiles. +#if defined(WORDS_BIGENDIAN) && !defined(HAVE_SMALL) +# include "lz_encoder_hash_table.h" +#endif + +#include "memcmplen.h" + + +typedef struct { + /// LZ-based encoder e.g. LZMA + lzma_lz_encoder lz; + + /// History buffer and match finder + lzma_mf mf; + + /// Next coder in the chain + lzma_next_coder next; +} lzma_coder; + + +/// \brief Moves the data in the input window to free space for new data +/// +/// mf->buffer is a sliding input window, which keeps mf->keep_size_before +/// bytes of input history available all the time. Now and then we need to +/// "slide" the buffer to make space for the new data to the end of the +/// buffer. At the same time, data older than keep_size_before is dropped. +/// +static void +move_window(lzma_mf *mf) +{ + // Align the move to a multiple of 16 bytes. Some LZ-based encoders + // like LZMA use the lowest bits of mf->read_pos to know the + // alignment of the uncompressed data. We also get better speed + // for memmove() with aligned buffers. + assert(mf->read_pos > mf->keep_size_before); + const uint32_t move_offset + = (mf->read_pos - mf->keep_size_before) & ~UINT32_C(15); + + assert(mf->write_pos > move_offset); + const size_t move_size = mf->write_pos - move_offset; + + assert(move_offset + move_size <= mf->size); + + memmove(mf->buffer, mf->buffer + move_offset, move_size); + + mf->offset += move_offset; + mf->read_pos -= move_offset; + mf->read_limit -= move_offset; + mf->write_pos -= move_offset; + + return; +} + + +/// \brief Tries to fill the input window (mf->buffer) +/// +/// If we are the last encoder in the chain, our input data is in in[]. +/// Otherwise we call the next filter in the chain to process in[] and +/// write its output to mf->buffer. +/// +/// This function must not be called once it has returned LZMA_STREAM_END. +/// +static lzma_ret +fill_window(lzma_coder *coder, const lzma_allocator *allocator, + const uint8_t *in, size_t *in_pos, size_t in_size, + lzma_action action) +{ + assert(coder->mf.read_pos <= coder->mf.write_pos); + + // Move the sliding window if needed. + if (coder->mf.read_pos >= coder->mf.size - coder->mf.keep_size_after) + move_window(&coder->mf); + + // Maybe this is ugly, but lzma_mf uses uint32_t for most things + // (which I find cleanest), but we need size_t here when filling + // the history window. + size_t write_pos = coder->mf.write_pos; + lzma_ret ret; + if (coder->next.code == NULL) { + // Not using a filter, simply memcpy() as much as possible. + lzma_bufcpy(in, in_pos, in_size, coder->mf.buffer, + &write_pos, coder->mf.size); + + ret = action != LZMA_RUN && *in_pos == in_size + ? LZMA_STREAM_END : LZMA_OK; + + } else { + ret = coder->next.code(coder->next.coder, allocator, + in, in_pos, in_size, + coder->mf.buffer, &write_pos, + coder->mf.size, action); + } + + coder->mf.write_pos = write_pos; + + // Silence Valgrind. lzma_memcmplen() can read extra bytes + // and Valgrind will give warnings if those bytes are uninitialized + // because Valgrind cannot see that the values of the uninitialized + // bytes are eventually ignored. + memzero(coder->mf.buffer + write_pos, LZMA_MEMCMPLEN_EXTRA); + + // If end of stream has been reached or flushing completed, we allow + // the encoder to process all the input (that is, read_pos is allowed + // to reach write_pos). Otherwise we keep keep_size_after bytes + // available as prebuffer. + if (ret == LZMA_STREAM_END) { + assert(*in_pos == in_size); + ret = LZMA_OK; + coder->mf.action = action; + coder->mf.read_limit = coder->mf.write_pos; + + } else if (coder->mf.write_pos > coder->mf.keep_size_after) { + // This needs to be done conditionally, because if we got + // only little new input, there may be too little input + // to do any encoding yet. + coder->mf.read_limit = coder->mf.write_pos + - coder->mf.keep_size_after; + } + + // Restart the match finder after finished LZMA_SYNC_FLUSH. + if (coder->mf.pending > 0 + && coder->mf.read_pos < coder->mf.read_limit) { + // Match finder may update coder->pending and expects it to + // start from zero, so use a temporary variable. + const uint32_t pending = coder->mf.pending; + coder->mf.pending = 0; + + // Rewind read_pos so that the match finder can hash + // the pending bytes. + assert(coder->mf.read_pos >= pending); + coder->mf.read_pos -= pending; + + // Call the skip function directly instead of using + // mf_skip(), since we don't want to touch mf->read_ahead. + coder->mf.skip(&coder->mf, pending); + } + + return ret; +} + + +static lzma_ret +lz_encode(void *coder_ptr, const lzma_allocator *allocator, + const uint8_t *restrict in, size_t *restrict in_pos, + size_t in_size, + uint8_t *restrict out, size_t *restrict out_pos, + size_t out_size, lzma_action action) +{ + lzma_coder *coder = coder_ptr; + + while (*out_pos < out_size + && (*in_pos < in_size || action != LZMA_RUN)) { + // Read more data to coder->mf.buffer if needed. + if (coder->mf.action == LZMA_RUN && coder->mf.read_pos + >= coder->mf.read_limit) + return_if_error(fill_window(coder, allocator, + in, in_pos, in_size, action)); + + // Encode + const lzma_ret ret = coder->lz.code(coder->lz.coder, + &coder->mf, out, out_pos, out_size); + if (ret != LZMA_OK) { + // Setting this to LZMA_RUN for cases when we are + // flushing. It doesn't matter when finishing or if + // an error occurred. + coder->mf.action = LZMA_RUN; + return ret; + } + } + + return LZMA_OK; +} + + +static bool +lz_encoder_prepare(lzma_mf *mf, const lzma_allocator *allocator, + const lzma_lz_options *lz_options) +{ + // For now, the dictionary size is limited to 1.5 GiB. This may grow + // in the future if needed, but it needs a little more work than just + // changing this check. + if (lz_options->dict_size < LZMA_DICT_SIZE_MIN + || lz_options->dict_size + > (UINT32_C(1) << 30) + (UINT32_C(1) << 29) + || lz_options->nice_len > lz_options->match_len_max) + return true; + + mf->keep_size_before = lz_options->before_size + lz_options->dict_size; + + mf->keep_size_after = lz_options->after_size + + lz_options->match_len_max; + + // To avoid constant memmove()s, allocate some extra space. Since + // memmove()s become more expensive when the size of the buffer + // increases, we reserve more space when a large dictionary is + // used to make the memmove() calls rarer. + // + // This works with dictionaries up to about 3 GiB. If bigger + // dictionary is wanted, some extra work is needed: + // - Several variables in lzma_mf have to be changed from uint32_t + // to size_t. + // - Memory usage calculation needs something too, e.g. use uint64_t + // for mf->size. + uint32_t reserve = lz_options->dict_size / 2; + if (reserve > (UINT32_C(1) << 30)) + reserve /= 2; + + reserve += (lz_options->before_size + lz_options->match_len_max + + lz_options->after_size) / 2 + (UINT32_C(1) << 19); + + const uint32_t old_size = mf->size; + mf->size = mf->keep_size_before + reserve + mf->keep_size_after; + + // Deallocate the old history buffer if it exists but has different + // size than what is needed now. + if (mf->buffer != NULL && old_size != mf->size) { + lzma_free(mf->buffer, allocator); + mf->buffer = NULL; + } + + // Match finder options + mf->match_len_max = lz_options->match_len_max; + mf->nice_len = lz_options->nice_len; + + // cyclic_size has to stay smaller than 2 Gi. Note that this doesn't + // mean limiting dictionary size to less than 2 GiB. With a match + // finder that uses multibyte resolution (hashes start at e.g. every + // fourth byte), cyclic_size would stay below 2 Gi even when + // dictionary size is greater than 2 GiB. + // + // It would be possible to allow cyclic_size >= 2 Gi, but then we + // would need to be careful to use 64-bit types in various places + // (size_t could do since we would need bigger than 32-bit address + // space anyway). It would also require either zeroing a multigigabyte + // buffer at initialization (waste of time and RAM) or allow + // normalization in lz_encoder_mf.c to access uninitialized + // memory to keep the code simpler. The current way is simple and + // still allows pretty big dictionaries, so I don't expect these + // limits to change. + mf->cyclic_size = lz_options->dict_size + 1; + + // Validate the match finder ID and setup the function pointers. + switch (lz_options->match_finder) { +#ifdef HAVE_MF_HC3 + case LZMA_MF_HC3: + mf->find = &lzma_mf_hc3_find; + mf->skip = &lzma_mf_hc3_skip; + break; +#endif +#ifdef HAVE_MF_HC4 + case LZMA_MF_HC4: + mf->find = &lzma_mf_hc4_find; + mf->skip = &lzma_mf_hc4_skip; + break; +#endif +#ifdef HAVE_MF_BT2 + case LZMA_MF_BT2: + mf->find = &lzma_mf_bt2_find; + mf->skip = &lzma_mf_bt2_skip; + break; +#endif +#ifdef HAVE_MF_BT3 + case LZMA_MF_BT3: + mf->find = &lzma_mf_bt3_find; + mf->skip = &lzma_mf_bt3_skip; + break; +#endif +#ifdef HAVE_MF_BT4 + case LZMA_MF_BT4: + mf->find = &lzma_mf_bt4_find; + mf->skip = &lzma_mf_bt4_skip; + break; +#endif + + default: + return true; + } + + // Calculate the sizes of mf->hash and mf->son and check that + // nice_len is big enough for the selected match finder. + const uint32_t hash_bytes = lz_options->match_finder & 0x0F; + if (hash_bytes > mf->nice_len) + return true; + + const bool is_bt = (lz_options->match_finder & 0x10) != 0; + uint32_t hs; + + if (hash_bytes == 2) { + hs = 0xFFFF; + } else { + // Round dictionary size up to the next 2^n - 1 so it can + // be used as a hash mask. + hs = lz_options->dict_size - 1; + hs |= hs >> 1; + hs |= hs >> 2; + hs |= hs >> 4; + hs |= hs >> 8; + hs >>= 1; + hs |= 0xFFFF; + + if (hs > (UINT32_C(1) << 24)) { + if (hash_bytes == 3) + hs = (UINT32_C(1) << 24) - 1; + else + hs >>= 1; + } + } + + mf->hash_mask = hs; + + ++hs; + if (hash_bytes > 2) + hs += HASH_2_SIZE; + if (hash_bytes > 3) + hs += HASH_3_SIZE; +/* + No match finder uses this at the moment. + if (mf->hash_bytes > 4) + hs += HASH_4_SIZE; +*/ + + const uint32_t old_hash_count = mf->hash_count; + const uint32_t old_sons_count = mf->sons_count; + mf->hash_count = hs; + mf->sons_count = mf->cyclic_size; + if (is_bt) + mf->sons_count *= 2; + + // Deallocate the old hash array if it exists and has different size + // than what is needed now. + if (old_hash_count != mf->hash_count + || old_sons_count != mf->sons_count) { + lzma_free(mf->hash, allocator); + mf->hash = NULL; + + lzma_free(mf->son, allocator); + mf->son = NULL; + } + + // Maximum number of match finder cycles + mf->depth = lz_options->depth; + if (mf->depth == 0) { + if (is_bt) + mf->depth = 16 + mf->nice_len / 2; + else + mf->depth = 4 + mf->nice_len / 4; + } + + return false; +} + + +static bool +lz_encoder_init(lzma_mf *mf, const lzma_allocator *allocator, + const lzma_lz_options *lz_options) +{ + // Allocate the history buffer. + if (mf->buffer == NULL) { + // lzma_memcmplen() is used for the dictionary buffer + // so we need to allocate a few extra bytes to prevent + // it from reading past the end of the buffer. + mf->buffer = lzma_alloc(mf->size + LZMA_MEMCMPLEN_EXTRA, + allocator); + if (mf->buffer == NULL) + return true; + + // Keep Valgrind happy with lzma_memcmplen() and initialize + // the extra bytes whose value may get read but which will + // effectively get ignored. + memzero(mf->buffer + mf->size, LZMA_MEMCMPLEN_EXTRA); + } + + // Use cyclic_size as initial mf->offset. This allows + // avoiding a few branches in the match finders. The downside is + // that match finder needs to be normalized more often, which may + // hurt performance with huge dictionaries. + mf->offset = mf->cyclic_size; + mf->read_pos = 0; + mf->read_ahead = 0; + mf->read_limit = 0; + mf->write_pos = 0; + mf->pending = 0; + +#if UINT32_MAX >= SIZE_MAX / 4 + // Check for integer overflow. (Huge dictionaries are not + // possible on 32-bit CPU.) + if (mf->hash_count > SIZE_MAX / sizeof(uint32_t) + || mf->sons_count > SIZE_MAX / sizeof(uint32_t)) + return true; +#endif + + // Allocate and initialize the hash table. Since EMPTY_HASH_VALUE + // is zero, we can use lzma_alloc_zero() or memzero() for mf->hash. + // + // We don't need to initialize mf->son, but not doing that may + // make Valgrind complain in normalization (see normalize() in + // lz_encoder_mf.c). Skipping the initialization is *very* good + // when big dictionary is used but only small amount of data gets + // actually compressed: most of the mf->son won't get actually + // allocated by the kernel, so we avoid wasting RAM and improve + // initialization speed a lot. + if (mf->hash == NULL) { + mf->hash = lzma_alloc_zero(mf->hash_count * sizeof(uint32_t), + allocator); + mf->son = lzma_alloc(mf->sons_count * sizeof(uint32_t), + allocator); + + if (mf->hash == NULL || mf->son == NULL) { + lzma_free(mf->hash, allocator); + mf->hash = NULL; + + lzma_free(mf->son, allocator); + mf->son = NULL; + + return true; + } + } else { +/* + for (uint32_t i = 0; i < mf->hash_count; ++i) + mf->hash[i] = EMPTY_HASH_VALUE; +*/ + memzero(mf->hash, mf->hash_count * sizeof(uint32_t)); + } + + mf->cyclic_pos = 0; + + // Handle preset dictionary. + if (lz_options->preset_dict != NULL + && lz_options->preset_dict_size > 0) { + // If the preset dictionary is bigger than the actual + // dictionary, use only the tail. + mf->write_pos = my_min(lz_options->preset_dict_size, mf->size); + memcpy(mf->buffer, lz_options->preset_dict + + lz_options->preset_dict_size - mf->write_pos, + mf->write_pos); + mf->action = LZMA_SYNC_FLUSH; + mf->skip(mf, mf->write_pos); + } + + mf->action = LZMA_RUN; + + return false; +} + + +extern uint64_t +lzma_lz_encoder_memusage(const lzma_lz_options *lz_options) +{ + // Old buffers must not exist when calling lz_encoder_prepare(). + lzma_mf mf = { + .buffer = NULL, + .hash = NULL, + .son = NULL, + .hash_count = 0, + .sons_count = 0, + }; + + // Setup the size information into mf. + if (lz_encoder_prepare(&mf, NULL, lz_options)) + return UINT64_MAX; + + // Calculate the memory usage. + return ((uint64_t)(mf.hash_count) + mf.sons_count) * sizeof(uint32_t) + + mf.size + sizeof(lzma_coder); +} + + +static void +lz_encoder_end(void *coder_ptr, const lzma_allocator *allocator) +{ + lzma_coder *coder = coder_ptr; + + lzma_next_end(&coder->next, allocator); + + lzma_free(coder->mf.son, allocator); + lzma_free(coder->mf.hash, allocator); + lzma_free(coder->mf.buffer, allocator); + + if (coder->lz.end != NULL) + coder->lz.end(coder->lz.coder, allocator); + else + lzma_free(coder->lz.coder, allocator); + + lzma_free(coder, allocator); + return; +} + + +static lzma_ret +lz_encoder_update(void *coder_ptr, const lzma_allocator *allocator, + const lzma_filter *filters_null lzma_attribute((__unused__)), + const lzma_filter *reversed_filters) +{ + lzma_coder *coder = coder_ptr; + + if (coder->lz.options_update == NULL) + return LZMA_PROG_ERROR; + + return_if_error(coder->lz.options_update( + coder->lz.coder, reversed_filters)); + + return lzma_next_filter_update( + &coder->next, allocator, reversed_filters + 1); +} + + +extern lzma_ret +lzma_lz_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter_info *filters, + lzma_ret (*lz_init)(lzma_lz_encoder *lz, + const lzma_allocator *allocator, const void *options, + lzma_lz_options *lz_options)) +{ +#ifdef HAVE_SMALL + // We need that the CRC32 table has been initialized. + lzma_crc32_init(); +#endif + + // Allocate and initialize the base data structure. + lzma_coder *coder = next->coder; + if (coder == NULL) { + coder = lzma_alloc(sizeof(lzma_coder), allocator); + if (coder == NULL) + return LZMA_MEM_ERROR; + + next->coder = coder; + next->code = &lz_encode; + next->end = &lz_encoder_end; + next->update = &lz_encoder_update; + + coder->lz.coder = NULL; + coder->lz.code = NULL; + coder->lz.end = NULL; + + // mf.size is initialized to silence Valgrind + // when used on optimized binaries (GCC may reorder + // code in a way that Valgrind gets unhappy). + coder->mf.buffer = NULL; + coder->mf.size = 0; + coder->mf.hash = NULL; + coder->mf.son = NULL; + coder->mf.hash_count = 0; + coder->mf.sons_count = 0; + + coder->next = LZMA_NEXT_CODER_INIT; + } + + // Initialize the LZ-based encoder. + lzma_lz_options lz_options; + return_if_error(lz_init(&coder->lz, allocator, + filters[0].options, &lz_options)); + + // Setup the size information into coder->mf and deallocate + // old buffers if they have wrong size. + if (lz_encoder_prepare(&coder->mf, allocator, &lz_options)) + return LZMA_OPTIONS_ERROR; + + // Allocate new buffers if needed, and do the rest of + // the initialization. + if (lz_encoder_init(&coder->mf, allocator, &lz_options)) + return LZMA_MEM_ERROR; + + // Initialize the next filter in the chain, if any. + return lzma_next_filter_init(&coder->next, allocator, filters + 1); +} + + +extern LZMA_API(lzma_bool) +lzma_mf_is_supported(lzma_match_finder mf) +{ + bool ret = false; + +#ifdef HAVE_MF_HC3 + if (mf == LZMA_MF_HC3) + ret = true; +#endif + +#ifdef HAVE_MF_HC4 + if (mf == LZMA_MF_HC4) + ret = true; +#endif + +#ifdef HAVE_MF_BT2 + if (mf == LZMA_MF_BT2) + ret = true; +#endif + +#ifdef HAVE_MF_BT3 + if (mf == LZMA_MF_BT3) + ret = true; +#endif + +#ifdef HAVE_MF_BT4 + if (mf == LZMA_MF_BT4) + ret = true; +#endif + + return ret; +} diff --git a/dependencies/cmliblzma/liblzma/lz/lz_encoder.h b/dependencies/cmliblzma/liblzma/lz/lz_encoder.h new file mode 100644 index 0000000..426dcd8 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/lz/lz_encoder.h @@ -0,0 +1,327 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file lz_encoder.h +/// \brief LZ in window and match finder API +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_LZ_ENCODER_H +#define LZMA_LZ_ENCODER_H + +#include "common.h" + + +/// A table of these is used by the LZ-based encoder to hold +/// the length-distance pairs found by the match finder. +typedef struct { + uint32_t len; + uint32_t dist; +} lzma_match; + + +typedef struct lzma_mf_s lzma_mf; +struct lzma_mf_s { + /////////////// + // In Window // + /////////////// + + /// Pointer to buffer with data to be compressed + uint8_t *buffer; + + /// Total size of the allocated buffer (that is, including all + /// the extra space) + uint32_t size; + + /// Number of bytes that must be kept available in our input history. + /// That is, once keep_size_before bytes have been processed, + /// buffer[read_pos - keep_size_before] is the oldest byte that + /// must be available for reading. + uint32_t keep_size_before; + + /// Number of bytes that must be kept in buffer after read_pos. + /// That is, read_pos <= write_pos - keep_size_after as long as + /// action is LZMA_RUN; when action != LZMA_RUN, read_pos is allowed + /// to reach write_pos so that the last bytes get encoded too. + uint32_t keep_size_after; + + /// Match finders store locations of matches using 32-bit integers. + /// To avoid adjusting several megabytes of integers every time the + /// input window is moved with move_window, we only adjust the + /// offset of the buffer. Thus, buffer[value_in_hash_table - offset] + /// is the byte pointed by value_in_hash_table. + uint32_t offset; + + /// buffer[read_pos] is the next byte to run through the match + /// finder. This is incremented in the match finder once the byte + /// has been processed. + uint32_t read_pos; + + /// Number of bytes that have been ran through the match finder, but + /// which haven't been encoded by the LZ-based encoder yet. + uint32_t read_ahead; + + /// As long as read_pos is less than read_limit, there is enough + /// input available in buffer for at least one encoding loop. + /// + /// Because of the stateful API, read_limit may and will get greater + /// than read_pos quite often. This is taken into account when + /// calculating the value for keep_size_after. + uint32_t read_limit; + + /// buffer[write_pos] is the first byte that doesn't contain valid + /// uncompressed data; that is, the next input byte will be copied + /// to buffer[write_pos]. + uint32_t write_pos; + + /// Number of bytes not hashed before read_pos. This is needed to + /// restart the match finder after LZMA_SYNC_FLUSH. + uint32_t pending; + + ////////////////// + // Match Finder // + ////////////////// + + /// Find matches. Returns the number of distance-length pairs written + /// to the matches array. This is called only via lzma_mf_find(). + uint32_t (*find)(lzma_mf *mf, lzma_match *matches); + + /// Skips num bytes. This is like find() but doesn't make the + /// distance-length pairs available, thus being a little faster. + /// This is called only via mf_skip(). + void (*skip)(lzma_mf *mf, uint32_t num); + + uint32_t *hash; + uint32_t *son; + uint32_t cyclic_pos; + uint32_t cyclic_size; // Must be dictionary size + 1. + uint32_t hash_mask; + + /// Maximum number of loops in the match finder + uint32_t depth; + + /// Maximum length of a match that the match finder will try to find. + uint32_t nice_len; + + /// Maximum length of a match supported by the LZ-based encoder. + /// If the longest match found by the match finder is nice_len, + /// mf_find() tries to expand it up to match_len_max bytes. + uint32_t match_len_max; + + /// When running out of input, binary tree match finders need to know + /// if it is due to flushing or finishing. The action is used also + /// by the LZ-based encoders themselves. + lzma_action action; + + /// Number of elements in hash[] + uint32_t hash_count; + + /// Number of elements in son[] + uint32_t sons_count; +}; + + +typedef struct { + /// Extra amount of data to keep available before the "actual" + /// dictionary. + size_t before_size; + + /// Size of the history buffer + size_t dict_size; + + /// Extra amount of data to keep available after the "actual" + /// dictionary. + size_t after_size; + + /// Maximum length of a match that the LZ-based encoder can accept. + /// This is used to extend matches of length nice_len to the + /// maximum possible length. + size_t match_len_max; + + /// Match finder will search matches up to this length. + /// This must be less than or equal to match_len_max. + size_t nice_len; + + /// Type of the match finder to use + lzma_match_finder match_finder; + + /// Maximum search depth + uint32_t depth; + + /// TODO: Comment + const uint8_t *preset_dict; + + uint32_t preset_dict_size; + +} lzma_lz_options; + + +// The total usable buffer space at any moment outside the match finder: +// before_size + dict_size + after_size + match_len_max +// +// In reality, there's some extra space allocated to prevent the number of +// memmove() calls reasonable. The bigger the dict_size is, the bigger +// this extra buffer will be since with bigger dictionaries memmove() would +// also take longer. +// +// A single encoder loop in the LZ-based encoder may call the match finder +// (mf_find() or mf_skip()) at most after_size times. In other words, +// a single encoder loop may increment lzma_mf.read_pos at most after_size +// times. Since matches are looked up to +// lzma_mf.buffer[lzma_mf.read_pos + match_len_max - 1], the total +// amount of extra buffer needed after dict_size becomes +// after_size + match_len_max. +// +// before_size has two uses. The first one is to keep literals available +// in cases when the LZ-based encoder has made some read ahead. +// TODO: Maybe this could be changed by making the LZ-based encoders to +// store the actual literals as they do with length-distance pairs. +// +// Algorithms such as LZMA2 first try to compress a chunk, and then check +// if the encoded result is smaller than the uncompressed one. If the chunk +// was uncompressible, it is better to store it in uncompressed form in +// the output stream. To do this, the whole uncompressed chunk has to be +// still available in the history buffer. before_size achieves that. + + +typedef struct { + /// Data specific to the LZ-based encoder + void *coder; + + /// Function to encode from *dict to out[] + lzma_ret (*code)(void *coder, + lzma_mf *restrict mf, uint8_t *restrict out, + size_t *restrict out_pos, size_t out_size); + + /// Free allocated resources + void (*end)(void *coder, const lzma_allocator *allocator); + + /// Update the options in the middle of the encoding. + lzma_ret (*options_update)(void *coder, const lzma_filter *filter); + +} lzma_lz_encoder; + + +// Basic steps: +// 1. Input gets copied into the dictionary. +// 2. Data in dictionary gets run through the match finder byte by byte. +// 3. The literals and matches are encoded using e.g. LZMA. +// +// The bytes that have been ran through the match finder, but not encoded yet, +// are called `read ahead'. + + +/// Get pointer to the first byte not ran through the match finder +static inline const uint8_t * +mf_ptr(const lzma_mf *mf) +{ + return mf->buffer + mf->read_pos; +} + + +/// Get the number of bytes that haven't been ran through the match finder yet. +static inline uint32_t +mf_avail(const lzma_mf *mf) +{ + return mf->write_pos - mf->read_pos; +} + + +/// Get the number of bytes that haven't been encoded yet (some of these +/// bytes may have been ran through the match finder though). +static inline uint32_t +mf_unencoded(const lzma_mf *mf) +{ + return mf->write_pos - mf->read_pos + mf->read_ahead; +} + + +/// Calculate the absolute offset from the beginning of the most recent +/// dictionary reset. Only the lowest four bits are important, so there's no +/// problem that we don't know the 64-bit size of the data encoded so far. +/// +/// NOTE: When moving the input window, we need to do it so that the lowest +/// bits of dict->read_pos are not modified to keep this macro working +/// as intended. +static inline uint32_t +mf_position(const lzma_mf *mf) +{ + return mf->read_pos - mf->read_ahead; +} + + +/// Since everything else begins with mf_, use it also for lzma_mf_find(). +#define mf_find lzma_mf_find + + +/// Skip the given number of bytes. This is used when a good match was found. +/// For example, if mf_find() finds a match of 200 bytes long, the first byte +/// of that match was already consumed by mf_find(), and the rest 199 bytes +/// have to be skipped with mf_skip(mf, 199). +static inline void +mf_skip(lzma_mf *mf, uint32_t amount) +{ + if (amount != 0) { + mf->skip(mf, amount); + mf->read_ahead += amount; + } +} + + +/// Copies at most *left number of bytes from the history buffer +/// to out[]. This is needed by LZMA2 to encode uncompressed chunks. +static inline void +mf_read(lzma_mf *mf, uint8_t *out, size_t *out_pos, size_t out_size, + size_t *left) +{ + const size_t out_avail = out_size - *out_pos; + const size_t copy_size = my_min(out_avail, *left); + + assert(mf->read_ahead == 0); + assert(mf->read_pos >= *left); + + memcpy(out + *out_pos, mf->buffer + mf->read_pos - *left, + copy_size); + + *out_pos += copy_size; + *left -= copy_size; + return; +} + + +extern lzma_ret lzma_lz_encoder_init( + lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter_info *filters, + lzma_ret (*lz_init)(lzma_lz_encoder *lz, + const lzma_allocator *allocator, const void *options, + lzma_lz_options *lz_options)); + + +extern uint64_t lzma_lz_encoder_memusage(const lzma_lz_options *lz_options); + + +// These are only for LZ encoder's internal use. +extern uint32_t lzma_mf_find( + lzma_mf *mf, uint32_t *count, lzma_match *matches); + +extern uint32_t lzma_mf_hc3_find(lzma_mf *dict, lzma_match *matches); +extern void lzma_mf_hc3_skip(lzma_mf *dict, uint32_t amount); + +extern uint32_t lzma_mf_hc4_find(lzma_mf *dict, lzma_match *matches); +extern void lzma_mf_hc4_skip(lzma_mf *dict, uint32_t amount); + +extern uint32_t lzma_mf_bt2_find(lzma_mf *dict, lzma_match *matches); +extern void lzma_mf_bt2_skip(lzma_mf *dict, uint32_t amount); + +extern uint32_t lzma_mf_bt3_find(lzma_mf *dict, lzma_match *matches); +extern void lzma_mf_bt3_skip(lzma_mf *dict, uint32_t amount); + +extern uint32_t lzma_mf_bt4_find(lzma_mf *dict, lzma_match *matches); +extern void lzma_mf_bt4_skip(lzma_mf *dict, uint32_t amount); + +#endif diff --git a/dependencies/cmliblzma/liblzma/lz/lz_encoder_hash.h b/dependencies/cmliblzma/liblzma/lz/lz_encoder_hash.h new file mode 100644 index 0000000..342a333 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/lz/lz_encoder_hash.h @@ -0,0 +1,108 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file lz_encoder_hash.h +/// \brief Hash macros for match finders +// +// Author: Igor Pavlov +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_LZ_ENCODER_HASH_H +#define LZMA_LZ_ENCODER_HASH_H + +#if defined(WORDS_BIGENDIAN) && !defined(HAVE_SMALL) + // This is to make liblzma produce the same output on big endian + // systems that it does on little endian systems. lz_encoder.c + // takes care of including the actual table. + extern const uint32_t lzma_lz_hash_table[256]; +# define hash_table lzma_lz_hash_table +#else +# include "check.h" +# define hash_table lzma_crc32_table[0] +#endif + +#define HASH_2_SIZE (UINT32_C(1) << 10) +#define HASH_3_SIZE (UINT32_C(1) << 16) +#define HASH_4_SIZE (UINT32_C(1) << 20) + +#define HASH_2_MASK (HASH_2_SIZE - 1) +#define HASH_3_MASK (HASH_3_SIZE - 1) +#define HASH_4_MASK (HASH_4_SIZE - 1) + +#define FIX_3_HASH_SIZE (HASH_2_SIZE) +#define FIX_4_HASH_SIZE (HASH_2_SIZE + HASH_3_SIZE) +#define FIX_5_HASH_SIZE (HASH_2_SIZE + HASH_3_SIZE + HASH_4_SIZE) + +// Endianness doesn't matter in hash_2_calc() (no effect on the output). +#ifdef TUKLIB_FAST_UNALIGNED_ACCESS +# define hash_2_calc() \ + const uint32_t hash_value = *(const uint16_t *)(cur) +#else +# define hash_2_calc() \ + const uint32_t hash_value \ + = (uint32_t)(cur[0]) | ((uint32_t)(cur[1]) << 8) +#endif + +#define hash_3_calc() \ + const uint32_t temp = hash_table[cur[0]] ^ cur[1]; \ + const uint32_t hash_2_value = temp & HASH_2_MASK; \ + const uint32_t hash_value \ + = (temp ^ ((uint32_t)(cur[2]) << 8)) & mf->hash_mask + +#define hash_4_calc() \ + const uint32_t temp = hash_table[cur[0]] ^ cur[1]; \ + const uint32_t hash_2_value = temp & HASH_2_MASK; \ + const uint32_t hash_3_value \ + = (temp ^ ((uint32_t)(cur[2]) << 8)) & HASH_3_MASK; \ + const uint32_t hash_value = (temp ^ ((uint32_t)(cur[2]) << 8) \ + ^ (hash_table[cur[3]] << 5)) & mf->hash_mask + + +// The following are not currently used. + +#define hash_5_calc() \ + const uint32_t temp = hash_table[cur[0]] ^ cur[1]; \ + const uint32_t hash_2_value = temp & HASH_2_MASK; \ + const uint32_t hash_3_value \ + = (temp ^ ((uint32_t)(cur[2]) << 8)) & HASH_3_MASK; \ + uint32_t hash_4_value = (temp ^ ((uint32_t)(cur[2]) << 8) ^ \ + ^ hash_table[cur[3]] << 5); \ + const uint32_t hash_value \ + = (hash_4_value ^ (hash_table[cur[4]] << 3)) \ + & mf->hash_mask; \ + hash_4_value &= HASH_4_MASK + +/* +#define hash_zip_calc() \ + const uint32_t hash_value \ + = (((uint32_t)(cur[0]) | ((uint32_t)(cur[1]) << 8)) \ + ^ hash_table[cur[2]]) & 0xFFFF +*/ + +#define hash_zip_calc() \ + const uint32_t hash_value \ + = (((uint32_t)(cur[2]) | ((uint32_t)(cur[0]) << 8)) \ + ^ hash_table[cur[1]]) & 0xFFFF + +#define mt_hash_2_calc() \ + const uint32_t hash_2_value \ + = (hash_table[cur[0]] ^ cur[1]) & HASH_2_MASK + +#define mt_hash_3_calc() \ + const uint32_t temp = hash_table[cur[0]] ^ cur[1]; \ + const uint32_t hash_2_value = temp & HASH_2_MASK; \ + const uint32_t hash_3_value \ + = (temp ^ ((uint32_t)(cur[2]) << 8)) & HASH_3_MASK + +#define mt_hash_4_calc() \ + const uint32_t temp = hash_table[cur[0]] ^ cur[1]; \ + const uint32_t hash_2_value = temp & HASH_2_MASK; \ + const uint32_t hash_3_value \ + = (temp ^ ((uint32_t)(cur[2]) << 8)) & HASH_3_MASK; \ + const uint32_t hash_4_value = (temp ^ ((uint32_t)(cur[2]) << 8) ^ \ + (hash_table[cur[3]] << 5)) & HASH_4_MASK + +#endif diff --git a/dependencies/cmliblzma/liblzma/lz/lz_encoder_hash_table.h b/dependencies/cmliblzma/liblzma/lz/lz_encoder_hash_table.h new file mode 100644 index 0000000..8c51717 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/lz/lz_encoder_hash_table.h @@ -0,0 +1,68 @@ +/* This file has been automatically generated by crc32_tablegen.c. */ + +const uint32_t lzma_lz_hash_table[256] = { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, + 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, + 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, + 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, + 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, + 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, + 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, + 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, + 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, + 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, + 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, + 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, + 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, + 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, + 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, + 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, + 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, + 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, + 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, + 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, + 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, + 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, + 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, + 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, + 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, + 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, + 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, + 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D +}; diff --git a/dependencies/cmliblzma/liblzma/lz/lz_encoder_mf.c b/dependencies/cmliblzma/liblzma/lz/lz_encoder_mf.c new file mode 100644 index 0000000..7852077 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/lz/lz_encoder_mf.c @@ -0,0 +1,744 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file lz_encoder_mf.c +/// \brief Match finders +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "lz_encoder.h" +#include "lz_encoder_hash.h" +#include "memcmplen.h" + + +/// \brief Find matches starting from the current byte +/// +/// \return The length of the longest match found +extern uint32_t +lzma_mf_find(lzma_mf *mf, uint32_t *count_ptr, lzma_match *matches) +{ + // Call the match finder. It returns the number of length-distance + // pairs found. + // FIXME: Minimum count is zero, what _exactly_ is the maximum? + const uint32_t count = mf->find(mf, matches); + + // Length of the longest match; assume that no matches were found + // and thus the maximum length is zero. + uint32_t len_best = 0; + + if (count > 0) { +#ifndef NDEBUG + // Validate the matches. + for (uint32_t i = 0; i < count; ++i) { + assert(matches[i].len <= mf->nice_len); + assert(matches[i].dist < mf->read_pos); + assert(memcmp(mf_ptr(mf) - 1, + mf_ptr(mf) - matches[i].dist - 2, + matches[i].len) == 0); + } +#endif + + // The last used element in the array contains + // the longest match. + len_best = matches[count - 1].len; + + // If a match of maximum search length was found, try to + // extend the match to maximum possible length. + if (len_best == mf->nice_len) { + // The limit for the match length is either the + // maximum match length supported by the LZ-based + // encoder or the number of bytes left in the + // dictionary, whichever is smaller. + uint32_t limit = mf_avail(mf) + 1; + if (limit > mf->match_len_max) + limit = mf->match_len_max; + + // Pointer to the byte we just ran through + // the match finder. + const uint8_t *p1 = mf_ptr(mf) - 1; + + // Pointer to the beginning of the match. We need -1 + // here because the match distances are zero based. + const uint8_t *p2 = p1 - matches[count - 1].dist - 1; + + len_best = lzma_memcmplen(p1, p2, len_best, limit); + } + } + + *count_ptr = count; + + // Finally update the read position to indicate that match finder was + // run for this dictionary offset. + ++mf->read_ahead; + + return len_best; +} + + +/// Hash value to indicate unused element in the hash. Since we start the +/// positions from dict_size + 1, zero is always too far to qualify +/// as usable match position. +#define EMPTY_HASH_VALUE 0 + + +/// Normalization must be done when lzma_mf.offset + lzma_mf.read_pos +/// reaches MUST_NORMALIZE_POS. +#define MUST_NORMALIZE_POS UINT32_MAX + + +/// \brief Normalizes hash values +/// +/// The hash arrays store positions of match candidates. The positions are +/// relative to an arbitrary offset that is not the same as the absolute +/// offset in the input stream. The relative position of the current byte +/// is lzma_mf.offset + lzma_mf.read_pos. The distances of the matches are +/// the differences of the current read position and the position found from +/// the hash. +/// +/// To prevent integer overflows of the offsets stored in the hash arrays, +/// we need to "normalize" the stored values now and then. During the +/// normalization, we drop values that indicate distance greater than the +/// dictionary size, thus making space for new values. +static void +normalize(lzma_mf *mf) +{ + assert(mf->read_pos + mf->offset == MUST_NORMALIZE_POS); + + // In future we may not want to touch the lowest bits, because there + // may be match finders that use larger resolution than one byte. + const uint32_t subvalue + = (MUST_NORMALIZE_POS - mf->cyclic_size); + // & (~(UINT32_C(1) << 10) - 1); + + for (uint32_t i = 0; i < mf->hash_count; ++i) { + // If the distance is greater than the dictionary size, + // we can simply mark the hash element as empty. + if (mf->hash[i] <= subvalue) + mf->hash[i] = EMPTY_HASH_VALUE; + else + mf->hash[i] -= subvalue; + } + + for (uint32_t i = 0; i < mf->sons_count; ++i) { + // Do the same for mf->son. + // + // NOTE: There may be uninitialized elements in mf->son. + // Valgrind may complain that the "if" below depends on + // an uninitialized value. In this case it is safe to ignore + // the warning. See also the comments in lz_encoder_init() + // in lz_encoder.c. + if (mf->son[i] <= subvalue) + mf->son[i] = EMPTY_HASH_VALUE; + else + mf->son[i] -= subvalue; + } + + // Update offset to match the new locations. + mf->offset -= subvalue; + + return; +} + + +/// Mark the current byte as processed from point of view of the match finder. +static void +move_pos(lzma_mf *mf) +{ + if (++mf->cyclic_pos == mf->cyclic_size) + mf->cyclic_pos = 0; + + ++mf->read_pos; + assert(mf->read_pos <= mf->write_pos); + + if (unlikely(mf->read_pos + mf->offset == UINT32_MAX)) + normalize(mf); +} + + +/// When flushing, we cannot run the match finder unless there is nice_len +/// bytes available in the dictionary. Instead, we skip running the match +/// finder (indicating that no match was found), and count how many bytes we +/// have ignored this way. +/// +/// When new data is given after the flushing was completed, the match finder +/// is restarted by rewinding mf->read_pos backwards by mf->pending. Then +/// the missed bytes are added to the hash using the match finder's skip +/// function (with small amount of input, it may start using mf->pending +/// again if flushing). +/// +/// Due to this rewinding, we don't touch cyclic_pos or test for +/// normalization. It will be done when the match finder's skip function +/// catches up after a flush. +static void +move_pending(lzma_mf *mf) +{ + ++mf->read_pos; + assert(mf->read_pos <= mf->write_pos); + ++mf->pending; +} + + +/// Calculate len_limit and determine if there is enough input to run +/// the actual match finder code. Sets up "cur" and "pos". This macro +/// is used by all find functions and binary tree skip functions. Hash +/// chain skip function doesn't need len_limit so a simpler code is used +/// in them. +#define header(is_bt, len_min, ret_op) \ + uint32_t len_limit = mf_avail(mf); \ + if (mf->nice_len <= len_limit) { \ + len_limit = mf->nice_len; \ + } else if (len_limit < (len_min) \ + || (is_bt && mf->action == LZMA_SYNC_FLUSH)) { \ + assert(mf->action != LZMA_RUN); \ + move_pending(mf); \ + ret_op; \ + } \ + const uint8_t *cur = mf_ptr(mf); \ + const uint32_t pos = mf->read_pos + mf->offset + + +/// Header for find functions. "return 0" indicates that zero matches +/// were found. +#define header_find(is_bt, len_min) \ + header(is_bt, len_min, return 0); \ + uint32_t matches_count = 0 + + +/// Header for a loop in a skip function. "continue" tells to skip the rest +/// of the code in the loop. +#define header_skip(is_bt, len_min) \ + header(is_bt, len_min, continue) + + +/// Calls hc_find_func() or bt_find_func() and calculates the total number +/// of matches found. Updates the dictionary position and returns the number +/// of matches found. +#define call_find(func, len_best) \ +do { \ + matches_count = func(len_limit, pos, cur, cur_match, mf->depth, \ + mf->son, mf->cyclic_pos, mf->cyclic_size, \ + matches + matches_count, len_best) \ + - matches; \ + move_pos(mf); \ + return matches_count; \ +} while (0) + + +//////////////// +// Hash Chain // +//////////////// + +#if defined(HAVE_MF_HC3) || defined(HAVE_MF_HC4) +/// +/// +/// \param len_limit Don't look for matches longer than len_limit. +/// \param pos lzma_mf.read_pos + lzma_mf.offset +/// \param cur Pointer to current byte (mf_ptr(mf)) +/// \param cur_match Start position of the current match candidate +/// \param depth Maximum length of the hash chain +/// \param son lzma_mf.son (contains the hash chain) +/// \param cyclic_pos +/// \param cyclic_size +/// \param matches Array to hold the matches. +/// \param len_best The length of the longest match found so far. +static lzma_match * +hc_find_func( + const uint32_t len_limit, + const uint32_t pos, + const uint8_t *const cur, + uint32_t cur_match, + uint32_t depth, + uint32_t *const son, + const uint32_t cyclic_pos, + const uint32_t cyclic_size, + lzma_match *matches, + uint32_t len_best) +{ + son[cyclic_pos] = cur_match; + + while (true) { + const uint32_t delta = pos - cur_match; + if (depth-- == 0 || delta >= cyclic_size) + return matches; + + const uint8_t *const pb = cur - delta; + cur_match = son[cyclic_pos - delta + + (delta > cyclic_pos ? cyclic_size : 0)]; + + if (pb[len_best] == cur[len_best] && pb[0] == cur[0]) { + uint32_t len = lzma_memcmplen(pb, cur, 1, len_limit); + + if (len_best < len) { + len_best = len; + matches->len = len; + matches->dist = delta - 1; + ++matches; + + if (len == len_limit) + return matches; + } + } + } +} + + +#define hc_find(len_best) \ + call_find(hc_find_func, len_best) + + +#define hc_skip() \ +do { \ + mf->son[mf->cyclic_pos] = cur_match; \ + move_pos(mf); \ +} while (0) + +#endif + + +#ifdef HAVE_MF_HC3 +extern uint32_t +lzma_mf_hc3_find(lzma_mf *mf, lzma_match *matches) +{ + header_find(false, 3); + + hash_3_calc(); + + const uint32_t delta2 = pos - mf->hash[hash_2_value]; + const uint32_t cur_match = mf->hash[FIX_3_HASH_SIZE + hash_value]; + + mf->hash[hash_2_value] = pos; + mf->hash[FIX_3_HASH_SIZE + hash_value] = pos; + + uint32_t len_best = 2; + + if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) { + len_best = lzma_memcmplen(cur - delta2, cur, + len_best, len_limit); + + matches[0].len = len_best; + matches[0].dist = delta2 - 1; + matches_count = 1; + + if (len_best == len_limit) { + hc_skip(); + return 1; // matches_count + } + } + + hc_find(len_best); +} + + +extern void +lzma_mf_hc3_skip(lzma_mf *mf, uint32_t amount) +{ + do { + if (mf_avail(mf) < 3) { + move_pending(mf); + continue; + } + + const uint8_t *cur = mf_ptr(mf); + const uint32_t pos = mf->read_pos + mf->offset; + + hash_3_calc(); + + const uint32_t cur_match + = mf->hash[FIX_3_HASH_SIZE + hash_value]; + + mf->hash[hash_2_value] = pos; + mf->hash[FIX_3_HASH_SIZE + hash_value] = pos; + + hc_skip(); + + } while (--amount != 0); +} +#endif + + +#ifdef HAVE_MF_HC4 +extern uint32_t +lzma_mf_hc4_find(lzma_mf *mf, lzma_match *matches) +{ + header_find(false, 4); + + hash_4_calc(); + + uint32_t delta2 = pos - mf->hash[hash_2_value]; + const uint32_t delta3 + = pos - mf->hash[FIX_3_HASH_SIZE + hash_3_value]; + const uint32_t cur_match = mf->hash[FIX_4_HASH_SIZE + hash_value]; + + mf->hash[hash_2_value ] = pos; + mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos; + mf->hash[FIX_4_HASH_SIZE + hash_value] = pos; + + uint32_t len_best = 1; + + if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) { + len_best = 2; + matches[0].len = 2; + matches[0].dist = delta2 - 1; + matches_count = 1; + } + + if (delta2 != delta3 && delta3 < mf->cyclic_size + && *(cur - delta3) == *cur) { + len_best = 3; + matches[matches_count++].dist = delta3 - 1; + delta2 = delta3; + } + + if (matches_count != 0) { + len_best = lzma_memcmplen(cur - delta2, cur, + len_best, len_limit); + + matches[matches_count - 1].len = len_best; + + if (len_best == len_limit) { + hc_skip(); + return matches_count; + } + } + + if (len_best < 3) + len_best = 3; + + hc_find(len_best); +} + + +extern void +lzma_mf_hc4_skip(lzma_mf *mf, uint32_t amount) +{ + do { + if (mf_avail(mf) < 4) { + move_pending(mf); + continue; + } + + const uint8_t *cur = mf_ptr(mf); + const uint32_t pos = mf->read_pos + mf->offset; + + hash_4_calc(); + + const uint32_t cur_match + = mf->hash[FIX_4_HASH_SIZE + hash_value]; + + mf->hash[hash_2_value] = pos; + mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos; + mf->hash[FIX_4_HASH_SIZE + hash_value] = pos; + + hc_skip(); + + } while (--amount != 0); +} +#endif + + +///////////////// +// Binary Tree // +///////////////// + +#if defined(HAVE_MF_BT2) || defined(HAVE_MF_BT3) || defined(HAVE_MF_BT4) +static lzma_match * +bt_find_func( + const uint32_t len_limit, + const uint32_t pos, + const uint8_t *const cur, + uint32_t cur_match, + uint32_t depth, + uint32_t *const son, + const uint32_t cyclic_pos, + const uint32_t cyclic_size, + lzma_match *matches, + uint32_t len_best) +{ + uint32_t *ptr0 = son + (cyclic_pos << 1) + 1; + uint32_t *ptr1 = son + (cyclic_pos << 1); + + uint32_t len0 = 0; + uint32_t len1 = 0; + + while (true) { + const uint32_t delta = pos - cur_match; + if (depth-- == 0 || delta >= cyclic_size) { + *ptr0 = EMPTY_HASH_VALUE; + *ptr1 = EMPTY_HASH_VALUE; + return matches; + } + + uint32_t *const pair = son + ((cyclic_pos - delta + + (delta > cyclic_pos ? cyclic_size : 0)) + << 1); + + const uint8_t *const pb = cur - delta; + uint32_t len = my_min(len0, len1); + + if (pb[len] == cur[len]) { + len = lzma_memcmplen(pb, cur, len + 1, len_limit); + + if (len_best < len) { + len_best = len; + matches->len = len; + matches->dist = delta - 1; + ++matches; + + if (len == len_limit) { + *ptr1 = pair[0]; + *ptr0 = pair[1]; + return matches; + } + } + } + + if (pb[len] < cur[len]) { + *ptr1 = cur_match; + ptr1 = pair + 1; + cur_match = *ptr1; + len1 = len; + } else { + *ptr0 = cur_match; + ptr0 = pair; + cur_match = *ptr0; + len0 = len; + } + } +} + + +static void +bt_skip_func( + const uint32_t len_limit, + const uint32_t pos, + const uint8_t *const cur, + uint32_t cur_match, + uint32_t depth, + uint32_t *const son, + const uint32_t cyclic_pos, + const uint32_t cyclic_size) +{ + uint32_t *ptr0 = son + (cyclic_pos << 1) + 1; + uint32_t *ptr1 = son + (cyclic_pos << 1); + + uint32_t len0 = 0; + uint32_t len1 = 0; + + while (true) { + const uint32_t delta = pos - cur_match; + if (depth-- == 0 || delta >= cyclic_size) { + *ptr0 = EMPTY_HASH_VALUE; + *ptr1 = EMPTY_HASH_VALUE; + return; + } + + uint32_t *pair = son + ((cyclic_pos - delta + + (delta > cyclic_pos ? cyclic_size : 0)) + << 1); + const uint8_t *pb = cur - delta; + uint32_t len = my_min(len0, len1); + + if (pb[len] == cur[len]) { + len = lzma_memcmplen(pb, cur, len + 1, len_limit); + + if (len == len_limit) { + *ptr1 = pair[0]; + *ptr0 = pair[1]; + return; + } + } + + if (pb[len] < cur[len]) { + *ptr1 = cur_match; + ptr1 = pair + 1; + cur_match = *ptr1; + len1 = len; + } else { + *ptr0 = cur_match; + ptr0 = pair; + cur_match = *ptr0; + len0 = len; + } + } +} + + +#define bt_find(len_best) \ + call_find(bt_find_func, len_best) + +#define bt_skip() \ +do { \ + bt_skip_func(len_limit, pos, cur, cur_match, mf->depth, \ + mf->son, mf->cyclic_pos, \ + mf->cyclic_size); \ + move_pos(mf); \ +} while (0) + +#endif + + +#ifdef HAVE_MF_BT2 +extern uint32_t +lzma_mf_bt2_find(lzma_mf *mf, lzma_match *matches) +{ + header_find(true, 2); + + hash_2_calc(); + + const uint32_t cur_match = mf->hash[hash_value]; + mf->hash[hash_value] = pos; + + bt_find(1); +} + + +extern void +lzma_mf_bt2_skip(lzma_mf *mf, uint32_t amount) +{ + do { + header_skip(true, 2); + + hash_2_calc(); + + const uint32_t cur_match = mf->hash[hash_value]; + mf->hash[hash_value] = pos; + + bt_skip(); + + } while (--amount != 0); +} +#endif + + +#ifdef HAVE_MF_BT3 +extern uint32_t +lzma_mf_bt3_find(lzma_mf *mf, lzma_match *matches) +{ + header_find(true, 3); + + hash_3_calc(); + + const uint32_t delta2 = pos - mf->hash[hash_2_value]; + const uint32_t cur_match = mf->hash[FIX_3_HASH_SIZE + hash_value]; + + mf->hash[hash_2_value] = pos; + mf->hash[FIX_3_HASH_SIZE + hash_value] = pos; + + uint32_t len_best = 2; + + if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) { + len_best = lzma_memcmplen( + cur, cur - delta2, len_best, len_limit); + + matches[0].len = len_best; + matches[0].dist = delta2 - 1; + matches_count = 1; + + if (len_best == len_limit) { + bt_skip(); + return 1; // matches_count + } + } + + bt_find(len_best); +} + + +extern void +lzma_mf_bt3_skip(lzma_mf *mf, uint32_t amount) +{ + do { + header_skip(true, 3); + + hash_3_calc(); + + const uint32_t cur_match + = mf->hash[FIX_3_HASH_SIZE + hash_value]; + + mf->hash[hash_2_value] = pos; + mf->hash[FIX_3_HASH_SIZE + hash_value] = pos; + + bt_skip(); + + } while (--amount != 0); +} +#endif + + +#ifdef HAVE_MF_BT4 +extern uint32_t +lzma_mf_bt4_find(lzma_mf *mf, lzma_match *matches) +{ + header_find(true, 4); + + hash_4_calc(); + + uint32_t delta2 = pos - mf->hash[hash_2_value]; + const uint32_t delta3 + = pos - mf->hash[FIX_3_HASH_SIZE + hash_3_value]; + const uint32_t cur_match = mf->hash[FIX_4_HASH_SIZE + hash_value]; + + mf->hash[hash_2_value] = pos; + mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos; + mf->hash[FIX_4_HASH_SIZE + hash_value] = pos; + + uint32_t len_best = 1; + + if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) { + len_best = 2; + matches[0].len = 2; + matches[0].dist = delta2 - 1; + matches_count = 1; + } + + if (delta2 != delta3 && delta3 < mf->cyclic_size + && *(cur - delta3) == *cur) { + len_best = 3; + matches[matches_count++].dist = delta3 - 1; + delta2 = delta3; + } + + if (matches_count != 0) { + len_best = lzma_memcmplen( + cur, cur - delta2, len_best, len_limit); + + matches[matches_count - 1].len = len_best; + + if (len_best == len_limit) { + bt_skip(); + return matches_count; + } + } + + if (len_best < 3) + len_best = 3; + + bt_find(len_best); +} + + +extern void +lzma_mf_bt4_skip(lzma_mf *mf, uint32_t amount) +{ + do { + header_skip(true, 4); + + hash_4_calc(); + + const uint32_t cur_match + = mf->hash[FIX_4_HASH_SIZE + hash_value]; + + mf->hash[hash_2_value] = pos; + mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos; + mf->hash[FIX_4_HASH_SIZE + hash_value] = pos; + + bt_skip(); + + } while (--amount != 0); +} +#endif diff --git a/dependencies/cmliblzma/liblzma/lzma/fastpos.h b/dependencies/cmliblzma/liblzma/lzma/fastpos.h new file mode 100644 index 0000000..a3feea5 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/lzma/fastpos.h @@ -0,0 +1,141 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file fastpos.h +/// \brief Kind of two-bit version of bit scan reverse +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_FASTPOS_H +#define LZMA_FASTPOS_H + +// LZMA encodes match distances by storing the highest two bits using +// a six-bit value [0, 63], and then the missing lower bits. +// Dictionary size is also stored using this encoding in the .xz +// file format header. +// +// fastpos.h provides a way to quickly find out the correct six-bit +// values. The following table gives some examples of this encoding: +// +// dist return +// 0 0 +// 1 1 +// 2 2 +// 3 3 +// 4 4 +// 5 4 +// 6 5 +// 7 5 +// 8 6 +// 11 6 +// 12 7 +// ... ... +// 15 7 +// 16 8 +// 17 8 +// ... ... +// 23 8 +// 24 9 +// 25 9 +// ... ... +// +// +// Provided functions or macros +// ---------------------------- +// +// get_dist_slot(dist) is the basic version. get_dist_slot_2(dist) +// assumes that dist >= FULL_DISTANCES, thus the result is at least +// FULL_DISTANCES_BITS * 2. Using get_dist_slot(dist) instead of +// get_dist_slot_2(dist) would give the same result, but get_dist_slot_2(dist) +// should be tiny bit faster due to the assumption being made. +// +// +// Size vs. speed +// -------------- +// +// With some CPUs that have fast BSR (bit scan reverse) instruction, the +// size optimized version is slightly faster than the bigger table based +// approach. Such CPUs include Intel Pentium Pro, Pentium II, Pentium III +// and Core 2 (possibly others). AMD K7 seems to have slower BSR, but that +// would still have speed roughly comparable to the table version. Older +// x86 CPUs like the original Pentium have very slow BSR; on those systems +// the table version is a lot faster. +// +// On some CPUs, the table version is a lot faster when using position +// dependent code, but with position independent code the size optimized +// version is slightly faster. This occurs at least on 32-bit SPARC (no +// ASM optimizations). +// +// I'm making the table version the default, because that has good speed +// on all systems I have tried. The size optimized version is sometimes +// slightly faster, but sometimes it is a lot slower. + +#ifdef HAVE_SMALL +# define get_dist_slot(dist) \ + ((dist) <= 4 ? (dist) : get_dist_slot_2(dist)) + +static inline uint32_t +get_dist_slot_2(uint32_t dist) +{ + const uint32_t i = bsr32(dist); + return (i + i) + ((dist >> (i - 1)) & 1); +} + + +#else + +#define FASTPOS_BITS 13 + +extern const uint8_t lzma_fastpos[1 << FASTPOS_BITS]; + + +#define fastpos_shift(extra, n) \ + ((extra) + (n) * (FASTPOS_BITS - 1)) + +#define fastpos_limit(extra, n) \ + (UINT32_C(1) << (FASTPOS_BITS + fastpos_shift(extra, n))) + +#define fastpos_result(dist, extra, n) \ + lzma_fastpos[(dist) >> fastpos_shift(extra, n)] \ + + 2 * fastpos_shift(extra, n) + + +static inline uint32_t +get_dist_slot(uint32_t dist) +{ + // If it is small enough, we can pick the result directly from + // the precalculated table. + if (dist < fastpos_limit(0, 0)) + return lzma_fastpos[dist]; + + if (dist < fastpos_limit(0, 1)) + return fastpos_result(dist, 0, 1); + + return fastpos_result(dist, 0, 2); +} + + +#ifdef FULL_DISTANCES_BITS +static inline uint32_t +get_dist_slot_2(uint32_t dist) +{ + assert(dist >= FULL_DISTANCES); + + if (dist < fastpos_limit(FULL_DISTANCES_BITS - 1, 0)) + return fastpos_result(dist, FULL_DISTANCES_BITS - 1, 0); + + if (dist < fastpos_limit(FULL_DISTANCES_BITS - 1, 1)) + return fastpos_result(dist, FULL_DISTANCES_BITS - 1, 1); + + return fastpos_result(dist, FULL_DISTANCES_BITS - 1, 2); +} +#endif + +#endif + +#endif diff --git a/dependencies/cmliblzma/liblzma/lzma/fastpos_table.c b/dependencies/cmliblzma/liblzma/lzma/fastpos_table.c new file mode 100644 index 0000000..6a3ceac --- /dev/null +++ b/dependencies/cmliblzma/liblzma/lzma/fastpos_table.c @@ -0,0 +1,519 @@ +/* This file has been automatically generated by fastpos_tablegen.c. */ + +#include "common.h" +#include "fastpos.h" + +const uint8_t lzma_fastpos[1 << FASTPOS_BITS] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 +}; diff --git a/dependencies/cmliblzma/liblzma/lzma/fastpos_tablegen.c b/dependencies/cmliblzma/liblzma/lzma/fastpos_tablegen.c new file mode 100644 index 0000000..c97e6f4 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/lzma/fastpos_tablegen.c @@ -0,0 +1,56 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file fastpos_tablegen.c +/// \brief Generates the lzma_fastpos[] lookup table +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include "fastpos.h" + + +int +main(void) +{ + uint8_t fastpos[1 << FASTPOS_BITS]; + + const uint8_t fast_slots = 2 * FASTPOS_BITS; + uint32_t c = 2; + + fastpos[0] = 0; + fastpos[1] = 1; + + for (uint8_t slot_fast = 2; slot_fast < fast_slots; ++slot_fast) { + const uint32_t k = 1 << ((slot_fast >> 1) - 1); + for (uint32_t j = 0; j < k; ++j, ++c) + fastpos[c] = slot_fast; + } + + printf("/* This file has been automatically generated " + "by fastpos_tablegen.c. */\n\n" + "#include \"common.h\"\n" + "#include \"fastpos.h\"\n\n" + "const uint8_t lzma_fastpos[1 << FASTPOS_BITS] = {"); + + for (size_t i = 0; i < (1 << FASTPOS_BITS); ++i) { + if (i % 16 == 0) + printf("\n\t"); + + printf("%3u", (unsigned int)(fastpos[i])); + + if (i != (1 << FASTPOS_BITS) - 1) + printf(","); + } + + printf("\n};\n"); + + return 0; +} diff --git a/dependencies/cmliblzma/liblzma/lzma/lzma2_decoder.c b/dependencies/cmliblzma/liblzma/lzma/lzma2_decoder.c new file mode 100644 index 0000000..878c870 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/lzma/lzma2_decoder.c @@ -0,0 +1,310 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file lzma2_decoder.c +/// \brief LZMA2 decoder +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "lzma2_decoder.h" +#include "lz_decoder.h" +#include "lzma_decoder.h" + + +typedef struct { + enum sequence { + SEQ_CONTROL, + SEQ_UNCOMPRESSED_1, + SEQ_UNCOMPRESSED_2, + SEQ_COMPRESSED_0, + SEQ_COMPRESSED_1, + SEQ_PROPERTIES, + SEQ_LZMA, + SEQ_COPY, + } sequence; + + /// Sequence after the size fields have been decoded. + enum sequence next_sequence; + + /// LZMA decoder + lzma_lz_decoder lzma; + + /// Uncompressed size of LZMA chunk + size_t uncompressed_size; + + /// Compressed size of the chunk (naturally equals to uncompressed + /// size of uncompressed chunk) + size_t compressed_size; + + /// True if properties are needed. This is false before the + /// first LZMA chunk. + bool need_properties; + + /// True if dictionary reset is needed. This is false before the + /// first chunk (LZMA or uncompressed). + bool need_dictionary_reset; + + lzma_options_lzma options; +} lzma_lzma2_coder; + + +static lzma_ret +lzma2_decode(void *coder_ptr, lzma_dict *restrict dict, + const uint8_t *restrict in, size_t *restrict in_pos, + size_t in_size) +{ + lzma_lzma2_coder *restrict coder = coder_ptr; + + // With SEQ_LZMA it is possible that no new input is needed to do + // some progress. The rest of the sequences assume that there is + // at least one byte of input. + while (*in_pos < in_size || coder->sequence == SEQ_LZMA) + switch (coder->sequence) { + case SEQ_CONTROL: { + const uint32_t control = in[*in_pos]; + ++*in_pos; + + // End marker + if (control == 0x00) + return LZMA_STREAM_END; + + if (control >= 0xE0 || control == 1) { + // Dictionary reset implies that next LZMA chunk has + // to set new properties. + coder->need_properties = true; + coder->need_dictionary_reset = true; + } else if (coder->need_dictionary_reset) { + return LZMA_DATA_ERROR; + } + + if (control >= 0x80) { + // LZMA chunk. The highest five bits of the + // uncompressed size are taken from the control byte. + coder->uncompressed_size = (control & 0x1F) << 16; + coder->sequence = SEQ_UNCOMPRESSED_1; + + // See if there are new properties or if we need to + // reset the state. + if (control >= 0xC0) { + // When there are new properties, state reset + // is done at SEQ_PROPERTIES. + coder->need_properties = false; + coder->next_sequence = SEQ_PROPERTIES; + + } else if (coder->need_properties) { + return LZMA_DATA_ERROR; + + } else { + coder->next_sequence = SEQ_LZMA; + + // If only state reset is wanted with old + // properties, do the resetting here for + // simplicity. + if (control >= 0xA0) + coder->lzma.reset(coder->lzma.coder, + &coder->options); + } + } else { + // Invalid control values + if (control > 2) + return LZMA_DATA_ERROR; + + // It's uncompressed chunk + coder->sequence = SEQ_COMPRESSED_0; + coder->next_sequence = SEQ_COPY; + } + + if (coder->need_dictionary_reset) { + // Finish the dictionary reset and let the caller + // flush the dictionary to the actual output buffer. + coder->need_dictionary_reset = false; + dict_reset(dict); + return LZMA_OK; + } + + break; + } + + case SEQ_UNCOMPRESSED_1: + coder->uncompressed_size += (uint32_t)(in[(*in_pos)++]) << 8; + coder->sequence = SEQ_UNCOMPRESSED_2; + break; + + case SEQ_UNCOMPRESSED_2: + coder->uncompressed_size += in[(*in_pos)++] + 1; + coder->sequence = SEQ_COMPRESSED_0; + coder->lzma.set_uncompressed(coder->lzma.coder, + coder->uncompressed_size); + break; + + case SEQ_COMPRESSED_0: + coder->compressed_size = (uint32_t)(in[(*in_pos)++]) << 8; + coder->sequence = SEQ_COMPRESSED_1; + break; + + case SEQ_COMPRESSED_1: + coder->compressed_size += in[(*in_pos)++] + 1; + coder->sequence = coder->next_sequence; + break; + + case SEQ_PROPERTIES: + if (lzma_lzma_lclppb_decode(&coder->options, in[(*in_pos)++])) + return LZMA_DATA_ERROR; + + coder->lzma.reset(coder->lzma.coder, &coder->options); + + coder->sequence = SEQ_LZMA; + break; + + case SEQ_LZMA: { + // Store the start offset so that we can update + // coder->compressed_size later. + const size_t in_start = *in_pos; + + // Decode from in[] to *dict. + const lzma_ret ret = coder->lzma.code(coder->lzma.coder, + dict, in, in_pos, in_size); + + // Validate and update coder->compressed_size. + const size_t in_used = *in_pos - in_start; + if (in_used > coder->compressed_size) + return LZMA_DATA_ERROR; + + coder->compressed_size -= in_used; + + // Return if we didn't finish the chunk, or an error occurred. + if (ret != LZMA_STREAM_END) + return ret; + + // The LZMA decoder must have consumed the whole chunk now. + // We don't need to worry about uncompressed size since it + // is checked by the LZMA decoder. + if (coder->compressed_size != 0) + return LZMA_DATA_ERROR; + + coder->sequence = SEQ_CONTROL; + break; + } + + case SEQ_COPY: { + // Copy from input to the dictionary as is. + dict_write(dict, in, in_pos, in_size, &coder->compressed_size); + if (coder->compressed_size != 0) + return LZMA_OK; + + coder->sequence = SEQ_CONTROL; + break; + } + + default: + assert(0); + return LZMA_PROG_ERROR; + } + + return LZMA_OK; +} + + +static void +lzma2_decoder_end(void *coder_ptr, const lzma_allocator *allocator) +{ + lzma_lzma2_coder *coder = coder_ptr; + + assert(coder->lzma.end == NULL); + lzma_free(coder->lzma.coder, allocator); + + lzma_free(coder, allocator); + + return; +} + + +static lzma_ret +lzma2_decoder_init(lzma_lz_decoder *lz, const lzma_allocator *allocator, + const void *opt, lzma_lz_options *lz_options) +{ + lzma_lzma2_coder *coder = lz->coder; + if (coder == NULL) { + coder = lzma_alloc(sizeof(lzma_lzma2_coder), allocator); + if (coder == NULL) + return LZMA_MEM_ERROR; + + lz->coder = coder; + lz->code = &lzma2_decode; + lz->end = &lzma2_decoder_end; + + coder->lzma = LZMA_LZ_DECODER_INIT; + } + + const lzma_options_lzma *options = opt; + + coder->sequence = SEQ_CONTROL; + coder->need_properties = true; + coder->need_dictionary_reset = options->preset_dict == NULL + || options->preset_dict_size == 0; + + return lzma_lzma_decoder_create(&coder->lzma, + allocator, options, lz_options); +} + + +extern lzma_ret +lzma_lzma2_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter_info *filters) +{ + // LZMA2 can only be the last filter in the chain. This is enforced + // by the raw_decoder initialization. + assert(filters[1].init == NULL); + + return lzma_lz_decoder_init(next, allocator, filters, + &lzma2_decoder_init); +} + + +extern uint64_t +lzma_lzma2_decoder_memusage(const void *options) +{ + return sizeof(lzma_lzma2_coder) + + lzma_lzma_decoder_memusage_nocheck(options); +} + + +extern lzma_ret +lzma_lzma2_props_decode(void **options, const lzma_allocator *allocator, + const uint8_t *props, size_t props_size) +{ + if (props_size != 1) + return LZMA_OPTIONS_ERROR; + + // Check that reserved bits are unset. + if (props[0] & 0xC0) + return LZMA_OPTIONS_ERROR; + + // Decode the dictionary size. + if (props[0] > 40) + return LZMA_OPTIONS_ERROR; + + lzma_options_lzma *opt = lzma_alloc( + sizeof(lzma_options_lzma), allocator); + if (opt == NULL) + return LZMA_MEM_ERROR; + + if (props[0] == 40) { + opt->dict_size = UINT32_MAX; + } else { + opt->dict_size = 2 | (props[0] & 1); + opt->dict_size <<= props[0] / 2 + 11; + } + + opt->preset_dict = NULL; + opt->preset_dict_size = 0; + + *options = opt; + + return LZMA_OK; +} diff --git a/dependencies/cmliblzma/liblzma/lzma/lzma2_decoder.h b/dependencies/cmliblzma/liblzma/lzma/lzma2_decoder.h new file mode 100644 index 0000000..ef2dcbf --- /dev/null +++ b/dependencies/cmliblzma/liblzma/lzma/lzma2_decoder.h @@ -0,0 +1,29 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file lzma2_decoder.h +/// \brief LZMA2 decoder +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_LZMA2_DECODER_H +#define LZMA_LZMA2_DECODER_H + +#include "common.h" + +extern lzma_ret lzma_lzma2_decoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters); + +extern uint64_t lzma_lzma2_decoder_memusage(const void *options); + +extern lzma_ret lzma_lzma2_props_decode( + void **options, const lzma_allocator *allocator, + const uint8_t *props, size_t props_size); + +#endif diff --git a/dependencies/cmliblzma/liblzma/lzma/lzma2_encoder.c b/dependencies/cmliblzma/liblzma/lzma/lzma2_encoder.c new file mode 100644 index 0000000..63588ee --- /dev/null +++ b/dependencies/cmliblzma/liblzma/lzma/lzma2_encoder.c @@ -0,0 +1,410 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file lzma2_encoder.c +/// \brief LZMA2 encoder +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "lz_encoder.h" +#include "lzma_encoder.h" +#include "fastpos.h" +#include "lzma2_encoder.h" + + +typedef struct { + enum { + SEQ_INIT, + SEQ_LZMA_ENCODE, + SEQ_LZMA_COPY, + SEQ_UNCOMPRESSED_HEADER, + SEQ_UNCOMPRESSED_COPY, + } sequence; + + /// LZMA encoder + void *lzma; + + /// LZMA options currently in use. + lzma_options_lzma opt_cur; + + bool need_properties; + bool need_state_reset; + bool need_dictionary_reset; + + /// Uncompressed size of a chunk + size_t uncompressed_size; + + /// Compressed size of a chunk (excluding headers); this is also used + /// to indicate the end of buf[] in SEQ_LZMA_COPY. + size_t compressed_size; + + /// Read position in buf[] + size_t buf_pos; + + /// Buffer to hold the chunk header and LZMA compressed data + uint8_t buf[LZMA2_HEADER_MAX + LZMA2_CHUNK_MAX]; +} lzma_lzma2_coder; + + +static void +lzma2_header_lzma(lzma_lzma2_coder *coder) +{ + assert(coder->uncompressed_size > 0); + assert(coder->uncompressed_size <= LZMA2_UNCOMPRESSED_MAX); + assert(coder->compressed_size > 0); + assert(coder->compressed_size <= LZMA2_CHUNK_MAX); + + size_t pos; + + if (coder->need_properties) { + pos = 0; + + if (coder->need_dictionary_reset) + coder->buf[pos] = 0x80 + (3 << 5); + else + coder->buf[pos] = 0x80 + (2 << 5); + } else { + pos = 1; + + if (coder->need_state_reset) + coder->buf[pos] = 0x80 + (1 << 5); + else + coder->buf[pos] = 0x80; + } + + // Set the start position for copying. + coder->buf_pos = pos; + + // Uncompressed size + size_t size = coder->uncompressed_size - 1; + coder->buf[pos++] += size >> 16; + coder->buf[pos++] = (size >> 8) & 0xFF; + coder->buf[pos++] = size & 0xFF; + + // Compressed size + size = coder->compressed_size - 1; + coder->buf[pos++] = size >> 8; + coder->buf[pos++] = size & 0xFF; + + // Properties, if needed + if (coder->need_properties) + lzma_lzma_lclppb_encode(&coder->opt_cur, coder->buf + pos); + + coder->need_properties = false; + coder->need_state_reset = false; + coder->need_dictionary_reset = false; + + // The copying code uses coder->compressed_size to indicate the end + // of coder->buf[], so we need add the maximum size of the header here. + coder->compressed_size += LZMA2_HEADER_MAX; + + return; +} + + +static void +lzma2_header_uncompressed(lzma_lzma2_coder *coder) +{ + assert(coder->uncompressed_size > 0); + assert(coder->uncompressed_size <= LZMA2_CHUNK_MAX); + + // If this is the first chunk, we need to include dictionary + // reset indicator. + if (coder->need_dictionary_reset) + coder->buf[0] = 1; + else + coder->buf[0] = 2; + + coder->need_dictionary_reset = false; + + // "Compressed" size + coder->buf[1] = (coder->uncompressed_size - 1) >> 8; + coder->buf[2] = (coder->uncompressed_size - 1) & 0xFF; + + // Set the start position for copying. + coder->buf_pos = 0; + return; +} + + +static lzma_ret +lzma2_encode(void *coder_ptr, lzma_mf *restrict mf, + uint8_t *restrict out, size_t *restrict out_pos, + size_t out_size) +{ + lzma_lzma2_coder *restrict coder = coder_ptr; + + while (*out_pos < out_size) + switch (coder->sequence) { + case SEQ_INIT: + // If there's no input left and we are flushing or finishing, + // don't start a new chunk. + if (mf_unencoded(mf) == 0) { + // Write end of payload marker if finishing. + if (mf->action == LZMA_FINISH) + out[(*out_pos)++] = 0; + + return mf->action == LZMA_RUN + ? LZMA_OK : LZMA_STREAM_END; + } + + if (coder->need_state_reset) + return_if_error(lzma_lzma_encoder_reset( + coder->lzma, &coder->opt_cur)); + + coder->uncompressed_size = 0; + coder->compressed_size = 0; + coder->sequence = SEQ_LZMA_ENCODE; + + // Fall through + + case SEQ_LZMA_ENCODE: { + // Calculate how much more uncompressed data this chunk + // could accept. + const uint32_t left = LZMA2_UNCOMPRESSED_MAX + - coder->uncompressed_size; + uint32_t limit; + + if (left < mf->match_len_max) { + // Must flush immediately since the next LZMA symbol + // could make the uncompressed size of the chunk too + // big. + limit = 0; + } else { + // Calculate maximum read_limit that is OK from point + // of view of LZMA2 chunk size. + limit = mf->read_pos - mf->read_ahead + + left - mf->match_len_max; + } + + // Save the start position so that we can update + // coder->uncompressed_size. + const uint32_t read_start = mf->read_pos - mf->read_ahead; + + // Call the LZMA encoder until the chunk is finished. + const lzma_ret ret = lzma_lzma_encode(coder->lzma, mf, + coder->buf + LZMA2_HEADER_MAX, + &coder->compressed_size, + LZMA2_CHUNK_MAX, limit); + + coder->uncompressed_size += mf->read_pos - mf->read_ahead + - read_start; + + assert(coder->compressed_size <= LZMA2_CHUNK_MAX); + assert(coder->uncompressed_size <= LZMA2_UNCOMPRESSED_MAX); + + if (ret != LZMA_STREAM_END) + return LZMA_OK; + + // See if the chunk compressed. If it didn't, we encode it + // as uncompressed chunk. This saves a few bytes of space + // and makes decoding faster. + if (coder->compressed_size >= coder->uncompressed_size) { + coder->uncompressed_size += mf->read_ahead; + assert(coder->uncompressed_size + <= LZMA2_UNCOMPRESSED_MAX); + mf->read_ahead = 0; + lzma2_header_uncompressed(coder); + coder->need_state_reset = true; + coder->sequence = SEQ_UNCOMPRESSED_HEADER; + break; + } + + // The chunk did compress at least by one byte, so we store + // the chunk as LZMA. + lzma2_header_lzma(coder); + + coder->sequence = SEQ_LZMA_COPY; + } + + // Fall through + + case SEQ_LZMA_COPY: + // Copy the compressed chunk along its headers to the + // output buffer. + lzma_bufcpy(coder->buf, &coder->buf_pos, + coder->compressed_size, + out, out_pos, out_size); + if (coder->buf_pos != coder->compressed_size) + return LZMA_OK; + + coder->sequence = SEQ_INIT; + break; + + case SEQ_UNCOMPRESSED_HEADER: + // Copy the three-byte header to indicate uncompressed chunk. + lzma_bufcpy(coder->buf, &coder->buf_pos, + LZMA2_HEADER_UNCOMPRESSED, + out, out_pos, out_size); + if (coder->buf_pos != LZMA2_HEADER_UNCOMPRESSED) + return LZMA_OK; + + coder->sequence = SEQ_UNCOMPRESSED_COPY; + + // Fall through + + case SEQ_UNCOMPRESSED_COPY: + // Copy the uncompressed data as is from the dictionary + // to the output buffer. + mf_read(mf, out, out_pos, out_size, &coder->uncompressed_size); + if (coder->uncompressed_size != 0) + return LZMA_OK; + + coder->sequence = SEQ_INIT; + break; + } + + return LZMA_OK; +} + + +static void +lzma2_encoder_end(void *coder_ptr, const lzma_allocator *allocator) +{ + lzma_lzma2_coder *coder = coder_ptr; + lzma_free(coder->lzma, allocator); + lzma_free(coder, allocator); + return; +} + + +static lzma_ret +lzma2_encoder_options_update(void *coder_ptr, const lzma_filter *filter) +{ + lzma_lzma2_coder *coder = coder_ptr; + + // New options can be set only when there is no incomplete chunk. + // This is the case at the beginning of the raw stream and right + // after LZMA_SYNC_FLUSH. + if (filter->options == NULL || coder->sequence != SEQ_INIT) + return LZMA_PROG_ERROR; + + // Look if there are new options. At least for now, + // only lc/lp/pb can be changed. + const lzma_options_lzma *opt = filter->options; + if (coder->opt_cur.lc != opt->lc || coder->opt_cur.lp != opt->lp + || coder->opt_cur.pb != opt->pb) { + // Validate the options. + if (opt->lc > LZMA_LCLP_MAX || opt->lp > LZMA_LCLP_MAX + || opt->lc + opt->lp > LZMA_LCLP_MAX + || opt->pb > LZMA_PB_MAX) + return LZMA_OPTIONS_ERROR; + + // The new options will be used when the encoder starts + // a new LZMA2 chunk. + coder->opt_cur.lc = opt->lc; + coder->opt_cur.lp = opt->lp; + coder->opt_cur.pb = opt->pb; + coder->need_properties = true; + coder->need_state_reset = true; + } + + return LZMA_OK; +} + + +static lzma_ret +lzma2_encoder_init(lzma_lz_encoder *lz, const lzma_allocator *allocator, + const void *options, lzma_lz_options *lz_options) +{ + if (options == NULL) + return LZMA_PROG_ERROR; + + lzma_lzma2_coder *coder = lz->coder; + if (coder == NULL) { + coder = lzma_alloc(sizeof(lzma_lzma2_coder), allocator); + if (coder == NULL) + return LZMA_MEM_ERROR; + + lz->coder = coder; + lz->code = &lzma2_encode; + lz->end = &lzma2_encoder_end; + lz->options_update = &lzma2_encoder_options_update; + + coder->lzma = NULL; + } + + coder->opt_cur = *(const lzma_options_lzma *)(options); + + coder->sequence = SEQ_INIT; + coder->need_properties = true; + coder->need_state_reset = false; + coder->need_dictionary_reset + = coder->opt_cur.preset_dict == NULL + || coder->opt_cur.preset_dict_size == 0; + + // Initialize LZMA encoder + return_if_error(lzma_lzma_encoder_create(&coder->lzma, allocator, + &coder->opt_cur, lz_options)); + + // Make sure that we will always have enough history available in + // case we need to use uncompressed chunks. They are used when the + // compressed size of a chunk is not smaller than the uncompressed + // size, so we need to have at least LZMA2_COMPRESSED_MAX bytes + // history available. + if (lz_options->before_size + lz_options->dict_size < LZMA2_CHUNK_MAX) + lz_options->before_size + = LZMA2_CHUNK_MAX - lz_options->dict_size; + + return LZMA_OK; +} + + +extern lzma_ret +lzma_lzma2_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter_info *filters) +{ + return lzma_lz_encoder_init( + next, allocator, filters, &lzma2_encoder_init); +} + + +extern uint64_t +lzma_lzma2_encoder_memusage(const void *options) +{ + const uint64_t lzma_mem = lzma_lzma_encoder_memusage(options); + if (lzma_mem == UINT64_MAX) + return UINT64_MAX; + + return sizeof(lzma_lzma2_coder) + lzma_mem; +} + + +extern lzma_ret +lzma_lzma2_props_encode(const void *options, uint8_t *out) +{ + const lzma_options_lzma *const opt = options; + uint32_t d = my_max(opt->dict_size, LZMA_DICT_SIZE_MIN); + + // Round up to the next 2^n - 1 or 2^n + 2^(n - 1) - 1 depending + // on which one is the next: + --d; + d |= d >> 2; + d |= d >> 3; + d |= d >> 4; + d |= d >> 8; + d |= d >> 16; + + // Get the highest two bits using the proper encoding: + if (d == UINT32_MAX) + out[0] = 40; + else + out[0] = get_dist_slot(d + 1) - 24; + + return LZMA_OK; +} + + +extern uint64_t +lzma_lzma2_block_size(const void *options) +{ + const lzma_options_lzma *const opt = options; + + // Use at least 1 MiB to keep compression ratio better. + return my_max((uint64_t)(opt->dict_size) * 3, UINT64_C(1) << 20); +} diff --git a/dependencies/cmliblzma/liblzma/lzma/lzma2_encoder.h b/dependencies/cmliblzma/liblzma/lzma/lzma2_encoder.h new file mode 100644 index 0000000..515f183 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/lzma/lzma2_encoder.h @@ -0,0 +1,43 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file lzma2_encoder.h +/// \brief LZMA2 encoder +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_LZMA2_ENCODER_H +#define LZMA_LZMA2_ENCODER_H + +#include "common.h" + + +/// Maximum number of bytes of actual data per chunk (no headers) +#define LZMA2_CHUNK_MAX (UINT32_C(1) << 16) + +/// Maximum uncompressed size of LZMA chunk (no headers) +#define LZMA2_UNCOMPRESSED_MAX (UINT32_C(1) << 21) + +/// Maximum size of LZMA2 headers +#define LZMA2_HEADER_MAX 6 + +/// Size of a header for uncompressed chunk +#define LZMA2_HEADER_UNCOMPRESSED 3 + + +extern lzma_ret lzma_lzma2_encoder_init( + lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter_info *filters); + +extern uint64_t lzma_lzma2_encoder_memusage(const void *options); + +extern lzma_ret lzma_lzma2_props_encode(const void *options, uint8_t *out); + +extern uint64_t lzma_lzma2_block_size(const void *options); + +#endif diff --git a/dependencies/cmliblzma/liblzma/lzma/lzma_common.h b/dependencies/cmliblzma/liblzma/lzma/lzma_common.h new file mode 100644 index 0000000..09efd38 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/lzma/lzma_common.h @@ -0,0 +1,224 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file lzma_common.h +/// \brief Private definitions common to LZMA encoder and decoder +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_LZMA_COMMON_H +#define LZMA_LZMA_COMMON_H + +#include "common.h" +#include "range_common.h" + + +/////////////////// +// Miscellaneous // +/////////////////// + +/// Maximum number of position states. A position state is the lowest pos bits +/// number of bits of the current uncompressed offset. In some places there +/// are different sets of probabilities for different pos states. +#define POS_STATES_MAX (1 << LZMA_PB_MAX) + + +/// Validates lc, lp, and pb. +static inline bool +is_lclppb_valid(const lzma_options_lzma *options) +{ + return options->lc <= LZMA_LCLP_MAX && options->lp <= LZMA_LCLP_MAX + && options->lc + options->lp <= LZMA_LCLP_MAX + && options->pb <= LZMA_PB_MAX; +} + + +/////////// +// State // +/////////// + +/// This enum is used to track which events have occurred most recently and +/// in which order. This information is used to predict the next event. +/// +/// Events: +/// - 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 event names are in from STATE_oldest_older_previous. REP means +/// either short or long repeated match, and NONLIT means any non-literal. +typedef enum { + 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, +} lzma_lzma_state; + + +/// 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 state was a literal. +#define update_literal(state) \ + state = ((state) <= STATE_SHORTREP_LIT_LIT \ + ? STATE_LIT_LIT \ + : ((state) <= STATE_LIT_SHORTREP \ + ? (state) - 3 \ + : (state) - 6)) + +/// Indicate that the latest state was a match. +#define update_match(state) \ + state = ((state) < LIT_STATES ? STATE_LIT_MATCH : STATE_NONLIT_MATCH) + +/// Indicate that the latest state was a long repeated match. +#define update_long_rep(state) \ + state = ((state) < LIT_STATES ? STATE_LIT_LONGREP : STATE_NONLIT_REP) + +/// Indicate that the latest state was a short match. +#define update_short_rep(state) \ + state = ((state) < LIT_STATES ? STATE_LIT_SHORTREP : STATE_NONLIT_REP) + +/// Test if the previous state was a literal. +#define is_literal_state(state) \ + ((state) < LIT_STATES) + + +///////////// +// Literal // +///////////// + +/// 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 << LZMA_LCLP_MAX) + +/// Locate the literal coder for the next literal byte. The choice depends on +/// - the lowest literal_pos_bits bits of the position of the current +/// byte; and +/// - the highest literal_context_bits bits of the previous byte. +#define literal_subcoder(probs, lc, lp_mask, pos, prev_byte) \ + ((probs)[(((pos) & lp_mask) << lc) + ((prev_byte) >> (8 - lc))]) + + +static inline void +literal_init(probability (*probs)[LITERAL_CODER_SIZE], + uint32_t lc, uint32_t lp) +{ + assert(lc + lp <= LZMA_LCLP_MAX); + + const uint32_t coders = 1U << (lc + lp); + + for (uint32_t i = 0; i < coders; ++i) + for (uint32_t j = 0; j < LITERAL_CODER_SIZE; ++j) + bit_reset(probs[i][j]); + + return; +} + + +////////////////// +// Match length // +////////////////// + +// 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) + + +//////////////////// +// Match distance // +//////////////////// + +// 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 + +// Macro to get the index of the appropriate probability array. +#define get_dist_state(len) \ + ((len) < DIST_STATES + MATCH_LEN_MIN \ + ? (len) - MATCH_LEN_MIN \ + : DIST_STATES - 1) + +// The highest two bits of a match distance (distance slot) are encoded +// using six bits. See fastpos.h for more explanation. +#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 (see the table in +// fastpos.h to understand why). +#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) + +// 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/dependencies/cmliblzma/liblzma/lzma/lzma_decoder.c b/dependencies/cmliblzma/liblzma/lzma/lzma_decoder.c new file mode 100644 index 0000000..d0f29b7 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/lzma/lzma_decoder.c @@ -0,0 +1,1064 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file lzma_decoder.c +/// \brief LZMA decoder +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "lz_decoder.h" +#include "lzma_common.h" +#include "lzma_decoder.h" +#include "range_decoder.h" + +// The macros unroll loops with switch statements. +// Silence warnings about missing fall-through comments. +#if TUKLIB_GNUC_REQ(7, 0) +# pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#endif + + +#ifdef HAVE_SMALL + +// Macros for (somewhat) size-optimized code. +#define seq_4(seq) seq + +#define seq_6(seq) seq + +#define seq_8(seq) seq + +#define seq_len(seq) \ + seq ## _CHOICE, \ + seq ## _CHOICE2, \ + seq ## _BITTREE + +#define len_decode(target, ld, pos_state, seq) \ +do { \ +case seq ## _CHOICE: \ + rc_if_0(ld.choice, seq ## _CHOICE) { \ + rc_update_0(ld.choice); \ + probs = ld.low[pos_state];\ + limit = LEN_LOW_SYMBOLS; \ + target = MATCH_LEN_MIN; \ + } else { \ + rc_update_1(ld.choice); \ +case seq ## _CHOICE2: \ + rc_if_0(ld.choice2, seq ## _CHOICE2) { \ + rc_update_0(ld.choice2); \ + probs = ld.mid[pos_state]; \ + limit = LEN_MID_SYMBOLS; \ + target = MATCH_LEN_MIN + LEN_LOW_SYMBOLS; \ + } else { \ + rc_update_1(ld.choice2); \ + probs = ld.high; \ + limit = LEN_HIGH_SYMBOLS; \ + target = MATCH_LEN_MIN + LEN_LOW_SYMBOLS \ + + LEN_MID_SYMBOLS; \ + } \ + } \ + symbol = 1; \ +case seq ## _BITTREE: \ + do { \ + rc_bit(probs[symbol], , , seq ## _BITTREE); \ + } while (symbol < limit); \ + target += symbol - limit; \ +} while (0) + +#else // HAVE_SMALL + +// Unrolled versions +#define seq_4(seq) \ + seq ## 0, \ + seq ## 1, \ + seq ## 2, \ + seq ## 3 + +#define seq_6(seq) \ + seq ## 0, \ + seq ## 1, \ + seq ## 2, \ + seq ## 3, \ + seq ## 4, \ + seq ## 5 + +#define seq_8(seq) \ + seq ## 0, \ + seq ## 1, \ + seq ## 2, \ + seq ## 3, \ + seq ## 4, \ + seq ## 5, \ + seq ## 6, \ + seq ## 7 + +#define seq_len(seq) \ + seq ## _CHOICE, \ + seq ## _LOW0, \ + seq ## _LOW1, \ + seq ## _LOW2, \ + seq ## _CHOICE2, \ + seq ## _MID0, \ + seq ## _MID1, \ + seq ## _MID2, \ + seq ## _HIGH0, \ + seq ## _HIGH1, \ + seq ## _HIGH2, \ + seq ## _HIGH3, \ + seq ## _HIGH4, \ + seq ## _HIGH5, \ + seq ## _HIGH6, \ + seq ## _HIGH7 + +#define len_decode(target, ld, pos_state, seq) \ +do { \ + symbol = 1; \ +case seq ## _CHOICE: \ + rc_if_0(ld.choice, seq ## _CHOICE) { \ + rc_update_0(ld.choice); \ + rc_bit_case(ld.low[pos_state][symbol], , , seq ## _LOW0); \ + rc_bit_case(ld.low[pos_state][symbol], , , seq ## _LOW1); \ + rc_bit_case(ld.low[pos_state][symbol], , , seq ## _LOW2); \ + target = symbol - LEN_LOW_SYMBOLS + MATCH_LEN_MIN; \ + } else { \ + rc_update_1(ld.choice); \ +case seq ## _CHOICE2: \ + rc_if_0(ld.choice2, seq ## _CHOICE2) { \ + rc_update_0(ld.choice2); \ + rc_bit_case(ld.mid[pos_state][symbol], , , \ + seq ## _MID0); \ + rc_bit_case(ld.mid[pos_state][symbol], , , \ + seq ## _MID1); \ + rc_bit_case(ld.mid[pos_state][symbol], , , \ + seq ## _MID2); \ + target = symbol - LEN_MID_SYMBOLS \ + + MATCH_LEN_MIN + LEN_LOW_SYMBOLS; \ + } else { \ + rc_update_1(ld.choice2); \ + rc_bit_case(ld.high[symbol], , , seq ## _HIGH0); \ + rc_bit_case(ld.high[symbol], , , seq ## _HIGH1); \ + rc_bit_case(ld.high[symbol], , , seq ## _HIGH2); \ + rc_bit_case(ld.high[symbol], , , seq ## _HIGH3); \ + rc_bit_case(ld.high[symbol], , , seq ## _HIGH4); \ + rc_bit_case(ld.high[symbol], , , seq ## _HIGH5); \ + rc_bit_case(ld.high[symbol], , , seq ## _HIGH6); \ + rc_bit_case(ld.high[symbol], , , seq ## _HIGH7); \ + target = symbol - LEN_HIGH_SYMBOLS \ + + MATCH_LEN_MIN \ + + LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS; \ + } \ + } \ +} while (0) + +#endif // HAVE_SMALL + + +/// Length decoder probabilities; see comments in lzma_common.h. +typedef struct { + probability choice; + probability choice2; + probability low[POS_STATES_MAX][LEN_LOW_SYMBOLS]; + probability mid[POS_STATES_MAX][LEN_MID_SYMBOLS]; + probability high[LEN_HIGH_SYMBOLS]; +} lzma_length_decoder; + + +typedef struct { + /////////////////// + // Probabilities // + /////////////////// + + /// Literals; see comments in lzma_common.h. + probability literal[LITERAL_CODERS_MAX][LITERAL_CODER_SIZE]; + + /// If 1, it's a match. Otherwise it's a single 8-bit literal. + probability is_match[STATES][POS_STATES_MAX]; + + /// If 1, it's a repeated match. The distance is one of rep0 .. rep3. + probability is_rep[STATES]; + + /// If 0, distance of a repeated match is rep0. + /// Otherwise check is_rep1. + probability is_rep0[STATES]; + + /// If 0, distance of a repeated match is rep1. + /// Otherwise check is_rep2. + probability is_rep1[STATES]; + + /// If 0, distance of a repeated match is rep2. Otherwise it is rep3. + probability is_rep2[STATES]; + + /// If 1, the repeated match has length of one byte. Otherwise + /// the length is decoded from rep_len_decoder. + probability 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]. + probability dist_slot[DIST_STATES][DIST_SLOTS]; + + /// Probability trees for additional bits for match distance when the + /// distance is in the range [4, 127]. + probability pos_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. + probability pos_align[ALIGN_SIZE]; + + /// Length of a normal match + lzma_length_decoder match_len_decoder; + + /// Length of a repeated match + lzma_length_decoder rep_len_decoder; + + /////////////////// + // Decoder state // + /////////////////// + + // Range coder + lzma_range_decoder rc; + + // Types of the most recently seen LZMA symbols + lzma_lzma_state state; + + uint32_t rep0; ///< Distance of the latest match + uint32_t rep1; ///< Distance of second latest match + uint32_t rep2; ///< Distance of third latest match + uint32_t rep3; ///< Distance of fourth latest match + + uint32_t pos_mask; // (1U << pb) - 1 + uint32_t literal_context_bits; + uint32_t literal_pos_mask; + + /// Uncompressed size as bytes, or LZMA_VLI_UNKNOWN if end of + /// payload marker is expected. + lzma_vli uncompressed_size; + + //////////////////////////////// + // State of incomplete symbol // + //////////////////////////////// + + /// Position where to continue the decoder loop + enum { + SEQ_NORMALIZE, + SEQ_IS_MATCH, + seq_8(SEQ_LITERAL), + seq_8(SEQ_LITERAL_MATCHED), + SEQ_LITERAL_WRITE, + SEQ_IS_REP, + seq_len(SEQ_MATCH_LEN), + seq_6(SEQ_DIST_SLOT), + SEQ_DIST_MODEL, + SEQ_DIRECT, + seq_4(SEQ_ALIGN), + SEQ_EOPM, + SEQ_IS_REP0, + SEQ_SHORTREP, + SEQ_IS_REP0_LONG, + SEQ_IS_REP1, + SEQ_IS_REP2, + seq_len(SEQ_REP_LEN), + SEQ_COPY, + } sequence; + + /// Base of the current probability tree + probability *probs; + + /// Symbol being decoded. This is also used as an index variable in + /// bittree decoders: probs[symbol] + uint32_t symbol; + + /// Used as a loop termination condition on bittree decoders and + /// direct bits decoder. + uint32_t limit; + + /// Matched literal decoder: 0x100 or 0 to help avoiding branches. + /// Bittree reverse decoders: Offset of the next bit: 1 << offset + uint32_t offset; + + /// If decoding a literal: match byte. + /// If decoding a match: length of the match. + uint32_t len; +} lzma_lzma1_decoder; + + +static lzma_ret +lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr, + const uint8_t *restrict in, + size_t *restrict in_pos, size_t in_size) +{ + lzma_lzma1_decoder *restrict coder = coder_ptr; + + //////////////////// + // Initialization // + //////////////////// + + { + const lzma_ret ret = rc_read_init( + &coder->rc, in, in_pos, in_size); + if (ret != LZMA_STREAM_END) + return ret; + } + + /////////////// + // Variables // + /////////////// + + // Making local copies of often-used variables improves both + // speed and readability. + + lzma_dict dict = *dictptr; + + const size_t dict_start = dict.pos; + + // Range decoder + rc_to_local(coder->rc, *in_pos); + + // State + uint32_t state = coder->state; + uint32_t rep0 = coder->rep0; + uint32_t rep1 = coder->rep1; + uint32_t rep2 = coder->rep2; + uint32_t rep3 = coder->rep3; + + const uint32_t pos_mask = coder->pos_mask; + + // These variables are actually needed only if we last time ran + // out of input in the middle of the decoder loop. + probability *probs = coder->probs; + uint32_t symbol = coder->symbol; + uint32_t limit = coder->limit; + uint32_t offset = coder->offset; + uint32_t len = coder->len; + + const uint32_t literal_pos_mask = coder->literal_pos_mask; + const uint32_t literal_context_bits = coder->literal_context_bits; + + // Temporary variables + uint32_t pos_state = dict.pos & pos_mask; + + lzma_ret ret = LZMA_OK; + + // If uncompressed size is known, there must be no end of payload + // marker. + const bool no_eopm = coder->uncompressed_size + != LZMA_VLI_UNKNOWN; + if (no_eopm && coder->uncompressed_size < dict.limit - dict.pos) + dict.limit = dict.pos + (size_t)(coder->uncompressed_size); + + // The main decoder loop. The "switch" is used to restart the decoder at + // correct location. Once restarted, the "switch" is no longer used. + switch (coder->sequence) + while (true) { + // Calculate new pos_state. This is skipped on the first loop + // since we already calculated it when setting up the local + // variables. + pos_state = dict.pos & pos_mask; + + case SEQ_NORMALIZE: + case SEQ_IS_MATCH: + if (unlikely(no_eopm && dict.pos == dict.limit)) + break; + + rc_if_0(coder->is_match[state][pos_state], SEQ_IS_MATCH) { + rc_update_0(coder->is_match[state][pos_state]); + + // It's a literal i.e. a single 8-bit byte. + + probs = literal_subcoder(coder->literal, + literal_context_bits, literal_pos_mask, + dict.pos, dict_get(&dict, 0)); + symbol = 1; + + if (is_literal_state(state)) { + // Decode literal without match byte. +#ifdef HAVE_SMALL + case SEQ_LITERAL: + do { + rc_bit(probs[symbol], , , SEQ_LITERAL); + } while (symbol < (1 << 8)); +#else + rc_bit_case(probs[symbol], , , SEQ_LITERAL0); + rc_bit_case(probs[symbol], , , SEQ_LITERAL1); + rc_bit_case(probs[symbol], , , SEQ_LITERAL2); + rc_bit_case(probs[symbol], , , SEQ_LITERAL3); + rc_bit_case(probs[symbol], , , SEQ_LITERAL4); + rc_bit_case(probs[symbol], , , SEQ_LITERAL5); + rc_bit_case(probs[symbol], , , SEQ_LITERAL6); + rc_bit_case(probs[symbol], , , SEQ_LITERAL7); +#endif + } else { + // Decode literal with match byte. + // + // We store the byte we compare against + // ("match byte") to "len" to minimize the + // number of variables we need to store + // between decoder calls. + len = dict_get(&dict, rep0) << 1; + + // The usage of "offset" allows omitting some + // branches, which should give tiny speed + // improvement on some CPUs. "offset" gets + // set to zero if match_bit didn't match. + offset = 0x100; + +#ifdef HAVE_SMALL + case SEQ_LITERAL_MATCHED: + do { + const uint32_t match_bit + = len & offset; + const uint32_t subcoder_index + = offset + match_bit + + symbol; + + rc_bit(probs[subcoder_index], + offset &= ~match_bit, + offset &= match_bit, + SEQ_LITERAL_MATCHED); + + // It seems to be faster to do this + // here instead of putting it to the + // beginning of the loop and then + // putting the "case" in the middle + // of the loop. + len <<= 1; + + } while (symbol < (1 << 8)); +#else + // Unroll the loop. + uint32_t match_bit; + uint32_t subcoder_index; + +# define d(seq) \ + case seq: \ + match_bit = len & offset; \ + subcoder_index = offset + match_bit + symbol; \ + rc_bit(probs[subcoder_index], \ + offset &= ~match_bit, \ + offset &= match_bit, \ + seq) + + d(SEQ_LITERAL_MATCHED0); + len <<= 1; + d(SEQ_LITERAL_MATCHED1); + len <<= 1; + d(SEQ_LITERAL_MATCHED2); + len <<= 1; + d(SEQ_LITERAL_MATCHED3); + len <<= 1; + d(SEQ_LITERAL_MATCHED4); + len <<= 1; + d(SEQ_LITERAL_MATCHED5); + len <<= 1; + d(SEQ_LITERAL_MATCHED6); + len <<= 1; + d(SEQ_LITERAL_MATCHED7); +# undef d +#endif + } + + //update_literal(state); + // Use a lookup table to update to literal state, + // since compared to other state updates, this would + // need two branches. + static const lzma_lzma_state next_state[] = { + STATE_LIT_LIT, + STATE_LIT_LIT, + STATE_LIT_LIT, + 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_MATCH_LIT, + STATE_REP_LIT + }; + state = next_state[state]; + + case SEQ_LITERAL_WRITE: + if (unlikely(dict_put(&dict, symbol))) { + coder->sequence = SEQ_LITERAL_WRITE; + goto out; + } + + continue; + } + + // Instead of a new byte we are going to get a byte range + // (distance and length) which will be repeated from our + // output history. + + rc_update_1(coder->is_match[state][pos_state]); + + case SEQ_IS_REP: + rc_if_0(coder->is_rep[state], SEQ_IS_REP) { + // Not a repeated match + rc_update_0(coder->is_rep[state]); + update_match(state); + + // The latest three match distances are kept in + // memory in case there are repeated matches. + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + + // Decode the length of the match. + len_decode(len, coder->match_len_decoder, + pos_state, SEQ_MATCH_LEN); + + // Prepare to decode the highest two bits of the + // match distance. + probs = coder->dist_slot[get_dist_state(len)]; + symbol = 1; + +#ifdef HAVE_SMALL + case SEQ_DIST_SLOT: + do { + rc_bit(probs[symbol], , , SEQ_DIST_SLOT); + } while (symbol < DIST_SLOTS); +#else + rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT0); + rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT1); + rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT2); + rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT3); + rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT4); + rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT5); +#endif + // Get rid of the highest bit that was needed for + // indexing of the probability array. + symbol -= DIST_SLOTS; + assert(symbol <= 63); + + if (symbol < DIST_MODEL_START) { + // Match distances [0, 3] have only two bits. + rep0 = symbol; + } else { + // Decode the lowest [1, 29] bits of + // the match distance. + limit = (symbol >> 1) - 1; + assert(limit >= 1 && limit <= 30); + rep0 = 2 + (symbol & 1); + + if (symbol < DIST_MODEL_END) { + // Prepare to decode the low bits for + // a distance of [4, 127]. + assert(limit <= 5); + rep0 <<= limit; + assert(rep0 <= 96); + // -1 is fine, because we start + // decoding at probs[1], not probs[0]. + // NOTE: This violates the C standard, + // since we are doing pointer + // arithmetic past the beginning of + // the array. + assert((int32_t)(rep0 - symbol - 1) + >= -1); + assert((int32_t)(rep0 - symbol - 1) + <= 82); + probs = coder->pos_special + rep0 + - symbol - 1; + symbol = 1; + offset = 0; + case SEQ_DIST_MODEL: +#ifdef HAVE_SMALL + do { + rc_bit(probs[symbol], , + rep0 += 1 << offset, + SEQ_DIST_MODEL); + } while (++offset < limit); +#else + switch (limit) { + case 5: + assert(offset == 0); + rc_bit(probs[symbol], , + rep0 += 1, + SEQ_DIST_MODEL); + ++offset; + --limit; + case 4: + rc_bit(probs[symbol], , + rep0 += 1 << offset, + SEQ_DIST_MODEL); + ++offset; + --limit; + case 3: + rc_bit(probs[symbol], , + rep0 += 1 << offset, + SEQ_DIST_MODEL); + ++offset; + --limit; + case 2: + rc_bit(probs[symbol], , + rep0 += 1 << offset, + SEQ_DIST_MODEL); + ++offset; + --limit; + case 1: + // We need "symbol" only for + // indexing the probability + // array, thus we can use + // rc_bit_last() here to omit + // the unneeded updating of + // "symbol". + rc_bit_last(probs[symbol], , + rep0 += 1 << offset, + SEQ_DIST_MODEL); + } +#endif + } else { + // The distance is >= 128. Decode the + // lower bits without probabilities + // except the lowest four bits. + assert(symbol >= 14); + assert(limit >= 6); + limit -= ALIGN_BITS; + assert(limit >= 2); + case SEQ_DIRECT: + // Not worth manual unrolling + do { + rc_direct(rep0, SEQ_DIRECT); + } while (--limit > 0); + + // Decode the lowest four bits using + // probabilities. + rep0 <<= ALIGN_BITS; + symbol = 1; +#ifdef HAVE_SMALL + offset = 0; + case SEQ_ALIGN: + do { + rc_bit(coder->pos_align[ + symbol], , + rep0 += 1 << offset, + SEQ_ALIGN); + } while (++offset < ALIGN_BITS); +#else + case SEQ_ALIGN0: + rc_bit(coder->pos_align[symbol], , + rep0 += 1, SEQ_ALIGN0); + case SEQ_ALIGN1: + rc_bit(coder->pos_align[symbol], , + rep0 += 2, SEQ_ALIGN1); + case SEQ_ALIGN2: + rc_bit(coder->pos_align[symbol], , + rep0 += 4, SEQ_ALIGN2); + case SEQ_ALIGN3: + // Like in SEQ_DIST_MODEL, we don't + // need "symbol" for anything else + // than indexing the probability array. + rc_bit_last(coder->pos_align[symbol], , + rep0 += 8, SEQ_ALIGN3); +#endif + + if (rep0 == UINT32_MAX) { + // End of payload marker was + // found. It must not be + // present if uncompressed + // size is known. + if (coder->uncompressed_size + != LZMA_VLI_UNKNOWN) { + ret = LZMA_DATA_ERROR; + goto out; + } + + case SEQ_EOPM: + // LZMA1 stream with + // end-of-payload marker. + rc_normalize(SEQ_EOPM); + ret = LZMA_STREAM_END; + goto out; + } + } + } + + // Validate the distance we just decoded. + if (unlikely(!dict_is_distance_valid(&dict, rep0))) { + ret = LZMA_DATA_ERROR; + goto out; + } + + } else { + rc_update_1(coder->is_rep[state]); + + // Repeated match + // + // The match distance is a value that we have had + // earlier. The latest four match distances are + // available as rep0, rep1, rep2 and rep3. We will + // now decode which of them is the new distance. + // + // There cannot be a match if we haven't produced + // any output, so check that first. + if (unlikely(!dict_is_distance_valid(&dict, 0))) { + ret = LZMA_DATA_ERROR; + goto out; + } + + case SEQ_IS_REP0: + rc_if_0(coder->is_rep0[state], SEQ_IS_REP0) { + rc_update_0(coder->is_rep0[state]); + // The distance is rep0. + + case SEQ_IS_REP0_LONG: + rc_if_0(coder->is_rep0_long[state][pos_state], + SEQ_IS_REP0_LONG) { + rc_update_0(coder->is_rep0_long[ + state][pos_state]); + + update_short_rep(state); + + case SEQ_SHORTREP: + if (unlikely(dict_put(&dict, dict_get( + &dict, rep0)))) { + coder->sequence = SEQ_SHORTREP; + goto out; + } + + continue; + } + + // Repeating more than one byte at + // distance of rep0. + rc_update_1(coder->is_rep0_long[ + state][pos_state]); + + } else { + rc_update_1(coder->is_rep0[state]); + + case SEQ_IS_REP1: + // The distance is rep1, rep2 or rep3. Once + // we find out which one of these three, it + // is stored to rep0 and rep1, rep2 and rep3 + // are updated accordingly. + rc_if_0(coder->is_rep1[state], SEQ_IS_REP1) { + rc_update_0(coder->is_rep1[state]); + + const uint32_t distance = rep1; + rep1 = rep0; + rep0 = distance; + + } else { + rc_update_1(coder->is_rep1[state]); + case SEQ_IS_REP2: + rc_if_0(coder->is_rep2[state], + SEQ_IS_REP2) { + rc_update_0(coder->is_rep2[ + state]); + + const uint32_t distance = rep2; + rep2 = rep1; + rep1 = rep0; + rep0 = distance; + + } else { + rc_update_1(coder->is_rep2[ + state]); + + const uint32_t distance = rep3; + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + rep0 = distance; + } + } + } + + update_long_rep(state); + + // Decode the length of the repeated match. + len_decode(len, coder->rep_len_decoder, + pos_state, SEQ_REP_LEN); + } + + ///////////////////////////////// + // Repeat from history buffer. // + ///////////////////////////////// + + // The length is always between these limits. There is no way + // to trigger the algorithm to set len outside this range. + assert(len >= MATCH_LEN_MIN); + assert(len <= MATCH_LEN_MAX); + + case SEQ_COPY: + // Repeat len bytes from distance of rep0. + if (unlikely(dict_repeat(&dict, rep0, &len))) { + coder->sequence = SEQ_COPY; + goto out; + } + } + + rc_normalize(SEQ_NORMALIZE); + coder->sequence = SEQ_IS_MATCH; + +out: + // Save state + + // NOTE: Must not copy dict.limit. + dictptr->pos = dict.pos; + dictptr->full = dict.full; + + rc_from_local(coder->rc, *in_pos); + + coder->state = state; + coder->rep0 = rep0; + coder->rep1 = rep1; + coder->rep2 = rep2; + coder->rep3 = rep3; + + coder->probs = probs; + coder->symbol = symbol; + coder->limit = limit; + coder->offset = offset; + coder->len = len; + + // Update the remaining amount of uncompressed data if uncompressed + // size was known. + if (coder->uncompressed_size != LZMA_VLI_UNKNOWN) { + coder->uncompressed_size -= dict.pos - dict_start; + + // Since there cannot be end of payload marker if the + // uncompressed size was known, we check here if we + // finished decoding. + if (coder->uncompressed_size == 0 && ret == LZMA_OK + && coder->sequence != SEQ_NORMALIZE) + ret = coder->sequence == SEQ_IS_MATCH + ? LZMA_STREAM_END : LZMA_DATA_ERROR; + } + + // We can do an additional check in the range decoder to catch some + // corrupted files. + if (ret == LZMA_STREAM_END) { + if (!rc_is_finished(coder->rc)) + ret = LZMA_DATA_ERROR; + + // Reset the range decoder so that it is ready to reinitialize + // for a new LZMA2 chunk. + rc_reset(coder->rc); + } + + return ret; +} + + + +static void +lzma_decoder_uncompressed(void *coder_ptr, lzma_vli uncompressed_size) +{ + lzma_lzma1_decoder *coder = coder_ptr; + coder->uncompressed_size = uncompressed_size; +} + + +static void +lzma_decoder_reset(void *coder_ptr, const void *opt) +{ + lzma_lzma1_decoder *coder = coder_ptr; + const lzma_options_lzma *options = opt; + + // NOTE: We assume that lc/lp/pb are valid since they were + // successfully decoded with lzma_lzma_decode_properties(). + + // Calculate pos_mask. We don't need pos_bits as is for anything. + coder->pos_mask = (1U << options->pb) - 1; + + // Initialize the literal decoder. + literal_init(coder->literal, options->lc, options->lp); + + coder->literal_context_bits = options->lc; + coder->literal_pos_mask = (1U << options->lp) - 1; + + // State + coder->state = STATE_LIT_LIT; + coder->rep0 = 0; + coder->rep1 = 0; + coder->rep2 = 0; + coder->rep3 = 0; + coder->pos_mask = (1U << options->pb) - 1; + + // Range decoder + rc_reset(coder->rc); + + // Bit and bittree decoders + for (uint32_t i = 0; i < STATES; ++i) { + for (uint32_t j = 0; j <= coder->pos_mask; ++j) { + bit_reset(coder->is_match[i][j]); + bit_reset(coder->is_rep0_long[i][j]); + } + + bit_reset(coder->is_rep[i]); + bit_reset(coder->is_rep0[i]); + bit_reset(coder->is_rep1[i]); + bit_reset(coder->is_rep2[i]); + } + + for (uint32_t i = 0; i < DIST_STATES; ++i) + bittree_reset(coder->dist_slot[i], DIST_SLOT_BITS); + + for (uint32_t i = 0; i < FULL_DISTANCES - DIST_MODEL_END; ++i) + bit_reset(coder->pos_special[i]); + + bittree_reset(coder->pos_align, ALIGN_BITS); + + // Len decoders (also bit/bittree) + const uint32_t num_pos_states = 1U << options->pb; + bit_reset(coder->match_len_decoder.choice); + bit_reset(coder->match_len_decoder.choice2); + bit_reset(coder->rep_len_decoder.choice); + bit_reset(coder->rep_len_decoder.choice2); + + for (uint32_t pos_state = 0; pos_state < num_pos_states; ++pos_state) { + bittree_reset(coder->match_len_decoder.low[pos_state], + LEN_LOW_BITS); + bittree_reset(coder->match_len_decoder.mid[pos_state], + LEN_MID_BITS); + + bittree_reset(coder->rep_len_decoder.low[pos_state], + LEN_LOW_BITS); + bittree_reset(coder->rep_len_decoder.mid[pos_state], + LEN_MID_BITS); + } + + bittree_reset(coder->match_len_decoder.high, LEN_HIGH_BITS); + bittree_reset(coder->rep_len_decoder.high, LEN_HIGH_BITS); + + coder->sequence = SEQ_IS_MATCH; + coder->probs = NULL; + coder->symbol = 0; + coder->limit = 0; + coder->offset = 0; + coder->len = 0; + + return; +} + + +extern lzma_ret +lzma_lzma_decoder_create(lzma_lz_decoder *lz, const lzma_allocator *allocator, + const void *opt, lzma_lz_options *lz_options) +{ + if (lz->coder == NULL) { + lz->coder = lzma_alloc(sizeof(lzma_lzma1_decoder), allocator); + if (lz->coder == NULL) + return LZMA_MEM_ERROR; + + lz->code = &lzma_decode; + lz->reset = &lzma_decoder_reset; + lz->set_uncompressed = &lzma_decoder_uncompressed; + } + + // All dictionary sizes are OK here. LZ decoder will take care of + // the special cases. + const lzma_options_lzma *options = opt; + lz_options->dict_size = options->dict_size; + lz_options->preset_dict = options->preset_dict; + lz_options->preset_dict_size = options->preset_dict_size; + + return LZMA_OK; +} + + +/// Allocate and initialize LZMA decoder. This is used only via LZ +/// initialization (lzma_lzma_decoder_init() passes function pointer to +/// the LZ initialization). +static lzma_ret +lzma_decoder_init(lzma_lz_decoder *lz, const lzma_allocator *allocator, + const void *options, lzma_lz_options *lz_options) +{ + if (!is_lclppb_valid(options)) + return LZMA_PROG_ERROR; + + return_if_error(lzma_lzma_decoder_create( + lz, allocator, options, lz_options)); + + lzma_decoder_reset(lz->coder, options); + lzma_decoder_uncompressed(lz->coder, LZMA_VLI_UNKNOWN); + + return LZMA_OK; +} + + +extern lzma_ret +lzma_lzma_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter_info *filters) +{ + // LZMA can only be the last filter in the chain. This is enforced + // by the raw_decoder initialization. + assert(filters[1].init == NULL); + + return lzma_lz_decoder_init(next, allocator, filters, + &lzma_decoder_init); +} + + +extern bool +lzma_lzma_lclppb_decode(lzma_options_lzma *options, uint8_t byte) +{ + if (byte > (4 * 5 + 4) * 9 + 8) + return true; + + // See the file format specification to understand this. + options->pb = byte / (9 * 5); + byte -= options->pb * 9 * 5; + options->lp = byte / 9; + options->lc = byte - options->lp * 9; + + return options->lc + options->lp > LZMA_LCLP_MAX; +} + + +extern uint64_t +lzma_lzma_decoder_memusage_nocheck(const void *options) +{ + const lzma_options_lzma *const opt = options; + return sizeof(lzma_lzma1_decoder) + + lzma_lz_decoder_memusage(opt->dict_size); +} + + +extern uint64_t +lzma_lzma_decoder_memusage(const void *options) +{ + if (!is_lclppb_valid(options)) + return UINT64_MAX; + + return lzma_lzma_decoder_memusage_nocheck(options); +} + + +extern lzma_ret +lzma_lzma_props_decode(void **options, const lzma_allocator *allocator, + const uint8_t *props, size_t props_size) +{ + if (props_size != 5) + return LZMA_OPTIONS_ERROR; + + lzma_options_lzma *opt + = lzma_alloc(sizeof(lzma_options_lzma), allocator); + if (opt == NULL) + return LZMA_MEM_ERROR; + + if (lzma_lzma_lclppb_decode(opt, props[0])) + goto error; + + // All dictionary sizes are accepted, including zero. LZ decoder + // will automatically use a dictionary at least a few KiB even if + // a smaller dictionary is requested. + opt->dict_size = unaligned_read32le(props + 1); + + opt->preset_dict = NULL; + opt->preset_dict_size = 0; + + *options = opt; + + return LZMA_OK; + +error: + lzma_free(opt, allocator); + return LZMA_OPTIONS_ERROR; +} diff --git a/dependencies/cmliblzma/liblzma/lzma/lzma_decoder.h b/dependencies/cmliblzma/liblzma/lzma/lzma_decoder.h new file mode 100644 index 0000000..fa8ecb2 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/lzma/lzma_decoder.h @@ -0,0 +1,53 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file lzma_decoder.h +/// \brief LZMA decoder API +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_LZMA_DECODER_H +#define LZMA_LZMA_DECODER_H + +#include "common.h" + + +/// Allocates and initializes LZMA decoder +extern lzma_ret lzma_lzma_decoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters); + +extern uint64_t lzma_lzma_decoder_memusage(const void *options); + +extern lzma_ret lzma_lzma_props_decode( + void **options, const lzma_allocator *allocator, + const uint8_t *props, size_t props_size); + + +/// \brief Decodes the LZMA Properties byte (lc/lp/pb) +/// +/// \return true if error occurred, false on success +/// +extern bool lzma_lzma_lclppb_decode( + lzma_options_lzma *options, uint8_t byte); + + +#ifdef LZMA_LZ_DECODER_H +/// Allocate and setup function pointers only. This is used by LZMA1 and +/// LZMA2 decoders. +extern lzma_ret lzma_lzma_decoder_create( + lzma_lz_decoder *lz, const lzma_allocator *allocator, + const void *opt, lzma_lz_options *lz_options); + +/// Gets memory usage without validating lc/lp/pb. This is used by LZMA2 +/// decoder, because raw LZMA2 decoding doesn't need lc/lp/pb. +extern uint64_t lzma_lzma_decoder_memusage_nocheck(const void *options); + +#endif + +#endif diff --git a/dependencies/cmliblzma/liblzma/lzma/lzma_encoder.c b/dependencies/cmliblzma/liblzma/lzma/lzma_encoder.c new file mode 100644 index 0000000..ba9ce69 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/lzma/lzma_encoder.c @@ -0,0 +1,677 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file lzma_encoder.c +/// \brief LZMA encoder +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "lzma2_encoder.h" +#include "lzma_encoder_private.h" +#include "fastpos.h" + + +///////////// +// Literal // +///////////// + +static inline void +literal_matched(lzma_range_encoder *rc, probability *subcoder, + uint32_t match_byte, uint32_t symbol) +{ + uint32_t offset = 0x100; + symbol += UINT32_C(1) << 8; + + do { + match_byte <<= 1; + const uint32_t match_bit = match_byte & offset; + const uint32_t subcoder_index + = offset + match_bit + (symbol >> 8); + const uint32_t bit = (symbol >> 7) & 1; + rc_bit(rc, &subcoder[subcoder_index], bit); + + symbol <<= 1; + offset &= ~(match_byte ^ symbol); + + } while (symbol < (UINT32_C(1) << 16)); +} + + +static inline void +literal(lzma_lzma1_encoder *coder, lzma_mf *mf, uint32_t position) +{ + // Locate the literal byte to be encoded and the subcoder. + const uint8_t cur_byte = mf->buffer[ + mf->read_pos - mf->read_ahead]; + probability *subcoder = literal_subcoder(coder->literal, + coder->literal_context_bits, coder->literal_pos_mask, + position, mf->buffer[mf->read_pos - mf->read_ahead - 1]); + + if (is_literal_state(coder->state)) { + // Previous LZMA-symbol was a literal. Encode a normal + // literal without a match byte. + rc_bittree(&coder->rc, subcoder, 8, cur_byte); + } else { + // Previous LZMA-symbol was a match. Use the last byte of + // the match as a "match byte". That is, compare the bits + // of the current literal and the match byte. + const uint8_t match_byte = mf->buffer[ + mf->read_pos - coder->reps[0] - 1 + - mf->read_ahead]; + literal_matched(&coder->rc, subcoder, match_byte, cur_byte); + } + + update_literal(coder->state); +} + + +////////////////// +// Match length // +////////////////// + +static void +length_update_prices(lzma_length_encoder *lc, const uint32_t pos_state) +{ + const uint32_t table_size = lc->table_size; + lc->counters[pos_state] = table_size; + + const uint32_t a0 = rc_bit_0_price(lc->choice); + const uint32_t a1 = rc_bit_1_price(lc->choice); + const uint32_t b0 = a1 + rc_bit_0_price(lc->choice2); + const uint32_t b1 = a1 + rc_bit_1_price(lc->choice2); + uint32_t *const prices = lc->prices[pos_state]; + + uint32_t i; + for (i = 0; i < table_size && i < LEN_LOW_SYMBOLS; ++i) + prices[i] = a0 + rc_bittree_price(lc->low[pos_state], + LEN_LOW_BITS, i); + + for (; i < table_size && i < LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS; ++i) + prices[i] = b0 + rc_bittree_price(lc->mid[pos_state], + LEN_MID_BITS, i - LEN_LOW_SYMBOLS); + + for (; i < table_size; ++i) + prices[i] = b1 + rc_bittree_price(lc->high, LEN_HIGH_BITS, + i - LEN_LOW_SYMBOLS - LEN_MID_SYMBOLS); + + return; +} + + +static inline void +length(lzma_range_encoder *rc, lzma_length_encoder *lc, + const uint32_t pos_state, uint32_t len, const bool fast_mode) +{ + assert(len <= MATCH_LEN_MAX); + len -= MATCH_LEN_MIN; + + if (len < LEN_LOW_SYMBOLS) { + rc_bit(rc, &lc->choice, 0); + rc_bittree(rc, lc->low[pos_state], LEN_LOW_BITS, len); + } else { + rc_bit(rc, &lc->choice, 1); + len -= LEN_LOW_SYMBOLS; + + if (len < LEN_MID_SYMBOLS) { + rc_bit(rc, &lc->choice2, 0); + rc_bittree(rc, lc->mid[pos_state], LEN_MID_BITS, len); + } else { + rc_bit(rc, &lc->choice2, 1); + len -= LEN_MID_SYMBOLS; + rc_bittree(rc, lc->high, LEN_HIGH_BITS, len); + } + } + + // Only getoptimum uses the prices so don't update the table when + // in fast mode. + if (!fast_mode) + if (--lc->counters[pos_state] == 0) + length_update_prices(lc, pos_state); +} + + +/////////// +// Match // +/////////// + +static inline void +match(lzma_lzma1_encoder *coder, const uint32_t pos_state, + const uint32_t distance, const uint32_t len) +{ + update_match(coder->state); + + length(&coder->rc, &coder->match_len_encoder, pos_state, len, + coder->fast_mode); + + const uint32_t dist_slot = get_dist_slot(distance); + const uint32_t dist_state = get_dist_state(len); + rc_bittree(&coder->rc, coder->dist_slot[dist_state], + DIST_SLOT_BITS, dist_slot); + + if (dist_slot >= DIST_MODEL_START) { + const uint32_t footer_bits = (dist_slot >> 1) - 1; + const uint32_t base = (2 | (dist_slot & 1)) << footer_bits; + const uint32_t dist_reduced = distance - base; + + if (dist_slot < DIST_MODEL_END) { + // Careful here: base - dist_slot - 1 can be -1, but + // rc_bittree_reverse starts at probs[1], not probs[0]. + rc_bittree_reverse(&coder->rc, + coder->dist_special + base - dist_slot - 1, + footer_bits, dist_reduced); + } else { + rc_direct(&coder->rc, dist_reduced >> ALIGN_BITS, + footer_bits - ALIGN_BITS); + rc_bittree_reverse( + &coder->rc, coder->dist_align, + ALIGN_BITS, dist_reduced & ALIGN_MASK); + ++coder->align_price_count; + } + } + + coder->reps[3] = coder->reps[2]; + coder->reps[2] = coder->reps[1]; + coder->reps[1] = coder->reps[0]; + coder->reps[0] = distance; + ++coder->match_price_count; +} + + +//////////////////// +// Repeated match // +//////////////////// + +static inline void +rep_match(lzma_lzma1_encoder *coder, const uint32_t pos_state, + const uint32_t rep, const uint32_t len) +{ + if (rep == 0) { + rc_bit(&coder->rc, &coder->is_rep0[coder->state], 0); + rc_bit(&coder->rc, + &coder->is_rep0_long[coder->state][pos_state], + len != 1); + } else { + const uint32_t distance = coder->reps[rep]; + rc_bit(&coder->rc, &coder->is_rep0[coder->state], 1); + + if (rep == 1) { + rc_bit(&coder->rc, &coder->is_rep1[coder->state], 0); + } else { + rc_bit(&coder->rc, &coder->is_rep1[coder->state], 1); + rc_bit(&coder->rc, &coder->is_rep2[coder->state], + rep - 2); + + if (rep == 3) + coder->reps[3] = coder->reps[2]; + + coder->reps[2] = coder->reps[1]; + } + + coder->reps[1] = coder->reps[0]; + coder->reps[0] = distance; + } + + if (len == 1) { + update_short_rep(coder->state); + } else { + length(&coder->rc, &coder->rep_len_encoder, pos_state, len, + coder->fast_mode); + update_long_rep(coder->state); + } +} + + +////////// +// Main // +////////// + +static void +encode_symbol(lzma_lzma1_encoder *coder, lzma_mf *mf, + uint32_t back, uint32_t len, uint32_t position) +{ + const uint32_t pos_state = position & coder->pos_mask; + + if (back == UINT32_MAX) { + // Literal i.e. eight-bit byte + assert(len == 1); + rc_bit(&coder->rc, + &coder->is_match[coder->state][pos_state], 0); + literal(coder, mf, position); + } else { + // Some type of match + rc_bit(&coder->rc, + &coder->is_match[coder->state][pos_state], 1); + + if (back < REPS) { + // It's a repeated match i.e. the same distance + // has been used earlier. + rc_bit(&coder->rc, &coder->is_rep[coder->state], 1); + rep_match(coder, pos_state, back, len); + } else { + // Normal match + rc_bit(&coder->rc, &coder->is_rep[coder->state], 0); + match(coder, pos_state, back - REPS, len); + } + } + + assert(mf->read_ahead >= len); + mf->read_ahead -= len; +} + + +static bool +encode_init(lzma_lzma1_encoder *coder, lzma_mf *mf) +{ + assert(mf_position(mf) == 0); + + if (mf->read_pos == mf->read_limit) { + if (mf->action == LZMA_RUN) + return false; // We cannot do anything. + + // We are finishing (we cannot get here when flushing). + assert(mf->write_pos == mf->read_pos); + assert(mf->action == LZMA_FINISH); + } else { + // Do the actual initialization. The first LZMA symbol must + // always be a literal. + mf_skip(mf, 1); + mf->read_ahead = 0; + rc_bit(&coder->rc, &coder->is_match[0][0], 0); + rc_bittree(&coder->rc, coder->literal[0], 8, mf->buffer[0]); + } + + // Initialization is done (except if empty file). + coder->is_initialized = true; + + return true; +} + + +static void +encode_eopm(lzma_lzma1_encoder *coder, uint32_t position) +{ + const uint32_t pos_state = position & coder->pos_mask; + rc_bit(&coder->rc, &coder->is_match[coder->state][pos_state], 1); + rc_bit(&coder->rc, &coder->is_rep[coder->state], 0); + match(coder, pos_state, UINT32_MAX, MATCH_LEN_MIN); +} + + +/// Number of bytes that a single encoding loop in lzma_lzma_encode() can +/// consume from the dictionary. This limit comes from lzma_lzma_optimum() +/// and may need to be updated if that function is significantly modified. +#define LOOP_INPUT_MAX (OPTS + 1) + + +extern lzma_ret +lzma_lzma_encode(lzma_lzma1_encoder *restrict coder, lzma_mf *restrict mf, + uint8_t *restrict out, size_t *restrict out_pos, + size_t out_size, uint32_t limit) +{ + // Initialize the stream if no data has been encoded yet. + if (!coder->is_initialized && !encode_init(coder, mf)) + return LZMA_OK; + + // Get the lowest bits of the uncompressed offset from the LZ layer. + uint32_t position = mf_position(mf); + + while (true) { + // Encode pending bits, if any. Calling this before encoding + // the next symbol is needed only with plain LZMA, since + // LZMA2 always provides big enough buffer to flush + // everything out from the range encoder. For the same reason, + // rc_encode() never returns true when this function is used + // as part of LZMA2 encoder. + if (rc_encode(&coder->rc, out, out_pos, out_size)) { + assert(limit == UINT32_MAX); + return LZMA_OK; + } + + // With LZMA2 we need to take care that compressed size of + // a chunk doesn't get too big. + // FIXME? Check if this could be improved. + if (limit != UINT32_MAX + && (mf->read_pos - mf->read_ahead >= limit + || *out_pos + rc_pending(&coder->rc) + >= LZMA2_CHUNK_MAX + - LOOP_INPUT_MAX)) + break; + + // Check that there is some input to process. + if (mf->read_pos >= mf->read_limit) { + if (mf->action == LZMA_RUN) + return LZMA_OK; + + if (mf->read_ahead == 0) + break; + } + + // Get optimal match (repeat position and length). + // Value ranges for pos: + // - [0, REPS): repeated match + // - [REPS, UINT32_MAX): + // match at (pos - REPS) + // - UINT32_MAX: not a match but a literal + // Value ranges for len: + // - [MATCH_LEN_MIN, MATCH_LEN_MAX] + uint32_t len; + uint32_t back; + + if (coder->fast_mode) + lzma_lzma_optimum_fast(coder, mf, &back, &len); + else + lzma_lzma_optimum_normal( + coder, mf, &back, &len, position); + + encode_symbol(coder, mf, back, len, position); + + position += len; + } + + if (!coder->is_flushed) { + coder->is_flushed = true; + + // We don't support encoding plain LZMA streams without EOPM, + // and LZMA2 doesn't use EOPM at LZMA level. + if (limit == UINT32_MAX) + encode_eopm(coder, position); + + // Flush the remaining bytes from the range encoder. + rc_flush(&coder->rc); + + // Copy the remaining bytes to the output buffer. If there + // isn't enough output space, we will copy out the remaining + // bytes on the next call to this function by using + // the rc_encode() call in the encoding loop above. + if (rc_encode(&coder->rc, out, out_pos, out_size)) { + assert(limit == UINT32_MAX); + return LZMA_OK; + } + } + + // Make it ready for the next LZMA2 chunk. + coder->is_flushed = false; + + return LZMA_STREAM_END; +} + + +static lzma_ret +lzma_encode(void *coder, lzma_mf *restrict mf, + uint8_t *restrict out, size_t *restrict out_pos, + size_t out_size) +{ + // Plain LZMA has no support for sync-flushing. + if (unlikely(mf->action == LZMA_SYNC_FLUSH)) + return LZMA_OPTIONS_ERROR; + + return lzma_lzma_encode(coder, mf, out, out_pos, out_size, UINT32_MAX); +} + + +//////////////////// +// Initialization // +//////////////////// + +static bool +is_options_valid(const lzma_options_lzma *options) +{ + // Validate some of the options. LZ encoder validates nice_len too + // but we need a valid value here earlier. + return is_lclppb_valid(options) + && options->nice_len >= MATCH_LEN_MIN + && options->nice_len <= MATCH_LEN_MAX + && (options->mode == LZMA_MODE_FAST + || options->mode == LZMA_MODE_NORMAL); +} + + +static void +set_lz_options(lzma_lz_options *lz_options, const lzma_options_lzma *options) +{ + // LZ encoder initialization does the validation for these so we + // don't need to validate here. + lz_options->before_size = OPTS; + lz_options->dict_size = options->dict_size; + lz_options->after_size = LOOP_INPUT_MAX; + lz_options->match_len_max = MATCH_LEN_MAX; + lz_options->nice_len = options->nice_len; + lz_options->match_finder = options->mf; + lz_options->depth = options->depth; + lz_options->preset_dict = options->preset_dict; + lz_options->preset_dict_size = options->preset_dict_size; + return; +} + + +static void +length_encoder_reset(lzma_length_encoder *lencoder, + const uint32_t num_pos_states, const bool fast_mode) +{ + bit_reset(lencoder->choice); + bit_reset(lencoder->choice2); + + for (size_t pos_state = 0; pos_state < num_pos_states; ++pos_state) { + bittree_reset(lencoder->low[pos_state], LEN_LOW_BITS); + bittree_reset(lencoder->mid[pos_state], LEN_MID_BITS); + } + + bittree_reset(lencoder->high, LEN_HIGH_BITS); + + if (!fast_mode) + for (uint32_t pos_state = 0; pos_state < num_pos_states; + ++pos_state) + length_update_prices(lencoder, pos_state); + + return; +} + + +extern lzma_ret +lzma_lzma_encoder_reset(lzma_lzma1_encoder *coder, + const lzma_options_lzma *options) +{ + if (!is_options_valid(options)) + return LZMA_OPTIONS_ERROR; + + coder->pos_mask = (1U << options->pb) - 1; + coder->literal_context_bits = options->lc; + coder->literal_pos_mask = (1U << options->lp) - 1; + + // Range coder + rc_reset(&coder->rc); + + // State + coder->state = STATE_LIT_LIT; + for (size_t i = 0; i < REPS; ++i) + coder->reps[i] = 0; + + literal_init(coder->literal, options->lc, options->lp); + + // Bit encoders + for (size_t i = 0; i < STATES; ++i) { + for (size_t j = 0; j <= coder->pos_mask; ++j) { + bit_reset(coder->is_match[i][j]); + bit_reset(coder->is_rep0_long[i][j]); + } + + bit_reset(coder->is_rep[i]); + bit_reset(coder->is_rep0[i]); + bit_reset(coder->is_rep1[i]); + bit_reset(coder->is_rep2[i]); + } + + for (size_t i = 0; i < FULL_DISTANCES - DIST_MODEL_END; ++i) + bit_reset(coder->dist_special[i]); + + // Bit tree encoders + for (size_t i = 0; i < DIST_STATES; ++i) + bittree_reset(coder->dist_slot[i], DIST_SLOT_BITS); + + bittree_reset(coder->dist_align, ALIGN_BITS); + + // Length encoders + length_encoder_reset(&coder->match_len_encoder, + 1U << options->pb, coder->fast_mode); + + length_encoder_reset(&coder->rep_len_encoder, + 1U << options->pb, coder->fast_mode); + + // Price counts are incremented every time appropriate probabilities + // are changed. price counts are set to zero when the price tables + // are updated, which is done when the appropriate price counts have + // big enough value, and lzma_mf.read_ahead == 0 which happens at + // least every OPTS (a few thousand) possible price count increments. + // + // By resetting price counts to UINT32_MAX / 2, we make sure that the + // price tables will be initialized before they will be used (since + // the value is definitely big enough), and that it is OK to increment + // price counts without risk of integer overflow (since UINT32_MAX / 2 + // is small enough). The current code doesn't increment price counts + // before initializing price tables, but it maybe done in future if + // we add support for saving the state between LZMA2 chunks. + coder->match_price_count = UINT32_MAX / 2; + coder->align_price_count = UINT32_MAX / 2; + + coder->opts_end_index = 0; + coder->opts_current_index = 0; + + return LZMA_OK; +} + + +extern lzma_ret +lzma_lzma_encoder_create(void **coder_ptr, + const lzma_allocator *allocator, + const lzma_options_lzma *options, lzma_lz_options *lz_options) +{ + // Allocate lzma_lzma1_encoder if it wasn't already allocated. + if (*coder_ptr == NULL) { + *coder_ptr = lzma_alloc(sizeof(lzma_lzma1_encoder), allocator); + if (*coder_ptr == NULL) + return LZMA_MEM_ERROR; + } + + lzma_lzma1_encoder *coder = *coder_ptr; + + // Set compression mode. We haven't validates the options yet, + // but it's OK here, since nothing bad happens with invalid + // options in the code below, and they will get rejected by + // lzma_lzma_encoder_reset() call at the end of this function. + switch (options->mode) { + case LZMA_MODE_FAST: + coder->fast_mode = true; + break; + + case LZMA_MODE_NORMAL: { + coder->fast_mode = false; + + // Set dist_table_size. + // Round the dictionary size up to next 2^n. + uint32_t log_size = 0; + while ((UINT32_C(1) << log_size) < options->dict_size) + ++log_size; + + coder->dist_table_size = log_size * 2; + + // Length encoders' price table size + coder->match_len_encoder.table_size + = options->nice_len + 1 - MATCH_LEN_MIN; + coder->rep_len_encoder.table_size + = options->nice_len + 1 - MATCH_LEN_MIN; + break; + } + + default: + return LZMA_OPTIONS_ERROR; + } + + // We don't need to write the first byte as literal if there is + // a non-empty preset dictionary. encode_init() wouldn't even work + // if there is a non-empty preset dictionary, because encode_init() + // assumes that position is zero and previous byte is also zero. + coder->is_initialized = options->preset_dict != NULL + && options->preset_dict_size > 0; + coder->is_flushed = false; + + set_lz_options(lz_options, options); + + return lzma_lzma_encoder_reset(coder, options); +} + + +static lzma_ret +lzma_encoder_init(lzma_lz_encoder *lz, const lzma_allocator *allocator, + const void *options, lzma_lz_options *lz_options) +{ + lz->code = &lzma_encode; + return lzma_lzma_encoder_create( + &lz->coder, allocator, options, lz_options); +} + + +extern lzma_ret +lzma_lzma_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter_info *filters) +{ + return lzma_lz_encoder_init( + next, allocator, filters, &lzma_encoder_init); +} + + +extern uint64_t +lzma_lzma_encoder_memusage(const void *options) +{ + if (!is_options_valid(options)) + return UINT64_MAX; + + lzma_lz_options lz_options; + set_lz_options(&lz_options, options); + + const uint64_t lz_memusage = lzma_lz_encoder_memusage(&lz_options); + if (lz_memusage == UINT64_MAX) + return UINT64_MAX; + + return (uint64_t)(sizeof(lzma_lzma1_encoder)) + lz_memusage; +} + + +extern bool +lzma_lzma_lclppb_encode(const lzma_options_lzma *options, uint8_t *byte) +{ + if (!is_lclppb_valid(options)) + return true; + + *byte = (options->pb * 5 + options->lp) * 9 + options->lc; + assert(*byte <= (4 * 5 + 4) * 9 + 8); + + return false; +} + + +#ifdef HAVE_ENCODER_LZMA1 +extern lzma_ret +lzma_lzma_props_encode(const void *options, uint8_t *out) +{ + const lzma_options_lzma *const opt = options; + + if (lzma_lzma_lclppb_encode(opt, out)) + return LZMA_PROG_ERROR; + + unaligned_write32le(out + 1, opt->dict_size); + + return LZMA_OK; +} +#endif + + +extern LZMA_API(lzma_bool) +lzma_mode_is_supported(lzma_mode mode) +{ + return mode == LZMA_MODE_FAST || mode == LZMA_MODE_NORMAL; +} diff --git a/dependencies/cmliblzma/liblzma/lzma/lzma_encoder.h b/dependencies/cmliblzma/liblzma/lzma/lzma_encoder.h new file mode 100644 index 0000000..6cfdf22 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/lzma/lzma_encoder.h @@ -0,0 +1,58 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file lzma_encoder.h +/// \brief LZMA encoder API +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_LZMA_ENCODER_H +#define LZMA_LZMA_ENCODER_H + +#include "common.h" + + +typedef struct lzma_lzma1_encoder_s lzma_lzma1_encoder; + + +extern lzma_ret lzma_lzma_encoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters); + + +extern uint64_t lzma_lzma_encoder_memusage(const void *options); + +extern lzma_ret lzma_lzma_props_encode(const void *options, uint8_t *out); + + +/// Encodes lc/lp/pb into one byte. Returns false on success and true on error. +extern bool lzma_lzma_lclppb_encode( + const lzma_options_lzma *options, uint8_t *byte); + + +#ifdef LZMA_LZ_ENCODER_H + +/// Initializes raw LZMA encoder; this is used by LZMA2. +extern lzma_ret lzma_lzma_encoder_create( + void **coder_ptr, const lzma_allocator *allocator, + const lzma_options_lzma *options, lzma_lz_options *lz_options); + + +/// Resets an already initialized LZMA encoder; this is used by LZMA2. +extern lzma_ret lzma_lzma_encoder_reset( + lzma_lzma1_encoder *coder, const lzma_options_lzma *options); + + +extern lzma_ret lzma_lzma_encode(lzma_lzma1_encoder *restrict coder, + lzma_mf *restrict mf, uint8_t *restrict out, + size_t *restrict out_pos, size_t out_size, + uint32_t read_limit); + +#endif + +#endif diff --git a/dependencies/cmliblzma/liblzma/lzma/lzma_encoder_optimum_fast.c b/dependencies/cmliblzma/liblzma/lzma/lzma_encoder_optimum_fast.c new file mode 100644 index 0000000..6c53d2b --- /dev/null +++ b/dependencies/cmliblzma/liblzma/lzma/lzma_encoder_optimum_fast.c @@ -0,0 +1,170 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file lzma_encoder_optimum_fast.c +// +// Author: Igor Pavlov +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "lzma_encoder_private.h" +#include "memcmplen.h" + + +#define change_pair(small_dist, big_dist) \ + (((big_dist) >> 7) > (small_dist)) + + +extern void +lzma_lzma_optimum_fast(lzma_lzma1_encoder *restrict coder, + lzma_mf *restrict mf, + uint32_t *restrict back_res, uint32_t *restrict len_res) +{ + const uint32_t nice_len = mf->nice_len; + + uint32_t len_main; + uint32_t matches_count; + if (mf->read_ahead == 0) { + len_main = mf_find(mf, &matches_count, coder->matches); + } else { + assert(mf->read_ahead == 1); + len_main = coder->longest_match_length; + matches_count = coder->matches_count; + } + + const uint8_t *buf = mf_ptr(mf) - 1; + const uint32_t buf_avail = my_min(mf_avail(mf) + 1, MATCH_LEN_MAX); + + if (buf_avail < 2) { + // There's not enough input left to encode a match. + *back_res = UINT32_MAX; + *len_res = 1; + return; + } + + // Look for repeated matches; scan the previous four match distances + uint32_t rep_len = 0; + uint32_t rep_index = 0; + + for (uint32_t i = 0; i < REPS; ++i) { + // Pointer to the beginning of the match candidate + const uint8_t *const buf_back = buf - coder->reps[i] - 1; + + // If the first two bytes (2 == MATCH_LEN_MIN) do not match, + // this rep is not useful. + if (not_equal_16(buf, buf_back)) + continue; + + // The first two bytes matched. + // Calculate the length of the match. + const uint32_t len = lzma_memcmplen( + buf, buf_back, 2, buf_avail); + + // If we have found a repeated match that is at least + // nice_len long, return it immediately. + if (len >= nice_len) { + *back_res = i; + *len_res = len; + mf_skip(mf, len - 1); + return; + } + + if (len > rep_len) { + rep_index = i; + rep_len = len; + } + } + + // We didn't find a long enough repeated match. Encode it as a normal + // match if the match length is at least nice_len. + if (len_main >= nice_len) { + *back_res = coder->matches[matches_count - 1].dist + REPS; + *len_res = len_main; + mf_skip(mf, len_main - 1); + return; + } + + uint32_t back_main = 0; + if (len_main >= 2) { + back_main = coder->matches[matches_count - 1].dist; + + while (matches_count > 1 && len_main == + coder->matches[matches_count - 2].len + 1) { + if (!change_pair(coder->matches[ + matches_count - 2].dist, + back_main)) + break; + + --matches_count; + len_main = coder->matches[matches_count - 1].len; + back_main = coder->matches[matches_count - 1].dist; + } + + if (len_main == 2 && back_main >= 0x80) + len_main = 1; + } + + if (rep_len >= 2) { + if (rep_len + 1 >= len_main + || (rep_len + 2 >= len_main + && back_main > (UINT32_C(1) << 9)) + || (rep_len + 3 >= len_main + && back_main > (UINT32_C(1) << 15))) { + *back_res = rep_index; + *len_res = rep_len; + mf_skip(mf, rep_len - 1); + return; + } + } + + if (len_main < 2 || buf_avail <= 2) { + *back_res = UINT32_MAX; + *len_res = 1; + return; + } + + // Get the matches for the next byte. If we find a better match, + // the current byte is encoded as a literal. + coder->longest_match_length = mf_find(mf, + &coder->matches_count, coder->matches); + + if (coder->longest_match_length >= 2) { + const uint32_t new_dist = coder->matches[ + coder->matches_count - 1].dist; + + if ((coder->longest_match_length >= len_main + && new_dist < back_main) + || (coder->longest_match_length == len_main + 1 + && !change_pair(back_main, new_dist)) + || (coder->longest_match_length > len_main + 1) + || (coder->longest_match_length + 1 >= len_main + && len_main >= 3 + && change_pair(new_dist, back_main))) { + *back_res = UINT32_MAX; + *len_res = 1; + return; + } + } + + // In contrast to LZMA SDK, dictionary could not have been moved + // between mf_find() calls, thus it is safe to just increment + // the old buf pointer instead of recalculating it with mf_ptr(). + ++buf; + + const uint32_t limit = my_max(2, len_main - 1); + + for (uint32_t i = 0; i < REPS; ++i) { + if (memcmp(buf, buf - coder->reps[i] - 1, limit) == 0) { + *back_res = UINT32_MAX; + *len_res = 1; + return; + } + } + + *back_res = back_main + REPS; + *len_res = len_main; + mf_skip(mf, len_main - 2); + return; +} diff --git a/dependencies/cmliblzma/liblzma/lzma/lzma_encoder_optimum_normal.c b/dependencies/cmliblzma/liblzma/lzma/lzma_encoder_optimum_normal.c new file mode 100644 index 0000000..59f7734 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/lzma/lzma_encoder_optimum_normal.c @@ -0,0 +1,855 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file lzma_encoder_optimum_normal.c +// +// Author: Igor Pavlov +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "lzma_encoder_private.h" +#include "fastpos.h" +#include "memcmplen.h" + + +//////////// +// Prices // +//////////// + +static uint32_t +get_literal_price(const lzma_lzma1_encoder *const coder, const uint32_t pos, + const uint32_t prev_byte, const bool match_mode, + uint32_t match_byte, uint32_t symbol) +{ + const probability *const subcoder = literal_subcoder(coder->literal, + coder->literal_context_bits, coder->literal_pos_mask, + pos, prev_byte); + + uint32_t price = 0; + + if (!match_mode) { + price = rc_bittree_price(subcoder, 8, symbol); + } else { + uint32_t offset = 0x100; + symbol += UINT32_C(1) << 8; + + do { + match_byte <<= 1; + + const uint32_t match_bit = match_byte & offset; + const uint32_t subcoder_index + = offset + match_bit + (symbol >> 8); + const uint32_t bit = (symbol >> 7) & 1; + price += rc_bit_price(subcoder[subcoder_index], bit); + + symbol <<= 1; + offset &= ~(match_byte ^ symbol); + + } while (symbol < (UINT32_C(1) << 16)); + } + + return price; +} + + +static inline uint32_t +get_len_price(const lzma_length_encoder *const lencoder, + const uint32_t len, const uint32_t pos_state) +{ + // NOTE: Unlike the other price tables, length prices are updated + // in lzma_encoder.c + return lencoder->prices[pos_state][len - MATCH_LEN_MIN]; +} + + +static inline uint32_t +get_short_rep_price(const lzma_lzma1_encoder *const coder, + const lzma_lzma_state state, const uint32_t pos_state) +{ + return rc_bit_0_price(coder->is_rep0[state]) + + rc_bit_0_price(coder->is_rep0_long[state][pos_state]); +} + + +static inline uint32_t +get_pure_rep_price(const lzma_lzma1_encoder *const coder, const uint32_t rep_index, + const lzma_lzma_state state, uint32_t pos_state) +{ + uint32_t price; + + if (rep_index == 0) { + price = rc_bit_0_price(coder->is_rep0[state]); + price += rc_bit_1_price(coder->is_rep0_long[state][pos_state]); + } else { + price = rc_bit_1_price(coder->is_rep0[state]); + + if (rep_index == 1) { + price += rc_bit_0_price(coder->is_rep1[state]); + } else { + price += rc_bit_1_price(coder->is_rep1[state]); + price += rc_bit_price(coder->is_rep2[state], + rep_index - 2); + } + } + + return price; +} + + +static inline uint32_t +get_rep_price(const lzma_lzma1_encoder *const coder, const uint32_t rep_index, + const uint32_t len, const lzma_lzma_state state, + const uint32_t pos_state) +{ + return get_len_price(&coder->rep_len_encoder, len, pos_state) + + get_pure_rep_price(coder, rep_index, state, pos_state); +} + + +static inline uint32_t +get_dist_len_price(const lzma_lzma1_encoder *const coder, const uint32_t dist, + const uint32_t len, const uint32_t pos_state) +{ + const uint32_t dist_state = get_dist_state(len); + uint32_t price; + + if (dist < FULL_DISTANCES) { + price = coder->dist_prices[dist_state][dist]; + } else { + const uint32_t dist_slot = get_dist_slot_2(dist); + price = coder->dist_slot_prices[dist_state][dist_slot] + + coder->align_prices[dist & ALIGN_MASK]; + } + + price += get_len_price(&coder->match_len_encoder, len, pos_state); + + return price; +} + + +static void +fill_dist_prices(lzma_lzma1_encoder *coder) +{ + for (uint32_t dist_state = 0; dist_state < DIST_STATES; ++dist_state) { + + uint32_t *const dist_slot_prices + = coder->dist_slot_prices[dist_state]; + + // Price to encode the dist_slot. + for (uint32_t dist_slot = 0; + dist_slot < coder->dist_table_size; ++dist_slot) + dist_slot_prices[dist_slot] = rc_bittree_price( + coder->dist_slot[dist_state], + DIST_SLOT_BITS, dist_slot); + + // For matches with distance >= FULL_DISTANCES, add the price + // of the direct bits part of the match distance. (Align bits + // are handled by fill_align_prices()). + for (uint32_t dist_slot = DIST_MODEL_END; + dist_slot < coder->dist_table_size; + ++dist_slot) + dist_slot_prices[dist_slot] += rc_direct_price( + ((dist_slot >> 1) - 1) - ALIGN_BITS); + + // Distances in the range [0, 3] are fully encoded with + // dist_slot, so they are used for coder->dist_prices + // as is. + for (uint32_t i = 0; i < DIST_MODEL_START; ++i) + coder->dist_prices[dist_state][i] + = dist_slot_prices[i]; + } + + // Distances in the range [4, 127] depend on dist_slot and + // dist_special. We do this in a loop separate from the above + // loop to avoid redundant calls to get_dist_slot(). + for (uint32_t i = DIST_MODEL_START; i < FULL_DISTANCES; ++i) { + const uint32_t dist_slot = get_dist_slot(i); + const uint32_t footer_bits = ((dist_slot >> 1) - 1); + const uint32_t base = (2 | (dist_slot & 1)) << footer_bits; + const uint32_t price = rc_bittree_reverse_price( + coder->dist_special + base - dist_slot - 1, + footer_bits, i - base); + + for (uint32_t dist_state = 0; dist_state < DIST_STATES; + ++dist_state) + coder->dist_prices[dist_state][i] + = price + coder->dist_slot_prices[ + dist_state][dist_slot]; + } + + coder->match_price_count = 0; + return; +} + + +static void +fill_align_prices(lzma_lzma1_encoder *coder) +{ + for (uint32_t i = 0; i < ALIGN_SIZE; ++i) + coder->align_prices[i] = rc_bittree_reverse_price( + coder->dist_align, ALIGN_BITS, i); + + coder->align_price_count = 0; + return; +} + + +///////////// +// Optimal // +///////////// + +static inline void +make_literal(lzma_optimal *optimal) +{ + optimal->back_prev = UINT32_MAX; + optimal->prev_1_is_literal = false; +} + + +static inline void +make_short_rep(lzma_optimal *optimal) +{ + optimal->back_prev = 0; + optimal->prev_1_is_literal = false; +} + + +#define is_short_rep(optimal) \ + ((optimal).back_prev == 0) + + +static void +backward(lzma_lzma1_encoder *restrict coder, uint32_t *restrict len_res, + uint32_t *restrict back_res, uint32_t cur) +{ + coder->opts_end_index = cur; + + uint32_t pos_mem = coder->opts[cur].pos_prev; + uint32_t back_mem = coder->opts[cur].back_prev; + + do { + if (coder->opts[cur].prev_1_is_literal) { + make_literal(&coder->opts[pos_mem]); + coder->opts[pos_mem].pos_prev = pos_mem - 1; + + if (coder->opts[cur].prev_2) { + coder->opts[pos_mem - 1].prev_1_is_literal + = false; + coder->opts[pos_mem - 1].pos_prev + = coder->opts[cur].pos_prev_2; + coder->opts[pos_mem - 1].back_prev + = coder->opts[cur].back_prev_2; + } + } + + const uint32_t pos_prev = pos_mem; + const uint32_t back_cur = back_mem; + + back_mem = coder->opts[pos_prev].back_prev; + pos_mem = coder->opts[pos_prev].pos_prev; + + coder->opts[pos_prev].back_prev = back_cur; + coder->opts[pos_prev].pos_prev = cur; + cur = pos_prev; + + } while (cur != 0); + + coder->opts_current_index = coder->opts[0].pos_prev; + *len_res = coder->opts[0].pos_prev; + *back_res = coder->opts[0].back_prev; + + return; +} + + +////////// +// Main // +////////// + +static inline uint32_t +helper1(lzma_lzma1_encoder *restrict coder, lzma_mf *restrict mf, + uint32_t *restrict back_res, uint32_t *restrict len_res, + uint32_t position) +{ + const uint32_t nice_len = mf->nice_len; + + uint32_t len_main; + uint32_t matches_count; + + if (mf->read_ahead == 0) { + len_main = mf_find(mf, &matches_count, coder->matches); + } else { + assert(mf->read_ahead == 1); + len_main = coder->longest_match_length; + matches_count = coder->matches_count; + } + + const uint32_t buf_avail = my_min(mf_avail(mf) + 1, MATCH_LEN_MAX); + if (buf_avail < 2) { + *back_res = UINT32_MAX; + *len_res = 1; + return UINT32_MAX; + } + + const uint8_t *const buf = mf_ptr(mf) - 1; + + uint32_t rep_lens[REPS]; + uint32_t rep_max_index = 0; + + for (uint32_t i = 0; i < REPS; ++i) { + const uint8_t *const buf_back = buf - coder->reps[i] - 1; + + if (not_equal_16(buf, buf_back)) { + rep_lens[i] = 0; + continue; + } + + rep_lens[i] = lzma_memcmplen(buf, buf_back, 2, buf_avail); + + if (rep_lens[i] > rep_lens[rep_max_index]) + rep_max_index = i; + } + + if (rep_lens[rep_max_index] >= nice_len) { + *back_res = rep_max_index; + *len_res = rep_lens[rep_max_index]; + mf_skip(mf, *len_res - 1); + return UINT32_MAX; + } + + + if (len_main >= nice_len) { + *back_res = coder->matches[matches_count - 1].dist + REPS; + *len_res = len_main; + mf_skip(mf, len_main - 1); + return UINT32_MAX; + } + + const uint8_t current_byte = *buf; + const uint8_t match_byte = *(buf - coder->reps[0] - 1); + + if (len_main < 2 && current_byte != match_byte + && rep_lens[rep_max_index] < 2) { + *back_res = UINT32_MAX; + *len_res = 1; + return UINT32_MAX; + } + + coder->opts[0].state = coder->state; + + const uint32_t pos_state = position & coder->pos_mask; + + coder->opts[1].price = rc_bit_0_price( + coder->is_match[coder->state][pos_state]) + + get_literal_price(coder, position, buf[-1], + !is_literal_state(coder->state), + match_byte, current_byte); + + make_literal(&coder->opts[1]); + + const uint32_t match_price = rc_bit_1_price( + coder->is_match[coder->state][pos_state]); + const uint32_t rep_match_price = match_price + + rc_bit_1_price(coder->is_rep[coder->state]); + + if (match_byte == current_byte) { + const uint32_t short_rep_price = rep_match_price + + get_short_rep_price( + coder, coder->state, pos_state); + + if (short_rep_price < coder->opts[1].price) { + coder->opts[1].price = short_rep_price; + make_short_rep(&coder->opts[1]); + } + } + + const uint32_t len_end = my_max(len_main, rep_lens[rep_max_index]); + + if (len_end < 2) { + *back_res = coder->opts[1].back_prev; + *len_res = 1; + return UINT32_MAX; + } + + coder->opts[1].pos_prev = 0; + + for (uint32_t i = 0; i < REPS; ++i) + coder->opts[0].backs[i] = coder->reps[i]; + + uint32_t len = len_end; + do { + coder->opts[len].price = RC_INFINITY_PRICE; + } while (--len >= 2); + + + for (uint32_t i = 0; i < REPS; ++i) { + uint32_t rep_len = rep_lens[i]; + if (rep_len < 2) + continue; + + const uint32_t price = rep_match_price + get_pure_rep_price( + coder, i, coder->state, pos_state); + + do { + const uint32_t cur_and_len_price = price + + get_len_price( + &coder->rep_len_encoder, + rep_len, pos_state); + + if (cur_and_len_price < coder->opts[rep_len].price) { + coder->opts[rep_len].price = cur_and_len_price; + coder->opts[rep_len].pos_prev = 0; + coder->opts[rep_len].back_prev = i; + coder->opts[rep_len].prev_1_is_literal = false; + } + } while (--rep_len >= 2); + } + + + const uint32_t normal_match_price = match_price + + rc_bit_0_price(coder->is_rep[coder->state]); + + len = rep_lens[0] >= 2 ? rep_lens[0] + 1 : 2; + if (len <= len_main) { + uint32_t i = 0; + while (len > coder->matches[i].len) + ++i; + + for(; ; ++len) { + const uint32_t dist = coder->matches[i].dist; + const uint32_t cur_and_len_price = normal_match_price + + get_dist_len_price(coder, + dist, len, pos_state); + + if (cur_and_len_price < coder->opts[len].price) { + coder->opts[len].price = cur_and_len_price; + coder->opts[len].pos_prev = 0; + coder->opts[len].back_prev = dist + REPS; + coder->opts[len].prev_1_is_literal = false; + } + + if (len == coder->matches[i].len) + if (++i == matches_count) + break; + } + } + + return len_end; +} + + +static inline uint32_t +helper2(lzma_lzma1_encoder *coder, uint32_t *reps, const uint8_t *buf, + uint32_t len_end, uint32_t position, const uint32_t cur, + const uint32_t nice_len, const uint32_t buf_avail_full) +{ + uint32_t matches_count = coder->matches_count; + uint32_t new_len = coder->longest_match_length; + uint32_t pos_prev = coder->opts[cur].pos_prev; + lzma_lzma_state state; + + if (coder->opts[cur].prev_1_is_literal) { + --pos_prev; + + if (coder->opts[cur].prev_2) { + state = coder->opts[coder->opts[cur].pos_prev_2].state; + + if (coder->opts[cur].back_prev_2 < REPS) + update_long_rep(state); + else + update_match(state); + + } else { + state = coder->opts[pos_prev].state; + } + + update_literal(state); + + } else { + state = coder->opts[pos_prev].state; + } + + if (pos_prev == cur - 1) { + if (is_short_rep(coder->opts[cur])) + update_short_rep(state); + else + update_literal(state); + } else { + uint32_t pos; + if (coder->opts[cur].prev_1_is_literal + && coder->opts[cur].prev_2) { + pos_prev = coder->opts[cur].pos_prev_2; + pos = coder->opts[cur].back_prev_2; + update_long_rep(state); + } else { + pos = coder->opts[cur].back_prev; + if (pos < REPS) + update_long_rep(state); + else + update_match(state); + } + + if (pos < REPS) { + reps[0] = coder->opts[pos_prev].backs[pos]; + + uint32_t i; + for (i = 1; i <= pos; ++i) + reps[i] = coder->opts[pos_prev].backs[i - 1]; + + for (; i < REPS; ++i) + reps[i] = coder->opts[pos_prev].backs[i]; + + } else { + reps[0] = pos - REPS; + + for (uint32_t i = 1; i < REPS; ++i) + reps[i] = coder->opts[pos_prev].backs[i - 1]; + } + } + + coder->opts[cur].state = state; + + for (uint32_t i = 0; i < REPS; ++i) + coder->opts[cur].backs[i] = reps[i]; + + const uint32_t cur_price = coder->opts[cur].price; + + const uint8_t current_byte = *buf; + const uint8_t match_byte = *(buf - reps[0] - 1); + + const uint32_t pos_state = position & coder->pos_mask; + + const uint32_t cur_and_1_price = cur_price + + rc_bit_0_price(coder->is_match[state][pos_state]) + + get_literal_price(coder, position, buf[-1], + !is_literal_state(state), match_byte, current_byte); + + bool next_is_literal = false; + + if (cur_and_1_price < coder->opts[cur + 1].price) { + coder->opts[cur + 1].price = cur_and_1_price; + coder->opts[cur + 1].pos_prev = cur; + make_literal(&coder->opts[cur + 1]); + next_is_literal = true; + } + + const uint32_t match_price = cur_price + + rc_bit_1_price(coder->is_match[state][pos_state]); + const uint32_t rep_match_price = match_price + + rc_bit_1_price(coder->is_rep[state]); + + if (match_byte == current_byte + && !(coder->opts[cur + 1].pos_prev < cur + && coder->opts[cur + 1].back_prev == 0)) { + + const uint32_t short_rep_price = rep_match_price + + get_short_rep_price(coder, state, pos_state); + + if (short_rep_price <= coder->opts[cur + 1].price) { + coder->opts[cur + 1].price = short_rep_price; + coder->opts[cur + 1].pos_prev = cur; + make_short_rep(&coder->opts[cur + 1]); + next_is_literal = true; + } + } + + if (buf_avail_full < 2) + return len_end; + + const uint32_t buf_avail = my_min(buf_avail_full, nice_len); + + if (!next_is_literal && match_byte != current_byte) { // speed optimization + // try literal + rep0 + const uint8_t *const buf_back = buf - reps[0] - 1; + const uint32_t limit = my_min(buf_avail_full, nice_len + 1); + + const uint32_t len_test = lzma_memcmplen(buf, buf_back, 1, limit) - 1; + + if (len_test >= 2) { + lzma_lzma_state state_2 = state; + update_literal(state_2); + + const uint32_t pos_state_next = (position + 1) & coder->pos_mask; + const uint32_t next_rep_match_price = cur_and_1_price + + rc_bit_1_price(coder->is_match[state_2][pos_state_next]) + + rc_bit_1_price(coder->is_rep[state_2]); + + //for (; len_test >= 2; --len_test) { + const uint32_t offset = cur + 1 + len_test; + + while (len_end < offset) + coder->opts[++len_end].price = RC_INFINITY_PRICE; + + const uint32_t cur_and_len_price = next_rep_match_price + + get_rep_price(coder, 0, len_test, + state_2, pos_state_next); + + if (cur_and_len_price < coder->opts[offset].price) { + coder->opts[offset].price = cur_and_len_price; + coder->opts[offset].pos_prev = cur + 1; + coder->opts[offset].back_prev = 0; + coder->opts[offset].prev_1_is_literal = true; + coder->opts[offset].prev_2 = false; + } + //} + } + } + + + uint32_t start_len = 2; // speed optimization + + for (uint32_t rep_index = 0; rep_index < REPS; ++rep_index) { + const uint8_t *const buf_back = buf - reps[rep_index] - 1; + if (not_equal_16(buf, buf_back)) + continue; + + uint32_t len_test = lzma_memcmplen(buf, buf_back, 2, buf_avail); + + while (len_end < cur + len_test) + coder->opts[++len_end].price = RC_INFINITY_PRICE; + + const uint32_t len_test_temp = len_test; + const uint32_t price = rep_match_price + get_pure_rep_price( + coder, rep_index, state, pos_state); + + do { + const uint32_t cur_and_len_price = price + + get_len_price(&coder->rep_len_encoder, + len_test, pos_state); + + if (cur_and_len_price < coder->opts[cur + len_test].price) { + coder->opts[cur + len_test].price = cur_and_len_price; + coder->opts[cur + len_test].pos_prev = cur; + coder->opts[cur + len_test].back_prev = rep_index; + coder->opts[cur + len_test].prev_1_is_literal = false; + } + } while (--len_test >= 2); + + len_test = len_test_temp; + + if (rep_index == 0) + start_len = len_test + 1; + + + uint32_t len_test_2 = len_test + 1; + const uint32_t limit = my_min(buf_avail_full, + len_test_2 + nice_len); + for (; len_test_2 < limit + && buf[len_test_2] == buf_back[len_test_2]; + ++len_test_2) ; + + len_test_2 -= len_test + 1; + + if (len_test_2 >= 2) { + lzma_lzma_state state_2 = state; + update_long_rep(state_2); + + uint32_t pos_state_next = (position + len_test) & coder->pos_mask; + + const uint32_t cur_and_len_literal_price = price + + get_len_price(&coder->rep_len_encoder, + len_test, pos_state) + + rc_bit_0_price(coder->is_match[state_2][pos_state_next]) + + get_literal_price(coder, position + len_test, + buf[len_test - 1], true, + buf_back[len_test], buf[len_test]); + + update_literal(state_2); + + pos_state_next = (position + len_test + 1) & coder->pos_mask; + + const uint32_t next_rep_match_price = cur_and_len_literal_price + + rc_bit_1_price(coder->is_match[state_2][pos_state_next]) + + rc_bit_1_price(coder->is_rep[state_2]); + + //for(; len_test_2 >= 2; len_test_2--) { + const uint32_t offset = cur + len_test + 1 + len_test_2; + + while (len_end < offset) + coder->opts[++len_end].price = RC_INFINITY_PRICE; + + const uint32_t cur_and_len_price = next_rep_match_price + + get_rep_price(coder, 0, len_test_2, + state_2, pos_state_next); + + if (cur_and_len_price < coder->opts[offset].price) { + coder->opts[offset].price = cur_and_len_price; + coder->opts[offset].pos_prev = cur + len_test + 1; + coder->opts[offset].back_prev = 0; + coder->opts[offset].prev_1_is_literal = true; + coder->opts[offset].prev_2 = true; + coder->opts[offset].pos_prev_2 = cur; + coder->opts[offset].back_prev_2 = rep_index; + } + //} + } + } + + + //for (uint32_t len_test = 2; len_test <= new_len; ++len_test) + if (new_len > buf_avail) { + new_len = buf_avail; + + matches_count = 0; + while (new_len > coder->matches[matches_count].len) + ++matches_count; + + coder->matches[matches_count++].len = new_len; + } + + + if (new_len >= start_len) { + const uint32_t normal_match_price = match_price + + rc_bit_0_price(coder->is_rep[state]); + + while (len_end < cur + new_len) + coder->opts[++len_end].price = RC_INFINITY_PRICE; + + uint32_t i = 0; + while (start_len > coder->matches[i].len) + ++i; + + for (uint32_t len_test = start_len; ; ++len_test) { + const uint32_t cur_back = coder->matches[i].dist; + uint32_t cur_and_len_price = normal_match_price + + get_dist_len_price(coder, + cur_back, len_test, pos_state); + + if (cur_and_len_price < coder->opts[cur + len_test].price) { + coder->opts[cur + len_test].price = cur_and_len_price; + coder->opts[cur + len_test].pos_prev = cur; + coder->opts[cur + len_test].back_prev + = cur_back + REPS; + coder->opts[cur + len_test].prev_1_is_literal = false; + } + + if (len_test == coder->matches[i].len) { + // Try Match + Literal + Rep0 + const uint8_t *const buf_back = buf - cur_back - 1; + uint32_t len_test_2 = len_test + 1; + const uint32_t limit = my_min(buf_avail_full, + len_test_2 + nice_len); + + for (; len_test_2 < limit && + buf[len_test_2] == buf_back[len_test_2]; + ++len_test_2) ; + + len_test_2 -= len_test + 1; + + if (len_test_2 >= 2) { + lzma_lzma_state state_2 = state; + update_match(state_2); + uint32_t pos_state_next + = (position + len_test) & coder->pos_mask; + + const uint32_t cur_and_len_literal_price = cur_and_len_price + + rc_bit_0_price( + coder->is_match[state_2][pos_state_next]) + + get_literal_price(coder, + position + len_test, + buf[len_test - 1], + true, + buf_back[len_test], + buf[len_test]); + + update_literal(state_2); + pos_state_next = (pos_state_next + 1) & coder->pos_mask; + + const uint32_t next_rep_match_price + = cur_and_len_literal_price + + rc_bit_1_price( + coder->is_match[state_2][pos_state_next]) + + rc_bit_1_price(coder->is_rep[state_2]); + + // for(; len_test_2 >= 2; --len_test_2) { + const uint32_t offset = cur + len_test + 1 + len_test_2; + + while (len_end < offset) + coder->opts[++len_end].price = RC_INFINITY_PRICE; + + cur_and_len_price = next_rep_match_price + + get_rep_price(coder, 0, len_test_2, + state_2, pos_state_next); + + if (cur_and_len_price < coder->opts[offset].price) { + coder->opts[offset].price = cur_and_len_price; + coder->opts[offset].pos_prev = cur + len_test + 1; + coder->opts[offset].back_prev = 0; + coder->opts[offset].prev_1_is_literal = true; + coder->opts[offset].prev_2 = true; + coder->opts[offset].pos_prev_2 = cur; + coder->opts[offset].back_prev_2 + = cur_back + REPS; + } + //} + } + + if (++i == matches_count) + break; + } + } + } + + return len_end; +} + + +extern void +lzma_lzma_optimum_normal(lzma_lzma1_encoder *restrict coder, + lzma_mf *restrict mf, + uint32_t *restrict back_res, uint32_t *restrict len_res, + uint32_t position) +{ + // If we have symbols pending, return the next pending symbol. + if (coder->opts_end_index != coder->opts_current_index) { + assert(mf->read_ahead > 0); + *len_res = coder->opts[coder->opts_current_index].pos_prev + - coder->opts_current_index; + *back_res = coder->opts[coder->opts_current_index].back_prev; + coder->opts_current_index = coder->opts[ + coder->opts_current_index].pos_prev; + return; + } + + // Update the price tables. In LZMA SDK <= 4.60 (and possibly later) + // this was done in both initialization function and in the main loop. + // In liblzma they were moved into this single place. + if (mf->read_ahead == 0) { + if (coder->match_price_count >= (1 << 7)) + fill_dist_prices(coder); + + if (coder->align_price_count >= ALIGN_SIZE) + fill_align_prices(coder); + } + + // TODO: This needs quite a bit of cleaning still. But splitting + // the original function into two pieces makes it at least a little + // more readable, since those two parts don't share many variables. + + uint32_t len_end = helper1(coder, mf, back_res, len_res, position); + if (len_end == UINT32_MAX) + return; + + uint32_t reps[REPS]; + memcpy(reps, coder->reps, sizeof(reps)); + + uint32_t cur; + for (cur = 1; cur < len_end; ++cur) { + assert(cur < OPTS); + + coder->longest_match_length = mf_find( + mf, &coder->matches_count, coder->matches); + + if (coder->longest_match_length >= mf->nice_len) + break; + + len_end = helper2(coder, reps, mf_ptr(mf) - 1, len_end, + position + cur, cur, mf->nice_len, + my_min(mf_avail(mf) + 1, OPTS - 1 - cur)); + } + + backward(coder, len_res, back_res, cur); + return; +} diff --git a/dependencies/cmliblzma/liblzma/lzma/lzma_encoder_presets.c b/dependencies/cmliblzma/liblzma/lzma/lzma_encoder_presets.c new file mode 100644 index 0000000..711df02 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/lzma/lzma_encoder_presets.c @@ -0,0 +1,64 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file lzma_encoder_presets.c +/// \brief Encoder presets +/// \note xz needs this even when only decoding is enabled. +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "common.h" + + +extern LZMA_API(lzma_bool) +lzma_lzma_preset(lzma_options_lzma *options, uint32_t preset) +{ + const uint32_t level = preset & LZMA_PRESET_LEVEL_MASK; + const uint32_t flags = preset & ~LZMA_PRESET_LEVEL_MASK; + const uint32_t supported_flags = LZMA_PRESET_EXTREME; + + if (level > 9 || (flags & ~supported_flags)) + return true; + + options->preset_dict = NULL; + options->preset_dict_size = 0; + + options->lc = LZMA_LC_DEFAULT; + options->lp = LZMA_LP_DEFAULT; + options->pb = LZMA_PB_DEFAULT; + + static const uint8_t dict_pow2[] + = { 18, 20, 21, 22, 22, 23, 23, 24, 25, 26 }; + options->dict_size = UINT32_C(1) << dict_pow2[level]; + + if (level <= 3) { + options->mode = LZMA_MODE_FAST; + options->mf = level == 0 ? LZMA_MF_HC3 : LZMA_MF_HC4; + options->nice_len = level <= 1 ? 128 : 273; + static const uint8_t depths[] = { 4, 8, 24, 48 }; + options->depth = depths[level]; + } else { + options->mode = LZMA_MODE_NORMAL; + options->mf = LZMA_MF_BT4; + options->nice_len = level == 4 ? 16 : level == 5 ? 32 : 64; + options->depth = 0; + } + + if (flags & LZMA_PRESET_EXTREME) { + options->mode = LZMA_MODE_NORMAL; + options->mf = LZMA_MF_BT4; + if (level == 3 || level == 5) { + options->nice_len = 192; + options->depth = 0; + } else { + options->nice_len = 273; + options->depth = 512; + } + } + + return false; +} diff --git a/dependencies/cmliblzma/liblzma/lzma/lzma_encoder_private.h b/dependencies/cmliblzma/liblzma/lzma/lzma_encoder_private.h new file mode 100644 index 0000000..a2da969 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/lzma/lzma_encoder_private.h @@ -0,0 +1,148 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file lzma_encoder_private.h +/// \brief Private definitions for LZMA encoder +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_LZMA_ENCODER_PRIVATE_H +#define LZMA_LZMA_ENCODER_PRIVATE_H + +#include "lz_encoder.h" +#include "range_encoder.h" +#include "lzma_common.h" +#include "lzma_encoder.h" + + +// Macro to compare if the first two bytes in two buffers differ. This is +// needed in lzma_lzma_optimum_*() to test if the match is at least +// MATCH_LEN_MIN bytes. Unaligned access gives tiny gain so there's no +// reason to not use it when it is supported. +#ifdef TUKLIB_FAST_UNALIGNED_ACCESS +# define not_equal_16(a, b) \ + (*(const uint16_t *)(a) != *(const uint16_t *)(b)) +#else +# define not_equal_16(a, b) \ + ((a)[0] != (b)[0] || (a)[1] != (b)[1]) +#endif + + +// Optimal - Number of entries in the optimum array. +#define OPTS (1 << 12) + + +typedef struct { + probability choice; + probability choice2; + probability low[POS_STATES_MAX][LEN_LOW_SYMBOLS]; + probability mid[POS_STATES_MAX][LEN_MID_SYMBOLS]; + probability high[LEN_HIGH_SYMBOLS]; + + uint32_t prices[POS_STATES_MAX][LEN_SYMBOLS]; + uint32_t table_size; + uint32_t counters[POS_STATES_MAX]; + +} lzma_length_encoder; + + +typedef struct { + lzma_lzma_state state; + + bool prev_1_is_literal; + bool prev_2; + + uint32_t pos_prev_2; + uint32_t back_prev_2; + + uint32_t price; + uint32_t pos_prev; // pos_next; + uint32_t back_prev; + + uint32_t backs[REPS]; + +} lzma_optimal; + + +struct lzma_lzma1_encoder_s { + /// Range encoder + lzma_range_encoder rc; + + /// State + lzma_lzma_state state; + + /// The four most recent match distances + uint32_t reps[REPS]; + + /// Array of match candidates + lzma_match matches[MATCH_LEN_MAX + 1]; + + /// Number of match candidates in matches[] + uint32_t matches_count; + + /// Variable to hold the length of the longest match between calls + /// to lzma_lzma_optimum_*(). + uint32_t longest_match_length; + + /// True if using getoptimumfast + bool fast_mode; + + /// True if the encoder has been initialized by encoding the first + /// byte as a literal. + bool is_initialized; + + /// True if the range encoder has been flushed, but not all bytes + /// have been written to the output buffer yet. + bool is_flushed; + + uint32_t pos_mask; ///< (1 << pos_bits) - 1 + uint32_t literal_context_bits; + uint32_t literal_pos_mask; + + // These are the same as in lzma_decoder.c. See comments there. + probability literal[LITERAL_CODERS_MAX][LITERAL_CODER_SIZE]; + probability is_match[STATES][POS_STATES_MAX]; + probability is_rep[STATES]; + probability is_rep0[STATES]; + probability is_rep1[STATES]; + probability is_rep2[STATES]; + probability is_rep0_long[STATES][POS_STATES_MAX]; + probability dist_slot[DIST_STATES][DIST_SLOTS]; + probability dist_special[FULL_DISTANCES - DIST_MODEL_END]; + probability dist_align[ALIGN_SIZE]; + + // These are the same as in lzma_decoder.c except that the encoders + // include also price tables. + lzma_length_encoder match_len_encoder; + lzma_length_encoder rep_len_encoder; + + // Price tables + uint32_t dist_slot_prices[DIST_STATES][DIST_SLOTS]; + uint32_t dist_prices[DIST_STATES][FULL_DISTANCES]; + uint32_t dist_table_size; + uint32_t match_price_count; + + uint32_t align_prices[ALIGN_SIZE]; + uint32_t align_price_count; + + // Optimal + uint32_t opts_end_index; + uint32_t opts_current_index; + lzma_optimal opts[OPTS]; +}; + + +extern void lzma_lzma_optimum_fast( + lzma_lzma1_encoder *restrict coder, lzma_mf *restrict mf, + uint32_t *restrict back_res, uint32_t *restrict len_res); + +extern void lzma_lzma_optimum_normal(lzma_lzma1_encoder *restrict coder, + lzma_mf *restrict mf, uint32_t *restrict back_res, + uint32_t *restrict len_res, uint32_t position); + +#endif diff --git a/dependencies/cmliblzma/liblzma/rangecoder/price.h b/dependencies/cmliblzma/liblzma/rangecoder/price.h new file mode 100644 index 0000000..8ae02ca --- /dev/null +++ b/dependencies/cmliblzma/liblzma/rangecoder/price.h @@ -0,0 +1,92 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file price.h +/// \brief Probability price calculation +// +// Author: Igor Pavlov +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_PRICE_H +#define LZMA_PRICE_H + + +#define RC_MOVE_REDUCING_BITS 4 +#define RC_BIT_PRICE_SHIFT_BITS 4 +#define RC_PRICE_TABLE_SIZE (RC_BIT_MODEL_TOTAL >> RC_MOVE_REDUCING_BITS) + +#define RC_INFINITY_PRICE (UINT32_C(1) << 30) + + +/// Lookup table for the inline functions defined in this file. +extern const uint8_t lzma_rc_prices[RC_PRICE_TABLE_SIZE]; + + +static inline uint32_t +rc_bit_price(const probability prob, const uint32_t bit) +{ + return lzma_rc_prices[(prob ^ ((UINT32_C(0) - bit) + & (RC_BIT_MODEL_TOTAL - 1))) >> RC_MOVE_REDUCING_BITS]; +} + + +static inline uint32_t +rc_bit_0_price(const probability prob) +{ + return lzma_rc_prices[prob >> RC_MOVE_REDUCING_BITS]; +} + + +static inline uint32_t +rc_bit_1_price(const probability prob) +{ + return lzma_rc_prices[(prob ^ (RC_BIT_MODEL_TOTAL - 1)) + >> RC_MOVE_REDUCING_BITS]; +} + + +static inline uint32_t +rc_bittree_price(const probability *const probs, + const uint32_t bit_levels, uint32_t symbol) +{ + uint32_t price = 0; + symbol += UINT32_C(1) << bit_levels; + + do { + const uint32_t bit = symbol & 1; + symbol >>= 1; + price += rc_bit_price(probs[symbol], bit); + } while (symbol != 1); + + return price; +} + + +static inline uint32_t +rc_bittree_reverse_price(const probability *const probs, + uint32_t bit_levels, uint32_t symbol) +{ + uint32_t price = 0; + uint32_t model_index = 1; + + do { + const uint32_t bit = symbol & 1; + symbol >>= 1; + price += rc_bit_price(probs[model_index], bit); + model_index = (model_index << 1) + bit; + } while (--bit_levels != 0); + + return price; +} + + +static inline uint32_t +rc_direct_price(const uint32_t bits) +{ + return bits << RC_BIT_PRICE_SHIFT_BITS; +} + +#endif diff --git a/dependencies/cmliblzma/liblzma/rangecoder/price_table.c b/dependencies/cmliblzma/liblzma/rangecoder/price_table.c new file mode 100644 index 0000000..ac64bf6 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/rangecoder/price_table.c @@ -0,0 +1,22 @@ +/* This file has been automatically generated by price_tablegen.c. */ + +#include "range_encoder.h" + +const uint8_t lzma_rc_prices[RC_PRICE_TABLE_SIZE] = { + 128, 103, 91, 84, 78, 73, 69, 66, + 63, 61, 58, 56, 54, 52, 51, 49, + 48, 46, 45, 44, 43, 42, 41, 40, + 39, 38, 37, 36, 35, 34, 34, 33, + 32, 31, 31, 30, 29, 29, 28, 28, + 27, 26, 26, 25, 25, 24, 24, 23, + 23, 22, 22, 22, 21, 21, 20, 20, + 19, 19, 19, 18, 18, 17, 17, 17, + 16, 16, 16, 15, 15, 15, 14, 14, + 14, 13, 13, 13, 12, 12, 12, 11, + 11, 11, 11, 10, 10, 10, 10, 9, + 9, 9, 9, 8, 8, 8, 8, 7, + 7, 7, 7, 6, 6, 6, 6, 5, + 5, 5, 5, 5, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 2, 2, 2, + 2, 2, 2, 1, 1, 1, 1, 1 +}; diff --git a/dependencies/cmliblzma/liblzma/rangecoder/price_tablegen.c b/dependencies/cmliblzma/liblzma/rangecoder/price_tablegen.c new file mode 100644 index 0000000..bf08ce3 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/rangecoder/price_tablegen.c @@ -0,0 +1,87 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file price_tablegen.c +/// \brief Probability price table generator +/// +/// Compiling: gcc -std=c99 -o price_tablegen price_tablegen.c +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include "range_common.h" +#include "price.h" + + +static uint32_t rc_prices[RC_PRICE_TABLE_SIZE]; + + +static void +init_price_table(void) +{ + for (uint32_t i = (UINT32_C(1) << RC_MOVE_REDUCING_BITS) / 2; + i < RC_BIT_MODEL_TOTAL; + i += (UINT32_C(1) << RC_MOVE_REDUCING_BITS)) { + const uint32_t cycles_bits = RC_BIT_PRICE_SHIFT_BITS; + uint32_t w = i; + uint32_t bit_count = 0; + + for (uint32_t j = 0; j < cycles_bits; ++j) { + w *= w; + bit_count <<= 1; + + while (w >= (UINT32_C(1) << 16)) { + w >>= 1; + ++bit_count; + } + } + + rc_prices[i >> RC_MOVE_REDUCING_BITS] + = (RC_BIT_MODEL_TOTAL_BITS << cycles_bits) + - 15 - bit_count; + } + + return; +} + + +static void +print_price_table(void) +{ + printf("/* This file has been automatically generated by " + "price_tablegen.c. */\n\n" + "#include \"range_encoder.h\"\n\n" + "const uint8_t lzma_rc_prices[" + "RC_PRICE_TABLE_SIZE] = {"); + + const size_t array_size = sizeof(lzma_rc_prices) + / sizeof(lzma_rc_prices[0]); + for (size_t i = 0; i < array_size; ++i) { + if (i % 8 == 0) + printf("\n\t"); + + printf("%4" PRIu32, rc_prices[i]); + + if (i != array_size - 1) + printf(","); + } + + printf("\n};\n"); + + return; +} + + +int +main(void) +{ + init_price_table(); + print_price_table(); + return 0; +} diff --git a/dependencies/cmliblzma/liblzma/rangecoder/range_common.h b/dependencies/cmliblzma/liblzma/rangecoder/range_common.h new file mode 100644 index 0000000..2c74dc1 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/rangecoder/range_common.h @@ -0,0 +1,71 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file range_common.h +/// \brief Common things for range encoder and decoder +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_RANGE_COMMON_H +#define LZMA_RANGE_COMMON_H + +#include "common.h" + + +/////////////// +// Constants // +/////////////// + +#define RC_SHIFT_BITS 8 +#define RC_TOP_BITS 24 +#define RC_TOP_VALUE (UINT32_C(1) << RC_TOP_BITS) +#define RC_BIT_MODEL_TOTAL_BITS 11 +#define RC_BIT_MODEL_TOTAL (UINT32_C(1) << RC_BIT_MODEL_TOTAL_BITS) +#define RC_MOVE_BITS 5 + + +//////////// +// Macros // +//////////// + +// Resets the probability so that both 0 and 1 have probability of 50 % +#define bit_reset(prob) \ + prob = RC_BIT_MODEL_TOTAL >> 1 + +// This does the same for a complete bit tree. +// (A tree represented as an array.) +#define bittree_reset(probs, bit_levels) \ + for (uint32_t bt_i = 0; bt_i < (1 << (bit_levels)); ++bt_i) \ + bit_reset((probs)[bt_i]) + + +////////////////////// +// Type definitions // +////////////////////// + +/// \brief Type of probabilities used with range coder +/// +/// This needs to be at least 12-bit integer, so uint16_t is a logical choice. +/// However, on some architecture and compiler combinations, a bigger type +/// may give better speed, because the probability variables are accessed +/// a lot. On the other hand, bigger probability type increases cache +/// footprint, since there are 2 to 14 thousand probability variables in +/// LZMA (assuming the limit of lc + lp <= 4; with lc + lp <= 12 there +/// would be about 1.5 million variables). +/// +/// With malicious files, the initialization speed of the LZMA decoder can +/// become important. In that case, smaller probability variables mean that +/// there is less bytes to write to RAM, which makes initialization faster. +/// With big probability type, the initialization can become so slow that it +/// can be a problem e.g. for email servers doing virus scanning. +/// +/// I will be sticking to uint16_t unless some specific architectures +/// are *much* faster (20-50 %) with uint32_t. +typedef uint16_t probability; + +#endif diff --git a/dependencies/cmliblzma/liblzma/rangecoder/range_decoder.h b/dependencies/cmliblzma/liblzma/rangecoder/range_decoder.h new file mode 100644 index 0000000..e0b051f --- /dev/null +++ b/dependencies/cmliblzma/liblzma/rangecoder/range_decoder.h @@ -0,0 +1,185 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file range_decoder.h +/// \brief Range Decoder +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_RANGE_DECODER_H +#define LZMA_RANGE_DECODER_H + +#include "range_common.h" + + +typedef struct { + uint32_t range; + uint32_t code; + uint32_t init_bytes_left; +} lzma_range_decoder; + + +/// Reads the first five bytes to initialize the range decoder. +static inline lzma_ret +rc_read_init(lzma_range_decoder *rc, const uint8_t *restrict in, + size_t *restrict in_pos, size_t in_size) +{ + while (rc->init_bytes_left > 0) { + if (*in_pos == in_size) + return LZMA_OK; + + // The first byte is always 0x00. It could have been omitted + // in LZMA2 but it wasn't, so one byte is wasted in every + // LZMA2 chunk. + if (rc->init_bytes_left == 5 && in[*in_pos] != 0x00) + return LZMA_DATA_ERROR; + + rc->code = (rc->code << 8) | in[*in_pos]; + ++*in_pos; + --rc->init_bytes_left; + } + + return LZMA_STREAM_END; +} + + +/// Makes local copies of range decoder and *in_pos variables. Doing this +/// improves speed significantly. The range decoder macros expect also +/// variables `in' and `in_size' to be defined. +#define rc_to_local(range_decoder, in_pos) \ + lzma_range_decoder rc = range_decoder; \ + size_t rc_in_pos = (in_pos); \ + uint32_t rc_bound + + +/// Stores the local copes back to the range decoder structure. +#define rc_from_local(range_decoder, in_pos) \ +do { \ + range_decoder = rc; \ + in_pos = rc_in_pos; \ +} while (0) + + +/// Resets the range decoder structure. +#define rc_reset(range_decoder) \ +do { \ + (range_decoder).range = UINT32_MAX; \ + (range_decoder).code = 0; \ + (range_decoder).init_bytes_left = 5; \ +} while (0) + + +/// When decoding has been properly finished, rc.code is always zero unless +/// the input stream is corrupt. So checking this can catch some corrupt +/// files especially if they don't have any other integrity check. +#define rc_is_finished(range_decoder) \ + ((range_decoder).code == 0) + + +/// Read the next input byte if needed. If more input is needed but there is +/// no more input available, "goto out" is used to jump out of the main +/// decoder loop. +#define rc_normalize(seq) \ +do { \ + if (rc.range < RC_TOP_VALUE) { \ + if (unlikely(rc_in_pos == in_size)) { \ + coder->sequence = seq; \ + goto out; \ + } \ + rc.range <<= RC_SHIFT_BITS; \ + rc.code = (rc.code << RC_SHIFT_BITS) | in[rc_in_pos++]; \ + } \ +} while (0) + + +/// Start decoding a bit. This must be used together with rc_update_0() +/// and rc_update_1(): +/// +/// rc_if_0(prob, seq) { +/// rc_update_0(prob); +/// // Do something +/// } else { +/// rc_update_1(prob); +/// // Do something else +/// } +/// +#define rc_if_0(prob, seq) \ + rc_normalize(seq); \ + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) * (prob); \ + if (rc.code < rc_bound) + + +/// Update the range decoder state and the used probability variable to +/// match a decoded bit of 0. +#define rc_update_0(prob) \ +do { \ + rc.range = rc_bound; \ + prob += (RC_BIT_MODEL_TOTAL - (prob)) >> RC_MOVE_BITS; \ +} while (0) + + +/// Update the range decoder state and the used probability variable to +/// match a decoded bit of 1. +#define rc_update_1(prob) \ +do { \ + rc.range -= rc_bound; \ + rc.code -= rc_bound; \ + prob -= (prob) >> RC_MOVE_BITS; \ +} while (0) + + +/// Decodes one bit and runs action0 or action1 depending on the decoded bit. +/// This macro is used as the last step in bittree reverse decoders since +/// those don't use "symbol" for anything else than indexing the probability +/// arrays. +#define rc_bit_last(prob, action0, action1, seq) \ +do { \ + rc_if_0(prob, seq) { \ + rc_update_0(prob); \ + action0; \ + } else { \ + rc_update_1(prob); \ + action1; \ + } \ +} while (0) + + +/// Decodes one bit, updates "symbol", and runs action0 or action1 depending +/// on the decoded bit. +#define rc_bit(prob, action0, action1, seq) \ + rc_bit_last(prob, \ + symbol <<= 1; action0, \ + symbol = (symbol << 1) + 1; action1, \ + seq); + + +/// Like rc_bit() but add "case seq:" as a prefix. This makes the unrolled +/// loops more readable because the code isn't littered with "case" +/// statements. On the other hand this also makes it less readable, since +/// spotting the places where the decoder loop may be restarted is less +/// obvious. +#define rc_bit_case(prob, action0, action1, seq) \ + case seq: rc_bit(prob, action0, action1, seq) + + +/// Decode a bit without using a probability. +#define rc_direct(dest, seq) \ +do { \ + rc_normalize(seq); \ + rc.range >>= 1; \ + rc.code -= rc.range; \ + rc_bound = UINT32_C(0) - (rc.code >> 31); \ + rc.code += rc.range & rc_bound; \ + dest = (dest << 1) + (rc_bound + 1); \ +} while (0) + + +// NOTE: No macros are provided for bittree decoding. It seems to be simpler +// to just write them open in the code. + +#endif diff --git a/dependencies/cmliblzma/liblzma/rangecoder/range_encoder.h b/dependencies/cmliblzma/liblzma/rangecoder/range_encoder.h new file mode 100644 index 0000000..1e1c369 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/rangecoder/range_encoder.h @@ -0,0 +1,231 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file range_encoder.h +/// \brief Range Encoder +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_RANGE_ENCODER_H +#define LZMA_RANGE_ENCODER_H + +#include "range_common.h" +#include "price.h" + + +/// Maximum number of symbols that can be put pending into lzma_range_encoder +/// structure between calls to lzma_rc_encode(). For LZMA, 52+5 is enough +/// (match with big distance and length followed by range encoder flush). +#define RC_SYMBOLS_MAX 58 + + +typedef struct { + uint64_t low; + uint64_t cache_size; + uint32_t range; + uint8_t cache; + + /// Number of symbols in the tables + size_t count; + + /// rc_encode()'s position in the tables + size_t pos; + + /// Symbols to encode + enum { + RC_BIT_0, + RC_BIT_1, + RC_DIRECT_0, + RC_DIRECT_1, + RC_FLUSH, + } symbols[RC_SYMBOLS_MAX]; + + /// Probabilities associated with RC_BIT_0 or RC_BIT_1 + probability *probs[RC_SYMBOLS_MAX]; + +} lzma_range_encoder; + + +static inline void +rc_reset(lzma_range_encoder *rc) +{ + rc->low = 0; + rc->cache_size = 1; + rc->range = UINT32_MAX; + rc->cache = 0; + rc->count = 0; + rc->pos = 0; +} + + +static inline void +rc_bit(lzma_range_encoder *rc, probability *prob, uint32_t bit) +{ + rc->symbols[rc->count] = bit; + rc->probs[rc->count] = prob; + ++rc->count; +} + + +static inline void +rc_bittree(lzma_range_encoder *rc, probability *probs, + uint32_t bit_count, uint32_t symbol) +{ + uint32_t model_index = 1; + + do { + const uint32_t bit = (symbol >> --bit_count) & 1; + rc_bit(rc, &probs[model_index], bit); + model_index = (model_index << 1) + bit; + } while (bit_count != 0); +} + + +static inline void +rc_bittree_reverse(lzma_range_encoder *rc, probability *probs, + uint32_t bit_count, uint32_t symbol) +{ + uint32_t model_index = 1; + + do { + const uint32_t bit = symbol & 1; + symbol >>= 1; + rc_bit(rc, &probs[model_index], bit); + model_index = (model_index << 1) + bit; + } while (--bit_count != 0); +} + + +static inline void +rc_direct(lzma_range_encoder *rc, + uint32_t value, uint32_t bit_count) +{ + do { + rc->symbols[rc->count++] + = RC_DIRECT_0 + ((value >> --bit_count) & 1); + } while (bit_count != 0); +} + + +static inline void +rc_flush(lzma_range_encoder *rc) +{ + for (size_t i = 0; i < 5; ++i) + rc->symbols[rc->count++] = RC_FLUSH; +} + + +static inline bool +rc_shift_low(lzma_range_encoder *rc, + uint8_t *out, size_t *out_pos, size_t out_size) +{ + if ((uint32_t)(rc->low) < (uint32_t)(0xFF000000) + || (uint32_t)(rc->low >> 32) != 0) { + do { + if (*out_pos == out_size) + return true; + + out[*out_pos] = rc->cache + (uint8_t)(rc->low >> 32); + ++*out_pos; + rc->cache = 0xFF; + + } while (--rc->cache_size != 0); + + rc->cache = (rc->low >> 24) & 0xFF; + } + + ++rc->cache_size; + rc->low = (rc->low & 0x00FFFFFF) << RC_SHIFT_BITS; + + return false; +} + + +static inline bool +rc_encode(lzma_range_encoder *rc, + uint8_t *out, size_t *out_pos, size_t out_size) +{ + assert(rc->count <= RC_SYMBOLS_MAX); + + while (rc->pos < rc->count) { + // Normalize + if (rc->range < RC_TOP_VALUE) { + if (rc_shift_low(rc, out, out_pos, out_size)) + return true; + + rc->range <<= RC_SHIFT_BITS; + } + + // Encode a bit + switch (rc->symbols[rc->pos]) { + case RC_BIT_0: { + probability prob = *rc->probs[rc->pos]; + rc->range = (rc->range >> RC_BIT_MODEL_TOTAL_BITS) + * prob; + prob += (RC_BIT_MODEL_TOTAL - prob) >> RC_MOVE_BITS; + *rc->probs[rc->pos] = prob; + break; + } + + case RC_BIT_1: { + probability prob = *rc->probs[rc->pos]; + const uint32_t bound = prob * (rc->range + >> RC_BIT_MODEL_TOTAL_BITS); + rc->low += bound; + rc->range -= bound; + prob -= prob >> RC_MOVE_BITS; + *rc->probs[rc->pos] = prob; + break; + } + + case RC_DIRECT_0: + rc->range >>= 1; + break; + + case RC_DIRECT_1: + rc->range >>= 1; + rc->low += rc->range; + break; + + case RC_FLUSH: + // Prevent further normalizations. + rc->range = UINT32_MAX; + + // Flush the last five bytes (see rc_flush()). + do { + if (rc_shift_low(rc, out, out_pos, out_size)) + return true; + } while (++rc->pos < rc->count); + + // Reset the range encoder so we are ready to continue + // encoding if we weren't finishing the stream. + rc_reset(rc); + return false; + + default: + assert(0); + break; + } + + ++rc->pos; + } + + rc->count = 0; + rc->pos = 0; + + return false; +} + + +static inline uint64_t +rc_pending(const lzma_range_encoder *rc) +{ + return rc->cache_size + 5 - 1; +} + +#endif diff --git a/dependencies/cmliblzma/liblzma/simple/arm.c b/dependencies/cmliblzma/liblzma/simple/arm.c new file mode 100644 index 0000000..181d0e3 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/simple/arm.c @@ -0,0 +1,71 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file arm.c +/// \brief Filter for ARM binaries +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "simple_private.h" + + +static size_t +arm_code(void *simple lzma_attribute((__unused__)), + uint32_t now_pos, bool is_encoder, + uint8_t *buffer, size_t size) +{ + size_t i; + for (i = 0; i + 4 <= size; i += 4) { + if (buffer[i + 3] == 0xEB) { + uint32_t src = (buffer[i + 2] << 16) + | (buffer[i + 1] << 8) + | (buffer[i + 0]); + src <<= 2; + + uint32_t dest; + if (is_encoder) + dest = now_pos + (uint32_t)(i) + 8 + src; + else + dest = src - (now_pos + (uint32_t)(i) + 8); + + dest >>= 2; + buffer[i + 2] = (dest >> 16); + buffer[i + 1] = (dest >> 8); + buffer[i + 0] = dest; + } + } + + return i; +} + + +static lzma_ret +arm_coder_init(lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter_info *filters, bool is_encoder) +{ + return lzma_simple_coder_init(next, allocator, filters, + &arm_code, 0, 4, 4, is_encoder); +} + + +extern lzma_ret +lzma_simple_arm_encoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters) +{ + return arm_coder_init(next, allocator, filters, true); +} + + +extern lzma_ret +lzma_simple_arm_decoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters) +{ + return arm_coder_init(next, allocator, filters, false); +} diff --git a/dependencies/cmliblzma/liblzma/simple/armthumb.c b/dependencies/cmliblzma/liblzma/simple/armthumb.c new file mode 100644 index 0000000..eab4862 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/simple/armthumb.c @@ -0,0 +1,76 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file armthumb.c +/// \brief Filter for ARM-Thumb binaries +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "simple_private.h" + + +static size_t +armthumb_code(void *simple lzma_attribute((__unused__)), + uint32_t now_pos, bool is_encoder, + uint8_t *buffer, size_t size) +{ + size_t i; + for (i = 0; i + 4 <= size; i += 2) { + if ((buffer[i + 1] & 0xF8) == 0xF0 + && (buffer[i + 3] & 0xF8) == 0xF8) { + uint32_t src = ((buffer[i + 1] & 0x7) << 19) + | (buffer[i + 0] << 11) + | ((buffer[i + 3] & 0x7) << 8) + | (buffer[i + 2]); + + src <<= 1; + + uint32_t dest; + if (is_encoder) + dest = now_pos + (uint32_t)(i) + 4 + src; + else + dest = src - (now_pos + (uint32_t)(i) + 4); + + dest >>= 1; + buffer[i + 1] = 0xF0 | ((dest >> 19) & 0x7); + buffer[i + 0] = (dest >> 11); + buffer[i + 3] = 0xF8 | ((dest >> 8) & 0x7); + buffer[i + 2] = (dest); + i += 2; + } + } + + return i; +} + + +static lzma_ret +armthumb_coder_init(lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter_info *filters, bool is_encoder) +{ + return lzma_simple_coder_init(next, allocator, filters, + &armthumb_code, 0, 4, 2, is_encoder); +} + + +extern lzma_ret +lzma_simple_armthumb_encoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters) +{ + return armthumb_coder_init(next, allocator, filters, true); +} + + +extern lzma_ret +lzma_simple_armthumb_decoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters) +{ + return armthumb_coder_init(next, allocator, filters, false); +} diff --git a/dependencies/cmliblzma/liblzma/simple/ia64.c b/dependencies/cmliblzma/liblzma/simple/ia64.c new file mode 100644 index 0000000..580529e --- /dev/null +++ b/dependencies/cmliblzma/liblzma/simple/ia64.c @@ -0,0 +1,112 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file ia64.c +/// \brief Filter for IA64 (Itanium) binaries +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "simple_private.h" + + +static size_t +ia64_code(void *simple lzma_attribute((__unused__)), + uint32_t now_pos, bool is_encoder, + uint8_t *buffer, size_t size) +{ + static const uint32_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 + }; + + size_t i; + for (i = 0; i + 16 <= size; i += 16) { + const uint32_t instr_template = buffer[i] & 0x1F; + const uint32_t mask = BRANCH_TABLE[instr_template]; + uint32_t bit_pos = 5; + + for (size_t slot = 0; slot < 3; ++slot, bit_pos += 41) { + if (((mask >> slot) & 1) == 0) + continue; + + const size_t byte_pos = (bit_pos >> 3); + const uint32_t bit_res = bit_pos & 0x7; + uint64_t instruction = 0; + + for (size_t j = 0; j < 6; ++j) + instruction += (uint64_t)( + buffer[i + j + byte_pos]) + << (8 * j); + + uint64_t inst_norm = instruction >> bit_res; + + if (((inst_norm >> 37) & 0xF) == 0x5 + && ((inst_norm >> 9) & 0x7) == 0 + /* && (inst_norm & 0x3F)== 0 */ + ) { + uint32_t src = (uint32_t)( + (inst_norm >> 13) & 0xFFFFF); + src |= ((inst_norm >> 36) & 1) << 20; + + src <<= 4; + + uint32_t dest; + if (is_encoder) + dest = now_pos + (uint32_t)(i) + src; + else + dest = src - (now_pos + (uint32_t)(i)); + + dest >>= 4; + + inst_norm &= ~((uint64_t)(0x8FFFFF) << 13); + inst_norm |= (uint64_t)(dest & 0xFFFFF) << 13; + inst_norm |= (uint64_t)(dest & 0x100000) + << (36 - 20); + + instruction &= (1 << bit_res) - 1; + instruction |= (inst_norm << bit_res); + + for (size_t j = 0; j < 6; j++) + buffer[i + j + byte_pos] = (uint8_t)( + instruction + >> (8 * j)); + } + } + } + + return i; +} + + +static lzma_ret +ia64_coder_init(lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter_info *filters, bool is_encoder) +{ + return lzma_simple_coder_init(next, allocator, filters, + &ia64_code, 0, 16, 16, is_encoder); +} + + +extern lzma_ret +lzma_simple_ia64_encoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters) +{ + return ia64_coder_init(next, allocator, filters, true); +} + + +extern lzma_ret +lzma_simple_ia64_decoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters) +{ + return ia64_coder_init(next, allocator, filters, false); +} diff --git a/dependencies/cmliblzma/liblzma/simple/powerpc.c b/dependencies/cmliblzma/liblzma/simple/powerpc.c new file mode 100644 index 0000000..54dfbf1 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/simple/powerpc.c @@ -0,0 +1,75 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file powerpc.c +/// \brief Filter for PowerPC (big endian) binaries +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "simple_private.h" + + +static size_t +powerpc_code(void *simple lzma_attribute((__unused__)), + uint32_t now_pos, bool is_encoder, + uint8_t *buffer, size_t size) +{ + size_t i; + for (i = 0; i + 4 <= size; i += 4) { + // PowerPC branch 6(48) 24(Offset) 1(Abs) 1(Link) + if ((buffer[i] >> 2) == 0x12 + && ((buffer[i + 3] & 3) == 1)) { + + const uint32_t src = ((buffer[i + 0] & 3) << 24) + | (buffer[i + 1] << 16) + | (buffer[i + 2] << 8) + | (buffer[i + 3] & (~3)); + + uint32_t dest; + if (is_encoder) + dest = now_pos + (uint32_t)(i) + src; + else + dest = src - (now_pos + (uint32_t)(i)); + + buffer[i + 0] = 0x48 | ((dest >> 24) & 0x03); + buffer[i + 1] = (dest >> 16); + buffer[i + 2] = (dest >> 8); + buffer[i + 3] &= 0x03; + buffer[i + 3] |= dest; + } + } + + return i; +} + + +static lzma_ret +powerpc_coder_init(lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter_info *filters, bool is_encoder) +{ + return lzma_simple_coder_init(next, allocator, filters, + &powerpc_code, 0, 4, 4, is_encoder); +} + + +extern lzma_ret +lzma_simple_powerpc_encoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters) +{ + return powerpc_coder_init(next, allocator, filters, true); +} + + +extern lzma_ret +lzma_simple_powerpc_decoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters) +{ + return powerpc_coder_init(next, allocator, filters, false); +} diff --git a/dependencies/cmliblzma/liblzma/simple/simple_coder.c b/dependencies/cmliblzma/liblzma/simple/simple_coder.c new file mode 100644 index 0000000..13ebabc --- /dev/null +++ b/dependencies/cmliblzma/liblzma/simple/simple_coder.c @@ -0,0 +1,282 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file simple_coder.c +/// \brief Wrapper for simple filters +/// +/// Simple filters don't change the size of the data i.e. number of bytes +/// in equals the number of bytes out. +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "simple_private.h" + + +/// Copied or encodes/decodes more data to out[]. +static lzma_ret +copy_or_code(lzma_simple_coder *coder, const lzma_allocator *allocator, + const uint8_t *restrict in, size_t *restrict in_pos, + size_t in_size, uint8_t *restrict out, + size_t *restrict out_pos, size_t out_size, lzma_action action) +{ + assert(!coder->end_was_reached); + + if (coder->next.code == NULL) { + lzma_bufcpy(in, in_pos, in_size, out, out_pos, out_size); + + // Check if end of stream was reached. + if (coder->is_encoder && action == LZMA_FINISH + && *in_pos == in_size) + coder->end_was_reached = true; + + } else { + // Call the next coder in the chain to provide us some data. + const lzma_ret ret = coder->next.code( + coder->next.coder, allocator, + in, in_pos, in_size, + out, out_pos, out_size, action); + + if (ret == LZMA_STREAM_END) { + assert(!coder->is_encoder + || action == LZMA_FINISH); + coder->end_was_reached = true; + + } else if (ret != LZMA_OK) { + return ret; + } + } + + return LZMA_OK; +} + + +static size_t +call_filter(lzma_simple_coder *coder, uint8_t *buffer, size_t size) +{ + const size_t filtered = coder->filter(coder->simple, + coder->now_pos, coder->is_encoder, + buffer, size); + coder->now_pos += filtered; + return filtered; +} + + +static lzma_ret +simple_code(void *coder_ptr, const lzma_allocator *allocator, + const uint8_t *restrict in, size_t *restrict in_pos, + size_t in_size, uint8_t *restrict out, + size_t *restrict out_pos, size_t out_size, lzma_action action) +{ + lzma_simple_coder *coder = coder_ptr; + + // TODO: Add partial support for LZMA_SYNC_FLUSH. We can support it + // in cases when the filter is able to filter everything. With most + // simple filters it can be done at offset that is a multiple of 2, + // 4, or 16. With x86 filter, it needs good luck, and thus cannot + // be made to work predictably. + if (action == LZMA_SYNC_FLUSH) + return LZMA_OPTIONS_ERROR; + + // Flush already filtered data from coder->buffer[] to out[]. + if (coder->pos < coder->filtered) { + lzma_bufcpy(coder->buffer, &coder->pos, coder->filtered, + out, out_pos, out_size); + + // If we couldn't flush all the filtered data, return to + // application immediately. + if (coder->pos < coder->filtered) + return LZMA_OK; + + if (coder->end_was_reached) { + assert(coder->filtered == coder->size); + return LZMA_STREAM_END; + } + } + + // If we get here, there is no filtered data left in the buffer. + coder->filtered = 0; + + assert(!coder->end_was_reached); + + // If there is more output space left than there is unfiltered data + // in coder->buffer[], flush coder->buffer[] to out[], and copy/code + // more data to out[] hopefully filling it completely. Then filter + // the data in out[]. This step is where most of the data gets + // filtered if the buffer sizes used by the application are reasonable. + const size_t out_avail = out_size - *out_pos; + const size_t buf_avail = coder->size - coder->pos; + if (out_avail > buf_avail || buf_avail == 0) { + // Store the old position so that we know from which byte + // to start filtering. + const size_t out_start = *out_pos; + + // Flush data from coder->buffer[] to out[], but don't reset + // coder->pos and coder->size yet. This way the coder can be + // restarted if the next filter in the chain returns e.g. + // LZMA_MEM_ERROR. + memcpy(out + *out_pos, coder->buffer + coder->pos, buf_avail); + *out_pos += buf_avail; + + // Copy/Encode/Decode more data to out[]. + { + const lzma_ret ret = copy_or_code(coder, allocator, + in, in_pos, in_size, + out, out_pos, out_size, action); + assert(ret != LZMA_STREAM_END); + if (ret != LZMA_OK) + return ret; + } + + // Filter out[]. + const size_t size = *out_pos - out_start; + const size_t filtered = call_filter( + coder, out + out_start, size); + + const size_t unfiltered = size - filtered; + assert(unfiltered <= coder->allocated / 2); + + // Now we can update coder->pos and coder->size, because + // the next coder in the chain (if any) was successful. + coder->pos = 0; + coder->size = unfiltered; + + if (coder->end_was_reached) { + // The last byte has been copied to out[] already. + // They are left as is. + coder->size = 0; + + } else if (unfiltered > 0) { + // There is unfiltered data left in out[]. Copy it to + // coder->buffer[] and rewind *out_pos appropriately. + *out_pos -= unfiltered; + memcpy(coder->buffer, out + *out_pos, unfiltered); + } + } else if (coder->pos > 0) { + memmove(coder->buffer, coder->buffer + coder->pos, buf_avail); + coder->size -= coder->pos; + coder->pos = 0; + } + + assert(coder->pos == 0); + + // If coder->buffer[] isn't empty, try to fill it by copying/decoding + // more data. Then filter coder->buffer[] and copy the successfully + // filtered data to out[]. It is probable, that some filtered and + // unfiltered data will be left to coder->buffer[]. + if (coder->size > 0) { + { + const lzma_ret ret = copy_or_code(coder, allocator, + in, in_pos, in_size, + coder->buffer, &coder->size, + coder->allocated, action); + assert(ret != LZMA_STREAM_END); + if (ret != LZMA_OK) + return ret; + } + + coder->filtered = call_filter( + coder, coder->buffer, coder->size); + + // Everything is considered to be filtered if coder->buffer[] + // contains the last bytes of the data. + if (coder->end_was_reached) + coder->filtered = coder->size; + + // Flush as much as possible. + lzma_bufcpy(coder->buffer, &coder->pos, coder->filtered, + out, out_pos, out_size); + } + + // Check if we got everything done. + if (coder->end_was_reached && coder->pos == coder->size) + return LZMA_STREAM_END; + + return LZMA_OK; +} + + +static void +simple_coder_end(void *coder_ptr, const lzma_allocator *allocator) +{ + lzma_simple_coder *coder = coder_ptr; + lzma_next_end(&coder->next, allocator); + lzma_free(coder->simple, allocator); + lzma_free(coder, allocator); + return; +} + + +static lzma_ret +simple_coder_update(void *coder_ptr, const lzma_allocator *allocator, + const lzma_filter *filters_null lzma_attribute((__unused__)), + const lzma_filter *reversed_filters) +{ + lzma_simple_coder *coder = coder_ptr; + + // No update support, just call the next filter in the chain. + return lzma_next_filter_update( + &coder->next, allocator, reversed_filters + 1); +} + + +extern lzma_ret +lzma_simple_coder_init(lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter_info *filters, + size_t (*filter)(void *simple, uint32_t now_pos, + bool is_encoder, uint8_t *buffer, size_t size), + size_t simple_size, size_t unfiltered_max, + uint32_t alignment, bool is_encoder) +{ + // Allocate memory for the lzma_simple_coder structure if needed. + lzma_simple_coder *coder = next->coder; + if (coder == NULL) { + // Here we allocate space also for the temporary buffer. We + // need twice the size of unfiltered_max, because then it + // is always possible to filter at least unfiltered_max bytes + // more data in coder->buffer[] if it can be filled completely. + coder = lzma_alloc(sizeof(lzma_simple_coder) + + 2 * unfiltered_max, allocator); + if (coder == NULL) + return LZMA_MEM_ERROR; + + next->coder = coder; + next->code = &simple_code; + next->end = &simple_coder_end; + next->update = &simple_coder_update; + + coder->next = LZMA_NEXT_CODER_INIT; + coder->filter = filter; + coder->allocated = 2 * unfiltered_max; + + // Allocate memory for filter-specific data structure. + if (simple_size > 0) { + coder->simple = lzma_alloc(simple_size, allocator); + if (coder->simple == NULL) + return LZMA_MEM_ERROR; + } else { + coder->simple = NULL; + } + } + + if (filters[0].options != NULL) { + const lzma_options_bcj *simple = filters[0].options; + coder->now_pos = simple->start_offset; + if (coder->now_pos & (alignment - 1)) + return LZMA_OPTIONS_ERROR; + } else { + coder->now_pos = 0; + } + + // Reset variables. + coder->is_encoder = is_encoder; + coder->end_was_reached = false; + coder->pos = 0; + coder->filtered = 0; + coder->size = 0; + + return lzma_next_filter_init(&coder->next, allocator, filters + 1); +} diff --git a/dependencies/cmliblzma/liblzma/simple/simple_coder.h b/dependencies/cmliblzma/liblzma/simple/simple_coder.h new file mode 100644 index 0000000..19c2ee0 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/simple/simple_coder.h @@ -0,0 +1,72 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file simple_coder.h +/// \brief Wrapper for simple filters +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_SIMPLE_CODER_H +#define LZMA_SIMPLE_CODER_H + +#include "common.h" + + +extern lzma_ret lzma_simple_x86_encoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters); + +extern lzma_ret lzma_simple_x86_decoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters); + + +extern lzma_ret lzma_simple_powerpc_encoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters); + +extern lzma_ret lzma_simple_powerpc_decoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters); + + +extern lzma_ret lzma_simple_ia64_encoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters); + +extern lzma_ret lzma_simple_ia64_decoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters); + + +extern lzma_ret lzma_simple_arm_encoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters); + +extern lzma_ret lzma_simple_arm_decoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters); + + +extern lzma_ret lzma_simple_armthumb_encoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters); + +extern lzma_ret lzma_simple_armthumb_decoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters); + + +extern lzma_ret lzma_simple_sparc_encoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters); + +extern lzma_ret lzma_simple_sparc_decoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters); + +#endif diff --git a/dependencies/cmliblzma/liblzma/simple/simple_decoder.c b/dependencies/cmliblzma/liblzma/simple/simple_decoder.c new file mode 100644 index 0000000..1d864f2 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/simple/simple_decoder.c @@ -0,0 +1,40 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file simple_decoder.c +/// \brief Properties decoder for simple filters +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "simple_decoder.h" + + +extern lzma_ret +lzma_simple_props_decode(void **options, const lzma_allocator *allocator, + const uint8_t *props, size_t props_size) +{ + if (props_size == 0) + return LZMA_OK; + + if (props_size != 4) + return LZMA_OPTIONS_ERROR; + + lzma_options_bcj *opt = lzma_alloc( + sizeof(lzma_options_bcj), allocator); + if (opt == NULL) + return LZMA_MEM_ERROR; + + opt->start_offset = unaligned_read32le(props); + + // Don't leave an options structure allocated if start_offset is zero. + if (opt->start_offset == 0) + lzma_free(opt, allocator); + else + *options = opt; + + return LZMA_OK; +} diff --git a/dependencies/cmliblzma/liblzma/simple/simple_decoder.h b/dependencies/cmliblzma/liblzma/simple/simple_decoder.h new file mode 100644 index 0000000..bed8d37 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/simple/simple_decoder.h @@ -0,0 +1,22 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file simple_decoder.h +/// \brief Properties decoder for simple filters +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_SIMPLE_DECODER_H +#define LZMA_SIMPLE_DECODER_H + +#include "simple_coder.h" + +extern lzma_ret lzma_simple_props_decode( + void **options, const lzma_allocator *allocator, + const uint8_t *props, size_t props_size); + +#endif diff --git a/dependencies/cmliblzma/liblzma/simple/simple_encoder.c b/dependencies/cmliblzma/liblzma/simple/simple_encoder.c new file mode 100644 index 0000000..8aa463b --- /dev/null +++ b/dependencies/cmliblzma/liblzma/simple/simple_encoder.c @@ -0,0 +1,38 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file simple_encoder.c +/// \brief Properties encoder for simple filters +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "simple_encoder.h" + + +extern lzma_ret +lzma_simple_props_size(uint32_t *size, const void *options) +{ + const lzma_options_bcj *const opt = options; + *size = (opt == NULL || opt->start_offset == 0) ? 0 : 4; + return LZMA_OK; +} + + +extern lzma_ret +lzma_simple_props_encode(const void *options, uint8_t *out) +{ + const lzma_options_bcj *const opt = options; + + // The default start offset is zero, so we don't need to store any + // options unless the start offset is non-zero. + if (opt == NULL || opt->start_offset == 0) + return LZMA_OK; + + unaligned_write32le(out, opt->start_offset); + + return LZMA_OK; +} diff --git a/dependencies/cmliblzma/liblzma/simple/simple_encoder.h b/dependencies/cmliblzma/liblzma/simple/simple_encoder.h new file mode 100644 index 0000000..1cee482 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/simple/simple_encoder.h @@ -0,0 +1,23 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file simple_encoder.c +/// \brief Properties encoder for simple filters +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_SIMPLE_ENCODER_H +#define LZMA_SIMPLE_ENCODER_H + +#include "simple_coder.h" + + +extern lzma_ret lzma_simple_props_size(uint32_t *size, const void *options); + +extern lzma_ret lzma_simple_props_encode(const void *options, uint8_t *out); + +#endif diff --git a/dependencies/cmliblzma/liblzma/simple/simple_private.h b/dependencies/cmliblzma/liblzma/simple/simple_private.h new file mode 100644 index 0000000..9d2c0fd --- /dev/null +++ b/dependencies/cmliblzma/liblzma/simple/simple_private.h @@ -0,0 +1,74 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file simple_private.h +/// \brief Private definitions for so called simple filters +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_SIMPLE_PRIVATE_H +#define LZMA_SIMPLE_PRIVATE_H + +#include "simple_coder.h" + + +typedef struct { + /// Next filter in the chain + lzma_next_coder next; + + /// True if the next coder in the chain has returned LZMA_STREAM_END. + bool end_was_reached; + + /// True if filter() should encode the data; false to decode. + /// Currently all simple filters use the same function for encoding + /// and decoding, because the difference between encoders and decoders + /// is very small. + bool is_encoder; + + /// Pointer to filter-specific function, which does + /// the actual filtering. + size_t (*filter)(void *simple, uint32_t now_pos, + bool is_encoder, uint8_t *buffer, size_t size); + + /// Pointer to filter-specific data, or NULL if filter doesn't need + /// any extra data. + void *simple; + + /// The lowest 32 bits of the current position in the data. Most + /// filters need this to do conversions between absolute and relative + /// addresses. + uint32_t now_pos; + + /// Size of the memory allocated for the buffer. + size_t allocated; + + /// Flushing position in the temporary buffer. buffer[pos] is the + /// next byte to be copied to out[]. + size_t pos; + + /// buffer[filtered] is the first unfiltered byte. When pos is smaller + /// than filtered, there is unflushed filtered data in the buffer. + size_t filtered; + + /// Total number of bytes (both filtered and unfiltered) currently + /// in the temporary buffer. + size_t size; + + /// Temporary buffer + uint8_t buffer[]; +} lzma_simple_coder; + + +extern lzma_ret lzma_simple_coder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters, + size_t (*filter)(void *simple, uint32_t now_pos, + bool is_encoder, uint8_t *buffer, size_t size), + size_t simple_size, size_t unfiltered_max, + uint32_t alignment, bool is_encoder); + +#endif diff --git a/dependencies/cmliblzma/liblzma/simple/sparc.c b/dependencies/cmliblzma/liblzma/simple/sparc.c new file mode 100644 index 0000000..74b2655 --- /dev/null +++ b/dependencies/cmliblzma/liblzma/simple/sparc.c @@ -0,0 +1,83 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file sparc.c +/// \brief Filter for SPARC binaries +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "simple_private.h" + + +static size_t +sparc_code(void *simple lzma_attribute((__unused__)), + uint32_t now_pos, bool is_encoder, + uint8_t *buffer, size_t size) +{ + size_t i; + for (i = 0; i + 4 <= size; i += 4) { + + if ((buffer[i] == 0x40 && (buffer[i + 1] & 0xC0) == 0x00) + || (buffer[i] == 0x7F + && (buffer[i + 1] & 0xC0) == 0xC0)) { + + uint32_t src = ((uint32_t)buffer[i + 0] << 24) + | ((uint32_t)buffer[i + 1] << 16) + | ((uint32_t)buffer[i + 2] << 8) + | ((uint32_t)buffer[i + 3]); + + src <<= 2; + + uint32_t dest; + if (is_encoder) + dest = now_pos + (uint32_t)(i) + src; + else + dest = src - (now_pos + (uint32_t)(i)); + + dest >>= 2; + + dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) + | (dest & 0x3FFFFF) + | 0x40000000; + + buffer[i + 0] = (uint8_t)(dest >> 24); + buffer[i + 1] = (uint8_t)(dest >> 16); + buffer[i + 2] = (uint8_t)(dest >> 8); + buffer[i + 3] = (uint8_t)(dest); + } + } + + return i; +} + + +static lzma_ret +sparc_coder_init(lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter_info *filters, bool is_encoder) +{ + return lzma_simple_coder_init(next, allocator, filters, + &sparc_code, 0, 4, 4, is_encoder); +} + + +extern lzma_ret +lzma_simple_sparc_encoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters) +{ + return sparc_coder_init(next, allocator, filters, true); +} + + +extern lzma_ret +lzma_simple_sparc_decoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters) +{ + return sparc_coder_init(next, allocator, filters, false); +} diff --git a/dependencies/cmliblzma/liblzma/simple/x86.c b/dependencies/cmliblzma/liblzma/simple/x86.c new file mode 100644 index 0000000..b38cebf --- /dev/null +++ b/dependencies/cmliblzma/liblzma/simple/x86.c @@ -0,0 +1,159 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file x86.c +/// \brief Filter for x86 binaries (BCJ filter) +/// +// Authors: Igor Pavlov +// Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "simple_private.h" + + +#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) + + +typedef struct { + uint32_t prev_mask; + uint32_t prev_pos; +} lzma_simple_x86; + + +static size_t +x86_code(void *simple_ptr, uint32_t now_pos, bool is_encoder, + uint8_t *buffer, size_t size) +{ + static const bool MASK_TO_ALLOWED_STATUS[8] + = { true, true, true, false, true, false, false, false }; + + static const uint32_t MASK_TO_BIT_NUMBER[8] + = { 0, 1, 2, 2, 3, 3, 3, 3 }; + + lzma_simple_x86 *simple = simple_ptr; + uint32_t prev_mask = simple->prev_mask; + uint32_t prev_pos = simple->prev_pos; + + if (size < 5) + return 0; + + if (now_pos - prev_pos > 5) + prev_pos = now_pos - 5; + + const size_t limit = size - 5; + size_t buffer_pos = 0; + + while (buffer_pos <= limit) { + uint8_t b = buffer[buffer_pos]; + if (b != 0xE8 && b != 0xE9) { + ++buffer_pos; + continue; + } + + const uint32_t offset = now_pos + (uint32_t)(buffer_pos) + - prev_pos; + prev_pos = now_pos + (uint32_t)(buffer_pos); + + if (offset > 5) { + prev_mask = 0; + } else { + for (uint32_t i = 0; i < offset; ++i) { + prev_mask &= 0x77; + prev_mask <<= 1; + } + } + + b = buffer[buffer_pos + 4]; + + if (Test86MSByte(b) + && MASK_TO_ALLOWED_STATUS[(prev_mask >> 1) & 0x7] + && (prev_mask >> 1) < 0x10) { + + uint32_t src = ((uint32_t)(b) << 24) + | ((uint32_t)(buffer[buffer_pos + 3]) << 16) + | ((uint32_t)(buffer[buffer_pos + 2]) << 8) + | (buffer[buffer_pos + 1]); + + uint32_t dest; + while (true) { + if (is_encoder) + dest = src + (now_pos + (uint32_t)( + buffer_pos) + 5); + else + dest = src - (now_pos + (uint32_t)( + buffer_pos) + 5); + + if (prev_mask == 0) + break; + + const uint32_t i = MASK_TO_BIT_NUMBER[ + prev_mask >> 1]; + + b = (uint8_t)(dest >> (24 - i * 8)); + + if (!Test86MSByte(b)) + break; + + src = dest ^ ((1ull << (32 - i * 8)) - 1); + } + + buffer[buffer_pos + 4] + = (uint8_t)(~(((dest >> 24) & 1) - 1)); + buffer[buffer_pos + 3] = (uint8_t)(dest >> 16); + buffer[buffer_pos + 2] = (uint8_t)(dest >> 8); + buffer[buffer_pos + 1] = (uint8_t)(dest); + buffer_pos += 5; + prev_mask = 0; + + } else { + ++buffer_pos; + prev_mask |= 1; + if (Test86MSByte(b)) + prev_mask |= 0x10; + } + } + + simple->prev_mask = prev_mask; + simple->prev_pos = prev_pos; + + return buffer_pos; +} + + +static lzma_ret +x86_coder_init(lzma_next_coder *next, const lzma_allocator *allocator, + const lzma_filter_info *filters, bool is_encoder) +{ + const lzma_ret ret = lzma_simple_coder_init(next, allocator, filters, + &x86_code, sizeof(lzma_simple_x86), 5, 1, is_encoder); + + if (ret == LZMA_OK) { + lzma_simple_coder *coder = next->coder; + lzma_simple_x86 *simple = coder->simple; + simple->prev_mask = 0; + simple->prev_pos = (uint32_t)(-5); + } + + return ret; +} + + +extern lzma_ret +lzma_simple_x86_encoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters) +{ + return x86_coder_init(next, allocator, filters, true); +} + + +extern lzma_ret +lzma_simple_x86_decoder_init(lzma_next_coder *next, + const lzma_allocator *allocator, + const lzma_filter_info *filters) +{ + return x86_coder_init(next, allocator, filters, false); +} diff --git a/dependencies/drivelist/.editorconfig b/dependencies/drivelist/.editorconfig new file mode 100644 index 0000000..1afda63 --- /dev/null +++ b/dependencies/drivelist/.editorconfig @@ -0,0 +1,16 @@ +# editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false + +[*.plist] +indent_style = tab diff --git a/dependencies/drivelist/.eslintrc.yml b/dependencies/drivelist/.eslintrc.yml new file mode 100644 index 0000000..1cbfcfc --- /dev/null +++ b/dependencies/drivelist/.eslintrc.yml @@ -0,0 +1,467 @@ +env: + browser: true + commonjs: true + es6: true + node: true + mocha: true +extends: 'eslint:recommended' +rules: + + # Possible Errors + + comma-dangle: + - error + - never + no-cond-assign: + - off + no-console: + - off + no-constant-condition: + - error + no-control-regex: + - error + no-debugger: + - error + no-dupe-args: + - error + no-dupe-keys: + - error + no-duplicate-case: + - error + no-empty: + - error + no-empty-character-class: + - error + no-ex-assign: + - error + no-extra-boolean-cast: + - error + no-extra-parens: + - error + no-extra-semi: + - error + no-func-assign: + - error + no-inner-declarations: + - error + - both + no-invalid-regexp: + - error + no-irregular-whitespace: + - error + no-negated-in-lhs: + - error + no-obj-calls: + - error + no-prototype-builtins: + - error + no-regex-spaces: + - error + no-sparse-arrays: + - error + no-unexpected-multiline: + - error + no-unreachable: + - error + no-unsafe-finally: + - error + use-isnan: + - error + valid-jsdoc: + - error + - requireReturn: false + requireReturnDescription: false + valid-typeof: + - error + + # Best Practices + + accessor-pairs: + - error + array-callback-return: + - error + block-scoped-var: + - error + complexity: + - off + curly: + - error + default-case: + - error + dot-location: + - error + - property + dot-notation: + - error + eqeqeq: + - 1 + guard-for-in: + - error + no-alert: + - error + no-caller: + - error + no-case-declarations: + - error + no-div-regex: + - error + no-else-return: + - error + no-empty-function: + - error + no-empty-pattern: + - error + no-eq-null: + - off + no-eval: + - error + no-extend-native: + - error + no-extra-bind: + - error + no-extra-label: + - error + no-fallthrough: + - error + no-floating-decimal: + - error + no-implicit-coercion: + - error + no-implicit-globals: + - error + no-implied-eval: + - error + no-iterator: + - error + no-labels: + - error + no-lone-blocks: + - error + no-loop-func: + - error + no-multi-spaces: + - error + no-multi-str: + - error + no-native-reassign: + - error + no-new: + - error + no-new-func: + - error + no-new-wrappers: + - error + no-octal: + - error + no-octal-escape: + - error + no-proto: + - error + no-redeclare: + - error + no-return-assign: + - error + no-script-url: + - error + no-self-assign: + - error + no-self-compare: + - error + no-sequences: + - error + no-throw-literal: + - error + no-unmodified-loop-condition: + - error + no-unused-labels: + - error + no-useless-call: + - error + no-useless-concat: + - error + no-useless-escape: + - error + no-void: + - error + no-warning-comments: + - off + no-with: + - error + radix: + - error + vars-on-top: + - off + wrap-iife: + - error + - outside + yoda: + - error + + # Strict mode + + strict: + - error + - global + + # Variables + + no-catch-shadow: + - error + no-delete-var: + - error + no-label-var: + - error + no-shadow: + - error + no-shadow-restricted-names: + - error + no-undef: + - error + no-undef-init: + - error + no-unused-vars: + - error + no-use-before-define: + - error + + # NodeJS and CommonJS + + callback-return: + - error + global-require: + - off + handle-callback-err: + - error + no-mixed-requires: + - error + no-new-require: + - error + no-path-concat: + - error + no-process-env: + - off + no-process-exit: + - off + no-sync: + - off + + # Stylistic Issues + + array-bracket-spacing: + - error + - always + block-spacing: + - error + brace-style: + - error + - 1tbs + camelcase: + - error + comma-spacing: + - error + - before: false + after: true + comma-style: + - error + - last + computed-property-spacing: + - error + - never + consistent-this: + - error + - self + eol-last: + - error + func-names: + - error + - never + func-style: + - error + - expression + id-blacklist: + - error + indent: + - error + - 2 + - SwitchCase: 1 + key-spacing: + - error + - beforeColon: false + afterColon: true + mode: strict + keyword-spacing: + - error + - before: true + after: true + linebreak-style: + - error + - unix + lines-around-comment: + - error + - beforeBlockComment: true + afterBlockComment: false + beforeLineComment: true + afterLineComment: false + allowBlockStart: true + allowBlockEnd: false + allowObjectStart: true + allowObjectEnd: false + allowArrayStart: true + allowArrayEnd: false + max-len: + - error + - code: 130 + comments: 150 + ignoreComments: false + ignoreTrailingComments: false + ignoreUrls: true + max-statements-per-line: + - error + - max: 1 + new-parens: + - error + no-array-constructor: + - error + no-bitwise: + - error + no-continue: + - error + no-inline-comments: + - error + no-mixed-operators: + - off + no-mixed-spaces-and-tabs: + - error + no-multiple-empty-lines: + - error + - max: 1 + maxEOF: 1 + maxBOF: 0 + no-negated-condition: + - error + no-nested-ternary: + - error + no-new-object: + - error + no-plusplus: + - error + no-spaced-func: + - error + no-trailing-spaces: + - error + no-underscore-dangle: + - error + - allowAfterThis: false + no-unneeded-ternary: + - error + no-whitespace-before-property: + - error + object-curly-newline: + - error + - minProperties: 1 + object-curly-spacing: + - error + - always + object-property-newline: + - error + one-var: + - error + - never + operator-assignment: + - error + - always + operator-linebreak: + - error + - before + quote-props: + - error + - as-needed + quotes: + - error + - single + require-jsdoc: + - error + - require: + FunctionDeclaration: true + ClassDeclaration: true + MethodDefinition: true + semi: + - error + - always + semi-spacing: + - error + - before: false + after: true + space-before-blocks: + - error + space-before-function-paren: + - error + - never + space-in-parens: + - error + - never + space-infix-ops: + - error + spaced-comment: + - error + - always + unicode-bom: + - error + + # ECMAScript 6 + + arrow-body-style: + - error + - always + arrow-parens: + - error + - always + arrow-spacing: + - error + - before: true + after: true + constructor-super: + - error + generator-star-spacing: + - error + - before: true + after: false + no-class-assign: + - error + no-confusing-arrow: + - error + no-const-assign: + - error + no-dupe-class-members: + - error + no-duplicate-imports: + - error + no-new-symbol: + - error + no-this-before-super: + - error + no-useless-computed-key: + - error + no-useless-constructor: + - error + no-useless-rename: + - error + no-var: + - error + prefer-const: + - error + prefer-reflect: + - error + prefer-spread: + - error + require-yield: + - error + rest-spread-spacing: + - error + template-curly-spacing: + - error + - never + yield-star-spacing: + - error + - before: true + after: false diff --git a/dependencies/drivelist/.gitignore b/dependencies/drivelist/.gitignore new file mode 100644 index 0000000..9f0fb7e --- /dev/null +++ b/dependencies/drivelist/.gitignore @@ -0,0 +1,29 @@ +# Logs +logs +*.log +npm-debug.log* + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build + +# Dependency directory +# https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git +node_modules +prebuilds diff --git a/dependencies/drivelist/.npmignore b/dependencies/drivelist/.npmignore new file mode 100644 index 0000000..d7bc7e7 --- /dev/null +++ b/dependencies/drivelist/.npmignore @@ -0,0 +1,9 @@ +.* +*.yml + +build +doc +example +tests +prebuilds +ci diff --git a/dependencies/drivelist/.resinci.yml b/dependencies/drivelist/.resinci.yml new file mode 100644 index 0000000..a95e94a --- /dev/null +++ b/dependencies/drivelist/.resinci.yml @@ -0,0 +1,41 @@ +--- +npm: + environment: + - name: CCACHE_TEMPDIR + value: /tmp/.ccache-temp + - name: CCACHE_COMPRESS + value: 1 + - name: CC + value: clang + - name: CXX + value: clang++ + platforms: + - name: linux + os: ubuntu + architecture: x86_64 + node_versions: + - "10" + - "8" + - "6" + - name: linux + os: ubuntu + architecture: x86 + node_versions: + - "8" + - "6" + - name: darwin + os: macos + architecture: x86_64 + node_versions: + - "6" + - name: windows + os: windows + architecture: x86_64 + node_versions: + - "6" + - name: windows + os: windows + architecture: x86 + node_versions: + - "6" + diff --git a/dependencies/drivelist/.travis.yml b/dependencies/drivelist/.travis.yml new file mode 100644 index 0000000..6f43fbc --- /dev/null +++ b/dependencies/drivelist/.travis.yml @@ -0,0 +1,39 @@ +language: node_js +node_js: + - 10 + - 8 + - 6 +os: + - linux + - osx +before_install: + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then + pip install --user -r requirements.txt; + else + pip2 install -r requirements.txt; + fi +script: + - npm test +compiler: clang-4.0 +env: + global: + - CCACHE_TEMPDIR=/tmp/.ccache-temp + - CCACHE_COMPRESS=1 + - CC="clang" + - CXX="clang++" +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - libstdc++-5-dev +notifications: + email: false +deploy: + skip_cleanup: true + provider: script + script: ./ci/prebuild-publish.sh + on: + node: 10 + tags: true + branch: master diff --git a/dependencies/drivelist/CHANGELOG.md b/dependencies/drivelist/CHANGELOG.md new file mode 100644 index 0000000..b56dea5 --- /dev/null +++ b/dependencies/drivelist/CHANGELOG.md @@ -0,0 +1,606 @@ +# Change Log + +All notable changes to this project will be documented in this file +automatically by Versionist. DO NOT EDIT THIS FILE MANUALLY! +This project adheres to [Semantic Versioning](http://semver.org/). + +## 8.0.9 - 2019-11-06 + +* Avoid segfaulting on mac when some disk description fields are null [Alexis Svinartchouk] + +## 8.0.8 - 2019-10-08 + +* Fix tests [Alexis Svinartchouk] +* Fix typo in readme [Alexis Svinartchouk] + +## 8.0.7 - 2019-09-20 + +* Update nan to ^2.14 to fix builds targetting electron 6 [Alexis Svinartchouk] + +## 8.0.6 - 2019-03-20 + +* Update example in readme [Alexis Svinartchouk] + +## 8.0.5 - 2019-03-20 + +* Update resin-lint to ^3.0.1 [Alexis Svinartchouk] + +## 8.0.4 - 2019-03-19 + +* Unregister DASession callback to avoid crash [Robert Vojta] + +## 8.0.3 - 2019-03-18 + +* Fix DASession and NSMutableArray leaks on macOS [Alexis Svinartchouk] + +## 8.0.2 - 2019-03-04 + +* Fix isVirtual value on macOS [Robert Vojta] + +## 8.0.1 - 2019-02-27 + +* Fix macOS crash when SD card is ejected [Robert Vojta] + +## 8.0.0 - 2019-02-22 + +* Address PR comments [Alexis Svinartchouk] +* Try `lsblk --pairs` if parsing `lsblk --json` fails [Alexis Svinartchouk] +* Convert to typescript, use promises instead of callbacks [Alexis Svinartchouk] + +## 7.0.3 - 2019-02-20 + +* Fix parsing lsblk --pairs output for disks with no partition table [Alexis Svinartchouk] + +## 7.0.2 - 2019-02-20 + +* Update prebuild to ^8.1.2 [Alexis Svinartchouk] + +## 7.0.1 - 2019-01-28 + +* Remove unused diskutil file and its tests [Alexis Svinartchouk] + +## 7.0.0 - 2019-01-28 + +* Remove outdated docs. [Alexis Svinartchouk] +* Feat(mac): Native implementation for drivelist [Robin Andersson] + +## 6.4.6 - 2019-01-10 + +* Fix tests incorrect mountpoints [Lorenzo Alberto Maria Ambrosi] +* Fix devices mountpoints for lsblk in pairs mode [Lorenzo Alberto Maria Ambrosi] + +## 6.4.5 - 2019-01-10 + +* Fix tests incorrect device.size [Lorenzo Alberto Maria Ambrosi] +* Fix linting errors & add specs with plist return value assertions [Robin Andersson] + +## 6.4.4 - 2019-01-10 + +* Fix build on xcode 10.1 [Alexis Svinartchouk] + +## v6.4.3 - 2018-09-10 + +* Lsblk: Fix listing of empty mountpoints [Jonas Hermsmeier] + +## v6.4.2 - 2018-09-03 + +* Lsblk: Check `hotplug` to set `isRemovable` [Jonas Hermsmeier] +* Ci: Add .resinci.yml [John (Jack) Brown] + +## v6.4.1 - 2018-08-28 + +* Lsblk: Fix missing `devicePath` property [Jonas Hermsmeier] + +## v6.4.0 - 2018-08-02 + +* Feat(diskutil): Populate devicePath on Mac OS #297 [Jonas Hermsmeier] + +## v6.3.2 - 2018-08-02 + +* Fix(diskutil): Also probe Ejectable to determine removabililty #298 [Jonas Hermsmeier] + +## v6.3.1 - 2018-08-01 + +* Test(lsblk): Add test case for root device mountpoints #293 [Jonas Hermsmeier] +* Fix(lsblk): Enumerate mountpoints on root devices #293 [Jonas Hermsmeier] +* Fix(lsblk): Fall back to mountpoint if no label given #293 [Jonas Hermsmeier] +* Fix(lsblk): Resolve relative device names #293 [Jonas Hermsmeier] + +## v6.3.0 - 2018-07-09 + +* Fix(linux): Fix pair consolidation for lsblk #255 [Jonas Hermsmeier] +* Feat(lib): Use lsblk directly, parse json output #255 [Jonas Hermsmeier] + +## v6.2.5 - 2018-07-06 + +* Fix(linux): Add flag to lsblk to list all devices #287 [Jonas Hermsmeier] + +## v6.2.4 - 2018-07-04 + +* Fix(test): Add python requirements.txt for tests #288 [Jonas Hermsmeier] + +## v6.2.3 - 2018-05-25 + +* Fix(src): Fix nan callback deprecation warning #284 [Jonas Hermsmeier] + +## v6.2.2 - 2018-05-10 + +* Fix(ci): Fix Node version arg passed to prebuild script #280 [Jonas Hermsmeier] + +## v6.2.1 - 2018-05-10 + +* Upgrade(package): Bump prebuild dependencies #279 [Jonas Hermsmeier] +* Fix(ci): Only prebuild with Node 10 #279 [Jonas Hermsmeier] + +## v6.2.0 - 2018-05-09 + +* Feat(linux): Add unique device path #278 [User Name] + +## v6.1.8 - 2018-04-26 + +* Chore(ci): Build, test & publish releases for Node.js v10 #273 [Tim Perry] + +## v6.1.7 - 2018-04-16 + +* Fix(diskutil): Fall back to MediaName if EntryName is not available #270 [Jonas Hermsmeier] +* Fix(diskutil): Track & filter out device info errors #270 [Jonas Hermsmeier] + +## v6.1.6 - 2018-04-13 + +* Fix(diskutil): Added an error for diskutil returning null [grumpyoldman-io] + +## v6.1.5 - 2018-04-05 + +* Fix(diskutil): Fix ReferenceError when DeviceNode is undefined #266 [Jonas Hermsmeier] + +## v6.1.4 - 2018-04-02 + +* Upgrade(package): Bump dependencies #264 [Jonas Hermsmeier] + +## v6.1.3 - 2018-03-17 + +* Fix(diskutil): Use VolumeAllocationBlockSize if available #260 [Jonas Hermsmeier] + +## v6.1.2 - 2018-03-16 + +* Fix(test): Avoid test timeout on AppVeyor #259 [Jonas Hermsmeier] +* Test(diskutil): Add tests for devices without partitions #259 [Jonas Hermsmeier] +* Fix(diskutil): Support mountpoints without partitions #259 [Jonas Hermsmeier] +* Fix(diskutil): Fix handling of devices without partitions #259 [Jonas Hermsmeier] + +## v6.1.1 - 2018-03-13 + +* Fix(package): Remove obsolete bin entries #256 [Jonas Hermsmeier] + +## v6.1.0 - 2018-03-09 + +* Feat(lib): Use diskutil directly, parse plist output #253 [Jonas Hermsmeier] + +## v6.0.5 - 2018-03-02 + +* Upgrade(package): Bump dependencies #252 [Jonas Hermsmeier] + +## v6.0.4 - 2018-01-18 + +* Fix(windows): Impl IsSystemDevice() #250 [Jonas Hermsmeier] + +## v6.0.3 - 2018-01-18 + +* Fix crash on Windows 7 #249 [Jonas Hermsmeier] + +## v6.0.2 - 2018-01-14 + +* Fix(darwin): Use proper flag to enable extended regexes in `sed` Fixes #247 #248 [Andrew Scheller] + +## v6.0.1 - 2018-01-12 + +* Fix(darwin): Allow mountpoints containing space characters #246 [Andrew Scheller] + +## v6.0.0 - 2018-01-05 + +* Feat: Rewrite native bindings to use IOCTL #243 [Jonas Hermsmeier] + +## v5.2.12 - 2017-12-28 + +* Chore(package): Bump dependencies #242 [Jonas Hermsmeier] + +## v5.2.11 - 2017-12-14 + +* Refactor: Remove lodash #235 [Jonas Hermsmeier] + +## v5.2.10 - 2017-12-12 + +* Fix(package): Fix prebuild script being run on build #236 [Jonas Hermsmeier] + +## v5.2.9 - 2017-12-09 + +* Fix: Remove the final usage of perl from darwin.sh #238 [Andrew Scheller] + +## v5.2.8 - 2017-12-08 + +* Chore: pip on Travis OSX is now pip2 #239 [Andrew Scheller] + +## v5.2.7 - 2017-10-17 + +* Upgrade(package): Bump dependencies #232 [Jonas Hermsmeier] + +## v5.2.6 - 2017-10-13 + +* Fix(ci): Ensure the Travis box finds bash #230 [Jonas Hermsmeier] + +## v5.2.5 - 2017-10-13 + +* Chore(ci): Add CI deployment scripts #227 [Jonas Hermsmeier] + +## v5.2.4 - 2017-10-06 + +* Correctly execute macOS and GNU/Linux scripts inside directories mounted as `noexec`. #229 [Juan Cruz Viotti] + +## v5.2.3 - 2017-10-06 + +* Fix: Bring back support for Node.js v4 #225 [Zoltan Kochan] + +## v5.2.2 - 2017-10-02 + +* Chore(appveyor): Explicitly set base image #223 [Jonas Hermsmeier] + +## v5.2.1 - 2017-09-28 + +* Upgrade(package): Update dependencies #221 [Jonas Hermsmeier] + +## v5.2.0 - 2017-09-28 + +* Feat(package): Add prebuilds for native bindings #219 [Jonas Hermsmeier] + +## v5.1.8 - 2017-08-28 + +* Store GNU/Linux temporary scripts in `$XDG_RUNTIME_DIR`. #209 [Juan Cruz Viotti] + +## v5.1.7 - 2017-08-28 + +* Ensure all volume handles get closed on Windows. #212 [Juan Cruz Viotti] + +## v5.1.6 - 2017-08-28 + +* Fix(windows): log the volume we're working on #211 [Juan Cruz Viotti] + +## v5.1.5 - 2017-08-14 + +* Correctly handle BitLocker locked Windows volumes. #206 [Juan Cruz Viotti] + +## v5.1.4 - 2017-08-07 + +* Get more detailed error codes from the Windows implementation. [Juan Cruz Viotti] + +## v5.1.3 - 2017-08-01 + +* Fix "Couldn't scan the drives: An unknown error occurred" where there is a mounted virtual drive. [Juan Cruz Viotti] + +## v5.1.2 - 2017-08-01 + +* Fix "Couldn't initialize the scanner: An unknown error occurred" error. [Juan Cruz Viotti] + +## v5.1.1 - 2017-08-01 + +* Refactor(windows): don't use COM/WMI to retrieve a drive media type [Juan Cruz Viotti] + +## v5.1.0 - 2017-07-31 + +* Feat: add a `displayName` property to drive objects [Juan Cruz Viotti] + +## v5.0.28 - 2017-07-31 + +* Feat(windows): print HRESULT hex in debug information [Juan Cruz Viotti] + +## v5.0.27 - 2017-07-19 + +* Fix: small typo in EAGAIN error message [Juan Cruz Viotti] + +## v5.0.26 - 2017-07-18 + +* Fix: handle EAGAIN spawning errors [Juan Cruz Viotti] +* Refactor: reduce debug logging if unlink was successful [Juan Cruz Viotti] + +## v5.0.25 - 2017-06-29 + +* Feat(windows): print debugging information when DRIVELIST_DEBUG is set [Juan Cruz Viotti] +* Fix: property clean up tmp file after exec [Jonas Hermsmeier] +* Fix(windows): ERROR_NOT_READY on empty SD Card reader [Juan Cruz Viotti] +* Chore(package): Fix missing EOL in package.json [Jonas Hermsmeier] +* Fix(windows): all drives are interpreted as read-only [Juan Cruz Viotti] +* Refactor(windows): don't use WMI to list volumes [Juan Cruz Viotti] +* Fix(windows): detect read-only flag on SD Cards without a filesystem (#183) [Juan Cruz Viotti] +* Refactor(windows): Use an IOCTL to determine the partition type (#181) [Juan Cruz Viotti] + +## v5.0.24 - 2017-06-27 + +* Refactor(windows): implement volume::GetType() [Juan Cruz Viotti] + +## v5.0.23 - 2017-06-15 + +* Upgrade(package): Bump dependencies [Jonas Hermsmeier] +* Doc(README): Add npm monthly download count [Jonas Hermsmeier] +* Adapt changelog for versionbot [Kostas Lekkas] +* Doc(README): Fix Travis link, use Etcher chat [Jonas Hermsmeier] + +## v5.0.22 + +- Fix perl taking all the CPU in macOS in some cases + +## v5.0.21 + +- Join volume and device names as descriptions if they both exists on macOS + +## v5.0.20 + +- Inline platform scripts as a JSON file. + +## v5.0.19 + +- Correctly deal with unicode characters coming from drive descriptions +- Correctly deal with invalid escape sequences coming from drive descriptions + +## v5.0.18 + +- Fix mountpoints getting cut if they contain a `#` in GNU/Linux and macOS + +## v5.0.17 + +- Fix literal `\040` on mountpoints that contain spaces in GNU/Linux + +## v5.0.16 + +- Fix awk expression that replaces periods with underscores before evaluating + `udevadm` output in GNU/Linux. + +## v5.0.15 + +- Increase debug logging in the case of script errors +- Prevent errors when unplugging drives while the scripts are running + +## v5.0.14 + +- Catch the exit code of the wrapped VBScript on Windows. + +## v5.0.13 + +**Important:** v5.0.11 and v5.0.12 were both published to NPM from a Windows +machine. This messed up the execution permissions of the drive detection +scripts, causing `EACCES` errors. + +This version is equal to v5.0.12, but was released from a UNIX based system. + +## v5.0.12 [BROKEN] + +- Ensure the Windows script has execution permissions. + +## v5.0.11 [BROKEN] + +- Omit empty SD Card readers on Windows. + +## v5.0.10 + +- Don't include drive letters assigned to no file system in Windows mount points. + +## v5.0.9 + +- Print platform scripts `stderr` output to a debug channel instead of throwing if the script exitted with code zero. +- Fix bug where only the first mount point is reported on GNU/Linux. +- Ensure every potentially problematic value is double quoted in the GNU/Linux and macOS scripts. + +## v5.0.8 + +- Fix "is not recognised as an internal or external command" errors on Windows. + +## v5.0.7 + +- Interpret "Fixed" drives as system drives in macOS. + +## v5.0.6 + +- Fix uncaught error caused by a weird Windows configuration edge where multiple partitions were reported to have the same drive letter. + +## v5.0.5 + +- Fix system drives being detected as removable drives on Mac Mini. + +## v5.0.4 + +- Replace periods with underscores before evaluating `udevadm` output in GNU/Linux. + +## v5.0.3 + +- Fix `drivelist` not detecting mountpoints in Windows due to a space/tab YAML parsing issue. + +## v5.0.2 + +- Don't require .NET VBScript classes in Windows platform script. + +## v5.0.1 + +- Fix `YAMLException: bad indentation of a sequence entry` Windows error. + +## v5.0.0 + +- Transform `mountpoint` into an array of objects called `mountpoints`. +- Improve GNU/Linux detection performance. +- Correctly get SD Card readers descriptions in GNU/Linux. + +## v4.0.0 + +- Ignore invalid YAML output from platform scripts. +- Group mount points of drives with multiple partitions in Windows. +- Switch project to JavaScript. +- Switch license to Apache 2.0. + +## v3.3.4 + +- Ensure `%SYSTEMROOT%\System32` is in the `%PATH%` before calling `cscript.exe` on Windows. + +## v3.3.3 + +- Default device name to device id if drive doesn't have an assigned letter in Windows. + +## v3.3.2 + +- List all partition's mountpoints in OS X. + +## v3.3.1 + +- Fix `blkid: command not found` in GNU/Linux. + +## v3.3.0 + +- Fix `null` device when unplugging a device while detecting drives. +- Expose a "raw" property in all devices. +- Attempt to display the volume name as description in OS X. + +## v3.2.6 + +- Fix internal removable drives being considered "system" in macOS Sierra. + +## v3.2.5 + +- Fix YAML error when a description contains question marks in GNU/Linux. + +## v3.2.4 + +- Fix missing sizes in macOS Sierra. + +## v3.2.3 + +- Handle mountpoints with spaces in GNU/Linux. + +## v3.2.2 + +- Check if drive is removable when the drive has no file system in Windows. + +## v3.2.1 + +- Make use of `df` to determine mountpoints in GNU/Linux. + +## v3.2.0 + +- Add a property called `protected`. + +## v3.1.2 + +- Prevent certain system drives to be detected as removable in GNU/Linux. + +## v3.1.1 + +- Fix issue that caused some hard drives to be listed as removable drives. + +## v3.1.0 + +- Show non-mountable disk drives in Windows. + +## v3.0.0 + +- Parse size as a number representing bytes. + +## v2.0.14 + +- Detect mount points of drives mounted by UUID on GNU/Linux. + +## v2.0.13 + +- Keep once decimal in Windows drive sizes. + +## v2.0.12 + +- Make sure MacBook's internal SDCard readers are marked as removable. + +## v2.0.11 + +- Escape double quotes in description to prevent YAML errors. + +## v2.0.10 + +- Improve the way we detect system drives in Windows. + +## v2.0.9 + +- Use `udev` to determine if a drive is removable on GNU/Linux. +- Mark internal and non-removable drives as system drives in OS X. +- Omit loop devices in GNU/Linux. +- Omit CD/DVD drives in GNU/Linux. + +## v2.0.8 + +- Omit mounted DMG images in OS X. + +## v2.0.7 + +- Add a display name property called `name`. + +## v2.0.6 + +- Fix boolean values being surrounded by quotes. + +## v2.0.5 + +- Trim trailing commas on GNU/Linux mountpoints. + +## v2.0.4 + +- Support running inside Electron. + +## v2.0.3 + +- Treat multiple mountpoint as a comma separated list of paths in GNU/Linux. + +## v2.0.2 + +- Escape paths including spaces in unix based operating systems. + +## v2.0.1 + +- Escape backslashes in Windows devices to avoid weird characters. + +## v2.0.0 + +- Add example file for easy testing. +- Redesign Windows script to match the new output scheme. +- Refer to `osx` as Darwin everywhere. +- Implement GNU/Linux scanning bash script. +- Unify parsing between all supported operating systems. +- Add `system` property to returned drives. +- Remove `drivelist.isSystem()` predicate. +- Fix issue that caused some OS X drives to not be detected. + +## v1.3.2 + +- Handle edge case where OS X drives contain a description within parenthesis in `diskutil list`. + +## v1.3.1 + +- Surround Windows script path in double quotes to avoid issues with paths incuding white space. + +## v1.3.0 + +- Add `mountpoint` attribute to drives. + +## v1.2.2 + +- Fix issue where a removable drive was detected as a system drive in Linux. + +## v1.2.1 + +- Fix win32 issue where DeviceID gets part of the device description. + +## v1.2.0 + +- Implement isSystem predicate. + +## v1.1.2 + +- Prevent empty lsblk model crash the module. Return `undefined` description instead. + +## v1.1.1 + +- Prevent empty wmic size crash the module. Return `undefined` size instead. + +## v1.1.0 + +- Return non supported OS error to the callback instead of just throwing it. diff --git a/dependencies/drivelist/LICENSE b/dependencies/drivelist/LICENSE new file mode 100644 index 0000000..430d42b --- /dev/null +++ b/dependencies/drivelist/LICENSE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff --git a/dependencies/drivelist/README.md b/dependencies/drivelist/README.md new file mode 100644 index 0000000..86c39d8 --- /dev/null +++ b/dependencies/drivelist/README.md @@ -0,0 +1,218 @@ + + +drivelist +========= + +> List all connected drives in your computer, in all major operating systems. + +[![Current Release](https://img.shields.io/npm/v/drivelist.svg?style=flat-square)](https://npmjs.com/package/drivelist) +[![License](https://img.shields.io/npm/l/drivelist.svg?style=flat-square)](https://npmjs.com/package/drivelist) +[![Downloads](https://img.shields.io/npm/dm/drivelist.svg?style=flat-square)](https://npmjs.com/package/drivelist) +[![Travis CI status](https://img.shields.io/travis/balena-io-modules/drivelist/master.svg?style=flat-square&label=linux)](https://travis-ci.org/resin-io-modules/drivelist/branches) +[![AppVeyor status](https://img.shields.io/appveyor/ci/balena-io/drivelist/master.svg?style=flat-square&label=windows)](https://ci.appveyor.com/project/resin-io/drivelist/branch/master) +[![Dependency status](https://img.shields.io/david/balena-io-modules/drivelist.svg?style=flat-square)](https://david-dm.org/resin-io-modules/drivelist) +[![Gitter Chat](https://img.shields.io/gitter/room/balena-io/etcher.svg?style=flat-square)](https://gitter.im/resin-io/etcher) + +Notice that this module **does not require** admin privileges to get the drives in any supported operating system. + +Supports: + +- Windows. +- GNU/Linux distributions that include [util-linux](https://github.com/karelzak/util-linux) and [udev](https://wiki.archlinux.org/index.php/udev). +- Mac OS X. + +When the user executes `drivelist.list()`, the module checks the operating +system of the client and executes the corresponding drive scanning script. + +Examples (the output will vary depending on your machine): + +```js +const drivelist = require('drivelist'); + +const drives = await drivelist.list(); +console.log(drives); +``` + +*** + +Mac OS X: + +```sh +[ + { + device: '/dev/disk0', + displayName: '/dev/disk0', + description: 'GUID_partition_scheme', + size: 68719476736, + mountpoints: [ + { + path: '/' + } + ], + raw: '/dev/rdisk0', + protected: false, + system: true + }, + { + device: '/dev/disk1', + displayName: '/dev/disk1', + description: 'Apple_HFS Macintosh HD', + size: 68719476736, + mountpoints: [], + raw: '/dev/rdisk0', + protected: false, + system: true + } +] +``` + +*** + +GNU/Linux + +```sh +[ + { + device: '/dev/sda', + displayName: '/dev/sda', + description: 'WDC WD10JPVX-75J', + size: 68719476736, + mountpoints: [ + { + path: '/' + } + ], + raw: '/dev/sda', + protected: false, + system: true + }, + { + device: '/dev/sdb', + displayName: '/dev/sdb', + description: 'DataTraveler 2.0', + size: 7823458304, + mountpoints: [ + { + path: '/media/UNTITLED' + } + ], + raw: '/dev/sdb', + protected: true, + system: false + } +] +``` + +*** + +Windows + +```sh +[ + { + device: '\\\\.\\PHYSICALDRIVE0', + displayName: 'C:', + description: 'WDC WD10JPVX-75JC3T0', + size: 68719476736, + mountpoints: [ + { + path: 'C:' + } + ], + raw: '\\\\.\\PHYSICALDRIVE0', + protected: false, + system: true + }, + { + device: '\\\\.\\PHYSICALDRIVE1', + displayName: 'D:, F:', + description: 'Generic STORAGE DEVICE USB Device', + size: 7823458304, + mountpoints: [ + { + path: 'D:' + }, + { + path: 'F:' + } + ], + raw: '\\\\.\\PHYSICALDRIVE1', + protected: true, + system: false + }, + { + device: '\\\\.\\PHYSICALDRIVE2', + displayName: '\\\\.\\PHYSICALDRIVE2', + description: 'Silicon-Power2G', + size: 2014314496, + mountpoints: [], + raw: '\\\\.\\PHYSICALDRIVE2', + protected: false, + system: false + } +] +``` + +Installation +------------ + +Install `drivelist` by running: + +```sh +$ npm install --save drivelist +``` + +Documentation +------------- + + + +### drivelist~list() ⇒ Promise +**Kind**: inner method of [drivelist](#module_drivelist) +**Summary**: List available drives +**Returns**: Promise - [] +**Access**: public +**Example** +```js +const drivelist = require('drivelist'); + +const drives = await drivelist.list(); +drives.forEach((drive) => { + console.log(drive); +}); +``` + +Tests +----- + +Run the test suite by doing: + +```sh +$ npm test +``` + +Contribute +---------- + +We're looking forward to support more operating systems. Please raise an issue or even better, send a PR to increase support! + +- Issue Tracker: [github.com/balena-io-modules/drivelist/issues](https://github.com/resin-io-modules/drivelist/issues) +- Source Code: [github.com/balena-io-modules/drivelist](https://github.com/resin-io-modules/drivelist) + +Before submitting a PR, please make sure that you include tests, and that the linter runs without any warning: + +```sh +$ npm run lint +``` + +Support +------- + +If you're having any problem, please [raise an issue](https://github.com/balena-io-modules/drivelist/issues/new) on GitHub. + +License +------- + +The project is licensed under the Apache 2.0 license. + +[yaml]: http://yaml.org diff --git a/dependencies/drivelist/appveyor.yml b/dependencies/drivelist/appveyor.yml new file mode 100644 index 0000000..7ba2ec1 --- /dev/null +++ b/dependencies/drivelist/appveyor.yml @@ -0,0 +1,38 @@ +# appveyor file +# http://www.appveyor.com/docs/appveyor-yml +image: + - Visual Studio 2015 + +init: + - git config --global core.autocrlf input + +cache: + - C:\Users\appveyor\.node-gyp + - '%AppData%\npm-cache' + +# what combinations to test +environment: + matrix: + - nodejs_version: 10 + - nodejs_version: 8 + - nodejs_version: 6 + - nodejs_version: 4 + +platform: + - x86 + - x64 + +install: + - pip install -r requirements.txt + - ps: Install-Product node $env:nodejs_version x64 + - npm install + +build: off + +test_script: + - node --version + - npm --version + - cmd: npm test + +deploy_script: + - ci\prebuild-publish.bat %nodejs_version% diff --git a/dependencies/drivelist/binding.gyp b/dependencies/drivelist/binding.gyp new file mode 100644 index 0000000..8860d5e --- /dev/null +++ b/dependencies/drivelist/binding.gyp @@ -0,0 +1,62 @@ +{ + "targets": [ + { + "target_name": "drivelist", + "include_dirs" : [ + " + +drivelist +========= + +> List all connected drives in your computer, in all major operating systems. + +[![Current Release](https://img.shields.io/npm/v/drivelist.svg?style=flat-square)](https://npmjs.com/package/drivelist) +[![License](https://img.shields.io/npm/l/drivelist.svg?style=flat-square)](https://npmjs.com/package/drivelist) +[![Downloads](https://img.shields.io/npm/dm/drivelist.svg?style=flat-square)](https://npmjs.com/package/drivelist) +[![Travis CI status](https://img.shields.io/travis/balena-io-modules/drivelist/master.svg?style=flat-square&label=linux)](https://travis-ci.org/resin-io-modules/drivelist/branches) +[![AppVeyor status](https://img.shields.io/appveyor/ci/balena-io/drivelist/master.svg?style=flat-square&label=windows)](https://ci.appveyor.com/project/resin-io/drivelist/branch/master) +[![Dependency status](https://img.shields.io/david/balena-io-modules/drivelist.svg?style=flat-square)](https://david-dm.org/resin-io-modules/drivelist) +[![Gitter Chat](https://img.shields.io/gitter/room/balena-io/etcher.svg?style=flat-square)](https://gitter.im/resin-io/etcher) + +Notice that this module **does not require** admin privileges to get the drives in any supported operating system. + +Supports: + +- Windows. +- GNU/Linux distributions that include [util-linux](https://github.com/karelzak/util-linux) and [udev](https://wiki.archlinux.org/index.php/udev). +- Mac OS X. + +When the user executes `drivelist.list()`, the module checks the operating +system of the client and executes the corresponding drive scanning script. + +Examples (the output will vary depending on your machine): + +```js +const drivelist = require('drivelist'); + +const drives = await drivelist.list(); +console.log(drives); +``` + +*** + +Mac OS X: + +```sh +[ + { + device: '/dev/disk0', + displayName: '/dev/disk0', + description: 'GUID_partition_scheme', + size: 68719476736, + mountpoints: [ + { + path: '/' + } + ], + raw: '/dev/rdisk0', + protected: false, + system: true + }, + { + device: '/dev/disk1', + displayName: '/dev/disk1', + description: 'Apple_HFS Macintosh HD', + size: 68719476736, + mountpoints: [], + raw: '/dev/rdisk0', + protected: false, + system: true + } +] +``` + +*** + +GNU/Linux + +```sh +[ + { + device: '/dev/sda', + displayName: '/dev/sda', + description: 'WDC WD10JPVX-75J', + size: 68719476736, + mountpoints: [ + { + path: '/' + } + ], + raw: '/dev/sda', + protected: false, + system: true + }, + { + device: '/dev/sdb', + displayName: '/dev/sdb', + description: 'DataTraveler 2.0', + size: 7823458304, + mountpoints: [ + { + path: '/media/UNTITLED' + } + ], + raw: '/dev/sdb', + protected: true, + system: false + } +] +``` + +*** + +Windows + +```sh +[ + { + device: '\\\\.\\PHYSICALDRIVE0', + displayName: 'C:', + description: 'WDC WD10JPVX-75JC3T0', + size: 68719476736, + mountpoints: [ + { + path: 'C:' + } + ], + raw: '\\\\.\\PHYSICALDRIVE0', + protected: false, + system: true + }, + { + device: '\\\\.\\PHYSICALDRIVE1', + displayName: 'D:, F:', + description: 'Generic STORAGE DEVICE USB Device', + size: 7823458304, + mountpoints: [ + { + path: 'D:' + }, + { + path: 'F:' + } + ], + raw: '\\\\.\\PHYSICALDRIVE1', + protected: true, + system: false + }, + { + device: '\\\\.\\PHYSICALDRIVE2', + displayName: '\\\\.\\PHYSICALDRIVE2', + description: 'Silicon-Power2G', + size: 2014314496, + mountpoints: [], + raw: '\\\\.\\PHYSICALDRIVE2', + protected: false, + system: false + } +] +``` + +Installation +------------ + +Install `drivelist` by running: + +```sh +$ npm install --save drivelist +``` + +Documentation +------------- + +{{#module name="drivelist"}} +{{>body~}} +{{>member-index~}} +{{>separator~}} +{{>members~}} +{{/module}} + +Tests +----- + +Run the test suite by doing: + +```sh +$ npm test +``` + +Contribute +---------- + +We're looking forward to support more operating systems. Please raise an issue or even better, send a PR to increase support! + +- Issue Tracker: [github.com/balena-io-modules/drivelist/issues](https://github.com/resin-io-modules/drivelist/issues) +- Source Code: [github.com/balena-io-modules/drivelist](https://github.com/resin-io-modules/drivelist) + +Before submitting a PR, please make sure that you include tests, and that the linter runs without any warning: + +```sh +$ npm run lint +``` + +Support +------- + +If you're having any problem, please [raise an issue](https://github.com/balena-io-modules/drivelist/issues/new) on GitHub. + +License +------- + +The project is licensed under the Apache 2.0 license. + +[yaml]: http://yaml.org diff --git a/dependencies/drivelist/example/index.ts b/dependencies/drivelist/example/index.ts new file mode 100644 index 0000000..0c3de17 --- /dev/null +++ b/dependencies/drivelist/example/index.ts @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Balena.io + * + * 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. + */ +import { inspect } from 'util'; + +import { list } from '..'; + +async function main() { + let drives; + try { + drives = await list(); + } catch (error) { + console.error(error); + process.exitCode = 1; + return; + } + + console.log(inspect(drives, { + colors: process.stdout.isTTY, + depth: null + })); +} + +main(); diff --git a/dependencies/drivelist/lib/index.ts b/dependencies/drivelist/lib/index.ts new file mode 100644 index 0000000..bbc5c6c --- /dev/null +++ b/dependencies/drivelist/lib/index.ts @@ -0,0 +1,85 @@ +/* + * Copyright 2016 Balena.io + * + * 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. + */ + +/** + * @module drivelist + */ + +import bindings = require('bindings'); +import { platform } from 'os'; + +import { lsblk } from './lsblk'; + +export interface Mountpoint { + path: string; + label: string | null; +} + +export interface Drive { + blockSize: number; + busType: string; + busVersion: null; + description: string; + device: string; + devicePath: string | null; + enumerator: string; + error: null; + isCard: null; + isReadOnly: boolean; + isRemovable: boolean; + isSCSI: boolean | null; + isSystem: boolean; + isUAS: null; + isUSB: boolean | null; + isVirtual: boolean | null; + logicalBlockSize: number; + mountpoints: Mountpoint[]; + raw: string; + size: number | null; +} + +/** + * @summary List available drives + * @function + * @public + * + * @returns {Promise} [] + * + * @example + * const drivelist = require('drivelist'); + * + * const drives = await drivelist.list(); + * drives.forEach((drive) => { + * console.log(drive); + * }); + */ +export async function list(): Promise { + const plat = platform(); + if (plat === 'win32' || plat === 'darwin') { + return new Promise((resolve, reject) => { + bindings('drivelist').list((error: Error, drives: Drive[]) => { + if (error != null) { + reject(error); + } else { + resolve(drives); + } + }); + }); + } else if (plat === 'linux') { + return await lsblk(); + } + throw new Error(`Your OS is not supported by this module: ${platform()}`); +} diff --git a/dependencies/drivelist/lib/lsblk/index.ts b/dependencies/drivelist/lib/lsblk/index.ts new file mode 100644 index 0000000..191efeb --- /dev/null +++ b/dependencies/drivelist/lib/lsblk/index.ts @@ -0,0 +1,93 @@ +/* + * Copyright 2018 Balena.io + * + * 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. + */ + +import { execFile } from 'mz/child_process'; +import { readdir, readlink } from 'mz/fs'; +import { join, resolve } from 'path'; + +import { Drive } from '..'; +import { parse as parseJSON } from './json'; +import { parse as parsePairs } from './pairs'; + +const DISK_PATH_DIR = '/dev/disk/by-path/'; + +let SUPPORTS_JSON = true; + +async function getDevicePaths(): Promise> { + const mapping = new Map(); + for (const filename of await readdir(DISK_PATH_DIR)) { + const linkPath = join(DISK_PATH_DIR, filename); + let link: string; + try { + link = await readlink(linkPath); + } catch (error) { + continue; + } + const devicePath = resolve(DISK_PATH_DIR, link); + mapping.set(devicePath, linkPath); + } + return mapping; +} + +async function addDevicePaths(devices: Drive[]): Promise { + const devicePaths = await getDevicePaths(); + for (const device of devices) { + device.devicePath = devicePaths.get(device.device) || null; + } +} + +async function getOutput(command: string, ...args: string[]) { + const [stdout] = await execFile(command, args); + return stdout; +} + +async function lsblkJSON(): Promise { + return parseJSON( + await getOutput( + 'lsblk', + '--bytes', + '--all', + '--json', + '--paths', + '--output-all', + ), + ); +} + +async function lsblkPairs(): Promise { + return parsePairs(await getOutput('lsblk', '--bytes', '--all', '--pairs')); +} + +async function $lsblk(): Promise { + if (SUPPORTS_JSON) { + try { + return await lsblkJSON(); + } catch (error) { + SUPPORTS_JSON = false; + } + } + return await lsblkPairs(); +} + +export async function lsblk(): Promise { + const drives = await $lsblk(); + try { + await addDevicePaths(drives); + } catch (error) { + // Couldn't add device paths + } + return drives; +} diff --git a/dependencies/drivelist/lib/lsblk/json.ts b/dependencies/drivelist/lib/lsblk/json.ts new file mode 100644 index 0000000..b786786 --- /dev/null +++ b/dependencies/drivelist/lib/lsblk/json.ts @@ -0,0 +1,155 @@ +/* + * Copyright 2018 Balena.io + * + * 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. + */ + +import { posix } from 'path'; + +import { Drive, Mountpoint } from '..'; + +interface LsblkJsonOutput { + blockdevices: LsblkJsonOutputDevice[]; +} + +interface LsblkJsonOutputDevice { + children: LsblkJsonOutputDeviceChild[]; + hotplug?: string; + kname?: string; + label: string | null; + 'log-sec'?: string; + model: string | null; + mountpoint: string | null; + name: string; + partlabel: string | null; + 'phy-sec'?: string; + rm?: string; + ro?: string; + size?: string; + subsystems?: string; + tran?: string; + vendor: string | null; +} + +interface LsblkJsonOutputDeviceChild { + label: string | null; + mountpoint?: string; + partlabel: string | null; +} + +function getMountpoints( + children: Array, +): Mountpoint[] { + return children + .filter(child => { + return child.mountpoint; + }) + .map(child => { + return { + path: child.mountpoint!, + label: child.label || child.partlabel, + }; + }); +} + +function getDescription(device: LsblkJsonOutputDevice): string { + const description = [ + device.label || '', + device.vendor || '', + device.model || '', + ]; + if (device.children) { + let subLabels = device.children + .filter(c => (c.label && c.label !== device.label) || c.mountpoint) + .map(c => c.label || c.mountpoint); + subLabels = Array.from(new Set(subLabels)); + if (subLabels.length) { + description.push(`(${subLabels.join(', ')})`); + } + } + return description + .join(' ') + .replace(/\s+/g, ' ') + .trim(); +} + +function resolveDeviceName(name?: string): string | null { + if (!name) { + return null; + } + if (!posix.isAbsolute(name)) { + return posix.resolve('/dev', name); + } + return name; +} + +export function transform(data: LsblkJsonOutput): Drive[] { + return data.blockdevices + .map(device => + Object.assign({}, device, { + name: resolveDeviceName(device.name), + kname: resolveDeviceName(device.kname), + }), + ) + .filter( + device => + // Omit loop devices, CD/DVD drives, and RAM + !device.name.startsWith('/dev/loop') && + !device.name.startsWith('/dev/sr') && + !device.name.startsWith('/dev/ram'), + ) + .map( + (device: LsblkJsonOutputDevice): Drive => { + const isVirtual = device.subsystems + ? /^(block)$/i.test(device.subsystems) + : null; + const isSCSI = device.tran + ? /^(sata|scsi|ata|ide|pci)$/i.test(device.tran) + : null; + const isUSB = device.tran ? /^(usb)$/i.test(device.tran) : null; + const isReadOnly = Number(device.ro) === 1; + const isRemovable = + Number(device.rm) === 1 || + Number(device.hotplug) === 1 || + Boolean(isVirtual); + return { + enumerator: 'lsblk:json', + busType: (device.tran || 'UNKNOWN').toUpperCase(), + busVersion: null, + device: device.name, + devicePath: null, + raw: device.kname || device.name, + description: getDescription(device), + error: null, + size: Number(device.size) || null, + blockSize: Number(device['phy-sec']) || 512, + logicalBlockSize: Number(device['log-sec']) || 512, + mountpoints: device.children + ? getMountpoints(device.children) + : getMountpoints([device]), + isReadOnly, + isSystem: !isRemovable && !isVirtual, + isVirtual, + isRemovable, + isCard: null, + isSCSI, + isUSB, + isUAS: null, + }; + }, + ); +} + +export function parse(stdout: string): Drive[] { + return transform(JSON.parse(stdout)); +} diff --git a/dependencies/drivelist/lib/lsblk/pairs.ts b/dependencies/drivelist/lib/lsblk/pairs.ts new file mode 100644 index 0000000..f7a1065 --- /dev/null +++ b/dependencies/drivelist/lib/lsblk/pairs.ts @@ -0,0 +1,182 @@ +/* + * Copyright 2018 Balena.io + * + * 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. + */ +import { Drive, Mountpoint } from '..'; + +interface Dict { + [K: string]: T; +} + +function parseLsblkLine(line: string): Dict { + const data: Dict = {}; + let offset = 0; + let key = ''; + let value = ''; + + const keyChar = /[^"=]/; + const whitespace = /\s+/; + const escape = '\\'; + let state = 'key'; + + while (offset < line.length) { + if (state === 'key') { + while (keyChar.test(line[offset])) { + key += line[offset]; + offset += 1; + } + if (line[offset] === '=') { + state = 'value'; + offset += 1; + } + } else if (state === 'value') { + if (line[offset] !== '"') { + throw new Error(`Expected '"', saw "${line[offset]}"`); + } + offset += 1; + while (line[offset] !== '"' && line[offset - 1] !== escape) { + value += line[offset]; + offset += 1; + } + if (line[offset] !== '"') { + throw new Error(`Expected '"', saw "${line[offset]}"`); + } + offset += 1; + data[key.toLowerCase()] = value.trim(); + key = ''; + value = ''; + state = 'space'; + } else if (state === 'space') { + while (whitespace.test(line[offset])) { + offset += 1; + } + state = 'key'; + } else { + throw new Error(`Undefined state "${state}"`); + } + } + + return data; +} + +function parseLsblk(output: string): Array> { + return output + .trim() + .split(/\r?\n/g) + .map(parseLsblkLine); +} + +function consolidate( + devices: Array>, +): Array & { mountpoints: Mountpoint[] }> { + const primaries = devices.filter(device => { + return ( + device.type === 'disk' && + !device.name.startsWith('ram') && + !device.name.startsWith('sr') + ); + }); + + return primaries.map(device => { + return Object.assign({}, device, { + mountpoints: devices + .filter(child => { + return ( + ['disk', 'part'].includes(child.type) && + child.mountpoint && + child.name.startsWith(device.name) + ); + }) + .map( + (child): Mountpoint => { + return { + path: child.mountpoint, + label: child.label, + }; + }, + ), + }); + }); +} + +function getDescription( + device: Dict & { mountpoints: Mountpoint[] }, +): string { + const description = [ + device.label || '', + device.vendor || '', + device.model || '', + ]; + if (device.mountpoints.length) { + let subLabels = device.mountpoints + .filter(c => { + return (c.label && c.label !== device.label) || c.path; + }) + .map(c => { + return c.label || c.path; + }); + subLabels = Array.from(new Set(subLabels)); + if (subLabels.length) { + description.push(`(${subLabels.join(', ')})`); + } + } + return description + .join(' ') + .replace(/\s+/g, ' ') + .trim(); +} + +export function parse(stdout: string): Drive[] { + const devices = consolidate(parseLsblk(stdout)); + + return devices.map( + (device: Dict & { mountpoints: Mountpoint[] }): Drive => { + const isVirtual = device.subsystems + ? /^block$/i.test(device.subsystems) + : null; + const isSCSI = device.tran + ? /^(?:sata|scsi|ata|ide|pci)$/i.test(device.tran) + : null; + const isUSB = device.tran ? /^usb$/i.test(device.tran) : null; + const isReadOnly = Number(device.ro) === 1; + const isRemovable = + Number(device.rm) === 1 || + Number(device.hotplug) === 1 || + Boolean(isVirtual); + + return { + enumerator: 'lsblk:pairs', + busType: (device.tran || 'UNKNOWN').toUpperCase(), + busVersion: null, + device: '/dev/' + device.name, + devicePath: null, + raw: '/dev/' + device.name, + description: getDescription(device) || device.name, + error: null, + size: Number(device.size) || null, + blockSize: Number(device['phy-sec']) || 512, + logicalBlockSize: Number(device['log-sec']) || 512, + mountpoints: device.mountpoints, + isReadOnly, + isSystem: !isRemovable && !isVirtual, + isVirtual, + isRemovable, + isCard: null, + isSCSI, + isUSB, + isUAS: null, + }; + }, + ); +} diff --git a/dependencies/drivelist/package.json b/dependencies/drivelist/package.json new file mode 100644 index 0000000..7e342dd --- /dev/null +++ b/dependencies/drivelist/package.json @@ -0,0 +1,66 @@ +{ + "name": "drivelist", + "version": "8.0.9", + "description": "List all connected drives in your computer, in all major operating systems", + "main": "js/index.js", + "homepage": "https://github.com/balena-io-modules/drivelist", + "gypfile": true, + "repository": { + "type": "git", + "url": "git://github.com/balena-io-modules/drivelist.git" + }, + "keywords": [ + "disk", + "cross", + "platform", + "physical", + "drive", + "list" + ], + "directories": { + "test": "tests" + }, + "scripts": { + "test": "mocha -r ts-node/register tests/**/*.spec.ts -R spec", + "lint": "npm run lint-cpp && npm run lint-ts", + "lint-cpp": "cpplint --recursive src", + "lint-ts": "resin-lint --typescript lib tests", + "prettier": "prettier --config ./node_modules/resin-lint/config/.prettierrc --write \"lib/**/*.ts\" \"tests/**/*.ts\"", + "readme": "jsdoc2md --template doc/README.hbs js/index.js > README.md", + "configure": "node-gyp configure", + "build": "node-gyp rebuild", + "build-ts": "tsc", + "rebuild": "node-gyp rebuild", + "install": "prebuild-install || node-gyp rebuild", + "prebuild-release": "prebuild --all --strip", + "prepublishOnly": "npm run build-ts && npm run readme" + }, + "author": "Juan Cruz Viotti ", + "license": "Apache-2.0", + "engines": { + "node": ">=6" + }, + "devDependencies": { + "@types/bindings": "^1.3.0", + "@types/chai": "^4.1.7", + "@types/mocha": "^5.2.6", + "@types/mz": "0.0.32", + "@types/sinon": "^7.0.6", + "chai": "^4.2.0", + "eslint": "^4.19.1", + "jsdoc-to-markdown": "^4.0.1", + "mocha": "^6.0.0", + "prebuild": "^8.1.2", + "resin-lint": "^3.0.1", + "sinon": "^7.2.4", + "ts-node": "^8.0.2", + "typescript": "^3.2.4" + }, + "dependencies": { + "bindings": "^1.3.0", + "debug": "^3.1.0", + "mz": "^2.7.0", + "nan": "^2.14.0", + "prebuild-install": "^5.2.4" + } +} diff --git a/dependencies/drivelist/requirements.txt b/dependencies/drivelist/requirements.txt new file mode 100644 index 0000000..ca3b3e8 --- /dev/null +++ b/dependencies/drivelist/requirements.txt @@ -0,0 +1 @@ +cpplint==1.3.0 diff --git a/dependencies/drivelist/src/darwin/REDiskList.h b/dependencies/drivelist/src/darwin/REDiskList.h new file mode 100644 index 0000000..5566ca6 --- /dev/null +++ b/dependencies/drivelist/src/darwin/REDiskList.h @@ -0,0 +1,41 @@ +/* + * Copyright 2019 balena.io + * Copyright 2018 Robin Andersson + * + * 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. + */ + +#ifndef SRC_DARWIN_REDISKLIST_H_ +#define SRC_DARWIN_REDISKLIST_H_ + +#import + +/** + * Class to return a list of disks synchronously + * To use the class, just init an instance of it and + * it will populate the disks property with NSStrings + * + * @author Robin Andersson + */ +@interface REDiskList : NSObject + +/** + * NSArray of disks and partitions + * Disks are in the format disk0, disk1 etc + * Partitions are in the format disk0s1, disk1s1 etc + */ +@property(readonly) NSArray *disks; + +@end + +#endif // SRC_DARWIN_REDISKLIST_H_ diff --git a/dependencies/drivelist/src/darwin/REDiskList.m b/dependencies/drivelist/src/darwin/REDiskList.m new file mode 100644 index 0000000..60a63d0 --- /dev/null +++ b/dependencies/drivelist/src/darwin/REDiskList.m @@ -0,0 +1,61 @@ +/* + * Copyright 2019 balena.io + * Copyright 2018 Robin Andersson + * + * 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. + */ + +#import "REDiskList.h" +#import + +@implementation REDiskList + +- (id)init { + self = [super init]; + + if (self) { + _disks = [[NSMutableArray alloc] init]; + [self populateDisksBlocking]; + [_disks sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; + } + + return self; +} + +-(void)dealloc { + [_disks release]; + [super dealloc]; +} + +void appendDisk(DADiskRef disk, void *context) { + NSMutableArray *_disks = (__bridge NSMutableArray*)context; + const char *bsdName = DADiskGetBSDName(disk); + if (bsdName != nil) { + [_disks addObject:[NSString stringWithUTF8String:bsdName]]; + } +} + +- (void)populateDisksBlocking { + DASessionRef session = DASessionCreate(kCFAllocatorDefault); + if (session) { + DARegisterDiskAppearedCallback(session, NULL, appendDisk, (void*)_disks); + CFRunLoopRef runLoop = [[NSRunLoop currentRunLoop] getCFRunLoop]; + DASessionScheduleWithRunLoop(session, runLoop, kCFRunLoopDefaultMode); + CFRunLoopStop(runLoop); + CFRunLoopRunInMode((CFStringRef)NSDefaultRunLoopMode, 0.05, NO); + DAUnregisterCallback(session, appendDisk, (void*)_disks); + CFRelease(session); + } +} + +@end diff --git a/dependencies/drivelist/src/darwin/list.mm b/dependencies/drivelist/src/darwin/list.mm new file mode 100644 index 0000000..f8f1dd4 --- /dev/null +++ b/dependencies/drivelist/src/darwin/list.mm @@ -0,0 +1,179 @@ +/* + * Copyright 2019 balena.io + * Copyright 2018 Robin Andersson + * + * 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 +#include "../drivelist.hpp" + +#import "REDiskList.h" +#import +#import + +namespace Drivelist { + bool IsDiskPartition(NSString *disk) { + NSPredicate *partitionRegEx = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", @"disk\\d+s\\d+"]; + return [partitionRegEx evaluateWithObject:disk]; + } + + bool IsCard(CFDictionaryRef diskDescription) { + CFDictionaryRef mediaIconDict = (CFDictionaryRef)CFDictionaryGetValue( + diskDescription, + kDADiskDescriptionMediaIconKey + ); + if (mediaIconDict == nil) { + return false; + } + + CFStringRef iconFileNameKeyRef = CFStringCreateWithCString(NULL, "IOBundleResourceFile", kCFStringEncodingUTF8); + CFStringRef iconFileNameRef = (CFStringRef)CFDictionaryGetValue(mediaIconDict, iconFileNameKeyRef); + CFRelease(iconFileNameKeyRef); + + if (iconFileNameRef == nil) { + return false; + } + + // macOS 10.14.3 - External SD card reader provides `Removable.icns`, not `SD.icns`. + // But we can't use it to detect SD card, because external drive has `Removable.icns` as well. + return [(NSString *)iconFileNameRef isEqualToString:@"SD.icns"]; + } + + NSNumber *DictionaryGetNumber(CFDictionaryRef dict, const void *key) { + return (NSNumber*)CFDictionaryGetValue(dict, key); + } + + DeviceDescriptor CreateDeviceDescriptorFromDiskDescription(std::string diskBsdName, CFDictionaryRef diskDescription) { + NSString *deviceProtocol = (NSString*)CFDictionaryGetValue(diskDescription, kDADiskDescriptionDeviceProtocolKey); + NSNumber *blockSize = DictionaryGetNumber(diskDescription, kDADiskDescriptionMediaBlockSizeKey); + bool isInternal = [DictionaryGetNumber(diskDescription, kDADiskDescriptionDeviceInternalKey) boolValue]; + bool isRemovable = [DictionaryGetNumber(diskDescription, kDADiskDescriptionMediaRemovableKey) boolValue]; + bool isEjectable = [DictionaryGetNumber(diskDescription, kDADiskDescriptionMediaEjectableKey) boolValue]; + + DeviceDescriptor device = DeviceDescriptor(); + device.enumerator = "DiskArbitration"; + device.busType = (deviceProtocol != nil) ? [deviceProtocol UTF8String] : ""; + device.busVersion = ""; + device.busVersionNull = true; + device.device = "/dev/" + diskBsdName; + NSString *devicePath = (NSString*)CFDictionaryGetValue(diskDescription, kDADiskDescriptionBusPathKey); + device.devicePath = (devicePath != nil) ? [devicePath UTF8String] : ""; + device.raw = "/dev/r" + diskBsdName; + NSString *description = (NSString*)CFDictionaryGetValue(diskDescription, kDADiskDescriptionMediaNameKey); + device.description = (description != nil) ? [description UTF8String] : ""; + device.error = ""; + // NOTE: Not sure if kDADiskDescriptionMediaBlockSizeKey returns + // the physical or logical block size since both values are equal + // on my machine + // + // The can be checked with the following command: + // diskutil info / | grep "Block Size" + device.blockSize = [blockSize unsignedIntValue]; + device.logicalBlockSize = [blockSize unsignedIntValue]; + device.size = [DictionaryGetNumber(diskDescription, kDADiskDescriptionMediaSizeKey) unsignedLongValue]; + device.isReadOnly = ![DictionaryGetNumber(diskDescription, kDADiskDescriptionMediaWritableKey) boolValue]; + device.isSystem = isInternal && !isRemovable; + device.isVirtual = ((deviceProtocol != nil) && [deviceProtocol isEqualToString:@"Virtual Interface"]); + device.isRemovable = isRemovable || isEjectable; + device.isCard = IsCard(diskDescription); + // NOTE(robin): Not convinced that these bus types should result + // in device.isSCSI = true, it is rather "not usb or sd drive" bool + // But the old implementation was like this so kept it this way + NSArray *scsiTypes = [NSArray arrayWithObjects:@"SATA", @"SCSI", @"ATA", @"IDE", @"PCI", nil]; + device.isSCSI = ((deviceProtocol != nil) && [scsiTypes containsObject:deviceProtocol]); + device.isUSB = ((deviceProtocol != nil) && [deviceProtocol isEqualToString:@"USB"]); + device.isUAS = false; + device.isUASNull = true; + + return device; + } + + std::vector ListStorageDevices() { + std::vector deviceList; + + DASessionRef session = DASessionCreate(kCFAllocatorDefault); + if (session == nil) { + return deviceList; + } + + REDiskList *dl = [[REDiskList alloc] init]; + for (NSString* diskBsdName in dl.disks) { + if (IsDiskPartition(diskBsdName)) { + continue; + } + + std::string diskBsdNameStr = [diskBsdName UTF8String]; + DADiskRef disk = DADiskCreateFromBSDName(kCFAllocatorDefault, session, diskBsdNameStr.c_str()); + if (disk == nil) { + continue; + } + + CFDictionaryRef diskDescription = DADiskCopyDescription(disk); + if (diskDescription == nil) { + CFRelease(disk); + continue; + } + + DeviceDescriptor device = CreateDeviceDescriptorFromDiskDescription(diskBsdNameStr, diskDescription); + deviceList.push_back(device); + + CFRelease(diskDescription); + CFRelease(disk); + } + [dl release]; + + // Add mount points + NSArray *volumeKeys = [NSArray arrayWithObjects:NSURLVolumeNameKey, NSURLVolumeLocalizedNameKey, nil]; + NSArray *volumePaths = [ + [NSFileManager defaultManager] + mountedVolumeURLsIncludingResourceValuesForKeys:volumeKeys + options:0 + ]; + + for (NSURL *path in volumePaths) { + DADiskRef disk = DADiskCreateFromVolumePath(kCFAllocatorDefault, session, (__bridge CFURLRef)path); + if (disk == nil) { + continue; + } + + const char *bsdnameChar = DADiskGetBSDName(disk); + if (bsdnameChar == nil) { + CFRelease(disk); + continue; + } + + NSString *volumeName; + [path getResourceValue:&volumeName forKey:NSURLVolumeLocalizedNameKey error:nil]; + + std::string partitionBsdName = std::string(bsdnameChar); + std::string diskBsdName = partitionBsdName.substr(0, partitionBsdName.find("s", 5)); + + for(std::vector::size_type i = 0; i != deviceList.size(); i++) { + DeviceDescriptor *dd = &deviceList[i]; + + if (dd->device == "/dev/" + diskBsdName) { + dd->mountpoints.push_back([[path path] UTF8String]); + dd->mountpointLabels.push_back([volumeName UTF8String]); + break; + } + } + + CFRelease(disk); + } + CFRelease(session); + + return deviceList; + } + +} // namespace Drivelist diff --git a/dependencies/drivelist/src/device-descriptor.cpp b/dependencies/drivelist/src/device-descriptor.cpp new file mode 100644 index 0000000..71d2df9 --- /dev/null +++ b/dependencies/drivelist/src/device-descriptor.cpp @@ -0,0 +1,152 @@ +/* + * Copyright 2017 balena.io + * + * 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 +#include "drivelist.hpp" + +using v8::String; +using v8::Number; +using v8::Boolean; +using v8::Local; +using v8::Value; +using Nan::New; + +namespace Drivelist { + +v8::Local PackDriveDescriptor(const DeviceDescriptor *instance) { + v8::Local object = Nan::New(); + + Nan::Set(object, + New("enumerator").ToLocalChecked(), + New(instance->enumerator).ToLocalChecked()); + + Nan::Set(object, + New("busType").ToLocalChecked(), + New(instance->busType).ToLocalChecked()); + + Local busVersion = instance->busVersionNull ? + (Local)Nan::Null() : + (Local)New(instance->busVersion).ToLocalChecked(); + + Nan::Set(object, + New("busVersion").ToLocalChecked(), + busVersion); + + Nan::Set(object, + New("device").ToLocalChecked(), + New(instance->device).ToLocalChecked()); + + Local devicePath = instance->devicePathNull ? + (Local)Nan::Null() : + (Local)New(instance->devicePath).ToLocalChecked(); + + Nan::Set(object, + New("devicePath").ToLocalChecked(), + devicePath); + + Nan::Set(object, + New("raw").ToLocalChecked(), + New(instance->raw).ToLocalChecked()); + + Nan::Set(object, + New("description").ToLocalChecked(), + New(instance->description).ToLocalChecked()); + + if (instance->error != "") { + Nan::Set(object, + New("error").ToLocalChecked(), + New(instance->error).ToLocalChecked()); + } else { + Nan::Set(object, + New("error").ToLocalChecked(), + Nan::Null()); + } + + Nan::Set(object, + New("size").ToLocalChecked(), + New(static_cast(instance->size))); + + Nan::Set(object, + New("blockSize").ToLocalChecked(), + New(static_cast(instance->blockSize))); + + Nan::Set(object, + New("logicalBlockSize").ToLocalChecked(), + New(static_cast(instance->logicalBlockSize))); + + v8::Local mountpoints = Nan::New(); + + uint32_t index = 0; + for (std::string mountpointPath : instance->mountpoints) { + v8::Local mountpoint = Nan::New(); + Nan::Set(mountpoint, + New("path").ToLocalChecked(), + New(mountpointPath).ToLocalChecked()); + + if (index < instance->mountpointLabels.size()) { + Nan::Set(mountpoint, + New("label").ToLocalChecked(), + New(instance->mountpointLabels[index]).ToLocalChecked()); + } + + Nan::Set(mountpoints, index, mountpoint); + index++; + } + + Nan::Set(object, + New("mountpoints").ToLocalChecked(), + mountpoints); + + Nan::Set(object, + New("isReadOnly").ToLocalChecked(), + New(instance->isReadOnly)); + + Nan::Set(object, + New("isSystem").ToLocalChecked(), + New(instance->isSystem)); + + Nan::Set(object, + New("isVirtual").ToLocalChecked(), + New(instance->isVirtual)); + + Nan::Set(object, + New("isRemovable").ToLocalChecked(), + New(instance->isRemovable)); + + Nan::Set(object, + New("isCard").ToLocalChecked(), + New(instance->isCard)); + + Nan::Set(object, + New("isSCSI").ToLocalChecked(), + New(instance->isSCSI)); + + Nan::Set(object, + New("isUSB").ToLocalChecked(), + New(instance->isUSB)); + + Local isUAS = instance->isUASNull ? + (Local)Nan::Null() : + (Local)New(instance->isUAS); + + Nan::Set(object, + New("isUAS").ToLocalChecked(), + isUAS); + + return object; +} + +} // namespace Drivelist diff --git a/dependencies/drivelist/src/drivelist.cpp b/dependencies/drivelist/src/drivelist.cpp new file mode 100644 index 0000000..5f3be19 --- /dev/null +++ b/dependencies/drivelist/src/drivelist.cpp @@ -0,0 +1,66 @@ +/* + * Copyright 2017 balena.io + * + * 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 +#include +#include "drivelist.hpp" + +class DriveListWorker : public Nan::AsyncWorker { + public: + explicit DriveListWorker(Nan::Callback *callback) + : Nan::AsyncWorker(callback), devices() {} + + ~DriveListWorker() {} + + void Execute() { + devices = Drivelist::ListStorageDevices(); + } + + void HandleOKCallback() { + Nan::HandleScope scope; + v8::Local drives = Nan::New(); + + uint32_t i; + uint32_t size = (uint32_t) devices.size(); + + for (i = 0; i < size; i++) { + Nan::Set(drives, i, Drivelist::PackDriveDescriptor(&devices[i])); + } + + v8::Local argv[] = { Nan::Null(), drives }; + callback->Call(2, argv, async_resource); + } + + private: + std::vector devices; +}; + +NAN_METHOD(list) { + if (!info[0]->IsFunction()) { + return Nan::ThrowTypeError("Callback must be a function"); + } + + Nan::Callback *callback = new Nan::Callback(info[0].As()); + Nan::AsyncQueueWorker(new DriveListWorker(callback)); + + info.GetReturnValue().SetUndefined(); +} + +NAN_MODULE_INIT(InitAll) { + NAN_EXPORT(target, list); +} + +NODE_MODULE(DriveList, InitAll); diff --git a/dependencies/drivelist/src/drivelist.hpp b/dependencies/drivelist/src/drivelist.hpp new file mode 100644 index 0000000..1de452f --- /dev/null +++ b/dependencies/drivelist/src/drivelist.hpp @@ -0,0 +1,64 @@ +/* + * Copyright 2017 balena.io + * + * 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. + */ + +#ifndef SRC_DRIVELIST_HPP_ +#define SRC_DRIVELIST_HPP_ + +#include +#include +#include + +namespace Drivelist { + +struct MountPoint { + std::string path; +}; + +struct DeviceDescriptor { + std::string enumerator; + std::string busType; + std::string busVersion; + bool busVersionNull; + std::string device; + std::string devicePath; + bool devicePathNull; + std::string raw; + std::string description; + std::string error; + uint64_t size; + uint32_t blockSize = 512; + uint32_t logicalBlockSize = 512; + std::vector mountpoints; + std::vector mountpointLabels; + bool isReadOnly; // Device is read-only + bool isSystem; // Device is a system drive + bool isVirtual; // Device is a virtual storage device + bool isRemovable; // Device is removable from the running system + bool isCard; // Device is an SD-card + bool isSCSI; // Connected via the Small Computer System Interface (SCSI) + bool isUSB; // Connected via Universal Serial Bus (USB) + bool isUAS; // Connected via the USB Attached SCSI (UAS) + bool isUASNull; +}; + +std::vector ListStorageDevices(); +v8::Local PackDriveDescriptor(const DeviceDescriptor *instance); + +} // namespace Drivelist + +NAN_METHOD(list); + +#endif // SRC_DRIVELIST_HPP_ diff --git a/dependencies/drivelist/src/linux/list.cpp b/dependencies/drivelist/src/linux/list.cpp new file mode 100644 index 0000000..f4696ea --- /dev/null +++ b/dependencies/drivelist/src/linux/list.cpp @@ -0,0 +1,28 @@ +/* + * Copyright 2017 balena.io + * + * 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 +#include "../drivelist.hpp" + +namespace Drivelist { + + // TODO(jhermsmeier): Implement + std::vector ListStorageDevices() { + std::vector drivelist; + return drivelist; + } + +} // namespace Drivelist diff --git a/dependencies/drivelist/src/windows/list.cpp b/dependencies/drivelist/src/windows/list.cpp new file mode 100644 index 0000000..e39034a --- /dev/null +++ b/dependencies/drivelist/src/windows/list.cpp @@ -0,0 +1,680 @@ +/* + * Copyright 2017 balena.io + * + * 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. + */ + +// See https://support.microsoft.com/en-us/kb/165721 +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#define _WIN32_WINNT 0x0601 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../drivelist.hpp" +#include "list.hpp" + +#include + +// Maxnet edit +#ifndef DEVPKEY_Device_EnumeratorName +DEFINE_DEVPROPKEY(DEVPKEY_Device_EnumeratorName, 0xa45c254e,0xdf1c,0x4efd,0x80,0x20,0x67,0xd1,0x46,0xa8,0x50,0xe0, 24); +#endif +// + +namespace Drivelist { + +char* WCharToUtf8(const wchar_t* wstr) { + char *str = NULL; + size_t size = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL); + + if (size <= 1) { + return NULL; + } + + if ((str = reinterpret_cast(calloc(size, 1))) == NULL) { + return NULL; + } + + size_t utf8Size = WideCharToMultiByte( + CP_UTF8, 0, wstr, -1, str, size, NULL, NULL); + + if (utf8Size != size) { + free(str); + return NULL; + } + + return str; +} + +char* GetEnumeratorName(HDEVINFO hDeviceInfo, SP_DEVINFO_DATA deviceInfoData) { + char buffer[MAX_PATH]; + + ZeroMemory(&buffer, sizeof(buffer)); + + BOOL hasEnumeratorName = SetupDiGetDeviceRegistryPropertyA( + hDeviceInfo, &deviceInfoData, SPDRP_ENUMERATOR_NAME, + NULL, (LPBYTE) buffer, sizeof(buffer), NULL); + + /*if (!hasEnumeratorName) + { + hasEnumeratorName = SetupDiGetDevicePropertyW(hDeviceInfo, &deviceInfoData, &DEVPKEY_Device_EnumeratorName, NULL, (LPBYTE) buffer, sizeof(buffer), NULL, 0); + }*/ + + return hasEnumeratorName ? buffer : NULL; +} + +std::string GetFriendlyName(HDEVINFO hDeviceInfo, + SP_DEVINFO_DATA deviceInfoData) { + wchar_t wbuffer[MAX_PATH]; + + ZeroMemory(&wbuffer, sizeof(wbuffer)); + + BOOL hasFriendlyName = SetupDiGetDeviceRegistryPropertyW( + hDeviceInfo, &deviceInfoData, SPDRP_FRIENDLYNAME, + NULL, (PBYTE) wbuffer, sizeof(wbuffer), NULL); + + return hasFriendlyName ? WCharToUtf8(wbuffer) : std::string(""); +} + +bool IsSCSIDevice(std::string enumeratorName) { + for (std::string driverName : GENERIC_STORAGE_DRIVERS) { + if (enumeratorName == driverName) { + return true; + } + } + + return false; +} + +bool IsUSBDevice(std::string enumeratorName) { + for (std::string driverName : USB_STORAGE_DRIVERS) { + if (enumeratorName == driverName) { + return true; + } + } + + return false; +} + +bool IsRemovableDevice(HDEVINFO hDeviceInfo, SP_DEVINFO_DATA deviceInfoData) { + DWORD result = 0; + + BOOL hasRemovalPolicy = SetupDiGetDeviceRegistryProperty( + hDeviceInfo, &deviceInfoData, SPDRP_REMOVAL_POLICY, + NULL, (PBYTE) &result, sizeof(result), NULL); + + switch (result) { + case CM_REMOVAL_POLICY_EXPECT_SURPRISE_REMOVAL: + case CM_REMOVAL_POLICY_EXPECT_ORDERLY_REMOVAL: + return true; + default: + return false; + } + + return false; +} + +bool IsVirtualHardDrive(HDEVINFO hDeviceInfo, SP_DEVINFO_DATA deviceInfoData) { + char buffer[MAX_PATH]; + + ZeroMemory(&buffer, sizeof(buffer)); + + BOOL hasHardwareId = SetupDiGetDeviceRegistryPropertyA( + hDeviceInfo, &deviceInfoData, SPDRP_HARDWAREID, + NULL, (LPBYTE) buffer, sizeof(buffer), NULL); + + if (!hasHardwareId) { + return false; + } + + // printf("SPDRP_HARDWAREID: %s\n", buffer); + + std::string hardwareId(buffer); + + for (std::string vhdHardwareId : VHD_HARDWARE_IDS) { + if (hardwareId.find(vhdHardwareId, 0) != std::string::npos) { + return true; + } + } + + return false; +} + +bool IsSystemDevice(HDEVINFO hDeviceInfo, DeviceDescriptor *device) { + PWSTR folderPath = NULL; + BOOL isSystem = false; + + for (const GUID folderId : KNOWN_FOLDER_IDS) { + HRESULT result = SHGetKnownFolderPath( + folderId, 0, NULL, &folderPath); + + if (result == S_OK) { + std::string systemPath = WCharToUtf8(folderPath); + // printf("systemPath %s\n", systemPath.c_str()); + for (std::string mountpoint : device->mountpoints) { + // printf("%s find %s\n", systemPath.c_str(), mountpoint.c_str()); + if (systemPath.find(mountpoint, 0) != std::string::npos) { + isSystem = true; + break; + } + } + } + + CoTaskMemFree(folderPath); + } + + return isSystem; +} + +std::vector GetAvailableVolumes() { + DWORD logicalDrivesMask = GetLogicalDrives(); + std::vector logicalDrives; + + if (logicalDrivesMask == 0) { + return logicalDrives; + } + + char currentDriveLetter = 'A'; + + while (logicalDrivesMask) { + if (logicalDrivesMask & 1) { + logicalDrives.push_back(std::string(1, currentDriveLetter)); + } + currentDriveLetter++; + logicalDrivesMask >>= 1; + } + + return logicalDrives; +} + +int32_t GetDeviceNumber(HANDLE hDevice) { + BOOL result; + DWORD size; + DWORD errorCode = 0; + int32_t diskNumber = -1; + + STORAGE_DEVICE_NUMBER deviceNumber; + VOLUME_DISK_EXTENTS diskExtents; + + // Some devices will have the diskNumber exposed through their disk extents, + // while most of them will only have one accessible through + // `IOCTL_STORAGE_GET_DEVICE_NUMBER`, so we check this one first, + // augmenting / overriding it with the latter + result = DeviceIoControl( + hDevice, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, + &diskExtents, sizeof(VOLUME_DISK_EXTENTS), &size, NULL); + + if (result && diskExtents.NumberOfDiskExtents > 0) { + // printf("[INFO] DiskNumber: %i\n", diskExtents.Extents[0].DiskNumber); + + // NOTE: Always ignore RAIDs + // TODO(jhermsmeier): Handle RAIDs properly + if (diskExtents.NumberOfDiskExtents >= 2) { + // printf("[INFO] Possible RAID: %i\n", + // diskExtents.Extents[0].DiskNumber); + return -1; + } + diskNumber = diskExtents.Extents[0].DiskNumber; + } else { + errorCode = GetLastError(); + // printf("[INFO] VOLUME_GET_VOLUME_DISK_EXTENTS: Error 0x%08lX\n", + // errorCode); + } + + result = DeviceIoControl( + hDevice, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, + &deviceNumber, sizeof(deviceNumber), &size, NULL); + + if (result) { + // printf("[INFO] DeviceNumber: %i\n", deviceNumber.DeviceNumber); + diskNumber = deviceNumber.DeviceNumber; + } + + // errorCode = GetLastError(); + // printf("[INFO] STORAGE_GET_DEVICE_NUMBER: Error 0x%08lX\n", errorCode); + + return diskNumber; +} + +void GetMountpoints(int32_t deviceNumber, + std::vector *mountpoints) { + HANDLE hLogical = INVALID_HANDLE_VALUE; + int32_t logicalVolumeDeviceNumber = -1; + UINT driveType; + + std::vector logicalVolumes = GetAvailableVolumes(); + + for (std::string volumeName : logicalVolumes) { + if (hLogical != INVALID_HANDLE_VALUE) { + CloseHandle(hLogical); + hLogical = INVALID_HANDLE_VALUE; + } + + // NOTE: Ignore everything that's not a fixed or removable drive, + // as device numbers are not unique across storage type drivers (!?), + // and this would otherwise cause CD/DVD drive letters to be + // attributed to blockdevices + driveType = GetDriveTypeA((volumeName + ":\\").c_str()); + + // printf("[INFO] Checking %s:/\n", volumeName.c_str()); + + if ((driveType != DRIVE_FIXED) && (driveType != DRIVE_REMOVABLE)) { + // printf("[INFO] Ignoring volume %s:/ - Not FIXED | REMOVABLE\n", + // volumeName.c_str()); + continue; + } + + hLogical = CreateFileA( + ("\\\\.\\" + volumeName + ":").c_str(), 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if (hLogical == INVALID_HANDLE_VALUE) { + // printf("[INFO] Couldn't open handle to logical volume %s\n", + // volumeName.c_str()); + continue; + } + + logicalVolumeDeviceNumber = GetDeviceNumber(hLogical); + + if (logicalVolumeDeviceNumber == -1) { + // printf("[INFO] Couldn't get device number for logical volume %s\n", + // volumeName.c_str()); + continue; + } + + if (logicalVolumeDeviceNumber == deviceNumber) { + // printf("[INFO] Device number for logical volume %s is %i\n", + // volumeName.c_str(), logicalVolumeDeviceNumber); + mountpoints->push_back(volumeName + ":\\"); + } + } + + if (hLogical != INVALID_HANDLE_VALUE) { + CloseHandle(hLogical); + hLogical = INVALID_HANDLE_VALUE; + } +} + +std::string GetBusType(STORAGE_ADAPTER_DESCRIPTOR *adapterDescriptor) { + switch (adapterDescriptor->BusType) { + case STORAGE_BUS_TYPE::BusTypeUnknown: return "UNKNOWN"; + case STORAGE_BUS_TYPE::BusTypeScsi: return "SCSI"; + case STORAGE_BUS_TYPE::BusTypeAtapi: return "ATAPI"; + case STORAGE_BUS_TYPE::BusTypeAta: return "ATA"; + case STORAGE_BUS_TYPE::BusType1394: return "1394"; // IEEE 1394 + case STORAGE_BUS_TYPE::BusTypeSsa: return "SSA"; + case STORAGE_BUS_TYPE::BusTypeFibre: return "FIBRE"; + case STORAGE_BUS_TYPE::BusTypeUsb: return "USB"; + case STORAGE_BUS_TYPE::BusTypeRAID: return "RAID"; + case STORAGE_BUS_TYPE::BusTypeiScsi: return "iSCSI"; + case STORAGE_BUS_TYPE::BusTypeSas: return "SAS"; // Serial-Attached SCSI + case STORAGE_BUS_TYPE::BusTypeSata: return "SATA"; + case STORAGE_BUS_TYPE::BusTypeSd: return "SD"; // Secure Digital (SD) + case STORAGE_BUS_TYPE::BusTypeMmc: return "MMC"; // Multimedia card + case STORAGE_BUS_TYPE::BusTypeVirtual: return "VIRTUAL"; + case STORAGE_BUS_TYPE::BusTypeFileBackedVirtual: return "FILEBACKEDVIRTUAL"; + default: return "INVALID"; + } +} + +bool GetAdapterInfo(HANDLE hPhysical, DeviceDescriptor *device) { + STORAGE_PROPERTY_QUERY query; + STORAGE_ADAPTER_DESCRIPTOR adapterDescriptor; + DWORD size = 0; + + ZeroMemory(&query, sizeof(query)); + + query.QueryType = STORAGE_QUERY_TYPE::PropertyStandardQuery; + query.PropertyId = STORAGE_PROPERTY_ID::StorageAdapterProperty; + + BOOL hasAdapterInfo = DeviceIoControl( + hPhysical, IOCTL_STORAGE_QUERY_PROPERTY, + &query, sizeof(STORAGE_PROPERTY_QUERY), + &adapterDescriptor, sizeof(STORAGE_ADAPTER_DESCRIPTOR), &size, NULL); + + if (hasAdapterInfo) { + device->busType = GetBusType(&adapterDescriptor); + device->busVersion = std::to_string(adapterDescriptor.BusMajorVersion) + + "." + std::to_string(adapterDescriptor.BusMinorVersion); + return true; + } + + return false; +} + +bool GetDeviceBlockSize(HANDLE hPhysical, DeviceDescriptor *device) { + STORAGE_PROPERTY_QUERY query; + STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR alignmentDescriptor; + DWORD size = 0; + + ZeroMemory(&query, sizeof(query)); + + query.QueryType = STORAGE_QUERY_TYPE::PropertyStandardQuery; + query.PropertyId = STORAGE_PROPERTY_ID::StorageAccessAlignmentProperty; + + BOOL hasAlignmentDescriptor = DeviceIoControl( + hPhysical, IOCTL_STORAGE_QUERY_PROPERTY, + &query, sizeof(STORAGE_PROPERTY_QUERY), + &alignmentDescriptor, sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR), + &size, NULL); + + if (hasAlignmentDescriptor) { + device->blockSize = alignmentDescriptor.BytesPerPhysicalSector; + device->logicalBlockSize = alignmentDescriptor.BytesPerLogicalSector; + return true; + } + + return false; +} + +bool GetDeviceSize(HANDLE hPhysical, DeviceDescriptor *device) { + DISK_GEOMETRY_EX diskGeometry; + + // printf("[INFO] hasDiskGeometry\n"); + + BOOL hasDiskGeometry = false; + DWORD size = 0; + + hasDiskGeometry = DeviceIoControl( + hPhysical, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, + &diskGeometry, sizeof(DISK_GEOMETRY_EX), &size, NULL); + + // printf("[INFO] hasDiskGeometry %i\n", hasDiskGeometry); + + // NOTE: Another way to get the block size would be + // `IOCTL_STORAGE_QUERY_PROPERTY` with `STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR`, + // which can yield more (or possibly more accurate?) info, + // but might not work with external HDDs/SSDs + if (hasDiskGeometry) { + device->size = diskGeometry.DiskSize.QuadPart; + device->blockSize = diskGeometry.Geometry.BytesPerSector; + } + + return hasDiskGeometry; +} + +bool GetDetailData(DeviceDescriptor* device, + HDEVINFO hDeviceInfo, SP_DEVINFO_DATA deviceInfoData) { + DWORD index; + DWORD size; + DWORD errorCode = 0; + bool result = true; + + HANDLE hDevice = INVALID_HANDLE_VALUE; + HANDLE hPhysical = INVALID_HANDLE_VALUE; + SP_DEVICE_INTERFACE_DATA deviceInterfaceData; + PSP_DEVICE_INTERFACE_DETAIL_DATA_W deviceDetailData(NULL); + + for (index = 0; ; index++) { + if (hDevice != INVALID_HANDLE_VALUE) { + CloseHandle(hDevice); + hDevice = INVALID_HANDLE_VALUE; + } + + if (hPhysical != INVALID_HANDLE_VALUE) { + CloseHandle(hPhysical); + hPhysical = INVALID_HANDLE_VALUE; + } + + deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); + + // printf("[INFO] (%i) SetupDiEnumDeviceInterfaces - isDisk\n", index); + + BOOL isDisk = SetupDiEnumDeviceInterfaces( + hDeviceInfo, &deviceInfoData, &GUID_DEVICE_INTERFACE_DISK, + index, &deviceInterfaceData); + + if (!isDisk) { + errorCode = GetLastError(); + if (errorCode == ERROR_NO_MORE_ITEMS) { + // printf("[INFO] (%i) EnumDeviceInterfaces: No more items 0x%08lX\n", + // index, errorCode); + result = index != 0; + break; + } else { + device->error = "SetupDiEnumDeviceInterfaces: Error " + + std::to_string(errorCode); + } + result = false; + break; + } + + BOOL hasDeviceInterfaceData = SetupDiGetDeviceInterfaceDetailW( + hDeviceInfo, &deviceInterfaceData, NULL, 0, &size, NULL); + + if (!hasDeviceInterfaceData) { + errorCode = GetLastError(); + if (errorCode == ERROR_INSUFFICIENT_BUFFER) { + deviceDetailData = static_cast + (malloc(size)); + if (deviceDetailData == NULL) { + device->error = "SetupDiGetDeviceInterfaceDetailW: " + "Unable to allocate SP_DEVICE_INTERFACE_DETAIL_DATA_W" + "(" + std::to_string(size) + "); " + "Error " + std::to_string(errorCode); + result = false; + break; + } + // printf("Allocated SP_DEVICE_INTERFACE_DETAIL_DATA_W\n"); + } else { + device->error = "SetupDiGetDeviceInterfaceDetailW: " + "Couldn't get detail data; Error " + std::to_string(errorCode); + result = false; + break; + } + } + + // printf("[INFO] (%i) Getting SP_DEVICE_INTERFACE_DETAIL_DATA_W\n", index); + + deviceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W); + + BOOL hasDeviceDetail = SetupDiGetDeviceInterfaceDetailW( + hDeviceInfo, &deviceInterfaceData, deviceDetailData, size, &size, NULL); + + if (!hasDeviceDetail) { + errorCode = GetLastError(); + device->error = "Couldn't SetupDiGetDeviceInterfaceDetailW: Error " + + std::to_string(errorCode); + result = false; + break; + } + + // printf("[INFO] (%i) SetupDiGetDeviceInterfaceDetailW:\n %s\n", + // index, WCharToUtf8(deviceDetailData->DevicePath)); + + // Passing zero to `CreateFile()` doesn't require permissions to + // open the device handle, but only lets you acquire device metadata, + // which is all we want + hDevice = CreateFileW( + deviceDetailData->DevicePath, 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if (hDevice == INVALID_HANDLE_VALUE) { + errorCode = GetLastError(); + // printf("[ERROR] Couldn't open handle to device: Error %i", errorCode); + device->error = "Couldn't open handle to device: Error " + + std::to_string(errorCode); + result = false; + break; + } + + int32_t deviceNumber = GetDeviceNumber(hDevice); + + if (deviceNumber == -1) { + device->error = "Couldn't get device number"; + result = false; + break; + } + + device->raw = "\\\\.\\PhysicalDrive" + std::to_string(deviceNumber); + device->device = device->raw; + + GetMountpoints(deviceNumber, &device->mountpoints); + + // printf("[INFO] Opening handle to %s\n", device->raw.c_str()); + + hPhysical = CreateFileA( + device->raw.c_str(), 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + // printf("[INFO] Opened handle to %s\n", device->raw.c_str()); + // printf("[INFO] Handle %i (INVALID %i)\n", + // hPhysical, INVALID_HANDLE_VALUE); + + if (hPhysical == INVALID_HANDLE_VALUE) { + errorCode = GetLastError(); + // printf("[INFO] Couldn't open handle to %s: Error %i\n", + // device->raw.c_str(), errorCode); + device->error = "Couldn't open handle to physical device: Error " + + std::to_string(errorCode); + result = false; + break; + } + + // printf("[INFO] GetDeviceSize( %s )\n", device->raw.c_str()); + + if (!GetDeviceSize(hPhysical, device)) { + errorCode = GetLastError(); + // printf("[ERROR] Couldn't get disk geometry: Error %i\n", errorCode); + device->error = "Couldn't get disk geometry: Error " + + std::to_string(errorCode); + result = false; + break; + } + + // printf("[INFO] GetAdapterInfo( %s )\n", device->raw.c_str()); + + if (!GetAdapterInfo(hPhysical, device)) { + errorCode = GetLastError(); + // printf("[ERROR] Couldn't get device adapter descriptor: Error %i\n", + // errorCode); + device->error = "Couldn't get device adapter descriptor: Error " + + std::to_string(errorCode); + result = false; + break; + } + + // printf("[INFO] GetDeviceBlockSize( %s )\n", device->raw.c_str()); + + // NOTE: No need to fail over this one, + // as we can safely default to a 512B block size + if (!GetDeviceBlockSize(hPhysical, device)) { + errorCode = GetLastError(); + // printf("[INFO] Couldn't get block size: Error %u\n", errorCode); + } + + // printf("[INFO] isWritable( %s )\n", device->raw.c_str()); + + BOOL isWritable = DeviceIoControl( + hPhysical, IOCTL_DISK_IS_WRITABLE, NULL, 0, + NULL, 0, &size, NULL); + + device->isReadOnly = !isWritable; + } // end for (index = 0; ; index++) + + if (hDevice != INVALID_HANDLE_VALUE) { + CloseHandle(hDevice); + hDevice = INVALID_HANDLE_VALUE; + } + + if (hPhysical != INVALID_HANDLE_VALUE) { + CloseHandle(hPhysical); + hPhysical = INVALID_HANDLE_VALUE; + } + + free(deviceDetailData); + + return result; +} + +std::vector ListStorageDevices() { + HDEVINFO hDeviceInfo = NULL; + SP_DEVINFO_DATA deviceInfoData; + std::vector deviceList; + + DWORD i; + char *enumeratorName; + DeviceDescriptor device; + + hDeviceInfo = SetupDiGetClassDevsA( + &GUID_DEVICE_INTERFACE_DISK, NULL, NULL, + DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + + if (hDeviceInfo == INVALID_HANDLE_VALUE) { + printf("[ERROR] Invalid DeviceInfo handle\n"); + return deviceList; + } + + deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); + + for (i = 0; SetupDiEnumDeviceInfo(hDeviceInfo, i, &deviceInfoData); i++) { + enumeratorName = GetEnumeratorName(hDeviceInfo, deviceInfoData); + + printf("[INFO] Enumerating %s\n", enumeratorName); + + // If it failed to get the SPDRP_ENUMERATOR_NAME, skip it + //if (enumeratorName == NULL) { + // continue; + //} + + device = DeviceDescriptor(); + + device.enumerator = enumeratorName ? std::string(enumeratorName) : ""; + device.description = GetFriendlyName(hDeviceInfo, deviceInfoData); + device.isRemovable = IsRemovableDevice(hDeviceInfo, deviceInfoData); + device.isVirtual = IsVirtualHardDrive(hDeviceInfo, deviceInfoData); + device.isSCSI = enumeratorName ? IsSCSIDevice(enumeratorName) : false; + device.isUSB = enumeratorName ? IsUSBDevice(enumeratorName) : false; + device.isCard = device.enumerator == "SD"; + device.isSystem = !device.isRemovable && + (device.enumerator == "SCSI" || device.enumerator == "IDE"); + device.isUAS = device.isSCSI && device.isRemovable && + !device.isVirtual && !device.isCard; + device.devicePathNull = true; + + if (GetDetailData(&device, hDeviceInfo, deviceInfoData)) { + device.isSystem = device.isSystem || IsSystemDevice(hDeviceInfo, &device); + device.isCard = device.busType == "SD" || device.busType == "MMC"; + device.isUAS = device.enumerator == "SCSI" && device.busType == "USB"; + device.isVirtual = device.isVirtual || + device.busType == "VIRTUAL" || + device.busType == "FILEBACKEDVIRTUAL"; + } else if (device.error == "") { + device.error = "Couldn't get detail data"; + } + + deviceList.push_back(device); + } + + SetupDiDestroyDeviceInfoList(hDeviceInfo); + + return deviceList; +} + +} // namespace Drivelist diff --git a/dependencies/drivelist/src/windows/list.hpp b/dependencies/drivelist/src/windows/list.hpp new file mode 100644 index 0000000..0a39978 --- /dev/null +++ b/dependencies/drivelist/src/windows/list.hpp @@ -0,0 +1,108 @@ +/* + * Copyright 2017 balena.io + * + * 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. + */ + +#ifndef SRC_WINDOWS_LIST_HPP_ +#define SRC_WINDOWS_LIST_HPP_ + +#include +#include +#include + +namespace Drivelist { + +// The , and headers include the following +// device interface GUIDs we're interested in; +// @see https://docs.microsoft.com/en-us/windows-hardware/drivers/install/install-reference +// @see https://msdn.microsoft.com/en-us/library/windows/hardware/ff541389(v=vs.85).aspx +// To avoid cluttering the global namespace, +// we'll just define here what we need: +// +// - GUID_DEVINTERFACE_DISK { 53F56307-B6BF-11D0-94F2-00A0C91EFB8B } +// - GUID_DEVINTERFACE_CDROM { 53F56308-B6BF-11D0-94F2-00A0C91EFB8B } +// - GUID_DEVINTERFACE_USB_HUB { F18A0E88-C30C-11D0-8815-00A0C906BED8 } +// - GUID_DEVINTERFACE_FLOPPY { 53F56311-B6BF-11D0-94F2-00A0C91EFB8B } +// - GUID_DEVINTERFACE_WRITEONCEDISK { 53F5630C-B6BF-11D0-94F2-00A0C91EFB8B } +// - GUID_DEVINTERFACE_TAPE { 53F5630B-B6BF-11D0-94F2-00A0C91EFB8B } +// - GUID_DEVINTERFACE_USB_DEVICE { A5DCBF10-6530-11D2-901F-00C04FB951ED } +// - GUID_DEVINTERFACE_VOLUME { 53F5630D-B6BF-11D0-94F2-00A0C91EFB8B } +// - GUID_DEVINTERFACE_STORAGEPORT { 2ACCFE60-C130-11D2-B082-00A0C91EFB8B } +// +const GUID GUID_DEVICE_INTERFACE_DISK = { +0x53F56307L, 0xB6BF, 0x11D0, { 0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B } +}; + +const GUID GUID_DEVICE_INTERFACE_CDROM = { +0x53F56308L, 0xB6BF, 0x11D0, { 0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B } +}; + +const GUID GUID_DEVICE_INTERFACE_USB_HUB = { +0xF18A0E88L, 0xC30C, 0x11D0, { 0x88, 0x15, 0x00, 0xA0, 0xC9, 0x06, 0xBE, 0xD8 } +}; + +const GUID GUID_DEVICE_INTERFACE_FLOPPY = { +0x53F56311L, 0xB6BF, 0x11D0, { 0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B } +}; + +const GUID GUID_DEVICE_INTERFACE_WRITEONCEDISK = { +0x53F5630CL, 0xB6BF, 0x11D0, { 0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B } +}; + +const GUID GUID_DEVICE_INTERFACE_TAPE = { +0x53F5630BL, 0xB6BF, 0x11D0, { 0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B } +}; + +const GUID GUID_DEVICE_INTERFACE_USB_DEVICE = { +0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } +}; + +const GUID GUID_DEVICE_INTERFACE_VOLUME = { +0x53F5630DL, 0xB6BF, 0x11D0, { 0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B } +}; + +const GUID GUID_DEVICE_INTERFACE_STORAGEPORT = { +0x2ACCFE60L, 0xC130, 0x11D2, { 0xB0, 0x82, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B } +}; + +const std::set USB_STORAGE_DRIVERS { + "USBSTOR", "UASPSTOR", "VUSBSTOR", + "RTUSER", "CMIUCR", "EUCR", + "ETRONSTOR", "ASUSSTPT" +}; + +const std::set GENERIC_STORAGE_DRIVERS { + "SCSI", "SD", "PCISTOR", + "RTSOR", "JMCR", "JMCF", "RIMMPTSK", "RIMSPTSK", "RIXDPTSK", + "TI21SONY", "ESD7SK", "ESM7SK", "O2MD", "O2SD", "VIACR" +}; + +// List of known virtual disk hardware IDs +const std::set VHD_HARDWARE_IDS { + "Arsenal_________Virtual_", + "KernSafeVirtual_________", + "Msft____Virtual_Disk____", + "VMware__VMware_Virtual_S" +}; + +const GUID KNOWN_FOLDER_IDS[] { + FOLDERID_Windows, + FOLDERID_Profile, + FOLDERID_ProgramFiles, + FOLDERID_ProgramFilesX86 +}; + +} // namespace Drivelist + +#endif // SRC_WINDOWS_LIST_HPP_ diff --git a/dependencies/drivelist/tests/data/lsblk/no-children-mountpoints.json b/dependencies/drivelist/tests/data/lsblk/no-children-mountpoints.json new file mode 100644 index 0000000..ab67ac7 --- /dev/null +++ b/dependencies/drivelist/tests/data/lsblk/no-children-mountpoints.json @@ -0,0 +1,44 @@ +{ + "blockdevices": [{ + "name": "sda", + "maj:min": "8:0", + "rm": "1", + "size": "14.3G", + "ro": "0", + "type": "disk", + "mountpoint": "/media/jwentz/Temp" + }, { + "name": "nvme0n1", + "maj:min": "259:0", + "rm": "0", + "size": "477G", + "ro": "0", + "type": "disk", + "mountpoint": null, + "children": [{ + "name": "nvme0n1p3", + "maj:min": "259:3", + "rm": "0", + "size": "15.8G", + "ro": "0", + "type": "part", + "mountpoint": "[SWAP]" + }, { + "name": "nvme0n1p1", + "maj:min": "259:1", + "rm": "0", + "size": "512M", + "ro": "0", + "type": "part", + "mountpoint": "/boot/efi" + }, { + "name": "nvme0n1p2", + "maj:min": "259:2", + "rm": "0", + "size": "460.7G", + "ro": "0", + "type": "part", + "mountpoint": "/" + }] + }] +} diff --git a/dependencies/drivelist/tests/data/lsblk/no-partition-table.txt b/dependencies/drivelist/tests/data/lsblk/no-partition-table.txt new file mode 100644 index 0000000..282ab4b --- /dev/null +++ b/dependencies/drivelist/tests/data/lsblk/no-partition-table.txt @@ -0,0 +1,9 @@ +NAME="sda" MAJ:MIN="8:0" RM="0" SIZE="240065183744" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="sda1" MAJ:MIN="8:1" RM="0" SIZE="209715200" RO="0" TYPE="part" MOUNTPOINT="/boot/efi" +NAME="sda2" MAJ:MIN="8:2" RM="0" SIZE="1073741824" RO="0" TYPE="part" MOUNTPOINT="/boot" +NAME="sda3" MAJ:MIN="8:3" RM="0" SIZE="115835142144" RO="0" TYPE="part" MOUNTPOINT="" +NAME="centos-root" MAJ:MIN="253:0" RM="0" SIZE="53687091200" RO="0" TYPE="lvm" MOUNTPOINT="/" +NAME="centos-swap" MAJ:MIN="253:1" RM="0" SIZE="8455716864" RO="0" TYPE="lvm" MOUNTPOINT="[SWAP]" +NAME="centos-home" MAJ:MIN="253:2" RM="0" SIZE="53687091200" RO="0" TYPE="lvm" MOUNTPOINT="/home" +NAME="sdb" MAJ:MIN="8:16" RM="1" SIZE="" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="sdc" MAJ:MIN="8:32" RM="1" SIZE="31457280000" RO="0" TYPE="disk" MOUNTPOINT="/run/media/DA2E4172/BUILD" diff --git a/dependencies/drivelist/tests/data/lsblk/ubuntu-14.04-1.txt b/dependencies/drivelist/tests/data/lsblk/ubuntu-14.04-1.txt new file mode 100644 index 0000000..33b6f49 --- /dev/null +++ b/dependencies/drivelist/tests/data/lsblk/ubuntu-14.04-1.txt @@ -0,0 +1,32 @@ +NAME="sda" MAJ:MIN="8:0" RM="0" SIZE="1024209543168" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="sda1" MAJ:MIN="8:1" RM="0" SIZE="524288000" RO="0" TYPE="part" MOUNTPOINT="/boot/efi" +NAME="sda2" MAJ:MIN="8:2" RM="0" SIZE="41943040" RO="0" TYPE="part" MOUNTPOINT="" +NAME="sda3" MAJ:MIN="8:3" RM="0" SIZE="3221225472" RO="0" TYPE="part" MOUNTPOINT="" +NAME="sda4" MAJ:MIN="8:4" RM="0" SIZE="235291017216" RO="0" TYPE="part" MOUNTPOINT="/" +NAME="sda5" MAJ:MIN="8:5" RM="0" SIZE="16980639744" RO="0" TYPE="part" MOUNTPOINT="[SWAP]" +NAME="sda6" MAJ:MIN="8:6" RM="0" SIZE="549755813888" RO="0" TYPE="part" MOUNTPOINT="/home" +NAME="sda7" MAJ:MIN="8:7" RM="0" SIZE="218392166400" RO="0" TYPE="part" MOUNTPOINT="" +NAME="ram0" MAJ:MIN="1:0" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram1" MAJ:MIN="1:1" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram2" MAJ:MIN="1:2" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram3" MAJ:MIN="1:3" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram4" MAJ:MIN="1:4" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram5" MAJ:MIN="1:5" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram6" MAJ:MIN="1:6" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram7" MAJ:MIN="1:7" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram8" MAJ:MIN="1:8" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram9" MAJ:MIN="1:9" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="loop0" MAJ:MIN="7:0" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT="" +NAME="loop1" MAJ:MIN="7:1" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT="" +NAME="loop2" MAJ:MIN="7:2" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT="" +NAME="loop3" MAJ:MIN="7:3" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT="" +NAME="loop4" MAJ:MIN="7:4" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT="" +NAME="loop5" MAJ:MIN="7:5" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT="" +NAME="loop6" MAJ:MIN="7:6" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT="" +NAME="loop7" MAJ:MIN="7:7" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT="" +NAME="ram10" MAJ:MIN="1:10" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram11" MAJ:MIN="1:11" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram12" MAJ:MIN="1:12" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram13" MAJ:MIN="1:13" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram14" MAJ:MIN="1:14" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram15" MAJ:MIN="1:15" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT="" diff --git a/dependencies/drivelist/tests/data/lsblk/ubuntu-14.04-2.txt b/dependencies/drivelist/tests/data/lsblk/ubuntu-14.04-2.txt new file mode 100644 index 0000000..8e4071a --- /dev/null +++ b/dependencies/drivelist/tests/data/lsblk/ubuntu-14.04-2.txt @@ -0,0 +1,30 @@ +NAME="fd0" MAJ:MIN="2:0" RM="1" SIZE="" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="sda" MAJ:MIN="8:0" RM="0" SIZE="32G" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="sda1" MAJ:MIN="8:1" RM="0" SIZE="30G" RO="0" TYPE="part" MOUNTPOINT="/" +NAME="sda2" MAJ:MIN="8:2" RM="0" SIZE="1K" RO="0" TYPE="part" MOUNTPOINT="" +NAME="sda5" MAJ:MIN="8:5" RM="0" SIZE="2G" RO="0" TYPE="part" MOUNTPOINT="[SWAP]" +NAME="sr0" MAJ:MIN="11:0" RM="1" SIZE="1024M" RO="0" TYPE="rom" MOUNTPOINT="" +NAME="ram0" MAJ:MIN="1:0" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram1" MAJ:MIN="1:1" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram2" MAJ:MIN="1:2" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram3" MAJ:MIN="1:3" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram4" MAJ:MIN="1:4" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram5" MAJ:MIN="1:5" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram6" MAJ:MIN="1:6" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram7" MAJ:MIN="1:7" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram8" MAJ:MIN="1:8" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram9" MAJ:MIN="1:9" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="loop0" MAJ:MIN="7:0" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT="" +NAME="loop1" MAJ:MIN="7:1" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT="" +NAME="loop2" MAJ:MIN="7:2" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT="" +NAME="loop3" MAJ:MIN="7:3" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT="" +NAME="loop4" MAJ:MIN="7:4" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT="" +NAME="loop5" MAJ:MIN="7:5" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT="" +NAME="loop6" MAJ:MIN="7:6" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT="" +NAME="loop7" MAJ:MIN="7:7" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT="" +NAME="ram10" MAJ:MIN="1:10" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram11" MAJ:MIN="1:11" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram12" MAJ:MIN="1:12" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram13" MAJ:MIN="1:13" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram14" MAJ:MIN="1:14" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="ram15" MAJ:MIN="1:15" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT="" diff --git a/dependencies/drivelist/tests/data/lsblk/ubuntu-14.04-3.txt b/dependencies/drivelist/tests/data/lsblk/ubuntu-14.04-3.txt new file mode 100644 index 0000000..72714a3 --- /dev/null +++ b/dependencies/drivelist/tests/data/lsblk/ubuntu-14.04-3.txt @@ -0,0 +1,23 @@ +NAME="sda" MAJ:MIN="8:0" RM="0" SIZE="931.5G" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="sda1" MAJ:MIN="8:1" RM="0" SIZE="1K" RO="0" TYPE="part" MOUNTPOINT="" +NAME="sda2" MAJ:MIN="8:2" RM="0" SIZE="488.3G" RO="0" TYPE="part" MOUNTPOINT="" +NAME="sda5" MAJ:MIN="8:5" RM="0" SIZE="14.9G" RO="0" TYPE="part" MOUNTPOINT="" +NAME="sda6" MAJ:MIN="8:6" RM="0" SIZE="335.2G" RO="0" TYPE="part" MOUNTPOINT="" +NAME="sdb" MAJ:MIN="8:16" RM="1" SIZE="" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="sdc" MAJ:MIN="8:32" RM="1" SIZE="" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="sdd" MAJ:MIN="8:48" RM="1" SIZE="7.4G" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="sdd1" MAJ:MIN="8:49" RM="1" SIZE="7.4G" RO="0" TYPE="part" MOUNTPOINT="/media//85CA-6700" +NAME="sr0" MAJ:MIN="11:0" RM="1" SIZE="1024M" RO="0" TYPE="rom" MOUNTPOINT="" +NAME="loop0" MAJ:MIN="7:0" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT="" +NAME="loop1" MAJ:MIN="7:1" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT="" +NAME="loop2" MAJ:MIN="7:2" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT="" +NAME="loop3" MAJ:MIN="7:3" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT="" +NAME="loop4" MAJ:MIN="7:4" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT="" +NAME="loop5" MAJ:MIN="7:5" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT="" +NAME="loop6" MAJ:MIN="7:6" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT="" +NAME="loop7" MAJ:MIN="7:7" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT="" +NAME="nvme0n1" MAJ:MIN="259:0" RM="0" SIZE="238.5G" RO="0" TYPE="disk" MOUNTPOINT="" +NAME="nvme0n1p1" MAJ:MIN="259:1" RM="0" SIZE="499M" RO="0" TYPE="part" MOUNTPOINT="" +NAME="nvme0n1p2" MAJ:MIN="259:2" RM="0" SIZE="116.6G" RO="0" TYPE="part" MOUNTPOINT="" +NAME="nvme0n1p3" MAJ:MIN="259:3" RM="0" SIZE="4.9G" RO="0" TYPE="part" MOUNTPOINT="" +NAME="nvme0n1p4" MAJ:MIN="259:4" RM="0" SIZE="116.5G" RO="0" TYPE="part" MOUNTPOINT="/" diff --git a/dependencies/drivelist/tests/drivelist.spec.ts b/dependencies/drivelist/tests/drivelist.spec.ts new file mode 100644 index 0000000..8b3b354 --- /dev/null +++ b/dependencies/drivelist/tests/drivelist.spec.ts @@ -0,0 +1,114 @@ +/* + * Copyright 2016 Balena.io + * + * 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. + */ + +import { ok } from 'assert'; +import { expect } from 'chai'; +import * as os from 'os'; +import { stub } from 'sinon'; + +import { list } from '../lib'; + +describe('Drivelist', () => { + describe('.list()', () => { + it('should yield results', async () => { + const devices = await list(); + devices.forEach(device => { + ok(device.enumerator, `Invalid enumerator: ${device.enumerator}`); + ok(device.busType, `Invalid busType: ${device.busType}`); + ok(device.device, `Invalid device: ${device.device}`); + ok(device.raw, `Invalid raw: ${device.raw}`); + ok(device.description, `Invalid description: ${device.description}`); + ok(device.error === null, `Invalid error: ${device.error}`); + ok( + device.size === null || Number.isFinite(device.size), + `Invalid size: ${device.size}`, + ); + ok( + Number.isFinite(device.blockSize), + `Invalid blockSize: ${device.blockSize}`, + ); + ok( + Number.isFinite(device.logicalBlockSize), + `Invalid logicalBlockSize: ${device.logicalBlockSize}`, + ); + ok( + Array.isArray(device.mountpoints), + `Invalid mountpoints: ${device.mountpoints}`, + ); + ok( + device.isReadOnly === null || typeof device.isReadOnly === 'boolean', + `Invalid isReadOnly flag: ${device.isReadOnly}`, + ); + ok( + device.isSystem === null || typeof device.isSystem === 'boolean', + `Invalid isSystem flag: ${device.isSystem}`, + ); + ok( + device.isVirtual === null || typeof device.isVirtual === 'boolean', + `Invalid isVirtual flag: ${device.isVirtual}`, + ); + ok( + device.isRemovable === null || + typeof device.isRemovable === 'boolean', + `Invalid isRemovable flag: ${device.isRemovable}`, + ); + ok( + device.isCard === null || typeof device.isCard === 'boolean', + `Invalid isCard flag: ${device.isCard}`, + ); + ok( + device.isSCSI === null || typeof device.isSCSI === 'boolean', + `Invalid isSCSI flag: ${device.isSCSI}`, + ); + ok( + device.isUSB === null || typeof device.isUSB === 'boolean', + `Invalid isUSB flag: ${device.isUSB}`, + ); + ok( + device.isUAS === null || typeof device.isUAS === 'boolean', + `Invalid isUAS flag: ${device.isUAS}`, + ); + }); + }); + + describe('given an unsupported os', () => { + beforeEach(() => { + // @ts-ignore + this.osPlatformStub = stub(os, 'platform'); + // @ts-ignore + this.osPlatformStub.returns('foobar'); + }); + + afterEach(() => { + // @ts-ignore + this.osPlatformStub.restore(); + }); + + it('should yield an unsupported error', async () => { + try { + await list(); + } catch (error) { + expect(error).to.be.an.instanceof(Error); + expect(error.message).to.equal( + 'Your OS is not supported by this module: foobar', + ); + return; + } + ok(false, 'Expected error not thrown'); + }); + }); + }); +}); diff --git a/dependencies/drivelist/tests/lsblk.spec.ts b/dependencies/drivelist/tests/lsblk.spec.ts new file mode 100644 index 0000000..727efc0 --- /dev/null +++ b/dependencies/drivelist/tests/lsblk.spec.ts @@ -0,0 +1,461 @@ +/* + * Copyright 2018 Balena.io + * + * 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. + */ + +import { expect } from 'chai'; +import { readFileSync } from 'fs'; +import { join } from 'path'; +import * as util from 'util'; + +import { transform as transformJSON } from '../lib/lsblk/json'; +import { parse as parsePairs } from '../lib/lsblk/pairs'; + +function inspect(value: any) { + console.log( + util.inspect(value, { + colors: true, + depth: null, + }), + ); +} + +describe('Drivelist', () => { + context('lsblk', () => { + it('can handle --pairs output on Ubuntu 14.04', () => { + const listData = readFileSync( + join(__dirname, 'data', 'lsblk', 'ubuntu-14.04-1.txt'), + 'utf8', + ); + const devices = parsePairs(listData); + + const expected = [ + { + enumerator: 'lsblk:pairs', + busType: 'UNKNOWN', + busVersion: null, + device: '/dev/sda', + devicePath: null, + raw: '/dev/sda', + description: '(/boot/efi, /, [SWAP], /home)', + error: null, + size: 1024209543168, + blockSize: 512, + logicalBlockSize: 512, + mountpoints: [ + { + path: '/boot/efi', + label: undefined, + }, + { + path: '/', + label: undefined, + }, + { + path: '[SWAP]', + label: undefined, + }, + { + path: '/home', + label: undefined, + }, + ], + isReadOnly: false, + isSystem: true, + isVirtual: null, + isRemovable: false, + isCard: null, + isSCSI: null, + isUSB: null, + isUAS: null, + }, + ]; + + inspect(parsePairs(listData)); + + expect(devices).to.deep.equal(expected); + }); + + it('can handle --pairs output on Ubuntu 14.04, sample 2', () => { + const listData = readFileSync( + join(__dirname, 'data', 'lsblk', 'ubuntu-14.04-2.txt'), + 'utf8', + ); + const devices = parsePairs(listData); + + const expected = [ + { + enumerator: 'lsblk:pairs', + busType: 'UNKNOWN', + busVersion: null, + device: '/dev/fd0', + devicePath: null, + raw: '/dev/fd0', + description: 'fd0', + error: null, + size: null, + blockSize: 512, + logicalBlockSize: 512, + mountpoints: [], + isReadOnly: false, + isSystem: false, + isVirtual: null, + isRemovable: true, + isCard: null, + isSCSI: null, + isUSB: null, + isUAS: null, + }, + { + enumerator: 'lsblk:pairs', + busType: 'UNKNOWN', + busVersion: null, + device: '/dev/sda', + devicePath: null, + raw: '/dev/sda', + description: '(/, [SWAP])', + error: null, + size: null, + blockSize: 512, + logicalBlockSize: 512, + mountpoints: [ + { + path: '/', + label: undefined, + }, + { + path: '[SWAP]', + label: undefined, + }, + ], + isReadOnly: false, + isSystem: true, + isVirtual: null, + isRemovable: false, + isCard: null, + isSCSI: null, + isUSB: null, + isUAS: null, + }, + ]; + + inspect(parsePairs(listData)); + + expect(devices).to.deep.equal(expected); + }); + + it('can handle mountpoints on root devices', () => { + const listData = require('./data/lsblk/no-children-mountpoints.json'); + const actual = transformJSON(listData); + + const expected = [ + { + enumerator: 'lsblk:json', + busType: 'UNKNOWN', + busVersion: null, + device: '/dev/sda', + devicePath: null, + raw: '/dev/sda', + description: '', + error: null, + size: null, + blockSize: 512, + logicalBlockSize: 512, + mountpoints: [ + { + path: '/media/jwentz/Temp', + label: undefined, + }, + ], + isReadOnly: false, + isSystem: false, + isVirtual: null, + isRemovable: true, + isCard: null, + isSCSI: null, + isUSB: null, + isUAS: null, + }, + { + enumerator: 'lsblk:json', + busType: 'UNKNOWN', + busVersion: null, + device: '/dev/nvme0n1', + devicePath: null, + raw: '/dev/nvme0n1', + description: '([SWAP], /boot/efi, /)', + error: null, + size: null, + blockSize: 512, + logicalBlockSize: 512, + mountpoints: [ + { + path: '[SWAP]', + label: undefined, + }, + { + path: '/boot/efi', + label: undefined, + }, + { + path: '/', + label: undefined, + }, + ], + isReadOnly: false, + isSystem: true, + isVirtual: null, + isRemovable: false, + isCard: null, + isSCSI: null, + isUSB: null, + isUAS: null, + }, + ]; + + inspect(actual); + + expect(actual).to.deep.equal(expected); + }); + + it('can handle empty mountpoints in lsblk --pairs output', () => { + const listData = readFileSync( + join(__dirname, 'data', 'lsblk', 'ubuntu-14.04-3.txt'), + 'utf8', + ); + const actual = parsePairs(listData); + const expected = [ + { + enumerator: 'lsblk:pairs', + busType: 'UNKNOWN', + busVersion: null, + device: '/dev/sda', + devicePath: null, + raw: '/dev/sda', + description: 'sda', + error: null, + size: null, + blockSize: 512, + logicalBlockSize: 512, + mountpoints: [], + isReadOnly: false, + isSystem: true, + isVirtual: null, + isRemovable: false, + isCard: null, + isSCSI: null, + isUSB: null, + isUAS: null, + }, + { + enumerator: 'lsblk:pairs', + busType: 'UNKNOWN', + busVersion: null, + device: '/dev/sdb', + devicePath: null, + raw: '/dev/sdb', + description: 'sdb', + error: null, + size: null, + blockSize: 512, + logicalBlockSize: 512, + mountpoints: [], + isReadOnly: false, + isSystem: false, + isVirtual: null, + isRemovable: true, + isCard: null, + isSCSI: null, + isUSB: null, + isUAS: null, + }, + { + enumerator: 'lsblk:pairs', + busType: 'UNKNOWN', + busVersion: null, + device: '/dev/sdc', + devicePath: null, + raw: '/dev/sdc', + description: 'sdc', + error: null, + size: null, + blockSize: 512, + logicalBlockSize: 512, + mountpoints: [], + isReadOnly: false, + isSystem: false, + isVirtual: null, + isRemovable: true, + isCard: null, + isSCSI: null, + isUSB: null, + isUAS: null, + }, + { + enumerator: 'lsblk:pairs', + busType: 'UNKNOWN', + busVersion: null, + device: '/dev/sdd', + devicePath: null, + raw: '/dev/sdd', + description: '(/media//85CA-6700)', + error: null, + size: null, + blockSize: 512, + logicalBlockSize: 512, + mountpoints: [ + { + path: '/media//85CA-6700', + label: undefined, + }, + ], + isReadOnly: false, + isSystem: false, + isVirtual: null, + isRemovable: true, + isCard: null, + isSCSI: null, + isUSB: null, + isUAS: null, + }, + { + enumerator: 'lsblk:pairs', + busType: 'UNKNOWN', + busVersion: null, + device: '/dev/nvme0n1', + devicePath: null, + raw: '/dev/nvme0n1', + description: '(/)', + error: null, + size: null, + blockSize: 512, + logicalBlockSize: 512, + mountpoints: [ + { + path: '/', + label: undefined, + }, + ], + isReadOnly: false, + isSystem: true, + isVirtual: null, + isRemovable: false, + isCard: null, + isSCSI: null, + isUSB: null, + isUAS: null, + }, + ]; + + inspect(actual); + + expect(actual).to.deep.equal(expected); + }); + + it('can handle mountpoints on root devices in --pairs output', () => { + const listData = readFileSync( + join(__dirname, 'data', 'lsblk', 'no-partition-table.txt'), + 'utf8', + ); + const devices = parsePairs(listData); + + const expected = [ + { + blockSize: 512, + busType: 'UNKNOWN', + busVersion: null, + description: '(/boot/efi, /boot)', + device: '/dev/sda', + devicePath: null, + enumerator: 'lsblk:pairs', + error: null, + isCard: null, + isReadOnly: false, + isRemovable: false, + isSCSI: null, + isSystem: true, + isUAS: null, + isUSB: null, + isVirtual: null, + logicalBlockSize: 512, + mountpoints: [ + { + label: undefined, + path: '/boot/efi', + }, + { + label: undefined, + path: '/boot', + }, + ], + raw: '/dev/sda', + size: 240065183744, + }, + { + blockSize: 512, + busType: 'UNKNOWN', + busVersion: null, + description: 'sdb', + device: '/dev/sdb', + devicePath: null, + enumerator: 'lsblk:pairs', + error: null, + isCard: null, + isReadOnly: false, + isRemovable: true, + isSCSI: null, + isSystem: false, + isUAS: null, + isUSB: null, + isVirtual: null, + logicalBlockSize: 512, + mountpoints: [], + raw: '/dev/sdb', + size: null, + }, + { + blockSize: 512, + busType: 'UNKNOWN', + busVersion: null, + description: '(/run/media/DA2E4172/BUILD)', + device: '/dev/sdc', + devicePath: null, + enumerator: 'lsblk:pairs', + error: null, + isCard: null, + isReadOnly: false, + isRemovable: true, + isSCSI: null, + isSystem: false, + isUAS: null, + isUSB: null, + isVirtual: null, + logicalBlockSize: 512, + mountpoints: [ + { + label: undefined, + path: '/run/media/DA2E4172/BUILD', + }, + ], + raw: '/dev/sdc', + size: 31457280000, + }, + ]; + + inspect(parsePairs(listData)); + + expect(devices).to.deep.equal(expected); + }); + }); +}); diff --git a/dependencies/drivelist/tsconfig.json b/dependencies/drivelist/tsconfig.json new file mode 100644 index 0000000..a9a9438 --- /dev/null +++ b/dependencies/drivelist/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "module": "commonjs", + "outDir": "js", + "sourceMap": true, + "declaration": true, + "target": "es6", + "noImplicitAny": true, + "strictNullChecks": true, + "noUnusedLocals": true, + "noUnusedParameters": true + }, + "include": [ + "lib" + ] +} diff --git a/dependencies/fat32format/.gitignore b/dependencies/fat32format/.gitignore new file mode 100644 index 0000000..1c6f0b1 --- /dev/null +++ b/dependencies/fat32format/.gitignore @@ -0,0 +1,366 @@ + +# Created by https://www.gitignore.io/api/windows,visualstudio +# Edit at https://www.gitignore.io/?templates=windows,visualstudio + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +### VisualStudio ### +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# End of https://www.gitignore.io/api/windows,visualstudio diff --git a/dependencies/fat32format/CMakeLists.txt b/dependencies/fat32format/CMakeLists.txt new file mode 100644 index 0000000..e829dd8 --- /dev/null +++ b/dependencies/fat32format/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 2.4.4) +project(fat32format LANGUAGES CXX) + +add_executable(${PROJECT_NAME} fat32format.cpp) diff --git a/dependencies/fat32format/LICENSE b/dependencies/fat32format/LICENSE new file mode 100644 index 0000000..733c072 --- /dev/null +++ b/dependencies/fat32format/LICENSE @@ -0,0 +1,675 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. + diff --git a/dependencies/fat32format/Makefile b/dependencies/fat32format/Makefile new file mode 100644 index 0000000..117d41e --- /dev/null +++ b/dependencies/fat32format/Makefile @@ -0,0 +1,6 @@ +CXX = clang-cl +CXXFLAGS += -utf-8 -std:c++latest -EHsc -GR- -W4 -Werror=gnu -Wmicrosoft -Wno-missing-field-initializers -Wpedantic + +fat32format: fat32format.cpp +clean: + rm fat32format.exe \ No newline at end of file diff --git a/dependencies/fat32format/README.md b/dependencies/fat32format/README.md new file mode 100644 index 0000000..7ab42f7 --- /dev/null +++ b/dependencies/fat32format/README.md @@ -0,0 +1,53 @@ +# fat32format +``` +Usage Fat32Format [-cN] [-lLABEL] [-p] [-y] { C: | \\.\C: | \\?\Volume{GUID} } +Erase all data on specified volume, format it for FAT32 + + -c Specify a cluster size by sector count. + Accepts 1, 2, 4, 8, 16, 32, 64, 128 + EXAMPLE: Fat32Format -c4 X: - use 4 sectors per cluster + -l Specify volume label. + If exceeds 11-bytes, truncate label. + -p Make immutable AUTORUN.INF on root directory. + This file cannot do anything on Windows. + +Modified Version see https://github.com/0xbadfca11/fat32format + +Original Version 1.07, see http://www.ridgecrop.demon.co.uk/fat32format.htm +This software is covered by the GPL +Use with care - Ridgecrop are not liable for data lost using this tool +``` + +## Changes from original + +### Alignment awareness +Original fat32format allocates only necessary size to metadata. +This isn't always aligned cluster. +Modified fat32format always round up 1 MiB. + +NOTE: FAT32 is different from NTFS, metadata exists between start of the partition and first cluster. + +### Immutable AUTORUN.INF +You can not open, read, write, rename, move or delete this on Windows OS. +Only re-format can delete this. (or delete from non-Windows OS) + +NOTE: This behavior is undocumented. +It does not guarantee also be the same behavior in the future. + +### Strict drive letter +Original fat32format accepts + + fat32format.exe XYZABCDKGS!@#$% + +This will format X: drive. +Modified fat32format deny this. +Only accepts + + fat32format.exe X: + fat32format.exe \\.\X: + fat32format.exe \\?\Volume{GUID} + +### Support volume label at format + +## LICENSE +GPL diff --git a/dependencies/fat32format/fat32format.cpp b/dependencies/fat32format/fat32format.cpp new file mode 100644 index 0000000..c0deb99 --- /dev/null +++ b/dependencies/fat32format/fat32format.cpp @@ -0,0 +1,792 @@ +// Fat32 formatter version 1.05 +// (c) Tom Thornhill 2007,2008,2009 +// This software is covered by the GPL. +// By using this tool, you agree to absolve Ridgecrop of an liabilities for lost data. +// Please backup any data you value before using this tool. + +// | ALIGNING_SIZE * N | +// | BPB,FSInfo,Reserved | FAT1 | FAT2 | Cluster0 +static const int ALIGNING_SIZE = 1024 * 1024; + +#define WIN32_LEAN_AND_MEAN +#define STRICT_GS_ENABLED +#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 +#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT 1 +#define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 1 +#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_MEMORY 1 +#define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES_MEMORY 1 + +#include +#include +#include + +#include +#include +#include + +// EDIT for mingw +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif +#include +// + + +#pragma pack(push, 1) +struct FAT_BOOTSECTOR32 +{ + // Common fields. + BYTE sJmpBoot[3]; + CHAR sOEMName[8]; + WORD wBytsPerSec; + BYTE bSecPerClus; + WORD wRsvdSecCnt; + BYTE bNumFATs; + WORD wRootEntCnt; + WORD wTotSec16; // if zero, use dTotSec32 instead + BYTE bMedia; + WORD wFATSz16; + WORD wSecPerTrk; + WORD wNumHeads; + DWORD dHiddSec; + DWORD dTotSec32; + // Fat 32/16 only + DWORD dFATSz32; + WORD wExtFlags; + WORD wFSVer; + DWORD dRootClus; + WORD wFSInfo; + WORD wBkBootSec; + BYTE Reserved[12]; + BYTE bDrvNum; + BYTE Reserved1; + BYTE bBootSig; // == 0x29 if next three fields are ok + DWORD dBS_VolID; + BYTE sVolLab[11]; + BYTE sBS_FilSysType[8]; +}; + +struct FAT_FSINFO +{ + DWORD dLeadSig; // 0x41615252 + BYTE sReserved1[480]; // zeros + DWORD dStrucSig; // 0x61417272 + DWORD dFree_Count; // 0xFFFFFFFF + DWORD dNxt_Free; // 0xFFFFFFFF + BYTE sReserved2[12]; // zeros + DWORD dTrailSig; // 0xAA550000 +}; + +struct FAT_DIRECTORY +{ + UINT8 DIR_Name[8 + 3]; + UINT8 DIR_Attr; + UINT8 DIR_NTRes; + UINT8 DIR_CrtTimeTenth; + UINT16 DIR_CrtTime; + UINT16 DIR_CrtDate; + UINT16 DIR_LstAccDate; + UINT16 DIR_FstClusHI; + UINT16 DIR_WrtTime; + UINT16 DIR_WrtDate; + UINT16 DIR_FstClusLO; + UINT32 DIR_FileSize; +}; +static_assert(sizeof(FAT_DIRECTORY) == 32); + +#pragma pack(pop) + +/* +28.2 CALCULATING THE VOLUME SERIAL NUMBER + +For example, say a disk was formatted on 26 Dec 95 at 9:55 PM and 41.94 +seconds. DOS takes the date and time just before it writes it to the +disk. + +Low order word is calculated: Volume Serial Number is: + Month & Day 12/26 0c1ah + Sec & Hundrenths 41:94 295eh 3578:1d02 + ----- + 3578h + +High order word is calculated: + Hours & Minutes 21:55 1537h + Year 1995 07cbh + ----- + 1d02h +*/ +DWORD get_volume_id() +{ + SYSTEMTIME s; + + GetLocalTime(&s); + + WORD lo = s.wDay + (s.wMonth << 8); + WORD tmp = (s.wMilliseconds / 10) + (s.wSecond << 8); + lo += tmp; + + WORD hi = s.wMinute + (s.wHour << 8); + hi += s.wYear; + + return lo + (hi << 16); +} + +struct format_params +{ + int sectors_per_cluster = 0; // can be zero for default or 1,2,4,8,16,32 or 64 + bool make_protected_autorun = false; + bool all_yes = false; + char volume_label[sizeof(FAT_BOOTSECTOR32::sVolLab) + 1] = {}; +}; + +[[noreturn]] +void die(_In_z_ PCSTR error) +{ + DWORD dw = GetLastError(); + + if (dw != NO_ERROR) + { + PSTR lpMsgBuf; + FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + dw, + 0, + (PSTR)&lpMsgBuf, + 0, NULL); + fprintf(stderr, "%s\nGetLastError()=%lu: %s\n", error, dw, lpMsgBuf); + LocalFree(lpMsgBuf); + } + else + { + fprintf(stderr, "%s\n", error); + } + + exit(dw); +} + +/* +This is the Microsoft calculation from FATGEN + + DWORD RootDirSectors = 0; + DWORD TmpVal1, TmpVal2, FATSz; + + TmpVal1 = DskSize - ( ReservedSecCnt + RootDirSectors); + TmpVal2 = (256 * SecPerClus) + NumFATs; + TmpVal2 = TmpVal2 / 2; + FATSz = (TmpVal1 + (TmpVal2 - 1)) / TmpVal2; + + return( FatSz ); +*/ + +DWORD get_fat_size_sectors(_In_ DWORD DskSize, _In_ DWORD ReservedSecCnt, _In_ DWORD SecPerClus, _In_ DWORD NumFATs, _In_ DWORD BytesPerSect) +{ + const ULONGLONG FatElementSize = 4; + + // This is based on + // http://hjem.get2net.dk/rune_moeller_barnkob/filesystems/fat.html + // I've made the obvious changes for FAT32 + ULONGLONG Numerator = FatElementSize * (DskSize - ReservedSecCnt); + ULONGLONG Denominator = (1ULL * SecPerClus * BytesPerSect) + (FatElementSize * NumFATs); + ULONGLONG FatSz = Numerator / Denominator; + // round up + FatSz += 1; + const ULONG AlignSectorCount = ALIGNING_SIZE / BytesPerSect; + FatSz = ((FatSz * NumFATs + ReservedSecCnt + AlignSectorCount - 1) / AlignSectorCount * AlignSectorCount - ReservedSecCnt) / NumFATs; + + return (DWORD)FatSz; +} + +void seek_to_sect(_In_ HANDLE hDevice, _In_ DWORD Sector, _In_ DWORD BytesPerSect) +{ + LARGE_INTEGER Offset; + + Offset.QuadPart = 1LL * Sector * BytesPerSect; + BOOL ret = SetFilePointerEx(hDevice, Offset, nullptr, FILE_BEGIN); + + if (!ret) + die("Failed to seek"); +} + +void write_sect(_In_ HANDLE hDevice, _In_ DWORD Sector, _In_ DWORD BytesPerSector, _In_ void* Data, _In_ DWORD NumSects) +{ + DWORD dwWritten; + + seek_to_sect(hDevice, Sector, BytesPerSector); + BOOL ret = WriteFile(hDevice, Data, NumSects * BytesPerSector, &dwWritten, NULL); + + if (!ret) + die("Failed to write"); +} + +void zero_sectors(_In_ HANDLE hDevice, _In_ DWORD Sector, _In_ DWORD BytesPerSect, _In_ DWORD NumSects) +{ + LARGE_INTEGER Start, End, Ticks, Frequency; + DWORD qBytesTotal = NumSects * BytesPerSect; + + DWORD BurstSize = 1024 * 1024 / BytesPerSect; + + PBYTE pZeroSect = (PBYTE)VirtualAlloc(NULL, BytesPerSect * BurstSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + + seek_to_sect(hDevice, Sector, BytesPerSect); + + QueryPerformanceFrequency(&Frequency); + QueryPerformanceCounter(&Start); + while (NumSects) + { + DWORD WriteSize = min(NumSects, BurstSize); + DWORD dwWritten; + + BOOL ret = WriteFile(hDevice, pZeroSect, WriteSize * BytesPerSect, &dwWritten, NULL); + if (!ret) + die("Failed to write"); + + NumSects -= WriteSize; + } + + QueryPerformanceCounter(&End); + Ticks.QuadPart = End.QuadPart - Start.QuadPart; + double fTime = (double)(Ticks.QuadPart) / Frequency.QuadPart; + double fBytesTotal = (double)qBytesTotal; + printf("Wrote %lu bytes in %.2f seconds, %.2f Megabytes/sec\n", qBytesTotal, fTime, fBytesTotal / (fTime * 1024.0 * 1024.0)); +} + +BYTE get_spc(_In_ DWORD ClusterSizeKB, _In_ DWORD BytesPerSect) +{ + DWORD spc = (ClusterSizeKB * 1024) / BytesPerSect; + return (BYTE)spc; +} +BYTE get_sectors_per_cluster(_In_ LONGLONG DiskSizeBytes, _In_ DWORD BytesPerSect) +{ + LONGLONG DiskSizeMB = DiskSizeBytes / (1024 * 1024); + + // Larger than 32,768 MB 32 KB + if (DiskSizeMB > 32768) + return get_spc(32, BytesPerSect); + + // 16,384 MB to 32,767 MB 16 KB + if (DiskSizeMB > 16384) + return get_spc(16, BytesPerSect); + + // 8,192 MB to 16,383 MB 8 KB + if (DiskSizeMB > 8192) + return get_spc(8, BytesPerSect); + + // 256 MB to 8,191 MB 4 KB + if (DiskSizeMB > 256) + return get_spc(4, BytesPerSect); + + // 128 MB to 256 MB 2 KB + if (DiskSizeMB > 128) + return get_spc(2, BytesPerSect); + + // 64 MB to 128 MB 1 KB + if (DiskSizeMB > 64) + return get_spc(1, BytesPerSect); + + // 32 MB to 64 MB 0.5 KB + return 1; +} + +int format_volume(_In_z_ LPCSTR vol, _In_ const format_params* params) +{ + DWORD cbRet; + BOOL bRet; + DISK_GEOMETRY dgDrive; + PARTITION_INFORMATION piDrive; + PARTITION_INFORMATION_EX xpiDrive; + bool bGPTMode = false; + const WORD ReservedSectCount = 32; + const BYTE NumFATs = 2; + const BYTE VolId[12] = "NO NAME "; + DWORD FatSize; + DWORD BytesPerSect; + BYTE SectorsPerCluster; + DWORD TotalSectors; + DWORD SystemAreaSize; + DWORD UserAreaSize; + ULONGLONG qTotalSectors; + ULONGLONG FatNeeded, ClusterCount; + + if (!IsDebuggerPresent() && !params->all_yes) + { + printf("Warning ALL data on drive '%s' will be lost irretrievably, are you sure\n(y/n) :", vol); + if (toupper(getchar()) != 'Y') + { + exit(EXIT_FAILURE); + } + } + + HANDLE hDevice = CreateFileA( + vol, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_NO_BUFFERING, + NULL + ); + + if (hDevice == INVALID_HANDLE_VALUE) + die("Failed to open device - close any files before formatting and make sure you have Admin rights when using fat32format\n Are you SURE you're formatting the RIGHT DRIVE!!!"); + + bRet = DeviceIoControl(hDevice, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0, &cbRet, NULL); + + if (!bRet) + printf("Failed to allow extended DASD on device"); + + bRet = DeviceIoControl(hDevice, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &cbRet, NULL); + + if (!bRet) + die("Failed to lock device"); + + bRet = DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &dgDrive, sizeof(dgDrive), &cbRet, NULL); + + if (!bRet) + die("Failed to get device geometry"); + + bRet = DeviceIoControl(hDevice, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, &piDrive, sizeof(piDrive), &cbRet, NULL); + + if (!bRet) + { + printf("IOCTL_DISK_GET_PARTITION_INFO failed, trying IOCTL_DISK_GET_PARTITION_INFO_EX\n"); + bRet = DeviceIoControl(hDevice, IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0, &xpiDrive, sizeof(xpiDrive), &cbRet, NULL); + + if (!bRet) + die("Failed to get partition info (both regular and _ex)"); + + memset(&piDrive, 0, sizeof(piDrive)); + piDrive.StartingOffset.QuadPart = xpiDrive.StartingOffset.QuadPart; + piDrive.PartitionLength.QuadPart = xpiDrive.PartitionLength.QuadPart; + piDrive.HiddenSectors = (DWORD)(xpiDrive.StartingOffset.QuadPart / dgDrive.BytesPerSector); + + bGPTMode = xpiDrive.PartitionStyle != PARTITION_STYLE_MBR; + printf("IOCTL_DISK_GET_PARTITION_INFO_EX ok, GPTMode=%d\n", bGPTMode); + } + + BytesPerSect = dgDrive.BytesPerSector; + __analysis_assume(BytesPerSect >= 512); + + // Checks on Disk Size + qTotalSectors = piDrive.PartitionLength.QuadPart / dgDrive.BytesPerSector; + // low end limit - 65536 sectors + if (qTotalSectors < 65536) + { + // I suspect that most FAT32 implementations would mount this volume just fine, but the + // spec says that we shouldn't do this, so we won't + die("This drive is too small for FAT32 - there must be at least 64K clusters\n"); + } + + if (qTotalSectors >= 0xffffffff) + { + // This is a more fundamental limitation on FAT32 - the total sector count in the root dir + // is 32bit. With a bit of creativity, FAT32 could be extended to handle at least 2^28 clusters + // There would need to be an extra field in the FSInfo sector, and the old sector count could + // be set to 0xffffffff. This is non standard though, the Windows FAT driver FASTFAT.SYS won't + // understand this. Perhaps a future version of FAT32 and FASTFAT will handle this. + die("This drive is too big for FAT32 - max 2TB supported\n"); + } + + if (IsWindowsVistaOrGreater()) + { + STORAGE_PROPERTY_QUERY Query = { StorageAccessAlignmentProperty, PropertyStandardQuery }; + STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR Alignment = {}; + if (DeviceIoControl( + hDevice, + IOCTL_STORAGE_QUERY_PROPERTY, + &Query, + sizeof Query, + &Alignment, + sizeof Alignment, + &cbRet, + NULL + )) + { + if (Alignment.BytesOffsetForSectorAlignment) + puts("Warning This disk has 'alignment offset'"); + if (piDrive.StartingOffset.QuadPart > 0 && piDrive.StartingOffset.QuadPart % Alignment.BytesPerPhysicalSector) + puts("Warning This partition isn't aligned"); + } + } + + FAT_BOOTSECTOR32* pFAT32BootSect = (FAT_BOOTSECTOR32*)VirtualAlloc(NULL, BytesPerSect, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + FAT_FSINFO* pFAT32FsInfo = (FAT_FSINFO*)VirtualAlloc(NULL, BytesPerSect, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + DWORD* pFirstSectOfFat = (DWORD*)VirtualAlloc(NULL, BytesPerSect, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + FAT_DIRECTORY* pFAT32Directory = (FAT_DIRECTORY*)VirtualAlloc(NULL, BytesPerSect, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + + if (!pFAT32BootSect || !pFAT32FsInfo || !pFirstSectOfFat || !pFAT32Directory) + die("Failed to allocate memory"); + + // fill out the boot sector and fs info + pFAT32BootSect->sJmpBoot[0] = 0xEB; + pFAT32BootSect->sJmpBoot[1] = 0x58; // jmp.s $+0x5a is 0xeb 0x58, not 0xeb 0x5a. Thanks Marco! + pFAT32BootSect->sJmpBoot[2] = 0x90; + memcpy(pFAT32BootSect->sOEMName, "MSWIN4.1", sizeof(FAT_BOOTSECTOR32::sOEMName)); + pFAT32BootSect->wBytsPerSec = (WORD)BytesPerSect; + + if (params->sectors_per_cluster) + SectorsPerCluster = (BYTE)params->sectors_per_cluster; + else + SectorsPerCluster = get_sectors_per_cluster(piDrive.PartitionLength.QuadPart, BytesPerSect); + + pFAT32BootSect->bSecPerClus = SectorsPerCluster; + pFAT32BootSect->wRsvdSecCnt = ReservedSectCount; + pFAT32BootSect->bNumFATs = NumFATs; + pFAT32BootSect->wRootEntCnt = 0; + pFAT32BootSect->wTotSec16 = 0; + pFAT32BootSect->bMedia = 0xF8; + pFAT32BootSect->wFATSz16 = 0; + pFAT32BootSect->wSecPerTrk = (WORD)dgDrive.SectorsPerTrack; + pFAT32BootSect->wNumHeads = (WORD)dgDrive.TracksPerCylinder; + pFAT32BootSect->dHiddSec = (DWORD)piDrive.HiddenSectors; + TotalSectors = (DWORD)(piDrive.PartitionLength.QuadPart / dgDrive.BytesPerSector); + pFAT32BootSect->dTotSec32 = TotalSectors; + + FatSize = get_fat_size_sectors(pFAT32BootSect->dTotSec32, pFAT32BootSect->wRsvdSecCnt, pFAT32BootSect->bSecPerClus, pFAT32BootSect->bNumFATs, BytesPerSect); + + pFAT32BootSect->dFATSz32 = FatSize; + pFAT32BootSect->wExtFlags = 0; + pFAT32BootSect->wFSVer = 0; + pFAT32BootSect->dRootClus = 2; + pFAT32BootSect->wFSInfo = 1; + pFAT32BootSect->wBkBootSec = 6; + pFAT32BootSect->bDrvNum = 0x80; + pFAT32BootSect->Reserved1 = 0; + pFAT32BootSect->bBootSig = 0x29; + + pFAT32BootSect->dBS_VolID = get_volume_id(); + memcpy(pFAT32BootSect->sVolLab, VolId, 11); + memcpy(pFAT32BootSect->sBS_FilSysType, "FAT32 ", 8); + ((BYTE*)pFAT32BootSect)[510] = 0x55; + ((BYTE*)pFAT32BootSect)[511] = 0xaa; + + /* FATGEN103.DOC says "NOTE: Many FAT documents mistakenly say that this 0xAA55 signature occupies the "last 2 bytes of + the boot sector". This statement is correct if - and only if - BPB_BytsPerSec is 512. If BPB_BytsPerSec is greater than + 512, the offsets of these signature bytes do not change (although it is perfectly OK for the last two bytes at the end + of the boot sector to also contain this signature)." + + Windows seems to only check the bytes at offsets 510 and 511. Other OSs might check the ones at the end of the sector, + so we'll put them there too. + */ + if (BytesPerSect != 512) + { + ((BYTE*)pFAT32BootSect)[BytesPerSect - 2] = 0x55; + ((BYTE*)pFAT32BootSect)[BytesPerSect - 1] = 0xaa; + } + + // FSInfo sect + pFAT32FsInfo->dLeadSig = 0x41615252; + pFAT32FsInfo->dStrucSig = 0x61417272; + pFAT32FsInfo->dFree_Count = MAXDWORD; + pFAT32FsInfo->dNxt_Free = MAXDWORD; + pFAT32FsInfo->dTrailSig = 0xaa550000; + + // First FAT Sector + pFirstSectOfFat[0] = 0x0ffffff8; // Reserved cluster 1 media id in low byte + pFirstSectOfFat[1] = 0x0fffffff; // Reserved cluster 2 EOC + pFirstSectOfFat[2] = 0x0fffffff; // end of cluster chain for root dir + + // Write boot sector, fats + // Sector 0 Boot Sector + // Sector 1 FSInfo + // Sector 2 More boot code - we write zeros here + // Sector 3 unused + // Sector 4 unused + // Sector 5 unused + // Sector 6 Backup boot sector + // Sector 7 Backup FSInfo sector + // Sector 8 Backup 'more boot code' + // zero'd sectors upto ReservedSectCount + // FAT1 ReservedSectCount to ReservedSectCount + FatSize + // ... + // FATn ReservedSectCount to ReservedSectCount + FatSize + // RootDir - allocated to cluster2 + + UserAreaSize = TotalSectors - ReservedSectCount - NumFATs * FatSize; + ClusterCount = UserAreaSize / SectorsPerCluster; + + // Sanity check for a cluster count of >2^28, since the upper 4 bits of the cluster values in the FAT are reserved. + // Cluster 0x00000000 meaning unused + // Cluster 0x00000001 reserved + // Cluster 0x0FFFFFF7 bad cluster + // Cluster 0x0FFFFFF[8-F] end of cluster chain + if (ClusterCount > 0x0FFFFFF4) + { + die("This drive has more than 2^28 clusters, try to specify a larger cluster size or use the default (i.e. don't use -cXX)\n"); + } + + // Sanity check - < 64K clusters means that the volume will be misdetected as FAT16 + if (ClusterCount < 65536) + { + die("FAT32 must have at least 65536 clusters, try to specify a smaller cluster size or use the default (i.e. don't use -cXX)\n"); + } + + // Sanity check, make sure the fat is big enough + // Convert the cluster count into a Fat sector count, and check the fat size value we calculated + // earlier is OK. + FatNeeded = ClusterCount * 4; + FatNeeded = (FatNeeded + BytesPerSect - 1) / BytesPerSect; + if (FatNeeded > FatSize) + { + die("This drive is too big for this version of fat32format, check for an upgrade\n"); + } + + // Now we're commited - print some info first + printf("Size : %gGB %lu sectors\n", piDrive.PartitionLength.QuadPart / (1024.f * 1024.f * 1024.f), TotalSectors); + printf("%lu Bytes Per Sector, Cluster size %lu bytes\n", BytesPerSect, SectorsPerCluster * BytesPerSect); + printf("Volume ID is %04lX:%04lX\n", pFAT32BootSect->dBS_VolID >> 16, pFAT32BootSect->dBS_VolID & 0xffff); + printf("%u Reserved Sectors, %lu Sectors per FAT, %u fats\n", ReservedSectCount, FatSize, NumFATs); + + printf("%llu Total clusters\n", ClusterCount); + + // fix up the FSInfo sector + pFAT32FsInfo->dFree_Count = (UserAreaSize / SectorsPerCluster) - 1; + pFAT32FsInfo->dNxt_Free = 3; // clusters 0-1 resered, we used cluster 2 for the root dir + + printf("%lu Free Clusters\n", pFAT32FsInfo->dFree_Count); + // Work out the Cluster count + + printf("Formatting drive %s...\n", vol); + + // Once zero_sectors has run, any data on the drive is basically lost.... + + // First zero out ReservedSect + FatSize * NumFats + SectorsPerCluster + SystemAreaSize = (pFAT32BootSect->wRsvdSecCnt + (pFAT32BootSect->bNumFATs * FatSize) + SectorsPerCluster); + printf("Clearing out %lu sectors for Reserved sectors, fats and root directory...\n", SystemAreaSize); + zero_sectors(hDevice, 0, BytesPerSect, SystemAreaSize); + puts("Initialising reserved sectors and FATs..."); + // Now we should write the boot sector and fsinfo twice, once at 0 and once at the backup boot sect position + for (int i = 0; i < 2; i++) + { + int SectorStart = (i == 0) ? 0 : pFAT32BootSect->wBkBootSec; + write_sect(hDevice, SectorStart, BytesPerSect, pFAT32BootSect, 1); + write_sect(hDevice, SectorStart + 1, BytesPerSect, pFAT32FsInfo, 1); + } + + // Write the first fat sector in the right places + for (int i = 0; i < pFAT32BootSect->bNumFATs; i++) + { + int SectorStart = pFAT32BootSect->wRsvdSecCnt + (i * FatSize); + write_sect(hDevice, SectorStart, BytesPerSect, pFirstSectOfFat, 1); + } + + if (params->make_protected_autorun) + { + memcpy(pFAT32Directory[0].DIR_Name, "AUTORUN INF", sizeof(FAT_DIRECTORY::DIR_Name)); + pFAT32Directory[0].DIR_Attr = FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM; + write_sect(hDevice, ReservedSectCount + NumFATs * FatSize, BytesPerSect, pFAT32Directory, 1); + } + + // The filesystem recogniser in Windows XP doesn't use the partition type - in can be + // set to pretty much anything other Os's like Dos (still useful for Norton Ghost!) and Windows ME might, + // so we could fix it here + // On the other hand, I'm not sure that exposing big partitions to Windows ME/98 is a very good idea + // There are a couple of issues here - + // 1) WinME/98 doesn't know about 48bit LBA, so IDE drives bigger than 137GB will cause it + // problems. Rather than refuse to mount them, it uses 28bit LBA which wraps + // around, so writing to files above the 137GB boundary will erase the FAT and root dirs. + // 2) Win98 and WinME have 16 bit scandisk tools, which you need to disable, assuming you + // can get third party support for 48bit LBA, or use a USB external case, most of which + // will let you use a 48bit LBA drive. + // see http://www.48bitlba.com/win98.htm for instructions + + // If we have a GPT disk, don't mess with the partition type + if (!bGPTMode) + { + SET_PARTITION_INFORMATION spiDrive = { PARTITION_FAT32_XINT13 }; + bRet = DeviceIoControl(hDevice, IOCTL_DISK_SET_PARTITION_INFO, &spiDrive, sizeof(spiDrive), NULL, 0, &cbRet, NULL); + + if (!bRet) + { + // This happens because the drive is a Super Floppy + // i.e. with no partition table. Disk.sys creates a PARTITION_INFORMATION + // record spanning the whole disk and then fails requests to set the + // partition info since it's not actually stored on disk. + // So only complain if there really is a partition table to set + if (piDrive.HiddenSectors) + die("Failed to set parition info"); + } + } + + bRet = DeviceIoControl(hDevice, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &cbRet, NULL); + + if (!bRet) + die("Failed to dismount device"); + + bRet = DeviceIoControl(hDevice, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &cbRet, NULL); + + if (!bRet) + die("Failed to unlock device"); + + CloseHandle(hDevice); + + puts("Done"); + + return TRUE; +} + +[[noreturn]] +void usage(void) +{ + puts( + "Usage Fat32Format [-cN] [-lLABEL] [-p] [-y] " R"({ C: | \\.\C: | \\?\Volume{GUID} })" "\n" + "Erase all data on specified volume, format it for FAT32\n" + "\n" + " -c Specify a cluster size by sector count.\n" + " Accepts 1, 2, 4, 8, 16, 32, 64, 128\n" + " EXAMPLE: Fat32Format -c4 X: - use 4 sectors per cluster\n" + " -l Specify volume label.\n" + " If exceeds 11-bytes, truncate label.\n" + " -p Make immutable AUTORUN.INF on root directory.\n" + " This file cannot do anything on Windows.\n" + "\n" + "Modified Version see https://github.com/0xbadfca11/fat32format \n" + "\n" + "Original Version 1.07, see http://www.ridgecrop.demon.co.uk/fat32format.htm \n" + "This software is covered by the GPL \n" + "Use with care - Ridgecrop are not liable for data lost using this tool" + ); + exit(EXIT_FAILURE); +} + +int main(int argc, char* argv[]) +{ + if (const FARPROC SetDefaultDllDirectoriesPtr = GetProcAddress(GetModuleHandleW(L"kernel32"), "SetDefaultDllDirectories")) + { + reinterpret_cast(SetDefaultDllDirectoriesPtr)(LOAD_LIBRARY_SEARCH_SYSTEM32); + } + + if (argc < 2) + { + usage(); + } + + PCSTR volume_argv = nullptr; + format_params p; + for (int i = 1; i < argc; i++) + { + if (argv[i][0] == '-' || argv[i][0] == '/') + { + switch (argv[i][1]) + { + case 'c': + if (strlen(argv[i]) >= 3) + { + p.sectors_per_cluster = atol(&argv[i][2]); + if ((p.sectors_per_cluster & (p.sectors_per_cluster - 1)) != 0 || p.sectors_per_cluster > 128) + { + printf("Ignoring bad cluster size %d\n", p.sectors_per_cluster); + p.sectors_per_cluster = 0; + } + } + else + { + usage(); + } + break; + case 'l': + size_t len; + if ((len = strlen(argv[i])) >= 3) + { + switch (strncpy_s(p.volume_label, &argv[i][2], _TRUNCATE)) + { + case 0: + break; + case STRUNCATE: + puts("Warning Volume label too long. Truncate volume label."); + break; + default: + perror("strncpy_s"); + exit(EXIT_FAILURE); + } + if (p.volume_label[0] == '\xE5') + { + puts("Warning Volume label started with 0xE5. Available until unmount."); + } + } + else + { + usage(); + } + break; + case 'p': + if (strcmp(argv[i], "-p") != 0) + { + usage(); + } + p.make_protected_autorun = true; + break; + case 'y': + if (strcmp(argv[i], "-y") != 0) + { + usage(); + } + p.all_yes = true; + break; + case '?': + usage(); + break; + default: + printf("bad flag '-%c'\n", argv[i][1]); + usage(); + break; + } + } + else + { + if (volume_argv) + { + usage(); + } + volume_argv = argv[i]; + } + } + if (!volume_argv) + { + usage(); + } + + if (strncmp(volume_argv, R"(\\?\Volume{)", 11) == 0) + { + char volume_guid[50]; + size_t pos; + + strcpy_s(volume_guid, volume_argv); + pos = strlen(volume_guid) - 1; + if (volume_guid[pos] == '\\') + { + volume_guid[pos] = '\0'; + } + format_volume(volume_guid, &p); + strcat_s(volume_guid, "\\"); + if (!SetVolumeLabelA(volume_guid, p.volume_label)) + { + die("Failed to set volume label"); + } + } + else + { + char volume[8] = R"(\\.\?:)"; + if (strlen(volume_argv) == 2 && isalpha(volume_argv[0]) && volume_argv[1] == ':') + { + volume[4] = volume_argv[0]; + } + else if (strlen(volume_argv) == 6 && strncmp(volume_argv, R"(\\.\)", 4) == 0 && isalpha(volume_argv[4]) && volume_argv[5] == ':') + { + volume[4] = volume_argv[4]; + } + else + { + usage(); + } + format_volume(volume, &p); + strcat_s(volume, "\\"); + if (!SetVolumeLabelA(volume, p.volume_label)) + { + die("Failed to set volume label"); + } + } +} diff --git a/dependencies/fat32format/fat32format.sln b/dependencies/fat32format/fat32format.sln new file mode 100644 index 0000000..1fd915b --- /dev/null +++ b/dependencies/fat32format/fat32format.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28306.52 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fat32format", "fat32format.vcxproj", "{568C331C-2776-4EE1-A2C6-CEDF11F5D4E5}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {568C331C-2776-4EE1-A2C6-CEDF11F5D4E5}.Debug|x86.ActiveCfg = Debug|Win32 + {568C331C-2776-4EE1-A2C6-CEDF11F5D4E5}.Debug|x86.Build.0 = Debug|Win32 + {568C331C-2776-4EE1-A2C6-CEDF11F5D4E5}.Release|x86.ActiveCfg = Release|Win32 + {568C331C-2776-4EE1-A2C6-CEDF11F5D4E5}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {ECA92B69-47F1-4204-8D02-F620DE37D5F3} + EndGlobalSection +EndGlobal diff --git a/dependencies/fat32format/fat32format.vcxproj b/dependencies/fat32format/fat32format.vcxproj new file mode 100644 index 0000000..5d6ed2d --- /dev/null +++ b/dependencies/fat32format/fat32format.vcxproj @@ -0,0 +1,91 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {568C331C-2776-4EE1-A2C6-CEDF11F5D4E5} + 10.0.16299.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + Unicode + + + + + + + + + + + + + true + + + false + + + + Level4 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + true + true + true + stdcpp17 + + + Console + true + + + + + Level4 + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + true + false + Guard + MultiThreaded + NoExtensions + true + stdcpp17 + + + Console + true + true + true + true + 5.1 + /PDBALTPATH:%_PDB% /DEPENDENTLOADFLAG:0x800 %(AdditionalOptions) + + + + + + + + + \ No newline at end of file diff --git a/dependencies/fat32format/fat32format.vcxproj.filters b/dependencies/fat32format/fat32format.vcxproj.filters new file mode 100644 index 0000000..88e7b61 --- /dev/null +++ b/dependencies/fat32format/fat32format.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {bd9de17c-6753-4b74-88c1-053ae3e4be54} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {a8723b2b-074a-4151-b954-d9e358891d00} + h;hpp;hxx;hm;inl + + + {073cca14-a20b-4658-af2c-34be74fe99f6} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + Source Files + + + \ No newline at end of file diff --git a/dependencies/libarchive-3.4.2/CMakeLists.txt b/dependencies/libarchive-3.4.2/CMakeLists.txt new file mode 100644 index 0000000..5a9b325 --- /dev/null +++ b/dependencies/libarchive-3.4.2/CMakeLists.txt @@ -0,0 +1,2046 @@ +# +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12 FATAL_ERROR) +if(POLICY CMP0074) + cmake_policy(SET CMP0074 NEW) #3.12.0 `find_package()`` uses ``_ROOT`` variables. +endif() +# +PROJECT(libarchive C) +# +SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build/cmake") +if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${libarchive_BINARY_DIR}/bin) +endif() +# +# Set the Build type for make based generators. +# You can choose following types: +# Debug : Debug build +# Release : Release build +# RelWithDebInfo : Release build with Debug Info +# MinSizeRel : Release Min Size build +IF(NOT CMAKE_BUILD_TYPE) + SET(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build Type" FORCE) +ENDIF(NOT CMAKE_BUILD_TYPE) +# Set a value type to properly display CMAKE_BUILD_TYPE on GUI if the +# value type is "UNINITIALIZED". +GET_PROPERTY(cached_type CACHE CMAKE_BUILD_TYPE PROPERTY TYPE) +IF("${cached_type}" STREQUAL "UNINITIALIZED") + SET(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING "Build Type" FORCE) +ENDIF("${cached_type}" STREQUAL "UNINITIALIZED") +# Check the Build Type. +IF(NOT "${CMAKE_BUILD_TYPE}" + MATCHES "^(Debug|Release|RelWithDebInfo|MinSizeRel)\$") + MESSAGE(FATAL_ERROR + "Unknown keyword for CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}\n" + "Acceptable keywords: Debug,Release,RelWithDebInfo,MinSizeRel") +ENDIF(NOT "${CMAKE_BUILD_TYPE}" + MATCHES "^(Debug|Release|RelWithDebInfo|MinSizeRel)\$") + +# On MacOS, prefer MacPorts libraries to system libraries. +# I haven't come up with a compelling argument for this to be conditional. +list(APPEND CMAKE_PREFIX_PATH /opt/local) +# Enable @rpath in the install name. +# detail in "cmake --help-policy CMP0042" +SET(CMAKE_MACOSX_RPATH ON) + +# +# Version - read from 'version' file. +# +FILE(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/build/version _version) +STRING(REGEX REPLACE + "^([0-9])[0-9][0-9][0-9][0-9][0-9][0-9][a-z]*$" "\\1" _major ${_version}) +STRING(REGEX REPLACE + "^[0-9]([0-9][0-9][0-9])[0-9][0-9][0-9][a-z]*$" "\\1" _minor ${_version}) +STRING(REGEX REPLACE + "^[0-9][0-9][0-9][0-9]([0-9][0-9][0-9])[a-z]*$" "\\1" _revision ${_version}) +STRING(REGEX REPLACE + "^[0-9][0-9][0-9][0-9][0-9][0-9][0-9]([a-z]*)$" "\\1" _quality ${_version}) +SET(_version_number ${_major}${_minor}${_revision}) +STRING(REGEX REPLACE "[0]*([^0]*[0-9])$" "\\1" _trimmed_minor ${_minor}) +STRING(REGEX REPLACE "[0]*([^0]*[0-9])$" "\\1" _trimmed_revision ${_revision}) +# +SET(VERSION "${_major}.${_trimmed_minor}.${_trimmed_revision}${_quality}") +SET(BSDCPIO_VERSION_STRING "${VERSION}") +SET(BSDTAR_VERSION_STRING "${VERSION}") +SET(BSDCAT_VERSION_STRING "${VERSION}") +SET(LIBARCHIVE_VERSION_NUMBER "${_version_number}") +SET(LIBARCHIVE_VERSION_STRING "${VERSION}") + +# INTERFACE_VERSION increments with every release +# libarchive 2.7 == interface version 9 = 2 + 7 +# libarchive 2.8 == interface version 10 = 2 + 8 +# libarchive 2.9 == interface version 11 = 2 + 9 +# libarchive 3.0 == interface version 12 +# libarchive 3.1 == interface version 13 +math(EXPR INTERFACE_VERSION "13 + ${_minor}") + +# Set SOVERSION == Interface version +# ?? Should there be more here ?? +SET(SOVERSION "${INTERFACE_VERSION}") + +# Enalbe CMAKE_PUSH_CHECK_STATE() and CMAKE_POP_CHECK_STATE() macros +# saving and restoring the state of the variables. +INCLUDE(CMakePushCheckState) + +# Initialize the state of the variables. This initialization is not +# necessary but this shows you what value the variables initially have. +SET(CMAKE_REQUIRED_DEFINITIONS) +SET(CMAKE_REQUIRED_INCLUDES) +SET(CMAKE_REQUIRED_LIBRARIES) +SET(CMAKE_REQUIRED_FLAGS) +if (CMAKE_BUILD_TYPE STREQUAL "Debug") + OPTION(ENABLE_WERROR "Treat warnings as errors - default is ON for Debug, OFF otherwise." ON) +else () + OPTION(ENABLE_WERROR "Treat warnings as errors - default is ON for Debug, OFF otherwise." OFF) +endif () + +# Especially for early development, we want to be a little +# aggressive about diagnosing build problems; this can get +# relaxed somewhat in final shipping versions. +IF (CMAKE_C_COMPILER_ID MATCHES "^GNU$") + SET(CMAKE_REQUIRED_FLAGS "-Wall -Wformat -Wformat-security") + ################################################################# + # Set compile flags for all build types. + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wformat -Wformat-security") + if (ENABLE_WERROR) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") + endif () + ################################################################# + # Set compile flags for debug build. + # This is added into CMAKE_C_FLAGS when CMAKE_BUILD_TYPE is "Debug" + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wextra") + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wunused") + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wshadow") + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wmissing-prototypes") + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wcast-qual") +ENDIF (CMAKE_C_COMPILER_ID MATCHES "^GNU$") +IF (CMAKE_C_COMPILER_ID MATCHES "^Clang$") + SET(CMAKE_REQUIRED_FLAGS "-Wall -Wformat -Wformat-security") + ################################################################# + # Set compile flags for all build types. + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wformat -Wformat-security") + if (ENABLE_WERROR) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") + endif () + ################################################################# + # Set compile flags for debug build. + # This is added into CMAKE_C_FLAGS when CMAKE_BUILD_TYPE is "Debug" + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g") + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wextra") + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wunused") + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wshadow") + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wmissing-prototypes") + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wcast-qual") +ENDIF (CMAKE_C_COMPILER_ID MATCHES "^Clang$") +IF (CMAKE_C_COMPILER_ID MATCHES "^XL$") + SET(CMAKE_C_COMPILER "xlc_r") + SET(CMAKE_REQUIRED_FLAGS "-qflag=e:e -qformat=sec") + ################################################################# + # Set compile flags for all build types. + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -qflag=e:e -qformat=sec") + if (ENABLE_WERROR) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -qhalt=w") + endif () + ################################################################# + # Set compile flags for debug build. + # This is added into CMAKE_C_FLAGS when CMAKE_BUILD_TYPE is "Debug" + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g") + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -qflag=w:w") + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -qinfo=pro:use") +ENDIF(CMAKE_C_COMPILER_ID MATCHES "^XL$") +IF (MSVC) + if (ENABLE_WERROR) + # /WX option is the same as gcc's -Werror option. + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX") + endif () + ################################################################# + # Set compile flags for debug build. + # This is added into CMAKE_C_FLAGS when CMAKE_BUILD_TYPE is "Debug" + # Enable level 4 C4062: The enumerate has no associated handler in a switch + # statement and there is no default that can catch it. + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4062") + # Enable level 4 C4254: A larger bit field was assigned to a smaller bit + # field. + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4254") + # Enable level 4 C4295: An array was initialized but the last character in + # the array is not a null; accessing the array may + # produce unexpected results. + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4295") + # Enable level 4 C4296: An unsigned variable was used in a comparison + # operation with zero. + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4296") + # Enable level 4 C4389: An operation involved signed and unsigned variables. + # This could result in a loss of data. + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4389") + # Enable level 4 C4505: The given function is local and not referenced in + # the body of the module; therefore, the function is + # dead code. + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4505") + # Enable level 4 C4514: The optimizer removed an inline function that is not + # called. + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4514") + # Enable level 4 C4702: Unreachable code. + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4702") + # Enable level 4 C4706: The test value in a conditional expression was the + # result of an assignment. + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4706") + # /Oi option enables built-in functions. + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Oi") + ################################################################# + # Set compile flags for release build. + SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Oi") +ENDIF (MSVC) + +# Enable CTest/CDash support +include(CTest) + +OPTION(ENABLE_MBEDTLS "Enable use of mbed TLS" OFF) +OPTION(ENABLE_NETTLE "Enable use of Nettle" OFF) +OPTION(ENABLE_OPENSSL "Enable use of OpenSSL" ON) +OPTION(ENABLE_LIBB2 "Enable the use of the system LIBB2 library if found" ON) +OPTION(ENABLE_LZ4 "Enable the use of the system LZ4 library if found" ON) +OPTION(ENABLE_LZO "Enable the use of the system LZO library if found" OFF) +OPTION(ENABLE_LZMA "Enable the use of the system LZMA library if found" ON) +OPTION(ENABLE_ZSTD "Enable the use of the system zstd library if found" ON) + +OPTION(ENABLE_ZLIB "Enable the use of the system ZLIB library if found" ON) +OPTION(ENABLE_BZip2 "Enable the use of the system BZip2 library if found" ON) +OPTION(ENABLE_LIBXML2 "Enable the use of the system libxml2 library if found" ON) +OPTION(ENABLE_EXPAT "Enable the use of the system EXPAT library if found" ON) +OPTION(ENABLE_PCREPOSIX "Enable the use of the system PCREPOSIX library if found" ON) +OPTION(ENABLE_LibGCC "Enable the use of the system LibGCC library if found" ON) +# CNG is used for encrypt/decrypt Zip archives on Windows. +OPTION(ENABLE_CNG "Enable the use of CNG(Crypto Next Generation)" ON) + +OPTION(ENABLE_TAR "Enable tar building" ON) +OPTION(ENABLE_TAR_SHARED "Enable dynamic build of tar" FALSE) +OPTION(ENABLE_CPIO "Enable cpio building" ON) +OPTION(ENABLE_CPIO_SHARED "Enable dynamic build of cpio" FALSE) +OPTION(ENABLE_CAT "Enable cat building" ON) +OPTION(ENABLE_CAT_SHARED "Enable dynamic build of cat" FALSE) +OPTION(ENABLE_XATTR "Enable extended attribute support" ON) +OPTION(ENABLE_ACL "Enable ACL support" ON) +OPTION(ENABLE_ICONV "Enable iconv support" ON) +OPTION(ENABLE_TEST "Enable unit and regression tests" ON) +OPTION(ENABLE_COVERAGE "Enable code coverage (GCC only, automatically sets ENABLE_TEST to ON)" FALSE) +OPTION(ENABLE_INSTALL "Enable installing of libraries" ON) + +SET(POSIX_REGEX_LIB "AUTO" CACHE STRING "Choose what library should provide POSIX regular expression support") +SET(ENABLE_SAFESEH "AUTO" CACHE STRING "Enable use of /SAFESEH linker flag (MSVC only)") +SET(WINDOWS_VERSION "WIN7" CACHE STRING "Set Windows version to use (Windows only)") + +IF(ENABLE_COVERAGE) + include(LibarchiveCodeCoverage) +ENDIF(ENABLE_COVERAGE) + +IF(ENABLE_TEST) + ENABLE_TESTING() +ENDIF(ENABLE_TEST) + +IF(WIN32) + IF(WINDOWS_VERSION STREQUAL "WIN8") + SET(NTDDI_VERSION 0x06020000) + SET(_WIN32_WINNT 0x0602) + SET(WINVER 0x0602) + ELSEIF(WINDOWS_VERSION STREQUAL "WIN7") + SET(NTDDI_VERSION 0x06010000) + SET(_WIN32_WINNT 0x0601) + SET(WINVER 0x0601) + ELSEIF(WINDOWS_VERSION STREQUAL "WS08") + SET(NTDDI_VERSION 0x06000100) + SET(_WIN32_WINNT 0x0600) + SET(WINVER 0x0600) + ELSEIF(WINDOWS_VERSION STREQUAL "VISTA") + SET(NTDDI_VERSION 0x06000000) + SET(_WIN32_WINNT 0x0600) + SET(WINVER 0x0600) + ELSEIF(WINDOWS_VERSION STREQUAL "WS03") + SET(NTDDI_VERSION 0x05020000) + SET(_WIN32_WINNT 0x0502) + SET(WINVER 0x0502) + ELSEIF(WINDOWS_VERSION STREQUAL "WINXP") + SET(NTDDI_VERSION 0x05010000) + SET(_WIN32_WINNT 0x0501) + SET(WINVER 0x0501) + ELSE(WINDOWS_VERSION STREQUAL "WIN8") + # Default to Windows Server 2003 API if we don't recognize the specifier + SET(NTDDI_VERSION 0x05020000) + SET(_WIN32_WINNT 0x0502) + SET(WINVER 0x0502) + ENDIF(WINDOWS_VERSION STREQUAL "WIN8") +ENDIF(WIN32) + +IF(MSVC) + IF(ENABLE_SAFESEH STREQUAL "YES") + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH") + SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH") + SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH") + SET(ENV{LDFLAGS} "$ENV{LDFLAGS} /SAFESEH") + ELSEIF(ENABLE_SAFESEH STREQUAL "NO") + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO") + SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO") + SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO") + SET(ENV{LDFLAGS} "$ENV{LDFLAGS} /SAFESEH:NO") + ENDIF(ENABLE_SAFESEH STREQUAL "YES") +ENDIF(MSVC) + +IF("${CMAKE_C_PLATFORM_ID}" MATCHES "^(HP-UX)$") + ADD_DEFINITIONS(-D_XOPEN_SOURCE=500) # Ask wchar.h for mbstate_t +ENDIF() + +IF(MINGW) + ADD_DEFINITIONS(-D__USE_MINGW_ANSI_STDIO) +ENDIF() + +# +INCLUDE(CheckCSourceCompiles) +INCLUDE(CheckCSourceRuns) +INCLUDE(CheckFileOffsetBits) +INCLUDE(CheckFuncs) +INCLUDE(CheckHeaderDirent) +INCLUDE(CheckIncludeFile) +INCLUDE(CheckIncludeFiles) +INCLUDE(CheckLibraryExists) +INCLUDE(CheckStructHasMember) +INCLUDE(CheckSymbolExists) +INCLUDE(CheckTypeExists) +INCLUDE(CheckTypeSize) + +# +# Generate list.h +# +MACRO (GENERATE_LIST_H _listfile _cmlist __list_sources) + SET(_argv ${ARGV}) + # Remove _listfile and _cmlist from _argv + LIST(REMOVE_AT _argv 0 1) + IF (NOT EXISTS "${_listfile}" OR + ${_cmlist} IS_NEWER_THAN "${_listfile}") + + MESSAGE(STATUS "Generating ${_listfile}") + FILE(WRITE ${_listfile} "") + FOREACH (testfile ${_argv}) + IF (testfile MATCHES "^test_[^/]+[.]c$") + FILE(STRINGS ${testfile} testvar REGEX "^DEFINE_TEST") + FOREACH (deftest ${testvar}) + FILE(APPEND ${_listfile} "${deftest}\n") + ENDFOREACH (deftest) + ENDIF (testfile MATCHES "^test_[^/]+[.]c$") + ENDFOREACH (testfile) + + ENDIF (NOT EXISTS "${_listfile}" OR + ${_cmlist} IS_NEWER_THAN "${_listfile}") +ENDMACRO (GENERATE_LIST_H) +# +# Generate installation rules for man pages. +# +MACRO (INSTALL_MAN __mans) + FOREACH (_man ${ARGV}) + STRING(REGEX REPLACE "^.+[.]([1-9])" "\\1" _mansect ${_man}) + INSTALL(FILES ${_man} DESTINATION "share/man/man${_mansect}") + ENDFOREACH (_man) +ENDMACRO (INSTALL_MAN __mans) +# +# Find out what macro is needed to use libraries on Windows. +# +MACRO (TRY_MACRO_FOR_LIBRARY INCLUDES LIBRARIES + TRY_TYPE SAMPLE_SOURCE MACRO_LIST) + IF(WIN32 AND NOT CYGWIN) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables + SET(CMAKE_REQUIRED_INCLUDES ${INCLUDES}) + SET(CMAKE_REQUIRED_LIBRARIES ${LIBRARIES}) + FOREACH(VAR ${MACRO_LIST}) + # Clear ${VAR} from CACHE If the libraries which ${VAR} was + # checked with are changed. + SET(VAR_WITH_LIB "${VAR}_WITH_LIB") + GET_PROPERTY(PREV_VAR_WITH_LIB VARIABLE PROPERTY ${VAR_WITH_LIB}) + IF(NOT "${PREV_VAR_WITH_LIB}" STREQUAL "${LIBRARIES}") + UNSET(${VAR} CACHE) + ENDIF(NOT "${PREV_VAR_WITH_LIB}" STREQUAL "${LIBRARIES}") + # Check if the library can be used with the macro. + IF("${TRY_TYPE}" MATCHES "COMPILES") + CHECK_C_SOURCE_COMPILES("${SAMPLE_SOURCE}" ${VAR}) + ELSEIF("${TRY_TYPE}" MATCHES "RUNS") + CHECK_C_SOURCE_RUNS("${SAMPLE_SOURCE}" ${VAR}) + ELSE("${TRY_TYPE}" MATCHES "COMPILES") + MESSAGE(FATAL_ERROR "UNKNOWN KEYWORD \"${TRY_TYPE}\" FOR TRY_TYPE") + ENDIF("${TRY_TYPE}" MATCHES "COMPILES") + # Save the libraries which ${VAR} is checked with. + SET(${VAR_WITH_LIB} "${LIBRARIES}" CACHE INTERNAL + "Macro ${VAR} is checked with") + ENDFOREACH(VAR) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables + ENDIF(WIN32 AND NOT CYGWIN) +ENDMACRO (TRY_MACRO_FOR_LIBRARY) +# +# Check compress/decompress libraries +# +IF(WIN32 AND NOT CMAKE_CL_64 AND NOT CYGWIN) + # GnuWin32 is only for Win32, not Win64. + SET(__GNUWIN32PATH "C:/Program Files/GnuWin32") +ENDIF(WIN32 AND NOT CMAKE_CL_64 AND NOT CYGWIN) +IF(DEFINED __GNUWIN32PATH AND EXISTS "${__GNUWIN32PATH}") + # You have to add a path availabel DLL file into PATH environment variable. + # Maybe DLL path is "C:/Program Files/GnuWin32/bin". + # The zlib and the bzip2 Setup program have installed programs and DLLs into + # "C:/Program Files/GnuWin32" by default. + # This is convenience setting for Windows. + SET(CMAKE_PREFIX_PATH ${__GNUWIN32PATH} $(CMAKE_PREFIX_PATH)) + # + # If you didn't use Setup program or installed into nonstandard path, + # cmake cannot find out your zlib or bzip2 libraries and include files, + # you should execute cmake with -DCMAKE_PREFIX_PATH option. + # e.g. + # cmake -DCMAKE_PREFIX_PATH= + # + # If compiling error occurred in zconf.h, You may need patch to zconf.h. + #--- zconf.h.orig 2005-07-21 00:40:26.000000000 + #+++ zconf.h 2009-01-19 11:39:10.093750000 + #@@ -286,7 +286,7 @@ + # + # #if 1 /* HAVE_UNISTD_H -- this line is updated by ./configure */ + # # include /* for off_t */ + #-# include /* for SEEK_* and off_t */ + #+# include /* for SEEK_* and off_t */ + # # ifdef VMS + # # include /* for off_t */ + # # endif +ENDIF(DEFINED __GNUWIN32PATH AND EXISTS "${__GNUWIN32PATH}") + +SET(ADDITIONAL_LIBS "") +# +# Find ZLIB +# +IF(ENABLE_ZLIB) + FIND_PACKAGE(ZLIB) +ELSE() + SET(ZLIB_FOUND FALSE) # Override cached value +ENDIF() +IF(ZLIB_FOUND) + SET(HAVE_LIBZ 1) + SET(HAVE_ZLIB_H 1) + INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${ZLIB_LIBRARIES}) + IF(WIN32 AND NOT CYGWIN) + # + # Test if ZLIB_WINAPI macro is needed to use. + # + TRY_MACRO_FOR_LIBRARY( + "${ZLIB_INCLUDE_DIR}" "${ZLIB_LIBRARIES}" + RUNS + "#include \nint main() {uLong f = zlibCompileFlags(); return (f&(1U<<10))?0:-1; }" + ZLIB_WINAPI) + IF(ZLIB_WINAPI) + ADD_DEFINITIONS(-DZLIB_WINAPI) + ELSE(ZLIB_WINAPI) + # Test if a macro is needed for the library. + TRY_MACRO_FOR_LIBRARY( + "${ZLIB_INCLUDE_DIR}" "${ZLIB_LIBRARIES}" + COMPILES + "#include \nint main() {return zlibVersion()?1:0; }" + "ZLIB_DLL;WITHOUT_ZLIB_DLL") + IF(ZLIB_DLL) + ADD_DEFINITIONS(-DZLIB_DLL) + ENDIF(ZLIB_DLL) + ENDIF(ZLIB_WINAPI) + ENDIF(WIN32 AND NOT CYGWIN) +ENDIF(ZLIB_FOUND) +MARK_AS_ADVANCED(CLEAR ZLIB_INCLUDE_DIR) +MARK_AS_ADVANCED(CLEAR ZLIB_LIBRARY) +# +# Find BZip2 +# +IF(ENABLE_BZip2) + FIND_PACKAGE(BZip2) +ELSE() + SET(BZIP2_FOUND FALSE) # Override cached value +ENDIF() +IF(BZIP2_FOUND) + SET(HAVE_LIBBZ2 1) + SET(HAVE_BZLIB_H 1) + INCLUDE_DIRECTORIES(${BZIP2_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${BZIP2_LIBRARIES}) + # Test if a macro is needed for the library. + TRY_MACRO_FOR_LIBRARY( + "${BZIP2_INCLUDE_DIR}" "${BZIP2_LIBRARIES}" + COMPILES + "#include \nint main() {return BZ2_bzlibVersion()?1:0; }" + "USE_BZIP2_DLL;USE_BZIP2_STATIC") + IF(USE_BZIP2_DLL) + ADD_DEFINITIONS(-DUSE_BZIP2_DLL) + ELSEIF(USE_BZIP2_STATIC) + ADD_DEFINITIONS(-DUSE_BZIP2_STATIC) + ENDIF(USE_BZIP2_DLL) +ENDIF(BZIP2_FOUND) +MARK_AS_ADVANCED(CLEAR BZIP2_INCLUDE_DIR) +MARK_AS_ADVANCED(CLEAR BZIP2_LIBRARIES) + + +# +# Find LZMA +# +IF(ENABLE_LZMA) + FIND_PACKAGE(LibLZMA) +ELSE() + SET(LIBLZMA_FOUND FALSE) # Override cached value +ENDIF() + +IF(LIBLZMA_FOUND) + SET(HAVE_LIBLZMA 1) + SET(HAVE_LZMA_H 1) + CMAKE_PUSH_CHECK_STATE() + SET(CMAKE_REQUIRED_INCLUDES ${LIBLZMA_INCLUDE_DIR}) + SET(CMAKE_REQUIRED_LIBRARIES ${LIBLZMA_LIBRARIES}) + INCLUDE_DIRECTORIES(${LIBLZMA_INCLUDE_DIRS}) + LIST(APPEND ADDITIONAL_LIBS ${LIBLZMA_LIBRARIES}) + # Test if a macro is needed for the library. + TRY_MACRO_FOR_LIBRARY( + "${LIBLZMA_INCLUDE_DIRS}" "${LIBLZMA_LIBRARIES}" + COMPILES + "#include \nint main() {return (int)lzma_version_number(); }" + "WITHOUT_LZMA_API_STATIC;LZMA_API_STATIC") + IF(NOT WITHOUT_LZMA_API_STATIC AND LZMA_API_STATIC) + ADD_DEFINITIONS(-DLZMA_API_STATIC) + ENDIF(NOT WITHOUT_LZMA_API_STATIC AND LZMA_API_STATIC) + CMAKE_POP_CHECK_STATE() +ELSE(LIBLZMA_FOUND) +# LZMA not found and will not be used. +ENDIF(LIBLZMA_FOUND) +MARK_AS_ADVANCED(CLEAR LIBLZMA_INCLUDE_DIR) +MARK_AS_ADVANCED(CLEAR LIBLZMA_LIBRARY) + +# +# Find LZO2 +# +IF(ENABLE_LZO) + IF (LZO2_INCLUDE_DIR) + # Already in cache, be silent + SET(LZO2_FIND_QUIETLY TRUE) + ENDIF (LZO2_INCLUDE_DIR) + + FIND_PATH(LZO2_INCLUDE_DIR lzo/lzoconf.h) + FIND_LIBRARY(LZO2_LIBRARY NAMES lzo2 liblzo2) + INCLUDE(FindPackageHandleStandardArgs) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZO2 DEFAULT_MSG LZO2_LIBRARY LZO2_INCLUDE_DIR) +ELSE(ENABLE_LZO) + SET(LZO2_FOUND FALSE) # Override cached value +ENDIF(ENABLE_LZO) +IF(LZO2_FOUND) + SET(HAVE_LIBLZO2 1) + SET(HAVE_LZO_LZOCONF_H 1) + SET(HAVE_LZO_LZO1X_H 1) + INCLUDE_DIRECTORIES(${LZO2_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${LZO2_LIBRARY}) + # + # TODO: test for static library. + # +ENDIF(LZO2_FOUND) +MARK_AS_ADVANCED(CLEAR LZO2_INCLUDE_DIR) +MARK_AS_ADVANCED(CLEAR LZO2_LIBRARY) +# +# Find libb2 +# +IF(ENABLE_LIBB2) + IF (LIBB2_INCLUDE_DIR) + # Already in cache, be silent + SET(LIBB2_FIND_QUIETLY TRUE) + ENDIF (LIBB2_INCLUDE_DIR) + + FIND_PATH(LIBB2_INCLUDE_DIR blake2.h) + FIND_LIBRARY(LIBB2_LIBRARY NAMES b2 libb2) + INCLUDE(FindPackageHandleStandardArgs) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBB2 DEFAULT_MSG LIBB2_LIBRARY LIBB2_INCLUDE_DIR) +ELSE(ENABLE_LIBB2) + SET(LIBB2_FOUND FALSE) # Override cached value +ENDIF(ENABLE_LIBB2) +IF(LIBB2_FOUND) + SET(HAVE_LIBB2 1) + SET(HAVE_BLAKE2_H 1) + SET(ARCHIVE_BLAKE2 FALSE) + LIST(APPEND ADDITIONAL_LIBS ${LIBB2_LIBRARY}) + CMAKE_PUSH_CHECK_STATE() + SET(CMAKE_REQUIRED_LIBRARIES ${LIBB2_LIBRARY}) + SET(CMAKE_REQUIRED_INCLUDES ${LIBB2_INCLUDE_DIR}) + CHECK_FUNCTION_EXISTS(blake2sp_init HAVE_LIBB2) + CMAKE_POP_CHECK_STATE() +ELSE(LIBB2_FOUND) + SET(ARCHIVE_BLAKE2 TRUE) +ENDIF(LIBB2_FOUND) +# +# Find LZ4 +# +IF(ENABLE_LZ4) + IF (LZ4_INCLUDE_DIR) + # Already in cache, be silent + SET(LZ4_FIND_QUIETLY TRUE) + ENDIF (LZ4_INCLUDE_DIR) + + FIND_PATH(LZ4_INCLUDE_DIR lz4.h) + FIND_LIBRARY(LZ4_LIBRARY NAMES lz4 liblz4) + INCLUDE(FindPackageHandleStandardArgs) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZ4 DEFAULT_MSG LZ4_LIBRARY LZ4_INCLUDE_DIR) +ELSE(ENABLE_LZ4) + SET(LZ4_FOUND FALSE) # Override cached value +ENDIF(ENABLE_LZ4) +IF(LZ4_FOUND) + SET(HAVE_LIBLZ4 1) + SET(HAVE_LZ4_H 1) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables + SET(CMAKE_REQUIRED_INCLUDES ${LZ4_INCLUDE_DIR}) + CHECK_INCLUDE_FILES("lz4hc.h" HAVE_LZ4HC_H) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables + INCLUDE_DIRECTORIES(${LZ4_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${LZ4_LIBRARY}) + # + # TODO: test for static library. + # +ENDIF(LZ4_FOUND) +MARK_AS_ADVANCED(CLEAR LZ4_INCLUDE_DIR) +MARK_AS_ADVANCED(CLEAR LZ4_LIBRARY) +# +# Find Zstd +# +IF(ENABLE_ZSTD) + IF (ZSTD_INCLUDE_DIR) + # Already in cache, be silent + SET(ZSTD_FIND_QUIETLY TRUE) + ENDIF (ZSTD_INCLUDE_DIR) + + FIND_PATH(ZSTD_INCLUDE_DIR zstd.h) + FIND_LIBRARY(ZSTD_LIBRARY NAMES zstd libzstd) + INCLUDE(FindPackageHandleStandardArgs) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(ZSTD DEFAULT_MSG ZSTD_LIBRARY ZSTD_INCLUDE_DIR) +ELSE(ENABLE_ZSTD) + SET(ZSTD_FOUND FALSE) # Override cached value +ENDIF(ENABLE_ZSTD) +IF(ZSTD_FOUND) + SET(HAVE_ZSTD_H 1) + INCLUDE_DIRECTORIES(${ZSTD_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${ZSTD_LIBRARY}) + CMAKE_PUSH_CHECK_STATE() + SET(CMAKE_REQUIRED_LIBRARIES ${ZSTD_LIBRARY}) + SET(CMAKE_REQUIRED_INCLUDES ${ZSTD_INCLUDE_DIR}) + CHECK_FUNCTION_EXISTS(ZSTD_compressStream HAVE_LIBZSTD) + # + # TODO: test for static library. + # + CMAKE_POP_CHECK_STATE() +ENDIF(ZSTD_FOUND) +MARK_AS_ADVANCED(CLEAR ZSTD_INCLUDE_DIR) +MARK_AS_ADVANCED(CLEAR ZSTD_LIBRARY) + + +# +# Check headers +# +CHECK_HEADER_DIRENT() + +SET(INCLUDES "") +MACRO (LA_CHECK_INCLUDE_FILE header var) + CHECK_INCLUDE_FILES("${INCLUDES};${header}" ${var}) + IF (${var}) + SET(INCLUDES ${INCLUDES} ${header}) + ENDIF (${var}) +ENDMACRO (LA_CHECK_INCLUDE_FILE) + +# Some FreeBSD headers assume sys/types.h was already included. +LA_CHECK_INCLUDE_FILE("sys/types.h" HAVE_SYS_TYPES_H) + +# Alphabetize the rest unless there's a compelling reason +LA_CHECK_INCLUDE_FILE("acl/libacl.h" HAVE_ACL_LIBACL_H) +LA_CHECK_INCLUDE_FILE("attr/xattr.h" HAVE_ATTR_XATTR_H) +LA_CHECK_INCLUDE_FILE("ctype.h" HAVE_CTYPE_H) +LA_CHECK_INCLUDE_FILE("copyfile.h" HAVE_COPYFILE_H) +LA_CHECK_INCLUDE_FILE("direct.h" HAVE_DIRECT_H) +LA_CHECK_INCLUDE_FILE("dlfcn.h" HAVE_DLFCN_H) +LA_CHECK_INCLUDE_FILE("errno.h" HAVE_ERRNO_H) +LA_CHECK_INCLUDE_FILE("ext2fs/ext2_fs.h" HAVE_EXT2FS_EXT2_FS_H) + +CHECK_C_SOURCE_COMPILES("#include +#include +int main(void) { return EXT2_IOC_GETFLAGS; }" HAVE_WORKING_EXT2_IOC_GETFLAGS) + +LA_CHECK_INCLUDE_FILE("fcntl.h" HAVE_FCNTL_H) +LA_CHECK_INCLUDE_FILE("grp.h" HAVE_GRP_H) +LA_CHECK_INCLUDE_FILE("inttypes.h" HAVE_INTTYPES_H) +LA_CHECK_INCLUDE_FILE("io.h" HAVE_IO_H) +LA_CHECK_INCLUDE_FILE("langinfo.h" HAVE_LANGINFO_H) +LA_CHECK_INCLUDE_FILE("limits.h" HAVE_LIMITS_H) +LA_CHECK_INCLUDE_FILE("linux/types.h" HAVE_LINUX_TYPES_H) +LA_CHECK_INCLUDE_FILE("linux/fiemap.h" HAVE_LINUX_FIEMAP_H) +LA_CHECK_INCLUDE_FILE("linux/fs.h" HAVE_LINUX_FS_H) + +CHECK_C_SOURCE_COMPILES("#include +#include +int main(void) { return FS_IOC_GETFLAGS; }" HAVE_WORKING_FS_IOC_GETFLAGS) + +LA_CHECK_INCLUDE_FILE("linux/magic.h" HAVE_LINUX_MAGIC_H) +LA_CHECK_INCLUDE_FILE("locale.h" HAVE_LOCALE_H) +LA_CHECK_INCLUDE_FILE("membership.h" HAVE_MEMBERSHIP_H) +LA_CHECK_INCLUDE_FILE("memory.h" HAVE_MEMORY_H) +LA_CHECK_INCLUDE_FILE("paths.h" HAVE_PATHS_H) +LA_CHECK_INCLUDE_FILE("poll.h" HAVE_POLL_H) +LA_CHECK_INCLUDE_FILE("process.h" HAVE_PROCESS_H) +LA_CHECK_INCLUDE_FILE("pthread.h" HAVE_PTHREAD_H) +LA_CHECK_INCLUDE_FILE("pwd.h" HAVE_PWD_H) +LA_CHECK_INCLUDE_FILE("readpassphrase.h" HAVE_READPASSPHRASE_H) +LA_CHECK_INCLUDE_FILE("regex.h" HAVE_REGEX_H) +LA_CHECK_INCLUDE_FILE("signal.h" HAVE_SIGNAL_H) +LA_CHECK_INCLUDE_FILE("spawn.h" HAVE_SPAWN_H) +LA_CHECK_INCLUDE_FILE("stdarg.h" HAVE_STDARG_H) +LA_CHECK_INCLUDE_FILE("stdint.h" HAVE_STDINT_H) +LA_CHECK_INCLUDE_FILE("stdlib.h" HAVE_STDLIB_H) +LA_CHECK_INCLUDE_FILE("string.h" HAVE_STRING_H) +LA_CHECK_INCLUDE_FILE("strings.h" HAVE_STRINGS_H) +LA_CHECK_INCLUDE_FILE("sys/acl.h" HAVE_SYS_ACL_H) +LA_CHECK_INCLUDE_FILE("sys/cdefs.h" HAVE_SYS_CDEFS_H) +LA_CHECK_INCLUDE_FILE("sys/extattr.h" HAVE_SYS_EXTATTR_H) +LA_CHECK_INCLUDE_FILE("sys/ioctl.h" HAVE_SYS_IOCTL_H) +LA_CHECK_INCLUDE_FILE("sys/mkdev.h" HAVE_SYS_MKDEV_H) +LA_CHECK_INCLUDE_FILE("sys/mount.h" HAVE_SYS_MOUNT_H) +LA_CHECK_INCLUDE_FILE("sys/param.h" HAVE_SYS_PARAM_H) +LA_CHECK_INCLUDE_FILE("sys/poll.h" HAVE_SYS_POLL_H) +LA_CHECK_INCLUDE_FILE("sys/richacl.h" HAVE_SYS_RICHACL_H) +LA_CHECK_INCLUDE_FILE("sys/select.h" HAVE_SYS_SELECT_H) +LA_CHECK_INCLUDE_FILE("sys/stat.h" HAVE_SYS_STAT_H) +LA_CHECK_INCLUDE_FILE("sys/statfs.h" HAVE_SYS_STATFS_H) +LA_CHECK_INCLUDE_FILE("sys/statvfs.h" HAVE_SYS_STATVFS_H) +LA_CHECK_INCLUDE_FILE("sys/sysmacros.h" HAVE_SYS_SYSMACROS_H) +LA_CHECK_INCLUDE_FILE("sys/time.h" HAVE_SYS_TIME_H) +LA_CHECK_INCLUDE_FILE("sys/utime.h" HAVE_SYS_UTIME_H) +LA_CHECK_INCLUDE_FILE("sys/utsname.h" HAVE_SYS_UTSNAME_H) +LA_CHECK_INCLUDE_FILE("sys/vfs.h" HAVE_SYS_VFS_H) +LA_CHECK_INCLUDE_FILE("sys/wait.h" HAVE_SYS_WAIT_H) +LA_CHECK_INCLUDE_FILE("sys/xattr.h" HAVE_SYS_XATTR_H) +LA_CHECK_INCLUDE_FILE("time.h" HAVE_TIME_H) +LA_CHECK_INCLUDE_FILE("unistd.h" HAVE_UNISTD_H) +LA_CHECK_INCLUDE_FILE("utime.h" HAVE_UTIME_H) +LA_CHECK_INCLUDE_FILE("wchar.h" HAVE_WCHAR_H) +LA_CHECK_INCLUDE_FILE("wctype.h" HAVE_WCTYPE_H) +LA_CHECK_INCLUDE_FILE("windows.h" HAVE_WINDOWS_H) +IF(ENABLE_CNG) + LA_CHECK_INCLUDE_FILE("Bcrypt.h" HAVE_BCRYPT_H) + IF(HAVE_BCRYPT_H) + LIST(APPEND ADDITIONAL_LIBS "Bcrypt") + ENDIF(HAVE_BCRYPT_H) +ELSE(ENABLE_CNG) + UNSET(HAVE_BCRYPT_H CACHE) +ENDIF(ENABLE_CNG) +# Following files need windows.h, so we should test it after windows.h test. +LA_CHECK_INCLUDE_FILE("wincrypt.h" HAVE_WINCRYPT_H) +LA_CHECK_INCLUDE_FILE("winioctl.h" HAVE_WINIOCTL_H) + +# +# Check whether use of __EXTENSIONS__ is safe. +# We need some macro such as _GNU_SOURCE to use extension functions. +# +SET(_INCLUDE_FILES) +FOREACH (it ${_HEADER}) + SET(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n") +ENDFOREACH (it) + +CHECK_C_SOURCE_COMPILES( + "#define __EXTENSIONS__ 1 + ${_INCLUDE_FILES} + int main() { return 0;}" + SAFE_TO_DEFINE_EXTENSIONS) + +# +# Find mbed TLS +# +IF(ENABLE_MBEDTLS) + FIND_PACKAGE(MbedTLS) + IF(MBEDTLS_FOUND) + SET(HAVE_LIBMBEDCRYPTO 1) + LIST(APPEND ADDITIONAL_LIBS ${MBEDCRYPTO_LIBRARY}) + INCLUDE_DIRECTORIES(${MBEDTLS_INCLUDE_DIRS}) + + LIST(APPEND CMAKE_REQUIRED_INCLUDES ${MBEDTLS_INCLUDE_DIRS}) + LA_CHECK_INCLUDE_FILE("mbedtls/aes.h" HAVE_MBEDTLS_AES_H) + LA_CHECK_INCLUDE_FILE("mbedtls/md.h" HAVE_MBEDTLS_MD_H) + LA_CHECK_INCLUDE_FILE("mbedtls/pkcs5.h" HAVE_MBEDTLS_PKCS5_H) + + ENDIF(MBEDTLS_FOUND) + MARK_AS_ADVANCED(CLEAR MBEDTLS_INCLUDE_DIRS) + MARK_AS_ADVANCED(CLEAR MBEDCRYPTO_LIBRARY) +ENDIF(ENABLE_MBEDTLS) + +# +# Find Nettle +# +IF(ENABLE_NETTLE) + FIND_PACKAGE(Nettle) + IF(NETTLE_FOUND) + SET(HAVE_LIBNETTLE 1) + LIST(APPEND ADDITIONAL_LIBS ${NETTLE_LIBRARIES}) + INCLUDE_DIRECTORIES(${NETTLE_INCLUDE_DIR}) + + LIST(APPEND CMAKE_REQUIRED_INCLUDES ${NETTLE_INCLUDE_DIR}) + LA_CHECK_INCLUDE_FILE("nettle/aes.h" HAVE_NETTLE_AES_H) + LA_CHECK_INCLUDE_FILE("nettle/hmac.h" HAVE_NETTLE_HMAC_H) + LA_CHECK_INCLUDE_FILE("nettle/md5.h" HAVE_NETTLE_MD5_H) + LA_CHECK_INCLUDE_FILE("nettle/pbkdf2.h" HAVE_NETTLE_PBKDF2_H) + LA_CHECK_INCLUDE_FILE("nettle/ripemd160.h" HAVE_NETTLE_RIPEMD160_H) + LA_CHECK_INCLUDE_FILE("nettle/sha.h" HAVE_NETTLE_SHA_H) + + ENDIF(NETTLE_FOUND) + MARK_AS_ADVANCED(CLEAR NETTLE_INCLUDE_DIR) + MARK_AS_ADVANCED(CLEAR NETTLE_LIBRARIES) +ENDIF(ENABLE_NETTLE) + +# +# Find OpenSSL +# (Except on Mac, where OpenSSL is deprecated.) +# +IF(ENABLE_OPENSSL AND NOT CMAKE_SYSTEM_NAME MATCHES "Darwin") + FIND_PACKAGE(OpenSSL) + IF(OPENSSL_FOUND) + SET(HAVE_LIBCRYPTO 1) + INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${OPENSSL_CRYPTO_LIBRARY}) + ENDIF(OPENSSL_FOUND) +ELSE() + SET(OPENSSL_FOUND FALSE) # Override cached value +ENDIF() + +# FreeBSD libmd +IF(NOT OPENSSL_FOUND) + CHECK_LIBRARY_EXISTS(md "MD5Init" "" LIBMD_FOUND) + IF(LIBMD_FOUND) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables + SET(CMAKE_REQUIRED_LIBRARIES "md") + FIND_LIBRARY(LIBMD_LIBRARY NAMES md) + LIST(APPEND ADDITIONAL_LIBS ${LIBMD_LIBRARY}) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables + ENDIF(LIBMD_FOUND) +ENDIF(NOT OPENSSL_FOUND) + +# +# How to prove that CRYPTO functions, which have several names on various +# platforms, just see if archive_digest.c can compile and link against +# required libraries. +# +MACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION) + FOREACH(ALGORITHM ${ALGORITHMS}) + IF(NOT ARCHIVE_CRYPTO_${ALGORITHM}) + STRING(TOLOWER "${ALGORITHM}" lower_algorithm) + STRING(TOUPPER "${ALGORITHM}" algorithm) + IF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND NOT OPENSSL_FOUND) + SET(ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} FALSE) + ELSEIF("${IMPLEMENTATION}" MATCHES "^MBEDTLS$" AND NOT MBEDTLS_FOUND) + SET(ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} FALSE) + ELSEIF("${IMPLEMENTATION}" MATCHES "^NETTLE$" AND NOT NETTLE_FOUND) + SET(ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} FALSE) + ENDIF("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND NOT OPENSSL_FOUND) + + IF(NOT DEFINED ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}) + # Probe the local implementation for whether this + # crypto implementation is available on this platform. + SET(TRY_CRYPTO_REQUIRED_INCLUDES + "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}/libarchive;${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp") + SET(TRY_CRYPTO_REQUIRED_LIBS) + IF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND) + SET(TRY_CRYPTO_REQUIRED_INCLUDES + "${TRY_CRYPTO_REQUIRED_INCLUDES};${OPENSSL_INCLUDE_DIR}") + SET(TRY_CRYPTO_REQUIRED_LIBS + "-DLINK_LIBRARIES:STRING=${OPENSSL_LIBRARIES}") + ELSEIF("${IMPLEMENTATION}" MATCHES "^MBEDTLS$" AND MBEDTLS_FOUND) + SET(TRY_CRYPTO_REQUIRED_INCLUDES + "${TRY_CRYPTO_REQUIRED_INCLUDES};${MBEDTLS_INCLUDE_DIRS}") + SET(TRY_CRYPTO_REQUIRED_LIBS + "-DLINK_LIBRARIES:STRING=${MBEDCRYPTO_LIBRARY}") + ELSEIF("${IMPLEMENTATION}" MATCHES "^NETTLE$" AND NETTLE_FOUND) + SET(TRY_CRYPTO_REQUIRED_INCLUDES + "${TRY_CRYPTO_REQUIRED_INCLUDES};${NETTLE_INCLUDE_DIR}") + SET(TRY_CRYPTO_REQUIRED_LIBS + "-DLINK_LIBRARIES:STRING=${NETTLE_LIBRARY}") + ELSEIF("${IMPLEMENTATION}" MATCHES "^LIBMD$" AND LIBMD_FOUND) + SET(TRY_CRYPTO_REQUIRED_LIBS + "-DLINK_LIBRARIES:STRING=${LIBMD_LIBRARY}") + ENDIF("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND) + + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h) + FILE(READ "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h" + CONFDEFS_H) + FILE(READ "${CMAKE_CURRENT_SOURCE_DIR}/libarchive/archive_digest.c" + ARCHIVE_CRYPTO_C) + + SET(SOURCE "${CONFDEFS_H} + +#define ARCHIVE_${algorithm}_COMPILE_TEST +#define ARCHIVE_CRYPTO_${algorithm}_${IMPLEMENTATION} +#define PLATFORM_CONFIG_H \"check_crypto_md.h\" + +${ARCHIVE_CRYPTO_C} + +int +main(int argc, char **argv) +{ + archive_${lower_algorithm}_ctx ctx; + archive_${lower_algorithm}_init(&ctx); + archive_${lower_algorithm}_update(&ctx, *argv, argc); + archive_${lower_algorithm}_final(&ctx, NULL); + return 0; +} +") + + FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_md.h" "") + FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_md.c" "${SOURCE}") + MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}") + + TRY_COMPILE(ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} + ${CMAKE_BINARY_DIR} + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_md.c + CMAKE_FLAGS + "${TRY_CRYPTO_REQUIRED_LIBS}" + "${TRY_CRYPTO_REQUIRED_INCLUDES}" + OUTPUT_VARIABLE OUTPUT) + + # Inform user whether or not we found it; if not, log why we didn't. + IF (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}) + MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} -- found") + SET(ARCHIVE_CRYPTO_${ALGORITHM} 1) + ELSE (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}) + MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} -- not found") + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} failed with the following output:\n" + "${OUTPUT}\n" + "Source file was:\n${SOURCE}\n") + ENDIF (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}) + ENDIF(NOT DEFINED ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}) + + # Add appropriate libs/includes depending on whether the implementation + # was found on this platform. + IF (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}) + IF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND) + INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${OPENSSL_LIBRARIES}) + LIST(REMOVE_DUPLICATES ADDITIONAL_LIBS) + ENDIF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND) + ENDIF (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}) + ENDIF(NOT ARCHIVE_CRYPTO_${ALGORITHM}) + ENDFOREACH(ALGORITHM ${ALGORITHMS}) +ENDMACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION) + +# +# CRYPTO functions on Windows is defined at archive_windows.c, thus we do not +# need the test what the functions can be mapped to archive_{crypto name}_init, +# archive_{crypto name}_update and archive_{crypto name}_final. +# The functions on Windows use CALG_{crypto name} macro to create a crypt object +# and then we need to know what CALG_{crypto name} macros is available to show +# ARCHIVE_CRYPTO_{crypto name}_WIN macros because Windows 2000 and earlier version +# of Windows XP do not support SHA256, SHA384 and SHA512. +# +MACRO(CHECK_CRYPTO_WIN CRYPTO_LIST) + IF(WIN32 AND NOT CYGWIN) + FOREACH(CRYPTO ${CRYPTO_LIST}) + IF(NOT ARCHIVE_CRYPTO_${CRYPTO}) + IF(NOT DEFINED ARCHIVE_CRYPTO_${CRYPTO}_WIN) + STRING(TOUPPER "${CRYPTO}" crypto) + SET(ALGID "") + IF ("${CRYPTO}" MATCHES "^MD5$") + SET(ALGID "CALG_MD5") + ENDIF ("${CRYPTO}" MATCHES "^MD5$") + IF ("${CRYPTO}" MATCHES "^SHA1$") + SET(ALGID "CALG_SHA1") + ENDIF ("${CRYPTO}" MATCHES "^SHA1$") + IF ("${CRYPTO}" MATCHES "^SHA256$") + SET(ALGID "CALG_SHA_256") + ENDIF ("${CRYPTO}" MATCHES "^SHA256$") + IF ("${CRYPTO}" MATCHES "^SHA384$") + SET(ALGID "CALG_SHA_384") + ENDIF ("${CRYPTO}" MATCHES "^SHA384$") + IF ("${CRYPTO}" MATCHES "^SHA512$") + SET(ALGID "CALG_SHA_512") + ENDIF ("${CRYPTO}" MATCHES "^SHA512$") + + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h) + FILE(READ "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h" + CONFDEFS_H) + + SET(SOURCE "${CONFDEFS_H} + +#define ${crypto}_COMPILE_TEST +#include +#include + +int +main(int argc, char **argv) +{ + return ${ALGID}; +} +") + SET(SOURCE_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_win.c") + + FILE(WRITE "${SOURCE_FILE}" "${SOURCE}") + MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN") + + TRY_COMPILE(ARCHIVE_CRYPTO_${CRYPTO}_WIN + ${CMAKE_BINARY_DIR} + ${SOURCE_FILE} + CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}/libarchive" + OUTPUT_VARIABLE OUTPUT) + + IF (ARCHIVE_CRYPTO_${CRYPTO}_WIN) + MESSAGE(STATUS + "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN -- found") + SET(ARCHIVE_CRYPTO_${CRYPTO} 1) + ELSE (ARCHIVE_CRYPTO_${CRYPTO}_WIN) + MESSAGE(STATUS + "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN -- not found") + FILE(APPEND + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN failed with the following output:\n" + "${OUTPUT}\n" + "Source file was:\n${SOURCE}\n") + ENDIF (ARCHIVE_CRYPTO_${CRYPTO}_WIN) + + ENDIF(NOT DEFINED ARCHIVE_CRYPTO_${CRYPTO}_WIN) + ENDIF(NOT ARCHIVE_CRYPTO_${CRYPTO}) + ENDFOREACH(CRYPTO) + ENDIF(WIN32 AND NOT CYGWIN) +ENDMACRO(CHECK_CRYPTO_WIN CRYPTO_LIST) + +# +# Find iconv +# POSIX defines the second arg as const char ** +# and requires it to be in libc. But we can accept +# a non-const argument here and can support iconv() +# being in libiconv. +# +MACRO(CHECK_ICONV LIB TRY_ICONV_CONST) + IF(NOT HAVE_ICONV) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables + IF (CMAKE_C_COMPILER_ID MATCHES "^GNU$" OR + CMAKE_C_COMPILER_ID MATCHES "^Clang$") + # + # During checking iconv proto type, we should use -Werror to avoid the + # success of iconv detection with a warnig which success is a miss + # detection. So this needs for all build mode(even it's a release mode). + # + SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror") + ENDIF (CMAKE_C_COMPILER_ID MATCHES "^GNU$" OR + CMAKE_C_COMPILER_ID MATCHES "^Clang$") + IF (CMAKE_C_COMPILER_ID MATCHES "^XL$") + SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -qhalt=w -qflag=w:w") + ENDIF (CMAKE_C_COMPILER_ID MATCHES "^XL$") + IF (MSVC) + # NOTE: /WX option is the same as gcc's -Werror option. + SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} /WX") + ENDIF (MSVC) + # + CHECK_C_SOURCE_COMPILES( + "#include + #include + int main() { + ${TRY_ICONV_CONST} char *ccp; + iconv_t cd = iconv_open(\"\", \"\"); + iconv(cd, &ccp, (size_t *)0, (char **)0, (size_t *)0); + iconv_close(cd); + return 0; + }" + HAVE_ICONV_${LIB}_${TRY_ICONV_CONST}) + IF(HAVE_ICONV_${LIB}_${TRY_ICONV_CONST}) + SET(HAVE_ICONV true) + SET(ICONV_CONST ${TRY_ICONV_CONST}) + ENDIF(HAVE_ICONV_${LIB}_${TRY_ICONV_CONST}) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables + ENDIF(NOT HAVE_ICONV) +ENDMACRO(CHECK_ICONV TRY_ICONV_CONST) + +IF(ENABLE_ICONV) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables + FIND_PATH(ICONV_INCLUDE_DIR iconv.h) + IF(ICONV_INCLUDE_DIR) + #SET(INCLUDES ${INCLUDES} "iconv.h") + SET(HAVE_ICONV_H 1) + INCLUDE_DIRECTORIES(${ICONV_INCLUDE_DIR}) + SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR}) + CHECK_ICONV("libc" "const") + CHECK_ICONV("libc" "") + + # If iconv isn't in libc and we have a libiconv, try that. + FIND_LIBRARY(LIBICONV_PATH NAMES iconv libiconv) + IF(NOT HAVE_ICONV AND LIBICONV_PATH) + LIST(APPEND CMAKE_REQUIRED_LIBRARIES ${LIBICONV_PATH}) + # Test if a macro is needed for the library. + TRY_MACRO_FOR_LIBRARY( + "${ICONV_INCLUDE_DIR}" "${LIBICONV_PATH}" + COMPILES + "#include \nint main() {return iconv_close((iconv_t)0);}" + "WITHOUT_LIBICONV_STATIC;LIBICONV_STATIC") + IF(NOT WITHOUT_LIBICONV_STATIC AND LIBICONV_STATIC) + ADD_DEFINITIONS(-DLIBICONV_STATIC) + ENDIF(NOT WITHOUT_LIBICONV_STATIC AND LIBICONV_STATIC) + # + # Set up CMAKE_REQUIRED_* for CHECK_ICONV + # + SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR}) + SET(CMAKE_REQUIRED_LIBRARIES ${LIBICONV_PATH}) + IF(LIBICONV_STATIC) + # LIBICONV_STATIC is necessary for the success of CHECK_ICONV + # on Windows. + SET(CMAKE_REQUIRED_DEFINITIONS "-DLIBICONV_STATIC") + ELSE(LIBICONV_STATIC) + SET(CMAKE_REQUIRED_DEFINITIONS) + ENDIF(LIBICONV_STATIC) + CHECK_ICONV("libiconv" "const") + CHECK_ICONV("libiconv" "") + IF (HAVE_ICONV) + LIST(APPEND ADDITIONAL_LIBS ${LIBICONV_PATH}) + ENDIF(HAVE_ICONV) + ENDIF(NOT HAVE_ICONV AND LIBICONV_PATH) + ENDIF(ICONV_INCLUDE_DIR) + # + # Find locale_charset() for libiconv. + # + IF(LIBICONV_PATH) + SET(CMAKE_REQUIRED_DEFINITIONS) + SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR}) + SET(CMAKE_REQUIRED_LIBRARIES) + CHECK_INCLUDE_FILES("localcharset.h" HAVE_LOCALCHARSET_H) + FIND_LIBRARY(LIBCHARSET_PATH NAMES charset libcharset) + IF(LIBCHARSET_PATH) + SET(CMAKE_REQUIRED_LIBRARIES ${LIBCHARSET_PATH}) + IF(WIN32 AND NOT CYGWIN) + # Test if a macro is needed for the library. + TRY_MACRO_FOR_LIBRARY( + "${ICONV_INCLUDE_DIR}" "${LIBCHARSET_PATH}" + COMPILES + "#include \nint main() {return locale_charset()?1:0;}" + "WITHOUT_LIBCHARSET_STATIC;LIBCHARSET_STATIC") + IF(NOT WITHOUT_LIBCHARSET_STATIC AND LIBCHARSET_STATIC) + ADD_DEFINITIONS(-DLIBCHARSET_STATIC) + ENDIF(NOT WITHOUT_LIBCHARSET_STATIC AND LIBCHARSET_STATIC) + IF(WITHOUT_LIBCHARSET_STATIC OR LIBCHARSET_STATIC) + SET(HAVE_LOCALE_CHARSET ON CACHE INTERNAL + "Have function locale_charset") + ENDIF(WITHOUT_LIBCHARSET_STATIC OR LIBCHARSET_STATIC) + ELSE(WIN32 AND NOT CYGWIN) + CHECK_FUNCTION_EXISTS_GLIBC(locale_charset HAVE_LOCALE_CHARSET) + ENDIF(WIN32 AND NOT CYGWIN) + IF(HAVE_LOCALE_CHARSET) + LIST(APPEND ADDITIONAL_LIBS ${LIBCHARSET_PATH}) + ENDIF(HAVE_LOCALE_CHARSET) + ENDIF(LIBCHARSET_PATH) + ENDIF(LIBICONV_PATH) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables +ELSE(ENABLE_ICONV) + # Make sure ICONV variables are not in CACHE after ENABLE_ICONV disabled + # (once enabled). + UNSET(HAVE_LOCALE_CHARSET CACHE) + UNSET(HAVE_ICONV CACHE) + UNSET(HAVE_ICONV_libc_ CACHE) + UNSET(HAVE_ICONV_libc_const CACHE) + UNSET(HAVE_ICONV_libiconv_ CACHE) + UNSET(HAVE_ICONV_libiconv_const CACHE) + UNSET(ICONV_INCLUDE_DIR CACHE) + UNSET(LIBICONV_PATH CACHE) + UNSET(LIBICONV_DLL CACHE) + UNSET(LIBICONV_STATIC CACHE) + UNSET(LIBCHARSET_DLL CACHE) + UNSET(LIBCHARSET_STATIC CACHE) +ENDIF(ENABLE_ICONV) + +# +# Find Libxml2 +# +IF(ENABLE_LIBXML2) + FIND_PACKAGE(LibXml2) +ELSE() + SET(LIBXML2_FOUND FALSE) +ENDIF() +IF(LIBXML2_FOUND) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables + INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${LIBXML2_LIBRARIES}) + SET(HAVE_LIBXML2 1) + # libxml2's include files use iconv.h + SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR}) + CHECK_INCLUDE_FILES("libxml/xmlreader.h" HAVE_LIBXML_XMLREADER_H) + CHECK_INCLUDE_FILES("libxml/xmlwriter.h" HAVE_LIBXML_XMLWRITER_H) + # Test if a macro is needed for the library. + TRY_MACRO_FOR_LIBRARY( + "${ICONV_INCLUDE_DIR};${LIBXML2_INCLUDE_DIR}" + "ws2_32.lib;${ZLIB_LIBRARIES};${LIBICONV_PATH};${LIBXML2_LIBRARIES}" + COMPILES + "#include \n#include \nint main() {return xmlTextReaderRead((xmlTextReaderPtr)(void *)0);}" + "WITHOUT_LIBXML_STATIC;LIBXML_STATIC") + IF(NOT WITHOUT_LIBXML_STATIC AND LIBXML_STATIC) + ADD_DEFINITIONS(-DLIBXML_STATIC) + ENDIF(NOT WITHOUT_LIBXML_STATIC AND LIBXML_STATIC) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables +ELSE(LIBXML2_FOUND) + # + # Find Expat + # + IF(ENABLE_EXPAT) + FIND_PACKAGE(EXPAT) + ELSE() + SET(EXPAT_FOUND FALSE) + ENDIF() + IF(EXPAT_FOUND) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables + INCLUDE_DIRECTORIES(${EXPAT_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${EXPAT_LIBRARIES}) + SET(HAVE_LIBEXPAT 1) + LA_CHECK_INCLUDE_FILE("expat.h" HAVE_EXPAT_H) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables + ENDIF(EXPAT_FOUND) +ENDIF(LIBXML2_FOUND) +MARK_AS_ADVANCED(CLEAR LIBXML2_INCLUDE_DIR) +MARK_AS_ADVANCED(CLEAR LIBXML2_LIBRARIES) + +# +# POSIX Regular Expression support +# +IF(POSIX_REGEX_LIB MATCHES "^(AUTO|LIBC|LIBREGEX)$") + # + # If PCREPOSIX is not found or not requested, try using regex + # from libc or libregex + # + FIND_PATH(REGEX_INCLUDE_DIR regex.h) + IF(REGEX_INCLUDE_DIR) + CHECK_FUNCTION_EXISTS_GLIBC(regcomp HAVE_REGCOMP_LIBC) + # + # If libc does not provide regex, find libregex. + # + IF(NOT HAVE_REGCOMP_LIBC) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables + FIND_LIBRARY(REGEX_LIBRARY regex) + IF(REGEX_LIBRARY) + SET(CMAKE_REQUIRED_LIBRARIES ${REGEX_LIBRARY}) + CHECK_FUNCTION_EXISTS_GLIBC(regcomp HAVE_REGCOMP_LIBREGEX) + IF(HAVE_REGCOMP_LIBREGEX) + LIST(APPEND ADDITIONAL_LIBS ${REGEX_LIBRARY}) + # + # If regex.h is not found, retry looking for regex.h at + # REGEX_INCLUDE_DIR + # + IF(NOT HAVE_REGEX_H) + UNSET(HAVE_REGEX_H CACHE) + INCLUDE_DIRECTORIES(${REGEX_INCLUDE_DIR}) + SET(CMAKE_REQUIRED_INCLUDES ${REGEX_INCLUDE_DIR}) + LA_CHECK_INCLUDE_FILE("regex.h" HAVE_REGEX_H) + ENDIF(NOT HAVE_REGEX_H) + # Test if a macro is needed for the library. + TRY_MACRO_FOR_LIBRARY( + "${REGEX_INCLUDE_DIR}" "${REGEX_LIBRARY}" + COMPILES + "#include \n#include \nint main() {regex_t r;return regcomp(&r, \"\", 0);}" + "USE_REGEX_DLL;USE_REGEX_STATIC") + IF(USE_REGEX_DLL) + ADD_DEFINITIONS(-DUSE_REGEX_DLL) + ELSEIF(USE_REGEX_STATIC) + ADD_DEFINITIONS(-DUSE_REGEX_STATIC) + ENDIF(USE_REGEX_DLL) + ENDIF(HAVE_REGCOMP_LIBREGEX) + ENDIF(REGEX_LIBRARY) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables + ENDIF(NOT HAVE_REGCOMP_LIBC) + ENDIF(REGEX_INCLUDE_DIR) + IF(HAVE_REGCOMP_LIBC OR HAVE_REGCOMP_LIBREGEX) + SET(FOUND_POSIX_REGEX_LIB 1) + ENDIF(HAVE_REGCOMP_LIBC OR HAVE_REGCOMP_LIBREGEX) +ENDIF(POSIX_REGEX_LIB MATCHES "^(AUTO|LIBC|LIBREGEX)$") + +IF(NOT FOUND_POSIX_REGEX_LIB AND POSIX_REGEX_LIB MATCHES "^(AUTO|LIBPCREPOSIX)$") + # + # If requested, try finding library for PCREPOSIX + # + IF(ENABLE_LibGCC) + FIND_PACKAGE(LibGCC) + ELSE() + SET(LIBGCC_FOUND FALSE) # Override cached value + ENDIF() + IF(ENABLE_PCREPOSIX) + FIND_PACKAGE(PCREPOSIX) + ELSE() + SET(PCREPOSIX_FOUND FALSE) # Override cached value + ENDIF() + IF(PCREPOSIX_FOUND) + INCLUDE_DIRECTORIES(${PCRE_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${PCREPOSIX_LIBRARIES}) + # Test if a macro is needed for the library. + TRY_MACRO_FOR_LIBRARY( + "${PCRE_INCLUDE_DIR}" "${PCREPOSIX_LIBRARIES}" + COMPILES + "#include \nint main() {regex_t r;return regcomp(&r, \"\", 0);}" + "WITHOUT_PCRE_STATIC;PCRE_STATIC") + IF(NOT WITHOUT_PCRE_STATIC AND PCRE_STATIC) + ADD_DEFINITIONS(-DPCRE_STATIC) + ELSEIF(NOT WITHOUT_PCRE_STATIC AND NOT PCRE_STATIC AND PCRE_FOUND) + # Determine if pcre static libraries are to be used. + LIST(APPEND ADDITIONAL_LIBS ${PCRE_LIBRARIES}) + SET(TMP_LIBRARIES ${PCREPOSIX_LIBRARIES} ${PCRE_LIBRARIES}) + MESSAGE(STATUS "trying again with -lpcre included") + TRY_MACRO_FOR_LIBRARY( + "${PCRE_INCLUDE_DIR}" "${TMP_LIBRARIES}" + COMPILES + "#include \nint main() {regex_t r;return regcomp(&r, \"\", 0);}" + "WITHOUT_PCRE_STATIC;PCRE_STATIC") + IF(NOT WITHOUT_PCRE_STATIC AND PCRE_STATIC) + ADD_DEFINITIONS(-DPCRE_STATIC) + ELSEIF(NOT WITHOUT_PCRE_STATIC AND NOT PCRE_STATIC AND MSVC AND LIBGCC_FOUND) + # When doing a Visual Studio build using pcre static libraries + # built using the mingw toolchain, -lgcc is needed to resolve + # ___chkstk_ms. + MESSAGE(STATUS "Visual Studio build detected, trying again with -lgcc included") + LIST(APPEND ADDITIONAL_LIBS ${LIBGCC_LIBRARIES}) + SET(TMP_LIBRARIES ${PCREPOSIX_LIBRARIES} ${PCRE_LIBRARIES} ${LIBGCC_LIBRARIES}) + TRY_MACRO_FOR_LIBRARY( + "${PCRE_INCLUDE_DIR}" "${TMP_LIBRARIES}" + COMPILES + "#include \nint main() {regex_t r;return regcomp(&r, \"\", 0);}" + "WITHOUT_PCRE_STATIC;PCRE_STATIC") + IF(NOT WITHOUT_PCRE_STATIC AND PCRE_STATIC) + ADD_DEFINITIONS(-DPCRE_STATIC) + ENDIF(NOT WITHOUT_PCRE_STATIC AND PCRE_STATIC) + ENDIF(NOT WITHOUT_PCRE_STATIC AND PCRE_STATIC) + ENDIF(NOT WITHOUT_PCRE_STATIC AND PCRE_STATIC) + ENDIF(PCREPOSIX_FOUND) + MARK_AS_ADVANCED(CLEAR PCRE_INCLUDE_DIR) + MARK_AS_ADVANCED(CLEAR PCREPOSIX_LIBRARIES) + MARK_AS_ADVANCED(CLEAR PCRE_LIBRARIES) + MARK_AS_ADVANCED(CLEAR LIBGCC_LIBRARIES) +ENDIF(NOT FOUND_POSIX_REGEX_LIB AND POSIX_REGEX_LIB MATCHES "^(AUTO|LIBPCREPOSIX)$") + +# +# Check functions +# +CMAKE_PUSH_CHECK_STATE() # Save the state of the variables +IF (CMAKE_C_COMPILER_ID MATCHES "^GNU$" OR + CMAKE_C_COMPILER_ID MATCHES "^Clang$") + # + # During checking functions, we should use -fno-builtin to avoid the + # failure of function detection which failure is an error "conflicting + # types for built-in function" caused by using -Werror option. + # + SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-builtin") +ENDIF (CMAKE_C_COMPILER_ID MATCHES "^GNU$" OR + CMAKE_C_COMPILER_ID MATCHES "^Clang$") +CHECK_SYMBOL_EXISTS(_CrtSetReportMode "crtdbg.h" HAVE__CrtSetReportMode) +CHECK_FUNCTION_EXISTS_GLIBC(arc4random_buf HAVE_ARC4RANDOM_BUF) +CHECK_FUNCTION_EXISTS_GLIBC(chflags HAVE_CHFLAGS) +CHECK_FUNCTION_EXISTS_GLIBC(chown HAVE_CHOWN) +CHECK_FUNCTION_EXISTS_GLIBC(chroot HAVE_CHROOT) +CHECK_FUNCTION_EXISTS_GLIBC(ctime_r HAVE_CTIME_R) +CHECK_FUNCTION_EXISTS_GLIBC(fchdir HAVE_FCHDIR) +CHECK_FUNCTION_EXISTS_GLIBC(fchflags HAVE_FCHFLAGS) +CHECK_FUNCTION_EXISTS_GLIBC(fchmod HAVE_FCHMOD) +CHECK_FUNCTION_EXISTS_GLIBC(fchown HAVE_FCHOWN) +CHECK_FUNCTION_EXISTS_GLIBC(fcntl HAVE_FCNTL) +CHECK_FUNCTION_EXISTS_GLIBC(fdopendir HAVE_FDOPENDIR) +CHECK_FUNCTION_EXISTS_GLIBC(fork HAVE_FORK) +CHECK_FUNCTION_EXISTS_GLIBC(fstat HAVE_FSTAT) +CHECK_FUNCTION_EXISTS_GLIBC(fstatat HAVE_FSTATAT) +CHECK_FUNCTION_EXISTS_GLIBC(fstatfs HAVE_FSTATFS) +CHECK_FUNCTION_EXISTS_GLIBC(fstatvfs HAVE_FSTATVFS) +CHECK_FUNCTION_EXISTS_GLIBC(ftruncate HAVE_FTRUNCATE) +CHECK_FUNCTION_EXISTS_GLIBC(futimens HAVE_FUTIMENS) +CHECK_FUNCTION_EXISTS_GLIBC(futimes HAVE_FUTIMES) +CHECK_FUNCTION_EXISTS_GLIBC(futimesat HAVE_FUTIMESAT) +CHECK_FUNCTION_EXISTS_GLIBC(geteuid HAVE_GETEUID) +CHECK_FUNCTION_EXISTS_GLIBC(getgrgid_r HAVE_GETGRGID_R) +CHECK_FUNCTION_EXISTS_GLIBC(getgrnam_r HAVE_GETGRNAM_R) +CHECK_FUNCTION_EXISTS_GLIBC(getpwnam_r HAVE_GETPWNAM_R) +CHECK_FUNCTION_EXISTS_GLIBC(getpwuid_r HAVE_GETPWUID_R) +CHECK_FUNCTION_EXISTS_GLIBC(getpid HAVE_GETPID) +CHECK_FUNCTION_EXISTS_GLIBC(getvfsbyname HAVE_GETVFSBYNAME) +CHECK_FUNCTION_EXISTS_GLIBC(gmtime_r HAVE_GMTIME_R) +CHECK_FUNCTION_EXISTS_GLIBC(lchflags HAVE_LCHFLAGS) +CHECK_FUNCTION_EXISTS_GLIBC(lchmod HAVE_LCHMOD) +CHECK_FUNCTION_EXISTS_GLIBC(lchown HAVE_LCHOWN) +CHECK_FUNCTION_EXISTS_GLIBC(link HAVE_LINK) +CHECK_FUNCTION_EXISTS_GLIBC(localtime_r HAVE_LOCALTIME_R) +CHECK_FUNCTION_EXISTS_GLIBC(lstat HAVE_LSTAT) +CHECK_FUNCTION_EXISTS_GLIBC(lutimes HAVE_LUTIMES) +CHECK_FUNCTION_EXISTS_GLIBC(mbrtowc HAVE_MBRTOWC) +CHECK_FUNCTION_EXISTS_GLIBC(memmove HAVE_MEMMOVE) +CHECK_FUNCTION_EXISTS_GLIBC(mkdir HAVE_MKDIR) +CHECK_FUNCTION_EXISTS_GLIBC(mkfifo HAVE_MKFIFO) +CHECK_FUNCTION_EXISTS_GLIBC(mknod HAVE_MKNOD) +CHECK_FUNCTION_EXISTS_GLIBC(mkstemp HAVE_MKSTEMP) +CHECK_FUNCTION_EXISTS_GLIBC(nl_langinfo HAVE_NL_LANGINFO) +CHECK_FUNCTION_EXISTS_GLIBC(openat HAVE_OPENAT) +CHECK_FUNCTION_EXISTS_GLIBC(pipe HAVE_PIPE) +CHECK_FUNCTION_EXISTS_GLIBC(poll HAVE_POLL) +CHECK_FUNCTION_EXISTS_GLIBC(posix_spawnp HAVE_POSIX_SPAWNP) +CHECK_FUNCTION_EXISTS_GLIBC(readlink HAVE_READLINK) +CHECK_FUNCTION_EXISTS_GLIBC(readpassphrase HAVE_READPASSPHRASE) +CHECK_FUNCTION_EXISTS_GLIBC(select HAVE_SELECT) +CHECK_FUNCTION_EXISTS_GLIBC(setenv HAVE_SETENV) +CHECK_FUNCTION_EXISTS_GLIBC(setlocale HAVE_SETLOCALE) +CHECK_FUNCTION_EXISTS_GLIBC(sigaction HAVE_SIGACTION) +CHECK_FUNCTION_EXISTS_GLIBC(statfs HAVE_STATFS) +CHECK_FUNCTION_EXISTS_GLIBC(statvfs HAVE_STATVFS) +CHECK_FUNCTION_EXISTS_GLIBC(strchr HAVE_STRCHR) +CHECK_FUNCTION_EXISTS_GLIBC(strdup HAVE_STRDUP) +CHECK_FUNCTION_EXISTS_GLIBC(strerror HAVE_STRERROR) +CHECK_FUNCTION_EXISTS_GLIBC(strncpy_s HAVE_STRNCPY_S) +CHECK_FUNCTION_EXISTS_GLIBC(strrchr HAVE_STRRCHR) +CHECK_FUNCTION_EXISTS_GLIBC(symlink HAVE_SYMLINK) +CHECK_FUNCTION_EXISTS_GLIBC(timegm HAVE_TIMEGM) +CHECK_FUNCTION_EXISTS_GLIBC(tzset HAVE_TZSET) +CHECK_FUNCTION_EXISTS_GLIBC(unlinkat HAVE_UNLINKAT) +CHECK_FUNCTION_EXISTS_GLIBC(unsetenv HAVE_UNSETENV) +CHECK_FUNCTION_EXISTS_GLIBC(utime HAVE_UTIME) +CHECK_FUNCTION_EXISTS_GLIBC(utimes HAVE_UTIMES) +CHECK_FUNCTION_EXISTS_GLIBC(utimensat HAVE_UTIMENSAT) +CHECK_FUNCTION_EXISTS_GLIBC(vfork HAVE_VFORK) +CHECK_FUNCTION_EXISTS_GLIBC(wcrtomb HAVE_WCRTOMB) +CHECK_FUNCTION_EXISTS_GLIBC(wcscmp HAVE_WCSCMP) +CHECK_FUNCTION_EXISTS_GLIBC(wcscpy HAVE_WCSCPY) +CHECK_FUNCTION_EXISTS_GLIBC(wcslen HAVE_WCSLEN) +CHECK_FUNCTION_EXISTS_GLIBC(wctomb HAVE_WCTOMB) +CHECK_FUNCTION_EXISTS_GLIBC(_ctime64_s HAVE__CTIME64_S) +CHECK_FUNCTION_EXISTS_GLIBC(_fseeki64 HAVE__FSEEKI64) +CHECK_FUNCTION_EXISTS_GLIBC(_get_timezone HAVE__GET_TIMEZONE) +CHECK_FUNCTION_EXISTS_GLIBC(_gmtime64_s HAVE__GMTIME64_S) +CHECK_FUNCTION_EXISTS_GLIBC(_localtime64_s HAVE__LOCALTIME64_S) +CHECK_FUNCTION_EXISTS_GLIBC(_mkgmtime64 HAVE__MKGMTIME64) + +SET(CMAKE_REQUIRED_LIBRARIES "") +CHECK_FUNCTION_EXISTS(cygwin_conv_path HAVE_CYGWIN_CONV_PATH) +CHECK_FUNCTION_EXISTS(fseeko HAVE_FSEEKO) +CHECK_FUNCTION_EXISTS(strerror_r HAVE_STRERROR_R) +CHECK_FUNCTION_EXISTS(strftime HAVE_STRFTIME) +CHECK_FUNCTION_EXISTS(vprintf HAVE_VPRINTF) +CHECK_FUNCTION_EXISTS(wmemcmp HAVE_WMEMCMP) +CHECK_FUNCTION_EXISTS(wmemcpy HAVE_WMEMCPY) +CHECK_FUNCTION_EXISTS(wmemmove HAVE_WMEMMOVE) + +CMAKE_POP_CHECK_STATE() # Restore the state of the variables + +CHECK_C_SOURCE_COMPILES( + "#include \n#include \nint main(void) { struct vfsconf v; return sizeof(v);}" + HAVE_STRUCT_VFSCONF) + +CHECK_C_SOURCE_COMPILES( + "#include \n#include \nint main(void) { struct xvfsconf v; return sizeof(v);}" + HAVE_STRUCT_XVFSCONF) + +# Make sure we have the POSIX version of readdir_r, not the +# older 2-argument version. +CHECK_C_SOURCE_COMPILES( + "#include \nint main() {DIR *d = opendir(\".\"); struct dirent e,*r; return readdir_r(d,&e,&r);}" + HAVE_READDIR_R) + +# dirfd can be either a function or a macro. +CHECK_C_SOURCE_COMPILES( + "#include \nint main() {DIR *d = opendir(\".\"); return dirfd(d);}" + HAVE_DIRFD) + +# Only detect readlinkat() if we also have AT_FDCWD in unistd.h. +# NOTE: linux requires fcntl.h for AT_FDCWD. +CHECK_C_SOURCE_COMPILES( + "#include \n#include \nint main() {char buf[10]; return readlinkat(AT_FDCWD, \"\", buf, 0);}" + HAVE_READLINKAT) + + +# To verify major(), we need to both include the header +# of interest and verify that the result can be linked. +# CHECK_FUNCTION_EXISTS doesn't accept a header argument, +# CHECK_SYMBOL_EXISTS doesn't test linkage. +CHECK_C_SOURCE_COMPILES( + "#include \nint main() { return major(256); }" + MAJOR_IN_MKDEV) +CHECK_C_SOURCE_COMPILES( + "#include \nint main() { return major(256); }" + MAJOR_IN_SYSMACROS) + +CHECK_C_SOURCE_COMPILES( + "#include \n#if LZMA_VERSION < 50020000\n#error unsupported\n#endif\nint main(void){lzma_stream_encoder_mt(0, 0); return 0;}" + HAVE_LZMA_STREAM_ENCODER_MT) + +IF(HAVE_STRERROR_R) + SET(HAVE_DECL_STRERROR_R 1) +ENDIF(HAVE_STRERROR_R) + +# +# Check defines +# +SET(headers "limits.h") +IF(HAVE_STDINT_H) + LIST(APPEND headers "stdint.h") +ENDIF(HAVE_STDINT_H) +IF(HAVE_INTTYPES_H) + LIST(APPEND headers "inttypes.h") +ENDIF(HAVE_INTTYPES_H) +CHECK_SYMBOL_EXISTS(EFTYPE "errno.h" HAVE_EFTYPE) +CHECK_SYMBOL_EXISTS(EILSEQ "errno.h" HAVE_EILSEQ) +CHECK_SYMBOL_EXISTS(D_MD_ORDER "langinfo.h" HAVE_D_MD_ORDER) +CHECK_SYMBOL_EXISTS(INT32_MAX "${headers}" HAVE_DECL_INT32_MAX) +CHECK_SYMBOL_EXISTS(INT32_MIN "${headers}" HAVE_DECL_INT32_MIN) +CHECK_SYMBOL_EXISTS(INT64_MAX "${headers}" HAVE_DECL_INT64_MAX) +CHECK_SYMBOL_EXISTS(INT64_MIN "${headers}" HAVE_DECL_INT64_MIN) +CHECK_SYMBOL_EXISTS(INTMAX_MAX "${headers}" HAVE_DECL_INTMAX_MAX) +CHECK_SYMBOL_EXISTS(INTMAX_MIN "${headers}" HAVE_DECL_INTMAX_MIN) +CHECK_SYMBOL_EXISTS(UINT32_MAX "${headers}" HAVE_DECL_UINT32_MAX) +CHECK_SYMBOL_EXISTS(UINT64_MAX "${headers}" HAVE_DECL_UINT64_MAX) +CHECK_SYMBOL_EXISTS(UINTMAX_MAX "${headers}" HAVE_DECL_UINTMAX_MAX) +CHECK_SYMBOL_EXISTS(SIZE_MAX "${headers}" HAVE_DECL_SIZE_MAX) +CHECK_SYMBOL_EXISTS(SSIZE_MAX "limits.h" HAVE_DECL_SSIZE_MAX) + +# +# Check struct members +# +# Check for tm_gmtoff in struct tm +CHECK_STRUCT_HAS_MEMBER("struct tm" tm_gmtoff + "time.h" HAVE_STRUCT_TM_TM_GMTOFF) +CHECK_STRUCT_HAS_MEMBER("struct tm" __tm_gmtoff + "time.h" HAVE_STRUCT_TM___TM_GMTOFF) + +# Check for f_namemax in struct statfs +CHECK_STRUCT_HAS_MEMBER("struct statfs" f_namemax + "sys/param.h;sys/mount.h" HAVE_STRUCT_STATFS_F_NAMEMAX) + +# Check for birthtime in struct stat +CHECK_STRUCT_HAS_MEMBER("struct stat" st_birthtime + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BIRTHTIME) + +# Check for high-resolution timestamps in struct stat +CHECK_STRUCT_HAS_MEMBER("struct stat" st_birthtimespec.tv_nsec + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC) +CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtimespec.tv_nsec + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC) +CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtim.tv_nsec + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) +CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtime_n + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIME_N) +CHECK_STRUCT_HAS_MEMBER("struct stat" st_umtime + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_UMTIME) +CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtime_usec + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIME_USEC) +# Check for block size support in struct stat +CHECK_STRUCT_HAS_MEMBER("struct stat" st_blksize + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BLKSIZE) +# Check for st_flags in struct stat (BSD fflags) +CHECK_STRUCT_HAS_MEMBER("struct stat" st_flags + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_FLAGS) + +IF(HAVE_SYS_STATVFS_H) + CHECK_STRUCT_HAS_MEMBER("struct statvfs" f_iosize + "sys/types.h;sys/statvfs.h" HAVE_STRUCT_STATVFS_F_IOSIZE) +ENDIF() + +# +# +CHECK_STRUCT_HAS_MEMBER("struct tm" tm_sec + "sys/types.h;sys/time.h;time.h" TIME_WITH_SYS_TIME) + +# +# Check for integer types +# +# +CHECK_TYPE_SIZE("short" SIZE_OF_SHORT) +CHECK_TYPE_SIZE("int" SIZE_OF_INT) +CHECK_TYPE_SIZE("long" SIZE_OF_LONG) +CHECK_TYPE_SIZE("long long" SIZE_OF_LONG_LONG) + +CHECK_TYPE_SIZE("unsigned short" SIZE_OF_UNSIGNED_SHORT) +CHECK_TYPE_SIZE("unsigned" SIZE_OF_UNSIGNED) +CHECK_TYPE_SIZE("unsigned long" SIZE_OF_UNSIGNED_LONG) +CHECK_TYPE_SIZE("unsigned long long" SIZE_OF_UNSIGNED_LONG_LONG) + +CHECK_TYPE_SIZE("__int64" __INT64) +CHECK_TYPE_SIZE("unsigned __int64" UNSIGNED___INT64) + +CHECK_TYPE_SIZE(int16_t INT16_T) +CHECK_TYPE_SIZE(int32_t INT32_T) +CHECK_TYPE_SIZE(int64_t INT64_T) +CHECK_TYPE_SIZE(intmax_t INTMAX_T) +CHECK_TYPE_SIZE(uint8_t UINT8_T) +CHECK_TYPE_SIZE(uint16_t UINT16_T) +CHECK_TYPE_SIZE(uint32_t UINT32_T) +CHECK_TYPE_SIZE(uint64_t UINT64_T) +CHECK_TYPE_SIZE(uintmax_t UINTMAX_T) + +CHECK_TYPE_SIZE(dev_t DEV_T) +IF(NOT HAVE_DEV_T) + IF(MSVC) + SET(dev_t "unsigned int") + ENDIF(MSVC) +ENDIF(NOT HAVE_DEV_T) +# +CHECK_TYPE_SIZE(gid_t GID_T) +IF(NOT HAVE_GID_T) + IF(WIN32) + SET(gid_t "short") + ELSE(WIN32) + SET(gid_t "unsigned int") + ENDIF(WIN32) +ENDIF(NOT HAVE_GID_T) +# +CHECK_TYPE_SIZE(id_t ID_T) +IF(NOT HAVE_ID_T) + IF(WIN32) + SET(id_t "short") + ELSE(WIN32) + SET(id_t "unsigned int") + ENDIF(WIN32) +ENDIF(NOT HAVE_ID_T) +# +CHECK_TYPE_SIZE(mode_t MODE_T) +IF(NOT HAVE_MODE_T) + IF(WIN32) + SET(mode_t "unsigned short") + ELSE(WIN32) + SET(mode_t "int") + ENDIF(WIN32) +ENDIF(NOT HAVE_MODE_T) +# +CHECK_TYPE_SIZE(off_t OFF_T) +IF(NOT HAVE_OFF_T) + SET(off_t "__int64") +ENDIF(NOT HAVE_OFF_T) +# +CHECK_TYPE_SIZE(size_t SIZE_T) +IF(NOT HAVE_SIZE_T) + IF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) + SET(size_t "uint64_t") + ELSE("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) + SET(size_t "uint32_t") + ENDIF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) +ENDIF(NOT HAVE_SIZE_T) +# +CHECK_TYPE_SIZE(ssize_t SSIZE_T) +IF(NOT HAVE_SSIZE_T) + IF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) + SET(ssize_t "int64_t") + ELSE("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) + SET(ssize_t "long") + ENDIF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) +ENDIF(NOT HAVE_SSIZE_T) +# +CHECK_TYPE_SIZE(uid_t UID_T) +IF(NOT HAVE_UID_T) + IF(WIN32) + SET(uid_t "short") + ELSE(WIN32) + SET(uid_t "unsigned int") + ENDIF(WIN32) +ENDIF(NOT HAVE_UID_T) +# +CHECK_TYPE_SIZE(pid_t PID_T) +IF(NOT HAVE_PID_T) + IF(WIN32) + SET(pid_t "int") + ELSE(WIN32) + MESSAGE(FATAL_ERROR "pid_t doesn't exist on this platform?") + ENDIF(WIN32) +ENDIF(NOT HAVE_PID_T) +# +CHECK_TYPE_SIZE(intptr_t INTPTR_T) +IF(NOT HAVE_INTPTR_T) + IF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) + SET(intptr_t "int64_t") + ELSE() + SET(intptr_t "int32_t") + ENDIF() +ENDIF(NOT HAVE_INTPTR_T) +# +CHECK_TYPE_SIZE(uintptr_t UINTPTR_T) +IF(NOT HAVE_UINTPTR_T) + IF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) + SET(uintptr_t "uint64_t") + ELSE() + SET(uintptr_t "uint32_t") + ENDIF() +ENDIF(NOT HAVE_UINTPTR_T) +# +CHECK_TYPE_SIZE(wchar_t SIZEOF_WCHAR_T) +IF(HAVE_SIZEOF_WCHAR_T) + SET(HAVE_WCHAR_T 1) +ENDIF(HAVE_SIZEOF_WCHAR_T) +# +# Check if _FILE_OFFSET_BITS macro needed for large files +# +CHECK_FILE_OFFSET_BITS() + +# +# Check for Extended Attribute libraries, headers, and functions +# +IF(ENABLE_XATTR) + CHECK_LIBRARY_EXISTS(attr "setxattr" "" HAVE_LIBATTR) + IF(HAVE_LIBATTR) + SET(CMAKE_REQUIRED_LIBRARIES "attr") + ELSE() + CHECK_LIBRARY_EXISTS(gnu "setxattr" "" HAVE_LIBATTR_GNU) + IF(HAVE_LIBATTR_GNU) + SET(CMAKE_REQUIRED_LIBRARIES "gnu") + ENDIF() + ENDIF(HAVE_LIBATTR) + CHECK_SYMBOL_EXISTS(EXTATTR_NAMESPACE_USER "sys/types.h;sys/extattr.h" HAVE_DECL_EXTATTR_NAMESPACE_USER) + CHECK_SYMBOL_EXISTS(XATTR_NOFOLLOW "sys/xattr.h" HAVE_DECL_XATTR_NOFOLLOW) + IF(HAVE_SYS_XATTR_H AND HAVE_DECL_XATTR_NOFOLLOW) + CHECK_FUNCTION_EXISTS(fgetxattr HAVE_FGETXATTR) + CHECK_FUNCTION_EXISTS(flistxattr HAVE_FLISTXATTR) + CHECK_FUNCTION_EXISTS(fsetxattr HAVE_FSETXATTR) + CHECK_FUNCTION_EXISTS(getxattr HAVE_GETXATTR) + CHECK_FUNCTION_EXISTS(listxattr HAVE_LISTXATTR) + CHECK_FUNCTION_EXISTS(setxattr HAVE_SETXATTR) + IF(HAVE_FGETXATTR AND + HAVE_FLISTXATTR AND + HAVE_FSETXATTR AND + HAVE_GETXATTR AND + HAVE_LISTXATTR AND + HAVE_SETXATTR) + SET(ARCHIVE_XATTR_DARWIN TRUE) + ENDIF() + ELSEIF(HAVE_SYS_EXTATTR_H AND HAVE_DECL_EXTATTR_NAMESPACE_USER) + # FreeBSD xattr support + CHECK_FUNCTION_EXISTS(extattr_get_fd HAVE_EXTATTR_GET_FD) + CHECK_FUNCTION_EXISTS(extattr_get_file HAVE_EXTATTR_GET_FILE) + CHECK_FUNCTION_EXISTS(extattr_get_link HAVE_EXTATTR_GET_LINK) + CHECK_FUNCTION_EXISTS(extattr_list_fd HAVE_EXTATTR_LIST_FD) + CHECK_FUNCTION_EXISTS(extattr_list_file HAVE_EXTATTR_LIST_FILE) + CHECK_FUNCTION_EXISTS(extattr_list_link HAVE_EXTATTR_LIST_LINK) + CHECK_FUNCTION_EXISTS(extattr_set_fd HAVE_EXTATTR_SET_FD) + CHECK_FUNCTION_EXISTS(extattr_set_link HAVE_EXTATTR_SET_LINK) + IF(HAVE_EXTATTR_GET_FD AND + HAVE_EXTATTR_GET_FILE AND + HAVE_EXTATTR_GET_LINK AND + HAVE_EXTATTR_LIST_FD AND + HAVE_EXTATTR_LIST_FILE AND + HAVE_EXTATTR_LIST_LINK AND + HAVE_EXTATTR_SET_FD AND + HAVE_EXTATTR_SET_LINK) + SET(ARCHIVE_XATTR_FREEBSD TRUE) + ENDIF() + ELSEIF(HAVE_SYS_XATTR_H OR HAVE_ATTR_XATTR_H) + # Linux xattr support + CHECK_FUNCTION_EXISTS_GLIBC(fgetxattr HAVE_FGETXATTR) + CHECK_FUNCTION_EXISTS_GLIBC(flistxattr HAVE_FLISTXATTR) + CHECK_FUNCTION_EXISTS_GLIBC(fsetxattr HAVE_FSETXATTR) + CHECK_FUNCTION_EXISTS_GLIBC(getxattr HAVE_GETXATTR) + CHECK_FUNCTION_EXISTS_GLIBC(lgetxattr HAVE_LGETXATTR) + CHECK_FUNCTION_EXISTS_GLIBC(listxattr HAVE_LISTXATTR) + CHECK_FUNCTION_EXISTS_GLIBC(llistxattr HAVE_LLISTXATTR) + CHECK_FUNCTION_EXISTS_GLIBC(lsetxattr HAVE_LSETXATTR) + IF(HAVE_FGETXATTR AND + HAVE_FLISTXATTR AND + HAVE_FSETXATTR AND + HAVE_GETXATTR AND + HAVE_LGETXATTR AND + HAVE_LISTXATTR AND + HAVE_LLISTXATTR AND + HAVE_LSETXATTR) + SET(ARCHIVE_XATTR_LINUX TRUE) + ENDIF() + ELSEIF(HAVE_SYS_EA_H) + # AIX xattr support + CHECK_FUNCTION_EXISTS(fgetea HAVE_FGETEA) + CHECK_FUNCTION_EXISTS(flistea HAVE_FLISTEA) + CHECK_FUNCTION_EXISTS(fsetea HAVE_FSETEA) + CHECK_FUNCTION_EXISTS(getea HAVE_GETEA) + CHECK_FUNCTION_EXISTS(lgetea HAVE_LGETEA) + CHECK_FUNCTION_EXISTS(listea HAVE_LISTEA) + CHECK_FUNCTION_EXISTS(llistea HAVE_LLISTEA) + CHECK_FUNCTION_EXISTS(lsetea HAVE_LSETEA) + IF(HAVE_FGETEA AND + HAVE_FLISTEA AND + HAVE_FSETEA AND + HAVE_GETEA AND + HAVE_LGETEA AND + HAVE_LISTEA AND + HAVE_LLISTEA AND + HAVE_LSETEA) + SET(ARCHIVE_XATTR_AIX TRUE) + ENDIF() + ENDIF() + + IF(ARCHIVE_XATTR_DARWIN) + MESSAGE(STATUS "Extended attributes support: Darwin") + ELSEIF(ARCHIVE_XATTR_FREEBSD) + MESSAGE(STATUS "Extended attributes support: FreeBSD") + ELSEIF(ARCHIVE_XATTR_LINUX) + MESSAGE(STATUS "Extended attributes support: Linux") + ELSEIF(ARCHIVE_XATTR_AIX) + MESSAGE(STATUS "Extended attributes support: AIX") + ELSE() + MESSAGE(STATUS "Extended attributes support: none") + ENDIF() +ELSE(ENABLE_XATTR) + SET(ARCHIVE_XATTR_DARWIN FALSE) + SET(ARCHIVE_XATTR_FREEBSD FALSE) + SET(ARCHIVE_XATTR_LINUX FALSE) + SET(ARCHIVE_XATTR_AIX FALSE) +ENDIF(ENABLE_XATTR) + +# +# Check for ACL libraries, headers, and functions +# +# The ACL support in libarchive is written against the POSIX1e draft, +# which was never officially approved and varies quite a bit across +# platforms. Worse, some systems have completely non-POSIX acl functions, +# which makes the following checks rather more complex than I would like. +# +IF(ENABLE_ACL) + # Solaris and derivates ACLs + CHECK_FUNCTION_EXISTS(acl HAVE_ACL) + CHECK_FUNCTION_EXISTS(facl HAVE_FACL) + + # Libacl + CHECK_LIBRARY_EXISTS(acl "acl_get_file" "" HAVE_LIBACL) + IF(HAVE_LIBACL) + SET(CMAKE_REQUIRED_LIBRARIES "acl") + FIND_LIBRARY(ACL_LIBRARY NAMES acl) + LIST(APPEND ADDITIONAL_LIBS ${ACL_LIBRARY}) + ENDIF(HAVE_LIBACL) + + CHECK_TYPE_EXISTS(acl_t "sys/types.h;sys/acl.h" HAVE_ACL_T) + CHECK_TYPE_EXISTS(acl_entry_t "sys/types.h;sys/acl.h" HAVE_ACL_ENTRY_T) + CHECK_TYPE_EXISTS(acl_permset_t "sys/types.h;sys/acl.h" HAVE_ACL_PERMSET_T) + CHECK_TYPE_EXISTS(acl_tag_t "sys/types.h;sys/acl.h" HAVE_ACL_TAG_T) + + IF(HAVE_ACL AND HAVE_FACL) + CHECK_TYPE_EXISTS(aclent_t "sys/acl.h" HAVE_ACLENT_T) + IF(HAVE_ACLENT_T) + CHECK_SYMBOL_EXISTS(GETACL "sys/acl.h" HAVE_DECL_GETACL) + CHECK_SYMBOL_EXISTS(GETACLCNT "sys/acl.h" HAVE_DECL_GETACLCNT) + CHECK_SYMBOL_EXISTS(SETACL "sys/acl.h" HAVE_DECL_SETACL) + IF(HAVE_DECL_GETACL AND + HAVE_DECL_GETACLCNT AND + HAVE_DECL_SETACL) + SET(ARCHIVE_ACL_SUNOS TRUE) + ENDIF() + CHECK_TYPE_EXISTS(ace_t "sys/acl.h" HAVE_ACE_T) + IF(HAVE_ACE_T) + CHECK_SYMBOL_EXISTS(ACE_GETACL "sys/acl.h" HAVE_DECL_ACE_GETACL) + CHECK_SYMBOL_EXISTS(ACE_GETACLCNT "sys/acl.h" HAVE_DECL_ACE_GETACLCNT) + CHECK_SYMBOL_EXISTS(ACE_SETACL "sys/acl.h" HAVE_DECL_ACE_SETACL) + IF(HAVE_DECL_ACE_GETACL AND + HAVE_DECL_ACE_GETACLCNT AND + HAVE_DECL_ACE_SETACL) + SET(ARCHIVE_ACL_SUNOS_NFS4 TRUE) + ENDIF() + ENDIF(HAVE_ACE_T) + ENDIF(HAVE_ACLENT_T) + ENDIF(HAVE_ACL AND HAVE_FACL) + + IF(HAVE_ACL_T AND HAVE_ACL_ENTRY_T AND HAVE_ACL_PERMSET_T AND HAVE_ACL_TAG_T) + CHECK_FUNCTION_EXISTS_GLIBC(acl_add_perm HAVE_ACL_ADD_PERM) + CHECK_FUNCTION_EXISTS_GLIBC(acl_clear_perms HAVE_ACL_CLEAR_PERMS) + CHECK_FUNCTION_EXISTS_GLIBC(acl_create_entry HAVE_ACL_CREATE_ENTRY) + CHECK_FUNCTION_EXISTS_GLIBC(acl_delete_def_file HAVE_ACL_DELETE_DEF_FILE) + CHECK_FUNCTION_EXISTS_GLIBC(acl_free HAVE_ACL_FREE) + CHECK_FUNCTION_EXISTS_GLIBC(acl_get_entry HAVE_ACL_GET_ENTRY) + CHECK_FUNCTION_EXISTS_GLIBC(acl_get_fd HAVE_ACL_GET_FD) + CHECK_FUNCTION_EXISTS_GLIBC(acl_get_file HAVE_ACL_GET_FILE) + CHECK_FUNCTION_EXISTS_GLIBC(acl_get_permset HAVE_ACL_GET_PERMSET) + CHECK_FUNCTION_EXISTS_GLIBC(acl_get_qualifier HAVE_ACL_GET_QUALIFIER) + CHECK_FUNCTION_EXISTS_GLIBC(acl_get_tag_type HAVE_ACL_GET_TAG_TYPE) + CHECK_FUNCTION_EXISTS_GLIBC(acl_init HAVE_ACL_INIT) + CHECK_FUNCTION_EXISTS_GLIBC(acl_set_fd HAVE_ACL_SET_FD) + CHECK_FUNCTION_EXISTS_GLIBC(acl_set_file HAVE_ACL_SET_FILE) + CHECK_FUNCTION_EXISTS_GLIBC(acl_set_qualifier HAVE_ACL_SET_QUALIFIER) + CHECK_FUNCTION_EXISTS_GLIBC(acl_set_tag_type HAVE_ACL_SET_TAG_TYPE) + IF(HAVE_ACL_ADD_PERM AND + HAVE_ACL_CLEAR_PERMS AND + HAVE_ACL_CREATE_ENTRY AND + HAVE_ACL_DELETE_DEF_FILE AND + HAVE_ACL_FREE AND + HAVE_ACL_GET_ENTRY AND + HAVE_ACL_GET_FD AND + HAVE_ACL_GET_FILE AND + HAVE_ACL_GET_PERMSET AND + HAVE_ACL_GET_QUALIFIER AND + HAVE_ACL_GET_TAG_TYPE AND + HAVE_ACL_INIT AND + HAVE_ACL_SET_FD AND + HAVE_ACL_SET_FILE AND + HAVE_ACL_SET_QUALIFIER AND + HAVE_ACL_SET_TAG_TYPE) + SET(HAVE_POSIX_ACL_FUNCS 1) + ENDIF() + + CHECK_FUNCTION_EXISTS_GLIBC(acl_get_perm HAVE_ACL_GET_PERM) + + IF(HAVE_POSIX_ACL_FUNCS AND HAVE_ACL_LIBACL_H AND HAVE_LIBACL AND + HAVE_ACL_GET_PERM) + SET(ARCHIVE_ACL_LIBACL TRUE) + ELSE() + CHECK_FUNCTION_EXISTS(acl_add_flag_np HAVE_ACL_ADD_FLAG_NP) + CHECK_FUNCTION_EXISTS(acl_clear_flags_np HAVE_ACL_CLEAR_FLAGS_NP) + CHECK_FUNCTION_EXISTS(acl_get_brand_np HAVE_ACL_GET_BRAND_NP) + CHECK_FUNCTION_EXISTS(acl_get_entry_type_np HAVE_ACL_GET_ENTRY_TYPE_NP) + CHECK_FUNCTION_EXISTS(acl_get_flag_np HAVE_ACL_GET_FLAG_NP) + CHECK_FUNCTION_EXISTS(acl_get_flagset_np HAVE_ACL_GET_FLAGSET_NP) + CHECK_FUNCTION_EXISTS(acl_get_fd_np HAVE_ACL_GET_FD_NP) + CHECK_FUNCTION_EXISTS(acl_get_link_np HAVE_ACL_GET_LINK_NP) + CHECK_FUNCTION_EXISTS(acl_get_perm_np HAVE_ACL_GET_PERM_NP) + CHECK_FUNCTION_EXISTS(acl_is_trivial_np HAVE_ACL_IS_TRIVIAL_NP) + CHECK_FUNCTION_EXISTS(acl_set_entry_type_np HAVE_ACL_SET_ENTRY_TYPE_NP) + CHECK_FUNCTION_EXISTS(acl_set_fd_np HAVE_ACL_SET_FD_NP) + CHECK_FUNCTION_EXISTS(acl_set_link_np HAVE_ACL_SET_LINK_NP) + CHECK_FUNCTION_EXISTS(mbr_gid_to_uuid HAVE_MBR_GID_TO_UUID) + CHECK_FUNCTION_EXISTS(mbr_uid_to_uuid HAVE_MBR_UID_TO_UUID) + CHECK_FUNCTION_EXISTS(mbr_uuid_to_id HAVE_MBR_UUID_TO_ID) + + CHECK_C_SOURCE_COMPILES("#include +#include +int main(void) { return ACL_TYPE_EXTENDED; }" HAVE_DECL_ACL_TYPE_EXTENDED) + CHECK_C_SOURCE_COMPILES("#include +#include +int main(void) { return ACL_SYNCHRONIZE; }" HAVE_DECL_ACL_SYNCHRONIZE) + CHECK_SYMBOL_EXISTS(ACL_TYPE_NFS4 "sys/acl.h" HAVE_DECL_ACL_TYPE_NFS4) + CHECK_SYMBOL_EXISTS(ACL_USER "sys/acl.h" HAVE_DECL_ACL_USER) + + IF(HAVE_POSIX_ACL_FUNCS AND + HAVE_ACL_GET_FD_NP AND + HAVE_ACL_GET_PERM_NP AND + NOT HAVE_ACL_GET_PERM AND + HAVE_ACL_SET_FD_NP) + IF(HAVE_DECL_ACL_USER) + SET(ARCHIVE_ACL_FREEBSD TRUE) + IF(HAVE_DECL_ACL_TYPE_NFS4 AND + HAVE_ACL_ADD_FLAG_NP AND + HAVE_ACL_CLEAR_FLAGS_NP AND + HAVE_ACL_GET_BRAND_NP AND + HAVE_ACL_GET_ENTRY_TYPE_NP AND + HAVE_ACL_GET_FLAGSET_NP AND + HAVE_ACL_SET_ENTRY_TYPE_NP) + SET(ARCHIVE_ACL_FREEBSD_NFS4 TRUE) + ENDIF() + ELSEIF(HAVE_DECL_ACL_TYPE_EXTENDED AND + HAVE_MEMBERSHIP_H AND + HAVE_ACL_ADD_FLAG_NP AND + HAVE_ACL_CLEAR_FLAGS_NP AND + HAVE_ACL_GET_FLAGSET_NP AND + HAVE_ACL_GET_LINK_NP AND + HAVE_ACL_SET_LINK_NP AND + HAVE_MBR_UID_TO_UUID AND + HAVE_MBR_GID_TO_UUID AND + HAVE_MBR_UUID_TO_ID) + SET(ARCHIVE_ACL_DARWIN TRUE) + ENDIF() + ENDIF() + ENDIF() + ENDIF(HAVE_ACL_T AND HAVE_ACL_ENTRY_T AND HAVE_ACL_PERMSET_T AND + HAVE_ACL_TAG_T) + + # Richacl + CHECK_LIBRARY_EXISTS(richacl "richacl_get_file" "" HAVE_LIBRICHACL) + IF(HAVE_LIBRICHACL) + SET(CMAKE_REQUIRED_LIBRARIES "richacl") + FIND_LIBRARY(RICHACL_LIBRARY NAMES richacl) + LIST(APPEND ADDITIONAL_LIBS ${RICHACL_LIBRARY}) + ENDIF(HAVE_LIBRICHACL) + + CHECK_STRUCT_HAS_MEMBER("struct richace" e_type "sys/richacl.h" + HAVE_STRUCT_RICHACE) + CHECK_STRUCT_HAS_MEMBER("struct richacl" a_flags "sys/richacl.h" + HAVE_STRUCT_RICHACL) + + IF(HAVE_LIBRICHACL AND HAVE_STRUCT_RICHACL AND HAVE_STRUCT_RICHACE) + CHECK_FUNCTION_EXISTS_GLIBC(richacl_alloc HAVE_RICHACL_ALLOC) + CHECK_FUNCTION_EXISTS_GLIBC(richacl_equiv_mode HAVE_RICHACL_EQUIV_MODE) + CHECK_FUNCTION_EXISTS_GLIBC(richacl_free HAVE_RICHACL_FREE) + CHECK_FUNCTION_EXISTS_GLIBC(richacl_get_fd HAVE_RICHACL_GET_FD) + CHECK_FUNCTION_EXISTS_GLIBC(richacl_get_file HAVE_RICHACL_GET_FILE) + CHECK_FUNCTION_EXISTS_GLIBC(richacl_set_fd HAVE_RICHACL_SET_FD) + CHECK_FUNCTION_EXISTS_GLIBC(richacl_set_file HAVE_RICHACL_SET_FILE) + IF(HAVE_RICHACL_ALLOC AND + HAVE_RICHACL_EQUIV_MODE AND + HAVE_RICHACL_FREE AND + HAVE_RICHACL_GET_FD AND + HAVE_RICHACL_GET_FILE AND + HAVE_RICHACL_SET_FD AND + HAVE_RICHACL_SET_FILE) + SET(ARCHIVE_ACL_LIBRICHACL TRUE) + ENDIF() + ENDIF(HAVE_LIBRICHACL AND HAVE_STRUCT_RICHACL AND HAVE_STRUCT_RICHACE) + + IF(ARCHIVE_ACL_DARWIN) + MESSAGE(STATUS "ACL support: Darwin (limited NFSv4)") + ELSEIF(ARCHIVE_ACL_FREEBSD_NFS4) + MESSAGE(STATUS "ACL support: FreeBSD (POSIX.1e and NFSv4)") + ELSEIF(ARCHIVE_ACL_FREEBSD) + MESSAGE(STATUS "ACL support: FreeBSD (POSIX.1e)") + ELSEIF(ARCHIVE_ACL_LIBACL OR ARCHIVE_ACL_LIBRICHACL) + IF(ARCHIVE_ACL_LIBACL AND ARCHIVE_ACL_LIBRICHACL) + MESSAGE(STATUS "ACL support: libacl (POSIX.1e) + librichacl (NFSv4)") + ELSEIF(ARCHIVE_ACL_LIBRICHACL) + MESSAGE(STATUS "ACL support: librichacl (NFSv4)") + ELSE() + MESSAGE(STATUS "ACL support: libacl (POSIX.1e)") + ENDIF() + ELSEIF(ARCHIVE_ACL_SUNOS_NFS4) + MESSAGE(STATUS "ACL support: Solaris (POSIX.1e and NFSv4)") + ELSEIF(ARCHIVE_ACL_SUNOS) + MESSAGE(STATUS "ACL support: Solaris (POSIX.1e)") + ELSE() + MESSAGE(STATUS "ACL support: none") + ENDIF() + +ELSE(ENABLE_ACL) + # If someone runs cmake, then disables ACL support, we need + # to forcibly override the cached values for these. + SET(ARCHIVE_ACL_DARWIN FALSE) + SET(ARCHIVE_ACL_FREEBSD FALSE) + SET(ARCHIVE_ACL_FREEBSD_NFS4 FALSE) + SET(ARCHIVE_ACL_LIBACL FALSE) + SET(ARCHIVE_ACL_SUNOS FALSE) + SET(ARCHIVE_ACL_SUNOS_NFS4 FALSE) +ENDIF(ENABLE_ACL) + +# +# Check MD5/RMD160/SHA support +# NOTE: Crypto checks must be run last before generating config.h +# +CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA384;SHA512" LIBC) +CHECK_CRYPTO("SHA256;SHA384;SHA512" LIBC2) +CHECK_CRYPTO("SHA256;SHA384;SHA512" LIBC3) +CHECK_CRYPTO("MD5;SHA1;SHA256;SHA384;SHA512" LIBSYSTEM) +CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA384;SHA512" MBEDTLS) +CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA384;SHA512" NETTLE) +CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA384;SHA512" OPENSSL) + +# Libmd has to be probed after OpenSSL. +CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA512" LIBMD) + +CHECK_CRYPTO_WIN("MD5;SHA1;SHA256;SHA384;SHA512") + +# Generate "config.h" from "build/cmake/config.h.in" +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in + ${CMAKE_CURRENT_BINARY_DIR}/config.h) +INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) +ADD_DEFINITIONS(-DHAVE_CONFIG_H) + +# Handle generation of the libarchive.pc file for pkg-config +INCLUDE(CreatePkgConfigFile) + +# +# Register installation of PDF documents. +# +IF(WIN32 AND NOT CYGWIN) + # + # On Windows platform, It's better that we install PDF documents + # on one's computer. + # These PDF documents are available in the release package. + # + IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/doc/pdf) + INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc/pdf + DESTINATION share/man + FILES_MATCHING PATTERN "*.pdf" + ) + ENDIF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/doc/pdf) +ENDIF(WIN32 AND NOT CYGWIN) +# +# +# +INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/libarchive) +# +IF(MSVC) + ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE) +ENDIF(MSVC) + +IF(ENABLE_TEST) + ADD_CUSTOM_TARGET(run_all_tests) +ENDIF(ENABLE_TEST) + +add_subdirectory(libarchive) +add_subdirectory(cat) +add_subdirectory(tar) +add_subdirectory(cpio) diff --git a/dependencies/libarchive-3.4.2/COPYING b/dependencies/libarchive-3.4.2/COPYING new file mode 100644 index 0000000..14bbefa --- /dev/null +++ b/dependencies/libarchive-3.4.2/COPYING @@ -0,0 +1,66 @@ +The libarchive distribution as a whole is Copyright by Tim Kientzle +and is subject to the copyright notice reproduced at the bottom of +this file. + +Each individual file in this distribution should have a clear +copyright/licensing statement at the beginning of the file. If any do +not, please let me know and I will rectify it. The following is +intended to summarize the copyright status of the individual files; +the actual statements in the files are controlling. + +* Except as listed below, all C sources (including .c and .h files) + and documentation files are subject to the copyright notice reproduced + at the bottom of this file. + +* The following source files are also subject in whole or in part to + a 3-clause UC Regents copyright; please read the individual source + files for details: + libarchive/archive_entry.c + libarchive/archive_read_support_filter_compress.c + libarchive/archive_write_add_filter_compress.c + libarchive/mtree.5 + +* The following source files are in the public domain: + libarchive/archive_getdate.c + +* The following source files are triple-licensed with the ability to choose + from CC0 1.0 Universal, OpenSSL or Apache 2.0 licenses: + libarchive/archive_blake2.h + libarchive/archive_blake2_impl.h + libarchive/archive_blake2s_ref.c + libarchive/archive_blake2sp_ref.c + +* The build files---including Makefiles, configure scripts, + and auxiliary scripts used as part of the compile process---have + widely varying licensing terms. Please check individual files before + distributing them to see if those restrictions apply to you. + +I intend for all new source code to use the license below and hope over +time to replace code with other licenses with new implementations that +do use the license below. The varying licensing of the build scripts +seems to be an unavoidable mess. + + +Copyright (c) 2003-2018 +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer + in this position and unchanged. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/dependencies/libarchive-3.4.2/INSTALL b/dependencies/libarchive-3.4.2/INSTALL new file mode 100644 index 0000000..2fafbd5 --- /dev/null +++ b/dependencies/libarchive-3.4.2/INSTALL @@ -0,0 +1,35 @@ +More complete build documentation is available on the libarchive +Wiki: https://github.com/libarchive/libarchive/wiki + +On most Unix-like systems, you should be able to install libarchive, +bsdtar, and bsdcpio using the following common steps: + ./configure + make + make install + +If you need to customize the target directories or otherwise adjust +the build setting, use + ./configure --help +to list the configure options. + +If you are developing libarchive and need to update the +configure script and other build files: + /bin/sh build/autogen.sh + +To create a distribution, please use the 'distcheck' target: + /bin/sh build/autogen.sh && ./configure && make distcheck + +On Unix-like and non-Unix-like systems, use the "cmake" utility (available from +http://cmake.org/) to generate suitable build files for your platform. +Cmake requires the name of the directory containing CmakeLists.txt and +the "generator" to use for your build environment. For example, to +build with Xcode on Mac OS, you can use the following command: + cmake -G "Xcode" ~/libarchive-download-dir/ +The result will be appropriate makefiles, solution files, or project +files that can be used with the corresponding development tool. +The default on Unix-like systems is to generate Makefiles, so you +can also use cmake instead of the configure script: + cmake ~/libarchive-download-dir/ + make + make install +See the libarchive Wiki or the cmake site for further documentation. diff --git a/dependencies/libarchive-3.4.2/Makefile.am b/dependencies/libarchive-3.4.2/Makefile.am new file mode 100644 index 0000000..41b2808 --- /dev/null +++ b/dependencies/libarchive-3.4.2/Makefile.am @@ -0,0 +1,1405 @@ +## Process this file with automake to produce Makefile.in + +AUTOMAKE_OPTIONS= foreign subdir-objects +ACLOCAL_AMFLAGS = -I build/autoconf + +# +# What to build and install +# +lib_LTLIBRARIES= libarchive.la +noinst_LTLIBRARIES= libarchive_fe.la +bin_PROGRAMS= $(bsdtar_programs) $(bsdcpio_programs) $(bsdcat_programs) +man_MANS= $(libarchive_man_MANS) $(bsdtar_man_MANS) $(bsdcpio_man_MANS) $(bsdcat_man_MANS) +BUILT_SOURCES= libarchive/test/list.h tar/test/list.h cpio/test/list.h cat/test/list.h + +# +# What to test: We always test libarchive, test bsdtar and bsdcpio only +# if we built them. +# +check_PROGRAMS= libarchive_test $(bsdtar_test_programs) $(bsdcpio_test_programs) $(bsdcat_test_programs) +TESTS= libarchive_test $(bsdtar_test_programs) $(bsdcpio_test_programs) $(bsdcat_test_programs) +TESTS_ENVIRONMENT= $(libarchive_TESTS_ENVIRONMENT) $(bsdtar_TESTS_ENVIRONMENT) $(bsdcpio_TESTS_ENVIRONMENT) $(bsdcat_TESTS_ENVIRONMENT) +# Always build and test both bsdtar and bsdcpio as part of 'distcheck' +DISTCHECK_CONFIGURE_FLAGS = --enable-bsdtar --enable-bsdcpio +# The next line is commented out by default in shipping libarchive releases. +# It is uncommented by default in trunk. +# DEV_CFLAGS=-Werror -Wextra -Wunused -Wshadow -Wmissing-prototypes -Wcast-qual -g +AM_CFLAGS=$(DEV_CFLAGS) +PLATFORMCPPFLAGS = @PLATFORMCPPFLAGS@ +AM_CPPFLAGS=$(PLATFORMCPPFLAGS) + +# +# What to include in the distribution +# +EXTRA_DIST= \ + CMakeLists.txt \ + README.md \ + build/autogen.sh \ + build/bump-version.sh \ + build/clean.sh \ + build/cmake \ + build/version \ + contrib \ + doc \ + examples \ + $(libarchive_EXTRA_DIST) \ + $(libarchive_test_EXTRA_DIST) \ + $(bsdtar_EXTRA_DIST) \ + $(bsdtar_test_EXTRA_DIST) \ + $(bsdcpio_EXTRA_DIST) \ + $(bsdcpio_test_EXTRA_DIST) \ + $(bsdcat_EXTRA_DIST) \ + $(bsdcat_test_EXTRA_DIST) + +# a) Clean out some unneeded files and directories +# b) Collect all documentation and format it for distribution. +dist-hook: + rm -rf `find $(distdir) -name CVS -type d` + rm -rf `find $(distdir) -name .svn -type d` + rm -f `find $(distdir) -name '*~'` + rm -f `find $(distdir) -name '*.out'` + rm -f `find $(distdir) -name '*.core'` + -rm -f $(distdir)/*/Makefile $(distdir)/*/*/Makefile + cd $(distdir)/doc && /bin/sh update.sh + +# +# Extra rules for cleanup +# +DISTCLEANFILES= \ + libarchive/test/list.h \ + tar/test/list.h \ + cpio/test/list.h \ + cat/test/list.h + +distclean-local: + -rm -rf .ref + -rm -rf autom4te.cache/ + -rm -f *~ + -[ -f libarchive/Makefile ] && cd libarchive && make clean + -[ -f libarchive/test/Makefile ] && cd libarchive/test && make clean + -[ -f tar/Makefile ] && cd tar && make clean + -[ -f tar/test/Makefile ] && cd tar/test && make clean + -[ -f cpio/Makefile ] && cd cpio && make clean + -[ -f cpio/test/Makefile ] && cd cpio/test && make clean + -[ -f cat/Makefile ] && cd cat && make clean + -[ -f cpio/test/Makefile ] && cd cat/test && make clean + +# +# Libarchive headers, source, etc. +# +# + +include_HEADERS= libarchive/archive.h libarchive/archive_entry.h + +libarchive_la_SOURCES= \ + libarchive/archive_acl.c \ + libarchive/archive_acl_private.h \ + libarchive/archive_check_magic.c \ + libarchive/archive_cmdline.c \ + libarchive/archive_cmdline_private.h \ + libarchive/archive_crc32.h \ + libarchive/archive_cryptor.c \ + libarchive/archive_cryptor_private.h \ + libarchive/archive_digest.c \ + libarchive/archive_digest_private.h \ + libarchive/archive_endian.h \ + libarchive/archive_entry.c \ + libarchive/archive_entry.h \ + libarchive/archive_entry_copy_stat.c \ + libarchive/archive_entry_link_resolver.c \ + libarchive/archive_entry_locale.h \ + libarchive/archive_entry_private.h \ + libarchive/archive_entry_sparse.c \ + libarchive/archive_entry_stat.c \ + libarchive/archive_entry_strmode.c \ + libarchive/archive_entry_xattr.c \ + libarchive/archive_getdate.c \ + libarchive/archive_getdate.h \ + libarchive/archive_hmac.c \ + libarchive/archive_hmac_private.h \ + libarchive/archive_match.c \ + libarchive/archive_openssl_evp_private.h \ + libarchive/archive_openssl_hmac_private.h \ + libarchive/archive_options.c \ + libarchive/archive_options_private.h \ + libarchive/archive_pack_dev.h \ + libarchive/archive_pack_dev.c \ + libarchive/archive_pathmatch.c \ + libarchive/archive_pathmatch.h \ + libarchive/archive_platform.h \ + libarchive/archive_platform_acl.h \ + libarchive/archive_platform_xattr.h \ + libarchive/archive_ppmd_private.h \ + libarchive/archive_ppmd7.c \ + libarchive/archive_ppmd7_private.h \ + libarchive/archive_ppmd8.c \ + libarchive/archive_ppmd8_private.h \ + libarchive/archive_private.h \ + libarchive/archive_random.c \ + libarchive/archive_random_private.h \ + libarchive/archive_rb.c \ + libarchive/archive_rb.h \ + libarchive/archive_read.c \ + libarchive/archive_read_add_passphrase.c \ + libarchive/archive_read_append_filter.c \ + libarchive/archive_read_data_into_fd.c \ + libarchive/archive_read_disk_entry_from_file.c \ + libarchive/archive_read_disk_posix.c \ + libarchive/archive_read_disk_private.h \ + libarchive/archive_read_disk_set_standard_lookup.c \ + libarchive/archive_read_extract.c \ + libarchive/archive_read_extract2.c \ + libarchive/archive_read_open_fd.c \ + libarchive/archive_read_open_file.c \ + libarchive/archive_read_open_filename.c \ + libarchive/archive_read_open_memory.c \ + libarchive/archive_read_private.h \ + libarchive/archive_read_set_format.c \ + libarchive/archive_read_set_options.c \ + libarchive/archive_read_support_filter_all.c \ + libarchive/archive_read_support_filter_bzip2.c \ + libarchive/archive_read_support_filter_compress.c \ + libarchive/archive_read_support_filter_grzip.c \ + libarchive/archive_read_support_filter_gzip.c \ + libarchive/archive_read_support_filter_lrzip.c \ + libarchive/archive_read_support_filter_lz4.c \ + libarchive/archive_read_support_filter_lzop.c \ + libarchive/archive_read_support_filter_none.c \ + libarchive/archive_read_support_filter_program.c \ + libarchive/archive_read_support_filter_rpm.c \ + libarchive/archive_read_support_filter_uu.c \ + libarchive/archive_read_support_filter_xz.c \ + libarchive/archive_read_support_filter_zstd.c \ + libarchive/archive_read_support_format_7zip.c \ + libarchive/archive_read_support_format_all.c \ + libarchive/archive_read_support_format_ar.c \ + libarchive/archive_read_support_format_by_code.c \ + libarchive/archive_read_support_format_cab.c \ + libarchive/archive_read_support_format_cpio.c \ + libarchive/archive_read_support_format_empty.c \ + libarchive/archive_read_support_format_iso9660.c \ + libarchive/archive_read_support_format_lha.c \ + libarchive/archive_read_support_format_mtree.c \ + libarchive/archive_read_support_format_rar.c \ + libarchive/archive_read_support_format_rar5.c \ + libarchive/archive_read_support_format_raw.c \ + libarchive/archive_read_support_format_tar.c \ + libarchive/archive_read_support_format_warc.c \ + libarchive/archive_read_support_format_xar.c \ + libarchive/archive_read_support_format_zip.c \ + libarchive/archive_string.c \ + libarchive/archive_string.h \ + libarchive/archive_string_composition.h \ + libarchive/archive_string_sprintf.c \ + libarchive/archive_util.c \ + libarchive/archive_version_details.c \ + libarchive/archive_virtual.c \ + libarchive/archive_write.c \ + libarchive/archive_write_disk_posix.c \ + libarchive/archive_write_disk_private.h \ + libarchive/archive_write_disk_set_standard_lookup.c \ + libarchive/archive_write_open_fd.c \ + libarchive/archive_write_open_file.c \ + libarchive/archive_write_open_filename.c \ + libarchive/archive_write_open_memory.c \ + libarchive/archive_write_private.h \ + libarchive/archive_write_add_filter.c \ + libarchive/archive_write_add_filter_b64encode.c \ + libarchive/archive_write_add_filter_by_name.c \ + libarchive/archive_write_add_filter_bzip2.c \ + libarchive/archive_write_add_filter_compress.c \ + libarchive/archive_write_add_filter_grzip.c \ + libarchive/archive_write_add_filter_gzip.c \ + libarchive/archive_write_add_filter_lrzip.c \ + libarchive/archive_write_add_filter_lz4.c \ + libarchive/archive_write_add_filter_lzop.c \ + libarchive/archive_write_add_filter_none.c \ + libarchive/archive_write_add_filter_program.c \ + libarchive/archive_write_add_filter_uuencode.c \ + libarchive/archive_write_add_filter_xz.c \ + libarchive/archive_write_add_filter_zstd.c \ + libarchive/archive_write_set_format.c \ + libarchive/archive_write_set_format_7zip.c \ + libarchive/archive_write_set_format_ar.c \ + libarchive/archive_write_set_format_by_name.c \ + libarchive/archive_write_set_format_cpio.c \ + libarchive/archive_write_set_format_cpio_newc.c \ + libarchive/archive_write_set_format_filter_by_ext.c \ + libarchive/archive_write_set_format_iso9660.c \ + libarchive/archive_write_set_format_mtree.c \ + libarchive/archive_write_set_format_pax.c \ + libarchive/archive_write_set_format_private.h \ + libarchive/archive_write_set_format_raw.c \ + libarchive/archive_write_set_format_shar.c \ + libarchive/archive_write_set_format_ustar.c \ + libarchive/archive_write_set_format_v7tar.c \ + libarchive/archive_write_set_format_gnutar.c \ + libarchive/archive_write_set_format_warc.c \ + libarchive/archive_write_set_format_xar.c \ + libarchive/archive_write_set_format_zip.c \ + libarchive/archive_write_set_options.c \ + libarchive/archive_write_set_passphrase.c \ + libarchive/archive_xxhash.h \ + libarchive/config_freebsd.h \ + libarchive/filter_fork_posix.c \ + libarchive/filter_fork.h \ + libarchive/xxhash.c + +if INC_WINDOWS_FILES +libarchive_la_SOURCES+= \ + libarchive/archive_entry_copy_bhfi.c \ + libarchive/archive_read_disk_windows.c \ + libarchive/archive_windows.h \ + libarchive/archive_windows.c \ + libarchive/archive_write_disk_windows.c \ + libarchive/filter_fork_windows.c +endif + +if INC_BLAKE2 +libarchive_la_SOURCES+= \ + libarchive/archive_blake2.h \ + libarchive/archive_blake2_impl.h \ + libarchive/archive_blake2s_ref.c \ + libarchive/archive_blake2sp_ref.c +endif + +if INC_LINUX_ACL +libarchive_la_SOURCES+= libarchive/archive_disk_acl_linux.c +else +if INC_SUNOS_ACL +libarchive_la_SOURCES+= libarchive/archive_disk_acl_sunos.c +else +if INC_DARWIN_ACL +libarchive_la_SOURCES+= libarchive/archive_disk_acl_darwin.c +else +if INC_FREEBSD_ACL +libarchive_la_SOURCES+= libarchive/archive_disk_acl_freebsd.c +endif +endif +endif +endif + +# -no-undefined marks that libarchive doesn't rely on symbols +# defined in the application. This is mandatory for cygwin. +libarchive_la_LDFLAGS= -no-undefined -version-info $(ARCHIVE_LIBTOOL_VERSION) +libarchive_la_LIBADD= $(LTLIBICONV) + +# Manpages to install +libarchive_man_MANS= \ + libarchive/archive_entry.3 \ + libarchive/archive_entry_acl.3 \ + libarchive/archive_entry_linkify.3 \ + libarchive/archive_entry_misc.3 \ + libarchive/archive_entry_paths.3 \ + libarchive/archive_entry_perms.3 \ + libarchive/archive_entry_stat.3 \ + libarchive/archive_entry_time.3 \ + libarchive/archive_read.3 \ + libarchive/archive_read_add_passphrase.3 \ + libarchive/archive_read_data.3 \ + libarchive/archive_read_disk.3 \ + libarchive/archive_read_extract.3 \ + libarchive/archive_read_filter.3 \ + libarchive/archive_read_format.3 \ + libarchive/archive_read_free.3 \ + libarchive/archive_read_header.3 \ + libarchive/archive_read_new.3 \ + libarchive/archive_read_open.3 \ + libarchive/archive_read_set_options.3 \ + libarchive/archive_util.3 \ + libarchive/archive_write.3 \ + libarchive/archive_write_blocksize.3 \ + libarchive/archive_write_data.3 \ + libarchive/archive_write_disk.3 \ + libarchive/archive_write_filter.3 \ + libarchive/archive_write_finish_entry.3 \ + libarchive/archive_write_format.3 \ + libarchive/archive_write_free.3 \ + libarchive/archive_write_header.3 \ + libarchive/archive_write_new.3 \ + libarchive/archive_write_open.3 \ + libarchive/archive_write_set_options.3 \ + libarchive/archive_write_set_passphrase.3 \ + libarchive/cpio.5 \ + libarchive/libarchive.3 \ + libarchive/libarchive_changes.3 \ + libarchive/libarchive_internals.3 \ + libarchive/libarchive-formats.5 \ + libarchive/mtree.5 \ + libarchive/tar.5 + +# Additional libarchive files to include in the distribution +libarchive_EXTRA_DIST= \ + libarchive/archive_windows.c \ + libarchive/archive_windows.h \ + libarchive/filter_fork_windows.c \ + libarchive/CMakeLists.txt \ + $(libarchive_man_MANS) + +# pkgconfig +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = build/pkgconfig/libarchive.pc + +# Sources needed by all test programs +test_utils_SOURCES= \ + test_utils/test_utils.c \ + test_utils/test_utils.h \ + test_utils/test_main.c \ + test_utils/test_common.h + +# +# +# libarchive_test program +# +# +libarchive_test_SOURCES= \ + $(libarchive_la_SOURCES) \ + $(test_utils_SOURCES) \ + libarchive/test/read_open_memory.c \ + libarchive/test/test.h \ + libarchive/test/test_acl_nfs4.c \ + libarchive/test/test_acl_pax.c \ + libarchive/test/test_acl_platform_nfs4.c \ + libarchive/test/test_acl_platform_posix1e.c \ + libarchive/test/test_acl_posix1e.c \ + libarchive/test/test_acl_text.c \ + libarchive/test/test_archive_api_feature.c \ + libarchive/test/test_archive_clear_error.c \ + libarchive/test/test_archive_cmdline.c \ + libarchive/test/test_archive_digest.c \ + libarchive/test/test_archive_getdate.c \ + libarchive/test/test_archive_match_owner.c \ + libarchive/test/test_archive_match_path.c \ + libarchive/test/test_archive_match_time.c \ + libarchive/test/test_archive_pathmatch.c \ + libarchive/test/test_archive_read_add_passphrase.c \ + libarchive/test/test_archive_read_close_twice.c \ + libarchive/test/test_archive_read_close_twice_open_fd.c \ + libarchive/test/test_archive_read_close_twice_open_filename.c \ + libarchive/test/test_archive_read_multiple_data_objects.c \ + libarchive/test/test_archive_read_next_header_empty.c \ + libarchive/test/test_archive_read_next_header_raw.c \ + libarchive/test/test_archive_read_open2.c \ + libarchive/test/test_archive_read_set_filter_option.c \ + libarchive/test/test_archive_read_set_format_option.c \ + libarchive/test/test_archive_read_set_option.c \ + libarchive/test/test_archive_read_set_options.c \ + libarchive/test/test_archive_read_support.c \ + libarchive/test/test_archive_set_error.c \ + libarchive/test/test_archive_string.c \ + libarchive/test/test_archive_string_conversion.c \ + libarchive/test/test_archive_write_add_filter_by_name.c \ + libarchive/test/test_archive_write_set_filter_option.c \ + libarchive/test/test_archive_write_set_format_by_name.c \ + libarchive/test/test_archive_write_set_format_filter_by_ext.c \ + libarchive/test/test_archive_write_set_format_option.c \ + libarchive/test/test_archive_write_set_option.c \ + libarchive/test/test_archive_write_set_options.c \ + libarchive/test/test_archive_write_set_passphrase.c \ + libarchive/test/test_bad_fd.c \ + libarchive/test/test_compat_bzip2.c \ + libarchive/test/test_compat_cpio.c \ + libarchive/test/test_compat_gtar.c \ + libarchive/test/test_compat_gzip.c \ + libarchive/test/test_compat_lz4.c \ + libarchive/test/test_compat_lzip.c \ + libarchive/test/test_compat_lzma.c \ + libarchive/test/test_compat_lzop.c \ + libarchive/test/test_compat_mac.c \ + libarchive/test/test_compat_perl_archive_tar.c \ + libarchive/test/test_compat_plexus_archiver_tar.c \ + libarchive/test/test_compat_solaris_tar_acl.c \ + libarchive/test/test_compat_solaris_pax_sparse.c \ + libarchive/test/test_compat_star_acl.c \ + libarchive/test/test_compat_tar_hardlink.c \ + libarchive/test/test_compat_uudecode.c \ + libarchive/test/test_compat_uudecode_large.c \ + libarchive/test/test_compat_xz.c \ + libarchive/test/test_compat_zip.c \ + libarchive/test/test_compat_zstd.c \ + libarchive/test/test_empty_write.c \ + libarchive/test/test_entry.c \ + libarchive/test/test_entry_strmode.c \ + libarchive/test/test_extattr_freebsd.c \ + libarchive/test/test_filter_count.c \ + libarchive/test/test_fuzz.c \ + libarchive/test/test_gnutar_filename_encoding.c \ + libarchive/test/test_link_resolver.c \ + libarchive/test/test_open_failure.c \ + libarchive/test/test_open_fd.c \ + libarchive/test/test_open_file.c \ + libarchive/test/test_open_filename.c \ + libarchive/test/test_pax_filename_encoding.c \ + libarchive/test/test_pax_xattr_header.c \ + libarchive/test/test_read_data_large.c \ + libarchive/test/test_read_disk.c \ + libarchive/test/test_read_disk_directory_traversals.c \ + libarchive/test/test_read_disk_entry_from_file.c \ + libarchive/test/test_read_extract.c \ + libarchive/test/test_read_file_nonexistent.c \ + libarchive/test/test_read_filter_compress.c \ + libarchive/test/test_read_filter_grzip.c \ + libarchive/test/test_read_filter_lrzip.c \ + libarchive/test/test_read_filter_lzop.c \ + libarchive/test/test_read_filter_lzop_multiple_parts.c \ + libarchive/test/test_read_filter_program.c \ + libarchive/test/test_read_filter_program_signature.c \ + libarchive/test/test_read_filter_uudecode.c \ + libarchive/test/test_read_format_7zip.c \ + libarchive/test/test_read_format_7zip_encryption_data.c \ + libarchive/test/test_read_format_7zip_encryption_partially.c \ + libarchive/test/test_read_format_7zip_encryption_header.c \ + libarchive/test/test_read_format_7zip_malformed.c \ + libarchive/test/test_read_format_7zip_packinfo_digests.c \ + libarchive/test/test_read_format_ar.c \ + libarchive/test/test_read_format_cab.c \ + libarchive/test/test_read_format_cab_filename.c \ + libarchive/test/test_read_format_cpio_afio.c \ + libarchive/test/test_read_format_cpio_bin.c \ + libarchive/test/test_read_format_cpio_bin_Z.c \ + libarchive/test/test_read_format_cpio_bin_be.c \ + libarchive/test/test_read_format_cpio_bin_bz2.c \ + libarchive/test/test_read_format_cpio_bin_gz.c \ + libarchive/test/test_read_format_cpio_bin_le.c \ + libarchive/test/test_read_format_cpio_bin_lzip.c \ + libarchive/test/test_read_format_cpio_bin_lzma.c \ + libarchive/test/test_read_format_cpio_bin_xz.c \ + libarchive/test/test_read_format_cpio_filename.c \ + libarchive/test/test_read_format_cpio_odc.c \ + libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c \ + libarchive/test/test_read_format_cpio_svr4_gzip.c \ + libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c \ + libarchive/test/test_read_format_cpio_svr4c_Z.c \ + libarchive/test/test_read_format_empty.c \ + libarchive/test/test_read_format_gtar_filename.c \ + libarchive/test/test_read_format_gtar_gz.c \ + libarchive/test/test_read_format_gtar_lzma.c \ + libarchive/test/test_read_format_gtar_sparse.c \ + libarchive/test/test_read_format_gtar_sparse_skip_entry.c \ + libarchive/test/test_read_format_iso_Z.c \ + libarchive/test/test_read_format_iso_multi_extent.c \ + libarchive/test/test_read_format_iso_xorriso.c \ + libarchive/test/test_read_format_isojoliet_bz2.c \ + libarchive/test/test_read_format_isojoliet_long.c \ + libarchive/test/test_read_format_isojoliet_rr.c \ + libarchive/test/test_read_format_isojoliet_versioned.c \ + libarchive/test/test_read_format_isorr_bz2.c \ + libarchive/test/test_read_format_isorr_ce.c \ + libarchive/test/test_read_format_isorr_new_bz2.c \ + libarchive/test/test_read_format_isorr_rr_moved.c \ + libarchive/test/test_read_format_isozisofs_bz2.c \ + libarchive/test/test_read_format_lha.c \ + libarchive/test/test_read_format_lha_bugfix_0.c \ + libarchive/test/test_read_format_lha_filename.c \ + libarchive/test/test_read_format_lha_filename_utf16.c \ + libarchive/test/test_read_format_mtree.c \ + libarchive/test/test_read_format_mtree_crash747.c \ + libarchive/test/test_read_format_pax_bz2.c \ + libarchive/test/test_read_format_rar.c \ + libarchive/test/test_read_format_rar_encryption_data.c \ + libarchive/test/test_read_format_rar_encryption_partially.c \ + libarchive/test/test_read_format_rar_encryption_header.c \ + libarchive/test/test_read_format_rar_invalid1.c \ + libarchive/test/test_read_format_rar5.c \ + libarchive/test/test_read_format_raw.c \ + libarchive/test/test_read_format_tar.c \ + libarchive/test/test_read_format_tar_concatenated.c \ + libarchive/test/test_read_format_tar_empty_pax.c \ + libarchive/test/test_read_format_tar_empty_filename.c \ + libarchive/test/test_read_format_tar_empty_with_gnulabel.c \ + libarchive/test/test_read_format_tar_filename.c \ + libarchive/test/test_read_format_tbz.c \ + libarchive/test/test_read_format_tgz.c \ + libarchive/test/test_read_format_tlz.c \ + libarchive/test/test_read_format_txz.c \ + libarchive/test/test_read_format_tz.c \ + libarchive/test/test_read_format_ustar_filename.c \ + libarchive/test/test_read_format_warc.c \ + libarchive/test/test_read_format_xar.c \ + libarchive/test/test_read_format_zip.c \ + libarchive/test/test_read_format_zip_7075_utf8_paths.c \ + libarchive/test/test_read_format_zip_comment_stored.c \ + libarchive/test/test_read_format_zip_encryption_data.c \ + libarchive/test/test_read_format_zip_encryption_partially.c \ + libarchive/test/test_read_format_zip_encryption_header.c \ + libarchive/test/test_read_format_zip_extra_padding.c \ + libarchive/test/test_read_format_zip_filename.c \ + libarchive/test/test_read_format_zip_high_compression.c \ + libarchive/test/test_read_format_zip_jar.c \ + libarchive/test/test_read_format_zip_mac_metadata.c \ + libarchive/test/test_read_format_zip_malformed.c \ + libarchive/test/test_read_format_zip_msdos.c \ + libarchive/test/test_read_format_zip_nested.c \ + libarchive/test/test_read_format_zip_nofiletype.c \ + libarchive/test/test_read_format_zip_padded.c \ + libarchive/test/test_read_format_zip_sfx.c \ + libarchive/test/test_read_format_zip_traditional_encryption_data.c \ + libarchive/test/test_read_format_zip_winzip_aes.c \ + libarchive/test/test_read_format_zip_winzip_aes_large.c \ + libarchive/test/test_read_format_zip_zip64.c \ + libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c \ + libarchive/test/test_read_large.c \ + libarchive/test/test_read_pax_schily_xattr.c \ + libarchive/test/test_read_pax_truncated.c \ + libarchive/test/test_read_position.c \ + libarchive/test/test_read_set_format.c \ + libarchive/test/test_read_too_many_filters.c \ + libarchive/test/test_read_truncated.c \ + libarchive/test/test_read_truncated_filter.c \ + libarchive/test/test_sparse_basic.c \ + libarchive/test/test_tar_filenames.c \ + libarchive/test/test_tar_large.c \ + libarchive/test/test_ustar_filenames.c \ + libarchive/test/test_ustar_filename_encoding.c \ + libarchive/test/test_warn_missing_hardlink_target.c \ + libarchive/test/test_write_disk.c \ + libarchive/test/test_write_disk_appledouble.c \ + libarchive/test/test_write_disk_failures.c \ + libarchive/test/test_write_disk_hardlink.c \ + libarchive/test/test_write_disk_hfs_compression.c \ + libarchive/test/test_write_disk_lookup.c \ + libarchive/test/test_write_disk_mac_metadata.c \ + libarchive/test/test_write_disk_no_hfs_compression.c \ + libarchive/test/test_write_disk_perms.c \ + libarchive/test/test_write_disk_secure.c \ + libarchive/test/test_write_disk_secure744.c \ + libarchive/test/test_write_disk_secure745.c \ + libarchive/test/test_write_disk_secure746.c \ + libarchive/test/test_write_disk_sparse.c \ + libarchive/test/test_write_disk_symlink.c \ + libarchive/test/test_write_disk_times.c \ + libarchive/test/test_write_filter_b64encode.c \ + libarchive/test/test_write_filter_bzip2.c \ + libarchive/test/test_write_filter_compress.c \ + libarchive/test/test_write_filter_gzip.c \ + libarchive/test/test_write_filter_gzip_timestamp.c \ + libarchive/test/test_write_filter_lrzip.c \ + libarchive/test/test_write_filter_lz4.c \ + libarchive/test/test_write_filter_lzip.c \ + libarchive/test/test_write_filter_lzma.c \ + libarchive/test/test_write_filter_lzop.c \ + libarchive/test/test_write_filter_program.c \ + libarchive/test/test_write_filter_uuencode.c \ + libarchive/test/test_write_filter_xz.c \ + libarchive/test/test_write_filter_zstd.c \ + libarchive/test/test_write_format_7zip.c \ + libarchive/test/test_write_format_7zip_empty.c \ + libarchive/test/test_write_format_7zip_large.c \ + libarchive/test/test_write_format_ar.c \ + libarchive/test/test_write_format_cpio.c \ + libarchive/test/test_write_format_cpio_empty.c \ + libarchive/test/test_write_format_cpio_newc.c \ + libarchive/test/test_write_format_cpio_odc.c \ + libarchive/test/test_write_format_gnutar.c \ + libarchive/test/test_write_format_gnutar_filenames.c \ + libarchive/test/test_write_format_iso9660.c \ + libarchive/test/test_write_format_iso9660_boot.c \ + libarchive/test/test_write_format_iso9660_empty.c \ + libarchive/test/test_write_format_iso9660_filename.c \ + libarchive/test/test_write_format_iso9660_zisofs.c \ + libarchive/test/test_write_format_mtree.c \ + libarchive/test/test_write_format_mtree_absolute_path.c \ + libarchive/test/test_write_format_mtree_classic.c \ + libarchive/test/test_write_format_mtree_classic_indent.c\ + libarchive/test/test_write_format_mtree_fflags.c \ + libarchive/test/test_write_format_mtree_no_separator.c \ + libarchive/test/test_write_format_mtree_quoted_filename.c\ + libarchive/test/test_write_format_pax.c \ + libarchive/test/test_write_format_raw.c \ + libarchive/test/test_write_format_raw_b64.c \ + libarchive/test/test_write_format_shar_empty.c \ + libarchive/test/test_write_format_tar.c \ + libarchive/test/test_write_format_tar_empty.c \ + libarchive/test/test_write_format_tar_sparse.c \ + libarchive/test/test_write_format_tar_ustar.c \ + libarchive/test/test_write_format_tar_v7tar.c \ + libarchive/test/test_write_format_warc.c \ + libarchive/test/test_write_format_warc_empty.c \ + libarchive/test/test_write_format_xar.c \ + libarchive/test/test_write_format_xar_empty.c \ + libarchive/test/test_write_format_zip.c \ + libarchive/test/test_write_format_zip_compression_store.c \ + libarchive/test/test_write_format_zip_empty.c \ + libarchive/test/test_write_format_zip_empty_zip64.c \ + libarchive/test/test_write_format_zip_file.c \ + libarchive/test/test_write_format_zip_file_zip64.c \ + libarchive/test/test_write_format_zip_large.c \ + libarchive/test/test_write_format_zip_zip64.c \ + libarchive/test/test_write_open_memory.c \ + libarchive/test/test_write_read_format_zip.c \ + libarchive/test/test_xattr_platform.c \ + libarchive/test/test_zip_filename_encoding.c + +libarchive_test_CPPFLAGS= \ + -I$(top_srcdir)/libarchive \ + -I$(top_srcdir)/libarchive/test \ + -I$(top_srcdir)/test_utils \ + -I$(top_builddir)/libarchive/test \ + -DLIBARCHIVE_STATIC $(PLATFORMCPPFLAGS) + +libarchive_test_LDADD= $(LTLIBICONV) + +# The "list.h" file just lists all of the tests defined in all of the sources. +# Building it automatically provides a sanity-check on libarchive_test_SOURCES +# above. +libarchive/test/list.h: Makefile + $(MKDIR_P) libarchive/test + cat $(top_srcdir)/libarchive/test/test_*.c | grep '^DEFINE_TEST' > libarchive/test/list.h + +libarchive_TESTS_ENVIRONMENT= LIBARCHIVE_TEST_FILES=`cd $(top_srcdir);/bin/pwd`/libarchive/test LRZIP=NOCONFIG + +libarchive_test_EXTRA_DIST=\ + libarchive/test/list.h \ + libarchive/test/test_acl_pax_posix1e.tar.uu \ + libarchive/test/test_acl_pax_nfs4.tar.uu \ + libarchive/test/test_archive_string_conversion.txt.Z.uu \ + libarchive/test/test_compat_bzip2_1.tbz.uu \ + libarchive/test/test_compat_bzip2_2.tbz.uu \ + libarchive/test/test_compat_cpio_1.cpio.uu \ + libarchive/test/test_compat_gtar_1.tar.uu \ + libarchive/test/test_compat_gtar_2.tar.uu \ + libarchive/test/test_compat_gzip_1.tgz.uu \ + libarchive/test/test_compat_gzip_2.tgz.uu \ + libarchive/test/test_compat_lz4_1.tar.lz4.uu \ + libarchive/test/test_compat_lz4_2.tar.lz4.uu \ + libarchive/test/test_compat_lz4_3.tar.lz4.uu \ + libarchive/test/test_compat_lz4_B4.tar.lz4.uu \ + libarchive/test/test_compat_lz4_B4BD.tar.lz4.uu \ + libarchive/test/test_compat_lz4_B4BDBX.tar.lz4.uu \ + libarchive/test/test_compat_lz4_B5.tar.lz4.uu \ + libarchive/test/test_compat_lz4_B5BD.tar.lz4.uu \ + libarchive/test/test_compat_lz4_B6.tar.lz4.uu \ + libarchive/test/test_compat_lz4_B6BD.tar.lz4.uu \ + libarchive/test/test_compat_lz4_B7.tar.lz4.uu \ + libarchive/test/test_compat_lz4_B7BD.tar.lz4.uu \ + libarchive/test/test_compat_lzip_1.tlz.uu \ + libarchive/test/test_compat_lzip_2.tlz.uu \ + libarchive/test/test_compat_lzma_1.tlz.uu \ + libarchive/test/test_compat_lzma_2.tlz.uu \ + libarchive/test/test_compat_lzma_3.tlz.uu \ + libarchive/test/test_compat_lzop_1.tar.lzo.uu \ + libarchive/test/test_compat_lzop_2.tar.lzo.uu \ + libarchive/test/test_compat_lzop_3.tar.lzo.uu \ + libarchive/test/test_compat_mac-1.tar.Z.uu \ + libarchive/test/test_compat_mac-2.tar.Z.uu \ + libarchive/test/test_compat_perl_archive_tar.tar.uu \ + libarchive/test/test_compat_plexus_archiver_tar.tar.uu \ + libarchive/test/test_compat_solaris_pax_sparse_1.pax.Z.uu \ + libarchive/test/test_compat_solaris_pax_sparse_2.pax.Z.uu \ + libarchive/test/test_compat_solaris_tar_acl.tar.uu \ + libarchive/test/test_compat_star_acl_nfs4.tar.uu \ + libarchive/test/test_compat_star_acl_posix1e.tar.uu \ + libarchive/test/test_compat_tar_hardlink_1.tar.uu \ + libarchive/test/test_compat_uudecode_large.tar.Z.uu \ + libarchive/test/test_compat_xz_1.txz.uu \ + libarchive/test/test_compat_zip_1.zip.uu \ + libarchive/test/test_compat_zip_2.zip.uu \ + libarchive/test/test_compat_zip_3.zip.uu \ + libarchive/test/test_compat_zip_4.zip.uu \ + libarchive/test/test_compat_zip_5.zip.uu \ + libarchive/test/test_compat_zip_6.zip.uu \ + libarchive/test/test_compat_zip_7.xps.uu \ + libarchive/test/test_compat_zip_8.zip.uu \ + libarchive/test/test_compat_zstd_1.tar.zst.uu \ + libarchive/test/test_fuzz.cab.uu \ + libarchive/test/test_fuzz.lzh.uu \ + libarchive/test/test_fuzz_1.iso.Z.uu \ + libarchive/test/test_pax_filename_encoding.tar.uu \ + libarchive/test/test_pax_xattr_header_all.tar.uu \ + libarchive/test/test_pax_xattr_header_libarchive.tar.uu \ + libarchive/test/test_pax_xattr_header_schily.tar.uu \ + libarchive/test/test_rar_multivolume_multiple_files.part1.rar.uu \ + libarchive/test/test_rar_multivolume_multiple_files.part2.rar.uu \ + libarchive/test/test_rar_multivolume_multiple_files.part3.rar.uu \ + libarchive/test/test_rar_multivolume_multiple_files.part4.rar.uu \ + libarchive/test/test_rar_multivolume_multiple_files.part5.rar.uu \ + libarchive/test/test_rar_multivolume_multiple_files.part6.rar.uu \ + libarchive/test/test_rar_multivolume_single_file.part1.rar.uu \ + libarchive/test/test_rar_multivolume_single_file.part2.rar.uu \ + libarchive/test/test_rar_multivolume_single_file.part3.rar.uu \ + libarchive/test/test_rar_multivolume_uncompressed_files.part01.rar.uu \ + libarchive/test/test_rar_multivolume_uncompressed_files.part02.rar.uu \ + libarchive/test/test_rar_multivolume_uncompressed_files.part03.rar.uu \ + libarchive/test/test_rar_multivolume_uncompressed_files.part04.rar.uu \ + libarchive/test/test_rar_multivolume_uncompressed_files.part05.rar.uu \ + libarchive/test/test_rar_multivolume_uncompressed_files.part06.rar.uu \ + libarchive/test/test_rar_multivolume_uncompressed_files.part07.rar.uu \ + libarchive/test/test_rar_multivolume_uncompressed_files.part08.rar.uu \ + libarchive/test/test_rar_multivolume_uncompressed_files.part09.rar.uu \ + libarchive/test/test_rar_multivolume_uncompressed_files.part10.rar.uu \ + libarchive/test/test_read_filter_grzip.tar.grz.uu \ + libarchive/test/test_read_filter_lrzip.tar.lrz.uu \ + libarchive/test/test_read_filter_lzop.tar.lzo.uu \ + libarchive/test/test_read_filter_lzop_multiple_parts.tar.lzo.uu \ + libarchive/test/test_read_format_mtree_crash747.mtree.bz2.uu \ + libarchive/test/test_read_format_mtree_noprint.mtree.uu \ + libarchive/test/test_read_format_7zip_bcj2_bzip2.7z.uu \ + libarchive/test/test_read_format_7zip_bcj2_copy_1.7z.uu \ + libarchive/test/test_read_format_7zip_bcj2_copy_2.7z.uu \ + libarchive/test/test_read_format_7zip_bcj2_copy_lzma.7z.uu \ + libarchive/test/test_read_format_7zip_bcj2_deflate.7z.uu \ + libarchive/test/test_read_format_7zip_bcj2_lzma1_1.7z.uu \ + libarchive/test/test_read_format_7zip_bcj2_lzma1_2.7z.uu \ + libarchive/test/test_read_format_7zip_bcj2_lzma2_1.7z.uu \ + libarchive/test/test_read_format_7zip_bcj2_lzma2_2.7z.uu \ + libarchive/test/test_read_format_7zip_bcj_bzip2.7z.uu \ + libarchive/test/test_read_format_7zip_bcj_copy.7z.uu \ + libarchive/test/test_read_format_7zip_bcj_deflate.7z.uu \ + libarchive/test/test_read_format_7zip_bcj_lzma1.7z.uu \ + libarchive/test/test_read_format_7zip_bcj_lzma2.7z.uu \ + libarchive/test/test_read_format_7zip_bzip2.7z.uu \ + libarchive/test/test_read_format_7zip_copy.7z.uu \ + libarchive/test/test_read_format_7zip_copy_2.7z.uu \ + libarchive/test/test_read_format_7zip_deflate.7z.uu \ + libarchive/test/test_read_format_7zip_delta_lzma1.7z.uu \ + libarchive/test/test_read_format_7zip_delta4_lzma1.7z.uu \ + libarchive/test/test_read_format_7zip_delta_lzma2.7z.uu \ + libarchive/test/test_read_format_7zip_delta4_lzma2.7z.uu \ + libarchive/test/test_read_format_7zip_empty_archive.7z.uu \ + libarchive/test/test_read_format_7zip_empty_file.7z.uu \ + libarchive/test/test_read_format_7zip_encryption.7z.uu \ + libarchive/test/test_read_format_7zip_encryption_header.7z.uu \ + libarchive/test/test_read_format_7zip_encryption_partially.7z.uu \ + libarchive/test/test_read_format_7zip_lzma1.7z.uu \ + libarchive/test/test_read_format_7zip_lzma1_2.7z.uu \ + libarchive/test/test_read_format_7zip_lzma1_lzma2.7z.uu \ + libarchive/test/test_read_format_7zip_lzma2.7z.uu \ + libarchive/test/test_read_format_7zip_malformed.7z.uu \ + libarchive/test/test_read_format_7zip_malformed2.7z.uu \ + libarchive/test/test_read_format_7zip_packinfo_digests.7z.uu \ + libarchive/test/test_read_format_7zip_ppmd.7z.uu \ + libarchive/test/test_read_format_7zip_symbolic_name.7z.uu \ + libarchive/test/test_read_format_ar.ar.uu \ + libarchive/test/test_read_format_cab_1.cab.uu \ + libarchive/test/test_read_format_cab_2.cab.uu \ + libarchive/test/test_read_format_cab_3.cab.uu \ + libarchive/test/test_read_format_cab_filename_cp932.cab.uu \ + libarchive/test/test_read_format_cpio_bin_be.cpio.uu \ + libarchive/test/test_read_format_cpio_bin_le.cpio.uu \ + libarchive/test/test_read_format_cpio_filename_cp866.cpio.uu \ + libarchive/test/test_read_format_cpio_filename_eucjp.cpio.uu \ + libarchive/test/test_read_format_cpio_filename_koi8r.cpio.uu \ + libarchive/test/test_read_format_cpio_filename_utf8_jp.cpio.uu \ + libarchive/test/test_read_format_cpio_filename_utf8_ru.cpio.uu \ + libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.rpm.uu \ + libarchive/test/test_read_format_cpio_svr4_gzip_rpm.rpm.uu \ + libarchive/test/test_read_format_gtar_filename_cp866.tar.Z.uu \ + libarchive/test/test_read_format_gtar_filename_eucjp.tar.Z.uu \ + libarchive/test/test_read_format_gtar_filename_koi8r.tar.Z.uu \ + libarchive/test/test_read_format_gtar_sparse_1_13.tar.uu \ + libarchive/test/test_read_format_gtar_sparse_1_17.tar.uu \ + libarchive/test/test_read_format_gtar_sparse_1_17_posix00.tar.uu \ + libarchive/test/test_read_format_gtar_sparse_1_17_posix01.tar.uu \ + libarchive/test/test_read_format_gtar_sparse_1_17_posix10.tar.uu \ + libarchive/test/test_read_format_gtar_sparse_1_17_posix10_modified.tar.uu \ + libarchive/test/test_read_format_gtar_sparse_skip_entry.tar.Z.uu \ + libarchive/test/test_read_format_iso.iso.Z.uu \ + libarchive/test/test_read_format_iso_2.iso.Z.uu \ + libarchive/test/test_read_format_iso_joliet.iso.Z.uu \ + libarchive/test/test_read_format_iso_joliet_by_nero.iso.Z.uu \ + libarchive/test/test_read_format_iso_joliet_long.iso.Z.uu \ + libarchive/test/test_read_format_iso_joliet_rockridge.iso.Z.uu \ + libarchive/test/test_read_format_iso_multi_extent.iso.Z.uu \ + libarchive/test/test_read_format_iso_rockridge.iso.Z.uu \ + libarchive/test/test_read_format_iso_rockridge_ce.iso.Z.uu \ + libarchive/test/test_read_format_iso_rockridge_new.iso.Z.uu \ + libarchive/test/test_read_format_iso_rockridge_rr_moved.iso.Z.uu \ + libarchive/test/test_read_format_iso_xorriso.iso.Z.uu \ + libarchive/test/test_read_format_iso_zisofs.iso.Z.uu \ + libarchive/test/test_read_format_lha_bugfix_0.lzh.uu \ + libarchive/test/test_read_format_lha_filename_cp932.lzh.uu \ + libarchive/test/test_read_format_lha_filename_utf16.lzh.uu \ + libarchive/test/test_read_format_lha_header0.lzh.uu \ + libarchive/test/test_read_format_lha_header1.lzh.uu \ + libarchive/test/test_read_format_lha_header2.lzh.uu \ + libarchive/test/test_read_format_lha_header3.lzh.uu \ + libarchive/test/test_read_format_lha_lh0.lzh.uu \ + libarchive/test/test_read_format_lha_lh6.lzh.uu \ + libarchive/test/test_read_format_lha_lh7.lzh.uu \ + libarchive/test/test_read_format_lha_withjunk.lzh.uu \ + libarchive/test/test_read_format_mtree.mtree.uu \ + libarchive/test/test_read_format_mtree_nomagic.mtree.uu \ + libarchive/test/test_read_format_mtree_nomagic2.mtree.uu \ + libarchive/test/test_read_format_mtree_nomagic3.mtree.uu \ + libarchive/test/test_read_format_rar.rar.uu \ + libarchive/test/test_read_format_rar_binary_data.rar.uu \ + libarchive/test/test_read_format_rar_compress_best.rar.uu \ + libarchive/test/test_read_format_rar_compress_normal.rar.uu \ + libarchive/test/test_read_format_rar_encryption_data.rar.uu \ + libarchive/test/test_read_format_rar_encryption_header.rar.uu \ + libarchive/test/test_read_format_rar_encryption_partially.rar.uu \ + libarchive/test/test_read_format_rar_invalid1.rar.uu \ + libarchive/test/test_read_format_rar_multi_lzss_blocks.rar.uu \ + libarchive/test/test_read_format_rar_multivolume.part0001.rar.uu \ + libarchive/test/test_read_format_rar_multivolume.part0002.rar.uu \ + libarchive/test/test_read_format_rar_multivolume.part0003.rar.uu \ + libarchive/test/test_read_format_rar_multivolume.part0004.rar.uu \ + libarchive/test/test_read_format_rar_noeof.rar.uu \ + libarchive/test/test_read_format_rar_ppmd_lzss_conversion.rar.uu \ + libarchive/test/test_read_format_rar_ppmd_use_after_free.rar.uu \ + libarchive/test/test_read_format_rar_ppmd_use_after_free2.rar.uu \ + libarchive/test/test_read_format_rar_sfx.exe.uu \ + libarchive/test/test_read_format_rar_subblock.rar.uu \ + libarchive/test/test_read_format_rar_unicode.rar.uu \ + libarchive/test/test_read_format_rar_windows.rar.uu \ + libarchive/test/test_read_format_rar5_arm.rar.uu \ + libarchive/test/test_read_format_rar5_blake2.rar.uu \ + libarchive/test/test_read_format_rar5_compressed.rar.uu \ + libarchive/test/test_read_format_rar5_different_window_size.rar.uu \ + libarchive/test/test_read_format_rar5_different_solid_window_size.rar.uu \ + libarchive/test/test_read_format_rar5_distance_overflow.rar.uu \ + libarchive/test/test_read_format_rar5_extra_field_version.rar.uu \ + libarchive/test/test_read_format_rar5_fileattr.rar.uu \ + libarchive/test/test_read_format_rar5_hardlink.rar.uu \ + libarchive/test/test_read_format_rar5_invalid_dict_reference.rar.uu \ + libarchive/test/test_read_format_rar5_leftshift1.rar.uu \ + libarchive/test/test_read_format_rar5_leftshift2.rar.uu \ + libarchive/test/test_read_format_rar5_multiarchive.part01.rar.uu \ + libarchive/test/test_read_format_rar5_multiarchive.part02.rar.uu \ + libarchive/test/test_read_format_rar5_multiarchive.part03.rar.uu \ + libarchive/test/test_read_format_rar5_multiarchive.part04.rar.uu \ + libarchive/test/test_read_format_rar5_multiarchive.part05.rar.uu \ + libarchive/test/test_read_format_rar5_multiarchive.part06.rar.uu \ + libarchive/test/test_read_format_rar5_multiarchive.part07.rar.uu \ + libarchive/test/test_read_format_rar5_multiarchive.part08.rar.uu \ + libarchive/test/test_read_format_rar5_multiarchive_solid.part01.rar.uu \ + libarchive/test/test_read_format_rar5_multiarchive_solid.part02.rar.uu \ + libarchive/test/test_read_format_rar5_multiarchive_solid.part03.rar.uu \ + libarchive/test/test_read_format_rar5_multiarchive_solid.part04.rar.uu \ + libarchive/test/test_read_format_rar5_multiple_files.rar.uu \ + libarchive/test/test_read_format_rar5_multiple_files_solid.rar.uu \ + libarchive/test/test_read_format_rar5_nonempty_dir_stream.rar.uu \ + libarchive/test/test_read_format_rar5_owner.rar.uu \ + libarchive/test/test_read_format_rar5_readtables_overflow.rar.uu \ + libarchive/test/test_read_format_rar5_solid.rar.uu \ + libarchive/test/test_read_format_rar5_stored.rar.uu \ + libarchive/test/test_read_format_rar5_stored_manyfiles.rar.uu \ + libarchive/test/test_read_format_rar5_symlink.rar.uu \ + libarchive/test/test_read_format_rar5_truncated_huff.rar.uu \ + libarchive/test/test_read_format_rar5_win32.rar.uu \ + libarchive/test/test_read_format_rar5_arm_filter_on_window_boundary.rar.uu \ + libarchive/test/test_read_format_rar5_different_winsize_on_merge.rar.uu \ + libarchive/test/test_read_format_rar5_block_size_is_too_small.rar.uu \ + libarchive/test/test_read_format_raw.bufr.uu \ + libarchive/test/test_read_format_raw.data.gz.uu \ + libarchive/test/test_read_format_raw.data.Z.uu \ + libarchive/test/test_read_format_raw.data.uu \ + libarchive/test/test_read_format_tar_concatenated.tar.uu \ + libarchive/test/test_read_format_tar_empty_filename.tar.uu \ + libarchive/test/test_read_format_tar_empty_with_gnulabel.tar.uu \ + libarchive/test/test_read_format_tar_empty_pax.tar.Z.uu \ + libarchive/test/test_read_format_tar_filename_koi8r.tar.Z.uu \ + libarchive/test/test_read_format_ustar_filename_cp866.tar.Z.uu \ + libarchive/test/test_read_format_ustar_filename_eucjp.tar.Z.uu \ + libarchive/test/test_read_format_ustar_filename_koi8r.tar.Z.uu \ + libarchive/test/test_read_format_warc.warc.uu \ + libarchive/test/test_read_format_zip.zip.uu \ + libarchive/test/test_read_format_zip_7075_utf8_paths.zip.uu \ + libarchive/test/test_read_format_zip_bz2_hang.zip.uu \ + libarchive/test/test_read_format_zip_bzip2.zipx.uu \ + libarchive/test/test_read_format_zip_bzip2_multi.zipx.uu \ + libarchive/test/test_read_format_zip_comment_stored_1.zip.uu \ + libarchive/test/test_read_format_zip_comment_stored_2.zip.uu \ + libarchive/test/test_read_format_zip_encryption_data.zip.uu \ + libarchive/test/test_read_format_zip_encryption_header.zip.uu \ + libarchive/test/test_read_format_zip_encryption_partially.zip.uu \ + libarchive/test/test_read_format_zip_extra_padding.zip.uu \ + libarchive/test/test_read_format_zip_filename_cp866.zip.uu \ + libarchive/test/test_read_format_zip_filename_cp932.zip.uu \ + libarchive/test/test_read_format_zip_filename_koi8r.zip.uu \ + libarchive/test/test_read_format_zip_filename_utf8_jp.zip.uu \ + libarchive/test/test_read_format_zip_filename_utf8_ru.zip.uu \ + libarchive/test/test_read_format_zip_filename_utf8_ru2.zip.uu \ + libarchive/test/test_read_format_zip_high_compression.zip.uu \ + libarchive/test/test_read_format_zip_length_at_end.zip.uu \ + libarchive/test/test_read_format_zip_lzma.zipx.uu \ + libarchive/test/test_read_format_zip_lzma_alone_leak.zipx.uu \ + libarchive/test/test_read_format_zip_lzma_multi.zipx.uu \ + libarchive/test/test_read_format_zip_jar.jar.uu \ + libarchive/test/test_read_format_zip_mac_metadata.zip.uu \ + libarchive/test/test_read_format_zip_malformed1.zip.uu \ + libarchive/test/test_read_format_zip_msdos.zip.uu \ + libarchive/test/test_read_format_zip_nested.zip.uu \ + libarchive/test/test_read_format_zip_nofiletype.zip.uu \ + libarchive/test/test_read_format_zip_padded1.zip.uu \ + libarchive/test/test_read_format_zip_padded2.zip.uu \ + libarchive/test/test_read_format_zip_padded3.zip.uu \ + libarchive/test/test_read_format_zip_ppmd8.zipx.uu \ + libarchive/test/test_read_format_zip_ppmd8_crash_1.zipx.uu \ + libarchive/test/test_read_format_zip_ppmd8_crash_2.zipx.uu \ + libarchive/test/test_read_format_zip_ppmd8_multi.zipx.uu \ + libarchive/test/test_read_format_zip_sfx.uu \ + libarchive/test/test_read_format_zip_symlink.zip.uu \ + libarchive/test/test_read_format_zip_traditional_encryption_data.zip.uu \ + libarchive/test/test_read_format_zip_ux.zip.uu \ + libarchive/test/test_read_format_zip_winzip_aes128.zip.uu \ + libarchive/test/test_read_format_zip_winzip_aes256.zip.uu \ + libarchive/test/test_read_format_zip_winzip_aes256_large.zip.uu \ + libarchive/test/test_read_format_zip_winzip_aes256_stored.zip.uu \ + libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.zip.uu \ + libarchive/test/test_read_format_zip_xz_multi.zipx.uu \ + libarchive/test/test_read_format_zip_zip64a.zip.uu \ + libarchive/test/test_read_format_zip_zip64b.zip.uu \ + libarchive/test/test_read_large_splitted_rar_aa.uu \ + libarchive/test/test_read_large_splitted_rar_ab.uu \ + libarchive/test/test_read_large_splitted_rar_ac.uu \ + libarchive/test/test_read_large_splitted_rar_ad.uu \ + libarchive/test/test_read_large_splitted_rar_ae.uu \ + libarchive/test/test_read_pax_schily_xattr.tar.uu \ + libarchive/test/test_read_splitted_rar_aa.uu \ + libarchive/test/test_read_splitted_rar_ab.uu \ + libarchive/test/test_read_splitted_rar_ac.uu \ + libarchive/test/test_read_splitted_rar_ad.uu \ + libarchive/test/test_read_too_many_filters.gz.uu \ + libarchive/test/test_splitted_rar_seek_support_aa.uu \ + libarchive/test/test_splitted_rar_seek_support_ab.uu \ + libarchive/test/test_splitted_rar_seek_support_ac.uu \ + libarchive/test/test_write_disk_appledouble.cpio.gz.uu \ + libarchive/test/test_write_disk_hfs_compression.tgz.uu \ + libarchive/test/test_write_disk_mac_metadata.tar.gz.uu \ + libarchive/test/test_write_disk_no_hfs_compression.tgz.uu \ + libarchive/test/CMakeLists.txt \ + libarchive/test/README + +# +# Common code for libarchive frontends (cpio, tar) +# +libarchive_fe_la_SOURCES= \ + libarchive_fe/err.c \ + libarchive_fe/err.h \ + libarchive_fe/lafe_platform.h \ + libarchive_fe/line_reader.c \ + libarchive_fe/line_reader.h \ + libarchive_fe/passphrase.c \ + libarchive_fe/passphrase.h + +libarchive_fe_la_CPPFLAGS= -I$(top_srcdir)/libarchive +# +# +# bsdtar source, docs, etc. +# +# + +bsdtar_SOURCES= \ + tar/bsdtar.c \ + tar/bsdtar.h \ + tar/bsdtar_platform.h \ + tar/cmdline.c \ + tar/creation_set.c \ + tar/read.c \ + tar/subst.c \ + tar/util.c \ + tar/write.c + +if INC_WINDOWS_FILES +bsdtar_SOURCES+= \ + tar/bsdtar_windows.h \ + tar/bsdtar_windows.c +endif + +bsdtar_DEPENDENCIES= libarchive.la libarchive_fe.la + +if STATIC_BSDTAR +bsdtar_ldstatic= -static +bsdtar_ccstatic= -DLIBARCHIVE_STATIC +else +bsdtar_ldstatic= +bsdtar_ccstatic= +endif + +bsdtar_LDADD= libarchive.la libarchive_fe.la $(LTLIBICONV) +bsdtar_CPPFLAGS= -I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe $(bsdtar_ccstatic) $(PLATFORMCPPFLAGS) +bsdtar_LDFLAGS= $(bsdtar_ldstatic) + +bsdtar_EXTRA_DIST= \ + tar/bsdtar.1 \ + tar/bsdtar_windows.h \ + tar/bsdtar_windows.c \ + tar/CMakeLists.txt \ + tar/config_freebsd.h + + +if BUILD_BSDTAR +bsdtar_man_MANS= tar/bsdtar.1 +bsdtar_programs= bsdtar +else +bsdtar_man_MANS= +bsdtar_programs= +endif + +# +# bsdtar_test +# + +bsdtar_test_SOURCES= \ + $(test_utils_SOURCES) \ + tar/test/test.h \ + tar/test/test_0.c \ + tar/test/test_basic.c \ + tar/test/test_copy.c \ + tar/test/test_empty_mtree.c \ + tar/test/test_extract_tar_Z.c \ + tar/test/test_extract_tar_bz2.c \ + tar/test/test_extract_tar_grz.c \ + tar/test/test_extract_tar_gz.c \ + tar/test/test_extract_tar_lrz.c \ + tar/test/test_extract_tar_lz.c \ + tar/test/test_extract_tar_lz4.c \ + tar/test/test_extract_tar_lzma.c \ + tar/test/test_extract_tar_lzo.c \ + tar/test/test_extract_tar_xz.c \ + tar/test/test_extract_tar_zstd.c \ + tar/test/test_format_newc.c \ + tar/test/test_help.c \ + tar/test/test_leading_slash.c \ + tar/test/test_missing_file.c \ + tar/test/test_option_C_mtree.c \ + tar/test/test_option_C_upper.c \ + tar/test/test_option_H_upper.c \ + tar/test/test_option_L_upper.c \ + tar/test/test_option_O_upper.c \ + tar/test/test_option_T_upper.c \ + tar/test/test_option_U_upper.c \ + tar/test/test_option_X_upper.c \ + tar/test/test_option_acls.c \ + tar/test/test_option_a.c \ + tar/test/test_option_b.c \ + tar/test/test_option_b64encode.c \ + tar/test/test_option_exclude.c \ + tar/test/test_option_exclude_vcs.c \ + tar/test/test_option_fflags.c \ + tar/test/test_option_gid_gname.c \ + tar/test/test_option_grzip.c \ + tar/test/test_option_j.c \ + tar/test/test_option_k.c \ + tar/test/test_option_keep_newer_files.c \ + tar/test/test_option_lrzip.c \ + tar/test/test_option_lz4.c \ + tar/test/test_option_lzma.c \ + tar/test/test_option_lzop.c \ + tar/test/test_option_n.c \ + tar/test/test_option_newer_than.c \ + tar/test/test_option_nodump.c \ + tar/test/test_option_older_than.c \ + tar/test/test_option_passphrase.c \ + tar/test/test_option_q.c \ + tar/test/test_option_r.c \ + tar/test/test_option_s.c \ + tar/test/test_option_safe_writes.c \ + tar/test/test_option_uid_uname.c \ + tar/test/test_option_uuencode.c \ + tar/test/test_option_xattrs.c \ + tar/test/test_option_xz.c \ + tar/test/test_option_z.c \ + tar/test/test_option_zstd.c \ + tar/test/test_patterns.c \ + tar/test/test_print_longpath.c \ + tar/test/test_stdio.c \ + tar/test/test_strip_components.c \ + tar/test/test_symlink_dir.c \ + tar/test/test_version.c \ + tar/test/test_windows.c + +bsdtar_test_CPPFLAGS=\ + -I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe \ + -I$(top_srcdir)/test_utils \ + -I$(top_srcdir)/tar -I$(top_srcdir)/tar/test \ + -I$(top_builddir)/tar/test \ + $(PLATFORMCPPFLAGS) + +tar/test/list.h: Makefile + $(MKDIR_P) tar/test + cat $(top_srcdir)/tar/test/test_*.c | grep '^DEFINE_TEST' > tar/test/list.h + +if BUILD_BSDTAR +bsdtar_test_programs= bsdtar_test +bsdtar_TESTS_ENVIRONMENT= BSDTAR=`cd $(top_builddir);/bin/pwd`/bsdtar$(EXEEXT) BSDTAR_TEST_FILES=`cd $(top_srcdir);/bin/pwd`/tar/test +else +bsdtar_test_programs= +bsdtar_TESTS_ENVIRONMENT= +endif + +bsdtar_test_EXTRA_DIST= \ + tar/test/list.h \ + tar/test/test_extract.tar.Z.uu \ + tar/test/test_extract.tar.bz2.uu \ + tar/test/test_extract.tar.grz.uu \ + tar/test/test_extract.tar.gz.uu \ + tar/test/test_extract.tar.lrz.uu \ + tar/test/test_extract.tar.lz.uu \ + tar/test/test_extract.tar.lz4.uu \ + tar/test/test_extract.tar.zst.uu \ + tar/test/test_extract.tar.lzma.uu \ + tar/test/test_extract.tar.lzo.uu \ + tar/test/test_extract.tar.xz.uu \ + tar/test/test_leading_slash.tar.uu \ + tar/test/test_option_keep_newer_files.tar.Z.uu \ + tar/test/test_option_passphrase.zip.uu \ + tar/test/test_option_s.tar.Z.uu \ + tar/test/test_patterns_2.tar.uu \ + tar/test/test_patterns_3.tar.uu \ + tar/test/test_patterns_4.tar.uu \ + tar/test/test_print_longpath.tar.Z.uu \ + tar/test/CMakeLists.txt + + +# +# +# bsdcpio source, docs, etc. +# +# + +bsdcpio_SOURCES= \ + cpio/cmdline.c \ + cpio/cpio.c \ + cpio/cpio.h \ + cpio/cpio_platform.h + +if INC_WINDOWS_FILES +bsdcpio_SOURCES+= \ + cpio/cpio_windows.h \ + cpio/cpio_windows.c +endif + +bsdcpio_DEPENDENCIES = libarchive.la libarchive_fe.la + + +if STATIC_BSDCPIO +bsdcpio_ldstatic= -static +bsdcpio_ccstatic= -DLIBARCHIVE_STATIC +else +bsdcpio_ldstatic= +bsdcpio_ccstatic= +endif + +bsdcpio_LDADD= libarchive_fe.la libarchive.la $(LTLIBICONV) +bsdcpio_CPPFLAGS= -I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe $(bsdcpio_ccstatic) $(PLATFORMCPPFLAGS) +bsdcpio_LDFLAGS= $(bsdcpio_ldstatic) + +bsdcpio_EXTRA_DIST= \ + cpio/bsdcpio.1 \ + cpio/cpio_windows.h \ + cpio/cpio_windows.c \ + cpio/CMakeLists.txt \ + cpio/config_freebsd.h + + +if BUILD_BSDCPIO +# Manpages to install +bsdcpio_man_MANS= cpio/bsdcpio.1 +bsdcpio_programs= bsdcpio +else +bsdcpio_man_MANS= +bsdcpio_programs= +endif + +# +# bsdcpio_test +# + +bsdcpio_test_SOURCES= \ + $(test_utils_SOURCES) \ + cpio/cmdline.c \ + cpio/test/test.h \ + cpio/test/test_0.c \ + cpio/test/test_basic.c \ + cpio/test/test_cmdline.c \ + cpio/test/test_extract_cpio_Z.c \ + cpio/test/test_extract_cpio_bz2.c \ + cpio/test/test_extract_cpio_grz.c \ + cpio/test/test_extract_cpio_gz.c \ + cpio/test/test_extract_cpio_lrz.c \ + cpio/test/test_extract_cpio_lz.c \ + cpio/test/test_extract_cpio_lz4.c \ + cpio/test/test_extract_cpio_lzma.c \ + cpio/test/test_extract_cpio_lzo.c \ + cpio/test/test_extract_cpio_xz.c \ + cpio/test/test_extract_cpio_zstd.c \ + cpio/test/test_format_newc.c \ + cpio/test/test_gcpio_compat.c \ + cpio/test/test_missing_file.c \ + cpio/test/test_option_0.c \ + cpio/test/test_option_B_upper.c \ + cpio/test/test_option_C_upper.c \ + cpio/test/test_option_J_upper.c \ + cpio/test/test_option_L_upper.c \ + cpio/test/test_option_Z_upper.c \ + cpio/test/test_option_a.c \ + cpio/test/test_option_b64encode.c \ + cpio/test/test_option_c.c \ + cpio/test/test_option_d.c \ + cpio/test/test_option_f.c \ + cpio/test/test_option_grzip.c \ + cpio/test/test_option_help.c \ + cpio/test/test_option_l.c \ + cpio/test/test_option_lrzip.c \ + cpio/test/test_option_lz4.c \ + cpio/test/test_option_lzma.c \ + cpio/test/test_option_lzop.c \ + cpio/test/test_option_m.c \ + cpio/test/test_option_passphrase.c \ + cpio/test/test_option_t.c \ + cpio/test/test_option_u.c \ + cpio/test/test_option_uuencode.c \ + cpio/test/test_option_version.c \ + cpio/test/test_option_xz.c \ + cpio/test/test_option_y.c \ + cpio/test/test_option_z.c \ + cpio/test/test_option_zstd.c \ + cpio/test/test_owner_parse.c \ + cpio/test/test_passthrough_dotdot.c \ + cpio/test/test_passthrough_reverse.c + +bsdcpio_test_CPPFLAGS= \ + -I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe \ + -I$(top_srcdir)/test_utils \ + -I$(top_srcdir)/cpio -I$(top_srcdir)/cpio/test \ + -I$(top_builddir)/cpio/test \ + $(PLATFORMCPPFLAGS) +bsdcpio_test_LDADD=libarchive_fe.la + +cpio/test/list.h: Makefile + $(MKDIR_P) cpio/test + cat $(top_srcdir)/cpio/test/test_*.c | grep '^DEFINE_TEST' > cpio/test/list.h + +if BUILD_BSDCPIO +bsdcpio_test_programs= bsdcpio_test +bsdcpio_TESTS_ENVIRONMENT= BSDCPIO=`cd $(top_builddir);/bin/pwd`/bsdcpio$(EXEEXT) BSDCPIO_TEST_FILES=`cd $(top_srcdir);/bin/pwd`/cpio/test +else +bsdcpio_test_programs= +bsdcpio_TESTS_ENVIRONMENT= +endif + +bsdcpio_test_EXTRA_DIST= \ + cpio/test/list.h \ + cpio/test/test_extract.cpio.Z.uu \ + cpio/test/test_extract.cpio.bz2.uu \ + cpio/test/test_extract.cpio.grz.uu \ + cpio/test/test_extract.cpio.gz.uu \ + cpio/test/test_extract.cpio.lrz.uu \ + cpio/test/test_extract.cpio.lz.uu \ + cpio/test/test_extract.cpio.lz4.uu \ + cpio/test/test_extract.cpio.zst.uu \ + cpio/test/test_extract.cpio.lzma.uu \ + cpio/test/test_extract.cpio.lzo.uu \ + cpio/test/test_extract.cpio.xz.uu \ + cpio/test/test_gcpio_compat_ref.bin.uu \ + cpio/test/test_gcpio_compat_ref.crc.uu \ + cpio/test/test_gcpio_compat_ref.newc.uu \ + cpio/test/test_gcpio_compat_ref.ustar.uu \ + cpio/test/test_gcpio_compat_ref_nosym.bin.uu \ + cpio/test/test_gcpio_compat_ref_nosym.crc.uu \ + cpio/test/test_gcpio_compat_ref_nosym.newc.uu \ + cpio/test/test_gcpio_compat_ref_nosym.ustar.uu \ + cpio/test/test_option_f.cpio.uu \ + cpio/test/test_option_m.cpio.uu \ + cpio/test/test_option_passphrase.zip.uu \ + cpio/test/test_option_t.cpio.uu \ + cpio/test/test_option_t.stdout.uu \ + cpio/test/test_option_tv.stdout.uu \ + cpio/test/CMakeLists.txt + +# +# +# bsdcat source, docs, etc. +# +# + +bsdcat_SOURCES= \ + cat/bsdcat.c \ + cat/bsdcat.h \ + cat/bsdcat_platform.h \ + cat/cmdline.c + +if INC_WINDOWS_FILES +bsdcat_SOURCES+= +endif + +bsdcat_DEPENDENCIES = libarchive.la libarchive_fe.la + + +if STATIC_BSDCAT +bsdcat_ldstatic= -static +bsdcat_ccstatic= -DLIBARCHIVE_STATIC +else +bsdcat_ldstatic= +bsdcat_ccstatic= +endif + +bsdcat_LDADD= libarchive_fe.la libarchive.la $(LTLIBICONV) +bsdcat_CPPFLAGS= -I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe $(bsdcat_ccstatic) $(PLATFORMCPPFLAGS) +bsdcat_LDFLAGS= $(bsdcat_ldstatic) + +bsdcat_EXTRA_DIST= \ + cat/bsdcat.1 \ + cat/CMakeLists.txt + + +if BUILD_BSDCAT +# Manpages to install +bsdcat_man_MANS= cat/bsdcat.1 +bsdcat_programs= bsdcat +else +bsdcat_man_MANS= +bsdcat_programs= +endif + +# +# bsdcat_test +# + +bsdcat_test_SOURCES= \ + $(test_utils_SOURCES) \ + cat/test/test.h \ + cat/test/test_0.c \ + cat/test/test_empty_gz.c \ + cat/test/test_empty_lz4.c \ + cat/test/test_empty_xz.c \ + cat/test/test_empty_zstd.c \ + cat/test/test_error.c \ + cat/test/test_error_mixed.c \ + cat/test/test_expand_Z.c \ + cat/test/test_expand_bz2.c \ + cat/test/test_expand_gz.c \ + cat/test/test_expand_lz4.c \ + cat/test/test_expand_mixed.c \ + cat/test/test_expand_plain.c \ + cat/test/test_expand_xz.c \ + cat/test/test_expand_zstd.c \ + cat/test/test_help.c \ + cat/test/test_stdin.c \ + cat/test/test_version.c + +bsdcat_test_CPPFLAGS= \ + -I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe \ + -I$(top_srcdir)/test_utils \ + -I$(top_srcdir)/cat -I$(top_srcdir)/cat/test \ + -I$(top_builddir)/cat/test \ + $(PLATFORMCPPFLAGS) +bsdcat_test_LDADD=libarchive_fe.la + +cat/test/list.h: Makefile + cat $(top_srcdir)/cat/test/test_*.c | grep '^DEFINE_TEST' > cat/test/list.h + +if BUILD_BSDCAT +bsdcat_test_programs= bsdcat_test +bsdcat_TESTS_ENVIRONMENT= BSDCAT=`cd $(top_builddir);/bin/pwd`/bsdcat$(EXEEXT) BSDCAT_TEST_FILES=`cd $(top_srcdir);/bin/pwd`/cat/test +else +bsdcat_test_programs= +bsdcat_TESTS_ENVIRONMENT= +endif + +bsdcat_test_EXTRA_DIST= \ + cat/test/list.h \ + cat/test/test_empty.gz.uu \ + cat/test/test_empty.lz4.uu \ + cat/test/test_empty.zst.uu \ + cat/test/test_empty.xz.uu \ + cat/test/test_expand.Z.uu \ + cat/test/test_expand.bz2.uu \ + cat/test/test_expand.gz.uu \ + cat/test/test_expand.lz4.uu \ + cat/test/test_expand.zst.uu \ + cat/test/test_expand.plain.uu \ + cat/test/test_expand.xz.uu \ + cat/test/CMakeLists.txt diff --git a/dependencies/libarchive-3.4.2/Makefile.in b/dependencies/libarchive-3.4.2/Makefile.in new file mode 100644 index 0000000..a690063 --- /dev/null +++ b/dependencies/libarchive-3.4.2/Makefile.in @@ -0,0 +1,14535 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +bin_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) +check_PROGRAMS = libarchive_test$(EXEEXT) $(am__EXEEXT_4) \ + $(am__EXEEXT_5) $(am__EXEEXT_6) +TESTS = libarchive_test$(EXEEXT) $(am__EXEEXT_4) $(am__EXEEXT_5) \ + $(am__EXEEXT_6) +@INC_WINDOWS_FILES_TRUE@am__append_1 = \ +@INC_WINDOWS_FILES_TRUE@ libarchive/archive_entry_copy_bhfi.c \ +@INC_WINDOWS_FILES_TRUE@ libarchive/archive_read_disk_windows.c \ +@INC_WINDOWS_FILES_TRUE@ libarchive/archive_windows.h \ +@INC_WINDOWS_FILES_TRUE@ libarchive/archive_windows.c \ +@INC_WINDOWS_FILES_TRUE@ libarchive/archive_write_disk_windows.c \ +@INC_WINDOWS_FILES_TRUE@ libarchive/filter_fork_windows.c + +@INC_BLAKE2_TRUE@am__append_2 = \ +@INC_BLAKE2_TRUE@ libarchive/archive_blake2.h \ +@INC_BLAKE2_TRUE@ libarchive/archive_blake2_impl.h \ +@INC_BLAKE2_TRUE@ libarchive/archive_blake2s_ref.c \ +@INC_BLAKE2_TRUE@ libarchive/archive_blake2sp_ref.c + +@INC_LINUX_ACL_TRUE@am__append_3 = libarchive/archive_disk_acl_linux.c +@INC_LINUX_ACL_FALSE@@INC_SUNOS_ACL_TRUE@am__append_4 = libarchive/archive_disk_acl_sunos.c +@INC_DARWIN_ACL_TRUE@@INC_LINUX_ACL_FALSE@@INC_SUNOS_ACL_FALSE@am__append_5 = libarchive/archive_disk_acl_darwin.c +@INC_DARWIN_ACL_FALSE@@INC_FREEBSD_ACL_TRUE@@INC_LINUX_ACL_FALSE@@INC_SUNOS_ACL_FALSE@am__append_6 = libarchive/archive_disk_acl_freebsd.c +@INC_WINDOWS_FILES_TRUE@am__append_7 = \ +@INC_WINDOWS_FILES_TRUE@ tar/bsdtar_windows.h \ +@INC_WINDOWS_FILES_TRUE@ tar/bsdtar_windows.c + +@INC_WINDOWS_FILES_TRUE@am__append_8 = \ +@INC_WINDOWS_FILES_TRUE@ cpio/cpio_windows.h \ +@INC_WINDOWS_FILES_TRUE@ cpio/cpio_windows.c + +@INC_WINDOWS_FILES_TRUE@am__append_9 = +subdir = . +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/build/autoconf/ax_append_compile_flags.m4 \ + $(top_srcdir)/build/autoconf/ax_append_flag.m4 \ + $(top_srcdir)/build/autoconf/ax_check_compile_flag.m4 \ + $(top_srcdir)/build/autoconf/ax_require_defined.m4 \ + $(top_srcdir)/build/autoconf/check_stdcall_func.m4 \ + $(top_srcdir)/build/autoconf/iconv.m4 \ + $(top_srcdir)/build/autoconf/la_uid_t.m4 \ + $(top_srcdir)/build/autoconf/lib-ld.m4 \ + $(top_srcdir)/build/autoconf/lib-link.m4 \ + $(top_srcdir)/build/autoconf/lib-prefix.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(include_HEADERS) $(am__DIST_COMMON) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = build/pkgconfig/libarchive.pc +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ + "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man3dir)" \ + "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(pkgconfigdir)" \ + "$(DESTDIR)$(includedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) +am__DEPENDENCIES_1 = +libarchive_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am__libarchive_la_SOURCES_DIST = libarchive/archive_acl.c \ + libarchive/archive_acl_private.h \ + libarchive/archive_check_magic.c libarchive/archive_cmdline.c \ + libarchive/archive_cmdline_private.h \ + libarchive/archive_crc32.h libarchive/archive_cryptor.c \ + libarchive/archive_cryptor_private.h \ + libarchive/archive_digest.c \ + libarchive/archive_digest_private.h \ + libarchive/archive_endian.h libarchive/archive_entry.c \ + libarchive/archive_entry.h \ + libarchive/archive_entry_copy_stat.c \ + libarchive/archive_entry_link_resolver.c \ + libarchive/archive_entry_locale.h \ + libarchive/archive_entry_private.h \ + libarchive/archive_entry_sparse.c \ + libarchive/archive_entry_stat.c \ + libarchive/archive_entry_strmode.c \ + libarchive/archive_entry_xattr.c libarchive/archive_getdate.c \ + libarchive/archive_getdate.h libarchive/archive_hmac.c \ + libarchive/archive_hmac_private.h libarchive/archive_match.c \ + libarchive/archive_openssl_evp_private.h \ + libarchive/archive_openssl_hmac_private.h \ + libarchive/archive_options.c \ + libarchive/archive_options_private.h \ + libarchive/archive_pack_dev.h libarchive/archive_pack_dev.c \ + libarchive/archive_pathmatch.c libarchive/archive_pathmatch.h \ + libarchive/archive_platform.h \ + libarchive/archive_platform_acl.h \ + libarchive/archive_platform_xattr.h \ + libarchive/archive_ppmd_private.h libarchive/archive_ppmd7.c \ + libarchive/archive_ppmd7_private.h libarchive/archive_ppmd8.c \ + libarchive/archive_ppmd8_private.h \ + libarchive/archive_private.h libarchive/archive_random.c \ + libarchive/archive_random_private.h libarchive/archive_rb.c \ + libarchive/archive_rb.h libarchive/archive_read.c \ + libarchive/archive_read_add_passphrase.c \ + libarchive/archive_read_append_filter.c \ + libarchive/archive_read_data_into_fd.c \ + libarchive/archive_read_disk_entry_from_file.c \ + libarchive/archive_read_disk_posix.c \ + libarchive/archive_read_disk_private.h \ + libarchive/archive_read_disk_set_standard_lookup.c \ + libarchive/archive_read_extract.c \ + libarchive/archive_read_extract2.c \ + libarchive/archive_read_open_fd.c \ + libarchive/archive_read_open_file.c \ + libarchive/archive_read_open_filename.c \ + libarchive/archive_read_open_memory.c \ + libarchive/archive_read_private.h \ + libarchive/archive_read_set_format.c \ + libarchive/archive_read_set_options.c \ + libarchive/archive_read_support_filter_all.c \ + libarchive/archive_read_support_filter_bzip2.c \ + libarchive/archive_read_support_filter_compress.c \ + libarchive/archive_read_support_filter_grzip.c \ + libarchive/archive_read_support_filter_gzip.c \ + libarchive/archive_read_support_filter_lrzip.c \ + libarchive/archive_read_support_filter_lz4.c \ + libarchive/archive_read_support_filter_lzop.c \ + libarchive/archive_read_support_filter_none.c \ + libarchive/archive_read_support_filter_program.c \ + libarchive/archive_read_support_filter_rpm.c \ + libarchive/archive_read_support_filter_uu.c \ + libarchive/archive_read_support_filter_xz.c \ + libarchive/archive_read_support_filter_zstd.c \ + libarchive/archive_read_support_format_7zip.c \ + libarchive/archive_read_support_format_all.c \ + libarchive/archive_read_support_format_ar.c \ + libarchive/archive_read_support_format_by_code.c \ + libarchive/archive_read_support_format_cab.c \ + libarchive/archive_read_support_format_cpio.c \ + libarchive/archive_read_support_format_empty.c \ + libarchive/archive_read_support_format_iso9660.c \ + libarchive/archive_read_support_format_lha.c \ + libarchive/archive_read_support_format_mtree.c \ + libarchive/archive_read_support_format_rar.c \ + libarchive/archive_read_support_format_rar5.c \ + libarchive/archive_read_support_format_raw.c \ + libarchive/archive_read_support_format_tar.c \ + libarchive/archive_read_support_format_warc.c \ + libarchive/archive_read_support_format_xar.c \ + libarchive/archive_read_support_format_zip.c \ + libarchive/archive_string.c libarchive/archive_string.h \ + libarchive/archive_string_composition.h \ + libarchive/archive_string_sprintf.c libarchive/archive_util.c \ + libarchive/archive_version_details.c \ + libarchive/archive_virtual.c libarchive/archive_write.c \ + libarchive/archive_write_disk_posix.c \ + libarchive/archive_write_disk_private.h \ + libarchive/archive_write_disk_set_standard_lookup.c \ + libarchive/archive_write_open_fd.c \ + libarchive/archive_write_open_file.c \ + libarchive/archive_write_open_filename.c \ + libarchive/archive_write_open_memory.c \ + libarchive/archive_write_private.h \ + libarchive/archive_write_add_filter.c \ + libarchive/archive_write_add_filter_b64encode.c \ + libarchive/archive_write_add_filter_by_name.c \ + libarchive/archive_write_add_filter_bzip2.c \ + libarchive/archive_write_add_filter_compress.c \ + libarchive/archive_write_add_filter_grzip.c \ + libarchive/archive_write_add_filter_gzip.c \ + libarchive/archive_write_add_filter_lrzip.c \ + libarchive/archive_write_add_filter_lz4.c \ + libarchive/archive_write_add_filter_lzop.c \ + libarchive/archive_write_add_filter_none.c \ + libarchive/archive_write_add_filter_program.c \ + libarchive/archive_write_add_filter_uuencode.c \ + libarchive/archive_write_add_filter_xz.c \ + libarchive/archive_write_add_filter_zstd.c \ + libarchive/archive_write_set_format.c \ + libarchive/archive_write_set_format_7zip.c \ + libarchive/archive_write_set_format_ar.c \ + libarchive/archive_write_set_format_by_name.c \ + libarchive/archive_write_set_format_cpio.c \ + libarchive/archive_write_set_format_cpio_newc.c \ + libarchive/archive_write_set_format_filter_by_ext.c \ + libarchive/archive_write_set_format_iso9660.c \ + libarchive/archive_write_set_format_mtree.c \ + libarchive/archive_write_set_format_pax.c \ + libarchive/archive_write_set_format_private.h \ + libarchive/archive_write_set_format_raw.c \ + libarchive/archive_write_set_format_shar.c \ + libarchive/archive_write_set_format_ustar.c \ + libarchive/archive_write_set_format_v7tar.c \ + libarchive/archive_write_set_format_gnutar.c \ + libarchive/archive_write_set_format_warc.c \ + libarchive/archive_write_set_format_xar.c \ + libarchive/archive_write_set_format_zip.c \ + libarchive/archive_write_set_options.c \ + libarchive/archive_write_set_passphrase.c \ + libarchive/archive_xxhash.h libarchive/config_freebsd.h \ + libarchive/filter_fork_posix.c libarchive/filter_fork.h \ + libarchive/xxhash.c libarchive/archive_entry_copy_bhfi.c \ + libarchive/archive_read_disk_windows.c \ + libarchive/archive_windows.h libarchive/archive_windows.c \ + libarchive/archive_write_disk_windows.c \ + libarchive/filter_fork_windows.c libarchive/archive_blake2.h \ + libarchive/archive_blake2_impl.h \ + libarchive/archive_blake2s_ref.c \ + libarchive/archive_blake2sp_ref.c \ + libarchive/archive_disk_acl_linux.c \ + libarchive/archive_disk_acl_sunos.c \ + libarchive/archive_disk_acl_darwin.c \ + libarchive/archive_disk_acl_freebsd.c +am__dirstamp = $(am__leading_dot)dirstamp +@INC_WINDOWS_FILES_TRUE@am__objects_1 = \ +@INC_WINDOWS_FILES_TRUE@ libarchive/archive_entry_copy_bhfi.lo \ +@INC_WINDOWS_FILES_TRUE@ libarchive/archive_read_disk_windows.lo \ +@INC_WINDOWS_FILES_TRUE@ libarchive/archive_windows.lo \ +@INC_WINDOWS_FILES_TRUE@ libarchive/archive_write_disk_windows.lo \ +@INC_WINDOWS_FILES_TRUE@ libarchive/filter_fork_windows.lo +@INC_BLAKE2_TRUE@am__objects_2 = libarchive/archive_blake2s_ref.lo \ +@INC_BLAKE2_TRUE@ libarchive/archive_blake2sp_ref.lo +@INC_LINUX_ACL_TRUE@am__objects_3 = \ +@INC_LINUX_ACL_TRUE@ libarchive/archive_disk_acl_linux.lo +@INC_LINUX_ACL_FALSE@@INC_SUNOS_ACL_TRUE@am__objects_4 = libarchive/archive_disk_acl_sunos.lo +@INC_DARWIN_ACL_TRUE@@INC_LINUX_ACL_FALSE@@INC_SUNOS_ACL_FALSE@am__objects_5 = libarchive/archive_disk_acl_darwin.lo +@INC_DARWIN_ACL_FALSE@@INC_FREEBSD_ACL_TRUE@@INC_LINUX_ACL_FALSE@@INC_SUNOS_ACL_FALSE@am__objects_6 = libarchive/archive_disk_acl_freebsd.lo +am_libarchive_la_OBJECTS = libarchive/archive_acl.lo \ + libarchive/archive_check_magic.lo \ + libarchive/archive_cmdline.lo libarchive/archive_cryptor.lo \ + libarchive/archive_digest.lo libarchive/archive_entry.lo \ + libarchive/archive_entry_copy_stat.lo \ + libarchive/archive_entry_link_resolver.lo \ + libarchive/archive_entry_sparse.lo \ + libarchive/archive_entry_stat.lo \ + libarchive/archive_entry_strmode.lo \ + libarchive/archive_entry_xattr.lo \ + libarchive/archive_getdate.lo libarchive/archive_hmac.lo \ + libarchive/archive_match.lo libarchive/archive_options.lo \ + libarchive/archive_pack_dev.lo libarchive/archive_pathmatch.lo \ + libarchive/archive_ppmd7.lo libarchive/archive_ppmd8.lo \ + libarchive/archive_random.lo libarchive/archive_rb.lo \ + libarchive/archive_read.lo \ + libarchive/archive_read_add_passphrase.lo \ + libarchive/archive_read_append_filter.lo \ + libarchive/archive_read_data_into_fd.lo \ + libarchive/archive_read_disk_entry_from_file.lo \ + libarchive/archive_read_disk_posix.lo \ + libarchive/archive_read_disk_set_standard_lookup.lo \ + libarchive/archive_read_extract.lo \ + libarchive/archive_read_extract2.lo \ + libarchive/archive_read_open_fd.lo \ + libarchive/archive_read_open_file.lo \ + libarchive/archive_read_open_filename.lo \ + libarchive/archive_read_open_memory.lo \ + libarchive/archive_read_set_format.lo \ + libarchive/archive_read_set_options.lo \ + libarchive/archive_read_support_filter_all.lo \ + libarchive/archive_read_support_filter_bzip2.lo \ + libarchive/archive_read_support_filter_compress.lo \ + libarchive/archive_read_support_filter_grzip.lo \ + libarchive/archive_read_support_filter_gzip.lo \ + libarchive/archive_read_support_filter_lrzip.lo \ + libarchive/archive_read_support_filter_lz4.lo \ + libarchive/archive_read_support_filter_lzop.lo \ + libarchive/archive_read_support_filter_none.lo \ + libarchive/archive_read_support_filter_program.lo \ + libarchive/archive_read_support_filter_rpm.lo \ + libarchive/archive_read_support_filter_uu.lo \ + libarchive/archive_read_support_filter_xz.lo \ + libarchive/archive_read_support_filter_zstd.lo \ + libarchive/archive_read_support_format_7zip.lo \ + libarchive/archive_read_support_format_all.lo \ + libarchive/archive_read_support_format_ar.lo \ + libarchive/archive_read_support_format_by_code.lo \ + libarchive/archive_read_support_format_cab.lo \ + libarchive/archive_read_support_format_cpio.lo \ + libarchive/archive_read_support_format_empty.lo \ + libarchive/archive_read_support_format_iso9660.lo \ + libarchive/archive_read_support_format_lha.lo \ + libarchive/archive_read_support_format_mtree.lo \ + libarchive/archive_read_support_format_rar.lo \ + libarchive/archive_read_support_format_rar5.lo \ + libarchive/archive_read_support_format_raw.lo \ + libarchive/archive_read_support_format_tar.lo \ + libarchive/archive_read_support_format_warc.lo \ + libarchive/archive_read_support_format_xar.lo \ + libarchive/archive_read_support_format_zip.lo \ + libarchive/archive_string.lo \ + libarchive/archive_string_sprintf.lo \ + libarchive/archive_util.lo \ + libarchive/archive_version_details.lo \ + libarchive/archive_virtual.lo libarchive/archive_write.lo \ + libarchive/archive_write_disk_posix.lo \ + libarchive/archive_write_disk_set_standard_lookup.lo \ + libarchive/archive_write_open_fd.lo \ + libarchive/archive_write_open_file.lo \ + libarchive/archive_write_open_filename.lo \ + libarchive/archive_write_open_memory.lo \ + libarchive/archive_write_add_filter.lo \ + libarchive/archive_write_add_filter_b64encode.lo \ + libarchive/archive_write_add_filter_by_name.lo \ + libarchive/archive_write_add_filter_bzip2.lo \ + libarchive/archive_write_add_filter_compress.lo \ + libarchive/archive_write_add_filter_grzip.lo \ + libarchive/archive_write_add_filter_gzip.lo \ + libarchive/archive_write_add_filter_lrzip.lo \ + libarchive/archive_write_add_filter_lz4.lo \ + libarchive/archive_write_add_filter_lzop.lo \ + libarchive/archive_write_add_filter_none.lo \ + libarchive/archive_write_add_filter_program.lo \ + libarchive/archive_write_add_filter_uuencode.lo \ + libarchive/archive_write_add_filter_xz.lo \ + libarchive/archive_write_add_filter_zstd.lo \ + libarchive/archive_write_set_format.lo \ + libarchive/archive_write_set_format_7zip.lo \ + libarchive/archive_write_set_format_ar.lo \ + libarchive/archive_write_set_format_by_name.lo \ + libarchive/archive_write_set_format_cpio.lo \ + libarchive/archive_write_set_format_cpio_newc.lo \ + libarchive/archive_write_set_format_filter_by_ext.lo \ + libarchive/archive_write_set_format_iso9660.lo \ + libarchive/archive_write_set_format_mtree.lo \ + libarchive/archive_write_set_format_pax.lo \ + libarchive/archive_write_set_format_raw.lo \ + libarchive/archive_write_set_format_shar.lo \ + libarchive/archive_write_set_format_ustar.lo \ + libarchive/archive_write_set_format_v7tar.lo \ + libarchive/archive_write_set_format_gnutar.lo \ + libarchive/archive_write_set_format_warc.lo \ + libarchive/archive_write_set_format_xar.lo \ + libarchive/archive_write_set_format_zip.lo \ + libarchive/archive_write_set_options.lo \ + libarchive/archive_write_set_passphrase.lo \ + libarchive/filter_fork_posix.lo libarchive/xxhash.lo \ + $(am__objects_1) $(am__objects_2) $(am__objects_3) \ + $(am__objects_4) $(am__objects_5) $(am__objects_6) +libarchive_la_OBJECTS = $(am_libarchive_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libarchive_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libarchive_la_LDFLAGS) $(LDFLAGS) -o $@ +libarchive_fe_la_LIBADD = +am_libarchive_fe_la_OBJECTS = libarchive_fe/libarchive_fe_la-err.lo \ + libarchive_fe/libarchive_fe_la-line_reader.lo \ + libarchive_fe/libarchive_fe_la-passphrase.lo +libarchive_fe_la_OBJECTS = $(am_libarchive_fe_la_OBJECTS) +@BUILD_BSDTAR_TRUE@am__EXEEXT_1 = bsdtar$(EXEEXT) +@BUILD_BSDCPIO_TRUE@am__EXEEXT_2 = bsdcpio$(EXEEXT) +@BUILD_BSDCAT_TRUE@am__EXEEXT_3 = bsdcat$(EXEEXT) +@BUILD_BSDTAR_TRUE@am__EXEEXT_4 = bsdtar_test$(EXEEXT) +@BUILD_BSDCPIO_TRUE@am__EXEEXT_5 = bsdcpio_test$(EXEEXT) +@BUILD_BSDCAT_TRUE@am__EXEEXT_6 = bsdcat_test$(EXEEXT) +PROGRAMS = $(bin_PROGRAMS) +am__objects_7 = +am_bsdcat_OBJECTS = cat/bsdcat-bsdcat.$(OBJEXT) \ + cat/bsdcat-cmdline.$(OBJEXT) $(am__objects_7) +bsdcat_OBJECTS = $(am_bsdcat_OBJECTS) +bsdcat_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(bsdcat_LDFLAGS) $(LDFLAGS) -o $@ +am__objects_8 = test_utils/bsdcat_test-test_utils.$(OBJEXT) \ + test_utils/bsdcat_test-test_main.$(OBJEXT) +am_bsdcat_test_OBJECTS = $(am__objects_8) \ + cat/test/bsdcat_test-test_0.$(OBJEXT) \ + cat/test/bsdcat_test-test_empty_gz.$(OBJEXT) \ + cat/test/bsdcat_test-test_empty_lz4.$(OBJEXT) \ + cat/test/bsdcat_test-test_empty_xz.$(OBJEXT) \ + cat/test/bsdcat_test-test_empty_zstd.$(OBJEXT) \ + cat/test/bsdcat_test-test_error.$(OBJEXT) \ + cat/test/bsdcat_test-test_error_mixed.$(OBJEXT) \ + cat/test/bsdcat_test-test_expand_Z.$(OBJEXT) \ + cat/test/bsdcat_test-test_expand_bz2.$(OBJEXT) \ + cat/test/bsdcat_test-test_expand_gz.$(OBJEXT) \ + cat/test/bsdcat_test-test_expand_lz4.$(OBJEXT) \ + cat/test/bsdcat_test-test_expand_mixed.$(OBJEXT) \ + cat/test/bsdcat_test-test_expand_plain.$(OBJEXT) \ + cat/test/bsdcat_test-test_expand_xz.$(OBJEXT) \ + cat/test/bsdcat_test-test_expand_zstd.$(OBJEXT) \ + cat/test/bsdcat_test-test_help.$(OBJEXT) \ + cat/test/bsdcat_test-test_stdin.$(OBJEXT) \ + cat/test/bsdcat_test-test_version.$(OBJEXT) +bsdcat_test_OBJECTS = $(am_bsdcat_test_OBJECTS) +bsdcat_test_DEPENDENCIES = libarchive_fe.la +am__bsdcpio_SOURCES_DIST = cpio/cmdline.c cpio/cpio.c cpio/cpio.h \ + cpio/cpio_platform.h cpio/cpio_windows.h cpio/cpio_windows.c +@INC_WINDOWS_FILES_TRUE@am__objects_9 = \ +@INC_WINDOWS_FILES_TRUE@ cpio/bsdcpio-cpio_windows.$(OBJEXT) +am_bsdcpio_OBJECTS = cpio/bsdcpio-cmdline.$(OBJEXT) \ + cpio/bsdcpio-cpio.$(OBJEXT) $(am__objects_9) +bsdcpio_OBJECTS = $(am_bsdcpio_OBJECTS) +bsdcpio_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(bsdcpio_LDFLAGS) $(LDFLAGS) -o $@ +am__objects_10 = test_utils/bsdcpio_test-test_utils.$(OBJEXT) \ + test_utils/bsdcpio_test-test_main.$(OBJEXT) +am_bsdcpio_test_OBJECTS = $(am__objects_10) \ + cpio/bsdcpio_test-cmdline.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_0.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_basic.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_cmdline.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_extract_cpio_Z.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_extract_cpio_bz2.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_extract_cpio_grz.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_extract_cpio_gz.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_extract_cpio_lrz.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_extract_cpio_lz.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_extract_cpio_lz4.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_extract_cpio_lzma.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_extract_cpio_lzo.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_extract_cpio_xz.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_extract_cpio_zstd.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_format_newc.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_gcpio_compat.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_missing_file.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_0.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_B_upper.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_C_upper.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_J_upper.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_L_upper.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_Z_upper.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_a.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_b64encode.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_c.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_d.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_f.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_grzip.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_help.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_l.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_lrzip.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_lz4.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_lzma.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_lzop.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_m.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_passphrase.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_t.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_u.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_uuencode.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_version.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_xz.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_y.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_z.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_option_zstd.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_owner_parse.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_passthrough_dotdot.$(OBJEXT) \ + cpio/test/bsdcpio_test-test_passthrough_reverse.$(OBJEXT) +bsdcpio_test_OBJECTS = $(am_bsdcpio_test_OBJECTS) +bsdcpio_test_DEPENDENCIES = libarchive_fe.la +am__bsdtar_SOURCES_DIST = tar/bsdtar.c tar/bsdtar.h \ + tar/bsdtar_platform.h tar/cmdline.c tar/creation_set.c \ + tar/read.c tar/subst.c tar/util.c tar/write.c \ + tar/bsdtar_windows.h tar/bsdtar_windows.c +@INC_WINDOWS_FILES_TRUE@am__objects_11 = \ +@INC_WINDOWS_FILES_TRUE@ tar/bsdtar-bsdtar_windows.$(OBJEXT) +am_bsdtar_OBJECTS = tar/bsdtar-bsdtar.$(OBJEXT) \ + tar/bsdtar-cmdline.$(OBJEXT) tar/bsdtar-creation_set.$(OBJEXT) \ + tar/bsdtar-read.$(OBJEXT) tar/bsdtar-subst.$(OBJEXT) \ + tar/bsdtar-util.$(OBJEXT) tar/bsdtar-write.$(OBJEXT) \ + $(am__objects_11) +bsdtar_OBJECTS = $(am_bsdtar_OBJECTS) +bsdtar_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(bsdtar_LDFLAGS) $(LDFLAGS) -o $@ +am__objects_12 = test_utils/bsdtar_test-test_utils.$(OBJEXT) \ + test_utils/bsdtar_test-test_main.$(OBJEXT) +am_bsdtar_test_OBJECTS = $(am__objects_12) \ + tar/test/bsdtar_test-test_0.$(OBJEXT) \ + tar/test/bsdtar_test-test_basic.$(OBJEXT) \ + tar/test/bsdtar_test-test_copy.$(OBJEXT) \ + tar/test/bsdtar_test-test_empty_mtree.$(OBJEXT) \ + tar/test/bsdtar_test-test_extract_tar_Z.$(OBJEXT) \ + tar/test/bsdtar_test-test_extract_tar_bz2.$(OBJEXT) \ + tar/test/bsdtar_test-test_extract_tar_grz.$(OBJEXT) \ + tar/test/bsdtar_test-test_extract_tar_gz.$(OBJEXT) \ + tar/test/bsdtar_test-test_extract_tar_lrz.$(OBJEXT) \ + tar/test/bsdtar_test-test_extract_tar_lz.$(OBJEXT) \ + tar/test/bsdtar_test-test_extract_tar_lz4.$(OBJEXT) \ + tar/test/bsdtar_test-test_extract_tar_lzma.$(OBJEXT) \ + tar/test/bsdtar_test-test_extract_tar_lzo.$(OBJEXT) \ + tar/test/bsdtar_test-test_extract_tar_xz.$(OBJEXT) \ + tar/test/bsdtar_test-test_extract_tar_zstd.$(OBJEXT) \ + tar/test/bsdtar_test-test_format_newc.$(OBJEXT) \ + tar/test/bsdtar_test-test_help.$(OBJEXT) \ + tar/test/bsdtar_test-test_leading_slash.$(OBJEXT) \ + tar/test/bsdtar_test-test_missing_file.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_C_mtree.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_C_upper.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_H_upper.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_L_upper.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_O_upper.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_T_upper.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_U_upper.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_X_upper.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_acls.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_a.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_b.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_b64encode.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_exclude.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_exclude_vcs.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_fflags.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_gid_gname.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_grzip.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_j.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_k.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_keep_newer_files.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_lrzip.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_lz4.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_lzma.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_lzop.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_n.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_newer_than.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_nodump.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_older_than.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_passphrase.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_q.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_r.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_s.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_safe_writes.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_uid_uname.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_uuencode.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_xattrs.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_xz.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_z.$(OBJEXT) \ + tar/test/bsdtar_test-test_option_zstd.$(OBJEXT) \ + tar/test/bsdtar_test-test_patterns.$(OBJEXT) \ + tar/test/bsdtar_test-test_print_longpath.$(OBJEXT) \ + tar/test/bsdtar_test-test_stdio.$(OBJEXT) \ + tar/test/bsdtar_test-test_strip_components.$(OBJEXT) \ + tar/test/bsdtar_test-test_symlink_dir.$(OBJEXT) \ + tar/test/bsdtar_test-test_version.$(OBJEXT) \ + tar/test/bsdtar_test-test_windows.$(OBJEXT) +bsdtar_test_OBJECTS = $(am_bsdtar_test_OBJECTS) +bsdtar_test_LDADD = $(LDADD) +am__libarchive_test_SOURCES_DIST = libarchive/archive_acl.c \ + libarchive/archive_acl_private.h \ + libarchive/archive_check_magic.c libarchive/archive_cmdline.c \ + libarchive/archive_cmdline_private.h \ + libarchive/archive_crc32.h libarchive/archive_cryptor.c \ + libarchive/archive_cryptor_private.h \ + libarchive/archive_digest.c \ + libarchive/archive_digest_private.h \ + libarchive/archive_endian.h libarchive/archive_entry.c \ + libarchive/archive_entry.h \ + libarchive/archive_entry_copy_stat.c \ + libarchive/archive_entry_link_resolver.c \ + libarchive/archive_entry_locale.h \ + libarchive/archive_entry_private.h \ + libarchive/archive_entry_sparse.c \ + libarchive/archive_entry_stat.c \ + libarchive/archive_entry_strmode.c \ + libarchive/archive_entry_xattr.c libarchive/archive_getdate.c \ + libarchive/archive_getdate.h libarchive/archive_hmac.c \ + libarchive/archive_hmac_private.h libarchive/archive_match.c \ + libarchive/archive_openssl_evp_private.h \ + libarchive/archive_openssl_hmac_private.h \ + libarchive/archive_options.c \ + libarchive/archive_options_private.h \ + libarchive/archive_pack_dev.h libarchive/archive_pack_dev.c \ + libarchive/archive_pathmatch.c libarchive/archive_pathmatch.h \ + libarchive/archive_platform.h \ + libarchive/archive_platform_acl.h \ + libarchive/archive_platform_xattr.h \ + libarchive/archive_ppmd_private.h libarchive/archive_ppmd7.c \ + libarchive/archive_ppmd7_private.h libarchive/archive_ppmd8.c \ + libarchive/archive_ppmd8_private.h \ + libarchive/archive_private.h libarchive/archive_random.c \ + libarchive/archive_random_private.h libarchive/archive_rb.c \ + libarchive/archive_rb.h libarchive/archive_read.c \ + libarchive/archive_read_add_passphrase.c \ + libarchive/archive_read_append_filter.c \ + libarchive/archive_read_data_into_fd.c \ + libarchive/archive_read_disk_entry_from_file.c \ + libarchive/archive_read_disk_posix.c \ + libarchive/archive_read_disk_private.h \ + libarchive/archive_read_disk_set_standard_lookup.c \ + libarchive/archive_read_extract.c \ + libarchive/archive_read_extract2.c \ + libarchive/archive_read_open_fd.c \ + libarchive/archive_read_open_file.c \ + libarchive/archive_read_open_filename.c \ + libarchive/archive_read_open_memory.c \ + libarchive/archive_read_private.h \ + libarchive/archive_read_set_format.c \ + libarchive/archive_read_set_options.c \ + libarchive/archive_read_support_filter_all.c \ + libarchive/archive_read_support_filter_bzip2.c \ + libarchive/archive_read_support_filter_compress.c \ + libarchive/archive_read_support_filter_grzip.c \ + libarchive/archive_read_support_filter_gzip.c \ + libarchive/archive_read_support_filter_lrzip.c \ + libarchive/archive_read_support_filter_lz4.c \ + libarchive/archive_read_support_filter_lzop.c \ + libarchive/archive_read_support_filter_none.c \ + libarchive/archive_read_support_filter_program.c \ + libarchive/archive_read_support_filter_rpm.c \ + libarchive/archive_read_support_filter_uu.c \ + libarchive/archive_read_support_filter_xz.c \ + libarchive/archive_read_support_filter_zstd.c \ + libarchive/archive_read_support_format_7zip.c \ + libarchive/archive_read_support_format_all.c \ + libarchive/archive_read_support_format_ar.c \ + libarchive/archive_read_support_format_by_code.c \ + libarchive/archive_read_support_format_cab.c \ + libarchive/archive_read_support_format_cpio.c \ + libarchive/archive_read_support_format_empty.c \ + libarchive/archive_read_support_format_iso9660.c \ + libarchive/archive_read_support_format_lha.c \ + libarchive/archive_read_support_format_mtree.c \ + libarchive/archive_read_support_format_rar.c \ + libarchive/archive_read_support_format_rar5.c \ + libarchive/archive_read_support_format_raw.c \ + libarchive/archive_read_support_format_tar.c \ + libarchive/archive_read_support_format_warc.c \ + libarchive/archive_read_support_format_xar.c \ + libarchive/archive_read_support_format_zip.c \ + libarchive/archive_string.c libarchive/archive_string.h \ + libarchive/archive_string_composition.h \ + libarchive/archive_string_sprintf.c libarchive/archive_util.c \ + libarchive/archive_version_details.c \ + libarchive/archive_virtual.c libarchive/archive_write.c \ + libarchive/archive_write_disk_posix.c \ + libarchive/archive_write_disk_private.h \ + libarchive/archive_write_disk_set_standard_lookup.c \ + libarchive/archive_write_open_fd.c \ + libarchive/archive_write_open_file.c \ + libarchive/archive_write_open_filename.c \ + libarchive/archive_write_open_memory.c \ + libarchive/archive_write_private.h \ + libarchive/archive_write_add_filter.c \ + libarchive/archive_write_add_filter_b64encode.c \ + libarchive/archive_write_add_filter_by_name.c \ + libarchive/archive_write_add_filter_bzip2.c \ + libarchive/archive_write_add_filter_compress.c \ + libarchive/archive_write_add_filter_grzip.c \ + libarchive/archive_write_add_filter_gzip.c \ + libarchive/archive_write_add_filter_lrzip.c \ + libarchive/archive_write_add_filter_lz4.c \ + libarchive/archive_write_add_filter_lzop.c \ + libarchive/archive_write_add_filter_none.c \ + libarchive/archive_write_add_filter_program.c \ + libarchive/archive_write_add_filter_uuencode.c \ + libarchive/archive_write_add_filter_xz.c \ + libarchive/archive_write_add_filter_zstd.c \ + libarchive/archive_write_set_format.c \ + libarchive/archive_write_set_format_7zip.c \ + libarchive/archive_write_set_format_ar.c \ + libarchive/archive_write_set_format_by_name.c \ + libarchive/archive_write_set_format_cpio.c \ + libarchive/archive_write_set_format_cpio_newc.c \ + libarchive/archive_write_set_format_filter_by_ext.c \ + libarchive/archive_write_set_format_iso9660.c \ + libarchive/archive_write_set_format_mtree.c \ + libarchive/archive_write_set_format_pax.c \ + libarchive/archive_write_set_format_private.h \ + libarchive/archive_write_set_format_raw.c \ + libarchive/archive_write_set_format_shar.c \ + libarchive/archive_write_set_format_ustar.c \ + libarchive/archive_write_set_format_v7tar.c \ + libarchive/archive_write_set_format_gnutar.c \ + libarchive/archive_write_set_format_warc.c \ + libarchive/archive_write_set_format_xar.c \ + libarchive/archive_write_set_format_zip.c \ + libarchive/archive_write_set_options.c \ + libarchive/archive_write_set_passphrase.c \ + libarchive/archive_xxhash.h libarchive/config_freebsd.h \ + libarchive/filter_fork_posix.c libarchive/filter_fork.h \ + libarchive/xxhash.c libarchive/archive_entry_copy_bhfi.c \ + libarchive/archive_read_disk_windows.c \ + libarchive/archive_windows.h libarchive/archive_windows.c \ + libarchive/archive_write_disk_windows.c \ + libarchive/filter_fork_windows.c libarchive/archive_blake2.h \ + libarchive/archive_blake2_impl.h \ + libarchive/archive_blake2s_ref.c \ + libarchive/archive_blake2sp_ref.c \ + libarchive/archive_disk_acl_linux.c \ + libarchive/archive_disk_acl_sunos.c \ + libarchive/archive_disk_acl_darwin.c \ + libarchive/archive_disk_acl_freebsd.c test_utils/test_utils.c \ + test_utils/test_utils.h test_utils/test_main.c \ + test_utils/test_common.h libarchive/test/read_open_memory.c \ + libarchive/test/test.h libarchive/test/test_acl_nfs4.c \ + libarchive/test/test_acl_pax.c \ + libarchive/test/test_acl_platform_nfs4.c \ + libarchive/test/test_acl_platform_posix1e.c \ + libarchive/test/test_acl_posix1e.c \ + libarchive/test/test_acl_text.c \ + libarchive/test/test_archive_api_feature.c \ + libarchive/test/test_archive_clear_error.c \ + libarchive/test/test_archive_cmdline.c \ + libarchive/test/test_archive_digest.c \ + libarchive/test/test_archive_getdate.c \ + libarchive/test/test_archive_match_owner.c \ + libarchive/test/test_archive_match_path.c \ + libarchive/test/test_archive_match_time.c \ + libarchive/test/test_archive_pathmatch.c \ + libarchive/test/test_archive_read_add_passphrase.c \ + libarchive/test/test_archive_read_close_twice.c \ + libarchive/test/test_archive_read_close_twice_open_fd.c \ + libarchive/test/test_archive_read_close_twice_open_filename.c \ + libarchive/test/test_archive_read_multiple_data_objects.c \ + libarchive/test/test_archive_read_next_header_empty.c \ + libarchive/test/test_archive_read_next_header_raw.c \ + libarchive/test/test_archive_read_open2.c \ + libarchive/test/test_archive_read_set_filter_option.c \ + libarchive/test/test_archive_read_set_format_option.c \ + libarchive/test/test_archive_read_set_option.c \ + libarchive/test/test_archive_read_set_options.c \ + libarchive/test/test_archive_read_support.c \ + libarchive/test/test_archive_set_error.c \ + libarchive/test/test_archive_string.c \ + libarchive/test/test_archive_string_conversion.c \ + libarchive/test/test_archive_write_add_filter_by_name.c \ + libarchive/test/test_archive_write_set_filter_option.c \ + libarchive/test/test_archive_write_set_format_by_name.c \ + libarchive/test/test_archive_write_set_format_filter_by_ext.c \ + libarchive/test/test_archive_write_set_format_option.c \ + libarchive/test/test_archive_write_set_option.c \ + libarchive/test/test_archive_write_set_options.c \ + libarchive/test/test_archive_write_set_passphrase.c \ + libarchive/test/test_bad_fd.c \ + libarchive/test/test_compat_bzip2.c \ + libarchive/test/test_compat_cpio.c \ + libarchive/test/test_compat_gtar.c \ + libarchive/test/test_compat_gzip.c \ + libarchive/test/test_compat_lz4.c \ + libarchive/test/test_compat_lzip.c \ + libarchive/test/test_compat_lzma.c \ + libarchive/test/test_compat_lzop.c \ + libarchive/test/test_compat_mac.c \ + libarchive/test/test_compat_perl_archive_tar.c \ + libarchive/test/test_compat_plexus_archiver_tar.c \ + libarchive/test/test_compat_solaris_tar_acl.c \ + libarchive/test/test_compat_solaris_pax_sparse.c \ + libarchive/test/test_compat_star_acl.c \ + libarchive/test/test_compat_tar_hardlink.c \ + libarchive/test/test_compat_uudecode.c \ + libarchive/test/test_compat_uudecode_large.c \ + libarchive/test/test_compat_xz.c \ + libarchive/test/test_compat_zip.c \ + libarchive/test/test_compat_zstd.c \ + libarchive/test/test_empty_write.c \ + libarchive/test/test_entry.c \ + libarchive/test/test_entry_strmode.c \ + libarchive/test/test_extattr_freebsd.c \ + libarchive/test/test_filter_count.c \ + libarchive/test/test_fuzz.c \ + libarchive/test/test_gnutar_filename_encoding.c \ + libarchive/test/test_link_resolver.c \ + libarchive/test/test_open_failure.c \ + libarchive/test/test_open_fd.c \ + libarchive/test/test_open_file.c \ + libarchive/test/test_open_filename.c \ + libarchive/test/test_pax_filename_encoding.c \ + libarchive/test/test_pax_xattr_header.c \ + libarchive/test/test_read_data_large.c \ + libarchive/test/test_read_disk.c \ + libarchive/test/test_read_disk_directory_traversals.c \ + libarchive/test/test_read_disk_entry_from_file.c \ + libarchive/test/test_read_extract.c \ + libarchive/test/test_read_file_nonexistent.c \ + libarchive/test/test_read_filter_compress.c \ + libarchive/test/test_read_filter_grzip.c \ + libarchive/test/test_read_filter_lrzip.c \ + libarchive/test/test_read_filter_lzop.c \ + libarchive/test/test_read_filter_lzop_multiple_parts.c \ + libarchive/test/test_read_filter_program.c \ + libarchive/test/test_read_filter_program_signature.c \ + libarchive/test/test_read_filter_uudecode.c \ + libarchive/test/test_read_format_7zip.c \ + libarchive/test/test_read_format_7zip_encryption_data.c \ + libarchive/test/test_read_format_7zip_encryption_partially.c \ + libarchive/test/test_read_format_7zip_encryption_header.c \ + libarchive/test/test_read_format_7zip_malformed.c \ + libarchive/test/test_read_format_7zip_packinfo_digests.c \ + libarchive/test/test_read_format_ar.c \ + libarchive/test/test_read_format_cab.c \ + libarchive/test/test_read_format_cab_filename.c \ + libarchive/test/test_read_format_cpio_afio.c \ + libarchive/test/test_read_format_cpio_bin.c \ + libarchive/test/test_read_format_cpio_bin_Z.c \ + libarchive/test/test_read_format_cpio_bin_be.c \ + libarchive/test/test_read_format_cpio_bin_bz2.c \ + libarchive/test/test_read_format_cpio_bin_gz.c \ + libarchive/test/test_read_format_cpio_bin_le.c \ + libarchive/test/test_read_format_cpio_bin_lzip.c \ + libarchive/test/test_read_format_cpio_bin_lzma.c \ + libarchive/test/test_read_format_cpio_bin_xz.c \ + libarchive/test/test_read_format_cpio_filename.c \ + libarchive/test/test_read_format_cpio_odc.c \ + libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c \ + libarchive/test/test_read_format_cpio_svr4_gzip.c \ + libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c \ + libarchive/test/test_read_format_cpio_svr4c_Z.c \ + libarchive/test/test_read_format_empty.c \ + libarchive/test/test_read_format_gtar_filename.c \ + libarchive/test/test_read_format_gtar_gz.c \ + libarchive/test/test_read_format_gtar_lzma.c \ + libarchive/test/test_read_format_gtar_sparse.c \ + libarchive/test/test_read_format_gtar_sparse_skip_entry.c \ + libarchive/test/test_read_format_iso_Z.c \ + libarchive/test/test_read_format_iso_multi_extent.c \ + libarchive/test/test_read_format_iso_xorriso.c \ + libarchive/test/test_read_format_isojoliet_bz2.c \ + libarchive/test/test_read_format_isojoliet_long.c \ + libarchive/test/test_read_format_isojoliet_rr.c \ + libarchive/test/test_read_format_isojoliet_versioned.c \ + libarchive/test/test_read_format_isorr_bz2.c \ + libarchive/test/test_read_format_isorr_ce.c \ + libarchive/test/test_read_format_isorr_new_bz2.c \ + libarchive/test/test_read_format_isorr_rr_moved.c \ + libarchive/test/test_read_format_isozisofs_bz2.c \ + libarchive/test/test_read_format_lha.c \ + libarchive/test/test_read_format_lha_bugfix_0.c \ + libarchive/test/test_read_format_lha_filename.c \ + libarchive/test/test_read_format_lha_filename_utf16.c \ + libarchive/test/test_read_format_mtree.c \ + libarchive/test/test_read_format_mtree_crash747.c \ + libarchive/test/test_read_format_pax_bz2.c \ + libarchive/test/test_read_format_rar.c \ + libarchive/test/test_read_format_rar_encryption_data.c \ + libarchive/test/test_read_format_rar_encryption_partially.c \ + libarchive/test/test_read_format_rar_encryption_header.c \ + libarchive/test/test_read_format_rar_invalid1.c \ + libarchive/test/test_read_format_rar5.c \ + libarchive/test/test_read_format_raw.c \ + libarchive/test/test_read_format_tar.c \ + libarchive/test/test_read_format_tar_concatenated.c \ + libarchive/test/test_read_format_tar_empty_pax.c \ + libarchive/test/test_read_format_tar_empty_filename.c \ + libarchive/test/test_read_format_tar_empty_with_gnulabel.c \ + libarchive/test/test_read_format_tar_filename.c \ + libarchive/test/test_read_format_tbz.c \ + libarchive/test/test_read_format_tgz.c \ + libarchive/test/test_read_format_tlz.c \ + libarchive/test/test_read_format_txz.c \ + libarchive/test/test_read_format_tz.c \ + libarchive/test/test_read_format_ustar_filename.c \ + libarchive/test/test_read_format_warc.c \ + libarchive/test/test_read_format_xar.c \ + libarchive/test/test_read_format_zip.c \ + libarchive/test/test_read_format_zip_7075_utf8_paths.c \ + libarchive/test/test_read_format_zip_comment_stored.c \ + libarchive/test/test_read_format_zip_encryption_data.c \ + libarchive/test/test_read_format_zip_encryption_partially.c \ + libarchive/test/test_read_format_zip_encryption_header.c \ + libarchive/test/test_read_format_zip_extra_padding.c \ + libarchive/test/test_read_format_zip_filename.c \ + libarchive/test/test_read_format_zip_high_compression.c \ + libarchive/test/test_read_format_zip_jar.c \ + libarchive/test/test_read_format_zip_mac_metadata.c \ + libarchive/test/test_read_format_zip_malformed.c \ + libarchive/test/test_read_format_zip_msdos.c \ + libarchive/test/test_read_format_zip_nested.c \ + libarchive/test/test_read_format_zip_nofiletype.c \ + libarchive/test/test_read_format_zip_padded.c \ + libarchive/test/test_read_format_zip_sfx.c \ + libarchive/test/test_read_format_zip_traditional_encryption_data.c \ + libarchive/test/test_read_format_zip_winzip_aes.c \ + libarchive/test/test_read_format_zip_winzip_aes_large.c \ + libarchive/test/test_read_format_zip_zip64.c \ + libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c \ + libarchive/test/test_read_large.c \ + libarchive/test/test_read_pax_schily_xattr.c \ + libarchive/test/test_read_pax_truncated.c \ + libarchive/test/test_read_position.c \ + libarchive/test/test_read_set_format.c \ + libarchive/test/test_read_too_many_filters.c \ + libarchive/test/test_read_truncated.c \ + libarchive/test/test_read_truncated_filter.c \ + libarchive/test/test_sparse_basic.c \ + libarchive/test/test_tar_filenames.c \ + libarchive/test/test_tar_large.c \ + libarchive/test/test_ustar_filenames.c \ + libarchive/test/test_ustar_filename_encoding.c \ + libarchive/test/test_warn_missing_hardlink_target.c \ + libarchive/test/test_write_disk.c \ + libarchive/test/test_write_disk_appledouble.c \ + libarchive/test/test_write_disk_failures.c \ + libarchive/test/test_write_disk_hardlink.c \ + libarchive/test/test_write_disk_hfs_compression.c \ + libarchive/test/test_write_disk_lookup.c \ + libarchive/test/test_write_disk_mac_metadata.c \ + libarchive/test/test_write_disk_no_hfs_compression.c \ + libarchive/test/test_write_disk_perms.c \ + libarchive/test/test_write_disk_secure.c \ + libarchive/test/test_write_disk_secure744.c \ + libarchive/test/test_write_disk_secure745.c \ + libarchive/test/test_write_disk_secure746.c \ + libarchive/test/test_write_disk_sparse.c \ + libarchive/test/test_write_disk_symlink.c \ + libarchive/test/test_write_disk_times.c \ + libarchive/test/test_write_filter_b64encode.c \ + libarchive/test/test_write_filter_bzip2.c \ + libarchive/test/test_write_filter_compress.c \ + libarchive/test/test_write_filter_gzip.c \ + libarchive/test/test_write_filter_gzip_timestamp.c \ + libarchive/test/test_write_filter_lrzip.c \ + libarchive/test/test_write_filter_lz4.c \ + libarchive/test/test_write_filter_lzip.c \ + libarchive/test/test_write_filter_lzma.c \ + libarchive/test/test_write_filter_lzop.c \ + libarchive/test/test_write_filter_program.c \ + libarchive/test/test_write_filter_uuencode.c \ + libarchive/test/test_write_filter_xz.c \ + libarchive/test/test_write_filter_zstd.c \ + libarchive/test/test_write_format_7zip.c \ + libarchive/test/test_write_format_7zip_empty.c \ + libarchive/test/test_write_format_7zip_large.c \ + libarchive/test/test_write_format_ar.c \ + libarchive/test/test_write_format_cpio.c \ + libarchive/test/test_write_format_cpio_empty.c \ + libarchive/test/test_write_format_cpio_newc.c \ + libarchive/test/test_write_format_cpio_odc.c \ + libarchive/test/test_write_format_gnutar.c \ + libarchive/test/test_write_format_gnutar_filenames.c \ + libarchive/test/test_write_format_iso9660.c \ + libarchive/test/test_write_format_iso9660_boot.c \ + libarchive/test/test_write_format_iso9660_empty.c \ + libarchive/test/test_write_format_iso9660_filename.c \ + libarchive/test/test_write_format_iso9660_zisofs.c \ + libarchive/test/test_write_format_mtree.c \ + libarchive/test/test_write_format_mtree_absolute_path.c \ + libarchive/test/test_write_format_mtree_classic.c \ + libarchive/test/test_write_format_mtree_classic_indent.c \ + libarchive/test/test_write_format_mtree_fflags.c \ + libarchive/test/test_write_format_mtree_no_separator.c \ + libarchive/test/test_write_format_mtree_quoted_filename.c \ + libarchive/test/test_write_format_pax.c \ + libarchive/test/test_write_format_raw.c \ + libarchive/test/test_write_format_raw_b64.c \ + libarchive/test/test_write_format_shar_empty.c \ + libarchive/test/test_write_format_tar.c \ + libarchive/test/test_write_format_tar_empty.c \ + libarchive/test/test_write_format_tar_sparse.c \ + libarchive/test/test_write_format_tar_ustar.c \ + libarchive/test/test_write_format_tar_v7tar.c \ + libarchive/test/test_write_format_warc.c \ + libarchive/test/test_write_format_warc_empty.c \ + libarchive/test/test_write_format_xar.c \ + libarchive/test/test_write_format_xar_empty.c \ + libarchive/test/test_write_format_zip.c \ + libarchive/test/test_write_format_zip_compression_store.c \ + libarchive/test/test_write_format_zip_empty.c \ + libarchive/test/test_write_format_zip_empty_zip64.c \ + libarchive/test/test_write_format_zip_file.c \ + libarchive/test/test_write_format_zip_file_zip64.c \ + libarchive/test/test_write_format_zip_large.c \ + libarchive/test/test_write_format_zip_zip64.c \ + libarchive/test/test_write_open_memory.c \ + libarchive/test/test_write_read_format_zip.c \ + libarchive/test/test_xattr_platform.c \ + libarchive/test/test_zip_filename_encoding.c +@INC_WINDOWS_FILES_TRUE@am__objects_13 = libarchive/libarchive_test-archive_entry_copy_bhfi.$(OBJEXT) \ +@INC_WINDOWS_FILES_TRUE@ libarchive/libarchive_test-archive_read_disk_windows.$(OBJEXT) \ +@INC_WINDOWS_FILES_TRUE@ libarchive/libarchive_test-archive_windows.$(OBJEXT) \ +@INC_WINDOWS_FILES_TRUE@ libarchive/libarchive_test-archive_write_disk_windows.$(OBJEXT) \ +@INC_WINDOWS_FILES_TRUE@ libarchive/libarchive_test-filter_fork_windows.$(OBJEXT) +@INC_BLAKE2_TRUE@am__objects_14 = libarchive/libarchive_test-archive_blake2s_ref.$(OBJEXT) \ +@INC_BLAKE2_TRUE@ libarchive/libarchive_test-archive_blake2sp_ref.$(OBJEXT) +@INC_LINUX_ACL_TRUE@am__objects_15 = libarchive/libarchive_test-archive_disk_acl_linux.$(OBJEXT) +@INC_LINUX_ACL_FALSE@@INC_SUNOS_ACL_TRUE@am__objects_16 = libarchive/libarchive_test-archive_disk_acl_sunos.$(OBJEXT) +@INC_DARWIN_ACL_TRUE@@INC_LINUX_ACL_FALSE@@INC_SUNOS_ACL_FALSE@am__objects_17 = libarchive/libarchive_test-archive_disk_acl_darwin.$(OBJEXT) +@INC_DARWIN_ACL_FALSE@@INC_FREEBSD_ACL_TRUE@@INC_LINUX_ACL_FALSE@@INC_SUNOS_ACL_FALSE@am__objects_18 = libarchive/libarchive_test-archive_disk_acl_freebsd.$(OBJEXT) +am__objects_19 = libarchive/libarchive_test-archive_acl.$(OBJEXT) \ + libarchive/libarchive_test-archive_check_magic.$(OBJEXT) \ + libarchive/libarchive_test-archive_cmdline.$(OBJEXT) \ + libarchive/libarchive_test-archive_cryptor.$(OBJEXT) \ + libarchive/libarchive_test-archive_digest.$(OBJEXT) \ + libarchive/libarchive_test-archive_entry.$(OBJEXT) \ + libarchive/libarchive_test-archive_entry_copy_stat.$(OBJEXT) \ + libarchive/libarchive_test-archive_entry_link_resolver.$(OBJEXT) \ + libarchive/libarchive_test-archive_entry_sparse.$(OBJEXT) \ + libarchive/libarchive_test-archive_entry_stat.$(OBJEXT) \ + libarchive/libarchive_test-archive_entry_strmode.$(OBJEXT) \ + libarchive/libarchive_test-archive_entry_xattr.$(OBJEXT) \ + libarchive/libarchive_test-archive_getdate.$(OBJEXT) \ + libarchive/libarchive_test-archive_hmac.$(OBJEXT) \ + libarchive/libarchive_test-archive_match.$(OBJEXT) \ + libarchive/libarchive_test-archive_options.$(OBJEXT) \ + libarchive/libarchive_test-archive_pack_dev.$(OBJEXT) \ + libarchive/libarchive_test-archive_pathmatch.$(OBJEXT) \ + libarchive/libarchive_test-archive_ppmd7.$(OBJEXT) \ + libarchive/libarchive_test-archive_ppmd8.$(OBJEXT) \ + libarchive/libarchive_test-archive_random.$(OBJEXT) \ + libarchive/libarchive_test-archive_rb.$(OBJEXT) \ + libarchive/libarchive_test-archive_read.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_add_passphrase.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_append_filter.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_data_into_fd.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_disk_entry_from_file.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_disk_posix.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_disk_set_standard_lookup.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_extract.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_extract2.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_open_fd.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_open_file.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_open_filename.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_open_memory.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_set_format.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_set_options.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_filter_all.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_filter_bzip2.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_filter_compress.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_filter_grzip.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_filter_gzip.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_filter_lrzip.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_filter_lz4.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_filter_lzop.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_filter_none.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_filter_program.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_filter_rpm.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_filter_uu.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_filter_xz.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_filter_zstd.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_format_7zip.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_format_all.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_format_ar.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_format_by_code.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_format_cab.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_format_cpio.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_format_empty.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_format_iso9660.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_format_lha.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_format_mtree.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_format_rar.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_format_rar5.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_format_raw.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_format_tar.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_format_warc.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_format_xar.$(OBJEXT) \ + libarchive/libarchive_test-archive_read_support_format_zip.$(OBJEXT) \ + libarchive/libarchive_test-archive_string.$(OBJEXT) \ + libarchive/libarchive_test-archive_string_sprintf.$(OBJEXT) \ + libarchive/libarchive_test-archive_util.$(OBJEXT) \ + libarchive/libarchive_test-archive_version_details.$(OBJEXT) \ + libarchive/libarchive_test-archive_virtual.$(OBJEXT) \ + libarchive/libarchive_test-archive_write.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_disk_posix.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_disk_set_standard_lookup.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_open_fd.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_open_file.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_open_filename.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_open_memory.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_add_filter.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_add_filter_b64encode.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_add_filter_by_name.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_add_filter_bzip2.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_add_filter_compress.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_add_filter_grzip.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_add_filter_gzip.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_add_filter_lrzip.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_add_filter_lz4.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_add_filter_lzop.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_add_filter_none.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_add_filter_program.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_add_filter_uuencode.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_add_filter_xz.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_add_filter_zstd.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_set_format.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_set_format_7zip.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_set_format_ar.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_set_format_by_name.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_set_format_cpio.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_set_format_cpio_newc.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_set_format_filter_by_ext.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_set_format_iso9660.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_set_format_mtree.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_set_format_pax.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_set_format_raw.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_set_format_shar.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_set_format_ustar.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_set_format_v7tar.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_set_format_gnutar.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_set_format_warc.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_set_format_xar.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_set_format_zip.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_set_options.$(OBJEXT) \ + libarchive/libarchive_test-archive_write_set_passphrase.$(OBJEXT) \ + libarchive/libarchive_test-filter_fork_posix.$(OBJEXT) \ + libarchive/libarchive_test-xxhash.$(OBJEXT) $(am__objects_13) \ + $(am__objects_14) $(am__objects_15) $(am__objects_16) \ + $(am__objects_17) $(am__objects_18) +am__objects_20 = test_utils/libarchive_test-test_utils.$(OBJEXT) \ + test_utils/libarchive_test-test_main.$(OBJEXT) +am_libarchive_test_OBJECTS = $(am__objects_19) $(am__objects_20) \ + libarchive/test/libarchive_test-read_open_memory.$(OBJEXT) \ + libarchive/test/libarchive_test-test_acl_nfs4.$(OBJEXT) \ + libarchive/test/libarchive_test-test_acl_pax.$(OBJEXT) \ + libarchive/test/libarchive_test-test_acl_platform_nfs4.$(OBJEXT) \ + libarchive/test/libarchive_test-test_acl_platform_posix1e.$(OBJEXT) \ + libarchive/test/libarchive_test-test_acl_posix1e.$(OBJEXT) \ + libarchive/test/libarchive_test-test_acl_text.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_api_feature.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_clear_error.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_cmdline.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_digest.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_getdate.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_match_owner.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_match_path.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_match_time.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_pathmatch.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_read_add_passphrase.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_read_close_twice.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_read_close_twice_open_fd.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_read_close_twice_open_filename.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_read_multiple_data_objects.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_read_next_header_empty.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_read_next_header_raw.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_read_open2.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_read_set_filter_option.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_read_set_format_option.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_read_set_option.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_read_set_options.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_read_support.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_set_error.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_string.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_string_conversion.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_write_add_filter_by_name.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_write_set_filter_option.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_write_set_format_by_name.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_write_set_format_filter_by_ext.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_write_set_format_option.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_write_set_option.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_write_set_options.$(OBJEXT) \ + libarchive/test/libarchive_test-test_archive_write_set_passphrase.$(OBJEXT) \ + libarchive/test/libarchive_test-test_bad_fd.$(OBJEXT) \ + libarchive/test/libarchive_test-test_compat_bzip2.$(OBJEXT) \ + libarchive/test/libarchive_test-test_compat_cpio.$(OBJEXT) \ + libarchive/test/libarchive_test-test_compat_gtar.$(OBJEXT) \ + libarchive/test/libarchive_test-test_compat_gzip.$(OBJEXT) \ + libarchive/test/libarchive_test-test_compat_lz4.$(OBJEXT) \ + libarchive/test/libarchive_test-test_compat_lzip.$(OBJEXT) \ + libarchive/test/libarchive_test-test_compat_lzma.$(OBJEXT) \ + libarchive/test/libarchive_test-test_compat_lzop.$(OBJEXT) \ + libarchive/test/libarchive_test-test_compat_mac.$(OBJEXT) \ + libarchive/test/libarchive_test-test_compat_perl_archive_tar.$(OBJEXT) \ + libarchive/test/libarchive_test-test_compat_plexus_archiver_tar.$(OBJEXT) \ + libarchive/test/libarchive_test-test_compat_solaris_tar_acl.$(OBJEXT) \ + libarchive/test/libarchive_test-test_compat_solaris_pax_sparse.$(OBJEXT) \ + libarchive/test/libarchive_test-test_compat_star_acl.$(OBJEXT) \ + libarchive/test/libarchive_test-test_compat_tar_hardlink.$(OBJEXT) \ + libarchive/test/libarchive_test-test_compat_uudecode.$(OBJEXT) \ + libarchive/test/libarchive_test-test_compat_uudecode_large.$(OBJEXT) \ + libarchive/test/libarchive_test-test_compat_xz.$(OBJEXT) \ + libarchive/test/libarchive_test-test_compat_zip.$(OBJEXT) \ + libarchive/test/libarchive_test-test_compat_zstd.$(OBJEXT) \ + libarchive/test/libarchive_test-test_empty_write.$(OBJEXT) \ + libarchive/test/libarchive_test-test_entry.$(OBJEXT) \ + libarchive/test/libarchive_test-test_entry_strmode.$(OBJEXT) \ + libarchive/test/libarchive_test-test_extattr_freebsd.$(OBJEXT) \ + libarchive/test/libarchive_test-test_filter_count.$(OBJEXT) \ + libarchive/test/libarchive_test-test_fuzz.$(OBJEXT) \ + libarchive/test/libarchive_test-test_gnutar_filename_encoding.$(OBJEXT) \ + libarchive/test/libarchive_test-test_link_resolver.$(OBJEXT) \ + libarchive/test/libarchive_test-test_open_failure.$(OBJEXT) \ + libarchive/test/libarchive_test-test_open_fd.$(OBJEXT) \ + libarchive/test/libarchive_test-test_open_file.$(OBJEXT) \ + libarchive/test/libarchive_test-test_open_filename.$(OBJEXT) \ + libarchive/test/libarchive_test-test_pax_filename_encoding.$(OBJEXT) \ + libarchive/test/libarchive_test-test_pax_xattr_header.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_data_large.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_disk.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_disk_directory_traversals.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_disk_entry_from_file.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_extract.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_file_nonexistent.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_filter_compress.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_filter_grzip.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_filter_lrzip.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_filter_lzop.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_filter_lzop_multiple_parts.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_filter_program.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_filter_program_signature.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_filter_uudecode.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_7zip.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_7zip_encryption_data.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_7zip_encryption_partially.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_7zip_encryption_header.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_7zip_malformed.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_7zip_packinfo_digests.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_ar.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_cab.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_cab_filename.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_cpio_afio.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_cpio_bin.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_cpio_bin_Z.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_cpio_bin_be.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_cpio_bin_bz2.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_cpio_bin_gz.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_cpio_bin_le.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_cpio_bin_lzip.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_cpio_bin_lzma.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_cpio_bin_xz.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_cpio_filename.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_cpio_odc.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_cpio_svr4_bzip2_rpm.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_cpio_svr4_gzip.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_cpio_svr4_gzip_rpm.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_cpio_svr4c_Z.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_empty.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_gtar_filename.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_gtar_gz.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_gtar_lzma.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_gtar_sparse.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_gtar_sparse_skip_entry.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_iso_Z.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_iso_multi_extent.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_iso_xorriso.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_isojoliet_bz2.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_isojoliet_long.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_isojoliet_rr.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_isojoliet_versioned.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_isorr_bz2.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_isorr_ce.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_isorr_new_bz2.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_isorr_rr_moved.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_isozisofs_bz2.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_lha.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_lha_bugfix_0.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_lha_filename.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_lha_filename_utf16.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_mtree.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_mtree_crash747.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_pax_bz2.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_rar.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_rar_encryption_data.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_rar_encryption_partially.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_rar_encryption_header.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_rar_invalid1.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_rar5.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_raw.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_tar.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_tar_concatenated.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_tar_empty_pax.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_tar_empty_filename.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_tar_empty_with_gnulabel.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_tar_filename.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_tbz.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_tgz.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_tlz.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_txz.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_tz.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_ustar_filename.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_warc.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_xar.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_zip.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_zip_7075_utf8_paths.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_zip_comment_stored.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_zip_encryption_data.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_zip_encryption_partially.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_zip_encryption_header.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_zip_extra_padding.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_zip_filename.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_zip_high_compression.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_zip_jar.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_zip_mac_metadata.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_zip_malformed.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_zip_msdos.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_zip_nested.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_zip_nofiletype.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_zip_padded.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_zip_sfx.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_zip_traditional_encryption_data.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_zip_winzip_aes.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_zip_winzip_aes_large.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_zip_zip64.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_format_zip_with_invalid_traditional_eocd.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_large.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_pax_schily_xattr.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_pax_truncated.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_position.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_set_format.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_too_many_filters.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_truncated.$(OBJEXT) \ + libarchive/test/libarchive_test-test_read_truncated_filter.$(OBJEXT) \ + libarchive/test/libarchive_test-test_sparse_basic.$(OBJEXT) \ + libarchive/test/libarchive_test-test_tar_filenames.$(OBJEXT) \ + libarchive/test/libarchive_test-test_tar_large.$(OBJEXT) \ + libarchive/test/libarchive_test-test_ustar_filenames.$(OBJEXT) \ + libarchive/test/libarchive_test-test_ustar_filename_encoding.$(OBJEXT) \ + libarchive/test/libarchive_test-test_warn_missing_hardlink_target.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_disk.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_disk_appledouble.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_disk_failures.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_disk_hardlink.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_disk_hfs_compression.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_disk_lookup.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_disk_mac_metadata.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_disk_no_hfs_compression.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_disk_perms.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_disk_secure.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_disk_secure744.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_disk_secure745.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_disk_secure746.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_disk_sparse.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_disk_symlink.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_disk_times.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_filter_b64encode.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_filter_bzip2.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_filter_compress.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_filter_gzip.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_filter_gzip_timestamp.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_filter_lrzip.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_filter_lz4.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_filter_lzip.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_filter_lzma.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_filter_lzop.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_filter_program.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_filter_uuencode.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_filter_xz.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_filter_zstd.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_7zip.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_7zip_empty.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_7zip_large.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_ar.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_cpio.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_cpio_empty.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_cpio_newc.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_cpio_odc.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_gnutar.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_gnutar_filenames.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_iso9660.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_iso9660_boot.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_iso9660_empty.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_iso9660_filename.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_iso9660_zisofs.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_mtree.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_mtree_absolute_path.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_mtree_classic.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_mtree_classic_indent.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_mtree_fflags.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_mtree_no_separator.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_mtree_quoted_filename.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_pax.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_raw.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_raw_b64.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_shar_empty.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_tar.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_tar_empty.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_tar_sparse.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_tar_ustar.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_tar_v7tar.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_warc.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_warc_empty.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_xar.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_xar_empty.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_zip.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_zip_compression_store.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_zip_empty.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_zip_empty_zip64.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_zip_file.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_zip_file_zip64.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_zip_large.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_format_zip_zip64.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_open_memory.$(OBJEXT) \ + libarchive/test/libarchive_test-test_write_read_format_zip.$(OBJEXT) \ + libarchive/test/libarchive_test-test_xattr_platform.$(OBJEXT) \ + libarchive/test/libarchive_test-test_zip_filename_encoding.$(OBJEXT) +libarchive_test_OBJECTS = $(am_libarchive_test_OBJECTS) +libarchive_test_DEPENDENCIES = $(am__DEPENDENCIES_1) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/build/autoconf/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libarchive_la_SOURCES) $(libarchive_fe_la_SOURCES) \ + $(bsdcat_SOURCES) $(bsdcat_test_SOURCES) $(bsdcpio_SOURCES) \ + $(bsdcpio_test_SOURCES) $(bsdtar_SOURCES) \ + $(bsdtar_test_SOURCES) $(libarchive_test_SOURCES) +DIST_SOURCES = $(am__libarchive_la_SOURCES_DIST) \ + $(libarchive_fe_la_SOURCES) $(bsdcat_SOURCES) \ + $(bsdcat_test_SOURCES) $(am__bsdcpio_SOURCES_DIST) \ + $(bsdcpio_test_SOURCES) $(am__bsdtar_SOURCES_DIST) \ + $(bsdtar_test_SOURCES) $(am__libarchive_test_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +man1dir = $(mandir)/man1 +man3dir = $(mandir)/man3 +man5dir = $(mandir)/man5 +NROFF = nroff +MANS = $(man_MANS) +DATA = $(pkgconfig_DATA) +HEADERS = $(include_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ + $(LISP)config.h.in +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +CSCOPE = cscope +AM_RECURSIVE_TARGETS = cscope check recheck +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red=''; \ + grn=''; \ + lgn=''; \ + blu=''; \ + mgn=''; \ + brg=''; \ + std=''; \ + fi; \ +} +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +RECHECK_LOGS = $(TEST_LOGS) +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_DRIVER = $(SHELL) $(top_srcdir)/build/autoconf/test-driver +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/build/autoconf/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(top_srcdir)/build/autoconf/compile \ + $(top_srcdir)/build/autoconf/config.guess \ + $(top_srcdir)/build/autoconf/config.rpath \ + $(top_srcdir)/build/autoconf/config.sub \ + $(top_srcdir)/build/autoconf/depcomp \ + $(top_srcdir)/build/autoconf/install-sh \ + $(top_srcdir)/build/autoconf/ltmain.sh \ + $(top_srcdir)/build/autoconf/missing \ + $(top_srcdir)/build/autoconf/test-driver \ + $(top_srcdir)/build/pkgconfig/libarchive.pc.in COPYING INSTALL \ + NEWS build/autoconf/compile build/autoconf/config.guess \ + build/autoconf/config.rpath build/autoconf/config.sub \ + build/autoconf/depcomp build/autoconf/install-sh \ + build/autoconf/ltmain.sh build/autoconf/missing +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +DIST_ARCHIVES = $(distdir).tar.gz $(distdir).tar.xz $(distdir).zip +GZIP_ENV = --best +DIST_TARGETS = dist-xz dist-gzip dist-zip +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ARCHIVE_LIBTOOL_VERSION = @ARCHIVE_LIBTOOL_VERSION@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BSDCAT_VERSION_STRING = @BSDCAT_VERSION_STRING@ +BSDCPIO_VERSION_STRING = @BSDCPIO_VERSION_STRING@ +BSDTAR_VERSION_STRING = @BSDTAR_VERSION_STRING@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBARCHIVE_VERSION_NUMBER = @LIBARCHIVE_VERSION_NUMBER@ +LIBARCHIVE_VERSION_STRING = @LIBARCHIVE_VERSION_STRING@ +LIBICONV = @LIBICONV@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBXML2_PC_CFLAGS = @LIBXML2_PC_CFLAGS@ +LIBXML2_PC_LIBS = @LIBXML2_PC_LIBS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PLATFORMCPPFLAGS = @PLATFORMCPPFLAGS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = foreign subdir-objects +ACLOCAL_AMFLAGS = -I build/autoconf + +# +# What to build and install +# +lib_LTLIBRARIES = libarchive.la +noinst_LTLIBRARIES = libarchive_fe.la +man_MANS = $(libarchive_man_MANS) $(bsdtar_man_MANS) $(bsdcpio_man_MANS) $(bsdcat_man_MANS) +BUILT_SOURCES = libarchive/test/list.h tar/test/list.h cpio/test/list.h cat/test/list.h +TESTS_ENVIRONMENT = $(libarchive_TESTS_ENVIRONMENT) $(bsdtar_TESTS_ENVIRONMENT) $(bsdcpio_TESTS_ENVIRONMENT) $(bsdcat_TESTS_ENVIRONMENT) +# Always build and test both bsdtar and bsdcpio as part of 'distcheck' +DISTCHECK_CONFIGURE_FLAGS = --enable-bsdtar --enable-bsdcpio +# The next line is commented out by default in shipping libarchive releases. +# It is uncommented by default in trunk. +# DEV_CFLAGS=-Werror -Wextra -Wunused -Wshadow -Wmissing-prototypes -Wcast-qual -g +AM_CFLAGS = $(DEV_CFLAGS) +AM_CPPFLAGS = $(PLATFORMCPPFLAGS) + +# +# What to include in the distribution +# +EXTRA_DIST = \ + CMakeLists.txt \ + README.md \ + build/autogen.sh \ + build/bump-version.sh \ + build/clean.sh \ + build/cmake \ + build/version \ + contrib \ + doc \ + examples \ + $(libarchive_EXTRA_DIST) \ + $(libarchive_test_EXTRA_DIST) \ + $(bsdtar_EXTRA_DIST) \ + $(bsdtar_test_EXTRA_DIST) \ + $(bsdcpio_EXTRA_DIST) \ + $(bsdcpio_test_EXTRA_DIST) \ + $(bsdcat_EXTRA_DIST) \ + $(bsdcat_test_EXTRA_DIST) + + +# +# Extra rules for cleanup +# +DISTCLEANFILES = \ + libarchive/test/list.h \ + tar/test/list.h \ + cpio/test/list.h \ + cat/test/list.h + + +# +# Libarchive headers, source, etc. +# +# +include_HEADERS = libarchive/archive.h libarchive/archive_entry.h +libarchive_la_SOURCES = libarchive/archive_acl.c \ + libarchive/archive_acl_private.h \ + libarchive/archive_check_magic.c libarchive/archive_cmdline.c \ + libarchive/archive_cmdline_private.h \ + libarchive/archive_crc32.h libarchive/archive_cryptor.c \ + libarchive/archive_cryptor_private.h \ + libarchive/archive_digest.c \ + libarchive/archive_digest_private.h \ + libarchive/archive_endian.h libarchive/archive_entry.c \ + libarchive/archive_entry.h \ + libarchive/archive_entry_copy_stat.c \ + libarchive/archive_entry_link_resolver.c \ + libarchive/archive_entry_locale.h \ + libarchive/archive_entry_private.h \ + libarchive/archive_entry_sparse.c \ + libarchive/archive_entry_stat.c \ + libarchive/archive_entry_strmode.c \ + libarchive/archive_entry_xattr.c libarchive/archive_getdate.c \ + libarchive/archive_getdate.h libarchive/archive_hmac.c \ + libarchive/archive_hmac_private.h libarchive/archive_match.c \ + libarchive/archive_openssl_evp_private.h \ + libarchive/archive_openssl_hmac_private.h \ + libarchive/archive_options.c \ + libarchive/archive_options_private.h \ + libarchive/archive_pack_dev.h libarchive/archive_pack_dev.c \ + libarchive/archive_pathmatch.c libarchive/archive_pathmatch.h \ + libarchive/archive_platform.h \ + libarchive/archive_platform_acl.h \ + libarchive/archive_platform_xattr.h \ + libarchive/archive_ppmd_private.h libarchive/archive_ppmd7.c \ + libarchive/archive_ppmd7_private.h libarchive/archive_ppmd8.c \ + libarchive/archive_ppmd8_private.h \ + libarchive/archive_private.h libarchive/archive_random.c \ + libarchive/archive_random_private.h libarchive/archive_rb.c \ + libarchive/archive_rb.h libarchive/archive_read.c \ + libarchive/archive_read_add_passphrase.c \ + libarchive/archive_read_append_filter.c \ + libarchive/archive_read_data_into_fd.c \ + libarchive/archive_read_disk_entry_from_file.c \ + libarchive/archive_read_disk_posix.c \ + libarchive/archive_read_disk_private.h \ + libarchive/archive_read_disk_set_standard_lookup.c \ + libarchive/archive_read_extract.c \ + libarchive/archive_read_extract2.c \ + libarchive/archive_read_open_fd.c \ + libarchive/archive_read_open_file.c \ + libarchive/archive_read_open_filename.c \ + libarchive/archive_read_open_memory.c \ + libarchive/archive_read_private.h \ + libarchive/archive_read_set_format.c \ + libarchive/archive_read_set_options.c \ + libarchive/archive_read_support_filter_all.c \ + libarchive/archive_read_support_filter_bzip2.c \ + libarchive/archive_read_support_filter_compress.c \ + libarchive/archive_read_support_filter_grzip.c \ + libarchive/archive_read_support_filter_gzip.c \ + libarchive/archive_read_support_filter_lrzip.c \ + libarchive/archive_read_support_filter_lz4.c \ + libarchive/archive_read_support_filter_lzop.c \ + libarchive/archive_read_support_filter_none.c \ + libarchive/archive_read_support_filter_program.c \ + libarchive/archive_read_support_filter_rpm.c \ + libarchive/archive_read_support_filter_uu.c \ + libarchive/archive_read_support_filter_xz.c \ + libarchive/archive_read_support_filter_zstd.c \ + libarchive/archive_read_support_format_7zip.c \ + libarchive/archive_read_support_format_all.c \ + libarchive/archive_read_support_format_ar.c \ + libarchive/archive_read_support_format_by_code.c \ + libarchive/archive_read_support_format_cab.c \ + libarchive/archive_read_support_format_cpio.c \ + libarchive/archive_read_support_format_empty.c \ + libarchive/archive_read_support_format_iso9660.c \ + libarchive/archive_read_support_format_lha.c \ + libarchive/archive_read_support_format_mtree.c \ + libarchive/archive_read_support_format_rar.c \ + libarchive/archive_read_support_format_rar5.c \ + libarchive/archive_read_support_format_raw.c \ + libarchive/archive_read_support_format_tar.c \ + libarchive/archive_read_support_format_warc.c \ + libarchive/archive_read_support_format_xar.c \ + libarchive/archive_read_support_format_zip.c \ + libarchive/archive_string.c libarchive/archive_string.h \ + libarchive/archive_string_composition.h \ + libarchive/archive_string_sprintf.c libarchive/archive_util.c \ + libarchive/archive_version_details.c \ + libarchive/archive_virtual.c libarchive/archive_write.c \ + libarchive/archive_write_disk_posix.c \ + libarchive/archive_write_disk_private.h \ + libarchive/archive_write_disk_set_standard_lookup.c \ + libarchive/archive_write_open_fd.c \ + libarchive/archive_write_open_file.c \ + libarchive/archive_write_open_filename.c \ + libarchive/archive_write_open_memory.c \ + libarchive/archive_write_private.h \ + libarchive/archive_write_add_filter.c \ + libarchive/archive_write_add_filter_b64encode.c \ + libarchive/archive_write_add_filter_by_name.c \ + libarchive/archive_write_add_filter_bzip2.c \ + libarchive/archive_write_add_filter_compress.c \ + libarchive/archive_write_add_filter_grzip.c \ + libarchive/archive_write_add_filter_gzip.c \ + libarchive/archive_write_add_filter_lrzip.c \ + libarchive/archive_write_add_filter_lz4.c \ + libarchive/archive_write_add_filter_lzop.c \ + libarchive/archive_write_add_filter_none.c \ + libarchive/archive_write_add_filter_program.c \ + libarchive/archive_write_add_filter_uuencode.c \ + libarchive/archive_write_add_filter_xz.c \ + libarchive/archive_write_add_filter_zstd.c \ + libarchive/archive_write_set_format.c \ + libarchive/archive_write_set_format_7zip.c \ + libarchive/archive_write_set_format_ar.c \ + libarchive/archive_write_set_format_by_name.c \ + libarchive/archive_write_set_format_cpio.c \ + libarchive/archive_write_set_format_cpio_newc.c \ + libarchive/archive_write_set_format_filter_by_ext.c \ + libarchive/archive_write_set_format_iso9660.c \ + libarchive/archive_write_set_format_mtree.c \ + libarchive/archive_write_set_format_pax.c \ + libarchive/archive_write_set_format_private.h \ + libarchive/archive_write_set_format_raw.c \ + libarchive/archive_write_set_format_shar.c \ + libarchive/archive_write_set_format_ustar.c \ + libarchive/archive_write_set_format_v7tar.c \ + libarchive/archive_write_set_format_gnutar.c \ + libarchive/archive_write_set_format_warc.c \ + libarchive/archive_write_set_format_xar.c \ + libarchive/archive_write_set_format_zip.c \ + libarchive/archive_write_set_options.c \ + libarchive/archive_write_set_passphrase.c \ + libarchive/archive_xxhash.h libarchive/config_freebsd.h \ + libarchive/filter_fork_posix.c libarchive/filter_fork.h \ + libarchive/xxhash.c $(am__append_1) $(am__append_2) \ + $(am__append_3) $(am__append_4) $(am__append_5) \ + $(am__append_6) + +# -no-undefined marks that libarchive doesn't rely on symbols +# defined in the application. This is mandatory for cygwin. +libarchive_la_LDFLAGS = -no-undefined -version-info $(ARCHIVE_LIBTOOL_VERSION) +libarchive_la_LIBADD = $(LTLIBICONV) + +# Manpages to install +libarchive_man_MANS = \ + libarchive/archive_entry.3 \ + libarchive/archive_entry_acl.3 \ + libarchive/archive_entry_linkify.3 \ + libarchive/archive_entry_misc.3 \ + libarchive/archive_entry_paths.3 \ + libarchive/archive_entry_perms.3 \ + libarchive/archive_entry_stat.3 \ + libarchive/archive_entry_time.3 \ + libarchive/archive_read.3 \ + libarchive/archive_read_add_passphrase.3 \ + libarchive/archive_read_data.3 \ + libarchive/archive_read_disk.3 \ + libarchive/archive_read_extract.3 \ + libarchive/archive_read_filter.3 \ + libarchive/archive_read_format.3 \ + libarchive/archive_read_free.3 \ + libarchive/archive_read_header.3 \ + libarchive/archive_read_new.3 \ + libarchive/archive_read_open.3 \ + libarchive/archive_read_set_options.3 \ + libarchive/archive_util.3 \ + libarchive/archive_write.3 \ + libarchive/archive_write_blocksize.3 \ + libarchive/archive_write_data.3 \ + libarchive/archive_write_disk.3 \ + libarchive/archive_write_filter.3 \ + libarchive/archive_write_finish_entry.3 \ + libarchive/archive_write_format.3 \ + libarchive/archive_write_free.3 \ + libarchive/archive_write_header.3 \ + libarchive/archive_write_new.3 \ + libarchive/archive_write_open.3 \ + libarchive/archive_write_set_options.3 \ + libarchive/archive_write_set_passphrase.3 \ + libarchive/cpio.5 \ + libarchive/libarchive.3 \ + libarchive/libarchive_changes.3 \ + libarchive/libarchive_internals.3 \ + libarchive/libarchive-formats.5 \ + libarchive/mtree.5 \ + libarchive/tar.5 + + +# Additional libarchive files to include in the distribution +libarchive_EXTRA_DIST = \ + libarchive/archive_windows.c \ + libarchive/archive_windows.h \ + libarchive/filter_fork_windows.c \ + libarchive/CMakeLists.txt \ + $(libarchive_man_MANS) + + +# pkgconfig +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = build/pkgconfig/libarchive.pc + +# Sources needed by all test programs +test_utils_SOURCES = \ + test_utils/test_utils.c \ + test_utils/test_utils.h \ + test_utils/test_main.c \ + test_utils/test_common.h + + +# +# +# libarchive_test program +# +# +libarchive_test_SOURCES = \ + $(libarchive_la_SOURCES) \ + $(test_utils_SOURCES) \ + libarchive/test/read_open_memory.c \ + libarchive/test/test.h \ + libarchive/test/test_acl_nfs4.c \ + libarchive/test/test_acl_pax.c \ + libarchive/test/test_acl_platform_nfs4.c \ + libarchive/test/test_acl_platform_posix1e.c \ + libarchive/test/test_acl_posix1e.c \ + libarchive/test/test_acl_text.c \ + libarchive/test/test_archive_api_feature.c \ + libarchive/test/test_archive_clear_error.c \ + libarchive/test/test_archive_cmdline.c \ + libarchive/test/test_archive_digest.c \ + libarchive/test/test_archive_getdate.c \ + libarchive/test/test_archive_match_owner.c \ + libarchive/test/test_archive_match_path.c \ + libarchive/test/test_archive_match_time.c \ + libarchive/test/test_archive_pathmatch.c \ + libarchive/test/test_archive_read_add_passphrase.c \ + libarchive/test/test_archive_read_close_twice.c \ + libarchive/test/test_archive_read_close_twice_open_fd.c \ + libarchive/test/test_archive_read_close_twice_open_filename.c \ + libarchive/test/test_archive_read_multiple_data_objects.c \ + libarchive/test/test_archive_read_next_header_empty.c \ + libarchive/test/test_archive_read_next_header_raw.c \ + libarchive/test/test_archive_read_open2.c \ + libarchive/test/test_archive_read_set_filter_option.c \ + libarchive/test/test_archive_read_set_format_option.c \ + libarchive/test/test_archive_read_set_option.c \ + libarchive/test/test_archive_read_set_options.c \ + libarchive/test/test_archive_read_support.c \ + libarchive/test/test_archive_set_error.c \ + libarchive/test/test_archive_string.c \ + libarchive/test/test_archive_string_conversion.c \ + libarchive/test/test_archive_write_add_filter_by_name.c \ + libarchive/test/test_archive_write_set_filter_option.c \ + libarchive/test/test_archive_write_set_format_by_name.c \ + libarchive/test/test_archive_write_set_format_filter_by_ext.c \ + libarchive/test/test_archive_write_set_format_option.c \ + libarchive/test/test_archive_write_set_option.c \ + libarchive/test/test_archive_write_set_options.c \ + libarchive/test/test_archive_write_set_passphrase.c \ + libarchive/test/test_bad_fd.c \ + libarchive/test/test_compat_bzip2.c \ + libarchive/test/test_compat_cpio.c \ + libarchive/test/test_compat_gtar.c \ + libarchive/test/test_compat_gzip.c \ + libarchive/test/test_compat_lz4.c \ + libarchive/test/test_compat_lzip.c \ + libarchive/test/test_compat_lzma.c \ + libarchive/test/test_compat_lzop.c \ + libarchive/test/test_compat_mac.c \ + libarchive/test/test_compat_perl_archive_tar.c \ + libarchive/test/test_compat_plexus_archiver_tar.c \ + libarchive/test/test_compat_solaris_tar_acl.c \ + libarchive/test/test_compat_solaris_pax_sparse.c \ + libarchive/test/test_compat_star_acl.c \ + libarchive/test/test_compat_tar_hardlink.c \ + libarchive/test/test_compat_uudecode.c \ + libarchive/test/test_compat_uudecode_large.c \ + libarchive/test/test_compat_xz.c \ + libarchive/test/test_compat_zip.c \ + libarchive/test/test_compat_zstd.c \ + libarchive/test/test_empty_write.c \ + libarchive/test/test_entry.c \ + libarchive/test/test_entry_strmode.c \ + libarchive/test/test_extattr_freebsd.c \ + libarchive/test/test_filter_count.c \ + libarchive/test/test_fuzz.c \ + libarchive/test/test_gnutar_filename_encoding.c \ + libarchive/test/test_link_resolver.c \ + libarchive/test/test_open_failure.c \ + libarchive/test/test_open_fd.c \ + libarchive/test/test_open_file.c \ + libarchive/test/test_open_filename.c \ + libarchive/test/test_pax_filename_encoding.c \ + libarchive/test/test_pax_xattr_header.c \ + libarchive/test/test_read_data_large.c \ + libarchive/test/test_read_disk.c \ + libarchive/test/test_read_disk_directory_traversals.c \ + libarchive/test/test_read_disk_entry_from_file.c \ + libarchive/test/test_read_extract.c \ + libarchive/test/test_read_file_nonexistent.c \ + libarchive/test/test_read_filter_compress.c \ + libarchive/test/test_read_filter_grzip.c \ + libarchive/test/test_read_filter_lrzip.c \ + libarchive/test/test_read_filter_lzop.c \ + libarchive/test/test_read_filter_lzop_multiple_parts.c \ + libarchive/test/test_read_filter_program.c \ + libarchive/test/test_read_filter_program_signature.c \ + libarchive/test/test_read_filter_uudecode.c \ + libarchive/test/test_read_format_7zip.c \ + libarchive/test/test_read_format_7zip_encryption_data.c \ + libarchive/test/test_read_format_7zip_encryption_partially.c \ + libarchive/test/test_read_format_7zip_encryption_header.c \ + libarchive/test/test_read_format_7zip_malformed.c \ + libarchive/test/test_read_format_7zip_packinfo_digests.c \ + libarchive/test/test_read_format_ar.c \ + libarchive/test/test_read_format_cab.c \ + libarchive/test/test_read_format_cab_filename.c \ + libarchive/test/test_read_format_cpio_afio.c \ + libarchive/test/test_read_format_cpio_bin.c \ + libarchive/test/test_read_format_cpio_bin_Z.c \ + libarchive/test/test_read_format_cpio_bin_be.c \ + libarchive/test/test_read_format_cpio_bin_bz2.c \ + libarchive/test/test_read_format_cpio_bin_gz.c \ + libarchive/test/test_read_format_cpio_bin_le.c \ + libarchive/test/test_read_format_cpio_bin_lzip.c \ + libarchive/test/test_read_format_cpio_bin_lzma.c \ + libarchive/test/test_read_format_cpio_bin_xz.c \ + libarchive/test/test_read_format_cpio_filename.c \ + libarchive/test/test_read_format_cpio_odc.c \ + libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c \ + libarchive/test/test_read_format_cpio_svr4_gzip.c \ + libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c \ + libarchive/test/test_read_format_cpio_svr4c_Z.c \ + libarchive/test/test_read_format_empty.c \ + libarchive/test/test_read_format_gtar_filename.c \ + libarchive/test/test_read_format_gtar_gz.c \ + libarchive/test/test_read_format_gtar_lzma.c \ + libarchive/test/test_read_format_gtar_sparse.c \ + libarchive/test/test_read_format_gtar_sparse_skip_entry.c \ + libarchive/test/test_read_format_iso_Z.c \ + libarchive/test/test_read_format_iso_multi_extent.c \ + libarchive/test/test_read_format_iso_xorriso.c \ + libarchive/test/test_read_format_isojoliet_bz2.c \ + libarchive/test/test_read_format_isojoliet_long.c \ + libarchive/test/test_read_format_isojoliet_rr.c \ + libarchive/test/test_read_format_isojoliet_versioned.c \ + libarchive/test/test_read_format_isorr_bz2.c \ + libarchive/test/test_read_format_isorr_ce.c \ + libarchive/test/test_read_format_isorr_new_bz2.c \ + libarchive/test/test_read_format_isorr_rr_moved.c \ + libarchive/test/test_read_format_isozisofs_bz2.c \ + libarchive/test/test_read_format_lha.c \ + libarchive/test/test_read_format_lha_bugfix_0.c \ + libarchive/test/test_read_format_lha_filename.c \ + libarchive/test/test_read_format_lha_filename_utf16.c \ + libarchive/test/test_read_format_mtree.c \ + libarchive/test/test_read_format_mtree_crash747.c \ + libarchive/test/test_read_format_pax_bz2.c \ + libarchive/test/test_read_format_rar.c \ + libarchive/test/test_read_format_rar_encryption_data.c \ + libarchive/test/test_read_format_rar_encryption_partially.c \ + libarchive/test/test_read_format_rar_encryption_header.c \ + libarchive/test/test_read_format_rar_invalid1.c \ + libarchive/test/test_read_format_rar5.c \ + libarchive/test/test_read_format_raw.c \ + libarchive/test/test_read_format_tar.c \ + libarchive/test/test_read_format_tar_concatenated.c \ + libarchive/test/test_read_format_tar_empty_pax.c \ + libarchive/test/test_read_format_tar_empty_filename.c \ + libarchive/test/test_read_format_tar_empty_with_gnulabel.c \ + libarchive/test/test_read_format_tar_filename.c \ + libarchive/test/test_read_format_tbz.c \ + libarchive/test/test_read_format_tgz.c \ + libarchive/test/test_read_format_tlz.c \ + libarchive/test/test_read_format_txz.c \ + libarchive/test/test_read_format_tz.c \ + libarchive/test/test_read_format_ustar_filename.c \ + libarchive/test/test_read_format_warc.c \ + libarchive/test/test_read_format_xar.c \ + libarchive/test/test_read_format_zip.c \ + libarchive/test/test_read_format_zip_7075_utf8_paths.c \ + libarchive/test/test_read_format_zip_comment_stored.c \ + libarchive/test/test_read_format_zip_encryption_data.c \ + libarchive/test/test_read_format_zip_encryption_partially.c \ + libarchive/test/test_read_format_zip_encryption_header.c \ + libarchive/test/test_read_format_zip_extra_padding.c \ + libarchive/test/test_read_format_zip_filename.c \ + libarchive/test/test_read_format_zip_high_compression.c \ + libarchive/test/test_read_format_zip_jar.c \ + libarchive/test/test_read_format_zip_mac_metadata.c \ + libarchive/test/test_read_format_zip_malformed.c \ + libarchive/test/test_read_format_zip_msdos.c \ + libarchive/test/test_read_format_zip_nested.c \ + libarchive/test/test_read_format_zip_nofiletype.c \ + libarchive/test/test_read_format_zip_padded.c \ + libarchive/test/test_read_format_zip_sfx.c \ + libarchive/test/test_read_format_zip_traditional_encryption_data.c \ + libarchive/test/test_read_format_zip_winzip_aes.c \ + libarchive/test/test_read_format_zip_winzip_aes_large.c \ + libarchive/test/test_read_format_zip_zip64.c \ + libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c \ + libarchive/test/test_read_large.c \ + libarchive/test/test_read_pax_schily_xattr.c \ + libarchive/test/test_read_pax_truncated.c \ + libarchive/test/test_read_position.c \ + libarchive/test/test_read_set_format.c \ + libarchive/test/test_read_too_many_filters.c \ + libarchive/test/test_read_truncated.c \ + libarchive/test/test_read_truncated_filter.c \ + libarchive/test/test_sparse_basic.c \ + libarchive/test/test_tar_filenames.c \ + libarchive/test/test_tar_large.c \ + libarchive/test/test_ustar_filenames.c \ + libarchive/test/test_ustar_filename_encoding.c \ + libarchive/test/test_warn_missing_hardlink_target.c \ + libarchive/test/test_write_disk.c \ + libarchive/test/test_write_disk_appledouble.c \ + libarchive/test/test_write_disk_failures.c \ + libarchive/test/test_write_disk_hardlink.c \ + libarchive/test/test_write_disk_hfs_compression.c \ + libarchive/test/test_write_disk_lookup.c \ + libarchive/test/test_write_disk_mac_metadata.c \ + libarchive/test/test_write_disk_no_hfs_compression.c \ + libarchive/test/test_write_disk_perms.c \ + libarchive/test/test_write_disk_secure.c \ + libarchive/test/test_write_disk_secure744.c \ + libarchive/test/test_write_disk_secure745.c \ + libarchive/test/test_write_disk_secure746.c \ + libarchive/test/test_write_disk_sparse.c \ + libarchive/test/test_write_disk_symlink.c \ + libarchive/test/test_write_disk_times.c \ + libarchive/test/test_write_filter_b64encode.c \ + libarchive/test/test_write_filter_bzip2.c \ + libarchive/test/test_write_filter_compress.c \ + libarchive/test/test_write_filter_gzip.c \ + libarchive/test/test_write_filter_gzip_timestamp.c \ + libarchive/test/test_write_filter_lrzip.c \ + libarchive/test/test_write_filter_lz4.c \ + libarchive/test/test_write_filter_lzip.c \ + libarchive/test/test_write_filter_lzma.c \ + libarchive/test/test_write_filter_lzop.c \ + libarchive/test/test_write_filter_program.c \ + libarchive/test/test_write_filter_uuencode.c \ + libarchive/test/test_write_filter_xz.c \ + libarchive/test/test_write_filter_zstd.c \ + libarchive/test/test_write_format_7zip.c \ + libarchive/test/test_write_format_7zip_empty.c \ + libarchive/test/test_write_format_7zip_large.c \ + libarchive/test/test_write_format_ar.c \ + libarchive/test/test_write_format_cpio.c \ + libarchive/test/test_write_format_cpio_empty.c \ + libarchive/test/test_write_format_cpio_newc.c \ + libarchive/test/test_write_format_cpio_odc.c \ + libarchive/test/test_write_format_gnutar.c \ + libarchive/test/test_write_format_gnutar_filenames.c \ + libarchive/test/test_write_format_iso9660.c \ + libarchive/test/test_write_format_iso9660_boot.c \ + libarchive/test/test_write_format_iso9660_empty.c \ + libarchive/test/test_write_format_iso9660_filename.c \ + libarchive/test/test_write_format_iso9660_zisofs.c \ + libarchive/test/test_write_format_mtree.c \ + libarchive/test/test_write_format_mtree_absolute_path.c \ + libarchive/test/test_write_format_mtree_classic.c \ + libarchive/test/test_write_format_mtree_classic_indent.c\ + libarchive/test/test_write_format_mtree_fflags.c \ + libarchive/test/test_write_format_mtree_no_separator.c \ + libarchive/test/test_write_format_mtree_quoted_filename.c\ + libarchive/test/test_write_format_pax.c \ + libarchive/test/test_write_format_raw.c \ + libarchive/test/test_write_format_raw_b64.c \ + libarchive/test/test_write_format_shar_empty.c \ + libarchive/test/test_write_format_tar.c \ + libarchive/test/test_write_format_tar_empty.c \ + libarchive/test/test_write_format_tar_sparse.c \ + libarchive/test/test_write_format_tar_ustar.c \ + libarchive/test/test_write_format_tar_v7tar.c \ + libarchive/test/test_write_format_warc.c \ + libarchive/test/test_write_format_warc_empty.c \ + libarchive/test/test_write_format_xar.c \ + libarchive/test/test_write_format_xar_empty.c \ + libarchive/test/test_write_format_zip.c \ + libarchive/test/test_write_format_zip_compression_store.c \ + libarchive/test/test_write_format_zip_empty.c \ + libarchive/test/test_write_format_zip_empty_zip64.c \ + libarchive/test/test_write_format_zip_file.c \ + libarchive/test/test_write_format_zip_file_zip64.c \ + libarchive/test/test_write_format_zip_large.c \ + libarchive/test/test_write_format_zip_zip64.c \ + libarchive/test/test_write_open_memory.c \ + libarchive/test/test_write_read_format_zip.c \ + libarchive/test/test_xattr_platform.c \ + libarchive/test/test_zip_filename_encoding.c + +libarchive_test_CPPFLAGS = \ + -I$(top_srcdir)/libarchive \ + -I$(top_srcdir)/libarchive/test \ + -I$(top_srcdir)/test_utils \ + -I$(top_builddir)/libarchive/test \ + -DLIBARCHIVE_STATIC $(PLATFORMCPPFLAGS) + +libarchive_test_LDADD = $(LTLIBICONV) +libarchive_TESTS_ENVIRONMENT = LIBARCHIVE_TEST_FILES=`cd $(top_srcdir);/bin/pwd`/libarchive/test LRZIP=NOCONFIG +libarchive_test_EXTRA_DIST = \ + libarchive/test/list.h \ + libarchive/test/test_acl_pax_posix1e.tar.uu \ + libarchive/test/test_acl_pax_nfs4.tar.uu \ + libarchive/test/test_archive_string_conversion.txt.Z.uu \ + libarchive/test/test_compat_bzip2_1.tbz.uu \ + libarchive/test/test_compat_bzip2_2.tbz.uu \ + libarchive/test/test_compat_cpio_1.cpio.uu \ + libarchive/test/test_compat_gtar_1.tar.uu \ + libarchive/test/test_compat_gtar_2.tar.uu \ + libarchive/test/test_compat_gzip_1.tgz.uu \ + libarchive/test/test_compat_gzip_2.tgz.uu \ + libarchive/test/test_compat_lz4_1.tar.lz4.uu \ + libarchive/test/test_compat_lz4_2.tar.lz4.uu \ + libarchive/test/test_compat_lz4_3.tar.lz4.uu \ + libarchive/test/test_compat_lz4_B4.tar.lz4.uu \ + libarchive/test/test_compat_lz4_B4BD.tar.lz4.uu \ + libarchive/test/test_compat_lz4_B4BDBX.tar.lz4.uu \ + libarchive/test/test_compat_lz4_B5.tar.lz4.uu \ + libarchive/test/test_compat_lz4_B5BD.tar.lz4.uu \ + libarchive/test/test_compat_lz4_B6.tar.lz4.uu \ + libarchive/test/test_compat_lz4_B6BD.tar.lz4.uu \ + libarchive/test/test_compat_lz4_B7.tar.lz4.uu \ + libarchive/test/test_compat_lz4_B7BD.tar.lz4.uu \ + libarchive/test/test_compat_lzip_1.tlz.uu \ + libarchive/test/test_compat_lzip_2.tlz.uu \ + libarchive/test/test_compat_lzma_1.tlz.uu \ + libarchive/test/test_compat_lzma_2.tlz.uu \ + libarchive/test/test_compat_lzma_3.tlz.uu \ + libarchive/test/test_compat_lzop_1.tar.lzo.uu \ + libarchive/test/test_compat_lzop_2.tar.lzo.uu \ + libarchive/test/test_compat_lzop_3.tar.lzo.uu \ + libarchive/test/test_compat_mac-1.tar.Z.uu \ + libarchive/test/test_compat_mac-2.tar.Z.uu \ + libarchive/test/test_compat_perl_archive_tar.tar.uu \ + libarchive/test/test_compat_plexus_archiver_tar.tar.uu \ + libarchive/test/test_compat_solaris_pax_sparse_1.pax.Z.uu \ + libarchive/test/test_compat_solaris_pax_sparse_2.pax.Z.uu \ + libarchive/test/test_compat_solaris_tar_acl.tar.uu \ + libarchive/test/test_compat_star_acl_nfs4.tar.uu \ + libarchive/test/test_compat_star_acl_posix1e.tar.uu \ + libarchive/test/test_compat_tar_hardlink_1.tar.uu \ + libarchive/test/test_compat_uudecode_large.tar.Z.uu \ + libarchive/test/test_compat_xz_1.txz.uu \ + libarchive/test/test_compat_zip_1.zip.uu \ + libarchive/test/test_compat_zip_2.zip.uu \ + libarchive/test/test_compat_zip_3.zip.uu \ + libarchive/test/test_compat_zip_4.zip.uu \ + libarchive/test/test_compat_zip_5.zip.uu \ + libarchive/test/test_compat_zip_6.zip.uu \ + libarchive/test/test_compat_zip_7.xps.uu \ + libarchive/test/test_compat_zip_8.zip.uu \ + libarchive/test/test_compat_zstd_1.tar.zst.uu \ + libarchive/test/test_fuzz.cab.uu \ + libarchive/test/test_fuzz.lzh.uu \ + libarchive/test/test_fuzz_1.iso.Z.uu \ + libarchive/test/test_pax_filename_encoding.tar.uu \ + libarchive/test/test_pax_xattr_header_all.tar.uu \ + libarchive/test/test_pax_xattr_header_libarchive.tar.uu \ + libarchive/test/test_pax_xattr_header_schily.tar.uu \ + libarchive/test/test_rar_multivolume_multiple_files.part1.rar.uu \ + libarchive/test/test_rar_multivolume_multiple_files.part2.rar.uu \ + libarchive/test/test_rar_multivolume_multiple_files.part3.rar.uu \ + libarchive/test/test_rar_multivolume_multiple_files.part4.rar.uu \ + libarchive/test/test_rar_multivolume_multiple_files.part5.rar.uu \ + libarchive/test/test_rar_multivolume_multiple_files.part6.rar.uu \ + libarchive/test/test_rar_multivolume_single_file.part1.rar.uu \ + libarchive/test/test_rar_multivolume_single_file.part2.rar.uu \ + libarchive/test/test_rar_multivolume_single_file.part3.rar.uu \ + libarchive/test/test_rar_multivolume_uncompressed_files.part01.rar.uu \ + libarchive/test/test_rar_multivolume_uncompressed_files.part02.rar.uu \ + libarchive/test/test_rar_multivolume_uncompressed_files.part03.rar.uu \ + libarchive/test/test_rar_multivolume_uncompressed_files.part04.rar.uu \ + libarchive/test/test_rar_multivolume_uncompressed_files.part05.rar.uu \ + libarchive/test/test_rar_multivolume_uncompressed_files.part06.rar.uu \ + libarchive/test/test_rar_multivolume_uncompressed_files.part07.rar.uu \ + libarchive/test/test_rar_multivolume_uncompressed_files.part08.rar.uu \ + libarchive/test/test_rar_multivolume_uncompressed_files.part09.rar.uu \ + libarchive/test/test_rar_multivolume_uncompressed_files.part10.rar.uu \ + libarchive/test/test_read_filter_grzip.tar.grz.uu \ + libarchive/test/test_read_filter_lrzip.tar.lrz.uu \ + libarchive/test/test_read_filter_lzop.tar.lzo.uu \ + libarchive/test/test_read_filter_lzop_multiple_parts.tar.lzo.uu \ + libarchive/test/test_read_format_mtree_crash747.mtree.bz2.uu \ + libarchive/test/test_read_format_mtree_noprint.mtree.uu \ + libarchive/test/test_read_format_7zip_bcj2_bzip2.7z.uu \ + libarchive/test/test_read_format_7zip_bcj2_copy_1.7z.uu \ + libarchive/test/test_read_format_7zip_bcj2_copy_2.7z.uu \ + libarchive/test/test_read_format_7zip_bcj2_copy_lzma.7z.uu \ + libarchive/test/test_read_format_7zip_bcj2_deflate.7z.uu \ + libarchive/test/test_read_format_7zip_bcj2_lzma1_1.7z.uu \ + libarchive/test/test_read_format_7zip_bcj2_lzma1_2.7z.uu \ + libarchive/test/test_read_format_7zip_bcj2_lzma2_1.7z.uu \ + libarchive/test/test_read_format_7zip_bcj2_lzma2_2.7z.uu \ + libarchive/test/test_read_format_7zip_bcj_bzip2.7z.uu \ + libarchive/test/test_read_format_7zip_bcj_copy.7z.uu \ + libarchive/test/test_read_format_7zip_bcj_deflate.7z.uu \ + libarchive/test/test_read_format_7zip_bcj_lzma1.7z.uu \ + libarchive/test/test_read_format_7zip_bcj_lzma2.7z.uu \ + libarchive/test/test_read_format_7zip_bzip2.7z.uu \ + libarchive/test/test_read_format_7zip_copy.7z.uu \ + libarchive/test/test_read_format_7zip_copy_2.7z.uu \ + libarchive/test/test_read_format_7zip_deflate.7z.uu \ + libarchive/test/test_read_format_7zip_delta_lzma1.7z.uu \ + libarchive/test/test_read_format_7zip_delta4_lzma1.7z.uu \ + libarchive/test/test_read_format_7zip_delta_lzma2.7z.uu \ + libarchive/test/test_read_format_7zip_delta4_lzma2.7z.uu \ + libarchive/test/test_read_format_7zip_empty_archive.7z.uu \ + libarchive/test/test_read_format_7zip_empty_file.7z.uu \ + libarchive/test/test_read_format_7zip_encryption.7z.uu \ + libarchive/test/test_read_format_7zip_encryption_header.7z.uu \ + libarchive/test/test_read_format_7zip_encryption_partially.7z.uu \ + libarchive/test/test_read_format_7zip_lzma1.7z.uu \ + libarchive/test/test_read_format_7zip_lzma1_2.7z.uu \ + libarchive/test/test_read_format_7zip_lzma1_lzma2.7z.uu \ + libarchive/test/test_read_format_7zip_lzma2.7z.uu \ + libarchive/test/test_read_format_7zip_malformed.7z.uu \ + libarchive/test/test_read_format_7zip_malformed2.7z.uu \ + libarchive/test/test_read_format_7zip_packinfo_digests.7z.uu \ + libarchive/test/test_read_format_7zip_ppmd.7z.uu \ + libarchive/test/test_read_format_7zip_symbolic_name.7z.uu \ + libarchive/test/test_read_format_ar.ar.uu \ + libarchive/test/test_read_format_cab_1.cab.uu \ + libarchive/test/test_read_format_cab_2.cab.uu \ + libarchive/test/test_read_format_cab_3.cab.uu \ + libarchive/test/test_read_format_cab_filename_cp932.cab.uu \ + libarchive/test/test_read_format_cpio_bin_be.cpio.uu \ + libarchive/test/test_read_format_cpio_bin_le.cpio.uu \ + libarchive/test/test_read_format_cpio_filename_cp866.cpio.uu \ + libarchive/test/test_read_format_cpio_filename_eucjp.cpio.uu \ + libarchive/test/test_read_format_cpio_filename_koi8r.cpio.uu \ + libarchive/test/test_read_format_cpio_filename_utf8_jp.cpio.uu \ + libarchive/test/test_read_format_cpio_filename_utf8_ru.cpio.uu \ + libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.rpm.uu \ + libarchive/test/test_read_format_cpio_svr4_gzip_rpm.rpm.uu \ + libarchive/test/test_read_format_gtar_filename_cp866.tar.Z.uu \ + libarchive/test/test_read_format_gtar_filename_eucjp.tar.Z.uu \ + libarchive/test/test_read_format_gtar_filename_koi8r.tar.Z.uu \ + libarchive/test/test_read_format_gtar_sparse_1_13.tar.uu \ + libarchive/test/test_read_format_gtar_sparse_1_17.tar.uu \ + libarchive/test/test_read_format_gtar_sparse_1_17_posix00.tar.uu \ + libarchive/test/test_read_format_gtar_sparse_1_17_posix01.tar.uu \ + libarchive/test/test_read_format_gtar_sparse_1_17_posix10.tar.uu \ + libarchive/test/test_read_format_gtar_sparse_1_17_posix10_modified.tar.uu \ + libarchive/test/test_read_format_gtar_sparse_skip_entry.tar.Z.uu \ + libarchive/test/test_read_format_iso.iso.Z.uu \ + libarchive/test/test_read_format_iso_2.iso.Z.uu \ + libarchive/test/test_read_format_iso_joliet.iso.Z.uu \ + libarchive/test/test_read_format_iso_joliet_by_nero.iso.Z.uu \ + libarchive/test/test_read_format_iso_joliet_long.iso.Z.uu \ + libarchive/test/test_read_format_iso_joliet_rockridge.iso.Z.uu \ + libarchive/test/test_read_format_iso_multi_extent.iso.Z.uu \ + libarchive/test/test_read_format_iso_rockridge.iso.Z.uu \ + libarchive/test/test_read_format_iso_rockridge_ce.iso.Z.uu \ + libarchive/test/test_read_format_iso_rockridge_new.iso.Z.uu \ + libarchive/test/test_read_format_iso_rockridge_rr_moved.iso.Z.uu \ + libarchive/test/test_read_format_iso_xorriso.iso.Z.uu \ + libarchive/test/test_read_format_iso_zisofs.iso.Z.uu \ + libarchive/test/test_read_format_lha_bugfix_0.lzh.uu \ + libarchive/test/test_read_format_lha_filename_cp932.lzh.uu \ + libarchive/test/test_read_format_lha_filename_utf16.lzh.uu \ + libarchive/test/test_read_format_lha_header0.lzh.uu \ + libarchive/test/test_read_format_lha_header1.lzh.uu \ + libarchive/test/test_read_format_lha_header2.lzh.uu \ + libarchive/test/test_read_format_lha_header3.lzh.uu \ + libarchive/test/test_read_format_lha_lh0.lzh.uu \ + libarchive/test/test_read_format_lha_lh6.lzh.uu \ + libarchive/test/test_read_format_lha_lh7.lzh.uu \ + libarchive/test/test_read_format_lha_withjunk.lzh.uu \ + libarchive/test/test_read_format_mtree.mtree.uu \ + libarchive/test/test_read_format_mtree_nomagic.mtree.uu \ + libarchive/test/test_read_format_mtree_nomagic2.mtree.uu \ + libarchive/test/test_read_format_mtree_nomagic3.mtree.uu \ + libarchive/test/test_read_format_rar.rar.uu \ + libarchive/test/test_read_format_rar_binary_data.rar.uu \ + libarchive/test/test_read_format_rar_compress_best.rar.uu \ + libarchive/test/test_read_format_rar_compress_normal.rar.uu \ + libarchive/test/test_read_format_rar_encryption_data.rar.uu \ + libarchive/test/test_read_format_rar_encryption_header.rar.uu \ + libarchive/test/test_read_format_rar_encryption_partially.rar.uu \ + libarchive/test/test_read_format_rar_invalid1.rar.uu \ + libarchive/test/test_read_format_rar_multi_lzss_blocks.rar.uu \ + libarchive/test/test_read_format_rar_multivolume.part0001.rar.uu \ + libarchive/test/test_read_format_rar_multivolume.part0002.rar.uu \ + libarchive/test/test_read_format_rar_multivolume.part0003.rar.uu \ + libarchive/test/test_read_format_rar_multivolume.part0004.rar.uu \ + libarchive/test/test_read_format_rar_noeof.rar.uu \ + libarchive/test/test_read_format_rar_ppmd_lzss_conversion.rar.uu \ + libarchive/test/test_read_format_rar_ppmd_use_after_free.rar.uu \ + libarchive/test/test_read_format_rar_ppmd_use_after_free2.rar.uu \ + libarchive/test/test_read_format_rar_sfx.exe.uu \ + libarchive/test/test_read_format_rar_subblock.rar.uu \ + libarchive/test/test_read_format_rar_unicode.rar.uu \ + libarchive/test/test_read_format_rar_windows.rar.uu \ + libarchive/test/test_read_format_rar5_arm.rar.uu \ + libarchive/test/test_read_format_rar5_blake2.rar.uu \ + libarchive/test/test_read_format_rar5_compressed.rar.uu \ + libarchive/test/test_read_format_rar5_different_window_size.rar.uu \ + libarchive/test/test_read_format_rar5_different_solid_window_size.rar.uu \ + libarchive/test/test_read_format_rar5_distance_overflow.rar.uu \ + libarchive/test/test_read_format_rar5_extra_field_version.rar.uu \ + libarchive/test/test_read_format_rar5_fileattr.rar.uu \ + libarchive/test/test_read_format_rar5_hardlink.rar.uu \ + libarchive/test/test_read_format_rar5_invalid_dict_reference.rar.uu \ + libarchive/test/test_read_format_rar5_leftshift1.rar.uu \ + libarchive/test/test_read_format_rar5_leftshift2.rar.uu \ + libarchive/test/test_read_format_rar5_multiarchive.part01.rar.uu \ + libarchive/test/test_read_format_rar5_multiarchive.part02.rar.uu \ + libarchive/test/test_read_format_rar5_multiarchive.part03.rar.uu \ + libarchive/test/test_read_format_rar5_multiarchive.part04.rar.uu \ + libarchive/test/test_read_format_rar5_multiarchive.part05.rar.uu \ + libarchive/test/test_read_format_rar5_multiarchive.part06.rar.uu \ + libarchive/test/test_read_format_rar5_multiarchive.part07.rar.uu \ + libarchive/test/test_read_format_rar5_multiarchive.part08.rar.uu \ + libarchive/test/test_read_format_rar5_multiarchive_solid.part01.rar.uu \ + libarchive/test/test_read_format_rar5_multiarchive_solid.part02.rar.uu \ + libarchive/test/test_read_format_rar5_multiarchive_solid.part03.rar.uu \ + libarchive/test/test_read_format_rar5_multiarchive_solid.part04.rar.uu \ + libarchive/test/test_read_format_rar5_multiple_files.rar.uu \ + libarchive/test/test_read_format_rar5_multiple_files_solid.rar.uu \ + libarchive/test/test_read_format_rar5_nonempty_dir_stream.rar.uu \ + libarchive/test/test_read_format_rar5_owner.rar.uu \ + libarchive/test/test_read_format_rar5_readtables_overflow.rar.uu \ + libarchive/test/test_read_format_rar5_solid.rar.uu \ + libarchive/test/test_read_format_rar5_stored.rar.uu \ + libarchive/test/test_read_format_rar5_stored_manyfiles.rar.uu \ + libarchive/test/test_read_format_rar5_symlink.rar.uu \ + libarchive/test/test_read_format_rar5_truncated_huff.rar.uu \ + libarchive/test/test_read_format_rar5_win32.rar.uu \ + libarchive/test/test_read_format_rar5_arm_filter_on_window_boundary.rar.uu \ + libarchive/test/test_read_format_rar5_different_winsize_on_merge.rar.uu \ + libarchive/test/test_read_format_rar5_block_size_is_too_small.rar.uu \ + libarchive/test/test_read_format_raw.bufr.uu \ + libarchive/test/test_read_format_raw.data.gz.uu \ + libarchive/test/test_read_format_raw.data.Z.uu \ + libarchive/test/test_read_format_raw.data.uu \ + libarchive/test/test_read_format_tar_concatenated.tar.uu \ + libarchive/test/test_read_format_tar_empty_filename.tar.uu \ + libarchive/test/test_read_format_tar_empty_with_gnulabel.tar.uu \ + libarchive/test/test_read_format_tar_empty_pax.tar.Z.uu \ + libarchive/test/test_read_format_tar_filename_koi8r.tar.Z.uu \ + libarchive/test/test_read_format_ustar_filename_cp866.tar.Z.uu \ + libarchive/test/test_read_format_ustar_filename_eucjp.tar.Z.uu \ + libarchive/test/test_read_format_ustar_filename_koi8r.tar.Z.uu \ + libarchive/test/test_read_format_warc.warc.uu \ + libarchive/test/test_read_format_zip.zip.uu \ + libarchive/test/test_read_format_zip_7075_utf8_paths.zip.uu \ + libarchive/test/test_read_format_zip_bz2_hang.zip.uu \ + libarchive/test/test_read_format_zip_bzip2.zipx.uu \ + libarchive/test/test_read_format_zip_bzip2_multi.zipx.uu \ + libarchive/test/test_read_format_zip_comment_stored_1.zip.uu \ + libarchive/test/test_read_format_zip_comment_stored_2.zip.uu \ + libarchive/test/test_read_format_zip_encryption_data.zip.uu \ + libarchive/test/test_read_format_zip_encryption_header.zip.uu \ + libarchive/test/test_read_format_zip_encryption_partially.zip.uu \ + libarchive/test/test_read_format_zip_extra_padding.zip.uu \ + libarchive/test/test_read_format_zip_filename_cp866.zip.uu \ + libarchive/test/test_read_format_zip_filename_cp932.zip.uu \ + libarchive/test/test_read_format_zip_filename_koi8r.zip.uu \ + libarchive/test/test_read_format_zip_filename_utf8_jp.zip.uu \ + libarchive/test/test_read_format_zip_filename_utf8_ru.zip.uu \ + libarchive/test/test_read_format_zip_filename_utf8_ru2.zip.uu \ + libarchive/test/test_read_format_zip_high_compression.zip.uu \ + libarchive/test/test_read_format_zip_length_at_end.zip.uu \ + libarchive/test/test_read_format_zip_lzma.zipx.uu \ + libarchive/test/test_read_format_zip_lzma_alone_leak.zipx.uu \ + libarchive/test/test_read_format_zip_lzma_multi.zipx.uu \ + libarchive/test/test_read_format_zip_jar.jar.uu \ + libarchive/test/test_read_format_zip_mac_metadata.zip.uu \ + libarchive/test/test_read_format_zip_malformed1.zip.uu \ + libarchive/test/test_read_format_zip_msdos.zip.uu \ + libarchive/test/test_read_format_zip_nested.zip.uu \ + libarchive/test/test_read_format_zip_nofiletype.zip.uu \ + libarchive/test/test_read_format_zip_padded1.zip.uu \ + libarchive/test/test_read_format_zip_padded2.zip.uu \ + libarchive/test/test_read_format_zip_padded3.zip.uu \ + libarchive/test/test_read_format_zip_ppmd8.zipx.uu \ + libarchive/test/test_read_format_zip_ppmd8_crash_1.zipx.uu \ + libarchive/test/test_read_format_zip_ppmd8_crash_2.zipx.uu \ + libarchive/test/test_read_format_zip_ppmd8_multi.zipx.uu \ + libarchive/test/test_read_format_zip_sfx.uu \ + libarchive/test/test_read_format_zip_symlink.zip.uu \ + libarchive/test/test_read_format_zip_traditional_encryption_data.zip.uu \ + libarchive/test/test_read_format_zip_ux.zip.uu \ + libarchive/test/test_read_format_zip_winzip_aes128.zip.uu \ + libarchive/test/test_read_format_zip_winzip_aes256.zip.uu \ + libarchive/test/test_read_format_zip_winzip_aes256_large.zip.uu \ + libarchive/test/test_read_format_zip_winzip_aes256_stored.zip.uu \ + libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.zip.uu \ + libarchive/test/test_read_format_zip_xz_multi.zipx.uu \ + libarchive/test/test_read_format_zip_zip64a.zip.uu \ + libarchive/test/test_read_format_zip_zip64b.zip.uu \ + libarchive/test/test_read_large_splitted_rar_aa.uu \ + libarchive/test/test_read_large_splitted_rar_ab.uu \ + libarchive/test/test_read_large_splitted_rar_ac.uu \ + libarchive/test/test_read_large_splitted_rar_ad.uu \ + libarchive/test/test_read_large_splitted_rar_ae.uu \ + libarchive/test/test_read_pax_schily_xattr.tar.uu \ + libarchive/test/test_read_splitted_rar_aa.uu \ + libarchive/test/test_read_splitted_rar_ab.uu \ + libarchive/test/test_read_splitted_rar_ac.uu \ + libarchive/test/test_read_splitted_rar_ad.uu \ + libarchive/test/test_read_too_many_filters.gz.uu \ + libarchive/test/test_splitted_rar_seek_support_aa.uu \ + libarchive/test/test_splitted_rar_seek_support_ab.uu \ + libarchive/test/test_splitted_rar_seek_support_ac.uu \ + libarchive/test/test_write_disk_appledouble.cpio.gz.uu \ + libarchive/test/test_write_disk_hfs_compression.tgz.uu \ + libarchive/test/test_write_disk_mac_metadata.tar.gz.uu \ + libarchive/test/test_write_disk_no_hfs_compression.tgz.uu \ + libarchive/test/CMakeLists.txt \ + libarchive/test/README + + +# +# Common code for libarchive frontends (cpio, tar) +# +libarchive_fe_la_SOURCES = \ + libarchive_fe/err.c \ + libarchive_fe/err.h \ + libarchive_fe/lafe_platform.h \ + libarchive_fe/line_reader.c \ + libarchive_fe/line_reader.h \ + libarchive_fe/passphrase.c \ + libarchive_fe/passphrase.h + +libarchive_fe_la_CPPFLAGS = -I$(top_srcdir)/libarchive +# +# +# bsdtar source, docs, etc. +# +# +bsdtar_SOURCES = tar/bsdtar.c tar/bsdtar.h tar/bsdtar_platform.h \ + tar/cmdline.c tar/creation_set.c tar/read.c tar/subst.c \ + tar/util.c tar/write.c $(am__append_7) +bsdtar_DEPENDENCIES = libarchive.la libarchive_fe.la +@STATIC_BSDTAR_FALSE@bsdtar_ldstatic = +@STATIC_BSDTAR_TRUE@bsdtar_ldstatic = -static +@STATIC_BSDTAR_FALSE@bsdtar_ccstatic = +@STATIC_BSDTAR_TRUE@bsdtar_ccstatic = -DLIBARCHIVE_STATIC +bsdtar_LDADD = libarchive.la libarchive_fe.la $(LTLIBICONV) +bsdtar_CPPFLAGS = -I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe $(bsdtar_ccstatic) $(PLATFORMCPPFLAGS) +bsdtar_LDFLAGS = $(bsdtar_ldstatic) +bsdtar_EXTRA_DIST = \ + tar/bsdtar.1 \ + tar/bsdtar_windows.h \ + tar/bsdtar_windows.c \ + tar/CMakeLists.txt \ + tar/config_freebsd.h + +@BUILD_BSDTAR_FALSE@bsdtar_man_MANS = +@BUILD_BSDTAR_TRUE@bsdtar_man_MANS = tar/bsdtar.1 +@BUILD_BSDTAR_FALSE@bsdtar_programs = +@BUILD_BSDTAR_TRUE@bsdtar_programs = bsdtar + +# +# bsdtar_test +# +bsdtar_test_SOURCES = \ + $(test_utils_SOURCES) \ + tar/test/test.h \ + tar/test/test_0.c \ + tar/test/test_basic.c \ + tar/test/test_copy.c \ + tar/test/test_empty_mtree.c \ + tar/test/test_extract_tar_Z.c \ + tar/test/test_extract_tar_bz2.c \ + tar/test/test_extract_tar_grz.c \ + tar/test/test_extract_tar_gz.c \ + tar/test/test_extract_tar_lrz.c \ + tar/test/test_extract_tar_lz.c \ + tar/test/test_extract_tar_lz4.c \ + tar/test/test_extract_tar_lzma.c \ + tar/test/test_extract_tar_lzo.c \ + tar/test/test_extract_tar_xz.c \ + tar/test/test_extract_tar_zstd.c \ + tar/test/test_format_newc.c \ + tar/test/test_help.c \ + tar/test/test_leading_slash.c \ + tar/test/test_missing_file.c \ + tar/test/test_option_C_mtree.c \ + tar/test/test_option_C_upper.c \ + tar/test/test_option_H_upper.c \ + tar/test/test_option_L_upper.c \ + tar/test/test_option_O_upper.c \ + tar/test/test_option_T_upper.c \ + tar/test/test_option_U_upper.c \ + tar/test/test_option_X_upper.c \ + tar/test/test_option_acls.c \ + tar/test/test_option_a.c \ + tar/test/test_option_b.c \ + tar/test/test_option_b64encode.c \ + tar/test/test_option_exclude.c \ + tar/test/test_option_exclude_vcs.c \ + tar/test/test_option_fflags.c \ + tar/test/test_option_gid_gname.c \ + tar/test/test_option_grzip.c \ + tar/test/test_option_j.c \ + tar/test/test_option_k.c \ + tar/test/test_option_keep_newer_files.c \ + tar/test/test_option_lrzip.c \ + tar/test/test_option_lz4.c \ + tar/test/test_option_lzma.c \ + tar/test/test_option_lzop.c \ + tar/test/test_option_n.c \ + tar/test/test_option_newer_than.c \ + tar/test/test_option_nodump.c \ + tar/test/test_option_older_than.c \ + tar/test/test_option_passphrase.c \ + tar/test/test_option_q.c \ + tar/test/test_option_r.c \ + tar/test/test_option_s.c \ + tar/test/test_option_safe_writes.c \ + tar/test/test_option_uid_uname.c \ + tar/test/test_option_uuencode.c \ + tar/test/test_option_xattrs.c \ + tar/test/test_option_xz.c \ + tar/test/test_option_z.c \ + tar/test/test_option_zstd.c \ + tar/test/test_patterns.c \ + tar/test/test_print_longpath.c \ + tar/test/test_stdio.c \ + tar/test/test_strip_components.c \ + tar/test/test_symlink_dir.c \ + tar/test/test_version.c \ + tar/test/test_windows.c + +bsdtar_test_CPPFLAGS = \ + -I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe \ + -I$(top_srcdir)/test_utils \ + -I$(top_srcdir)/tar -I$(top_srcdir)/tar/test \ + -I$(top_builddir)/tar/test \ + $(PLATFORMCPPFLAGS) + +@BUILD_BSDTAR_FALSE@bsdtar_test_programs = +@BUILD_BSDTAR_TRUE@bsdtar_test_programs = bsdtar_test +@BUILD_BSDTAR_FALSE@bsdtar_TESTS_ENVIRONMENT = +@BUILD_BSDTAR_TRUE@bsdtar_TESTS_ENVIRONMENT = BSDTAR=`cd $(top_builddir);/bin/pwd`/bsdtar$(EXEEXT) BSDTAR_TEST_FILES=`cd $(top_srcdir);/bin/pwd`/tar/test +bsdtar_test_EXTRA_DIST = \ + tar/test/list.h \ + tar/test/test_extract.tar.Z.uu \ + tar/test/test_extract.tar.bz2.uu \ + tar/test/test_extract.tar.grz.uu \ + tar/test/test_extract.tar.gz.uu \ + tar/test/test_extract.tar.lrz.uu \ + tar/test/test_extract.tar.lz.uu \ + tar/test/test_extract.tar.lz4.uu \ + tar/test/test_extract.tar.zst.uu \ + tar/test/test_extract.tar.lzma.uu \ + tar/test/test_extract.tar.lzo.uu \ + tar/test/test_extract.tar.xz.uu \ + tar/test/test_leading_slash.tar.uu \ + tar/test/test_option_keep_newer_files.tar.Z.uu \ + tar/test/test_option_passphrase.zip.uu \ + tar/test/test_option_s.tar.Z.uu \ + tar/test/test_patterns_2.tar.uu \ + tar/test/test_patterns_3.tar.uu \ + tar/test/test_patterns_4.tar.uu \ + tar/test/test_print_longpath.tar.Z.uu \ + tar/test/CMakeLists.txt + + +# +# +# bsdcpio source, docs, etc. +# +# +bsdcpio_SOURCES = cpio/cmdline.c cpio/cpio.c cpio/cpio.h \ + cpio/cpio_platform.h $(am__append_8) +bsdcpio_DEPENDENCIES = libarchive.la libarchive_fe.la +@STATIC_BSDCPIO_FALSE@bsdcpio_ldstatic = +@STATIC_BSDCPIO_TRUE@bsdcpio_ldstatic = -static +@STATIC_BSDCPIO_FALSE@bsdcpio_ccstatic = +@STATIC_BSDCPIO_TRUE@bsdcpio_ccstatic = -DLIBARCHIVE_STATIC +bsdcpio_LDADD = libarchive_fe.la libarchive.la $(LTLIBICONV) +bsdcpio_CPPFLAGS = -I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe $(bsdcpio_ccstatic) $(PLATFORMCPPFLAGS) +bsdcpio_LDFLAGS = $(bsdcpio_ldstatic) +bsdcpio_EXTRA_DIST = \ + cpio/bsdcpio.1 \ + cpio/cpio_windows.h \ + cpio/cpio_windows.c \ + cpio/CMakeLists.txt \ + cpio/config_freebsd.h + +@BUILD_BSDCPIO_FALSE@bsdcpio_man_MANS = + +# Manpages to install +@BUILD_BSDCPIO_TRUE@bsdcpio_man_MANS = cpio/bsdcpio.1 +@BUILD_BSDCPIO_FALSE@bsdcpio_programs = +@BUILD_BSDCPIO_TRUE@bsdcpio_programs = bsdcpio + +# +# bsdcpio_test +# +bsdcpio_test_SOURCES = \ + $(test_utils_SOURCES) \ + cpio/cmdline.c \ + cpio/test/test.h \ + cpio/test/test_0.c \ + cpio/test/test_basic.c \ + cpio/test/test_cmdline.c \ + cpio/test/test_extract_cpio_Z.c \ + cpio/test/test_extract_cpio_bz2.c \ + cpio/test/test_extract_cpio_grz.c \ + cpio/test/test_extract_cpio_gz.c \ + cpio/test/test_extract_cpio_lrz.c \ + cpio/test/test_extract_cpio_lz.c \ + cpio/test/test_extract_cpio_lz4.c \ + cpio/test/test_extract_cpio_lzma.c \ + cpio/test/test_extract_cpio_lzo.c \ + cpio/test/test_extract_cpio_xz.c \ + cpio/test/test_extract_cpio_zstd.c \ + cpio/test/test_format_newc.c \ + cpio/test/test_gcpio_compat.c \ + cpio/test/test_missing_file.c \ + cpio/test/test_option_0.c \ + cpio/test/test_option_B_upper.c \ + cpio/test/test_option_C_upper.c \ + cpio/test/test_option_J_upper.c \ + cpio/test/test_option_L_upper.c \ + cpio/test/test_option_Z_upper.c \ + cpio/test/test_option_a.c \ + cpio/test/test_option_b64encode.c \ + cpio/test/test_option_c.c \ + cpio/test/test_option_d.c \ + cpio/test/test_option_f.c \ + cpio/test/test_option_grzip.c \ + cpio/test/test_option_help.c \ + cpio/test/test_option_l.c \ + cpio/test/test_option_lrzip.c \ + cpio/test/test_option_lz4.c \ + cpio/test/test_option_lzma.c \ + cpio/test/test_option_lzop.c \ + cpio/test/test_option_m.c \ + cpio/test/test_option_passphrase.c \ + cpio/test/test_option_t.c \ + cpio/test/test_option_u.c \ + cpio/test/test_option_uuencode.c \ + cpio/test/test_option_version.c \ + cpio/test/test_option_xz.c \ + cpio/test/test_option_y.c \ + cpio/test/test_option_z.c \ + cpio/test/test_option_zstd.c \ + cpio/test/test_owner_parse.c \ + cpio/test/test_passthrough_dotdot.c \ + cpio/test/test_passthrough_reverse.c + +bsdcpio_test_CPPFLAGS = \ + -I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe \ + -I$(top_srcdir)/test_utils \ + -I$(top_srcdir)/cpio -I$(top_srcdir)/cpio/test \ + -I$(top_builddir)/cpio/test \ + $(PLATFORMCPPFLAGS) + +bsdcpio_test_LDADD = libarchive_fe.la +@BUILD_BSDCPIO_FALSE@bsdcpio_test_programs = +@BUILD_BSDCPIO_TRUE@bsdcpio_test_programs = bsdcpio_test +@BUILD_BSDCPIO_FALSE@bsdcpio_TESTS_ENVIRONMENT = +@BUILD_BSDCPIO_TRUE@bsdcpio_TESTS_ENVIRONMENT = BSDCPIO=`cd $(top_builddir);/bin/pwd`/bsdcpio$(EXEEXT) BSDCPIO_TEST_FILES=`cd $(top_srcdir);/bin/pwd`/cpio/test +bsdcpio_test_EXTRA_DIST = \ + cpio/test/list.h \ + cpio/test/test_extract.cpio.Z.uu \ + cpio/test/test_extract.cpio.bz2.uu \ + cpio/test/test_extract.cpio.grz.uu \ + cpio/test/test_extract.cpio.gz.uu \ + cpio/test/test_extract.cpio.lrz.uu \ + cpio/test/test_extract.cpio.lz.uu \ + cpio/test/test_extract.cpio.lz4.uu \ + cpio/test/test_extract.cpio.zst.uu \ + cpio/test/test_extract.cpio.lzma.uu \ + cpio/test/test_extract.cpio.lzo.uu \ + cpio/test/test_extract.cpio.xz.uu \ + cpio/test/test_gcpio_compat_ref.bin.uu \ + cpio/test/test_gcpio_compat_ref.crc.uu \ + cpio/test/test_gcpio_compat_ref.newc.uu \ + cpio/test/test_gcpio_compat_ref.ustar.uu \ + cpio/test/test_gcpio_compat_ref_nosym.bin.uu \ + cpio/test/test_gcpio_compat_ref_nosym.crc.uu \ + cpio/test/test_gcpio_compat_ref_nosym.newc.uu \ + cpio/test/test_gcpio_compat_ref_nosym.ustar.uu \ + cpio/test/test_option_f.cpio.uu \ + cpio/test/test_option_m.cpio.uu \ + cpio/test/test_option_passphrase.zip.uu \ + cpio/test/test_option_t.cpio.uu \ + cpio/test/test_option_t.stdout.uu \ + cpio/test/test_option_tv.stdout.uu \ + cpio/test/CMakeLists.txt + + +# +# +# bsdcat source, docs, etc. +# +# +bsdcat_SOURCES = cat/bsdcat.c cat/bsdcat.h cat/bsdcat_platform.h \ + cat/cmdline.c $(am__append_9) +bsdcat_DEPENDENCIES = libarchive.la libarchive_fe.la +@STATIC_BSDCAT_FALSE@bsdcat_ldstatic = +@STATIC_BSDCAT_TRUE@bsdcat_ldstatic = -static +@STATIC_BSDCAT_FALSE@bsdcat_ccstatic = +@STATIC_BSDCAT_TRUE@bsdcat_ccstatic = -DLIBARCHIVE_STATIC +bsdcat_LDADD = libarchive_fe.la libarchive.la $(LTLIBICONV) +bsdcat_CPPFLAGS = -I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe $(bsdcat_ccstatic) $(PLATFORMCPPFLAGS) +bsdcat_LDFLAGS = $(bsdcat_ldstatic) +bsdcat_EXTRA_DIST = \ + cat/bsdcat.1 \ + cat/CMakeLists.txt + +@BUILD_BSDCAT_FALSE@bsdcat_man_MANS = + +# Manpages to install +@BUILD_BSDCAT_TRUE@bsdcat_man_MANS = cat/bsdcat.1 +@BUILD_BSDCAT_FALSE@bsdcat_programs = +@BUILD_BSDCAT_TRUE@bsdcat_programs = bsdcat + +# +# bsdcat_test +# +bsdcat_test_SOURCES = \ + $(test_utils_SOURCES) \ + cat/test/test.h \ + cat/test/test_0.c \ + cat/test/test_empty_gz.c \ + cat/test/test_empty_lz4.c \ + cat/test/test_empty_xz.c \ + cat/test/test_empty_zstd.c \ + cat/test/test_error.c \ + cat/test/test_error_mixed.c \ + cat/test/test_expand_Z.c \ + cat/test/test_expand_bz2.c \ + cat/test/test_expand_gz.c \ + cat/test/test_expand_lz4.c \ + cat/test/test_expand_mixed.c \ + cat/test/test_expand_plain.c \ + cat/test/test_expand_xz.c \ + cat/test/test_expand_zstd.c \ + cat/test/test_help.c \ + cat/test/test_stdin.c \ + cat/test/test_version.c + +bsdcat_test_CPPFLAGS = \ + -I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe \ + -I$(top_srcdir)/test_utils \ + -I$(top_srcdir)/cat -I$(top_srcdir)/cat/test \ + -I$(top_builddir)/cat/test \ + $(PLATFORMCPPFLAGS) + +bsdcat_test_LDADD = libarchive_fe.la +@BUILD_BSDCAT_FALSE@bsdcat_test_programs = +@BUILD_BSDCAT_TRUE@bsdcat_test_programs = bsdcat_test +@BUILD_BSDCAT_FALSE@bsdcat_TESTS_ENVIRONMENT = +@BUILD_BSDCAT_TRUE@bsdcat_TESTS_ENVIRONMENT = BSDCAT=`cd $(top_builddir);/bin/pwd`/bsdcat$(EXEEXT) BSDCAT_TEST_FILES=`cd $(top_srcdir);/bin/pwd`/cat/test +bsdcat_test_EXTRA_DIST = \ + cat/test/list.h \ + cat/test/test_empty.gz.uu \ + cat/test/test_empty.lz4.uu \ + cat/test/test_empty.zst.uu \ + cat/test/test_empty.xz.uu \ + cat/test/test_expand.Z.uu \ + cat/test/test_expand.bz2.uu \ + cat/test/test_expand.gz.uu \ + cat/test/test_expand.lz4.uu \ + cat/test/test_expand.zst.uu \ + cat/test/test_expand.plain.uu \ + cat/test/test_expand.xz.uu \ + cat/test/CMakeLists.txt + +all: $(BUILT_SOURCES) config.h + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @test -f $@ || rm -f stamp-h1 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 +build/pkgconfig/libarchive.pc: $(top_builddir)/config.status $(top_srcdir)/build/pkgconfig/libarchive.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libarchive/$(am__dirstamp): + @$(MKDIR_P) libarchive + @: > libarchive/$(am__dirstamp) +libarchive/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) libarchive/$(DEPDIR) + @: > libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_acl.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_check_magic.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_cmdline.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_cryptor.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_digest.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_entry.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_entry_copy_stat.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_entry_link_resolver.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_entry_sparse.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_entry_stat.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_entry_strmode.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_entry_xattr.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_getdate.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_hmac.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_match.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_options.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_pack_dev.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_pathmatch.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_ppmd7.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_ppmd8.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_random.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_rb.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_add_passphrase.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_append_filter.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_data_into_fd.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_disk_entry_from_file.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_disk_posix.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_disk_set_standard_lookup.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_extract.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_extract2.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_open_fd.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_open_file.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_open_filename.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_open_memory.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_set_format.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_set_options.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_filter_all.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_filter_bzip2.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_filter_compress.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_filter_grzip.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_filter_gzip.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_filter_lrzip.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_filter_lz4.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_filter_lzop.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_filter_none.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_filter_program.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_filter_rpm.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_filter_uu.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_filter_xz.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_filter_zstd.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_format_7zip.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_format_all.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_format_ar.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_format_by_code.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_format_cab.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_format_cpio.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_format_empty.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_format_iso9660.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_format_lha.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_format_mtree.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_format_rar.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_format_rar5.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_format_raw.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_format_tar.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_format_warc.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_format_xar.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_support_format_zip.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_string.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_string_sprintf.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_util.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_version_details.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_virtual.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_disk_posix.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_disk_set_standard_lookup.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_open_fd.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_open_file.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_open_filename.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_open_memory.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_add_filter.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_add_filter_b64encode.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_add_filter_by_name.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_add_filter_bzip2.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_add_filter_compress.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_add_filter_grzip.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_add_filter_gzip.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_add_filter_lrzip.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_add_filter_lz4.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_add_filter_lzop.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_add_filter_none.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_add_filter_program.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_add_filter_uuencode.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_add_filter_xz.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_add_filter_zstd.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_set_format.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_set_format_7zip.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_set_format_ar.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_set_format_by_name.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_set_format_cpio.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_set_format_cpio_newc.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_set_format_filter_by_ext.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_set_format_iso9660.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_set_format_mtree.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_set_format_pax.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_set_format_raw.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_set_format_shar.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_set_format_ustar.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_set_format_v7tar.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_set_format_gnutar.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_set_format_warc.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_set_format_xar.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_set_format_zip.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_set_options.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_set_passphrase.lo: \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/filter_fork_posix.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/xxhash.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_entry_copy_bhfi.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_read_disk_windows.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_windows.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_write_disk_windows.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/filter_fork_windows.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_blake2s_ref.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_blake2sp_ref.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_disk_acl_linux.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_disk_acl_sunos.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_disk_acl_darwin.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/archive_disk_acl_freebsd.lo: libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) + +libarchive.la: $(libarchive_la_OBJECTS) $(libarchive_la_DEPENDENCIES) $(EXTRA_libarchive_la_DEPENDENCIES) + $(AM_V_CCLD)$(libarchive_la_LINK) -rpath $(libdir) $(libarchive_la_OBJECTS) $(libarchive_la_LIBADD) $(LIBS) +libarchive_fe/$(am__dirstamp): + @$(MKDIR_P) libarchive_fe + @: > libarchive_fe/$(am__dirstamp) +libarchive_fe/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) libarchive_fe/$(DEPDIR) + @: > libarchive_fe/$(DEPDIR)/$(am__dirstamp) +libarchive_fe/libarchive_fe_la-err.lo: libarchive_fe/$(am__dirstamp) \ + libarchive_fe/$(DEPDIR)/$(am__dirstamp) +libarchive_fe/libarchive_fe_la-line_reader.lo: \ + libarchive_fe/$(am__dirstamp) \ + libarchive_fe/$(DEPDIR)/$(am__dirstamp) +libarchive_fe/libarchive_fe_la-passphrase.lo: \ + libarchive_fe/$(am__dirstamp) \ + libarchive_fe/$(DEPDIR)/$(am__dirstamp) + +libarchive_fe.la: $(libarchive_fe_la_OBJECTS) $(libarchive_fe_la_DEPENDENCIES) $(EXTRA_libarchive_fe_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libarchive_fe_la_OBJECTS) $(libarchive_fe_la_LIBADD) $(LIBS) +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +cat/$(am__dirstamp): + @$(MKDIR_P) cat + @: > cat/$(am__dirstamp) +cat/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) cat/$(DEPDIR) + @: > cat/$(DEPDIR)/$(am__dirstamp) +cat/bsdcat-bsdcat.$(OBJEXT): cat/$(am__dirstamp) \ + cat/$(DEPDIR)/$(am__dirstamp) +cat/bsdcat-cmdline.$(OBJEXT): cat/$(am__dirstamp) \ + cat/$(DEPDIR)/$(am__dirstamp) + +bsdcat$(EXEEXT): $(bsdcat_OBJECTS) $(bsdcat_DEPENDENCIES) $(EXTRA_bsdcat_DEPENDENCIES) + @rm -f bsdcat$(EXEEXT) + $(AM_V_CCLD)$(bsdcat_LINK) $(bsdcat_OBJECTS) $(bsdcat_LDADD) $(LIBS) +test_utils/$(am__dirstamp): + @$(MKDIR_P) test_utils + @: > test_utils/$(am__dirstamp) +test_utils/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) test_utils/$(DEPDIR) + @: > test_utils/$(DEPDIR)/$(am__dirstamp) +test_utils/bsdcat_test-test_utils.$(OBJEXT): \ + test_utils/$(am__dirstamp) \ + test_utils/$(DEPDIR)/$(am__dirstamp) +test_utils/bsdcat_test-test_main.$(OBJEXT): \ + test_utils/$(am__dirstamp) \ + test_utils/$(DEPDIR)/$(am__dirstamp) +cat/test/$(am__dirstamp): + @$(MKDIR_P) cat/test + @: > cat/test/$(am__dirstamp) +cat/test/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) cat/test/$(DEPDIR) + @: > cat/test/$(DEPDIR)/$(am__dirstamp) +cat/test/bsdcat_test-test_0.$(OBJEXT): cat/test/$(am__dirstamp) \ + cat/test/$(DEPDIR)/$(am__dirstamp) +cat/test/bsdcat_test-test_empty_gz.$(OBJEXT): \ + cat/test/$(am__dirstamp) cat/test/$(DEPDIR)/$(am__dirstamp) +cat/test/bsdcat_test-test_empty_lz4.$(OBJEXT): \ + cat/test/$(am__dirstamp) cat/test/$(DEPDIR)/$(am__dirstamp) +cat/test/bsdcat_test-test_empty_xz.$(OBJEXT): \ + cat/test/$(am__dirstamp) cat/test/$(DEPDIR)/$(am__dirstamp) +cat/test/bsdcat_test-test_empty_zstd.$(OBJEXT): \ + cat/test/$(am__dirstamp) cat/test/$(DEPDIR)/$(am__dirstamp) +cat/test/bsdcat_test-test_error.$(OBJEXT): cat/test/$(am__dirstamp) \ + cat/test/$(DEPDIR)/$(am__dirstamp) +cat/test/bsdcat_test-test_error_mixed.$(OBJEXT): \ + cat/test/$(am__dirstamp) cat/test/$(DEPDIR)/$(am__dirstamp) +cat/test/bsdcat_test-test_expand_Z.$(OBJEXT): \ + cat/test/$(am__dirstamp) cat/test/$(DEPDIR)/$(am__dirstamp) +cat/test/bsdcat_test-test_expand_bz2.$(OBJEXT): \ + cat/test/$(am__dirstamp) cat/test/$(DEPDIR)/$(am__dirstamp) +cat/test/bsdcat_test-test_expand_gz.$(OBJEXT): \ + cat/test/$(am__dirstamp) cat/test/$(DEPDIR)/$(am__dirstamp) +cat/test/bsdcat_test-test_expand_lz4.$(OBJEXT): \ + cat/test/$(am__dirstamp) cat/test/$(DEPDIR)/$(am__dirstamp) +cat/test/bsdcat_test-test_expand_mixed.$(OBJEXT): \ + cat/test/$(am__dirstamp) cat/test/$(DEPDIR)/$(am__dirstamp) +cat/test/bsdcat_test-test_expand_plain.$(OBJEXT): \ + cat/test/$(am__dirstamp) cat/test/$(DEPDIR)/$(am__dirstamp) +cat/test/bsdcat_test-test_expand_xz.$(OBJEXT): \ + cat/test/$(am__dirstamp) cat/test/$(DEPDIR)/$(am__dirstamp) +cat/test/bsdcat_test-test_expand_zstd.$(OBJEXT): \ + cat/test/$(am__dirstamp) cat/test/$(DEPDIR)/$(am__dirstamp) +cat/test/bsdcat_test-test_help.$(OBJEXT): cat/test/$(am__dirstamp) \ + cat/test/$(DEPDIR)/$(am__dirstamp) +cat/test/bsdcat_test-test_stdin.$(OBJEXT): cat/test/$(am__dirstamp) \ + cat/test/$(DEPDIR)/$(am__dirstamp) +cat/test/bsdcat_test-test_version.$(OBJEXT): cat/test/$(am__dirstamp) \ + cat/test/$(DEPDIR)/$(am__dirstamp) + +bsdcat_test$(EXEEXT): $(bsdcat_test_OBJECTS) $(bsdcat_test_DEPENDENCIES) $(EXTRA_bsdcat_test_DEPENDENCIES) + @rm -f bsdcat_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(bsdcat_test_OBJECTS) $(bsdcat_test_LDADD) $(LIBS) +cpio/$(am__dirstamp): + @$(MKDIR_P) cpio + @: > cpio/$(am__dirstamp) +cpio/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) cpio/$(DEPDIR) + @: > cpio/$(DEPDIR)/$(am__dirstamp) +cpio/bsdcpio-cmdline.$(OBJEXT): cpio/$(am__dirstamp) \ + cpio/$(DEPDIR)/$(am__dirstamp) +cpio/bsdcpio-cpio.$(OBJEXT): cpio/$(am__dirstamp) \ + cpio/$(DEPDIR)/$(am__dirstamp) +cpio/bsdcpio-cpio_windows.$(OBJEXT): cpio/$(am__dirstamp) \ + cpio/$(DEPDIR)/$(am__dirstamp) + +bsdcpio$(EXEEXT): $(bsdcpio_OBJECTS) $(bsdcpio_DEPENDENCIES) $(EXTRA_bsdcpio_DEPENDENCIES) + @rm -f bsdcpio$(EXEEXT) + $(AM_V_CCLD)$(bsdcpio_LINK) $(bsdcpio_OBJECTS) $(bsdcpio_LDADD) $(LIBS) +test_utils/bsdcpio_test-test_utils.$(OBJEXT): \ + test_utils/$(am__dirstamp) \ + test_utils/$(DEPDIR)/$(am__dirstamp) +test_utils/bsdcpio_test-test_main.$(OBJEXT): \ + test_utils/$(am__dirstamp) \ + test_utils/$(DEPDIR)/$(am__dirstamp) +cpio/bsdcpio_test-cmdline.$(OBJEXT): cpio/$(am__dirstamp) \ + cpio/$(DEPDIR)/$(am__dirstamp) +cpio/test/$(am__dirstamp): + @$(MKDIR_P) cpio/test + @: > cpio/test/$(am__dirstamp) +cpio/test/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) cpio/test/$(DEPDIR) + @: > cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_0.$(OBJEXT): cpio/test/$(am__dirstamp) \ + cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_basic.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_cmdline.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_extract_cpio_Z.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_extract_cpio_bz2.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_extract_cpio_grz.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_extract_cpio_gz.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_extract_cpio_lrz.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_extract_cpio_lz.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_extract_cpio_lz4.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_extract_cpio_lzma.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_extract_cpio_lzo.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_extract_cpio_xz.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_extract_cpio_zstd.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_format_newc.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_gcpio_compat.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_missing_file.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_0.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_B_upper.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_C_upper.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_J_upper.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_L_upper.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_Z_upper.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_a.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_b64encode.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_c.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_d.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_f.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_grzip.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_help.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_l.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_lrzip.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_lz4.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_lzma.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_lzop.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_m.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_passphrase.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_t.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_u.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_uuencode.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_version.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_xz.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_y.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_z.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_option_zstd.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_owner_parse.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_passthrough_dotdot.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) +cpio/test/bsdcpio_test-test_passthrough_reverse.$(OBJEXT): \ + cpio/test/$(am__dirstamp) cpio/test/$(DEPDIR)/$(am__dirstamp) + +bsdcpio_test$(EXEEXT): $(bsdcpio_test_OBJECTS) $(bsdcpio_test_DEPENDENCIES) $(EXTRA_bsdcpio_test_DEPENDENCIES) + @rm -f bsdcpio_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(bsdcpio_test_OBJECTS) $(bsdcpio_test_LDADD) $(LIBS) +tar/$(am__dirstamp): + @$(MKDIR_P) tar + @: > tar/$(am__dirstamp) +tar/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) tar/$(DEPDIR) + @: > tar/$(DEPDIR)/$(am__dirstamp) +tar/bsdtar-bsdtar.$(OBJEXT): tar/$(am__dirstamp) \ + tar/$(DEPDIR)/$(am__dirstamp) +tar/bsdtar-cmdline.$(OBJEXT): tar/$(am__dirstamp) \ + tar/$(DEPDIR)/$(am__dirstamp) +tar/bsdtar-creation_set.$(OBJEXT): tar/$(am__dirstamp) \ + tar/$(DEPDIR)/$(am__dirstamp) +tar/bsdtar-read.$(OBJEXT): tar/$(am__dirstamp) \ + tar/$(DEPDIR)/$(am__dirstamp) +tar/bsdtar-subst.$(OBJEXT): tar/$(am__dirstamp) \ + tar/$(DEPDIR)/$(am__dirstamp) +tar/bsdtar-util.$(OBJEXT): tar/$(am__dirstamp) \ + tar/$(DEPDIR)/$(am__dirstamp) +tar/bsdtar-write.$(OBJEXT): tar/$(am__dirstamp) \ + tar/$(DEPDIR)/$(am__dirstamp) +tar/bsdtar-bsdtar_windows.$(OBJEXT): tar/$(am__dirstamp) \ + tar/$(DEPDIR)/$(am__dirstamp) + +bsdtar$(EXEEXT): $(bsdtar_OBJECTS) $(bsdtar_DEPENDENCIES) $(EXTRA_bsdtar_DEPENDENCIES) + @rm -f bsdtar$(EXEEXT) + $(AM_V_CCLD)$(bsdtar_LINK) $(bsdtar_OBJECTS) $(bsdtar_LDADD) $(LIBS) +test_utils/bsdtar_test-test_utils.$(OBJEXT): \ + test_utils/$(am__dirstamp) \ + test_utils/$(DEPDIR)/$(am__dirstamp) +test_utils/bsdtar_test-test_main.$(OBJEXT): \ + test_utils/$(am__dirstamp) \ + test_utils/$(DEPDIR)/$(am__dirstamp) +tar/test/$(am__dirstamp): + @$(MKDIR_P) tar/test + @: > tar/test/$(am__dirstamp) +tar/test/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) tar/test/$(DEPDIR) + @: > tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_0.$(OBJEXT): tar/test/$(am__dirstamp) \ + tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_basic.$(OBJEXT): tar/test/$(am__dirstamp) \ + tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_copy.$(OBJEXT): tar/test/$(am__dirstamp) \ + tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_empty_mtree.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_extract_tar_Z.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_extract_tar_bz2.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_extract_tar_grz.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_extract_tar_gz.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_extract_tar_lrz.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_extract_tar_lz.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_extract_tar_lz4.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_extract_tar_lzma.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_extract_tar_lzo.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_extract_tar_xz.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_extract_tar_zstd.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_format_newc.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_help.$(OBJEXT): tar/test/$(am__dirstamp) \ + tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_leading_slash.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_missing_file.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_C_mtree.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_C_upper.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_H_upper.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_L_upper.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_O_upper.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_T_upper.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_U_upper.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_X_upper.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_acls.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_a.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_b.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_b64encode.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_exclude.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_exclude_vcs.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_fflags.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_gid_gname.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_grzip.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_j.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_k.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_keep_newer_files.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_lrzip.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_lz4.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_lzma.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_lzop.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_n.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_newer_than.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_nodump.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_older_than.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_passphrase.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_q.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_r.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_s.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_safe_writes.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_uid_uname.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_uuencode.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_xattrs.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_xz.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_z.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_option_zstd.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_patterns.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_print_longpath.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_stdio.$(OBJEXT): tar/test/$(am__dirstamp) \ + tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_strip_components.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_symlink_dir.$(OBJEXT): \ + tar/test/$(am__dirstamp) tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_version.$(OBJEXT): tar/test/$(am__dirstamp) \ + tar/test/$(DEPDIR)/$(am__dirstamp) +tar/test/bsdtar_test-test_windows.$(OBJEXT): tar/test/$(am__dirstamp) \ + tar/test/$(DEPDIR)/$(am__dirstamp) + +bsdtar_test$(EXEEXT): $(bsdtar_test_OBJECTS) $(bsdtar_test_DEPENDENCIES) $(EXTRA_bsdtar_test_DEPENDENCIES) + @rm -f bsdtar_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(bsdtar_test_OBJECTS) $(bsdtar_test_LDADD) $(LIBS) +libarchive/libarchive_test-archive_acl.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_check_magic.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_cmdline.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_cryptor.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_digest.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_entry.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_entry_copy_stat.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_entry_link_resolver.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_entry_sparse.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_entry_stat.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_entry_strmode.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_entry_xattr.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_getdate.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_hmac.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_match.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_options.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_pack_dev.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_pathmatch.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_ppmd7.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_ppmd8.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_random.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_rb.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_add_passphrase.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_append_filter.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_data_into_fd.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_disk_entry_from_file.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_disk_posix.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_disk_set_standard_lookup.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_extract.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_extract2.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_open_fd.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_open_file.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_open_filename.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_open_memory.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_set_format.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_set_options.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_filter_all.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_filter_bzip2.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_filter_compress.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_filter_grzip.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_filter_gzip.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_filter_lrzip.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_filter_lz4.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_filter_lzop.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_filter_none.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_filter_program.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_filter_rpm.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_filter_uu.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_filter_xz.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_filter_zstd.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_format_7zip.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_format_all.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_format_ar.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_format_by_code.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_format_cab.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_format_cpio.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_format_empty.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_format_iso9660.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_format_lha.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_format_mtree.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_format_rar.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_format_rar5.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_format_raw.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_format_tar.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_format_warc.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_format_xar.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_support_format_zip.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_string.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_string_sprintf.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_util.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_version_details.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_virtual.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_disk_posix.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_disk_set_standard_lookup.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_open_fd.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_open_file.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_open_filename.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_open_memory.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_add_filter.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_add_filter_b64encode.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_add_filter_by_name.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_add_filter_bzip2.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_add_filter_compress.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_add_filter_grzip.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_add_filter_gzip.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_add_filter_lrzip.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_add_filter_lz4.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_add_filter_lzop.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_add_filter_none.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_add_filter_program.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_add_filter_uuencode.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_add_filter_xz.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_add_filter_zstd.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_set_format.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_set_format_7zip.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_set_format_ar.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_set_format_by_name.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_set_format_cpio.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_set_format_cpio_newc.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_set_format_filter_by_ext.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_set_format_iso9660.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_set_format_mtree.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_set_format_pax.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_set_format_raw.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_set_format_shar.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_set_format_ustar.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_set_format_v7tar.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_set_format_gnutar.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_set_format_warc.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_set_format_xar.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_set_format_zip.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_set_options.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_set_passphrase.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-filter_fork_posix.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-xxhash.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_entry_copy_bhfi.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_read_disk_windows.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_windows.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_write_disk_windows.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-filter_fork_windows.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_blake2s_ref.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_blake2sp_ref.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_disk_acl_linux.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_disk_acl_sunos.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_disk_acl_darwin.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +libarchive/libarchive_test-archive_disk_acl_freebsd.$(OBJEXT): \ + libarchive/$(am__dirstamp) \ + libarchive/$(DEPDIR)/$(am__dirstamp) +test_utils/libarchive_test-test_utils.$(OBJEXT): \ + test_utils/$(am__dirstamp) \ + test_utils/$(DEPDIR)/$(am__dirstamp) +test_utils/libarchive_test-test_main.$(OBJEXT): \ + test_utils/$(am__dirstamp) \ + test_utils/$(DEPDIR)/$(am__dirstamp) +libarchive/test/$(am__dirstamp): + @$(MKDIR_P) libarchive/test + @: > libarchive/test/$(am__dirstamp) +libarchive/test/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) libarchive/test/$(DEPDIR) + @: > libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-read_open_memory.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_acl_nfs4.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_acl_pax.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_acl_platform_nfs4.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_acl_platform_posix1e.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_acl_posix1e.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_acl_text.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_api_feature.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_clear_error.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_cmdline.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_digest.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_getdate.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_match_owner.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_match_path.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_match_time.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_pathmatch.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_read_add_passphrase.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_read_close_twice.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_read_close_twice_open_fd.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_read_close_twice_open_filename.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_read_multiple_data_objects.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_read_next_header_empty.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_read_next_header_raw.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_read_open2.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_read_set_filter_option.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_read_set_format_option.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_read_set_option.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_read_set_options.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_read_support.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_set_error.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_string.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_string_conversion.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_write_add_filter_by_name.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_write_set_filter_option.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_write_set_format_by_name.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_write_set_format_filter_by_ext.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_write_set_format_option.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_write_set_option.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_write_set_options.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_archive_write_set_passphrase.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_bad_fd.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_compat_bzip2.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_compat_cpio.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_compat_gtar.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_compat_gzip.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_compat_lz4.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_compat_lzip.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_compat_lzma.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_compat_lzop.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_compat_mac.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_compat_perl_archive_tar.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_compat_plexus_archiver_tar.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_compat_solaris_tar_acl.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_compat_solaris_pax_sparse.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_compat_star_acl.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_compat_tar_hardlink.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_compat_uudecode.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_compat_uudecode_large.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_compat_xz.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_compat_zip.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_compat_zstd.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_empty_write.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_entry.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_entry_strmode.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_extattr_freebsd.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_filter_count.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_fuzz.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_gnutar_filename_encoding.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_link_resolver.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_open_failure.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_open_fd.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_open_file.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_open_filename.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_pax_filename_encoding.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_pax_xattr_header.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_data_large.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_disk.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_disk_directory_traversals.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_disk_entry_from_file.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_extract.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_file_nonexistent.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_filter_compress.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_filter_grzip.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_filter_lrzip.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_filter_lzop.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_filter_lzop_multiple_parts.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_filter_program.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_filter_program_signature.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_filter_uudecode.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_7zip.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_7zip_encryption_data.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_7zip_encryption_partially.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_7zip_encryption_header.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_7zip_malformed.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_7zip_packinfo_digests.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_ar.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_cab.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_cab_filename.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_cpio_afio.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_cpio_bin.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_cpio_bin_Z.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_cpio_bin_be.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_cpio_bin_bz2.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_cpio_bin_gz.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_cpio_bin_le.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_cpio_bin_lzip.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_cpio_bin_lzma.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_cpio_bin_xz.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_cpio_filename.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_cpio_odc.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_cpio_svr4_bzip2_rpm.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_cpio_svr4_gzip.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_cpio_svr4_gzip_rpm.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_cpio_svr4c_Z.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_empty.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_gtar_filename.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_gtar_gz.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_gtar_lzma.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_gtar_sparse.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_gtar_sparse_skip_entry.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_iso_Z.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_iso_multi_extent.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_iso_xorriso.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_isojoliet_bz2.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_isojoliet_long.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_isojoliet_rr.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_isojoliet_versioned.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_isorr_bz2.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_isorr_ce.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_isorr_new_bz2.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_isorr_rr_moved.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_isozisofs_bz2.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_lha.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_lha_bugfix_0.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_lha_filename.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_lha_filename_utf16.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_mtree.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_mtree_crash747.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_pax_bz2.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_rar.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_rar_encryption_data.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_rar_encryption_partially.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_rar_encryption_header.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_rar_invalid1.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_rar5.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_raw.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_tar.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_tar_concatenated.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_tar_empty_pax.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_tar_empty_filename.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_tar_empty_with_gnulabel.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_tar_filename.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_tbz.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_tgz.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_tlz.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_txz.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_tz.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_ustar_filename.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_warc.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_xar.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_zip.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_zip_7075_utf8_paths.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_zip_comment_stored.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_zip_encryption_data.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_zip_encryption_partially.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_zip_encryption_header.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_zip_extra_padding.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_zip_filename.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_zip_high_compression.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_zip_jar.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_zip_mac_metadata.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_zip_malformed.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_zip_msdos.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_zip_nested.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_zip_nofiletype.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_zip_padded.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_zip_sfx.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_zip_traditional_encryption_data.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_zip_winzip_aes.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_zip_winzip_aes_large.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_zip_zip64.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_format_zip_with_invalid_traditional_eocd.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_large.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_pax_schily_xattr.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_pax_truncated.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_position.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_set_format.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_too_many_filters.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_truncated.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_read_truncated_filter.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_sparse_basic.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_tar_filenames.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_tar_large.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_ustar_filenames.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_ustar_filename_encoding.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_warn_missing_hardlink_target.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_disk.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_disk_appledouble.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_disk_failures.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_disk_hardlink.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_disk_hfs_compression.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_disk_lookup.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_disk_mac_metadata.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_disk_no_hfs_compression.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_disk_perms.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_disk_secure.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_disk_secure744.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_disk_secure745.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_disk_secure746.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_disk_sparse.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_disk_symlink.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_disk_times.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_filter_b64encode.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_filter_bzip2.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_filter_compress.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_filter_gzip.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_filter_gzip_timestamp.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_filter_lrzip.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_filter_lz4.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_filter_lzip.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_filter_lzma.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_filter_lzop.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_filter_program.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_filter_uuencode.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_filter_xz.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_filter_zstd.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_7zip.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_7zip_empty.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_7zip_large.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_ar.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_cpio.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_cpio_empty.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_cpio_newc.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_cpio_odc.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_gnutar.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_gnutar_filenames.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_iso9660.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_iso9660_boot.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_iso9660_empty.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_iso9660_filename.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_iso9660_zisofs.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_mtree.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_mtree_absolute_path.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_mtree_classic.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_mtree_classic_indent.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_mtree_fflags.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_mtree_no_separator.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_mtree_quoted_filename.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_pax.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_raw.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_raw_b64.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_shar_empty.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_tar.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_tar_empty.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_tar_sparse.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_tar_ustar.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_tar_v7tar.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_warc.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_warc_empty.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_xar.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_xar_empty.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_zip.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_zip_compression_store.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_zip_empty.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_zip_empty_zip64.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_zip_file.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_zip_file_zip64.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_zip_large.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_format_zip_zip64.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_open_memory.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_write_read_format_zip.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_xattr_platform.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) +libarchive/test/libarchive_test-test_zip_filename_encoding.$(OBJEXT): \ + libarchive/test/$(am__dirstamp) \ + libarchive/test/$(DEPDIR)/$(am__dirstamp) + +libarchive_test$(EXEEXT): $(libarchive_test_OBJECTS) $(libarchive_test_DEPENDENCIES) $(EXTRA_libarchive_test_DEPENDENCIES) + @rm -f libarchive_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(libarchive_test_OBJECTS) $(libarchive_test_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f cat/*.$(OBJEXT) + -rm -f cat/test/*.$(OBJEXT) + -rm -f cpio/*.$(OBJEXT) + -rm -f cpio/test/*.$(OBJEXT) + -rm -f libarchive/*.$(OBJEXT) + -rm -f libarchive/*.lo + -rm -f libarchive/test/*.$(OBJEXT) + -rm -f libarchive_fe/*.$(OBJEXT) + -rm -f libarchive_fe/*.lo + -rm -f tar/*.$(OBJEXT) + -rm -f tar/test/*.$(OBJEXT) + -rm -f test_utils/*.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@cat/$(DEPDIR)/bsdcat-bsdcat.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cat/$(DEPDIR)/bsdcat-cmdline.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cat/test/$(DEPDIR)/bsdcat_test-test_0.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cat/test/$(DEPDIR)/bsdcat_test-test_empty_gz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cat/test/$(DEPDIR)/bsdcat_test-test_empty_lz4.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cat/test/$(DEPDIR)/bsdcat_test-test_empty_xz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cat/test/$(DEPDIR)/bsdcat_test-test_empty_zstd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cat/test/$(DEPDIR)/bsdcat_test-test_error.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cat/test/$(DEPDIR)/bsdcat_test-test_error_mixed.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cat/test/$(DEPDIR)/bsdcat_test-test_expand_Z.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cat/test/$(DEPDIR)/bsdcat_test-test_expand_bz2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cat/test/$(DEPDIR)/bsdcat_test-test_expand_gz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cat/test/$(DEPDIR)/bsdcat_test-test_expand_lz4.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cat/test/$(DEPDIR)/bsdcat_test-test_expand_mixed.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cat/test/$(DEPDIR)/bsdcat_test-test_expand_plain.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cat/test/$(DEPDIR)/bsdcat_test-test_expand_xz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cat/test/$(DEPDIR)/bsdcat_test-test_expand_zstd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cat/test/$(DEPDIR)/bsdcat_test-test_help.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cat/test/$(DEPDIR)/bsdcat_test-test_stdin.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cat/test/$(DEPDIR)/bsdcat_test-test_version.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/$(DEPDIR)/bsdcpio-cmdline.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/$(DEPDIR)/bsdcpio-cpio.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/$(DEPDIR)/bsdcpio-cpio_windows.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/$(DEPDIR)/bsdcpio_test-cmdline.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_0.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_basic.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_cmdline.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_Z.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_bz2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_grz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_gz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lrz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lz4.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lzma.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lzo.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_xz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_zstd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_format_newc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_gcpio_compat.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_missing_file.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_0.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_B_upper.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_C_upper.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_J_upper.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_L_upper.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_Z_upper.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_a.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_b64encode.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_c.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_d.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_f.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_grzip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_help.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_l.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lrzip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lz4.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lzma.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lzop.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_m.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_passphrase.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_t.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_u.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_uuencode.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_version.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_xz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_y.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_z.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_option_zstd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_owner_parse.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_passthrough_dotdot.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cpio/test/$(DEPDIR)/bsdcpio_test-test_passthrough_reverse.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_acl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_blake2s_ref.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_blake2sp_ref.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_check_magic.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_cmdline.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_cryptor.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_digest.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_disk_acl_darwin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_disk_acl_freebsd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_disk_acl_linux.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_disk_acl_sunos.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_entry.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_entry_copy_bhfi.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_entry_copy_stat.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_entry_link_resolver.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_entry_sparse.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_entry_stat.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_entry_strmode.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_entry_xattr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_getdate.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_hmac.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_match.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_options.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_pack_dev.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_pathmatch.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_ppmd7.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_ppmd8.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_random.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_rb.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_add_passphrase.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_append_filter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_data_into_fd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_disk_entry_from_file.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_disk_posix.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_disk_set_standard_lookup.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_disk_windows.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_extract.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_extract2.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_open_fd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_open_file.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_open_filename.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_open_memory.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_set_format.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_set_options.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_filter_all.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_filter_bzip2.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_filter_compress.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_filter_grzip.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_filter_gzip.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_filter_lrzip.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_filter_lz4.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_filter_lzop.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_filter_none.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_filter_program.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_filter_rpm.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_filter_uu.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_filter_xz.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_filter_zstd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_format_7zip.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_format_all.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_format_ar.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_format_by_code.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_format_cab.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_format_cpio.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_format_empty.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_format_iso9660.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_format_lha.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_format_mtree.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_format_rar.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_format_rar5.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_format_raw.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_format_tar.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_format_warc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_format_xar.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_read_support_format_zip.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_string.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_string_sprintf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_util.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_version_details.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_virtual.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_windows.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_add_filter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_add_filter_b64encode.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_add_filter_by_name.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_add_filter_bzip2.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_add_filter_compress.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_add_filter_grzip.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_add_filter_gzip.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_add_filter_lrzip.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_add_filter_lz4.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_add_filter_lzop.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_add_filter_none.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_add_filter_program.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_add_filter_uuencode.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_add_filter_xz.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_add_filter_zstd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_disk_posix.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_disk_set_standard_lookup.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_disk_windows.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_open_fd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_open_file.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_open_filename.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_open_memory.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_set_format.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_set_format_7zip.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_set_format_ar.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_set_format_by_name.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_set_format_cpio.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_set_format_cpio_newc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_set_format_filter_by_ext.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_set_format_gnutar.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_set_format_iso9660.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_set_format_mtree.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_set_format_pax.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_set_format_raw.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_set_format_shar.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_set_format_ustar.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_set_format_v7tar.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_set_format_warc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_set_format_xar.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_set_format_zip.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_set_options.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/archive_write_set_passphrase.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/filter_fork_posix.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/filter_fork_windows.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_acl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_blake2s_ref.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_blake2sp_ref.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_check_magic.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_cmdline.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_cryptor.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_digest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_darwin.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_freebsd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_linux.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_sunos.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_entry.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_entry_copy_bhfi.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_entry_copy_stat.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_entry_link_resolver.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_entry_sparse.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_entry_stat.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_entry_strmode.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_entry_xattr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_getdate.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_hmac.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_match.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_options.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_pack_dev.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_pathmatch.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_ppmd7.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_ppmd8.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_random.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_rb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_add_passphrase.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_append_filter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_data_into_fd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_entry_from_file.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_posix.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_set_standard_lookup.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_windows.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_extract.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_extract2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_open_fd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_open_file.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_open_filename.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_open_memory.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_set_format.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_set_options.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_all.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_bzip2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_compress.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_grzip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_gzip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_lrzip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_lz4.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_lzop.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_none.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_program.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_rpm.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_uu.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_xz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_zstd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_7zip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_all.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_ar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_by_code.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_cab.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_cpio.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_empty.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_iso9660.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_lha.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_mtree.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_rar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_rar5.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_raw.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_tar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_warc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_xar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_zip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_string.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_string_sprintf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_util.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_version_details.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_virtual.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_windows.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_b64encode.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_by_name.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_bzip2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_compress.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_grzip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_gzip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_lrzip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_lz4.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_lzop.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_none.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_program.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_uuencode.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_xz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_zstd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_disk_posix.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_disk_set_standard_lookup.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_disk_windows.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_open_fd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_open_file.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_open_filename.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_open_memory.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_7zip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_ar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_by_name.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_cpio.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_cpio_newc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_filter_by_ext.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_gnutar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_iso9660.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_mtree.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_pax.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_raw.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_shar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_ustar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_v7tar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_warc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_xar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_zip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_set_options.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-archive_write_set_passphrase.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-filter_fork_posix.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-filter_fork_windows.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/libarchive_test-xxhash.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/$(DEPDIR)/xxhash.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-read_open_memory.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_acl_nfs4.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_acl_pax.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_acl_platform_nfs4.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_acl_platform_posix1e.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_acl_posix1e.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_acl_text.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_api_feature.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_clear_error.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_cmdline.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_digest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_getdate.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_match_owner.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_match_path.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_match_time.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_pathmatch.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_add_passphrase.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_close_twice.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_close_twice_open_fd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_close_twice_open_filename.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_multiple_data_objects.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_next_header_empty.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_next_header_raw.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_open2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_filter_option.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_format_option.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_option.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_options.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_support.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_set_error.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_string.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_string_conversion.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_add_filter_by_name.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_filter_option.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_format_by_name.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_format_filter_by_ext.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_format_option.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_option.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_options.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_passphrase.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_bad_fd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_compat_bzip2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_compat_cpio.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_compat_gtar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_compat_gzip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lz4.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lzip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lzma.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lzop.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_compat_mac.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_compat_perl_archive_tar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_compat_plexus_archiver_tar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_compat_solaris_pax_sparse.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_compat_solaris_tar_acl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_compat_star_acl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_compat_tar_hardlink.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_compat_uudecode.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_compat_uudecode_large.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_compat_xz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_compat_zip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_compat_zstd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_empty_write.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_entry.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_entry_strmode.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_extattr_freebsd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_filter_count.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_fuzz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_gnutar_filename_encoding.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_link_resolver.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_open_failure.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_open_fd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_open_file.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_open_filename.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_pax_filename_encoding.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_pax_xattr_header.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_data_large.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_disk.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_disk_directory_traversals.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_disk_entry_from_file.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_extract.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_file_nonexistent.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_compress.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_grzip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_lrzip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_lzop.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_lzop_multiple_parts.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_program.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_program_signature.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_uudecode.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_encryption_data.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_encryption_header.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_encryption_partially.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_malformed.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_packinfo_digests.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_ar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cab.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cab_filename.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_afio.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_Z.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_be.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_bz2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_gz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_le.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_lzip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_lzma.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_xz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_filename.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_odc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4_bzip2_rpm.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4_gzip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4_gzip_rpm.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4c_Z.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_empty.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_filename.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_gz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_lzma.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_sparse.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_sparse_skip_entry.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_iso_Z.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_iso_multi_extent.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_iso_xorriso.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_bz2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_long.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_rr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_versioned.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_bz2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_ce.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_new_bz2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_rr_moved.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isozisofs_bz2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha_bugfix_0.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha_filename.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha_filename_utf16.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_mtree.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_mtree_crash747.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_pax_bz2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar5.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_encryption_data.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_encryption_header.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_encryption_partially.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_invalid1.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_raw.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_concatenated.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_empty_filename.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_empty_pax.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_empty_with_gnulabel.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_filename.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tbz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tgz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tlz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_txz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_ustar_filename.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_warc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_xar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_7075_utf8_paths.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_comment_stored.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_encryption_data.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_encryption_header.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_encryption_partially.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_extra_padding.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_filename.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_high_compression.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_jar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_mac_metadata.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_malformed.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_msdos.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_nested.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_nofiletype.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_padded.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_sfx.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_traditional_encryption_data.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_winzip_aes.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_winzip_aes_large.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_with_invalid_traditional_eocd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_zip64.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_large.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_pax_schily_xattr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_pax_truncated.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_position.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_set_format.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_too_many_filters.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_truncated.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_read_truncated_filter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_sparse_basic.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_tar_filenames.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_tar_large.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_ustar_filename_encoding.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_ustar_filenames.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_warn_missing_hardlink_target.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_appledouble.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_failures.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_hardlink.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_hfs_compression.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_lookup.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_mac_metadata.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_no_hfs_compression.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_perms.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure744.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure745.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure746.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_sparse.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_symlink.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_times.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_b64encode.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_bzip2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_compress.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_gzip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_gzip_timestamp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lrzip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lz4.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lzip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lzma.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lzop.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_program.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_uuencode.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_xz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_zstd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_7zip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_7zip_empty.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_7zip_large.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_ar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio_empty.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio_newc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio_odc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_gnutar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_gnutar_filenames.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_boot.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_empty.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_filename.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_zisofs.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_absolute_path.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_classic.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_classic_indent.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_fflags.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_no_separator.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_quoted_filename.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_pax.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_raw.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_raw_b64.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_shar_empty.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_empty.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_sparse.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_ustar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_v7tar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_warc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_warc_empty.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_xar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_xar_empty.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_compression_store.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_empty.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_empty_zip64.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_file.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_file_zip64.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_large.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_zip64.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_open_memory.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_write_read_format_zip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_xattr_platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive/test/$(DEPDIR)/libarchive_test-test_zip_filename_encoding.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive_fe/$(DEPDIR)/libarchive_fe_la-err.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive_fe/$(DEPDIR)/libarchive_fe_la-line_reader.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libarchive_fe/$(DEPDIR)/libarchive_fe_la-passphrase.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/$(DEPDIR)/bsdtar-bsdtar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/$(DEPDIR)/bsdtar-bsdtar_windows.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/$(DEPDIR)/bsdtar-cmdline.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/$(DEPDIR)/bsdtar-creation_set.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/$(DEPDIR)/bsdtar-read.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/$(DEPDIR)/bsdtar-subst.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/$(DEPDIR)/bsdtar-util.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/$(DEPDIR)/bsdtar-write.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_0.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_basic.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_copy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_empty_mtree.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_Z.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_bz2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_grz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_gz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lrz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lz4.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lzma.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lzo.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_xz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_zstd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_format_newc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_help.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_leading_slash.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_missing_file.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_C_mtree.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_C_upper.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_H_upper.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_L_upper.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_O_upper.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_T_upper.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_U_upper.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_X_upper.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_a.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_acls.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_b.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_b64encode.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_exclude.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_exclude_vcs.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_fflags.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_gid_gname.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_grzip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_j.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_k.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_keep_newer_files.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_lrzip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_lz4.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_lzma.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_lzop.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_n.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_newer_than.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_nodump.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_older_than.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_passphrase.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_q.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_r.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_s.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_safe_writes.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_uid_uname.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_uuencode.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_xattrs.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_xz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_z.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_option_zstd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_patterns.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_print_longpath.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_stdio.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_strip_components.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_symlink_dir.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_version.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tar/test/$(DEPDIR)/bsdtar_test-test_windows.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@test_utils/$(DEPDIR)/bsdcat_test-test_main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@test_utils/$(DEPDIR)/bsdcat_test-test_utils.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@test_utils/$(DEPDIR)/bsdcpio_test-test_main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@test_utils/$(DEPDIR)/bsdcpio_test-test_utils.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@test_utils/$(DEPDIR)/bsdtar_test-test_main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@test_utils/$(DEPDIR)/bsdtar_test-test_utils.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@test_utils/$(DEPDIR)/libarchive_test-test_main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@test_utils/$(DEPDIR)/libarchive_test-test_utils.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libarchive_fe/libarchive_fe_la-err.lo: libarchive_fe/err.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_fe_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive_fe/libarchive_fe_la-err.lo -MD -MP -MF libarchive_fe/$(DEPDIR)/libarchive_fe_la-err.Tpo -c -o libarchive_fe/libarchive_fe_la-err.lo `test -f 'libarchive_fe/err.c' || echo '$(srcdir)/'`libarchive_fe/err.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive_fe/$(DEPDIR)/libarchive_fe_la-err.Tpo libarchive_fe/$(DEPDIR)/libarchive_fe_la-err.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive_fe/err.c' object='libarchive_fe/libarchive_fe_la-err.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_fe_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive_fe/libarchive_fe_la-err.lo `test -f 'libarchive_fe/err.c' || echo '$(srcdir)/'`libarchive_fe/err.c + +libarchive_fe/libarchive_fe_la-line_reader.lo: libarchive_fe/line_reader.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_fe_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive_fe/libarchive_fe_la-line_reader.lo -MD -MP -MF libarchive_fe/$(DEPDIR)/libarchive_fe_la-line_reader.Tpo -c -o libarchive_fe/libarchive_fe_la-line_reader.lo `test -f 'libarchive_fe/line_reader.c' || echo '$(srcdir)/'`libarchive_fe/line_reader.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive_fe/$(DEPDIR)/libarchive_fe_la-line_reader.Tpo libarchive_fe/$(DEPDIR)/libarchive_fe_la-line_reader.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive_fe/line_reader.c' object='libarchive_fe/libarchive_fe_la-line_reader.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_fe_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive_fe/libarchive_fe_la-line_reader.lo `test -f 'libarchive_fe/line_reader.c' || echo '$(srcdir)/'`libarchive_fe/line_reader.c + +libarchive_fe/libarchive_fe_la-passphrase.lo: libarchive_fe/passphrase.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_fe_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive_fe/libarchive_fe_la-passphrase.lo -MD -MP -MF libarchive_fe/$(DEPDIR)/libarchive_fe_la-passphrase.Tpo -c -o libarchive_fe/libarchive_fe_la-passphrase.lo `test -f 'libarchive_fe/passphrase.c' || echo '$(srcdir)/'`libarchive_fe/passphrase.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive_fe/$(DEPDIR)/libarchive_fe_la-passphrase.Tpo libarchive_fe/$(DEPDIR)/libarchive_fe_la-passphrase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive_fe/passphrase.c' object='libarchive_fe/libarchive_fe_la-passphrase.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_fe_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive_fe/libarchive_fe_la-passphrase.lo `test -f 'libarchive_fe/passphrase.c' || echo '$(srcdir)/'`libarchive_fe/passphrase.c + +cat/bsdcat-bsdcat.o: cat/bsdcat.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/bsdcat-bsdcat.o -MD -MP -MF cat/$(DEPDIR)/bsdcat-bsdcat.Tpo -c -o cat/bsdcat-bsdcat.o `test -f 'cat/bsdcat.c' || echo '$(srcdir)/'`cat/bsdcat.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/$(DEPDIR)/bsdcat-bsdcat.Tpo cat/$(DEPDIR)/bsdcat-bsdcat.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/bsdcat.c' object='cat/bsdcat-bsdcat.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/bsdcat-bsdcat.o `test -f 'cat/bsdcat.c' || echo '$(srcdir)/'`cat/bsdcat.c + +cat/bsdcat-bsdcat.obj: cat/bsdcat.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/bsdcat-bsdcat.obj -MD -MP -MF cat/$(DEPDIR)/bsdcat-bsdcat.Tpo -c -o cat/bsdcat-bsdcat.obj `if test -f 'cat/bsdcat.c'; then $(CYGPATH_W) 'cat/bsdcat.c'; else $(CYGPATH_W) '$(srcdir)/cat/bsdcat.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/$(DEPDIR)/bsdcat-bsdcat.Tpo cat/$(DEPDIR)/bsdcat-bsdcat.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/bsdcat.c' object='cat/bsdcat-bsdcat.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/bsdcat-bsdcat.obj `if test -f 'cat/bsdcat.c'; then $(CYGPATH_W) 'cat/bsdcat.c'; else $(CYGPATH_W) '$(srcdir)/cat/bsdcat.c'; fi` + +cat/bsdcat-cmdline.o: cat/cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/bsdcat-cmdline.o -MD -MP -MF cat/$(DEPDIR)/bsdcat-cmdline.Tpo -c -o cat/bsdcat-cmdline.o `test -f 'cat/cmdline.c' || echo '$(srcdir)/'`cat/cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/$(DEPDIR)/bsdcat-cmdline.Tpo cat/$(DEPDIR)/bsdcat-cmdline.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/cmdline.c' object='cat/bsdcat-cmdline.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/bsdcat-cmdline.o `test -f 'cat/cmdline.c' || echo '$(srcdir)/'`cat/cmdline.c + +cat/bsdcat-cmdline.obj: cat/cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/bsdcat-cmdline.obj -MD -MP -MF cat/$(DEPDIR)/bsdcat-cmdline.Tpo -c -o cat/bsdcat-cmdline.obj `if test -f 'cat/cmdline.c'; then $(CYGPATH_W) 'cat/cmdline.c'; else $(CYGPATH_W) '$(srcdir)/cat/cmdline.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/$(DEPDIR)/bsdcat-cmdline.Tpo cat/$(DEPDIR)/bsdcat-cmdline.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/cmdline.c' object='cat/bsdcat-cmdline.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/bsdcat-cmdline.obj `if test -f 'cat/cmdline.c'; then $(CYGPATH_W) 'cat/cmdline.c'; else $(CYGPATH_W) '$(srcdir)/cat/cmdline.c'; fi` + +test_utils/bsdcat_test-test_utils.o: test_utils/test_utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_utils/bsdcat_test-test_utils.o -MD -MP -MF test_utils/$(DEPDIR)/bsdcat_test-test_utils.Tpo -c -o test_utils/bsdcat_test-test_utils.o `test -f 'test_utils/test_utils.c' || echo '$(srcdir)/'`test_utils/test_utils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) test_utils/$(DEPDIR)/bsdcat_test-test_utils.Tpo test_utils/$(DEPDIR)/bsdcat_test-test_utils.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_utils/test_utils.c' object='test_utils/bsdcat_test-test_utils.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_utils/bsdcat_test-test_utils.o `test -f 'test_utils/test_utils.c' || echo '$(srcdir)/'`test_utils/test_utils.c + +test_utils/bsdcat_test-test_utils.obj: test_utils/test_utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_utils/bsdcat_test-test_utils.obj -MD -MP -MF test_utils/$(DEPDIR)/bsdcat_test-test_utils.Tpo -c -o test_utils/bsdcat_test-test_utils.obj `if test -f 'test_utils/test_utils.c'; then $(CYGPATH_W) 'test_utils/test_utils.c'; else $(CYGPATH_W) '$(srcdir)/test_utils/test_utils.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) test_utils/$(DEPDIR)/bsdcat_test-test_utils.Tpo test_utils/$(DEPDIR)/bsdcat_test-test_utils.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_utils/test_utils.c' object='test_utils/bsdcat_test-test_utils.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_utils/bsdcat_test-test_utils.obj `if test -f 'test_utils/test_utils.c'; then $(CYGPATH_W) 'test_utils/test_utils.c'; else $(CYGPATH_W) '$(srcdir)/test_utils/test_utils.c'; fi` + +test_utils/bsdcat_test-test_main.o: test_utils/test_main.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_utils/bsdcat_test-test_main.o -MD -MP -MF test_utils/$(DEPDIR)/bsdcat_test-test_main.Tpo -c -o test_utils/bsdcat_test-test_main.o `test -f 'test_utils/test_main.c' || echo '$(srcdir)/'`test_utils/test_main.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) test_utils/$(DEPDIR)/bsdcat_test-test_main.Tpo test_utils/$(DEPDIR)/bsdcat_test-test_main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_utils/test_main.c' object='test_utils/bsdcat_test-test_main.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_utils/bsdcat_test-test_main.o `test -f 'test_utils/test_main.c' || echo '$(srcdir)/'`test_utils/test_main.c + +test_utils/bsdcat_test-test_main.obj: test_utils/test_main.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_utils/bsdcat_test-test_main.obj -MD -MP -MF test_utils/$(DEPDIR)/bsdcat_test-test_main.Tpo -c -o test_utils/bsdcat_test-test_main.obj `if test -f 'test_utils/test_main.c'; then $(CYGPATH_W) 'test_utils/test_main.c'; else $(CYGPATH_W) '$(srcdir)/test_utils/test_main.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) test_utils/$(DEPDIR)/bsdcat_test-test_main.Tpo test_utils/$(DEPDIR)/bsdcat_test-test_main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_utils/test_main.c' object='test_utils/bsdcat_test-test_main.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_utils/bsdcat_test-test_main.obj `if test -f 'test_utils/test_main.c'; then $(CYGPATH_W) 'test_utils/test_main.c'; else $(CYGPATH_W) '$(srcdir)/test_utils/test_main.c'; fi` + +cat/test/bsdcat_test-test_0.o: cat/test/test_0.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_0.o -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_0.Tpo -c -o cat/test/bsdcat_test-test_0.o `test -f 'cat/test/test_0.c' || echo '$(srcdir)/'`cat/test/test_0.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_0.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_0.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_0.c' object='cat/test/bsdcat_test-test_0.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_0.o `test -f 'cat/test/test_0.c' || echo '$(srcdir)/'`cat/test/test_0.c + +cat/test/bsdcat_test-test_0.obj: cat/test/test_0.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_0.obj -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_0.Tpo -c -o cat/test/bsdcat_test-test_0.obj `if test -f 'cat/test/test_0.c'; then $(CYGPATH_W) 'cat/test/test_0.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_0.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_0.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_0.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_0.c' object='cat/test/bsdcat_test-test_0.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_0.obj `if test -f 'cat/test/test_0.c'; then $(CYGPATH_W) 'cat/test/test_0.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_0.c'; fi` + +cat/test/bsdcat_test-test_empty_gz.o: cat/test/test_empty_gz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_empty_gz.o -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_empty_gz.Tpo -c -o cat/test/bsdcat_test-test_empty_gz.o `test -f 'cat/test/test_empty_gz.c' || echo '$(srcdir)/'`cat/test/test_empty_gz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_empty_gz.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_empty_gz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_empty_gz.c' object='cat/test/bsdcat_test-test_empty_gz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_empty_gz.o `test -f 'cat/test/test_empty_gz.c' || echo '$(srcdir)/'`cat/test/test_empty_gz.c + +cat/test/bsdcat_test-test_empty_gz.obj: cat/test/test_empty_gz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_empty_gz.obj -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_empty_gz.Tpo -c -o cat/test/bsdcat_test-test_empty_gz.obj `if test -f 'cat/test/test_empty_gz.c'; then $(CYGPATH_W) 'cat/test/test_empty_gz.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_empty_gz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_empty_gz.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_empty_gz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_empty_gz.c' object='cat/test/bsdcat_test-test_empty_gz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_empty_gz.obj `if test -f 'cat/test/test_empty_gz.c'; then $(CYGPATH_W) 'cat/test/test_empty_gz.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_empty_gz.c'; fi` + +cat/test/bsdcat_test-test_empty_lz4.o: cat/test/test_empty_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_empty_lz4.o -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_empty_lz4.Tpo -c -o cat/test/bsdcat_test-test_empty_lz4.o `test -f 'cat/test/test_empty_lz4.c' || echo '$(srcdir)/'`cat/test/test_empty_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_empty_lz4.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_empty_lz4.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_empty_lz4.c' object='cat/test/bsdcat_test-test_empty_lz4.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_empty_lz4.o `test -f 'cat/test/test_empty_lz4.c' || echo '$(srcdir)/'`cat/test/test_empty_lz4.c + +cat/test/bsdcat_test-test_empty_lz4.obj: cat/test/test_empty_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_empty_lz4.obj -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_empty_lz4.Tpo -c -o cat/test/bsdcat_test-test_empty_lz4.obj `if test -f 'cat/test/test_empty_lz4.c'; then $(CYGPATH_W) 'cat/test/test_empty_lz4.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_empty_lz4.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_empty_lz4.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_empty_lz4.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_empty_lz4.c' object='cat/test/bsdcat_test-test_empty_lz4.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_empty_lz4.obj `if test -f 'cat/test/test_empty_lz4.c'; then $(CYGPATH_W) 'cat/test/test_empty_lz4.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_empty_lz4.c'; fi` + +cat/test/bsdcat_test-test_empty_xz.o: cat/test/test_empty_xz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_empty_xz.o -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_empty_xz.Tpo -c -o cat/test/bsdcat_test-test_empty_xz.o `test -f 'cat/test/test_empty_xz.c' || echo '$(srcdir)/'`cat/test/test_empty_xz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_empty_xz.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_empty_xz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_empty_xz.c' object='cat/test/bsdcat_test-test_empty_xz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_empty_xz.o `test -f 'cat/test/test_empty_xz.c' || echo '$(srcdir)/'`cat/test/test_empty_xz.c + +cat/test/bsdcat_test-test_empty_xz.obj: cat/test/test_empty_xz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_empty_xz.obj -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_empty_xz.Tpo -c -o cat/test/bsdcat_test-test_empty_xz.obj `if test -f 'cat/test/test_empty_xz.c'; then $(CYGPATH_W) 'cat/test/test_empty_xz.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_empty_xz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_empty_xz.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_empty_xz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_empty_xz.c' object='cat/test/bsdcat_test-test_empty_xz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_empty_xz.obj `if test -f 'cat/test/test_empty_xz.c'; then $(CYGPATH_W) 'cat/test/test_empty_xz.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_empty_xz.c'; fi` + +cat/test/bsdcat_test-test_empty_zstd.o: cat/test/test_empty_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_empty_zstd.o -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_empty_zstd.Tpo -c -o cat/test/bsdcat_test-test_empty_zstd.o `test -f 'cat/test/test_empty_zstd.c' || echo '$(srcdir)/'`cat/test/test_empty_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_empty_zstd.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_empty_zstd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_empty_zstd.c' object='cat/test/bsdcat_test-test_empty_zstd.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_empty_zstd.o `test -f 'cat/test/test_empty_zstd.c' || echo '$(srcdir)/'`cat/test/test_empty_zstd.c + +cat/test/bsdcat_test-test_empty_zstd.obj: cat/test/test_empty_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_empty_zstd.obj -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_empty_zstd.Tpo -c -o cat/test/bsdcat_test-test_empty_zstd.obj `if test -f 'cat/test/test_empty_zstd.c'; then $(CYGPATH_W) 'cat/test/test_empty_zstd.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_empty_zstd.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_empty_zstd.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_empty_zstd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_empty_zstd.c' object='cat/test/bsdcat_test-test_empty_zstd.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_empty_zstd.obj `if test -f 'cat/test/test_empty_zstd.c'; then $(CYGPATH_W) 'cat/test/test_empty_zstd.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_empty_zstd.c'; fi` + +cat/test/bsdcat_test-test_error.o: cat/test/test_error.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_error.o -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_error.Tpo -c -o cat/test/bsdcat_test-test_error.o `test -f 'cat/test/test_error.c' || echo '$(srcdir)/'`cat/test/test_error.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_error.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_error.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_error.c' object='cat/test/bsdcat_test-test_error.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_error.o `test -f 'cat/test/test_error.c' || echo '$(srcdir)/'`cat/test/test_error.c + +cat/test/bsdcat_test-test_error.obj: cat/test/test_error.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_error.obj -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_error.Tpo -c -o cat/test/bsdcat_test-test_error.obj `if test -f 'cat/test/test_error.c'; then $(CYGPATH_W) 'cat/test/test_error.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_error.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_error.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_error.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_error.c' object='cat/test/bsdcat_test-test_error.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_error.obj `if test -f 'cat/test/test_error.c'; then $(CYGPATH_W) 'cat/test/test_error.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_error.c'; fi` + +cat/test/bsdcat_test-test_error_mixed.o: cat/test/test_error_mixed.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_error_mixed.o -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_error_mixed.Tpo -c -o cat/test/bsdcat_test-test_error_mixed.o `test -f 'cat/test/test_error_mixed.c' || echo '$(srcdir)/'`cat/test/test_error_mixed.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_error_mixed.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_error_mixed.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_error_mixed.c' object='cat/test/bsdcat_test-test_error_mixed.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_error_mixed.o `test -f 'cat/test/test_error_mixed.c' || echo '$(srcdir)/'`cat/test/test_error_mixed.c + +cat/test/bsdcat_test-test_error_mixed.obj: cat/test/test_error_mixed.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_error_mixed.obj -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_error_mixed.Tpo -c -o cat/test/bsdcat_test-test_error_mixed.obj `if test -f 'cat/test/test_error_mixed.c'; then $(CYGPATH_W) 'cat/test/test_error_mixed.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_error_mixed.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_error_mixed.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_error_mixed.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_error_mixed.c' object='cat/test/bsdcat_test-test_error_mixed.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_error_mixed.obj `if test -f 'cat/test/test_error_mixed.c'; then $(CYGPATH_W) 'cat/test/test_error_mixed.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_error_mixed.c'; fi` + +cat/test/bsdcat_test-test_expand_Z.o: cat/test/test_expand_Z.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_expand_Z.o -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_expand_Z.Tpo -c -o cat/test/bsdcat_test-test_expand_Z.o `test -f 'cat/test/test_expand_Z.c' || echo '$(srcdir)/'`cat/test/test_expand_Z.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_expand_Z.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_expand_Z.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_expand_Z.c' object='cat/test/bsdcat_test-test_expand_Z.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_expand_Z.o `test -f 'cat/test/test_expand_Z.c' || echo '$(srcdir)/'`cat/test/test_expand_Z.c + +cat/test/bsdcat_test-test_expand_Z.obj: cat/test/test_expand_Z.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_expand_Z.obj -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_expand_Z.Tpo -c -o cat/test/bsdcat_test-test_expand_Z.obj `if test -f 'cat/test/test_expand_Z.c'; then $(CYGPATH_W) 'cat/test/test_expand_Z.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_expand_Z.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_expand_Z.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_expand_Z.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_expand_Z.c' object='cat/test/bsdcat_test-test_expand_Z.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_expand_Z.obj `if test -f 'cat/test/test_expand_Z.c'; then $(CYGPATH_W) 'cat/test/test_expand_Z.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_expand_Z.c'; fi` + +cat/test/bsdcat_test-test_expand_bz2.o: cat/test/test_expand_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_expand_bz2.o -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_expand_bz2.Tpo -c -o cat/test/bsdcat_test-test_expand_bz2.o `test -f 'cat/test/test_expand_bz2.c' || echo '$(srcdir)/'`cat/test/test_expand_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_expand_bz2.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_expand_bz2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_expand_bz2.c' object='cat/test/bsdcat_test-test_expand_bz2.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_expand_bz2.o `test -f 'cat/test/test_expand_bz2.c' || echo '$(srcdir)/'`cat/test/test_expand_bz2.c + +cat/test/bsdcat_test-test_expand_bz2.obj: cat/test/test_expand_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_expand_bz2.obj -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_expand_bz2.Tpo -c -o cat/test/bsdcat_test-test_expand_bz2.obj `if test -f 'cat/test/test_expand_bz2.c'; then $(CYGPATH_W) 'cat/test/test_expand_bz2.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_expand_bz2.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_expand_bz2.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_expand_bz2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_expand_bz2.c' object='cat/test/bsdcat_test-test_expand_bz2.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_expand_bz2.obj `if test -f 'cat/test/test_expand_bz2.c'; then $(CYGPATH_W) 'cat/test/test_expand_bz2.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_expand_bz2.c'; fi` + +cat/test/bsdcat_test-test_expand_gz.o: cat/test/test_expand_gz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_expand_gz.o -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_expand_gz.Tpo -c -o cat/test/bsdcat_test-test_expand_gz.o `test -f 'cat/test/test_expand_gz.c' || echo '$(srcdir)/'`cat/test/test_expand_gz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_expand_gz.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_expand_gz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_expand_gz.c' object='cat/test/bsdcat_test-test_expand_gz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_expand_gz.o `test -f 'cat/test/test_expand_gz.c' || echo '$(srcdir)/'`cat/test/test_expand_gz.c + +cat/test/bsdcat_test-test_expand_gz.obj: cat/test/test_expand_gz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_expand_gz.obj -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_expand_gz.Tpo -c -o cat/test/bsdcat_test-test_expand_gz.obj `if test -f 'cat/test/test_expand_gz.c'; then $(CYGPATH_W) 'cat/test/test_expand_gz.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_expand_gz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_expand_gz.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_expand_gz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_expand_gz.c' object='cat/test/bsdcat_test-test_expand_gz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_expand_gz.obj `if test -f 'cat/test/test_expand_gz.c'; then $(CYGPATH_W) 'cat/test/test_expand_gz.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_expand_gz.c'; fi` + +cat/test/bsdcat_test-test_expand_lz4.o: cat/test/test_expand_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_expand_lz4.o -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_expand_lz4.Tpo -c -o cat/test/bsdcat_test-test_expand_lz4.o `test -f 'cat/test/test_expand_lz4.c' || echo '$(srcdir)/'`cat/test/test_expand_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_expand_lz4.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_expand_lz4.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_expand_lz4.c' object='cat/test/bsdcat_test-test_expand_lz4.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_expand_lz4.o `test -f 'cat/test/test_expand_lz4.c' || echo '$(srcdir)/'`cat/test/test_expand_lz4.c + +cat/test/bsdcat_test-test_expand_lz4.obj: cat/test/test_expand_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_expand_lz4.obj -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_expand_lz4.Tpo -c -o cat/test/bsdcat_test-test_expand_lz4.obj `if test -f 'cat/test/test_expand_lz4.c'; then $(CYGPATH_W) 'cat/test/test_expand_lz4.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_expand_lz4.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_expand_lz4.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_expand_lz4.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_expand_lz4.c' object='cat/test/bsdcat_test-test_expand_lz4.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_expand_lz4.obj `if test -f 'cat/test/test_expand_lz4.c'; then $(CYGPATH_W) 'cat/test/test_expand_lz4.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_expand_lz4.c'; fi` + +cat/test/bsdcat_test-test_expand_mixed.o: cat/test/test_expand_mixed.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_expand_mixed.o -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_expand_mixed.Tpo -c -o cat/test/bsdcat_test-test_expand_mixed.o `test -f 'cat/test/test_expand_mixed.c' || echo '$(srcdir)/'`cat/test/test_expand_mixed.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_expand_mixed.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_expand_mixed.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_expand_mixed.c' object='cat/test/bsdcat_test-test_expand_mixed.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_expand_mixed.o `test -f 'cat/test/test_expand_mixed.c' || echo '$(srcdir)/'`cat/test/test_expand_mixed.c + +cat/test/bsdcat_test-test_expand_mixed.obj: cat/test/test_expand_mixed.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_expand_mixed.obj -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_expand_mixed.Tpo -c -o cat/test/bsdcat_test-test_expand_mixed.obj `if test -f 'cat/test/test_expand_mixed.c'; then $(CYGPATH_W) 'cat/test/test_expand_mixed.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_expand_mixed.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_expand_mixed.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_expand_mixed.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_expand_mixed.c' object='cat/test/bsdcat_test-test_expand_mixed.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_expand_mixed.obj `if test -f 'cat/test/test_expand_mixed.c'; then $(CYGPATH_W) 'cat/test/test_expand_mixed.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_expand_mixed.c'; fi` + +cat/test/bsdcat_test-test_expand_plain.o: cat/test/test_expand_plain.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_expand_plain.o -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_expand_plain.Tpo -c -o cat/test/bsdcat_test-test_expand_plain.o `test -f 'cat/test/test_expand_plain.c' || echo '$(srcdir)/'`cat/test/test_expand_plain.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_expand_plain.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_expand_plain.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_expand_plain.c' object='cat/test/bsdcat_test-test_expand_plain.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_expand_plain.o `test -f 'cat/test/test_expand_plain.c' || echo '$(srcdir)/'`cat/test/test_expand_plain.c + +cat/test/bsdcat_test-test_expand_plain.obj: cat/test/test_expand_plain.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_expand_plain.obj -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_expand_plain.Tpo -c -o cat/test/bsdcat_test-test_expand_plain.obj `if test -f 'cat/test/test_expand_plain.c'; then $(CYGPATH_W) 'cat/test/test_expand_plain.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_expand_plain.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_expand_plain.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_expand_plain.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_expand_plain.c' object='cat/test/bsdcat_test-test_expand_plain.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_expand_plain.obj `if test -f 'cat/test/test_expand_plain.c'; then $(CYGPATH_W) 'cat/test/test_expand_plain.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_expand_plain.c'; fi` + +cat/test/bsdcat_test-test_expand_xz.o: cat/test/test_expand_xz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_expand_xz.o -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_expand_xz.Tpo -c -o cat/test/bsdcat_test-test_expand_xz.o `test -f 'cat/test/test_expand_xz.c' || echo '$(srcdir)/'`cat/test/test_expand_xz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_expand_xz.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_expand_xz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_expand_xz.c' object='cat/test/bsdcat_test-test_expand_xz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_expand_xz.o `test -f 'cat/test/test_expand_xz.c' || echo '$(srcdir)/'`cat/test/test_expand_xz.c + +cat/test/bsdcat_test-test_expand_xz.obj: cat/test/test_expand_xz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_expand_xz.obj -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_expand_xz.Tpo -c -o cat/test/bsdcat_test-test_expand_xz.obj `if test -f 'cat/test/test_expand_xz.c'; then $(CYGPATH_W) 'cat/test/test_expand_xz.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_expand_xz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_expand_xz.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_expand_xz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_expand_xz.c' object='cat/test/bsdcat_test-test_expand_xz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_expand_xz.obj `if test -f 'cat/test/test_expand_xz.c'; then $(CYGPATH_W) 'cat/test/test_expand_xz.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_expand_xz.c'; fi` + +cat/test/bsdcat_test-test_expand_zstd.o: cat/test/test_expand_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_expand_zstd.o -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_expand_zstd.Tpo -c -o cat/test/bsdcat_test-test_expand_zstd.o `test -f 'cat/test/test_expand_zstd.c' || echo '$(srcdir)/'`cat/test/test_expand_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_expand_zstd.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_expand_zstd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_expand_zstd.c' object='cat/test/bsdcat_test-test_expand_zstd.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_expand_zstd.o `test -f 'cat/test/test_expand_zstd.c' || echo '$(srcdir)/'`cat/test/test_expand_zstd.c + +cat/test/bsdcat_test-test_expand_zstd.obj: cat/test/test_expand_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_expand_zstd.obj -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_expand_zstd.Tpo -c -o cat/test/bsdcat_test-test_expand_zstd.obj `if test -f 'cat/test/test_expand_zstd.c'; then $(CYGPATH_W) 'cat/test/test_expand_zstd.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_expand_zstd.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_expand_zstd.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_expand_zstd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_expand_zstd.c' object='cat/test/bsdcat_test-test_expand_zstd.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_expand_zstd.obj `if test -f 'cat/test/test_expand_zstd.c'; then $(CYGPATH_W) 'cat/test/test_expand_zstd.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_expand_zstd.c'; fi` + +cat/test/bsdcat_test-test_help.o: cat/test/test_help.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_help.o -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_help.Tpo -c -o cat/test/bsdcat_test-test_help.o `test -f 'cat/test/test_help.c' || echo '$(srcdir)/'`cat/test/test_help.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_help.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_help.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_help.c' object='cat/test/bsdcat_test-test_help.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_help.o `test -f 'cat/test/test_help.c' || echo '$(srcdir)/'`cat/test/test_help.c + +cat/test/bsdcat_test-test_help.obj: cat/test/test_help.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_help.obj -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_help.Tpo -c -o cat/test/bsdcat_test-test_help.obj `if test -f 'cat/test/test_help.c'; then $(CYGPATH_W) 'cat/test/test_help.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_help.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_help.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_help.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_help.c' object='cat/test/bsdcat_test-test_help.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_help.obj `if test -f 'cat/test/test_help.c'; then $(CYGPATH_W) 'cat/test/test_help.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_help.c'; fi` + +cat/test/bsdcat_test-test_stdin.o: cat/test/test_stdin.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_stdin.o -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_stdin.Tpo -c -o cat/test/bsdcat_test-test_stdin.o `test -f 'cat/test/test_stdin.c' || echo '$(srcdir)/'`cat/test/test_stdin.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_stdin.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_stdin.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_stdin.c' object='cat/test/bsdcat_test-test_stdin.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_stdin.o `test -f 'cat/test/test_stdin.c' || echo '$(srcdir)/'`cat/test/test_stdin.c + +cat/test/bsdcat_test-test_stdin.obj: cat/test/test_stdin.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_stdin.obj -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_stdin.Tpo -c -o cat/test/bsdcat_test-test_stdin.obj `if test -f 'cat/test/test_stdin.c'; then $(CYGPATH_W) 'cat/test/test_stdin.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_stdin.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_stdin.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_stdin.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_stdin.c' object='cat/test/bsdcat_test-test_stdin.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_stdin.obj `if test -f 'cat/test/test_stdin.c'; then $(CYGPATH_W) 'cat/test/test_stdin.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_stdin.c'; fi` + +cat/test/bsdcat_test-test_version.o: cat/test/test_version.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_version.o -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_version.Tpo -c -o cat/test/bsdcat_test-test_version.o `test -f 'cat/test/test_version.c' || echo '$(srcdir)/'`cat/test/test_version.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_version.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_version.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_version.c' object='cat/test/bsdcat_test-test_version.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_version.o `test -f 'cat/test/test_version.c' || echo '$(srcdir)/'`cat/test/test_version.c + +cat/test/bsdcat_test-test_version.obj: cat/test/test_version.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cat/test/bsdcat_test-test_version.obj -MD -MP -MF cat/test/$(DEPDIR)/bsdcat_test-test_version.Tpo -c -o cat/test/bsdcat_test-test_version.obj `if test -f 'cat/test/test_version.c'; then $(CYGPATH_W) 'cat/test/test_version.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_version.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cat/test/$(DEPDIR)/bsdcat_test-test_version.Tpo cat/test/$(DEPDIR)/bsdcat_test-test_version.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cat/test/test_version.c' object='cat/test/bsdcat_test-test_version.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cat/test/bsdcat_test-test_version.obj `if test -f 'cat/test/test_version.c'; then $(CYGPATH_W) 'cat/test/test_version.c'; else $(CYGPATH_W) '$(srcdir)/cat/test/test_version.c'; fi` + +cpio/bsdcpio-cmdline.o: cpio/cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/bsdcpio-cmdline.o -MD -MP -MF cpio/$(DEPDIR)/bsdcpio-cmdline.Tpo -c -o cpio/bsdcpio-cmdline.o `test -f 'cpio/cmdline.c' || echo '$(srcdir)/'`cpio/cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/$(DEPDIR)/bsdcpio-cmdline.Tpo cpio/$(DEPDIR)/bsdcpio-cmdline.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/cmdline.c' object='cpio/bsdcpio-cmdline.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/bsdcpio-cmdline.o `test -f 'cpio/cmdline.c' || echo '$(srcdir)/'`cpio/cmdline.c + +cpio/bsdcpio-cmdline.obj: cpio/cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/bsdcpio-cmdline.obj -MD -MP -MF cpio/$(DEPDIR)/bsdcpio-cmdline.Tpo -c -o cpio/bsdcpio-cmdline.obj `if test -f 'cpio/cmdline.c'; then $(CYGPATH_W) 'cpio/cmdline.c'; else $(CYGPATH_W) '$(srcdir)/cpio/cmdline.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/$(DEPDIR)/bsdcpio-cmdline.Tpo cpio/$(DEPDIR)/bsdcpio-cmdline.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/cmdline.c' object='cpio/bsdcpio-cmdline.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/bsdcpio-cmdline.obj `if test -f 'cpio/cmdline.c'; then $(CYGPATH_W) 'cpio/cmdline.c'; else $(CYGPATH_W) '$(srcdir)/cpio/cmdline.c'; fi` + +cpio/bsdcpio-cpio.o: cpio/cpio.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/bsdcpio-cpio.o -MD -MP -MF cpio/$(DEPDIR)/bsdcpio-cpio.Tpo -c -o cpio/bsdcpio-cpio.o `test -f 'cpio/cpio.c' || echo '$(srcdir)/'`cpio/cpio.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/$(DEPDIR)/bsdcpio-cpio.Tpo cpio/$(DEPDIR)/bsdcpio-cpio.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/cpio.c' object='cpio/bsdcpio-cpio.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/bsdcpio-cpio.o `test -f 'cpio/cpio.c' || echo '$(srcdir)/'`cpio/cpio.c + +cpio/bsdcpio-cpio.obj: cpio/cpio.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/bsdcpio-cpio.obj -MD -MP -MF cpio/$(DEPDIR)/bsdcpio-cpio.Tpo -c -o cpio/bsdcpio-cpio.obj `if test -f 'cpio/cpio.c'; then $(CYGPATH_W) 'cpio/cpio.c'; else $(CYGPATH_W) '$(srcdir)/cpio/cpio.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/$(DEPDIR)/bsdcpio-cpio.Tpo cpio/$(DEPDIR)/bsdcpio-cpio.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/cpio.c' object='cpio/bsdcpio-cpio.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/bsdcpio-cpio.obj `if test -f 'cpio/cpio.c'; then $(CYGPATH_W) 'cpio/cpio.c'; else $(CYGPATH_W) '$(srcdir)/cpio/cpio.c'; fi` + +cpio/bsdcpio-cpio_windows.o: cpio/cpio_windows.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/bsdcpio-cpio_windows.o -MD -MP -MF cpio/$(DEPDIR)/bsdcpio-cpio_windows.Tpo -c -o cpio/bsdcpio-cpio_windows.o `test -f 'cpio/cpio_windows.c' || echo '$(srcdir)/'`cpio/cpio_windows.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/$(DEPDIR)/bsdcpio-cpio_windows.Tpo cpio/$(DEPDIR)/bsdcpio-cpio_windows.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/cpio_windows.c' object='cpio/bsdcpio-cpio_windows.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/bsdcpio-cpio_windows.o `test -f 'cpio/cpio_windows.c' || echo '$(srcdir)/'`cpio/cpio_windows.c + +cpio/bsdcpio-cpio_windows.obj: cpio/cpio_windows.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/bsdcpio-cpio_windows.obj -MD -MP -MF cpio/$(DEPDIR)/bsdcpio-cpio_windows.Tpo -c -o cpio/bsdcpio-cpio_windows.obj `if test -f 'cpio/cpio_windows.c'; then $(CYGPATH_W) 'cpio/cpio_windows.c'; else $(CYGPATH_W) '$(srcdir)/cpio/cpio_windows.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/$(DEPDIR)/bsdcpio-cpio_windows.Tpo cpio/$(DEPDIR)/bsdcpio-cpio_windows.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/cpio_windows.c' object='cpio/bsdcpio-cpio_windows.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/bsdcpio-cpio_windows.obj `if test -f 'cpio/cpio_windows.c'; then $(CYGPATH_W) 'cpio/cpio_windows.c'; else $(CYGPATH_W) '$(srcdir)/cpio/cpio_windows.c'; fi` + +test_utils/bsdcpio_test-test_utils.o: test_utils/test_utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_utils/bsdcpio_test-test_utils.o -MD -MP -MF test_utils/$(DEPDIR)/bsdcpio_test-test_utils.Tpo -c -o test_utils/bsdcpio_test-test_utils.o `test -f 'test_utils/test_utils.c' || echo '$(srcdir)/'`test_utils/test_utils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) test_utils/$(DEPDIR)/bsdcpio_test-test_utils.Tpo test_utils/$(DEPDIR)/bsdcpio_test-test_utils.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_utils/test_utils.c' object='test_utils/bsdcpio_test-test_utils.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_utils/bsdcpio_test-test_utils.o `test -f 'test_utils/test_utils.c' || echo '$(srcdir)/'`test_utils/test_utils.c + +test_utils/bsdcpio_test-test_utils.obj: test_utils/test_utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_utils/bsdcpio_test-test_utils.obj -MD -MP -MF test_utils/$(DEPDIR)/bsdcpio_test-test_utils.Tpo -c -o test_utils/bsdcpio_test-test_utils.obj `if test -f 'test_utils/test_utils.c'; then $(CYGPATH_W) 'test_utils/test_utils.c'; else $(CYGPATH_W) '$(srcdir)/test_utils/test_utils.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) test_utils/$(DEPDIR)/bsdcpio_test-test_utils.Tpo test_utils/$(DEPDIR)/bsdcpio_test-test_utils.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_utils/test_utils.c' object='test_utils/bsdcpio_test-test_utils.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_utils/bsdcpio_test-test_utils.obj `if test -f 'test_utils/test_utils.c'; then $(CYGPATH_W) 'test_utils/test_utils.c'; else $(CYGPATH_W) '$(srcdir)/test_utils/test_utils.c'; fi` + +test_utils/bsdcpio_test-test_main.o: test_utils/test_main.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_utils/bsdcpio_test-test_main.o -MD -MP -MF test_utils/$(DEPDIR)/bsdcpio_test-test_main.Tpo -c -o test_utils/bsdcpio_test-test_main.o `test -f 'test_utils/test_main.c' || echo '$(srcdir)/'`test_utils/test_main.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) test_utils/$(DEPDIR)/bsdcpio_test-test_main.Tpo test_utils/$(DEPDIR)/bsdcpio_test-test_main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_utils/test_main.c' object='test_utils/bsdcpio_test-test_main.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_utils/bsdcpio_test-test_main.o `test -f 'test_utils/test_main.c' || echo '$(srcdir)/'`test_utils/test_main.c + +test_utils/bsdcpio_test-test_main.obj: test_utils/test_main.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_utils/bsdcpio_test-test_main.obj -MD -MP -MF test_utils/$(DEPDIR)/bsdcpio_test-test_main.Tpo -c -o test_utils/bsdcpio_test-test_main.obj `if test -f 'test_utils/test_main.c'; then $(CYGPATH_W) 'test_utils/test_main.c'; else $(CYGPATH_W) '$(srcdir)/test_utils/test_main.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) test_utils/$(DEPDIR)/bsdcpio_test-test_main.Tpo test_utils/$(DEPDIR)/bsdcpio_test-test_main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_utils/test_main.c' object='test_utils/bsdcpio_test-test_main.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_utils/bsdcpio_test-test_main.obj `if test -f 'test_utils/test_main.c'; then $(CYGPATH_W) 'test_utils/test_main.c'; else $(CYGPATH_W) '$(srcdir)/test_utils/test_main.c'; fi` + +cpio/bsdcpio_test-cmdline.o: cpio/cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/bsdcpio_test-cmdline.o -MD -MP -MF cpio/$(DEPDIR)/bsdcpio_test-cmdline.Tpo -c -o cpio/bsdcpio_test-cmdline.o `test -f 'cpio/cmdline.c' || echo '$(srcdir)/'`cpio/cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/$(DEPDIR)/bsdcpio_test-cmdline.Tpo cpio/$(DEPDIR)/bsdcpio_test-cmdline.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/cmdline.c' object='cpio/bsdcpio_test-cmdline.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/bsdcpio_test-cmdline.o `test -f 'cpio/cmdline.c' || echo '$(srcdir)/'`cpio/cmdline.c + +cpio/bsdcpio_test-cmdline.obj: cpio/cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/bsdcpio_test-cmdline.obj -MD -MP -MF cpio/$(DEPDIR)/bsdcpio_test-cmdline.Tpo -c -o cpio/bsdcpio_test-cmdline.obj `if test -f 'cpio/cmdline.c'; then $(CYGPATH_W) 'cpio/cmdline.c'; else $(CYGPATH_W) '$(srcdir)/cpio/cmdline.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/$(DEPDIR)/bsdcpio_test-cmdline.Tpo cpio/$(DEPDIR)/bsdcpio_test-cmdline.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/cmdline.c' object='cpio/bsdcpio_test-cmdline.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/bsdcpio_test-cmdline.obj `if test -f 'cpio/cmdline.c'; then $(CYGPATH_W) 'cpio/cmdline.c'; else $(CYGPATH_W) '$(srcdir)/cpio/cmdline.c'; fi` + +cpio/test/bsdcpio_test-test_0.o: cpio/test/test_0.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_0.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_0.Tpo -c -o cpio/test/bsdcpio_test-test_0.o `test -f 'cpio/test/test_0.c' || echo '$(srcdir)/'`cpio/test/test_0.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_0.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_0.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_0.c' object='cpio/test/bsdcpio_test-test_0.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_0.o `test -f 'cpio/test/test_0.c' || echo '$(srcdir)/'`cpio/test/test_0.c + +cpio/test/bsdcpio_test-test_0.obj: cpio/test/test_0.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_0.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_0.Tpo -c -o cpio/test/bsdcpio_test-test_0.obj `if test -f 'cpio/test/test_0.c'; then $(CYGPATH_W) 'cpio/test/test_0.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_0.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_0.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_0.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_0.c' object='cpio/test/bsdcpio_test-test_0.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_0.obj `if test -f 'cpio/test/test_0.c'; then $(CYGPATH_W) 'cpio/test/test_0.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_0.c'; fi` + +cpio/test/bsdcpio_test-test_basic.o: cpio/test/test_basic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_basic.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_basic.Tpo -c -o cpio/test/bsdcpio_test-test_basic.o `test -f 'cpio/test/test_basic.c' || echo '$(srcdir)/'`cpio/test/test_basic.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_basic.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_basic.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_basic.c' object='cpio/test/bsdcpio_test-test_basic.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_basic.o `test -f 'cpio/test/test_basic.c' || echo '$(srcdir)/'`cpio/test/test_basic.c + +cpio/test/bsdcpio_test-test_basic.obj: cpio/test/test_basic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_basic.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_basic.Tpo -c -o cpio/test/bsdcpio_test-test_basic.obj `if test -f 'cpio/test/test_basic.c'; then $(CYGPATH_W) 'cpio/test/test_basic.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_basic.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_basic.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_basic.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_basic.c' object='cpio/test/bsdcpio_test-test_basic.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_basic.obj `if test -f 'cpio/test/test_basic.c'; then $(CYGPATH_W) 'cpio/test/test_basic.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_basic.c'; fi` + +cpio/test/bsdcpio_test-test_cmdline.o: cpio/test/test_cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_cmdline.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_cmdline.Tpo -c -o cpio/test/bsdcpio_test-test_cmdline.o `test -f 'cpio/test/test_cmdline.c' || echo '$(srcdir)/'`cpio/test/test_cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_cmdline.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_cmdline.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_cmdline.c' object='cpio/test/bsdcpio_test-test_cmdline.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_cmdline.o `test -f 'cpio/test/test_cmdline.c' || echo '$(srcdir)/'`cpio/test/test_cmdline.c + +cpio/test/bsdcpio_test-test_cmdline.obj: cpio/test/test_cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_cmdline.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_cmdline.Tpo -c -o cpio/test/bsdcpio_test-test_cmdline.obj `if test -f 'cpio/test/test_cmdline.c'; then $(CYGPATH_W) 'cpio/test/test_cmdline.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_cmdline.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_cmdline.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_cmdline.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_cmdline.c' object='cpio/test/bsdcpio_test-test_cmdline.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_cmdline.obj `if test -f 'cpio/test/test_cmdline.c'; then $(CYGPATH_W) 'cpio/test/test_cmdline.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_cmdline.c'; fi` + +cpio/test/bsdcpio_test-test_extract_cpio_Z.o: cpio/test/test_extract_cpio_Z.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_extract_cpio_Z.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_Z.Tpo -c -o cpio/test/bsdcpio_test-test_extract_cpio_Z.o `test -f 'cpio/test/test_extract_cpio_Z.c' || echo '$(srcdir)/'`cpio/test/test_extract_cpio_Z.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_Z.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_Z.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_extract_cpio_Z.c' object='cpio/test/bsdcpio_test-test_extract_cpio_Z.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_extract_cpio_Z.o `test -f 'cpio/test/test_extract_cpio_Z.c' || echo '$(srcdir)/'`cpio/test/test_extract_cpio_Z.c + +cpio/test/bsdcpio_test-test_extract_cpio_Z.obj: cpio/test/test_extract_cpio_Z.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_extract_cpio_Z.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_Z.Tpo -c -o cpio/test/bsdcpio_test-test_extract_cpio_Z.obj `if test -f 'cpio/test/test_extract_cpio_Z.c'; then $(CYGPATH_W) 'cpio/test/test_extract_cpio_Z.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_extract_cpio_Z.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_Z.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_Z.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_extract_cpio_Z.c' object='cpio/test/bsdcpio_test-test_extract_cpio_Z.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_extract_cpio_Z.obj `if test -f 'cpio/test/test_extract_cpio_Z.c'; then $(CYGPATH_W) 'cpio/test/test_extract_cpio_Z.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_extract_cpio_Z.c'; fi` + +cpio/test/bsdcpio_test-test_extract_cpio_bz2.o: cpio/test/test_extract_cpio_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_extract_cpio_bz2.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_bz2.Tpo -c -o cpio/test/bsdcpio_test-test_extract_cpio_bz2.o `test -f 'cpio/test/test_extract_cpio_bz2.c' || echo '$(srcdir)/'`cpio/test/test_extract_cpio_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_bz2.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_bz2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_extract_cpio_bz2.c' object='cpio/test/bsdcpio_test-test_extract_cpio_bz2.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_extract_cpio_bz2.o `test -f 'cpio/test/test_extract_cpio_bz2.c' || echo '$(srcdir)/'`cpio/test/test_extract_cpio_bz2.c + +cpio/test/bsdcpio_test-test_extract_cpio_bz2.obj: cpio/test/test_extract_cpio_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_extract_cpio_bz2.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_bz2.Tpo -c -o cpio/test/bsdcpio_test-test_extract_cpio_bz2.obj `if test -f 'cpio/test/test_extract_cpio_bz2.c'; then $(CYGPATH_W) 'cpio/test/test_extract_cpio_bz2.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_extract_cpio_bz2.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_bz2.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_bz2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_extract_cpio_bz2.c' object='cpio/test/bsdcpio_test-test_extract_cpio_bz2.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_extract_cpio_bz2.obj `if test -f 'cpio/test/test_extract_cpio_bz2.c'; then $(CYGPATH_W) 'cpio/test/test_extract_cpio_bz2.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_extract_cpio_bz2.c'; fi` + +cpio/test/bsdcpio_test-test_extract_cpio_grz.o: cpio/test/test_extract_cpio_grz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_extract_cpio_grz.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_grz.Tpo -c -o cpio/test/bsdcpio_test-test_extract_cpio_grz.o `test -f 'cpio/test/test_extract_cpio_grz.c' || echo '$(srcdir)/'`cpio/test/test_extract_cpio_grz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_grz.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_grz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_extract_cpio_grz.c' object='cpio/test/bsdcpio_test-test_extract_cpio_grz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_extract_cpio_grz.o `test -f 'cpio/test/test_extract_cpio_grz.c' || echo '$(srcdir)/'`cpio/test/test_extract_cpio_grz.c + +cpio/test/bsdcpio_test-test_extract_cpio_grz.obj: cpio/test/test_extract_cpio_grz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_extract_cpio_grz.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_grz.Tpo -c -o cpio/test/bsdcpio_test-test_extract_cpio_grz.obj `if test -f 'cpio/test/test_extract_cpio_grz.c'; then $(CYGPATH_W) 'cpio/test/test_extract_cpio_grz.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_extract_cpio_grz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_grz.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_grz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_extract_cpio_grz.c' object='cpio/test/bsdcpio_test-test_extract_cpio_grz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_extract_cpio_grz.obj `if test -f 'cpio/test/test_extract_cpio_grz.c'; then $(CYGPATH_W) 'cpio/test/test_extract_cpio_grz.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_extract_cpio_grz.c'; fi` + +cpio/test/bsdcpio_test-test_extract_cpio_gz.o: cpio/test/test_extract_cpio_gz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_extract_cpio_gz.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_gz.Tpo -c -o cpio/test/bsdcpio_test-test_extract_cpio_gz.o `test -f 'cpio/test/test_extract_cpio_gz.c' || echo '$(srcdir)/'`cpio/test/test_extract_cpio_gz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_gz.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_gz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_extract_cpio_gz.c' object='cpio/test/bsdcpio_test-test_extract_cpio_gz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_extract_cpio_gz.o `test -f 'cpio/test/test_extract_cpio_gz.c' || echo '$(srcdir)/'`cpio/test/test_extract_cpio_gz.c + +cpio/test/bsdcpio_test-test_extract_cpio_gz.obj: cpio/test/test_extract_cpio_gz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_extract_cpio_gz.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_gz.Tpo -c -o cpio/test/bsdcpio_test-test_extract_cpio_gz.obj `if test -f 'cpio/test/test_extract_cpio_gz.c'; then $(CYGPATH_W) 'cpio/test/test_extract_cpio_gz.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_extract_cpio_gz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_gz.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_gz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_extract_cpio_gz.c' object='cpio/test/bsdcpio_test-test_extract_cpio_gz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_extract_cpio_gz.obj `if test -f 'cpio/test/test_extract_cpio_gz.c'; then $(CYGPATH_W) 'cpio/test/test_extract_cpio_gz.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_extract_cpio_gz.c'; fi` + +cpio/test/bsdcpio_test-test_extract_cpio_lrz.o: cpio/test/test_extract_cpio_lrz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_extract_cpio_lrz.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lrz.Tpo -c -o cpio/test/bsdcpio_test-test_extract_cpio_lrz.o `test -f 'cpio/test/test_extract_cpio_lrz.c' || echo '$(srcdir)/'`cpio/test/test_extract_cpio_lrz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lrz.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lrz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_extract_cpio_lrz.c' object='cpio/test/bsdcpio_test-test_extract_cpio_lrz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_extract_cpio_lrz.o `test -f 'cpio/test/test_extract_cpio_lrz.c' || echo '$(srcdir)/'`cpio/test/test_extract_cpio_lrz.c + +cpio/test/bsdcpio_test-test_extract_cpio_lrz.obj: cpio/test/test_extract_cpio_lrz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_extract_cpio_lrz.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lrz.Tpo -c -o cpio/test/bsdcpio_test-test_extract_cpio_lrz.obj `if test -f 'cpio/test/test_extract_cpio_lrz.c'; then $(CYGPATH_W) 'cpio/test/test_extract_cpio_lrz.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_extract_cpio_lrz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lrz.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lrz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_extract_cpio_lrz.c' object='cpio/test/bsdcpio_test-test_extract_cpio_lrz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_extract_cpio_lrz.obj `if test -f 'cpio/test/test_extract_cpio_lrz.c'; then $(CYGPATH_W) 'cpio/test/test_extract_cpio_lrz.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_extract_cpio_lrz.c'; fi` + +cpio/test/bsdcpio_test-test_extract_cpio_lz.o: cpio/test/test_extract_cpio_lz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_extract_cpio_lz.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lz.Tpo -c -o cpio/test/bsdcpio_test-test_extract_cpio_lz.o `test -f 'cpio/test/test_extract_cpio_lz.c' || echo '$(srcdir)/'`cpio/test/test_extract_cpio_lz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lz.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_extract_cpio_lz.c' object='cpio/test/bsdcpio_test-test_extract_cpio_lz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_extract_cpio_lz.o `test -f 'cpio/test/test_extract_cpio_lz.c' || echo '$(srcdir)/'`cpio/test/test_extract_cpio_lz.c + +cpio/test/bsdcpio_test-test_extract_cpio_lz.obj: cpio/test/test_extract_cpio_lz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_extract_cpio_lz.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lz.Tpo -c -o cpio/test/bsdcpio_test-test_extract_cpio_lz.obj `if test -f 'cpio/test/test_extract_cpio_lz.c'; then $(CYGPATH_W) 'cpio/test/test_extract_cpio_lz.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_extract_cpio_lz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lz.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_extract_cpio_lz.c' object='cpio/test/bsdcpio_test-test_extract_cpio_lz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_extract_cpio_lz.obj `if test -f 'cpio/test/test_extract_cpio_lz.c'; then $(CYGPATH_W) 'cpio/test/test_extract_cpio_lz.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_extract_cpio_lz.c'; fi` + +cpio/test/bsdcpio_test-test_extract_cpio_lz4.o: cpio/test/test_extract_cpio_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_extract_cpio_lz4.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lz4.Tpo -c -o cpio/test/bsdcpio_test-test_extract_cpio_lz4.o `test -f 'cpio/test/test_extract_cpio_lz4.c' || echo '$(srcdir)/'`cpio/test/test_extract_cpio_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lz4.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lz4.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_extract_cpio_lz4.c' object='cpio/test/bsdcpio_test-test_extract_cpio_lz4.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_extract_cpio_lz4.o `test -f 'cpio/test/test_extract_cpio_lz4.c' || echo '$(srcdir)/'`cpio/test/test_extract_cpio_lz4.c + +cpio/test/bsdcpio_test-test_extract_cpio_lz4.obj: cpio/test/test_extract_cpio_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_extract_cpio_lz4.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lz4.Tpo -c -o cpio/test/bsdcpio_test-test_extract_cpio_lz4.obj `if test -f 'cpio/test/test_extract_cpio_lz4.c'; then $(CYGPATH_W) 'cpio/test/test_extract_cpio_lz4.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_extract_cpio_lz4.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lz4.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lz4.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_extract_cpio_lz4.c' object='cpio/test/bsdcpio_test-test_extract_cpio_lz4.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_extract_cpio_lz4.obj `if test -f 'cpio/test/test_extract_cpio_lz4.c'; then $(CYGPATH_W) 'cpio/test/test_extract_cpio_lz4.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_extract_cpio_lz4.c'; fi` + +cpio/test/bsdcpio_test-test_extract_cpio_lzma.o: cpio/test/test_extract_cpio_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_extract_cpio_lzma.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lzma.Tpo -c -o cpio/test/bsdcpio_test-test_extract_cpio_lzma.o `test -f 'cpio/test/test_extract_cpio_lzma.c' || echo '$(srcdir)/'`cpio/test/test_extract_cpio_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lzma.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lzma.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_extract_cpio_lzma.c' object='cpio/test/bsdcpio_test-test_extract_cpio_lzma.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_extract_cpio_lzma.o `test -f 'cpio/test/test_extract_cpio_lzma.c' || echo '$(srcdir)/'`cpio/test/test_extract_cpio_lzma.c + +cpio/test/bsdcpio_test-test_extract_cpio_lzma.obj: cpio/test/test_extract_cpio_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_extract_cpio_lzma.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lzma.Tpo -c -o cpio/test/bsdcpio_test-test_extract_cpio_lzma.obj `if test -f 'cpio/test/test_extract_cpio_lzma.c'; then $(CYGPATH_W) 'cpio/test/test_extract_cpio_lzma.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_extract_cpio_lzma.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lzma.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lzma.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_extract_cpio_lzma.c' object='cpio/test/bsdcpio_test-test_extract_cpio_lzma.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_extract_cpio_lzma.obj `if test -f 'cpio/test/test_extract_cpio_lzma.c'; then $(CYGPATH_W) 'cpio/test/test_extract_cpio_lzma.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_extract_cpio_lzma.c'; fi` + +cpio/test/bsdcpio_test-test_extract_cpio_lzo.o: cpio/test/test_extract_cpio_lzo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_extract_cpio_lzo.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lzo.Tpo -c -o cpio/test/bsdcpio_test-test_extract_cpio_lzo.o `test -f 'cpio/test/test_extract_cpio_lzo.c' || echo '$(srcdir)/'`cpio/test/test_extract_cpio_lzo.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lzo.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lzo.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_extract_cpio_lzo.c' object='cpio/test/bsdcpio_test-test_extract_cpio_lzo.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_extract_cpio_lzo.o `test -f 'cpio/test/test_extract_cpio_lzo.c' || echo '$(srcdir)/'`cpio/test/test_extract_cpio_lzo.c + +cpio/test/bsdcpio_test-test_extract_cpio_lzo.obj: cpio/test/test_extract_cpio_lzo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_extract_cpio_lzo.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lzo.Tpo -c -o cpio/test/bsdcpio_test-test_extract_cpio_lzo.obj `if test -f 'cpio/test/test_extract_cpio_lzo.c'; then $(CYGPATH_W) 'cpio/test/test_extract_cpio_lzo.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_extract_cpio_lzo.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lzo.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_lzo.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_extract_cpio_lzo.c' object='cpio/test/bsdcpio_test-test_extract_cpio_lzo.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_extract_cpio_lzo.obj `if test -f 'cpio/test/test_extract_cpio_lzo.c'; then $(CYGPATH_W) 'cpio/test/test_extract_cpio_lzo.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_extract_cpio_lzo.c'; fi` + +cpio/test/bsdcpio_test-test_extract_cpio_xz.o: cpio/test/test_extract_cpio_xz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_extract_cpio_xz.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_xz.Tpo -c -o cpio/test/bsdcpio_test-test_extract_cpio_xz.o `test -f 'cpio/test/test_extract_cpio_xz.c' || echo '$(srcdir)/'`cpio/test/test_extract_cpio_xz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_xz.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_xz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_extract_cpio_xz.c' object='cpio/test/bsdcpio_test-test_extract_cpio_xz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_extract_cpio_xz.o `test -f 'cpio/test/test_extract_cpio_xz.c' || echo '$(srcdir)/'`cpio/test/test_extract_cpio_xz.c + +cpio/test/bsdcpio_test-test_extract_cpio_xz.obj: cpio/test/test_extract_cpio_xz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_extract_cpio_xz.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_xz.Tpo -c -o cpio/test/bsdcpio_test-test_extract_cpio_xz.obj `if test -f 'cpio/test/test_extract_cpio_xz.c'; then $(CYGPATH_W) 'cpio/test/test_extract_cpio_xz.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_extract_cpio_xz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_xz.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_xz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_extract_cpio_xz.c' object='cpio/test/bsdcpio_test-test_extract_cpio_xz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_extract_cpio_xz.obj `if test -f 'cpio/test/test_extract_cpio_xz.c'; then $(CYGPATH_W) 'cpio/test/test_extract_cpio_xz.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_extract_cpio_xz.c'; fi` + +cpio/test/bsdcpio_test-test_extract_cpio_zstd.o: cpio/test/test_extract_cpio_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_extract_cpio_zstd.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_zstd.Tpo -c -o cpio/test/bsdcpio_test-test_extract_cpio_zstd.o `test -f 'cpio/test/test_extract_cpio_zstd.c' || echo '$(srcdir)/'`cpio/test/test_extract_cpio_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_zstd.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_zstd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_extract_cpio_zstd.c' object='cpio/test/bsdcpio_test-test_extract_cpio_zstd.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_extract_cpio_zstd.o `test -f 'cpio/test/test_extract_cpio_zstd.c' || echo '$(srcdir)/'`cpio/test/test_extract_cpio_zstd.c + +cpio/test/bsdcpio_test-test_extract_cpio_zstd.obj: cpio/test/test_extract_cpio_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_extract_cpio_zstd.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_zstd.Tpo -c -o cpio/test/bsdcpio_test-test_extract_cpio_zstd.obj `if test -f 'cpio/test/test_extract_cpio_zstd.c'; then $(CYGPATH_W) 'cpio/test/test_extract_cpio_zstd.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_extract_cpio_zstd.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_zstd.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_extract_cpio_zstd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_extract_cpio_zstd.c' object='cpio/test/bsdcpio_test-test_extract_cpio_zstd.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_extract_cpio_zstd.obj `if test -f 'cpio/test/test_extract_cpio_zstd.c'; then $(CYGPATH_W) 'cpio/test/test_extract_cpio_zstd.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_extract_cpio_zstd.c'; fi` + +cpio/test/bsdcpio_test-test_format_newc.o: cpio/test/test_format_newc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_format_newc.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_format_newc.Tpo -c -o cpio/test/bsdcpio_test-test_format_newc.o `test -f 'cpio/test/test_format_newc.c' || echo '$(srcdir)/'`cpio/test/test_format_newc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_format_newc.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_format_newc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_format_newc.c' object='cpio/test/bsdcpio_test-test_format_newc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_format_newc.o `test -f 'cpio/test/test_format_newc.c' || echo '$(srcdir)/'`cpio/test/test_format_newc.c + +cpio/test/bsdcpio_test-test_format_newc.obj: cpio/test/test_format_newc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_format_newc.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_format_newc.Tpo -c -o cpio/test/bsdcpio_test-test_format_newc.obj `if test -f 'cpio/test/test_format_newc.c'; then $(CYGPATH_W) 'cpio/test/test_format_newc.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_format_newc.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_format_newc.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_format_newc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_format_newc.c' object='cpio/test/bsdcpio_test-test_format_newc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_format_newc.obj `if test -f 'cpio/test/test_format_newc.c'; then $(CYGPATH_W) 'cpio/test/test_format_newc.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_format_newc.c'; fi` + +cpio/test/bsdcpio_test-test_gcpio_compat.o: cpio/test/test_gcpio_compat.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_gcpio_compat.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_gcpio_compat.Tpo -c -o cpio/test/bsdcpio_test-test_gcpio_compat.o `test -f 'cpio/test/test_gcpio_compat.c' || echo '$(srcdir)/'`cpio/test/test_gcpio_compat.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_gcpio_compat.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_gcpio_compat.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_gcpio_compat.c' object='cpio/test/bsdcpio_test-test_gcpio_compat.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_gcpio_compat.o `test -f 'cpio/test/test_gcpio_compat.c' || echo '$(srcdir)/'`cpio/test/test_gcpio_compat.c + +cpio/test/bsdcpio_test-test_gcpio_compat.obj: cpio/test/test_gcpio_compat.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_gcpio_compat.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_gcpio_compat.Tpo -c -o cpio/test/bsdcpio_test-test_gcpio_compat.obj `if test -f 'cpio/test/test_gcpio_compat.c'; then $(CYGPATH_W) 'cpio/test/test_gcpio_compat.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_gcpio_compat.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_gcpio_compat.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_gcpio_compat.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_gcpio_compat.c' object='cpio/test/bsdcpio_test-test_gcpio_compat.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_gcpio_compat.obj `if test -f 'cpio/test/test_gcpio_compat.c'; then $(CYGPATH_W) 'cpio/test/test_gcpio_compat.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_gcpio_compat.c'; fi` + +cpio/test/bsdcpio_test-test_missing_file.o: cpio/test/test_missing_file.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_missing_file.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_missing_file.Tpo -c -o cpio/test/bsdcpio_test-test_missing_file.o `test -f 'cpio/test/test_missing_file.c' || echo '$(srcdir)/'`cpio/test/test_missing_file.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_missing_file.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_missing_file.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_missing_file.c' object='cpio/test/bsdcpio_test-test_missing_file.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_missing_file.o `test -f 'cpio/test/test_missing_file.c' || echo '$(srcdir)/'`cpio/test/test_missing_file.c + +cpio/test/bsdcpio_test-test_missing_file.obj: cpio/test/test_missing_file.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_missing_file.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_missing_file.Tpo -c -o cpio/test/bsdcpio_test-test_missing_file.obj `if test -f 'cpio/test/test_missing_file.c'; then $(CYGPATH_W) 'cpio/test/test_missing_file.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_missing_file.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_missing_file.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_missing_file.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_missing_file.c' object='cpio/test/bsdcpio_test-test_missing_file.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_missing_file.obj `if test -f 'cpio/test/test_missing_file.c'; then $(CYGPATH_W) 'cpio/test/test_missing_file.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_missing_file.c'; fi` + +cpio/test/bsdcpio_test-test_option_0.o: cpio/test/test_option_0.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_0.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_0.Tpo -c -o cpio/test/bsdcpio_test-test_option_0.o `test -f 'cpio/test/test_option_0.c' || echo '$(srcdir)/'`cpio/test/test_option_0.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_0.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_0.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_0.c' object='cpio/test/bsdcpio_test-test_option_0.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_0.o `test -f 'cpio/test/test_option_0.c' || echo '$(srcdir)/'`cpio/test/test_option_0.c + +cpio/test/bsdcpio_test-test_option_0.obj: cpio/test/test_option_0.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_0.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_0.Tpo -c -o cpio/test/bsdcpio_test-test_option_0.obj `if test -f 'cpio/test/test_option_0.c'; then $(CYGPATH_W) 'cpio/test/test_option_0.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_0.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_0.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_0.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_0.c' object='cpio/test/bsdcpio_test-test_option_0.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_0.obj `if test -f 'cpio/test/test_option_0.c'; then $(CYGPATH_W) 'cpio/test/test_option_0.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_0.c'; fi` + +cpio/test/bsdcpio_test-test_option_B_upper.o: cpio/test/test_option_B_upper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_B_upper.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_B_upper.Tpo -c -o cpio/test/bsdcpio_test-test_option_B_upper.o `test -f 'cpio/test/test_option_B_upper.c' || echo '$(srcdir)/'`cpio/test/test_option_B_upper.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_B_upper.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_B_upper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_B_upper.c' object='cpio/test/bsdcpio_test-test_option_B_upper.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_B_upper.o `test -f 'cpio/test/test_option_B_upper.c' || echo '$(srcdir)/'`cpio/test/test_option_B_upper.c + +cpio/test/bsdcpio_test-test_option_B_upper.obj: cpio/test/test_option_B_upper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_B_upper.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_B_upper.Tpo -c -o cpio/test/bsdcpio_test-test_option_B_upper.obj `if test -f 'cpio/test/test_option_B_upper.c'; then $(CYGPATH_W) 'cpio/test/test_option_B_upper.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_B_upper.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_B_upper.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_B_upper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_B_upper.c' object='cpio/test/bsdcpio_test-test_option_B_upper.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_B_upper.obj `if test -f 'cpio/test/test_option_B_upper.c'; then $(CYGPATH_W) 'cpio/test/test_option_B_upper.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_B_upper.c'; fi` + +cpio/test/bsdcpio_test-test_option_C_upper.o: cpio/test/test_option_C_upper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_C_upper.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_C_upper.Tpo -c -o cpio/test/bsdcpio_test-test_option_C_upper.o `test -f 'cpio/test/test_option_C_upper.c' || echo '$(srcdir)/'`cpio/test/test_option_C_upper.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_C_upper.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_C_upper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_C_upper.c' object='cpio/test/bsdcpio_test-test_option_C_upper.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_C_upper.o `test -f 'cpio/test/test_option_C_upper.c' || echo '$(srcdir)/'`cpio/test/test_option_C_upper.c + +cpio/test/bsdcpio_test-test_option_C_upper.obj: cpio/test/test_option_C_upper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_C_upper.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_C_upper.Tpo -c -o cpio/test/bsdcpio_test-test_option_C_upper.obj `if test -f 'cpio/test/test_option_C_upper.c'; then $(CYGPATH_W) 'cpio/test/test_option_C_upper.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_C_upper.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_C_upper.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_C_upper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_C_upper.c' object='cpio/test/bsdcpio_test-test_option_C_upper.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_C_upper.obj `if test -f 'cpio/test/test_option_C_upper.c'; then $(CYGPATH_W) 'cpio/test/test_option_C_upper.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_C_upper.c'; fi` + +cpio/test/bsdcpio_test-test_option_J_upper.o: cpio/test/test_option_J_upper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_J_upper.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_J_upper.Tpo -c -o cpio/test/bsdcpio_test-test_option_J_upper.o `test -f 'cpio/test/test_option_J_upper.c' || echo '$(srcdir)/'`cpio/test/test_option_J_upper.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_J_upper.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_J_upper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_J_upper.c' object='cpio/test/bsdcpio_test-test_option_J_upper.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_J_upper.o `test -f 'cpio/test/test_option_J_upper.c' || echo '$(srcdir)/'`cpio/test/test_option_J_upper.c + +cpio/test/bsdcpio_test-test_option_J_upper.obj: cpio/test/test_option_J_upper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_J_upper.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_J_upper.Tpo -c -o cpio/test/bsdcpio_test-test_option_J_upper.obj `if test -f 'cpio/test/test_option_J_upper.c'; then $(CYGPATH_W) 'cpio/test/test_option_J_upper.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_J_upper.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_J_upper.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_J_upper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_J_upper.c' object='cpio/test/bsdcpio_test-test_option_J_upper.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_J_upper.obj `if test -f 'cpio/test/test_option_J_upper.c'; then $(CYGPATH_W) 'cpio/test/test_option_J_upper.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_J_upper.c'; fi` + +cpio/test/bsdcpio_test-test_option_L_upper.o: cpio/test/test_option_L_upper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_L_upper.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_L_upper.Tpo -c -o cpio/test/bsdcpio_test-test_option_L_upper.o `test -f 'cpio/test/test_option_L_upper.c' || echo '$(srcdir)/'`cpio/test/test_option_L_upper.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_L_upper.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_L_upper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_L_upper.c' object='cpio/test/bsdcpio_test-test_option_L_upper.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_L_upper.o `test -f 'cpio/test/test_option_L_upper.c' || echo '$(srcdir)/'`cpio/test/test_option_L_upper.c + +cpio/test/bsdcpio_test-test_option_L_upper.obj: cpio/test/test_option_L_upper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_L_upper.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_L_upper.Tpo -c -o cpio/test/bsdcpio_test-test_option_L_upper.obj `if test -f 'cpio/test/test_option_L_upper.c'; then $(CYGPATH_W) 'cpio/test/test_option_L_upper.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_L_upper.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_L_upper.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_L_upper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_L_upper.c' object='cpio/test/bsdcpio_test-test_option_L_upper.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_L_upper.obj `if test -f 'cpio/test/test_option_L_upper.c'; then $(CYGPATH_W) 'cpio/test/test_option_L_upper.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_L_upper.c'; fi` + +cpio/test/bsdcpio_test-test_option_Z_upper.o: cpio/test/test_option_Z_upper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_Z_upper.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_Z_upper.Tpo -c -o cpio/test/bsdcpio_test-test_option_Z_upper.o `test -f 'cpio/test/test_option_Z_upper.c' || echo '$(srcdir)/'`cpio/test/test_option_Z_upper.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_Z_upper.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_Z_upper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_Z_upper.c' object='cpio/test/bsdcpio_test-test_option_Z_upper.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_Z_upper.o `test -f 'cpio/test/test_option_Z_upper.c' || echo '$(srcdir)/'`cpio/test/test_option_Z_upper.c + +cpio/test/bsdcpio_test-test_option_Z_upper.obj: cpio/test/test_option_Z_upper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_Z_upper.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_Z_upper.Tpo -c -o cpio/test/bsdcpio_test-test_option_Z_upper.obj `if test -f 'cpio/test/test_option_Z_upper.c'; then $(CYGPATH_W) 'cpio/test/test_option_Z_upper.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_Z_upper.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_Z_upper.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_Z_upper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_Z_upper.c' object='cpio/test/bsdcpio_test-test_option_Z_upper.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_Z_upper.obj `if test -f 'cpio/test/test_option_Z_upper.c'; then $(CYGPATH_W) 'cpio/test/test_option_Z_upper.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_Z_upper.c'; fi` + +cpio/test/bsdcpio_test-test_option_a.o: cpio/test/test_option_a.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_a.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_a.Tpo -c -o cpio/test/bsdcpio_test-test_option_a.o `test -f 'cpio/test/test_option_a.c' || echo '$(srcdir)/'`cpio/test/test_option_a.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_a.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_a.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_a.c' object='cpio/test/bsdcpio_test-test_option_a.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_a.o `test -f 'cpio/test/test_option_a.c' || echo '$(srcdir)/'`cpio/test/test_option_a.c + +cpio/test/bsdcpio_test-test_option_a.obj: cpio/test/test_option_a.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_a.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_a.Tpo -c -o cpio/test/bsdcpio_test-test_option_a.obj `if test -f 'cpio/test/test_option_a.c'; then $(CYGPATH_W) 'cpio/test/test_option_a.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_a.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_a.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_a.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_a.c' object='cpio/test/bsdcpio_test-test_option_a.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_a.obj `if test -f 'cpio/test/test_option_a.c'; then $(CYGPATH_W) 'cpio/test/test_option_a.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_a.c'; fi` + +cpio/test/bsdcpio_test-test_option_b64encode.o: cpio/test/test_option_b64encode.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_b64encode.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_b64encode.Tpo -c -o cpio/test/bsdcpio_test-test_option_b64encode.o `test -f 'cpio/test/test_option_b64encode.c' || echo '$(srcdir)/'`cpio/test/test_option_b64encode.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_b64encode.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_b64encode.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_b64encode.c' object='cpio/test/bsdcpio_test-test_option_b64encode.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_b64encode.o `test -f 'cpio/test/test_option_b64encode.c' || echo '$(srcdir)/'`cpio/test/test_option_b64encode.c + +cpio/test/bsdcpio_test-test_option_b64encode.obj: cpio/test/test_option_b64encode.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_b64encode.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_b64encode.Tpo -c -o cpio/test/bsdcpio_test-test_option_b64encode.obj `if test -f 'cpio/test/test_option_b64encode.c'; then $(CYGPATH_W) 'cpio/test/test_option_b64encode.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_b64encode.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_b64encode.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_b64encode.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_b64encode.c' object='cpio/test/bsdcpio_test-test_option_b64encode.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_b64encode.obj `if test -f 'cpio/test/test_option_b64encode.c'; then $(CYGPATH_W) 'cpio/test/test_option_b64encode.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_b64encode.c'; fi` + +cpio/test/bsdcpio_test-test_option_c.o: cpio/test/test_option_c.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_c.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_c.Tpo -c -o cpio/test/bsdcpio_test-test_option_c.o `test -f 'cpio/test/test_option_c.c' || echo '$(srcdir)/'`cpio/test/test_option_c.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_c.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_c.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_c.c' object='cpio/test/bsdcpio_test-test_option_c.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_c.o `test -f 'cpio/test/test_option_c.c' || echo '$(srcdir)/'`cpio/test/test_option_c.c + +cpio/test/bsdcpio_test-test_option_c.obj: cpio/test/test_option_c.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_c.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_c.Tpo -c -o cpio/test/bsdcpio_test-test_option_c.obj `if test -f 'cpio/test/test_option_c.c'; then $(CYGPATH_W) 'cpio/test/test_option_c.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_c.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_c.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_c.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_c.c' object='cpio/test/bsdcpio_test-test_option_c.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_c.obj `if test -f 'cpio/test/test_option_c.c'; then $(CYGPATH_W) 'cpio/test/test_option_c.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_c.c'; fi` + +cpio/test/bsdcpio_test-test_option_d.o: cpio/test/test_option_d.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_d.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_d.Tpo -c -o cpio/test/bsdcpio_test-test_option_d.o `test -f 'cpio/test/test_option_d.c' || echo '$(srcdir)/'`cpio/test/test_option_d.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_d.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_d.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_d.c' object='cpio/test/bsdcpio_test-test_option_d.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_d.o `test -f 'cpio/test/test_option_d.c' || echo '$(srcdir)/'`cpio/test/test_option_d.c + +cpio/test/bsdcpio_test-test_option_d.obj: cpio/test/test_option_d.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_d.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_d.Tpo -c -o cpio/test/bsdcpio_test-test_option_d.obj `if test -f 'cpio/test/test_option_d.c'; then $(CYGPATH_W) 'cpio/test/test_option_d.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_d.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_d.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_d.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_d.c' object='cpio/test/bsdcpio_test-test_option_d.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_d.obj `if test -f 'cpio/test/test_option_d.c'; then $(CYGPATH_W) 'cpio/test/test_option_d.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_d.c'; fi` + +cpio/test/bsdcpio_test-test_option_f.o: cpio/test/test_option_f.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_f.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_f.Tpo -c -o cpio/test/bsdcpio_test-test_option_f.o `test -f 'cpio/test/test_option_f.c' || echo '$(srcdir)/'`cpio/test/test_option_f.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_f.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_f.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_f.c' object='cpio/test/bsdcpio_test-test_option_f.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_f.o `test -f 'cpio/test/test_option_f.c' || echo '$(srcdir)/'`cpio/test/test_option_f.c + +cpio/test/bsdcpio_test-test_option_f.obj: cpio/test/test_option_f.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_f.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_f.Tpo -c -o cpio/test/bsdcpio_test-test_option_f.obj `if test -f 'cpio/test/test_option_f.c'; then $(CYGPATH_W) 'cpio/test/test_option_f.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_f.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_f.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_f.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_f.c' object='cpio/test/bsdcpio_test-test_option_f.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_f.obj `if test -f 'cpio/test/test_option_f.c'; then $(CYGPATH_W) 'cpio/test/test_option_f.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_f.c'; fi` + +cpio/test/bsdcpio_test-test_option_grzip.o: cpio/test/test_option_grzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_grzip.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_grzip.Tpo -c -o cpio/test/bsdcpio_test-test_option_grzip.o `test -f 'cpio/test/test_option_grzip.c' || echo '$(srcdir)/'`cpio/test/test_option_grzip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_grzip.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_grzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_grzip.c' object='cpio/test/bsdcpio_test-test_option_grzip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_grzip.o `test -f 'cpio/test/test_option_grzip.c' || echo '$(srcdir)/'`cpio/test/test_option_grzip.c + +cpio/test/bsdcpio_test-test_option_grzip.obj: cpio/test/test_option_grzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_grzip.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_grzip.Tpo -c -o cpio/test/bsdcpio_test-test_option_grzip.obj `if test -f 'cpio/test/test_option_grzip.c'; then $(CYGPATH_W) 'cpio/test/test_option_grzip.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_grzip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_grzip.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_grzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_grzip.c' object='cpio/test/bsdcpio_test-test_option_grzip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_grzip.obj `if test -f 'cpio/test/test_option_grzip.c'; then $(CYGPATH_W) 'cpio/test/test_option_grzip.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_grzip.c'; fi` + +cpio/test/bsdcpio_test-test_option_help.o: cpio/test/test_option_help.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_help.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_help.Tpo -c -o cpio/test/bsdcpio_test-test_option_help.o `test -f 'cpio/test/test_option_help.c' || echo '$(srcdir)/'`cpio/test/test_option_help.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_help.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_help.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_help.c' object='cpio/test/bsdcpio_test-test_option_help.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_help.o `test -f 'cpio/test/test_option_help.c' || echo '$(srcdir)/'`cpio/test/test_option_help.c + +cpio/test/bsdcpio_test-test_option_help.obj: cpio/test/test_option_help.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_help.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_help.Tpo -c -o cpio/test/bsdcpio_test-test_option_help.obj `if test -f 'cpio/test/test_option_help.c'; then $(CYGPATH_W) 'cpio/test/test_option_help.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_help.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_help.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_help.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_help.c' object='cpio/test/bsdcpio_test-test_option_help.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_help.obj `if test -f 'cpio/test/test_option_help.c'; then $(CYGPATH_W) 'cpio/test/test_option_help.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_help.c'; fi` + +cpio/test/bsdcpio_test-test_option_l.o: cpio/test/test_option_l.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_l.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_l.Tpo -c -o cpio/test/bsdcpio_test-test_option_l.o `test -f 'cpio/test/test_option_l.c' || echo '$(srcdir)/'`cpio/test/test_option_l.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_l.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_l.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_l.c' object='cpio/test/bsdcpio_test-test_option_l.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_l.o `test -f 'cpio/test/test_option_l.c' || echo '$(srcdir)/'`cpio/test/test_option_l.c + +cpio/test/bsdcpio_test-test_option_l.obj: cpio/test/test_option_l.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_l.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_l.Tpo -c -o cpio/test/bsdcpio_test-test_option_l.obj `if test -f 'cpio/test/test_option_l.c'; then $(CYGPATH_W) 'cpio/test/test_option_l.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_l.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_l.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_l.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_l.c' object='cpio/test/bsdcpio_test-test_option_l.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_l.obj `if test -f 'cpio/test/test_option_l.c'; then $(CYGPATH_W) 'cpio/test/test_option_l.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_l.c'; fi` + +cpio/test/bsdcpio_test-test_option_lrzip.o: cpio/test/test_option_lrzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_lrzip.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lrzip.Tpo -c -o cpio/test/bsdcpio_test-test_option_lrzip.o `test -f 'cpio/test/test_option_lrzip.c' || echo '$(srcdir)/'`cpio/test/test_option_lrzip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lrzip.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lrzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_lrzip.c' object='cpio/test/bsdcpio_test-test_option_lrzip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_lrzip.o `test -f 'cpio/test/test_option_lrzip.c' || echo '$(srcdir)/'`cpio/test/test_option_lrzip.c + +cpio/test/bsdcpio_test-test_option_lrzip.obj: cpio/test/test_option_lrzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_lrzip.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lrzip.Tpo -c -o cpio/test/bsdcpio_test-test_option_lrzip.obj `if test -f 'cpio/test/test_option_lrzip.c'; then $(CYGPATH_W) 'cpio/test/test_option_lrzip.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_lrzip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lrzip.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lrzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_lrzip.c' object='cpio/test/bsdcpio_test-test_option_lrzip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_lrzip.obj `if test -f 'cpio/test/test_option_lrzip.c'; then $(CYGPATH_W) 'cpio/test/test_option_lrzip.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_lrzip.c'; fi` + +cpio/test/bsdcpio_test-test_option_lz4.o: cpio/test/test_option_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_lz4.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lz4.Tpo -c -o cpio/test/bsdcpio_test-test_option_lz4.o `test -f 'cpio/test/test_option_lz4.c' || echo '$(srcdir)/'`cpio/test/test_option_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lz4.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lz4.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_lz4.c' object='cpio/test/bsdcpio_test-test_option_lz4.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_lz4.o `test -f 'cpio/test/test_option_lz4.c' || echo '$(srcdir)/'`cpio/test/test_option_lz4.c + +cpio/test/bsdcpio_test-test_option_lz4.obj: cpio/test/test_option_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_lz4.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lz4.Tpo -c -o cpio/test/bsdcpio_test-test_option_lz4.obj `if test -f 'cpio/test/test_option_lz4.c'; then $(CYGPATH_W) 'cpio/test/test_option_lz4.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_lz4.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lz4.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lz4.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_lz4.c' object='cpio/test/bsdcpio_test-test_option_lz4.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_lz4.obj `if test -f 'cpio/test/test_option_lz4.c'; then $(CYGPATH_W) 'cpio/test/test_option_lz4.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_lz4.c'; fi` + +cpio/test/bsdcpio_test-test_option_lzma.o: cpio/test/test_option_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_lzma.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lzma.Tpo -c -o cpio/test/bsdcpio_test-test_option_lzma.o `test -f 'cpio/test/test_option_lzma.c' || echo '$(srcdir)/'`cpio/test/test_option_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lzma.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lzma.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_lzma.c' object='cpio/test/bsdcpio_test-test_option_lzma.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_lzma.o `test -f 'cpio/test/test_option_lzma.c' || echo '$(srcdir)/'`cpio/test/test_option_lzma.c + +cpio/test/bsdcpio_test-test_option_lzma.obj: cpio/test/test_option_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_lzma.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lzma.Tpo -c -o cpio/test/bsdcpio_test-test_option_lzma.obj `if test -f 'cpio/test/test_option_lzma.c'; then $(CYGPATH_W) 'cpio/test/test_option_lzma.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_lzma.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lzma.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lzma.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_lzma.c' object='cpio/test/bsdcpio_test-test_option_lzma.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_lzma.obj `if test -f 'cpio/test/test_option_lzma.c'; then $(CYGPATH_W) 'cpio/test/test_option_lzma.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_lzma.c'; fi` + +cpio/test/bsdcpio_test-test_option_lzop.o: cpio/test/test_option_lzop.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_lzop.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lzop.Tpo -c -o cpio/test/bsdcpio_test-test_option_lzop.o `test -f 'cpio/test/test_option_lzop.c' || echo '$(srcdir)/'`cpio/test/test_option_lzop.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lzop.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lzop.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_lzop.c' object='cpio/test/bsdcpio_test-test_option_lzop.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_lzop.o `test -f 'cpio/test/test_option_lzop.c' || echo '$(srcdir)/'`cpio/test/test_option_lzop.c + +cpio/test/bsdcpio_test-test_option_lzop.obj: cpio/test/test_option_lzop.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_lzop.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lzop.Tpo -c -o cpio/test/bsdcpio_test-test_option_lzop.obj `if test -f 'cpio/test/test_option_lzop.c'; then $(CYGPATH_W) 'cpio/test/test_option_lzop.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_lzop.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lzop.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_lzop.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_lzop.c' object='cpio/test/bsdcpio_test-test_option_lzop.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_lzop.obj `if test -f 'cpio/test/test_option_lzop.c'; then $(CYGPATH_W) 'cpio/test/test_option_lzop.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_lzop.c'; fi` + +cpio/test/bsdcpio_test-test_option_m.o: cpio/test/test_option_m.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_m.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_m.Tpo -c -o cpio/test/bsdcpio_test-test_option_m.o `test -f 'cpio/test/test_option_m.c' || echo '$(srcdir)/'`cpio/test/test_option_m.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_m.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_m.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_m.c' object='cpio/test/bsdcpio_test-test_option_m.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_m.o `test -f 'cpio/test/test_option_m.c' || echo '$(srcdir)/'`cpio/test/test_option_m.c + +cpio/test/bsdcpio_test-test_option_m.obj: cpio/test/test_option_m.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_m.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_m.Tpo -c -o cpio/test/bsdcpio_test-test_option_m.obj `if test -f 'cpio/test/test_option_m.c'; then $(CYGPATH_W) 'cpio/test/test_option_m.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_m.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_m.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_m.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_m.c' object='cpio/test/bsdcpio_test-test_option_m.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_m.obj `if test -f 'cpio/test/test_option_m.c'; then $(CYGPATH_W) 'cpio/test/test_option_m.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_m.c'; fi` + +cpio/test/bsdcpio_test-test_option_passphrase.o: cpio/test/test_option_passphrase.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_passphrase.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_passphrase.Tpo -c -o cpio/test/bsdcpio_test-test_option_passphrase.o `test -f 'cpio/test/test_option_passphrase.c' || echo '$(srcdir)/'`cpio/test/test_option_passphrase.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_passphrase.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_passphrase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_passphrase.c' object='cpio/test/bsdcpio_test-test_option_passphrase.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_passphrase.o `test -f 'cpio/test/test_option_passphrase.c' || echo '$(srcdir)/'`cpio/test/test_option_passphrase.c + +cpio/test/bsdcpio_test-test_option_passphrase.obj: cpio/test/test_option_passphrase.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_passphrase.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_passphrase.Tpo -c -o cpio/test/bsdcpio_test-test_option_passphrase.obj `if test -f 'cpio/test/test_option_passphrase.c'; then $(CYGPATH_W) 'cpio/test/test_option_passphrase.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_passphrase.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_passphrase.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_passphrase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_passphrase.c' object='cpio/test/bsdcpio_test-test_option_passphrase.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_passphrase.obj `if test -f 'cpio/test/test_option_passphrase.c'; then $(CYGPATH_W) 'cpio/test/test_option_passphrase.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_passphrase.c'; fi` + +cpio/test/bsdcpio_test-test_option_t.o: cpio/test/test_option_t.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_t.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_t.Tpo -c -o cpio/test/bsdcpio_test-test_option_t.o `test -f 'cpio/test/test_option_t.c' || echo '$(srcdir)/'`cpio/test/test_option_t.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_t.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_t.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_t.c' object='cpio/test/bsdcpio_test-test_option_t.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_t.o `test -f 'cpio/test/test_option_t.c' || echo '$(srcdir)/'`cpio/test/test_option_t.c + +cpio/test/bsdcpio_test-test_option_t.obj: cpio/test/test_option_t.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_t.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_t.Tpo -c -o cpio/test/bsdcpio_test-test_option_t.obj `if test -f 'cpio/test/test_option_t.c'; then $(CYGPATH_W) 'cpio/test/test_option_t.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_t.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_t.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_t.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_t.c' object='cpio/test/bsdcpio_test-test_option_t.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_t.obj `if test -f 'cpio/test/test_option_t.c'; then $(CYGPATH_W) 'cpio/test/test_option_t.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_t.c'; fi` + +cpio/test/bsdcpio_test-test_option_u.o: cpio/test/test_option_u.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_u.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_u.Tpo -c -o cpio/test/bsdcpio_test-test_option_u.o `test -f 'cpio/test/test_option_u.c' || echo '$(srcdir)/'`cpio/test/test_option_u.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_u.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_u.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_u.c' object='cpio/test/bsdcpio_test-test_option_u.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_u.o `test -f 'cpio/test/test_option_u.c' || echo '$(srcdir)/'`cpio/test/test_option_u.c + +cpio/test/bsdcpio_test-test_option_u.obj: cpio/test/test_option_u.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_u.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_u.Tpo -c -o cpio/test/bsdcpio_test-test_option_u.obj `if test -f 'cpio/test/test_option_u.c'; then $(CYGPATH_W) 'cpio/test/test_option_u.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_u.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_u.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_u.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_u.c' object='cpio/test/bsdcpio_test-test_option_u.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_u.obj `if test -f 'cpio/test/test_option_u.c'; then $(CYGPATH_W) 'cpio/test/test_option_u.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_u.c'; fi` + +cpio/test/bsdcpio_test-test_option_uuencode.o: cpio/test/test_option_uuencode.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_uuencode.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_uuencode.Tpo -c -o cpio/test/bsdcpio_test-test_option_uuencode.o `test -f 'cpio/test/test_option_uuencode.c' || echo '$(srcdir)/'`cpio/test/test_option_uuencode.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_uuencode.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_uuencode.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_uuencode.c' object='cpio/test/bsdcpio_test-test_option_uuencode.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_uuencode.o `test -f 'cpio/test/test_option_uuencode.c' || echo '$(srcdir)/'`cpio/test/test_option_uuencode.c + +cpio/test/bsdcpio_test-test_option_uuencode.obj: cpio/test/test_option_uuencode.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_uuencode.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_uuencode.Tpo -c -o cpio/test/bsdcpio_test-test_option_uuencode.obj `if test -f 'cpio/test/test_option_uuencode.c'; then $(CYGPATH_W) 'cpio/test/test_option_uuencode.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_uuencode.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_uuencode.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_uuencode.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_uuencode.c' object='cpio/test/bsdcpio_test-test_option_uuencode.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_uuencode.obj `if test -f 'cpio/test/test_option_uuencode.c'; then $(CYGPATH_W) 'cpio/test/test_option_uuencode.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_uuencode.c'; fi` + +cpio/test/bsdcpio_test-test_option_version.o: cpio/test/test_option_version.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_version.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_version.Tpo -c -o cpio/test/bsdcpio_test-test_option_version.o `test -f 'cpio/test/test_option_version.c' || echo '$(srcdir)/'`cpio/test/test_option_version.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_version.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_version.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_version.c' object='cpio/test/bsdcpio_test-test_option_version.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_version.o `test -f 'cpio/test/test_option_version.c' || echo '$(srcdir)/'`cpio/test/test_option_version.c + +cpio/test/bsdcpio_test-test_option_version.obj: cpio/test/test_option_version.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_version.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_version.Tpo -c -o cpio/test/bsdcpio_test-test_option_version.obj `if test -f 'cpio/test/test_option_version.c'; then $(CYGPATH_W) 'cpio/test/test_option_version.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_version.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_version.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_version.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_version.c' object='cpio/test/bsdcpio_test-test_option_version.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_version.obj `if test -f 'cpio/test/test_option_version.c'; then $(CYGPATH_W) 'cpio/test/test_option_version.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_version.c'; fi` + +cpio/test/bsdcpio_test-test_option_xz.o: cpio/test/test_option_xz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_xz.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_xz.Tpo -c -o cpio/test/bsdcpio_test-test_option_xz.o `test -f 'cpio/test/test_option_xz.c' || echo '$(srcdir)/'`cpio/test/test_option_xz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_xz.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_xz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_xz.c' object='cpio/test/bsdcpio_test-test_option_xz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_xz.o `test -f 'cpio/test/test_option_xz.c' || echo '$(srcdir)/'`cpio/test/test_option_xz.c + +cpio/test/bsdcpio_test-test_option_xz.obj: cpio/test/test_option_xz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_xz.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_xz.Tpo -c -o cpio/test/bsdcpio_test-test_option_xz.obj `if test -f 'cpio/test/test_option_xz.c'; then $(CYGPATH_W) 'cpio/test/test_option_xz.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_xz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_xz.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_xz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_xz.c' object='cpio/test/bsdcpio_test-test_option_xz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_xz.obj `if test -f 'cpio/test/test_option_xz.c'; then $(CYGPATH_W) 'cpio/test/test_option_xz.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_xz.c'; fi` + +cpio/test/bsdcpio_test-test_option_y.o: cpio/test/test_option_y.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_y.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_y.Tpo -c -o cpio/test/bsdcpio_test-test_option_y.o `test -f 'cpio/test/test_option_y.c' || echo '$(srcdir)/'`cpio/test/test_option_y.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_y.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_y.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_y.c' object='cpio/test/bsdcpio_test-test_option_y.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_y.o `test -f 'cpio/test/test_option_y.c' || echo '$(srcdir)/'`cpio/test/test_option_y.c + +cpio/test/bsdcpio_test-test_option_y.obj: cpio/test/test_option_y.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_y.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_y.Tpo -c -o cpio/test/bsdcpio_test-test_option_y.obj `if test -f 'cpio/test/test_option_y.c'; then $(CYGPATH_W) 'cpio/test/test_option_y.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_y.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_y.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_y.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_y.c' object='cpio/test/bsdcpio_test-test_option_y.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_y.obj `if test -f 'cpio/test/test_option_y.c'; then $(CYGPATH_W) 'cpio/test/test_option_y.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_y.c'; fi` + +cpio/test/bsdcpio_test-test_option_z.o: cpio/test/test_option_z.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_z.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_z.Tpo -c -o cpio/test/bsdcpio_test-test_option_z.o `test -f 'cpio/test/test_option_z.c' || echo '$(srcdir)/'`cpio/test/test_option_z.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_z.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_z.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_z.c' object='cpio/test/bsdcpio_test-test_option_z.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_z.o `test -f 'cpio/test/test_option_z.c' || echo '$(srcdir)/'`cpio/test/test_option_z.c + +cpio/test/bsdcpio_test-test_option_z.obj: cpio/test/test_option_z.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_z.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_z.Tpo -c -o cpio/test/bsdcpio_test-test_option_z.obj `if test -f 'cpio/test/test_option_z.c'; then $(CYGPATH_W) 'cpio/test/test_option_z.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_z.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_z.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_z.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_z.c' object='cpio/test/bsdcpio_test-test_option_z.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_z.obj `if test -f 'cpio/test/test_option_z.c'; then $(CYGPATH_W) 'cpio/test/test_option_z.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_z.c'; fi` + +cpio/test/bsdcpio_test-test_option_zstd.o: cpio/test/test_option_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_zstd.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_zstd.Tpo -c -o cpio/test/bsdcpio_test-test_option_zstd.o `test -f 'cpio/test/test_option_zstd.c' || echo '$(srcdir)/'`cpio/test/test_option_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_zstd.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_zstd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_zstd.c' object='cpio/test/bsdcpio_test-test_option_zstd.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_zstd.o `test -f 'cpio/test/test_option_zstd.c' || echo '$(srcdir)/'`cpio/test/test_option_zstd.c + +cpio/test/bsdcpio_test-test_option_zstd.obj: cpio/test/test_option_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_option_zstd.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_option_zstd.Tpo -c -o cpio/test/bsdcpio_test-test_option_zstd.obj `if test -f 'cpio/test/test_option_zstd.c'; then $(CYGPATH_W) 'cpio/test/test_option_zstd.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_zstd.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_option_zstd.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_option_zstd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_option_zstd.c' object='cpio/test/bsdcpio_test-test_option_zstd.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_option_zstd.obj `if test -f 'cpio/test/test_option_zstd.c'; then $(CYGPATH_W) 'cpio/test/test_option_zstd.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_option_zstd.c'; fi` + +cpio/test/bsdcpio_test-test_owner_parse.o: cpio/test/test_owner_parse.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_owner_parse.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_owner_parse.Tpo -c -o cpio/test/bsdcpio_test-test_owner_parse.o `test -f 'cpio/test/test_owner_parse.c' || echo '$(srcdir)/'`cpio/test/test_owner_parse.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_owner_parse.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_owner_parse.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_owner_parse.c' object='cpio/test/bsdcpio_test-test_owner_parse.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_owner_parse.o `test -f 'cpio/test/test_owner_parse.c' || echo '$(srcdir)/'`cpio/test/test_owner_parse.c + +cpio/test/bsdcpio_test-test_owner_parse.obj: cpio/test/test_owner_parse.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_owner_parse.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_owner_parse.Tpo -c -o cpio/test/bsdcpio_test-test_owner_parse.obj `if test -f 'cpio/test/test_owner_parse.c'; then $(CYGPATH_W) 'cpio/test/test_owner_parse.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_owner_parse.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_owner_parse.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_owner_parse.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_owner_parse.c' object='cpio/test/bsdcpio_test-test_owner_parse.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_owner_parse.obj `if test -f 'cpio/test/test_owner_parse.c'; then $(CYGPATH_W) 'cpio/test/test_owner_parse.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_owner_parse.c'; fi` + +cpio/test/bsdcpio_test-test_passthrough_dotdot.o: cpio/test/test_passthrough_dotdot.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_passthrough_dotdot.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_passthrough_dotdot.Tpo -c -o cpio/test/bsdcpio_test-test_passthrough_dotdot.o `test -f 'cpio/test/test_passthrough_dotdot.c' || echo '$(srcdir)/'`cpio/test/test_passthrough_dotdot.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_passthrough_dotdot.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_passthrough_dotdot.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_passthrough_dotdot.c' object='cpio/test/bsdcpio_test-test_passthrough_dotdot.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_passthrough_dotdot.o `test -f 'cpio/test/test_passthrough_dotdot.c' || echo '$(srcdir)/'`cpio/test/test_passthrough_dotdot.c + +cpio/test/bsdcpio_test-test_passthrough_dotdot.obj: cpio/test/test_passthrough_dotdot.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_passthrough_dotdot.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_passthrough_dotdot.Tpo -c -o cpio/test/bsdcpio_test-test_passthrough_dotdot.obj `if test -f 'cpio/test/test_passthrough_dotdot.c'; then $(CYGPATH_W) 'cpio/test/test_passthrough_dotdot.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_passthrough_dotdot.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_passthrough_dotdot.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_passthrough_dotdot.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_passthrough_dotdot.c' object='cpio/test/bsdcpio_test-test_passthrough_dotdot.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_passthrough_dotdot.obj `if test -f 'cpio/test/test_passthrough_dotdot.c'; then $(CYGPATH_W) 'cpio/test/test_passthrough_dotdot.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_passthrough_dotdot.c'; fi` + +cpio/test/bsdcpio_test-test_passthrough_reverse.o: cpio/test/test_passthrough_reverse.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_passthrough_reverse.o -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_passthrough_reverse.Tpo -c -o cpio/test/bsdcpio_test-test_passthrough_reverse.o `test -f 'cpio/test/test_passthrough_reverse.c' || echo '$(srcdir)/'`cpio/test/test_passthrough_reverse.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_passthrough_reverse.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_passthrough_reverse.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_passthrough_reverse.c' object='cpio/test/bsdcpio_test-test_passthrough_reverse.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_passthrough_reverse.o `test -f 'cpio/test/test_passthrough_reverse.c' || echo '$(srcdir)/'`cpio/test/test_passthrough_reverse.c + +cpio/test/bsdcpio_test-test_passthrough_reverse.obj: cpio/test/test_passthrough_reverse.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpio/test/bsdcpio_test-test_passthrough_reverse.obj -MD -MP -MF cpio/test/$(DEPDIR)/bsdcpio_test-test_passthrough_reverse.Tpo -c -o cpio/test/bsdcpio_test-test_passthrough_reverse.obj `if test -f 'cpio/test/test_passthrough_reverse.c'; then $(CYGPATH_W) 'cpio/test/test_passthrough_reverse.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_passthrough_reverse.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) cpio/test/$(DEPDIR)/bsdcpio_test-test_passthrough_reverse.Tpo cpio/test/$(DEPDIR)/bsdcpio_test-test_passthrough_reverse.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpio/test/test_passthrough_reverse.c' object='cpio/test/bsdcpio_test-test_passthrough_reverse.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdcpio_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpio/test/bsdcpio_test-test_passthrough_reverse.obj `if test -f 'cpio/test/test_passthrough_reverse.c'; then $(CYGPATH_W) 'cpio/test/test_passthrough_reverse.c'; else $(CYGPATH_W) '$(srcdir)/cpio/test/test_passthrough_reverse.c'; fi` + +tar/bsdtar-bsdtar.o: tar/bsdtar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/bsdtar-bsdtar.o -MD -MP -MF tar/$(DEPDIR)/bsdtar-bsdtar.Tpo -c -o tar/bsdtar-bsdtar.o `test -f 'tar/bsdtar.c' || echo '$(srcdir)/'`tar/bsdtar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/$(DEPDIR)/bsdtar-bsdtar.Tpo tar/$(DEPDIR)/bsdtar-bsdtar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/bsdtar.c' object='tar/bsdtar-bsdtar.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/bsdtar-bsdtar.o `test -f 'tar/bsdtar.c' || echo '$(srcdir)/'`tar/bsdtar.c + +tar/bsdtar-bsdtar.obj: tar/bsdtar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/bsdtar-bsdtar.obj -MD -MP -MF tar/$(DEPDIR)/bsdtar-bsdtar.Tpo -c -o tar/bsdtar-bsdtar.obj `if test -f 'tar/bsdtar.c'; then $(CYGPATH_W) 'tar/bsdtar.c'; else $(CYGPATH_W) '$(srcdir)/tar/bsdtar.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/$(DEPDIR)/bsdtar-bsdtar.Tpo tar/$(DEPDIR)/bsdtar-bsdtar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/bsdtar.c' object='tar/bsdtar-bsdtar.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/bsdtar-bsdtar.obj `if test -f 'tar/bsdtar.c'; then $(CYGPATH_W) 'tar/bsdtar.c'; else $(CYGPATH_W) '$(srcdir)/tar/bsdtar.c'; fi` + +tar/bsdtar-cmdline.o: tar/cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/bsdtar-cmdline.o -MD -MP -MF tar/$(DEPDIR)/bsdtar-cmdline.Tpo -c -o tar/bsdtar-cmdline.o `test -f 'tar/cmdline.c' || echo '$(srcdir)/'`tar/cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/$(DEPDIR)/bsdtar-cmdline.Tpo tar/$(DEPDIR)/bsdtar-cmdline.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/cmdline.c' object='tar/bsdtar-cmdline.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/bsdtar-cmdline.o `test -f 'tar/cmdline.c' || echo '$(srcdir)/'`tar/cmdline.c + +tar/bsdtar-cmdline.obj: tar/cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/bsdtar-cmdline.obj -MD -MP -MF tar/$(DEPDIR)/bsdtar-cmdline.Tpo -c -o tar/bsdtar-cmdline.obj `if test -f 'tar/cmdline.c'; then $(CYGPATH_W) 'tar/cmdline.c'; else $(CYGPATH_W) '$(srcdir)/tar/cmdline.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/$(DEPDIR)/bsdtar-cmdline.Tpo tar/$(DEPDIR)/bsdtar-cmdline.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/cmdline.c' object='tar/bsdtar-cmdline.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/bsdtar-cmdline.obj `if test -f 'tar/cmdline.c'; then $(CYGPATH_W) 'tar/cmdline.c'; else $(CYGPATH_W) '$(srcdir)/tar/cmdline.c'; fi` + +tar/bsdtar-creation_set.o: tar/creation_set.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/bsdtar-creation_set.o -MD -MP -MF tar/$(DEPDIR)/bsdtar-creation_set.Tpo -c -o tar/bsdtar-creation_set.o `test -f 'tar/creation_set.c' || echo '$(srcdir)/'`tar/creation_set.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/$(DEPDIR)/bsdtar-creation_set.Tpo tar/$(DEPDIR)/bsdtar-creation_set.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/creation_set.c' object='tar/bsdtar-creation_set.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/bsdtar-creation_set.o `test -f 'tar/creation_set.c' || echo '$(srcdir)/'`tar/creation_set.c + +tar/bsdtar-creation_set.obj: tar/creation_set.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/bsdtar-creation_set.obj -MD -MP -MF tar/$(DEPDIR)/bsdtar-creation_set.Tpo -c -o tar/bsdtar-creation_set.obj `if test -f 'tar/creation_set.c'; then $(CYGPATH_W) 'tar/creation_set.c'; else $(CYGPATH_W) '$(srcdir)/tar/creation_set.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/$(DEPDIR)/bsdtar-creation_set.Tpo tar/$(DEPDIR)/bsdtar-creation_set.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/creation_set.c' object='tar/bsdtar-creation_set.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/bsdtar-creation_set.obj `if test -f 'tar/creation_set.c'; then $(CYGPATH_W) 'tar/creation_set.c'; else $(CYGPATH_W) '$(srcdir)/tar/creation_set.c'; fi` + +tar/bsdtar-read.o: tar/read.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/bsdtar-read.o -MD -MP -MF tar/$(DEPDIR)/bsdtar-read.Tpo -c -o tar/bsdtar-read.o `test -f 'tar/read.c' || echo '$(srcdir)/'`tar/read.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/$(DEPDIR)/bsdtar-read.Tpo tar/$(DEPDIR)/bsdtar-read.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/read.c' object='tar/bsdtar-read.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/bsdtar-read.o `test -f 'tar/read.c' || echo '$(srcdir)/'`tar/read.c + +tar/bsdtar-read.obj: tar/read.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/bsdtar-read.obj -MD -MP -MF tar/$(DEPDIR)/bsdtar-read.Tpo -c -o tar/bsdtar-read.obj `if test -f 'tar/read.c'; then $(CYGPATH_W) 'tar/read.c'; else $(CYGPATH_W) '$(srcdir)/tar/read.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/$(DEPDIR)/bsdtar-read.Tpo tar/$(DEPDIR)/bsdtar-read.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/read.c' object='tar/bsdtar-read.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/bsdtar-read.obj `if test -f 'tar/read.c'; then $(CYGPATH_W) 'tar/read.c'; else $(CYGPATH_W) '$(srcdir)/tar/read.c'; fi` + +tar/bsdtar-subst.o: tar/subst.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/bsdtar-subst.o -MD -MP -MF tar/$(DEPDIR)/bsdtar-subst.Tpo -c -o tar/bsdtar-subst.o `test -f 'tar/subst.c' || echo '$(srcdir)/'`tar/subst.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/$(DEPDIR)/bsdtar-subst.Tpo tar/$(DEPDIR)/bsdtar-subst.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/subst.c' object='tar/bsdtar-subst.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/bsdtar-subst.o `test -f 'tar/subst.c' || echo '$(srcdir)/'`tar/subst.c + +tar/bsdtar-subst.obj: tar/subst.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/bsdtar-subst.obj -MD -MP -MF tar/$(DEPDIR)/bsdtar-subst.Tpo -c -o tar/bsdtar-subst.obj `if test -f 'tar/subst.c'; then $(CYGPATH_W) 'tar/subst.c'; else $(CYGPATH_W) '$(srcdir)/tar/subst.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/$(DEPDIR)/bsdtar-subst.Tpo tar/$(DEPDIR)/bsdtar-subst.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/subst.c' object='tar/bsdtar-subst.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/bsdtar-subst.obj `if test -f 'tar/subst.c'; then $(CYGPATH_W) 'tar/subst.c'; else $(CYGPATH_W) '$(srcdir)/tar/subst.c'; fi` + +tar/bsdtar-util.o: tar/util.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/bsdtar-util.o -MD -MP -MF tar/$(DEPDIR)/bsdtar-util.Tpo -c -o tar/bsdtar-util.o `test -f 'tar/util.c' || echo '$(srcdir)/'`tar/util.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/$(DEPDIR)/bsdtar-util.Tpo tar/$(DEPDIR)/bsdtar-util.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/util.c' object='tar/bsdtar-util.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/bsdtar-util.o `test -f 'tar/util.c' || echo '$(srcdir)/'`tar/util.c + +tar/bsdtar-util.obj: tar/util.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/bsdtar-util.obj -MD -MP -MF tar/$(DEPDIR)/bsdtar-util.Tpo -c -o tar/bsdtar-util.obj `if test -f 'tar/util.c'; then $(CYGPATH_W) 'tar/util.c'; else $(CYGPATH_W) '$(srcdir)/tar/util.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/$(DEPDIR)/bsdtar-util.Tpo tar/$(DEPDIR)/bsdtar-util.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/util.c' object='tar/bsdtar-util.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/bsdtar-util.obj `if test -f 'tar/util.c'; then $(CYGPATH_W) 'tar/util.c'; else $(CYGPATH_W) '$(srcdir)/tar/util.c'; fi` + +tar/bsdtar-write.o: tar/write.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/bsdtar-write.o -MD -MP -MF tar/$(DEPDIR)/bsdtar-write.Tpo -c -o tar/bsdtar-write.o `test -f 'tar/write.c' || echo '$(srcdir)/'`tar/write.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/$(DEPDIR)/bsdtar-write.Tpo tar/$(DEPDIR)/bsdtar-write.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/write.c' object='tar/bsdtar-write.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/bsdtar-write.o `test -f 'tar/write.c' || echo '$(srcdir)/'`tar/write.c + +tar/bsdtar-write.obj: tar/write.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/bsdtar-write.obj -MD -MP -MF tar/$(DEPDIR)/bsdtar-write.Tpo -c -o tar/bsdtar-write.obj `if test -f 'tar/write.c'; then $(CYGPATH_W) 'tar/write.c'; else $(CYGPATH_W) '$(srcdir)/tar/write.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/$(DEPDIR)/bsdtar-write.Tpo tar/$(DEPDIR)/bsdtar-write.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/write.c' object='tar/bsdtar-write.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/bsdtar-write.obj `if test -f 'tar/write.c'; then $(CYGPATH_W) 'tar/write.c'; else $(CYGPATH_W) '$(srcdir)/tar/write.c'; fi` + +tar/bsdtar-bsdtar_windows.o: tar/bsdtar_windows.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/bsdtar-bsdtar_windows.o -MD -MP -MF tar/$(DEPDIR)/bsdtar-bsdtar_windows.Tpo -c -o tar/bsdtar-bsdtar_windows.o `test -f 'tar/bsdtar_windows.c' || echo '$(srcdir)/'`tar/bsdtar_windows.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/$(DEPDIR)/bsdtar-bsdtar_windows.Tpo tar/$(DEPDIR)/bsdtar-bsdtar_windows.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/bsdtar_windows.c' object='tar/bsdtar-bsdtar_windows.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/bsdtar-bsdtar_windows.o `test -f 'tar/bsdtar_windows.c' || echo '$(srcdir)/'`tar/bsdtar_windows.c + +tar/bsdtar-bsdtar_windows.obj: tar/bsdtar_windows.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/bsdtar-bsdtar_windows.obj -MD -MP -MF tar/$(DEPDIR)/bsdtar-bsdtar_windows.Tpo -c -o tar/bsdtar-bsdtar_windows.obj `if test -f 'tar/bsdtar_windows.c'; then $(CYGPATH_W) 'tar/bsdtar_windows.c'; else $(CYGPATH_W) '$(srcdir)/tar/bsdtar_windows.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/$(DEPDIR)/bsdtar-bsdtar_windows.Tpo tar/$(DEPDIR)/bsdtar-bsdtar_windows.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/bsdtar_windows.c' object='tar/bsdtar-bsdtar_windows.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/bsdtar-bsdtar_windows.obj `if test -f 'tar/bsdtar_windows.c'; then $(CYGPATH_W) 'tar/bsdtar_windows.c'; else $(CYGPATH_W) '$(srcdir)/tar/bsdtar_windows.c'; fi` + +test_utils/bsdtar_test-test_utils.o: test_utils/test_utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_utils/bsdtar_test-test_utils.o -MD -MP -MF test_utils/$(DEPDIR)/bsdtar_test-test_utils.Tpo -c -o test_utils/bsdtar_test-test_utils.o `test -f 'test_utils/test_utils.c' || echo '$(srcdir)/'`test_utils/test_utils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) test_utils/$(DEPDIR)/bsdtar_test-test_utils.Tpo test_utils/$(DEPDIR)/bsdtar_test-test_utils.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_utils/test_utils.c' object='test_utils/bsdtar_test-test_utils.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_utils/bsdtar_test-test_utils.o `test -f 'test_utils/test_utils.c' || echo '$(srcdir)/'`test_utils/test_utils.c + +test_utils/bsdtar_test-test_utils.obj: test_utils/test_utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_utils/bsdtar_test-test_utils.obj -MD -MP -MF test_utils/$(DEPDIR)/bsdtar_test-test_utils.Tpo -c -o test_utils/bsdtar_test-test_utils.obj `if test -f 'test_utils/test_utils.c'; then $(CYGPATH_W) 'test_utils/test_utils.c'; else $(CYGPATH_W) '$(srcdir)/test_utils/test_utils.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) test_utils/$(DEPDIR)/bsdtar_test-test_utils.Tpo test_utils/$(DEPDIR)/bsdtar_test-test_utils.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_utils/test_utils.c' object='test_utils/bsdtar_test-test_utils.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_utils/bsdtar_test-test_utils.obj `if test -f 'test_utils/test_utils.c'; then $(CYGPATH_W) 'test_utils/test_utils.c'; else $(CYGPATH_W) '$(srcdir)/test_utils/test_utils.c'; fi` + +test_utils/bsdtar_test-test_main.o: test_utils/test_main.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_utils/bsdtar_test-test_main.o -MD -MP -MF test_utils/$(DEPDIR)/bsdtar_test-test_main.Tpo -c -o test_utils/bsdtar_test-test_main.o `test -f 'test_utils/test_main.c' || echo '$(srcdir)/'`test_utils/test_main.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) test_utils/$(DEPDIR)/bsdtar_test-test_main.Tpo test_utils/$(DEPDIR)/bsdtar_test-test_main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_utils/test_main.c' object='test_utils/bsdtar_test-test_main.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_utils/bsdtar_test-test_main.o `test -f 'test_utils/test_main.c' || echo '$(srcdir)/'`test_utils/test_main.c + +test_utils/bsdtar_test-test_main.obj: test_utils/test_main.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_utils/bsdtar_test-test_main.obj -MD -MP -MF test_utils/$(DEPDIR)/bsdtar_test-test_main.Tpo -c -o test_utils/bsdtar_test-test_main.obj `if test -f 'test_utils/test_main.c'; then $(CYGPATH_W) 'test_utils/test_main.c'; else $(CYGPATH_W) '$(srcdir)/test_utils/test_main.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) test_utils/$(DEPDIR)/bsdtar_test-test_main.Tpo test_utils/$(DEPDIR)/bsdtar_test-test_main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_utils/test_main.c' object='test_utils/bsdtar_test-test_main.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_utils/bsdtar_test-test_main.obj `if test -f 'test_utils/test_main.c'; then $(CYGPATH_W) 'test_utils/test_main.c'; else $(CYGPATH_W) '$(srcdir)/test_utils/test_main.c'; fi` + +tar/test/bsdtar_test-test_0.o: tar/test/test_0.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_0.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_0.Tpo -c -o tar/test/bsdtar_test-test_0.o `test -f 'tar/test/test_0.c' || echo '$(srcdir)/'`tar/test/test_0.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_0.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_0.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_0.c' object='tar/test/bsdtar_test-test_0.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_0.o `test -f 'tar/test/test_0.c' || echo '$(srcdir)/'`tar/test/test_0.c + +tar/test/bsdtar_test-test_0.obj: tar/test/test_0.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_0.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_0.Tpo -c -o tar/test/bsdtar_test-test_0.obj `if test -f 'tar/test/test_0.c'; then $(CYGPATH_W) 'tar/test/test_0.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_0.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_0.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_0.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_0.c' object='tar/test/bsdtar_test-test_0.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_0.obj `if test -f 'tar/test/test_0.c'; then $(CYGPATH_W) 'tar/test/test_0.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_0.c'; fi` + +tar/test/bsdtar_test-test_basic.o: tar/test/test_basic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_basic.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_basic.Tpo -c -o tar/test/bsdtar_test-test_basic.o `test -f 'tar/test/test_basic.c' || echo '$(srcdir)/'`tar/test/test_basic.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_basic.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_basic.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_basic.c' object='tar/test/bsdtar_test-test_basic.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_basic.o `test -f 'tar/test/test_basic.c' || echo '$(srcdir)/'`tar/test/test_basic.c + +tar/test/bsdtar_test-test_basic.obj: tar/test/test_basic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_basic.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_basic.Tpo -c -o tar/test/bsdtar_test-test_basic.obj `if test -f 'tar/test/test_basic.c'; then $(CYGPATH_W) 'tar/test/test_basic.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_basic.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_basic.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_basic.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_basic.c' object='tar/test/bsdtar_test-test_basic.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_basic.obj `if test -f 'tar/test/test_basic.c'; then $(CYGPATH_W) 'tar/test/test_basic.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_basic.c'; fi` + +tar/test/bsdtar_test-test_copy.o: tar/test/test_copy.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_copy.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_copy.Tpo -c -o tar/test/bsdtar_test-test_copy.o `test -f 'tar/test/test_copy.c' || echo '$(srcdir)/'`tar/test/test_copy.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_copy.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_copy.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_copy.c' object='tar/test/bsdtar_test-test_copy.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_copy.o `test -f 'tar/test/test_copy.c' || echo '$(srcdir)/'`tar/test/test_copy.c + +tar/test/bsdtar_test-test_copy.obj: tar/test/test_copy.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_copy.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_copy.Tpo -c -o tar/test/bsdtar_test-test_copy.obj `if test -f 'tar/test/test_copy.c'; then $(CYGPATH_W) 'tar/test/test_copy.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_copy.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_copy.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_copy.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_copy.c' object='tar/test/bsdtar_test-test_copy.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_copy.obj `if test -f 'tar/test/test_copy.c'; then $(CYGPATH_W) 'tar/test/test_copy.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_copy.c'; fi` + +tar/test/bsdtar_test-test_empty_mtree.o: tar/test/test_empty_mtree.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_empty_mtree.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_empty_mtree.Tpo -c -o tar/test/bsdtar_test-test_empty_mtree.o `test -f 'tar/test/test_empty_mtree.c' || echo '$(srcdir)/'`tar/test/test_empty_mtree.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_empty_mtree.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_empty_mtree.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_empty_mtree.c' object='tar/test/bsdtar_test-test_empty_mtree.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_empty_mtree.o `test -f 'tar/test/test_empty_mtree.c' || echo '$(srcdir)/'`tar/test/test_empty_mtree.c + +tar/test/bsdtar_test-test_empty_mtree.obj: tar/test/test_empty_mtree.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_empty_mtree.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_empty_mtree.Tpo -c -o tar/test/bsdtar_test-test_empty_mtree.obj `if test -f 'tar/test/test_empty_mtree.c'; then $(CYGPATH_W) 'tar/test/test_empty_mtree.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_empty_mtree.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_empty_mtree.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_empty_mtree.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_empty_mtree.c' object='tar/test/bsdtar_test-test_empty_mtree.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_empty_mtree.obj `if test -f 'tar/test/test_empty_mtree.c'; then $(CYGPATH_W) 'tar/test/test_empty_mtree.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_empty_mtree.c'; fi` + +tar/test/bsdtar_test-test_extract_tar_Z.o: tar/test/test_extract_tar_Z.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_extract_tar_Z.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_Z.Tpo -c -o tar/test/bsdtar_test-test_extract_tar_Z.o `test -f 'tar/test/test_extract_tar_Z.c' || echo '$(srcdir)/'`tar/test/test_extract_tar_Z.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_Z.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_Z.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_extract_tar_Z.c' object='tar/test/bsdtar_test-test_extract_tar_Z.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_extract_tar_Z.o `test -f 'tar/test/test_extract_tar_Z.c' || echo '$(srcdir)/'`tar/test/test_extract_tar_Z.c + +tar/test/bsdtar_test-test_extract_tar_Z.obj: tar/test/test_extract_tar_Z.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_extract_tar_Z.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_Z.Tpo -c -o tar/test/bsdtar_test-test_extract_tar_Z.obj `if test -f 'tar/test/test_extract_tar_Z.c'; then $(CYGPATH_W) 'tar/test/test_extract_tar_Z.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_extract_tar_Z.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_Z.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_Z.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_extract_tar_Z.c' object='tar/test/bsdtar_test-test_extract_tar_Z.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_extract_tar_Z.obj `if test -f 'tar/test/test_extract_tar_Z.c'; then $(CYGPATH_W) 'tar/test/test_extract_tar_Z.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_extract_tar_Z.c'; fi` + +tar/test/bsdtar_test-test_extract_tar_bz2.o: tar/test/test_extract_tar_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_extract_tar_bz2.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_bz2.Tpo -c -o tar/test/bsdtar_test-test_extract_tar_bz2.o `test -f 'tar/test/test_extract_tar_bz2.c' || echo '$(srcdir)/'`tar/test/test_extract_tar_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_bz2.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_bz2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_extract_tar_bz2.c' object='tar/test/bsdtar_test-test_extract_tar_bz2.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_extract_tar_bz2.o `test -f 'tar/test/test_extract_tar_bz2.c' || echo '$(srcdir)/'`tar/test/test_extract_tar_bz2.c + +tar/test/bsdtar_test-test_extract_tar_bz2.obj: tar/test/test_extract_tar_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_extract_tar_bz2.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_bz2.Tpo -c -o tar/test/bsdtar_test-test_extract_tar_bz2.obj `if test -f 'tar/test/test_extract_tar_bz2.c'; then $(CYGPATH_W) 'tar/test/test_extract_tar_bz2.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_extract_tar_bz2.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_bz2.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_bz2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_extract_tar_bz2.c' object='tar/test/bsdtar_test-test_extract_tar_bz2.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_extract_tar_bz2.obj `if test -f 'tar/test/test_extract_tar_bz2.c'; then $(CYGPATH_W) 'tar/test/test_extract_tar_bz2.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_extract_tar_bz2.c'; fi` + +tar/test/bsdtar_test-test_extract_tar_grz.o: tar/test/test_extract_tar_grz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_extract_tar_grz.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_grz.Tpo -c -o tar/test/bsdtar_test-test_extract_tar_grz.o `test -f 'tar/test/test_extract_tar_grz.c' || echo '$(srcdir)/'`tar/test/test_extract_tar_grz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_grz.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_grz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_extract_tar_grz.c' object='tar/test/bsdtar_test-test_extract_tar_grz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_extract_tar_grz.o `test -f 'tar/test/test_extract_tar_grz.c' || echo '$(srcdir)/'`tar/test/test_extract_tar_grz.c + +tar/test/bsdtar_test-test_extract_tar_grz.obj: tar/test/test_extract_tar_grz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_extract_tar_grz.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_grz.Tpo -c -o tar/test/bsdtar_test-test_extract_tar_grz.obj `if test -f 'tar/test/test_extract_tar_grz.c'; then $(CYGPATH_W) 'tar/test/test_extract_tar_grz.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_extract_tar_grz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_grz.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_grz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_extract_tar_grz.c' object='tar/test/bsdtar_test-test_extract_tar_grz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_extract_tar_grz.obj `if test -f 'tar/test/test_extract_tar_grz.c'; then $(CYGPATH_W) 'tar/test/test_extract_tar_grz.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_extract_tar_grz.c'; fi` + +tar/test/bsdtar_test-test_extract_tar_gz.o: tar/test/test_extract_tar_gz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_extract_tar_gz.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_gz.Tpo -c -o tar/test/bsdtar_test-test_extract_tar_gz.o `test -f 'tar/test/test_extract_tar_gz.c' || echo '$(srcdir)/'`tar/test/test_extract_tar_gz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_gz.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_gz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_extract_tar_gz.c' object='tar/test/bsdtar_test-test_extract_tar_gz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_extract_tar_gz.o `test -f 'tar/test/test_extract_tar_gz.c' || echo '$(srcdir)/'`tar/test/test_extract_tar_gz.c + +tar/test/bsdtar_test-test_extract_tar_gz.obj: tar/test/test_extract_tar_gz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_extract_tar_gz.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_gz.Tpo -c -o tar/test/bsdtar_test-test_extract_tar_gz.obj `if test -f 'tar/test/test_extract_tar_gz.c'; then $(CYGPATH_W) 'tar/test/test_extract_tar_gz.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_extract_tar_gz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_gz.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_gz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_extract_tar_gz.c' object='tar/test/bsdtar_test-test_extract_tar_gz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_extract_tar_gz.obj `if test -f 'tar/test/test_extract_tar_gz.c'; then $(CYGPATH_W) 'tar/test/test_extract_tar_gz.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_extract_tar_gz.c'; fi` + +tar/test/bsdtar_test-test_extract_tar_lrz.o: tar/test/test_extract_tar_lrz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_extract_tar_lrz.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lrz.Tpo -c -o tar/test/bsdtar_test-test_extract_tar_lrz.o `test -f 'tar/test/test_extract_tar_lrz.c' || echo '$(srcdir)/'`tar/test/test_extract_tar_lrz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lrz.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lrz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_extract_tar_lrz.c' object='tar/test/bsdtar_test-test_extract_tar_lrz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_extract_tar_lrz.o `test -f 'tar/test/test_extract_tar_lrz.c' || echo '$(srcdir)/'`tar/test/test_extract_tar_lrz.c + +tar/test/bsdtar_test-test_extract_tar_lrz.obj: tar/test/test_extract_tar_lrz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_extract_tar_lrz.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lrz.Tpo -c -o tar/test/bsdtar_test-test_extract_tar_lrz.obj `if test -f 'tar/test/test_extract_tar_lrz.c'; then $(CYGPATH_W) 'tar/test/test_extract_tar_lrz.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_extract_tar_lrz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lrz.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lrz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_extract_tar_lrz.c' object='tar/test/bsdtar_test-test_extract_tar_lrz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_extract_tar_lrz.obj `if test -f 'tar/test/test_extract_tar_lrz.c'; then $(CYGPATH_W) 'tar/test/test_extract_tar_lrz.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_extract_tar_lrz.c'; fi` + +tar/test/bsdtar_test-test_extract_tar_lz.o: tar/test/test_extract_tar_lz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_extract_tar_lz.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lz.Tpo -c -o tar/test/bsdtar_test-test_extract_tar_lz.o `test -f 'tar/test/test_extract_tar_lz.c' || echo '$(srcdir)/'`tar/test/test_extract_tar_lz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lz.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_extract_tar_lz.c' object='tar/test/bsdtar_test-test_extract_tar_lz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_extract_tar_lz.o `test -f 'tar/test/test_extract_tar_lz.c' || echo '$(srcdir)/'`tar/test/test_extract_tar_lz.c + +tar/test/bsdtar_test-test_extract_tar_lz.obj: tar/test/test_extract_tar_lz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_extract_tar_lz.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lz.Tpo -c -o tar/test/bsdtar_test-test_extract_tar_lz.obj `if test -f 'tar/test/test_extract_tar_lz.c'; then $(CYGPATH_W) 'tar/test/test_extract_tar_lz.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_extract_tar_lz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lz.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_extract_tar_lz.c' object='tar/test/bsdtar_test-test_extract_tar_lz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_extract_tar_lz.obj `if test -f 'tar/test/test_extract_tar_lz.c'; then $(CYGPATH_W) 'tar/test/test_extract_tar_lz.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_extract_tar_lz.c'; fi` + +tar/test/bsdtar_test-test_extract_tar_lz4.o: tar/test/test_extract_tar_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_extract_tar_lz4.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lz4.Tpo -c -o tar/test/bsdtar_test-test_extract_tar_lz4.o `test -f 'tar/test/test_extract_tar_lz4.c' || echo '$(srcdir)/'`tar/test/test_extract_tar_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lz4.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lz4.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_extract_tar_lz4.c' object='tar/test/bsdtar_test-test_extract_tar_lz4.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_extract_tar_lz4.o `test -f 'tar/test/test_extract_tar_lz4.c' || echo '$(srcdir)/'`tar/test/test_extract_tar_lz4.c + +tar/test/bsdtar_test-test_extract_tar_lz4.obj: tar/test/test_extract_tar_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_extract_tar_lz4.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lz4.Tpo -c -o tar/test/bsdtar_test-test_extract_tar_lz4.obj `if test -f 'tar/test/test_extract_tar_lz4.c'; then $(CYGPATH_W) 'tar/test/test_extract_tar_lz4.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_extract_tar_lz4.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lz4.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lz4.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_extract_tar_lz4.c' object='tar/test/bsdtar_test-test_extract_tar_lz4.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_extract_tar_lz4.obj `if test -f 'tar/test/test_extract_tar_lz4.c'; then $(CYGPATH_W) 'tar/test/test_extract_tar_lz4.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_extract_tar_lz4.c'; fi` + +tar/test/bsdtar_test-test_extract_tar_lzma.o: tar/test/test_extract_tar_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_extract_tar_lzma.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lzma.Tpo -c -o tar/test/bsdtar_test-test_extract_tar_lzma.o `test -f 'tar/test/test_extract_tar_lzma.c' || echo '$(srcdir)/'`tar/test/test_extract_tar_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lzma.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lzma.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_extract_tar_lzma.c' object='tar/test/bsdtar_test-test_extract_tar_lzma.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_extract_tar_lzma.o `test -f 'tar/test/test_extract_tar_lzma.c' || echo '$(srcdir)/'`tar/test/test_extract_tar_lzma.c + +tar/test/bsdtar_test-test_extract_tar_lzma.obj: tar/test/test_extract_tar_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_extract_tar_lzma.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lzma.Tpo -c -o tar/test/bsdtar_test-test_extract_tar_lzma.obj `if test -f 'tar/test/test_extract_tar_lzma.c'; then $(CYGPATH_W) 'tar/test/test_extract_tar_lzma.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_extract_tar_lzma.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lzma.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lzma.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_extract_tar_lzma.c' object='tar/test/bsdtar_test-test_extract_tar_lzma.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_extract_tar_lzma.obj `if test -f 'tar/test/test_extract_tar_lzma.c'; then $(CYGPATH_W) 'tar/test/test_extract_tar_lzma.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_extract_tar_lzma.c'; fi` + +tar/test/bsdtar_test-test_extract_tar_lzo.o: tar/test/test_extract_tar_lzo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_extract_tar_lzo.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lzo.Tpo -c -o tar/test/bsdtar_test-test_extract_tar_lzo.o `test -f 'tar/test/test_extract_tar_lzo.c' || echo '$(srcdir)/'`tar/test/test_extract_tar_lzo.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lzo.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lzo.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_extract_tar_lzo.c' object='tar/test/bsdtar_test-test_extract_tar_lzo.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_extract_tar_lzo.o `test -f 'tar/test/test_extract_tar_lzo.c' || echo '$(srcdir)/'`tar/test/test_extract_tar_lzo.c + +tar/test/bsdtar_test-test_extract_tar_lzo.obj: tar/test/test_extract_tar_lzo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_extract_tar_lzo.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lzo.Tpo -c -o tar/test/bsdtar_test-test_extract_tar_lzo.obj `if test -f 'tar/test/test_extract_tar_lzo.c'; then $(CYGPATH_W) 'tar/test/test_extract_tar_lzo.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_extract_tar_lzo.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lzo.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_lzo.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_extract_tar_lzo.c' object='tar/test/bsdtar_test-test_extract_tar_lzo.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_extract_tar_lzo.obj `if test -f 'tar/test/test_extract_tar_lzo.c'; then $(CYGPATH_W) 'tar/test/test_extract_tar_lzo.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_extract_tar_lzo.c'; fi` + +tar/test/bsdtar_test-test_extract_tar_xz.o: tar/test/test_extract_tar_xz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_extract_tar_xz.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_xz.Tpo -c -o tar/test/bsdtar_test-test_extract_tar_xz.o `test -f 'tar/test/test_extract_tar_xz.c' || echo '$(srcdir)/'`tar/test/test_extract_tar_xz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_xz.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_xz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_extract_tar_xz.c' object='tar/test/bsdtar_test-test_extract_tar_xz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_extract_tar_xz.o `test -f 'tar/test/test_extract_tar_xz.c' || echo '$(srcdir)/'`tar/test/test_extract_tar_xz.c + +tar/test/bsdtar_test-test_extract_tar_xz.obj: tar/test/test_extract_tar_xz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_extract_tar_xz.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_xz.Tpo -c -o tar/test/bsdtar_test-test_extract_tar_xz.obj `if test -f 'tar/test/test_extract_tar_xz.c'; then $(CYGPATH_W) 'tar/test/test_extract_tar_xz.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_extract_tar_xz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_xz.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_xz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_extract_tar_xz.c' object='tar/test/bsdtar_test-test_extract_tar_xz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_extract_tar_xz.obj `if test -f 'tar/test/test_extract_tar_xz.c'; then $(CYGPATH_W) 'tar/test/test_extract_tar_xz.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_extract_tar_xz.c'; fi` + +tar/test/bsdtar_test-test_extract_tar_zstd.o: tar/test/test_extract_tar_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_extract_tar_zstd.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_zstd.Tpo -c -o tar/test/bsdtar_test-test_extract_tar_zstd.o `test -f 'tar/test/test_extract_tar_zstd.c' || echo '$(srcdir)/'`tar/test/test_extract_tar_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_zstd.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_zstd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_extract_tar_zstd.c' object='tar/test/bsdtar_test-test_extract_tar_zstd.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_extract_tar_zstd.o `test -f 'tar/test/test_extract_tar_zstd.c' || echo '$(srcdir)/'`tar/test/test_extract_tar_zstd.c + +tar/test/bsdtar_test-test_extract_tar_zstd.obj: tar/test/test_extract_tar_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_extract_tar_zstd.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_zstd.Tpo -c -o tar/test/bsdtar_test-test_extract_tar_zstd.obj `if test -f 'tar/test/test_extract_tar_zstd.c'; then $(CYGPATH_W) 'tar/test/test_extract_tar_zstd.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_extract_tar_zstd.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_zstd.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_extract_tar_zstd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_extract_tar_zstd.c' object='tar/test/bsdtar_test-test_extract_tar_zstd.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_extract_tar_zstd.obj `if test -f 'tar/test/test_extract_tar_zstd.c'; then $(CYGPATH_W) 'tar/test/test_extract_tar_zstd.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_extract_tar_zstd.c'; fi` + +tar/test/bsdtar_test-test_format_newc.o: tar/test/test_format_newc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_format_newc.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_format_newc.Tpo -c -o tar/test/bsdtar_test-test_format_newc.o `test -f 'tar/test/test_format_newc.c' || echo '$(srcdir)/'`tar/test/test_format_newc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_format_newc.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_format_newc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_format_newc.c' object='tar/test/bsdtar_test-test_format_newc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_format_newc.o `test -f 'tar/test/test_format_newc.c' || echo '$(srcdir)/'`tar/test/test_format_newc.c + +tar/test/bsdtar_test-test_format_newc.obj: tar/test/test_format_newc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_format_newc.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_format_newc.Tpo -c -o tar/test/bsdtar_test-test_format_newc.obj `if test -f 'tar/test/test_format_newc.c'; then $(CYGPATH_W) 'tar/test/test_format_newc.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_format_newc.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_format_newc.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_format_newc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_format_newc.c' object='tar/test/bsdtar_test-test_format_newc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_format_newc.obj `if test -f 'tar/test/test_format_newc.c'; then $(CYGPATH_W) 'tar/test/test_format_newc.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_format_newc.c'; fi` + +tar/test/bsdtar_test-test_help.o: tar/test/test_help.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_help.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_help.Tpo -c -o tar/test/bsdtar_test-test_help.o `test -f 'tar/test/test_help.c' || echo '$(srcdir)/'`tar/test/test_help.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_help.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_help.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_help.c' object='tar/test/bsdtar_test-test_help.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_help.o `test -f 'tar/test/test_help.c' || echo '$(srcdir)/'`tar/test/test_help.c + +tar/test/bsdtar_test-test_help.obj: tar/test/test_help.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_help.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_help.Tpo -c -o tar/test/bsdtar_test-test_help.obj `if test -f 'tar/test/test_help.c'; then $(CYGPATH_W) 'tar/test/test_help.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_help.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_help.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_help.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_help.c' object='tar/test/bsdtar_test-test_help.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_help.obj `if test -f 'tar/test/test_help.c'; then $(CYGPATH_W) 'tar/test/test_help.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_help.c'; fi` + +tar/test/bsdtar_test-test_leading_slash.o: tar/test/test_leading_slash.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_leading_slash.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_leading_slash.Tpo -c -o tar/test/bsdtar_test-test_leading_slash.o `test -f 'tar/test/test_leading_slash.c' || echo '$(srcdir)/'`tar/test/test_leading_slash.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_leading_slash.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_leading_slash.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_leading_slash.c' object='tar/test/bsdtar_test-test_leading_slash.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_leading_slash.o `test -f 'tar/test/test_leading_slash.c' || echo '$(srcdir)/'`tar/test/test_leading_slash.c + +tar/test/bsdtar_test-test_leading_slash.obj: tar/test/test_leading_slash.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_leading_slash.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_leading_slash.Tpo -c -o tar/test/bsdtar_test-test_leading_slash.obj `if test -f 'tar/test/test_leading_slash.c'; then $(CYGPATH_W) 'tar/test/test_leading_slash.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_leading_slash.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_leading_slash.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_leading_slash.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_leading_slash.c' object='tar/test/bsdtar_test-test_leading_slash.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_leading_slash.obj `if test -f 'tar/test/test_leading_slash.c'; then $(CYGPATH_W) 'tar/test/test_leading_slash.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_leading_slash.c'; fi` + +tar/test/bsdtar_test-test_missing_file.o: tar/test/test_missing_file.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_missing_file.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_missing_file.Tpo -c -o tar/test/bsdtar_test-test_missing_file.o `test -f 'tar/test/test_missing_file.c' || echo '$(srcdir)/'`tar/test/test_missing_file.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_missing_file.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_missing_file.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_missing_file.c' object='tar/test/bsdtar_test-test_missing_file.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_missing_file.o `test -f 'tar/test/test_missing_file.c' || echo '$(srcdir)/'`tar/test/test_missing_file.c + +tar/test/bsdtar_test-test_missing_file.obj: tar/test/test_missing_file.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_missing_file.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_missing_file.Tpo -c -o tar/test/bsdtar_test-test_missing_file.obj `if test -f 'tar/test/test_missing_file.c'; then $(CYGPATH_W) 'tar/test/test_missing_file.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_missing_file.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_missing_file.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_missing_file.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_missing_file.c' object='tar/test/bsdtar_test-test_missing_file.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_missing_file.obj `if test -f 'tar/test/test_missing_file.c'; then $(CYGPATH_W) 'tar/test/test_missing_file.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_missing_file.c'; fi` + +tar/test/bsdtar_test-test_option_C_mtree.o: tar/test/test_option_C_mtree.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_C_mtree.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_C_mtree.Tpo -c -o tar/test/bsdtar_test-test_option_C_mtree.o `test -f 'tar/test/test_option_C_mtree.c' || echo '$(srcdir)/'`tar/test/test_option_C_mtree.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_C_mtree.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_C_mtree.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_C_mtree.c' object='tar/test/bsdtar_test-test_option_C_mtree.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_C_mtree.o `test -f 'tar/test/test_option_C_mtree.c' || echo '$(srcdir)/'`tar/test/test_option_C_mtree.c + +tar/test/bsdtar_test-test_option_C_mtree.obj: tar/test/test_option_C_mtree.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_C_mtree.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_C_mtree.Tpo -c -o tar/test/bsdtar_test-test_option_C_mtree.obj `if test -f 'tar/test/test_option_C_mtree.c'; then $(CYGPATH_W) 'tar/test/test_option_C_mtree.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_C_mtree.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_C_mtree.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_C_mtree.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_C_mtree.c' object='tar/test/bsdtar_test-test_option_C_mtree.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_C_mtree.obj `if test -f 'tar/test/test_option_C_mtree.c'; then $(CYGPATH_W) 'tar/test/test_option_C_mtree.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_C_mtree.c'; fi` + +tar/test/bsdtar_test-test_option_C_upper.o: tar/test/test_option_C_upper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_C_upper.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_C_upper.Tpo -c -o tar/test/bsdtar_test-test_option_C_upper.o `test -f 'tar/test/test_option_C_upper.c' || echo '$(srcdir)/'`tar/test/test_option_C_upper.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_C_upper.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_C_upper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_C_upper.c' object='tar/test/bsdtar_test-test_option_C_upper.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_C_upper.o `test -f 'tar/test/test_option_C_upper.c' || echo '$(srcdir)/'`tar/test/test_option_C_upper.c + +tar/test/bsdtar_test-test_option_C_upper.obj: tar/test/test_option_C_upper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_C_upper.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_C_upper.Tpo -c -o tar/test/bsdtar_test-test_option_C_upper.obj `if test -f 'tar/test/test_option_C_upper.c'; then $(CYGPATH_W) 'tar/test/test_option_C_upper.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_C_upper.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_C_upper.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_C_upper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_C_upper.c' object='tar/test/bsdtar_test-test_option_C_upper.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_C_upper.obj `if test -f 'tar/test/test_option_C_upper.c'; then $(CYGPATH_W) 'tar/test/test_option_C_upper.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_C_upper.c'; fi` + +tar/test/bsdtar_test-test_option_H_upper.o: tar/test/test_option_H_upper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_H_upper.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_H_upper.Tpo -c -o tar/test/bsdtar_test-test_option_H_upper.o `test -f 'tar/test/test_option_H_upper.c' || echo '$(srcdir)/'`tar/test/test_option_H_upper.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_H_upper.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_H_upper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_H_upper.c' object='tar/test/bsdtar_test-test_option_H_upper.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_H_upper.o `test -f 'tar/test/test_option_H_upper.c' || echo '$(srcdir)/'`tar/test/test_option_H_upper.c + +tar/test/bsdtar_test-test_option_H_upper.obj: tar/test/test_option_H_upper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_H_upper.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_H_upper.Tpo -c -o tar/test/bsdtar_test-test_option_H_upper.obj `if test -f 'tar/test/test_option_H_upper.c'; then $(CYGPATH_W) 'tar/test/test_option_H_upper.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_H_upper.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_H_upper.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_H_upper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_H_upper.c' object='tar/test/bsdtar_test-test_option_H_upper.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_H_upper.obj `if test -f 'tar/test/test_option_H_upper.c'; then $(CYGPATH_W) 'tar/test/test_option_H_upper.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_H_upper.c'; fi` + +tar/test/bsdtar_test-test_option_L_upper.o: tar/test/test_option_L_upper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_L_upper.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_L_upper.Tpo -c -o tar/test/bsdtar_test-test_option_L_upper.o `test -f 'tar/test/test_option_L_upper.c' || echo '$(srcdir)/'`tar/test/test_option_L_upper.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_L_upper.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_L_upper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_L_upper.c' object='tar/test/bsdtar_test-test_option_L_upper.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_L_upper.o `test -f 'tar/test/test_option_L_upper.c' || echo '$(srcdir)/'`tar/test/test_option_L_upper.c + +tar/test/bsdtar_test-test_option_L_upper.obj: tar/test/test_option_L_upper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_L_upper.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_L_upper.Tpo -c -o tar/test/bsdtar_test-test_option_L_upper.obj `if test -f 'tar/test/test_option_L_upper.c'; then $(CYGPATH_W) 'tar/test/test_option_L_upper.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_L_upper.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_L_upper.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_L_upper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_L_upper.c' object='tar/test/bsdtar_test-test_option_L_upper.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_L_upper.obj `if test -f 'tar/test/test_option_L_upper.c'; then $(CYGPATH_W) 'tar/test/test_option_L_upper.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_L_upper.c'; fi` + +tar/test/bsdtar_test-test_option_O_upper.o: tar/test/test_option_O_upper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_O_upper.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_O_upper.Tpo -c -o tar/test/bsdtar_test-test_option_O_upper.o `test -f 'tar/test/test_option_O_upper.c' || echo '$(srcdir)/'`tar/test/test_option_O_upper.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_O_upper.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_O_upper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_O_upper.c' object='tar/test/bsdtar_test-test_option_O_upper.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_O_upper.o `test -f 'tar/test/test_option_O_upper.c' || echo '$(srcdir)/'`tar/test/test_option_O_upper.c + +tar/test/bsdtar_test-test_option_O_upper.obj: tar/test/test_option_O_upper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_O_upper.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_O_upper.Tpo -c -o tar/test/bsdtar_test-test_option_O_upper.obj `if test -f 'tar/test/test_option_O_upper.c'; then $(CYGPATH_W) 'tar/test/test_option_O_upper.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_O_upper.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_O_upper.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_O_upper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_O_upper.c' object='tar/test/bsdtar_test-test_option_O_upper.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_O_upper.obj `if test -f 'tar/test/test_option_O_upper.c'; then $(CYGPATH_W) 'tar/test/test_option_O_upper.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_O_upper.c'; fi` + +tar/test/bsdtar_test-test_option_T_upper.o: tar/test/test_option_T_upper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_T_upper.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_T_upper.Tpo -c -o tar/test/bsdtar_test-test_option_T_upper.o `test -f 'tar/test/test_option_T_upper.c' || echo '$(srcdir)/'`tar/test/test_option_T_upper.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_T_upper.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_T_upper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_T_upper.c' object='tar/test/bsdtar_test-test_option_T_upper.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_T_upper.o `test -f 'tar/test/test_option_T_upper.c' || echo '$(srcdir)/'`tar/test/test_option_T_upper.c + +tar/test/bsdtar_test-test_option_T_upper.obj: tar/test/test_option_T_upper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_T_upper.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_T_upper.Tpo -c -o tar/test/bsdtar_test-test_option_T_upper.obj `if test -f 'tar/test/test_option_T_upper.c'; then $(CYGPATH_W) 'tar/test/test_option_T_upper.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_T_upper.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_T_upper.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_T_upper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_T_upper.c' object='tar/test/bsdtar_test-test_option_T_upper.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_T_upper.obj `if test -f 'tar/test/test_option_T_upper.c'; then $(CYGPATH_W) 'tar/test/test_option_T_upper.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_T_upper.c'; fi` + +tar/test/bsdtar_test-test_option_U_upper.o: tar/test/test_option_U_upper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_U_upper.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_U_upper.Tpo -c -o tar/test/bsdtar_test-test_option_U_upper.o `test -f 'tar/test/test_option_U_upper.c' || echo '$(srcdir)/'`tar/test/test_option_U_upper.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_U_upper.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_U_upper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_U_upper.c' object='tar/test/bsdtar_test-test_option_U_upper.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_U_upper.o `test -f 'tar/test/test_option_U_upper.c' || echo '$(srcdir)/'`tar/test/test_option_U_upper.c + +tar/test/bsdtar_test-test_option_U_upper.obj: tar/test/test_option_U_upper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_U_upper.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_U_upper.Tpo -c -o tar/test/bsdtar_test-test_option_U_upper.obj `if test -f 'tar/test/test_option_U_upper.c'; then $(CYGPATH_W) 'tar/test/test_option_U_upper.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_U_upper.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_U_upper.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_U_upper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_U_upper.c' object='tar/test/bsdtar_test-test_option_U_upper.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_U_upper.obj `if test -f 'tar/test/test_option_U_upper.c'; then $(CYGPATH_W) 'tar/test/test_option_U_upper.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_U_upper.c'; fi` + +tar/test/bsdtar_test-test_option_X_upper.o: tar/test/test_option_X_upper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_X_upper.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_X_upper.Tpo -c -o tar/test/bsdtar_test-test_option_X_upper.o `test -f 'tar/test/test_option_X_upper.c' || echo '$(srcdir)/'`tar/test/test_option_X_upper.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_X_upper.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_X_upper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_X_upper.c' object='tar/test/bsdtar_test-test_option_X_upper.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_X_upper.o `test -f 'tar/test/test_option_X_upper.c' || echo '$(srcdir)/'`tar/test/test_option_X_upper.c + +tar/test/bsdtar_test-test_option_X_upper.obj: tar/test/test_option_X_upper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_X_upper.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_X_upper.Tpo -c -o tar/test/bsdtar_test-test_option_X_upper.obj `if test -f 'tar/test/test_option_X_upper.c'; then $(CYGPATH_W) 'tar/test/test_option_X_upper.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_X_upper.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_X_upper.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_X_upper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_X_upper.c' object='tar/test/bsdtar_test-test_option_X_upper.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_X_upper.obj `if test -f 'tar/test/test_option_X_upper.c'; then $(CYGPATH_W) 'tar/test/test_option_X_upper.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_X_upper.c'; fi` + +tar/test/bsdtar_test-test_option_acls.o: tar/test/test_option_acls.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_acls.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_acls.Tpo -c -o tar/test/bsdtar_test-test_option_acls.o `test -f 'tar/test/test_option_acls.c' || echo '$(srcdir)/'`tar/test/test_option_acls.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_acls.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_acls.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_acls.c' object='tar/test/bsdtar_test-test_option_acls.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_acls.o `test -f 'tar/test/test_option_acls.c' || echo '$(srcdir)/'`tar/test/test_option_acls.c + +tar/test/bsdtar_test-test_option_acls.obj: tar/test/test_option_acls.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_acls.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_acls.Tpo -c -o tar/test/bsdtar_test-test_option_acls.obj `if test -f 'tar/test/test_option_acls.c'; then $(CYGPATH_W) 'tar/test/test_option_acls.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_acls.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_acls.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_acls.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_acls.c' object='tar/test/bsdtar_test-test_option_acls.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_acls.obj `if test -f 'tar/test/test_option_acls.c'; then $(CYGPATH_W) 'tar/test/test_option_acls.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_acls.c'; fi` + +tar/test/bsdtar_test-test_option_a.o: tar/test/test_option_a.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_a.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_a.Tpo -c -o tar/test/bsdtar_test-test_option_a.o `test -f 'tar/test/test_option_a.c' || echo '$(srcdir)/'`tar/test/test_option_a.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_a.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_a.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_a.c' object='tar/test/bsdtar_test-test_option_a.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_a.o `test -f 'tar/test/test_option_a.c' || echo '$(srcdir)/'`tar/test/test_option_a.c + +tar/test/bsdtar_test-test_option_a.obj: tar/test/test_option_a.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_a.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_a.Tpo -c -o tar/test/bsdtar_test-test_option_a.obj `if test -f 'tar/test/test_option_a.c'; then $(CYGPATH_W) 'tar/test/test_option_a.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_a.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_a.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_a.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_a.c' object='tar/test/bsdtar_test-test_option_a.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_a.obj `if test -f 'tar/test/test_option_a.c'; then $(CYGPATH_W) 'tar/test/test_option_a.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_a.c'; fi` + +tar/test/bsdtar_test-test_option_b.o: tar/test/test_option_b.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_b.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_b.Tpo -c -o tar/test/bsdtar_test-test_option_b.o `test -f 'tar/test/test_option_b.c' || echo '$(srcdir)/'`tar/test/test_option_b.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_b.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_b.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_b.c' object='tar/test/bsdtar_test-test_option_b.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_b.o `test -f 'tar/test/test_option_b.c' || echo '$(srcdir)/'`tar/test/test_option_b.c + +tar/test/bsdtar_test-test_option_b.obj: tar/test/test_option_b.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_b.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_b.Tpo -c -o tar/test/bsdtar_test-test_option_b.obj `if test -f 'tar/test/test_option_b.c'; then $(CYGPATH_W) 'tar/test/test_option_b.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_b.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_b.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_b.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_b.c' object='tar/test/bsdtar_test-test_option_b.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_b.obj `if test -f 'tar/test/test_option_b.c'; then $(CYGPATH_W) 'tar/test/test_option_b.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_b.c'; fi` + +tar/test/bsdtar_test-test_option_b64encode.o: tar/test/test_option_b64encode.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_b64encode.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_b64encode.Tpo -c -o tar/test/bsdtar_test-test_option_b64encode.o `test -f 'tar/test/test_option_b64encode.c' || echo '$(srcdir)/'`tar/test/test_option_b64encode.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_b64encode.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_b64encode.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_b64encode.c' object='tar/test/bsdtar_test-test_option_b64encode.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_b64encode.o `test -f 'tar/test/test_option_b64encode.c' || echo '$(srcdir)/'`tar/test/test_option_b64encode.c + +tar/test/bsdtar_test-test_option_b64encode.obj: tar/test/test_option_b64encode.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_b64encode.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_b64encode.Tpo -c -o tar/test/bsdtar_test-test_option_b64encode.obj `if test -f 'tar/test/test_option_b64encode.c'; then $(CYGPATH_W) 'tar/test/test_option_b64encode.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_b64encode.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_b64encode.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_b64encode.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_b64encode.c' object='tar/test/bsdtar_test-test_option_b64encode.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_b64encode.obj `if test -f 'tar/test/test_option_b64encode.c'; then $(CYGPATH_W) 'tar/test/test_option_b64encode.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_b64encode.c'; fi` + +tar/test/bsdtar_test-test_option_exclude.o: tar/test/test_option_exclude.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_exclude.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_exclude.Tpo -c -o tar/test/bsdtar_test-test_option_exclude.o `test -f 'tar/test/test_option_exclude.c' || echo '$(srcdir)/'`tar/test/test_option_exclude.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_exclude.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_exclude.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_exclude.c' object='tar/test/bsdtar_test-test_option_exclude.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_exclude.o `test -f 'tar/test/test_option_exclude.c' || echo '$(srcdir)/'`tar/test/test_option_exclude.c + +tar/test/bsdtar_test-test_option_exclude.obj: tar/test/test_option_exclude.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_exclude.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_exclude.Tpo -c -o tar/test/bsdtar_test-test_option_exclude.obj `if test -f 'tar/test/test_option_exclude.c'; then $(CYGPATH_W) 'tar/test/test_option_exclude.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_exclude.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_exclude.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_exclude.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_exclude.c' object='tar/test/bsdtar_test-test_option_exclude.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_exclude.obj `if test -f 'tar/test/test_option_exclude.c'; then $(CYGPATH_W) 'tar/test/test_option_exclude.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_exclude.c'; fi` + +tar/test/bsdtar_test-test_option_exclude_vcs.o: tar/test/test_option_exclude_vcs.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_exclude_vcs.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_exclude_vcs.Tpo -c -o tar/test/bsdtar_test-test_option_exclude_vcs.o `test -f 'tar/test/test_option_exclude_vcs.c' || echo '$(srcdir)/'`tar/test/test_option_exclude_vcs.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_exclude_vcs.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_exclude_vcs.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_exclude_vcs.c' object='tar/test/bsdtar_test-test_option_exclude_vcs.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_exclude_vcs.o `test -f 'tar/test/test_option_exclude_vcs.c' || echo '$(srcdir)/'`tar/test/test_option_exclude_vcs.c + +tar/test/bsdtar_test-test_option_exclude_vcs.obj: tar/test/test_option_exclude_vcs.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_exclude_vcs.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_exclude_vcs.Tpo -c -o tar/test/bsdtar_test-test_option_exclude_vcs.obj `if test -f 'tar/test/test_option_exclude_vcs.c'; then $(CYGPATH_W) 'tar/test/test_option_exclude_vcs.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_exclude_vcs.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_exclude_vcs.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_exclude_vcs.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_exclude_vcs.c' object='tar/test/bsdtar_test-test_option_exclude_vcs.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_exclude_vcs.obj `if test -f 'tar/test/test_option_exclude_vcs.c'; then $(CYGPATH_W) 'tar/test/test_option_exclude_vcs.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_exclude_vcs.c'; fi` + +tar/test/bsdtar_test-test_option_fflags.o: tar/test/test_option_fflags.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_fflags.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_fflags.Tpo -c -o tar/test/bsdtar_test-test_option_fflags.o `test -f 'tar/test/test_option_fflags.c' || echo '$(srcdir)/'`tar/test/test_option_fflags.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_fflags.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_fflags.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_fflags.c' object='tar/test/bsdtar_test-test_option_fflags.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_fflags.o `test -f 'tar/test/test_option_fflags.c' || echo '$(srcdir)/'`tar/test/test_option_fflags.c + +tar/test/bsdtar_test-test_option_fflags.obj: tar/test/test_option_fflags.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_fflags.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_fflags.Tpo -c -o tar/test/bsdtar_test-test_option_fflags.obj `if test -f 'tar/test/test_option_fflags.c'; then $(CYGPATH_W) 'tar/test/test_option_fflags.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_fflags.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_fflags.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_fflags.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_fflags.c' object='tar/test/bsdtar_test-test_option_fflags.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_fflags.obj `if test -f 'tar/test/test_option_fflags.c'; then $(CYGPATH_W) 'tar/test/test_option_fflags.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_fflags.c'; fi` + +tar/test/bsdtar_test-test_option_gid_gname.o: tar/test/test_option_gid_gname.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_gid_gname.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_gid_gname.Tpo -c -o tar/test/bsdtar_test-test_option_gid_gname.o `test -f 'tar/test/test_option_gid_gname.c' || echo '$(srcdir)/'`tar/test/test_option_gid_gname.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_gid_gname.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_gid_gname.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_gid_gname.c' object='tar/test/bsdtar_test-test_option_gid_gname.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_gid_gname.o `test -f 'tar/test/test_option_gid_gname.c' || echo '$(srcdir)/'`tar/test/test_option_gid_gname.c + +tar/test/bsdtar_test-test_option_gid_gname.obj: tar/test/test_option_gid_gname.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_gid_gname.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_gid_gname.Tpo -c -o tar/test/bsdtar_test-test_option_gid_gname.obj `if test -f 'tar/test/test_option_gid_gname.c'; then $(CYGPATH_W) 'tar/test/test_option_gid_gname.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_gid_gname.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_gid_gname.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_gid_gname.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_gid_gname.c' object='tar/test/bsdtar_test-test_option_gid_gname.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_gid_gname.obj `if test -f 'tar/test/test_option_gid_gname.c'; then $(CYGPATH_W) 'tar/test/test_option_gid_gname.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_gid_gname.c'; fi` + +tar/test/bsdtar_test-test_option_grzip.o: tar/test/test_option_grzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_grzip.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_grzip.Tpo -c -o tar/test/bsdtar_test-test_option_grzip.o `test -f 'tar/test/test_option_grzip.c' || echo '$(srcdir)/'`tar/test/test_option_grzip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_grzip.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_grzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_grzip.c' object='tar/test/bsdtar_test-test_option_grzip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_grzip.o `test -f 'tar/test/test_option_grzip.c' || echo '$(srcdir)/'`tar/test/test_option_grzip.c + +tar/test/bsdtar_test-test_option_grzip.obj: tar/test/test_option_grzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_grzip.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_grzip.Tpo -c -o tar/test/bsdtar_test-test_option_grzip.obj `if test -f 'tar/test/test_option_grzip.c'; then $(CYGPATH_W) 'tar/test/test_option_grzip.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_grzip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_grzip.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_grzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_grzip.c' object='tar/test/bsdtar_test-test_option_grzip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_grzip.obj `if test -f 'tar/test/test_option_grzip.c'; then $(CYGPATH_W) 'tar/test/test_option_grzip.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_grzip.c'; fi` + +tar/test/bsdtar_test-test_option_j.o: tar/test/test_option_j.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_j.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_j.Tpo -c -o tar/test/bsdtar_test-test_option_j.o `test -f 'tar/test/test_option_j.c' || echo '$(srcdir)/'`tar/test/test_option_j.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_j.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_j.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_j.c' object='tar/test/bsdtar_test-test_option_j.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_j.o `test -f 'tar/test/test_option_j.c' || echo '$(srcdir)/'`tar/test/test_option_j.c + +tar/test/bsdtar_test-test_option_j.obj: tar/test/test_option_j.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_j.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_j.Tpo -c -o tar/test/bsdtar_test-test_option_j.obj `if test -f 'tar/test/test_option_j.c'; then $(CYGPATH_W) 'tar/test/test_option_j.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_j.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_j.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_j.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_j.c' object='tar/test/bsdtar_test-test_option_j.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_j.obj `if test -f 'tar/test/test_option_j.c'; then $(CYGPATH_W) 'tar/test/test_option_j.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_j.c'; fi` + +tar/test/bsdtar_test-test_option_k.o: tar/test/test_option_k.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_k.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_k.Tpo -c -o tar/test/bsdtar_test-test_option_k.o `test -f 'tar/test/test_option_k.c' || echo '$(srcdir)/'`tar/test/test_option_k.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_k.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_k.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_k.c' object='tar/test/bsdtar_test-test_option_k.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_k.o `test -f 'tar/test/test_option_k.c' || echo '$(srcdir)/'`tar/test/test_option_k.c + +tar/test/bsdtar_test-test_option_k.obj: tar/test/test_option_k.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_k.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_k.Tpo -c -o tar/test/bsdtar_test-test_option_k.obj `if test -f 'tar/test/test_option_k.c'; then $(CYGPATH_W) 'tar/test/test_option_k.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_k.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_k.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_k.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_k.c' object='tar/test/bsdtar_test-test_option_k.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_k.obj `if test -f 'tar/test/test_option_k.c'; then $(CYGPATH_W) 'tar/test/test_option_k.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_k.c'; fi` + +tar/test/bsdtar_test-test_option_keep_newer_files.o: tar/test/test_option_keep_newer_files.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_keep_newer_files.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_keep_newer_files.Tpo -c -o tar/test/bsdtar_test-test_option_keep_newer_files.o `test -f 'tar/test/test_option_keep_newer_files.c' || echo '$(srcdir)/'`tar/test/test_option_keep_newer_files.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_keep_newer_files.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_keep_newer_files.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_keep_newer_files.c' object='tar/test/bsdtar_test-test_option_keep_newer_files.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_keep_newer_files.o `test -f 'tar/test/test_option_keep_newer_files.c' || echo '$(srcdir)/'`tar/test/test_option_keep_newer_files.c + +tar/test/bsdtar_test-test_option_keep_newer_files.obj: tar/test/test_option_keep_newer_files.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_keep_newer_files.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_keep_newer_files.Tpo -c -o tar/test/bsdtar_test-test_option_keep_newer_files.obj `if test -f 'tar/test/test_option_keep_newer_files.c'; then $(CYGPATH_W) 'tar/test/test_option_keep_newer_files.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_keep_newer_files.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_keep_newer_files.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_keep_newer_files.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_keep_newer_files.c' object='tar/test/bsdtar_test-test_option_keep_newer_files.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_keep_newer_files.obj `if test -f 'tar/test/test_option_keep_newer_files.c'; then $(CYGPATH_W) 'tar/test/test_option_keep_newer_files.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_keep_newer_files.c'; fi` + +tar/test/bsdtar_test-test_option_lrzip.o: tar/test/test_option_lrzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_lrzip.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_lrzip.Tpo -c -o tar/test/bsdtar_test-test_option_lrzip.o `test -f 'tar/test/test_option_lrzip.c' || echo '$(srcdir)/'`tar/test/test_option_lrzip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_lrzip.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_lrzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_lrzip.c' object='tar/test/bsdtar_test-test_option_lrzip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_lrzip.o `test -f 'tar/test/test_option_lrzip.c' || echo '$(srcdir)/'`tar/test/test_option_lrzip.c + +tar/test/bsdtar_test-test_option_lrzip.obj: tar/test/test_option_lrzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_lrzip.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_lrzip.Tpo -c -o tar/test/bsdtar_test-test_option_lrzip.obj `if test -f 'tar/test/test_option_lrzip.c'; then $(CYGPATH_W) 'tar/test/test_option_lrzip.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_lrzip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_lrzip.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_lrzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_lrzip.c' object='tar/test/bsdtar_test-test_option_lrzip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_lrzip.obj `if test -f 'tar/test/test_option_lrzip.c'; then $(CYGPATH_W) 'tar/test/test_option_lrzip.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_lrzip.c'; fi` + +tar/test/bsdtar_test-test_option_lz4.o: tar/test/test_option_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_lz4.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_lz4.Tpo -c -o tar/test/bsdtar_test-test_option_lz4.o `test -f 'tar/test/test_option_lz4.c' || echo '$(srcdir)/'`tar/test/test_option_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_lz4.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_lz4.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_lz4.c' object='tar/test/bsdtar_test-test_option_lz4.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_lz4.o `test -f 'tar/test/test_option_lz4.c' || echo '$(srcdir)/'`tar/test/test_option_lz4.c + +tar/test/bsdtar_test-test_option_lz4.obj: tar/test/test_option_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_lz4.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_lz4.Tpo -c -o tar/test/bsdtar_test-test_option_lz4.obj `if test -f 'tar/test/test_option_lz4.c'; then $(CYGPATH_W) 'tar/test/test_option_lz4.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_lz4.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_lz4.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_lz4.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_lz4.c' object='tar/test/bsdtar_test-test_option_lz4.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_lz4.obj `if test -f 'tar/test/test_option_lz4.c'; then $(CYGPATH_W) 'tar/test/test_option_lz4.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_lz4.c'; fi` + +tar/test/bsdtar_test-test_option_lzma.o: tar/test/test_option_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_lzma.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_lzma.Tpo -c -o tar/test/bsdtar_test-test_option_lzma.o `test -f 'tar/test/test_option_lzma.c' || echo '$(srcdir)/'`tar/test/test_option_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_lzma.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_lzma.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_lzma.c' object='tar/test/bsdtar_test-test_option_lzma.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_lzma.o `test -f 'tar/test/test_option_lzma.c' || echo '$(srcdir)/'`tar/test/test_option_lzma.c + +tar/test/bsdtar_test-test_option_lzma.obj: tar/test/test_option_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_lzma.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_lzma.Tpo -c -o tar/test/bsdtar_test-test_option_lzma.obj `if test -f 'tar/test/test_option_lzma.c'; then $(CYGPATH_W) 'tar/test/test_option_lzma.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_lzma.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_lzma.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_lzma.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_lzma.c' object='tar/test/bsdtar_test-test_option_lzma.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_lzma.obj `if test -f 'tar/test/test_option_lzma.c'; then $(CYGPATH_W) 'tar/test/test_option_lzma.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_lzma.c'; fi` + +tar/test/bsdtar_test-test_option_lzop.o: tar/test/test_option_lzop.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_lzop.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_lzop.Tpo -c -o tar/test/bsdtar_test-test_option_lzop.o `test -f 'tar/test/test_option_lzop.c' || echo '$(srcdir)/'`tar/test/test_option_lzop.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_lzop.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_lzop.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_lzop.c' object='tar/test/bsdtar_test-test_option_lzop.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_lzop.o `test -f 'tar/test/test_option_lzop.c' || echo '$(srcdir)/'`tar/test/test_option_lzop.c + +tar/test/bsdtar_test-test_option_lzop.obj: tar/test/test_option_lzop.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_lzop.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_lzop.Tpo -c -o tar/test/bsdtar_test-test_option_lzop.obj `if test -f 'tar/test/test_option_lzop.c'; then $(CYGPATH_W) 'tar/test/test_option_lzop.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_lzop.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_lzop.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_lzop.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_lzop.c' object='tar/test/bsdtar_test-test_option_lzop.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_lzop.obj `if test -f 'tar/test/test_option_lzop.c'; then $(CYGPATH_W) 'tar/test/test_option_lzop.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_lzop.c'; fi` + +tar/test/bsdtar_test-test_option_n.o: tar/test/test_option_n.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_n.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_n.Tpo -c -o tar/test/bsdtar_test-test_option_n.o `test -f 'tar/test/test_option_n.c' || echo '$(srcdir)/'`tar/test/test_option_n.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_n.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_n.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_n.c' object='tar/test/bsdtar_test-test_option_n.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_n.o `test -f 'tar/test/test_option_n.c' || echo '$(srcdir)/'`tar/test/test_option_n.c + +tar/test/bsdtar_test-test_option_n.obj: tar/test/test_option_n.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_n.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_n.Tpo -c -o tar/test/bsdtar_test-test_option_n.obj `if test -f 'tar/test/test_option_n.c'; then $(CYGPATH_W) 'tar/test/test_option_n.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_n.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_n.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_n.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_n.c' object='tar/test/bsdtar_test-test_option_n.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_n.obj `if test -f 'tar/test/test_option_n.c'; then $(CYGPATH_W) 'tar/test/test_option_n.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_n.c'; fi` + +tar/test/bsdtar_test-test_option_newer_than.o: tar/test/test_option_newer_than.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_newer_than.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_newer_than.Tpo -c -o tar/test/bsdtar_test-test_option_newer_than.o `test -f 'tar/test/test_option_newer_than.c' || echo '$(srcdir)/'`tar/test/test_option_newer_than.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_newer_than.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_newer_than.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_newer_than.c' object='tar/test/bsdtar_test-test_option_newer_than.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_newer_than.o `test -f 'tar/test/test_option_newer_than.c' || echo '$(srcdir)/'`tar/test/test_option_newer_than.c + +tar/test/bsdtar_test-test_option_newer_than.obj: tar/test/test_option_newer_than.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_newer_than.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_newer_than.Tpo -c -o tar/test/bsdtar_test-test_option_newer_than.obj `if test -f 'tar/test/test_option_newer_than.c'; then $(CYGPATH_W) 'tar/test/test_option_newer_than.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_newer_than.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_newer_than.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_newer_than.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_newer_than.c' object='tar/test/bsdtar_test-test_option_newer_than.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_newer_than.obj `if test -f 'tar/test/test_option_newer_than.c'; then $(CYGPATH_W) 'tar/test/test_option_newer_than.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_newer_than.c'; fi` + +tar/test/bsdtar_test-test_option_nodump.o: tar/test/test_option_nodump.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_nodump.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_nodump.Tpo -c -o tar/test/bsdtar_test-test_option_nodump.o `test -f 'tar/test/test_option_nodump.c' || echo '$(srcdir)/'`tar/test/test_option_nodump.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_nodump.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_nodump.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_nodump.c' object='tar/test/bsdtar_test-test_option_nodump.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_nodump.o `test -f 'tar/test/test_option_nodump.c' || echo '$(srcdir)/'`tar/test/test_option_nodump.c + +tar/test/bsdtar_test-test_option_nodump.obj: tar/test/test_option_nodump.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_nodump.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_nodump.Tpo -c -o tar/test/bsdtar_test-test_option_nodump.obj `if test -f 'tar/test/test_option_nodump.c'; then $(CYGPATH_W) 'tar/test/test_option_nodump.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_nodump.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_nodump.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_nodump.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_nodump.c' object='tar/test/bsdtar_test-test_option_nodump.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_nodump.obj `if test -f 'tar/test/test_option_nodump.c'; then $(CYGPATH_W) 'tar/test/test_option_nodump.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_nodump.c'; fi` + +tar/test/bsdtar_test-test_option_older_than.o: tar/test/test_option_older_than.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_older_than.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_older_than.Tpo -c -o tar/test/bsdtar_test-test_option_older_than.o `test -f 'tar/test/test_option_older_than.c' || echo '$(srcdir)/'`tar/test/test_option_older_than.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_older_than.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_older_than.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_older_than.c' object='tar/test/bsdtar_test-test_option_older_than.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_older_than.o `test -f 'tar/test/test_option_older_than.c' || echo '$(srcdir)/'`tar/test/test_option_older_than.c + +tar/test/bsdtar_test-test_option_older_than.obj: tar/test/test_option_older_than.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_older_than.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_older_than.Tpo -c -o tar/test/bsdtar_test-test_option_older_than.obj `if test -f 'tar/test/test_option_older_than.c'; then $(CYGPATH_W) 'tar/test/test_option_older_than.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_older_than.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_older_than.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_older_than.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_older_than.c' object='tar/test/bsdtar_test-test_option_older_than.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_older_than.obj `if test -f 'tar/test/test_option_older_than.c'; then $(CYGPATH_W) 'tar/test/test_option_older_than.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_older_than.c'; fi` + +tar/test/bsdtar_test-test_option_passphrase.o: tar/test/test_option_passphrase.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_passphrase.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_passphrase.Tpo -c -o tar/test/bsdtar_test-test_option_passphrase.o `test -f 'tar/test/test_option_passphrase.c' || echo '$(srcdir)/'`tar/test/test_option_passphrase.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_passphrase.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_passphrase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_passphrase.c' object='tar/test/bsdtar_test-test_option_passphrase.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_passphrase.o `test -f 'tar/test/test_option_passphrase.c' || echo '$(srcdir)/'`tar/test/test_option_passphrase.c + +tar/test/bsdtar_test-test_option_passphrase.obj: tar/test/test_option_passphrase.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_passphrase.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_passphrase.Tpo -c -o tar/test/bsdtar_test-test_option_passphrase.obj `if test -f 'tar/test/test_option_passphrase.c'; then $(CYGPATH_W) 'tar/test/test_option_passphrase.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_passphrase.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_passphrase.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_passphrase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_passphrase.c' object='tar/test/bsdtar_test-test_option_passphrase.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_passphrase.obj `if test -f 'tar/test/test_option_passphrase.c'; then $(CYGPATH_W) 'tar/test/test_option_passphrase.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_passphrase.c'; fi` + +tar/test/bsdtar_test-test_option_q.o: tar/test/test_option_q.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_q.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_q.Tpo -c -o tar/test/bsdtar_test-test_option_q.o `test -f 'tar/test/test_option_q.c' || echo '$(srcdir)/'`tar/test/test_option_q.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_q.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_q.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_q.c' object='tar/test/bsdtar_test-test_option_q.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_q.o `test -f 'tar/test/test_option_q.c' || echo '$(srcdir)/'`tar/test/test_option_q.c + +tar/test/bsdtar_test-test_option_q.obj: tar/test/test_option_q.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_q.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_q.Tpo -c -o tar/test/bsdtar_test-test_option_q.obj `if test -f 'tar/test/test_option_q.c'; then $(CYGPATH_W) 'tar/test/test_option_q.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_q.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_q.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_q.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_q.c' object='tar/test/bsdtar_test-test_option_q.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_q.obj `if test -f 'tar/test/test_option_q.c'; then $(CYGPATH_W) 'tar/test/test_option_q.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_q.c'; fi` + +tar/test/bsdtar_test-test_option_r.o: tar/test/test_option_r.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_r.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_r.Tpo -c -o tar/test/bsdtar_test-test_option_r.o `test -f 'tar/test/test_option_r.c' || echo '$(srcdir)/'`tar/test/test_option_r.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_r.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_r.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_r.c' object='tar/test/bsdtar_test-test_option_r.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_r.o `test -f 'tar/test/test_option_r.c' || echo '$(srcdir)/'`tar/test/test_option_r.c + +tar/test/bsdtar_test-test_option_r.obj: tar/test/test_option_r.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_r.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_r.Tpo -c -o tar/test/bsdtar_test-test_option_r.obj `if test -f 'tar/test/test_option_r.c'; then $(CYGPATH_W) 'tar/test/test_option_r.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_r.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_r.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_r.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_r.c' object='tar/test/bsdtar_test-test_option_r.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_r.obj `if test -f 'tar/test/test_option_r.c'; then $(CYGPATH_W) 'tar/test/test_option_r.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_r.c'; fi` + +tar/test/bsdtar_test-test_option_s.o: tar/test/test_option_s.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_s.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_s.Tpo -c -o tar/test/bsdtar_test-test_option_s.o `test -f 'tar/test/test_option_s.c' || echo '$(srcdir)/'`tar/test/test_option_s.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_s.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_s.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_s.c' object='tar/test/bsdtar_test-test_option_s.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_s.o `test -f 'tar/test/test_option_s.c' || echo '$(srcdir)/'`tar/test/test_option_s.c + +tar/test/bsdtar_test-test_option_s.obj: tar/test/test_option_s.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_s.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_s.Tpo -c -o tar/test/bsdtar_test-test_option_s.obj `if test -f 'tar/test/test_option_s.c'; then $(CYGPATH_W) 'tar/test/test_option_s.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_s.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_s.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_s.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_s.c' object='tar/test/bsdtar_test-test_option_s.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_s.obj `if test -f 'tar/test/test_option_s.c'; then $(CYGPATH_W) 'tar/test/test_option_s.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_s.c'; fi` + +tar/test/bsdtar_test-test_option_safe_writes.o: tar/test/test_option_safe_writes.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_safe_writes.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_safe_writes.Tpo -c -o tar/test/bsdtar_test-test_option_safe_writes.o `test -f 'tar/test/test_option_safe_writes.c' || echo '$(srcdir)/'`tar/test/test_option_safe_writes.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_safe_writes.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_safe_writes.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_safe_writes.c' object='tar/test/bsdtar_test-test_option_safe_writes.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_safe_writes.o `test -f 'tar/test/test_option_safe_writes.c' || echo '$(srcdir)/'`tar/test/test_option_safe_writes.c + +tar/test/bsdtar_test-test_option_safe_writes.obj: tar/test/test_option_safe_writes.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_safe_writes.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_safe_writes.Tpo -c -o tar/test/bsdtar_test-test_option_safe_writes.obj `if test -f 'tar/test/test_option_safe_writes.c'; then $(CYGPATH_W) 'tar/test/test_option_safe_writes.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_safe_writes.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_safe_writes.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_safe_writes.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_safe_writes.c' object='tar/test/bsdtar_test-test_option_safe_writes.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_safe_writes.obj `if test -f 'tar/test/test_option_safe_writes.c'; then $(CYGPATH_W) 'tar/test/test_option_safe_writes.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_safe_writes.c'; fi` + +tar/test/bsdtar_test-test_option_uid_uname.o: tar/test/test_option_uid_uname.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_uid_uname.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_uid_uname.Tpo -c -o tar/test/bsdtar_test-test_option_uid_uname.o `test -f 'tar/test/test_option_uid_uname.c' || echo '$(srcdir)/'`tar/test/test_option_uid_uname.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_uid_uname.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_uid_uname.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_uid_uname.c' object='tar/test/bsdtar_test-test_option_uid_uname.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_uid_uname.o `test -f 'tar/test/test_option_uid_uname.c' || echo '$(srcdir)/'`tar/test/test_option_uid_uname.c + +tar/test/bsdtar_test-test_option_uid_uname.obj: tar/test/test_option_uid_uname.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_uid_uname.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_uid_uname.Tpo -c -o tar/test/bsdtar_test-test_option_uid_uname.obj `if test -f 'tar/test/test_option_uid_uname.c'; then $(CYGPATH_W) 'tar/test/test_option_uid_uname.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_uid_uname.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_uid_uname.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_uid_uname.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_uid_uname.c' object='tar/test/bsdtar_test-test_option_uid_uname.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_uid_uname.obj `if test -f 'tar/test/test_option_uid_uname.c'; then $(CYGPATH_W) 'tar/test/test_option_uid_uname.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_uid_uname.c'; fi` + +tar/test/bsdtar_test-test_option_uuencode.o: tar/test/test_option_uuencode.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_uuencode.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_uuencode.Tpo -c -o tar/test/bsdtar_test-test_option_uuencode.o `test -f 'tar/test/test_option_uuencode.c' || echo '$(srcdir)/'`tar/test/test_option_uuencode.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_uuencode.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_uuencode.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_uuencode.c' object='tar/test/bsdtar_test-test_option_uuencode.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_uuencode.o `test -f 'tar/test/test_option_uuencode.c' || echo '$(srcdir)/'`tar/test/test_option_uuencode.c + +tar/test/bsdtar_test-test_option_uuencode.obj: tar/test/test_option_uuencode.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_uuencode.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_uuencode.Tpo -c -o tar/test/bsdtar_test-test_option_uuencode.obj `if test -f 'tar/test/test_option_uuencode.c'; then $(CYGPATH_W) 'tar/test/test_option_uuencode.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_uuencode.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_uuencode.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_uuencode.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_uuencode.c' object='tar/test/bsdtar_test-test_option_uuencode.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_uuencode.obj `if test -f 'tar/test/test_option_uuencode.c'; then $(CYGPATH_W) 'tar/test/test_option_uuencode.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_uuencode.c'; fi` + +tar/test/bsdtar_test-test_option_xattrs.o: tar/test/test_option_xattrs.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_xattrs.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_xattrs.Tpo -c -o tar/test/bsdtar_test-test_option_xattrs.o `test -f 'tar/test/test_option_xattrs.c' || echo '$(srcdir)/'`tar/test/test_option_xattrs.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_xattrs.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_xattrs.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_xattrs.c' object='tar/test/bsdtar_test-test_option_xattrs.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_xattrs.o `test -f 'tar/test/test_option_xattrs.c' || echo '$(srcdir)/'`tar/test/test_option_xattrs.c + +tar/test/bsdtar_test-test_option_xattrs.obj: tar/test/test_option_xattrs.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_xattrs.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_xattrs.Tpo -c -o tar/test/bsdtar_test-test_option_xattrs.obj `if test -f 'tar/test/test_option_xattrs.c'; then $(CYGPATH_W) 'tar/test/test_option_xattrs.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_xattrs.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_xattrs.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_xattrs.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_xattrs.c' object='tar/test/bsdtar_test-test_option_xattrs.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_xattrs.obj `if test -f 'tar/test/test_option_xattrs.c'; then $(CYGPATH_W) 'tar/test/test_option_xattrs.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_xattrs.c'; fi` + +tar/test/bsdtar_test-test_option_xz.o: tar/test/test_option_xz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_xz.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_xz.Tpo -c -o tar/test/bsdtar_test-test_option_xz.o `test -f 'tar/test/test_option_xz.c' || echo '$(srcdir)/'`tar/test/test_option_xz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_xz.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_xz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_xz.c' object='tar/test/bsdtar_test-test_option_xz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_xz.o `test -f 'tar/test/test_option_xz.c' || echo '$(srcdir)/'`tar/test/test_option_xz.c + +tar/test/bsdtar_test-test_option_xz.obj: tar/test/test_option_xz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_xz.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_xz.Tpo -c -o tar/test/bsdtar_test-test_option_xz.obj `if test -f 'tar/test/test_option_xz.c'; then $(CYGPATH_W) 'tar/test/test_option_xz.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_xz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_xz.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_xz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_xz.c' object='tar/test/bsdtar_test-test_option_xz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_xz.obj `if test -f 'tar/test/test_option_xz.c'; then $(CYGPATH_W) 'tar/test/test_option_xz.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_xz.c'; fi` + +tar/test/bsdtar_test-test_option_z.o: tar/test/test_option_z.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_z.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_z.Tpo -c -o tar/test/bsdtar_test-test_option_z.o `test -f 'tar/test/test_option_z.c' || echo '$(srcdir)/'`tar/test/test_option_z.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_z.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_z.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_z.c' object='tar/test/bsdtar_test-test_option_z.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_z.o `test -f 'tar/test/test_option_z.c' || echo '$(srcdir)/'`tar/test/test_option_z.c + +tar/test/bsdtar_test-test_option_z.obj: tar/test/test_option_z.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_z.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_z.Tpo -c -o tar/test/bsdtar_test-test_option_z.obj `if test -f 'tar/test/test_option_z.c'; then $(CYGPATH_W) 'tar/test/test_option_z.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_z.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_z.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_z.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_z.c' object='tar/test/bsdtar_test-test_option_z.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_z.obj `if test -f 'tar/test/test_option_z.c'; then $(CYGPATH_W) 'tar/test/test_option_z.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_z.c'; fi` + +tar/test/bsdtar_test-test_option_zstd.o: tar/test/test_option_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_zstd.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_zstd.Tpo -c -o tar/test/bsdtar_test-test_option_zstd.o `test -f 'tar/test/test_option_zstd.c' || echo '$(srcdir)/'`tar/test/test_option_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_zstd.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_zstd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_zstd.c' object='tar/test/bsdtar_test-test_option_zstd.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_zstd.o `test -f 'tar/test/test_option_zstd.c' || echo '$(srcdir)/'`tar/test/test_option_zstd.c + +tar/test/bsdtar_test-test_option_zstd.obj: tar/test/test_option_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_option_zstd.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_option_zstd.Tpo -c -o tar/test/bsdtar_test-test_option_zstd.obj `if test -f 'tar/test/test_option_zstd.c'; then $(CYGPATH_W) 'tar/test/test_option_zstd.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_zstd.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_option_zstd.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_option_zstd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_option_zstd.c' object='tar/test/bsdtar_test-test_option_zstd.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_option_zstd.obj `if test -f 'tar/test/test_option_zstd.c'; then $(CYGPATH_W) 'tar/test/test_option_zstd.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_option_zstd.c'; fi` + +tar/test/bsdtar_test-test_patterns.o: tar/test/test_patterns.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_patterns.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_patterns.Tpo -c -o tar/test/bsdtar_test-test_patterns.o `test -f 'tar/test/test_patterns.c' || echo '$(srcdir)/'`tar/test/test_patterns.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_patterns.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_patterns.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_patterns.c' object='tar/test/bsdtar_test-test_patterns.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_patterns.o `test -f 'tar/test/test_patterns.c' || echo '$(srcdir)/'`tar/test/test_patterns.c + +tar/test/bsdtar_test-test_patterns.obj: tar/test/test_patterns.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_patterns.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_patterns.Tpo -c -o tar/test/bsdtar_test-test_patterns.obj `if test -f 'tar/test/test_patterns.c'; then $(CYGPATH_W) 'tar/test/test_patterns.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_patterns.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_patterns.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_patterns.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_patterns.c' object='tar/test/bsdtar_test-test_patterns.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_patterns.obj `if test -f 'tar/test/test_patterns.c'; then $(CYGPATH_W) 'tar/test/test_patterns.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_patterns.c'; fi` + +tar/test/bsdtar_test-test_print_longpath.o: tar/test/test_print_longpath.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_print_longpath.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_print_longpath.Tpo -c -o tar/test/bsdtar_test-test_print_longpath.o `test -f 'tar/test/test_print_longpath.c' || echo '$(srcdir)/'`tar/test/test_print_longpath.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_print_longpath.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_print_longpath.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_print_longpath.c' object='tar/test/bsdtar_test-test_print_longpath.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_print_longpath.o `test -f 'tar/test/test_print_longpath.c' || echo '$(srcdir)/'`tar/test/test_print_longpath.c + +tar/test/bsdtar_test-test_print_longpath.obj: tar/test/test_print_longpath.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_print_longpath.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_print_longpath.Tpo -c -o tar/test/bsdtar_test-test_print_longpath.obj `if test -f 'tar/test/test_print_longpath.c'; then $(CYGPATH_W) 'tar/test/test_print_longpath.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_print_longpath.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_print_longpath.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_print_longpath.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_print_longpath.c' object='tar/test/bsdtar_test-test_print_longpath.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_print_longpath.obj `if test -f 'tar/test/test_print_longpath.c'; then $(CYGPATH_W) 'tar/test/test_print_longpath.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_print_longpath.c'; fi` + +tar/test/bsdtar_test-test_stdio.o: tar/test/test_stdio.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_stdio.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_stdio.Tpo -c -o tar/test/bsdtar_test-test_stdio.o `test -f 'tar/test/test_stdio.c' || echo '$(srcdir)/'`tar/test/test_stdio.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_stdio.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_stdio.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_stdio.c' object='tar/test/bsdtar_test-test_stdio.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_stdio.o `test -f 'tar/test/test_stdio.c' || echo '$(srcdir)/'`tar/test/test_stdio.c + +tar/test/bsdtar_test-test_stdio.obj: tar/test/test_stdio.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_stdio.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_stdio.Tpo -c -o tar/test/bsdtar_test-test_stdio.obj `if test -f 'tar/test/test_stdio.c'; then $(CYGPATH_W) 'tar/test/test_stdio.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_stdio.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_stdio.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_stdio.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_stdio.c' object='tar/test/bsdtar_test-test_stdio.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_stdio.obj `if test -f 'tar/test/test_stdio.c'; then $(CYGPATH_W) 'tar/test/test_stdio.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_stdio.c'; fi` + +tar/test/bsdtar_test-test_strip_components.o: tar/test/test_strip_components.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_strip_components.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_strip_components.Tpo -c -o tar/test/bsdtar_test-test_strip_components.o `test -f 'tar/test/test_strip_components.c' || echo '$(srcdir)/'`tar/test/test_strip_components.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_strip_components.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_strip_components.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_strip_components.c' object='tar/test/bsdtar_test-test_strip_components.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_strip_components.o `test -f 'tar/test/test_strip_components.c' || echo '$(srcdir)/'`tar/test/test_strip_components.c + +tar/test/bsdtar_test-test_strip_components.obj: tar/test/test_strip_components.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_strip_components.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_strip_components.Tpo -c -o tar/test/bsdtar_test-test_strip_components.obj `if test -f 'tar/test/test_strip_components.c'; then $(CYGPATH_W) 'tar/test/test_strip_components.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_strip_components.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_strip_components.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_strip_components.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_strip_components.c' object='tar/test/bsdtar_test-test_strip_components.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_strip_components.obj `if test -f 'tar/test/test_strip_components.c'; then $(CYGPATH_W) 'tar/test/test_strip_components.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_strip_components.c'; fi` + +tar/test/bsdtar_test-test_symlink_dir.o: tar/test/test_symlink_dir.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_symlink_dir.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_symlink_dir.Tpo -c -o tar/test/bsdtar_test-test_symlink_dir.o `test -f 'tar/test/test_symlink_dir.c' || echo '$(srcdir)/'`tar/test/test_symlink_dir.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_symlink_dir.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_symlink_dir.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_symlink_dir.c' object='tar/test/bsdtar_test-test_symlink_dir.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_symlink_dir.o `test -f 'tar/test/test_symlink_dir.c' || echo '$(srcdir)/'`tar/test/test_symlink_dir.c + +tar/test/bsdtar_test-test_symlink_dir.obj: tar/test/test_symlink_dir.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_symlink_dir.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_symlink_dir.Tpo -c -o tar/test/bsdtar_test-test_symlink_dir.obj `if test -f 'tar/test/test_symlink_dir.c'; then $(CYGPATH_W) 'tar/test/test_symlink_dir.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_symlink_dir.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_symlink_dir.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_symlink_dir.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_symlink_dir.c' object='tar/test/bsdtar_test-test_symlink_dir.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_symlink_dir.obj `if test -f 'tar/test/test_symlink_dir.c'; then $(CYGPATH_W) 'tar/test/test_symlink_dir.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_symlink_dir.c'; fi` + +tar/test/bsdtar_test-test_version.o: tar/test/test_version.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_version.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_version.Tpo -c -o tar/test/bsdtar_test-test_version.o `test -f 'tar/test/test_version.c' || echo '$(srcdir)/'`tar/test/test_version.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_version.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_version.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_version.c' object='tar/test/bsdtar_test-test_version.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_version.o `test -f 'tar/test/test_version.c' || echo '$(srcdir)/'`tar/test/test_version.c + +tar/test/bsdtar_test-test_version.obj: tar/test/test_version.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_version.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_version.Tpo -c -o tar/test/bsdtar_test-test_version.obj `if test -f 'tar/test/test_version.c'; then $(CYGPATH_W) 'tar/test/test_version.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_version.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_version.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_version.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_version.c' object='tar/test/bsdtar_test-test_version.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_version.obj `if test -f 'tar/test/test_version.c'; then $(CYGPATH_W) 'tar/test/test_version.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_version.c'; fi` + +tar/test/bsdtar_test-test_windows.o: tar/test/test_windows.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_windows.o -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_windows.Tpo -c -o tar/test/bsdtar_test-test_windows.o `test -f 'tar/test/test_windows.c' || echo '$(srcdir)/'`tar/test/test_windows.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_windows.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_windows.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_windows.c' object='tar/test/bsdtar_test-test_windows.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_windows.o `test -f 'tar/test/test_windows.c' || echo '$(srcdir)/'`tar/test/test_windows.c + +tar/test/bsdtar_test-test_windows.obj: tar/test/test_windows.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tar/test/bsdtar_test-test_windows.obj -MD -MP -MF tar/test/$(DEPDIR)/bsdtar_test-test_windows.Tpo -c -o tar/test/bsdtar_test-test_windows.obj `if test -f 'tar/test/test_windows.c'; then $(CYGPATH_W) 'tar/test/test_windows.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_windows.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tar/test/$(DEPDIR)/bsdtar_test-test_windows.Tpo tar/test/$(DEPDIR)/bsdtar_test-test_windows.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tar/test/test_windows.c' object='tar/test/bsdtar_test-test_windows.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bsdtar_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tar/test/bsdtar_test-test_windows.obj `if test -f 'tar/test/test_windows.c'; then $(CYGPATH_W) 'tar/test/test_windows.c'; else $(CYGPATH_W) '$(srcdir)/tar/test/test_windows.c'; fi` + +libarchive/libarchive_test-archive_acl.o: libarchive/archive_acl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_acl.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_acl.Tpo -c -o libarchive/libarchive_test-archive_acl.o `test -f 'libarchive/archive_acl.c' || echo '$(srcdir)/'`libarchive/archive_acl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_acl.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_acl.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_acl.c' object='libarchive/libarchive_test-archive_acl.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_acl.o `test -f 'libarchive/archive_acl.c' || echo '$(srcdir)/'`libarchive/archive_acl.c + +libarchive/libarchive_test-archive_acl.obj: libarchive/archive_acl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_acl.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_acl.Tpo -c -o libarchive/libarchive_test-archive_acl.obj `if test -f 'libarchive/archive_acl.c'; then $(CYGPATH_W) 'libarchive/archive_acl.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_acl.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_acl.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_acl.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_acl.c' object='libarchive/libarchive_test-archive_acl.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_acl.obj `if test -f 'libarchive/archive_acl.c'; then $(CYGPATH_W) 'libarchive/archive_acl.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_acl.c'; fi` + +libarchive/libarchive_test-archive_check_magic.o: libarchive/archive_check_magic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_check_magic.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_check_magic.Tpo -c -o libarchive/libarchive_test-archive_check_magic.o `test -f 'libarchive/archive_check_magic.c' || echo '$(srcdir)/'`libarchive/archive_check_magic.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_check_magic.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_check_magic.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_check_magic.c' object='libarchive/libarchive_test-archive_check_magic.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_check_magic.o `test -f 'libarchive/archive_check_magic.c' || echo '$(srcdir)/'`libarchive/archive_check_magic.c + +libarchive/libarchive_test-archive_check_magic.obj: libarchive/archive_check_magic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_check_magic.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_check_magic.Tpo -c -o libarchive/libarchive_test-archive_check_magic.obj `if test -f 'libarchive/archive_check_magic.c'; then $(CYGPATH_W) 'libarchive/archive_check_magic.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_check_magic.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_check_magic.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_check_magic.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_check_magic.c' object='libarchive/libarchive_test-archive_check_magic.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_check_magic.obj `if test -f 'libarchive/archive_check_magic.c'; then $(CYGPATH_W) 'libarchive/archive_check_magic.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_check_magic.c'; fi` + +libarchive/libarchive_test-archive_cmdline.o: libarchive/archive_cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_cmdline.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_cmdline.Tpo -c -o libarchive/libarchive_test-archive_cmdline.o `test -f 'libarchive/archive_cmdline.c' || echo '$(srcdir)/'`libarchive/archive_cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_cmdline.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_cmdline.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_cmdline.c' object='libarchive/libarchive_test-archive_cmdline.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_cmdline.o `test -f 'libarchive/archive_cmdline.c' || echo '$(srcdir)/'`libarchive/archive_cmdline.c + +libarchive/libarchive_test-archive_cmdline.obj: libarchive/archive_cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_cmdline.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_cmdline.Tpo -c -o libarchive/libarchive_test-archive_cmdline.obj `if test -f 'libarchive/archive_cmdline.c'; then $(CYGPATH_W) 'libarchive/archive_cmdline.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_cmdline.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_cmdline.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_cmdline.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_cmdline.c' object='libarchive/libarchive_test-archive_cmdline.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_cmdline.obj `if test -f 'libarchive/archive_cmdline.c'; then $(CYGPATH_W) 'libarchive/archive_cmdline.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_cmdline.c'; fi` + +libarchive/libarchive_test-archive_cryptor.o: libarchive/archive_cryptor.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_cryptor.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_cryptor.Tpo -c -o libarchive/libarchive_test-archive_cryptor.o `test -f 'libarchive/archive_cryptor.c' || echo '$(srcdir)/'`libarchive/archive_cryptor.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_cryptor.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_cryptor.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_cryptor.c' object='libarchive/libarchive_test-archive_cryptor.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_cryptor.o `test -f 'libarchive/archive_cryptor.c' || echo '$(srcdir)/'`libarchive/archive_cryptor.c + +libarchive/libarchive_test-archive_cryptor.obj: libarchive/archive_cryptor.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_cryptor.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_cryptor.Tpo -c -o libarchive/libarchive_test-archive_cryptor.obj `if test -f 'libarchive/archive_cryptor.c'; then $(CYGPATH_W) 'libarchive/archive_cryptor.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_cryptor.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_cryptor.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_cryptor.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_cryptor.c' object='libarchive/libarchive_test-archive_cryptor.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_cryptor.obj `if test -f 'libarchive/archive_cryptor.c'; then $(CYGPATH_W) 'libarchive/archive_cryptor.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_cryptor.c'; fi` + +libarchive/libarchive_test-archive_digest.o: libarchive/archive_digest.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_digest.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_digest.Tpo -c -o libarchive/libarchive_test-archive_digest.o `test -f 'libarchive/archive_digest.c' || echo '$(srcdir)/'`libarchive/archive_digest.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_digest.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_digest.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_digest.c' object='libarchive/libarchive_test-archive_digest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_digest.o `test -f 'libarchive/archive_digest.c' || echo '$(srcdir)/'`libarchive/archive_digest.c + +libarchive/libarchive_test-archive_digest.obj: libarchive/archive_digest.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_digest.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_digest.Tpo -c -o libarchive/libarchive_test-archive_digest.obj `if test -f 'libarchive/archive_digest.c'; then $(CYGPATH_W) 'libarchive/archive_digest.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_digest.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_digest.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_digest.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_digest.c' object='libarchive/libarchive_test-archive_digest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_digest.obj `if test -f 'libarchive/archive_digest.c'; then $(CYGPATH_W) 'libarchive/archive_digest.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_digest.c'; fi` + +libarchive/libarchive_test-archive_entry.o: libarchive/archive_entry.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_entry.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_entry.Tpo -c -o libarchive/libarchive_test-archive_entry.o `test -f 'libarchive/archive_entry.c' || echo '$(srcdir)/'`libarchive/archive_entry.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_entry.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_entry.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_entry.c' object='libarchive/libarchive_test-archive_entry.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_entry.o `test -f 'libarchive/archive_entry.c' || echo '$(srcdir)/'`libarchive/archive_entry.c + +libarchive/libarchive_test-archive_entry.obj: libarchive/archive_entry.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_entry.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_entry.Tpo -c -o libarchive/libarchive_test-archive_entry.obj `if test -f 'libarchive/archive_entry.c'; then $(CYGPATH_W) 'libarchive/archive_entry.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_entry.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_entry.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_entry.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_entry.c' object='libarchive/libarchive_test-archive_entry.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_entry.obj `if test -f 'libarchive/archive_entry.c'; then $(CYGPATH_W) 'libarchive/archive_entry.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_entry.c'; fi` + +libarchive/libarchive_test-archive_entry_copy_stat.o: libarchive/archive_entry_copy_stat.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_entry_copy_stat.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_entry_copy_stat.Tpo -c -o libarchive/libarchive_test-archive_entry_copy_stat.o `test -f 'libarchive/archive_entry_copy_stat.c' || echo '$(srcdir)/'`libarchive/archive_entry_copy_stat.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_entry_copy_stat.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_entry_copy_stat.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_entry_copy_stat.c' object='libarchive/libarchive_test-archive_entry_copy_stat.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_entry_copy_stat.o `test -f 'libarchive/archive_entry_copy_stat.c' || echo '$(srcdir)/'`libarchive/archive_entry_copy_stat.c + +libarchive/libarchive_test-archive_entry_copy_stat.obj: libarchive/archive_entry_copy_stat.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_entry_copy_stat.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_entry_copy_stat.Tpo -c -o libarchive/libarchive_test-archive_entry_copy_stat.obj `if test -f 'libarchive/archive_entry_copy_stat.c'; then $(CYGPATH_W) 'libarchive/archive_entry_copy_stat.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_entry_copy_stat.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_entry_copy_stat.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_entry_copy_stat.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_entry_copy_stat.c' object='libarchive/libarchive_test-archive_entry_copy_stat.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_entry_copy_stat.obj `if test -f 'libarchive/archive_entry_copy_stat.c'; then $(CYGPATH_W) 'libarchive/archive_entry_copy_stat.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_entry_copy_stat.c'; fi` + +libarchive/libarchive_test-archive_entry_link_resolver.o: libarchive/archive_entry_link_resolver.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_entry_link_resolver.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_entry_link_resolver.Tpo -c -o libarchive/libarchive_test-archive_entry_link_resolver.o `test -f 'libarchive/archive_entry_link_resolver.c' || echo '$(srcdir)/'`libarchive/archive_entry_link_resolver.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_entry_link_resolver.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_entry_link_resolver.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_entry_link_resolver.c' object='libarchive/libarchive_test-archive_entry_link_resolver.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_entry_link_resolver.o `test -f 'libarchive/archive_entry_link_resolver.c' || echo '$(srcdir)/'`libarchive/archive_entry_link_resolver.c + +libarchive/libarchive_test-archive_entry_link_resolver.obj: libarchive/archive_entry_link_resolver.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_entry_link_resolver.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_entry_link_resolver.Tpo -c -o libarchive/libarchive_test-archive_entry_link_resolver.obj `if test -f 'libarchive/archive_entry_link_resolver.c'; then $(CYGPATH_W) 'libarchive/archive_entry_link_resolver.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_entry_link_resolver.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_entry_link_resolver.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_entry_link_resolver.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_entry_link_resolver.c' object='libarchive/libarchive_test-archive_entry_link_resolver.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_entry_link_resolver.obj `if test -f 'libarchive/archive_entry_link_resolver.c'; then $(CYGPATH_W) 'libarchive/archive_entry_link_resolver.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_entry_link_resolver.c'; fi` + +libarchive/libarchive_test-archive_entry_sparse.o: libarchive/archive_entry_sparse.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_entry_sparse.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_entry_sparse.Tpo -c -o libarchive/libarchive_test-archive_entry_sparse.o `test -f 'libarchive/archive_entry_sparse.c' || echo '$(srcdir)/'`libarchive/archive_entry_sparse.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_entry_sparse.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_entry_sparse.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_entry_sparse.c' object='libarchive/libarchive_test-archive_entry_sparse.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_entry_sparse.o `test -f 'libarchive/archive_entry_sparse.c' || echo '$(srcdir)/'`libarchive/archive_entry_sparse.c + +libarchive/libarchive_test-archive_entry_sparse.obj: libarchive/archive_entry_sparse.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_entry_sparse.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_entry_sparse.Tpo -c -o libarchive/libarchive_test-archive_entry_sparse.obj `if test -f 'libarchive/archive_entry_sparse.c'; then $(CYGPATH_W) 'libarchive/archive_entry_sparse.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_entry_sparse.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_entry_sparse.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_entry_sparse.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_entry_sparse.c' object='libarchive/libarchive_test-archive_entry_sparse.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_entry_sparse.obj `if test -f 'libarchive/archive_entry_sparse.c'; then $(CYGPATH_W) 'libarchive/archive_entry_sparse.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_entry_sparse.c'; fi` + +libarchive/libarchive_test-archive_entry_stat.o: libarchive/archive_entry_stat.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_entry_stat.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_entry_stat.Tpo -c -o libarchive/libarchive_test-archive_entry_stat.o `test -f 'libarchive/archive_entry_stat.c' || echo '$(srcdir)/'`libarchive/archive_entry_stat.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_entry_stat.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_entry_stat.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_entry_stat.c' object='libarchive/libarchive_test-archive_entry_stat.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_entry_stat.o `test -f 'libarchive/archive_entry_stat.c' || echo '$(srcdir)/'`libarchive/archive_entry_stat.c + +libarchive/libarchive_test-archive_entry_stat.obj: libarchive/archive_entry_stat.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_entry_stat.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_entry_stat.Tpo -c -o libarchive/libarchive_test-archive_entry_stat.obj `if test -f 'libarchive/archive_entry_stat.c'; then $(CYGPATH_W) 'libarchive/archive_entry_stat.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_entry_stat.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_entry_stat.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_entry_stat.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_entry_stat.c' object='libarchive/libarchive_test-archive_entry_stat.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_entry_stat.obj `if test -f 'libarchive/archive_entry_stat.c'; then $(CYGPATH_W) 'libarchive/archive_entry_stat.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_entry_stat.c'; fi` + +libarchive/libarchive_test-archive_entry_strmode.o: libarchive/archive_entry_strmode.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_entry_strmode.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_entry_strmode.Tpo -c -o libarchive/libarchive_test-archive_entry_strmode.o `test -f 'libarchive/archive_entry_strmode.c' || echo '$(srcdir)/'`libarchive/archive_entry_strmode.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_entry_strmode.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_entry_strmode.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_entry_strmode.c' object='libarchive/libarchive_test-archive_entry_strmode.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_entry_strmode.o `test -f 'libarchive/archive_entry_strmode.c' || echo '$(srcdir)/'`libarchive/archive_entry_strmode.c + +libarchive/libarchive_test-archive_entry_strmode.obj: libarchive/archive_entry_strmode.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_entry_strmode.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_entry_strmode.Tpo -c -o libarchive/libarchive_test-archive_entry_strmode.obj `if test -f 'libarchive/archive_entry_strmode.c'; then $(CYGPATH_W) 'libarchive/archive_entry_strmode.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_entry_strmode.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_entry_strmode.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_entry_strmode.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_entry_strmode.c' object='libarchive/libarchive_test-archive_entry_strmode.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_entry_strmode.obj `if test -f 'libarchive/archive_entry_strmode.c'; then $(CYGPATH_W) 'libarchive/archive_entry_strmode.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_entry_strmode.c'; fi` + +libarchive/libarchive_test-archive_entry_xattr.o: libarchive/archive_entry_xattr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_entry_xattr.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_entry_xattr.Tpo -c -o libarchive/libarchive_test-archive_entry_xattr.o `test -f 'libarchive/archive_entry_xattr.c' || echo '$(srcdir)/'`libarchive/archive_entry_xattr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_entry_xattr.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_entry_xattr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_entry_xattr.c' object='libarchive/libarchive_test-archive_entry_xattr.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_entry_xattr.o `test -f 'libarchive/archive_entry_xattr.c' || echo '$(srcdir)/'`libarchive/archive_entry_xattr.c + +libarchive/libarchive_test-archive_entry_xattr.obj: libarchive/archive_entry_xattr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_entry_xattr.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_entry_xattr.Tpo -c -o libarchive/libarchive_test-archive_entry_xattr.obj `if test -f 'libarchive/archive_entry_xattr.c'; then $(CYGPATH_W) 'libarchive/archive_entry_xattr.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_entry_xattr.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_entry_xattr.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_entry_xattr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_entry_xattr.c' object='libarchive/libarchive_test-archive_entry_xattr.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_entry_xattr.obj `if test -f 'libarchive/archive_entry_xattr.c'; then $(CYGPATH_W) 'libarchive/archive_entry_xattr.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_entry_xattr.c'; fi` + +libarchive/libarchive_test-archive_getdate.o: libarchive/archive_getdate.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_getdate.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_getdate.Tpo -c -o libarchive/libarchive_test-archive_getdate.o `test -f 'libarchive/archive_getdate.c' || echo '$(srcdir)/'`libarchive/archive_getdate.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_getdate.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_getdate.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_getdate.c' object='libarchive/libarchive_test-archive_getdate.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_getdate.o `test -f 'libarchive/archive_getdate.c' || echo '$(srcdir)/'`libarchive/archive_getdate.c + +libarchive/libarchive_test-archive_getdate.obj: libarchive/archive_getdate.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_getdate.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_getdate.Tpo -c -o libarchive/libarchive_test-archive_getdate.obj `if test -f 'libarchive/archive_getdate.c'; then $(CYGPATH_W) 'libarchive/archive_getdate.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_getdate.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_getdate.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_getdate.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_getdate.c' object='libarchive/libarchive_test-archive_getdate.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_getdate.obj `if test -f 'libarchive/archive_getdate.c'; then $(CYGPATH_W) 'libarchive/archive_getdate.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_getdate.c'; fi` + +libarchive/libarchive_test-archive_hmac.o: libarchive/archive_hmac.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_hmac.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_hmac.Tpo -c -o libarchive/libarchive_test-archive_hmac.o `test -f 'libarchive/archive_hmac.c' || echo '$(srcdir)/'`libarchive/archive_hmac.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_hmac.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_hmac.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_hmac.c' object='libarchive/libarchive_test-archive_hmac.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_hmac.o `test -f 'libarchive/archive_hmac.c' || echo '$(srcdir)/'`libarchive/archive_hmac.c + +libarchive/libarchive_test-archive_hmac.obj: libarchive/archive_hmac.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_hmac.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_hmac.Tpo -c -o libarchive/libarchive_test-archive_hmac.obj `if test -f 'libarchive/archive_hmac.c'; then $(CYGPATH_W) 'libarchive/archive_hmac.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_hmac.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_hmac.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_hmac.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_hmac.c' object='libarchive/libarchive_test-archive_hmac.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_hmac.obj `if test -f 'libarchive/archive_hmac.c'; then $(CYGPATH_W) 'libarchive/archive_hmac.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_hmac.c'; fi` + +libarchive/libarchive_test-archive_match.o: libarchive/archive_match.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_match.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_match.Tpo -c -o libarchive/libarchive_test-archive_match.o `test -f 'libarchive/archive_match.c' || echo '$(srcdir)/'`libarchive/archive_match.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_match.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_match.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_match.c' object='libarchive/libarchive_test-archive_match.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_match.o `test -f 'libarchive/archive_match.c' || echo '$(srcdir)/'`libarchive/archive_match.c + +libarchive/libarchive_test-archive_match.obj: libarchive/archive_match.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_match.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_match.Tpo -c -o libarchive/libarchive_test-archive_match.obj `if test -f 'libarchive/archive_match.c'; then $(CYGPATH_W) 'libarchive/archive_match.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_match.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_match.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_match.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_match.c' object='libarchive/libarchive_test-archive_match.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_match.obj `if test -f 'libarchive/archive_match.c'; then $(CYGPATH_W) 'libarchive/archive_match.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_match.c'; fi` + +libarchive/libarchive_test-archive_options.o: libarchive/archive_options.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_options.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_options.Tpo -c -o libarchive/libarchive_test-archive_options.o `test -f 'libarchive/archive_options.c' || echo '$(srcdir)/'`libarchive/archive_options.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_options.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_options.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_options.c' object='libarchive/libarchive_test-archive_options.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_options.o `test -f 'libarchive/archive_options.c' || echo '$(srcdir)/'`libarchive/archive_options.c + +libarchive/libarchive_test-archive_options.obj: libarchive/archive_options.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_options.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_options.Tpo -c -o libarchive/libarchive_test-archive_options.obj `if test -f 'libarchive/archive_options.c'; then $(CYGPATH_W) 'libarchive/archive_options.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_options.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_options.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_options.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_options.c' object='libarchive/libarchive_test-archive_options.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_options.obj `if test -f 'libarchive/archive_options.c'; then $(CYGPATH_W) 'libarchive/archive_options.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_options.c'; fi` + +libarchive/libarchive_test-archive_pack_dev.o: libarchive/archive_pack_dev.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_pack_dev.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_pack_dev.Tpo -c -o libarchive/libarchive_test-archive_pack_dev.o `test -f 'libarchive/archive_pack_dev.c' || echo '$(srcdir)/'`libarchive/archive_pack_dev.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_pack_dev.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_pack_dev.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_pack_dev.c' object='libarchive/libarchive_test-archive_pack_dev.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_pack_dev.o `test -f 'libarchive/archive_pack_dev.c' || echo '$(srcdir)/'`libarchive/archive_pack_dev.c + +libarchive/libarchive_test-archive_pack_dev.obj: libarchive/archive_pack_dev.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_pack_dev.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_pack_dev.Tpo -c -o libarchive/libarchive_test-archive_pack_dev.obj `if test -f 'libarchive/archive_pack_dev.c'; then $(CYGPATH_W) 'libarchive/archive_pack_dev.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_pack_dev.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_pack_dev.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_pack_dev.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_pack_dev.c' object='libarchive/libarchive_test-archive_pack_dev.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_pack_dev.obj `if test -f 'libarchive/archive_pack_dev.c'; then $(CYGPATH_W) 'libarchive/archive_pack_dev.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_pack_dev.c'; fi` + +libarchive/libarchive_test-archive_pathmatch.o: libarchive/archive_pathmatch.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_pathmatch.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_pathmatch.Tpo -c -o libarchive/libarchive_test-archive_pathmatch.o `test -f 'libarchive/archive_pathmatch.c' || echo '$(srcdir)/'`libarchive/archive_pathmatch.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_pathmatch.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_pathmatch.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_pathmatch.c' object='libarchive/libarchive_test-archive_pathmatch.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_pathmatch.o `test -f 'libarchive/archive_pathmatch.c' || echo '$(srcdir)/'`libarchive/archive_pathmatch.c + +libarchive/libarchive_test-archive_pathmatch.obj: libarchive/archive_pathmatch.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_pathmatch.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_pathmatch.Tpo -c -o libarchive/libarchive_test-archive_pathmatch.obj `if test -f 'libarchive/archive_pathmatch.c'; then $(CYGPATH_W) 'libarchive/archive_pathmatch.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_pathmatch.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_pathmatch.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_pathmatch.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_pathmatch.c' object='libarchive/libarchive_test-archive_pathmatch.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_pathmatch.obj `if test -f 'libarchive/archive_pathmatch.c'; then $(CYGPATH_W) 'libarchive/archive_pathmatch.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_pathmatch.c'; fi` + +libarchive/libarchive_test-archive_ppmd7.o: libarchive/archive_ppmd7.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_ppmd7.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_ppmd7.Tpo -c -o libarchive/libarchive_test-archive_ppmd7.o `test -f 'libarchive/archive_ppmd7.c' || echo '$(srcdir)/'`libarchive/archive_ppmd7.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_ppmd7.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_ppmd7.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_ppmd7.c' object='libarchive/libarchive_test-archive_ppmd7.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_ppmd7.o `test -f 'libarchive/archive_ppmd7.c' || echo '$(srcdir)/'`libarchive/archive_ppmd7.c + +libarchive/libarchive_test-archive_ppmd7.obj: libarchive/archive_ppmd7.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_ppmd7.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_ppmd7.Tpo -c -o libarchive/libarchive_test-archive_ppmd7.obj `if test -f 'libarchive/archive_ppmd7.c'; then $(CYGPATH_W) 'libarchive/archive_ppmd7.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_ppmd7.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_ppmd7.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_ppmd7.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_ppmd7.c' object='libarchive/libarchive_test-archive_ppmd7.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_ppmd7.obj `if test -f 'libarchive/archive_ppmd7.c'; then $(CYGPATH_W) 'libarchive/archive_ppmd7.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_ppmd7.c'; fi` + +libarchive/libarchive_test-archive_ppmd8.o: libarchive/archive_ppmd8.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_ppmd8.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_ppmd8.Tpo -c -o libarchive/libarchive_test-archive_ppmd8.o `test -f 'libarchive/archive_ppmd8.c' || echo '$(srcdir)/'`libarchive/archive_ppmd8.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_ppmd8.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_ppmd8.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_ppmd8.c' object='libarchive/libarchive_test-archive_ppmd8.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_ppmd8.o `test -f 'libarchive/archive_ppmd8.c' || echo '$(srcdir)/'`libarchive/archive_ppmd8.c + +libarchive/libarchive_test-archive_ppmd8.obj: libarchive/archive_ppmd8.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_ppmd8.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_ppmd8.Tpo -c -o libarchive/libarchive_test-archive_ppmd8.obj `if test -f 'libarchive/archive_ppmd8.c'; then $(CYGPATH_W) 'libarchive/archive_ppmd8.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_ppmd8.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_ppmd8.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_ppmd8.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_ppmd8.c' object='libarchive/libarchive_test-archive_ppmd8.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_ppmd8.obj `if test -f 'libarchive/archive_ppmd8.c'; then $(CYGPATH_W) 'libarchive/archive_ppmd8.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_ppmd8.c'; fi` + +libarchive/libarchive_test-archive_random.o: libarchive/archive_random.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_random.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_random.Tpo -c -o libarchive/libarchive_test-archive_random.o `test -f 'libarchive/archive_random.c' || echo '$(srcdir)/'`libarchive/archive_random.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_random.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_random.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_random.c' object='libarchive/libarchive_test-archive_random.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_random.o `test -f 'libarchive/archive_random.c' || echo '$(srcdir)/'`libarchive/archive_random.c + +libarchive/libarchive_test-archive_random.obj: libarchive/archive_random.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_random.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_random.Tpo -c -o libarchive/libarchive_test-archive_random.obj `if test -f 'libarchive/archive_random.c'; then $(CYGPATH_W) 'libarchive/archive_random.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_random.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_random.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_random.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_random.c' object='libarchive/libarchive_test-archive_random.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_random.obj `if test -f 'libarchive/archive_random.c'; then $(CYGPATH_W) 'libarchive/archive_random.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_random.c'; fi` + +libarchive/libarchive_test-archive_rb.o: libarchive/archive_rb.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_rb.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_rb.Tpo -c -o libarchive/libarchive_test-archive_rb.o `test -f 'libarchive/archive_rb.c' || echo '$(srcdir)/'`libarchive/archive_rb.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_rb.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_rb.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_rb.c' object='libarchive/libarchive_test-archive_rb.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_rb.o `test -f 'libarchive/archive_rb.c' || echo '$(srcdir)/'`libarchive/archive_rb.c + +libarchive/libarchive_test-archive_rb.obj: libarchive/archive_rb.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_rb.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_rb.Tpo -c -o libarchive/libarchive_test-archive_rb.obj `if test -f 'libarchive/archive_rb.c'; then $(CYGPATH_W) 'libarchive/archive_rb.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_rb.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_rb.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_rb.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_rb.c' object='libarchive/libarchive_test-archive_rb.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_rb.obj `if test -f 'libarchive/archive_rb.c'; then $(CYGPATH_W) 'libarchive/archive_rb.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_rb.c'; fi` + +libarchive/libarchive_test-archive_read.o: libarchive/archive_read.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read.Tpo -c -o libarchive/libarchive_test-archive_read.o `test -f 'libarchive/archive_read.c' || echo '$(srcdir)/'`libarchive/archive_read.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read.c' object='libarchive/libarchive_test-archive_read.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read.o `test -f 'libarchive/archive_read.c' || echo '$(srcdir)/'`libarchive/archive_read.c + +libarchive/libarchive_test-archive_read.obj: libarchive/archive_read.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read.Tpo -c -o libarchive/libarchive_test-archive_read.obj `if test -f 'libarchive/archive_read.c'; then $(CYGPATH_W) 'libarchive/archive_read.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read.c' object='libarchive/libarchive_test-archive_read.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read.obj `if test -f 'libarchive/archive_read.c'; then $(CYGPATH_W) 'libarchive/archive_read.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read.c'; fi` + +libarchive/libarchive_test-archive_read_add_passphrase.o: libarchive/archive_read_add_passphrase.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_add_passphrase.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_add_passphrase.Tpo -c -o libarchive/libarchive_test-archive_read_add_passphrase.o `test -f 'libarchive/archive_read_add_passphrase.c' || echo '$(srcdir)/'`libarchive/archive_read_add_passphrase.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_add_passphrase.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_add_passphrase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_add_passphrase.c' object='libarchive/libarchive_test-archive_read_add_passphrase.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_add_passphrase.o `test -f 'libarchive/archive_read_add_passphrase.c' || echo '$(srcdir)/'`libarchive/archive_read_add_passphrase.c + +libarchive/libarchive_test-archive_read_add_passphrase.obj: libarchive/archive_read_add_passphrase.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_add_passphrase.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_add_passphrase.Tpo -c -o libarchive/libarchive_test-archive_read_add_passphrase.obj `if test -f 'libarchive/archive_read_add_passphrase.c'; then $(CYGPATH_W) 'libarchive/archive_read_add_passphrase.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_add_passphrase.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_add_passphrase.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_add_passphrase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_add_passphrase.c' object='libarchive/libarchive_test-archive_read_add_passphrase.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_add_passphrase.obj `if test -f 'libarchive/archive_read_add_passphrase.c'; then $(CYGPATH_W) 'libarchive/archive_read_add_passphrase.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_add_passphrase.c'; fi` + +libarchive/libarchive_test-archive_read_append_filter.o: libarchive/archive_read_append_filter.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_append_filter.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_append_filter.Tpo -c -o libarchive/libarchive_test-archive_read_append_filter.o `test -f 'libarchive/archive_read_append_filter.c' || echo '$(srcdir)/'`libarchive/archive_read_append_filter.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_append_filter.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_append_filter.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_append_filter.c' object='libarchive/libarchive_test-archive_read_append_filter.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_append_filter.o `test -f 'libarchive/archive_read_append_filter.c' || echo '$(srcdir)/'`libarchive/archive_read_append_filter.c + +libarchive/libarchive_test-archive_read_append_filter.obj: libarchive/archive_read_append_filter.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_append_filter.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_append_filter.Tpo -c -o libarchive/libarchive_test-archive_read_append_filter.obj `if test -f 'libarchive/archive_read_append_filter.c'; then $(CYGPATH_W) 'libarchive/archive_read_append_filter.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_append_filter.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_append_filter.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_append_filter.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_append_filter.c' object='libarchive/libarchive_test-archive_read_append_filter.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_append_filter.obj `if test -f 'libarchive/archive_read_append_filter.c'; then $(CYGPATH_W) 'libarchive/archive_read_append_filter.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_append_filter.c'; fi` + +libarchive/libarchive_test-archive_read_data_into_fd.o: libarchive/archive_read_data_into_fd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_data_into_fd.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_data_into_fd.Tpo -c -o libarchive/libarchive_test-archive_read_data_into_fd.o `test -f 'libarchive/archive_read_data_into_fd.c' || echo '$(srcdir)/'`libarchive/archive_read_data_into_fd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_data_into_fd.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_data_into_fd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_data_into_fd.c' object='libarchive/libarchive_test-archive_read_data_into_fd.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_data_into_fd.o `test -f 'libarchive/archive_read_data_into_fd.c' || echo '$(srcdir)/'`libarchive/archive_read_data_into_fd.c + +libarchive/libarchive_test-archive_read_data_into_fd.obj: libarchive/archive_read_data_into_fd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_data_into_fd.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_data_into_fd.Tpo -c -o libarchive/libarchive_test-archive_read_data_into_fd.obj `if test -f 'libarchive/archive_read_data_into_fd.c'; then $(CYGPATH_W) 'libarchive/archive_read_data_into_fd.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_data_into_fd.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_data_into_fd.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_data_into_fd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_data_into_fd.c' object='libarchive/libarchive_test-archive_read_data_into_fd.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_data_into_fd.obj `if test -f 'libarchive/archive_read_data_into_fd.c'; then $(CYGPATH_W) 'libarchive/archive_read_data_into_fd.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_data_into_fd.c'; fi` + +libarchive/libarchive_test-archive_read_disk_entry_from_file.o: libarchive/archive_read_disk_entry_from_file.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_disk_entry_from_file.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_entry_from_file.Tpo -c -o libarchive/libarchive_test-archive_read_disk_entry_from_file.o `test -f 'libarchive/archive_read_disk_entry_from_file.c' || echo '$(srcdir)/'`libarchive/archive_read_disk_entry_from_file.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_entry_from_file.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_entry_from_file.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_disk_entry_from_file.c' object='libarchive/libarchive_test-archive_read_disk_entry_from_file.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_disk_entry_from_file.o `test -f 'libarchive/archive_read_disk_entry_from_file.c' || echo '$(srcdir)/'`libarchive/archive_read_disk_entry_from_file.c + +libarchive/libarchive_test-archive_read_disk_entry_from_file.obj: libarchive/archive_read_disk_entry_from_file.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_disk_entry_from_file.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_entry_from_file.Tpo -c -o libarchive/libarchive_test-archive_read_disk_entry_from_file.obj `if test -f 'libarchive/archive_read_disk_entry_from_file.c'; then $(CYGPATH_W) 'libarchive/archive_read_disk_entry_from_file.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_disk_entry_from_file.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_entry_from_file.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_entry_from_file.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_disk_entry_from_file.c' object='libarchive/libarchive_test-archive_read_disk_entry_from_file.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_disk_entry_from_file.obj `if test -f 'libarchive/archive_read_disk_entry_from_file.c'; then $(CYGPATH_W) 'libarchive/archive_read_disk_entry_from_file.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_disk_entry_from_file.c'; fi` + +libarchive/libarchive_test-archive_read_disk_posix.o: libarchive/archive_read_disk_posix.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_disk_posix.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_posix.Tpo -c -o libarchive/libarchive_test-archive_read_disk_posix.o `test -f 'libarchive/archive_read_disk_posix.c' || echo '$(srcdir)/'`libarchive/archive_read_disk_posix.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_posix.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_posix.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_disk_posix.c' object='libarchive/libarchive_test-archive_read_disk_posix.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_disk_posix.o `test -f 'libarchive/archive_read_disk_posix.c' || echo '$(srcdir)/'`libarchive/archive_read_disk_posix.c + +libarchive/libarchive_test-archive_read_disk_posix.obj: libarchive/archive_read_disk_posix.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_disk_posix.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_posix.Tpo -c -o libarchive/libarchive_test-archive_read_disk_posix.obj `if test -f 'libarchive/archive_read_disk_posix.c'; then $(CYGPATH_W) 'libarchive/archive_read_disk_posix.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_disk_posix.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_posix.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_posix.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_disk_posix.c' object='libarchive/libarchive_test-archive_read_disk_posix.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_disk_posix.obj `if test -f 'libarchive/archive_read_disk_posix.c'; then $(CYGPATH_W) 'libarchive/archive_read_disk_posix.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_disk_posix.c'; fi` + +libarchive/libarchive_test-archive_read_disk_set_standard_lookup.o: libarchive/archive_read_disk_set_standard_lookup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_disk_set_standard_lookup.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_set_standard_lookup.Tpo -c -o libarchive/libarchive_test-archive_read_disk_set_standard_lookup.o `test -f 'libarchive/archive_read_disk_set_standard_lookup.c' || echo '$(srcdir)/'`libarchive/archive_read_disk_set_standard_lookup.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_set_standard_lookup.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_set_standard_lookup.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_disk_set_standard_lookup.c' object='libarchive/libarchive_test-archive_read_disk_set_standard_lookup.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_disk_set_standard_lookup.o `test -f 'libarchive/archive_read_disk_set_standard_lookup.c' || echo '$(srcdir)/'`libarchive/archive_read_disk_set_standard_lookup.c + +libarchive/libarchive_test-archive_read_disk_set_standard_lookup.obj: libarchive/archive_read_disk_set_standard_lookup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_disk_set_standard_lookup.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_set_standard_lookup.Tpo -c -o libarchive/libarchive_test-archive_read_disk_set_standard_lookup.obj `if test -f 'libarchive/archive_read_disk_set_standard_lookup.c'; then $(CYGPATH_W) 'libarchive/archive_read_disk_set_standard_lookup.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_disk_set_standard_lookup.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_set_standard_lookup.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_set_standard_lookup.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_disk_set_standard_lookup.c' object='libarchive/libarchive_test-archive_read_disk_set_standard_lookup.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_disk_set_standard_lookup.obj `if test -f 'libarchive/archive_read_disk_set_standard_lookup.c'; then $(CYGPATH_W) 'libarchive/archive_read_disk_set_standard_lookup.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_disk_set_standard_lookup.c'; fi` + +libarchive/libarchive_test-archive_read_extract.o: libarchive/archive_read_extract.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_extract.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_extract.Tpo -c -o libarchive/libarchive_test-archive_read_extract.o `test -f 'libarchive/archive_read_extract.c' || echo '$(srcdir)/'`libarchive/archive_read_extract.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_extract.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_extract.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_extract.c' object='libarchive/libarchive_test-archive_read_extract.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_extract.o `test -f 'libarchive/archive_read_extract.c' || echo '$(srcdir)/'`libarchive/archive_read_extract.c + +libarchive/libarchive_test-archive_read_extract.obj: libarchive/archive_read_extract.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_extract.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_extract.Tpo -c -o libarchive/libarchive_test-archive_read_extract.obj `if test -f 'libarchive/archive_read_extract.c'; then $(CYGPATH_W) 'libarchive/archive_read_extract.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_extract.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_extract.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_extract.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_extract.c' object='libarchive/libarchive_test-archive_read_extract.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_extract.obj `if test -f 'libarchive/archive_read_extract.c'; then $(CYGPATH_W) 'libarchive/archive_read_extract.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_extract.c'; fi` + +libarchive/libarchive_test-archive_read_extract2.o: libarchive/archive_read_extract2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_extract2.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_extract2.Tpo -c -o libarchive/libarchive_test-archive_read_extract2.o `test -f 'libarchive/archive_read_extract2.c' || echo '$(srcdir)/'`libarchive/archive_read_extract2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_extract2.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_extract2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_extract2.c' object='libarchive/libarchive_test-archive_read_extract2.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_extract2.o `test -f 'libarchive/archive_read_extract2.c' || echo '$(srcdir)/'`libarchive/archive_read_extract2.c + +libarchive/libarchive_test-archive_read_extract2.obj: libarchive/archive_read_extract2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_extract2.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_extract2.Tpo -c -o libarchive/libarchive_test-archive_read_extract2.obj `if test -f 'libarchive/archive_read_extract2.c'; then $(CYGPATH_W) 'libarchive/archive_read_extract2.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_extract2.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_extract2.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_extract2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_extract2.c' object='libarchive/libarchive_test-archive_read_extract2.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_extract2.obj `if test -f 'libarchive/archive_read_extract2.c'; then $(CYGPATH_W) 'libarchive/archive_read_extract2.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_extract2.c'; fi` + +libarchive/libarchive_test-archive_read_open_fd.o: libarchive/archive_read_open_fd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_open_fd.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_open_fd.Tpo -c -o libarchive/libarchive_test-archive_read_open_fd.o `test -f 'libarchive/archive_read_open_fd.c' || echo '$(srcdir)/'`libarchive/archive_read_open_fd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_open_fd.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_open_fd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_open_fd.c' object='libarchive/libarchive_test-archive_read_open_fd.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_open_fd.o `test -f 'libarchive/archive_read_open_fd.c' || echo '$(srcdir)/'`libarchive/archive_read_open_fd.c + +libarchive/libarchive_test-archive_read_open_fd.obj: libarchive/archive_read_open_fd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_open_fd.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_open_fd.Tpo -c -o libarchive/libarchive_test-archive_read_open_fd.obj `if test -f 'libarchive/archive_read_open_fd.c'; then $(CYGPATH_W) 'libarchive/archive_read_open_fd.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_open_fd.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_open_fd.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_open_fd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_open_fd.c' object='libarchive/libarchive_test-archive_read_open_fd.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_open_fd.obj `if test -f 'libarchive/archive_read_open_fd.c'; then $(CYGPATH_W) 'libarchive/archive_read_open_fd.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_open_fd.c'; fi` + +libarchive/libarchive_test-archive_read_open_file.o: libarchive/archive_read_open_file.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_open_file.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_open_file.Tpo -c -o libarchive/libarchive_test-archive_read_open_file.o `test -f 'libarchive/archive_read_open_file.c' || echo '$(srcdir)/'`libarchive/archive_read_open_file.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_open_file.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_open_file.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_open_file.c' object='libarchive/libarchive_test-archive_read_open_file.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_open_file.o `test -f 'libarchive/archive_read_open_file.c' || echo '$(srcdir)/'`libarchive/archive_read_open_file.c + +libarchive/libarchive_test-archive_read_open_file.obj: libarchive/archive_read_open_file.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_open_file.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_open_file.Tpo -c -o libarchive/libarchive_test-archive_read_open_file.obj `if test -f 'libarchive/archive_read_open_file.c'; then $(CYGPATH_W) 'libarchive/archive_read_open_file.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_open_file.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_open_file.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_open_file.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_open_file.c' object='libarchive/libarchive_test-archive_read_open_file.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_open_file.obj `if test -f 'libarchive/archive_read_open_file.c'; then $(CYGPATH_W) 'libarchive/archive_read_open_file.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_open_file.c'; fi` + +libarchive/libarchive_test-archive_read_open_filename.o: libarchive/archive_read_open_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_open_filename.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_open_filename.Tpo -c -o libarchive/libarchive_test-archive_read_open_filename.o `test -f 'libarchive/archive_read_open_filename.c' || echo '$(srcdir)/'`libarchive/archive_read_open_filename.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_open_filename.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_open_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_open_filename.c' object='libarchive/libarchive_test-archive_read_open_filename.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_open_filename.o `test -f 'libarchive/archive_read_open_filename.c' || echo '$(srcdir)/'`libarchive/archive_read_open_filename.c + +libarchive/libarchive_test-archive_read_open_filename.obj: libarchive/archive_read_open_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_open_filename.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_open_filename.Tpo -c -o libarchive/libarchive_test-archive_read_open_filename.obj `if test -f 'libarchive/archive_read_open_filename.c'; then $(CYGPATH_W) 'libarchive/archive_read_open_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_open_filename.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_open_filename.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_open_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_open_filename.c' object='libarchive/libarchive_test-archive_read_open_filename.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_open_filename.obj `if test -f 'libarchive/archive_read_open_filename.c'; then $(CYGPATH_W) 'libarchive/archive_read_open_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_open_filename.c'; fi` + +libarchive/libarchive_test-archive_read_open_memory.o: libarchive/archive_read_open_memory.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_open_memory.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_open_memory.Tpo -c -o libarchive/libarchive_test-archive_read_open_memory.o `test -f 'libarchive/archive_read_open_memory.c' || echo '$(srcdir)/'`libarchive/archive_read_open_memory.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_open_memory.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_open_memory.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_open_memory.c' object='libarchive/libarchive_test-archive_read_open_memory.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_open_memory.o `test -f 'libarchive/archive_read_open_memory.c' || echo '$(srcdir)/'`libarchive/archive_read_open_memory.c + +libarchive/libarchive_test-archive_read_open_memory.obj: libarchive/archive_read_open_memory.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_open_memory.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_open_memory.Tpo -c -o libarchive/libarchive_test-archive_read_open_memory.obj `if test -f 'libarchive/archive_read_open_memory.c'; then $(CYGPATH_W) 'libarchive/archive_read_open_memory.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_open_memory.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_open_memory.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_open_memory.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_open_memory.c' object='libarchive/libarchive_test-archive_read_open_memory.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_open_memory.obj `if test -f 'libarchive/archive_read_open_memory.c'; then $(CYGPATH_W) 'libarchive/archive_read_open_memory.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_open_memory.c'; fi` + +libarchive/libarchive_test-archive_read_set_format.o: libarchive/archive_read_set_format.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_set_format.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_set_format.Tpo -c -o libarchive/libarchive_test-archive_read_set_format.o `test -f 'libarchive/archive_read_set_format.c' || echo '$(srcdir)/'`libarchive/archive_read_set_format.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_set_format.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_set_format.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_set_format.c' object='libarchive/libarchive_test-archive_read_set_format.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_set_format.o `test -f 'libarchive/archive_read_set_format.c' || echo '$(srcdir)/'`libarchive/archive_read_set_format.c + +libarchive/libarchive_test-archive_read_set_format.obj: libarchive/archive_read_set_format.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_set_format.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_set_format.Tpo -c -o libarchive/libarchive_test-archive_read_set_format.obj `if test -f 'libarchive/archive_read_set_format.c'; then $(CYGPATH_W) 'libarchive/archive_read_set_format.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_set_format.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_set_format.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_set_format.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_set_format.c' object='libarchive/libarchive_test-archive_read_set_format.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_set_format.obj `if test -f 'libarchive/archive_read_set_format.c'; then $(CYGPATH_W) 'libarchive/archive_read_set_format.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_set_format.c'; fi` + +libarchive/libarchive_test-archive_read_set_options.o: libarchive/archive_read_set_options.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_set_options.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_set_options.Tpo -c -o libarchive/libarchive_test-archive_read_set_options.o `test -f 'libarchive/archive_read_set_options.c' || echo '$(srcdir)/'`libarchive/archive_read_set_options.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_set_options.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_set_options.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_set_options.c' object='libarchive/libarchive_test-archive_read_set_options.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_set_options.o `test -f 'libarchive/archive_read_set_options.c' || echo '$(srcdir)/'`libarchive/archive_read_set_options.c + +libarchive/libarchive_test-archive_read_set_options.obj: libarchive/archive_read_set_options.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_set_options.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_set_options.Tpo -c -o libarchive/libarchive_test-archive_read_set_options.obj `if test -f 'libarchive/archive_read_set_options.c'; then $(CYGPATH_W) 'libarchive/archive_read_set_options.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_set_options.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_set_options.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_set_options.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_set_options.c' object='libarchive/libarchive_test-archive_read_set_options.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_set_options.obj `if test -f 'libarchive/archive_read_set_options.c'; then $(CYGPATH_W) 'libarchive/archive_read_set_options.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_set_options.c'; fi` + +libarchive/libarchive_test-archive_read_support_filter_all.o: libarchive/archive_read_support_filter_all.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_all.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_all.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_all.o `test -f 'libarchive/archive_read_support_filter_all.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_all.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_all.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_all.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_all.c' object='libarchive/libarchive_test-archive_read_support_filter_all.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_all.o `test -f 'libarchive/archive_read_support_filter_all.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_all.c + +libarchive/libarchive_test-archive_read_support_filter_all.obj: libarchive/archive_read_support_filter_all.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_all.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_all.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_all.obj `if test -f 'libarchive/archive_read_support_filter_all.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_all.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_all.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_all.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_all.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_all.c' object='libarchive/libarchive_test-archive_read_support_filter_all.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_all.obj `if test -f 'libarchive/archive_read_support_filter_all.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_all.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_all.c'; fi` + +libarchive/libarchive_test-archive_read_support_filter_bzip2.o: libarchive/archive_read_support_filter_bzip2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_bzip2.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_bzip2.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_bzip2.o `test -f 'libarchive/archive_read_support_filter_bzip2.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_bzip2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_bzip2.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_bzip2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_bzip2.c' object='libarchive/libarchive_test-archive_read_support_filter_bzip2.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_bzip2.o `test -f 'libarchive/archive_read_support_filter_bzip2.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_bzip2.c + +libarchive/libarchive_test-archive_read_support_filter_bzip2.obj: libarchive/archive_read_support_filter_bzip2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_bzip2.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_bzip2.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_bzip2.obj `if test -f 'libarchive/archive_read_support_filter_bzip2.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_bzip2.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_bzip2.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_bzip2.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_bzip2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_bzip2.c' object='libarchive/libarchive_test-archive_read_support_filter_bzip2.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_bzip2.obj `if test -f 'libarchive/archive_read_support_filter_bzip2.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_bzip2.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_bzip2.c'; fi` + +libarchive/libarchive_test-archive_read_support_filter_compress.o: libarchive/archive_read_support_filter_compress.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_compress.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_compress.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_compress.o `test -f 'libarchive/archive_read_support_filter_compress.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_compress.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_compress.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_compress.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_compress.c' object='libarchive/libarchive_test-archive_read_support_filter_compress.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_compress.o `test -f 'libarchive/archive_read_support_filter_compress.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_compress.c + +libarchive/libarchive_test-archive_read_support_filter_compress.obj: libarchive/archive_read_support_filter_compress.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_compress.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_compress.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_compress.obj `if test -f 'libarchive/archive_read_support_filter_compress.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_compress.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_compress.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_compress.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_compress.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_compress.c' object='libarchive/libarchive_test-archive_read_support_filter_compress.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_compress.obj `if test -f 'libarchive/archive_read_support_filter_compress.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_compress.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_compress.c'; fi` + +libarchive/libarchive_test-archive_read_support_filter_grzip.o: libarchive/archive_read_support_filter_grzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_grzip.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_grzip.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_grzip.o `test -f 'libarchive/archive_read_support_filter_grzip.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_grzip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_grzip.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_grzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_grzip.c' object='libarchive/libarchive_test-archive_read_support_filter_grzip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_grzip.o `test -f 'libarchive/archive_read_support_filter_grzip.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_grzip.c + +libarchive/libarchive_test-archive_read_support_filter_grzip.obj: libarchive/archive_read_support_filter_grzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_grzip.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_grzip.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_grzip.obj `if test -f 'libarchive/archive_read_support_filter_grzip.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_grzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_grzip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_grzip.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_grzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_grzip.c' object='libarchive/libarchive_test-archive_read_support_filter_grzip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_grzip.obj `if test -f 'libarchive/archive_read_support_filter_grzip.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_grzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_grzip.c'; fi` + +libarchive/libarchive_test-archive_read_support_filter_gzip.o: libarchive/archive_read_support_filter_gzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_gzip.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_gzip.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_gzip.o `test -f 'libarchive/archive_read_support_filter_gzip.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_gzip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_gzip.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_gzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_gzip.c' object='libarchive/libarchive_test-archive_read_support_filter_gzip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_gzip.o `test -f 'libarchive/archive_read_support_filter_gzip.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_gzip.c + +libarchive/libarchive_test-archive_read_support_filter_gzip.obj: libarchive/archive_read_support_filter_gzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_gzip.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_gzip.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_gzip.obj `if test -f 'libarchive/archive_read_support_filter_gzip.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_gzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_gzip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_gzip.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_gzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_gzip.c' object='libarchive/libarchive_test-archive_read_support_filter_gzip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_gzip.obj `if test -f 'libarchive/archive_read_support_filter_gzip.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_gzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_gzip.c'; fi` + +libarchive/libarchive_test-archive_read_support_filter_lrzip.o: libarchive/archive_read_support_filter_lrzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_lrzip.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_lrzip.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_lrzip.o `test -f 'libarchive/archive_read_support_filter_lrzip.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_lrzip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_lrzip.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_lrzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_lrzip.c' object='libarchive/libarchive_test-archive_read_support_filter_lrzip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_lrzip.o `test -f 'libarchive/archive_read_support_filter_lrzip.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_lrzip.c + +libarchive/libarchive_test-archive_read_support_filter_lrzip.obj: libarchive/archive_read_support_filter_lrzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_lrzip.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_lrzip.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_lrzip.obj `if test -f 'libarchive/archive_read_support_filter_lrzip.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_lrzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_lrzip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_lrzip.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_lrzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_lrzip.c' object='libarchive/libarchive_test-archive_read_support_filter_lrzip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_lrzip.obj `if test -f 'libarchive/archive_read_support_filter_lrzip.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_lrzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_lrzip.c'; fi` + +libarchive/libarchive_test-archive_read_support_filter_lz4.o: libarchive/archive_read_support_filter_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_lz4.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_lz4.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_lz4.o `test -f 'libarchive/archive_read_support_filter_lz4.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_lz4.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_lz4.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_lz4.c' object='libarchive/libarchive_test-archive_read_support_filter_lz4.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_lz4.o `test -f 'libarchive/archive_read_support_filter_lz4.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_lz4.c + +libarchive/libarchive_test-archive_read_support_filter_lz4.obj: libarchive/archive_read_support_filter_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_lz4.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_lz4.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_lz4.obj `if test -f 'libarchive/archive_read_support_filter_lz4.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_lz4.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_lz4.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_lz4.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_lz4.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_lz4.c' object='libarchive/libarchive_test-archive_read_support_filter_lz4.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_lz4.obj `if test -f 'libarchive/archive_read_support_filter_lz4.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_lz4.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_lz4.c'; fi` + +libarchive/libarchive_test-archive_read_support_filter_lzop.o: libarchive/archive_read_support_filter_lzop.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_lzop.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_lzop.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_lzop.o `test -f 'libarchive/archive_read_support_filter_lzop.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_lzop.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_lzop.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_lzop.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_lzop.c' object='libarchive/libarchive_test-archive_read_support_filter_lzop.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_lzop.o `test -f 'libarchive/archive_read_support_filter_lzop.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_lzop.c + +libarchive/libarchive_test-archive_read_support_filter_lzop.obj: libarchive/archive_read_support_filter_lzop.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_lzop.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_lzop.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_lzop.obj `if test -f 'libarchive/archive_read_support_filter_lzop.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_lzop.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_lzop.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_lzop.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_lzop.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_lzop.c' object='libarchive/libarchive_test-archive_read_support_filter_lzop.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_lzop.obj `if test -f 'libarchive/archive_read_support_filter_lzop.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_lzop.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_lzop.c'; fi` + +libarchive/libarchive_test-archive_read_support_filter_none.o: libarchive/archive_read_support_filter_none.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_none.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_none.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_none.o `test -f 'libarchive/archive_read_support_filter_none.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_none.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_none.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_none.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_none.c' object='libarchive/libarchive_test-archive_read_support_filter_none.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_none.o `test -f 'libarchive/archive_read_support_filter_none.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_none.c + +libarchive/libarchive_test-archive_read_support_filter_none.obj: libarchive/archive_read_support_filter_none.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_none.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_none.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_none.obj `if test -f 'libarchive/archive_read_support_filter_none.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_none.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_none.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_none.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_none.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_none.c' object='libarchive/libarchive_test-archive_read_support_filter_none.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_none.obj `if test -f 'libarchive/archive_read_support_filter_none.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_none.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_none.c'; fi` + +libarchive/libarchive_test-archive_read_support_filter_program.o: libarchive/archive_read_support_filter_program.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_program.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_program.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_program.o `test -f 'libarchive/archive_read_support_filter_program.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_program.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_program.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_program.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_program.c' object='libarchive/libarchive_test-archive_read_support_filter_program.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_program.o `test -f 'libarchive/archive_read_support_filter_program.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_program.c + +libarchive/libarchive_test-archive_read_support_filter_program.obj: libarchive/archive_read_support_filter_program.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_program.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_program.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_program.obj `if test -f 'libarchive/archive_read_support_filter_program.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_program.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_program.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_program.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_program.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_program.c' object='libarchive/libarchive_test-archive_read_support_filter_program.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_program.obj `if test -f 'libarchive/archive_read_support_filter_program.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_program.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_program.c'; fi` + +libarchive/libarchive_test-archive_read_support_filter_rpm.o: libarchive/archive_read_support_filter_rpm.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_rpm.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_rpm.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_rpm.o `test -f 'libarchive/archive_read_support_filter_rpm.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_rpm.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_rpm.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_rpm.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_rpm.c' object='libarchive/libarchive_test-archive_read_support_filter_rpm.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_rpm.o `test -f 'libarchive/archive_read_support_filter_rpm.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_rpm.c + +libarchive/libarchive_test-archive_read_support_filter_rpm.obj: libarchive/archive_read_support_filter_rpm.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_rpm.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_rpm.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_rpm.obj `if test -f 'libarchive/archive_read_support_filter_rpm.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_rpm.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_rpm.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_rpm.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_rpm.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_rpm.c' object='libarchive/libarchive_test-archive_read_support_filter_rpm.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_rpm.obj `if test -f 'libarchive/archive_read_support_filter_rpm.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_rpm.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_rpm.c'; fi` + +libarchive/libarchive_test-archive_read_support_filter_uu.o: libarchive/archive_read_support_filter_uu.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_uu.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_uu.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_uu.o `test -f 'libarchive/archive_read_support_filter_uu.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_uu.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_uu.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_uu.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_uu.c' object='libarchive/libarchive_test-archive_read_support_filter_uu.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_uu.o `test -f 'libarchive/archive_read_support_filter_uu.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_uu.c + +libarchive/libarchive_test-archive_read_support_filter_uu.obj: libarchive/archive_read_support_filter_uu.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_uu.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_uu.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_uu.obj `if test -f 'libarchive/archive_read_support_filter_uu.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_uu.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_uu.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_uu.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_uu.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_uu.c' object='libarchive/libarchive_test-archive_read_support_filter_uu.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_uu.obj `if test -f 'libarchive/archive_read_support_filter_uu.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_uu.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_uu.c'; fi` + +libarchive/libarchive_test-archive_read_support_filter_xz.o: libarchive/archive_read_support_filter_xz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_xz.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_xz.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_xz.o `test -f 'libarchive/archive_read_support_filter_xz.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_xz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_xz.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_xz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_xz.c' object='libarchive/libarchive_test-archive_read_support_filter_xz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_xz.o `test -f 'libarchive/archive_read_support_filter_xz.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_xz.c + +libarchive/libarchive_test-archive_read_support_filter_xz.obj: libarchive/archive_read_support_filter_xz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_xz.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_xz.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_xz.obj `if test -f 'libarchive/archive_read_support_filter_xz.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_xz.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_xz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_xz.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_xz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_xz.c' object='libarchive/libarchive_test-archive_read_support_filter_xz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_xz.obj `if test -f 'libarchive/archive_read_support_filter_xz.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_xz.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_xz.c'; fi` + +libarchive/libarchive_test-archive_read_support_filter_zstd.o: libarchive/archive_read_support_filter_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_zstd.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_zstd.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_zstd.o `test -f 'libarchive/archive_read_support_filter_zstd.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_zstd.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_zstd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_zstd.c' object='libarchive/libarchive_test-archive_read_support_filter_zstd.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_zstd.o `test -f 'libarchive/archive_read_support_filter_zstd.c' || echo '$(srcdir)/'`libarchive/archive_read_support_filter_zstd.c + +libarchive/libarchive_test-archive_read_support_filter_zstd.obj: libarchive/archive_read_support_filter_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_filter_zstd.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_zstd.Tpo -c -o libarchive/libarchive_test-archive_read_support_filter_zstd.obj `if test -f 'libarchive/archive_read_support_filter_zstd.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_zstd.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_zstd.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_zstd.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_filter_zstd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_filter_zstd.c' object='libarchive/libarchive_test-archive_read_support_filter_zstd.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_filter_zstd.obj `if test -f 'libarchive/archive_read_support_filter_zstd.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_filter_zstd.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_filter_zstd.c'; fi` + +libarchive/libarchive_test-archive_read_support_format_7zip.o: libarchive/archive_read_support_format_7zip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_7zip.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_7zip.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_7zip.o `test -f 'libarchive/archive_read_support_format_7zip.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_7zip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_7zip.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_7zip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_7zip.c' object='libarchive/libarchive_test-archive_read_support_format_7zip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_7zip.o `test -f 'libarchive/archive_read_support_format_7zip.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_7zip.c + +libarchive/libarchive_test-archive_read_support_format_7zip.obj: libarchive/archive_read_support_format_7zip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_7zip.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_7zip.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_7zip.obj `if test -f 'libarchive/archive_read_support_format_7zip.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_7zip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_7zip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_7zip.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_7zip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_7zip.c' object='libarchive/libarchive_test-archive_read_support_format_7zip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_7zip.obj `if test -f 'libarchive/archive_read_support_format_7zip.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_7zip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_7zip.c'; fi` + +libarchive/libarchive_test-archive_read_support_format_all.o: libarchive/archive_read_support_format_all.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_all.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_all.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_all.o `test -f 'libarchive/archive_read_support_format_all.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_all.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_all.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_all.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_all.c' object='libarchive/libarchive_test-archive_read_support_format_all.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_all.o `test -f 'libarchive/archive_read_support_format_all.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_all.c + +libarchive/libarchive_test-archive_read_support_format_all.obj: libarchive/archive_read_support_format_all.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_all.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_all.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_all.obj `if test -f 'libarchive/archive_read_support_format_all.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_all.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_all.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_all.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_all.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_all.c' object='libarchive/libarchive_test-archive_read_support_format_all.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_all.obj `if test -f 'libarchive/archive_read_support_format_all.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_all.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_all.c'; fi` + +libarchive/libarchive_test-archive_read_support_format_ar.o: libarchive/archive_read_support_format_ar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_ar.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_ar.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_ar.o `test -f 'libarchive/archive_read_support_format_ar.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_ar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_ar.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_ar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_ar.c' object='libarchive/libarchive_test-archive_read_support_format_ar.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_ar.o `test -f 'libarchive/archive_read_support_format_ar.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_ar.c + +libarchive/libarchive_test-archive_read_support_format_ar.obj: libarchive/archive_read_support_format_ar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_ar.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_ar.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_ar.obj `if test -f 'libarchive/archive_read_support_format_ar.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_ar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_ar.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_ar.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_ar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_ar.c' object='libarchive/libarchive_test-archive_read_support_format_ar.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_ar.obj `if test -f 'libarchive/archive_read_support_format_ar.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_ar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_ar.c'; fi` + +libarchive/libarchive_test-archive_read_support_format_by_code.o: libarchive/archive_read_support_format_by_code.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_by_code.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_by_code.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_by_code.o `test -f 'libarchive/archive_read_support_format_by_code.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_by_code.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_by_code.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_by_code.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_by_code.c' object='libarchive/libarchive_test-archive_read_support_format_by_code.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_by_code.o `test -f 'libarchive/archive_read_support_format_by_code.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_by_code.c + +libarchive/libarchive_test-archive_read_support_format_by_code.obj: libarchive/archive_read_support_format_by_code.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_by_code.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_by_code.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_by_code.obj `if test -f 'libarchive/archive_read_support_format_by_code.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_by_code.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_by_code.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_by_code.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_by_code.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_by_code.c' object='libarchive/libarchive_test-archive_read_support_format_by_code.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_by_code.obj `if test -f 'libarchive/archive_read_support_format_by_code.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_by_code.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_by_code.c'; fi` + +libarchive/libarchive_test-archive_read_support_format_cab.o: libarchive/archive_read_support_format_cab.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_cab.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_cab.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_cab.o `test -f 'libarchive/archive_read_support_format_cab.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_cab.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_cab.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_cab.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_cab.c' object='libarchive/libarchive_test-archive_read_support_format_cab.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_cab.o `test -f 'libarchive/archive_read_support_format_cab.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_cab.c + +libarchive/libarchive_test-archive_read_support_format_cab.obj: libarchive/archive_read_support_format_cab.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_cab.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_cab.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_cab.obj `if test -f 'libarchive/archive_read_support_format_cab.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_cab.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_cab.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_cab.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_cab.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_cab.c' object='libarchive/libarchive_test-archive_read_support_format_cab.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_cab.obj `if test -f 'libarchive/archive_read_support_format_cab.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_cab.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_cab.c'; fi` + +libarchive/libarchive_test-archive_read_support_format_cpio.o: libarchive/archive_read_support_format_cpio.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_cpio.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_cpio.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_cpio.o `test -f 'libarchive/archive_read_support_format_cpio.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_cpio.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_cpio.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_cpio.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_cpio.c' object='libarchive/libarchive_test-archive_read_support_format_cpio.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_cpio.o `test -f 'libarchive/archive_read_support_format_cpio.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_cpio.c + +libarchive/libarchive_test-archive_read_support_format_cpio.obj: libarchive/archive_read_support_format_cpio.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_cpio.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_cpio.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_cpio.obj `if test -f 'libarchive/archive_read_support_format_cpio.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_cpio.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_cpio.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_cpio.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_cpio.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_cpio.c' object='libarchive/libarchive_test-archive_read_support_format_cpio.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_cpio.obj `if test -f 'libarchive/archive_read_support_format_cpio.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_cpio.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_cpio.c'; fi` + +libarchive/libarchive_test-archive_read_support_format_empty.o: libarchive/archive_read_support_format_empty.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_empty.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_empty.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_empty.o `test -f 'libarchive/archive_read_support_format_empty.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_empty.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_empty.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_empty.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_empty.c' object='libarchive/libarchive_test-archive_read_support_format_empty.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_empty.o `test -f 'libarchive/archive_read_support_format_empty.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_empty.c + +libarchive/libarchive_test-archive_read_support_format_empty.obj: libarchive/archive_read_support_format_empty.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_empty.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_empty.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_empty.obj `if test -f 'libarchive/archive_read_support_format_empty.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_empty.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_empty.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_empty.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_empty.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_empty.c' object='libarchive/libarchive_test-archive_read_support_format_empty.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_empty.obj `if test -f 'libarchive/archive_read_support_format_empty.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_empty.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_empty.c'; fi` + +libarchive/libarchive_test-archive_read_support_format_iso9660.o: libarchive/archive_read_support_format_iso9660.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_iso9660.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_iso9660.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_iso9660.o `test -f 'libarchive/archive_read_support_format_iso9660.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_iso9660.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_iso9660.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_iso9660.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_iso9660.c' object='libarchive/libarchive_test-archive_read_support_format_iso9660.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_iso9660.o `test -f 'libarchive/archive_read_support_format_iso9660.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_iso9660.c + +libarchive/libarchive_test-archive_read_support_format_iso9660.obj: libarchive/archive_read_support_format_iso9660.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_iso9660.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_iso9660.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_iso9660.obj `if test -f 'libarchive/archive_read_support_format_iso9660.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_iso9660.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_iso9660.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_iso9660.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_iso9660.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_iso9660.c' object='libarchive/libarchive_test-archive_read_support_format_iso9660.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_iso9660.obj `if test -f 'libarchive/archive_read_support_format_iso9660.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_iso9660.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_iso9660.c'; fi` + +libarchive/libarchive_test-archive_read_support_format_lha.o: libarchive/archive_read_support_format_lha.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_lha.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_lha.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_lha.o `test -f 'libarchive/archive_read_support_format_lha.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_lha.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_lha.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_lha.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_lha.c' object='libarchive/libarchive_test-archive_read_support_format_lha.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_lha.o `test -f 'libarchive/archive_read_support_format_lha.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_lha.c + +libarchive/libarchive_test-archive_read_support_format_lha.obj: libarchive/archive_read_support_format_lha.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_lha.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_lha.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_lha.obj `if test -f 'libarchive/archive_read_support_format_lha.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_lha.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_lha.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_lha.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_lha.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_lha.c' object='libarchive/libarchive_test-archive_read_support_format_lha.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_lha.obj `if test -f 'libarchive/archive_read_support_format_lha.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_lha.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_lha.c'; fi` + +libarchive/libarchive_test-archive_read_support_format_mtree.o: libarchive/archive_read_support_format_mtree.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_mtree.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_mtree.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_mtree.o `test -f 'libarchive/archive_read_support_format_mtree.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_mtree.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_mtree.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_mtree.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_mtree.c' object='libarchive/libarchive_test-archive_read_support_format_mtree.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_mtree.o `test -f 'libarchive/archive_read_support_format_mtree.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_mtree.c + +libarchive/libarchive_test-archive_read_support_format_mtree.obj: libarchive/archive_read_support_format_mtree.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_mtree.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_mtree.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_mtree.obj `if test -f 'libarchive/archive_read_support_format_mtree.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_mtree.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_mtree.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_mtree.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_mtree.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_mtree.c' object='libarchive/libarchive_test-archive_read_support_format_mtree.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_mtree.obj `if test -f 'libarchive/archive_read_support_format_mtree.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_mtree.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_mtree.c'; fi` + +libarchive/libarchive_test-archive_read_support_format_rar.o: libarchive/archive_read_support_format_rar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_rar.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_rar.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_rar.o `test -f 'libarchive/archive_read_support_format_rar.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_rar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_rar.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_rar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_rar.c' object='libarchive/libarchive_test-archive_read_support_format_rar.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_rar.o `test -f 'libarchive/archive_read_support_format_rar.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_rar.c + +libarchive/libarchive_test-archive_read_support_format_rar.obj: libarchive/archive_read_support_format_rar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_rar.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_rar.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_rar.obj `if test -f 'libarchive/archive_read_support_format_rar.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_rar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_rar.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_rar.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_rar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_rar.c' object='libarchive/libarchive_test-archive_read_support_format_rar.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_rar.obj `if test -f 'libarchive/archive_read_support_format_rar.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_rar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_rar.c'; fi` + +libarchive/libarchive_test-archive_read_support_format_rar5.o: libarchive/archive_read_support_format_rar5.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_rar5.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_rar5.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_rar5.o `test -f 'libarchive/archive_read_support_format_rar5.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_rar5.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_rar5.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_rar5.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_rar5.c' object='libarchive/libarchive_test-archive_read_support_format_rar5.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_rar5.o `test -f 'libarchive/archive_read_support_format_rar5.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_rar5.c + +libarchive/libarchive_test-archive_read_support_format_rar5.obj: libarchive/archive_read_support_format_rar5.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_rar5.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_rar5.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_rar5.obj `if test -f 'libarchive/archive_read_support_format_rar5.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_rar5.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_rar5.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_rar5.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_rar5.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_rar5.c' object='libarchive/libarchive_test-archive_read_support_format_rar5.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_rar5.obj `if test -f 'libarchive/archive_read_support_format_rar5.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_rar5.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_rar5.c'; fi` + +libarchive/libarchive_test-archive_read_support_format_raw.o: libarchive/archive_read_support_format_raw.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_raw.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_raw.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_raw.o `test -f 'libarchive/archive_read_support_format_raw.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_raw.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_raw.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_raw.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_raw.c' object='libarchive/libarchive_test-archive_read_support_format_raw.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_raw.o `test -f 'libarchive/archive_read_support_format_raw.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_raw.c + +libarchive/libarchive_test-archive_read_support_format_raw.obj: libarchive/archive_read_support_format_raw.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_raw.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_raw.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_raw.obj `if test -f 'libarchive/archive_read_support_format_raw.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_raw.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_raw.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_raw.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_raw.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_raw.c' object='libarchive/libarchive_test-archive_read_support_format_raw.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_raw.obj `if test -f 'libarchive/archive_read_support_format_raw.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_raw.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_raw.c'; fi` + +libarchive/libarchive_test-archive_read_support_format_tar.o: libarchive/archive_read_support_format_tar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_tar.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_tar.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_tar.o `test -f 'libarchive/archive_read_support_format_tar.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_tar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_tar.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_tar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_tar.c' object='libarchive/libarchive_test-archive_read_support_format_tar.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_tar.o `test -f 'libarchive/archive_read_support_format_tar.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_tar.c + +libarchive/libarchive_test-archive_read_support_format_tar.obj: libarchive/archive_read_support_format_tar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_tar.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_tar.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_tar.obj `if test -f 'libarchive/archive_read_support_format_tar.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_tar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_tar.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_tar.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_tar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_tar.c' object='libarchive/libarchive_test-archive_read_support_format_tar.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_tar.obj `if test -f 'libarchive/archive_read_support_format_tar.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_tar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_tar.c'; fi` + +libarchive/libarchive_test-archive_read_support_format_warc.o: libarchive/archive_read_support_format_warc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_warc.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_warc.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_warc.o `test -f 'libarchive/archive_read_support_format_warc.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_warc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_warc.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_warc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_warc.c' object='libarchive/libarchive_test-archive_read_support_format_warc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_warc.o `test -f 'libarchive/archive_read_support_format_warc.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_warc.c + +libarchive/libarchive_test-archive_read_support_format_warc.obj: libarchive/archive_read_support_format_warc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_warc.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_warc.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_warc.obj `if test -f 'libarchive/archive_read_support_format_warc.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_warc.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_warc.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_warc.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_warc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_warc.c' object='libarchive/libarchive_test-archive_read_support_format_warc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_warc.obj `if test -f 'libarchive/archive_read_support_format_warc.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_warc.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_warc.c'; fi` + +libarchive/libarchive_test-archive_read_support_format_xar.o: libarchive/archive_read_support_format_xar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_xar.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_xar.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_xar.o `test -f 'libarchive/archive_read_support_format_xar.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_xar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_xar.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_xar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_xar.c' object='libarchive/libarchive_test-archive_read_support_format_xar.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_xar.o `test -f 'libarchive/archive_read_support_format_xar.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_xar.c + +libarchive/libarchive_test-archive_read_support_format_xar.obj: libarchive/archive_read_support_format_xar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_xar.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_xar.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_xar.obj `if test -f 'libarchive/archive_read_support_format_xar.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_xar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_xar.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_xar.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_xar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_xar.c' object='libarchive/libarchive_test-archive_read_support_format_xar.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_xar.obj `if test -f 'libarchive/archive_read_support_format_xar.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_xar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_xar.c'; fi` + +libarchive/libarchive_test-archive_read_support_format_zip.o: libarchive/archive_read_support_format_zip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_zip.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_zip.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_zip.o `test -f 'libarchive/archive_read_support_format_zip.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_zip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_zip.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_zip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_zip.c' object='libarchive/libarchive_test-archive_read_support_format_zip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_zip.o `test -f 'libarchive/archive_read_support_format_zip.c' || echo '$(srcdir)/'`libarchive/archive_read_support_format_zip.c + +libarchive/libarchive_test-archive_read_support_format_zip.obj: libarchive/archive_read_support_format_zip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_support_format_zip.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_zip.Tpo -c -o libarchive/libarchive_test-archive_read_support_format_zip.obj `if test -f 'libarchive/archive_read_support_format_zip.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_zip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_zip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_zip.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_support_format_zip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_support_format_zip.c' object='libarchive/libarchive_test-archive_read_support_format_zip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_support_format_zip.obj `if test -f 'libarchive/archive_read_support_format_zip.c'; then $(CYGPATH_W) 'libarchive/archive_read_support_format_zip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_support_format_zip.c'; fi` + +libarchive/libarchive_test-archive_string.o: libarchive/archive_string.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_string.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_string.Tpo -c -o libarchive/libarchive_test-archive_string.o `test -f 'libarchive/archive_string.c' || echo '$(srcdir)/'`libarchive/archive_string.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_string.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_string.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_string.c' object='libarchive/libarchive_test-archive_string.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_string.o `test -f 'libarchive/archive_string.c' || echo '$(srcdir)/'`libarchive/archive_string.c + +libarchive/libarchive_test-archive_string.obj: libarchive/archive_string.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_string.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_string.Tpo -c -o libarchive/libarchive_test-archive_string.obj `if test -f 'libarchive/archive_string.c'; then $(CYGPATH_W) 'libarchive/archive_string.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_string.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_string.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_string.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_string.c' object='libarchive/libarchive_test-archive_string.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_string.obj `if test -f 'libarchive/archive_string.c'; then $(CYGPATH_W) 'libarchive/archive_string.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_string.c'; fi` + +libarchive/libarchive_test-archive_string_sprintf.o: libarchive/archive_string_sprintf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_string_sprintf.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_string_sprintf.Tpo -c -o libarchive/libarchive_test-archive_string_sprintf.o `test -f 'libarchive/archive_string_sprintf.c' || echo '$(srcdir)/'`libarchive/archive_string_sprintf.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_string_sprintf.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_string_sprintf.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_string_sprintf.c' object='libarchive/libarchive_test-archive_string_sprintf.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_string_sprintf.o `test -f 'libarchive/archive_string_sprintf.c' || echo '$(srcdir)/'`libarchive/archive_string_sprintf.c + +libarchive/libarchive_test-archive_string_sprintf.obj: libarchive/archive_string_sprintf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_string_sprintf.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_string_sprintf.Tpo -c -o libarchive/libarchive_test-archive_string_sprintf.obj `if test -f 'libarchive/archive_string_sprintf.c'; then $(CYGPATH_W) 'libarchive/archive_string_sprintf.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_string_sprintf.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_string_sprintf.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_string_sprintf.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_string_sprintf.c' object='libarchive/libarchive_test-archive_string_sprintf.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_string_sprintf.obj `if test -f 'libarchive/archive_string_sprintf.c'; then $(CYGPATH_W) 'libarchive/archive_string_sprintf.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_string_sprintf.c'; fi` + +libarchive/libarchive_test-archive_util.o: libarchive/archive_util.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_util.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_util.Tpo -c -o libarchive/libarchive_test-archive_util.o `test -f 'libarchive/archive_util.c' || echo '$(srcdir)/'`libarchive/archive_util.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_util.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_util.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_util.c' object='libarchive/libarchive_test-archive_util.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_util.o `test -f 'libarchive/archive_util.c' || echo '$(srcdir)/'`libarchive/archive_util.c + +libarchive/libarchive_test-archive_util.obj: libarchive/archive_util.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_util.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_util.Tpo -c -o libarchive/libarchive_test-archive_util.obj `if test -f 'libarchive/archive_util.c'; then $(CYGPATH_W) 'libarchive/archive_util.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_util.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_util.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_util.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_util.c' object='libarchive/libarchive_test-archive_util.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_util.obj `if test -f 'libarchive/archive_util.c'; then $(CYGPATH_W) 'libarchive/archive_util.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_util.c'; fi` + +libarchive/libarchive_test-archive_version_details.o: libarchive/archive_version_details.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_version_details.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_version_details.Tpo -c -o libarchive/libarchive_test-archive_version_details.o `test -f 'libarchive/archive_version_details.c' || echo '$(srcdir)/'`libarchive/archive_version_details.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_version_details.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_version_details.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_version_details.c' object='libarchive/libarchive_test-archive_version_details.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_version_details.o `test -f 'libarchive/archive_version_details.c' || echo '$(srcdir)/'`libarchive/archive_version_details.c + +libarchive/libarchive_test-archive_version_details.obj: libarchive/archive_version_details.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_version_details.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_version_details.Tpo -c -o libarchive/libarchive_test-archive_version_details.obj `if test -f 'libarchive/archive_version_details.c'; then $(CYGPATH_W) 'libarchive/archive_version_details.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_version_details.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_version_details.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_version_details.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_version_details.c' object='libarchive/libarchive_test-archive_version_details.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_version_details.obj `if test -f 'libarchive/archive_version_details.c'; then $(CYGPATH_W) 'libarchive/archive_version_details.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_version_details.c'; fi` + +libarchive/libarchive_test-archive_virtual.o: libarchive/archive_virtual.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_virtual.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_virtual.Tpo -c -o libarchive/libarchive_test-archive_virtual.o `test -f 'libarchive/archive_virtual.c' || echo '$(srcdir)/'`libarchive/archive_virtual.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_virtual.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_virtual.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_virtual.c' object='libarchive/libarchive_test-archive_virtual.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_virtual.o `test -f 'libarchive/archive_virtual.c' || echo '$(srcdir)/'`libarchive/archive_virtual.c + +libarchive/libarchive_test-archive_virtual.obj: libarchive/archive_virtual.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_virtual.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_virtual.Tpo -c -o libarchive/libarchive_test-archive_virtual.obj `if test -f 'libarchive/archive_virtual.c'; then $(CYGPATH_W) 'libarchive/archive_virtual.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_virtual.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_virtual.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_virtual.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_virtual.c' object='libarchive/libarchive_test-archive_virtual.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_virtual.obj `if test -f 'libarchive/archive_virtual.c'; then $(CYGPATH_W) 'libarchive/archive_virtual.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_virtual.c'; fi` + +libarchive/libarchive_test-archive_write.o: libarchive/archive_write.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write.Tpo -c -o libarchive/libarchive_test-archive_write.o `test -f 'libarchive/archive_write.c' || echo '$(srcdir)/'`libarchive/archive_write.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write.c' object='libarchive/libarchive_test-archive_write.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write.o `test -f 'libarchive/archive_write.c' || echo '$(srcdir)/'`libarchive/archive_write.c + +libarchive/libarchive_test-archive_write.obj: libarchive/archive_write.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write.Tpo -c -o libarchive/libarchive_test-archive_write.obj `if test -f 'libarchive/archive_write.c'; then $(CYGPATH_W) 'libarchive/archive_write.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write.c' object='libarchive/libarchive_test-archive_write.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write.obj `if test -f 'libarchive/archive_write.c'; then $(CYGPATH_W) 'libarchive/archive_write.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write.c'; fi` + +libarchive/libarchive_test-archive_write_disk_posix.o: libarchive/archive_write_disk_posix.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_disk_posix.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_disk_posix.Tpo -c -o libarchive/libarchive_test-archive_write_disk_posix.o `test -f 'libarchive/archive_write_disk_posix.c' || echo '$(srcdir)/'`libarchive/archive_write_disk_posix.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_disk_posix.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_disk_posix.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_disk_posix.c' object='libarchive/libarchive_test-archive_write_disk_posix.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_disk_posix.o `test -f 'libarchive/archive_write_disk_posix.c' || echo '$(srcdir)/'`libarchive/archive_write_disk_posix.c + +libarchive/libarchive_test-archive_write_disk_posix.obj: libarchive/archive_write_disk_posix.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_disk_posix.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_disk_posix.Tpo -c -o libarchive/libarchive_test-archive_write_disk_posix.obj `if test -f 'libarchive/archive_write_disk_posix.c'; then $(CYGPATH_W) 'libarchive/archive_write_disk_posix.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_disk_posix.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_disk_posix.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_disk_posix.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_disk_posix.c' object='libarchive/libarchive_test-archive_write_disk_posix.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_disk_posix.obj `if test -f 'libarchive/archive_write_disk_posix.c'; then $(CYGPATH_W) 'libarchive/archive_write_disk_posix.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_disk_posix.c'; fi` + +libarchive/libarchive_test-archive_write_disk_set_standard_lookup.o: libarchive/archive_write_disk_set_standard_lookup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_disk_set_standard_lookup.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_disk_set_standard_lookup.Tpo -c -o libarchive/libarchive_test-archive_write_disk_set_standard_lookup.o `test -f 'libarchive/archive_write_disk_set_standard_lookup.c' || echo '$(srcdir)/'`libarchive/archive_write_disk_set_standard_lookup.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_disk_set_standard_lookup.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_disk_set_standard_lookup.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_disk_set_standard_lookup.c' object='libarchive/libarchive_test-archive_write_disk_set_standard_lookup.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_disk_set_standard_lookup.o `test -f 'libarchive/archive_write_disk_set_standard_lookup.c' || echo '$(srcdir)/'`libarchive/archive_write_disk_set_standard_lookup.c + +libarchive/libarchive_test-archive_write_disk_set_standard_lookup.obj: libarchive/archive_write_disk_set_standard_lookup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_disk_set_standard_lookup.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_disk_set_standard_lookup.Tpo -c -o libarchive/libarchive_test-archive_write_disk_set_standard_lookup.obj `if test -f 'libarchive/archive_write_disk_set_standard_lookup.c'; then $(CYGPATH_W) 'libarchive/archive_write_disk_set_standard_lookup.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_disk_set_standard_lookup.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_disk_set_standard_lookup.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_disk_set_standard_lookup.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_disk_set_standard_lookup.c' object='libarchive/libarchive_test-archive_write_disk_set_standard_lookup.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_disk_set_standard_lookup.obj `if test -f 'libarchive/archive_write_disk_set_standard_lookup.c'; then $(CYGPATH_W) 'libarchive/archive_write_disk_set_standard_lookup.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_disk_set_standard_lookup.c'; fi` + +libarchive/libarchive_test-archive_write_open_fd.o: libarchive/archive_write_open_fd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_open_fd.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_open_fd.Tpo -c -o libarchive/libarchive_test-archive_write_open_fd.o `test -f 'libarchive/archive_write_open_fd.c' || echo '$(srcdir)/'`libarchive/archive_write_open_fd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_open_fd.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_open_fd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_open_fd.c' object='libarchive/libarchive_test-archive_write_open_fd.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_open_fd.o `test -f 'libarchive/archive_write_open_fd.c' || echo '$(srcdir)/'`libarchive/archive_write_open_fd.c + +libarchive/libarchive_test-archive_write_open_fd.obj: libarchive/archive_write_open_fd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_open_fd.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_open_fd.Tpo -c -o libarchive/libarchive_test-archive_write_open_fd.obj `if test -f 'libarchive/archive_write_open_fd.c'; then $(CYGPATH_W) 'libarchive/archive_write_open_fd.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_open_fd.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_open_fd.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_open_fd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_open_fd.c' object='libarchive/libarchive_test-archive_write_open_fd.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_open_fd.obj `if test -f 'libarchive/archive_write_open_fd.c'; then $(CYGPATH_W) 'libarchive/archive_write_open_fd.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_open_fd.c'; fi` + +libarchive/libarchive_test-archive_write_open_file.o: libarchive/archive_write_open_file.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_open_file.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_open_file.Tpo -c -o libarchive/libarchive_test-archive_write_open_file.o `test -f 'libarchive/archive_write_open_file.c' || echo '$(srcdir)/'`libarchive/archive_write_open_file.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_open_file.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_open_file.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_open_file.c' object='libarchive/libarchive_test-archive_write_open_file.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_open_file.o `test -f 'libarchive/archive_write_open_file.c' || echo '$(srcdir)/'`libarchive/archive_write_open_file.c + +libarchive/libarchive_test-archive_write_open_file.obj: libarchive/archive_write_open_file.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_open_file.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_open_file.Tpo -c -o libarchive/libarchive_test-archive_write_open_file.obj `if test -f 'libarchive/archive_write_open_file.c'; then $(CYGPATH_W) 'libarchive/archive_write_open_file.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_open_file.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_open_file.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_open_file.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_open_file.c' object='libarchive/libarchive_test-archive_write_open_file.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_open_file.obj `if test -f 'libarchive/archive_write_open_file.c'; then $(CYGPATH_W) 'libarchive/archive_write_open_file.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_open_file.c'; fi` + +libarchive/libarchive_test-archive_write_open_filename.o: libarchive/archive_write_open_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_open_filename.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_open_filename.Tpo -c -o libarchive/libarchive_test-archive_write_open_filename.o `test -f 'libarchive/archive_write_open_filename.c' || echo '$(srcdir)/'`libarchive/archive_write_open_filename.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_open_filename.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_open_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_open_filename.c' object='libarchive/libarchive_test-archive_write_open_filename.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_open_filename.o `test -f 'libarchive/archive_write_open_filename.c' || echo '$(srcdir)/'`libarchive/archive_write_open_filename.c + +libarchive/libarchive_test-archive_write_open_filename.obj: libarchive/archive_write_open_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_open_filename.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_open_filename.Tpo -c -o libarchive/libarchive_test-archive_write_open_filename.obj `if test -f 'libarchive/archive_write_open_filename.c'; then $(CYGPATH_W) 'libarchive/archive_write_open_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_open_filename.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_open_filename.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_open_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_open_filename.c' object='libarchive/libarchive_test-archive_write_open_filename.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_open_filename.obj `if test -f 'libarchive/archive_write_open_filename.c'; then $(CYGPATH_W) 'libarchive/archive_write_open_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_open_filename.c'; fi` + +libarchive/libarchive_test-archive_write_open_memory.o: libarchive/archive_write_open_memory.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_open_memory.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_open_memory.Tpo -c -o libarchive/libarchive_test-archive_write_open_memory.o `test -f 'libarchive/archive_write_open_memory.c' || echo '$(srcdir)/'`libarchive/archive_write_open_memory.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_open_memory.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_open_memory.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_open_memory.c' object='libarchive/libarchive_test-archive_write_open_memory.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_open_memory.o `test -f 'libarchive/archive_write_open_memory.c' || echo '$(srcdir)/'`libarchive/archive_write_open_memory.c + +libarchive/libarchive_test-archive_write_open_memory.obj: libarchive/archive_write_open_memory.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_open_memory.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_open_memory.Tpo -c -o libarchive/libarchive_test-archive_write_open_memory.obj `if test -f 'libarchive/archive_write_open_memory.c'; then $(CYGPATH_W) 'libarchive/archive_write_open_memory.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_open_memory.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_open_memory.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_open_memory.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_open_memory.c' object='libarchive/libarchive_test-archive_write_open_memory.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_open_memory.obj `if test -f 'libarchive/archive_write_open_memory.c'; then $(CYGPATH_W) 'libarchive/archive_write_open_memory.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_open_memory.c'; fi` + +libarchive/libarchive_test-archive_write_add_filter.o: libarchive/archive_write_add_filter.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter.o `test -f 'libarchive/archive_write_add_filter.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter.c' object='libarchive/libarchive_test-archive_write_add_filter.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter.o `test -f 'libarchive/archive_write_add_filter.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter.c + +libarchive/libarchive_test-archive_write_add_filter.obj: libarchive/archive_write_add_filter.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter.obj `if test -f 'libarchive/archive_write_add_filter.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter.c' object='libarchive/libarchive_test-archive_write_add_filter.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter.obj `if test -f 'libarchive/archive_write_add_filter.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter.c'; fi` + +libarchive/libarchive_test-archive_write_add_filter_b64encode.o: libarchive/archive_write_add_filter_b64encode.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_b64encode.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_b64encode.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_b64encode.o `test -f 'libarchive/archive_write_add_filter_b64encode.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_b64encode.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_b64encode.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_b64encode.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_b64encode.c' object='libarchive/libarchive_test-archive_write_add_filter_b64encode.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_b64encode.o `test -f 'libarchive/archive_write_add_filter_b64encode.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_b64encode.c + +libarchive/libarchive_test-archive_write_add_filter_b64encode.obj: libarchive/archive_write_add_filter_b64encode.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_b64encode.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_b64encode.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_b64encode.obj `if test -f 'libarchive/archive_write_add_filter_b64encode.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_b64encode.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_b64encode.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_b64encode.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_b64encode.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_b64encode.c' object='libarchive/libarchive_test-archive_write_add_filter_b64encode.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_b64encode.obj `if test -f 'libarchive/archive_write_add_filter_b64encode.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_b64encode.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_b64encode.c'; fi` + +libarchive/libarchive_test-archive_write_add_filter_by_name.o: libarchive/archive_write_add_filter_by_name.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_by_name.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_by_name.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_by_name.o `test -f 'libarchive/archive_write_add_filter_by_name.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_by_name.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_by_name.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_by_name.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_by_name.c' object='libarchive/libarchive_test-archive_write_add_filter_by_name.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_by_name.o `test -f 'libarchive/archive_write_add_filter_by_name.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_by_name.c + +libarchive/libarchive_test-archive_write_add_filter_by_name.obj: libarchive/archive_write_add_filter_by_name.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_by_name.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_by_name.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_by_name.obj `if test -f 'libarchive/archive_write_add_filter_by_name.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_by_name.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_by_name.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_by_name.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_by_name.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_by_name.c' object='libarchive/libarchive_test-archive_write_add_filter_by_name.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_by_name.obj `if test -f 'libarchive/archive_write_add_filter_by_name.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_by_name.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_by_name.c'; fi` + +libarchive/libarchive_test-archive_write_add_filter_bzip2.o: libarchive/archive_write_add_filter_bzip2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_bzip2.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_bzip2.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_bzip2.o `test -f 'libarchive/archive_write_add_filter_bzip2.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_bzip2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_bzip2.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_bzip2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_bzip2.c' object='libarchive/libarchive_test-archive_write_add_filter_bzip2.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_bzip2.o `test -f 'libarchive/archive_write_add_filter_bzip2.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_bzip2.c + +libarchive/libarchive_test-archive_write_add_filter_bzip2.obj: libarchive/archive_write_add_filter_bzip2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_bzip2.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_bzip2.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_bzip2.obj `if test -f 'libarchive/archive_write_add_filter_bzip2.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_bzip2.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_bzip2.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_bzip2.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_bzip2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_bzip2.c' object='libarchive/libarchive_test-archive_write_add_filter_bzip2.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_bzip2.obj `if test -f 'libarchive/archive_write_add_filter_bzip2.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_bzip2.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_bzip2.c'; fi` + +libarchive/libarchive_test-archive_write_add_filter_compress.o: libarchive/archive_write_add_filter_compress.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_compress.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_compress.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_compress.o `test -f 'libarchive/archive_write_add_filter_compress.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_compress.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_compress.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_compress.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_compress.c' object='libarchive/libarchive_test-archive_write_add_filter_compress.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_compress.o `test -f 'libarchive/archive_write_add_filter_compress.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_compress.c + +libarchive/libarchive_test-archive_write_add_filter_compress.obj: libarchive/archive_write_add_filter_compress.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_compress.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_compress.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_compress.obj `if test -f 'libarchive/archive_write_add_filter_compress.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_compress.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_compress.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_compress.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_compress.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_compress.c' object='libarchive/libarchive_test-archive_write_add_filter_compress.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_compress.obj `if test -f 'libarchive/archive_write_add_filter_compress.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_compress.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_compress.c'; fi` + +libarchive/libarchive_test-archive_write_add_filter_grzip.o: libarchive/archive_write_add_filter_grzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_grzip.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_grzip.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_grzip.o `test -f 'libarchive/archive_write_add_filter_grzip.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_grzip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_grzip.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_grzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_grzip.c' object='libarchive/libarchive_test-archive_write_add_filter_grzip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_grzip.o `test -f 'libarchive/archive_write_add_filter_grzip.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_grzip.c + +libarchive/libarchive_test-archive_write_add_filter_grzip.obj: libarchive/archive_write_add_filter_grzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_grzip.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_grzip.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_grzip.obj `if test -f 'libarchive/archive_write_add_filter_grzip.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_grzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_grzip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_grzip.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_grzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_grzip.c' object='libarchive/libarchive_test-archive_write_add_filter_grzip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_grzip.obj `if test -f 'libarchive/archive_write_add_filter_grzip.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_grzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_grzip.c'; fi` + +libarchive/libarchive_test-archive_write_add_filter_gzip.o: libarchive/archive_write_add_filter_gzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_gzip.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_gzip.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_gzip.o `test -f 'libarchive/archive_write_add_filter_gzip.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_gzip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_gzip.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_gzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_gzip.c' object='libarchive/libarchive_test-archive_write_add_filter_gzip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_gzip.o `test -f 'libarchive/archive_write_add_filter_gzip.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_gzip.c + +libarchive/libarchive_test-archive_write_add_filter_gzip.obj: libarchive/archive_write_add_filter_gzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_gzip.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_gzip.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_gzip.obj `if test -f 'libarchive/archive_write_add_filter_gzip.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_gzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_gzip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_gzip.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_gzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_gzip.c' object='libarchive/libarchive_test-archive_write_add_filter_gzip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_gzip.obj `if test -f 'libarchive/archive_write_add_filter_gzip.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_gzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_gzip.c'; fi` + +libarchive/libarchive_test-archive_write_add_filter_lrzip.o: libarchive/archive_write_add_filter_lrzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_lrzip.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_lrzip.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_lrzip.o `test -f 'libarchive/archive_write_add_filter_lrzip.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_lrzip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_lrzip.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_lrzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_lrzip.c' object='libarchive/libarchive_test-archive_write_add_filter_lrzip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_lrzip.o `test -f 'libarchive/archive_write_add_filter_lrzip.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_lrzip.c + +libarchive/libarchive_test-archive_write_add_filter_lrzip.obj: libarchive/archive_write_add_filter_lrzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_lrzip.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_lrzip.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_lrzip.obj `if test -f 'libarchive/archive_write_add_filter_lrzip.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_lrzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_lrzip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_lrzip.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_lrzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_lrzip.c' object='libarchive/libarchive_test-archive_write_add_filter_lrzip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_lrzip.obj `if test -f 'libarchive/archive_write_add_filter_lrzip.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_lrzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_lrzip.c'; fi` + +libarchive/libarchive_test-archive_write_add_filter_lz4.o: libarchive/archive_write_add_filter_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_lz4.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_lz4.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_lz4.o `test -f 'libarchive/archive_write_add_filter_lz4.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_lz4.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_lz4.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_lz4.c' object='libarchive/libarchive_test-archive_write_add_filter_lz4.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_lz4.o `test -f 'libarchive/archive_write_add_filter_lz4.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_lz4.c + +libarchive/libarchive_test-archive_write_add_filter_lz4.obj: libarchive/archive_write_add_filter_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_lz4.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_lz4.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_lz4.obj `if test -f 'libarchive/archive_write_add_filter_lz4.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_lz4.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_lz4.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_lz4.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_lz4.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_lz4.c' object='libarchive/libarchive_test-archive_write_add_filter_lz4.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_lz4.obj `if test -f 'libarchive/archive_write_add_filter_lz4.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_lz4.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_lz4.c'; fi` + +libarchive/libarchive_test-archive_write_add_filter_lzop.o: libarchive/archive_write_add_filter_lzop.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_lzop.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_lzop.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_lzop.o `test -f 'libarchive/archive_write_add_filter_lzop.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_lzop.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_lzop.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_lzop.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_lzop.c' object='libarchive/libarchive_test-archive_write_add_filter_lzop.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_lzop.o `test -f 'libarchive/archive_write_add_filter_lzop.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_lzop.c + +libarchive/libarchive_test-archive_write_add_filter_lzop.obj: libarchive/archive_write_add_filter_lzop.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_lzop.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_lzop.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_lzop.obj `if test -f 'libarchive/archive_write_add_filter_lzop.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_lzop.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_lzop.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_lzop.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_lzop.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_lzop.c' object='libarchive/libarchive_test-archive_write_add_filter_lzop.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_lzop.obj `if test -f 'libarchive/archive_write_add_filter_lzop.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_lzop.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_lzop.c'; fi` + +libarchive/libarchive_test-archive_write_add_filter_none.o: libarchive/archive_write_add_filter_none.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_none.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_none.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_none.o `test -f 'libarchive/archive_write_add_filter_none.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_none.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_none.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_none.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_none.c' object='libarchive/libarchive_test-archive_write_add_filter_none.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_none.o `test -f 'libarchive/archive_write_add_filter_none.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_none.c + +libarchive/libarchive_test-archive_write_add_filter_none.obj: libarchive/archive_write_add_filter_none.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_none.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_none.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_none.obj `if test -f 'libarchive/archive_write_add_filter_none.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_none.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_none.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_none.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_none.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_none.c' object='libarchive/libarchive_test-archive_write_add_filter_none.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_none.obj `if test -f 'libarchive/archive_write_add_filter_none.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_none.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_none.c'; fi` + +libarchive/libarchive_test-archive_write_add_filter_program.o: libarchive/archive_write_add_filter_program.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_program.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_program.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_program.o `test -f 'libarchive/archive_write_add_filter_program.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_program.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_program.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_program.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_program.c' object='libarchive/libarchive_test-archive_write_add_filter_program.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_program.o `test -f 'libarchive/archive_write_add_filter_program.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_program.c + +libarchive/libarchive_test-archive_write_add_filter_program.obj: libarchive/archive_write_add_filter_program.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_program.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_program.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_program.obj `if test -f 'libarchive/archive_write_add_filter_program.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_program.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_program.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_program.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_program.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_program.c' object='libarchive/libarchive_test-archive_write_add_filter_program.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_program.obj `if test -f 'libarchive/archive_write_add_filter_program.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_program.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_program.c'; fi` + +libarchive/libarchive_test-archive_write_add_filter_uuencode.o: libarchive/archive_write_add_filter_uuencode.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_uuencode.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_uuencode.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_uuencode.o `test -f 'libarchive/archive_write_add_filter_uuencode.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_uuencode.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_uuencode.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_uuencode.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_uuencode.c' object='libarchive/libarchive_test-archive_write_add_filter_uuencode.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_uuencode.o `test -f 'libarchive/archive_write_add_filter_uuencode.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_uuencode.c + +libarchive/libarchive_test-archive_write_add_filter_uuencode.obj: libarchive/archive_write_add_filter_uuencode.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_uuencode.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_uuencode.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_uuencode.obj `if test -f 'libarchive/archive_write_add_filter_uuencode.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_uuencode.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_uuencode.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_uuencode.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_uuencode.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_uuencode.c' object='libarchive/libarchive_test-archive_write_add_filter_uuencode.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_uuencode.obj `if test -f 'libarchive/archive_write_add_filter_uuencode.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_uuencode.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_uuencode.c'; fi` + +libarchive/libarchive_test-archive_write_add_filter_xz.o: libarchive/archive_write_add_filter_xz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_xz.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_xz.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_xz.o `test -f 'libarchive/archive_write_add_filter_xz.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_xz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_xz.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_xz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_xz.c' object='libarchive/libarchive_test-archive_write_add_filter_xz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_xz.o `test -f 'libarchive/archive_write_add_filter_xz.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_xz.c + +libarchive/libarchive_test-archive_write_add_filter_xz.obj: libarchive/archive_write_add_filter_xz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_xz.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_xz.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_xz.obj `if test -f 'libarchive/archive_write_add_filter_xz.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_xz.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_xz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_xz.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_xz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_xz.c' object='libarchive/libarchive_test-archive_write_add_filter_xz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_xz.obj `if test -f 'libarchive/archive_write_add_filter_xz.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_xz.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_xz.c'; fi` + +libarchive/libarchive_test-archive_write_add_filter_zstd.o: libarchive/archive_write_add_filter_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_zstd.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_zstd.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_zstd.o `test -f 'libarchive/archive_write_add_filter_zstd.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_zstd.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_zstd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_zstd.c' object='libarchive/libarchive_test-archive_write_add_filter_zstd.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_zstd.o `test -f 'libarchive/archive_write_add_filter_zstd.c' || echo '$(srcdir)/'`libarchive/archive_write_add_filter_zstd.c + +libarchive/libarchive_test-archive_write_add_filter_zstd.obj: libarchive/archive_write_add_filter_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_add_filter_zstd.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_zstd.Tpo -c -o libarchive/libarchive_test-archive_write_add_filter_zstd.obj `if test -f 'libarchive/archive_write_add_filter_zstd.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_zstd.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_zstd.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_zstd.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_add_filter_zstd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_add_filter_zstd.c' object='libarchive/libarchive_test-archive_write_add_filter_zstd.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_add_filter_zstd.obj `if test -f 'libarchive/archive_write_add_filter_zstd.c'; then $(CYGPATH_W) 'libarchive/archive_write_add_filter_zstd.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_add_filter_zstd.c'; fi` + +libarchive/libarchive_test-archive_write_set_format.o: libarchive/archive_write_set_format.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format.Tpo -c -o libarchive/libarchive_test-archive_write_set_format.o `test -f 'libarchive/archive_write_set_format.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format.c' object='libarchive/libarchive_test-archive_write_set_format.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format.o `test -f 'libarchive/archive_write_set_format.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format.c + +libarchive/libarchive_test-archive_write_set_format.obj: libarchive/archive_write_set_format.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format.Tpo -c -o libarchive/libarchive_test-archive_write_set_format.obj `if test -f 'libarchive/archive_write_set_format.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format.c' object='libarchive/libarchive_test-archive_write_set_format.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format.obj `if test -f 'libarchive/archive_write_set_format.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format.c'; fi` + +libarchive/libarchive_test-archive_write_set_format_7zip.o: libarchive/archive_write_set_format_7zip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_7zip.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_7zip.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_7zip.o `test -f 'libarchive/archive_write_set_format_7zip.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_7zip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_7zip.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_7zip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_7zip.c' object='libarchive/libarchive_test-archive_write_set_format_7zip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_7zip.o `test -f 'libarchive/archive_write_set_format_7zip.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_7zip.c + +libarchive/libarchive_test-archive_write_set_format_7zip.obj: libarchive/archive_write_set_format_7zip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_7zip.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_7zip.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_7zip.obj `if test -f 'libarchive/archive_write_set_format_7zip.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_7zip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_7zip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_7zip.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_7zip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_7zip.c' object='libarchive/libarchive_test-archive_write_set_format_7zip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_7zip.obj `if test -f 'libarchive/archive_write_set_format_7zip.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_7zip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_7zip.c'; fi` + +libarchive/libarchive_test-archive_write_set_format_ar.o: libarchive/archive_write_set_format_ar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_ar.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_ar.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_ar.o `test -f 'libarchive/archive_write_set_format_ar.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_ar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_ar.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_ar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_ar.c' object='libarchive/libarchive_test-archive_write_set_format_ar.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_ar.o `test -f 'libarchive/archive_write_set_format_ar.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_ar.c + +libarchive/libarchive_test-archive_write_set_format_ar.obj: libarchive/archive_write_set_format_ar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_ar.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_ar.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_ar.obj `if test -f 'libarchive/archive_write_set_format_ar.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_ar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_ar.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_ar.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_ar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_ar.c' object='libarchive/libarchive_test-archive_write_set_format_ar.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_ar.obj `if test -f 'libarchive/archive_write_set_format_ar.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_ar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_ar.c'; fi` + +libarchive/libarchive_test-archive_write_set_format_by_name.o: libarchive/archive_write_set_format_by_name.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_by_name.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_by_name.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_by_name.o `test -f 'libarchive/archive_write_set_format_by_name.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_by_name.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_by_name.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_by_name.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_by_name.c' object='libarchive/libarchive_test-archive_write_set_format_by_name.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_by_name.o `test -f 'libarchive/archive_write_set_format_by_name.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_by_name.c + +libarchive/libarchive_test-archive_write_set_format_by_name.obj: libarchive/archive_write_set_format_by_name.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_by_name.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_by_name.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_by_name.obj `if test -f 'libarchive/archive_write_set_format_by_name.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_by_name.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_by_name.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_by_name.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_by_name.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_by_name.c' object='libarchive/libarchive_test-archive_write_set_format_by_name.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_by_name.obj `if test -f 'libarchive/archive_write_set_format_by_name.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_by_name.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_by_name.c'; fi` + +libarchive/libarchive_test-archive_write_set_format_cpio.o: libarchive/archive_write_set_format_cpio.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_cpio.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_cpio.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_cpio.o `test -f 'libarchive/archive_write_set_format_cpio.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_cpio.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_cpio.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_cpio.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_cpio.c' object='libarchive/libarchive_test-archive_write_set_format_cpio.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_cpio.o `test -f 'libarchive/archive_write_set_format_cpio.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_cpio.c + +libarchive/libarchive_test-archive_write_set_format_cpio.obj: libarchive/archive_write_set_format_cpio.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_cpio.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_cpio.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_cpio.obj `if test -f 'libarchive/archive_write_set_format_cpio.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_cpio.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_cpio.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_cpio.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_cpio.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_cpio.c' object='libarchive/libarchive_test-archive_write_set_format_cpio.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_cpio.obj `if test -f 'libarchive/archive_write_set_format_cpio.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_cpio.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_cpio.c'; fi` + +libarchive/libarchive_test-archive_write_set_format_cpio_newc.o: libarchive/archive_write_set_format_cpio_newc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_cpio_newc.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_cpio_newc.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_cpio_newc.o `test -f 'libarchive/archive_write_set_format_cpio_newc.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_cpio_newc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_cpio_newc.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_cpio_newc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_cpio_newc.c' object='libarchive/libarchive_test-archive_write_set_format_cpio_newc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_cpio_newc.o `test -f 'libarchive/archive_write_set_format_cpio_newc.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_cpio_newc.c + +libarchive/libarchive_test-archive_write_set_format_cpio_newc.obj: libarchive/archive_write_set_format_cpio_newc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_cpio_newc.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_cpio_newc.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_cpio_newc.obj `if test -f 'libarchive/archive_write_set_format_cpio_newc.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_cpio_newc.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_cpio_newc.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_cpio_newc.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_cpio_newc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_cpio_newc.c' object='libarchive/libarchive_test-archive_write_set_format_cpio_newc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_cpio_newc.obj `if test -f 'libarchive/archive_write_set_format_cpio_newc.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_cpio_newc.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_cpio_newc.c'; fi` + +libarchive/libarchive_test-archive_write_set_format_filter_by_ext.o: libarchive/archive_write_set_format_filter_by_ext.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_filter_by_ext.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_filter_by_ext.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_filter_by_ext.o `test -f 'libarchive/archive_write_set_format_filter_by_ext.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_filter_by_ext.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_filter_by_ext.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_filter_by_ext.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_filter_by_ext.c' object='libarchive/libarchive_test-archive_write_set_format_filter_by_ext.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_filter_by_ext.o `test -f 'libarchive/archive_write_set_format_filter_by_ext.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_filter_by_ext.c + +libarchive/libarchive_test-archive_write_set_format_filter_by_ext.obj: libarchive/archive_write_set_format_filter_by_ext.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_filter_by_ext.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_filter_by_ext.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_filter_by_ext.obj `if test -f 'libarchive/archive_write_set_format_filter_by_ext.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_filter_by_ext.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_filter_by_ext.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_filter_by_ext.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_filter_by_ext.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_filter_by_ext.c' object='libarchive/libarchive_test-archive_write_set_format_filter_by_ext.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_filter_by_ext.obj `if test -f 'libarchive/archive_write_set_format_filter_by_ext.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_filter_by_ext.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_filter_by_ext.c'; fi` + +libarchive/libarchive_test-archive_write_set_format_iso9660.o: libarchive/archive_write_set_format_iso9660.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_iso9660.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_iso9660.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_iso9660.o `test -f 'libarchive/archive_write_set_format_iso9660.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_iso9660.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_iso9660.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_iso9660.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_iso9660.c' object='libarchive/libarchive_test-archive_write_set_format_iso9660.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_iso9660.o `test -f 'libarchive/archive_write_set_format_iso9660.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_iso9660.c + +libarchive/libarchive_test-archive_write_set_format_iso9660.obj: libarchive/archive_write_set_format_iso9660.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_iso9660.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_iso9660.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_iso9660.obj `if test -f 'libarchive/archive_write_set_format_iso9660.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_iso9660.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_iso9660.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_iso9660.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_iso9660.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_iso9660.c' object='libarchive/libarchive_test-archive_write_set_format_iso9660.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_iso9660.obj `if test -f 'libarchive/archive_write_set_format_iso9660.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_iso9660.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_iso9660.c'; fi` + +libarchive/libarchive_test-archive_write_set_format_mtree.o: libarchive/archive_write_set_format_mtree.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_mtree.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_mtree.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_mtree.o `test -f 'libarchive/archive_write_set_format_mtree.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_mtree.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_mtree.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_mtree.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_mtree.c' object='libarchive/libarchive_test-archive_write_set_format_mtree.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_mtree.o `test -f 'libarchive/archive_write_set_format_mtree.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_mtree.c + +libarchive/libarchive_test-archive_write_set_format_mtree.obj: libarchive/archive_write_set_format_mtree.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_mtree.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_mtree.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_mtree.obj `if test -f 'libarchive/archive_write_set_format_mtree.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_mtree.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_mtree.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_mtree.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_mtree.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_mtree.c' object='libarchive/libarchive_test-archive_write_set_format_mtree.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_mtree.obj `if test -f 'libarchive/archive_write_set_format_mtree.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_mtree.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_mtree.c'; fi` + +libarchive/libarchive_test-archive_write_set_format_pax.o: libarchive/archive_write_set_format_pax.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_pax.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_pax.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_pax.o `test -f 'libarchive/archive_write_set_format_pax.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_pax.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_pax.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_pax.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_pax.c' object='libarchive/libarchive_test-archive_write_set_format_pax.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_pax.o `test -f 'libarchive/archive_write_set_format_pax.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_pax.c + +libarchive/libarchive_test-archive_write_set_format_pax.obj: libarchive/archive_write_set_format_pax.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_pax.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_pax.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_pax.obj `if test -f 'libarchive/archive_write_set_format_pax.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_pax.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_pax.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_pax.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_pax.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_pax.c' object='libarchive/libarchive_test-archive_write_set_format_pax.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_pax.obj `if test -f 'libarchive/archive_write_set_format_pax.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_pax.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_pax.c'; fi` + +libarchive/libarchive_test-archive_write_set_format_raw.o: libarchive/archive_write_set_format_raw.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_raw.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_raw.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_raw.o `test -f 'libarchive/archive_write_set_format_raw.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_raw.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_raw.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_raw.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_raw.c' object='libarchive/libarchive_test-archive_write_set_format_raw.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_raw.o `test -f 'libarchive/archive_write_set_format_raw.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_raw.c + +libarchive/libarchive_test-archive_write_set_format_raw.obj: libarchive/archive_write_set_format_raw.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_raw.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_raw.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_raw.obj `if test -f 'libarchive/archive_write_set_format_raw.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_raw.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_raw.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_raw.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_raw.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_raw.c' object='libarchive/libarchive_test-archive_write_set_format_raw.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_raw.obj `if test -f 'libarchive/archive_write_set_format_raw.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_raw.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_raw.c'; fi` + +libarchive/libarchive_test-archive_write_set_format_shar.o: libarchive/archive_write_set_format_shar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_shar.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_shar.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_shar.o `test -f 'libarchive/archive_write_set_format_shar.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_shar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_shar.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_shar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_shar.c' object='libarchive/libarchive_test-archive_write_set_format_shar.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_shar.o `test -f 'libarchive/archive_write_set_format_shar.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_shar.c + +libarchive/libarchive_test-archive_write_set_format_shar.obj: libarchive/archive_write_set_format_shar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_shar.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_shar.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_shar.obj `if test -f 'libarchive/archive_write_set_format_shar.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_shar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_shar.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_shar.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_shar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_shar.c' object='libarchive/libarchive_test-archive_write_set_format_shar.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_shar.obj `if test -f 'libarchive/archive_write_set_format_shar.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_shar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_shar.c'; fi` + +libarchive/libarchive_test-archive_write_set_format_ustar.o: libarchive/archive_write_set_format_ustar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_ustar.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_ustar.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_ustar.o `test -f 'libarchive/archive_write_set_format_ustar.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_ustar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_ustar.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_ustar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_ustar.c' object='libarchive/libarchive_test-archive_write_set_format_ustar.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_ustar.o `test -f 'libarchive/archive_write_set_format_ustar.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_ustar.c + +libarchive/libarchive_test-archive_write_set_format_ustar.obj: libarchive/archive_write_set_format_ustar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_ustar.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_ustar.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_ustar.obj `if test -f 'libarchive/archive_write_set_format_ustar.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_ustar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_ustar.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_ustar.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_ustar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_ustar.c' object='libarchive/libarchive_test-archive_write_set_format_ustar.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_ustar.obj `if test -f 'libarchive/archive_write_set_format_ustar.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_ustar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_ustar.c'; fi` + +libarchive/libarchive_test-archive_write_set_format_v7tar.o: libarchive/archive_write_set_format_v7tar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_v7tar.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_v7tar.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_v7tar.o `test -f 'libarchive/archive_write_set_format_v7tar.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_v7tar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_v7tar.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_v7tar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_v7tar.c' object='libarchive/libarchive_test-archive_write_set_format_v7tar.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_v7tar.o `test -f 'libarchive/archive_write_set_format_v7tar.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_v7tar.c + +libarchive/libarchive_test-archive_write_set_format_v7tar.obj: libarchive/archive_write_set_format_v7tar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_v7tar.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_v7tar.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_v7tar.obj `if test -f 'libarchive/archive_write_set_format_v7tar.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_v7tar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_v7tar.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_v7tar.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_v7tar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_v7tar.c' object='libarchive/libarchive_test-archive_write_set_format_v7tar.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_v7tar.obj `if test -f 'libarchive/archive_write_set_format_v7tar.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_v7tar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_v7tar.c'; fi` + +libarchive/libarchive_test-archive_write_set_format_gnutar.o: libarchive/archive_write_set_format_gnutar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_gnutar.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_gnutar.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_gnutar.o `test -f 'libarchive/archive_write_set_format_gnutar.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_gnutar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_gnutar.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_gnutar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_gnutar.c' object='libarchive/libarchive_test-archive_write_set_format_gnutar.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_gnutar.o `test -f 'libarchive/archive_write_set_format_gnutar.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_gnutar.c + +libarchive/libarchive_test-archive_write_set_format_gnutar.obj: libarchive/archive_write_set_format_gnutar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_gnutar.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_gnutar.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_gnutar.obj `if test -f 'libarchive/archive_write_set_format_gnutar.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_gnutar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_gnutar.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_gnutar.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_gnutar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_gnutar.c' object='libarchive/libarchive_test-archive_write_set_format_gnutar.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_gnutar.obj `if test -f 'libarchive/archive_write_set_format_gnutar.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_gnutar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_gnutar.c'; fi` + +libarchive/libarchive_test-archive_write_set_format_warc.o: libarchive/archive_write_set_format_warc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_warc.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_warc.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_warc.o `test -f 'libarchive/archive_write_set_format_warc.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_warc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_warc.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_warc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_warc.c' object='libarchive/libarchive_test-archive_write_set_format_warc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_warc.o `test -f 'libarchive/archive_write_set_format_warc.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_warc.c + +libarchive/libarchive_test-archive_write_set_format_warc.obj: libarchive/archive_write_set_format_warc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_warc.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_warc.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_warc.obj `if test -f 'libarchive/archive_write_set_format_warc.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_warc.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_warc.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_warc.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_warc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_warc.c' object='libarchive/libarchive_test-archive_write_set_format_warc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_warc.obj `if test -f 'libarchive/archive_write_set_format_warc.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_warc.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_warc.c'; fi` + +libarchive/libarchive_test-archive_write_set_format_xar.o: libarchive/archive_write_set_format_xar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_xar.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_xar.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_xar.o `test -f 'libarchive/archive_write_set_format_xar.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_xar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_xar.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_xar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_xar.c' object='libarchive/libarchive_test-archive_write_set_format_xar.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_xar.o `test -f 'libarchive/archive_write_set_format_xar.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_xar.c + +libarchive/libarchive_test-archive_write_set_format_xar.obj: libarchive/archive_write_set_format_xar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_xar.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_xar.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_xar.obj `if test -f 'libarchive/archive_write_set_format_xar.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_xar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_xar.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_xar.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_xar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_xar.c' object='libarchive/libarchive_test-archive_write_set_format_xar.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_xar.obj `if test -f 'libarchive/archive_write_set_format_xar.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_xar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_xar.c'; fi` + +libarchive/libarchive_test-archive_write_set_format_zip.o: libarchive/archive_write_set_format_zip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_zip.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_zip.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_zip.o `test -f 'libarchive/archive_write_set_format_zip.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_zip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_zip.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_zip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_zip.c' object='libarchive/libarchive_test-archive_write_set_format_zip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_zip.o `test -f 'libarchive/archive_write_set_format_zip.c' || echo '$(srcdir)/'`libarchive/archive_write_set_format_zip.c + +libarchive/libarchive_test-archive_write_set_format_zip.obj: libarchive/archive_write_set_format_zip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_format_zip.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_zip.Tpo -c -o libarchive/libarchive_test-archive_write_set_format_zip.obj `if test -f 'libarchive/archive_write_set_format_zip.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_zip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_zip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_zip.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_format_zip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_format_zip.c' object='libarchive/libarchive_test-archive_write_set_format_zip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_format_zip.obj `if test -f 'libarchive/archive_write_set_format_zip.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_format_zip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_format_zip.c'; fi` + +libarchive/libarchive_test-archive_write_set_options.o: libarchive/archive_write_set_options.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_options.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_options.Tpo -c -o libarchive/libarchive_test-archive_write_set_options.o `test -f 'libarchive/archive_write_set_options.c' || echo '$(srcdir)/'`libarchive/archive_write_set_options.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_options.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_options.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_options.c' object='libarchive/libarchive_test-archive_write_set_options.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_options.o `test -f 'libarchive/archive_write_set_options.c' || echo '$(srcdir)/'`libarchive/archive_write_set_options.c + +libarchive/libarchive_test-archive_write_set_options.obj: libarchive/archive_write_set_options.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_options.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_options.Tpo -c -o libarchive/libarchive_test-archive_write_set_options.obj `if test -f 'libarchive/archive_write_set_options.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_options.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_options.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_options.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_options.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_options.c' object='libarchive/libarchive_test-archive_write_set_options.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_options.obj `if test -f 'libarchive/archive_write_set_options.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_options.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_options.c'; fi` + +libarchive/libarchive_test-archive_write_set_passphrase.o: libarchive/archive_write_set_passphrase.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_passphrase.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_passphrase.Tpo -c -o libarchive/libarchive_test-archive_write_set_passphrase.o `test -f 'libarchive/archive_write_set_passphrase.c' || echo '$(srcdir)/'`libarchive/archive_write_set_passphrase.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_passphrase.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_passphrase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_passphrase.c' object='libarchive/libarchive_test-archive_write_set_passphrase.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_passphrase.o `test -f 'libarchive/archive_write_set_passphrase.c' || echo '$(srcdir)/'`libarchive/archive_write_set_passphrase.c + +libarchive/libarchive_test-archive_write_set_passphrase.obj: libarchive/archive_write_set_passphrase.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_set_passphrase.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_set_passphrase.Tpo -c -o libarchive/libarchive_test-archive_write_set_passphrase.obj `if test -f 'libarchive/archive_write_set_passphrase.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_passphrase.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_passphrase.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_set_passphrase.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_set_passphrase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_set_passphrase.c' object='libarchive/libarchive_test-archive_write_set_passphrase.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_set_passphrase.obj `if test -f 'libarchive/archive_write_set_passphrase.c'; then $(CYGPATH_W) 'libarchive/archive_write_set_passphrase.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_set_passphrase.c'; fi` + +libarchive/libarchive_test-filter_fork_posix.o: libarchive/filter_fork_posix.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-filter_fork_posix.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-filter_fork_posix.Tpo -c -o libarchive/libarchive_test-filter_fork_posix.o `test -f 'libarchive/filter_fork_posix.c' || echo '$(srcdir)/'`libarchive/filter_fork_posix.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-filter_fork_posix.Tpo libarchive/$(DEPDIR)/libarchive_test-filter_fork_posix.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/filter_fork_posix.c' object='libarchive/libarchive_test-filter_fork_posix.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-filter_fork_posix.o `test -f 'libarchive/filter_fork_posix.c' || echo '$(srcdir)/'`libarchive/filter_fork_posix.c + +libarchive/libarchive_test-filter_fork_posix.obj: libarchive/filter_fork_posix.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-filter_fork_posix.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-filter_fork_posix.Tpo -c -o libarchive/libarchive_test-filter_fork_posix.obj `if test -f 'libarchive/filter_fork_posix.c'; then $(CYGPATH_W) 'libarchive/filter_fork_posix.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/filter_fork_posix.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-filter_fork_posix.Tpo libarchive/$(DEPDIR)/libarchive_test-filter_fork_posix.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/filter_fork_posix.c' object='libarchive/libarchive_test-filter_fork_posix.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-filter_fork_posix.obj `if test -f 'libarchive/filter_fork_posix.c'; then $(CYGPATH_W) 'libarchive/filter_fork_posix.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/filter_fork_posix.c'; fi` + +libarchive/libarchive_test-xxhash.o: libarchive/xxhash.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-xxhash.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-xxhash.Tpo -c -o libarchive/libarchive_test-xxhash.o `test -f 'libarchive/xxhash.c' || echo '$(srcdir)/'`libarchive/xxhash.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-xxhash.Tpo libarchive/$(DEPDIR)/libarchive_test-xxhash.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/xxhash.c' object='libarchive/libarchive_test-xxhash.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-xxhash.o `test -f 'libarchive/xxhash.c' || echo '$(srcdir)/'`libarchive/xxhash.c + +libarchive/libarchive_test-xxhash.obj: libarchive/xxhash.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-xxhash.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-xxhash.Tpo -c -o libarchive/libarchive_test-xxhash.obj `if test -f 'libarchive/xxhash.c'; then $(CYGPATH_W) 'libarchive/xxhash.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/xxhash.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-xxhash.Tpo libarchive/$(DEPDIR)/libarchive_test-xxhash.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/xxhash.c' object='libarchive/libarchive_test-xxhash.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-xxhash.obj `if test -f 'libarchive/xxhash.c'; then $(CYGPATH_W) 'libarchive/xxhash.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/xxhash.c'; fi` + +libarchive/libarchive_test-archive_entry_copy_bhfi.o: libarchive/archive_entry_copy_bhfi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_entry_copy_bhfi.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_entry_copy_bhfi.Tpo -c -o libarchive/libarchive_test-archive_entry_copy_bhfi.o `test -f 'libarchive/archive_entry_copy_bhfi.c' || echo '$(srcdir)/'`libarchive/archive_entry_copy_bhfi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_entry_copy_bhfi.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_entry_copy_bhfi.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_entry_copy_bhfi.c' object='libarchive/libarchive_test-archive_entry_copy_bhfi.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_entry_copy_bhfi.o `test -f 'libarchive/archive_entry_copy_bhfi.c' || echo '$(srcdir)/'`libarchive/archive_entry_copy_bhfi.c + +libarchive/libarchive_test-archive_entry_copy_bhfi.obj: libarchive/archive_entry_copy_bhfi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_entry_copy_bhfi.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_entry_copy_bhfi.Tpo -c -o libarchive/libarchive_test-archive_entry_copy_bhfi.obj `if test -f 'libarchive/archive_entry_copy_bhfi.c'; then $(CYGPATH_W) 'libarchive/archive_entry_copy_bhfi.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_entry_copy_bhfi.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_entry_copy_bhfi.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_entry_copy_bhfi.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_entry_copy_bhfi.c' object='libarchive/libarchive_test-archive_entry_copy_bhfi.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_entry_copy_bhfi.obj `if test -f 'libarchive/archive_entry_copy_bhfi.c'; then $(CYGPATH_W) 'libarchive/archive_entry_copy_bhfi.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_entry_copy_bhfi.c'; fi` + +libarchive/libarchive_test-archive_read_disk_windows.o: libarchive/archive_read_disk_windows.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_disk_windows.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_windows.Tpo -c -o libarchive/libarchive_test-archive_read_disk_windows.o `test -f 'libarchive/archive_read_disk_windows.c' || echo '$(srcdir)/'`libarchive/archive_read_disk_windows.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_windows.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_windows.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_disk_windows.c' object='libarchive/libarchive_test-archive_read_disk_windows.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_disk_windows.o `test -f 'libarchive/archive_read_disk_windows.c' || echo '$(srcdir)/'`libarchive/archive_read_disk_windows.c + +libarchive/libarchive_test-archive_read_disk_windows.obj: libarchive/archive_read_disk_windows.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_read_disk_windows.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_windows.Tpo -c -o libarchive/libarchive_test-archive_read_disk_windows.obj `if test -f 'libarchive/archive_read_disk_windows.c'; then $(CYGPATH_W) 'libarchive/archive_read_disk_windows.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_disk_windows.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_windows.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_read_disk_windows.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_read_disk_windows.c' object='libarchive/libarchive_test-archive_read_disk_windows.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_read_disk_windows.obj `if test -f 'libarchive/archive_read_disk_windows.c'; then $(CYGPATH_W) 'libarchive/archive_read_disk_windows.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_read_disk_windows.c'; fi` + +libarchive/libarchive_test-archive_windows.o: libarchive/archive_windows.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_windows.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_windows.Tpo -c -o libarchive/libarchive_test-archive_windows.o `test -f 'libarchive/archive_windows.c' || echo '$(srcdir)/'`libarchive/archive_windows.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_windows.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_windows.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_windows.c' object='libarchive/libarchive_test-archive_windows.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_windows.o `test -f 'libarchive/archive_windows.c' || echo '$(srcdir)/'`libarchive/archive_windows.c + +libarchive/libarchive_test-archive_windows.obj: libarchive/archive_windows.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_windows.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_windows.Tpo -c -o libarchive/libarchive_test-archive_windows.obj `if test -f 'libarchive/archive_windows.c'; then $(CYGPATH_W) 'libarchive/archive_windows.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_windows.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_windows.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_windows.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_windows.c' object='libarchive/libarchive_test-archive_windows.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_windows.obj `if test -f 'libarchive/archive_windows.c'; then $(CYGPATH_W) 'libarchive/archive_windows.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_windows.c'; fi` + +libarchive/libarchive_test-archive_write_disk_windows.o: libarchive/archive_write_disk_windows.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_disk_windows.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_disk_windows.Tpo -c -o libarchive/libarchive_test-archive_write_disk_windows.o `test -f 'libarchive/archive_write_disk_windows.c' || echo '$(srcdir)/'`libarchive/archive_write_disk_windows.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_disk_windows.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_disk_windows.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_disk_windows.c' object='libarchive/libarchive_test-archive_write_disk_windows.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_disk_windows.o `test -f 'libarchive/archive_write_disk_windows.c' || echo '$(srcdir)/'`libarchive/archive_write_disk_windows.c + +libarchive/libarchive_test-archive_write_disk_windows.obj: libarchive/archive_write_disk_windows.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_write_disk_windows.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_write_disk_windows.Tpo -c -o libarchive/libarchive_test-archive_write_disk_windows.obj `if test -f 'libarchive/archive_write_disk_windows.c'; then $(CYGPATH_W) 'libarchive/archive_write_disk_windows.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_disk_windows.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_write_disk_windows.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_write_disk_windows.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_write_disk_windows.c' object='libarchive/libarchive_test-archive_write_disk_windows.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_write_disk_windows.obj `if test -f 'libarchive/archive_write_disk_windows.c'; then $(CYGPATH_W) 'libarchive/archive_write_disk_windows.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_write_disk_windows.c'; fi` + +libarchive/libarchive_test-filter_fork_windows.o: libarchive/filter_fork_windows.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-filter_fork_windows.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-filter_fork_windows.Tpo -c -o libarchive/libarchive_test-filter_fork_windows.o `test -f 'libarchive/filter_fork_windows.c' || echo '$(srcdir)/'`libarchive/filter_fork_windows.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-filter_fork_windows.Tpo libarchive/$(DEPDIR)/libarchive_test-filter_fork_windows.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/filter_fork_windows.c' object='libarchive/libarchive_test-filter_fork_windows.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-filter_fork_windows.o `test -f 'libarchive/filter_fork_windows.c' || echo '$(srcdir)/'`libarchive/filter_fork_windows.c + +libarchive/libarchive_test-filter_fork_windows.obj: libarchive/filter_fork_windows.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-filter_fork_windows.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-filter_fork_windows.Tpo -c -o libarchive/libarchive_test-filter_fork_windows.obj `if test -f 'libarchive/filter_fork_windows.c'; then $(CYGPATH_W) 'libarchive/filter_fork_windows.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/filter_fork_windows.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-filter_fork_windows.Tpo libarchive/$(DEPDIR)/libarchive_test-filter_fork_windows.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/filter_fork_windows.c' object='libarchive/libarchive_test-filter_fork_windows.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-filter_fork_windows.obj `if test -f 'libarchive/filter_fork_windows.c'; then $(CYGPATH_W) 'libarchive/filter_fork_windows.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/filter_fork_windows.c'; fi` + +libarchive/libarchive_test-archive_blake2s_ref.o: libarchive/archive_blake2s_ref.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_blake2s_ref.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_blake2s_ref.Tpo -c -o libarchive/libarchive_test-archive_blake2s_ref.o `test -f 'libarchive/archive_blake2s_ref.c' || echo '$(srcdir)/'`libarchive/archive_blake2s_ref.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_blake2s_ref.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_blake2s_ref.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_blake2s_ref.c' object='libarchive/libarchive_test-archive_blake2s_ref.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_blake2s_ref.o `test -f 'libarchive/archive_blake2s_ref.c' || echo '$(srcdir)/'`libarchive/archive_blake2s_ref.c + +libarchive/libarchive_test-archive_blake2s_ref.obj: libarchive/archive_blake2s_ref.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_blake2s_ref.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_blake2s_ref.Tpo -c -o libarchive/libarchive_test-archive_blake2s_ref.obj `if test -f 'libarchive/archive_blake2s_ref.c'; then $(CYGPATH_W) 'libarchive/archive_blake2s_ref.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_blake2s_ref.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_blake2s_ref.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_blake2s_ref.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_blake2s_ref.c' object='libarchive/libarchive_test-archive_blake2s_ref.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_blake2s_ref.obj `if test -f 'libarchive/archive_blake2s_ref.c'; then $(CYGPATH_W) 'libarchive/archive_blake2s_ref.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_blake2s_ref.c'; fi` + +libarchive/libarchive_test-archive_blake2sp_ref.o: libarchive/archive_blake2sp_ref.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_blake2sp_ref.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_blake2sp_ref.Tpo -c -o libarchive/libarchive_test-archive_blake2sp_ref.o `test -f 'libarchive/archive_blake2sp_ref.c' || echo '$(srcdir)/'`libarchive/archive_blake2sp_ref.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_blake2sp_ref.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_blake2sp_ref.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_blake2sp_ref.c' object='libarchive/libarchive_test-archive_blake2sp_ref.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_blake2sp_ref.o `test -f 'libarchive/archive_blake2sp_ref.c' || echo '$(srcdir)/'`libarchive/archive_blake2sp_ref.c + +libarchive/libarchive_test-archive_blake2sp_ref.obj: libarchive/archive_blake2sp_ref.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_blake2sp_ref.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_blake2sp_ref.Tpo -c -o libarchive/libarchive_test-archive_blake2sp_ref.obj `if test -f 'libarchive/archive_blake2sp_ref.c'; then $(CYGPATH_W) 'libarchive/archive_blake2sp_ref.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_blake2sp_ref.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_blake2sp_ref.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_blake2sp_ref.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_blake2sp_ref.c' object='libarchive/libarchive_test-archive_blake2sp_ref.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_blake2sp_ref.obj `if test -f 'libarchive/archive_blake2sp_ref.c'; then $(CYGPATH_W) 'libarchive/archive_blake2sp_ref.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_blake2sp_ref.c'; fi` + +libarchive/libarchive_test-archive_disk_acl_linux.o: libarchive/archive_disk_acl_linux.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_disk_acl_linux.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_linux.Tpo -c -o libarchive/libarchive_test-archive_disk_acl_linux.o `test -f 'libarchive/archive_disk_acl_linux.c' || echo '$(srcdir)/'`libarchive/archive_disk_acl_linux.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_linux.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_linux.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_disk_acl_linux.c' object='libarchive/libarchive_test-archive_disk_acl_linux.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_disk_acl_linux.o `test -f 'libarchive/archive_disk_acl_linux.c' || echo '$(srcdir)/'`libarchive/archive_disk_acl_linux.c + +libarchive/libarchive_test-archive_disk_acl_linux.obj: libarchive/archive_disk_acl_linux.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_disk_acl_linux.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_linux.Tpo -c -o libarchive/libarchive_test-archive_disk_acl_linux.obj `if test -f 'libarchive/archive_disk_acl_linux.c'; then $(CYGPATH_W) 'libarchive/archive_disk_acl_linux.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_disk_acl_linux.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_linux.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_linux.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_disk_acl_linux.c' object='libarchive/libarchive_test-archive_disk_acl_linux.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_disk_acl_linux.obj `if test -f 'libarchive/archive_disk_acl_linux.c'; then $(CYGPATH_W) 'libarchive/archive_disk_acl_linux.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_disk_acl_linux.c'; fi` + +libarchive/libarchive_test-archive_disk_acl_sunos.o: libarchive/archive_disk_acl_sunos.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_disk_acl_sunos.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_sunos.Tpo -c -o libarchive/libarchive_test-archive_disk_acl_sunos.o `test -f 'libarchive/archive_disk_acl_sunos.c' || echo '$(srcdir)/'`libarchive/archive_disk_acl_sunos.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_sunos.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_sunos.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_disk_acl_sunos.c' object='libarchive/libarchive_test-archive_disk_acl_sunos.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_disk_acl_sunos.o `test -f 'libarchive/archive_disk_acl_sunos.c' || echo '$(srcdir)/'`libarchive/archive_disk_acl_sunos.c + +libarchive/libarchive_test-archive_disk_acl_sunos.obj: libarchive/archive_disk_acl_sunos.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_disk_acl_sunos.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_sunos.Tpo -c -o libarchive/libarchive_test-archive_disk_acl_sunos.obj `if test -f 'libarchive/archive_disk_acl_sunos.c'; then $(CYGPATH_W) 'libarchive/archive_disk_acl_sunos.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_disk_acl_sunos.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_sunos.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_sunos.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_disk_acl_sunos.c' object='libarchive/libarchive_test-archive_disk_acl_sunos.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_disk_acl_sunos.obj `if test -f 'libarchive/archive_disk_acl_sunos.c'; then $(CYGPATH_W) 'libarchive/archive_disk_acl_sunos.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_disk_acl_sunos.c'; fi` + +libarchive/libarchive_test-archive_disk_acl_darwin.o: libarchive/archive_disk_acl_darwin.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_disk_acl_darwin.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_darwin.Tpo -c -o libarchive/libarchive_test-archive_disk_acl_darwin.o `test -f 'libarchive/archive_disk_acl_darwin.c' || echo '$(srcdir)/'`libarchive/archive_disk_acl_darwin.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_darwin.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_darwin.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_disk_acl_darwin.c' object='libarchive/libarchive_test-archive_disk_acl_darwin.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_disk_acl_darwin.o `test -f 'libarchive/archive_disk_acl_darwin.c' || echo '$(srcdir)/'`libarchive/archive_disk_acl_darwin.c + +libarchive/libarchive_test-archive_disk_acl_darwin.obj: libarchive/archive_disk_acl_darwin.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_disk_acl_darwin.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_darwin.Tpo -c -o libarchive/libarchive_test-archive_disk_acl_darwin.obj `if test -f 'libarchive/archive_disk_acl_darwin.c'; then $(CYGPATH_W) 'libarchive/archive_disk_acl_darwin.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_disk_acl_darwin.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_darwin.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_darwin.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_disk_acl_darwin.c' object='libarchive/libarchive_test-archive_disk_acl_darwin.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_disk_acl_darwin.obj `if test -f 'libarchive/archive_disk_acl_darwin.c'; then $(CYGPATH_W) 'libarchive/archive_disk_acl_darwin.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_disk_acl_darwin.c'; fi` + +libarchive/libarchive_test-archive_disk_acl_freebsd.o: libarchive/archive_disk_acl_freebsd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_disk_acl_freebsd.o -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_freebsd.Tpo -c -o libarchive/libarchive_test-archive_disk_acl_freebsd.o `test -f 'libarchive/archive_disk_acl_freebsd.c' || echo '$(srcdir)/'`libarchive/archive_disk_acl_freebsd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_freebsd.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_freebsd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_disk_acl_freebsd.c' object='libarchive/libarchive_test-archive_disk_acl_freebsd.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_disk_acl_freebsd.o `test -f 'libarchive/archive_disk_acl_freebsd.c' || echo '$(srcdir)/'`libarchive/archive_disk_acl_freebsd.c + +libarchive/libarchive_test-archive_disk_acl_freebsd.obj: libarchive/archive_disk_acl_freebsd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/libarchive_test-archive_disk_acl_freebsd.obj -MD -MP -MF libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_freebsd.Tpo -c -o libarchive/libarchive_test-archive_disk_acl_freebsd.obj `if test -f 'libarchive/archive_disk_acl_freebsd.c'; then $(CYGPATH_W) 'libarchive/archive_disk_acl_freebsd.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_disk_acl_freebsd.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_freebsd.Tpo libarchive/$(DEPDIR)/libarchive_test-archive_disk_acl_freebsd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/archive_disk_acl_freebsd.c' object='libarchive/libarchive_test-archive_disk_acl_freebsd.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/libarchive_test-archive_disk_acl_freebsd.obj `if test -f 'libarchive/archive_disk_acl_freebsd.c'; then $(CYGPATH_W) 'libarchive/archive_disk_acl_freebsd.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/archive_disk_acl_freebsd.c'; fi` + +test_utils/libarchive_test-test_utils.o: test_utils/test_utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_utils/libarchive_test-test_utils.o -MD -MP -MF test_utils/$(DEPDIR)/libarchive_test-test_utils.Tpo -c -o test_utils/libarchive_test-test_utils.o `test -f 'test_utils/test_utils.c' || echo '$(srcdir)/'`test_utils/test_utils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) test_utils/$(DEPDIR)/libarchive_test-test_utils.Tpo test_utils/$(DEPDIR)/libarchive_test-test_utils.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_utils/test_utils.c' object='test_utils/libarchive_test-test_utils.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_utils/libarchive_test-test_utils.o `test -f 'test_utils/test_utils.c' || echo '$(srcdir)/'`test_utils/test_utils.c + +test_utils/libarchive_test-test_utils.obj: test_utils/test_utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_utils/libarchive_test-test_utils.obj -MD -MP -MF test_utils/$(DEPDIR)/libarchive_test-test_utils.Tpo -c -o test_utils/libarchive_test-test_utils.obj `if test -f 'test_utils/test_utils.c'; then $(CYGPATH_W) 'test_utils/test_utils.c'; else $(CYGPATH_W) '$(srcdir)/test_utils/test_utils.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) test_utils/$(DEPDIR)/libarchive_test-test_utils.Tpo test_utils/$(DEPDIR)/libarchive_test-test_utils.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_utils/test_utils.c' object='test_utils/libarchive_test-test_utils.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_utils/libarchive_test-test_utils.obj `if test -f 'test_utils/test_utils.c'; then $(CYGPATH_W) 'test_utils/test_utils.c'; else $(CYGPATH_W) '$(srcdir)/test_utils/test_utils.c'; fi` + +test_utils/libarchive_test-test_main.o: test_utils/test_main.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_utils/libarchive_test-test_main.o -MD -MP -MF test_utils/$(DEPDIR)/libarchive_test-test_main.Tpo -c -o test_utils/libarchive_test-test_main.o `test -f 'test_utils/test_main.c' || echo '$(srcdir)/'`test_utils/test_main.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) test_utils/$(DEPDIR)/libarchive_test-test_main.Tpo test_utils/$(DEPDIR)/libarchive_test-test_main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_utils/test_main.c' object='test_utils/libarchive_test-test_main.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_utils/libarchive_test-test_main.o `test -f 'test_utils/test_main.c' || echo '$(srcdir)/'`test_utils/test_main.c + +test_utils/libarchive_test-test_main.obj: test_utils/test_main.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_utils/libarchive_test-test_main.obj -MD -MP -MF test_utils/$(DEPDIR)/libarchive_test-test_main.Tpo -c -o test_utils/libarchive_test-test_main.obj `if test -f 'test_utils/test_main.c'; then $(CYGPATH_W) 'test_utils/test_main.c'; else $(CYGPATH_W) '$(srcdir)/test_utils/test_main.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) test_utils/$(DEPDIR)/libarchive_test-test_main.Tpo test_utils/$(DEPDIR)/libarchive_test-test_main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_utils/test_main.c' object='test_utils/libarchive_test-test_main.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_utils/libarchive_test-test_main.obj `if test -f 'test_utils/test_main.c'; then $(CYGPATH_W) 'test_utils/test_main.c'; else $(CYGPATH_W) '$(srcdir)/test_utils/test_main.c'; fi` + +libarchive/test/libarchive_test-read_open_memory.o: libarchive/test/read_open_memory.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-read_open_memory.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-read_open_memory.Tpo -c -o libarchive/test/libarchive_test-read_open_memory.o `test -f 'libarchive/test/read_open_memory.c' || echo '$(srcdir)/'`libarchive/test/read_open_memory.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-read_open_memory.Tpo libarchive/test/$(DEPDIR)/libarchive_test-read_open_memory.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/read_open_memory.c' object='libarchive/test/libarchive_test-read_open_memory.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-read_open_memory.o `test -f 'libarchive/test/read_open_memory.c' || echo '$(srcdir)/'`libarchive/test/read_open_memory.c + +libarchive/test/libarchive_test-read_open_memory.obj: libarchive/test/read_open_memory.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-read_open_memory.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-read_open_memory.Tpo -c -o libarchive/test/libarchive_test-read_open_memory.obj `if test -f 'libarchive/test/read_open_memory.c'; then $(CYGPATH_W) 'libarchive/test/read_open_memory.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/read_open_memory.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-read_open_memory.Tpo libarchive/test/$(DEPDIR)/libarchive_test-read_open_memory.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/read_open_memory.c' object='libarchive/test/libarchive_test-read_open_memory.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-read_open_memory.obj `if test -f 'libarchive/test/read_open_memory.c'; then $(CYGPATH_W) 'libarchive/test/read_open_memory.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/read_open_memory.c'; fi` + +libarchive/test/libarchive_test-test_acl_nfs4.o: libarchive/test/test_acl_nfs4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_acl_nfs4.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_acl_nfs4.Tpo -c -o libarchive/test/libarchive_test-test_acl_nfs4.o `test -f 'libarchive/test/test_acl_nfs4.c' || echo '$(srcdir)/'`libarchive/test/test_acl_nfs4.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_acl_nfs4.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_acl_nfs4.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_acl_nfs4.c' object='libarchive/test/libarchive_test-test_acl_nfs4.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_acl_nfs4.o `test -f 'libarchive/test/test_acl_nfs4.c' || echo '$(srcdir)/'`libarchive/test/test_acl_nfs4.c + +libarchive/test/libarchive_test-test_acl_nfs4.obj: libarchive/test/test_acl_nfs4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_acl_nfs4.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_acl_nfs4.Tpo -c -o libarchive/test/libarchive_test-test_acl_nfs4.obj `if test -f 'libarchive/test/test_acl_nfs4.c'; then $(CYGPATH_W) 'libarchive/test/test_acl_nfs4.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_acl_nfs4.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_acl_nfs4.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_acl_nfs4.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_acl_nfs4.c' object='libarchive/test/libarchive_test-test_acl_nfs4.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_acl_nfs4.obj `if test -f 'libarchive/test/test_acl_nfs4.c'; then $(CYGPATH_W) 'libarchive/test/test_acl_nfs4.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_acl_nfs4.c'; fi` + +libarchive/test/libarchive_test-test_acl_pax.o: libarchive/test/test_acl_pax.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_acl_pax.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_acl_pax.Tpo -c -o libarchive/test/libarchive_test-test_acl_pax.o `test -f 'libarchive/test/test_acl_pax.c' || echo '$(srcdir)/'`libarchive/test/test_acl_pax.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_acl_pax.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_acl_pax.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_acl_pax.c' object='libarchive/test/libarchive_test-test_acl_pax.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_acl_pax.o `test -f 'libarchive/test/test_acl_pax.c' || echo '$(srcdir)/'`libarchive/test/test_acl_pax.c + +libarchive/test/libarchive_test-test_acl_pax.obj: libarchive/test/test_acl_pax.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_acl_pax.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_acl_pax.Tpo -c -o libarchive/test/libarchive_test-test_acl_pax.obj `if test -f 'libarchive/test/test_acl_pax.c'; then $(CYGPATH_W) 'libarchive/test/test_acl_pax.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_acl_pax.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_acl_pax.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_acl_pax.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_acl_pax.c' object='libarchive/test/libarchive_test-test_acl_pax.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_acl_pax.obj `if test -f 'libarchive/test/test_acl_pax.c'; then $(CYGPATH_W) 'libarchive/test/test_acl_pax.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_acl_pax.c'; fi` + +libarchive/test/libarchive_test-test_acl_platform_nfs4.o: libarchive/test/test_acl_platform_nfs4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_acl_platform_nfs4.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_acl_platform_nfs4.Tpo -c -o libarchive/test/libarchive_test-test_acl_platform_nfs4.o `test -f 'libarchive/test/test_acl_platform_nfs4.c' || echo '$(srcdir)/'`libarchive/test/test_acl_platform_nfs4.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_acl_platform_nfs4.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_acl_platform_nfs4.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_acl_platform_nfs4.c' object='libarchive/test/libarchive_test-test_acl_platform_nfs4.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_acl_platform_nfs4.o `test -f 'libarchive/test/test_acl_platform_nfs4.c' || echo '$(srcdir)/'`libarchive/test/test_acl_platform_nfs4.c + +libarchive/test/libarchive_test-test_acl_platform_nfs4.obj: libarchive/test/test_acl_platform_nfs4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_acl_platform_nfs4.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_acl_platform_nfs4.Tpo -c -o libarchive/test/libarchive_test-test_acl_platform_nfs4.obj `if test -f 'libarchive/test/test_acl_platform_nfs4.c'; then $(CYGPATH_W) 'libarchive/test/test_acl_platform_nfs4.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_acl_platform_nfs4.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_acl_platform_nfs4.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_acl_platform_nfs4.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_acl_platform_nfs4.c' object='libarchive/test/libarchive_test-test_acl_platform_nfs4.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_acl_platform_nfs4.obj `if test -f 'libarchive/test/test_acl_platform_nfs4.c'; then $(CYGPATH_W) 'libarchive/test/test_acl_platform_nfs4.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_acl_platform_nfs4.c'; fi` + +libarchive/test/libarchive_test-test_acl_platform_posix1e.o: libarchive/test/test_acl_platform_posix1e.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_acl_platform_posix1e.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_acl_platform_posix1e.Tpo -c -o libarchive/test/libarchive_test-test_acl_platform_posix1e.o `test -f 'libarchive/test/test_acl_platform_posix1e.c' || echo '$(srcdir)/'`libarchive/test/test_acl_platform_posix1e.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_acl_platform_posix1e.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_acl_platform_posix1e.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_acl_platform_posix1e.c' object='libarchive/test/libarchive_test-test_acl_platform_posix1e.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_acl_platform_posix1e.o `test -f 'libarchive/test/test_acl_platform_posix1e.c' || echo '$(srcdir)/'`libarchive/test/test_acl_platform_posix1e.c + +libarchive/test/libarchive_test-test_acl_platform_posix1e.obj: libarchive/test/test_acl_platform_posix1e.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_acl_platform_posix1e.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_acl_platform_posix1e.Tpo -c -o libarchive/test/libarchive_test-test_acl_platform_posix1e.obj `if test -f 'libarchive/test/test_acl_platform_posix1e.c'; then $(CYGPATH_W) 'libarchive/test/test_acl_platform_posix1e.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_acl_platform_posix1e.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_acl_platform_posix1e.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_acl_platform_posix1e.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_acl_platform_posix1e.c' object='libarchive/test/libarchive_test-test_acl_platform_posix1e.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_acl_platform_posix1e.obj `if test -f 'libarchive/test/test_acl_platform_posix1e.c'; then $(CYGPATH_W) 'libarchive/test/test_acl_platform_posix1e.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_acl_platform_posix1e.c'; fi` + +libarchive/test/libarchive_test-test_acl_posix1e.o: libarchive/test/test_acl_posix1e.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_acl_posix1e.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_acl_posix1e.Tpo -c -o libarchive/test/libarchive_test-test_acl_posix1e.o `test -f 'libarchive/test/test_acl_posix1e.c' || echo '$(srcdir)/'`libarchive/test/test_acl_posix1e.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_acl_posix1e.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_acl_posix1e.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_acl_posix1e.c' object='libarchive/test/libarchive_test-test_acl_posix1e.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_acl_posix1e.o `test -f 'libarchive/test/test_acl_posix1e.c' || echo '$(srcdir)/'`libarchive/test/test_acl_posix1e.c + +libarchive/test/libarchive_test-test_acl_posix1e.obj: libarchive/test/test_acl_posix1e.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_acl_posix1e.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_acl_posix1e.Tpo -c -o libarchive/test/libarchive_test-test_acl_posix1e.obj `if test -f 'libarchive/test/test_acl_posix1e.c'; then $(CYGPATH_W) 'libarchive/test/test_acl_posix1e.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_acl_posix1e.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_acl_posix1e.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_acl_posix1e.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_acl_posix1e.c' object='libarchive/test/libarchive_test-test_acl_posix1e.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_acl_posix1e.obj `if test -f 'libarchive/test/test_acl_posix1e.c'; then $(CYGPATH_W) 'libarchive/test/test_acl_posix1e.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_acl_posix1e.c'; fi` + +libarchive/test/libarchive_test-test_acl_text.o: libarchive/test/test_acl_text.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_acl_text.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_acl_text.Tpo -c -o libarchive/test/libarchive_test-test_acl_text.o `test -f 'libarchive/test/test_acl_text.c' || echo '$(srcdir)/'`libarchive/test/test_acl_text.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_acl_text.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_acl_text.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_acl_text.c' object='libarchive/test/libarchive_test-test_acl_text.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_acl_text.o `test -f 'libarchive/test/test_acl_text.c' || echo '$(srcdir)/'`libarchive/test/test_acl_text.c + +libarchive/test/libarchive_test-test_acl_text.obj: libarchive/test/test_acl_text.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_acl_text.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_acl_text.Tpo -c -o libarchive/test/libarchive_test-test_acl_text.obj `if test -f 'libarchive/test/test_acl_text.c'; then $(CYGPATH_W) 'libarchive/test/test_acl_text.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_acl_text.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_acl_text.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_acl_text.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_acl_text.c' object='libarchive/test/libarchive_test-test_acl_text.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_acl_text.obj `if test -f 'libarchive/test/test_acl_text.c'; then $(CYGPATH_W) 'libarchive/test/test_acl_text.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_acl_text.c'; fi` + +libarchive/test/libarchive_test-test_archive_api_feature.o: libarchive/test/test_archive_api_feature.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_api_feature.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_api_feature.Tpo -c -o libarchive/test/libarchive_test-test_archive_api_feature.o `test -f 'libarchive/test/test_archive_api_feature.c' || echo '$(srcdir)/'`libarchive/test/test_archive_api_feature.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_api_feature.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_api_feature.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_api_feature.c' object='libarchive/test/libarchive_test-test_archive_api_feature.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_api_feature.o `test -f 'libarchive/test/test_archive_api_feature.c' || echo '$(srcdir)/'`libarchive/test/test_archive_api_feature.c + +libarchive/test/libarchive_test-test_archive_api_feature.obj: libarchive/test/test_archive_api_feature.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_api_feature.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_api_feature.Tpo -c -o libarchive/test/libarchive_test-test_archive_api_feature.obj `if test -f 'libarchive/test/test_archive_api_feature.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_api_feature.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_api_feature.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_api_feature.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_api_feature.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_api_feature.c' object='libarchive/test/libarchive_test-test_archive_api_feature.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_api_feature.obj `if test -f 'libarchive/test/test_archive_api_feature.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_api_feature.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_api_feature.c'; fi` + +libarchive/test/libarchive_test-test_archive_clear_error.o: libarchive/test/test_archive_clear_error.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_clear_error.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_clear_error.Tpo -c -o libarchive/test/libarchive_test-test_archive_clear_error.o `test -f 'libarchive/test/test_archive_clear_error.c' || echo '$(srcdir)/'`libarchive/test/test_archive_clear_error.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_clear_error.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_clear_error.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_clear_error.c' object='libarchive/test/libarchive_test-test_archive_clear_error.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_clear_error.o `test -f 'libarchive/test/test_archive_clear_error.c' || echo '$(srcdir)/'`libarchive/test/test_archive_clear_error.c + +libarchive/test/libarchive_test-test_archive_clear_error.obj: libarchive/test/test_archive_clear_error.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_clear_error.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_clear_error.Tpo -c -o libarchive/test/libarchive_test-test_archive_clear_error.obj `if test -f 'libarchive/test/test_archive_clear_error.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_clear_error.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_clear_error.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_clear_error.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_clear_error.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_clear_error.c' object='libarchive/test/libarchive_test-test_archive_clear_error.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_clear_error.obj `if test -f 'libarchive/test/test_archive_clear_error.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_clear_error.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_clear_error.c'; fi` + +libarchive/test/libarchive_test-test_archive_cmdline.o: libarchive/test/test_archive_cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_cmdline.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_cmdline.Tpo -c -o libarchive/test/libarchive_test-test_archive_cmdline.o `test -f 'libarchive/test/test_archive_cmdline.c' || echo '$(srcdir)/'`libarchive/test/test_archive_cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_cmdline.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_cmdline.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_cmdline.c' object='libarchive/test/libarchive_test-test_archive_cmdline.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_cmdline.o `test -f 'libarchive/test/test_archive_cmdline.c' || echo '$(srcdir)/'`libarchive/test/test_archive_cmdline.c + +libarchive/test/libarchive_test-test_archive_cmdline.obj: libarchive/test/test_archive_cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_cmdline.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_cmdline.Tpo -c -o libarchive/test/libarchive_test-test_archive_cmdline.obj `if test -f 'libarchive/test/test_archive_cmdline.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_cmdline.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_cmdline.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_cmdline.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_cmdline.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_cmdline.c' object='libarchive/test/libarchive_test-test_archive_cmdline.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_cmdline.obj `if test -f 'libarchive/test/test_archive_cmdline.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_cmdline.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_cmdline.c'; fi` + +libarchive/test/libarchive_test-test_archive_digest.o: libarchive/test/test_archive_digest.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_digest.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_digest.Tpo -c -o libarchive/test/libarchive_test-test_archive_digest.o `test -f 'libarchive/test/test_archive_digest.c' || echo '$(srcdir)/'`libarchive/test/test_archive_digest.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_digest.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_digest.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_digest.c' object='libarchive/test/libarchive_test-test_archive_digest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_digest.o `test -f 'libarchive/test/test_archive_digest.c' || echo '$(srcdir)/'`libarchive/test/test_archive_digest.c + +libarchive/test/libarchive_test-test_archive_digest.obj: libarchive/test/test_archive_digest.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_digest.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_digest.Tpo -c -o libarchive/test/libarchive_test-test_archive_digest.obj `if test -f 'libarchive/test/test_archive_digest.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_digest.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_digest.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_digest.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_digest.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_digest.c' object='libarchive/test/libarchive_test-test_archive_digest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_digest.obj `if test -f 'libarchive/test/test_archive_digest.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_digest.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_digest.c'; fi` + +libarchive/test/libarchive_test-test_archive_getdate.o: libarchive/test/test_archive_getdate.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_getdate.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_getdate.Tpo -c -o libarchive/test/libarchive_test-test_archive_getdate.o `test -f 'libarchive/test/test_archive_getdate.c' || echo '$(srcdir)/'`libarchive/test/test_archive_getdate.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_getdate.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_getdate.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_getdate.c' object='libarchive/test/libarchive_test-test_archive_getdate.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_getdate.o `test -f 'libarchive/test/test_archive_getdate.c' || echo '$(srcdir)/'`libarchive/test/test_archive_getdate.c + +libarchive/test/libarchive_test-test_archive_getdate.obj: libarchive/test/test_archive_getdate.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_getdate.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_getdate.Tpo -c -o libarchive/test/libarchive_test-test_archive_getdate.obj `if test -f 'libarchive/test/test_archive_getdate.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_getdate.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_getdate.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_getdate.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_getdate.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_getdate.c' object='libarchive/test/libarchive_test-test_archive_getdate.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_getdate.obj `if test -f 'libarchive/test/test_archive_getdate.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_getdate.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_getdate.c'; fi` + +libarchive/test/libarchive_test-test_archive_match_owner.o: libarchive/test/test_archive_match_owner.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_match_owner.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_match_owner.Tpo -c -o libarchive/test/libarchive_test-test_archive_match_owner.o `test -f 'libarchive/test/test_archive_match_owner.c' || echo '$(srcdir)/'`libarchive/test/test_archive_match_owner.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_match_owner.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_match_owner.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_match_owner.c' object='libarchive/test/libarchive_test-test_archive_match_owner.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_match_owner.o `test -f 'libarchive/test/test_archive_match_owner.c' || echo '$(srcdir)/'`libarchive/test/test_archive_match_owner.c + +libarchive/test/libarchive_test-test_archive_match_owner.obj: libarchive/test/test_archive_match_owner.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_match_owner.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_match_owner.Tpo -c -o libarchive/test/libarchive_test-test_archive_match_owner.obj `if test -f 'libarchive/test/test_archive_match_owner.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_match_owner.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_match_owner.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_match_owner.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_match_owner.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_match_owner.c' object='libarchive/test/libarchive_test-test_archive_match_owner.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_match_owner.obj `if test -f 'libarchive/test/test_archive_match_owner.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_match_owner.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_match_owner.c'; fi` + +libarchive/test/libarchive_test-test_archive_match_path.o: libarchive/test/test_archive_match_path.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_match_path.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_match_path.Tpo -c -o libarchive/test/libarchive_test-test_archive_match_path.o `test -f 'libarchive/test/test_archive_match_path.c' || echo '$(srcdir)/'`libarchive/test/test_archive_match_path.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_match_path.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_match_path.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_match_path.c' object='libarchive/test/libarchive_test-test_archive_match_path.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_match_path.o `test -f 'libarchive/test/test_archive_match_path.c' || echo '$(srcdir)/'`libarchive/test/test_archive_match_path.c + +libarchive/test/libarchive_test-test_archive_match_path.obj: libarchive/test/test_archive_match_path.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_match_path.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_match_path.Tpo -c -o libarchive/test/libarchive_test-test_archive_match_path.obj `if test -f 'libarchive/test/test_archive_match_path.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_match_path.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_match_path.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_match_path.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_match_path.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_match_path.c' object='libarchive/test/libarchive_test-test_archive_match_path.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_match_path.obj `if test -f 'libarchive/test/test_archive_match_path.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_match_path.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_match_path.c'; fi` + +libarchive/test/libarchive_test-test_archive_match_time.o: libarchive/test/test_archive_match_time.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_match_time.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_match_time.Tpo -c -o libarchive/test/libarchive_test-test_archive_match_time.o `test -f 'libarchive/test/test_archive_match_time.c' || echo '$(srcdir)/'`libarchive/test/test_archive_match_time.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_match_time.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_match_time.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_match_time.c' object='libarchive/test/libarchive_test-test_archive_match_time.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_match_time.o `test -f 'libarchive/test/test_archive_match_time.c' || echo '$(srcdir)/'`libarchive/test/test_archive_match_time.c + +libarchive/test/libarchive_test-test_archive_match_time.obj: libarchive/test/test_archive_match_time.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_match_time.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_match_time.Tpo -c -o libarchive/test/libarchive_test-test_archive_match_time.obj `if test -f 'libarchive/test/test_archive_match_time.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_match_time.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_match_time.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_match_time.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_match_time.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_match_time.c' object='libarchive/test/libarchive_test-test_archive_match_time.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_match_time.obj `if test -f 'libarchive/test/test_archive_match_time.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_match_time.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_match_time.c'; fi` + +libarchive/test/libarchive_test-test_archive_pathmatch.o: libarchive/test/test_archive_pathmatch.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_pathmatch.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_pathmatch.Tpo -c -o libarchive/test/libarchive_test-test_archive_pathmatch.o `test -f 'libarchive/test/test_archive_pathmatch.c' || echo '$(srcdir)/'`libarchive/test/test_archive_pathmatch.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_pathmatch.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_pathmatch.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_pathmatch.c' object='libarchive/test/libarchive_test-test_archive_pathmatch.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_pathmatch.o `test -f 'libarchive/test/test_archive_pathmatch.c' || echo '$(srcdir)/'`libarchive/test/test_archive_pathmatch.c + +libarchive/test/libarchive_test-test_archive_pathmatch.obj: libarchive/test/test_archive_pathmatch.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_pathmatch.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_pathmatch.Tpo -c -o libarchive/test/libarchive_test-test_archive_pathmatch.obj `if test -f 'libarchive/test/test_archive_pathmatch.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_pathmatch.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_pathmatch.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_pathmatch.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_pathmatch.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_pathmatch.c' object='libarchive/test/libarchive_test-test_archive_pathmatch.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_pathmatch.obj `if test -f 'libarchive/test/test_archive_pathmatch.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_pathmatch.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_pathmatch.c'; fi` + +libarchive/test/libarchive_test-test_archive_read_add_passphrase.o: libarchive/test/test_archive_read_add_passphrase.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_read_add_passphrase.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_add_passphrase.Tpo -c -o libarchive/test/libarchive_test-test_archive_read_add_passphrase.o `test -f 'libarchive/test/test_archive_read_add_passphrase.c' || echo '$(srcdir)/'`libarchive/test/test_archive_read_add_passphrase.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_add_passphrase.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_add_passphrase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_read_add_passphrase.c' object='libarchive/test/libarchive_test-test_archive_read_add_passphrase.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_read_add_passphrase.o `test -f 'libarchive/test/test_archive_read_add_passphrase.c' || echo '$(srcdir)/'`libarchive/test/test_archive_read_add_passphrase.c + +libarchive/test/libarchive_test-test_archive_read_add_passphrase.obj: libarchive/test/test_archive_read_add_passphrase.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_read_add_passphrase.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_add_passphrase.Tpo -c -o libarchive/test/libarchive_test-test_archive_read_add_passphrase.obj `if test -f 'libarchive/test/test_archive_read_add_passphrase.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_read_add_passphrase.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_read_add_passphrase.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_add_passphrase.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_add_passphrase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_read_add_passphrase.c' object='libarchive/test/libarchive_test-test_archive_read_add_passphrase.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_read_add_passphrase.obj `if test -f 'libarchive/test/test_archive_read_add_passphrase.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_read_add_passphrase.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_read_add_passphrase.c'; fi` + +libarchive/test/libarchive_test-test_archive_read_close_twice.o: libarchive/test/test_archive_read_close_twice.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_read_close_twice.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_close_twice.Tpo -c -o libarchive/test/libarchive_test-test_archive_read_close_twice.o `test -f 'libarchive/test/test_archive_read_close_twice.c' || echo '$(srcdir)/'`libarchive/test/test_archive_read_close_twice.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_close_twice.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_close_twice.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_read_close_twice.c' object='libarchive/test/libarchive_test-test_archive_read_close_twice.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_read_close_twice.o `test -f 'libarchive/test/test_archive_read_close_twice.c' || echo '$(srcdir)/'`libarchive/test/test_archive_read_close_twice.c + +libarchive/test/libarchive_test-test_archive_read_close_twice.obj: libarchive/test/test_archive_read_close_twice.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_read_close_twice.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_close_twice.Tpo -c -o libarchive/test/libarchive_test-test_archive_read_close_twice.obj `if test -f 'libarchive/test/test_archive_read_close_twice.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_read_close_twice.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_read_close_twice.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_close_twice.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_close_twice.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_read_close_twice.c' object='libarchive/test/libarchive_test-test_archive_read_close_twice.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_read_close_twice.obj `if test -f 'libarchive/test/test_archive_read_close_twice.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_read_close_twice.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_read_close_twice.c'; fi` + +libarchive/test/libarchive_test-test_archive_read_close_twice_open_fd.o: libarchive/test/test_archive_read_close_twice_open_fd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_read_close_twice_open_fd.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_close_twice_open_fd.Tpo -c -o libarchive/test/libarchive_test-test_archive_read_close_twice_open_fd.o `test -f 'libarchive/test/test_archive_read_close_twice_open_fd.c' || echo '$(srcdir)/'`libarchive/test/test_archive_read_close_twice_open_fd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_close_twice_open_fd.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_close_twice_open_fd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_read_close_twice_open_fd.c' object='libarchive/test/libarchive_test-test_archive_read_close_twice_open_fd.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_read_close_twice_open_fd.o `test -f 'libarchive/test/test_archive_read_close_twice_open_fd.c' || echo '$(srcdir)/'`libarchive/test/test_archive_read_close_twice_open_fd.c + +libarchive/test/libarchive_test-test_archive_read_close_twice_open_fd.obj: libarchive/test/test_archive_read_close_twice_open_fd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_read_close_twice_open_fd.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_close_twice_open_fd.Tpo -c -o libarchive/test/libarchive_test-test_archive_read_close_twice_open_fd.obj `if test -f 'libarchive/test/test_archive_read_close_twice_open_fd.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_read_close_twice_open_fd.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_read_close_twice_open_fd.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_close_twice_open_fd.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_close_twice_open_fd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_read_close_twice_open_fd.c' object='libarchive/test/libarchive_test-test_archive_read_close_twice_open_fd.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_read_close_twice_open_fd.obj `if test -f 'libarchive/test/test_archive_read_close_twice_open_fd.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_read_close_twice_open_fd.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_read_close_twice_open_fd.c'; fi` + +libarchive/test/libarchive_test-test_archive_read_close_twice_open_filename.o: libarchive/test/test_archive_read_close_twice_open_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_read_close_twice_open_filename.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_close_twice_open_filename.Tpo -c -o libarchive/test/libarchive_test-test_archive_read_close_twice_open_filename.o `test -f 'libarchive/test/test_archive_read_close_twice_open_filename.c' || echo '$(srcdir)/'`libarchive/test/test_archive_read_close_twice_open_filename.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_close_twice_open_filename.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_close_twice_open_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_read_close_twice_open_filename.c' object='libarchive/test/libarchive_test-test_archive_read_close_twice_open_filename.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_read_close_twice_open_filename.o `test -f 'libarchive/test/test_archive_read_close_twice_open_filename.c' || echo '$(srcdir)/'`libarchive/test/test_archive_read_close_twice_open_filename.c + +libarchive/test/libarchive_test-test_archive_read_close_twice_open_filename.obj: libarchive/test/test_archive_read_close_twice_open_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_read_close_twice_open_filename.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_close_twice_open_filename.Tpo -c -o libarchive/test/libarchive_test-test_archive_read_close_twice_open_filename.obj `if test -f 'libarchive/test/test_archive_read_close_twice_open_filename.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_read_close_twice_open_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_read_close_twice_open_filename.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_close_twice_open_filename.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_close_twice_open_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_read_close_twice_open_filename.c' object='libarchive/test/libarchive_test-test_archive_read_close_twice_open_filename.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_read_close_twice_open_filename.obj `if test -f 'libarchive/test/test_archive_read_close_twice_open_filename.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_read_close_twice_open_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_read_close_twice_open_filename.c'; fi` + +libarchive/test/libarchive_test-test_archive_read_multiple_data_objects.o: libarchive/test/test_archive_read_multiple_data_objects.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_read_multiple_data_objects.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_multiple_data_objects.Tpo -c -o libarchive/test/libarchive_test-test_archive_read_multiple_data_objects.o `test -f 'libarchive/test/test_archive_read_multiple_data_objects.c' || echo '$(srcdir)/'`libarchive/test/test_archive_read_multiple_data_objects.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_multiple_data_objects.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_multiple_data_objects.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_read_multiple_data_objects.c' object='libarchive/test/libarchive_test-test_archive_read_multiple_data_objects.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_read_multiple_data_objects.o `test -f 'libarchive/test/test_archive_read_multiple_data_objects.c' || echo '$(srcdir)/'`libarchive/test/test_archive_read_multiple_data_objects.c + +libarchive/test/libarchive_test-test_archive_read_multiple_data_objects.obj: libarchive/test/test_archive_read_multiple_data_objects.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_read_multiple_data_objects.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_multiple_data_objects.Tpo -c -o libarchive/test/libarchive_test-test_archive_read_multiple_data_objects.obj `if test -f 'libarchive/test/test_archive_read_multiple_data_objects.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_read_multiple_data_objects.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_read_multiple_data_objects.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_multiple_data_objects.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_multiple_data_objects.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_read_multiple_data_objects.c' object='libarchive/test/libarchive_test-test_archive_read_multiple_data_objects.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_read_multiple_data_objects.obj `if test -f 'libarchive/test/test_archive_read_multiple_data_objects.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_read_multiple_data_objects.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_read_multiple_data_objects.c'; fi` + +libarchive/test/libarchive_test-test_archive_read_next_header_empty.o: libarchive/test/test_archive_read_next_header_empty.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_read_next_header_empty.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_next_header_empty.Tpo -c -o libarchive/test/libarchive_test-test_archive_read_next_header_empty.o `test -f 'libarchive/test/test_archive_read_next_header_empty.c' || echo '$(srcdir)/'`libarchive/test/test_archive_read_next_header_empty.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_next_header_empty.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_next_header_empty.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_read_next_header_empty.c' object='libarchive/test/libarchive_test-test_archive_read_next_header_empty.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_read_next_header_empty.o `test -f 'libarchive/test/test_archive_read_next_header_empty.c' || echo '$(srcdir)/'`libarchive/test/test_archive_read_next_header_empty.c + +libarchive/test/libarchive_test-test_archive_read_next_header_empty.obj: libarchive/test/test_archive_read_next_header_empty.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_read_next_header_empty.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_next_header_empty.Tpo -c -o libarchive/test/libarchive_test-test_archive_read_next_header_empty.obj `if test -f 'libarchive/test/test_archive_read_next_header_empty.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_read_next_header_empty.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_read_next_header_empty.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_next_header_empty.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_next_header_empty.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_read_next_header_empty.c' object='libarchive/test/libarchive_test-test_archive_read_next_header_empty.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_read_next_header_empty.obj `if test -f 'libarchive/test/test_archive_read_next_header_empty.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_read_next_header_empty.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_read_next_header_empty.c'; fi` + +libarchive/test/libarchive_test-test_archive_read_next_header_raw.o: libarchive/test/test_archive_read_next_header_raw.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_read_next_header_raw.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_next_header_raw.Tpo -c -o libarchive/test/libarchive_test-test_archive_read_next_header_raw.o `test -f 'libarchive/test/test_archive_read_next_header_raw.c' || echo '$(srcdir)/'`libarchive/test/test_archive_read_next_header_raw.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_next_header_raw.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_next_header_raw.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_read_next_header_raw.c' object='libarchive/test/libarchive_test-test_archive_read_next_header_raw.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_read_next_header_raw.o `test -f 'libarchive/test/test_archive_read_next_header_raw.c' || echo '$(srcdir)/'`libarchive/test/test_archive_read_next_header_raw.c + +libarchive/test/libarchive_test-test_archive_read_next_header_raw.obj: libarchive/test/test_archive_read_next_header_raw.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_read_next_header_raw.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_next_header_raw.Tpo -c -o libarchive/test/libarchive_test-test_archive_read_next_header_raw.obj `if test -f 'libarchive/test/test_archive_read_next_header_raw.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_read_next_header_raw.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_read_next_header_raw.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_next_header_raw.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_next_header_raw.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_read_next_header_raw.c' object='libarchive/test/libarchive_test-test_archive_read_next_header_raw.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_read_next_header_raw.obj `if test -f 'libarchive/test/test_archive_read_next_header_raw.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_read_next_header_raw.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_read_next_header_raw.c'; fi` + +libarchive/test/libarchive_test-test_archive_read_open2.o: libarchive/test/test_archive_read_open2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_read_open2.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_open2.Tpo -c -o libarchive/test/libarchive_test-test_archive_read_open2.o `test -f 'libarchive/test/test_archive_read_open2.c' || echo '$(srcdir)/'`libarchive/test/test_archive_read_open2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_open2.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_open2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_read_open2.c' object='libarchive/test/libarchive_test-test_archive_read_open2.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_read_open2.o `test -f 'libarchive/test/test_archive_read_open2.c' || echo '$(srcdir)/'`libarchive/test/test_archive_read_open2.c + +libarchive/test/libarchive_test-test_archive_read_open2.obj: libarchive/test/test_archive_read_open2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_read_open2.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_open2.Tpo -c -o libarchive/test/libarchive_test-test_archive_read_open2.obj `if test -f 'libarchive/test/test_archive_read_open2.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_read_open2.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_read_open2.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_open2.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_open2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_read_open2.c' object='libarchive/test/libarchive_test-test_archive_read_open2.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_read_open2.obj `if test -f 'libarchive/test/test_archive_read_open2.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_read_open2.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_read_open2.c'; fi` + +libarchive/test/libarchive_test-test_archive_read_set_filter_option.o: libarchive/test/test_archive_read_set_filter_option.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_read_set_filter_option.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_filter_option.Tpo -c -o libarchive/test/libarchive_test-test_archive_read_set_filter_option.o `test -f 'libarchive/test/test_archive_read_set_filter_option.c' || echo '$(srcdir)/'`libarchive/test/test_archive_read_set_filter_option.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_filter_option.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_filter_option.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_read_set_filter_option.c' object='libarchive/test/libarchive_test-test_archive_read_set_filter_option.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_read_set_filter_option.o `test -f 'libarchive/test/test_archive_read_set_filter_option.c' || echo '$(srcdir)/'`libarchive/test/test_archive_read_set_filter_option.c + +libarchive/test/libarchive_test-test_archive_read_set_filter_option.obj: libarchive/test/test_archive_read_set_filter_option.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_read_set_filter_option.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_filter_option.Tpo -c -o libarchive/test/libarchive_test-test_archive_read_set_filter_option.obj `if test -f 'libarchive/test/test_archive_read_set_filter_option.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_read_set_filter_option.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_read_set_filter_option.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_filter_option.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_filter_option.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_read_set_filter_option.c' object='libarchive/test/libarchive_test-test_archive_read_set_filter_option.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_read_set_filter_option.obj `if test -f 'libarchive/test/test_archive_read_set_filter_option.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_read_set_filter_option.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_read_set_filter_option.c'; fi` + +libarchive/test/libarchive_test-test_archive_read_set_format_option.o: libarchive/test/test_archive_read_set_format_option.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_read_set_format_option.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_format_option.Tpo -c -o libarchive/test/libarchive_test-test_archive_read_set_format_option.o `test -f 'libarchive/test/test_archive_read_set_format_option.c' || echo '$(srcdir)/'`libarchive/test/test_archive_read_set_format_option.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_format_option.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_format_option.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_read_set_format_option.c' object='libarchive/test/libarchive_test-test_archive_read_set_format_option.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_read_set_format_option.o `test -f 'libarchive/test/test_archive_read_set_format_option.c' || echo '$(srcdir)/'`libarchive/test/test_archive_read_set_format_option.c + +libarchive/test/libarchive_test-test_archive_read_set_format_option.obj: libarchive/test/test_archive_read_set_format_option.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_read_set_format_option.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_format_option.Tpo -c -o libarchive/test/libarchive_test-test_archive_read_set_format_option.obj `if test -f 'libarchive/test/test_archive_read_set_format_option.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_read_set_format_option.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_read_set_format_option.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_format_option.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_format_option.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_read_set_format_option.c' object='libarchive/test/libarchive_test-test_archive_read_set_format_option.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_read_set_format_option.obj `if test -f 'libarchive/test/test_archive_read_set_format_option.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_read_set_format_option.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_read_set_format_option.c'; fi` + +libarchive/test/libarchive_test-test_archive_read_set_option.o: libarchive/test/test_archive_read_set_option.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_read_set_option.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_option.Tpo -c -o libarchive/test/libarchive_test-test_archive_read_set_option.o `test -f 'libarchive/test/test_archive_read_set_option.c' || echo '$(srcdir)/'`libarchive/test/test_archive_read_set_option.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_option.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_option.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_read_set_option.c' object='libarchive/test/libarchive_test-test_archive_read_set_option.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_read_set_option.o `test -f 'libarchive/test/test_archive_read_set_option.c' || echo '$(srcdir)/'`libarchive/test/test_archive_read_set_option.c + +libarchive/test/libarchive_test-test_archive_read_set_option.obj: libarchive/test/test_archive_read_set_option.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_read_set_option.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_option.Tpo -c -o libarchive/test/libarchive_test-test_archive_read_set_option.obj `if test -f 'libarchive/test/test_archive_read_set_option.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_read_set_option.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_read_set_option.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_option.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_option.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_read_set_option.c' object='libarchive/test/libarchive_test-test_archive_read_set_option.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_read_set_option.obj `if test -f 'libarchive/test/test_archive_read_set_option.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_read_set_option.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_read_set_option.c'; fi` + +libarchive/test/libarchive_test-test_archive_read_set_options.o: libarchive/test/test_archive_read_set_options.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_read_set_options.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_options.Tpo -c -o libarchive/test/libarchive_test-test_archive_read_set_options.o `test -f 'libarchive/test/test_archive_read_set_options.c' || echo '$(srcdir)/'`libarchive/test/test_archive_read_set_options.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_options.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_options.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_read_set_options.c' object='libarchive/test/libarchive_test-test_archive_read_set_options.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_read_set_options.o `test -f 'libarchive/test/test_archive_read_set_options.c' || echo '$(srcdir)/'`libarchive/test/test_archive_read_set_options.c + +libarchive/test/libarchive_test-test_archive_read_set_options.obj: libarchive/test/test_archive_read_set_options.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_read_set_options.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_options.Tpo -c -o libarchive/test/libarchive_test-test_archive_read_set_options.obj `if test -f 'libarchive/test/test_archive_read_set_options.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_read_set_options.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_read_set_options.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_options.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_set_options.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_read_set_options.c' object='libarchive/test/libarchive_test-test_archive_read_set_options.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_read_set_options.obj `if test -f 'libarchive/test/test_archive_read_set_options.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_read_set_options.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_read_set_options.c'; fi` + +libarchive/test/libarchive_test-test_archive_read_support.o: libarchive/test/test_archive_read_support.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_read_support.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_support.Tpo -c -o libarchive/test/libarchive_test-test_archive_read_support.o `test -f 'libarchive/test/test_archive_read_support.c' || echo '$(srcdir)/'`libarchive/test/test_archive_read_support.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_support.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_support.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_read_support.c' object='libarchive/test/libarchive_test-test_archive_read_support.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_read_support.o `test -f 'libarchive/test/test_archive_read_support.c' || echo '$(srcdir)/'`libarchive/test/test_archive_read_support.c + +libarchive/test/libarchive_test-test_archive_read_support.obj: libarchive/test/test_archive_read_support.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_read_support.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_support.Tpo -c -o libarchive/test/libarchive_test-test_archive_read_support.obj `if test -f 'libarchive/test/test_archive_read_support.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_read_support.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_read_support.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_support.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_read_support.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_read_support.c' object='libarchive/test/libarchive_test-test_archive_read_support.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_read_support.obj `if test -f 'libarchive/test/test_archive_read_support.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_read_support.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_read_support.c'; fi` + +libarchive/test/libarchive_test-test_archive_set_error.o: libarchive/test/test_archive_set_error.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_set_error.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_set_error.Tpo -c -o libarchive/test/libarchive_test-test_archive_set_error.o `test -f 'libarchive/test/test_archive_set_error.c' || echo '$(srcdir)/'`libarchive/test/test_archive_set_error.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_set_error.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_set_error.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_set_error.c' object='libarchive/test/libarchive_test-test_archive_set_error.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_set_error.o `test -f 'libarchive/test/test_archive_set_error.c' || echo '$(srcdir)/'`libarchive/test/test_archive_set_error.c + +libarchive/test/libarchive_test-test_archive_set_error.obj: libarchive/test/test_archive_set_error.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_set_error.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_set_error.Tpo -c -o libarchive/test/libarchive_test-test_archive_set_error.obj `if test -f 'libarchive/test/test_archive_set_error.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_set_error.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_set_error.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_set_error.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_set_error.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_set_error.c' object='libarchive/test/libarchive_test-test_archive_set_error.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_set_error.obj `if test -f 'libarchive/test/test_archive_set_error.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_set_error.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_set_error.c'; fi` + +libarchive/test/libarchive_test-test_archive_string.o: libarchive/test/test_archive_string.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_string.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_string.Tpo -c -o libarchive/test/libarchive_test-test_archive_string.o `test -f 'libarchive/test/test_archive_string.c' || echo '$(srcdir)/'`libarchive/test/test_archive_string.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_string.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_string.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_string.c' object='libarchive/test/libarchive_test-test_archive_string.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_string.o `test -f 'libarchive/test/test_archive_string.c' || echo '$(srcdir)/'`libarchive/test/test_archive_string.c + +libarchive/test/libarchive_test-test_archive_string.obj: libarchive/test/test_archive_string.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_string.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_string.Tpo -c -o libarchive/test/libarchive_test-test_archive_string.obj `if test -f 'libarchive/test/test_archive_string.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_string.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_string.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_string.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_string.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_string.c' object='libarchive/test/libarchive_test-test_archive_string.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_string.obj `if test -f 'libarchive/test/test_archive_string.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_string.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_string.c'; fi` + +libarchive/test/libarchive_test-test_archive_string_conversion.o: libarchive/test/test_archive_string_conversion.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_string_conversion.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_string_conversion.Tpo -c -o libarchive/test/libarchive_test-test_archive_string_conversion.o `test -f 'libarchive/test/test_archive_string_conversion.c' || echo '$(srcdir)/'`libarchive/test/test_archive_string_conversion.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_string_conversion.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_string_conversion.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_string_conversion.c' object='libarchive/test/libarchive_test-test_archive_string_conversion.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_string_conversion.o `test -f 'libarchive/test/test_archive_string_conversion.c' || echo '$(srcdir)/'`libarchive/test/test_archive_string_conversion.c + +libarchive/test/libarchive_test-test_archive_string_conversion.obj: libarchive/test/test_archive_string_conversion.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_string_conversion.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_string_conversion.Tpo -c -o libarchive/test/libarchive_test-test_archive_string_conversion.obj `if test -f 'libarchive/test/test_archive_string_conversion.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_string_conversion.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_string_conversion.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_string_conversion.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_string_conversion.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_string_conversion.c' object='libarchive/test/libarchive_test-test_archive_string_conversion.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_string_conversion.obj `if test -f 'libarchive/test/test_archive_string_conversion.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_string_conversion.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_string_conversion.c'; fi` + +libarchive/test/libarchive_test-test_archive_write_add_filter_by_name.o: libarchive/test/test_archive_write_add_filter_by_name.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_write_add_filter_by_name.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_add_filter_by_name.Tpo -c -o libarchive/test/libarchive_test-test_archive_write_add_filter_by_name.o `test -f 'libarchive/test/test_archive_write_add_filter_by_name.c' || echo '$(srcdir)/'`libarchive/test/test_archive_write_add_filter_by_name.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_add_filter_by_name.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_add_filter_by_name.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_write_add_filter_by_name.c' object='libarchive/test/libarchive_test-test_archive_write_add_filter_by_name.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_write_add_filter_by_name.o `test -f 'libarchive/test/test_archive_write_add_filter_by_name.c' || echo '$(srcdir)/'`libarchive/test/test_archive_write_add_filter_by_name.c + +libarchive/test/libarchive_test-test_archive_write_add_filter_by_name.obj: libarchive/test/test_archive_write_add_filter_by_name.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_write_add_filter_by_name.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_add_filter_by_name.Tpo -c -o libarchive/test/libarchive_test-test_archive_write_add_filter_by_name.obj `if test -f 'libarchive/test/test_archive_write_add_filter_by_name.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_write_add_filter_by_name.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_write_add_filter_by_name.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_add_filter_by_name.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_add_filter_by_name.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_write_add_filter_by_name.c' object='libarchive/test/libarchive_test-test_archive_write_add_filter_by_name.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_write_add_filter_by_name.obj `if test -f 'libarchive/test/test_archive_write_add_filter_by_name.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_write_add_filter_by_name.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_write_add_filter_by_name.c'; fi` + +libarchive/test/libarchive_test-test_archive_write_set_filter_option.o: libarchive/test/test_archive_write_set_filter_option.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_write_set_filter_option.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_filter_option.Tpo -c -o libarchive/test/libarchive_test-test_archive_write_set_filter_option.o `test -f 'libarchive/test/test_archive_write_set_filter_option.c' || echo '$(srcdir)/'`libarchive/test/test_archive_write_set_filter_option.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_filter_option.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_filter_option.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_write_set_filter_option.c' object='libarchive/test/libarchive_test-test_archive_write_set_filter_option.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_write_set_filter_option.o `test -f 'libarchive/test/test_archive_write_set_filter_option.c' || echo '$(srcdir)/'`libarchive/test/test_archive_write_set_filter_option.c + +libarchive/test/libarchive_test-test_archive_write_set_filter_option.obj: libarchive/test/test_archive_write_set_filter_option.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_write_set_filter_option.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_filter_option.Tpo -c -o libarchive/test/libarchive_test-test_archive_write_set_filter_option.obj `if test -f 'libarchive/test/test_archive_write_set_filter_option.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_write_set_filter_option.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_write_set_filter_option.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_filter_option.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_filter_option.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_write_set_filter_option.c' object='libarchive/test/libarchive_test-test_archive_write_set_filter_option.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_write_set_filter_option.obj `if test -f 'libarchive/test/test_archive_write_set_filter_option.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_write_set_filter_option.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_write_set_filter_option.c'; fi` + +libarchive/test/libarchive_test-test_archive_write_set_format_by_name.o: libarchive/test/test_archive_write_set_format_by_name.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_write_set_format_by_name.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_format_by_name.Tpo -c -o libarchive/test/libarchive_test-test_archive_write_set_format_by_name.o `test -f 'libarchive/test/test_archive_write_set_format_by_name.c' || echo '$(srcdir)/'`libarchive/test/test_archive_write_set_format_by_name.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_format_by_name.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_format_by_name.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_write_set_format_by_name.c' object='libarchive/test/libarchive_test-test_archive_write_set_format_by_name.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_write_set_format_by_name.o `test -f 'libarchive/test/test_archive_write_set_format_by_name.c' || echo '$(srcdir)/'`libarchive/test/test_archive_write_set_format_by_name.c + +libarchive/test/libarchive_test-test_archive_write_set_format_by_name.obj: libarchive/test/test_archive_write_set_format_by_name.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_write_set_format_by_name.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_format_by_name.Tpo -c -o libarchive/test/libarchive_test-test_archive_write_set_format_by_name.obj `if test -f 'libarchive/test/test_archive_write_set_format_by_name.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_write_set_format_by_name.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_write_set_format_by_name.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_format_by_name.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_format_by_name.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_write_set_format_by_name.c' object='libarchive/test/libarchive_test-test_archive_write_set_format_by_name.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_write_set_format_by_name.obj `if test -f 'libarchive/test/test_archive_write_set_format_by_name.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_write_set_format_by_name.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_write_set_format_by_name.c'; fi` + +libarchive/test/libarchive_test-test_archive_write_set_format_filter_by_ext.o: libarchive/test/test_archive_write_set_format_filter_by_ext.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_write_set_format_filter_by_ext.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_format_filter_by_ext.Tpo -c -o libarchive/test/libarchive_test-test_archive_write_set_format_filter_by_ext.o `test -f 'libarchive/test/test_archive_write_set_format_filter_by_ext.c' || echo '$(srcdir)/'`libarchive/test/test_archive_write_set_format_filter_by_ext.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_format_filter_by_ext.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_format_filter_by_ext.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_write_set_format_filter_by_ext.c' object='libarchive/test/libarchive_test-test_archive_write_set_format_filter_by_ext.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_write_set_format_filter_by_ext.o `test -f 'libarchive/test/test_archive_write_set_format_filter_by_ext.c' || echo '$(srcdir)/'`libarchive/test/test_archive_write_set_format_filter_by_ext.c + +libarchive/test/libarchive_test-test_archive_write_set_format_filter_by_ext.obj: libarchive/test/test_archive_write_set_format_filter_by_ext.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_write_set_format_filter_by_ext.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_format_filter_by_ext.Tpo -c -o libarchive/test/libarchive_test-test_archive_write_set_format_filter_by_ext.obj `if test -f 'libarchive/test/test_archive_write_set_format_filter_by_ext.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_write_set_format_filter_by_ext.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_write_set_format_filter_by_ext.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_format_filter_by_ext.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_format_filter_by_ext.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_write_set_format_filter_by_ext.c' object='libarchive/test/libarchive_test-test_archive_write_set_format_filter_by_ext.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_write_set_format_filter_by_ext.obj `if test -f 'libarchive/test/test_archive_write_set_format_filter_by_ext.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_write_set_format_filter_by_ext.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_write_set_format_filter_by_ext.c'; fi` + +libarchive/test/libarchive_test-test_archive_write_set_format_option.o: libarchive/test/test_archive_write_set_format_option.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_write_set_format_option.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_format_option.Tpo -c -o libarchive/test/libarchive_test-test_archive_write_set_format_option.o `test -f 'libarchive/test/test_archive_write_set_format_option.c' || echo '$(srcdir)/'`libarchive/test/test_archive_write_set_format_option.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_format_option.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_format_option.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_write_set_format_option.c' object='libarchive/test/libarchive_test-test_archive_write_set_format_option.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_write_set_format_option.o `test -f 'libarchive/test/test_archive_write_set_format_option.c' || echo '$(srcdir)/'`libarchive/test/test_archive_write_set_format_option.c + +libarchive/test/libarchive_test-test_archive_write_set_format_option.obj: libarchive/test/test_archive_write_set_format_option.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_write_set_format_option.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_format_option.Tpo -c -o libarchive/test/libarchive_test-test_archive_write_set_format_option.obj `if test -f 'libarchive/test/test_archive_write_set_format_option.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_write_set_format_option.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_write_set_format_option.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_format_option.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_format_option.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_write_set_format_option.c' object='libarchive/test/libarchive_test-test_archive_write_set_format_option.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_write_set_format_option.obj `if test -f 'libarchive/test/test_archive_write_set_format_option.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_write_set_format_option.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_write_set_format_option.c'; fi` + +libarchive/test/libarchive_test-test_archive_write_set_option.o: libarchive/test/test_archive_write_set_option.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_write_set_option.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_option.Tpo -c -o libarchive/test/libarchive_test-test_archive_write_set_option.o `test -f 'libarchive/test/test_archive_write_set_option.c' || echo '$(srcdir)/'`libarchive/test/test_archive_write_set_option.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_option.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_option.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_write_set_option.c' object='libarchive/test/libarchive_test-test_archive_write_set_option.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_write_set_option.o `test -f 'libarchive/test/test_archive_write_set_option.c' || echo '$(srcdir)/'`libarchive/test/test_archive_write_set_option.c + +libarchive/test/libarchive_test-test_archive_write_set_option.obj: libarchive/test/test_archive_write_set_option.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_write_set_option.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_option.Tpo -c -o libarchive/test/libarchive_test-test_archive_write_set_option.obj `if test -f 'libarchive/test/test_archive_write_set_option.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_write_set_option.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_write_set_option.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_option.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_option.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_write_set_option.c' object='libarchive/test/libarchive_test-test_archive_write_set_option.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_write_set_option.obj `if test -f 'libarchive/test/test_archive_write_set_option.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_write_set_option.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_write_set_option.c'; fi` + +libarchive/test/libarchive_test-test_archive_write_set_options.o: libarchive/test/test_archive_write_set_options.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_write_set_options.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_options.Tpo -c -o libarchive/test/libarchive_test-test_archive_write_set_options.o `test -f 'libarchive/test/test_archive_write_set_options.c' || echo '$(srcdir)/'`libarchive/test/test_archive_write_set_options.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_options.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_options.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_write_set_options.c' object='libarchive/test/libarchive_test-test_archive_write_set_options.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_write_set_options.o `test -f 'libarchive/test/test_archive_write_set_options.c' || echo '$(srcdir)/'`libarchive/test/test_archive_write_set_options.c + +libarchive/test/libarchive_test-test_archive_write_set_options.obj: libarchive/test/test_archive_write_set_options.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_write_set_options.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_options.Tpo -c -o libarchive/test/libarchive_test-test_archive_write_set_options.obj `if test -f 'libarchive/test/test_archive_write_set_options.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_write_set_options.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_write_set_options.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_options.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_options.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_write_set_options.c' object='libarchive/test/libarchive_test-test_archive_write_set_options.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_write_set_options.obj `if test -f 'libarchive/test/test_archive_write_set_options.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_write_set_options.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_write_set_options.c'; fi` + +libarchive/test/libarchive_test-test_archive_write_set_passphrase.o: libarchive/test/test_archive_write_set_passphrase.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_write_set_passphrase.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_passphrase.Tpo -c -o libarchive/test/libarchive_test-test_archive_write_set_passphrase.o `test -f 'libarchive/test/test_archive_write_set_passphrase.c' || echo '$(srcdir)/'`libarchive/test/test_archive_write_set_passphrase.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_passphrase.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_passphrase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_write_set_passphrase.c' object='libarchive/test/libarchive_test-test_archive_write_set_passphrase.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_write_set_passphrase.o `test -f 'libarchive/test/test_archive_write_set_passphrase.c' || echo '$(srcdir)/'`libarchive/test/test_archive_write_set_passphrase.c + +libarchive/test/libarchive_test-test_archive_write_set_passphrase.obj: libarchive/test/test_archive_write_set_passphrase.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_archive_write_set_passphrase.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_passphrase.Tpo -c -o libarchive/test/libarchive_test-test_archive_write_set_passphrase.obj `if test -f 'libarchive/test/test_archive_write_set_passphrase.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_write_set_passphrase.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_write_set_passphrase.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_passphrase.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_archive_write_set_passphrase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_archive_write_set_passphrase.c' object='libarchive/test/libarchive_test-test_archive_write_set_passphrase.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_archive_write_set_passphrase.obj `if test -f 'libarchive/test/test_archive_write_set_passphrase.c'; then $(CYGPATH_W) 'libarchive/test/test_archive_write_set_passphrase.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_archive_write_set_passphrase.c'; fi` + +libarchive/test/libarchive_test-test_bad_fd.o: libarchive/test/test_bad_fd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_bad_fd.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_bad_fd.Tpo -c -o libarchive/test/libarchive_test-test_bad_fd.o `test -f 'libarchive/test/test_bad_fd.c' || echo '$(srcdir)/'`libarchive/test/test_bad_fd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_bad_fd.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_bad_fd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_bad_fd.c' object='libarchive/test/libarchive_test-test_bad_fd.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_bad_fd.o `test -f 'libarchive/test/test_bad_fd.c' || echo '$(srcdir)/'`libarchive/test/test_bad_fd.c + +libarchive/test/libarchive_test-test_bad_fd.obj: libarchive/test/test_bad_fd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_bad_fd.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_bad_fd.Tpo -c -o libarchive/test/libarchive_test-test_bad_fd.obj `if test -f 'libarchive/test/test_bad_fd.c'; then $(CYGPATH_W) 'libarchive/test/test_bad_fd.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_bad_fd.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_bad_fd.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_bad_fd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_bad_fd.c' object='libarchive/test/libarchive_test-test_bad_fd.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_bad_fd.obj `if test -f 'libarchive/test/test_bad_fd.c'; then $(CYGPATH_W) 'libarchive/test/test_bad_fd.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_bad_fd.c'; fi` + +libarchive/test/libarchive_test-test_compat_bzip2.o: libarchive/test/test_compat_bzip2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_bzip2.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_bzip2.Tpo -c -o libarchive/test/libarchive_test-test_compat_bzip2.o `test -f 'libarchive/test/test_compat_bzip2.c' || echo '$(srcdir)/'`libarchive/test/test_compat_bzip2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_bzip2.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_bzip2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_bzip2.c' object='libarchive/test/libarchive_test-test_compat_bzip2.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_bzip2.o `test -f 'libarchive/test/test_compat_bzip2.c' || echo '$(srcdir)/'`libarchive/test/test_compat_bzip2.c + +libarchive/test/libarchive_test-test_compat_bzip2.obj: libarchive/test/test_compat_bzip2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_bzip2.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_bzip2.Tpo -c -o libarchive/test/libarchive_test-test_compat_bzip2.obj `if test -f 'libarchive/test/test_compat_bzip2.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_bzip2.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_bzip2.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_bzip2.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_bzip2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_bzip2.c' object='libarchive/test/libarchive_test-test_compat_bzip2.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_bzip2.obj `if test -f 'libarchive/test/test_compat_bzip2.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_bzip2.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_bzip2.c'; fi` + +libarchive/test/libarchive_test-test_compat_cpio.o: libarchive/test/test_compat_cpio.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_cpio.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_cpio.Tpo -c -o libarchive/test/libarchive_test-test_compat_cpio.o `test -f 'libarchive/test/test_compat_cpio.c' || echo '$(srcdir)/'`libarchive/test/test_compat_cpio.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_cpio.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_cpio.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_cpio.c' object='libarchive/test/libarchive_test-test_compat_cpio.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_cpio.o `test -f 'libarchive/test/test_compat_cpio.c' || echo '$(srcdir)/'`libarchive/test/test_compat_cpio.c + +libarchive/test/libarchive_test-test_compat_cpio.obj: libarchive/test/test_compat_cpio.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_cpio.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_cpio.Tpo -c -o libarchive/test/libarchive_test-test_compat_cpio.obj `if test -f 'libarchive/test/test_compat_cpio.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_cpio.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_cpio.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_cpio.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_cpio.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_cpio.c' object='libarchive/test/libarchive_test-test_compat_cpio.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_cpio.obj `if test -f 'libarchive/test/test_compat_cpio.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_cpio.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_cpio.c'; fi` + +libarchive/test/libarchive_test-test_compat_gtar.o: libarchive/test/test_compat_gtar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_gtar.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_gtar.Tpo -c -o libarchive/test/libarchive_test-test_compat_gtar.o `test -f 'libarchive/test/test_compat_gtar.c' || echo '$(srcdir)/'`libarchive/test/test_compat_gtar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_gtar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_gtar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_gtar.c' object='libarchive/test/libarchive_test-test_compat_gtar.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_gtar.o `test -f 'libarchive/test/test_compat_gtar.c' || echo '$(srcdir)/'`libarchive/test/test_compat_gtar.c + +libarchive/test/libarchive_test-test_compat_gtar.obj: libarchive/test/test_compat_gtar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_gtar.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_gtar.Tpo -c -o libarchive/test/libarchive_test-test_compat_gtar.obj `if test -f 'libarchive/test/test_compat_gtar.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_gtar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_gtar.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_gtar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_gtar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_gtar.c' object='libarchive/test/libarchive_test-test_compat_gtar.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_gtar.obj `if test -f 'libarchive/test/test_compat_gtar.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_gtar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_gtar.c'; fi` + +libarchive/test/libarchive_test-test_compat_gzip.o: libarchive/test/test_compat_gzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_gzip.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_gzip.Tpo -c -o libarchive/test/libarchive_test-test_compat_gzip.o `test -f 'libarchive/test/test_compat_gzip.c' || echo '$(srcdir)/'`libarchive/test/test_compat_gzip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_gzip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_gzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_gzip.c' object='libarchive/test/libarchive_test-test_compat_gzip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_gzip.o `test -f 'libarchive/test/test_compat_gzip.c' || echo '$(srcdir)/'`libarchive/test/test_compat_gzip.c + +libarchive/test/libarchive_test-test_compat_gzip.obj: libarchive/test/test_compat_gzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_gzip.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_gzip.Tpo -c -o libarchive/test/libarchive_test-test_compat_gzip.obj `if test -f 'libarchive/test/test_compat_gzip.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_gzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_gzip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_gzip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_gzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_gzip.c' object='libarchive/test/libarchive_test-test_compat_gzip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_gzip.obj `if test -f 'libarchive/test/test_compat_gzip.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_gzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_gzip.c'; fi` + +libarchive/test/libarchive_test-test_compat_lz4.o: libarchive/test/test_compat_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_lz4.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lz4.Tpo -c -o libarchive/test/libarchive_test-test_compat_lz4.o `test -f 'libarchive/test/test_compat_lz4.c' || echo '$(srcdir)/'`libarchive/test/test_compat_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lz4.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lz4.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_lz4.c' object='libarchive/test/libarchive_test-test_compat_lz4.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_lz4.o `test -f 'libarchive/test/test_compat_lz4.c' || echo '$(srcdir)/'`libarchive/test/test_compat_lz4.c + +libarchive/test/libarchive_test-test_compat_lz4.obj: libarchive/test/test_compat_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_lz4.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lz4.Tpo -c -o libarchive/test/libarchive_test-test_compat_lz4.obj `if test -f 'libarchive/test/test_compat_lz4.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_lz4.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_lz4.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lz4.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lz4.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_lz4.c' object='libarchive/test/libarchive_test-test_compat_lz4.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_lz4.obj `if test -f 'libarchive/test/test_compat_lz4.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_lz4.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_lz4.c'; fi` + +libarchive/test/libarchive_test-test_compat_lzip.o: libarchive/test/test_compat_lzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_lzip.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lzip.Tpo -c -o libarchive/test/libarchive_test-test_compat_lzip.o `test -f 'libarchive/test/test_compat_lzip.c' || echo '$(srcdir)/'`libarchive/test/test_compat_lzip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lzip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_lzip.c' object='libarchive/test/libarchive_test-test_compat_lzip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_lzip.o `test -f 'libarchive/test/test_compat_lzip.c' || echo '$(srcdir)/'`libarchive/test/test_compat_lzip.c + +libarchive/test/libarchive_test-test_compat_lzip.obj: libarchive/test/test_compat_lzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_lzip.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lzip.Tpo -c -o libarchive/test/libarchive_test-test_compat_lzip.obj `if test -f 'libarchive/test/test_compat_lzip.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_lzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_lzip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lzip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_lzip.c' object='libarchive/test/libarchive_test-test_compat_lzip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_lzip.obj `if test -f 'libarchive/test/test_compat_lzip.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_lzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_lzip.c'; fi` + +libarchive/test/libarchive_test-test_compat_lzma.o: libarchive/test/test_compat_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_lzma.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lzma.Tpo -c -o libarchive/test/libarchive_test-test_compat_lzma.o `test -f 'libarchive/test/test_compat_lzma.c' || echo '$(srcdir)/'`libarchive/test/test_compat_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lzma.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lzma.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_lzma.c' object='libarchive/test/libarchive_test-test_compat_lzma.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_lzma.o `test -f 'libarchive/test/test_compat_lzma.c' || echo '$(srcdir)/'`libarchive/test/test_compat_lzma.c + +libarchive/test/libarchive_test-test_compat_lzma.obj: libarchive/test/test_compat_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_lzma.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lzma.Tpo -c -o libarchive/test/libarchive_test-test_compat_lzma.obj `if test -f 'libarchive/test/test_compat_lzma.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_lzma.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_lzma.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lzma.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lzma.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_lzma.c' object='libarchive/test/libarchive_test-test_compat_lzma.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_lzma.obj `if test -f 'libarchive/test/test_compat_lzma.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_lzma.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_lzma.c'; fi` + +libarchive/test/libarchive_test-test_compat_lzop.o: libarchive/test/test_compat_lzop.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_lzop.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lzop.Tpo -c -o libarchive/test/libarchive_test-test_compat_lzop.o `test -f 'libarchive/test/test_compat_lzop.c' || echo '$(srcdir)/'`libarchive/test/test_compat_lzop.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lzop.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lzop.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_lzop.c' object='libarchive/test/libarchive_test-test_compat_lzop.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_lzop.o `test -f 'libarchive/test/test_compat_lzop.c' || echo '$(srcdir)/'`libarchive/test/test_compat_lzop.c + +libarchive/test/libarchive_test-test_compat_lzop.obj: libarchive/test/test_compat_lzop.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_lzop.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lzop.Tpo -c -o libarchive/test/libarchive_test-test_compat_lzop.obj `if test -f 'libarchive/test/test_compat_lzop.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_lzop.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_lzop.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lzop.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_lzop.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_lzop.c' object='libarchive/test/libarchive_test-test_compat_lzop.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_lzop.obj `if test -f 'libarchive/test/test_compat_lzop.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_lzop.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_lzop.c'; fi` + +libarchive/test/libarchive_test-test_compat_mac.o: libarchive/test/test_compat_mac.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_mac.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_mac.Tpo -c -o libarchive/test/libarchive_test-test_compat_mac.o `test -f 'libarchive/test/test_compat_mac.c' || echo '$(srcdir)/'`libarchive/test/test_compat_mac.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_mac.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_mac.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_mac.c' object='libarchive/test/libarchive_test-test_compat_mac.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_mac.o `test -f 'libarchive/test/test_compat_mac.c' || echo '$(srcdir)/'`libarchive/test/test_compat_mac.c + +libarchive/test/libarchive_test-test_compat_mac.obj: libarchive/test/test_compat_mac.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_mac.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_mac.Tpo -c -o libarchive/test/libarchive_test-test_compat_mac.obj `if test -f 'libarchive/test/test_compat_mac.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_mac.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_mac.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_mac.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_mac.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_mac.c' object='libarchive/test/libarchive_test-test_compat_mac.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_mac.obj `if test -f 'libarchive/test/test_compat_mac.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_mac.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_mac.c'; fi` + +libarchive/test/libarchive_test-test_compat_perl_archive_tar.o: libarchive/test/test_compat_perl_archive_tar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_perl_archive_tar.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_perl_archive_tar.Tpo -c -o libarchive/test/libarchive_test-test_compat_perl_archive_tar.o `test -f 'libarchive/test/test_compat_perl_archive_tar.c' || echo '$(srcdir)/'`libarchive/test/test_compat_perl_archive_tar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_perl_archive_tar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_perl_archive_tar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_perl_archive_tar.c' object='libarchive/test/libarchive_test-test_compat_perl_archive_tar.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_perl_archive_tar.o `test -f 'libarchive/test/test_compat_perl_archive_tar.c' || echo '$(srcdir)/'`libarchive/test/test_compat_perl_archive_tar.c + +libarchive/test/libarchive_test-test_compat_perl_archive_tar.obj: libarchive/test/test_compat_perl_archive_tar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_perl_archive_tar.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_perl_archive_tar.Tpo -c -o libarchive/test/libarchive_test-test_compat_perl_archive_tar.obj `if test -f 'libarchive/test/test_compat_perl_archive_tar.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_perl_archive_tar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_perl_archive_tar.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_perl_archive_tar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_perl_archive_tar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_perl_archive_tar.c' object='libarchive/test/libarchive_test-test_compat_perl_archive_tar.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_perl_archive_tar.obj `if test -f 'libarchive/test/test_compat_perl_archive_tar.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_perl_archive_tar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_perl_archive_tar.c'; fi` + +libarchive/test/libarchive_test-test_compat_plexus_archiver_tar.o: libarchive/test/test_compat_plexus_archiver_tar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_plexus_archiver_tar.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_plexus_archiver_tar.Tpo -c -o libarchive/test/libarchive_test-test_compat_plexus_archiver_tar.o `test -f 'libarchive/test/test_compat_plexus_archiver_tar.c' || echo '$(srcdir)/'`libarchive/test/test_compat_plexus_archiver_tar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_plexus_archiver_tar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_plexus_archiver_tar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_plexus_archiver_tar.c' object='libarchive/test/libarchive_test-test_compat_plexus_archiver_tar.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_plexus_archiver_tar.o `test -f 'libarchive/test/test_compat_plexus_archiver_tar.c' || echo '$(srcdir)/'`libarchive/test/test_compat_plexus_archiver_tar.c + +libarchive/test/libarchive_test-test_compat_plexus_archiver_tar.obj: libarchive/test/test_compat_plexus_archiver_tar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_plexus_archiver_tar.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_plexus_archiver_tar.Tpo -c -o libarchive/test/libarchive_test-test_compat_plexus_archiver_tar.obj `if test -f 'libarchive/test/test_compat_plexus_archiver_tar.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_plexus_archiver_tar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_plexus_archiver_tar.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_plexus_archiver_tar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_plexus_archiver_tar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_plexus_archiver_tar.c' object='libarchive/test/libarchive_test-test_compat_plexus_archiver_tar.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_plexus_archiver_tar.obj `if test -f 'libarchive/test/test_compat_plexus_archiver_tar.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_plexus_archiver_tar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_plexus_archiver_tar.c'; fi` + +libarchive/test/libarchive_test-test_compat_solaris_tar_acl.o: libarchive/test/test_compat_solaris_tar_acl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_solaris_tar_acl.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_solaris_tar_acl.Tpo -c -o libarchive/test/libarchive_test-test_compat_solaris_tar_acl.o `test -f 'libarchive/test/test_compat_solaris_tar_acl.c' || echo '$(srcdir)/'`libarchive/test/test_compat_solaris_tar_acl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_solaris_tar_acl.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_solaris_tar_acl.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_solaris_tar_acl.c' object='libarchive/test/libarchive_test-test_compat_solaris_tar_acl.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_solaris_tar_acl.o `test -f 'libarchive/test/test_compat_solaris_tar_acl.c' || echo '$(srcdir)/'`libarchive/test/test_compat_solaris_tar_acl.c + +libarchive/test/libarchive_test-test_compat_solaris_tar_acl.obj: libarchive/test/test_compat_solaris_tar_acl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_solaris_tar_acl.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_solaris_tar_acl.Tpo -c -o libarchive/test/libarchive_test-test_compat_solaris_tar_acl.obj `if test -f 'libarchive/test/test_compat_solaris_tar_acl.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_solaris_tar_acl.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_solaris_tar_acl.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_solaris_tar_acl.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_solaris_tar_acl.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_solaris_tar_acl.c' object='libarchive/test/libarchive_test-test_compat_solaris_tar_acl.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_solaris_tar_acl.obj `if test -f 'libarchive/test/test_compat_solaris_tar_acl.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_solaris_tar_acl.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_solaris_tar_acl.c'; fi` + +libarchive/test/libarchive_test-test_compat_solaris_pax_sparse.o: libarchive/test/test_compat_solaris_pax_sparse.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_solaris_pax_sparse.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_solaris_pax_sparse.Tpo -c -o libarchive/test/libarchive_test-test_compat_solaris_pax_sparse.o `test -f 'libarchive/test/test_compat_solaris_pax_sparse.c' || echo '$(srcdir)/'`libarchive/test/test_compat_solaris_pax_sparse.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_solaris_pax_sparse.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_solaris_pax_sparse.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_solaris_pax_sparse.c' object='libarchive/test/libarchive_test-test_compat_solaris_pax_sparse.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_solaris_pax_sparse.o `test -f 'libarchive/test/test_compat_solaris_pax_sparse.c' || echo '$(srcdir)/'`libarchive/test/test_compat_solaris_pax_sparse.c + +libarchive/test/libarchive_test-test_compat_solaris_pax_sparse.obj: libarchive/test/test_compat_solaris_pax_sparse.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_solaris_pax_sparse.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_solaris_pax_sparse.Tpo -c -o libarchive/test/libarchive_test-test_compat_solaris_pax_sparse.obj `if test -f 'libarchive/test/test_compat_solaris_pax_sparse.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_solaris_pax_sparse.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_solaris_pax_sparse.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_solaris_pax_sparse.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_solaris_pax_sparse.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_solaris_pax_sparse.c' object='libarchive/test/libarchive_test-test_compat_solaris_pax_sparse.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_solaris_pax_sparse.obj `if test -f 'libarchive/test/test_compat_solaris_pax_sparse.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_solaris_pax_sparse.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_solaris_pax_sparse.c'; fi` + +libarchive/test/libarchive_test-test_compat_star_acl.o: libarchive/test/test_compat_star_acl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_star_acl.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_star_acl.Tpo -c -o libarchive/test/libarchive_test-test_compat_star_acl.o `test -f 'libarchive/test/test_compat_star_acl.c' || echo '$(srcdir)/'`libarchive/test/test_compat_star_acl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_star_acl.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_star_acl.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_star_acl.c' object='libarchive/test/libarchive_test-test_compat_star_acl.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_star_acl.o `test -f 'libarchive/test/test_compat_star_acl.c' || echo '$(srcdir)/'`libarchive/test/test_compat_star_acl.c + +libarchive/test/libarchive_test-test_compat_star_acl.obj: libarchive/test/test_compat_star_acl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_star_acl.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_star_acl.Tpo -c -o libarchive/test/libarchive_test-test_compat_star_acl.obj `if test -f 'libarchive/test/test_compat_star_acl.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_star_acl.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_star_acl.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_star_acl.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_star_acl.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_star_acl.c' object='libarchive/test/libarchive_test-test_compat_star_acl.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_star_acl.obj `if test -f 'libarchive/test/test_compat_star_acl.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_star_acl.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_star_acl.c'; fi` + +libarchive/test/libarchive_test-test_compat_tar_hardlink.o: libarchive/test/test_compat_tar_hardlink.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_tar_hardlink.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_tar_hardlink.Tpo -c -o libarchive/test/libarchive_test-test_compat_tar_hardlink.o `test -f 'libarchive/test/test_compat_tar_hardlink.c' || echo '$(srcdir)/'`libarchive/test/test_compat_tar_hardlink.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_tar_hardlink.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_tar_hardlink.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_tar_hardlink.c' object='libarchive/test/libarchive_test-test_compat_tar_hardlink.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_tar_hardlink.o `test -f 'libarchive/test/test_compat_tar_hardlink.c' || echo '$(srcdir)/'`libarchive/test/test_compat_tar_hardlink.c + +libarchive/test/libarchive_test-test_compat_tar_hardlink.obj: libarchive/test/test_compat_tar_hardlink.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_tar_hardlink.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_tar_hardlink.Tpo -c -o libarchive/test/libarchive_test-test_compat_tar_hardlink.obj `if test -f 'libarchive/test/test_compat_tar_hardlink.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_tar_hardlink.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_tar_hardlink.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_tar_hardlink.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_tar_hardlink.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_tar_hardlink.c' object='libarchive/test/libarchive_test-test_compat_tar_hardlink.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_tar_hardlink.obj `if test -f 'libarchive/test/test_compat_tar_hardlink.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_tar_hardlink.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_tar_hardlink.c'; fi` + +libarchive/test/libarchive_test-test_compat_uudecode.o: libarchive/test/test_compat_uudecode.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_uudecode.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_uudecode.Tpo -c -o libarchive/test/libarchive_test-test_compat_uudecode.o `test -f 'libarchive/test/test_compat_uudecode.c' || echo '$(srcdir)/'`libarchive/test/test_compat_uudecode.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_uudecode.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_uudecode.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_uudecode.c' object='libarchive/test/libarchive_test-test_compat_uudecode.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_uudecode.o `test -f 'libarchive/test/test_compat_uudecode.c' || echo '$(srcdir)/'`libarchive/test/test_compat_uudecode.c + +libarchive/test/libarchive_test-test_compat_uudecode.obj: libarchive/test/test_compat_uudecode.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_uudecode.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_uudecode.Tpo -c -o libarchive/test/libarchive_test-test_compat_uudecode.obj `if test -f 'libarchive/test/test_compat_uudecode.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_uudecode.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_uudecode.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_uudecode.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_uudecode.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_uudecode.c' object='libarchive/test/libarchive_test-test_compat_uudecode.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_uudecode.obj `if test -f 'libarchive/test/test_compat_uudecode.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_uudecode.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_uudecode.c'; fi` + +libarchive/test/libarchive_test-test_compat_uudecode_large.o: libarchive/test/test_compat_uudecode_large.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_uudecode_large.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_uudecode_large.Tpo -c -o libarchive/test/libarchive_test-test_compat_uudecode_large.o `test -f 'libarchive/test/test_compat_uudecode_large.c' || echo '$(srcdir)/'`libarchive/test/test_compat_uudecode_large.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_uudecode_large.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_uudecode_large.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_uudecode_large.c' object='libarchive/test/libarchive_test-test_compat_uudecode_large.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_uudecode_large.o `test -f 'libarchive/test/test_compat_uudecode_large.c' || echo '$(srcdir)/'`libarchive/test/test_compat_uudecode_large.c + +libarchive/test/libarchive_test-test_compat_uudecode_large.obj: libarchive/test/test_compat_uudecode_large.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_uudecode_large.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_uudecode_large.Tpo -c -o libarchive/test/libarchive_test-test_compat_uudecode_large.obj `if test -f 'libarchive/test/test_compat_uudecode_large.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_uudecode_large.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_uudecode_large.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_uudecode_large.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_uudecode_large.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_uudecode_large.c' object='libarchive/test/libarchive_test-test_compat_uudecode_large.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_uudecode_large.obj `if test -f 'libarchive/test/test_compat_uudecode_large.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_uudecode_large.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_uudecode_large.c'; fi` + +libarchive/test/libarchive_test-test_compat_xz.o: libarchive/test/test_compat_xz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_xz.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_xz.Tpo -c -o libarchive/test/libarchive_test-test_compat_xz.o `test -f 'libarchive/test/test_compat_xz.c' || echo '$(srcdir)/'`libarchive/test/test_compat_xz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_xz.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_xz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_xz.c' object='libarchive/test/libarchive_test-test_compat_xz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_xz.o `test -f 'libarchive/test/test_compat_xz.c' || echo '$(srcdir)/'`libarchive/test/test_compat_xz.c + +libarchive/test/libarchive_test-test_compat_xz.obj: libarchive/test/test_compat_xz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_xz.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_xz.Tpo -c -o libarchive/test/libarchive_test-test_compat_xz.obj `if test -f 'libarchive/test/test_compat_xz.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_xz.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_xz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_xz.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_xz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_xz.c' object='libarchive/test/libarchive_test-test_compat_xz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_xz.obj `if test -f 'libarchive/test/test_compat_xz.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_xz.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_xz.c'; fi` + +libarchive/test/libarchive_test-test_compat_zip.o: libarchive/test/test_compat_zip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_zip.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_zip.Tpo -c -o libarchive/test/libarchive_test-test_compat_zip.o `test -f 'libarchive/test/test_compat_zip.c' || echo '$(srcdir)/'`libarchive/test/test_compat_zip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_zip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_zip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_zip.c' object='libarchive/test/libarchive_test-test_compat_zip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_zip.o `test -f 'libarchive/test/test_compat_zip.c' || echo '$(srcdir)/'`libarchive/test/test_compat_zip.c + +libarchive/test/libarchive_test-test_compat_zip.obj: libarchive/test/test_compat_zip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_zip.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_zip.Tpo -c -o libarchive/test/libarchive_test-test_compat_zip.obj `if test -f 'libarchive/test/test_compat_zip.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_zip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_zip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_zip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_zip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_zip.c' object='libarchive/test/libarchive_test-test_compat_zip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_zip.obj `if test -f 'libarchive/test/test_compat_zip.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_zip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_zip.c'; fi` + +libarchive/test/libarchive_test-test_compat_zstd.o: libarchive/test/test_compat_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_zstd.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_zstd.Tpo -c -o libarchive/test/libarchive_test-test_compat_zstd.o `test -f 'libarchive/test/test_compat_zstd.c' || echo '$(srcdir)/'`libarchive/test/test_compat_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_zstd.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_zstd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_zstd.c' object='libarchive/test/libarchive_test-test_compat_zstd.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_zstd.o `test -f 'libarchive/test/test_compat_zstd.c' || echo '$(srcdir)/'`libarchive/test/test_compat_zstd.c + +libarchive/test/libarchive_test-test_compat_zstd.obj: libarchive/test/test_compat_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_compat_zstd.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_compat_zstd.Tpo -c -o libarchive/test/libarchive_test-test_compat_zstd.obj `if test -f 'libarchive/test/test_compat_zstd.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_zstd.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_zstd.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_compat_zstd.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_compat_zstd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_compat_zstd.c' object='libarchive/test/libarchive_test-test_compat_zstd.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_compat_zstd.obj `if test -f 'libarchive/test/test_compat_zstd.c'; then $(CYGPATH_W) 'libarchive/test/test_compat_zstd.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_compat_zstd.c'; fi` + +libarchive/test/libarchive_test-test_empty_write.o: libarchive/test/test_empty_write.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_empty_write.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_empty_write.Tpo -c -o libarchive/test/libarchive_test-test_empty_write.o `test -f 'libarchive/test/test_empty_write.c' || echo '$(srcdir)/'`libarchive/test/test_empty_write.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_empty_write.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_empty_write.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_empty_write.c' object='libarchive/test/libarchive_test-test_empty_write.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_empty_write.o `test -f 'libarchive/test/test_empty_write.c' || echo '$(srcdir)/'`libarchive/test/test_empty_write.c + +libarchive/test/libarchive_test-test_empty_write.obj: libarchive/test/test_empty_write.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_empty_write.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_empty_write.Tpo -c -o libarchive/test/libarchive_test-test_empty_write.obj `if test -f 'libarchive/test/test_empty_write.c'; then $(CYGPATH_W) 'libarchive/test/test_empty_write.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_empty_write.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_empty_write.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_empty_write.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_empty_write.c' object='libarchive/test/libarchive_test-test_empty_write.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_empty_write.obj `if test -f 'libarchive/test/test_empty_write.c'; then $(CYGPATH_W) 'libarchive/test/test_empty_write.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_empty_write.c'; fi` + +libarchive/test/libarchive_test-test_entry.o: libarchive/test/test_entry.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_entry.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_entry.Tpo -c -o libarchive/test/libarchive_test-test_entry.o `test -f 'libarchive/test/test_entry.c' || echo '$(srcdir)/'`libarchive/test/test_entry.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_entry.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_entry.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_entry.c' object='libarchive/test/libarchive_test-test_entry.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_entry.o `test -f 'libarchive/test/test_entry.c' || echo '$(srcdir)/'`libarchive/test/test_entry.c + +libarchive/test/libarchive_test-test_entry.obj: libarchive/test/test_entry.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_entry.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_entry.Tpo -c -o libarchive/test/libarchive_test-test_entry.obj `if test -f 'libarchive/test/test_entry.c'; then $(CYGPATH_W) 'libarchive/test/test_entry.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_entry.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_entry.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_entry.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_entry.c' object='libarchive/test/libarchive_test-test_entry.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_entry.obj `if test -f 'libarchive/test/test_entry.c'; then $(CYGPATH_W) 'libarchive/test/test_entry.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_entry.c'; fi` + +libarchive/test/libarchive_test-test_entry_strmode.o: libarchive/test/test_entry_strmode.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_entry_strmode.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_entry_strmode.Tpo -c -o libarchive/test/libarchive_test-test_entry_strmode.o `test -f 'libarchive/test/test_entry_strmode.c' || echo '$(srcdir)/'`libarchive/test/test_entry_strmode.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_entry_strmode.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_entry_strmode.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_entry_strmode.c' object='libarchive/test/libarchive_test-test_entry_strmode.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_entry_strmode.o `test -f 'libarchive/test/test_entry_strmode.c' || echo '$(srcdir)/'`libarchive/test/test_entry_strmode.c + +libarchive/test/libarchive_test-test_entry_strmode.obj: libarchive/test/test_entry_strmode.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_entry_strmode.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_entry_strmode.Tpo -c -o libarchive/test/libarchive_test-test_entry_strmode.obj `if test -f 'libarchive/test/test_entry_strmode.c'; then $(CYGPATH_W) 'libarchive/test/test_entry_strmode.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_entry_strmode.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_entry_strmode.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_entry_strmode.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_entry_strmode.c' object='libarchive/test/libarchive_test-test_entry_strmode.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_entry_strmode.obj `if test -f 'libarchive/test/test_entry_strmode.c'; then $(CYGPATH_W) 'libarchive/test/test_entry_strmode.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_entry_strmode.c'; fi` + +libarchive/test/libarchive_test-test_extattr_freebsd.o: libarchive/test/test_extattr_freebsd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_extattr_freebsd.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_extattr_freebsd.Tpo -c -o libarchive/test/libarchive_test-test_extattr_freebsd.o `test -f 'libarchive/test/test_extattr_freebsd.c' || echo '$(srcdir)/'`libarchive/test/test_extattr_freebsd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_extattr_freebsd.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_extattr_freebsd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_extattr_freebsd.c' object='libarchive/test/libarchive_test-test_extattr_freebsd.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_extattr_freebsd.o `test -f 'libarchive/test/test_extattr_freebsd.c' || echo '$(srcdir)/'`libarchive/test/test_extattr_freebsd.c + +libarchive/test/libarchive_test-test_extattr_freebsd.obj: libarchive/test/test_extattr_freebsd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_extattr_freebsd.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_extattr_freebsd.Tpo -c -o libarchive/test/libarchive_test-test_extattr_freebsd.obj `if test -f 'libarchive/test/test_extattr_freebsd.c'; then $(CYGPATH_W) 'libarchive/test/test_extattr_freebsd.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_extattr_freebsd.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_extattr_freebsd.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_extattr_freebsd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_extattr_freebsd.c' object='libarchive/test/libarchive_test-test_extattr_freebsd.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_extattr_freebsd.obj `if test -f 'libarchive/test/test_extattr_freebsd.c'; then $(CYGPATH_W) 'libarchive/test/test_extattr_freebsd.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_extattr_freebsd.c'; fi` + +libarchive/test/libarchive_test-test_filter_count.o: libarchive/test/test_filter_count.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_filter_count.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_filter_count.Tpo -c -o libarchive/test/libarchive_test-test_filter_count.o `test -f 'libarchive/test/test_filter_count.c' || echo '$(srcdir)/'`libarchive/test/test_filter_count.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_filter_count.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_filter_count.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_filter_count.c' object='libarchive/test/libarchive_test-test_filter_count.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_filter_count.o `test -f 'libarchive/test/test_filter_count.c' || echo '$(srcdir)/'`libarchive/test/test_filter_count.c + +libarchive/test/libarchive_test-test_filter_count.obj: libarchive/test/test_filter_count.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_filter_count.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_filter_count.Tpo -c -o libarchive/test/libarchive_test-test_filter_count.obj `if test -f 'libarchive/test/test_filter_count.c'; then $(CYGPATH_W) 'libarchive/test/test_filter_count.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_filter_count.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_filter_count.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_filter_count.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_filter_count.c' object='libarchive/test/libarchive_test-test_filter_count.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_filter_count.obj `if test -f 'libarchive/test/test_filter_count.c'; then $(CYGPATH_W) 'libarchive/test/test_filter_count.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_filter_count.c'; fi` + +libarchive/test/libarchive_test-test_fuzz.o: libarchive/test/test_fuzz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_fuzz.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_fuzz.Tpo -c -o libarchive/test/libarchive_test-test_fuzz.o `test -f 'libarchive/test/test_fuzz.c' || echo '$(srcdir)/'`libarchive/test/test_fuzz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_fuzz.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_fuzz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_fuzz.c' object='libarchive/test/libarchive_test-test_fuzz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_fuzz.o `test -f 'libarchive/test/test_fuzz.c' || echo '$(srcdir)/'`libarchive/test/test_fuzz.c + +libarchive/test/libarchive_test-test_fuzz.obj: libarchive/test/test_fuzz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_fuzz.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_fuzz.Tpo -c -o libarchive/test/libarchive_test-test_fuzz.obj `if test -f 'libarchive/test/test_fuzz.c'; then $(CYGPATH_W) 'libarchive/test/test_fuzz.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_fuzz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_fuzz.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_fuzz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_fuzz.c' object='libarchive/test/libarchive_test-test_fuzz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_fuzz.obj `if test -f 'libarchive/test/test_fuzz.c'; then $(CYGPATH_W) 'libarchive/test/test_fuzz.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_fuzz.c'; fi` + +libarchive/test/libarchive_test-test_gnutar_filename_encoding.o: libarchive/test/test_gnutar_filename_encoding.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_gnutar_filename_encoding.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_gnutar_filename_encoding.Tpo -c -o libarchive/test/libarchive_test-test_gnutar_filename_encoding.o `test -f 'libarchive/test/test_gnutar_filename_encoding.c' || echo '$(srcdir)/'`libarchive/test/test_gnutar_filename_encoding.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_gnutar_filename_encoding.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_gnutar_filename_encoding.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_gnutar_filename_encoding.c' object='libarchive/test/libarchive_test-test_gnutar_filename_encoding.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_gnutar_filename_encoding.o `test -f 'libarchive/test/test_gnutar_filename_encoding.c' || echo '$(srcdir)/'`libarchive/test/test_gnutar_filename_encoding.c + +libarchive/test/libarchive_test-test_gnutar_filename_encoding.obj: libarchive/test/test_gnutar_filename_encoding.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_gnutar_filename_encoding.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_gnutar_filename_encoding.Tpo -c -o libarchive/test/libarchive_test-test_gnutar_filename_encoding.obj `if test -f 'libarchive/test/test_gnutar_filename_encoding.c'; then $(CYGPATH_W) 'libarchive/test/test_gnutar_filename_encoding.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_gnutar_filename_encoding.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_gnutar_filename_encoding.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_gnutar_filename_encoding.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_gnutar_filename_encoding.c' object='libarchive/test/libarchive_test-test_gnutar_filename_encoding.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_gnutar_filename_encoding.obj `if test -f 'libarchive/test/test_gnutar_filename_encoding.c'; then $(CYGPATH_W) 'libarchive/test/test_gnutar_filename_encoding.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_gnutar_filename_encoding.c'; fi` + +libarchive/test/libarchive_test-test_link_resolver.o: libarchive/test/test_link_resolver.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_link_resolver.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_link_resolver.Tpo -c -o libarchive/test/libarchive_test-test_link_resolver.o `test -f 'libarchive/test/test_link_resolver.c' || echo '$(srcdir)/'`libarchive/test/test_link_resolver.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_link_resolver.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_link_resolver.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_link_resolver.c' object='libarchive/test/libarchive_test-test_link_resolver.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_link_resolver.o `test -f 'libarchive/test/test_link_resolver.c' || echo '$(srcdir)/'`libarchive/test/test_link_resolver.c + +libarchive/test/libarchive_test-test_link_resolver.obj: libarchive/test/test_link_resolver.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_link_resolver.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_link_resolver.Tpo -c -o libarchive/test/libarchive_test-test_link_resolver.obj `if test -f 'libarchive/test/test_link_resolver.c'; then $(CYGPATH_W) 'libarchive/test/test_link_resolver.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_link_resolver.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_link_resolver.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_link_resolver.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_link_resolver.c' object='libarchive/test/libarchive_test-test_link_resolver.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_link_resolver.obj `if test -f 'libarchive/test/test_link_resolver.c'; then $(CYGPATH_W) 'libarchive/test/test_link_resolver.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_link_resolver.c'; fi` + +libarchive/test/libarchive_test-test_open_failure.o: libarchive/test/test_open_failure.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_open_failure.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_open_failure.Tpo -c -o libarchive/test/libarchive_test-test_open_failure.o `test -f 'libarchive/test/test_open_failure.c' || echo '$(srcdir)/'`libarchive/test/test_open_failure.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_open_failure.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_open_failure.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_open_failure.c' object='libarchive/test/libarchive_test-test_open_failure.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_open_failure.o `test -f 'libarchive/test/test_open_failure.c' || echo '$(srcdir)/'`libarchive/test/test_open_failure.c + +libarchive/test/libarchive_test-test_open_failure.obj: libarchive/test/test_open_failure.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_open_failure.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_open_failure.Tpo -c -o libarchive/test/libarchive_test-test_open_failure.obj `if test -f 'libarchive/test/test_open_failure.c'; then $(CYGPATH_W) 'libarchive/test/test_open_failure.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_open_failure.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_open_failure.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_open_failure.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_open_failure.c' object='libarchive/test/libarchive_test-test_open_failure.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_open_failure.obj `if test -f 'libarchive/test/test_open_failure.c'; then $(CYGPATH_W) 'libarchive/test/test_open_failure.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_open_failure.c'; fi` + +libarchive/test/libarchive_test-test_open_fd.o: libarchive/test/test_open_fd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_open_fd.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_open_fd.Tpo -c -o libarchive/test/libarchive_test-test_open_fd.o `test -f 'libarchive/test/test_open_fd.c' || echo '$(srcdir)/'`libarchive/test/test_open_fd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_open_fd.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_open_fd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_open_fd.c' object='libarchive/test/libarchive_test-test_open_fd.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_open_fd.o `test -f 'libarchive/test/test_open_fd.c' || echo '$(srcdir)/'`libarchive/test/test_open_fd.c + +libarchive/test/libarchive_test-test_open_fd.obj: libarchive/test/test_open_fd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_open_fd.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_open_fd.Tpo -c -o libarchive/test/libarchive_test-test_open_fd.obj `if test -f 'libarchive/test/test_open_fd.c'; then $(CYGPATH_W) 'libarchive/test/test_open_fd.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_open_fd.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_open_fd.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_open_fd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_open_fd.c' object='libarchive/test/libarchive_test-test_open_fd.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_open_fd.obj `if test -f 'libarchive/test/test_open_fd.c'; then $(CYGPATH_W) 'libarchive/test/test_open_fd.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_open_fd.c'; fi` + +libarchive/test/libarchive_test-test_open_file.o: libarchive/test/test_open_file.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_open_file.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_open_file.Tpo -c -o libarchive/test/libarchive_test-test_open_file.o `test -f 'libarchive/test/test_open_file.c' || echo '$(srcdir)/'`libarchive/test/test_open_file.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_open_file.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_open_file.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_open_file.c' object='libarchive/test/libarchive_test-test_open_file.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_open_file.o `test -f 'libarchive/test/test_open_file.c' || echo '$(srcdir)/'`libarchive/test/test_open_file.c + +libarchive/test/libarchive_test-test_open_file.obj: libarchive/test/test_open_file.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_open_file.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_open_file.Tpo -c -o libarchive/test/libarchive_test-test_open_file.obj `if test -f 'libarchive/test/test_open_file.c'; then $(CYGPATH_W) 'libarchive/test/test_open_file.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_open_file.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_open_file.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_open_file.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_open_file.c' object='libarchive/test/libarchive_test-test_open_file.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_open_file.obj `if test -f 'libarchive/test/test_open_file.c'; then $(CYGPATH_W) 'libarchive/test/test_open_file.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_open_file.c'; fi` + +libarchive/test/libarchive_test-test_open_filename.o: libarchive/test/test_open_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_open_filename.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_open_filename.Tpo -c -o libarchive/test/libarchive_test-test_open_filename.o `test -f 'libarchive/test/test_open_filename.c' || echo '$(srcdir)/'`libarchive/test/test_open_filename.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_open_filename.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_open_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_open_filename.c' object='libarchive/test/libarchive_test-test_open_filename.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_open_filename.o `test -f 'libarchive/test/test_open_filename.c' || echo '$(srcdir)/'`libarchive/test/test_open_filename.c + +libarchive/test/libarchive_test-test_open_filename.obj: libarchive/test/test_open_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_open_filename.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_open_filename.Tpo -c -o libarchive/test/libarchive_test-test_open_filename.obj `if test -f 'libarchive/test/test_open_filename.c'; then $(CYGPATH_W) 'libarchive/test/test_open_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_open_filename.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_open_filename.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_open_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_open_filename.c' object='libarchive/test/libarchive_test-test_open_filename.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_open_filename.obj `if test -f 'libarchive/test/test_open_filename.c'; then $(CYGPATH_W) 'libarchive/test/test_open_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_open_filename.c'; fi` + +libarchive/test/libarchive_test-test_pax_filename_encoding.o: libarchive/test/test_pax_filename_encoding.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_pax_filename_encoding.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_pax_filename_encoding.Tpo -c -o libarchive/test/libarchive_test-test_pax_filename_encoding.o `test -f 'libarchive/test/test_pax_filename_encoding.c' || echo '$(srcdir)/'`libarchive/test/test_pax_filename_encoding.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_pax_filename_encoding.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_pax_filename_encoding.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_pax_filename_encoding.c' object='libarchive/test/libarchive_test-test_pax_filename_encoding.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_pax_filename_encoding.o `test -f 'libarchive/test/test_pax_filename_encoding.c' || echo '$(srcdir)/'`libarchive/test/test_pax_filename_encoding.c + +libarchive/test/libarchive_test-test_pax_filename_encoding.obj: libarchive/test/test_pax_filename_encoding.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_pax_filename_encoding.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_pax_filename_encoding.Tpo -c -o libarchive/test/libarchive_test-test_pax_filename_encoding.obj `if test -f 'libarchive/test/test_pax_filename_encoding.c'; then $(CYGPATH_W) 'libarchive/test/test_pax_filename_encoding.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_pax_filename_encoding.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_pax_filename_encoding.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_pax_filename_encoding.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_pax_filename_encoding.c' object='libarchive/test/libarchive_test-test_pax_filename_encoding.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_pax_filename_encoding.obj `if test -f 'libarchive/test/test_pax_filename_encoding.c'; then $(CYGPATH_W) 'libarchive/test/test_pax_filename_encoding.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_pax_filename_encoding.c'; fi` + +libarchive/test/libarchive_test-test_pax_xattr_header.o: libarchive/test/test_pax_xattr_header.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_pax_xattr_header.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_pax_xattr_header.Tpo -c -o libarchive/test/libarchive_test-test_pax_xattr_header.o `test -f 'libarchive/test/test_pax_xattr_header.c' || echo '$(srcdir)/'`libarchive/test/test_pax_xattr_header.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_pax_xattr_header.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_pax_xattr_header.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_pax_xattr_header.c' object='libarchive/test/libarchive_test-test_pax_xattr_header.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_pax_xattr_header.o `test -f 'libarchive/test/test_pax_xattr_header.c' || echo '$(srcdir)/'`libarchive/test/test_pax_xattr_header.c + +libarchive/test/libarchive_test-test_pax_xattr_header.obj: libarchive/test/test_pax_xattr_header.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_pax_xattr_header.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_pax_xattr_header.Tpo -c -o libarchive/test/libarchive_test-test_pax_xattr_header.obj `if test -f 'libarchive/test/test_pax_xattr_header.c'; then $(CYGPATH_W) 'libarchive/test/test_pax_xattr_header.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_pax_xattr_header.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_pax_xattr_header.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_pax_xattr_header.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_pax_xattr_header.c' object='libarchive/test/libarchive_test-test_pax_xattr_header.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_pax_xattr_header.obj `if test -f 'libarchive/test/test_pax_xattr_header.c'; then $(CYGPATH_W) 'libarchive/test/test_pax_xattr_header.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_pax_xattr_header.c'; fi` + +libarchive/test/libarchive_test-test_read_data_large.o: libarchive/test/test_read_data_large.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_data_large.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_data_large.Tpo -c -o libarchive/test/libarchive_test-test_read_data_large.o `test -f 'libarchive/test/test_read_data_large.c' || echo '$(srcdir)/'`libarchive/test/test_read_data_large.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_data_large.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_data_large.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_data_large.c' object='libarchive/test/libarchive_test-test_read_data_large.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_data_large.o `test -f 'libarchive/test/test_read_data_large.c' || echo '$(srcdir)/'`libarchive/test/test_read_data_large.c + +libarchive/test/libarchive_test-test_read_data_large.obj: libarchive/test/test_read_data_large.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_data_large.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_data_large.Tpo -c -o libarchive/test/libarchive_test-test_read_data_large.obj `if test -f 'libarchive/test/test_read_data_large.c'; then $(CYGPATH_W) 'libarchive/test/test_read_data_large.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_data_large.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_data_large.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_data_large.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_data_large.c' object='libarchive/test/libarchive_test-test_read_data_large.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_data_large.obj `if test -f 'libarchive/test/test_read_data_large.c'; then $(CYGPATH_W) 'libarchive/test/test_read_data_large.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_data_large.c'; fi` + +libarchive/test/libarchive_test-test_read_disk.o: libarchive/test/test_read_disk.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_disk.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_disk.Tpo -c -o libarchive/test/libarchive_test-test_read_disk.o `test -f 'libarchive/test/test_read_disk.c' || echo '$(srcdir)/'`libarchive/test/test_read_disk.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_disk.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_disk.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_disk.c' object='libarchive/test/libarchive_test-test_read_disk.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_disk.o `test -f 'libarchive/test/test_read_disk.c' || echo '$(srcdir)/'`libarchive/test/test_read_disk.c + +libarchive/test/libarchive_test-test_read_disk.obj: libarchive/test/test_read_disk.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_disk.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_disk.Tpo -c -o libarchive/test/libarchive_test-test_read_disk.obj `if test -f 'libarchive/test/test_read_disk.c'; then $(CYGPATH_W) 'libarchive/test/test_read_disk.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_disk.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_disk.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_disk.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_disk.c' object='libarchive/test/libarchive_test-test_read_disk.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_disk.obj `if test -f 'libarchive/test/test_read_disk.c'; then $(CYGPATH_W) 'libarchive/test/test_read_disk.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_disk.c'; fi` + +libarchive/test/libarchive_test-test_read_disk_directory_traversals.o: libarchive/test/test_read_disk_directory_traversals.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_disk_directory_traversals.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_disk_directory_traversals.Tpo -c -o libarchive/test/libarchive_test-test_read_disk_directory_traversals.o `test -f 'libarchive/test/test_read_disk_directory_traversals.c' || echo '$(srcdir)/'`libarchive/test/test_read_disk_directory_traversals.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_disk_directory_traversals.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_disk_directory_traversals.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_disk_directory_traversals.c' object='libarchive/test/libarchive_test-test_read_disk_directory_traversals.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_disk_directory_traversals.o `test -f 'libarchive/test/test_read_disk_directory_traversals.c' || echo '$(srcdir)/'`libarchive/test/test_read_disk_directory_traversals.c + +libarchive/test/libarchive_test-test_read_disk_directory_traversals.obj: libarchive/test/test_read_disk_directory_traversals.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_disk_directory_traversals.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_disk_directory_traversals.Tpo -c -o libarchive/test/libarchive_test-test_read_disk_directory_traversals.obj `if test -f 'libarchive/test/test_read_disk_directory_traversals.c'; then $(CYGPATH_W) 'libarchive/test/test_read_disk_directory_traversals.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_disk_directory_traversals.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_disk_directory_traversals.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_disk_directory_traversals.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_disk_directory_traversals.c' object='libarchive/test/libarchive_test-test_read_disk_directory_traversals.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_disk_directory_traversals.obj `if test -f 'libarchive/test/test_read_disk_directory_traversals.c'; then $(CYGPATH_W) 'libarchive/test/test_read_disk_directory_traversals.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_disk_directory_traversals.c'; fi` + +libarchive/test/libarchive_test-test_read_disk_entry_from_file.o: libarchive/test/test_read_disk_entry_from_file.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_disk_entry_from_file.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_disk_entry_from_file.Tpo -c -o libarchive/test/libarchive_test-test_read_disk_entry_from_file.o `test -f 'libarchive/test/test_read_disk_entry_from_file.c' || echo '$(srcdir)/'`libarchive/test/test_read_disk_entry_from_file.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_disk_entry_from_file.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_disk_entry_from_file.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_disk_entry_from_file.c' object='libarchive/test/libarchive_test-test_read_disk_entry_from_file.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_disk_entry_from_file.o `test -f 'libarchive/test/test_read_disk_entry_from_file.c' || echo '$(srcdir)/'`libarchive/test/test_read_disk_entry_from_file.c + +libarchive/test/libarchive_test-test_read_disk_entry_from_file.obj: libarchive/test/test_read_disk_entry_from_file.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_disk_entry_from_file.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_disk_entry_from_file.Tpo -c -o libarchive/test/libarchive_test-test_read_disk_entry_from_file.obj `if test -f 'libarchive/test/test_read_disk_entry_from_file.c'; then $(CYGPATH_W) 'libarchive/test/test_read_disk_entry_from_file.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_disk_entry_from_file.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_disk_entry_from_file.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_disk_entry_from_file.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_disk_entry_from_file.c' object='libarchive/test/libarchive_test-test_read_disk_entry_from_file.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_disk_entry_from_file.obj `if test -f 'libarchive/test/test_read_disk_entry_from_file.c'; then $(CYGPATH_W) 'libarchive/test/test_read_disk_entry_from_file.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_disk_entry_from_file.c'; fi` + +libarchive/test/libarchive_test-test_read_extract.o: libarchive/test/test_read_extract.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_extract.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_extract.Tpo -c -o libarchive/test/libarchive_test-test_read_extract.o `test -f 'libarchive/test/test_read_extract.c' || echo '$(srcdir)/'`libarchive/test/test_read_extract.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_extract.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_extract.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_extract.c' object='libarchive/test/libarchive_test-test_read_extract.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_extract.o `test -f 'libarchive/test/test_read_extract.c' || echo '$(srcdir)/'`libarchive/test/test_read_extract.c + +libarchive/test/libarchive_test-test_read_extract.obj: libarchive/test/test_read_extract.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_extract.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_extract.Tpo -c -o libarchive/test/libarchive_test-test_read_extract.obj `if test -f 'libarchive/test/test_read_extract.c'; then $(CYGPATH_W) 'libarchive/test/test_read_extract.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_extract.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_extract.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_extract.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_extract.c' object='libarchive/test/libarchive_test-test_read_extract.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_extract.obj `if test -f 'libarchive/test/test_read_extract.c'; then $(CYGPATH_W) 'libarchive/test/test_read_extract.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_extract.c'; fi` + +libarchive/test/libarchive_test-test_read_file_nonexistent.o: libarchive/test/test_read_file_nonexistent.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_file_nonexistent.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_file_nonexistent.Tpo -c -o libarchive/test/libarchive_test-test_read_file_nonexistent.o `test -f 'libarchive/test/test_read_file_nonexistent.c' || echo '$(srcdir)/'`libarchive/test/test_read_file_nonexistent.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_file_nonexistent.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_file_nonexistent.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_file_nonexistent.c' object='libarchive/test/libarchive_test-test_read_file_nonexistent.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_file_nonexistent.o `test -f 'libarchive/test/test_read_file_nonexistent.c' || echo '$(srcdir)/'`libarchive/test/test_read_file_nonexistent.c + +libarchive/test/libarchive_test-test_read_file_nonexistent.obj: libarchive/test/test_read_file_nonexistent.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_file_nonexistent.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_file_nonexistent.Tpo -c -o libarchive/test/libarchive_test-test_read_file_nonexistent.obj `if test -f 'libarchive/test/test_read_file_nonexistent.c'; then $(CYGPATH_W) 'libarchive/test/test_read_file_nonexistent.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_file_nonexistent.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_file_nonexistent.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_file_nonexistent.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_file_nonexistent.c' object='libarchive/test/libarchive_test-test_read_file_nonexistent.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_file_nonexistent.obj `if test -f 'libarchive/test/test_read_file_nonexistent.c'; then $(CYGPATH_W) 'libarchive/test/test_read_file_nonexistent.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_file_nonexistent.c'; fi` + +libarchive/test/libarchive_test-test_read_filter_compress.o: libarchive/test/test_read_filter_compress.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_filter_compress.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_compress.Tpo -c -o libarchive/test/libarchive_test-test_read_filter_compress.o `test -f 'libarchive/test/test_read_filter_compress.c' || echo '$(srcdir)/'`libarchive/test/test_read_filter_compress.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_compress.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_compress.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_filter_compress.c' object='libarchive/test/libarchive_test-test_read_filter_compress.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_filter_compress.o `test -f 'libarchive/test/test_read_filter_compress.c' || echo '$(srcdir)/'`libarchive/test/test_read_filter_compress.c + +libarchive/test/libarchive_test-test_read_filter_compress.obj: libarchive/test/test_read_filter_compress.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_filter_compress.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_compress.Tpo -c -o libarchive/test/libarchive_test-test_read_filter_compress.obj `if test -f 'libarchive/test/test_read_filter_compress.c'; then $(CYGPATH_W) 'libarchive/test/test_read_filter_compress.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_filter_compress.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_compress.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_compress.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_filter_compress.c' object='libarchive/test/libarchive_test-test_read_filter_compress.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_filter_compress.obj `if test -f 'libarchive/test/test_read_filter_compress.c'; then $(CYGPATH_W) 'libarchive/test/test_read_filter_compress.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_filter_compress.c'; fi` + +libarchive/test/libarchive_test-test_read_filter_grzip.o: libarchive/test/test_read_filter_grzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_filter_grzip.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_grzip.Tpo -c -o libarchive/test/libarchive_test-test_read_filter_grzip.o `test -f 'libarchive/test/test_read_filter_grzip.c' || echo '$(srcdir)/'`libarchive/test/test_read_filter_grzip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_grzip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_grzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_filter_grzip.c' object='libarchive/test/libarchive_test-test_read_filter_grzip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_filter_grzip.o `test -f 'libarchive/test/test_read_filter_grzip.c' || echo '$(srcdir)/'`libarchive/test/test_read_filter_grzip.c + +libarchive/test/libarchive_test-test_read_filter_grzip.obj: libarchive/test/test_read_filter_grzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_filter_grzip.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_grzip.Tpo -c -o libarchive/test/libarchive_test-test_read_filter_grzip.obj `if test -f 'libarchive/test/test_read_filter_grzip.c'; then $(CYGPATH_W) 'libarchive/test/test_read_filter_grzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_filter_grzip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_grzip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_grzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_filter_grzip.c' object='libarchive/test/libarchive_test-test_read_filter_grzip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_filter_grzip.obj `if test -f 'libarchive/test/test_read_filter_grzip.c'; then $(CYGPATH_W) 'libarchive/test/test_read_filter_grzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_filter_grzip.c'; fi` + +libarchive/test/libarchive_test-test_read_filter_lrzip.o: libarchive/test/test_read_filter_lrzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_filter_lrzip.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_lrzip.Tpo -c -o libarchive/test/libarchive_test-test_read_filter_lrzip.o `test -f 'libarchive/test/test_read_filter_lrzip.c' || echo '$(srcdir)/'`libarchive/test/test_read_filter_lrzip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_lrzip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_lrzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_filter_lrzip.c' object='libarchive/test/libarchive_test-test_read_filter_lrzip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_filter_lrzip.o `test -f 'libarchive/test/test_read_filter_lrzip.c' || echo '$(srcdir)/'`libarchive/test/test_read_filter_lrzip.c + +libarchive/test/libarchive_test-test_read_filter_lrzip.obj: libarchive/test/test_read_filter_lrzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_filter_lrzip.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_lrzip.Tpo -c -o libarchive/test/libarchive_test-test_read_filter_lrzip.obj `if test -f 'libarchive/test/test_read_filter_lrzip.c'; then $(CYGPATH_W) 'libarchive/test/test_read_filter_lrzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_filter_lrzip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_lrzip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_lrzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_filter_lrzip.c' object='libarchive/test/libarchive_test-test_read_filter_lrzip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_filter_lrzip.obj `if test -f 'libarchive/test/test_read_filter_lrzip.c'; then $(CYGPATH_W) 'libarchive/test/test_read_filter_lrzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_filter_lrzip.c'; fi` + +libarchive/test/libarchive_test-test_read_filter_lzop.o: libarchive/test/test_read_filter_lzop.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_filter_lzop.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_lzop.Tpo -c -o libarchive/test/libarchive_test-test_read_filter_lzop.o `test -f 'libarchive/test/test_read_filter_lzop.c' || echo '$(srcdir)/'`libarchive/test/test_read_filter_lzop.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_lzop.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_lzop.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_filter_lzop.c' object='libarchive/test/libarchive_test-test_read_filter_lzop.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_filter_lzop.o `test -f 'libarchive/test/test_read_filter_lzop.c' || echo '$(srcdir)/'`libarchive/test/test_read_filter_lzop.c + +libarchive/test/libarchive_test-test_read_filter_lzop.obj: libarchive/test/test_read_filter_lzop.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_filter_lzop.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_lzop.Tpo -c -o libarchive/test/libarchive_test-test_read_filter_lzop.obj `if test -f 'libarchive/test/test_read_filter_lzop.c'; then $(CYGPATH_W) 'libarchive/test/test_read_filter_lzop.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_filter_lzop.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_lzop.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_lzop.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_filter_lzop.c' object='libarchive/test/libarchive_test-test_read_filter_lzop.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_filter_lzop.obj `if test -f 'libarchive/test/test_read_filter_lzop.c'; then $(CYGPATH_W) 'libarchive/test/test_read_filter_lzop.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_filter_lzop.c'; fi` + +libarchive/test/libarchive_test-test_read_filter_lzop_multiple_parts.o: libarchive/test/test_read_filter_lzop_multiple_parts.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_filter_lzop_multiple_parts.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_lzop_multiple_parts.Tpo -c -o libarchive/test/libarchive_test-test_read_filter_lzop_multiple_parts.o `test -f 'libarchive/test/test_read_filter_lzop_multiple_parts.c' || echo '$(srcdir)/'`libarchive/test/test_read_filter_lzop_multiple_parts.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_lzop_multiple_parts.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_lzop_multiple_parts.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_filter_lzop_multiple_parts.c' object='libarchive/test/libarchive_test-test_read_filter_lzop_multiple_parts.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_filter_lzop_multiple_parts.o `test -f 'libarchive/test/test_read_filter_lzop_multiple_parts.c' || echo '$(srcdir)/'`libarchive/test/test_read_filter_lzop_multiple_parts.c + +libarchive/test/libarchive_test-test_read_filter_lzop_multiple_parts.obj: libarchive/test/test_read_filter_lzop_multiple_parts.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_filter_lzop_multiple_parts.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_lzop_multiple_parts.Tpo -c -o libarchive/test/libarchive_test-test_read_filter_lzop_multiple_parts.obj `if test -f 'libarchive/test/test_read_filter_lzop_multiple_parts.c'; then $(CYGPATH_W) 'libarchive/test/test_read_filter_lzop_multiple_parts.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_filter_lzop_multiple_parts.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_lzop_multiple_parts.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_lzop_multiple_parts.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_filter_lzop_multiple_parts.c' object='libarchive/test/libarchive_test-test_read_filter_lzop_multiple_parts.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_filter_lzop_multiple_parts.obj `if test -f 'libarchive/test/test_read_filter_lzop_multiple_parts.c'; then $(CYGPATH_W) 'libarchive/test/test_read_filter_lzop_multiple_parts.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_filter_lzop_multiple_parts.c'; fi` + +libarchive/test/libarchive_test-test_read_filter_program.o: libarchive/test/test_read_filter_program.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_filter_program.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_program.Tpo -c -o libarchive/test/libarchive_test-test_read_filter_program.o `test -f 'libarchive/test/test_read_filter_program.c' || echo '$(srcdir)/'`libarchive/test/test_read_filter_program.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_program.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_program.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_filter_program.c' object='libarchive/test/libarchive_test-test_read_filter_program.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_filter_program.o `test -f 'libarchive/test/test_read_filter_program.c' || echo '$(srcdir)/'`libarchive/test/test_read_filter_program.c + +libarchive/test/libarchive_test-test_read_filter_program.obj: libarchive/test/test_read_filter_program.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_filter_program.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_program.Tpo -c -o libarchive/test/libarchive_test-test_read_filter_program.obj `if test -f 'libarchive/test/test_read_filter_program.c'; then $(CYGPATH_W) 'libarchive/test/test_read_filter_program.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_filter_program.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_program.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_program.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_filter_program.c' object='libarchive/test/libarchive_test-test_read_filter_program.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_filter_program.obj `if test -f 'libarchive/test/test_read_filter_program.c'; then $(CYGPATH_W) 'libarchive/test/test_read_filter_program.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_filter_program.c'; fi` + +libarchive/test/libarchive_test-test_read_filter_program_signature.o: libarchive/test/test_read_filter_program_signature.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_filter_program_signature.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_program_signature.Tpo -c -o libarchive/test/libarchive_test-test_read_filter_program_signature.o `test -f 'libarchive/test/test_read_filter_program_signature.c' || echo '$(srcdir)/'`libarchive/test/test_read_filter_program_signature.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_program_signature.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_program_signature.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_filter_program_signature.c' object='libarchive/test/libarchive_test-test_read_filter_program_signature.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_filter_program_signature.o `test -f 'libarchive/test/test_read_filter_program_signature.c' || echo '$(srcdir)/'`libarchive/test/test_read_filter_program_signature.c + +libarchive/test/libarchive_test-test_read_filter_program_signature.obj: libarchive/test/test_read_filter_program_signature.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_filter_program_signature.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_program_signature.Tpo -c -o libarchive/test/libarchive_test-test_read_filter_program_signature.obj `if test -f 'libarchive/test/test_read_filter_program_signature.c'; then $(CYGPATH_W) 'libarchive/test/test_read_filter_program_signature.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_filter_program_signature.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_program_signature.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_program_signature.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_filter_program_signature.c' object='libarchive/test/libarchive_test-test_read_filter_program_signature.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_filter_program_signature.obj `if test -f 'libarchive/test/test_read_filter_program_signature.c'; then $(CYGPATH_W) 'libarchive/test/test_read_filter_program_signature.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_filter_program_signature.c'; fi` + +libarchive/test/libarchive_test-test_read_filter_uudecode.o: libarchive/test/test_read_filter_uudecode.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_filter_uudecode.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_uudecode.Tpo -c -o libarchive/test/libarchive_test-test_read_filter_uudecode.o `test -f 'libarchive/test/test_read_filter_uudecode.c' || echo '$(srcdir)/'`libarchive/test/test_read_filter_uudecode.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_uudecode.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_uudecode.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_filter_uudecode.c' object='libarchive/test/libarchive_test-test_read_filter_uudecode.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_filter_uudecode.o `test -f 'libarchive/test/test_read_filter_uudecode.c' || echo '$(srcdir)/'`libarchive/test/test_read_filter_uudecode.c + +libarchive/test/libarchive_test-test_read_filter_uudecode.obj: libarchive/test/test_read_filter_uudecode.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_filter_uudecode.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_uudecode.Tpo -c -o libarchive/test/libarchive_test-test_read_filter_uudecode.obj `if test -f 'libarchive/test/test_read_filter_uudecode.c'; then $(CYGPATH_W) 'libarchive/test/test_read_filter_uudecode.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_filter_uudecode.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_uudecode.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_filter_uudecode.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_filter_uudecode.c' object='libarchive/test/libarchive_test-test_read_filter_uudecode.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_filter_uudecode.obj `if test -f 'libarchive/test/test_read_filter_uudecode.c'; then $(CYGPATH_W) 'libarchive/test/test_read_filter_uudecode.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_filter_uudecode.c'; fi` + +libarchive/test/libarchive_test-test_read_format_7zip.o: libarchive/test/test_read_format_7zip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_7zip.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip.Tpo -c -o libarchive/test/libarchive_test-test_read_format_7zip.o `test -f 'libarchive/test/test_read_format_7zip.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_7zip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_7zip.c' object='libarchive/test/libarchive_test-test_read_format_7zip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_7zip.o `test -f 'libarchive/test/test_read_format_7zip.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_7zip.c + +libarchive/test/libarchive_test-test_read_format_7zip.obj: libarchive/test/test_read_format_7zip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_7zip.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip.Tpo -c -o libarchive/test/libarchive_test-test_read_format_7zip.obj `if test -f 'libarchive/test/test_read_format_7zip.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_7zip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_7zip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_7zip.c' object='libarchive/test/libarchive_test-test_read_format_7zip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_7zip.obj `if test -f 'libarchive/test/test_read_format_7zip.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_7zip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_7zip.c'; fi` + +libarchive/test/libarchive_test-test_read_format_7zip_encryption_data.o: libarchive/test/test_read_format_7zip_encryption_data.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_7zip_encryption_data.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_encryption_data.Tpo -c -o libarchive/test/libarchive_test-test_read_format_7zip_encryption_data.o `test -f 'libarchive/test/test_read_format_7zip_encryption_data.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_7zip_encryption_data.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_encryption_data.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_encryption_data.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_7zip_encryption_data.c' object='libarchive/test/libarchive_test-test_read_format_7zip_encryption_data.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_7zip_encryption_data.o `test -f 'libarchive/test/test_read_format_7zip_encryption_data.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_7zip_encryption_data.c + +libarchive/test/libarchive_test-test_read_format_7zip_encryption_data.obj: libarchive/test/test_read_format_7zip_encryption_data.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_7zip_encryption_data.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_encryption_data.Tpo -c -o libarchive/test/libarchive_test-test_read_format_7zip_encryption_data.obj `if test -f 'libarchive/test/test_read_format_7zip_encryption_data.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_7zip_encryption_data.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_7zip_encryption_data.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_encryption_data.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_encryption_data.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_7zip_encryption_data.c' object='libarchive/test/libarchive_test-test_read_format_7zip_encryption_data.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_7zip_encryption_data.obj `if test -f 'libarchive/test/test_read_format_7zip_encryption_data.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_7zip_encryption_data.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_7zip_encryption_data.c'; fi` + +libarchive/test/libarchive_test-test_read_format_7zip_encryption_partially.o: libarchive/test/test_read_format_7zip_encryption_partially.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_7zip_encryption_partially.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_encryption_partially.Tpo -c -o libarchive/test/libarchive_test-test_read_format_7zip_encryption_partially.o `test -f 'libarchive/test/test_read_format_7zip_encryption_partially.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_7zip_encryption_partially.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_encryption_partially.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_encryption_partially.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_7zip_encryption_partially.c' object='libarchive/test/libarchive_test-test_read_format_7zip_encryption_partially.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_7zip_encryption_partially.o `test -f 'libarchive/test/test_read_format_7zip_encryption_partially.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_7zip_encryption_partially.c + +libarchive/test/libarchive_test-test_read_format_7zip_encryption_partially.obj: libarchive/test/test_read_format_7zip_encryption_partially.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_7zip_encryption_partially.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_encryption_partially.Tpo -c -o libarchive/test/libarchive_test-test_read_format_7zip_encryption_partially.obj `if test -f 'libarchive/test/test_read_format_7zip_encryption_partially.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_7zip_encryption_partially.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_7zip_encryption_partially.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_encryption_partially.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_encryption_partially.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_7zip_encryption_partially.c' object='libarchive/test/libarchive_test-test_read_format_7zip_encryption_partially.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_7zip_encryption_partially.obj `if test -f 'libarchive/test/test_read_format_7zip_encryption_partially.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_7zip_encryption_partially.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_7zip_encryption_partially.c'; fi` + +libarchive/test/libarchive_test-test_read_format_7zip_encryption_header.o: libarchive/test/test_read_format_7zip_encryption_header.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_7zip_encryption_header.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_encryption_header.Tpo -c -o libarchive/test/libarchive_test-test_read_format_7zip_encryption_header.o `test -f 'libarchive/test/test_read_format_7zip_encryption_header.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_7zip_encryption_header.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_encryption_header.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_encryption_header.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_7zip_encryption_header.c' object='libarchive/test/libarchive_test-test_read_format_7zip_encryption_header.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_7zip_encryption_header.o `test -f 'libarchive/test/test_read_format_7zip_encryption_header.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_7zip_encryption_header.c + +libarchive/test/libarchive_test-test_read_format_7zip_encryption_header.obj: libarchive/test/test_read_format_7zip_encryption_header.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_7zip_encryption_header.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_encryption_header.Tpo -c -o libarchive/test/libarchive_test-test_read_format_7zip_encryption_header.obj `if test -f 'libarchive/test/test_read_format_7zip_encryption_header.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_7zip_encryption_header.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_7zip_encryption_header.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_encryption_header.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_encryption_header.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_7zip_encryption_header.c' object='libarchive/test/libarchive_test-test_read_format_7zip_encryption_header.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_7zip_encryption_header.obj `if test -f 'libarchive/test/test_read_format_7zip_encryption_header.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_7zip_encryption_header.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_7zip_encryption_header.c'; fi` + +libarchive/test/libarchive_test-test_read_format_7zip_malformed.o: libarchive/test/test_read_format_7zip_malformed.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_7zip_malformed.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_malformed.Tpo -c -o libarchive/test/libarchive_test-test_read_format_7zip_malformed.o `test -f 'libarchive/test/test_read_format_7zip_malformed.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_7zip_malformed.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_malformed.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_malformed.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_7zip_malformed.c' object='libarchive/test/libarchive_test-test_read_format_7zip_malformed.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_7zip_malformed.o `test -f 'libarchive/test/test_read_format_7zip_malformed.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_7zip_malformed.c + +libarchive/test/libarchive_test-test_read_format_7zip_malformed.obj: libarchive/test/test_read_format_7zip_malformed.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_7zip_malformed.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_malformed.Tpo -c -o libarchive/test/libarchive_test-test_read_format_7zip_malformed.obj `if test -f 'libarchive/test/test_read_format_7zip_malformed.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_7zip_malformed.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_7zip_malformed.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_malformed.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_malformed.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_7zip_malformed.c' object='libarchive/test/libarchive_test-test_read_format_7zip_malformed.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_7zip_malformed.obj `if test -f 'libarchive/test/test_read_format_7zip_malformed.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_7zip_malformed.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_7zip_malformed.c'; fi` + +libarchive/test/libarchive_test-test_read_format_7zip_packinfo_digests.o: libarchive/test/test_read_format_7zip_packinfo_digests.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_7zip_packinfo_digests.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_packinfo_digests.Tpo -c -o libarchive/test/libarchive_test-test_read_format_7zip_packinfo_digests.o `test -f 'libarchive/test/test_read_format_7zip_packinfo_digests.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_7zip_packinfo_digests.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_packinfo_digests.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_packinfo_digests.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_7zip_packinfo_digests.c' object='libarchive/test/libarchive_test-test_read_format_7zip_packinfo_digests.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_7zip_packinfo_digests.o `test -f 'libarchive/test/test_read_format_7zip_packinfo_digests.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_7zip_packinfo_digests.c + +libarchive/test/libarchive_test-test_read_format_7zip_packinfo_digests.obj: libarchive/test/test_read_format_7zip_packinfo_digests.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_7zip_packinfo_digests.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_packinfo_digests.Tpo -c -o libarchive/test/libarchive_test-test_read_format_7zip_packinfo_digests.obj `if test -f 'libarchive/test/test_read_format_7zip_packinfo_digests.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_7zip_packinfo_digests.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_7zip_packinfo_digests.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_packinfo_digests.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_7zip_packinfo_digests.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_7zip_packinfo_digests.c' object='libarchive/test/libarchive_test-test_read_format_7zip_packinfo_digests.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_7zip_packinfo_digests.obj `if test -f 'libarchive/test/test_read_format_7zip_packinfo_digests.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_7zip_packinfo_digests.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_7zip_packinfo_digests.c'; fi` + +libarchive/test/libarchive_test-test_read_format_ar.o: libarchive/test/test_read_format_ar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_ar.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_ar.Tpo -c -o libarchive/test/libarchive_test-test_read_format_ar.o `test -f 'libarchive/test/test_read_format_ar.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_ar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_ar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_ar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_ar.c' object='libarchive/test/libarchive_test-test_read_format_ar.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_ar.o `test -f 'libarchive/test/test_read_format_ar.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_ar.c + +libarchive/test/libarchive_test-test_read_format_ar.obj: libarchive/test/test_read_format_ar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_ar.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_ar.Tpo -c -o libarchive/test/libarchive_test-test_read_format_ar.obj `if test -f 'libarchive/test/test_read_format_ar.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_ar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_ar.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_ar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_ar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_ar.c' object='libarchive/test/libarchive_test-test_read_format_ar.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_ar.obj `if test -f 'libarchive/test/test_read_format_ar.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_ar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_ar.c'; fi` + +libarchive/test/libarchive_test-test_read_format_cab.o: libarchive/test/test_read_format_cab.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cab.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cab.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cab.o `test -f 'libarchive/test/test_read_format_cab.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cab.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cab.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cab.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cab.c' object='libarchive/test/libarchive_test-test_read_format_cab.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cab.o `test -f 'libarchive/test/test_read_format_cab.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cab.c + +libarchive/test/libarchive_test-test_read_format_cab.obj: libarchive/test/test_read_format_cab.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cab.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cab.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cab.obj `if test -f 'libarchive/test/test_read_format_cab.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cab.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cab.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cab.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cab.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cab.c' object='libarchive/test/libarchive_test-test_read_format_cab.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cab.obj `if test -f 'libarchive/test/test_read_format_cab.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cab.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cab.c'; fi` + +libarchive/test/libarchive_test-test_read_format_cab_filename.o: libarchive/test/test_read_format_cab_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cab_filename.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cab_filename.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cab_filename.o `test -f 'libarchive/test/test_read_format_cab_filename.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cab_filename.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cab_filename.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cab_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cab_filename.c' object='libarchive/test/libarchive_test-test_read_format_cab_filename.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cab_filename.o `test -f 'libarchive/test/test_read_format_cab_filename.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cab_filename.c + +libarchive/test/libarchive_test-test_read_format_cab_filename.obj: libarchive/test/test_read_format_cab_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cab_filename.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cab_filename.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cab_filename.obj `if test -f 'libarchive/test/test_read_format_cab_filename.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cab_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cab_filename.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cab_filename.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cab_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cab_filename.c' object='libarchive/test/libarchive_test-test_read_format_cab_filename.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cab_filename.obj `if test -f 'libarchive/test/test_read_format_cab_filename.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cab_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cab_filename.c'; fi` + +libarchive/test/libarchive_test-test_read_format_cpio_afio.o: libarchive/test/test_read_format_cpio_afio.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_afio.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_afio.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_afio.o `test -f 'libarchive/test/test_read_format_cpio_afio.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_afio.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_afio.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_afio.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_afio.c' object='libarchive/test/libarchive_test-test_read_format_cpio_afio.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_afio.o `test -f 'libarchive/test/test_read_format_cpio_afio.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_afio.c + +libarchive/test/libarchive_test-test_read_format_cpio_afio.obj: libarchive/test/test_read_format_cpio_afio.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_afio.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_afio.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_afio.obj `if test -f 'libarchive/test/test_read_format_cpio_afio.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_afio.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_afio.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_afio.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_afio.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_afio.c' object='libarchive/test/libarchive_test-test_read_format_cpio_afio.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_afio.obj `if test -f 'libarchive/test/test_read_format_cpio_afio.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_afio.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_afio.c'; fi` + +libarchive/test/libarchive_test-test_read_format_cpio_bin.o: libarchive/test/test_read_format_cpio_bin.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_bin.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin.o `test -f 'libarchive/test/test_read_format_cpio_bin.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_bin.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_bin.c' object='libarchive/test/libarchive_test-test_read_format_cpio_bin.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin.o `test -f 'libarchive/test/test_read_format_cpio_bin.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_bin.c + +libarchive/test/libarchive_test-test_read_format_cpio_bin.obj: libarchive/test/test_read_format_cpio_bin.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_bin.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin.obj `if test -f 'libarchive/test/test_read_format_cpio_bin.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_bin.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_bin.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_bin.c' object='libarchive/test/libarchive_test-test_read_format_cpio_bin.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin.obj `if test -f 'libarchive/test/test_read_format_cpio_bin.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_bin.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_bin.c'; fi` + +libarchive/test/libarchive_test-test_read_format_cpio_bin_Z.o: libarchive/test/test_read_format_cpio_bin_Z.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_bin_Z.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_Z.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_Z.o `test -f 'libarchive/test/test_read_format_cpio_bin_Z.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_bin_Z.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_Z.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_Z.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_bin_Z.c' object='libarchive/test/libarchive_test-test_read_format_cpio_bin_Z.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_Z.o `test -f 'libarchive/test/test_read_format_cpio_bin_Z.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_bin_Z.c + +libarchive/test/libarchive_test-test_read_format_cpio_bin_Z.obj: libarchive/test/test_read_format_cpio_bin_Z.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_bin_Z.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_Z.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_Z.obj `if test -f 'libarchive/test/test_read_format_cpio_bin_Z.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_bin_Z.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_bin_Z.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_Z.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_Z.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_bin_Z.c' object='libarchive/test/libarchive_test-test_read_format_cpio_bin_Z.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_Z.obj `if test -f 'libarchive/test/test_read_format_cpio_bin_Z.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_bin_Z.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_bin_Z.c'; fi` + +libarchive/test/libarchive_test-test_read_format_cpio_bin_be.o: libarchive/test/test_read_format_cpio_bin_be.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_bin_be.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_be.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_be.o `test -f 'libarchive/test/test_read_format_cpio_bin_be.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_bin_be.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_be.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_be.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_bin_be.c' object='libarchive/test/libarchive_test-test_read_format_cpio_bin_be.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_be.o `test -f 'libarchive/test/test_read_format_cpio_bin_be.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_bin_be.c + +libarchive/test/libarchive_test-test_read_format_cpio_bin_be.obj: libarchive/test/test_read_format_cpio_bin_be.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_bin_be.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_be.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_be.obj `if test -f 'libarchive/test/test_read_format_cpio_bin_be.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_bin_be.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_bin_be.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_be.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_be.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_bin_be.c' object='libarchive/test/libarchive_test-test_read_format_cpio_bin_be.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_be.obj `if test -f 'libarchive/test/test_read_format_cpio_bin_be.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_bin_be.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_bin_be.c'; fi` + +libarchive/test/libarchive_test-test_read_format_cpio_bin_bz2.o: libarchive/test/test_read_format_cpio_bin_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_bin_bz2.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_bz2.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_bz2.o `test -f 'libarchive/test/test_read_format_cpio_bin_bz2.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_bin_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_bz2.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_bz2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_bin_bz2.c' object='libarchive/test/libarchive_test-test_read_format_cpio_bin_bz2.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_bz2.o `test -f 'libarchive/test/test_read_format_cpio_bin_bz2.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_bin_bz2.c + +libarchive/test/libarchive_test-test_read_format_cpio_bin_bz2.obj: libarchive/test/test_read_format_cpio_bin_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_bin_bz2.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_bz2.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_bz2.obj `if test -f 'libarchive/test/test_read_format_cpio_bin_bz2.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_bin_bz2.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_bin_bz2.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_bz2.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_bz2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_bin_bz2.c' object='libarchive/test/libarchive_test-test_read_format_cpio_bin_bz2.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_bz2.obj `if test -f 'libarchive/test/test_read_format_cpio_bin_bz2.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_bin_bz2.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_bin_bz2.c'; fi` + +libarchive/test/libarchive_test-test_read_format_cpio_bin_gz.o: libarchive/test/test_read_format_cpio_bin_gz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_bin_gz.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_gz.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_gz.o `test -f 'libarchive/test/test_read_format_cpio_bin_gz.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_bin_gz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_gz.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_gz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_bin_gz.c' object='libarchive/test/libarchive_test-test_read_format_cpio_bin_gz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_gz.o `test -f 'libarchive/test/test_read_format_cpio_bin_gz.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_bin_gz.c + +libarchive/test/libarchive_test-test_read_format_cpio_bin_gz.obj: libarchive/test/test_read_format_cpio_bin_gz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_bin_gz.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_gz.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_gz.obj `if test -f 'libarchive/test/test_read_format_cpio_bin_gz.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_bin_gz.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_bin_gz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_gz.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_gz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_bin_gz.c' object='libarchive/test/libarchive_test-test_read_format_cpio_bin_gz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_gz.obj `if test -f 'libarchive/test/test_read_format_cpio_bin_gz.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_bin_gz.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_bin_gz.c'; fi` + +libarchive/test/libarchive_test-test_read_format_cpio_bin_le.o: libarchive/test/test_read_format_cpio_bin_le.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_bin_le.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_le.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_le.o `test -f 'libarchive/test/test_read_format_cpio_bin_le.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_bin_le.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_le.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_le.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_bin_le.c' object='libarchive/test/libarchive_test-test_read_format_cpio_bin_le.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_le.o `test -f 'libarchive/test/test_read_format_cpio_bin_le.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_bin_le.c + +libarchive/test/libarchive_test-test_read_format_cpio_bin_le.obj: libarchive/test/test_read_format_cpio_bin_le.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_bin_le.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_le.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_le.obj `if test -f 'libarchive/test/test_read_format_cpio_bin_le.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_bin_le.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_bin_le.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_le.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_le.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_bin_le.c' object='libarchive/test/libarchive_test-test_read_format_cpio_bin_le.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_le.obj `if test -f 'libarchive/test/test_read_format_cpio_bin_le.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_bin_le.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_bin_le.c'; fi` + +libarchive/test/libarchive_test-test_read_format_cpio_bin_lzip.o: libarchive/test/test_read_format_cpio_bin_lzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_bin_lzip.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_lzip.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_lzip.o `test -f 'libarchive/test/test_read_format_cpio_bin_lzip.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_bin_lzip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_lzip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_lzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_bin_lzip.c' object='libarchive/test/libarchive_test-test_read_format_cpio_bin_lzip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_lzip.o `test -f 'libarchive/test/test_read_format_cpio_bin_lzip.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_bin_lzip.c + +libarchive/test/libarchive_test-test_read_format_cpio_bin_lzip.obj: libarchive/test/test_read_format_cpio_bin_lzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_bin_lzip.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_lzip.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_lzip.obj `if test -f 'libarchive/test/test_read_format_cpio_bin_lzip.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_bin_lzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_bin_lzip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_lzip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_lzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_bin_lzip.c' object='libarchive/test/libarchive_test-test_read_format_cpio_bin_lzip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_lzip.obj `if test -f 'libarchive/test/test_read_format_cpio_bin_lzip.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_bin_lzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_bin_lzip.c'; fi` + +libarchive/test/libarchive_test-test_read_format_cpio_bin_lzma.o: libarchive/test/test_read_format_cpio_bin_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_bin_lzma.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_lzma.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_lzma.o `test -f 'libarchive/test/test_read_format_cpio_bin_lzma.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_bin_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_lzma.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_lzma.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_bin_lzma.c' object='libarchive/test/libarchive_test-test_read_format_cpio_bin_lzma.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_lzma.o `test -f 'libarchive/test/test_read_format_cpio_bin_lzma.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_bin_lzma.c + +libarchive/test/libarchive_test-test_read_format_cpio_bin_lzma.obj: libarchive/test/test_read_format_cpio_bin_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_bin_lzma.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_lzma.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_lzma.obj `if test -f 'libarchive/test/test_read_format_cpio_bin_lzma.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_bin_lzma.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_bin_lzma.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_lzma.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_lzma.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_bin_lzma.c' object='libarchive/test/libarchive_test-test_read_format_cpio_bin_lzma.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_lzma.obj `if test -f 'libarchive/test/test_read_format_cpio_bin_lzma.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_bin_lzma.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_bin_lzma.c'; fi` + +libarchive/test/libarchive_test-test_read_format_cpio_bin_xz.o: libarchive/test/test_read_format_cpio_bin_xz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_bin_xz.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_xz.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_xz.o `test -f 'libarchive/test/test_read_format_cpio_bin_xz.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_bin_xz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_xz.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_xz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_bin_xz.c' object='libarchive/test/libarchive_test-test_read_format_cpio_bin_xz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_xz.o `test -f 'libarchive/test/test_read_format_cpio_bin_xz.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_bin_xz.c + +libarchive/test/libarchive_test-test_read_format_cpio_bin_xz.obj: libarchive/test/test_read_format_cpio_bin_xz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_bin_xz.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_xz.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_xz.obj `if test -f 'libarchive/test/test_read_format_cpio_bin_xz.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_bin_xz.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_bin_xz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_xz.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_bin_xz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_bin_xz.c' object='libarchive/test/libarchive_test-test_read_format_cpio_bin_xz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_bin_xz.obj `if test -f 'libarchive/test/test_read_format_cpio_bin_xz.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_bin_xz.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_bin_xz.c'; fi` + +libarchive/test/libarchive_test-test_read_format_cpio_filename.o: libarchive/test/test_read_format_cpio_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_filename.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_filename.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_filename.o `test -f 'libarchive/test/test_read_format_cpio_filename.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_filename.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_filename.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_filename.c' object='libarchive/test/libarchive_test-test_read_format_cpio_filename.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_filename.o `test -f 'libarchive/test/test_read_format_cpio_filename.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_filename.c + +libarchive/test/libarchive_test-test_read_format_cpio_filename.obj: libarchive/test/test_read_format_cpio_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_filename.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_filename.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_filename.obj `if test -f 'libarchive/test/test_read_format_cpio_filename.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_filename.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_filename.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_filename.c' object='libarchive/test/libarchive_test-test_read_format_cpio_filename.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_filename.obj `if test -f 'libarchive/test/test_read_format_cpio_filename.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_filename.c'; fi` + +libarchive/test/libarchive_test-test_read_format_cpio_odc.o: libarchive/test/test_read_format_cpio_odc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_odc.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_odc.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_odc.o `test -f 'libarchive/test/test_read_format_cpio_odc.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_odc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_odc.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_odc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_odc.c' object='libarchive/test/libarchive_test-test_read_format_cpio_odc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_odc.o `test -f 'libarchive/test/test_read_format_cpio_odc.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_odc.c + +libarchive/test/libarchive_test-test_read_format_cpio_odc.obj: libarchive/test/test_read_format_cpio_odc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_odc.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_odc.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_odc.obj `if test -f 'libarchive/test/test_read_format_cpio_odc.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_odc.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_odc.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_odc.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_odc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_odc.c' object='libarchive/test/libarchive_test-test_read_format_cpio_odc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_odc.obj `if test -f 'libarchive/test/test_read_format_cpio_odc.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_odc.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_odc.c'; fi` + +libarchive/test/libarchive_test-test_read_format_cpio_svr4_bzip2_rpm.o: libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_svr4_bzip2_rpm.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4_bzip2_rpm.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_svr4_bzip2_rpm.o `test -f 'libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4_bzip2_rpm.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4_bzip2_rpm.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c' object='libarchive/test/libarchive_test-test_read_format_cpio_svr4_bzip2_rpm.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_svr4_bzip2_rpm.o `test -f 'libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c + +libarchive/test/libarchive_test-test_read_format_cpio_svr4_bzip2_rpm.obj: libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_svr4_bzip2_rpm.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4_bzip2_rpm.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_svr4_bzip2_rpm.obj `if test -f 'libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4_bzip2_rpm.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4_bzip2_rpm.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c' object='libarchive/test/libarchive_test-test_read_format_cpio_svr4_bzip2_rpm.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_svr4_bzip2_rpm.obj `if test -f 'libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c'; fi` + +libarchive/test/libarchive_test-test_read_format_cpio_svr4_gzip.o: libarchive/test/test_read_format_cpio_svr4_gzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_svr4_gzip.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4_gzip.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_svr4_gzip.o `test -f 'libarchive/test/test_read_format_cpio_svr4_gzip.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_svr4_gzip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4_gzip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4_gzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_svr4_gzip.c' object='libarchive/test/libarchive_test-test_read_format_cpio_svr4_gzip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_svr4_gzip.o `test -f 'libarchive/test/test_read_format_cpio_svr4_gzip.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_svr4_gzip.c + +libarchive/test/libarchive_test-test_read_format_cpio_svr4_gzip.obj: libarchive/test/test_read_format_cpio_svr4_gzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_svr4_gzip.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4_gzip.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_svr4_gzip.obj `if test -f 'libarchive/test/test_read_format_cpio_svr4_gzip.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_svr4_gzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_svr4_gzip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4_gzip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4_gzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_svr4_gzip.c' object='libarchive/test/libarchive_test-test_read_format_cpio_svr4_gzip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_svr4_gzip.obj `if test -f 'libarchive/test/test_read_format_cpio_svr4_gzip.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_svr4_gzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_svr4_gzip.c'; fi` + +libarchive/test/libarchive_test-test_read_format_cpio_svr4_gzip_rpm.o: libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_svr4_gzip_rpm.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4_gzip_rpm.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_svr4_gzip_rpm.o `test -f 'libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4_gzip_rpm.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4_gzip_rpm.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c' object='libarchive/test/libarchive_test-test_read_format_cpio_svr4_gzip_rpm.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_svr4_gzip_rpm.o `test -f 'libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c + +libarchive/test/libarchive_test-test_read_format_cpio_svr4_gzip_rpm.obj: libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_svr4_gzip_rpm.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4_gzip_rpm.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_svr4_gzip_rpm.obj `if test -f 'libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4_gzip_rpm.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4_gzip_rpm.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c' object='libarchive/test/libarchive_test-test_read_format_cpio_svr4_gzip_rpm.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_svr4_gzip_rpm.obj `if test -f 'libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c'; fi` + +libarchive/test/libarchive_test-test_read_format_cpio_svr4c_Z.o: libarchive/test/test_read_format_cpio_svr4c_Z.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_svr4c_Z.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4c_Z.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_svr4c_Z.o `test -f 'libarchive/test/test_read_format_cpio_svr4c_Z.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_svr4c_Z.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4c_Z.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4c_Z.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_svr4c_Z.c' object='libarchive/test/libarchive_test-test_read_format_cpio_svr4c_Z.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_svr4c_Z.o `test -f 'libarchive/test/test_read_format_cpio_svr4c_Z.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_cpio_svr4c_Z.c + +libarchive/test/libarchive_test-test_read_format_cpio_svr4c_Z.obj: libarchive/test/test_read_format_cpio_svr4c_Z.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_cpio_svr4c_Z.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4c_Z.Tpo -c -o libarchive/test/libarchive_test-test_read_format_cpio_svr4c_Z.obj `if test -f 'libarchive/test/test_read_format_cpio_svr4c_Z.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_svr4c_Z.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_svr4c_Z.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4c_Z.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_cpio_svr4c_Z.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_cpio_svr4c_Z.c' object='libarchive/test/libarchive_test-test_read_format_cpio_svr4c_Z.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_cpio_svr4c_Z.obj `if test -f 'libarchive/test/test_read_format_cpio_svr4c_Z.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_cpio_svr4c_Z.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_cpio_svr4c_Z.c'; fi` + +libarchive/test/libarchive_test-test_read_format_empty.o: libarchive/test/test_read_format_empty.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_empty.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_empty.Tpo -c -o libarchive/test/libarchive_test-test_read_format_empty.o `test -f 'libarchive/test/test_read_format_empty.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_empty.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_empty.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_empty.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_empty.c' object='libarchive/test/libarchive_test-test_read_format_empty.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_empty.o `test -f 'libarchive/test/test_read_format_empty.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_empty.c + +libarchive/test/libarchive_test-test_read_format_empty.obj: libarchive/test/test_read_format_empty.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_empty.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_empty.Tpo -c -o libarchive/test/libarchive_test-test_read_format_empty.obj `if test -f 'libarchive/test/test_read_format_empty.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_empty.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_empty.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_empty.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_empty.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_empty.c' object='libarchive/test/libarchive_test-test_read_format_empty.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_empty.obj `if test -f 'libarchive/test/test_read_format_empty.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_empty.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_empty.c'; fi` + +libarchive/test/libarchive_test-test_read_format_gtar_filename.o: libarchive/test/test_read_format_gtar_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_gtar_filename.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_filename.Tpo -c -o libarchive/test/libarchive_test-test_read_format_gtar_filename.o `test -f 'libarchive/test/test_read_format_gtar_filename.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_gtar_filename.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_filename.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_gtar_filename.c' object='libarchive/test/libarchive_test-test_read_format_gtar_filename.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_gtar_filename.o `test -f 'libarchive/test/test_read_format_gtar_filename.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_gtar_filename.c + +libarchive/test/libarchive_test-test_read_format_gtar_filename.obj: libarchive/test/test_read_format_gtar_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_gtar_filename.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_filename.Tpo -c -o libarchive/test/libarchive_test-test_read_format_gtar_filename.obj `if test -f 'libarchive/test/test_read_format_gtar_filename.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_gtar_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_gtar_filename.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_filename.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_gtar_filename.c' object='libarchive/test/libarchive_test-test_read_format_gtar_filename.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_gtar_filename.obj `if test -f 'libarchive/test/test_read_format_gtar_filename.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_gtar_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_gtar_filename.c'; fi` + +libarchive/test/libarchive_test-test_read_format_gtar_gz.o: libarchive/test/test_read_format_gtar_gz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_gtar_gz.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_gz.Tpo -c -o libarchive/test/libarchive_test-test_read_format_gtar_gz.o `test -f 'libarchive/test/test_read_format_gtar_gz.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_gtar_gz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_gz.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_gz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_gtar_gz.c' object='libarchive/test/libarchive_test-test_read_format_gtar_gz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_gtar_gz.o `test -f 'libarchive/test/test_read_format_gtar_gz.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_gtar_gz.c + +libarchive/test/libarchive_test-test_read_format_gtar_gz.obj: libarchive/test/test_read_format_gtar_gz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_gtar_gz.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_gz.Tpo -c -o libarchive/test/libarchive_test-test_read_format_gtar_gz.obj `if test -f 'libarchive/test/test_read_format_gtar_gz.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_gtar_gz.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_gtar_gz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_gz.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_gz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_gtar_gz.c' object='libarchive/test/libarchive_test-test_read_format_gtar_gz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_gtar_gz.obj `if test -f 'libarchive/test/test_read_format_gtar_gz.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_gtar_gz.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_gtar_gz.c'; fi` + +libarchive/test/libarchive_test-test_read_format_gtar_lzma.o: libarchive/test/test_read_format_gtar_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_gtar_lzma.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_lzma.Tpo -c -o libarchive/test/libarchive_test-test_read_format_gtar_lzma.o `test -f 'libarchive/test/test_read_format_gtar_lzma.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_gtar_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_lzma.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_lzma.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_gtar_lzma.c' object='libarchive/test/libarchive_test-test_read_format_gtar_lzma.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_gtar_lzma.o `test -f 'libarchive/test/test_read_format_gtar_lzma.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_gtar_lzma.c + +libarchive/test/libarchive_test-test_read_format_gtar_lzma.obj: libarchive/test/test_read_format_gtar_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_gtar_lzma.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_lzma.Tpo -c -o libarchive/test/libarchive_test-test_read_format_gtar_lzma.obj `if test -f 'libarchive/test/test_read_format_gtar_lzma.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_gtar_lzma.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_gtar_lzma.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_lzma.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_lzma.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_gtar_lzma.c' object='libarchive/test/libarchive_test-test_read_format_gtar_lzma.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_gtar_lzma.obj `if test -f 'libarchive/test/test_read_format_gtar_lzma.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_gtar_lzma.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_gtar_lzma.c'; fi` + +libarchive/test/libarchive_test-test_read_format_gtar_sparse.o: libarchive/test/test_read_format_gtar_sparse.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_gtar_sparse.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_sparse.Tpo -c -o libarchive/test/libarchive_test-test_read_format_gtar_sparse.o `test -f 'libarchive/test/test_read_format_gtar_sparse.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_gtar_sparse.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_sparse.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_sparse.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_gtar_sparse.c' object='libarchive/test/libarchive_test-test_read_format_gtar_sparse.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_gtar_sparse.o `test -f 'libarchive/test/test_read_format_gtar_sparse.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_gtar_sparse.c + +libarchive/test/libarchive_test-test_read_format_gtar_sparse.obj: libarchive/test/test_read_format_gtar_sparse.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_gtar_sparse.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_sparse.Tpo -c -o libarchive/test/libarchive_test-test_read_format_gtar_sparse.obj `if test -f 'libarchive/test/test_read_format_gtar_sparse.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_gtar_sparse.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_gtar_sparse.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_sparse.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_sparse.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_gtar_sparse.c' object='libarchive/test/libarchive_test-test_read_format_gtar_sparse.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_gtar_sparse.obj `if test -f 'libarchive/test/test_read_format_gtar_sparse.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_gtar_sparse.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_gtar_sparse.c'; fi` + +libarchive/test/libarchive_test-test_read_format_gtar_sparse_skip_entry.o: libarchive/test/test_read_format_gtar_sparse_skip_entry.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_gtar_sparse_skip_entry.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_sparse_skip_entry.Tpo -c -o libarchive/test/libarchive_test-test_read_format_gtar_sparse_skip_entry.o `test -f 'libarchive/test/test_read_format_gtar_sparse_skip_entry.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_gtar_sparse_skip_entry.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_sparse_skip_entry.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_sparse_skip_entry.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_gtar_sparse_skip_entry.c' object='libarchive/test/libarchive_test-test_read_format_gtar_sparse_skip_entry.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_gtar_sparse_skip_entry.o `test -f 'libarchive/test/test_read_format_gtar_sparse_skip_entry.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_gtar_sparse_skip_entry.c + +libarchive/test/libarchive_test-test_read_format_gtar_sparse_skip_entry.obj: libarchive/test/test_read_format_gtar_sparse_skip_entry.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_gtar_sparse_skip_entry.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_sparse_skip_entry.Tpo -c -o libarchive/test/libarchive_test-test_read_format_gtar_sparse_skip_entry.obj `if test -f 'libarchive/test/test_read_format_gtar_sparse_skip_entry.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_gtar_sparse_skip_entry.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_gtar_sparse_skip_entry.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_sparse_skip_entry.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_gtar_sparse_skip_entry.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_gtar_sparse_skip_entry.c' object='libarchive/test/libarchive_test-test_read_format_gtar_sparse_skip_entry.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_gtar_sparse_skip_entry.obj `if test -f 'libarchive/test/test_read_format_gtar_sparse_skip_entry.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_gtar_sparse_skip_entry.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_gtar_sparse_skip_entry.c'; fi` + +libarchive/test/libarchive_test-test_read_format_iso_Z.o: libarchive/test/test_read_format_iso_Z.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_iso_Z.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_iso_Z.Tpo -c -o libarchive/test/libarchive_test-test_read_format_iso_Z.o `test -f 'libarchive/test/test_read_format_iso_Z.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_iso_Z.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_iso_Z.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_iso_Z.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_iso_Z.c' object='libarchive/test/libarchive_test-test_read_format_iso_Z.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_iso_Z.o `test -f 'libarchive/test/test_read_format_iso_Z.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_iso_Z.c + +libarchive/test/libarchive_test-test_read_format_iso_Z.obj: libarchive/test/test_read_format_iso_Z.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_iso_Z.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_iso_Z.Tpo -c -o libarchive/test/libarchive_test-test_read_format_iso_Z.obj `if test -f 'libarchive/test/test_read_format_iso_Z.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_iso_Z.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_iso_Z.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_iso_Z.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_iso_Z.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_iso_Z.c' object='libarchive/test/libarchive_test-test_read_format_iso_Z.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_iso_Z.obj `if test -f 'libarchive/test/test_read_format_iso_Z.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_iso_Z.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_iso_Z.c'; fi` + +libarchive/test/libarchive_test-test_read_format_iso_multi_extent.o: libarchive/test/test_read_format_iso_multi_extent.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_iso_multi_extent.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_iso_multi_extent.Tpo -c -o libarchive/test/libarchive_test-test_read_format_iso_multi_extent.o `test -f 'libarchive/test/test_read_format_iso_multi_extent.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_iso_multi_extent.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_iso_multi_extent.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_iso_multi_extent.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_iso_multi_extent.c' object='libarchive/test/libarchive_test-test_read_format_iso_multi_extent.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_iso_multi_extent.o `test -f 'libarchive/test/test_read_format_iso_multi_extent.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_iso_multi_extent.c + +libarchive/test/libarchive_test-test_read_format_iso_multi_extent.obj: libarchive/test/test_read_format_iso_multi_extent.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_iso_multi_extent.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_iso_multi_extent.Tpo -c -o libarchive/test/libarchive_test-test_read_format_iso_multi_extent.obj `if test -f 'libarchive/test/test_read_format_iso_multi_extent.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_iso_multi_extent.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_iso_multi_extent.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_iso_multi_extent.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_iso_multi_extent.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_iso_multi_extent.c' object='libarchive/test/libarchive_test-test_read_format_iso_multi_extent.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_iso_multi_extent.obj `if test -f 'libarchive/test/test_read_format_iso_multi_extent.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_iso_multi_extent.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_iso_multi_extent.c'; fi` + +libarchive/test/libarchive_test-test_read_format_iso_xorriso.o: libarchive/test/test_read_format_iso_xorriso.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_iso_xorriso.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_iso_xorriso.Tpo -c -o libarchive/test/libarchive_test-test_read_format_iso_xorriso.o `test -f 'libarchive/test/test_read_format_iso_xorriso.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_iso_xorriso.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_iso_xorriso.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_iso_xorriso.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_iso_xorriso.c' object='libarchive/test/libarchive_test-test_read_format_iso_xorriso.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_iso_xorriso.o `test -f 'libarchive/test/test_read_format_iso_xorriso.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_iso_xorriso.c + +libarchive/test/libarchive_test-test_read_format_iso_xorriso.obj: libarchive/test/test_read_format_iso_xorriso.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_iso_xorriso.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_iso_xorriso.Tpo -c -o libarchive/test/libarchive_test-test_read_format_iso_xorriso.obj `if test -f 'libarchive/test/test_read_format_iso_xorriso.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_iso_xorriso.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_iso_xorriso.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_iso_xorriso.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_iso_xorriso.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_iso_xorriso.c' object='libarchive/test/libarchive_test-test_read_format_iso_xorriso.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_iso_xorriso.obj `if test -f 'libarchive/test/test_read_format_iso_xorriso.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_iso_xorriso.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_iso_xorriso.c'; fi` + +libarchive/test/libarchive_test-test_read_format_isojoliet_bz2.o: libarchive/test/test_read_format_isojoliet_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_isojoliet_bz2.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_bz2.Tpo -c -o libarchive/test/libarchive_test-test_read_format_isojoliet_bz2.o `test -f 'libarchive/test/test_read_format_isojoliet_bz2.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_isojoliet_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_bz2.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_bz2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_isojoliet_bz2.c' object='libarchive/test/libarchive_test-test_read_format_isojoliet_bz2.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_isojoliet_bz2.o `test -f 'libarchive/test/test_read_format_isojoliet_bz2.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_isojoliet_bz2.c + +libarchive/test/libarchive_test-test_read_format_isojoliet_bz2.obj: libarchive/test/test_read_format_isojoliet_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_isojoliet_bz2.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_bz2.Tpo -c -o libarchive/test/libarchive_test-test_read_format_isojoliet_bz2.obj `if test -f 'libarchive/test/test_read_format_isojoliet_bz2.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_isojoliet_bz2.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_isojoliet_bz2.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_bz2.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_bz2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_isojoliet_bz2.c' object='libarchive/test/libarchive_test-test_read_format_isojoliet_bz2.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_isojoliet_bz2.obj `if test -f 'libarchive/test/test_read_format_isojoliet_bz2.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_isojoliet_bz2.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_isojoliet_bz2.c'; fi` + +libarchive/test/libarchive_test-test_read_format_isojoliet_long.o: libarchive/test/test_read_format_isojoliet_long.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_isojoliet_long.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_long.Tpo -c -o libarchive/test/libarchive_test-test_read_format_isojoliet_long.o `test -f 'libarchive/test/test_read_format_isojoliet_long.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_isojoliet_long.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_long.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_long.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_isojoliet_long.c' object='libarchive/test/libarchive_test-test_read_format_isojoliet_long.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_isojoliet_long.o `test -f 'libarchive/test/test_read_format_isojoliet_long.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_isojoliet_long.c + +libarchive/test/libarchive_test-test_read_format_isojoliet_long.obj: libarchive/test/test_read_format_isojoliet_long.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_isojoliet_long.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_long.Tpo -c -o libarchive/test/libarchive_test-test_read_format_isojoliet_long.obj `if test -f 'libarchive/test/test_read_format_isojoliet_long.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_isojoliet_long.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_isojoliet_long.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_long.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_long.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_isojoliet_long.c' object='libarchive/test/libarchive_test-test_read_format_isojoliet_long.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_isojoliet_long.obj `if test -f 'libarchive/test/test_read_format_isojoliet_long.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_isojoliet_long.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_isojoliet_long.c'; fi` + +libarchive/test/libarchive_test-test_read_format_isojoliet_rr.o: libarchive/test/test_read_format_isojoliet_rr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_isojoliet_rr.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_rr.Tpo -c -o libarchive/test/libarchive_test-test_read_format_isojoliet_rr.o `test -f 'libarchive/test/test_read_format_isojoliet_rr.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_isojoliet_rr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_rr.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_rr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_isojoliet_rr.c' object='libarchive/test/libarchive_test-test_read_format_isojoliet_rr.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_isojoliet_rr.o `test -f 'libarchive/test/test_read_format_isojoliet_rr.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_isojoliet_rr.c + +libarchive/test/libarchive_test-test_read_format_isojoliet_rr.obj: libarchive/test/test_read_format_isojoliet_rr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_isojoliet_rr.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_rr.Tpo -c -o libarchive/test/libarchive_test-test_read_format_isojoliet_rr.obj `if test -f 'libarchive/test/test_read_format_isojoliet_rr.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_isojoliet_rr.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_isojoliet_rr.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_rr.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_rr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_isojoliet_rr.c' object='libarchive/test/libarchive_test-test_read_format_isojoliet_rr.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_isojoliet_rr.obj `if test -f 'libarchive/test/test_read_format_isojoliet_rr.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_isojoliet_rr.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_isojoliet_rr.c'; fi` + +libarchive/test/libarchive_test-test_read_format_isojoliet_versioned.o: libarchive/test/test_read_format_isojoliet_versioned.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_isojoliet_versioned.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_versioned.Tpo -c -o libarchive/test/libarchive_test-test_read_format_isojoliet_versioned.o `test -f 'libarchive/test/test_read_format_isojoliet_versioned.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_isojoliet_versioned.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_versioned.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_versioned.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_isojoliet_versioned.c' object='libarchive/test/libarchive_test-test_read_format_isojoliet_versioned.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_isojoliet_versioned.o `test -f 'libarchive/test/test_read_format_isojoliet_versioned.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_isojoliet_versioned.c + +libarchive/test/libarchive_test-test_read_format_isojoliet_versioned.obj: libarchive/test/test_read_format_isojoliet_versioned.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_isojoliet_versioned.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_versioned.Tpo -c -o libarchive/test/libarchive_test-test_read_format_isojoliet_versioned.obj `if test -f 'libarchive/test/test_read_format_isojoliet_versioned.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_isojoliet_versioned.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_isojoliet_versioned.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_versioned.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isojoliet_versioned.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_isojoliet_versioned.c' object='libarchive/test/libarchive_test-test_read_format_isojoliet_versioned.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_isojoliet_versioned.obj `if test -f 'libarchive/test/test_read_format_isojoliet_versioned.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_isojoliet_versioned.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_isojoliet_versioned.c'; fi` + +libarchive/test/libarchive_test-test_read_format_isorr_bz2.o: libarchive/test/test_read_format_isorr_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_isorr_bz2.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_bz2.Tpo -c -o libarchive/test/libarchive_test-test_read_format_isorr_bz2.o `test -f 'libarchive/test/test_read_format_isorr_bz2.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_isorr_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_bz2.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_bz2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_isorr_bz2.c' object='libarchive/test/libarchive_test-test_read_format_isorr_bz2.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_isorr_bz2.o `test -f 'libarchive/test/test_read_format_isorr_bz2.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_isorr_bz2.c + +libarchive/test/libarchive_test-test_read_format_isorr_bz2.obj: libarchive/test/test_read_format_isorr_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_isorr_bz2.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_bz2.Tpo -c -o libarchive/test/libarchive_test-test_read_format_isorr_bz2.obj `if test -f 'libarchive/test/test_read_format_isorr_bz2.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_isorr_bz2.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_isorr_bz2.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_bz2.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_bz2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_isorr_bz2.c' object='libarchive/test/libarchive_test-test_read_format_isorr_bz2.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_isorr_bz2.obj `if test -f 'libarchive/test/test_read_format_isorr_bz2.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_isorr_bz2.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_isorr_bz2.c'; fi` + +libarchive/test/libarchive_test-test_read_format_isorr_ce.o: libarchive/test/test_read_format_isorr_ce.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_isorr_ce.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_ce.Tpo -c -o libarchive/test/libarchive_test-test_read_format_isorr_ce.o `test -f 'libarchive/test/test_read_format_isorr_ce.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_isorr_ce.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_ce.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_ce.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_isorr_ce.c' object='libarchive/test/libarchive_test-test_read_format_isorr_ce.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_isorr_ce.o `test -f 'libarchive/test/test_read_format_isorr_ce.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_isorr_ce.c + +libarchive/test/libarchive_test-test_read_format_isorr_ce.obj: libarchive/test/test_read_format_isorr_ce.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_isorr_ce.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_ce.Tpo -c -o libarchive/test/libarchive_test-test_read_format_isorr_ce.obj `if test -f 'libarchive/test/test_read_format_isorr_ce.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_isorr_ce.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_isorr_ce.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_ce.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_ce.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_isorr_ce.c' object='libarchive/test/libarchive_test-test_read_format_isorr_ce.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_isorr_ce.obj `if test -f 'libarchive/test/test_read_format_isorr_ce.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_isorr_ce.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_isorr_ce.c'; fi` + +libarchive/test/libarchive_test-test_read_format_isorr_new_bz2.o: libarchive/test/test_read_format_isorr_new_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_isorr_new_bz2.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_new_bz2.Tpo -c -o libarchive/test/libarchive_test-test_read_format_isorr_new_bz2.o `test -f 'libarchive/test/test_read_format_isorr_new_bz2.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_isorr_new_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_new_bz2.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_new_bz2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_isorr_new_bz2.c' object='libarchive/test/libarchive_test-test_read_format_isorr_new_bz2.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_isorr_new_bz2.o `test -f 'libarchive/test/test_read_format_isorr_new_bz2.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_isorr_new_bz2.c + +libarchive/test/libarchive_test-test_read_format_isorr_new_bz2.obj: libarchive/test/test_read_format_isorr_new_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_isorr_new_bz2.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_new_bz2.Tpo -c -o libarchive/test/libarchive_test-test_read_format_isorr_new_bz2.obj `if test -f 'libarchive/test/test_read_format_isorr_new_bz2.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_isorr_new_bz2.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_isorr_new_bz2.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_new_bz2.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_new_bz2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_isorr_new_bz2.c' object='libarchive/test/libarchive_test-test_read_format_isorr_new_bz2.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_isorr_new_bz2.obj `if test -f 'libarchive/test/test_read_format_isorr_new_bz2.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_isorr_new_bz2.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_isorr_new_bz2.c'; fi` + +libarchive/test/libarchive_test-test_read_format_isorr_rr_moved.o: libarchive/test/test_read_format_isorr_rr_moved.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_isorr_rr_moved.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_rr_moved.Tpo -c -o libarchive/test/libarchive_test-test_read_format_isorr_rr_moved.o `test -f 'libarchive/test/test_read_format_isorr_rr_moved.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_isorr_rr_moved.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_rr_moved.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_rr_moved.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_isorr_rr_moved.c' object='libarchive/test/libarchive_test-test_read_format_isorr_rr_moved.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_isorr_rr_moved.o `test -f 'libarchive/test/test_read_format_isorr_rr_moved.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_isorr_rr_moved.c + +libarchive/test/libarchive_test-test_read_format_isorr_rr_moved.obj: libarchive/test/test_read_format_isorr_rr_moved.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_isorr_rr_moved.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_rr_moved.Tpo -c -o libarchive/test/libarchive_test-test_read_format_isorr_rr_moved.obj `if test -f 'libarchive/test/test_read_format_isorr_rr_moved.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_isorr_rr_moved.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_isorr_rr_moved.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_rr_moved.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isorr_rr_moved.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_isorr_rr_moved.c' object='libarchive/test/libarchive_test-test_read_format_isorr_rr_moved.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_isorr_rr_moved.obj `if test -f 'libarchive/test/test_read_format_isorr_rr_moved.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_isorr_rr_moved.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_isorr_rr_moved.c'; fi` + +libarchive/test/libarchive_test-test_read_format_isozisofs_bz2.o: libarchive/test/test_read_format_isozisofs_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_isozisofs_bz2.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isozisofs_bz2.Tpo -c -o libarchive/test/libarchive_test-test_read_format_isozisofs_bz2.o `test -f 'libarchive/test/test_read_format_isozisofs_bz2.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_isozisofs_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isozisofs_bz2.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isozisofs_bz2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_isozisofs_bz2.c' object='libarchive/test/libarchive_test-test_read_format_isozisofs_bz2.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_isozisofs_bz2.o `test -f 'libarchive/test/test_read_format_isozisofs_bz2.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_isozisofs_bz2.c + +libarchive/test/libarchive_test-test_read_format_isozisofs_bz2.obj: libarchive/test/test_read_format_isozisofs_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_isozisofs_bz2.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isozisofs_bz2.Tpo -c -o libarchive/test/libarchive_test-test_read_format_isozisofs_bz2.obj `if test -f 'libarchive/test/test_read_format_isozisofs_bz2.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_isozisofs_bz2.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_isozisofs_bz2.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isozisofs_bz2.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_isozisofs_bz2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_isozisofs_bz2.c' object='libarchive/test/libarchive_test-test_read_format_isozisofs_bz2.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_isozisofs_bz2.obj `if test -f 'libarchive/test/test_read_format_isozisofs_bz2.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_isozisofs_bz2.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_isozisofs_bz2.c'; fi` + +libarchive/test/libarchive_test-test_read_format_lha.o: libarchive/test/test_read_format_lha.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_lha.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha.Tpo -c -o libarchive/test/libarchive_test-test_read_format_lha.o `test -f 'libarchive/test/test_read_format_lha.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_lha.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_lha.c' object='libarchive/test/libarchive_test-test_read_format_lha.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_lha.o `test -f 'libarchive/test/test_read_format_lha.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_lha.c + +libarchive/test/libarchive_test-test_read_format_lha.obj: libarchive/test/test_read_format_lha.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_lha.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha.Tpo -c -o libarchive/test/libarchive_test-test_read_format_lha.obj `if test -f 'libarchive/test/test_read_format_lha.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_lha.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_lha.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_lha.c' object='libarchive/test/libarchive_test-test_read_format_lha.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_lha.obj `if test -f 'libarchive/test/test_read_format_lha.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_lha.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_lha.c'; fi` + +libarchive/test/libarchive_test-test_read_format_lha_bugfix_0.o: libarchive/test/test_read_format_lha_bugfix_0.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_lha_bugfix_0.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha_bugfix_0.Tpo -c -o libarchive/test/libarchive_test-test_read_format_lha_bugfix_0.o `test -f 'libarchive/test/test_read_format_lha_bugfix_0.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_lha_bugfix_0.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha_bugfix_0.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha_bugfix_0.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_lha_bugfix_0.c' object='libarchive/test/libarchive_test-test_read_format_lha_bugfix_0.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_lha_bugfix_0.o `test -f 'libarchive/test/test_read_format_lha_bugfix_0.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_lha_bugfix_0.c + +libarchive/test/libarchive_test-test_read_format_lha_bugfix_0.obj: libarchive/test/test_read_format_lha_bugfix_0.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_lha_bugfix_0.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha_bugfix_0.Tpo -c -o libarchive/test/libarchive_test-test_read_format_lha_bugfix_0.obj `if test -f 'libarchive/test/test_read_format_lha_bugfix_0.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_lha_bugfix_0.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_lha_bugfix_0.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha_bugfix_0.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha_bugfix_0.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_lha_bugfix_0.c' object='libarchive/test/libarchive_test-test_read_format_lha_bugfix_0.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_lha_bugfix_0.obj `if test -f 'libarchive/test/test_read_format_lha_bugfix_0.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_lha_bugfix_0.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_lha_bugfix_0.c'; fi` + +libarchive/test/libarchive_test-test_read_format_lha_filename.o: libarchive/test/test_read_format_lha_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_lha_filename.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha_filename.Tpo -c -o libarchive/test/libarchive_test-test_read_format_lha_filename.o `test -f 'libarchive/test/test_read_format_lha_filename.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_lha_filename.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha_filename.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_lha_filename.c' object='libarchive/test/libarchive_test-test_read_format_lha_filename.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_lha_filename.o `test -f 'libarchive/test/test_read_format_lha_filename.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_lha_filename.c + +libarchive/test/libarchive_test-test_read_format_lha_filename.obj: libarchive/test/test_read_format_lha_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_lha_filename.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha_filename.Tpo -c -o libarchive/test/libarchive_test-test_read_format_lha_filename.obj `if test -f 'libarchive/test/test_read_format_lha_filename.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_lha_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_lha_filename.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha_filename.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_lha_filename.c' object='libarchive/test/libarchive_test-test_read_format_lha_filename.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_lha_filename.obj `if test -f 'libarchive/test/test_read_format_lha_filename.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_lha_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_lha_filename.c'; fi` + +libarchive/test/libarchive_test-test_read_format_lha_filename_utf16.o: libarchive/test/test_read_format_lha_filename_utf16.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_lha_filename_utf16.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha_filename_utf16.Tpo -c -o libarchive/test/libarchive_test-test_read_format_lha_filename_utf16.o `test -f 'libarchive/test/test_read_format_lha_filename_utf16.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_lha_filename_utf16.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha_filename_utf16.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha_filename_utf16.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_lha_filename_utf16.c' object='libarchive/test/libarchive_test-test_read_format_lha_filename_utf16.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_lha_filename_utf16.o `test -f 'libarchive/test/test_read_format_lha_filename_utf16.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_lha_filename_utf16.c + +libarchive/test/libarchive_test-test_read_format_lha_filename_utf16.obj: libarchive/test/test_read_format_lha_filename_utf16.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_lha_filename_utf16.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha_filename_utf16.Tpo -c -o libarchive/test/libarchive_test-test_read_format_lha_filename_utf16.obj `if test -f 'libarchive/test/test_read_format_lha_filename_utf16.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_lha_filename_utf16.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_lha_filename_utf16.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha_filename_utf16.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_lha_filename_utf16.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_lha_filename_utf16.c' object='libarchive/test/libarchive_test-test_read_format_lha_filename_utf16.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_lha_filename_utf16.obj `if test -f 'libarchive/test/test_read_format_lha_filename_utf16.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_lha_filename_utf16.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_lha_filename_utf16.c'; fi` + +libarchive/test/libarchive_test-test_read_format_mtree.o: libarchive/test/test_read_format_mtree.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_mtree.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_mtree.Tpo -c -o libarchive/test/libarchive_test-test_read_format_mtree.o `test -f 'libarchive/test/test_read_format_mtree.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_mtree.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_mtree.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_mtree.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_mtree.c' object='libarchive/test/libarchive_test-test_read_format_mtree.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_mtree.o `test -f 'libarchive/test/test_read_format_mtree.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_mtree.c + +libarchive/test/libarchive_test-test_read_format_mtree.obj: libarchive/test/test_read_format_mtree.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_mtree.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_mtree.Tpo -c -o libarchive/test/libarchive_test-test_read_format_mtree.obj `if test -f 'libarchive/test/test_read_format_mtree.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_mtree.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_mtree.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_mtree.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_mtree.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_mtree.c' object='libarchive/test/libarchive_test-test_read_format_mtree.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_mtree.obj `if test -f 'libarchive/test/test_read_format_mtree.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_mtree.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_mtree.c'; fi` + +libarchive/test/libarchive_test-test_read_format_mtree_crash747.o: libarchive/test/test_read_format_mtree_crash747.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_mtree_crash747.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_mtree_crash747.Tpo -c -o libarchive/test/libarchive_test-test_read_format_mtree_crash747.o `test -f 'libarchive/test/test_read_format_mtree_crash747.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_mtree_crash747.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_mtree_crash747.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_mtree_crash747.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_mtree_crash747.c' object='libarchive/test/libarchive_test-test_read_format_mtree_crash747.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_mtree_crash747.o `test -f 'libarchive/test/test_read_format_mtree_crash747.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_mtree_crash747.c + +libarchive/test/libarchive_test-test_read_format_mtree_crash747.obj: libarchive/test/test_read_format_mtree_crash747.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_mtree_crash747.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_mtree_crash747.Tpo -c -o libarchive/test/libarchive_test-test_read_format_mtree_crash747.obj `if test -f 'libarchive/test/test_read_format_mtree_crash747.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_mtree_crash747.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_mtree_crash747.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_mtree_crash747.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_mtree_crash747.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_mtree_crash747.c' object='libarchive/test/libarchive_test-test_read_format_mtree_crash747.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_mtree_crash747.obj `if test -f 'libarchive/test/test_read_format_mtree_crash747.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_mtree_crash747.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_mtree_crash747.c'; fi` + +libarchive/test/libarchive_test-test_read_format_pax_bz2.o: libarchive/test/test_read_format_pax_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_pax_bz2.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_pax_bz2.Tpo -c -o libarchive/test/libarchive_test-test_read_format_pax_bz2.o `test -f 'libarchive/test/test_read_format_pax_bz2.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_pax_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_pax_bz2.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_pax_bz2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_pax_bz2.c' object='libarchive/test/libarchive_test-test_read_format_pax_bz2.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_pax_bz2.o `test -f 'libarchive/test/test_read_format_pax_bz2.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_pax_bz2.c + +libarchive/test/libarchive_test-test_read_format_pax_bz2.obj: libarchive/test/test_read_format_pax_bz2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_pax_bz2.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_pax_bz2.Tpo -c -o libarchive/test/libarchive_test-test_read_format_pax_bz2.obj `if test -f 'libarchive/test/test_read_format_pax_bz2.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_pax_bz2.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_pax_bz2.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_pax_bz2.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_pax_bz2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_pax_bz2.c' object='libarchive/test/libarchive_test-test_read_format_pax_bz2.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_pax_bz2.obj `if test -f 'libarchive/test/test_read_format_pax_bz2.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_pax_bz2.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_pax_bz2.c'; fi` + +libarchive/test/libarchive_test-test_read_format_rar.o: libarchive/test/test_read_format_rar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_rar.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar.Tpo -c -o libarchive/test/libarchive_test-test_read_format_rar.o `test -f 'libarchive/test/test_read_format_rar.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_rar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_rar.c' object='libarchive/test/libarchive_test-test_read_format_rar.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_rar.o `test -f 'libarchive/test/test_read_format_rar.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_rar.c + +libarchive/test/libarchive_test-test_read_format_rar.obj: libarchive/test/test_read_format_rar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_rar.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar.Tpo -c -o libarchive/test/libarchive_test-test_read_format_rar.obj `if test -f 'libarchive/test/test_read_format_rar.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_rar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_rar.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_rar.c' object='libarchive/test/libarchive_test-test_read_format_rar.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_rar.obj `if test -f 'libarchive/test/test_read_format_rar.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_rar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_rar.c'; fi` + +libarchive/test/libarchive_test-test_read_format_rar_encryption_data.o: libarchive/test/test_read_format_rar_encryption_data.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_rar_encryption_data.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_encryption_data.Tpo -c -o libarchive/test/libarchive_test-test_read_format_rar_encryption_data.o `test -f 'libarchive/test/test_read_format_rar_encryption_data.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_rar_encryption_data.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_encryption_data.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_encryption_data.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_rar_encryption_data.c' object='libarchive/test/libarchive_test-test_read_format_rar_encryption_data.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_rar_encryption_data.o `test -f 'libarchive/test/test_read_format_rar_encryption_data.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_rar_encryption_data.c + +libarchive/test/libarchive_test-test_read_format_rar_encryption_data.obj: libarchive/test/test_read_format_rar_encryption_data.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_rar_encryption_data.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_encryption_data.Tpo -c -o libarchive/test/libarchive_test-test_read_format_rar_encryption_data.obj `if test -f 'libarchive/test/test_read_format_rar_encryption_data.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_rar_encryption_data.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_rar_encryption_data.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_encryption_data.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_encryption_data.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_rar_encryption_data.c' object='libarchive/test/libarchive_test-test_read_format_rar_encryption_data.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_rar_encryption_data.obj `if test -f 'libarchive/test/test_read_format_rar_encryption_data.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_rar_encryption_data.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_rar_encryption_data.c'; fi` + +libarchive/test/libarchive_test-test_read_format_rar_encryption_partially.o: libarchive/test/test_read_format_rar_encryption_partially.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_rar_encryption_partially.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_encryption_partially.Tpo -c -o libarchive/test/libarchive_test-test_read_format_rar_encryption_partially.o `test -f 'libarchive/test/test_read_format_rar_encryption_partially.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_rar_encryption_partially.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_encryption_partially.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_encryption_partially.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_rar_encryption_partially.c' object='libarchive/test/libarchive_test-test_read_format_rar_encryption_partially.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_rar_encryption_partially.o `test -f 'libarchive/test/test_read_format_rar_encryption_partially.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_rar_encryption_partially.c + +libarchive/test/libarchive_test-test_read_format_rar_encryption_partially.obj: libarchive/test/test_read_format_rar_encryption_partially.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_rar_encryption_partially.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_encryption_partially.Tpo -c -o libarchive/test/libarchive_test-test_read_format_rar_encryption_partially.obj `if test -f 'libarchive/test/test_read_format_rar_encryption_partially.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_rar_encryption_partially.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_rar_encryption_partially.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_encryption_partially.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_encryption_partially.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_rar_encryption_partially.c' object='libarchive/test/libarchive_test-test_read_format_rar_encryption_partially.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_rar_encryption_partially.obj `if test -f 'libarchive/test/test_read_format_rar_encryption_partially.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_rar_encryption_partially.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_rar_encryption_partially.c'; fi` + +libarchive/test/libarchive_test-test_read_format_rar_encryption_header.o: libarchive/test/test_read_format_rar_encryption_header.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_rar_encryption_header.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_encryption_header.Tpo -c -o libarchive/test/libarchive_test-test_read_format_rar_encryption_header.o `test -f 'libarchive/test/test_read_format_rar_encryption_header.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_rar_encryption_header.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_encryption_header.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_encryption_header.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_rar_encryption_header.c' object='libarchive/test/libarchive_test-test_read_format_rar_encryption_header.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_rar_encryption_header.o `test -f 'libarchive/test/test_read_format_rar_encryption_header.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_rar_encryption_header.c + +libarchive/test/libarchive_test-test_read_format_rar_encryption_header.obj: libarchive/test/test_read_format_rar_encryption_header.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_rar_encryption_header.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_encryption_header.Tpo -c -o libarchive/test/libarchive_test-test_read_format_rar_encryption_header.obj `if test -f 'libarchive/test/test_read_format_rar_encryption_header.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_rar_encryption_header.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_rar_encryption_header.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_encryption_header.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_encryption_header.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_rar_encryption_header.c' object='libarchive/test/libarchive_test-test_read_format_rar_encryption_header.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_rar_encryption_header.obj `if test -f 'libarchive/test/test_read_format_rar_encryption_header.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_rar_encryption_header.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_rar_encryption_header.c'; fi` + +libarchive/test/libarchive_test-test_read_format_rar_invalid1.o: libarchive/test/test_read_format_rar_invalid1.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_rar_invalid1.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_invalid1.Tpo -c -o libarchive/test/libarchive_test-test_read_format_rar_invalid1.o `test -f 'libarchive/test/test_read_format_rar_invalid1.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_rar_invalid1.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_invalid1.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_invalid1.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_rar_invalid1.c' object='libarchive/test/libarchive_test-test_read_format_rar_invalid1.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_rar_invalid1.o `test -f 'libarchive/test/test_read_format_rar_invalid1.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_rar_invalid1.c + +libarchive/test/libarchive_test-test_read_format_rar_invalid1.obj: libarchive/test/test_read_format_rar_invalid1.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_rar_invalid1.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_invalid1.Tpo -c -o libarchive/test/libarchive_test-test_read_format_rar_invalid1.obj `if test -f 'libarchive/test/test_read_format_rar_invalid1.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_rar_invalid1.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_rar_invalid1.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_invalid1.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar_invalid1.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_rar_invalid1.c' object='libarchive/test/libarchive_test-test_read_format_rar_invalid1.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_rar_invalid1.obj `if test -f 'libarchive/test/test_read_format_rar_invalid1.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_rar_invalid1.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_rar_invalid1.c'; fi` + +libarchive/test/libarchive_test-test_read_format_rar5.o: libarchive/test/test_read_format_rar5.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_rar5.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar5.Tpo -c -o libarchive/test/libarchive_test-test_read_format_rar5.o `test -f 'libarchive/test/test_read_format_rar5.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_rar5.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar5.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar5.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_rar5.c' object='libarchive/test/libarchive_test-test_read_format_rar5.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_rar5.o `test -f 'libarchive/test/test_read_format_rar5.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_rar5.c + +libarchive/test/libarchive_test-test_read_format_rar5.obj: libarchive/test/test_read_format_rar5.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_rar5.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar5.Tpo -c -o libarchive/test/libarchive_test-test_read_format_rar5.obj `if test -f 'libarchive/test/test_read_format_rar5.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_rar5.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_rar5.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar5.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_rar5.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_rar5.c' object='libarchive/test/libarchive_test-test_read_format_rar5.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_rar5.obj `if test -f 'libarchive/test/test_read_format_rar5.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_rar5.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_rar5.c'; fi` + +libarchive/test/libarchive_test-test_read_format_raw.o: libarchive/test/test_read_format_raw.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_raw.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_raw.Tpo -c -o libarchive/test/libarchive_test-test_read_format_raw.o `test -f 'libarchive/test/test_read_format_raw.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_raw.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_raw.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_raw.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_raw.c' object='libarchive/test/libarchive_test-test_read_format_raw.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_raw.o `test -f 'libarchive/test/test_read_format_raw.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_raw.c + +libarchive/test/libarchive_test-test_read_format_raw.obj: libarchive/test/test_read_format_raw.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_raw.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_raw.Tpo -c -o libarchive/test/libarchive_test-test_read_format_raw.obj `if test -f 'libarchive/test/test_read_format_raw.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_raw.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_raw.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_raw.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_raw.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_raw.c' object='libarchive/test/libarchive_test-test_read_format_raw.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_raw.obj `if test -f 'libarchive/test/test_read_format_raw.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_raw.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_raw.c'; fi` + +libarchive/test/libarchive_test-test_read_format_tar.o: libarchive/test/test_read_format_tar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_tar.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar.Tpo -c -o libarchive/test/libarchive_test-test_read_format_tar.o `test -f 'libarchive/test/test_read_format_tar.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_tar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_tar.c' object='libarchive/test/libarchive_test-test_read_format_tar.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_tar.o `test -f 'libarchive/test/test_read_format_tar.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_tar.c + +libarchive/test/libarchive_test-test_read_format_tar.obj: libarchive/test/test_read_format_tar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_tar.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar.Tpo -c -o libarchive/test/libarchive_test-test_read_format_tar.obj `if test -f 'libarchive/test/test_read_format_tar.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_tar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_tar.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_tar.c' object='libarchive/test/libarchive_test-test_read_format_tar.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_tar.obj `if test -f 'libarchive/test/test_read_format_tar.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_tar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_tar.c'; fi` + +libarchive/test/libarchive_test-test_read_format_tar_concatenated.o: libarchive/test/test_read_format_tar_concatenated.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_tar_concatenated.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_concatenated.Tpo -c -o libarchive/test/libarchive_test-test_read_format_tar_concatenated.o `test -f 'libarchive/test/test_read_format_tar_concatenated.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_tar_concatenated.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_concatenated.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_concatenated.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_tar_concatenated.c' object='libarchive/test/libarchive_test-test_read_format_tar_concatenated.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_tar_concatenated.o `test -f 'libarchive/test/test_read_format_tar_concatenated.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_tar_concatenated.c + +libarchive/test/libarchive_test-test_read_format_tar_concatenated.obj: libarchive/test/test_read_format_tar_concatenated.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_tar_concatenated.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_concatenated.Tpo -c -o libarchive/test/libarchive_test-test_read_format_tar_concatenated.obj `if test -f 'libarchive/test/test_read_format_tar_concatenated.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_tar_concatenated.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_tar_concatenated.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_concatenated.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_concatenated.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_tar_concatenated.c' object='libarchive/test/libarchive_test-test_read_format_tar_concatenated.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_tar_concatenated.obj `if test -f 'libarchive/test/test_read_format_tar_concatenated.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_tar_concatenated.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_tar_concatenated.c'; fi` + +libarchive/test/libarchive_test-test_read_format_tar_empty_pax.o: libarchive/test/test_read_format_tar_empty_pax.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_tar_empty_pax.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_empty_pax.Tpo -c -o libarchive/test/libarchive_test-test_read_format_tar_empty_pax.o `test -f 'libarchive/test/test_read_format_tar_empty_pax.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_tar_empty_pax.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_empty_pax.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_empty_pax.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_tar_empty_pax.c' object='libarchive/test/libarchive_test-test_read_format_tar_empty_pax.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_tar_empty_pax.o `test -f 'libarchive/test/test_read_format_tar_empty_pax.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_tar_empty_pax.c + +libarchive/test/libarchive_test-test_read_format_tar_empty_pax.obj: libarchive/test/test_read_format_tar_empty_pax.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_tar_empty_pax.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_empty_pax.Tpo -c -o libarchive/test/libarchive_test-test_read_format_tar_empty_pax.obj `if test -f 'libarchive/test/test_read_format_tar_empty_pax.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_tar_empty_pax.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_tar_empty_pax.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_empty_pax.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_empty_pax.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_tar_empty_pax.c' object='libarchive/test/libarchive_test-test_read_format_tar_empty_pax.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_tar_empty_pax.obj `if test -f 'libarchive/test/test_read_format_tar_empty_pax.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_tar_empty_pax.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_tar_empty_pax.c'; fi` + +libarchive/test/libarchive_test-test_read_format_tar_empty_filename.o: libarchive/test/test_read_format_tar_empty_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_tar_empty_filename.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_empty_filename.Tpo -c -o libarchive/test/libarchive_test-test_read_format_tar_empty_filename.o `test -f 'libarchive/test/test_read_format_tar_empty_filename.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_tar_empty_filename.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_empty_filename.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_empty_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_tar_empty_filename.c' object='libarchive/test/libarchive_test-test_read_format_tar_empty_filename.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_tar_empty_filename.o `test -f 'libarchive/test/test_read_format_tar_empty_filename.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_tar_empty_filename.c + +libarchive/test/libarchive_test-test_read_format_tar_empty_filename.obj: libarchive/test/test_read_format_tar_empty_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_tar_empty_filename.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_empty_filename.Tpo -c -o libarchive/test/libarchive_test-test_read_format_tar_empty_filename.obj `if test -f 'libarchive/test/test_read_format_tar_empty_filename.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_tar_empty_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_tar_empty_filename.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_empty_filename.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_empty_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_tar_empty_filename.c' object='libarchive/test/libarchive_test-test_read_format_tar_empty_filename.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_tar_empty_filename.obj `if test -f 'libarchive/test/test_read_format_tar_empty_filename.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_tar_empty_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_tar_empty_filename.c'; fi` + +libarchive/test/libarchive_test-test_read_format_tar_empty_with_gnulabel.o: libarchive/test/test_read_format_tar_empty_with_gnulabel.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_tar_empty_with_gnulabel.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_empty_with_gnulabel.Tpo -c -o libarchive/test/libarchive_test-test_read_format_tar_empty_with_gnulabel.o `test -f 'libarchive/test/test_read_format_tar_empty_with_gnulabel.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_tar_empty_with_gnulabel.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_empty_with_gnulabel.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_empty_with_gnulabel.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_tar_empty_with_gnulabel.c' object='libarchive/test/libarchive_test-test_read_format_tar_empty_with_gnulabel.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_tar_empty_with_gnulabel.o `test -f 'libarchive/test/test_read_format_tar_empty_with_gnulabel.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_tar_empty_with_gnulabel.c + +libarchive/test/libarchive_test-test_read_format_tar_empty_with_gnulabel.obj: libarchive/test/test_read_format_tar_empty_with_gnulabel.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_tar_empty_with_gnulabel.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_empty_with_gnulabel.Tpo -c -o libarchive/test/libarchive_test-test_read_format_tar_empty_with_gnulabel.obj `if test -f 'libarchive/test/test_read_format_tar_empty_with_gnulabel.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_tar_empty_with_gnulabel.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_tar_empty_with_gnulabel.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_empty_with_gnulabel.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_empty_with_gnulabel.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_tar_empty_with_gnulabel.c' object='libarchive/test/libarchive_test-test_read_format_tar_empty_with_gnulabel.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_tar_empty_with_gnulabel.obj `if test -f 'libarchive/test/test_read_format_tar_empty_with_gnulabel.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_tar_empty_with_gnulabel.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_tar_empty_with_gnulabel.c'; fi` + +libarchive/test/libarchive_test-test_read_format_tar_filename.o: libarchive/test/test_read_format_tar_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_tar_filename.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_filename.Tpo -c -o libarchive/test/libarchive_test-test_read_format_tar_filename.o `test -f 'libarchive/test/test_read_format_tar_filename.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_tar_filename.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_filename.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_tar_filename.c' object='libarchive/test/libarchive_test-test_read_format_tar_filename.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_tar_filename.o `test -f 'libarchive/test/test_read_format_tar_filename.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_tar_filename.c + +libarchive/test/libarchive_test-test_read_format_tar_filename.obj: libarchive/test/test_read_format_tar_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_tar_filename.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_filename.Tpo -c -o libarchive/test/libarchive_test-test_read_format_tar_filename.obj `if test -f 'libarchive/test/test_read_format_tar_filename.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_tar_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_tar_filename.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_filename.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tar_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_tar_filename.c' object='libarchive/test/libarchive_test-test_read_format_tar_filename.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_tar_filename.obj `if test -f 'libarchive/test/test_read_format_tar_filename.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_tar_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_tar_filename.c'; fi` + +libarchive/test/libarchive_test-test_read_format_tbz.o: libarchive/test/test_read_format_tbz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_tbz.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tbz.Tpo -c -o libarchive/test/libarchive_test-test_read_format_tbz.o `test -f 'libarchive/test/test_read_format_tbz.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_tbz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tbz.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tbz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_tbz.c' object='libarchive/test/libarchive_test-test_read_format_tbz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_tbz.o `test -f 'libarchive/test/test_read_format_tbz.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_tbz.c + +libarchive/test/libarchive_test-test_read_format_tbz.obj: libarchive/test/test_read_format_tbz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_tbz.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tbz.Tpo -c -o libarchive/test/libarchive_test-test_read_format_tbz.obj `if test -f 'libarchive/test/test_read_format_tbz.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_tbz.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_tbz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tbz.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tbz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_tbz.c' object='libarchive/test/libarchive_test-test_read_format_tbz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_tbz.obj `if test -f 'libarchive/test/test_read_format_tbz.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_tbz.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_tbz.c'; fi` + +libarchive/test/libarchive_test-test_read_format_tgz.o: libarchive/test/test_read_format_tgz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_tgz.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tgz.Tpo -c -o libarchive/test/libarchive_test-test_read_format_tgz.o `test -f 'libarchive/test/test_read_format_tgz.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_tgz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tgz.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tgz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_tgz.c' object='libarchive/test/libarchive_test-test_read_format_tgz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_tgz.o `test -f 'libarchive/test/test_read_format_tgz.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_tgz.c + +libarchive/test/libarchive_test-test_read_format_tgz.obj: libarchive/test/test_read_format_tgz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_tgz.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tgz.Tpo -c -o libarchive/test/libarchive_test-test_read_format_tgz.obj `if test -f 'libarchive/test/test_read_format_tgz.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_tgz.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_tgz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tgz.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tgz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_tgz.c' object='libarchive/test/libarchive_test-test_read_format_tgz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_tgz.obj `if test -f 'libarchive/test/test_read_format_tgz.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_tgz.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_tgz.c'; fi` + +libarchive/test/libarchive_test-test_read_format_tlz.o: libarchive/test/test_read_format_tlz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_tlz.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tlz.Tpo -c -o libarchive/test/libarchive_test-test_read_format_tlz.o `test -f 'libarchive/test/test_read_format_tlz.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_tlz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tlz.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tlz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_tlz.c' object='libarchive/test/libarchive_test-test_read_format_tlz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_tlz.o `test -f 'libarchive/test/test_read_format_tlz.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_tlz.c + +libarchive/test/libarchive_test-test_read_format_tlz.obj: libarchive/test/test_read_format_tlz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_tlz.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tlz.Tpo -c -o libarchive/test/libarchive_test-test_read_format_tlz.obj `if test -f 'libarchive/test/test_read_format_tlz.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_tlz.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_tlz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tlz.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tlz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_tlz.c' object='libarchive/test/libarchive_test-test_read_format_tlz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_tlz.obj `if test -f 'libarchive/test/test_read_format_tlz.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_tlz.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_tlz.c'; fi` + +libarchive/test/libarchive_test-test_read_format_txz.o: libarchive/test/test_read_format_txz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_txz.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_txz.Tpo -c -o libarchive/test/libarchive_test-test_read_format_txz.o `test -f 'libarchive/test/test_read_format_txz.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_txz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_txz.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_txz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_txz.c' object='libarchive/test/libarchive_test-test_read_format_txz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_txz.o `test -f 'libarchive/test/test_read_format_txz.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_txz.c + +libarchive/test/libarchive_test-test_read_format_txz.obj: libarchive/test/test_read_format_txz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_txz.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_txz.Tpo -c -o libarchive/test/libarchive_test-test_read_format_txz.obj `if test -f 'libarchive/test/test_read_format_txz.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_txz.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_txz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_txz.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_txz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_txz.c' object='libarchive/test/libarchive_test-test_read_format_txz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_txz.obj `if test -f 'libarchive/test/test_read_format_txz.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_txz.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_txz.c'; fi` + +libarchive/test/libarchive_test-test_read_format_tz.o: libarchive/test/test_read_format_tz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_tz.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tz.Tpo -c -o libarchive/test/libarchive_test-test_read_format_tz.o `test -f 'libarchive/test/test_read_format_tz.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_tz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tz.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_tz.c' object='libarchive/test/libarchive_test-test_read_format_tz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_tz.o `test -f 'libarchive/test/test_read_format_tz.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_tz.c + +libarchive/test/libarchive_test-test_read_format_tz.obj: libarchive/test/test_read_format_tz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_tz.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tz.Tpo -c -o libarchive/test/libarchive_test-test_read_format_tz.obj `if test -f 'libarchive/test/test_read_format_tz.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_tz.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_tz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tz.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_tz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_tz.c' object='libarchive/test/libarchive_test-test_read_format_tz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_tz.obj `if test -f 'libarchive/test/test_read_format_tz.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_tz.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_tz.c'; fi` + +libarchive/test/libarchive_test-test_read_format_ustar_filename.o: libarchive/test/test_read_format_ustar_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_ustar_filename.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_ustar_filename.Tpo -c -o libarchive/test/libarchive_test-test_read_format_ustar_filename.o `test -f 'libarchive/test/test_read_format_ustar_filename.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_ustar_filename.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_ustar_filename.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_ustar_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_ustar_filename.c' object='libarchive/test/libarchive_test-test_read_format_ustar_filename.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_ustar_filename.o `test -f 'libarchive/test/test_read_format_ustar_filename.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_ustar_filename.c + +libarchive/test/libarchive_test-test_read_format_ustar_filename.obj: libarchive/test/test_read_format_ustar_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_ustar_filename.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_ustar_filename.Tpo -c -o libarchive/test/libarchive_test-test_read_format_ustar_filename.obj `if test -f 'libarchive/test/test_read_format_ustar_filename.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_ustar_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_ustar_filename.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_ustar_filename.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_ustar_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_ustar_filename.c' object='libarchive/test/libarchive_test-test_read_format_ustar_filename.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_ustar_filename.obj `if test -f 'libarchive/test/test_read_format_ustar_filename.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_ustar_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_ustar_filename.c'; fi` + +libarchive/test/libarchive_test-test_read_format_warc.o: libarchive/test/test_read_format_warc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_warc.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_warc.Tpo -c -o libarchive/test/libarchive_test-test_read_format_warc.o `test -f 'libarchive/test/test_read_format_warc.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_warc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_warc.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_warc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_warc.c' object='libarchive/test/libarchive_test-test_read_format_warc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_warc.o `test -f 'libarchive/test/test_read_format_warc.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_warc.c + +libarchive/test/libarchive_test-test_read_format_warc.obj: libarchive/test/test_read_format_warc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_warc.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_warc.Tpo -c -o libarchive/test/libarchive_test-test_read_format_warc.obj `if test -f 'libarchive/test/test_read_format_warc.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_warc.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_warc.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_warc.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_warc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_warc.c' object='libarchive/test/libarchive_test-test_read_format_warc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_warc.obj `if test -f 'libarchive/test/test_read_format_warc.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_warc.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_warc.c'; fi` + +libarchive/test/libarchive_test-test_read_format_xar.o: libarchive/test/test_read_format_xar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_xar.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_xar.Tpo -c -o libarchive/test/libarchive_test-test_read_format_xar.o `test -f 'libarchive/test/test_read_format_xar.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_xar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_xar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_xar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_xar.c' object='libarchive/test/libarchive_test-test_read_format_xar.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_xar.o `test -f 'libarchive/test/test_read_format_xar.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_xar.c + +libarchive/test/libarchive_test-test_read_format_xar.obj: libarchive/test/test_read_format_xar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_xar.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_xar.Tpo -c -o libarchive/test/libarchive_test-test_read_format_xar.obj `if test -f 'libarchive/test/test_read_format_xar.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_xar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_xar.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_xar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_xar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_xar.c' object='libarchive/test/libarchive_test-test_read_format_xar.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_xar.obj `if test -f 'libarchive/test/test_read_format_xar.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_xar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_xar.c'; fi` + +libarchive/test/libarchive_test-test_read_format_zip.o: libarchive/test/test_read_format_zip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip.o `test -f 'libarchive/test/test_read_format_zip.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip.c' object='libarchive/test/libarchive_test-test_read_format_zip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip.o `test -f 'libarchive/test/test_read_format_zip.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip.c + +libarchive/test/libarchive_test-test_read_format_zip.obj: libarchive/test/test_read_format_zip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip.obj `if test -f 'libarchive/test/test_read_format_zip.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip.c' object='libarchive/test/libarchive_test-test_read_format_zip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip.obj `if test -f 'libarchive/test/test_read_format_zip.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip.c'; fi` + +libarchive/test/libarchive_test-test_read_format_zip_7075_utf8_paths.o: libarchive/test/test_read_format_zip_7075_utf8_paths.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_7075_utf8_paths.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_7075_utf8_paths.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_7075_utf8_paths.o `test -f 'libarchive/test/test_read_format_zip_7075_utf8_paths.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_7075_utf8_paths.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_7075_utf8_paths.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_7075_utf8_paths.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_7075_utf8_paths.c' object='libarchive/test/libarchive_test-test_read_format_zip_7075_utf8_paths.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_7075_utf8_paths.o `test -f 'libarchive/test/test_read_format_zip_7075_utf8_paths.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_7075_utf8_paths.c + +libarchive/test/libarchive_test-test_read_format_zip_7075_utf8_paths.obj: libarchive/test/test_read_format_zip_7075_utf8_paths.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_7075_utf8_paths.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_7075_utf8_paths.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_7075_utf8_paths.obj `if test -f 'libarchive/test/test_read_format_zip_7075_utf8_paths.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_7075_utf8_paths.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_7075_utf8_paths.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_7075_utf8_paths.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_7075_utf8_paths.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_7075_utf8_paths.c' object='libarchive/test/libarchive_test-test_read_format_zip_7075_utf8_paths.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_7075_utf8_paths.obj `if test -f 'libarchive/test/test_read_format_zip_7075_utf8_paths.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_7075_utf8_paths.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_7075_utf8_paths.c'; fi` + +libarchive/test/libarchive_test-test_read_format_zip_comment_stored.o: libarchive/test/test_read_format_zip_comment_stored.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_comment_stored.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_comment_stored.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_comment_stored.o `test -f 'libarchive/test/test_read_format_zip_comment_stored.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_comment_stored.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_comment_stored.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_comment_stored.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_comment_stored.c' object='libarchive/test/libarchive_test-test_read_format_zip_comment_stored.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_comment_stored.o `test -f 'libarchive/test/test_read_format_zip_comment_stored.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_comment_stored.c + +libarchive/test/libarchive_test-test_read_format_zip_comment_stored.obj: libarchive/test/test_read_format_zip_comment_stored.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_comment_stored.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_comment_stored.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_comment_stored.obj `if test -f 'libarchive/test/test_read_format_zip_comment_stored.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_comment_stored.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_comment_stored.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_comment_stored.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_comment_stored.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_comment_stored.c' object='libarchive/test/libarchive_test-test_read_format_zip_comment_stored.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_comment_stored.obj `if test -f 'libarchive/test/test_read_format_zip_comment_stored.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_comment_stored.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_comment_stored.c'; fi` + +libarchive/test/libarchive_test-test_read_format_zip_encryption_data.o: libarchive/test/test_read_format_zip_encryption_data.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_encryption_data.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_encryption_data.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_encryption_data.o `test -f 'libarchive/test/test_read_format_zip_encryption_data.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_encryption_data.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_encryption_data.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_encryption_data.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_encryption_data.c' object='libarchive/test/libarchive_test-test_read_format_zip_encryption_data.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_encryption_data.o `test -f 'libarchive/test/test_read_format_zip_encryption_data.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_encryption_data.c + +libarchive/test/libarchive_test-test_read_format_zip_encryption_data.obj: libarchive/test/test_read_format_zip_encryption_data.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_encryption_data.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_encryption_data.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_encryption_data.obj `if test -f 'libarchive/test/test_read_format_zip_encryption_data.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_encryption_data.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_encryption_data.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_encryption_data.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_encryption_data.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_encryption_data.c' object='libarchive/test/libarchive_test-test_read_format_zip_encryption_data.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_encryption_data.obj `if test -f 'libarchive/test/test_read_format_zip_encryption_data.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_encryption_data.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_encryption_data.c'; fi` + +libarchive/test/libarchive_test-test_read_format_zip_encryption_partially.o: libarchive/test/test_read_format_zip_encryption_partially.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_encryption_partially.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_encryption_partially.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_encryption_partially.o `test -f 'libarchive/test/test_read_format_zip_encryption_partially.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_encryption_partially.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_encryption_partially.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_encryption_partially.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_encryption_partially.c' object='libarchive/test/libarchive_test-test_read_format_zip_encryption_partially.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_encryption_partially.o `test -f 'libarchive/test/test_read_format_zip_encryption_partially.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_encryption_partially.c + +libarchive/test/libarchive_test-test_read_format_zip_encryption_partially.obj: libarchive/test/test_read_format_zip_encryption_partially.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_encryption_partially.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_encryption_partially.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_encryption_partially.obj `if test -f 'libarchive/test/test_read_format_zip_encryption_partially.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_encryption_partially.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_encryption_partially.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_encryption_partially.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_encryption_partially.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_encryption_partially.c' object='libarchive/test/libarchive_test-test_read_format_zip_encryption_partially.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_encryption_partially.obj `if test -f 'libarchive/test/test_read_format_zip_encryption_partially.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_encryption_partially.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_encryption_partially.c'; fi` + +libarchive/test/libarchive_test-test_read_format_zip_encryption_header.o: libarchive/test/test_read_format_zip_encryption_header.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_encryption_header.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_encryption_header.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_encryption_header.o `test -f 'libarchive/test/test_read_format_zip_encryption_header.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_encryption_header.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_encryption_header.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_encryption_header.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_encryption_header.c' object='libarchive/test/libarchive_test-test_read_format_zip_encryption_header.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_encryption_header.o `test -f 'libarchive/test/test_read_format_zip_encryption_header.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_encryption_header.c + +libarchive/test/libarchive_test-test_read_format_zip_encryption_header.obj: libarchive/test/test_read_format_zip_encryption_header.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_encryption_header.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_encryption_header.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_encryption_header.obj `if test -f 'libarchive/test/test_read_format_zip_encryption_header.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_encryption_header.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_encryption_header.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_encryption_header.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_encryption_header.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_encryption_header.c' object='libarchive/test/libarchive_test-test_read_format_zip_encryption_header.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_encryption_header.obj `if test -f 'libarchive/test/test_read_format_zip_encryption_header.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_encryption_header.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_encryption_header.c'; fi` + +libarchive/test/libarchive_test-test_read_format_zip_extra_padding.o: libarchive/test/test_read_format_zip_extra_padding.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_extra_padding.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_extra_padding.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_extra_padding.o `test -f 'libarchive/test/test_read_format_zip_extra_padding.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_extra_padding.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_extra_padding.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_extra_padding.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_extra_padding.c' object='libarchive/test/libarchive_test-test_read_format_zip_extra_padding.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_extra_padding.o `test -f 'libarchive/test/test_read_format_zip_extra_padding.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_extra_padding.c + +libarchive/test/libarchive_test-test_read_format_zip_extra_padding.obj: libarchive/test/test_read_format_zip_extra_padding.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_extra_padding.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_extra_padding.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_extra_padding.obj `if test -f 'libarchive/test/test_read_format_zip_extra_padding.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_extra_padding.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_extra_padding.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_extra_padding.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_extra_padding.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_extra_padding.c' object='libarchive/test/libarchive_test-test_read_format_zip_extra_padding.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_extra_padding.obj `if test -f 'libarchive/test/test_read_format_zip_extra_padding.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_extra_padding.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_extra_padding.c'; fi` + +libarchive/test/libarchive_test-test_read_format_zip_filename.o: libarchive/test/test_read_format_zip_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_filename.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_filename.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_filename.o `test -f 'libarchive/test/test_read_format_zip_filename.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_filename.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_filename.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_filename.c' object='libarchive/test/libarchive_test-test_read_format_zip_filename.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_filename.o `test -f 'libarchive/test/test_read_format_zip_filename.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_filename.c + +libarchive/test/libarchive_test-test_read_format_zip_filename.obj: libarchive/test/test_read_format_zip_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_filename.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_filename.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_filename.obj `if test -f 'libarchive/test/test_read_format_zip_filename.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_filename.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_filename.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_filename.c' object='libarchive/test/libarchive_test-test_read_format_zip_filename.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_filename.obj `if test -f 'libarchive/test/test_read_format_zip_filename.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_filename.c'; fi` + +libarchive/test/libarchive_test-test_read_format_zip_high_compression.o: libarchive/test/test_read_format_zip_high_compression.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_high_compression.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_high_compression.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_high_compression.o `test -f 'libarchive/test/test_read_format_zip_high_compression.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_high_compression.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_high_compression.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_high_compression.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_high_compression.c' object='libarchive/test/libarchive_test-test_read_format_zip_high_compression.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_high_compression.o `test -f 'libarchive/test/test_read_format_zip_high_compression.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_high_compression.c + +libarchive/test/libarchive_test-test_read_format_zip_high_compression.obj: libarchive/test/test_read_format_zip_high_compression.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_high_compression.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_high_compression.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_high_compression.obj `if test -f 'libarchive/test/test_read_format_zip_high_compression.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_high_compression.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_high_compression.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_high_compression.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_high_compression.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_high_compression.c' object='libarchive/test/libarchive_test-test_read_format_zip_high_compression.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_high_compression.obj `if test -f 'libarchive/test/test_read_format_zip_high_compression.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_high_compression.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_high_compression.c'; fi` + +libarchive/test/libarchive_test-test_read_format_zip_jar.o: libarchive/test/test_read_format_zip_jar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_jar.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_jar.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_jar.o `test -f 'libarchive/test/test_read_format_zip_jar.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_jar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_jar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_jar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_jar.c' object='libarchive/test/libarchive_test-test_read_format_zip_jar.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_jar.o `test -f 'libarchive/test/test_read_format_zip_jar.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_jar.c + +libarchive/test/libarchive_test-test_read_format_zip_jar.obj: libarchive/test/test_read_format_zip_jar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_jar.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_jar.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_jar.obj `if test -f 'libarchive/test/test_read_format_zip_jar.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_jar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_jar.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_jar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_jar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_jar.c' object='libarchive/test/libarchive_test-test_read_format_zip_jar.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_jar.obj `if test -f 'libarchive/test/test_read_format_zip_jar.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_jar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_jar.c'; fi` + +libarchive/test/libarchive_test-test_read_format_zip_mac_metadata.o: libarchive/test/test_read_format_zip_mac_metadata.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_mac_metadata.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_mac_metadata.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_mac_metadata.o `test -f 'libarchive/test/test_read_format_zip_mac_metadata.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_mac_metadata.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_mac_metadata.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_mac_metadata.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_mac_metadata.c' object='libarchive/test/libarchive_test-test_read_format_zip_mac_metadata.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_mac_metadata.o `test -f 'libarchive/test/test_read_format_zip_mac_metadata.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_mac_metadata.c + +libarchive/test/libarchive_test-test_read_format_zip_mac_metadata.obj: libarchive/test/test_read_format_zip_mac_metadata.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_mac_metadata.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_mac_metadata.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_mac_metadata.obj `if test -f 'libarchive/test/test_read_format_zip_mac_metadata.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_mac_metadata.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_mac_metadata.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_mac_metadata.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_mac_metadata.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_mac_metadata.c' object='libarchive/test/libarchive_test-test_read_format_zip_mac_metadata.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_mac_metadata.obj `if test -f 'libarchive/test/test_read_format_zip_mac_metadata.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_mac_metadata.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_mac_metadata.c'; fi` + +libarchive/test/libarchive_test-test_read_format_zip_malformed.o: libarchive/test/test_read_format_zip_malformed.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_malformed.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_malformed.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_malformed.o `test -f 'libarchive/test/test_read_format_zip_malformed.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_malformed.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_malformed.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_malformed.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_malformed.c' object='libarchive/test/libarchive_test-test_read_format_zip_malformed.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_malformed.o `test -f 'libarchive/test/test_read_format_zip_malformed.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_malformed.c + +libarchive/test/libarchive_test-test_read_format_zip_malformed.obj: libarchive/test/test_read_format_zip_malformed.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_malformed.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_malformed.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_malformed.obj `if test -f 'libarchive/test/test_read_format_zip_malformed.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_malformed.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_malformed.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_malformed.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_malformed.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_malformed.c' object='libarchive/test/libarchive_test-test_read_format_zip_malformed.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_malformed.obj `if test -f 'libarchive/test/test_read_format_zip_malformed.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_malformed.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_malformed.c'; fi` + +libarchive/test/libarchive_test-test_read_format_zip_msdos.o: libarchive/test/test_read_format_zip_msdos.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_msdos.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_msdos.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_msdos.o `test -f 'libarchive/test/test_read_format_zip_msdos.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_msdos.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_msdos.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_msdos.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_msdos.c' object='libarchive/test/libarchive_test-test_read_format_zip_msdos.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_msdos.o `test -f 'libarchive/test/test_read_format_zip_msdos.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_msdos.c + +libarchive/test/libarchive_test-test_read_format_zip_msdos.obj: libarchive/test/test_read_format_zip_msdos.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_msdos.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_msdos.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_msdos.obj `if test -f 'libarchive/test/test_read_format_zip_msdos.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_msdos.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_msdos.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_msdos.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_msdos.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_msdos.c' object='libarchive/test/libarchive_test-test_read_format_zip_msdos.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_msdos.obj `if test -f 'libarchive/test/test_read_format_zip_msdos.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_msdos.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_msdos.c'; fi` + +libarchive/test/libarchive_test-test_read_format_zip_nested.o: libarchive/test/test_read_format_zip_nested.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_nested.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_nested.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_nested.o `test -f 'libarchive/test/test_read_format_zip_nested.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_nested.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_nested.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_nested.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_nested.c' object='libarchive/test/libarchive_test-test_read_format_zip_nested.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_nested.o `test -f 'libarchive/test/test_read_format_zip_nested.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_nested.c + +libarchive/test/libarchive_test-test_read_format_zip_nested.obj: libarchive/test/test_read_format_zip_nested.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_nested.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_nested.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_nested.obj `if test -f 'libarchive/test/test_read_format_zip_nested.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_nested.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_nested.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_nested.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_nested.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_nested.c' object='libarchive/test/libarchive_test-test_read_format_zip_nested.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_nested.obj `if test -f 'libarchive/test/test_read_format_zip_nested.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_nested.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_nested.c'; fi` + +libarchive/test/libarchive_test-test_read_format_zip_nofiletype.o: libarchive/test/test_read_format_zip_nofiletype.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_nofiletype.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_nofiletype.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_nofiletype.o `test -f 'libarchive/test/test_read_format_zip_nofiletype.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_nofiletype.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_nofiletype.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_nofiletype.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_nofiletype.c' object='libarchive/test/libarchive_test-test_read_format_zip_nofiletype.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_nofiletype.o `test -f 'libarchive/test/test_read_format_zip_nofiletype.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_nofiletype.c + +libarchive/test/libarchive_test-test_read_format_zip_nofiletype.obj: libarchive/test/test_read_format_zip_nofiletype.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_nofiletype.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_nofiletype.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_nofiletype.obj `if test -f 'libarchive/test/test_read_format_zip_nofiletype.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_nofiletype.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_nofiletype.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_nofiletype.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_nofiletype.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_nofiletype.c' object='libarchive/test/libarchive_test-test_read_format_zip_nofiletype.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_nofiletype.obj `if test -f 'libarchive/test/test_read_format_zip_nofiletype.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_nofiletype.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_nofiletype.c'; fi` + +libarchive/test/libarchive_test-test_read_format_zip_padded.o: libarchive/test/test_read_format_zip_padded.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_padded.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_padded.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_padded.o `test -f 'libarchive/test/test_read_format_zip_padded.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_padded.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_padded.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_padded.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_padded.c' object='libarchive/test/libarchive_test-test_read_format_zip_padded.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_padded.o `test -f 'libarchive/test/test_read_format_zip_padded.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_padded.c + +libarchive/test/libarchive_test-test_read_format_zip_padded.obj: libarchive/test/test_read_format_zip_padded.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_padded.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_padded.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_padded.obj `if test -f 'libarchive/test/test_read_format_zip_padded.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_padded.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_padded.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_padded.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_padded.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_padded.c' object='libarchive/test/libarchive_test-test_read_format_zip_padded.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_padded.obj `if test -f 'libarchive/test/test_read_format_zip_padded.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_padded.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_padded.c'; fi` + +libarchive/test/libarchive_test-test_read_format_zip_sfx.o: libarchive/test/test_read_format_zip_sfx.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_sfx.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_sfx.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_sfx.o `test -f 'libarchive/test/test_read_format_zip_sfx.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_sfx.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_sfx.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_sfx.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_sfx.c' object='libarchive/test/libarchive_test-test_read_format_zip_sfx.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_sfx.o `test -f 'libarchive/test/test_read_format_zip_sfx.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_sfx.c + +libarchive/test/libarchive_test-test_read_format_zip_sfx.obj: libarchive/test/test_read_format_zip_sfx.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_sfx.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_sfx.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_sfx.obj `if test -f 'libarchive/test/test_read_format_zip_sfx.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_sfx.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_sfx.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_sfx.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_sfx.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_sfx.c' object='libarchive/test/libarchive_test-test_read_format_zip_sfx.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_sfx.obj `if test -f 'libarchive/test/test_read_format_zip_sfx.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_sfx.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_sfx.c'; fi` + +libarchive/test/libarchive_test-test_read_format_zip_traditional_encryption_data.o: libarchive/test/test_read_format_zip_traditional_encryption_data.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_traditional_encryption_data.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_traditional_encryption_data.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_traditional_encryption_data.o `test -f 'libarchive/test/test_read_format_zip_traditional_encryption_data.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_traditional_encryption_data.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_traditional_encryption_data.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_traditional_encryption_data.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_traditional_encryption_data.c' object='libarchive/test/libarchive_test-test_read_format_zip_traditional_encryption_data.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_traditional_encryption_data.o `test -f 'libarchive/test/test_read_format_zip_traditional_encryption_data.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_traditional_encryption_data.c + +libarchive/test/libarchive_test-test_read_format_zip_traditional_encryption_data.obj: libarchive/test/test_read_format_zip_traditional_encryption_data.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_traditional_encryption_data.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_traditional_encryption_data.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_traditional_encryption_data.obj `if test -f 'libarchive/test/test_read_format_zip_traditional_encryption_data.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_traditional_encryption_data.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_traditional_encryption_data.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_traditional_encryption_data.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_traditional_encryption_data.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_traditional_encryption_data.c' object='libarchive/test/libarchive_test-test_read_format_zip_traditional_encryption_data.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_traditional_encryption_data.obj `if test -f 'libarchive/test/test_read_format_zip_traditional_encryption_data.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_traditional_encryption_data.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_traditional_encryption_data.c'; fi` + +libarchive/test/libarchive_test-test_read_format_zip_winzip_aes.o: libarchive/test/test_read_format_zip_winzip_aes.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_winzip_aes.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_winzip_aes.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_winzip_aes.o `test -f 'libarchive/test/test_read_format_zip_winzip_aes.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_winzip_aes.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_winzip_aes.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_winzip_aes.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_winzip_aes.c' object='libarchive/test/libarchive_test-test_read_format_zip_winzip_aes.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_winzip_aes.o `test -f 'libarchive/test/test_read_format_zip_winzip_aes.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_winzip_aes.c + +libarchive/test/libarchive_test-test_read_format_zip_winzip_aes.obj: libarchive/test/test_read_format_zip_winzip_aes.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_winzip_aes.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_winzip_aes.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_winzip_aes.obj `if test -f 'libarchive/test/test_read_format_zip_winzip_aes.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_winzip_aes.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_winzip_aes.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_winzip_aes.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_winzip_aes.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_winzip_aes.c' object='libarchive/test/libarchive_test-test_read_format_zip_winzip_aes.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_winzip_aes.obj `if test -f 'libarchive/test/test_read_format_zip_winzip_aes.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_winzip_aes.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_winzip_aes.c'; fi` + +libarchive/test/libarchive_test-test_read_format_zip_winzip_aes_large.o: libarchive/test/test_read_format_zip_winzip_aes_large.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_winzip_aes_large.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_winzip_aes_large.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_winzip_aes_large.o `test -f 'libarchive/test/test_read_format_zip_winzip_aes_large.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_winzip_aes_large.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_winzip_aes_large.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_winzip_aes_large.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_winzip_aes_large.c' object='libarchive/test/libarchive_test-test_read_format_zip_winzip_aes_large.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_winzip_aes_large.o `test -f 'libarchive/test/test_read_format_zip_winzip_aes_large.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_winzip_aes_large.c + +libarchive/test/libarchive_test-test_read_format_zip_winzip_aes_large.obj: libarchive/test/test_read_format_zip_winzip_aes_large.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_winzip_aes_large.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_winzip_aes_large.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_winzip_aes_large.obj `if test -f 'libarchive/test/test_read_format_zip_winzip_aes_large.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_winzip_aes_large.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_winzip_aes_large.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_winzip_aes_large.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_winzip_aes_large.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_winzip_aes_large.c' object='libarchive/test/libarchive_test-test_read_format_zip_winzip_aes_large.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_winzip_aes_large.obj `if test -f 'libarchive/test/test_read_format_zip_winzip_aes_large.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_winzip_aes_large.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_winzip_aes_large.c'; fi` + +libarchive/test/libarchive_test-test_read_format_zip_zip64.o: libarchive/test/test_read_format_zip_zip64.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_zip64.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_zip64.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_zip64.o `test -f 'libarchive/test/test_read_format_zip_zip64.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_zip64.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_zip64.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_zip64.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_zip64.c' object='libarchive/test/libarchive_test-test_read_format_zip_zip64.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_zip64.o `test -f 'libarchive/test/test_read_format_zip_zip64.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_zip64.c + +libarchive/test/libarchive_test-test_read_format_zip_zip64.obj: libarchive/test/test_read_format_zip_zip64.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_zip64.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_zip64.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_zip64.obj `if test -f 'libarchive/test/test_read_format_zip_zip64.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_zip64.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_zip64.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_zip64.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_zip64.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_zip64.c' object='libarchive/test/libarchive_test-test_read_format_zip_zip64.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_zip64.obj `if test -f 'libarchive/test/test_read_format_zip_zip64.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_zip64.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_zip64.c'; fi` + +libarchive/test/libarchive_test-test_read_format_zip_with_invalid_traditional_eocd.o: libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_with_invalid_traditional_eocd.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_with_invalid_traditional_eocd.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_with_invalid_traditional_eocd.o `test -f 'libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_with_invalid_traditional_eocd.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_with_invalid_traditional_eocd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c' object='libarchive/test/libarchive_test-test_read_format_zip_with_invalid_traditional_eocd.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_with_invalid_traditional_eocd.o `test -f 'libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c' || echo '$(srcdir)/'`libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c + +libarchive/test/libarchive_test-test_read_format_zip_with_invalid_traditional_eocd.obj: libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_format_zip_with_invalid_traditional_eocd.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_with_invalid_traditional_eocd.Tpo -c -o libarchive/test/libarchive_test-test_read_format_zip_with_invalid_traditional_eocd.obj `if test -f 'libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_with_invalid_traditional_eocd.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_format_zip_with_invalid_traditional_eocd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c' object='libarchive/test/libarchive_test-test_read_format_zip_with_invalid_traditional_eocd.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_format_zip_with_invalid_traditional_eocd.obj `if test -f 'libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c'; then $(CYGPATH_W) 'libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c'; fi` + +libarchive/test/libarchive_test-test_read_large.o: libarchive/test/test_read_large.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_large.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_large.Tpo -c -o libarchive/test/libarchive_test-test_read_large.o `test -f 'libarchive/test/test_read_large.c' || echo '$(srcdir)/'`libarchive/test/test_read_large.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_large.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_large.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_large.c' object='libarchive/test/libarchive_test-test_read_large.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_large.o `test -f 'libarchive/test/test_read_large.c' || echo '$(srcdir)/'`libarchive/test/test_read_large.c + +libarchive/test/libarchive_test-test_read_large.obj: libarchive/test/test_read_large.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_large.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_large.Tpo -c -o libarchive/test/libarchive_test-test_read_large.obj `if test -f 'libarchive/test/test_read_large.c'; then $(CYGPATH_W) 'libarchive/test/test_read_large.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_large.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_large.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_large.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_large.c' object='libarchive/test/libarchive_test-test_read_large.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_large.obj `if test -f 'libarchive/test/test_read_large.c'; then $(CYGPATH_W) 'libarchive/test/test_read_large.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_large.c'; fi` + +libarchive/test/libarchive_test-test_read_pax_schily_xattr.o: libarchive/test/test_read_pax_schily_xattr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_pax_schily_xattr.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_pax_schily_xattr.Tpo -c -o libarchive/test/libarchive_test-test_read_pax_schily_xattr.o `test -f 'libarchive/test/test_read_pax_schily_xattr.c' || echo '$(srcdir)/'`libarchive/test/test_read_pax_schily_xattr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_pax_schily_xattr.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_pax_schily_xattr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_pax_schily_xattr.c' object='libarchive/test/libarchive_test-test_read_pax_schily_xattr.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_pax_schily_xattr.o `test -f 'libarchive/test/test_read_pax_schily_xattr.c' || echo '$(srcdir)/'`libarchive/test/test_read_pax_schily_xattr.c + +libarchive/test/libarchive_test-test_read_pax_schily_xattr.obj: libarchive/test/test_read_pax_schily_xattr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_pax_schily_xattr.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_pax_schily_xattr.Tpo -c -o libarchive/test/libarchive_test-test_read_pax_schily_xattr.obj `if test -f 'libarchive/test/test_read_pax_schily_xattr.c'; then $(CYGPATH_W) 'libarchive/test/test_read_pax_schily_xattr.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_pax_schily_xattr.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_pax_schily_xattr.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_pax_schily_xattr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_pax_schily_xattr.c' object='libarchive/test/libarchive_test-test_read_pax_schily_xattr.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_pax_schily_xattr.obj `if test -f 'libarchive/test/test_read_pax_schily_xattr.c'; then $(CYGPATH_W) 'libarchive/test/test_read_pax_schily_xattr.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_pax_schily_xattr.c'; fi` + +libarchive/test/libarchive_test-test_read_pax_truncated.o: libarchive/test/test_read_pax_truncated.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_pax_truncated.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_pax_truncated.Tpo -c -o libarchive/test/libarchive_test-test_read_pax_truncated.o `test -f 'libarchive/test/test_read_pax_truncated.c' || echo '$(srcdir)/'`libarchive/test/test_read_pax_truncated.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_pax_truncated.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_pax_truncated.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_pax_truncated.c' object='libarchive/test/libarchive_test-test_read_pax_truncated.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_pax_truncated.o `test -f 'libarchive/test/test_read_pax_truncated.c' || echo '$(srcdir)/'`libarchive/test/test_read_pax_truncated.c + +libarchive/test/libarchive_test-test_read_pax_truncated.obj: libarchive/test/test_read_pax_truncated.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_pax_truncated.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_pax_truncated.Tpo -c -o libarchive/test/libarchive_test-test_read_pax_truncated.obj `if test -f 'libarchive/test/test_read_pax_truncated.c'; then $(CYGPATH_W) 'libarchive/test/test_read_pax_truncated.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_pax_truncated.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_pax_truncated.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_pax_truncated.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_pax_truncated.c' object='libarchive/test/libarchive_test-test_read_pax_truncated.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_pax_truncated.obj `if test -f 'libarchive/test/test_read_pax_truncated.c'; then $(CYGPATH_W) 'libarchive/test/test_read_pax_truncated.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_pax_truncated.c'; fi` + +libarchive/test/libarchive_test-test_read_position.o: libarchive/test/test_read_position.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_position.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_position.Tpo -c -o libarchive/test/libarchive_test-test_read_position.o `test -f 'libarchive/test/test_read_position.c' || echo '$(srcdir)/'`libarchive/test/test_read_position.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_position.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_position.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_position.c' object='libarchive/test/libarchive_test-test_read_position.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_position.o `test -f 'libarchive/test/test_read_position.c' || echo '$(srcdir)/'`libarchive/test/test_read_position.c + +libarchive/test/libarchive_test-test_read_position.obj: libarchive/test/test_read_position.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_position.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_position.Tpo -c -o libarchive/test/libarchive_test-test_read_position.obj `if test -f 'libarchive/test/test_read_position.c'; then $(CYGPATH_W) 'libarchive/test/test_read_position.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_position.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_position.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_position.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_position.c' object='libarchive/test/libarchive_test-test_read_position.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_position.obj `if test -f 'libarchive/test/test_read_position.c'; then $(CYGPATH_W) 'libarchive/test/test_read_position.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_position.c'; fi` + +libarchive/test/libarchive_test-test_read_set_format.o: libarchive/test/test_read_set_format.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_set_format.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_set_format.Tpo -c -o libarchive/test/libarchive_test-test_read_set_format.o `test -f 'libarchive/test/test_read_set_format.c' || echo '$(srcdir)/'`libarchive/test/test_read_set_format.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_set_format.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_set_format.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_set_format.c' object='libarchive/test/libarchive_test-test_read_set_format.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_set_format.o `test -f 'libarchive/test/test_read_set_format.c' || echo '$(srcdir)/'`libarchive/test/test_read_set_format.c + +libarchive/test/libarchive_test-test_read_set_format.obj: libarchive/test/test_read_set_format.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_set_format.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_set_format.Tpo -c -o libarchive/test/libarchive_test-test_read_set_format.obj `if test -f 'libarchive/test/test_read_set_format.c'; then $(CYGPATH_W) 'libarchive/test/test_read_set_format.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_set_format.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_set_format.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_set_format.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_set_format.c' object='libarchive/test/libarchive_test-test_read_set_format.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_set_format.obj `if test -f 'libarchive/test/test_read_set_format.c'; then $(CYGPATH_W) 'libarchive/test/test_read_set_format.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_set_format.c'; fi` + +libarchive/test/libarchive_test-test_read_too_many_filters.o: libarchive/test/test_read_too_many_filters.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_too_many_filters.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_too_many_filters.Tpo -c -o libarchive/test/libarchive_test-test_read_too_many_filters.o `test -f 'libarchive/test/test_read_too_many_filters.c' || echo '$(srcdir)/'`libarchive/test/test_read_too_many_filters.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_too_many_filters.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_too_many_filters.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_too_many_filters.c' object='libarchive/test/libarchive_test-test_read_too_many_filters.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_too_many_filters.o `test -f 'libarchive/test/test_read_too_many_filters.c' || echo '$(srcdir)/'`libarchive/test/test_read_too_many_filters.c + +libarchive/test/libarchive_test-test_read_too_many_filters.obj: libarchive/test/test_read_too_many_filters.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_too_many_filters.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_too_many_filters.Tpo -c -o libarchive/test/libarchive_test-test_read_too_many_filters.obj `if test -f 'libarchive/test/test_read_too_many_filters.c'; then $(CYGPATH_W) 'libarchive/test/test_read_too_many_filters.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_too_many_filters.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_too_many_filters.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_too_many_filters.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_too_many_filters.c' object='libarchive/test/libarchive_test-test_read_too_many_filters.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_too_many_filters.obj `if test -f 'libarchive/test/test_read_too_many_filters.c'; then $(CYGPATH_W) 'libarchive/test/test_read_too_many_filters.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_too_many_filters.c'; fi` + +libarchive/test/libarchive_test-test_read_truncated.o: libarchive/test/test_read_truncated.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_truncated.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_truncated.Tpo -c -o libarchive/test/libarchive_test-test_read_truncated.o `test -f 'libarchive/test/test_read_truncated.c' || echo '$(srcdir)/'`libarchive/test/test_read_truncated.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_truncated.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_truncated.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_truncated.c' object='libarchive/test/libarchive_test-test_read_truncated.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_truncated.o `test -f 'libarchive/test/test_read_truncated.c' || echo '$(srcdir)/'`libarchive/test/test_read_truncated.c + +libarchive/test/libarchive_test-test_read_truncated.obj: libarchive/test/test_read_truncated.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_truncated.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_truncated.Tpo -c -o libarchive/test/libarchive_test-test_read_truncated.obj `if test -f 'libarchive/test/test_read_truncated.c'; then $(CYGPATH_W) 'libarchive/test/test_read_truncated.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_truncated.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_truncated.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_truncated.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_truncated.c' object='libarchive/test/libarchive_test-test_read_truncated.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_truncated.obj `if test -f 'libarchive/test/test_read_truncated.c'; then $(CYGPATH_W) 'libarchive/test/test_read_truncated.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_truncated.c'; fi` + +libarchive/test/libarchive_test-test_read_truncated_filter.o: libarchive/test/test_read_truncated_filter.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_truncated_filter.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_truncated_filter.Tpo -c -o libarchive/test/libarchive_test-test_read_truncated_filter.o `test -f 'libarchive/test/test_read_truncated_filter.c' || echo '$(srcdir)/'`libarchive/test/test_read_truncated_filter.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_truncated_filter.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_truncated_filter.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_truncated_filter.c' object='libarchive/test/libarchive_test-test_read_truncated_filter.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_truncated_filter.o `test -f 'libarchive/test/test_read_truncated_filter.c' || echo '$(srcdir)/'`libarchive/test/test_read_truncated_filter.c + +libarchive/test/libarchive_test-test_read_truncated_filter.obj: libarchive/test/test_read_truncated_filter.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_read_truncated_filter.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_read_truncated_filter.Tpo -c -o libarchive/test/libarchive_test-test_read_truncated_filter.obj `if test -f 'libarchive/test/test_read_truncated_filter.c'; then $(CYGPATH_W) 'libarchive/test/test_read_truncated_filter.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_truncated_filter.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_read_truncated_filter.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_read_truncated_filter.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_read_truncated_filter.c' object='libarchive/test/libarchive_test-test_read_truncated_filter.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_read_truncated_filter.obj `if test -f 'libarchive/test/test_read_truncated_filter.c'; then $(CYGPATH_W) 'libarchive/test/test_read_truncated_filter.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_read_truncated_filter.c'; fi` + +libarchive/test/libarchive_test-test_sparse_basic.o: libarchive/test/test_sparse_basic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_sparse_basic.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_sparse_basic.Tpo -c -o libarchive/test/libarchive_test-test_sparse_basic.o `test -f 'libarchive/test/test_sparse_basic.c' || echo '$(srcdir)/'`libarchive/test/test_sparse_basic.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_sparse_basic.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_sparse_basic.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_sparse_basic.c' object='libarchive/test/libarchive_test-test_sparse_basic.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_sparse_basic.o `test -f 'libarchive/test/test_sparse_basic.c' || echo '$(srcdir)/'`libarchive/test/test_sparse_basic.c + +libarchive/test/libarchive_test-test_sparse_basic.obj: libarchive/test/test_sparse_basic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_sparse_basic.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_sparse_basic.Tpo -c -o libarchive/test/libarchive_test-test_sparse_basic.obj `if test -f 'libarchive/test/test_sparse_basic.c'; then $(CYGPATH_W) 'libarchive/test/test_sparse_basic.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_sparse_basic.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_sparse_basic.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_sparse_basic.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_sparse_basic.c' object='libarchive/test/libarchive_test-test_sparse_basic.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_sparse_basic.obj `if test -f 'libarchive/test/test_sparse_basic.c'; then $(CYGPATH_W) 'libarchive/test/test_sparse_basic.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_sparse_basic.c'; fi` + +libarchive/test/libarchive_test-test_tar_filenames.o: libarchive/test/test_tar_filenames.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_tar_filenames.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_tar_filenames.Tpo -c -o libarchive/test/libarchive_test-test_tar_filenames.o `test -f 'libarchive/test/test_tar_filenames.c' || echo '$(srcdir)/'`libarchive/test/test_tar_filenames.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_tar_filenames.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_tar_filenames.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_tar_filenames.c' object='libarchive/test/libarchive_test-test_tar_filenames.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_tar_filenames.o `test -f 'libarchive/test/test_tar_filenames.c' || echo '$(srcdir)/'`libarchive/test/test_tar_filenames.c + +libarchive/test/libarchive_test-test_tar_filenames.obj: libarchive/test/test_tar_filenames.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_tar_filenames.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_tar_filenames.Tpo -c -o libarchive/test/libarchive_test-test_tar_filenames.obj `if test -f 'libarchive/test/test_tar_filenames.c'; then $(CYGPATH_W) 'libarchive/test/test_tar_filenames.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_tar_filenames.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_tar_filenames.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_tar_filenames.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_tar_filenames.c' object='libarchive/test/libarchive_test-test_tar_filenames.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_tar_filenames.obj `if test -f 'libarchive/test/test_tar_filenames.c'; then $(CYGPATH_W) 'libarchive/test/test_tar_filenames.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_tar_filenames.c'; fi` + +libarchive/test/libarchive_test-test_tar_large.o: libarchive/test/test_tar_large.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_tar_large.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_tar_large.Tpo -c -o libarchive/test/libarchive_test-test_tar_large.o `test -f 'libarchive/test/test_tar_large.c' || echo '$(srcdir)/'`libarchive/test/test_tar_large.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_tar_large.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_tar_large.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_tar_large.c' object='libarchive/test/libarchive_test-test_tar_large.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_tar_large.o `test -f 'libarchive/test/test_tar_large.c' || echo '$(srcdir)/'`libarchive/test/test_tar_large.c + +libarchive/test/libarchive_test-test_tar_large.obj: libarchive/test/test_tar_large.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_tar_large.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_tar_large.Tpo -c -o libarchive/test/libarchive_test-test_tar_large.obj `if test -f 'libarchive/test/test_tar_large.c'; then $(CYGPATH_W) 'libarchive/test/test_tar_large.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_tar_large.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_tar_large.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_tar_large.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_tar_large.c' object='libarchive/test/libarchive_test-test_tar_large.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_tar_large.obj `if test -f 'libarchive/test/test_tar_large.c'; then $(CYGPATH_W) 'libarchive/test/test_tar_large.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_tar_large.c'; fi` + +libarchive/test/libarchive_test-test_ustar_filenames.o: libarchive/test/test_ustar_filenames.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_ustar_filenames.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_ustar_filenames.Tpo -c -o libarchive/test/libarchive_test-test_ustar_filenames.o `test -f 'libarchive/test/test_ustar_filenames.c' || echo '$(srcdir)/'`libarchive/test/test_ustar_filenames.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_ustar_filenames.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_ustar_filenames.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_ustar_filenames.c' object='libarchive/test/libarchive_test-test_ustar_filenames.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_ustar_filenames.o `test -f 'libarchive/test/test_ustar_filenames.c' || echo '$(srcdir)/'`libarchive/test/test_ustar_filenames.c + +libarchive/test/libarchive_test-test_ustar_filenames.obj: libarchive/test/test_ustar_filenames.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_ustar_filenames.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_ustar_filenames.Tpo -c -o libarchive/test/libarchive_test-test_ustar_filenames.obj `if test -f 'libarchive/test/test_ustar_filenames.c'; then $(CYGPATH_W) 'libarchive/test/test_ustar_filenames.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_ustar_filenames.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_ustar_filenames.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_ustar_filenames.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_ustar_filenames.c' object='libarchive/test/libarchive_test-test_ustar_filenames.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_ustar_filenames.obj `if test -f 'libarchive/test/test_ustar_filenames.c'; then $(CYGPATH_W) 'libarchive/test/test_ustar_filenames.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_ustar_filenames.c'; fi` + +libarchive/test/libarchive_test-test_ustar_filename_encoding.o: libarchive/test/test_ustar_filename_encoding.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_ustar_filename_encoding.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_ustar_filename_encoding.Tpo -c -o libarchive/test/libarchive_test-test_ustar_filename_encoding.o `test -f 'libarchive/test/test_ustar_filename_encoding.c' || echo '$(srcdir)/'`libarchive/test/test_ustar_filename_encoding.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_ustar_filename_encoding.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_ustar_filename_encoding.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_ustar_filename_encoding.c' object='libarchive/test/libarchive_test-test_ustar_filename_encoding.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_ustar_filename_encoding.o `test -f 'libarchive/test/test_ustar_filename_encoding.c' || echo '$(srcdir)/'`libarchive/test/test_ustar_filename_encoding.c + +libarchive/test/libarchive_test-test_ustar_filename_encoding.obj: libarchive/test/test_ustar_filename_encoding.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_ustar_filename_encoding.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_ustar_filename_encoding.Tpo -c -o libarchive/test/libarchive_test-test_ustar_filename_encoding.obj `if test -f 'libarchive/test/test_ustar_filename_encoding.c'; then $(CYGPATH_W) 'libarchive/test/test_ustar_filename_encoding.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_ustar_filename_encoding.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_ustar_filename_encoding.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_ustar_filename_encoding.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_ustar_filename_encoding.c' object='libarchive/test/libarchive_test-test_ustar_filename_encoding.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_ustar_filename_encoding.obj `if test -f 'libarchive/test/test_ustar_filename_encoding.c'; then $(CYGPATH_W) 'libarchive/test/test_ustar_filename_encoding.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_ustar_filename_encoding.c'; fi` + +libarchive/test/libarchive_test-test_warn_missing_hardlink_target.o: libarchive/test/test_warn_missing_hardlink_target.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_warn_missing_hardlink_target.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_warn_missing_hardlink_target.Tpo -c -o libarchive/test/libarchive_test-test_warn_missing_hardlink_target.o `test -f 'libarchive/test/test_warn_missing_hardlink_target.c' || echo '$(srcdir)/'`libarchive/test/test_warn_missing_hardlink_target.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_warn_missing_hardlink_target.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_warn_missing_hardlink_target.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_warn_missing_hardlink_target.c' object='libarchive/test/libarchive_test-test_warn_missing_hardlink_target.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_warn_missing_hardlink_target.o `test -f 'libarchive/test/test_warn_missing_hardlink_target.c' || echo '$(srcdir)/'`libarchive/test/test_warn_missing_hardlink_target.c + +libarchive/test/libarchive_test-test_warn_missing_hardlink_target.obj: libarchive/test/test_warn_missing_hardlink_target.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_warn_missing_hardlink_target.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_warn_missing_hardlink_target.Tpo -c -o libarchive/test/libarchive_test-test_warn_missing_hardlink_target.obj `if test -f 'libarchive/test/test_warn_missing_hardlink_target.c'; then $(CYGPATH_W) 'libarchive/test/test_warn_missing_hardlink_target.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_warn_missing_hardlink_target.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_warn_missing_hardlink_target.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_warn_missing_hardlink_target.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_warn_missing_hardlink_target.c' object='libarchive/test/libarchive_test-test_warn_missing_hardlink_target.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_warn_missing_hardlink_target.obj `if test -f 'libarchive/test/test_warn_missing_hardlink_target.c'; then $(CYGPATH_W) 'libarchive/test/test_warn_missing_hardlink_target.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_warn_missing_hardlink_target.c'; fi` + +libarchive/test/libarchive_test-test_write_disk.o: libarchive/test/test_write_disk.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk.Tpo -c -o libarchive/test/libarchive_test-test_write_disk.o `test -f 'libarchive/test/test_write_disk.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk.c' object='libarchive/test/libarchive_test-test_write_disk.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk.o `test -f 'libarchive/test/test_write_disk.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk.c + +libarchive/test/libarchive_test-test_write_disk.obj: libarchive/test/test_write_disk.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk.Tpo -c -o libarchive/test/libarchive_test-test_write_disk.obj `if test -f 'libarchive/test/test_write_disk.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk.c' object='libarchive/test/libarchive_test-test_write_disk.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk.obj `if test -f 'libarchive/test/test_write_disk.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk.c'; fi` + +libarchive/test/libarchive_test-test_write_disk_appledouble.o: libarchive/test/test_write_disk_appledouble.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_appledouble.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_appledouble.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_appledouble.o `test -f 'libarchive/test/test_write_disk_appledouble.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_appledouble.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_appledouble.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_appledouble.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_appledouble.c' object='libarchive/test/libarchive_test-test_write_disk_appledouble.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_appledouble.o `test -f 'libarchive/test/test_write_disk_appledouble.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_appledouble.c + +libarchive/test/libarchive_test-test_write_disk_appledouble.obj: libarchive/test/test_write_disk_appledouble.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_appledouble.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_appledouble.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_appledouble.obj `if test -f 'libarchive/test/test_write_disk_appledouble.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_appledouble.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_appledouble.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_appledouble.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_appledouble.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_appledouble.c' object='libarchive/test/libarchive_test-test_write_disk_appledouble.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_appledouble.obj `if test -f 'libarchive/test/test_write_disk_appledouble.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_appledouble.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_appledouble.c'; fi` + +libarchive/test/libarchive_test-test_write_disk_failures.o: libarchive/test/test_write_disk_failures.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_failures.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_failures.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_failures.o `test -f 'libarchive/test/test_write_disk_failures.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_failures.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_failures.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_failures.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_failures.c' object='libarchive/test/libarchive_test-test_write_disk_failures.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_failures.o `test -f 'libarchive/test/test_write_disk_failures.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_failures.c + +libarchive/test/libarchive_test-test_write_disk_failures.obj: libarchive/test/test_write_disk_failures.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_failures.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_failures.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_failures.obj `if test -f 'libarchive/test/test_write_disk_failures.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_failures.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_failures.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_failures.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_failures.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_failures.c' object='libarchive/test/libarchive_test-test_write_disk_failures.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_failures.obj `if test -f 'libarchive/test/test_write_disk_failures.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_failures.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_failures.c'; fi` + +libarchive/test/libarchive_test-test_write_disk_hardlink.o: libarchive/test/test_write_disk_hardlink.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_hardlink.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_hardlink.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_hardlink.o `test -f 'libarchive/test/test_write_disk_hardlink.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_hardlink.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_hardlink.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_hardlink.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_hardlink.c' object='libarchive/test/libarchive_test-test_write_disk_hardlink.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_hardlink.o `test -f 'libarchive/test/test_write_disk_hardlink.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_hardlink.c + +libarchive/test/libarchive_test-test_write_disk_hardlink.obj: libarchive/test/test_write_disk_hardlink.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_hardlink.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_hardlink.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_hardlink.obj `if test -f 'libarchive/test/test_write_disk_hardlink.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_hardlink.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_hardlink.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_hardlink.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_hardlink.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_hardlink.c' object='libarchive/test/libarchive_test-test_write_disk_hardlink.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_hardlink.obj `if test -f 'libarchive/test/test_write_disk_hardlink.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_hardlink.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_hardlink.c'; fi` + +libarchive/test/libarchive_test-test_write_disk_hfs_compression.o: libarchive/test/test_write_disk_hfs_compression.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_hfs_compression.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_hfs_compression.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_hfs_compression.o `test -f 'libarchive/test/test_write_disk_hfs_compression.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_hfs_compression.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_hfs_compression.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_hfs_compression.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_hfs_compression.c' object='libarchive/test/libarchive_test-test_write_disk_hfs_compression.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_hfs_compression.o `test -f 'libarchive/test/test_write_disk_hfs_compression.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_hfs_compression.c + +libarchive/test/libarchive_test-test_write_disk_hfs_compression.obj: libarchive/test/test_write_disk_hfs_compression.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_hfs_compression.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_hfs_compression.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_hfs_compression.obj `if test -f 'libarchive/test/test_write_disk_hfs_compression.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_hfs_compression.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_hfs_compression.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_hfs_compression.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_hfs_compression.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_hfs_compression.c' object='libarchive/test/libarchive_test-test_write_disk_hfs_compression.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_hfs_compression.obj `if test -f 'libarchive/test/test_write_disk_hfs_compression.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_hfs_compression.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_hfs_compression.c'; fi` + +libarchive/test/libarchive_test-test_write_disk_lookup.o: libarchive/test/test_write_disk_lookup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_lookup.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_lookup.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_lookup.o `test -f 'libarchive/test/test_write_disk_lookup.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_lookup.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_lookup.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_lookup.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_lookup.c' object='libarchive/test/libarchive_test-test_write_disk_lookup.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_lookup.o `test -f 'libarchive/test/test_write_disk_lookup.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_lookup.c + +libarchive/test/libarchive_test-test_write_disk_lookup.obj: libarchive/test/test_write_disk_lookup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_lookup.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_lookup.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_lookup.obj `if test -f 'libarchive/test/test_write_disk_lookup.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_lookup.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_lookup.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_lookup.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_lookup.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_lookup.c' object='libarchive/test/libarchive_test-test_write_disk_lookup.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_lookup.obj `if test -f 'libarchive/test/test_write_disk_lookup.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_lookup.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_lookup.c'; fi` + +libarchive/test/libarchive_test-test_write_disk_mac_metadata.o: libarchive/test/test_write_disk_mac_metadata.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_mac_metadata.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_mac_metadata.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_mac_metadata.o `test -f 'libarchive/test/test_write_disk_mac_metadata.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_mac_metadata.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_mac_metadata.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_mac_metadata.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_mac_metadata.c' object='libarchive/test/libarchive_test-test_write_disk_mac_metadata.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_mac_metadata.o `test -f 'libarchive/test/test_write_disk_mac_metadata.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_mac_metadata.c + +libarchive/test/libarchive_test-test_write_disk_mac_metadata.obj: libarchive/test/test_write_disk_mac_metadata.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_mac_metadata.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_mac_metadata.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_mac_metadata.obj `if test -f 'libarchive/test/test_write_disk_mac_metadata.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_mac_metadata.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_mac_metadata.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_mac_metadata.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_mac_metadata.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_mac_metadata.c' object='libarchive/test/libarchive_test-test_write_disk_mac_metadata.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_mac_metadata.obj `if test -f 'libarchive/test/test_write_disk_mac_metadata.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_mac_metadata.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_mac_metadata.c'; fi` + +libarchive/test/libarchive_test-test_write_disk_no_hfs_compression.o: libarchive/test/test_write_disk_no_hfs_compression.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_no_hfs_compression.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_no_hfs_compression.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_no_hfs_compression.o `test -f 'libarchive/test/test_write_disk_no_hfs_compression.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_no_hfs_compression.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_no_hfs_compression.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_no_hfs_compression.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_no_hfs_compression.c' object='libarchive/test/libarchive_test-test_write_disk_no_hfs_compression.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_no_hfs_compression.o `test -f 'libarchive/test/test_write_disk_no_hfs_compression.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_no_hfs_compression.c + +libarchive/test/libarchive_test-test_write_disk_no_hfs_compression.obj: libarchive/test/test_write_disk_no_hfs_compression.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_no_hfs_compression.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_no_hfs_compression.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_no_hfs_compression.obj `if test -f 'libarchive/test/test_write_disk_no_hfs_compression.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_no_hfs_compression.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_no_hfs_compression.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_no_hfs_compression.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_no_hfs_compression.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_no_hfs_compression.c' object='libarchive/test/libarchive_test-test_write_disk_no_hfs_compression.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_no_hfs_compression.obj `if test -f 'libarchive/test/test_write_disk_no_hfs_compression.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_no_hfs_compression.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_no_hfs_compression.c'; fi` + +libarchive/test/libarchive_test-test_write_disk_perms.o: libarchive/test/test_write_disk_perms.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_perms.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_perms.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_perms.o `test -f 'libarchive/test/test_write_disk_perms.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_perms.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_perms.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_perms.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_perms.c' object='libarchive/test/libarchive_test-test_write_disk_perms.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_perms.o `test -f 'libarchive/test/test_write_disk_perms.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_perms.c + +libarchive/test/libarchive_test-test_write_disk_perms.obj: libarchive/test/test_write_disk_perms.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_perms.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_perms.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_perms.obj `if test -f 'libarchive/test/test_write_disk_perms.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_perms.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_perms.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_perms.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_perms.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_perms.c' object='libarchive/test/libarchive_test-test_write_disk_perms.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_perms.obj `if test -f 'libarchive/test/test_write_disk_perms.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_perms.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_perms.c'; fi` + +libarchive/test/libarchive_test-test_write_disk_secure.o: libarchive/test/test_write_disk_secure.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_secure.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_secure.o `test -f 'libarchive/test/test_write_disk_secure.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_secure.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_secure.c' object='libarchive/test/libarchive_test-test_write_disk_secure.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_secure.o `test -f 'libarchive/test/test_write_disk_secure.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_secure.c + +libarchive/test/libarchive_test-test_write_disk_secure.obj: libarchive/test/test_write_disk_secure.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_secure.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_secure.obj `if test -f 'libarchive/test/test_write_disk_secure.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_secure.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_secure.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_secure.c' object='libarchive/test/libarchive_test-test_write_disk_secure.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_secure.obj `if test -f 'libarchive/test/test_write_disk_secure.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_secure.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_secure.c'; fi` + +libarchive/test/libarchive_test-test_write_disk_secure744.o: libarchive/test/test_write_disk_secure744.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_secure744.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure744.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_secure744.o `test -f 'libarchive/test/test_write_disk_secure744.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_secure744.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure744.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure744.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_secure744.c' object='libarchive/test/libarchive_test-test_write_disk_secure744.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_secure744.o `test -f 'libarchive/test/test_write_disk_secure744.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_secure744.c + +libarchive/test/libarchive_test-test_write_disk_secure744.obj: libarchive/test/test_write_disk_secure744.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_secure744.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure744.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_secure744.obj `if test -f 'libarchive/test/test_write_disk_secure744.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_secure744.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_secure744.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure744.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure744.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_secure744.c' object='libarchive/test/libarchive_test-test_write_disk_secure744.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_secure744.obj `if test -f 'libarchive/test/test_write_disk_secure744.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_secure744.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_secure744.c'; fi` + +libarchive/test/libarchive_test-test_write_disk_secure745.o: libarchive/test/test_write_disk_secure745.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_secure745.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure745.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_secure745.o `test -f 'libarchive/test/test_write_disk_secure745.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_secure745.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure745.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure745.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_secure745.c' object='libarchive/test/libarchive_test-test_write_disk_secure745.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_secure745.o `test -f 'libarchive/test/test_write_disk_secure745.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_secure745.c + +libarchive/test/libarchive_test-test_write_disk_secure745.obj: libarchive/test/test_write_disk_secure745.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_secure745.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure745.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_secure745.obj `if test -f 'libarchive/test/test_write_disk_secure745.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_secure745.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_secure745.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure745.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure745.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_secure745.c' object='libarchive/test/libarchive_test-test_write_disk_secure745.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_secure745.obj `if test -f 'libarchive/test/test_write_disk_secure745.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_secure745.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_secure745.c'; fi` + +libarchive/test/libarchive_test-test_write_disk_secure746.o: libarchive/test/test_write_disk_secure746.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_secure746.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure746.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_secure746.o `test -f 'libarchive/test/test_write_disk_secure746.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_secure746.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure746.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure746.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_secure746.c' object='libarchive/test/libarchive_test-test_write_disk_secure746.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_secure746.o `test -f 'libarchive/test/test_write_disk_secure746.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_secure746.c + +libarchive/test/libarchive_test-test_write_disk_secure746.obj: libarchive/test/test_write_disk_secure746.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_secure746.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure746.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_secure746.obj `if test -f 'libarchive/test/test_write_disk_secure746.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_secure746.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_secure746.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure746.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_secure746.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_secure746.c' object='libarchive/test/libarchive_test-test_write_disk_secure746.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_secure746.obj `if test -f 'libarchive/test/test_write_disk_secure746.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_secure746.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_secure746.c'; fi` + +libarchive/test/libarchive_test-test_write_disk_sparse.o: libarchive/test/test_write_disk_sparse.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_sparse.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_sparse.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_sparse.o `test -f 'libarchive/test/test_write_disk_sparse.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_sparse.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_sparse.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_sparse.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_sparse.c' object='libarchive/test/libarchive_test-test_write_disk_sparse.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_sparse.o `test -f 'libarchive/test/test_write_disk_sparse.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_sparse.c + +libarchive/test/libarchive_test-test_write_disk_sparse.obj: libarchive/test/test_write_disk_sparse.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_sparse.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_sparse.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_sparse.obj `if test -f 'libarchive/test/test_write_disk_sparse.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_sparse.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_sparse.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_sparse.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_sparse.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_sparse.c' object='libarchive/test/libarchive_test-test_write_disk_sparse.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_sparse.obj `if test -f 'libarchive/test/test_write_disk_sparse.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_sparse.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_sparse.c'; fi` + +libarchive/test/libarchive_test-test_write_disk_symlink.o: libarchive/test/test_write_disk_symlink.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_symlink.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_symlink.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_symlink.o `test -f 'libarchive/test/test_write_disk_symlink.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_symlink.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_symlink.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_symlink.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_symlink.c' object='libarchive/test/libarchive_test-test_write_disk_symlink.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_symlink.o `test -f 'libarchive/test/test_write_disk_symlink.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_symlink.c + +libarchive/test/libarchive_test-test_write_disk_symlink.obj: libarchive/test/test_write_disk_symlink.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_symlink.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_symlink.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_symlink.obj `if test -f 'libarchive/test/test_write_disk_symlink.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_symlink.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_symlink.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_symlink.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_symlink.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_symlink.c' object='libarchive/test/libarchive_test-test_write_disk_symlink.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_symlink.obj `if test -f 'libarchive/test/test_write_disk_symlink.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_symlink.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_symlink.c'; fi` + +libarchive/test/libarchive_test-test_write_disk_times.o: libarchive/test/test_write_disk_times.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_times.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_times.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_times.o `test -f 'libarchive/test/test_write_disk_times.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_times.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_times.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_times.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_times.c' object='libarchive/test/libarchive_test-test_write_disk_times.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_times.o `test -f 'libarchive/test/test_write_disk_times.c' || echo '$(srcdir)/'`libarchive/test/test_write_disk_times.c + +libarchive/test/libarchive_test-test_write_disk_times.obj: libarchive/test/test_write_disk_times.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_disk_times.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_times.Tpo -c -o libarchive/test/libarchive_test-test_write_disk_times.obj `if test -f 'libarchive/test/test_write_disk_times.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_times.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_times.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_times.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_disk_times.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_disk_times.c' object='libarchive/test/libarchive_test-test_write_disk_times.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_disk_times.obj `if test -f 'libarchive/test/test_write_disk_times.c'; then $(CYGPATH_W) 'libarchive/test/test_write_disk_times.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_disk_times.c'; fi` + +libarchive/test/libarchive_test-test_write_filter_b64encode.o: libarchive/test/test_write_filter_b64encode.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_b64encode.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_b64encode.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_b64encode.o `test -f 'libarchive/test/test_write_filter_b64encode.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_b64encode.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_b64encode.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_b64encode.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_b64encode.c' object='libarchive/test/libarchive_test-test_write_filter_b64encode.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_b64encode.o `test -f 'libarchive/test/test_write_filter_b64encode.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_b64encode.c + +libarchive/test/libarchive_test-test_write_filter_b64encode.obj: libarchive/test/test_write_filter_b64encode.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_b64encode.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_b64encode.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_b64encode.obj `if test -f 'libarchive/test/test_write_filter_b64encode.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_b64encode.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_b64encode.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_b64encode.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_b64encode.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_b64encode.c' object='libarchive/test/libarchive_test-test_write_filter_b64encode.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_b64encode.obj `if test -f 'libarchive/test/test_write_filter_b64encode.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_b64encode.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_b64encode.c'; fi` + +libarchive/test/libarchive_test-test_write_filter_bzip2.o: libarchive/test/test_write_filter_bzip2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_bzip2.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_bzip2.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_bzip2.o `test -f 'libarchive/test/test_write_filter_bzip2.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_bzip2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_bzip2.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_bzip2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_bzip2.c' object='libarchive/test/libarchive_test-test_write_filter_bzip2.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_bzip2.o `test -f 'libarchive/test/test_write_filter_bzip2.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_bzip2.c + +libarchive/test/libarchive_test-test_write_filter_bzip2.obj: libarchive/test/test_write_filter_bzip2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_bzip2.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_bzip2.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_bzip2.obj `if test -f 'libarchive/test/test_write_filter_bzip2.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_bzip2.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_bzip2.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_bzip2.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_bzip2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_bzip2.c' object='libarchive/test/libarchive_test-test_write_filter_bzip2.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_bzip2.obj `if test -f 'libarchive/test/test_write_filter_bzip2.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_bzip2.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_bzip2.c'; fi` + +libarchive/test/libarchive_test-test_write_filter_compress.o: libarchive/test/test_write_filter_compress.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_compress.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_compress.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_compress.o `test -f 'libarchive/test/test_write_filter_compress.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_compress.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_compress.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_compress.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_compress.c' object='libarchive/test/libarchive_test-test_write_filter_compress.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_compress.o `test -f 'libarchive/test/test_write_filter_compress.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_compress.c + +libarchive/test/libarchive_test-test_write_filter_compress.obj: libarchive/test/test_write_filter_compress.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_compress.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_compress.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_compress.obj `if test -f 'libarchive/test/test_write_filter_compress.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_compress.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_compress.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_compress.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_compress.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_compress.c' object='libarchive/test/libarchive_test-test_write_filter_compress.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_compress.obj `if test -f 'libarchive/test/test_write_filter_compress.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_compress.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_compress.c'; fi` + +libarchive/test/libarchive_test-test_write_filter_gzip.o: libarchive/test/test_write_filter_gzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_gzip.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_gzip.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_gzip.o `test -f 'libarchive/test/test_write_filter_gzip.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_gzip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_gzip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_gzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_gzip.c' object='libarchive/test/libarchive_test-test_write_filter_gzip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_gzip.o `test -f 'libarchive/test/test_write_filter_gzip.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_gzip.c + +libarchive/test/libarchive_test-test_write_filter_gzip.obj: libarchive/test/test_write_filter_gzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_gzip.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_gzip.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_gzip.obj `if test -f 'libarchive/test/test_write_filter_gzip.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_gzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_gzip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_gzip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_gzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_gzip.c' object='libarchive/test/libarchive_test-test_write_filter_gzip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_gzip.obj `if test -f 'libarchive/test/test_write_filter_gzip.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_gzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_gzip.c'; fi` + +libarchive/test/libarchive_test-test_write_filter_gzip_timestamp.o: libarchive/test/test_write_filter_gzip_timestamp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_gzip_timestamp.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_gzip_timestamp.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_gzip_timestamp.o `test -f 'libarchive/test/test_write_filter_gzip_timestamp.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_gzip_timestamp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_gzip_timestamp.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_gzip_timestamp.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_gzip_timestamp.c' object='libarchive/test/libarchive_test-test_write_filter_gzip_timestamp.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_gzip_timestamp.o `test -f 'libarchive/test/test_write_filter_gzip_timestamp.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_gzip_timestamp.c + +libarchive/test/libarchive_test-test_write_filter_gzip_timestamp.obj: libarchive/test/test_write_filter_gzip_timestamp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_gzip_timestamp.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_gzip_timestamp.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_gzip_timestamp.obj `if test -f 'libarchive/test/test_write_filter_gzip_timestamp.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_gzip_timestamp.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_gzip_timestamp.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_gzip_timestamp.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_gzip_timestamp.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_gzip_timestamp.c' object='libarchive/test/libarchive_test-test_write_filter_gzip_timestamp.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_gzip_timestamp.obj `if test -f 'libarchive/test/test_write_filter_gzip_timestamp.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_gzip_timestamp.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_gzip_timestamp.c'; fi` + +libarchive/test/libarchive_test-test_write_filter_lrzip.o: libarchive/test/test_write_filter_lrzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_lrzip.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lrzip.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_lrzip.o `test -f 'libarchive/test/test_write_filter_lrzip.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_lrzip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lrzip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lrzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_lrzip.c' object='libarchive/test/libarchive_test-test_write_filter_lrzip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_lrzip.o `test -f 'libarchive/test/test_write_filter_lrzip.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_lrzip.c + +libarchive/test/libarchive_test-test_write_filter_lrzip.obj: libarchive/test/test_write_filter_lrzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_lrzip.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lrzip.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_lrzip.obj `if test -f 'libarchive/test/test_write_filter_lrzip.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_lrzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_lrzip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lrzip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lrzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_lrzip.c' object='libarchive/test/libarchive_test-test_write_filter_lrzip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_lrzip.obj `if test -f 'libarchive/test/test_write_filter_lrzip.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_lrzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_lrzip.c'; fi` + +libarchive/test/libarchive_test-test_write_filter_lz4.o: libarchive/test/test_write_filter_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_lz4.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lz4.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_lz4.o `test -f 'libarchive/test/test_write_filter_lz4.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lz4.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lz4.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_lz4.c' object='libarchive/test/libarchive_test-test_write_filter_lz4.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_lz4.o `test -f 'libarchive/test/test_write_filter_lz4.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_lz4.c + +libarchive/test/libarchive_test-test_write_filter_lz4.obj: libarchive/test/test_write_filter_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_lz4.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lz4.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_lz4.obj `if test -f 'libarchive/test/test_write_filter_lz4.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_lz4.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_lz4.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lz4.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lz4.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_lz4.c' object='libarchive/test/libarchive_test-test_write_filter_lz4.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_lz4.obj `if test -f 'libarchive/test/test_write_filter_lz4.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_lz4.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_lz4.c'; fi` + +libarchive/test/libarchive_test-test_write_filter_lzip.o: libarchive/test/test_write_filter_lzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_lzip.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lzip.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_lzip.o `test -f 'libarchive/test/test_write_filter_lzip.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_lzip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lzip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_lzip.c' object='libarchive/test/libarchive_test-test_write_filter_lzip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_lzip.o `test -f 'libarchive/test/test_write_filter_lzip.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_lzip.c + +libarchive/test/libarchive_test-test_write_filter_lzip.obj: libarchive/test/test_write_filter_lzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_lzip.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lzip.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_lzip.obj `if test -f 'libarchive/test/test_write_filter_lzip.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_lzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_lzip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lzip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_lzip.c' object='libarchive/test/libarchive_test-test_write_filter_lzip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_lzip.obj `if test -f 'libarchive/test/test_write_filter_lzip.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_lzip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_lzip.c'; fi` + +libarchive/test/libarchive_test-test_write_filter_lzma.o: libarchive/test/test_write_filter_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_lzma.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lzma.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_lzma.o `test -f 'libarchive/test/test_write_filter_lzma.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lzma.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lzma.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_lzma.c' object='libarchive/test/libarchive_test-test_write_filter_lzma.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_lzma.o `test -f 'libarchive/test/test_write_filter_lzma.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_lzma.c + +libarchive/test/libarchive_test-test_write_filter_lzma.obj: libarchive/test/test_write_filter_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_lzma.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lzma.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_lzma.obj `if test -f 'libarchive/test/test_write_filter_lzma.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_lzma.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_lzma.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lzma.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lzma.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_lzma.c' object='libarchive/test/libarchive_test-test_write_filter_lzma.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_lzma.obj `if test -f 'libarchive/test/test_write_filter_lzma.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_lzma.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_lzma.c'; fi` + +libarchive/test/libarchive_test-test_write_filter_lzop.o: libarchive/test/test_write_filter_lzop.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_lzop.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lzop.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_lzop.o `test -f 'libarchive/test/test_write_filter_lzop.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_lzop.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lzop.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lzop.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_lzop.c' object='libarchive/test/libarchive_test-test_write_filter_lzop.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_lzop.o `test -f 'libarchive/test/test_write_filter_lzop.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_lzop.c + +libarchive/test/libarchive_test-test_write_filter_lzop.obj: libarchive/test/test_write_filter_lzop.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_lzop.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lzop.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_lzop.obj `if test -f 'libarchive/test/test_write_filter_lzop.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_lzop.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_lzop.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lzop.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_lzop.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_lzop.c' object='libarchive/test/libarchive_test-test_write_filter_lzop.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_lzop.obj `if test -f 'libarchive/test/test_write_filter_lzop.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_lzop.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_lzop.c'; fi` + +libarchive/test/libarchive_test-test_write_filter_program.o: libarchive/test/test_write_filter_program.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_program.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_program.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_program.o `test -f 'libarchive/test/test_write_filter_program.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_program.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_program.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_program.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_program.c' object='libarchive/test/libarchive_test-test_write_filter_program.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_program.o `test -f 'libarchive/test/test_write_filter_program.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_program.c + +libarchive/test/libarchive_test-test_write_filter_program.obj: libarchive/test/test_write_filter_program.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_program.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_program.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_program.obj `if test -f 'libarchive/test/test_write_filter_program.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_program.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_program.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_program.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_program.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_program.c' object='libarchive/test/libarchive_test-test_write_filter_program.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_program.obj `if test -f 'libarchive/test/test_write_filter_program.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_program.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_program.c'; fi` + +libarchive/test/libarchive_test-test_write_filter_uuencode.o: libarchive/test/test_write_filter_uuencode.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_uuencode.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_uuencode.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_uuencode.o `test -f 'libarchive/test/test_write_filter_uuencode.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_uuencode.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_uuencode.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_uuencode.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_uuencode.c' object='libarchive/test/libarchive_test-test_write_filter_uuencode.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_uuencode.o `test -f 'libarchive/test/test_write_filter_uuencode.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_uuencode.c + +libarchive/test/libarchive_test-test_write_filter_uuencode.obj: libarchive/test/test_write_filter_uuencode.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_uuencode.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_uuencode.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_uuencode.obj `if test -f 'libarchive/test/test_write_filter_uuencode.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_uuencode.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_uuencode.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_uuencode.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_uuencode.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_uuencode.c' object='libarchive/test/libarchive_test-test_write_filter_uuencode.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_uuencode.obj `if test -f 'libarchive/test/test_write_filter_uuencode.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_uuencode.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_uuencode.c'; fi` + +libarchive/test/libarchive_test-test_write_filter_xz.o: libarchive/test/test_write_filter_xz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_xz.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_xz.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_xz.o `test -f 'libarchive/test/test_write_filter_xz.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_xz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_xz.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_xz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_xz.c' object='libarchive/test/libarchive_test-test_write_filter_xz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_xz.o `test -f 'libarchive/test/test_write_filter_xz.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_xz.c + +libarchive/test/libarchive_test-test_write_filter_xz.obj: libarchive/test/test_write_filter_xz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_xz.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_xz.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_xz.obj `if test -f 'libarchive/test/test_write_filter_xz.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_xz.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_xz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_xz.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_xz.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_xz.c' object='libarchive/test/libarchive_test-test_write_filter_xz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_xz.obj `if test -f 'libarchive/test/test_write_filter_xz.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_xz.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_xz.c'; fi` + +libarchive/test/libarchive_test-test_write_filter_zstd.o: libarchive/test/test_write_filter_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_zstd.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_zstd.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_zstd.o `test -f 'libarchive/test/test_write_filter_zstd.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_zstd.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_zstd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_zstd.c' object='libarchive/test/libarchive_test-test_write_filter_zstd.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_zstd.o `test -f 'libarchive/test/test_write_filter_zstd.c' || echo '$(srcdir)/'`libarchive/test/test_write_filter_zstd.c + +libarchive/test/libarchive_test-test_write_filter_zstd.obj: libarchive/test/test_write_filter_zstd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_filter_zstd.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_zstd.Tpo -c -o libarchive/test/libarchive_test-test_write_filter_zstd.obj `if test -f 'libarchive/test/test_write_filter_zstd.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_zstd.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_zstd.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_zstd.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_filter_zstd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_filter_zstd.c' object='libarchive/test/libarchive_test-test_write_filter_zstd.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_filter_zstd.obj `if test -f 'libarchive/test/test_write_filter_zstd.c'; then $(CYGPATH_W) 'libarchive/test/test_write_filter_zstd.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_filter_zstd.c'; fi` + +libarchive/test/libarchive_test-test_write_format_7zip.o: libarchive/test/test_write_format_7zip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_7zip.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_7zip.Tpo -c -o libarchive/test/libarchive_test-test_write_format_7zip.o `test -f 'libarchive/test/test_write_format_7zip.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_7zip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_7zip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_7zip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_7zip.c' object='libarchive/test/libarchive_test-test_write_format_7zip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_7zip.o `test -f 'libarchive/test/test_write_format_7zip.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_7zip.c + +libarchive/test/libarchive_test-test_write_format_7zip.obj: libarchive/test/test_write_format_7zip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_7zip.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_7zip.Tpo -c -o libarchive/test/libarchive_test-test_write_format_7zip.obj `if test -f 'libarchive/test/test_write_format_7zip.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_7zip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_7zip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_7zip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_7zip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_7zip.c' object='libarchive/test/libarchive_test-test_write_format_7zip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_7zip.obj `if test -f 'libarchive/test/test_write_format_7zip.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_7zip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_7zip.c'; fi` + +libarchive/test/libarchive_test-test_write_format_7zip_empty.o: libarchive/test/test_write_format_7zip_empty.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_7zip_empty.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_7zip_empty.Tpo -c -o libarchive/test/libarchive_test-test_write_format_7zip_empty.o `test -f 'libarchive/test/test_write_format_7zip_empty.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_7zip_empty.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_7zip_empty.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_7zip_empty.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_7zip_empty.c' object='libarchive/test/libarchive_test-test_write_format_7zip_empty.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_7zip_empty.o `test -f 'libarchive/test/test_write_format_7zip_empty.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_7zip_empty.c + +libarchive/test/libarchive_test-test_write_format_7zip_empty.obj: libarchive/test/test_write_format_7zip_empty.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_7zip_empty.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_7zip_empty.Tpo -c -o libarchive/test/libarchive_test-test_write_format_7zip_empty.obj `if test -f 'libarchive/test/test_write_format_7zip_empty.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_7zip_empty.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_7zip_empty.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_7zip_empty.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_7zip_empty.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_7zip_empty.c' object='libarchive/test/libarchive_test-test_write_format_7zip_empty.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_7zip_empty.obj `if test -f 'libarchive/test/test_write_format_7zip_empty.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_7zip_empty.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_7zip_empty.c'; fi` + +libarchive/test/libarchive_test-test_write_format_7zip_large.o: libarchive/test/test_write_format_7zip_large.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_7zip_large.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_7zip_large.Tpo -c -o libarchive/test/libarchive_test-test_write_format_7zip_large.o `test -f 'libarchive/test/test_write_format_7zip_large.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_7zip_large.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_7zip_large.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_7zip_large.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_7zip_large.c' object='libarchive/test/libarchive_test-test_write_format_7zip_large.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_7zip_large.o `test -f 'libarchive/test/test_write_format_7zip_large.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_7zip_large.c + +libarchive/test/libarchive_test-test_write_format_7zip_large.obj: libarchive/test/test_write_format_7zip_large.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_7zip_large.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_7zip_large.Tpo -c -o libarchive/test/libarchive_test-test_write_format_7zip_large.obj `if test -f 'libarchive/test/test_write_format_7zip_large.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_7zip_large.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_7zip_large.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_7zip_large.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_7zip_large.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_7zip_large.c' object='libarchive/test/libarchive_test-test_write_format_7zip_large.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_7zip_large.obj `if test -f 'libarchive/test/test_write_format_7zip_large.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_7zip_large.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_7zip_large.c'; fi` + +libarchive/test/libarchive_test-test_write_format_ar.o: libarchive/test/test_write_format_ar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_ar.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_ar.Tpo -c -o libarchive/test/libarchive_test-test_write_format_ar.o `test -f 'libarchive/test/test_write_format_ar.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_ar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_ar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_ar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_ar.c' object='libarchive/test/libarchive_test-test_write_format_ar.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_ar.o `test -f 'libarchive/test/test_write_format_ar.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_ar.c + +libarchive/test/libarchive_test-test_write_format_ar.obj: libarchive/test/test_write_format_ar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_ar.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_ar.Tpo -c -o libarchive/test/libarchive_test-test_write_format_ar.obj `if test -f 'libarchive/test/test_write_format_ar.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_ar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_ar.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_ar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_ar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_ar.c' object='libarchive/test/libarchive_test-test_write_format_ar.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_ar.obj `if test -f 'libarchive/test/test_write_format_ar.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_ar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_ar.c'; fi` + +libarchive/test/libarchive_test-test_write_format_cpio.o: libarchive/test/test_write_format_cpio.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_cpio.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio.Tpo -c -o libarchive/test/libarchive_test-test_write_format_cpio.o `test -f 'libarchive/test/test_write_format_cpio.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_cpio.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_cpio.c' object='libarchive/test/libarchive_test-test_write_format_cpio.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_cpio.o `test -f 'libarchive/test/test_write_format_cpio.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_cpio.c + +libarchive/test/libarchive_test-test_write_format_cpio.obj: libarchive/test/test_write_format_cpio.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_cpio.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio.Tpo -c -o libarchive/test/libarchive_test-test_write_format_cpio.obj `if test -f 'libarchive/test/test_write_format_cpio.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_cpio.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_cpio.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_cpio.c' object='libarchive/test/libarchive_test-test_write_format_cpio.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_cpio.obj `if test -f 'libarchive/test/test_write_format_cpio.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_cpio.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_cpio.c'; fi` + +libarchive/test/libarchive_test-test_write_format_cpio_empty.o: libarchive/test/test_write_format_cpio_empty.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_cpio_empty.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio_empty.Tpo -c -o libarchive/test/libarchive_test-test_write_format_cpio_empty.o `test -f 'libarchive/test/test_write_format_cpio_empty.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_cpio_empty.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio_empty.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio_empty.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_cpio_empty.c' object='libarchive/test/libarchive_test-test_write_format_cpio_empty.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_cpio_empty.o `test -f 'libarchive/test/test_write_format_cpio_empty.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_cpio_empty.c + +libarchive/test/libarchive_test-test_write_format_cpio_empty.obj: libarchive/test/test_write_format_cpio_empty.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_cpio_empty.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio_empty.Tpo -c -o libarchive/test/libarchive_test-test_write_format_cpio_empty.obj `if test -f 'libarchive/test/test_write_format_cpio_empty.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_cpio_empty.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_cpio_empty.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio_empty.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio_empty.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_cpio_empty.c' object='libarchive/test/libarchive_test-test_write_format_cpio_empty.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_cpio_empty.obj `if test -f 'libarchive/test/test_write_format_cpio_empty.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_cpio_empty.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_cpio_empty.c'; fi` + +libarchive/test/libarchive_test-test_write_format_cpio_newc.o: libarchive/test/test_write_format_cpio_newc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_cpio_newc.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio_newc.Tpo -c -o libarchive/test/libarchive_test-test_write_format_cpio_newc.o `test -f 'libarchive/test/test_write_format_cpio_newc.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_cpio_newc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio_newc.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio_newc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_cpio_newc.c' object='libarchive/test/libarchive_test-test_write_format_cpio_newc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_cpio_newc.o `test -f 'libarchive/test/test_write_format_cpio_newc.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_cpio_newc.c + +libarchive/test/libarchive_test-test_write_format_cpio_newc.obj: libarchive/test/test_write_format_cpio_newc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_cpio_newc.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio_newc.Tpo -c -o libarchive/test/libarchive_test-test_write_format_cpio_newc.obj `if test -f 'libarchive/test/test_write_format_cpio_newc.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_cpio_newc.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_cpio_newc.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio_newc.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio_newc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_cpio_newc.c' object='libarchive/test/libarchive_test-test_write_format_cpio_newc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_cpio_newc.obj `if test -f 'libarchive/test/test_write_format_cpio_newc.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_cpio_newc.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_cpio_newc.c'; fi` + +libarchive/test/libarchive_test-test_write_format_cpio_odc.o: libarchive/test/test_write_format_cpio_odc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_cpio_odc.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio_odc.Tpo -c -o libarchive/test/libarchive_test-test_write_format_cpio_odc.o `test -f 'libarchive/test/test_write_format_cpio_odc.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_cpio_odc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio_odc.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio_odc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_cpio_odc.c' object='libarchive/test/libarchive_test-test_write_format_cpio_odc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_cpio_odc.o `test -f 'libarchive/test/test_write_format_cpio_odc.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_cpio_odc.c + +libarchive/test/libarchive_test-test_write_format_cpio_odc.obj: libarchive/test/test_write_format_cpio_odc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_cpio_odc.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio_odc.Tpo -c -o libarchive/test/libarchive_test-test_write_format_cpio_odc.obj `if test -f 'libarchive/test/test_write_format_cpio_odc.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_cpio_odc.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_cpio_odc.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio_odc.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_cpio_odc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_cpio_odc.c' object='libarchive/test/libarchive_test-test_write_format_cpio_odc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_cpio_odc.obj `if test -f 'libarchive/test/test_write_format_cpio_odc.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_cpio_odc.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_cpio_odc.c'; fi` + +libarchive/test/libarchive_test-test_write_format_gnutar.o: libarchive/test/test_write_format_gnutar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_gnutar.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_gnutar.Tpo -c -o libarchive/test/libarchive_test-test_write_format_gnutar.o `test -f 'libarchive/test/test_write_format_gnutar.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_gnutar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_gnutar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_gnutar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_gnutar.c' object='libarchive/test/libarchive_test-test_write_format_gnutar.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_gnutar.o `test -f 'libarchive/test/test_write_format_gnutar.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_gnutar.c + +libarchive/test/libarchive_test-test_write_format_gnutar.obj: libarchive/test/test_write_format_gnutar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_gnutar.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_gnutar.Tpo -c -o libarchive/test/libarchive_test-test_write_format_gnutar.obj `if test -f 'libarchive/test/test_write_format_gnutar.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_gnutar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_gnutar.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_gnutar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_gnutar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_gnutar.c' object='libarchive/test/libarchive_test-test_write_format_gnutar.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_gnutar.obj `if test -f 'libarchive/test/test_write_format_gnutar.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_gnutar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_gnutar.c'; fi` + +libarchive/test/libarchive_test-test_write_format_gnutar_filenames.o: libarchive/test/test_write_format_gnutar_filenames.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_gnutar_filenames.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_gnutar_filenames.Tpo -c -o libarchive/test/libarchive_test-test_write_format_gnutar_filenames.o `test -f 'libarchive/test/test_write_format_gnutar_filenames.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_gnutar_filenames.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_gnutar_filenames.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_gnutar_filenames.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_gnutar_filenames.c' object='libarchive/test/libarchive_test-test_write_format_gnutar_filenames.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_gnutar_filenames.o `test -f 'libarchive/test/test_write_format_gnutar_filenames.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_gnutar_filenames.c + +libarchive/test/libarchive_test-test_write_format_gnutar_filenames.obj: libarchive/test/test_write_format_gnutar_filenames.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_gnutar_filenames.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_gnutar_filenames.Tpo -c -o libarchive/test/libarchive_test-test_write_format_gnutar_filenames.obj `if test -f 'libarchive/test/test_write_format_gnutar_filenames.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_gnutar_filenames.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_gnutar_filenames.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_gnutar_filenames.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_gnutar_filenames.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_gnutar_filenames.c' object='libarchive/test/libarchive_test-test_write_format_gnutar_filenames.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_gnutar_filenames.obj `if test -f 'libarchive/test/test_write_format_gnutar_filenames.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_gnutar_filenames.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_gnutar_filenames.c'; fi` + +libarchive/test/libarchive_test-test_write_format_iso9660.o: libarchive/test/test_write_format_iso9660.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_iso9660.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660.Tpo -c -o libarchive/test/libarchive_test-test_write_format_iso9660.o `test -f 'libarchive/test/test_write_format_iso9660.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_iso9660.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_iso9660.c' object='libarchive/test/libarchive_test-test_write_format_iso9660.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_iso9660.o `test -f 'libarchive/test/test_write_format_iso9660.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_iso9660.c + +libarchive/test/libarchive_test-test_write_format_iso9660.obj: libarchive/test/test_write_format_iso9660.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_iso9660.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660.Tpo -c -o libarchive/test/libarchive_test-test_write_format_iso9660.obj `if test -f 'libarchive/test/test_write_format_iso9660.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_iso9660.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_iso9660.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_iso9660.c' object='libarchive/test/libarchive_test-test_write_format_iso9660.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_iso9660.obj `if test -f 'libarchive/test/test_write_format_iso9660.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_iso9660.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_iso9660.c'; fi` + +libarchive/test/libarchive_test-test_write_format_iso9660_boot.o: libarchive/test/test_write_format_iso9660_boot.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_iso9660_boot.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_boot.Tpo -c -o libarchive/test/libarchive_test-test_write_format_iso9660_boot.o `test -f 'libarchive/test/test_write_format_iso9660_boot.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_iso9660_boot.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_boot.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_boot.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_iso9660_boot.c' object='libarchive/test/libarchive_test-test_write_format_iso9660_boot.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_iso9660_boot.o `test -f 'libarchive/test/test_write_format_iso9660_boot.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_iso9660_boot.c + +libarchive/test/libarchive_test-test_write_format_iso9660_boot.obj: libarchive/test/test_write_format_iso9660_boot.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_iso9660_boot.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_boot.Tpo -c -o libarchive/test/libarchive_test-test_write_format_iso9660_boot.obj `if test -f 'libarchive/test/test_write_format_iso9660_boot.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_iso9660_boot.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_iso9660_boot.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_boot.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_boot.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_iso9660_boot.c' object='libarchive/test/libarchive_test-test_write_format_iso9660_boot.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_iso9660_boot.obj `if test -f 'libarchive/test/test_write_format_iso9660_boot.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_iso9660_boot.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_iso9660_boot.c'; fi` + +libarchive/test/libarchive_test-test_write_format_iso9660_empty.o: libarchive/test/test_write_format_iso9660_empty.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_iso9660_empty.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_empty.Tpo -c -o libarchive/test/libarchive_test-test_write_format_iso9660_empty.o `test -f 'libarchive/test/test_write_format_iso9660_empty.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_iso9660_empty.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_empty.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_empty.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_iso9660_empty.c' object='libarchive/test/libarchive_test-test_write_format_iso9660_empty.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_iso9660_empty.o `test -f 'libarchive/test/test_write_format_iso9660_empty.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_iso9660_empty.c + +libarchive/test/libarchive_test-test_write_format_iso9660_empty.obj: libarchive/test/test_write_format_iso9660_empty.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_iso9660_empty.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_empty.Tpo -c -o libarchive/test/libarchive_test-test_write_format_iso9660_empty.obj `if test -f 'libarchive/test/test_write_format_iso9660_empty.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_iso9660_empty.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_iso9660_empty.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_empty.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_empty.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_iso9660_empty.c' object='libarchive/test/libarchive_test-test_write_format_iso9660_empty.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_iso9660_empty.obj `if test -f 'libarchive/test/test_write_format_iso9660_empty.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_iso9660_empty.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_iso9660_empty.c'; fi` + +libarchive/test/libarchive_test-test_write_format_iso9660_filename.o: libarchive/test/test_write_format_iso9660_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_iso9660_filename.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_filename.Tpo -c -o libarchive/test/libarchive_test-test_write_format_iso9660_filename.o `test -f 'libarchive/test/test_write_format_iso9660_filename.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_iso9660_filename.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_filename.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_iso9660_filename.c' object='libarchive/test/libarchive_test-test_write_format_iso9660_filename.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_iso9660_filename.o `test -f 'libarchive/test/test_write_format_iso9660_filename.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_iso9660_filename.c + +libarchive/test/libarchive_test-test_write_format_iso9660_filename.obj: libarchive/test/test_write_format_iso9660_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_iso9660_filename.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_filename.Tpo -c -o libarchive/test/libarchive_test-test_write_format_iso9660_filename.obj `if test -f 'libarchive/test/test_write_format_iso9660_filename.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_iso9660_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_iso9660_filename.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_filename.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_iso9660_filename.c' object='libarchive/test/libarchive_test-test_write_format_iso9660_filename.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_iso9660_filename.obj `if test -f 'libarchive/test/test_write_format_iso9660_filename.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_iso9660_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_iso9660_filename.c'; fi` + +libarchive/test/libarchive_test-test_write_format_iso9660_zisofs.o: libarchive/test/test_write_format_iso9660_zisofs.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_iso9660_zisofs.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_zisofs.Tpo -c -o libarchive/test/libarchive_test-test_write_format_iso9660_zisofs.o `test -f 'libarchive/test/test_write_format_iso9660_zisofs.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_iso9660_zisofs.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_zisofs.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_zisofs.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_iso9660_zisofs.c' object='libarchive/test/libarchive_test-test_write_format_iso9660_zisofs.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_iso9660_zisofs.o `test -f 'libarchive/test/test_write_format_iso9660_zisofs.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_iso9660_zisofs.c + +libarchive/test/libarchive_test-test_write_format_iso9660_zisofs.obj: libarchive/test/test_write_format_iso9660_zisofs.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_iso9660_zisofs.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_zisofs.Tpo -c -o libarchive/test/libarchive_test-test_write_format_iso9660_zisofs.obj `if test -f 'libarchive/test/test_write_format_iso9660_zisofs.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_iso9660_zisofs.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_iso9660_zisofs.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_zisofs.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_iso9660_zisofs.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_iso9660_zisofs.c' object='libarchive/test/libarchive_test-test_write_format_iso9660_zisofs.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_iso9660_zisofs.obj `if test -f 'libarchive/test/test_write_format_iso9660_zisofs.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_iso9660_zisofs.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_iso9660_zisofs.c'; fi` + +libarchive/test/libarchive_test-test_write_format_mtree.o: libarchive/test/test_write_format_mtree.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_mtree.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree.Tpo -c -o libarchive/test/libarchive_test-test_write_format_mtree.o `test -f 'libarchive/test/test_write_format_mtree.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_mtree.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_mtree.c' object='libarchive/test/libarchive_test-test_write_format_mtree.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_mtree.o `test -f 'libarchive/test/test_write_format_mtree.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_mtree.c + +libarchive/test/libarchive_test-test_write_format_mtree.obj: libarchive/test/test_write_format_mtree.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_mtree.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree.Tpo -c -o libarchive/test/libarchive_test-test_write_format_mtree.obj `if test -f 'libarchive/test/test_write_format_mtree.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_mtree.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_mtree.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_mtree.c' object='libarchive/test/libarchive_test-test_write_format_mtree.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_mtree.obj `if test -f 'libarchive/test/test_write_format_mtree.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_mtree.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_mtree.c'; fi` + +libarchive/test/libarchive_test-test_write_format_mtree_absolute_path.o: libarchive/test/test_write_format_mtree_absolute_path.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_mtree_absolute_path.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_absolute_path.Tpo -c -o libarchive/test/libarchive_test-test_write_format_mtree_absolute_path.o `test -f 'libarchive/test/test_write_format_mtree_absolute_path.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_mtree_absolute_path.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_absolute_path.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_absolute_path.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_mtree_absolute_path.c' object='libarchive/test/libarchive_test-test_write_format_mtree_absolute_path.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_mtree_absolute_path.o `test -f 'libarchive/test/test_write_format_mtree_absolute_path.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_mtree_absolute_path.c + +libarchive/test/libarchive_test-test_write_format_mtree_absolute_path.obj: libarchive/test/test_write_format_mtree_absolute_path.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_mtree_absolute_path.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_absolute_path.Tpo -c -o libarchive/test/libarchive_test-test_write_format_mtree_absolute_path.obj `if test -f 'libarchive/test/test_write_format_mtree_absolute_path.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_mtree_absolute_path.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_mtree_absolute_path.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_absolute_path.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_absolute_path.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_mtree_absolute_path.c' object='libarchive/test/libarchive_test-test_write_format_mtree_absolute_path.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_mtree_absolute_path.obj `if test -f 'libarchive/test/test_write_format_mtree_absolute_path.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_mtree_absolute_path.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_mtree_absolute_path.c'; fi` + +libarchive/test/libarchive_test-test_write_format_mtree_classic.o: libarchive/test/test_write_format_mtree_classic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_mtree_classic.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_classic.Tpo -c -o libarchive/test/libarchive_test-test_write_format_mtree_classic.o `test -f 'libarchive/test/test_write_format_mtree_classic.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_mtree_classic.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_classic.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_classic.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_mtree_classic.c' object='libarchive/test/libarchive_test-test_write_format_mtree_classic.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_mtree_classic.o `test -f 'libarchive/test/test_write_format_mtree_classic.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_mtree_classic.c + +libarchive/test/libarchive_test-test_write_format_mtree_classic.obj: libarchive/test/test_write_format_mtree_classic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_mtree_classic.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_classic.Tpo -c -o libarchive/test/libarchive_test-test_write_format_mtree_classic.obj `if test -f 'libarchive/test/test_write_format_mtree_classic.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_mtree_classic.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_mtree_classic.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_classic.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_classic.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_mtree_classic.c' object='libarchive/test/libarchive_test-test_write_format_mtree_classic.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_mtree_classic.obj `if test -f 'libarchive/test/test_write_format_mtree_classic.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_mtree_classic.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_mtree_classic.c'; fi` + +libarchive/test/libarchive_test-test_write_format_mtree_classic_indent.o: libarchive/test/test_write_format_mtree_classic_indent.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_mtree_classic_indent.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_classic_indent.Tpo -c -o libarchive/test/libarchive_test-test_write_format_mtree_classic_indent.o `test -f 'libarchive/test/test_write_format_mtree_classic_indent.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_mtree_classic_indent.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_classic_indent.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_classic_indent.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_mtree_classic_indent.c' object='libarchive/test/libarchive_test-test_write_format_mtree_classic_indent.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_mtree_classic_indent.o `test -f 'libarchive/test/test_write_format_mtree_classic_indent.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_mtree_classic_indent.c + +libarchive/test/libarchive_test-test_write_format_mtree_classic_indent.obj: libarchive/test/test_write_format_mtree_classic_indent.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_mtree_classic_indent.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_classic_indent.Tpo -c -o libarchive/test/libarchive_test-test_write_format_mtree_classic_indent.obj `if test -f 'libarchive/test/test_write_format_mtree_classic_indent.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_mtree_classic_indent.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_mtree_classic_indent.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_classic_indent.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_classic_indent.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_mtree_classic_indent.c' object='libarchive/test/libarchive_test-test_write_format_mtree_classic_indent.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_mtree_classic_indent.obj `if test -f 'libarchive/test/test_write_format_mtree_classic_indent.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_mtree_classic_indent.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_mtree_classic_indent.c'; fi` + +libarchive/test/libarchive_test-test_write_format_mtree_fflags.o: libarchive/test/test_write_format_mtree_fflags.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_mtree_fflags.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_fflags.Tpo -c -o libarchive/test/libarchive_test-test_write_format_mtree_fflags.o `test -f 'libarchive/test/test_write_format_mtree_fflags.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_mtree_fflags.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_fflags.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_fflags.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_mtree_fflags.c' object='libarchive/test/libarchive_test-test_write_format_mtree_fflags.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_mtree_fflags.o `test -f 'libarchive/test/test_write_format_mtree_fflags.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_mtree_fflags.c + +libarchive/test/libarchive_test-test_write_format_mtree_fflags.obj: libarchive/test/test_write_format_mtree_fflags.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_mtree_fflags.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_fflags.Tpo -c -o libarchive/test/libarchive_test-test_write_format_mtree_fflags.obj `if test -f 'libarchive/test/test_write_format_mtree_fflags.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_mtree_fflags.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_mtree_fflags.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_fflags.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_fflags.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_mtree_fflags.c' object='libarchive/test/libarchive_test-test_write_format_mtree_fflags.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_mtree_fflags.obj `if test -f 'libarchive/test/test_write_format_mtree_fflags.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_mtree_fflags.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_mtree_fflags.c'; fi` + +libarchive/test/libarchive_test-test_write_format_mtree_no_separator.o: libarchive/test/test_write_format_mtree_no_separator.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_mtree_no_separator.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_no_separator.Tpo -c -o libarchive/test/libarchive_test-test_write_format_mtree_no_separator.o `test -f 'libarchive/test/test_write_format_mtree_no_separator.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_mtree_no_separator.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_no_separator.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_no_separator.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_mtree_no_separator.c' object='libarchive/test/libarchive_test-test_write_format_mtree_no_separator.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_mtree_no_separator.o `test -f 'libarchive/test/test_write_format_mtree_no_separator.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_mtree_no_separator.c + +libarchive/test/libarchive_test-test_write_format_mtree_no_separator.obj: libarchive/test/test_write_format_mtree_no_separator.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_mtree_no_separator.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_no_separator.Tpo -c -o libarchive/test/libarchive_test-test_write_format_mtree_no_separator.obj `if test -f 'libarchive/test/test_write_format_mtree_no_separator.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_mtree_no_separator.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_mtree_no_separator.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_no_separator.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_no_separator.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_mtree_no_separator.c' object='libarchive/test/libarchive_test-test_write_format_mtree_no_separator.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_mtree_no_separator.obj `if test -f 'libarchive/test/test_write_format_mtree_no_separator.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_mtree_no_separator.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_mtree_no_separator.c'; fi` + +libarchive/test/libarchive_test-test_write_format_mtree_quoted_filename.o: libarchive/test/test_write_format_mtree_quoted_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_mtree_quoted_filename.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_quoted_filename.Tpo -c -o libarchive/test/libarchive_test-test_write_format_mtree_quoted_filename.o `test -f 'libarchive/test/test_write_format_mtree_quoted_filename.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_mtree_quoted_filename.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_quoted_filename.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_quoted_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_mtree_quoted_filename.c' object='libarchive/test/libarchive_test-test_write_format_mtree_quoted_filename.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_mtree_quoted_filename.o `test -f 'libarchive/test/test_write_format_mtree_quoted_filename.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_mtree_quoted_filename.c + +libarchive/test/libarchive_test-test_write_format_mtree_quoted_filename.obj: libarchive/test/test_write_format_mtree_quoted_filename.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_mtree_quoted_filename.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_quoted_filename.Tpo -c -o libarchive/test/libarchive_test-test_write_format_mtree_quoted_filename.obj `if test -f 'libarchive/test/test_write_format_mtree_quoted_filename.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_mtree_quoted_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_mtree_quoted_filename.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_quoted_filename.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_mtree_quoted_filename.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_mtree_quoted_filename.c' object='libarchive/test/libarchive_test-test_write_format_mtree_quoted_filename.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_mtree_quoted_filename.obj `if test -f 'libarchive/test/test_write_format_mtree_quoted_filename.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_mtree_quoted_filename.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_mtree_quoted_filename.c'; fi` + +libarchive/test/libarchive_test-test_write_format_pax.o: libarchive/test/test_write_format_pax.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_pax.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_pax.Tpo -c -o libarchive/test/libarchive_test-test_write_format_pax.o `test -f 'libarchive/test/test_write_format_pax.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_pax.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_pax.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_pax.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_pax.c' object='libarchive/test/libarchive_test-test_write_format_pax.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_pax.o `test -f 'libarchive/test/test_write_format_pax.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_pax.c + +libarchive/test/libarchive_test-test_write_format_pax.obj: libarchive/test/test_write_format_pax.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_pax.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_pax.Tpo -c -o libarchive/test/libarchive_test-test_write_format_pax.obj `if test -f 'libarchive/test/test_write_format_pax.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_pax.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_pax.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_pax.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_pax.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_pax.c' object='libarchive/test/libarchive_test-test_write_format_pax.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_pax.obj `if test -f 'libarchive/test/test_write_format_pax.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_pax.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_pax.c'; fi` + +libarchive/test/libarchive_test-test_write_format_raw.o: libarchive/test/test_write_format_raw.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_raw.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_raw.Tpo -c -o libarchive/test/libarchive_test-test_write_format_raw.o `test -f 'libarchive/test/test_write_format_raw.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_raw.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_raw.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_raw.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_raw.c' object='libarchive/test/libarchive_test-test_write_format_raw.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_raw.o `test -f 'libarchive/test/test_write_format_raw.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_raw.c + +libarchive/test/libarchive_test-test_write_format_raw.obj: libarchive/test/test_write_format_raw.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_raw.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_raw.Tpo -c -o libarchive/test/libarchive_test-test_write_format_raw.obj `if test -f 'libarchive/test/test_write_format_raw.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_raw.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_raw.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_raw.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_raw.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_raw.c' object='libarchive/test/libarchive_test-test_write_format_raw.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_raw.obj `if test -f 'libarchive/test/test_write_format_raw.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_raw.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_raw.c'; fi` + +libarchive/test/libarchive_test-test_write_format_raw_b64.o: libarchive/test/test_write_format_raw_b64.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_raw_b64.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_raw_b64.Tpo -c -o libarchive/test/libarchive_test-test_write_format_raw_b64.o `test -f 'libarchive/test/test_write_format_raw_b64.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_raw_b64.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_raw_b64.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_raw_b64.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_raw_b64.c' object='libarchive/test/libarchive_test-test_write_format_raw_b64.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_raw_b64.o `test -f 'libarchive/test/test_write_format_raw_b64.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_raw_b64.c + +libarchive/test/libarchive_test-test_write_format_raw_b64.obj: libarchive/test/test_write_format_raw_b64.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_raw_b64.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_raw_b64.Tpo -c -o libarchive/test/libarchive_test-test_write_format_raw_b64.obj `if test -f 'libarchive/test/test_write_format_raw_b64.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_raw_b64.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_raw_b64.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_raw_b64.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_raw_b64.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_raw_b64.c' object='libarchive/test/libarchive_test-test_write_format_raw_b64.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_raw_b64.obj `if test -f 'libarchive/test/test_write_format_raw_b64.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_raw_b64.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_raw_b64.c'; fi` + +libarchive/test/libarchive_test-test_write_format_shar_empty.o: libarchive/test/test_write_format_shar_empty.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_shar_empty.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_shar_empty.Tpo -c -o libarchive/test/libarchive_test-test_write_format_shar_empty.o `test -f 'libarchive/test/test_write_format_shar_empty.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_shar_empty.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_shar_empty.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_shar_empty.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_shar_empty.c' object='libarchive/test/libarchive_test-test_write_format_shar_empty.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_shar_empty.o `test -f 'libarchive/test/test_write_format_shar_empty.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_shar_empty.c + +libarchive/test/libarchive_test-test_write_format_shar_empty.obj: libarchive/test/test_write_format_shar_empty.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_shar_empty.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_shar_empty.Tpo -c -o libarchive/test/libarchive_test-test_write_format_shar_empty.obj `if test -f 'libarchive/test/test_write_format_shar_empty.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_shar_empty.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_shar_empty.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_shar_empty.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_shar_empty.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_shar_empty.c' object='libarchive/test/libarchive_test-test_write_format_shar_empty.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_shar_empty.obj `if test -f 'libarchive/test/test_write_format_shar_empty.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_shar_empty.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_shar_empty.c'; fi` + +libarchive/test/libarchive_test-test_write_format_tar.o: libarchive/test/test_write_format_tar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_tar.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar.Tpo -c -o libarchive/test/libarchive_test-test_write_format_tar.o `test -f 'libarchive/test/test_write_format_tar.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_tar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_tar.c' object='libarchive/test/libarchive_test-test_write_format_tar.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_tar.o `test -f 'libarchive/test/test_write_format_tar.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_tar.c + +libarchive/test/libarchive_test-test_write_format_tar.obj: libarchive/test/test_write_format_tar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_tar.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar.Tpo -c -o libarchive/test/libarchive_test-test_write_format_tar.obj `if test -f 'libarchive/test/test_write_format_tar.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_tar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_tar.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_tar.c' object='libarchive/test/libarchive_test-test_write_format_tar.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_tar.obj `if test -f 'libarchive/test/test_write_format_tar.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_tar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_tar.c'; fi` + +libarchive/test/libarchive_test-test_write_format_tar_empty.o: libarchive/test/test_write_format_tar_empty.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_tar_empty.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_empty.Tpo -c -o libarchive/test/libarchive_test-test_write_format_tar_empty.o `test -f 'libarchive/test/test_write_format_tar_empty.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_tar_empty.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_empty.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_empty.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_tar_empty.c' object='libarchive/test/libarchive_test-test_write_format_tar_empty.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_tar_empty.o `test -f 'libarchive/test/test_write_format_tar_empty.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_tar_empty.c + +libarchive/test/libarchive_test-test_write_format_tar_empty.obj: libarchive/test/test_write_format_tar_empty.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_tar_empty.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_empty.Tpo -c -o libarchive/test/libarchive_test-test_write_format_tar_empty.obj `if test -f 'libarchive/test/test_write_format_tar_empty.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_tar_empty.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_tar_empty.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_empty.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_empty.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_tar_empty.c' object='libarchive/test/libarchive_test-test_write_format_tar_empty.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_tar_empty.obj `if test -f 'libarchive/test/test_write_format_tar_empty.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_tar_empty.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_tar_empty.c'; fi` + +libarchive/test/libarchive_test-test_write_format_tar_sparse.o: libarchive/test/test_write_format_tar_sparse.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_tar_sparse.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_sparse.Tpo -c -o libarchive/test/libarchive_test-test_write_format_tar_sparse.o `test -f 'libarchive/test/test_write_format_tar_sparse.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_tar_sparse.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_sparse.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_sparse.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_tar_sparse.c' object='libarchive/test/libarchive_test-test_write_format_tar_sparse.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_tar_sparse.o `test -f 'libarchive/test/test_write_format_tar_sparse.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_tar_sparse.c + +libarchive/test/libarchive_test-test_write_format_tar_sparse.obj: libarchive/test/test_write_format_tar_sparse.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_tar_sparse.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_sparse.Tpo -c -o libarchive/test/libarchive_test-test_write_format_tar_sparse.obj `if test -f 'libarchive/test/test_write_format_tar_sparse.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_tar_sparse.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_tar_sparse.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_sparse.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_sparse.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_tar_sparse.c' object='libarchive/test/libarchive_test-test_write_format_tar_sparse.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_tar_sparse.obj `if test -f 'libarchive/test/test_write_format_tar_sparse.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_tar_sparse.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_tar_sparse.c'; fi` + +libarchive/test/libarchive_test-test_write_format_tar_ustar.o: libarchive/test/test_write_format_tar_ustar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_tar_ustar.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_ustar.Tpo -c -o libarchive/test/libarchive_test-test_write_format_tar_ustar.o `test -f 'libarchive/test/test_write_format_tar_ustar.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_tar_ustar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_ustar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_ustar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_tar_ustar.c' object='libarchive/test/libarchive_test-test_write_format_tar_ustar.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_tar_ustar.o `test -f 'libarchive/test/test_write_format_tar_ustar.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_tar_ustar.c + +libarchive/test/libarchive_test-test_write_format_tar_ustar.obj: libarchive/test/test_write_format_tar_ustar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_tar_ustar.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_ustar.Tpo -c -o libarchive/test/libarchive_test-test_write_format_tar_ustar.obj `if test -f 'libarchive/test/test_write_format_tar_ustar.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_tar_ustar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_tar_ustar.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_ustar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_ustar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_tar_ustar.c' object='libarchive/test/libarchive_test-test_write_format_tar_ustar.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_tar_ustar.obj `if test -f 'libarchive/test/test_write_format_tar_ustar.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_tar_ustar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_tar_ustar.c'; fi` + +libarchive/test/libarchive_test-test_write_format_tar_v7tar.o: libarchive/test/test_write_format_tar_v7tar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_tar_v7tar.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_v7tar.Tpo -c -o libarchive/test/libarchive_test-test_write_format_tar_v7tar.o `test -f 'libarchive/test/test_write_format_tar_v7tar.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_tar_v7tar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_v7tar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_v7tar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_tar_v7tar.c' object='libarchive/test/libarchive_test-test_write_format_tar_v7tar.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_tar_v7tar.o `test -f 'libarchive/test/test_write_format_tar_v7tar.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_tar_v7tar.c + +libarchive/test/libarchive_test-test_write_format_tar_v7tar.obj: libarchive/test/test_write_format_tar_v7tar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_tar_v7tar.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_v7tar.Tpo -c -o libarchive/test/libarchive_test-test_write_format_tar_v7tar.obj `if test -f 'libarchive/test/test_write_format_tar_v7tar.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_tar_v7tar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_tar_v7tar.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_v7tar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_tar_v7tar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_tar_v7tar.c' object='libarchive/test/libarchive_test-test_write_format_tar_v7tar.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_tar_v7tar.obj `if test -f 'libarchive/test/test_write_format_tar_v7tar.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_tar_v7tar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_tar_v7tar.c'; fi` + +libarchive/test/libarchive_test-test_write_format_warc.o: libarchive/test/test_write_format_warc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_warc.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_warc.Tpo -c -o libarchive/test/libarchive_test-test_write_format_warc.o `test -f 'libarchive/test/test_write_format_warc.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_warc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_warc.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_warc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_warc.c' object='libarchive/test/libarchive_test-test_write_format_warc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_warc.o `test -f 'libarchive/test/test_write_format_warc.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_warc.c + +libarchive/test/libarchive_test-test_write_format_warc.obj: libarchive/test/test_write_format_warc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_warc.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_warc.Tpo -c -o libarchive/test/libarchive_test-test_write_format_warc.obj `if test -f 'libarchive/test/test_write_format_warc.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_warc.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_warc.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_warc.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_warc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_warc.c' object='libarchive/test/libarchive_test-test_write_format_warc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_warc.obj `if test -f 'libarchive/test/test_write_format_warc.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_warc.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_warc.c'; fi` + +libarchive/test/libarchive_test-test_write_format_warc_empty.o: libarchive/test/test_write_format_warc_empty.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_warc_empty.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_warc_empty.Tpo -c -o libarchive/test/libarchive_test-test_write_format_warc_empty.o `test -f 'libarchive/test/test_write_format_warc_empty.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_warc_empty.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_warc_empty.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_warc_empty.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_warc_empty.c' object='libarchive/test/libarchive_test-test_write_format_warc_empty.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_warc_empty.o `test -f 'libarchive/test/test_write_format_warc_empty.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_warc_empty.c + +libarchive/test/libarchive_test-test_write_format_warc_empty.obj: libarchive/test/test_write_format_warc_empty.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_warc_empty.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_warc_empty.Tpo -c -o libarchive/test/libarchive_test-test_write_format_warc_empty.obj `if test -f 'libarchive/test/test_write_format_warc_empty.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_warc_empty.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_warc_empty.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_warc_empty.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_warc_empty.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_warc_empty.c' object='libarchive/test/libarchive_test-test_write_format_warc_empty.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_warc_empty.obj `if test -f 'libarchive/test/test_write_format_warc_empty.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_warc_empty.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_warc_empty.c'; fi` + +libarchive/test/libarchive_test-test_write_format_xar.o: libarchive/test/test_write_format_xar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_xar.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_xar.Tpo -c -o libarchive/test/libarchive_test-test_write_format_xar.o `test -f 'libarchive/test/test_write_format_xar.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_xar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_xar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_xar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_xar.c' object='libarchive/test/libarchive_test-test_write_format_xar.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_xar.o `test -f 'libarchive/test/test_write_format_xar.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_xar.c + +libarchive/test/libarchive_test-test_write_format_xar.obj: libarchive/test/test_write_format_xar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_xar.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_xar.Tpo -c -o libarchive/test/libarchive_test-test_write_format_xar.obj `if test -f 'libarchive/test/test_write_format_xar.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_xar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_xar.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_xar.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_xar.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_xar.c' object='libarchive/test/libarchive_test-test_write_format_xar.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_xar.obj `if test -f 'libarchive/test/test_write_format_xar.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_xar.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_xar.c'; fi` + +libarchive/test/libarchive_test-test_write_format_xar_empty.o: libarchive/test/test_write_format_xar_empty.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_xar_empty.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_xar_empty.Tpo -c -o libarchive/test/libarchive_test-test_write_format_xar_empty.o `test -f 'libarchive/test/test_write_format_xar_empty.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_xar_empty.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_xar_empty.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_xar_empty.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_xar_empty.c' object='libarchive/test/libarchive_test-test_write_format_xar_empty.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_xar_empty.o `test -f 'libarchive/test/test_write_format_xar_empty.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_xar_empty.c + +libarchive/test/libarchive_test-test_write_format_xar_empty.obj: libarchive/test/test_write_format_xar_empty.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_xar_empty.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_xar_empty.Tpo -c -o libarchive/test/libarchive_test-test_write_format_xar_empty.obj `if test -f 'libarchive/test/test_write_format_xar_empty.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_xar_empty.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_xar_empty.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_xar_empty.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_xar_empty.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_xar_empty.c' object='libarchive/test/libarchive_test-test_write_format_xar_empty.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_xar_empty.obj `if test -f 'libarchive/test/test_write_format_xar_empty.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_xar_empty.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_xar_empty.c'; fi` + +libarchive/test/libarchive_test-test_write_format_zip.o: libarchive/test/test_write_format_zip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_zip.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip.Tpo -c -o libarchive/test/libarchive_test-test_write_format_zip.o `test -f 'libarchive/test/test_write_format_zip.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_zip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_zip.c' object='libarchive/test/libarchive_test-test_write_format_zip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_zip.o `test -f 'libarchive/test/test_write_format_zip.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_zip.c + +libarchive/test/libarchive_test-test_write_format_zip.obj: libarchive/test/test_write_format_zip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_zip.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip.Tpo -c -o libarchive/test/libarchive_test-test_write_format_zip.obj `if test -f 'libarchive/test/test_write_format_zip.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_zip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_zip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_zip.c' object='libarchive/test/libarchive_test-test_write_format_zip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_zip.obj `if test -f 'libarchive/test/test_write_format_zip.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_zip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_zip.c'; fi` + +libarchive/test/libarchive_test-test_write_format_zip_compression_store.o: libarchive/test/test_write_format_zip_compression_store.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_zip_compression_store.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_compression_store.Tpo -c -o libarchive/test/libarchive_test-test_write_format_zip_compression_store.o `test -f 'libarchive/test/test_write_format_zip_compression_store.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_zip_compression_store.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_compression_store.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_compression_store.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_zip_compression_store.c' object='libarchive/test/libarchive_test-test_write_format_zip_compression_store.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_zip_compression_store.o `test -f 'libarchive/test/test_write_format_zip_compression_store.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_zip_compression_store.c + +libarchive/test/libarchive_test-test_write_format_zip_compression_store.obj: libarchive/test/test_write_format_zip_compression_store.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_zip_compression_store.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_compression_store.Tpo -c -o libarchive/test/libarchive_test-test_write_format_zip_compression_store.obj `if test -f 'libarchive/test/test_write_format_zip_compression_store.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_zip_compression_store.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_zip_compression_store.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_compression_store.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_compression_store.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_zip_compression_store.c' object='libarchive/test/libarchive_test-test_write_format_zip_compression_store.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_zip_compression_store.obj `if test -f 'libarchive/test/test_write_format_zip_compression_store.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_zip_compression_store.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_zip_compression_store.c'; fi` + +libarchive/test/libarchive_test-test_write_format_zip_empty.o: libarchive/test/test_write_format_zip_empty.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_zip_empty.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_empty.Tpo -c -o libarchive/test/libarchive_test-test_write_format_zip_empty.o `test -f 'libarchive/test/test_write_format_zip_empty.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_zip_empty.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_empty.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_empty.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_zip_empty.c' object='libarchive/test/libarchive_test-test_write_format_zip_empty.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_zip_empty.o `test -f 'libarchive/test/test_write_format_zip_empty.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_zip_empty.c + +libarchive/test/libarchive_test-test_write_format_zip_empty.obj: libarchive/test/test_write_format_zip_empty.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_zip_empty.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_empty.Tpo -c -o libarchive/test/libarchive_test-test_write_format_zip_empty.obj `if test -f 'libarchive/test/test_write_format_zip_empty.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_zip_empty.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_zip_empty.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_empty.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_empty.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_zip_empty.c' object='libarchive/test/libarchive_test-test_write_format_zip_empty.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_zip_empty.obj `if test -f 'libarchive/test/test_write_format_zip_empty.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_zip_empty.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_zip_empty.c'; fi` + +libarchive/test/libarchive_test-test_write_format_zip_empty_zip64.o: libarchive/test/test_write_format_zip_empty_zip64.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_zip_empty_zip64.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_empty_zip64.Tpo -c -o libarchive/test/libarchive_test-test_write_format_zip_empty_zip64.o `test -f 'libarchive/test/test_write_format_zip_empty_zip64.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_zip_empty_zip64.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_empty_zip64.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_empty_zip64.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_zip_empty_zip64.c' object='libarchive/test/libarchive_test-test_write_format_zip_empty_zip64.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_zip_empty_zip64.o `test -f 'libarchive/test/test_write_format_zip_empty_zip64.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_zip_empty_zip64.c + +libarchive/test/libarchive_test-test_write_format_zip_empty_zip64.obj: libarchive/test/test_write_format_zip_empty_zip64.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_zip_empty_zip64.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_empty_zip64.Tpo -c -o libarchive/test/libarchive_test-test_write_format_zip_empty_zip64.obj `if test -f 'libarchive/test/test_write_format_zip_empty_zip64.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_zip_empty_zip64.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_zip_empty_zip64.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_empty_zip64.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_empty_zip64.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_zip_empty_zip64.c' object='libarchive/test/libarchive_test-test_write_format_zip_empty_zip64.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_zip_empty_zip64.obj `if test -f 'libarchive/test/test_write_format_zip_empty_zip64.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_zip_empty_zip64.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_zip_empty_zip64.c'; fi` + +libarchive/test/libarchive_test-test_write_format_zip_file.o: libarchive/test/test_write_format_zip_file.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_zip_file.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_file.Tpo -c -o libarchive/test/libarchive_test-test_write_format_zip_file.o `test -f 'libarchive/test/test_write_format_zip_file.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_zip_file.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_file.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_file.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_zip_file.c' object='libarchive/test/libarchive_test-test_write_format_zip_file.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_zip_file.o `test -f 'libarchive/test/test_write_format_zip_file.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_zip_file.c + +libarchive/test/libarchive_test-test_write_format_zip_file.obj: libarchive/test/test_write_format_zip_file.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_zip_file.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_file.Tpo -c -o libarchive/test/libarchive_test-test_write_format_zip_file.obj `if test -f 'libarchive/test/test_write_format_zip_file.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_zip_file.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_zip_file.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_file.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_file.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_zip_file.c' object='libarchive/test/libarchive_test-test_write_format_zip_file.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_zip_file.obj `if test -f 'libarchive/test/test_write_format_zip_file.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_zip_file.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_zip_file.c'; fi` + +libarchive/test/libarchive_test-test_write_format_zip_file_zip64.o: libarchive/test/test_write_format_zip_file_zip64.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_zip_file_zip64.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_file_zip64.Tpo -c -o libarchive/test/libarchive_test-test_write_format_zip_file_zip64.o `test -f 'libarchive/test/test_write_format_zip_file_zip64.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_zip_file_zip64.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_file_zip64.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_file_zip64.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_zip_file_zip64.c' object='libarchive/test/libarchive_test-test_write_format_zip_file_zip64.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_zip_file_zip64.o `test -f 'libarchive/test/test_write_format_zip_file_zip64.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_zip_file_zip64.c + +libarchive/test/libarchive_test-test_write_format_zip_file_zip64.obj: libarchive/test/test_write_format_zip_file_zip64.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_zip_file_zip64.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_file_zip64.Tpo -c -o libarchive/test/libarchive_test-test_write_format_zip_file_zip64.obj `if test -f 'libarchive/test/test_write_format_zip_file_zip64.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_zip_file_zip64.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_zip_file_zip64.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_file_zip64.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_file_zip64.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_zip_file_zip64.c' object='libarchive/test/libarchive_test-test_write_format_zip_file_zip64.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_zip_file_zip64.obj `if test -f 'libarchive/test/test_write_format_zip_file_zip64.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_zip_file_zip64.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_zip_file_zip64.c'; fi` + +libarchive/test/libarchive_test-test_write_format_zip_large.o: libarchive/test/test_write_format_zip_large.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_zip_large.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_large.Tpo -c -o libarchive/test/libarchive_test-test_write_format_zip_large.o `test -f 'libarchive/test/test_write_format_zip_large.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_zip_large.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_large.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_large.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_zip_large.c' object='libarchive/test/libarchive_test-test_write_format_zip_large.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_zip_large.o `test -f 'libarchive/test/test_write_format_zip_large.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_zip_large.c + +libarchive/test/libarchive_test-test_write_format_zip_large.obj: libarchive/test/test_write_format_zip_large.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_zip_large.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_large.Tpo -c -o libarchive/test/libarchive_test-test_write_format_zip_large.obj `if test -f 'libarchive/test/test_write_format_zip_large.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_zip_large.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_zip_large.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_large.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_large.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_zip_large.c' object='libarchive/test/libarchive_test-test_write_format_zip_large.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_zip_large.obj `if test -f 'libarchive/test/test_write_format_zip_large.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_zip_large.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_zip_large.c'; fi` + +libarchive/test/libarchive_test-test_write_format_zip_zip64.o: libarchive/test/test_write_format_zip_zip64.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_zip_zip64.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_zip64.Tpo -c -o libarchive/test/libarchive_test-test_write_format_zip_zip64.o `test -f 'libarchive/test/test_write_format_zip_zip64.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_zip_zip64.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_zip64.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_zip64.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_zip_zip64.c' object='libarchive/test/libarchive_test-test_write_format_zip_zip64.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_zip_zip64.o `test -f 'libarchive/test/test_write_format_zip_zip64.c' || echo '$(srcdir)/'`libarchive/test/test_write_format_zip_zip64.c + +libarchive/test/libarchive_test-test_write_format_zip_zip64.obj: libarchive/test/test_write_format_zip_zip64.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_format_zip_zip64.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_zip64.Tpo -c -o libarchive/test/libarchive_test-test_write_format_zip_zip64.obj `if test -f 'libarchive/test/test_write_format_zip_zip64.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_zip_zip64.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_zip_zip64.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_zip64.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_format_zip_zip64.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_format_zip_zip64.c' object='libarchive/test/libarchive_test-test_write_format_zip_zip64.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_format_zip_zip64.obj `if test -f 'libarchive/test/test_write_format_zip_zip64.c'; then $(CYGPATH_W) 'libarchive/test/test_write_format_zip_zip64.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_format_zip_zip64.c'; fi` + +libarchive/test/libarchive_test-test_write_open_memory.o: libarchive/test/test_write_open_memory.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_open_memory.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_open_memory.Tpo -c -o libarchive/test/libarchive_test-test_write_open_memory.o `test -f 'libarchive/test/test_write_open_memory.c' || echo '$(srcdir)/'`libarchive/test/test_write_open_memory.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_open_memory.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_open_memory.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_open_memory.c' object='libarchive/test/libarchive_test-test_write_open_memory.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_open_memory.o `test -f 'libarchive/test/test_write_open_memory.c' || echo '$(srcdir)/'`libarchive/test/test_write_open_memory.c + +libarchive/test/libarchive_test-test_write_open_memory.obj: libarchive/test/test_write_open_memory.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_open_memory.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_open_memory.Tpo -c -o libarchive/test/libarchive_test-test_write_open_memory.obj `if test -f 'libarchive/test/test_write_open_memory.c'; then $(CYGPATH_W) 'libarchive/test/test_write_open_memory.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_open_memory.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_open_memory.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_open_memory.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_open_memory.c' object='libarchive/test/libarchive_test-test_write_open_memory.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_open_memory.obj `if test -f 'libarchive/test/test_write_open_memory.c'; then $(CYGPATH_W) 'libarchive/test/test_write_open_memory.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_open_memory.c'; fi` + +libarchive/test/libarchive_test-test_write_read_format_zip.o: libarchive/test/test_write_read_format_zip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_read_format_zip.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_read_format_zip.Tpo -c -o libarchive/test/libarchive_test-test_write_read_format_zip.o `test -f 'libarchive/test/test_write_read_format_zip.c' || echo '$(srcdir)/'`libarchive/test/test_write_read_format_zip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_read_format_zip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_read_format_zip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_read_format_zip.c' object='libarchive/test/libarchive_test-test_write_read_format_zip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_read_format_zip.o `test -f 'libarchive/test/test_write_read_format_zip.c' || echo '$(srcdir)/'`libarchive/test/test_write_read_format_zip.c + +libarchive/test/libarchive_test-test_write_read_format_zip.obj: libarchive/test/test_write_read_format_zip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_write_read_format_zip.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_write_read_format_zip.Tpo -c -o libarchive/test/libarchive_test-test_write_read_format_zip.obj `if test -f 'libarchive/test/test_write_read_format_zip.c'; then $(CYGPATH_W) 'libarchive/test/test_write_read_format_zip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_read_format_zip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_write_read_format_zip.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_write_read_format_zip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_write_read_format_zip.c' object='libarchive/test/libarchive_test-test_write_read_format_zip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_write_read_format_zip.obj `if test -f 'libarchive/test/test_write_read_format_zip.c'; then $(CYGPATH_W) 'libarchive/test/test_write_read_format_zip.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_write_read_format_zip.c'; fi` + +libarchive/test/libarchive_test-test_xattr_platform.o: libarchive/test/test_xattr_platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_xattr_platform.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_xattr_platform.Tpo -c -o libarchive/test/libarchive_test-test_xattr_platform.o `test -f 'libarchive/test/test_xattr_platform.c' || echo '$(srcdir)/'`libarchive/test/test_xattr_platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_xattr_platform.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_xattr_platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_xattr_platform.c' object='libarchive/test/libarchive_test-test_xattr_platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_xattr_platform.o `test -f 'libarchive/test/test_xattr_platform.c' || echo '$(srcdir)/'`libarchive/test/test_xattr_platform.c + +libarchive/test/libarchive_test-test_xattr_platform.obj: libarchive/test/test_xattr_platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_xattr_platform.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_xattr_platform.Tpo -c -o libarchive/test/libarchive_test-test_xattr_platform.obj `if test -f 'libarchive/test/test_xattr_platform.c'; then $(CYGPATH_W) 'libarchive/test/test_xattr_platform.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_xattr_platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_xattr_platform.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_xattr_platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_xattr_platform.c' object='libarchive/test/libarchive_test-test_xattr_platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_xattr_platform.obj `if test -f 'libarchive/test/test_xattr_platform.c'; then $(CYGPATH_W) 'libarchive/test/test_xattr_platform.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_xattr_platform.c'; fi` + +libarchive/test/libarchive_test-test_zip_filename_encoding.o: libarchive/test/test_zip_filename_encoding.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_zip_filename_encoding.o -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_zip_filename_encoding.Tpo -c -o libarchive/test/libarchive_test-test_zip_filename_encoding.o `test -f 'libarchive/test/test_zip_filename_encoding.c' || echo '$(srcdir)/'`libarchive/test/test_zip_filename_encoding.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_zip_filename_encoding.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_zip_filename_encoding.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_zip_filename_encoding.c' object='libarchive/test/libarchive_test-test_zip_filename_encoding.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_zip_filename_encoding.o `test -f 'libarchive/test/test_zip_filename_encoding.c' || echo '$(srcdir)/'`libarchive/test/test_zip_filename_encoding.c + +libarchive/test/libarchive_test-test_zip_filename_encoding.obj: libarchive/test/test_zip_filename_encoding.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libarchive/test/libarchive_test-test_zip_filename_encoding.obj -MD -MP -MF libarchive/test/$(DEPDIR)/libarchive_test-test_zip_filename_encoding.Tpo -c -o libarchive/test/libarchive_test-test_zip_filename_encoding.obj `if test -f 'libarchive/test/test_zip_filename_encoding.c'; then $(CYGPATH_W) 'libarchive/test/test_zip_filename_encoding.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_zip_filename_encoding.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libarchive/test/$(DEPDIR)/libarchive_test-test_zip_filename_encoding.Tpo libarchive/test/$(DEPDIR)/libarchive_test-test_zip_filename_encoding.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libarchive/test/test_zip_filename_encoding.c' object='libarchive/test/libarchive_test-test_zip_filename_encoding.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libarchive_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libarchive/test/libarchive_test-test_zip_filename_encoding.obj `if test -f 'libarchive/test/test_zip_filename_encoding.c'; then $(CYGPATH_W) 'libarchive/test/test_zip_filename_encoding.c'; else $(CYGPATH_W) '$(srcdir)/libarchive/test/test_zip_filename_encoding.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + -rm -rf libarchive/.libs libarchive/_libs + -rm -rf libarchive_fe/.libs libarchive_fe/_libs + +distclean-libtool: + -rm -f libtool config.lt +install-man1: $(man_MANS) + @$(NORMAL_INSTALL) + @list1=''; \ + list2='$(man_MANS)'; \ + test -n "$(man1dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.1[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ + done; } + +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list=''; test -n "$(man1dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.1[a-z]*$$/p'; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) +install-man3: $(man_MANS) + @$(NORMAL_INSTALL) + @list1=''; \ + list2='$(man_MANS)'; \ + test -n "$(man3dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man3dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man3dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.3[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man3dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man3dir)" || exit $$?; }; \ + done; } + +uninstall-man3: + @$(NORMAL_UNINSTALL) + @list=''; test -n "$(man3dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.3[a-z]*$$/p'; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man3dir)'; $(am__uninstall_files_from_dir) +install-man5: $(man_MANS) + @$(NORMAL_INSTALL) + @list1=''; \ + list2='$(man_MANS)'; \ + test -n "$(man5dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.5[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \ + done; } + +uninstall-man5: + @$(NORMAL_UNINSTALL) + @list=''; test -n "$(man5dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.5[a-z]*$$/p'; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir) +install-pkgconfigDATA: $(pkgconfig_DATA) + @$(NORMAL_INSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ + done + +uninstall-pkgconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) +install-includeHEADERS: $(include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \ + done + +uninstall-includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) +clean-cscope: + -rm -f cscope.files +cscope.files: clean-cscope cscopelist +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all $(check_PROGRAMS) + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +libarchive_test.log: libarchive_test$(EXEEXT) + @p='libarchive_test$(EXEEXT)'; \ + b='libarchive_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +bsdtar_test.log: bsdtar_test$(EXEEXT) + @p='bsdtar_test$(EXEEXT)'; \ + b='bsdtar_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +bsdcpio_test.log: bsdcpio_test$(EXEEXT) + @p='bsdcpio_test$(EXEEXT)'; \ + b='bsdcpio_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +bsdcat_test.log: bsdcat_test$(EXEEXT) + @p='bsdcat_test$(EXEEXT)'; \ + b='bsdcat_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz + $(am__post_remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__post_remove_distdir) + +dist-tarZ: distdir + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__post_remove_distdir) + +dist-shar: distdir + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz + $(am__post_remove_distdir) +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__post_remove_distdir) + +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + --srcdir=../.. --prefix="$$dc_install_base" \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__post_remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(MANS) $(DATA) $(HEADERS) \ + config.h +install-binPROGRAMS: install-libLTLIBRARIES + +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f cat/$(DEPDIR)/$(am__dirstamp) + -rm -f cat/$(am__dirstamp) + -rm -f cat/test/$(DEPDIR)/$(am__dirstamp) + -rm -f cat/test/$(am__dirstamp) + -rm -f cpio/$(DEPDIR)/$(am__dirstamp) + -rm -f cpio/$(am__dirstamp) + -rm -f cpio/test/$(DEPDIR)/$(am__dirstamp) + -rm -f cpio/test/$(am__dirstamp) + -rm -f libarchive/$(DEPDIR)/$(am__dirstamp) + -rm -f libarchive/$(am__dirstamp) + -rm -f libarchive/test/$(DEPDIR)/$(am__dirstamp) + -rm -f libarchive/test/$(am__dirstamp) + -rm -f libarchive_fe/$(DEPDIR)/$(am__dirstamp) + -rm -f libarchive_fe/$(am__dirstamp) + -rm -f tar/$(DEPDIR)/$(am__dirstamp) + -rm -f tar/$(am__dirstamp) + -rm -f tar/test/$(DEPDIR)/$(am__dirstamp) + -rm -f tar/test/$(am__dirstamp) + -rm -f test_utils/$(DEPDIR)/$(am__dirstamp) + -rm -f test_utils/$(am__dirstamp) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ + clean-libLTLIBRARIES clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf cat/$(DEPDIR) cat/test/$(DEPDIR) cpio/$(DEPDIR) cpio/test/$(DEPDIR) libarchive/$(DEPDIR) libarchive/test/$(DEPDIR) libarchive_fe/$(DEPDIR) tar/$(DEPDIR) tar/test/$(DEPDIR) test_utils/$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-hdr distclean-libtool distclean-local distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-includeHEADERS install-man \ + install-pkgconfigDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: install-man1 install-man3 install-man5 + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -rf cat/$(DEPDIR) cat/test/$(DEPDIR) cpio/$(DEPDIR) cpio/test/$(DEPDIR) libarchive/$(DEPDIR) libarchive/test/$(DEPDIR) libarchive_fe/$(DEPDIR) tar/$(DEPDIR) tar/test/$(DEPDIR) test_utils/$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-includeHEADERS \ + uninstall-libLTLIBRARIES uninstall-man uninstall-pkgconfigDATA + +uninstall-man: uninstall-man1 uninstall-man3 uninstall-man5 + +.MAKE: all check check-am install install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--refresh check check-TESTS \ + check-am clean clean-binPROGRAMS clean-checkPROGRAMS \ + clean-cscope clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-noinstLTLIBRARIES cscope cscopelist-am ctags ctags-am \ + dist dist-all dist-bzip2 dist-gzip dist-hook dist-lzip \ + dist-shar dist-tarZ dist-xz dist-zip distcheck distclean \ + distclean-compile distclean-generic distclean-hdr \ + distclean-libtool distclean-local distclean-tags \ + distcleancheck distdir distuninstallcheck dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-includeHEADERS install-info install-info-am \ + install-libLTLIBRARIES install-man install-man1 install-man3 \ + install-man5 install-pdf install-pdf-am install-pkgconfigDATA \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + recheck tags tags-am uninstall uninstall-am \ + uninstall-binPROGRAMS uninstall-includeHEADERS \ + uninstall-libLTLIBRARIES uninstall-man uninstall-man1 \ + uninstall-man3 uninstall-man5 uninstall-pkgconfigDATA + +.PRECIOUS: Makefile + + +# a) Clean out some unneeded files and directories +# b) Collect all documentation and format it for distribution. +dist-hook: + rm -rf `find $(distdir) -name CVS -type d` + rm -rf `find $(distdir) -name .svn -type d` + rm -f `find $(distdir) -name '*~'` + rm -f `find $(distdir) -name '*.out'` + rm -f `find $(distdir) -name '*.core'` + -rm -f $(distdir)/*/Makefile $(distdir)/*/*/Makefile + cd $(distdir)/doc && /bin/sh update.sh + +distclean-local: + -rm -rf .ref + -rm -rf autom4te.cache/ + -rm -f *~ + -[ -f libarchive/Makefile ] && cd libarchive && make clean + -[ -f libarchive/test/Makefile ] && cd libarchive/test && make clean + -[ -f tar/Makefile ] && cd tar && make clean + -[ -f tar/test/Makefile ] && cd tar/test && make clean + -[ -f cpio/Makefile ] && cd cpio && make clean + -[ -f cpio/test/Makefile ] && cd cpio/test && make clean + -[ -f cat/Makefile ] && cd cat && make clean + -[ -f cpio/test/Makefile ] && cd cat/test && make clean + +# The "list.h" file just lists all of the tests defined in all of the sources. +# Building it automatically provides a sanity-check on libarchive_test_SOURCES +# above. +libarchive/test/list.h: Makefile + $(MKDIR_P) libarchive/test + cat $(top_srcdir)/libarchive/test/test_*.c | grep '^DEFINE_TEST' > libarchive/test/list.h + +tar/test/list.h: Makefile + $(MKDIR_P) tar/test + cat $(top_srcdir)/tar/test/test_*.c | grep '^DEFINE_TEST' > tar/test/list.h + +cpio/test/list.h: Makefile + $(MKDIR_P) cpio/test + cat $(top_srcdir)/cpio/test/test_*.c | grep '^DEFINE_TEST' > cpio/test/list.h + +cat/test/list.h: Makefile + cat $(top_srcdir)/cat/test/test_*.c | grep '^DEFINE_TEST' > cat/test/list.h + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/dependencies/libarchive-3.4.2/NEWS b/dependencies/libarchive-3.4.2/NEWS new file mode 100644 index 0000000..15360f5 --- /dev/null +++ b/dependencies/libarchive-3.4.2/NEWS @@ -0,0 +1,727 @@ +Feb 11, 2020: libarchive 3.4.2 released + +Jan 23, 2020: Important fixes for writing XAR archives + +Jan 20, 2020: New tar option: --safe-writes (atomical file extraction) + +Jan 03, 2020: Support mbed TLS (PolarSSL) as optional crypto provider + +Dec 30, 2019: libarchive 3.4.1 released + +Dec 11, 2019: New pax write option "xattrhdr" + +Nov 17, 2019: Unicode filename support for reading lha/lzh archives + +Jun 11, 2019: libarchive 3.4.0 released + +May 18, 2019: Fixes for reading Android APK and JAR archives + +Apr 16, 2019: Support for non-recursive list and extract + +Apr 14, 2019: New tar option: --exclude-vcs + +Mar 27, 2019: Support for file and directory symlinks on Windows + +Mar 12, 2019: Important fixes for storing file attributes and flags + +Jan 20, 2019: Support for xz, lzma, ppmd8 and bzip2 decompression in ZIP files + +Oct 06, 2018: RAR 5.0 reader + +Sep 03, 2018: libarchive 3.3.3 released + +Jul 19, 2018: Avoid super-linear slowdown on malformed mtree files + +Jan 27, 2018: Many fixes for building with Visual Studio + +Oct 19, 2017: NO_OVERWRITE doesn't change existing directory attributes + +Aug 12, 2017: New support for Zstandard read and write filters + +Jul 09, 2017: libarchive 3.3.2 released + +Mar 16, 2017: NFSv4 ACL support for Linux (librichacl) + +Feb 26, 2017: libarchive 3.3.1 released + Security & Feature release + +Feb 19, 2017: libarchive 3.3.0 released + Security & Feature release + +Jan 29, 2017: Limited NFSv4 ACL support for Mac OS (Darwin) + +Jan 10, 2017: POSIX.1e and NFSv4 ACL support for Solaris and derivates + +Dec 27, 2016: NFSv4 ACL read and write support for pax + Deprecated functions: archive_entry_acl_text(), archive_entry_acl_text_w() + +Nov, 2016: libarchive is now being tested by the OSS-Fuzz project + +Oct 26, 2016: Remove liblzmadec support + +Oct 23, 2016: libarchive 3.2.2 released + Security release + +Jun 20, 2016: libarchive 3.2.1 released + This fixes a handful of security and other critical issues with 3.2.0 + +May 01, 2016: libarchive 3.2.0 released + +Apr 09, 2016: libarchive 3.1.901a released + Another test release in preparation for 3.2.0 + +Feb 13, 2016: libarchive 3.1.900a released + This is a test release in preparation for 3.2.0 + +Oct 21, 2015: Preliminary port to OSF + +Apr 11, 2015: libarchive's issue tracker is now hosted at GitHub. + https://github.com/libarchive/libarchive/issues + +Early 2015: Many fixes to crash and overflow bugs thanks to Hanno Boeck + +Oct 13, 2014: Zip encryption and decryption support + +Aug 13, 2014: Add support for lz4 compression. + +Jun 10, 2014: Add warc format support + +May 3, 2014: Add experimental Zip streaming extension + +Apr 6, 2014: Add bsdcat command-line tool + +Jan 12, 2014: Add Zip64 support + +Dec 1, 2013: Rewrite Zip write logic + +Jul 1, 2013: Add ability to detect encrypted entries for many formats + (This does not add the ability to *decrypt* those entries, however) + +Feb 23, 2013: "raw" write support added + +Feb 09, 2013: libarchive 3.1.2 released + +Jan 28, 2013: libarchive's new website moved to http://www.libarchive.org. + +Jan 13, 2013: libarchive 3.1.1 released + +Jan 13, 2013: libarchive 3.1.0 released + +Dec 07, 2012: Implement functions to manually set the format and filters used. + +Nov 11, 2012: Add support for __MACOSX directory in Zip archives, which resource + forks are stored in. + +Oct 20, 2012: Add support for writing v7 tar format. + +Oct 09, 2012: Add support for grzip compression. + +Oct 07, 2012: Introduce b64encode filter. +Oct 07, 2012: Introduce uuencode filter. + +Oct 06, 2012: Add support for lzop. + +Sep 27, 2012: Implement function used to seek within data blocks. + (Currently only supported for uncompressed RAR archives). + +Apr 22, 2012: Add basic archive read and write filter support for lrzip. + +Mar 27, 2012: libarchive 3.0.4 released + +Feb 05, 2012: libarchive development now hosted at GitHub. + http://libarchive.github.com/ +Feb 05, 2012: libarchive's issue tracker remains at Google Code. + http://code.google.com/p/libarchive/issues/list +Feb 05, 2012: libarchive's mailing lists remain at Google Groups. + +Dec 24, 2011: libarchive 3.0.2 released +Dec 23, 2011: Various fixes merged from FreeBSD +Dec 23, 2011: Symlink support in Zip reader and writer +Dec 23, 2011: Robustness fixes to 7Zip reader + +Nov 27, 2011: libarchive 3.0.1b released + +Nov 26, 2011: 7Zip reader +Nov 26, 2011: Small fixes to ISO and Zip to improve robustness with corrupted input +Nov 24, 2011: Improve streaming Zip reader's support for uncompressed entries +Nov 20, 2011: New seeking Zip reader supports SFX Zip archives +Nov 20, 2011: Build fixes on Windows + +Nov 13, 2011: libarchive 3.0.0a released + +Nov 06, 2011: Update shared-library version calculations for libarchive 3.x +Sep 04, 2011: Fix tar -s; follow GNU tar for controlling hardlink/symlink substitutions +Aug 18, 2011: Fix reading ISO images built by NetBSD's mkisofs +Aug 15, 2011: Old archive_read_support_compression_XXX functions are deprecated and + will disappear in libarchive 4.0. +Jun 26, 2011: RAR reader +Jun 16, 2011: Add tar:compat-2x option to emulate broken libarchive 2.x + handling of pax UTF-8 headers +Apr 25, 2011: Refactor read_open() into a collection of single-item setters; + support the old interfaces as wrappers +Apr 12, 2011: Split disk writer into separate POSIX and Windows implementations +Apr 10, 2011: Improvements to character translations on Windows. +Mar 30, 2011: More work to return errors instead of calling abort() +Mar 23, 2011: Add charset option to many writers to control MBCS filenames +Mar 17, 2011: Overhauled support for per-format extension options +Mar 17, 2011: Track character set used for mbcs strings, support + translating to/from user-specified locale +Mar 09, 2011: Recognize mtree files without requiring a signature +Mar 06, 2011: Use iconv to convert to/from Unicode instead of making bad + assumptions about the C90 character set translation functions +Feb 17, 2011: Fixes for AIX, TRU64, and other platforms +Dec 22, 2010: CAB reader +Dec 20, 2010: LHA/LZH reader +Jul 03, 2010: minitar example demonstrates archive_read_disk directory traversal +Jun 29, 2010: Many improvements to ISO reader compatibility +Jun 26, 2010: Use larger buffers when copy files into an archive +Jun 18, 2010: Reimplement Mac OS extensions in libarchive +Jun 09, 2010: archive_read_disk now supports traversals +May 28, 2010: XAR writer +May 16, 2010: Fix ^T handling; don't exit on interrupted reads and writes +May 09, 2010: Improved detection of platform-specific crypto support +May 04, 2010: lzip read and write filters +May 01, 2010: New options: tar --gid --gname --uid --uname +Apr 28, 2010: Use Red-black tree for ISO reader/writer to improve performance +Apr 17, 2010: Minimal writer for legacy GNU tar format +Mar 12, 2010: Don't dereference symlinks on Linux when reading ACLs. +Mar 06, 2010: Fix build when an older libarchive is already installed +Feb 28, 2010: Relax handling of state failures; misuse by clients now generally + results in a sticky ARCHIVE_FATAL rather than a visit to abort() +Feb 25, 2010: ISO writer +Feb 21, 2010: Split many man pages into smaller chunks. +Feb 21, 2010: Performance: Cheat on block sizes when reading archives from disk. +Feb 21, 2010: Use int64_t instead of off_t, dev_t, ino_t, uid_t, and gid_t +Feb 20, 2010: Document new ACL functions. +Feb 19, 2010: Support multiple write filters +Feb 07, 2010: Remove some legacy libarchive 1.x APIs +Feb 04, 2010: Read afio headers +Feb 02, 2010: Archive sparse files compatibly with GNU tar +Feb 01, 2010: Integrate Apple extensions for Mac OS extended attributes into bsdtar +Jan 31, 2010: Support cpio -V + +Feb 04, 2010: libarchive 2.8.0 released +Jan 17, 2010: Fix error handling for 'echo nonexistent | cpio -o' +Jan 17, 2010: Don't use futimes() on Cygwin + +Jan 02, 2010: libarchive 2.7.902a released (test release for 2.8) +Jan 02, 2010: Fix tar/test/test_windows on MinGW +Jan 02, 2010: Fix memory leaks in libarchive tests +Jan 01, 2010: Fix memory leak when filter startup fails + +Dec 27, 2009: libarchive 2.7.901a released (test release for 2.8) + +Aug 04, 2009: libarchive 2.7.1 released +Jul 20, 2009: Suppress bogus warning about unxz +Jul 19, 2009: Support Cygwin 1.7 +Jun 11, 2009: Support lzma/xz files compressed with larger buffer sizes. +May 24, 2009: Handle gzip files signed with OpenBSD "gzsig" program. +May 07, 2009: Avoid false failures when reading from pipe. + +Apr 16, 2009: libarchive 2.7.0 released + +Apr 10, 2009: libarchive 2.6.992a released +Apr 09, 2009: Fix SIGPIPE issue building with MSVC. +Apr 09, 2009: Fix several minor memory leaks in libarchive and libarchive_test + +Apr 08, 2009: libarchive 2.6.991a released +Apr 07, 2009: Additional tests added to bsdcpio_test + +Apr 01, 2009: libarchive 2.6.990a released +Apr 01, 2009: Use command-line gunzip, bunzip2, unxz, unlzma for + decompression if the library is built without suitable + libraries. The setup functions return ARCHIVE_WARN + in this case so clients can adapt if necessary. +Apr 01, 2009: Use getpw*_r and getgr*_r functions for thread-safety. +Mar 24, 2009: Add archive_read_next_header2(), which is up to 25% + more efficient for some clients; from Brian Harring. +Mar 22, 2009: PDF versions of manpages are now included in the distribution. +Mar, 2009: Major work to improve Cygwin build by Charles Wilson. +Feb/Mar, 2009: Major work on cmake build support, mostly by Michihiro NAKAJIMA. +Feb/Mar, 2009: Major work on Visual Studio support by Michihiro NAKAJIMA. + All tests now pass. +Feb 25, 2009: Fix Debian Bug #516577 +Feb 21, 2009: Yacc is no longer needed to build; date parser rewritten in C. +Jan/Feb, 2009: Mtree work by Michihiro. +Feb, 2009: Joliet support by Andreas Henriksson. +Jan/Feb, 2009: New options framework by Michihiro. +Feb, 2009: High-res timestamps on Tru64, AIX, and GNU Hurd, by Björn Jacke. +Jan 18, 2009: Extended attributes work on FreeBSD and Linux now with pax format. +Jan 07, 2009: New archive_read_disk_entry_from_file() knows about ACLs, + extended attributes, etc so that bsdtar and bsdcpio don't require + such system-specific knowledge. +Jan 03, 2009: Read filter system extensively refactored. In particular, + read filter pipelines are now built out automatically and individual + filters should be much easier to implement. Documentation on the + Googlecode Wiki explains how to implement new filters. +Dec 28, 2008: Many Windows/Visual Studio fixes from Michihiro NAKAJIMA. + +Dec 28, 2008: Main libarchive development moved from FreeBSD Perforce + server to Google Code. This should make it easier for more + people to participate in libarchive development. + +Dec 28, 2008: libarchive 2.6.0 released +Dec 25, 2008: libarchive 2.5.905a released +Dec 10, 2008: libarchive 2.5.904a released +Dec 04, 2008: libarchive 2.5.903a released +Nov 09, 2008: libarchive 2.5.902a released +Nov 08, 2008: libarchive 2.5.901a released +Nov 08, 2008: Start of pre-release testing for libarchive 2.6 + +Nov 07, 2008: Read filter refactor: The decompression routines just + consume and produce arbitrarily-sized blocks. The reblocking + from read_support_compression_none() has been pulled into the + read core. Also, the decompression bid now makes multiple + passes and stacks read filters. +Oct 21, 2008: bsdcpio: New command-line parser. +Oct 19, 2008: Internal read_ahead change: short reads are now an error +Oct 06, 2008: bsdtar: option parser no longer uses getopt_long(), + gives consistent option parsing on all platforms. +Sep 19, 2008: Jaakko Heinonen: shar utility built on libarchive +Sep 17, 2008: Pedro Giffuni: birthtime support +Sep 17, 2008: Miklos Vajna: lzma reader and test. Note: I still have + some concerns about the auto-detection (LZMA file format + doesn't support auto-detection well), so this is not yet + enabled under archive_read_support_compression_all(). For + now, you must call archive_read_support_compression_lzma() if + you want LZMA read support. +Sep 11, 2008: Ivailo Petrov: Many fixes to Windows build, new solution files +Jul 26, 2008: archive_entry now tracks which values have not been set. + This helps zip extraction (file size is often "unknown") and + time restores (tar usually doesn't know atime). +Jul 26, 2008: Joerg Sonnenberger: Performance improvements to shar writer +Jul 25, 2008: Joerg Sonnenberger: mtree write support + +Jul 02, 2008: libarchive 2.5.5 released + +Jul 02, 2008: libarchive 2.5.5b released +Jul 01, 2008: bsdcpio is being used by enough people, we can call it 1.0.0 now +Jun 20, 2008: bsdcpio: If a -l link fails with EXDEV, copy the file instead +Jun 19, 2008: bsdcpio: additional long options for better GNU cpio compat +Jun 15, 2008: Many small portability and bugfixes since 2.5.4b. + +May 25, 2008: libarchive 2.5.4b released +May 21, 2008: Joerg Sonnenberger: fix bsdtar hardlink handling for newc format + +May 21, 2008: More progress on Windows building. Thanks to "Scott" + for the Windows makefiles, thanks to Kees Zeelenberg for + code contributions. + +May 21, 2008: Fix a number of non-exploitable integer and buffer overflows, + thanks to David Remahl at Apple for pointing these out. + +May 21, 2008: Colin Percival: SIGINFO or SIGUSR1 to bsdtar prints progress info + +May 16, 2008: bsdtar's test harness no longer depends on file ordering. + This was causing spurious test failures on a lot of systems. + Thanks to Bernhard R. Link for the diagnosis. + +May 14, 2008: Joerg Sonnenberger: -s substitution support for bsdtar + +May 13, 2008: Joerg Sonnenberger: Many mtree improvements + +May 11, 2008: Joerg Sonnenberger: fix hardlink extraction when + hardlinks have different permissions from original file + +April 30, 2008: Primary libarchive work has been moved into the FreeBSD + project's Perforce repository: http://perforce.freebsd.org/ + The libarchive project can be browsed at + //depot/user/kientzle/libarchive-portable + Direct link: http://preview.tinyurl.com/46mdgr + +May 04, 2008: libarchive 2.5.3b released + * libarchive: Several fixes to link resolver to address bsdcpio crashes + * bsdcpio: -p hardlink handling fixes + * tar/pax: Ensure ustar dirnames end in '/'; be more careful about + measuring filenames when deciding what pathname fields to use + * libarchive: Mark which entry strings are set; be accurate about + distinguishing empty strings ("") from unset ones (NULL) + * tar: Don't crash reading entries with empty filenames + * libarchive_test, bsdtar_test, bsdcpio_test: Better defaults: + run all tests, delete temp dirs, summarize repeated failures + * -no-undefined to libtool for Cygwin + * libarchive_test: Skip large file tests on systems with 32-bit off_t + * iso9660: Don't bother trying to find the body of an empty file; + this works around strange behavior from some ISO9660 writers + * tar: allow -r -T to be used together + * tar: allow --format with -r or -u + * libarchive: Don't build archive.h + +May 04, 2008: Simplified building: archive.h is no longer constructed + This may require additional #if conditionals on some platforms. + +Mar 30, 2008: libarchive 2.5.1b released + +Mar 15, 2008: libarchive 2.5.0b released +Mar 15, 2008: bsdcpio now seems to correctly write hardlinks into newc, + ustar, and old cpio archives. Just a little more testing before + bsdcpio 1.0 becomes a reality. +Mar 15, 2008: I think the new linkify() interface is finally handling + all known hardlink strategies. +Mar 15, 2008: Mtree read fixes from Joerg Sonnenberger. +Mar 15, 2008: Many new bsdtar and bsdcpio options from Joerg Sonnenberger. +Mar 15, 2008: test harnesses no longer require uudecode; they + now have built-in decoding logic that decodes the reference + files as they are needed. + +Mar 14, 2008: libarchive 2.4.14 released; identical to 2.4.13 except for + a point fix for gname/uname mixup in pax format that was introduced + with the UTF-8 fixes. + +Feb 26, 2008: libarchive 2.4.13 released +Feb 25, 2008: Handle path, linkname, gname, or uname that can't be converted + to/from UTF-8. Implement "hdrcharset" attribute from SUS-2008. +Feb 25, 2008: Fix name clash on NetBSD. +Feb 18, 2008: Fix writing empty 'ar' archives, per Kai Wang +Feb 18, 2008: [bsdtar] Permit appending on block devices. +Feb 09, 2008: New "linkify" resolver to help with newc hardlink writing; + bsdcpio still needs to be converted to use this. +Feb 02, 2008: Windows compatibility fixes from Ivailo Petrov, Kees Zeelenberg +Jan 30, 2008: Ignore hardlink size for non-POSIX tar archives. + +Jan 22, 2008: libarchive 2.4.12 released +Jan 22, 2008: Fix bad padding when writing symlinks to newc cpio archives. +Jan 22, 2008: Verify bsdcpio_test by getting it to work against GNU cpio 2.9. + bsdcpio_test complains about missing options (-y and -z), format + of informational messages (--version, --help), and a minor formatting + issue in odc format output. After this update, bsdcpio_test uncovered + several more cosmetic issues in bsdcpio, all now fixed. +Jan 22, 2008: Experimental support for self-extracting Zip archives. +Jan 22, 2008: Extend hardlink restore strategy to work correctly with + hardlinks extracted from newc cpio files. (Which store the body + only with the last occurrence of a link.) + +Dec 30, 2007: libarchive 2.4.11 released +Dec 30, 2007: Fixed a compile error in bsdcpio on some systems. + +Dec 29, 2007: libarchive 2.4.10 released +Dec 29, 2007: bsdcpio 0.9.0 is ready for wider use. +Dec 29, 2007: Completed initial test harness for bsdcpio. + +Dec 22, 2007: libarchive 2.4.9 released +Dec 22, 2007: Implement the remaining options for bsdcpio: -a, -q, -L, -f, + pattern selection for -i and -it. + +Dec 13, 2007: libarchive 2.4.8 released +Dec 13, 2007: gzip and bzip2 compression now handle zero-byte writes correctly, + Thanks to Damien Golding for bringing this to my attention. + +Dec 12, 2007: libarchive 2.4.7 released + +Dec 10, 2007: libarchive 2.4.6 released +Dec 09, 2007: tar/test/test_copy.c verifies "tar -c | tar -x" copy pipeline +Dec 07, 2007: Fix a couple of minor memory leaks. + +Dec 04, 2007: libarchive 2.4.5 released +Dec 04, 2007: Fix cpio/test/test_write_odc by setting the umask first. + +Dec 03, 2007: libarchive 2.4.4 released +Dec 03, 2007: New configure options --disable-xattr and --disable-acl, + thanks to Samuli Suominen. + +Dec 03, 2007: libarchive 2.4.3 released +Dec 03, 2007: Thanks to Lapo Luchini for sending me a ZIP file that + libarchive couldn't handle. Fixed a bug in handling of + "length at end" flags in ZIP files. +Dec 03, 2007: Fixed bsdcpio -help, bsdtar -help tests. +Dec 02, 2007: First cut at real bsdtar test harness. + +Dec 02, 2007: libarchive 2.4.2 released + +Dec 02, 2007: libarchive 2.4.1 released +Dec 02, 2007: Minor fixes, rough cut of mdoc-to-man conversion for + man pages. + +Oct 30, 2007: libarchive 2.4.0 released +Oct 30, 2007: Minor compile fix thanks to Joerg Schilling. +Oct 30, 2007: Only run the format auction once at the beginning of the + archive. This is simpler and supports better error recovery. +Oct 29, 2007: Test support for very large entries in tar archives: + libarchive_test now exercises entries from 2GB up to 1TB. + +Oct 27, 2007: libarchive 2.3.5 released +Oct 27, 2007: Correct some unnecessary internal data copying in the + "compression none" reader and writer; this reduces user time + by up to 2/3 in some tests. (Thanks to Jan Psota for + publishing his performance test results to GNU tar's bug-tar + mailing list; those results pointed me towards this problem.) +Oct 27, 2007: Fix for skipping archive entries that are exactly + a multiple of 4G on 32-bit platforms. +Oct 25, 2007: Fix for reading very large (>8G) tar archives; this was + broken when I put in support for new GNU tar sparse formats. +Oct 20, 2007: Initial work on new pattern-matching code for cpio; I + hope this eventually replaces the code currently in bsdtar. + +Oct 08, 2007: libarchive 2.3.4 released +Oct 05, 2007: Continuing work on bsdcpio test suite. +Oct 05, 2007: New cpio.5 manpage, updates to "History" of bsdcpio.1 and + bsdtar.1 manpages. +Oct 05, 2007: Fix zip reader to immediately return EOF if you try + to read body of non-regular file. In particular, this fixes + bsdtar extraction of zip archives. + +Sep 30, 2007: libarchive 2.3.3 released +Sep 26, 2007: Rework Makefile.am so that the enable/disable options + actually do the right things. +Sep 26, 2007: cpio-odc and cpio-newc archives no longer write bodies + for non-regular files. +Sep 26, 2007: Test harness for bsdcpio is in place, needs more tests written. + This is much nicer than the ragtag collection of test scripts + that bsdtar has. + +Sep 20, 2007: libarchive 2.3.2 released +Sep 20, 2007: libarchive 2.3.1 broke bsdtar because the archive_write_data() + fix was implemented incorrectly. + +Sep 16, 2007: libarchive 2.3.1 released +Sep 16, 2007: Many fixes to bsdcpio 0.3: handle hardlinks with -p, recognize + block size on writing, fix a couple of segfaults. +Sep 16, 2007: Fixed return value from archive_write_data() when used + with archive_write_disk() to match the documentation and other + instances of this same function. +Sep 15, 2007: Add archive_entry_link_resolver, archive_entry_strmode + +Sep 11, 2007: libarchive 2.2.8 released +Sep 09, 2007: bsdcpio 0.2 supports most (not yet all) of the old POSIX spec. + +Sep 01, 2007: libarchive 2.2.7 released +Aug 31, 2007: Support for reading mtree files, including an mtree.5 manpage + (A little experimental still.) +Aug 18, 2007: Read gtar 1.17 --posix --sparse entries. +Aug 13, 2007: Refined suid/sgid restore handling; it is no longer + an error if suid/sgid bits are dropped when you request + perm restore but don't request owner restore. +Aug 06, 2007: Use --enable-bsdcpio if you want to try bsdcpio + +Aug 05, 2007: libarchive 2.2.6 released +Aug 05, 2007: New configure option --disable-bsdtar, thanks to Joerg + Sonnenberger. +Aug 05, 2007: Several bug fixes from FreeBSD CVS repo. + +Jul 13, 2007: libarchive 2.2.5 released + +Jul 12, 2007: libarchive 2.2.4 released +Jul 12, 2007: Thanks to Colin Percival's help in diagnosing and + fixing several critical security bugs. Details available at + http://security.freebsd.org/advisories/FreeBSD-SA-07:05.libarchive.asc + +May 26, 2007: libarchive 2.2.3 released +May 26, 2007: Fix memory leaks in ZIP reader and shar writer, add some + missing system headers to archive_entry.h, dead code cleanup + from Colin Percival, more tests for gzip/bzip2, fix an + EOF anomaly in bzip2 decompression. + +May 12, 2007: libarchive 2.2.2 released +May 12, 2007: Fix archive_write_disk permission restore by cloning + entry passed into write_header so that permission info is + still available at finish_entry time. (archive_read_extract() + worked okay because it held onto the passed-in entry, but + direct consumers of archive_write_disk would break). This + required fixing archive_entry_clone(), which now works and has + a reasonably complete test case. +May 10, 2007: Skeletal cpio implementation. + +May 06, 2007: libarchive 2.2.1 released +May 06, 2007: Flesh out a lot more of test_entry.c so as to catch + problems such as the device node breakage before releasing . +May 05, 2007: Fix a bad bug introduced in 2.1.9 that broke device + node entries in tar archives. +May 03, 2007: Move 'struct stat' out of archive_entry core as well. + This removes some portability headaches and fixes a bunch + of corner cases that arise when manipulating archives on + dissimilar systems. + +Apr 30, 2007: libarchive 2.1.10 released +Apr 31, 2007: Minor code cleanup. + +Apr 24, 2007: libarchive 2.1.9 released +Apr 24, 2007: Fix some recently-introduced problems with libraries + (Just let automake handle it and it all works much better.) + Finish isolating major()/minor()/makedev() in archive_entry.c. + +Apr 23, 2007: libarchive 2.1.8 released +Apr 23, 2007: Minor fixes found from building on MacOS X + +Apr 22, 2007: libarchive 2.1.7 released +Apr 22, 2007: Eliminated all uses of 'struct stat' from the + format readers/writers. This should improve portability; + 'struct stat' is now only used in archive_entry and in + code that actually touches the disk. + +Apr 17, 2007: libarchive 2.1.6 released + Libarchive now compiles and passes all tests on Interix. + +Apr 16, 2007: libarchive 2.1.5 released + +Apr 15, 2007: libarchive 2.1b2 released +Apr 15, 2007: New libarchive_internals.3 documentation of internal APIs. + Not complete, but should prove helpful. +Apr 15, 2007: Experimental "read_compress_program" and "write_compress_program" + for using libarchive with external compression. Not yet + well tested, and likely has portability issues. Feedback + appreciated. + +Apr 14, 2007: libarchive 2.0.31 released +Apr 14, 2007: More fixes for Interix, more 'ar' work + +Apr 14, 2007: libarchive 2.0.30 released +Apr 13, 2007: libarchive now enforces trailing '/' on dirs + written to tar archives + +Apr 11, 2007: libarchive 2.0.29 released +Apr 11, 2007: Make it easier to statically configure for different platforms. +Apr 11, 2007: Updated config.guess, config.sub, libtool + +Apr 06, 2007: libarchive 2.0.28 released +Apr 06, 2007: 'ar' format read/write support thanks to Kai Wang. + +Apr 01, 2007: libarchive 2.0.27 released +Mar 31, 2007: Several minor fixes from Colin Percival and Joerg Sonnenberger. + +Mar 12, 2007: libarchive 2.0.25 released +Mar 12, 2007: Fix broken --unlink flag. + +Mar 11, 2007: libarchive 2.0.24 released +Mar 10, 2007: Correct an ACL blunder that causes any ACL with an entry + that refers to a non-existent user or group to not be restored correctly. + The fix both makes the parser more tolerant (so that archives created + with the buggy ACLs can be read now) and corrects the ACL formatter. +Mar 10, 2007: More work on test portability to Linux. + +Mar 10, 2007: libarchive 2.0.22 released +Mar 10, 2007: Header cleanups; added linux/fs.h, removed + some unnecessary headers, added #include guards in bsdtar. + If you see any obvious compile failures from this, let me know. +Mar 10, 2007: Work on bsdtar test scripts: not yet robust enough + to enable as part of "make check", but getting better. +Mar 10, 2007: libarchive now returns ARCHIVE_FAILED when + a header write fails in a way that only affects this item. + Less bad than ARCHIVE_FATAL, but worse than ARCHIVE_WARN. + +Mar 07, 2007: libarchive 2.0.21 released +Mar 07, 2007: Add some ACL tests (only for the system-independent + portion of the ACL support for now). +Mar 07, 2007: tar's ability to read ACLs off disk got + turned off for FreeBSD; re-enable it. (ACL restores and + libarchive support for storing/reading ACLs from pax + archives was unaffected.) + +Mar 02, 2007: libarchive 2.0.20 released +Mar 2, 2007: It's not perfect, but it's pretty good. + Libarchive 2.0 is officially out of beta. + +Feb 28, 2007: libarchive 2.0b17 released +Feb 27, 2007: Make the GID restore checks more robust by checking + whether the current user has too few or too many privileges. + +Feb 26, 2007: libarchive 2.0b15 released +Feb 26, 2007: Don't lose symlinks when extracting from ISOs. + Thanks to Diego "Flameeyes" Pettenò for telling me about the + broken testcase on Gentoo that (finally!) led me to the cause + of this long-standing bug. + +Feb 26, 2007: libarchive 2.0b14 released +Feb 26, 2007: Fix a broken test on platforms that lack lchmod(). + +Feb 25, 2007: libarchive 2.0b13 released +Feb 25, 2007: Empty archives were being written as empty files, + without a proper end-of-archive marker. Fixed. + +Feb 23, 2007: libarchive 2.0b12 released +Feb 22, 2007: Basic security checks added: _EXTRACT_SECURE_NODOTDOT + and _EXTRACT_SECURE_SYMLINK. These checks used to be in bsdtar, + but they belong down in libarchive where they can be used by + other tools and where they can be better optimized. + +Feb 11, 2007: libarchive 2.0b11 released +Feb 10, 2007: Fixed a bunch of errors in libarchive's handling + of EXTRACT_PERM and EXTRACT_OWNER, especially relating + to SUID and SGID bits. + +Jan 31, 2007: libarchive 2.0b9 released +Jan 31, 2007: Added read support for "empty" archives as a + distinct archive format. Bsdtar uses this to handle, e.g., + "touch foo.tar; tar -rf foo.tar" + +Jan 22, 2007: libarchive 2.0b6 released +Jan 22, 2007: archive_write_disk API is now in place. It provides + a finer-grained interface than archive_read_extract. In particular, + you can use it to create objects on disk without having an archive + around (just feed it archive_entry objects describing what you + want to create), you can override the uname/gname-to-uid/gid lookups + (minitar uses this to avoid getpwXXX() and getgrXXX() bloat). + +Jan 09, 2007: libarchive 2.0a3 released +Jan 9, 2007: archive_extract is now much better; it handles the + most common cases with a minimal number of system calls. + Some features still need a lot of testing, especially corner + cases involving objects that already exist on disk. I expect + the next round of API overhaul will simplify building test cases. +Jan 9, 2007: a number of fixes thanks to Colin Percival, especially + corrections to the skip() framework and handling of large files. +Jan 9, 2007: Fixes for large ISOs. The code should correctly handle + very large ISOs with entries up to 4G. Thanks to Robert Sciuk + for pointing out these issues. + +Sep 05, 2006: libarchive 1.3.1 released +Sep 5, 2006: Bump version to 1.3 for new I/O wrappers. +Sep 4, 2006: New memory and FILE read/write wrappers. +Sep 4, 2006: libarchive test harness is now minimally functional; + it's located a few minor bugs in error-handling logic + +Aug 17, 2006: libarchive 1.2.54 released +Aug 17, 2006: Outline ABI changes for libarchive 2.0; these + are protected behind #ifdef's until I think I've found everything + that needs to change. +Aug 17, 2006: Fix error-handling in archive_read/write_close() + They weren't returning any errors before. +Aug 17, 2006: Fix recursive-add logic to not trigger if it's not set + Fixes a bug adding files when writing archive to pipe or when + using archive_write_open() directly. +Jul 2006: New "skip" handling improves performance extracting + single files from large uncompressed archives. + +Mar 21, 2006: 1.2.52 released +Mar 21, 2006: Fix -p on platforms that don't have platform-specific + extended attribute code. +Mar 20, 2006: Add NEWS file; fill in some older history from other + files. I'll try to keep this file up-to-date from now on. + +OLDER NEWS SUMMARIES + +Mar 19, 2006: libarchive 1.2.51 released +Mar 18, 2006: Many fixes to extended attribute support, including a redesign + of the storage format to simplify debugging. +Mar 12, 2006: Remove 'tp' support; it was a fun idea, but not worth + spending much time on. +Mar 11, 2006: Incorporated Jaakko Heinonen's still-experimental support + for extended attributes (Currently Linux-only.). +Mar 11, 2006: Reorganized distribution package: There is now one tar.gz + file that builds both libarchive and bsdtar. +Feb 13, 2006: Minor bug fixes: correctly read cpio device entries, write + Pax attribute entry names. +Nov 7, 2005: Experimental 'tp' format support in libarchive. Feedback + appreciated; this is not enabled by archive_read_support_format_all() + yet as I'm not quite content with the format detection heuristics. +Nov 7, 2005: Some more portability improvements thanks to Darin Broady, + minor bugfixes. +Oct 12, 2005: Use GNU libtool to build shared libraries on many systems. +Aug 9, 2005: Correctly detect that MacOS X does not have POSIX ACLs. +Apr 17, 2005: Kees Zeelenberg has ported libarchive and bsdtar to Windows: + http://gnuwin32.sourceforge.net/ +Apr 11, 2005: Extended Zip/Zip64 support thanks to Dan Nelson. -L/-h + fix from Jaakko Heinonen. +Mar 12, 2005: archive_read_extract can now handle very long + pathnames (I've tested with pathnames up to 1MB). +Mar 12, 2005: Marcus Geiger has written an article about libarchive + http://xsnil.antbear.org/2005/02/05/archive-mit-libarchive-verarbeiten/ + including examples of using it from Objective-C. His MoinX + http://moinx.antbear.org/ desktop Wiki uses + libarchive for archiving and restoring Wiki pages. +Jan 22, 2005: Preliminary ZIP extraction support, + new directory-walking code for bsdtar. +Jan 16, 2005: ISO9660 extraction code added; manpage corrections. +May 22, 2004: Many gtar-compatible long options have been added; almost + all FreeBSD ports extract correctly with bsdtar. +May 18, 2004: bsdtar can read Solaris, HP-UX, Unixware, star, gtar, + and pdtar archives. diff --git a/dependencies/libarchive-3.4.2/README.md b/dependencies/libarchive-3.4.2/README.md new file mode 100644 index 0000000..2912b3d --- /dev/null +++ b/dependencies/libarchive-3.4.2/README.md @@ -0,0 +1,224 @@ +# Welcome to libarchive! + +The libarchive project develops a portable, efficient C library that +can read and write streaming archives in a variety of formats. It +also includes implementations of the common `tar`, `cpio`, and `zcat` +command-line tools that use the libarchive library. + +## Questions? Issues? + +* http://www.libarchive.org is the home for ongoing + libarchive development, including documentation, + and links to the libarchive mailing lists. +* To report an issue, use the issue tracker at + https://github.com/libarchive/libarchive/issues +* To submit an enhancement to libarchive, please + submit a pull request via GitHub: https://github.com/libarchive/libarchive/pulls + +## Contents of the Distribution + +This distribution bundle includes the following major components: + +* **libarchive**: a library for reading and writing streaming archives +* **tar**: the 'bsdtar' program is a full-featured 'tar' implementation built on libarchive +* **cpio**: the 'bsdcpio' program is a different interface to essentially the same functionality +* **cat**: the 'bsdcat' program is a simple replacement tool for zcat, bzcat, xzcat, and such +* **examples**: Some small example programs that you may find useful. +* **examples/minitar**: a compact sample demonstrating use of libarchive. +* **contrib**: Various items sent to me by third parties; please contact the authors with any questions. + +The top-level directory contains the following information files: + +* **NEWS** - highlights of recent changes +* **COPYING** - what you can do with this +* **INSTALL** - installation instructions +* **README** - this file +* **CMakeLists.txt** - input for "cmake" build tool, see INSTALL +* **configure** - configuration script, see INSTALL for details. If your copy of the source lacks a `configure` script, you can try to construct it by running the script in `build/autogen.sh` (or use `cmake`). + +The following files in the top-level directory are used by the 'configure' script: +* `Makefile.am`, `aclocal.m4`, `configure.ac` - used to build this distribution, only needed by maintainers +* `Makefile.in`, `config.h.in` - templates used by configure script + +## Documentation + +In addition to the informational articles and documentation +in the online [libarchive Wiki](https://github.com/libarchive/libarchive/wiki), +the distribution also includes a number of manual pages: + + * bsdtar.1 explains the use of the bsdtar program + * bsdcpio.1 explains the use of the bsdcpio program + * bsdcat.1 explains the use of the bsdcat program + * libarchive.3 gives an overview of the library as a whole + * archive_read.3, archive_write.3, archive_write_disk.3, and + archive_read_disk.3 provide detailed calling sequences for the read + and write APIs + * archive_entry.3 details the "struct archive_entry" utility class + * archive_internals.3 provides some insight into libarchive's + internal structure and operation. + * libarchive-formats.5 documents the file formats supported by the library + * cpio.5, mtree.5, and tar.5 provide detailed information about these + popular archive formats, including hard-to-find details about + modern cpio and tar variants. + +The manual pages above are provided in the 'doc' directory in +a number of different formats. + +You should also read the copious comments in `archive.h` and the +source code for the sample programs for more details. Please let us +know about any errors or omissions you find. + +## Supported Formats + +Currently, the library automatically detects and reads the following fomats: + * Old V7 tar archives + * POSIX ustar + * GNU tar format (including GNU long filenames, long link names, and sparse files) + * Solaris 9 extended tar format (including ACLs) + * POSIX pax interchange format + * POSIX octet-oriented cpio + * SVR4 ASCII cpio + * Binary cpio (big-endian or little-endian) + * ISO9660 CD-ROM images (with optional Rockridge or Joliet extensions) + * ZIP archives (with uncompressed or "deflate" compressed entries, including support for encrypted Zip archives) + * ZIPX archives (with support for bzip2, ppmd8, lzma and xz compressed entries) + * GNU and BSD 'ar' archives + * 'mtree' format + * 7-Zip archives + * Microsoft CAB format + * LHA and LZH archives + * RAR and RAR 5.0 archives (with some limitations due to RAR's proprietary status) + * XAR archives + +The library also detects and handles any of the following before evaluating the archive: + * uuencoded files + * files with RPM wrapper + * gzip compression + * bzip2 compression + * compress/LZW compression + * lzma, lzip, and xz compression + * lz4 compression + * lzop compression + * zstandard compression + +The library can create archives in any of the following formats: + * POSIX ustar + * POSIX pax interchange format + * "restricted" pax format, which will create ustar archives except for + entries that require pax extensions (for long filenames, ACLs, etc). + * Old GNU tar format + * Old V7 tar format + * POSIX octet-oriented cpio + * SVR4 "newc" cpio + * shar archives + * ZIP archives (with uncompressed or "deflate" compressed entries) + * GNU and BSD 'ar' archives + * 'mtree' format + * ISO9660 format + * 7-Zip archives + * XAR archives + +When creating archives, the result can be filtered with any of the following: + * uuencode + * gzip compression + * bzip2 compression + * compress/LZW compression + * lzma, lzip, and xz compression + * lz4 compression + * lzop compression + * zstandard compression + +## Notes about the Library Design + +The following notes address many of the most common +questions we are asked about libarchive: + +* This is a heavily stream-oriented system. That means that + it is optimized to read or write the archive in a single + pass from beginning to end. For example, this allows + libarchive to process archives too large to store on disk + by processing them on-the-fly as they are read from or + written to a network or tape drive. This also makes + libarchive useful for tools that need to produce + archives on-the-fly (such as webservers that provide + archived contents of a users account). + +* In-place modification and random access to the contents + of an archive are not directly supported. For some formats, + this is not an issue: For example, tar.gz archives are not + designed for random access. In some other cases, libarchive + can re-open an archive and scan it from the beginning quickly + enough to provide the needed abilities even without true + random access. Of course, some applications do require true + random access; those applications should consider alternatives + to libarchive. + +* The library is designed to be extended with new compression and + archive formats. The only requirement is that the format be + readable or writable as a stream and that each archive entry be + independent. There are articles on the libarchive Wiki explaining + how to extend libarchive. + +* On read, compression and format are always detected automatically. + +* The same API is used for all formats; it should be very + easy for software using libarchive to transparently handle + any of libarchive's archiving formats. + +* Libarchive's automatic support for decompression can be used + without archiving by explicitly selecting the "raw" and "empty" + formats. + +* I've attempted to minimize static link pollution. If you don't + explicitly invoke a particular feature (such as support for a + particular compression or format), it won't get pulled in to + statically-linked programs. In particular, if you don't explicitly + enable a particular compression or decompression support, you won't + need to link against the corresponding compression or decompression + libraries. This also reduces the size of statically-linked + binaries in environments where that matters. + +* The library is generally _thread safe_ depending on the platform: + it does not define any global variables of its own. However, some + platforms do not provide fully thread-safe versions of key C library + functions. On those platforms, libarchive will use the non-thread-safe + functions. Patches to improve this are of great interest to us. + +* In particular, libarchive's modules to read or write a directory + tree do use `chdir()` to optimize the directory traversals. This + can cause problems for programs that expect to do disk access from + multiple threads. Of course, those modules are completely + optional and you can use the rest of libarchive without them. + +* The library is _not_ thread aware, however. It does no locking + or thread management of any kind. If you create a libarchive + object and need to access it from multiple threads, you will + need to provide your own locking. + +* On read, the library accepts whatever blocks you hand it. + Your read callback is free to pass the library a byte at a time + or mmap the entire archive and give it to the library at once. + On write, the library always produces correctly-blocked output. + +* The object-style approach allows you to have multiple archive streams + open at once. bsdtar uses this in its "@archive" extension. + +* The archive itself is read/written using callback functions. + You can read an archive directly from an in-memory buffer or + write it to a socket, if you wish. There are some utility + functions to provide easy-to-use "open file," etc, capabilities. + +* The read/write APIs are designed to allow individual entries + to be read or written to any data source: You can create + a block of data in memory and add it to a tar archive without + first writing a temporary file. You can also read an entry from + an archive and write the data directly to a socket. If you want + to read/write entries to disk, there are convenience functions to + make this especially easy. + +* Note: The "pax interchange format" is a POSIX standard extended tar + format that should be used when the older _ustar_ format is not + appropriate. It has many advantages over other tar formats + (including the legacy GNU tar format) and is widely supported by + current tar implementations. + diff --git a/dependencies/libarchive-3.4.2/aclocal.m4 b/dependencies/libarchive-3.4.2/aclocal.m4 new file mode 100644 index 0000000..62cc146 --- /dev/null +++ b/dependencies/libarchive-3.4.2/aclocal.m4 @@ -0,0 +1,10521 @@ +# generated automatically by aclocal 1.15.1 -*- Autoconf -*- + +# Copyright (C) 1996-2017 Free Software Foundation, Inc. + +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, +[m4_warning([this file was generated for autoconf 2.69. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically 'autoreconf'.])]) + +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +# +# Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +m4_define([_LT_COPYING], [dnl +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +]) + +# serial 58 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_PREPARE_CC_BASENAME +# ----------------------- +m4_defun([_LT_PREPARE_CC_BASENAME], [ +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in @S|@*""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} +])# _LT_PREPARE_CC_BASENAME + + +# _LT_CC_BASENAME(CC) +# ------------------- +# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, +# but that macro is also expanded into generated libtool script, which +# arranges for $SED and $ECHO to be set by different means. +m4_defun([_LT_CC_BASENAME], +[m4_require([_LT_PREPARE_CC_BASENAME])dnl +AC_REQUIRE([_LT_DECL_SED])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl +func_cc_basename $1 +cc_basename=$func_cc_basename_result +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + +_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl +dnl +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_WITH_SYSROOT])dnl +m4_require([_LT_CMD_TRUNCATE])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from 'configure', and 'config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# 'config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain=$ac_aux_dir/ltmain.sh +])# _LT_PROG_LTMAIN + + + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the 'libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to 'config.status' so that its +# declaration there will have the same value as in 'configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags='_LT_TAGS'dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into 'config.status', and then the shell code to quote escape them in +# for loops in 'config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +_LT_OUTPUT_LIBTOOL_INIT +]) + +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# '#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test 0 = "$lt_write_fail" && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), incase it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) + +cat >>"$CONFIG_LT" <<\_LTEOF +lt_cl_silent=false +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +'$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to ." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2011 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test 0 != $[#] +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try '$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try '$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +lt_cl_success=: +test yes = "$silent" && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +_LT_COPYING +_LT_LIBTOOL_TAGS + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +_LT_PREPARE_MUNGE_PATH_LIST +_LT_PREPARE_CC_BASENAME + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Go], [_LT_LANG(GO)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +m4_ifndef([AC_PROG_GO], [ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_GO. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +m4_defun([AC_PROG_GO], +[AC_LANG_PUSH(Go)dnl +AC_ARG_VAR([GOC], [Go compiler command])dnl +AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl +_AC_ARG_VAR_LDFLAGS()dnl +AC_CHECK_TOOL(GOC, gccgo) +if test -z "$GOC"; then + if test -n "$ac_tool_prefix"; then + AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) + fi +fi +if test -z "$GOC"; then + AC_CHECK_PROG(GOC, gccgo, gccgo, false) +fi +])#m4_defun +])#m4_ifndef + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([AC_PROG_GO], + [LT_LANG(GO)], + [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS=$save_LDFLAGS + ]) + + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[[012]][[,.]]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES([TAG]) +# --------------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + if test yes = "$lt_cv_ld_force_load"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], + [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + m4_if([$1], [CXX], +[ if test yes != "$lt_cv_apple_cc_single_mod"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) +# ---------------------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +# Store the results from the different compilers for each TAGNAME. +# Allow to override them for all tags through lt_cv_aix_libpath. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], + [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ + lt_aix_libpath_sed='[ + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }]' + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi],[]) + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib + fi + ]) + aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) +fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script that will find a shell with a builtin +# printf (that we can use as an echo command). +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +case $ECHO in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac + +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) + +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_WITH_SYSROOT +# ---------------- +AC_DEFUN([_LT_WITH_SYSROOT], +[AC_MSG_CHECKING([for sysroot]) +AC_ARG_WITH([sysroot], +[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], + [Search for dependent libraries within DIR (or the compiler's sysroot + if not specified).])], +[], [with_sysroot=no]) + +dnl lt_sysroot will always be passed unquoted. We quote it here +dnl in case the user passed a directory name. +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + AC_MSG_RESULT([$with_sysroot]) + AC_MSG_ERROR([The sysroot must be an absolute path.]) + ;; +esac + + AC_MSG_RESULT([${lt_sysroot:-no}]) +_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl +[dependent libraries, and where our libraries should be installed.])]) + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock +])# _LT_ENABLE_LOCK + + +# _LT_PROG_AR +# ----------- +m4_defun([_LT_PROG_AR], +[AC_CHECK_TOOLS(AR, [ar], false) +: ${AR=ar} +: ${AR_FLAGS=cru} +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], + [lt_cv_ar_at_file=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([lt_ar_try]) + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + AC_TRY_EVAL([lt_ar_try]) + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + ]) + ]) + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi +_LT_DECL([], [archiver_list_spec], [1], + [How to feed a file listing to the archiver]) +])# _LT_PROG_AR + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[_LT_PROG_AR + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test yes = "[$]$2"; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS +]) + +if test yes = "[$]$2"; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n "$lt_cv_sys_max_cmd_len"; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes = "$cross_compiling"; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen=shl_load], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen=dlopen], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links=nottested +if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test no = "$hard_links"; then + AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", + [Define to the sub-directory where libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then + + # We can hardcode non-existent directories. + if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && + test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || + test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_PREPARE_MUNGE_PATH_LIST +# --------------------------- +# Make sure func_munge_path_list() is defined correctly. +m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], +[[# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x@S|@2 in + x) + ;; + *:) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" + ;; + x:*) + eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" + ;; + *) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + esac +} +]])# _LT_PREPARE_PATH_LIST + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +AC_ARG_VAR([LT_SYS_LIBRARY_PATH], +[User-defined run-time library search path.]) + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[[4-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a[(]lib.so.V[)]' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[23]].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[[3-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[List of archive names. First name is the real one, the rest are links. + The last name is the one that the linker finds with -lNAME]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], + [Detected run-time system search path for libraries]) +_LT_DECL([], [configure_time_lt_sys_library_path], [2], + [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program that can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$1"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac]) +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program that can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test no = "$withval" || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], +[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi]) +rm -f conftest.i conftest2.i conftest.out]) +])# _LT_PATH_DD + + +# _LT_CMD_TRUNCATE +# ---------------- +# find command to truncate a binary pipe +m4_defun([_LT_CMD_TRUNCATE], +[m4_require([_LT_PATH_DD]) +AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], +[printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) +_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], + [Command to truncate a binary pipe]) +])# _LT_CMD_TRUNCATE + + +# _LT_CHECK_MAGIC_METHOD +# ---------------------- +# how to check for library dependencies +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_MAGIC_METHOD], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +AC_CACHE_CHECK([how to recognize dependent libraries], +lt_cv_deplibs_check_method, +[lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[[4-9]]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[[45]]*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method = "file_magic"]) +_LT_DECL([], [file_magic_glob], [1], + [How to find potential files when deplibs_check_method = "file_magic"]) +_LT_DECL([], [want_nocaseglob], [1], + [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi]) +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + AC_SUBST([DUMPBIN]) + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + +# _LT_CHECK_SHAREDLIB_FROM_LINKLIB +# -------------------------------- +# how to determine the name of the shared library +# associated with a specific link library. +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +m4_require([_LT_DECL_DLLTOOL]) +AC_CACHE_CHECK([how to associate runtime and link libraries], +lt_cv_sharedlib_from_linklib_cmd, +[lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac +]) +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + +_LT_DECL([], [sharedlib_from_linklib_cmd], [1], + [Command to associate shared and link libraries]) +])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB + + +# _LT_PATH_MANIFEST_TOOL +# ---------------------- +# locate the manifest tool +m4_defun([_LT_PATH_MANIFEST_TOOL], +[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], + [lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&AS_MESSAGE_LOG_FD + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest*]) +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi +_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl +])# _LT_PATH_MANIFEST_TOOL + + +# _LT_DLL_DEF_P([FILE]) +# --------------------- +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with func_dll_def_p in the libtool script +AC_DEFUN([_LT_DLL_DEF_P], +[dnl + test DEF = "`$SED -n dnl + -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace + -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments + -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl + -e q dnl Only consider the first "real" line + $1`" dnl +])# _LT_DLL_DEF_P + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM=-lm) + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[[ABCDEGRST]]' + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT@&t@_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT@&t@_DLSYM_CONST +#else +# define LT@&t@_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT@&t@_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], + [Transform the output of nm into a list of symbols to manually relocate]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([nm_interface], [lt_cv_nm_interface], [1], + [The name lister interface]) +_LT_DECL([], [nm_file_list_spec], [1], + [Specify filename containing input files for $NM]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64, which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd* | netbsdelf*-gnu) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test yes = "$GCC"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + *Sun\ F* | *Sun*Fortran*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + *Intel*\ [[CF]]*Compiler*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + *Portland\ Group*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +AC_CACHE_CHECK([for $compiler option to produce PIC], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + case $host_os in + aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + ;; + esac + ;; + linux* | k*bsd*-gnu | gnu*) + _LT_TAGVAR(link_all_deplibs, $1)=no + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + linux* | k*bsd*-gnu | gnu*) + _LT_TAGVAR(link_all_deplibs, $1)=no + ;; + esac + + _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + esac + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + ;; + esac + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], + [lt_cv_irix_exported_symbol], + [save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + AC_LINK_IFELSE( + [AC_LANG_SOURCE( + [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], + [C++], [[int foo (void) { return 0; }]], + [Fortran 77], [[ + subroutine foo + end]], + [Fortran], [[ + subroutine foo + end]])])], + [lt_cv_irix_exported_symbol=yes], + [lt_cv_irix_exported_symbol=no]) + LDFLAGS=$save_LDFLAGS]) + if test yes = "$lt_cv_irix_exported_symbol"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + _LT_TAGVAR(link_all_deplibs, $1)=no + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(ld_shlibs, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + osf3*) + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $_LT_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting $shlibpath_var if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [postlink_cmds], [2], + [Commands necessary for finishing linking programs]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC=$CC +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report what library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC=$lt_save_CC +])# _LT_LANG_C_CONFIG + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +if test -n "$CXX" && ( test no != "$CXX" && + ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || + (test g++ != "$CXX"))); then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_caught_CXX_error"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test yes = "$GXX"; then + # Set up default GNU C++ configuration + + LT_PATH_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test yes = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='$wl' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GXX"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag=$shared_flag' $wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + # The "-G" linker flag allows undefined symbols. + _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared + # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd2.*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ + $RM $lib.exp' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require '-G' NOT '-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + + _LT_TAGVAR(GCC, $1)=$GXX + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test yes != "$_lt_caught_CXX_error" + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_FUNC_STRIPNAME_CNF +# ---------------------- +# func_stripname_cnf prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# +# This function is identical to the (non-XSI) version of func_stripname, +# except this one can be used by m4 code that may be executed by configure, +# rather than the libtool script. +m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl +AC_REQUIRE([_LT_DECL_SED]) +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) +func_stripname_cnf () +{ + case @S|@2 in + .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; + *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; + esac +} # func_stripname_cnf +])# _LT_FUNC_STRIPNAME_CNF + + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF +package foo +func foo() { +} +_LT_EOF +]) + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case $prev$p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test x-L = "$p" || + test x-R = "$p"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test no = "$pre_test_object_deps_done"; then + case $prev in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)=$prev$p + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test no = "$pre_test_object_deps_done"; then + if test -z "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)=$p + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)=$p + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test no = "$F77"; then + _lt_disable_F77=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_F77"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${F77-"f77"} + CFLAGS=$FFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$G77 + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_F77" + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test no = "$FC"; then + _lt_disable_FC=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_FC"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${FC-"f95"} + CFLAGS=$FCFLAGS + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_FC" + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +CFLAGS=$GCJFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_GO_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Go compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GO_CONFIG], +[AC_REQUIRE([LT_PROG_GO])dnl +AC_LANG_SAVE + +# Source file extension for Go test sources. +ac_ext=go + +# Object file extension for compiled Go test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="package main; func main() { }" + +# Code to be used in simple link tests +lt_simple_link_test_code='package main; func main() { }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GOC-"gccgo"} +CFLAGS=$GOFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# Go did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GO_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code=$lt_simple_compile_test_code + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +CFLAGS= +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_GO +# ---------- +AC_DEFUN([LT_PROG_GO], +[AC_CHECK_TOOL(GOC, gccgo,) +]) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + +# _LT_DECL_DLLTOOL +# ---------------- +# Ensure DLLTOOL variable is set. +m4_defun([_LT_DECL_DLLTOOL], +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) +AC_SUBST([DLLTOOL]) +]) + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f "$lt_ac_sed" && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test 10 -lt "$lt_ac_count" && break + lt_ac_count=`expr $lt_ac_count + 1` + if test "$lt_ac_count" -gt "$lt_ac_max"; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PATH_CONVERSION_FUNCTIONS +# ----------------------------- +# Determine what file name conversion functions should be used by +# func_to_host_file (and, implicitly, by func_to_host_path). These are needed +# for certain cross-compile configurations and native mingw. +m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_MSG_CHECKING([how to convert $build file names to $host format]) +AC_CACHE_VAL(lt_cv_to_host_file_cmd, +[case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac +]) +to_host_file_cmd=$lt_cv_to_host_file_cmd +AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) +_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], + [0], [convert $build file names to $host format])dnl + +AC_MSG_CHECKING([how to convert $build file names to toolchain format]) +AC_CACHE_VAL(lt_cv_to_tool_file_cmd, +[#assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac +]) +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) +_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], + [0], [convert $build files to toolchain format])dnl +])# _LT_PATH_CONVERSION_FUNCTIONS + +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 8 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option '$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl 'shared' nor 'disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], + [_LT_WITH_AIX_SONAME([aix])]) + ]) +])# _LT_SET_OPTIONS + + + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [1], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the 'shared' and +# 'disable-shared' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the 'static' and +# 'disable-static' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the 'fast-install' +# and 'disable-fast-install' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_AIX_SONAME([DEFAULT]) +# ---------------------------------- +# implement the --with-aix-soname flag, and support the `aix-soname=aix' +# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT +# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. +m4_define([_LT_WITH_AIX_SONAME], +[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl +shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[[5-9]]*,yes) + AC_MSG_CHECKING([which variant of shared library versioning to provide]) + AC_ARG_WITH([aix-soname], + [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], + [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], + [case $withval in + aix|svr4|both) + ;; + *) + AC_MSG_ERROR([Unknown argument to --with-aix-soname]) + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname], + [AC_CACHE_VAL([lt_cv_with_aix_soname], + [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) + with_aix_soname=$lt_cv_with_aix_soname]) + AC_MSG_RESULT([$with_aix_soname]) + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + +_LT_DECL([], [shared_archive_member_spec], [0], + [Shared archive member basename, for filename based shared library versioning on AIX])dnl +])# _LT_WITH_AIX_SONAME + +LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the 'pic-only' and 'no-pic' +# LT_INIT options. +# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [pic_mode=m4_default([$1], [default])]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) + +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59, which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) + +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# @configure_input@ + +# serial 4179 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.4.6]) +m4_define([LT_PACKAGE_REVISION], [2.4.6]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.4.6' +macro_revision='2.4.6' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) + +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 5 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) + +dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +dnl serial 11 (pkg-config-0.29.1) +dnl +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29.1]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])dnl PKG_PROG_PKG_CONFIG + +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])dnl _PKG_CONFIG + +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])dnl _PKG_SHORT_ERRORS_SUPPORTED + + +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR + +# Copyright (C) 2002-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.15' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.15.1], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.15.1])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to +# '$srcdir', '$srcdir/..', or '$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is '.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ([2.52])dnl + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], + [$1], [CXX], [depcc="$CXX" am_compiler_list=], + [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], + [$1], [UPC], [depcc="$UPC" am_compiler_list=], + [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES. +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE([dependency-tracking], [dnl +AS_HELP_STRING( + [--enable-dependency-tracking], + [do not reject slow dependency extractors]) +AS_HELP_STRING( + [--disable-dependency-tracking], + [speeds up one-time build])]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "$am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each '.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. +m4_define([AC_PROG_CC], +m4_defn([AC_PROG_CC]) +[_AM_PROG_CC_C_O +]) + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.65])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[AC_DIAGNOSE([obsolete], + [$0: two- and three-arguments forms are deprecated.]) +m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if( + m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), + [ok:ok],, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) + AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) +AM_MISSING_PROG([AUTOCONF], [autoconf]) +AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) +AM_MISSING_PROG([AUTOHEADER], [autoheader]) +AM_MISSING_PROG([MAKEINFO], [makeinfo]) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +AC_SUBST([mkdir_p], ['$(MKDIR_P)']) +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES([CC])], + [m4_define([AC_PROG_CC], + m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES([CXX])], + [m4_define([AC_PROG_CXX], + m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES([OBJC])], + [m4_define([AC_PROG_OBJC], + m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], + [_AM_DEPENDENCIES([OBJCXX])], + [m4_define([AC_PROG_OBJCXX], + m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl +]) +AC_REQUIRE([AM_SILENT_RULES])dnl +dnl The testsuite driver may need to know about EXEEXT, so add the +dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This +dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) + fi +fi +dnl The trailing newline in this macro's definition is deliberate, for +dnl backward compatibility and to allow trailing 'dnl'-style comments +dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. +]) + +dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST([install_sh])]) + +# Copyright (C) 2003-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Add --enable-maintainer-mode option to configure. -*- Autoconf -*- +# From Jim Meyering + +# Copyright (C) 1996-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MAINTAINER_MODE([DEFAULT-MODE]) +# ---------------------------------- +# Control maintainer-specific portions of Makefiles. +# Default is to disable them, unless 'enable' is passed literally. +# For symmetry, 'disable' may be passed as well. Anyway, the user +# can override the default with the --enable/--disable switch. +AC_DEFUN([AM_MAINTAINER_MODE], +[m4_case(m4_default([$1], [disable]), + [enable], [m4_define([am_maintainer_other], [disable])], + [disable], [m4_define([am_maintainer_other], [enable])], + [m4_define([am_maintainer_other], [enable]) + m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) +AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) + dnl maintainer-mode's default is 'disable' unless 'enable' is passed + AC_ARG_ENABLE([maintainer-mode], + [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode], + am_maintainer_other[ make rules and dependencies not useful + (and sometimes confusing) to the casual installer])], + [USE_MAINTAINER_MODE=$enableval], + [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) + AC_MSG_RESULT([$USE_MAINTAINER_MODE]) + AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST([MAINT])dnl +] +) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it is modern enough. +# If it is, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + AC_MSG_WARN(['missing' script is too old or missing]) +fi +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Copyright (C) 1999-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_CC_C_O +# --------------- +# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC +# to automatically call this. +AC_DEFUN([_AM_PROG_CC_C_O], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +AC_LANG_PUSH([C])dnl +AC_CACHE_CHECK( + [whether $CC understands -c and -o together], + [am_cv_prog_cc_c_o], + [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i]) +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +AC_LANG_POP([C])]) + +# For backward compatibility. +AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) + +# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_RUN_LOG(COMMAND) +# ------------------- +# Run COMMAND, save the exit status in ac_status, and log it. +# (This has been adapted from Autoconf's _AC_RUN_LOG macro.) +AC_DEFUN([AM_RUN_LOG], +[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD + ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + (exit $ac_status); }]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken + alias in your environment]) + fi + if test "$[2]" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT([yes]) +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi +AC_CONFIG_COMMANDS_PRE( + [AC_MSG_CHECKING([that generated files are newer than configure]) + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + AC_MSG_RESULT([done])]) +rm -f conftest.file +]) + +# Copyright (C) 2009-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SILENT_RULES([DEFAULT]) +# -------------------------- +# Enable less verbose build rules; with the default set to DEFAULT +# ("yes" being less verbose, "no" or empty being verbose). +AC_DEFUN([AM_SILENT_RULES], +[AC_ARG_ENABLE([silent-rules], [dnl +AS_HELP_STRING( + [--enable-silent-rules], + [less verbose build output (undo: "make V=1")]) +AS_HELP_STRING( + [--disable-silent-rules], + [verbose build output (undo: "make V=0")])dnl +]) +case $enable_silent_rules in @%:@ ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; +esac +dnl +dnl A few 'make' implementations (e.g., NonStop OS and NextStep) +dnl do not support nested variable expansions. +dnl See automake bug#9928 and bug#10237. +am_make=${MAKE-make} +AC_CACHE_CHECK([whether $am_make supports nested variables], + [am_cv_make_support_nested_variables], + [if AS_ECHO([['TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi]) +if test $am_cv_make_support_nested_variables = yes; then + dnl Using '$V' instead of '$(V)' breaks IRIX make. + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AC_SUBST([AM_V])dnl +AM_SUBST_NOTMAKE([AM_V])dnl +AC_SUBST([AM_DEFAULT_V])dnl +AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl +AC_SUBST([AM_DEFAULT_VERBOSITY])dnl +AM_BACKSLASH='\' +AC_SUBST([AM_BACKSLASH])dnl +_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl +]) + +# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor 'install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in "make install-strip", and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of 'v7', 'ustar', or 'pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +# +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' + +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + + [m4_case([$1], + [ustar], + [# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) + if test $am_uid -le $am_max_uid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi + AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) + if test $am_gid -le $am_max_gid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi], + + [pax], + [], + + [m4_fatal([Unknown tar format])]) + + AC_MSG_CHECKING([how to create a $1 tar archive]) + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_$1-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi + done + rm -rf conftest.dir + + AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) + AC_MSG_RESULT([$am_cv_prog_tar_$1])]) + +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +m4_include([build/autoconf/ax_append_compile_flags.m4]) +m4_include([build/autoconf/ax_append_flag.m4]) +m4_include([build/autoconf/ax_check_compile_flag.m4]) +m4_include([build/autoconf/ax_require_defined.m4]) +m4_include([build/autoconf/check_stdcall_func.m4]) +m4_include([build/autoconf/iconv.m4]) +m4_include([build/autoconf/la_uid_t.m4]) +m4_include([build/autoconf/lib-ld.m4]) +m4_include([build/autoconf/lib-link.m4]) +m4_include([build/autoconf/lib-prefix.m4]) diff --git a/dependencies/libarchive-3.4.2/build/autoconf/ax_append_compile_flags.m4 b/dependencies/libarchive-3.4.2/build/autoconf/ax_append_compile_flags.m4 new file mode 100644 index 0000000..2bb27ef --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/autoconf/ax_append_compile_flags.m4 @@ -0,0 +1,67 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_append_compile_flags.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_APPEND_COMPILE_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT]) +# +# DESCRIPTION +# +# For every FLAG1, FLAG2 it is checked whether the compiler works with the +# flag. If it does, the flag is added FLAGS-VARIABLE +# +# If FLAGS-VARIABLE is not specified, the current language's flags (e.g. +# CFLAGS) is used. During the check the flag is always added to the +# current language's flags. +# +# If EXTRA-FLAGS is defined, it is added to the current language's default +# flags (e.g. CFLAGS) when the check is done. The check is thus made with +# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to +# force the compiler to issue an error when a bad flag is given. +# +# INPUT gives an alternative input source to AC_COMPILE_IFELSE. +# +# NOTE: This macro depends on the AX_APPEND_FLAG and +# AX_CHECK_COMPILE_FLAG. Please keep this macro in sync with +# AX_APPEND_LINK_FLAGS. +# +# LICENSE +# +# Copyright (c) 2011 Maarten Bosmans +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 5 + +AC_DEFUN([AX_APPEND_COMPILE_FLAGS], +[AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG]) +AX_REQUIRE_DEFINED([AX_APPEND_FLAG]) +for flag in $1; do + AX_CHECK_COMPILE_FLAG([$flag], [AX_APPEND_FLAG([$flag], [$2])], [], [$3], [$4]) +done +])dnl AX_APPEND_COMPILE_FLAGS diff --git a/dependencies/libarchive-3.4.2/build/autoconf/ax_append_flag.m4 b/dependencies/libarchive-3.4.2/build/autoconf/ax_append_flag.m4 new file mode 100644 index 0000000..08f2e07 --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/autoconf/ax_append_flag.m4 @@ -0,0 +1,71 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_append_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE]) +# +# DESCRIPTION +# +# FLAG is appended to the FLAGS-VARIABLE shell variable, with a space +# added in between. +# +# If FLAGS-VARIABLE is not specified, the current language's flags (e.g. +# CFLAGS) is used. FLAGS-VARIABLE is not changed if it already contains +# FLAG. If FLAGS-VARIABLE is unset in the shell, it is set to exactly +# FLAG. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim +# Copyright (c) 2011 Maarten Bosmans +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 6 + +AC_DEFUN([AX_APPEND_FLAG], +[dnl +AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_SET_IF +AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])]) +AS_VAR_SET_IF(FLAGS,[ + AS_CASE([" AS_VAR_GET(FLAGS) "], + [*" $1 "*], [AC_RUN_LOG([: FLAGS already contains $1])], + [ + AS_VAR_APPEND(FLAGS,[" $1"]) + AC_RUN_LOG([: FLAGS="$FLAGS"]) + ]) + ], + [ + AS_VAR_SET(FLAGS,[$1]) + AC_RUN_LOG([: FLAGS="$FLAGS"]) + ]) +AS_VAR_POPDEF([FLAGS])dnl +])dnl AX_APPEND_FLAG diff --git a/dependencies/libarchive-3.4.2/build/autoconf/ax_check_compile_flag.m4 b/dependencies/libarchive-3.4.2/build/autoconf/ax_check_compile_flag.m4 new file mode 100644 index 0000000..ca36397 --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/autoconf/ax_check_compile_flag.m4 @@ -0,0 +1,74 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) +# +# DESCRIPTION +# +# Check whether the given FLAG works with the current language's compiler +# or gives an error. (Warnings, however, are ignored) +# +# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on +# success/failure. +# +# If EXTRA-FLAGS is defined, it is added to the current language's default +# flags (e.g. CFLAGS) when the check is done. The check is thus made with +# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to +# force the compiler to issue an error when a bad flag is given. +# +# INPUT gives an alternative input source to AC_COMPILE_IFELSE. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this +# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim +# Copyright (c) 2011 Maarten Bosmans +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 4 + +AC_DEFUN([AX_CHECK_COMPILE_FLAG], +[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF +AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl +AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ + ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS + _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" + AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], + [AS_VAR_SET(CACHEVAR,[yes])], + [AS_VAR_SET(CACHEVAR,[no])]) + _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) +AS_VAR_IF(CACHEVAR,yes, + [m4_default([$2], :)], + [m4_default([$3], :)]) +AS_VAR_POPDEF([CACHEVAR])dnl +])dnl AX_CHECK_COMPILE_FLAGS diff --git a/dependencies/libarchive-3.4.2/build/autoconf/ax_require_defined.m4 b/dependencies/libarchive-3.4.2/build/autoconf/ax_require_defined.m4 new file mode 100644 index 0000000..cae1111 --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/autoconf/ax_require_defined.m4 @@ -0,0 +1,37 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_require_defined.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_REQUIRE_DEFINED(MACRO) +# +# DESCRIPTION +# +# AX_REQUIRE_DEFINED is a simple helper for making sure other macros have +# been defined and thus are available for use. This avoids random issues +# where a macro isn't expanded. Instead the configure script emits a +# non-fatal: +# +# ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found +# +# It's like AC_REQUIRE except it doesn't expand the required macro. +# +# Here's an example: +# +# AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) +# +# LICENSE +# +# Copyright (c) 2014 Mike Frysinger +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 1 + +AC_DEFUN([AX_REQUIRE_DEFINED], [dnl + m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])]) +])dnl AX_REQUIRE_DEFINED diff --git a/dependencies/libarchive-3.4.2/build/autoconf/check_stdcall_func.m4 b/dependencies/libarchive-3.4.2/build/autoconf/check_stdcall_func.m4 new file mode 100644 index 0000000..926b046 --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/autoconf/check_stdcall_func.m4 @@ -0,0 +1,51 @@ +# AC_LANG_STDCALL_FUNC_LINK_TRY(FUNCTION, SIGNATURE) +# ------------------------------- +# Produce a source which links correctly iff the FUNCTION exists. +AC_DEFUN([AC_LANG_STDCALL_FUNC_LINK_TRY], +[_AC_LANG_DISPATCH([$0], _AC_LANG, $@)]) + +# AC_CHECK_STDCALL_FUNC(FUNCTION, SIGNATURE, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# ----------------------------------------------------------------- +AC_DEFUN([AC_CHECK_STDCALL_FUNC], +[AS_VAR_PUSHDEF([ac_var], [ac_cv_func_$1])dnl +AC_CACHE_CHECK([for $1], ac_var, +[AC_LINK_IFELSE([AC_LANG_STDCALL_FUNC_LINK_TRY([$1],[$2])], + [AS_VAR_SET(ac_var, yes)], + [AS_VAR_SET(ac_var, no)])]) +AS_IF([test AS_VAR_GET(ac_var) = yes], [$3], [$4])dnl +AS_VAR_POPDEF([ac_var])dnl +])# AC_CHECK_FUNC + +# AC_LANG_STDCALL_FUNC_LINK_TRY(C)(FUNCTION, SIGNATURE) +# ---------------------------------- +# Don't include because on OSF/1 3.0 it includes +# which includes which contains a +# prototype for select. Similarly for bzero. +m4_define([AC_LANG_STDCALL_FUNC_LINK_TRY(C)], +[AC_LANG_PROGRAM( +[/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char __stdcall $1 ( $2 ) below. */ +#include +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char __stdcall $1 ( $2 ); +char (*f) ( $2 ); +], +[/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$1) || defined (__stub___$1) +choke me +#else +f = $1; +#endif +])]) + +# AC_LANG_STDCALL_FUNC_LINK_TRY(C++)(FUNCTION) +# ------------------------------------ +m4_copy([AC_LANG_STDCALL_FUNC_LINK_TRY(C)], [AC_LANG_STDCALL_FUNC_LINK_TRY(C++)]) + diff --git a/dependencies/libarchive-3.4.2/build/autoconf/compile b/dependencies/libarchive-3.4.2/build/autoconf/compile new file mode 100755 index 0000000..a85b723 --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/autoconf/compile @@ -0,0 +1,347 @@ +#! /bin/sh +# Wrapper for compilers which do not understand '-c -o'. + +scriptversion=2012-10-14.11; # UTC + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Written by Tom Tromey . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +nl=' +' + +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent tools from complaining about whitespace usage. +IFS=" "" $nl" + +file_conv= + +# func_file_conv build_file lazy +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. If the determined conversion +# type is listed in (the comma separated) LAZY, no conversion will +# take place. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv/,$2, in + *,$file_conv,*) + ;; + mingw/*) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin/*) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine/*) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + if test -f "$dir/lib$lib.a"; then + found=yes + lib=$dir/lib$lib.a + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + +# func_cl_wrapper cl arg... +# Adjust compile command to suit cl +func_cl_wrapper () +{ + # Assume a capable shell + lib_path= + shared=: + linker_opts= + for arg + do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + eat=1 + case $2 in + *.o | *.[oO][bB][jJ]) + func_file_conv "$2" + set x "$@" -Fo"$file" + shift + ;; + *) + func_file_conv "$2" + set x "$@" -Fe"$file" + shift + ;; + esac + ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; + -I*) + func_file_conv "${1#-I}" mingw + set x "$@" -I"$file" + shift + ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; + -l*) + func_cl_dashl "${1#-l}" + set x "$@" "$lib" + shift + ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; + -L*) + func_cl_dashL "${1#-L}" + ;; + -static) + shared=false + ;; + -Wl,*) + arg=${1#-Wl,} + save_ifs="$IFS"; IFS=',' + for flag in $arg; do + IFS="$save_ifs" + linker_opts="$linker_opts $flag" + done + IFS="$save_ifs" + ;; + -Xlinker) + eat=1 + linker_opts="$linker_opts $2" + ;; + -*) + set x "$@" "$1" + shift + ;; + *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) + func_file_conv "$1" + set x "$@" -Tp"$file" + shift + ;; + *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) + func_file_conv "$1" mingw + set x "$@" "$file" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift + done + if test -n "$linker_opts"; then + linker_opts="-link$linker_opts" + fi + exec "$@" $linker_opts + exit 1 +} + +eat= + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand '-c -o'. +Remove '-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file 'INSTALL'. + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) + func_cl_wrapper "$@" # Doesn't return... + ;; +esac + +ofile= +cfile= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + # So we strip '-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no '-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # '.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use '[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/dependencies/libarchive-3.4.2/build/autoconf/config.guess b/dependencies/libarchive-3.4.2/build/autoconf/config.guess new file mode 100755 index 0000000..f50dcdb --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/autoconf/config.guess @@ -0,0 +1,1480 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2018 Free Software Foundation, Inc. + +timestamp='2018-02-24' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. +# +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +# +# Please send patches to . + + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Options: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright 1992-2018 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > "$dummy.c" ; + for c in cc gcc c89 c99 ; do + if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +case "$UNAME_SYSTEM" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval "$set_cc_for_build" + cat <<-EOF > "$dummy.c" + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" + + # If ldd exists, use it to detect musl libc. + if command -v ldd >/dev/null && \ + ldd --version 2>&1 | grep -q ^musl + then + LIBC=musl + fi + ;; +esac + +# Note: order is significant - the case branches are not exclusive. + +case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + "/sbin/$sysctl" 2>/dev/null || \ + "/usr/sbin/$sysctl" 2>/dev/null || \ + echo unknown)` + case "$UNAME_MACHINE_ARCH" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + earmv*) + arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` + machine="${arch}${endian}"-unknown + ;; + *) machine="$UNAME_MACHINE_ARCH"-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently (or will in the future) and ABI. + case "$UNAME_MACHINE_ARCH" in + earm*) + os=netbsdelf + ;; + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval "$set_cc_for_build" + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # Determine ABI tags. + case "$UNAME_MACHINE_ARCH" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "$UNAME_VERSION" in + Debian*) + release='-gnu' + ;; + *) + release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "$machine-${os}${release}${abi}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" + exit ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" + exit ;; + *:MidnightBSD:*:*) + echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" + exit ;; + *:ekkoBSD:*:*) + echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" + exit ;; + *:SolidBSD:*:*) + echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd"$UNAME_RELEASE" + exit ;; + *:MirBSD:*:*) + echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" + exit ;; + *:Sortix:*:*) + echo "$UNAME_MACHINE"-unknown-sortix + exit ;; + *:Redox:*:*) + echo "$UNAME_MACHINE"-unknown-redox + exit ;; + mips:OSF1:*.*) + echo mips-dec-osf1 + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE=alpha ;; + "EV4.5 (21064)") + UNAME_MACHINE=alpha ;; + "LCA4 (21066/21068)") + UNAME_MACHINE=alpha ;; + "EV5 (21164)") + UNAME_MACHINE=alphaev5 ;; + "EV5.6 (21164A)") + UNAME_MACHINE=alphaev56 ;; + "EV5.6 (21164PC)") + UNAME_MACHINE=alphapca56 ;; + "EV5.7 (21164PC)") + UNAME_MACHINE=alphapca57 ;; + "EV6 (21264)") + UNAME_MACHINE=alphaev6 ;; + "EV6.7 (21264A)") + UNAME_MACHINE=alphaev67 ;; + "EV6.8CB (21264C)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8AL (21264B)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8CX (21264D)") + UNAME_MACHINE=alphaev68 ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE=alphaev69 ;; + "EV7 (21364)") + UNAME_MACHINE=alphaev7 ;; + "EV7.9 (21364A)") + UNAME_MACHINE=alphaev79 ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo "$UNAME_MACHINE"-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo "$UNAME_MACHINE"-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix"$UNAME_RELEASE" + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux"$UNAME_RELEASE" + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval "$set_cc_for_build" + SUN_ARCH=i386 + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH=x86_64 + fi + fi + echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`" + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos"$UNAME_RELEASE" + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos"$UNAME_RELEASE" + ;; + sun4) + echo sparc-sun-sunos"$UNAME_RELEASE" + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos"$UNAME_RELEASE" + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint"$UNAME_RELEASE" + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint"$UNAME_RELEASE" + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint"$UNAME_RELEASE" + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint"$UNAME_RELEASE" + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint"$UNAME_RELEASE" + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint"$UNAME_RELEASE" + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten"$UNAME_RELEASE" + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten"$UNAME_RELEASE" + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix"$UNAME_RELEASE" + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix"$UNAME_RELEASE" + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix"$UNAME_RELEASE" + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && + dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`"$dummy" "$dummyarg"` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos"$UNAME_RELEASE" + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ] + then + if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ + [ "$TARGET_BINARY_INTERFACE"x = x ] + then + echo m88k-dg-dgux"$UNAME_RELEASE" + else + echo m88k-dg-dguxbcs"$UNAME_RELEASE" + fi + else + echo i586-dg-dgux"$UNAME_RELEASE" + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`" + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" + fi + echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` + else + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" + fi + echo "$IBM_ARCH"-ibm-aix"$IBM_REV" + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + case "$UNAME_MACHINE" in + 9000/31?) HP_ARCH=m68000 ;; + 9000/[34]??) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "$sc_cpu_version" in + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "$sc_kernel_bits" in + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "$HP_ARCH" = "" ]; then + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ "$HP_ARCH" = hppa2.0w ] + then + eval "$set_cc_for_build" + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH=hppa2.0w + else + HP_ARCH=hppa64 + fi + fi + echo "$HP_ARCH"-hp-hpux"$HPUX_REV" + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux"$HPUX_REV" + exit ;; + 3050*:HI-UX:*:*) + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo "$UNAME_MACHINE"-unknown-osf1mk + else + echo "$UNAME_MACHINE"-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi"$UNAME_RELEASE" + exit ;; + *:BSD/OS:*:*) + echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case "$UNAME_PROCESSOR" in + amd64) + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; + esac + echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" + exit ;; + i*:CYGWIN*:*) + echo "$UNAME_MACHINE"-pc-cygwin + exit ;; + *:MINGW64*:*) + echo "$UNAME_MACHINE"-pc-mingw64 + exit ;; + *:MINGW*:*) + echo "$UNAME_MACHINE"-pc-mingw32 + exit ;; + *:MSYS*:*) + echo "$UNAME_MACHINE"-pc-msys + exit ;; + i*:PW*:*) + echo "$UNAME_MACHINE"-pc-pw32 + exit ;; + *:Interix*:*) + case "$UNAME_MACHINE" in + x86) + echo i586-pc-interix"$UNAME_RELEASE" + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix"$UNAME_RELEASE" + exit ;; + IA64) + echo ia64-unknown-interix"$UNAME_RELEASE" + exit ;; + esac ;; + i*:UWIN*:*) + echo "$UNAME_MACHINE"-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; + *:GNU:*:*) + # the GNU system + echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`" + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" + exit ;; + i*86:Minix:*:*) + echo "$UNAME_MACHINE"-pc-minix + exit ;; + aarch64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + arm*:Linux:*:*) + eval "$set_cc_for_build" + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi + else + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + cris:Linux:*:*) + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit ;; + crisv32:Linux:*:*) + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit ;; + e2k:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + frv:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + hexagon:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + i*86:Linux:*:*) + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" + exit ;; + ia64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + k1om:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + m32r*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + m68*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`" + test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; } + ;; + mips64el:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-"$LIBC" + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-"$LIBC" + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-"$LIBC" + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; + PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; + *) echo hppa-unknown-linux-"$LIBC" ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-"$LIBC" + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-"$LIBC" + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-"$LIBC" + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-"$LIBC" + exit ;; + riscv32:Linux:*:* | riscv64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" + exit ;; + sh64*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + sh*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + tile*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + vax:Linux:*:*) + echo "$UNAME_MACHINE"-dec-linux-"$LIBC" + exit ;; + x86_64:Linux:*:*) + if objdump -f /bin/sh | grep -q elf32-x86-64; then + echo "$UNAME_MACHINE"-pc-linux-"$LIBC"x32 + else + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" + fi + exit ;; + xtensa*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo "$UNAME_MACHINE"-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo "$UNAME_MACHINE"-unknown-stop + exit ;; + i*86:atheos:*:*) + echo "$UNAME_MACHINE"-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo "$UNAME_MACHINE"-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos"$UNAME_RELEASE" + exit ;; + i*86:*DOS:*:*) + echo "$UNAME_MACHINE"-pc-msdosdjgpp + exit ;; + i*86:*:4.*:*) + UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" + else + echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}" + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" + else + echo "$UNAME_MACHINE"-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configure will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos"$UNAME_RELEASE" + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos"$UNAME_RELEASE" + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos"$UNAME_RELEASE" + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos"$UNAME_RELEASE" + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv"$UNAME_RELEASE" + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo "$UNAME_MACHINE"-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo "$UNAME_MACHINE"-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux"$UNAME_RELEASE" + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv"$UNAME_RELEASE" + else + echo mips-unknown-sysv"$UNAME_RELEASE" + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux"$UNAME_RELEASE" + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux"$UNAME_RELEASE" + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux"$UNAME_RELEASE" + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux"$UNAME_RELEASE" + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux"$UNAME_RELEASE" + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux"$UNAME_RELEASE" + exit ;; + SX-ACE:SUPER-UX:*:*) + echo sxace-nec-superux"$UNAME_RELEASE" + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody"$UNAME_RELEASE" + exit ;; + *:Rhapsody:*:*) + echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + eval "$set_cc_for_build" + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc + fi + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + fi + echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = x86; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-*:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSR-*:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSV-*:NONSTOP_KERNEL:*:*) + echo nsv-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSX-*:NONSTOP_KERNEL:*:*) + echo nsx-tandem-nsk"$UNAME_RELEASE" + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = 386; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo "$UNAME_MACHINE"-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux"$UNAME_RELEASE" + exit ;; + *:DragonFly:*:*) + echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "$UNAME_MACHINE" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`" + exit ;; + i*86:rdos:*:*) + echo "$UNAME_MACHINE"-pc-rdos + exit ;; + i*86:AROS:*:*) + echo "$UNAME_MACHINE"-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo "$UNAME_MACHINE"-unknown-esx + exit ;; + amd64:Isilon\ OneFS:*:*) + echo x86_64-unknown-onefs + exit ;; +esac + +echo "$0: unable to guess system type" >&2 + +case "$UNAME_MACHINE:$UNAME_SYSTEM" in + mips:Linux | mips64:Linux) + # If we got here on MIPS GNU/Linux, output extra information. + cat >&2 <&2 </dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = "$UNAME_MACHINE" +UNAME_RELEASE = "$UNAME_RELEASE" +UNAME_SYSTEM = "$UNAME_SYSTEM" +UNAME_VERSION = "$UNAME_VERSION" +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-functions 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/dependencies/libarchive-3.4.2/build/autoconf/config.rpath b/dependencies/libarchive-3.4.2/build/autoconf/config.rpath new file mode 100755 index 0000000..51cf442 --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/autoconf/config.rpath @@ -0,0 +1,696 @@ +#! /bin/sh +# +# NOTE: This file was brought from +# http://git.savannah.gnu.org/cgit/gnulib.git/plain/build-aux/config.rpath +# You should sometimes check if the file is updated and bring it to +# our trunk and copy this note to the top of that file. +# +# Output a system dependent set of variables, describing how to set the +# run time search path of shared libraries in an executable. +# +# Copyright 1996-2011 Free Software Foundation, Inc. +# Taken from GNU libtool, 2001 +# Originally by Gordon Matzigkeit , 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# The first argument passed to this file is the canonical host specification, +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld +# should be set by the caller. +# +# The set of defined variables is at the end of this script. + +# Known limitations: +# - On IRIX 6.5 with CC="cc", the run time search patch must not be longer +# than 256 bytes, otherwise the compiler driver will dump core. The only +# known workaround is to choose shorter directory names for the build +# directory and/or the installation directory. + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a +shrext=.so + +host="$1" +host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + +# Code taken from libtool.m4's _LT_CC_BASENAME. + +for cc_temp in $CC""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'` + +# Code taken from libtool.m4's _LT_COMPILER_PIC. + +wl= +if test "$GCC" = yes; then + wl='-Wl,' +else + case "$host_os" in + aix*) + wl='-Wl,' + ;; + mingw* | cygwin* | msys* | pw32* | os2* | cegcc*) + ;; + hpux9* | hpux10* | hpux11*) + wl='-Wl,' + ;; + irix5* | irix6* | nonstopux*) + wl='-Wl,' + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + ecc*) + wl='-Wl,' + ;; + icc* | ifort*) + wl='-Wl,' + ;; + lf95*) + wl='-Wl,' + ;; + nagfor*) + wl='-Wl,-Wl,,' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + wl='-Wl,' + ;; + ccc*) + wl='-Wl,' + ;; + xl* | bgxl* | bgf* | mpixl*) + wl='-Wl,' + ;; + como) + wl='-lopt=' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ F* | *Sun*Fortran*) + wl= + ;; + *Sun\ C*) + wl='-Wl,' + ;; + esac + ;; + esac + ;; + newsos6) + ;; + *nto* | *qnx*) + ;; + osf3* | osf4* | osf5*) + wl='-Wl,' + ;; + rdos*) + ;; + solaris*) + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + wl='-Qoption ld ' + ;; + *) + wl='-Wl,' + ;; + esac + ;; + sunos4*) + wl='-Qoption ld ' + ;; + sysv4 | sysv4.2uw2* | sysv4.3*) + wl='-Wl,' + ;; + sysv4*MP*) + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + wl='-Wl,' + ;; + unicos*) + wl='-Wl,' + ;; + uts4*) + ;; + esac +fi + +# Code taken from libtool.m4's _LT_LINKER_SHLIBS. + +hardcode_libdir_flag_spec= +hardcode_libdir_separator= +hardcode_direct=no +hardcode_minus_L=no + +case "$host_os" in + cygwin* | msys* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; +esac + +ld_shlibs=yes +if test "$with_gnu_ld" = yes; then + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + # Unlike libtool, we use -rpath here, not --rpath, since the documented + # option of GNU ld is called -rpath, not --rpath. + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + case "$host_os" in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + fi + ;; + amigaos*) + case "$host_cpu" in + powerpc) + ;; + m68k) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + cygwin* | msys* | mingw* | pw32* | cegcc*) + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + haiku*) + ;; + interix[3-9]*) + hardcode_direct=no + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + netbsd*) + ;; + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + else + ld_shlibs=no + fi + ;; + esac + ;; + sunos4*) + hardcode_direct=yes + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + esac + if test "$ld_shlibs" = no; then + hardcode_libdir_flag_spec= + fi +else + case "$host_os" in + aix3*) + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + aix[4-9]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + else + aix_use_runtimelinking=no + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + fi + hardcode_direct=yes + hardcode_libdir_separator=':' + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + fi + # Begin _LT_AC_SYS_LIBPATH_AIX. + echo 'int main () { return 0; }' > conftest.c + ${CC} ${LDFLAGS} conftest.c -o conftest + aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` + if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` + fi + if test -z "$aix_libpath"; then + aix_libpath="/usr/lib:/lib" + fi + rm -f conftest.c conftest + # End _LT_AC_SYS_LIBPATH_AIX. + if test "$aix_use_runtimelinking" = yes; then + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + else + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + fi + fi + ;; + amigaos*) + case "$host_cpu" in + powerpc) + ;; + m68k) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + bsdi[45]*) + ;; + cygwin* | msys* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec=' ' + libext=lib + ;; + darwin* | rhapsody*) + hardcode_direct=no + if { case $cc_basename in ifort*) true;; *) test "$GCC" = yes;; esac; }; then + : + else + ld_shlibs=no + fi + ;; + dgux*) + hardcode_libdir_flag_spec='-L$libdir' + ;; + freebsd2.2*) + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + ;; + freebsd2*) + hardcode_direct=yes + hardcode_minus_L=yes + ;; + freebsd* | dragonfly*) + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + ;; + hpux9*) + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + hpux10*) + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + hpux11*) + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + ;; + *) + hardcode_direct=yes + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + irix5* | irix6* | nonstopux*) + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + netbsd*) + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + ;; + newsos6) + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + *nto* | *qnx*) + ;; + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + else + case "$host_os" in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + else + ld_shlibs=no + fi + ;; + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + osf3*) + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + osf4* | osf5*) + if test "$GCC" = yes; then + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + # Both cc and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + hardcode_libdir_separator=: + ;; + solaris*) + hardcode_libdir_flag_spec='-R$libdir' + ;; + sunos4*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + ;; + sysv4) + case $host_vendor in + sni) + hardcode_direct=yes # is this really true??? + ;; + siemens) + hardcode_direct=no + ;; + motorola) + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + ;; + sysv4.3*) + ;; + sysv4*MP*) + if test -d /usr/nec; then + ld_shlibs=yes + fi + ;; + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + ;; + sysv5* | sco3.2v5* | sco5v6*) + hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator=':' + ;; + uts4*) + hardcode_libdir_flag_spec='-L$libdir' + ;; + *) + ld_shlibs=no + ;; + esac +fi + +# Check dynamic linker characteristics +# Code taken from libtool.m4's _LT_SYS_DYNAMIC_LINKER. +# Unlike libtool.m4, here we don't care about _all_ names of the library, but +# only about the one the linker finds when passed -lNAME. This is the last +# element of library_names_spec in libtool.m4, or possibly two of them if the +# linker has special search rules. +library_names_spec= # the last element of library_names_spec in libtool.m4 +libname_spec='lib$name' +case "$host_os" in + aix3*) + library_names_spec='$libname.a' + ;; + aix[4-9]*) + library_names_spec='$libname$shrext' + ;; + amigaos*) + case "$host_cpu" in + powerpc*) + library_names_spec='$libname$shrext' ;; + m68k) + library_names_spec='$libname.a' ;; + esac + ;; + beos*) + library_names_spec='$libname$shrext' + ;; + bsdi[45]*) + library_names_spec='$libname$shrext' + ;; + cygwin* | msys* | mingw* | pw32* | cegcc*) + shrext=.dll + library_names_spec='$libname.dll.a $libname.lib' + ;; + darwin* | rhapsody*) + shrext=.dylib + library_names_spec='$libname$shrext' + ;; + dgux*) + library_names_spec='$libname$shrext' + ;; + freebsd* | dragonfly*) + case "$host_os" in + freebsd[123]*) + library_names_spec='$libname$shrext$versuffix' ;; + *) + library_names_spec='$libname$shrext' ;; + esac + ;; + gnu*) + library_names_spec='$libname$shrext' + ;; + haiku*) + library_names_spec='$libname$shrext' + ;; + hpux9* | hpux10* | hpux11*) + case $host_cpu in + ia64*) + shrext=.so + ;; + hppa*64*) + shrext=.sl + ;; + *) + shrext=.sl + ;; + esac + library_names_spec='$libname$shrext' + ;; + interix[3-9]*) + library_names_spec='$libname$shrext' + ;; + irix5* | irix6* | nonstopux*) + library_names_spec='$libname$shrext' + case "$host_os" in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;; + *) libsuff= shlibsuff= ;; + esac + ;; + esac + ;; + linux*oldld* | linux*aout* | linux*coff*) + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu) + library_names_spec='$libname$shrext' + ;; + knetbsd*-gnu) + library_names_spec='$libname$shrext' + ;; + netbsd*) + library_names_spec='$libname$shrext' + ;; + newsos6) + library_names_spec='$libname$shrext' + ;; + *nto* | *qnx*) + library_names_spec='$libname$shrext' + ;; + openbsd*) + library_names_spec='$libname$shrext$versuffix' + ;; + os2*) + libname_spec='$name' + shrext=.dll + library_names_spec='$libname.a' + ;; + osf3* | osf4* | osf5*) + library_names_spec='$libname$shrext' + ;; + rdos*) + ;; + solaris*) + library_names_spec='$libname$shrext' + ;; + sunos4*) + library_names_spec='$libname$shrext$versuffix' + ;; + sysv4 | sysv4.3*) + library_names_spec='$libname$shrext' + ;; + sysv4*MP*) + library_names_spec='$libname$shrext' + ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + library_names_spec='$libname$shrext' + ;; + tpf*) + library_names_spec='$libname$shrext' + ;; + uts4*) + library_names_spec='$libname$shrext' + ;; +esac + +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' +escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"` +shlibext=`echo "$shrext" | sed -e 's,^\.,,'` +escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` +escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` +escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` + +LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + + +# Please send patches to . +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS + +Canonicalize a configuration name. + +Options: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright 1992-2018 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo "$1" + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ + kopensolaris*-gnu* | cloudabi*-eabi* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo "$1" | sed 's/-[^-]*$//'` + if [ "$basic_machine" != "$1" ] + then os=`echo "$1" | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze*) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | ba \ + | be32 | be64 \ + | bfin \ + | c4x | c8051 | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | epiphany \ + | fido | fr30 | frv | ft32 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia16 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ + | ns16k | ns32k \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pru \ + | pyramid \ + | riscv32 | riscv64 \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ + | wasm32 \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | ba-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | e2k-* | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ + | ip2k-* | iq2000-* \ + | k1om-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | or1k*-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pru-* \ + | pyramid-* \ + | riscv32-* | riscv64-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | visium-* \ + | wasm32-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-pc + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + asmjs) + basic_machine=asmjs-unknown + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2*) + basic_machine=m68k-bull + os=-sysv3 + ;; + e500v[12]) + basic_machine=powerpc-unknown + os=$os"spe" + ;; + e500v[12]-*) + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=$os"spe" + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'` + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=-linux + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + mingw32) + basic_machine=i686-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i686-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + nsv-tandem) + basic_machine=nsv-tandem + ;; + nsx-tandem) + basic_machine=nsx-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + x64) + basic_machine=x86_64-pc + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases that might get confused + # with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # es1800 is here to avoid being matched by es* (a different OS) + -es1800*) + os=-ose + ;; + # Now accept the basic system types. + # The portable systems comes first. + # Each alternative MUST end in a * to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* | -plan9* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* | -cloudabi* | -sortix* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ + | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \ + | -midnightbsd*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -xray | -os68k* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo "$os" | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo "$os" | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo "$os" | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4*) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -pikeos*) + # Until real need of OS specific support for + # particular features comes up, bare metal + # configurations are quite functional. + case $basic_machine in + arm*) + os=-eabi + ;; + *) + os=-elf + ;; + esac + ;; + -nacl*) + ;; + -ios) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + pru-*) + os=-elf + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"` + ;; +esac + +echo "$basic_machine$os" +exit + +# Local variables: +# eval: (add-hook 'write-file-functions 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/dependencies/libarchive-3.4.2/build/autoconf/depcomp b/dependencies/libarchive-3.4.2/build/autoconf/depcomp new file mode 100755 index 0000000..b39f98f --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/autoconf/depcomp @@ -0,0 +1,791 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2016-01-11.22; # UTC + +# Copyright (C) 1999-2017 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by 'PROGRAMS ARGS'. + object Object file output by 'PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputting dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +# Get the directory component of the given path, and save it in the +# global variables '$dir'. Note that this directory component will +# be either empty or ending with a '/' character. This is deliberate. +set_dir_from () +{ + case $1 in + */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; + *) dir=;; + esac +} + +# Get the suffix-stripped basename of the given path, and save it the +# global variable '$base'. +set_base_from () +{ + base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` +} + +# If no dependency file was actually created by the compiler invocation, +# we still have to create a dummy depfile, to avoid errors with the +# Makefile "include basename.Plo" scheme. +make_dummy_depfile () +{ + echo "#dummy" > "$depfile" +} + +# Factor out some common post-processing of the generated depfile. +# Requires the auxiliary global variable '$tmpdepfile' to be set. +aix_post_process_depfile () +{ + # If the compiler actually managed to produce a dependency file, + # post-process it. + if test -f "$tmpdepfile"; then + # Each line is of the form 'foo.o: dependency.h'. + # Do two passes, one to just change these to + # $object: dependency.h + # and one to simply output + # dependency.h: + # which is needed to avoid the deleted-header problem. + { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" + sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" + } > "$depfile" + rm -f "$tmpdepfile" + else + make_dummy_depfile + fi +} + +# A tabulation character. +tab=' ' +# A newline character. +nl=' +' +# Character ranges might be problematic outside the C locale. +# These definitions help. +upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ +lower=abcdefghijklmnopqrstuvwxyz +digits=0123456789 +alpha=${upper}${lower} + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Avoid interferences from the environment. +gccflag= dashmflag= + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvisualcpp +fi + +if test "$depmode" = msvc7msys; then + # This is just like msvc7 but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvc7 +fi + +if test "$depmode" = xlc; then + # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. + gccflag=-qmakedep=gcc,-MF + depmode=gcc +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. +## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. +## (see the conditional assignment to $gccflag above). +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). Also, it might not be +## supported by the other compilers which use the 'gcc' depmode. +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The second -e expression handles DOS-style file names with drive + # letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the "deleted header file" problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. +## Some versions of gcc put a space before the ':'. On the theory +## that the space means something, we add a space to the output as +## well. hp depmode also adds that space, but also prefixes the VPATH +## to the object. Take care to not repeat it in the output. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like '#:fec' to the end of the + # dependency line. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ + | tr "$nl" ' ' >> "$depfile" + echo >> "$depfile" + # The second pass generates a dummy entry for each header file. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" + ;; + +xlc) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts '$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + aix_post_process_depfile + ;; + +tcc) + # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 + # FIXME: That version still under development at the moment of writing. + # Make that this statement remains true also for stable, released + # versions. + # It will wrap lines (doesn't matter whether long or short) with a + # trailing '\', as in: + # + # foo.o : \ + # foo.c \ + # foo.h \ + # + # It will put a trailing '\' even on the last line, and will use leading + # spaces rather than leading tabs (at least since its commit 0394caf7 + # "Emit spaces for -MD"). + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. + # We have to change lines of the first kind to '$object: \'. + sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" + # And for each line of the second kind, we have to emit a 'dep.h:' + # dummy dependency, to avoid the deleted-header problem. + sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" + rm -f "$tmpdepfile" + ;; + +## The order of this option in the case statement is important, since the +## shell code in configure will try each of these formats in the order +## listed in this file. A plain '-MD' option would be understood by many +## compilers, so we must ensure this comes after the gcc and icc options. +pgcc) + # Portland's C compiler understands '-MD'. + # Will always output deps to 'file.d' where file is the root name of the + # source file under compilation, even if file resides in a subdirectory. + # The object file name does not affect the name of the '.d' file. + # pgcc 10.2 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using '\' : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + set_dir_from "$object" + # Use the source, not the object, to determine the base name, since + # that's sadly what pgcc will do too. + set_base_from "$source" + tmpdepfile=$base.d + + # For projects that build the same source file twice into different object + # files, the pgcc approach of using the *source* file root name can cause + # problems in parallel builds. Use a locking strategy to avoid stomping on + # the same $tmpdepfile. + lockdir=$base.d-lock + trap " + echo '$0: caught signal, cleaning up...' >&2 + rmdir '$lockdir' + exit 1 + " 1 2 13 15 + numtries=100 + i=$numtries + while test $i -gt 0; do + # mkdir is a portable test-and-set. + if mkdir "$lockdir" 2>/dev/null; then + # This process acquired the lock. + "$@" -MD + stat=$? + # Release the lock. + rmdir "$lockdir" + break + else + # If the lock is being held by a different process, wait + # until the winning process is done or we timeout. + while test -d "$lockdir" && test $i -gt 0; do + sleep 1 + i=`expr $i - 1` + done + fi + i=`expr $i - 1` + done + trap - 1 2 13 15 + if test $i -le 0; then + echo "$0: failed to acquire lock after $numtries attempts" >&2 + echo "$0: check lockdir '$lockdir'" >&2 + exit 1 + fi + + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" + # Add 'dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in 'foo.d' instead, so we check for that too. + # Subdirectories are respected. + set_dir_from "$object" + set_base_from "$object" + + if test "$libtool" = yes; then + # Libtool generates 2 separate objects for the 2 libraries. These + # two compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir$base.o.d # libtool 1.5 + tmpdepfile2=$dir.libs/$base.o.d # Likewise. + tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + # Same post-processing that is required for AIX mode. + aix_post_process_depfile + ;; + +msvc7) + if test "$libtool" = yes; then + showIncludes=-Wc,-showIncludes + else + showIncludes=-showIncludes + fi + "$@" $showIncludes > "$tmpdepfile" + stat=$? + grep -v '^Note: including file: ' "$tmpdepfile" + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The first sed program below extracts the file names and escapes + # backslashes for cygpath. The second sed program outputs the file + # name when reading, but also accumulates all include files in the + # hold buffer in order to output them again at the end. This only + # works with sed implementations that can handle large buffers. + sed < "$tmpdepfile" -n ' +/^Note: including file: *\(.*\)/ { + s//\1/ + s/\\/\\\\/g + p +}' | $cygpath_u | sort -u | sed -n ' +s/ /\\ /g +s/\(.*\)/'"$tab"'\1 \\/p +s/.\(.*\) \\/\1:/ +H +$ { + s/.*/'"$tab"'/ + G + p +}' >> "$depfile" + echo >> "$depfile" # make sure the fragment doesn't end with a backslash + rm -f "$tmpdepfile" + ;; + +msvc7msys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for ':' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. + "$@" $dashmflag | + sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this sed invocation + # correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + # makedepend may prepend the VPATH from the source file name to the object. + # No need to regex-escape $object, excess matching of '.' is harmless. + sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process the last invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed '1,2d' "$tmpdepfile" \ + | tr ' ' "$nl" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E \ + | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + | sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" + echo "$tab" >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/dependencies/libarchive-3.4.2/build/autoconf/iconv.m4 b/dependencies/libarchive-3.4.2/build/autoconf/iconv.m4 new file mode 100644 index 0000000..4e37363 --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/autoconf/iconv.m4 @@ -0,0 +1,271 @@ +# iconv.m4 serial 19 (gettext-0.18.2) +dnl Copyright (C) 2000-2002, 2007-2014 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([AM_ICONV_LINKFLAGS_BODY], +[ + dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + + dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV + dnl accordingly. + AC_LIB_LINKFLAGS_BODY([iconv]) +]) + +AC_DEFUN([AM_ICONV_LINK], +[ + dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and + dnl those with the standalone portable GNU libiconv installed). + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + + dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV + dnl accordingly. + AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) + + dnl Add $INCICONV to CPPFLAGS before performing the following checks, + dnl because if the user has installed libiconv and not disabled its use + dnl via --without-libiconv-prefix, he wants to use it. The first + dnl AC_LINK_IFELSE will then fail, the second AC_LINK_IFELSE will succeed. + am_save_CPPFLAGS="$CPPFLAGS" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV]) + + AC_CACHE_CHECK([for iconv], [am_cv_func_iconv], [ + am_cv_func_iconv="no, consider installing GNU libiconv" + am_cv_lib_iconv=no + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include + ]], + [[iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);]])], + [am_cv_func_iconv=yes]) + if test "$am_cv_func_iconv" != yes; then + am_save_LIBS="$LIBS" + LIBS="$LIBS $LIBICONV" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include + ]], + [[iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);]])], + [am_cv_lib_iconv=yes] + [am_cv_func_iconv=yes]) + LIBS="$am_save_LIBS" + fi + ]) + if test "$am_cv_func_iconv" = yes; then + AC_CACHE_CHECK([for working iconv], [am_cv_func_iconv_works], [ + dnl This tests against bugs in AIX 5.1, AIX 6.1..7.1, HP-UX 11.11, + dnl Solaris 10. + am_save_LIBS="$LIBS" + if test $am_cv_lib_iconv = yes; then + LIBS="$LIBS $LIBICONV" + fi + am_cv_func_iconv_works=no + for ac_iconv_const in '' 'const'; do + AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include + +#ifndef ICONV_CONST +# define ICONV_CONST $ac_iconv_const +#endif + ]], + [[int result = 0; + /* Test against AIX 5.1 bug: Failures are not distinguishable from successful + returns. */ + { + iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); + if (cd_utf8_to_88591 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\342\202\254"; /* EURO SIGN */ + char buf[10]; + ICONV_CONST char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_utf8_to_88591, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 1; + iconv_close (cd_utf8_to_88591); + } + } + /* Test against Solaris 10 bug: Failures are not distinguishable from + successful returns. */ + { + iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646"); + if (cd_ascii_to_88591 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\263"; + char buf[10]; + ICONV_CONST char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_ascii_to_88591, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 2; + iconv_close (cd_ascii_to_88591); + } + } + /* Test against AIX 6.1..7.1 bug: Buffer overrun. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\304"; + static char buf[2] = { (char)0xDE, (char)0xAD }; + ICONV_CONST char *inptr = input; + size_t inbytesleft = 1; + char *outptr = buf; + size_t outbytesleft = 1; + size_t res = iconv (cd_88591_to_utf8, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD) + result |= 4; + iconv_close (cd_88591_to_utf8); + } + } +#if 0 /* This bug could be worked around by the caller. */ + /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; + char buf[50]; + ICONV_CONST char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_88591_to_utf8, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if ((int)res > 0) + result |= 8; + iconv_close (cd_88591_to_utf8); + } + } +#endif + /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is + provided. */ + if (/* Try standardized names. */ + iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1) + /* Try IRIX, OSF/1 names. */ + && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1) + /* Try AIX names. */ + && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1) + /* Try HP-UX names. */ + && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) + result |= 16; + return result; +]])], + [am_cv_func_iconv_works=yes], , + [case "$host_os" in + aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; + *) am_cv_func_iconv_works="guessing yes" ;; + esac]) + test "$am_cv_func_iconv_works" = no || break + done + LIBS="$am_save_LIBS" + ]) + case "$am_cv_func_iconv_works" in + *no) am_func_iconv=no am_cv_lib_iconv=no ;; + *) am_func_iconv=yes ;; + esac + else + am_func_iconv=no am_cv_lib_iconv=no + fi + if test "$am_func_iconv" = yes; then + AC_DEFINE([HAVE_ICONV], [1], + [Define if you have the iconv() function and it works.]) + fi + if test "$am_cv_lib_iconv" = yes; then + AC_MSG_CHECKING([how to link with libiconv]) + AC_MSG_RESULT([$LIBICONV]) + else + dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV + dnl either. + CPPFLAGS="$am_save_CPPFLAGS" + LIBICONV= + LTLIBICONV= + fi + AC_SUBST([LIBICONV]) + AC_SUBST([LTLIBICONV]) +]) + +dnl Define AM_ICONV using AC_DEFUN_ONCE for Autoconf >= 2.64, in order to +dnl avoid warnings like +dnl "warning: AC_REQUIRE: `AM_ICONV' was expanded before it was required". +dnl This is tricky because of the way 'aclocal' is implemented: +dnl - It requires defining an auxiliary macro whose name ends in AC_DEFUN. +dnl Otherwise aclocal's initial scan pass would miss the macro definition. +dnl - It requires a line break inside the AC_DEFUN_ONCE and AC_DEFUN expansions. +dnl Otherwise aclocal would emit many "Use of uninitialized value $1" +dnl warnings. +m4_define([gl_iconv_AC_DEFUN], + m4_version_prereq([2.64], + [[AC_DEFUN_ONCE( + [$1], [$2])]], + [m4_ifdef([gl_00GNULIB], + [[AC_DEFUN_ONCE( + [$1], [$2])]], + [[AC_DEFUN( + [$1], [$2])]])])) +gl_iconv_AC_DEFUN([AM_ICONV], +[ + AM_ICONV_LINK + if test "$am_cv_func_iconv" = yes; then + AC_MSG_CHECKING([for iconv declaration]) + AC_CACHE_VAL([am_cv_proto_iconv], [ + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include +extern +#ifdef __cplusplus +"C" +#endif +#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) +size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); +#else +size_t iconv(); +#endif + ]], + [[]])], + [am_cv_proto_iconv_arg1=""], + [am_cv_proto_iconv_arg1="const"]) + am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"]) + am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` + AC_MSG_RESULT([ + $am_cv_proto_iconv]) + AC_DEFINE_UNQUOTED([ICONV_CONST], [$am_cv_proto_iconv_arg1], + [Define as const if the declaration of iconv() needs const.]) + dnl Also substitute ICONV_CONST in the gnulib generated . + m4_ifdef([gl_ICONV_H_DEFAULTS], + [AC_REQUIRE([gl_ICONV_H_DEFAULTS]) + if test -n "$am_cv_proto_iconv_arg1"; then + ICONV_CONST="const" + fi + ]) + fi +]) diff --git a/dependencies/libarchive-3.4.2/build/autoconf/install-sh b/dependencies/libarchive-3.4.2/build/autoconf/install-sh new file mode 100755 index 0000000..59990a1 --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/autoconf/install-sh @@ -0,0 +1,508 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2014-09-12.12; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# 'make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +tab=' ' +nl=' +' +IFS=" $tab$nl" + +# Set DOITPROG to "echo" to test this script. + +doit=${DOITPROG-} +doit_exec=${doit:-exec} + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +is_target_a_directory=possibly + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) is_target_a_directory=never;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi +fi + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + dstdir=`dirname "$dst"` + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + # $RANDOM is not portable (e.g. dash); use it when possible to + # lower collision chance + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 + + # As "mkdir -p" follows symlinks and we work in /tmp possibly; so + # create the $tmpdir first (and fail if unsuccessful) to make sure + # that nobody tries to guess the $tmpdir name. + if (umask $mkdir_umask && + $mkdirprog $mkdir_mode "$tmpdir" && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + test_tmpdir="$tmpdir/a" + ls_ld_tmpdir=`ls -ld "$test_tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + oIFS=$IFS + IFS=/ + set -f + set fnord $dstdir + shift + set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + set +f && + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/dependencies/libarchive-3.4.2/build/autoconf/la_uid_t.m4 b/dependencies/libarchive-3.4.2/build/autoconf/la_uid_t.m4 new file mode 100644 index 0000000..31eef5e --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/autoconf/la_uid_t.m4 @@ -0,0 +1,20 @@ +# la_TYPE_UID_T +# ------------- +AC_DEFUN([la_TYPE_UID_T], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_CACHE_CHECK(for uid_t in sys/types.h, la_cv_type_uid_t, +[AC_EGREP_HEADER(uid_t, sys/types.h, + la_cv_type_uid_t=yes, la_cv_type_uid_t=no)]) +if test $la_cv_type_uid_t = no; then + case $host in + *mingw*) def_uid_t=short ;; + *) def_uid_t=int ;; + esac + AC_DEFINE_UNQUOTED(uid_t, [$def_uid_t], + [Define to match typeof st_uid field of struct stat if doesn't define.]) + AC_DEFINE_UNQUOTED(gid_t, [$def_uid_t], + [Define to match typeof st_gid field of struct stat if doesn't define.]) +fi +]) +AU_ALIAS([AC_TYPE_UID_T], [la_TYPE_UID_T]) + diff --git a/dependencies/libarchive-3.4.2/build/autoconf/lib-ld.m4 b/dependencies/libarchive-3.4.2/build/autoconf/lib-ld.m4 new file mode 100644 index 0000000..ae003f7 --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/autoconf/lib-ld.m4 @@ -0,0 +1,109 @@ +# lib-ld.m4 serial 5 (gettext-0.18.2) +dnl Copyright (C) 1996-2003, 2009-2011 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Subroutines of libtool.m4, +dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision +dnl with libtool.m4. + +dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no. +AC_DEFUN([AC_LIB_PROG_LD_GNU], +[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], [acl_cv_prog_gnu_ld], +[# I'd rather use --version here, but apparently some GNU ld's only accept -v. +case `$LD -v 2>&1 /dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } +fi +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by GCC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]* | [A-Za-z]:[\\/]*)] + [re_direlt='/[^/][^/]*/\.\./'] + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL([acl_cv_path_LD], +[if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + acl_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in + *GNU* | *'with BFD'*) + test "$with_gnu_ld" != no && break ;; + *) + test "$with_gnu_ld" != yes && break ;; + esac + fi + done + IFS="$ac_save_ifs" +else + acl_cv_path_LD="$LD" # Let the user override the test with a path. +fi]) +LD="$acl_cv_path_LD" +if test -n "$LD"; then + AC_MSG_RESULT([$LD]) +else + AC_MSG_RESULT([no]) +fi +test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) +AC_LIB_PROG_LD_GNU +]) diff --git a/dependencies/libarchive-3.4.2/build/autoconf/lib-link.m4 b/dependencies/libarchive-3.4.2/build/autoconf/lib-link.m4 new file mode 100644 index 0000000..e7c9ba9 --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/autoconf/lib-link.m4 @@ -0,0 +1,777 @@ +# lib-link.m4 serial 26 (gettext-0.18.2) +dnl Copyright (C) 2001-2011 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_PREREQ([2.54]) + +dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and +dnl the libraries corresponding to explicit and implicit dependencies. +dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and +dnl augments the CPPFLAGS variable. +dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname +dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem. +AC_DEFUN([AC_LIB_LINKFLAGS], +[ + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + pushdef([Name],[m4_translit([$1],[./+-], [____])]) + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [ + AC_LIB_LINKFLAGS_BODY([$1], [$2]) + ac_cv_lib[]Name[]_libs="$LIB[]NAME" + ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME" + ac_cv_lib[]Name[]_cppflags="$INC[]NAME" + ac_cv_lib[]Name[]_prefix="$LIB[]NAME[]_PREFIX" + ]) + LIB[]NAME="$ac_cv_lib[]Name[]_libs" + LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs" + INC[]NAME="$ac_cv_lib[]Name[]_cppflags" + LIB[]NAME[]_PREFIX="$ac_cv_lib[]Name[]_prefix" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) + AC_SUBST([LIB]NAME) + AC_SUBST([LTLIB]NAME) + AC_SUBST([LIB]NAME[_PREFIX]) + dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the + dnl results of this search when this library appears as a dependency. + HAVE_LIB[]NAME=yes + popdef([NAME]) + popdef([Name]) +]) + +dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode, [missing-message]) +dnl searches for libname and the libraries corresponding to explicit and +dnl implicit dependencies, together with the specified include files and +dnl the ability to compile and link the specified testcode. The missing-message +dnl defaults to 'no' and may contain additional hints for the user. +dnl If found, it sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} +dnl and LTLIB${NAME} variables and augments the CPPFLAGS variable, and +dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs +dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty. +dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname +dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem. +AC_DEFUN([AC_LIB_HAVE_LINKFLAGS], +[ + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + pushdef([Name],[m4_translit([$1],[./+-], [____])]) + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + + dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME + dnl accordingly. + AC_LIB_LINKFLAGS_BODY([$1], [$2]) + + dnl Add $INC[]NAME to CPPFLAGS before performing the following checks, + dnl because if the user has installed lib[]Name and not disabled its use + dnl via --without-lib[]Name-prefix, he wants to use it. + ac_save_CPPFLAGS="$CPPFLAGS" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) + + AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [ + ac_save_LIBS="$LIBS" + dnl If $LIB[]NAME contains some -l options, add it to the end of LIBS, + dnl because these -l options might require -L options that are present in + dnl LIBS. -l options benefit only from the -L options listed before it. + dnl Otherwise, add it to the front of LIBS, because it may be a static + dnl library that depends on another static library that is present in LIBS. + dnl Static libraries benefit only from the static libraries listed after + dnl it. + case " $LIB[]NAME" in + *" -l"*) LIBS="$LIBS $LIB[]NAME" ;; + *) LIBS="$LIB[]NAME $LIBS" ;; + esac + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[$3]], [[$4]])], + [ac_cv_lib[]Name=yes], + [ac_cv_lib[]Name='m4_if([$5], [], [no], [[$5]])']) + LIBS="$ac_save_LIBS" + ]) + if test "$ac_cv_lib[]Name" = yes; then + HAVE_LIB[]NAME=yes + AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the lib][$1 library.]) + AC_MSG_CHECKING([how to link with lib[]$1]) + AC_MSG_RESULT([$LIB[]NAME]) + else + HAVE_LIB[]NAME=no + dnl If $LIB[]NAME didn't lead to a usable library, we don't need + dnl $INC[]NAME either. + CPPFLAGS="$ac_save_CPPFLAGS" + LIB[]NAME= + LTLIB[]NAME= + LIB[]NAME[]_PREFIX= + fi + AC_SUBST([HAVE_LIB]NAME) + AC_SUBST([LIB]NAME) + AC_SUBST([LTLIB]NAME) + AC_SUBST([LIB]NAME[_PREFIX]) + popdef([NAME]) + popdef([Name]) +]) + +dnl Determine the platform dependent parameters needed to use rpath: +dnl acl_libext, +dnl acl_shlibext, +dnl acl_libname_spec, +dnl acl_library_names_spec, +dnl acl_hardcode_libdir_flag_spec, +dnl acl_hardcode_libdir_separator, +dnl acl_hardcode_direct, +dnl acl_hardcode_minus_L. +AC_DEFUN([AC_LIB_RPATH], +[ + dnl Tell automake >= 1.10 to complain if config.rpath is missing. + m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])]) + AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS + AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld + AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host + AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir + AC_CACHE_CHECK([for shared library run path origin], [acl_cv_rpath], [ + CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ + ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh + . ./conftest.sh + rm -f ./conftest.sh + acl_cv_rpath=done + ]) + wl="$acl_cv_wl" + acl_libext="$acl_cv_libext" + acl_shlibext="$acl_cv_shlibext" + acl_libname_spec="$acl_cv_libname_spec" + acl_library_names_spec="$acl_cv_library_names_spec" + acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" + acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" + acl_hardcode_direct="$acl_cv_hardcode_direct" + acl_hardcode_minus_L="$acl_cv_hardcode_minus_L" + dnl Determine whether the user wants rpath handling at all. + AC_ARG_ENABLE([rpath], + [ --disable-rpath do not hardcode runtime library paths], + :, enable_rpath=yes) +]) + +dnl AC_LIB_FROMPACKAGE(name, package) +dnl declares that libname comes from the given package. The configure file +dnl will then not have a --with-libname-prefix option but a +dnl --with-package-prefix option. Several libraries can come from the same +dnl package. This declaration must occur before an AC_LIB_LINKFLAGS or similar +dnl macro call that searches for libname. +AC_DEFUN([AC_LIB_FROMPACKAGE], +[ + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + define([acl_frompackage_]NAME, [$2]) + popdef([NAME]) + pushdef([PACK],[$2]) + pushdef([PACKUP],[m4_translit(PACK,[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + define([acl_libsinpackage_]PACKUP, + m4_ifdef([acl_libsinpackage_]PACKUP, [m4_defn([acl_libsinpackage_]PACKUP)[, ]],)[lib$1]) + popdef([PACKUP]) + popdef([PACK]) +]) + +dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and +dnl the libraries corresponding to explicit and implicit dependencies. +dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables. +dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found +dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem. +AC_DEFUN([AC_LIB_LINKFLAGS_BODY], +[ + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + pushdef([PACK],[m4_ifdef([acl_frompackage_]NAME, [acl_frompackage_]NAME, lib[$1])]) + pushdef([PACKUP],[m4_translit(PACK,[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + pushdef([PACKLIBS],[m4_ifdef([acl_frompackage_]NAME, [acl_libsinpackage_]PACKUP, lib[$1])]) + dnl Autoconf >= 2.61 supports dots in --with options. + pushdef([P_A_C_K],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[m4_translit(PACK,[.],[_])],PACK)]) + dnl By default, look in $includedir and $libdir. + use_additional=yes + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + AC_ARG_WITH(P_A_C_K[-prefix], +[[ --with-]]P_A_C_K[[-prefix[=DIR] search for ]PACKLIBS[ in DIR/include and DIR/lib + --without-]]P_A_C_K[[-prefix don't search for ]PACKLIBS[ in includedir and libdir]], +[ + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + if test "$acl_libdirstem2" != "$acl_libdirstem" \ + && ! test -d "$withval/$acl_libdirstem"; then + additional_libdir="$withval/$acl_libdirstem2" + fi + fi + fi +]) + dnl Search the library and its dependencies in $additional_libdir and + dnl $LDFLAGS. Using breadth-first-seach. + LIB[]NAME= + LTLIB[]NAME= + INC[]NAME= + LIB[]NAME[]_PREFIX= + dnl HAVE_LIB${NAME} is an indicator that LIB${NAME}, LTLIB${NAME} have been + dnl computed. So it has to be reset here. + HAVE_LIB[]NAME= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='$1 $2' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + dnl See if it was already located by an earlier AC_LIB_LINKFLAGS + dnl or AC_LIB_HAVE_LINKFLAGS call. + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./+-|ABCDEFGHIJKLMNOPQRSTUVWXYZ____|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value" + else + dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined + dnl that this library doesn't exist. So just drop it. + : + fi + else + dnl Search the library lib$name in $additional_libdir and $LDFLAGS + dnl and the already constructed $LIBNAME/$LTLIBNAME. + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + dnl The same code as in the loop below: + dnl First look for a shared library. + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + dnl Then look for a static library. + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + dnl First look for a shared library. + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + dnl Then look for a static library. + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + dnl Found the library. + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + dnl Linking with a shared library. We attempt to hardcode its + dnl directory into the executable's runpath, unless it's the + dnl standard /usr/lib. + if test "$enable_rpath" = no \ + || test "X$found_dir" = "X/usr/$acl_libdirstem" \ + || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then + dnl No hardcoding is needed. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + dnl Use an explicit option to hardcode DIR into the resulting + dnl binary. + dnl Potentially add DIR to ltrpathdirs. + dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + dnl The hardcoding into $LIBNAME is system dependent. + if test "$acl_hardcode_direct" = yes; then + dnl Using DIR/libNAME.so during linking hardcodes DIR into the + dnl resulting binary. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + dnl Use an explicit option to hardcode DIR into the resulting + dnl binary. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + dnl Potentially add DIR to rpathdirs. + dnl The rpathdirs will be appended to $LIBNAME at the end. + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + dnl Rely on "-L$found_dir". + dnl But don't add it if it's already contained in the LDFLAGS + dnl or the already constructed $LIBNAME + haveit= + for x in $LDFLAGS $LIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + dnl FIXME: Not sure whether we should use + dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" + dnl here. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + dnl We cannot use $acl_hardcode_runpath_var and LD_RUN_PATH + dnl here, because this doesn't fit in flags passed to the + dnl compiler. So give up. No hardcoding. This affects only + dnl very old systems. + dnl FIXME: Not sure whether we should use + dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" + dnl here. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + dnl Linking with a static library. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a" + else + dnl We shouldn't come here, but anyway it's good to have a + dnl fallback. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name" + fi + fi + dnl Assume the include files are nearby. + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + if test "$name" = '$1'; then + LIB[]NAME[]_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + */$acl_libdirstem2 | */$acl_libdirstem2/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'` + if test "$name" = '$1'; then + LIB[]NAME[]_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + dnl Potentially add $additional_includedir to $INCNAME. + dnl But don't add it + dnl 1. if it's the standard /usr/include, + dnl 2. if it's /usr/local/include and we are using GCC on Linux, + dnl 3. if it's already present in $CPPFLAGS or the already + dnl constructed $INCNAME, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INC[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + dnl Really add $additional_includedir to $INCNAME. + INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + dnl Look for dependencies. + if test -n "$found_la"; then + dnl Read the .la file. It defines the variables + dnl dlname, library_names, old_library, dependency_libs, current, + dnl age, revision, installed, dlopen, dlpreopen, libdir. + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + dnl We use only dependency_libs. + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME. + dnl But don't add it + dnl 1. if it's the standard /usr/lib, + dnl 2. if it's /usr/local/lib and we are using GCC on Linux, + dnl 3. if it's already present in $LDFLAGS or the already + dnl constructed $LIBNAME, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \ + && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \ + || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LIBNAME. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LTLIBNAME. + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + dnl Potentially add DIR to rpathdirs. + dnl The rpathdirs will be appended to $LIBNAME at the end. + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + dnl Potentially add DIR to ltrpathdirs. + dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + dnl Handle this in the next round. + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + dnl Handle this in the next round. Throw away the .la's + dnl directory; it is already contained in a preceding -L + dnl option. + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + dnl Most likely an immediate library name. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep" + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep" + ;; + esac + done + fi + else + dnl Didn't find the library; assume it is in the system directories + dnl known to the linker and runtime loader. (All the system + dnl directories known to the linker should also be known to the + dnl runtime loader, otherwise the system is severely misconfigured.) + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + dnl Weird platform: only the last -rpath option counts, the user must + dnl pass all path elements in one option. We can arrange that for a + dnl single library, but not when more than one $LIBNAMEs are used. + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl. + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" + else + dnl The -rpath options are cumulative. + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + dnl When using libtool, the option that works for both libraries and + dnl executables is -R. The -R options are cumulative. + for found_dir in $ltrpathdirs; do + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir" + done + fi + popdef([P_A_C_K]) + popdef([PACKLIBS]) + popdef([PACKUP]) + popdef([PACK]) + popdef([NAME]) +]) + +dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR, +dnl unless already present in VAR. +dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes +dnl contains two or three consecutive elements that belong together. +AC_DEFUN([AC_LIB_APPENDTOVAR], +[ + for element in [$2]; do + haveit= + for x in $[$1]; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + [$1]="${[$1]}${[$1]:+ }$element" + fi + done +]) + +dnl For those cases where a variable contains several -L and -l options +dnl referring to unknown libraries and directories, this macro determines the +dnl necessary additional linker options for the runtime path. +dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL]) +dnl sets LDADDVAR to linker options needed together with LIBSVALUE. +dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed, +dnl otherwise linking without libtool is assumed. +AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS], +[ + AC_REQUIRE([AC_LIB_RPATH]) + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + $1= + if test "$enable_rpath" != no; then + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + dnl Use an explicit option to hardcode directories into the resulting + dnl binary. + rpathdirs= + next= + for opt in $2; do + if test -n "$next"; then + dir="$next" + dnl No need to hardcode the standard /usr/lib. + if test "X$dir" != "X/usr/$acl_libdirstem" \ + && test "X$dir" != "X/usr/$acl_libdirstem2"; then + rpathdirs="$rpathdirs $dir" + fi + next= + else + case $opt in + -L) next=yes ;; + -L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'` + dnl No need to hardcode the standard /usr/lib. + if test "X$dir" != "X/usr/$acl_libdirstem" \ + && test "X$dir" != "X/usr/$acl_libdirstem2"; then + rpathdirs="$rpathdirs $dir" + fi + next= ;; + *) next= ;; + esac + fi + done + if test "X$rpathdirs" != "X"; then + if test -n ""$3""; then + dnl libtool is used for linking. Use -R options. + for dir in $rpathdirs; do + $1="${$1}${$1:+ }-R$dir" + done + else + dnl The linker is used for linking directly. + if test -n "$acl_hardcode_libdir_separator"; then + dnl Weird platform: only the last -rpath option counts, the user + dnl must pass all path elements in one option. + alldirs= + for dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + $1="$flag" + else + dnl The -rpath options are cumulative. + for dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + $1="${$1}${$1:+ }$flag" + done + fi + fi + fi + fi + fi + AC_SUBST([$1]) +]) diff --git a/dependencies/libarchive-3.4.2/build/autoconf/lib-prefix.m4 b/dependencies/libarchive-3.4.2/build/autoconf/lib-prefix.m4 new file mode 100644 index 0000000..7e5f0bd --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/autoconf/lib-prefix.m4 @@ -0,0 +1,224 @@ +# lib-prefix.m4 serial 7 (gettext-0.18) +dnl Copyright (C) 2001-2005, 2008-2011 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and +dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't +dnl require excessive bracketing. +ifdef([AC_HELP_STRING], +[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])], +[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])]) + +dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed +dnl to access previously installed libraries. The basic assumption is that +dnl a user will want packages to use other packages he previously installed +dnl with the same --prefix option. +dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate +dnl libraries, but is otherwise very convenient. +AC_DEFUN([AC_LIB_PREFIX], +[ + AC_BEFORE([$0], [AC_LIB_LINKFLAGS]) + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + dnl By default, look in $includedir and $libdir. + use_additional=yes + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + AC_LIB_ARG_WITH([lib-prefix], +[ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib + --without-lib-prefix don't search for libraries in includedir and libdir], +[ + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + fi + fi +]) + if test $use_additional = yes; then + dnl Potentially add $additional_includedir to $CPPFLAGS. + dnl But don't add it + dnl 1. if it's the standard /usr/include, + dnl 2. if it's already present in $CPPFLAGS, + dnl 3. if it's /usr/local/include and we are using GCC on Linux, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + for x in $CPPFLAGS; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + dnl Really add $additional_includedir to $CPPFLAGS. + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir" + fi + fi + fi + fi + dnl Potentially add $additional_libdir to $LDFLAGS. + dnl But don't add it + dnl 1. if it's the standard /usr/lib, + dnl 2. if it's already present in $LDFLAGS, + dnl 3. if it's /usr/local/lib and we are using GCC on Linux, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then + haveit= + for x in $LDFLAGS; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then + if test -n "$GCC"; then + case $host_os in + linux*) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LDFLAGS. + LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir" + fi + fi + fi + fi + fi +]) + +dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix, +dnl acl_final_exec_prefix, containing the values to which $prefix and +dnl $exec_prefix will expand at the end of the configure script. +AC_DEFUN([AC_LIB_PREPARE_PREFIX], +[ + dnl Unfortunately, prefix and exec_prefix get only finally determined + dnl at the end of configure. + if test "X$prefix" = "XNONE"; then + acl_final_prefix="$ac_default_prefix" + else + acl_final_prefix="$prefix" + fi + if test "X$exec_prefix" = "XNONE"; then + acl_final_exec_prefix='${prefix}' + else + acl_final_exec_prefix="$exec_prefix" + fi + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" + prefix="$acl_save_prefix" +]) + +dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the +dnl variables prefix and exec_prefix bound to the values they will have +dnl at the end of the configure script. +AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX], +[ + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + $1 + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" +]) + +dnl AC_LIB_PREPARE_MULTILIB creates +dnl - a variable acl_libdirstem, containing the basename of the libdir, either +dnl "lib" or "lib64" or "lib/64", +dnl - a variable acl_libdirstem2, as a secondary possible value for +dnl acl_libdirstem, either the same as acl_libdirstem or "lib/sparcv9" or +dnl "lib/amd64". +AC_DEFUN([AC_LIB_PREPARE_MULTILIB], +[ + dnl There is no formal standard regarding lib and lib64. + dnl On glibc systems, the current practice is that on a system supporting + dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under + dnl $prefix/lib64 and 32-bit libraries go under $prefix/lib. We determine + dnl the compiler's default mode by looking at the compiler's library search + dnl path. If at least one of its elements ends in /lib64 or points to a + dnl directory whose absolute pathname ends in /lib64, we assume a 64-bit ABI. + dnl Otherwise we use the default, namely "lib". + dnl On Solaris systems, the current practice is that on a system supporting + dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under + dnl $prefix/lib/64 (which is a symlink to either $prefix/lib/sparcv9 or + dnl $prefix/lib/amd64) and 32-bit libraries go under $prefix/lib. + AC_REQUIRE([AC_CANONICAL_HOST]) + acl_libdirstem=lib + acl_libdirstem2= + case "$host_os" in + solaris*) + dnl See Solaris 10 Software Developer Collection > Solaris 64-bit Developer's Guide > The Development Environment + dnl . + dnl "Portable Makefiles should refer to any library directories using the 64 symbolic link." + dnl But we want to recognize the sparcv9 or amd64 subdirectory also if the + dnl symlink is missing, so we set acl_libdirstem2 too. + AC_CACHE_CHECK([for 64-bit host], [gl_cv_solaris_64bit], + [AC_EGREP_CPP([sixtyfour bits], [ +#ifdef _LP64 +sixtyfour bits +#endif + ], [gl_cv_solaris_64bit=yes], [gl_cv_solaris_64bit=no]) + ]) + if test $gl_cv_solaris_64bit = yes; then + acl_libdirstem=lib/64 + case "$host_cpu" in + sparc*) acl_libdirstem2=lib/sparcv9 ;; + i*86 | x86_64) acl_libdirstem2=lib/amd64 ;; + esac + fi + ;; + *) + searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` + if test -n "$searchpath"; then + acl_save_IFS="${IFS= }"; IFS=":" + for searchdir in $searchpath; do + if test -d "$searchdir"; then + case "$searchdir" in + */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; + */../ | */.. ) + # Better ignore directories of this form. They are misleading. + ;; + *) searchdir=`cd "$searchdir" && pwd` + case "$searchdir" in + */lib64 ) acl_libdirstem=lib64 ;; + esac ;; + esac + fi + done + IFS="$acl_save_IFS" + fi + ;; + esac + test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem" +]) diff --git a/dependencies/libarchive-3.4.2/build/autoconf/ltmain.sh b/dependencies/libarchive-3.4.2/build/autoconf/ltmain.sh new file mode 100644 index 0000000..a736cf9 --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/autoconf/ltmain.sh @@ -0,0 +1,11156 @@ +#! /bin/sh +## DO NOT EDIT - This file generated from ./build-aux/ltmain.in +## by inline-source v2014-01-03.01 + +# libtool (GNU libtool) 2.4.6 +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +PROGRAM=libtool +PACKAGE=libtool +VERSION="2.4.6 Debian-2.4.6-2" +package_revision=2.4.6 + + +## ------ ## +## Usage. ## +## ------ ## + +# Run './libtool --help' for help with using this script from the +# command line. + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# After configure completes, it has a better idea of some of the +# shell tools we need than the defaults used by the functions shared +# with bootstrap, so set those here where they can still be over- +# ridden by the user, but otherwise take precedence. + +: ${AUTOCONF="autoconf"} +: ${AUTOMAKE="automake"} + + +## -------------------------- ## +## Source external libraries. ## +## -------------------------- ## + +# Much of our low-level functionality needs to be sourced from external +# libraries, which are installed to $pkgauxdir. + +# Set a version string for this script. +scriptversion=2015-01-20.17; # UTC + +# General shell script boiler plate, and helper functions. +# Written by Gary V. Vaughan, 2004 + +# Copyright (C) 2004-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# As a special exception to the GNU General Public License, if you distribute +# this file as part of a program or library that is built using GNU Libtool, +# you may include this file under the same distribution terms that you use +# for the rest of that program. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNES FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# Evaluate this file near the top of your script to gain access to +# the functions and variables defined here: +# +# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh +# +# If you need to override any of the default environment variable +# settings, do that before evaluating this file. + + +## -------------------- ## +## Shell normalisation. ## +## -------------------- ## + +# Some shells need a little help to be as Bourne compatible as possible. +# Before doing anything else, make sure all that help has been provided! + +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac +fi + +# NLS nuisances: We save the old values in case they are required later. +_G_user_locale= +_G_safe_locale= +for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test set = \"\${$_G_var+set}\"; then + save_$_G_var=\$$_G_var + $_G_var=C + export $_G_var + _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" + _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" + fi" +done + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Make sure IFS has a sensible default +sp=' ' +nl=' +' +IFS="$sp $nl" + +# There are apparently some retarded systems that use ';' as a PATH separator! +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + + +## ------------------------- ## +## Locate command utilities. ## +## ------------------------- ## + + +# func_executable_p FILE +# ---------------------- +# Check that FILE is an executable regular file. +func_executable_p () +{ + test -f "$1" && test -x "$1" +} + + +# func_path_progs PROGS_LIST CHECK_FUNC [PATH] +# -------------------------------------------- +# Search for either a program that responds to --version with output +# containing "GNU", or else returned by CHECK_FUNC otherwise, by +# trying all the directories in PATH with each of the elements of +# PROGS_LIST. +# +# CHECK_FUNC should accept the path to a candidate program, and +# set $func_check_prog_result if it truncates its output less than +# $_G_path_prog_max characters. +func_path_progs () +{ + _G_progs_list=$1 + _G_check_func=$2 + _G_PATH=${3-"$PATH"} + + _G_path_prog_max=0 + _G_path_prog_found=false + _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} + for _G_dir in $_G_PATH; do + IFS=$_G_save_IFS + test -z "$_G_dir" && _G_dir=. + for _G_prog_name in $_G_progs_list; do + for _exeext in '' .EXE; do + _G_path_prog=$_G_dir/$_G_prog_name$_exeext + func_executable_p "$_G_path_prog" || continue + case `"$_G_path_prog" --version 2>&1` in + *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; + *) $_G_check_func $_G_path_prog + func_path_progs_result=$func_check_prog_result + ;; + esac + $_G_path_prog_found && break 3 + done + done + done + IFS=$_G_save_IFS + test -z "$func_path_progs_result" && { + echo "no acceptable sed could be found in \$PATH" >&2 + exit 1 + } +} + + +# We want to be able to use the functions in this file before configure +# has figured out where the best binaries are kept, which means we have +# to search for them ourselves - except when the results are already set +# where we skip the searches. + +# Unless the user overrides by setting SED, search the path for either GNU +# sed, or the sed that truncates its output the least. +test -z "$SED" && { + _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for _G_i in 1 2 3 4 5 6 7; do + _G_sed_script=$_G_sed_script$nl$_G_sed_script + done + echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed + _G_sed_script= + + func_check_prog_sed () + { + _G_path_prog=$1 + + _G_count=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo '' >> conftest.nl + "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin + rm -f conftest.sed + SED=$func_path_progs_result +} + + +# Unless the user overrides by setting GREP, search the path for either GNU +# grep, or the grep that truncates its output the least. +test -z "$GREP" && { + func_check_prog_grep () + { + _G_path_prog=$1 + + _G_count=0 + _G_path_prog_max=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo 'GREP' >> conftest.nl + "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin + GREP=$func_path_progs_result +} + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# All uppercase variable names are used for environment variables. These +# variables can be overridden by the user before calling a script that +# uses them if a suitable command of that name is not already available +# in the command search PATH. + +: ${CP="cp -f"} +: ${ECHO="printf %s\n"} +: ${EGREP="$GREP -E"} +: ${FGREP="$GREP -F"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} + + +## -------------------- ## +## Useful sed snippets. ## +## -------------------- ## + +sed_dirname='s|/[^/]*$||' +sed_basename='s|^.*/||' + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Same as above, but do not quote variable references. +sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' + +# Sed substitution that converts a w32 file name or path +# that contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-'\' parameter expansions in output of sed_double_quote_subst that +# were '\'-ed in input to the same. If an odd number of '\' preceded a +# '$' in input to sed_double_quote_subst, that '$' was protected from +# expansion. Since each input '\' is now two '\'s, look for any number +# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. +_G_bs='\\' +_G_bs2='\\\\' +_G_bs4='\\\\\\\\' +_G_dollar='\$' +sed_double_backslash="\ + s/$_G_bs4/&\\ +/g + s/^$_G_bs2$_G_dollar/$_G_bs&/ + s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g + s/\n//g" + + +## ----------------- ## +## Global variables. ## +## ----------------- ## + +# Except for the global variables explicitly listed below, the following +# functions in the '^func_' namespace, and the '^require_' namespace +# variables initialised in the 'Resource management' section, sourcing +# this file will not pollute your global namespace with anything +# else. There's no portable way to scope variables in Bourne shell +# though, so actually running these functions will sometimes place +# results into a variable named after the function, and often use +# temporary variables in the '^_G_' namespace. If you are careful to +# avoid using those namespaces casually in your sourcing script, things +# should continue to work as you expect. And, of course, you can freely +# overwrite any of the functions or variables defined here before +# calling anything to customize them. + +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +# Allow overriding, eg assuming that you follow the convention of +# putting '$debug_cmd' at the start of all your functions, you can get +# bash to show function call trace with: +# +# debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name +debug_cmd=${debug_cmd-":"} +exit_cmd=: + +# By convention, finish your script with: +# +# exit $exit_status +# +# so that you can set exit_status to non-zero if you want to indicate +# something went wrong during execution without actually bailing out at +# the point of failure. +exit_status=$EXIT_SUCCESS + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath=$0 + +# The name of this program. +progname=`$ECHO "$progpath" |$SED "$sed_basename"` + +# Make sure we have an absolute progpath for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` + progdir=`cd "$progdir" && pwd` + progpath=$progdir/$progname + ;; + *) + _G_IFS=$IFS + IFS=${PATH_SEPARATOR-:} + for progdir in $PATH; do + IFS=$_G_IFS + test -x "$progdir/$progname" && break + done + IFS=$_G_IFS + test -n "$progdir" || progdir=`pwd` + progpath=$progdir/$progname + ;; +esac + + +## ----------------- ## +## Standard options. ## +## ----------------- ## + +# The following options affect the operation of the functions defined +# below, and should be set appropriately depending on run-time para- +# meters passed on the command line. + +opt_dry_run=false +opt_quiet=false +opt_verbose=false + +# Categories 'all' and 'none' are always available. Append any others +# you will pass as the first argument to func_warning from your own +# code. +warning_categories= + +# By default, display warnings according to 'opt_warning_types'. Set +# 'warning_func' to ':' to elide all warnings, or func_fatal_error to +# treat the next displayed warning as a fatal error. +warning_func=func_warn_and_continue + +# Set to 'all' to display all warnings, 'none' to suppress all +# warnings, or a space delimited list of some subset of +# 'warning_categories' to display only the listed warnings. +opt_warning_types=all + + +## -------------------- ## +## Resource management. ## +## -------------------- ## + +# This section contains definitions for functions that each ensure a +# particular resource (a file, or a non-empty configuration variable for +# example) is available, and if appropriate to extract default values +# from pertinent package files. Call them using their associated +# 'require_*' variable to ensure that they are executed, at most, once. +# +# It's entirely deliberate that calling these functions can set +# variables that don't obey the namespace limitations obeyed by the rest +# of this file, in order that that they be as useful as possible to +# callers. + + +# require_term_colors +# ------------------- +# Allow display of bold text on terminals that support it. +require_term_colors=func_require_term_colors +func_require_term_colors () +{ + $debug_cmd + + test -t 1 && { + # COLORTERM and USE_ANSI_COLORS environment variables take + # precedence, because most terminfo databases neglect to describe + # whether color sequences are supported. + test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} + + if test 1 = "$USE_ANSI_COLORS"; then + # Standard ANSI escape sequences + tc_reset='' + tc_bold=''; tc_standout='' + tc_red=''; tc_green='' + tc_blue=''; tc_cyan='' + else + # Otherwise trust the terminfo database after all. + test -n "`tput sgr0 2>/dev/null`" && { + tc_reset=`tput sgr0` + test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` + tc_standout=$tc_bold + test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` + test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` + test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` + test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` + test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` + } + fi + } + + require_term_colors=: +} + + +## ----------------- ## +## Function library. ## +## ----------------- ## + +# This section contains a variety of useful functions to call in your +# scripts. Take note of the portable wrappers for features provided by +# some modern shells, which will fall back to slower equivalents on +# less featureful shells. + + +# func_append VAR VALUE +# --------------------- +# Append VALUE onto the existing contents of VAR. + + # We should try to minimise forks, especially on Windows where they are + # unreasonably slow, so skip the feature probes when bash or zsh are + # being used: + if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then + : ${_G_HAVE_ARITH_OP="yes"} + : ${_G_HAVE_XSI_OPS="yes"} + # The += operator was introduced in bash 3.1 + case $BASH_VERSION in + [12].* | 3.0 | 3.0*) ;; + *) + : ${_G_HAVE_PLUSEQ_OP="yes"} + ;; + esac + fi + + # _G_HAVE_PLUSEQ_OP + # Can be empty, in which case the shell is probed, "yes" if += is + # useable or anything else if it does not work. + test -z "$_G_HAVE_PLUSEQ_OP" \ + && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ + && _G_HAVE_PLUSEQ_OP=yes + +if test yes = "$_G_HAVE_PLUSEQ_OP" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_append () + { + $debug_cmd + + eval "$1+=\$2" + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_append () + { + $debug_cmd + + eval "$1=\$$1\$2" + } +fi + + +# func_append_quoted VAR VALUE +# ---------------------------- +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +if test yes = "$_G_HAVE_PLUSEQ_OP"; then + eval 'func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1+=\\ \$func_quote_for_eval_result" + }' +else + func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1=\$$1\\ \$func_quote_for_eval_result" + } +fi + + +# func_append_uniq VAR VALUE +# -------------------------- +# Append unique VALUE onto the existing contents of VAR, assuming +# entries are delimited by the first character of VALUE. For example: +# +# func_append_uniq options " --another-option option-argument" +# +# will only append to $options if " --another-option option-argument " +# is not already present somewhere in $options already (note spaces at +# each end implied by leading space in second argument). +func_append_uniq () +{ + $debug_cmd + + eval _G_current_value='`$ECHO $'$1'`' + _G_delim=`expr "$2" : '\(.\)'` + + case $_G_delim$_G_current_value$_G_delim in + *"$2$_G_delim"*) ;; + *) func_append "$@" ;; + esac +} + + +# func_arith TERM... +# ------------------ +# Set func_arith_result to the result of evaluating TERMs. + test -z "$_G_HAVE_ARITH_OP" \ + && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ + && _G_HAVE_ARITH_OP=yes + +if test yes = "$_G_HAVE_ARITH_OP"; then + eval 'func_arith () + { + $debug_cmd + + func_arith_result=$(( $* )) + }' +else + func_arith () + { + $debug_cmd + + func_arith_result=`expr "$@"` + } +fi + + +# func_basename FILE +# ------------------ +# Set func_basename_result to FILE with everything up to and including +# the last / stripped. +if test yes = "$_G_HAVE_XSI_OPS"; then + # If this shell supports suffix pattern removal, then use it to avoid + # forking. Hide the definitions single quotes in case the shell chokes + # on unsupported syntax... + _b='func_basename_result=${1##*/}' + _d='case $1 in + */*) func_dirname_result=${1%/*}$2 ;; + * ) func_dirname_result=$3 ;; + esac' + +else + # ...otherwise fall back to using sed. + _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' + _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` + if test "X$func_dirname_result" = "X$1"; then + func_dirname_result=$3 + else + func_append func_dirname_result "$2" + fi' +fi + +eval 'func_basename () +{ + $debug_cmd + + '"$_b"' +}' + + +# func_dirname FILE APPEND NONDIR_REPLACEMENT +# ------------------------------------------- +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +eval 'func_dirname () +{ + $debug_cmd + + '"$_d"' +}' + + +# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT +# -------------------------------------------------------- +# Perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# For efficiency, we do not delegate to the functions above but instead +# duplicate the functionality here. +eval 'func_dirname_and_basename () +{ + $debug_cmd + + '"$_b"' + '"$_d"' +}' + + +# func_echo ARG... +# ---------------- +# Echo program name prefixed message. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_echo_all ARG... +# -------------------- +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + + +# func_echo_infix_1 INFIX ARG... +# ------------------------------ +# Echo program name, followed by INFIX on the first line, with any +# additional lines not showing INFIX. +func_echo_infix_1 () +{ + $debug_cmd + + $require_term_colors + + _G_infix=$1; shift + _G_indent=$_G_infix + _G_prefix="$progname: $_G_infix: " + _G_message=$* + + # Strip color escape sequences before counting printable length + for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" + do + test -n "$_G_tc" && { + _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` + _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` + } + done + _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes + + func_echo_infix_1_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_infix_1_IFS + $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 + _G_prefix=$_G_indent + done + IFS=$func_echo_infix_1_IFS +} + + +# func_error ARG... +# ----------------- +# Echo program name prefixed message to standard error. +func_error () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 +} + + +# func_fatal_error ARG... +# ----------------------- +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + $debug_cmd + + func_error "$*" + exit $EXIT_FAILURE +} + + +# func_grep EXPRESSION FILENAME +# ----------------------------- +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $debug_cmd + + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_len STRING +# --------------- +# Set func_len_result to the length of STRING. STRING may not +# start with a hyphen. + test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_len () + { + $debug_cmd + + func_len_result=${#1} + }' +else + func_len () + { + $debug_cmd + + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` + } +fi + + +# func_mkdir_p DIRECTORY-PATH +# --------------------------- +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + $debug_cmd + + _G_directory_path=$1 + _G_dir_list= + + if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then + + # Protect directory names starting with '-' + case $_G_directory_path in + -*) _G_directory_path=./$_G_directory_path ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$_G_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + _G_dir_list=$_G_directory_path:$_G_dir_list + + # If the last portion added has no slash in it, the list is done + case $_G_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` + done + _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` + + func_mkdir_p_IFS=$IFS; IFS=: + for _G_dir in $_G_dir_list; do + IFS=$func_mkdir_p_IFS + # mkdir can fail with a 'File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$_G_dir" 2>/dev/null || : + done + IFS=$func_mkdir_p_IFS + + # Bail out if we (or some other process) failed to create a directory. + test -d "$_G_directory_path" || \ + func_fatal_error "Failed to create '$1'" + fi +} + + +# func_mktempdir [BASENAME] +# ------------------------- +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, BASENAME is the basename for that directory. +func_mktempdir () +{ + $debug_cmd + + _G_template=${TMPDIR-/tmp}/${1-$progname} + + if test : = "$opt_dry_run"; then + # Return a directory name, but don't create it in dry-run mode + _G_tmpdir=$_G_template-$$ + else + + # If mktemp works, use that first and foremost + _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` + + if test ! -d "$_G_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + _G_tmpdir=$_G_template-${RANDOM-0}$$ + + func_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$_G_tmpdir" + umask $func_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$_G_tmpdir" || \ + func_fatal_error "cannot create temporary directory '$_G_tmpdir'" + fi + + $ECHO "$_G_tmpdir" +} + + +# func_normal_abspath PATH +# ------------------------ +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +func_normal_abspath () +{ + $debug_cmd + + # These SED scripts presuppose an absolute path with a trailing slash. + _G_pathcar='s|^/\([^/]*\).*$|\1|' + _G_pathcdr='s|^/[^/]*||' + _G_removedotparts=':dotsl + s|/\./|/|g + t dotsl + s|/\.$|/|' + _G_collapseslashes='s|/\{1,\}|/|g' + _G_finalslash='s|/*$|/|' + + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` + while :; do + # Processed it all yet? + if test / = "$func_normal_abspath_tpath"; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result"; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + + +# func_notquiet ARG... +# -------------------- +# Echo program name prefixed message only when not in quiet mode. +func_notquiet () +{ + $debug_cmd + + $opt_quiet || func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + + +# func_relative_path SRCDIR DSTDIR +# -------------------------------- +# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. +func_relative_path () +{ + $debug_cmd + + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=$func_dirname_result + if test -z "$func_relative_path_tlibdir"; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test -n "$func_stripname_result"; then + func_append func_relative_path_result "/$func_stripname_result" + fi + + # Normalisation. If bindir is libdir, return '.' else relative path. + if test -n "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + fi + + test -n "$func_relative_path_result" || func_relative_path_result=. + + : +} + + +# func_quote_for_eval ARG... +# -------------------------- +# Aesthetically quote ARGs to be evaled later. +# This function returns two values: +# i) func_quote_for_eval_result +# double-quoted, suitable for a subsequent eval +# ii) func_quote_for_eval_unquoted_result +# has all characters that are still active within double +# quotes backslashified. +func_quote_for_eval () +{ + $debug_cmd + + func_quote_for_eval_unquoted_result= + func_quote_for_eval_result= + while test 0 -lt $#; do + case $1 in + *[\\\`\"\$]*) + _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; + *) + _G_unquoted_arg=$1 ;; + esac + if test -n "$func_quote_for_eval_unquoted_result"; then + func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" + else + func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" + fi + + case $_G_unquoted_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and variable expansion + # for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_quoted_arg=\"$_G_unquoted_arg\" + ;; + *) + _G_quoted_arg=$_G_unquoted_arg + ;; + esac + + if test -n "$func_quote_for_eval_result"; then + func_append func_quote_for_eval_result " $_G_quoted_arg" + else + func_append func_quote_for_eval_result "$_G_quoted_arg" + fi + shift + done +} + + +# func_quote_for_expand ARG +# ------------------------- +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + $debug_cmd + + case $1 in + *[\\\`\"]*) + _G_arg=`$ECHO "$1" | $SED \ + -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; + *) + _G_arg=$1 ;; + esac + + case $_G_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_arg=\"$_G_arg\" + ;; + esac + + func_quote_for_expand_result=$_G_arg +} + + +# func_stripname PREFIX SUFFIX NAME +# --------------------------------- +# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_stripname () + { + $debug_cmd + + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary variable first. + func_stripname_result=$3 + func_stripname_result=${func_stripname_result#"$1"} + func_stripname_result=${func_stripname_result%"$2"} + }' +else + func_stripname () + { + $debug_cmd + + case $2 in + .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; + *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; + esac + } +fi + + +# func_show_eval CMD [FAIL_EXP] +# ----------------------------- +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + func_quote_for_expand "$_G_cmd" + eval "func_notquiet $func_quote_for_expand_result" + + $opt_dry_run || { + eval "$_G_cmd" + _G_status=$? + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_show_eval_locale CMD [FAIL_EXP] +# ------------------------------------ +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + $opt_quiet || { + func_quote_for_expand "$_G_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + $opt_dry_run || { + eval "$_G_user_locale + $_G_cmd" + _G_status=$? + eval "$_G_safe_locale" + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_tr_sh +# ---------- +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + $debug_cmd + + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_verbose ARG... +# ------------------- +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $debug_cmd + + $opt_verbose && func_echo "$*" + + : +} + + +# func_warn_and_continue ARG... +# ----------------------------- +# Echo program name prefixed warning message to standard error. +func_warn_and_continue () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 +} + + +# func_warning CATEGORY ARG... +# ---------------------------- +# Echo program name prefixed warning message to standard error. Warning +# messages can be filtered according to CATEGORY, where this function +# elides messages where CATEGORY is not listed in the global variable +# 'opt_warning_types'. +func_warning () +{ + $debug_cmd + + # CATEGORY must be in the warning_categories list! + case " $warning_categories " in + *" $1 "*) ;; + *) func_internal_error "invalid warning category '$1'" ;; + esac + + _G_category=$1 + shift + + case " $opt_warning_types " in + *" $_G_category "*) $warning_func ${1+"$@"} ;; + esac +} + + +# func_sort_ver VER1 VER2 +# ----------------------- +# 'sort -V' is not generally available. +# Note this deviates from the version comparison in automake +# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a +# but this should suffice as we won't be specifying old +# version formats or redundant trailing .0 in bootstrap.conf. +# If we did want full compatibility then we should probably +# use m4_version_compare from autoconf. +func_sort_ver () +{ + $debug_cmd + + printf '%s\n%s\n' "$1" "$2" \ + | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n +} + +# func_lt_ver PREV CURR +# --------------------- +# Return true if PREV and CURR are in the correct order according to +# func_sort_ver, otherwise false. Use it like this: +# +# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." +func_lt_ver () +{ + $debug_cmd + + test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: +#! /bin/sh + +# Set a version string for this script. +scriptversion=2014-01-07.03; # UTC + +# A portable, pluggable option parser for Bourne shell. +# Written by Gary V. Vaughan, 2010 + +# Copyright (C) 2010-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# This file is a library for parsing options in your shell scripts along +# with assorted other useful supporting features that you can make use +# of too. +# +# For the simplest scripts you might need only: +# +# #!/bin/sh +# . relative/path/to/funclib.sh +# . relative/path/to/options-parser +# scriptversion=1.0 +# func_options ${1+"$@"} +# eval set dummy "$func_options_result"; shift +# ...rest of your script... +# +# In order for the '--version' option to work, you will need to have a +# suitably formatted comment like the one at the top of this file +# starting with '# Written by ' and ending with '# warranty; '. +# +# For '-h' and '--help' to work, you will also need a one line +# description of your script's purpose in a comment directly above the +# '# Written by ' line, like the one at the top of this file. +# +# The default options also support '--debug', which will turn on shell +# execution tracing (see the comment above debug_cmd below for another +# use), and '--verbose' and the func_verbose function to allow your script +# to display verbose messages only when your user has specified +# '--verbose'. +# +# After sourcing this file, you can plug processing for additional +# options by amending the variables from the 'Configuration' section +# below, and following the instructions in the 'Option parsing' +# section further down. + +## -------------- ## +## Configuration. ## +## -------------- ## + +# You should override these variables in your script after sourcing this +# file so that they reflect the customisations you have added to the +# option parser. + +# The usage line for option parsing errors and the start of '-h' and +# '--help' output messages. You can embed shell variables for delayed +# expansion at the time the message is displayed, but you will need to +# quote other shell meta-characters carefully to prevent them being +# expanded when the contents are evaled. +usage='$progpath [OPTION]...' + +# Short help message in response to '-h' and '--help'. Add to this or +# override it after sourcing this library to reflect the full set of +# options your script accepts. +usage_message="\ + --debug enable verbose shell tracing + -W, --warnings=CATEGORY + report the warnings falling in CATEGORY [all] + -v, --verbose verbosely report processing + --version print version information and exit + -h, --help print short or long help message and exit +" + +# Additional text appended to 'usage_message' in response to '--help'. +long_help_message=" +Warning categories include: + 'all' show all warnings + 'none' turn off all the warnings + 'error' warnings are treated as fatal errors" + +# Help message printed before fatal option parsing errors. +fatal_help="Try '\$progname --help' for more information." + + + +## ------------------------- ## +## Hook function management. ## +## ------------------------- ## + +# This section contains functions for adding, removing, and running hooks +# to the main code. A hook is just a named list of of function, that can +# be run in order later on. + +# func_hookable FUNC_NAME +# ----------------------- +# Declare that FUNC_NAME will run hooks added with +# 'func_add_hook FUNC_NAME ...'. +func_hookable () +{ + $debug_cmd + + func_append hookable_fns " $1" +} + + +# func_add_hook FUNC_NAME HOOK_FUNC +# --------------------------------- +# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must +# first have been declared "hookable" by a call to 'func_hookable'. +func_add_hook () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not accept hook functions." ;; + esac + + eval func_append ${1}_hooks '" $2"' +} + + +# func_remove_hook FUNC_NAME HOOK_FUNC +# ------------------------------------ +# Remove HOOK_FUNC from the list of functions called by FUNC_NAME. +func_remove_hook () +{ + $debug_cmd + + eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' +} + + +# func_run_hooks FUNC_NAME [ARG]... +# --------------------------------- +# Run all hook functions registered to FUNC_NAME. +# It is assumed that the list of hook functions contains nothing more +# than a whitespace-delimited list of legal shell function names, and +# no effort is wasted trying to catch shell meta-characters or preserve +# whitespace. +func_run_hooks () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not support hook funcions.n" ;; + esac + + eval _G_hook_fns=\$$1_hooks; shift + + for _G_hook in $_G_hook_fns; do + eval $_G_hook '"$@"' + + # store returned options list back into positional + # parameters for next 'cmd' execution. + eval _G_hook_result=\$${_G_hook}_result + eval set dummy "$_G_hook_result"; shift + done + + func_quote_for_eval ${1+"$@"} + func_run_hooks_result=$func_quote_for_eval_result +} + + + +## --------------- ## +## Option parsing. ## +## --------------- ## + +# In order to add your own option parsing hooks, you must accept the +# full positional parameter list in your hook function, remove any +# options that you action, and then pass back the remaining unprocessed +# options in '_result', escaped suitably for +# 'eval'. Like this: +# +# my_options_prep () +# { +# $debug_cmd +# +# # Extend the existing usage message. +# usage_message=$usage_message' +# -s, --silent don'\''t print informational messages +# ' +# +# func_quote_for_eval ${1+"$@"} +# my_options_prep_result=$func_quote_for_eval_result +# } +# func_add_hook func_options_prep my_options_prep +# +# +# my_silent_option () +# { +# $debug_cmd +# +# # Note that for efficiency, we parse as many options as we can +# # recognise in a loop before passing the remainder back to the +# # caller on the first unrecognised argument we encounter. +# while test $# -gt 0; do +# opt=$1; shift +# case $opt in +# --silent|-s) opt_silent=: ;; +# # Separate non-argument short options: +# -s*) func_split_short_opt "$_G_opt" +# set dummy "$func_split_short_opt_name" \ +# "-$func_split_short_opt_arg" ${1+"$@"} +# shift +# ;; +# *) set dummy "$_G_opt" "$*"; shift; break ;; +# esac +# done +# +# func_quote_for_eval ${1+"$@"} +# my_silent_option_result=$func_quote_for_eval_result +# } +# func_add_hook func_parse_options my_silent_option +# +# +# my_option_validation () +# { +# $debug_cmd +# +# $opt_silent && $opt_verbose && func_fatal_help "\ +# '--silent' and '--verbose' options are mutually exclusive." +# +# func_quote_for_eval ${1+"$@"} +# my_option_validation_result=$func_quote_for_eval_result +# } +# func_add_hook func_validate_options my_option_validation +# +# You'll alse need to manually amend $usage_message to reflect the extra +# options you parse. It's preferable to append if you can, so that +# multiple option parsing hooks can be added safely. + + +# func_options [ARG]... +# --------------------- +# All the functions called inside func_options are hookable. See the +# individual implementations for details. +func_hookable func_options +func_options () +{ + $debug_cmd + + func_options_prep ${1+"$@"} + eval func_parse_options \ + ${func_options_prep_result+"$func_options_prep_result"} + eval func_validate_options \ + ${func_parse_options_result+"$func_parse_options_result"} + + eval func_run_hooks func_options \ + ${func_validate_options_result+"$func_validate_options_result"} + + # save modified positional parameters for caller + func_options_result=$func_run_hooks_result +} + + +# func_options_prep [ARG]... +# -------------------------- +# All initialisations required before starting the option parse loop. +# Note that when calling hook functions, we pass through the list of +# positional parameters. If a hook function modifies that list, and +# needs to propogate that back to rest of this script, then the complete +# modified list must be put in 'func_run_hooks_result' before +# returning. +func_hookable func_options_prep +func_options_prep () +{ + $debug_cmd + + # Option defaults: + opt_verbose=false + opt_warning_types= + + func_run_hooks func_options_prep ${1+"$@"} + + # save modified positional parameters for caller + func_options_prep_result=$func_run_hooks_result +} + + +# func_parse_options [ARG]... +# --------------------------- +# The main option parsing loop. +func_hookable func_parse_options +func_parse_options () +{ + $debug_cmd + + func_parse_options_result= + + # this just eases exit handling + while test $# -gt 0; do + # Defer to hook functions for initial option parsing, so they + # get priority in the event of reusing an option name. + func_run_hooks func_parse_options ${1+"$@"} + + # Adjust func_parse_options positional parameters to match + eval set dummy "$func_run_hooks_result"; shift + + # Break out of the loop if we already parsed every option. + test $# -gt 0 || break + + _G_opt=$1 + shift + case $_G_opt in + --debug|-x) debug_cmd='set -x' + func_echo "enabling shell trace mode" + $debug_cmd + ;; + + --no-warnings|--no-warning|--no-warn) + set dummy --warnings none ${1+"$@"} + shift + ;; + + --warnings|--warning|-W) + test $# = 0 && func_missing_arg $_G_opt && break + case " $warning_categories $1" in + *" $1 "*) + # trailing space prevents matching last $1 above + func_append_uniq opt_warning_types " $1" + ;; + *all) + opt_warning_types=$warning_categories + ;; + *none) + opt_warning_types=none + warning_func=: + ;; + *error) + opt_warning_types=$warning_categories + warning_func=func_fatal_error + ;; + *) + func_fatal_error \ + "unsupported warning category: '$1'" + ;; + esac + shift + ;; + + --verbose|-v) opt_verbose=: ;; + --version) func_version ;; + -\?|-h) func_usage ;; + --help) func_help ;; + + # Separate optargs to long options (plugins may need this): + --*=*) func_split_equals "$_G_opt" + set dummy "$func_split_equals_lhs" \ + "$func_split_equals_rhs" ${1+"$@"} + shift + ;; + + # Separate optargs to short options: + -W*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-v*|-x*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) break ;; + -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + esac + done + + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + func_parse_options_result=$func_quote_for_eval_result +} + + +# func_validate_options [ARG]... +# ------------------------------ +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +func_hookable func_validate_options +func_validate_options () +{ + $debug_cmd + + # Display all warnings if -W was not given. + test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" + + func_run_hooks func_validate_options ${1+"$@"} + + # Bail if the options were screwed! + $exit_cmd $EXIT_FAILURE + + # save modified positional parameters for caller + func_validate_options_result=$func_run_hooks_result +} + + + +## ----------------- ## +## Helper functions. ## +## ----------------- ## + +# This section contains the helper functions used by the rest of the +# hookable option parser framework in ascii-betical order. + + +# func_fatal_help ARG... +# ---------------------- +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + eval \$ECHO \""$fatal_help"\" + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + + +# func_help +# --------- +# Echo long help message to standard output and exit. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message" + exit 0 +} + + +# func_missing_arg ARGNAME +# ------------------------ +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $debug_cmd + + func_error "Missing argument for '$1'." + exit_cmd=exit +} + + +# func_split_equals STRING +# ------------------------ +# Set func_split_equals_lhs and func_split_equals_rhs shell variables after +# splitting STRING at the '=' sign. +test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=${1%%=*} + func_split_equals_rhs=${1#*=} + test "x$func_split_equals_lhs" = "x$1" \ + && func_split_equals_rhs= + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` + func_split_equals_rhs= + test "x$func_split_equals_lhs" = "x$1" \ + || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` + } +fi #func_split_equals + + +# func_split_short_opt SHORTOPT +# ----------------------------- +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"} + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` + func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` + } +fi #func_split_short_opt + + +# func_usage +# ---------- +# Echo short help message to standard output and exit. +func_usage () +{ + $debug_cmd + + func_usage_message + $ECHO "Run '$progname --help |${PAGER-more}' for full usage" + exit 0 +} + + +# func_usage_message +# ------------------ +# Echo short help message to standard output. +func_usage_message () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + echo + $SED -n 's|^# || + /^Written by/{ + x;p;x + } + h + /^Written by/q' < "$progpath" + echo + eval \$ECHO \""$usage_message"\" +} + + +# func_version +# ------------ +# Echo version message to standard output and exit. +func_version () +{ + $debug_cmd + + printf '%s\n' "$progname $scriptversion" + $SED -n ' + /(C)/!b go + :more + /\./!{ + N + s|\n# | | + b more + } + :go + /^# Written by /,/# warranty; / { + s|^# || + s|^# *$|| + s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| + p + } + /^# Written by / { + s|^# || + p + } + /^warranty; /q' < "$progpath" + + exit $? +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: + +# Set a version string. +scriptversion='(GNU libtool) 2.4.6' + + +# func_echo ARG... +# ---------------- +# Libtool also displays the current mode in messages, so override +# funclib.sh func_echo with this custom definition. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_warning ARG... +# ------------------- +# Libtool warnings are not categorized, so override funclib.sh +# func_warning with this simpler definition. +func_warning () +{ + $debug_cmd + + $warning_func ${1+"$@"} +} + + +## ---------------- ## +## Options parsing. ## +## ---------------- ## + +# Hook in the functions to make sure our own options are parsed during +# the option parsing loop. + +usage='$progpath [OPTION]... [MODE-ARG]...' + +# Short help message in response to '-h'. +usage_message="Options: + --config show all configuration variables + --debug enable verbose shell tracing + -n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --mode=MODE use operation mode MODE + --no-warnings equivalent to '-Wnone' + --preserve-dup-deps don't remove duplicate dependency libraries + --quiet, --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + -v, --verbose print more informational messages than default + --version print version information + -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] + -h, --help, --help-all print short, long, or detailed help message +" + +# Additional text appended to 'usage_message' in response to '--help'. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. When passed as first option, +'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. +Try '$progname --help --mode=MODE' for a more detailed description of MODE. + +When reporting a bug, please describe a test case to reproduce it and +include the following information: + + host-triplet: $host + shell: $SHELL + compiler: $LTCC + compiler flags: $LTCFLAGS + linker: $LD (gnu? $with_gnu_ld) + version: $progname $scriptversion Debian-2.4.6-2 + automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` + autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` + +Report bugs to . +GNU libtool home page: . +General help using GNU software: ." + exit 0 +} + + +# func_lo2o OBJECT-NAME +# --------------------- +# Transform OBJECT-NAME from a '.lo' suffix to the platform specific +# object suffix. + +lo2o=s/\\.lo\$/.$objext/ +o2lo=s/\\.$objext\$/.lo/ + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_lo2o () + { + case $1 in + *.lo) func_lo2o_result=${1%.lo}.$objext ;; + * ) func_lo2o_result=$1 ;; + esac + }' + + # func_xform LIBOBJ-OR-SOURCE + # --------------------------- + # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) + # suffix to a '.lo' libtool-object suffix. + eval 'func_xform () + { + func_xform_result=${1%.*}.lo + }' +else + # ...otherwise fall back to using sed. + func_lo2o () + { + func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` + } + + func_xform () + { + func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` + } +fi + + +# func_fatal_configuration ARG... +# ------------------------------- +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func__fatal_error ${1+"$@"} \ + "See the $PACKAGE documentation for more information." \ + "Fatal configuration error." +} + + +# func_config +# ----------- +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + + +# func_features +# ------------- +# Display the features supported by this script. +func_features () +{ + echo "host: $host" + if test yes = "$build_libtool_libs"; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test yes = "$build_old_libs"; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + + exit $? +} + + +# func_enable_tag TAGNAME +# ----------------------- +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname=$1 + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf=/$re_begincf/,/$re_endcf/p + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + + +# func_check_version_match +# ------------------------ +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# libtool_options_prep [ARG]... +# ----------------------------- +# Preparation for options parsed by libtool. +libtool_options_prep () +{ + $debug_mode + + # Option defaults: + opt_config=false + opt_dlopen= + opt_dry_run=false + opt_help=false + opt_mode= + opt_preserve_dup_deps=false + opt_quiet=false + + nonopt= + preserve_args= + + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; + esac + + # Pass back the list of options. + func_quote_for_eval ${1+"$@"} + libtool_options_prep_result=$func_quote_for_eval_result +} +func_add_hook func_options_prep libtool_options_prep + + +# libtool_parse_options [ARG]... +# --------------------------------- +# Provide handling for libtool specific options. +libtool_parse_options () +{ + $debug_cmd + + # Perform our own loop to consume as many options as possible in + # each iteration. + while test $# -gt 0; do + _G_opt=$1 + shift + case $_G_opt in + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + + --config) func_config ;; + + --dlopen|-dlopen) + opt_dlopen="${opt_dlopen+$opt_dlopen +}$1" + shift + ;; + + --preserve-dup-deps) + opt_preserve_dup_deps=: ;; + + --features) func_features ;; + + --finish) set dummy --mode finish ${1+"$@"}; shift ;; + + --help) opt_help=: ;; + + --help-all) opt_help=': help-all' ;; + + --mode) test $# = 0 && func_missing_arg $_G_opt && break + opt_mode=$1 + case $1 in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $_G_opt" + exit_cmd=exit + break + ;; + esac + shift + ;; + + --no-silent|--no-quiet) + opt_quiet=false + func_append preserve_args " $_G_opt" + ;; + + --no-warnings|--no-warning|--no-warn) + opt_warning=false + func_append preserve_args " $_G_opt" + ;; + + --no-verbose) + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --silent|--quiet) + opt_quiet=: + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --tag) test $# = 0 && func_missing_arg $_G_opt && break + opt_tag=$1 + func_append preserve_args " $_G_opt $1" + func_enable_tag "$1" + shift + ;; + + --verbose|-v) opt_quiet=false + opt_verbose=: + func_append preserve_args " $_G_opt" + ;; + + # An option not handled by this hook function: + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + esac + done + + + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + libtool_parse_options_result=$func_quote_for_eval_result +} +func_add_hook func_parse_options libtool_parse_options + + + +# libtool_validate_options [ARG]... +# --------------------------------- +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +libtool_validate_options () +{ + # save first non-option argument + if test 0 -lt $#; then + nonopt=$1 + shift + fi + + # preserve --debug + test : = "$debug_cmd" || func_append preserve_args " --debug" + + case $host in + # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 + # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 + *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + test yes != "$build_libtool_libs" \ + && test yes != "$build_old_libs" \ + && func_fatal_configuration "not configured to build any kind of library" + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test execute != "$opt_mode"; then + func_error "unrecognized option '-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help=$help + help="Try '$progname --help --mode=$opt_mode' for more information." + } + + # Pass back the unparsed argument list + func_quote_for_eval ${1+"$@"} + libtool_validate_options_result=$func_quote_for_eval_result +} +func_add_hook func_validate_options libtool_validate_options + + +# Process options as early as possible so that --help and --version +# can return quickly. +func_options ${1+"$@"} +eval set dummy "$func_options_result"; shift + + + +## ----------- ## +## Main. ## +## ----------- ## + +magic='%%%MAGIC variable%%%' +magic_exe='%%%MAGIC EXE variable%%%' + +# Global variables. +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# func_generated_by_libtool +# True iff stdin has been generated by Libtool. This function is only +# a basic sanity check; it will hardly flush out determined imposters. +func_generated_by_libtool_p () +{ + $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if 'file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case $lalib_p_line in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test yes = "$lalib_p" +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + test -f "$1" && + $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $debug_cmd + + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# 'FILE.' does not work on cygwin managed mounts. +func_source () +{ + $debug_cmd + + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case $lt_sysroot:$1 in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result='='$func_stripname_result + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $debug_cmd + + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with '--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=$1 + if test yes = "$build_libtool_libs"; then + write_lobj=\'$2\' + else + write_lobj=none + fi + + if test yes = "$build_old_libs"; then + write_oldobj=\'$3\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T </dev/null` + if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $debug_cmd + + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result= + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result"; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $debug_cmd + + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $debug_cmd + + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $debug_cmd + + if test -z "$2" && test -n "$1"; then + func_error "Could not determine host file name corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result=$1 + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $debug_cmd + + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " '$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result=$3 + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $debug_cmd + + case $4 in + $1 ) func_to_host_path_result=$3$func_to_host_path_result + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via '$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $debug_cmd + + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $debug_cmd + + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result=$1 +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result=$func_convert_core_msys_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result=$func_convert_core_file_wine_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via '$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $debug_cmd + + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd=func_convert_path_$func_stripname_result + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $debug_cmd + + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result=$1 +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_msys_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_path_wine_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_dll_def_p FILE +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with _LT_DLL_DEF_P in libtool.m4 +func_dll_def_p () +{ + $debug_cmd + + func_dll_def_p_tmp=`$SED -n \ + -e 's/^[ ]*//' \ + -e '/^\(;.*\)*$/d' \ + -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ + -e q \ + "$1"` + test DEF = "$func_dll_def_p_tmp" +} + + +# func_mode_compile arg... +func_mode_compile () +{ + $debug_cmd + + # Get the compilation command and the source file. + base_compile= + srcfile=$nonopt # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg=$arg + arg_mode=normal + ;; + + target ) + libobj=$arg + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify '-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append later " $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs=$IFS; IFS=, + for arg in $args; do + IFS=$save_ifs + func_append_quoted lastarg "$arg" + done + IFS=$save_ifs + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append base_compile " $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg=$srcfile + srcfile=$arg + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with '-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj=$func_basename_result + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from '$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test yes = "$build_libtool_libs" \ + || func_fatal_configuration "cannot build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_for_eval "$libobj" + test "X$libobj" != "X$func_quote_for_eval_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name '$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname=$func_basename_result + xdir=$func_dirname_result + lobj=$xdir$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test yes = "$build_old_libs"; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test no = "$compiler_c_o"; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext + lockfile=$output_obj.lock + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test yes = "$need_locks"; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test warn = "$need_locks"; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test yes = "$build_libtool_libs"; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test no != "$pic_mode"; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test yes = "$suppress_opt"; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test yes = "$build_old_libs"; then + if test yes != "$pic_mode"; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test yes = "$compiler_c_o"; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test no != "$need_locks"; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test compile = "$opt_mode" && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a '.o' file suitable for static linking + -static only build a '.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +COMPILE-COMMAND is a command to be used in creating a 'standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix '.c' with the +library object suffix, '.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to '-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the '--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the 'install' or 'cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE use a list of object files found in FILE to specify objects + -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +All other options (arguments beginning with '-') are ignored. + +Every other argument is treated as a filename. Files ending in '.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in '.la', then a libtool library is created, +only library objects ('.lo' files) may be specified, and '-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created +using 'ar' and 'ranlib', or on Windows using 'lib'. + +If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode '$opt_mode'" + ;; + esac + + echo + $ECHO "Try '$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test : = "$opt_help"; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | $SED -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + $SED '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $debug_cmd + + # The first argument is the command name. + cmd=$nonopt + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "'$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "'$file' was not linked with '-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir=$func_dirname_result + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir=$func_dirname_result + ;; + + *) + func_warning "'-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir=$absdir + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic=$magic + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file=$progdir/$program + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file=$progdir/$program + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if $opt_dry_run; then + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + else + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd=\$cmd$args + fi +} + +test execute = "$opt_mode" && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $debug_cmd + + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "'$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument '$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and '=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_quiet && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the '-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the '$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the '$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the '$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" + fi + echo + + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test finish = "$opt_mode" && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $debug_cmd + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || + # Allow the use of GNU shtool's install command. + case $nonopt in *shtool*) :;; *) false;; esac + then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + func_append install_prog "$func_quote_for_eval_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=false + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=: ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test X-m = "X$prev" && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + func_append install_prog " $func_quote_for_eval_result" + if test -n "$arg2"; then + func_quote_for_eval "$arg2" + fi + func_append install_shared_prog " $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the '$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_for_eval "$install_override_mode" + func_append install_shared_prog " -m $func_quote_for_eval_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=: + if $isdir; then + destdir=$dest + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir=$func_dirname_result + destname=$func_basename_result + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "'$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "'$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir=$func_dirname_result + func_append dir "$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking '$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname=$1 + shift + + srcname=$realname + test -n "$relink_command" && srcname=${realname}T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme=$stripme + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme= + ;; + esac + ;; + os2*) + case $realname in + *_dll.a) + tstripme= + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try 'ln -sf' first, because the 'ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib=$destdir/$realname + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name=$func_basename_result + instname=$dir/${name}i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append staticlibs " $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest=$destfile + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to '$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test yes = "$build_old_libs"; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext= + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=.exe + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script '$wrapper'" + + finalize=: + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "'$lib' has not been installed in '$libdir'" + finalize=false + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test no = "$fast_install" && test -n "$relink_command"; then + $opt_dry_run || { + if $finalize; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file=$func_basename_result + outputname=$tmpdir/$file + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_quiet || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink '$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file=$outputname + else + func_warning "cannot relink '$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name=$func_basename_result + + # Set up the ranlib parameters. + oldlib=$destdir/$name + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $tool_oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run '$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test install = "$opt_mode" && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $debug_cmd + + my_outputname=$1 + my_originator=$2 + my_pic_p=${3-false} + my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms=${my_outputname}S.c + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist=$output_objdir/$my_outputname.nm + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* External symbol declarations for the compiler. */\ +" + + if test yes = "$dlself"; then + func_verbose "generating symbol list for '$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from '$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols=$output_objdir/$outputname.exp + $opt_dry_run || { + $RM $export_symbols + eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from '$dlprefile'" + func_basename "$dlprefile" + name=$func_basename_result + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename= + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname"; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename=$func_basename_result + else + # no lafile. user explicitly requested -dlpreopen . + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename"; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + func_show_eval '$RM "${nlist}I"' + if test -n "$global_symbol_to_import"; then + eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[];\ +" + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ +static void lt_syminit(void) +{ + LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; + for (; symbol->name; ++symbol) + {" + $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" + echo >> "$output_objdir/$my_dlsyms" "\ + } +}" + fi + echo >> "$output_objdir/$my_dlsyms" "\ +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{ {\"$my_originator\", (void *) 0}," + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ + {\"@INIT@\", (void *) <_syminit}," + fi + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + $my_pic_p && pic_flag_for_symtable=" $pic_flag" + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' + + # Transform the symbol file into the correct name. + symfileobj=$output_objdir/${my_outputname}S.$objext + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for '$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $debug_cmd + + win32_libid_type=unknown + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + case $nm_interface in + "MS dumpbin") + if func_cygming_ms_implib_p "$1" || + func_cygming_gnu_implib_p "$1" + then + win32_nmres=import + else + win32_nmres= + fi + ;; + *) + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' + 1,100{ + / I /{ + s|.*|import| + p + q + } + }'` + ;; + esac + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $debug_cmd + + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $debug_cmd + + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive that possess that section. Heuristic: eliminate + # all those that have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $debug_cmd + + if func_cygming_gnu_implib_p "$1"; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1"; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result= + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $debug_cmd + + f_ex_an_ar_dir=$1; shift + f_ex_an_ar_oldlib=$1 + if test yes = "$lock_old_archive_extraction"; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test yes = "$lock_old_archive_extraction"; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $debug_cmd + + my_gentop=$1; shift + my_oldlibs=${1+"$@"} + my_oldobjs= + my_xlib= + my_xabs= + my_xdir= + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib=$func_basename_result + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir=$my_gentop/$my_xlib_u + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + func_basename "$darwin_archive" + darwin_base_archive=$func_basename_result + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches; do + func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" + $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" + cd "unfat-$$/$darwin_base_archive-$darwin_arch" + func_extract_an_archive "`pwd`" "$darwin_base_archive" + cd "$darwin_curdir" + $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result=$my_oldobjs +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory where it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + file=\"\$0\"" + + qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=\"$qECHO\" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case \" \$* \" in + *\\ --lt-*) + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done ;; + esac + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test yes = "$fast_install"; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + \$ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +#else +# include +# include +# ifdef __CYGWIN__ +# include +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* declarations of non-ANSI functions */ +#if defined __MINGW32__ +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined __CYGWIN__ +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined other_platform || defined ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined _MSC_VER +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +#elif defined __MINGW32__ +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined __CYGWIN__ +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined other platforms ... */ +#endif + +#if defined PATH_MAX +# define LT_PATHMAX PATH_MAX +#elif defined MAXPATHLEN +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ + defined __OS2__ +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free (stale); stale = 0; } \ +} while (0) + +#if defined LT_DEBUGWRAPPER +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + size_t tmp_len; + char *concat_name; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined HAVE_DOS_BASED_FILE_SYSTEM + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined HAVE_DOS_BASED_FILE_SYSTEM + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = (size_t) (q - p); + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (STREQ (str, pat)) + *str = '\0'; + } + return str; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + size_t len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + size_t orig_value_len = strlen (orig_value); + size_t add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + size_t len = strlen (new_value); + while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[--len] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -n -e ' +s/^\(.\{79\}\)\(..*\)/\1\ +\2/ +h +s/\([\\"]\)/\\\1/g +s/$/\\n/ +s/\([^\n]*\).*/ fputs ("\1", f);/p +g +D' + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $debug_cmd + + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_suncc_cstd_abi +# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! +# Several compiler flags select an ABI that is incompatible with the +# Cstd library. Avoid specifying it if any are in CXXFLAGS. +func_suncc_cstd_abi () +{ + $debug_cmd + + case " $compile_command " in + *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) + suncc_use_cstd_abi=no + ;; + *) + suncc_use_cstd_abi=yes + ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $debug_cmd + + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # what system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll that has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + os2dllname= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=false + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module=$wl-single_module + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test yes != "$build_libtool_libs" \ + && func_fatal_configuration "cannot build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg=$1 + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir=$arg + prev= + continue + ;; + dlfiles|dlprefiles) + $preload || { + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=: + } + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test no = "$dlself"; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test dlprefiles = "$prev"; then + dlself=yes + elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test dlfiles = "$prev"; then + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols=$arg + test -f "$arg" \ + || func_fatal_error "symbol file '$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex=$arg + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir=$arg + prev= + continue + ;; + mllvm) + # Clang does not use LLVM to link, so we can simply discard any + # '-mllvm $arg' options when doing the link step. + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + if test none != "$pic_object"; then + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + fi + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file '$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + os2dllname) + os2dllname=$arg + prev= + continue + ;; + precious_regex) + precious_files_regex=$arg + prev= + continue + ;; + release) + release=-$arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test rpath = "$prev"; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds=$arg + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg=$arg + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "'-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test X-export-symbols = "X$arg"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between '-L' and '$1'" + else + func_fatal_error "need path for '-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of '$dir'" + dir=$absdir + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test X-lc = "X$arg" || test X-lm = "X$arg"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test X-lc = "X$arg" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc due to us having libc/libc_r. + test X-lc = "X$arg" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + func_append deplibs " System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test X-lc = "X$arg" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test X-lc = "X$arg" && continue + ;; + esac + elif test X-lc_r = "X$arg"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + func_append deplibs " $arg" + continue + ;; + + -mllvm) + prev=mllvm + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module=$wl-multi_module + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "'-no-install' is ignored for $host" + func_warning "assuming '-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -os2dllname) + prev=os2dllname + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $func_quote_for_eval_result" + func_append compiler_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $wl$func_quote_for_eval_result" + func_append compiler_flags " $wl$func_quote_for_eval_result" + func_append linker_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # -fstack-protector* stack protector flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -specs=* GCC specs files + # -stdlib=* select c++ std lib with clang + # -fsanitize=* Clang/GCC memory and address sanitizer + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ + -specs=*|-fsanitize=*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + -Z*) + if test os2 = "`expr $host : '.*\(os2\)'`"; then + # OS/2 uses -Zxxx to specify OS/2-specific options + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case $arg in + -Zlinker | -Zstack) + prev=xcompiler + ;; + esac + continue + else + # Otherwise treat like 'Some other compiler flag' below + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + fi + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + test none = "$pic_object" || { + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + } + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test dlfiles = "$prev"; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test dlprefiles = "$prev"; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the '$prevarg' option requires an argument" + + if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname=$func_basename_result + libobjs_save=$libobjs + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + # Definition is injected by LT_CONFIG during libtool generation. + func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" + + func_dirname "$output" "/" "" + output_objdir=$func_dirname_result$objdir + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_preserve_dup_deps; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append libs " $deplib" + done + + if test lib = "$linkmode"; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append pre_post_deps " $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=false + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test lib,link = "$linkmode,$pass"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs=$tmp_deplibs + fi + + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass"; then + libs=$deplibs + deplibs= + fi + if test prog = "$linkmode"; then + case $pass in + dlopen) libs=$dlfiles ;; + dlpreopen) libs=$dlprefiles ;; + link) + libs="$deplibs %DEPLIBS%" + test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" + ;; + esac + fi + if test lib,dlpreopen = "$linkmode,$pass"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs=$dlprefiles + fi + if test dlopen = "$pass"; then + # Collect dlpreopened libraries + save_deplibs=$deplibs + deplibs= + fi + + for deplib in $libs; do + lib= + found=false + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test lib != "$linkmode" && test prog != "$linkmode"; then + func_warning "'-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test lib = "$linkmode"; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib=$searchdir/lib$name$search_ext + if test -f "$lib"; then + if test .la = "$search_ext"; then + found=: + else + found=false + fi + break 2 + fi + done + done + if $found; then + # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll=$l + done + if test "X$ll" = "X$old_library"; then # only static version available + found=false + func_dirname "$lib" "" "." + ladir=$func_dirname_result + lib=$ladir/$old_library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + else + # deplib doesn't seem to be a libtool library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + ;; # -l + *.ltframework) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test conv = "$pass" && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + prog) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + if test scan = "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "'-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test link = "$pass"; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=false + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=: + fi + ;; + pass_all) + valid_a_lib=: + ;; + esac + if $valid_a_lib; then + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + else + echo + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." + fi + ;; + esac + continue + ;; + prog) + if test link != "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + elif test prog = "$linkmode"; then + if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=: + continue + ;; + esac # case $deplib + + $found || test -f "$lib" \ + || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "'$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir=$func_dirname_result + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass" || + { test prog != "$linkmode" && test lib != "$linkmode"; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" + fi + + if test conv = "$pass"; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + elif test prog != "$linkmode" && test lib != "$linkmode"; then + func_fatal_error "'$lib' is not a convenience library" + fi + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test yes = "$prefer_static_libs" || + test built,no = "$prefer_static_libs,$installed"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib=$l + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + + # This library was specified with -dlopen. + if test dlopen = "$pass"; then + test -z "$libdir" \ + && func_fatal_error "cannot -dlopen a convenience library: '$lib'" + if test -z "$dlname" || + test yes != "$dlopen_support" || + test no = "$build_libtool_libs" + then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + func_append dlprefiles " $lib $dependency_libs" + else + func_append newdlfiles " $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of '$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir=$ladir + fi + ;; + esac + func_basename "$lib" + laname=$func_basename_result + + # Find the relevant object directory and library name. + if test yes = "$installed"; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library '$lib' was moved." + dir=$ladir + absdir=$abs_ladir + libdir=$abs_ladir + else + dir=$lt_sysroot$libdir + absdir=$lt_sysroot$libdir + fi + test yes = "$hardcode_automatic" && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir=$ladir + absdir=$abs_ladir + # Remove this search path later + func_append notinst_path " $abs_ladir" + else + dir=$ladir/$objdir + absdir=$abs_ladir/$objdir + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test dlpreopen = "$pass"; then + if test -z "$libdir" && test prog = "$linkmode"; then + func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" + fi + case $host in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test lib = "$linkmode"; then + deplibs="$dir/$old_library $deplibs" + elif test prog,link = "$linkmode,$pass"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test prog = "$linkmode" && test link != "$pass"; then + func_append newlib_search_path " $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=false + if test no != "$link_all_deplibs" || test -z "$library_names" || + test no = "$build_libtool_libs"; then + linkalldeplibs=: + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + esac + # Need to link against all dependency_libs? + if $linkalldeplibs; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test prog,link = "$linkmode,$pass"; then + if test -n "$library_names" && + { { test no = "$prefer_static_libs" || + test built,yes = "$prefer_static_libs,$installed"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then + # Make sure the rpath contains only unique directories. + case $temp_rpath: in + *"$absdir:"*) ;; + *) func_append temp_rpath "$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if $alldeplibs && + { test pass_all = "$deplibs_check_method" || + { test yes = "$build_libtool_libs" && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test built = "$use_static_libs" && test yes = "$installed"; then + use_static_libs=no + fi + if test -n "$library_names" && + { test no = "$use_static_libs" || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc* | *os2*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test no = "$installed"; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule= + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule=$dlpremoduletest + break + fi + done + if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then + echo + if test prog = "$linkmode"; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test lib = "$linkmode" && + test yes = "$hardcode_into_libs"; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname=$1 + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname=$dlname + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc* | *os2*) + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + esac + eval soname=\"$soname_spec\" + else + soname=$realname + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot=$soname + func_basename "$soroot" + soname=$func_basename_result + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from '$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for '$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test prog = "$linkmode" || test relink != "$opt_mode"; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test no = "$hardcode_direct"; then + add=$dir/$linklib + case $host in + *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; + *-*-sysv4*uw2*) add_dir=-L$dir ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir=-L$dir ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we cannot + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library"; then + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" + else + add=$dir/$old_library + fi + elif test -n "$old_library"; then + add=$dir/$old_library + fi + fi + esac + elif test no = "$hardcode_minus_L"; then + case $host in + *-*-sunos*) add_shlibpath=$dir ;; + esac + add_dir=-L$dir + add=-l$name + elif test no = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + relink) + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$dir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$absdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test yes != "$lib_linked"; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; + esac + fi + if test prog = "$linkmode"; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test yes != "$hardcode_direct" && + test yes != "$hardcode_minus_L" && + test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test prog = "$linkmode" || test relink = "$opt_mode"; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$libdir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$libdir + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + add=-l$name + elif test yes = "$hardcode_automatic"; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib"; then + add=$inst_prefix_dir$libdir/$linklib + else + add=$libdir/$linklib + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir=-L$libdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + fi + + if test prog = "$linkmode"; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test prog = "$linkmode"; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test unsupported != "$hardcode_direct"; then + test -n "$old_library" && linklib=$old_library + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test yes = "$build_libtool_libs"; then + # Not a shared library + if test pass_all != "$deplibs_check_method"; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + $ECHO "*** Warning: This system cannot link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test yes = "$module"; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test lib = "$linkmode"; then + if test -n "$dependency_libs" && + { test yes != "$hardcode_into_libs" || + test yes = "$build_old_libs" || + test yes = "$link_static"; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs=$temp_deplibs + fi + + func_append newlib_search_path " $absdir" + # Link against this library + test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test no != "$link_all_deplibs"; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path=$deplib ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of '$dir'" + absdir=$dir + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names"; then + for tmp in $deplibrary_names; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl"; then + depdepl=$absdir/$objdir/$depdepl + darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" + func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" + path= + fi + fi + ;; + *) + path=-L$absdir/$objdir + ;; + esac + else + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "'$deplib' seems to be moved" + + path=-L$absdir + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test link = "$pass"; then + if test prog = "$linkmode"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs=$newdependency_libs + if test dlpreopen = "$pass"; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test dlopen != "$pass"; then + test conv = "$pass" || { + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) func_append lib_search_path " $dir" ;; + esac + done + newlib_search_path= + } + + if test prog,link = "$linkmode,$pass"; then + vars="compile_deplibs finalize_deplibs" + else + vars=deplibs + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append tmp_libs " $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + + # Add Sun CC postdeps if required: + test CXX = "$tagname" && { + case $host_os in + linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C++ 5.9 + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + + solaris*) + func_cc_basename "$CC" + case $func_cc_basename_result in + CC* | sunCC*) + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + esac + } + + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i= + ;; + esac + if test -n "$i"; then + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test prog = "$linkmode"; then + dlfiles=$newdlfiles + fi + if test prog = "$linkmode" || test lib = "$linkmode"; then + dlprefiles=$newdlprefiles + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "'-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "'-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs=$output + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form 'libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test no = "$module" \ + && func_fatal_help "libtool library '$output' must begin with 'lib'" + + if test no != "$need_lib_prefix"; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test pass_all != "$deplibs_check_method"; then + func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test no = "$dlself" \ + || func_warning "'-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test 1 -lt "$#" \ + && func_warning "ignoring multiple '-rpath's for a libtool library" + + install_libdir=$1 + + oldlibs= + if test -z "$rpath"; then + if test yes = "$build_libtool_libs"; then + # Building a libtool convenience library. + # Some compilers have problems with a '.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "'-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs=$IFS; IFS=: + set dummy $vinfo 0 0 0 + shift + IFS=$save_ifs + + test -n "$7" && \ + func_fatal_help "too many parameters to '-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major=$1 + number_minor=$2 + number_revision=$3 + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # that has an extra 1 added just for fun + # + case $version_type in + # correct linux to gnu/linux during the next big refactor + darwin|freebsd-elf|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_revision + ;; + freebsd-aout|qnx|sunos) + current=$number_major + revision=$number_minor + age=0 + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_minor + lt_irix_increment=no + ;; + *) + func_fatal_configuration "$modename: unknown library version type '$version_type'" + ;; + esac + ;; + no) + current=$1 + revision=$2 + age=$3 + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT '$current' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION '$revision' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE '$age' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE '$age' is greater than the current interface number '$current'" + func_fatal_error "'$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + # On Darwin other compilers + case $CC in + nagfor*) + verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + ;; + *) + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + esac + ;; + + freebsd-aout) + major=.$current + versuffix=.$current.$revision + ;; + + freebsd-elf) + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + irix | nonstopux) + if test no = "$lt_irix_increment"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring=$verstring_prefix$major.$revision + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test 0 -ne "$loop"; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring_prefix$major.$iface:$verstring + done + + # Before this point, $major must not contain '.'. + major=.$major + versuffix=$major.$revision + ;; + + linux) # correct to gnu/linux during the next big refactor + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=.$current.$age.$revision + verstring=$current.$age.$revision + + # Add in all the interfaces that we are compatible with. + loop=$age + while test 0 -ne "$loop"; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring:$iface.0 + done + + # Make executables depend on our current version. + func_append verstring ":$current.0" + ;; + + qnx) + major=.$current + versuffix=.$current + ;; + + sco) + major=.$current + versuffix=.$current + ;; + + sunos) + major=.$current + versuffix=.$current.$revision + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 file systems. + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + + *) + func_fatal_configuration "unknown library version type '$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring=0.0 + ;; + esac + if test no = "$need_version"; then + versuffix= + else + versuffix=.0.0 + fi + fi + + # Remove version info from name if versioning should be avoided + if test yes,no = "$avoid_version,$need_version"; then + major= + versuffix= + verstring= + fi + + # Check to see if the archive will have undefined symbols. + if test yes = "$allow_undefined"; then + if test unsupported = "$allow_undefined_flag"; then + if test yes = "$build_old_libs"; then + func_warning "undefined symbols not allowed in $host shared libraries; building static only" + build_libtool_libs=no + else + func_fatal_error "can't build $host shared library unless -no-undefined is specified" + fi + fi + else + # Don't allow undefined symbols. + allow_undefined_flag=$no_undefined_flag + fi + + fi + + func_generate_dlsyms "$libname" "$libname" : + func_append libobjs " $symfileobj" + test " " = "$libobjs" && libobjs= + + if test relink != "$opt_mode"; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) + if test -n "$precious_files_regex"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles=$dlfiles + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) func_append dlfiles " $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles=$dlprefiles + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test yes = "$build_libtool_libs"; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test yes = "$build_libtool_need_lc"; then + func_append deplibs " -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release= + versuffix= + major= + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib=$potent_lib + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | $SED 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; + *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib= + ;; + esac + fi + if test -n "$a_deplib"; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib=$potent_lib # see symlink-check above in file_magic test + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs= + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + for i in $predeps $postdeps; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + echo + if test none = "$deplibs_check_method"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + ;; + esac + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + if test yes = "$droppeddeps"; then + if test yes = "$module"; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test no = "$allow_undefined"; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + deplibs=$new_libs + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test yes = "$build_libtool_libs"; then + # Remove $wl instances when linking with ld. + # FIXME: should test the right _cmds variable. + case $archive_cmds in + *\$LD\ *) wl= ;; + esac + if test yes = "$hardcode_into_libs"; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath=$finalize_rpath + test relink = "$opt_mode" || rpath=$compile_rpath$rpath + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath=$finalize_shlibpath + test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname=$1 + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname=$realname + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib=$output_objdir/$realname + linknames= + for link + do + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols=$output_objdir/$libname.uexp + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + func_dll_def_p "$export_symbols" || { + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols=$export_symbols + export_symbols= + always_export_symbols=yes + } + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs=$IFS; IFS='~' + for cmd1 in $cmds; do + IFS=$save_ifs + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test yes = "$try_normal_branch" \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=$output_objdir/$output_la.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS=$save_ifs + if test -n "$export_symbols_regex" && test : != "$skipped_export"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test : != "$skipped_export" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs=$tmp_deplibs + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test yes = "$compiler_needs_object" && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test : != "$skipped_export" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then + output=$output_objdir/$output_la.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then + output=$output_objdir/$output_la.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test yes = "$compiler_needs_object"; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-$k.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test -z "$objlist" || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test 1 -eq "$k"; then + # The first file doesn't have a previous command to add. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-$k.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-$k.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + ${skipped_export-false} && { + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + } + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs=$IFS; IFS='~' + for cmd in $concat_cmds; do + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + ${skipped_export-false} && { + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + } + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs=$IFS; IFS='~' + for cmd in $cmds; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test yes = "$module" || test yes = "$export_dynamic"; then + # On all known operating systems, these are identical. + dlname=$soname + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "'-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object '$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj=$output + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # if reload_cmds runs $LD directly, get rid of -Wl from + # whole_archive_flag_spec and hope we can get by with turning comma + # into space. + case $reload_cmds in + *\$LD[\ \$]*) wl= ;; + esac + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags + else + gentop=$output_objdir/${obj}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test yes = "$build_libtool_libs" || libobjs=$non_pic_objects + + # Create the old-style object. + reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs + + output=$obj + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + test yes = "$build_libtool_libs" || { + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + } + + if test -n "$pic_flag" || test default != "$pic_mode"; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output=$libobj + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "'-release' is ignored for programs" + + $preload \ + && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ + && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test CXX = "$tagname"; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " $wl-bind_at_load" + func_append finalize_command " $wl-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs=$new_libs + + + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath=$rpath + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append finalize_perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath=$rpath + + if test -n "$libobjs" && test yes = "$build_old_libs"; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" false + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=: + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=false + ;; + *cygwin* | *mingw* ) + test yes = "$build_libtool_libs" || wrappers_required=false + ;; + *) + if test no = "$need_relink" || test yes != "$build_libtool_libs"; then + wrappers_required=false + fi + ;; + esac + $wrappers_required || { + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command=$compile_command$compile_rpath + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.$objext"; then + func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' + fi + + exit $exit_status + } + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + func_append rpath "$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test yes = "$no_install"; then + # We don't need to create a wrapper script. + link_command=$compile_var$compile_command$compile_rpath + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + exit $EXIT_SUCCESS + fi + + case $hardcode_action,$fast_install in + relink,*) + # Fast installation is not supported + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "'$output' will be relinked during installation" + ;; + *,yes) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + ;; + *,no) + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + ;; + *,needless) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command= + ;; + esac + + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource=$output_path/$objdir/lt-$output_name.c + cwrapper=$output_path/$output_name.exe + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host"; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + case $build_libtool_libs in + convenience) + oldobjs="$libobjs_save $symfileobj" + addlibs=$convenience + build_libtool_libs=no + ;; + module) + oldobjs=$libobjs_save + addlibs=$old_convenience + build_libtool_libs=no + ;; + *) + oldobjs="$old_deplibs $non_pic_objects" + $preload && test -f "$symfileobj" \ + && func_append oldobjs " $symfileobj" + addlibs=$old_convenience + ;; + esac + + if test -n "$addlibs"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append oldobjs " $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase=$func_basename_result + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj"; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test -z "$oldobjs"; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test yes = "$build_old_libs" && old_library=$libname.$libext + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + if test yes = "$hardcode_automatic"; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test yes = "$installed"; then + if test -z "$install_libdir"; then + break + fi + output=$output_objdir/${outputname}i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name=$func_basename_result + func_resolve_sysroot "$deplib" + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs=$newdependency_libs + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles=$newdlprefiles + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles=$newdlprefiles + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test -n "$bindir"; then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result/$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test no,yes = "$installed,$need_relink"; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +if test link = "$opt_mode" || test relink = "$opt_mode"; then + func_mode_link ${1+"$@"} +fi + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $debug_cmd + + RM=$nonopt + files= + rmforce=false + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + for arg + do + case $arg in + -f) func_append RM " $arg"; rmforce=: ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir=$func_dirname_result + if test . = "$dir"; then + odir=$objdir + else + odir=$dir/$objdir + fi + func_basename "$file" + name=$func_basename_result + test uninstall = "$opt_mode" && odir=$dir + + # Remember odir for removal later, being careful to avoid duplicates + if test clean = "$opt_mode"; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif $rmforce; then + continue + fi + + rmfiles=$file + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case $opt_mode in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && test none != "$pic_object"; then + func_append rmfiles " $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && test none != "$non_pic_object"; then + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test clean = "$opt_mode"; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.$objext" + if test yes = "$fast_install" && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name" + fi + if test "X$noexename" != "X$name"; then + func_append rmfiles " $odir/lt-$noexename.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the $objdir's in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then + func_mode_uninstall ${1+"$@"} +fi + +test -z "$opt_mode" && { + help=$generic_help + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode '$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# where we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/dependencies/libarchive-3.4.2/build/autoconf/missing b/dependencies/libarchive-3.4.2/build/autoconf/missing new file mode 100755 index 0000000..f62bbae --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/autoconf/missing @@ -0,0 +1,215 @@ +#! /bin/sh +# Common wrapper for a few potentially missing GNU programs. + +scriptversion=2013-10-28.13; # UTC + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Originally written by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try '$0 --help' for more information" + exit 1 +fi + +case $1 in + + --is-lightweight) + # Used by our autoconf macros to check whether the available missing + # script is modern enough. + exit 0 + ;; + + --run) + # Back-compat with the calling convention used by older automake. + shift + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due +to PROGRAM being missing or too old. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal autoconf autoheader autom4te automake makeinfo + bison yacc flex lex help2man + +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" + exit 1 + ;; + +esac + +# Run the given program, remember its exit status. +"$@"; st=$? + +# If it succeeded, we are done. +test $st -eq 0 && exit 0 + +# Also exit now if we it failed (or wasn't found), and '--version' was +# passed; such an option is passed most likely to detect whether the +# program is present and works. +case $2 in --version|--help) exit $st;; esac + +# Exit code 63 means version mismatch. This often happens when the user +# tries to use an ancient version of a tool on a file that requires a +# minimum version. +if test $st -eq 63; then + msg="probably too old" +elif test $st -eq 127; then + # Program was missing. + msg="missing on your system" +else + # Program was found and executed, but failed. Give up. + exit $st +fi + +perl_URL=http://www.perl.org/ +flex_URL=http://flex.sourceforge.net/ +gnu_software_URL=http://www.gnu.org/software + +program_details () +{ + case $1 in + aclocal|automake) + echo "The '$1' program is part of the GNU Automake package:" + echo "<$gnu_software_URL/automake>" + echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/autoconf>" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + autoconf|autom4te|autoheader) + echo "The '$1' program is part of the GNU Autoconf package:" + echo "<$gnu_software_URL/autoconf/>" + echo "It also requires GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + esac +} + +give_advice () +{ + # Normalize program name to check for. + normalized_program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + + printf '%s\n' "'$1' is $msg." + + configure_deps="'configure.ac' or m4 files included by 'configure.ac'" + case $normalized_program in + autoconf*) + echo "You should only need it if you modified 'configure.ac'," + echo "or m4 files included by it." + program_details 'autoconf' + ;; + autoheader*) + echo "You should only need it if you modified 'acconfig.h' or" + echo "$configure_deps." + program_details 'autoheader' + ;; + automake*) + echo "You should only need it if you modified 'Makefile.am' or" + echo "$configure_deps." + program_details 'automake' + ;; + aclocal*) + echo "You should only need it if you modified 'acinclude.m4' or" + echo "$configure_deps." + program_details 'aclocal' + ;; + autom4te*) + echo "You might have modified some maintainer files that require" + echo "the 'autom4te' program to be rebuilt." + program_details 'autom4te' + ;; + bison*|yacc*) + echo "You should only need it if you modified a '.y' file." + echo "You may want to install the GNU Bison package:" + echo "<$gnu_software_URL/bison/>" + ;; + lex*|flex*) + echo "You should only need it if you modified a '.l' file." + echo "You may want to install the Fast Lexical Analyzer package:" + echo "<$flex_URL>" + ;; + help2man*) + echo "You should only need it if you modified a dependency" \ + "of a man page." + echo "You may want to install the GNU Help2man package:" + echo "<$gnu_software_URL/help2man/>" + ;; + makeinfo*) + echo "You should only need it if you modified a '.texi' file, or" + echo "any other file indirectly affecting the aspect of the manual." + echo "You might want to install the Texinfo package:" + echo "<$gnu_software_URL/texinfo/>" + echo "The spurious makeinfo call might also be the consequence of" + echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" + echo "want to install GNU make:" + echo "<$gnu_software_URL/make/>" + ;; + *) + echo "You might have modified some files without having the proper" + echo "tools for further handling them. Check the 'README' file, it" + echo "often tells you about the needed prerequisites for installing" + echo "this package. You may also peek at any GNU archive site, in" + echo "case some other package contains this missing '$1' program." + ;; + esac +} + +give_advice "$1" | sed -e '1s/^/WARNING: /' \ + -e '2,$s/^/ /' >&2 + +# Propagate the correct exit status (expected to be 127 for a program +# not found, 63 for a program that failed due to version mismatch). +exit $st + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/dependencies/libarchive-3.4.2/build/autoconf/test-driver b/dependencies/libarchive-3.4.2/build/autoconf/test-driver new file mode 100755 index 0000000..8e575b0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/autoconf/test-driver @@ -0,0 +1,148 @@ +#! /bin/sh +# test-driver - basic testsuite driver script. + +scriptversion=2013-07-13.22; # UTC + +# Copyright (C) 2011-2014 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +# Make unconditional expansion of undefined variables an error. This +# helps a lot in preventing typo-related bugs. +set -u + +usage_error () +{ + echo "$0: $*" >&2 + print_usage >&2 + exit 2 +} + +print_usage () +{ + cat <$log_file 2>&1 +estatus=$? + +if test $enable_hard_errors = no && test $estatus -eq 99; then + tweaked_estatus=1 +else + tweaked_estatus=$estatus +fi + +case $tweaked_estatus:$expect_failure in + 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; + 0:*) col=$grn res=PASS recheck=no gcopy=no;; + 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; + 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; + *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; + *:*) col=$red res=FAIL recheck=yes gcopy=yes;; +esac + +# Report the test outcome and exit status in the logs, so that one can +# know whether the test passed or failed simply by looking at the '.log' +# file, without the need of also peaking into the corresponding '.trs' +# file (automake bug#11814). +echo "$res $test_name (exit status: $estatus)" >>$log_file + +# Report outcome to console. +echo "${col}${res}${std}: $test_name" + +# Register the test result, and other relevant metadata. +echo ":test-result: $res" > $trs_file +echo ":global-test-result: $res" >> $trs_file +echo ":recheck: $recheck" >> $trs_file +echo ":copy-in-global-log: $gcopy" >> $trs_file + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/dependencies/libarchive-3.4.2/build/autogen.sh b/dependencies/libarchive-3.4.2/build/autogen.sh new file mode 100755 index 0000000..e720e9b --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/autogen.sh @@ -0,0 +1,68 @@ +#!/bin/sh + +PATH=/usr/local/gnu-autotools/bin/:$PATH +export PATH + +# Start from one level above the build directory +if [ -f version ]; then + cd .. +fi + +if [ \! -f build/version ]; then + echo "Can't find source directory" + exit 1 +fi + +# BSD make's "OBJDIR" support freaks out the automake-generated +# Makefile. Effectively disable it. +export MAKEOBJDIRPREFIX=/junk + +# Start from the build directory, where the version file is located +if [ -f build/version ]; then + cd build +fi + +if [ \! -f version ]; then + echo "Can't find version file" + exit 1 +fi + +# Update the build number in the 'version' file. +# Separate number from additional alpha/beta/etc marker +MARKER=`cat version | sed 's/[0-9.]//g'` +# Bump the number +VN=`cat version | sed 's/[^0-9.]//g'` +# Build out the string. +VS="$(($VN/1000000)).$(( ($VN/1000)%1000 )).$(( $VN%1000 ))$MARKER" + +cd .. + +# Clean up the source dir as much as we can. +/bin/sh build/clean.sh + +# Substitute the versions into Libarchive's archive.h and archive_entry.h +perl -p -i -e "s/^(#define\tARCHIVE_VERSION_NUMBER).*/\$1 $VN/" libarchive/archive.h +perl -p -i -e "s/^(#define\tARCHIVE_VERSION_NUMBER).*/\$1 $VN/" libarchive/archive_entry.h +perl -p -i -e "s/^(#define\tARCHIVE_VERSION_ONLY_STRING).*/\$1 \"$VS\"/" libarchive/archive.h +# Substitute versions into configure.ac as well +perl -p -i -e 's/(m4_define\(\[LIBARCHIVE_VERSION_S\]),.*\)/$1,['"$VS"'])/' configure.ac +perl -p -i -e 's/(m4_define\(\[LIBARCHIVE_VERSION_N\]),.*\)/$1,['"$VN"'])/' configure.ac + +# Remove developer CFLAGS if a release build is being made +if [ -n "${MAKE_LIBARCHIVE_RELEASE}" ]; then + perl -p -i -e "s/^(DEV_CFLAGS.*)/# \$1/" Makefile.am + perl -p -i -e 's/CMAKE_BUILD_TYPE "[A-Za-z]*"/CMAKE_BUILD_TYPE "Release"/' CMakeLists.txt +fi + +set -xe +aclocal -I build/autoconf + +# Note: --automake flag needed only for libtoolize from +# libtool 1.5.x; in libtool 2.2.x it is a synonym for --quiet +case `uname` in +Darwin) glibtoolize --automake -c;; +*) libtoolize --automake -c;; +esac +autoconf +autoheader +automake -a -c diff --git a/dependencies/libarchive-3.4.2/build/bump-version.sh b/dependencies/libarchive-3.4.2/build/bump-version.sh new file mode 100755 index 0000000..eec4235 --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/bump-version.sh @@ -0,0 +1,36 @@ +#!/bin/sh +v + +# Start from the build directory, where the version file is located +if [ -f build/version ]; then + cd build +fi + +if [ \! -f version ]; then + echo "Can't find version file" + exit 1 +fi + +# Update the build number in the 'version' file. +# Separate number from additional alpha/beta/etc marker +MARKER=`cat version | sed 's/[0-9.]//g'` +# Bump the number +VN=`cat version | sed 's/[^0-9.]//g'` +# Reassemble and write back out +VN=$(($VN + 1)) +rm -f version.old +mv version version.old +chmod +w version.old +echo $VN$MARKER > version +VS="$(($VN/1000000)).$(( ($VN/1000)%1000 )).$(( $VN%1000 ))$MARKER" +cd .. + +ANNOUNCE=`date +"%b %d, %Y:"`" libarchive $VS released" + +echo $ANNOUNCE + +# Add a version notice to NEWS +mv NEWS NEWS.bak +chmod +w NEWS.bak +echo $ANNOUNCE >> NEWS +echo >> NEWS +cat NEWS.bak >> NEWS diff --git a/dependencies/libarchive-3.4.2/build/clean.sh b/dependencies/libarchive-3.4.2/build/clean.sh new file mode 100755 index 0000000..b669426 --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/clean.sh @@ -0,0 +1,99 @@ +#!/bin/sh + +# +# Attempt to remove as many generated files as we can. +# Ideally, a well-used development sandbox would look like +# a pristine checkout after running this script. +# + +if [ \! -f build/version ]; then + echo 'Must run the clean script from the top-level dir of the libarchive distribution' 1>&2 + exit 1 +fi + +# If we're on BSD, blow away the build dir under /usr/obj +rm -rf /usr/obj`pwd` + +# +# Try to clean up a bit more... +# + +find . -name '*.So' | xargs rm -f +find . -name '*.a' | xargs rm -f +find . -name '*.la' | xargs rm -f +find . -name '*.lo' | xargs rm -f +find . -name '*.o' | xargs rm -f +find . -name '*.orig' | xargs rm -f +find . -name '*.po' | xargs rm -f +find . -name '*.rej' | xargs rm -f +find . -name '*~' | xargs rm -f +find . -name '.depend' | xargs rm -f +find . -name '.deps' | xargs rm -rf +find . -name '.dirstamp' | xargs rm -f +find . -name '.libs' | xargs rm -rf +find . -name 'CMakeFiles' | xargs rm -rf +find . -name 'cmake_install.cmake' | xargs rm -f +find . -name 'CTestTestfile.cmake' | xargs rm -f + +rm -rf Testing +rm -rf autom4te.cache +rm -rf bin +rm -rf cmake.tmp +rm -rf libarchive/Testing + +rm -f CMakeCache.txt +rm -f DartConfiguration.tcl +rm -f Makefile +rm -f Makefile.in +rm -f aclocal.m4 +rm -f bsdcpio +rm -f bsdcpio_test +rm -f bsdtar +rm -f bsdtar_test +rm -f build/autoconf/compile +rm -f build/autoconf/config.guess +rm -f build/autoconf/config.sub +rm -f build/autoconf/depcomp +rm -f build/autoconf/install-sh +rm -f build/autoconf/libtool.m4 +rm -f build/autoconf/ltmain.sh +rm -f build/autoconf/ltoptions.m4 +rm -f build/autoconf/ltsugar.m4 +rm -f build/autoconf/ltversion.m4 +rm -f build/autoconf/lt~obsolete.m4 +rm -f build/autoconf/missing +rm -f build/autoconf/test-driver +rm -f build/pkgconfig/libarchive.pc +rm -f build/version.old +rm -f cat/test/list.h +rm -f config.h +rm -f config.h.in +rm -f config.log +rm -f config.status +rm -f configure +rm -f cpio/*.1.gz +rm -f cpio/Makefile +rm -f cpio/bsdcpio +rm -f cpio/test/Makefile +rm -f cpio/test/bsdcpio_test +rm -f cpio/test/list.h +rm -f doc/html/* +rm -f doc/man/* +rm -f doc/pdf/* +rm -f doc/text/* +rm -f doc/wiki/* +rm -f libarchive/*.[35].gz +rm -f libarchive/Makefile +rm -f libarchive/libarchive.so* +rm -f libarchive/test/Makefile +rm -f libarchive/test/libarchive_test +rm -f libarchive/test/list.h +rm -f libarchive_test +rm -f libtool +rm -f stamp-h1 +rm -f tar/*.1.gz +rm -f tar/Makefile +rm -f tar/bsdtar +rm -f tar/test/Makefile +rm -f tar/test/bsdtar_test +rm -f tar/test/list.h diff --git a/dependencies/libarchive-3.4.2/build/cmake/CheckFileOffsetBits.c b/dependencies/libarchive-3.4.2/build/cmake/CheckFileOffsetBits.c new file mode 100644 index 0000000..d948fec --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/cmake/CheckFileOffsetBits.c @@ -0,0 +1,14 @@ +#include + +#define KB ((off_t)1024) +#define MB ((off_t)1024 * KB) +#define GB ((off_t)1024 * MB) +#define TB ((off_t)1024 * GB) +int t2[(((64 * GB -1) % 671088649) == 268434537) + && (((TB - (64 * GB -1) + 255) % 1792151290) == 305159546)? 1: -1]; + +int main() +{ + ; + return 0; +} diff --git a/dependencies/libarchive-3.4.2/build/cmake/CheckFileOffsetBits.cmake b/dependencies/libarchive-3.4.2/build/cmake/CheckFileOffsetBits.cmake new file mode 100644 index 0000000..b347c93 --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/cmake/CheckFileOffsetBits.cmake @@ -0,0 +1,44 @@ +# - Check if _FILE_OFFSET_BITS macro needed for large files +# CHECK_FILE_OFFSET_BITS () +# +# The following variables may be set before calling this macro to +# modify the way the check is run: +# +# CMAKE_REQUIRED_FLAGS = string of compile command line flags +# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar) +# CMAKE_REQUIRED_INCLUDES = list of include directories +# Copyright (c) 2009, Michihiro NAKAJIMA +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +#INCLUDE(CheckCXXSourceCompiles) + +GET_FILENAME_COMPONENT(_selfdir_CheckFileOffsetBits + "${CMAKE_CURRENT_LIST_FILE}" PATH) + +MACRO (CHECK_FILE_OFFSET_BITS) + IF(NOT DEFINED _FILE_OFFSET_BITS) + MESSAGE(STATUS "Checking _FILE_OFFSET_BITS for large files") + TRY_COMPILE(__WITHOUT_FILE_OFFSET_BITS_64 + ${CMAKE_CURRENT_BINARY_DIR} + ${_selfdir_CheckFileOffsetBits}/CheckFileOffsetBits.c + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}) + IF(NOT __WITHOUT_FILE_OFFSET_BITS_64) + TRY_COMPILE(__WITH_FILE_OFFSET_BITS_64 + ${CMAKE_CURRENT_BINARY_DIR} + ${_selfdir_CheckFileOffsetBits}/CheckFileOffsetBits.c + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -D_FILE_OFFSET_BITS=64) + ENDIF(NOT __WITHOUT_FILE_OFFSET_BITS_64) + + IF(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64) + SET(_FILE_OFFSET_BITS 64 CACHE INTERNAL "_FILE_OFFSET_BITS macro needed for large files") + MESSAGE(STATUS "Checking _FILE_OFFSET_BITS for large files - needed") + ELSE(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64) + SET(_FILE_OFFSET_BITS "" CACHE INTERNAL "_FILE_OFFSET_BITS macro needed for large files") + MESSAGE(STATUS "Checking _FILE_OFFSET_BITS for large files - not needed") + ENDIF(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64) + ENDIF(NOT DEFINED _FILE_OFFSET_BITS) + +ENDMACRO (CHECK_FILE_OFFSET_BITS) + diff --git a/dependencies/libarchive-3.4.2/build/cmake/CheckFuncs.cmake b/dependencies/libarchive-3.4.2/build/cmake/CheckFuncs.cmake new file mode 100644 index 0000000..0670df9 --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/cmake/CheckFuncs.cmake @@ -0,0 +1,49 @@ +# Check if the system has the specified function; treat glibc "stub" +# functions as nonexistent: +# CHECK_FUNCTION_EXISTS_GLIBC (FUNCTION FUNCVAR) +# +# FUNCTION - the function(s) where the prototype should be declared +# FUNCVAR - variable to define if the function does exist +# +# In particular, this understands the glibc convention of +# defining macros __stub_XXXX or __stub___XXXX if the function +# does appear in the library but is merely a stub that does nothing. +# By detecting this case, we can select alternate behavior on +# platforms that don't support this functionality. +# +# The following variables may be set before calling this macro to +# modify the way the check is run: +# +# CMAKE_REQUIRED_FLAGS = string of compile command line flags +# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar) +# CMAKE_REQUIRED_INCLUDES = list of include directories +# Copyright (c) 2009, Michihiro NAKAJIMA +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +INCLUDE(CheckFunctionExists) +GET_FILENAME_COMPONENT(_selfdir_CheckFunctionExistsGlibc + "${CMAKE_CURRENT_LIST_FILE}" PATH) + +MACRO (CHECK_FUNCTION_EXISTS_GLIBC _FUNC _FUNCVAR) + IF(NOT DEFINED ${_FUNCVAR}) + SET(CHECK_STUB_FUNC_1 "__stub_${_FUNC}") + SET(CHECK_STUB_FUNC_2 "__stub___${_FUNC}") + CONFIGURE_FILE( ${_selfdir_CheckFunctionExistsGlibc}/CheckFuncs_stub.c.in + ${CMAKE_CURRENT_BINARY_DIR}/cmake.tmp/CheckFuncs_stub.c IMMEDIATE) + TRY_COMPILE(__stub + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/cmake.tmp/CheckFuncs_stub.c + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + CMAKE_FLAGS + -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_INCLUDE_FILE_FLAGS} + "${CHECK_INCLUDE_FILE_C_INCLUDE_DIRS}") + IF (__stub) + SET("${_FUNCVAR}" "" CACHE INTERNAL "Have function ${_FUNC}") + ELSE (__stub) + CHECK_FUNCTION_EXISTS("${_FUNC}" "${_FUNCVAR}") + ENDIF (__stub) + ENDIF(NOT DEFINED ${_FUNCVAR}) +ENDMACRO (CHECK_FUNCTION_EXISTS_GLIBC) + diff --git a/dependencies/libarchive-3.4.2/build/cmake/CheckFuncs_stub.c.in b/dependencies/libarchive-3.4.2/build/cmake/CheckFuncs_stub.c.in new file mode 100644 index 0000000..50da414 --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/cmake/CheckFuncs_stub.c.in @@ -0,0 +1,16 @@ +#ifdef __STDC__ +#include +#else +#include +#endif + +int +main() +{ +#if defined ${CHECK_STUB_FUNC_1} || defined ${CHECK_STUB_FUNC_2} + return 0; +#else +this system have stub + return 0; +#endif +} diff --git a/dependencies/libarchive-3.4.2/build/cmake/CheckHeaderDirent.cmake b/dependencies/libarchive-3.4.2/build/cmake/CheckHeaderDirent.cmake new file mode 100644 index 0000000..e9a7ea8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/cmake/CheckHeaderDirent.cmake @@ -0,0 +1,32 @@ +# - Check if the system has the specified type +# CHECK_HEADER_DIRENT (HEADER1 HEARDER2 ...) +# +# HEADER - the header(s) where the prototype should be declared +# +# The following variables may be set before calling this macro to +# modify the way the check is run: +# +# CMAKE_REQUIRED_FLAGS = string of compile command line flags +# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar) +# CMAKE_REQUIRED_INCLUDES = list of include directories +# Copyright (c) 2009, Michihiro NAKAJIMA +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + + +INCLUDE(CheckTypeExists) + +MACRO (CHECK_HEADER_DIRENT) + CHECK_TYPE_EXISTS("DIR *" dirent.h HAVE_DIRENT_H) + IF(NOT HAVE_DIRENT_H) + CHECK_TYPE_EXISTS("DIR *" sys/ndir.h HAVE_SYS_NDIR_H) + IF(NOT HAVE_SYS_NDIR_H) + CHECK_TYPE_EXISTS("DIR *" ndir.h HAVE_NDIR_H) + IF(NOT HAVE_NDIR_H) + CHECK_TYPE_EXISTS("DIR *" sys/dir.h HAVE_SYS_DIR_H) + ENDIF(NOT HAVE_NDIR_H) + ENDIF(NOT HAVE_SYS_NDIR_H) + ENDIF(NOT HAVE_DIRENT_H) +ENDMACRO (CHECK_HEADER_DIRENT) + diff --git a/dependencies/libarchive-3.4.2/build/cmake/CheckTypeExists.cmake b/dependencies/libarchive-3.4.2/build/cmake/CheckTypeExists.cmake new file mode 100644 index 0000000..b05234f --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/cmake/CheckTypeExists.cmake @@ -0,0 +1,42 @@ +# - Check if the system has the specified type +# CHECK_TYPE_EXISTS (TYPE HEADER VARIABLE) +# +# TYPE - the name of the type or struct or class you are interested in +# HEADER - the header(s) where the prototype should be declared +# VARIABLE - variable to store the result +# +# The following variables may be set before calling this macro to +# modify the way the check is run: +# +# CMAKE_REQUIRED_FLAGS = string of compile command line flags +# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar) +# CMAKE_REQUIRED_INCLUDES = list of include directories +# Copyright (c) 2009, Michihiro NAKAJIMA +# Copyright (c) 2006, Alexander Neundorf, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + + +INCLUDE(CheckCSourceCompiles) + +MACRO (CHECK_TYPE_EXISTS _TYPE _HEADER _RESULT) + SET(_INCLUDE_FILES) + FOREACH (it ${_HEADER}) + SET(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n") + ENDFOREACH (it) + + SET(_CHECK_TYPE_EXISTS_SOURCE_CODE " +${_INCLUDE_FILES} +int main() +{ + static ${_TYPE} tmp; + if (sizeof(tmp)) + return 0; + return 0; +} +") + CHECK_C_SOURCE_COMPILES("${_CHECK_TYPE_EXISTS_SOURCE_CODE}" ${_RESULT}) + +ENDMACRO (CHECK_TYPE_EXISTS) + diff --git a/dependencies/libarchive-3.4.2/build/cmake/CreatePkgConfigFile.cmake b/dependencies/libarchive-3.4.2/build/cmake/CreatePkgConfigFile.cmake new file mode 100644 index 0000000..fc8529a --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/cmake/CreatePkgConfigFile.cmake @@ -0,0 +1,33 @@ +# - Generate a libarchive.pc like autotools for pkg-config +# + +# Set the required variables (we use the same input file as autotools) +SET(prefix ${CMAKE_INSTALL_PREFIX}) +SET(exec_prefix \${prefix}) +SET(libdir \${exec_prefix}/lib) +SET(includedir \${prefix}/include) +# Now, this is not particularly pretty, nor is it terribly accurate... +# Loop over all our additional libs +FOREACH(mylib ${ADDITIONAL_LIBS}) + # Extract the filename from the absolute path + GET_FILENAME_COMPONENT(mylib_name ${mylib} NAME_WE) + # Strip the lib prefix + STRING(REGEX REPLACE "^lib" "" mylib_name ${mylib_name}) + # Append it to our LIBS string + SET(LIBS "${LIBS} -l${mylib_name}") +ENDFOREACH() +# libxml2 is easier, since it's already using pkg-config +FOREACH(mylib ${PC_LIBXML_STATIC_LDFLAGS}) + SET(LIBS "${LIBS} ${mylib}") +ENDFOREACH() +# FIXME: The order of the libraries doesn't take dependencies into account, +# thus there's a good chance it'll make some binutils versions unhappy... +# This only affects Libs.private (looked up for static builds) though. +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/pkgconfig/libarchive.pc.in + ${CMAKE_CURRENT_SOURCE_DIR}/build/pkgconfig/libarchive.pc + @ONLY) +# And install it, of course ;). +IF(ENABLE_INSTALL) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/build/pkgconfig/libarchive.pc + DESTINATION "lib/pkgconfig") +ENDIF() diff --git a/dependencies/libarchive-3.4.2/build/cmake/FindLibGCC.cmake b/dependencies/libarchive-3.4.2/build/cmake/FindLibGCC.cmake new file mode 100644 index 0000000..5883ff8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/cmake/FindLibGCC.cmake @@ -0,0 +1,22 @@ +# - Find libgcc +# Find the libgcc library. +# +# LIBGCC_LIBRARIES - List of libraries when using libgcc +# LIBGCC_FOUND - True if libgcc found. + +IF (LIBGCC_LIBRARY) + # Already in cache, be silent + SET(LIBGCC_FIND_QUIETLY TRUE) +ENDIF (LIBGCC_LIBRARY) + +FIND_LIBRARY(LIBGCC_LIBRARY NAMES gcc libgcc) + +# handle the QUIETLY and REQUIRED arguments and set LIBGCC_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBGCC DEFAULT_MSG LIBGCC_LIBRARY) + +IF(LIBGCC_FOUND) + SET(LIBGCC_LIBRARIES ${LIBGCC_LIBRARY}) + SET(HAVE_LIBGCC 1) +ENDIF(LIBGCC_FOUND) diff --git a/dependencies/libarchive-3.4.2/build/cmake/FindMbedTLS.cmake b/dependencies/libarchive-3.4.2/build/cmake/FindMbedTLS.cmake new file mode 100644 index 0000000..a916395 --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/cmake/FindMbedTLS.cmake @@ -0,0 +1,13 @@ +find_path(MBEDTLS_INCLUDE_DIRS mbedtls/ssl.h) + +find_library(MBEDTLS_LIBRARY mbedtls) +find_library(MBEDX509_LIBRARY mbedx509) +find_library(MBEDCRYPTO_LIBRARY mbedcrypto) + +set(MBEDTLS_LIBRARIES "${MBEDTLS_LIBRARY}" "${MBEDX509_LIBRARY}" "${MBEDCRYPTO_LIBRARY}") + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(MBEDTLS DEFAULT_MSG + MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY) + +mark_as_advanced(MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY) diff --git a/dependencies/libarchive-3.4.2/build/cmake/FindNettle.cmake b/dependencies/libarchive-3.4.2/build/cmake/FindNettle.cmake new file mode 100644 index 0000000..54ec9f5 --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/cmake/FindNettle.cmake @@ -0,0 +1,23 @@ +# - Find Nettle +# Find the Nettle include directory and library +# +# NETTLE_INCLUDE_DIR - where to find , etc. +# NETTLE_LIBRARIES - List of libraries when using libnettle. +# NETTLE_FOUND - True if libnettle found. + +IF (NETTLE_INCLUDE_DIR) + # Already in cache, be silent + SET(NETTLE_FIND_QUIETLY TRUE) +ENDIF (NETTLE_INCLUDE_DIR) + +FIND_PATH(NETTLE_INCLUDE_DIR nettle/md5.h nettle/ripemd160.h nettle/sha.h) +FIND_LIBRARY(NETTLE_LIBRARY NAMES nettle libnettle) + +# handle the QUIETLY and REQUIRED arguments and set NETTLE_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(NETTLE DEFAULT_MSG NETTLE_LIBRARY NETTLE_INCLUDE_DIR) + +IF(NETTLE_FOUND) + SET(NETTLE_LIBRARIES ${NETTLE_LIBRARY}) +ENDIF(NETTLE_FOUND) diff --git a/dependencies/libarchive-3.4.2/build/cmake/FindPCREPOSIX.cmake b/dependencies/libarchive-3.4.2/build/cmake/FindPCREPOSIX.cmake new file mode 100644 index 0000000..56cc17e --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/cmake/FindPCREPOSIX.cmake @@ -0,0 +1,34 @@ +# - Find pcreposix +# Find the native PCRE and PCREPOSIX include and libraries +# +# PCRE_INCLUDE_DIR - where to find pcreposix.h, etc. +# PCREPOSIX_LIBRARIES - List of libraries when using libpcreposix. +# PCRE_LIBRARIES - List of libraries when using libpcre. +# PCREPOSIX_FOUND - True if libpcreposix found. +# PCRE_FOUND - True if libpcre found. + +IF (PCRE_INCLUDE_DIR) + # Already in cache, be silent + SET(PCRE_FIND_QUIETLY TRUE) +ENDIF (PCRE_INCLUDE_DIR) + +FIND_PATH(PCRE_INCLUDE_DIR pcreposix.h) +FIND_LIBRARY(PCREPOSIX_LIBRARY NAMES pcreposix libpcreposix) +FIND_LIBRARY(PCRE_LIBRARY NAMES pcre libpcre) + +# handle the QUIETLY and REQUIRED arguments and set PCREPOSIX_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCREPOSIX DEFAULT_MSG PCREPOSIX_LIBRARY PCRE_INCLUDE_DIR) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE DEFAULT_MSG PCRE_LIBRARY) + +IF(PCREPOSIX_FOUND) + SET(PCREPOSIX_LIBRARIES ${PCREPOSIX_LIBRARY}) + SET(HAVE_LIBPCREPOSIX 1) + SET(HAVE_PCREPOSIX_H 1) +ENDIF(PCREPOSIX_FOUND) + +IF(PCRE_FOUND) + SET(PCRE_LIBRARIES ${PCRE_LIBRARY}) + SET(HAVE_LIBPCRE 1) +ENDIF(PCRE_FOUND) diff --git a/dependencies/libarchive-3.4.2/build/cmake/LibarchiveCodeCoverage.cmake b/dependencies/libarchive-3.4.2/build/cmake/LibarchiveCodeCoverage.cmake new file mode 100644 index 0000000..297b886 --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/cmake/LibarchiveCodeCoverage.cmake @@ -0,0 +1,68 @@ +################################################################# +# Adds a build target called "coverage" for code coverage. +# +# This compiles the code using special GCC flags, run the tests, +# and then generates a nice HTML output. This new "coverage" make +# target will only be available if you build using GCC in Debug +# mode. If any of the required programs (lcov and genhtml) were +# not found, a FATAL_ERROR message is printed. +# +# If not already done, this code will set ENABLE_TEST to ON. +# +# To build the code coverage and open it in your browser do this: +# +# mkdir debug +# cd debug +# cmake -DCMAKE_BUILD_TYPE=Debug -DENABLE_COVERAGE=ON .. +# make -j4 +# make coverage +# xdg-open coverage/index.html +################################################################# + +# Find programs we need +FIND_PROGRAM(LCOV_EXECUTABLE lcov DOC "Full path to lcov executable") +FIND_PROGRAM(GENHTML_EXECUTABLE genhtml DOC "Full path to genhtml executable") +MARK_AS_ADVANCED(LCOV_EXECUTABLE GENHTML_EXECUTABLE) + +# Check, compiler, build types and programs are available +IF(NOT CMAKE_COMPILER_IS_GNUCC) +MESSAGE(FATAL_ERROR "Coverage can only be built on GCC") +ELSEIF(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") +MESSAGE(FATAL_ERROR "Coverage can only be built in Debug mode") +ELSEIF(NOT LCOV_EXECUTABLE) +MESSAGE(FATAL_ERROR "lcov executable not found") +ELSEIF(NOT GENHTML_EXECUTABLE) +MESSAGE(FATAL_ERROR "genhtml executable not found") +ENDIF(NOT CMAKE_COMPILER_IS_GNUCC) + +# Enable testing if not already done +SET(ENABLE_TEST ON) + +################################################################# +# Set special compiler and linker flags for test coverage +################################################################# +# 0. Enable debug: -g +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g") +# 1. Disable optimizations: -O0 +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0") +# 2. Enable all kind of warnings: +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -W") +# 3. Enable special coverage flag (HINT: --coverage is a synonym for -fprofile-arcs -ftest-coverage) +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage") +SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --coverage") +SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") +################################################################# + +ADD_CUSTOM_TARGET(coverage +COMMAND ${CMAKE_COMMAND} -E echo "Beginning test coverage. Output is written to coverage.log." +COMMAND ${CMAKE_COMMAND} -E echo "COVERAGE-STEP-1/5: Reset all execution counts to zero" +COMMAND ${LCOV_EXECUTABLE} --directory . --zerocounters > coverage.log 2>&1 +COMMAND ${CMAKE_COMMAND} -E echo "COVERAGE-STEP-2/5: Run testrunner" +COMMAND ${CMAKE_CTEST_COMMAND} >> coverage.log 2>&1 +COMMAND ${CMAKE_COMMAND} -E echo "COVERAGE-STEP-3/5: Collect coverage data" +COMMAND ${LCOV_EXECUTABLE} --capture --directory . --output-file "./coverage.info" >> coverage.log 2>&1 +COMMAND ${CMAKE_COMMAND} -E echo "COVERAGE-STEP-4/5: Generate HTML from coverage data" +COMMAND ${GENHTML_EXECUTABLE} "coverage.info" --title="libarchive-${LIBARCHIVE_VERSION_STRING}" --show-details --legend --output-directory "./coverage" >> coverage.log 2>&1 +COMMAND ${CMAKE_COMMAND} -E echo "COVERAGE-STEP-5/5: Open test coverage HTML output in browser: xdg-open ./coverage/index.html" +COMMENT "Runs testrunner and generates coverage output (formats: .info and .html)") + diff --git a/dependencies/libarchive-3.4.2/build/cmake/config.h.in b/dependencies/libarchive-3.4.2/build/cmake/config.h.in new file mode 100644 index 0000000..fcbd80c --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/cmake/config.h.in @@ -0,0 +1,1338 @@ +/* config.h. Generated from build/cmake/config.h.in by cmake configure */ + +/* + * Ensure we have C99-style int64_t, etc, all defined. + */ + +/* First, we need to know if the system has already defined them. */ +#cmakedefine HAVE_INT16_T +#cmakedefine HAVE_INT32_T +#cmakedefine HAVE_INT64_T +#cmakedefine HAVE_INTMAX_T + +#cmakedefine HAVE_UINT8_T +#cmakedefine HAVE_UINT16_T +#cmakedefine HAVE_UINT32_T +#cmakedefine HAVE_UINT64_T +#cmakedefine HAVE_UINTMAX_T + +/* We might have the types we want under other spellings. */ +#cmakedefine HAVE___INT64 +#cmakedefine HAVE_U_INT64_T +#cmakedefine HAVE_UNSIGNED___INT64 + +/* The sizes of various standard integer types. */ +@SIZE_OF_SHORT_CODE@ +@SIZE_OF_INT_CODE@ +@SIZE_OF_LONG_CODE@ +@SIZE_OF_LONG_LONG_CODE@ +@SIZE_OF_UNSIGNED_SHORT_CODE@ +@SIZE_OF_UNSIGNED_CODE@ +@SIZE_OF_UNSIGNED_LONG_CODE@ +@SIZE_OF_UNSIGNED_LONG_LONG_CODE@ + +/* + * If we lack int64_t, define it to the first of __int64, int, long, and long long + * that exists and is the right size. + */ +#if !defined(HAVE_INT64_T) && defined(HAVE___INT64) +typedef __int64 int64_t; +#define HAVE_INT64_T +#endif + +#if !defined(HAVE_INT64_T) && SIZE_OF_INT == 8 +typedef int int64_t; +#define HAVE_INT64_T +#endif + +#if !defined(HAVE_INT64_T) && SIZE_OF_LONG == 8 +typedef long int64_t; +#define HAVE_INT64_T +#endif + +#if !defined(HAVE_INT64_T) && SIZE_OF_LONG_LONG == 8 +typedef long long int64_t; +#define HAVE_INT64_T +#endif + +#if !defined(HAVE_INT64_T) +#error No 64-bit integer type was found. +#endif + +/* + * Similarly for int32_t + */ +#if !defined(HAVE_INT32_T) && SIZE_OF_INT == 4 +typedef int int32_t; +#define HAVE_INT32_T +#endif + +#if !defined(HAVE_INT32_T) && SIZE_OF_LONG == 4 +typedef long int32_t; +#define HAVE_INT32_T +#endif + +#if !defined(HAVE_INT32_T) +#error No 32-bit integer type was found. +#endif + +/* + * Similarly for int16_t + */ +#if !defined(HAVE_INT16_T) && SIZE_OF_INT == 2 +typedef int int16_t; +#define HAVE_INT16_T +#endif + +#if !defined(HAVE_INT16_T) && SIZE_OF_SHORT == 2 +typedef short int16_t; +#define HAVE_INT16_T +#endif + +#if !defined(HAVE_INT16_T) +#error No 16-bit integer type was found. +#endif + +/* + * Similarly for uint64_t + */ +#if !defined(HAVE_UINT64_T) && defined(HAVE_UNSIGNED___INT64) +typedef unsigned __int64 uint64_t; +#define HAVE_UINT64_T +#endif + +#if !defined(HAVE_UINT64_T) && SIZE_OF_UNSIGNED == 8 +typedef unsigned uint64_t; +#define HAVE_UINT64_T +#endif + +#if !defined(HAVE_UINT64_T) && SIZE_OF_UNSIGNED_LONG == 8 +typedef unsigned long uint64_t; +#define HAVE_UINT64_T +#endif + +#if !defined(HAVE_UINT64_T) && SIZE_OF_UNSIGNED_LONG_LONG == 8 +typedef unsigned long long uint64_t; +#define HAVE_UINT64_T +#endif + +#if !defined(HAVE_UINT64_T) +#error No 64-bit unsigned integer type was found. +#endif + + +/* + * Similarly for uint32_t + */ +#if !defined(HAVE_UINT32_T) && SIZE_OF_UNSIGNED == 4 +typedef unsigned uint32_t; +#define HAVE_UINT32_T +#endif + +#if !defined(HAVE_UINT32_T) && SIZE_OF_UNSIGNED_LONG == 4 +typedef unsigned long uint32_t; +#define HAVE_UINT32_T +#endif + +#if !defined(HAVE_UINT32_T) +#error No 32-bit unsigned integer type was found. +#endif + +/* + * Similarly for uint16_t + */ +#if !defined(HAVE_UINT16_T) && SIZE_OF_UNSIGNED == 2 +typedef unsigned uint16_t; +#define HAVE_UINT16_T +#endif + +#if !defined(HAVE_UINT16_T) && SIZE_OF_UNSIGNED_SHORT == 2 +typedef unsigned short uint16_t; +#define HAVE_UINT16_T +#endif + +#if !defined(HAVE_UINT16_T) +#error No 16-bit unsigned integer type was found. +#endif + +/* + * Similarly for uint8_t + */ +#if !defined(HAVE_UINT8_T) +typedef unsigned char uint8_t; +#define HAVE_UINT8_T +#endif + +#if !defined(HAVE_UINT16_T) +#error No 8-bit unsigned integer type was found. +#endif + +/* Define intmax_t and uintmax_t if they are not already defined. */ +#if !defined(HAVE_INTMAX_T) +typedef int64_t intmax_t; +#endif + +#if !defined(HAVE_UINTMAX_T) +typedef uint64_t uintmax_t; +#endif + +/* Define ZLIB_WINAPI if zlib was built on Visual Studio. */ +#cmakedefine ZLIB_WINAPI 1 + +/* Darwin ACL support */ +#cmakedefine ARCHIVE_ACL_DARWIN 1 + +/* FreeBSD ACL support */ +#cmakedefine ARCHIVE_ACL_FREEBSD 1 + +/* FreeBSD NFSv4 ACL support */ +#cmakedefine ARCHIVE_ACL_FREEBSD_NFS4 1 + +/* Linux POSIX.1e ACL support via libacl */ +#cmakedefine ARCHIVE_ACL_LIBACL 1 + +/* Linux NFSv4 ACL support via librichacl */ +#cmakedefine ARCHIVE_ACL_LIBRICHACL 1 + +/* Solaris ACL support */ +#cmakedefine ARCHIVE_ACL_SUNOS 1 + +/* Solaris NFSv4 ACL support */ +#cmakedefine ARCHIVE_ACL_SUNOS_NFS4 1 + +/* MD5 via ARCHIVE_CRYPTO_MD5_LIBC supported. */ +#cmakedefine ARCHIVE_CRYPTO_MD5_LIBC 1 + +/* MD5 via ARCHIVE_CRYPTO_MD5_LIBSYSTEM supported. */ +#cmakedefine ARCHIVE_CRYPTO_MD5_LIBSYSTEM 1 + +/* MD5 via ARCHIVE_CRYPTO_MD5_NETTLE supported. */ +#cmakedefine ARCHIVE_CRYPTO_MD5_NETTLE 1 + +/* MD5 via ARCHIVE_CRYPTO_MD5_OPENSSL supported. */ +#cmakedefine ARCHIVE_CRYPTO_MD5_OPENSSL 1 + +/* MD5 via ARCHIVE_CRYPTO_MD5_WIN supported. */ +#cmakedefine ARCHIVE_CRYPTO_MD5_WIN 1 + +/* RMD160 via ARCHIVE_CRYPTO_RMD160_LIBC supported. */ +#cmakedefine ARCHIVE_CRYPTO_RMD160_LIBC 1 + +/* RMD160 via ARCHIVE_CRYPTO_RMD160_NETTLE supported. */ +#cmakedefine ARCHIVE_CRYPTO_RMD160_NETTLE 1 + +/* RMD160 via ARCHIVE_CRYPTO_RMD160_OPENSSL supported. */ +#cmakedefine ARCHIVE_CRYPTO_RMD160_OPENSSL 1 + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBC supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA1_LIBC 1 + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBSYSTEM supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA1_LIBSYSTEM 1 + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_NETTLE supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA1_NETTLE 1 + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_OPENSSL supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA1_OPENSSL 1 + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_WIN supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA1_WIN 1 + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA256_LIBC 1 + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC2 supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA256_LIBC2 1 + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC3 supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA256_LIBC3 1 + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBSYSTEM supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA256_LIBSYSTEM 1 + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_NETTLE supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA256_NETTLE 1 + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_OPENSSL supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA256_OPENSSL 1 + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_WIN supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA256_WIN 1 + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA384_LIBC 1 + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC2 supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA384_LIBC2 1 + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC3 supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA384_LIBC3 1 + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBSYSTEM supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA384_LIBSYSTEM 1 + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_NETTLE supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA384_NETTLE 1 + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_OPENSSL supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA384_OPENSSL 1 + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_WIN supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA384_WIN 1 + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA512_LIBC 1 + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC2 supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA512_LIBC2 1 + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC3 supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA512_LIBC3 1 + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBSYSTEM supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA512_LIBSYSTEM 1 + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_NETTLE supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA512_NETTLE 1 + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_OPENSSL supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA512_OPENSSL 1 + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_WIN supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA512_WIN 1 + +/* AIX xattr support */ +#cmakedefine ARCHIVE_XATTR_AIX 1 + +/* Darwin xattr support */ +#cmakedefine ARCHIVE_XATTR_DARWIN 1 + +/* FreeBSD xattr support */ +#cmakedefine ARCHIVE_XATTR_FREEBSD 1 + +/* Linux xattr support */ +#cmakedefine ARCHIVE_XATTR_LINUX 1 + +/* Version number of bsdcpio */ +#cmakedefine BSDCPIO_VERSION_STRING "${BSDCPIO_VERSION_STRING}" + +/* Version number of bsdtar */ +#cmakedefine BSDTAR_VERSION_STRING "${BSDTAR_VERSION_STRING}" + +/* Version number of bsdcat */ +#cmakedefine BSDCAT_VERSION_STRING "${BSDCAT_VERSION_STRING}" + +/* Define to 1 if you have the `acl_create_entry' function. */ +#cmakedefine HAVE_ACL_CREATE_ENTRY 1 + +/* Define to 1 if you have the `acl_get_fd_np' function. */ +#cmakedefine HAVE_ACL_GET_FD_NP 1 + +/* Define to 1 if you have the `acl_get_link' function. */ +#cmakedefine HAVE_ACL_GET_LINK 1 + +/* Define to 1 if you have the `acl_get_link_np' function. */ +#cmakedefine HAVE_ACL_GET_LINK_NP 1 + +/* Define to 1 if you have the `acl_get_perm' function. */ +#cmakedefine HAVE_ACL_GET_PERM 1 + +/* Define to 1 if you have the `acl_get_perm_np' function. */ +#cmakedefine HAVE_ACL_GET_PERM_NP 1 + +/* Define to 1 if you have the `acl_init' function. */ +#cmakedefine HAVE_ACL_INIT 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ACL_LIBACL_H 1 + +/* Define to 1 if the system has the type `acl_permset_t'. */ +#cmakedefine HAVE_ACL_PERMSET_T 1 + +/* Define to 1 if you have the `acl_set_fd' function. */ +#cmakedefine HAVE_ACL_SET_FD 1 + +/* Define to 1 if you have the `acl_set_fd_np' function. */ +#cmakedefine HAVE_ACL_SET_FD_NP 1 + +/* Define to 1 if you have the `acl_set_file' function. */ +#cmakedefine HAVE_ACL_SET_FILE 1 + +/* Define to 1 if you have the `arc4random_buf' function. */ +#cmakedefine HAVE_ARC4RANDOM_BUF 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ATTR_XATTR_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_BCRYPT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_BSDXML_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_BZLIB_H 1 + +/* Define to 1 if you have the `chflags' function. */ +#cmakedefine HAVE_CHFLAGS 1 + +/* Define to 1 if you have the `chown' function. */ +#cmakedefine HAVE_CHOWN 1 + +/* Define to 1 if you have the `chroot' function. */ +#cmakedefine HAVE_CHROOT 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_COPYFILE_H 1 + +/* Define to 1 if you have the `ctime_r' function. */ +#cmakedefine HAVE_CTIME_R 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_CTYPE_H 1 + +/* Define to 1 if you have the `cygwin_conv_path' function. */ +#cmakedefine HAVE_CYGWIN_CONV_PATH 1 + +/* Define to 1 if you have the declaration of `ACE_GETACL', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_ACE_GETACL 1 + +/* Define to 1 if you have the declaration of `ACE_GETACLCNT', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_ACE_GETACLCNT 1 + +/* Define to 1 if you have the declaration of `ACE_SETACL', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_ACE_SETACL 1 + +/* Define to 1 if you have the declaration of `ACL_SYNCHRONIZE', and to 0 if + you don't. */ +#cmakedefine HAVE_DECL_ACL_SYNCHRONIZE 1 + +/* Define to 1 if you have the declaration of `ACL_TYPE_EXTENDED', and to 0 if + you don't. */ +#cmakedefine HAVE_DECL_ACL_TYPE_EXTENDED 1 + +/* Define to 1 if you have the declaration of `ACL_TYPE_NFS4', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_ACL_TYPE_NFS4 1 + +/* Define to 1 if you have the declaration of `ACL_USER', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_ACL_USER 1 + +/* Define to 1 if you have the declaration of `INT32_MAX', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_INT32_MAX 1 + +/* Define to 1 if you have the declaration of `INT32_MIN', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_INT32_MIN 1 + +/* Define to 1 if you have the declaration of `INT64_MAX', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_INT64_MAX 1 + +/* Define to 1 if you have the declaration of `INT64_MIN', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_INT64_MIN 1 + +/* Define to 1 if you have the declaration of `INTMAX_MAX', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_INTMAX_MAX 1 + +/* Define to 1 if you have the declaration of `INTMAX_MIN', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_INTMAX_MIN 1 + +/* Define to 1 if you have the declaration of `SETACL', and to 0 if you don't. + */ +#cmakedefine HAVE_DECL_SETACL 1 + +/* Define to 1 if you have the declaration of `SIZE_MAX', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_SIZE_MAX 1 + +/* Define to 1 if you have the declaration of `SSIZE_MAX', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_SSIZE_MAX 1 + +/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_STRERROR_R 1 + +/* Define to 1 if you have the declaration of `UINT32_MAX', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_UINT32_MAX 1 + +/* Define to 1 if you have the declaration of `UINT64_MAX', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_UINT64_MAX 1 + +/* Define to 1 if you have the declaration of `UINTMAX_MAX', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_UINTMAX_MAX 1 + +/* Define to 1 if you have the declaration of `XATTR_NOFOLLOW', and to 0 if + you don't. */ +#cmakedefine HAVE_DECL_XATTR_NOFOLLOW 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_DIRECT_H 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#cmakedefine HAVE_DIRENT_H 1 + +/* Define to 1 if you have the `dirfd' function. */ +#cmakedefine HAVE_DIRFD 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_DLFCN_H 1 + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +#cmakedefine HAVE_DOPRNT 1 + +/* Define to 1 if nl_langinfo supports D_MD_ORDER */ +#cmakedefine HAVE_D_MD_ORDER 1 + +/* A possible errno value for invalid file format errors */ +#cmakedefine HAVE_EFTYPE 1 + +/* A possible errno value for invalid file format errors */ +#cmakedefine HAVE_EILSEQ 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_EXPAT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_EXT2FS_EXT2_FS_H 1 + +/* Define to 1 if you have the `extattr_get_file' function. */ +#cmakedefine HAVE_EXTATTR_GET_FILE 1 + +/* Define to 1 if you have the `extattr_list_file' function. */ +#cmakedefine HAVE_EXTATTR_LIST_FILE 1 + +/* Define to 1 if you have the `extattr_set_fd' function. */ +#cmakedefine HAVE_EXTATTR_SET_FD 1 + +/* Define to 1 if you have the `extattr_set_file' function. */ +#cmakedefine HAVE_EXTATTR_SET_FILE 1 + +/* Define to 1 if EXTATTR_NAMESPACE_USER is defined in sys/extattr.h. */ +#cmakedefine HAVE_DECL_EXTATTR_NAMESPACE_USER 1 + +/* Define to 1 if you have the declaration of `GETACL', and to 0 if you don't. + */ +#cmakedefine HAVE_DECL_GETACL 1 + +/* Define to 1 if you have the declaration of `GETACLCNT', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_GETACLCNT 1 + +/* Define to 1 if you have the `fchdir' function. */ +#cmakedefine HAVE_FCHDIR 1 + +/* Define to 1 if you have the `fchflags' function. */ +#cmakedefine HAVE_FCHFLAGS 1 + +/* Define to 1 if you have the `fchmod' function. */ +#cmakedefine HAVE_FCHMOD 1 + +/* Define to 1 if you have the `fchown' function. */ +#cmakedefine HAVE_FCHOWN 1 + +/* Define to 1 if you have the `fcntl' function. */ +#cmakedefine HAVE_FCNTL 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `fdopendir' function. */ +#cmakedefine HAVE_FDOPENDIR 1 + +/* Define to 1 if you have the `fgetea' function. */ +#cmakedefine HAVE_FGETEA 1 + +/* Define to 1 if you have the `fgetxattr' function. */ +#cmakedefine HAVE_FGETXATTR 1 + +/* Define to 1 if you have the `flistea' function. */ +#cmakedefine HAVE_FLISTEA 1 + +/* Define to 1 if you have the `flistxattr' function. */ +#cmakedefine HAVE_FLISTXATTR 1 + +/* Define to 1 if you have the `fork' function. */ +#cmakedefine HAVE_FORK 1 + +/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ +#cmakedefine HAVE_FSEEKO 1 + +/* Define to 1 if you have the `fsetea' function. */ +#cmakedefine HAVE_FSETEA 1 + +/* Define to 1 if you have the `fsetxattr' function. */ +#cmakedefine HAVE_FSETXATTR 1 + +/* Define to 1 if you have the `fstat' function. */ +#cmakedefine HAVE_FSTAT 1 + +/* Define to 1 if you have the `fstatat' function. */ +#cmakedefine HAVE_FSTATAT 1 + +/* Define to 1 if you have the `fstatfs' function. */ +#cmakedefine HAVE_FSTATFS 1 + +/* Define to 1 if you have the `fstatvfs' function. */ +#cmakedefine HAVE_FSTATVFS 1 + +/* Define to 1 if you have the `ftruncate' function. */ +#cmakedefine HAVE_FTRUNCATE 1 + +/* Define to 1 if you have the `futimens' function. */ +#cmakedefine HAVE_FUTIMENS 1 + +/* Define to 1 if you have the `futimes' function. */ +#cmakedefine HAVE_FUTIMES 1 + +/* Define to 1 if you have the `futimesat' function. */ +#cmakedefine HAVE_FUTIMESAT 1 + +/* Define to 1 if you have the `getea' function. */ +#cmakedefine HAVE_GETEA 1 + +/* Define to 1 if you have the `geteuid' function. */ +#cmakedefine HAVE_GETEUID 1 + +/* Define to 1 if you have the `getgrgid_r' function. */ +#cmakedefine HAVE_GETGRGID_R 1 + +/* Define to 1 if you have the `getgrnam_r' function. */ +#cmakedefine HAVE_GETGRNAM_R 1 + +/* Define to 1 if you have the `getpid' function. */ +#cmakedefine HAVE_GETPID 1 + +/* Define to 1 if you have the `getpwnam_r' function. */ +#cmakedefine HAVE_GETPWNAM_R 1 + +/* Define to 1 if you have the `getpwuid_r' function. */ +#cmakedefine HAVE_GETPWUID_R 1 + +/* Define to 1 if you have the `getvfsbyname' function. */ +#cmakedefine HAVE_GETVFSBYNAME 1 + +/* Define to 1 if you have the `getxattr' function. */ +#cmakedefine HAVE_GETXATTR 1 + +/* Define to 1 if you have the `gmtime_r' function. */ +#cmakedefine HAVE_GMTIME_R 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_GRP_H 1 + +/* Define to 1 if you have the `iconv' function. */ +#cmakedefine HAVE_ICONV 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ICONV_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_IO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LANGINFO_H 1 + +/* Define to 1 if you have the `lchflags' function. */ +#cmakedefine HAVE_LCHFLAGS 1 + +/* Define to 1 if you have the `lchmod' function. */ +#cmakedefine HAVE_LCHMOD 1 + +/* Define to 1 if you have the `lchown' function. */ +#cmakedefine HAVE_LCHOWN 1 + +/* Define to 1 if you have the `lgetea' function. */ +#cmakedefine HAVE_LGETEA 1 + +/* Define to 1 if you have the `lgetxattr' function. */ +#cmakedefine HAVE_LGETXATTR 1 + +/* Define to 1 if you have the `acl' library (-lacl). */ +#cmakedefine HAVE_LIBACL 1 + +/* Define to 1 if you have the `attr' library (-lattr). */ +#cmakedefine HAVE_LIBATTR 1 + +/* Define to 1 if you have the `bsdxml' library (-lbsdxml). */ +#cmakedefine HAVE_LIBBSDXML 1 + +/* Define to 1 if you have the `bz2' library (-lbz2). */ +#cmakedefine HAVE_LIBBZ2 1 + +/* Define to 1 if you have the `b2' library (-lb2). */ +#cmakedefine HAVE_LIBB2 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_BLAKE2_H 1 + +/* Define to 1 if you have the `charset' library (-lcharset). */ +#cmakedefine HAVE_LIBCHARSET 1 + +/* Define to 1 if you have the `crypto' library (-lcrypto). */ +#cmakedefine HAVE_LIBCRYPTO 1 + +/* Define to 1 if you have the `expat' library (-lexpat). */ +#cmakedefine HAVE_LIBEXPAT 1 + +/* Define to 1 if you have the `gcc' library (-lgcc). */ +#cmakedefine HAVE_LIBGCC 1 + +/* Define to 1 if you have the `lz4' library (-llz4). */ +#cmakedefine HAVE_LIBLZ4 1 + +/* Define to 1 if you have the `lzma' library (-llzma). */ +#cmakedefine HAVE_LIBLZMA 1 + +/* Define to 1 if you have the `lzmadec' library (-llzmadec). */ +#cmakedefine HAVE_LIBLZMADEC 1 + +/* Define to 1 if you have the `lzo2' library (-llzo2). */ +#cmakedefine HAVE_LIBLZO2 1 + +/* Define to 1 if you have the `mbedcrypto' library (-lmbedcrypto). */ +#cmakedefine HAVE_LIBMBEDCRYPTO 1 + +/* Define to 1 if you have the `nettle' library (-lnettle). */ +#cmakedefine HAVE_LIBNETTLE 1 + +/* Define to 1 if you have the `pcre' library (-lpcre). */ +#cmakedefine HAVE_LIBPCRE 1 + +/* Define to 1 if you have the `pcreposix' library (-lpcreposix). */ +#cmakedefine HAVE_LIBPCREPOSIX 1 + +/* Define to 1 if you have the `xml2' library (-lxml2). */ +#cmakedefine HAVE_LIBXML2 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LIBXML_XMLREADER_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LIBXML_XMLWRITER_H 1 + +/* Define to 1 if you have the `z' library (-lz). */ +#cmakedefine HAVE_LIBZ 1 + +/* Define to 1 if you have the `zstd' library (-lzstd). */ +#cmakedefine HAVE_LIBZSTD 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LIMITS_H 1 + +/* Define to 1 if you have the `link' function. */ +#cmakedefine HAVE_LINK 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LINUX_FIEMAP_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LINUX_FS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LINUX_MAGIC_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LINUX_TYPES_H 1 + +/* Define to 1 if you have the `listea' function. */ +#cmakedefine HAVE_LISTEA 1 + +/* Define to 1 if you have the `listxattr' function. */ +#cmakedefine HAVE_LISTXATTR 1 + +/* Define to 1 if you have the `llistea' function. */ +#cmakedefine HAVE_LLISTEA 1 + +/* Define to 1 if you have the `llistxattr' function. */ +#cmakedefine HAVE_LLISTXATTR 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LOCALCHARSET_H 1 + +/* Define to 1 if you have the `locale_charset' function. */ +#cmakedefine HAVE_LOCALE_CHARSET 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LOCALE_H 1 + +/* Define to 1 if you have the `localtime_r' function. */ +#cmakedefine HAVE_LOCALTIME_R 1 + +/* Define to 1 if the system has the type `long long int'. */ +#cmakedefine HAVE_LONG_LONG_INT 1 + +/* Define to 1 if you have the `lsetea' function. */ +#cmakedefine HAVE_LSETEA 1 + +/* Define to 1 if you have the `lsetxattr' function. */ +#cmakedefine HAVE_LSETXATTR 1 + +/* Define to 1 if you have the `lstat' function. */ +#cmakedefine HAVE_LSTAT 1 + +/* Define to 1 if `lstat' has the bug that it succeeds when given the + zero-length file name argument. */ +#cmakedefine HAVE_LSTAT_EMPTY_STRING_BUG 1 + +/* Define to 1 if you have the `lutimes' function. */ +#cmakedefine HAVE_LUTIMES 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LZ4HC_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LZ4_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LZMADEC_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LZMA_H 1 + +/* Define to 1 if you have a working `lzma_stream_encoder_mt' function. */ +#cmakedefine HAVE_LZMA_STREAM_ENCODER_MT 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LZO_LZO1X_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LZO_LZOCONF_H 1 + +/* Define to 1 if you have the `mbrtowc' function. */ +#cmakedefine HAVE_MBRTOWC 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MEMBERSHIP_H 1 + +/* Define to 1 if you have the `memmove' function. */ +#cmakedefine HAVE_MEMMOVE 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mkdir' function. */ +#cmakedefine HAVE_MKDIR 1 + +/* Define to 1 if you have the `mkfifo' function. */ +#cmakedefine HAVE_MKFIFO 1 + +/* Define to 1 if you have the `mknod' function. */ +#cmakedefine HAVE_MKNOD 1 + +/* Define to 1 if you have the `mkstemp' function. */ +#cmakedefine HAVE_MKSTEMP 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +#cmakedefine HAVE_NDIR_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETTLE_AES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETTLE_HMAC_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETTLE_MD5_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETTLE_PBKDF2_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETTLE_RIPEMD160_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETTLE_SHA_H 1 + +/* Define to 1 if you have the `nl_langinfo' function. */ +#cmakedefine HAVE_NL_LANGINFO 1 + +/* Define to 1 if you have the `openat' function. */ +#cmakedefine HAVE_OPENAT 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_PATHS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_PCREPOSIX_H 1 + +/* Define to 1 if you have the `pipe' function. */ +#cmakedefine HAVE_PIPE 1 + +/* Define to 1 if you have the `PKCS5_PBKDF2_HMAC_SHA1' function. */ +#cmakedefine HAVE_PKCS5_PBKDF2_HMAC_SHA1 1 + +/* Define to 1 if you have the `poll' function. */ +#cmakedefine HAVE_POLL 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_POLL_H 1 + +/* Define to 1 if you have the `posix_spawnp' function. */ +#cmakedefine HAVE_POSIX_SPAWNP 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_PROCESS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_PTHREAD_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_PWD_H 1 + +/* Define to 1 if you have the `readdir_r' function. */ +#cmakedefine HAVE_READDIR_R 1 + +/* Define to 1 if you have the `readlink' function. */ +#cmakedefine HAVE_READLINK 1 + +/* Define to 1 if you have the `readlinkat' function. */ +#cmakedefine HAVE_READLINKAT 1 + +/* Define to 1 if you have the `readpassphrase' function. */ +#cmakedefine HAVE_READPASSPHRASE 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_READPASSPHRASE_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_REGEX_H 1 + +/* Define to 1 if you have the `select' function. */ +#cmakedefine HAVE_SELECT 1 + +/* Define to 1 if you have the `setenv' function. */ +#cmakedefine HAVE_SETENV 1 + +/* Define to 1 if you have the `setlocale' function. */ +#cmakedefine HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `sigaction' function. */ +#cmakedefine HAVE_SIGACTION 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SPAWN_H 1 + +/* Define to 1 if you have the `statfs' function. */ +#cmakedefine HAVE_STATFS 1 + +/* Define to 1 if you have the `statvfs' function. */ +#cmakedefine HAVE_STATVFS 1 + +/* Define to 1 if `stat' has the bug that it succeeds when given the + zero-length file name argument. */ +#cmakedefine HAVE_STAT_EMPTY_STRING_BUG 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDARG_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strchr' function. */ +#cmakedefine HAVE_STRCHR 1 + +/* Define to 1 if you have the `strdup' function. */ +#cmakedefine HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror' function. */ +#cmakedefine HAVE_STRERROR 1 + +/* Define to 1 if you have the `strerror_r' function. */ +#cmakedefine HAVE_STRERROR_R 1 + +/* Define to 1 if you have the `strftime' function. */ +#cmakedefine HAVE_STRFTIME 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRING_H 1 + +/* Define to 1 if you have the `strrchr' function. */ +#cmakedefine HAVE_STRRCHR 1 + +/* Define to 1 if `f_namemax' is a member of `struct statfs'. */ +#cmakedefine HAVE_STRUCT_STATFS_F_NAMEMAX 1 + +/* Define to 1 if `f_iosize' is a member of `struct statvfs'. */ +#cmakedefine HAVE_STRUCT_STATVFS_F_IOSIZE 1 + +/* Define to 1 if `st_birthtime' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_BIRTHTIME 1 + +/* Define to 1 if `st_birthtimespec.tv_nsec' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC 1 + +/* Define to 1 if `st_blksize' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_BLKSIZE 1 + +/* Define to 1 if `st_flags' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_FLAGS 1 + +/* Define to 1 if `st_mtimespec.tv_nsec' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1 + +/* Define to 1 if `st_mtime_n' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_MTIME_N 1 + +/* Define to 1 if `st_mtime_usec' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_MTIME_USEC 1 + +/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1 + +/* Define to 1 if `st_umtime' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_UMTIME 1 + +/* Define to 1 if `tm_gmtoff' is a member of `struct tm'. */ +#cmakedefine HAVE_STRUCT_TM_TM_GMTOFF 1 + +/* Define to 1 if `__tm_gmtoff' is a member of `struct tm'. */ +#cmakedefine HAVE_STRUCT_TM___TM_GMTOFF 1 + +/* Define to 1 if you have `struct vfsconf'. */ +#cmakedefine HAVE_STRUCT_VFSCONF 1 + +/* Define to 1 if you have `struct xvfsconf'. */ +#cmakedefine HAVE_STRUCT_XVFSCONF 1 + +/* Define to 1 if you have the `symlink' function. */ +#cmakedefine HAVE_SYMLINK 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_ACL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_CDEFS_H 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#cmakedefine HAVE_SYS_DIR_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_EA_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_EXTATTR_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_MKDEV_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_MOUNT_H 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#cmakedefine HAVE_SYS_NDIR_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_POLL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_RICHACL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_STATFS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_STATVFS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_STAT_H 1 + + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_SYSMACROS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_UTIME_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_UTSNAME_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_VFS_H 1 + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#cmakedefine HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_XATTR_H 1 + +/* Define to 1 if you have the `timegm' function. */ +#cmakedefine HAVE_TIMEGM 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_TIME_H 1 + +/* Define to 1 if you have the `tzset' function. */ +#cmakedefine HAVE_TZSET 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `unlinkat' function. */ +#cmakedefine HAVE_UNLINKAT 1 + +/* Define to 1 if you have the `unsetenv' function. */ +#cmakedefine HAVE_UNSETENV 1 + +/* Define to 1 if the system has the type `unsigned long long'. */ +#cmakedefine HAVE_UNSIGNED_LONG_LONG 1 + +/* Define to 1 if the system has the type `unsigned long long int'. */ +#cmakedefine HAVE_UNSIGNED_LONG_LONG_INT 1 + +/* Define to 1 if you have the `utime' function. */ +#cmakedefine HAVE_UTIME 1 + +/* Define to 1 if you have the `utimensat' function. */ +#cmakedefine HAVE_UTIMENSAT 1 + +/* Define to 1 if you have the `utimes' function. */ +#cmakedefine HAVE_UTIMES 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UTIME_H 1 + +/* Define to 1 if you have the `vfork' function. */ +#cmakedefine HAVE_VFORK 1 + +/* Define to 1 if you have the `vprintf' function. */ +#cmakedefine HAVE_VPRINTF 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_WCHAR_H 1 + +/* Define to 1 if the system has the type `wchar_t'. */ +#cmakedefine HAVE_WCHAR_T 1 + +/* Define to 1 if you have the `wcrtomb' function. */ +#cmakedefine HAVE_WCRTOMB 1 + +/* Define to 1 if you have the `wcscmp' function. */ +#cmakedefine HAVE_WCSCMP 1 + +/* Define to 1 if you have the `wcscpy' function. */ +#cmakedefine HAVE_WCSCPY 1 + +/* Define to 1 if you have the `wcslen' function. */ +#cmakedefine HAVE_WCSLEN 1 + +/* Define to 1 if you have the `wctomb' function. */ +#cmakedefine HAVE_WCTOMB 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_WCTYPE_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_WINCRYPT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_WINDOWS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_WINIOCTL_H 1 + +/* Define to 1 if you have _CrtSetReportMode in */ +#cmakedefine HAVE__CrtSetReportMode 1 + +/* Define to 1 if you have the `wmemcmp' function. */ +#cmakedefine HAVE_WMEMCMP 1 + +/* Define to 1 if you have the `wmemcpy' function. */ +#cmakedefine HAVE_WMEMCPY 1 + +/* Define to 1 if you have the `wmemmove' function. */ +#cmakedefine HAVE_WMEMMOVE 1 + +/* Define to 1 if you have a working EXT2_IOC_GETFLAGS */ +#cmakedefine HAVE_WORKING_EXT2_IOC_GETFLAGS 1 + +/* Define to 1 if you have a working FS_IOC_GETFLAGS */ +#cmakedefine HAVE_WORKING_FS_IOC_GETFLAGS 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ZLIB_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ZSTD_H 1 + +/* Define to 1 if you have the `_ctime64_s' function. */ +#cmakedefine HAVE__CTIME64_S 1 + +/* Define to 1 if you have the `_fseeki64' function. */ +#cmakedefine HAVE__FSEEKI64 1 + +/* Define to 1 if you have the `_get_timezone' function. */ +#cmakedefine HAVE__GET_TIMEZONE 1 + +/* Define to 1 if you have the `_gmtime64_s' function. */ +#cmakedefine HAVE__GMTIME64_S 1 + +/* Define to 1 if you have the `_localtime64_s' function. */ +#cmakedefine HAVE__LOCALTIME64_S 1 + +/* Define to 1 if you have the `_mkgmtime64' function. */ +#cmakedefine HAVE__MKGMTIME64 1 + +/* Define as const if the declaration of iconv() needs const. */ +#define ICONV_CONST ${ICONV_CONST} + +/* Version number of libarchive as a single integer */ +#cmakedefine LIBARCHIVE_VERSION_NUMBER "${LIBARCHIVE_VERSION_NUMBER}" + +/* Version number of libarchive */ +#cmakedefine LIBARCHIVE_VERSION_STRING "${LIBARCHIVE_VERSION_STRING}" + +/* Define to 1 if `lstat' dereferences a symlink specified with a trailing + slash. */ +#cmakedefine LSTAT_FOLLOWS_SLASHED_SYMLINK 1 + +/* Define to 1 if `major', `minor', and `makedev' are declared in . + */ +#cmakedefine MAJOR_IN_MKDEV 1 + +/* Define to 1 if `major', `minor', and `makedev' are declared in + . */ +#cmakedefine MAJOR_IN_SYSMACROS 1 + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +#cmakedefine NO_MINUS_C_MINUS_O 1 + +/* The size of `wchar_t', as computed by sizeof. */ +#cmakedefine SIZEOF_WCHAR_T ${SIZEOF_WCHAR_T} + +/* Define to 1 if strerror_r returns char *. */ +#cmakedefine STRERROR_R_CHAR_P 1 + +/* Define to 1 if you can safely include both and . */ +#cmakedefine TIME_WITH_SYS_TIME 1 + +/* + * Some platform requires a macro to use extension functions. + */ +#cmakedefine SAFE_TO_DEFINE_EXTENSIONS 1 +#ifdef SAFE_TO_DEFINE_EXTENSIONS +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# define _ALL_SOURCE 1 +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# define _TANDEM_SOURCE 1 +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# define __EXTENSIONS__ 1 +#endif +#endif /* SAFE_TO_DEFINE_EXTENSIONS */ + +/* Version number of package */ +#cmakedefine VERSION "${VERSION}" + +/* Number of bits in a file offset, on hosts where this is settable. */ +#cmakedefine _FILE_OFFSET_BITS ${_FILE_OFFSET_BITS} + +/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ +#cmakedefine _LARGEFILE_SOURCE 1 + +/* Define for large files, on AIX-style hosts. */ +#cmakedefine _LARGE_FILES ${_LARGE_FILES} + +/* Define to control Windows SDK version */ +#ifndef NTDDI_VERSION +#cmakedefine NTDDI_VERSION ${NTDDI_VERSION} +#endif // NTDDI_VERSION + +#ifndef _WIN32_WINNT +#cmakedefine _WIN32_WINNT ${_WIN32_WINNT} +#endif // _WIN32_WINNT + +#ifndef WINVER +#cmakedefine WINVER ${WINVER} +#endif // WINVER + +/* Define to empty if `const' does not conform to ANSI C. */ +#cmakedefine const ${const} + +/* Define to `int' if doesn't define. */ +#cmakedefine gid_t ${gid_t} + +/* Define to `unsigned long' if does not define. */ +#cmakedefine id_t ${id_t} + +/* Define to `int' if does not define. */ +#cmakedefine mode_t ${mode_t} + +/* Define to `long long' if does not define. */ +#cmakedefine off_t ${off_t} + +/* Define to `int' if doesn't define. */ +#cmakedefine pid_t ${pid_t} + +/* Define to `unsigned int' if does not define. */ +#cmakedefine size_t ${size_t} + +/* Define to `int' if does not define. */ +#cmakedefine ssize_t ${ssize_t} + +/* Define to `int' if doesn't define. */ +#cmakedefine uid_t ${uid_t} + +/* Define to `int' if does not define. */ +#cmakedefine intptr_t ${intptr_t} + +/* Define to `unsigned int' if does not define. */ +#cmakedefine uintptr_t ${uintptr_t} diff --git a/dependencies/libarchive-3.4.2/build/pkgconfig/libarchive.pc.in b/dependencies/libarchive-3.4.2/build/pkgconfig/libarchive.pc.in new file mode 100644 index 0000000..4b631e6 --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/pkgconfig/libarchive.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libarchive +Description: library that can create and read several streaming archive formats +Version: @VERSION@ +Cflags: -I${includedir} +Cflags.private: -DLIBARCHIVE_STATIC +Libs: -L${libdir} -larchive +Libs.private: @LIBS@ diff --git a/dependencies/libarchive-3.4.2/build/version b/dependencies/libarchive-3.4.2/build/version new file mode 100644 index 0000000..78be3ab --- /dev/null +++ b/dependencies/libarchive-3.4.2/build/version @@ -0,0 +1 @@ +3004002 diff --git a/dependencies/libarchive-3.4.2/cat/CMakeLists.txt b/dependencies/libarchive-3.4.2/cat/CMakeLists.txt new file mode 100644 index 0000000..4fe6354 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/CMakeLists.txt @@ -0,0 +1,37 @@ +############################################ +# +# How to build bsdcat +# +############################################ +IF(ENABLE_CAT) + + SET(bsdcat_SOURCES + bsdcat.c + bsdcat.h + bsdcat_platform.h + cmdline.c + ../libarchive_fe/err.c + ../libarchive_fe/err.h + ../libarchive_fe/lafe_platform.h + ) + INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../libarchive_fe) + + # bsdcat documentation + SET(bsdcat_MANS bsdcat.1) + + # How to build bsdcat + ADD_EXECUTABLE(bsdcat ${bsdcat_SOURCES}) + IF(ENABLE_CAT_SHARED) + TARGET_LINK_LIBRARIES(bsdcat archive ${ADDITIONAL_LIBS}) + ELSE(ENABLE_CAT_SHARED) + TARGET_LINK_LIBRARIES(bsdcat archive_static ${ADDITIONAL_LIBS}) + SET_TARGET_PROPERTIES(bsdcat PROPERTIES COMPILE_DEFINITIONS + LIBARCHIVE_STATIC) + ENDIF(ENABLE_CAT_SHARED) + + # Installation rules + INSTALL(TARGETS bsdcat RUNTIME DESTINATION bin) + INSTALL_MAN(${bsdcat_MANS}) +ENDIF(ENABLE_CAT) + +add_subdirectory(test) diff --git a/dependencies/libarchive-3.4.2/cat/bsdcat.1 b/dependencies/libarchive-3.4.2/cat/bsdcat.1 new file mode 100644 index 0000000..036623e --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/bsdcat.1 @@ -0,0 +1,61 @@ +.\" Copyright (c) 2011-2014, Mike Kazantsev +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd March 1, 2014 +.Dt BSDCAT 1 +.Os +.Sh NAME +.Nm bsdcat +.Nd expand files to standard output +.Sh SYNOPSIS +.Nm +.Op options +.Op files +.Sh DESCRIPTION +.Nm +expands files to standard output. +.Sh OPTIONS +.Nm +typically takes a filename as an argument or reads standard input when used in a +pipe. +In both cases decompressed data it written to standard output. +.Sh EXAMPLES +To decompress a file: +.Pp +.Dl bsdcat example.txt.gz > example.txt +.Pp +To decompress standard input in a pipe: +.Pp +.Dl cat example.txt.gz | bsdcat > example.txt +.Pp +Both examples achieve the same results - a decompressed file by redirecting +output. +.Sh SEE ALSO +.Xr bzcat 1 , +.Xr uncompress 1 , +.Xr xzcat 1 , +.Xr zcat 1 , +.Xr libarchive-formats 5 diff --git a/dependencies/libarchive-3.4.2/cat/bsdcat.c b/dependencies/libarchive-3.4.2/cat/bsdcat.c new file mode 100644 index 0000000..bdb9c40 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/bsdcat.c @@ -0,0 +1,156 @@ +/*- + * Copyright (c) 2011-2014, Mike Kazantsev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "bsdcat_platform.h" +__FBSDID("$FreeBSD$"); + +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "bsdcat.h" +#include "err.h" + +#define BYTES_PER_BLOCK (20*512) + +static struct archive *a; +static struct archive_entry *ae; +static const char *bsdcat_current_path; +static int exit_status = 0; + + +void +usage(FILE *stream, int eval) +{ + const char *p; + p = lafe_getprogname(); + fprintf(stream, + "Usage: %s [-h] [--help] [--version] [--] [filenames...]\n", p); + exit(eval); +} + +static void +version(void) +{ + printf("bsdcat %s - %s \n", + BSDCAT_VERSION_STRING, + archive_version_details()); + exit(0); +} + +void +bsdcat_next(void) +{ + if (a != NULL) { + if (archive_read_close(a) != ARCHIVE_OK) + bsdcat_print_error(); + archive_read_free(a); + } + + a = archive_read_new(); + archive_read_support_filter_all(a); + archive_read_support_format_empty(a); + archive_read_support_format_raw(a); +} + +void +bsdcat_print_error(void) +{ + lafe_warnc(0, "%s: %s", + bsdcat_current_path, archive_error_string(a)); + exit_status = 1; +} + +void +bsdcat_read_to_stdout(const char* filename) +{ + int r; + + if (archive_read_open_filename(a, filename, BYTES_PER_BLOCK) + != ARCHIVE_OK) + bsdcat_print_error(); + else if (r = archive_read_next_header(a, &ae), + r != ARCHIVE_OK && r != ARCHIVE_EOF) + bsdcat_print_error(); + else if (r == ARCHIVE_EOF) + /* for empty payloads don't try and read data */ + ; + else if (archive_read_data_into_fd(a, 1) != ARCHIVE_OK) + bsdcat_print_error(); + if (archive_read_close(a) != ARCHIVE_OK) + bsdcat_print_error(); + archive_read_free(a); + a = NULL; +} + +int +main(int argc, char **argv) +{ + struct bsdcat *bsdcat, bsdcat_storage; + int c; + + bsdcat = &bsdcat_storage; + memset(bsdcat, 0, sizeof(*bsdcat)); + + lafe_setprogname(*argv, "bsdcat"); + + bsdcat->argv = argv; + bsdcat->argc = argc; + + while ((c = bsdcat_getopt(bsdcat)) != -1) { + switch (c) { + case 'h': + usage(stdout, 0); + break; + case OPTION_VERSION: + version(); + break; + default: + usage(stderr, 1); + } + } + + bsdcat_next(); + if (*bsdcat->argv == NULL) { + bsdcat_current_path = ""; + bsdcat_read_to_stdout(NULL); + } else { + while (*bsdcat->argv) { + bsdcat_current_path = *bsdcat->argv++; + bsdcat_read_to_stdout(bsdcat_current_path); + bsdcat_next(); + } + archive_read_free(a); /* Help valgrind & friends */ + } + + exit(exit_status); +} diff --git a/dependencies/libarchive-3.4.2/cat/bsdcat.h b/dependencies/libarchive-3.4.2/cat/bsdcat.h new file mode 100644 index 0000000..6467d6e --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/bsdcat.h @@ -0,0 +1,61 @@ +/*- + * Copyright (c) 2014, Mike Kazantsev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BSDCAT_H_INCLUDED +#define BSDCAT_H_INCLUDED + +#if defined(PLATFORM_CONFIG_H) +/* Use hand-built config.h in environments that need it. */ +#include PLATFORM_CONFIG_H +#else +/* Not having a config.h of some sort is a serious problem. */ +#include "config.h" +#endif + +#include +#include + +struct bsdcat { + /* Option parser state */ + int getopt_state; + char *getopt_word; + + /* Miscellaneous state information */ + int argc; + char **argv; + const char *argument; +}; + +enum { + OPTION_VERSION +}; + +int bsdcat_getopt(struct bsdcat *); +void usage(FILE *stream, int eval); +void bsdcat_next(void); +void bsdcat_print_error(void); +void bsdcat_read_to_stdout(const char* filename); + +#endif diff --git a/dependencies/libarchive-3.4.2/cat/bsdcat_platform.h b/dependencies/libarchive-3.4.2/cat/bsdcat_platform.h new file mode 100644 index 0000000..10b7113 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/bsdcat_platform.h @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: src/usr.bin/tar/bsdtar_platform.h,v 1.26 2008/12/06 07:37:14 kientzle Exp $ + */ + +/* + * This header is the first thing included in any of the bsdtar + * source files. As far as possible, platform-specific issues should + * be dealt with here and not within individual source files. + */ + +#ifndef BSDCAT_PLATFORM_H_INCLUDED +#define BSDCAT_PLATFORM_H_INCLUDED + +#if defined(PLATFORM_CONFIG_H) +/* Use hand-built config.h in environments that need it. */ +#include PLATFORM_CONFIG_H +#else +/* Not having a config.h of some sort is a serious problem. */ +#include "config.h" +#endif + +/* Get a real definition for __FBSDID if we can */ +#if HAVE_SYS_CDEFS_H +#include +#endif + +/* If not, define it so as to avoid dangling semicolons. */ +#ifndef __FBSDID +#define __FBSDID(a) struct _undefined_hack +#endif + +#ifdef HAVE_LIBARCHIVE +/* If we're using the platform libarchive, include system headers. */ +#include +#include +#else +/* Otherwise, include user headers. */ +#include "archive.h" +#include "archive_entry.h" +#endif + +/* How to mark functions that don't return. */ +/* This facilitates use of some newer static code analysis tools. */ +#undef __LA_DEAD +#if defined(__GNUC__) && (__GNUC__ > 2 || \ + (__GNUC__ == 2 && __GNUC_MINOR__ >= 5)) +#define __LA_DEAD __attribute__((__noreturn__)) +#else +#define __LA_DEAD +#endif + +#endif /* !BSDCAT_PLATFORM_H_INCLUDED */ diff --git a/dependencies/libarchive-3.4.2/cat/cmdline.c b/dependencies/libarchive-3.4.2/cat/cmdline.c new file mode 100644 index 0000000..cae19be --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/cmdline.c @@ -0,0 +1,283 @@ +/*- + * Copyright (c) 2003-2008 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Command line parser for tar. + */ + +#include "bsdcat_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "bsdcat.h" +#include "err.h" + +/* + * Short options for tar. Please keep this sorted. + */ +static const char *short_options = "h"; + +/* + * Long options for tar. Please keep this list sorted. + * + * The symbolic names for options that lack a short equivalent are + * defined in bsdcat.h. Also note that so far I've found no need + * to support optional arguments to long options. That would be + * a small change to the code below. + */ + +static const struct bsdcat_option { + const char *name; + int required; /* 1 if this option requires an argument. */ + int equivalent; /* Equivalent short option. */ +} tar_longopts[] = { + { "help", 0, 'h' }, + { "version", 0, OPTION_VERSION }, + { NULL, 0, 0 } +}; + +/* + * This getopt implementation has two key features that common + * getopt_long() implementations lack. Apart from those, it's a + * straightforward option parser, considerably simplified by not + * needing to support the wealth of exotic getopt_long() features. It + * has, of course, been shamelessly tailored for bsdcat. (If you're + * looking for a generic getopt_long() implementation for your + * project, I recommend Gregory Pietsch's public domain getopt_long() + * implementation.) The two additional features are: + * + * Old-style tar arguments: The original tar implementation treated + * the first argument word as a list of single-character option + * letters. All arguments follow as separate words. For example, + * tar xbf 32 /dev/tape + * Here, the "xbf" is three option letters, "32" is the argument for + * "b" and "/dev/tape" is the argument for "f". We support this usage + * if the first command-line argument does not begin with '-'. We + * also allow regular short and long options to follow, e.g., + * tar xbf 32 /dev/tape -P --format=pax + * + * -W long options: There's an obscure GNU convention (only rarely + * supported even there) that allows "-W option=argument" as an + * alternative way to support long options. This was supported in + * early bsdcat as a way to access long options on platforms that did + * not support getopt_long() and is preserved here for backwards + * compatibility. (Of course, if I'd started with a custom + * command-line parser from the beginning, I would have had normal + * long option support on every platform so that hack wouldn't have + * been necessary. Oh, well. Some mistakes you just have to live + * with.) + * + * TODO: We should be able to use this to pull files and intermingled + * options (such as -C) from the command line in write mode. That + * will require a little rethinking of the argument handling in + * bsdcat.c. + * + * TODO: If we want to support arbitrary command-line options from -T + * input (as GNU tar does), we may need to extend this to handle option + * words from sources other than argv/argc. I'm not really sure if I + * like that feature of GNU tar, so it's certainly not a priority. + */ + +int +bsdcat_getopt(struct bsdcat *bsdcat) +{ + enum { state_start = 0, state_old_tar, state_next_word, + state_short, state_long }; + + const struct bsdcat_option *popt, *match = NULL, *match2 = NULL; + const char *p, *long_prefix = "--"; + size_t optlength; + int opt = '?'; + int required = 0; + + bsdcat->argument = NULL; + + /* First time through, initialize everything. */ + if (bsdcat->getopt_state == state_start) { + /* Skip program name. */ + ++bsdcat->argv; + --bsdcat->argc; + if (*bsdcat->argv == NULL) + return (-1); + /* Decide between "new style" and "old style" arguments. */ + bsdcat->getopt_state = state_next_word; + } + + /* + * We're ready to look at the next word in argv. + */ + if (bsdcat->getopt_state == state_next_word) { + /* No more arguments, so no more options. */ + if (bsdcat->argv[0] == NULL) + return (-1); + /* Doesn't start with '-', so no more options. */ + if (bsdcat->argv[0][0] != '-') + return (-1); + /* "--" marks end of options; consume it and return. */ + if (strcmp(bsdcat->argv[0], "--") == 0) { + ++bsdcat->argv; + --bsdcat->argc; + return (-1); + } + /* Get next word for parsing. */ + bsdcat->getopt_word = *bsdcat->argv++; + --bsdcat->argc; + if (bsdcat->getopt_word[1] == '-') { + /* Set up long option parser. */ + bsdcat->getopt_state = state_long; + bsdcat->getopt_word += 2; /* Skip leading '--' */ + } else { + /* Set up short option parser. */ + bsdcat->getopt_state = state_short; + ++bsdcat->getopt_word; /* Skip leading '-' */ + } + } + + /* + * We're parsing a group of POSIX-style single-character options. + */ + if (bsdcat->getopt_state == state_short) { + /* Peel next option off of a group of short options. */ + opt = *bsdcat->getopt_word++; + if (opt == '\0') { + /* End of this group; recurse to get next option. */ + bsdcat->getopt_state = state_next_word; + return bsdcat_getopt(bsdcat); + } + + /* Does this option take an argument? */ + p = strchr(short_options, opt); + if (p == NULL) + return ('?'); + if (p[1] == ':') + required = 1; + + /* If it takes an argument, parse that. */ + if (required) { + /* If arg is run-in, bsdcat->getopt_word already points to it. */ + if (bsdcat->getopt_word[0] == '\0') { + /* Otherwise, pick up the next word. */ + bsdcat->getopt_word = *bsdcat->argv; + if (bsdcat->getopt_word == NULL) { + lafe_warnc(0, + "Option -%c requires an argument", + opt); + return ('?'); + } + ++bsdcat->argv; + --bsdcat->argc; + } + if (opt == 'W') { + bsdcat->getopt_state = state_long; + long_prefix = "-W "; /* For clearer errors. */ + } else { + bsdcat->getopt_state = state_next_word; + bsdcat->argument = bsdcat->getopt_word; + } + } + } + + /* We're reading a long option, including -W long=arg convention. */ + if (bsdcat->getopt_state == state_long) { + /* After this long option, we'll be starting a new word. */ + bsdcat->getopt_state = state_next_word; + + /* Option name ends at '=' if there is one. */ + p = strchr(bsdcat->getopt_word, '='); + if (p != NULL) { + optlength = (size_t)(p - bsdcat->getopt_word); + bsdcat->argument = (char *)(uintptr_t)(p + 1); + } else { + optlength = strlen(bsdcat->getopt_word); + } + + /* Search the table for an unambiguous match. */ + for (popt = tar_longopts; popt->name != NULL; popt++) { + /* Short-circuit if first chars don't match. */ + if (popt->name[0] != bsdcat->getopt_word[0]) + continue; + /* If option is a prefix of name in table, record it.*/ + if (strncmp(bsdcat->getopt_word, popt->name, optlength) == 0) { + match2 = match; /* Record up to two matches. */ + match = popt; + /* If it's an exact match, we're done. */ + if (strlen(popt->name) == optlength) { + match2 = NULL; /* Forget the others. */ + break; + } + } + } + + /* Fail if there wasn't a unique match. */ + if (match == NULL) { + lafe_warnc(0, + "Option %s%s is not supported", + long_prefix, bsdcat->getopt_word); + return ('?'); + } + if (match2 != NULL) { + lafe_warnc(0, + "Ambiguous option %s%s (matches --%s and --%s)", + long_prefix, bsdcat->getopt_word, match->name, match2->name); + return ('?'); + } + + /* We've found a unique match; does it need an argument? */ + if (match->required) { + /* Argument required: get next word if necessary. */ + if (bsdcat->argument == NULL) { + bsdcat->argument = *bsdcat->argv; + if (bsdcat->argument == NULL) { + lafe_warnc(0, + "Option %s%s requires an argument", + long_prefix, match->name); + return ('?'); + } + ++bsdcat->argv; + --bsdcat->argc; + } + } else { + /* Argument forbidden: fail if there is one. */ + if (bsdcat->argument != NULL) { + lafe_warnc(0, + "Option %s%s does not allow an argument", + long_prefix, match->name); + return ('?'); + } + } + return (match->equivalent); + } + + return (opt); +} diff --git a/dependencies/libarchive-3.4.2/cat/test/CMakeLists.txt b/dependencies/libarchive-3.4.2/cat/test/CMakeLists.txt new file mode 100644 index 0000000..72f4a10 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/CMakeLists.txt @@ -0,0 +1,80 @@ +############################################ +# +# How to build bsdtar_test +# +############################################ +IF(ENABLE_CAT AND ENABLE_TEST) + SET(bsdcat_test_SOURCES + ../../test_utils/test_utils.c + ../../test_utils/test_main.c + test.h + test_0.c + test_empty_gz.c + test_empty_lz4.c + test_empty_xz.c + test_empty_zstd.c + test_error.c + test_error_mixed.c + test_expand_Z.c + test_expand_bz2.c + test_expand_gz.c + test_expand_lz4.c + test_expand_mixed.c + test_expand_plain.c + test_expand_xz.c + test_expand_zstd.c + test_help.c + test_stdin.c + test_version.c + ) + + # + # Register target + # + ADD_EXECUTABLE(bsdcat_test ${bsdcat_test_SOURCES}) + IF(ENABLE_ACL) + SET(TEST_ACL_LIBS "") + IF(HAVE_LIBACL) + LIST(APPEND TEST_ACL_LIBS ${ACL_LIBRARY}) + ENDIF(HAVE_LIBACL) + IF(HAVE_LIBRICHACL) + LIST(APPEND TEST_ACL_LIBS ${RICHACL_LIBRARY}) + ENDIF(HAVE_LIBRICHACL) + TARGET_LINK_LIBRARIES(bsdcat_test ${TEST_ACL_LIBS}) + ENDIF(ENABLE_ACL) + SET_PROPERTY(TARGET bsdcat_test PROPERTY COMPILE_DEFINITIONS LIST_H) + + # + # Generate list.h by grepping DEFINE_TEST() lines out of the C sources. + # + GENERATE_LIST_H(${CMAKE_CURRENT_BINARY_DIR}/list.h + ${CMAKE_CURRENT_LIST_FILE} ${bsdcat_test_SOURCES}) + SET_PROPERTY(DIRECTORY APPEND PROPERTY INCLUDE_DIRECTORIES + ${CMAKE_CURRENT_BINARY_DIR}) + + # list.h has a line DEFINE_TEST(testname) for every + # test. We can use that to define the tests for cmake by + # defining a DEFINE_TEST macro and reading list.h in. + MACRO (DEFINE_TEST _testname) + ADD_TEST( + NAME bsdcat_${_testname} + COMMAND bsdcat_test -vv + -p $ + -r ${CMAKE_CURRENT_SOURCE_DIR} + ${_testname}) + ENDMACRO (DEFINE_TEST _testname) + + INCLUDE(${CMAKE_CURRENT_BINARY_DIR}/list.h) + INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) + INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/test_utils) + INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/cat/test) + + # Experimental new test handling + ADD_CUSTOM_TARGET(run_bsdcat_test + COMMAND bsdcat_test -p $ + -r ${CMAKE_CURRENT_SOURCE_DIR} + -vv) + ADD_DEPENDENCIES(run_bsdcat_test bsdcat) + ADD_DEPENDENCIES(run_all_tests run_bsdcat_test) + +ENDIF(ENABLE_CAT AND ENABLE_TEST) diff --git a/dependencies/libarchive-3.4.2/cat/test/list.h b/dependencies/libarchive-3.4.2/cat/test/list.h new file mode 100644 index 0000000..57f2f2a --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/list.h @@ -0,0 +1,18 @@ +DEFINE_TEST(test_0) +DEFINE_TEST(test_empty_gz) +DEFINE_TEST(test_empty_lz4) +DEFINE_TEST(test_empty_xz) +DEFINE_TEST(test_empty_zstd) +DEFINE_TEST(test_error) +DEFINE_TEST(test_error_mixed) +DEFINE_TEST(test_expand_Z) +DEFINE_TEST(test_expand_bz2) +DEFINE_TEST(test_expand_gz) +DEFINE_TEST(test_expand_lz4) +DEFINE_TEST(test_expand_mixed) +DEFINE_TEST(test_expand_plain) +DEFINE_TEST(test_expand_xz) +DEFINE_TEST(test_expand_zstd) +DEFINE_TEST(test_help) +DEFINE_TEST(test_stdin) +DEFINE_TEST(test_version) diff --git a/dependencies/libarchive-3.4.2/cat/test/test.h b/dependencies/libarchive-3.4.2/cat/test/test.h new file mode 100644 index 0000000..350bcad --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/test.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2003-2006 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* Every test program should #include "test.h" as the first thing. */ + +#define KNOWNREF "test_expand.Z.uu" +#define ENVBASE "BSDCAT" /* Prefix for environment variables. */ +#define PROGRAM "bsdcat" /* Name of program being tested. */ +#define PROGRAM_ALIAS "cat" /* Generic alias for program */ +#undef LIBRARY /* Not testing a library. */ +#undef EXTRA_DUMP /* How to dump extra data */ +#undef EXTRA_ERRNO /* How to dump errno */ +/* How to generate extra version info. */ +#define EXTRA_VERSION (systemf("%s --version", testprog) ? "" : "") + +#include "test_common.h" diff --git a/dependencies/libarchive-3.4.2/cat/test/test_0.c b/dependencies/libarchive-3.4.2/cat/test/test_0.c new file mode 100644 index 0000000..c806c24 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/test_0.c @@ -0,0 +1,67 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +/* + * This first test does basic sanity checks on the environment. For + * most of these, we just exit on failure. + */ +#if !defined(_WIN32) || defined(__CYGWIN__) +#define DEV_NULL "/dev/null" +#else +#define DEV_NULL "NUL" +#endif + +DEFINE_TEST(test_0) +{ + struct stat st; + + failure("File %s does not exist?!", testprog); + if (!assertEqualInt(0, stat(testprogfile, &st))) { + fprintf(stderr, + "\nFile %s does not exist; aborting test.\n\n", + testprog); + exit(1); + } + + failure("%s is not executable?!", testprog); + if (!assert((st.st_mode & 0111) != 0)) { + fprintf(stderr, + "\nFile %s not executable; aborting test.\n\n", + testprog); + exit(1); + } + + /* + * Try to successfully run the program; this requires that + * we know some option that will succeed. + */ + if (0 != systemf("%s --version >" DEV_NULL, testprog)) { + failure("Unable to successfully run: %s --version\n", testprog); + assert(0); + } + + /* TODO: Ensure that our reference files are available. */ +} diff --git a/dependencies/libarchive-3.4.2/cat/test/test_empty.gz.uu b/dependencies/libarchive-3.4.2/cat/test/test_empty.gz.uu new file mode 100644 index 0000000..22b5230 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/test_empty.gz.uu @@ -0,0 +1,4 @@ +begin 644 test_empty.gz +?'XL(""\MZE,``W1EG840`` +` +end diff --git a/dependencies/libarchive-3.4.2/cat/test/test_empty_gz.c b/dependencies/libarchive-3.4.2/cat/test/test_empty_gz.c new file mode 100644 index 0000000..6181f93 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/test_empty_gz.c @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 2014 Sebastian Freundt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_empty_gz) +{ + const char *reffile = "test_empty.gz"; + int f; + + extract_reference_file(reffile); + f = systemf("%s %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canGzip()) { + assertEqualInt(0, f); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + } else { + skipping("It seems gzip is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/cat/test/test_empty_lz4.c b/dependencies/libarchive-3.4.2/cat/test/test_empty_lz4.c new file mode 100644 index 0000000..9d98e9c --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/test_empty_lz4.c @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 2014 Sebastian Freundt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_empty_lz4) +{ + const char *reffile = "test_empty.lz4"; + int f; + + extract_reference_file(reffile); + f = systemf("%s %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canLz4()) { + assertEqualInt(0, f); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + } else { + skipping("It seems lz4 is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/cat/test/test_empty_xz.c b/dependencies/libarchive-3.4.2/cat/test/test_empty_xz.c new file mode 100644 index 0000000..368ffb5 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/test_empty_xz.c @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 2014 Sebastian Freundt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_empty_xz) +{ + const char *reffile = "test_empty.xz"; + int f; + + extract_reference_file(reffile); + f = systemf("%s %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canXz()) { + assertEqualInt(0, f); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + } else { + skipping("It seems xz is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/cat/test/test_empty_zstd.c b/dependencies/libarchive-3.4.2/cat/test/test_empty_zstd.c new file mode 100644 index 0000000..c2d5ea1 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/test_empty_zstd.c @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 2017 Sean Purcell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_empty_zstd) +{ + const char *reffile = "test_empty.zst"; + int f; + + extract_reference_file(reffile); + f = systemf("%s %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canZstd()) { + assertEqualInt(0, f); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + } else { + skipping("It seems zstd is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/cat/test/test_error.c b/dependencies/libarchive-3.4.2/cat/test/test_error.c new file mode 100644 index 0000000..918af01 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/test_error.c @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 2014 Mike Kazantsev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_error) +{ + const char *reffile = "test_expand.error"; + + assertFileNotExists(reffile); + assert(0 != systemf("%s %s >test.out 2>test.err", testprog, reffile)); + + assertEmptyFile("test.out"); + assertNonEmptyFile("test.err"); +} diff --git a/dependencies/libarchive-3.4.2/cat/test/test_error_mixed.c b/dependencies/libarchive-3.4.2/cat/test/test_error_mixed.c new file mode 100644 index 0000000..7d94fce --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/test_error_mixed.c @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 2014 Mike Kazantsev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_error_mixed) +{ + const char *reffile1 = "test_expand.plain"; + const char *reffile2 = "test_expand.error"; + const char *reffile3 = "test_expand.Z"; + + assertFileNotExists(reffile2); + extract_reference_file(reffile1); + extract_reference_file(reffile3); + assert(0 != systemf("%s %s %s %s >test.out 2>test.err", + testprog, reffile1, reffile2, reffile3)); + + assertTextFileContents( + "contents of test_expand.plain.\n" + "contents of test_expand.Z.\n", "test.out"); + assertNonEmptyFile("test.err"); +} diff --git a/dependencies/libarchive-3.4.2/cat/test/test_expand.Z.uu b/dependencies/libarchive-3.4.2/cat/test/test_expand.Z.uu new file mode 100644 index 0000000..b65efc1 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/test_expand.Z.uu @@ -0,0 +1,3 @@ +begin 664 test_expand.Z +@'YV08]ZXH5-FX!P0;\R`(#B'SI."$<4/&A187"@` +end diff --git a/dependencies/libarchive-3.4.2/cat/test/test_expand.bz2.uu b/dependencies/libarchive-3.4.2/cat/test/test_expand.bz2.uu new file mode 100644 index 0000000..344c1cb --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/test_expand.bz2.uu @@ -0,0 +1,5 @@ +begin 664 test_expand.bz2 +M0EIH.3%!62936=[T@^L [__N000(!!(#!@\P+(, !@4 1 @$" (0 80$ +M(!D0 " 5%)D::#( #0]0 9J%1Z@>H :!B:&33(!"X";"%C@I$+32H/(0MXG +J,EA1G51 WG-"6JV7JKA;/&]$X 6MNH 8'N@3[\XCA_%W)%.%"0WO2#ZP +end diff --git a/dependencies/libarchive-3.4.2/cat/test/test_expand.gz.uu b/dependencies/libarchive-3.4.2/cat/test/test_expand.gz.uu new file mode 100644 index 0000000..528167c --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/test_expand.gz.uu @@ -0,0 +1,4 @@ +begin 664 test_expand.gz +M'XL("-UD1%,``V%S9`!+SL\K2C0N"@`````Y +#!E9+ +` +end diff --git a/dependencies/libarchive-3.4.2/cat/test/test_expand.plain.uu b/dependencies/libarchive-3.4.2/cat/test/test_expand.plain.uu new file mode 100644 index 0000000..ab83c9c --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/test_expand.plain.uu @@ -0,0 +1,3 @@ +begin 664 test_expand.plain +?8V]N=&5N=',@;V8@=&5S=%]E>'!A;F0N<&QA:6XN"@ +end diff --git a/dependencies/libarchive-3.4.2/cat/test/test_expand.xz.uu b/dependencies/libarchive-3.4.2/cat/test/test_expand.xz.uu new file mode 100644 index 0000000..8a92980 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/test_expand.xz.uu @@ -0,0 +1,4 @@ +begin 664 test_expand.xz +M_3=Z6%H 3FUK1& @ A 18 !T+^6C 0 ;8V]N=&5N=',@;V8@=&5S=%]E +G>'!A;F0N>'HN"@!S;^LVAO^3[ !-!R3&JV/'[;S?0$ !%E: +end diff --git a/dependencies/libarchive-3.4.2/cat/test/test_expand.zst.uu b/dependencies/libarchive-3.4.2/cat/test/test_expand.zst.uu new file mode 100644 index 0000000..89c28b1 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/test_expand.zst.uu @@ -0,0 +1,4 @@ +begin 644 test_expand.zst +J*+4O_010Z0``8V]N=&5N=',@;V8@=&5S=%]E>'!A;F0N>G-T+@J;23#F +` +end diff --git a/dependencies/libarchive-3.4.2/cat/test/test_expand_Z.c b/dependencies/libarchive-3.4.2/cat/test/test_expand_Z.c new file mode 100644 index 0000000..d48d497 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/test_expand_Z.c @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 2014 Mike Kazantsev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_expand_Z) +{ + const char *reffile = "test_expand.Z"; + + extract_reference_file(reffile); + assertEqualInt(0, systemf("%s %s >test.out 2>test.err", testprog, reffile)); + + assertTextFileContents("contents of test_expand.Z.\n", "test.out"); + assertEmptyFile("test.err"); +} diff --git a/dependencies/libarchive-3.4.2/cat/test/test_expand_bz2.c b/dependencies/libarchive-3.4.2/cat/test/test_expand_bz2.c new file mode 100644 index 0000000..82f074b --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/test_expand_bz2.c @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2014 Mike Kazantsev + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_expand_bz2) +{ + const char *reffile = "test_expand.bz2"; + int f; + + extract_reference_file(reffile); + f = systemf("%s %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canBzip2()) { + assertEqualInt(0, f); + assertTextFileContents("contents of test_expand.bz2.\n", "test.out"); + assertEmptyFile("test.err"); + } else { + skipping("It seems bzip2 is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/cat/test/test_expand_gz.c b/dependencies/libarchive-3.4.2/cat/test/test_expand_gz.c new file mode 100644 index 0000000..18b715c --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/test_expand_gz.c @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2014 Mike Kazantsev + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_expand_gz) +{ + const char *reffile = "test_expand.gz"; + int f; + + extract_reference_file(reffile); + f = systemf("%s %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canGzip()) { + assertEqualInt(0, f); + assertTextFileContents("contents of test_expand.gz.\n", "test.out"); + assertEmptyFile("test.err"); + } else { + skipping("It seems gzip is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/cat/test/test_expand_lz4.c b/dependencies/libarchive-3.4.2/cat/test/test_expand_lz4.c new file mode 100644 index 0000000..1b1d210 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/test_expand_lz4.c @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2014 Mike Kazantsev + * Copyright (c) 2012, 2014 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_expand_lz4) +{ + const char *reffile = "test_expand.lz4"; + int f; + + extract_reference_file(reffile); + f = systemf("%s %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canLz4()) { + assertEqualInt(0, f); + assertTextFileContents("contents of test_expand.lz4.\n", "test.out"); + assertEmptyFile("test.err"); + } else { + skipping("It seems lz4 is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/cat/test/test_expand_mixed.c b/dependencies/libarchive-3.4.2/cat/test/test_expand_mixed.c new file mode 100644 index 0000000..fa22357 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/test_expand_mixed.c @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 2014 Mike Kazantsev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_expand_mixed) +{ + const char *reffile1 = "test_expand.Z"; + const char *reffile2 = "test_expand.plain"; + + extract_reference_file(reffile1); + extract_reference_file(reffile2); + assertEqualInt(0, systemf("%s %s %s >test.out 2>test.err", + testprog, reffile1, reffile2)); + + assertTextFileContents( + "contents of test_expand.Z.\n" + "contents of test_expand.plain.\n", "test.out"); + assertEmptyFile("test.err"); +} diff --git a/dependencies/libarchive-3.4.2/cat/test/test_expand_plain.c b/dependencies/libarchive-3.4.2/cat/test/test_expand_plain.c new file mode 100644 index 0000000..8b22769 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/test_expand_plain.c @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 2014 Mike Kazantsev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_expand_plain) +{ + const char *reffile = "test_expand.plain"; + + extract_reference_file(reffile); + assertEqualInt(0, systemf("%s %s >test.out 2>test.err", testprog, reffile)); + + assertTextFileContents("contents of test_expand.plain.\n", "test.out"); + assertEmptyFile("test.err"); +} diff --git a/dependencies/libarchive-3.4.2/cat/test/test_expand_xz.c b/dependencies/libarchive-3.4.2/cat/test/test_expand_xz.c new file mode 100644 index 0000000..99f87bf --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/test_expand_xz.c @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2014 Mike Kazantsev + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_expand_xz) +{ + const char *reffile = "test_expand.xz"; + int f; + + extract_reference_file(reffile); + f = systemf("%s %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canXz()) { + assertEqualInt(0, f); + assertTextFileContents("contents of test_expand.xz.\n", "test.out"); + assertEmptyFile("test.err"); + } else { + skipping("It seems xz is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/cat/test/test_expand_zstd.c b/dependencies/libarchive-3.4.2/cat/test/test_expand_zstd.c new file mode 100644 index 0000000..23d9182 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/test_expand_zstd.c @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 2017 Sean Purcell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_expand_zstd) +{ + const char *reffile = "test_expand.zst"; + int f; + + extract_reference_file(reffile); + f = systemf("%s %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canZstd()) { + assertEqualInt(0, f); + assertTextFileContents("contents of test_expand.zst.\n", "test.out"); + assertEmptyFile("test.err"); + } else { + skipping("It seems zstd is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/cat/test/test_help.c b/dependencies/libarchive-3.4.2/cat/test/test_help.c new file mode 100644 index 0000000..4ed47a0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/test_help.c @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +/* + * Test that "--help", "-h", and "-W help" options all work and + * generate reasonable output. + */ + +static int +in_first_line(const char *p, const char *substring) +{ + size_t l = strlen(substring); + + while (*p != '\0' && *p != '\n') { + if (memcmp(p, substring, l) == 0) + return (1); + ++p; + } + return (0); +} + +DEFINE_TEST(test_help) +{ + int r; + char *p; + size_t plen; + + /* Exercise --help option. */ + r = systemf("%s --help >help.stdout 2>help.stderr", testprog); + assertEqualInt(r, 0); + failure("--help should generate nothing to stderr."); + assertEmptyFile("help.stderr"); + /* Help message should start with name of program. */ + p = slurpfile(&plen, "help.stdout"); + failure("Help output should be long enough."); + assert(plen >= 6); + failure("First line of help output should contain 'bsdcat': %s", p); + assert(in_first_line(p, "bsdcat")); + /* + * TODO: Extend this check to further verify that --help output + * looks approximately right. + */ + free(p); + + /* -h option should generate the same output. */ + r = systemf("%s -h >h.stdout 2>h.stderr", testprog); + assertEqualInt(r, 0); + failure("-h should generate nothing to stderr."); + assertEmptyFile("h.stderr"); + failure("stdout should be same for -h and --help"); + assertEqualFile("h.stdout", "help.stdout"); +} diff --git a/dependencies/libarchive-3.4.2/cat/test/test_stdin.c b/dependencies/libarchive-3.4.2/cat/test/test_stdin.c new file mode 100644 index 0000000..cea5eb0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/test_stdin.c @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2017 Sean Purcell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +#if !defined(_WIN32) || defined(__CYGWIN__) +#define DEV_NULL "/dev/null" +#else +#define DEV_NULL "NUL" +#endif + +DEFINE_TEST(test_stdin) +{ + int f; + + f = systemf("%s <%s >test.out 2>test.err", testprog, DEV_NULL); + assertEqualInt(0, f); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); +} + diff --git a/dependencies/libarchive-3.4.2/cat/test/test_version.c b/dependencies/libarchive-3.4.2/cat/test/test_version.c new file mode 100644 index 0000000..51a4fd4 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cat/test/test_version.c @@ -0,0 +1,34 @@ +/*- + * Copyright (c) 2003-2017 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +/* + * Test that --version option works and generates reasonable output. + */ + +DEFINE_TEST(test_version) +{ + assertVersion(testprog, "bsdcat"); +} diff --git a/dependencies/libarchive-3.4.2/config.h.in b/dependencies/libarchive-3.4.2/config.h.in new file mode 100644 index 0000000..1a94a69 --- /dev/null +++ b/dependencies/libarchive-3.4.2/config.h.in @@ -0,0 +1,1428 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Darwin ACL support */ +#undef ARCHIVE_ACL_DARWIN + +/* FreeBSD ACL support */ +#undef ARCHIVE_ACL_FREEBSD + +/* FreeBSD NFSv4 ACL support */ +#undef ARCHIVE_ACL_FREEBSD_NFS4 + +/* Linux POSIX.1e ACL support via libacl */ +#undef ARCHIVE_ACL_LIBACL + +/* Linux NFSv4 ACL support via librichacl */ +#undef ARCHIVE_ACL_LIBRICHACL + +/* Solaris ACL support */ +#undef ARCHIVE_ACL_SUNOS + +/* Solaris NFSv4 ACL support */ +#undef ARCHIVE_ACL_SUNOS_NFS4 + +/* MD5 via ARCHIVE_CRYPTO_MD5_LIBC supported. */ +#undef ARCHIVE_CRYPTO_MD5_LIBC + +/* MD5 via ARCHIVE_CRYPTO_MD5_LIBMD supported. */ +#undef ARCHIVE_CRYPTO_MD5_LIBMD + +/* MD5 via ARCHIVE_CRYPTO_MD5_LIBSYSTEM supported. */ +#undef ARCHIVE_CRYPTO_MD5_LIBSYSTEM + +/* MD5 via ARCHIVE_CRYPTO_MD5_MBEDTLS supported. */ +#undef ARCHIVE_CRYPTO_MD5_MBEDTLS + +/* MD5 via ARCHIVE_CRYPTO_MD5_NETTLE supported. */ +#undef ARCHIVE_CRYPTO_MD5_NETTLE + +/* MD5 via ARCHIVE_CRYPTO_MD5_OPENSSL supported. */ +#undef ARCHIVE_CRYPTO_MD5_OPENSSL + +/* MD5 via ARCHIVE_CRYPTO_MD5_WIN supported. */ +#undef ARCHIVE_CRYPTO_MD5_WIN + +/* RMD160 via ARCHIVE_CRYPTO_RMD160_LIBC supported. */ +#undef ARCHIVE_CRYPTO_RMD160_LIBC + +/* RMD160 via ARCHIVE_CRYPTO_RMD160_LIBMD supported. */ +#undef ARCHIVE_CRYPTO_RMD160_LIBMD + +/* RMD160 via ARCHIVE_CRYPTO_RMD160_MBEDTLS supported. */ +#undef ARCHIVE_CRYPTO_RMD160_MBEDTLS + +/* RMD160 via ARCHIVE_CRYPTO_RMD160_NETTLE supported. */ +#undef ARCHIVE_CRYPTO_RMD160_NETTLE + +/* RMD160 via ARCHIVE_CRYPTO_RMD160_OPENSSL supported. */ +#undef ARCHIVE_CRYPTO_RMD160_OPENSSL + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBC supported. */ +#undef ARCHIVE_CRYPTO_SHA1_LIBC + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBMD supported. */ +#undef ARCHIVE_CRYPTO_SHA1_LIBMD + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBSYSTEM supported. */ +#undef ARCHIVE_CRYPTO_SHA1_LIBSYSTEM + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_MBEDTLS supported. */ +#undef ARCHIVE_CRYPTO_SHA1_MBEDTLS + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_NETTLE supported. */ +#undef ARCHIVE_CRYPTO_SHA1_NETTLE + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_OPENSSL supported. */ +#undef ARCHIVE_CRYPTO_SHA1_OPENSSL + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_WIN supported. */ +#undef ARCHIVE_CRYPTO_SHA1_WIN + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC supported. */ +#undef ARCHIVE_CRYPTO_SHA256_LIBC + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC2 supported. */ +#undef ARCHIVE_CRYPTO_SHA256_LIBC2 + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC3 supported. */ +#undef ARCHIVE_CRYPTO_SHA256_LIBC3 + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBMD supported. */ +#undef ARCHIVE_CRYPTO_SHA256_LIBMD + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBSYSTEM supported. */ +#undef ARCHIVE_CRYPTO_SHA256_LIBSYSTEM + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_MBEDTLS supported. */ +#undef ARCHIVE_CRYPTO_SHA256_MBEDTLS + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_NETTLE supported. */ +#undef ARCHIVE_CRYPTO_SHA256_NETTLE + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_OPENSSL supported. */ +#undef ARCHIVE_CRYPTO_SHA256_OPENSSL + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_WIN supported. */ +#undef ARCHIVE_CRYPTO_SHA256_WIN + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC supported. */ +#undef ARCHIVE_CRYPTO_SHA384_LIBC + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC2 supported. */ +#undef ARCHIVE_CRYPTO_SHA384_LIBC2 + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC3 supported. */ +#undef ARCHIVE_CRYPTO_SHA384_LIBC3 + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBSYSTEM supported. */ +#undef ARCHIVE_CRYPTO_SHA384_LIBSYSTEM + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_MBEDTLS supported. */ +#undef ARCHIVE_CRYPTO_SHA384_MBEDTLS + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_NETTLE supported. */ +#undef ARCHIVE_CRYPTO_SHA384_NETTLE + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_OPENSSL supported. */ +#undef ARCHIVE_CRYPTO_SHA384_OPENSSL + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_WIN supported. */ +#undef ARCHIVE_CRYPTO_SHA384_WIN + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC supported. */ +#undef ARCHIVE_CRYPTO_SHA512_LIBC + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC2 supported. */ +#undef ARCHIVE_CRYPTO_SHA512_LIBC2 + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC3 supported. */ +#undef ARCHIVE_CRYPTO_SHA512_LIBC3 + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBMD supported. */ +#undef ARCHIVE_CRYPTO_SHA512_LIBMD + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBSYSTEM supported. */ +#undef ARCHIVE_CRYPTO_SHA512_LIBSYSTEM + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_MBEDTLS supported. */ +#undef ARCHIVE_CRYPTO_SHA512_MBEDTLS + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_NETTLE supported. */ +#undef ARCHIVE_CRYPTO_SHA512_NETTLE + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_OPENSSL supported. */ +#undef ARCHIVE_CRYPTO_SHA512_OPENSSL + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_WIN supported. */ +#undef ARCHIVE_CRYPTO_SHA512_WIN + +/* AIX xattr support */ +#undef ARCHIVE_XATTR_AIX + +/* Darwin xattr support */ +#undef ARCHIVE_XATTR_DARWIN + +/* FreeBSD xattr support */ +#undef ARCHIVE_XATTR_FREEBSD + +/* Linux xattr support */ +#undef ARCHIVE_XATTR_LINUX + +/* Version number of bsdcat */ +#undef BSDCAT_VERSION_STRING + +/* Version number of bsdcpio */ +#undef BSDCPIO_VERSION_STRING + +/* Version number of bsdtar */ +#undef BSDTAR_VERSION_STRING + +/* Define to 1 if the system has the type `ace_t'. */ +#undef HAVE_ACE_T + +/* Define to 1 if you have the `acl' function. */ +#undef HAVE_ACL + +/* Define to 1 if the system has the type `aclent_t'. */ +#undef HAVE_ACLENT_T + +/* Define to 1 if you have the `acl_add_flag_np' function. */ +#undef HAVE_ACL_ADD_FLAG_NP + +/* Define to 1 if you have the `acl_add_perm' function. */ +#undef HAVE_ACL_ADD_PERM + +/* Define to 1 if you have the `acl_clear_flags_np' function. */ +#undef HAVE_ACL_CLEAR_FLAGS_NP + +/* Define to 1 if you have the `acl_clear_perms' function. */ +#undef HAVE_ACL_CLEAR_PERMS + +/* Define to 1 if you have the `acl_create_entry' function. */ +#undef HAVE_ACL_CREATE_ENTRY + +/* Define to 1 if you have the `acl_delete_def_file' function. */ +#undef HAVE_ACL_DELETE_DEF_FILE + +/* Define to 1 if the system has the type `acl_entry_t'. */ +#undef HAVE_ACL_ENTRY_T + +/* Define to 1 if you have the `acl_free' function. */ +#undef HAVE_ACL_FREE + +/* Define to 1 if you have the `acl_get_brand_np' function. */ +#undef HAVE_ACL_GET_BRAND_NP + +/* Define to 1 if you have the `acl_get_entry' function. */ +#undef HAVE_ACL_GET_ENTRY + +/* Define to 1 if you have the `acl_get_entry_type_np' function. */ +#undef HAVE_ACL_GET_ENTRY_TYPE_NP + +/* Define to 1 if you have the `acl_get_fd' function. */ +#undef HAVE_ACL_GET_FD + +/* Define to 1 if you have the `acl_get_fd_np' function. */ +#undef HAVE_ACL_GET_FD_NP + +/* Define to 1 if you have the `acl_get_file' function. */ +#undef HAVE_ACL_GET_FILE + +/* Define to 1 if you have the `acl_get_flagset_np' function. */ +#undef HAVE_ACL_GET_FLAGSET_NP + +/* Define to 1 if you have the `acl_get_flag_np' function. */ +#undef HAVE_ACL_GET_FLAG_NP + +/* Define to 1 if you have the `acl_get_link_np' function. */ +#undef HAVE_ACL_GET_LINK_NP + +/* Define to 1 if you have the `acl_get_perm' function. */ +#undef HAVE_ACL_GET_PERM + +/* Define to 1 if you have the `acl_get_permset' function. */ +#undef HAVE_ACL_GET_PERMSET + +/* Define to 1 if you have the `acl_get_perm_np' function. */ +#undef HAVE_ACL_GET_PERM_NP + +/* Define to 1 if you have the `acl_get_qualifier' function. */ +#undef HAVE_ACL_GET_QUALIFIER + +/* Define to 1 if you have the `acl_get_tag_type' function. */ +#undef HAVE_ACL_GET_TAG_TYPE + +/* Define to 1 if you have the `acl_init' function. */ +#undef HAVE_ACL_INIT + +/* Define to 1 if you have the `acl_is_trivial_np' function. */ +#undef HAVE_ACL_IS_TRIVIAL_NP + +/* Define to 1 if you have the header file. */ +#undef HAVE_ACL_LIBACL_H + +/* Define to 1 if the system has the type `acl_permset_t'. */ +#undef HAVE_ACL_PERMSET_T + +/* Define to 1 if you have the `acl_set_entry_type_np' function. */ +#undef HAVE_ACL_SET_ENTRY_TYPE_NP + +/* Define to 1 if you have the `acl_set_fd' function. */ +#undef HAVE_ACL_SET_FD + +/* Define to 1 if you have the `acl_set_fd_np' function. */ +#undef HAVE_ACL_SET_FD_NP + +/* Define to 1 if you have the `acl_set_file' function. */ +#undef HAVE_ACL_SET_FILE + +/* Define to 1 if you have the `acl_set_link_np' function. */ +#undef HAVE_ACL_SET_LINK_NP + +/* Define to 1 if you have the `acl_set_qualifier' function. */ +#undef HAVE_ACL_SET_QUALIFIER + +/* Define to 1 if you have the `acl_set_tag_type' function. */ +#undef HAVE_ACL_SET_TAG_TYPE + +/* Define to 1 if the system has the type `acl_t'. */ +#undef HAVE_ACL_T + +/* Define to 1 if the system has the type `acl_tag_t'. */ +#undef HAVE_ACL_TAG_T + +/* Define to 1 if you have the `arc4random_buf' function. */ +#undef HAVE_ARC4RANDOM_BUF + +/* Define to 1 if you have the header file. */ +#undef HAVE_ATTR_XATTR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_BCRYPT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_BLAKE2_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_BZLIB_H + +/* Define to 1 if you have the `chflags' function. */ +#undef HAVE_CHFLAGS + +/* Define to 1 if you have the `chown' function. */ +#undef HAVE_CHOWN + +/* Define to 1 if you have the `chroot' function. */ +#undef HAVE_CHROOT + +/* Define to 1 if you have the header file. */ +#undef HAVE_COPYFILE_H + +/* Define to 1 if you have the `ctime_r' function. */ +#undef HAVE_CTIME_R + +/* Define to 1 if you have the header file. */ +#undef HAVE_CTYPE_H + +/* Define to 1 if you have the `cygwin_conv_path' function. */ +#undef HAVE_CYGWIN_CONV_PATH + +/* Define to 1 if you have the declaration of `ACE_GETACL', and to 0 if you + don't. */ +#undef HAVE_DECL_ACE_GETACL + +/* Define to 1 if you have the declaration of `ACE_GETACLCNT', and to 0 if you + don't. */ +#undef HAVE_DECL_ACE_GETACLCNT + +/* Define to 1 if you have the declaration of `ACE_SETACL', and to 0 if you + don't. */ +#undef HAVE_DECL_ACE_SETACL + +/* Define to 1 if you have the declaration of `ACL_SYNCHRONIZE', and to 0 if + you don't. */ +#undef HAVE_DECL_ACL_SYNCHRONIZE + +/* Define to 1 if you have the declaration of `ACL_TYPE_EXTENDED', and to 0 if + you don't. */ +#undef HAVE_DECL_ACL_TYPE_EXTENDED + +/* Define to 1 if you have the declaration of `ACL_TYPE_NFS4', and to 0 if you + don't. */ +#undef HAVE_DECL_ACL_TYPE_NFS4 + +/* Define to 1 if you have the declaration of `ACL_USER', and to 0 if you + don't. */ +#undef HAVE_DECL_ACL_USER + +/* Define to 1 if you have the declaration of `EXTATTR_NAMESPACE_USER', and to + 0 if you don't. */ +#undef HAVE_DECL_EXTATTR_NAMESPACE_USER + +/* Define to 1 if you have the declaration of `GETACL', and to 0 if you don't. + */ +#undef HAVE_DECL_GETACL + +/* Define to 1 if you have the declaration of `GETACLCNT', and to 0 if you + don't. */ +#undef HAVE_DECL_GETACLCNT + +/* Define to 1 if you have the declaration of `INT32_MAX', and to 0 if you + don't. */ +#undef HAVE_DECL_INT32_MAX + +/* Define to 1 if you have the declaration of `INT32_MIN', and to 0 if you + don't. */ +#undef HAVE_DECL_INT32_MIN + +/* Define to 1 if you have the declaration of `INT64_MAX', and to 0 if you + don't. */ +#undef HAVE_DECL_INT64_MAX + +/* Define to 1 if you have the declaration of `INT64_MIN', and to 0 if you + don't. */ +#undef HAVE_DECL_INT64_MIN + +/* Define to 1 if you have the declaration of `INTMAX_MAX', and to 0 if you + don't. */ +#undef HAVE_DECL_INTMAX_MAX + +/* Define to 1 if you have the declaration of `INTMAX_MIN', and to 0 if you + don't. */ +#undef HAVE_DECL_INTMAX_MIN + +/* Define to 1 if you have the declaration of `SETACL', and to 0 if you don't. + */ +#undef HAVE_DECL_SETACL + +/* Define to 1 if you have the declaration of `SIZE_MAX', and to 0 if you + don't. */ +#undef HAVE_DECL_SIZE_MAX + +/* Define to 1 if you have the declaration of `SSIZE_MAX', and to 0 if you + don't. */ +#undef HAVE_DECL_SSIZE_MAX + +/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you + don't. */ +#undef HAVE_DECL_STRERROR_R + +/* Define to 1 if you have the declaration of `UINT32_MAX', and to 0 if you + don't. */ +#undef HAVE_DECL_UINT32_MAX + +/* Define to 1 if you have the declaration of `UINT64_MAX', and to 0 if you + don't. */ +#undef HAVE_DECL_UINT64_MAX + +/* Define to 1 if you have the declaration of `UINTMAX_MAX', and to 0 if you + don't. */ +#undef HAVE_DECL_UINTMAX_MAX + +/* Define to 1 if you have the declaration of `XATTR_NOFOLLOW', and to 0 if + you don't. */ +#undef HAVE_DECL_XATTR_NOFOLLOW + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_DIRENT_H + +/* Define to 1 if you have a dirfd function or macro */ +#undef HAVE_DIRFD + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +#undef HAVE_DOPRNT + +/* Define to 1 if nl_langinfo supports D_MD_ORDER */ +#undef HAVE_D_MD_ORDER + +/* A possible errno value for invalid file format errors */ +#undef HAVE_EFTYPE + +/* A possible errno value for invalid file format errors */ +#undef HAVE_EILSEQ + +/* Define to 1 if you have the header file. */ +#undef HAVE_ERRNO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_EXPAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_EXT2FS_EXT2_FS_H + +/* Define to 1 if you have the `extattr_get_fd' function. */ +#undef HAVE_EXTATTR_GET_FD + +/* Define to 1 if you have the `extattr_get_file' function. */ +#undef HAVE_EXTATTR_GET_FILE + +/* Define to 1 if you have the `extattr_get_link' function. */ +#undef HAVE_EXTATTR_GET_LINK + +/* Define to 1 if you have the `extattr_list_fd' function. */ +#undef HAVE_EXTATTR_LIST_FD + +/* Define to 1 if you have the `extattr_list_file' function. */ +#undef HAVE_EXTATTR_LIST_FILE + +/* Define to 1 if you have the `extattr_list_link' function. */ +#undef HAVE_EXTATTR_LIST_LINK + +/* Define to 1 if you have the `extattr_set_fd' function. */ +#undef HAVE_EXTATTR_SET_FD + +/* Define to 1 if you have the `extattr_set_link' function. */ +#undef HAVE_EXTATTR_SET_LINK + +/* Define to 1 if you have the `facl' function. */ +#undef HAVE_FACL + +/* Define to 1 if you have the `fchdir' function. */ +#undef HAVE_FCHDIR + +/* Define to 1 if you have the `fchflags' function. */ +#undef HAVE_FCHFLAGS + +/* Define to 1 if you have the `fchmod' function. */ +#undef HAVE_FCHMOD + +/* Define to 1 if you have the `fchown' function. */ +#undef HAVE_FCHOWN + +/* Define to 1 if you have the `fcntl' function. */ +#undef HAVE_FCNTL + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the `fdopendir' function. */ +#undef HAVE_FDOPENDIR + +/* Define to 1 if you have the `fgetea' function. */ +#undef HAVE_FGETEA + +/* Define to 1 if you have the `fgetxattr' function. */ +#undef HAVE_FGETXATTR + +/* Define to 1 if you have the `flistea' function. */ +#undef HAVE_FLISTEA + +/* Define to 1 if you have the `flistxattr' function. */ +#undef HAVE_FLISTXATTR + +/* Define to 1 if you have the `fork' function. */ +#undef HAVE_FORK + +/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ +#undef HAVE_FSEEKO + +/* Define to 1 if you have the `fsetea' function. */ +#undef HAVE_FSETEA + +/* Define to 1 if you have the `fsetxattr' function. */ +#undef HAVE_FSETXATTR + +/* Define to 1 if you have the `fstat' function. */ +#undef HAVE_FSTAT + +/* Define to 1 if you have the `fstatat' function. */ +#undef HAVE_FSTATAT + +/* Define to 1 if you have the `fstatfs' function. */ +#undef HAVE_FSTATFS + +/* Define to 1 if you have the `fstatvfs' function. */ +#undef HAVE_FSTATVFS + +/* Define to 1 if you have the `ftruncate' function. */ +#undef HAVE_FTRUNCATE + +/* Define to 1 if you have the `futimens' function. */ +#undef HAVE_FUTIMENS + +/* Define to 1 if you have the `futimes' function. */ +#undef HAVE_FUTIMES + +/* Define to 1 if you have the `futimesat' function. */ +#undef HAVE_FUTIMESAT + +/* Define to 1 if you have the `getea' function. */ +#undef HAVE_GETEA + +/* Define to 1 if you have the `geteuid' function. */ +#undef HAVE_GETEUID + +/* Define to 1 if you have the `getgrgid_r' function. */ +#undef HAVE_GETGRGID_R + +/* Define to 1 if you have the `getgrnam_r' function. */ +#undef HAVE_GETGRNAM_R + +/* Define to 1 if you have the `getpid' function. */ +#undef HAVE_GETPID + +/* Define to 1 if you have the `getpwnam_r' function. */ +#undef HAVE_GETPWNAM_R + +/* Define to 1 if you have the `getpwuid_r' function. */ +#undef HAVE_GETPWUID_R + +/* Define to 1 if you have the `getvfsbyname' function. */ +#undef HAVE_GETVFSBYNAME + +/* Define to 1 if you have the `getxattr' function. */ +#undef HAVE_GETXATTR + +/* Define to 1 if you have the `gmtime_r' function. */ +#undef HAVE_GMTIME_R + +/* Define to 1 if you have the header file. */ +#undef HAVE_GRP_H + +/* Define if you have the iconv() function and it works. */ +#undef HAVE_ICONV + +/* Define to 1 if you have the header file. */ +#undef HAVE_ICONV_H + +/* Define to 1 if the system has the type `intmax_t'. */ +#undef HAVE_INTMAX_T + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_IO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LANGINFO_H + +/* Define to 1 if you have the `lchflags' function. */ +#undef HAVE_LCHFLAGS + +/* Define to 1 if you have the `lchmod' function. */ +#undef HAVE_LCHMOD + +/* Define to 1 if you have the `lchown' function. */ +#undef HAVE_LCHOWN + +/* Define to 1 if you have the `lgetea' function. */ +#undef HAVE_LGETEA + +/* Define to 1 if you have the `lgetxattr' function. */ +#undef HAVE_LGETXATTR + +/* Define to 1 if you have the `acl' library (-lacl). */ +#undef HAVE_LIBACL + +/* Define to 1 if you have the `b2' library (-lb2). */ +#undef HAVE_LIBB2 + +/* Define to 1 if you have the `bz2' library (-lbz2). */ +#undef HAVE_LIBBZ2 + +/* Define to 1 if you have the `charset' library (-lcharset). */ +#undef HAVE_LIBCHARSET + +/* Define to 1 if you have the `crypto' library (-lcrypto). */ +#undef HAVE_LIBCRYPTO + +/* Define to 1 if you have the `eay32' library (-leay32). */ +#undef HAVE_LIBEAY32 + +/* Define to 1 if you have the `eay64' library (-leay64). */ +#undef HAVE_LIBEAY64 + +/* Define to 1 if you have the `expat' library (-lexpat). */ +#undef HAVE_LIBEXPAT + +/* Define to 1 if you have the `lz4' library (-llz4). */ +#undef HAVE_LIBLZ4 + +/* Define to 1 if you have the `lzma' library (-llzma). */ +#undef HAVE_LIBLZMA + +/* Define to 1 if you have the `lzo2' library (-llzo2). */ +#undef HAVE_LIBLZO2 + +/* Define to 1 if you have the `mbedcrypto' library (-lmbedcrypto). */ +#undef HAVE_LIBMBEDCRYPTO + +/* Define to 1 if you have the `md' library (-lmd). */ +#undef HAVE_LIBMD + +/* Define to 1 if you have the `nettle' library (-lnettle). */ +#undef HAVE_LIBNETTLE + +/* Define to 1 if you have the `pcre' library (-lpcre). */ +#undef HAVE_LIBPCRE + +/* Define to 1 if you have the `pcreposix' library (-lpcreposix). */ +#undef HAVE_LIBPCREPOSIX + +/* Define to 1 if you have the `regex' library (-lregex). */ +#undef HAVE_LIBREGEX + +/* Define to 1 if you have the `richacl' library (-lrichacl). */ +#undef HAVE_LIBRICHACL + +/* Define to 1 if you have the `xml2' library (-lxml2). */ +#undef HAVE_LIBXML2 + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBXML_XMLREADER_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBXML_XMLWRITER_H + +/* Define to 1 if you have the `z' library (-lz). */ +#undef HAVE_LIBZ + +/* Define to 1 if you have the `zstd' library (-lzstd). */ +#undef HAVE_LIBZSTD + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define to 1 if you have the `link' function. */ +#undef HAVE_LINK + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_FIEMAP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_FS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_MAGIC_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_TYPES_H + +/* Define to 1 if you have the `listea' function. */ +#undef HAVE_LISTEA + +/* Define to 1 if you have the `listxattr' function. */ +#undef HAVE_LISTXATTR + +/* Define to 1 if you have the `llistea' function. */ +#undef HAVE_LLISTEA + +/* Define to 1 if you have the `llistxattr' function. */ +#undef HAVE_LLISTXATTR + +/* Define to 1 if you have the header file. */ +#undef HAVE_LOCALCHARSET_H + +/* Define to 1 if you have the `locale_charset' function. */ +#undef HAVE_LOCALE_CHARSET + +/* Define to 1 if you have the header file. */ +#undef HAVE_LOCALE_H + +/* Define to 1 if you have the `localtime_r' function. */ +#undef HAVE_LOCALTIME_R + +/* Define to 1 if the system has the type `long long int'. */ +#undef HAVE_LONG_LONG_INT + +/* Define to 1 if you have the `lsetea' function. */ +#undef HAVE_LSETEA + +/* Define to 1 if you have the `lsetxattr' function. */ +#undef HAVE_LSETXATTR + +/* Define to 1 if you have the `lstat' function. */ +#undef HAVE_LSTAT + +/* Define to 1 if `lstat' has the bug that it succeeds when given the + zero-length file name argument. */ +#undef HAVE_LSTAT_EMPTY_STRING_BUG + +/* Define to 1 if you have the `lutimes' function. */ +#undef HAVE_LUTIMES + +/* Define to 1 if you have the header file. */ +#undef HAVE_LZ4HC_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LZ4_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LZMA_H + +/* Define to 1 if you have the `lzma_stream_encoder_mt' function. */ +#undef HAVE_LZMA_STREAM_ENCODER_MT + +/* Define to 1 if you have the header file. */ +#undef HAVE_LZO_LZO1X_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LZO_LZOCONF_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MBEDTLS_AES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MBEDTLS_MD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MBEDTLS_PKCS5_H + +/* Define to 1 if you have the `mbrtowc' function. */ +#undef HAVE_MBRTOWC + +/* Define to 1 if you have the `mbr_gid_to_uuid' function. */ +#undef HAVE_MBR_GID_TO_UUID + +/* Define to 1 if you have the `mbr_uid_to_uuid' function. */ +#undef HAVE_MBR_UID_TO_UUID + +/* Define to 1 if you have the `mbr_uuid_to_id' function. */ +#undef HAVE_MBR_UUID_TO_ID + +/* Define to 1 if you have the header file. */ +#undef HAVE_MD5_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMBERSHIP_H + +/* Define to 1 if you have the `memmove' function. */ +#undef HAVE_MEMMOVE + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `memset' function. */ +#undef HAVE_MEMSET + +/* Define to 1 if you have the `mkdir' function. */ +#undef HAVE_MKDIR + +/* Define to 1 if you have the `mkfifo' function. */ +#undef HAVE_MKFIFO + +/* Define to 1 if you have the `mknod' function. */ +#undef HAVE_MKNOD + +/* Define to 1 if you have the `mkstemp' function. */ +#undef HAVE_MKSTEMP + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +#undef HAVE_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETTLE_AES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETTLE_HMAC_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETTLE_MD5_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETTLE_PBKDF2_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETTLE_RIPEMD160_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETTLE_SHA_H + +/* Define to 1 if you have the `nl_langinfo' function. */ +#undef HAVE_NL_LANGINFO + +/* Define to 1 if you have the `openat' function. */ +#undef HAVE_OPENAT + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_EVP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_PATHS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_PCREPOSIX_H + +/* Define to 1 if you have the `pipe' function. */ +#undef HAVE_PIPE + +/* Define to 1 if you have the `PKCS5_PBKDF2_HMAC_SHA1' function. */ +#undef HAVE_PKCS5_PBKDF2_HMAC_SHA1 + +/* Define to 1 if you have the `poll' function. */ +#undef HAVE_POLL + +/* Define to 1 if you have the header file. */ +#undef HAVE_POLL_H + +/* Define to 1 if you have the `posix_spawnp' function. */ +#undef HAVE_POSIX_SPAWNP + +/* Define to 1 if you have the header file. */ +#undef HAVE_PTHREAD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_PWD_H + +/* Define to 1 if you have a POSIX compatible readdir_r */ +#undef HAVE_READDIR_R + +/* Define to 1 if you have the `readlink' function. */ +#undef HAVE_READLINK + +/* Define to 1 if you have the `readlinkat' function. */ +#undef HAVE_READLINKAT + +/* Define to 1 if you have the `readpassphrase' function. */ +#undef HAVE_READPASSPHRASE + +/* Define to 1 if you have the header file. */ +#undef HAVE_READPASSPHRASE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_REGEX_H + +/* Define to 1 if you have the `richacl_alloc' function. */ +#undef HAVE_RICHACL_ALLOC + +/* Define to 1 if you have the `richacl_equiv_mode' function. */ +#undef HAVE_RICHACL_EQUIV_MODE + +/* Define to 1 if you have the `richacl_free' function. */ +#undef HAVE_RICHACL_FREE + +/* Define to 1 if you have the `richacl_get_fd' function. */ +#undef HAVE_RICHACL_GET_FD + +/* Define to 1 if you have the `richacl_get_file' function. */ +#undef HAVE_RICHACL_GET_FILE + +/* Define to 1 if you have the `richacl_set_fd' function. */ +#undef HAVE_RICHACL_SET_FD + +/* Define to 1 if you have the `richacl_set_file' function. */ +#undef HAVE_RICHACL_SET_FILE + +/* Define to 1 if you have the header file. */ +#undef HAVE_RIPEMD_H + +/* Define to 1 if you have the `select' function. */ +#undef HAVE_SELECT + +/* Define to 1 if you have the `setenv' function. */ +#undef HAVE_SETENV + +/* Define to 1 if you have the `setlocale' function. */ +#undef HAVE_SETLOCALE + +/* Define to 1 if you have the `setxattr' function. */ +#undef HAVE_SETXATTR + +/* Define to 1 if you have the header file. */ +#undef HAVE_SHA256_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SHA512_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SHA_H + +/* Define to 1 if you have the `sigaction' function. */ +#undef HAVE_SIGACTION + +/* Define to 1 if you have the header file. */ +#undef HAVE_SIGNAL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SPAWN_H + +/* Define to 1 if you have the `statfs' function. */ +#undef HAVE_STATFS + +/* Define to 1 if you have the `statvfs' function. */ +#undef HAVE_STATVFS + +/* Define to 1 if `stat' has the bug that it succeeds when given the + zero-length file name argument. */ +#undef HAVE_STAT_EMPTY_STRING_BUG + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDARG_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strchr' function. */ +#undef HAVE_STRCHR + +/* Define to 1 if you have the `strdup' function. */ +#undef HAVE_STRDUP + +/* Define to 1 if you have the `strerror' function. */ +#undef HAVE_STRERROR + +/* Define to 1 if you have the `strerror_r' function. */ +#undef HAVE_STRERROR_R + +/* Define to 1 if you have the `strftime' function. */ +#undef HAVE_STRFTIME + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strncpy_s' function. */ +#undef HAVE_STRNCPY_S + +/* Define to 1 if you have the `strrchr' function. */ +#undef HAVE_STRRCHR + +/* Define to 1 if the system has the type `struct richace'. */ +#undef HAVE_STRUCT_RICHACE + +/* Define to 1 if the system has the type `struct richacl'. */ +#undef HAVE_STRUCT_RICHACL + +/* Define to 1 if `f_namemax' is a member of `struct statfs'. */ +#undef HAVE_STRUCT_STATFS_F_NAMEMAX + +/* Define to 1 if `f_iosize' is a member of `struct statvfs'. */ +#undef HAVE_STRUCT_STATVFS_F_IOSIZE + +/* Define to 1 if `st_birthtime' is a member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_BIRTHTIME + +/* Define to 1 if `st_birthtimespec.tv_nsec' is a member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC + +/* Define to 1 if `st_blksize' is a member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_BLKSIZE + +/* Define to 1 if `st_flags' is a member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_FLAGS + +/* Define to 1 if `st_mtimespec.tv_nsec' is a member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC + +/* Define to 1 if `st_mtime_n' is a member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_MTIME_N + +/* Define to 1 if `st_mtime_usec' is a member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_MTIME_USEC + +/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC + +/* Define to 1 if `st_umtime' is a member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_UMTIME + +/* Define to 1 if `tm_gmtoff' is a member of `struct tm'. */ +#undef HAVE_STRUCT_TM_TM_GMTOFF + +/* Define to 1 if `__tm_gmtoff' is a member of `struct tm'. */ +#undef HAVE_STRUCT_TM___TM_GMTOFF + +/* Define to 1 if the system has the type `struct vfsconf'. */ +#undef HAVE_STRUCT_VFSCONF + +/* Define to 1 if the system has the type `struct xvfsconf'. */ +#undef HAVE_STRUCT_XVFSCONF + +/* Define to 1 if you have the `symlink' function. */ +#undef HAVE_SYMLINK + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_ACL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_CDEFS_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_DIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_EA_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_EXTATTR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_IOCTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MKDEV_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MOUNT_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_POLL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_RICHACL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SELECT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STATFS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STATVFS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SYSMACROS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UTIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UTSNAME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_VFS_H + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#undef HAVE_SYS_WAIT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_XATTR_H + +/* Define to 1 if you have the `timegm' function. */ +#undef HAVE_TIMEGM + +/* Define to 1 if you have the header file. */ +#undef HAVE_TIME_H + +/* Define to 1 if you have the `tzset' function. */ +#undef HAVE_TZSET + +/* Define to 1 if the system has the type `uintmax_t'. */ +#undef HAVE_UINTMAX_T + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `unlinkat' function. */ +#undef HAVE_UNLINKAT + +/* Define to 1 if you have the `unsetenv' function. */ +#undef HAVE_UNSETENV + +/* Define to 1 if the system has the type `unsigned long long'. */ +#undef HAVE_UNSIGNED_LONG_LONG + +/* Define to 1 if the system has the type `unsigned long long int'. */ +#undef HAVE_UNSIGNED_LONG_LONG_INT + +/* Define to 1 if you have the `utime' function. */ +#undef HAVE_UTIME + +/* Define to 1 if you have the `utimensat' function. */ +#undef HAVE_UTIMENSAT + +/* Define to 1 if you have the `utimes' function. */ +#undef HAVE_UTIMES + +/* Define to 1 if you have the header file. */ +#undef HAVE_UTIME_H + +/* Define to 1 if you have the `vfork' function. */ +#undef HAVE_VFORK + +/* Define to 1 if you have the `vprintf' function. */ +#undef HAVE_VPRINTF + +/* Define to 1 if you have the header file. */ +#undef HAVE_WCHAR_H + +/* Define to 1 if the system has the type `wchar_t'. */ +#undef HAVE_WCHAR_T + +/* Define to 1 if you have the `wcrtomb' function. */ +#undef HAVE_WCRTOMB + +/* Define to 1 if you have the `wcscmp' function. */ +#undef HAVE_WCSCMP + +/* Define to 1 if you have the `wcscpy' function. */ +#undef HAVE_WCSCPY + +/* Define to 1 if you have the `wcslen' function. */ +#undef HAVE_WCSLEN + +/* Define to 1 if you have the `wctomb' function. */ +#undef HAVE_WCTOMB + +/* Define to 1 if you have the header file. */ +#undef HAVE_WCTYPE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_WINCRYPT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_WINDOWS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_WINIOCTL_H + +/* Define to 1 if you have the `wmemcmp' function. */ +#undef HAVE_WMEMCMP + +/* Define to 1 if you have the `wmemcpy' function. */ +#undef HAVE_WMEMCPY + +/* Define to 1 if you have the `wmemmove' function. */ +#undef HAVE_WMEMMOVE + +/* Define to 1 if you have a working EXT2_IOC_GETFLAGS */ +#undef HAVE_WORKING_EXT2_IOC_GETFLAGS + +/* Define to 1 if you have a working FS_IOC_GETFLAGS */ +#undef HAVE_WORKING_FS_IOC_GETFLAGS + +/* Define to 1 if you have the header file. */ +#undef HAVE_ZLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ZSTD_H + +/* Define to 1 if you have the `_ctime64_s' function. */ +#undef HAVE__CTIME64_S + +/* Define to 1 if you have the `_fseeki64' function. */ +#undef HAVE__FSEEKI64 + +/* Define to 1 if you have the `_get_timezone' function. */ +#undef HAVE__GET_TIMEZONE + +/* Define to 1 if you have the `_gmtime64_s' function. */ +#undef HAVE__GMTIME64_S + +/* Define to 1 if you have the `_localtime64_s' function. */ +#undef HAVE__LOCALTIME64_S + +/* Define to 1 if you have the `_mkgmtime64' function. */ +#undef HAVE__MKGMTIME64 + +/* Define as const if the declaration of iconv() needs const. */ +#undef ICONV_CONST + +/* Version number of libarchive as a single integer */ +#undef LIBARCHIVE_VERSION_NUMBER + +/* Version number of libarchive */ +#undef LIBARCHIVE_VERSION_STRING + +/* Define to 1 if `lstat' dereferences a symlink specified with a trailing + slash. */ +#undef LSTAT_FOLLOWS_SLASHED_SYMLINK + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#undef LT_OBJDIR + +/* Define to 1 if `major', `minor', and `makedev' are declared in . + */ +#undef MAJOR_IN_MKDEV + +/* Define to 1 if `major', `minor', and `makedev' are declared in + . */ +#undef MAJOR_IN_SYSMACROS + +/* Define to '0x05020000' for Windows Server 2003 APIs. */ +#undef NTDDI_VERSION + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if PCRE_STATIC needs to be defined. */ +#undef PCRE_STATIC + +/* The size of `wchar_t', as computed by sizeof. */ +#undef SIZEOF_WCHAR_T + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if strerror_r returns char *. */ +#undef STRERROR_R_CHAR_P + +/* Define to 1 if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# undef _POSIX_PTHREAD_SEMANTICS +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# undef _TANDEM_SOURCE +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# undef __EXTENSIONS__ +#endif + + +/* Version number of package */ +#undef VERSION + +/* Define to '0x0502' for Windows Server 2003 APIs. */ +#undef WINVER + +/* Enable large inode numbers on Mac OS X 10.5. */ +#ifndef _DARWIN_USE_64_BIT_INODE +# define _DARWIN_USE_64_BIT_INODE 1 +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +#undef _FILE_OFFSET_BITS + +/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ +#undef _LARGEFILE_SOURCE + +/* Define for large files, on AIX-style hosts. */ +#undef _LARGE_FILES + +/* Define to 1 if on MINIX. */ +#undef _MINIX + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +#undef _POSIX_1_SOURCE + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +#undef _POSIX_SOURCE + +/* Define for Solaris 2.5.1 so the uint32_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT32_T + +/* Define for Solaris 2.5.1 so the uint64_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT64_T + +/* Define for Solaris 2.5.1 so the uint8_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT8_T + +/* Define to '0x0502' for Windows Server 2003 APIs. */ +#undef _WIN32_WINNT + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to match typeof st_gid field of struct stat if doesn't + define. */ +#undef gid_t + +/* Define to `unsigned long' if does not define. */ +#undef id_t + +/* Define to the type of a signed integer type of width exactly 16 bits if + such a type exists and the standard includes do not define it. */ +#undef int16_t + +/* Define to the type of a signed integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +#undef int32_t + +/* Define to the type of a signed integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +#undef int64_t + +/* Define to the widest signed integer type if and do + not define. */ +#undef intmax_t + +/* Define to `int' if does not define. */ +#undef mode_t + +/* Define to `long long' if does not define. */ +#undef off_t + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +/* Define to match typeof st_uid field of struct stat if doesn't + define. */ +#undef uid_t + +/* Define to the type of an unsigned integer type of width exactly 16 bits if + such a type exists and the standard includes do not define it. */ +#undef uint16_t + +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +#undef uint32_t + +/* Define to the type of an unsigned integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +#undef uint64_t + +/* Define to the type of an unsigned integer type of width exactly 8 bits if + such a type exists and the standard includes do not define it. */ +#undef uint8_t + +/* Define to the widest unsigned integer type if and + do not define. */ +#undef uintmax_t + +/* Define to `unsigned int' if does not define. */ +#undef uintptr_t diff --git a/dependencies/libarchive-3.4.2/configure b/dependencies/libarchive-3.4.2/configure new file mode 100755 index 0000000..ec6d059 --- /dev/null +++ b/dependencies/libarchive-3.4.2/configure @@ -0,0 +1,24025 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for libarchive 3.4.2. +# +# Report bugs to . +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1 + + test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org and +$0: libarchive-discuss@googlegroups.com about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + +SHELL=${CONFIG_SHELL-/bin/sh} + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='libarchive' +PACKAGE_TARNAME='libarchive' +PACKAGE_VERSION='3.4.2' +PACKAGE_STRING='libarchive 3.4.2' +PACKAGE_BUGREPORT='libarchive-discuss@googlegroups.com' +PACKAGE_URL='' + +ac_unique_file="libarchive" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +INC_FREEBSD_ACL_FALSE +INC_FREEBSD_ACL_TRUE +INC_DARWIN_ACL_FALSE +INC_DARWIN_ACL_TRUE +INC_SUNOS_ACL_FALSE +INC_SUNOS_ACL_TRUE +INC_LINUX_ACL_FALSE +INC_LINUX_ACL_TRUE +LIBOBJS +LIBXML2_PC_LIBS +LIBXML2_PC_CFLAGS +PKG_CONFIG_LIBDIR +PKG_CONFIG_PATH +PKG_CONFIG +LTLIBICONV +LIBICONV +INC_BLAKE2_FALSE +INC_BLAKE2_TRUE +STATIC_BSDCPIO_FALSE +STATIC_BSDCPIO_TRUE +BUILD_BSDCPIO_FALSE +BUILD_BSDCPIO_TRUE +STATIC_BSDCAT_FALSE +STATIC_BSDCAT_TRUE +BUILD_BSDCAT_FALSE +BUILD_BSDCAT_TRUE +STATIC_BSDTAR_FALSE +STATIC_BSDTAR_TRUE +BUILD_BSDTAR_FALSE +BUILD_BSDTAR_TRUE +LT_SYS_LIBRARY_PATH +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +MANIFEST_TOOL +RANLIB +ac_ct_AR +AR +LN_S +NM +ac_ct_DUMPBIN +DUMPBIN +LD +FGREP +SED +LIBTOOL +OBJDUMP +DLLTOOL +AS +EGREP +GREP +CPP +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +am__nodep +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +PLATFORMCPPFLAGS +INC_CYGWIN_FILES_FALSE +INC_CYGWIN_FILES_TRUE +INC_WINDOWS_FILES_FALSE +INC_WINDOWS_FILES_TRUE +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +LIBARCHIVE_VERSION_NUMBER +LIBARCHIVE_VERSION_STRING +BSDCAT_VERSION_STRING +BSDTAR_VERSION_STRING +BSDCPIO_VERSION_STRING +ARCHIVE_LIBTOOL_VERSION +MAINT +MAINTAINER_MODE_FALSE +MAINTAINER_MODE_TRUE +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +AM_DEFAULT_V +AM_V +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +runstatedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_silent_rules +enable_maintainer_mode +enable_dependency_tracking +enable_shared +enable_static +with_pic +enable_fast_install +with_aix_soname +with_gnu_ld +with_sysroot +enable_libtool_lock +enable_bsdtar +enable_bsdcat +enable_bsdcpio +with_zlib +with_bz2lib +with_libb2 +with_iconv +enable_rpath +with_libiconv_prefix +with_lz4 +with_zstd +with_lzma +with_lzo2 +with_cng +with_mbedtls +with_nettle +with_openssl +with_xml2 +with_expat +enable_posix_regex_lib +enable_xattr +enable_acl +enable_largefile +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP +LT_SYS_LIBRARY_PATH +PKG_CONFIG +PKG_CONFIG_PATH +PKG_CONFIG_LIBDIR +LIBXML2_PC_CFLAGS +LIBXML2_PC_LIBS' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir runstatedir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures libarchive 3.4.2 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/libarchive] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of libarchive 3.4.2:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-silent-rules less verbose build output (undo: "make V=1") + --disable-silent-rules verbose build output (undo: "make V=0") + --disable-maintainer-mode + disable make rules and dependencies not useful (and + sometimes confusing) to the casual installer + --enable-dependency-tracking + do not reject slow dependency extractors + --disable-dependency-tracking + speeds up one-time build + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-static[=PKGS] build static libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + --enable-bsdtar enable build of bsdtar (default) + --enable-bsdtar=static force static build of bsdtar + --enable-bsdtar=shared force dynamic build of bsdtar + --disable-bsdtar disable build of bsdtar + --enable-bsdcat enable build of bsdcat (default) + --enable-bsdcat=static force static build of bsdcat + --enable-bsdcat=shared force dynamic build of bsdcat + --disable-bsdcat disable build of bsdcat + --enable-bsdcpio enable build of bsdcpio (default) + --enable-bsdcpio=static static build of bsdcpio + --enable-bsdcpio=shared dynamic build of bsdcpio + --disable-bsdcpio disable build of bsdcpio + --disable-rpath do not hardcode runtime library paths + --enable-posix-regex-lib + choose what library to use for POSIX regular + expression support (default: auto) + --enable-posix-regex-lib=libc + use libc POSIX regular expression support + --enable-posix-regex-lib=libregex + use libregex POSIX regular expression support + --enable-posix-regex-lib=libpcreposix + use libpcreposix POSIX regular expression support + --disable-posix-regex-lib + don't enable POSIX regular expression support + --disable-xattr Disable Extended Attributes support (default: check) + --disable-acl Disable ACL support (default: check) + --disable-largefile omit support for large files + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use + both] + --with-aix-soname=aix|svr4|both + shared library versioning (aka "SONAME") variant to + provide on AIX, [default=aix]. + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-sysroot[=DIR] Search for dependent libraries within DIR (or the + compiler's sysroot if not specified). + --without-zlib Don't build support for gzip through zlib + --without-bz2lib Don't build support for bzip2 through bz2lib + --without-libb2 Don't build support for BLAKE2 through libb2 + --without-iconv Don't try to link against iconv + --with-gnu-ld assume the C compiler uses GNU ld default=no + --with-libiconv-prefix[=DIR] search for libiconv in DIR/include and DIR/lib + --without-libiconv-prefix don't search for libiconv in includedir and libdir + --without-lz4 Don't build support for lz4 through liblz4 + --without-zstd Don't build support for zstd through libzstd + --without-lzma Don't build support for xz through lzma + --with-lzo2 Build with LZO support from liblzo2 + --without-cng Don't build support of CNG(Crypto Next Generation) + --with-mbedtls Build with crypto support from mbed TLS + --with-nettle Build with crypto support from Nettle + --without-openssl Don't build support for mtree and xar hashes through + openssl + --without-xml2 Don't build support for xar through libxml2 + --without-expat Don't build support for xar through expat + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + LT_SYS_LIBRARY_PATH + User-defined run-time library search path. + PKG_CONFIG path to pkg-config utility + PKG_CONFIG_PATH + directories to add to pkg-config's search path + PKG_CONFIG_LIBDIR + path overriding pkg-config's built-in search path + LIBXML2_PC_CFLAGS + C compiler flags for LIBXML2_PC, overriding pkg-config + LIBXML2_PC_LIBS + linker flags for LIBXML2_PC, overriding pkg-config + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +libarchive configure 3.4.2 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## -------------------------------------------------- ## +## Report this to libarchive-discuss@googlegroups.com ## +## -------------------------------------------------- ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type + +# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES +# ---------------------------------------------------- +# Tries to find if the field MEMBER exists in type AGGR, after including +# INCLUDES, setting cache variable VAR accordingly. +ac_fn_c_check_member () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 +$as_echo_n "checking for $2.$3... " >&6; } +if eval \${$4+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (sizeof ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + eval "$4=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$4 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_member + +# ac_fn_c_find_intX_t LINENO BITS VAR +# ----------------------------------- +# Finds a signed integer type with width BITS, setting cache variable VAR +# accordingly. +ac_fn_c_find_intX_t () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for int$2_t" >&5 +$as_echo_n "checking for int$2_t... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + # Order is important - never check a type that is potentially smaller + # than half of the expected target width. + for ac_type in int$2_t 'int' 'long int' \ + 'long long int' 'short int' 'signed char'; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default + enum { N = $2 / 2 - 1 }; +int +main () +{ +static int test_array [1 - 2 * !(0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default + enum { N = $2 / 2 - 1 }; +int +main () +{ +static int test_array [1 - 2 * !(($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1) + < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 2))]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + case $ac_type in #( + int$2_t) : + eval "$3=yes" ;; #( + *) : + eval "$3=\$ac_type" ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if eval test \"x\$"$3"\" = x"no"; then : + +else + break +fi + done +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_find_intX_t + +# ac_fn_c_find_uintX_t LINENO BITS VAR +# ------------------------------------ +# Finds an unsigned integer type with width BITS, setting cache variable VAR +# accordingly. +ac_fn_c_find_uintX_t () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint$2_t" >&5 +$as_echo_n "checking for uint$2_t... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + # Order is important - never check a type that is potentially smaller + # than half of the expected target width. + for ac_type in uint$2_t 'unsigned int' 'unsigned long int' \ + 'unsigned long long int' 'unsigned short int' 'unsigned char'; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !((($ac_type) -1 >> ($2 / 2 - 1)) >> ($2 / 2 - 1) == 3)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + case $ac_type in #( + uint$2_t) : + eval "$3=yes" ;; #( + *) : + eval "$3=\$ac_type" ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if eval test \"x\$"$3"\" = x"no"; then : + +else + break +fi + done +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_find_uintX_t + +# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES +# --------------------------------------------- +# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR +# accordingly. +ac_fn_c_check_decl () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + as_decl_name=`echo $2|sed 's/ *(.*//'` + as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 +$as_echo_n "checking whether $as_decl_name is declared... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +#ifndef $as_decl_name +#ifdef __cplusplus + (void) $as_decl_use; +#else + (void) $as_decl_name; +#endif +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_decl + +# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES +# -------------------------------------------- +# Tries to find the compile-time value of EXPR in a program that includes +# INCLUDES, setting VAR accordingly. Returns whether the value could be +# computed +ac_fn_c_compute_int () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= 0)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=0 ac_mid=0 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid; break +else + as_fn_arith $ac_mid + 1 && ac_lo=$as_val + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) < 0)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=-1 ac_mid=-1 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=$ac_mid; break +else + as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + ac_lo= ac_hi= +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid +else + as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in #(( +?*) eval "$3=\$ac_lo"; ac_retval=0 ;; +'') ac_retval=1 ;; +esac + else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +static long int longval () { return $2; } +static unsigned long int ulongval () { return $2; } +#include +#include +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + return 1; + if (($2) < 0) + { + long int i = longval (); + if (i != ($2)) + return 1; + fprintf (f, "%ld", i); + } + else + { + unsigned long int i = ulongval (); + if (i != ($2)) + return 1; + fprintf (f, "%lu", i); + } + /* Do not output a trailing newline, as this causes \r\n confusion + on some platforms. */ + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + echo >>conftest.val; read $3 config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by libarchive $as_me 3.4.2, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Make sure the srcdir contains "libarchive" directory + +# Use auxiliary subscripts from this subdirectory (cleans up root) +ac_aux_dir= +for ac_dir in build/autoconf "$srcdir"/build/autoconf; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in build/autoconf \"$srcdir\"/build/autoconf" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# M4 scripts + +# Must follow AC_CONFIG macros above... +am__api_version='1.15' + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi + +rm -f conftest.file + +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=1;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='libarchive' + VERSION='3.4.2' + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +mkdir_p='$(MKDIR_P)' + +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar pax cpio none' + +am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' + + + + + + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 + fi +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 +$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } + # Check whether --enable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then : + enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval +else + USE_MAINTAINER_MODE=yes +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 +$as_echo "$USE_MAINTAINER_MODE" >&6; } + if test $USE_MAINTAINER_MODE = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi + + MAINT=$MAINTAINER_MODE_TRUE + + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=0;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + + +# Libtool's "interface version" can be computed from the libarchive version. + +# Libtool interface version bumps on any API change, so increments +# whenever libarchive minor version does. +ARCHIVE_MINOR=$(( (3004002 / 1000) % 1000 )) +# Libarchive 2.7 == libtool interface 9 = 2 + 7 +# Libarchive 2.8 == libtool interface 10 = 2 + 8 +# Libarchive 2.9 == libtool interface 11 = 2 + 8 +# Libarchive 3.0 == libtool interface 12 +# Libarchive 3.1 == libtool interface 13 +ARCHIVE_INTERFACE=`echo $((13 + ${ARCHIVE_MINOR}))` +# Libarchive revision is bumped on any source change === libtool revision +ARCHIVE_REVISION=$(( 3004002 % 1000 )) +# Libarchive minor is bumped on any interface addition === libtool age +ARCHIVE_LIBTOOL_VERSION=$ARCHIVE_INTERFACE:$ARCHIVE_REVISION:$ARCHIVE_MINOR + +# Stick the version numbers into config.h + +$as_echo "#define LIBARCHIVE_VERSION_STRING \"3.4.2\"" >>confdefs.h + + +cat >>confdefs.h <<_ACEOF +#define LIBARCHIVE_VERSION_NUMBER "3004002" +_ACEOF + + +$as_echo "#define BSDCPIO_VERSION_STRING \"3.4.2\"" >>confdefs.h + + +$as_echo "#define BSDTAR_VERSION_STRING \"3.4.2\"" >>confdefs.h + + +$as_echo "#define BSDCAT_VERSION_STRING \"3.4.2\"" >>confdefs.h + + +# The shell variables here must be the same as the AC_SUBST() variables +# below, but the shell variable names apparently cannot be the same as +# the m4 macro names above. Why? Ask autoconf. +BSDCPIO_VERSION_STRING=3.4.2 +BSDTAR_VERSION_STRING=3.4.2 +BSDCAT_VERSION_STRING=3.4.2 +LIBARCHIVE_VERSION_STRING=3.4.2 +LIBARCHIVE_VERSION_NUMBER=3004002 + +# Substitute the above version numbers into the various files below. +# Yes, I believe this is the fourth time we define what are essentially +# the same symbols. Why? Ask autoconf. + + + + + + + +ac_config_headers="$ac_config_headers config.h" + +ac_config_files="$ac_config_files Makefile" + +ac_config_files="$ac_config_files build/pkgconfig/libarchive.pc" + + +# Check for host type +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + + +inc_windows_files=no +inc_cygwin_files=no +case "$host_os" in + *mingw* ) inc_windows_files=yes ;; + *cygwin* | *msys*) inc_cygwin_files=yes ;; +esac + if test $inc_windows_files = yes; then + INC_WINDOWS_FILES_TRUE= + INC_WINDOWS_FILES_FALSE='#' +else + INC_WINDOWS_FILES_TRUE='#' + INC_WINDOWS_FILES_FALSE= +fi + + if test $inc_cygwin_files = yes; then + INC_CYGWIN_FILES_TRUE= + INC_CYGWIN_FILES_FALSE='#' +else + INC_CYGWIN_FILES_TRUE='#' + INC_CYGWIN_FILES_FALSE= +fi + + +PLATFORMCPPFLAGS= +case "$host_os" in + *mingw* ) PLATFORMCPPFLAGS=-D__USE_MINGW_ANSI_STDIO ;; +esac + + +# Checks for programs. +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 +$as_echo_n "checking for style of include used by $am_make... " >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 +$as_echo "$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default" +if test "x$ac_cv_header_minix_config_h" = xyes; then : + MINIX=yes +else + MINIX= +fi + + + if test "$MINIX" = yes; then + +$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h + + +$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h + + +$as_echo "#define _MINIX 1" >>confdefs.h + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5 +$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; } +if ${ac_cv_safe_to_define___extensions__+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +# define __EXTENSIONS__ 1 + $ac_includes_default +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_safe_to_define___extensions__=yes +else + ac_cv_safe_to_define___extensions__=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5 +$as_echo "$ac_cv_safe_to_define___extensions__" >&6; } + test $ac_cv_safe_to_define___extensions__ = yes && + $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h + + $as_echo "#define _ALL_SOURCE 1" >>confdefs.h + + $as_echo "#define _GNU_SOURCE 1" >>confdefs.h + + $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h + + $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h + + +enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args. +set dummy ${ac_tool_prefix}as; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AS+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AS"; then + ac_cv_prog_AS="$AS" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AS="${ac_tool_prefix}as" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AS=$ac_cv_prog_AS +if test -n "$AS"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5 +$as_echo "$AS" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_AS"; then + ac_ct_AS=$AS + # Extract the first word of "as", so it can be a program name with args. +set dummy as; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AS+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AS"; then + ac_cv_prog_ac_ct_AS="$ac_ct_AS" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AS="as" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AS=$ac_cv_prog_ac_ct_AS +if test -n "$ac_ct_AS"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AS" >&5 +$as_echo "$ac_ct_AS" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_AS" = x; then + AS="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AS=$ac_ct_AS + fi +else + AS="$ac_cv_prog_AS" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + + ;; +esac + +test -z "$AS" && AS=as + + + + + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.4.6' +macro_revision='2.4.6' + + + + + + + + + + + + + +ltmain=$ac_aux_dir/ltmain.sh + +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case $ECHO in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if ${ac_cv_path_FGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_FGREP" || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if ${lt_cv_path_NM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in dumpbin "link -dump" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if ${lt_cv_nm_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if ${lt_cv_sys_max_cmd_len+:} false; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n "$lt_cv_sys_max_cmd_len"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +$as_echo_n "checking how to convert $build file names to $host format... " >&6; } +if ${lt_cv_to_host_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac + +fi + +to_host_file_cmd=$lt_cv_to_host_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +$as_echo "$lt_cv_to_host_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } +if ${lt_cv_to_tool_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + #assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac + +fi + +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +$as_echo "$lt_cv_to_tool_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if ${lt_cv_ld_reload_flag+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test yes != "$GCC"; then + reload_cmds=false + fi + ;; + darwin*) + if test yes = "$GCC"; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if ${lt_cv_deplibs_check_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + + + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +$as_echo_n "checking how to associate runtime and link libraries... " >&6; } +if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + + + + + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} +: ${AR_FLAGS=cru} + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 +$as_echo_n "checking for archiver @FILE support... " >&6; } +if ${lt_cv_ar_at_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ar_at_file=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 +$as_echo "$lt_cv_ar_at_file" >&6; } + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if ${lt_cv_sys_global_symbol_pipe+:} false; then : + $as_echo_n "(cached) " >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[ABCDEGRST]' + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 +$as_echo_n "checking for sysroot... " >&6; } + +# Check whether --with-sysroot was given. +if test "${with_sysroot+set}" = set; then : + withval=$with_sysroot; +else + with_sysroot=no +fi + + +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 +$as_echo "$with_sysroot" >&6; } + as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 + ;; +esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 +$as_echo "${lt_sysroot:-no}" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 +$as_echo_n "checking for a working dd... " >&6; } +if ${ac_cv_path_lt_DD+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +if test -z "$lt_DD"; then + ac_path_lt_DD_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in dd; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_lt_DD" || continue +if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi + $ac_path_lt_DD_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_lt_DD"; then + : + fi +else + ac_cv_path_lt_DD=$lt_DD +fi + +rm -f conftest.i conftest2.i conftest.out +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 +$as_echo "$ac_cv_path_lt_DD" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 +$as_echo_n "checking how to truncate binary pipes... " >&6; } +if ${lt_cv_truncate_bin+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 +$as_echo "$lt_cv_truncate_bin" >&6; } + + + + + + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then : + enableval=$enable_libtool_lock; +fi + +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if ${lt_cv_cc_needs_belf+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$lt_cv_cc_needs_belf" >&6; } + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. +set dummy ${ac_tool_prefix}mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MANIFEST_TOOL"; then + ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL +if test -n "$MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 +$as_echo "$MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_MANIFEST_TOOL"; then + ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL + # Extract the first word of "mt", so it can be a program name with args. +set dummy mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_MANIFEST_TOOL"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL +if test -n "$ac_ct_MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 +$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_MANIFEST_TOOL" = x; then + MANIFEST_TOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL + fi +else + MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" +fi + +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 +$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } +if ${lt_cv_path_mainfest_tool+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&5 + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 +$as_echo "$lt_cv_path_mainfest_tool" >&6; } +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi + + + + + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_LIPO="lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL="otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if ${lt_cv_apple_cc_single_mod+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&5 + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if ${lt_cv_ld_exported_symbols_list+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if ${lt_cv_ld_force_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 + echo "$RANLIB libconftest.a" >&5 + $RANLIB libconftest.a 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&5 + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[012][,.]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + + + +# Set options + + + + enable_dlopen=no + + + + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + # Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_static=yes +fi + + + + + + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + pic_mode=default +fi + + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_fast_install=yes +fi + + + + + + + + + shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[5-9]*,yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 +$as_echo_n "checking which variant of shared library versioning to provide... " >&6; } + +# Check whether --with-aix-soname was given. +if test "${with_aix_soname+set}" = set; then : + withval=$with_aix_soname; case $withval in + aix|svr4|both) + ;; + *) + as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname +else + if ${lt_cv_with_aix_soname+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_with_aix_soname=aix +fi + + with_aix_soname=$lt_cv_with_aix_soname +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 +$as_echo "$with_aix_soname" >&6; } + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if ${lt_cv_objdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +func_cc_basename $compiler +cc_basename=$func_cc_basename_result + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/${ac_tool_prefix}file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac +fi + +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac +fi + +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +lt_save_CC=$CC +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + + + + + + + lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + + + if test yes = "$GCC"; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + lt_prog_compiler_pic='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + if test -n "$lt_prog_compiler_pic"; then + lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + *Sun\ F* | *Sun*Fortran*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + *Intel*\ [CF]*Compiler*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + *Portland\ Group*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic=$lt_prog_compiler_pic +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 +$as_echo "$lt_cv_prog_compiler_pic" >&6; } +lt_prog_compiler_pic=$lt_cv_prog_compiler_pic + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if ${lt_cv_prog_compiler_pic_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test yes = "$lt_cv_prog_compiler_pic_works"; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi + + + + + + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test yes = "$lt_cv_prog_compiler_static_works"; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + +hard_links=nottested +if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test no = "$hard_links"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + linux* | k*bsd*-gnu | gnu*) + link_all_deplibs=no + ;; + esac + + ld_shlibs=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + export_dynamic_flag_spec='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='$wl--export-all-symbols' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + export_dynamic_flag_spec='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + ld_shlibs=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test no = "$ld_shlibs"; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix[4-9]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + hardcode_direct=no + hardcode_direct_absolute=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + export_dynamic_flag_spec='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' $wl-bernotok' + allow_undefined_flag=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi + archive_cmds_need_lc=yes + archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + always_export_symbols=yes + file_list_spec='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, )='true' + enable_shared_with_static_runtimes=yes + exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + old_postinstall_cmds='chmod 644 $oldlib' + postlink_cmds='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + enable_shared_with_static_runtimes=yes + ;; + esac + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + if test yes = "$lt_cv_ld_force_load"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + + else + whole_archive_flag_spec='' + fi + link_all_deplibs=yes + allow_undefined_flag=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + + else + ld_shlibs=no + fi + + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test yes = "$GCC"; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if ${lt_cv_prog_compiler__b+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -b" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test yes = "$lt_cv_prog_compiler__b"; then + archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +fi + + ;; + esac + fi + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 +$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } +if ${lt_cv_irix_exported_symbol+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo (void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_irix_exported_symbol=yes +else + lt_cv_irix_exported_symbol=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 +$as_echo "$lt_cv_irix_exported_symbol" >&6; } + if test yes = "$lt_cv_irix_exported_symbol"; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + link_all_deplibs=no + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + link_all_deplibs=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + ld_shlibs=yes + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' + else + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + fi + else + ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + + osf3*) + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='$wl-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='$wl-z,text' + allow_undefined_flag='$wl-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='$wl-R,$libdir' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='$wl-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test no = "$ld_shlibs" && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([A-Za-z]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + + + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[4-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a(lib.so.V)' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[23].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + hardcode_libdir_flag_spec='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test yes = "$hardcode_automatic"; then + + # We can hardcode non-existent directories. + if test no != "$hardcode_direct" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && + test no != "$hardcode_minus_L"; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test relink = "$hardcode_action" || + test yes = "$inherit_rpath"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else + + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : + lt_cv_dlopen=shl_load +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + lt_cv_dlopen=dlopen +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if ${ac_cv_lib_svld_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if ${ac_cv_lib_dld_dld_link+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : + lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test yes = "$cross_compiling"; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$lt_cv_dlopen_self" >&6; } + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self_static+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test yes = "$cross_compiling"; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +fi + + + + + + + + + + + + + # Report what library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[4-9]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC=$lt_save_CC + + + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + + + +# +# Options for building bsdtar. +# +# Default is to build bsdtar, but allow people to override that. +# +# Check whether --enable-bsdtar was given. +if test "${enable_bsdtar+set}" = set; then : + enableval=$enable_bsdtar; +else + enable_bsdtar=yes +fi + + +case "$enable_bsdtar" in +yes) + if test "$enable_static" = "no"; then + static_bsdtar=no + else + static_bsdtar=yes + fi + build_bsdtar=yes + ;; +dynamic|shared) + if test "$enable_shared" = "no"; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "Shared linking of bsdtar requires shared libarchive +See \`config.log' for more details" "$LINENO" 5; } + fi + build_bsdtar=yes + static_bsdtar=no + ;; +static) + build_bsdtar=yes + static_bsdtar=yes + ;; +no) + build_bsdtar=no + static_bsdtar=no + ;; +*) + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "Unsupported value for --enable-bsdtar +See \`config.log' for more details" "$LINENO" 5; } + ;; +esac + + if test "$build_bsdtar" = yes ; then + BUILD_BSDTAR_TRUE= + BUILD_BSDTAR_FALSE='#' +else + BUILD_BSDTAR_TRUE='#' + BUILD_BSDTAR_FALSE= +fi + + if test "$static_bsdtar" = yes ; then + STATIC_BSDTAR_TRUE= + STATIC_BSDTAR_FALSE='#' +else + STATIC_BSDTAR_TRUE='#' + STATIC_BSDTAR_FALSE= +fi + + +# +# Options for building bsdcat. +# +# Default is to build bsdcat, but allow people to override that. +# +# Check whether --enable-bsdcat was given. +if test "${enable_bsdcat+set}" = set; then : + enableval=$enable_bsdcat; +else + enable_bsdcat=yes +fi + + +case "$enable_bsdcat" in +yes) + if test "$enable_static" = "no"; then + static_bsdcat=no + else + static_bsdcat=yes + fi + build_bsdcat=yes + ;; +dynamic|shared) + if test "$enable_shared" = "no"; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "Shared linking of bsdcat requires shared libarchive +See \`config.log' for more details" "$LINENO" 5; } + fi + build_bsdcat=yes + static_bsdcat=no + ;; +static) + build_bsdcat=yes + static_bsdcat=yes + ;; +no) + build_bsdcat=no + static_bsdcat=no + ;; +*) + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "Unsupported value for --enable-bsdcat +See \`config.log' for more details" "$LINENO" 5; } + ;; +esac + + if test "$build_bsdcat" = yes ; then + BUILD_BSDCAT_TRUE= + BUILD_BSDCAT_FALSE='#' +else + BUILD_BSDCAT_TRUE='#' + BUILD_BSDCAT_FALSE= +fi + + if test "$static_bsdcat" = yes ; then + STATIC_BSDCAT_TRUE= + STATIC_BSDCAT_FALSE='#' +else + STATIC_BSDCAT_TRUE='#' + STATIC_BSDCAT_FALSE= +fi + + +# +# Options for building bsdcpio. +# +# Default is not to build bsdcpio, but that can be overridden. +# +# Check whether --enable-bsdcpio was given. +if test "${enable_bsdcpio+set}" = set; then : + enableval=$enable_bsdcpio; +else + enable_bsdcpio=yes +fi + + +case "$enable_bsdcpio" in +yes) + if test "$enable_static" = "no"; then + static_bsdcpio=no + else + static_bsdcpio=yes + fi + build_bsdcpio=yes + ;; +dynamic|shared) + if test "$enabled_shared" = "no"; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "Shared linking of bsdcpio requires shared libarchive +See \`config.log' for more details" "$LINENO" 5; } + fi + build_bsdcpio=yes + ;; +static) + build_bsdcpio=yes + static_bsdcpio=yes + ;; +no) + build_bsdcpio=no + static_bsdcpio=no + ;; +*) + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "Unsupported value for --enable-bsdcpio +See \`config.log' for more details" "$LINENO" 5; } + ;; +esac + + if test "$build_bsdcpio" = yes ; then + BUILD_BSDCPIO_TRUE= + BUILD_BSDCPIO_FALSE='#' +else + BUILD_BSDCPIO_TRUE='#' + BUILD_BSDCPIO_FALSE= +fi + + if test "$static_bsdcpio" = yes ; then + STATIC_BSDCPIO_TRUE= + STATIC_BSDCPIO_FALSE='#' +else + STATIC_BSDCPIO_TRUE='#' + STATIC_BSDCPIO_FALSE= +fi + + +# Set up defines needed before including any headers +case $host in + *mingw* | *cygwin* | *msys* ) + +$as_echo "#define _WIN32_WINNT 0x0502" >>confdefs.h + + +$as_echo "#define WINVER 0x0502" >>confdefs.h + + +$as_echo "#define NTDDI_VERSION 0x05020000" >>confdefs.h + + ;; +esac + +# Checks for header files. +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do + as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5 +$as_echo_n "checking for $ac_hdr that defines DIR... " >&6; } +if eval \${$as_ac_Header+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include <$ac_hdr> + +int +main () +{ +if ((DIR *) 0) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$as_ac_Header=yes" +else + eval "$as_ac_Header=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$as_ac_Header + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 +_ACEOF + +ac_header_dirent=$ac_hdr; break +fi + +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 +$as_echo_n "checking for library containing opendir... " >&6; } +if ${ac_cv_search_opendir+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dir; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_opendir=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_opendir+:} false; then : + break +fi +done +if ${ac_cv_search_opendir+:} false; then : + +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 +$as_echo "$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 +$as_echo_n "checking for library containing opendir... " >&6; } +if ${ac_cv_search_opendir+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' x; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_opendir=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_opendir+:} false; then : + break +fi +done +if ${ac_cv_search_opendir+:} false; then : + +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 +$as_echo "$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sys/wait.h that is POSIX.1 compatible" >&5 +$as_echo_n "checking for sys/wait.h that is POSIX.1 compatible... " >&6; } +if ${ac_cv_header_sys_wait_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#ifndef WEXITSTATUS +# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8) +#endif +#ifndef WIFEXITED +# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif + +int +main () +{ + int s; + wait (&s); + s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_sys_wait_h=yes +else + ac_cv_header_sys_wait_h=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_wait_h" >&5 +$as_echo "$ac_cv_header_sys_wait_h" >&6; } +if test $ac_cv_header_sys_wait_h = yes; then + +$as_echo "#define HAVE_SYS_WAIT_H 1" >>confdefs.h + +fi + +for ac_header in acl/libacl.h attr/xattr.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in copyfile.h ctype.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in errno.h ext2fs/ext2_fs.h fcntl.h grp.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether EXT2_IOC_GETFLAGS is usable" >&5 +$as_echo_n "checking whether EXT2_IOC_GETFLAGS is usable... " >&6; } +if ${ac_cv_have_decl_EXT2_IOC_GETFLAGS+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +int +main () +{ +int x = EXT2_IOC_GETFLAGS + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_have_decl_EXT2_IOC_GETFLAGS=yes +else + ac_cv_have_decl_EXT2_IOC_GETFLAGS=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_decl_EXT2_IOC_GETFLAGS" >&5 +$as_echo "$ac_cv_have_decl_EXT2_IOC_GETFLAGS" >&6; } + +if test "x$ac_cv_have_decl_EXT2_IOC_GETFLAGS" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_WORKING_EXT2_IOC_GETFLAGS 1 +_ACEOF + +fi + +for ac_header in inttypes.h io.h langinfo.h limits.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in linux/fiemap.h linux/fs.h linux/magic.h linux/types.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether FS_IOC_GETFLAGS is usable" >&5 +$as_echo_n "checking whether FS_IOC_GETFLAGS is usable... " >&6; } +if ${ac_cv_have_decl_FS_IOC_GETFLAGS+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +int +main () +{ +int x = FS_IOC_GETFLAGS + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_have_decl_FS_IOC_GETFLAGS=yes +else + ac_cv_have_decl_FS_IOC_GETFLAGS=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_decl_FS_IOC_GETFLAGS" >&5 +$as_echo "$ac_cv_have_decl_FS_IOC_GETFLAGS" >&6; } + +if test "x$ac_cv_have_decl_FS_IOC_GETFLAGS" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_WORKING_FS_IOC_GETFLAGS 1 +_ACEOF + +fi + +for ac_header in locale.h membership.h paths.h poll.h pthread.h pwd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in readpassphrase.h signal.h spawn.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in stdarg.h stdint.h stdlib.h string.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in sys/acl.h sys/cdefs.h sys/ea.h sys/extattr.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in sys/ioctl.h sys/mkdev.h sys/mount.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in sys/param.h sys/poll.h sys/richacl.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in sys/select.h sys/statfs.h sys/statvfs.h sys/sysmacros.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in sys/time.h sys/utime.h sys/utsname.h sys/vfs.h sys/xattr.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in time.h unistd.h utime.h wchar.h wctype.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in windows.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "windows.h" "ac_cv_header_windows_h" "$ac_includes_default" +if test "x$ac_cv_header_windows_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_WINDOWS_H 1 +_ACEOF + +fi + +done + +# check windows.h first; the other headers require it. +for ac_header in wincrypt.h winioctl.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#ifdef HAVE_WINDOWS_H +# include +#endif + +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +# Checks for libraries. + +# Check whether --with-zlib was given. +if test "${with_zlib+set}" = set; then : + withval=$with_zlib; +fi + + +if test "x$with_zlib" != "xno"; then + for ac_header in zlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" +if test "x$ac_cv_header_zlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ZLIB_H 1 +_ACEOF + +fi + +done + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inflate in -lz" >&5 +$as_echo_n "checking for inflate in -lz... " >&6; } +if ${ac_cv_lib_z_inflate+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lz $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char inflate (); +int +main () +{ +return inflate (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_z_inflate=yes +else + ac_cv_lib_z_inflate=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_inflate" >&5 +$as_echo "$ac_cv_lib_z_inflate" >&6; } +if test "x$ac_cv_lib_z_inflate" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBZ 1 +_ACEOF + + LIBS="-lz $LIBS" + +fi + +fi + + +# Check whether --with-bz2lib was given. +if test "${with_bz2lib+set}" = set; then : + withval=$with_bz2lib; +fi + + +if test "x$with_bz2lib" != "xno"; then + for ac_header in bzlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "bzlib.h" "ac_cv_header_bzlib_h" "$ac_includes_default" +if test "x$ac_cv_header_bzlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_BZLIB_H 1 +_ACEOF + +fi + +done + + case "$host_os" in + *mingw* | *cygwin* | *msys*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BZ2_bzDecompressInit in -lbz2" >&5 +$as_echo_n "checking for BZ2_bzDecompressInit in -lbz2... " >&6; } + old_LIBS="$LIBS" + LIBS="-lbz2 $LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + int main() { return BZ2_bzDecompressInit(NULL, 0, 0); } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_bz2_BZ2_bzDecompressInit=yes +else + ac_cv_lib_bz2_BZ2_bzDecompressInit=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$old_LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bz2_BZ2_bzDecompressInit" >&5 +$as_echo "$ac_cv_lib_bz2_BZ2_bzDecompressInit" >&6; } + if test "x$ac_cv_lib_bz2_BZ2_bzDecompressInit" = xyes; then + +$as_echo "#define HAVE_LIBBZ2 1" >>confdefs.h + + LIBS="-lbz2 $LIBS" + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BZ2_bzDecompressInit in -lbz2" >&5 +$as_echo_n "checking for BZ2_bzDecompressInit in -lbz2... " >&6; } +if ${ac_cv_lib_bz2_BZ2_bzDecompressInit+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbz2 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char BZ2_bzDecompressInit (); +int +main () +{ +return BZ2_bzDecompressInit (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_bz2_BZ2_bzDecompressInit=yes +else + ac_cv_lib_bz2_BZ2_bzDecompressInit=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bz2_BZ2_bzDecompressInit" >&5 +$as_echo "$ac_cv_lib_bz2_BZ2_bzDecompressInit" >&6; } +if test "x$ac_cv_lib_bz2_BZ2_bzDecompressInit" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBBZ2 1 +_ACEOF + + LIBS="-lbz2 $LIBS" + +fi + + ;; + esac +fi + + +# Check whether --with-libb2 was given. +if test "${with_libb2+set}" = set; then : + withval=$with_libb2; +fi + + +if test "x$with_libb2" != "xno"; then + for ac_header in blake2.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "blake2.h" "ac_cv_header_blake2_h" "$ac_includes_default" +if test "x$ac_cv_header_blake2_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_BLAKE2_H 1 +_ACEOF + +fi + +done + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for blake2sp_init in -lb2" >&5 +$as_echo_n "checking for blake2sp_init in -lb2... " >&6; } +if ${ac_cv_lib_b2_blake2sp_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lb2 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char blake2sp_init (); +int +main () +{ +return blake2sp_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_b2_blake2sp_init=yes +else + ac_cv_lib_b2_blake2sp_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_b2_blake2sp_init" >&5 +$as_echo "$ac_cv_lib_b2_blake2sp_init" >&6; } +if test "x$ac_cv_lib_b2_blake2sp_init" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBB2 1 +_ACEOF + + LIBS="-lb2 $LIBS" + +fi + +fi + + if test "x$ac_cv_lib_b2_blake2sp_init" != "xyes"; then + INC_BLAKE2_TRUE= + INC_BLAKE2_FALSE='#' +else + INC_BLAKE2_TRUE='#' + INC_BLAKE2_FALSE= +fi + + + +# Check whether --with-iconv was given. +if test "${with_iconv+set}" = set; then : + withval=$with_iconv; +fi + + +if test "x$with_iconv" != "xno"; then + + if test "X$prefix" = "XNONE"; then + acl_final_prefix="$ac_default_prefix" + else + acl_final_prefix="$prefix" + fi + if test "X$exec_prefix" = "XNONE"; then + acl_final_exec_prefix='${prefix}' + else + acl_final_exec_prefix="$exec_prefix" + fi + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" + prefix="$acl_save_prefix" + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which + # contains only /bin. Note that ksh looks also at the FPATH variable, + # so we have to set that as well for the test. + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } +fi +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by GCC" >&5 +$as_echo_n "checking for ld used by GCC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | [A-Za-z]:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${acl_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + acl_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in + *GNU* | *'with BFD'*) + test "$with_gnu_ld" != no && break ;; + *) + test "$with_gnu_ld" != yes && break ;; + esac + fi + done + IFS="$ac_save_ifs" +else + acl_cv_path_LD="$LD" # Let the user override the test with a path. +fi +fi + +LD="$acl_cv_path_LD" +if test -n "$LD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${acl_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU ld's only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$acl_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$acl_cv_prog_gnu_ld + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shared library run path origin" >&5 +$as_echo_n "checking for shared library run path origin... " >&6; } +if ${acl_cv_rpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + + CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ + ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh + . ./conftest.sh + rm -f ./conftest.sh + acl_cv_rpath=done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $acl_cv_rpath" >&5 +$as_echo "$acl_cv_rpath" >&6; } + wl="$acl_cv_wl" + acl_libext="$acl_cv_libext" + acl_shlibext="$acl_cv_shlibext" + acl_libname_spec="$acl_cv_libname_spec" + acl_library_names_spec="$acl_cv_library_names_spec" + acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" + acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" + acl_hardcode_direct="$acl_cv_hardcode_direct" + acl_hardcode_minus_L="$acl_cv_hardcode_minus_L" + # Check whether --enable-rpath was given. +if test "${enable_rpath+set}" = set; then : + enableval=$enable_rpath; : +else + enable_rpath=yes +fi + + + + + acl_libdirstem=lib + acl_libdirstem2= + case "$host_os" in + solaris*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit host" >&5 +$as_echo_n "checking for 64-bit host... " >&6; } +if ${gl_cv_solaris_64bit+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#ifdef _LP64 +sixtyfour bits +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "sixtyfour bits" >/dev/null 2>&1; then : + gl_cv_solaris_64bit=yes +else + gl_cv_solaris_64bit=no +fi +rm -f conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_solaris_64bit" >&5 +$as_echo "$gl_cv_solaris_64bit" >&6; } + if test $gl_cv_solaris_64bit = yes; then + acl_libdirstem=lib/64 + case "$host_cpu" in + sparc*) acl_libdirstem2=lib/sparcv9 ;; + i*86 | x86_64) acl_libdirstem2=lib/amd64 ;; + esac + fi + ;; + *) + searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` + if test -n "$searchpath"; then + acl_save_IFS="${IFS= }"; IFS=":" + for searchdir in $searchpath; do + if test -d "$searchdir"; then + case "$searchdir" in + */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; + */../ | */.. ) + # Better ignore directories of this form. They are misleading. + ;; + *) searchdir=`cd "$searchdir" && pwd` + case "$searchdir" in + */lib64 ) acl_libdirstem=lib64 ;; + esac ;; + esac + fi + done + IFS="$acl_save_IFS" + fi + ;; + esac + test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem" + + + + + + + + + + + + + use_additional=yes + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + +# Check whether --with-libiconv-prefix was given. +if test "${with_libiconv_prefix+set}" = set; then : + withval=$with_libiconv_prefix; + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + if test "$acl_libdirstem2" != "$acl_libdirstem" \ + && ! test -d "$withval/$acl_libdirstem"; then + additional_libdir="$withval/$acl_libdirstem2" + fi + fi + fi + +fi + + LIBICONV= + LTLIBICONV= + INCICONV= + LIBICONV_PREFIX= + HAVE_LIBICONV= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='iconv ' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./+-|ABCDEFGHIJKLMNOPQRSTUVWXYZ____|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIBICONV="${LIBICONV}${LIBICONV:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$value" + else + : + fi + else + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + if test "$enable_rpath" = no \ + || test "X$found_dir" = "X/usr/$acl_libdirstem" \ + || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + else + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + if test "$acl_hardcode_direct" = yes; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + haveit= + for x in $LDFLAGS $LIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + else + LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_a" + else + LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir -l$name" + fi + fi + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + if test "$name" = 'iconv'; then + LIBICONV_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + */$acl_libdirstem2 | */$acl_libdirstem2/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'` + if test "$name" = 'iconv'; then + LIBICONV_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INCICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + INCICONV="${INCICONV}${INCICONV:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + if test -n "$found_la"; then + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \ + && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \ + || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + LIBICONV="${LIBICONV}${LIBICONV:+ }$dep" + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$dep" + ;; + esac + done + fi + else + LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" + else + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + for found_dir in $ltrpathdirs; do + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-R$found_dir" + done + fi + + + + + + + + + + + + + am_save_CPPFLAGS="$CPPFLAGS" + + for element in $INCICONV; do + haveit= + for x in $CPPFLAGS; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" + fi + done + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv" >&5 +$as_echo_n "checking for iconv... " >&6; } +if ${am_cv_func_iconv+:} false; then : + $as_echo_n "(cached) " >&6 +else + + am_cv_func_iconv="no, consider installing GNU libiconv" + am_cv_lib_iconv=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include + +int +main () +{ +iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + am_cv_func_iconv=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test "$am_cv_func_iconv" != yes; then + am_save_LIBS="$LIBS" + LIBS="$LIBS $LIBICONV" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include + +int +main () +{ +iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + am_cv_lib_iconv=yes + am_cv_func_iconv=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$am_save_LIBS" + fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv" >&5 +$as_echo "$am_cv_func_iconv" >&6; } + if test "$am_cv_func_iconv" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working iconv" >&5 +$as_echo_n "checking for working iconv... " >&6; } +if ${am_cv_func_iconv_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + + am_save_LIBS="$LIBS" + if test $am_cv_lib_iconv = yes; then + LIBS="$LIBS $LIBICONV" + fi + am_cv_func_iconv_works=no + for ac_iconv_const in '' 'const'; do + if test "$cross_compiling" = yes; then : + case "$host_os" in + aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; + *) am_cv_func_iconv_works="guessing yes" ;; + esac +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include + +#ifndef ICONV_CONST +# define ICONV_CONST $ac_iconv_const +#endif + +int +main () +{ +int result = 0; + /* Test against AIX 5.1 bug: Failures are not distinguishable from successful + returns. */ + { + iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); + if (cd_utf8_to_88591 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\342\202\254"; /* EURO SIGN */ + char buf[10]; + ICONV_CONST char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_utf8_to_88591, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 1; + iconv_close (cd_utf8_to_88591); + } + } + /* Test against Solaris 10 bug: Failures are not distinguishable from + successful returns. */ + { + iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646"); + if (cd_ascii_to_88591 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\263"; + char buf[10]; + ICONV_CONST char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_ascii_to_88591, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 2; + iconv_close (cd_ascii_to_88591); + } + } + /* Test against AIX 6.1..7.1 bug: Buffer overrun. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\304"; + static char buf[2] = { (char)0xDE, (char)0xAD }; + ICONV_CONST char *inptr = input; + size_t inbytesleft = 1; + char *outptr = buf; + size_t outbytesleft = 1; + size_t res = iconv (cd_88591_to_utf8, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD) + result |= 4; + iconv_close (cd_88591_to_utf8); + } + } +#if 0 /* This bug could be worked around by the caller. */ + /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; + char buf[50]; + ICONV_CONST char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_88591_to_utf8, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if ((int)res > 0) + result |= 8; + iconv_close (cd_88591_to_utf8); + } + } +#endif + /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is + provided. */ + if (/* Try standardized names. */ + iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1) + /* Try IRIX, OSF/1 names. */ + && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1) + /* Try AIX names. */ + && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1) + /* Try HP-UX names. */ + && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) + result |= 16; + return result; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + am_cv_func_iconv_works=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + test "$am_cv_func_iconv_works" = no || break + done + LIBS="$am_save_LIBS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv_works" >&5 +$as_echo "$am_cv_func_iconv_works" >&6; } + case "$am_cv_func_iconv_works" in + *no) am_func_iconv=no am_cv_lib_iconv=no ;; + *) am_func_iconv=yes ;; + esac + else + am_func_iconv=no am_cv_lib_iconv=no + fi + if test "$am_func_iconv" = yes; then + +$as_echo "#define HAVE_ICONV 1" >>confdefs.h + + fi + if test "$am_cv_lib_iconv" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libiconv" >&5 +$as_echo_n "checking how to link with libiconv... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBICONV" >&5 +$as_echo "$LIBICONV" >&6; } + else + CPPFLAGS="$am_save_CPPFLAGS" + LIBICONV= + LTLIBICONV= + fi + + + + if test "$am_cv_func_iconv" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv declaration" >&5 +$as_echo_n "checking for iconv declaration... " >&6; } + if ${am_cv_proto_iconv+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +extern +#ifdef __cplusplus +"C" +#endif +#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) +size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); +#else +size_t iconv(); +#endif + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + am_cv_proto_iconv_arg1="" +else + am_cv_proto_iconv_arg1="const" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);" +fi + + am_cv_proto_iconv=`echo "$am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: + $am_cv_proto_iconv" >&5 +$as_echo " + $am_cv_proto_iconv" >&6; } + +cat >>confdefs.h <<_ACEOF +#define ICONV_CONST $am_cv_proto_iconv_arg1 +_ACEOF + + + fi + + for ac_header in iconv.h +do : + ac_fn_c_check_header_compile "$LINENO" "iconv.h" "ac_cv_header_iconv_h" "#include +" +if test "x$ac_cv_header_iconv_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ICONV_H 1 +_ACEOF + +fi + +done + + if test "x$am_cv_func_iconv" = "xyes"; then + for ac_header in localcharset.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "localcharset.h" "ac_cv_header_localcharset_h" "$ac_includes_default" +if test "x$ac_cv_header_localcharset_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LOCALCHARSET_H 1 +_ACEOF + +fi + +done + + am_save_LIBS="$LIBS" + LIBS="${LIBS} ${LIBICONV}" + for ac_func in locale_charset +do : + ac_fn_c_check_func "$LINENO" "locale_charset" "ac_cv_func_locale_charset" +if test "x$ac_cv_func_locale_charset" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LOCALE_CHARSET 1 +_ACEOF + +fi +done + + LIBS="${am_save_LIBS}" + if test "x$ac_cv_func_locale_charset" != "xyes"; then + # If locale_charset() is not in libiconv, we have to find libcharset. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for locale_charset in -lcharset" >&5 +$as_echo_n "checking for locale_charset in -lcharset... " >&6; } +if ${ac_cv_lib_charset_locale_charset+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcharset $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char locale_charset (); +int +main () +{ +return locale_charset (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_charset_locale_charset=yes +else + ac_cv_lib_charset_locale_charset=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_charset_locale_charset" >&5 +$as_echo "$ac_cv_lib_charset_locale_charset" >&6; } +if test "x$ac_cv_lib_charset_locale_charset" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBCHARSET 1 +_ACEOF + + LIBS="-lcharset $LIBS" + +fi + + fi + fi +fi + + +# Check whether --with-lz4 was given. +if test "${with_lz4+set}" = set; then : + withval=$with_lz4; +fi + + +if test "x$with_lz4" != "xno"; then + for ac_header in lz4.h lz4hc.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LZ4_decompress_safe in -llz4" >&5 +$as_echo_n "checking for LZ4_decompress_safe in -llz4... " >&6; } +if ${ac_cv_lib_lz4_LZ4_decompress_safe+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-llz4 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char LZ4_decompress_safe (); +int +main () +{ +return LZ4_decompress_safe (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_lz4_LZ4_decompress_safe=yes +else + ac_cv_lib_lz4_LZ4_decompress_safe=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lz4_LZ4_decompress_safe" >&5 +$as_echo "$ac_cv_lib_lz4_LZ4_decompress_safe" >&6; } +if test "x$ac_cv_lib_lz4_LZ4_decompress_safe" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBLZ4 1 +_ACEOF + + LIBS="-llz4 $LIBS" + +fi + +fi + + +# Check whether --with-zstd was given. +if test "${with_zstd+set}" = set; then : + withval=$with_zstd; +fi + + +if test "x$with_zstd" != "xno"; then + for ac_header in zstd.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "zstd.h" "ac_cv_header_zstd_h" "$ac_includes_default" +if test "x$ac_cv_header_zstd_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ZSTD_H 1 +_ACEOF + +fi + +done + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ZSTD_compressStream in -lzstd" >&5 +$as_echo_n "checking for ZSTD_compressStream in -lzstd... " >&6; } +if ${ac_cv_lib_zstd_ZSTD_compressStream+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lzstd $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ZSTD_compressStream (); +int +main () +{ +return ZSTD_compressStream (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_zstd_ZSTD_compressStream=yes +else + ac_cv_lib_zstd_ZSTD_compressStream=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_zstd_ZSTD_compressStream" >&5 +$as_echo "$ac_cv_lib_zstd_ZSTD_compressStream" >&6; } +if test "x$ac_cv_lib_zstd_ZSTD_compressStream" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBZSTD 1 +_ACEOF + + LIBS="-lzstd $LIBS" + +fi + +fi + + +# Check whether --with-lzma was given. +if test "${with_lzma+set}" = set; then : + withval=$with_lzma; +fi + + +if test "x$with_lzma" != "xno"; then + for ac_header in lzma.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "lzma.h" "ac_cv_header_lzma_h" "$ac_includes_default" +if test "x$ac_cv_header_lzma_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LZMA_H 1 +_ACEOF + +fi + +done + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lzma_stream_decoder in -llzma" >&5 +$as_echo_n "checking for lzma_stream_decoder in -llzma... " >&6; } +if ${ac_cv_lib_lzma_lzma_stream_decoder+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-llzma $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char lzma_stream_decoder (); +int +main () +{ +return lzma_stream_decoder (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_lzma_lzma_stream_decoder=yes +else + ac_cv_lib_lzma_lzma_stream_decoder=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lzma_lzma_stream_decoder" >&5 +$as_echo "$ac_cv_lib_lzma_lzma_stream_decoder" >&6; } +if test "x$ac_cv_lib_lzma_lzma_stream_decoder" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBLZMA 1 +_ACEOF + + LIBS="-llzma $LIBS" + +fi + + # Some pre-release (but widely distributed) versions of liblzma + # included a disabled version of lzma_stream_encoder_mt that + # fools a naive AC_CHECK_LIB or AC_CHECK_FUNC, so we need + # to do something more complex here: + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have multithread support in lzma" >&5 +$as_echo_n "checking whether we have multithread support in lzma... " >&6; } +if ${ac_cv_lzma_has_mt+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #if LZMA_VERSION < 50020000 + #error unsupported + #endif +int +main () +{ +lzma_stream_encoder_mt(0, 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lzma_has_mt=yes +else + ac_cv_lzma_has_mt=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lzma_has_mt" >&5 +$as_echo "$ac_cv_lzma_has_mt" >&6; } + if test "x$ac_cv_lzma_has_mt" != xno; then + +$as_echo "#define HAVE_LZMA_STREAM_ENCODER_MT 1" >>confdefs.h + + fi +fi + + +# Check whether --with-lzo2 was given. +if test "${with_lzo2+set}" = set; then : + withval=$with_lzo2; +fi + + +if test "x$with_lzo2" = "xyes"; then + for ac_header in lzo/lzoconf.h lzo/lzo1x.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lzo1x_decompress_safe in -llzo2" >&5 +$as_echo_n "checking for lzo1x_decompress_safe in -llzo2... " >&6; } +if ${ac_cv_lib_lzo2_lzo1x_decompress_safe+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-llzo2 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char lzo1x_decompress_safe (); +int +main () +{ +return lzo1x_decompress_safe (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_lzo2_lzo1x_decompress_safe=yes +else + ac_cv_lib_lzo2_lzo1x_decompress_safe=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lzo2_lzo1x_decompress_safe" >&5 +$as_echo "$ac_cv_lib_lzo2_lzo1x_decompress_safe" >&6; } +if test "x$ac_cv_lib_lzo2_lzo1x_decompress_safe" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBLZO2 1 +_ACEOF + + LIBS="-llzo2 $LIBS" + +fi + +fi + + +# Check whether --with-cng was given. +if test "${with_cng+set}" = set; then : + withval=$with_cng; +fi + + + +# Check whether --with-mbedtls was given. +if test "${with_mbedtls+set}" = set; then : + withval=$with_mbedtls; +fi + + +# Check whether --with-nettle was given. +if test "${with_nettle+set}" = set; then : + withval=$with_nettle; +fi + + +# Check whether --with-openssl was given. +if test "${with_openssl+set}" = set; then : + withval=$with_openssl; +fi + +case "$host_os" in + *darwin* ) with_openssl=no ;; +esac + + +# Check whether --with-xml2 was given. +if test "${with_xml2+set}" = set; then : + withval=$with_xml2; +fi + + +# Check whether --with-expat was given. +if test "${with_expat+set}" = set; then : + withval=$with_expat; +fi + + +if test "x$with_xml2" != "xno"; then + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBXML2_PC" >&5 +$as_echo_n "checking for LIBXML2_PC... " >&6; } + +if test -n "$LIBXML2_PC_CFLAGS"; then + pkg_cv_LIBXML2_PC_CFLAGS="$LIBXML2_PC_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libxml-2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libxml-2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBXML2_PC_CFLAGS=`$PKG_CONFIG --cflags "libxml-2.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LIBXML2_PC_LIBS"; then + pkg_cv_LIBXML2_PC_LIBS="$LIBXML2_PC_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libxml-2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libxml-2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBXML2_PC_LIBS=`$PKG_CONFIG --libs "libxml-2.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LIBXML2_PC_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libxml-2.0" 2>&1` + else + LIBXML2_PC_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libxml-2.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LIBXML2_PC_PKG_ERRORS" >&5 + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for xmlInitParser in -lxml2" >&5 +$as_echo_n "checking for xmlInitParser in -lxml2... " >&6; } +if ${ac_cv_lib_xml2_xmlInitParser+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lxml2 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char xmlInitParser (); +int +main () +{ +return xmlInitParser (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_xml2_xmlInitParser=yes +else + ac_cv_lib_xml2_xmlInitParser=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xml2_xmlInitParser" >&5 +$as_echo "$ac_cv_lib_xml2_xmlInitParser" >&6; } +if test "x$ac_cv_lib_xml2_xmlInitParser" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBXML2 1 +_ACEOF + + LIBS="-lxml2 $LIBS" + +fi + + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for xmlInitParser in -lxml2" >&5 +$as_echo_n "checking for xmlInitParser in -lxml2... " >&6; } +if ${ac_cv_lib_xml2_xmlInitParser+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lxml2 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char xmlInitParser (); +int +main () +{ +return xmlInitParser (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_xml2_xmlInitParser=yes +else + ac_cv_lib_xml2_xmlInitParser=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xml2_xmlInitParser" >&5 +$as_echo "$ac_cv_lib_xml2_xmlInitParser" >&6; } +if test "x$ac_cv_lib_xml2_xmlInitParser" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBXML2 1 +_ACEOF + + LIBS="-lxml2 $LIBS" + +fi + + +else + LIBXML2_PC_CFLAGS=$pkg_cv_LIBXML2_PC_CFLAGS + LIBXML2_PC_LIBS=$pkg_cv_LIBXML2_PC_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + CPPFLAGS="${CPPFLAGS} ${LIBXML2_PC_CFLAGS}" + LIBS="${LIBS} ${LIBXML2_PC_LIBS}" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for xmlInitParser in -lxml2" >&5 +$as_echo_n "checking for xmlInitParser in -lxml2... " >&6; } +if ${ac_cv_lib_xml2_xmlInitParser+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lxml2 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char xmlInitParser (); +int +main () +{ +return xmlInitParser (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_xml2_xmlInitParser=yes +else + ac_cv_lib_xml2_xmlInitParser=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xml2_xmlInitParser" >&5 +$as_echo "$ac_cv_lib_xml2_xmlInitParser" >&6; } +if test "x$ac_cv_lib_xml2_xmlInitParser" = xyes; then : + true +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "Missing xml2 library +See \`config.log' for more details" "$LINENO" 5; } +fi + + +fi + for ac_header in libxml/xmlreader.h libxml/xmlwriter.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +fi +if test "x$ac_cv_header_libxml_xmlreader_h" != "xyes"; then + if test "x$with_expat" != "xno"; then + for ac_header in expat.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "expat.h" "ac_cv_header_expat_h" "$ac_includes_default" +if test "x$ac_cv_header_expat_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_EXPAT_H 1 +_ACEOF + +fi + +done + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XML_ParserCreate in -lexpat" >&5 +$as_echo_n "checking for XML_ParserCreate in -lexpat... " >&6; } +if ${ac_cv_lib_expat_XML_ParserCreate+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lexpat $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XML_ParserCreate (); +int +main () +{ +return XML_ParserCreate (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_expat_XML_ParserCreate=yes +else + ac_cv_lib_expat_XML_ParserCreate=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_expat_XML_ParserCreate" >&5 +$as_echo "$ac_cv_lib_expat_XML_ParserCreate" >&6; } +if test "x$ac_cv_lib_expat_XML_ParserCreate" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBEXPAT 1 +_ACEOF + + LIBS="-lexpat $LIBS" + +fi + + fi +fi + +# Check whether --enable-posix-regex-lib was given. +if test "${enable_posix_regex_lib+set}" = set; then : + enableval=$enable_posix_regex_lib; +else + enable_posix_regex_lib=auto +fi + + +posix_regex_lib_found= +if test "$enable_posix_regex_lib" = "auto" || test "$enable_posix_regex_lib" = "libc" || test "$enable_posix_regex_lib" = "libregex"; then + for ac_header in regex.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "regex.h" "ac_cv_header_regex_h" "$ac_includes_default" +if test "x$ac_cv_header_regex_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_REGEX_H 1 +_ACEOF + +fi + +done + + if test "x$ac_cv_header_regex_h" != "xno"; then + ac_fn_c_check_func "$LINENO" "regcomp" "ac_cv_func_regcomp" +if test "x$ac_cv_func_regcomp" = xyes; then : + +fi + + if test "x$ac_cv_func_regcomp" = xyes; then + posix_regex_lib_found=1 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for regcomp in -lregex" >&5 +$as_echo_n "checking for regcomp in -lregex... " >&6; } +if ${ac_cv_lib_regex_regcomp+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lregex $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char regcomp (); +int +main () +{ +return regcomp (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_regex_regcomp=yes +else + ac_cv_lib_regex_regcomp=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_regex_regcomp" >&5 +$as_echo "$ac_cv_lib_regex_regcomp" >&6; } +if test "x$ac_cv_lib_regex_regcomp" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBREGEX 1 +_ACEOF + + LIBS="-lregex $LIBS" + +fi + + if test "x$ac_cv_lib_regex_regcomp" = xyes; then + posix_regex_lib_found=1 + fi + fi + fi +fi +if test -z $posix_regex_lib_found && (test "$enable_posix_regex_lib" = "auto" || test "$enable_posix_regex_lib" = "libpcreposix"); then + for ac_header in pcreposix.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "pcreposix.h" "ac_cv_header_pcreposix_h" "$ac_includes_default" +if test "x$ac_cv_header_pcreposix_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PCREPOSIX_H 1 +_ACEOF + +fi + +done + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for regcomp in -lpcreposix" >&5 +$as_echo_n "checking for regcomp in -lpcreposix... " >&6; } +if ${ac_cv_lib_pcreposix_regcomp+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpcreposix $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char regcomp (); +int +main () +{ +return regcomp (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pcreposix_regcomp=yes +else + ac_cv_lib_pcreposix_regcomp=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcreposix_regcomp" >&5 +$as_echo "$ac_cv_lib_pcreposix_regcomp" >&6; } +if test "x$ac_cv_lib_pcreposix_regcomp" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPCREPOSIX 1 +_ACEOF + + LIBS="-lpcreposix $LIBS" + +fi + + if test "x$ac_cv_lib_pcreposix_regcomp" != xyes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: trying libpcreposix check again with libpcre" >&5 +$as_echo "$as_me: trying libpcreposix check again with libpcre" >&6;} + unset ac_cv_lib_pcreposix_regcomp + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcre_exec in -lpcre" >&5 +$as_echo_n "checking for pcre_exec in -lpcre... " >&6; } +if ${ac_cv_lib_pcre_pcre_exec+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpcre $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pcre_exec (); +int +main () +{ +return pcre_exec (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pcre_pcre_exec=yes +else + ac_cv_lib_pcre_pcre_exec=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcre_pcre_exec" >&5 +$as_echo "$ac_cv_lib_pcre_pcre_exec" >&6; } +if test "x$ac_cv_lib_pcre_pcre_exec" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPCRE 1 +_ACEOF + + LIBS="-lpcre $LIBS" + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for regcomp in -lpcreposix" >&5 +$as_echo_n "checking for regcomp in -lpcreposix... " >&6; } +if ${ac_cv_lib_pcreposix_regcomp+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpcreposix $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char regcomp (); +int +main () +{ +return regcomp (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pcreposix_regcomp=yes +else + ac_cv_lib_pcreposix_regcomp=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcreposix_regcomp" >&5 +$as_echo "$ac_cv_lib_pcreposix_regcomp" >&6; } +if test "x$ac_cv_lib_pcreposix_regcomp" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPCREPOSIX 1 +_ACEOF + + LIBS="-lpcreposix $LIBS" + +fi + + if test "x$ac_cv_lib_pcre_pcre_exec" = xyes && test "x$ac_cv_lib_pcreposix_regcomp" = xyes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if PCRE_STATIC needs to be defined" >&5 +$as_echo_n "checking if PCRE_STATIC needs to be defined... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + int main() { return regcomp(NULL, NULL, 0); } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + without_pcre_static=yes +else + without_pcre_static=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define PCRE_STATIC + #include + int main() { return regcomp(NULL, NULL, 0); } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + with_pcre_static=yes +else + with_pcre_static=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test "x$without_pcre_static" != xyes && test "x$with_pcre_static" = xyes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define PCRE_STATIC 1" >>confdefs.h + + elif test "x$without_pcre_static" = xyes || test "x$with_pcre_static" = xyes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + posix_regex_lib_found=1 + fi + else + posix_regex_lib_found=1 + fi +fi + +# TODO: Give the user the option of using a pre-existing system +# libarchive. This will define HAVE_LIBARCHIVE which will cause +# bsdtar_platform.h to use #include <...> for the libarchive headers. +# Need to include Makefile.am magic to link against system +# -larchive in that case. +#AC_CHECK_LIB(archive,archive_version) + +# Checks for supported compiler flags + + + + +for flag in -Wall -Wformat -Wformat-security; do + as_CACHEVAR=`$as_echo "ax_cv_check_cflags__$flag" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 +$as_echo_n "checking whether C compiler accepts $flag... " >&6; } +if eval \${$as_CACHEVAR+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$CFLAGS + CFLAGS="$CFLAGS $flag" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$as_CACHEVAR=yes" +else + eval "$as_CACHEVAR=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$ax_check_save_flags +fi +eval ac_res=\$$as_CACHEVAR + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 + (: CFLAGS already contains $flag) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + ;; +esac + +else + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + +fi + +else + : +fi + +done + + +# Checks for typedefs, structures, and compiler characteristics. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 +$as_echo_n "checking for an ANSI C-conforming const... " >&6; } +if ${ac_cv_c_const+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#ifndef __cplusplus + /* Ultrix mips cc rejects this sort of thing. */ + typedef int charset[2]; + const charset cs = { 0, 0 }; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *pcpcc; + char **ppc; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + pcpcc = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++pcpcc; + ppc = (char**) pcpcc; + pcpcc = (char const *const *) ppc; + { /* SCO 3.2v4 cc rejects this sort of thing. */ + char tx; + char *t = &tx; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; } bx; + struct s *b = &bx; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !cs[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_const=yes +else + ac_cv_c_const=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 +$as_echo "$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +$as_echo "#define const /**/" >>confdefs.h + +fi + +# la_TYPE_UID_T defaults to "int", which is incorrect for MinGW +# and MSVC. Use a customized version. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5 +$as_echo_n "checking for uid_t in sys/types.h... " >&6; } +if ${la_cv_type_uid_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "uid_t" >/dev/null 2>&1; then : + la_cv_type_uid_t=yes +else + la_cv_type_uid_t=no +fi +rm -f conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $la_cv_type_uid_t" >&5 +$as_echo "$la_cv_type_uid_t" >&6; } +if test $la_cv_type_uid_t = no; then + case $host in + *mingw*) def_uid_t=short ;; + *) def_uid_t=int ;; + esac + +cat >>confdefs.h <<_ACEOF +#define uid_t $def_uid_t +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define gid_t $def_uid_t +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "mode_t" "ac_cv_type_mode_t" "$ac_includes_default" +if test "x$ac_cv_type_mode_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define mode_t int +_ACEOF + +fi + +# AC_TYPE_OFF_T defaults to "long", which limits us to 4GB files on +# most systems... default to "long long" instead. +ac_fn_c_check_type "$LINENO" "off_t" "ac_cv_type_off_t" "$ac_includes_default" +if test "x$ac_cv_type_off_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define off_t long long +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "id_t" "ac_cv_type_id_t" "$ac_includes_default" +if test "x$ac_cv_type_id_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define id_t unsigned long +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "$ac_includes_default" +if test "x$ac_cv_type_uintptr_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define uintptr_t unsigned int +_ACEOF + +fi + + +# Check for tm_gmtoff in struct tm +ac_fn_c_check_member "$LINENO" "struct tm" "tm_gmtoff" "ac_cv_member_struct_tm_tm_gmtoff" " +#include + +" +if test "x$ac_cv_member_struct_tm_tm_gmtoff" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_TM_TM_GMTOFF 1 +_ACEOF + + +fi +ac_fn_c_check_member "$LINENO" "struct tm" "__tm_gmtoff" "ac_cv_member_struct_tm___tm_gmtoff" " +#include + +" +if test "x$ac_cv_member_struct_tm___tm_gmtoff" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_TM___TM_GMTOFF 1 +_ACEOF + + +fi + + +# Check for f_namemax in struct statfs +ac_fn_c_check_member "$LINENO" "struct statfs" "f_namemax" "ac_cv_member_struct_statfs_f_namemax" " +#include +#include + +" +if test "x$ac_cv_member_struct_statfs_f_namemax" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STATFS_F_NAMEMAX 1 +_ACEOF + + +fi + + +# Check for f_iosize in struct statvfs +ac_fn_c_check_member "$LINENO" "struct statvfs" "f_iosize" "ac_cv_member_struct_statvfs_f_iosize" " +#include + +" +if test "x$ac_cv_member_struct_statvfs_f_iosize" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STATVFS_F_IOSIZE 1 +_ACEOF + + +fi + + +# Check for birthtime in struct stat +ac_fn_c_check_member "$LINENO" "struct stat" "st_birthtime" "ac_cv_member_struct_stat_st_birthtime" "$ac_includes_default" +if test "x$ac_cv_member_struct_stat_st_birthtime" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STAT_ST_BIRTHTIME 1 +_ACEOF + + +fi + + +# Check for high-resolution timestamps in struct stat +ac_fn_c_check_member "$LINENO" "struct stat" "st_birthtimespec.tv_nsec" "ac_cv_member_struct_stat_st_birthtimespec_tv_nsec" "$ac_includes_default" +if test "x$ac_cv_member_struct_stat_st_birthtimespec_tv_nsec" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC 1 +_ACEOF + + +fi + +ac_fn_c_check_member "$LINENO" "struct stat" "st_mtimespec.tv_nsec" "ac_cv_member_struct_stat_st_mtimespec_tv_nsec" "$ac_includes_default" +if test "x$ac_cv_member_struct_stat_st_mtimespec_tv_nsec" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1 +_ACEOF + + +fi + +ac_fn_c_check_member "$LINENO" "struct stat" "st_mtim.tv_nsec" "ac_cv_member_struct_stat_st_mtim_tv_nsec" "$ac_includes_default" +if test "x$ac_cv_member_struct_stat_st_mtim_tv_nsec" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1 +_ACEOF + + +fi + +ac_fn_c_check_member "$LINENO" "struct stat" "st_mtime_n" "ac_cv_member_struct_stat_st_mtime_n" "$ac_includes_default" +if test "x$ac_cv_member_struct_stat_st_mtime_n" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STAT_ST_MTIME_N 1 +_ACEOF + + +fi + # AIX +ac_fn_c_check_member "$LINENO" "struct stat" "st_umtime" "ac_cv_member_struct_stat_st_umtime" "$ac_includes_default" +if test "x$ac_cv_member_struct_stat_st_umtime" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STAT_ST_UMTIME 1 +_ACEOF + + +fi + # Tru64 +ac_fn_c_check_member "$LINENO" "struct stat" "st_mtime_usec" "ac_cv_member_struct_stat_st_mtime_usec" "$ac_includes_default" +if test "x$ac_cv_member_struct_stat_st_mtime_usec" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STAT_ST_MTIME_USEC 1 +_ACEOF + + +fi + # Hurd +# Check for block size support in struct stat +ac_fn_c_check_member "$LINENO" "struct stat" "st_blksize" "ac_cv_member_struct_stat_st_blksize" "$ac_includes_default" +if test "x$ac_cv_member_struct_stat_st_blksize" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STAT_ST_BLKSIZE 1 +_ACEOF + + +fi + +# Check for st_flags in struct stat (BSD fflags) +ac_fn_c_check_member "$LINENO" "struct stat" "st_flags" "ac_cv_member_struct_stat_st_flags" "$ac_includes_default" +if test "x$ac_cv_member_struct_stat_st_flags" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STAT_ST_FLAGS 1 +_ACEOF + + +fi + + +# If you have uintmax_t, we assume printf supports %ju +# If you have unsigned long long, we assume printf supports %llu +# TODO: Check for %ju and %llu support directly. +ac_fn_c_check_type "$LINENO" "uintmax_t" "ac_cv_type_uintmax_t" "$ac_includes_default" +if test "x$ac_cv_type_uintmax_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_UINTMAX_T 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "unsigned long long" "ac_cv_type_unsigned_long_long" "$ac_includes_default" +if test "x$ac_cv_type_unsigned_long_long" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_UNSIGNED_LONG_LONG 1 +_ACEOF + + +fi + + +# We use C99-style integer types +# Declare them if the local platform doesn't already do so. + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for unsigned long long int" >&5 +$as_echo_n "checking for unsigned long long int... " >&6; } +if ${ac_cv_type_unsigned_long_long_int+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_type_unsigned_long_long_int=yes + if test "x${ac_cv_prog_cc_c99-no}" = xno; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + /* For now, do not test the preprocessor; as of 2007 there are too many + implementations with broken preprocessors. Perhaps this can + be revisited in 2012. In the meantime, code should not expect + #if to work with literals wider than 32 bits. */ + /* Test literals. */ + long long int ll = 9223372036854775807ll; + long long int nll = -9223372036854775807LL; + unsigned long long int ull = 18446744073709551615ULL; + /* Test constant expressions. */ + typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) + ? 1 : -1)]; + typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1 + ? 1 : -1)]; + int i = 63; +int +main () +{ +/* Test availability of runtime routines for shift and division. */ + long long int llmax = 9223372036854775807ll; + unsigned long long int ullmax = 18446744073709551615ull; + return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i) + | (llmax / ll) | (llmax % ll) + | (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i) + | (ullmax / ull) | (ullmax % ull)); + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + +else + ac_cv_type_unsigned_long_long_int=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_unsigned_long_long_int" >&5 +$as_echo "$ac_cv_type_unsigned_long_long_int" >&6; } + if test $ac_cv_type_unsigned_long_long_int = yes; then + +$as_echo "#define HAVE_UNSIGNED_LONG_LONG_INT 1" >>confdefs.h + + fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for long long int" >&5 +$as_echo_n "checking for long long int... " >&6; } +if ${ac_cv_type_long_long_int+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_type_long_long_int=yes + if test "x${ac_cv_prog_cc_c99-no}" = xno; then + ac_cv_type_long_long_int=$ac_cv_type_unsigned_long_long_int + if test $ac_cv_type_long_long_int = yes; then + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #ifndef LLONG_MAX + # define HALF \ + (1LL << (sizeof (long long int) * CHAR_BIT - 2)) + # define LLONG_MAX (HALF - 1 + HALF) + #endif +int +main () +{ +long long int n = 1; + int i; + for (i = 0; ; i++) + { + long long int m = n << i; + if (m >> i != n) + return 1; + if (LLONG_MAX / 2 < m) + break; + } + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_type_long_long_int=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_long_long_int" >&5 +$as_echo "$ac_cv_type_long_long_int" >&6; } + if test $ac_cv_type_long_long_int = yes; then + +$as_echo "#define HAVE_LONG_LONG_INT 1" >>confdefs.h + + fi + + + + ac_fn_c_check_type "$LINENO" "intmax_t" "ac_cv_type_intmax_t" "$ac_includes_default" +if test "x$ac_cv_type_intmax_t" = xyes; then : + +$as_echo "#define HAVE_INTMAX_T 1" >>confdefs.h + +else + test $ac_cv_type_long_long_int = yes \ + && ac_type='long long int' \ + || ac_type='long int' + +cat >>confdefs.h <<_ACEOF +#define intmax_t $ac_type +_ACEOF + +fi + + + + + ac_fn_c_check_type "$LINENO" "uintmax_t" "ac_cv_type_uintmax_t" "$ac_includes_default" +if test "x$ac_cv_type_uintmax_t" = xyes; then : + +$as_echo "#define HAVE_UINTMAX_T 1" >>confdefs.h + +else + test $ac_cv_type_unsigned_long_long_int = yes \ + && ac_type='unsigned long long int' \ + || ac_type='unsigned long int' + +cat >>confdefs.h <<_ACEOF +#define uintmax_t $ac_type +_ACEOF + +fi + + +ac_fn_c_find_intX_t "$LINENO" "64" "ac_cv_c_int64_t" +case $ac_cv_c_int64_t in #( + no|yes) ;; #( + *) + +cat >>confdefs.h <<_ACEOF +#define int64_t $ac_cv_c_int64_t +_ACEOF +;; +esac + +ac_fn_c_find_uintX_t "$LINENO" "64" "ac_cv_c_uint64_t" +case $ac_cv_c_uint64_t in #( + no|yes) ;; #( + *) + +$as_echo "#define _UINT64_T 1" >>confdefs.h + + +cat >>confdefs.h <<_ACEOF +#define uint64_t $ac_cv_c_uint64_t +_ACEOF +;; + esac + +ac_fn_c_find_intX_t "$LINENO" "32" "ac_cv_c_int32_t" +case $ac_cv_c_int32_t in #( + no|yes) ;; #( + *) + +cat >>confdefs.h <<_ACEOF +#define int32_t $ac_cv_c_int32_t +_ACEOF +;; +esac + +ac_fn_c_find_uintX_t "$LINENO" "32" "ac_cv_c_uint32_t" +case $ac_cv_c_uint32_t in #( + no|yes) ;; #( + *) + +$as_echo "#define _UINT32_T 1" >>confdefs.h + + +cat >>confdefs.h <<_ACEOF +#define uint32_t $ac_cv_c_uint32_t +_ACEOF +;; + esac + +ac_fn_c_find_intX_t "$LINENO" "16" "ac_cv_c_int16_t" +case $ac_cv_c_int16_t in #( + no|yes) ;; #( + *) + +cat >>confdefs.h <<_ACEOF +#define int16_t $ac_cv_c_int16_t +_ACEOF +;; +esac + +ac_fn_c_find_uintX_t "$LINENO" "16" "ac_cv_c_uint16_t" +case $ac_cv_c_uint16_t in #( + no|yes) ;; #( + *) + + +cat >>confdefs.h <<_ACEOF +#define uint16_t $ac_cv_c_uint16_t +_ACEOF +;; + esac + +ac_fn_c_find_uintX_t "$LINENO" "8" "ac_cv_c_uint8_t" +case $ac_cv_c_uint8_t in #( + no|yes) ;; #( + *) + +$as_echo "#define _UINT8_T 1" >>confdefs.h + + +cat >>confdefs.h <<_ACEOF +#define uint8_t $ac_cv_c_uint8_t +_ACEOF +;; + esac + + +ac_fn_c_check_decl "$LINENO" "SIZE_MAX" "ac_cv_have_decl_SIZE_MAX" "$ac_includes_default" +if test "x$ac_cv_have_decl_SIZE_MAX" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_SIZE_MAX $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "INT32_MAX" "ac_cv_have_decl_INT32_MAX" "$ac_includes_default" +if test "x$ac_cv_have_decl_INT32_MAX" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_INT32_MAX $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "INT32_MIN" "ac_cv_have_decl_INT32_MIN" "$ac_includes_default" +if test "x$ac_cv_have_decl_INT32_MIN" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_INT32_MIN $ac_have_decl +_ACEOF + +ac_fn_c_check_decl "$LINENO" "INT64_MAX" "ac_cv_have_decl_INT64_MAX" "$ac_includes_default" +if test "x$ac_cv_have_decl_INT64_MAX" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_INT64_MAX $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "INT64_MIN" "ac_cv_have_decl_INT64_MIN" "$ac_includes_default" +if test "x$ac_cv_have_decl_INT64_MIN" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_INT64_MIN $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "UINT64_MAX" "ac_cv_have_decl_UINT64_MAX" "$ac_includes_default" +if test "x$ac_cv_have_decl_UINT64_MAX" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_UINT64_MAX $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "UINT32_MAX" "ac_cv_have_decl_UINT32_MAX" "$ac_includes_default" +if test "x$ac_cv_have_decl_UINT32_MAX" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_UINT32_MAX $ac_have_decl +_ACEOF + +ac_fn_c_check_decl "$LINENO" "INTMAX_MAX" "ac_cv_have_decl_INTMAX_MAX" "$ac_includes_default" +if test "x$ac_cv_have_decl_INTMAX_MAX" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_INTMAX_MAX $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "INTMAX_MIN" "ac_cv_have_decl_INTMAX_MIN" "$ac_includes_default" +if test "x$ac_cv_have_decl_INTMAX_MIN" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_INTMAX_MIN $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "UINTMAX_MAX" "ac_cv_have_decl_UINTMAX_MAX" "$ac_includes_default" +if test "x$ac_cv_have_decl_UINTMAX_MAX" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_UINTMAX_MAX $ac_have_decl +_ACEOF + + +ac_fn_c_check_decl "$LINENO" "SSIZE_MAX" "ac_cv_have_decl_SSIZE_MAX" "#include +" +if test "x$ac_cv_have_decl_SSIZE_MAX" = xyes; then : + +$as_echo "#define HAVE_DECL_SSIZE_MAX 1" >>confdefs.h + +fi + + +ac_fn_c_check_decl "$LINENO" "EFTYPE" "ac_cv_have_decl_EFTYPE" "#include +" +if test "x$ac_cv_have_decl_EFTYPE" = xyes; then : + +$as_echo "#define HAVE_EFTYPE 1" >>confdefs.h + +fi + +ac_fn_c_check_decl "$LINENO" "EILSEQ" "ac_cv_have_decl_EILSEQ" "#include +" +if test "x$ac_cv_have_decl_EILSEQ" = xyes; then : + +$as_echo "#define HAVE_EILSEQ 1" >>confdefs.h + +fi + +ac_fn_c_check_type "$LINENO" "wchar_t" "ac_cv_type_wchar_t" "$ac_includes_default" +if test "x$ac_cv_type_wchar_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_WCHAR_T 1 +_ACEOF + # The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of wchar_t" >&5 +$as_echo_n "checking size of wchar_t... " >&6; } +if ${ac_cv_sizeof_wchar_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (wchar_t))" "ac_cv_sizeof_wchar_t" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_wchar_t" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (wchar_t) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_wchar_t=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_wchar_t" >&5 +$as_echo "$ac_cv_sizeof_wchar_t" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_WCHAR_T $ac_cv_sizeof_wchar_t +_ACEOF + + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 +$as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } +if ${ac_cv_header_time+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include + +int +main () +{ +if ((struct tm *) 0) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_time=yes +else + ac_cv_header_time=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 +$as_echo "$ac_cv_header_time" >&6; } +if test $ac_cv_header_time = yes; then + +$as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h + +fi + + +# Checks for library functions. +if test $ac_cv_c_compiler_gnu = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC needs -traditional" >&5 +$as_echo_n "checking whether $CC needs -traditional... " >&6; } +if ${ac_cv_prog_gcc_traditional+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_pattern="Autoconf.*'x'" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +Autoconf TIOCGETP +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "$ac_pattern" >/dev/null 2>&1; then : + ac_cv_prog_gcc_traditional=yes +else + ac_cv_prog_gcc_traditional=no +fi +rm -f conftest* + + + if test $ac_cv_prog_gcc_traditional = no; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +Autoconf TCGETA +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "$ac_pattern" >/dev/null 2>&1; then : + ac_cv_prog_gcc_traditional=yes +fi +rm -f conftest* + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_gcc_traditional" >&5 +$as_echo "$ac_cv_prog_gcc_traditional" >&6; } + if test $ac_cv_prog_gcc_traditional = yes; then + CC="$CC -traditional" + fi +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether sys/types.h defines makedev" >&5 +$as_echo_n "checking whether sys/types.h defines makedev... " >&6; } +if ${ac_cv_header_sys_types_h_makedev+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +return makedev(0, 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_header_sys_types_h_makedev=yes +else + ac_cv_header_sys_types_h_makedev=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_types_h_makedev" >&5 +$as_echo "$ac_cv_header_sys_types_h_makedev" >&6; } + +if test $ac_cv_header_sys_types_h_makedev = no; then +ac_fn_c_check_header_mongrel "$LINENO" "sys/mkdev.h" "ac_cv_header_sys_mkdev_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_mkdev_h" = xyes; then : + +$as_echo "#define MAJOR_IN_MKDEV 1" >>confdefs.h + +fi + + + + if test $ac_cv_header_sys_mkdev_h = no; then + ac_fn_c_check_header_mongrel "$LINENO" "sys/sysmacros.h" "ac_cv_header_sys_sysmacros_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_sysmacros_h" = xyes; then : + +$as_echo "#define MAJOR_IN_SYSMACROS 1" >>confdefs.h + +fi + + + fi +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGEFILE_SOURCE value needed for large files" >&5 +$as_echo_n "checking for _LARGEFILE_SOURCE value needed for large files... " >&6; } +if ${ac_cv_sys_largefile_source+:} false; then : + $as_echo_n "(cached) " >&6 +else + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include /* for off_t */ + #include +int +main () +{ +int (*fp) (FILE *, off_t, int) = fseeko; + return fseeko (stdin, 0, 0) && fp (stdin, 0, 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_sys_largefile_source=no; break +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _LARGEFILE_SOURCE 1 +#include /* for off_t */ + #include +int +main () +{ +int (*fp) (FILE *, off_t, int) = fseeko; + return fseeko (stdin, 0, 0) && fp (stdin, 0, 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_sys_largefile_source=1; break +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_cv_sys_largefile_source=unknown + break +done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_source" >&5 +$as_echo "$ac_cv_sys_largefile_source" >&6; } +case $ac_cv_sys_largefile_source in #( + no | unknown) ;; + *) +cat >>confdefs.h <<_ACEOF +#define _LARGEFILE_SOURCE $ac_cv_sys_largefile_source +_ACEOF +;; +esac +rm -rf conftest* + +# We used to try defining _XOPEN_SOURCE=500 too, to work around a bug +# in glibc 2.1.3, but that breaks too many other things. +# If you want fseeko and ftello with glibc, upgrade to a fixed glibc. +if test $ac_cv_sys_largefile_source != unknown; then + +$as_echo "#define HAVE_FSEEKO 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working memcmp" >&5 +$as_echo_n "checking for working memcmp... " >&6; } +if ${ac_cv_func_memcmp_working+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_memcmp_working=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Some versions of memcmp are not 8-bit clean. */ + char c0 = '\100', c1 = '\200', c2 = '\201'; + if (memcmp(&c0, &c2, 1) >= 0 || memcmp(&c1, &c2, 1) >= 0) + return 1; + + /* The Next x86 OpenStep bug shows up only when comparing 16 bytes + or more and with at least one buffer not starting on a 4-byte boundary. + William Lewis provided this test program. */ + { + char foo[21]; + char bar[21]; + int i; + for (i = 0; i < 4; i++) + { + char *a = foo + i; + char *b = bar + i; + strcpy (a, "--------01111111"); + strcpy (b, "--------10000000"); + if (memcmp (a, b, 16) >= 0) + return 1; + } + return 0; + } + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_memcmp_working=yes +else + ac_cv_func_memcmp_working=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_memcmp_working" >&5 +$as_echo "$ac_cv_func_memcmp_working" >&6; } +test $ac_cv_func_memcmp_working = no && case " $LIBOBJS " in + *" memcmp.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS memcmp.$ac_objext" + ;; +esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether lstat correctly handles trailing slash" >&5 +$as_echo_n "checking whether lstat correctly handles trailing slash... " >&6; } +if ${ac_cv_func_lstat_dereferences_slashed_symlink+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f conftest.sym conftest.file +echo >conftest.file +if test "$as_ln_s" = "ln -s" && ln -s conftest.file conftest.sym; then + if test "$cross_compiling" = yes; then : + ac_cv_func_lstat_dereferences_slashed_symlink=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +struct stat sbuf; + /* Linux will dereference the symlink and fail, as required by POSIX. + That is better in the sense that it means we will not + have to compile and use the lstat wrapper. */ + return lstat ("conftest.sym/", &sbuf) == 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_lstat_dereferences_slashed_symlink=yes +else + ac_cv_func_lstat_dereferences_slashed_symlink=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +else + # If the `ln -s' command failed, then we probably don't even + # have an lstat function. + ac_cv_func_lstat_dereferences_slashed_symlink=no +fi +rm -f conftest.sym conftest.file + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_lstat_dereferences_slashed_symlink" >&5 +$as_echo "$ac_cv_func_lstat_dereferences_slashed_symlink" >&6; } + +test $ac_cv_func_lstat_dereferences_slashed_symlink = yes && + +cat >>confdefs.h <<_ACEOF +#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1 +_ACEOF + + +if test "x$ac_cv_func_lstat_dereferences_slashed_symlink" = xno; then + case " $LIBOBJS " in + *" lstat.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS lstat.$ac_objext" + ;; +esac + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether lstat accepts an empty string" >&5 +$as_echo_n "checking whether lstat accepts an empty string... " >&6; } +if ${ac_cv_func_lstat_empty_string_bug+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_lstat_empty_string_bug=yes +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +struct stat sbuf; + return lstat ("", &sbuf) == 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_lstat_empty_string_bug=no +else + ac_cv_func_lstat_empty_string_bug=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_lstat_empty_string_bug" >&5 +$as_echo "$ac_cv_func_lstat_empty_string_bug" >&6; } +if test $ac_cv_func_lstat_empty_string_bug = yes; then + case " $LIBOBJS " in + *" lstat.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS lstat.$ac_objext" + ;; +esac + + +cat >>confdefs.h <<_ACEOF +#define HAVE_LSTAT_EMPTY_STRING_BUG 1 +_ACEOF + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stat accepts an empty string" >&5 +$as_echo_n "checking whether stat accepts an empty string... " >&6; } +if ${ac_cv_func_stat_empty_string_bug+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_stat_empty_string_bug=yes +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +struct stat sbuf; + return stat ("", &sbuf) == 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_stat_empty_string_bug=no +else + ac_cv_func_stat_empty_string_bug=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_stat_empty_string_bug" >&5 +$as_echo "$ac_cv_func_stat_empty_string_bug" >&6; } +if test $ac_cv_func_stat_empty_string_bug = yes; then + case " $LIBOBJS " in + *" stat.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS stat.$ac_objext" + ;; +esac + + +cat >>confdefs.h <<_ACEOF +#define HAVE_STAT_EMPTY_STRING_BUG 1 +_ACEOF + +fi + +ac_fn_c_check_decl "$LINENO" "strerror_r" "ac_cv_have_decl_strerror_r" "$ac_includes_default" +if test "x$ac_cv_have_decl_strerror_r" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_STRERROR_R $ac_have_decl +_ACEOF + +for ac_func in strerror_r +do : + ac_fn_c_check_func "$LINENO" "strerror_r" "ac_cv_func_strerror_r" +if test "x$ac_cv_func_strerror_r" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STRERROR_R 1 +_ACEOF + +fi +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether strerror_r returns char *" >&5 +$as_echo_n "checking whether strerror_r returns char *... " >&6; } +if ${ac_cv_func_strerror_r_char_p+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ac_cv_func_strerror_r_char_p=no + if test $ac_cv_have_decl_strerror_r = yes; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + char buf[100]; + char x = *strerror_r (0, buf, sizeof buf); + char *p = strerror_r (0, buf, sizeof buf); + return !p || x; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_strerror_r_char_p=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + else + # strerror_r is not declared. Choose between + # systems that have relatively inaccessible declarations for the + # function. BeOS and DEC UNIX 4.0 fall in this category, but the + # former has a strerror_r that returns char*, while the latter + # has a strerror_r that returns `int'. + # This test should segfault on the DEC system. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default + extern char *strerror_r (); +int +main () +{ +char buf[100]; + char x = *strerror_r (0, buf, sizeof buf); + return ! isalpha (x); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_strerror_r_char_p=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_strerror_r_char_p" >&5 +$as_echo "$ac_cv_func_strerror_r_char_p" >&6; } +if test $ac_cv_func_strerror_r_char_p = yes; then + +$as_echo "#define STRERROR_R_CHAR_P 1" >>confdefs.h + +fi + +for ac_func in strftime +do : + ac_fn_c_check_func "$LINENO" "strftime" "ac_cv_func_strftime" +if test "x$ac_cv_func_strftime" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STRFTIME 1 +_ACEOF + +else + # strftime is in -lintl on SCO UNIX. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for strftime in -lintl" >&5 +$as_echo_n "checking for strftime in -lintl... " >&6; } +if ${ac_cv_lib_intl_strftime+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lintl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char strftime (); +int +main () +{ +return strftime (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_intl_strftime=yes +else + ac_cv_lib_intl_strftime=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_strftime" >&5 +$as_echo "$ac_cv_lib_intl_strftime" >&6; } +if test "x$ac_cv_lib_intl_strftime" = xyes; then : + $as_echo "#define HAVE_STRFTIME 1" >>confdefs.h + +LIBS="-lintl $LIBS" +fi + +fi +done + +for ac_func in vprintf +do : + ac_fn_c_check_func "$LINENO" "vprintf" "ac_cv_func_vprintf" +if test "x$ac_cv_func_vprintf" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_VPRINTF 1 +_ACEOF + +ac_fn_c_check_func "$LINENO" "_doprnt" "ac_cv_func__doprnt" +if test "x$ac_cv_func__doprnt" = xyes; then : + +$as_echo "#define HAVE_DOPRNT 1" >>confdefs.h + +fi + +fi +done + + +# check for: +# CreateHardLinkA(LPCSTR, LPCSTR, LPSECURITY_ATTRIBUTES) +# To avoid necessity for including windows.h or special forward declaration +# workarounds, we use 'void *' for 'struct SECURITY_ATTRIBUTES *' +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CreateHardLinkA" >&5 +$as_echo_n "checking for CreateHardLinkA... " >&6; } +if ${ac_cv_func_CreateHardLinkA+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char __stdcall CreateHardLinkA ( const char *, const char *, void * ) below. */ +#include +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char __stdcall CreateHardLinkA ( const char *, const char *, void * ); +char (*f) ( const char *, const char *, void * ); + +int +main () +{ +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_CreateHardLinkA) || defined (__stub___CreateHardLinkA) +choke me +#else +f = CreateHardLinkA; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_func_CreateHardLinkA=yes +else + ac_cv_func_CreateHardLinkA=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_CreateHardLinkA" >&5 +$as_echo "$ac_cv_func_CreateHardLinkA" >&6; } +if test $ac_cv_func_CreateHardLinkA = yes; then : + +fi +for ac_func in arc4random_buf chflags chown chroot ctime_r +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in fchdir fchflags fchmod fchown fcntl fdopendir fork +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in fstat fstatat fstatfs fstatvfs ftruncate +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in futimens futimes futimesat +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in geteuid getpid getgrgid_r getgrnam_r +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in getpwnam_r getpwuid_r getvfsbyname gmtime_r +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in lchflags lchmod lchown link localtime_r lstat lutimes +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in mbrtowc memmove memset +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in mkdir mkfifo mknod mkstemp +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in nl_langinfo openat pipe poll posix_spawnp readlink readlinkat +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in readpassphrase +do : + ac_fn_c_check_func "$LINENO" "readpassphrase" "ac_cv_func_readpassphrase" +if test "x$ac_cv_func_readpassphrase" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_READPASSPHRASE 1 +_ACEOF + +fi +done + +for ac_func in select setenv setlocale sigaction statfs statvfs +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in strchr strdup strerror strncpy_s strrchr symlink timegm +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in tzset unlinkat unsetenv utime utimensat utimes vfork +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in wcrtomb wcscmp wcscpy wcslen wctomb wmemcmp wmemcpy wmemmove +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in _ctime64_s _fseeki64 +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in _get_timezone _gmtime64_s _localtime64_s _mkgmtime64 +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +# detects cygwin-1.7, as opposed to older versions +for ac_func in cygwin_conv_path +do : + ac_fn_c_check_func "$LINENO" "cygwin_conv_path" "ac_cv_func_cygwin_conv_path" +if test "x$ac_cv_func_cygwin_conv_path" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_CYGWIN_CONV_PATH 1 +_ACEOF + +fi +done + + +# DragonFly uses vfsconf, FreeBSD xvfsconf. +ac_fn_c_check_type "$LINENO" "struct vfsconf" "ac_cv_type_struct_vfsconf" "#if HAVE_SYS_TYPES_H + #include + #endif + #include + +" +if test "x$ac_cv_type_struct_vfsconf" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_VFSCONF 1 +_ACEOF + + +fi + + +ac_fn_c_check_type "$LINENO" "struct xvfsconf" "ac_cv_type_struct_xvfsconf" "#if HAVE_SYS_TYPES_H + #include + #endif + #include + +" +if test "x$ac_cv_type_struct_xvfsconf" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_XVFSCONF 1 +_ACEOF + + +fi + + +# There are several variants of readdir_r around; we only +# accept the POSIX-compliant version. +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +DIR *dir; struct dirent e, *r; + return(readdir_r(dir, &e, &r)); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define HAVE_READDIR_R 1" >>confdefs.h + + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# dirfd can be either a function or a macro. +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + DIR *dir; +int +main () +{ +return(dirfd(dir)); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define HAVE_DIRFD 1" >>confdefs.h + + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +# FreeBSD's nl_langinfo supports an option to specify whether the +# current locale uses month/day or day/month ordering. It makes the +# output a little prettier... +ac_fn_c_check_decl "$LINENO" "D_MD_ORDER" "ac_cv_have_decl_D_MD_ORDER" "#if HAVE_LANGINFO_H +#include +#endif + +" +if test "x$ac_cv_have_decl_D_MD_ORDER" = xyes; then : + +$as_echo "#define HAVE_D_MD_ORDER 1" >>confdefs.h + +fi + + +# Check for dirent.d_namlen field explicitly +# (This is a bit more straightforward than, if not quite as portable as, +# the recipe given by the autoconf maintainers.) +ac_fn_c_check_member "$LINENO" "struct dirent" "d_namlen" "ac_cv_member_struct_dirent_d_namlen" "#if HAVE_DIRENT_H +#include +#endif + +" +if test "x$ac_cv_member_struct_dirent_d_namlen" = xyes; then : + +fi + + +# Check for Extended Attributes support +# Check whether --enable-xattr was given. +if test "${enable_xattr+set}" = set; then : + enableval=$enable_xattr; +fi + + +if test "x$enable_xattr" != "xno"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing setxattr" >&5 +$as_echo_n "checking for library containing setxattr... " >&6; } +if ${ac_cv_search_setxattr+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char setxattr (); +int +main () +{ +return setxattr (); + ; + return 0; +} +_ACEOF +for ac_lib in '' attr gnu; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_setxattr=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_setxattr+:} false; then : + break +fi +done +if ${ac_cv_search_setxattr+:} false; then : + +else + ac_cv_search_setxattr=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_setxattr" >&5 +$as_echo "$ac_cv_search_setxattr" >&6; } +ac_res=$ac_cv_search_setxattr +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + ac_fn_c_check_decl "$LINENO" "EXTATTR_NAMESPACE_USER" "ac_cv_have_decl_EXTATTR_NAMESPACE_USER" "#include +#include + +" +if test "x$ac_cv_have_decl_EXTATTR_NAMESPACE_USER" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_EXTATTR_NAMESPACE_USER $ac_have_decl +_ACEOF + + ac_fn_c_check_decl "$LINENO" "XATTR_NOFOLLOW" "ac_cv_have_decl_XATTR_NOFOLLOW" "#include + +" +if test "x$ac_cv_have_decl_XATTR_NOFOLLOW" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_XATTR_NOFOLLOW $ac_have_decl +_ACEOF + + if test "x$ac_cv_header_sys_xattr_h" = "xyes" \ + -a "x$ac_cv_have_decl_XATTR_NOFOLLOW" = "xyes"; then + # Darwin extended attributes support + if ${ac_cv_archive_xattr_darwin+:} false; then : + $as_echo_n "(cached) " >&6 +else + for ac_func in fgetxattr \ + flistxattr \ + fsetxattr \ + getxattr \ + listxattr \ + setxattr +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + ac_cv_archive_xattr_darwin=yes +else + ac_cv_archive_xattr_darwin=no +fi +done + + + +fi + + elif test "x$ac_cv_header_sys_extattr_h" = "xyes" \ + -a "x$ac_cv_have_decl_EXTATTR_NAMESPACE_USER" = "xyes"; then + # FreeBSD extended attributes support + if ${ac_cv_archive_xattr_freebsd+:} false; then : + $as_echo_n "(cached) " >&6 +else + for ac_func in extattr_get_fd \ + extattr_get_file \ + extattr_get_link \ + extattr_list_fd \ + extattr_list_file \ + extattr_list_link \ + extattr_set_fd \ + extattr_set_link +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + ac_cv_archive_xattr_freebsd=yes +else + ac_cv_archive_xattr_freebsd=no +fi +done + + + +fi + + elif test "x$ac_cv_header_sys_xattr_h" = "xyes" \ + -o "x$ac_cv_header_attr_xattr_h" = "xyes"; then + # Linux extended attributes support + if ${ac_cv_archive_xattr_linux+:} false; then : + $as_echo_n "(cached) " >&6 +else + for ac_func in fgetxattr \ + flistxattr \ + fsetxattr \ + getxattr \ + lgetxattr \ + listxattr \ + llistxattr \ + lsetxattr +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + ac_cv_archive_xattr_linux=yes +else + ac_cv_archive_xattr_linux=no +fi +done + + + +fi + + elif test "x$ac_cv_header_sys_ea_h" = "xyes"; then + # AIX extended attributes support + if ${ac_cv_archive_xattr_aix+:} false; then : + $as_echo_n "(cached) " >&6 +else + for ac_func in fgetea \ + flistea \ + fsetea \ + getea \ + lgetea \ + listea \ + llistea \ + lsetea +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + ac_cv_archive_xattr_aix=yes +else + ac_cv_archive_xattr_aix=no +fi +done + + + +fi + + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for extended attributes support" >&5 +$as_echo_n "checking for extended attributes support... " >&6; } + if test "x$ac_cv_archive_xattr_linux" = "xyes"; then + +$as_echo "#define ARCHIVE_XATTR_LINUX 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Linux" >&5 +$as_echo "Linux" >&6; } + elif test "x$ac_cv_archive_xattr_darwin" = "xyes"; then + +$as_echo "#define ARCHIVE_XATTR_DARWIN 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Darwin" >&5 +$as_echo "Darwin" >&6; } + elif test "x$ac_cv_archive_xattr_freebsd" = "xyes"; then + +$as_echo "#define ARCHIVE_XATTR_FREEBSD 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: FreeBSD" >&5 +$as_echo "FreeBSD" >&6; } + elif test "x$ac_cv_archive_xattr_aix" = "xyes"; then + +$as_echo "#define ARCHIVE_XATTR_AIX 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: AIX" >&5 +$as_echo "AIX" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } + fi +fi + +# Check for ACL support +# +# The ACL support in libarchive is written against the POSIX1e draft, +# which was never officially approved and varies quite a bit across +# platforms. Worse, some systems have completely non-POSIX acl functions, +# which makes the following checks rather more complex than I would like. +# +# Check whether --enable-acl was given. +if test "${enable_acl+set}" = set; then : + enableval=$enable_acl; +fi + + +if test "x$enable_acl" != "xno"; then + # Libacl + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for acl_get_file in -lacl" >&5 +$as_echo_n "checking for acl_get_file in -lacl... " >&6; } +if ${ac_cv_lib_acl_acl_get_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lacl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char acl_get_file (); +int +main () +{ +return acl_get_file (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_acl_acl_get_file=yes +else + ac_cv_lib_acl_acl_get_file=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_acl_acl_get_file" >&5 +$as_echo "$ac_cv_lib_acl_acl_get_file" >&6; } +if test "x$ac_cv_lib_acl_acl_get_file" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBACL 1 +_ACEOF + + LIBS="-lacl $LIBS" + +fi + + + ac_fn_c_check_type "$LINENO" "acl_t" "ac_cv_type_acl_t" " + #if HAVE_SYS_TYPES_H + #include + #endif + #if HAVE_SYS_ACL_H + #include + #endif + +" +if test "x$ac_cv_type_acl_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_ACL_T 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "acl_entry_t" "ac_cv_type_acl_entry_t" " + #if HAVE_SYS_TYPES_H + #include + #endif + #if HAVE_SYS_ACL_H + #include + #endif + +" +if test "x$ac_cv_type_acl_entry_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_ACL_ENTRY_T 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "acl_permset_t" "ac_cv_type_acl_permset_t" " + #if HAVE_SYS_TYPES_H + #include + #endif + #if HAVE_SYS_ACL_H + #include + #endif + +" +if test "x$ac_cv_type_acl_permset_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_ACL_PERMSET_T 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "acl_tag_t" "ac_cv_type_acl_tag_t" " + #if HAVE_SYS_TYPES_H + #include + #endif + #if HAVE_SYS_ACL_H + #include + #endif + +" +if test "x$ac_cv_type_acl_tag_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_ACL_TAG_T 1 +_ACEOF + + +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for richacl_get_file in -lrichacl" >&5 +$as_echo_n "checking for richacl_get_file in -lrichacl... " >&6; } +if ${ac_cv_lib_richacl_richacl_get_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lrichacl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char richacl_get_file (); +int +main () +{ +return richacl_get_file (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_richacl_richacl_get_file=yes +else + ac_cv_lib_richacl_richacl_get_file=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_richacl_richacl_get_file" >&5 +$as_echo "$ac_cv_lib_richacl_richacl_get_file" >&6; } +if test "x$ac_cv_lib_richacl_richacl_get_file" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBRICHACL 1 +_ACEOF + + LIBS="-lrichacl $LIBS" + +fi + + + ac_fn_c_check_type "$LINENO" "struct richace" "ac_cv_type_struct_richace" " + #if HAVE_SYS_RICHACL_H + #include + #endif + +" +if test "x$ac_cv_type_struct_richace" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_RICHACE 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "struct richacl" "ac_cv_type_struct_richacl" " + #if HAVE_SYS_RICHACL_H + #include + #endif + +" +if test "x$ac_cv_type_struct_richacl" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_RICHACL 1 +_ACEOF + + +fi + + + # Solaris and derivates ACLs + for ac_func in acl facl +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + if test "x$ac_cv_lib_richacl_richacl_get_file" = "xyes" \ + -a "x$ac_cv_type_struct_richace" = "xyes" \ + -a "x$ac_cv_type_struct_richacl" = "xyes"; then + if ${ac_cv_archive_acl_librichacl+:} false; then : + $as_echo_n "(cached) " >&6 +else + for ac_func in richacl_alloc \ + richacl_equiv_mode \ + richacl_free \ + richacl_get_fd \ + richacl_get_file \ + richacl_set_fd \ + richacl_set_file +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + ac_cv_archive_acl_librichacl=yes +else + ac_cv_archive_acl_librichacl=no +fi +done + +fi + + fi + + if test "x$ac_cv_func_acl" = "xyes" \ + -a "x$ac_cv_func_facl" = "xyes"; then + ac_fn_c_check_type "$LINENO" "aclent_t" "ac_cv_type_aclent_t" "#include +" +if test "x$ac_cv_type_aclent_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_ACLENT_T 1 +_ACEOF + + +fi + + if test "x$ac_cv_type_aclent_t" = "xyes"; then + if ${ac_cv_archive_acl_sunos+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_fn_c_check_decl "$LINENO" "GETACL" "ac_cv_have_decl_GETACL" "#include +" +if test "x$ac_cv_have_decl_GETACL" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_GETACL $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + ac_cv_archive_acl_sunos=yes +else + ac_cv_archive_acl_sunos=no +fi +ac_fn_c_check_decl "$LINENO" "SETACL" "ac_cv_have_decl_SETACL" "#include +" +if test "x$ac_cv_have_decl_SETACL" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_SETACL $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + ac_cv_archive_acl_sunos=yes +else + ac_cv_archive_acl_sunos=no +fi +ac_fn_c_check_decl "$LINENO" "GETACLCNT" "ac_cv_have_decl_GETACLCNT" "#include +" +if test "x$ac_cv_have_decl_GETACLCNT" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_GETACLCNT $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + ac_cv_archive_acl_sunos=yes +else + ac_cv_archive_acl_sunos=no +fi + +fi + + ac_fn_c_check_type "$LINENO" "ace_t" "ac_cv_type_ace_t" "#include +" +if test "x$ac_cv_type_ace_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_ACE_T 1 +_ACEOF + + +fi + + if test "x$ac_cv_type_ace_t" = "xyes"; then + if ${ac_cv_archive_acl_sunos_nfs4+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_fn_c_check_decl "$LINENO" "ACE_GETACL" "ac_cv_have_decl_ACE_GETACL" "#include +" +if test "x$ac_cv_have_decl_ACE_GETACL" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_ACE_GETACL $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + ac_cv_archive_acl_sunos_nfs4=yes +else + ac_cv_archive_acl_sonos_nfs4=no +fi +ac_fn_c_check_decl "$LINENO" "ACE_SETACL" "ac_cv_have_decl_ACE_SETACL" "#include +" +if test "x$ac_cv_have_decl_ACE_SETACL" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_ACE_SETACL $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + ac_cv_archive_acl_sunos_nfs4=yes +else + ac_cv_archive_acl_sonos_nfs4=no +fi +ac_fn_c_check_decl "$LINENO" "ACE_GETACLCNT" "ac_cv_have_decl_ACE_GETACLCNT" "#include +" +if test "x$ac_cv_have_decl_ACE_GETACLCNT" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_ACE_GETACLCNT $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + ac_cv_archive_acl_sunos_nfs4=yes +else + ac_cv_archive_acl_sonos_nfs4=no +fi + +fi + + fi + fi + elif test "x$ac_cv_type_acl_t" = "xyes" \ + -a "x$ac_cv_type_acl_entry_t" = "xyes" \ + -a "x$ac_cv_type_acl_permset_t" = "xyes" \ + -a "x$ac_cv_type_acl_tag_t" = "xyes"; then + # POSIX.1e ACL functions + if ${ac_cv_posix_acl_funcs+:} false; then : + $as_echo_n "(cached) " >&6 +else + for ac_func in acl_add_perm \ + acl_clear_perms \ + acl_create_entry \ + acl_delete_def_file \ + acl_free \ + acl_get_entry \ + acl_get_fd \ + acl_get_file \ + acl_get_permset \ + acl_get_qualifier \ + acl_get_tag_type \ + acl_init \ + acl_set_fd \ + acl_set_file \ + acl_set_qualifier \ + acl_set_tag_type +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + ac_cv_posix_acl_funcs=yes +else + ac_cv_posix_acl_funcs=no +fi +done + + +fi + + + for ac_func in acl_get_perm +do : + ac_fn_c_check_func "$LINENO" "acl_get_perm" "ac_cv_func_acl_get_perm" +if test "x$ac_cv_func_acl_get_perm" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ACL_GET_PERM 1 +_ACEOF + +fi +done + + + if test "x$ac_cv_posix_acl_funcs" = "xyes" \ + -a "x$ac_cv_header_acl_libacl_h" = "xyes" \ + -a "x$ac_cv_lib_acl_acl_get_file" = "xyes" \ + -a "x$ac_cv_func_acl_get_perm"; then + if ${ac_cv_archive_acl_libacl+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_archive_acl_libacl=yes +fi + + +$as_echo "#define ARCHIVE_ACL_LIBACL 1" >>confdefs.h + + else + # FreeBSD/Darwin + for ac_func in acl_add_flag_np \ + acl_clear_flags_np \ + acl_get_brand_np \ + acl_get_entry_type_np \ + acl_get_flag_np \ + acl_get_flagset_np \ + acl_get_fd_np \ + acl_get_link_np \ + acl_get_perm_np \ + acl_is_trivial_np \ + acl_set_entry_type_np \ + acl_set_fd_np \ + acl_set_link_np +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + for ac_func in mbr_uid_to_uuid \ + mbr_uuid_to_id \ + mbr_gid_to_uuid +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + ac_fn_c_check_decl "$LINENO" "ACL_TYPE_EXTENDED" "ac_cv_have_decl_ACL_TYPE_EXTENDED" "#include + #include +" +if test "x$ac_cv_have_decl_ACL_TYPE_EXTENDED" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_ACL_TYPE_EXTENDED $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "ACL_TYPE_NFS4" "ac_cv_have_decl_ACL_TYPE_NFS4" "#include + #include +" +if test "x$ac_cv_have_decl_ACL_TYPE_NFS4" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_ACL_TYPE_NFS4 $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "ACL_USER" "ac_cv_have_decl_ACL_USER" "#include + #include +" +if test "x$ac_cv_have_decl_ACL_USER" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_ACL_USER $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "ACL_SYNCHRONIZE" "ac_cv_have_decl_ACL_SYNCHRONIZE" "#include + #include +" +if test "x$ac_cv_have_decl_ACL_SYNCHRONIZE" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_ACL_SYNCHRONIZE $ac_have_decl +_ACEOF + + if test "x$ac_cv_posix_acl_funcs" = "xyes" \ + -a "x$ac_cv_func_acl_get_fd_np" = "xyes" \ + -a "x$ac_cv_func_acl_get_perm" != "xyes" \ + -a "x$ac_cv_func_acl_get_perm_np" = "xyes" \ + -a "x$ac_cv_func_acl_set_fd_np" = "xyes"; then + if test "x$ac_cv_have_decl_ACL_USER" = "xyes"; then + if ${ac_cv_archive_acl_freebsd+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_archive_acl_freebsd=yes +fi + + if test "x$ac_cv_have_decl_ACL_TYPE_NFS4" = "xyes" \ + -a "x$ac_cv_func_acl_add_flag_np" = "xyes" \ + -a "x$ac_cv_func_acl_get_brand_np" = "xyes" \ + -a "x$ac_cv_func_acl_get_entry_type_np" = "xyes" \ + -a "x$ac_cv_func_acl_get_flagset_np" = "xyes" \ + -a "x$ac_cv_func_acl_set_entry_type_np" = "xyes"; then + if ${ac_cv_archive_acl_freebsd_nfs4+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_archive_acl_freebsd_nfs4=yes +fi + + fi + elif test "x$ac_cv_have_decl_ACL_TYPE_EXTENDED" = "xyes" \ + -a "x$ac_cv_func_acl_add_flag_np" = "xyes" \ + -a "x$ac_cv_func_acl_get_flagset_np" = "xyes" \ + -a "x$ac_cv_func_acl_get_link_np" = "xyes" \ + -a "x$ac_cv_func_acl_set_link_np" = "xyes" \ + -a "x$ac_cv_func_mbr_uid_to_uuid" = "xyes" \ + -a "x$ac_cv_func_mbr_uuid_to_id" = "xyes" \ + -a "x$ac_cv_func_mbr_gid_to_uuid" = "xyes"; then + if ${ac_cv_archive_acl_darwin+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_archive_acl_darwin=yes +fi + + fi + fi + fi + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ACL support" >&5 +$as_echo_n "checking for ACL support... " >&6; } + if test "x$ac_cv_archive_acl_libacl" = "xyes" \ + -a "x$ac_cv_archive_acl_librichacl" = "xyes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: libacl (POSIX.1e) + librichacl (NFSv4)" >&5 +$as_echo "libacl (POSIX.1e) + librichacl (NFSv4)" >&6; } + +$as_echo "#define ARCHIVE_ACL_LIBACL 1" >>confdefs.h + + +$as_echo "#define ARCHIVE_ACL_LIBRICHACL 1" >>confdefs.h + + elif test "x$ac_cv_archive_acl_libacl" = "xyes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: libacl (POSIX.1e)" >&5 +$as_echo "libacl (POSIX.1e)" >&6; } + +$as_echo "#define ARCHIVE_ACL_LIBACL 1" >>confdefs.h + + elif test "x$ac_cv_archive_acl_librichacl" = "xyes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: librichacl (NFSv4)" >&5 +$as_echo "librichacl (NFSv4)" >&6; } + +$as_echo "#define ARCHIVE_ACL_LIBRICHACL 1" >>confdefs.h + + elif test "x$ac_cv_archive_acl_darwin" = "xyes"; then + +$as_echo "#define ARCHIVE_ACL_DARWIN 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Darwin (limited NFSv4)" >&5 +$as_echo "Darwin (limited NFSv4)" >&6; } + elif test "x$ac_cv_archive_acl_sunos" = "xyes"; then + +$as_echo "#define ARCHIVE_ACL_SUNOS 1" >>confdefs.h + + if test "x$ac_cv_archive_acl_sunos_nfs4" = "xyes"; then + +$as_echo "#define ARCHIVE_ACL_SUNOS_NFS4 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Solaris (POSIX.1e and NFSv4)" >&5 +$as_echo "Solaris (POSIX.1e and NFSv4)" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Solaris (POSIX.1e)" >&5 +$as_echo "Solaris (POSIX.1e)" >&6; } + fi + elif test "x$ac_cv_archive_acl_freebsd" = "xyes"; then + +$as_echo "#define ARCHIVE_ACL_FREEBSD 1" >>confdefs.h + + if test "x$ac_cv_archive_acl_freebsd_nfs4" = "xyes"; then + +$as_echo "#define ARCHIVE_ACL_FREEBSD_NFS4 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: FreeBSD (POSIX.1e and NFSv4)" >&5 +$as_echo "FreeBSD (POSIX.1e and NFSv4)" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: FreeBSD (POSIX.1e)" >&5 +$as_echo "FreeBSD (POSIX.1e)" >&6; } + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } + fi +fi + + + if test "x$ac_cv_archive_acl_libacl" = "xyes" \ + -o "x$ac_cv_archive_acl_librichacl" = "xyes"; then + INC_LINUX_ACL_TRUE= + INC_LINUX_ACL_FALSE='#' +else + INC_LINUX_ACL_TRUE='#' + INC_LINUX_ACL_FALSE= +fi + + if test "x$ac_cv_archive_acl_sunos" = "xyes"; then + INC_SUNOS_ACL_TRUE= + INC_SUNOS_ACL_FALSE='#' +else + INC_SUNOS_ACL_TRUE='#' + INC_SUNOS_ACL_FALSE= +fi + + if test "x$ac_cv_archive_acl_darwin" = "xyes"; then + INC_DARWIN_ACL_TRUE= + INC_DARWIN_ACL_FALSE='#' +else + INC_DARWIN_ACL_TRUE='#' + INC_DARWIN_ACL_FALSE= +fi + + if test "x$ac_cv_archive_acl_freebsd" = "xyes"; then + INC_FREEBSD_ACL_TRUE= + INC_FREEBSD_ACL_FALSE='#' +else + INC_FREEBSD_ACL_TRUE='#' + INC_FREEBSD_ACL_FALSE= +fi + + +# Additional requirements +# Check whether --enable-largefile was given. +if test "${enable_largefile+set}" = set; then : + enableval=$enable_largefile; +fi + +if test "$enable_largefile" != no; then + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5 +$as_echo_n "checking for special C compiler options needed for large files... " >&6; } +if ${ac_cv_sys_largefile_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_sys_largefile_CC=no + if test "$GCC" != yes; then + ac_save_CC=$CC + while :; do + # IRIX 6.2 and later do not support large files by default, + # so use the C compiler's -n32 option if that helps. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF + if ac_fn_c_try_compile "$LINENO"; then : + break +fi +rm -f core conftest.err conftest.$ac_objext + CC="$CC -n32" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_largefile_CC=' -n32'; break +fi +rm -f core conftest.err conftest.$ac_objext + break + done + CC=$ac_save_CC + rm -f conftest.$ac_ext + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5 +$as_echo "$ac_cv_sys_largefile_CC" >&6; } + if test "$ac_cv_sys_largefile_CC" != no; then + CC=$CC$ac_cv_sys_largefile_CC + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 +$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } +if ${ac_cv_sys_file_offset_bits+:} false; then : + $as_echo_n "(cached) " >&6 +else + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_file_offset_bits=no; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _FILE_OFFSET_BITS 64 +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_file_offset_bits=64; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cv_sys_file_offset_bits=unknown + break +done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 +$as_echo "$ac_cv_sys_file_offset_bits" >&6; } +case $ac_cv_sys_file_offset_bits in #( + no | unknown) ;; + *) +cat >>confdefs.h <<_ACEOF +#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits +_ACEOF +;; +esac +rm -rf conftest* + if test $ac_cv_sys_file_offset_bits = unknown; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 +$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; } +if ${ac_cv_sys_large_files+:} false; then : + $as_echo_n "(cached) " >&6 +else + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_large_files=no; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _LARGE_FILES 1 +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_large_files=1; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cv_sys_large_files=unknown + break +done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 +$as_echo "$ac_cv_sys_large_files" >&6; } +case $ac_cv_sys_large_files in #( + no | unknown) ;; + *) +cat >>confdefs.h <<_ACEOF +#define _LARGE_FILES $ac_cv_sys_large_files +_ACEOF +;; +esac +rm -rf conftest* + fi + + +fi + + + + + + +case "$host_os" in + *mingw* | *cygwin* | *msys*) + ;; + *) + + if test "$found_MD5" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_MD5_LIBC" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_MD5_LIBC... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_MD5_COMPILE_TEST +#define ARCHIVE_CRYPTO_MD5_LIBC +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_md5_ctx ctx; + archive_md5_init(&ctx); + archive_md5_update(&ctx, *argv, argc); + archive_md5_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_MD5=yes + found_LIBC=yes + +$as_echo "#define ARCHIVE_CRYPTO_MD5_LIBC 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_MD5" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_MD5_LIBSYSTEM" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_MD5_LIBSYSTEM... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_MD5_COMPILE_TEST +#define ARCHIVE_CRYPTO_MD5_LIBSYSTEM +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_md5_ctx ctx; + archive_md5_init(&ctx); + archive_md5_update(&ctx, *argv, argc); + archive_md5_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_MD5=yes + found_LIBSYSTEM=yes + +$as_echo "#define ARCHIVE_CRYPTO_MD5_LIBSYSTEM 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_RMD160" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_RMD160_LIBC" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_RMD160_LIBC... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_RMD160_COMPILE_TEST +#define ARCHIVE_CRYPTO_RMD160_LIBC +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_rmd160_ctx ctx; + archive_rmd160_init(&ctx); + archive_rmd160_update(&ctx, *argv, argc); + archive_rmd160_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_RMD160=yes + found_LIBC=yes + +$as_echo "#define ARCHIVE_CRYPTO_RMD160_LIBC 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA1" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA1_LIBC" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA1_LIBC... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA1_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA1_LIBC +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha1_ctx ctx; + archive_sha1_init(&ctx); + archive_sha1_update(&ctx, *argv, argc); + archive_sha1_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA1=yes + found_LIBC=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA1_LIBC 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA1" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA1_LIBSYSTEM" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA1_LIBSYSTEM... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA1_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA1_LIBSYSTEM +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha1_ctx ctx; + archive_sha1_init(&ctx); + archive_sha1_update(&ctx, *argv, argc); + archive_sha1_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA1=yes + found_LIBSYSTEM=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA1_LIBSYSTEM 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA256" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA256_LIBC" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA256_LIBC... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA256_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA256_LIBC +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha256_ctx ctx; + archive_sha256_init(&ctx); + archive_sha256_update(&ctx, *argv, argc); + archive_sha256_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA256=yes + found_LIBC=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA256_LIBC 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA256" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA256_LIBC2" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA256_LIBC2... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA256_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA256_LIBC2 +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha256_ctx ctx; + archive_sha256_init(&ctx); + archive_sha256_update(&ctx, *argv, argc); + archive_sha256_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA256=yes + found_LIBC2=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA256_LIBC2 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA256" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA256_LIBC3" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA256_LIBC3... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA256_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA256_LIBC3 +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha256_ctx ctx; + archive_sha256_init(&ctx); + archive_sha256_update(&ctx, *argv, argc); + archive_sha256_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA256=yes + found_LIBC3=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA256_LIBC3 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA256" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA256_LIBSYSTEM" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA256_LIBSYSTEM... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA256_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA256_LIBSYSTEM +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha256_ctx ctx; + archive_sha256_init(&ctx); + archive_sha256_update(&ctx, *argv, argc); + archive_sha256_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA256=yes + found_LIBSYSTEM=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA256_LIBSYSTEM 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA384" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA384_LIBC" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA384_LIBC... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA384_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA384_LIBC +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha384_ctx ctx; + archive_sha384_init(&ctx); + archive_sha384_update(&ctx, *argv, argc); + archive_sha384_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA384=yes + found_LIBC=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA384_LIBC 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA384" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA384_LIBC2" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA384_LIBC2... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA384_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA384_LIBC2 +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha384_ctx ctx; + archive_sha384_init(&ctx); + archive_sha384_update(&ctx, *argv, argc); + archive_sha384_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA384=yes + found_LIBC2=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA384_LIBC2 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA384" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA384_LIBC3" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA384_LIBC3... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA384_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA384_LIBC3 +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha384_ctx ctx; + archive_sha384_init(&ctx); + archive_sha384_update(&ctx, *argv, argc); + archive_sha384_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA384=yes + found_LIBC3=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA384_LIBC3 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA384" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA384_LIBSYSTEM" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA384_LIBSYSTEM... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA384_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA384_LIBSYSTEM +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha384_ctx ctx; + archive_sha384_init(&ctx); + archive_sha384_update(&ctx, *argv, argc); + archive_sha384_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA384=yes + found_LIBSYSTEM=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA384_LIBSYSTEM 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA512" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA512_LIBC" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA512_LIBC... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA512_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA512_LIBC +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha512_ctx ctx; + archive_sha512_init(&ctx); + archive_sha512_update(&ctx, *argv, argc); + archive_sha512_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA512=yes + found_LIBC=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA512_LIBC 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA512" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA512_LIBC2" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA512_LIBC2... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA512_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA512_LIBC2 +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha512_ctx ctx; + archive_sha512_init(&ctx); + archive_sha512_update(&ctx, *argv, argc); + archive_sha512_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA512=yes + found_LIBC2=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA512_LIBC2 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA512" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA512_LIBC3" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA512_LIBC3... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA512_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA512_LIBC3 +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha512_ctx ctx; + archive_sha512_init(&ctx); + archive_sha512_update(&ctx, *argv, argc); + archive_sha512_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA512=yes + found_LIBC3=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA512_LIBC3 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA512" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA512_LIBSYSTEM" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA512_LIBSYSTEM... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA512_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA512_LIBSYSTEM +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha512_ctx ctx; + archive_sha512_init(&ctx); + archive_sha512_update(&ctx, *argv, argc); + archive_sha512_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA512=yes + found_LIBSYSTEM=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA512_LIBSYSTEM 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + ;; +esac + +if test "x$with_cng" != "xno"; then + for ac_header in bcrypt.h +do : + ac_fn_c_check_header_compile "$LINENO" "bcrypt.h" "ac_cv_header_bcrypt_h" "#ifdef HAVE_WINDOWS_H + # include + #endif + +" +if test "x$ac_cv_header_bcrypt_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_BCRYPT_H 1 +_ACEOF + + LIBS="$LIBS -lbcrypt" + +fi + +done + +fi + +if test "x$with_mbedtls" = "xyes"; then + for ac_header in mbedtls/aes.h mbedtls/md.h mbedtls/pkcs5.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + saved_LIBS=$LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mbedtls_sha1_init in -lmbedcrypto" >&5 +$as_echo_n "checking for mbedtls_sha1_init in -lmbedcrypto... " >&6; } +if ${ac_cv_lib_mbedcrypto_mbedtls_sha1_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lmbedcrypto $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char mbedtls_sha1_init (); +int +main () +{ +return mbedtls_sha1_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_mbedcrypto_mbedtls_sha1_init=yes +else + ac_cv_lib_mbedcrypto_mbedtls_sha1_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mbedcrypto_mbedtls_sha1_init" >&5 +$as_echo "$ac_cv_lib_mbedcrypto_mbedtls_sha1_init" >&6; } +if test "x$ac_cv_lib_mbedcrypto_mbedtls_sha1_init" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBMBEDCRYPTO 1 +_ACEOF + + LIBS="-lmbedcrypto $LIBS" + +fi + + + if test "$found_MD5" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_MD5_MBEDTLS" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_MD5_MBEDTLS... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_MD5_COMPILE_TEST +#define ARCHIVE_CRYPTO_MD5_MBEDTLS +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_md5_ctx ctx; + archive_md5_init(&ctx); + archive_md5_update(&ctx, *argv, argc); + archive_md5_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_MD5=yes + found_MBEDTLS=yes + +$as_echo "#define ARCHIVE_CRYPTO_MD5_MBEDTLS 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_RMD160" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_RMD160_MBEDTLS" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_RMD160_MBEDTLS... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_RMD160_COMPILE_TEST +#define ARCHIVE_CRYPTO_RMD160_MBEDTLS +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_rmd160_ctx ctx; + archive_rmd160_init(&ctx); + archive_rmd160_update(&ctx, *argv, argc); + archive_rmd160_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_RMD160=yes + found_MBEDTLS=yes + +$as_echo "#define ARCHIVE_CRYPTO_RMD160_MBEDTLS 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA1" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA1_MBEDTLS" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA1_MBEDTLS... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA1_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA1_MBEDTLS +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha1_ctx ctx; + archive_sha1_init(&ctx); + archive_sha1_update(&ctx, *argv, argc); + archive_sha1_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA1=yes + found_MBEDTLS=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA1_MBEDTLS 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA256" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA256_MBEDTLS" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA256_MBEDTLS... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA256_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA256_MBEDTLS +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha256_ctx ctx; + archive_sha256_init(&ctx); + archive_sha256_update(&ctx, *argv, argc); + archive_sha256_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA256=yes + found_MBEDTLS=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA256_MBEDTLS 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA384" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA384_MBEDTLS" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA384_MBEDTLS... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA384_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA384_MBEDTLS +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha384_ctx ctx; + archive_sha384_init(&ctx); + archive_sha384_update(&ctx, *argv, argc); + archive_sha384_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA384=yes + found_MBEDTLS=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA384_MBEDTLS 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA512" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA512_MBEDTLS" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA512_MBEDTLS... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA512_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA512_MBEDTLS +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha512_ctx ctx; + archive_sha512_init(&ctx); + archive_sha512_update(&ctx, *argv, argc); + archive_sha512_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA512=yes + found_MBEDTLS=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA512_MBEDTLS 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + if test "x$found_MBEDTLS" != "xyes"; then + LIBS=$saved_LIBS + fi +fi + +if test "x$with_nettle" = "xyes"; then + for ac_header in nettle/md5.h nettle/ripemd160.h nettle/sha.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + for ac_header in nettle/pbkdf2.h nettle/aes.h nettle/hmac.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + saved_LIBS=$LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nettle_sha1_init in -lnettle" >&5 +$as_echo_n "checking for nettle_sha1_init in -lnettle... " >&6; } +if ${ac_cv_lib_nettle_nettle_sha1_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnettle $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char nettle_sha1_init (); +int +main () +{ +return nettle_sha1_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_nettle_nettle_sha1_init=yes +else + ac_cv_lib_nettle_nettle_sha1_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nettle_nettle_sha1_init" >&5 +$as_echo "$ac_cv_lib_nettle_nettle_sha1_init" >&6; } +if test "x$ac_cv_lib_nettle_nettle_sha1_init" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBNETTLE 1 +_ACEOF + + LIBS="-lnettle $LIBS" + +fi + + + if test "$found_MD5" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_MD5_NETTLE" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_MD5_NETTLE... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_MD5_COMPILE_TEST +#define ARCHIVE_CRYPTO_MD5_NETTLE +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_md5_ctx ctx; + archive_md5_init(&ctx); + archive_md5_update(&ctx, *argv, argc); + archive_md5_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_MD5=yes + found_NETTLE=yes + +$as_echo "#define ARCHIVE_CRYPTO_MD5_NETTLE 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_RMD160" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_RMD160_NETTLE" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_RMD160_NETTLE... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_RMD160_COMPILE_TEST +#define ARCHIVE_CRYPTO_RMD160_NETTLE +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_rmd160_ctx ctx; + archive_rmd160_init(&ctx); + archive_rmd160_update(&ctx, *argv, argc); + archive_rmd160_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_RMD160=yes + found_NETTLE=yes + +$as_echo "#define ARCHIVE_CRYPTO_RMD160_NETTLE 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA1" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA1_NETTLE" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA1_NETTLE... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA1_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA1_NETTLE +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha1_ctx ctx; + archive_sha1_init(&ctx); + archive_sha1_update(&ctx, *argv, argc); + archive_sha1_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA1=yes + found_NETTLE=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA1_NETTLE 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA256" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA256_NETTLE" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA256_NETTLE... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA256_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA256_NETTLE +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha256_ctx ctx; + archive_sha256_init(&ctx); + archive_sha256_update(&ctx, *argv, argc); + archive_sha256_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA256=yes + found_NETTLE=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA256_NETTLE 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA384" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA384_NETTLE" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA384_NETTLE... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA384_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA384_NETTLE +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha384_ctx ctx; + archive_sha384_init(&ctx); + archive_sha384_update(&ctx, *argv, argc); + archive_sha384_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA384=yes + found_NETTLE=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA384_NETTLE 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA512" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA512_NETTLE" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA512_NETTLE... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA512_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA512_NETTLE +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha512_ctx ctx; + archive_sha512_init(&ctx); + archive_sha512_update(&ctx, *argv, argc); + archive_sha512_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA512=yes + found_NETTLE=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA512_NETTLE 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + if test "x$found_NETTLE" != "xyes"; then + LIBS=$saved_LIBS + fi +fi + +if test "x$with_openssl" != "xno"; then + for ac_header in openssl/evp.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "openssl/evp.h" "ac_cv_header_openssl_evp_h" "$ac_includes_default" +if test "x$ac_cv_header_openssl_evp_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OPENSSL_EVP_H 1 +_ACEOF + +fi + +done + + saved_LIBS=$LIBS + case "$host_os" in + *mingw* | *cygwin* | *msys*) + case "$host_cpu" in + x86_64) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OPENSSL_config in -leay64" >&5 +$as_echo_n "checking for OPENSSL_config in -leay64... " >&6; } +if ${ac_cv_lib_eay64_OPENSSL_config+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-leay64 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char OPENSSL_config (); +int +main () +{ +return OPENSSL_config (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_eay64_OPENSSL_config=yes +else + ac_cv_lib_eay64_OPENSSL_config=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_eay64_OPENSSL_config" >&5 +$as_echo "$ac_cv_lib_eay64_OPENSSL_config" >&6; } +if test "x$ac_cv_lib_eay64_OPENSSL_config" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBEAY64 1 +_ACEOF + + LIBS="-leay64 $LIBS" + +fi + + if test "x$ac_cv_lib_eay64_main" != "xyes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OPENSSL_config in -leay32" >&5 +$as_echo_n "checking for OPENSSL_config in -leay32... " >&6; } +if ${ac_cv_lib_eay32_OPENSSL_config+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-leay32 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char OPENSSL_config (); +int +main () +{ +return OPENSSL_config (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_eay32_OPENSSL_config=yes +else + ac_cv_lib_eay32_OPENSSL_config=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_eay32_OPENSSL_config" >&5 +$as_echo "$ac_cv_lib_eay32_OPENSSL_config" >&6; } +if test "x$ac_cv_lib_eay32_OPENSSL_config" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBEAY32 1 +_ACEOF + + LIBS="-leay32 $LIBS" + +fi + + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OPENSSL_config in -leay32" >&5 +$as_echo_n "checking for OPENSSL_config in -leay32... " >&6; } +if ${ac_cv_lib_eay32_OPENSSL_config+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-leay32 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char OPENSSL_config (); +int +main () +{ +return OPENSSL_config (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_eay32_OPENSSL_config=yes +else + ac_cv_lib_eay32_OPENSSL_config=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_eay32_OPENSSL_config" >&5 +$as_echo "$ac_cv_lib_eay32_OPENSSL_config" >&6; } +if test "x$ac_cv_lib_eay32_OPENSSL_config" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBEAY32 1 +_ACEOF + + LIBS="-leay32 $LIBS" + +fi + + ;; + esac + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OPENSSL_config in -lcrypto" >&5 +$as_echo_n "checking for OPENSSL_config in -lcrypto... " >&6; } +if ${ac_cv_lib_crypto_OPENSSL_config+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypto $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char OPENSSL_config (); +int +main () +{ +return OPENSSL_config (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_crypto_OPENSSL_config=yes +else + ac_cv_lib_crypto_OPENSSL_config=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_OPENSSL_config" >&5 +$as_echo "$ac_cv_lib_crypto_OPENSSL_config" >&6; } +if test "x$ac_cv_lib_crypto_OPENSSL_config" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBCRYPTO 1 +_ACEOF + + LIBS="-lcrypto $LIBS" + +fi + + ;; + esac + + if test "$found_MD5" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_MD5_OPENSSL" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_MD5_OPENSSL... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_MD5_COMPILE_TEST +#define ARCHIVE_CRYPTO_MD5_OPENSSL +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_md5_ctx ctx; + archive_md5_init(&ctx); + archive_md5_update(&ctx, *argv, argc); + archive_md5_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_MD5=yes + found_OPENSSL=yes + +$as_echo "#define ARCHIVE_CRYPTO_MD5_OPENSSL 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_RMD160" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_RMD160_OPENSSL" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_RMD160_OPENSSL... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_RMD160_COMPILE_TEST +#define ARCHIVE_CRYPTO_RMD160_OPENSSL +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_rmd160_ctx ctx; + archive_rmd160_init(&ctx); + archive_rmd160_update(&ctx, *argv, argc); + archive_rmd160_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_RMD160=yes + found_OPENSSL=yes + +$as_echo "#define ARCHIVE_CRYPTO_RMD160_OPENSSL 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA1" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA1_OPENSSL" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA1_OPENSSL... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA1_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA1_OPENSSL +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha1_ctx ctx; + archive_sha1_init(&ctx); + archive_sha1_update(&ctx, *argv, argc); + archive_sha1_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA1=yes + found_OPENSSL=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA1_OPENSSL 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA256" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA256_OPENSSL" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA256_OPENSSL... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA256_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA256_OPENSSL +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha256_ctx ctx; + archive_sha256_init(&ctx); + archive_sha256_update(&ctx, *argv, argc); + archive_sha256_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA256=yes + found_OPENSSL=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA256_OPENSSL 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA384" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA384_OPENSSL" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA384_OPENSSL... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA384_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA384_OPENSSL +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha384_ctx ctx; + archive_sha384_init(&ctx); + archive_sha384_update(&ctx, *argv, argc); + archive_sha384_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA384=yes + found_OPENSSL=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA384_OPENSSL 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA512" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA512_OPENSSL" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA512_OPENSSL... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA512_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA512_OPENSSL +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha512_ctx ctx; + archive_sha512_init(&ctx); + archive_sha512_update(&ctx, *argv, argc); + archive_sha512_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA512=yes + found_OPENSSL=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA512_OPENSSL 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + for ac_func in PKCS5_PBKDF2_HMAC_SHA1 +do : + ac_fn_c_check_func "$LINENO" "PKCS5_PBKDF2_HMAC_SHA1" "ac_cv_func_PKCS5_PBKDF2_HMAC_SHA1" +if test "x$ac_cv_func_PKCS5_PBKDF2_HMAC_SHA1" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PKCS5_PBKDF2_HMAC_SHA1 1 +_ACEOF + +fi +done + +fi + +# Probe libmd AFTER OpenSSL/libcrypto. +# The two are incompatible and OpenSSL is more complete. +for ac_header in md5.h ripemd.h sha.h sha256.h sha512.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +saved_LIBS=$LIBS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for MD5Init in -lmd" >&5 +$as_echo_n "checking for MD5Init in -lmd... " >&6; } +if ${ac_cv_lib_md_MD5Init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lmd $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char MD5Init (); +int +main () +{ +return MD5Init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_md_MD5Init=yes +else + ac_cv_lib_md_MD5Init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_md_MD5Init" >&5 +$as_echo "$ac_cv_lib_md_MD5Init" >&6; } +if test "x$ac_cv_lib_md_MD5Init" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBMD 1 +_ACEOF + + LIBS="-lmd $LIBS" + +fi + + + if test "$found_MD5" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_MD5_LIBMD" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_MD5_LIBMD... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_MD5_COMPILE_TEST +#define ARCHIVE_CRYPTO_MD5_LIBMD +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_md5_ctx ctx; + archive_md5_init(&ctx); + archive_md5_update(&ctx, *argv, argc); + archive_md5_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_MD5=yes + found_LIBMD=yes + +$as_echo "#define ARCHIVE_CRYPTO_MD5_LIBMD 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_RMD160" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_RMD160_LIBMD" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_RMD160_LIBMD... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_RMD160_COMPILE_TEST +#define ARCHIVE_CRYPTO_RMD160_LIBMD +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_rmd160_ctx ctx; + archive_rmd160_init(&ctx); + archive_rmd160_update(&ctx, *argv, argc); + archive_rmd160_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_RMD160=yes + found_LIBMD=yes + +$as_echo "#define ARCHIVE_CRYPTO_RMD160_LIBMD 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA1" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA1_LIBMD" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA1_LIBMD... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA1_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA1_LIBMD +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha1_ctx ctx; + archive_sha1_init(&ctx); + archive_sha1_update(&ctx, *argv, argc); + archive_sha1_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA1=yes + found_LIBMD=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA1_LIBMD 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA256" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA256_LIBMD" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA256_LIBMD... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA256_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA256_LIBMD +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha256_ctx ctx; + archive_sha256_init(&ctx); + archive_sha256_update(&ctx, *argv, argc); + archive_sha256_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA256=yes + found_LIBMD=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA256_LIBMD 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + + + if test "$found_SHA512" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA512_LIBMD" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA512_LIBMD... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA512_COMPILE_TEST +#define ARCHIVE_CRYPTO_SHA512_LIBMD +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_sha512_ctx ctx; + archive_sha512_init(&ctx); + archive_sha512_update(&ctx, *argv, argc); + archive_sha512_final(&ctx, NULL); + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA512=yes + found_LIBMD=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA512_LIBMD 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi + +if test "x$found_LIBMD" != "xyes"; then + LIBS=$saved_LIBS +fi + +case "$host_os" in + *mingw* | *cygwin* | *msys*) + + if test "$found_MD5" != yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_MD5_WIN" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_MD5_WIN... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_MD5_COMPILE_TEST +#include +#include + +int +main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + return (CALG_MD5); +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_MD5=yes + found_WIN=yes + +$as_echo "#define ARCHIVE_CRYPTO_MD5_WIN 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + fi + + + if test "$found_SHA1" != yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA1_WIN" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA1_WIN... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA1_COMPILE_TEST +#include +#include + +int +main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + return (CALG_SHA1); +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA1=yes + found_WIN=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA1_WIN 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + fi + + + if test "$found_SHA256" != yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA256_WIN" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA256_WIN... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA256_COMPILE_TEST +#include +#include + +int +main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + return (CALG_SHA_256); +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA256=yes + found_WIN=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA256_WIN 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + fi + + + if test "$found_SHA384" != yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA384_WIN" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA384_WIN... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA384_COMPILE_TEST +#include +#include + +int +main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + return (CALG_SHA_384); +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA384=yes + found_WIN=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA384_WIN 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + fi + + + if test "$found_SHA512" != yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for ARCHIVE_CRYPTO_SHA512_WIN" >&5 +$as_echo_n "checking support for ARCHIVE_CRYPTO_SHA512_WIN... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define ARCHIVE_SHA512_COMPILE_TEST +#include +#include + +int +main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + return (CALG_SHA_512); +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_SHA512=yes + found_WIN=yes + +$as_echo "#define ARCHIVE_CRYPTO_SHA512_WIN 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + fi + + ;; +esac + +# Ensure test directories are present if building out-of-tree +ac_config_commands="$ac_config_commands mkdirs" + + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 +$as_echo_n "checking that generated files are newer than configure... " >&6; } + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 +$as_echo "done" >&6; } + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then + as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${INC_WINDOWS_FILES_TRUE}" && test -z "${INC_WINDOWS_FILES_FALSE}"; then + as_fn_error $? "conditional \"INC_WINDOWS_FILES\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${INC_CYGWIN_FILES_TRUE}" && test -z "${INC_CYGWIN_FILES_FALSE}"; then + as_fn_error $? "conditional \"INC_CYGWIN_FILES\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_BSDTAR_TRUE}" && test -z "${BUILD_BSDTAR_FALSE}"; then + as_fn_error $? "conditional \"BUILD_BSDTAR\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${STATIC_BSDTAR_TRUE}" && test -z "${STATIC_BSDTAR_FALSE}"; then + as_fn_error $? "conditional \"STATIC_BSDTAR\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_BSDCAT_TRUE}" && test -z "${BUILD_BSDCAT_FALSE}"; then + as_fn_error $? "conditional \"BUILD_BSDCAT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${STATIC_BSDCAT_TRUE}" && test -z "${STATIC_BSDCAT_FALSE}"; then + as_fn_error $? "conditional \"STATIC_BSDCAT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_BSDCPIO_TRUE}" && test -z "${BUILD_BSDCPIO_FALSE}"; then + as_fn_error $? "conditional \"BUILD_BSDCPIO\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${STATIC_BSDCPIO_TRUE}" && test -z "${STATIC_BSDCPIO_FALSE}"; then + as_fn_error $? "conditional \"STATIC_BSDCPIO\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${INC_BLAKE2_TRUE}" && test -z "${INC_BLAKE2_FALSE}"; then + as_fn_error $? "conditional \"INC_BLAKE2\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${INC_LINUX_ACL_TRUE}" && test -z "${INC_LINUX_ACL_FALSE}"; then + as_fn_error $? "conditional \"INC_LINUX_ACL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${INC_SUNOS_ACL_TRUE}" && test -z "${INC_SUNOS_ACL_FALSE}"; then + as_fn_error $? "conditional \"INC_SUNOS_ACL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${INC_DARWIN_ACL_TRUE}" && test -z "${INC_DARWIN_ACL_FALSE}"; then + as_fn_error $? "conditional \"INC_DARWIN_ACL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${INC_FREEBSD_ACL_TRUE}" && test -z "${INC_FREEBSD_ACL_FALSE}"; then + as_fn_error $? "conditional \"INC_FREEBSD_ACL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by libarchive $as_me 3.4.2, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +libarchive config.status 3.4.2 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +AS='`$ECHO "$AS" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' +lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' +want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' +sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' +nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' +lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' +configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in AS \ +DLLTOOL \ +OBJDUMP \ +SHELL \ +ECHO \ +PATH_SEPARATOR \ +SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +deplibs_check_method \ +file_magic_cmd \ +file_magic_glob \ +want_nocaseglob \ +sharedlib_from_linklib_cmd \ +AR \ +AR_FLAGS \ +archiver_list_spec \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_import \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +lt_cv_nm_interface \ +nm_file_list_spec \ +lt_cv_truncate_bin \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_pic \ +lt_prog_compiler_wl \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +MANIFEST_TOOL \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_separator \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +install_override_mode \ +finish_eval \ +old_striplib \ +striplib; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postlink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +configure_time_dlsearch_path \ +configure_time_lt_sys_library_path; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +ac_aux_dir='$ac_aux_dir' + +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile' + + + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "build/pkgconfig/libarchive.pc") CONFIG_FILES="$CONFIG_FILES build/pkgconfig/libarchive.pc" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "mkdirs") CONFIG_COMMANDS="$CONFIG_COMMANDS mkdirs" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "$am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + "libtool":C) + + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +# The names of the tagged configurations supported by this script. +available_tags='' + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG + +# Assembler program. +AS=$lt_AS + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Object dumper program. +OBJDUMP=$lt_OBJDUMP + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# Shared archive member basename,for filename based shared library versioning on AIX. +shared_archive_member_spec=$shared_archive_member_spec + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + +# The PATH separator for the build system. +PATH_SEPARATOR=$lt_PATH_SEPARATOR + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# convert \$build file names to \$host format. +to_host_file_cmd=$lt_cv_to_host_file_cmd + +# convert \$build files to toolchain format. +to_tool_file_cmd=$lt_cv_to_tool_file_cmd + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method = "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob=$lt_file_magic_glob + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob=$lt_want_nocaseglob + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd + +# The archiver. +AR=$lt_AR + +# Flags to create an archive. +AR_FLAGS=$lt_AR_FLAGS + +# How to feed a file listing to the archiver. +archiver_list_spec=$lt_archiver_list_spec + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm into a list of symbols to manually relocate. +global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# The name lister interface. +nm_interface=$lt_lt_cv_nm_interface + +# Specify filename containing input files for \$NM. +nm_file_list_spec=$lt_nm_file_list_spec + +# The root where to search for dependent libraries,and where our libraries should be installed. +lt_sysroot=$lt_sysroot + +# Command to truncate a binary pipe. +lt_truncate_bin=$lt_lt_cv_truncate_bin + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Manifest tool. +MANIFEST_TOOL=$lt_MANIFEST_TOOL + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Detected run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path + +# Explicit LT_SYS_LIBRARY_PATH set during ./configure time. +configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \$shlibpath_var if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain=$ac_aux_dir/ltmain.sh + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + ;; + "mkdirs":C) mkdir -p libarchive/test tar/test cat/test cpio/test ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/dependencies/libarchive-3.4.2/configure.ac b/dependencies/libarchive-3.4.2/configure.ac new file mode 100644 index 0000000..2581087 --- /dev/null +++ b/dependencies/libarchive-3.4.2/configure.ac @@ -0,0 +1,1214 @@ +dnl Process this file with autoconf to produce a configure script. + +dnl First, define all of the version numbers up front. +dnl In particular, this allows the version macro to be used in AC_INIT + +dnl These first two version numbers are updated automatically on each release. +m4_define([LIBARCHIVE_VERSION_S],[3.4.2]) +m4_define([LIBARCHIVE_VERSION_N],[3004002]) + +dnl bsdtar and bsdcpio versioning tracks libarchive +m4_define([BSDTAR_VERSION_S],LIBARCHIVE_VERSION_S()) +m4_define([BSDCPIO_VERSION_S],LIBARCHIVE_VERSION_S()) +m4_define([BSDCAT_VERSION_S],LIBARCHIVE_VERSION_S()) + +AC_PREREQ([2.69]) + +# +# Now starts the "real" configure script. +# + +AC_INIT([libarchive],[LIBARCHIVE_VERSION_S()],[libarchive-discuss@googlegroups.com]) +# Make sure the srcdir contains "libarchive" directory +AC_CONFIG_SRCDIR([libarchive]) +# Use auxiliary subscripts from this subdirectory (cleans up root) +AC_CONFIG_AUX_DIR([build/autoconf]) +# M4 scripts +AC_CONFIG_MACRO_DIR([build/autoconf]) +# Must follow AC_CONFIG macros above... +AM_INIT_AUTOMAKE([1.11 dist-xz dist-zip]) +AM_MAINTAINER_MODE([enable]) +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +# Libtool's "interface version" can be computed from the libarchive version. + +# Libtool interface version bumps on any API change, so increments +# whenever libarchive minor version does. +ARCHIVE_MINOR=$(( (LIBARCHIVE_VERSION_N() / 1000) % 1000 )) +# Libarchive 2.7 == libtool interface 9 = 2 + 7 +# Libarchive 2.8 == libtool interface 10 = 2 + 8 +# Libarchive 2.9 == libtool interface 11 = 2 + 8 +# Libarchive 3.0 == libtool interface 12 +# Libarchive 3.1 == libtool interface 13 +ARCHIVE_INTERFACE=`echo $((13 + ${ARCHIVE_MINOR}))` +# Libarchive revision is bumped on any source change === libtool revision +ARCHIVE_REVISION=$(( LIBARCHIVE_VERSION_N() % 1000 )) +# Libarchive minor is bumped on any interface addition === libtool age +ARCHIVE_LIBTOOL_VERSION=$ARCHIVE_INTERFACE:$ARCHIVE_REVISION:$ARCHIVE_MINOR + +# Stick the version numbers into config.h +AC_DEFINE([LIBARCHIVE_VERSION_STRING],"LIBARCHIVE_VERSION_S()", + [Version number of libarchive]) +AC_DEFINE_UNQUOTED([LIBARCHIVE_VERSION_NUMBER],"LIBARCHIVE_VERSION_N()", + [Version number of libarchive as a single integer]) +AC_DEFINE([BSDCPIO_VERSION_STRING],"BSDCPIO_VERSION_S()", + [Version number of bsdcpio]) +AC_DEFINE([BSDTAR_VERSION_STRING],"BSDTAR_VERSION_S()", + [Version number of bsdtar]) +AC_DEFINE([BSDCAT_VERSION_STRING],"BSDTAR_VERSION_S()", + [Version number of bsdcat]) + +# The shell variables here must be the same as the AC_SUBST() variables +# below, but the shell variable names apparently cannot be the same as +# the m4 macro names above. Why? Ask autoconf. +BSDCPIO_VERSION_STRING=BSDCPIO_VERSION_S() +BSDTAR_VERSION_STRING=BSDTAR_VERSION_S() +BSDCAT_VERSION_STRING=BSDCAT_VERSION_S() +LIBARCHIVE_VERSION_STRING=LIBARCHIVE_VERSION_S() +LIBARCHIVE_VERSION_NUMBER=LIBARCHIVE_VERSION_N() + +# Substitute the above version numbers into the various files below. +# Yes, I believe this is the fourth time we define what are essentially +# the same symbols. Why? Ask autoconf. +AC_SUBST(ARCHIVE_LIBTOOL_VERSION) +AC_SUBST(BSDCPIO_VERSION_STRING) +AC_SUBST(BSDTAR_VERSION_STRING) +AC_SUBST(BSDCAT_VERSION_STRING) +AC_SUBST(LIBARCHIVE_VERSION_STRING) +AC_SUBST(LIBARCHIVE_VERSION_NUMBER) + +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_FILES([Makefile]) +AC_CONFIG_FILES([build/pkgconfig/libarchive.pc]) + +# Check for host type +AC_CANONICAL_HOST + +dnl Compilation on mingw and Cygwin needs special Makefile rules +inc_windows_files=no +inc_cygwin_files=no +case "$host_os" in + *mingw* ) inc_windows_files=yes ;; + *cygwin* | *msys*) inc_cygwin_files=yes ;; +esac +AM_CONDITIONAL([INC_WINDOWS_FILES], [test $inc_windows_files = yes]) +AM_CONDITIONAL([INC_CYGWIN_FILES], [test $inc_cygwin_files = yes]) + +dnl Defines that are required for specific platforms (e.g. -D_POSIX_SOURCE, etc) +PLATFORMCPPFLAGS= +case "$host_os" in + *mingw* ) PLATFORMCPPFLAGS=-D__USE_MINGW_ANSI_STDIO ;; +esac +AC_SUBST(PLATFORMCPPFLAGS) + +# Checks for programs. +AC_PROG_CC +AM_PROG_CC_C_O +AC_USE_SYSTEM_EXTENSIONS +AC_LIBTOOL_WIN32_DLL +AC_PROG_LIBTOOL +AC_CHECK_TOOL([STRIP],[strip]) +AC_PROG_MKDIR_P + +# +# Options for building bsdtar. +# +# Default is to build bsdtar, but allow people to override that. +# +AC_ARG_ENABLE([bsdtar], + [AS_HELP_STRING([--enable-bsdtar], [enable build of bsdtar (default)]) + AS_HELP_STRING([--enable-bsdtar=static], [force static build of bsdtar]) + AS_HELP_STRING([--enable-bsdtar=shared], [force dynamic build of bsdtar]) +AS_HELP_STRING([--disable-bsdtar], [disable build of bsdtar])], + [], [enable_bsdtar=yes]) + +case "$enable_bsdtar" in +yes) + if test "$enable_static" = "no"; then + static_bsdtar=no + else + static_bsdtar=yes + fi + build_bsdtar=yes + ;; +dynamic|shared) + if test "$enable_shared" = "no"; then + AC_MSG_FAILURE([Shared linking of bsdtar requires shared libarchive]) + fi + build_bsdtar=yes + static_bsdtar=no + ;; +static) + build_bsdtar=yes + static_bsdtar=yes + ;; +no) + build_bsdtar=no + static_bsdtar=no + ;; +*) + AC_MSG_FAILURE([Unsupported value for --enable-bsdtar]) + ;; +esac + +AM_CONDITIONAL([BUILD_BSDTAR], [ test "$build_bsdtar" = yes ]) +AM_CONDITIONAL([STATIC_BSDTAR], [ test "$static_bsdtar" = yes ]) + +# +# Options for building bsdcat. +# +# Default is to build bsdcat, but allow people to override that. +# +AC_ARG_ENABLE([bsdcat], + [AS_HELP_STRING([--enable-bsdcat], [enable build of bsdcat (default)]) + AS_HELP_STRING([--enable-bsdcat=static], [force static build of bsdcat]) + AS_HELP_STRING([--enable-bsdcat=shared], [force dynamic build of bsdcat]) +AS_HELP_STRING([--disable-bsdcat], [disable build of bsdcat])], + [], [enable_bsdcat=yes]) + +case "$enable_bsdcat" in +yes) + if test "$enable_static" = "no"; then + static_bsdcat=no + else + static_bsdcat=yes + fi + build_bsdcat=yes + ;; +dynamic|shared) + if test "$enable_shared" = "no"; then + AC_MSG_FAILURE([Shared linking of bsdcat requires shared libarchive]) + fi + build_bsdcat=yes + static_bsdcat=no + ;; +static) + build_bsdcat=yes + static_bsdcat=yes + ;; +no) + build_bsdcat=no + static_bsdcat=no + ;; +*) + AC_MSG_FAILURE([Unsupported value for --enable-bsdcat]) + ;; +esac + +AM_CONDITIONAL([BUILD_BSDCAT], [ test "$build_bsdcat" = yes ]) +AM_CONDITIONAL([STATIC_BSDCAT], [ test "$static_bsdcat" = yes ]) + +# +# Options for building bsdcpio. +# +# Default is not to build bsdcpio, but that can be overridden. +# +AC_ARG_ENABLE([bsdcpio], + [AS_HELP_STRING([--enable-bsdcpio], [enable build of bsdcpio (default)]) + AS_HELP_STRING([--enable-bsdcpio=static], [static build of bsdcpio]) + AS_HELP_STRING([--enable-bsdcpio=shared], [dynamic build of bsdcpio]) +AS_HELP_STRING([--disable-bsdcpio], [disable build of bsdcpio])], + [], [enable_bsdcpio=yes]) + +case "$enable_bsdcpio" in +yes) + if test "$enable_static" = "no"; then + static_bsdcpio=no + else + static_bsdcpio=yes + fi + build_bsdcpio=yes + ;; +dynamic|shared) + if test "$enabled_shared" = "no"; then + AC_MSG_FAILURE([Shared linking of bsdcpio requires shared libarchive]) + fi + build_bsdcpio=yes + ;; +static) + build_bsdcpio=yes + static_bsdcpio=yes + ;; +no) + build_bsdcpio=no + static_bsdcpio=no + ;; +*) + AC_MSG_FAILURE([Unsupported value for --enable-bsdcpio]) + ;; +esac + +AM_CONDITIONAL([BUILD_BSDCPIO], [ test "$build_bsdcpio" = yes ]) +AM_CONDITIONAL([STATIC_BSDCPIO], [ test "$static_bsdcpio" = yes ]) + +# Set up defines needed before including any headers +case $host in + *mingw* | *cygwin* | *msys* ) + AC_DEFINE([_WIN32_WINNT], 0x0502, [Define to '0x0502' for Windows Server 2003 APIs.]) + AC_DEFINE([WINVER], 0x0502, [Define to '0x0502' for Windows Server 2003 APIs.]) + AC_DEFINE([NTDDI_VERSION], 0x05020000, [Define to '0x05020000' for Windows Server 2003 APIs.]) + ;; +esac + +# Checks for header files. +AC_HEADER_DIRENT +AC_HEADER_SYS_WAIT +AC_CHECK_HEADERS([acl/libacl.h attr/xattr.h]) +AC_CHECK_HEADERS([copyfile.h ctype.h]) +AC_CHECK_HEADERS([errno.h ext2fs/ext2_fs.h fcntl.h grp.h]) + +AC_CACHE_CHECK([whether EXT2_IOC_GETFLAGS is usable], + [ac_cv_have_decl_EXT2_IOC_GETFLAGS], + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([@%:@include +@%:@include ], + [int x = EXT2_IOC_GETFLAGS])], + [AS_VAR_SET([ac_cv_have_decl_EXT2_IOC_GETFLAGS], [yes])], + [AS_VAR_SET([ac_cv_have_decl_EXT2_IOC_GETFLAGS], [no])])]) + +AS_VAR_IF([ac_cv_have_decl_EXT2_IOC_GETFLAGS], [yes], + [AC_DEFINE_UNQUOTED([HAVE_WORKING_EXT2_IOC_GETFLAGS], [1], + [Define to 1 if you have a working EXT2_IOC_GETFLAGS])]) + +AC_CHECK_HEADERS([inttypes.h io.h langinfo.h limits.h]) +AC_CHECK_HEADERS([linux/fiemap.h linux/fs.h linux/magic.h linux/types.h]) + +AC_CACHE_CHECK([whether FS_IOC_GETFLAGS is usable], + [ac_cv_have_decl_FS_IOC_GETFLAGS], + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([@%:@include +@%:@include ], + [int x = FS_IOC_GETFLAGS])], + [AS_VAR_SET([ac_cv_have_decl_FS_IOC_GETFLAGS], [yes])], + [AS_VAR_SET([ac_cv_have_decl_FS_IOC_GETFLAGS], [no])])]) + +AS_VAR_IF([ac_cv_have_decl_FS_IOC_GETFLAGS], [yes], + [AC_DEFINE_UNQUOTED([HAVE_WORKING_FS_IOC_GETFLAGS], [1], + [Define to 1 if you have a working FS_IOC_GETFLAGS])]) + +AC_CHECK_HEADERS([locale.h membership.h paths.h poll.h pthread.h pwd.h]) +AC_CHECK_HEADERS([readpassphrase.h signal.h spawn.h]) +AC_CHECK_HEADERS([stdarg.h stdint.h stdlib.h string.h]) +AC_CHECK_HEADERS([sys/acl.h sys/cdefs.h sys/ea.h sys/extattr.h]) +AC_CHECK_HEADERS([sys/ioctl.h sys/mkdev.h sys/mount.h]) +AC_CHECK_HEADERS([sys/param.h sys/poll.h sys/richacl.h]) +AC_CHECK_HEADERS([sys/select.h sys/statfs.h sys/statvfs.h sys/sysmacros.h]) +AC_CHECK_HEADERS([sys/time.h sys/utime.h sys/utsname.h sys/vfs.h sys/xattr.h]) +AC_CHECK_HEADERS([time.h unistd.h utime.h wchar.h wctype.h]) +AC_CHECK_HEADERS([windows.h]) +# check windows.h first; the other headers require it. +AC_CHECK_HEADERS([wincrypt.h winioctl.h],[],[], +[[#ifdef HAVE_WINDOWS_H +# include +#endif +]]) + +# Checks for libraries. +AC_ARG_WITH([zlib], + AS_HELP_STRING([--without-zlib], [Don't build support for gzip through zlib])) + +if test "x$with_zlib" != "xno"; then + AC_CHECK_HEADERS([zlib.h]) + AC_CHECK_LIB(z,inflate) +fi + +AC_ARG_WITH([bz2lib], + AS_HELP_STRING([--without-bz2lib], [Don't build support for bzip2 through bz2lib])) + +if test "x$with_bz2lib" != "xno"; then + AC_CHECK_HEADERS([bzlib.h]) + case "$host_os" in + *mingw* | *cygwin* | *msys*) + dnl AC_CHECK_LIB cannot be used on the Windows port of libbz2, therefore + dnl use AC_LINK_IFELSE. + AC_MSG_CHECKING([for BZ2_bzDecompressInit in -lbz2]) + old_LIBS="$LIBS" + LIBS="-lbz2 $LIBS" + AC_LINK_IFELSE( + [AC_LANG_SOURCE(#include + int main() { return BZ2_bzDecompressInit(NULL, 0, 0); })], + [ac_cv_lib_bz2_BZ2_bzDecompressInit=yes], + [ac_cv_lib_bz2_BZ2_bzDecompressInit=no]) + LIBS="$old_LIBS" + AC_MSG_RESULT($ac_cv_lib_bz2_BZ2_bzDecompressInit) + if test "x$ac_cv_lib_bz2_BZ2_bzDecompressInit" = xyes; then + AC_DEFINE([HAVE_LIBBZ2], [1], [Define to 1 if you have the `bz2' library (-lbz2).]) + LIBS="-lbz2 $LIBS" + fi + ;; + *) + AC_CHECK_LIB(bz2,BZ2_bzDecompressInit) + ;; + esac +fi + +AC_ARG_WITH([libb2], + AS_HELP_STRING([--without-libb2], [Don't build support for BLAKE2 through libb2])) + +if test "x$with_libb2" != "xno"; then + AC_CHECK_HEADERS([blake2.h]) + AC_CHECK_LIB(b2,blake2sp_init) +fi + +AM_CONDITIONAL([INC_BLAKE2], [test "x$ac_cv_lib_b2_blake2sp_init" != "xyes"]) + +AC_ARG_WITH([iconv], + AS_HELP_STRING([--without-iconv], [Don't try to link against iconv])) + +if test "x$with_iconv" != "xno"; then + AM_ICONV + AC_CHECK_HEADERS([iconv.h],[],[],[#include ]) + if test "x$am_cv_func_iconv" = "xyes"; then + AC_CHECK_HEADERS([localcharset.h]) + am_save_LIBS="$LIBS" + LIBS="${LIBS} ${LIBICONV}" + AC_CHECK_FUNCS([locale_charset]) + LIBS="${am_save_LIBS}" + if test "x$ac_cv_func_locale_charset" != "xyes"; then + # If locale_charset() is not in libiconv, we have to find libcharset. + AC_CHECK_LIB(charset,locale_charset) + fi + fi +fi + +AC_ARG_WITH([lz4], + AS_HELP_STRING([--without-lz4], [Don't build support for lz4 through liblz4])) + +if test "x$with_lz4" != "xno"; then + AC_CHECK_HEADERS([lz4.h lz4hc.h]) + AC_CHECK_LIB(lz4,LZ4_decompress_safe) +fi + +AC_ARG_WITH([zstd], + AS_HELP_STRING([--without-zstd], [Don't build support for zstd through libzstd])) + +if test "x$with_zstd" != "xno"; then + AC_CHECK_HEADERS([zstd.h]) + AC_CHECK_LIB(zstd,ZSTD_compressStream) +fi + +AC_ARG_WITH([lzma], + AS_HELP_STRING([--without-lzma], [Don't build support for xz through lzma])) + +if test "x$with_lzma" != "xno"; then + AC_CHECK_HEADERS([lzma.h]) + AC_CHECK_LIB(lzma,lzma_stream_decoder) + # Some pre-release (but widely distributed) versions of liblzma + # included a disabled version of lzma_stream_encoder_mt that + # fools a naive AC_CHECK_LIB or AC_CHECK_FUNC, so we need + # to do something more complex here: + AC_CACHE_CHECK( + [whether we have multithread support in lzma], + ac_cv_lzma_has_mt, + [AC_LINK_IFELSE([ + AC_LANG_PROGRAM([[#include ] + [#if LZMA_VERSION < 50020000] + [#error unsupported] + [#endif]], + [[lzma_stream_encoder_mt(0, 0);]])], + [ac_cv_lzma_has_mt=yes], [ac_cv_lzma_has_mt=no])]) + if test "x$ac_cv_lzma_has_mt" != xno; then + AC_DEFINE([HAVE_LZMA_STREAM_ENCODER_MT], [1], [Define to 1 if you have the `lzma_stream_encoder_mt' function.]) + fi +fi + +AC_ARG_WITH([lzo2], + AS_HELP_STRING([--with-lzo2], [Build with LZO support from liblzo2])) + +if test "x$with_lzo2" = "xyes"; then + AC_CHECK_HEADERS([lzo/lzoconf.h lzo/lzo1x.h]) + AC_CHECK_LIB(lzo2,lzo1x_decompress_safe) +fi + +AC_ARG_WITH([cng], + AS_HELP_STRING([--without-cng], [Don't build support of CNG(Crypto Next Generation)])) + +AC_ARG_WITH([mbedtls], + AS_HELP_STRING([--with-mbedtls], [Build with crypto support from mbed TLS])) +AC_ARG_WITH([nettle], + AS_HELP_STRING([--with-nettle], [Build with crypto support from Nettle])) +AC_ARG_WITH([openssl], + AS_HELP_STRING([--without-openssl], [Don't build support for mtree and xar hashes through openssl])) +case "$host_os" in + *darwin* ) with_openssl=no ;; +esac + +AC_ARG_WITH([xml2], + AS_HELP_STRING([--without-xml2], [Don't build support for xar through libxml2])) +AC_ARG_WITH([expat], + AS_HELP_STRING([--without-expat], [Don't build support for xar through expat])) + +if test "x$with_xml2" != "xno"; then + PKG_PROG_PKG_CONFIG + PKG_CHECK_MODULES(LIBXML2_PC, [libxml-2.0], [ + CPPFLAGS="${CPPFLAGS} ${LIBXML2_PC_CFLAGS}" + LIBS="${LIBS} ${LIBXML2_PC_LIBS}" + AC_CHECK_LIB(xml2,xmlInitParser,[true],AC_MSG_FAILURE(Missing xml2 library)) + ], [ + AC_CHECK_LIB(xml2,xmlInitParser) + ]) + AC_CHECK_HEADERS([libxml/xmlreader.h libxml/xmlwriter.h]) +fi +if test "x$ac_cv_header_libxml_xmlreader_h" != "xyes"; then + if test "x$with_expat" != "xno"; then + AC_CHECK_HEADERS([expat.h]) + AC_CHECK_LIB(expat,XML_ParserCreate) + fi +fi + +AC_ARG_ENABLE([posix-regex-lib], + [AS_HELP_STRING([--enable-posix-regex-lib], + [choose what library to use for POSIX regular expression support (default: auto)]) + AS_HELP_STRING([--enable-posix-regex-lib=libc], [use libc POSIX regular expression support]) + AS_HELP_STRING([--enable-posix-regex-lib=libregex], [use libregex POSIX regular expression support]) + AS_HELP_STRING([--enable-posix-regex-lib=libpcreposix], [use libpcreposix POSIX regular expression support]) + AS_HELP_STRING([--disable-posix-regex-lib], [don't enable POSIX regular expression support])], + [], [enable_posix_regex_lib=auto]) + +posix_regex_lib_found= +if test "$enable_posix_regex_lib" = "auto" || test "$enable_posix_regex_lib" = "libc" || test "$enable_posix_regex_lib" = "libregex"; then + AC_CHECK_HEADERS([regex.h]) + if test "x$ac_cv_header_regex_h" != "xno"; then + AC_CHECK_FUNC(regcomp) + if test "x$ac_cv_func_regcomp" = xyes; then + posix_regex_lib_found=1 + else + AC_CHECK_LIB(regex,regcomp) + if test "x$ac_cv_lib_regex_regcomp" = xyes; then + posix_regex_lib_found=1 + fi + fi + fi +fi +if test -z $posix_regex_lib_found && (test "$enable_posix_regex_lib" = "auto" || test "$enable_posix_regex_lib" = "libpcreposix"); then + AC_CHECK_HEADERS([pcreposix.h]) + AC_CHECK_LIB(pcreposix,regcomp) + if test "x$ac_cv_lib_pcreposix_regcomp" != xyes; then + AC_MSG_NOTICE(trying libpcreposix check again with libpcre) + unset ac_cv_lib_pcreposix_regcomp + AC_CHECK_LIB(pcre,pcre_exec) + AC_CHECK_LIB(pcreposix,regcomp) + if test "x$ac_cv_lib_pcre_pcre_exec" = xyes && test "x$ac_cv_lib_pcreposix_regcomp" = xyes; then + AC_MSG_CHECKING(if PCRE_STATIC needs to be defined) + AC_LINK_IFELSE( + [AC_LANG_SOURCE(#include + int main() { return regcomp(NULL, NULL, 0); })], + [without_pcre_static=yes], + [without_pcre_static=no]) + AC_LINK_IFELSE( + [AC_LANG_SOURCE(#define PCRE_STATIC + #include + int main() { return regcomp(NULL, NULL, 0); })], + [with_pcre_static=yes], + [with_pcre_static=no]) + if test "x$without_pcre_static" != xyes && test "x$with_pcre_static" = xyes; then + AC_MSG_RESULT(yes) + AC_DEFINE([PCRE_STATIC], [1], [Define to 1 if PCRE_STATIC needs to be defined.]) + elif test "x$without_pcre_static" = xyes || test "x$with_pcre_static" = xyes; then + AC_MSG_RESULT(no) + fi + posix_regex_lib_found=1 + fi + else + posix_regex_lib_found=1 + fi +fi + +# TODO: Give the user the option of using a pre-existing system +# libarchive. This will define HAVE_LIBARCHIVE which will cause +# bsdtar_platform.h to use #include <...> for the libarchive headers. +# Need to include Makefile.am magic to link against system +# -larchive in that case. +#AC_CHECK_LIB(archive,archive_version) + +# Checks for supported compiler flags +AX_APPEND_COMPILE_FLAGS([-Wall -Wformat -Wformat-security]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +# la_TYPE_UID_T defaults to "int", which is incorrect for MinGW +# and MSVC. Use a customized version. +la_TYPE_UID_T +AC_TYPE_MODE_T +# AC_TYPE_OFF_T defaults to "long", which limits us to 4GB files on +# most systems... default to "long long" instead. +AC_CHECK_TYPE(off_t, [long long]) +AC_TYPE_SIZE_T +AC_CHECK_TYPE(id_t, [unsigned long]) +AC_CHECK_TYPE(uintptr_t, [unsigned int]) + +# Check for tm_gmtoff in struct tm +AC_CHECK_MEMBERS([struct tm.tm_gmtoff, struct tm.__tm_gmtoff],,, +[ +#include +]) + +# Check for f_namemax in struct statfs +AC_CHECK_MEMBERS([struct statfs.f_namemax],,, +[ +#include +#include +]) + +# Check for f_iosize in struct statvfs +AC_CHECK_MEMBERS([struct statvfs.f_iosize],,, +[ +#include +]) + +# Check for birthtime in struct stat +AC_CHECK_MEMBERS([struct stat.st_birthtime]) + +# Check for high-resolution timestamps in struct stat +AC_CHECK_MEMBERS([struct stat.st_birthtimespec.tv_nsec]) +AC_CHECK_MEMBERS([struct stat.st_mtimespec.tv_nsec]) +AC_CHECK_MEMBERS([struct stat.st_mtim.tv_nsec]) +AC_CHECK_MEMBERS([struct stat.st_mtime_n]) # AIX +AC_CHECK_MEMBERS([struct stat.st_umtime]) # Tru64 +AC_CHECK_MEMBERS([struct stat.st_mtime_usec]) # Hurd +# Check for block size support in struct stat +AC_CHECK_MEMBERS([struct stat.st_blksize]) +# Check for st_flags in struct stat (BSD fflags) +AC_CHECK_MEMBERS([struct stat.st_flags]) + +# If you have uintmax_t, we assume printf supports %ju +# If you have unsigned long long, we assume printf supports %llu +# TODO: Check for %ju and %llu support directly. +AC_CHECK_TYPES([uintmax_t, unsigned long long]) + +# We use C99-style integer types +# Declare them if the local platform doesn't already do so. +AC_TYPE_INTMAX_T +AC_TYPE_UINTMAX_T +AC_TYPE_INT64_T +AC_TYPE_UINT64_T +AC_TYPE_INT32_T +AC_TYPE_UINT32_T +AC_TYPE_INT16_T +AC_TYPE_UINT16_T +AC_TYPE_UINT8_T + +AC_CHECK_DECLS([SIZE_MAX, INT32_MAX, INT32_MIN]) +AC_CHECK_DECLS([INT64_MAX, INT64_MIN, UINT64_MAX, UINT32_MAX]) +AC_CHECK_DECLS([INTMAX_MAX, INTMAX_MIN, UINTMAX_MAX]) + +AC_CHECK_DECL([SSIZE_MAX], + [AC_DEFINE(HAVE_DECL_SSIZE_MAX, 1, [Define to 1 if you have the declaration of `SSIZE_MAX', and to 0 if you don't.])], + [], + [#include ]) + +AC_CHECK_DECL([EFTYPE], + [AC_DEFINE(HAVE_EFTYPE, 1, [A possible errno value for invalid file format errors])], + [], + [#include ]) +AC_CHECK_DECL([EILSEQ], + [AC_DEFINE(HAVE_EILSEQ, 1, [A possible errno value for invalid file format errors])], + [], + [#include ]) +AC_CHECK_TYPE([wchar_t], + [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_[]wchar_t), 1, [Define to 1 if the system has the type `wchar_t'.])dnl + AC_CHECK_SIZEOF([wchar_t])], + []) + +AC_HEADER_TIME + +# Checks for library functions. +AC_PROG_GCC_TRADITIONAL +AC_HEADER_MAJOR +AC_FUNC_FSEEKO +AC_FUNC_MEMCMP +AC_FUNC_LSTAT +AC_FUNC_STAT +AC_FUNC_STRERROR_R +AC_FUNC_STRFTIME +AC_FUNC_VPRINTF +# check for: +# CreateHardLinkA(LPCSTR, LPCSTR, LPSECURITY_ATTRIBUTES) +# To avoid necessity for including windows.h or special forward declaration +# workarounds, we use 'void *' for 'struct SECURITY_ATTRIBUTES *' +AC_CHECK_STDCALL_FUNC([CreateHardLinkA],[const char *, const char *, void *]) +AC_CHECK_FUNCS([arc4random_buf chflags chown chroot ctime_r]) +AC_CHECK_FUNCS([fchdir fchflags fchmod fchown fcntl fdopendir fork]) +AC_CHECK_FUNCS([fstat fstatat fstatfs fstatvfs ftruncate]) +AC_CHECK_FUNCS([futimens futimes futimesat]) +AC_CHECK_FUNCS([geteuid getpid getgrgid_r getgrnam_r]) +AC_CHECK_FUNCS([getpwnam_r getpwuid_r getvfsbyname gmtime_r]) +AC_CHECK_FUNCS([lchflags lchmod lchown link localtime_r lstat lutimes]) +AC_CHECK_FUNCS([mbrtowc memmove memset]) +AC_CHECK_FUNCS([mkdir mkfifo mknod mkstemp]) +AC_CHECK_FUNCS([nl_langinfo openat pipe poll posix_spawnp readlink readlinkat]) +AC_CHECK_FUNCS([readpassphrase]) +AC_CHECK_FUNCS([select setenv setlocale sigaction statfs statvfs]) +AC_CHECK_FUNCS([strchr strdup strerror strncpy_s strrchr symlink timegm]) +AC_CHECK_FUNCS([tzset unlinkat unsetenv utime utimensat utimes vfork]) +AC_CHECK_FUNCS([wcrtomb wcscmp wcscpy wcslen wctomb wmemcmp wmemcpy wmemmove]) +AC_CHECK_FUNCS([_ctime64_s _fseeki64]) +AC_CHECK_FUNCS([_get_timezone _gmtime64_s _localtime64_s _mkgmtime64]) +# detects cygwin-1.7, as opposed to older versions +AC_CHECK_FUNCS([cygwin_conv_path]) + +# DragonFly uses vfsconf, FreeBSD xvfsconf. +AC_CHECK_TYPES(struct vfsconf,,, + [#if HAVE_SYS_TYPES_H + #include + #endif + #include + ]) + +AC_CHECK_TYPES(struct xvfsconf,,, + [#if HAVE_SYS_TYPES_H + #include + #endif + #include + ]) + +# There are several variants of readdir_r around; we only +# accept the POSIX-compliant version. +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[#include ]], + [[DIR *dir; struct dirent e, *r; + return(readdir_r(dir, &e, &r));]])], + [AC_DEFINE(HAVE_READDIR_R,1,[Define to 1 if you have a POSIX compatible readdir_r])] +) +# dirfd can be either a function or a macro. +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[#include + DIR *dir;]], + [[return(dirfd(dir));]])], + [AC_DEFINE(HAVE_DIRFD,1,[Define to 1 if you have a dirfd function or macro])] +) + +# FreeBSD's nl_langinfo supports an option to specify whether the +# current locale uses month/day or day/month ordering. It makes the +# output a little prettier... +AC_CHECK_DECL([D_MD_ORDER], +[AC_DEFINE(HAVE_D_MD_ORDER, 1, [Define to 1 if nl_langinfo supports D_MD_ORDER])], +[], +[#if HAVE_LANGINFO_H +#include +#endif +]) + +# Check for dirent.d_namlen field explicitly +# (This is a bit more straightforward than, if not quite as portable as, +# the recipe given by the autoconf maintainers.) +AC_CHECK_MEMBER(struct dirent.d_namlen,,, +[#if HAVE_DIRENT_H +#include +#endif +]) + +# Check for Extended Attributes support +AC_ARG_ENABLE([xattr], + AS_HELP_STRING([--disable-xattr], + [Disable Extended Attributes support (default: check)])) + +if test "x$enable_xattr" != "xno"; then + AC_SEARCH_LIBS([setxattr], [attr gnu]) + AC_CHECK_DECLS([EXTATTR_NAMESPACE_USER], [], [], [#include +#include +]) + AC_CHECK_DECLS([XATTR_NOFOLLOW], [], [], [#include +]) + if test "x$ac_cv_header_sys_xattr_h" = "xyes" \ + -a "x$ac_cv_have_decl_XATTR_NOFOLLOW" = "xyes"; then + # Darwin extended attributes support + AC_CACHE_VAL([ac_cv_archive_xattr_darwin], + [AC_CHECK_FUNCS(fgetxattr \ + flistxattr \ + fsetxattr \ + getxattr \ + listxattr \ + setxattr, + [ac_cv_archive_xattr_darwin=yes], + [ac_cv_archive_xattr_darwin=no], + [#include +]) + ] + ) + elif test "x$ac_cv_header_sys_extattr_h" = "xyes" \ + -a "x$ac_cv_have_decl_EXTATTR_NAMESPACE_USER" = "xyes"; then + # FreeBSD extended attributes support + AC_CACHE_VAL([ac_cv_archive_xattr_freebsd], + [AC_CHECK_FUNCS(extattr_get_fd \ + extattr_get_file \ + extattr_get_link \ + extattr_list_fd \ + extattr_list_file \ + extattr_list_link \ + extattr_set_fd \ + extattr_set_link, + [ac_cv_archive_xattr_freebsd=yes], + [ac_cv_archive_xattr_freebsd=no], + [#include +#include +]) + ] + ) + elif test "x$ac_cv_header_sys_xattr_h" = "xyes" \ + -o "x$ac_cv_header_attr_xattr_h" = "xyes"; then + # Linux extended attributes support + AC_CACHE_VAL([ac_cv_archive_xattr_linux], + [AC_CHECK_FUNCS(fgetxattr \ + flistxattr \ + fsetxattr \ + getxattr \ + lgetxattr \ + listxattr \ + llistxattr \ + lsetxattr, + [ac_cv_archive_xattr_linux=yes], + [ac_cv_archive_xattr_linux=no], + [#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_SYS_XATTR_H +#include +#endif +#if HAVE_ATTR_XATTR_H +#include +#endif +]) + ] + ) + elif test "x$ac_cv_header_sys_ea_h" = "xyes"; then + # AIX extended attributes support + AC_CACHE_VAL([ac_cv_archive_xattr_aix], + [AC_CHECK_FUNCS(fgetea \ + flistea \ + fsetea \ + getea \ + lgetea \ + listea \ + llistea \ + lsetea, + [ac_cv_archive_xattr_aix=yes], + [ac_cv_archive_xattr_aix=no], + [#include +]) + ] + ) + fi + + AC_MSG_CHECKING([for extended attributes support]) + if test "x$ac_cv_archive_xattr_linux" = "xyes"; then + AC_DEFINE([ARCHIVE_XATTR_LINUX], [1], [Linux xattr support]) + AC_MSG_RESULT([Linux]) + elif test "x$ac_cv_archive_xattr_darwin" = "xyes"; then + AC_DEFINE([ARCHIVE_XATTR_DARWIN], [1], [Darwin xattr support]) + AC_MSG_RESULT([Darwin]) + elif test "x$ac_cv_archive_xattr_freebsd" = "xyes"; then + AC_DEFINE([ARCHIVE_XATTR_FREEBSD], [1], [FreeBSD xattr support]) + AC_MSG_RESULT([FreeBSD]) + elif test "x$ac_cv_archive_xattr_aix" = "xyes"; then + AC_DEFINE([ARCHIVE_XATTR_AIX], [1], [AIX xattr support]) + AC_MSG_RESULT([AIX]) + else + AC_MSG_RESULT([none]) + fi +fi + +# Check for ACL support +# +# The ACL support in libarchive is written against the POSIX1e draft, +# which was never officially approved and varies quite a bit across +# platforms. Worse, some systems have completely non-POSIX acl functions, +# which makes the following checks rather more complex than I would like. +# +AC_ARG_ENABLE([acl], + AS_HELP_STRING([--disable-acl], + [Disable ACL support (default: check)])) + +if test "x$enable_acl" != "xno"; then + # Libacl + AC_CHECK_LIB([acl], [acl_get_file]) + + AC_CHECK_TYPES([acl_t, acl_entry_t, acl_permset_t, acl_tag_t], [], [], [ + #if HAVE_SYS_TYPES_H + #include + #endif + #if HAVE_SYS_ACL_H + #include + #endif + ]) + + AC_CHECK_LIB([richacl], [richacl_get_file]) + + AC_CHECK_TYPES([[struct richace], [struct richacl]], [], [], [ + #if HAVE_SYS_RICHACL_H + #include + #endif + ]) + + # Solaris and derivates ACLs + AC_CHECK_FUNCS(acl facl) + + if test "x$ac_cv_lib_richacl_richacl_get_file" = "xyes" \ + -a "x$ac_cv_type_struct_richace" = "xyes" \ + -a "x$ac_cv_type_struct_richacl" = "xyes"; then + AC_CACHE_VAL([ac_cv_archive_acl_librichacl], + [AC_CHECK_FUNCS(richacl_alloc \ + richacl_equiv_mode \ + richacl_free \ + richacl_get_fd \ + richacl_get_file \ + richacl_set_fd \ + richacl_set_file, + [ac_cv_archive_acl_librichacl=yes], [ac_cv_archive_acl_librichacl=no], [#include ])]) + fi + + if test "x$ac_cv_func_acl" = "xyes" \ + -a "x$ac_cv_func_facl" = "xyes"; then + AC_CHECK_TYPES([aclent_t], [], [], [[#include ]]) + if test "x$ac_cv_type_aclent_t" = "xyes"; then + AC_CACHE_VAL([ac_cv_archive_acl_sunos], + [AC_CHECK_DECLS([GETACL, SETACL, GETACLCNT], + [ac_cv_archive_acl_sunos=yes], [ac_cv_archive_acl_sunos=no], + [#include ])]) + AC_CHECK_TYPES([ace_t], [], [], [[#include ]]) + if test "x$ac_cv_type_ace_t" = "xyes"; then + AC_CACHE_VAL([ac_cv_archive_acl_sunos_nfs4], + [AC_CHECK_DECLS([ACE_GETACL, ACE_SETACL, ACE_GETACLCNT], + [ac_cv_archive_acl_sunos_nfs4=yes], + [ac_cv_archive_acl_sonos_nfs4=no], + [#include ])]) + fi + fi + elif test "x$ac_cv_type_acl_t" = "xyes" \ + -a "x$ac_cv_type_acl_entry_t" = "xyes" \ + -a "x$ac_cv_type_acl_permset_t" = "xyes" \ + -a "x$ac_cv_type_acl_tag_t" = "xyes"; then + # POSIX.1e ACL functions + AC_CACHE_VAL([ac_cv_posix_acl_funcs], + [AC_CHECK_FUNCS(acl_add_perm \ + acl_clear_perms \ + acl_create_entry \ + acl_delete_def_file \ + acl_free \ + acl_get_entry \ + acl_get_fd \ + acl_get_file \ + acl_get_permset \ + acl_get_qualifier \ + acl_get_tag_type \ + acl_init \ + acl_set_fd \ + acl_set_file \ + acl_set_qualifier \ + acl_set_tag_type, + [ac_cv_posix_acl_funcs=yes], [ac_cv_posix_acl_funcs=no], + [#if HAVE_SYS_TYPES_H + #include + #endif + #if HAVE_SYS_ACL_H + #include + #endif + ]) + ]) + + AC_CHECK_FUNCS(acl_get_perm) + + if test "x$ac_cv_posix_acl_funcs" = "xyes" \ + -a "x$ac_cv_header_acl_libacl_h" = "xyes" \ + -a "x$ac_cv_lib_acl_acl_get_file" = "xyes" \ + -a "x$ac_cv_func_acl_get_perm"; then + AC_CACHE_VAL([ac_cv_archive_acl_libacl], + [ac_cv_archive_acl_libacl=yes]) + AC_DEFINE([ARCHIVE_ACL_LIBACL], [1], + [POSIX.1e ACL support via libacl]) + else + # FreeBSD/Darwin + AC_CHECK_FUNCS(acl_add_flag_np \ + acl_clear_flags_np \ + acl_get_brand_np \ + acl_get_entry_type_np \ + acl_get_flag_np \ + acl_get_flagset_np \ + acl_get_fd_np \ + acl_get_link_np \ + acl_get_perm_np \ + acl_is_trivial_np \ + acl_set_entry_type_np \ + acl_set_fd_np \ + acl_set_link_np,,, + [#include + #include ]) + + AC_CHECK_FUNCS(mbr_uid_to_uuid \ + mbr_uuid_to_id \ + mbr_gid_to_uuid,,, + [#include ]) + + AC_CHECK_DECLS([ACL_TYPE_EXTENDED, ACL_TYPE_NFS4, ACL_USER, + ACL_SYNCHRONIZE], [], [], + [#include + #include ]) + if test "x$ac_cv_posix_acl_funcs" = "xyes" \ + -a "x$ac_cv_func_acl_get_fd_np" = "xyes" \ + -a "x$ac_cv_func_acl_get_perm" != "xyes" \ + -a "x$ac_cv_func_acl_get_perm_np" = "xyes" \ + -a "x$ac_cv_func_acl_set_fd_np" = "xyes"; then + if test "x$ac_cv_have_decl_ACL_USER" = "xyes"; then + AC_CACHE_VAL([ac_cv_archive_acl_freebsd], + [ac_cv_archive_acl_freebsd=yes]) + if test "x$ac_cv_have_decl_ACL_TYPE_NFS4" = "xyes" \ + -a "x$ac_cv_func_acl_add_flag_np" = "xyes" \ + -a "x$ac_cv_func_acl_get_brand_np" = "xyes" \ + -a "x$ac_cv_func_acl_get_entry_type_np" = "xyes" \ + -a "x$ac_cv_func_acl_get_flagset_np" = "xyes" \ + -a "x$ac_cv_func_acl_set_entry_type_np" = "xyes"; then + AC_CACHE_VAL([ac_cv_archive_acl_freebsd_nfs4], + [ac_cv_archive_acl_freebsd_nfs4=yes]) + fi + elif test "x$ac_cv_have_decl_ACL_TYPE_EXTENDED" = "xyes" \ + -a "x$ac_cv_func_acl_add_flag_np" = "xyes" \ + -a "x$ac_cv_func_acl_get_flagset_np" = "xyes" \ + -a "x$ac_cv_func_acl_get_link_np" = "xyes" \ + -a "x$ac_cv_func_acl_set_link_np" = "xyes" \ + -a "x$ac_cv_func_mbr_uid_to_uuid" = "xyes" \ + -a "x$ac_cv_func_mbr_uuid_to_id" = "xyes" \ + -a "x$ac_cv_func_mbr_gid_to_uuid" = "xyes"; then + AC_CACHE_VAL([ac_cv_archive_acl_darwin], + [ac_cv_archive_acl_darwin=yes]) + fi + fi + fi + fi + AC_MSG_CHECKING([for ACL support]) + if test "x$ac_cv_archive_acl_libacl" = "xyes" \ + -a "x$ac_cv_archive_acl_librichacl" = "xyes"; then + AC_MSG_RESULT([libacl (POSIX.1e) + librichacl (NFSv4)]) + AC_DEFINE([ARCHIVE_ACL_LIBACL], [1], + [Linux POSIX.1e ACL support via libacl]) + AC_DEFINE([ARCHIVE_ACL_LIBRICHACL], [1], + [Linux NFSv4 ACL support via librichacl]) + elif test "x$ac_cv_archive_acl_libacl" = "xyes"; then + AC_MSG_RESULT([libacl (POSIX.1e)]) + AC_DEFINE([ARCHIVE_ACL_LIBACL], [1], + [Linux POSIX.1e ACL support via libacl]) + elif test "x$ac_cv_archive_acl_librichacl" = "xyes"; then + AC_MSG_RESULT([librichacl (NFSv4)]) + AC_DEFINE([ARCHIVE_ACL_LIBRICHACL], [1], + [Linux NFSv4 ACL support via librichacl]) + elif test "x$ac_cv_archive_acl_darwin" = "xyes"; then + AC_DEFINE([ARCHIVE_ACL_DARWIN], [1], [Darwin ACL support]) + AC_MSG_RESULT([Darwin (limited NFSv4)]) + elif test "x$ac_cv_archive_acl_sunos" = "xyes"; then + AC_DEFINE([ARCHIVE_ACL_SUNOS], [1], [Solaris ACL support]) + if test "x$ac_cv_archive_acl_sunos_nfs4" = "xyes"; then + AC_DEFINE([ARCHIVE_ACL_SUNOS_NFS4], [1], + [Solaris NFSv4 ACL support]) + AC_MSG_RESULT([Solaris (POSIX.1e and NFSv4)]) + else + AC_MSG_RESULT([Solaris (POSIX.1e)]) + fi + elif test "x$ac_cv_archive_acl_freebsd" = "xyes"; then + AC_DEFINE([ARCHIVE_ACL_FREEBSD], [1], [FreeBSD ACL support]) + if test "x$ac_cv_archive_acl_freebsd_nfs4" = "xyes"; then + AC_DEFINE([ARCHIVE_ACL_FREEBSD_NFS4], [1], + [FreeBSD NFSv4 ACL support]) + AC_MSG_RESULT([FreeBSD (POSIX.1e and NFSv4)]) + else + AC_MSG_RESULT([FreeBSD (POSIX.1e)]) + fi + else + AC_MSG_RESULT([none]) + fi +fi + + +AM_CONDITIONAL([INC_LINUX_ACL], + [test "x$ac_cv_archive_acl_libacl" = "xyes" \ + -o "x$ac_cv_archive_acl_librichacl" = "xyes"]) +AM_CONDITIONAL([INC_SUNOS_ACL], [test "x$ac_cv_archive_acl_sunos" = "xyes"]) +AM_CONDITIONAL([INC_DARWIN_ACL], + [test "x$ac_cv_archive_acl_darwin" = "xyes"]) +AM_CONDITIONAL([INC_FREEBSD_ACL], + [test "x$ac_cv_archive_acl_freebsd" = "xyes"]) + +# Additional requirements +AC_SYS_LARGEFILE + +dnl NOTE: Crypto checks must run last. +AC_DEFUN([CRYPTO_CHECK], [ + if test "$found_$1" != yes; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" + touch "check_crypto_md.h" + AC_MSG_CHECKING([support for ARCHIVE_CRYPTO_$1_$2]) + AC_LINK_IFELSE([AC_LANG_SOURCE([ +#define ARCHIVE_$1_COMPILE_TEST +#define ARCHIVE_CRYPTO_$1_$2 +#define PLATFORM_CONFIG_H "check_crypto_md.h" + +$(cat "$srcdir/libarchive/archive_digest.c") + +int +main(int argc, char **argv) +{ + archive_$3_ctx ctx; + archive_$3_init(&ctx); + archive_$3_update(&ctx, *argv, argc); + archive_$3_final(&ctx, NULL); + return 0; +} +])], + [ AC_MSG_RESULT([yes]) + found_$1=yes + found_$2=yes + AC_DEFINE(ARCHIVE_CRYPTO_$1_$2, 1, [ $1 via ARCHIVE_CRYPTO_$1_$2 supported.]) + ], + [ AC_MSG_RESULT([no])]) + CPPFLAGS="$saved_CPPFLAGS" + rm "check_crypto_md.h" + fi +]) + +AC_DEFUN([CRYPTO_CHECK_WIN], [ + if test "$found_$1" != yes; then + AC_MSG_CHECKING([support for ARCHIVE_CRYPTO_$1_WIN]) + AC_LINK_IFELSE([AC_LANG_SOURCE([ +#define ARCHIVE_$1_COMPILE_TEST +#include +#include + +int +main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + return ($2); +} +])], + [ AC_MSG_RESULT([yes]) + found_$1=yes + found_WIN=yes + AC_DEFINE(ARCHIVE_CRYPTO_$1_WIN, 1, [ $1 via ARCHIVE_CRYPTO_$1_WIN supported.]) + ], + [ AC_MSG_RESULT([no])]) + fi +]) + +case "$host_os" in + *mingw* | *cygwin* | *msys*) + ;; + *) + CRYPTO_CHECK(MD5, LIBC, md5) + CRYPTO_CHECK(MD5, LIBSYSTEM, md5) + CRYPTO_CHECK(RMD160, LIBC, rmd160) + CRYPTO_CHECK(SHA1, LIBC, sha1) + CRYPTO_CHECK(SHA1, LIBSYSTEM, sha1) + CRYPTO_CHECK(SHA256, LIBC, sha256) + CRYPTO_CHECK(SHA256, LIBC2, sha256) + CRYPTO_CHECK(SHA256, LIBC3, sha256) + CRYPTO_CHECK(SHA256, LIBSYSTEM, sha256) + CRYPTO_CHECK(SHA384, LIBC, sha384) + CRYPTO_CHECK(SHA384, LIBC2, sha384) + CRYPTO_CHECK(SHA384, LIBC3, sha384) + CRYPTO_CHECK(SHA384, LIBSYSTEM, sha384) + CRYPTO_CHECK(SHA512, LIBC, sha512) + CRYPTO_CHECK(SHA512, LIBC2, sha512) + CRYPTO_CHECK(SHA512, LIBC3, sha512) + CRYPTO_CHECK(SHA512, LIBSYSTEM, sha512) + ;; +esac + +if test "x$with_cng" != "xno"; then + AC_CHECK_HEADERS([bcrypt.h],[ + LIBS="$LIBS -lbcrypt" + ],[], + [[#ifdef HAVE_WINDOWS_H + # include + #endif + ]]) +fi + +if test "x$with_mbedtls" = "xyes"; then + AC_CHECK_HEADERS([mbedtls/aes.h mbedtls/md.h mbedtls/pkcs5.h]) + saved_LIBS=$LIBS + AC_CHECK_LIB(mbedcrypto,mbedtls_sha1_init) + CRYPTO_CHECK(MD5, MBEDTLS, md5) + CRYPTO_CHECK(RMD160, MBEDTLS, rmd160) + CRYPTO_CHECK(SHA1, MBEDTLS, sha1) + CRYPTO_CHECK(SHA256, MBEDTLS, sha256) + CRYPTO_CHECK(SHA384, MBEDTLS, sha384) + CRYPTO_CHECK(SHA512, MBEDTLS, sha512) + if test "x$found_MBEDTLS" != "xyes"; then + LIBS=$saved_LIBS + fi +fi + +if test "x$with_nettle" = "xyes"; then + AC_CHECK_HEADERS([nettle/md5.h nettle/ripemd160.h nettle/sha.h]) + AC_CHECK_HEADERS([nettle/pbkdf2.h nettle/aes.h nettle/hmac.h]) + saved_LIBS=$LIBS + AC_CHECK_LIB(nettle,nettle_sha1_init) + CRYPTO_CHECK(MD5, NETTLE, md5) + CRYPTO_CHECK(RMD160, NETTLE, rmd160) + CRYPTO_CHECK(SHA1, NETTLE, sha1) + CRYPTO_CHECK(SHA256, NETTLE, sha256) + CRYPTO_CHECK(SHA384, NETTLE, sha384) + CRYPTO_CHECK(SHA512, NETTLE, sha512) + if test "x$found_NETTLE" != "xyes"; then + LIBS=$saved_LIBS + fi +fi + +if test "x$with_openssl" != "xno"; then + AC_CHECK_HEADERS([openssl/evp.h]) + saved_LIBS=$LIBS + case "$host_os" in + *mingw* | *cygwin* | *msys*) + case "$host_cpu" in + x86_64) + AC_CHECK_LIB(eay64,OPENSSL_config) + if test "x$ac_cv_lib_eay64_main" != "xyes"; then + AC_CHECK_LIB(eay32,OPENSSL_config) + fi + ;; + *) + AC_CHECK_LIB(eay32,OPENSSL_config) + ;; + esac + ;; + *) + AC_CHECK_LIB(crypto,OPENSSL_config) + ;; + esac + CRYPTO_CHECK(MD5, OPENSSL, md5) + CRYPTO_CHECK(RMD160, OPENSSL, rmd160) + CRYPTO_CHECK(SHA1, OPENSSL, sha1) + CRYPTO_CHECK(SHA256, OPENSSL, sha256) + CRYPTO_CHECK(SHA384, OPENSSL, sha384) + CRYPTO_CHECK(SHA512, OPENSSL, sha512) + AC_CHECK_FUNCS([PKCS5_PBKDF2_HMAC_SHA1]) +fi + +# Probe libmd AFTER OpenSSL/libcrypto. +# The two are incompatible and OpenSSL is more complete. +AC_CHECK_HEADERS([md5.h ripemd.h sha.h sha256.h sha512.h]) +saved_LIBS=$LIBS +AC_CHECK_LIB(md,MD5Init) +CRYPTO_CHECK(MD5, LIBMD, md5) +CRYPTO_CHECK(RMD160, LIBMD, rmd160) +CRYPTO_CHECK(SHA1, LIBMD, sha1) +CRYPTO_CHECK(SHA256, LIBMD, sha256) +CRYPTO_CHECK(SHA512, LIBMD, sha512) +if test "x$found_LIBMD" != "xyes"; then + LIBS=$saved_LIBS +fi + +case "$host_os" in + *mingw* | *cygwin* | *msys*) + CRYPTO_CHECK_WIN(MD5, CALG_MD5) + CRYPTO_CHECK_WIN(SHA1, CALG_SHA1) + CRYPTO_CHECK_WIN(SHA256, CALG_SHA_256) + CRYPTO_CHECK_WIN(SHA384, CALG_SHA_384) + CRYPTO_CHECK_WIN(SHA512, CALG_SHA_512) + ;; +esac + +# Ensure test directories are present if building out-of-tree +AC_CONFIG_COMMANDS([mkdirs], + [mkdir -p libarchive/test tar/test cat/test cpio/test]) + +AC_OUTPUT diff --git a/dependencies/libarchive-3.4.2/contrib/README b/dependencies/libarchive-3.4.2/contrib/README new file mode 100644 index 0000000..8ad352a --- /dev/null +++ b/dependencies/libarchive-3.4.2/contrib/README @@ -0,0 +1,59 @@ +Many people have graciously sent me configuration +files, small programs that use libarchive, and other +useful and interesting tidbits. + +I do not support or use any of these; but if you can use them, enjoy! + +====================================================================== + +From: Andre Stechert + +libarchive_autodetect-st_lib_archive.m4 + +M4 macros for use with autoconf to detect whether a suitable +version of libarchive is installed on this system. + + +====================================================================== + +libarchive.spec + +An RPM ".spec" file for building libarchive on most systems. +This apparently was originally developed by a group at pld-linux.org. +Several people have sent me different versions of this file. + +====================================================================== + +From: Robert Meier + +libarchive.1aix53.spec + +As above, for use on AIX5.3. + +====================================================================== + +psota-benchmark + +Some scripts used by Jan Psota in benchmarking +various tar implementations. + +I've edited his results slightly to correctly reflect that +bsdtar does not support a "compare" operation. + +====================================================================== + +shar + +A simple shar program written on top of libarchive. + +====================================================================== + +untar.c + +A very simple and very portable standalone program that can +extract basic ustar archives. +This does not use libarchive and so can be used to extract +the libarchive distribution on any system that has a C compiler +but does not have a tar program. + +====================================================================== diff --git a/dependencies/libarchive-3.4.2/contrib/android/Android.mk b/dependencies/libarchive-3.4.2/contrib/android/Android.mk new file mode 100644 index 0000000..3f7619d --- /dev/null +++ b/dependencies/libarchive-3.4.2/contrib/android/Android.mk @@ -0,0 +1,308 @@ +# +# Copyright (C) 2014 Trevor Drake +# +# 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. +# +# + + +# A bit of a non-standard LOCAL_PATH declaration here +# The Android.mk lives below the top source directory +# but LOCAL_PATH needs to point to the top of the module +# source tree to maintain the integrity of the intermediates +# directories +LOCAL_PATH := $(subst /contrib/android,,$(call my-dir)) + +libarchive_target_config := contrib/android/config/android.h + +libarchive_src_files := libarchive/archive_acl.c \ + libarchive/archive_check_magic.c \ + libarchive/archive_cmdline.c \ + libarchive/archive_cryptor.c \ + libarchive/archive_digest.c \ + libarchive/archive_entry.c \ + libarchive/archive_entry_copy_stat.c \ + libarchive/archive_entry_link_resolver.c \ + libarchive/archive_entry_sparse.c \ + libarchive/archive_entry_stat.c \ + libarchive/archive_entry_strmode.c \ + libarchive/archive_entry_xattr.c \ + libarchive/archive_getdate.c \ + libarchive/archive_hmac.c \ + libarchive/archive_match.c \ + libarchive/archive_options.c \ + libarchive/archive_pack_dev.c \ + libarchive/archive_pathmatch.c \ + libarchive/archive_ppmd7.c \ + libarchive/archive_random.c \ + libarchive/archive_rb.c \ + libarchive/archive_read.c \ + libarchive/archive_read_add_passphrase.c \ + libarchive/archive_read_append_filter.c \ + libarchive/archive_read_data_into_fd.c \ + libarchive/archive_read_disk_entry_from_file.c \ + libarchive/archive_read_disk_posix.c \ + libarchive/archive_read_disk_set_standard_lookup.c \ + libarchive/archive_read_extract.c \ + libarchive/archive_read_extract2.c \ + libarchive/archive_read_open_fd.c \ + libarchive/archive_read_open_file.c \ + libarchive/archive_read_open_filename.c \ + libarchive/archive_read_open_memory.c \ + libarchive/archive_read_set_format.c \ + libarchive/archive_read_set_options.c \ + libarchive/archive_read_support_filter_all.c \ + libarchive/archive_read_support_filter_bzip2.c \ + libarchive/archive_read_support_filter_compress.c \ + libarchive/archive_read_support_filter_grzip.c \ + libarchive/archive_read_support_filter_gzip.c \ + libarchive/archive_read_support_filter_lrzip.c \ + libarchive/archive_read_support_filter_lz4.c \ + libarchive/archive_read_support_filter_lzop.c \ + libarchive/archive_read_support_filter_none.c \ + libarchive/archive_read_support_filter_program.c \ + libarchive/archive_read_support_filter_rpm.c \ + libarchive/archive_read_support_filter_uu.c \ + libarchive/archive_read_support_filter_xz.c \ + libarchive/archive_read_support_filter_zstd.c \ + libarchive/archive_read_support_format_7zip.c \ + libarchive/archive_read_support_format_all.c \ + libarchive/archive_read_support_format_ar.c \ + libarchive/archive_read_support_format_by_code.c \ + libarchive/archive_read_support_format_cab.c \ + libarchive/archive_read_support_format_cpio.c \ + libarchive/archive_read_support_format_empty.c \ + libarchive/archive_read_support_format_iso9660.c \ + libarchive/archive_read_support_format_lha.c \ + libarchive/archive_read_support_format_mtree.c \ + libarchive/archive_read_support_format_rar.c \ + libarchive/archive_read_support_format_raw.c \ + libarchive/archive_read_support_format_tar.c \ + libarchive/archive_read_support_format_warc.c \ + libarchive/archive_read_support_format_xar.c \ + libarchive/archive_read_support_format_zip.c \ + libarchive/archive_string.c \ + libarchive/archive_string_sprintf.c \ + libarchive/archive_util.c \ + libarchive/archive_version_details.c \ + libarchive/archive_virtual.c \ + libarchive/archive_write.c \ + libarchive/archive_write_disk_posix.c \ + libarchive/archive_write_disk_set_standard_lookup.c \ + libarchive/archive_write_open_fd.c \ + libarchive/archive_write_open_file.c \ + libarchive/archive_write_open_filename.c \ + libarchive/archive_write_open_memory.c \ + libarchive/archive_write_add_filter.c \ + libarchive/archive_write_add_filter_b64encode.c \ + libarchive/archive_write_add_filter_by_name.c \ + libarchive/archive_write_add_filter_bzip2.c \ + libarchive/archive_write_add_filter_compress.c \ + libarchive/archive_write_add_filter_grzip.c \ + libarchive/archive_write_add_filter_gzip.c \ + libarchive/archive_write_add_filter_lrzip.c \ + libarchive/archive_write_add_filter_lz4.c \ + libarchive/archive_write_add_filter_lzop.c \ + libarchive/archive_write_add_filter_none.c \ + libarchive/archive_write_add_filter_program.c \ + libarchive/archive_write_add_filter_uuencode.c \ + libarchive/archive_write_add_filter_xz.c \ + libarchive/archive_write_add_filter_zstd.c \ + libarchive/archive_write_set_format.c \ + libarchive/archive_write_set_format_7zip.c \ + libarchive/archive_write_set_format_ar.c \ + libarchive/archive_write_set_format_by_name.c \ + libarchive/archive_write_set_format_cpio.c \ + libarchive/archive_write_set_format_cpio_newc.c \ + libarchive/archive_write_set_format_iso9660.c \ + libarchive/archive_write_set_format_mtree.c \ + libarchive/archive_write_set_format_pax.c \ + libarchive/archive_write_set_format_raw.c \ + libarchive/archive_write_set_format_shar.c \ + libarchive/archive_write_set_format_ustar.c \ + libarchive/archive_write_set_format_v7tar.c \ + libarchive/archive_write_set_format_gnutar.c \ + libarchive/archive_write_set_format_warc.c \ + libarchive/archive_write_set_format_xar.c \ + libarchive/archive_write_set_format_zip.c \ + libarchive/archive_write_set_options.c \ + libarchive/archive_write_set_passphrase.c \ + libarchive/filter_fork_posix.c \ + libarchive/xxhash.c + +ifeq ($(HOST_OS),windows) +libarchive_host_src_files := \ + libarchive/archive_entry_copy_bhfi.c \ + libarchive/archive_read_disk_windows.c \ + libarchive/archive_write_disk_windows.c \ + libarchive/filter_fork_windows.c \ + libarchive/archive_windows.c +else +libarchive_host_src_files := +endif + +libarchive_fe_src_files := libarchive_fe/err.c \ + libarchive_fe/line_reader.c \ + libarchive_fe/passphrase.c + +bsdtar_src_files := tar/bsdtar.c \ + tar/bsdtar_windows.c \ + tar/cmdline.c \ + tar/creation_set.c \ + tar/read.c \ + tar/subst.c \ + tar/util.c \ + tar/write.c + +bsdcpio_src_files := cpio/cmdline.c \ + cpio/cpio.c + +bsdcat_src_files := cat/cmdline.c \ + cat/bsdcat.c + + +ifeq ($(HOST_OS),darwin) +$(warning Host : $(HOST_OS) Not Supported. Host Build Will Be Skipped ) +else +libarchive_host_config := contrib/android/config/$(HOST_OS)_host.h + +include $(CLEAR_VARS) +LOCAL_MODULE := libarchive +LOCAL_MODULE_TAGS := optional +LOCAL_SRC_FILES := $(libarchive_src_files) $(libarchive_host_src_files) +LOCAL_CFLAGS := -DPLATFORM_CONFIG_H=\"$(libarchive_host_config)\" +LOCAL_C_INCLUDES := $(LOCAL_PATH)/contrib/android/include +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/libarchive +include $(BUILD_HOST_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := libarchive +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := -DPLATFORM_CONFIG_H=\"$(libarchive_host_config)\" +LOCAL_SHARED_LIBRARIES := libz-host +LOCAL_WHOLE_STATIC_LIBRARIES := libarchive +LOCAL_C_INCLUDES := $(LOCAL_PATH)/contrib/android/include +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/libarchive +include $(BUILD_HOST_SHARED_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := libarchive_fe +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := -DPLATFORM_CONFIG_H=\"$(libarchive_host_config)\" +LOCAL_SRC_FILES := $(libarchive_fe_src_files) +LOCAL_C_INCLUDES := $(LOCAL_PATH)/contrib/android/include +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/libarchive_fe +include $(BUILD_HOST_STATIC_LIBRARY) + +endif + + +# Do not build target binaries if we are not targeting linux +# on the host +ifeq ($(HOST_OS),linux) + +include $(CLEAR_VARS) +LOCAL_MODULE := bsdtar +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := -DBSDTAR_VERSION_STRING=ARCHIVE_VERSION_ONLY_STRING -DPLATFORM_CONFIG_H=\"$(libarchive_host_config)\" +LOCAL_SHARED_LIBRARIES := libz-host +LOCAL_STATIC_LIBRARIES := libarchive libarchive_fe +LOCAL_SRC_FILES := $(bsdtar_src_files) +LOCAL_C_INCLUDES := $(LOCAL_PATH)/contrib/android/include +include $(BUILD_HOST_EXECUTABLE) + +include $(CLEAR_VARS) +LOCAL_MODULE := bsdcpio +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := -DBSDCPIO_VERSION_STRING=ARCHIVE_VERSION_ONLY_STRING -DPLATFORM_CONFIG_H=\"$(libarchive_host_config)\" +LOCAL_SHARED_LIBRARIES := libz-host +LOCAL_STATIC_LIBRARIES := libarchive libarchive_fe +LOCAL_SRC_FILES := $(bsdcpio_src_files) +LOCAL_C_INCLUDES := $(LOCAL_PATH)/contrib/android/include +include $(BUILD_HOST_EXECUTABLE) + +include $(CLEAR_VARS) +LOCAL_MODULE := bsdcat +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := -DBSDCAT_VERSION_STRING=ARCHIVE_VERSION_ONLY_STRING -DPLATFORM_CONFIG_H=\"$(libarchive_host_config)\" +LOCAL_SHARED_LIBRARIES := libz-host +LOCAL_STATIC_LIBRARIES := libarchive libarchive_fe +LOCAL_SRC_FILES := $(bsdcat_src_files) +LOCAL_C_INCLUDES := $(LOCAL_PATH)/contrib/android/include +include $(BUILD_HOST_EXECUTABLE) + + + +include $(CLEAR_VARS) +LOCAL_MODULE := libarchive +LOCAL_MODULE_TAGS := optional +LOCAL_SRC_FILES := $(libarchive_src_files) +LOCAL_STATIC_LIBRARIES := libz liblz4 +LOCAL_CFLAGS := -DPLATFORM_CONFIG_H=\"$(libarchive_target_config)\" +LOCAL_C_INCLUDES := $(LOCAL_PATH)/contrib/android/include +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/libarchive +include $(BUILD_STATIC_LIBRARY) + + +include $(CLEAR_VARS) +LOCAL_MODULE := libarchive +LOCAL_MODULE_TAGS := optional +LOCAL_C_INCLUDES := +LOCAL_CFLAGS := -DPLATFORM_CONFIG_H=\"$(libarchive_target_config)\" +LOCAL_SHARED_LIBRARIES := libz +LOCAL_WHOLE_STATIC_LIBRARIES := libarchive +LOCAL_C_INCLUDES := $(LOCAL_PATH)/contrib/android/include +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/libarchive +include $(BUILD_SHARED_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := libarchive_fe +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := -DPLATFORM_CONFIG_H=\"$(libarchive_target_config)\" +LOCAL_SRC_FILES := $(libarchive_fe_src_files) +LOCAL_C_INCLUDES := $(LOCAL_PATH)/contrib/android/include +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/libarchive_fe +include $(BUILD_STATIC_LIBRARY) + + +include $(CLEAR_VARS) +LOCAL_MODULE := bsdtar +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := -DBSDTAR_VERSION_STRING=ARCHIVE_VERSION_ONLY_STRING -DPLATFORM_CONFIG_H=\"$(libarchive_target_config)\" +LOCAL_SHARED_LIBRARIES := libz +LOCAL_STATIC_LIBRARIES := libarchive libarchive_fe +LOCAL_SRC_FILES := $(bsdtar_src_files) +LOCAL_C_INCLUDES := $(LOCAL_PATH)/libarchive $(LOCAL_PATH)/libarchive_fe $(LOCAL_PATH)/contrib/android/include +include $(BUILD_EXECUTABLE) + +include $(CLEAR_VARS) +LOCAL_MODULE := bsdcpio +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := -DBSDCPIO_VERSION_STRING=ARCHIVE_VERSION_ONLY_STRING -DPLATFORM_CONFIG_H=\"$(libarchive_target_config)\" +LOCAL_SHARED_LIBRARIES := libz +LOCAL_STATIC_LIBRARIES := libarchive libarchive_fe +LOCAL_SRC_FILES := $(bsdcpio_src_files) +LOCAL_C_INCLUDES := $(LOCAL_PATH)/libarchive $(LOCAL_PATH)/libarchive_fe $(LOCAL_PATH)/contrib/android/include +include $(BUILD_EXECUTABLE) + +include $(CLEAR_VARS) +LOCAL_MODULE := bsdcat +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := -DBSDCAT_VERSION_STRING=ARCHIVE_VERSION_ONLY_STRING -DPLATFORM_CONFIG_H=\"$(libarchive_target_config)\" +LOCAL_SHARED_LIBRARIES := libz +LOCAL_STATIC_LIBRARIES := libarchive libarchive_fe +LOCAL_SRC_FILES := $(bsdcat_src_files) +LOCAL_C_INCLUDES := $(LOCAL_PATH)/libarchive $(LOCAL_PATH)/libarchive_fe $(LOCAL_PATH)/contrib/android/include +include $(BUILD_EXECUTABLE) + +endif diff --git a/dependencies/libarchive-3.4.2/contrib/android/config/android.h b/dependencies/libarchive-3.4.2/contrib/android/config/android.h new file mode 100644 index 0000000..8e18312 --- /dev/null +++ b/dependencies/libarchive-3.4.2/contrib/android/config/android.h @@ -0,0 +1,184 @@ +/*- + * Copyright (c) 2014 Trevor Drake + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef ARCHIVE_PLATFORM_H_ANDROID_INCLUDED +#define ARCHIVE_PLATFORM_H_ANDROID_INCLUDED + +#include +#ifdef __ANDROID_API__ +#if __ANDROID_API__ > 20 +#define HAVE_FSTATVFS 1 +#define HAVE_STATVFS 1 +#define HAVE_TIMEGM 1 +#define HAVE_SYS_XATTR_H 1 +#define HAVE_LINUX_FIEMAP_H 1 +#define HAVE_SYS_STATVFS_H 1 +#endif +#endif + +#define HAVE_CHOWN 1 +#define HAVE_CHROOT 1 +#define HAVE_CTIME_R 1 +#define HAVE_CTYPE_H 1 +#define HAVE_DECL_EXTATTR_NAMESPACE_USER 0 +#define HAVE_DECL_INTMAX_MIN 1 +#define HAVE_DECL_INTMAX_MAX 1 +#define HAVE_DECL_INT64_MAX 1 +#define HAVE_DECL_INT64_MIN 1 +#define HAVE_DECL_SIZE_MAX 1 +#define HAVE_DECL_SSIZE_MAX 1 +#define HAVE_DECL_STRERROR_R 1 +#define HAVE_DECL_UINTMAX_MAX 1 +#define HAVE_DECL_UINT32_MAX 1 +#define HAVE_DECL_UINT64_MAX 1 +#define HAVE_DIRENT_H 1 +#define HAVE_DIRFD 1 +#define HAVE_DLFCN_H 1 +#define HAVE_EILSEQ 1 +#define HAVE_ERRNO_H 1 +#define HAVE_FCHDIR 1 +#define HAVE_FCHMOD 1 +#define HAVE_FCHOWN 1 +#define HAVE_FCNTL 1 +#define HAVE_FCNTL_H 1 +#define HAVE_FDOPENDIR 1 +#define HAVE_FGETXATTR 1 +#define HAVE_FLISTXATTR 1 +#define HAVE_FORK 1 +#define HAVE_FSEEKO 1 +#define HAVE_FSETXATTR 1 +#define HAVE_FSTAT 1 +#define HAVE_FSTATAT 1 +#define HAVE_FSTATFS 1 +#define HAVE_FTRUNCATE 1 +#define HAVE_GETEUID 1 +#define HAVE_GETPID 1 +#define HAVE_GETPWNAM_R 1 +#define HAVE_GETPWUID_R 1 +#define HAVE_GETXATTR 1 +#define HAVE_GMTIME_R 1 +#define HAVE_GRP_H 1 +#define HAVE_INTMAX_T 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_LCHOWN 1 +#define HAVE_LGETXATTR 1 +#define HAVE_LIBLZMA 1 +#define HAVE_LIBZ 1 +#define HAVE_LIMITS_H 1 +#define HAVE_LINK 1 +#define HAVE_LINUX_FS_H 1 +#define HAVE_LINUX_MAGIC_H 1 +#define HAVE_LINUX_TYPES_H 1 +#define HAVE_LISTXATTR 1 +#define HAVE_LLISTXATTR 1 +#define HAVE_LOCALE_H 1 +#define HAVE_LOCALTIME_R 1 +#define HAVE_LONG_LONG_INT 1 +#define HAVE_LSETXATTR 1 +#define HAVE_LSTAT 1 +#define HAVE_MBRTOWC 1 +#define HAVE_MEMMOVE 1 +#define HAVE_MEMORY_H 1 +#define HAVE_MEMSET 1 +#define HAVE_MKDIR 1 +#define HAVE_MKFIFO 1 +#define HAVE_MKNOD 1 +#define HAVE_MKSTEMP 1 +#define HAVE_OPENAT 1 +#define HAVE_PATHS_H 1 +#define HAVE_PIPE 1 +#define HAVE_POLL 1 +#define HAVE_POLL_H 1 +#define HAVE_PTHREAD_H 1 +#define HAVE_PWD_H 1 +#define HAVE_READDIR_R 1 +#define HAVE_READLINK 1 +#define HAVE_READLINKAT 1 +#define HAVE_REGEX_H 1 +#define HAVE_SELECT 1 +#define HAVE_SETENV 1 +#define HAVE_SETLOCALE 1 +#define HAVE_SIGACTION 1 +#define HAVE_SIGNAL_H 1 +#define HAVE_STATFS 1 +#define HAVE_STDARG_H 1 +#define HAVE_STDINT_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_STRCHR 1 +#define HAVE_STRDUP 1 +#define HAVE_STRERROR 1 +#define HAVE_STRERROR_R 1 +#define HAVE_STRFTIME 1 +#define HAVE_STRINGS_H 1 +#define HAVE_STRING_H 1 +#define HAVE_STRRCHR 1 +#define HAVE_STRUCT_STAT_ST_BLKSIZE 1 +#define HAVE_STRUCT_STAT_ST_MTIME_NSEC 1 +#define HAVE_STRUCT_TM_TM_GMTOFF 1 +#define HAVE_SYMLINK 1 +#define HAVE_SYS_CDEFS_H 1 +#define HAVE_SYS_IOCTL_H 1 +#define HAVE_SYS_MOUNT_H 1 +#define HAVE_SYS_PARAM_H 1 +#define HAVE_SYS_POLL_H 1 +#define HAVE_SYS_SELECT_H 1 +#define HAVE_SYS_STATFS_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_SYS_TIME_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_SYS_UTSNAME_H 1 +#define HAVE_SYS_VFS_H 1 +#define HAVE_SYS_WAIT_H 1 +#define HAVE_TIME_H 1 +#define HAVE_TZSET 1 +#define HAVE_UINTMAX_T 1 +#define HAVE_UNISTD_H 1 +#define HAVE_UNSETENV 1 +#define HAVE_UNSIGNED_LONG_LONG 1 +#define HAVE_UNSIGNED_LONG_LONG_INT 1 +#define HAVE_UTIME 1 +#define HAVE_UTIMENSAT 1 +#define HAVE_UTIMES 1 +#define HAVE_UTIME_H 1 +#define HAVE_VFORK 1 +#define HAVE_VPRINTF 1 +#define HAVE_WCHAR_H 1 +#define HAVE_WCHAR_T 1 +#define HAVE_WCRTOMB 1 +#define HAVE_WCSCMP 1 +#define HAVE_WCSCPY 1 +#define HAVE_WCSLEN 1 +#define HAVE_WCTOMB 1 +#define HAVE_WCTYPE_H 1 +#define HAVE_WMEMCMP 1 +#define HAVE_WMEMCPY 1 +#define HAVE_ARC4RANDOM_BUF 1 +#define HAVE_ZLIB_H 1 +#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1 +#define SIZEOF_WCHAR_T 4 +#define STDC_HEADERS 1 +#define STRERROR_R_CHAR_P 1 +#define TIME_WITH_SYS_TIME 1 +#endif diff --git a/dependencies/libarchive-3.4.2/contrib/android/config/linux_host.h b/dependencies/libarchive-3.4.2/contrib/android/config/linux_host.h new file mode 100644 index 0000000..709b657 --- /dev/null +++ b/dependencies/libarchive-3.4.2/contrib/android/config/linux_host.h @@ -0,0 +1,189 @@ +/*- + * Copyright (c) 2014 Trevor Drake + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef ARCHIVE_PLATFORM_H_ANDROID_LINUX_HOST_INCLUDED +#define ARCHIVE_PLATFORM_H_ANDROID_LINUX_HOST_INCLUDED + +#define HAVE_CHOWN 1 +#define HAVE_CHROOT 1 +#define HAVE_CTIME_R 1 +#define HAVE_CTYPE_H 1 +#define HAVE_DECL_EXTATTR_NAMESPACE_USER 0 +#define HAVE_DECL_INT64_MAX 1 +#define HAVE_DECL_INT64_MIN 1 +#define HAVE_DECL_SIZE_MAX 1 +#define HAVE_DECL_SSIZE_MAX 1 +#define HAVE_DECL_STRERROR_R 1 +#define HAVE_DECL_UINT32_MAX 1 +#define HAVE_DECL_UINT64_MAX 1 +#define HAVE_DIRENT_H 1 +#define HAVE_DIRFD 1 +#define HAVE_DLFCN_H 1 +#define HAVE_EILSEQ 1 +#define HAVE_ERRNO_H 1 +#define HAVE_FCHDIR 1 +#define HAVE_FCHMOD 1 +#define HAVE_FCHOWN 1 +#define HAVE_FCNTL 1 +#define HAVE_FCNTL_H 1 +#define HAVE_FDOPENDIR 1 +#define HAVE_FGETXATTR 1 +#define HAVE_FLISTXATTR 1 +#define HAVE_FORK 1 +#define HAVE_FSEEKO 1 +#define HAVE_FSETXATTR 1 +#define HAVE_FSTAT 1 +#define HAVE_FSTATAT 1 +#define HAVE_FSTATFS 1 +#define HAVE_FSTATVFS 1 +#define HAVE_FTRUNCATE 1 +#define HAVE_FUTIMENS 1 +#define HAVE_FUTIMES 1 +#define HAVE_FUTIMESAT 1 +#define HAVE_GETEUID 1 +#define HAVE_GETGRGID_R 1 +#define HAVE_GETGRNAM_R 1 +#define HAVE_GETPID 1 +#define HAVE_GETPWNAM_R 1 +#define HAVE_GETPWUID_R 1 +#define HAVE_GETXATTR 1 +#define HAVE_GMTIME_R 1 +#define HAVE_GRP_H 1 +#define HAVE_ICONV 1 +#define HAVE_ICONV_H 1 +#define HAVE_INTMAX_T 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_LANGINFO_H 1 +#define HAVE_LCHOWN 1 +#define HAVE_LGETXATTR 1 +#define HAVE_LIBLZMA 1 +#define HAVE_LIBZ 1 +#define HAVE_LIMITS_H 1 +#define HAVE_LINK 1 +#define HAVE_LINUX_FIEMAP_H 1 +#define HAVE_LINUX_FS_H 1 +#define HAVE_LINUX_MAGIC_H 1 +#define HAVE_LINUX_TYPES_H 1 +#define HAVE_LISTXATTR 1 +#define HAVE_LLISTXATTR 1 +#define HAVE_LOCALE_H 1 +#define HAVE_LOCALTIME_R 1 +#define HAVE_LONG_LONG_INT 1 +#define HAVE_LSETXATTR 1 +#define HAVE_LSTAT 1 +#define HAVE_LUTIMES 1 +#define HAVE_MBRTOWC 1 +#define HAVE_MEMMOVE 1 +#define HAVE_MEMORY_H 1 +#define HAVE_MEMSET 1 +#define HAVE_MKDIR 1 +#define HAVE_MKFIFO 1 +#define HAVE_MKNOD 1 +#define HAVE_MKSTEMP 1 +#define HAVE_NL_LANGINFO 1 +#define HAVE_OPENAT 1 +#define HAVE_PATHS_H 1 +#define HAVE_PIPE 1 +#define HAVE_POLL 1 +#define HAVE_POLL_H 1 +#define HAVE_POSIX_SPAWNP 1 +#define HAVE_PTHREAD_H 1 +#define HAVE_PWD_H 1 +#define HAVE_READDIR_R 1 +#define HAVE_READLINK 1 +#define HAVE_READLINKAT 1 +#define HAVE_REGEX_H 1 +#define HAVE_SELECT 1 +#define HAVE_SETENV 1 +#define HAVE_SETLOCALE 1 +#define HAVE_SIGACTION 1 +#define HAVE_SIGNAL_H 1 +#define HAVE_SPAWN_H 1 +#define HAVE_STATFS 1 +#define HAVE_STATVFS 1 +#define HAVE_STDARG_H 1 +#define HAVE_STDINT_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_STRCHR 1 +#define HAVE_STRDUP 1 +#define HAVE_STRERROR 1 +#define HAVE_STRERROR_R 1 +#define HAVE_STRFTIME 1 +#define HAVE_STRINGS_H 1 +#define HAVE_STRING_H 1 +#define HAVE_STRRCHR 1 +#define HAVE_STRUCT_STAT_ST_BLKSIZE 1 +#define HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1 +#define HAVE_STRUCT_TM_TM_GMTOFF 1 +#define HAVE_SYMLINK 1 +#define HAVE_SYS_CDEFS_H 1 +#define HAVE_SYS_IOCTL_H 1 +#define HAVE_SYS_MOUNT_H 1 +#define HAVE_SYS_PARAM_H 1 +#define HAVE_SYS_POLL_H 1 +#define HAVE_SYS_SELECT_H 1 +#define HAVE_SYS_STATFS_H 1 +#define HAVE_SYS_STATVFS_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_SYS_TIME_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_SYS_UTSNAME_H 1 +#define HAVE_SYS_VFS_H 1 +#define HAVE_SYS_WAIT_H 1 +#define HAVE_SYS_XATTR_H 1 +#define HAVE_TIMEGM 1 +#define HAVE_TIME_H 1 +#define HAVE_TZSET 1 +#define HAVE_UINTMAX_T 1 +#define HAVE_UNISTD_H 1 +#define HAVE_UNSETENV 1 +#define HAVE_UNSIGNED_LONG_LONG 1 +#define HAVE_UNSIGNED_LONG_LONG_INT 1 +#define HAVE_UTIME 1 +#define HAVE_UTIMENSAT 1 +#define HAVE_UTIMES 1 +#define HAVE_UTIME_H 1 +#define HAVE_VFORK 1 +#define HAVE_VPRINTF 1 +#define HAVE_WCHAR_H 1 +#define HAVE_WCHAR_T 1 +#define HAVE_WCRTOMB 1 +#define HAVE_WCSCMP 1 +#define HAVE_WCSCPY 1 +#define HAVE_WCSLEN 1 +#define HAVE_WCTOMB 1 +#define HAVE_WCTYPE_H 1 +#define HAVE_WMEMCMP 1 +#define HAVE_WMEMCPY 1 +#define HAVE_ZLIB_H 1 +#define ICONV_CONST +#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1 +#define SIZEOF_WCHAR_T 4 +#define STDC_HEADERS 1 +#define STRERROR_R_CHAR_P 1 +#define TIME_WITH_SYS_TIME 1 +#define _GNU_SOURCE 1 + +#endif diff --git a/dependencies/libarchive-3.4.2/contrib/android/config/windows_host.h b/dependencies/libarchive-3.4.2/contrib/android/config/windows_host.h new file mode 100644 index 0000000..2d899d1 --- /dev/null +++ b/dependencies/libarchive-3.4.2/contrib/android/config/windows_host.h @@ -0,0 +1,1059 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* MD5 via ARCHIVE_CRYPTO_MD5_LIBC supported. */ +/* #undef ARCHIVE_CRYPTO_MD5_LIBC */ + +/* MD5 via ARCHIVE_CRYPTO_MD5_LIBMD supported. */ +/* #undef ARCHIVE_CRYPTO_MD5_LIBMD */ + +/* MD5 via ARCHIVE_CRYPTO_MD5_LIBSYSTEM supported. */ +/* #undef ARCHIVE_CRYPTO_MD5_LIBSYSTEM */ + +/* MD5 via ARCHIVE_CRYPTO_MD5_NETTLE supported. */ +/* #undef ARCHIVE_CRYPTO_MD5_NETTLE */ + +/* MD5 via ARCHIVE_CRYPTO_MD5_OPENSSL supported. */ +/* #undef ARCHIVE_CRYPTO_MD5_OPENSSL */ + +/* MD5 via ARCHIVE_CRYPTO_MD5_WIN supported. */ +#define ARCHIVE_CRYPTO_MD5_WIN 1 + +/* RMD160 via ARCHIVE_CRYPTO_RMD160_LIBC supported. */ +/* #undef ARCHIVE_CRYPTO_RMD160_LIBC */ + +/* RMD160 via ARCHIVE_CRYPTO_RMD160_LIBMD supported. */ +/* #undef ARCHIVE_CRYPTO_RMD160_LIBMD */ + +/* RMD160 via ARCHIVE_CRYPTO_RMD160_NETTLE supported. */ +/* #undef ARCHIVE_CRYPTO_RMD160_NETTLE */ + +/* RMD160 via ARCHIVE_CRYPTO_RMD160_OPENSSL supported. */ +/* #undef ARCHIVE_CRYPTO_RMD160_OPENSSL */ + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBC supported. */ +/* #undef ARCHIVE_CRYPTO_SHA1_LIBC */ + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBMD supported. */ +/* #undef ARCHIVE_CRYPTO_SHA1_LIBMD */ + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBSYSTEM supported. */ +/* #undef ARCHIVE_CRYPTO_SHA1_LIBSYSTEM */ + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_NETTLE supported. */ +/* #undef ARCHIVE_CRYPTO_SHA1_NETTLE */ + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_OPENSSL supported. */ +/* #undef ARCHIVE_CRYPTO_SHA1_OPENSSL */ + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_WIN supported. */ +#define ARCHIVE_CRYPTO_SHA1_WIN 1 + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC supported. */ +/* #undef ARCHIVE_CRYPTO_SHA256_LIBC */ + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC2 supported. */ +/* #undef ARCHIVE_CRYPTO_SHA256_LIBC2 */ + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC3 supported. */ +/* #undef ARCHIVE_CRYPTO_SHA256_LIBC3 */ + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBMD supported. */ +/* #undef ARCHIVE_CRYPTO_SHA256_LIBMD */ + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBSYSTEM supported. */ +/* #undef ARCHIVE_CRYPTO_SHA256_LIBSYSTEM */ + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_NETTLE supported. */ +/* #undef ARCHIVE_CRYPTO_SHA256_NETTLE */ + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_OPENSSL supported. */ +/* #undef ARCHIVE_CRYPTO_SHA256_OPENSSL */ + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_WIN supported. */ +#define ARCHIVE_CRYPTO_SHA256_WIN 1 + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC supported. */ +/* #undef ARCHIVE_CRYPTO_SHA384_LIBC */ + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC2 supported. */ +/* #undef ARCHIVE_CRYPTO_SHA384_LIBC2 */ + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC3 supported. */ +/* #undef ARCHIVE_CRYPTO_SHA384_LIBC3 */ + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBSYSTEM supported. */ +/* #undef ARCHIVE_CRYPTO_SHA384_LIBSYSTEM */ + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_NETTLE supported. */ +/* #undef ARCHIVE_CRYPTO_SHA384_NETTLE */ + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_OPENSSL supported. */ +/* #undef ARCHIVE_CRYPTO_SHA384_OPENSSL */ + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_WIN supported. */ +#define ARCHIVE_CRYPTO_SHA384_WIN 1 + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC supported. */ +/* #undef ARCHIVE_CRYPTO_SHA512_LIBC */ + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC2 supported. */ +/* #undef ARCHIVE_CRYPTO_SHA512_LIBC2 */ + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC3 supported. */ +/* #undef ARCHIVE_CRYPTO_SHA512_LIBC3 */ + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBMD supported. */ +/* #undef ARCHIVE_CRYPTO_SHA512_LIBMD */ + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBSYSTEM supported. */ +/* #undef ARCHIVE_CRYPTO_SHA512_LIBSYSTEM */ + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_NETTLE supported. */ +/* #undef ARCHIVE_CRYPTO_SHA512_NETTLE */ + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_OPENSSL supported. */ +/* #undef ARCHIVE_CRYPTO_SHA512_OPENSSL */ + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_WIN supported. */ +#define ARCHIVE_CRYPTO_SHA512_WIN 1 + +/* Define to 1 if you have the `acl_create_entry' function. */ +/* #undef HAVE_ACL_CREATE_ENTRY */ + +/* Define to 1 if you have the `acl_get_link' function. */ +/* #undef HAVE_ACL_GET_LINK */ + +/* Define to 1 if you have the `acl_get_link_np' function. */ +/* #undef HAVE_ACL_GET_LINK_NP */ + +/* Define to 1 if you have the `acl_get_perm' function. */ +/* #undef HAVE_ACL_GET_PERM */ + +/* Define to 1 if you have the `acl_get_perm_np' function. */ +/* #undef HAVE_ACL_GET_PERM_NP */ + +/* Define to 1 if you have the `acl_init' function. */ +/* #undef HAVE_ACL_INIT */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ACL_LIBACL_H */ + +/* Define to 1 if the system has the type `acl_permset_t'. */ +/* #undef HAVE_ACL_PERMSET_T */ + +/* Define to 1 if you have the `acl_set_fd' function. */ +/* #undef HAVE_ACL_SET_FD */ + +/* Define to 1 if you have the `acl_set_fd_np' function. */ +/* #undef HAVE_ACL_SET_FD_NP */ + +/* Define to 1 if you have the `acl_set_file' function. */ +/* #undef HAVE_ACL_SET_FILE */ + +/* True for systems with POSIX ACL support */ +/* #undef HAVE_ACL_USER */ + +/* Define to 1 if you have the `arc4random_buf' function. */ +/* #undef HAVE_ARC4RANDOM_BUF */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ATTR_XATTR_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_BCRYPT_H + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_BZLIB_H */ + +/* Define to 1 if you have the `chflags' function. */ +/* #undef HAVE_CHFLAGS */ + +/* Define to 1 if you have the `chown' function. */ +/* #undef HAVE_CHOWN */ + +/* Define to 1 if you have the `chroot' function. */ +/* #undef HAVE_CHROOT */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_COPYFILE_H */ + +/* Define to 1 if you have the `ctime_r' function. */ +/* #undef HAVE_CTIME_R */ + +/* Define to 1 if you have the header file. */ +#define HAVE_CTYPE_H 1 + +/* Define to 1 if you have the `cygwin_conv_path' function. */ +/* #undef HAVE_CYGWIN_CONV_PATH */ + +/* Define to 1 if you have the declaration of `EXTATTR_NAMESPACE_USER', and to + 0 if you don't. */ +#define HAVE_DECL_EXTATTR_NAMESPACE_USER 0 + +/* Define to 1 if you have the declaration of `INT64_MAX', and to 0 if you + don't. */ +#define HAVE_DECL_INT64_MAX 1 + +/* Define to 1 if you have the declaration of `INT64_MIN', and to 0 if you + don't. */ +#define HAVE_DECL_INT64_MIN 1 + +/* Define to 1 if you have the declaration of `SIZE_MAX', and to 0 if you + don't. */ +#define HAVE_DECL_SIZE_MAX 1 + +/* Define to 1 if you have the declaration of `SSIZE_MAX', and to 0 if you + don't. */ +#define HAVE_DECL_SSIZE_MAX 1 + +/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you + don't. */ +#define HAVE_DECL_STRERROR_R 0 + +/* Define to 1 if you have the declaration of `UINT32_MAX', and to 0 if you + don't. */ +#define HAVE_DECL_UINT32_MAX 1 + +/* Define to 1 if you have the declaration of `UINT64_MAX', and to 0 if you + don't. */ +#define HAVE_DECL_UINT64_MAX 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#define HAVE_DIRENT_H 1 + +/* Define to 1 if you have the `dirfd' function. */ +/* #undef HAVE_DIRFD */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DLFCN_H */ + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +/* #undef HAVE_DOPRNT */ + +/* Define to 1 if nl_langinfo supports D_MD_ORDER */ +/* #undef HAVE_D_MD_ORDER */ + +/* A possible errno value for invalid file format errors */ +/* #undef HAVE_EFTYPE */ + +/* A possible errno value for invalid file format errors */ +#define HAVE_EILSEQ 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_EXPAT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_EXT2FS_EXT2_FS_H */ + +/* Define to 1 if you have the `extattr_get_file' function. */ +/* #undef HAVE_EXTATTR_GET_FILE */ + +/* Define to 1 if you have the `extattr_list_file' function. */ +/* #undef HAVE_EXTATTR_LIST_FILE */ + +/* Define to 1 if you have the `extattr_set_fd' function. */ +/* #undef HAVE_EXTATTR_SET_FD */ + +/* Define to 1 if you have the `extattr_set_file' function. */ +/* #undef HAVE_EXTATTR_SET_FILE */ + +/* Define to 1 if you have the `fchdir' function. */ +/* #undef HAVE_FCHDIR */ + +/* Define to 1 if you have the `fchflags' function. */ +/* #undef HAVE_FCHFLAGS */ + +/* Define to 1 if you have the `fchmod' function. */ +/* #undef HAVE_FCHMOD */ + +/* Define to 1 if you have the `fchown' function. */ +/* #undef HAVE_FCHOWN */ + +/* Define to 1 if you have the `fcntl' function. */ +/* #undef HAVE_FCNTL */ + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `fdopendir' function. */ +/* #undef HAVE_FDOPENDIR */ + +/* Define to 1 if you have the `fgetea' function. */ +/* #undef HAVE_FGETEA */ + +/* Define to 1 if you have the `fgetxattr' function. */ +/* #undef HAVE_FGETXATTR */ + +/* Define to 1 if you have the `flistea' function. */ +/* #undef HAVE_FLISTEA */ + +/* Define to 1 if you have the `flistxattr' function. */ +/* #undef HAVE_FLISTXATTR */ + +/* Define to 1 if you have the `fork' function. */ +/* #undef HAVE_FORK */ + +/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ +#define HAVE_FSEEKO 1 + +/* Define to 1 if you have the `fsetea' function. */ +/* #undef HAVE_FSETEA */ + +/* Define to 1 if you have the `fsetxattr' function. */ +/* #undef HAVE_FSETXATTR */ + +/* Define to 1 if you have the `fstat' function. */ +#define HAVE_FSTAT 1 + +/* Define to 1 if you have the `fstatat' function. */ +/* #undef HAVE_FSTATAT */ + +/* Define to 1 if you have the `fstatfs' function. */ +/* #undef HAVE_FSTATFS */ + +/* Define to 1 if you have the `fstatvfs' function. */ +/* #undef HAVE_FSTATVFS */ + +/* Define to 1 if you have the `ftruncate' function. */ +#define HAVE_FTRUNCATE 1 + +/* Define to 1 if you have the `futimens' function. */ +/* #undef HAVE_FUTIMENS */ + +/* Define to 1 if you have the `futimes' function. */ +/* #undef HAVE_FUTIMES */ + +/* Define to 1 if you have the `futimesat' function. */ +/* #undef HAVE_FUTIMESAT */ + +/* Define to 1 if you have the `getea' function. */ +/* #undef HAVE_GETEA */ + +/* Define to 1 if you have the `geteuid' function. */ +/* #undef HAVE_GETEUID */ + +/* Define to 1 if you have the `getgrgid_r' function. */ +/* #undef HAVE_GETGRGID_R */ + +/* Define to 1 if you have the `getgrnam_r' function. */ +/* #undef HAVE_GETGRNAM_R */ + +/* Define to 1 if you have the `getpid' function. */ +#define HAVE_GETPID 1 + +/* Define to 1 if you have the `getpwnam_r' function. */ +/* #undef HAVE_GETPWNAM_R */ + +/* Define to 1 if you have the `getpwuid_r' function. */ +/* #undef HAVE_GETPWUID_R */ + +/* Define to 1 if you have the `getvfsbyname' function. */ +/* #undef HAVE_GETVFSBYNAME */ + +/* Define to 1 if you have the `getxattr' function. */ +/* #undef HAVE_GETXATTR */ + +/* Define to 1 if you have the `gmtime_r' function. */ +/* #undef HAVE_GMTIME_R */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GRP_H */ + +/* Define if you have the iconv() function and it works. */ +/* #undef HAVE_ICONV */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ICONV_H */ + +/* Define to 1 if the system has the type `intmax_t'. */ +#define HAVE_INTMAX_T 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_IO_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LANGINFO_H */ + +/* Define to 1 if you have the `lchflags' function. */ +/* #undef HAVE_LCHFLAGS */ + +/* Define to 1 if you have the `lchmod' function. */ +/* #undef HAVE_LCHMOD */ + +/* Define to 1 if you have the `lchown' function. */ +/* #undef HAVE_LCHOWN */ + +/* Define to 1 if you have the `lgetea' function. */ +/* #undef HAVE_LGETEA */ + +/* Define to 1 if you have the `lgetxattr' function. */ +/* #undef HAVE_LGETXATTR */ + +/* Define to 1 if you have the `acl' library (-lacl). */ +/* #undef HAVE_LIBACL */ + +/* Define to 1 if you have the `attr' library (-lattr). */ +/* #undef HAVE_LIBATTR */ + +/* Define to 1 if you have the `bz2' library (-lbz2). */ +/* #undef HAVE_LIBBZ2 */ + +/* Define to 1 if you have the `charset' library (-lcharset). */ +/* #undef HAVE_LIBCHARSET */ + +/* Define to 1 if you have the `crypto' library (-lcrypto). */ +/* #undef HAVE_LIBCRYPTO */ + +/* Define to 1 if you have the `eay32' library (-leay32). */ +/* #undef HAVE_LIBEAY32 */ + +/* Define to 1 if you have the `eay64' library (-leay64). */ +/* #undef HAVE_LIBEAY64 */ + +/* Define to 1 if you have the `expat' library (-lexpat). */ +/* #undef HAVE_LIBEXPAT */ + +/* Define to 1 if you have the `lz4' library (-llz4). */ +/* #undef HAVE_LIBLZ4 */ + +/* Define to 1 if you have the `lzma' library (-llzma). */ +/* #undef HAVE_LIBLZMA */ + +/* Define to 1 if you have the `lzo2' library (-llzo2). */ +/* #undef HAVE_LIBLZO2 */ + +/* Define to 1 if you have the `md' library (-lmd). */ +/* #undef HAVE_LIBMD */ + +/* Define to 1 if you have the `nettle' library (-lnettle). */ +/* #undef HAVE_LIBNETTLE */ + +/* Define to 1 if you have the `pcre' library (-lpcre). */ +/* #undef HAVE_LIBPCRE */ + +/* Define to 1 if you have the `pcreposix' library (-lpcreposix). */ +/* #undef HAVE_LIBPCREPOSIX */ + +/* Define to 1 if you have the `regex' library (-lregex). */ +/* #undef HAVE_LIBREGEX */ + +/* Define to 1 if you have the `xml2' library (-lxml2). */ +/* #undef HAVE_LIBXML2 */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBXML_XMLREADER_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBXML_XMLWRITER_H */ + +/* Define to 1 if you have the `z' library (-lz). */ +/* #undef HAVE_LIBZ */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the `link' function. */ +/* #undef HAVE_LINK */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LINUX_FIEMAP_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LINUX_FS_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LINUX_MAGIC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LINUX_TYPES_H */ + +/* Define to 1 if you have the `listea' function. */ +/* #undef HAVE_LISTEA */ + +/* Define to 1 if you have the `listxattr' function. */ +/* #undef HAVE_LISTXATTR */ + +/* Define to 1 if you have the `llistea' function. */ +/* #undef HAVE_LLISTEA */ + +/* Define to 1 if you have the `llistxattr' function. */ +/* #undef HAVE_LLISTXATTR */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LOCALCHARSET_H */ + +/* Define to 1 if you have the `locale_charset' function. */ +/* #undef HAVE_LOCALE_CHARSET */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define to 1 if you have the `localtime_r' function. */ +/* #undef HAVE_LOCALTIME_R */ + +/* Define to 1 if the system has the type `long long int'. */ +#define HAVE_LONG_LONG_INT 1 + +/* Define to 1 if you have the `lsetea' function. */ +/* #undef HAVE_LSETEA */ + +/* Define to 1 if you have the `lsetxattr' function. */ +/* #undef HAVE_LSETXATTR */ + +/* Define to 1 if you have the `lstat' function. */ +/* #undef HAVE_LSTAT */ + +/* Define to 1 if `lstat' has the bug that it succeeds when given the + zero-length file name argument. */ +#define HAVE_LSTAT_EMPTY_STRING_BUG 1 + +/* Define to 1 if you have the `lutimes' function. */ +/* #undef HAVE_LUTIMES */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LZ4HC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LZ4_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LZMADEC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LZMA_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LZO_LZO1X_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LZO_LZOCONF_H */ + +/* Define to 1 if you have the `mbrtowc' function. */ +#define HAVE_MBRTOWC 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_MD5_H */ + +/* Define to 1 if you have the `memmove' function. */ +#define HAVE_MEMMOVE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `memset' function. */ +#define HAVE_MEMSET 1 + +/* Define to 1 if you have the `mkdir' function. */ +#define HAVE_MKDIR 1 + +/* Define to 1 if you have the `mkfifo' function. */ +/* #undef HAVE_MKFIFO */ + +/* Define to 1 if you have the `mknod' function. */ +/* #undef HAVE_MKNOD */ + +/* Define to 1 if you have the `mkstemp' function. */ +/* #undef HAVE_MKSTEMP */ + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +/* #undef HAVE_NDIR_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETTLE_MD5_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETTLE_PBKDF2_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETTLE_RIPEMD160_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETTLE_SHA_H */ + +/* Define to 1 if you have the `nl_langinfo' function. */ +/* #undef HAVE_NL_LANGINFO */ + +/* Define to 1 if you have the `openat' function. */ +/* #undef HAVE_OPENAT */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_EVP_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PATHS_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PCREPOSIX_H */ + +/* Define to 1 if you have the `pipe' function. */ +/* #undef HAVE_PIPE */ + +/* Define to 1 if you have the `PKCS5_PBKDF2_HMAC_SHA1' function. */ +/* #undef HAVE_PKCS5_PBKDF2_HMAC_SHA1 */ + +/* Define to 1 if you have the `poll' function. */ +/* #undef HAVE_POLL */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_POLL_H */ + +/* Define to 1 if you have the `posix_spawnp' function. */ +/* #undef HAVE_POSIX_SPAWNP */ + +/* Define to 1 if you have the header file. */ +#define HAVE_PTHREAD_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PWD_H */ + +/* Define to 1 if you have a POSIX compatible readdir_r */ +#define HAVE_READDIR_R 1 + +/* Define to 1 if you have the `readlink' function. */ +/* #undef HAVE_READLINK */ + +/* Define to 1 if you have the `readlinkat' function. */ +/* #undef HAVE_READLINKAT */ + +/* Define to 1 if you have the `readpassphrase' function. */ +/* #undef HAVE_READPASSPHRASE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_READPASSPHRASE_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_REGEX_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_RIPEMD_H */ + +/* Define to 1 if you have the `select' function. */ +/* #undef HAVE_SELECT */ + +/* Define to 1 if you have the `setenv' function. */ +/* #undef HAVE_SETENV */ + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SHA256_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SHA512_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SHA_H */ + +/* Define to 1 if you have the `sigaction' function. */ +/* #undef HAVE_SIGACTION */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SPAWN_H */ + +/* Define to 1 if you have the `statfs' function. */ +/* #undef HAVE_STATFS */ + +/* Define to 1 if you have the `statvfs' function. */ +/* #undef HAVE_STATVFS */ + +/* Define to 1 if `stat' has the bug that it succeeds when given the + zero-length file name argument. */ +#define HAVE_STAT_EMPTY_STRING_BUG 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDARG_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strchr' function. */ +#define HAVE_STRCHR 1 + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the `strerror_r' function. */ +/* #undef HAVE_STRERROR_R */ + +/* Define to 1 if you have the `strftime' function. */ +#define HAVE_STRFTIME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strncpy_s' function. */ +#define HAVE_STRNCPY_S 1 + +/* Define to 1 if you have the `strrchr' function. */ +#define HAVE_STRRCHR 1 + +/* Define to 1 if `f_namemax' is a member of `struct statfs'. */ +/* #undef HAVE_STRUCT_STATFS_F_NAMEMAX */ + +/* Define to 1 if `f_iosize' is a member of `struct statvfs'. */ +/* #undef HAVE_STRUCT_STATVFS_F_IOSIZE */ + +/* Define to 1 if `st_birthtime' is a member of `struct stat'. */ +/* #undef HAVE_STRUCT_STAT_ST_BIRTHTIME */ + +/* Define to 1 if `st_birthtimespec.tv_nsec' is a member of `struct stat'. */ +/* #undef HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC */ + +/* Define to 1 if `st_blksize' is a member of `struct stat'. */ +/* #undef HAVE_STRUCT_STAT_ST_BLKSIZE */ + +/* Define to 1 if `st_flags' is a member of `struct stat'. */ +/* #undef HAVE_STRUCT_STAT_ST_FLAGS */ + +/* Define to 1 if `st_mtimespec.tv_nsec' is a member of `struct stat'. */ +/* #undef HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC */ + +/* Define to 1 if `st_mtime_n' is a member of `struct stat'. */ +/* #undef HAVE_STRUCT_STAT_ST_MTIME_N */ + +/* Define to 1 if `st_mtime_usec' is a member of `struct stat'. */ +/* #undef HAVE_STRUCT_STAT_ST_MTIME_USEC */ + +/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */ +/* #undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC */ + +/* Define to 1 if `st_umtime' is a member of `struct stat'. */ +/* #undef HAVE_STRUCT_STAT_ST_UMTIME */ + +/* Define to 1 if `tm_gmtoff' is a member of `struct tm'. */ +/* #undef HAVE_STRUCT_TM_TM_GMTOFF */ + +/* Define to 1 if `__tm_gmtoff' is a member of `struct tm'. */ +/* #undef HAVE_STRUCT_TM___TM_GMTOFF */ + +/* Define to 1 if you have the `symlink' function. */ +/* #undef HAVE_SYMLINK */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_ACL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_CDEFS_H 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_DIR_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_EA_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_EXTATTR_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_IOCTL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_MKDEV_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_MOUNT_H */ + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_NDIR_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_POLL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SELECT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_STATFS_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_STATVFS_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UTIME_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_UTSNAME_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_VFS_H */ + +/* Define to 1 if you have that is POSIX.1 compatible. */ +/* #undef HAVE_SYS_WAIT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_XATTR_H */ + +/* Define to 1 if you have the `timegm' function. */ +/* #undef HAVE_TIMEGM */ + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the `tzset' function. */ +#define HAVE_TZSET 1 + +/* Define to 1 if the system has the type `uintmax_t'. */ +#define HAVE_UINTMAX_T 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `unsetenv' function. */ +/* #undef HAVE_UNSETENV */ + +/* Define to 1 if the system has the type `unsigned long long'. */ +#define HAVE_UNSIGNED_LONG_LONG 1 + +/* Define to 1 if the system has the type `unsigned long long int'. */ +#define HAVE_UNSIGNED_LONG_LONG_INT 1 + +/* Define to 1 if you have the `utime' function. */ +#define HAVE_UTIME 1 + +/* Define to 1 if you have the `utimensat' function. */ +/* #undef HAVE_UTIMENSAT */ + +/* Define to 1 if you have the `utimes' function. */ +/* #undef HAVE_UTIMES */ + +/* Define to 1 if you have the header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if you have the `vfork' function. */ +/* #undef HAVE_VFORK */ + +/* Define to 1 if you have the `vprintf' function. */ +#define HAVE_VPRINTF 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_WCHAR_H 1 + +/* Define to 1 if the system has the type `wchar_t'. */ +#define HAVE_WCHAR_T 1 + +/* Define to 1 if you have the `wcrtomb' function. */ +#define HAVE_WCRTOMB 1 + +/* Define to 1 if you have the `wcscmp' function. */ +#define HAVE_WCSCMP 1 + +/* Define to 1 if you have the `wcscpy' function. */ +#define HAVE_WCSCPY 1 + +/* Define to 1 if you have the `wcslen' function. */ +#define HAVE_WCSLEN 1 + +/* Define to 1 if you have the `wctomb' function. */ +#define HAVE_WCTOMB 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_WCTYPE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_WINCRYPT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_WINDOWS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_WINIOCTL_H 1 + +/* Define to 1 if you have the `wmemcmp' function. */ +#define HAVE_WMEMCMP 1 + +/* Define to 1 if you have the `wmemcpy' function. */ +#define HAVE_WMEMCPY 1 + +/* Define to 1 if you have a working EXT2_IOC_GETFLAGS */ +/* #undef HAVE_WORKING_EXT2_IOC_GETFLAGS */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ZLIB_H */ + +/* Define to 1 if you have the `_ctime64_s' function. */ +#define HAVE__CTIME64_S 1 + +/* Define to 1 if you have the `_fseeki64' function. */ +#define HAVE__FSEEKI64 1 + +/* Define to 1 if you have the `_get_timezone' function. */ +/* #undef HAVE__GET_TIMEZONE */ + +/* Define to 1 if you have the `_localtime64_s' function. */ +#define HAVE__LOCALTIME64_S 1 + +/* Define to 1 if you have the `_mkgmtime64' function. */ +/* #define HAVE__MKGMTIME64 1 */ + +/* Define as const if the declaration of iconv() needs const. */ +/* #undef ICONV_CONST */ + +/* Define to 1 if `lstat' dereferences a symlink specified with a trailing + slash. */ +/* #undef LSTAT_FOLLOWS_SLASHED_SYMLINK */ + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ + +/* Define to 1 if `major', `minor', and `makedev' are declared in . + */ +/* #undef MAJOR_IN_MKDEV */ + +/* Define to 1 if `major', `minor', and `makedev' are declared in + . */ +/* #undef MAJOR_IN_SYSMACROS */ + + +/* Define to 1 if PCRE_STATIC needs to be defined. */ +/* #undef PCRE_STATIC */ + +/* The size of `wchar_t', as computed by sizeof. */ +#define SIZEOF_WCHAR_T 2 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if strerror_r returns char *. */ +/* #undef STRERROR_R_CHAR_P */ + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + + + +/* Define to '0x0500' for Windows 2000 APIs. */ +#define WINVER 0x0500 + +/* Number of bits in a file offset, on hosts where this is settable. */ +#define _FILE_OFFSET_BITS 64 + +/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ +/* #undef _LARGEFILE_SOURCE */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to 1 if on MINIX. */ +/* #undef _MINIX */ + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +/* #undef _POSIX_1_SOURCE */ + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +/* #undef _POSIX_SOURCE */ + +/* Define for Solaris 2.5.1 so the uint32_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT32_T */ + +/* Define for Solaris 2.5.1 so the uint64_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT64_T */ + +/* Define for Solaris 2.5.1 so the uint8_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT8_T */ + +/* Define to '0x0500' for Windows 2000 APIs. */ +#define _WIN32_WINNT 0x0500 + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to match typeof st_gid field of struct stat if doesn't + define. */ +#define gid_t short + +/* Define to `unsigned long' if does not define. */ +#define id_t unsigned long + +/* Define to the type of a signed integer type of width exactly 16 bits if + such a type exists and the standard includes do not define it. */ +/* #undef int16_t */ + +/* Define to the type of a signed integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +/* #undef int32_t */ + +/* Define to the type of a signed integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +/* #undef int64_t */ + +/* Define to the widest signed integer type if and do + not define. */ +/* #undef intmax_t */ + +/* Define to `int' if does not define. */ +/* #undef mode_t */ + +/* Define to `long long' if does not define. */ +/* #undef off_t */ + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* Define to match typeof st_uid field of struct stat if doesn't + define. */ +#define uid_t short + +/* Define to the type of an unsigned integer type of width exactly 16 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint16_t */ + +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint32_t */ + +/* Define to the type of an unsigned integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint64_t */ + +/* Define to the type of an unsigned integer type of width exactly 8 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint8_t */ + +/* Define to the widest unsigned integer type if and + do not define. */ +/* #undef uintmax_t */ + +/* Define to `unsigned int' if does not define. */ +/* #undef uintptr_t */ diff --git a/dependencies/libarchive-3.4.2/contrib/android/include/Bcrypt.h b/dependencies/libarchive-3.4.2/contrib/android/include/Bcrypt.h new file mode 100644 index 0000000..df29599 --- /dev/null +++ b/dependencies/libarchive-3.4.2/contrib/android/include/Bcrypt.h @@ -0,0 +1 @@ +#include diff --git a/dependencies/libarchive-3.4.2/contrib/android/include/Windows.h b/dependencies/libarchive-3.4.2/contrib/android/include/Windows.h new file mode 100644 index 0000000..776a87c --- /dev/null +++ b/dependencies/libarchive-3.4.2/contrib/android/include/Windows.h @@ -0,0 +1 @@ +#include diff --git a/dependencies/libarchive-3.4.2/contrib/android/include/android_lf.h b/dependencies/libarchive-3.4.2/contrib/android/include/android_lf.h new file mode 100644 index 0000000..3c5475e --- /dev/null +++ b/dependencies/libarchive-3.4.2/contrib/android/include/android_lf.h @@ -0,0 +1,47 @@ +/* + * Macros for file64 functions + * + * Android does not support the macro _FILE_OFFSET_BITS=64 + * As of android-21 it does however support many file64 functions +*/ + +#ifndef ARCHIVE_ANDROID_LF_H_INCLUDED +#define ARCHIVE_ANDROID_LF_H_INCLUDED + +#if __ANDROID_API__ > 20 + +#include +#include +#include +#include +#include +#include +#include + +//dirent.h +#define readdir_r readdir64_r +#define readdir readdir64 +#define dirent dirent64 +//fcntl.h +#define openat openat64 +#define open open64 +#define mkstemp mkstemp64 +//unistd.h +#define lseek lseek64 +#define ftruncate ftruncate64 +//sys/stat.h +#define fstatat fstatat64 +#define fstat fstat64 +#define lstat lstat64 +#define stat stat64 +//sys/statvfs.h +#define fstatvfs fstatvfs64 +#define statvfs statvfs64 +//sys/types.h +#define off_t off64_t +//sys/vfs.h +#define fstatfs fstatfs64 +#define statfs statfs64 +#endif + +#endif /* ARCHIVE_ANDROID_LF_H_INCLUDED */ diff --git a/dependencies/libarchive-3.4.2/contrib/archivetest.c b/dependencies/libarchive-3.4.2/contrib/archivetest.c new file mode 100644 index 0000000..e4a25e3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/contrib/archivetest.c @@ -0,0 +1,224 @@ +/*- + * Copyright (c) 2019 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Archivetest verifies reading archives with libarchive + * + * It may be used to reproduce failures in testcases discovered by OSS-Fuzz + * https://github.com/google/oss-fuzz/blob/master/projects/libarchive + */ + +#include +#include +#include +#include +#include +#include + +#if defined __MINGW32__ +#include +#endif + +static const char *errnostr(int e) +{ + char *estr; + switch(e) { + case ARCHIVE_EOF: + estr = "ARCHIVE_EOF"; + break; + case ARCHIVE_OK: + estr = "ARCHIVE_OK"; + break; + case ARCHIVE_WARN: + estr = "ARCHIVE_WARN"; + break; + case ARCHIVE_RETRY: + estr = "ARCHIVE_RETRY"; + break; + case ARCHIVE_FAILED: + estr = "ARCHIVE_FAILED"; + break; + case ARCHIVE_FATAL: + estr = "ARCHIVE_FATAL"; + break; + default: + estr = "Unknown"; + break; + } + return (estr); +} + +static void usage(const char *prog) +{ + fprintf(stderr, "Usage: %s [-f filename] [-h] [-q] [-s]\n", prog); +} + +static void printhelp() +{ + fprintf(stdout, "archivetest: verify reading archives with " + "libarchive\n\n" + "Options:\n" + " -f filename Filename to verify\n" + " -h Show this help\n" + " -q Quiet mode\n" + " -s Verify only headers (skip data)\n\n" + "If no filename is specified, data is read from standard input.\n" + "\n%s\n", archive_version_details()); +} + +static int v_print(int verbose, const char *format, ...) +{ + int r = 0; + + if (verbose) { + va_list args; + + va_start(args, format); + r = vfprintf(stdout, format, args); + va_end(args); + } + return (r); +} + +int main(int argc, char *argv[]) +{ + struct archive *a; + struct archive_entry *entry; + char *filename; + const char *p; + char buffer[4096]; + int c; + int v, skip_data; + int r = ARCHIVE_OK; + int format_printed; + + filename = NULL; + skip_data = 0; + v = 1; + + while ((c = getopt (argc, argv, "f:hqs")) != -1) { + switch (c) { + case 'f': + filename = optarg; + break; + case 'h': + printhelp(); + exit(0); + case 'q': + v = 0; + break; + case 's': + skip_data = 1; + break; + case '?': + if (optopt == 'f') + fprintf(stderr, "Option -%c requires " + "an argument.\n", optopt); + else if (isprint(optopt)) + fprintf(stderr, "Unknown option '-%c'" + ".\n", optopt); + else + fprintf(stderr, "Unknown option " + "character '\\x%x'.\n", optopt); + usage(argv[0]); + exit(1); + break; + default: + exit(1); + } + } + + a = archive_read_new(); + + archive_read_support_filter_all(a); + archive_read_support_format_all(a); + + v_print(v, "Data source: "); + + if (filename == NULL) { + v_print(v, "standard input\n"); + r = archive_read_open_fd(a, STDIN_FILENO, 4096); + } else { + v_print(v, "filename: %s\n", filename); + r = archive_read_open_filename(a, filename, 4096); + } + + if (r != ARCHIVE_OK) { + archive_read_free(a); + fprintf(stderr, "Invalid or unsupported data source\n"); + exit(1); + } + + format_printed = 0; + c = 1; + + while (1) { + r = archive_read_next_header(a, &entry); + if (r == ARCHIVE_FATAL) { + v_print(v, "Entry %d: fatal error reading " + "header\n", c); + break; + } + if (!format_printed) { + v_print(v, "Filter: %s\nFormat: %s\n", + archive_filter_name(a, 0), archive_format_name(a)); + format_printed = 1; + } + if (r == ARCHIVE_RETRY) + continue; + if (r == ARCHIVE_EOF) + break; + p = archive_entry_pathname(entry); + v_print(v, "Entry %d: %s, pathname", c, errnostr(r)); + if (p == NULL || p[0] == '\0') + v_print(v, " unreadable"); + else + v_print(v, ": %s", p); + v_print(v, ", data: "); + if (skip_data) { + v_print(v, "skipping"); + } else { + while ((r = archive_read_data(a, buffer, 4096) > 0)) + ; + if (r == ARCHIVE_FATAL) { + v_print(v, "ERROR\nError string: %s\n", + archive_error_string(a)); + break; + } + v_print(v, "OK"); + } + v_print(v, "\n"); + c++; + } + + v_print(v, "Last return code: %s (%d)\n", errnostr(r), r); + if (r == ARCHIVE_EOF || r == ARCHIVE_OK) { + archive_read_free(a); + exit(0); + } + v_print(v, "Error string: %s\n", archive_error_string(a)); + archive_read_free(a); + exit(2); +} diff --git a/dependencies/libarchive-3.4.2/contrib/libarchive.1aix53.spec b/dependencies/libarchive-3.4.2/contrib/libarchive.1aix53.spec new file mode 100644 index 0000000..fe81d14 --- /dev/null +++ b/dependencies/libarchive-3.4.2/contrib/libarchive.1aix53.spec @@ -0,0 +1,160 @@ +# $LastChangedRevision$, $LastChangedDate$ +Summary: Library to create and read several different archive formats +Summary(pl): Biblioteka do tworzenia i odczytu ró¿nych formatów archiwów +Name: libarchive +Version: 2.0a3 +Release: 1aix53 +License: BSD +Group: Libraries +Source0: http://people.freebsd.org/~kientzle/libarchive/src/%{name}-%{version}.tar.gz +Patch: %{name}-0123457890.patch +URL: http://people.freebsd.org/~kientzle/libarchive/ +Requires: glibc +Requires: zlib +Requires: bzip2 +BuildRequires: gcc +BuildRequires: gcc-c++ +BuildRequires: gawk +BuildRequires: zlib-devel +BuildRequires: bzip2 +BuildRoot: %{_tmppath}/%{name}-%{version}-build + +%description +Libarchive is a programming library that can create and read several +different streaming archive formats, including most popular TAR +variants and several CPIO formats. It can also write SHAR archives. + +%description -l pl +Libarchive jest bibliotek± s³u¿ac± to tworzenia i odczytu wielu +ró¿nych strumieniowych formatów archiwów, w³±czaj±c w to popularne +odmiany TAR oraz wiele formatów CPIO. Biblioteka ta potrafi tak¿e +zapisywaæ archiwa SHAR. + +%package devel +Summary: Header files for libarchive library +Summary(pl): Pliki nag³ówkowe biblioteki libarchive +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} + +%description devel +Header files for libarchive library. + +%description devel -l pl +Pliki nag³ówkowe biblioteki libarchive. + +%package static +Summary: Static libarchive library +Summary(pl): Statyczna biblioteka libarchive +Group: Development/Libraries +Requires: %{name}-devel = %{version}-%{release} + +%description static +Static libarchive library. + +%description static -l pl +Statyczna biblioteka libarchive. + +%package -n bsdtar +Summary: bsdtar - tar(1) implementation based on libarchive +Summary(pl): bsdtar - implementacja programu tar(1) oparta na libarchive +Group: Applications/Archiving +Requires: %{name} = %{version}-%{release} + +%description -n bsdtar +bsdtar - tar(1) implementation based on libarchive. + +%description -n bsdtar -l pl +bsdtar - implementacja programu tar(1), oparta na libarchive. + +%prep +%setup -q +%patch0 -p1 + +%build +# Specify paths to avoid use of vacpp +# -maix64 - required to use large files with aix-5.3 +# -static - required for interoperability without copying libraries +# -D_BSD - required to include definition of makedev +# -X64 - required to assemble 64-bit COFF files +mkdir -p %{buildroot} +PATH=/opt/freeware/libexec:/opt/freeware/bin:/usr/local/bin:/usr/bin:/etc:/usr/sbin:/usr/ucb:/usr/bin/X11:/sbin:. \ +CPATH=/opt/freeware/include:/usr/local/include \ +LIBPATH=/opt/freeware/lib:/usr/local/lib:/usr/share/lib \ +LD_LIBRARY_PATH=/opt/freeware/lib:/usr/local/lib:/usr/share/lib \ +CFLAGS="$RPM_OPT_FLAGS -maix64 -static -D_BSD" \ +CXXFLAGS="$RPM_OPT_FLAGS -maix64 -static -D_BSD" \ +AR="ar -X64" \ +./configure \ +--prefix=%{_prefix} \ +--libexecdir=%{_libexecdir} \ +--mandir=%{_mandir} \ +--infodir=%{_infodir} \ +--enable-shared=yes \ +--enable-static=yes \ +| tee %{buildroot}/config.log +make | tee %{buildroot}/make.log + +%install +[ "%buildroot" != "/" ] && [ -d %buildroot ] && rm -rf %buildroot; +make DESTDIR=%buildroot install +# original install builds, but does install bsdtar +cp .libs/%{name}.a %{buildroot}%{_libdir} +cp bsdtar %{buildroot}%{_bindir} +cp tar/bsdtar.1 %{buildroot}%{_mandir}/man1 + +%clean +rm -fr %buildroot + +%files +%defattr(644,root,root,755) +%{_libdir}/libarchive.a + +%files devel +%defattr(644,root,root,755) +%{_libdir}/libarchive.la +%{_includedir}/*.h +%doc %{_mandir}/man3/* +%doc %{_mandir}/man5/* + +%files -n bsdtar +%defattr(644,root,root,755) +%attr(755,root,root) %{_bindir}/bsdtar +%doc %{_mandir}/man1/bsdtar.1* + +%define date %(echo `LC_ALL="C" date +"%a %b %d %Y"`) +%changelog +* %{date} PLD Team +All persons listed below can be reached at @pld-linux.org + +$Log: libarchive.spec,v $ +Release 1aix53 2006/12/12 rm1023@dcx.com +- tweak for aix-5.3 +- added libarchive-0123457890.patch for "0123457890" error +- replaced libarchive-1.3.1.tar.gz with libarchive-2.0a3.tar.gz +- removed obsolete -CVE-2006-5680.patch and -man_progname.patch + +Revision 1.6 2006/11/15 10:41:28 qboosh +- BR: acl-devel,attr-devel +- devel deps + +Revision 1.5 2006/11/08 22:22:25 twittner +- up to 1.3.1 +- added BR: e2fsprogs-devel +- added -CVE-2006-5680.patch against entering an infinite +loop in corrupt archives +- added bsdtar package (bsdtar is included now in libarchive +sources) +- rel. 0.1 for testing + +Revision 1.4 2005/12/15 18:26:36 twittner +- up to 1.2.37 +- removed -shared.patch (no longer needed) + +Revision 1.3 2005/10/05 17:00:12 arekm +- up to 1.02.034 + +Revision 1.2 2005/07/27 20:17:21 qboosh +- typo + +Revision 1.1 2005/07/27 08:36:03 adamg +- new diff --git a/dependencies/libarchive-3.4.2/contrib/libarchive.spec b/dependencies/libarchive-3.4.2/contrib/libarchive.spec new file mode 100644 index 0000000..211b391 --- /dev/null +++ b/dependencies/libarchive-3.4.2/contrib/libarchive.spec @@ -0,0 +1,216 @@ +Name: {{{ git_name }}} +Version: {{{ git_version lead=3 follow=4 }}} +Release: 1%{?dist} +Summary: A library for handling streaming archive formats + +License: BSD +URL: http://www.libarchive.org/ +Source: {{{ git_pack }}} + +VCS: {{{ git_vcs }}} + +BuildRequires: automake +BuildRequires: bison +BuildRequires: bzip2-devel +BuildRequires: e2fsprogs-devel +BuildRequires: gcc +BuildRequires: libacl-devel +BuildRequires: libattr-devel +BuildRequires: libtool +BuildRequires: libxml2-devel +BuildRequires: libzstd-devel +BuildRequires: lz4-devel +BuildRequires: lzo-devel +BuildRequires: openssl-devel +BuildRequires: sharutils +BuildRequires: xz-devel +BuildRequires: zlib-devel + +%description +Libarchive is a programming library that can create and read several different +streaming archive formats, including most popular tar variants, several cpio +formats, and both BSD and GNU ar variants. It can also write shar archives and +read ISO9660 CDROM images and ZIP archives. + + +%package devel +Summary: Development files for %{name} +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description devel +The %{name}-devel package contains libraries and header files for +developing applications that use %{name}. + + +%package -n bsdtar +Summary: Manipulate tape archives +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description -n bsdtar +The bsdtar package contains standalone bsdtar utility split off regular +libarchive packages. + + +%package -n bsdcpio +Summary: Copy files to and from archives +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description -n bsdcpio +The bsdcpio package contains standalone bsdcpio utility split off regular +libarchive packages. + + +%package -n bsdcat +Summary: Expand files to standard output +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description -n bsdcat +The bsdcat program typically takes a filename as an argument or reads standard +input when used in a pipe. In both cases decompressed data it written to +standard output. + + +%prep +{{{ git_setup_macro }}} +%autosetup -p1 + + +%build +build/autogen.sh +%configure --disable-static --without-nettle LT_SYS_LIBRARY_PATH=%_libdir +%make_build + + +%install +make install DESTDIR=$RPM_BUILD_ROOT +find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';' + +# rhbz#1294252 +replace () +{ + filename=$1 + file=`basename "$filename"` + binary=${file%%.*} + pattern=${binary##bsd} + + awk " + # replace the topic + /^.Dt ${pattern^^} 1/ { + print \".Dt ${binary^^} 1\"; + next; + } + # replace the first occurence of \"$pattern\" by \"$binary\" + !stop && /^.Nm $pattern/ { + print \".Nm $binary\" ; + stop = 1 ; + next; + } + # print remaining lines + 1; + " "$filename" > "$filename.new" + mv "$filename".new "$filename" +} + +for manpage in bsdtar.1 bsdcpio.1 +do + installed_manpage=`find "$RPM_BUILD_ROOT" -name "$manpage"` + replace "$installed_manpage" +done + + +%check +%if %{with check} +logfiles () +{ + find -name '*_test.log' -or -name test-suite.log +} + +tempdirs () +{ + cat `logfiles` \ + | awk "match(\$0, /[^[:space:]]*`date -I`[^[:space:]]*/) { print substr(\$0, RSTART, RLENGTH); }" \ + | sort | uniq +} + +cat_logs () +{ + for i in `logfiles` + do + echo "=== $i ===" + cat "$i" + done +} + +run_testsuite () +{ + rc=0 + %make_build check -j1 || { + # error happened - try to extract in koji as much info as possible + cat_logs + + for i in `tempdirs`; do + if test -d "$i" ; then + find $i -printf "%p\n ~> a: %a\n ~> c: %c\n ~> t: %t\n ~> %s B\n" + cat $i/*.log + fi + done + return 1 + } + cat_logs +} + +# On a ppc/ppc64 is some race condition causing 'make check' fail on ppc +# when both 32 and 64 builds are done in parallel on the same machine in +# koji. Try to run once again if failed. +%ifarch ppc +run_testsuite || run_testsuite +%else +run_testsuite +%endif +%endif + + +%files +%{!?_licensedir:%global license %%doc} +%license COPYING +%doc NEWS README.md +%{_libdir}/libarchive.so.13* +%{_mandir}/*/cpio.* +%{_mandir}/*/mtree.* +%{_mandir}/*/tar.* + +%files devel +%{_includedir}/*.h +%{_mandir}/*/archive* +%{_mandir}/*/libarchive* +%{_libdir}/libarchive.so +%{_libdir}/pkgconfig/libarchive.pc + +%files -n bsdtar +%{!?_licensedir:%global license %%doc} +%license COPYING +%doc NEWS README.md +%{_bindir}/bsdtar +%{_mandir}/*/bsdtar* + +%files -n bsdcpio +%{!?_licensedir:%global license %%doc} +%license COPYING +%doc NEWS README.md +%{_bindir}/bsdcpio +%{_mandir}/*/bsdcpio* + +%files -n bsdcat +%{!?_licensedir:%global license %%doc} +%license COPYING +%doc NEWS README.md +%{_bindir}/bsdcat +%{_mandir}/*/bsdcat* + + + +%changelog +* Thu Mar 28 2019 Pavel Raiskup - 3.3.3-7 +- simplify libtool hacks + +{{ git_changelog }} diff --git a/dependencies/libarchive-3.4.2/contrib/libarchive_autodetect-st_lib_archive.m4 b/dependencies/libarchive-3.4.2/contrib/libarchive_autodetect-st_lib_archive.m4 new file mode 100644 index 0000000..4419e88 --- /dev/null +++ b/dependencies/libarchive-3.4.2/contrib/libarchive_autodetect-st_lib_archive.m4 @@ -0,0 +1,154 @@ +dnl +dnl @synopsis ST_LIB_ARCHIVE([ENABLED-DEFAULT]) +dnl +dnl This macro figures out what's necessary to link a program against an +dnl instance of the BSD libarchive package by Tim Kientzle. +dnl +dnl See http://people.freebsd.org/~kientzle/libarchive/ for more info. +dnl +dnl It exports and substitutes the variables LIBARCHIVE_LIBS, LIBARCHIVE_LDFLAGS, +dnl and LIBARCHIVE_CPPFLAGS to appropriate values for the identified instance of +dnl libarchive. The values are AC_SUBST'd, so a user could, for example, simply +dnl include @LIBARCHIVE_CPPFLAGS@ in the definition of AM_CPPFLAGS in a Makefile.am. +dnl +dnl ENABLED-DEFAULT is either "yes" or "no" and determines whether the default value +dnl is --with-libarchive or --without-libarchive. It is not possible to specify a +dnl default directory. More simply, any reasonable choice for a default should just +dnl go into the auto-detect list. +dnl +dnl The macro defines the symbol HAVE_LIBARCHIVE if the library is found. You +dnl should use autoheader to include a definition for this symbol in a config.h +dnl file. Sample usage in a C/C++ source is as follows: +dnl +dnl #ifdef HAVE_LIBARCHIVE +dnl #include +dnl #endif /* HAVE_LIBARCHIVE */ +dnl +dnl @category InstalledPackages +dnl @author Andre Stechert +dnl @version 2006-04-20 +dnl @license GPLWithACException + +AC_DEFUN([ST_LIB_ARCHIVE], +[ +# +# Handle input from the configurer and blend with the requirements from the maintainer. +# We go through the trouble of creating a second set of variables other than the with_foo +# variables in order to be sure that error/corner cases have been cleaned up. +# +# After this statement, three trusted variable are defined. +# +# st_lib_archive_ENABLED will be either "yes" or "no". its value determines whether +# or not we bother with the rest of the checks and whether or not we export a +# bunch of variables. +# +# st_lib_archive_LOCATION will be either "auto" or "defined". if it is "auto", then +# we try a bunch of standard locations. if it is "defined", then we just try the value +# provided in st_lib_archive_DIR. +# +# st_lib_archive_DIR will contain the string provided by the user, provided that it's +# actually a directory. +# +AC_MSG_CHECKING([if libarchive is wanted]) +AC_ARG_WITH([libarchive], + AS_HELP_STRING([--with-libarchive=DIR], [libarchive installation directory]), + [if test "x$with_libarchive" = "xno" ; then + st_lib_archive_ENABLED=no + elif test "x$with_libarchive" = "xyes" ; then + st_lib_archive_ENABLED=yes + st_lib_archive_LOCATION=auto + else + st_lib_archive_ENABLED=yes + st_lib_archive_LOCATION=defined + if test -d "$with_libarchive" ; then + st_lib_archive_DIR="$with_libarchive" + else + AC_MSG_ERROR([$with_libarchive is not a directory]) + fi + fi], + [if test "x$1" = "xno" ; then + st_lib_archive_ENABLED=no + elif test "x$1" = "xyes" ; then + st_lib_archive_ENABLED=yes + else + st_lib_archive_ENABLED=yes + fi]) + +if test "$st_lib_archive_ENABLED" = "yes" ; then + AC_MSG_RESULT([yes]) +# +# After this statement, one trusted variable is defined. +# +# st_lib_archive_LIB will be either "lib" or "lib64", depending on whether the configurer +# specified 32, 64. The default is "lib". +# + AC_MSG_CHECKING([whether to use lib or lib64]) + AC_ARG_WITH([libarchive-bits], + AS_HELP_STRING([--with-libarchive-bits=32/64], [if 64, look in /lib64 on hybrid systems]), + [if test "x$with_libarchive_bits" = "x32" ; then + st_lib_archive_LIB=lib + elif test "x$with_libarchive_bits" = "x64" ; then + st_lib_archive_LIB=lib64 + else + AC_MSG_ERROR([the argument must be either 32 or 64]) + fi], + [st_lib_archive_LIB=lib]) + AC_MSG_RESULT($st_lib_archive_LIB) +# +# Save the environment before verifying libarchive availability +# + st_lib_archive_SAVECPPFLAGS="$CPPFLAGS" + st_lib_archive_SAVELDFLAGS="$LDFLAGS" + AC_LANG_SAVE + AC_LANG_C + + if test "x$st_lib_archive_LOCATION" = "xdefined" ; then + CPPFLAGS="-I$st_lib_archive_DIR/include $st_lib_archive_SAVECPPFLAGS" + LDFLAGS="-L$st_lib_archive_DIR/$st_lib_archive_LIB $st_lib_archive_SAVELDFLAGS" + AC_CHECK_LIB(archive, archive_read_new, [st_lib_archive_found_lib=yes], [st_lib_archive_found_lib=no]) + AC_CHECK_HEADER(archive.h, [st_lib_archive_found_hdr=yes], [st_lib_archive_found_hdr=no]) + if test "x$st_lib_archive_found_lib" = "xyes" && test "x$st_lib_archive_found_hdr" = "xyes"; then + LIBARCHIVE_CPPFLAGS="-I$dir/include" + LIBARCHIVE_LDFLAGS="-L$dir/$st_lib_archive_LIB" + else + AC_MSG_ERROR([could not find libarchive in the requested location]) + fi + else + # + # These are the common install directories for Linux, FreeBSD, Solaris, and Mac. + # + for dir in /usr /usr/local /usr/sfw /opt/csw /opt/local /sw + do + if test -d "$dir" ; then + CPPFLAGS="-I$dir/include $st_lib_archive_SAVECPPFLAGS" + LDFLAGS="-L$dir/$st_lib_archive_LIB $st_lib_archive_SAVELDFLAGS" + AC_CHECK_LIB(archive, archive_read_new, [st_lib_archive_found_lib=yes], [st_lib_archive_found_lib=no]) + AC_CHECK_HEADER(archive.h, [st_lib_archive_found_hdr=yes], [st_lib_archive_found_hdr=no]) + if test "x$st_lib_archive_found_lib" = "xyes" && test "x$st_lib_archive_found_hdr" = "xyes"; then + LIBARCHIVE_CPPFLAGS="-I$dir/include" + LIBARCHIVE_LDFLAGS="-L$dir/$st_lib_archive_LIB" + break + fi + fi + done + fi + + if test "x$st_lib_archive_found_hdr" = "xyes" && test "x$st_lib_archive_found_lib" = "xyes" ; then + LIBARCHIVE_LIBS="-larchive" + AC_DEFINE([HAVE_LIBARCHIVE], [1], [Defined to 1 if libarchive is available for use.]) + AC_SUBST(LIBARCHIVE_LIBS) + AC_SUBST(LIBARCHIVE_CPPFLAGS) + AC_SUBST(LIBARCHIVE_LDFLAGS) + fi + +# +# Restore the environment now that we're done. +# + AC_LANG_RESTORE + CPPFLAGS="$st_lib_archive_SAVECPPFLAGS" + LDFLAGS="$st_lib_archive_SAVELDFLAGS" +else + AC_MSG_RESULT([no]) +fi +AM_CONDITIONAL(LIBARCHIVE, test "x$st_lib_archive_found_lib" = "xyes" && test "x$st_lib_archive_found_hdr" = "xyes") +]) diff --git a/dependencies/libarchive-3.4.2/contrib/psota-benchmark/results.txt b/dependencies/libarchive-3.4.2/contrib/psota-benchmark/results.txt new file mode 100644 index 0000000..2d364c5 --- /dev/null +++ b/dependencies/libarchive-3.4.2/contrib/psota-benchmark/results.txt @@ -0,0 +1,136 @@ +ODP: [Bug-tar] GNU tar, star and BSD tar speed comparison +new script + +Jan Psota +Thu, 25 Oct 2007 06:51:13 -0700 + +Latest TCP script at the bottom (3180 bytes). +4 tests: 64bit dual core Athlon tmpfs / disk (reiserfs) - 60MB/s, + 32bit Athlon tmpfs / disk (reiserfs) - 55MB/s +Both machines were idle -- used for testing only. +Tarball and extracted files were on different physical devices. +Test data: linux 2.6.22/3 kernel sources for memory operations, +for the other data average file size should bring enough info. + +2 x [...] processor means 1 processor with 2 cores (2 entries in cpuinfo). +Archive format is set to pax (Joerg). +Let's end with it. I only wanted to send You a new version of TCP script :-). + +-- +Jan Psota + +TCP, version 2007-10-25 +Linux 2.6.22-suspend2-r2 / Gentoo Base System release 2.0.0_rc5 +2012MB of memory, 2 x AMD Athlon(tm) 64 X2 Dual Core Processor 4200+ 2211.348 +512 KB 4426.24 bmips +gcc (GCC) 4.2.2 (Gentoo 4.2.2 p1.0) +CFLAGS="-O2 -march=k8 -pipe" + +bsdtar: bsdtar 2.3.4 - libarchive 2.3.4 +gnutar: tar (GNU tar) 1.19 +star: star: star 1.5a85 (x86_64-unknown-linux-gnu) + +best time of 5 repetitions, + src=linux-2.6.23, 291M in 23867 files, avg 13KB/file, + archive=/tmp/tcp.tar, extract to /tmp/tcptmp +program operation real user system %CPU speed +bsdtar create 0.764 0.232 0.532 99.96 370308 KB/s +gnutar create 0.743 0.200 0.512 95.87 380775 KB/s +star create 0.587 0.040 0.820 100.00 441247 KB/s + +bsdtar list 0.164 0.096 0.068 99.84 1579341 KB/s +gnutar list 0.218 0.064 0.152 98.92 1188128 KB/s +star list 0.359 0.044 0.240 79.09 721481 KB/s + +bsdtar extract 0.733 0.200 0.504 96.02 353358 KB/s +gnutar extract 0.625 0.092 0.508 96.02 414419 KB/s +star extract 0.875 0.096 0.980 100.00 296013 KB/s + +bsdtar compare 0.001 0.000 0.000 0.00 259012000 KB/s +gnutar compare 0.719 0.288 0.400 95.66 360239 KB/s +star compare 0.695 0.224 0.636 100.00 372679 KB/s + +[...] +best time of 3 repetitions, + src=/home, 3.2G in 7447 files, avg 554KB/file, + archive=/var/tcp.tar, extract to /mnt/a/tcptmp +program operation real user system %CPU speed +bsdtar create 184.680 0.552 13.365 7.53 17958 KB/s +gnutar create 159.240 0.256 12.417 7.95 20827 KB/s +star create 181.779 0.140 14.789 8.21 18203 KB/s + +bsdtar list 0.053 0.032 0.016 91.41 62435471 KB/s +gnutar list 56.535 0.136 3.764 6.89 58531 KB/s +star list 56.652 0.080 5.236 9.38 58410 KB/s + +bsdtar extract 78.914 0.820 15.149 20.23 41932 KB/s +gnutar extract 78.480 0.196 14.197 18.33 42164 KB/s +star extract 79.439 0.132 12.973 16.49 41655 KB/s + +bsdtar compare 0.001 0.000 0.000 0.00 3309080000 KB/s +gnutar compare 61.771 3.464 8.905 20.02 53570 KB/s +star compare 57.561 1.728 9.897 20.19 57488 KB/s + + +Linux 2.6.22-suspend2-smp / Gentoo Base System release 2.0.0_rc5 +504MB of memory, 1 x AMD Athlon(tm) Processor 1500.033 256 KB 3002.55 bmips +gcc (GCC) 4.2.2 (Gentoo 4.2.2 p1.0) +CFLAGS="-O2 -march=athlon-xp -mfpmath=sse -frename-registers -pipe" + +bsdtar: bsdtar 2.3.4 - libarchive 2.3.4 +gnutar: tar (GNU tar) 1.19 +star: star: star 1.5a85 (i686-pc-linux-gnu) + +best time of 3 repetitions, + src=/usr/src/linux-2.6.22-suspend2/drivers, 119M in 5900 files, + avg 21KB/file, archive=/tmp/tcp.tar, extract to /tmp/tcptmp +program operation real user system %CPU speed +bsdtar create 1.329 0.192 1.132 99.63 89784 KB/s +gnutar create 1.223 0.124 1.092 99.46 97566 KB/s +star create 1.848 0.036 1.708 94.36 61372 KB/s + +bsdtar list 0.167 0.060 0.108 100.00 679137 KB/s +gnutar list 0.161 0.040 0.124 100.00 704447 KB/s +star list 0.859 0.044 0.716 88.51 132032 KB/s + +bsdtar extract 1.186 0.172 1.012 99.87 95629 KB/s +gnutar extract 1.064 0.056 1.004 99.63 106593 KB/s +star extract 1.920 0.088 1.724 94.40 59070 KB/s + +bsdtar compare 0.002 0.000 0.000 0.00 56708000 KB/s +gnutar compare 0.925 0.232 0.692 99.90 122611 KB/s +star compare 1.569 0.376 1.096 93.79 72285 KB/s + +[...] +best time of 3 repetitions, + src=/home/jasiu, 2.1G in 8416 files, avg 277KB/file, + archive=/home/j2/tcp.tar, extract to /mnt/a/tar/tcptmp +program operation real user system %CPU speed +bsdtar create 182.171 1.692 29.130 16.91 11584 KB/s +gnutar create 174.999 0.632 27.450 16.04 12059 KB/s +star create 180.004 0.360 41.795 23.41 11677 KB/s + +bsdtar list 0.214 0.076 0.136 99.04 9822294 KB/s +gnutar list 0.210 0.076 0.136 100.00 10009385 KB/s +star list 43.462 0.148 18.109 42.00 48363 KB/s + +bsdtar extract 94.912 4.476 31.574 37.98 22146 KB/s +gnutar extract 94.657 0.396 29.462 31.54 22206 KB/s +star extract 100.814 0.400 39.906 39.98 20849 KB/s + +bsdtar compare 0.003 0.000 0.004 100.00 700657000 KB/s +gnutar compare 80.174 3.932 20.365 30.30 26217 KB/s +star compare 73.911 8.341 27.670 48.72 28439 KB/s + +============================================================= + +Note by Tim Kientzle: The "bsdtar compare" results here are +invalid since bsdtar does not support that operation. +For the list numbers, note that libarchive automatically optimizes +list operations on uncompressed tar archives on disk by using lseek() +to skip over the bodies of entries. GNU tar added an option to +provide the same feature. + +The biggest problem with these tests is that they only +cover uncompressed archives stored on disk. The results for +compressed archives and/or archives stored on tape are +likely quite different. diff --git a/dependencies/libarchive-3.4.2/contrib/psota-benchmark/tcp.sh b/dependencies/libarchive-3.4.2/contrib/psota-benchmark/tcp.sh new file mode 100755 index 0000000..3f63073 --- /dev/null +++ b/dependencies/libarchive-3.4.2/contrib/psota-benchmark/tcp.sh @@ -0,0 +1,110 @@ +#!/bin/sh +# tar comparison program +# 2007-10-25 Jan Psota + +n=3 # number of repetitions +TAR="bsdtar gnutar star" # Tape archivers to compare +OPT=("" "--seek" "-no-fsync") +pax="--format=pax" # comment out for defaults +OPN=(create list extract compare) # operations +version="2007-10-25" +TIMEFORMAT=$'%R\t%U\t%S\t%P' +LC_ALL=C + +test $# -ge 2 || { + echo -e "usage:\t$0 source_dir where_to_place_archive +[where_to_extract_it] + +TCP, version $version +TCP stands for Tar Comparison Program here. +It currently compares: BSD tar (bsdtar), GNU tar (gnutar) and star in archive +creation, listing, extraction and archive-to-extracted comparison. +Tcp prints out best time of n=$n repetitions. + +Tcp creates temporary archive named tcp.tar with $pax and some native +(--seek/-no-fsync) options and extracts it to [\$3]/tcptmp/. +If unset, third argument defaults to [\$2]. +After normal exit tcp removes tarball and extracted files. +Tcp does not check filesystems destination directories are on for free space, +so make sure there is enough space (a bit more than source_dir uses) for both: +archive and extracted files. +Do not use white space in arguments. + Jan Psota, $version" + exit 0 +} +src=$1 +dst=$2/tcp.tar +dst_path=${3:-$2}/tcptmp +test -e $dst -o -e /tmp/tcp \ + && { echo "$dst or /tmp/tcp exists, exiting"; exit 1; } +mkdir $dst_path || exit 2 + +use_times () +{ + awk -F"\t" -vN=$n -vL="`du -k $dst`" -vOFS="\t" -vORS="" ' + { if (NF==4) { printf "\t%s\t%10.1d KB/s\n", $0, ($1+0>0 ? +(L+0)/($1+0) : 0) } }' \ + /tmp/tcp | sort | head -1 + > /tmp/tcp +} + +test -d $src || { echo "'$src' is not a directory"; exit 3; } + +# system information: type, release, memory, cpu(s), compiler and flags +echo -e "TCP, version $version\n"`uname -sr`" / "`head -1 /etc/*-release` +free -m | awk '/^Mem/ { printf "%dMB of memory, ", $2 }' +test -e /proc/cpuinfo \ + && awk -F: '/name|cache size|MHz|mips/ { if (!a) b=b $2 } + /^$/ { a++ } END { print a" x"b" bmips" }' /proc/cpuinfo +test -e /etc/gentoo-release \ + && gcc --version | head -1 && grep ^CFLAGS /etc/make.conf + +# tar versions +t= +echo +for tar in $TAR; do + if which $tar &> /dev/null; then + t="$t $tar"; + echo -ne "$tar:\t"; $tar --version | head -1; + fi +done + +TAR="$t" + +echo -e "\nbest time of $n repetitions,\n"\ +" src=$src, "\ +`du -sh $src | awk '{print $1}'`" in "`find $src | wc -l`" files, "\ +"avg "$((`du -sk $src | awk '{print $1}'`/`find $src -type f | wc -l`))"KB/file,\n"\ +" archive=$dst, extract to $dst_path" + +echo -e "program\toperation\treal\tuser\tsystem\t%CPU\t speed" +> /tmp/tcp +let op_num=0 +for op in "cf $dst $pax -C $src ." "tf $dst" "xf $dst -C $dst_path" \ + "f $dst -C $dst_path --diff"; do + let tar_num=0 + for tar in $TAR; do + echo -en "$tar\t${OPN[op_num]}\t" + for ((i=1; i<=$n; i++)); do + echo $op | grep -q ^cf && rm -f $dst + echo $op | grep -q ^xf && + { chmod -R u+w $dst_path + rm -rf $dst_path; mkdir $dst_path; } + sync + if echo $op | grep -q ^f; then # op == compare + time $tar $op ${OPT[$tar_num]} > /dev/null + else # op in (create | list | extract) + time $tar $op ${OPT[$tar_num]} > /dev/null \ + || break 3 + fi 2>> /tmp/tcp + done + use_times + let tar_num++ + done + let op_num++ + echo +done +rm -rf $dst_path $dst +echo +cat /tmp/tcp +rm -f /tmp/tcp diff --git a/dependencies/libarchive-3.4.2/contrib/shar/shar.1 b/dependencies/libarchive-3.4.2/contrib/shar/shar.1 new file mode 100644 index 0000000..3156197 --- /dev/null +++ b/dependencies/libarchive-3.4.2/contrib/shar/shar.1 @@ -0,0 +1,131 @@ +.\" Copyright (c) 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)shar.1 8.1 (Berkeley) 6/6/93 +.\" $FreeBSD$ +.\" +.Dd April 17, 2008 +.Dt SHAR 1 +.Os +.Sh NAME +.Nm shar +.Nd create a shell archive of files +.Sh SYNOPSIS +.Nm +.Op Fl br +.Op Fl o Ar archive-file +.Ar +.Sh DESCRIPTION +The +.Nm +command writes a +.Xr sh 1 +shell script which will recreate the file hierarchy specified by the command +line operands. +.Pp +The +.Nm +command is normally used for distributing files by +.Xr ftp 1 +or +.Xr mail 1 . +.Pp +The following options are available: +.Bl -tag -width indent +.It Fl b +Use an alternative binary format. +Content of files will be uuencoded. +This option should be used to archive binary files correctly. +In this mode also file permissions will be stored to the archive. +uudecode(1) is needed to extract archives created with this option. +.It Fl o Ar archive-file +Redirect output to +.Ar archive-file . +.It Fl r +If +.Ar file +given on command line is a directory the entire subtree will be archived. +Symbolic links given on command line are followed. +Other symbolic links will be archived as such. +.El +.Sh EXAMPLES +To create a shell archive of the program +.Xr ls 1 +and mail it to Rick: +.Bd -literal -offset indent +cd ls +shar -r . \&| mail -s "ls source" rick +.Ed +.Pp +To recreate the program directory: +.Bd -literal -offset indent +mkdir ls +cd ls +\&... + +\&... +sh archive +.Ed +.Sh SEE ALSO +.Xr compress 1 , +.Xr mail 1 , +.Xr tar 1 , +.Xr uuencode 1 , +.Xr uuencode 5 +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.4 . +This is a re-implementation based on the libarchive(3) library. +.Sh BUGS +The +.Nm +command makes no provisions for hard links. +.Pp +Files containing magic characters or files without a newline ('\\n') as the +last character are not handled correctly with the default format. +Use the +.Fl b +option for binary files. +.Pp +It is easy to insert trojan horses into +.Nm +files. +It is strongly recommended that all shell archive files be examined +before running them through +.Xr sh 1 . +Archives produced using this implementation of +.Nm +may be easily examined with the command: +.Bd -literal -offset indent +egrep -v '^[X#]' shar.file +.Ed diff --git a/dependencies/libarchive-3.4.2/contrib/shar/shar.c b/dependencies/libarchive-3.4.2/contrib/shar/shar.c new file mode 100644 index 0000000..6d5c206 --- /dev/null +++ b/dependencies/libarchive-3.4.2/contrib/shar/shar.c @@ -0,0 +1,314 @@ +/*- + * Copyright (c) 2008 Jaakko Heinonen + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#ifdef __FBSDID +__FBSDID("$FreeBSD$"); +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tree.h" + +/* command line options */ +static int b_opt; /* use alternative shar binary format */ +static int r_opt; /* recurse into subdirectories */ +static char *o_arg; /* output file name */ + +static void +usage(void) +{ + fprintf(stderr, "Usage: shar [-br] [-o filename] file ...\n"); + exit(EX_USAGE); +} + +/* + * Initialize archive structure and create a shar archive. + */ +static struct archive * +shar_create(void) +{ + struct archive *a; + + if ((a = archive_write_new()) == NULL) + errx(EXIT_FAILURE, "%s", archive_error_string(a)); + + if (b_opt) + archive_write_set_format_shar_dump(a); + else + archive_write_set_format_shar(a); + archive_write_set_compression_none(a); + + if (archive_write_open_filename(a, o_arg) != ARCHIVE_OK) + errx(EX_CANTCREAT, "%s", archive_error_string(a)); + + return (a); +} + +/* buffer for file data */ +static char buffer[32768]; + +/* + * Write file data to an archive entry. + */ +static int +shar_write_entry_data(struct archive *a, const int fd) +{ + ssize_t bytes_read, bytes_written; + + assert(a != NULL); + assert(fd >= 0); + + bytes_read = read(fd, buffer, sizeof(buffer)); + while (bytes_read != 0) { + if (bytes_read < 0) { + archive_set_error(a, errno, "Read failed"); + return (ARCHIVE_WARN); + } + bytes_written = archive_write_data(a, buffer, bytes_read); + if (bytes_written < 0) + return (ARCHIVE_WARN); + bytes_read = read(fd, buffer, sizeof(buffer)); + } + + return (ARCHIVE_OK); +} + +/* + * Write a file to the archive. We have special handling for symbolic links. + */ +static int +shar_write_entry(struct archive *a, const char *pathname, const char *accpath, + const struct stat *st) +{ + struct archive_entry *entry; + int fd = -1; + int ret = ARCHIVE_OK; + + assert(a != NULL); + assert(pathname != NULL); + assert(accpath != NULL); + assert(st != NULL); + + entry = archive_entry_new(); + + if (S_ISREG(st->st_mode) && st->st_size > 0) { + /* regular file */ + if ((fd = open(accpath, O_RDONLY)) == -1) { + warn("%s", accpath); + ret = ARCHIVE_WARN; + goto out; + } + } else if (S_ISLNK(st->st_mode)) { + /* symbolic link */ + char lnkbuff[PATH_MAX + 1]; + int lnklen; + if ((lnklen = readlink(accpath, lnkbuff, PATH_MAX)) == -1) { + warn("%s", accpath); + ret = ARCHIVE_WARN; + goto out; + } + lnkbuff[lnklen] = '\0'; + archive_entry_set_symlink(entry, lnkbuff); + } + archive_entry_copy_stat(entry, st); + archive_entry_set_pathname(entry, pathname); + if (!S_ISREG(st->st_mode) || st->st_size == 0) + archive_entry_set_size(entry, 0); + if (archive_write_header(a, entry) != ARCHIVE_OK) { + warnx("%s: %s", pathname, archive_error_string(a)); + ret = ARCHIVE_WARN; + goto out; + } + if (fd >= 0) { + if ((ret = shar_write_entry_data(a, fd)) != ARCHIVE_OK) + warnx("%s: %s", accpath, archive_error_string(a)); + } +out: + archive_entry_free(entry); + if (fd >= 0) + close(fd); + + return (ret); +} + +/* + * Write singe path to the archive. The path can be a regular file, directory + * or device. Symbolic links are followed. + */ +static int +shar_write_path(struct archive *a, const char *pathname) +{ + struct stat st; + + assert(a != NULL); + assert(pathname != NULL); + + if ((stat(pathname, &st)) == -1) { + warn("%s", pathname); + return (ARCHIVE_WARN); + } + + return (shar_write_entry(a, pathname, pathname, &st)); +} + +/* + * Write tree to the archive. If pathname is a symbolic link it will be + * followed. Other symbolic links are stored as such to the archive. + */ +static int +shar_write_tree(struct archive *a, const char *pathname) +{ + struct tree *t; + const struct stat *lst, *st; + int error = 0; + int tree_ret; + int first; + + assert(a != NULL); + assert(pathname != NULL); + + t = tree_open(pathname); + for (first = 1; (tree_ret = tree_next(t)); first = 0) { + if (tree_ret == TREE_ERROR_DIR) { + warnx("%s: %s", tree_current_path(t), + strerror(tree_errno(t))); + error = 1; + continue; + } else if (tree_ret != TREE_REGULAR) + continue; + if ((lst = tree_current_lstat(t)) == NULL) { + warn("%s", tree_current_path(t)); + error = 1; + continue; + } + /* + * If the symlink was given on command line then + * follow it rather than write it as symlink. + */ + if (first && S_ISLNK(lst->st_mode)) { + if ((st = tree_current_stat(t)) == NULL) { + warn("%s", tree_current_path(t)); + error = 1; + continue; + } + } else + st = lst; + + if (shar_write_entry(a, tree_current_path(t), + tree_current_access_path(t), st) != ARCHIVE_OK) + error = 1; + + tree_descend(t); + } + + tree_close(t); + + return ((error != 0) ? ARCHIVE_WARN : ARCHIVE_OK); +} + +/* + * Create a shar archive and write files/trees into it. + */ +static int +shar_write(char **fn, size_t nfn) +{ + struct archive *a; + size_t i; + int error = 0; + + assert(fn != NULL); + assert(nfn > 0); + + a = shar_create(); + + for (i = 0; i < nfn; i++) { + if (r_opt) { + if (shar_write_tree(a, fn[i]) != ARCHIVE_OK) + error = 1; + } else { + if (shar_write_path(a, fn[i]) != ARCHIVE_OK) + error = 1; + } + } + + if (archive_write_free(a) != ARCHIVE_OK) + errx(EXIT_FAILURE, "%s", archive_error_string(a)); + + if (error != 0) + warnx("Error exit delayed from previous errors."); + + return (error); +} + +int +main(int argc, char **argv) +{ + int opt; + + while ((opt = getopt(argc, argv, "bro:")) != -1) { + switch (opt) { + case 'b': + b_opt = 1; + break; + case 'o': + o_arg = optarg; + break; + case 'r': + r_opt = 1; + break; + default: + usage(); + /* NOTREACHED */ + } + } + argc -= optind; + argv += optind; + + if(argc < 1) + usage(); + + if (shar_write(argv, argc) != 0) + exit(EXIT_FAILURE); + else + exit(EXIT_SUCCESS); + /* NOTREACHED */ +} + diff --git a/dependencies/libarchive-3.4.2/contrib/shar/tree.c b/dependencies/libarchive-3.4.2/contrib/shar/tree.c new file mode 100644 index 0000000..a80d836 --- /dev/null +++ b/dependencies/libarchive-3.4.2/contrib/shar/tree.c @@ -0,0 +1,541 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * This is a new directory-walking system that addresses a number + * of problems I've had with fts(3). In particular, it has no + * pathname-length limits (other than the size of 'int'), handles + * deep logical traversals, uses considerably less memory, and has + * an opaque interface (easier to modify in the future). + * + * Internally, it keeps a single list of "tree_entry" items that + * represent filesystem objects that require further attention. + * Non-directories are not kept in memory: they are pulled from + * readdir(), returned to the client, then freed as soon as possible. + * Any directory entry to be traversed gets pushed onto the stack. + * + * There is surprisingly little information that needs to be kept for + * each item on the stack. Just the name, depth (represented here as the + * string length of the parent directory's pathname), and some markers + * indicating how to get back to the parent (via chdir("..") for a + * regular dir or via fchdir(2) for a symlink). + */ +#include "tree_config.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_DIRENT_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "tree.h" + +/* + * TODO: + * 1) Loop checking. + * 3) Arbitrary logical traversals by closing/reopening intermediate fds. + */ + +struct tree_entry { + struct tree_entry *next; + struct tree_entry *parent; + char *name; + size_t dirname_length; + dev_t dev; + ino_t ino; + int fd; + int flags; +}; + +/* Definitions for tree_entry.flags bitmap. */ +#define isDir 1 /* This entry is a regular directory. */ +#define isDirLink 2 /* This entry is a symbolic link to a directory. */ +#define needsPreVisit 4 /* This entry needs to be previsited. */ +#define needsPostVisit 8 /* This entry needs to be postvisited. */ + +/* + * Local data for this package. + */ +struct tree { + struct tree_entry *stack; + struct tree_entry *current; + DIR *d; + int initialDirFd; + int flags; + int visit_type; + int tree_errno; /* Error code from last failed operation. */ + + char *buff; + const char *basename; + size_t buff_length; + size_t path_length; + size_t dirname_length; + + int depth; + int openCount; + int maxOpenCount; + + struct stat lst; + struct stat st; +}; + +/* Definitions for tree.flags bitmap. */ +#define needsReturn 8 /* Marks first entry as not having been returned yet. */ +#define hasStat 16 /* The st entry is set. */ +#define hasLstat 32 /* The lst entry is set. */ + + +#ifdef HAVE_DIRENT_D_NAMLEN +/* BSD extension; avoids need for a strlen() call. */ +#define D_NAMELEN(dp) (dp)->d_namlen +#else +#define D_NAMELEN(dp) (strlen((dp)->d_name)) +#endif + +#if 0 +#include +void +tree_dump(struct tree *t, FILE *out) +{ + struct tree_entry *te; + + fprintf(out, "\tdepth: %d\n", t->depth); + fprintf(out, "\tbuff: %s\n", t->buff); + fprintf(out, "\tpwd: "); fflush(stdout); system("pwd"); + fprintf(out, "\taccess: %s\n", t->basename); + fprintf(out, "\tstack:\n"); + for (te = t->stack; te != NULL; te = te->next) { + fprintf(out, "\t\tte->name: %s%s%s\n", te->name, + te->flags & needsPreVisit ? "" : " *", + t->current == te ? " (current)" : ""); + } +} +#endif + +/* + * Add a directory path to the current stack. + */ +static void +tree_push(struct tree *t, const char *path) +{ + struct tree_entry *te; + + te = malloc(sizeof(*te)); + memset(te, 0, sizeof(*te)); + te->next = t->stack; + t->stack = te; + te->fd = -1; + te->name = strdup(path); + te->flags = needsPreVisit | needsPostVisit; + te->dirname_length = t->dirname_length; +} + +/* + * Append a name to the current path. + */ +static void +tree_append(struct tree *t, const char *name, size_t name_length) +{ + char *p; + + if (t->buff != NULL) + t->buff[t->dirname_length] = '\0'; + /* Strip trailing '/' from name, unless entire name is "/". */ + while (name_length > 1 && name[name_length - 1] == '/') + name_length--; + + /* Resize pathname buffer as needed. */ + while (name_length + 1 + t->dirname_length >= t->buff_length) { + t->buff_length *= 2; + if (t->buff_length < 1024) + t->buff_length = 1024; + t->buff = realloc(t->buff, t->buff_length); + } + p = t->buff + t->dirname_length; + t->path_length = t->dirname_length + name_length; + /* Add a separating '/' if it's needed. */ + if (t->dirname_length > 0 && p[-1] != '/') { + *p++ = '/'; + t->path_length ++; + } + strncpy(p, name, name_length); + p[name_length] = '\0'; + t->basename = p; +} + +/* + * Open a directory tree for traversal. + */ +struct tree * +tree_open(const char *path) +{ + struct tree *t; + + t = malloc(sizeof(*t)); + memset(t, 0, sizeof(*t)); + tree_append(t, path, strlen(path)); + t->initialDirFd = open(".", O_RDONLY); + /* + * During most of the traversal, items are set up and then + * returned immediately from tree_next(). That doesn't work + * for the very first entry, so we set a flag for this special + * case. + */ + t->flags = needsReturn; + return (t); +} + +/* + * We've finished a directory; ascend back to the parent. + */ +static void +tree_ascend(struct tree *t) +{ + struct tree_entry *te; + + te = t->stack; + t->depth--; + if (te->flags & isDirLink) { + fchdir(te->fd); + close(te->fd); + t->openCount--; + } else { + chdir(".."); + } +} + +/* + * Pop the working stack. + */ +static void +tree_pop(struct tree *t) +{ + struct tree_entry *te; + + t->buff[t->dirname_length] = '\0'; + if (t->stack == t->current && t->current != NULL) + t->current = t->current->parent; + te = t->stack; + t->stack = te->next; + t->dirname_length = te->dirname_length; + t->basename = t->buff + t->dirname_length; + /* Special case: starting dir doesn't skip leading '/'. */ + if (t->dirname_length > 0) + t->basename++; + free(te->name); + free(te); +} + +/* + * Get the next item in the tree traversal. + */ +int +tree_next(struct tree *t) +{ + struct dirent *de = NULL; + + /* Handle the startup case by returning the initial entry. */ + if (t->flags & needsReturn) { + t->flags &= ~needsReturn; + return (t->visit_type = TREE_REGULAR); + } + + while (t->stack != NULL) { + /* If there's an open dir, get the next entry from there. */ + while (t->d != NULL) { + de = readdir(t->d); + if (de == NULL) { + closedir(t->d); + t->d = NULL; + } else if (de->d_name[0] == '.' + && de->d_name[1] == '\0') { + /* Skip '.' */ + } else if (de->d_name[0] == '.' + && de->d_name[1] == '.' + && de->d_name[2] == '\0') { + /* Skip '..' */ + } else { + /* + * Append the path to the current path + * and return it. + */ + tree_append(t, de->d_name, D_NAMELEN(de)); + t->flags &= ~hasLstat; + t->flags &= ~hasStat; + return (t->visit_type = TREE_REGULAR); + } + } + + /* If the current dir needs to be visited, set it up. */ + if (t->stack->flags & needsPreVisit) { + t->current = t->stack; + tree_append(t, t->stack->name, strlen(t->stack->name)); + t->stack->flags &= ~needsPreVisit; + /* If it is a link, set up fd for the ascent. */ + if (t->stack->flags & isDirLink) { + t->stack->fd = open(".", O_RDONLY); + t->openCount++; + if (t->openCount > t->maxOpenCount) + t->maxOpenCount = t->openCount; + } + t->dirname_length = t->path_length; + if (chdir(t->stack->name) != 0) { + /* chdir() failed; return error */ + tree_pop(t); + t->tree_errno = errno; + return (t->visit_type = TREE_ERROR_DIR); + } + t->depth++; + t->d = opendir("."); + if (t->d == NULL) { + tree_ascend(t); /* Undo "chdir" */ + tree_pop(t); + t->tree_errno = errno; + return (t->visit_type = TREE_ERROR_DIR); + } + t->flags &= ~hasLstat; + t->flags &= ~hasStat; + t->basename = "."; + return (t->visit_type = TREE_POSTDESCENT); + } + + /* We've done everything necessary for the top stack entry. */ + if (t->stack->flags & needsPostVisit) { + tree_ascend(t); + tree_pop(t); + t->flags &= ~hasLstat; + t->flags &= ~hasStat; + return (t->visit_type = TREE_POSTASCENT); + } + } + return (t->visit_type = 0); +} + +/* + * Return error code. + */ +int +tree_errno(struct tree *t) +{ + return (t->tree_errno); +} + +/* + * Called by the client to mark the directory just returned from + * tree_next() as needing to be visited. + */ +void +tree_descend(struct tree *t) +{ + if (t->visit_type != TREE_REGULAR) + return; + + if (tree_current_is_physical_dir(t)) { + tree_push(t, t->basename); + t->stack->flags |= isDir; + } else if (tree_current_is_dir(t)) { + tree_push(t, t->basename); + t->stack->flags |= isDirLink; + } +} + +/* + * Get the stat() data for the entry just returned from tree_next(). + */ +const struct stat * +tree_current_stat(struct tree *t) +{ + if (!(t->flags & hasStat)) { + if (stat(t->basename, &t->st) != 0) + return NULL; + t->flags |= hasStat; + } + return (&t->st); +} + +/* + * Get the lstat() data for the entry just returned from tree_next(). + */ +const struct stat * +tree_current_lstat(struct tree *t) +{ + if (!(t->flags & hasLstat)) { + if (lstat(t->basename, &t->lst) != 0) + return NULL; + t->flags |= hasLstat; + } + return (&t->lst); +} + +/* + * Test whether current entry is a dir or link to a dir. + */ +int +tree_current_is_dir(struct tree *t) +{ + const struct stat *st; + + /* + * If we already have lstat() info, then try some + * cheap tests to determine if this is a dir. + */ + if (t->flags & hasLstat) { + /* If lstat() says it's a dir, it must be a dir. */ + if (S_ISDIR(tree_current_lstat(t)->st_mode)) + return 1; + /* Not a dir; might be a link to a dir. */ + /* If it's not a link, then it's not a link to a dir. */ + if (!S_ISLNK(tree_current_lstat(t)->st_mode)) + return 0; + /* + * It's a link, but we don't know what it's a link to, + * so we'll have to use stat(). + */ + } + + st = tree_current_stat(t); + /* If we can't stat it, it's not a dir. */ + if (st == NULL) + return 0; + /* Use the definitive test. Hopefully this is cached. */ + return (S_ISDIR(st->st_mode)); +} + +/* + * Test whether current entry is a physical directory. Usually, we + * already have at least one of stat() or lstat() in memory, so we + * use tricks to try to avoid an extra trip to the disk. + */ +int +tree_current_is_physical_dir(struct tree *t) +{ + const struct stat *st; + + /* + * If stat() says it isn't a dir, then it's not a dir. + * If stat() data is cached, this check is free, so do it first. + */ + if ((t->flags & hasStat) + && (!S_ISDIR(tree_current_stat(t)->st_mode))) + return 0; + + /* + * Either stat() said it was a dir (in which case, we have + * to determine whether it's really a link to a dir) or + * stat() info wasn't available. So we use lstat(), which + * hopefully is already cached. + */ + + st = tree_current_lstat(t); + /* If we can't stat it, it's not a dir. */ + if (st == NULL) + return 0; + /* Use the definitive test. Hopefully this is cached. */ + return (S_ISDIR(st->st_mode)); +} + +/* + * Test whether current entry is a symbolic link. + */ +int +tree_current_is_physical_link(struct tree *t) +{ + const struct stat *st = tree_current_lstat(t); + if (st == NULL) + return 0; + return (S_ISLNK(st->st_mode)); +} + +/* + * Return the access path for the entry just returned from tree_next(). + */ +const char * +tree_current_access_path(struct tree *t) +{ + return (t->basename); +} + +/* + * Return the full path for the entry just returned from tree_next(). + */ +const char * +tree_current_path(struct tree *t) +{ + return (t->buff); +} + +/* + * Return the length of the path for the entry just returned from tree_next(). + */ +size_t +tree_current_pathlen(struct tree *t) +{ + return (t->path_length); +} + +/* + * Return the nesting depth of the entry just returned from tree_next(). + */ +int +tree_current_depth(struct tree *t) +{ + return (t->depth); +} + +/* + * Terminate the traversal and release any resources. + */ +void +tree_close(struct tree *t) +{ + /* Release anything remaining in the stack. */ + while (t->stack != NULL) + tree_pop(t); + free(t->buff); + /* chdir() back to where we started. */ + if (t->initialDirFd >= 0) { + fchdir(t->initialDirFd); + close(t->initialDirFd); + t->initialDirFd = -1; + } + free(t); +} diff --git a/dependencies/libarchive-3.4.2/contrib/shar/tree.h b/dependencies/libarchive-3.4.2/contrib/shar/tree.h new file mode 100644 index 0000000..ff38f53 --- /dev/null +++ b/dependencies/libarchive-3.4.2/contrib/shar/tree.h @@ -0,0 +1,115 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/*- + * A set of routines for traversing directory trees. + * Similar in concept to the fts library, but with a few + * important differences: + * * Uses less memory. In particular, fts stores an entire directory + * in memory at a time. This package only keeps enough subdirectory + * information in memory to track the traversal. Information + * about non-directories is discarded as soon as possible. + * * Supports very deep logical traversals. The fts package + * uses "non-chdir" approach for logical traversals. This + * package does use a chdir approach for logical traversals + * and can therefore handle pathnames much longer than + * PATH_MAX. + * * Supports deep physical traversals "out of the box." + * Due to the memory optimizations above, there's no need to + * limit dir names to 32k. + */ + +#include +#include + +struct tree; + +/* Initiate/terminate a tree traversal. */ +struct tree *tree_open(const char * /* pathname */); +void tree_close(struct tree *); + +/* + * tree_next() returns Zero if there is no next entry, non-zero if there is. + * Note that directories are potentially visited three times. The first + * time as "regular" file. If tree_descend() is invoked at that time, + * the directory is added to a work list and will be visited two more + * times: once just after descending into the directory and again + * just after ascending back to the parent. + * + * TREE_ERROR is returned if the descent failed (because the + * directory couldn't be opened, for instance). This is returned + * instead of TREE_PREVISIT/TREE_POSTVISIT. + */ +#define TREE_REGULAR 1 +#define TREE_POSTDESCENT 2 +#define TREE_POSTASCENT 3 +#define TREE_ERROR_DIR -1 +int tree_next(struct tree *); + +int tree_errno(struct tree *); + +/* + * Request that current entry be visited. If you invoke it on every + * directory, you'll get a physical traversal. This is ignored if the + * current entry isn't a directory or a link to a directory. So, if + * you invoke this on every returned path, you'll get a full logical + * traversal. + */ +void tree_descend(struct tree *); + +/* + * Return information about the current entry. + */ + +int tree_current_depth(struct tree *); +/* + * The current full pathname, length of the full pathname, + * and a name that can be used to access the file. + * Because tree does use chdir extensively, the access path is + * almost never the same as the full current path. + */ +const char *tree_current_path(struct tree *); +size_t tree_current_pathlen(struct tree *); +const char *tree_current_access_path(struct tree *); +/* + * Request the lstat() or stat() data for the current path. Since the + * tree package needs to do some of this anyway, and caches the + * results, you should take advantage of it here if you need it rather + * than make a redundant stat() or lstat() call of your own. + */ +const struct stat *tree_current_stat(struct tree *); +const struct stat *tree_current_lstat(struct tree *); +/* The following tests may use mechanisms much faster than stat()/lstat(). */ +/* "is_physical_dir" is equivalent to S_ISDIR(tree_current_lstat()->st_mode) */ +int tree_current_is_physical_dir(struct tree *); +/* "is_physical_link" is equivalent to S_ISLNK(tree_current_lstat()->st_mode) */ +int tree_current_is_physical_link(struct tree *); +/* "is_dir" is equivalent to S_ISDIR(tree_current_stat()->st_mode) */ +int tree_current_is_dir(struct tree *); + +/* For testing/debugging: Dump the internal status to the given filehandle. */ +void tree_dump(struct tree *, FILE *); diff --git a/dependencies/libarchive-3.4.2/contrib/shar/tree_config.h b/dependencies/libarchive-3.4.2/contrib/shar/tree_config.h new file mode 100644 index 0000000..8dfd90b --- /dev/null +++ b/dependencies/libarchive-3.4.2/contrib/shar/tree_config.h @@ -0,0 +1,78 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef TREE_CONFIG_H_INCLUDED +#define TREE_CONFIG_H_INCLUDED + +#if defined(PLATFORM_CONFIG_H) +/* + * Use hand-built config.h in environments that need it. + */ +#include PLATFORM_CONFIG_H +#elif defined(HAVE_CONFIG_H) +/* + * Most POSIX platforms use the 'configure' script to build config.h + */ +#include "../config.h" +#elif defined(__FreeBSD__) +/* + * Built-in definitions for FreeBSD. + */ +#define HAVE_DIRENT_D_NAMLEN 1 +#define HAVE_DIRENT_H 1 +#define HAVE_ERRNO_H 1 +#define HAVE_FCNTL_H 1 +#define HAVE_LIBARCHIVE 1 +#define HAVE_STDLIB_H 1 +#define HAVE_STRING_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_UNISTD_H 1 +#else +/* + * Warn if there's no platform configuration. + */ +#error Oops: No config.h and no built-in configuration in bsdtar_platform.h. +#endif /* !HAVE_CONFIG_H */ + +/* No non-FreeBSD platform will have __FBSDID, so just define it here. */ +#ifdef __FreeBSD__ +#include /* For __FBSDID */ +#else +/* Just leaving this macro replacement empty leads to a dangling semicolon. */ +#define __FBSDID(a) struct _undefined_hack +#endif + +#ifdef HAVE_LIBARCHIVE +/* If we're using the platform libarchive, include system headers. */ +#include +#include +#else +/* Otherwise, include user headers. */ +#include "archive.h" +#include "archive_entry.h" +#endif + +#endif /* !TREE_CONFIG_H_INCLUDED */ diff --git a/dependencies/libarchive-3.4.2/contrib/untar.c b/dependencies/libarchive-3.4.2/contrib/untar.c new file mode 100644 index 0000000..3d954f6 --- /dev/null +++ b/dependencies/libarchive-3.4.2/contrib/untar.c @@ -0,0 +1,229 @@ +/* + * This file is in the public domain. Use it as you see fit. + */ + +/* + * "untar" is an extremely simple tar extractor: + * * A single C source file, so it should be easy to compile + * and run on any system with a C compiler. + * * Extremely portable standard C. The only non-ANSI function + * used is mkdir(). + * * Reads basic ustar tar archives. + * * Does not require libarchive or any other special library. + * + * To compile: cc -o untar untar.c + * + * Usage: untar + * + * In particular, this program should be sufficient to extract the + * distribution for libarchive, allowing people to bootstrap + * libarchive on systems that do not already have a tar program. + * + * To unpack libarchive-x.y.z.tar.gz: + * * gunzip libarchive-x.y.z.tar.gz + * * untar libarchive-x.y.z.tar + * + * Written by Tim Kientzle, March 2009. + * + * Released into the public domain. + */ + +/* These are all highly standard and portable headers. */ +#include +#include +#include + +/* This is for mkdir(); this may need to be changed for some platforms. */ +#include /* For mkdir() */ + +/* Parse an octal number, ignoring leading and trailing nonsense. */ +static int +parseoct(const char *p, size_t n) +{ + int i = 0; + + while ((*p < '0' || *p > '7') && n > 0) { + ++p; + --n; + } + while (*p >= '0' && *p <= '7' && n > 0) { + i *= 8; + i += *p - '0'; + ++p; + --n; + } + return (i); +} + +/* Returns true if this is 512 zero bytes. */ +static int +is_end_of_archive(const char *p) +{ + int n; + for (n = 511; n >= 0; --n) + if (p[n] != '\0') + return (0); + return (1); +} + +/* Create a directory, including parent directories as necessary. */ +static void +create_dir(char *pathname, int mode) +{ + char *p; + int r; + + /* Strip trailing '/' */ + if (pathname[strlen(pathname) - 1] == '/') + pathname[strlen(pathname) - 1] = '\0'; + + /* Try creating the directory. */ + r = mkdir(pathname, mode); + + if (r != 0) { + /* On failure, try creating parent directory. */ + p = strrchr(pathname, '/'); + if (p != NULL) { + *p = '\0'; + create_dir(pathname, 0755); + *p = '/'; + r = mkdir(pathname, mode); + } + } + if (r != 0) + fprintf(stderr, "Could not create directory %s\n", pathname); +} + +/* Create a file, including parent directory as necessary. */ +static FILE * +create_file(char *pathname, int mode) +{ + FILE *f; + f = fopen(pathname, "wb+"); + if (f == NULL) { + /* Try creating parent dir and then creating file. */ + char *p = strrchr(pathname, '/'); + if (p != NULL) { + *p = '\0'; + create_dir(pathname, 0755); + *p = '/'; + f = fopen(pathname, "wb+"); + } + } + return (f); +} + +/* Verify the tar checksum. */ +static int +verify_checksum(const char *p) +{ + int n, u = 0; + for (n = 0; n < 512; ++n) { + if (n < 148 || n > 155) + /* Standard tar checksum adds unsigned bytes. */ + u += ((unsigned char *)p)[n]; + else + u += 0x20; + + } + return (u == parseoct(p + 148, 8)); +} + +/* Extract a tar archive. */ +static void +untar(FILE *a, const char *path) +{ + char buff[512]; + FILE *f = NULL; + size_t bytes_read; + int filesize; + + printf("Extracting from %s\n", path); + for (;;) { + bytes_read = fread(buff, 1, 512, a); + if (bytes_read < 512) { + fprintf(stderr, + "Short read on %s: expected 512, got %d\n", + path, (int)bytes_read); + return; + } + if (is_end_of_archive(buff)) { + printf("End of %s\n", path); + return; + } + if (!verify_checksum(buff)) { + fprintf(stderr, "Checksum failure\n"); + return; + } + filesize = parseoct(buff + 124, 12); + switch (buff[156]) { + case '1': + printf(" Ignoring hardlink %s\n", buff); + break; + case '2': + printf(" Ignoring symlink %s\n", buff); + break; + case '3': + printf(" Ignoring character device %s\n", buff); + break; + case '4': + printf(" Ignoring block device %s\n", buff); + break; + case '5': + printf(" Extracting dir %s\n", buff); + create_dir(buff, parseoct(buff + 100, 8)); + filesize = 0; + break; + case '6': + printf(" Ignoring FIFO %s\n", buff); + break; + default: + printf(" Extracting file %s\n", buff); + f = create_file(buff, parseoct(buff + 100, 8)); + break; + } + while (filesize > 0) { + bytes_read = fread(buff, 1, 512, a); + if (bytes_read < 512) { + fprintf(stderr, + "Short read on %s: Expected 512, got %d\n", + path, (int)bytes_read); + return; + } + if (filesize < 512) + bytes_read = filesize; + if (f != NULL) { + if (fwrite(buff, 1, bytes_read, f) + != bytes_read) + { + fprintf(stderr, "Failed write\n"); + fclose(f); + f = NULL; + } + } + filesize -= bytes_read; + } + if (f != NULL) { + fclose(f); + f = NULL; + } + } +} + +int +main(int argc, char **argv) +{ + FILE *a; + + ++argv; /* Skip program name */ + for ( ;*argv != NULL; ++argv) { + a = fopen(*argv, "rb"); + if (a == NULL) + fprintf(stderr, "Unable to open %s\n", *argv); + else { + untar(a, *argv); + fclose(a); + } + } + return (0); +} diff --git a/dependencies/libarchive-3.4.2/cpio/CMakeLists.txt b/dependencies/libarchive-3.4.2/cpio/CMakeLists.txt new file mode 100644 index 0000000..85fda77 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/CMakeLists.txt @@ -0,0 +1,48 @@ +############################################ +# +# How to build bsdcpio +# +############################################ +IF(ENABLE_CPIO) + + SET(bsdcpio_SOURCES + cmdline.c + cpio.c + cpio.h + cpio_platform.h + ../libarchive_fe/err.c + ../libarchive_fe/err.h + ../libarchive_fe/lafe_platform.h + ../libarchive_fe/line_reader.c + ../libarchive_fe/line_reader.h + ../libarchive_fe/passphrase.c + ../libarchive_fe/passphrase.h + ) + INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/test_utils) + INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../libarchive_fe) + IF(WIN32 AND NOT CYGWIN) + LIST(APPEND bsdcpio_SOURCES cpio_windows.c) + LIST(APPEND bsdcpio_SOURCES cpio_windows.h) + ENDIF(WIN32 AND NOT CYGWIN) + + # bsdcpio documentation + SET(bsdcpio_MANS bsdcpio.1) + + # How to build bsdcpio + ADD_EXECUTABLE(bsdcpio ${bsdcpio_SOURCES}) + IF(ENABLE_CPIO_SHARED) + TARGET_LINK_LIBRARIES(bsdcpio archive ${ADDITIONAL_LIBS}) + ELSE(ENABLE_CPIO_SHARED) + TARGET_LINK_LIBRARIES(bsdcpio archive_static ${ADDITIONAL_LIBS}) + SET_TARGET_PROPERTIES(bsdcpio PROPERTIES COMPILE_DEFINITIONS + LIBARCHIVE_STATIC) + ENDIF(ENABLE_CPIO_SHARED) + + # Installation rules + INSTALL(TARGETS bsdcpio RUNTIME DESTINATION bin) + INSTALL_MAN(${bsdcpio_MANS}) + +ENDIF(ENABLE_CPIO) + +# Test suite +add_subdirectory(test) diff --git a/dependencies/libarchive-3.4.2/cpio/bsdcpio.1 b/dependencies/libarchive-3.4.2/cpio/bsdcpio.1 new file mode 100644 index 0000000..514c1a2 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/bsdcpio.1 @@ -0,0 +1,435 @@ +.\" Copyright (c) 2003-2007 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd September 16, 2014 +.Dt CPIO 1 +.Os +.Sh NAME +.Nm cpio +.Nd copy files to and from archives +.Sh SYNOPSIS +.Nm +.Fl i +.Op Ar options +.Op Ar pattern ... +.Op Ar < archive +.Nm +.Fl o +.Op Ar options +.Ar < name-list +.Op Ar > archive +.Nm +.Fl p +.Op Ar options +.Ar dest-dir +.Ar < name-list +.Sh DESCRIPTION +.Nm +copies files between archives and directories. +This implementation can extract from tar, pax, cpio, zip, jar, ar, +and ISO 9660 cdrom images and can create tar, pax, cpio, ar, +and shar archives. +.Pp +The first option to +.Nm +is a mode indicator from the following list: +.Bl -tag -compact -width indent +.It Fl i +Input. +Read an archive from standard input (unless overridden) and extract the +contents to disk or (if the +.Fl t +option is specified) +list the contents to standard output. +If one or more file patterns are specified, only files matching +one of the patterns will be extracted. +.It Fl o +Output. +Read a list of filenames from standard input and produce a new archive +on standard output (unless overridden) containing the specified items. +.It Fl p +Pass-through. +Read a list of filenames from standard input and copy the files to the +specified directory. +.El +.Sh OPTIONS +Unless specifically stated otherwise, options are applicable in +all operating modes. +.Bl -tag -width indent +.It Fl 0 , Fl Fl null +Read filenames separated by NUL characters instead of newlines. +This is necessary if any of the filenames being read might contain newlines. +.It Fl A +(o mode only) +Append to the specified archive. +(Not yet implemented.) +.It Fl a +(o and p modes) +Reset access times on files after they are read. +.It Fl B +(o mode only) +Block output to records of 5120 bytes. +.It Fl C Ar size +(o mode only) +Block output to records of +.Ar size +bytes. +.It Fl c +(o mode only) +Use the old POSIX portable character format. +Equivalent to +.Fl Fl format Ar odc . +.It Fl d , Fl Fl make-directories +(i and p modes) +Create directories as necessary. +.It Fl E Ar file +(i mode only) +Read list of file name patterns from +.Ar file +to list and extract. +.It Fl F Ar file , Fl Fl file Ar file +Read archive from or write archive to +.Ar file . +.It Fl f Ar pattern +(i mode only) +Ignore files that match +.Ar pattern . +.It Fl H Ar format , Fl Fl format Ar format +(o mode only) +Produce the output archive in the specified format. +Supported formats include: +.Pp +.Bl -tag -width "iso9660" -compact +.It Ar cpio +Synonym for +.Ar odc . +.It Ar newc +The SVR4 portable cpio format. +.It Ar odc +The old POSIX.1 portable octet-oriented cpio format. +.It Ar pax +The POSIX.1 pax format, an extension of the ustar format. +.It Ar ustar +The POSIX.1 tar format. +.El +.Pp +The default format is +.Ar odc . +See +.Xr libarchive-formats 5 +for more complete information about the +formats currently supported by the underlying +.Xr libarchive 3 +library. +.It Fl h , Fl Fl help +Print usage information. +.It Fl I Ar file +Read archive from +.Ar file . +.It Fl i , Fl Fl extract +Input mode. +See above for description. +.It Fl Fl insecure +(i and p mode only) +Disable security checks during extraction or copying. +This allows extraction via symbolic links, absolute paths, +and path names containing +.Sq .. +in the name. +.It Fl J , Fl Fl xz +(o mode only) +Compress the file with xz-compatible compression before writing it. +In input mode, this option is ignored; xz compression is recognized +automatically on input. +.It Fl j +Synonym for +.Fl y . +.It Fl L +(o and p modes) +All symbolic links will be followed. +Normally, symbolic links are archived and copied as symbolic links. +With this option, the target of the link will be archived or copied instead. +.It Fl l , Fl Fl link +(p mode only) +Create links from the target directory to the original files, +instead of copying. +.It Fl Fl lrzip +(o mode only) +Compress the resulting archive with +.Xr lrzip 1 . +In input mode, this option is ignored. +.It Fl Fl lz4 +(o mode only) +Compress the archive with lz4-compatible compression before writing it. +In input mode, this option is ignored; lz4 compression is recognized +automatically on input. +.It Fl Fl zstd +(o mode only) +Compress the archive with zstd-compatible compression before writing it. +In input mode, this option is ignored; zstd compression is recognized +automatically on input. +.It Fl Fl lzma +(o mode only) +Compress the file with lzma-compatible compression before writing it. +In input mode, this option is ignored; lzma compression is recognized +automatically on input. +.It Fl Fl lzop +(o mode only) +Compress the resulting archive with +.Xr lzop 1 . +In input mode, this option is ignored. +.It Fl Fl passphrase Ar passphrase +The +.Pa passphrase +is used to extract or create an encrypted archive. +Currently, zip is only a format that +.Nm +can handle encrypted archives. +You shouldn't use this option unless you realize how insecure +use of this option is. +.It Fl m , Fl Fl preserve-modification-time +(i and p modes) +Set file modification time on created files to match +those in the source. +.It Fl n , Fl Fl numeric-uid-gid +(i mode, only with +.Fl t ) +Display numeric uid and gid. +By default, +.Nm +displays the user and group names when they are provided in the +archive, or looks up the user and group names in the system +password database. +.It Fl Fl no-preserve-owner +(i mode only) +Do not attempt to restore file ownership. +This is the default when run by non-root users. +.It Fl O Ar file +Write archive to +.Ar file . +.It Fl o , Fl Fl create +Output mode. +See above for description. +.It Fl p , Fl Fl pass-through +Pass-through mode. +See above for description. +.It Fl Fl preserve-owner +(i mode only) +Restore file ownership. +This is the default when run by the root user. +.It Fl Fl quiet +Suppress unnecessary messages. +.It Fl R Oo user Oc Ns Oo : Oc Ns Oo group Oc , Fl Fl owner Oo user Oc Ns Oo : Oc Ns Oo group Oc +Set the owner and/or group on files in the output. +If group is specified with no user +(for example, +.Fl R Ar :wheel ) +then the group will be set but not the user. +If the user is specified with a trailing colon and no group +(for example, +.Fl R Ar root: ) +then the group will be set to the user's default group. +If the user is specified with no trailing colon, then +the user will be set but not the group. +In +.Fl i +and +.Fl p +modes, this option can only be used by the super-user. +(For compatibility, a period can be used in place of the colon.) +.It Fl r +(All modes.) +Rename files interactively. +For each file, a prompt is written to +.Pa /dev/tty +containing the name of the file and a line is read from +.Pa /dev/tty . +If the line read is blank, the file is skipped. +If the line contains a single period, the file is processed normally. +Otherwise, the line is taken to be the new name of the file. +.It Fl t , Fl Fl list +(i mode only) +List the contents of the archive to stdout; +do not restore the contents to disk. +.It Fl u , Fl Fl unconditional +(i and p modes) +Unconditionally overwrite existing files. +Ordinarily, an older file will not overwrite a newer file on disk. +.It Fl V , Fl Fl dot +Print a dot to stderr for each file as it is processed. +Superseded by +.Fl v . +.It Fl v , Fl Fl verbose +Print the name of each file to stderr as it is processed. +With +.Fl t , +provide a detailed listing of each file. +.It Fl Fl version +Print the program version information and exit. +.It Fl y +(o mode only) +Compress the archive with bzip2-compatible compression before writing it. +In input mode, this option is ignored; +bzip2 compression is recognized automatically on input. +.It Fl Z +(o mode only) +Compress the archive with compress-compatible compression before writing it. +In input mode, this option is ignored; +compression is recognized automatically on input. +.It Fl z +(o mode only) +Compress the archive with gzip-compatible compression before writing it. +In input mode, this option is ignored; +gzip compression is recognized automatically on input. +.El +.Sh EXIT STATUS +.Ex -std +.Sh ENVIRONMENT +The following environment variables affect the execution of +.Nm : +.Bl -tag -width ".Ev BLOCKSIZE" +.It Ev LANG +The locale to use. +See +.Xr environ 7 +for more information. +.It Ev TZ +The timezone to use when displaying dates. +See +.Xr environ 7 +for more information. +.El +.Sh EXAMPLES +The +.Nm +command is traditionally used to copy file hierarchies in conjunction +with the +.Xr find 1 +command. +The first example here simply copies all files from +.Pa src +to +.Pa dest : +.Dl Nm find Pa src | Nm Fl pmud Pa dest +.Pp +By carefully selecting options to the +.Xr find 1 +command and combining it with other standard utilities, +it is possible to exercise very fine control over which files are copied. +This next example copies files from +.Pa src +to +.Pa dest +that are more than 2 days old and whose names match a particular pattern: +.Dl Nm find Pa src Fl mtime Ar +2 | Nm grep foo[bar] | Nm Fl pdmu Pa dest +.Pp +This example copies files from +.Pa src +to +.Pa dest +that are more than 2 days old and which contain the word +.Do foobar Dc : +.Dl Nm find Pa src Fl mtime Ar +2 | Nm xargs Nm grep -l foobar | Nm Fl pdmu Pa dest +.Sh COMPATIBILITY +The mode options i, o, and p and the options +a, B, c, d, f, l, m, r, t, u, and v comply with SUSv2. +.Pp +The old POSIX.1 standard specified that only +.Fl i , +.Fl o , +and +.Fl p +were interpreted as command-line options. +Each took a single argument of a list of modifier +characters. +For example, the standard syntax allows +.Fl imu +but does not support +.Fl miu +or +.Fl i Fl m Fl u , +since +.Ar m +and +.Ar u +are only modifiers to +.Fl i , +they are not command-line options in their own right. +The syntax supported by this implementation is backwards-compatible +with the standard. +For best compatibility, scripts should limit themselves to the +standard syntax. +.Sh SEE ALSO +.Xr bzip2 1 , +.Xr gzip 1 , +.Xr mt 1 , +.Xr pax 1 , +.Xr tar 1 , +.Xr libarchive 3 , +.Xr cpio 5 , +.Xr libarchive-formats 5 , +.Xr tar 5 +.Sh STANDARDS +There is no current POSIX standard for the cpio command; it appeared +in +.St -p1003.1-96 +but was dropped from +.St -p1003.1-2001 . +.Pp +The cpio, ustar, and pax interchange file formats are defined by +.St -p1003.1-2001 +for the pax command. +.Sh HISTORY +The original +.Nm cpio +and +.Nm find +utilities were written by Dick Haight +while working in AT&T's Unix Support Group. +They first appeared in 1977 in PWB/UNIX 1.0, the +.Dq Programmer's Work Bench +system developed for use within AT&T. +They were first released outside of AT&T as part of System III Unix in 1981. +As a result, +.Nm cpio +actually predates +.Nm tar , +even though it was not well-known outside of AT&T until some time later. +.Pp +This is a complete re-implementation based on the +.Xr libarchive 3 +library. +.Sh BUGS +The cpio archive format has several basic limitations: +It does not store user and group names, only numbers. +As a result, it cannot be reliably used to transfer +files between systems with dissimilar user and group numbering. +Older cpio formats limit the user and group numbers to +16 or 18 bits, which is insufficient for modern systems. +The cpio archive formats cannot support files over 4 gigabytes, +except for the +.Dq odc +variant, which can support files up to 8 gigabytes. diff --git a/dependencies/libarchive-3.4.2/cpio/cmdline.c b/dependencies/libarchive-3.4.2/cpio/cmdline.c new file mode 100644 index 0000000..c8fc30e --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/cmdline.c @@ -0,0 +1,382 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "cpio_platform.h" +__FBSDID("$FreeBSD: src/usr.bin/cpio/cmdline.c,v 1.5 2008/12/06 07:30:40 kientzle Exp $"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_GRP_H +#include +#endif +#ifdef HAVE_PWD_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "cpio.h" +#include "err.h" + +/* + * Short options for cpio. Please keep this sorted. + */ +static const char *short_options = "0AaBC:cdE:F:f:H:hI:iJjLlmnO:opR:rtuVvW:yZz"; + +/* + * Long options for cpio. Please keep this sorted. + */ +static const struct option { + const char *name; + int required; /* 1 if this option requires an argument */ + int equivalent; /* Equivalent short option. */ +} cpio_longopts[] = { + { "b64encode", 0, OPTION_B64ENCODE }, + { "create", 0, 'o' }, + { "dereference", 0, 'L' }, + { "dot", 0, 'V' }, + { "extract", 0, 'i' }, + { "file", 1, 'F' }, + { "format", 1, 'H' }, + { "grzip", 0, OPTION_GRZIP }, + { "help", 0, 'h' }, + { "insecure", 0, OPTION_INSECURE }, + { "link", 0, 'l' }, + { "list", 0, 't' }, + { "lrzip", 0, OPTION_LRZIP }, + { "lz4", 0, OPTION_LZ4 }, + { "lzma", 0, OPTION_LZMA }, + { "lzop", 0, OPTION_LZOP }, + { "make-directories", 0, 'd' }, + { "no-preserve-owner", 0, OPTION_NO_PRESERVE_OWNER }, + { "null", 0, '0' }, + { "numeric-uid-gid", 0, 'n' }, + { "owner", 1, 'R' }, + { "passphrase", 1, OPTION_PASSPHRASE }, + { "pass-through", 0, 'p' }, + { "preserve-modification-time", 0, 'm' }, + { "preserve-owner", 0, OPTION_PRESERVE_OWNER }, + { "quiet", 0, OPTION_QUIET }, + { "unconditional", 0, 'u' }, + { "uuencode", 0, OPTION_UUENCODE }, + { "verbose", 0, 'v' }, + { "version", 0, OPTION_VERSION }, + { "xz", 0, 'J' }, + { "zstd", 0, OPTION_ZSTD }, + { NULL, 0, 0 } +}; + +/* + * I used to try to select platform-provided getopt() or + * getopt_long(), but that caused a lot of headaches. In particular, + * I couldn't consistently use long options in the test harness + * because not all platforms have getopt_long(). That in turn led to + * overuse of the -W hack in the test harness, which made it rough to + * run the test harness against GNU cpio. (I periodically run the + * test harness here against GNU cpio as a sanity-check. Yes, + * I've found a couple of bugs in GNU cpio that way.) + */ +int +cpio_getopt(struct cpio *cpio) +{ + enum { state_start = 0, state_next_word, state_short, state_long }; + static int state = state_start; + static char *opt_word; + + const struct option *popt, *match = NULL, *match2 = NULL; + const char *p, *long_prefix = "--"; + size_t optlength; + int opt = '?'; + int required = 0; + + cpio->argument = NULL; + + /* First time through, initialize everything. */ + if (state == state_start) { + /* Skip program name. */ + ++cpio->argv; + --cpio->argc; + state = state_next_word; + } + + /* + * We're ready to look at the next word in argv. + */ + if (state == state_next_word) { + /* No more arguments, so no more options. */ + if (cpio->argv[0] == NULL) + return (-1); + /* Doesn't start with '-', so no more options. */ + if (cpio->argv[0][0] != '-') + return (-1); + /* "--" marks end of options; consume it and return. */ + if (strcmp(cpio->argv[0], "--") == 0) { + ++cpio->argv; + --cpio->argc; + return (-1); + } + /* Get next word for parsing. */ + opt_word = *cpio->argv++; + --cpio->argc; + if (opt_word[1] == '-') { + /* Set up long option parser. */ + state = state_long; + opt_word += 2; /* Skip leading '--' */ + } else { + /* Set up short option parser. */ + state = state_short; + ++opt_word; /* Skip leading '-' */ + } + } + + /* + * We're parsing a group of POSIX-style single-character options. + */ + if (state == state_short) { + /* Peel next option off of a group of short options. */ + opt = *opt_word++; + if (opt == '\0') { + /* End of this group; recurse to get next option. */ + state = state_next_word; + return cpio_getopt(cpio); + } + + /* Does this option take an argument? */ + p = strchr(short_options, opt); + if (p == NULL) + return ('?'); + if (p[1] == ':') + required = 1; + + /* If it takes an argument, parse that. */ + if (required) { + /* If arg is run-in, opt_word already points to it. */ + if (opt_word[0] == '\0') { + /* Otherwise, pick up the next word. */ + opt_word = *cpio->argv; + if (opt_word == NULL) { + lafe_warnc(0, + "Option -%c requires an argument", + opt); + return ('?'); + } + ++cpio->argv; + --cpio->argc; + } + if (opt == 'W') { + state = state_long; + long_prefix = "-W "; /* For clearer errors. */ + } else { + state = state_next_word; + cpio->argument = opt_word; + } + } + } + + /* We're reading a long option, including -W long=arg convention. */ + if (state == state_long) { + /* After this long option, we'll be starting a new word. */ + state = state_next_word; + + /* Option name ends at '=' if there is one. */ + p = strchr(opt_word, '='); + if (p != NULL) { + optlength = (size_t)(p - opt_word); + cpio->argument = (char *)(uintptr_t)(p + 1); + } else { + optlength = strlen(opt_word); + } + + /* Search the table for an unambiguous match. */ + for (popt = cpio_longopts; popt->name != NULL; popt++) { + /* Short-circuit if first chars don't match. */ + if (popt->name[0] != opt_word[0]) + continue; + /* If option is a prefix of name in table, record it.*/ + if (strncmp(opt_word, popt->name, optlength) == 0) { + match2 = match; /* Record up to two matches. */ + match = popt; + /* If it's an exact match, we're done. */ + if (strlen(popt->name) == optlength) { + match2 = NULL; /* Forget the others. */ + break; + } + } + } + + /* Fail if there wasn't a unique match. */ + if (match == NULL) { + lafe_warnc(0, + "Option %s%s is not supported", + long_prefix, opt_word); + return ('?'); + } + if (match2 != NULL) { + lafe_warnc(0, + "Ambiguous option %s%s (matches --%s and --%s)", + long_prefix, opt_word, match->name, match2->name); + return ('?'); + } + + /* We've found a unique match; does it need an argument? */ + if (match->required) { + /* Argument required: get next word if necessary. */ + if (cpio->argument == NULL) { + cpio->argument = *cpio->argv; + if (cpio->argument == NULL) { + lafe_warnc(0, + "Option %s%s requires an argument", + long_prefix, match->name); + return ('?'); + } + ++cpio->argv; + --cpio->argc; + } + } else { + /* Argument forbidden: fail if there is one. */ + if (cpio->argument != NULL) { + lafe_warnc(0, + "Option %s%s does not allow an argument", + long_prefix, match->name); + return ('?'); + } + } + return (match->equivalent); + } + + return (opt); +} + + +/* + * Parse the argument to the -R or --owner flag. + * + * The format is one of the following: + * - Override user but not group + * : - Override both, group is user's default group + * : - Override user but not group + * : - Override both + * : - Override group but not user + * + * Where uid/gid are decimal representations and groupname/username + * are names to be looked up in system database. Note that we try + * to look up an argument as a name first, then try numeric parsing. + * + * A period can be used instead of the colon. + * + * Sets uid/gid return as appropriate, -1 indicates uid/gid not specified. + * TODO: If the spec uses uname/gname, then return those to the caller + * as well. If the spec provides uid/gid, just return names as NULL. + * + * Returns NULL if no error, otherwise returns error string for display. + * + */ +const char * +owner_parse(const char *spec, int *uid, int *gid) +{ + static char errbuff[128]; + const char *u, *ue, *g; + + *uid = -1; + *gid = -1; + + if (spec[0] == '\0') + return ("Invalid empty user/group spec"); + + /* + * Split spec into [user][:.][group] + * u -> first char of username, NULL if no username + * ue -> first char after username (colon, period, or \0) + * g -> first char of group name + */ + if (*spec == ':' || *spec == '.') { + /* If spec starts with ':' or '.', then just group. */ + ue = u = NULL; + g = spec + 1; + } else { + /* Otherwise, [user] or [user][:] or [user][:][group] */ + ue = u = spec; + while (*ue != ':' && *ue != '.' && *ue != '\0') + ++ue; + g = ue; + if (*g != '\0') /* Skip : or . to find first char of group. */ + ++g; + } + + if (u != NULL) { + /* Look up user: ue is first char after end of user. */ + char *user; + struct passwd *pwent; + + user = (char *)malloc(ue - u + 1); + if (user == NULL) + return ("Couldn't allocate memory"); + memcpy(user, u, ue - u); + user[ue - u] = '\0'; + if ((pwent = getpwnam(user)) != NULL) { + *uid = pwent->pw_uid; + if (*ue != '\0') + *gid = pwent->pw_gid; + } else { + char *end; + errno = 0; + *uid = (int)strtoul(user, &end, 10); + if (errno || *end != '\0') { + snprintf(errbuff, sizeof(errbuff), + "Couldn't lookup user ``%s''", user); + errbuff[sizeof(errbuff) - 1] = '\0'; + free(user); + return (errbuff); + } + } + free(user); + } + + if (*g != '\0') { + struct group *grp; + if ((grp = getgrnam(g)) != NULL) { + *gid = grp->gr_gid; + } else { + char *end; + errno = 0; + *gid = (int)strtoul(g, &end, 10); + if (errno || *end != '\0') { + snprintf(errbuff, sizeof(errbuff), + "Couldn't lookup group ``%s''", g); + errbuff[sizeof(errbuff) - 1] = '\0'; + return (errbuff); + } + } + } + return (NULL); +} diff --git a/dependencies/libarchive-3.4.2/cpio/config_freebsd.h b/dependencies/libarchive-3.4.2/cpio/config_freebsd.h new file mode 100644 index 0000000..00c4c73 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/config_freebsd.h @@ -0,0 +1,56 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: src/usr.bin/cpio/config_freebsd.h,v 1.3 2008/12/06 07:30:40 kientzle Exp $ + */ + +/* A hand-tooled configuration for FreeBSD. */ + +#include /* __FreeBSD_version */ + +#define HAVE_DIRENT_H 1 +#define HAVE_ERRNO_H 1 +#define HAVE_FCNTL_H 1 +#define HAVE_FUTIMES 1 +#define HAVE_GRP_H 1 +#define HAVE_LIBARCHIVE 1 +#define HAVE_LINK 1 +#define HAVE_LSTAT 1 +#define HAVE_LUTIMES 1 +#define HAVE_PWD_H 1 +#define HAVE_READLINK 1 +#define HAVE_STDARG_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_STRING_H 1 +#define HAVE_SYMLINK 1 +#define HAVE_SYS_CDEFS_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_SYS_TIME_H 1 +#define HAVE_TIME_H 1 +#define HAVE_UINTMAX_T 1 +#define HAVE_UNISTD_H 1 +#define HAVE_UNSIGNED_LONG_LONG 1 +#define HAVE_UTIME_H 1 +#define HAVE_UTIMES 1 + diff --git a/dependencies/libarchive-3.4.2/cpio/cpio.c b/dependencies/libarchive-3.4.2/cpio/cpio.c new file mode 100644 index 0000000..da5c398 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/cpio.c @@ -0,0 +1,1507 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "cpio_platform.h" +__FBSDID("$FreeBSD: src/usr.bin/cpio/cpio.c,v 1.15 2008/12/06 07:30:40 kientzle Exp $"); + +#include +#include +#include + +#ifdef HAVE_SYS_MKDEV_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_GRP_H +#include +#endif +#ifdef HAVE_LOCALE_H +#include +#endif +#ifdef HAVE_PWD_H +#include +#endif +#ifdef HAVE_SIGNAL_H +#include +#endif +#ifdef HAVE_STDARG_H +#include +#endif +#ifdef HAVE_STDINT_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_TIME_H +#include +#endif + +#include "cpio.h" +#include "err.h" +#include "line_reader.h" +#include "passphrase.h" + +/* Fixed size of uname/gname caches. */ +#define name_cache_size 101 + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +struct name_cache { + int probes; + int hits; + size_t size; + struct { + id_t id; + char *name; + } cache[name_cache_size]; +}; + +static int extract_data(struct archive *, struct archive *); +const char * cpio_i64toa(int64_t); +static const char *cpio_rename(const char *name); +static int entry_to_archive(struct cpio *, struct archive_entry *); +static int file_to_archive(struct cpio *, const char *); +static void free_cache(struct name_cache *cache); +static void list_item_verbose(struct cpio *, struct archive_entry *); +static void long_help(void) __LA_DEAD; +static const char *lookup_gname(struct cpio *, gid_t gid); +static int lookup_gname_helper(struct cpio *, + const char **name, id_t gid); +static const char *lookup_uname(struct cpio *, uid_t uid); +static int lookup_uname_helper(struct cpio *, + const char **name, id_t uid); +static void mode_in(struct cpio *) __LA_DEAD; +static void mode_list(struct cpio *) __LA_DEAD; +static void mode_out(struct cpio *); +static void mode_pass(struct cpio *, const char *); +static const char *remove_leading_slash(const char *); +static int restore_time(struct cpio *, struct archive_entry *, + const char *, int fd); +static void usage(void) __LA_DEAD; +static void version(void) __LA_DEAD; +static const char * passphrase_callback(struct archive *, void *); +static void passphrase_free(char *); + +int +main(int argc, char *argv[]) +{ + static char buff[16384]; + struct cpio _cpio; /* Allocated on stack. */ + struct cpio *cpio; + const char *errmsg; + char *tptr; + int uid, gid; + int opt, t; + + cpio = &_cpio; + memset(cpio, 0, sizeof(*cpio)); + cpio->buff = buff; + cpio->buff_size = sizeof(buff); + +#if defined(HAVE_SIGACTION) && defined(SIGPIPE) + { /* Ignore SIGPIPE signals. */ + struct sigaction sa; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &sa, NULL); + } +#endif + + /* Set lafe_progname before calling lafe_warnc. */ + lafe_setprogname(*argv, "bsdcpio"); + +#if HAVE_SETLOCALE + if (setlocale(LC_ALL, "") == NULL) + lafe_warnc(0, "Failed to set default locale"); +#endif + + cpio->uid_override = -1; + cpio->gid_override = -1; + cpio->argv = argv; + cpio->argc = argc; + cpio->mode = '\0'; + cpio->verbose = 0; + cpio->compress = '\0'; + cpio->extract_flags = ARCHIVE_EXTRACT_NO_AUTODIR; + cpio->extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER; + cpio->extract_flags |= ARCHIVE_EXTRACT_SECURE_SYMLINKS; + cpio->extract_flags |= ARCHIVE_EXTRACT_SECURE_NODOTDOT; + cpio->extract_flags |= ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS; + cpio->extract_flags |= ARCHIVE_EXTRACT_PERM; + cpio->extract_flags |= ARCHIVE_EXTRACT_FFLAGS; + cpio->extract_flags |= ARCHIVE_EXTRACT_ACL; +#if !defined(_WIN32) && !defined(__CYGWIN__) + if (geteuid() == 0) + cpio->extract_flags |= ARCHIVE_EXTRACT_OWNER; +#endif + cpio->bytes_per_block = 512; + cpio->filename = NULL; + + cpio->matching = archive_match_new(); + if (cpio->matching == NULL) + lafe_errc(1, 0, "Out of memory"); + + while ((opt = cpio_getopt(cpio)) != -1) { + switch (opt) { + case '0': /* GNU convention: --null, -0 */ + cpio->option_null = 1; + break; + case 'A': /* NetBSD/OpenBSD */ + cpio->option_append = 1; + break; + case 'a': /* POSIX 1997 */ + cpio->option_atime_restore = 1; + break; + case 'B': /* POSIX 1997 */ + cpio->bytes_per_block = 5120; + break; + case OPTION_B64ENCODE: + cpio->add_filter = opt; + break; + case 'C': /* NetBSD/OpenBSD */ + errno = 0; + tptr = NULL; + t = (int)strtol(cpio->argument, &tptr, 10); + if (errno || t <= 0 || *(cpio->argument) == '\0' || + tptr == NULL || *tptr != '\0') { + lafe_errc(1, 0, "Invalid blocksize: %s", + cpio->argument); + } + cpio->bytes_per_block = t; + break; + case 'c': /* POSIX 1997 */ + cpio->format = "odc"; + break; + case 'd': /* POSIX 1997 */ + cpio->extract_flags &= ~ARCHIVE_EXTRACT_NO_AUTODIR; + break; + case 'E': /* NetBSD/OpenBSD */ + if (archive_match_include_pattern_from_file( + cpio->matching, cpio->argument, + cpio->option_null) != ARCHIVE_OK) + lafe_errc(1, 0, "Error : %s", + archive_error_string(cpio->matching)); + break; + case 'F': /* NetBSD/OpenBSD/GNU cpio */ + cpio->filename = cpio->argument; + break; + case 'f': /* POSIX 1997 */ + if (archive_match_exclude_pattern(cpio->matching, + cpio->argument) != ARCHIVE_OK) + lafe_errc(1, 0, "Error : %s", + archive_error_string(cpio->matching)); + break; + case OPTION_GRZIP: + cpio->compress = opt; + break; + case 'H': /* GNU cpio (also --format) */ + cpio->format = cpio->argument; + break; + case 'h': + long_help(); + break; + case 'I': /* NetBSD/OpenBSD */ + cpio->filename = cpio->argument; + break; + case 'i': /* POSIX 1997 */ + if (cpio->mode != '\0') + lafe_errc(1, 0, + "Cannot use both -i and -%c", cpio->mode); + cpio->mode = opt; + break; + case 'J': /* GNU tar, others */ + cpio->compress = opt; + break; + case 'j': /* GNU tar, others */ + cpio->compress = opt; + break; + case OPTION_INSECURE: + cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_SYMLINKS; + cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NODOTDOT; + cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS; + break; + case 'L': /* GNU cpio */ + cpio->option_follow_links = 1; + break; + case 'l': /* POSIX 1997 */ + cpio->option_link = 1; + break; + case OPTION_LRZIP: + case OPTION_LZ4: + case OPTION_LZMA: /* GNU tar, others */ + case OPTION_LZOP: /* GNU tar, others */ + case OPTION_ZSTD: + cpio->compress = opt; + break; + case 'm': /* POSIX 1997 */ + cpio->extract_flags |= ARCHIVE_EXTRACT_TIME; + break; + case 'n': /* GNU cpio */ + cpio->option_numeric_uid_gid = 1; + break; + case OPTION_NO_PRESERVE_OWNER: /* GNU cpio */ + cpio->extract_flags &= ~ARCHIVE_EXTRACT_OWNER; + break; + case 'O': /* GNU cpio */ + cpio->filename = cpio->argument; + break; + case 'o': /* POSIX 1997 */ + if (cpio->mode != '\0') + lafe_errc(1, 0, + "Cannot use both -o and -%c", cpio->mode); + cpio->mode = opt; + break; + case 'p': /* POSIX 1997 */ + if (cpio->mode != '\0') + lafe_errc(1, 0, + "Cannot use both -p and -%c", cpio->mode); + cpio->mode = opt; + cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NODOTDOT; + cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS; + break; + case OPTION_PASSPHRASE: + cpio->passphrase = cpio->argument; + break; + case OPTION_PRESERVE_OWNER: + cpio->extract_flags |= ARCHIVE_EXTRACT_OWNER; + break; + case OPTION_QUIET: /* GNU cpio */ + cpio->quiet = 1; + break; + case 'R': /* GNU cpio, also --owner */ + /* TODO: owner_parse should return uname/gname + * also; use that to set [ug]name_override. */ + errmsg = owner_parse(cpio->argument, &uid, &gid); + if (errmsg) { + lafe_warnc(-1, "%s", errmsg); + usage(); + } + if (uid != -1) { + cpio->uid_override = uid; + cpio->uname_override = NULL; + } + if (gid != -1) { + cpio->gid_override = gid; + cpio->gname_override = NULL; + } + break; + case 'r': /* POSIX 1997 */ + cpio->option_rename = 1; + break; + case 't': /* POSIX 1997 */ + cpio->option_list = 1; + break; + case 'u': /* POSIX 1997 */ + cpio->extract_flags + &= ~ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER; + break; + case OPTION_UUENCODE: + cpio->add_filter = opt; + break; + case 'v': /* POSIX 1997 */ + cpio->verbose++; + break; + case 'V': /* GNU cpio */ + cpio->dot++; + break; + case OPTION_VERSION: /* GNU convention */ + version(); + break; +#if 0 + /* + * cpio_getopt() handles -W specially, so it's not + * available here. + */ + case 'W': /* Obscure, but useful GNU convention. */ + break; +#endif + case 'y': /* tar convention */ + cpio->compress = opt; + break; + case 'Z': /* tar convention */ + cpio->compress = opt; + break; + case 'z': /* tar convention */ + cpio->compress = opt; + break; + default: + usage(); + } + } + + /* + * Sanity-check args, error out on nonsensical combinations. + */ + /* -t implies -i if no mode was specified. */ + if (cpio->option_list && cpio->mode == '\0') + cpio->mode = 'i'; + /* -t requires -i */ + if (cpio->option_list && cpio->mode != 'i') + lafe_errc(1, 0, "Option -t requires -i"); + /* -n requires -it */ + if (cpio->option_numeric_uid_gid && !cpio->option_list) + lafe_errc(1, 0, "Option -n requires -it"); + /* Can only specify format when writing */ + if (cpio->format != NULL && cpio->mode != 'o') + lafe_errc(1, 0, "Option --format requires -o"); + /* -l requires -p */ + if (cpio->option_link && cpio->mode != 'p') + lafe_errc(1, 0, "Option -l requires -p"); + /* -v overrides -V */ + if (cpio->dot && cpio->verbose) + cpio->dot = 0; + /* TODO: Flag other nonsensical combinations. */ + + switch (cpio->mode) { + case 'o': + /* TODO: Implement old binary format in libarchive, + use that here. */ + if (cpio->format == NULL) + cpio->format = "odc"; /* Default format */ + + mode_out(cpio); + break; + case 'i': + while (*cpio->argv != NULL) { + if (archive_match_include_pattern(cpio->matching, + *cpio->argv) != ARCHIVE_OK) + lafe_errc(1, 0, "Error : %s", + archive_error_string(cpio->matching)); + --cpio->argc; + ++cpio->argv; + } + if (cpio->option_list) + mode_list(cpio); + else + mode_in(cpio); + break; + case 'p': + if (*cpio->argv == NULL || **cpio->argv == '\0') + lafe_errc(1, 0, + "-p mode requires a target directory"); + mode_pass(cpio, *cpio->argv); + break; + default: + lafe_errc(1, 0, + "Must specify at least one of -i, -o, or -p"); + } + + archive_match_free(cpio->matching); + free_cache(cpio->gname_cache); + free_cache(cpio->uname_cache); + free(cpio->destdir); + passphrase_free(cpio->ppbuff); + return (cpio->return_value); +} + +static void +usage(void) +{ + const char *p; + + p = lafe_getprogname(); + + fprintf(stderr, "Brief Usage:\n"); + fprintf(stderr, " List: %s -it < archive\n", p); + fprintf(stderr, " Extract: %s -i < archive\n", p); + fprintf(stderr, " Create: %s -o < filenames > archive\n", p); + fprintf(stderr, " Help: %s --help\n", p); + exit(1); +} + +static const char *long_help_msg = + "First option must be a mode specifier:\n" + " -i Input -o Output -p Pass\n" + "Common Options:\n" + " -v Verbose filenames -V one dot per file\n" + "Create: %p -o [options] < [list of files] > [archive]\n" + " -J,-y,-z,--lzma Compress archive with xz/bzip2/gzip/lzma\n" + " --format {odc|newc|ustar} Select archive format\n" + "List: %p -it < [archive]\n" + "Extract: %p -i [options] < [archive]\n"; + + +/* + * Note that the word 'bsdcpio' will always appear in the first line + * of output. + * + * In particular, /bin/sh scripts that need to test for the presence + * of bsdcpio can use the following template: + * + * if (cpio --help 2>&1 | grep bsdcpio >/dev/null 2>&1 ) then \ + * echo bsdcpio; else echo not bsdcpio; fi + */ +static void +long_help(void) +{ + const char *prog; + const char *p; + + prog = lafe_getprogname(); + + fflush(stderr); + + p = (strcmp(prog,"bsdcpio") != 0) ? "(bsdcpio)" : ""; + printf("%s%s: manipulate archive files\n", prog, p); + + for (p = long_help_msg; *p != '\0'; p++) { + if (*p == '%') { + if (p[1] == 'p') { + fputs(prog, stdout); + p++; + } else + putchar('%'); + } else + putchar(*p); + } + version(); +} + +static void +version(void) +{ + fprintf(stdout,"bsdcpio %s - %s \n", + BSDCPIO_VERSION_STRING, + archive_version_details()); + exit(0); +} + +static void +mode_out(struct cpio *cpio) +{ + struct archive_entry *entry, *spare; + struct lafe_line_reader *lr; + const char *p; + int r; + + if (cpio->option_append) + lafe_errc(1, 0, "Append mode not yet supported."); + + cpio->archive_read_disk = archive_read_disk_new(); + if (cpio->archive_read_disk == NULL) + lafe_errc(1, 0, "Failed to allocate archive object"); + if (cpio->option_follow_links) + archive_read_disk_set_symlink_logical(cpio->archive_read_disk); + else + archive_read_disk_set_symlink_physical(cpio->archive_read_disk); + archive_read_disk_set_standard_lookup(cpio->archive_read_disk); + + cpio->archive = archive_write_new(); + if (cpio->archive == NULL) + lafe_errc(1, 0, "Failed to allocate archive object"); + switch (cpio->compress) { + case OPTION_GRZIP: + r = archive_write_add_filter_grzip(cpio->archive); + break; + case 'J': + r = archive_write_add_filter_xz(cpio->archive); + break; + case OPTION_LRZIP: + r = archive_write_add_filter_lrzip(cpio->archive); + break; + case OPTION_LZ4: + r = archive_write_add_filter_lz4(cpio->archive); + break; + case OPTION_LZMA: + r = archive_write_add_filter_lzma(cpio->archive); + break; + case OPTION_LZOP: + r = archive_write_add_filter_lzop(cpio->archive); + break; + case OPTION_ZSTD: + r = archive_write_add_filter_zstd(cpio->archive); + break; + case 'j': case 'y': + r = archive_write_add_filter_bzip2(cpio->archive); + break; + case 'z': + r = archive_write_add_filter_gzip(cpio->archive); + break; + case 'Z': + r = archive_write_add_filter_compress(cpio->archive); + break; + default: + r = archive_write_add_filter_none(cpio->archive); + break; + } + if (r < ARCHIVE_WARN) + lafe_errc(1, 0, "Requested compression not available"); + switch (cpio->add_filter) { + case 0: + r = ARCHIVE_OK; + break; + case OPTION_B64ENCODE: + r = archive_write_add_filter_b64encode(cpio->archive); + break; + case OPTION_UUENCODE: + r = archive_write_add_filter_uuencode(cpio->archive); + break; + } + if (r < ARCHIVE_WARN) + lafe_errc(1, 0, "Requested filter not available"); + r = archive_write_set_format_by_name(cpio->archive, cpio->format); + if (r != ARCHIVE_OK) + lafe_errc(1, 0, "%s", archive_error_string(cpio->archive)); + archive_write_set_bytes_per_block(cpio->archive, cpio->bytes_per_block); + cpio->linkresolver = archive_entry_linkresolver_new(); + archive_entry_linkresolver_set_strategy(cpio->linkresolver, + archive_format(cpio->archive)); + if (cpio->passphrase != NULL) + r = archive_write_set_passphrase(cpio->archive, + cpio->passphrase); + else + r = archive_write_set_passphrase_callback(cpio->archive, cpio, + &passphrase_callback); + if (r != ARCHIVE_OK) + lafe_errc(1, 0, "%s", archive_error_string(cpio->archive)); + + /* + * The main loop: Copy each file into the output archive. + */ + r = archive_write_open_filename(cpio->archive, cpio->filename); + if (r != ARCHIVE_OK) + lafe_errc(1, 0, "%s", archive_error_string(cpio->archive)); + lr = lafe_line_reader("-", cpio->option_null); + while ((p = lafe_line_reader_next(lr)) != NULL) + file_to_archive(cpio, p); + lafe_line_reader_free(lr); + + /* + * The hardlink detection may have queued up a couple of entries + * that can now be flushed. + */ + entry = NULL; + archive_entry_linkify(cpio->linkresolver, &entry, &spare); + while (entry != NULL) { + entry_to_archive(cpio, entry); + archive_entry_free(entry); + entry = NULL; + archive_entry_linkify(cpio->linkresolver, &entry, &spare); + } + + r = archive_write_close(cpio->archive); + if (cpio->dot) + fprintf(stderr, "\n"); + if (r != ARCHIVE_OK) + lafe_errc(1, 0, "%s", archive_error_string(cpio->archive)); + + if (!cpio->quiet) { + int64_t blocks = + (archive_filter_bytes(cpio->archive, 0) + 511) + / 512; + fprintf(stderr, "%lu %s\n", (unsigned long)blocks, + blocks == 1 ? "block" : "blocks"); + } + archive_write_free(cpio->archive); + archive_entry_linkresolver_free(cpio->linkresolver); +} + +static const char * +remove_leading_slash(const char *p) +{ + const char *rp; + + /* Remove leading "//./" or "//?/" or "//?/UNC/" + * (absolute path prefixes used by Windows API) */ + if ((p[0] == '/' || p[0] == '\\') && + (p[1] == '/' || p[1] == '\\') && + (p[2] == '.' || p[2] == '?') && + (p[3] == '/' || p[3] == '\\')) + { + if (p[2] == '?' && + (p[4] == 'U' || p[4] == 'u') && + (p[5] == 'N' || p[5] == 'n') && + (p[6] == 'C' || p[6] == 'c') && + (p[7] == '/' || p[7] == '\\')) + p += 8; + else + p += 4; + } + do { + rp = p; + /* Remove leading drive letter from archives created + * on Windows. */ + if (((p[0] >= 'a' && p[0] <= 'z') || + (p[0] >= 'A' && p[0] <= 'Z')) && + p[1] == ':') { + p += 2; + } + /* Remove leading "/../", "//", etc. */ + while (p[0] == '/' || p[0] == '\\') { + if (p[1] == '.' && p[2] == '.' && + (p[3] == '/' || p[3] == '\\')) { + p += 3; /* Remove "/..", leave "/" + * for next pass. */ + } else + p += 1; /* Remove "/". */ + } + } while (rp != p); + return (p); +} + +/* + * This is used by both out mode (to copy objects from disk into + * an archive) and pass mode (to copy objects from disk to + * an archive_write_disk "archive"). + */ +static int +file_to_archive(struct cpio *cpio, const char *srcpath) +{ + const char *destpath; + struct archive_entry *entry, *spare; + size_t len; + int r; + + /* + * Create an archive_entry describing the source file. + * + */ + entry = archive_entry_new(); + if (entry == NULL) + lafe_errc(1, 0, "Couldn't allocate entry"); + archive_entry_copy_sourcepath(entry, srcpath); + r = archive_read_disk_entry_from_file(cpio->archive_read_disk, + entry, -1, NULL); + if (r < ARCHIVE_FAILED) + lafe_errc(1, 0, "%s", + archive_error_string(cpio->archive_read_disk)); + if (r < ARCHIVE_OK) + lafe_warnc(0, "%s", + archive_error_string(cpio->archive_read_disk)); + if (r <= ARCHIVE_FAILED) { + archive_entry_free(entry); + cpio->return_value = 1; + return (r); + } + + if (cpio->uid_override >= 0) { + archive_entry_set_uid(entry, cpio->uid_override); + archive_entry_set_uname(entry, cpio->uname_override); + } + if (cpio->gid_override >= 0) { + archive_entry_set_gid(entry, cpio->gid_override); + archive_entry_set_gname(entry, cpio->gname_override); + } + + /* + * Generate a destination path for this entry. + * "destination path" is the name to which it will be copied in + * pass mode or the name that will go into the archive in + * output mode. + */ + destpath = srcpath; + if (cpio->destdir) { + len = strlen(cpio->destdir) + strlen(srcpath) + 8; + if (len >= cpio->pass_destpath_alloc) { + while (len >= cpio->pass_destpath_alloc) { + cpio->pass_destpath_alloc += 512; + cpio->pass_destpath_alloc *= 2; + } + free(cpio->pass_destpath); + cpio->pass_destpath = malloc(cpio->pass_destpath_alloc); + if (cpio->pass_destpath == NULL) + lafe_errc(1, ENOMEM, + "Can't allocate path buffer"); + } + strcpy(cpio->pass_destpath, cpio->destdir); + strcat(cpio->pass_destpath, remove_leading_slash(srcpath)); + destpath = cpio->pass_destpath; + } + if (cpio->option_rename) + destpath = cpio_rename(destpath); + if (destpath == NULL) { + archive_entry_free(entry); + return (0); + } + archive_entry_copy_pathname(entry, destpath); + + /* + * If we're trying to preserve hardlinks, match them here. + */ + spare = NULL; + if (cpio->linkresolver != NULL + && archive_entry_filetype(entry) != AE_IFDIR) { + archive_entry_linkify(cpio->linkresolver, &entry, &spare); + } + + if (entry != NULL) { + r = entry_to_archive(cpio, entry); + archive_entry_free(entry); + if (spare != NULL) { + if (r == 0) + r = entry_to_archive(cpio, spare); + archive_entry_free(spare); + } + } + return (r); +} + +static int +entry_to_archive(struct cpio *cpio, struct archive_entry *entry) +{ + const char *destpath = archive_entry_pathname(entry); + const char *srcpath = archive_entry_sourcepath(entry); + int fd = -1; + ssize_t bytes_read; + int r; + + /* Print out the destination name to the user. */ + if (cpio->verbose) + fprintf(stderr,"%s", destpath); + if (cpio->dot) + fprintf(stderr, "."); + + /* + * Option_link only makes sense in pass mode and for + * regular files. Also note: if a link operation fails + * because of cross-device restrictions, we'll fall back + * to copy mode for that entry. + * + * TODO: Test other cpio implementations to see if they + * hard-link anything other than regular files here. + */ + if (cpio->option_link + && archive_entry_filetype(entry) == AE_IFREG) + { + struct archive_entry *t; + /* Save the original entry in case we need it later. */ + t = archive_entry_clone(entry); + if (t == NULL) + lafe_errc(1, ENOMEM, "Can't create link"); + /* Note: link(2) doesn't create parent directories, + * so we use archive_write_header() instead as a + * convenience. */ + archive_entry_set_hardlink(t, srcpath); + /* This is a straight link that carries no data. */ + archive_entry_set_size(t, 0); + r = archive_write_header(cpio->archive, t); + archive_entry_free(t); + if (r != ARCHIVE_OK) + lafe_warnc(archive_errno(cpio->archive), + "%s", archive_error_string(cpio->archive)); + if (r == ARCHIVE_FATAL) + exit(1); +#ifdef EXDEV + if (r != ARCHIVE_OK && archive_errno(cpio->archive) == EXDEV) { + /* Cross-device link: Just fall through and use + * the original entry to copy the file over. */ + lafe_warnc(0, "Copying file instead"); + } else +#endif + return (0); + } + + /* + * Make sure we can open the file (if necessary) before + * trying to write the header. + */ + if (archive_entry_filetype(entry) == AE_IFREG) { + if (archive_entry_size(entry) > 0) { + fd = open(srcpath, O_RDONLY | O_BINARY); + if (fd < 0) { + lafe_warnc(errno, + "%s: could not open file", srcpath); + goto cleanup; + } + } + } else { + archive_entry_set_size(entry, 0); + } + + r = archive_write_header(cpio->archive, entry); + + if (r != ARCHIVE_OK) + lafe_warnc(archive_errno(cpio->archive), + "%s: %s", + srcpath, + archive_error_string(cpio->archive)); + + if (r == ARCHIVE_FATAL) + exit(1); + + if (r >= ARCHIVE_WARN && archive_entry_size(entry) > 0 && fd >= 0) { + bytes_read = read(fd, cpio->buff, (unsigned)cpio->buff_size); + while (bytes_read > 0) { + ssize_t bytes_write; + bytes_write = archive_write_data(cpio->archive, + cpio->buff, bytes_read); + if (bytes_write < 0) + lafe_errc(1, archive_errno(cpio->archive), + "%s", archive_error_string(cpio->archive)); + if (bytes_write < bytes_read) { + lafe_warnc(0, + "Truncated write; file may have " + "grown while being archived."); + } + bytes_read = read(fd, cpio->buff, + (unsigned)cpio->buff_size); + } + } + + fd = restore_time(cpio, entry, srcpath, fd); + +cleanup: + if (cpio->verbose) + fprintf(stderr,"\n"); + if (fd >= 0) + close(fd); + return (0); +} + +static int +restore_time(struct cpio *cpio, struct archive_entry *entry, + const char *name, int fd) +{ +#ifndef HAVE_UTIMES + static int warned = 0; + + (void)cpio; /* UNUSED */ + (void)entry; /* UNUSED */ + (void)name; /* UNUSED */ + + if (!warned) + lafe_warnc(0, "Can't restore access times on this platform"); + warned = 1; + return (fd); +#else +#if defined(_WIN32) && !defined(__CYGWIN__) + struct __timeval times[2]; +#else + struct timeval times[2]; +#endif + + if (!cpio->option_atime_restore) + return (fd); + + times[1].tv_sec = archive_entry_mtime(entry); + times[1].tv_usec = archive_entry_mtime_nsec(entry) / 1000; + + times[0].tv_sec = archive_entry_atime(entry); + times[0].tv_usec = archive_entry_atime_nsec(entry) / 1000; + +#if defined(HAVE_FUTIMES) && !defined(__CYGWIN__) + if (fd >= 0 && futimes(fd, times) == 0) + return (fd); +#endif + /* + * Some platform cannot restore access times if the file descriptor + * is still opened. + */ + if (fd >= 0) { + close(fd); + fd = -1; + } + +#ifdef HAVE_LUTIMES + if (lutimes(name, times) != 0) +#else + if ((AE_IFLNK != archive_entry_filetype(entry)) + && utimes(name, times) != 0) +#endif + lafe_warnc(errno, "Can't update time for %s", name); +#endif + return (fd); +} + + +static void +mode_in(struct cpio *cpio) +{ + struct archive *a; + struct archive_entry *entry; + struct archive *ext; + const char *destpath; + int r; + + ext = archive_write_disk_new(); + if (ext == NULL) + lafe_errc(1, 0, "Couldn't allocate restore object"); + r = archive_write_disk_set_options(ext, cpio->extract_flags); + if (r != ARCHIVE_OK) + lafe_errc(1, 0, "%s", archive_error_string(ext)); + a = archive_read_new(); + if (a == NULL) + lafe_errc(1, 0, "Couldn't allocate archive object"); + archive_read_support_filter_all(a); + archive_read_support_format_all(a); + if (cpio->passphrase != NULL) + r = archive_read_add_passphrase(a, cpio->passphrase); + else + r = archive_read_set_passphrase_callback(a, cpio, + &passphrase_callback); + if (r != ARCHIVE_OK) + lafe_errc(1, 0, "%s", archive_error_string(a)); + + if (archive_read_open_filename(a, cpio->filename, + cpio->bytes_per_block)) + lafe_errc(1, archive_errno(a), + "%s", archive_error_string(a)); + for (;;) { + r = archive_read_next_header(a, &entry); + if (r == ARCHIVE_EOF) + break; + if (r != ARCHIVE_OK) { + lafe_errc(1, archive_errno(a), + "%s", archive_error_string(a)); + } + if (archive_match_path_excluded(cpio->matching, entry)) + continue; + if (cpio->option_rename) { + destpath = cpio_rename(archive_entry_pathname(entry)); + archive_entry_set_pathname(entry, destpath); + } else + destpath = archive_entry_pathname(entry); + if (destpath == NULL) + continue; + if (cpio->verbose) + fprintf(stderr, "%s\n", destpath); + if (cpio->dot) + fprintf(stderr, "."); + if (cpio->uid_override >= 0) + archive_entry_set_uid(entry, cpio->uid_override); + if (cpio->gid_override >= 0) + archive_entry_set_gid(entry, cpio->gid_override); + r = archive_write_header(ext, entry); + if (r != ARCHIVE_OK) { + fprintf(stderr, "%s: %s\n", + archive_entry_pathname(entry), + archive_error_string(ext)); + } else if (!archive_entry_size_is_set(entry) + || archive_entry_size(entry) > 0) { + r = extract_data(a, ext); + if (r != ARCHIVE_OK) + cpio->return_value = 1; + } + } + r = archive_read_close(a); + if (cpio->dot) + fprintf(stderr, "\n"); + if (r != ARCHIVE_OK) + lafe_errc(1, 0, "%s", archive_error_string(a)); + r = archive_write_close(ext); + if (r != ARCHIVE_OK) + lafe_errc(1, 0, "%s", archive_error_string(ext)); + if (!cpio->quiet) { + int64_t blocks = (archive_filter_bytes(a, 0) + 511) + / 512; + fprintf(stderr, "%lu %s\n", (unsigned long)blocks, + blocks == 1 ? "block" : "blocks"); + } + archive_read_free(a); + archive_write_free(ext); + exit(cpio->return_value); +} + +/* + * Exits if there's a fatal error. Returns ARCHIVE_OK + * if everything is kosher. + */ +static int +extract_data(struct archive *ar, struct archive *aw) +{ + int r; + size_t size; + const void *block; + int64_t offset; + + for (;;) { + r = archive_read_data_block(ar, &block, &size, &offset); + if (r == ARCHIVE_EOF) + return (ARCHIVE_OK); + if (r != ARCHIVE_OK) { + lafe_warnc(archive_errno(ar), + "%s", archive_error_string(ar)); + exit(1); + } + r = (int)archive_write_data_block(aw, block, size, offset); + if (r != ARCHIVE_OK) { + lafe_warnc(archive_errno(aw), + "%s", archive_error_string(aw)); + return (r); + } + } +} + +static void +mode_list(struct cpio *cpio) +{ + struct archive *a; + struct archive_entry *entry; + int r; + + a = archive_read_new(); + if (a == NULL) + lafe_errc(1, 0, "Couldn't allocate archive object"); + archive_read_support_filter_all(a); + archive_read_support_format_all(a); + if (cpio->passphrase != NULL) + r = archive_read_add_passphrase(a, cpio->passphrase); + else + r = archive_read_set_passphrase_callback(a, cpio, + &passphrase_callback); + if (r != ARCHIVE_OK) + lafe_errc(1, 0, "%s", archive_error_string(a)); + + if (archive_read_open_filename(a, cpio->filename, + cpio->bytes_per_block)) + lafe_errc(1, archive_errno(a), + "%s", archive_error_string(a)); + for (;;) { + r = archive_read_next_header(a, &entry); + if (r == ARCHIVE_EOF) + break; + if (r != ARCHIVE_OK) { + lafe_errc(1, archive_errno(a), + "%s", archive_error_string(a)); + } + if (archive_match_path_excluded(cpio->matching, entry)) + continue; + if (cpio->verbose) + list_item_verbose(cpio, entry); + else + fprintf(stdout, "%s\n", archive_entry_pathname(entry)); + } + r = archive_read_close(a); + if (r != ARCHIVE_OK) + lafe_errc(1, 0, "%s", archive_error_string(a)); + if (!cpio->quiet) { + int64_t blocks = (archive_filter_bytes(a, 0) + 511) + / 512; + fprintf(stderr, "%lu %s\n", (unsigned long)blocks, + blocks == 1 ? "block" : "blocks"); + } + archive_read_free(a); + exit(0); +} + +/* + * Display information about the current file. + * + * The format here roughly duplicates the output of 'ls -l'. + * This is based on SUSv2, where 'tar tv' is documented as + * listing additional information in an "unspecified format," + * and 'pax -l' is documented as using the same format as 'ls -l'. + */ +static void +list_item_verbose(struct cpio *cpio, struct archive_entry *entry) +{ + char size[32]; + char date[32]; + char uids[16], gids[16]; + const char *uname, *gname; + FILE *out = stdout; + const char *fmt; + time_t mtime; + static time_t now; + struct tm *ltime; +#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S) + struct tm tmbuf; +#endif +#if defined(HAVE__LOCALTIME64_S) + errno_t terr; + __time64_t tmptime; +#endif + + if (!now) + time(&now); + + if (cpio->option_numeric_uid_gid) { + /* Format numeric uid/gid for display. */ + strcpy(uids, cpio_i64toa(archive_entry_uid(entry))); + uname = uids; + strcpy(gids, cpio_i64toa(archive_entry_gid(entry))); + gname = gids; + } else { + /* Use uname if it's present, else lookup name from uid. */ + uname = archive_entry_uname(entry); + if (uname == NULL) + uname = lookup_uname(cpio, (uid_t)archive_entry_uid(entry)); + /* Use gname if it's present, else lookup name from gid. */ + gname = archive_entry_gname(entry); + if (gname == NULL) + gname = lookup_gname(cpio, (uid_t)archive_entry_gid(entry)); + } + + /* Print device number or file size. */ + if (archive_entry_filetype(entry) == AE_IFCHR + || archive_entry_filetype(entry) == AE_IFBLK) { + snprintf(size, sizeof(size), "%lu,%lu", + (unsigned long)archive_entry_rdevmajor(entry), + (unsigned long)archive_entry_rdevminor(entry)); + } else { + strcpy(size, cpio_i64toa(archive_entry_size(entry))); + } + + /* Format the time using 'ls -l' conventions. */ + mtime = archive_entry_mtime(entry); +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Windows' strftime function does not support %e format. */ + if (mtime - now > 365*86400/2 + || mtime - now < -365*86400/2) + fmt = cpio->day_first ? "%d %b %Y" : "%b %d %Y"; + else + fmt = cpio->day_first ? "%d %b %H:%M" : "%b %d %H:%M"; +#else + if (mtime - now > 365*86400/2 + || mtime - now < -365*86400/2) + fmt = cpio->day_first ? "%e %b %Y" : "%b %e %Y"; + else + fmt = cpio->day_first ? "%e %b %H:%M" : "%b %e %H:%M"; +#endif +#if defined(HAVE_LOCALTIME_R) + ltime = localtime_r(&mtime, &tmbuf); +#elif defined(HAVE__LOCALTIME64_S) + tmptime = mtime; + terr = _localtime64_s(&tmbuf, &tmptime); + if (terr) + ltime = NULL; + else + ltime = &tmbuf; +#else + ltime = localtime(&mtime); +#endif + strftime(date, sizeof(date), fmt, ltime); + + fprintf(out, "%s%3d %-8s %-8s %8s %12s %s", + archive_entry_strmode(entry), + archive_entry_nlink(entry), + uname, gname, size, date, + archive_entry_pathname(entry)); + + /* Extra information for links. */ + if (archive_entry_hardlink(entry)) /* Hard link */ + fprintf(out, " link to %s", archive_entry_hardlink(entry)); + else if (archive_entry_symlink(entry)) /* Symbolic link */ + fprintf(out, " -> %s", archive_entry_symlink(entry)); + fprintf(out, "\n"); +} + +static void +mode_pass(struct cpio *cpio, const char *destdir) +{ + struct lafe_line_reader *lr; + const char *p; + int r; + size_t destdir_len; + + /* Ensure target dir has a trailing '/' to simplify path surgery. */ + destdir_len = strlen(destdir); + cpio->destdir = malloc(destdir_len + 8); + memcpy(cpio->destdir, destdir, destdir_len); + if (destdir_len == 0 || destdir[destdir_len - 1] != '/') + cpio->destdir[destdir_len++] = '/'; + cpio->destdir[destdir_len++] = '\0'; + + cpio->archive = archive_write_disk_new(); + if (cpio->archive == NULL) + lafe_errc(1, 0, "Failed to allocate archive object"); + r = archive_write_disk_set_options(cpio->archive, cpio->extract_flags); + if (r != ARCHIVE_OK) + lafe_errc(1, 0, "%s", archive_error_string(cpio->archive)); + cpio->linkresolver = archive_entry_linkresolver_new(); + archive_write_disk_set_standard_lookup(cpio->archive); + + cpio->archive_read_disk = archive_read_disk_new(); + if (cpio->archive_read_disk == NULL) + lafe_errc(1, 0, "Failed to allocate archive object"); + if (cpio->option_follow_links) + archive_read_disk_set_symlink_logical(cpio->archive_read_disk); + else + archive_read_disk_set_symlink_physical(cpio->archive_read_disk); + archive_read_disk_set_standard_lookup(cpio->archive_read_disk); + + lr = lafe_line_reader("-", cpio->option_null); + while ((p = lafe_line_reader_next(lr)) != NULL) + file_to_archive(cpio, p); + lafe_line_reader_free(lr); + + archive_entry_linkresolver_free(cpio->linkresolver); + r = archive_write_close(cpio->archive); + if (cpio->dot) + fprintf(stderr, "\n"); + if (r != ARCHIVE_OK) + lafe_errc(1, 0, "%s", archive_error_string(cpio->archive)); + + if (!cpio->quiet) { + int64_t blocks = + (archive_filter_bytes(cpio->archive, 0) + 511) + / 512; + fprintf(stderr, "%lu %s\n", (unsigned long)blocks, + blocks == 1 ? "block" : "blocks"); + } + + archive_write_free(cpio->archive); + free(cpio->pass_destpath); +} + +/* + * Prompt for a new name for this entry. Returns a pointer to the + * new name or NULL if the entry should not be copied. This + * implements the semantics defined in POSIX.1-1996, which specifies + * that an input of '.' means the name should be unchanged. GNU cpio + * treats '.' as a literal new name. + */ +static const char * +cpio_rename(const char *name) +{ + static char buff[1024]; + FILE *t; + char *p, *ret; +#if defined(_WIN32) && !defined(__CYGWIN__) + FILE *to; + + t = fopen("CONIN$", "r"); + if (t == NULL) + return (name); + to = fopen("CONOUT$", "w"); + if (to == NULL) { + fclose(t); + return (name); + } + fprintf(to, "%s (Enter/./(new name))? ", name); + fclose(to); +#else + t = fopen("/dev/tty", "r+"); + if (t == NULL) + return (name); + fprintf(t, "%s (Enter/./(new name))? ", name); + fflush(t); +#endif + + p = fgets(buff, sizeof(buff), t); + fclose(t); + if (p == NULL) + /* End-of-file is a blank line. */ + return (NULL); + + while (*p == ' ' || *p == '\t') + ++p; + if (*p == '\n' || *p == '\0') + /* Empty line. */ + return (NULL); + if (*p == '.' && p[1] == '\n') + /* Single period preserves original name. */ + return (name); + ret = p; + /* Trim the final newline. */ + while (*p != '\0' && *p != '\n') + ++p; + /* Overwrite the final \n with a null character. */ + *p = '\0'; + return (ret); +} + +static void +free_cache(struct name_cache *cache) +{ + size_t i; + + if (cache != NULL) { + for (i = 0; i < cache->size; i++) + free(cache->cache[i].name); + free(cache); + } +} + +/* + * Lookup uname/gname from uid/gid, return NULL if no match. + */ +static const char * +lookup_name(struct cpio *cpio, struct name_cache **name_cache_variable, + int (*lookup_fn)(struct cpio *, const char **, id_t), id_t id) +{ + char asnum[16]; + struct name_cache *cache; + const char *name; + int slot; + + + if (*name_cache_variable == NULL) { + *name_cache_variable = calloc(1, sizeof(struct name_cache)); + if (*name_cache_variable == NULL) + lafe_errc(1, ENOMEM, "No more memory"); + (*name_cache_variable)->size = name_cache_size; + } + + cache = *name_cache_variable; + cache->probes++; + + slot = id % cache->size; + if (cache->cache[slot].name != NULL) { + if (cache->cache[slot].id == id) { + cache->hits++; + return (cache->cache[slot].name); + } + free(cache->cache[slot].name); + cache->cache[slot].name = NULL; + } + + if (lookup_fn(cpio, &name, id)) { + /* If lookup failed, format it as a number. */ + snprintf(asnum, sizeof(asnum), "%u", (unsigned)id); + name = asnum; + } + + cache->cache[slot].name = strdup(name); + if (cache->cache[slot].name != NULL) { + cache->cache[slot].id = id; + return (cache->cache[slot].name); + } + + /* + * Conveniently, NULL marks an empty slot, so + * if the strdup() fails, we've just failed to + * cache it. No recovery necessary. + */ + return (NULL); +} + +static const char * +lookup_uname(struct cpio *cpio, uid_t uid) +{ + return (lookup_name(cpio, &cpio->uname_cache, + &lookup_uname_helper, (id_t)uid)); +} + +static int +lookup_uname_helper(struct cpio *cpio, const char **name, id_t id) +{ + struct passwd *pwent; + + (void)cpio; /* UNUSED */ + + errno = 0; + pwent = getpwuid((uid_t)id); + if (pwent == NULL) { + if (errno && errno != ENOENT) + lafe_warnc(errno, "getpwuid(%s) failed", + cpio_i64toa((int64_t)id)); + return 1; + } + + *name = pwent->pw_name; + return 0; +} + +static const char * +lookup_gname(struct cpio *cpio, gid_t gid) +{ + return (lookup_name(cpio, &cpio->gname_cache, + &lookup_gname_helper, (id_t)gid)); +} + +static int +lookup_gname_helper(struct cpio *cpio, const char **name, id_t id) +{ + struct group *grent; + + (void)cpio; /* UNUSED */ + + errno = 0; + grent = getgrgid((gid_t)id); + if (grent == NULL) { + if (errno && errno != ENOENT) + lafe_warnc(errno, "getgrgid(%s) failed", + cpio_i64toa((int64_t)id)); + return 1; + } + + *name = grent->gr_name; + return 0; +} + +/* + * It would be nice to just use printf() for formatting large numbers, + * but the compatibility problems are a big headache. Hence the + * following simple utility function. + */ +const char * +cpio_i64toa(int64_t n0) +{ + /* 2^64 =~ 1.8 * 10^19, so 20 decimal digits suffice. + * We also need 1 byte for '-' and 1 for '\0'. + */ + static char buff[22]; + int64_t n = n0 < 0 ? -n0 : n0; + char *p = buff + sizeof(buff); + + *--p = '\0'; + do { + *--p = '0' + (int)(n % 10); + n /= 10; + } while (n > 0); + if (n0 < 0) + *--p = '-'; + return p; +} + +#define PPBUFF_SIZE 1024 +static const char * +passphrase_callback(struct archive *a, void *_client_data) +{ + struct cpio *cpio = (struct cpio *)_client_data; + (void)a; /* UNUSED */ + + if (cpio->ppbuff == NULL) { + cpio->ppbuff = malloc(PPBUFF_SIZE); + if (cpio->ppbuff == NULL) + lafe_errc(1, errno, "Out of memory"); + } + return lafe_readpassphrase("Enter passphrase:", + cpio->ppbuff, PPBUFF_SIZE); +} + +static void +passphrase_free(char *ppbuff) +{ + if (ppbuff != NULL) { + memset(ppbuff, 0, PPBUFF_SIZE); + free(ppbuff); + } +} diff --git a/dependencies/libarchive-3.4.2/cpio/cpio.h b/dependencies/libarchive-3.4.2/cpio/cpio.h new file mode 100644 index 0000000..abf3628 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/cpio.h @@ -0,0 +1,120 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: src/usr.bin/cpio/cpio.h,v 1.7 2008/12/06 07:30:40 kientzle Exp $ + */ + +#ifndef CPIO_H_INCLUDED +#define CPIO_H_INCLUDED + +#include "cpio_platform.h" +#include + +/* + * The internal state for the "cpio" program. + * + * Keeping all of the state in a structure like this simplifies memory + * leak testing (at exit, anything left on the heap is suspect). A + * pointer to this structure is passed to most cpio internal + * functions. + */ +struct cpio { + /* Option parsing */ + const char *argument; + + /* Options */ + int add_filter; /* --uuencode */ + const char *filename; + int mode; /* -i -o -p */ + int compress; /* -j, -y, or -z */ + const char *format; /* -H format */ + int bytes_per_block; /* -b block_size */ + int verbose; /* -v */ + int dot; /* -V */ + int quiet; /* --quiet */ + int extract_flags; /* Flags for extract operation */ + const char *compress_program; + int option_append; /* -A, only relevant for -o */ + int option_atime_restore; /* -a */ + int option_follow_links; /* -L */ + int option_link; /* -l */ + int option_list; /* -t */ + char option_null; /* --null */ + int option_numeric_uid_gid; /* -n */ + int option_rename; /* -r */ + char *destdir; + size_t pass_destpath_alloc; + char *pass_destpath; + int uid_override; + char *uname_override; + int gid_override; + char *gname_override; + int day_first; /* true if locale prefers day/mon */ + const char *passphrase; + + /* If >= 0, then close this when done. */ + int fd; + + /* Miscellaneous state information */ + struct archive *archive; + struct archive *archive_read_disk; + int argc; + char **argv; + int return_value; /* Value returned by main() */ + struct archive_entry_linkresolver *linkresolver; + + struct name_cache *uname_cache; + struct name_cache *gname_cache; + + /* Work data. */ + struct archive *matching; + char *buff; + size_t buff_size; + char *ppbuff; +}; + +const char *owner_parse(const char *, int *, int *); + + +/* Fake short equivalents for long options that otherwise lack them. */ +enum { + OPTION_B64ENCODE = 1, + OPTION_GRZIP, + OPTION_INSECURE, + OPTION_LRZIP, + OPTION_LZ4, + OPTION_LZMA, + OPTION_LZOP, + OPTION_PASSPHRASE, + OPTION_NO_PRESERVE_OWNER, + OPTION_PRESERVE_OWNER, + OPTION_QUIET, + OPTION_UUENCODE, + OPTION_VERSION, + OPTION_ZSTD, +}; + +int cpio_getopt(struct cpio *cpio); + +#endif diff --git a/dependencies/libarchive-3.4.2/cpio/cpio_platform.h b/dependencies/libarchive-3.4.2/cpio/cpio_platform.h new file mode 100644 index 0000000..58d2edb --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/cpio_platform.h @@ -0,0 +1,77 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: src/usr.bin/cpio/cpio_platform.h,v 1.2 2008/12/06 07:15:42 kientzle Exp $ + */ + +/* + * This header is the first thing included in any of the cpio + * source files. As far as possible, platform-specific issues should + * be dealt with here and not within individual source files. + */ + +#ifndef CPIO_PLATFORM_H_INCLUDED +#define CPIO_PLATFORM_H_INCLUDED + +#if defined(PLATFORM_CONFIG_H) +/* Use hand-built config.h in environments that need it. */ +#include PLATFORM_CONFIG_H +#else +/* Read config.h or die trying. */ +#include "config.h" +#endif + +#if defined(_WIN32) && !defined(__CYGWIN__) +#include "cpio_windows.h" +#endif + +/* Get a real definition for __FBSDID if we can */ +#if HAVE_SYS_CDEFS_H +#include +#endif + +/* If not, define it so as to avoid dangling semicolons. */ +#ifndef __FBSDID +#define __FBSDID(a) struct _undefined_hack +#endif + +#ifdef HAVE_LIBARCHIVE +/* If we're using the platform libarchive, include system headers. */ +#include +#include +#else +/* Otherwise, include user headers. */ +#include "archive.h" +#include "archive_entry.h" +#endif + +/* How to mark functions that don't return. */ +#if defined(__GNUC__) && (__GNUC__ > 2 || \ + (__GNUC__ == 2 && __GNUC_MINOR__ >= 5)) +#define __LA_DEAD __attribute__((__noreturn__)) +#else +#define __LA_DEAD +#endif + +#endif /* !CPIO_PLATFORM_H_INCLUDED */ diff --git a/dependencies/libarchive-3.4.2/cpio/cpio_windows.c b/dependencies/libarchive-3.4.2/cpio/cpio_windows.c new file mode 100644 index 0000000..63f6df0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/cpio_windows.c @@ -0,0 +1,338 @@ +/*- + * Copyright (c) 2009 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#if defined(_WIN32) && !defined(__CYGWIN__) + +#include "cpio_platform.h" +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_UTIME_H +#include +#endif +#include +#include +#include +#include +#include +#include + +#include "cpio.h" +#include "err.h" + +#define EPOC_TIME (116444736000000000ULL) + +static void cpio_dosmaperr(unsigned long); + +/* + * Prepend "\\?\" to the path name and convert it to unicode to permit + * an extended-length path for a maximum total path length of 32767 + * characters. + * see also http://msdn.microsoft.com/en-us/library/aa365247.aspx + */ +static wchar_t * +permissive_name(const char *name) +{ + wchar_t *wn, *wnp; + wchar_t *ws, *wsp; + DWORD l, len, slen, alloclen; + int unc; + + len = (DWORD)strlen(name); + wn = malloc((len + 1) * sizeof(wchar_t)); + if (wn == NULL) + return (NULL); + l = MultiByteToWideChar(CP_ACP, 0, name, len, wn, len); + if (l == 0) { + free(wn); + return (NULL); + } + wn[l] = L'\0'; + + /* Get a full path names */ + l = GetFullPathNameW(wn, 0, NULL, NULL); + if (l == 0) { + free(wn); + return (NULL); + } + wnp = malloc(l * sizeof(wchar_t)); + if (wnp == NULL) { + free(wn); + return (NULL); + } + len = GetFullPathNameW(wn, l, wnp, NULL); + free(wn); + wn = wnp; + + if (wnp[0] == L'\\' && wnp[1] == L'\\' && + wnp[2] == L'?' && wnp[3] == L'\\') + /* We have already permissive names. */ + return (wn); + + if (wnp[0] == L'\\' && wnp[1] == L'\\' && + wnp[2] == L'.' && wnp[3] == L'\\') { + /* Device names */ + if (((wnp[4] >= L'a' && wnp[4] <= L'z') || + (wnp[4] >= L'A' && wnp[4] <= L'Z')) && + wnp[5] == L':' && wnp[6] == L'\\') + wnp[2] = L'?';/* Not device names. */ + return (wn); + } + + unc = 0; + if (wnp[0] == L'\\' && wnp[1] == L'\\' && wnp[2] != L'\\') { + wchar_t *p = &wnp[2]; + + /* Skip server-name letters. */ + while (*p != L'\\' && *p != L'\0') + ++p; + if (*p == L'\\') { + wchar_t *rp = ++p; + /* Skip share-name letters. */ + while (*p != L'\\' && *p != L'\0') + ++p; + if (*p == L'\\' && p != rp) { + /* Now, match patterns such as + * "\\server-name\share-name\" */ + wnp += 2; + len -= 2; + unc = 1; + } + } + } + + alloclen = slen = 4 + (unc * 4) + len + 1; + ws = wsp = malloc(slen * sizeof(wchar_t)); + if (ws == NULL) { + free(wn); + return (NULL); + } + /* prepend "\\?\" */ + wcsncpy(wsp, L"\\\\?\\", 4); + wsp += 4; + slen -= 4; + if (unc) { + /* append "UNC\" ---> "\\?\UNC\" */ + wcsncpy(wsp, L"UNC\\", 4); + wsp += 4; + slen -= 4; + } + wcsncpy(wsp, wnp, slen); + free(wn); + ws[alloclen - 1] = L'\0'; + return (ws); +} + +static HANDLE +cpio_CreateFile(const char *path, DWORD dwDesiredAccess, DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) +{ + wchar_t *wpath; + HANDLE handle; + + handle = CreateFileA(path, dwDesiredAccess, dwShareMode, + lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, + hTemplateFile); + if (handle != INVALID_HANDLE_VALUE) + return (handle); + if (GetLastError() != ERROR_PATH_NOT_FOUND) + return (handle); + wpath = permissive_name(path); + if (wpath == NULL) + return (handle); + handle = CreateFileW(wpath, dwDesiredAccess, dwShareMode, + lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, + hTemplateFile); + free(wpath); + return (handle); +} + +#define WINTIME(sec, usec) ((Int32x32To64(sec, 10000000) + EPOC_TIME) + (usec * 10)) +static int +__hutimes(HANDLE handle, const struct __timeval *times) +{ + ULARGE_INTEGER wintm; + FILETIME fatime, fmtime; + + wintm.QuadPart = WINTIME(times[0].tv_sec, times[0].tv_usec); + fatime.dwLowDateTime = wintm.LowPart; + fatime.dwHighDateTime = wintm.HighPart; + wintm.QuadPart = WINTIME(times[1].tv_sec, times[1].tv_usec); + fmtime.dwLowDateTime = wintm.LowPart; + fmtime.dwHighDateTime = wintm.HighPart; + if (SetFileTime(handle, NULL, &fatime, &fmtime) == 0) { + errno = EINVAL; + return (-1); + } + return (0); +} + +int +futimes(int fd, const struct __timeval *times) +{ + + return (__hutimes((HANDLE)_get_osfhandle(fd), times)); +} + +int +utimes(const char *name, const struct __timeval *times) +{ + int ret; + HANDLE handle; + + handle = cpio_CreateFile(name, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (handle == INVALID_HANDLE_VALUE) { + cpio_dosmaperr(GetLastError()); + return (-1); + } + ret = __hutimes(handle, times); + CloseHandle(handle); + return (ret); +} + +/* + * The following function was modified from PostgreSQL sources and is + * subject to the copyright below. + */ +/*------------------------------------------------------------------------- + * + * win32error.c + * Map win32 error codes to errno values + * + * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group + * + * IDENTIFICATION + * $PostgreSQL: pgsql/src/port/win32error.c,v 1.4 2008/01/01 19:46:00 momjian Exp $ + * + *------------------------------------------------------------------------- + */ +/* +PostgreSQL Database Management System +(formerly known as Postgres, then as Postgres95) + +Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group + +Portions Copyright (c) 1994, The Regents of the University of California + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose, without fee, and without a written agreement +is hereby granted, provided that the above copyright notice and this +paragraph and the following two paragraphs appear in all copies. + +IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR +DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING +LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS +DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS +ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO +PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. +*/ + +static const struct { + DWORD winerr; + int doserr; +} doserrors[] = +{ + { ERROR_INVALID_FUNCTION, EINVAL }, + { ERROR_FILE_NOT_FOUND, ENOENT }, + { ERROR_PATH_NOT_FOUND, ENOENT }, + { ERROR_TOO_MANY_OPEN_FILES, EMFILE }, + { ERROR_ACCESS_DENIED, EACCES }, + { ERROR_INVALID_HANDLE, EBADF }, + { ERROR_ARENA_TRASHED, ENOMEM }, + { ERROR_NOT_ENOUGH_MEMORY, ENOMEM }, + { ERROR_INVALID_BLOCK, ENOMEM }, + { ERROR_BAD_ENVIRONMENT, E2BIG }, + { ERROR_BAD_FORMAT, ENOEXEC }, + { ERROR_INVALID_ACCESS, EINVAL }, + { ERROR_INVALID_DATA, EINVAL }, + { ERROR_INVALID_DRIVE, ENOENT }, + { ERROR_CURRENT_DIRECTORY, EACCES }, + { ERROR_NOT_SAME_DEVICE, EXDEV }, + { ERROR_NO_MORE_FILES, ENOENT }, + { ERROR_LOCK_VIOLATION, EACCES }, + { ERROR_SHARING_VIOLATION, EACCES }, + { ERROR_BAD_NETPATH, ENOENT }, + { ERROR_NETWORK_ACCESS_DENIED, EACCES }, + { ERROR_BAD_NET_NAME, ENOENT }, + { ERROR_FILE_EXISTS, EEXIST }, + { ERROR_CANNOT_MAKE, EACCES }, + { ERROR_FAIL_I24, EACCES }, + { ERROR_INVALID_PARAMETER, EINVAL }, + { ERROR_NO_PROC_SLOTS, EAGAIN }, + { ERROR_DRIVE_LOCKED, EACCES }, + { ERROR_BROKEN_PIPE, EPIPE }, + { ERROR_DISK_FULL, ENOSPC }, + { ERROR_INVALID_TARGET_HANDLE, EBADF }, + { ERROR_INVALID_HANDLE, EINVAL }, + { ERROR_WAIT_NO_CHILDREN, ECHILD }, + { ERROR_CHILD_NOT_COMPLETE, ECHILD }, + { ERROR_DIRECT_ACCESS_HANDLE, EBADF }, + { ERROR_NEGATIVE_SEEK, EINVAL }, + { ERROR_SEEK_ON_DEVICE, EACCES }, + { ERROR_DIR_NOT_EMPTY, ENOTEMPTY }, + { ERROR_NOT_LOCKED, EACCES }, + { ERROR_BAD_PATHNAME, ENOENT }, + { ERROR_MAX_THRDS_REACHED, EAGAIN }, + { ERROR_LOCK_FAILED, EACCES }, + { ERROR_ALREADY_EXISTS, EEXIST }, + { ERROR_FILENAME_EXCED_RANGE, ENOENT }, + { ERROR_NESTING_NOT_ALLOWED, EAGAIN }, + { ERROR_NOT_ENOUGH_QUOTA, ENOMEM } +}; + +static void +cpio_dosmaperr(unsigned long e) +{ + int i; + + if (e == 0) { + errno = 0; + return; + } + + for (i = 0; i < (int)sizeof(doserrors); i++) { + if (doserrors[i].winerr == e) { + errno = doserrors[i].doserr; + return; + } + } + + /* fprintf(stderr, "unrecognized win32 error code: %lu", e); */ + errno = EINVAL; + return; +} +#endif diff --git a/dependencies/libarchive-3.4.2/cpio/cpio_windows.h b/dependencies/libarchive-3.4.2/cpio/cpio_windows.h new file mode 100644 index 0000000..970a63d --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/cpio_windows.h @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 2009 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef CPIO_WINDOWS_H +#define CPIO_WINDOWS_H 1 +#include + +#include +#include + +#define getgrgid(id) NULL +#define getgrnam(name) NULL +#define getpwnam(name) NULL +#define getpwuid(id) NULL + +#if defined(_MSC_VER) + #if _MSC_VER < 1900 + #define snprintf sprintf_s + #endif // _MSC_VER < 1900 +#define strdup _strdup +#define open _open +#define read _read +#define close _close +#endif + +struct passwd { + char *pw_name; + uid_t pw_uid; + gid_t pw_gid; +}; + +struct group { + char *gr_name; + gid_t gr_gid; +}; + +struct _timeval64i32 { + time_t tv_sec; + long tv_usec; +}; +#define __timeval _timeval64i32 + +extern int futimes(int fd, const struct __timeval *times); +#ifndef HAVE_FUTIMES +#define HAVE_FUTIMES 1 +#endif +extern int utimes(const char *name, const struct __timeval *times); +#ifndef HAVE_UTIMES +#define HAVE_UTIMES 1 +#endif + +#endif /* CPIO_WINDOWS_H */ diff --git a/dependencies/libarchive-3.4.2/cpio/test/CMakeLists.txt b/dependencies/libarchive-3.4.2/cpio/test/CMakeLists.txt new file mode 100644 index 0000000..d0927a8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/CMakeLists.txt @@ -0,0 +1,112 @@ +############################################ +# +# How to build bsdcpio_test +# +############################################ +IF(ENABLE_CPIO AND ENABLE_TEST) + SET(bsdcpio_test_SOURCES + ../cmdline.c + ../../libarchive_fe/err.c + ../../test_utils/test_utils.c + ../../test_utils/test_main.c + test.h + test_0.c + test_basic.c + test_cmdline.c + test_extract_cpio_Z + test_extract_cpio_bz2 + test_extract_cpio_grz + test_extract_cpio_gz + test_extract_cpio_lrz + test_extract_cpio_lz + test_extract_cpio_lz4 + test_extract_cpio_lzma + test_extract_cpio_lzo + test_extract_cpio_xz + test_extract_cpio_zstd + test_format_newc.c + test_gcpio_compat.c + test_missing_file.c + test_option_0.c + test_option_B_upper.c + test_option_C_upper.c + test_option_J_upper.c + test_option_L_upper.c + test_option_Z_upper.c + test_option_a.c + test_option_b64encode.c + test_option_c.c + test_option_d.c + test_option_f.c + test_option_grzip.c + test_option_help.c + test_option_l.c + test_option_lrzip.c + test_option_lz4.c + test_option_lzma.c + test_option_lzop.c + test_option_m.c + test_option_passphrase.c + test_option_t.c + test_option_u.c + test_option_uuencode.c + test_option_version.c + test_option_xz.c + test_option_y.c + test_option_z.c + test_option_zstd.c + test_owner_parse.c + test_passthrough_dotdot.c + test_passthrough_reverse.c + ) + + # + # Register target + # + ADD_EXECUTABLE(bsdcpio_test ${bsdcpio_test_SOURCES}) + IF(ENABLE_ACL) + SET(TEST_ACL_LIBS "") + IF(HAVE_LIBACL) + LIST(APPEND TEST_ACL_LIBS ${ACL_LIBRARY}) + ENDIF(HAVE_LIBACL) + IF(HAVE_LIBRICHACL) + LIST(APPEND TEST_ACL_LIBS ${RICHACL_LIBRARY}) + ENDIF(HAVE_LIBRICHACL) + TARGET_LINK_LIBRARIES(bsdcpio_test ${TEST_ACL_LIBS}) + ENDIF(ENABLE_ACL) + SET_PROPERTY(TARGET bsdcpio_test PROPERTY COMPILE_DEFINITIONS LIST_H) + + # + # Generate list.h by grepping DEFINE_TEST() lines out of the C sources. + # + GENERATE_LIST_H(${CMAKE_CURRENT_BINARY_DIR}/list.h + ${CMAKE_CURRENT_LIST_FILE} ${bsdcpio_test_SOURCES}) + SET_PROPERTY(DIRECTORY APPEND PROPERTY INCLUDE_DIRECTORIES + ${CMAKE_CURRENT_BINARY_DIR}) + + # list.h has a line DEFINE_TEST(testname) for every + # test. We can use that to define the tests for cmake by + # defining a DEFINE_TEST macro and reading list.h in. + MACRO (DEFINE_TEST _testname) + ADD_TEST( + NAME bsdcpio_${_testname} + COMMAND bsdcpio_test -vv + -p $ + -r ${CMAKE_CURRENT_SOURCE_DIR} + ${_testname}) + ENDMACRO (DEFINE_TEST _testname) + + INCLUDE(${CMAKE_CURRENT_BINARY_DIR}/list.h) + INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) + INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/test_utils) + INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/cpio/test) + + # Experimental new test handling + ADD_CUSTOM_TARGET(run_bsdcpio_test + COMMAND bsdcpio_test -p $ + -r ${CMAKE_CURRENT_SOURCE_DIR} + -vv) + ADD_DEPENDENCIES(run_bsdcpio_test bsdcpio) + ADD_DEPENDENCIES(run_all_tests run_bsdcpio_test) +ENDIF(ENABLE_CPIO AND ENABLE_TEST) + diff --git a/dependencies/libarchive-3.4.2/cpio/test/list.h b/dependencies/libarchive-3.4.2/cpio/test/list.h new file mode 100644 index 0000000..9c170a0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/list.h @@ -0,0 +1,48 @@ +DEFINE_TEST(test_0) +DEFINE_TEST(test_basic) +DEFINE_TEST(test_cmdline) +DEFINE_TEST(test_extract_cpio_Z) +DEFINE_TEST(test_extract_cpio_bz2) +DEFINE_TEST(test_extract_cpio_grz) +DEFINE_TEST(test_extract_cpio_gz) +DEFINE_TEST(test_extract_cpio_lrz) +DEFINE_TEST(test_extract_cpio_lz) +DEFINE_TEST(test_extract_cpio_lz4) +DEFINE_TEST(test_extract_cpio_lzma) +DEFINE_TEST(test_extract_cpio_lzo) +DEFINE_TEST(test_extract_cpio_xz) +DEFINE_TEST(test_extract_cpio_zstd) +DEFINE_TEST(test_format_newc) +DEFINE_TEST(test_gcpio_compat) +DEFINE_TEST(test_missing_file) +DEFINE_TEST(test_option_0) +DEFINE_TEST(test_option_B_upper) +DEFINE_TEST(test_option_C_upper) +DEFINE_TEST(test_option_J_upper) +DEFINE_TEST(test_option_L_upper) +DEFINE_TEST(test_option_Z_upper) +DEFINE_TEST(test_option_a) +DEFINE_TEST(test_option_b64encode) +DEFINE_TEST(test_option_c) +DEFINE_TEST(test_option_d) +DEFINE_TEST(test_option_f) +DEFINE_TEST(test_option_grzip) +DEFINE_TEST(test_option_help) +DEFINE_TEST(test_option_l) +DEFINE_TEST(test_option_lrzip) +DEFINE_TEST(test_option_lz4) +DEFINE_TEST(test_option_lzma) +DEFINE_TEST(test_option_lzop) +DEFINE_TEST(test_option_m) +DEFINE_TEST(test_option_passphrase) +DEFINE_TEST(test_option_t) +DEFINE_TEST(test_option_u) +DEFINE_TEST(test_option_uuencode) +DEFINE_TEST(test_option_version) +DEFINE_TEST(test_option_xz) +DEFINE_TEST(test_option_y) +DEFINE_TEST(test_option_z) +DEFINE_TEST(test_option_zstd) +DEFINE_TEST(test_owner_parse) +DEFINE_TEST(test_passthrough_dotdot) +DEFINE_TEST(test_passthrough_reverse) diff --git a/dependencies/libarchive-3.4.2/cpio/test/test.h b/dependencies/libarchive-3.4.2/cpio/test/test.h new file mode 100644 index 0000000..1dadf68 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2003-2017 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* Every test program should #include "test.h" as the first thing. */ + +#define KNOWNREF "test_option_f.cpio.uu" +#define ENVBASE "BSDCPIO" /* Prefix for environment variables. */ +#define PROGRAM "bsdcpio" /* Name of program being tested. */ +#define PROGRAM_ALIAS "cpio" /* Generic alias for program */ +#undef LIBRARY /* Not testing a library. */ +#undef EXTRA_DUMP /* How to dump extra data */ +#undef EXTRA_ERRNO /* How to dump errno */ +/* How to generate extra version info. */ +#define EXTRA_VERSION (systemf("%s --version", testprog) ? "" : "") + +#include "test_common.h" diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_0.c b/dependencies/libarchive-3.4.2/cpio/test/test_0.c new file mode 100644 index 0000000..fa52def --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_0.c @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * This first test does basic sanity checks on the environment. For + * most of these, we just exit on failure. + */ +#if !defined(_WIN32) || defined(__CYGWIN__) +#define DEV_NULL "/dev/null" +#else +#define DEV_NULL "NUL" +#endif + +DEFINE_TEST(test_0) +{ + struct stat st; + + failure("File %s does not exist?!", testprogfile); + if (!assertEqualInt(0, stat(testprogfile, &st))) { + fprintf(stderr, + "\nFile %s does not exist; aborting test.\n\n", + testprog); + exit(1); + } + + failure("%s is not executable?!", testprogfile); + if (!assert((st.st_mode & 0111) != 0)) { + fprintf(stderr, + "\nFile %s not executable; aborting test.\n\n", + testprog); + exit(1); + } + + /* + * Try to successfully run the program; this requires that + * we know some option that will succeed. + */ + if (0 == systemf("%s --version >" DEV_NULL, testprog)) { + /* This worked. */ + } else if (0 == systemf("%s -W version >" DEV_NULL, testprog)) { + /* This worked. */ + } else { + failure("Unable to successfully run any of the following:\n" + " * %s --version\n" + " * %s -W version\n", + testprog, testprog); + assert(0); + } + + /* TODO: Ensure that our reference files are available. */ +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_basic.c b/dependencies/libarchive-3.4.2/cpio/test/test_basic.c new file mode 100644 index 0000000..b716253 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_basic.c @@ -0,0 +1,238 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/usr.bin/cpio/test/test_basic.c,v 1.4 2008/08/25 06:39:29 kientzle Exp $"); + +static void +verify_files(const char *msg) +{ + /* + * Verify unpacked files. + */ + + /* Regular file with 2 links. */ + failure("%s", msg); + assertIsReg("file", 0644); + failure("%s", msg); + assertFileSize("file", 10); + failure("%s", msg); + assertFileNLinks("file", 2); + + /* Another name for the same file. */ + failure("%s", msg); + assertIsHardlink("linkfile", "file"); + + /* Symlink */ + if (canSymlink()) + assertIsSymlink("symlink", "file", 0); + + /* Another file with 1 link and different permissions. */ + failure("%s", msg); + assertIsReg("file2", 0777); + failure("%s", msg); + assertFileSize("file2", 10); + failure("%s", msg); + assertFileNLinks("file2", 1); + + /* dir */ + assertIsDir("dir", 0775); +} + +static void +basic_cpio(const char *target, + const char *pack_options, + const char *unpack_options, + const char *se, const char *se2) +{ + int r; + + if (!assertMakeDir(target, 0775)) + return; + + /* Use the cpio program to create an archive. */ + r = systemf("%s -R 1000:1000 -o %s < filelist >%s/archive 2>%s/pack.err", + testprog, pack_options, target, target); + failure("Error invoking %s -o %s", testprog, pack_options); + assertEqualInt(r, 0); + + assertChdir(target); + + /* Verify stderr. */ + failure("Expected: %s, options=%s", se, pack_options); + assertTextFileContents(se, "pack.err"); + + /* + * Use cpio to unpack the archive into another directory. + */ + r = systemf("%s -i %s< archive >unpack.out 2>unpack.err", + testprog, unpack_options); + failure("Error invoking %s -i %s", testprog, unpack_options); + assertEqualInt(r, 0); + + /* Verify stderr. */ + failure("Error invoking %s -i %s in dir %s", testprog, unpack_options, target); + assertTextFileContents(se2, "unpack.err"); + + verify_files(pack_options); + + assertChdir(".."); +} + +static void +passthrough(const char *target) +{ + int r; + + if (!assertMakeDir(target, 0775)) + return; + + /* + * Use cpio passthrough mode to copy files to another directory. + */ + r = systemf("%s -p %s %s/stdout 2>%s/stderr", + testprog, target, target, target); + failure("Error invoking %s -p", testprog); + assertEqualInt(r, 0); + + assertChdir(target); + + /* Verify stderr. */ + failure("Error invoking %s -p in dir %s", + testprog, target); + assertTextFileContents("1 block\n", "stderr"); + + verify_files("passthrough"); + assertChdir(".."); +} + +DEFINE_TEST(test_basic) +{ + FILE *filelist; + const char *msg; + char result[1024]; + + assertUmask(0); + + /* + * Create an assortment of files on disk. + */ + filelist = fopen("filelist", "w"); + memset(result, 0, sizeof(result)); + + /* File with 10 bytes content. */ + assertMakeFile("file", 0644, "1234567890"); + fprintf(filelist, "file\n"); + if (is_LargeInode("file")) { + strncat(result, + "bsdcpio: file: large inode number truncated: ", + sizeof(result) - strlen(result) -1); + strncat(result, + strerror(ERANGE), + sizeof(result) - strlen(result) -1); + strncat(result, + "\n", + sizeof(result) - strlen(result) -1); + } + + /* hardlink to above file. */ + assertMakeHardlink("linkfile", "file"); + fprintf(filelist, "linkfile\n"); + if (is_LargeInode("linkfile")) { + strncat(result, + "bsdcpio: linkfile: large inode number truncated: ", + sizeof(result) - strlen(result) -1); + strncat(result, + strerror(ERANGE), + sizeof(result) - strlen(result) -1); + strncat(result, + "\n", + sizeof(result) - strlen(result) -1); + } + + /* Symlink to above file. */ + if (canSymlink()) { + assertMakeSymlink("symlink", "file", 0); + fprintf(filelist, "symlink\n"); + if (is_LargeInode("symlink")) { + strncat(result, + "bsdcpio: symlink: large inode number truncated: ", + sizeof(result) - strlen(result) -1); + strncat(result, + strerror(ERANGE), + sizeof(result) - strlen(result) -1); + strncat(result, + "\n", + sizeof(result) - strlen(result) -1); + } + } + + /* Another file with different permissions. */ + assertMakeFile("file2", 0777, "1234567890"); + fprintf(filelist, "file2\n"); + if (is_LargeInode("file2")) { + strncat(result, + "bsdcpio: file2: large inode number truncated: ", + sizeof(result) - strlen(result) -1); + strncat(result, + strerror(ERANGE), + sizeof(result) - strlen(result) -1); + strncat(result, + "\n", + sizeof(result) - strlen(result) -1); + } + + /* Directory. */ + assertMakeDir("dir", 0775); + fprintf(filelist, "dir\n"); + if (is_LargeInode("dir")) { + strncat(result, + "bsdcpio: dir: large inode number truncated: ", + sizeof(result) - strlen(result) -1); + strncat(result, + strerror(ERANGE), + sizeof(result) - strlen(result) -1); + strncat(result, + "\n", + sizeof(result) - strlen(result) -1); + } + strncat(result, "2 blocks\n", sizeof(result) - strlen(result) -1); + + /* All done. */ + fclose(filelist); + + assertUmask(022); + + /* Archive/dearchive with a variety of options. */ + msg = canSymlink() ? "2 blocks\n" : "1 block\n"; + basic_cpio("copy", "", "", msg, msg); + basic_cpio("copy_odc", "--format=odc", "", msg, msg); + basic_cpio("copy_newc", "-H newc", "", result, "2 blocks\n"); + basic_cpio("copy_cpio", "-H odc", "", msg, msg); + msg = canSymlink() ? "9 blocks\n" : "8 blocks\n"; + basic_cpio("copy_ustar", "-H ustar", "", msg, msg); + + /* Copy in one step using -p */ + passthrough("passthrough"); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_cmdline.c b/dependencies/libarchive-3.4.2/cpio/test/test_cmdline.c new file mode 100644 index 0000000..2dd7d65 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_cmdline.c @@ -0,0 +1,107 @@ +/*- + * Copyright (c) 2003-2009 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * Test the command-line parsing. + */ + +DEFINE_TEST(test_cmdline) +{ + FILE *f; + + /* Create an empty file. */ + f = fopen("empty", "wb"); + assert(f != NULL); + fclose(f); + + failure("-Q is an invalid option on every cpio program I know of"); + assert(0 != systemf("%s -i -Q 1.out 2>1.err", testprog)); + assertEmptyFile("1.out"); + + failure("-f requires an argument"); + assert(0 != systemf("%s -if 2.out 2>2.err", testprog)); + assertEmptyFile("2.out"); + + failure("-f requires an argument"); + assert(0 != systemf("%s -i -f 3.out 2>3.err", testprog)); + assertEmptyFile("3.out"); + + failure("--format requires an argument"); + assert(0 != systemf("%s -i --format 4.out 2>4.err", testprog)); + assertEmptyFile("4.out"); + + failure("--badopt is an invalid option"); + assert(0 != systemf("%s -i --badop 5.out 2>5.err", testprog)); + assertEmptyFile("5.out"); + + failure("--badopt is an invalid option"); + assert(0 != systemf("%s -i --badopt 6.out 2>6.err", testprog)); + assertEmptyFile("6.out"); + + failure("--n is ambiguous"); + assert(0 != systemf("%s -i --n 7.out 2>7.err", testprog)); + assertEmptyFile("7.out"); + + failure("--create forbids an argument"); + assert(0 != systemf("%s --create=arg 8.out 2>8.err", testprog)); + assertEmptyFile("8.out"); + + failure("-i with empty input should succeed"); + assert(0 == systemf("%s -i 9.out 2>9.err", testprog)); + assertEmptyFile("9.out"); + + failure("-o with empty input should succeed"); + assert(0 == systemf("%s -o 10.out 2>10.err", testprog)); + + failure("-i -p is nonsense"); + assert(0 != systemf("%s -i -p 11.out 2>11.err", testprog)); + assertEmptyFile("11.out"); + + failure("-p -i is nonsense"); + assert(0 != systemf("%s -p -i 12.out 2>12.err", testprog)); + assertEmptyFile("12.out"); + + failure("-i -o is nonsense"); + assert(0 != systemf("%s -i -o 13.out 2>13.err", testprog)); + assertEmptyFile("13.out"); + + failure("-o -i is nonsense"); + assert(0 != systemf("%s -o -i 14.out 2>14.err", testprog)); + assertEmptyFile("14.out"); + + failure("-o -p is nonsense"); + assert(0 != systemf("%s -o -p 15.out 2>15.err", testprog)); + assertEmptyFile("15.out"); + + failure("-p -o is nonsense"); + assert(0 != systemf("%s -p -o 16.out 2>16.err", testprog)); + assertEmptyFile("16.out"); + + failure("-p with empty input should fail"); + assert(0 != systemf("%s -p 17.out 2>17.err", testprog)); + assertEmptyFile("17.out"); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.Z.uu b/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.Z.uu new file mode 100644 index 0000000..e520a34 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.Z.uu @@ -0,0 +1,7 @@ +begin 664 test_extract.cpio.Z +M'YV0,&X$'`B#!@P8,0XJC)$0A@T;!A'>J+%PHL*%%P_&D`%CAHP;!F7,B*C0 +M1L:+(LVD85,F!H`Q;]S0*2-S#H@W9D"H9!G#A8*!`@46U)A11L.'$6-8U+CT +M8D.G'#V"A"&#!L6+)D\>3+FRC(R7,6?6O)ESIU>?0`EJ7/'D!4# +` +end diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.bz2.uu b/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.bz2.uu new file mode 100644 index 0000000..228a957 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.bz2.uu @@ -0,0 +1,7 @@ +begin 664 test_extract.cpio.bz2 +M0EIH.3%!629365?=.4@``#G_@G*0(`#@`7^`(B04``LEC```!"``E`E(>I,H +M::'J&@_4C3:@E$AD#0&@&@%"E;V/1!XIP>#C9T[41`4PQ1A`@S*4F&BD@B0T +MBA$$-:\/@BQGNKU1G@%#`G+N0R%$JTHG(XBRB%1$V8F4#F_IWT=S4+ERVL(? +40V!'@1L4+AO_B[DBG"A(*^Z0,#J&)3G"\^YE?X_' +M_K._F':0[`DL%IQ=<,Z-JH>V$S,?.[`&42C7]J^XQ@9OY!Z$!$^JLQPKZU[: +/!M,+.$MY:Y(HS<<]U`&` +` +end diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.gz.uu b/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.gz.uu new file mode 100644 index 0000000..7ddccad --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.gz.uu @@ -0,0 +1,7 @@ +begin 664 test_extract.cpio.gz +M'XL("`5X2FE=2K)"? +MI@`6T>,R0+?$B$A+3$RQ6F*$88D1PA*"P!"[J#$2)R3(T=/'-4A149%AF`,` +(305ZBP`"```` +` +end diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.lrz.uu b/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.lrz.uu new file mode 100644 index 0000000..563f797 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.lrz.uu @@ -0,0 +1,8 @@ +begin 664 test_extract.cpio.lrz +M3%):20`&``(``````````%T````!`0```@$`$`,`````#@`#`````"\``QH` +M&@````!W``$G`&4``#,``2(``0``#0$````U<-`Y!F$`MP$````8#=\$8#<1 +MR/BL39$D4M>["H7&@4%L/4*_(*VGB*YU>?RX.9]HL86'.A)H@Y;Z\^$?M^8_ +M!/-;62G.*7*A&A!_ENZ8$7]O-M7_.FTRC%BCGC95:6'9ZH3)QSCR4RX42P!` +/-E>/7"L[:OY"/A924S4$ +` +end diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.lz.uu b/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.lz.uu new file mode 100644 index 0000000..67e41e9 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.lz.uu @@ -0,0 +1,6 @@ +begin 664 test_extract.cpio.lz +M3%I)4`$,`!@-WP1@-Q'(^*Q-D212U[L*A<:!06P]0K\@K:>(KG5Y_+@YGVBQ +MA8;_>8N3MLP="$0SJ#QKYB?@8 +G]@'$$7\&W^T*+9?6B=?__M$G@$T%>HL``@```````($````````` +` +end diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.lz4.uu b/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.lz4.uu new file mode 100644 index 0000000..0adc7bb --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.lz4.uu @@ -0,0 +1,7 @@ +begin 644 test_extract.cpio.lz4 +M!")-&&1PN9$````A,#<"`&`P-#`P,3`!`&`Q,3`P-C8/`#0W-3`&```)``$& +M`,$P,3(P,S(W-#`R,S01`!$V!@```@#Q!3(S9FEL93$`8V]N=&5N=',@;V8@ +M$@`A+@IC``AE`!\R90`4$#2#``YE`!TR90`6,F4`#P(`#@+H``P"`"["H7&@4%L/4*_(*VGB*YU +M>?RX.9]HL86'.A)H@Y;Z\^$?M^8_!/-;62G.*7*A&A!_HGF_WF+D[;.+!OW3 +:T_2I)V(;K[FNL#'W%T+L;ATS`A*3__[1Z``` +` +end diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.lzo.uu b/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.lzo.uu new file mode 100644 index 0000000..8ce87c7 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.lzo.uu @@ -0,0 +1,9 @@ +begin 664 test_extract.cpio.lzo +MB4Q:3P`-"AH*$#`@8`E``04#```!``"!M%!R>-T`````$71E`$#-S4P,#`QE`!@`7`#"C`P,3(P,S(W-#`R,S2!`C:4`'````(R,V9I;&4Q +M`&-O;G1E;G1S(&]F((8"+@HOD0$R(`:1`31J$#`P+I$!,B^1`3(HD`%L$3L, +M`+P<+HH`,3,I1``(5%)!24Q%4B$A(0`@JP````$````````````````````` +*````$0`````````` +` +end diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.xz.uu b/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.xz.uu new file mode 100644 index 0000000..5c593cf --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.xz.uu @@ -0,0 +1,7 @@ +begin 664 test_extract.cpio.xz +M_3=Z6%H```3FUK1&`@`A`18```!T+^6CX`'_`&%=`!@-WP1@-Q'(^*Q-D212 +MU[L*A<:!06P]0K\@K:>(KG5Y_+@YGVBQA8;_>8N3MLXL&_=/3]*DG8ANON:ZP,?<70NQN'3"CP@``````J9FA +=#1$]4L<``7V`!`````?M;4JQQ&?[`@`````$65H` +` +end diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.zst.uu b/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.zst.uu new file mode 100644 index 0000000..5ec854b --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_extract.cpio.zst.uu @@ -0,0 +1,6 @@ +begin 644 test_extract.cpio.zst +M*+4O_01090,`,@41%X")&@#'G6T\K16_MR)#=DK)5:.1,2J0HY2"!(1!`!7R +M$(UB`2"*D41;J2UF&)<0!Y7X'TU<%W.\W^R]GO-WW^OO^QX0`%P<]30-!#U` +?!KD!`#XP,_`U4`HT3+RF:#!7Y\V@R)5"7P"^;WEUK@`` +` +end diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_Z.c b/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_Z.c new file mode 100644 index 0000000..f908fc5 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_Z.c @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_extract_cpio_Z) +{ + const char *reffile = "test_extract.cpio.Z"; + + extract_reference_file(reffile); + assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err", + testprog, reffile)); + + assertFileExists("file1"); + assertTextFileContents("contents of file1.\n", "file1"); + assertFileExists("file2"); + assertTextFileContents("contents of file2.\n", "file2"); + assertEmptyFile("test.out"); + assertTextFileContents("1 block\n", "test.err"); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_bz2.c b/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_bz2.c new file mode 100644 index 0000000..9525e63 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_bz2.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_extract_cpio_bz2) +{ + const char *reffile = "test_extract.cpio.bz2"; + int f; + + extract_reference_file(reffile); + f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canBzip2()) { + assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err", + testprog, reffile)); + + assertFileExists("file1"); + assertTextFileContents("contents of file1.\n", "file1"); + assertFileExists("file2"); + assertTextFileContents("contents of file2.\n", "file2"); + assertEmptyFile("test.out"); + assertTextFileContents("1 block\n", "test.err"); + } else { + skipping("It seems bzip2 is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_grz.c b/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_grz.c new file mode 100644 index 0000000..f1a0805 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_grz.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_extract_cpio_grz) +{ + const char *reffile = "test_extract.cpio.grz"; + int f; + + extract_reference_file(reffile); + f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canGrzip()) { + assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err", + testprog, reffile)); + + assertFileExists("file1"); + assertTextFileContents("contents of file1.\n", "file1"); + assertFileExists("file2"); + assertTextFileContents("contents of file2.\n", "file2"); + assertEmptyFile("test.out"); + assertTextFileContents("1 block\n", "test.err"); + } else { + skipping("It seems grzip is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_gz.c b/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_gz.c new file mode 100644 index 0000000..19cee51 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_gz.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_extract_cpio_gz) +{ + const char *reffile = "test_extract.cpio.gz"; + int f; + + extract_reference_file(reffile); + f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canGzip()) { + assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err", + testprog, reffile)); + + assertFileExists("file1"); + assertTextFileContents("contents of file1.\n", "file1"); + assertFileExists("file2"); + assertTextFileContents("contents of file2.\n", "file2"); + assertEmptyFile("test.out"); + assertTextFileContents("1 block\n", "test.err"); + } else { + skipping("It seems gzip is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_lrz.c b/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_lrz.c new file mode 100644 index 0000000..6766758 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_lrz.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_extract_cpio_lrz) +{ + const char *reffile = "test_extract.cpio.lrz"; + int f; + + extract_reference_file(reffile); + f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canLrzip()) { + assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err", + testprog, reffile)); + + assertFileExists("file1"); + assertTextFileContents("contents of file1.\n", "file1"); + assertFileExists("file2"); + assertTextFileContents("contents of file2.\n", "file2"); + assertEmptyFile("test.out"); + assertTextFileContents("1 block\n", "test.err"); + } else { + skipping("It seems lrzip is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_lz.c b/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_lz.c new file mode 100644 index 0000000..4454e7b --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_lz.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_extract_cpio_lz) +{ + const char *reffile = "test_extract.cpio.lz"; + int f; + + extract_reference_file(reffile); + f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canLzip()) { + assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err", + testprog, reffile)); + + assertFileExists("file1"); + assertTextFileContents("contents of file1.\n", "file1"); + assertFileExists("file2"); + assertTextFileContents("contents of file2.\n", "file2"); + assertEmptyFile("test.out"); + assertTextFileContents("1 block\n", "test.err"); + } else { + skipping("It seems lzip is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_lz4.c b/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_lz4.c new file mode 100644 index 0000000..c16247b --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_lz4.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2012,2014 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_extract_cpio_lz4) +{ + const char *reffile = "test_extract.cpio.lz4"; + int f; + + extract_reference_file(reffile); + f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canLz4()) { + assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err", + testprog, reffile)); + + assertFileExists("file1"); + assertTextFileContents("contents of file1.\n", "file1"); + assertFileExists("file2"); + assertTextFileContents("contents of file2.\n", "file2"); + assertEmptyFile("test.out"); + assertTextFileContents("1 block\n", "test.err"); + } else { + skipping("It seems lz4 is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_lzma.c b/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_lzma.c new file mode 100644 index 0000000..ae630d6 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_lzma.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_extract_cpio_lzma) +{ + const char *reffile = "test_extract.cpio.lzma"; + int f; + + extract_reference_file(reffile); + f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canLzma()) { + assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err", + testprog, reffile)); + + assertFileExists("file1"); + assertTextFileContents("contents of file1.\n", "file1"); + assertFileExists("file2"); + assertTextFileContents("contents of file2.\n", "file2"); + assertEmptyFile("test.out"); + assertTextFileContents("1 block\n", "test.err"); + } else { + skipping("It seems lzma is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_lzo.c b/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_lzo.c new file mode 100644 index 0000000..99476af --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_lzo.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_extract_cpio_lzo) +{ + const char *reffile = "test_extract.cpio.lzo"; + int f; + + extract_reference_file(reffile); + f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canLzop()) { + assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err", + testprog, reffile)); + + assertFileExists("file1"); + assertTextFileContents("contents of file1.\n", "file1"); + assertFileExists("file2"); + assertTextFileContents("contents of file2.\n", "file2"); + assertEmptyFile("test.out"); + assertTextFileContents("1 block\n", "test.err"); + } else { + skipping("It seems lzop is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_xz.c b/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_xz.c new file mode 100644 index 0000000..60f1b5a --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_xz.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_extract_cpio_xz) +{ + const char *reffile = "test_extract.cpio.xz"; + int f; + + extract_reference_file(reffile); + f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canXz()) { + assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err", + testprog, reffile)); + + assertFileExists("file1"); + assertTextFileContents("contents of file1.\n", "file1"); + assertFileExists("file2"); + assertTextFileContents("contents of file2.\n", "file2"); + assertEmptyFile("test.out"); + assertTextFileContents("1 block\n", "test.err"); + } else { + skipping("It seems xz is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_zstd.c b/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_zstd.c new file mode 100644 index 0000000..289f33d --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_extract_cpio_zstd.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2017 Sean Purcell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_extract_cpio_zstd) +{ + const char *reffile = "test_extract.cpio.zst"; + int f; + + extract_reference_file(reffile); + f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canZstd()) { + assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err", + testprog, reffile)); + + assertFileExists("file1"); + assertTextFileContents("contents of file1.\n", "file1"); + assertFileExists("file2"); + assertTextFileContents("contents of file2.\n", "file2"); + assertEmptyFile("test.out"); + assertTextFileContents("1 block\n", "test.err"); + } else { + skipping("It seems zstd is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_format_newc.c b/dependencies/libarchive-3.4.2/cpio/test/test_format_newc.c new file mode 100644 index 0000000..49387a7 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_format_newc.c @@ -0,0 +1,355 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/usr.bin/cpio/test/test_format_newc.c,v 1.2 2008/08/22 02:09:10 kientzle Exp $"); + +/* Number of bytes needed to pad 'n' to multiple of 'block', assuming + * that 'block' is a power of two. This trick can be more easily + * remembered as -n & (block - 1), but many compilers quite reasonably + * warn about "-n" when n is an unsigned value. (~(n) + 1) is the + * same thing, but written in a way that won't offend anyone. */ +#define PAD(n, block) ((~(n) + 1) & ((block) - 1)) + +static int +is_hex(const char *p, size_t l) +{ + while (l > 0) { + if ((*p >= '0' && *p <= '9') + || (*p >= 'a' && *p <= 'f') + || (*p >= 'A' && *p <= 'F')) + { + --l; + ++p; + } else + return (0); + + } + return (1); +} + +static int +from_hex(const char *p, size_t l) +{ + int r = 0; + + while (l > 0) { + r *= 16; + if (*p >= 'a' && *p <= 'f') + r += *p + 10 - 'a'; + else if (*p >= 'A' && *p <= 'F') + r += *p + 10 - 'A'; + else + r += *p - '0'; + --l; + ++p; + } + return (r); +} + +#if !defined(_WIN32) || defined(__CYGWIN__) +static int +nlinks(const char *p) +{ + struct stat st; + assertEqualInt(0, stat(p, &st)); + return st.st_nlink; +} +#endif + +DEFINE_TEST(test_format_newc) +{ + FILE *list; + int r; + int devmajor, devminor, ino, gid; + int uid = -1; + time_t t, t2, now; + char *p, *e; + size_t s, fs, ns; + char result[1024]; + + assertUmask(0); + +#if !defined(_WIN32) + uid = getuid(); +#endif + + /* + * Create an assortment of files. + * TODO: Extend this to cover more filetypes. + */ + list = fopen("list", "w"); + + /* "file1" */ + assertMakeFile("file1", 0644, "1234567890"); + fprintf(list, "file1\n"); + + /* "hardlink" */ + assertMakeHardlink("hardlink", "file1"); + fprintf(list, "hardlink\n"); + + /* Another hardlink, but this one won't be archived. */ + assertMakeHardlink("hardlink2", "file1"); + + /* "symlink" */ + if (canSymlink()) { + assertMakeSymlink("symlink", "file1", 0); + fprintf(list, "symlink\n"); + } + + /* "dir" */ + assertMakeDir("dir", 0775); + fprintf(list, "dir\n"); + + /* Setup result message. */ + memset(result, 0, sizeof(result)); + if (is_LargeInode("file1")) { + strncat(result, + "bsdcpio: file1: large inode number truncated: ", + sizeof(result) - strlen(result) -1); + strncat(result, strerror(ERANGE), + sizeof(result) - strlen(result) -1); + strncat(result, "\n", + sizeof(result) - strlen(result) -1); + } + if (canSymlink() && is_LargeInode("symlink")) { + strncat(result, + "bsdcpio: symlink: large inode number truncated: ", + sizeof(result) - strlen(result) -1); + strncat(result, strerror(ERANGE), + sizeof(result) - strlen(result) -1); + strncat(result, "\n", + sizeof(result) - strlen(result) -1); + } + if (is_LargeInode("dir")) { + strncat(result, + "bsdcpio: dir: large inode number truncated: ", + sizeof(result) - strlen(result) -1); + strncat(result, strerror(ERANGE), + sizeof(result) - strlen(result) -1); + strncat(result, "\n", + sizeof(result) - strlen(result) -1); + } + if (is_LargeInode("hardlink")) { + strncat(result, + "bsdcpio: hardlink: large inode number truncated: ", + sizeof(result) - strlen(result) -1); + strncat(result, strerror(ERANGE), + sizeof(result) - strlen(result) -1); + strncat(result, "\n", + sizeof(result) - strlen(result) -1); + } + + /* Record some facts about what we just created: */ + now = time(NULL); /* They were all created w/in last two seconds. */ + + /* Use the cpio program to create an archive. */ + fclose(list); + r = systemf("%s -o --format=newc newc.out 2>newc.err", + testprog); + if (!assertEqualInt(r, 0)) + return; + + /* Verify that nothing went to stderr. */ + if (canSymlink()) { + strncat(result, "2 blocks\n", sizeof(result) - strlen(result) -1); + } else { + strncat(result, "1 block\n", sizeof(result) - strlen(result) -1); + } + assertTextFileContents(result, "newc.err"); + + /* Verify that stdout is a well-formed cpio file in "newc" format. */ + p = slurpfile(&s, "newc.out"); + assertEqualInt(s, canSymlink() ? 1024 : 512); + e = p; + + /* + * Some of these assertions could be stronger, but it's + * a little tricky because they depend on the local environment. + */ + + /* First entry is "file1" */ + assert(is_hex(e, 110)); /* Entire header is octal digits. */ + assertEqualMem(e + 0, "070701", 6); /* Magic */ + ino = from_hex(e + 6, 8); /* ino */ +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Group members bits and others bits do not work. */ + assertEqualInt(0x8180, from_hex(e + 14, 8) & 0xffc0); /* Mode */ +#else + assertEqualInt(0x81a4, from_hex(e + 14, 8)); /* Mode */ +#endif + if (uid < 0) + uid = from_hex(e + 22, 8); + assertEqualInt(from_hex(e + 22, 8), uid); /* uid */ + gid = from_hex(e + 30, 8); /* gid */ + assertEqualMem(e + 38, "00000003", 8); /* nlink */ + t = from_hex(e + 46, 8); /* mtime */ + failure("t=%#08jx now=%#08jx=%jd", (intmax_t)t, (intmax_t)now, + (intmax_t)now); + assert(t <= now); /* File wasn't created in future. */ + failure("t=%#08jx now - 2=%#08jx=%jd", (intmax_t)t, (intmax_t)now - 2, + (intmax_t)now - 2); + assert(t >= now - 2); /* File was created w/in last 2 secs. */ + failure("newc format stores body only with last appearance of a link\n" + " first appearance should be empty, so this file size\n" + " field should be zero"); + assertEqualInt(0, from_hex(e + 54, 8)); /* File size */ + fs = from_hex(e + 54, 8); + fs += PAD(fs, 4); + devmajor = from_hex(e + 62, 8); /* devmajor */ + devminor = from_hex(e + 70, 8); /* devminor */ + assert(is_hex(e + 78, 8)); /* rdevmajor */ + assert(is_hex(e + 86, 8)); /* rdevminor */ + assertEqualMem(e + 94, "00000006", 8); /* Name size */ + ns = from_hex(e + 94, 8); + ns += PAD(ns + 2, 4); + assertEqualInt(0, from_hex(e + 102, 8)); /* check field */ + assertEqualMem(e + 110, "file1\0", 6); /* Name contents */ + /* Since there's another link, no file contents here. */ + /* But add in file size so that an error here doesn't cascade. */ + e += 110 + fs + ns; + + if (canSymlink()) { + /* "symlink" pointing to "file1" */ + assert(is_hex(e, 110)); + assertEqualMem(e + 0, "070701", 6); /* Magic */ + assert(is_hex(e + 6, 8)); /* ino */ +#if defined(_WIN32) && !defined(CYGWIN) + /* Mode: Group members bits and others bits do not work. */ + assertEqualInt(0xa180, from_hex(e + 14, 8) & 0xffc0); +#else + assertEqualInt(0xa1ff, from_hex(e + 14, 8)); /* Mode */ +#endif + assertEqualInt(from_hex(e + 22, 8), uid); /* uid */ + assertEqualInt(gid, from_hex(e + 30, 8)); /* gid */ + assertEqualMem(e + 38, "00000001", 8); /* nlink */ + t2 = from_hex(e + 46, 8); /* mtime */ + failure("First entry created at t=%#08jx this entry created" + " at t2=%#08jx", (intmax_t)t, (intmax_t)t2); + assert(t2 == t || t2 == t + 1); /* Almost same as first entry. */ + assertEqualMem(e + 54, "00000005", 8); /* File size */ + fs = from_hex(e + 54, 8); + fs += PAD(fs, 4); + assertEqualInt(devmajor, from_hex(e + 62, 8)); /* devmajor */ + assertEqualInt(devminor, from_hex(e + 70, 8)); /* devminor */ + assert(is_hex(e + 78, 8)); /* rdevmajor */ + assert(is_hex(e + 86, 8)); /* rdevminor */ + assertEqualMem(e + 94, "00000008", 8); /* Name size */ + ns = from_hex(e + 94, 8); + ns += PAD(ns + 2, 4); + assertEqualInt(0, from_hex(e + 102, 8)); /* check field */ + assertEqualMem(e + 110, "symlink\0\0\0", 10); /* Name contents */ + assertEqualMem(e + 110 + ns, "file1\0\0\0", 8); /* symlink target */ + e += 110 + fs + ns; + } + + /* "dir" */ + assert(is_hex(e, 110)); + assertEqualMem(e + 0, "070701", 6); /* Magic */ + assert(is_hex(e + 6, 8)); /* ino */ +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Group members bits and others bits do not work. */ + assertEqualInt(0x41c0, from_hex(e + 14, 8) & 0xffc0); /* Mode */ +#else + /* Mode: sgid bit sometimes propagates from parent dirs, ignore it. */ + assertEqualInt(040775, from_hex(e + 14, 8) & ~02000); +#endif + assertEqualInt(uid, from_hex(e + 22, 8)); /* uid */ + assertEqualInt(gid, from_hex(e + 30, 8)); /* gid */ +#if !defined(_WIN32) || defined(__CYGWIN__) + assertEqualInt(nlinks("dir"), from_hex(e + 38, 8)); /* nlinks */ +#endif + t2 = from_hex(e + 46, 8); /* mtime */ + failure("First entry created at t=%#08jx this entry created at" + "t2=%#08jx", (intmax_t)t, (intmax_t)t2); + assert(t2 == t || t2 == t + 1); /* Almost same as first entry. */ + assertEqualMem(e + 54, "00000000", 8); /* File size */ + fs = from_hex(e + 54, 8); + fs += PAD(fs, 4); + assertEqualInt(devmajor, from_hex(e + 62, 8)); /* devmajor */ + assertEqualInt(devminor, from_hex(e + 70, 8)); /* devminor */ + assert(is_hex(e + 78, 8)); /* rdevmajor */ + assert(is_hex(e + 86, 8)); /* rdevminor */ + assertEqualMem(e + 94, "00000004", 8); /* Name size */ + ns = from_hex(e + 94, 8); + ns += PAD(ns + 2, 4); + assertEqualInt(0, from_hex(e + 102, 8)); /* check field */ + assertEqualMem(e + 110, "dir\0\0\0", 6); /* Name contents */ + e += 110 + fs + ns; + + /* Hardlink identical to "file1" */ + /* Since we only wrote two of the three links to this + * file, this link should get deferred by the hardlink logic. */ + assert(is_hex(e, 110)); + assertEqualMem(e + 0, "070701", 6); /* Magic */ + failure("If these aren't the same, then the hardlink detection failed to match them."); + assertEqualInt(ino, from_hex(e + 6, 8)); /* ino */ +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Group members bits and others bits do not work. */ + assertEqualInt(0x8180, from_hex(e + 14, 8) & 0xffc0); /* Mode */ +#else + assertEqualInt(0x81a4, from_hex(e + 14, 8)); /* Mode */ +#endif + assertEqualInt(from_hex(e + 22, 8), uid); /* uid */ + assertEqualInt(gid, from_hex(e + 30, 8)); /* gid */ + assertEqualMem(e + 38, "00000003", 8); /* nlink */ + t2 = from_hex(e + 46, 8); /* mtime */ + failure("First entry created at t=%#08jx this entry created at" + "t2=%#08jx", (intmax_t)t, (intmax_t)t2); + assert(t2 == t || t2 == t + 1); /* Almost same as first entry. */ + assertEqualInt(10, from_hex(e + 54, 8)); /* File size */ + fs = from_hex(e + 54, 8); + fs += PAD(fs, 4); + assertEqualInt(devmajor, from_hex(e + 62, 8)); /* devmajor */ + assertEqualInt(devminor, from_hex(e + 70, 8)); /* devminor */ + assert(is_hex(e + 78, 8)); /* rdevmajor */ + assert(is_hex(e + 86, 8)); /* rdevminor */ + assertEqualMem(e + 94, "00000009", 8); /* Name size */ + ns = from_hex(e + 94, 8); + ns += PAD(ns + 2, 4); + assertEqualInt(0, from_hex(e + 102, 8)); /* check field */ + assertEqualMem(e + 110, "hardlink\0\0", 10); /* Name contents */ + assertEqualMem(e + 110 + ns, "1234567890\0\0", 12); /* File contents */ + e += 110 + ns + fs; + + /* Last entry is end-of-archive marker. */ + assert(is_hex(e, 110)); + assertEqualMem(e + 0, "070701", 6); /* Magic */ + assertEqualMem(e + 8, "00000000", 8); /* ino */ + assertEqualMem(e + 14, "00000000", 8); /* mode */ + assertEqualMem(e + 22, "00000000", 8); /* uid */ + assertEqualMem(e + 30, "00000000", 8); /* gid */ + assertEqualMem(e + 38, "00000001", 8); /* nlink */ + assertEqualMem(e + 46, "00000000", 8); /* mtime */ + assertEqualMem(e + 54, "00000000", 8); /* size */ + assertEqualMem(e + 62, "00000000", 8); /* devmajor */ + assertEqualMem(e + 70, "00000000", 8); /* devminor */ + assertEqualMem(e + 78, "00000000", 8); /* rdevmajor */ + assertEqualMem(e + 86, "00000000", 8); /* rdevminor */ + assertEqualInt(11, from_hex(e + 94, 8)); /* name size */ + assertEqualMem(e + 102, "00000000", 8); /* check field */ + assertEqualMem(e + 110, "TRAILER!!!\0\0", 12); /* Name */ + + free(p); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_gcpio_compat.c b/dependencies/libarchive-3.4.2/cpio/test/test_gcpio_compat.c new file mode 100644 index 0000000..9bb9889 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_gcpio_compat.c @@ -0,0 +1,108 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/usr.bin/cpio/test/test_gcpio_compat.c,v 1.2 2008/08/22 02:27:06 kientzle Exp $"); + +static void +unpack_test(const char *from, const char *options, const char *se) +{ + int r; + + /* Create a work dir named after the file we're unpacking. */ + assertMakeDir(from, 0775); + assertChdir(from); + + /* + * Use cpio to unpack the sample archive + */ + extract_reference_file(from); + r = systemf("%s -i %s < %s >unpack.out 2>unpack.err", + testprog, options, from); + failure("Error invoking %s -i %s < %s", + testprog, options, from); + assertEqualInt(r, 0); + + /* Verify that nothing went to stderr. */ + if (canSymlink()) { + failure("Error invoking %s -i %s < %s", + testprog, options, from); + assertTextFileContents(se, "unpack.err"); + } + + /* + * Verify unpacked files. + */ + + /* Regular file with 2 links. */ + assertIsReg("file", 0644); + failure("%s", from); + assertFileSize("file", 10); + assertFileSize("linkfile", 10); + failure("%s", from); + assertFileNLinks("file", 2); + + /* Another name for the same file. */ + failure("%s", from); + assertIsHardlink("linkfile", "file"); + assertFileSize("file", 10); + assertFileSize("linkfile", 10); + + /* Symlink */ + if (canSymlink()) + assertIsSymlink("symlink", "file", 0); + + /* dir */ + assertIsDir("dir", 0775); + + assertChdir(".."); +} + +DEFINE_TEST(test_gcpio_compat) +{ + assertUmask(0); + + /* Dearchive sample files with a variety of options. */ + if (canSymlink()) { + unpack_test("test_gcpio_compat_ref.bin", + "--no-preserve-owner", "1 block\n"); + unpack_test("test_gcpio_compat_ref.crc", + "--no-preserve-owner", "2 blocks\n"); + unpack_test("test_gcpio_compat_ref.newc", + "--no-preserve-owner", "2 blocks\n"); + /* gcpio-2.9 only reads 6 blocks here */ + unpack_test("test_gcpio_compat_ref.ustar", + "--no-preserve-owner", "7 blocks\n"); + } else { + unpack_test("test_gcpio_compat_ref_nosym.bin", + "--no-preserve-owner", "1 block\n"); + unpack_test("test_gcpio_compat_ref_nosym.crc", + "--no-preserve-owner", "2 blocks\n"); + unpack_test("test_gcpio_compat_ref_nosym.newc", + "--no-preserve-owner", "2 blocks\n"); + /* gcpio-2.9 only reads 6 blocks here */ + unpack_test("test_gcpio_compat_ref_nosym.ustar", + "--no-preserve-owner", "7 blocks\n"); + } +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_gcpio_compat_ref.bin.uu b/dependencies/libarchive-3.4.2/cpio/test/test_gcpio_compat_ref.bin.uu new file mode 100644 index 0000000..745d8ab --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_gcpio_compat_ref.bin.uu @@ -0,0 +1,16 @@ +$FreeBSD$ +begin 644 test_gcpio_compat_ref.bin +MQW%9`*IWI('H`^@#`@````U'=YD%````"@!F:6QE```Q,C,T-38W.#D*QW%9 +M`*IWI('H`^@#`@````U'=YD)````"@!L:6YK9FEL90``,3(S-#4V-S@Y"L=Q +M60"K=^VAZ`/H`P$````-1X29"`````0`stdout1 2>stderr1", testprog); + assertEqualInt(r, 0); + assertTextFileContents("1 block\n", "stderr1"); + + assertMakeFile("filelist2", 0644, "file1\nfile2\nfile3\n"); + r = systemf("%s -o stdout2 2>stderr2", testprog); + assert(r != 0); + + assertMakeFile("filelist3", 0644, ""); + r = systemf("%s -o stdout3 2>stderr3", testprog); + assertEqualInt(r, 0); + assertTextFileContents("1 block\n", "stderr3"); + + assertMakeFile("filelist4", 0644, "file3\n"); + r = systemf("%s -o stdout4 2>stderr4", testprog); + assert(r != 0); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_0.c b/dependencies/libarchive-3.4.2/cpio/test/test_option_0.c new file mode 100644 index 0000000..bc4aecd --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_0.c @@ -0,0 +1,92 @@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_0) +{ + FILE *filelist; + int r; + + assertUmask(0); + + /* Create a few files. */ + assertMakeFile("file1", 0644, "1234567890"); + assertMakeFile("file2", 0644, "1234567890"); + assertMakeFile("file3", 0644, "1234567890"); + assertMakeFile("file4", 0644, "1234567890"); + + /* Create a file list of filenames with varying end-of-line. */ + filelist = fopen("filelist", "wb"); + assertEqualInt(fwrite("file1\x0a", 1, 6, filelist), 6); + assertEqualInt(fwrite("file2\x0d", 1, 6, filelist), 6); + assertEqualInt(fwrite("file3\x0a\x0d", 1, 7, filelist), 7); + assertEqualInt(fwrite("file4", 1, 5, filelist), 5); + fclose(filelist); + + /* Create a file list of null-delimited names. */ + filelist = fopen("filelistNull", "wb"); + assertEqualInt(fwrite("file1\0", 1, 6, filelist), 6); + assertEqualInt(fwrite("file2\0", 1, 6, filelist), 6); + assertEqualInt(fwrite("file3\0", 1, 6, filelist), 6); + assertEqualInt(fwrite("file4", 1, 5, filelist), 5); + fclose(filelist); + + assertUmask(022); + + /* Pack up using the file list with text line endings. */ + r = systemf("%s -o < filelist > archive 2> stderr1.txt", testprog); + assertEqualInt(r, 0); + + /* Extract into a new dir. */ + assertMakeDir("copy", 0775); + assertChdir("copy"); + r = systemf("%s -i < ../archive > stdout3.txt 2> stderr3.txt", testprog); + assertEqualInt(r, 0); + + /* Verify the files. */ + assertIsReg("file1", 0644); + assertIsReg("file2", 0644); + assertIsReg("file3", 0644); + assertIsReg("file4", 0644); + + assertChdir(".."); + + /* Pack up using the file list with nulls. */ + r = systemf("%s -o0 < filelistNull > archiveNull 2> stderr2.txt", testprog); + assertEqualInt(r, 0); + + /* Extract into a new dir. */ + assertMakeDir("copyNull", 0775); + assertChdir("copyNull"); + r = systemf("%s -i < ../archiveNull > stdout4.txt 2> stderr4.txt", testprog); + assertEqualInt(r, 0); + + /* Verify the files. */ + assertIsReg("file1", 0644); + assertIsReg("file2", 0644); + assertIsReg("file3", 0644); + assertIsReg("file4", 0644); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_B_upper.c b/dependencies/libarchive-3.4.2/cpio/test/test_option_B_upper.c new file mode 100644 index 0000000..b040354 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_B_upper.c @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + + +DEFINE_TEST(test_option_B_upper) +{ + struct stat st; + int r; + + /* + * Create a file on disk. + */ + assertMakeFile("file", 0644, NULL); + + /* Create an archive without -B; this should be 512 bytes. */ + r = systemf("echo file | %s -o > small.cpio 2>small.err", testprog); + assertEqualInt(r, 0); + assertTextFileContents("1 block\n", "small.err"); + assertEqualInt(0, stat("small.cpio", &st)); + assertEqualInt(512, st.st_size); + + /* Create an archive with -B; this should be 5120 bytes. */ + r = systemf("echo file | %s -oB > large.cpio 2>large.err", testprog); + assertEqualInt(r, 0); + assertTextFileContents("1 block\n", "large.err"); + assertEqualInt(0, stat("large.cpio", &st)); + assertEqualInt(5120, st.st_size); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_C_upper.c b/dependencies/libarchive-3.4.2/cpio/test/test_option_C_upper.c new file mode 100644 index 0000000..c8e63fd --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_C_upper.c @@ -0,0 +1,62 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + + +DEFINE_TEST(test_option_C_upper) +{ + int r; + + /* + * Create a file on disk. + */ + assertMakeFile("file", 0644, NULL); + + /* Create an archive without -C; this should be 512 bytes. */ + r = systemf("echo file | %s -o > small.cpio 2>small.err", testprog); + assertEqualInt(r, 0); + assertTextFileContents("1 block\n", "small.err"); + assertFileSize("small.cpio", 512); + + /* Create an archive with -C 513; this should be 513 bytes. */ + r = systemf("echo file | %s -o -C 513 > 513.cpio 2>513.err", + testprog); + assertEqualInt(r, 0); + assertTextFileContents("1 block\n", "513.err"); + assertFileSize("513.cpio", 513); + + /* Create an archive with -C 12345; this should be 12345 bytes. */ + r = systemf("echo file | %s -o -C12345 > 12345.cpio 2>12345.err", + testprog); + assertEqualInt(r, 0); + assertTextFileContents("1 block\n", "12345.err"); + assertFileSize("12345.cpio", 12345); + + /* Create an archive with invalid -C request */ + assert(0 != systemf("echo file | %s -o -C > bad.cpio 2>bad.err", + testprog)); + assertEmptyFile("bad.cpio"); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_J_upper.c b/dependencies/libarchive-3.4.2/cpio/test/test_option_J_upper.c new file mode 100644 index 0000000..1d7d051 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_J_upper.c @@ -0,0 +1,59 @@ +/*- + * Copyright (c) 2003-2009 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_J_upper) +{ + char *p; + int r; + size_t s; + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Archive it with xz compression. */ + r = systemf("echo f | %s -o -J >archive.out 2>archive.err", + testprog); + p = slurpfile(&s, "archive.err"); + p[s] = '\0'; + if (r != 0) { + if (strstr(p, "compression not available") != NULL) { + skipping("This version of bsdcpio was compiled " + "without xz support"); + return; + } + failure("-J option is broken"); + assertEqualInt(r, 0); + goto done; + } + free(p); + /* Check that the archive file has an xz signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "\3757zXZ", 5); +done: + free(p); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_L_upper.c b/dependencies/libarchive-3.4.2/cpio/test/test_option_L_upper.c new file mode 100644 index 0000000..cab41b6 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_L_upper.c @@ -0,0 +1,105 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/usr.bin/cpio/test/test_option_L.c,v 1.2 2008/08/24 06:21:00 kientzle Exp $"); + +/* This is a little pointless, as Windows doesn't support symlinks + * (except for the seriously crippled CreateSymbolicLink API) so these + * tests won't run on Windows. */ +#if defined(_WIN32) && !defined(__CYGWIN__) +#define CAT "type" +#define SEP "\\" +#else +#define CAT "cat" +#define SEP "/" +#endif + +DEFINE_TEST(test_option_L_upper) +{ + FILE *filelist; + int r; + + if (!canSymlink()) { + skipping("Symlink tests"); + return; + } + + filelist = fopen("filelist", "w"); + + /* Create a file and a symlink to the file. */ + assertMakeFile("file", 0644, "1234567890"); + fprintf(filelist, "file\n"); + + /* Symlink to above file. */ + assertMakeSymlink("symlink", "file", 0); + fprintf(filelist, "symlink\n"); + + fclose(filelist); + + r = systemf(CAT " filelist | %s -pd copy >copy.out 2>copy.err", testprog); + assertEqualInt(r, 0); + assertTextFileContents("1 block\n", "copy.err"); + + failure("Regular -p without -L should preserve symlinks."); + assertIsSymlink("copy/symlink", NULL, 0); + + r = systemf(CAT " filelist | %s -pd -L copy-L >copy-L.out 2>copy-L.err", testprog); + assertEqualInt(r, 0); + assertEmptyFile("copy-L.out"); + assertTextFileContents("1 block\n", "copy-L.err"); + failure("-pdL should dereference symlinks and turn them into files."); + assertIsReg("copy-L/symlink", -1); + + r = systemf(CAT " filelist | %s -o >archive.out 2>archive.err", testprog); + failure("Error invoking %s -o ", testprog); + assertEqualInt(r, 0); + assertTextFileContents("1 block\n", "archive.err"); + + assertMakeDir("unpack", 0755); + assertChdir("unpack"); + r = systemf(CAT " .." SEP "archive.out | %s -i >unpack.out 2>unpack.err", testprog); + + failure("Error invoking %s -i", testprog); + assertEqualInt(r, 0); + assertTextFileContents("1 block\n", "unpack.err"); + assertChdir(".."); + + assertIsSymlink("unpack/symlink", NULL, 0); + + r = systemf(CAT " filelist | %s -oL >archive-L.out 2>archive-L.err", testprog); + failure("Error invoking %s -oL", testprog); + assertEqualInt(r, 0); + assertTextFileContents("1 block\n", "archive-L.err"); + + assertMakeDir("unpack-L", 0755); + assertChdir("unpack-L"); + r = systemf(CAT " .." SEP "archive-L.out | %s -i >unpack-L.out 2>unpack-L.err", testprog); + + failure("Error invoking %s -i < archive-L.out", testprog); + assertEqualInt(r, 0); + assertTextFileContents("1 block\n", "unpack-L.err"); + assertChdir(".."); + assertIsReg("unpack-L/symlink", -1); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_Z_upper.c b/dependencies/libarchive-3.4.2/cpio/test/test_option_Z_upper.c new file mode 100644 index 0000000..ff38842 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_Z_upper.c @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 2003-2009 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_Z_upper) +{ + char *p; + int r; + size_t s; + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Archive it with compress compression. */ + r = systemf("echo f | %s -oZ >archive.out 2>archive.err", + testprog); + p = slurpfile(&s, "archive.err"); + p[s] = '\0'; + if (r != 0) { + if (strstr(p, "compression not available") != NULL) { + skipping("This version of bsdcpio was compiled " + "without compress support"); + free(p); + return; + } + failure("-Z option is broken"); + assertEqualInt(r, 0); + free(p); + return; + } + free(p); + /* Check that the archive file has a compress signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "\x1f\x9d", 2); + free(p); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_a.c b/dependencies/libarchive-3.4.2/cpio/test/test_option_a.c new file mode 100644 index 0000000..e96bdf3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_a.c @@ -0,0 +1,160 @@ +/*- + * Copyright (c) 2003-2008 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +#if defined(HAVE_UTIME_H) +#include +#elif defined(HAVE_SYS_UTIME_H) +#include +#endif +__FBSDID("$FreeBSD: src/usr.bin/cpio/test/test_option_a.c,v 1.3 2008/08/24 06:21:00 kientzle Exp $"); + +static struct { + const char *name; + time_t atime_sec; +} files[] = { + { "f0", 0 }, + { "f1", 0 }, + { "f2", 0 }, + { "f3", 0 }, + { "f4", 0 }, + { "f5", 0 } +}; + +/* + * Create a bunch of test files and record their atimes. + * For the atime preserve/change tests, the files must have + * atimes in the past. We can accomplish this by explicitly invoking + * utime() on platforms that support it or by simply sleeping + * for a second after creating the files. (Creating all of the files + * at once means we only need to sleep once.) + */ +static void +test_create(void) +{ + struct stat st; + struct utimbuf times; + static const int numfiles = sizeof(files) / sizeof(files[0]); + int i; + + for (i = 0; i < numfiles; ++i) { + /* + * Note: Have to write at least one byte to the file. + * cpio doesn't bother reading the file if it's zero length, + * so the atime never gets changed in that case, which + * makes the tests below rather pointless. + */ + assertMakeFile(files[i].name, 0644, "a"); + + /* If utime() isn't supported on your platform, just + * #ifdef this section out. Most of the test below is + * still valid. */ + memset(×, 0, sizeof(times)); +#if defined(_WIN32) && !defined(CYGWIN) + times.actime = 86400; + times.modtime = 86400; +#else + times.actime = 1; + times.modtime = 3; +#endif + assertEqualInt(0, utime(files[i].name, ×)); + + /* Record whatever atime the file ended up with. */ + /* If utime() is available, this should be 1, but there's + * no harm in being careful. */ + assertEqualInt(0, stat(files[i].name, &st)); + files[i].atime_sec = st.st_atime; + } + + /* Wait until the atime on the last file is actually in the past. */ + sleepUntilAfter(files[numfiles - 1].atime_sec); +} + +DEFINE_TEST(test_option_a) +{ + struct stat st; + int r; + char *p; + + /* Create all of the test files. */ + test_create(); + + /* Sanity check; verify that atimes really do get modified. */ + p = slurpfile(NULL, "f0"); + assert(p != NULL); + free(p); + assertEqualInt(0, stat("f0", &st)); + if (st.st_atime == files[0].atime_sec) { + skipping("Cannot verify -a option\n" + " Your system appears to not support atime."); + } + else + { + /* + * If this disk is mounted noatime, then we can't + * verify correct operation without -a. + */ + + /* Copy the file without -a; should change the atime. */ + r = systemf("echo %s | %s -pd copy-no-a > copy-no-a.out 2>copy-no-a.err", files[1].name, testprog); + assertEqualInt(r, 0); + assertTextFileContents("1 block\n", "copy-no-a.err"); + assertEmptyFile("copy-no-a.out"); + assertEqualInt(0, stat(files[1].name, &st)); + failure("Copying file without -a should have changed atime."); + assert(st.st_atime != files[1].atime_sec); + + /* Archive the file without -a; should change the atime. */ + r = systemf("echo %s | %s -o > archive-no-a.out 2>archive-no-a.err", files[2].name, testprog); + assertEqualInt(r, 0); + assertTextFileContents("1 block\n", "copy-no-a.err"); + assertEqualInt(0, stat(files[2].name, &st)); + failure("Archiving file without -a should have changed atime."); + assert(st.st_atime != files[2].atime_sec); + } + + /* + * We can, of course, still verify that the atime is unchanged + * when using the -a option. + */ + + /* Copy the file with -a; should not change the atime. */ + r = systemf("echo %s | %s -pad copy-a > copy-a.out 2>copy-a.err", + files[3].name, testprog); + assertEqualInt(r, 0); + assertTextFileContents("1 block\n", "copy-a.err"); + assertEmptyFile("copy-a.out"); + assertEqualInt(0, stat(files[3].name, &st)); + failure("Copying file with -a should not have changed atime."); + assertEqualInt(st.st_atime, files[3].atime_sec); + + /* Archive the file with -a; should not change the atime. */ + r = systemf("echo %s | %s -oa > archive-a.out 2>archive-a.err", + files[4].name, testprog); + assertEqualInt(r, 0); + assertTextFileContents("1 block\n", "copy-a.err"); + assertEqualInt(0, stat(files[4].name, &st)); + failure("Archiving file with -a should not have changed atime."); + assertEqualInt(st.st_atime, files[4].atime_sec); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_b64encode.c b/dependencies/libarchive-3.4.2/cpio/test/test_option_b64encode.c new file mode 100644 index 0000000..7c15a82 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_b64encode.c @@ -0,0 +1,56 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_b64encode) +{ + char *p; + size_t s; + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Archive it with compress compression and uuencode. */ + assertEqualInt(0, + systemf("echo f | %s -o -Z --b64encode >archive.out 2>archive.err", + testprog)); + /* Check that the archive file has an uuencode signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "begin-base64 644", 16); + free(p); + + /* Archive it with uuencode only. */ + assertEqualInt(0, + systemf("echo f | %s -o --b64encode >archive.out 2>archive.err", + testprog)); + /* Check that the archive file has an uuencode signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "begin-base64 644", 16); + free(p); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_c.c b/dependencies/libarchive-3.4.2/cpio/test/test_option_c.c new file mode 100644 index 0000000..013caed --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_c.c @@ -0,0 +1,229 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +static int +is_octal(const char *p, size_t l) +{ + while (l > 0) { + if (*p < '0' || *p > '7') + return (0); + --l; + ++p; + } + return (1); +} + +static int +from_octal(const char *p, size_t l) +{ + int r = 0; + + while (l > 0) { + r *= 8; + r += *p - '0'; + --l; + ++p; + } + return (r); +} + +#if !defined(_WIN32) || defined(__CYGWIN__) +static int +nlinks(const char *p) +{ + struct stat st; + assertEqualInt(0, stat(p, &st)); + return st.st_nlink; +} +#endif + +DEFINE_TEST(test_option_c) +{ + FILE *filelist; + int r; + int uid = 1000; + int dev, ino, gid = 1000; + time_t t, now; + char *p, *e; + size_t s; + + assertUmask(0); + + /* + * Create an assortment of files. + * TODO: Extend this to cover more filetypes. + */ + filelist = fopen("filelist", "w"); + + /* "file" */ + assertMakeFile("file", 0644, "1234567890"); + fprintf(filelist, "file\n"); + + /* "symlink" */ + if (canSymlink()) { + assertMakeSymlink("symlink", "file", 0); + fprintf(filelist, "symlink\n"); + } + + /* "dir" */ + assertMakeDir("dir", 0775); + /* Record some facts about what we just created: */ + now = time(NULL); /* They were all created w/in last two seconds. */ + fprintf(filelist, "dir\n"); + + /* Use the cpio program to create an archive. */ + fclose(filelist); + r = systemf("%s -R 1000:1000 -oc basic.out 2>basic.err", testprog); + /* Verify that nothing went to stderr. */ + assertTextFileContents("1 block\n", "basic.err"); + + /* Assert that the program finished. */ + failure("%s -oc crashed", testprog); + if (!assertEqualInt(r, 0)) + return; + + /* Verify that stdout is a well-formed cpio file in "odc" format. */ + p = slurpfile(&s, "basic.out"); + assertEqualInt(s, 512); + e = p; + + /* + * Some of these assertions could be stronger, but it's + * a little tricky because they depend on the local environment. + */ + + /* First entry is "file" */ + assert(is_octal(e, 76)); /* Entire header is octal digits. */ + assertEqualMem(e + 0, "070707", 6); /* Magic */ + assert(is_octal(e + 6, 6)); /* dev */ + dev = from_octal(e + 6, 6); + assert(is_octal(e + 12, 6)); /* ino */ + ino = from_octal(e + 12, 6); +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Group members bits and others bits do not work. */ + assertEqualMem(e + 18, "100666", 6); /* Mode */ +#else + assertEqualMem(e + 18, "100644", 6); /* Mode */ +#endif + if (uid < 0) + uid = from_octal(e + 24, 6); + assertEqualInt(from_octal(e + 24, 6), uid); /* uid */ + assert(is_octal(e + 30, 6)); /* gid */ + gid = from_octal(e + 30, 6); + assertEqualMem(e + 36, "000001", 6); /* nlink */ + failure("file entries should not have rdev set (dev field was 0%o)", + dev); + assertEqualMem(e + 42, "000000", 6); /* rdev */ + t = from_octal(e + 48, 11); /* mtime */ + assert(t <= now); /* File wasn't created in future. */ + assert(t >= now - 2); /* File was created w/in last 2 secs. */ + assertEqualMem(e + 59, "000005", 6); /* Name size */ + assertEqualMem(e + 65, "00000000012", 11); /* File size */ + assertEqualMem(e + 76, "file\0", 5); /* Name contents */ + assertEqualMem(e + 81, "1234567890", 10); /* File contents */ + e += 91; + + /* "symlink" pointing to "file" */ + if (canSymlink()) { + assert(is_octal(e, 76)); /* Entire header is octal digits. */ + assertEqualMem(e + 0, "070707", 6); /* Magic */ + assertEqualInt(dev, from_octal(e + 6, 6)); /* dev */ + assert(ino != from_octal(e + 12, 6)); /* ino */ +#if !defined(_WIN32) || defined(__CYGWIN__) + /* On Windows, symbolic link and group members bits and + * others bits do not work. */ + assertEqualMem(e + 18, "120777", 6); /* Mode */ +#endif + assertEqualInt(from_octal(e + 24, 6), uid); /* uid */ + assertEqualInt(gid, from_octal(e + 30, 6)); /* gid */ + assertEqualMem(e + 36, "000001", 6); /* nlink */ + failure("file entries should have rdev == 0 (dev was 0%o)", + from_octal(e + 6, 6)); + assertEqualMem(e + 42, "000000", 6); /* rdev */ + t = from_octal(e + 48, 11); /* mtime */ + assert(t <= now); /* File wasn't created in future. */ + assert(t >= now - 2); /* File was created w/in last 2 secs. */ + assertEqualMem(e + 59, "000010", 6); /* Name size */ + assertEqualMem(e + 65, "00000000004", 11); /* File size */ + assertEqualMem(e + 76, "symlink\0", 8); /* Name contents */ + assertEqualMem(e + 84, "file", 4); /* Symlink target. */ + e += 88; + } + + /* "dir" */ + assert(is_octal(e, 76)); + assertEqualMem(e + 0, "070707", 6); /* Magic */ + /* Dev should be same as first entry. */ + assert(is_octal(e + 6, 6)); /* dev */ + assertEqualInt(dev, from_octal(e + 6, 6)); + /* Ino must be different from first entry. */ + assert(is_octal(e + 12, 6)); /* ino */ + assert(ino != from_octal(e + 12, 6)); +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Group members bits and others bits do not work. */ + assertEqualMem(e + 18, "040777", 6); /* Mode */ +#else + /* Accept 042775 to accommodate systems where sgid bit propagates. */ + if (memcmp(e + 18, "042775", 6) != 0) + assertEqualMem(e + 18, "040775", 6); /* Mode */ +#endif + assertEqualInt(uid, from_octal(e + 24, 6)); /* uid */ + /* Gid should be same as first entry. */ + assert(is_octal(e + 30, 6)); /* gid */ + assertEqualInt(gid, from_octal(e + 30, 6)); + +#if !defined(_WIN32) || defined(__CYGWIN__) + assertEqualInt(nlinks("dir"), from_octal(e + 36, 6)); /* Nlink */ +#endif + + t = from_octal(e + 48, 11); /* mtime */ + assert(t <= now); /* File wasn't created in future. */ + assert(t >= now - 2); /* File was created w/in last 2 secs. */ + assertEqualMem(e + 59, "000004", 6); /* Name size */ + assertEqualMem(e + 65, "00000000000", 11); /* File size */ + assertEqualMem(e + 76, "dir\0", 4); /* name */ + e += 80; + + /* TODO: Verify other types of entries. */ + + /* Last entry is end-of-archive marker. */ + assert(is_octal(e, 76)); + assertEqualMem(e + 0, "070707", 6); /* Magic */ + assertEqualMem(e + 6, "000000", 6); /* dev */ + assertEqualMem(e + 12, "000000", 6); /* ino */ + assertEqualMem(e + 18, "000000", 6); /* Mode */ + assertEqualMem(e + 24, "000000", 6); /* uid */ + assertEqualMem(e + 30, "000000", 6); /* gid */ + assertEqualMem(e + 36, "000001", 6); /* Nlink */ + assertEqualMem(e + 42, "000000", 6); /* rdev */ + assertEqualMem(e + 48, "00000000000", 11); /* mtime */ + assertEqualMem(e + 59, "000013", 6); /* Name size */ + assertEqualMem(e + 65, "00000000000", 11); /* File size */ + assertEqualMem(e + 76, "TRAILER!!!\0", 11); /* Name */ + + free(p); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_d.c b/dependencies/libarchive-3.4.2/cpio/test/test_option_d.c new file mode 100644 index 0000000..9ff1453 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_d.c @@ -0,0 +1,64 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + + +DEFINE_TEST(test_option_d) +{ + int r; + + /* + * Create a file in a directory. + */ + assertMakeDir("dir", 0755); + assertMakeFile("dir/file", 0644, NULL); + + /* Create an archive. */ + r = systemf("echo dir/file | %s -o > archive.cpio 2>archive.err", testprog); + assertEqualInt(r, 0); + assertTextFileContents("1 block\n", "archive.err"); + assertFileSize("archive.cpio", 512); + + /* Dearchive without -d, this should fail. */ + assertMakeDir("without-d", 0755); + assertChdir("without-d"); + r = systemf("%s -i < ../archive.cpio >out 2>err", testprog); + assertEqualInt(r, 0); + assertEmptyFile("out"); + /* And the file should not be restored. */ + assertFileNotExists("dir/file"); + + /* Dearchive with -d, this should succeed. */ + assertChdir(".."); + assertMakeDir("with-d", 0755); + assertChdir("with-d"); + r = systemf("%s -id < ../archive.cpio >out 2>err", testprog); + assertEqualInt(r, 0); + assertEmptyFile("out"); + assertTextFileContents("1 block\n", "err"); + /* And the file should be restored. */ + assertFileExists("dir/file"); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_f.c b/dependencies/libarchive-3.4.2/cpio/test/test_option_f.c new file mode 100644 index 0000000..784e085 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_f.c @@ -0,0 +1,76 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * Unpack the archive in a new dir. + */ +static void +unpack(const char *dirname, const char *option) +{ + int r; + + assertMakeDir(dirname, 0755); + assertChdir(dirname); + extract_reference_file("test_option_f.cpio"); + r = systemf("%s -i %s < test_option_f.cpio > copy-no-a.out 2>copy-no-a.err", testprog, option); + assertEqualInt(0, r); + assertChdir(".."); +} + +DEFINE_TEST(test_option_f) +{ + /* Calibrate: No -f option, so everything should be extracted. */ + unpack("t0", "--no-preserve-owner"); + assertFileExists("t0/a123"); + assertFileExists("t0/a234"); + assertFileExists("t0/b123"); + assertFileExists("t0/b234"); + + /* Don't extract 'a*' files. */ +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Single quotes isn't used by command.exe. */ + unpack("t1", "--no-preserve-owner -f a*"); +#else + unpack("t1", "--no-preserve-owner -f 'a*'"); +#endif + assertFileNotExists("t1/a123"); + assertFileNotExists("t1/a234"); + assertFileExists("t1/b123"); + assertFileExists("t1/b234"); + + /* Don't extract 'b*' files. */ +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Single quotes isn't used by command.exe. */ + unpack("t2", "--no-preserve-owner -f b*"); +#else + unpack("t2", "--no-preserve-owner -f 'b*'"); +#endif + assertFileExists("t2/a123"); + assertFileExists("t2/a234"); + assertFileNotExists("t2/b123"); + assertFileNotExists("t2/b234"); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_f.cpio.uu b/dependencies/libarchive-3.4.2/cpio/test/test_option_f.cpio.uu new file mode 100644 index 0000000..42c63c3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_f.cpio.uu @@ -0,0 +1,16 @@ +$FreeBSD$ +begin 644 test_option_f.cpio +M,#archive.out 2>archive.err", + testprog)); + p = slurpfile(&s, "archive.err"); + free(p); + /* Check that the archive file has an grzip signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "GRZipII\x00\x02\x04:)", 12); + free(p); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_help.c b/dependencies/libarchive-3.4.2/cpio/test/test_option_help.c new file mode 100644 index 0000000..5623430 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_help.c @@ -0,0 +1,84 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * Test that "--help", "-h", and "-W help" options all work and + * generate reasonable output. + */ + +static int +in_first_line(const char *p, const char *substring) +{ + size_t l = strlen(substring); + + while (*p != '\0' && *p != '\n') { + if (memcmp(p, substring, l) == 0) + return (1); + ++p; + } + return (0); +} + +DEFINE_TEST(test_option_help) +{ + int r; + char *p; + size_t plen; + + /* Exercise --help option. */ + r = systemf("%s --help >help.stdout 2>help.stderr", testprog); + assertEqualInt(r, 0); + failure("--help should generate nothing to stderr."); + assertEmptyFile("help.stderr"); + /* Help message should start with name of program. */ + p = slurpfile(&plen, "help.stdout"); + failure("Help output should be long enough."); + assert(plen >= 7); + failure("First line of help output should contain string 'bsdcpio'"); + assert(in_first_line(p, "bsdcpio")); + /* + * TODO: Extend this check to further verify that --help output + * looks approximately right. + */ + free(p); + + /* -h option should generate the same output. */ + r = systemf("%s -h >h.stdout 2>h.stderr", testprog); + assertEqualInt(r, 0); + failure("-h should generate nothing to stderr."); + assertEmptyFile("h.stderr"); + failure("stdout should be same for -h and --help"); + assertEqualFile("h.stdout", "help.stdout"); + + /* -W help should be another synonym. */ + r = systemf("%s -W help >Whelp.stdout 2>Whelp.stderr", testprog); + assertEqualInt(r, 0); + failure("-W help should generate nothing to stderr."); + assertEmptyFile("Whelp.stderr"); + failure("stdout should be same for -W help and --help"); + assertEqualFile("Whelp.stdout", "help.stdout"); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_l.c b/dependencies/libarchive-3.4.2/cpio/test/test_option_l.c new file mode 100644 index 0000000..5c76e68 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_l.c @@ -0,0 +1,50 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_l) +{ + int r; + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Copy the file to the "copy" dir. */ + r = systemf("echo f | %s -pd copy >copy.out 2>copy.err", + testprog); + assertEqualInt(r, 0); + + /* Check that the copy is a true copy and not a link. */ + assertIsNotHardlink("f", "copy/f"); + + /* Copy the file to the "link" dir with the -l option. */ + r = systemf("echo f | %s -pld link >link.out 2>link.err", + testprog); + assertEqualInt(r, 0); + + /* Check that this is a link and not a copy. */ + assertIsHardlink("f", "link/f"); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_lrzip.c b/dependencies/libarchive-3.4.2/cpio/test/test_option_lrzip.c new file mode 100644 index 0000000..8d9c0d5 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_lrzip.c @@ -0,0 +1,53 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_lrzip) +{ + char *p; + size_t s; + + if (!canLrzip()) { + skipping("lrzip is not supported on this platform"); + return; + } + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Archive it with lrzip compression. */ + assertEqualInt(0, + systemf("echo f | %s -o --lrzip >archive.out 2>archive.err", + testprog)); + p = slurpfile(&s, "archive.err"); + free(p); + /* Check that the archive file has an lzma signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "LRZI\x00", 5); + free(p); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_lz4.c b/dependencies/libarchive-3.4.2/cpio/test/test_option_lz4.c new file mode 100644 index 0000000..ebd3767 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_lz4.c @@ -0,0 +1,88 @@ +/*- + * Copyright (c) 2014 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_lz4) +{ + char *p; + int r; + size_t s; + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Archive it with lz4 compression. */ + r = systemf("echo f | %s -o --lz4 >archive.out 2>archive.err", + testprog); + p = slurpfile(&s, "archive.err"); + p[s] = '\0'; + if (r != 0) { + if (strstr(p, "compression not available") != NULL) { + skipping("This version of bsdcpio was compiled " + "without lz4 support"); + free(p); + return; + } + /* POSIX permits different handling of the spawnp + * system call used to launch the subsidiary + * program: */ + /* Some systems fail immediately to spawn the new process. */ + if (strstr(p, "Can't launch") != NULL && !canLz4()) { + skipping("This version of bsdcpio uses an external lz4 program " + "but no such program is available on this system."); + free(p); + return; + } + /* Some systems successfully spawn the new process, + * but fail to exec a program within that process. + * This results in failure at the first attempt to + * write. */ + if (strstr(p, "Can't write") != NULL && !canLz4()) { + skipping("This version of bsdcpio uses an external lz4 program " + "but no such program is available on this system."); + free(p); + return; + } + /* On some systems the error won't be detected until closing + time, by a 127 exit error returned by waitpid. */ + if (strstr(p, "Error closing") != NULL && !canLz4()) { + skipping("This version of bsdcpio uses an external lz4 program " + "but no such program is available on this system."); + free(p); + return; + } + failure("--lz4 option is broken: %s", p); + free(p); + assertEqualInt(r, 0); + return; + } + free(p); + /* Check that the archive file has an lz4 signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "\x04\x22\x4d\x18", 4); + free(p); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_lzma.c b/dependencies/libarchive-3.4.2/cpio/test/test_option_lzma.c new file mode 100644 index 0000000..b7cad3d --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_lzma.c @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_lzma) +{ + char *p; + int r; + size_t s; + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Archive it with lzma compression. */ + r = systemf("echo f | %s -o --lzma >archive.out 2>archive.err", + testprog); + p = slurpfile(&s, "archive.err"); + p[s] = '\0'; + if (r != 0) { + if (strstr(p, "compression not available") != NULL) { + skipping("This version of bsdcpio was compiled " + "without lzma support"); + free(p); + return; + } + failure("--lzma option is broken"); + assertEqualInt(r, 0); + free(p); + return; + } + free(p); + /* Check that the archive file has an lzma signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "\x5d\00\00", 3); + free(p); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_lzop.c b/dependencies/libarchive-3.4.2/cpio/test/test_option_lzop.c new file mode 100644 index 0000000..aa40ef5 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_lzop.c @@ -0,0 +1,57 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_lzop) +{ + char *p; + int r; + size_t s; + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Archive it with lzop compression. */ + r = systemf("echo f | %s -o --lzop >archive.out 2>archive.err", + testprog); + p = slurpfile(&s, "archive.err"); + free(p); + if (r != 0) { + if (!canLzop()) { + skipping("lzop is not supported on this platform"); + return; + } + failure("--lzop option is broken"); + assertEqualInt(r, 0); + return; + } + /* Check that the archive file has an lzma signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a", 9); + free(p); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_m.c b/dependencies/libarchive-3.4.2/cpio/test/test_option_m.c new file mode 100644 index 0000000..de880b2 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_m.c @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + + +DEFINE_TEST(test_option_m) +{ + int r; + + /* + * The reference archive has one file with an mtime in 1970, 1 + * second after the start of the epoch. + */ + + /* Restored without -m, the result should have a current mtime. */ + assertMakeDir("without-m", 0755); + assertChdir("without-m"); + extract_reference_file("test_option_m.cpio"); + r = systemf("%s --no-preserve-owner -i < test_option_m.cpio >out 2>err", testprog); + assertEqualInt(r, 0); + assertEmptyFile("out"); + assertTextFileContents("1 block\n", "err"); + /* Should have been created within the last few seconds. */ + assertFileMtimeRecent("file"); + + /* With -m, it should have an mtime in 1970. */ + assertChdir(".."); + assertMakeDir("with-m", 0755); + assertChdir("with-m"); + extract_reference_file("test_option_m.cpio"); + r = systemf("%s --no-preserve-owner -im < test_option_m.cpio >out 2>err", testprog); + assertEqualInt(r, 0); + assertEmptyFile("out"); + assertTextFileContents("1 block\n", "err"); + /* + * mtime in reference archive is '1' == 1 second after + * midnight Jan 1, 1970 UTC. + */ + assertFileMtime("file", 1, 0); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_m.cpio.uu b/dependencies/libarchive-3.4.2/cpio/test/test_option_m.cpio.uu new file mode 100644 index 0000000..3d20023 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_m.cpio.uu @@ -0,0 +1,16 @@ +$FreeBSD$ +begin 644 test_option_m.cpio +M,#test.out 2>test.err", + testprog, reffile)); + + assertFileExists("file1"); + assertTextFileContents("contents of file1.\n", "file1"); + assertFileExists("file2"); + assertTextFileContents("contents of file2.\n", "file2"); + assertEmptyFile("test.out"); + assertTextFileContents("1 block\n", "test.err"); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_passphrase.zip.uu b/dependencies/libarchive-3.4.2/cpio/test/test_option_passphrase.zip.uu new file mode 100644 index 0000000..021ae85 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_passphrase.zip.uu @@ -0,0 +1,12 @@ +begin 644 test_option_passphrase.zip +M4$L#!`H`"0```#B91$7D$C4,'P```!,````%`!P`9FEL93%55`D``VS'+U0" +MQR]4=7@+``$$]0$```04````BHPD*"^*I04=XKI\_FQ*TE+#),TD7TTKSP/7 +MR6R35%!+!PCD$C4,'P```!,```!02P,$"@`)````09E$1;VL<`L``03U`0``!!0```!D#6Z\@CI8 +MV1GIJO5TISQF^I:7.;Y3<-G3$YOCL(C_4$L'"+VL +M`PH`"0```#B91$7D$C4,'P```!,````%`!@```````$```"D@0````!F:6QE +M,554!0`#;,`PH`"0```$&91$6]K',. +M'P```!,````%`!@```````$```"D@6X```!F:6QE,E54!0`#>< +#endif + +DEFINE_TEST(test_option_t) +{ + char *p; + int r; + time_t mtime; + char date[32]; + char date2[32]; + + /* List reference archive, make sure the TOC is correct. */ + extract_reference_file("test_option_t.cpio"); + r = systemf("%s -it < test_option_t.cpio >it.out 2>it.err", testprog); + assertEqualInt(r, 0); + assertTextFileContents("1 block\n", "it.err"); + extract_reference_file("test_option_t.stdout"); + p = slurpfile(NULL, "test_option_t.stdout"); + assertTextFileContents(p, "it.out"); + free(p); + + /* We accept plain "-t" as a synonym for "-it" */ + r = systemf("%s -t < test_option_t.cpio >t.out 2>t.err", testprog); + assertEqualInt(r, 0); + assertTextFileContents("1 block\n", "t.err"); + extract_reference_file("test_option_t.stdout"); + p = slurpfile(NULL, "test_option_t.stdout"); + assertTextFileContents(p, "t.out"); + free(p); + + /* But "-ot" is an error. */ + assert(0 != systemf("%s -ot < test_option_t.cpio >ot.out 2>ot.err", + testprog)); + assertEmptyFile("ot.out"); + + /* List reference archive verbosely, make sure the TOC is correct. */ + r = systemf("%s -itv < test_option_t.cpio >tv.out 2>tv.err", testprog); + assertEqualInt(r, 0); + assertTextFileContents("1 block\n", "tv.err"); + extract_reference_file("test_option_tv.stdout"); + + /* This doesn't work because the usernames on different systems + * are different and cpio now looks up numeric UIDs on + * the local system. */ + /* assertEqualFile("tv.out", "test_option_tv.stdout"); */ + + /* List reference archive with numeric IDs, verify TOC is correct. */ + r = systemf("%s -itnv < test_option_t.cpio >itnv.out 2>itnv.err", + testprog); + assertEqualInt(r, 0); + assertTextFileContents("1 block\n", "itnv.err"); + p = slurpfile(NULL, "itnv.out"); + /* Since -n uses numeric UID/GID, this part should be the + * same on every system. */ + assertEqualMem(p, "-rw-r--r-- 1 1000 1000 0 ",42); + + /* Date varies depending on local timezone and locale. */ + mtime = 1; +#ifdef HAVE_LOCALE_H + setlocale(LC_ALL, ""); +#endif +#if defined(_WIN32) && !defined(__CYGWIN__) + strftime(date2, sizeof(date2)-1, "%b %d %Y", localtime(&mtime)); + _snprintf(date, sizeof(date)-1, "%12.12s file", date2); +#else + strftime(date2, sizeof(date2)-1, "%b %e %Y", localtime(&mtime)); + snprintf(date, sizeof(date)-1, "%12.12s file", date2); +#endif + assertEqualMem(p + 42, date, strlen(date)); + free(p); + + /* But "-n" without "-t" is an error. */ + assert(0 != systemf("%s -in < test_option_t.cpio >in.out 2>in.err", + testprog)); + assertEmptyFile("in.out"); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_t.cpio.uu b/dependencies/libarchive-3.4.2/cpio/test/test_option_t.cpio.uu new file mode 100644 index 0000000..055fe74 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_t.cpio.uu @@ -0,0 +1,16 @@ +$FreeBSD$ +begin 644 test_option_t.cpio +M,# +#elif defined(HAVE_SYS_UTIME_H) +#include +#endif +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_u) +{ + struct utimbuf times; + char *p; + size_t s; + int r; + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Copy the file to the "copy" dir. */ + r = systemf("echo f| %s -pd copy >copy.out 2>copy.err", + testprog); + assertEqualInt(r, 0); + + /* Check that the file contains only a single "a" */ + p = slurpfile(&s, "copy/f"); + assertEqualInt(s, 1); + assertEqualMem(p, "a", 1); + free(p); + + /* Recreate the file with a single "b" */ + assertMakeFile("f", 0644, "b"); + + /* Set the mtime to the distant past. */ + memset(×, 0, sizeof(times)); + times.actime = 1; + times.modtime = 3; + assertEqualInt(0, utime("f", ×)); + + /* Copy the file to the "copy" dir. */ + r = systemf("echo f| %s -pd copy >copy.out 2>copy.err", + testprog); + assertEqualInt(r, 0); + + /* Verify that the file hasn't changed (it wasn't overwritten) */ + p = slurpfile(&s, "copy/f"); + assertEqualInt(s, 1); + assertEqualMem(p, "a", 1); + free(p); + + /* Copy the file to the "copy" dir with -u (force) */ + r = systemf("echo f| %s -pud copy >copy.out 2>copy.err", + testprog); + assertEqualInt(r, 0); + + /* Verify that the file has changed (it was overwritten) */ + p = slurpfile(&s, "copy/f"); + assertEqualInt(s, 1); + assertEqualMem(p, "b", 1); + free(p); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_uuencode.c b/dependencies/libarchive-3.4.2/cpio/test/test_option_uuencode.c new file mode 100644 index 0000000..a42a0e0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_uuencode.c @@ -0,0 +1,56 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_uuencode) +{ + char *p; + size_t s; + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Archive it with compress compression and uuencode. */ + assertEqualInt(0, + systemf("echo f | %s -o -Z --uuencode >archive.out 2>archive.err", + testprog)); + /* Check that the archive file has an uuencode signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "begin 644", 9); + free(p); + + /* Archive it with uuencode only. */ + assertEqualInt(0, + systemf("echo f | %s -o --uuencode >archive.out 2>archive.err", + testprog)); + /* Check that the archive file has an uuencode signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "begin 644", 9); + free(p); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_version.c b/dependencies/libarchive-3.4.2/cpio/test/test_option_version.c new file mode 100644 index 0000000..505db27 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_version.c @@ -0,0 +1,30 @@ +/*- + * Copyright (c) 2003-2017 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_option_version) +{ + assertVersion(testprog, "bsdcpio"); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_xz.c b/dependencies/libarchive-3.4.2/cpio/test/test_option_xz.c new file mode 100644 index 0000000..f0d3b33 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_xz.c @@ -0,0 +1,61 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_xz) +{ + char *p; + int r; + size_t s; + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Archive it with xz compression. */ + r = systemf("echo f | %s -o --xz >archive.out 2>archive.err", + testprog); + p = slurpfile(&s, "archive.err"); + p[s] = '\0'; + if (r != 0) { + if (strstr(p, "compression not available") != NULL) { + skipping("This version of bsdcpio was compiled " + "without xz support"); + free(p); + return; + } + free(p); + failure("--xz option is broken"); + assertEqualInt(r, 0); + return; + } + free(p); + /* Check that the archive file has an xz signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "\xFD\x37\x7A\x58\x5A\x00", 6); + free(p); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_y.c b/dependencies/libarchive-3.4.2/cpio/test/test_option_y.c new file mode 100644 index 0000000..989b5f1 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_y.c @@ -0,0 +1,57 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/usr.bin/cpio/test/test_option_y.c,v 1.2 2008/08/24 06:21:00 kientzle Exp $"); + +DEFINE_TEST(test_option_y) +{ + char *p; + int r; + size_t s; + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Archive it with bzip2 compression. */ + r = systemf("echo f | %s -oy >archive.out 2>archive.err", + testprog); + p = slurpfile(&s, "archive.err"); + free(p); + if (r != 0) { + if (!canBzip2()) { + skipping("bzip2 is not supported on this platform"); + return; + } + failure("-y option is broken"); + assertEqualInt(r, 0); + return; + } + assertTextFileContents("1 block\n", "archive.err"); + /* Check that the archive file has a bzip2 signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "BZh9", 4); + free(p); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_z.c b/dependencies/libarchive-3.4.2/cpio/test/test_option_z.c new file mode 100644 index 0000000..803232d --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_z.c @@ -0,0 +1,56 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_z) +{ + char *p; + int r; + size_t s; + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Archive it with gzip compression. */ + r = systemf("echo f | %s -oz >archive.out 2>archive.err", + testprog); + p = slurpfile(&s, "archive.err"); + free(p); + if (r != 0) { + if (!canGzip()) { + skipping("gzip is not supported on this platform"); + return; + } + failure("-z option is broken"); + assertEqualInt(r, 0); + return; + } + /* Check that the archive file has a gzip signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 4); + assertEqualMem(p, "\x1f\x8b\x08\x00", 4); + free(p); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_option_zstd.c b/dependencies/libarchive-3.4.2/cpio/test/test_option_zstd.c new file mode 100644 index 0000000..29b8c78 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_option_zstd.c @@ -0,0 +1,85 @@ +/*- + * Copyright (c) 2017 Sean Purcell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_zstd) +{ + char *p; + int r; + size_t s; + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Archive it with zstd compression. */ + r = systemf("echo f | %s -o --zstd >archive.out 2>archive.err", + testprog); + p = slurpfile(&s, "archive.err"); + p[s] = '\0'; + if (r != 0) { + if (strstr(p, "Unsupported compression") != NULL) { + skipping("This version of bsdcpio was compiled " + "without zstd support"); + goto done; + } + /* POSIX permits different handling of the spawnp + * system call used to launch the subsidiary + * program: */ + /* Some systems fail immediately to spawn the new process. */ + if (strstr(p, "Can't launch") != NULL && !canZstd()) { + skipping("This version of bsdcpio uses an external zstd program " + "but no such program is available on this system."); + goto done; + } + /* Some systems successfully spawn the new process, + * but fail to exec a program within that process. + * This results in failure at the first attempt to + * write. */ + if (strstr(p, "Can't write") != NULL && !canZstd()) { + skipping("This version of bsdcpio uses an external zstd program " + "but no such program is available on this system."); + goto done; + } + /* On some systems the error won't be detected until closing + time, by a 127 exit error returned by waitpid. */ + if (strstr(p, "Error closing") != NULL && !canZstd()) { + skipping("This version of bsdcpio uses an external zstd program " + "but no such program is available on this system."); + return; + } + failure("--zstd option is broken: %s", p); + assertEqualInt(r, 0); + goto done; + } + free(p); + /* Check that the archive file has an zstd signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "\x28\xb5\x2f\xfd", 4); + +done: + free(p); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_owner_parse.c b/dependencies/libarchive-3.4.2/cpio/test/test_owner_parse.c new file mode 100644 index 0000000..bef02da --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_owner_parse.c @@ -0,0 +1,121 @@ +/*- + * Copyright (c) 2003-2009 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +#include "../cpio.h" +#include "err.h" + +#if !defined(_WIN32) +#define ROOT "root" +static const int root_uids[] = { 0 }; +static const int root_gids[] = { 0, 1 }; +#elif defined(__CYGWIN__) +/* On cygwin, the Administrator user most likely exists (unless + * it has been renamed or is in a non-English localization), but + * its primary group membership depends on how the user set up + * their /etc/passwd. Likely values are 513 (None), 545 (Users), + * or 544 (Administrators). Just check for one of those... + * TODO: Handle non-English localizations... e.g. French 'Administrateur' + * Use CreateWellKnownSID() and LookupAccountName()? + */ +#define ROOT "Administrator" +static const int root_uids[] = { 500 }; +static const int root_gids[] = { 513, 545, 544 }; +#endif + +#if defined(ROOT) +static int +int_in_list(int i, const int *l, size_t n) +{ + while (n-- > 0) + if (*l++ == i) + return (1); + failure("%d", i); + return (0); +} +#endif + +DEFINE_TEST(test_owner_parse) +{ +#if !defined(ROOT) + skipping("No uid/gid configuration for this OS"); +#else + int uid, gid; + + assert(NULL == owner_parse(ROOT, &uid, &gid)); + assert(int_in_list(uid, root_uids, + sizeof(root_uids)/sizeof(root_uids[0]))); + assertEqualInt(-1, gid); + + + assert(NULL == owner_parse(ROOT ":", &uid, &gid)); + assert(int_in_list(uid, root_uids, + sizeof(root_uids)/sizeof(root_uids[0]))); + assert(int_in_list(gid, root_gids, + sizeof(root_gids)/sizeof(root_gids[0]))); + + assert(NULL == owner_parse(ROOT ".", &uid, &gid)); + assert(int_in_list(uid, root_uids, + sizeof(root_uids)/sizeof(root_uids[0]))); + assert(int_in_list(gid, root_gids, + sizeof(root_gids)/sizeof(root_gids[0]))); + + assert(NULL == owner_parse("111", &uid, &gid)); + assertEqualInt(111, uid); + assertEqualInt(-1, gid); + + assert(NULL == owner_parse("112:", &uid, &gid)); + assertEqualInt(112, uid); + /* Can't assert gid, since we don't know gid for user #112. */ + + assert(NULL == owner_parse("113.", &uid, &gid)); + assertEqualInt(113, uid); + /* Can't assert gid, since we don't know gid for user #113. */ + + assert(NULL == owner_parse(":114", &uid, &gid)); + assertEqualInt(-1, uid); + assertEqualInt(114, gid); + + assert(NULL == owner_parse(".115", &uid, &gid)); + assertEqualInt(-1, uid); + assertEqualInt(115, gid); + + assert(NULL == owner_parse("116:117", &uid, &gid)); + assertEqualInt(116, uid); + assertEqualInt(117, gid); + + /* + * TODO: Lookup current user/group name, build strings and + * use those to verify username/groupname lookups for ordinary + * users. + */ + + assert(NULL != owner_parse(":nonexistentgroup", &uid, &gid)); + assert(NULL != owner_parse(ROOT ":nonexistentgroup", &uid, &gid)); + assert(NULL != + owner_parse("nonexistentuser:nonexistentgroup", &uid, &gid)); +#endif +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_passthrough_dotdot.c b/dependencies/libarchive-3.4.2/cpio/test/test_passthrough_dotdot.c new file mode 100644 index 0000000..bb04341 --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_passthrough_dotdot.c @@ -0,0 +1,76 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/usr.bin/cpio/test/test_passthrough_dotdot.c,v 1.4 2008/08/24 06:21:00 kientzle Exp $"); + +/* + * Verify that "cpio -p .." works. + */ + +DEFINE_TEST(test_passthrough_dotdot) +{ + int r; + FILE *filelist; + + assertUmask(0); + + /* + * Create an assortment of files on disk. + */ + filelist = fopen("filelist", "w"); + + /* Directory. */ + assertMakeDir("dir", 0755); + assertChdir("dir"); + + fprintf(filelist, ".\n"); + + /* File with 10 bytes content. */ + assertMakeFile("file", 0642, "1234567890"); + fprintf(filelist, "file\n"); + + /* All done. */ + fclose(filelist); + + + /* + * Use cpio passthrough mode to copy files to another directory. + */ + r = systemf("%s -pdvm .. <../filelist >../stdout 2>../stderr", + testprog); + failure("Error invoking %s -pd ..", testprog); + assertEqualInt(r, 0); + + assertChdir(".."); + + /* Verify stderr and stdout. */ + assertTextFileContents("../.\n../file\n1 block\n", "stderr"); + assertEmptyFile("stdout"); + + /* Regular file. */ + assertIsReg("file", 0642); + assertFileSize("file", 10); + assertFileNLinks("file", 1); +} diff --git a/dependencies/libarchive-3.4.2/cpio/test/test_passthrough_reverse.c b/dependencies/libarchive-3.4.2/cpio/test/test_passthrough_reverse.c new file mode 100644 index 0000000..674e52b --- /dev/null +++ b/dependencies/libarchive-3.4.2/cpio/test/test_passthrough_reverse.c @@ -0,0 +1,85 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/usr.bin/cpio/test/test_passthrough_reverse.c,v 1.2 2008/08/24 06:21:00 kientzle Exp $"); + +/* + * As reported by Bernd Walter: Some people are in the habit of + * using "find -d" to generate a list for cpio -p because that + * copies the top-level dir last, which preserves owner and mode + * information. That's not necessary for bsdcpio (libarchive defers + * restoring directory information), but bsdcpio should still generate + * the correct results with this usage. + */ + +DEFINE_TEST(test_passthrough_reverse) +{ + int r; + FILE *filelist; + + assertUmask(0); + + /* + * Create an assortment of files on disk. + */ + filelist = fopen("filelist", "w"); + + /* Directory. */ + assertMakeDir("dir", 0743); + + /* File with 10 bytes content. */ + assertMakeFile("dir/file", 0644, "1234567890"); + fprintf(filelist, "dir/file\n"); + + /* Write dir last. */ + fprintf(filelist, "dir\n"); + + /* All done. */ + fclose(filelist); + + + /* + * Use cpio passthrough mode to copy files to another directory. + */ + r = systemf("%s -pdvm out stdout 2>stderr", testprog); + failure("Error invoking %s -pd out", testprog); + assertEqualInt(r, 0); + + assertChdir("out"); + + /* Verify stderr and stdout. */ + assertTextFileContents("out/dir/file\nout/dir\n1 block\n", + "../stderr"); + assertEmptyFile("../stdout"); + + /* dir */ + assertIsDir("dir", 0743); + + + /* Regular file. */ + assertIsReg("dir/file", 0644); + assertFileSize("dir/file", 10); + assertFileNLinks("dir/file", 1); +} diff --git a/dependencies/libarchive-3.4.2/doc/html/.ignore_me b/dependencies/libarchive-3.4.2/doc/html/.ignore_me new file mode 100644 index 0000000..d285484 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/.ignore_me @@ -0,0 +1,2 @@ +*** PLEASE DO NOT DELETE THIS FILE! *** +This file is used to track an otherwise empty directory in git. diff --git a/dependencies/libarchive-3.4.2/doc/html/Makefile b/dependencies/libarchive-3.4.2/doc/html/Makefile new file mode 100644 index 0000000..d15a786 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/Makefile @@ -0,0 +1,133 @@ + +default: all + + +archive_entry.3.html: ../../libarchive/archive_entry.3 + groff -mdoc -T html ../../libarchive/archive_entry.3 > archive_entry.3.html + +archive_entry_acl.3.html: ../../libarchive/archive_entry_acl.3 + groff -mdoc -T html ../../libarchive/archive_entry_acl.3 > archive_entry_acl.3.html + +archive_entry_linkify.3.html: ../../libarchive/archive_entry_linkify.3 + groff -mdoc -T html ../../libarchive/archive_entry_linkify.3 > archive_entry_linkify.3.html + +archive_entry_misc.3.html: ../../libarchive/archive_entry_misc.3 + groff -mdoc -T html ../../libarchive/archive_entry_misc.3 > archive_entry_misc.3.html + +archive_entry_paths.3.html: ../../libarchive/archive_entry_paths.3 + groff -mdoc -T html ../../libarchive/archive_entry_paths.3 > archive_entry_paths.3.html + +archive_entry_perms.3.html: ../../libarchive/archive_entry_perms.3 + groff -mdoc -T html ../../libarchive/archive_entry_perms.3 > archive_entry_perms.3.html + +archive_entry_stat.3.html: ../../libarchive/archive_entry_stat.3 + groff -mdoc -T html ../../libarchive/archive_entry_stat.3 > archive_entry_stat.3.html + +archive_entry_time.3.html: ../../libarchive/archive_entry_time.3 + groff -mdoc -T html ../../libarchive/archive_entry_time.3 > archive_entry_time.3.html + +archive_read.3.html: ../../libarchive/archive_read.3 + groff -mdoc -T html ../../libarchive/archive_read.3 > archive_read.3.html + +archive_read_add_passphrase.3.html: ../../libarchive/archive_read_add_passphrase.3 + groff -mdoc -T html ../../libarchive/archive_read_add_passphrase.3 > archive_read_add_passphrase.3.html + +archive_read_data.3.html: ../../libarchive/archive_read_data.3 + groff -mdoc -T html ../../libarchive/archive_read_data.3 > archive_read_data.3.html + +archive_read_disk.3.html: ../../libarchive/archive_read_disk.3 + groff -mdoc -T html ../../libarchive/archive_read_disk.3 > archive_read_disk.3.html + +archive_read_extract.3.html: ../../libarchive/archive_read_extract.3 + groff -mdoc -T html ../../libarchive/archive_read_extract.3 > archive_read_extract.3.html + +archive_read_filter.3.html: ../../libarchive/archive_read_filter.3 + groff -mdoc -T html ../../libarchive/archive_read_filter.3 > archive_read_filter.3.html + +archive_read_format.3.html: ../../libarchive/archive_read_format.3 + groff -mdoc -T html ../../libarchive/archive_read_format.3 > archive_read_format.3.html + +archive_read_free.3.html: ../../libarchive/archive_read_free.3 + groff -mdoc -T html ../../libarchive/archive_read_free.3 > archive_read_free.3.html + +archive_read_header.3.html: ../../libarchive/archive_read_header.3 + groff -mdoc -T html ../../libarchive/archive_read_header.3 > archive_read_header.3.html + +archive_read_new.3.html: ../../libarchive/archive_read_new.3 + groff -mdoc -T html ../../libarchive/archive_read_new.3 > archive_read_new.3.html + +archive_read_open.3.html: ../../libarchive/archive_read_open.3 + groff -mdoc -T html ../../libarchive/archive_read_open.3 > archive_read_open.3.html + +archive_read_set_options.3.html: ../../libarchive/archive_read_set_options.3 + groff -mdoc -T html ../../libarchive/archive_read_set_options.3 > archive_read_set_options.3.html + +archive_util.3.html: ../../libarchive/archive_util.3 + groff -mdoc -T html ../../libarchive/archive_util.3 > archive_util.3.html + +archive_write.3.html: ../../libarchive/archive_write.3 + groff -mdoc -T html ../../libarchive/archive_write.3 > archive_write.3.html + +archive_write_blocksize.3.html: ../../libarchive/archive_write_blocksize.3 + groff -mdoc -T html ../../libarchive/archive_write_blocksize.3 > archive_write_blocksize.3.html + +archive_write_data.3.html: ../../libarchive/archive_write_data.3 + groff -mdoc -T html ../../libarchive/archive_write_data.3 > archive_write_data.3.html + +archive_write_disk.3.html: ../../libarchive/archive_write_disk.3 + groff -mdoc -T html ../../libarchive/archive_write_disk.3 > archive_write_disk.3.html + +archive_write_filter.3.html: ../../libarchive/archive_write_filter.3 + groff -mdoc -T html ../../libarchive/archive_write_filter.3 > archive_write_filter.3.html + +archive_write_finish_entry.3.html: ../../libarchive/archive_write_finish_entry.3 + groff -mdoc -T html ../../libarchive/archive_write_finish_entry.3 > archive_write_finish_entry.3.html + +archive_write_format.3.html: ../../libarchive/archive_write_format.3 + groff -mdoc -T html ../../libarchive/archive_write_format.3 > archive_write_format.3.html + +archive_write_free.3.html: ../../libarchive/archive_write_free.3 + groff -mdoc -T html ../../libarchive/archive_write_free.3 > archive_write_free.3.html + +archive_write_header.3.html: ../../libarchive/archive_write_header.3 + groff -mdoc -T html ../../libarchive/archive_write_header.3 > archive_write_header.3.html + +archive_write_new.3.html: ../../libarchive/archive_write_new.3 + groff -mdoc -T html ../../libarchive/archive_write_new.3 > archive_write_new.3.html + +archive_write_open.3.html: ../../libarchive/archive_write_open.3 + groff -mdoc -T html ../../libarchive/archive_write_open.3 > archive_write_open.3.html + +archive_write_set_options.3.html: ../../libarchive/archive_write_set_options.3 + groff -mdoc -T html ../../libarchive/archive_write_set_options.3 > archive_write_set_options.3.html + +archive_write_set_passphrase.3.html: ../../libarchive/archive_write_set_passphrase.3 + groff -mdoc -T html ../../libarchive/archive_write_set_passphrase.3 > archive_write_set_passphrase.3.html + +cpio.5.html: ../../libarchive/cpio.5 + groff -mdoc -T html ../../libarchive/cpio.5 > cpio.5.html + +libarchive-formats.5.html: ../../libarchive/libarchive-formats.5 + groff -mdoc -T html ../../libarchive/libarchive-formats.5 > libarchive-formats.5.html + +libarchive.3.html: ../../libarchive/libarchive.3 + groff -mdoc -T html ../../libarchive/libarchive.3 > libarchive.3.html + +libarchive_changes.3.html: ../../libarchive/libarchive_changes.3 + groff -mdoc -T html ../../libarchive/libarchive_changes.3 > libarchive_changes.3.html + +libarchive_internals.3.html: ../../libarchive/libarchive_internals.3 + groff -mdoc -T html ../../libarchive/libarchive_internals.3 > libarchive_internals.3.html + +mtree.5.html: ../../libarchive/mtree.5 + groff -mdoc -T html ../../libarchive/mtree.5 > mtree.5.html + +tar.5.html: ../../libarchive/tar.5 + groff -mdoc -T html ../../libarchive/tar.5 > tar.5.html + +bsdtar.1.html: ../../tar/bsdtar.1 + groff -mdoc -T html ../../tar/bsdtar.1 > bsdtar.1.html + +bsdcpio.1.html: ../../cpio/bsdcpio.1 + groff -mdoc -T html ../../cpio/bsdcpio.1 > bsdcpio.1.html +all: archive_entry.3.html archive_entry_acl.3.html archive_entry_linkify.3.html archive_entry_misc.3.html archive_entry_paths.3.html archive_entry_perms.3.html archive_entry_stat.3.html archive_entry_time.3.html archive_read.3.html archive_read_add_passphrase.3.html archive_read_data.3.html archive_read_disk.3.html archive_read_extract.3.html archive_read_filter.3.html archive_read_format.3.html archive_read_free.3.html archive_read_header.3.html archive_read_new.3.html archive_read_open.3.html archive_read_set_options.3.html archive_util.3.html archive_write.3.html archive_write_blocksize.3.html archive_write_data.3.html archive_write_disk.3.html archive_write_filter.3.html archive_write_finish_entry.3.html archive_write_format.3.html archive_write_free.3.html archive_write_header.3.html archive_write_new.3.html archive_write_open.3.html archive_write_set_options.3.html archive_write_set_passphrase.3.html cpio.5.html libarchive-formats.5.html libarchive.3.html libarchive_changes.3.html libarchive_internals.3.html mtree.5.html tar.5.html bsdtar.1.html bsdcpio.1.html diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_entry.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_entry.3.html new file mode 100644 index 0000000..4c502b2 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_entry.3.html @@ -0,0 +1,187 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_ENTRY(3) BSD Library Functions Manual +ARCHIVE_ENTRY(3)

+ +

NAME

+ +

archive_entry_clear, +archive_entry_clone, archive_entry_free, +archive_entry_new — functions for managing +archive entry descriptions

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive_entry.h>

+ +

struct +archive_entry *

+ + +

archive_entry_clear(struct archive_entry *);

+ +

struct +archive_entry *

+ + +

archive_entry_clone(struct archive_entry *);

+ +

void

+ + +

archive_entry_free(struct archive_entry *);

+ +

struct +archive_entry *

+ + +

archive_entry_new(void);

+ +

DESCRIPTION

+ +

These functions create and +manipulate data objects that represent entries within an +archive. You can think of a struct archive_entry as a +heavy-duty version of struct stat: it includes everything +from struct stat plus associated pathname, textual group and +user names, etc. These objects are used by libarchive(3) to +represent the metadata associated with a particular entry in +an archive.

+ +

Create and +Destroy
+There are functions to allocate, destroy, clear, and copy +archive_entry objects:

+ +

archive_entry_clear()

+ +

Erases the object, resetting +all internal fields to the same state as a newly-created +object. This is provided to allow you to quickly recycle +objects without thrashing the heap.

+ +

archive_entry_clone()

+ +

A deep copy operation; all text +fields are duplicated.

+ +

archive_entry_free()

+ +

Releases the struct +archive_entry object.

+ +

archive_entry_new()

+ +

Allocate and return a blank +struct archive_entry object.

+ +

Function +groups
+Due to high number of functions, the accessor functions can +be found in man pages grouped by the purpose.

+ +

archive_entry_acl(3)

+ +

Access Control +List manipulation

+ +

archive_entry_paths(3)

+ +

Path name +manipulation

+ +

archive_entry_perms(3)

+ +

User, group and +mode manipulation

+ +

archive_entry_stat(3)

+ +

Functions not +in the other groups and copying to/from struct +stat.

+ +

archive_entry_time(3)

+ +

Time field +manipulation

+ +

Most of the +functions set or read entries in an object. Such functions +have one of the following forms:

+ +

archive_entry_set_XXXX()

+ +

Stores the provided data in the +object. In particular, for strings, the pointer is stored, +not the referenced string.

+ +

archive_entry_copy_XXXX()

+ +

As above, except that the +referenced data is copied into the object.

+ +

archive_entry_XXXX()

+ +

Returns the specified data. In +the case of strings, a const-qualified pointer to the string +is returned.

+ +

String data can be set or +accessed as wide character strings or normal char +strings. The functions that use wide character strings are +suffixed with _w. Note that these are different +representations of the same data: For example, if you store +a narrow string and read the corresponding wide string, the +object will transparently convert formats using the current +locale. Similarly, if you store a wide string and then store +a narrow string for the same data, the previously-set wide +string will be discarded in favor of the new data.

+ +

SEE ALSO

+ +

archive_entry_acl(3), +archive_entry_paths(3), archive_entry_perms(3), +archive_entry_time(3), libarchive(3)

+ +

HISTORY

+ +

The libarchive library +first appeared in FreeBSD 5.3.

+ +

AUTHORS

+ +

The libarchive library +was written by Tim Kientzle <kientzle@acm.org>.

+ +

BSD +February 2, 2012 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_entry_acl.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_entry_acl.3.html new file mode 100644 index 0000000..ee84f3d --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_entry_acl.3.html @@ -0,0 +1,570 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_ENTRY_ACL(3) BSD Library Functions Manual +ARCHIVE_ENTRY_ACL(3)

+ +

NAME

+ + +

archive_entry_acl_add_entry, +archive_entry_acl_add_entry_w, +archive_entry_acl_clear, +archive_entry_acl_count, +archive_entry_acl_from_text, +archive_entry_acl_from_text_w, +archive_entry_acl_next, +archive_entry_acl_reset, +archive_entry_acl_to_text, +archive_entry_acl_to_text_w, +archive_entry_acl_types — functions for +manipulating Access Control Lists in archive entry +descriptions

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive_entry.h>

+ +

void

+ + +

archive_entry_acl_add_entry(struct archive_entry *a, +int type, int permset, +int tag, int qualifier, +const char *name);

+ +

void

+ + +

archive_entry_acl_add_entry_w(struct archive_entry *a, +int type, int permset, +int tag, int qualifier, +const wchar_t *name);

+ +

void

+ + +

archive_entry_acl_clear(struct archive_entry *a);

+ +

int

+ + +

archive_entry_acl_count(struct archive_entry *a, +int type);

+ +

int

+ + +

archive_entry_acl_from_text(struct archive_entry *a, +const char *text, +int type);

+ +

int

+ + +

archive_entry_acl_from_text_w(struct archive_entry *a, +const wchar_t *text, +int type);

+ +

int

+ + +

archive_entry_acl_next(struct archive_entry *a, +int type, int *ret_type, +int *ret_permset, int *ret_tag, +int *ret_qual, +const char **ret_name);

+ +

int

+ + +

archive_entry_acl_reset(struct archive_entry *a, +int type);

+ +

char +*

+ + +

archive_entry_acl_to_text(struct archive_entry *a, +ssize_t *len_p, int flags);

+ +

wchar_t +*

+ + +

archive_entry_acl_to_text_w(struct archive_entry *a, +ssize_t *len_p, int flags);

+ +

int

+ + +

archive_entry_acl_types(struct archive_entry *a);

+ +

DESCRIPTION

+ +

The ’’Access Control +Lists (ACLs)’’ extend the standard Unix +permission model. The ACL interface of libarchive +supports both POSIX.1e and NFSv4 style ACLs. Use of ACLs is +restricted by various levels of ACL support in operating +systems, file systems and archive formats.

+ +

POSIX.1e +Access Control Lists
+A POSIX.1e ACL consists of a number of independent entries. +Each entry specifies the permission set as a bitmask of +basic permissions. Valid permissions in the permset +are:

+ +

ARCHIVE_ENTRY_ACL_READ (r)
+ARCHIVE_ENTRY_ACL_WRITE (w)
+ARCHIVE_ENTRY_ACL_EXECUTE (x)

+ +

The permissions correspond to +the normal Unix permissions.

+ +

The tag +specifies the principal to which the permission applies. +Valid values are:

+ +

ARCHIVE_ENTRY_ACL_USER

+ +

The user specified by the name +field.

+ +

ARCHIVE_ENTRY_ACL_USER_OBJ

+ +

The owner of the file.

+ +

ARCHIVE_ENTRY_ACL_GROUP

+ +

The group specified by the name +field.

+ +

ARCHIVE_ENTRY_ACL_GROUP_OBJ

+ +

The group which owns the +file.

+ +

ARCHIVE_ENTRY_ACL_MASK

+ +

The maximum permissions to be +obtained via group permissions.

+ +

ARCHIVE_ENTRY_ACL_OTHER

+ +

Any principal who is not the +file owner or a member of the owning group.

+ +

The principals +ARCHIVE_ENTRY_ACL_USER_OBJ, ARCHIVE_ENTRY_ACL_GROUP_OBJ and +ARCHIVE_ENTRY_ACL_OTHER are equivalent to user, group and +other in the classic Unix permission model and specify +non-extended ACL entries.

+ +

All files have +an access ACL (ARCHIVE_ENTRY_ACL_TYPE_ACCESS). This +specifies the permissions required for access to the file +itself. Directories have an additional ACL +(ARCHIVE_ENTRY_ACL_TYPE_DEFAULT), which controls the initial +access ACL for newly-created directory entries.

+ +

NFSv4 Access +Control Lists
+A NFSv4 ACL consists of multiple individual entries called +Access Control Entries (ACEs).

+ +

There are four +possible types of a NFSv4 ACE:

+ +

ARCHIVE_ENTRY_ACL_TYPE_ALLOW

+ +

Allow principal to perform +actions requiring given permissions.

+ +

ARCHIVE_ENTRY_ACL_TYPE_DENY

+ +

Prevent principal from +performing actions requiring given permissions.

+ +

ARCHIVE_ENTRY_ACL_TYPE_AUDIT

+ +

Log access attempts by +principal which require given permissions.

+ +

ARCHIVE_ENTRY_ACL_TYPE_ALARM

+ +

Trigger a system alarm on +access attempts by principal which require given +permissions.

+ +

The tag +specifies the principal to which the permission applies. +Valid values are:

+ +

ARCHIVE_ENTRY_ACL_USER

+ +

The user specified by the name +field.

+ +

ARCHIVE_ENTRY_ACL_USER_OBJ

+ +

The owner of the file.

+ +

ARCHIVE_ENTRY_ACL_GROUP

+ +

The group specified by the name +field.

+ +

ARCHIVE_ENTRY_ACL_GROUP_OBJ

+ +

The group which owns the +file.

+ +

ARCHIVE_ENTRY_ACL_EVERYONE

+ +

Any principal who is not the +file owner or a member of the owning group.

+ +

Entries with the +ARCHIVE_ENTRY_ACL_USER or ARCHIVE_ENTRY_ACL_GROUP tag store +the user and group name in the name string and +optionally the user or group ID in the qualifier +integer.

+ +

NFSv4 ACE +permissions and flags are stored in the same permset +bitfield. Some permissions share the same constant and +permission character but have different effect on +directories than on files. The following ACE permissions are +supported:

+ +

ARCHIVE_ENTRY_ACL_READ_DATA (r)

+ +

Read data (file).

+ +

ARCHIVE_ENTRY_ACL_LIST_DIRECTORY (r)

+ +

List entries (directory).

+ +

ARCHIVE_ENTRY_ACL_WRITE_DATA (w)

+ +

Write data (file).

+ +

ARCHIVE_ENTRY_ACL_ADD_FILE (w)

+ +

Create files (directory).

+ +

ARCHIVE_ENTRY_ACL_EXECUTE (x)

+ +

Execute file or change into a +directory.

+ +

ARCHIVE_ENTRY_ACL_APPEND_DATA (p)

+ +

Append data (file).

+ +

ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY (p)

+ +

Create subdirectories +(directory).

+ +

ARCHIVE_ENTRY_ACL_DELETE_CHILD (D)

+ +

Remove files and subdirectories +inside a directory.

+ +

ARCHIVE_ENTRY_ACL_DELETE (d)

+ +

Remove file or directory.

+ +

ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES (a)

+ +

Read file or directory +attributes.

+ +

ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES (A)

+ +

Write file or directory +attributes.

+ +

ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS (R)

+ +

Read named file or directory +attributes.

+ +

ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS (W)

+ +

Write named file or directory +attributes.

+ +

ARCHIVE_ENTRY_ACL_READ_ACL (c)

+ +

Read file or directory ACL.

+ +

ARCHIVE_ENTRY_ACL_WRITE_ACL (C)

+ +

Write file or directory +ACL.

+ +

ARCHIVE_ENTRY_ACL_WRITE_OWNER (o)

+ +

Change owner of a file or +directory.

+ +

ARCHIVE_ENTRY_ACL_SYNCHRONIZE (s)

+ +

Use synchronous I/O.

+ +

The following +NFSv4 ACL inheritance flags are supported:

+ +

ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT (f)

+ +

Inherit parent directory ACE to +files.

+ +

ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT (d)

+ +

Inherit parent directory ACE to +subdirectories.

+ +

ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY (i)

+ +

Only inherit, do not apply the +permission on the directory itself.

+ +

ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT +(n)

+ +

Do not propagate inherit flags. +Only first-level entries inherit ACLs.

+ +

ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS (S)

+ +

Trigger alarm or audit on +successful access.

+ +

ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS (F)

+ +

Trigger alarm or audit on +failed access.

+ +

ARCHIVE_ENTRY_ACL_ENTRY_INHERITED (I)

+ +

Mark that ACE was +inherited.

+ +

Functions +
+archive_entry_acl_add_entry
() and +archive_entry_acl_add_entry_w() add a single ACL +entry. For the access ACL and non-extended principals, the +classic Unix permissions are updated. An archive entry +cannot contain both POSIX.1e and NFSv4 ACL entries.

+ + +

archive_entry_acl_clear() +removes all ACL entries and resets the enumeration +pointer.

+ + +

archive_entry_acl_count() +counts the ACL entries that have the given type mask. +type can be the bitwise-or of

+ +

ARCHIVE_ENTRY_ACL_TYPE_ACCESS
+ARCHIVE_ENTRY_ACL_TYPE_DEFAULT

+ +

for POSIX.1e +ACLs and

+ +

ARCHIVE_ENTRY_ACL_TYPE_ALLOW
+ARCHIVE_ENTRY_ACL_TYPE_DENY
+ARCHIVE_ENTRY_ACL_TYPE_AUDIT
+ARCHIVE_ENTRY_ACL_TYPE_ALARM

+ +

for NFSv4 ACLs. +For POSIX.1e ACLs if ARCHIVE_ENTRY_ACL_TYPE_ACCESS is +included and at least one extended ACL entry is found, the +three non-extended ACLs are added.

+ + +

archive_entry_acl_from_text() +and archive_entry_acl_from_text_w() add new (or merge +with existing) ACL entries from (wide) text. The argument +type may take one of the following values:

+ +

ARCHIVE_ENTRY_ACL_TYPE_ACCESS
+ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
+ARCHIVE_ENTRY_ACL_TYPE_NFS4

+ +

Supports all +formats that can be created with +archive_entry_acl_to_text() or respectively +archive_entry_acl_to_text_w(). Existing ACL entries +are preserved. To get a clean new ACL from text +archive_entry_acl_clear() must be called first. +Entries prefixed with ’’default:’’ +are treated as ARCHIVE_ENTRY_ACL_TYPE_DEFAULT unless +type is ARCHIVE_ENTRY_ACL_TYPE_NFS4. Invalid entries, +non-parseable ACL entries and entries beginning with the +’#’ character (comments) are skipped.

+ + +

archive_entry_acl_next() +return the next entry of the ACL list. This functions may +only be called after archive_entry_acl_reset() has +indicated the presence of extended ACL entries.

+ + +

archive_entry_acl_reset() +prepare reading the list of ACL entries with +archive_entry_acl_next(). The function returns 0 if +no non-extended ACLs are found. In this case, the access +permissions should be obtained by archive_entry_mode(3) or +set using chmod(2). Otherwise, the function returns the same +value as archive_entry_acl_count().

+ + +

archive_entry_acl_to_text() +and archive_entry_acl_to_text_w() convert the ACL +entries for the given type into a (wide) string of ACL +entries separated by newline. If the pointer len_p is +not NULL, then the function shall return the length of the +string (not including the NULL terminator) in the location +pointed to by len_p. The flag argument is a +bitwise-or.

+ +

The following +flags are effective only on POSIX.1e ACL:

+ +

ARCHIVE_ENTRY_ACL_TYPE_ACCESS

+ +

Output access ACLs.

+ +

ARCHIVE_ENTRY_ACL_TYPE_DEFAULT

+ +

Output POSIX.1e default +ACLs.

+ +

ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT

+ +

Prefix each default ACL entry +with the word ’’default:’’.

+ +

ARCHIVE_ENTRY_ACL_STYLE_SOLARIS

+ +

The mask and other ACLs don not +contain a double colon.

+ +

The following +flags are effecive only on NFSv4 ACL:

+ +

ARCHIVE_ENTRY_ACL_STYLE_COMPACT

+ +

Do not output minus characters +for unset permissions and flags in NFSv4 ACL permission and +flag fields.

+ +

The following +flags are effective on both POSIX.1e and NFSv4 ACL:

+ +

ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID

+ +

Add an additional +colon-separated field containing the user or group id.

+ +

ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA

+ +

Separate ACL entries with comma +instead of newline.

+ +

If the archive +entry contains NFSv4 ACLs, all types of NFSv4 ACLs are +returned. It the entry contains POSIX.1e ACLs and none of +the flags ARCHIVE_ENTRY_ACL_TYPE_ACCESS or +ARCHIVE_ENTRY_ACL_TYPE_DEFAULT are specified, both access +and default entries are returned and default entries are +prefixed with ’’default:’’.

+ + +

archive_entry_acl_types() +get ACL entry types contained in an archive entry’s +ACL. As POSIX.1e and NFSv4 ACL entries cannot be mixed, this +function is a very efficient way to detect if an ACL already +contains POSIX.1e or NFSv4 ACL entries.

+ +

RETURN VALUES

+ + +

archive_entry_acl_count() +and archive_entry_acl_reset() returns the number of +ACL entries that match the given type mask. For POSIX.1e +ACLS if the type mask includes ARCHIVE_ENTRY_ACL_TYPE_ACCESS +and at least one extended ACL entry exists, the three +classic Unix permissions are counted.

+ + +

archive_entry_acl_from_text() +and archive_entry_acl_from_text_w() return ARCHIVE_OK +if all entries were successfully parsed and ARCHIVE_WARN if +one or more entries were invalid or non-parseable.

+ + +

archive_entry_acl_next() +returns ARCHIVE_OK on success, ARCHIVE_EOF if no more ACL +entries exist and ARCHIVE_WARN if +archive_entry_acl_reset() has not been called +first.

+ + +

archive_entry_acl_to_text() +returns a string representing the ACL entries matching the +given type and flags on success or NULL on error.

+ + +

archive_entry_acl_to_text_w() +returns a wide string representing the ACL entries matching +the given type and flags on success or NULL on error.

+ + +

archive_entry_acl_types() +returns a bitmask of ACL entry types or 0 if archive entry +has no ACL entries.

+ +

SEE ALSO

+ +

archive_entry(3), +libarchive(3)

+ +

BSD +February 15, 2017 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_entry_linkify.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_entry_linkify.3.html new file mode 100644 index 0000000..b92ff26 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_entry_linkify.3.html @@ -0,0 +1,212 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_ENTRY_LINKIFY(3) BSD Library Functions Manual +ARCHIVE_ENTRY_LINKIFY(3)

+ +

NAME

+ + +

archive_entry_linkresolver, +archive_entry_linkresolver_new, +archive_entry_linkresolver_set_strategy, +archive_entry_linkresolver_free, +archive_entry_linkify — hardlink resolver +functions

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive_entry.h>

+ +

struct +archive_entry_linkresolver *

+ + +

archive_entry_linkresolver_new(void);

+ +

void

+ + +

archive_entry_linkresolver_set_strategy(struct archive_entry_linkresolver *resolver, +int format);

+ +

void

+ + +

archive_entry_linkresolver_free(struct archive_entry_linkresolver *resolver);

+ +

void

+ + +

archive_entry_linkify(struct archive_entry_linkresolver *resolver, +struct archive_entry **entry, +struct archive_entry **sparse);

+ +

DESCRIPTION

+ +

Programs that want to create +archives have to deal with hardlinks. Hardlinks are handled +in different ways by the archive formats. The basic +strategies are:

+ +

1.

+ +

Ignore hardlinks and store the +body for each reference (old cpio, zip).

+ +

2.

+ +

Store the body the first time +an inode is seen (ustar, pax).

+ +

3.

+ +

Store the body the last time an +inode is seen (new cpio).

+ +

The +archive_entry_linkresolver functions help by +providing a unified interface and handling the complexity +behind the scene.

+ +

The +archive_entry_linkresolver functions assume that +archive_entry instances have valid nlinks, inode and +device values. The inode and device value is used to match +entries. The nlinks value is used to determined if all +references have been found and if the internal references +can be recycled.

+ +

The +archive_entry_linkresolver_new() function allocates a +new link resolver. The instance can be freed using +archive_entry_linkresolver_free(). All deferred +entries are flushed and the internal storage is freed.

+ +

The +archive_entry_linkresolver_set_strategy() function +selects the optimal hardlink strategy for the given format. +The format code can be obtained from archive_format(3). The +function can be called more than once, but it is recommended +to flush all deferred entries first.

+ +

The +archive_entry_linkify() function is the core of +archive_entry_linkresolver. The entry() +argument points to the archive_entry that should be +written. Depending on the strategy one of the following +actions is taken:

+ +

1.

+ +

For the simple archive formats +*entry is left unmodified and *sparse is set +to NULL.

+ +

2.

+ +

For tar like archive formats, +*sparse is set to NULL. If *entry is NULL, no +action is taken. If the hardlink count of *entry is +larger than 1 and the file type is a regular file or +symbolic link, the internal list is searched for a matching +inode. If such an inode is found, the link count is +decremented and the file size of *entry is set to 0 +to notify that no body should be written. If no such inode +is found, a copy of the entry is added to the internal cache +with a link count reduced by one.

+ +

3.

+ +

For new cpio like archive +formats a value for *entry of NULL is used to flush +deferred entries. In that case *entry is set to an +arbitrary deferred entry and the entry itself is removed +from the internal list. If the internal list is empty, +*entry is set to NULL. In either case, *sparse +is set to NULL and the function returns. If the hardlink +count of *entry is one or the file type is a +directory or device, *sparse is set to NULL and no +further action is taken. Otherwise, the internal list is +searched for a matching inode. If such an inode is not +found, the entry is added to the internal list, both +*entry and *sparse are set to NULL and the +function returns. If such an inode is found, the link count +is decremented. If it remains larger than one, the existing +entry on the internal list is swapped with *entry +after retaining the link count. The existing entry is +returned in *entry. If the link count reached one, +the new entry is also removed from the internal list and +returned in *sparse. Otherwise *sparse is set +to NULL.

+ +

The general +usage is therefore:

+ +

1.

+ +

For each new archive entry, +call archive_entry_linkify().

+ +

2.

+ +

Keep in mind that the entries +returned may have a size of 0 now.

+ +

3.

+ +

If *entry is not NULL, +archive it.

+ +

4.

+ +

If *sparse is not NULL, +archive it.

+ +

5.

+ +

After all entries have been +written to disk, call archive_entry_linkify() with +*entry set to NULL and archive the returned entry as +long as it is not NULL.

+ +

RETURN VALUES

+ + +

archive_entry_linkresolver_new() +returns NULL on malloc(3) failures.

+ +

SEE ALSO

+ +

archive_entry(3)

+ +

BSD +February 2, 2012 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_entry_misc.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_entry_misc.3.html new file mode 100644 index 0000000..e55e194 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_entry_misc.3.html @@ -0,0 +1,91 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_ENTRY_MISC(3) BSD Library Functions Manual +ARCHIVE_ENTRY_MISC(3)

+ +

NAME

+ + +

archive_entry_symlink_type, +archive_entry_set_symlink_type — miscellaneous +functions for manipulating properties of archive_entry

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive_entry.h>

+ +

int

+ + +

archive_entry_symlink_type(struct archive_entry *a);

+ +

void

+ + +

archive_entry_set_symlink_type(struct archive_entry *a, +int);

+ +

DESCRIPTION

+ +

The function +archive_entry_symlink_type() returns and the function +archive_entry_set_symlink_type() sets the type of the +symbolic link stored in an archive entry. These functions +have special meaning on operating systems that support +multiple symbolic link types (e.g. Microsoft Windows).

+ +

Supported values +are:

+ +

AE_SYMLINK_TYPE_UNDEFINED

+ +

Symbolic link +target type is not defined (default on unix systems)

+ +

AE_SYMLINK_TYPE_FILE

+ +

Symbolic link +points to a file

+ +

AE_SYMLINK_TYPE_DIRECTORY

+ +

Symbolic link +points to a directory

+ +

SEE ALSO

+ +

archive_entry(3), +archive_entry_paths(3), archive_entry_stat(3), +libarchive(3)

+ +

BSD +April 15, 2019 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_entry_paths.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_entry_paths.3.html new file mode 100644 index 0000000..510090b --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_entry_paths.3.html @@ -0,0 +1,284 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_ENTRY_PATHS(3) BSD Library Functions Manual +ARCHIVE_ENTRY_PATHS(3)

+ +

NAME

+ +

archive_entry_hardlink, +archive_entry_hardlink_w, +archive_entry_set_hardlink, +archive_entry_copy_hardlink, +archive_entry_copy_hardlink_w, +archive_entry_update_hardlink_utf8, +archive_entry_set_link, +archive_entry_copy_link, +archive_entry_copy_link_w, +archive_entry_update_link_utf8, +archive_entry_pathname, +archive_entry_pathname_w, +archive_entry_set_pathname, +archive_entry_copy_pathname, +archive_entry_copy_pathname_w, +archive_entry_update_pathname_utf8, +archive_entry_sourcepath, +archive_entry_copy_sourcepath, +archive_entry_symlink, +archive_entry_symlink_w, +archive_entry_set_symlink, +archive_entry_copy_symlink, +archive_entry_copy_symlink_w, +archive_entry_update_symlink_utf8 — functions +for manipulating path names in archive entry +descriptions

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive_entry.h>

+ +

const char +*

+ + +

archive_entry_hardlink(struct archive_entry *a);

+ +

const wchar_t +*

+ + +

archive_entry_hardlink_w(struct archive_entry *a);

+ +

void

+ + +

archive_entry_set_hardlink(struct archive_entry *a, +const char *path);

+ +

void

+ + +

archive_entry_copy_hardlink(struct archive_entry *a, +const char *path);

+ +

void

+ + +

archive_entry_copy_hardlink_w(struct archive_entry *a, +const, wchar_t, *path");

+ +

int

+ + +

archive_entry_update_hardlink_utf8(struct archive_entry *a, +const char *path);

+ +

void

+ + +

archive_entry_set_link(struct archive_entry *a, +const char *path);

+ +

void

+ + +

archive_entry_copy_link(struct archive_entry *a, +const char *path);

+ +

void

+ + +

archive_entry_copy_link_w(struct archive_entry *a, +const wchar_t *path);

+ +

int

+ + +

archive_entry_update_link_utf8(struct archive_entry *a, +const char *path);

+ +

const char +*

+ + +

archive_entry_pathname(struct archive_entry *a);

+ +

const wchar_t +*

+ + +

archive_entry_pathname_w(struct archive_entry *a);

+ +

void

+ + +

archive_entry_set_pathname(struct archive_entry *a, +const char *path);

+ +

void

+ + +

archive_entry_copy_pathname(struct archive_entry *a, +const char *path);

+ +

void

+ + +

archive_entry_copy_pathname_w(struct archive_entry *a, +const wchar_t *path);

+ +

int

+ + +

archive_entry_update_pathname_utf8(struct archive_entry *a, +const char *path);

+ +

const char +*

+ + +

archive_entry_sourcepath(struct archive_entry *a);

+ +

void

+ + +

archive_entry_copy_sourcepath(struct archive_entry *a, +const char *path);

+ +

const char +*

+ + +

archive_entry_symlink(struct archive_entry *a);

+ +

const wchar_t +*

+ + +

archive_entry_symlink_w(struct archive_entry *a);

+ +

void

+ + +

archive_entry_set_symlink(struct archive_entry *a, +const char *path);

+ +

void

+ + +

archive_entry_copy_symlink(struct archive_entry *a, +const char *path);

+ +

void

+ + +

archive_entry_copy_symlink_w(struct archive_entry *a, +const wchar_t *path);

+ +

int

+ + +

archive_entry_update_symlink_utf8(struct archive_entry *a, +const char *path);

+ +

DESCRIPTION

+ +

Path names supported by +archive_entry(3):

+ +

hardlink

+ +

Destination of +the hardlink.

+ +

link

+ +

Update only. +For a symlink, update the destination. Otherwise, make the +entry a hardlink and alter the destination for that.

+ +

pathname

+ +

Path in the +archive

+ +

sourcepath

+ +

Path on the +disk for use by archive_read_disk(3).

+ +

symlink

+ +

Destination of +the symbolic link.

+ +

Path names can +be provided in one of three different ways:

+ +

char *

+ +

Multibyte +strings in the current locale.

+ +

wchar_t *

+ +

Wide character +strings in the current locale. The accessor functions are +named XXX_w().

+ +

UTF-8

+ +

Unicode strings +encoded as UTF-8. These are convenience functions to update +both the multibyte and wide character strings at the same +time.

+ +

The sourcepath +is a pure filesystem concept and never stored in an archive +directly.

+ +

For that reason, +it is only available as multibyte string. The link path is a +convenience function for conditionally setting hardlink or +symlink destination. It doesn’t have a corresponding +get accessor function.

+ + +

archive_entry_set_XXX() +is an alias for archive_entry_copy_XXX().

+ +

SEE ALSO

+ +

archive_entry(3), +libarchive(3)

+ +

BSD +February 2, 2012 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_entry_perms.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_entry_perms.3.html new file mode 100644 index 0000000..35838a5 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_entry_perms.3.html @@ -0,0 +1,315 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_ENTRY_PERMS(3) BSD Library Functions Manual +ARCHIVE_ENTRY_PERMS(3)

+ +

NAME

+ +

archive_entry_gid, +archive_entry_set_gid, archive_entry_uid, +archive_entry_set_uid, archive_entry_perm, +archive_entry_set_perm, archive_entry_strmode, +archive_entry_uname, archive_entry_uname_w, +archive_entry_set_uname, +archive_entry_copy_uname, +archive_entry_copy_uname_w, +archive_entry_update_uname_utf8, +archive_entry_gname, archive_entry_gname_w, +archive_entry_set_gname, +archive_entry_copy_gname, +archive_entry_copy_gname_w, +archive_entry_update_gname_utf8, +archive_entry_fflags, +archive_entry_fflags_text, +archive_entry_set_fflags, +archive_entry_copy_fflags_text, +archive_entry_copy_fflags_text_w — functions +for manipulating ownership and permissions in archive entry +descriptions

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive_entry.h>

+ + +

gid_t

+ + +

archive_entry_gid(struct archive_entry *a);

+ +

void

+ + +

archive_entry_set_gid(struct archive_entry *a, +gid_t gid);

+ + +

uid_t

+ + +

archive_entry_uid(struct archive_entry *a);

+ +

void

+ + +

archive_entry_set_uid(struct archive_entry *a, +uid_t uid);

+ + +

mode_t

+ + +

archive_entry_perm(struct archive_entry *a);

+ +

void

+ + +

archive_entry_set_perm(struct archive_entry *a, +mode_t mode);

+ +

const char +*

+ + +

archive_entry_strmode(struct archive_entry *a);

+ +

const char +*

+ + +

archive_entry_gname(struct archive_entry *a);

+ +

const wchar_t +*

+ + +

archive_entry_gname_w(struct archive_entry *a);

+ +

void

+ + +

archive_entry_set_gname(struct archive_entry *a, +const char *a);

+ +

void

+ + +

archive_entry_copy_gname(struct archive_entry *a, +const char *name);

+ +

void

+ + +

archive_entry_copy_gname_w(struct archive_entry *a, +const wchar_t *name);

+ +

int

+ + +

archive_entry_update_gname_utf8(struct archive_entry *a, +const char *name);

+ +

const char +*

+ + +

archive_entry_uname(struct archive_entry *a);

+ +

const wchar_t +*

+ + +

archive_entry_uname_w(struct archive_entry *a);

+ +

void

+ + +

archive_entry_set_uname(struct archive_entry *a, +const char *name);

+ +

void

+ + +

archive_entry_copy_uname(struct archive_entry *a, +const char *name);

+ +

void

+ + +

archive_entry_copy_uname_w(struct archive_entry *a, +const wchar_t *name);

+ +

int

+ + +

archive_entry_update_uname_utf8(struct archive_entry *a, +const char *name);

+ +

void

+ + +

archive_entry_fflags(struct archive_entry *a, +unsigned long *set_bits, +unsigned long *clear_bits);

+ +

const char +*

+ + +

archive_entry_fflags_text(struct archive_entry *a);

+ +

void

+ + +

archive_entry_set_fflags(struct archive_entry *a, +unsigned long set_bits, +unsigned long clear_bits);

+ +

const char +*

+ + +

archive_entry_copy_fflags_text(struct archive_entry *a, +const char *text);

+ +

const wchar_t +*

+ + +

archive_entry_copy_fflags_text_w(struct archive_entry *a, +const wchar_t *text);

+ +

DESCRIPTION

+ +

User id, group id and +mode
+The functions archive_entry_uid(), +archive_entry_gid(), and archive_entry_perm() +can be used to extract the user id, group id and permission +from the given entry. The corresponding functions +archive_entry_set_uid(), +archive_entry_set_gid(), and +archive_entry_set_perm() store the given user id, +group id and permission in the entry. The permission is also +set as a side effect of calling +archive_entry_set_mode().

+ + +

archive_entry_strmode() +returns a string representation of the permission as used by +the long mode of ls(1).

+ +

User and +group name
+User and group names can be provided in one of three +different ways:

+ +

char *

+ +

Multibyte +strings in the current locale.

+ +

wchar_t *

+ +

Wide character +strings in the current locale. The accessor functions are +named XXX_w().

+ +

UTF-8

+ +

Unicode strings +encoded as UTF-8. These are convenience functions to update +both the multibyte and wide character strings at the same +time.

+ + +

archive_entry_set_XXX() +is an alias for archive_entry_copy_XXX().

+ +

File +Flags
+File flags are transparently converted between a bitmap +representation and a textual format. For example, if you set +the bitmap and ask for text, the library will build a +canonical text format. However, if you set a text format and +request a text format, you will get back the same text, even +if it is ill-formed. If you need to canonicalize a textual +flags string, you should first set the text form, then +request the bitmap form, then use that to set the bitmap +form. Setting the bitmap format will clear the internal text +representation and force it to be reconstructed when you +next request the text form.

+ +

The bitmap +format consists of two integers, one containing bits that +should be set, the other specifying bits that should be +cleared. Bits not mentioned in either bitmap will be +ignored. Usually, the bitmap of bits to be cleared will be +set to zero. In unusual circumstances, you can force a +fully-specified set of file flags by setting the bitmap of +flags to clear to the complement of the bitmap of flags to +set. (This differs from fflagstostr(3), which only includes +names for set bits.) Converting a bitmap to a textual string +is a platform-specific operation; bits that are not +meaningful on the current platform will be ignored.

+ +

The canonical +text format is a comma-separated list of flag names. The +archive_entry_copy_fflags_text() and +archive_entry_copy_fflags_text_w() functions parse +the provided text and set the internal bitmap values. This +is a platform-specific operation; names that are not +meaningful on the current platform will be ignored. The +function returns a pointer to the start of the first name +that was not recognized, or NULL if every name was +recognized. Note that every name — including names +that follow an unrecognized name — will be evaluated, +and the bitmaps will be set to reflect every name that is +recognized. (In particular, this differs from +strtofflags(3), which stops parsing at the first +unrecognized name.)

+ +

SEE ALSO

+ +

archive_entry(3), +archive_entry_acl(3), archive_read_disk(3), +archive_write_disk(3), libarchive(3)

+ +

BUGS

+ +

The platform types uid_t +and gid_t are often 16 or 32 bit wide. In this case +it is possible that the ids can not be correctly restored +from archives and get truncated.

+ +

BSD +February 2, 2012 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_entry_stat.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_entry_stat.3.html new file mode 100644 index 0000000..2786956 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_entry_stat.3.html @@ -0,0 +1,381 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_ENTRY_STAT(3) BSD Library Functions Manual +ARCHIVE_ENTRY_STAT(3)

+ +

NAME

+ +

archive_entry_stat, +archive_entry_copy_stat, +archive_entry_filetype, +archive_entry_set_filetype, +archive_entry_mode, archive_entry_set_mode, +archive_entry_size, archive_entry_size_is_set, +archive_entry_set_size, +archive_entry_unset_size, archive_entry_dev, +archive_entry_set_dev, +archive_entry_dev_is_set, +archive_entry_devmajor, +archive_entry_set_devmajor, +archive_entry_devminor, +archive_entry_set_devminor, archive_entry_ino, +archive_entry_set_ino, +archive_entry_ino_is_set, archive_entry_ino64, +archive_entry_set_ino64, archive_entry_nlink, +archive_entry_rdev, archive_entry_set_rdev, +archive_entry_rdevmajor, +archive_entry_set_rdevmajor, +archive_entry_rdevminor, +archive_entry_set_rdevminor — accessor +functions for manipulating archive entry descriptions

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive_entry.h>

+ +

const struct +stat *

+ + +

archive_entry_stat(struct archive_entry *a);

+ +

void

+ + +

archive_entry_copy_stat(struct archive_entry *a, +const struct stat *sb);

+ + +

mode_t

+ + +

archive_entry_filetype(struct archive_entry *a);

+ +

void

+ + +

archive_entry_set_filetype(struct archive_entry *a, +unsigned int type);

+ + +

mode_t

+ + +

archive_entry_mode(struct archive_entry *a);

+ +

void

+ + +

archive_entry_set_mode(struct archive_entry *a, +mode_t mode);

+ + +

int64_t

+ + +

archive_entry_size(struct archive_entry *a);

+ +

int

+ + +

archive_entry_size_is_set(struct archive_entry *a);

+ +

void

+ + +

archive_entry_set_size(struct archive_entry *a, +int64_t size);

+ +

void

+ + +

archive_entry_unset_size(struct archive_entry *a);

+ + +

dev_t

+ + +

archive_entry_dev(struct archive_entry *a);

+ +

void

+ + +

archive_entry_set_dev(struct archive_entry *a, +dev_t dev);

+ +

int

+ + +

archive_entry_dev_is_set(struct archive_entry *a);

+ + +

dev_t

+ + +

archive_entry_devmajor(struct archive_entry *a);

+ +

void

+ + +

archive_entry_set_devmajor(struct archive_entry *a, +dev_t major);

+ + +

dev_t

+ + +

archive_entry_devminor(struct archive_entry *a);

+ +

void

+ + +

archive_entry_set_devminor(struct archive_entry *a, +dev_t minor);

+ + +

ino_t

+ + +

archive_entry_ino(struct archive_entry *a);

+ +

void

+ + +

archive_entry_set_ino(struct archive_entry *a, +unsigned long ino);

+ +

int

+ + +

archive_entry_ino_is_set(struct archive_entry *a);

+ + +

int64_t

+ + +

archive_entry_ino64(struct archive_entry *a);

+ +

void

+ + +

archive_entry_set_ino64(struct archive_entry *a, +int64_t ino);

+ +

unsigned +int

+ + +

archive_entry_nlink(struct archive_entry *a);

+ +

void

+ + +

archive_entry_set_nlink(struct archive_entry *a, +unsigned int count);

+ + +

dev_t

+ + +

archive_entry_rdev(struct archive_entry *a);

+ + +

dev_t

+ + +

archive_entry_rdevmajor(struct archive_entry *a);

+ + +

dev_t

+ + +

archive_entry_rdevminor(struct archive_entry *a);

+ +

void

+ + +

archive_entry_set_rdev(struct archive_entry *a, +dev_t dev);

+ +

void

+ + +

archive_entry_set_rdevmajor(struct archive_entry *a, +dev_t major);

+ +

void

+ + +

archive_entry_set_rdevminor(struct archive_entry *a, +dev_t minor);

+ +

DESCRIPTION

+ +

Copying to and from +struct stat
+The function archive_entry_stat() converts the +various fields stored in the archive entry to the format +used by stat(2). The return value remains valid until either +archive_entry_clear() or archive_entry_free() +is called. It is not affected by calls to the set accessor +functions. It currently sets the following values in +struct stat: st_atime, st_ctime, +st_dev, st_gid, st_ino, st_mode, +st_mtime, st_nlink, st_rdev, +st_size, st_uid. In addition, +st_birthtime and high-precision information for +time-related fields will be included on platforms that +support it.

+ +

The function +archive_entry_copy_stat() copies fields from the +platform’s struct stat. Fields not provided by +struct stat are unchanged.

+ +

General +accessor functions
+The functions archive_entry_filetype() and +archive_entry_set_filetype() get respectively set the +filetype. The file type is one of the following +constants:

+ +

AE_IFREG

+ +

Regular +file

+ +

AE_IFLNK

+ +

Symbolic +link

+ +

AE_IFSOCK

+ +

Socket

+ +

AE_IFCHR

+ +

Character +device

+ +

AE_IFBLK

+ +

Block +device

+ +

AE_IFDIR

+ +

Directory

+ +

AE_IFIFO

+ +

Named pipe +(fifo)

+ +

Not all file types are supported +by all platforms. The constants used by stat(2) may have +different numeric values from the corresponding constants +above.

+ +

The functions +archive_entry_mode() and +archive_entry_set_mode() get/set a combination of +file type and permissions and provide the equivalent of +st_mode. Use of archive_entry_filetype() and +archive_entry_perm() for getting and +archive_entry_set_filetype() and +archive_entry_set_perm() for setting is +recommended.

+ +

The function +archive_entry_size() returns the file size, if it has +been set, and 0 otherwise. archive_entry_size() can +be used to query that status. +archive_entry_set_size() and +archive_entry_unset_size() set and unset the size, +respectively.

+ +

The number of +references (hardlinks) can be obtained by calling +archive_entry_nlinks() and set with +archive_entry_set_nlinks().

+ +

Identifying +unique files
+The functions archive_entry_dev() and +archive_entry_ino64() are used by +archive_entry_linkify(3) to find hardlinks. The pair of +device and inode is supposed to identify hardlinked +files.

+ +

The device major +and minor number can be obtained independently using +archive_entry_devmajor() and +archive_entry_devminor(). The device can be set +either via archive_entry_set_dev() or by the +combination of major and minor number using +archive_entry_set_devmajor() and +archive_entry_set_devminor().

+ +

The inode number +can be obtained using archive_entry_ino(). This is a +legacy interface that uses the platform ino_t, which +may be very small. To set the inode number, +archive_entry_set_ino64() is the preferred +interface.

+ +

Accessor +functions for block and character devices
+Block and character devices are characterised either using a +device number or a pair of major and minor number. The +combined device number can be obtained with +archive_device_rdev() and set with +archive_device_set_rdev(). The major and minor +numbers are accessed by archive_device_rdevmajor(), +archive_device_rdevminor() +archive_device_set_rdevmajor() and +archive_device_set_rdevminor().

+ +

The process of +splitting the combined device number into major and minor +number and the reverse process of combing them differs +between platforms. Some archive formats use the combined +form, while other formats use the split form.

+ +

SEE ALSO

+ +

stat(2), archive_entry_acl(3), +archive_entry_perms(3), archive_entry_time(3), +libarchive(3)

+ +

BSD +February 2, 2012 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_entry_time.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_entry_time.3.html new file mode 100644 index 0000000..fdd3cfe --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_entry_time.3.html @@ -0,0 +1,205 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_ENTRY_TIME(3) BSD Library Functions Manual +ARCHIVE_ENTRY_TIME(3)

+ +

NAME

+ +

archive_entry_atime, +archive_entry_atime_nsec, +archive_entry_atime_is_set, +archive_entry_set_atime, +archive_entry_unset_atime, +archive_entry_birthtime, +archive_entry_birthtime_nsec, +archive_entry_birthtime_is_set, +archive_entry_set_birthtime, +archive_entry_unset_birthtime, +archive_entry_ctime, archive_entry_ctime_nsec, +archive_entry_ctime_is_set, +archive_entry_set_ctime, +archive_entry_unset_ctime, +archive_entry_mtime, archive_entry_mtime_nsec, +archive_entry_mtime_is_set, +archive_entry_set_mtime, +archive_entry_unset_mtime — functions for +manipulating times in archive entry descriptions

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive_entry.h>

+ + +

time_t

+ + +

archive_entry_atime(struct archive_entry *a);

+ +

long

+ + +

archive_entry_atime_nsec(struct archive_entry *a);

+ +

int

+ + +

archive_entry_atime_is_set(struct archive_entry *a);

+ +

void

+ + +

archive_entry_set_atime(struct archive_entry *a, +time_t sec, long nanosec);

+ +

void

+ + +

archive_entry_unset_atime(struct archive_entry *a);

+ + +

time_t

+ + +

archive_entry_birthtime(struct archive_entry *a);

+ +

long

+ + +

archive_entry_birthtime_nsec(struct archive_entry *a);

+ +

int

+ + +

archive_entry_birthtime_is_set(struct archive_entry *a);

+ +

void

+ + +

archive_entry_set_birthtime(struct archive_entry *a, +time_t sec, long nanosec);

+ +

void

+ + +

archive_entry_unset_birthtime(struct archive_entry *a);

+ + +

time_t

+ + +

archive_entry_ctime(struct archive_entry *a);

+ +

long

+ + +

archive_entry_ctime_nsec(struct archive_entry *a);

+ +

int

+ + +

archive_entry_ctime_is_set(struct archive_entry *a);

+ +

void

+ + +

archive_entry_set_ctime(struct archive_entry *a, +time_t sec, long nanosec);

+ +

void

+ + +

archive_entry_unset_ctime(struct archive_entry *a);

+ + +

time_t

+ + +

archive_entry_mtime(struct archive_entry *a);

+ +

long

+ + +

archive_entry_mtime_nsec(struct archive_entry *a);

+ +

int

+ + +

archive_entry_mtime_is_set(struct archive_entry *a);

+ +

void

+ + +

archive_entry_set_mtime(struct archive_entry *a, +time_t sec, long nanosec);

+ +

void

+ + +

archive_entry_unset_mtime(struct archive_entry *a);

+ +

DESCRIPTION

+ +

These functions create and +manipulate the time fields in an archive_entry. +Supported time fields are atime (access time), birthtime +(creation time), ctime (last time an inode property was +changed) and mtime (modification time).

+ +

libarchive(3) +provides a high-resolution interface. The timestamps are +truncated automatically depending on the archive format (for +archiving) or the filesystem capabilities (for +restoring).

+ +

All timestamp +fields are optional. The XXX_unset() functions can be +used to mark the corresponding field as missing. The current +state can be queried using XXX_is_set(). Unset time +fields have a second and nanosecond field of 0.

+ +

SEE ALSO

+ +

archive_entry(3), +libarchive(3)

+ +

HISTORY

+ +

The libarchive library +first appeared in FreeBSD 5.3.

+ +

AUTHORS

+ +

The libarchive library +was written by Tim Kientzle <kientzle@acm.org>.

+ +

BSD +February 2, 2012 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_read.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_read.3.html new file mode 100644 index 0000000..e04db2f --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_read.3.html @@ -0,0 +1,233 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_READ(3) BSD Library Functions Manual +ARCHIVE_READ(3)

+ +

NAME

+ +

archive_read — +functions for reading streaming archives

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive.h>

+ +

DESCRIPTION

+ +

These functions provide a +complete API for reading streaming archives. The general +process is to first create the struct archive object, set +options, initialize the reader, iterate over the archive +headers and associated data, then close the archive and +release all resources.

+ +

Create +archive object
+See archive_read_new(3).

+ +

To read an +archive, you must first obtain an initialized struct archive +object from archive_read_new().

+ +

Enable +filters and formats
+See archive_read_filter(3) and archive_read_format(3).

+ +

You can then +modify this object for the desired operations with the +various archive_read_set_XXX() and +archive_read_support_XXX() functions. In particular, +you will need to invoke appropriate +archive_read_support_XXX() functions to enable the +corresponding compression and format support. Note that +these latter functions perform two distinct operations: they +cause the corresponding support code to be linked into your +program, and they enable the corresponding auto-detect code. +Unless you have specific constraints, you will generally +want to invoke archive_read_support_filter_all() and +archive_read_support_format_all() to enable +auto-detect for all formats and compression types currently +supported by the library.

+ +

Set +options
+See archive_read_set_options(3).

+ +

Open +archive
+See archive_read_open(3).

+ +

Once you have +prepared the struct archive object, you call +archive_read_open() to actually open the archive and +prepare it for reading. There are several variants of this +function; the most basic expects you to provide pointers to +several functions that can provide blocks of bytes from the +archive. There are convenience forms that allow you to +specify a filename, file descriptor, FILE * object, +or a block of memory from which to read the archive data. +Note that the core library makes no assumptions about the +size of the blocks read; callback functions are free to read +whatever block size is most appropriate for the medium.

+ +

Consume +archive
+See archive_read_header(3), archive_read_data(3) and +archive_read_extract(3).

+ +

Each archive +entry consists of a header followed by a certain amount of +data. You can obtain the next header with +archive_read_next_header(), which returns a pointer +to an struct archive_entry structure with information about +the current archive element. If the entry is a regular file, +then the header will be followed by the file data. You can +use archive_read_data() (which works much like the +read(2) system call) to read this data from the archive, or +archive_read_data_block() which provides a slightly +more efficient interface. You may prefer to use the +higher-level archive_read_data_skip(), which reads +and discards the data for this entry, +archive_read_data_into_fd(), which copies the data to +the provided file descriptor, or +archive_read_extract(), which recreates the specified +entry on disk and copies data from the archive. In +particular, note that archive_read_extract() uses the +struct archive_entry structure that you provide it, which +may differ from the entry just read from the archive. In +particular, many applications will want to override the +pathname, file permissions, or ownership.

+ +

Release +resources
+See archive_read_free(3).

+ +

Once you have +finished reading data from the archive, you should call +archive_read_close() to close the archive, then call +archive_read_free() to release all resources, +including all memory allocated by the library.

+ +

EXAMPLES

+ +

The following illustrates basic +usage of the library. In this example, the callback +functions are simply wrappers around the standard open(2), +read(2), and close(2) system calls.

+ +

void
+list_archive(const char *name)
+{
+struct mydata *mydata;
+struct archive *a;
+struct archive_entry *entry;

+ +

mydata = +malloc(sizeof(struct mydata));
+a = archive_read_new();
+mydata->name = name;
+archive_read_support_filter_all(a);
+archive_read_support_format_all(a);
+archive_read_open(a, mydata, myopen, myread, myclose);
+while (archive_read_next_header(a, &entry) == +ARCHIVE_OK) {
+printf("%s\n",archive_entry_pathname(entry));
+archive_read_data_skip(a);
+}
+archive_read_free(a);
+free(mydata);
+}

+ +

la_ssize_t
+myread(struct archive *a, void *client_data, const void +**buff)
+{
+struct mydata *mydata = client_data;

+ +

*buff = +mydata->buff;
+return (read(mydata->fd, mydata->buff, 10240));
+}

+ +

int
+myopen(struct archive *a, void *client_data)
+{
+struct mydata *mydata = client_data;

+ +

mydata->fd = +open(mydata->name, O_RDONLY);
+return (mydata->fd >= 0 ? ARCHIVE_OK : ARCHIVE_FATAL); +
+}

+ +

int
+myclose(struct archive *a, void *client_data)
+{
+struct mydata *mydata = client_data;

+ +

if +(mydata->fd > 0)
+close(mydata->fd);
+return (ARCHIVE_OK);
+}

+ +

SEE ALSO

+ +

tar(1), archive_read_data(3), +archive_read_extract(3), archive_read_filter(3), +archive_read_format(3), archive_read_header(3), +archive_read_new(3), archive_read_open(3), +archive_read_set_options(3), archive_util(3), libarchive(3), +tar(5)

+ +

HISTORY

+ +

The libarchive library +first appeared in FreeBSD 5.3.

+ +

AUTHORS

+ +

The libarchive library +was written by Tim Kientzle <kientzle@acm.org>.

+ +

BUGS

+ +

Many traditional archiver +programs treat empty files as valid empty archives. For +example, many implementations of tar(1) allow you to append +entries to an empty file. Of course, it is impossible to +determine the format of an empty file by inspecting the +contents, so this library treats empty files as having a +special ’’empty’’ format.

+ +

BSD +February 2, 2012 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_read_add_passphrase.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_read_add_passphrase.3.html new file mode 100644 index 0000000..1cd60de --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_read_add_passphrase.3.html @@ -0,0 +1,82 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_READ_ADD_PASS... BSD Library Functions Manual +ARCHIVE_READ_ADD_PASS...

+ +

NAME

+ + +

archive_read_add_passphrase, +archive_read_set_passphrase_callback — +functions for reading encrypted archives

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive.h>

+ +

int

+ + +

archive_read_add_passphrase(struct archive *, +const char *passphrase);

+ +

int

+ + +

archive_read_set_passphrase_callback(struct archive *, +void *client_data, +archive_passphrase_callback *);

+ +

DESCRIPTION
+archive_read_add_passphrase
()

+ +

Register passphrases for +reading an encryption archive. If passphrase is NULL +or empty, this function will do nothing and +ARCHIVE_FAILED will be returned. Otherwise, +ARCHIVE_OK will be returned.

+ + +

archive_read_set_passphrase_callback()

+ +

Register a callback function +that will be invoked to get a passphrase for decryption +after trying all the passphrases registered by the +archive_read_add_passphrase() function failed.

+ +

SEE ALSO

+ +

tar(1), archive_read(3), +archive_read_set_options(3), libarchive(3)

+ +

BSD +September 14, 2014 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_read_data.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_read_data.3.html new file mode 100644 index 0000000..f9775c7 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_read_data.3.html @@ -0,0 +1,142 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_READ_DATA(3) BSD Library Functions Manual +ARCHIVE_READ_DATA(3)

+ +

NAME

+ +

archive_read_data, +archive_read_data_block, +archive_read_data_skip, +archive_read_data_into_fd — functions for +reading streaming archives

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive.h>

+ + +

la_ssize_t

+ + +

archive_read_data(struct archive *, +void *buff, size_t len);

+ +

int

+ + +

archive_read_data_block(struct archive *, +const void **buff, size_t *len, +off_t *offset);

+ +

int

+ + +

archive_read_data_skip(struct archive *);

+ +

int

+ + +

archive_read_data_into_fd(struct archive *, +int fd);

+ +

DESCRIPTION
+archive_read_data
()

+ +

Read data associated with the +header just read. Internally, this is a convenience function +that calls archive_read_data_block() and fills any +gaps with nulls so that callers see a single continuous +stream of data.

+ +

archive_read_data_block()

+ +

Return the next available block +of data for this entry. Unlike archive_read_data(), +the archive_read_data_block() function avoids copying +data and allows you to correctly handle sparse files, as +supported by some archive formats. The library guarantees +that offsets will increase and that blocks will not overlap. +Note that the blocks returned from this function can be much +larger than the block size read from disk, due to +compression and internal buffer optimizations.

+ +

archive_read_data_skip()

+ +

A convenience function that +repeatedly calls archive_read_data_block() to skip +all of the data for this archive entry. Note that this +function is invoked automatically by +archive_read_next_header2() if the previous entry was +not completely consumed.

+ +

archive_read_data_into_fd()

+ +

A convenience function that +repeatedly calls archive_read_data_block() to copy +the entire entry to the provided file descriptor.

+ +

RETURN VALUES

+ +

Most functions return zero on +success, non-zero on error. The possible return codes +include: ARCHIVE_OK (the operation succeeded), +ARCHIVE_WARN (the operation succeeded but a +non-critical error was encountered), ARCHIVE_EOF +(end-of-archive was encountered), ARCHIVE_RETRY (the +operation failed but can be retried), and +ARCHIVE_FATAL (there was a fatal error; the archive +should be closed immediately).

+ + +

archive_read_data() +returns a count of bytes actually read or zero at the end of +the entry. On error, a value of ARCHIVE_FATAL, +ARCHIVE_WARN, or ARCHIVE_RETRY is +returned.

+ +

ERRORS

+ +

Detailed error codes and textual +descriptions are available from the archive_errno() +and archive_error_string() functions.

+ +

SEE ALSO

+ +

tar(1), archive_read(3), +archive_read_extract(3), archive_read_filter(3), +archive_read_format(3), archive_read_header(3), +archive_read_open(3), archive_read_set_options(3), +archive_util(3), libarchive(3), tar(5)

+ +

BSD +February 2, 2012 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_read_disk.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_read_disk.3.html new file mode 100644 index 0000000..ac1e306 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_read_disk.3.html @@ -0,0 +1,382 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_READ_DISK(3) BSD Library Functions Manual +ARCHIVE_READ_DISK(3)

+ +

NAME

+ +

archive_read_disk_new, +archive_read_disk_set_behavior, +archive_read_disk_set_symlink_logical, +archive_read_disk_set_symlink_physical, +archive_read_disk_set_symlink_hybrid, +archive_read_disk_entry_from_file, +archive_read_disk_gname, +archive_read_disk_uname, +archive_read_disk_set_uname_lookup, +archive_read_disk_set_gname_lookup, +archive_read_disk_set_standard_lookup — +functions for reading objects from disk

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive.h>

+ +

struct +archive *

+ + +

archive_read_disk_new(void);

+ +

int

+ + +

archive_read_disk_set_behavior(struct archive *, +int);

+ +

int

+ + +

archive_read_disk_set_symlink_logical(struct archive *);

+ +

int

+ + +

archive_read_disk_set_symlink_physical(struct archive *);

+ +

int

+ + +

archive_read_disk_set_symlink_hybrid(struct archive *);

+ +

const char +*

+ + +

archive_read_disk_gname(struct archive *, +gid_t);

+ +

const char +*

+ + +

archive_read_disk_uname(struct archive *, +uid_t);

+ +

int

+ + +

archive_read_disk_set_gname_lookup(struct archive *, +void *, +const char *(*lookup)(void *, gid_t), +void (*cleanup)(void *));

+ +

int

+ + +

archive_read_disk_set_uname_lookup(struct archive *, +void *, +const char *(*lookup)(void *, uid_t), +void (*cleanup)(void *));

+ +

int

+ + +

archive_read_disk_set_standard_lookup(struct archive *);

+ +

int

+ + +

archive_read_disk_entry_from_file(struct archive *, +struct archive_entry *, int fd, +const struct stat *);

+ +

DESCRIPTION

+ +

These functions provide an API +for reading information about objects on disk. In +particular, they provide an interface for populating struct +archive_entry objects.

+ + +

archive_read_disk_new()

+ +

Allocates and initializes a +struct archive object suitable for reading object +information from disk.

+ + +

archive_read_disk_set_behavior()

+ +

Configures various behavior +options when reading entries from disk. The flags field +consists of a bitwise OR of one or more of the following +values:

+ +

ARCHIVE_READDISK_HONOR_NODUMP

+ +

Skip files and directories with +the nodump file attribute (file flag) set. By default, the +nodump file attribute is ignored.

+ +

ARCHIVE_READDISK_MAC_COPYFILE

+ +

Mac OS X specific. Read +metadata (ACLs and extended attributes) with copyfile(3). By +default, metadata is read using copyfile(3).

+ +

ARCHIVE_READDISK_NO_ACL

+ +

Do not read Access Control +Lists. By default, ACLs are read from disk.

+ +

ARCHIVE_READDISK_NO_FFLAGS

+ +

Do not read file attributes +(file flags). By default, file attributes are read from +disk. See chattr(1) (Linux) or chflags(1) (FreeBSD, Mac OS +X) for more information on file attributes.

+ +

ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS

+ +

Do not traverse mount points. +By default, mount points are traversed.

+ +

ARCHIVE_READDISK_NO_XATTR

+ +

Do not read extended file +attributes (xattrs). By default, extended file attributes +are read from disk. See xattr(7) (Linux), xattr(2) (Mac OS +X), or getextattr(8) (FreeBSD) for more information on +extended file attributes.

+ +

ARCHIVE_READDISK_RESTORE_ATIME

+ +

Restore access time of +traversed files. By default, access time of traversed files +is not restored.

+ + +

archive_read_disk_set_symlink_logical(), +archive_read_disk_set_symlink_physical(), +archive_read_disk_set_symlink_hybrid()

+ +

This sets the mode used for +handling symbolic links. The +’’logical’’ mode follows all +symbolic links. The ’’physical’’ +mode does not follow any symbolic links. The +’’hybrid’’ mode currently behaves +identically to the ’’logical’’ +mode.

+ + +

archive_read_disk_gname(), +archive_read_disk_uname()

+ +

Returns a user or group name +given a gid or uid value. By default, these always return a +NULL string.

+ + +

archive_read_disk_set_gname_lookup(), +archive_read_disk_set_uname_lookup()

+ +

These allow you to override the +functions used for user and group name lookups. You may also +provide a void * pointer to a private data structure and a +cleanup function for that data. The cleanup function will be +invoked when the struct archive object is destroyed or when +new lookup functions are registered.

+ + +

archive_read_disk_set_standard_lookup()

+ +

This convenience function +installs a standard set of user and group name lookup +functions. These functions use getpwuid(3) and getgrgid(3) +to convert ids to names, defaulting to NULL if the names +cannot be looked up. These functions also implement a simple +memory cache to reduce the number of calls to getpwuid(3) +and getgrgid(3).

+ + +

archive_read_disk_entry_from_file()

+ +

Populates a struct +archive_entry object with information about a particular +file. The archive_entry object must have already been +created with archive_entry_new(3) and at least one of the +source path or path fields must already be set. (If both are +set, the source path will be used.)

+ +

Information is +read from disk using the path name from the struct +archive_entry object. If a file descriptor is provided, some +information will be obtained using that file descriptor, on +platforms that support the appropriate system calls.

+ +

If a pointer to +a struct stat is provided, information from that structure +will be used instead of reading from the disk where +appropriate. This can provide performance benefits in +scenarios where struct stat information has already been +read from the disk as a side effect of some other operation. +(For example, directory traversal libraries often provide +this information.)

+ +

Where +necessary, user and group ids are converted to user and +group names using the currently-registered lookup functions +above. This affects the file ownership fields and ACL values +in the struct archive_entry object.

+ +

More information about the +struct archive object and the overall design of the +library can be found in the libarchive(3) overview.

+ +

EXAMPLES

+ +

The following illustrates basic +usage of the library by showing how to use it to copy an +item on disk into an archive.

+ +

void
+file_to_archive(struct archive *a, const char *name)
+{
+char buff[8192];
+size_t bytes_read;
+struct archive *ard;
+struct archive_entry *entry;
+int fd;

+ +

ard = +archive_read_disk_new();
+archive_read_disk_set_standard_lookup(ard);
+entry = archive_entry_new();
+fd = open(name, O_RDONLY);
+if (fd < 0)
+return;
+archive_entry_copy_pathname(entry, name);
+archive_read_disk_entry_from_file(ard, entry, fd, NULL); +
+archive_write_header(a, entry);
+while ((bytes_read = read(fd, buff, sizeof(buff))) > 0) +
+archive_write_data(a, buff, bytes_read);
+archive_write_finish_entry(a);
+archive_read_free(ard);
+archive_entry_free(entry);
+}

+ +

RETURN VALUES

+ +

Most functions return +ARCHIVE_OK (zero) on success, or one of several +negative error codes for errors. Specific error codes +include: ARCHIVE_RETRY for operations that might +succeed if retried, ARCHIVE_WARN for unusual +conditions that do not prevent further operations, and +ARCHIVE_FATAL for serious errors that make remaining +operations impossible.

+ + +

archive_read_disk_new() +returns a pointer to a newly-allocated struct archive object +or NULL if the allocation failed for any reason.

+ + +

archive_read_disk_gname() +and archive_read_disk_uname() return const char * +pointers to the textual name or NULL if the lookup failed +for any reason. The returned pointer points to internal +storage that may be reused on the next call to either of +these functions; callers should copy the string if they need +to continue accessing it.

+ +

ERRORS

+ +

Detailed error codes and textual +descriptions are available from the archive_errno() +and archive_error_string() functions.

+ +

SEE ALSO

+ +

tar(1), archive_read(3), +archive_util(3), archive_write(3), archive_write_disk(3), +libarchive(3)

+ +

HISTORY

+ +

The libarchive library +first appeared in FreeBSD 5.3. The +archive_read_disk interface was added to +libarchive 2.6 and first appeared in +FreeBSD 8.0.

+ +

AUTHORS

+ +

The libarchive library +was written by Tim Kientzle +<kientzle@FreeBSD.org>.

+ +

BUGS

+ +

The +’’standard’’ user name and group +name lookup functions are not the defaults because +getgrgid(3) and getpwuid(3) are sometimes too large for +particular applications. The current design allows the +application author to use a more compact implementation when +appropriate.

+ +

The full list of +metadata read from disk by +archive_read_disk_entry_from_file() is necessarily +system-dependent.

+ +

The +archive_read_disk_entry_from_file() function reads as +much information as it can from disk. Some method should be +provided to limit this so that clients who do not need ACLs, +for instance, can avoid the extra work needed to look up +such information.

+ +

This API should +provide a set of methods for walking a directory tree. That +would make it a direct parallel of the archive_read(3) API. +When such methods are implemented, the +’’hybrid’’ symbolic link mode will +make sense.

+ +

BSD +April 3, 2017 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_read_extract.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_read_extract.3.html new file mode 100644 index 0000000..6c41457 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_read_extract.3.html @@ -0,0 +1,134 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_READ_EXTRACT(3) BSD Library Functions Manual +ARCHIVE_READ_EXTRACT(3)

+ +

NAME

+ +

archive_read_extract, +archive_read_extract2, +archive_read_extract_set_progress_callback — +functions for reading streaming archives

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive.h>

+ +

int

+ + +

archive_read_extract(struct archive *, +struct archive_entry *, +int flags);

+ +

int

+ + +

archive_read_extract2(struct archive *src, +struct archive_entry *, +struct archive *dest);

+ +

void

+ + +

archive_read_extract_set_progress_callback(struct archive *, +void (*func)(void *), +void *user_data);

+ +

DESCRIPTION
+archive_read_extract
(), +archive_read_extract_set_skip_file()

+ +

A convenience function that +wraps the corresponding archive_write_disk(3) interfaces. +The first call to archive_read_extract() creates a +restore object using archive_write_disk_new(3) and +archive_write_disk_set_standard_lookup(3), then +transparently invokes archive_write_disk_set_options(3), +archive_write_header(3), archive_write_data(3), and +archive_write_finish_entry(3) to create the entry on disk +and copy data into it. The flags argument is passed +unmodified to archive_write_disk_set_options(3).

+ +

archive_read_extract2()

+ +

This is another version of +archive_read_extract() that allows you to provide +your own restore object. In particular, this allows you to +override the standard lookup functions using +archive_write_disk_set_group_lookup(3), and +archive_write_disk_set_user_lookup(3). Note that +archive_read_extract2() does not accept a +flags argument; you should use +archive_write_disk_set_options() to set the restore +options yourself.

+ +

archive_read_extract_set_progress_callback()

+ +

Sets a pointer to a +user-defined callback that can be used for updating progress +displays during extraction. The progress function will be +invoked during the extraction of large regular files. The +progress function will be invoked with the pointer provided +to this call. Generally, the data pointed to should include +a reference to the archive object and the archive_entry +object so that various statistics can be retrieved for the +progress display.

+ +

RETURN VALUES

+ +

Most functions return zero on +success, non-zero on error. The possible return codes +include: ARCHIVE_OK (the operation succeeded), +ARCHIVE_WARN (the operation succeeded but a +non-critical error was encountered), ARCHIVE_EOF +(end-of-archive was encountered), ARCHIVE_RETRY (the +operation failed but can be retried), and +ARCHIVE_FATAL (there was a fatal error; the archive +should be closed immediately).

+ +

ERRORS

+ +

Detailed error codes and textual +descriptions are available from the archive_errno() +and archive_error_string() functions.

+ +

SEE ALSO

+ +

tar(1), archive_read(3), +archive_read_data(3), archive_read_filter(3), +archive_read_format(3), archive_read_open(3), +archive_read_set_options(3), archive_util(3), libarchive(3), +tar(5)

+ +

BSD +February 2, 2012 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_read_filter.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_read_filter.3.html new file mode 100644 index 0000000..b7f240f --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_read_filter.3.html @@ -0,0 +1,209 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_READ_FILTER(3) BSD Library Functions Manual +ARCHIVE_READ_FILTER(3)

+ +

NAME

+ + +

archive_read_support_filter_all, +archive_read_support_filter_bzip2, +archive_read_support_filter_compress, +archive_read_support_filter_gzip, +archive_read_support_filter_lz4, +archive_read_support_filter_lzma, +archive_read_support_filter_none, +archive_read_support_filter_rpm, +archive_read_support_filter_uu, +archive_read_support_filter_xz, +archive_read_support_filter_zstd, +archive_read_support_filter_program, +archive_read_support_filter_program_signature — +functions for reading streaming archives

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive.h>

+ +

int

+ + +

archive_read_support_filter_all(struct archive *);

+ +

int

+ + +

archive_read_support_filter_bzip2(struct archive *);

+ +

int

+ + +

archive_read_support_filter_compress(struct archive *);

+ +

int

+ + +

archive_read_support_filter_grzip(struct archive *);

+ +

int

+ + +

archive_read_support_filter_gzip(struct archive *);

+ +

int

+ + +

archive_read_support_filter_lrzip(struct archive *);

+ +

int

+ + +

archive_read_support_filter_lz4(struct archive *);

+ +

int

+ + +

archive_read_support_filter_lzma(struct archive *);

+ +

int

+ + +

archive_read_support_filter_lzop(struct archive *);

+ +

int

+ + +

archive_read_support_filter_none(struct archive *);

+ +

int

+ + +

archive_read_support_filter_rpm(struct archive *);

+ +

int

+ + +

archive_read_support_filter_uu(struct archive *);

+ +

int

+ + +

archive_read_support_filter_xz(struct archive *);

+ +

int

+ + +

archive_read_support_filter_zstd(struct archive *);

+ +

int

+ + +

archive_read_support_filter_program(struct archive *, +const char *cmd);

+ +

int

+ + +

archive_read_support_filter_program_signature(struct archive *, +const char *cmd, +const void *signature, +size_t signature_length);

+ +

DESCRIPTION
+archive_read_support_filter_bzip2
(), +archive_read_support_filter_compress(), +archive_read_support_filter_grzip(), +archive_read_support_filter_gzip(), +archive_read_support_filter_lrzip(), +archive_read_support_filter_lz4(), +archive_read_support_filter_lzma(), +archive_read_support_filter_lzop(), +archive_read_support_filter_none(), +archive_read_support_filter_rpm(), +archive_read_support_filter_uu(), +archive_read_support_filter_xz(), +archive_read_support_filter_zstd(),

+ +

Enables auto-detection code and +decompression support for the specified compression. These +functions may fall back on external programs if an +appropriate library was not available at build time. +Decompression using an external program is usually slower +than decompression through built-in libraries. Note that +’’none’’ is always enabled by +default.

+ +

archive_read_support_filter_all()

+ +

Enables all available +decompression filters.

+ +

archive_read_support_filter_program()

+ +

Data is fed through the +specified external program before being dearchived. Note +that this disables automatic detection of the compression +format, so it makes no sense to specify this in conjunction +with any other decompression option.

+ + +

archive_read_support_filter_program_signature()

+ +

This feeds data through the +specified external program but only if the initial bytes of +the data match the specified signature value.

+ +

RETURN VALUES

+ +

These functions return +ARCHIVE_OK if the compression is fully supported, +ARCHIVE_WARN if the compression is supported only +through an external program.

+ + +

archive_read_support_filter_none() +always succeeds.

+ +

ERRORS

+ +

Detailed error codes and textual +descriptions are available from the archive_errno() +and archive_error_string() functions.

+ +

SEE ALSO

+ +

archive_read(3), +archive_read_data(3), archive_read_format(3), +archive_read_format(3), libarchive(3)

+ +

BSD +August 14, 2014 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_read_format.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_read_format.3.html new file mode 100644 index 0000000..197fc23 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_read_format.3.html @@ -0,0 +1,227 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_READ_FORMAT(3) BSD Library Functions Manual +ARCHIVE_READ_FORMAT(3)

+ +

NAME

+ + +

archive_read_support_format_7zip, +archive_read_support_format_all, +archive_read_support_format_ar, +archive_read_support_format_by_code, +archive_read_support_format_cab, +archive_read_support_format_cpio, +archive_read_support_format_empty, +archive_read_support_format_iso9660, +archive_read_support_format_lha, +archive_read_support_format_mtree, +archive_read_support_format_rar, +archive_read_support_format_raw, +archive_read_support_format_tar, +archive_read_support_format_xar, +archive_read_support_format_zip — functions for +reading streaming archives

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive.h>

+ +

int

+ + +

archive_read_support_format_7zip(struct archive *);

+ +

int

+ + +

archive_read_support_format_all(struct archive *);

+ +

int

+ + +

archive_read_support_format_ar(struct archive *);

+ +

int

+ + +

archive_read_support_format_by_code(struct archive *, +int);

+ +

int

+ + +

archive_read_support_format_cab(struct archive *);

+ +

int

+ + +

archive_read_support_format_cpio(struct archive *);

+ +

int

+ + +

archive_read_support_format_empty(struct archive *);

+ +

int

+ + +

archive_read_support_format_iso9660(struct archive *);

+ +

int

+ + +

archive_read_support_format_lha(struct archive *);

+ +

int

+ + +

archive_read_support_format_mtree(struct archive *);

+ +

int

+ + +

archive_read_support_format_rar(struct archive *);

+ +

int

+ + +

archive_read_support_format_raw(struct archive *);

+ +

int

+ + +

archive_read_support_format_tar(struct archive *);

+ +

int

+ + +

archive_read_support_format_xar(struct archive *);

+ +

int

+ + +

archive_read_support_format_zip(struct archive *);

+ +

DESCRIPTION
+archive_read_support_format_7zip
(), +archive_read_support_format_ar(), +archive_read_support_format_cab(), +archive_read_support_format_cpio(), +archive_read_support_format_iso9660(), +archive_read_support_format_lha(), +archive_read_support_format_mtree(), +archive_read_support_format_rar(), +archive_read_support_format_raw(), +archive_read_support_format_tar(), +archive_read_support_format_xar(), +archive_read_support_format_zip()

+ +

Enables support---including +auto-detection code---for the specified archive format. For +example, archive_read_support_format_tar() enables +support for a variety of standard tar formats, old-style +tar, ustar, pax interchange format, and many common +variants.

+ +

archive_read_support_format_all()

+ +

Enables support for all +available formats except the ’’raw’’ +format (see below).

+ +

archive_read_support_format_by_code()

+ +

Enables a single format +specified by the format code. This can be useful when +reading a single archive twice; use archive_format() +after reading the first time and pass the resulting code to +this function to selectively enable only the necessary +format support. Note: In statically-linked executables, this +will cause your program to include support for every format. +If executable size is a concern, you may wish to avoid using +this function.

+ +

archive_read_support_format_empty()

+ +

Enables support for treating +empty files as empty archives. Because empty files are valid +for several different formats, it is not possible to +accurately determine a format for an empty file based purely +on contents. So empty files are treated by libarchive as a +distinct format.

+ +

archive_read_support_format_raw()

+ +

The +’’raw’’ format handler allows +libarchive to be used to read arbitrary data. It treats any +data stream as an archive with a single entry. The pathname +of this entry is ’’data’’; all other +entry fields are unset. This is not enabled by +archive_read_support_format_all() in order to avoid +erroneous handling of damaged archives.

+ +

RETURN VALUES

+ +

These functions return +ARCHIVE_OK on success, or ARCHIVE_FATAL.

+ +

ERRORS

+ +

Detailed error codes and textual +descriptions are available from the archive_errno() +and archive_error_string() functions.

+ +

SEE ALSO

+ +

tar(1), archive_read_data(3), +archive_read_filter(3), archive_read_set_options(3), +archive_util(3), libarchive(3), tar(5)

+ +

BUGS

+ +

Many traditional archiver +programs treat empty files as valid empty archives. For +example, many implementations of tar(1) allow you to append +entries to an empty file. Of course, it is impossible to +determine the format of an empty file by inspecting the +contents, so this library treats empty files as having a +special ’’empty’’ format.

+ +

Using the +’’raw’’ handler together with any +other handler will often work but can produce surprising +results.

+ +

BSD +February 2, 2012 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_read_free.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_read_free.3.html new file mode 100644 index 0000000..d16f30a --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_read_free.3.html @@ -0,0 +1,107 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_READ_FREE(3) BSD Library Functions Manual +ARCHIVE_READ_FREE(3)

+ +

NAME

+ +

archive_read_close, +archive_read_finish, archive_read_free — +functions for reading streaming archives

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive.h>

+ +

int

+ + +

archive_read_close(struct archive *);

+ +

int

+ + +

archive_read_finish(struct archive *);

+ +

int

+ + +

archive_read_free(struct archive *);

+ +

DESCRIPTION
+archive_read_close
()

+ +

Complete the archive and invoke +the close callback.

+ +

archive_read_finish()

+ +

This is a deprecated synonym +for archive_read_free(). The new name was introduced +with libarchive 3.0. Applications that need to compile with +either libarchive 2 or libarchive 3 should continue to use +the archive_read_finish() name. Both names will be +supported until libarchive 4.0 is released, which is not +expected to occur earlier than 2013.

+ +

archive_read_free()

+ +

Invokes +archive_read_close() if it was not invoked manually, +then release all resources. Note: In libarchive 1.x, this +function was declared to return void, which made it +impossible to detect certain errors when +archive_read_close() was invoked implicitly from this +function. The declaration is corrected beginning with +libarchive 2.0.

+ +

RETURN VALUES

+ +

These functions return +ARCHIVE_OK on success, or ARCHIVE_FATAL.

+ +

ERRORS

+ +

Detailed error codes and textual +descriptions are available from the archive_errno() +and archive_error_string() functions.

+ +

SEE ALSO

+ +

archive_read_data(3), +archive_read_filter(3), archive_read_format(3), +archive_read_new(3), archive_read_open(3), +archive_read_set_options(3), archive_util(3), +libarchive(3)

+ +

BSD +February 2, 2012 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_read_header.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_read_header.3.html new file mode 100644 index 0000000..a1a0dd4 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_read_header.3.html @@ -0,0 +1,98 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_READ_HEADER(3) BSD Library Functions Manual +ARCHIVE_READ_HEADER(3)

+ +

NAME

+ + +

archive_read_next_header, +archive_read_next_header2 — functions for +reading streaming archives

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive.h>

+ +

int

+ + +

archive_read_next_header(struct archive *, +struct archive_entry **);

+ +

int

+ + +

archive_read_next_header2(struct archive *, +struct archive_entry *);

+ +

DESCRIPTION
+archive_read_next_header
()

+ +

Read the header for the next +entry and return a pointer to a struct archive_entry. This +is a convenience wrapper around +archive_read_next_header2() that reuses an internal +struct archive_entry object for each request.

+ +

archive_read_next_header2()

+ +

Read the header for the next +entry and populate the provided struct archive_entry.

+ +

RETURN VALUES

+ +

These functions return +ARCHIVE_OK (the operation succeeded), +ARCHIVE_WARN (the operation succeeded but a +non-critical error was encountered), ARCHIVE_EOF +(end-of-archive was encountered), ARCHIVE_RETRY (the +operation failed but can be retried), and +ARCHIVE_FATAL (there was a fatal error; the archive +should be closed immediately).

+ +

ERRORS

+ +

Detailed error codes and textual +descriptions are available from the archive_errno() +and archive_error_string() functions.

+ +

SEE ALSO

+ +

tar(1), archive_read(3), +archive_read_data(3), archive_read_extract(3), +archive_read_filter(3), archive_read_format(3), +archive_read_open(3), archive_read_set_options(3), +archive_util(3), libarchive(3), tar(5)

+ +

BSD +February 2, 2012 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_read_new.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_read_new.3.html new file mode 100644 index 0000000..6841a05 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_read_new.3.html @@ -0,0 +1,68 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_READ_NEW(3) BSD Library Functions Manual +ARCHIVE_READ_NEW(3)

+ +

NAME

+ +

archive_read_new — +functions for reading streaming archives

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive.h>

+ +

struct +archive *

+ + +

archive_read_new(void);

+ +

DESCRIPTION

+ +

Allocates and initializes a +struct archive object suitable for reading from an archive. +NULL is returned on error.

+ +

A complete +description of the struct archive object can be found in the +overview manual page for libarchive(3).

+ +

SEE ALSO

+ +

tar(1), archive_read_data(3), +archive_read_filter(3), archive_read_format(3), +archive_read_set_options(3), archive_util(3), libarchive(3), +tar(5)

+ +

BSD +February 2, 2012 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_read_open.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_read_open.3.html new file mode 100644 index 0000000..25ade61 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_read_open.3.html @@ -0,0 +1,240 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_READ_OPEN(3) BSD Library Functions Manual +ARCHIVE_READ_OPEN(3)

+ +

NAME

+ +

archive_read_open, +archive_read_open2, archive_read_open_fd, +archive_read_open_FILE, +archive_read_open_filename, +archive_read_open_memory — functions for +reading streaming archives

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive.h>

+ +

int

+ + +

archive_read_open(struct archive *, +void *client_data, +archive_open_callback *, +archive_read_callback *, +archive_close_callback *);

+ +

int

+ + +

archive_read_open2(struct archive *, +void *client_data, +archive_open_callback *, +archive_read_callback *, +archive_skip_callback *, +archive_close_callback *);

+ +

int

+ + +

archive_read_open_FILE(struct archive *, +FILE *file);

+ +

int

+ + +

archive_read_open_fd(struct archive *, +int fd, size_t block_size);

+ +

int

+ + +

archive_read_open_filename(struct archive *, +const char *filename, +size_t block_size);

+ +

int

+ + +

archive_read_open_memory(struct archive *, +const void *buff, +size_t size);

+ +

DESCRIPTION
+archive_read_open
()

+ +

The same as +archive_read_open2(), except that the skip callback +is assumed to be NULL.

+ +

archive_read_open2()

+ +

Freeze the settings, open the +archive, and prepare for reading entries. This is the most +generic version of this call, which accepts four callback +functions. Most clients will want to use +archive_read_open_filename(), +archive_read_open_FILE(), +archive_read_open_fd(), or +archive_read_open_memory() instead. The library +invokes the client-provided functions to obtain raw bytes +from the archive.

+ +

archive_read_open_FILE()

+ +

Like +archive_read_open(), except that it accepts a FILE +* pointer. This function should not be used with tape +drives or other devices that require strict I/O +blocking.

+ +

archive_read_open_fd()

+ +

Like +archive_read_open(), except that it accepts a file +descriptor and block size rather than a set of function +pointers. Note that the file descriptor will not be +automatically closed at end-of-archive. This function is +safe for use with tape drives or other blocked devices.

+ +

archive_read_open_file()

+ +

This is a deprecated synonym +for archive_read_open_filename().

+ +

archive_read_open_filename()

+ +

Like +archive_read_open(), except that it accepts a simple +filename and a block size. A NULL filename represents +standard input. This function is safe for use with tape +drives or other blocked devices.

+ +

archive_read_open_memory()

+ +

Like +archive_read_open(), except that it accepts a pointer +and size of a block of memory containing the archive +data.

+ +

A complete +description of the struct archive and struct archive_entry +objects can be found in the overview manual page for +libarchive(3).

+ +

CLIENT CALLBACKS

+ +

The callback functions must +match the following prototypes:

+ +

typedef +la_ssize_t

+ + +

archive_read_callback(struct archive *, +void *client_data, +const void **buffer)

+ +

typedef +la_int64_t

+ + +

archive_skip_callback(struct archive *, +void *client_data, +off_t request)

+ +

typedef +int archive_open_callback(struct archive +*, void *client_data)

+ +

typedef +int archive_close_callback(struct archive +*, void *client_data)

+ +

The open +callback is invoked by archive_open(). It should +return ARCHIVE_OK if the underlying file or data +source is successfully opened. If the open fails, it should +call archive_set_error() to register an error code +and message and return ARCHIVE_FATAL.

+ +

The read +callback is invoked whenever the library requires raw bytes +from the archive. The read callback should read data into a +buffer, set the const void **buffer argument to point to the +available data, and return a count of the number of bytes +available. The library will invoke the read callback again +only after it has consumed this data. The library imposes no +constraints on the size of the data blocks returned. On +end-of-file, the read callback should return zero. On error, +the read callback should invoke archive_set_error() +to register an error code and message and return -1.

+ +

The skip +callback is invoked when the library wants to ignore a block +of data. The return value is the number of bytes actually +skipped, which may differ from the request. If the callback +cannot skip data, it should return zero. If the skip +callback is not provided (the function pointer is NULL ), +the library will invoke the read function instead and simply +discard the result. A skip callback can provide significant +performance gains when reading uncompressed archives from +slow disk drives or other media that can skip quickly.

+ +

The close +callback is invoked by archive_close when the archive +processing is complete. The callback should return +ARCHIVE_OK on success. On failure, the callback +should invoke archive_set_error() to register an +error code and message and return ARCHIVE_FATAL.

+ +

RETURN VALUES

+ +

These functions return +ARCHIVE_OK on success, or ARCHIVE_FATAL.

+ +

ERRORS

+ +

Detailed error codes and textual +descriptions are available from the archive_errno() +and archive_error_string() functions.

+ +

SEE ALSO

+ +

tar(1), archive_read(3), +archive_read_data(3), archive_read_filter(3), +archive_read_format(3), archive_read_set_options(3), +archive_util(3), libarchive(3), tar(5)

+ +

BSD +February 2, 2012 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_read_set_options.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_read_set_options.3.html new file mode 100644 index 0000000..861fb2c --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_read_set_options.3.html @@ -0,0 +1,252 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_READ_OPTIONS(3) BSD Library Functions Manual +ARCHIVE_READ_OPTIONS(3)

+ +

NAME

+ + +

archive_read_set_filter_option, +archive_read_set_format_option, +archive_read_set_option, +archive_read_set_options — functions +controlling options for reading archives

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

int

+ + +

archive_read_set_filter_option(struct archive *, +const char *module, +const char *option, +const char *value);

+ +

int

+ + +

archive_read_set_format_option(struct archive *, +const char *module, +const char *option, +const char *value);

+ +

int

+ + +

archive_read_set_option(struct archive *, +const char *module, +const char *option, +const char *value);

+ +

int

+ + +

archive_read_set_options(struct archive *, +const char *options);

+ +

DESCRIPTION

+ +

These functions provide a way +for libarchive clients to configure specific read +modules.

+ + +

archive_read_set_filter_option(), +archive_read_set_format_option()

+ +

Specifies an option that will +be passed to currently-registered filters (including +decompression filters) or format readers.

+ +

If +option and value are both NULL, these +functions will do nothing and ARCHIVE_OK will be +returned. If option is NULL but value is not, +these functions will do nothing and ARCHIVE_FAILED +will be returned.

+ +

If +module is not NULL, option and value +will be provided to the filter or reader named +module. The return value will be that of the module. +If there is no such module, ARCHIVE_FAILED will be +returned.

+ +

If +module is NULL, option and value will +be provided to every registered module. If any module +returns ARCHIVE_FATAL, this value will be returned +immediately. Otherwise, ARCHIVE_OK will be returned +if any module accepts the option, and ARCHIVE_FAILED +in all other cases.

+ + +

archive_read_set_option()

+ +

Calls +archive_read_set_format_option(), then +archive_read_set_filter_option(). If either function +returns ARCHIVE_FATAL, ARCHIVE_FATAL will be +returned immediately. Otherwise, greater of the two values +will be returned.

+ + +

archive_read_set_options()

+ +

options is a +comma-separated list of options. If options is NULL +or empty, ARCHIVE_OK will be returned +immediately.

+ +

Calls +archive_read_set_option() with each option in turn. +If any archive_read_set_option() call returns +ARCHIVE_FATAL, ARCHIVE_FATAL will be returned +immediately.

+ +

Individual +options have one of the following forms:

+ +

option=value

+ +

The option/value pair will be +provided to every module. Modules that do not accept an +option with this name will ignore it.

+ +

option

+ +

The option will +be provided to every module with a value of +’’1’’.

+ +

!option

+ +

The option will be provided to +every module with a NULL value.

+ +

module:option=value, module:option, +module:!option

+ +

As above, but the corresponding +option and value will be provided only to modules whose name +matches module.

+ +

OPTIONS
+Format cab
+hdrcharset

+ +

The value is used as a +character set name that will be used when translating file +names.

+ +

Format cpio
+hdrcharset

+ +

The value is used as a +character set name that will be used when translating file +names.

+ +

Format iso9660
+joliet

+ +

Support Joliet +extensions. Defaults to enabled, use !joliet to +disable.

+ +

rockridge

+ +

Support RockRidge extensions. +Defaults to enabled, use !rockridge to disable.

+ +

Format lha
+hdrcharset

+ +

The value is used as a +character set name that will be used when translating file +names.

+ +

Format mtree
+checkfs

+ +

Allow reading information +missing from the mtree from the file system. Disabled by +default.

+ +

Format rar
+hdrcharset

+ +

The value is used as a +character set name that will be used when translating file +names.

+ +

Format tar
+compat-2x

+ +

Libarchive 2.x incorrectly +encoded Unicode filenames on some platforms. This option +mimics the libarchive 2.x filename handling so that such +archives can be read correctly.

+ +

hdrcharset

+ +

The value is used as a +character set name that will be used when translating file +names.

+ +

mac-ext

+ +

Support Mac OS metadata +extension that records data in special files beginning with +a period and underscore. Defaults to enabled on Mac OS, +disabled on other platforms. Use !mac-ext to +disable.

+ +

read_concatenated_archives

+ +

Ignore zeroed blocks in the +archive, which occurs when multiple tar archives have been +concatenated together. Without this option, only the +contents of the first concatenated archive would be +read.

+ +

ERRORS

+ +

Detailed error codes and textual +descriptions are available from the archive_errno() +and archive_error_string() functions.

+ +

SEE ALSO

+ +

tar(1), archive_read(3), +archive_write_set_options(3), libarchive(3)

+ +

BSD +January 31, 2020 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_util.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_util.3.html new file mode 100644 index 0000000..d8701fb --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_util.3.html @@ -0,0 +1,293 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_UTIL(3) BSD Library Functions Manual +ARCHIVE_UTIL(3)

+ +

NAME

+ +

archive_clear_error, +archive_compression, archive_compression_name, +archive_copy_error, archive_errno, +archive_error_string, archive_file_count, +archive_filter_code, archive_filter_count, +archive_filter_name, archive_format, +archive_format_name, archive_position, +archive_set_error — libarchive utility +functions

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive.h>

+ +

void

+ + +

archive_clear_error(struct archive *);

+ +

int

+ + +

archive_compression(struct archive *);

+ +

const char +*

+ + +

archive_compression_name(struct archive *);

+ +

void

+ + +

archive_copy_error(struct archive *, +struct archive *);

+ +

int

+ + +

archive_errno(struct archive *);

+ +

const char +*

+ + +

archive_error_string(struct archive *);

+ +

int

+ + +

archive_file_count(struct archive *);

+ +

int

+ + +

archive_filter_code(struct archive *, +int);

+ +

int

+ + +

archive_filter_count(struct archive *, +int);

+ +

const char +*

+ + +

archive_filter_name(struct archive *, +int);

+ +

int

+ + +

archive_format(struct archive *);

+ +

const char +*

+ + +

archive_format_name(struct archive *);

+ + +

int64_t

+ + +

archive_position(struct archive *, +int);

+ +

void

+ + +

archive_set_error(struct archive *, +int error_code, +const char *fmt, ...);

+ +

DESCRIPTION

+ +

These functions provide access +to various information about the struct archive object used +in the libarchive(3) library.

+ +

archive_clear_error()

+ +

Clears any error information +left over from a previous call. Not generally used in client +code.

+ +

archive_compression()

+ +

Synonym for +archive_filter_code(a, 0).

+ +

archive_compression_name()

+ +

Synonym for +archive_filter_name(a, 0).

+ +

archive_copy_error()

+ +

Copies error information from +one archive to another.

+ +

archive_errno()

+ +

Returns a numeric error code +(see errno(2)) indicating the reason for the most recent +error return. Note that this can not be reliably used to +detect whether an error has occurred. It should be used only +after another libarchive function has returned an error +status.

+ +

archive_error_string()

+ +

Returns a textual error message +suitable for display. The error message here is usually more +specific than that obtained from passing the result of +archive_errno() to strerror(3).

+ +

archive_file_count()

+ +

Returns a count of the number +of files processed by this archive object. The count is +incremented by calls to archive_write_header(3) or +archive_read_next_header(3).

+ +

archive_filter_code()

+ +

Returns a numeric code +identifying the indicated filter. See +archive_filter_count() for details of the +numbering.

+ +

archive_filter_count()

+ +

Returns the number of filters +in the current pipeline. For read archive handles, these +filters are added automatically by the automatic format +detection. For write archive handles, these filters are +added by calls to the various +archive_write_add_filter_XXX() functions. Filters in +the resulting pipeline are numbered so that filter 0 is the +filter closest to the format handler. As a convenience, +functions that expect a filter number will accept -1 as a +synonym for the highest-numbered filter.

+ +

For example, +when reading a uuencoded gzipped tar archive, there are +three filters: filter 0 is the gunzip filter, filter 1 is +the uudecode filter, and filter 2 is the pseudo-filter that +wraps the archive read functions. In this case, requesting +archive_position(a, -1) would be a +synonym for archive_position(a, 2) +which would return the number of bytes currently read from +the archive, while archive_position(a, +1) would return the number of bytes after uudecoding, +and archive_position(a, 0) would return +the number of bytes after decompression.

+ +

archive_filter_name()

+ +

Returns a textual name +identifying the indicated filter. See +archive_filter_count() for details of the +numbering.

+ +

archive_format()

+ +

Returns a numeric code +indicating the format of the current archive entry. This +value is set by a successful call to +archive_read_next_header(). Note that it is common +for this value to change from entry to entry. For example, a +tar archive might have several entries that utilize GNU tar +extensions and several entries that do not. These entries +will have different format codes.

+ +

archive_format_name()

+ +

A textual description of the +format of the current entry.

+ +

archive_position()

+ +

Returns the number of bytes +read from or written to the indicated filter. In particular, +archive_position(a, 0) returns the +number of bytes read or written by the format handler, while +archive_position(a, -1) returns the +number of bytes read or written to the archive. See +archive_filter_count() for details of the numbering +here.

+ +

archive_set_error()

+ +

Sets the numeric error code and +error description that will be returned by +archive_errno() and archive_error_string(). +This function should be used within I/O callbacks to set +system-specific error codes and error descriptions. This +function accepts a printf-like format string and arguments. +However, you should be careful to use only the following +printf format specifiers: ’’%c’’, +’’%d’’, +’’%jd’’, +’’%jo’’, +’’%ju’’, +’’%jx’’, +’’%ld’’, +’’%lo’’, +’’%lu’’, +’’%lx’’, +’’%o’’, +’’%u’’, +’’%s’’, +’’%x’’, +’’%%’’. Field-width specifiers and +other printf features are not uniformly supported and should +not be used.

+ +

SEE ALSO

+ +

archive_read(3), +archive_write(3), libarchive(3), printf(3)

+ +

HISTORY

+ +

The libarchive library +first appeared in FreeBSD 5.3.

+ +

AUTHORS

+ +

The libarchive library +was written by Tim Kientzle <kientzle@acm.org>.

+ +

BSD +February 2, 2012 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_write.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_write.3.html new file mode 100644 index 0000000..ccc5830 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_write.3.html @@ -0,0 +1,290 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_WRITE(3) BSD Library Functions Manual +ARCHIVE_WRITE(3)

+ +

NAME

+ +

archive_write — +functions for creating archives

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive.h>

+ +

DESCRIPTION

+ +

These functions provide a +complete API for creating streaming archive files. The +general process is to first create the struct archive +object, set any desired options, initialize the archive, +append entries, then close the archive and release all +resources.

+ +

Create +archive object
+See archive_write_new(3).

+ +

To write an +archive, you must first obtain an initialized struct archive +object from archive_write_new().

+ +

Enable +filters and formats, configure block size and padding +
+See archive_write_filter(3), archive_write_format(3) and +archive_write_blocksize(3).

+ +

You can then +modify this object for the desired operations with the +various archive_write_set_XXX() functions. In +particular, you will need to invoke appropriate +archive_write_add_XXX() and +archive_write_set_XXX() functions to enable the +corresponding compression and format support.

+ +

Set +options
+See archive_write_set_options(3).

+ +

Open +archive
+See archive_write_open(3).

+ +

Once you have +prepared the struct archive object, you call +archive_write_open() to actually open the archive and +prepare it for writing. There are several variants of this +function; the most basic expects you to provide pointers to +several functions that can provide blocks of bytes from the +archive. There are convenience forms that allow you to +specify a filename, file descriptor, FILE * object, +or a block of memory from which to write the archive +data.

+ +

Produce +archive
+See archive_write_header(3) and archive_write_data(3).

+ +

Individual +archive entries are written in a three-step process: You +first initialize a struct archive_entry structure with +information about the new entry. At a minimum, you should +set the pathname of the entry and provide a struct +stat with a valid st_mode field, which specifies +the type of object and st_size field, which specifies +the size of the data portion of the object.

+ +

Release +resources
+See archive_write_free(3).

+ +

After all +entries have been written, use the +archive_write_free() function to release all +resources.

+ +

EXAMPLES

+ +

The following sketch illustrates +basic usage of the library. In this example, the callback +functions are simply wrappers around the standard open(2), +write(2), and close(2) system calls.

+ +

#ifdef +__linux__

+ + + + + + + +
+ + +

#define

+ + +

_FILE_OFFSET_BITS 64

+
+ +

#endif
+#include <sys/stat.h>
+#include <archive.h>
+#include <archive_entry.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>

+ +

struct mydata { +
+const char *name;
+int fd;
+};

+ +

int
+myopen(struct archive *a, void *client_data)
+{
+struct mydata *mydata = client_data;

+ +

mydata->fd = +open(mydata->name, O_WRONLY | O_CREAT, 0644);
+if (mydata->fd >= 0)
+return (ARCHIVE_OK);
+else
+return (ARCHIVE_FATAL);
+}

+ +

la_ssize_t
+mywrite(struct archive *a, void *client_data, const void +*buff, size_t n)
+{
+struct mydata *mydata = client_data;

+ +

return +(write(mydata->fd, buff, n));
+}

+ +

int
+myclose(struct archive *a, void *client_data)
+{
+struct mydata *mydata = client_data;

+ +

if +(mydata->fd > 0)
+close(mydata->fd);
+return (0);
+}

+ +

void
+write_archive(const char *outname, const char **filename) +
+{
+struct mydata *mydata = malloc(sizeof(struct mydata));
+struct archive *a;
+struct archive_entry *entry;
+struct stat st;
+char buff[8192];
+int len;
+int fd;

+ +

a = +archive_write_new();
+mydata->name = outname;
+/* Set archive format and filter according to output file +extension.
+* If it fails, set default format. Platform depended +function.
+* See supported formats in +archive_write_set_format_filter_by_ext.c */
+if (archive_write_set_format_filter_by_ext(a, outname) != +ARCHIVE_OK) {
+archive_write_add_filter_gzip(a);
+archive_write_set_format_ustar(a);
+}
+archive_write_open(a, mydata, myopen, mywrite, myclose); +
+while (*filename) {
+stat(*filename, &st);
+entry = archive_entry_new();
+archive_entry_copy_stat(entry, &st);
+archive_entry_set_pathname(entry, *filename);
+archive_write_header(a, entry);
+if ((fd = open(*filename, O_RDONLY)) != -1) {
+len = read(fd, buff, sizeof(buff));
+while (len > 0) {
+archive_write_data(a, buff, len);
+len = read(fd, buff, sizeof(buff));
+}
+close(fd);
+}
+archive_entry_free(entry);
+filename++;
+}
+archive_write_free(a);
+}

+ +

int main(int +argc, const char **argv)
+{
+const char *outname;
+argv++;
+outname = *argv++;
+write_archive(outname, argv);
+return 0;
+}

+ +

SEE ALSO

+ +

tar(1), +archive_write_set_options(3), libarchive(3), cpio(5), +mtree(5), tar(5)

+ +

HISTORY

+ +

The libarchive library +first appeared in FreeBSD 5.3.

+ +

AUTHORS

+ +

The libarchive library +was written by Tim Kientzle <kientzle@acm.org>.

+ +

BUGS

+ +

There are many peculiar bugs in +historic tar implementations that may cause certain programs +to reject archives written by this library. For example, +several historic implementations calculated header checksums +incorrectly and will thus reject valid archives; GNU tar +does not fully support pax interchange format; some old tar +implementations required specific field terminations.

+ +

The default pax +interchange format eliminates most of the historic tar +limitations and provides a generic key/value attribute +facility for vendor-defined extensions. One oversight in +POSIX is the failure to provide a standard attribute for +large device numbers. This library uses +’’SCHILY.devminor’’ and +’’SCHILY.devmajor’’ for device +numbers that exceed the range supported by the +backwards-compatible ustar header. These keys are compatible +with Joerg Schilling’s star archiver. Other +implementations may not recognize these keys and will thus +be unable to correctly restore device nodes with large +device numbers from archives created by this library.

+ +

BSD +February 2, 2012 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_write_blocksize.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_write_blocksize.3.html new file mode 100644 index 0000000..5548a0a --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_write_blocksize.3.html @@ -0,0 +1,141 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_WRITE_BLOCKSI... BSD Library Functions Manual +ARCHIVE_WRITE_BLOCKSI...

+ +

NAME

+ + +

archive_write_get_bytes_per_block, +archive_write_set_bytes_per_block, +archive_write_get_bytes_in_last_block, +archive_write_set_bytes_in_last_block — +functions for creating archives

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive.h>

+ +

int

+ + +

archive_write_get_bytes_per_block(struct archive *);

+ +

int

+ + +

archive_write_set_bytes_per_block(struct archive *, +int bytes_per_block);

+ +

int

+ + +

archive_write_get_bytes_in_last_block(struct archive *);

+ +

int

+ + +

archive_write_set_bytes_in_last_block(struct archive *, +int);

+ +

DESCRIPTION
+archive_write_set_bytes_per_block
()

+ +

Sets the block size used for +writing the archive data. Every call to the write callback +function, except possibly the last one, will use this value +for the length. The default is to use a block size of 10240 +bytes. Note that a block size of zero will suppress internal +blocking and cause writes to be sent directly to the write +callback as they occur.

+ + +

archive_write_get_bytes_per_block()

+ +

Retrieve the block size to be +used for writing. A value of -1 here indicates that the +library should use default values. A value of zero indicates +that internal blocking is suppressed.

+ + +

archive_write_set_bytes_in_last_block()

+ +

Sets the block size used for +writing the last block. If this value is zero, the last +block will be padded to the same size as the other blocks. +Otherwise, the final block will be padded to a multiple of +this size. In particular, setting it to 1 will cause the +final block to not be padded. For compressed output, any +padding generated by this option is applied only after the +compression. The uncompressed data is always unpadded. The +default is to pad the last block to the full block size +(note that archive_write_open_filename() will set +this based on the file type). Unlike the other +’’set’’ functions, this function can +be called after the archive is opened.

+ + +

archive_write_get_bytes_in_last_block()

+ +

Retrieve the currently-set +value for last block size. A value of -1 here indicates that +the library should use default values.

+ +

RETURN VALUES

+ + +

archive_write_set_bytes_per_block() +and archive_write_set_bytes_in_last_block() return +ARCHIVE_OK on success, or ARCHIVE_FATAL.

+ + +

archive_write_get_bytes_per_block() +and archive_write_get_bytes_in_last_block() return +currently configured block size (

+ +

-1 indicates the default block size ), or +ARCHIVE_FATAL.

+ +

ERRORS

+ +

Detailed error codes and textual +descriptions are available from the archive_errno() +and archive_error_string() functions.

+ +

SEE ALSO

+ +

tar(1), +archive_write_set_options(3), libarchive(3), cpio(5), +mtree(5), tar(5)

+ +

BSD +February 2, 2012 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_write_data.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_write_data.3.html new file mode 100644 index 0000000..9984207 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_write_data.3.html @@ -0,0 +1,107 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_WRITE_DATA(3) BSD Library Functions Manual +ARCHIVE_WRITE_DATA(3)

+ +

NAME

+ +

archive_write_data, +archive_write_data_block — functions for +creating archives

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive.h>

+ + +

la_ssize_t

+ + +

archive_write_data(struct archive *, +const void *, size_t);

+ + +

la_ssize_t

+ + +

archive_write_data_block(struct archive *, +const void *, size_t size, +int64_t offset);

+ +

DESCRIPTION
+archive_write_data
()

+ +

Write data corresponding to the +header just written.

+ + +

archive_write_data_block()

+ +

Write data corresponding to the +header just written. This is like +archive_write_data() except that it performs a seek +on the file being written to the specified offset before +writing the data. This is useful when restoring sparse files +from archive formats that support sparse files. Returns +number of bytes written or -1 on error. (Note: This is +currently not supported for archive_write handles, only for +archive_write_disk handles.

+ +

RETURN VALUES

+ +

This function returns the number +of bytes actually written, or a negative error code on +error.

+ +

ERRORS

+ +

Detailed error codes and textual +descriptions are available from the archive_errno() +and archive_error_string() functions.

+ +

BUGS

+ +

In libarchive 3.x, this function +sometimes returns zero on success instead of returning the +number of bytes written. Specifically, this occurs when +writing to an archive_write_disk handle. Clients +should treat any value less than zero as an error and +consider any non-negative value as success.

+ +

SEE ALSO

+ +

tar(1), +archive_write_finish_entry(3), archive_write_set_options(3), +libarchive(3), cpio(5), mtree(5), tar(5)

+ +

BSD +February 28, 2017 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_write_disk.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_write_disk.3.html new file mode 100644 index 0000000..6936137 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_write_disk.3.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_WRITE_DISK(3) BSD Library Functions Manual +ARCHIVE_WRITE_DISK(3)

+ +

NAME

+ +

archive_write_disk_new, +archive_write_disk_set_options, +archive_write_disk_set_skip_file, +archive_write_disk_set_group_lookup, +archive_write_disk_set_standard_lookup, +archive_write_disk_set_user_lookup — functions +for creating objects on disk

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive.h>

+ +

struct +archive *

+ + +

archive_write_disk_new(void);

+ +

int

+ + +

archive_write_disk_set_options(struct archive *, +int flags);

+ +

int

+ + +

archive_write_disk_set_skip_file(struct archive *, +dev_t, ino_t);

+ +

int

+ + +

archive_write_disk_set_group_lookup(struct archive *, +void *, +gid_t (*)(void *, const char *gname, gid_t gid), +void (*cleanup)(void *));

+ +

int

+ + +

archive_write_disk_set_standard_lookup(struct archive *);

+ +

int

+ + +

archive_write_disk_set_user_lookup(struct archive *, +void *, +uid_t (*)(void *, const char *uname, uid_t uid), +void (*cleanup)(void *));

+ +

DESCRIPTION

+ +

These functions provide a +complete API for creating objects on disk from struct +archive_entry descriptions. They are most naturally used +when extracting objects from an archive using the +archive_read() interface. The general process is to +read struct archive_entry objects from an archive, then +write those objects to a struct archive object created using +the archive_write_disk() family functions. This +interface is deliberately very similar to the +archive_write() interface used to write objects to a +streaming archive.

+ + +

archive_write_disk_new()

+ +

Allocates and initializes a +struct archive object suitable for writing objects to +disk.

+ + +

archive_write_disk_set_skip_file()

+ +

Records the device and inode +numbers of a file that should not be overwritten. This is +typically used to ensure that an extraction process does not +overwrite the archive from which objects are being read. +This capability is technically unnecessary but can be a +significant performance optimization in practice.

+ + +

archive_write_disk_set_options()

+ +

The options field consists of a +bitwise OR of one or more of the following values:

+ +

ARCHIVE_EXTRACT_ACL

+ +

Attempt to restore Access +Control Lists. By default, extended ACLs are ignored.

+ +

ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS

+ +

Before removing a file system +object prior to replacing it, clear platform-specific file +flags which might prevent its removal.

+ +

ARCHIVE_EXTRACT_FFLAGS

+ +

Attempt to restore file +attributes (file flags). By default, file attributes are +ignored. See chattr(1) (Linux) or chflags(1) (FreeBSD, Mac +OS X) for more information on file attributes.

+ +

ARCHIVE_EXTRACT_MAC_METADATA

+ +

Mac OS X specific. Restore +metadata using copyfile(3). By default, copyfile(3) metadata +is ignored.

+ +

ARCHIVE_EXTRACT_NO_OVERWRITE

+ +

Existing files on disk will not +be overwritten. By default, existing regular files are +truncated and overwritten; existing directories will have +their permissions updated; other pre-existing objects are +unlinked and recreated from scratch.

+ +

ARCHIVE_EXTRACT_OWNER

+ +

The user and group IDs should +be set on the restored file. By default, the user and group +IDs are not restored.

+ +

ARCHIVE_EXTRACT_PERM

+ +

Full permissions (including +SGID, SUID, and sticky bits) should be restored exactly as +specified, without obeying the current umask. Note that SUID +and SGID bits can only be restored if the user and group ID +of the object on disk are correct. If +ARCHIVE_EXTRACT_OWNER is not specified, then SUID and +SGID bits will only be restored if the default user and +group IDs of newly-created objects on disk happen to match +those specified in the archive entry. By default, only basic +permissions are restored, and umask is obeyed.

+ +

ARCHIVE_EXTRACT_SAFE_WRITES

+ +

Extract files atomically, by +first creating a unique temporary file and then renaming it +to its required destination name. This avoids a race where +an application might see a partial file (or no file) during +extraction.

+ +

ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS

+ +

Refuse to extract an absolute +path. The default is to not refuse such paths.

+ +

ARCHIVE_EXTRACT_SECURE_NODOTDOT

+ +

Refuse to extract a path that +contains a .. element anywhere within it. The default +is to not refuse such paths. Note that paths ending in +.. always cause an error, regardless of this +flag.

+ +

ARCHIVE_EXTRACT_SECURE_SYMLINKS

+ +

Refuse to extract any object +whose final location would be altered by a symlink on disk. +This is intended to help guard against a variety of mischief +caused by archives that (deliberately or otherwise) extract +files outside of the current directory. The default is not +to perform this check. If

+ +

ARCHIVE_EXTRACT_SPARSE

+ +

Scan data for blocks of NUL +bytes and try to recreate them with holes. This results in +sparse files, independent of whether the archive format +supports or uses them. ARCHIVE_EXTRACT_UNLINK is +specified together with this option, the library will remove +any intermediate symlinks it finds and return an error only +if such symlink could not be removed.

+ +

ARCHIVE_EXTRACT_TIME

+ +

The timestamps (mtime, ctime, +and atime) should be restored. By default, they are ignored. +Note that restoring of atime is not currently supported.

+ +

ARCHIVE_EXTRACT_UNLINK

+ +

Existing files on disk will be +unlinked before any attempt to create them. In some cases, +this can prove to be a significant performance improvement. +By default, existing files are truncated and rewritten, but +the file is not recreated. In particular, the default +behavior does not break existing hard links.

+ +

ARCHIVE_EXTRACT_XATTR

+ +

Attempt to restore extended +file attributes. By default, they are ignored. See xattr(7) +(Linux), xattr(2) (Mac OS X), or getextattr(8) (FreeBSD) for +more information on extended file attributes.

+ + +

archive_write_disk_set_group_lookup(), +archive_write_disk_set_user_lookup()

+ +

The struct archive_entry +objects contain both names and ids that can be used to +identify users and groups. These names and ids describe the +ownership of the file itself and also appear in ACL lists. +By default, the library uses the ids and ignores the names, +but this can be overridden by registering user and group +lookup functions. To register, you must provide a lookup +function which accepts both a name and id and returns a +suitable id. You may also provide a void * pointer to a +private data structure and a cleanup function for that data. +The cleanup function will be invoked when the struct archive +object is destroyed.

+ + +

archive_write_disk_set_standard_lookup()

+ +

This convenience function +installs a standard set of user and group lookup functions. +These functions use getpwnam(3) and getgrnam(3) to convert +names to ids, defaulting to the ids if the names cannot be +looked up. These functions also implement a simple memory +cache to reduce the number of calls to getpwnam(3) and +getgrnam(3).

+ +

More information about the +struct archive object and the overall design of the +library can be found in the libarchive(3) overview. Many of +these functions are also documented under +archive_write(3).

+ +

RETURN VALUES

+ +

Most functions return +ARCHIVE_OK (zero) on success, or one of several +non-zero error codes for errors. Specific error codes +include: ARCHIVE_RETRY for operations that might +succeed if retried, ARCHIVE_WARN for unusual +conditions that do not prevent further operations, and +ARCHIVE_FATAL for serious errors that make remaining +operations impossible.

+ + +

archive_write_disk_new() +returns a pointer to a newly-allocated struct archive +object.

+ + +

archive_write_data() +returns a count of the number of bytes actually written, or +-1 on error.

+ +

ERRORS

+ +

Detailed error codes and textual +descriptions are available from the archive_errno() +and archive_error_string() functions.

+ +

SEE ALSO

+ +

tar(1), archive_read(3), +archive_write(3), libarchive(3)

+ +

HISTORY

+ +

The libarchive library +first appeared in FreeBSD 5.3. The +archive_write_disk interface was added to +libarchive 2.0 and first appeared in +FreeBSD 6.3.

+ +

AUTHORS

+ +

The libarchive library +was written by Tim Kientzle <kientzle@acm.org>.

+ +

BUGS

+ +

Directories are actually +extracted in two distinct phases. Directories are created +during archive_write_header(), but final permissions +are not set until archive_write_close(). This +separation is necessary to correctly handle borderline cases +such as a non-writable directory containing files, but can +cause unexpected results. In particular, directory +permissions are not fully restored until the archive is +closed. If you use chdir(2) to change the current directory +between calls to archive_read_extract() or before +calling archive_read_close(), you may confuse the +permission-setting logic with the result that directory +permissions are restored incorrectly.

+ +

The library +attempts to create objects with filenames longer than +PATH_MAX by creating prefixes of the full path and +changing the current directory. Currently, this logic is +limited in scope; the fixup pass does not work correctly for +such objects and the symlink security check option disables +the support for very long pathnames.

+ +

Restoring the +path aa/../bb does create each intermediate +directory. In particular, the directory aa is created +as well as the final object bb. In theory, this can +be exploited to create an entire directory hierarchy with a +single request. Of course, this does not work if the +ARCHIVE_EXTRACT_NODOTDOT option is specified.

+ +

Implicit +directories are always created obeying the current umask. +Explicit objects are created obeying the current umask +unless ARCHIVE_EXTRACT_PERM is specified, in which +case they current umask is ignored.

+ +

SGID and SUID +bits are restored only if the correct user and group could +be set. If ARCHIVE_EXTRACT_OWNER is not specified, +then no attempt is made to set the ownership. In this case, +SGID and SUID bits are restored only if the user and group +of the final object happen to match those specified in the +entry.

+ +

The +’’standard’’ user-id and group-id +lookup functions are not the defaults because getgrnam(3) +and getpwnam(3) are sometimes too large for particular +applications. The current design allows the application +author to use a more compact implementation when +appropriate.

+ +

There should be +a corresponding archive_read_disk interface that +walks a directory hierarchy and returns archive entry +objects.

+ +

BSD +January 19, 2020 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_write_filter.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_write_filter.3.html new file mode 100644 index 0000000..9444515 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_write_filter.3.html @@ -0,0 +1,193 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_WRITE_FILTER(3) BSD Library Functions Manual +ARCHIVE_WRITE_FILTER(3)

+ +

NAME

+ + +

archive_write_add_filter_b64encode, +archive_write_add_filter_by_name, +archive_write_add_filter_bzip2, +archive_write_add_filter_compress, +archive_write_add_filter_grzip, +archive_write_add_filter_gzip, +archive_write_add_filter_lrzip, +archive_write_add_filter_lz4, +archive_write_add_filter_lzip, +archive_write_add_filter_lzma, +archive_write_add_filter_lzop, +archive_write_add_filter_none, +archive_write_add_filter_program, +archive_write_add_filter_uuencode, +archive_write_add_filter_xz, +archive_write_add_filter_zstd — functions +enabling output filters

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive.h>

+ +

int

+ + +

archive_write_add_filter_b64encode(struct archive *);

+ +

int

+ + +

archive_write_add_filter_bzip2(struct archive *);

+ +

int

+ + +

archive_write_add_filter_compress(struct archive *);

+ +

int

+ + +

archive_write_add_filter_grzip(struct archive *);

+ +

int

+ + +

archive_write_add_filter_gzip(struct archive *);

+ +

int

+ + +

archive_write_add_filter_lrzip(struct archive *);

+ +

int

+ + +

archive_write_add_filter_lz4(struct archive *);

+ +

int

+ + +

archive_write_add_filter_lzip(struct archive *);

+ +

int

+ + +

archive_write_add_filter_lzma(struct archive *);

+ +

int

+ + +

archive_write_add_filter_lzop(struct archive *);

+ +

int

+ + +

archive_write_add_filter_none(struct archive *);

+ +

int

+ + +

archive_write_add_filter_program(struct archive *, +const char * cmd);

+ +

int

+ + +

archive_write_add_filter_uuencode(struct archive *);

+ +

int

+ + +

archive_write_add_filter_xz(struct archive *);

+ +

int

+ + +

archive_write_add_filter_zstd(struct archive *);

+ +

DESCRIPTION
+archive_write_add_filter_bzip2
(), +archive_write_add_filter_compress(), +archive_write_add_filter_grzip(), +archive_write_add_filter_gzip(), +archive_write_add_filter_lrzip(), +archive_write_add_filter_lz4(), +archive_write_add_filter_lzip(), +archive_write_add_filter_lzma(), +archive_write_add_filter_lzop(), +archive_write_add_filter_xz(), +archive_write_add_filter_zstd(),

+ +

The resulting archive will be +compressed as specified. Note that the compressed output is +always properly blocked.

+ + +

archive_write_add_filter_b64encode(), +archive_write_add_filter_uuencode(),

+ +

The output will be encoded as +specified. The encoded output is always properly +blocked.

+ + +

archive_write_add_filter_none()

+ +

This is never necessary. It is +provided only for backwards compatibility.

+ + +

archive_write_add_filter_program()

+ +

The archive will be fed into +the specified compression program. The output of that +program is blocked and written to the client write +callbacks.

+ +

RETURN VALUES

+ +

These functions return +ARCHIVE_OK on success, or ARCHIVE_FATAL.

+ +

ERRORS

+ +

Detailed error codes and textual +descriptions are available from the archive_errno() +and archive_error_string() functions.

+ +

SEE ALSO

+ +

tar(1), archive_write(3), +archive_write_format(3), archive_write_set_options(3), +libarchive(3), cpio(5), mtree(5), tar(5)

+ +

BSD +August 14, 2014 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_write_finish_entry.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_write_finish_entry.3.html new file mode 100644 index 0000000..c3b6eda --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_write_finish_entry.3.html @@ -0,0 +1,85 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_WRITE_FINISH_... BSD Library Functions Manual +ARCHIVE_WRITE_FINISH_...

+ +

NAME

+ + +

archive_write_finish_entry +— functions for creating archives

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive.h>

+ +

int

+ + +

archive_write_finish_entry(struct archive *);

+ +

DESCRIPTION

+ +

Close out the entry just +written. In particular, this writes out the final padding +required by some formats. Ordinarily, clients never need to +call this, as it is called automatically by +archive_write_header() and +archive_write_close() as needed. For +archive_write_disk handles, this flushes pending file +attribute changes like modification time.

+ +

RETURN VALUES

+ +

This function returns +ARCHIVE_OK on success, or one of several non-zero +error codes for errors. Specific error codes include: +ARCHIVE_RETRY for operations that might succeed if +retried, ARCHIVE_WARN for unusual conditions that do +not prevent further operations, and ARCHIVE_FATAL for +serious errors that make remaining operations +impossible.

+ +

ERRORS

+ +

Detailed error codes and textual +descriptions are available from the archive_errno() +and archive_error_string() functions.

+ +

SEE ALSO

+ +

tar(1), archive_write_data(3), +archive_write_set_options(3), libarchive(3), cpio(5), +mtree(5), tar(5)

+ +

BSD +February 28, 2017 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_write_format.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_write_format.3.html new file mode 100644 index 0000000..fbdff7b --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_write_format.3.html @@ -0,0 +1,264 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_WRITE_FORMAT(3) BSD Library Functions Manual +ARCHIVE_WRITE_FORMAT(3)

+ +

NAME

+ + +

archive_write_set_format, +archive_write_set_format_7zip, +archive_write_set_format_ar, +archive_write_set_format_ar_bsd, +archive_write_set_format_ar_svr4, +archive_write_set_format_by_name, +archive_write_set_format_cpio, +archive_write_set_format_cpio_newc, +archive_write_set_format_filter_by_ext, +archive_write_set_format_filter_by_ext_def, +archive_write_set_format_gnutar, +archive_write_set_format_iso9660, +archive_write_set_format_mtree, +archive_write_set_format_mtree_classic, +archive_write_set_format_mtree_default, +archive_write_set_format_pax, +archive_write_set_format_pax_restricted, +archive_write_set_format_raw, +archive_write_set_format_shar, +archive_write_set_format_shar_dump, +archive_write_set_format_ustar, +archive_write_set_format_v7tar, +archive_write_set_format_warc, +archive_write_set_format_xar, +archive_write_set_format_zip — functions for +creating archives

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive.h>

+ +

int

+ + +

archive_write_set_format(struct archive *, +int code);

+ +

int

+ + +

archive_write_set_format_7zip(struct archive *);

+ +

int

+ + +

archive_write_set_format_ar(struct archive *);

+ +

int

+ + +

archive_write_set_format_ar_bsd(struct archive *);

+ +

int

+ + +

archive_write_set_format_ar_svr4(struct archive *);

+ +

int

+ + +

archive_write_set_format_by_name(struct archive *, +const char *name);

+ +

int

+ + +

archive_write_set_format_cpio(struct archive *);

+ +

int

+ + +

archive_write_set_format_cpio_newc(struct archive *);

+ +

int

+ + +

archive_write_set_format_filter_by_ext(struct archive *, +const char *filename);

+ +

int

+ + +

archive_write_set_format_filter_by_ext_def(struct archive *, +const char *filename, +const char *def_ext);

+ +

int

+ + +

archive_write_set_format_gnutar(struct archive *);

+ +

int

+ + +

archive_write_set_format_iso9660(struct archive *);

+ +

int

+ + +

archive_write_set_format_mtree(struct archive *);

+ +

int

+ + +

archive_write_set_format_pax(struct archive *);

+ +

int

+ + +

archive_write_set_format_pax_restricted(struct archive *);

+ +

int

+ + +

archive_write_set_format_raw(struct archive *);

+ +

int

+ + +

archive_write_set_format_shar(struct archive *);

+ +

int

+ + +

archive_write_set_format_shar_dump(struct archive *);

+ +

int

+ + +

archive_write_set_format_ustar(struct archive *);

+ +

int

+ + +

archive_write_set_format_v7tar(struct archive *);

+ +

int

+ + +

archive_write_set_format_warc(struct archive *);

+ +

int

+ + +

archive_write_set_format_xar(struct archive *);

+ +

int

+ + +

archive_write_set_format_zip(struct archive *);

+ +

DESCRIPTION

+ +

These functions set the format +that will be used for the archive.

+ +

The library can +write a variety of common archive formats.

+ + +

archive_write_set_format()

+ +

Sets the format based on the +format code (see archive.h for the full list of +format codes). In particular, this can be used in +conjunction with archive_format() to create a new +archive with the same format as an existing archive.

+ + +

archive_write_set_format_by_name()

+ +

Sets the corresponding format +based on the common name.

+ + +

archive_write_set_format_filter_by_ext(), +archive_write_set_format_filter_by_ext_def()

+ +

Sets both filters and format +based on the output filename. Supported extensions: .7z, +.zip, .jar, .cpio, .iso, .a, .ar, .tar, .tgz, .tar.gz, +.tar.bz2, .tar.xz

+ + +

archive_write_set_format_7zip() +archive_write_set_format_ar_bsd(), +archive_write_set_format_ar_svr4(), +archive_write_set_format_cpio() +archive_write_set_format_cpio_newc() +archive_write_set_format_gnutar() +archive_write_set_format_iso9660() +archive_write_set_format_mtree() +archive_write_set_format_mtree_classic() +archive_write_set_format_pax() +archive_write_set_format_pax_restricted() +archive_write_set_format_raw() +archive_write_set_format_shar() +archive_write_set_format_shar_dump() +archive_write_set_format_ustar() +archive_write_set_format_v7tar() +archive_write_set_format_warc() +archive_write_set_format_xar() +archive_write_set_format_zip()

+ +

Set the format as specified. +More details on the formats supported by libarchive can be +found in the libarchive-formats(5) manual page.

+ +

RETURN VALUES

+ +

These functions return +ARCHIVE_OK on success, or ARCHIVE_FATAL.

+ +

ERRORS

+ +

Detailed error codes and textual +descriptions are available from the archive_errno() +and archive_error_string() functions.

+ +

SEE ALSO

+ +

tar(1), archive_write(3), +archive_write_set_options(3), libarchive(3), cpio(5), +libarchive-formats(5), mtree(5), tar(5)

+ +

BSD +February 14, 2013 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_write_free.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_write_free.3.html new file mode 100644 index 0000000..d0535ad --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_write_free.3.html @@ -0,0 +1,116 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_WRITE_FREE(3) BSD Library Functions Manual +ARCHIVE_WRITE_FREE(3)

+ +

NAME

+ +

archive_write_fail, +archive_write_close, archive_write_finish, +archive_write_free — functions for creating +archives

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive.h>

+ +

int

+ + +

archive_write_fail(struct archive *);

+ +

int

+ + +

archive_write_close(struct archive *);

+ +

int

+ + +

archive_write_finish(struct archive *);

+ +

int

+ + +

archive_write_free(struct archive *);

+ +

DESCRIPTION
+archive_write_fail
()

+ +

Always returns +ARCHIVE_FATAL. This marks the archive object as being +unusable; after calling this function, the only call that +can succeed is archive_write_free() to release the +resources. This can be used to speed recovery when the +archive creation must be aborted. Note that the created +archive is likely to be malformed in this case;

+ + +

archive_write_close()

+ +

Complete the archive and invoke +the close callback.

+ + +

archive_write_finish()

+ +

This is a deprecated synonym +for archive_write_free().

+ +

archive_write_free()

+ +

Invokes +archive_write_close() if necessary, then releases all +resources. If you need detailed information about +archive_write_close() failures, you should be careful +to call it separately, as you cannot obtain error +information after archive_write_free() returns.

+ +

RETURN VALUES

+ +

These functions return +ARCHIVE_OK on success, or ARCHIVE_FATAL.

+ +

ERRORS

+ +

Detailed error codes and textual +descriptions are available from the archive_errno() +and archive_error_string() functions.

+ +

SEE ALSO

+ +

tar(1), +archive_write_set_options(3), libarchive(3), cpio(5), +mtree(5), tar(5)

+ +

BSD +February 2, 2012 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_write_header.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_write_header.3.html new file mode 100644 index 0000000..1a857e5 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_write_header.3.html @@ -0,0 +1,80 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_WRITE_HEADER(3) BSD Library Functions Manual +ARCHIVE_WRITE_HEADER(3)

+ +

NAME

+ +

archive_write_header +— functions for creating archives

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive.h>

+ +

int

+ + +

archive_write_header(struct archive *, +struct archive_entry *);

+ +

DESCRIPTION

+ +

Build and write a header using +the data in the provided struct archive_entry structure. See +archive_entry(3) for information on creating and populating +struct archive_entry objects.

+ +

RETURN VALUES

+ +

This function returns +ARCHIVE_OK on success, or one of the following on +error: ARCHIVE_RETRY for operations that might +succeed if retried, ARCHIVE_WARN for unusual +conditions that do not prevent further operations, and +ARCHIVE_FATAL for serious errors that make remaining +operations impossible.

+ +

ERRORS

+ +

Detailed error codes and textual +descriptions are available from the archive_errno() +and archive_error_string() functions.

+ +

SEE ALSO

+ +

tar(1), +archive_write_set_options(3), libarchive(3), cpio(5), +mtree(5), tar(5)

+ +

BSD +February 2, 2012 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_write_new.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_write_new.3.html new file mode 100644 index 0000000..9abd63e --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_write_new.3.html @@ -0,0 +1,67 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_WRITE_NEW(3) BSD Library Functions Manual +ARCHIVE_WRITE_NEW(3)

+ +

NAME

+ +

archive_write_new — +functions for creating archives

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive.h>

+ +

struct +archive *

+ + +

archive_write_new(void);

+ +

DESCRIPTION

+ +

Allocates and initializes a +struct archive object suitable for writing a tar archive. +NULL is returned on error.

+ +

A complete +description of the struct archive object can be found in the +overview manual page for libarchive(3).

+ +

SEE ALSO

+ +

tar(1), archive_write(3), +archive_write_set_options(3), libarchive(3), cpio(5), +mtree(5), tar(5)

+ +

BSD +February 2, 2012 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_write_open.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_write_open.3.html new file mode 100644 index 0000000..4042853 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_write_open.3.html @@ -0,0 +1,240 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_WRITE_OPEN(3) BSD Library Functions Manual +ARCHIVE_WRITE_OPEN(3)

+ +

NAME

+ +

archive_write_open, +archive_write_open_fd, +archive_write_open_FILE, +archive_write_open_filename, +archive_write_open_memory — functions for +creating archives

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive.h>

+ +

int

+ + +

archive_write_open(struct archive *, +void *client_data, +archive_open_callback *, +archive_write_callback *, +archive_close_callback *);

+ +

int

+ + +

archive_write_open_fd(struct archive *, +int fd);

+ +

int

+ + +

archive_write_open_FILE(struct archive *, +FILE *file);

+ +

int

+ + +

archive_write_open_filename(struct archive *, +const char *filename);

+ +

int

+ + +

archive_write_open_memory(struct archive *, +void *buffer, size_t bufferSize, +size_t *outUsed);

+ +

DESCRIPTION
+archive_write_open
()

+ +

Freeze the settings, open the +archive, and prepare for writing entries. This is the most +generic form of this function, which accepts pointers to +three callback functions which will be invoked by the +compression layer to write the constructed archive. This +does not alter the default archive padding.

+ + +

archive_write_open_fd()

+ +

A convenience form of +archive_write_open() that accepts a file descriptor. +The archive_write_open_fd() function is safe for use +with tape drives or other block-oriented devices.

+ + +

archive_write_open_FILE()

+ +

A convenience form of +archive_write_open() that accepts a FILE * +pointer. Note that archive_write_open_FILE() is not +safe for writing to tape drives or other devices that +require correct blocking.

+ + +

archive_write_open_file()

+ +

A deprecated synonym for +archive_write_open_filename().

+ + +

archive_write_open_filename()

+ +

A convenience form of +archive_write_open() that accepts a filename. A NULL +argument indicates that the output should be written to +standard output; an argument of +’’-’’ will open a file with that +name. If you have not invoked +archive_write_set_bytes_in_last_block(), then +archive_write_open_filename() will adjust the +last-block padding depending on the file: it will enable +padding when writing to standard output or to a character or +block device node, it will disable padding otherwise. You +can override this by manually invoking +archive_write_set_bytes_in_last_block() before +calling archive_write_open(). The +archive_write_open_filename() function is safe for +use with tape drives or other block-oriented devices.

+ + +

archive_write_open_memory()

+ +

A convenience form of +archive_write_open() that accepts a pointer to a +block of memory that will receive the archive. The final +size_t * argument points to a variable that will be +updated after each write to reflect how much of the buffer +is currently in use. You should be careful to ensure that +this variable remains allocated until after the archive is +closed. This function will disable padding unless you have +specifically set the block size.

+ +

More information about the +struct archive object and the overall design of the +library can be found in the libarchive(3) overview.

+ +

Note that the +convenience forms above vary in how they block the output. +See archive_write_blocksize(3) if you need to control the +block size used for writes or the end-of-file padding +behavior.

+ +

CLIENT CALLBACKS

+ +

To use this library, you will +need to define and register callback functions that will be +invoked to write data to the resulting archive. These +functions are registered by calling +archive_write_open():

+ +

typedef +int archive_open_callback(struct archive +*, void *client_data)

+ +

The open +callback is invoked by archive_write_open(). It +should return ARCHIVE_OK if the underlying file or +data source is successfully opened. If the open fails, it +should call archive_set_error() to register an error +code and message and return ARCHIVE_FATAL.

+ +

typedef +la_ssize_t

+ + +

archive_write_callback(struct archive *, +void *client_data, +const void *buffer, +size_t length)

+ +

The write +callback is invoked whenever the library needs to write raw +bytes to the archive. For correct blocking, each call to the +write callback function should translate into a single +write(2) system call. This is especially critical when +writing archives to tape drives. On success, the write +callback should return the number of bytes actually written. +On error, the callback should invoke +archive_set_error() to register an error code and +message and return -1.

+ +

typedef +int archive_close_callback(struct archive +*, void *client_data)

+ +

The close +callback is invoked by archive_close when the archive +processing is complete. The callback should return +ARCHIVE_OK on success. On failure, the callback +should invoke archive_set_error() to register an +error code and message and return ARCHIVE_FATAL.

+ +

Note that if the +client-provided write callback function returns a non-zero +value, that error will be propagated back to the caller +through whatever API function resulted in that call, which +may include archive_write_header(), +archive_write_data(), archive_write_close(), +archive_write_finish(), or +archive_write_free(). The client callback can call +archive_set_error() to provide values that can then +be retrieved by archive_errno() and +archive_error_string().

+ +

RETURN VALUES

+ +

These functions return +ARCHIVE_OK on success, or ARCHIVE_FATAL.

+ +

ERRORS

+ +

Detailed error codes and textual +descriptions are available from the archive_errno() +and archive_error_string() functions.

+ +

SEE ALSO

+ +

tar(1), archive_write(3), +archive_write_blocksize(3), archive_write_filter(3), +archive_write_format(3), archive_write_new(3), +archive_write_set_options(3), libarchive(3), cpio(5), +mtree(5), tar(5)

+ +

BSD +February 2, 2012 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_write_set_options.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_write_set_options.3.html new file mode 100644 index 0000000..e000e25 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_write_set_options.3.html @@ -0,0 +1,829 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_WRITE_OPTIONS(3) BSD Library Functions Manual +ARCHIVE_WRITE_OPTIONS(3)

+ +

NAME

+ + +

archive_write_set_filter_option, +archive_write_set_format_option, +archive_write_set_option, +archive_write_set_options — functions +controlling options for writing archives

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

int

+ + +

archive_write_set_filter_option(struct archive *, +const char *module, +const char *option, +const char *value);

+ +

int

+ + +

archive_write_set_format_option(struct archive *, +const char *module, +const char *option, +const char *value);

+ +

int

+ + +

archive_write_set_option(struct archive *, +const char *module, +const char *option, +const char *value);

+ +

int

+ + +

archive_write_set_options(struct archive *, +const char *options);

+ +

DESCRIPTION

+ +

These functions provide a way +for libarchive clients to configure specific write +modules.

+ + +

archive_write_set_filter_option(), +archive_write_set_format_option()

+ +

Specifies an option that will +be passed to the currently-registered filters (including +decompression filters) or format readers.

+ +

If +option and value are both NULL, these +functions will do nothing and ARCHIVE_OK will be +returned. If option is NULL but value is not, +these functions will do nothing and ARCHIVE_FAILED +will be returned.

+ +

If +module is not NULL, option and value +will be provided to the filter or reader named +module. The return value will be either +ARCHIVE_OK if the option was successfully handled or +ARCHIVE_WARN if the option was unrecognized by the +module or could otherwise not be handled. If there is no +such module, ARCHIVE_FAILED will be returned.

+ +

If +module is NULL, option and value will +be provided to every registered module. If any module +returns ARCHIVE_FATAL, this value will be returned +immediately. Otherwise, ARCHIVE_OK will be returned +if any module accepts the option, and ARCHIVE_FAILED +in all other cases.

+ + +

archive_write_set_option()

+ +

Calls +archive_write_set_format_option(), then +archive_write_set_filter_option(). If either function +returns ARCHIVE_FATAL, ARCHIVE_FATAL will be +returned immediately. Otherwise, the greater of the two +values will be returned.

+ + +

archive_write_set_options()

+ +

options is a +comma-separated list of options. If options is NULL +or empty, ARCHIVE_OK will be returned +immediately.

+ +

Individual +options have one of the following forms:

+ +

option=value

+ +

The option/value pair will be +provided to every module. Modules that do not accept an +option with this name will ignore it.

+ +

option

+ +

The option will +be provided to every module with a value of +’’1’’.

+ +

!option

+ +

The option will be provided to +every module with a NULL value.

+ +

module:option=value, module:option, +module:!option

+ +

As above, but the corresponding +option and value will be provided only to modules whose name +matches module.

+ +

OPTIONS
+Filter b64encode
+mode

+ +

The value is +interpreted as octal digits specifying the file mode.

+ +

name

+ +

The value +specifies the file name.

+ +

Filter bzip2
+compression-level

+ +

The value is interpreted as a +decimal integer specifying the bzip2 compression level. +Supported values are from 1 to 9.

+ +

Filter gzip
+compression-level

+ +

The value is interpreted as a +decimal integer specifying the gzip compression level. +Supported values are from 0 to 9.

+ +

timestamp

+ +

Store timestamp. This is +enabled by default.

+ +

Filter lrzip
+compression
=type

+ +

Use type as compression +method. Supported values are +’’bzip2’’, +’’gzipi’’, +’’lzo’’ (ultra fast), and +’’zpaq’’ (best, extremely slow).

+ +

compression-level

+ +

The value is interpreted as a +decimal integer specifying the lrzip compression level. +Supported values are from 1 to 9.

+ +

Filter lz4
+compression-level

+ +

The value is interpreted as a +decimal integer specifying the lz4 compression level. +Supported values are from 0 to 9.

+ +

stream-checksum

+ +

Enable stream checksum. This is +enabled by default.

+ +

block-checksum

+ +

Enable block checksum. This is +disabled by default.

+ +

block-size

+ +

The value is interpreted as a +decimal integer specifying the lz4 compression block size. +Supported values are from 4 to 7 (default).

+ +

block-dependence

+ +

Use the previous block of the +block being compressed for a compression dictionary to +improve compression ratio. This is disabled by default.

+ +

Filter lzop
+compression-level

+ +

The value is interpreted as a +decimal integer specifying the lzop compression level. +Supported values are from 1 to 9.

+ +

Filter uuencode
+mode

+ +

The value is +interpreted as octal digits specifying the file mode.

+ +

name

+ +

The value +specifies the file name.

+ +

Filter xz
+compression-level

+ +

The value is interpreted as a +decimal integer specifying the compression level. Supported +values are from 0 to 9.

+ +

threads

+ +

The value is interpreted as a +decimal integer specifying the number of threads for +multi-threaded lzma compression. If supported, the default +value is read from lzma_cputhreads().

+ +

Filter zstd
+compression-level

+ +

The value is interpreted as a +decimal integer specifying the compression level. Supported +values are from 1 to 22.

+ +

Format 7zip
+compression

+ +

The value is one of +’’store’’, +’’deflate’’, +’’bzip2’’, +’’lzma1’’, +’’lzma2’’ or +’’ppmd’’ to indicate how the +following entries should be compressed. Note that this +setting is ignored for directories, symbolic links, and +other special entries.

+ +

compression-level

+ +

The value is interpreted as a +decimal integer specifying the compression level. Values +between 0 and 9 are supported. The interpretation of the +compression level depends on the chosen compression +method.

+ +

Format cpio
+hdrcharset

+ +

The value is used as a +character set name that will be used when translating file +names.

+ +

Format gnutar
+hdrcharset

+ +

The value is used as a +character set name that will be used when translating file, +group and user names.

+ +

Format iso9660 - volume metadata

+ +

These options are used to set +standard ISO9660 metadata.

+ +

abstract-file=filename

+ +

The file with the specified +name will be identified in the ISO9660 metadata as holding +the abstract for this volume. Default: none.

+ +

application-id=filename

+ +

The file with the specified +name will be identified in the ISO9660 metadata as holding +the application identifier for this volume. Default: +none.

+ +

biblio-file=filename

+ +

The file with the specified +name will be identified in the ISO9660 metadata as holding +the bibliography for this volume. Default: none.

+ +

copyright-file=filename

+ +

The file with the specified +name will be identified in the ISO9660 metadata as holding +the copyright for this volume. Default: none.

+ +

publisher=filename

+ +

The file with the specified +name will be identified in the ISO9660 metadata as holding +the publisher information for this volume. Default: +none.

+ +

volume-id=string

+ +

The specified string will be +used as the Volume Identifier in the ISO9660 metadata. It is +limited to 32 bytes. Default: none.

+ +

Format iso9660 - boot support

+ +

These options are used to make +an ISO9660 image that can be directly booted on various +systems.

+ +

boot=filename

+ +

The file matching this name +will be used as the El Torito boot image file.

+ +

boot-catalog=name

+ +

The name that will be used for +the El Torito boot catalog. Default: boot.catalog

+ +

boot-info-table

+ +

The boot image file provided by +the boot=filename option will be edited with +appropriate boot information in bytes 8 through 64. Default: +disabled

+ +

boot-load-seg=hexadecimal-number

+ +

The load segment for a +no-emulation boot image.

+ +

boot-load-size=decimal-number

+ +

The number of +"virtual" 512-byte sectors to be loaded from a +no-emulation boot image. Some very old BIOSes can only load +very small images, setting this value to 4 will often allow +such BIOSes to load the first part of the boot image (which +will then need to be intelligent enough to load the rest of +itself). This should not be needed unless you are trying to +support systems with very old BIOSes. This defaults to the +full size of the image.

+ +

boot-type=value

+ +

Specifies the boot semantics +used by the El Torito boot image: If the value is +fd, then the boot image is assumed to be a bootable +floppy image. If the value is hd, then the +boot image is assumed to be a bootable hard disk image. If +the value is no-emulation, the boot image is +used without floppy or hard disk emulation. If the boot +image is exactly 1.2MB, 1.44MB, or 2.88MB, then the default +is fd, otherwise the default is +no-emulation.

+ +

Format iso9660 - filename and size extensions

+ +

Various extensions to the base +ISO9660 format.

+ +

allow-ldots

+ +

If enabled, allows filenames to +begin with a leading period. If disabled, filenames that +begin with a leading period will have that period replaced +by an underscore character in the standard ISO9660 +namespace. This does not impact names stored in the +Rockridge or Joliet extension area. Default: disabled.

+ +

allow-lowercase

+ +

If enabled, allows filenames to +contain lowercase characters. If disabled, filenames will be +forced to uppercase. This does not impact names stored in +the Rockridge or Joliet extension area. Default: +disabled.

+ +

allow-multidot

+ +

If enabled, allows filenames to +contain multiple period characters, in violation of the +ISO9660 specification. If disabled, additional periods will +be converted to underscore characters. This does not impact +names stored in the Rockridge or Joliet extension area. +Default: disabled.

+ +

allow-period

+ +

If enabled, allows filenames to +contain trailing period characters, in violation of the +ISO9660 specification. If disabled, trailing periods will be +converted to underscore characters. This does not impact +names stored in the Rockridge or Joliet extension area. +Default: disabled.

+ +

allow-pvd-lowercase

+ +

If enabled, the Primary Volume +Descriptor may contain lowercase ASCII characters, in +violation of the ISO9660 specification. If disabled, +characters will be converted to uppercase ASCII. Default: +disabled.

+ +

allow-sharp-tilde

+ +

If enabled, sharp and tilde +characters will be permitted in filenames, in violation if +the ISO9660 specification. If disabled, such characters will +be converted to underscore characters. Default: +disabled.

+ +

allow-vernum

+ +

If enabled, version numbers +will be included with files. If disabled, version numbers +will be suppressed, in violation of the ISO9660 standard. +This does not impact names stored in the Rockridge or Joliet +extension area. Default: enabled.

+ +

iso-level

+ +

This enables support for file +size and file name extensions in the core ISO9660 area. The +name extensions specified here do not affect the names +stored in the Rockridge or Joliet extension areas.

+ +

iso-level=1

+ +

The most compliant form of +ISO9660 image. Filenames are limited to 8.3 uppercase +format, directory names are limited to 8 uppercase +characters, files are limited to 4 GiB, the complete ISO9660 +image cannot exceed 4 GiB.

+ +

iso-level=2

+ +

Filenames are limited to 30 +uppercase characters with a 30-character extension, +directory names are limited to 30 characters, files are +limited to 4 GiB.

+ +

iso-level=3

+ +

As with iso-level=2, +except that files may exceed 4 GiB.

+ +

iso-level=4

+ +

As with iso-level=3, +except that filenames may be up to 193 characters and may +include arbitrary 8-bit characters.

+ +

joliet

+ + +

Microsoft’s +Joliet extensions store a completely separate set of +directory information about each file. In particular, this +information includes Unicode filenames of up to 255 +characters. Default: enabled.

+ +

limit-depth

+ +

If enabled, libarchive will use +directory relocation records to ensure that no pathname +exceeds the ISO9660 limit of 8 directory levels. If +disabled, no relocation will occur. Default: enabled.

+ +

limit-dirs

+ +

If enabled, libarchive will +cause an error if there are more than 65536 directories. If +disabled, there is no limit on the number of directories. +Default: enabled

+ +

pad

+ +

If enabled, 300 +kiB of zero bytes will be appended to the end of the +archive. Default: enabled

+ +

relaxed-filenames

+ +

If enabled, all 7-bit ASCII +characters are permitted in filenames (except lowercase +characters unless allow-lowercase is also specified). +This violates ISO9660 standards. This does not impact names +stored in the Rockridge or Joliet extension area. Default: +disabled.

+ +

rockridge

+ +

The Rockridge extensions store +an additional set of POSIX-style file information with each +file, including mtime, atime, ctime, permissions, and long +filenames with arbitrary 8-bit characters. These extensions +also support symbolic links and other POSIX file types. +Default: enabled.

+ +

Format iso9660 - zisofs support

+ +

The zisofs extensions permit +each file to be independently compressed using a +gzip-compatible compression. This can provide significant +size savings, but requires the reading system to have +support for these extensions. These extensions are disabled +by default.

+ +

compression-level=number

+ +

The compression level used by +the deflate compressor. Ranges from 0 (least effort) to 9 +(most effort). Default: 6

+ +

zisofs

+ +

Synonym for +zisofs=direct.

+ +

zisofs=direct

+ +

Compress each file in the +archive. Unlike zisofs=indirect, this is handled +entirely within libarchive and does not require a separate +utility. For best results, libarchive tests each file and +will store the file uncompressed if the compression does not +actually save any space. In particular, files under 2k will +never be compressed. Note that boot image files are never +compressed.

+ +

zisofs=indirect

+ +

Recognizes files that have +already been compressed with the mkzftree utility and +sets up the necessary file metadata so that readers will +correctly identify these as zisofs-compressed files.

+ +

zisofs-exclude=filename

+ +

Specifies a filename that +should not be compressed when using zisofs=direct. +This option can be provided multiple times to suppress +compression on many files.

+ +

Format mtree
+cksum
, device, flags, gid, +gname, indent, link, md5, +mode, nlink, rmd160, sha1, +sha256, sha384, sha512, size, +time, uid, uname

+ +

Enable a particular keyword in +the mtree output. Prefix with an exclamation mark to disable +the corresponding keyword. The default is equivalent to +’’device, flags, gid, gname, link, mode, nlink, +size, time, type, uid, uname’’.

+ +

all

+ +

Enables all of +the above keywords.

+ +

use-set

+ +

Enables generation of +/set lines that specify default values for the +following files and/or directories.

+ +

indent

+ +

XXX needs +explanation XXX

+ +

Format newc
+hdrcharset

+ +

The value is used as a +character set name that will be used when translating file +names.

+ +

Format pax
+hdrcharset

+ +

The value is used as a +character set name that will be used when translating file, +group and user names. The value is one of +’’BINARY’’ or +’’UTF-8’’. With +’’BINARY’’ there is no character +conversion, with ’’UTF-8’’ names are +converted to UTF-8.

+ +

xattrheader

+ +

When storing extended +attributes, this option configures which headers should be +written. The value is one of +’’all’’, +’’LIBARCHIVE’’, or +’’SCHILY’’. By default, both +’’LIBARCHIVE.xattr’’ and +’’SCHILY.xattr’’ headers are +written.

+ +

Format ustar
+hdrcharset

+ +

The value is used as a +character set name that will be used when translating file, +group and user names.

+ +

Format v7tar
+hdrcharset

+ +

The value is used as a +character set name that will be used when translating file, +group and user names.

+ +

Format warc
+omit-warcinfo

+ +

Set to +’’true’’ to disable output of the +warcinfo record.

+ +

Format xar
+checksum
=type

+ +

Use type as file +checksum method. Supported values are +’’none’’, +’’md5’’, and +’’sha1’’ (default).

+ +

compression=type

+ +

Use type as compression +method. Supported values are +’’none’’, +’’bzip2’’, +’’gzip’’ (default), +’’lzma’’ and +’’xz’’.

+ +

compression_level

+ +

The value is a decimal integer +from 1 to 9 specifying the compression level.

+ +

toc-checksum=type

+ +

Use type as table of +contents checksum method. Supported values are +’’none’’, +’’md5’’ and +’’sha1’’ (default).

+ +

Format zip
+compression

+ +

The value is either +’’store’’ or +’’deflate’’ to indicate how the +following entries should be compressed. Note that this +setting is ignored for directories, symbolic links, and +other special entries.

+ +

compression-level

+ +

The value is interpreted as a +decimal integer specifying the compression level. Values +between 0 and 9 are supported. A compression level of 0 +switches the compression method to +’’store’’, other values will enable +’’deflate’’ compression with the +given level.

+ +

encryption

+ +

Enable encryption using +traditional zip encryption.

+ +

encryption=type

+ +

Use type as encryption +type. Supported values are +’’zipcrypt’’ (traditional zip +encryption), ’’aes128’’ (WinZip +AES-128 encryption) and ’’aes256’’ +(WinZip AES-256 encryption).

+ +

experimental

+ +

This boolean option enables or +disables experimental Zip features that may not be +compatible with other Zip implementations.

+ +

fakecrc32

+ +

This boolean option disables +CRC calculations. All CRC fields are set to zero. It should +not be used except for testing purposes.

+ +

hdrcharset

+ +

The value is used as a +character set name that will be used when translating file +names.

+ +

zip64

+ +

Zip64 +extensions provide additional file size information for +entries larger than 4 GiB. They also provide extended file +offset and archive size information when archives exceed 4 +GiB. By default, the Zip writer selectively enables these +extensions only as needed. In particular, if the file size +is unknown, the Zip writer will include Zip64 extensions to +guard against the possibility that the file might be larger +than 4 GiB.

+ +

Setting this +boolean option will force the writer to use Zip64 extensions +even for small files that would not otherwise require them. +This is primarily useful for testing.

+ +

Disabling this +option with !zip64 will force the Zip writer to avoid +Zip64 extensions: It will reject files with size greater +than 4 GiB, it will reject any new entries once the total +archive size reaches 4 GiB, and it will not use Zip64 +extensions for files with unknown size. In particular, this +can improve compatibility when generating archives where the +entry sizes are not known in advance.

+ +

EXAMPLES

+ +

The following example creates an +archive write handle to create a gzip-compressed ISO9660 +format image. The two options here specify that the ISO9660 +archive will use kernel.img as the boot image for El +Torito booting, and that the gzip compressor should use the +maximum compression level.

+ +

a = +archive_write_new();
+archive_write_add_filter_gzip(a);
+archive_write_set_format_iso9660(a);
+archive_write_set_options(a, +"boot=kernel.img,compression=9");
+archive_write_open_filename(a, filename, blocksize);

+ +

ERRORS

+ +

More detailed error codes and +textual descriptions are available from the +archive_errno() and archive_error_string() +functions.

+ +

SEE ALSO

+ +

tar(1), +archive_read_set_options(3), archive_write(3), +libarchive(3)

+ +

HISTORY

+ +

The libarchive library +first appeared in FreeBSD 5.3.

+ +

AUTHORS

+ +

The options support for +libarchive was originally implemented by Michihiro +NAKAJIMA.

+ +

BUGS

+ +

BSD January 31, 2020 +BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/archive_write_set_passphrase.3.html b/dependencies/libarchive-3.4.2/doc/html/archive_write_set_passphrase.3.html new file mode 100644 index 0000000..f8c765b --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/archive_write_set_passphrase.3.html @@ -0,0 +1,82 @@ + + + + + + + + + + + + + +
+ + +

ARCHIVE_WRITE_SET_PAS... BSD Library Functions Manual +ARCHIVE_WRITE_SET_PAS...

+ +

NAME

+ + +

archive_write_set_passphrase, +archive_write_set_passphrase_callback — +functions for writing encrypted archives

+ +

LIBRARY

+ +

Streaming Archive Library +(libarchive, -larchive)

+ +

SYNOPSIS

+ +

#include +<archive.h>

+ +

int

+ + +

archive_write_set_passphrase(struct archive *, +const char *passphrase);

+ +

int

+ + +

archive_write_set_passphrase_callback(struct archive *, +void *client_data, +archive_passphrase_callback *);

+ +

DESCRIPTION
+archive_write_set_passphrase
()

+ +

Set a passphrase for writing an +encrypted archive. If passphrase is NULL or empty, +this function will do nothing and ARCHIVE_FAILED will +be returned. Otherwise, ARCHIVE_OK will be +returned.

+ + +

archive_write_set_passphrase_callback()

+ +

Register a callback function +that will be invoked to get a passphrase for encryption if +the passphrase was not set by the +archive_write_set_passphrase() function.

+ +

SEE ALSO

+ +

tar(1), archive_write(3), +archive_write_set_options(3), libarchive(3)

+ +

BSD +September 21, 2014 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/bsdcpio.1.html b/dependencies/libarchive-3.4.2/doc/html/bsdcpio.1.html new file mode 100644 index 0000000..862e8fe --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/bsdcpio.1.html @@ -0,0 +1,512 @@ + + + + + + + + + + + + + +
+ + +

CPIO(1) BSD General Commands Manual CPIO(1)

+ +

NAME

+ +

cpio — copy files +to and from archives

+ +

SYNOPSIS

+ +

cpio -i [options] +[pattern ...] [< archive]
+cpio -o
[options] < name-list +[> archive]
+cpio -p
[options] dest-dir < +name-list

+ +

DESCRIPTION

+ +

cpio copies files between +archives and directories. This implementation can extract +from tar, pax, cpio, zip, jar, ar, and ISO 9660 cdrom images +and can create tar, pax, cpio, ar, and shar archives.

+ +

The first option +to cpio is a mode indicator from the following +list:

+ +

-i

+ +

Input. Read an +archive from standard input (unless overridden) and extract +the contents to disk or (if the -t option is +specified) list the contents to standard output. If one or +more file patterns are specified, only files matching one of +the patterns will be extracted.

+ +

-o

+ +

Output. Read a +list of filenames from standard input and produce a new +archive on standard output (unless overridden) containing +the specified items.

+ +

-p

+ +

Pass-through. +Read a list of filenames from standard input and copy the +files to the specified directory.

+ +

OPTIONS

+ +

Unless specifically stated +otherwise, options are applicable in all operating +modes.

+ +

-0, --null

+ +

Read filenames separated by NUL +characters instead of newlines. This is necessary if any of +the filenames being read might contain newlines.

+ +

-A

+ +

(o mode only) +Append to the specified archive. (Not yet implemented.)

+ +

-a

+ +

(o and p modes) +Reset access times on files after they are read.

+ +

-B

+ +

(o mode only) +Block output to records of 5120 bytes.

+ +

-C size

+ +

(o mode only) Block output to +records of size bytes.

+ +

-c

+ +

(o mode only) +Use the old POSIX portable character format. Equivalent to +--format odc.

+ +

-d, +--make-directories

+ +

(i and p modes) Create +directories as necessary.

+ +

-E file

+ +

(i mode only) Read list of file +name patterns from file to list and extract.

+ +

-F file, +--file file

+ +

Read archive from or write +archive to file.

+ +

-f pattern

+ +

(i mode only) Ignore files that +match pattern.

+ +

-H format, +--format format

+ +

(o mode only) Produce the +output archive in the specified format. Supported formats +include:

+ +

cpio

+ +

Synonym for +odc.

+ +

newc

+ +

The SVR4 +portable cpio format.

+ +

odc

+ +

The old POSIX.1 +portable octet-oriented cpio format.

+ +

pax

+ +

The POSIX.1 pax +format, an extension of the ustar format.

+ +

ustar

+ +

The POSIX.1 tar +format.

+ +

The default +format is odc. See libarchive-formats(5) for more +complete information about the formats currently supported +by the underlying libarchive(3) library.

+ +

-h, --help

+ +

Print usage information.

+ +

-I file

+ +

Read archive from +file.

+ +

-i, --extract

+ +

Input mode. See above for +description.

+ +

--insecure

+ +

(i and p mode only) Disable +security checks during extraction or copying. This allows +extraction via symbolic links, absolute paths, and path +names containing ’..’ in the name.

+ +

-J, --xz

+ +

(o mode only) Compress the file +with xz-compatible compression before writing it. In input +mode, this option is ignored; xz compression is recognized +automatically on input.

+ +

-j

+ +

Synonym for +-y.

+ +

-L

+ +

(o and p modes) +All symbolic links will be followed. Normally, symbolic +links are archived and copied as symbolic links. With this +option, the target of the link will be archived or copied +instead.

+ +

-l, --link

+ +

(p mode only) Create links from +the target directory to the original files, instead of +copying.

+ +

--lrzip

+ +

(o mode only) Compress the +resulting archive with lrzip(1). In input mode, this option +is ignored.

+ +

--lz4

+ +

(o mode only) +Compress the archive with lz4-compatible compression before +writing it. In input mode, this option is ignored; lz4 +compression is recognized automatically on input.

+ +

--zstd

+ +

(o mode only) +Compress the archive with zstd-compatible compression before +writing it. In input mode, this option is ignored; zstd +compression is recognized automatically on input.

+ +

--lzma

+ +

(o mode only) +Compress the file with lzma-compatible compression before +writing it. In input mode, this option is ignored; lzma +compression is recognized automatically on input.

+ +

--lzop

+ +

(o mode only) +Compress the resulting archive with lzop(1). In input mode, +this option is ignored.

+ +

--passphrase +passphrase

+ +

The passphrase is used +to extract or create an encrypted archive. Currently, zip is +only a format that cpio can handle encrypted +archives. You shouldn’t use this option unless you +realize how insecure use of this option is.

+ +

-m, +--preserve-modification-time

+ +

(i and p modes) Set file +modification time on created files to match those in the +source.

+ +

-n, +--numeric-uid-gid

+ +

(i mode, only with -t) +Display numeric uid and gid. By default, cpio +displays the user and group names when they are provided in +the archive, or looks up the user and group names in the +system password database.

+ +

--no-preserve-owner

+ +

(i mode only) Do not attempt to +restore file ownership. This is the default when run by +non-root users.

+ +

-O file

+ +

Write archive to +file.

+ +

-o, --create

+ +

Output mode. See above for +description.

+ +

-p, +--pass-through

+ +

Pass-through mode. See above +for description.

+ +

--preserve-owner

+ +

(i mode only) Restore file +ownership. This is the default when run by the root +user.

+ +

--quiet

+ +

Suppress unnecessary +messages.

+ +

-R [
+user][
+:][
+group], --owner [
+user][
+:][
+group]

+ +

Set the owner and/or group on +files in the output. If group is specified with no user (for +example, -R :wheel) then the group will be set +but not the user. If the user is specified with a trailing +colon and no group (for example, -R root:) +then the group will be set to the user’s default +group. If the user is specified with no trailing colon, then +the user will be set but not the group. In -i and +-p modes, this option can only be used by the +super-user. (For compatibility, a period can be used in +place of the colon.)

+ +

-r

+ +

(All modes.) +Rename files interactively. For each file, a prompt is +written to /dev/tty containing the name of the file +and a line is read from /dev/tty. If the line read is +blank, the file is skipped. If the line contains a single +period, the file is processed normally. Otherwise, the line +is taken to be the new name of the file.

+ +

-t, --list

+ +

(i mode only) List the contents +of the archive to stdout; do not restore the contents to +disk.

+ +

-u, +--unconditional

+ +

(i and p modes) Unconditionally +overwrite existing files. Ordinarily, an older file will not +overwrite a newer file on disk.

+ +

-V, --dot

+ +

Print a dot to stderr for each +file as it is processed. Superseded by -v.

+ +

-v, --verbose

+ +

Print the name of each file to +stderr as it is processed. With -t, provide a +detailed listing of each file.

+ +

--version

+ +

Print the program version +information and exit.

+ +

-y

+ +

(o mode only) +Compress the archive with bzip2-compatible compression +before writing it. In input mode, this option is ignored; +bzip2 compression is recognized automatically on input.

+ +

-Z

+ +

(o mode only) +Compress the archive with compress-compatible compression +before writing it. In input mode, this option is ignored; +compression is recognized automatically on input.

+ +

-z

+ +

(o mode only) +Compress the archive with gzip-compatible compression before +writing it. In input mode, this option is ignored; gzip +compression is recognized automatically on input.

+ +

EXIT STATUS

+ +

The cpio utility +exits 0 on success, and >0 if an error +occurs.

+ +

ENVIRONMENT

+ +

The following environment +variables affect the execution of cpio:

+ +

LANG

+ +

The locale to +use. See environ(7) for more information.

+ +

TZ

+ +

The timezone to +use when displaying dates. See environ(7) for more +information.

+ +

EXAMPLES

+ +

The cpio command is +traditionally used to copy file hierarchies in conjunction +with the find(1) command. The first example here simply +copies all files from src to dest:

+ +

find src | +cpio -pmud dest

+ +

By carefully +selecting options to the find(1) command and combining it +with other standard utilities, it is possible to exercise +very fine control over which files are copied. This next +example copies files from src to dest that are +more than 2 days old and whose names match a particular +pattern:

+ +

find src +-mtime +2 | grep foo[bar] | cpio +-pdmu dest

+ +

This example +copies files from src to dest that are more +than 2 days old and which contain the word +’’

+ +

foobar ’’:

+ +

find src +-mtime +2 | xargs grep -l foobar | +cpio -pdmu dest

+ +

COMPATIBILITY

+ +

The mode options i, o, and p and +the options a, B, c, d, f, l, m, r, t, u, and v comply with +SUSv2.

+ +

The old POSIX.1 +standard specified that only -i, -o, and +-p were interpreted as command-line options. Each +took a single argument of a list of modifier characters. For +example, the standard syntax allows -imu but does not +support -miu or -i -m -u, since m and +u are only modifiers to -i, they are not +command-line options in their own right. The syntax +supported by this implementation is backwards-compatible +with the standard. For best compatibility, scripts should +limit themselves to the standard syntax.

+ +

SEE ALSO

+ +

bzip2(1), gzip(1), mt(1), +pax(1), tar(1), libarchive(3), cpio(5), +libarchive-formats(5), tar(5)

+ +

STANDARDS

+ +

There is no current POSIX +standard for the cpio command; it appeared in ISO/IEC +9945-1:1996 (’’POSIX.1’’) but was +dropped from IEEE Std 1003.1-2001 +(’’POSIX.1’’).

+ +

The cpio, ustar, +and pax interchange file formats are defined by IEEE Std +1003.1-2001 (’’POSIX.1’’) for the +pax command.

+ +

HISTORY

+ +

The original cpio and +find utilities were written by Dick Haight while +working in AT&T’s Unix Support Group. They first +appeared in 1977 in PWB/UNIX 1.0, the +’’Programmer’s Work Bench’’ +system developed for use within AT&T. They were first +released outside of AT&T as part of System III Unix in +1981. As a result, cpio actually predates tar, +even though it was not well-known outside of AT&T until +some time later.

+ +

This is a +complete re-implementation based on the libarchive(3) +library.

+ +

BUGS

+ +

The cpio archive format has +several basic limitations: It does not store user and group +names, only numbers. As a result, it cannot be reliably used +to transfer files between systems with dissimilar user and +group numbering. Older cpio formats limit the user and group +numbers to 16 or 18 bits, which is insufficient for modern +systems. The cpio archive formats cannot support files over +4 gigabytes, except for the ’’odc’’ +variant, which can support files up to 8 gigabytes.

+ +

BSD +September 16, 2014 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/bsdtar.1.html b/dependencies/libarchive-3.4.2/doc/html/bsdtar.1.html new file mode 100644 index 0000000..fbcf26a --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/bsdtar.1.html @@ -0,0 +1,1390 @@ + + + + + + + + + + + + + +
+ + +

TAR(1) BSD General Commands Manual TAR(1)

+ +

NAME

+ +

tar — manipulate +tape archives

+ +

SYNOPSIS

+ +

tar +[bundled-flags 

+ +

args ⟩] [⟨
+file
⟩ | ⟨
+pattern
⟩ ...]

+ +

tar {-c} +[options] +[files directories]
+tar
{-r -u} -f +archive-file [options] +[files directories]
+tar
{-t -x} [options] +[patterns]

+ +

DESCRIPTION

+ +

tar creates and +manipulates streaming archive files. This implementation can +extract from tar, pax, cpio, zip, jar, ar, xar, rpm, 7-zip, +and ISO 9660 cdrom images and can create tar, pax, cpio, ar, +zip, 7-zip, and shar archives.

+ +

The first +synopsis form shows a ’’bundled’’ +option word. This usage is provided for compatibility with +historical implementations. See COMPATIBILITY below for +details.

+ +

The other +synopsis forms show the preferred usage. The first option to +tar is a mode indicator from the following list:

+ +

-c

+ +

Create a new +archive containing the specified items. The long option form +is --create.

+ +

-r

+ +

Like -c, +but new entries are appended to the archive. Note that this +only works on uncompressed archives stored in regular files. +The -f option is required. The long option form is +--append.

+ +

-t

+ +

List archive +contents to stdout. The long option form is +--list.

+ +

-u

+ +

Like -r, +but new entries are added only if they have a modification +date newer than the corresponding entry in the archive. Note +that this only works on uncompressed archives stored in +regular files. The -f option is required. The long +form is --update.

+ +

-x

+ +

Extract to disk +from the archive. If a file with the same name appears more +than once in the archive, each copy will be extracted, with +later copies overwriting (replacing) earlier copies. The +long option form is --extract.

+ +

In -c, +-r, or -u mode, each specified file or +directory is added to the archive in the order specified on +the command line. By default, the contents of each directory +are also archived.

+ +

In extract or +list mode, the entire command line is read and parsed before +the archive is opened. The pathnames or patterns on the +command line indicate which items in the archive should be +processed. Patterns are shell-style globbing patterns as +documented in tcsh(1).

+ +

OPTIONS

+ +

Unless specifically stated +otherwise, options are applicable in all operating +modes.

+ +

@archive

+ +

(c and r modes only) The +specified archive is opened and the entries in it will be +appended to the current archive. As a simple example,

+ +

tar -c -f - +newfile @original.tar

+ +

writes a new archive to +standard output containing a file newfile and all of +the entries from original.tar. In contrast,

+ +

tar -c -f - newfile +original.tar

+ +

creates a new archive with only +two entries. Similarly,

+ +

tar -czf - +--format pax @-

+ +

reads an archive from standard +input (whose format will be determined automatically) and +converts it into a gzip-compressed pax-format archive on +stdout. In this way, tar can be used to convert +archives from one format to another.

+ +

-a, +--auto-compress

+ +

(c mode only) Use the archive +suffix to decide a set of the format and the compressions. +As a simple example,

+ +

tar -a -cf +archive.tgz source.c source.h

+ +

creates a new archive with +restricted pax format and gzip compression,

+ +

tar -a -cf +archive.tar.bz2.uu source.c source.h

+ +

creates a new archive with +restricted pax format and bzip2 compression and uuencode +compression,

+ +

tar -a -cf +archive.zip source.c source.h

+ +

creates a new archive with zip +format,

+ +

tar -a -jcf +archive.tgz source.c source.h

+ +

ignores the +’’-j’’ option, and creates a new +archive with restricted pax format and gzip compression,

+ +

tar -a -jcf +archive.xxx source.c source.h

+ +

if it is unknown suffix or no +suffix, creates a new archive with restricted pax format and +bzip2 compression.

+ +

--acls

+ +

(c, r, u, x +modes only) Archive or extract POSIX.1e or NFSv4 ACLs. This +is the reverse of --no-acls and the default behavior +in c, r, and u modes (except on Mac OS X) or if tar +is run in x mode as root. On Mac OS X this option translates +extended ACLs to NFSv4 ACLs. To store extended ACLs the +--mac-metadata option is preferred.

+ +

-B, +--read-full-blocks

+ +

Ignored for compatibility with +other tar(1) implementations.

+ +

-b blocksize, +--block-size blocksize

+ +

Specify the block size, in +512-byte records, for tape drive I/O. As a rule, this +argument is only needed when reading from or writing to tape +drives, and usually not even then as the default block size +of 20 records (10240 bytes) is very common.

+ +

-C directory, +--cd directory, --directory +directory

+ +

In c and r mode, this changes +the directory before adding the following files. In x mode, +change directories after opening the archive but before +extracting entries from the archive.

+ +

--chroot

+ +

(x mode only) chroot() +to the current directory after processing any -C +options and before extracting any files.

+ + +

--clear-nochange-fflags

+ +

(x mode only) Before removing +file system objects to replace them, clear platform-specific +file attributes or file flags that might prevent +removal.

+ +

--exclude +pattern

+ +

Do not process files or +directories that match the specified pattern. Note that +exclusions take precedence over patterns or filenames +specified on the command line.

+ +

--exclude-vcs

+ +

Do not process files or +directories internally used by the version control systems +’Arch’, ’Bazaar’, ’CVS’, +’Darcs’, ’Mercurial’, +’RCS’, ’SCCS’, ’SVN’ and +’git’.

+ +

--fflags

+ +

(c, r, u, x modes only) Archive +or extract platform-specific file attributes or file flags. +This is the reverse of --no-fflags and the default +behavior in c, r, and u modes or if tar is run in x +mode as root.

+ +

--format +format

+ +

(c, r, u mode only) Use the +specified format for the created archive. Supported formats +include ’’cpio’’, +’’pax’’, +’’shar’’, and +’’ustar’’. Other formats may also be +supported; see libarchive-formats(5) for more information +about currently-supported formats. In r and u modes, when +extending an existing archive, the format specified here +must be compatible with the format of the existing archive +on disk.

+ +

-f file, +--file file

+ +

Read the archive from or write +the archive to the specified file. The filename can be +- for standard input or standard output. The default +varies by system; on FreeBSD, the default is +/dev/sa0; on Linux, the default is +/dev/st0.

+ +

--gid id

+ +

Use the provided group id +number. On extract, this overrides the group id in the +archive; the group name in the archive will be ignored. On +create, this overrides the group id read from disk; if +--gname is not also specified, the group name will be +set to match the group id.

+ +

--gname name

+ +

Use the provided group name. On +extract, this overrides the group name in the archive; if +the provided group name does not exist on the system, the +group id (from the archive or from the --gid option) +will be used instead. On create, this sets the group name +that will be stored in the archive; the name will not be +verified against the system group database.

+ +

-H

+ +

(c and r modes +only) Symbolic links named on the command line will be +followed; the target of the link will be archived, not the +link itself.

+ +

-h

+ +

(c and r modes +only) Synonym for -L.

+ +

-I

+ +

Synonym for +-T.

+ +

--help

+ +

Show usage.

+ +

--hfsCompression

+ +

(x mode only) Mac OS X specific +(v10.6 or later). Compress extracted regular files with HFS+ +compression.

+ +

--ignore-zeros

+ +

An alias of --options +read_concatenated_archives for compatibility with GNU +tar.

+ +

--include +pattern

+ +

Process only files or +directories that match the specified pattern. Note that +exclusions specified with --exclude take precedence +over inclusions. If no inclusions are explicitly specified, +all entries are processed by default. The --include +option is especially useful when filtering archives. For +example, the command

+ +

tar -c -f new.tar +--include=’*foo*’ @old.tgz

+ +

creates a new archive +new.tar containing only the entries from +old.tgz containing the string ’foo’.

+ +

-J, --xz

+ +

(c mode only) Compress the +resulting archive with xz(1). In extract or list modes, this +option is ignored. Note that this tar implementation +recognizes XZ compression automatically when reading +archives.

+ +

-j, --bzip, +--bzip2, --bunzip2

+ +

(c mode only) Compress the +resulting archive with bzip2(1). In extract or list modes, +this option is ignored. Note that this tar +implementation recognizes bzip2 compression automatically +when reading archives.

+ +

-k, +--keep-old-files

+ +

(x mode only) Do not overwrite +existing files. In particular, if a file appears more than +once in an archive, later copies will not overwrite earlier +copies.

+ +

--keep-newer-files

+ +

(x mode only) Do not overwrite +existing files that are newer than the versions appearing in +the archive being extracted.

+ +

-L, +--dereference

+ +

(c and r modes only) All +symbolic links will be followed. Normally, symbolic links +are archived as such. With this option, the target of the +link will be archived instead.

+ +

-l, +--check-links

+ +

(c and r modes only) Issue a +warning message unless all links to each file are +archived.

+ +

--lrzip

+ +

(c mode only) Compress the +resulting archive with lrzip(1). In extract or list modes, +this option is ignored. Note that this tar +implementation recognizes lrzip compression automatically +when reading archives.

+ +

--lz4

+ +

(c mode only) +Compress the archive with lz4-compatible compression before +writing it. In extract or list modes, this option is +ignored. Note that this tar implementation recognizes +lz4 compression automatically when reading archives.

+ +

--zstd

+ +

(c mode only) +Compress the archive with zstd-compatible compression before +writing it. In extract or list modes, this option is +ignored. Note that this tar implementation recognizes +zstd compression automatically when reading archives.

+ +

--lzma

+ +

(c mode only) +Compress the resulting archive with the original LZMA +algorithm. In extract or list modes, this option is ignored. +Use of this option is discouraged and new archives should be +created with --xz instead. Note that this tar +implementation recognizes LZMA compression automatically +when reading archives.

+ +

--lzop

+ +

(c mode only) +Compress the resulting archive with lzop(1). In extract or +list modes, this option is ignored. Note that this +tar implementation recognizes LZO compression +automatically when reading archives.

+ +

-m, +--modification-time

+ +

(x mode only) Do not extract +modification time. By default, the modification time is set +to the time stored in the archive.

+ +

--mac-metadata

+ +

(c, r, u and x mode only) Mac +OS X specific. Archive or extract extended ACLs and extended +file attributes using copyfile(3) in AppleDouble format. +This is the reverse of --no-mac-metadata. and the +default behavior in c, r, and u modes or if tar is +run in x mode as root.

+ +

-n, --norecurse, +--no-recursion

+ +

Do not operate recursively on +the content of directories.

+ +

--newer date

+ +

(c, r, u modes only) Only +include files and directories newer than the specified date. +This compares ctime entries.

+ +

--newer-mtime +date

+ +

(c, r, u modes only) Like +--newer, except it compares mtime entries instead of +ctime entries.

+ +

--newer-than +file

+ +

(c, r, u modes only) Only +include files and directories newer than the specified file. +This compares ctime entries.

+ +

--newer-mtime-than +file

+ +

(c, r, u modes only) Like +--newer-than, except it compares mtime entries +instead of ctime entries.

+ +

--nodump

+ +

(c and r modes only) Honor the +nodump file flag by skipping this file.

+ + +

--nopreserveHFSCompression

+ +

(x mode only) Mac OS X specific +(v10.6 or later). Do not compress extracted regular files +which were compressed with HFS+ compression before archived. +By default, compress the regular files again with HFS+ +compression.

+ +

--null

+ +

(use with +-I or -T) Filenames or patterns are separated +by null characters, not by newlines. This is often used to +read filenames output by the -print0 option to +find(1).

+ +

--no-acls

+ +

(c, r, u, x modes only) Do not +archive or extract POSIX.1e or NFSv4 ACLs. This is the +reverse of --acls and the default behavior if +tar is run as non-root in x mode (on Mac OS X as any +user in c, r, u and x modes).

+ +

--no-fflags

+ +

(c, r, u, x modes only) Do not +archive or extract file attributes or file flags. This is +the reverse of --fflags and the default behavior if +tar is run as non-root in x mode.

+ +

--no-mac-metadata

+ +

(x mode only) Mac OS X +specific. Do not archive or extract ACLs and extended file +attributes using copyfile(3) in AppleDouble format. This is +the reverse of --mac-metadata. and the default +behavior if tar is run as non-root in x mode.

+ +

--no-safe-writes

+ +

(x mode only) Do not create +temporary files and use rename(2) to replace the original +ones. This is the reverse of --safe-writes.

+ +

--no-same-owner

+ +

(x mode only) Do not extract +owner and group IDs. This is the reverse of +--same-owner and the default behavior if tar +is run as non-root.

+ + +

--no-same-permissions

+ +

(x mode only) Do not extract +full permissions (SGID, SUID, sticky bit, file attributes or +file flags, extended file attributes and ACLs). This is the +reverse of -p and the default behavior if tar +is run as non-root.

+ +

--no-xattrs

+ +

(c, r, u, x modes only) Do not +archive or extract extended file attributes. This is the +reverse of --xattrs and the default behavior if +tar is run as non-root in x mode.

+ +

--numeric-owner

+ +

This is equivalent to +--uname "" --gname "". On +extract, it causes user and group names in the archive to be +ignored in favor of the numeric user and group ids. On +create, it causes user and group names to not be stored in +the archive.

+ +

-O, +--to-stdout

+ +

(x, t modes only) In extract +(-x) mode, files will be written to standard out rather than +being extracted to disk. In list (-t) mode, the file listing +will be written to stderr rather than the usual stdout.

+ +

-o

+ +

(x mode) Use +the user and group of the user running the program rather +than those specified in the archive. Note that this has no +significance unless -p is specified, and the program +is being run by the root user. In this case, the file modes +and flags from the archive will be restored, but ACLs or +owner information in the archive will be discarded.

+ +

-o

+ +

(c, r, u mode) +A synonym for --format ustar

+ +

--older date

+ +

(c, r, u modes only) Only +include files and directories older than the specified date. +This compares ctime entries.

+ +

--older-mtime +date

+ +

(c, r, u modes only) Like +--older, except it compares mtime entries instead of +ctime entries.

+ +

--older-than +file

+ +

(c, r, u modes only) Only +include files and directories older than the specified file. +This compares ctime entries.

+ +

--older-mtime-than +file

+ +

(c, r, u modes only) Like +--older-than, except it compares mtime entries +instead of ctime entries.

+ +

--one-file-system

+ +

(c, r, and u modes) Do not +cross mount points.

+ +

--options +options

+ +

Select optional behaviors for +particular modules. The argument is a text string containing +comma-separated keywords and values. These are passed to the +modules that handle particular formats to control how those +formats will behave. Each option has one of the following +forms:

+ +

key=value

+ +

The key will be set to the +specified value in every module that supports it. Modules +that do not support this key will ignore it.

+ +

key

+ +

The key will be +enabled in every module that supports it. This is equivalent +to key=1.

+ +

!key

+ +

The key will be +disabled in every module that supports it.

+ +

module:key=value, module:key, +module:!key

+ +

As above, but the corresponding +key and value will be provided only to modules whose name +matches module.

+ +

The complete +list of supported modules and keys for create and append +modes is in archive_write_set_options(3) and for extract and +list modes in archive_read_set_options(3).

+ +

Examples of +supported options:

+ +

iso9660:joliet

+ +

Support Joliet extensions. This +is enabled by default, use !joliet or +iso9660:!joliet to disable.

+ +

iso9660:rockridge

+ +

Support Rock Ridge extensions. +This is enabled by default, use !rockridge or +iso9660:!rockridge to disable.

+ +

gzip:compression-level

+ +

A decimal integer from 1 to 9 +specifying the gzip compression level.

+ +

gzip:timestamp

+ +

Store timestamp. This is +enabled by default, use !timestamp or +gzip:!timestamp to disable.

+ +

lrzip:compression=type

+ +

Use type as compression +method. Supported values are bzip2, gzip, lzo (ultra fast), +and zpaq (best, extremely slow).

+ +

lrzip:compression-level

+ +

A decimal integer from 1 to 9 +specifying the lrzip compression level.

+ +

lz4:compression-level

+ +

A decimal integer from 1 to 9 +specifying the lzop compression level.

+ +

lz4:stream-checksum

+ +

Enable stream checksum. This is +by default, use lz4:!stream-checksum to disable.

+ +

lz4:block-checksum

+ +

Enable block checksum (Disabled +by default).

+ +

lz4:block-size

+ +

A decimal integer from 4 to 7 +specifying the lz4 compression block size (7 is set by +default).

+ +

lz4:block-dependence

+ +

Use the previous block of the +block being compressed for a compression dictionary to +improve compression ratio.

+ +

zstd:compression-level

+ +

A decimal integer from 1 to 22 +specifying the zstd compression level.

+ +

lzop:compression-level

+ +

A decimal integer from 1 to 9 +specifying the lzop compression level.

+ +

xz:compression-level

+ +

A decimal integer from 0 to 9 +specifying the xz compression level.

+ +

mtree:keyword

+ +

The mtree writer module allows +you to specify which mtree keywords will be included in the +output. Supported keywords include: cksum, +device, flags, gid, gname, +indent, link, md5, mode, +nlink, rmd160, sha1, sha256, +sha384, sha512, size, time, +uid, uname. The default is equivalent to: +’’device, flags, gid, gname, link, mode, nlink, +size, time, type, uid, uname’’.

+ +

mtree:all

+ +

Enables all of the above +keywords. You can also use mtree:!all to disable all +keywords.

+ +

mtree:use-set

+ +

Enable generation of +/set lines in the output.

+ +

mtree:indent

+ +

Produce human-readable output +by indenting options and splitting lines to fit into 80 +columns.

+ +

zip:compression=type

+ +

Use type as compression +method. Supported values are store (uncompressed) and +deflate (gzip algorithm).

+ +

zip:encryption

+ +

Enable encryption using +traditional zip encryption.

+ +

zip:encryption=type

+ +

Use type as encryption +type. Supported values are zipcrypt (traditional zip +encryption), aes128 (WinZip AES-128 encryption) and aes256 +(WinZip AES-256 encryption).

+ +

read_concatenated_archives

+ +

Ignore zeroed blocks in the +archive, which occurs when multiple tar archives have been +concatenated together. Without this option, only the +contents of the first concatenated archive would be read. +This option is comparable to the -i, +--ignore-zeros option of GNU tar.

+ +

If a provided option is not +supported by any module, that is a fatal error.

+ +

-P, +--absolute-paths

+ +

Preserve pathnames. By default, +absolute pathnames (those that begin with a / character) +have the leading slash removed both when creating archives +and extracting from them. Also, tar will refuse to +extract archive entries whose pathnames contain .. or +whose target directory would be altered by a symlink. This +option suppresses these behaviors.

+ +

-p, --insecure, +--preserve-permissions

+ +

(x mode only) Preserve file +permissions. Attempt to restore the full permissions, +including file modes, file attributes or file flags, +extended file attributes and ACLs, if available, for each +item extracted from the archive. This is the reverse of +--no-same-permissions and the default if tar +is being run as root. It can be partially overridden by also +specifying --no-acls, --no-fflags, +--no-mac-metadata or --no-xattrs.

+ +

--passphrase +passphrase

+ +

The passphrase is used +to extract or create an encrypted archive. Currently, zip is +the only supported format that supports encryption. You +shouldn’t use this option unless you realize how +insecure use of this option is.

+ +

--posix

+ +

(c, r, u mode only) Synonym for +--format pax

+ +

-q, +--fast-read

+ +

(x and t mode only) Extract or +list only the first archive entry that matches each pattern +or filename operand. Exit as soon as each specified pattern +or filename has been matched. By default, the archive is +always read to the very end, since there can be multiple +entries with the same name and, by convention, later entries +overwrite earlier entries. This option is provided as a +performance optimization.

+ +

-S

+ +

(x mode only) +Extract files as sparse files. For every block on disk, +check first if it contains only NULL bytes and seek over it +otherwise. This works similar to the conv=sparse option of +dd.

+ +

-s pattern

+ +

Modify file or archive member +names according to pattern. The pattern has the +format /old/new/[ghHprRsS] where old is a +basic regular expression, new is the replacement +string of the matched part, and the optional trailing +letters modify how the replacement is handled. If old +is not matched, the pattern is skipped. Within new, ~ +is substituted with the match, \1 to \9 with the content of +the corresponding captured group. The optional trailing g +specifies that matching should continue after the matched +part and stop on the first unmatched pattern. The optional +trailing s specifies that the pattern applies to the value +of symbolic links. The optional trailing p specifies that +after a successful substitution the original path name and +the new path name should be printed to standard error. +Optional trailing H, R, or S characters suppress +substitutions for hardlink targets, regular filenames, or +symlink targets, respectively. Optional trailing h, r, or s +characters enable substitutions for hardlink targets, +regular filenames, or symlink targets, respectively. The +default is hrs which applies substitutions to all +names. In particular, it is never necessary to specify h, r, +or s.

+ +

--safe-writes

+ +

(x mode only) Extract files +atomically. By default tar unlinks the original file +with the same name as the extracted file (if it exists), and +then creates it immediately under the same name and writes +to it. For a short period of time, applications trying to +access the file might not find it, or see incomplete +results. If --safe-writes is enabled, tar +first creates a unique temporary file, then writes the new +contents to the temporary file, and finally renames the +temporary file to its final name atomically using rename(2). +This guarantees that an application accessing the file, will +either see the old contents or the new contents at all +times.

+ +

--same-owner

+ +

(x mode only) Extract owner and +group IDs. This is the reverse of --no-same-owner and +the default behavior if tar is run as root.

+ +

--strip-components +count

+ +

Remove the specified number of +leading path elements. Pathnames with fewer elements will be +silently skipped. Note that the pathname is edited after +checking inclusion/exclusion patterns but before security +checks.

+ +

-T filename, +--files-from filename

+ +

In x or t mode, tar will +read the list of names to be extracted from filename. +In c mode, tar will read names to be archived from +filename. The special name +’’-C’’ on a line by itself will +cause the current directory to be changed to the directory +specified on the following line. Names are terminated by +newlines unless --null is specified. Note that +--null also disables the special handling of lines +containing ’’-C’’. Note: If you are +generating lists of files using find(1), you probably want +to use -n as well.

+ +

--totals

+ +

(c, r, u modes only) After +archiving all files, print a summary to stderr.

+ +

-U, --unlink, +--unlink-first

+ +

(x mode only) Unlink files +before creating them. This can be a minor performance +optimization if most files already exist, but can make +things slower if most files do not already exist. This flag +also causes tar to remove intervening directory +symlinks instead of reporting an error. See the SECURITY +section below for more details.

+ +

--uid id

+ +

Use the provided user id number +and ignore the user name from the archive. On create, if +--uname is not also specified, the user name will be +set to match the user id.

+ +

--uname name

+ +

Use the provided user name. On +extract, this overrides the user name in the archive; if the +provided user name does not exist on the system, it will be +ignored and the user id (from the archive or from the +--uid option) will be used instead. On create, this +sets the user name that will be stored in the archive; the +name is not verified against the system user database.

+ +

--use-compress-program +program

+ +

Pipe the input (in x or t mode) +or the output (in c mode) through program instead of +using the builtin compression support.

+ +

-v, --verbose

+ +

Produce verbose output. In +create and extract modes, tar will list each file +name as it is read from or written to the archive. In list +mode, tar will produce output similar to that of +ls(1). An additional -v option will also provide +ls-like details in create and extract mode.

+ +

--version

+ +

Print version of tar and +libarchive, and exit.

+ +

-w, +--confirmation, --interactive

+ +

Ask for confirmation for every +action.

+ +

-X filename, +--exclude-from filename

+ +

Read a list of exclusion +patterns from the specified file. See --exclude for +more information about the handling of exclusions.

+ +

--xattrs

+ +

(c, r, u, x modes only) Archive +or extract extended file attributes. This is the reverse of +--no-xattrs and the default behavior in c, r, and u +modes or if tar is run in x mode as root.

+ +

-y

+ +

(c mode only) +Compress the resulting archive with bzip2(1). In extract or +list modes, this option is ignored. Note that this +tar implementation recognizes bzip2 compression +automatically when reading archives.

+ +

-Z, --compress, +--uncompress

+ +

(c mode only) Compress the +resulting archive with compress(1). In extract or list +modes, this option is ignored. Note that this tar +implementation recognizes compress compression automatically +when reading archives.

+ +

-z, --gunzip, +--gzip

+ +

(c mode only) Compress the +resulting archive with gzip(1). In extract or list modes, +this option is ignored. Note that this tar +implementation recognizes gzip compression automatically +when reading archives.

+ +

ENVIRONMENT

+ +

The following environment +variables affect the execution of tar:

+ +

TAR_READER_OPTIONS

+ +

The default options for format +readers and compression readers. The --options option +overrides this.

+ +

TAR_WRITER_OPTIONS

+ +

The default options for format +writers and compression writers. The --options option +overrides this.

+ +

LANG

+ +

The locale to +use. See environ(7) for more information.

+ +

TAPE

+ +

The default +device. The -f option overrides this. Please see the +description of the -f option above for more +details.

+ +

TZ

+ +

The timezone to +use when displaying dates. See environ(7) for more +information.

+ +

EXIT STATUS

+ +

The tar utility +exits 0 on success, and >0 if an error +occurs.

+ +

EXAMPLES

+ +

The following creates a new +archive called file.tar.gz that contains two files +source.c and source.h:

+ +

tar -czf file.tar.gz +source.c source.h

+ +

To view a +detailed table of contents for this archive:

+ +

tar -tvf +file.tar.gz

+ +

To extract all +entries from the archive on the default tape drive:

+ +

tar -x

+ +

To examine the +contents of an ISO 9660 cdrom image:

+ +

tar -tf +image.iso

+ +

To move file +hierarchies, invoke tar as

+ +

tar -cf - +-C srcdir . | tar -xpf - +-C destdir

+ +

or more traditionally

+ +

cd srcdir ; tar -cf - +. | (cd destdir ; tar -xpf -)

+ +

In create mode, +the list of files and directories to be archived can also +include directory change instructions of the form +-Cfoo/baz and archive inclusions of the form +@archive-file. For example, the command +line

+ +

tar -c -f new.tar +foo1 @old.tgz -C/tmp +foo2

+ +

will create a new archive +new.tar. tar will read the file foo1 +from the current directory and add it to the output archive. +It will then read each entry from old.tgz and add +those entries to the output archive. Finally, it will switch +to the /tmp directory and add foo2 to the +output archive.

+ +

An input file in +mtree(5) format can be used to create an output archive with +arbitrary ownership, permissions, or names that differ from +existing data on disk:

+ +

$ cat +input.mtree
+#mtree
+usr/bin uid=0 gid=0 mode=0755 type=dir
+usr/bin/ls uid=0 gid=0 mode=0755 type=file content=myls
+$ tar -cvf output.tar @input.mtree

+ +

The +--newer and --newer-mtime switches accept a +variety of common date and time specifications, including +’’12 Mar 2005 7:14:29pm’’, +’’2005-03-12 19:14’’, +’’5 minutes ago’’, and +’’19:14 PST May 1’’.

+ +

The +--options argument can be used to control various +details of archive generation or reading. For example, you +can generate mtree output which only contains type, +time, and uid keywords:

+ +

tar -cf file.tar +--format=mtree +--options=’!all,type,time,uid’ +dir

+ +

or you can set the compression +level used by gzip or xz compression:

+ +

tar -czf file.tar +--options=’compression-level=9’.

+ +

For more details, see the +explanation of the archive_read_set_options() and +archive_write_set_options() API calls that are +described in archive_read(3) and archive_write(3).

+ +

COMPATIBILITY

+ +

The bundled-arguments format is +supported for compatibility with historic implementations. +It consists of an initial word (with no leading - character) +in which each character indicates an option. Arguments +follow as separate words. The order of the arguments must +match the order of the corresponding characters in the +bundled command word. For example,

+ +

tar tbf 32 +file.tar

+ +

specifies three flags t, +b, and f. The b and f flags both +require arguments, so there must be two additional items on +the command line. The 32 is the argument to the +b flag, and file.tar is the argument to the +f flag.

+ +

The mode options +c, r, t, u, and x and the options b, f, l, m, o, v, and w +comply with SUSv2.

+ +

For maximum +portability, scripts that invoke tar should use the +bundled-argument format above, should limit themselves to +the c, t, and x modes, and the +b, f, m, v, and w +options.

+ +

Additional long +options are provided to improve compatibility with other tar +implementations.

+ +

SECURITY

+ +

Certain security issues are +common to many archiving programs, including tar. In +particular, carefully-crafted archives can request that +tar extract files to locations outside of the target +directory. This can potentially be used to cause unwitting +users to overwrite files they did not intend to overwrite. +If the archive is being extracted by the superuser, any file +on the system can potentially be overwritten. There are +three ways this can happen. Although tar has +mechanisms to protect against each one, savvy users should +be aware of the implications:

+ +

+ +

Archive entries can have +absolute pathnames. By default, tar removes the +leading / character from filenames before restoring +them to guard against this problem.

+ +

+ +

Archive entries can have +pathnames that include .. components. By default, +tar will not extract files containing .. +components in their pathname.

+ +

+ +

Archive entries can exploit +symbolic links to restore files to other directories. An +archive can restore a symbolic link to another directory, +then use that link to restore a file into that directory. To +guard against this, tar checks each extracted path +for symlinks. If the final path element is a symlink, it +will be removed and replaced with the archive entry. If +-U is specified, any intermediate symlink will also +be unconditionally removed. If neither -U nor +-P is specified, tar will refuse to extract +the entry.

+ +

To protect yourself, you should +be wary of any archives that come from untrusted sources. +You should examine the contents of an archive with

+ +

tar -tf +filename

+ +

before extraction. You should +use the -k option to ensure that tar will not +overwrite any existing files or the -U option to +remove any pre-existing files. You should generally not +extract archives while running with super-user privileges. +Note that the -P option to tar disables the +security checks above and allows you to extract an archive +while preserving any absolute pathnames, .. +components, or symlinks to other directories.

+ +

SEE ALSO

+ +

bzip2(1), compress(1), cpio(1), +gzip(1), mt(1), pax(1), shar(1), xz(1), libarchive(3), +libarchive-formats(5), tar(5)

+ +

STANDARDS

+ +

There is no current POSIX +standard for the tar command; it appeared in ISO/IEC +9945-1:1996 (’’POSIX.1’’) but was +dropped from IEEE Std 1003.1-2001 +(’’POSIX.1’’). The options supported +by this implementation were developed by surveying a number +of existing tar implementations as well as the old POSIX +specification for tar and the current POSIX specification +for pax.

+ +

The ustar and +pax interchange file formats are defined by IEEE Std +1003.1-2001 (’’POSIX.1’’) for the +pax command.

+ +

HISTORY

+ +

A tar command appeared in +Seventh Edition Unix, which was released in January, 1979. +There have been numerous other implementations, many of +which extended the file format. John Gilmore’s +pdtar public-domain implementation (circa November, +1987) was quite influential, and formed the basis of GNU +tar. GNU tar was included as the standard system tar in +FreeBSD beginning with FreeBSD 1.0.

+ +

This is a +complete re-implementation based on the libarchive(3) +library. It was first released with FreeBSD 5.4 in May, +2005.

+ +

BUGS

+ +

This program follows ISO/IEC +9945-1:1996 (’’POSIX.1’’) for the +definition of the -l option. Note that GNU tar prior +to version 1.15 treated -l as a synonym for the +--one-file-system option.

+ +

The -C +dir option may differ from historic +implementations.

+ +

All archive +output is written in correctly-sized blocks, even if the +output is being compressed. Whether or not the last output +block is padded to a full block size varies depending on the +format and the output device. For tar and cpio formats, the +last block of output is padded to a full block size if the +output is being written to standard output or to a character +or block device such as a tape drive. If the output is being +written to a regular file, the last block will not be +padded. Many compressors, including gzip(1) and bzip2(1), +complain about the null padding when decompressing an +archive created by tar, although they still extract +it correctly.

+ +

The compression +and decompression is implemented internally, so there may be +insignificant differences between the compressed output +generated by

+ +

tar -czf - +file

+ +

and that generated by

+ +

tar -cf - file | +gzip

+ +

The default +should be to read and write archives to the standard I/O +paths, but tradition (and POSIX) dictates otherwise.

+ +

The r and +u modes require that the archive be uncompressed and +located in a regular file on disk. Other archives can be +modified using c mode with the @archive-file +extension.

+ +

To archive a +file called @foo or -foo you must specify it +as ./@foo or ./-foo, respectively.

+ +

In create mode, +a leading ./ is always removed. A leading / is +stripped unless the -P option is specified.

+ +

There needs to +be better support for file selection on both create and +extract.

+ +

There is not yet +any support for multi-volume archives.

+ +

Converting +between dissimilar archive formats (such as tar and cpio) +using the @- convention can cause hard link +information to be lost. (This is a consequence of the +incompatible ways that different archive formats store +hardlink information.)

+ +

BSD +January 31, 2020 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/cpio.5.html b/dependencies/libarchive-3.4.2/doc/html/cpio.5.html new file mode 100644 index 0000000..de28c5c --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/cpio.5.html @@ -0,0 +1,415 @@ + + + + + + + + + + + + + +
+ + +

CPIO(5) BSD File Formats Manual CPIO(5)

+ +

NAME

+ +

cpio — format of +cpio archive files

+ +

DESCRIPTION

+ +

The cpio archive format +collects any number of files, directories, and other file +system objects (symbolic links, device nodes, etc.) into a +single stream of bytes.

+ +

General +Format
+Each file system object in a cpio archive comprises a +header record with basic numeric metadata followed by the +full pathname of the entry and the file data. The header +record stores a series of integer values that generally +follow the fields in struct stat. (See stat(2) for +details.) The variants differ primarily in how they store +those integers (binary, octal, or hexadecimal). The header +is followed by the pathname of the entry (the length of the +pathname is stored in the header) and any file data. The end +of the archive is indicated by a special record with the +pathname ’’TRAILER!!!’’.

+ +

PWB +format
+XXX Any documentation of the original PWB/UNIX 1.0 format? +XXX

+ +

Old Binary +Format
+The old binary cpio format stores numbers as 2-byte +and 4-byte binary values. Each entry begins with a header in +the following format:

+ +

struct +header_old_cpio {
+unsigned short c_magic;
+unsigned short c_dev;
+unsigned short c_ino;
+unsigned short c_mode;
+unsigned short c_uid;
+unsigned short c_gid;
+unsigned short c_nlink;
+unsigned short c_rdev;

+ + + + + + +
+ + +

unsigned short c_mtime[2];

+
+ +

unsigned short c_namesize;

+ + + + + +
+ + +

unsigned short c_filesize[2];

+ +

};

+ +

The unsigned +short fields here are 16-bit integer values; the +unsigned int fields are 32-bit integer values. The +fields are as follows

+ +

magic

+ +

The integer +value octal 070707. This value can be used to determine +whether this archive is written with little-endian or +big-endian integers.

+ +

dev, ino

+ +

The device and inode numbers +from the disk. These are used by programs that read +cpio archives to determine when two entries refer to +the same file. Programs that synthesize cpio archives +should be careful to set these to distinct values for each +entry.

+ +

mode

+ +

The mode +specifies both the regular permissions and the file type. It +consists of several bit fields as follows:

+ +

0170000

+ +

This masks the +file type bits.

+ +

0140000

+ +

File type value +for sockets.

+ +

0120000

+ +

File type value +for symbolic links. For symbolic links, the link body is +stored as file data.

+ +

0100000

+ +

File type value +for regular files.

+ +

0060000

+ +

File type value +for block special devices.

+ +

0040000

+ +

File type value +for directories.

+ +

0020000

+ +

File type value +for character special devices.

+ +

0010000

+ +

File type value +for named pipes or FIFOs.

+ +

0004000

+ +

SUID bit.

+ +

0002000

+ +

SGID bit.

+ +

0001000

+ +

Sticky bit. On +some systems, this modifies the behavior of executables +and/or directories.

+ +

0000777

+ +

The lower 9 +bits specify read/write/execute permissions for world, +group, and user following standard POSIX conventions.

+ +

uid, gid

+ +

The numeric user id and group +id of the owner.

+ +

nlink

+ +

The number of +links to this file. Directories always have a value of at +least two here. Note that hardlinked files include file data +with every copy in the archive.

+ +

rdev

+ +

For block +special and character special entries, this field contains +the associated device number. For all other entry types, it +should be set to zero by writers and ignored by readers.

+ +

mtime

+ +

Modification +time of the file, indicated as the number of seconds since +the start of the epoch, 00:00:00 UTC January 1, 1970. The +four-byte integer is stored with the most-significant 16 +bits first followed by the least-significant 16 bits. Each +of the two 16 bit values are stored in machine-native byte +order.

+ +

namesize

+ +

The number of bytes in the +pathname that follows the header. This count includes the +trailing NUL byte.

+ +

filesize

+ +

The size of the file. Note that +this archive format is limited to four gigabyte file sizes. +See mtime above for a description of the storage of +four-byte integers.

+ +

The pathname +immediately follows the fixed header. If the namesize +is odd, an additional NUL byte is added after the pathname. +The file data is then appended, padded with NUL bytes to an +even length.

+ +

Hardlinked files +are not given special treatment; the full file contents are +included with each copy of the file.

+ +

Portable +ASCII Format
+Version 2 of the Single UNIX Specification +(’’SUSv2’’) standardized an ASCII +variant that is portable across all platforms. It is +commonly known as the ’’old +character’’ format or as the +’’odc’’ format. It stores the same +numeric fields as the old binary format, but represents them +as 6-character or 11-character octal values.

+ +

struct +cpio_odc_header {
+char c_magic[6];
+char c_dev[6];
+char c_ino[6];
+char c_mode[6];
+char c_uid[6];
+char c_gid[6];
+char c_nlink[6];
+char c_rdev[6];
+char c_mtime[11];
+char c_namesize[6];
+char c_filesize[11];
+};

+ +

The fields are +identical to those in the old binary format. The name and +file body follow the fixed header. Unlike the old binary +format, there is no additional padding after the pathname or +file contents. If the files being archived are themselves +entirely ASCII, then the resulting archive will be entirely +ASCII, except for the NUL byte that terminates the name +field.

+ +

New ASCII +Format
+The "new" ASCII format uses 8-byte hexadecimal +fields for all numbers and separates device numbers into +separate fields for major and minor numbers.

+ +

struct +cpio_newc_header {
+char c_magic[6];
+char c_ino[8];
+char c_mode[8];
+char c_uid[8];
+char c_gid[8];
+char c_nlink[8];
+char c_mtime[8];
+char c_filesize[8];
+char c_devmajor[8];
+char c_devminor[8];
+char c_rdevmajor[8];
+char c_rdevminor[8];
+char c_namesize[8];
+char c_check[8];
+};

+ +

Except as +specified below, the fields here match those specified for +the old binary format above.

+ +

magic

+ +

The string +’’070701’’.

+ +

check

+ +

This field is +always set to zero by writers and ignored by readers. See +the next section for more details.

+ +

The pathname is +followed by NUL bytes so that the total size of the fixed +header plus pathname is a multiple of four. Likewise, the +file data is padded to a multiple of four bytes. Note that +this format supports only 4 gigabyte files (unlike the older +ASCII format, which supports 8 gigabyte files).

+ +

In this format, +hardlinked files are handled by setting the filesize to zero +for each entry except the last one that appears in the +archive.

+ +

New CRC +Format
+The CRC format is identical to the new ASCII format +described in the previous section except that the magic +field is set to ’’070702’’ and the +check field is set to the sum of all bytes in the +file data. This sum is computed treating all bytes as +unsigned values and using unsigned arithmetic. Only the +least-significant 32 bits of the sum are stored.

+ +

HP +variants
+The cpio implementation distributed with HPUX used +XXXX but stored device numbers differently XXX.

+ +

Other +Extensions and Variants
+Sun Solaris uses additional file types to store extended +file data, including ACLs and extended attributes, as +special entries in cpio archives.

+ +

XXX Others? +XXX

+ +

SEE ALSO

+ +

cpio(1), tar(5)

+ +

STANDARDS

+ +

The cpio utility is no +longer a part of POSIX or the Single Unix Standard. It last +appeared in Version 2 of the Single UNIX Specification +(’’SUSv2’’). It has been supplanted +in subsequent standards by pax(1). The portable ASCII format +is currently part of the specification for the pax(1) +utility.

+ +

HISTORY

+ +

The original cpio utility was +written by Dick Haight while working in AT&T’s +Unix Support Group. It appeared in 1977 as part of PWB/UNIX +1.0, the ’’Programmer’s Work +Bench’’ derived from Version 6 AT&T +UNIX that was used internally at AT&T. Both the old +binary and old character formats were in use by 1980, +according to the System III source released by SCO under +their ’’Ancient Unix’’ license. The +character format was adopted as part of IEEE Std 1003.1-1988 +(’’POSIX.1’’). XXX when did +"newc" appear? Who invented it? When did HP come +out with their variant? When did Sun introduce ACLs and +extended attributes? XXX

+ +

BUGS

+ +

The +’’CRC’’ format is mis-named, as it +uses a simple checksum and not a cyclic redundancy +check.

+ +

The old binary +format is limited to 16 bits for user id, group id, device, +and inode numbers. It is limited to 4 gigabyte file +sizes.

+ +

The old ASCII +format is limited to 18 bits for the user id, group id, +device, and inode numbers. It is limited to 8 gigabyte file +sizes.

+ +

The new ASCII +format is limited to 4 gigabyte file sizes.

+ +

None of the cpio +formats store user or group names, which are essential when +moving files between systems with dissimilar user or group +numbering.

+ +

Especially when +writing older cpio variants, it may be necessary to map +actual device/inode values to synthesized values that fit +the available fields. With very large filesystems, this may +be necessary even for the newer formats.

+ +

BSD +December 23, 2011 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/libarchive-formats.5.html b/dependencies/libarchive-3.4.2/doc/html/libarchive-formats.5.html new file mode 100644 index 0000000..345c300 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/libarchive-formats.5.html @@ -0,0 +1,504 @@ + + + + + + + + + + + + + +
+ + +

LIBARCHIVE-FORMATS(5) BSD File Formats Manual +LIBARCHIVE-FORMATS(5)

+ +

NAME

+ +

libarchive-formats +— archive formats supported by the libarchive +library

+ +

DESCRIPTION

+ +

The libarchive(3) library reads +and writes a variety of streaming archive formats. Generally +speaking, all of these archive formats consist of a series +of ’’entries’’. Each entry stores a +single file system object, such as a file, directory, or +symbolic link.

+ +

The following +provides a brief description of each format supported by +libarchive, with some information about recognized +extensions or limitations of the current library support. +Note that just because a format is supported by libarchive +does not imply that a program that uses libarchive will +support that format. Applications that use libarchive +specify which formats they wish to support, though many +programs do use libarchive convenience functions to enable +all supported formats.

+ +

Tar +Formats
+The libarchive(3) library can read most tar archives. It can +write POSIX-standard ’’ustar’’ and +’’pax interchange’’ formats as well +as v7 tar format and a subset of the legacy GNU tar +format.

+ +

All tar formats +store each entry in one or more 512-byte records. The first +record is used for file metadata, including filename, +timestamp, and mode information, and the file data is stored +in subsequent records. Later variants have extended this by +either appropriating undefined areas of the header record, +extending the header to multiple records, or by storing +special entries that modify the interpretation of subsequent +entries.

+ +

gnutar

+ +

The +libarchive(3) library can read most GNU-format tar archives. +It currently supports the most popular GNU extensions, +including modern long filename and linkname support, as well +as atime and ctime data. The libarchive library does not +support multi-volume archives, nor the old GNU long filename +format. It can read GNU sparse file entries, including the +new POSIX-based formats.

+ +

The +libarchive(3) library can write GNU tar format, including +long filename and linkname support, as well as atime and +ctime data.

+ +

pax

+ +

The +libarchive(3) library can read and write POSIX-compliant pax +interchange format archives. Pax interchange format archives +are an extension of the older ustar format that adds a +separate entry with additional attributes stored as +key/value pairs immediately before each regular entry. The +presence of these additional entries is the only difference +between pax interchange format and the older ustar format. +The extended attributes are of unlimited length and are +stored as UTF-8 Unicode strings. Keywords defined in the +standard are in all lowercase; vendors are allowed to define +custom keys by preceding them with the vendor name in all +uppercase. When writing pax archives, libarchive uses many +of the SCHILY keys defined by Joerg Schilling’s +’’star’’ archiver and a few +LIBARCHIVE keys. The libarchive library can read most of the +SCHILY keys and most of the GNU keys introduced by GNU tar. +It silently ignores any keywords that it does not +understand.

+ +

The pax +interchange format converts filenames to Unicode and stores +them using the UTF-8 encoding. Prior to libarchive 3.0, +libarchive erroneously assumed that the system +wide-character routines natively supported Unicode. This +caused it to mis-handle non-ASCII filenames on systems that +did not satisfy this assumption.

+ +

restricted pax

+ +

The libarchive library can also +write pax archives in which it attempts to suppress the +extended attributes entry whenever possible. The result will +be identical to a ustar archive unless the extended +attributes entry is required to store a long file name, long +linkname, extended ACL, file flags, or if any of the +standard ustar data (user name, group name, UID, GID, etc) +cannot be fully represented in the ustar header. In all +cases, the result can be dearchived by any program that can +read POSIX-compliant pax interchange format archives. +Programs that correctly read ustar format (see below) will +also be able to read this format; any extended attributes +will be extracted as separate files stored in +PaxHeader directories.

+ +

ustar

+ +

The libarchive +library can both read and write this format. This format has +the following limitations:

+ +

+ +

Device major and minor numbers +are limited to 21 bits. Nodes with larger numbers will not +be added to the archive.

+ +

+ +

Path names in the archive are +limited to 255 bytes. (Shorter if there is no / character in +exactly the right place.)

+ +

+ +

Symbolic links and hard links +are stored in the archive with the name of the referenced +file. This name is limited to 100 bytes.

+ +

+ +

Extended attributes, file +flags, and other extended security information cannot be +stored.

+ +

+ +

Archive entries are limited to +8 gigabytes in size.

+ +

Note that the pax interchange +format has none of these restrictions. The ustar format is +old and widely supported. It is recommended when +compatibility is the primary concern.

+ +

v7

+ +

The libarchive +library can read and write the legacy v7 tar format. This +format has the following limitations:

+ +

+ +

Only regular files, +directories, and symbolic links can be archived. Block and +character device nodes, FIFOs, and sockets cannot be +archived.

+ +

+ +

Path names in the archive are +limited to 100 bytes.

+ +

+ +

Symbolic links and hard links +are stored in the archive with the name of the referenced +file. This name is limited to 100 bytes.

+ +

+ +

User and group information are +stored as numeric IDs; there is no provision for storing +user or group names.

+ +

+ +

Extended attributes, file +flags, and other extended security information cannot be +stored.

+ +

+ +

Archive entries are limited to +8 gigabytes in size.

+ +

Generally, users should prefer +the ustar format for portability as the v7 tar format is +both less useful and less portable.

+ +

The libarchive +library also reads a variety of commonly-used extensions to +the basic tar format. These extensions are recognized +automatically whenever they appear.

+ +

Numeric extensions.

+ +

The POSIX standards require +fixed-length numeric fields to be written with some +character position reserved for terminators. Libarchive +allows these fields to be written without terminator +characters. This extends the allowable range; in particular, +ustar archives with this extension can support entries up to +64 gigabytes in size. Libarchive also recognizes base-256 +values in most numeric fields. This essentially removes all +limitations on file size, modification time, and device +numbers.

+ +

Solaris extensions

+ +

Libarchive recognizes ACL and +extended attribute records written by Solaris tar.

+ +

The first tar +program appeared in Seventh Edition Unix in 1979. The first +official standard for the tar file format was the +’’ustar’’ (Unix Standard Tar) format +defined by POSIX in 1988. POSIX.1-2001 extended the ustar +format to create the ’’pax +interchange’’ format.

+ +

Cpio +Formats
+The libarchive library can read a number of common cpio +variants and can write ’’odc’’ and +’’newc’’ format archives. A cpio +archive stores each entry as a fixed-size header followed by +a variable-length filename and variable-length data. Unlike +the tar format, the cpio format does only minimal padding of +the header or file data. There are several cpio variants, +which differ primarily in how they store the initial header: +some store the values as octal or hexadecimal numbers in +ASCII, others as binary values of varying byte order and +length.

+ +

binary

+ +

The libarchive +library transparently reads both big-endian and +little-endian variants of the original binary cpio format. +This format used 32-bit binary values for file size and +mtime, and 16-bit binary values for the other fields.

+ +

odc

+ +

The libarchive +library can both read and write this POSIX-standard format, +which is officially known as the ’’cpio +interchange format’’ or the +’’octet-oriented cpio archive +format’’ and sometimes unofficially referred to +as the ’’old character format’’. +This format stores the header contents as octal values in +ASCII. It is standard, portable, and immune from byte-order +confusion. File sizes and mtime are limited to 33 bits (8GB +file size), other fields are limited to 18 bits.

+ +

SVR4/newc

+ +

The libarchive library can read +both CRC and non-CRC variants of this format. The SVR4 +format uses eight-digit hexadecimal values for all header +fields. This limits file size to 4GB, and also limits the +mtime and other fields to 32 bits. The SVR4 format can +optionally include a CRC of the file contents, although +libarchive does not currently verify this CRC.

+ +

Cpio first +appeared in PWB/UNIX 1.0, which was released within AT&T +in 1977. PWB/UNIX 1.0 formed the basis of System III Unix, +released outside of AT&T in 1981. This makes cpio older +than tar, although cpio was not included in Version 7 +AT&T Unix. As a result, the tar command became much +better known in universities and research groups that used +Version 7. The combination of the find and +cpio utilities provided very precise control over +file selection. Unfortunately, the format has many +limitations that make it unsuitable for widespread use. Only +the POSIX format permits files over 4GB, and its 18-bit +limit for most other fields makes it unsuitable for modern +systems. In addition, cpio formats only store numeric +UID/GID values (not usernames and group names), which can +make it very difficult to correctly transfer archives across +systems with dissimilar user numbering.

+ +

Shar +Formats
+A ’’shell archive’’ is a shell +script that, when executed on a POSIX-compliant system, will +recreate a collection of file system objects. The libarchive +library can write two different kinds of shar archives:

+ +

shar

+ +

The traditional +shar format uses a limited set of POSIX commands, including +echo(1), mkdir(1), and sed(1). It is suitable for portably +archiving small collections of plain text files. However, it +is not generally well-suited for large archives (many +implementations of sh(1) have limits on the size of a +script) nor should it be used with non-text files.

+ +

shardump

+ +

This format is similar to shar +but encodes files using uuencode(1) so that the result will +be a plain text file regardless of the file contents. It +also includes additional shell commands that attempt to +reproduce as many file attributes as possible, including +owner, mode, and flags. The additional commands used to +restore file attributes make shardump archives less portable +than plain shar archives.

+ +

ISO9660 +format
+Libarchive can read and extract from files containing +ISO9660-compliant CDROM images. In many cases, this can +remove the need to burn a physical CDROM just in order to +read the files contained in an ISO9660 image. It also avoids +security and complexity issues that come with virtual mounts +and loopback devices. Libarchive supports the most common +Rockridge extensions and has partial support for Joliet +extensions. If both extensions are present, the Joliet +extensions will be used and the Rockridge extensions will be +ignored. In particular, this can create problems with +hardlinks and symlinks, which are supported by Rockridge but +not by Joliet.

+ +

Libarchive reads +ISO9660 images using a streaming strategy. This allows it to +read compressed images directly (decompressing on the fly) +and allows it to read images directly from network sockets, +pipes, and other non-seekable data sources. This strategy +works well for optimized ISO9660 images created by many +popular programs. Such programs collect all directory +information at the beginning of the ISO9660 image so it can +be read from a physical disk with a minimum of seeking. +However, not all ISO9660 images can be read in this +fashion.

+ +

Libarchive can +also write ISO9660 images. Such images are fully optimized +with the directory information preceding all file data. This +is done by storing all file data to a temporary file while +collecting directory information in memory. When the image +is finished, libarchive writes out the directory structure +followed by the file data. The location used for the +temporary file can be changed by the usual environment +variables.

+ +

Zip +format
+Libarchive can read and write zip format archives that have +uncompressed entries and entries compressed with the +’’deflate’’ algorithm. Other zip +compression algorithms are not supported. It can extract jar +archives, archives that use Zip64 extensions and +self-extracting zip archives. Libarchive can use either of +two different strategies for reading Zip archives: a +streaming strategy which is fast and can handle extremely +large archives, and a seeking strategy which can correctly +process self-extracting Zip archives and archives with +deleted members or other in-place modifications.

+ +

The streaming +reader processes Zip archives as they are read. It can read +archives of arbitrary size from tape or network sockets, and +can decode Zip archives that have been separately compressed +or encoded. However, self-extracting Zip archives and +archives with certain types of modifications cannot be +correctly handled. Such archives require that the reader +first process the Central Directory, which is ordinarily +located at the end of a Zip archive and is thus inaccessible +to the streaming reader. If the program using libarchive has +enabled seek support, then libarchive will use this to +processes the central directory first.

+ +

In particular, +the seeking reader must be used to correctly handle +self-extracting archives. Such archives consist of a program +followed by a regular Zip archive. The streaming reader +cannot parse the initial program portion, but the seeking +reader starts by reading the Central Directory from the end +of the archive. Similarly, Zip archives that have been +modified in-place can have deleted entries or other garbage +data that can only be accurately detected by first reading +the Central Directory.

+ +

Archive +(library) file format
+The Unix archive format (commonly created by the ar(1) +archiver) is a general-purpose format which is used almost +exclusively for object files to be read by the link editor +ld(1). The ar format has never been standardised. There are +two common variants: the GNU format derived from SVR4, and +the BSD format, which first appeared in 4.4BSD. The two +differ primarily in their handling of filenames longer than +15 characters: the GNU/SVR4 variant writes a filename table +at the beginning of the archive; the BSD format stores each +long filename in an extension area adjacent to the entry. +Libarchive can read both extensions, including archives that +may include both types of long filenames. Programs using +libarchive can write GNU/SVR4 format if they provide an +entry called // containing a filename table to be +written into the archive before any of the entries. Any +entries whose names are not in the filename table will be +written using BSD-style long filenames. This can cause +problems for programs such as GNU ld that do not support the +BSD-style long filenames.

+ +

mtree +
+Libarchive can read and write files in mtree(5) format. This +format is not a true archive format, but rather a textual +description of a file hierarchy in which each line specifies +the name of a file and provides specific metadata about that +file. Libarchive can read all of the keywords supported by +both the NetBSD and FreeBSD versions of mtree(8), although +many of the keywords cannot currently be stored in an +archive_entry object. When writing, libarchive supports use +of the archive_write_set_options(3) interface to specify +which keywords should be included in the output. If +libarchive was compiled with access to suitable +cryptographic libraries (such as the OpenSSL libraries), it +can compute hash entries such as sha512 or md5 +from file data being written to the mtree writer.

+ +

When reading an +mtree file, libarchive will locate the corresponding files +on disk using the contents keyword if present or the +regular filename. If it can locate and open the file on +disk, it will use that to fill in any metadata that is +missing from the mtree file and will read the file contents +and return those to the program using libarchive. If it +cannot locate and open the file on disk, libarchive will +return an error for any attempt to read the entry body.

+ +

7-Zip +
+Libarchive can read and write 7-Zip format archives. TODO: +Need more information

+ +

CAB
+Libarchive can read Microsoft Cabinet ( +’’CAB’’) format archives. TODO: Need +more information.

+ +

LHA
+TODO: Information about libarchive’s LHA support

+ +

RAR
+Libarchive has limited support for reading RAR format +archives. Currently, libarchive can read RARv3 format +archives which have been either created uncompressed, or +compressed using any of the compression methods supported by +the RARv3 format. Libarchive can also read self-extracting +RAR archives.

+ +

Warc
+Libarchive can read and write ’’web +archives’’. TODO: Need more information

+ +

XAR
+Libarchive can read and write the XAR format used by many +Apple tools. TODO: Need more information

+ +

SEE ALSO

+ +

ar(1), cpio(1), mkisofs(1), +shar(1), tar(1), zip(1), zlib(3), cpio(5), mtree(5), +tar(5)

+ +

BSD +December 27, 2016 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/libarchive.3.html b/dependencies/libarchive-3.4.2/doc/html/libarchive.3.html new file mode 100644 index 0000000..efaa08a --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/libarchive.3.html @@ -0,0 +1,318 @@ + + + + + + + + + + + + + +
+ + +

LIBARCHIVE(3) BSD Library Functions Manual +LIBARCHIVE(3)

+ +

NAME

+ +

libarchive — +functions for reading and writing streaming archives

+ +

OVERVIEW

+ +

The libarchive library +provides a flexible interface for reading and writing +archives in various formats such as tar and cpio. +libarchive also supports reading and writing archives +compressed using various compression filters such as gzip +and bzip2. The library is inherently stream-oriented; +readers serially iterate through the archive, writers +serially add things to the archive. In particular, note that +there is currently no built-in support for random access nor +for in-place modification.

+ +

When reading an +archive, the library automatically detects the format and +the compression. The library currently has read support +for:

+ +

+ +

old-style tar archives,

+ +

+ +

most variants of the POSIX +’’ustar’’ format,

+ +

+ +

the POSIX ’’pax +interchange’’ format,

+ +

+ +

GNU-format tar archives,

+ +

+ +

most common cpio archive +formats,

+ +

+ +

ISO9660 CD images (including +RockRidge and Joliet extensions),

+ +

+ +

Zip archives,

+ +

+ +

ar archives (including GNU/SysV +and BSD extensions),

+ +

+ +

Microsoft CAB archives,

+ +

+ +

LHA archives,

+ +

+ +

mtree file tree +descriptions,

+ +

+ +

RAR archives,

+ +

+ +

XAR archives.

+ +

The library automatically +detects archives compressed with gzip(1), bzip2(1), xz(1), +lzip(1), or compress(1) and decompresses them transparently. +It can similarly detect and decode archives processed with +uuencode(1) or which have an rpm(1) header.

+ +

When writing an +archive, you can specify the compression to be used and the +format to use. The library can write

+ +

+ +

POSIX-standard +’’ustar’’ archives,

+ +

+ +

POSIX ’’pax +interchange format’’ archives,

+ +

+ +

POSIX octet-oriented cpio +archives,

+ +

+ +

Zip archive,

+ +

+ +

two different variants of shar +archives,

+ +

+ +

ISO9660 CD images,

+ +

+ +

7-Zip archives,

+ +

+ +

ar archives,

+ +

+ +

mtree file tree +descriptions,

+ +

+ +

XAR archives.

+ +

Pax interchange format is an +extension of the tar archive format that eliminates +essentially all of the limitations of historic tar formats +in a standard fashion that is supported by POSIX-compliant +pax(1) implementations on many systems as well as several +newer implementations of tar(1). Note that the default write +format will suppress the pax extended attributes for most +entries; explicitly requesting pax format will enable those +attributes for all entries.

+ +

The read and +write APIs are accessed through the +archive_read_XXX() functions and the +archive_write_XXX() functions, respectively, and +either can be used independently of the other.

+ +

The rest of this +manual page provides an overview of the library operation. +More detailed information can be found in the individual +manual pages for each API or utility function.

+ +

READING AN ARCHIVE

+ +

See archive_read(3).

+ +

WRITING AN ARCHIVE

+ +

See archive_write(3).

+ +

WRITING ENTRIES TO +DISK

+ +

The archive_write_disk(3) API +allows you to write archive_entry(3) objects to disk using +the same API used by archive_write(3). The +archive_write_disk(3) API is used internally by +archive_read_extract(); using it directly can provide +greater control over how entries get written to disk. This +API also makes it possible to share code between +archive-to-archive copy and archive-to-disk extraction +operations.

+ +

READING ENTRIES FROM +DISK

+ +

The archive_read_disk(3) +supports for populating archive_entry(3) objects from +information in the filesystem. This includes the information +accessible from the stat(2) system call as well as ACLs, +extended attributes, and other metadata. The +archive_read_disk(3) API also supports iterating over +directory trees, which allows directories of files to be +read using an API compatible with the archive_read(3) +API.

+ +

DESCRIPTION

+ +

Detailed descriptions of each +function are provided by the corresponding manual pages.

+ +

All of the +functions utilize an opaque struct archive datatype that +provides access to the archive contents.

+ +

The struct +archive_entry structure contains a complete description of a +single archive entry. It uses an opaque interface that is +fully documented in archive_entry(3).

+ +

Users familiar +with historic formats should be aware that the newer +variants have eliminated most restrictions on the length of +textual fields. Clients should not assume that filenames, +link names, user names, or group names are limited in +length. In particular, pax interchange format can easily +accommodate pathnames in arbitrary character sets that +exceed PATH_MAX.

+ +

RETURN VALUES

+ +

Most functions return +ARCHIVE_OK (zero) on success, non-zero on error. The +return value indicates the general severity of the error, +ranging from ARCHIVE_WARN, which indicates a minor +problem that should probably be reported to the user, to +ARCHIVE_FATAL, which indicates a serious problem that +will prevent any further operations on this archive. On +error, the archive_errno() function can be used to +retrieve a numeric error code (see errno(2)). The +archive_error_string() returns a textual error +message suitable for display.

+ + +

archive_read_new() +and archive_write_new() return pointers to an +allocated and initialized struct archive object.

+ + +

archive_read_data() +and archive_write_data() return a count of the number +of bytes actually read or written. A value of zero indicates +the end of the data for this entry. A negative value +indicates an error, in which case the archive_errno() +and archive_error_string() functions can be used to +obtain more information.

+ +

ENVIRONMENT

+ +

There are character set +conversions within the archive_entry(3) functions that are +impacted by the currently-selected locale.

+ +

SEE ALSO

+ +

tar(1), archive_entry(3), +archive_read(3), archive_util(3), archive_write(3), +tar(5)

+ +

HISTORY

+ +

The libarchive library +first appeared in FreeBSD 5.3.

+ +

AUTHORS

+ +

The libarchive library +was originally written by Tim Kientzle +<kientzle@acm.org>.

+ +

BUGS

+ +

Some archive formats support +information that is not supported by struct archive_entry. +Such information cannot be fully archived or restored using +this library. This includes, for example, comments, +character sets, or the arbitrary key/value pairs that can +appear in pax interchange format archives.

+ +

Conversely, of +course, not all of the information that can be stored in an +struct archive_entry is supported by all formats. For +example, cpio formats do not support nanosecond timestamps; +old tar formats do not support large device numbers.

+ +

The ISO9660 +reader cannot yet read all ISO9660 images; it should learn +how to seek.

+ +

The AR writer +requires the client program to use two passes, unlike all +other libarchive writers.

+ +

BSD +March 18, 2012 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/libarchive_changes.3.html b/dependencies/libarchive-3.4.2/doc/html/libarchive_changes.3.html new file mode 100644 index 0000000..a19bff3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/libarchive_changes.3.html @@ -0,0 +1,464 @@ + + + + + + + + + + + + + +
+ + +

LIBARCHIVE_CHANGES(3) BSD Library Functions Manual +LIBARCHIVE_CHANGES(3)

+ +

NAME

+ +

libarchive_changes +— changes in libarchive interface

+ +

CHANGES IN LIBARCHIVE +3

+ +

This page describes user-visible +changes in libarchive3, and lists public functions and other +symbols changed, deprecated or removed in libarchive3, along +with their replacements if any.

+ +

Multiple +Filters
+Libarchive2 permitted a single (input or output) filter +active on an archive. Libarchive3 extends this into a +variable-length stack. Where +archive_write_set_compression_XXX() would replace any +existing filter, archive_write_add_filter_XXX() +extends the write pipeline with another filter.

+ +

Character Set +Handling
+Libarchive2 assumed that the local platform uses Unicode as +the native wchar_t encoding, which is true on Windows, +modern Linux, and a few other systems, but is certainly not +universal. As a result, pax format archives were written +incorrectly on some systems, since pax format requires UTF-8 +and libarchive 2 incorrectly assumed that wchar_t strings +can be easily converted to UTF-8.

+ +

Libarchive3 uses +the standard iconv library to convert between character sets +and is introducing the notion of a ’’default +character set for the archive’’. To support +this, archive_entry objects can now be bound to a particular +archive when they are created. The automatic character set +conversions performed by archive_entry objects when reading +and writing filenames, usernames, and other strings will now +use an appropriate default character set:

+ +

If the +archive_entry object is bound to an archive, it will use the +default character set for that archive.

+ +

The platform +default character encoding (as returned by +nl_langinfo(CHARSET)) will be used if nothing +else is specified.

+ +

Libarchive3 also +introduces charset options to many of the archive readers +and writers to control the character set that will be used +for filenames written in those archives. When possible, this +will be set automatically based on information in the +archive itself. Combining this with the notion of a default +character set for the archive should allow you to configure +libarchive to read archives from other platforms and have +the filenames and other information transparently converted +to the character encoding suitable for your application.

+ +

Prototype +Changes
+These changes break binary compatibility; libarchive3 has a +new shared library version to reflect these changes. The +library now uses portable wide types such as int64_t instead +of less-portable types such as off_t, gid_t, uid_t, and +ino_t.

+ +

There are a few +cases where these changes will affect your source code:

+ +

+ +

In some cases, +libarchive’s wider types will introduce the +possibility of truncation: for example, on a system with a +16-bit uid_t, you risk having uid 65536 be truncated to uid +0, which can cause serious security problems.

+ +

+ +

Typedef function pointer types +will be incompatible. For example, if you define custom skip +callbacks, you may have to use code similar to the following +if you want to support building against libarchive2 and +libarchive3:

+ +

#if +ARCHIVE_VERSION_NUMBER < 3000000
+typedef off_t myoff_t;
+#else
+typedef int64_t myoff_t;
+#endif

+ +

myoff_t
+my_skip_function(struct archive *a, void *v, myoff_t o)
+{
+... implementation ...
+}

+ +

Affected +functions:

+ +


+archive_entry_gid
(), archive_entry_set_gid() +
+•
+archive_entry_uid
(), archive_entry_set_uid() +
+•
+archive_entry_ino
(), archive_entry_set_ino() +
+•
+archive_read_data_block
(), +archive_write_data_block()
+•
+archive_read_disk_gname
(), +archive_read_disk_uname()
+•
+archive_read_disk_set_gname_lookup
(), +archive_read_disk_set_group_lookup(), +archive_read_disk_set_uname_lookup(), +archive_read_disk_set_user_lookup()
+•

+ + +

archive_skip_callback()

+ +


+archive_read_extract_set_skip_file
(), +archive_write_disk_set_skip_file(), +archive_write_set_skip_file()
+•
+archive_write_disk_set_group_lookup
(), +archive_write_disk_set_user_lookup()

+ +

Where these +functions or their arguments took or returned gid_t, ino_t, +off_t, or uid_t they now take or return int64_t or +equivalent.

+ +

Deprecated +Symbols
+Symbols deprecated in libarchive3 will be removed in +libarchive4. These symbols, along with their replacements if +any, are listed below:

+ + +

archive_position_compressed(), +archive_position_uncompressed()

+ + +

archive_filter_bytes()

+ + +

archive_compression()

+ + +

archive_filter_code()

+ + +

archive_compression_name()

+ + +

archive_filter_name()

+ +

archive_read_finish(), +archive_write_finish()

+ +

archive_read_free(), +archive_write_free()

+ + +

archive_read_open_file(), +archive_write_open_file()

+ + +

archive_read_open_filename(), +archive_write_open_filename()

+ + +

archive_read_support_compression_all()

+ + +

archive_read_support_filter_all()

+ + +

archive_read_support_compression_bzip2()

+ + +

archive_read_support_filter_bzip2()

+ + +

archive_read_support_compression_compress()

+ + +

archive_read_support_filter_compress()

+ + +

archive_read_support_compression_gzip()

+ + +

archive_read_support_filter_gzip()

+ + +

archive_read_support_compression_lzip()

+ + +

archive_read_support_filter_lzip()

+ + +

archive_read_support_compression_lzma()

+ + +

archive_read_support_filter_lzma()

+ + +

archive_read_support_compression_none()

+ + +

archive_read_support_filter_none()

+ + +

archive_read_support_compression_program()

+ + +

archive_read_support_filter_program()

+ + +

archive_read_support_compression_program_signature()

+ + +

archive_read_support_filter_program_signature()

+ + +

archive_read_support_compression_rpm()

+ + +

archive_read_support_filter_rpm()

+ + +

archive_read_support_compression_uu()

+ + +

archive_read_support_filter_uu()

+ + +

archive_read_support_compression_xz()

+ + +

archive_read_support_filter_xz()

+ + +

archive_write_set_compression_bzip2()

+ + +

archive_write_add_filter_bzip2()

+ + +

archive_write_set_compression_compress()

+ + +

archive_write_add_filter_compress()

+ + +

archive_write_set_compression_gzip()

+ + +

archive_write_add_filter_gzip()

+ + +

archive_write_set_compression_lzip()

+ + +

archive_write_add_filter_lzip()

+ + +

archive_write_set_compression_lzma()

+ + +

archive_write_add_filter_lzma()

+ + +

archive_write_set_compression_none()

+ + +

archive_write_add_filter_none()

+ + +

archive_write_set_compression_program()

+ + +

archive_write_add_filter_program()

+ + +

archive_write_set_compression_filter()

+ + +

archive_write_add_filter_filter()

+ +

Removed +Symbols
+These symbols, listed below along with their replacements if +any, were deprecated in libarchive2, and are not part of +libarchive3.

+ + +

archive_api_feature()

+ + +

archive_version_number()

+ + +

archive_api_version()

+ + +

archive_version_number()

+ +

archive_version()

+ + +

archive_version_string()

+ + +

archive_version_stamp()

+ + +

archive_version_number()

+ + +

archive_read_set_filter_options()

+ + +

archive_read_set_options() +or archive_read_set_filter_option()

+ + +

archive_read_set_format_options()

+ + +

archive_read_set_options() +or archive_read_set_format_option()

+ + +

archive_write_set_filter_options()

+ + +

archive_write_set_options() +or archive_write_set_filter_option()

+ + +

archive_write_set_format_options()

+ + +

archive_write_set_options() +or archive_write_set_format_option()

+ +

ARCHIVE_API_FEATURE

+ +

ARCHIVE_VERSION_NUMBER

+ +

ARCHIVE_API_VERSION

+ +

ARCHIVE_VERSION_NUMBER

+ +

ARCHIVE_VERSION_STAMP

+ +

ARCHIVE_VERSION_NUMBER

+ +

ARCHIVE_LIBRARY_VERSION

+ +

ARCHIVE_VERSION_STRING

+ +

ARCHIVE_COMPRESSION_NONE

+ +

ARCHIVE_FILTER_NONE

+ +

ARCHIVE_COMPRESSION_GZIP

+ +

ARCHIVE_FILTER_GZIP

+ +

ARCHIVE_COMPRESSION_BZIP2

+ +

ARCHIVE_FILTER_BZIP2

+ + +

ARCHIVE_COMPRESSION_COMPRESS

+ +

ARCHIVE_FILTER_COMPRESS

+ +

ARCHIVE_COMPRESSION_PROGRAM

+ +

ARCHIVE_FILTER_PROGRAM

+ +

ARCHIVE_COMPRESSION_LZMA

+ +

ARCHIVE_FILTER_LZMA

+ +

ARCHIVE_COMPRESSION_XZ

+ +

ARCHIVE_FILTER_XZ

+ +

ARCHIVE_COMPRESSION_UU

+ +

ARCHIVE_FILTER_UU

+ +

ARCHIVE_COMPRESSION_RPM

+ +

ARCHIVE_FILTER_RPM

+ +

ARCHIVE_COMPRESSION_LZIP

+ +

ARCHIVE_FILTER_LZIP

+ +

ARCHIVE_BYTES_PER_RECORD

+ +

512

+ + +

ARCHIVE_DEFAULT_BYTES_PER_BLOCK

+ +

10240

+ +

SEE ALSO

+ +

archive_read(3), +archive_read_filter(3), archive_read_format(3), +archive_read_set_options(3), archive_util(3), +archive_write(3), archive_write_filter(3), +archive_write_format(3), archive_write_set_options(3), +libarchive(3)

+ +

BSD +December 23, 2011 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/libarchive_internals.3.html b/dependencies/libarchive-3.4.2/doc/html/libarchive_internals.3.html new file mode 100644 index 0000000..bff4352 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/libarchive_internals.3.html @@ -0,0 +1,374 @@ + + + + + + + + + + + + + +
+ + +

LIBARCHIVE_INTERNALS(3) BSD Library Functions Manual +LIBARCHIVE_INTERNALS(3)

+ +

NAME

+ +

libarchive_internals +— description of libarchive internal interfaces

+ +

OVERVIEW

+ +

The libarchive library +provides a flexible interface for reading and writing +streaming archive files such as tar and cpio. Internally, it +follows a modular layered design that should make it easy to +add new archive and compression formats.

+ +

GENERAL ARCHITECTURE

+ +

Externally, libarchive exposes +most operations through an opaque, object-style interface. +The archive_entry(3) objects store information about a +single filesystem object. The rest of the library provides +facilities to write archive_entry(3) objects to archive +files, read them from archive files, and write them to disk. +(There are plans to add a facility to read archive_entry(3) +objects from disk as well.)

+ +

The read and +write APIs each have four layers: a public API layer, a +format layer that understands the archive file format, a +compression layer, and an I/O layer. The I/O layer is +completely exposed to clients who can replace it entirely +with their own functions.

+ +

In order to +provide as much consistency as possible for clients, some +public functions are virtualized. Eventually, it should be +possible for clients to open an archive or disk writer, and +then use a single set of code to select and write entries, +regardless of the target.

+ +

READ ARCHITECTURE

+ +

From the outside, clients use +the archive_read(3) API to manipulate an archive +object to read entries and bodies from an archive stream. +Internally, the archive object is cast to an +archive_read object, which holds all read-specific +data. The API has four layers: The lowest layer is the I/O +layer. This layer can be overridden by clients, but most +clients use the packaged I/O callbacks provided, for +example, by archive_read_open_memory(3), and +archive_read_open_fd(3). The compression layer calls the I/O +layer to read bytes and decompresses them for the format +layer. The format layer unpacks a stream of uncompressed +bytes and creates archive_entry objects from the +incoming data. The API layer tracks overall state (for +example, it prevents clients from reading data before +reading a header) and invokes the format and compression +layer operations through registered function pointers. In +particular, the API layer drives the format-detection +process: When opening the archive, it reads an initial block +of data and offers it to each registered compression +handler. The one with the highest bid is initialized with +the first block. Similarly, the format handlers are polled +to see which handler is the best for each archive. (Prior to +2.4.0, the format bidders were invoked for each entry, but +this design hindered error recovery.)

+ +

I/O Layer and +Client Callbacks
+The read API goes to some lengths to be nice to clients. As +a result, there are few restrictions on the behavior of the +client callbacks.

+ +

The client read +callback is expected to provide a block of data on each +call. A zero-length return does indicate end of file, but +otherwise blocks may be as small as one byte or as large as +the entire file. In particular, blocks may be of different +sizes.

+ +

The client skip +callback returns the number of bytes actually skipped, which +may be much smaller than the skip requested. The only +requirement is that the skip not be larger. In particular, +clients are allowed to return zero for any skip that they +don’t want to handle. The skip callback must never be +invoked with a negative value.

+ +

Keep in mind +that not all clients are reading from disk: clients reading +from networks may provide different-sized blocks on every +request and cannot skip at all; advanced clients may use +mmap(2) to read the entire file into memory at once and +return the entire file to libarchive as a single block; +other clients may begin asynchronous I/O operations for the +next block on each request.

+ + +

Decompresssion +Layer
+The decompression layer not only handles decompression, it +also buffers data so that the format handlers see a much +nicer I/O model. The decompression API is a two stage +peek/consume model. A read_ahead request specifies a minimum +read amount; the decompression layer must provide a pointer +to at least that much data. If more data is immediately +available, it should return more: the format layer handles +bulk data reads by asking for a minimum of one byte and then +copying as much data as is available.

+ +

A subsequent +call to the consume() function advances the read +pointer. Note that data returned from a read_ahead() +call is guaranteed to remain in place until the next call to +read_ahead(). Intervening calls to consume() +should not cause the data to move.

+ +

Skip requests +must always be handled exactly. Decompression handlers that +cannot seek forward should not register a skip handler; the +API layer fills in a generic skip handler that reads and +discards data.

+ +

A decompression +handler has a specific lifecycle:

+ +

Registration/Configuration

+ +

When the client invokes the +public support function, the decompression handler invokes +the internal __archive_read_register_compression() +function to provide bid and initialization functions. This +function returns NULL on error or else a pointer to a +struct decompressor_t. This structure contains a +void * config slot that can be used for storing any +customization information.

+ +

Bid

+ +

The bid +function is invoked with a pointer and size of a block of +data. The decompressor can access its config data through +the decompressor element of the archive_read +object. The bid function is otherwise stateless. In +particular, it must not perform any I/O operations.

+ +

The value +returned by the bid function indicates its suitability for +handling this data stream. A bid of zero will ensure that +this decompressor is never invoked. Return zero if magic +number checks fail. Otherwise, your initial implementation +should return the number of bits actually checked. For +example, if you verify two full bytes and three bits of +another byte, bid 19. Note that the initial block may be +very short; be careful to only inspect the data you are +given. (The current decompressors require two bytes for +correct bidding.)

+ +

Initialize

+ +

The winning bidder will have +its init function called. This function should initialize +the remaining slots of the struct decompressor_t +object pointed to by the decompressor element of the +archive_read object. In particular, it should +allocate any working data it needs in the data slot +of that structure. The init function is called with the +block of data that was used for tasting. At this point, the +decompressor is responsible for all I/O requests to the +client callbacks. The decompressor is free to read more data +as and when necessary.

+ +

Satisfy I/O requests

+ +

The format handler will invoke +the read_ahead, consume, and skip +functions as needed.

+ +

Finish

+ +

The finish +method is called only once when the archive is closed. It +should release anything stored in the data and +config slots of the decompressor object. It +should not invoke the client close callback.

+ +

Format +Layer
+The read formats have a similar lifecycle to the +decompression handlers:

+ +

Registration

+ +

Allocate your private data and +initialize your pointers.

+ +

Bid

+ +

Formats bid by +invoking the read_ahead() decompression method but +not calling the consume() method. This allows each +bidder to look ahead in the input stream. Bidders should not +look further ahead than necessary, as long look aheads put +pressure on the decompression layer to buffer lots of data. +Most formats only require a few hundred bytes of look ahead; +look aheads of a few kilobytes are reasonable. (The ISO9660 +reader sometimes looks ahead by 48k, which should be +considered an upper limit.)

+ +

Read header

+ +

The header read is usually the +most complex part of any format. There are a few strategies +worth mentioning: For formats such as tar or cpio, reading +and parsing the header is straightforward since headers +alternate with data. For formats that store all header data +at the beginning of the file, the first header read request +may have to read all headers into memory and store that +data, sorted by the location of the file data. Subsequent +header read requests will skip forward to the beginning of +the file data and return the corresponding header.

+ +

Read Data

+ +

The read data interface +supports sparse files; this requires that each call return a +block of data specifying the file offset and size. This may +require you to carefully track the location so that you can +return accurate file offsets for each read. Remember that +the decompressor will return as much data as it has. +Generally, you will want to request one byte, examine the +return value to see how much data is available, and possibly +trim that to the amount you can use. You should invoke +consume for each block just before you return it.

+ +

Skip All Data

+ +

The skip data call should skip +over all file data and trailing padding. This is called +automatically by the API layer just before each header read. +It is also called in response to the client calling the +public data_skip() function.

+ +

Cleanup

+ +

On cleanup, the format should +release all of its allocated memory.

+ +

API Layer +
+XXX to do XXX

+ +

WRITE ARCHITECTURE

+ +

The write API has a similar set +of four layers: an API layer, a format layer, a compression +layer, and an I/O layer. The registration here is much +simpler because only one format and one compression can be +registered at a time.

+ +

I/O Layer and +Client Callbacks
+XXX To be written XXX

+ +

Compression +Layer
+XXX To be written XXX

+ +

Format +Layer
+XXX To be written XXX

+ +

API Layer +
+XXX To be written XXX

+ +

WRITE_DISK +ARCHITECTURE

+ +

The write_disk API is intended +to look just like the write API to clients. Since it does +not handle multiple formats or compression, it is not +layered internally.

+ +

GENERAL SERVICES

+ +

The archive_read, +archive_write, and archive_write_disk objects +all contain an initial archive object which provides +common support for a set of standard services. (Recall that +ANSI/ISO C90 guarantees that you can cast freely between a +pointer to a structure and a pointer to the first element of +that structure.) The archive object has a magic value +that indicates which API this object is associated with, +slots for storing error information, and function pointers +for virtualized API functions.

+ +

MISCELLANEOUS NOTES

+ +

Connecting existing archiving +libraries into libarchive is generally quite difficult. In +particular, many existing libraries strongly assume that you +are reading from a file; they seek forwards and backwards as +necessary to locate various pieces of information. In +contrast, libarchive never seeks backwards in its input, +which sometimes requires very different approaches.

+ +

For example, +libarchive’s ISO9660 support operates very differently +from most ISO9660 readers. The libarchive support utilizes a +work-queue design that keeps a list of known entries sorted +by their location in the input. Whenever libarchive’s +ISO9660 implementation is asked for the next header, checks +this list to find the next item on the disk. Directories are +parsed when they are encountered and new items are added to +the list. This design relies heavily on the ISO9660 image +being optimized so that directories always occur earlier on +the disk than the files they describe.

+ +

Depending on the +specific format, such approaches may not be possible. The +ZIP format specification, for example, allows archivers to +store key information only at the end of the file. In +theory, it is possible to create ZIP archives that cannot be +read without seeking. Fortunately, such archives are very +rare, and libarchive can read most ZIP archives, though it +cannot always extract as much information as a dedicated ZIP +program.

+ +

SEE ALSO

+ +

archive_entry(3), +archive_read(3), archive_write(3), archive_write_disk(3), +libarchive(3)

+ +

HISTORY

+ +

The libarchive library +first appeared in FreeBSD 5.3.

+ +

AUTHORS

+ +

The libarchive library +was written by Tim Kientzle <kientzle@acm.org>.

+ +

BSD +January 26, 2011 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/mtree.5.html b/dependencies/libarchive-3.4.2/doc/html/mtree.5.html new file mode 100644 index 0000000..1dda8b5 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/mtree.5.html @@ -0,0 +1,383 @@ + + + + + + + + + + + + + +
+ + +

MTREE(5) BSD File Formats Manual MTREE(5)

+ +

NAME

+ +

mtree — format of +mtree dir hierarchy files

+ +

DESCRIPTION

+ +

The mtree format is a +textual format that describes a collection of filesystem +objects. Such files are typically used to create or verify +directory hierarchies.

+ +

General +Format
+An mtree file consists of a series of lines, each +providing information about a single filesystem object. +Leading whitespace is always ignored.

+ +

When encoding +file or pathnames, any backslash character or character +outside of the 95 printable ASCII characters must be encoded +as a backslash followed by three octal digits. When reading +mtree files, any appearance of a backslash followed by three +octal digits should be converted into the corresponding +character.

+ +

Each line is +interpreted independently as one of the following types:

+ +

Blank

+ +

Blank lines are +ignored.

+ +

Comment

+ +

Lines beginning +with # are ignored.

+ +

Special

+ +

Lines beginning +with / are special commands that influence the +interpretation of later lines.

+ +

Relative

+ +

If the first +whitespace-delimited word has no / characters, it is +the name of a file in the current directory. Any relative +entry that describes a directory changes the current +directory.

+ +

dot-dot

+ +

As a special +case, a relative entry with the filename .. changes +the current directory to the parent directory. Options on +dot-dot entries are always ignored.

+ +

Full

+ +

If the first +whitespace-delimited word has a / character after the +first character, it is the pathname of a file relative to +the starting directory. There can be multiple full entries +describing the same file.

+ +

Some tools that +process mtree files may require that multiple lines +describing the same file occur consecutively. It is not +permitted for the same file to be mentioned using both a +relative and a full file specification.

+ +

Special +commands
+Two special commands are currently defined:

+ +

/set

+ +

This command +defines default values for one or more keywords. It is +followed on the same line by one or more +whitespace-separated keyword definitions. These definitions +apply to all following files that do not specify a value for +that keyword.

+ +

/unset

+ +

This command +removes any default value set by a previous /set +command. It is followed on the same line by one or more +keywords separated by whitespace.

+ +

Keywords +
+After the filename, a full or relative entry consists of +zero or more whitespace-separated keyword definitions. Each +such definition consists of a key from the following list +immediately followed by an ’=’ sign and a value. +Software programs reading mtree files should warn about +unrecognized keywords.

+ +

Currently +supported keywords are as follows:

+ +

cksum

+ +

The checksum of +the file using the default algorithm specified by the +cksum(1) utility.

+ +

device

+ +

The device +number for block or char file types. The value +must be one of the following forms:

+ + +

format,major,minor[ +
+,subunit]

+ +

A device with major, +minor and optional subunit fields. Their +meaning is specified by the operating’s system +format. See below for valid formats.

+ +

number

+ +

Opaque number (as stored on the +file system).

+ +

The following +values for format are recognized: native, +386bsd, 4bsd, bsdos, freebsd, +hpux, isc, linux, netbsd, +osf1, sco, solaris, sunos, +svr3, svr4, and ultrix.

+ +

See mknod(8) +for more details.

+ +

contents

+ +

The full +pathname of a file that holds the contents of this file.

+ +

flags

+ +

The file flags +as a symbolic name. See chflags(1) for information on these +names. If no flags are to be set the string +’’none’’ may be used to override the +current default.

+ +

gid

+ +

The file group +as a numeric value.

+ +

gname

+ +

The file group +as a symbolic name.

+ +

ignore

+ +

Ignore any file +hierarchy below this file.

+ +

inode

+ +

The inode +number.

+ +

link

+ +

The target of +the symbolic link when type=link.

+ +

md5

+ +

The MD5 message +digest of the file.

+ +

md5digest

+ +

A synonym for +md5.

+ +

mode

+ +

The current +file’s permissions as a numeric (octal) or symbolic +value.

+ +

nlink

+ +

The number of +hard links the file is expected to have.

+ +

nochange

+ +

Make sure this +file or directory exists but otherwise ignore all +attributes.

+ +

optional

+ +

The file is +optional; do not complain about the file if it is not in the +file hierarchy.

+ +

resdevice

+ +

The +’’resident’’ device number of the +file, e.g. the ID of the device that contains the file. Its +format is the same as the one for device.

+ +

ripemd160digest

+ +

The RIPEMD160 message digest of +the file.

+ +

rmd160

+ +

A synonym for +ripemd160digest.

+ +

rmd160digest

+ +

A synonym for +ripemd160digest.

+ +

sha1

+ +

The FIPS 160-1 +(’’SHA-1’’) message digest of the +file.

+ +

sha1digest

+ +

A synonym for +sha1.

+ +

sha256

+ +

The FIPS 180-2 +(’’SHA-256’’) message digest of the +file.

+ +

sha256digest

+ +

A synonym for +sha256.

+ +

sha384

+ +

The FIPS 180-2 +(’’SHA-384’’) message digest of the +file.

+ +

sha384digest

+ +

A synonym for +sha384.

+ +

sha512

+ +

The FIPS 180-2 +(’’SHA-512’’) message digest of the +file.

+ +

sha512digest

+ +

A synonym for +sha512.

+ +

size

+ +

The size, in +bytes, of the file.

+ +

time

+ +

The last +modification time of the file.

+ +

type

+ +

The type of the +file; may be set to any one of the following:

+ +

block

+ +

block special +device

+ +

char

+ +

character +special device

+ +

dir

+ +

directory

+ +

fifo

+ +

fifo

+ +

file

+ +

regular +file

+ +

link

+ +

symbolic +link

+ +

socket

+ +

socket

+ +

uid

+ +

The file owner +as a numeric value.

+ +

uname

+ +

The file owner +as a symbolic name.

+ +

SEE ALSO

+ +

cksum(1), find(1), mtree(8)

+ +

HISTORY

+ +

The mtree utility +appeared in 4.3BSD-Reno. The MD5 digest capability was added +in FreeBSD 2.1, in response to the widespread use of +programs which can spoof cksum(1). The SHA-1 and RIPEMD160 +digests were added in FreeBSD 4.0, as new attacks have +demonstrated weaknesses in MD5. The SHA-256 digest was added +in FreeBSD 6.0. Support for file flags was added in +FreeBSD 4.0, and mostly comes from NetBSD. The +’’full’’ entry format was added by +NetBSD.

+ +

BSD +September 4, 2013 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/html/tar.5.html b/dependencies/libarchive-3.4.2/doc/html/tar.5.html new file mode 100644 index 0000000..b3f0f03 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/html/tar.5.html @@ -0,0 +1,1558 @@ + + + + + + + + + + + + + +
+ + +

TAR(5) BSD File Formats Manual TAR(5)

+ +

NAME

+ +

tar — format of +tape archive files

+ +

DESCRIPTION

+ +

The tar archive format +collects any number of files, directories, and other file +system objects (symbolic links, device nodes, etc.) into a +single stream of bytes. The format was originally designed +to be used with tape drives that operate with fixed-size +blocks, but is widely used as a general packaging +mechanism.

+ +

General +Format
+A tar archive consists of a series of 512-byte +records. Each file system object requires a header record +which stores basic metadata (pathname, owner, permissions, +etc.) and zero or more records containing any file data. The +end of the archive is indicated by two records consisting +entirely of zero bytes.

+ +

For +compatibility with tape drives that use fixed block sizes, +programs that read or write tar files always read or write a +fixed number of records with each I/O operation. These +’’blocks’’ are always a multiple of +the record size. The maximum block size supported by early +implementations was 10240 bytes or 20 records. This is still +the default for most implementations although block sizes of +1MiB (2048 records) or larger are commonly used with modern +high-speed tape drives. (Note: the terms +’’block’’ and +’’record’’ here are not entirely +standard; this document follows the convention established +by John Gilmore in documenting pdtar.)

+ +

Old-Style +Archive Format
+The original tar archive format has been extended many times +to include additional information that various implementors +found necessary. This section describes the variant +implemented by the tar command included in Version 7 +AT&T UNIX, which seems to be the earliest widely-used +version of the tar program.

+ +

The header +record for an old-style tar archive consists of the +following:

+ +

struct +header_old_tar {

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +

char name[100];

+
+ + +

char mode[8];

+
+ + +

char uid[8];

+
+ + +

char gid[8];

+
+ + +

char size[12];

+
+ + +

char mtime[12];

+
+ + +

char checksum[8];

+
+ + +

char linkflag[1];

+
+ + +

char linkname[100];

+
+ + +

char pad[255];

+
+ +

};

+ +

All unused bytes in the header +record are filled with nulls.

+ +

name

+ +

Pathname, +stored as a null-terminated string. Early tar +implementations only stored regular files (including +hardlinks to those files). One common early convention used +a trailing "/" character to indicate a directory +name, allowing directory permissions and owner information +to be archived and restored.

+ +

mode

+ +

File mode, +stored as an octal number in ASCII.

+ +

uid, gid

+ +

User id and group id of owner, +as octal numbers in ASCII.

+ +

size

+ +

Size of file, +as octal number in ASCII. For regular files only, this +indicates the amount of data that follows the header. In +particular, this field was ignored by early tar +implementations when extracting hardlinks. Modern writers +should always store a zero length for hardlink entries.

+ +

mtime

+ +

Modification +time of file, as an octal number in ASCII. This indicates +the number of seconds since the start of the epoch, 00:00:00 +UTC January 1, 1970. Note that negative values should be +avoided here, as they are handled inconsistently.

+ +

checksum

+ +

Header checksum, stored as an +octal number in ASCII. To compute the checksum, set the +checksum field to all spaces, then sum all bytes in the +header using unsigned arithmetic. This field should be +stored as six octal digits followed by a null and a space +character. Note that many early implementations of tar used +signed arithmetic for the checksum field, which can cause +interoperability problems when transferring archives between +systems. Modern robust readers compute the checksum both +ways and accept the header if either computation +matches.

+ +

linkflag, +linkname

+ +

In order to preserve hardlinks +and conserve tape, a file with multiple links is only +written to the archive the first time it is encountered. The +next time it is encountered, the linkflag is set to +an ASCII ’1’ and the linkname field holds +the first name under which this file appears. (Note that +regular files have a null value in the linkflag +field.)

+ +

Early tar +implementations varied in how they terminated these fields. +The tar command in Version 7 AT&T UNIX used the +following conventions (this is also documented in early BSD +manpages): the pathname must be null-terminated; the mode, +uid, and gid fields must end in a space and a null byte; the +size and mtime fields must end in a space; the checksum is +terminated by a null and a space. Early implementations +filled the numeric fields with leading spaces. This seems to +have been common practice until the IEEE Std 1003.1-1988 +(’’POSIX.1’’) standard was released. +For best portability, modern implementations should fill the +numeric fields with leading zeros.

+ +

Pre-POSIX +Archives
+An early draft of IEEE Std 1003.1-1988 +(’’POSIX.1’’) served as the basis +for John Gilmore’s pdtar program and many +system implementations from the late 1980s and early 1990s. +These archives generally follow the POSIX ustar format +described below with the following variations:

+ +

+ +

The magic value consists of the +five characters ’’ustar’’ followed +by a space. The version field contains a space character +followed by a null.

+ +

+ +

The numeric fields are +generally filled with leading spaces (not leading zeros as +recommended in the final standard).

+ +

+ +

The prefix field is often not +used, limiting pathnames to the 100 characters of old-style +archives.

+ +

POSIX ustar +Archives
+IEEE Std 1003.1-1988 (’’POSIX.1’’) +defined a standard tar file format to be read and written by +compliant implementations of tar(1). This format is often +called the ’’ustar’’ format, after +the magic value used in the header. (The name is an acronym +for ’’Unix Standard TAR’’.) It +extends the historic format with new fields:

+ +

struct +header_posix_ustar {

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +

char name[100];

+
+ + +

char mode[8];

+
+ + +

char uid[8];

+
+ + +

char gid[8];

+
+ + +

char size[12];

+
+ + +

char mtime[12];

+
+ + +

char checksum[8];

+
+ + +

char typeflag[1];

+
+ + +

char linkname[100];

+
+ + +

char magic[6];

+
+ + +

char version[2];

+
+ + +

char uname[32];

+
+ + +

char gname[32];

+
+ + +

char devmajor[8];

+
+ + +

char devminor[8];

+
+ + +

char prefix[155];

+
+ + +

char pad[12];

+
+ +

};

+ +

typeflag

+ +

Type of entry. POSIX extended +the earlier linkflag field with several new type +values:

+ +

’’0’’

+ +

Regular file. +NUL should be treated as a synonym, for compatibility +purposes.

+ +

’’1’’

+ +

Hard link.

+ +

’’2’’

+ +

Symbolic +link.

+ +

’’3’’

+ +

Character +device node.

+ +

’’4’’

+ +

Block device +node.

+ +

’’5’’

+ +

Directory.

+ +

’’6’’

+ +

FIFO node.

+ +

’’7’’

+ +

Reserved.

+ +

Other

+ +

A +POSIX-compliant implementation must treat any unrecognized +typeflag value as a regular file. In particular, writers +should ensure that all entries have a valid filename so that +they can be restored by readers that do not support the +corresponding extension. Uppercase letters "A" +through "Z" are reserved for custom extensions. +Note that sockets and whiteout entries are not +archivable.

+ +

It is worth noting that the +size field, in particular, has different meanings +depending on the type. For regular files, of course, it +indicates the amount of data following the header. For +directories, it may be used to indicate the total size of +all files in the directory, for use by operating systems +that pre-allocate directory space. For all other types, it +should be set to zero by writers and ignored by readers.

+ +

magic

+ +

Contains the +magic value ’’ustar’’ followed by a +NUL byte to indicate that this is a POSIX standard archive. +Full compliance requires the uname and gname fields be +properly set.

+ +

version

+ +

Version. This should be +’’00’’ (two copies of the ASCII +digit zero) for POSIX standard archives.

+ +

uname, gname

+ +

User and group names, as +null-terminated ASCII strings. These should be used in +preference to the uid/gid values when they are set and the +corresponding names exist on the system.

+ +

devmajor, +devminor

+ +

Major and minor numbers for +character device or block device entry.

+ +

name, prefix

+ +

If the pathname is too long to +fit in the 100 bytes provided by the standard format, it can +be split at any / character with the first portion +going into the prefix field. If the prefix field is not +empty, the reader will prepend the prefix value and a +/ character to the regular name field to obtain the +full pathname. The standard does not require a trailing +/ character on directory names, though most +implementations still include this for compatibility +reasons.

+ +

Note that all +unused bytes must be set to NUL.

+ +

Field +termination is specified slightly differently by POSIX than +by previous implementations. The magic, uname, +and gname fields must have a trailing NUL. The +pathname, linkname, and prefix fields +must have a trailing NUL unless they fill the entire field. +(In particular, it is possible to store a 256-character +pathname if it happens to have a / as the 156th +character.) POSIX requires numeric fields to be zero-padded +in the front, and requires them to be terminated with either +space or NUL characters.

+ +

Currently, most +tar implementations comply with the ustar format, +occasionally extending it by adding new fields to the blank +area at the end of the header record.

+ +

Numeric +Extensions
+There have been several attempts to extend the range of +sizes or times supported by modifying how numbers are stored +in the header.

+ +

One obvious +extension to increase the size of files is to eliminate the +terminating characters from the various numeric fields. For +example, the standard only allows the size field to contain +11 octal digits, reserving the twelfth byte for a trailing +NUL character. Allowing 12 octal digits allows file sizes up +to 64 GB.

+ +

Another +extension, utilized by GNU tar, star, and other newer +tar implementations, permits binary numbers in the +standard numeric fields. This is flagged by setting the high +bit of the first byte. The remainder of the field is treated +as a signed twos-complement value. This permits 95-bit +values for the length and time fields and 63-bit values for +the uid, gid, and device numbers. In particular, this +provides a consistent way to handle negative time values. +GNU tar supports this extension for the length, mtime, +ctime, and atime fields. Joerg Schilling’s star +program and the libarchive library support this extension +for all numeric fields. Note that this extension is largely +obsoleted by the extended attribute record provided by the +pax interchange format.

+ +

Another early +GNU extension allowed base-64 values rather than octal. This +extension was short-lived and is no longer supported by any +implementation.

+ +

Pax +Interchange Format
+There are many attributes that cannot be portably stored in +a POSIX ustar archive. IEEE Std 1003.1-2001 +(’’POSIX.1’’) defined a +’’pax interchange format’’ that uses +two new types of entries to hold text-formatted metadata +that applies to following entries. Note that a pax +interchange format archive is a ustar archive in every +respect. The new data is stored in ustar-compatible archive +entries that use the ’’x’’ or +’’g’’ typeflag. In particular, older +implementations that do not fully support these extensions +will extract the metadata into regular files, where the +metadata can be examined as necessary.

+ +

An entry in a +pax interchange format archive consists of one or two +standard ustar entries, each with its own header and data. +The first optional entry stores the extended attributes for +the following entry. This optional first entry has an +"x" typeflag and a size field that indicates the +total size of the extended attributes. The extended +attributes themselves are stored as a series of text-format +lines encoded in the portable UTF-8 encoding. Each line +consists of a decimal number, a space, a key string, an +equals sign, a value string, and a new line. The decimal +number indicates the length of the entire line, including +the initial length field and the trailing newline. An +example of such a field is:

+ +

25 ctime=1084839148.1212\n

+ +

Keys in all lowercase are +standard keys. Vendors can add their own keys by prefixing +them with an all uppercase vendor name and a period. Note +that, unlike the historic header, numeric values are stored +using decimal, not octal. A description of some common keys +follows:

+ +

atime, ctime, +mtime

+ +

File access, inode change, and +modification times. These fields can be negative or include +a decimal point and a fractional value.

+ +

hdrcharset

+ +

The character set used by the +pax extension values. By default, all textual values in the +pax extended attributes are assumed to be in UTF-8, +including pathnames, user names, and group names. In some +cases, it is not possible to translate local conventions +into UTF-8. If this key is present and the value is the +six-character ASCII string +’’BINARY’’, then all textual values +are assumed to be in a platform-dependent multi-byte +encoding. Note that there are only two valid values for this +key: ’’BINARY’’ or +’’ISO-IR 10646 2000 UTF-8’’. +No other values are permitted by the standard, and the +latter value should generally not be used as it is the +default when this key is not specified. In particular, this +flag should not be used as a general mechanism to allow +filenames to be stored in arbitrary encodings.

+ +

uname, uid, +gname, gid

+ +

User name, group name, and +numeric UID and GID values. The user name and group name +stored here are encoded in UTF8 and can thus include +non-ASCII characters. The UID and GID fields can be of +arbitrary length.

+ +

linkpath

+ +

The full path of the linked-to +file. Note that this is encoded in UTF8 and can thus include +non-ASCII characters.

+ +

path

+ +

The full +pathname of the entry. Note that this is encoded in UTF8 and +can thus include non-ASCII characters.

+ +

realtime.*, +security.*

+ +

These keys are reserved and may +be used for future standardization.

+ +

size

+ +

The size of the +file. Note that there is no length limit on this field, +allowing conforming archives to store files much larger than +the historic 8GB limit.

+ +

SCHILY.*

+ +

Vendor-specific attributes used +by Joerg Schilling’s star implementation.

+ +

SCHILY.acl.access, +SCHILY.acl.default, SCHILY.acl.ace

+ +

Stores the access, default and +NFSv4 ACLs as textual strings in a format that is an +extension of the format specified by POSIX.1e draft 17. In +particular, each user or group access specification can +include an additional colon-separated field with the numeric +UID or GID. This allows ACLs to be restored on systems that +may not have complete user or group information available +(such as when NIS/YP or LDAP services are temporarily +unavailable).

+ +

SCHILY.devminor, +SCHILY.devmajor

+ +

The full minor and major +numbers for device nodes.

+ +

SCHILY.fflags

+ +

The file flags.

+ +

SCHILY.realsize

+ +

The full size of the file on +disk. XXX explain? XXX

+ +

SCHILY.dev, +SCHILY.ino, SCHILY.nlinks

+ +

The device number, inode +number, and link count for the entry. In particular, note +that a pax interchange format archive using Joerg +Schilling’s SCHILY.* extensions can store all +of the data from struct stat.

+ +

LIBARCHIVE.*

+ +

Vendor-specific attributes used +by the libarchive library and programs that use +it.

+ + +

LIBARCHIVE.creationtime

+ +

The time when the file was +created. (This should not be confused with the POSIX +’’ctime’’ attribute, which refers to +the time when the file metadata was last changed.)

+ + +

LIBARCHIVE.xattr.namespace.key

+ +

Libarchive stores +POSIX.1e-style extended attributes using keys of this form. +The key value is URL-encoded: All non-ASCII +characters and the two special characters +’’=’’ and +’’%’’ are encoded as +’’%’’ followed by two uppercase +hexadecimal digits. The value of this key is the extended +attribute value encoded in base 64. XXX Detail the base-64 +format here XXX

+ +

VENDOR.*

+ +

XXX document other +vendor-specific extensions XXX

+ +

Any values +stored in an extended attribute override the corresponding +values in the regular tar header. Note that compliant +readers should ignore the regular fields when they are +overridden. This is important, as existing archivers are +known to store non-compliant values in the standard header +fields in this situation. There are no limits on length for +any of these fields. In particular, numeric fields can be +arbitrarily large. All text fields are encoded in UTF8. +Compliant writers should store only portable 7-bit ASCII +characters in the standard ustar header and use extended +attributes whenever a text value contains non-ASCII +characters.

+ +

In addition to +the x entry described above, the pax interchange +format also supports a g entry. The g entry is +identical in format, but specifies attributes that serve as +defaults for all subsequent archive entries. The g +entry is not widely used.

+ +

Besides the new +x and g entries, the pax interchange format +has a few other minor variations from the earlier ustar +format. The most troubling one is that hardlinks are +permitted to have data following them. This allows readers +to restore any hardlink to a file without having to rewind +the archive to find an earlier entry. However, it creates +complications for robust readers, as it is no longer clear +whether or not they should ignore the size field for +hardlink entries.

+ +

GNU Tar +Archives
+The GNU tar program started with a pre-POSIX format similar +to that described earlier and has extended it using several +different mechanisms: It added new fields to the empty space +in the header (some of which was later used by POSIX for +conflicting purposes); it allowed the header to be continued +over multiple records; and it defined new entries that +modify following entries (similar in principle to the +x entry described above, but each GNU special entry +is single-purpose, unlike the general-purpose x +entry). As a result, GNU tar archives are not POSIX +compatible, although more lenient POSIX-compliant readers +can successfully extract most GNU tar archives.

+ +

struct +header_gnu_tar {

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +

char name[100];

+
+ + +

char mode[8];

+
+ + +

char uid[8];

+
+ + +

char gid[8];

+
+ + +

char size[12];

+
+ + +

char mtime[12];

+
+ + +

char checksum[8];

+
+ + +

char typeflag[1];

+
+ + +

char linkname[100];

+
+ + +

char magic[6];

+
+ + +

char version[2];

+
+ + +

char uname[32];

+
+ + +

char gname[32];

+
+ + +

char devmajor[8];

+
+ + +

char devminor[8];

+
+ + +

char atime[12];

+
+ + +

char ctime[12];

+
+ + +

char offset[12];

+
+ + +

char longnames[4];

+
+ + +

char unused[1];

+
+ + +

struct {

+
+ + + +

char offset[12];

+
+ + + +

char numbytes[12];

+
+ + +

} sparse[4];

+
+ + +

char isextended[1];

+
+ + +

char realsize[12];

+
+ + +

char pad[17];

+
+ +

};

+ +

typeflag

+ +

GNU tar uses the following +special entry types, in addition to those defined by +POSIX:

+ +

7

+ +

GNU tar treats +type "7" records identically to type "0" +records, except on one obscure RTOS where they are used to +indicate the pre-allocation of a contiguous file on +disk.

+ +

D

+ +

This indicates +a directory entry. Unlike the POSIX-standard "5" +typeflag, the header is followed by data records listing the +names of files in this directory. Each name is preceded by +an ASCII "Y" if the file is stored in this archive +or "N" if the file is not stored in this archive. +Each name is terminated with a null, and an extra null marks +the end of the name list. The purpose of this entry is to +support incremental backups; a program restoring from such +an archive may wish to delete files on disk that did not +exist in the directory when the archive was made.

+ +

Note that the +"D" typeflag specifically violates POSIX, which +requires that unrecognized typeflags be restored as normal +files. In this case, restoring the "D" entry as a +file could interfere with subsequent creation of the +like-named directory.

+ +

K

+ +

The data for +this entry is a long linkname for the following regular +entry.

+ +

L

+ +

The data for +this entry is a long pathname for the following regular +entry.

+ +

M

+ +

This is a +continuation of the last file on the previous volume. GNU +multi-volume archives guarantee that each volume begins with +a valid entry header. To ensure this, a file may be split, +with part stored at the end of one volume, and part stored +at the beginning of the next volume. The "M" +typeflag indicates that this entry continues an existing +file. Such entries can only occur as the first or second +entry in an archive (the latter only if the first entry is a +volume label). The size field specifies the size of +this entry. The offset field at bytes 369-380 +specifies the offset where this file fragment begins. The +realsize field specifies the total size of the file +(which must equal size plus offset). When +extracting, GNU tar checks that the header file name is the +one it is expecting, that the header offset is in the +correct sequence, and that the sum of offset and size is +equal to realsize.

+ +

N

+ +

Type +"N" records are no longer generated by GNU tar. +They contained a list of files to be renamed or symlinked +after extraction; this was originally used to support long +names. The contents of this record are a text description of +the operations to be done, in the form ’’Rename +%s to %s\n’’ or ’’Symlink %s to +%s\n’’; in either case, both filenames are +escaped using K&R C syntax. Due to security concerns, +"N" records are now generally ignored when reading +archives.

+ +

S

+ +

This is a +’’sparse’’ regular file. Sparse +files are stored as a series of fragments. The header +contains a list of fragment offset/length pairs. If more +than four such entries are required, the header is extended +as necessary with ’’extra’’ header +extensions (an older format that is no longer used), or +’’sparse’’ extensions.

+ +

V

+ +

The name +field should be interpreted as a tape/volume header name. +This entry should generally be ignored on extraction.

+ +

magic

+ +

The magic field +holds the five characters ’’ustar’’ +followed by a space. Note that POSIX ustar archives have a +trailing null.

+ +

version

+ +

The version field holds a space +character followed by a null. Note that POSIX ustar archives +use two copies of the ASCII digit +’’0’’.

+ +

atime, ctime

+ +

The time the file was last +accessed and the time of last change of file information, +stored in octal as with mtime.

+ +

longnames

+ +

This field is apparently no +longer used.

+ +

Sparse offset / +numbytes

+ +

Each such structure specifies a +single fragment of a sparse file. The two fields store +values as octal numbers. The fragments are each padded to a +multiple of 512 bytes in the archive. On extraction, the +list of fragments is collected from the header (including +any extension headers), and the data is then read and +written to the file at appropriate offsets.

+ +

isextended

+ +

If this is set to non-zero, the +header will be followed by additional ’’sparse +header’’ records. Each such record contains +information about as many as 21 additional sparse blocks as +shown here:

+ +

struct +gnu_sparse_header {

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +

struct {

+
+ + + +

char offset[12];

+
+ + + +

char numbytes[12];

+
+ + +

} sparse[21];

+
+ + +

char isextended[1];

+
+ + +

char padding[7];

+
+ +

};

+ +

realsize

+ +

A binary representation of the +file’s complete size, with a much larger range than +the POSIX file size. In particular, with M type +files, the current entry is only a portion of the file. In +that case, the POSIX size field will indicate the size of +this entry; the realsize field will indicate the +total size of the file.

+ +

GNU tar pax +archives
+GNU tar 1.14 (XXX check this XXX) and later will write pax +interchange format archives when you specify the +--posix flag. This format follows the pax interchange +format closely, using some SCHILY tags and +introducing new keywords to store sparse file information. +There have been three iterations of the sparse file support, +referred to as ’’0.0’’, +’’0.1’’, and +’’1.0’’.

+ +

GNU.sparse.numblocks, +GNU.sparse.offset, GNU.sparse.numbytes, +GNU.sparse.size

+ +

The +’’0.0’’ format used an initial +GNU.sparse.numblocks attribute to indicate the number +of blocks in the file, a pair of GNU.sparse.offset +and GNU.sparse.numbytes to indicate the offset and +size of each block, and a single GNU.sparse.size to +indicate the full size of the file. This is not the same as +the size in the tar header because the latter value does not +include the size of any holes. This format required that the +order of attributes be preserved and relied on readers +accepting multiple appearances of the same attribute names, +which is not officially permitted by the standards.

+ +

GNU.sparse.map

+ +

The +’’0.1’’ format used a single +attribute that stored a comma-separated list of decimal +numbers. Each pair of numbers indicated the offset and size, +respectively, of a block of data. This does not work well if +the archive is extracted by an archiver that does not +recognize this extension, since many pax implementations +simply discard unrecognized attributes.

+ +

GNU.sparse.major, +GNU.sparse.minor, GNU.sparse.name, +GNU.sparse.realsize

+ +

The +’’1.0’’ format stores the sparse +block map in one or more 512-byte blocks prepended to the +file data in the entry body. The pax attributes indicate the +existence of this map (via the GNU.sparse.major and +GNU.sparse.minor fields) and the full size of the +file. The GNU.sparse.name holds the true name of the +file. To avoid confusion, the name stored in the regular tar +header is a modified name so that extraction errors will be +apparent to users.

+ +

Solaris +Tar
+XXX More Details Needed XXX

+ +

Solaris tar +(beginning with SunOS XXX 5.7 ?? XXX) supports an +’’extended’’ format that is +fundamentally similar to pax interchange format, with the +following differences:

+ +

+ +

Extended attributes are stored +in an entry whose type is X, not x, as used by +pax interchange format. The detailed format of this entry +appears to be the same as detailed above for the x +entry.

+ +

+ +

An additional A header +is used to store an ACL for the following regular entry. The +body of this entry contains a seven-digit octal number +followed by a zero byte, followed by the textual ACL +description. The octal value is the number of ACL entries +plus a constant that indicates the ACL type: 01000000 for +POSIX.1e ACLs and 03000000 for NFSv4 ACLs.

+ +

AIX Tar +
+XXX More details needed XXX

+ +

AIX Tar uses a +ustar-formatted header with the type A for storing +coded ACL information. Unlike the Solaris format, AIX tar +writes this header after the regular file body to which it +applies. The pathname in this header is either NFS4 +or AIXC to indicate the type of ACL stored. The +actual ACL is stored in platform-specific binary format.

+ +

Mac OS X +Tar
+The tar distributed with Apple’s Mac OS X stores most +regular files as two separate files in the tar archive. The +two files have the same name except that the first one has +’’._’’ prepended to the last path +element. This special file stores an AppleDouble-encoded +binary blob with additional metadata about the second file, +including ACL, extended attributes, and resources. To +recreate the original file on disk, each separate file can +be extracted and the Mac OS X copyfile() function can +be used to unpack the separate metadata file and apply it to +th regular file. Conversely, the same function provides a +’’pack’’ option to encode the +extended metadata from a file into a separate file whose +contents can then be put into a tar archive.

+ +

Note that the +Apple extended attributes interact badly with long +filenames. Since each file is stored with the full name, a +separate set of extensions needs to be included in the +archive for each one, doubling the overhead required for +files with long names.

+ +

Summary of +tar type codes
+The following list is a condensed summary of the type codes +used in tar header records generated by different tar +implementations. More details about specific implementations +can be found above:

+ +

NUL

+ +

Early tar +programs stored a zero byte for regular files.

+ +

0

+ +

POSIX standard +type code for a regular file.

+ +

1

+ +

POSIX standard +type code for a hard link description.

+ +

2

+ +

POSIX standard +type code for a symbolic link description.

+ +

3

+ +

POSIX standard +type code for a character device node.

+ +

4

+ +

POSIX standard +type code for a block device node.

+ +

5

+ +

POSIX standard +type code for a directory.

+ +

6

+ +

POSIX standard +type code for a FIFO.

+ +

7

+ +

POSIX +reserved.

+ +

7

+ +

GNU tar used +for pre-allocated files on some systems.

+ +

A

+ +

Solaris tar ACL +description stored prior to a regular file header.

+ +

A

+ +

AIX tar ACL +description stored after the file body.

+ +

D

+ +

GNU tar +directory dump.

+ +

K

+ +

GNU tar long +linkname for the following header.

+ +

L

+ +

GNU tar long +pathname for the following header.

+ +

M

+ +

GNU tar +multivolume marker, indicating the file is a continuation of +a file from the previous volume.

+ +

N

+ +

GNU tar long +filename support. Deprecated.

+ +

S

+ +

GNU tar sparse +regular file.

+ +

V

+ +

GNU tar +tape/volume header name.

+ +

X

+ +

Solaris tar +general-purpose extension header.

+ +

g

+ +

POSIX pax +interchange format global extensions.

+ +

x

+ +

POSIX pax +interchange format per-file extensions.

+ +

SEE ALSO

+ +

ar(1), pax(1), tar(1)

+ +

STANDARDS

+ +

The tar utility is no +longer a part of POSIX or the Single Unix Standard. It last +appeared in Version 2 of the Single UNIX Specification +(’’SUSv2’’). It has been supplanted +in subsequent standards by pax(1). The ustar format is +currently part of the specification for the pax(1) utility. +The pax interchange file format is new with IEEE Std +1003.1-2001 (’’POSIX.1’’).

+ +

HISTORY

+ +

A tar command appeared in +Seventh Edition Unix, which was released in January, 1979. +It replaced the tp program from Fourth Edition Unix +which in turn replaced the tap program from First +Edition Unix. John Gilmore’s pdtar +public-domain implementation (circa 1987) was highly +influential and formed the basis of GNU tar (circa +1988). Joerg Shilling’s star archiver is +another open-source (CDDL) archiver (originally developed +circa 1985) which features complete support for pax +interchange format.

+ +

This +documentation was written as part of the libarchive +and bsdtar project by Tim Kientzle +<kientzle@FreeBSD.org>.

+ +

BSD +December 27, 2016 BSD

+
+ + diff --git a/dependencies/libarchive-3.4.2/doc/man/.ignore_me b/dependencies/libarchive-3.4.2/doc/man/.ignore_me new file mode 100644 index 0000000..d285484 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/.ignore_me @@ -0,0 +1,2 @@ +*** PLEASE DO NOT DELETE THIS FILE! *** +This file is used to track an otherwise empty directory in git. diff --git a/dependencies/libarchive-3.4.2/doc/man/Makefile b/dependencies/libarchive-3.4.2/doc/man/Makefile new file mode 100644 index 0000000..1d56a6d --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/Makefile @@ -0,0 +1,133 @@ + +default: all + + +archive_entry.3: ../mdoc2man.awk ../../libarchive/archive_entry.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_entry.3 > archive_entry.3 + +archive_entry_acl.3: ../mdoc2man.awk ../../libarchive/archive_entry_acl.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_entry_acl.3 > archive_entry_acl.3 + +archive_entry_linkify.3: ../mdoc2man.awk ../../libarchive/archive_entry_linkify.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_entry_linkify.3 > archive_entry_linkify.3 + +archive_entry_misc.3: ../mdoc2man.awk ../../libarchive/archive_entry_misc.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_entry_misc.3 > archive_entry_misc.3 + +archive_entry_paths.3: ../mdoc2man.awk ../../libarchive/archive_entry_paths.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_entry_paths.3 > archive_entry_paths.3 + +archive_entry_perms.3: ../mdoc2man.awk ../../libarchive/archive_entry_perms.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_entry_perms.3 > archive_entry_perms.3 + +archive_entry_stat.3: ../mdoc2man.awk ../../libarchive/archive_entry_stat.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_entry_stat.3 > archive_entry_stat.3 + +archive_entry_time.3: ../mdoc2man.awk ../../libarchive/archive_entry_time.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_entry_time.3 > archive_entry_time.3 + +archive_read.3: ../mdoc2man.awk ../../libarchive/archive_read.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_read.3 > archive_read.3 + +archive_read_add_passphrase.3: ../mdoc2man.awk ../../libarchive/archive_read_add_passphrase.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_read_add_passphrase.3 > archive_read_add_passphrase.3 + +archive_read_data.3: ../mdoc2man.awk ../../libarchive/archive_read_data.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_read_data.3 > archive_read_data.3 + +archive_read_disk.3: ../mdoc2man.awk ../../libarchive/archive_read_disk.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_read_disk.3 > archive_read_disk.3 + +archive_read_extract.3: ../mdoc2man.awk ../../libarchive/archive_read_extract.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_read_extract.3 > archive_read_extract.3 + +archive_read_filter.3: ../mdoc2man.awk ../../libarchive/archive_read_filter.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_read_filter.3 > archive_read_filter.3 + +archive_read_format.3: ../mdoc2man.awk ../../libarchive/archive_read_format.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_read_format.3 > archive_read_format.3 + +archive_read_free.3: ../mdoc2man.awk ../../libarchive/archive_read_free.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_read_free.3 > archive_read_free.3 + +archive_read_header.3: ../mdoc2man.awk ../../libarchive/archive_read_header.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_read_header.3 > archive_read_header.3 + +archive_read_new.3: ../mdoc2man.awk ../../libarchive/archive_read_new.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_read_new.3 > archive_read_new.3 + +archive_read_open.3: ../mdoc2man.awk ../../libarchive/archive_read_open.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_read_open.3 > archive_read_open.3 + +archive_read_set_options.3: ../mdoc2man.awk ../../libarchive/archive_read_set_options.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_read_set_options.3 > archive_read_set_options.3 + +archive_util.3: ../mdoc2man.awk ../../libarchive/archive_util.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_util.3 > archive_util.3 + +archive_write.3: ../mdoc2man.awk ../../libarchive/archive_write.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_write.3 > archive_write.3 + +archive_write_blocksize.3: ../mdoc2man.awk ../../libarchive/archive_write_blocksize.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_write_blocksize.3 > archive_write_blocksize.3 + +archive_write_data.3: ../mdoc2man.awk ../../libarchive/archive_write_data.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_write_data.3 > archive_write_data.3 + +archive_write_disk.3: ../mdoc2man.awk ../../libarchive/archive_write_disk.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_write_disk.3 > archive_write_disk.3 + +archive_write_filter.3: ../mdoc2man.awk ../../libarchive/archive_write_filter.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_write_filter.3 > archive_write_filter.3 + +archive_write_finish_entry.3: ../mdoc2man.awk ../../libarchive/archive_write_finish_entry.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_write_finish_entry.3 > archive_write_finish_entry.3 + +archive_write_format.3: ../mdoc2man.awk ../../libarchive/archive_write_format.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_write_format.3 > archive_write_format.3 + +archive_write_free.3: ../mdoc2man.awk ../../libarchive/archive_write_free.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_write_free.3 > archive_write_free.3 + +archive_write_header.3: ../mdoc2man.awk ../../libarchive/archive_write_header.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_write_header.3 > archive_write_header.3 + +archive_write_new.3: ../mdoc2man.awk ../../libarchive/archive_write_new.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_write_new.3 > archive_write_new.3 + +archive_write_open.3: ../mdoc2man.awk ../../libarchive/archive_write_open.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_write_open.3 > archive_write_open.3 + +archive_write_set_options.3: ../mdoc2man.awk ../../libarchive/archive_write_set_options.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_write_set_options.3 > archive_write_set_options.3 + +archive_write_set_passphrase.3: ../mdoc2man.awk ../../libarchive/archive_write_set_passphrase.3 + awk -f ../mdoc2man.awk < ../../libarchive/archive_write_set_passphrase.3 > archive_write_set_passphrase.3 + +cpio.5: ../mdoc2man.awk ../../libarchive/cpio.5 + awk -f ../mdoc2man.awk < ../../libarchive/cpio.5 > cpio.5 + +libarchive-formats.5: ../mdoc2man.awk ../../libarchive/libarchive-formats.5 + awk -f ../mdoc2man.awk < ../../libarchive/libarchive-formats.5 > libarchive-formats.5 + +libarchive.3: ../mdoc2man.awk ../../libarchive/libarchive.3 + awk -f ../mdoc2man.awk < ../../libarchive/libarchive.3 > libarchive.3 + +libarchive_changes.3: ../mdoc2man.awk ../../libarchive/libarchive_changes.3 + awk -f ../mdoc2man.awk < ../../libarchive/libarchive_changes.3 > libarchive_changes.3 + +libarchive_internals.3: ../mdoc2man.awk ../../libarchive/libarchive_internals.3 + awk -f ../mdoc2man.awk < ../../libarchive/libarchive_internals.3 > libarchive_internals.3 + +mtree.5: ../mdoc2man.awk ../../libarchive/mtree.5 + awk -f ../mdoc2man.awk < ../../libarchive/mtree.5 > mtree.5 + +tar.5: ../mdoc2man.awk ../../libarchive/tar.5 + awk -f ../mdoc2man.awk < ../../libarchive/tar.5 > tar.5 + +bsdtar.1: ../mdoc2man.awk ../../tar/bsdtar.1 + awk -f ../mdoc2man.awk < ../../tar/bsdtar.1 > bsdtar.1 + +bsdcpio.1: ../mdoc2man.awk ../../cpio/bsdcpio.1 + awk -f ../mdoc2man.awk < ../../cpio/bsdcpio.1 > bsdcpio.1 +all: archive_entry.3 archive_entry_acl.3 archive_entry_linkify.3 archive_entry_misc.3 archive_entry_paths.3 archive_entry_perms.3 archive_entry_stat.3 archive_entry_time.3 archive_read.3 archive_read_add_passphrase.3 archive_read_data.3 archive_read_disk.3 archive_read_extract.3 archive_read_filter.3 archive_read_format.3 archive_read_free.3 archive_read_header.3 archive_read_new.3 archive_read_open.3 archive_read_set_options.3 archive_util.3 archive_write.3 archive_write_blocksize.3 archive_write_data.3 archive_write_disk.3 archive_write_filter.3 archive_write_finish_entry.3 archive_write_format.3 archive_write_free.3 archive_write_header.3 archive_write_new.3 archive_write_open.3 archive_write_set_options.3 archive_write_set_passphrase.3 cpio.5 libarchive-formats.5 libarchive.3 libarchive_changes.3 libarchive_internals.3 mtree.5 tar.5 bsdtar.1 bsdcpio.1 diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_entry.3 b/dependencies/libarchive-3.4.2/doc/man/archive_entry.3 new file mode 100644 index 0000000..e6938a6 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_entry.3 @@ -0,0 +1,143 @@ +.TH ARCHIVE_ENTRY 3 "February 2, 2012" "" +.SH NAME +.ad l +\fB\%archive_entry_clear\fP, +\fB\%archive_entry_clone\fP, +\fB\%archive_entry_free\fP, +\fB\%archive_entry_new\fP +\- functions for managing archive entry descriptions +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIstruct archive_entry *\fP +.br +\fB\%archive_entry_clear\fP(\fI\%struct\ archive_entry\ *\fP); +.br +\fIstruct archive_entry *\fP +.br +\fB\%archive_entry_clone\fP(\fI\%struct\ archive_entry\ *\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_free\fP(\fI\%struct\ archive_entry\ *\fP); +.br +\fIstruct archive_entry *\fP +.br +\fB\%archive_entry_new\fP(\fI\%void\fP); +.SH DESCRIPTION +.ad l +These functions create and manipulate data objects that +represent entries within an archive. +You can think of a +Tn struct archive_entry +as a heavy-duty version of +Tn struct stat: +it includes everything from +Tn struct stat +plus associated pathname, textual group and user names, etc. +These objects are used by +\fBlibarchive\fP(3) +to represent the metadata associated with a particular +entry in an archive. +.SS Create and Destroy +There are functions to allocate, destroy, clear, and copy +\fIarchive_entry\fP +objects: +.RS 5 +.TP +\fB\%archive_entry_clear\fP() +Erases the object, resetting all internal fields to the +same state as a newly-created object. +This is provided to allow you to quickly recycle objects +without thrashing the heap. +.TP +\fB\%archive_entry_clone\fP() +A deep copy operation; all text fields are duplicated. +.TP +\fB\%archive_entry_free\fP() +Releases the +Tn struct archive_entry +object. +.TP +\fB\%archive_entry_new\fP() +Allocate and return a blank +Tn struct archive_entry +object. +.RE +.SS Function groups +Due to high number of functions, the accessor functions can be found in +man pages grouped by the purpose. +.RS 5 +.TP +\fBarchive_entry_acl\fP(3) +Access Control List manipulation +.TP +\fBarchive_entry_paths\fP(3) +Path name manipulation +.TP +\fBarchive_entry_perms\fP(3) +User, group and mode manipulation +.TP +\fBarchive_entry_stat\fP(3) +Functions not in the other groups and copying to/from +Vt struct stat. +.TP +\fBarchive_entry_time\fP(3) +Time field manipulation +.RE +.PP +Most of the functions set or read entries in an object. +Such functions have one of the following forms: +.RS 5 +.TP +\fB\%archive_entry_set_XXXX\fP() +Stores the provided data in the object. +In particular, for strings, the pointer is stored, +not the referenced string. +.TP +\fB\%archive_entry_copy_XXXX\fP() +As above, except that the referenced data is copied +into the object. +.TP +\fB\%archive_entry_XXXX\fP() +Returns the specified data. +In the case of strings, a const-qualified pointer to +the string is returned. +.RE +String data can be set or accessed as wide character strings +or normal +\fIchar\fP +strings. +The functions that use wide character strings are suffixed with +\fB_w\fP. +Note that these are different representations of the same data: +For example, if you store a narrow string and read the corresponding +wide string, the object will transparently convert formats +using the current locale. +Similarly, if you store a wide string and then store a +narrow string for the same data, the previously-set wide string will +be discarded in favor of the new data. +.SH SEE ALSO +.ad l +\fBarchive_entry_acl\fP(3), +\fBarchive_entry_paths\fP(3), +\fBarchive_entry_perms\fP(3), +\fBarchive_entry_time\fP(3), +\fBlibarchive\fP(3) +.SH HISTORY +.ad l +The +\fB\%libarchive\fP +library first appeared in +FreeBSD 5.3. +.SH AUTHORS +.ad l +-nosplit +The +\fB\%libarchive\fP +library was written by +Tim Kientzle \% diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_entry_acl.3 b/dependencies/libarchive-3.4.2/doc/man/archive_entry_acl.3 new file mode 100644 index 0000000..06a104a --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_entry_acl.3 @@ -0,0 +1,452 @@ +.TH ARCHIVE_ENTRY_ACL 3 "February 15, 2017" "" +.SH NAME +.ad l +\fB\%archive_entry_acl_add_entry\fP, +\fB\%archive_entry_acl_add_entry_w\fP, +\fB\%archive_entry_acl_clear\fP, +\fB\%archive_entry_acl_count\fP, +\fB\%archive_entry_acl_from_text\fP, +\fB\%archive_entry_acl_from_text_w\fP, +\fB\%archive_entry_acl_next\fP, +\fB\%archive_entry_acl_reset\fP, +\fB\%archive_entry_acl_to_text\fP, +\fB\%archive_entry_acl_to_text_w\fP, +\fB\%archive_entry_acl_types\fP +\- functions for manipulating Access Control Lists in archive entry descriptions +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIvoid\fP +.br +\fB\%archive_entry_acl_add_entry\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%int\ type\fP, \fI\%int\ permset\fP, \fI\%int\ tag\fP, \fI\%int\ qualifier\fP, \fI\%const\ char\ *name\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_acl_add_entry_w\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%int\ type\fP, \fI\%int\ permset\fP, \fI\%int\ tag\fP, \fI\%int\ qualifier\fP, \fI\%const\ wchar_t\ *name\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_acl_clear\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIint\fP +.br +\fB\%archive_entry_acl_count\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%int\ type\fP); +.br +\fIint\fP +.br +\fB\%archive_entry_acl_from_text\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%const\ char\ *text\fP, \fI\%int\ type\fP); +.br +\fIint\fP +.br +\fB\%archive_entry_acl_from_text_w\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%const\ wchar_t\ *text\fP, \fI\%int\ type\fP); +.br +\fIint\fP +.br +\fB\%archive_entry_acl_next\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%int\ type\fP, \fI\%int\ *ret_type\fP, \fI\%int\ *ret_permset\fP, \fI\%int\ *ret_tag\fP, \fI\%int\ *ret_qual\fP, \fI\%const\ char\ **ret_name\fP); +.br +\fIint\fP +.br +\fB\%archive_entry_acl_reset\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%int\ type\fP); +.br +\fIchar *\fP +.br +\fB\%archive_entry_acl_to_text\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%ssize_t\ *len_p\fP, \fI\%int\ flags\fP); +.br +\fIwchar_t *\fP +.br +\fB\%archive_entry_acl_to_text_w\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%ssize_t\ *len_p\fP, \fI\%int\ flags\fP); +.br +\fIint\fP +.br +\fB\%archive_entry_acl_types\fP(\fI\%struct\ archive_entry\ *a\fP); +.SH DESCRIPTION +.ad l +The +``Access Control Lists (ACLs)'' +extend the standard Unix permission model. +The ACL interface of +\fB\%libarchive\fP +supports both POSIX.1e and NFSv4 style ACLs. +Use of ACLs is restricted by +various levels of ACL support in operating systems, file systems and archive +formats. +.SS POSIX.1e Access Control Lists +A POSIX.1e ACL consists of a number of independent entries. +Each entry specifies the permission set as a bitmask of basic permissions. +Valid permissions in the +are: +.RS 5 +.TP +.BR ARCHIVE_ENTRY_ACL_READ (.B r ) +.TP +.BR ARCHIVE_ENTRY_ACL_WRITE (.B w ) +.TP +.BR ARCHIVE_ENTRY_ACL_EXECUTE (.B x ) +.RE +The permissions correspond to the normal Unix permissions. +.PP +The +specifies the principal to which the permission applies. +Valid values are: +.RS 5 +It .BR ARCHIVE_ENTRY_ACL_USER +The user specified by the name field. +It .BR ARCHIVE_ENTRY_ACL_USER_OBJ +The owner of the file. +It .BR ARCHIVE_ENTRY_ACL_GROUP +The group specified by the name field. +It .BR ARCHIVE_ENTRY_ACL_GROUP_OBJ +The group which owns the file. +It .BR ARCHIVE_ENTRY_ACL_MASK +The maximum permissions to be obtained via group permissions. +It .BR ARCHIVE_ENTRY_ACL_OTHER +Any principal who is not the file owner or a member of the owning group. +.RE +.PP +The principals +.BR ARCHIVE_ENTRY_ACL_USER_OBJ, +.BR ARCHIVE_ENTRY_ACL_GROUP_OBJ +and +.BR ARCHIVE_ENTRY_ACL_OTHER +are equivalent to user, group and other in the classic Unix permission +model and specify non-extended ACL entries. +.PP +All files have an access ACL +(.BR ARCHIVE_ENTRY_ACL_TYPE_ACCESS.) +This specifies the permissions required for access to the file itself. +Directories have an additional ACL +(.BR ARCHIVE_ENTRY_ACL_TYPE_DEFAULT,) +which controls the initial access ACL for newly-created directory entries. +.SS NFSv4 Access Control Lists +A NFSv4 ACL consists of multiple individual entries called Access Control +Entries (ACEs). +.PP +There are four possible types of a NFSv4 ACE: +.RS 5 +It .BR ARCHIVE_ENTRY_ACL_TYPE_ALLOW +Allow principal to perform actions requiring given permissions. +It .BR ARCHIVE_ENTRY_ACL_TYPE_DENY +Prevent principal from performing actions requiring given permissions. +It .BR ARCHIVE_ENTRY_ACL_TYPE_AUDIT +Log access attempts by principal which require given permissions. +It .BR ARCHIVE_ENTRY_ACL_TYPE_ALARM +Trigger a system alarm on access attempts by principal which require given +permissions. +.RE +.PP +The +specifies the principal to which the permission applies. +Valid values are: +.RS 5 +It .BR ARCHIVE_ENTRY_ACL_USER +The user specified by the name field. +It .BR ARCHIVE_ENTRY_ACL_USER_OBJ +The owner of the file. +It .BR ARCHIVE_ENTRY_ACL_GROUP +The group specified by the name field. +It .BR ARCHIVE_ENTRY_ACL_GROUP_OBJ +The group which owns the file. +It .BR ARCHIVE_ENTRY_ACL_EVERYONE +Any principal who is not the file owner or a member of the owning group. +.RE +.PP +Entries with the +.BR ARCHIVE_ENTRY_ACL_USER +or +.BR ARCHIVE_ENTRY_ACL_GROUP +tag store the user and group name in the +string and optionally the user or group ID in the +integer. +.PP +NFSv4 ACE permissions and flags are stored in the same +bitfield. +Some permissions share the same constant and permission character +but have different effect on directories than on files. +The following ACE permissions are supported: +.RS 5 +.TP +.BR ARCHIVE_ENTRY_ACL_READ_DATA (.B r ) +Read data (file). +.TP +.BR ARCHIVE_ENTRY_ACL_LIST_DIRECTORY (.B r ) +List entries (directory). +.TP +ARCHIVE_ENTRY_ACL_WRITE_DATA (.B w ) +Write data (file). +.TP +ARCHIVE_ENTRY_ACL_ADD_FILE (.B w ) +Create files (directory). +.TP +.BR ARCHIVE_ENTRY_ACL_EXECUTE (.B x ) +Execute file or change into a directory. +.TP +.BR ARCHIVE_ENTRY_ACL_APPEND_DATA (.B p ) +Append data (file). +.TP +.BR ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY (.B p ) +Create subdirectories (directory). +.TP +.BR ARCHIVE_ENTRY_ACL_DELETE_CHILD (.B D ) +Remove files and subdirectories inside a directory. +.TP +.BR ARCHIVE_ENTRY_ACL_DELETE (.B d ) +Remove file or directory. +.TP +.BR ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES (.B a ) +Read file or directory attributes. +.TP +.BR ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES (.B A ) +Write file or directory attributes. +.TP +.BR ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS (.B R ) +Read named file or directory attributes. +.TP +.BR ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS (.B W ) +Write named file or directory attributes. +.TP +.BR ARCHIVE_ENTRY_ACL_READ_ACL (.B c ) +Read file or directory ACL. +.TP +.BR ARCHIVE_ENTRY_ACL_WRITE_ACL (.B C ) +Write file or directory ACL. +.TP +.BR ARCHIVE_ENTRY_ACL_WRITE_OWNER (.B o ) +Change owner of a file or directory. +.TP +.BR ARCHIVE_ENTRY_ACL_SYNCHRONIZE (.B s ) +Use synchronous I/O. +.RE +.PP +The following NFSv4 ACL inheritance flags are supported: +.RS 5 +.TP +.BR ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT (.B f ) +Inherit parent directory ACE to files. +.TP +.BR ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT (.B d ) +Inherit parent directory ACE to subdirectories. +.TP +.BR ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY (.B i ) +Only inherit, do not apply the permission on the directory itself. +.TP +.BR ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT (.B n ) +Do not propagate inherit flags. +Only first-level entries inherit ACLs. +.TP +.BR ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS (.B S ) +Trigger alarm or audit on successful access. +.TP +.BR ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS (.B F ) +Trigger alarm or audit on failed access. +.TP +.BR ARCHIVE_ENTRY_ACL_ENTRY_INHERITED (.B I ) +Mark that ACE was inherited. +.RE +.SS Functions +\fB\%archive_entry_acl_add_entry\fP() +and +\fB\%archive_entry_acl_add_entry_w\fP() +add a single ACL entry. +For the access ACL and non-extended principals, the classic Unix permissions +are updated. +An archive entry cannot contain both POSIX.1e and NFSv4 ACL entries. +.PP +\fB\%archive_entry_acl_clear\fP() +removes all ACL entries and resets the enumeration pointer. +.PP +\fB\%archive_entry_acl_count\fP() +counts the ACL entries that have the given type mask. +can be the bitwise-or of +.RS 5 +.TP +.BR ARCHIVE_ENTRY_ACL_TYPE_ACCESS +.TP +.BR ARCHIVE_ENTRY_ACL_TYPE_DEFAULT +.RE +for POSIX.1e ACLs and +.RS 5 +.TP +.BR ARCHIVE_ENTRY_ACL_TYPE_ALLOW +.TP +.BR ARCHIVE_ENTRY_ACL_TYPE_DENY +.TP +.BR ARCHIVE_ENTRY_ACL_TYPE_AUDIT +.TP +.BR ARCHIVE_ENTRY_ACL_TYPE_ALARM +.RE +for NFSv4 ACLs. +For POSIX.1e ACLs if +.BR ARCHIVE_ENTRY_ACL_TYPE_ACCESS +is included and at least one extended ACL entry is found, +the three non-extended ACLs are added. +.PP +\fB\%archive_entry_acl_from_text\fP() +and +\fB\%archive_entry_acl_from_text_w\fP() +add new +(or merge with existing) +ACL entries from +(wide) +text. +The argument +may take one of the following values: +.RS 5 +.TP +.BR ARCHIVE_ENTRY_ACL_TYPE_ACCESS +.TP +.BR ARCHIVE_ENTRY_ACL_TYPE_DEFAULT +.TP +.BR ARCHIVE_ENTRY_ACL_TYPE_NFS4 +.RE +Supports all formats that can be created with +\fB\%archive_entry_acl_to_text\fP() +or respectively +\fB\%archive_entry_acl_to_text_w\fP(). +Existing ACL entries are preserved. +To get a clean new ACL from text +\fB\%archive_entry_acl_clear\fP() +must be called first. +Entries prefixed with +``default:'' +are treated as +.BR ARCHIVE_ENTRY_ACL_TYPE_DEFAULT +unless +is +.BR ARCHIVE_ENTRY_ACL_TYPE_NFS4. +Invalid entries, non-parseable ACL entries and entries beginning with +the +Sq # +character +(comments) +are skipped. +.PP +\fB\%archive_entry_acl_next\fP() +return the next entry of the ACL list. +This functions may only be called after +\fB\%archive_entry_acl_reset\fP() +has indicated the presence of extended ACL entries. +.PP +\fB\%archive_entry_acl_reset\fP() +prepare reading the list of ACL entries with +\fB\%archive_entry_acl_next\fP(). +The function returns 0 if no non-extended ACLs are found. +In this case, the access permissions should be obtained by +\fBarchive_entry_mode\fP(3) +or set using +\fBchmod\fP(2). +Otherwise, the function returns the same value as +\fB\%archive_entry_acl_count\fP(). +.PP +\fB\%archive_entry_acl_to_text\fP() +and +\fB\%archive_entry_acl_to_text_w\fP() +convert the ACL entries for the given type into a +(wide) +string of ACL entries separated by newline. +If the pointer +is not NULL, then the function shall return the length of the string +(not including the NULL terminator) +in the location pointed to by +. +The +argument is a bitwise-or. +.PP +The following flags are effective only on POSIX.1e ACL: +.RS 5 +.TP +.BR ARCHIVE_ENTRY_ACL_TYPE_ACCESS +Output access ACLs. +.TP +.BR ARCHIVE_ENTRY_ACL_TYPE_DEFAULT +Output POSIX.1e default ACLs. +.TP +.BR ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT +Prefix each default ACL entry with the word +``default:''. +.TP +.BR ARCHIVE_ENTRY_ACL_STYLE_SOLARIS +The mask and other ACLs don not contain a double colon. +.RE +.PP +The following flags are effecive only on NFSv4 ACL: +.RS 5 +.TP +.BR ARCHIVE_ENTRY_ACL_STYLE_COMPACT +Do not output minus characters for unset permissions and flags in NFSv4 ACL +permission and flag fields. +.RE +.PP +The following flags are effective on both POSIX.1e and NFSv4 ACL: +.RS 5 +.TP +.BR ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID +Add an additional colon-separated field containing the user or group id. +.TP +.BR ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA +Separate ACL entries with comma instead of newline. +.RE +.PP +If the archive entry contains NFSv4 ACLs, all types of NFSv4 ACLs are returned. +It the entry contains POSIX.1e ACLs and none of the flags +.BR ARCHIVE_ENTRY_ACL_TYPE_ACCESS +or +.BR ARCHIVE_ENTRY_ACL_TYPE_DEFAULT +are specified, both access and default entries are returned and default entries +are prefixed with +``default:''. +.PP +\fB\%archive_entry_acl_types\fP() +get ACL entry types contained in an archive entry's ACL. +As POSIX.1e and NFSv4 +ACL entries cannot be mixed, this function is a very efficient way to detect if +an ACL already contains POSIX.1e or NFSv4 ACL entries. +.SH RETURN VALUES +.ad l +\fB\%archive_entry_acl_count\fP() +and +\fB\%archive_entry_acl_reset\fP() +returns the number of ACL entries that match the given type mask. +For POSIX.1e ACLS if the type mask includes +.BR ARCHIVE_ENTRY_ACL_TYPE_ACCESS +and at least one extended ACL entry exists, the three classic Unix +permissions are counted. +.PP +\fB\%archive_entry_acl_from_text\fP() +and +\fB\%archive_entry_acl_from_text_w\fP() +return +.BR ARCHIVE_OK +if all entries were successfully parsed and +.BR ARCHIVE_WARN +if one or more entries were invalid or non-parseable. +.PP +\fB\%archive_entry_acl_next\fP() +returns +.BR ARCHIVE_OK +on success, +.BR ARCHIVE_EOF +if no more ACL entries exist +and +.BR ARCHIVE_WARN +if +\fB\%archive_entry_acl_reset\fP() +has not been called first. +.PP +\fB\%archive_entry_acl_to_text\fP() +returns a string representing the ACL entries matching the given type and +flags on success or NULL on error. +.PP +\fB\%archive_entry_acl_to_text_w\fP() +returns a wide string representing the ACL entries matching the given type +and flags on success or NULL on error. +.PP +\fB\%archive_entry_acl_types\fP() +returns a bitmask of ACL entry types or 0 if archive entry has no ACL entries. +.SH SEE ALSO +.ad l +\fBarchive_entry\fP(3), +\fBlibarchive\fP(3) diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_entry_linkify.3 b/dependencies/libarchive-3.4.2/doc/man/archive_entry_linkify.3 new file mode 100644 index 0000000..c874ec3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_entry_linkify.3 @@ -0,0 +1,203 @@ +.TH ARCHIVE_ENTRY_LINKIFY 3 "February 2, 2012" "" +.SH NAME +.ad l +\fB\%archive_entry_linkresolver\fP, +\fB\%archive_entry_linkresolver_new\fP, +\fB\%archive_entry_linkresolver_set_strategy\fP, +\fB\%archive_entry_linkresolver_free\fP, +\fB\%archive_entry_linkify\fP +\- hardlink resolver functions +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIstruct archive_entry_linkresolver *\fP +.br +\fB\%archive_entry_linkresolver_new\fP(\fI\%void\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_linkresolver_set_strategy\fP(\fI\%struct\ archive_entry_linkresolver\ *resolver\fP, \fI\%int\ format\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_linkresolver_free\fP(\fI\%struct\ archive_entry_linkresolver\ *resolver\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_linkify\fP(\fI\%struct\ archive_entry_linkresolver\ *resolver\fP, \fI\%struct\ archive_entry\ **entry\fP, \fI\%struct\ archive_entry\ **sparse\fP); +.SH DESCRIPTION +.ad l +Programs that want to create archives have to deal with hardlinks. +Hardlinks are handled in different ways by the archive formats. +The basic strategies are: +.RS 5 +.IP 1. +Ignore hardlinks and store the body for each reference (old cpio, zip). +.IP 2. +Store the body the first time an inode is seen (ustar, pax). +.IP 3. +Store the body the last time an inode is seen (new cpio). +.RE +.PP +The +\fB\%archive_entry_linkresolver\fP +functions help by providing a unified interface and handling the complexity +behind the scene. +.PP +The +\fB\%archive_entry_linkresolver\fP +functions assume that +Vt archive_entry +instances have valid nlinks, inode and device values. +The inode and device value is used to match entries. +The nlinks value is used to determined if all references have been found and +if the internal references can be recycled. +.PP +The +\fB\%archive_entry_linkresolver_new\fP() +function allocates a new link resolver. +The instance can be freed using +\fB\%archive_entry_linkresolver_free\fP(). +All deferred entries are flushed and the internal storage is freed. +.PP +The +\fB\%archive_entry_linkresolver_set_strategy\fP() +function selects the optimal hardlink strategy for the given format. +The format code can be obtained from +\fBarchive_format\fP(3). +The function can be called more than once, but it is recommended to +flush all deferred entries first. +.PP +The +\fB\%archive_entry_linkify\fP() +function is the core of +\fB\%archive_entry_linkresolver\fP. +The +\fB\%entry\fP() +argument points to the +Vt archive_entry +that should be written. +Depending on the strategy one of the following actions is taken: +.RS 5 +.IP 1. +For the simple archive formats +\fI*entry\fP +is left unmodified and +\fI*sparse\fP +is set to +.BR NULL. +.IP 2. +For tar like archive formats, +\fI*sparse\fP +is set to +.BR NULL. +If +\fI*entry\fP +is +.BR NULL, +no action is taken. +If the hardlink count of +\fI*entry\fP +is larger than 1 and the file type is a regular file or symbolic link, +the internal list is searched for a matching inode. +If such an inode is found, the link count is decremented and the file size +of +\fI*entry\fP +is set to 0 to notify that no body should be written. +If no such inode is found, a copy of the entry is added to the internal cache +with a link count reduced by one. +.IP 3. +For new cpio like archive formats a value for +\fI*entry\fP +of +.BR NULL +is used to flush deferred entries. +In that case +\fI*entry\fP +is set to an arbitrary deferred entry and the entry itself is removed from the +internal list. +If the internal list is empty, +\fI*entry\fP +is set to +.BR NULL. +In either case, +\fI*sparse\fP +is set to +.BR NULL +and the function returns. +If the hardlink count of +\fI*entry\fP +is one or the file type is a directory or device, +\fI*sparse\fP +is set to +.BR NULL +and no further action is taken. +Otherwise, the internal list is searched for a matching inode. +If such an inode is not found, the entry is added to the internal list, +both +\fI*entry\fP +and +\fI*sparse\fP +are set to +.BR NULL +and the function returns. +If such an inode is found, the link count is decremented. +If it remains larger than one, the existing entry on the internal list +is swapped with +\fI*entry\fP +after retaining the link count. +The existing entry is returned in +\fI*entry\fP. +If the link count reached one, the new entry is also removed from the +internal list and returned in +\fI*sparse\fP. +Otherwise +\fI*sparse\fP +is set to +.BR NULL. +.RE +.PP +The general usage is therefore: +.RS 5 +.IP 1. +For each new archive entry, call +\fB\%archive_entry_linkify\fP(). +.IP 2. +Keep in mind that the entries returned may have a size of 0 now. +.IP 3. +If +\fI*entry\fP +is not +.BR NULL, +archive it. +.IP 4. +If +\fI*sparse\fP +is not +.BR NULL, +archive it. +.IP 5. +After all entries have been written to disk, call +\fB\%archive_entry_linkify\fP() +with +\fI*entry\fP +set to +.BR NULL +and archive the returned entry as long as it is not +.BR NULL. +.RE +.SH RETURN VALUES +.ad l +\fB\%archive_entry_linkresolver_new\fP() +returns +.BR NULL +on +\fBmalloc\fP(3) +failures. +.SH SEE ALSO +.ad l +\fBarchive_entry\fP(3) diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_entry_misc.3 b/dependencies/libarchive-3.4.2/doc/man/archive_entry_misc.3 new file mode 100644 index 0000000..6ce320b --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_entry_misc.3 @@ -0,0 +1,49 @@ +.TH ARCHIVE_ENTRY_MISC 3 "April 15, 2019" "" +.SH NAME +.ad l +\fB\%archive_entry_symlink_type\fP, +\fB\%archive_entry_set_symlink_type\fP +\- miscellaneous functions for manipulating properties of archive_entry +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIint\fP +.br +\fB\%archive_entry_symlink_type\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_symlink_type\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%int\fP); +.SH DESCRIPTION +.ad l +The function +\fB\%archive_entry_symlink_type\fP() +returns and the function +\fB\%archive_entry_set_symlink_type\fP() +sets the type of the symbolic link stored in an archive entry. +These functions +have special meaning on operating systems that support multiple symbolic link +types (e.g. Microsoft Windows). +.PP +Supported values are: +.RS 5 +.TP +AE_SYMLINK_TYPE_UNDEFINED +Symbolic link target type is not defined (default on unix systems) +.TP +AE_SYMLINK_TYPE_FILE +Symbolic link points to a file +.TP +AE_SYMLINK_TYPE_DIRECTORY +Symbolic link points to a directory +.RE +.SH SEE ALSO +.ad l +\fBarchive_entry\fP(3), +\fBarchive_entry_paths\fP(3), +\fBarchive_entry_stat\fP(3), +\fBlibarchive\fP(3) diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_entry_paths.3 b/dependencies/libarchive-3.4.2/doc/man/archive_entry_paths.3 new file mode 100644 index 0000000..3aa1c72 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_entry_paths.3 @@ -0,0 +1,188 @@ +.TH ARCHIVE_ENTRY_PATHS 3 "February 2, 2012" "" +.SH NAME +.ad l +\fB\%archive_entry_hardlink\fP, +\fB\%archive_entry_hardlink_w\fP, +\fB\%archive_entry_set_hardlink\fP, +\fB\%archive_entry_copy_hardlink\fP, +\fB\%archive_entry_copy_hardlink_w\fP, +\fB\%archive_entry_update_hardlink_utf8\fP, +\fB\%archive_entry_set_link\fP, +\fB\%archive_entry_copy_link\fP, +\fB\%archive_entry_copy_link_w\fP, +\fB\%archive_entry_update_link_utf8\fP, +\fB\%archive_entry_pathname\fP, +\fB\%archive_entry_pathname_w\fP, +\fB\%archive_entry_set_pathname\fP, +\fB\%archive_entry_copy_pathname\fP, +\fB\%archive_entry_copy_pathname_w\fP, +\fB\%archive_entry_update_pathname_utf8\fP, +\fB\%archive_entry_sourcepath\fP, +\fB\%archive_entry_copy_sourcepath\fP, +\fB\%archive_entry_symlink\fP, +\fB\%archive_entry_symlink_w\fP, +\fB\%archive_entry_set_symlink\fP, +\fB\%archive_entry_copy_symlink\fP, +\fB\%archive_entry_copy_symlink_w\fP, +\fB\%archive_entry_update_symlink_utf8\fP +\- functions for manipulating path names in archive entry descriptions +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIconst char *\fP +.br +\fB\%archive_entry_hardlink\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIconst wchar_t *\fP +.br +\fB\%archive_entry_hardlink_w\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_hardlink\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%const\ char\ *path\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_copy_hardlink\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%const\ char\ *path\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_copy_hardlink_w\fP(\fI\%struct\ archive_entry\ *a\ \fP, \fI\%const\fP, \fI\%wchar_t\fP, \fI\%*path"\fP); +.br +\fIint\fP +.br +\fB\%archive_entry_update_hardlink_utf8\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%const\ char\ *path\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_link\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%const\ char\ *path\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_copy_link\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%\ const\ char\ *path\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_copy_link_w\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%\ const\ wchar_t\ *path\fP); +.br +\fIint\fP +.br +\fB\%archive_entry_update_link_utf8\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%\ const\ char\ *path\fP); +.br +\fIconst char *\fP +.br +\fB\%archive_entry_pathname\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIconst wchar_t *\fP +.br +\fB\%archive_entry_pathname_w\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_pathname\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%const\ char\ *path\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_copy_pathname\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%const\ char\ *path\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_copy_pathname_w\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%const\ wchar_t\ *path\fP); +.br +\fIint\fP +.br +\fB\%archive_entry_update_pathname_utf8\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%const\ char\ *path\fP); +.br +\fIconst char *\fP +.br +\fB\%archive_entry_sourcepath\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_copy_sourcepath\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%const\ char\ *path\fP); +.br +\fIconst char *\fP +.br +\fB\%archive_entry_symlink\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIconst wchar_t *\fP +.br +\fB\%archive_entry_symlink_w\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_symlink\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%const\ char\ *path\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_copy_symlink\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%const\ char\ *path\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_copy_symlink_w\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%const\ wchar_t\ *path\fP); +.br +\fIint\fP +.br +\fB\%archive_entry_update_symlink_utf8\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%const\ char\ *path\fP); +.SH DESCRIPTION +.ad l +Path names supported by +\fBarchive_entry\fP(3): +.RS 5 +.TP +hardlink +Destination of the hardlink. +.TP +link +Update only. +For a symlink, update the destination. +Otherwise, make the entry a hardlink and alter +the destination for that. +.TP +pathname +Path in the archive +.TP +sourcepath +Path on the disk for use by +\fBarchive_read_disk\fP(3). +.TP +symlink +Destination of the symbolic link. +.RE +.PP +Path names can be provided in one of three different ways: +.RS 5 +.TP +char * +Multibyte strings in the current locale. +.TP +wchar_t * +Wide character strings in the current locale. +The accessor functions are named +\fB\%XXX_w\fP(). +.TP +UTF-8 +Unicode strings encoded as UTF-8. +These are convenience functions to update both the multibyte and wide +character strings at the same time. +.RE +.PP +The sourcepath is a pure filesystem concept and never stored in an +archive directly. +.PP +For that reason, it is only available as multibyte string. +The link path is a convenience function for conditionally setting +hardlink or symlink destination. +It doesn't have a corresponding get accessor function. +.PP +\fB\%archive_entry_set_XXX\fP() +is an alias for +\fB\%archive_entry_copy_XXX\fP(). +.SH SEE ALSO +.ad l +\fBarchive_entry\fP(3), +\fBlibarchive\fP(3) diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_entry_perms.3 b/dependencies/libarchive-3.4.2/doc/man/archive_entry_perms.3 new file mode 100644 index 0000000..3660b51 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_entry_perms.3 @@ -0,0 +1,231 @@ +.TH ARCHIVE_ENTRY_PERMS 3 "February 2, 2012" "" +.SH NAME +.ad l +\fB\%archive_entry_gid\fP, +\fB\%archive_entry_set_gid\fP, +\fB\%archive_entry_uid\fP, +\fB\%archive_entry_set_uid\fP, +\fB\%archive_entry_perm\fP, +\fB\%archive_entry_set_perm\fP, +\fB\%archive_entry_strmode\fP, +\fB\%archive_entry_uname\fP, +\fB\%archive_entry_uname_w\fP, +\fB\%archive_entry_set_uname\fP, +\fB\%archive_entry_copy_uname\fP, +\fB\%archive_entry_copy_uname_w\fP, +\fB\%archive_entry_update_uname_utf8\fP, +\fB\%archive_entry_gname\fP, +\fB\%archive_entry_gname_w\fP, +\fB\%archive_entry_set_gname\fP, +\fB\%archive_entry_copy_gname\fP, +\fB\%archive_entry_copy_gname_w\fP, +\fB\%archive_entry_update_gname_utf8\fP, +\fB\%archive_entry_fflags\fP, +\fB\%archive_entry_fflags_text\fP, +\fB\%archive_entry_set_fflags\fP, +\fB\%archive_entry_copy_fflags_text\fP, +\fB\%archive_entry_copy_fflags_text_w\fP +\- functions for manipulating ownership and permissions in archive entry descriptions +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIgid_t\fP +.br +\fB\%archive_entry_gid\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_gid\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%gid_t\ gid\fP); +.br +\fIuid_t\fP +.br +\fB\%archive_entry_uid\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_uid\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%uid_t\ uid\fP); +.br +\fImode_t\fP +.br +\fB\%archive_entry_perm\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_perm\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%mode_t\ mode\fP); +.br +\fIconst char *\fP +.br +\fB\%archive_entry_strmode\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIconst char *\fP +.br +\fB\%archive_entry_gname\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIconst wchar_t *\fP +.br +\fB\%archive_entry_gname_w\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_gname\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%const\ char\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_copy_gname\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%const\ char\ *name\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_copy_gname_w\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%const\ wchar_t\ *name\fP); +.br +\fIint\fP +.br +\fB\%archive_entry_update_gname_utf8\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%const\ char\ *name\fP); +.br +\fIconst char *\fP +.br +\fB\%archive_entry_uname\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIconst wchar_t *\fP +.br +\fB\%archive_entry_uname_w\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_uname\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%const\ char\ *name\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_copy_uname\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%const\ char\ *name\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_copy_uname_w\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%const\ wchar_t\ *name\fP); +.br +\fIint\fP +.br +\fB\%archive_entry_update_uname_utf8\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%const\ char\ *name\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_fflags\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%unsigned\ long\ *set_bits\fP, \fI\%unsigned\ long\ *clear_bits\fP); +.br +\fIconst char *\fP +.br +\fB\%archive_entry_fflags_text\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_fflags\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%unsigned\ long\ set_bits\fP, \fI\%unsigned\ long\ clear_bits\fP); +.br +\fIconst char *\fP +.br +\fB\%archive_entry_copy_fflags_text\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%const\ char\ *text\fP); +.br +\fIconst wchar_t *\fP +.br +\fB\%archive_entry_copy_fflags_text_w\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%const\ wchar_t\ *text\fP); +.SH DESCRIPTION +.ad l +.SS User id, group id and mode +The functions +\fB\%archive_entry_uid\fP(), +\fB\%archive_entry_gid\fP(), +and +\fB\%archive_entry_perm\fP() +can be used to extract the user id, group id and permission from the given entry. +The corresponding functions +\fB\%archive_entry_set_uid\fP(), +\fB\%archive_entry_set_gid\fP(), +and +\fB\%archive_entry_set_perm\fP() +store the given user id, group id and permission in the entry. +The permission is also set as a side effect of calling +\fB\%archive_entry_set_mode\fP(). +.PP +\fB\%archive_entry_strmode\fP() +returns a string representation of the permission as used by the long mode of +\fBls\fP(1). +.SS User and group name +User and group names can be provided in one of three different ways: +.RS 5 +.TP +char * +Multibyte strings in the current locale. +.TP +wchar_t * +Wide character strings in the current locale. +The accessor functions are named +\fB\%XXX_w\fP(). +.TP +UTF-8 +Unicode strings encoded as UTF-8. +These are convenience functions to update both the multibyte and wide +character strings at the same time. +.RE +.PP +\fB\%archive_entry_set_XXX\fP() +is an alias for +\fB\%archive_entry_copy_XXX\fP(). +.SS File Flags +File flags are transparently converted between a bitmap +representation and a textual format. +For example, if you set the bitmap and ask for text, the library +will build a canonical text format. +However, if you set a text format and request a text format, +you will get back the same text, even if it is ill-formed. +If you need to canonicalize a textual flags string, you should first set the +text form, then request the bitmap form, then use that to set the bitmap form. +Setting the bitmap format will clear the internal text representation +and force it to be reconstructed when you next request the text form. +.PP +The bitmap format consists of two integers, one containing bits +that should be set, the other specifying bits that should be +cleared. +Bits not mentioned in either bitmap will be ignored. +Usually, the bitmap of bits to be cleared will be set to zero. +In unusual circumstances, you can force a fully-specified set +of file flags by setting the bitmap of flags to clear to the complement +of the bitmap of flags to set. +(This differs from +\fBfflagstostr\fP(3), +which only includes names for set bits.) +Converting a bitmap to a textual string is a platform-specific +operation; bits that are not meaningful on the current platform +will be ignored. +.PP +The canonical text format is a comma-separated list of flag names. +The +\fB\%archive_entry_copy_fflags_text\fP() +and +\fB\%archive_entry_copy_fflags_text_w\fP() +functions parse the provided text and set the internal bitmap values. +This is a platform-specific operation; names that are not meaningful +on the current platform will be ignored. +The function returns a pointer to the start of the first name that was not +recognized, or NULL if every name was recognized. +Note that every name \(em including names that follow an unrecognized +name \(em will be evaluated, and the bitmaps will be set to reflect +every name that is recognized. +(In particular, this differs from +\fBstrtofflags\fP(3), +which stops parsing at the first unrecognized name.) +.SH SEE ALSO +.ad l +\fBarchive_entry\fP(3), +\fBarchive_entry_acl\fP(3), +\fBarchive_read_disk\fP(3), +\fBarchive_write_disk\fP(3), +\fBlibarchive\fP(3) +.SH BUGS +.ad l +The platform types +Vt uid_t +and +Vt gid_t +are often 16 or 32 bit wide. +In this case it is possible that the ids can not be correctly restored +from archives and get truncated. diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_entry_stat.3 b/dependencies/libarchive-3.4.2/doc/man/archive_entry_stat.3 new file mode 100644 index 0000000..c4f98a7 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_entry_stat.3 @@ -0,0 +1,320 @@ +.TH ARCHIVE_ENTRY_STAT 3 "February 2, 2012" "" +.SH NAME +.ad l +\fB\%archive_entry_stat\fP, +\fB\%archive_entry_copy_stat\fP, +\fB\%archive_entry_filetype\fP, +\fB\%archive_entry_set_filetype\fP, +\fB\%archive_entry_mode\fP, +\fB\%archive_entry_set_mode\fP, +\fB\%archive_entry_size\fP, +\fB\%archive_entry_size_is_set\fP, +\fB\%archive_entry_set_size\fP, +\fB\%archive_entry_unset_size\fP, +\fB\%archive_entry_dev\fP, +\fB\%archive_entry_set_dev\fP, +\fB\%archive_entry_dev_is_set\fP, +\fB\%archive_entry_devmajor\fP, +\fB\%archive_entry_set_devmajor\fP, +\fB\%archive_entry_devminor\fP, +\fB\%archive_entry_set_devminor\fP, +\fB\%archive_entry_ino\fP, +\fB\%archive_entry_set_ino\fP, +\fB\%archive_entry_ino_is_set\fP, +\fB\%archive_entry_ino64\fP, +\fB\%archive_entry_set_ino64\fP, +\fB\%archive_entry_nlink\fP, +\fB\%archive_entry_rdev\fP, +\fB\%archive_entry_set_rdev\fP, +\fB\%archive_entry_rdevmajor\fP, +\fB\%archive_entry_set_rdevmajor\fP, +\fB\%archive_entry_rdevminor\fP, +\fB\%archive_entry_set_rdevminor\fP +\- accessor functions for manipulating archive entry descriptions +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIconst struct stat *\fP +.br +\fB\%archive_entry_stat\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_copy_stat\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%const\ struct\ stat\ *sb\fP); +.br +\fImode_t\fP +.br +\fB\%archive_entry_filetype\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_filetype\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%unsigned\ int\ type\fP); +.br +\fImode_t\fP +.br +\fB\%archive_entry_mode\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_mode\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%mode_t\ mode\fP); +.br +\fIint64_t\fP +.br +\fB\%archive_entry_size\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIint\fP +.br +\fB\%archive_entry_size_is_set\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_size\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%int64_t\ size\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_unset_size\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIdev_t\fP +.br +\fB\%archive_entry_dev\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_dev\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%dev_t\ dev\fP); +.br +\fIint\fP +.br +\fB\%archive_entry_dev_is_set\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIdev_t\fP +.br +\fB\%archive_entry_devmajor\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_devmajor\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%dev_t\ major\fP); +.br +\fIdev_t\fP +.br +\fB\%archive_entry_devminor\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_devminor\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%dev_t\ minor\fP); +.br +\fIino_t\fP +.br +\fB\%archive_entry_ino\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_ino\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%unsigned\ long\ ino\fP); +.br +\fIint\fP +.br +\fB\%archive_entry_ino_is_set\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIint64_t\fP +.br +\fB\%archive_entry_ino64\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_ino64\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%int64_t\ ino\fP); +.br +\fIunsigned int\fP +.br +\fB\%archive_entry_nlink\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_nlink\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%unsigned\ int\ count\fP); +.br +\fIdev_t\fP +.br +\fB\%archive_entry_rdev\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIdev_t\fP +.br +\fB\%archive_entry_rdevmajor\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIdev_t\fP +.br +\fB\%archive_entry_rdevminor\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_rdev\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%dev_t\ dev\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_rdevmajor\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%dev_t\ major\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_rdevminor\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%dev_t\ minor\fP); +.SH DESCRIPTION +.ad l +.SS Copying to and from Vt struct stat +The function +\fB\%archive_entry_stat\fP() +converts the various fields stored in the archive entry to the format +used by +\fBstat\fP(2). +The return value remains valid until either +\fB\%archive_entry_clear\fP() +or +\fB\%archive_entry_free\fP() +is called. +It is not affected by calls to the set accessor functions. +It currently sets the following values in +Vt struct stat: +Vt st_atime, +Vt st_ctime, +Vt st_dev, +Vt st_gid, +Vt st_ino, +Vt st_mode, +Vt st_mtime, +Vt st_nlink, +Vt st_rdev, +Vt st_size, +Vt st_uid. +In addition, +Vt st_birthtime +and high-precision information for time-related fields +will be included on platforms that support it. +.PP +The function +\fB\%archive_entry_copy_stat\fP() +copies fields from the platform's +Vt struct stat. +Fields not provided by +Vt struct stat +are unchanged. +.SS General accessor functions +The functions +\fB\%archive_entry_filetype\fP() +and +\fB\%archive_entry_set_filetype\fP() +get respectively set the filetype. +The file type is one of the following constants: +.RS 5 +.TP +AE_IFREG +Regular file +.TP +AE_IFLNK +Symbolic link +.TP +AE_IFSOCK +Socket +.TP +AE_IFCHR +Character device +.TP +AE_IFBLK +Block device +.TP +AE_IFDIR +Directory +.TP +AE_IFIFO +Named pipe (fifo) +.RE +Not all file types are supported by all platforms. +The constants used by +\fBstat\fP(2) +may have different numeric values from the +corresponding constants above. +.PP +The functions +\fB\%archive_entry_mode\fP() +and +\fB\%archive_entry_set_mode\fP() +get/set a combination of file type and permissions and provide the +equivalent of +\fIst_mode\fP. +Use of +\fB\%archive_entry_filetype\fP() +and +\fB\%archive_entry_perm\fP() +for getting and +\fB\%archive_entry_set_filetype\fP() +and +\fB\%archive_entry_set_perm\fP() +for setting is recommended. +.PP +The function +\fB\%archive_entry_size\fP() +returns the file size, if it has been set, and 0 otherwise. +\fB\%archive_entry_size\fP() +can be used to query that status. +\fB\%archive_entry_set_size\fP() +and +\fB\%archive_entry_unset_size\fP() +set and unset the size, respectively. +.PP +The number of references (hardlinks) can be obtained by calling +\fB\%archive_entry_nlinks\fP() +and set with +\fB\%archive_entry_set_nlinks\fP(). +.SS Identifying unique files +The functions +\fB\%archive_entry_dev\fP() +and +\fB\%archive_entry_ino64\fP() +are used by +\fBarchive_entry_linkify\fP(3) +to find hardlinks. +The pair of device and inode is supposed to identify hardlinked files. +.PP +The device major and minor number can be obtained independently using +\fB\%archive_entry_devmajor\fP() +and +\fB\%archive_entry_devminor\fP(). +The device can be set either via +\fB\%archive_entry_set_dev\fP() +or by the combination of major and minor number using +\fB\%archive_entry_set_devmajor\fP() +and +\fB\%archive_entry_set_devminor\fP(). +.PP +The inode number can be obtained using +\fB\%archive_entry_ino\fP(). +This is a legacy interface that uses the platform +Vt ino_t, +which may be very small. +To set the inode number, +\fB\%archive_entry_set_ino64\fP() +is the preferred interface. +.SS Accessor functions for block and character devices +Block and character devices are characterised either using a device number +or a pair of major and minor number. +The combined device number can be obtained with +\fB\%archive_device_rdev\fP() +and set with +\fB\%archive_device_set_rdev\fP(). +The major and minor numbers are accessed by +\fB\%archive_device_rdevmajor\fP(), +\fB\%archive_device_rdevminor\fP() +\fB\%archive_device_set_rdevmajor\fP() +and +\fB\%archive_device_set_rdevminor\fP(). +.PP +The process of splitting the combined device number into major and +minor number and the reverse process of combing them differs between +platforms. +Some archive formats use the combined form, while other formats use +the split form. +.SH SEE ALSO +.ad l +\fBstat\fP(2), +\fBarchive_entry_acl\fP(3), +\fBarchive_entry_perms\fP(3), +\fBarchive_entry_time\fP(3), +\fBlibarchive\fP(3) diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_entry_time.3 b/dependencies/libarchive-3.4.2/doc/man/archive_entry_time.3 new file mode 100644 index 0000000..77f78f0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_entry_time.3 @@ -0,0 +1,146 @@ +.TH ARCHIVE_ENTRY_TIME 3 "February 2, 2012" "" +.SH NAME +.ad l +\fB\%archive_entry_atime\fP, +\fB\%archive_entry_atime_nsec\fP, +\fB\%archive_entry_atime_is_set\fP, +\fB\%archive_entry_set_atime\fP, +\fB\%archive_entry_unset_atime\fP, +\fB\%archive_entry_birthtime\fP, +\fB\%archive_entry_birthtime_nsec\fP, +\fB\%archive_entry_birthtime_is_set\fP, +\fB\%archive_entry_set_birthtime\fP, +\fB\%archive_entry_unset_birthtime\fP, +\fB\%archive_entry_ctime\fP, +\fB\%archive_entry_ctime_nsec\fP, +\fB\%archive_entry_ctime_is_set\fP, +\fB\%archive_entry_set_ctime\fP, +\fB\%archive_entry_unset_ctime\fP, +\fB\%archive_entry_mtime\fP, +\fB\%archive_entry_mtime_nsec\fP, +\fB\%archive_entry_mtime_is_set\fP, +\fB\%archive_entry_set_mtime\fP, +\fB\%archive_entry_unset_mtime\fP +\- functions for manipulating times in archive entry descriptions +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fItime_t\fP +.br +\fB\%archive_entry_atime\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIlong\fP +.br +\fB\%archive_entry_atime_nsec\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIint\fP +.br +\fB\%archive_entry_atime_is_set\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_atime\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%time_t\ sec\fP, \fI\%long\ nanosec\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_unset_atime\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fItime_t\fP +.br +\fB\%archive_entry_birthtime\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIlong\fP +.br +\fB\%archive_entry_birthtime_nsec\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIint\fP +.br +\fB\%archive_entry_birthtime_is_set\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_birthtime\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%time_t\ sec\fP, \fI\%long\ nanosec\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_unset_birthtime\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fItime_t\fP +.br +\fB\%archive_entry_ctime\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIlong\fP +.br +\fB\%archive_entry_ctime_nsec\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIint\fP +.br +\fB\%archive_entry_ctime_is_set\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_ctime\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%time_t\ sec\fP, \fI\%long\ nanosec\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_unset_ctime\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fItime_t\fP +.br +\fB\%archive_entry_mtime\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIlong\fP +.br +\fB\%archive_entry_mtime_nsec\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIint\fP +.br +\fB\%archive_entry_mtime_is_set\fP(\fI\%struct\ archive_entry\ *a\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_set_mtime\fP(\fI\%struct\ archive_entry\ *a\fP, \fI\%time_t\ sec\fP, \fI\%long\ nanosec\fP); +.br +\fIvoid\fP +.br +\fB\%archive_entry_unset_mtime\fP(\fI\%struct\ archive_entry\ *a\fP); +.SH DESCRIPTION +.ad l +These functions create and manipulate the time fields in an +Vt archive_entry. +Supported time fields are atime (access time), birthtime (creation time), +ctime (last time an inode property was changed) and mtime (modification time). +.PP +\fBlibarchive\fP(3) +provides a high-resolution interface. +The timestamps are truncated automatically depending on the archive format +(for archiving) or the filesystem capabilities (for restoring). +.PP +All timestamp fields are optional. +The +\fB\%XXX_unset\fP() +functions can be used to mark the corresponding field as missing. +The current state can be queried using +\fB\%XXX_is_set\fP(). +Unset time fields have a second and nanosecond field of 0. +.SH SEE ALSO +.ad l +\fBarchive_entry\fP(3), +\fBlibarchive\fP(3) +.SH HISTORY +.ad l +The +\fB\%libarchive\fP +library first appeared in +FreeBSD 5.3. +.SH AUTHORS +.ad l +-nosplit +The +\fB\%libarchive\fP +library was written by +Tim Kientzle \% diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_read.3 b/dependencies/libarchive-3.4.2/doc/man/archive_read.3 new file mode 100644 index 0000000..18fd3e4 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_read.3 @@ -0,0 +1,219 @@ +.TH ARCHIVE_READ 3 "February 2, 2012" "" +.SH NAME +.ad l +\fB\%archive_read\fP +\- functions for reading streaming archives +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.SH DESCRIPTION +.ad l +These functions provide a complete API for reading streaming archives. +The general process is to first create the +Tn struct archive +object, set options, initialize the reader, iterate over the archive +headers and associated data, then close the archive and release all +resources. +.SS Create archive object +See +\fBarchive_read_new\fP(3). +.PP +To read an archive, you must first obtain an initialized +Tn struct archive +object from +\fB\%archive_read_new\fP(). +.SS Enable filters and formats +See +\fBarchive_read_filter\fP(3) +and +\fBarchive_read_format\fP(3). +.PP +You can then modify this object for the desired operations with the +various +\fB\%archive_read_set_XXX\fP() +and +\fB\%archive_read_support_XXX\fP() +functions. +In particular, you will need to invoke appropriate +\fB\%archive_read_support_XXX\fP() +functions to enable the corresponding compression and format +support. +Note that these latter functions perform two distinct operations: +they cause the corresponding support code to be linked into your +program, and they enable the corresponding auto-detect code. +Unless you have specific constraints, you will generally want +to invoke +\fB\%archive_read_support_filter_all\fP() +and +\fB\%archive_read_support_format_all\fP() +to enable auto-detect for all formats and compression types +currently supported by the library. +.SS Set options +See +\fBarchive_read_set_options\fP(3). +.SS Open archive +See +\fBarchive_read_open\fP(3). +.PP +Once you have prepared the +Tn struct archive +object, you call +\fB\%archive_read_open\fP() +to actually open the archive and prepare it for reading. +There are several variants of this function; +the most basic expects you to provide pointers to several +functions that can provide blocks of bytes from the archive. +There are convenience forms that allow you to +specify a filename, file descriptor, +\fIFILE *\fP +object, or a block of memory from which to read the archive data. +Note that the core library makes no assumptions about the +size of the blocks read; +callback functions are free to read whatever block size is +most appropriate for the medium. +.SS Consume archive +See +\fBarchive_read_header\fP(3), +\fBarchive_read_data\fP(3) +and +\fBarchive_read_extract\fP(3). +.PP +Each archive entry consists of a header followed by a certain +amount of data. +You can obtain the next header with +\fB\%archive_read_next_header\fP(), +which returns a pointer to an +Tn struct archive_entry +structure with information about the current archive element. +If the entry is a regular file, then the header will be followed +by the file data. +You can use +\fB\%archive_read_data\fP() +(which works much like the +\fBread\fP(2) +system call) +to read this data from the archive, or +\fB\%archive_read_data_block\fP() +which provides a slightly more efficient interface. +You may prefer to use the higher-level +\fB\%archive_read_data_skip\fP(), +which reads and discards the data for this entry, +\fB\%archive_read_data_into_fd\fP(), +which copies the data to the provided file descriptor, or +\fB\%archive_read_extract\fP(), +which recreates the specified entry on disk and copies data +from the archive. +In particular, note that +\fB\%archive_read_extract\fP() +uses the +Tn struct archive_entry +structure that you provide it, which may differ from the +entry just read from the archive. +In particular, many applications will want to override the +pathname, file permissions, or ownership. +.SS Release resources +See +\fBarchive_read_free\fP(3). +.PP +Once you have finished reading data from the archive, you +should call +\fB\%archive_read_close\fP() +to close the archive, then call +\fB\%archive_read_free\fP() +to release all resources, including all memory allocated by the library. +.SH EXAMPLES +.ad l +The following illustrates basic usage of the library. +In this example, +the callback functions are simply wrappers around the standard +\fBopen\fP(2), +\fBread\fP(2), +and +\fBclose\fP(2) +system calls. +.RS 4 +.nf +void +list_archive(const char *name) +{ + struct mydata *mydata; + struct archive *a; + struct archive_entry *entry; + mydata = malloc(sizeof(struct mydata)); + a = archive_read_new(); + mydata->name = name; + archive_read_support_filter_all(a); + archive_read_support_format_all(a); + archive_read_open(a, mydata, myopen, myread, myclose); + while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { + printf("%s\en",archive_entry_pathname(entry)); + archive_read_data_skip(a); + } + archive_read_free(a); + free(mydata); +} +la_ssize_t +myread(struct archive *a, void *client_data, const void **buff) +{ + struct mydata *mydata = client_data; + *buff = mydata->buff; + return (read(mydata->fd, mydata->buff, 10240)); +} +int +myopen(struct archive *a, void *client_data) +{ + struct mydata *mydata = client_data; + mydata->fd = open(mydata->name, O_RDONLY); + return (mydata->fd >= 0 ? ARCHIVE_OK : ARCHIVE_FATAL); +} +int +myclose(struct archive *a, void *client_data) +{ + struct mydata *mydata = client_data; + if (mydata->fd > 0) + close(mydata->fd); + return (ARCHIVE_OK); +} +.RE +.SH SEE ALSO +.ad l +\fBtar\fP(1), +\fBarchive_read_data\fP(3), +\fBarchive_read_extract\fP(3), +\fBarchive_read_filter\fP(3), +\fBarchive_read_format\fP(3), +\fBarchive_read_header\fP(3), +\fBarchive_read_new\fP(3), +\fBarchive_read_open\fP(3), +\fBarchive_read_set_options\fP(3), +\fBarchive_util\fP(3), +\fBlibarchive\fP(3), +\fBtar\fP(5) +.SH HISTORY +.ad l +The +\fB\%libarchive\fP +library first appeared in +FreeBSD 5.3. +.SH AUTHORS +.ad l +-nosplit +The +\fB\%libarchive\fP +library was written by +Tim Kientzle \% +.SH BUGS +.ad l +Many traditional archiver programs treat +empty files as valid empty archives. +For example, many implementations of +\fBtar\fP(1) +allow you to append entries to an empty file. +Of course, it is impossible to determine the format of an empty file +by inspecting the contents, so this library treats empty files as +having a special +``empty'' +format. diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_read_add_passphrase.3 b/dependencies/libarchive-3.4.2/doc/man/archive_read_add_passphrase.3 new file mode 100644 index 0000000..054fa79 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_read_add_passphrase.3 @@ -0,0 +1,49 @@ +.TH ARCHIVE_READ_ADD_PASSPHRASE 3 "September 14, 2014" "" +.SH NAME +.ad l +\fB\%archive_read_add_passphrase\fP, +\fB\%archive_read_set_passphrase_callback\fP +\- functions for reading encrypted archives +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIint\fP +.br +\fB\%archive_read_add_passphrase\fP(\fI\%struct\ archive\ *\fP, \fI\%const\ char\ *passphrase\fP); +.br +\fIint\fP +.br +\fB\%archive_read_set_passphrase_callback\fP(\fI\%struct\ archive\ *\fP, \fI\%void\ *client_data\fP, \fI\%archive_passphrase_callback\ *\fP); +.SH DESCRIPTION +.ad l +.RS 5 +.TP +\fB\%archive_read_add_passphrase\fP() +Register passphrases for reading an encryption archive. +If +\fIpassphrase\fP +is +.BR NULL +or empty, this function will do nothing and +\fBARCHIVE_FAILED\fP +will be returned. +Otherwise, +\fBARCHIVE_OK\fP +will be returned. +.TP +\fB\%archive_read_set_passphrase_callback\fP() +Register a callback function that will be invoked to get a passphrase +for decryption after trying all the passphrases registered by the +\fB\%archive_read_add_passphrase\fP() +function failed. +.RE +.SH SEE ALSO +.ad l +\fBtar\fP(1), +\fBarchive_read\fP(3), +\fBarchive_read_set_options\fP(3), +\fBlibarchive\fP(3) diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_read_data.3 b/dependencies/libarchive-3.4.2/doc/man/archive_read_data.3 new file mode 100644 index 0000000..c0e9bfa --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_read_data.3 @@ -0,0 +1,112 @@ +.TH ARCHIVE_READ_DATA 3 "February 2, 2012" "" +.SH NAME +.ad l +\fB\%archive_read_data\fP, +\fB\%archive_read_data_block\fP, +\fB\%archive_read_data_skip\fP, +\fB\%archive_read_data_into_fd\fP +\- functions for reading streaming archives +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIla_ssize_t\fP +.br +\fB\%archive_read_data\fP(\fI\%struct\ archive\ *\fP, \fI\%void\ *buff\fP, \fI\%size_t\ len\fP); +.br +\fIint\fP +.br +\fB\%archive_read_data_block\fP(\fI\%struct\ archive\ *\fP, \fI\%const\ void\ **buff\fP, \fI\%size_t\ *len\fP, \fI\%off_t\ *offset\fP); +.br +\fIint\fP +.br +\fB\%archive_read_data_skip\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_data_into_fd\fP(\fI\%struct\ archive\ *\fP, \fI\%int\ fd\fP); +.SH DESCRIPTION +.ad l +.RS 5 +.TP +\fB\%archive_read_data\fP() +Read data associated with the header just read. +Internally, this is a convenience function that calls +\fB\%archive_read_data_block\fP() +and fills any gaps with nulls so that callers see a single +continuous stream of data. +.TP +\fB\%archive_read_data_block\fP() +Return the next available block of data for this entry. +Unlike +\fB\%archive_read_data\fP(), +the +\fB\%archive_read_data_block\fP() +function avoids copying data and allows you to correctly handle +sparse files, as supported by some archive formats. +The library guarantees that offsets will increase and that blocks +will not overlap. +Note that the blocks returned from this function can be much larger +than the block size read from disk, due to compression +and internal buffer optimizations. +.TP +\fB\%archive_read_data_skip\fP() +A convenience function that repeatedly calls +\fB\%archive_read_data_block\fP() +to skip all of the data for this archive entry. +Note that this function is invoked automatically by +\fB\%archive_read_next_header2\fP() +if the previous entry was not completely consumed. +.TP +\fB\%archive_read_data_into_fd\fP() +A convenience function that repeatedly calls +\fB\%archive_read_data_block\fP() +to copy the entire entry to the provided file descriptor. +.RE +.SH RETURN VALUES +.ad l +Most functions return zero on success, non-zero on error. +The possible return codes include: +\fBARCHIVE_OK\fP +(the operation succeeded), +\fBARCHIVE_WARN\fP +(the operation succeeded but a non-critical error was encountered), +\fBARCHIVE_EOF\fP +(end-of-archive was encountered), +\fBARCHIVE_RETRY\fP +(the operation failed but can be retried), +and +\fBARCHIVE_FATAL\fP +(there was a fatal error; the archive should be closed immediately). +.PP +\fB\%archive_read_data\fP() +returns a count of bytes actually read or zero at the end of the entry. +On error, a value of +\fBARCHIVE_FATAL\fP, +\fBARCHIVE_WARN\fP, +or +\fBARCHIVE_RETRY\fP +is returned. +.SH ERRORS +.ad l +Detailed error codes and textual descriptions are available from the +\fB\%archive_errno\fP() +and +\fB\%archive_error_string\fP() +functions. +.SH SEE ALSO +.ad l +\fBtar\fP(1), +\fBarchive_read\fP(3), +\fBarchive_read_extract\fP(3), +\fBarchive_read_filter\fP(3), +\fBarchive_read_format\fP(3), +\fBarchive_read_header\fP(3), +\fBarchive_read_open\fP(3), +\fBarchive_read_set_options\fP(3), +\fBarchive_util\fP(3), +\fBlibarchive\fP(3), +\fBtar\fP(5) diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_read_disk.3 b/dependencies/libarchive-3.4.2/doc/man/archive_read_disk.3 new file mode 100644 index 0000000..bd02537 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_read_disk.3 @@ -0,0 +1,342 @@ +.TH ARCHIVE_READ_DISK 3 "April 3, 2017" "" +.SH NAME +.ad l +\fB\%archive_read_disk_new\fP, +\fB\%archive_read_disk_set_behavior\fP, +\fB\%archive_read_disk_set_symlink_logical\fP, +\fB\%archive_read_disk_set_symlink_physical\fP, +\fB\%archive_read_disk_set_symlink_hybrid\fP, +\fB\%archive_read_disk_entry_from_file\fP, +\fB\%archive_read_disk_gname\fP, +\fB\%archive_read_disk_uname\fP, +\fB\%archive_read_disk_set_uname_lookup\fP, +\fB\%archive_read_disk_set_gname_lookup\fP, +\fB\%archive_read_disk_set_standard_lookup\fP +\- functions for reading objects from disk +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIstruct archive *\fP +.br +\fB\%archive_read_disk_new\fP(\fI\%void\fP); +.br +\fIint\fP +.br +\fB\%archive_read_disk_set_behavior\fP(\fI\%struct\ archive\ *\fP, \fI\%int\fP); +.br +\fIint\fP +.br +\fB\%archive_read_disk_set_symlink_logical\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_disk_set_symlink_physical\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_disk_set_symlink_hybrid\fP(\fI\%struct\ archive\ *\fP); +.br +\fIconst char *\fP +.br +\fB\%archive_read_disk_gname\fP(\fI\%struct\ archive\ *\fP, \fI\%gid_t\fP); +.br +\fIconst char *\fP +.br +\fB\%archive_read_disk_uname\fP(\fI\%struct\ archive\ *\fP, \fI\%uid_t\fP); +.br +\fIint\fP +.br +\fB\%archive_read_disk_set_gname_lookup\fP(\fI\%struct\ archive\ *\fP, \fI\%void\ *\fP, \fI\%const\ char\ *(*lookup)(void\ *,\ gid_t)\fP, \fI\%void\ (*cleanup)(void\ *)\fP); +.br +\fIint\fP +.br +\fB\%archive_read_disk_set_uname_lookup\fP(\fI\%struct\ archive\ *\fP, \fI\%void\ *\fP, \fI\%const\ char\ *(*lookup)(void\ *,\ uid_t)\fP, \fI\%void\ (*cleanup)(void\ *)\fP); +.br +\fIint\fP +.br +\fB\%archive_read_disk_set_standard_lookup\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_disk_entry_from_file\fP(\fI\%struct\ archive\ *\fP, \fI\%struct\ archive_entry\ *\fP, \fI\%int\ fd\fP, \fI\%const\ struct\ stat\ *\fP); +.SH DESCRIPTION +.ad l +These functions provide an API for reading information about +objects on disk. +In particular, they provide an interface for populating +Tn struct archive_entry +objects. +.RS 5 +.TP +\fB\%archive_read_disk_new\fP() +Allocates and initializes a +Tn struct archive +object suitable for reading object information from disk. +.TP +\fB\%archive_read_disk_set_behavior\fP() +Configures various behavior options when reading entries from disk. +The flags field consists of a bitwise OR of one or more of the +following values: +.RS 5 +.TP +\fBARCHIVE_READDISK_HONOR_NODUMP\fP +Skip files and directories with the nodump file attribute (file flag) set. +By default, the nodump file attribute is ignored. +.TP +\fBARCHIVE_READDISK_MAC_COPYFILE\fP +Mac OS X specific. +Read metadata (ACLs and extended attributes) with +\fBcopyfile\fP(3). +By default, metadata is read using +\fBcopyfile\fP(3). +.TP +\fBARCHIVE_READDISK_NO_ACL\fP +Do not read Access Control Lists. +By default, ACLs are read from disk. +.TP +\fBARCHIVE_READDISK_NO_FFLAGS\fP +Do not read file attributes (file flags). +By default, file attributes are read from disk. +See +\fBchattr\fP(1) +(Linux) +or +\fBchflags\fP(1) +(FreeBSD, Mac OS X) +for more information on file attributes. +.TP +\fBARCHIVE_READDISK_NO_TRAVERSE_MOUNTS\fP +Do not traverse mount points. +By default, mount points are traversed. +.TP +\fBARCHIVE_READDISK_NO_XATTR\fP +Do not read extended file attributes (xattrs). +By default, extended file attributes are read from disk. +See +\fBxattr\fP(7) +(Linux,) +\fBxattr\fP(2) +(Mac OS X,) +or +\fBgetextattr\fP(8) +(FreeBSD) +for more information on extended file attributes. +.TP +\fBARCHIVE_READDISK_RESTORE_ATIME\fP +Restore access time of traversed files. +By default, access time of traversed files is not restored. +.RE +.TP +\fB\%archive_read_disk_set_symlink_logical\fP(), +\fB\%archive_read_disk_set_symlink_physical\fP(), +\fB\%archive_read_disk_set_symlink_hybrid\fP() +This sets the mode used for handling symbolic links. +The +``logical'' +mode follows all symbolic links. +The +``physical'' +mode does not follow any symbolic links. +The +``hybrid'' +mode currently behaves identically to the +``logical'' +mode. +.TP +\fB\%archive_read_disk_gname\fP(), +\fB\%archive_read_disk_uname\fP() +Returns a user or group name given a gid or uid value. +By default, these always return a NULL string. +.TP +\fB\%archive_read_disk_set_gname_lookup\fP(), +\fB\%archive_read_disk_set_uname_lookup\fP() +These allow you to override the functions used for +user and group name lookups. +You may also provide a +Tn void * +pointer to a private data structure and a cleanup function for +that data. +The cleanup function will be invoked when the +Tn struct archive +object is destroyed or when new lookup functions are registered. +.TP +\fB\%archive_read_disk_set_standard_lookup\fP() +This convenience function installs a standard set of user +and group name lookup functions. +These functions use +\fBgetpwuid\fP(3) +and +\fBgetgrgid\fP(3) +to convert ids to names, defaulting to NULL if the names cannot +be looked up. +These functions also implement a simple memory cache to reduce +the number of calls to +\fBgetpwuid\fP(3) +and +\fBgetgrgid\fP(3). +.TP +\fB\%archive_read_disk_entry_from_file\fP() +Populates a +Tn struct archive_entry +object with information about a particular file. +The +Tn archive_entry +object must have already been created with +\fBarchive_entry_new\fP(3) +and at least one of the source path or path fields must already be set. +(If both are set, the source path will be used.) +.PP +Information is read from disk using the path name from the +Tn struct archive_entry +object. +If a file descriptor is provided, some information will be obtained using +that file descriptor, on platforms that support the appropriate +system calls. +.PP +If a pointer to a +Tn struct stat +is provided, information from that structure will be used instead +of reading from the disk where appropriate. +This can provide performance benefits in scenarios where +Tn struct stat +information has already been read from the disk as a side effect +of some other operation. +(For example, directory traversal libraries often provide this information.) +.PP +Where necessary, user and group ids are converted to user and group names +using the currently-registered lookup functions above. +This affects the file ownership fields and ACL values in the +Tn struct archive_entry +object. +.RE +More information about the +\fIstruct\fP archive +object and the overall design of the library can be found in the +\fBlibarchive\fP(3) +overview. +.SH EXAMPLES +.ad l +The following illustrates basic usage of the library by +showing how to use it to copy an item on disk into an archive. +.RS 4 +.nf +void +file_to_archive(struct archive *a, const char *name) +{ + char buff[8192]; + size_t bytes_read; + struct archive *ard; + struct archive_entry *entry; + int fd; + ard = archive_read_disk_new(); + archive_read_disk_set_standard_lookup(ard); + entry = archive_entry_new(); + fd = open(name, O_RDONLY); + if (fd < 0) + return; + archive_entry_copy_pathname(entry, name); + archive_read_disk_entry_from_file(ard, entry, fd, NULL); + archive_write_header(a, entry); + while ((bytes_read = read(fd, buff, sizeof(buff))) > 0) + archive_write_data(a, buff, bytes_read); + archive_write_finish_entry(a); + archive_read_free(ard); + archive_entry_free(entry); +} +.RE +.SH RETURN VALUES +.ad l +Most functions return +\fBARCHIVE_OK\fP +(zero) on success, or one of several negative +error codes for errors. +Specific error codes include: +\fBARCHIVE_RETRY\fP +for operations that might succeed if retried, +\fBARCHIVE_WARN\fP +for unusual conditions that do not prevent further operations, and +\fBARCHIVE_FATAL\fP +for serious errors that make remaining operations impossible. +.PP +\fB\%archive_read_disk_new\fP() +returns a pointer to a newly-allocated +Tn struct archive +object or NULL if the allocation failed for any reason. +.PP +\fB\%archive_read_disk_gname\fP() +and +\fB\%archive_read_disk_uname\fP() +return +Tn const char * +pointers to the textual name or NULL if the lookup failed for any reason. +The returned pointer points to internal storage that +may be reused on the next call to either of these functions; +callers should copy the string if they need to continue accessing it. +.SH ERRORS +.ad l +Detailed error codes and textual descriptions are available from the +\fB\%archive_errno\fP() +and +\fB\%archive_error_string\fP() +functions. +.SH SEE ALSO +.ad l +\fBtar\fP(1), +\fBarchive_read\fP(3), +\fBarchive_util\fP(3), +\fBarchive_write\fP(3), +\fBarchive_write_disk\fP(3), +\fBlibarchive\fP(3) +.SH HISTORY +.ad l +The +\fB\%libarchive\fP +library first appeared in +FreeBSD 5.3. +The +\fB\%archive_read_disk\fP +interface was added to +\fB\%libarchive\fP 2.6 +and first appeared in +FreeBSD 8.0. +.SH AUTHORS +.ad l +-nosplit +The +\fB\%libarchive\fP +library was written by +Tim Kientzle \% +.SH BUGS +.ad l +The +``standard'' +user name and group name lookup functions are not the defaults because +\fBgetgrgid\fP(3) +and +\fBgetpwuid\fP(3) +are sometimes too large for particular applications. +The current design allows the application author to use a more +compact implementation when appropriate. +.PP +The full list of metadata read from disk by +\fB\%archive_read_disk_entry_from_file\fP() +is necessarily system-dependent. +.PP +The +\fB\%archive_read_disk_entry_from_file\fP() +function reads as much information as it can from disk. +Some method should be provided to limit this so that clients who +do not need ACLs, for instance, can avoid the extra work needed +to look up such information. +.PP +This API should provide a set of methods for walking a directory tree. +That would make it a direct parallel of the +\fBarchive_read\fP(3) +API. +When such methods are implemented, the +``hybrid'' +symbolic link mode will make sense. diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_read_extract.3 b/dependencies/libarchive-3.4.2/doc/man/archive_read_extract.3 new file mode 100644 index 0000000..1fb057b --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_read_extract.3 @@ -0,0 +1,112 @@ +.TH ARCHIVE_READ_EXTRACT 3 "February 2, 2012" "" +.SH NAME +.ad l +\fB\%archive_read_extract\fP, +\fB\%archive_read_extract2\fP, +\fB\%archive_read_extract_set_progress_callback\fP +\- functions for reading streaming archives +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIint\fP +.br +\fB\%archive_read_extract\fP(\fI\%struct\ archive\ *\fP, \fI\%struct\ archive_entry\ *\fP, \fI\%int\ flags\fP); +.br +\fIint\fP +.br +\fB\%archive_read_extract2\fP(\fI\%struct\ archive\ *src\fP, \fI\%struct\ archive_entry\ *\fP, \fI\%struct\ archive\ *dest\fP); +.br +\fIvoid\fP +.br +\fB\%archive_read_extract_set_progress_callback\fP(\fI\%struct\ archive\ *\fP, \fI\%void\ (*func)(void\ *)\fP, \fI\%void\ *user_data\fP); +.SH DESCRIPTION +.ad l +.RS 5 +.TP +\fB\%archive_read_extract\fP(), \fB\%archive_read_extract_set_skip_file\fP() +A convenience function that wraps the corresponding +\fBarchive_write_disk\fP(3) +interfaces. +The first call to +\fB\%archive_read_extract\fP() +creates a restore object using +\fBarchive_write_disk_new\fP(3) +and +\fBarchive_write_disk_set_standard_lookup\fP(3), +then transparently invokes +\fBarchive_write_disk_set_options\fP(3), +\fBarchive_write_header\fP(3), +\fBarchive_write_data\fP(3), +and +\fBarchive_write_finish_entry\fP(3) +to create the entry on disk and copy data into it. +The +\fIflags\fP +argument is passed unmodified to +\fBarchive_write_disk_set_options\fP(3). +.TP +\fB\%archive_read_extract2\fP() +This is another version of +\fB\%archive_read_extract\fP() +that allows you to provide your own restore object. +In particular, this allows you to override the standard lookup functions +using +\fBarchive_write_disk_set_group_lookup\fP(3), +and +\fBarchive_write_disk_set_user_lookup\fP(3). +Note that +\fB\%archive_read_extract2\fP() +does not accept a +\fIflags\fP +argument; you should use +\fB\%archive_write_disk_set_options\fP() +to set the restore options yourself. +.TP +\fB\%archive_read_extract_set_progress_callback\fP() +Sets a pointer to a user-defined callback that can be used +for updating progress displays during extraction. +The progress function will be invoked during the extraction of large +regular files. +The progress function will be invoked with the pointer provided to this call. +Generally, the data pointed to should include a reference to the archive +object and the archive_entry object so that various statistics +can be retrieved for the progress display. +.RE +.SH RETURN VALUES +.ad l +Most functions return zero on success, non-zero on error. +The possible return codes include: +\fBARCHIVE_OK\fP +(the operation succeeded), +\fBARCHIVE_WARN\fP +(the operation succeeded but a non-critical error was encountered), +\fBARCHIVE_EOF\fP +(end-of-archive was encountered), +\fBARCHIVE_RETRY\fP +(the operation failed but can be retried), +and +\fBARCHIVE_FATAL\fP +(there was a fatal error; the archive should be closed immediately). +.SH ERRORS +.ad l +Detailed error codes and textual descriptions are available from the +\fB\%archive_errno\fP() +and +\fB\%archive_error_string\fP() +functions. +.SH SEE ALSO +.ad l +\fBtar\fP(1), +\fBarchive_read\fP(3), +\fBarchive_read_data\fP(3), +\fBarchive_read_filter\fP(3), +\fBarchive_read_format\fP(3), +\fBarchive_read_open\fP(3), +\fBarchive_read_set_options\fP(3), +\fBarchive_util\fP(3), +\fBlibarchive\fP(3), +\fBtar\fP(5) diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_read_filter.3 b/dependencies/libarchive-3.4.2/doc/man/archive_read_filter.3 new file mode 100644 index 0000000..3a12af0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_read_filter.3 @@ -0,0 +1,152 @@ +.TH ARCHIVE_READ_FILTER 3 "August 14, 2014" "" +.SH NAME +.ad l +\fB\%archive_read_support_filter_all\fP, +\fB\%archive_read_support_filter_bzip2\fP, +\fB\%archive_read_support_filter_compress\fP, +\fB\%archive_read_support_filter_gzip\fP, +\fB\%archive_read_support_filter_lz4\fP, +\fB\%archive_read_support_filter_lzma\fP, +\fB\%archive_read_support_filter_none\fP, +\fB\%archive_read_support_filter_rpm\fP, +\fB\%archive_read_support_filter_uu\fP, +\fB\%archive_read_support_filter_xz\fP, +\fB\%archive_read_support_filter_zstd\fP, +\fB\%archive_read_support_filter_program\fP, +\fB\%archive_read_support_filter_program_signature\fP +\- functions for reading streaming archives +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIint\fP +.br +\fB\%archive_read_support_filter_all\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_filter_bzip2\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_filter_compress\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_filter_grzip\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_filter_gzip\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_filter_lrzip\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_filter_lz4\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_filter_lzma\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_filter_lzop\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_filter_none\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_filter_rpm\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_filter_uu\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_filter_xz\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_filter_zstd\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_filter_program\fP(\fI\%struct\ archive\ *\fP, \fI\%const\ char\ *cmd\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_filter_program_signature\fP(\fI\%struct\ archive\ *\fP, \fI\%const\ char\ *cmd\fP, \fI\%const\ void\ *signature\fP, \fI\%size_t\ signature_length\fP); +.SH DESCRIPTION +.ad l +.RS 5 +.TP +\fB\%archive_read_support_filter_bzip2\fP(), +\fB\%archive_read_support_filter_compress\fP(), +\fB\%archive_read_support_filter_grzip\fP(), +\fB\%archive_read_support_filter_gzip\fP(), +\fB\%archive_read_support_filter_lrzip\fP(), +\fB\%archive_read_support_filter_lz4\fP(), +\fB\%archive_read_support_filter_lzma\fP(), +\fB\%archive_read_support_filter_lzop\fP(), +\fB\%archive_read_support_filter_none\fP(), +\fB\%archive_read_support_filter_rpm\fP(), +\fB\%archive_read_support_filter_uu\fP(), +\fB\%archive_read_support_filter_xz\fP(), +\fB\%archive_read_support_filter_zstd\fP(), +Enables auto-detection code and decompression support for the +specified compression. +These functions may fall back on external programs if an appropriate +library was not available at build time. +Decompression using an external program is usually slower than +decompression through built-in libraries. +Note that +``none'' +is always enabled by default. +.TP +\fB\%archive_read_support_filter_all\fP() +Enables all available decompression filters. +.TP +\fB\%archive_read_support_filter_program\fP() +Data is fed through the specified external program before being dearchived. +Note that this disables automatic detection of the compression format, +so it makes no sense to specify this in conjunction with any other +decompression option. +.TP +\fB\%archive_read_support_filter_program_signature\fP() +This feeds data through the specified external program +but only if the initial bytes of the data match the specified +signature value. +.RE +.SH RETURN VALUES +.ad l +These functions return +\fBARCHIVE_OK\fP +if the compression is fully supported, +\fBARCHIVE_WARN\fP +if the compression is supported only through an external program. +.PP +\fB\%archive_read_support_filter_none\fP() +always succeeds. +.SH ERRORS +.ad l +Detailed error codes and textual descriptions are available from the +\fB\%archive_errno\fP() +and +\fB\%archive_error_string\fP() +functions. +.SH SEE ALSO +.ad l +\fBarchive_read\fP(3), +\fBarchive_read_data\fP(3), +\fBarchive_read_format\fP(3), +\fBarchive_read_format\fP(3), +\fBlibarchive\fP(3) diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_read_format.3 b/dependencies/libarchive-3.4.2/doc/man/archive_read_format.3 new file mode 100644 index 0000000..9bd564d --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_read_format.3 @@ -0,0 +1,185 @@ +.TH ARCHIVE_READ_FORMAT 3 "February 2, 2012" "" +.SH NAME +.ad l +\fB\%archive_read_support_format_7zip\fP, +\fB\%archive_read_support_format_all\fP, +\fB\%archive_read_support_format_ar\fP, +\fB\%archive_read_support_format_by_code\fP, +\fB\%archive_read_support_format_cab\fP, +\fB\%archive_read_support_format_cpio\fP, +\fB\%archive_read_support_format_empty\fP, +\fB\%archive_read_support_format_iso9660\fP, +\fB\%archive_read_support_format_lha\fP, +\fB\%archive_read_support_format_mtree\fP, +\fB\%archive_read_support_format_rar\fP, +\fB\%archive_read_support_format_raw\fP, +\fB\%archive_read_support_format_tar\fP, +\fB\%archive_read_support_format_xar\fP, +\fB\%archive_read_support_format_zip\fP +\- functions for reading streaming archives +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIint\fP +.br +\fB\%archive_read_support_format_7zip\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_format_all\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_format_ar\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_format_by_code\fP(\fI\%struct\ archive\ *\fP, \fI\%int\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_format_cab\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_format_cpio\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_format_empty\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_format_iso9660\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_format_lha\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_format_mtree\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_format_rar\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_format_raw\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_format_tar\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_format_xar\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_support_format_zip\fP(\fI\%struct\ archive\ *\fP); +.SH DESCRIPTION +.ad l +.RS 5 +.TP +\fB\%archive_read_support_format_7zip\fP(), +\fB\%archive_read_support_format_ar\fP(), +\fB\%archive_read_support_format_cab\fP(), +\fB\%archive_read_support_format_cpio\fP(), +\fB\%archive_read_support_format_iso9660\fP(), +\fB\%archive_read_support_format_lha\fP(), +\fB\%archive_read_support_format_mtree\fP(), +\fB\%archive_read_support_format_rar\fP(), +\fB\%archive_read_support_format_raw\fP(), +\fB\%archive_read_support_format_tar\fP(), +\fB\%archive_read_support_format_xar\fP(), +\fB\%archive_read_support_format_zip\fP() +Enables support---including auto-detection code---for the +specified archive format. +For example, +\fB\%archive_read_support_format_tar\fP() +enables support for a variety of standard tar formats, old-style tar, +ustar, pax interchange format, and many common variants. +.TP +\fB\%archive_read_support_format_all\fP() +Enables support for all available formats except the +``raw'' +format (see below). +.TP +\fB\%archive_read_support_format_by_code\fP() +Enables a single format specified by the format code. +This can be useful when reading a single archive twice; +use +\fB\%archive_format\fP() +after reading the first time and pass the resulting code +to this function to selectively enable only the necessary +format support. +Note: In statically-linked executables, this will cause +your program to include support for every format. +If executable size is a concern, you may wish to avoid +using this function. +.TP +\fB\%archive_read_support_format_empty\fP() +Enables support for treating empty files as empty archives. +Because empty files are valid for several different formats, +it is not possible to accurately determine a format for +an empty file based purely on contents. +So empty files are treated by libarchive as a distinct +format. +.TP +\fB\%archive_read_support_format_raw\fP() +The +``raw'' +format handler allows libarchive to be used to read arbitrary data. +It treats any data stream as an archive with a single entry. +The pathname of this entry is +``data ;'' +all other entry fields are unset. +This is not enabled by +\fB\%archive_read_support_format_all\fP() +in order to avoid erroneous handling of damaged archives. +.RE +.SH RETURN VALUES +.ad l +These functions return +\fBARCHIVE_OK\fP +on success, or +\fBARCHIVE_FATAL\fP. +.SH ERRORS +.ad l +Detailed error codes and textual descriptions are available from the +\fB\%archive_errno\fP() +and +\fB\%archive_error_string\fP() +functions. +.SH SEE ALSO +.ad l +\fBtar\fP(1), +\fBarchive_read_data\fP(3), +\fBarchive_read_filter\fP(3), +\fBarchive_read_set_options\fP(3), +\fBarchive_util\fP(3), +\fBlibarchive\fP(3), +\fBtar\fP(5) +.SH BUGS +.ad l +Many traditional archiver programs treat +empty files as valid empty archives. +For example, many implementations of +\fBtar\fP(1) +allow you to append entries to an empty file. +Of course, it is impossible to determine the format of an empty file +by inspecting the contents, so this library treats empty files as +having a special +``empty'' +format. +.PP +Using the +``raw'' +handler together with any other handler will often work +but can produce surprising results. diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_read_free.3 b/dependencies/libarchive-3.4.2/doc/man/archive_read_free.3 new file mode 100644 index 0000000..559b205 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_read_free.3 @@ -0,0 +1,78 @@ +.TH ARCHIVE_READ_FREE 3 "February 2, 2012" "" +.SH NAME +.ad l +\fB\%archive_read_close\fP, +\fB\%archive_read_finish\fP, +\fB\%archive_read_free\fP +\- functions for reading streaming archives +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIint\fP +.br +\fB\%archive_read_close\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_finish\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_free\fP(\fI\%struct\ archive\ *\fP); +.SH DESCRIPTION +.ad l +.RS 5 +.TP +\fB\%archive_read_close\fP() +Complete the archive and invoke the close callback. +.TP +\fB\%archive_read_finish\fP() +This is a deprecated synonym for +\fB\%archive_read_free\fP(). +The new name was introduced with libarchive 3.0. +Applications that need to compile with either libarchive 2 +or libarchive 3 should continue to use the +\fB\%archive_read_finish\fP() +name. +Both names will be supported until libarchive 4.0 is +released, which is not expected to occur earlier +than 2013. +.TP +\fB\%archive_read_free\fP() +Invokes +\fB\%archive_read_close\fP() +if it was not invoked manually, then release all resources. +Note: In libarchive 1.x, this function was declared to return +\fIvoid ,\fP +which made it impossible to detect certain errors when +\fB\%archive_read_close\fP() +was invoked implicitly from this function. +The declaration is corrected beginning with libarchive 2.0. +.RE +.SH RETURN VALUES +.ad l +These functions return +\fBARCHIVE_OK\fP +on success, or +\fBARCHIVE_FATAL\fP. +.SH ERRORS +.ad l +Detailed error codes and textual descriptions are available from the +\fB\%archive_errno\fP() +and +\fB\%archive_error_string\fP() +functions. +.SH SEE ALSO +.ad l +\fBarchive_read_data\fP(3), +\fBarchive_read_filter\fP(3), +\fBarchive_read_format\fP(3), +\fBarchive_read_new\fP(3), +\fBarchive_read_open\fP(3), +\fBarchive_read_set_options\fP(3), +\fBarchive_util\fP(3), +\fBlibarchive\fP(3) diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_read_header.3 b/dependencies/libarchive-3.4.2/doc/man/archive_read_header.3 new file mode 100644 index 0000000..f13c53a --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_read_header.3 @@ -0,0 +1,72 @@ +.TH ARCHIVE_READ_HEADER 3 "February 2, 2012" "" +.SH NAME +.ad l +\fB\%archive_read_next_header\fP, +\fB\%archive_read_next_header2\fP +\- functions for reading streaming archives +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIint\fP +.br +\fB\%archive_read_next_header\fP(\fI\%struct\ archive\ *\fP, \fI\%struct\ archive_entry\ **\fP); +.br +\fIint\fP +.br +\fB\%archive_read_next_header2\fP(\fI\%struct\ archive\ *\fP, \fI\%struct\ archive_entry\ *\fP); +.SH DESCRIPTION +.ad l +.RS 5 +.TP +\fB\%archive_read_next_header\fP() +Read the header for the next entry and return a pointer to +a +Tn struct archive_entry. +This is a convenience wrapper around +\fB\%archive_read_next_header2\fP() +that reuses an internal +Tn struct archive_entry +object for each request. +.TP +\fB\%archive_read_next_header2\fP() +Read the header for the next entry and populate the provided +Tn struct archive_entry. +.RE +.SH RETURN VALUES +.ad l +These functions return +\fBARCHIVE_OK\fP +(the operation succeeded), +\fBARCHIVE_WARN\fP +(the operation succeeded but a non-critical error was encountered), +\fBARCHIVE_EOF\fP +(end-of-archive was encountered), +\fBARCHIVE_RETRY\fP +(the operation failed but can be retried), +and +\fBARCHIVE_FATAL\fP +(there was a fatal error; the archive should be closed immediately). +.SH ERRORS +.ad l +Detailed error codes and textual descriptions are available from the +\fB\%archive_errno\fP() +and +\fB\%archive_error_string\fP() +functions. +.SH SEE ALSO +.ad l +\fBtar\fP(1), +\fBarchive_read\fP(3), +\fBarchive_read_data\fP(3), +\fBarchive_read_extract\fP(3), +\fBarchive_read_filter\fP(3), +\fBarchive_read_format\fP(3), +\fBarchive_read_open\fP(3), +\fBarchive_read_set_options\fP(3), +\fBarchive_util\fP(3), +\fBlibarchive\fP(3), +\fBtar\fP(5) diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_read_new.3 b/dependencies/libarchive-3.4.2/doc/man/archive_read_new.3 new file mode 100644 index 0000000..8ad9a09 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_read_new.3 @@ -0,0 +1,37 @@ +.TH ARCHIVE_READ_NEW 3 "February 2, 2012" "" +.SH NAME +.ad l +\fB\%archive_read_new\fP +\- functions for reading streaming archives +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIstruct archive *\fP +.br +\fB\%archive_read_new\fP(\fI\%void\fP); +.SH DESCRIPTION +.ad l +Allocates and initializes a +Tn struct archive +object suitable for reading from an archive. +.BR NULL +is returned on error. +.PP +A complete description of the +Tn struct archive +object can be found in the overview manual page for +\fBlibarchive\fP(3). +.SH SEE ALSO +.ad l +\fBtar\fP(1), +\fBarchive_read_data\fP(3), +\fBarchive_read_filter\fP(3), +\fBarchive_read_format\fP(3), +\fBarchive_read_set_options\fP(3), +\fBarchive_util\fP(3), +\fBlibarchive\fP(3), +\fBtar\fP(5) diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_read_open.3 b/dependencies/libarchive-3.4.2/doc/man/archive_read_open.3 new file mode 100644 index 0000000..caf0b57 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_read_open.3 @@ -0,0 +1,205 @@ +.TH ARCHIVE_READ_OPEN 3 "February 2, 2012" "" +.SH NAME +.ad l +\fB\%archive_read_open\fP, +\fB\%archive_read_open2\fP, +\fB\%archive_read_open_fd\fP, +\fB\%archive_read_open_FILE\fP, +\fB\%archive_read_open_filename\fP, +\fB\%archive_read_open_memory\fP +\- functions for reading streaming archives +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIint\fP +.br +\fB\%archive_read_open\fP(\fI\%struct\ archive\ *\fP, \fI\%void\ *client_data\fP, \fI\%archive_open_callback\ *\fP, \fI\%archive_read_callback\ *\fP, \fI\%archive_close_callback\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_open2\fP(\fI\%struct\ archive\ *\fP, \fI\%void\ *client_data\fP, \fI\%archive_open_callback\ *\fP, \fI\%archive_read_callback\ *\fP, \fI\%archive_skip_callback\ *\fP, \fI\%archive_close_callback\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_read_open_FILE\fP(\fI\%struct\ archive\ *\fP, \fI\%FILE\ *file\fP); +.br +\fIint\fP +.br +\fB\%archive_read_open_fd\fP(\fI\%struct\ archive\ *\fP, \fI\%int\ fd\fP, \fI\%size_t\ block_size\fP); +.br +\fIint\fP +.br +\fB\%archive_read_open_filename\fP(\fI\%struct\ archive\ *\fP, \fI\%const\ char\ *filename\fP, \fI\%size_t\ block_size\fP); +.br +\fIint\fP +.br +\fB\%archive_read_open_memory\fP(\fI\%struct\ archive\ *\fP, \fI\%const\ void\ *buff\fP, \fI\%size_t\ size\fP); +.SH DESCRIPTION +.ad l +.RS 5 +.TP +\fB\%archive_read_open\fP() +The same as +\fB\%archive_read_open2\fP(), +except that the skip callback is assumed to be +.BR NULL. +.TP +\fB\%archive_read_open2\fP() +Freeze the settings, open the archive, and prepare for reading entries. +This is the most generic version of this call, which accepts +four callback functions. +Most clients will want to use +\fB\%archive_read_open_filename\fP(), +\fB\%archive_read_open_FILE\fP(), +\fB\%archive_read_open_fd\fP(), +or +\fB\%archive_read_open_memory\fP() +instead. +The library invokes the client-provided functions to obtain +raw bytes from the archive. +.TP +\fB\%archive_read_open_FILE\fP() +Like +\fB\%archive_read_open\fP(), +except that it accepts a +\fIFILE *\fP +pointer. +This function should not be used with tape drives or other devices +that require strict I/O blocking. +.TP +\fB\%archive_read_open_fd\fP() +Like +\fB\%archive_read_open\fP(), +except that it accepts a file descriptor and block size rather than +a set of function pointers. +Note that the file descriptor will not be automatically closed at +end-of-archive. +This function is safe for use with tape drives or other blocked devices. +.TP +\fB\%archive_read_open_file\fP() +This is a deprecated synonym for +\fB\%archive_read_open_filename\fP(). +.TP +\fB\%archive_read_open_filename\fP() +Like +\fB\%archive_read_open\fP(), +except that it accepts a simple filename and a block size. +A NULL filename represents standard input. +This function is safe for use with tape drives or other blocked devices. +.TP +\fB\%archive_read_open_memory\fP() +Like +\fB\%archive_read_open\fP(), +except that it accepts a pointer and size of a block of +memory containing the archive data. +.RE +.PP +A complete description of the +Tn struct archive +and +Tn struct archive_entry +objects can be found in the overview manual page for +\fBlibarchive\fP(3). +.SH CLIENT CALLBACKS +.ad l +The callback functions must match the following prototypes: +.RS 5 +.IP +\fItypedef la_ssize_t\fP +\fB\%archive_read_callback\fP(\fI\%struct\ archive\ *\fP, \fI\%void\ *client_data\fP, \fI\%const\ void\ **buffer\fP) +.IP +\fItypedef la_int64_t\fP +\fB\%archive_skip_callback\fP(\fI\%struct\ archive\ *\fP, \fI\%void\ *client_data\fP, \fI\%off_t\ request\fP) +.IP +\fItypedef int\fP +\fB\%archive_open_callback\fP(\fI\%struct\ archive\ *\fP, \fI\%void\ *client_data\fP) +.IP +\fItypedef int\fP +\fB\%archive_close_callback\fP(\fI\%struct\ archive\ *\fP, \fI\%void\ *client_data\fP) +.RE +.PP +The open callback is invoked by +\fB\%archive_open\fP(). +It should return +\fBARCHIVE_OK\fP +if the underlying file or data source is successfully +opened. +If the open fails, it should call +\fB\%archive_set_error\fP() +to register an error code and message and return +\fBARCHIVE_FATAL\fP. +.PP +The read callback is invoked whenever the library +requires raw bytes from the archive. +The read callback should read data into a buffer, +set the +.RS 4 +const void **buffer +.RE +argument to point to the available data, and +return a count of the number of bytes available. +The library will invoke the read callback again +only after it has consumed this data. +The library imposes no constraints on the size +of the data blocks returned. +On end-of-file, the read callback should +return zero. +On error, the read callback should invoke +\fB\%archive_set_error\fP() +to register an error code and message and +return -1. +.PP +The skip callback is invoked when the +library wants to ignore a block of data. +The return value is the number of bytes actually +skipped, which may differ from the request. +If the callback cannot skip data, it should return +zero. +If the skip callback is not provided (the +function pointer is +.BR NULL ), +the library will invoke the read function +instead and simply discard the result. +A skip callback can provide significant +performance gains when reading uncompressed +archives from slow disk drives or other media +that can skip quickly. +.PP +The close callback is invoked by archive_close when +the archive processing is complete. +The callback should return +\fBARCHIVE_OK\fP +on success. +On failure, the callback should invoke +\fB\%archive_set_error\fP() +to register an error code and message and +return +\fBARCHIVE_FATAL\fP. +.SH RETURN VALUES +.ad l +These functions return +\fBARCHIVE_OK\fP +on success, or +\fBARCHIVE_FATAL\fP. +.SH ERRORS +.ad l +Detailed error codes and textual descriptions are available from the +\fB\%archive_errno\fP() +and +\fB\%archive_error_string\fP() +functions. +.SH SEE ALSO +.ad l +\fBtar\fP(1), +\fBarchive_read\fP(3), +\fBarchive_read_data\fP(3), +\fBarchive_read_filter\fP(3), +\fBarchive_read_format\fP(3), +\fBarchive_read_set_options\fP(3), +\fBarchive_util\fP(3), +\fBlibarchive\fP(3), +\fBtar\fP(5) diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_read_set_options.3 b/dependencies/libarchive-3.4.2/doc/man/archive_read_set_options.3 new file mode 100644 index 0000000..a1c321f --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_read_set_options.3 @@ -0,0 +1,244 @@ +.TH ARCHIVE_READ_OPTIONS 3 "January 31, 2020" "" +.SH NAME +.ad l +\fB\%archive_read_set_filter_option\fP, +\fB\%archive_read_set_format_option\fP, +\fB\%archive_read_set_option\fP, +\fB\%archive_read_set_options\fP +\- functions controlling options for reading archives +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +.br +\fIint\fP +.br +\fB\%archive_read_set_filter_option\fP(\fI\%struct\ archive\ *\fP, \fI\%const\ char\ *module\fP, \fI\%const\ char\ *option\fP, \fI\%const\ char\ *value\fP); +.br +\fIint\fP +.br +\fB\%archive_read_set_format_option\fP(\fI\%struct\ archive\ *\fP, \fI\%const\ char\ *module\fP, \fI\%const\ char\ *option\fP, \fI\%const\ char\ *value\fP); +.br +\fIint\fP +.br +\fB\%archive_read_set_option\fP(\fI\%struct\ archive\ *\fP, \fI\%const\ char\ *module\fP, \fI\%const\ char\ *option\fP, \fI\%const\ char\ *value\fP); +.br +\fIint\fP +.br +\fB\%archive_read_set_options\fP(\fI\%struct\ archive\ *\fP, \fI\%const\ char\ *options\fP); +.SH DESCRIPTION +.ad l +These functions provide a way for libarchive clients to configure +specific read modules. +.RS 5 +.TP +\fB\%archive_read_set_filter_option\fP(), +\fB\%archive_read_set_format_option\fP() +Specifies an option that will be passed to currently-registered +filters (including decompression filters) or format readers. +.PP +If +\fIoption\fP +and +\fIvalue\fP +are both +.BR NULL, +these functions will do nothing and +\fBARCHIVE_OK\fP +will be returned. +If +\fIoption\fP +is +.BR NULL +but +\fIvalue\fP +is not, these functions will do nothing and +\fBARCHIVE_FAILED\fP +will be returned. +.PP +If +\fImodule\fP +is not +.BR NULL, +\fIoption\fP +and +\fIvalue\fP +will be provided to the filter or reader named +\fImodule\fP. +The return value will be that of the module. +If there is no such module, +\fBARCHIVE_FAILED\fP +will be returned. +.PP +If +\fImodule\fP +is +.BR NULL, +\fIoption\fP +and +\fIvalue\fP +will be provided to every registered module. +If any module returns +\fBARCHIVE_FATAL\fP, +this value will be returned immediately. +Otherwise, +\fBARCHIVE_OK\fP +will be returned if any module accepts the option, and +\fBARCHIVE_FAILED\fP +in all other cases. +.TP +\fB\%archive_read_set_option\fP() +Calls +\fB\%archive_read_set_format_option\fP(), +then +\fB\%archive_read_set_filter_option\fP(). +If either function returns +\fBARCHIVE_FATAL\fP, +\fBARCHIVE_FATAL\fP +will be returned +immediately. +Otherwise, greater of the two values will be returned. +.TP +\fB\%archive_read_set_options\fP() +\fIoptions\fP +is a comma-separated list of options. +If +\fIoptions\fP +is +.BR NULL +or empty, +\fBARCHIVE_OK\fP +will be returned immediately. +.PP +Calls +\fB\%archive_read_set_option\fP() +with each option in turn. +If any +\fB\%archive_read_set_option\fP() +call returns +\fBARCHIVE_FATAL\fP, +\fBARCHIVE_FATAL\fP +will be returned immediately. +.PP +Individual options have one of the following forms: +.RS 5 +.TP +\fIoption=value\fP +The option/value pair will be provided to every module. +Modules that do not accept an option with this name will ignore it. +.TP +\fIoption\fP +The option will be provided to every module with a value of +``1''. +.TP +\fI!option\fP +The option will be provided to every module with a NULL value. +.TP +\fImodule:option=value\fP, \fImodule:option\fP, \fImodule:!option\fP +As above, but the corresponding option and value will be provided +only to modules whose name matches +\fImodule\fP. +.RE +.RE +.SH OPTIONS +.ad l +.RS 5 +.TP +Format cab +.RS 5 +.TP +\fBhdrcharset\fP +The value is used as a character set name that will be +used when translating file names. +.RE +.TP +Format cpio +.RS 5 +.TP +\fBhdrcharset\fP +The value is used as a character set name that will be +used when translating file names. +.RE +.TP +Format iso9660 +.RS 5 +.TP +\fBjoliet\fP +Support Joliet extensions. +Defaults to enabled, use +\fB!joliet\fP +to disable. +.TP +\fBrockridge\fP +Support RockRidge extensions. +Defaults to enabled, use +\fB!rockridge\fP +to disable. +.RE +.TP +Format lha +.RS 5 +.TP +\fBhdrcharset\fP +The value is used as a character set name that will be +used when translating file names. +.RE +.TP +Format mtree +.RS 5 +.TP +\fBcheckfs\fP +Allow reading information missing from the mtree from the file system. +Disabled by default. +.RE +.TP +Format rar +.RS 5 +.TP +\fBhdrcharset\fP +The value is used as a character set name that will be +used when translating file names. +.RE +.TP +Format tar +.RS 5 +.TP +\fBcompat-2x\fP +Libarchive 2.x incorrectly encoded Unicode filenames on +some platforms. +This option mimics the libarchive 2.x filename handling +so that such archives can be read correctly. +.TP +\fBhdrcharset\fP +The value is used as a character set name that will be +used when translating file names. +.TP +\fBmac-ext\fP +Support Mac OS metadata extension that records data in special +files beginning with a period and underscore. +Defaults to enabled on Mac OS, disabled on other platforms. +Use +\fB!mac-ext\fP +to disable. +.TP +\fBread_concatenated_archives\fP +Ignore zeroed blocks in the archive, which occurs when multiple tar archives +have been concatenated together. +Without this option, only the contents of +the first concatenated archive would be read. +.RE +.RE +.SH ERRORS +.ad l +Detailed error codes and textual descriptions are available from the +\fB\%archive_errno\fP() +and +\fB\%archive_error_string\fP() +functions. +.SH SEE ALSO +.ad l +\fBtar\fP(1), +\fBarchive_read\fP(3), +\fBarchive_write_set_options\fP(3), +\fBlibarchive\fP(3) diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_util.3 b/dependencies/libarchive-3.4.2/doc/man/archive_util.3 new file mode 100644 index 0000000..08b1c95 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_util.3 @@ -0,0 +1,240 @@ +.TH ARCHIVE_UTIL 3 "February 2, 2012" "" +.SH NAME +.ad l +\fB\%archive_clear_error\fP, +\fB\%archive_compression\fP, +\fB\%archive_compression_name\fP, +\fB\%archive_copy_error\fP, +\fB\%archive_errno\fP, +\fB\%archive_error_string\fP, +\fB\%archive_file_count\fP, +\fB\%archive_filter_code\fP, +\fB\%archive_filter_count\fP, +\fB\%archive_filter_name\fP, +\fB\%archive_format\fP, +\fB\%archive_format_name\fP, +\fB\%archive_position\fP, +\fB\%archive_set_error\fP +\- libarchive utility functions +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIvoid\fP +.br +\fB\%archive_clear_error\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_compression\fP(\fI\%struct\ archive\ *\fP); +.br +\fIconst char *\fP +.br +\fB\%archive_compression_name\fP(\fI\%struct\ archive\ *\fP); +.br +\fIvoid\fP +.br +\fB\%archive_copy_error\fP(\fI\%struct\ archive\ *\fP, \fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_errno\fP(\fI\%struct\ archive\ *\fP); +.br +\fIconst char *\fP +.br +\fB\%archive_error_string\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_file_count\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_filter_code\fP(\fI\%struct\ archive\ *\fP, \fI\%int\fP); +.br +\fIint\fP +.br +\fB\%archive_filter_count\fP(\fI\%struct\ archive\ *\fP, \fI\%int\fP); +.br +\fIconst char *\fP +.br +\fB\%archive_filter_name\fP(\fI\%struct\ archive\ *\fP, \fI\%int\fP); +.br +\fIint\fP +.br +\fB\%archive_format\fP(\fI\%struct\ archive\ *\fP); +.br +\fIconst char *\fP +.br +\fB\%archive_format_name\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint64_t\fP +.br +\fB\%archive_position\fP(\fI\%struct\ archive\ *\fP, \fI\%int\fP); +.br +\fIvoid\fP +.br +\fB\%archive_set_error\fP(\fI\%struct\ archive\ *\fP, \fI\%int\ error_code\fP, \fI\%const\ char\ *fmt\fP, \fI\%...\fP); +.SH DESCRIPTION +.ad l +These functions provide access to various information about the +Tn struct archive +object used in the +\fBlibarchive\fP(3) +library. +.RS 5 +.TP +\fB\%archive_clear_error\fP() +Clears any error information left over from a previous call. +Not generally used in client code. +.TP +\fB\%archive_compression\fP() +Synonym for +\fB\%archive_filter_code\fP(\fI\%a\fP, \fI\%0\fP). +.TP +\fB\%archive_compression_name\fP() +Synonym for +\fB\%archive_filter_name\fP(\fI\%a\fP, \fI\%0\fP). +.TP +\fB\%archive_copy_error\fP() +Copies error information from one archive to another. +.TP +\fB\%archive_errno\fP() +Returns a numeric error code (see +\fBerrno\fP(2)) +indicating the reason for the most recent error return. +Note that this can not be reliably used to detect whether an +error has occurred. +It should be used only after another libarchive function +has returned an error status. +.TP +\fB\%archive_error_string\fP() +Returns a textual error message suitable for display. +The error message here is usually more specific than that +obtained from passing the result of +\fB\%archive_errno\fP() +to +\fBstrerror\fP(3). +.TP +\fB\%archive_file_count\fP() +Returns a count of the number of files processed by this archive object. +The count is incremented by calls to +\fBarchive_write_header\fP(3) +or +\fBarchive_read_next_header\fP(3). +.TP +\fB\%archive_filter_code\fP() +Returns a numeric code identifying the indicated filter. +See +\fB\%archive_filter_count\fP() +for details of the numbering. +.TP +\fB\%archive_filter_count\fP() +Returns the number of filters in the current pipeline. +For read archive handles, these filters are added automatically +by the automatic format detection. +For write archive handles, these filters are added by calls to the various +\fB\%archive_write_add_filter_XXX\fP() +functions. +Filters in the resulting pipeline are numbered so that filter 0 +is the filter closest to the format handler. +As a convenience, functions that expect a filter number will +accept -1 as a synonym for the highest-numbered filter. +.PP +For example, when reading a uuencoded gzipped tar archive, there +are three filters: +filter 0 is the gunzip filter, +filter 1 is the uudecode filter, +and filter 2 is the pseudo-filter that wraps the archive read functions. +In this case, requesting +\fB\%archive_position\fP(\fI\%a\fP, \fI\%-1\fP) +would be a synonym for +\fB\%archive_position\fP(\fI\%a\fP, \fI\%2\fP) +which would return the number of bytes currently read from the archive, while +\fB\%archive_position\fP(\fI\%a\fP, \fI\%1\fP) +would return the number of bytes after uudecoding, and +\fB\%archive_position\fP(\fI\%a\fP, \fI\%0\fP) +would return the number of bytes after decompression. +.TP +\fB\%archive_filter_name\fP() +Returns a textual name identifying the indicated filter. +See +\fB\%archive_filter_count\fP() +for details of the numbering. +.TP +\fB\%archive_format\fP() +Returns a numeric code indicating the format of the current +archive entry. +This value is set by a successful call to +\fB\%archive_read_next_header\fP(). +Note that it is common for this value to change from +entry to entry. +For example, a tar archive might have several entries that +utilize GNU tar extensions and several entries that do not. +These entries will have different format codes. +.TP +\fB\%archive_format_name\fP() +A textual description of the format of the current entry. +.TP +\fB\%archive_position\fP() +Returns the number of bytes read from or written to the indicated filter. +In particular, +\fB\%archive_position\fP(\fI\%a\fP, \fI\%0\fP) +returns the number of bytes read or written by the format handler, while +\fB\%archive_position\fP(\fI\%a\fP, \fI\%-1\fP) +returns the number of bytes read or written to the archive. +See +\fB\%archive_filter_count\fP() +for details of the numbering here. +.TP +\fB\%archive_set_error\fP() +Sets the numeric error code and error description that will be returned +by +\fB\%archive_errno\fP() +and +\fB\%archive_error_string\fP(). +This function should be used within I/O callbacks to set system-specific +error codes and error descriptions. +This function accepts a printf-like format string and arguments. +However, you should be careful to use only the following printf +format specifiers: +``%c'', +``%d'', +``%jd'', +``%jo'', +``%ju'', +``%jx'', +``%ld'', +``%lo'', +``%lu'', +``%lx'', +``%o'', +``%u'', +``%s'', +``%x'', +``%%''. +Field-width specifiers and other printf features are +not uniformly supported and should not be used. +.RE +.SH SEE ALSO +.ad l +\fBarchive_read\fP(3), +\fBarchive_write\fP(3), +\fBlibarchive\fP(3), +\fBprintf\fP(3) +.SH HISTORY +.ad l +The +\fB\%libarchive\fP +library first appeared in +FreeBSD 5.3. +.SH AUTHORS +.ad l +-nosplit +The +\fB\%libarchive\fP +library was written by +Tim Kientzle \% diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_write.3 b/dependencies/libarchive-3.4.2/doc/man/archive_write.3 new file mode 100644 index 0000000..af64b79 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_write.3 @@ -0,0 +1,233 @@ +.TH ARCHIVE_WRITE 3 "February 2, 2012" "" +.SH NAME +.ad l +\fB\%archive_write\fP +\- functions for creating archives +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.SH DESCRIPTION +.ad l +These functions provide a complete API for creating streaming +archive files. +The general process is to first create the +Tn struct archive +object, set any desired options, initialize the archive, append entries, then +close the archive and release all resources. +.SS Create archive object +See +\fBarchive_write_new\fP(3). +.PP +To write an archive, you must first obtain an initialized +Tn struct archive +object from +\fB\%archive_write_new\fP(). +.SS Enable filters and formats, configure block size and padding +See +\fBarchive_write_filter\fP(3), +\fBarchive_write_format\fP(3) +and +\fBarchive_write_blocksize\fP(3). +.PP +You can then modify this object for the desired operations with the +various +\fB\%archive_write_set_XXX\fP() +functions. +In particular, you will need to invoke appropriate +\fB\%archive_write_add_XXX\fP() +and +\fB\%archive_write_set_XXX\fP() +functions to enable the corresponding compression and format +support. +.SS Set options +See +\fBarchive_write_set_options\fP(3). +.SS Open archive +See +\fBarchive_write_open\fP(3). +.PP +Once you have prepared the +Tn struct archive +object, you call +\fB\%archive_write_open\fP() +to actually open the archive and prepare it for writing. +There are several variants of this function; +the most basic expects you to provide pointers to several +functions that can provide blocks of bytes from the archive. +There are convenience forms that allow you to +specify a filename, file descriptor, +\fIFILE *\fP +object, or a block of memory from which to write the archive data. +.SS Produce archive +See +\fBarchive_write_header\fP(3) +and +\fBarchive_write_data\fP(3). +.PP +Individual archive entries are written in a three-step +process: +You first initialize a +Tn struct archive_entry +structure with information about the new entry. +At a minimum, you should set the pathname of the +entry and provide a +\fIstruct\fP stat +with a valid +\fIst_mode\fP +field, which specifies the type of object and +\fIst_size\fP +field, which specifies the size of the data portion of the object. +.SS Release resources +See +\fBarchive_write_free\fP(3). +.PP +After all entries have been written, use the +\fB\%archive_write_free\fP() +function to release all resources. +.SH EXAMPLES +.ad l +The following sketch illustrates basic usage of the library. +In this example, +the callback functions are simply wrappers around the standard +\fBopen\fP(2), +\fBwrite\fP(2), +and +\fBclose\fP(2) +system calls. +.RS 4 +.nf +#ifdef __linux__ +#define _FILE_OFFSET_BITS 64 +#endif +#include +#include +#include +#include +#include +#include +struct mydata { + const char *name; + int fd; +}; +int +myopen(struct archive *a, void *client_data) +{ + struct mydata *mydata = client_data; + mydata->fd = open(mydata->name, O_WRONLY | O_CREAT, 0644); + if (mydata->fd >= 0) + return (ARCHIVE_OK); + else + return (ARCHIVE_FATAL); +} +la_ssize_t +mywrite(struct archive *a, void *client_data, const void *buff, size_t n) +{ + struct mydata *mydata = client_data; + return (write(mydata->fd, buff, n)); +} +int +myclose(struct archive *a, void *client_data) +{ + struct mydata *mydata = client_data; + if (mydata->fd > 0) + close(mydata->fd); + return (0); +} +void +write_archive(const char *outname, const char **filename) +{ + struct mydata *mydata = malloc(sizeof(struct mydata)); + struct archive *a; + struct archive_entry *entry; + struct stat st; + char buff[8192]; + int len; + int fd; + a = archive_write_new(); + mydata->name = outname; + /* Set archive format and filter according to output file extension. + * If it fails, set default format. Platform depended function. + * See supported formats in archive_write_set_format_filter_by_ext.c */ + if (archive_write_set_format_filter_by_ext(a, outname) != ARCHIVE_OK) { + archive_write_add_filter_gzip(a); + archive_write_set_format_ustar(a); + } + archive_write_open(a, mydata, myopen, mywrite, myclose); + while (*filename) { + stat(*filename, &st); + entry = archive_entry_new(); + archive_entry_copy_stat(entry, &st); + archive_entry_set_pathname(entry, *filename); + archive_write_header(a, entry); + if ((fd = open(*filename, O_RDONLY)) != -1) { + len = read(fd, buff, sizeof(buff)); + while (len > 0) { + archive_write_data(a, buff, len); + len = read(fd, buff, sizeof(buff)); + } + close(fd); + } + archive_entry_free(entry); + filename++; + } + archive_write_free(a); +} +int main(int argc, const char **argv) +{ + const char *outname; + argv++; + outname = *argv++; + write_archive(outname, argv); + return 0; +} +.RE +.SH SEE ALSO +.ad l +\fBtar\fP(1), +\fBarchive_write_set_options\fP(3), +\fBlibarchive\fP(3), +\fBcpio\fP(5), +\fBmtree\fP(5), +\fBtar\fP(5) +.SH HISTORY +.ad l +The +\fB\%libarchive\fP +library first appeared in +FreeBSD 5.3. +.SH AUTHORS +.ad l +-nosplit +The +\fB\%libarchive\fP +library was written by +Tim Kientzle \% +.SH BUGS +.ad l +There are many peculiar bugs in historic tar implementations that may cause +certain programs to reject archives written by this library. +For example, several historic implementations calculated header checksums +incorrectly and will thus reject valid archives; GNU tar does not fully support +pax interchange format; some old tar implementations required specific +field terminations. +.PP +The default pax interchange format eliminates most of the historic +tar limitations and provides a generic key/value attribute facility +for vendor-defined extensions. +One oversight in POSIX is the failure to provide a standard attribute +for large device numbers. +This library uses +``SCHILY.devminor'' +and +``SCHILY.devmajor'' +for device numbers that exceed the range supported by the backwards-compatible +ustar header. +These keys are compatible with Joerg Schilling's +\fB\%star\fP +archiver. +Other implementations may not recognize these keys and will thus be unable +to correctly restore device nodes with large device numbers from archives +created by this library. diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_write_blocksize.3 b/dependencies/libarchive-3.4.2/doc/man/archive_write_blocksize.3 new file mode 100644 index 0000000..5502bbe --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_write_blocksize.3 @@ -0,0 +1,104 @@ +.TH ARCHIVE_WRITE_BLOCKSIZE 3 "February 2, 2012" "" +.SH NAME +.ad l +\fB\%archive_write_get_bytes_per_block\fP, +\fB\%archive_write_set_bytes_per_block\fP, +\fB\%archive_write_get_bytes_in_last_block\fP, +\fB\%archive_write_set_bytes_in_last_block\fP +\- functions for creating archives +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIint\fP +.br +\fB\%archive_write_get_bytes_per_block\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_bytes_per_block\fP(\fI\%struct\ archive\ *\fP, \fI\%int\ bytes_per_block\fP); +.br +\fIint\fP +.br +\fB\%archive_write_get_bytes_in_last_block\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_bytes_in_last_block\fP(\fI\%struct\ archive\ *\fP, \fI\%int\fP); +.SH DESCRIPTION +.ad l +.RS 5 +.TP +\fB\%archive_write_set_bytes_per_block\fP() +Sets the block size used for writing the archive data. +Every call to the write callback function, except possibly the last one, will +use this value for the length. +The default is to use a block size of 10240 bytes. +Note that a block size of zero will suppress internal blocking +and cause writes to be sent directly to the write callback as they occur. +.TP +\fB\%archive_write_get_bytes_per_block\fP() +Retrieve the block size to be used for writing. +A value of -1 here indicates that the library should use default values. +A value of zero indicates that internal blocking is suppressed. +.TP +\fB\%archive_write_set_bytes_in_last_block\fP() +Sets the block size used for writing the last block. +If this value is zero, the last block will be padded to the same size +as the other blocks. +Otherwise, the final block will be padded to a multiple of this size. +In particular, setting it to 1 will cause the final block to not be padded. +For compressed output, any padding generated by this option +is applied only after the compression. +The uncompressed data is always unpadded. +The default is to pad the last block to the full block size (note that +\fB\%archive_write_open_filename\fP() +will set this based on the file type). +Unlike the other +``set'' +functions, this function can be called after the archive is opened. +.TP +\fB\%archive_write_get_bytes_in_last_block\fP() +Retrieve the currently-set value for last block size. +A value of -1 here indicates that the library should use default values. +.RE +.SH RETURN VALUES +.ad l +\fB\%archive_write_set_bytes_per_block\fP() +and +\fB\%archive_write_set_bytes_in_last_block\fP() +return +\fBARCHIVE_OK\fP +on success, or +\fBARCHIVE_FATAL\fP. +.PP +\fB\%archive_write_get_bytes_per_block\fP() +and +\fB\%archive_write_get_bytes_in_last_block\fP() +return currently configured block size +Po +.RS 4 +-1 +.RE +indicates the default block size +Pc, +or +\fBARCHIVE_FATAL\fP. +.SH ERRORS +.ad l +Detailed error codes and textual descriptions are available from the +\fB\%archive_errno\fP() +and +\fB\%archive_error_string\fP() +functions. +.SH SEE ALSO +.ad l +\fBtar\fP(1), +\fBarchive_write_set_options\fP(3), +\fBlibarchive\fP(3), +\fBcpio\fP(5), +\fBmtree\fP(5), +\fBtar\fP(5) diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_write_data.3 b/dependencies/libarchive-3.4.2/doc/man/archive_write_data.3 new file mode 100644 index 0000000..060083e --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_write_data.3 @@ -0,0 +1,71 @@ +.TH ARCHIVE_WRITE_DATA 3 "February 28, 2017" "" +.SH NAME +.ad l +\fB\%archive_write_data\fP, +\fB\%archive_write_data_block\fP +\- functions for creating archives +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIla_ssize_t\fP +.br +\fB\%archive_write_data\fP(\fI\%struct\ archive\ *\fP, \fI\%const\ void\ *\fP, \fI\%size_t\fP); +.br +\fIla_ssize_t\fP +.br +\fB\%archive_write_data_block\fP(\fI\%struct\ archive\ *\fP, \fI\%const\ void\ *\fP, \fI\%size_t\ size\fP, \fI\%int64_t\ offset\fP); +.SH DESCRIPTION +.ad l +.RS 5 +.TP +\fB\%archive_write_data\fP() +Write data corresponding to the header just written. +.TP +\fB\%archive_write_data_block\fP() +Write data corresponding to the header just written. +This is like +\fB\%archive_write_data\fP() +except that it performs a seek on the file being +written to the specified offset before writing the data. +This is useful when restoring sparse files from archive +formats that support sparse files. +Returns number of bytes written or -1 on error. +(Note: This is currently not supported for +Tn archive_write +handles, only for +Tn archive_write_disk +handles. +.RE +.SH RETURN VALUES +.ad l +This function returns the number of bytes actually written, or +a negative error code on error. +.SH ERRORS +.ad l +Detailed error codes and textual descriptions are available from the +\fB\%archive_errno\fP() +and +\fB\%archive_error_string\fP() +functions. +.SH BUGS +.ad l +In libarchive 3.x, this function sometimes returns +zero on success instead of returning the number of bytes written. +Specifically, this occurs when writing to an +Vt archive_write_disk +handle. +Clients should treat any value less than zero as an error +and consider any non-negative value as success. +.SH SEE ALSO +.ad l +\fBtar\fP(1), +\fBarchive_write_finish_entry\fP(3), +\fBarchive_write_set_options\fP(3), +\fBlibarchive\fP(3), +\fBcpio\fP(5), +\fBmtree\fP(5), +\fBtar\fP(5) diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_write_disk.3 b/dependencies/libarchive-3.4.2/doc/man/archive_write_disk.3 new file mode 100644 index 0000000..a4ee482 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_write_disk.3 @@ -0,0 +1,364 @@ +.TH ARCHIVE_WRITE_DISK 3 "January 19, 2020" "" +.SH NAME +.ad l +\fB\%archive_write_disk_new\fP, +\fB\%archive_write_disk_set_options\fP, +\fB\%archive_write_disk_set_skip_file\fP, +\fB\%archive_write_disk_set_group_lookup\fP, +\fB\%archive_write_disk_set_standard_lookup\fP, +\fB\%archive_write_disk_set_user_lookup\fP +\- functions for creating objects on disk +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIstruct archive *\fP +.br +\fB\%archive_write_disk_new\fP(\fI\%void\fP); +.br +\fIint\fP +.br +\fB\%archive_write_disk_set_options\fP(\fI\%struct\ archive\ *\fP, \fI\%int\ flags\fP); +.br +\fIint\fP +.br +\fB\%archive_write_disk_set_skip_file\fP(\fI\%struct\ archive\ *\fP, \fI\%dev_t\fP, \fI\%ino_t\fP); +.br +\fIint\fP +.br +\fB\%archive_write_disk_set_group_lookup\fP(\fI\%struct\ archive\ *\fP, \fI\%void\ *\fP, \fI\%gid_t\ (*)(void\ *,\ const\ char\ *gname,\ gid_t\ gid)\fP, \fI\%void\ (*cleanup)(void\ *)\fP); +.br +\fIint\fP +.br +\fB\%archive_write_disk_set_standard_lookup\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_disk_set_user_lookup\fP(\fI\%struct\ archive\ *\fP, \fI\%void\ *\fP, \fI\%uid_t\ (*)(void\ *,\ const\ char\ *uname,\ uid_t\ uid)\fP, \fI\%void\ (*cleanup)(void\ *)\fP); +.SH DESCRIPTION +.ad l +These functions provide a complete API for creating objects on +disk from +Tn struct archive_entry +descriptions. +They are most naturally used when extracting objects from an archive +using the +\fB\%archive_read\fP() +interface. +The general process is to read +Tn struct archive_entry +objects from an archive, then write those objects to a +Tn struct archive +object created using the +\fB\%archive_write_disk\fP() +family functions. +This interface is deliberately very similar to the +\fB\%archive_write\fP() +interface used to write objects to a streaming archive. +.RS 5 +.TP +\fB\%archive_write_disk_new\fP() +Allocates and initializes a +Tn struct archive +object suitable for writing objects to disk. +.TP +\fB\%archive_write_disk_set_skip_file\fP() +Records the device and inode numbers of a file that should not be +overwritten. +This is typically used to ensure that an extraction process does not +overwrite the archive from which objects are being read. +This capability is technically unnecessary but can be a significant +performance optimization in practice. +.TP +\fB\%archive_write_disk_set_options\fP() +The options field consists of a bitwise OR of one or more of the +following values: +.RS 5 +.TP +\fBARCHIVE_EXTRACT_ACL\fP +Attempt to restore Access Control Lists. +By default, extended ACLs are ignored. +.TP +\fBARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS\fP +Before removing a file system object prior to replacing it, clear +platform-specific file flags which might prevent its removal. +.TP +\fBARCHIVE_EXTRACT_FFLAGS\fP +Attempt to restore file attributes (file flags). +By default, file attributes are ignored. +See +\fBchattr\fP(1) +(Linux) +or +\fBchflags\fP(1) +(FreeBSD, Mac OS X) +for more information on file attributes. +.TP +\fBARCHIVE_EXTRACT_MAC_METADATA\fP +Mac OS X specific. +Restore metadata using +\fBcopyfile\fP(3). +By default, +\fBcopyfile\fP(3) +metadata is ignored. +.TP +\fBARCHIVE_EXTRACT_NO_OVERWRITE\fP +Existing files on disk will not be overwritten. +By default, existing regular files are truncated and overwritten; +existing directories will have their permissions updated; +other pre-existing objects are unlinked and recreated from scratch. +.TP +\fBARCHIVE_EXTRACT_OWNER\fP +The user and group IDs should be set on the restored file. +By default, the user and group IDs are not restored. +.TP +\fBARCHIVE_EXTRACT_PERM\fP +Full permissions (including SGID, SUID, and sticky bits) should +be restored exactly as specified, without obeying the +current umask. +Note that SUID and SGID bits can only be restored if the +user and group ID of the object on disk are correct. +If +\fBARCHIVE_EXTRACT_OWNER\fP +is not specified, then SUID and SGID bits will only be restored +if the default user and group IDs of newly-created objects on disk +happen to match those specified in the archive entry. +By default, only basic permissions are restored, and umask is obeyed. +.TP +\fBARCHIVE_EXTRACT_SAFE_WRITES\fP +Extract files atomically, by first creating a unique temporary file and then +renaming it to its required destination name. +This avoids a race where an application might see a partial file (or no +file) during extraction. +.TP +\fBARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS\fP +Refuse to extract an absolute path. +The default is to not refuse such paths. +.TP +\fBARCHIVE_EXTRACT_SECURE_NODOTDOT\fP +Refuse to extract a path that contains a +\fI\& ..\fP +element anywhere within it. +The default is to not refuse such paths. +Note that paths ending in +\fI\& ..\fP +always cause an error, regardless of this flag. +.TP +\fBARCHIVE_EXTRACT_SECURE_SYMLINKS\fP +Refuse to extract any object whose final location would be altered +by a symlink on disk. +This is intended to help guard against a variety of mischief +caused by archives that (deliberately or otherwise) extract +files outside of the current directory. +The default is not to perform this check. +If +.TP +\fBARCHIVE_EXTRACT_SPARSE\fP +Scan data for blocks of NUL bytes and try to recreate them with holes. +This results in sparse files, independent of whether the archive format +supports or uses them. +\fBARCHIVE_EXTRACT_UNLINK\fP +is specified together with this option, the library will +remove any intermediate symlinks it finds and return an +error only if such symlink could not be removed. +.TP +\fBARCHIVE_EXTRACT_TIME\fP +The timestamps (mtime, ctime, and atime) should be restored. +By default, they are ignored. +Note that restoring of atime is not currently supported. +.TP +\fBARCHIVE_EXTRACT_UNLINK\fP +Existing files on disk will be unlinked before any attempt to +create them. +In some cases, this can prove to be a significant performance improvement. +By default, existing files are truncated and rewritten, but +the file is not recreated. +In particular, the default behavior does not break existing hard links. +.TP +\fBARCHIVE_EXTRACT_XATTR\fP +Attempt to restore extended file attributes. +By default, they are ignored. +See +\fBxattr\fP(7) +(Linux,) +\fBxattr\fP(2) +(Mac OS X,) +or +\fBgetextattr\fP(8) +(FreeBSD) +for more information on extended file attributes. +.RE +.TP +\fB\%archive_write_disk_set_group_lookup\fP(), +\fB\%archive_write_disk_set_user_lookup\fP() +The +Tn struct archive_entry +objects contain both names and ids that can be used to identify users +and groups. +These names and ids describe the ownership of the file itself and +also appear in ACL lists. +By default, the library uses the ids and ignores the names, but +this can be overridden by registering user and group lookup functions. +To register, you must provide a lookup function which +accepts both a name and id and returns a suitable id. +You may also provide a +Tn void * +pointer to a private data structure and a cleanup function for +that data. +The cleanup function will be invoked when the +Tn struct archive +object is destroyed. +.TP +\fB\%archive_write_disk_set_standard_lookup\fP() +This convenience function installs a standard set of user +and group lookup functions. +These functions use +\fBgetpwnam\fP(3) +and +\fBgetgrnam\fP(3) +to convert names to ids, defaulting to the ids if the names cannot +be looked up. +These functions also implement a simple memory cache to reduce +the number of calls to +\fBgetpwnam\fP(3) +and +\fBgetgrnam\fP(3). +.RE +More information about the +\fIstruct\fP archive +object and the overall design of the library can be found in the +\fBlibarchive\fP(3) +overview. +Many of these functions are also documented under +\fBarchive_write\fP(3). +.SH RETURN VALUES +.ad l +Most functions return +\fBARCHIVE_OK\fP +(zero) on success, or one of several non-zero +error codes for errors. +Specific error codes include: +\fBARCHIVE_RETRY\fP +for operations that might succeed if retried, +\fBARCHIVE_WARN\fP +for unusual conditions that do not prevent further operations, and +\fBARCHIVE_FATAL\fP +for serious errors that make remaining operations impossible. +.PP +\fB\%archive_write_disk_new\fP() +returns a pointer to a newly-allocated +Tn struct archive +object. +.PP +\fB\%archive_write_data\fP() +returns a count of the number of bytes actually written, +or +.RS 4 +-1 +.RE +on error. +.SH ERRORS +.ad l +Detailed error codes and textual descriptions are available from the +\fB\%archive_errno\fP() +and +\fB\%archive_error_string\fP() +functions. +.SH SEE ALSO +.ad l +\fBtar\fP(1), +\fBarchive_read\fP(3), +\fBarchive_write\fP(3), +\fBlibarchive\fP(3) +.SH HISTORY +.ad l +The +\fB\%libarchive\fP +library first appeared in +FreeBSD 5.3. +The +\fB\%archive_write_disk\fP +interface was added to +\fB\%libarchive\fP 2.0 +and first appeared in +FreeBSD 6.3. +.SH AUTHORS +.ad l +-nosplit +The +\fB\%libarchive\fP +library was written by +Tim Kientzle \% +.SH BUGS +.ad l +Directories are actually extracted in two distinct phases. +Directories are created during +\fB\%archive_write_header\fP(), +but final permissions are not set until +\fB\%archive_write_close\fP(). +This separation is necessary to correctly handle borderline +cases such as a non-writable directory containing +files, but can cause unexpected results. +In particular, directory permissions are not fully +restored until the archive is closed. +If you use +\fBchdir\fP(2) +to change the current directory between calls to +\fB\%archive_read_extract\fP() +or before calling +\fB\%archive_read_close\fP(), +you may confuse the permission-setting logic with +the result that directory permissions are restored +incorrectly. +.PP +The library attempts to create objects with filenames longer than +\fBPATH_MAX\fP +by creating prefixes of the full path and changing the current directory. +Currently, this logic is limited in scope; the fixup pass does +not work correctly for such objects and the symlink security check +option disables the support for very long pathnames. +.PP +Restoring the path +\fIaa/../bb\fP +does create each intermediate directory. +In particular, the directory +\fIaa\fP +is created as well as the final object +\fIbb\fP. +In theory, this can be exploited to create an entire directory hierarchy +with a single request. +Of course, this does not work if the +\fBARCHIVE_EXTRACT_NODOTDOT\fP +option is specified. +.PP +Implicit directories are always created obeying the current umask. +Explicit objects are created obeying the current umask unless +\fBARCHIVE_EXTRACT_PERM\fP +is specified, in which case they current umask is ignored. +.PP +SGID and SUID bits are restored only if the correct user and +group could be set. +If +\fBARCHIVE_EXTRACT_OWNER\fP +is not specified, then no attempt is made to set the ownership. +In this case, SGID and SUID bits are restored only if the +user and group of the final object happen to match those specified +in the entry. +.PP +The +``standard'' +user-id and group-id lookup functions are not the defaults because +\fBgetgrnam\fP(3) +and +\fBgetpwnam\fP(3) +are sometimes too large for particular applications. +The current design allows the application author to use a more +compact implementation when appropriate. +.PP +There should be a corresponding +\fB\%archive_read_disk\fP +interface that walks a directory hierarchy and returns archive +entry objects. diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_write_filter.3 b/dependencies/libarchive-3.4.2/doc/man/archive_write_filter.3 new file mode 100644 index 0000000..65244ed --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_write_filter.3 @@ -0,0 +1,141 @@ +.TH ARCHIVE_WRITE_FILTER 3 "August 14, 2014" "" +.SH NAME +.ad l +\fB\%archive_write_add_filter_b64encode\fP, +\fB\%archive_write_add_filter_by_name\fP, +\fB\%archive_write_add_filter_bzip2\fP, +\fB\%archive_write_add_filter_compress\fP, +\fB\%archive_write_add_filter_grzip\fP, +\fB\%archive_write_add_filter_gzip\fP, +\fB\%archive_write_add_filter_lrzip\fP, +\fB\%archive_write_add_filter_lz4\fP, +\fB\%archive_write_add_filter_lzip\fP, +\fB\%archive_write_add_filter_lzma\fP, +\fB\%archive_write_add_filter_lzop\fP, +\fB\%archive_write_add_filter_none\fP, +\fB\%archive_write_add_filter_program\fP, +\fB\%archive_write_add_filter_uuencode\fP, +\fB\%archive_write_add_filter_xz\fP, +\fB\%archive_write_add_filter_zstd\fP +\- functions enabling output filters +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIint\fP +.br +\fB\%archive_write_add_filter_b64encode\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_add_filter_bzip2\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_add_filter_compress\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_add_filter_grzip\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_add_filter_gzip\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_add_filter_lrzip\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_add_filter_lz4\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_add_filter_lzip\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_add_filter_lzma\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_add_filter_lzop\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_add_filter_none\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_add_filter_program\fP(\fI\%struct\ archive\ *\fP, \fI\%const\ char\ *\ cmd\fP); +.br +\fIint\fP +.br +\fB\%archive_write_add_filter_uuencode\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_add_filter_xz\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_add_filter_zstd\fP(\fI\%struct\ archive\ *\fP); +.SH DESCRIPTION +.ad l +.RS 5 +.TP +\fB\%archive_write_add_filter_bzip2\fP(), +\fB\%archive_write_add_filter_compress\fP(), +\fB\%archive_write_add_filter_grzip\fP(), +\fB\%archive_write_add_filter_gzip\fP(), +\fB\%archive_write_add_filter_lrzip\fP(), +\fB\%archive_write_add_filter_lz4\fP(), +\fB\%archive_write_add_filter_lzip\fP(), +\fB\%archive_write_add_filter_lzma\fP(), +\fB\%archive_write_add_filter_lzop\fP(), +\fB\%archive_write_add_filter_xz\fP(), +\fB\%archive_write_add_filter_zstd\fP(), +The resulting archive will be compressed as specified. +Note that the compressed output is always properly blocked. +.TP +\fB\%archive_write_add_filter_b64encode\fP(), +\fB\%archive_write_add_filter_uuencode\fP(), +The output will be encoded as specified. +The encoded output is always properly blocked. +.TP +\fB\%archive_write_add_filter_none\fP() +This is never necessary. +It is provided only for backwards compatibility. +.TP +\fB\%archive_write_add_filter_program\fP() +The archive will be fed into the specified compression program. +The output of that program is blocked and written to the client +write callbacks. +.RE +.SH RETURN VALUES +.ad l +These functions return +\fBARCHIVE_OK\fP +on success, or +\fBARCHIVE_FATAL\fP. +.SH ERRORS +.ad l +Detailed error codes and textual descriptions are available from the +\fB\%archive_errno\fP() +and +\fB\%archive_error_string\fP() +functions. +.SH SEE ALSO +.ad l +\fBtar\fP(1), +\fBarchive_write\fP(3), +\fBarchive_write_format\fP(3), +\fBarchive_write_set_options\fP(3), +\fBlibarchive\fP(3), +\fBcpio\fP(5), +\fBmtree\fP(5), +\fBtar\fP(5) diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_write_finish_entry.3 b/dependencies/libarchive-3.4.2/doc/man/archive_write_finish_entry.3 new file mode 100644 index 0000000..a8f7f7c --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_write_finish_entry.3 @@ -0,0 +1,57 @@ +.TH ARCHIVE_WRITE_FINISH_ENTRY 3 "February 28, 2017" "" +.SH NAME +.ad l +\fB\%archive_write_finish_entry\fP +\- functions for creating archives +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIint\fP +.br +\fB\%archive_write_finish_entry\fP(\fI\%struct\ archive\ *\fP); +.SH DESCRIPTION +.ad l +Close out the entry just written. +In particular, this writes out the final padding required by some formats. +Ordinarily, clients never need to call this, as it +is called automatically by +\fB\%archive_write_header\fP() +and +\fB\%archive_write_close\fP() +as needed. +For +Tn archive_write_disk +handles, this flushes pending file attribute changes like modification time. +.SH RETURN VALUES +.ad l +This function returns +\fBARCHIVE_OK\fP +on success, or one of several non-zero +error codes for errors. +Specific error codes include: +\fBARCHIVE_RETRY\fP +for operations that might succeed if retried, +\fBARCHIVE_WARN\fP +for unusual conditions that do not prevent further operations, and +\fBARCHIVE_FATAL\fP +for serious errors that make remaining operations impossible. +.SH ERRORS +.ad l +Detailed error codes and textual descriptions are available from the +\fB\%archive_errno\fP() +and +\fB\%archive_error_string\fP() +functions. +.SH SEE ALSO +.ad l +\fBtar\fP(1), +\fBarchive_write_data\fP(3), +\fBarchive_write_set_options\fP(3), +\fBlibarchive\fP(3), +\fBcpio\fP(5), +\fBmtree\fP(5), +\fBtar\fP(5) diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_write_format.3 b/dependencies/libarchive-3.4.2/doc/man/archive_write_format.3 new file mode 100644 index 0000000..80ed63d --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_write_format.3 @@ -0,0 +1,197 @@ +.TH ARCHIVE_WRITE_FORMAT 3 "February 14, 2013" "" +.SH NAME +.ad l +\fB\%archive_write_set_format\fP, +\fB\%archive_write_set_format_7zip\fP, +\fB\%archive_write_set_format_ar\fP, +\fB\%archive_write_set_format_ar_bsd\fP, +\fB\%archive_write_set_format_ar_svr4\fP, +\fB\%archive_write_set_format_by_name\fP, +\fB\%archive_write_set_format_cpio\fP, +\fB\%archive_write_set_format_cpio_newc\fP, +\fB\%archive_write_set_format_filter_by_ext\fP, +\fB\%archive_write_set_format_filter_by_ext_def\fP, +\fB\%archive_write_set_format_gnutar\fP, +\fB\%archive_write_set_format_iso9660\fP, +\fB\%archive_write_set_format_mtree\fP, +\fB\%archive_write_set_format_mtree_classic\fP, +\fB\%archive_write_set_format_mtree_default\fP, +\fB\%archive_write_set_format_pax\fP, +\fB\%archive_write_set_format_pax_restricted\fP, +\fB\%archive_write_set_format_raw\fP, +\fB\%archive_write_set_format_shar\fP, +\fB\%archive_write_set_format_shar_dump\fP, +\fB\%archive_write_set_format_ustar\fP, +\fB\%archive_write_set_format_v7tar\fP, +\fB\%archive_write_set_format_warc\fP, +\fB\%archive_write_set_format_xar\fP, +\fB\%archive_write_set_format_zip\fP +\- functions for creating archives +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIint\fP +.br +\fB\%archive_write_set_format\fP(\fI\%struct\ archive\ *\fP, \fI\%int\ code\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_format_7zip\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_format_ar\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_format_ar_bsd\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_format_ar_svr4\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_format_by_name\fP(\fI\%struct\ archive\ *\fP, \fI\%const\ char\ *name\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_format_cpio\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_format_cpio_newc\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_format_filter_by_ext\fP(\fI\%struct\ archive\ *\fP, \fI\%const\ char\ *filename\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_format_filter_by_ext_def\fP(\fI\%struct\ archive\ *\fP, \fI\%const\ char\ *filename\fP, \fI\%const\ char\ *def_ext\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_format_gnutar\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_format_iso9660\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_format_mtree\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_format_pax\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_format_pax_restricted\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_format_raw\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_format_shar\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_format_shar_dump\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_format_ustar\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_format_v7tar\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_format_warc\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_format_xar\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_format_zip\fP(\fI\%struct\ archive\ *\fP); +.SH DESCRIPTION +.ad l +These functions set the format that will be used for the archive. +.PP +The library can write a variety of common archive formats. +.RS 5 +.TP +\fB\%archive_write_set_format\fP() +Sets the format based on the format code (see +\fIarchive.h\fP +for the full list of format codes). +In particular, this can be used in conjunction with +\fB\%archive_format\fP() +to create a new archive with the same format as an existing archive. +.TP +\fB\%archive_write_set_format_by_name\fP() +Sets the corresponding format based on the common name. +.TP +\fB\%archive_write_set_format_filter_by_ext\fP(), +\fB\%archive_write_set_format_filter_by_ext_def\fP() +Sets both filters and format based on the output filename. +Supported extensions: .7z, .zip, .jar, .cpio, .iso, .a, .ar, .tar, .tgz, .tar.gz, .tar.bz2, .tar.xz +.TP +\fB\%archive_write_set_format_7zip\fP() +\fB\%archive_write_set_format_ar_bsd\fP(), +\fB\%archive_write_set_format_ar_svr4\fP(), +\fB\%archive_write_set_format_cpio\fP() +\fB\%archive_write_set_format_cpio_newc\fP() +\fB\%archive_write_set_format_gnutar\fP() +\fB\%archive_write_set_format_iso9660\fP() +\fB\%archive_write_set_format_mtree\fP() +\fB\%archive_write_set_format_mtree_classic\fP() +\fB\%archive_write_set_format_pax\fP() +\fB\%archive_write_set_format_pax_restricted\fP() +\fB\%archive_write_set_format_raw\fP() +\fB\%archive_write_set_format_shar\fP() +\fB\%archive_write_set_format_shar_dump\fP() +\fB\%archive_write_set_format_ustar\fP() +\fB\%archive_write_set_format_v7tar\fP() +\fB\%archive_write_set_format_warc\fP() +\fB\%archive_write_set_format_xar\fP() +\fB\%archive_write_set_format_zip\fP() +Set the format as specified. +More details on the formats supported by libarchive can be found in the +\fBlibarchive-formats\fP(5) +manual page. +.RE +.SH RETURN VALUES +.ad l +These functions return +\fBARCHIVE_OK\fP +on success, or +\fBARCHIVE_FATAL\fP. +.SH ERRORS +.ad l +Detailed error codes and textual descriptions are available from the +\fB\%archive_errno\fP() +and +\fB\%archive_error_string\fP() +functions. +.SH SEE ALSO +.ad l +\fBtar\fP(1), +\fBarchive_write\fP(3), +\fBarchive_write_set_options\fP(3), +\fBlibarchive\fP(3), +\fBcpio\fP(5), +\fBlibarchive-formats\fP(5), +\fBmtree\fP(5), +\fBtar\fP(5) diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_write_free.3 b/dependencies/libarchive-3.4.2/doc/man/archive_write_free.3 new file mode 100644 index 0000000..efda9aa --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_write_free.3 @@ -0,0 +1,84 @@ +.TH ARCHIVE_WRITE_FREE 3 "February 2, 2012" "" +.SH NAME +.ad l +\fB\%archive_write_fail\fP, +\fB\%archive_write_close\fP, +\fB\%archive_write_finish\fP, +\fB\%archive_write_free\fP +\- functions for creating archives +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIint\fP +.br +\fB\%archive_write_fail\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_close\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_finish\fP(\fI\%struct\ archive\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_free\fP(\fI\%struct\ archive\ *\fP); +.SH DESCRIPTION +.ad l +.RS 5 +.TP +\fB\%archive_write_fail\fP() +Always returns +\fBARCHIVE_FATAL\fP. +This marks the archive object as being unusable; +after calling this function, the only call that can succeed is +\fB\%archive_write_free\fP() +to release the resources. +This can be used to speed recovery when the archive creation +must be aborted. +Note that the created archive is likely to be malformed in this case; +.TP +\fB\%archive_write_close\fP() +Complete the archive and invoke the close callback. +.TP +\fB\%archive_write_finish\fP() +This is a deprecated synonym for +\fB\%archive_write_free\fP(). +.TP +\fB\%archive_write_free\fP() +Invokes +\fB\%archive_write_close\fP() +if necessary, then releases all resources. +If you need detailed information about +\fB\%archive_write_close\fP() +failures, you should be careful to call it separately, as +you cannot obtain error information after +\fB\%archive_write_free\fP() +returns. +.RE +.SH RETURN VALUES +.ad l +These functions return +\fBARCHIVE_OK\fP +on success, or +\fBARCHIVE_FATAL\fP. +.SH ERRORS +.ad l +Detailed error codes and textual descriptions are available from the +\fB\%archive_errno\fP() +and +\fB\%archive_error_string\fP() +functions. +.SH SEE ALSO +.ad l +\fBtar\fP(1), +\fBarchive_write_set_options\fP(3), +\fBlibarchive\fP(3), +\fBcpio\fP(5), +\fBmtree\fP(5), +\fBtar\fP(5) diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_write_header.3 b/dependencies/libarchive-3.4.2/doc/man/archive_write_header.3 new file mode 100644 index 0000000..941ecef --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_write_header.3 @@ -0,0 +1,51 @@ +.TH ARCHIVE_WRITE_HEADER 3 "February 2, 2012" "" +.SH NAME +.ad l +\fB\%archive_write_header\fP +\- functions for creating archives +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIint\fP +.br +\fB\%archive_write_header\fP(\fI\%struct\ archive\ *\fP, \fI\%struct\ archive_entry\ *\fP); +.SH DESCRIPTION +.ad l +Build and write a header using the data in the provided +Tn struct archive_entry +structure. +See +\fBarchive_entry\fP(3) +for information on creating and populating +Tn struct archive_entry +objects. +.SH RETURN VALUES +.ad l +This function returns +\fBARCHIVE_OK\fP +on success, or one of the following on error: +\fBARCHIVE_RETRY\fP +for operations that might succeed if retried, +\fBARCHIVE_WARN\fP +for unusual conditions that do not prevent further operations, and +\fBARCHIVE_FATAL\fP +for serious errors that make remaining operations impossible. +.SH ERRORS +.ad l +Detailed error codes and textual descriptions are available from the +\fB\%archive_errno\fP() +and +\fB\%archive_error_string\fP() +functions. +.SH SEE ALSO +.ad l +\fBtar\fP(1), +\fBarchive_write_set_options\fP(3), +\fBlibarchive\fP(3), +\fBcpio\fP(5), +\fBmtree\fP(5), +\fBtar\fP(5) diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_write_new.3 b/dependencies/libarchive-3.4.2/doc/man/archive_write_new.3 new file mode 100644 index 0000000..c5969a3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_write_new.3 @@ -0,0 +1,36 @@ +.TH ARCHIVE_WRITE_NEW 3 "February 2, 2012" "" +.SH NAME +.ad l +\fB\%archive_write_new\fP +\- functions for creating archives +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIstruct archive *\fP +.br +\fB\%archive_write_new\fP(\fI\%void\fP); +.SH DESCRIPTION +.ad l +Allocates and initializes a +Tn struct archive +object suitable for writing a tar archive. +.BR NULL +is returned on error. +.PP +A complete description of the +Tn struct archive +object can be found in the overview manual page for +\fBlibarchive\fP(3). +.SH SEE ALSO +.ad l +\fBtar\fP(1), +\fBarchive_write\fP(3), +\fBarchive_write_set_options\fP(3), +\fBlibarchive\fP(3), +\fBcpio\fP(5), +\fBmtree\fP(5), +\fBtar\fP(5) diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_write_open.3 b/dependencies/libarchive-3.4.2/doc/man/archive_write_open.3 new file mode 100644 index 0000000..ab76795 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_write_open.3 @@ -0,0 +1,222 @@ +.TH ARCHIVE_WRITE_OPEN 3 "February 2, 2012" "" +.SH NAME +.ad l +\fB\%archive_write_open\fP, +\fB\%archive_write_open_fd\fP, +\fB\%archive_write_open_FILE\fP, +\fB\%archive_write_open_filename\fP, +\fB\%archive_write_open_memory\fP +\- functions for creating archives +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIint\fP +.br +\fB\%archive_write_open\fP(\fI\%struct\ archive\ *\fP, \fI\%void\ *client_data\fP, \fI\%archive_open_callback\ *\fP, \fI\%archive_write_callback\ *\fP, \fI\%archive_close_callback\ *\fP); +.br +\fIint\fP +.br +\fB\%archive_write_open_fd\fP(\fI\%struct\ archive\ *\fP, \fI\%int\ fd\fP); +.br +\fIint\fP +.br +\fB\%archive_write_open_FILE\fP(\fI\%struct\ archive\ *\fP, \fI\%FILE\ *file\fP); +.br +\fIint\fP +.br +\fB\%archive_write_open_filename\fP(\fI\%struct\ archive\ *\fP, \fI\%const\ char\ *filename\fP); +.br +\fIint\fP +.br +\fB\%archive_write_open_memory\fP(\fI\%struct\ archive\ *\fP, \fI\%void\ *buffer\fP, \fI\%size_t\ bufferSize\fP, \fI\%size_t\ *outUsed\fP); +.SH DESCRIPTION +.ad l +.RS 5 +.TP +\fB\%archive_write_open\fP() +Freeze the settings, open the archive, and prepare for writing entries. +This is the most generic form of this function, which accepts +pointers to three callback functions which will be invoked by +the compression layer to write the constructed archive. +This does not alter the default archive padding. +.TP +\fB\%archive_write_open_fd\fP() +A convenience form of +\fB\%archive_write_open\fP() +that accepts a file descriptor. +The +\fB\%archive_write_open_fd\fP() +function is safe for use with tape drives or other +block-oriented devices. +.TP +\fB\%archive_write_open_FILE\fP() +A convenience form of +\fB\%archive_write_open\fP() +that accepts a +\fIFILE *\fP +pointer. +Note that +\fB\%archive_write_open_FILE\fP() +is not safe for writing to tape drives or other devices +that require correct blocking. +.TP +\fB\%archive_write_open_file\fP() +A deprecated synonym for +\fB\%archive_write_open_filename\fP(). +.TP +\fB\%archive_write_open_filename\fP() +A convenience form of +\fB\%archive_write_open\fP() +that accepts a filename. +A NULL argument indicates that the output should be written to standard output; +an argument of +``-'' +will open a file with that name. +If you have not invoked +\fB\%archive_write_set_bytes_in_last_block\fP(), +then +\fB\%archive_write_open_filename\fP() +will adjust the last-block padding depending on the file: +it will enable padding when writing to standard output or +to a character or block device node, it will disable padding otherwise. +You can override this by manually invoking +\fB\%archive_write_set_bytes_in_last_block\fP() +before calling +\fB\%archive_write_open\fP(). +The +\fB\%archive_write_open_filename\fP() +function is safe for use with tape drives or other +block-oriented devices. +.TP +\fB\%archive_write_open_memory\fP() +A convenience form of +\fB\%archive_write_open\fP() +that accepts a pointer to a block of memory that will receive +the archive. +The final +\fIsize_t *\fP +argument points to a variable that will be updated +after each write to reflect how much of the buffer +is currently in use. +You should be careful to ensure that this variable +remains allocated until after the archive is +closed. +This function will disable padding unless you +have specifically set the block size. +.RE +More information about the +\fIstruct\fP archive +object and the overall design of the library can be found in the +\fBlibarchive\fP(3) +overview. +.PP +Note that the convenience forms above vary in how +they block the output. +See +\fBarchive_write_blocksize\fP(3) +if you need to control the block size used for writes +or the end-of-file padding behavior. +.SH CLIENT CALLBACKS +.ad l +To use this library, you will need to define and register +callback functions that will be invoked to write data to the +resulting archive. +These functions are registered by calling +\fB\%archive_write_open\fP(): +.RS 5 +.IP +\fItypedef int\fP +\fB\%archive_open_callback\fP(\fI\%struct\ archive\ *\fP, \fI\%void\ *client_data\fP) +.RE +.PP +The open callback is invoked by +\fB\%archive_write_open\fP(). +It should return +\fBARCHIVE_OK\fP +if the underlying file or data source is successfully +opened. +If the open fails, it should call +\fB\%archive_set_error\fP() +to register an error code and message and return +\fBARCHIVE_FATAL\fP. +.RS 5 +.IP +\fItypedef la_ssize_t\fP +\fB\%archive_write_callback\fP(\fI\%struct\ archive\ *\fP, \fI\%void\ *client_data\fP, \fI\%const\ void\ *buffer\fP, \fI\%size_t\ length\fP) +.RE +.PP +The write callback is invoked whenever the library +needs to write raw bytes to the archive. +For correct blocking, each call to the write callback function +should translate into a single +\fBwrite\fP(2) +system call. +This is especially critical when writing archives to tape drives. +On success, the write callback should return the +number of bytes actually written. +On error, the callback should invoke +\fB\%archive_set_error\fP() +to register an error code and message and return -1. +.RS 5 +.IP +\fItypedef int\fP +\fB\%archive_close_callback\fP(\fI\%struct\ archive\ *\fP, \fI\%void\ *client_data\fP) +.RE +.PP +The close callback is invoked by archive_close when +the archive processing is complete. +The callback should return +\fBARCHIVE_OK\fP +on success. +On failure, the callback should invoke +\fB\%archive_set_error\fP() +to register an error code and message and +return +\fBARCHIVE_FATAL\fP. +.PP +Note that if the client-provided write callback function +returns a non-zero value, that error will be propagated back to the caller +through whatever API function resulted in that call, which +may include +\fB\%archive_write_header\fP(), +\fB\%archive_write_data\fP(), +\fB\%archive_write_close\fP(), +\fB\%archive_write_finish\fP(), +or +\fB\%archive_write_free\fP(). +The client callback can call +\fB\%archive_set_error\fP() +to provide values that can then be retrieved by +\fB\%archive_errno\fP() +and +\fB\%archive_error_string\fP(). +.SH RETURN VALUES +.ad l +These functions return +\fBARCHIVE_OK\fP +on success, or +\fBARCHIVE_FATAL\fP. +.SH ERRORS +.ad l +Detailed error codes and textual descriptions are available from the +\fB\%archive_errno\fP() +and +\fB\%archive_error_string\fP() +functions. +.SH SEE ALSO +.ad l +\fBtar\fP(1), +\fBarchive_write\fP(3), +\fBarchive_write_blocksize\fP(3), +\fBarchive_write_filter\fP(3), +\fBarchive_write_format\fP(3), +\fBarchive_write_new\fP(3), +\fBarchive_write_set_options\fP(3), +\fBlibarchive\fP(3), +\fBcpio\fP(5), +\fBmtree\fP(5), +\fBtar\fP(5) diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_write_set_options.3 b/dependencies/libarchive-3.4.2/doc/man/archive_write_set_options.3 new file mode 100644 index 0000000..e5a4f7b --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_write_set_options.3 @@ -0,0 +1,784 @@ +.TH ARCHIVE_WRITE_OPTIONS 3 "January 31, 2020" "" +.SH NAME +.ad l +\fB\%archive_write_set_filter_option\fP, +\fB\%archive_write_set_format_option\fP, +\fB\%archive_write_set_option\fP, +\fB\%archive_write_set_options\fP +\- functions controlling options for writing archives +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +.br +\fIint\fP +.br +\fB\%archive_write_set_filter_option\fP(\fI\%struct\ archive\ *\fP, \fI\%const\ char\ *module\fP, \fI\%const\ char\ *option\fP, \fI\%const\ char\ *value\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_format_option\fP(\fI\%struct\ archive\ *\fP, \fI\%const\ char\ *module\fP, \fI\%const\ char\ *option\fP, \fI\%const\ char\ *value\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_option\fP(\fI\%struct\ archive\ *\fP, \fI\%const\ char\ *module\fP, \fI\%const\ char\ *option\fP, \fI\%const\ char\ *value\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_options\fP(\fI\%struct\ archive\ *\fP, \fI\%const\ char\ *options\fP); +.SH DESCRIPTION +.ad l +These functions provide a way for libarchive clients to configure +specific write modules. +.RS 5 +.TP +\fB\%archive_write_set_filter_option\fP(), +\fB\%archive_write_set_format_option\fP() +Specifies an option that will be passed to the currently-registered +filters (including decompression filters) or format readers. +.PP +If +\fIoption\fP +and +\fIvalue\fP +are both +.BR NULL, +these functions will do nothing and +\fBARCHIVE_OK\fP +will be returned. +If +\fIoption\fP +is +.BR NULL +but +\fIvalue\fP +is not, these functions will do nothing and +\fBARCHIVE_FAILED\fP +will be returned. +.PP +If +\fImodule\fP +is not +.BR NULL, +\fIoption\fP +and +\fIvalue\fP +will be provided to the filter or reader named +\fImodule\fP. +The return value will be either +\fBARCHIVE_OK\fP +if the option was successfully handled or +\fBARCHIVE_WARN\fP +if the option was unrecognized by the module or could otherwise +not be handled. +If there is no such module, +\fBARCHIVE_FAILED\fP +will be returned. +.PP +If +\fImodule\fP +is +.BR NULL, +\fIoption\fP +and +\fIvalue\fP +will be provided to every registered module. +If any module returns +\fBARCHIVE_FATAL\fP, +this value will be returned immediately. +Otherwise, +\fBARCHIVE_OK\fP +will be returned if any module accepts the option, and +\fBARCHIVE_FAILED\fP +in all other cases. +.TP +\fB\%archive_write_set_option\fP() +Calls +\fB\%archive_write_set_format_option\fP(), +then +\fB\%archive_write_set_filter_option\fP(). +If either function returns +\fBARCHIVE_FATAL\fP, +\fBARCHIVE_FATAL\fP +will be returned +immediately. +Otherwise, the greater of the two values will be returned. +.TP +\fB\%archive_write_set_options\fP() +\fIoptions\fP +is a comma-separated list of options. +If +\fIoptions\fP +is +.BR NULL +or empty, +\fBARCHIVE_OK\fP +will be returned immediately. +.PP +Individual options have one of the following forms: +.RS 5 +.TP +\fIoption=value\fP +The option/value pair will be provided to every module. +Modules that do not accept an option with this name will ignore it. +.TP +\fIoption\fP +The option will be provided to every module with a value of +``1''. +.TP +\fI!option\fP +The option will be provided to every module with a NULL value. +.TP +\fImodule:option=value\fP, \fImodule:option\fP, \fImodule:!option\fP +As above, but the corresponding option and value will be provided +only to modules whose name matches +\fImodule\fP. +.RE +.RE +.SH OPTIONS +.ad l +.RS 5 +.TP +Filter b64encode +.RS 5 +.TP +\fBmode\fP +The value is interpreted as octal digits specifying the file mode. +.TP +\fBname\fP +The value specifies the file name. +.RE +.TP +Filter bzip2 +.RS 5 +.TP +\fBcompression-level\fP +The value is interpreted as a decimal integer specifying the +bzip2 compression level. Supported values are from 1 to 9. +.RE +.TP +Filter gzip +.RS 5 +.TP +\fBcompression-level\fP +The value is interpreted as a decimal integer specifying the +gzip compression level. Supported values are from 0 to 9. +.TP +\fBtimestamp\fP +Store timestamp. This is enabled by default. +.RE +.TP +Filter lrzip +.RS 5 +.TP +\fBcompression\fP=\fItype\fP +Use +\fItype\fP +as compression method. +Supported values are +``bzip2'', +``gzipi'', +``lzo'' +(ultra fast,) +and +``zpaq'' +(best, extremely slow.) +.TP +\fBcompression-level\fP +The value is interpreted as a decimal integer specifying the +lrzip compression level. Supported values are from 1 to 9. +.RE +.TP +Filter lz4 +.RS 5 +.TP +\fBcompression-level\fP +The value is interpreted as a decimal integer specifying the +lz4 compression level. Supported values are from 0 to 9. +.TP +\fBstream-checksum\fP +Enable stream checksum. This is enabled by default. +.TP +\fBblock-checksum\fP +Enable block checksum. This is disabled by default. +.TP +\fBblock-size\fP +The value is interpreted as a decimal integer specifying the +lz4 compression block size. Supported values are from 4 to 7 +(default.) +.TP +\fBblock-dependence\fP +Use the previous block of the block being compressed for +a compression dictionary to improve compression ratio. +This is disabled by default. +.RE +.TP +Filter lzop +.RS 5 +.TP +\fBcompression-level\fP +The value is interpreted as a decimal integer specifying the +lzop compression level. Supported values are from 1 to 9. +.RE +.TP +Filter uuencode +.RS 5 +.TP +\fBmode\fP +The value is interpreted as octal digits specifying the file mode. +.TP +\fBname\fP +The value specifies the file name. +.RE +.TP +Filter xz +.RS 5 +.TP +\fBcompression-level\fP +The value is interpreted as a decimal integer specifying the +compression level. Supported values are from 0 to 9. +.TP +\fBthreads\fP +The value is interpreted as a decimal integer specifying the +number of threads for multi-threaded lzma compression. +If supported, the default value is read from +\fB\%lzma_cputhreads\fP(). +.RE +.TP +Filter zstd +.RS 5 +.TP +\fBcompression-level\fP +The value is interpreted as a decimal integer specifying the +compression level. Supported values are from 1 to 22. +.RE +.TP +Format 7zip +.RS 5 +.TP +\fBcompression\fP +The value is one of +``store'', +``deflate'', +``bzip2'', +``lzma1'', +``lzma2'' +or +``ppmd'' +to indicate how the following entries should be compressed. +Note that this setting is ignored for directories, symbolic links, +and other special entries. +.TP +\fBcompression-level\fP +The value is interpreted as a decimal integer specifying the +compression level. +Values between 0 and 9 are supported. +The interpretation of the compression level depends on the chosen +compression method. +.RE +.TP +Format cpio +.RS 5 +.TP +\fBhdrcharset\fP +The value is used as a character set name that will be +used when translating file names. +.RE +.TP +Format gnutar +.RS 5 +.TP +\fBhdrcharset\fP +The value is used as a character set name that will be +used when translating file, group and user names. +.RE +.TP +Format iso9660 - volume metadata +These options are used to set standard ISO9660 metadata. +.RS 5 +.TP +\fBabstract-file\fP=\fIfilename\fP +The file with the specified name will be identified in the ISO9660 metadata +as holding the abstract for this volume. +Default: none. +.TP +\fBapplication-id\fP=\fIfilename\fP +The file with the specified name will be identified in the ISO9660 metadata +as holding the application identifier for this volume. +Default: none. +.TP +\fBbiblio-file\fP=\fIfilename\fP +The file with the specified name will be identified in the ISO9660 metadata +as holding the bibliography for this volume. +Default: none. +.TP +\fBcopyright-file\fP=\fIfilename\fP +The file with the specified name will be identified in the ISO9660 metadata +as holding the copyright for this volume. +Default: none. +.TP +\fBpublisher\fP=\fIfilename\fP +The file with the specified name will be identified in the ISO9660 metadata +as holding the publisher information for this volume. +Default: none. +.TP +\fBvolume-id\fP=\fIstring\fP +The specified string will be used as the Volume Identifier in the ISO9660 metadata. +It is limited to 32 bytes. +Default: none. +.RE +.TP +Format iso9660 - boot support +These options are used to make an ISO9660 image that can be directly +booted on various systems. +.RS 5 +.TP +\fBboot\fP=\fIfilename\fP +The file matching this name will be used as the El Torito boot image file. +.TP +\fBboot-catalog\fP=\fIname\fP +The name that will be used for the El Torito boot catalog. +Default: +\fIboot.catalog\fP +.TP +\fBboot-info-table\fP +The boot image file provided by the +\fBboot\fP=\fIfilename\fP +option will be edited with appropriate boot information in bytes 8 through 64. +Default: disabled +.TP +\fBboot-load-seg\fP=\fIhexadecimal-number\fP +The load segment for a no-emulation boot image. +.TP +\fBboot-load-size\fP=\fIdecimal-number\fP +The number of "virtual" 512-byte sectors to be loaded from a no-emulation boot image. +Some very old BIOSes can only load very small images, setting this +value to 4 will often allow such BIOSes to load the first part of +the boot image (which will then need to be intelligent enough to +load the rest of itself). +This should not be needed unless you are trying to support systems with very old BIOSes. +This defaults to the full size of the image. +.TP +\fBboot-type\fP=\fIvalue\fP +Specifies the boot semantics used by the El Torito boot image: +If the +\fIvalue\fP +is +\fBfd\fP, +then the boot image is assumed to be a bootable floppy image. +If the +\fIvalue\fP +is +\fBhd\fP, +then the boot image is assumed to be a bootable hard disk image. +If the +\fIvalue\fP +is +\fBno-emulation\fP, +the boot image is used without floppy or hard disk emulation. +If the boot image is exactly 1.2MB, 1.44MB, or 2.88MB, then +the default is +\fBfd\fP, +otherwise the default is +\fBno-emulation\fP. +.RE +.TP +Format iso9660 - filename and size extensions +Various extensions to the base ISO9660 format. +.RS 5 +.TP +\fBallow-ldots\fP +If enabled, allows filenames to begin with a leading period. +If disabled, filenames that begin with a leading period will have +that period replaced by an underscore character in the standard ISO9660 +namespace. +This does not impact names stored in the Rockridge or Joliet extension area. +Default: disabled. +.TP +\fBallow-lowercase\fP +If enabled, allows filenames to contain lowercase characters. +If disabled, filenames will be forced to uppercase. +This does not impact names stored in the Rockridge or Joliet extension area. +Default: disabled. +.TP +\fBallow-multidot\fP +If enabled, allows filenames to contain multiple period characters, in violation of the ISO9660 specification. +If disabled, additional periods will be converted to underscore characters. +This does not impact names stored in the Rockridge or Joliet extension area. +Default: disabled. +.TP +\fBallow-period\fP +If enabled, allows filenames to contain trailing period characters, in violation of the ISO9660 specification. +If disabled, trailing periods will be converted to underscore characters. +This does not impact names stored in the Rockridge or Joliet extension area. +Default: disabled. +.TP +\fBallow-pvd-lowercase\fP +If enabled, the Primary Volume Descriptor may contain lowercase ASCII characters, in violation of the ISO9660 specification. +If disabled, characters will be converted to uppercase ASCII. +Default: disabled. +.TP +\fBallow-sharp-tilde\fP +If enabled, sharp and tilde characters will be permitted in filenames, in violation if the ISO9660 specification. +If disabled, such characters will be converted to underscore characters. +Default: disabled. +.TP +\fBallow-vernum\fP +If enabled, version numbers will be included with files. +If disabled, version numbers will be suppressed, in violation of the ISO9660 standard. +This does not impact names stored in the Rockridge or Joliet extension area. +Default: enabled. +.TP +\fBiso-level\fP +This enables support for file size and file name extensions in the +core ISO9660 area. +The name extensions specified here do not affect the names stored in the Rockridge or Joliet extension areas. +.RS 5 +.TP +\fBiso-level=1\fP +The most compliant form of ISO9660 image. +Filenames are limited to 8.3 uppercase format, +directory names are limited to 8 uppercase characters, +files are limited to 4 GiB, +the complete ISO9660 image cannot exceed 4 GiB. +.TP +\fBiso-level=2\fP +Filenames are limited to 30 uppercase characters with a 30-character extension, +directory names are limited to 30 characters, +files are limited to 4 GiB. +.TP +\fBiso-level=3\fP +As with +\fBiso-level=2\fP, +except that files may exceed 4 GiB. +.TP +\fBiso-level=4\fP +As with +\fBiso-level=3\fP, +except that filenames may be up to 193 characters +and may include arbitrary 8-bit characters. +.RE +.TP +\fBjoliet\fP +Microsoft's Joliet extensions store a completely separate set of directory information about each file. +In particular, this information includes Unicode filenames of up to 255 characters. +Default: enabled. +.TP +\fBlimit-depth\fP +If enabled, libarchive will use directory relocation records to ensure that +no pathname exceeds the ISO9660 limit of 8 directory levels. +If disabled, no relocation will occur. +Default: enabled. +.TP +\fBlimit-dirs\fP +If enabled, libarchive will cause an error if there are more than +65536 directories. +If disabled, there is no limit on the number of directories. +Default: enabled +.TP +\fBpad\fP +If enabled, 300 kiB of zero bytes will be appended to the end of the archive. +Default: enabled +.TP +\fBrelaxed-filenames\fP +If enabled, all 7-bit ASCII characters are permitted in filenames +(except lowercase characters unless +\fBallow-lowercase\fP +is also specified). +This violates ISO9660 standards. +This does not impact names stored in the Rockridge or Joliet extension area. +Default: disabled. +.TP +\fBrockridge\fP +The Rockridge extensions store an additional set of POSIX-style file +information with each file, including mtime, atime, ctime, permissions, +and long filenames with arbitrary 8-bit characters. +These extensions also support symbolic links and other POSIX file types. +Default: enabled. +.RE +.TP +Format iso9660 - zisofs support +The zisofs extensions permit each file to be independently compressed +using a gzip-compatible compression. +This can provide significant size savings, but requires the reading +system to have support for these extensions. +These extensions are disabled by default. +.RS 5 +.TP +\fBcompression-level\fP=number +The compression level used by the deflate compressor. +Ranges from 0 (least effort) to 9 (most effort). +Default: 6 +.TP +\fBzisofs\fP +Synonym for +\fBzisofs=direct\fP. +.TP +\fBzisofs=direct\fP +Compress each file in the archive. +Unlike +\fBzisofs=indirect\fP, +this is handled entirely within libarchive and does not require a +separate utility. +For best results, libarchive tests each file and will store +the file uncompressed if the compression does not actually save any space. +In particular, files under 2k will never be compressed. +Note that boot image files are never compressed. +.TP +\fBzisofs=indirect\fP +Recognizes files that have already been compressed with the +\fBmkzftree\fP +utility and sets up the necessary file metadata so that +readers will correctly identify these as zisofs-compressed files. +.TP +\fBzisofs-exclude\fP=\fIfilename\fP +Specifies a filename that should not be compressed when using +\fBzisofs=direct\fP. +This option can be provided multiple times to suppress compression +on many files. +.RE +.TP +Format mtree +.RS 5 +.TP +\fBcksum\fP, \fBdevice\fP, \fBflags\fP, \fBgid\fP, \fBgname\fP, \fBindent\fP, \fBlink\fP, \fBmd5\fP, \fBmode\fP, \fBnlink\fP, \fBrmd160\fP, \fBsha1\fP, \fBsha256\fP, \fBsha384\fP, \fBsha512\fP, \fBsize\fP, \fBtime\fP, \fBuid\fP, \fBuname\fP +Enable a particular keyword in the mtree output. +Prefix with an exclamation mark to disable the corresponding keyword. +The default is equivalent to +``device, flags, gid, gname, link, mode, nlink, size, time, type, uid, uname''. +.TP +\fBall\fP +Enables all of the above keywords. +.TP +\fBuse-set\fP +Enables generation of +\fB/set\fP +lines that specify default values for the following files and/or directories. +.TP +\fBindent\fP +XXX needs explanation XXX +.RE +.TP +Format newc +.RS 5 +.TP +\fBhdrcharset\fP +The value is used as a character set name that will be +used when translating file names. +.RE +.TP +Format pax +.RS 5 +.TP +\fBhdrcharset\fP +The value is used as a character set name that will be +used when translating file, group and user names. +The value is one of +``BINARY'' +or +``UTF-8''. +With +``BINARY'' +there is no character conversion, with +``UTF-8'' +names are converted to UTF-8. +.TP +\fBxattrheader\fP +When storing extended attributes, this option configures which +headers should be written. The value is one of +``all'', +``LIBARCHIVE'', +or +``SCHILY''. +By default, both +``LIBARCHIVE.xattr'' +and +``SCHILY.xattr'' +headers are written. +.RE +.TP +Format ustar +.RS 5 +.TP +\fBhdrcharset\fP +The value is used as a character set name that will be +used when translating file, group and user names. +.RE +.TP +Format v7tar +.RS 5 +.TP +\fBhdrcharset\fP +The value is used as a character set name that will be +used when translating file, group and user names. +.RE +.TP +Format warc +.RS 5 +.TP +\fBomit-warcinfo\fP +Set to +``true'' +to disable output of the warcinfo record. +.RE +.TP +Format xar +.RS 5 +.TP +\fBchecksum\fP=\fItype\fP +Use +\fItype\fP +as file checksum method. +Supported values are +``none'', +``md5'', +and +``sha1'' +(default.) +.TP +\fBcompression\fP=\fItype\fP +Use +\fItype\fP +as compression method. +Supported values are +``none'', +``bzip2'', +``gzip'' +(default,) +``lzma'' +and +``xz''. +.TP +\fBcompression_level\fP +The value is a decimal integer from 1 to 9 specifying the compression level. +.TP +\fBtoc-checksum\fP=\fItype\fP +Use +\fItype\fP +as table of contents checksum method. +Supported values are +``none'', +``md5'' +and +``sha1'' +(default.) +.RE +.TP +Format zip +.RS 5 +.TP +\fBcompression\fP +The value is either +``store'' +or +``deflate'' +to indicate how the following entries should be compressed. +Note that this setting is ignored for directories, symbolic links, +and other special entries. +.TP +\fBcompression-level\fP +The value is interpreted as a decimal integer specifying the +compression level. +Values between 0 and 9 are supported. +A compression level of 0 switches the compression method to +``store'', +other values will enable +``deflate'' +compression with the given level. +.TP +\fBencryption\fP +Enable encryption using traditional zip encryption. +.TP +\fBencryption\fP=\fItype\fP +Use +\fItype\fP +as encryption type. +Supported values are +``zipcrypt'' +(traditional zip encryption,) +``aes128'' +(WinZip AES-128 encryption) +and +``aes256'' +(WinZip AES-256 encryption.) +.TP +\fBexperimental\fP +This boolean option enables or disables experimental Zip features +that may not be compatible with other Zip implementations. +.TP +\fBfakecrc32\fP +This boolean option disables CRC calculations. +All CRC fields are set to zero. +It should not be used except for testing purposes. +.TP +\fBhdrcharset\fP +The value is used as a character set name that will be +used when translating file names. +.TP +\fBzip64\fP +Zip64 extensions provide additional file size information +for entries larger than 4 GiB. +They also provide extended file offset and archive size information +when archives exceed 4 GiB. +By default, the Zip writer selectively enables these extensions only as needed. +In particular, if the file size is unknown, the Zip writer will +include Zip64 extensions to guard against the possibility that the +file might be larger than 4 GiB. +.PP +Setting this boolean option will force the writer to use Zip64 extensions +even for small files that would not otherwise require them. +This is primarily useful for testing. +.PP +Disabling this option with +\fB!zip64\fP +will force the Zip writer to avoid Zip64 extensions: +It will reject files with size greater than 4 GiB, +it will reject any new entries once the total archive size reaches 4 GiB, +and it will not use Zip64 extensions for files with unknown size. +In particular, this can improve compatibility when generating archives +where the entry sizes are not known in advance. +.RE +.RE +.SH EXAMPLES +.ad l +The following example creates an archive write handle to +create a gzip-compressed ISO9660 format image. +The two options here specify that the ISO9660 archive will use +\fIkernel.img\fP +as the boot image for El Torito booting, and that the gzip +compressor should use the maximum compression level. +.RS 4 +.nf +a = archive_write_new(); +archive_write_add_filter_gzip(a); +archive_write_set_format_iso9660(a); +archive_write_set_options(a, "boot=kernel.img,compression=9"); +archive_write_open_filename(a, filename, blocksize); +.RE +.SH ERRORS +.ad l +More detailed error codes and textual descriptions are available from the +\fB\%archive_errno\fP() +and +\fB\%archive_error_string\fP() +functions. +.SH SEE ALSO +.ad l +\fBtar\fP(1), +\fBarchive_read_set_options\fP(3), +\fBarchive_write\fP(3), +\fBlibarchive\fP(3) +.SH HISTORY +.ad l +The +\fB\%libarchive\fP +library first appeared in +FreeBSD 5.3. +.SH AUTHORS +.ad l +-nosplit +The options support for libarchive was originally implemented by +Michihiro NAKAJIMA. +.SH BUGS +.ad l diff --git a/dependencies/libarchive-3.4.2/doc/man/archive_write_set_passphrase.3 b/dependencies/libarchive-3.4.2/doc/man/archive_write_set_passphrase.3 new file mode 100644 index 0000000..7e67415 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/archive_write_set_passphrase.3 @@ -0,0 +1,49 @@ +.TH ARCHIVE_WRITE_SET_PASSPHRASE 3 "September 21, 2014" "" +.SH NAME +.ad l +\fB\%archive_write_set_passphrase\fP, +\fB\%archive_write_set_passphrase_callback\fP +\- functions for writing encrypted archives +.SH LIBRARY +.ad l +Streaming Archive Library (libarchive, -larchive) +.SH SYNOPSIS +.ad l +\fB#include \fP +.br +\fIint\fP +.br +\fB\%archive_write_set_passphrase\fP(\fI\%struct\ archive\ *\fP, \fI\%const\ char\ *passphrase\fP); +.br +\fIint\fP +.br +\fB\%archive_write_set_passphrase_callback\fP(\fI\%struct\ archive\ *\fP, \fI\%void\ *client_data\fP, \fI\%archive_passphrase_callback\ *\fP); +.SH DESCRIPTION +.ad l +.RS 5 +.TP +\fB\%archive_write_set_passphrase\fP() +Set a passphrase for writing an encrypted archive. +If +\fIpassphrase\fP +is +.BR NULL +or empty, this function will do nothing and +\fBARCHIVE_FAILED\fP +will be returned. +Otherwise, +\fBARCHIVE_OK\fP +will be returned. +.TP +\fB\%archive_write_set_passphrase_callback\fP() +Register a callback function that will be invoked to get a passphrase +for encryption if the passphrase was not set by the +\fB\%archive_write_set_passphrase\fP() +function. +.RE +.SH SEE ALSO +.ad l +\fBtar\fP(1), +\fBarchive_write\fP(3), +\fBarchive_write_set_options\fP(3), +\fBlibarchive\fP(3) diff --git a/dependencies/libarchive-3.4.2/doc/man/bsdcpio.1 b/dependencies/libarchive-3.4.2/doc/man/bsdcpio.1 new file mode 100644 index 0000000..8f31df6 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/bsdcpio.1 @@ -0,0 +1,481 @@ +.TH CPIO 1 "September 16, 2014" "" +.SH NAME +.ad l +\fB\%cpio\fP +\- copy files to and from archives +.SH SYNOPSIS +.ad l +.br +\fB\%cpio\fP +\fB\-i\fP +[\fIoptions\fP] +[\fIpattern\fP ...] +[\fI<\fP archive] +.br +\fB\%cpio\fP +\fB\-o\fP +[\fIoptions\fP] +\fI<\fP name-list +[\fI>\fP archive] +.br +\fB\%cpio\fP +\fB\-p\fP +[\fIoptions\fP] +\fIdest-dir\fP +\fI<\fP name-list +.SH DESCRIPTION +.ad l +\fB\%cpio\fP +copies files between archives and directories. +This implementation can extract from tar, pax, cpio, zip, jar, ar, +and ISO 9660 cdrom images and can create tar, pax, cpio, ar, +and shar archives. +.PP +The first option to +\fB\%cpio\fP +is a mode indicator from the following list: +.RS 5 +.TP +\fB\-i\fP +Input. +Read an archive from standard input (unless overridden) and extract the +contents to disk or (if the +\fB\-t\fP +option is specified) +list the contents to standard output. +If one or more file patterns are specified, only files matching +one of the patterns will be extracted. +.TP +\fB\-o\fP +Output. +Read a list of filenames from standard input and produce a new archive +on standard output (unless overridden) containing the specified items. +.TP +\fB\-p\fP +Pass-through. +Read a list of filenames from standard input and copy the files to the +specified directory. +.RE +.SH OPTIONS +.ad l +Unless specifically stated otherwise, options are applicable in +all operating modes. +.RS 5 +.TP +\fB\-0\fP, \fB\-Fl\fP null +Read filenames separated by NUL characters instead of newlines. +This is necessary if any of the filenames being read might contain newlines. +.TP +\fB\-A\fP +(o mode only) +Append to the specified archive. +(Not yet implemented.) +.TP +\fB\-a\fP +(o and p modes) +Reset access times on files after they are read. +.TP +\fB\-B\fP +(o mode only) +Block output to records of 5120 bytes. +.TP +\fB\-C\fP \fIsize\fP +(o mode only) +Block output to records of +\fIsize\fP +bytes. +.TP +\fB\-c\fP +(o mode only) +Use the old POSIX portable character format. +Equivalent to +\fB\-Fl\fP format \fIodc\fP. +.TP +\fB\-d\fP, \fB\-Fl\fP make-directories +(i and p modes) +Create directories as necessary. +.TP +\fB\-E\fP \fIfile\fP +(i mode only) +Read list of file name patterns from +\fIfile\fP +to list and extract. +.TP +\fB\-F\fP \fIfile\fP, \fB\-Fl\fP file \fIfile\fP +Read archive from or write archive to +\fIfile\fP. +.TP +\fB\-f\fP \fIpattern\fP +(i mode only) +Ignore files that match +\fIpattern\fP. +.TP +\fB\-H\fP \fIformat\fP, \fB\-Fl\fP format \fIformat\fP +(o mode only) +Produce the output archive in the specified format. +Supported formats include: +.PP +.RS 5 +.TP +\fIcpio\fP +Synonym for +\fIodc\fP. +.TP +\fInewc\fP +The SVR4 portable cpio format. +.TP +\fIodc\fP +The old POSIX.1 portable octet-oriented cpio format. +.TP +\fIpax\fP +The POSIX.1 pax format, an extension of the ustar format. +.TP +\fIustar\fP +The POSIX.1 tar format. +.RE +.PP +The default format is +\fIodc\fP. +See +\fBlibarchive-formats\fP(5) +for more complete information about the +formats currently supported by the underlying +\fBlibarchive\fP(3) +library. +.TP +\fB\-h\fP, \fB\-Fl\fP help +Print usage information. +.TP +\fB\-I\fP \fIfile\fP +Read archive from +\fIfile\fP. +.TP +\fB\-i\fP, \fB\-Fl\fP extract +Input mode. +See above for description. +.TP +\fB\-Fl\fP insecure +(i and p mode only) +Disable security checks during extraction or copying. +This allows extraction via symbolic links, absolute paths, +and path names containing +Sq .. +in the name. +.TP +\fB\-J\fP, \fB\-Fl\fP xz +(o mode only) +Compress the file with xz-compatible compression before writing it. +In input mode, this option is ignored; xz compression is recognized +automatically on input. +.TP +\fB\-j\fP +Synonym for +\fB\-y\fP. +.TP +\fB\-L\fP +(o and p modes) +All symbolic links will be followed. +Normally, symbolic links are archived and copied as symbolic links. +With this option, the target of the link will be archived or copied instead. +.TP +\fB\-l\fP, \fB\-Fl\fP link +(p mode only) +Create links from the target directory to the original files, +instead of copying. +.TP +\fB\-Fl\fP lrzip +(o mode only) +Compress the resulting archive with +\fBlrzip\fP(1). +In input mode, this option is ignored. +.TP +\fB\-Fl\fP lz4 +(o mode only) +Compress the archive with lz4-compatible compression before writing it. +In input mode, this option is ignored; lz4 compression is recognized +automatically on input. +.TP +\fB\-Fl\fP zstd +(o mode only) +Compress the archive with zstd-compatible compression before writing it. +In input mode, this option is ignored; zstd compression is recognized +automatically on input. +.TP +\fB\-Fl\fP lzma +(o mode only) +Compress the file with lzma-compatible compression before writing it. +In input mode, this option is ignored; lzma compression is recognized +automatically on input. +.TP +\fB\-Fl\fP lzop +(o mode only) +Compress the resulting archive with +\fBlzop\fP(1). +In input mode, this option is ignored. +.TP +\fB\-Fl\fP passphrase \fIpassphrase\fP +The +\fIpassphrase\fP +is used to extract or create an encrypted archive. +Currently, zip is only a format that +\fB\%cpio\fP +can handle encrypted archives. +You shouldn't use this option unless you realize how insecure +use of this option is. +.TP +\fB\-m\fP, \fB\-Fl\fP preserve-modification-time +(i and p modes) +Set file modification time on created files to match +those in the source. +.TP +\fB\-n\fP, \fB\-Fl\fP numeric-uid-gid +(i mode, only with +\fB\-t\fP) +Display numeric uid and gid. +By default, +\fB\%cpio\fP +displays the user and group names when they are provided in the +archive, or looks up the user and group names in the system +password database. +.TP +\fB\-Fl\fP no-preserve-owner +(i mode only) +Do not attempt to restore file ownership. +This is the default when run by non-root users. +.TP +\fB\-O\fP \fIfile\fP +Write archive to +\fIfile\fP. +.TP +\fB\-o\fP, \fB\-Fl\fP create +Output mode. +See above for description. +.TP +\fB\-p\fP, \fB\-Fl\fP pass-through +Pass-through mode. +See above for description. +.TP +\fB\-Fl\fP preserve-owner +(i mode only) +Restore file ownership. +This is the default when run by the root user. +.TP +\fB\-Fl\fP quiet +Suppress unnecessary messages. +.TP +\fB\-R\fP [user] [:] [group], \fB\-Fl\fP owner [user] [:] [group] +Set the owner and/or group on files in the output. +If group is specified with no user +(for example, +\fB\-R\fP \fI:wheel\fP) +then the group will be set but not the user. +If the user is specified with a trailing colon and no group +(for example, +\fB\-R\fP \fIroot:\fP) +then the group will be set to the user's default group. +If the user is specified with no trailing colon, then +the user will be set but not the group. +In +\fB\-i\fP +and +\fB\-p\fP +modes, this option can only be used by the super-user. +(For compatibility, a period can be used in place of the colon.) +.TP +\fB\-r\fP +(All modes.) +Rename files interactively. +For each file, a prompt is written to +\fI/dev/tty\fP +containing the name of the file and a line is read from +\fI/dev/tty\fP. +If the line read is blank, the file is skipped. +If the line contains a single period, the file is processed normally. +Otherwise, the line is taken to be the new name of the file. +.TP +\fB\-t\fP, \fB\-Fl\fP list +(i mode only) +List the contents of the archive to stdout; +do not restore the contents to disk. +.TP +\fB\-u\fP, \fB\-Fl\fP unconditional +(i and p modes) +Unconditionally overwrite existing files. +Ordinarily, an older file will not overwrite a newer file on disk. +.TP +\fB\-V\fP, \fB\-Fl\fP dot +Print a dot to stderr for each file as it is processed. +Superseded by +\fB\-v\fP. +.TP +\fB\-v\fP, \fB\-Fl\fP verbose +Print the name of each file to stderr as it is processed. +With +\fB\-t\fP, +provide a detailed listing of each file. +.TP +\fB\-Fl\fP version +Print the program version information and exit. +.TP +\fB\-y\fP +(o mode only) +Compress the archive with bzip2-compatible compression before writing it. +In input mode, this option is ignored; +bzip2 compression is recognized automatically on input. +.TP +\fB\-Z\fP +(o mode only) +Compress the archive with compress-compatible compression before writing it. +In input mode, this option is ignored; +compression is recognized automatically on input. +.TP +\fB\-z\fP +(o mode only) +Compress the archive with gzip-compatible compression before writing it. +In input mode, this option is ignored; +gzip compression is recognized automatically on input. +.RE +.SH EXIT STATUS +.ad l +The \fBcpio\fP utility exits 0 on success, and >0 if an error occurs. +.SH ENVIRONMENT +.ad l +The following environment variables affect the execution of +\fB\%cpio\fP: +.RS 5 +.TP +.B LANG +The locale to use. +See +\fBenviron\fP(7) +for more information. +.TP +.B TZ +The timezone to use when displaying dates. +See +\fBenviron\fP(7) +for more information. +.RE +.SH EXAMPLES +.ad l +The +\fB\%cpio\fP +command is traditionally used to copy file hierarchies in conjunction +with the +\fBfind\fP(1) +command. +The first example here simply copies all files from +\fIsrc\fP +to +\fIdest\fP: +.RS 4 +\fB\%find\fP \fIsrc\fP | \fB\%cpio\fP \fB\-pmud\fP \fIdest\fP +.RE +.PP +By carefully selecting options to the +\fBfind\fP(1) +command and combining it with other standard utilities, +it is possible to exercise very fine control over which files are copied. +This next example copies files from +\fIsrc\fP +to +\fIdest\fP +that are more than 2 days old and whose names match a particular pattern: +.RS 4 +\fB\%find\fP \fIsrc\fP \fB\-mtime\fP \fI+2\fP | \fB\%grep\fP foo[bar] | \fB\%cpio\fP \fB\-pdmu\fP \fIdest\fP +.RE +.PP +This example copies files from +\fIsrc\fP +to +\fIdest\fP +that are more than 2 days old and which contain the word +``foobar'': +.RS 4 +\fB\%find\fP \fIsrc\fP \fB\-mtime\fP \fI+2\fP | \fB\%xargs\fP \fB\%grep\fP -l foobar | \fB\%cpio\fP \fB\-pdmu\fP \fIdest\fP +.RE +.SH COMPATIBILITY +.ad l +The mode options i, o, and p and the options +a, B, c, d, f, l, m, r, t, u, and v comply with SUSv2. +.PP +The old POSIX.1 standard specified that only +\fB\-i\fP, +\fB\-o\fP, +and +\fB\-p\fP +were interpreted as command-line options. +Each took a single argument of a list of modifier +characters. +For example, the standard syntax allows +\fB\-imu\fP +but does not support +\fB\-miu\fP +or +\fB\-i\fP \fB\-m\fP \fB\-u\fP, +since +\fIm\fP +and +\fIu\fP +are only modifiers to +\fB\-i\fP, +they are not command-line options in their own right. +The syntax supported by this implementation is backwards-compatible +with the standard. +For best compatibility, scripts should limit themselves to the +standard syntax. +.SH SEE ALSO +.ad l +\fBbzip2\fP(1), +\fBgzip\fP(1), +\fBmt\fP(1), +\fBpax\fP(1), +\fBtar\fP(1), +\fBlibarchive\fP(3), +\fBcpio\fP(5), +\fBlibarchive-formats\fP(5), +\fBtar\fP(5) +.SH STANDARDS +.ad l +There is no current POSIX standard for the cpio command; it appeared +in +ISO/IEC 9945-1:1996 (``POSIX.1'') +but was dropped from +IEEE Std 1003.1-2001 (``POSIX.1''). +.PP +The cpio, ustar, and pax interchange file formats are defined by +IEEE Std 1003.1-2001 (``POSIX.1'') +for the pax command. +.SH HISTORY +.ad l +The original +\fB\%cpio\fP +and +\fB\%find\fP +utilities were written by Dick Haight +while working in AT&T's Unix Support Group. +They first appeared in 1977 in PWB/UNIX 1.0, the +``Programmer's Work Bench'' +system developed for use within AT&T. +They were first released outside of AT&T as part of System III Unix in 1981. +As a result, +\fB\%cpio\fP +actually predates +\fB\%tar\fP, +even though it was not well-known outside of AT&T until some time later. +.PP +This is a complete re-implementation based on the +\fBlibarchive\fP(3) +library. +.SH BUGS +.ad l +The cpio archive format has several basic limitations: +It does not store user and group names, only numbers. +As a result, it cannot be reliably used to transfer +files between systems with dissimilar user and group numbering. +Older cpio formats limit the user and group numbers to +16 or 18 bits, which is insufficient for modern systems. +The cpio archive formats cannot support files over 4 gigabytes, +except for the +``odc'' +variant, which can support files up to 8 gigabytes. diff --git a/dependencies/libarchive-3.4.2/doc/man/bsdtar.1 b/dependencies/libarchive-3.4.2/doc/man/bsdtar.1 new file mode 100644 index 0000000..1a7d9db --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/bsdtar.1 @@ -0,0 +1,1473 @@ +.TH TAR 1 "January 31, 2020" "" +.SH NAME +.ad l +\fB\%tar\fP +\- manipulate tape archives +.SH SYNOPSIS +.ad l +.br +\fB\%tar\fP +[\fIbundled-flags\fP ] +[<\fIfile\fP> | <\fIpattern\fP> ...] +.br +\fB\%tar\fP +{\fB\-c\fP} +[\fIoptions\fP] +[\fIfiles\fP | \fIdirectories\fP] +.br +\fB\%tar\fP +{\fB\-r\fP | \fB\-u\fP} +\fB\-f\fP \fIarchive-file\fP +[\fIoptions\fP] +[\fIfiles\fP | \fIdirectories\fP] +.br +\fB\%tar\fP +{\fB\-t\fP | \fB\-x\fP} +[\fIoptions\fP] +[\fIpatterns\fP] +.SH DESCRIPTION +.ad l +\fB\%tar\fP +creates and manipulates streaming archive files. +This implementation can extract from tar, pax, cpio, zip, jar, ar, xar, +rpm, 7-zip, and ISO 9660 cdrom images and can create tar, pax, cpio, ar, zip, +7-zip, and shar archives. +.PP +The first synopsis form shows a +``bundled'' +option word. +This usage is provided for compatibility with historical implementations. +See COMPATIBILITY below for details. +.PP +The other synopsis forms show the preferred usage. +The first option to +\fB\%tar\fP +is a mode indicator from the following list: +.RS 5 +.TP +\fB\-c\fP +Create a new archive containing the specified items. +The long option form is +\fB\-Fl\fP create. +.TP +\fB\-r\fP +Like +\fB\-c\fP, +but new entries are appended to the archive. +Note that this only works on uncompressed archives stored in regular files. +The +\fB\-f\fP +option is required. +The long option form is +\fB\-Fl\fP append. +.TP +\fB\-t\fP +List archive contents to stdout. +The long option form is +\fB\-Fl\fP list. +.TP +\fB\-u\fP +Like +\fB\-r\fP, +but new entries are added only if they have a modification date +newer than the corresponding entry in the archive. +Note that this only works on uncompressed archives stored in regular files. +The +\fB\-f\fP +option is required. +The long form is +\fB\-Fl\fP update. +.TP +\fB\-x\fP +Extract to disk from the archive. +If a file with the same name appears more than once in the archive, +each copy will be extracted, with later copies overwriting (replacing) +earlier copies. +The long option form is +\fB\-Fl\fP extract. +.RE +.PP +In +\fB\-c\fP, +\fB\-r\fP, +or +\fB\-u\fP +mode, each specified file or directory is added to the +archive in the order specified on the command line. +By default, the contents of each directory are also archived. +.PP +In extract or list mode, the entire command line +is read and parsed before the archive is opened. +The pathnames or patterns on the command line indicate +which items in the archive should be processed. +Patterns are shell-style globbing patterns as +documented in +\fBtcsh\fP(1). +.SH OPTIONS +.ad l +Unless specifically stated otherwise, options are applicable in +all operating modes. +.RS 5 +.TP +\fB@\fP \fIarchive\fP +(c and r modes only) +The specified archive is opened and the entries +in it will be appended to the current archive. +As a simple example, +.RS 4 +\fB\%tar\fP \fB\-c\fP \fB\-f\fP \fI-\fP \fInewfile\fP \fB@\fP \fIoriginal.tar\fP +.RE +writes a new archive to standard output containing a file +\fInewfile\fP +and all of the entries from +\fIoriginal.tar\fP. +In contrast, +.RS 4 +\fB\%tar\fP \fB\-c\fP \fB\-f\fP \fI-\fP \fInewfile\fP \fIoriginal.tar\fP +.RE +creates a new archive with only two entries. +Similarly, +.RS 4 +\fB\%tar\fP \fB\-czf\fP \fI-\fP \fB\-Fl\fP format \fBpax\fP \fB@\fP \fI-\fP +.RE +reads an archive from standard input (whose format will be determined +automatically) and converts it into a gzip-compressed +pax-format archive on stdout. +In this way, +\fB\%tar\fP +can be used to convert archives from one format to another. +.TP +\fB\-a\fP, \fB\-Fl\fP auto-compress +(c mode only) +Use the archive suffix to decide a set of the format and +the compressions. +As a simple example, +.RS 4 +\fB\%tar\fP \fB\-a\fP \fB\-cf\fP \fIarchive.tgz\fP source.c source.h +.RE +creates a new archive with restricted pax format and gzip compression, +.RS 4 +\fB\%tar\fP \fB\-a\fP \fB\-cf\fP \fIarchive.tar.bz2.uu\fP source.c source.h +.RE +creates a new archive with restricted pax format and bzip2 compression +and uuencode compression, +.RS 4 +\fB\%tar\fP \fB\-a\fP \fB\-cf\fP \fIarchive.zip\fP source.c source.h +.RE +creates a new archive with zip format, +.RS 4 +\fB\%tar\fP \fB\-a\fP \fB\-jcf\fP \fIarchive.tgz\fP source.c source.h +.RE +ignores the +``-j'' +option, and creates a new archive with restricted pax format +and gzip compression, +.RS 4 +\fB\%tar\fP \fB\-a\fP \fB\-jcf\fP \fIarchive.xxx\fP source.c source.h +.RE +if it is unknown suffix or no suffix, creates a new archive with +restricted pax format and bzip2 compression. +.TP +\fB\-Fl\fP acls +(c, r, u, x modes only) +Archive or extract POSIX.1e or NFSv4 ACLs. +This is the reverse of +\fB\-Fl\fP no-acls +and the default behavior in c, r, and u modes (except on Mac OS X) or if +\fB\%tar\fP +is run in x mode as root. +On Mac OS X this option translates extended ACLs to NFSv4 ACLs. +To store extended ACLs the +\fB\-Fl\fP mac-metadata +option is preferred. +.TP +\fB\-B\fP, \fB\-Fl\fP read-full-blocks +Ignored for compatibility with other +\fBtar\fP(1) +implementations. +.TP +\fB\-b\fP \fIblocksize\fP, \fB\-Fl\fP block-size \fIblocksize\fP +Specify the block size, in 512-byte records, for tape drive I/O. +As a rule, this argument is only needed when reading from or writing +to tape drives, and usually not even then as the default block size of +20 records (10240 bytes) is very common. +.TP +\fB\-C\fP \fIdirectory\fP, \fB\-Fl\fP cd \fIdirectory\fP, \fB\-Fl\fP directory \fIdirectory\fP +In c and r mode, this changes the directory before adding +the following files. +In x mode, change directories after opening the archive +but before extracting entries from the archive. +.TP +\fB\-Fl\fP chroot +(x mode only) +\fB\%chroot\fP() +to the current directory after processing any +\fB\-C\fP +options and before extracting any files. +.TP +\fB\-Fl\fP clear-nochange-fflags +(x mode only) +Before removing file system objects to replace them, clear platform-specific +file attributes or file flags that might prevent removal. +.TP +\fB\-Fl\fP exclude \fIpattern\fP +Do not process files or directories that match the +specified pattern. +Note that exclusions take precedence over patterns or filenames +specified on the command line. +.TP +\fB\-Fl\fP exclude-vcs +Do not process files or directories internally used by the +version control systems +Sq Arch, +Sq Bazaar, +Sq CVS, +Sq Darcs, +Sq Mercurial, +Sq RCS, +Sq SCCS, +Sq SVN +and +Sq git. +.TP +\fB\-Fl\fP fflags +(c, r, u, x modes only) +Archive or extract platform-specific file attributes or file flags. +This is the reverse of +\fB\-Fl\fP no-fflags +and the default behavior in c, r, and u modes or if +\fB\%tar\fP +is run in x mode as root. +.TP +\fB\-Fl\fP format \fIformat\fP +(c, r, u mode only) +Use the specified format for the created archive. +Supported formats include +``cpio'', +``pax'', +``shar'', +and +``ustar''. +Other formats may also be supported; see +\fBlibarchive-formats\fP(5) +for more information about currently-supported formats. +In r and u modes, when extending an existing archive, the format specified +here must be compatible with the format of the existing archive on disk. +.TP +\fB\-f\fP \fIfile\fP, \fB\-Fl\fP file \fIfile\fP +Read the archive from or write the archive to the specified file. +The filename can be +\fI-\fP +for standard input or standard output. +The default varies by system; +on +FreeBSD, +the default is +\fI/dev/sa0\fP; +on Linux, the default is +\fI/dev/st0\fP. +.TP +\fB\-Fl\fP gid \fIid\fP +Use the provided group id number. +On extract, this overrides the group id in the archive; +the group name in the archive will be ignored. +On create, this overrides the group id read from disk; +if +\fB\-Fl\fP gname +is not also specified, the group name will be set to +match the group id. +.TP +\fB\-Fl\fP gname \fIname\fP +Use the provided group name. +On extract, this overrides the group name in the archive; +if the provided group name does not exist on the system, +the group id +(from the archive or from the +\fB\-Fl\fP gid +option) +will be used instead. +On create, this sets the group name that will be stored +in the archive; +the name will not be verified against the system group database. +.TP +\fB\-H\fP +(c and r modes only) +Symbolic links named on the command line will be followed; the +target of the link will be archived, not the link itself. +.TP +\fB\-h\fP +(c and r modes only) +Synonym for +\fB\-L\fP. +.TP +\fB\-I\fP +Synonym for +\fB\-T\fP. +.TP +\fB\-Fl\fP help +Show usage. +.TP +\fB\-Fl\fP hfsCompression +(x mode only) +Mac OS X specific (v10.6 or later). Compress extracted regular files with HFS+ +compression. +.TP +\fB\-Fl\fP ignore-zeros +An alias of +\fB\-Fl\fP options \fBread_concatenated_archives\fP +for compatibility with GNU tar. +.TP +\fB\-Fl\fP include \fIpattern\fP +Process only files or directories that match the specified pattern. +Note that exclusions specified with +\fB\-Fl\fP exclude +take precedence over inclusions. +If no inclusions are explicitly specified, all entries are processed by +default. +The +\fB\-Fl\fP include +option is especially useful when filtering archives. +For example, the command +.RS 4 +\fB\%tar\fP \fB\-c\fP \fB\-f\fP \fInew.tar\fP \fB\-Fl\fP include='*foo*' \fB@\fP \fIold.tgz\fP +.RE +creates a new archive +\fInew.tar\fP +containing only the entries from +\fIold.tgz\fP +containing the string +Sq foo. +.TP +\fB\-J\fP, \fB\-Fl\fP xz +(c mode only) +Compress the resulting archive with +\fBxz\fP(1). +In extract or list modes, this option is ignored. +Note that this +\fB\%tar\fP +implementation recognizes XZ compression automatically when reading archives. +.TP +\fB\-j\fP, \fB\-Fl\fP bzip, \fB\-Fl\fP bzip2, \fB\-Fl\fP bunzip2 +(c mode only) +Compress the resulting archive with +\fBbzip2\fP(1). +In extract or list modes, this option is ignored. +Note that this +\fB\%tar\fP +implementation recognizes bzip2 compression automatically when reading +archives. +.TP +\fB\-k\fP, \fB\-Fl\fP keep-old-files +(x mode only) +Do not overwrite existing files. +In particular, if a file appears more than once in an archive, +later copies will not overwrite earlier copies. +.TP +\fB\-Fl\fP keep-newer-files +(x mode only) +Do not overwrite existing files that are newer than the +versions appearing in the archive being extracted. +.TP +\fB\-L\fP, \fB\-Fl\fP dereference +(c and r modes only) +All symbolic links will be followed. +Normally, symbolic links are archived as such. +With this option, the target of the link will be archived instead. +.TP +\fB\-l\fP, \fB\-Fl\fP check-links +(c and r modes only) +Issue a warning message unless all links to each file are archived. +.TP +\fB\-Fl\fP lrzip +(c mode only) +Compress the resulting archive with +\fBlrzip\fP(1). +In extract or list modes, this option is ignored. +Note that this +\fB\%tar\fP +implementation recognizes lrzip compression automatically when reading +archives. +.TP +\fB\-Fl\fP lz4 +(c mode only) +Compress the archive with lz4-compatible compression before writing it. +In extract or list modes, this option is ignored. +Note that this +\fB\%tar\fP +implementation recognizes lz4 compression automatically when reading archives. +.TP +\fB\-Fl\fP zstd +(c mode only) +Compress the archive with zstd-compatible compression before writing it. +In extract or list modes, this option is ignored. +Note that this +\fB\%tar\fP +implementation recognizes zstd compression automatically when reading archives. +.TP +\fB\-Fl\fP lzma +(c mode only) Compress the resulting archive with the original LZMA algorithm. +In extract or list modes, this option is ignored. +Use of this option is discouraged and new archives should be created with +\fB\-Fl\fP xz +instead. +Note that this +\fB\%tar\fP +implementation recognizes LZMA compression automatically when reading archives. +.TP +\fB\-Fl\fP lzop +(c mode only) +Compress the resulting archive with +\fBlzop\fP(1). +In extract or list modes, this option is ignored. +Note that this +\fB\%tar\fP +implementation recognizes LZO compression automatically when reading archives. +.TP +\fB\-m\fP, \fB\-Fl\fP modification-time +(x mode only) +Do not extract modification time. +By default, the modification time is set to the time stored in the archive. +.TP +\fB\-Fl\fP mac-metadata +(c, r, u and x mode only) +Mac OS X specific. +Archive or extract extended ACLs and extended file +attributes using +\fBcopyfile\fP(3) +in AppleDouble format. +This is the reverse of +\fB\-Fl\fP no-mac-metadata. +and the default behavior in c, r, and u modes or if +\fB\%tar\fP +is run in x mode as root. +.TP +\fB\-n\fP, \fB\-Fl\fP norecurse, \fB\-Fl\fP no-recursion +Do not operate recursively on the content of directories. +.TP +\fB\-Fl\fP newer \fIdate\fP +(c, r, u modes only) +Only include files and directories newer than the specified date. +This compares ctime entries. +.TP +\fB\-Fl\fP newer-mtime \fIdate\fP +(c, r, u modes only) +Like +\fB\-Fl\fP newer, +except it compares mtime entries instead of ctime entries. +.TP +\fB\-Fl\fP newer-than \fIfile\fP +(c, r, u modes only) +Only include files and directories newer than the specified file. +This compares ctime entries. +.TP +\fB\-Fl\fP newer-mtime-than \fIfile\fP +(c, r, u modes only) +Like +\fB\-Fl\fP newer-than, +except it compares mtime entries instead of ctime entries. +.TP +\fB\-Fl\fP nodump +(c and r modes only) +Honor the nodump file flag by skipping this file. +.TP +\fB\-Fl\fP nopreserveHFSCompression +(x mode only) +Mac OS X specific (v10.6 or later). Do not compress extracted regular files +which were compressed with HFS+ compression before archived. +By default, compress the regular files again with HFS+ compression. +.TP +\fB\-Fl\fP null +(use with +\fB\-I\fP +or +\fB\-T\fP) +Filenames or patterns are separated by null characters, +not by newlines. +This is often used to read filenames output by the +\fB\-print0\fP +option to +\fBfind\fP(1). +.TP +\fB\-Fl\fP no-acls +(c, r, u, x modes only) +Do not archive or extract POSIX.1e or NFSv4 ACLs. +This is the reverse of +\fB\-Fl\fP acls +and the default behavior if +\fB\%tar\fP +is run as non-root in x mode (on Mac OS X as any user in c, r, u and x modes). +.TP +\fB\-Fl\fP no-fflags +(c, r, u, x modes only) +Do not archive or extract file attributes or file flags. +This is the reverse of +\fB\-Fl\fP fflags +and the default behavior if +\fB\%tar\fP +is run as non-root in x mode. +.TP +\fB\-Fl\fP no-mac-metadata +(x mode only) +Mac OS X specific. +Do not archive or extract ACLs and extended file attributes +using +\fBcopyfile\fP(3) +in AppleDouble format. +This is the reverse of +\fB\-Fl\fP mac-metadata. +and the default behavior if +\fB\%tar\fP +is run as non-root in x mode. +.TP +\fB\-Fl\fP no-safe-writes +(x mode only) +Do not create temporary files and use +\fBrename\fP(2) +to replace the original ones. +This is the reverse of +\fB\-Fl\fP safe-writes. +.TP +\fB\-Fl\fP no-same-owner +(x mode only) +Do not extract owner and group IDs. +This is the reverse of +\fB\-Fl\fP same-owner +and the default behavior if +\fB\%tar\fP +is run as non-root. +.TP +\fB\-Fl\fP no-same-permissions +(x mode only) +Do not extract full permissions (SGID, SUID, sticky bit, +file attributes or file flags, extended file attributes and ACLs). +This is the reverse of +\fB\-p\fP +and the default behavior if +\fB\%tar\fP +is run as non-root. +.TP +\fB\-Fl\fP no-xattrs +(c, r, u, x modes only) +Do not archive or extract extended file attributes. +This is the reverse of +\fB\-Fl\fP xattrs +and the default behavior if +\fB\%tar\fP +is run as non-root in x mode. +.TP +\fB\-Fl\fP numeric-owner +This is equivalent to +\fB\-Fl\fP uname +Qq +\fB\-Fl\fP gname +Qq. +On extract, it causes user and group names in the archive +to be ignored in favor of the numeric user and group ids. +On create, it causes user and group names to not be stored +in the archive. +.TP +\fB\-O\fP, \fB\-Fl\fP to-stdout +(x, t modes only) +In extract (-x) mode, files will be written to standard out rather than +being extracted to disk. +In list (-t) mode, the file listing will be written to stderr rather than +the usual stdout. +.TP +\fB\-o\fP +(x mode) +Use the user and group of the user running the program rather +than those specified in the archive. +Note that this has no significance unless +\fB\-p\fP +is specified, and the program is being run by the root user. +In this case, the file modes and flags from +the archive will be restored, but ACLs or owner information in +the archive will be discarded. +.TP +\fB\-o\fP +(c, r, u mode) +A synonym for +\fB\-Fl\fP format \fIustar\fP +.TP +\fB\-Fl\fP older \fIdate\fP +(c, r, u modes only) +Only include files and directories older than the specified date. +This compares ctime entries. +.TP +\fB\-Fl\fP older-mtime \fIdate\fP +(c, r, u modes only) +Like +\fB\-Fl\fP older, +except it compares mtime entries instead of ctime entries. +.TP +\fB\-Fl\fP older-than \fIfile\fP +(c, r, u modes only) +Only include files and directories older than the specified file. +This compares ctime entries. +.TP +\fB\-Fl\fP older-mtime-than \fIfile\fP +(c, r, u modes only) +Like +\fB\-Fl\fP older-than, +except it compares mtime entries instead of ctime entries. +.TP +\fB\-Fl\fP one-file-system +(c, r, and u modes) +Do not cross mount points. +.TP +\fB\-Fl\fP options \fIoptions\fP +Select optional behaviors for particular modules. +The argument is a text string containing comma-separated +keywords and values. +These are passed to the modules that handle particular +formats to control how those formats will behave. +Each option has one of the following forms: +.RS 5 +.TP +\fIkey=value\fP +The key will be set to the specified value in every module that supports it. +Modules that do not support this key will ignore it. +.TP +\fIkey\fP +The key will be enabled in every module that supports it. +This is equivalent to +\fIkey\fP \fB=1\fP. +.TP +\fI!key\fP +The key will be disabled in every module that supports it. +.TP +\fImodule:key=value\fP, \fImodule:key\fP, \fImodule:!key\fP +As above, but the corresponding key and value will be provided +only to modules whose name matches +\fImodule\fP. +.RE +.PP +The complete list of supported modules and keys +for create and append modes is in +\fBarchive_write_set_options\fP(3) +and for extract and list modes in +\fBarchive_read_set_options\fP(3). +.PP +Examples of supported options: +.RS 5 +.TP +\fBiso9660:joliet\fP +Support Joliet extensions. +This is enabled by default, use +\fB!joliet\fP +or +\fBiso9660:!joliet\fP +to disable. +.TP +\fBiso9660:rockridge\fP +Support Rock Ridge extensions. +This is enabled by default, use +\fB!rockridge\fP +or +\fBiso9660:!rockridge\fP +to disable. +.TP +\fBgzip:compression-level\fP +A decimal integer from 1 to 9 specifying the gzip compression level. +.TP +\fBgzip:timestamp\fP +Store timestamp. +This is enabled by default, use +\fB!timestamp\fP +or +\fBgzip:!timestamp\fP +to disable. +.TP +\fBlrzip:compression\fP=\fItype\fP +Use +\fItype\fP +as compression method. +Supported values are bzip2, gzip, lzo (ultra fast), +and zpaq (best, extremely slow). +.TP +\fBlrzip:compression-level\fP +A decimal integer from 1 to 9 specifying the lrzip compression level. +.TP +\fBlz4:compression-level\fP +A decimal integer from 1 to 9 specifying the lzop compression level. +.TP +\fBlz4:stream-checksum\fP +Enable stream checksum. +This is by default, use +\fBlz4:!stream-checksum\fP +to disable. +.TP +\fBlz4:block-checksum\fP +Enable block checksum (Disabled by default). +.TP +\fBlz4:block-size\fP +A decimal integer from 4 to 7 specifying the lz4 compression block size +(7 is set by default). +.TP +\fBlz4:block-dependence\fP +Use the previous block of the block being compressed for +a compression dictionary to improve compression ratio. +.TP +\fBzstd:compression-level\fP +A decimal integer from 1 to 22 specifying the zstd compression level. +.TP +\fBlzop:compression-level\fP +A decimal integer from 1 to 9 specifying the lzop compression level. +.TP +\fBxz:compression-level\fP +A decimal integer from 0 to 9 specifying the xz compression level. +.TP +\fBmtree:\fP \fIkeyword\fP +The mtree writer module allows you to specify which mtree keywords +will be included in the output. +Supported keywords include: +\fBcksum\fP, \fBdevice\fP, \fBflags\fP, \fBgid\fP, \fBgname\fP, \fBindent\fP, +\fBlink\fP, \fBmd5\fP, \fBmode\fP, \fBnlink\fP, \fBrmd160\fP, \fBsha1\fP, \fBsha256\fP, +\fBsha384\fP, \fBsha512\fP, \fBsize\fP, \fBtime\fP, \fBuid\fP, \fBuname\fP. +The default is equivalent to: +``device, flags, gid, gname, link, mode, nlink, size, time, type, uid, uname''. +.TP +\fBmtree:all\fP +Enables all of the above keywords. +You can also use +\fBmtree:!all\fP +to disable all keywords. +.TP +\fBmtree:use-set\fP +Enable generation of +\fB/set\fP +lines in the output. +.TP +\fBmtree:indent\fP +Produce human-readable output by indenting options and splitting lines +to fit into 80 columns. +.TP +\fBzip:compression\fP=\fItype\fP +Use +\fItype\fP +as compression method. +Supported values are store (uncompressed) and deflate (gzip algorithm). +.TP +\fBzip:encryption\fP +Enable encryption using traditional zip encryption. +.TP +\fBzip:encryption\fP=\fItype\fP +Use +\fItype\fP +as encryption type. +Supported values are zipcrypt (traditional zip encryption), +aes128 (WinZip AES-128 encryption) and aes256 (WinZip AES-256 encryption). +.TP +\fBread_concatenated_archives\fP +Ignore zeroed blocks in the archive, which occurs when multiple tar archives +have been concatenated together. +Without this option, only the contents of +the first concatenated archive would be read. +This option is comparable to the +\fB\-i\fP, \fB\-Fl\fP ignore-zeros +option of GNU tar. +.RE +If a provided option is not supported by any module, that +is a fatal error. +.TP +\fB\-P\fP, \fB\-Fl\fP absolute-paths +Preserve pathnames. +By default, absolute pathnames (those that begin with a / +character) have the leading slash removed both when creating archives +and extracting from them. +Also, +\fB\%tar\fP +will refuse to extract archive entries whose pathnames contain +\fI\& ..\fP +or whose target directory would be altered by a symlink. +This option suppresses these behaviors. +.TP +\fB\-p\fP, \fB\-Fl\fP insecure, \fB\-Fl\fP preserve-permissions +(x mode only) +Preserve file permissions. +Attempt to restore the full permissions, including file modes, file attributes +or file flags, extended file attributes and ACLs, if available, for each item +extracted from the archive. +This is the reverse of +\fB\-Fl\fP no-same-permissions +and the default if +\fB\%tar\fP +is being run as root. +It can be partially overridden by also specifying +\fB\-Fl\fP no-acls, +\fB\-Fl\fP no-fflags, +\fB\-Fl\fP no-mac-metadata +or +\fB\-Fl\fP no-xattrs. +.TP +\fB\-Fl\fP passphrase \fIpassphrase\fP +The +\fIpassphrase\fP +is used to extract or create an encrypted archive. +Currently, zip is the only supported format that supports encryption. +You shouldn't use this option unless you realize how insecure +use of this option is. +.TP +\fB\-Fl\fP posix +(c, r, u mode only) +Synonym for +\fB\-Fl\fP format \fIpax\fP +.TP +\fB\-q\fP, \fB\-Fl\fP fast-read +(x and t mode only) +Extract or list only the first archive entry that matches each pattern +or filename operand. +Exit as soon as each specified pattern or filename has been matched. +By default, the archive is always read to the very end, since +there can be multiple entries with the same name and, by convention, +later entries overwrite earlier entries. +This option is provided as a performance optimization. +.TP +\fB\-S\fP +(x mode only) +Extract files as sparse files. +For every block on disk, check first if it contains only NULL bytes and seek +over it otherwise. +This works similar to the conv=sparse option of dd. +.TP +\fB\-s\fP \fIpattern\fP +Modify file or archive member names according to +\fIpattern\fP. +The pattern has the format +\fI/old/new/\fP [ghHprRsS] +where +\fIold\fP +is a basic regular expression, +\fInew\fP +is the replacement string of the matched part, +and the optional trailing letters modify +how the replacement is handled. +If +\fIold\fP +is not matched, the pattern is skipped. +Within +\fInew\fP, +~ is substituted with the match, \e1 to \e9 with the content of +the corresponding captured group. +The optional trailing g specifies that matching should continue +after the matched part and stop on the first unmatched pattern. +The optional trailing s specifies that the pattern applies to the value +of symbolic links. +The optional trailing p specifies that after a successful substitution +the original path name and the new path name should be printed to +standard error. +Optional trailing H, R, or S characters suppress substitutions +for hardlink targets, regular filenames, or symlink targets, +respectively. +Optional trailing h, r, or s characters enable substitutions +for hardlink targets, regular filenames, or symlink targets, +respectively. +The default is +\fIhrs\fP +which applies substitutions to all names. +In particular, it is never necessary to specify h, r, or s. +.TP +\fB\-Fl\fP safe-writes +(x mode only) +Extract files atomically. +By default +\fB\%tar\fP +unlinks the original file with the same name as the extracted file (if it +exists), and then creates it immediately under the same name and writes to +it. +For a short period of time, applications trying to access the file might +not find it, or see incomplete results. +If +\fB\-Fl\fP safe-writes +is enabled, +\fB\%tar\fP +first creates a unique temporary file, then writes the new contents to +the temporary file, and finally renames the temporary file to its final +name atomically using +\fBrename\fP(2). +This guarantees that an application accessing the file, will either see +the old contents or the new contents at all times. +.TP +\fB\-Fl\fP same-owner +(x mode only) +Extract owner and group IDs. +This is the reverse of +\fB\-Fl\fP no-same-owner +and the default behavior if +\fB\%tar\fP +is run as root. +.TP +\fB\-Fl\fP strip-components \fIcount\fP +Remove the specified number of leading path elements. +Pathnames with fewer elements will be silently skipped. +Note that the pathname is edited after checking inclusion/exclusion patterns +but before security checks. +.TP +\fB\-T\fP \fIfilename\fP, \fB\-Fl\fP files-from \fIfilename\fP +In x or t mode, +\fB\%tar\fP +will read the list of names to be extracted from +\fIfilename\fP. +In c mode, +\fB\%tar\fP +will read names to be archived from +\fIfilename\fP. +The special name +``-C'' +on a line by itself will cause the current directory to be changed to +the directory specified on the following line. +Names are terminated by newlines unless +\fB\-Fl\fP null +is specified. +Note that +\fB\-Fl\fP null +also disables the special handling of lines containing +``-C''. +Note: If you are generating lists of files using +\fBfind\fP(1), +you probably want to use +\fB\-n\fP +as well. +.TP +\fB\-Fl\fP totals +(c, r, u modes only) +After archiving all files, print a summary to stderr. +.TP +\fB\-U\fP, \fB\-Fl\fP unlink, \fB\-Fl\fP unlink-first +(x mode only) +Unlink files before creating them. +This can be a minor performance optimization if most files +already exist, but can make things slower if most files +do not already exist. +This flag also causes +\fB\%tar\fP +to remove intervening directory symlinks instead of +reporting an error. +See the SECURITY section below for more details. +.TP +\fB\-Fl\fP uid \fIid\fP +Use the provided user id number and ignore the user +name from the archive. +On create, if +\fB\-Fl\fP uname +is not also specified, the user name will be set to +match the user id. +.TP +\fB\-Fl\fP uname \fIname\fP +Use the provided user name. +On extract, this overrides the user name in the archive; +if the provided user name does not exist on the system, +it will be ignored and the user id +(from the archive or from the +\fB\-Fl\fP uid +option) +will be used instead. +On create, this sets the user name that will be stored +in the archive; +the name is not verified against the system user database. +.TP +\fB\-Fl\fP use-compress-program \fIprogram\fP +Pipe the input (in x or t mode) or the output (in c mode) through +\fIprogram\fP +instead of using the builtin compression support. +.TP +\fB\-v\fP, \fB\-Fl\fP verbose +Produce verbose output. +In create and extract modes, +\fB\%tar\fP +will list each file name as it is read from or written to +the archive. +In list mode, +\fB\%tar\fP +will produce output similar to that of +\fBls\fP(1). +An additional +\fB\-v\fP +option will also provide ls-like details in create and extract mode. +.TP +\fB\-Fl\fP version +Print version of +\fB\%tar\fP +and +\fB\%libarchive\fP, +and exit. +.TP +\fB\-w\fP, \fB\-Fl\fP confirmation, \fB\-Fl\fP interactive +Ask for confirmation for every action. +.TP +\fB\-X\fP \fIfilename\fP, \fB\-Fl\fP exclude-from \fIfilename\fP +Read a list of exclusion patterns from the specified file. +See +\fB\-Fl\fP exclude +for more information about the handling of exclusions. +.TP +\fB\-Fl\fP xattrs +(c, r, u, x modes only) +Archive or extract extended file attributes. +This is the reverse of +\fB\-Fl\fP no-xattrs +and the default behavior in c, r, and u modes or if +\fB\%tar\fP +is run in x mode as root. +.TP +\fB\-y\fP +(c mode only) +Compress the resulting archive with +\fBbzip2\fP(1). +In extract or list modes, this option is ignored. +Note that this +\fB\%tar\fP +implementation recognizes bzip2 compression automatically when reading +archives. +.TP +\fB\-Z\fP, \fB\-Fl\fP compress, \fB\-Fl\fP uncompress +(c mode only) +Compress the resulting archive with +\fBcompress\fP(1). +In extract or list modes, this option is ignored. +Note that this +\fB\%tar\fP +implementation recognizes compress compression automatically when reading +archives. +.TP +\fB\-z\fP, \fB\-Fl\fP gunzip, \fB\-Fl\fP gzip +(c mode only) +Compress the resulting archive with +\fBgzip\fP(1). +In extract or list modes, this option is ignored. +Note that this +\fB\%tar\fP +implementation recognizes gzip compression automatically when reading +archives. +.RE +.SH ENVIRONMENT +.ad l +The following environment variables affect the execution of +\fB\%tar\fP: +.RS 5 +.TP +.B TAR_READER_OPTIONS +The default options for format readers and compression readers. +The +\fB\-Fl\fP options +option overrides this. +.TP +.B TAR_WRITER_OPTIONS +The default options for format writers and compression writers. +The +\fB\-Fl\fP options +option overrides this. +.TP +.B LANG +The locale to use. +See +\fBenviron\fP(7) +for more information. +.TP +.B TAPE +The default device. +The +\fB\-f\fP +option overrides this. +Please see the description of the +\fB\-f\fP +option above for more details. +.TP +.B TZ +The timezone to use when displaying dates. +See +\fBenviron\fP(7) +for more information. +.RE +.SH EXIT STATUS +.ad l +The \fBtar\fP utility exits 0 on success, and >0 if an error occurs. +.SH EXAMPLES +.ad l +The following creates a new archive +called +\fIfile.tar.gz\fP +that contains two files +\fIsource.c\fP +and +\fIsource.h\fP: +.RS 4 +\fB\%tar\fP \fB\-czf\fP \fIfile.tar.gz\fP \fIsource.c\fP \fIsource.h\fP +.RE +.PP +To view a detailed table of contents for this +archive: +.RS 4 +\fB\%tar\fP \fB\-tvf\fP \fIfile.tar.gz\fP +.RE +.PP +To extract all entries from the archive on +the default tape drive: +.RS 4 +\fB\%tar\fP \fB\-x\fP +.RE +.PP +To examine the contents of an ISO 9660 cdrom image: +.RS 4 +\fB\%tar\fP \fB\-tf\fP \fIimage.iso\fP +.RE +.PP +To move file hierarchies, invoke +\fB\%tar\fP +as +.RS 4 +\fB\%tar\fP \fB\-cf\fP \fI-\fP \fB\-C\fP \fIsrcdir\fP \&. | \fB\%tar\fP \fB\-xpf\fP \fI-\fP \fB\-C\fP \fIdestdir\fP +.RE +or more traditionally +.RS 4 +cd srcdir \&; \fB\%tar\fP \fB\-cf\fP \fI-\fP \&. | (cd destdir \&; \fB\%tar\fP \fB\-xpf\fP \fI-\fP) +.RE +.PP +In create mode, the list of files and directories to be archived +can also include directory change instructions of the form +\fB-C\fP \fIfoo/baz\fP +and archive inclusions of the form +\fB@\fP \fIarchive-file\fP. +For example, the command line +.RS 4 +\fB\%tar\fP \fB\-c\fP \fB\-f\fP \fInew.tar\fP \fIfoo1\fP \fB@\fP \fIold.tgz\fP \fB-C\fP \fI/tmp\fP \fIfoo2\fP +.RE +will create a new archive +\fInew.tar\fP. +\fB\%tar\fP +will read the file +\fIfoo1\fP +from the current directory and add it to the output archive. +It will then read each entry from +\fIold.tgz\fP +and add those entries to the output archive. +Finally, it will switch to the +\fI/tmp\fP +directory and add +\fIfoo2\fP +to the output archive. +.PP +An input file in +\fBmtree\fP(5) +format can be used to create an output archive with arbitrary ownership, +permissions, or names that differ from existing data on disk: +.RS 4 +.nf +$ cat input.mtree +#mtree +usr/bin uid=0 gid=0 mode=0755 type=dir +usr/bin/ls uid=0 gid=0 mode=0755 type=file content=myls +$ tar -cvf output.tar @input.mtree +.RE +.PP +The +\fB\-Fl\fP newer +and +\fB\-Fl\fP newer-mtime +switches accept a variety of common date and time specifications, including +``12 Mar 2005 7:14:29pm'', +``2005-03-12 19:14'', +``5 minutes ago'', +and +``19:14 PST May 1''. +.PP +The +\fB\-Fl\fP options +argument can be used to control various details of archive generation +or reading. +For example, you can generate mtree output which only contains +\fBtype\fP, \fBtime\fP, +and +\fBuid\fP +keywords: +.RS 4 +\fB\%tar\fP \fB\-cf\fP \fIfile.tar\fP \fB\-Fl\fP format=mtree \fB\-Fl\fP options='!all,type,time,uid' \fIdir\fP +.RE +or you can set the compression level used by gzip or xz compression: +.RS 4 +\fB\%tar\fP \fB\-czf\fP \fIfile.tar\fP \fB\-Fl\fP options='compression-level=9'. +.RE +For more details, see the explanation of the +\fB\%archive_read_set_options\fP() +and +\fB\%archive_write_set_options\fP() +API calls that are described in +\fBarchive_read\fP(3) +and +\fBarchive_write\fP(3). +.SH COMPATIBILITY +.ad l +The bundled-arguments format is supported for compatibility +with historic implementations. +It consists of an initial word (with no leading - character) in which +each character indicates an option. +Arguments follow as separate words. +The order of the arguments must match the order +of the corresponding characters in the bundled command word. +For example, +.RS 4 +\fB\%tar\fP \fBtbf\fP 32 \fIfile.tar\fP +.RE +specifies three flags +\fBt\fP, +\fBb\fP, +and +\fBf\fP. +The +\fBb\fP +and +\fBf\fP +flags both require arguments, +so there must be two additional items +on the command line. +The +\fI32\fP +is the argument to the +\fBb\fP +flag, and +\fIfile.tar\fP +is the argument to the +\fBf\fP +flag. +.PP +The mode options c, r, t, u, and x and the options +b, f, l, m, o, v, and w comply with SUSv2. +.PP +For maximum portability, scripts that invoke +\fB\%tar\fP +should use the bundled-argument format above, should limit +themselves to the +\fBc\fP, +\fBt\fP, +and +\fBx\fP +modes, and the +\fBb\fP, +\fBf\fP, +\fBm\fP, +\fBv\fP, +and +\fBw\fP +options. +.PP +Additional long options are provided to improve compatibility with other +tar implementations. +.SH SECURITY +.ad l +Certain security issues are common to many archiving programs, including +\fB\%tar\fP. +In particular, carefully-crafted archives can request that +\fB\%tar\fP +extract files to locations outside of the target directory. +This can potentially be used to cause unwitting users to overwrite +files they did not intend to overwrite. +If the archive is being extracted by the superuser, any file +on the system can potentially be overwritten. +There are three ways this can happen. +Although +\fB\%tar\fP +has mechanisms to protect against each one, +savvy users should be aware of the implications: +.RS 5 +.IP \(bu +Archive entries can have absolute pathnames. +By default, +\fB\%tar\fP +removes the leading +\fI/\fP +character from filenames before restoring them to guard against this problem. +.IP \(bu +Archive entries can have pathnames that include +\fI\& ..\fP +components. +By default, +\fB\%tar\fP +will not extract files containing +\fI\& ..\fP +components in their pathname. +.IP \(bu +Archive entries can exploit symbolic links to restore +files to other directories. +An archive can restore a symbolic link to another directory, +then use that link to restore a file into that directory. +To guard against this, +\fB\%tar\fP +checks each extracted path for symlinks. +If the final path element is a symlink, it will be removed +and replaced with the archive entry. +If +\fB\-U\fP +is specified, any intermediate symlink will also be unconditionally removed. +If neither +\fB\-U\fP +nor +\fB\-P\fP +is specified, +\fB\%tar\fP +will refuse to extract the entry. +.RE +To protect yourself, you should be wary of any archives that +come from untrusted sources. +You should examine the contents of an archive with +.RS 4 +\fB\%tar\fP \fB\-tf\fP \fIfilename\fP +.RE +before extraction. +You should use the +\fB\-k\fP +option to ensure that +\fB\%tar\fP +will not overwrite any existing files or the +\fB\-U\fP +option to remove any pre-existing files. +You should generally not extract archives while running with super-user +privileges. +Note that the +\fB\-P\fP +option to +\fB\%tar\fP +disables the security checks above and allows you to extract +an archive while preserving any absolute pathnames, +\fI\& ..\fP +components, or symlinks to other directories. +.SH SEE ALSO +.ad l +\fBbzip2\fP(1), +\fBcompress\fP(1), +\fBcpio\fP(1), +\fBgzip\fP(1), +\fBmt\fP(1), +\fBpax\fP(1), +\fBshar\fP(1), +\fBxz\fP(1), +\fBlibarchive\fP(3), +\fBlibarchive-formats\fP(5), +\fBtar\fP(5) +.SH STANDARDS +.ad l +There is no current POSIX standard for the tar command; it appeared +in +ISO/IEC 9945-1:1996 (``POSIX.1'') +but was dropped from +IEEE Std 1003.1-2001 (``POSIX.1''). +The options supported by this implementation were developed by surveying a +number of existing tar implementations as well as the old POSIX specification +for tar and the current POSIX specification for pax. +.PP +The ustar and pax interchange file formats are defined by +IEEE Std 1003.1-2001 (``POSIX.1'') +for the pax command. +.SH HISTORY +.ad l +A +\fB\%tar\fP +command appeared in Seventh Edition Unix, which was released in January, 1979. +There have been numerous other implementations, +many of which extended the file format. +John Gilmore's +\fB\%pdtar\fP +public-domain implementation (circa November, 1987) +was quite influential, and formed the basis of GNU tar. +GNU tar was included as the standard system tar +in +FreeBSD +beginning with +FreeBSD 1.0. +.PP +This is a complete re-implementation based on the +\fBlibarchive\fP(3) +library. +It was first released with +FreeBSD 5.4 +in May, 2005. +.SH BUGS +.ad l +This program follows +ISO/IEC 9945-1:1996 (``POSIX.1'') +for the definition of the +\fB\-l\fP +option. +Note that GNU tar prior to version 1.15 treated +\fB\-l\fP +as a synonym for the +\fB\-Fl\fP one-file-system +option. +.PP +The +\fB\-C\fP \fIdir\fP +option may differ from historic implementations. +.PP +All archive output is written in correctly-sized blocks, even +if the output is being compressed. +Whether or not the last output block is padded to a full +block size varies depending on the format and the +output device. +For tar and cpio formats, the last block of output is padded +to a full block size if the output is being +written to standard output or to a character or block device such as +a tape drive. +If the output is being written to a regular file, the last block +will not be padded. +Many compressors, including +\fBgzip\fP(1) +and +\fBbzip2\fP(1), +complain about the null padding when decompressing an archive created by +\fB\%tar\fP, +although they still extract it correctly. +.PP +The compression and decompression is implemented internally, so +there may be insignificant differences between the compressed output +generated by +.RS 4 +\fB\%tar\fP \fB\-czf\fP \fI-\fP file +.RE +and that generated by +.RS 4 +\fB\%tar\fP \fB\-cf\fP \fI-\fP file | \fB\%gzip\fP +.RE +.PP +The default should be to read and write archives to the standard I/O paths, +but tradition (and POSIX) dictates otherwise. +.PP +The +\fBr\fP +and +\fBu\fP +modes require that the archive be uncompressed +and located in a regular file on disk. +Other archives can be modified using +\fBc\fP +mode with the +\fI@archive-file\fP +extension. +.PP +To archive a file called +\fI@foo\fP +or +\fI-foo\fP +you must specify it as +\fI\& ./@foo\fP +or +\fI\& ./-foo\fP, +respectively. +.PP +In create mode, a leading +\fI\& ./\fP +is always removed. +A leading +\fI/\fP +is stripped unless the +\fB\-P\fP +option is specified. +.PP +There needs to be better support for file selection on both create +and extract. +.PP +There is not yet any support for multi-volume archives. +.PP +Converting between dissimilar archive formats (such as tar and cpio) using the +\fB@\fP \fI-\fP +convention can cause hard link information to be lost. +(This is a consequence of the incompatible ways that different archive +formats store hardlink information.) diff --git a/dependencies/libarchive-3.4.2/doc/man/cpio.5 b/dependencies/libarchive-3.4.2/doc/man/cpio.5 new file mode 100644 index 0000000..481f775 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/cpio.5 @@ -0,0 +1,329 @@ +.TH CPIO 5 "December 23, 2011" "" +.SH NAME +.ad l +\fB\%cpio\fP +\- format of cpio archive files +.SH DESCRIPTION +.ad l +The +\fB\%cpio\fP +archive format collects any number of files, directories, and other +file system objects (symbolic links, device nodes, etc.) into a single +stream of bytes. +.SS General Format +Each file system object in a +\fB\%cpio\fP +archive comprises a header record with basic numeric metadata +followed by the full pathname of the entry and the file data. +The header record stores a series of integer values that generally +follow the fields in +\fIstruct\fP stat. +(See +\fBstat\fP(2) +for details.) +The variants differ primarily in how they store those integers +(binary, octal, or hexadecimal). +The header is followed by the pathname of the +entry (the length of the pathname is stored in the header) +and any file data. +The end of the archive is indicated by a special record with +the pathname +``TRAILER!!!''. +.SS PWB format +XXX Any documentation of the original PWB/UNIX 1.0 format? XXX +.SS Old Binary Format +The old binary +\fB\%cpio\fP +format stores numbers as 2-byte and 4-byte binary values. +Each entry begins with a header in the following format: +.RS 4 +.nf +struct header_old_cpio { + unsigned short c_magic; + unsigned short c_dev; + unsigned short c_ino; + unsigned short c_mode; + unsigned short c_uid; + unsigned short c_gid; + unsigned short c_nlink; + unsigned short c_rdev; + unsigned short c_mtime[2]; + unsigned short c_namesize; + unsigned short c_filesize[2]; +}; +.RE +.PP +The +\fIunsigned\fP short +fields here are 16-bit integer values; the +\fIunsigned\fP int +fields are 32-bit integer values. +The fields are as follows +.RS 5 +.TP +\fImagic\fP +The integer value octal 070707. +This value can be used to determine whether this archive is +written with little-endian or big-endian integers. +.TP +\fIdev\fP, \fIino\fP +The device and inode numbers from the disk. +These are used by programs that read +\fB\%cpio\fP +archives to determine when two entries refer to the same file. +Programs that synthesize +\fB\%cpio\fP +archives should be careful to set these to distinct values for each entry. +.TP +\fImode\fP +The mode specifies both the regular permissions and the file type. +It consists of several bit fields as follows: +.RS 5 +.TP +0170000 +This masks the file type bits. +.TP +0140000 +File type value for sockets. +.TP +0120000 +File type value for symbolic links. +For symbolic links, the link body is stored as file data. +.TP +0100000 +File type value for regular files. +.TP +0060000 +File type value for block special devices. +.TP +0040000 +File type value for directories. +.TP +0020000 +File type value for character special devices. +.TP +0010000 +File type value for named pipes or FIFOs. +.TP +0004000 +SUID bit. +.TP +0002000 +SGID bit. +.TP +0001000 +Sticky bit. +On some systems, this modifies the behavior of executables and/or directories. +.TP +0000777 +The lower 9 bits specify read/write/execute permissions +for world, group, and user following standard POSIX conventions. +.RE +.TP +\fIuid\fP, \fIgid\fP +The numeric user id and group id of the owner. +.TP +\fInlink\fP +The number of links to this file. +Directories always have a value of at least two here. +Note that hardlinked files include file data with every copy in the archive. +.TP +\fIrdev\fP +For block special and character special entries, +this field contains the associated device number. +For all other entry types, it should be set to zero by writers +and ignored by readers. +.TP +\fImtime\fP +Modification time of the file, indicated as the number +of seconds since the start of the epoch, +00:00:00 UTC January 1, 1970. +The four-byte integer is stored with the most-significant 16 bits first +followed by the least-significant 16 bits. +Each of the two 16 bit values are stored in machine-native byte order. +.TP +\fInamesize\fP +The number of bytes in the pathname that follows the header. +This count includes the trailing NUL byte. +.TP +\fIfilesize\fP +The size of the file. +Note that this archive format is limited to +four gigabyte file sizes. +See +\fImtime\fP +above for a description of the storage of four-byte integers. +.RE +.PP +The pathname immediately follows the fixed header. +If the +\fBnamesize\fP +is odd, an additional NUL byte is added after the pathname. +The file data is then appended, padded with NUL +bytes to an even length. +.PP +Hardlinked files are not given special treatment; +the full file contents are included with each copy of the +file. +.SS Portable ASCII Format +Version 2 of the Single UNIX Specification (``SUSv2'') +standardized an ASCII variant that is portable across all +platforms. +It is commonly known as the +``old character'' +format or as the +``odc'' +format. +It stores the same numeric fields as the old binary format, but +represents them as 6-character or 11-character octal values. +.RS 4 +.nf +struct cpio_odc_header { + char c_magic[6]; + char c_dev[6]; + char c_ino[6]; + char c_mode[6]; + char c_uid[6]; + char c_gid[6]; + char c_nlink[6]; + char c_rdev[6]; + char c_mtime[11]; + char c_namesize[6]; + char c_filesize[11]; +}; +.RE +.PP +The fields are identical to those in the old binary format. +The name and file body follow the fixed header. +Unlike the old binary format, there is no additional padding +after the pathname or file contents. +If the files being archived are themselves entirely ASCII, then +the resulting archive will be entirely ASCII, except for the +NUL byte that terminates the name field. +.SS New ASCII Format +The "new" ASCII format uses 8-byte hexadecimal fields for +all numbers and separates device numbers into separate fields +for major and minor numbers. +.RS 4 +.nf +struct cpio_newc_header { + char c_magic[6]; + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; +}; +.RE +.PP +Except as specified below, the fields here match those specified +for the old binary format above. +.RS 5 +.TP +\fImagic\fP +The string +``070701''. +.TP +\fIcheck\fP +This field is always set to zero by writers and ignored by readers. +See the next section for more details. +.RE +.PP +The pathname is followed by NUL bytes so that the total size +of the fixed header plus pathname is a multiple of four. +Likewise, the file data is padded to a multiple of four bytes. +Note that this format supports only 4 gigabyte files (unlike the +older ASCII format, which supports 8 gigabyte files). +.PP +In this format, hardlinked files are handled by setting the +filesize to zero for each entry except the last one that +appears in the archive. +.SS New CRC Format +The CRC format is identical to the new ASCII format described +in the previous section except that the magic field is set +to +``070702'' +and the +\fIcheck\fP +field is set to the sum of all bytes in the file data. +This sum is computed treating all bytes as unsigned values +and using unsigned arithmetic. +Only the least-significant 32 bits of the sum are stored. +.SS HP variants +The +\fB\%cpio\fP +implementation distributed with HPUX used XXXX but stored +device numbers differently XXX. +.SS Other Extensions and Variants +Sun Solaris uses additional file types to store extended file +data, including ACLs and extended attributes, as special +entries in cpio archives. +.PP +XXX Others? XXX +.SH SEE ALSO +.ad l +\fBcpio\fP(1), +\fBtar\fP(5) +.SH STANDARDS +.ad l +The +\fB\%cpio\fP +utility is no longer a part of POSIX or the Single Unix Standard. +It last appeared in +Version 2 of the Single UNIX Specification (``SUSv2''). +It has been supplanted in subsequent standards by +\fBpax\fP(1). +The portable ASCII format is currently part of the specification for the +\fBpax\fP(1) +utility. +.SH HISTORY +.ad l +The original cpio utility was written by Dick Haight +while working in AT&T's Unix Support Group. +It appeared in 1977 as part of PWB/UNIX 1.0, the +``Programmer's Work Bench'' +derived from +At v6 +that was used internally at AT&T. +Both the old binary and old character formats were in use +by 1980, according to the System III source released +by SCO under their +``Ancient Unix'' +license. +The character format was adopted as part of +IEEE Std 1003.1-1988 (``POSIX.1''). +XXX when did "newc" appear? Who invented it? When did HP come out with their variant? When did Sun introduce ACLs and extended attributes? XXX +.SH BUGS +.ad l +The +``CRC'' +format is mis-named, as it uses a simple checksum and +not a cyclic redundancy check. +.PP +The old binary format is limited to 16 bits for user id, +group id, device, and inode numbers. +It is limited to 4 gigabyte file sizes. +.PP +The old ASCII format is limited to 18 bits for +the user id, group id, device, and inode numbers. +It is limited to 8 gigabyte file sizes. +.PP +The new ASCII format is limited to 4 gigabyte file sizes. +.PP +None of the cpio formats store user or group names, +which are essential when moving files between systems with +dissimilar user or group numbering. +.PP +Especially when writing older cpio variants, it may be necessary +to map actual device/inode values to synthesized values that +fit the available fields. +With very large filesystems, this may be necessary even for +the newer formats. diff --git a/dependencies/libarchive-3.4.2/doc/man/libarchive-formats.5 b/dependencies/libarchive-3.4.2/doc/man/libarchive-formats.5 new file mode 100644 index 0000000..091cbfb --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/libarchive-formats.5 @@ -0,0 +1,452 @@ +.TH LIBARCHIVE-FORMATS 5 "December 27, 2016" "" +.SH NAME +.ad l +\fB\%libarchive-formats\fP +\- archive formats supported by the libarchive library +.SH DESCRIPTION +.ad l +The +\fBlibarchive\fP(3) +library reads and writes a variety of streaming archive formats. +Generally speaking, all of these archive formats consist of a series of +``entries''. +Each entry stores a single file system object, such as a file, directory, +or symbolic link. +.PP +The following provides a brief description of each format supported +by libarchive, with some information about recognized extensions or +limitations of the current library support. +Note that just because a format is supported by libarchive does not +imply that a program that uses libarchive will support that format. +Applications that use libarchive specify which formats they wish +to support, though many programs do use libarchive convenience +functions to enable all supported formats. +.SS Tar Formats +The +\fBlibarchive\fP(3) +library can read most tar archives. +It can write POSIX-standard +``ustar'' +and +``pax interchange'' +formats as well as v7 tar format and a subset of the legacy GNU tar format. +.PP +All tar formats store each entry in one or more 512-byte records. +The first record is used for file metadata, including filename, +timestamp, and mode information, and the file data is stored in +subsequent records. +Later variants have extended this by either appropriating undefined +areas of the header record, extending the header to multiple records, +or by storing special entries that modify the interpretation of +subsequent entries. +.RS 5 +.TP +\fBgnutar\fP +The +\fBlibarchive\fP(3) +library can read most GNU-format tar archives. +It currently supports the most popular GNU extensions, including +modern long filename and linkname support, as well as atime and ctime data. +The libarchive library does not support multi-volume +archives, nor the old GNU long filename format. +It can read GNU sparse file entries, including the new POSIX-based +formats. +.PP +The +\fBlibarchive\fP(3) +library can write GNU tar format, including long filename +and linkname support, as well as atime and ctime data. +.TP +\fBpax\fP +The +\fBlibarchive\fP(3) +library can read and write POSIX-compliant pax interchange format +archives. +Pax interchange format archives are an extension of the older ustar +format that adds a separate entry with additional attributes stored +as key/value pairs immediately before each regular entry. +The presence of these additional entries is the only difference between +pax interchange format and the older ustar format. +The extended attributes are of unlimited length and are stored +as UTF-8 Unicode strings. +Keywords defined in the standard are in all lowercase; vendors are allowed +to define custom keys by preceding them with the vendor name in all uppercase. +When writing pax archives, libarchive uses many of the SCHILY keys +defined by Joerg Schilling's +``star'' +archiver and a few LIBARCHIVE keys. +The libarchive library can read most of the SCHILY keys +and most of the GNU keys introduced by GNU tar. +It silently ignores any keywords that it does not understand. +.PP +The pax interchange format converts filenames to Unicode +and stores them using the UTF-8 encoding. +Prior to libarchive 3.0, libarchive erroneously assumed +that the system wide-character routines natively supported +Unicode. +This caused it to mis-handle non-ASCII filenames on systems +that did not satisfy this assumption. +.TP +\fBrestricted\fP pax +The libarchive library can also write pax archives in which it +attempts to suppress the extended attributes entry whenever +possible. +The result will be identical to a ustar archive unless the +extended attributes entry is required to store a long file +name, long linkname, extended ACL, file flags, or if any of the standard +ustar data (user name, group name, UID, GID, etc) cannot be fully +represented in the ustar header. +In all cases, the result can be dearchived by any program that +can read POSIX-compliant pax interchange format archives. +Programs that correctly read ustar format (see below) will also be +able to read this format; any extended attributes will be extracted as +separate files stored in +\fIPaxHeader\fP +directories. +.TP +\fBustar\fP +The libarchive library can both read and write this format. +This format has the following limitations: +.RS 5 +.IP \(bu +Device major and minor numbers are limited to 21 bits. +Nodes with larger numbers will not be added to the archive. +.IP \(bu +Path names in the archive are limited to 255 bytes. +(Shorter if there is no / character in exactly the right place.) +.IP \(bu +Symbolic links and hard links are stored in the archive with +the name of the referenced file. +This name is limited to 100 bytes. +.IP \(bu +Extended attributes, file flags, and other extended +security information cannot be stored. +.IP \(bu +Archive entries are limited to 8 gigabytes in size. +.RE +Note that the pax interchange format has none of these restrictions. +The ustar format is old and widely supported. +It is recommended when compatibility is the primary concern. +.TP +\fBv7\fP +The libarchive library can read and write the legacy v7 tar format. +This format has the following limitations: +.RS 5 +.IP \(bu +Only regular files, directories, and symbolic links can be archived. +Block and character device nodes, FIFOs, and sockets cannot be archived. +.IP \(bu +Path names in the archive are limited to 100 bytes. +.IP \(bu +Symbolic links and hard links are stored in the archive with +the name of the referenced file. +This name is limited to 100 bytes. +.IP \(bu +User and group information are stored as numeric IDs; there +is no provision for storing user or group names. +.IP \(bu +Extended attributes, file flags, and other extended +security information cannot be stored. +.IP \(bu +Archive entries are limited to 8 gigabytes in size. +.RE +Generally, users should prefer the ustar format for portability +as the v7 tar format is both less useful and less portable. +.RE +.PP +The libarchive library also reads a variety of commonly-used extensions to +the basic tar format. +These extensions are recognized automatically whenever they appear. +.RS 5 +.TP +Numeric extensions. +The POSIX standards require fixed-length numeric fields to be written with +some character position reserved for terminators. +Libarchive allows these fields to be written without terminator characters. +This extends the allowable range; in particular, ustar archives with this +extension can support entries up to 64 gigabytes in size. +Libarchive also recognizes base-256 values in most numeric fields. +This essentially removes all limitations on file size, modification time, +and device numbers. +.TP +Solaris extensions +Libarchive recognizes ACL and extended attribute records written +by Solaris tar. +.RE +.PP +The first tar program appeared in Seventh Edition Unix in 1979. +The first official standard for the tar file format was the +``ustar'' +(Unix Standard Tar) format defined by POSIX in 1988. +POSIX.1-2001 extended the ustar format to create the +``pax interchange'' +format. +.SS Cpio Formats +The libarchive library can read a number of common cpio variants and can write +``odc'' +and +``newc'' +format archives. +A cpio archive stores each entry as a fixed-size header followed +by a variable-length filename and variable-length data. +Unlike the tar format, the cpio format does only minimal padding +of the header or file data. +There are several cpio variants, which differ primarily in +how they store the initial header: some store the values as +octal or hexadecimal numbers in ASCII, others as binary values of +varying byte order and length. +.RS 5 +.TP +\fBbinary\fP +The libarchive library transparently reads both big-endian and little-endian +variants of the original binary cpio format. +This format used 32-bit binary values for file size and mtime, +and 16-bit binary values for the other fields. +.TP +\fBodc\fP +The libarchive library can both read and write this +POSIX-standard format, which is officially known as the +``cpio interchange format'' +or the +``octet-oriented cpio archive format'' +and sometimes unofficially referred to as the +``old character format''. +This format stores the header contents as octal values in ASCII. +It is standard, portable, and immune from byte-order confusion. +File sizes and mtime are limited to 33 bits (8GB file size), +other fields are limited to 18 bits. +.TP +\fBSVR4/newc\fP +The libarchive library can read both CRC and non-CRC variants of +this format. +The SVR4 format uses eight-digit hexadecimal values for +all header fields. +This limits file size to 4GB, and also limits the mtime and +other fields to 32 bits. +The SVR4 format can optionally include a CRC of the file +contents, although libarchive does not currently verify this CRC. +.RE +.PP +Cpio first appeared in PWB/UNIX 1.0, which was released within +AT&T in 1977. +PWB/UNIX 1.0 formed the basis of System III Unix, released outside +of AT&T in 1981. +This makes cpio older than tar, although cpio was not included +in Version 7 AT&T Unix. +As a result, the tar command became much better known in universities +and research groups that used Version 7. +The combination of the +\fB\%find\fP +and +\fB\%cpio\fP +utilities provided very precise control over file selection. +Unfortunately, the format has many limitations that make it unsuitable +for widespread use. +Only the POSIX format permits files over 4GB, and its 18-bit +limit for most other fields makes it unsuitable for modern systems. +In addition, cpio formats only store numeric UID/GID values (not +usernames and group names), which can make it very difficult to correctly +transfer archives across systems with dissimilar user numbering. +.SS Shar Formats +A +``shell archive'' +is a shell script that, when executed on a POSIX-compliant +system, will recreate a collection of file system objects. +The libarchive library can write two different kinds of shar archives: +.RS 5 +.TP +\fBshar\fP +The traditional shar format uses a limited set of POSIX +commands, including +\fBecho\fP(1), +\fBmkdir\fP(1), +and +\fBsed\fP(1). +It is suitable for portably archiving small collections of plain text files. +However, it is not generally well-suited for large archives +(many implementations of +\fBsh\fP(1) +have limits on the size of a script) nor should it be used with non-text files. +.TP +\fBshardump\fP +This format is similar to shar but encodes files using +\fBuuencode\fP(1) +so that the result will be a plain text file regardless of the file contents. +It also includes additional shell commands that attempt to reproduce as +many file attributes as possible, including owner, mode, and flags. +The additional commands used to restore file attributes make +shardump archives less portable than plain shar archives. +.RE +.SS ISO9660 format +Libarchive can read and extract from files containing ISO9660-compliant +CDROM images. +In many cases, this can remove the need to burn a physical CDROM +just in order to read the files contained in an ISO9660 image. +It also avoids security and complexity issues that come with +virtual mounts and loopback devices. +Libarchive supports the most common Rockridge extensions and has partial +support for Joliet extensions. +If both extensions are present, the Joliet extensions will be +used and the Rockridge extensions will be ignored. +In particular, this can create problems with hardlinks and symlinks, +which are supported by Rockridge but not by Joliet. +.PP +Libarchive reads ISO9660 images using a streaming strategy. +This allows it to read compressed images directly +(decompressing on the fly) and allows it to read images +directly from network sockets, pipes, and other non-seekable +data sources. +This strategy works well for optimized ISO9660 images created +by many popular programs. +Such programs collect all directory information at the beginning +of the ISO9660 image so it can be read from a physical disk +with a minimum of seeking. +However, not all ISO9660 images can be read in this fashion. +.PP +Libarchive can also write ISO9660 images. +Such images are fully optimized with the directory information +preceding all file data. +This is done by storing all file data to a temporary file +while collecting directory information in memory. +When the image is finished, libarchive writes out the +directory structure followed by the file data. +The location used for the temporary file can be changed +by the usual environment variables. +.SS Zip format +Libarchive can read and write zip format archives that have +uncompressed entries and entries compressed with the +``deflate'' +algorithm. +Other zip compression algorithms are not supported. +It can extract jar archives, archives that use Zip64 extensions and +self-extracting zip archives. +Libarchive can use either of two different strategies for +reading Zip archives: +a streaming strategy which is fast and can handle extremely +large archives, and a seeking strategy which can correctly +process self-extracting Zip archives and archives with +deleted members or other in-place modifications. +.PP +The streaming reader processes Zip archives as they are read. +It can read archives of arbitrary size from tape or +network sockets, and can decode Zip archives that have +been separately compressed or encoded. +However, self-extracting Zip archives and archives with +certain types of modifications cannot be correctly +handled. +Such archives require that the reader first process the +Central Directory, which is ordinarily located +at the end of a Zip archive and is thus inaccessible +to the streaming reader. +If the program using libarchive has enabled seek support, then +libarchive will use this to processes the central directory first. +.PP +In particular, the seeking reader must be used to +correctly handle self-extracting archives. +Such archives consist of a program followed by a regular +Zip archive. +The streaming reader cannot parse the initial program +portion, but the seeking reader starts by reading the +Central Directory from the end of the archive. +Similarly, Zip archives that have been modified in-place +can have deleted entries or other garbage data that +can only be accurately detected by first reading the +Central Directory. +.SS Archive (library) file format +The Unix archive format (commonly created by the +\fBar\fP(1) +archiver) is a general-purpose format which is +used almost exclusively for object files to be +read by the link editor +\fBld\fP(1). +The ar format has never been standardised. +There are two common variants: +the GNU format derived from SVR4, +and the BSD format, which first appeared in 4.4BSD. +The two differ primarily in their handling of filenames +longer than 15 characters: +the GNU/SVR4 variant writes a filename table at the beginning of the archive; +the BSD format stores each long filename in an extension +area adjacent to the entry. +Libarchive can read both extensions, +including archives that may include both types of long filenames. +Programs using libarchive can write GNU/SVR4 format +if they provide an entry called +\fI//\fP +containing a filename table to be written into the archive +before any of the entries. +Any entries whose names are not in the filename table +will be written using BSD-style long filenames. +This can cause problems for programs such as +GNU ld that do not support the BSD-style long filenames. +.SS mtree +Libarchive can read and write files in +\fBmtree\fP(5) +format. +This format is not a true archive format, but rather a textual description +of a file hierarchy in which each line specifies the name of a file and +provides specific metadata about that file. +Libarchive can read all of the keywords supported by both +the NetBSD and FreeBSD versions of +\fBmtree\fP(8), +although many of the keywords cannot currently be stored in an +Tn archive_entry +object. +When writing, libarchive supports use of the +\fBarchive_write_set_options\fP(3) +interface to specify which keywords should be included in the +output. +If libarchive was compiled with access to suitable +cryptographic libraries (such as the OpenSSL libraries), +it can compute hash entries such as +\fBsha512\fP +or +\fBmd5\fP +from file data being written to the mtree writer. +.PP +When reading an mtree file, libarchive will locate the corresponding +files on disk using the +\fBcontents\fP +keyword if present or the regular filename. +If it can locate and open the file on disk, it will use that +to fill in any metadata that is missing from the mtree file +and will read the file contents and return those to the program +using libarchive. +If it cannot locate and open the file on disk, libarchive +will return an error for any attempt to read the entry +body. +.SS 7-Zip +Libarchive can read and write 7-Zip format archives. +TODO: Need more information +.SS CAB +Libarchive can read Microsoft Cabinet ( +``CAB )'' +format archives. +TODO: Need more information. +.SS LHA +TODO: Information about libarchive's LHA support +.SS RAR +Libarchive has limited support for reading RAR format archives. +Currently, libarchive can read RARv3 format archives +which have been either created uncompressed, or compressed using +any of the compression methods supported by the RARv3 format. +Libarchive can also read self-extracting RAR archives. +.SS Warc +Libarchive can read and write +``web archives''. +TODO: Need more information +.SS XAR +Libarchive can read and write the XAR format used by many Apple tools. +TODO: Need more information +.SH SEE ALSO +.ad l +\fBar\fP(1), +\fBcpio\fP(1), +\fBmkisofs\fP(1), +\fBshar\fP(1), +\fBtar\fP(1), +\fBzip\fP(1), +\fBzlib\fP(3), +\fBcpio\fP(5), +\fBmtree\fP(5), +\fBtar\fP(5) diff --git a/dependencies/libarchive-3.4.2/doc/man/libarchive.3 b/dependencies/libarchive-3.4.2/doc/man/libarchive.3 new file mode 100644 index 0000000..245a826 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/libarchive.3 @@ -0,0 +1,271 @@ +.TH LIBARCHIVE 3 "March 18, 2012" "" +.SH NAME +.ad l +\fB\%libarchive\fP +\- functions for reading and writing streaming archives +.SH OVERVIEW +.ad l +The +\fB\%libarchive\fP +library provides a flexible interface for reading and writing +archives in various formats such as tar and cpio. +\fB\%libarchive\fP +also supports reading and writing archives compressed using +various compression filters such as gzip and bzip2. +The library is inherently stream-oriented; readers serially iterate through +the archive, writers serially add things to the archive. +In particular, note that there is currently no built-in support for +random access nor for in-place modification. +.PP +When reading an archive, the library automatically detects the +format and the compression. +The library currently has read support for: +.RS 5 +.IP \(bu +old-style tar archives, +.IP \(bu +most variants of the POSIX +``ustar'' +format, +.IP \(bu +the POSIX +``pax interchange'' +format, +.IP \(bu +GNU-format tar archives, +.IP \(bu +most common cpio archive formats, +.IP \(bu +ISO9660 CD images (including RockRidge and Joliet extensions), +.IP \(bu +Zip archives, +.IP \(bu +ar archives (including GNU/SysV and BSD extensions), +.IP \(bu +Microsoft CAB archives, +.IP \(bu +LHA archives, +.IP \(bu +mtree file tree descriptions, +.IP \(bu +RAR archives, +.IP \(bu +XAR archives. +.RE +The library automatically detects archives compressed with +\fBgzip\fP(1), +\fBbzip2\fP(1), +\fBxz\fP(1), +\fBlzip\fP(1), +or +\fBcompress\fP(1) +and decompresses them transparently. +It can similarly detect and decode archives processed with +\fBuuencode\fP(1) +or which have an +\fBrpm\fP(1) +header. +.PP +When writing an archive, you can specify the compression +to be used and the format to use. +The library can write +.RS 5 +.IP \(bu +POSIX-standard +``ustar'' +archives, +.IP \(bu +POSIX +``pax interchange format'' +archives, +.IP \(bu +POSIX octet-oriented cpio archives, +.IP \(bu +Zip archive, +.IP \(bu +two different variants of shar archives, +.IP \(bu +ISO9660 CD images, +.IP \(bu +7-Zip archives, +.IP \(bu +ar archives, +.IP \(bu +mtree file tree descriptions, +.IP \(bu +XAR archives. +.RE +Pax interchange format is an extension of the tar archive format that +eliminates essentially all of the limitations of historic tar formats +in a standard fashion that is supported +by POSIX-compliant +\fBpax\fP(1) +implementations on many systems as well as several newer implementations of +\fBtar\fP(1). +Note that the default write format will suppress the pax extended +attributes for most entries; explicitly requesting pax format will +enable those attributes for all entries. +.PP +The read and write APIs are accessed through the +\fB\%archive_read_XXX\fP() +functions and the +\fB\%archive_write_XXX\fP() +functions, respectively, and either can be used independently +of the other. +.PP +The rest of this manual page provides an overview of the library +operation. +More detailed information can be found in the individual manual +pages for each API or utility function. +.SH READING AN ARCHIVE +.ad l +See +\fBarchive_read\fP(3). +.SH WRITING AN ARCHIVE +.ad l +See +\fBarchive_write\fP(3). +.SH WRITING ENTRIES TO DISK +.ad l +The +\fBarchive_write_disk\fP(3) +API allows you to write +\fBarchive_entry\fP(3) +objects to disk using the same API used by +\fBarchive_write\fP(3). +The +\fBarchive_write_disk\fP(3) +API is used internally by +\fB\%archive_read_extract\fP(\fI\%;\fP) +using it directly can provide greater control over how entries +get written to disk. +This API also makes it possible to share code between +archive-to-archive copy and archive-to-disk extraction +operations. +.SH READING ENTRIES FROM DISK +.ad l +The +\fBarchive_read_disk\fP(3) +supports for populating +\fBarchive_entry\fP(3) +objects from information in the filesystem. +This includes the information accessible from the +\fBstat\fP(2) +system call as well as ACLs, extended attributes, +and other metadata. +The +\fBarchive_read_disk\fP(3) +API also supports iterating over directory trees, +which allows directories of files to be read using +an API compatible with +the +\fBarchive_read\fP(3) +API. +.SH DESCRIPTION +.ad l +Detailed descriptions of each function are provided by the +corresponding manual pages. +.PP +All of the functions utilize an opaque +Tn struct archive +datatype that provides access to the archive contents. +.PP +The +Tn struct archive_entry +structure contains a complete description of a single archive +entry. +It uses an opaque interface that is fully documented in +\fBarchive_entry\fP(3). +.PP +Users familiar with historic formats should be aware that the newer +variants have eliminated most restrictions on the length of textual fields. +Clients should not assume that filenames, link names, user names, or +group names are limited in length. +In particular, pax interchange format can easily accommodate pathnames +in arbitrary character sets that exceed +\fIPATH_MAX\fP. +.SH RETURN VALUES +.ad l +Most functions return +\fBARCHIVE_OK\fP +(zero) on success, non-zero on error. +The return value indicates the general severity of the error, ranging +from +\fBARCHIVE_WARN\fP, +which indicates a minor problem that should probably be reported +to the user, to +\fBARCHIVE_FATAL\fP, +which indicates a serious problem that will prevent any further +operations on this archive. +On error, the +\fB\%archive_errno\fP() +function can be used to retrieve a numeric error code (see +\fBerrno\fP(2)). +The +\fB\%archive_error_string\fP() +returns a textual error message suitable for display. +.PP +\fB\%archive_read_new\fP() +and +\fB\%archive_write_new\fP() +return pointers to an allocated and initialized +Tn struct archive +object. +.PP +\fB\%archive_read_data\fP() +and +\fB\%archive_write_data\fP() +return a count of the number of bytes actually read or written. +A value of zero indicates the end of the data for this entry. +A negative value indicates an error, in which case the +\fB\%archive_errno\fP() +and +\fB\%archive_error_string\fP() +functions can be used to obtain more information. +.SH ENVIRONMENT +.ad l +There are character set conversions within the +\fBarchive_entry\fP(3) +functions that are impacted by the currently-selected locale. +.SH SEE ALSO +.ad l +\fBtar\fP(1), +\fBarchive_entry\fP(3), +\fBarchive_read\fP(3), +\fBarchive_util\fP(3), +\fBarchive_write\fP(3), +\fBtar\fP(5) +.SH HISTORY +.ad l +The +\fB\%libarchive\fP +library first appeared in +FreeBSD 5.3. +.SH AUTHORS +.ad l +-nosplit +The +\fB\%libarchive\fP +library was originally written by +Tim Kientzle \% +.SH BUGS +.ad l +Some archive formats support information that is not supported by +Tn struct archive_entry. +Such information cannot be fully archived or restored using this library. +This includes, for example, comments, character sets, +or the arbitrary key/value pairs that can appear in +pax interchange format archives. +.PP +Conversely, of course, not all of the information that can be +stored in an +Tn struct archive_entry +is supported by all formats. +For example, cpio formats do not support nanosecond timestamps; +old tar formats do not support large device numbers. +.PP +The ISO9660 reader cannot yet read all ISO9660 images; +it should learn how to seek. +.PP +The AR writer requires the client program to use +two passes, unlike all other libarchive writers. diff --git a/dependencies/libarchive-3.4.2/doc/man/libarchive_changes.3 b/dependencies/libarchive-3.4.2/doc/man/libarchive_changes.3 new file mode 100644 index 0000000..a1e2330 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/libarchive_changes.3 @@ -0,0 +1,340 @@ +.TH LIBARCHIVE_CHANGES 3 "December 23, 2011" "" +.SH NAME +.ad l +\fB\%libarchive_changes\fP +\- changes in libarchive interface +.SH CHANGES IN LIBARCHIVE 3 +.ad l +This page describes user-visible changes in libarchive3, and lists +public functions and other symbols changed, deprecated or removed +in libarchive3, along with their replacements if any. +.SS Multiple Filters +Libarchive2 permitted a single (input or output) filter active +on an archive. +Libarchive3 extends this into a variable-length stack. +Where +\fB\%archive_write_set_compression_XXX\fP() +would replace any existing filter, +\fB\%archive_write_add_filter_XXX\fP() +extends the write pipeline with another filter. +.SS Character Set Handling +Libarchive2 assumed that the local platform uses +Tn Unicode +as the native +Tn wchar_t +encoding, which is true on +Tn Windows, +modern +Tn Linux, +and a few other systems, but is certainly not universal. +As a result, pax format archives were written incorrectly on some +systems, since pax format requires +Tn UTF-8 +and libarchive 2 incorrectly +assumed that +Tn wchar_t +strings can be easily converted to +Tn UTF-8. +.PP +Libarchive3 uses the standard iconv library to convert between character +sets and is introducing the notion of a +``default character set for the archive''. +To support this, +Tn archive_entry +objects can now be bound to a particular archive when they are created. +The automatic character set conversions performed by +Tn archive_entry +objects when reading and writing filenames, usernames, and other strings +will now use an appropriate default character set: +.PP +If the +Tn archive_entry +object is bound to an archive, it will use the +default character set for that archive. +.PP +The platform default character encoding (as returned by +\fB\%nl_langinfo\fP(\fI\%CHARSET\fP, \fI\%)\fP) +will be used if nothing else is specified. +.PP +Libarchive3 also introduces charset options to many of the archive +readers and writers to control the character set that will be used for +filenames written in those archives. +When possible, this will be set automatically based on information in +the archive itself. +Combining this with the notion of a default character set for the +archive should allow you to configure libarchive to read archives from +other platforms and have the filenames and other information +transparently converted to the character encoding suitable for your +application. +.SS Prototype Changes +These changes break binary compatibility; libarchive3 has a new shared +library version to reflect these changes. +The library now uses portable wide types such as +Tn int64_t +instead of less-portable types such as +Tn off_t, +Tn gid_t, +Tn uid_t, +and +Tn ino_t. +.PP +There are a few cases where these changes will affect your source code: +.RS 5 +.IP \(bu +In some cases, libarchive's wider types will introduce the possibility +of truncation: for example, on a system with a 16-bit +Tn uid_t, you risk having uid +.RS 4 +65536 +.RE +be truncated to uid +.RS 4 +0, +.RE +which can cause serious security problems. +.IP \(bu +Typedef function pointer types will be incompatible. +For example, if you define custom skip callbacks, you may have to use +code similar to the following if you want to support building against +libarchive2 and libarchive3: +.RS 4 +.nf +#if ARCHIVE_VERSION_NUMBER < 3000000 +typedef off_t myoff_t; +#else +typedef int64_t myoff_t; +#endif +myoff_t +my_skip_function(struct archive *a, void *v, myoff_t o) +{ + ... implementation ... +} +.RE +.RE +.PP +Affected functions: +.PP +.RS 5 +.IP \(bu +\fB\%archive_entry_gid\fP(), +\fB\%archive_entry_set_gid\fP() +.IP \(bu +\fB\%archive_entry_uid\fP(), +\fB\%archive_entry_set_uid\fP() +.IP \(bu +\fB\%archive_entry_ino\fP(), +\fB\%archive_entry_set_ino\fP() +.IP \(bu +\fB\%archive_read_data_block\fP(), +\fB\%archive_write_data_block\fP() +.IP \(bu +\fB\%archive_read_disk_gname\fP(), +\fB\%archive_read_disk_uname\fP() +.IP \(bu +\fB\%archive_read_disk_set_gname_lookup\fP(), +\fB\%archive_read_disk_set_group_lookup\fP(), +\fB\%archive_read_disk_set_uname_lookup\fP(), +\fB\%archive_read_disk_set_user_lookup\fP() +.IP \(bu +\fB\%archive_skip_callback\fP() +.IP \(bu +\fB\%archive_read_extract_set_skip_file\fP(), +\fB\%archive_write_disk_set_skip_file\fP(), +\fB\%archive_write_set_skip_file\fP() +.IP \(bu +\fB\%archive_write_disk_set_group_lookup\fP(), +\fB\%archive_write_disk_set_user_lookup\fP() +.RE +.PP +Where these functions or their arguments took or returned +Tn gid_t, +Tn ino_t, +Tn off_t, +or +Tn uid_t +they now take or return +Tn int64_t +or equivalent. +.SS Deprecated Symbols +Symbols deprecated in libarchive3 will be removed in libarchive4. +These symbols, along with their replacements if any, are listed below: +.RS 5 +.TP +\fB\%archive_position_compressed\fP(), \fB\%archive_position_uncompressed\fP() +\fB\%archive_filter_bytes\fP() +.TP +\fB\%archive_compression\fP() +\fB\%archive_filter_code\fP() +.TP +\fB\%archive_compression_name\fP() +\fB\%archive_filter_name\fP() +.TP +\fB\%archive_read_finish\fP(), \fB\%archive_write_finish\fP() +\fB\%archive_read_free\fP(), +\fB\%archive_write_free\fP() +.TP +\fB\%archive_read_open_file\fP(), \fB\%archive_write_open_file\fP() +\fB\%archive_read_open_filename\fP(), +\fB\%archive_write_open_filename\fP() +.TP +\fB\%archive_read_support_compression_all\fP() +\fB\%archive_read_support_filter_all\fP() +.TP +\fB\%archive_read_support_compression_bzip2\fP() +\fB\%archive_read_support_filter_bzip2\fP() +.TP +\fB\%archive_read_support_compression_compress\fP() +\fB\%archive_read_support_filter_compress\fP() +.TP +\fB\%archive_read_support_compression_gzip\fP() +\fB\%archive_read_support_filter_gzip\fP() +.TP +\fB\%archive_read_support_compression_lzip\fP() +\fB\%archive_read_support_filter_lzip\fP() +.TP +\fB\%archive_read_support_compression_lzma\fP() +\fB\%archive_read_support_filter_lzma\fP() +.TP +\fB\%archive_read_support_compression_none\fP() +\fB\%archive_read_support_filter_none\fP() +.TP +\fB\%archive_read_support_compression_program\fP() +\fB\%archive_read_support_filter_program\fP() +.TP +\fB\%archive_read_support_compression_program_signature\fP() +\fB\%archive_read_support_filter_program_signature\fP() +.TP +\fB\%archive_read_support_compression_rpm\fP() +\fB\%archive_read_support_filter_rpm\fP() +.TP +\fB\%archive_read_support_compression_uu\fP() +\fB\%archive_read_support_filter_uu\fP() +.TP +\fB\%archive_read_support_compression_xz\fP() +\fB\%archive_read_support_filter_xz\fP() +.TP +\fB\%archive_write_set_compression_bzip2\fP() +\fB\%archive_write_add_filter_bzip2\fP() +.TP +\fB\%archive_write_set_compression_compress\fP() +\fB\%archive_write_add_filter_compress\fP() +.TP +\fB\%archive_write_set_compression_gzip\fP() +\fB\%archive_write_add_filter_gzip\fP() +.TP +\fB\%archive_write_set_compression_lzip\fP() +\fB\%archive_write_add_filter_lzip\fP() +.TP +\fB\%archive_write_set_compression_lzma\fP() +\fB\%archive_write_add_filter_lzma\fP() +.TP +\fB\%archive_write_set_compression_none\fP() +\fB\%archive_write_add_filter_none\fP() +.TP +\fB\%archive_write_set_compression_program\fP() +\fB\%archive_write_add_filter_program\fP() +.TP +\fB\%archive_write_set_compression_filter\fP() +\fB\%archive_write_add_filter_filter\fP() +.RE +.SS Removed Symbols +These symbols, listed below along with their replacements if any, +were deprecated in libarchive2, and are not part of libarchive3. +.RS 5 +.TP +\fB\%archive_api_feature\fP() +\fB\%archive_version_number\fP() +.TP +\fB\%archive_api_version\fP() +\fB\%archive_version_number\fP() +.TP +\fB\%archive_version\fP() +\fB\%archive_version_string\fP() +.TP +\fB\%archive_version_stamp\fP() +\fB\%archive_version_number\fP() +.TP +\fB\%archive_read_set_filter_options\fP() +\fB\%archive_read_set_options\fP() +or +\fB\%archive_read_set_filter_option\fP() +.TP +\fB\%archive_read_set_format_options\fP() +\fB\%archive_read_set_options\fP() +or +\fB\%archive_read_set_format_option\fP() +.TP +\fB\%archive_write_set_filter_options\fP() +\fB\%archive_write_set_options\fP() +or +\fB\%archive_write_set_filter_option\fP() +.TP +\fB\%archive_write_set_format_options\fP() +\fB\%archive_write_set_options\fP() +or +\fB\%archive_write_set_format_option\fP() +.TP +.BR ARCHIVE_API_FEATURE +.BR ARCHIVE_VERSION_NUMBER +.TP +.BR ARCHIVE_API_VERSION +.BR ARCHIVE_VERSION_NUMBER +.TP +.BR ARCHIVE_VERSION_STAMP +.BR ARCHIVE_VERSION_NUMBER +.TP +.BR ARCHIVE_LIBRARY_VERSION +.BR ARCHIVE_VERSION_STRING +.TP +.BR ARCHIVE_COMPRESSION_NONE +.BR ARCHIVE_FILTER_NONE +.TP +.BR ARCHIVE_COMPRESSION_GZIP +.BR ARCHIVE_FILTER_GZIP +.TP +.BR ARCHIVE_COMPRESSION_BZIP2 +.BR ARCHIVE_FILTER_BZIP2 +.TP +.BR ARCHIVE_COMPRESSION_COMPRESS +.BR ARCHIVE_FILTER_COMPRESS +.TP +.BR ARCHIVE_COMPRESSION_PROGRAM +.BR ARCHIVE_FILTER_PROGRAM +.TP +.BR ARCHIVE_COMPRESSION_LZMA +.BR ARCHIVE_FILTER_LZMA +.TP +.BR ARCHIVE_COMPRESSION_XZ +.BR ARCHIVE_FILTER_XZ +.TP +.BR ARCHIVE_COMPRESSION_UU +.BR ARCHIVE_FILTER_UU +.TP +.BR ARCHIVE_COMPRESSION_RPM +.BR ARCHIVE_FILTER_RPM +.TP +.BR ARCHIVE_COMPRESSION_LZIP +.BR ARCHIVE_FILTER_LZIP +.TP +.BR ARCHIVE_BYTES_PER_RECORD +.RS 4 +512 +.RE +.TP +.BR ARCHIVE_DEFAULT_BYTES_PER_BLOCK +.RS 4 +10240 +.RE +.RE +.SH SEE ALSO +.ad l +\fBarchive_read\fP(3), +\fBarchive_read_filter\fP(3), +\fBarchive_read_format\fP(3), +\fBarchive_read_set_options\fP(3), +\fBarchive_util\fP(3), +\fBarchive_write\fP(3), +\fBarchive_write_filter\fP(3), +\fBarchive_write_format\fP(3), +\fBarchive_write_set_options\fP(3), +\fBlibarchive\fP(3) diff --git a/dependencies/libarchive-3.4.2/doc/man/libarchive_internals.3 b/dependencies/libarchive-3.4.2/doc/man/libarchive_internals.3 new file mode 100644 index 0000000..05337ad --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/libarchive_internals.3 @@ -0,0 +1,359 @@ +.TH LIBARCHIVE_INTERNALS 3 "January 26, 2011" "" +.SH NAME +.ad l +\fB\%libarchive_internals\fP +\- description of libarchive internal interfaces +.SH OVERVIEW +.ad l +The +\fB\%libarchive\fP +library provides a flexible interface for reading and writing +streaming archive files such as tar and cpio. +Internally, it follows a modular layered design that should +make it easy to add new archive and compression formats. +.SH GENERAL ARCHITECTURE +.ad l +Externally, libarchive exposes most operations through an +opaque, object-style interface. +The +\fBarchive_entry\fP(3) +objects store information about a single filesystem object. +The rest of the library provides facilities to write +\fBarchive_entry\fP(3) +objects to archive files, +read them from archive files, +and write them to disk. +(There are plans to add a facility to read +\fBarchive_entry\fP(3) +objects from disk as well.) +.PP +The read and write APIs each have four layers: a public API +layer, a format layer that understands the archive file format, +a compression layer, and an I/O layer. +The I/O layer is completely exposed to clients who can replace +it entirely with their own functions. +.PP +In order to provide as much consistency as possible for clients, +some public functions are virtualized. +Eventually, it should be possible for clients to open +an archive or disk writer, and then use a single set of +code to select and write entries, regardless of the target. +.SH READ ARCHITECTURE +.ad l +From the outside, clients use the +\fBarchive_read\fP(3) +API to manipulate an +\fB\%archive\fP +object to read entries and bodies from an archive stream. +Internally, the +\fB\%archive\fP +object is cast to an +\fB\%archive_read\fP +object, which holds all read-specific data. +The API has four layers: +The lowest layer is the I/O layer. +This layer can be overridden by clients, but most clients use +the packaged I/O callbacks provided, for example, by +\fBarchive_read_open_memory\fP(3), +and +\fBarchive_read_open_fd\fP(3). +The compression layer calls the I/O layer to +read bytes and decompresses them for the format layer. +The format layer unpacks a stream of uncompressed bytes and +creates +\fB\%archive_entry\fP +objects from the incoming data. +The API layer tracks overall state +(for example, it prevents clients from reading data before reading a header) +and invokes the format and compression layer operations +through registered function pointers. +In particular, the API layer drives the format-detection process: +When opening the archive, it reads an initial block of data +and offers it to each registered compression handler. +The one with the highest bid is initialized with the first block. +Similarly, the format handlers are polled to see which handler +is the best for each archive. +(Prior to 2.4.0, the format bidders were invoked for each +entry, but this design hindered error recovery.) +.SS I/O Layer and Client Callbacks +The read API goes to some lengths to be nice to clients. +As a result, there are few restrictions on the behavior of +the client callbacks. +.PP +The client read callback is expected to provide a block +of data on each call. +A zero-length return does indicate end of file, but otherwise +blocks may be as small as one byte or as large as the entire file. +In particular, blocks may be of different sizes. +.PP +The client skip callback returns the number of bytes actually +skipped, which may be much smaller than the skip requested. +The only requirement is that the skip not be larger. +In particular, clients are allowed to return zero for any +skip that they don't want to handle. +The skip callback must never be invoked with a negative value. +.PP +Keep in mind that not all clients are reading from disk: +clients reading from networks may provide different-sized +blocks on every request and cannot skip at all; +advanced clients may use +\fBmmap\fP(2) +to read the entire file into memory at once and return the +entire file to libarchive as a single block; +other clients may begin asynchronous I/O operations for the +next block on each request. +.SS Decompresssion Layer +The decompression layer not only handles decompression, +it also buffers data so that the format handlers see a +much nicer I/O model. +The decompression API is a two stage peek/consume model. +A read_ahead request specifies a minimum read amount; +the decompression layer must provide a pointer to at least +that much data. +If more data is immediately available, it should return more: +the format layer handles bulk data reads by asking for a minimum +of one byte and then copying as much data as is available. +.PP +A subsequent call to the +\fB\%consume\fP() +function advances the read pointer. +Note that data returned from a +\fB\%read_ahead\fP() +call is guaranteed to remain in place until +the next call to +\fB\%read_ahead\fP(). +Intervening calls to +\fB\%consume\fP() +should not cause the data to move. +.PP +Skip requests must always be handled exactly. +Decompression handlers that cannot seek forward should +not register a skip handler; +the API layer fills in a generic skip handler that reads and discards data. +.PP +A decompression handler has a specific lifecycle: +.RS 5 +.TP +Registration/Configuration +When the client invokes the public support function, +the decompression handler invokes the internal +\fB\%__archive_read_register_compression\fP() +function to provide bid and initialization functions. +This function returns +\fBNULL\fP +on error or else a pointer to a +\fBstruct\fP decompressor_t. +This structure contains a +\fIvoid\fP * config +slot that can be used for storing any customization information. +.TP +Bid +The bid function is invoked with a pointer and size of a block of data. +The decompressor can access its config data +through the +\fIdecompressor\fP +element of the +\fBarchive_read\fP +object. +The bid function is otherwise stateless. +In particular, it must not perform any I/O operations. +.PP +The value returned by the bid function indicates its suitability +for handling this data stream. +A bid of zero will ensure that this decompressor is never invoked. +Return zero if magic number checks fail. +Otherwise, your initial implementation should return the number of bits +actually checked. +For example, if you verify two full bytes and three bits of another +byte, bid 19. +Note that the initial block may be very short; +be careful to only inspect the data you are given. +(The current decompressors require two bytes for correct bidding.) +.TP +Initialize +The winning bidder will have its init function called. +This function should initialize the remaining slots of the +\fIstruct\fP decompressor_t +object pointed to by the +\fIdecompressor\fP +element of the +\fIarchive_read\fP +object. +In particular, it should allocate any working data it needs +in the +\fIdata\fP +slot of that structure. +The init function is called with the block of data that +was used for tasting. +At this point, the decompressor is responsible for all I/O +requests to the client callbacks. +The decompressor is free to read more data as and when +necessary. +.TP +Satisfy I/O requests +The format handler will invoke the +\fIread_ahead\fP, +\fIconsume\fP, +and +\fIskip\fP +functions as needed. +.TP +Finish +The finish method is called only once when the archive is closed. +It should release anything stored in the +\fIdata\fP +and +\fIconfig\fP +slots of the +\fIdecompressor\fP +object. +It should not invoke the client close callback. +.RE +.SS Format Layer +The read formats have a similar lifecycle to the decompression handlers: +.RS 5 +.TP +Registration +Allocate your private data and initialize your pointers. +.TP +Bid +Formats bid by invoking the +\fB\%read_ahead\fP() +decompression method but not calling the +\fB\%consume\fP() +method. +This allows each bidder to look ahead in the input stream. +Bidders should not look further ahead than necessary, as long +look aheads put pressure on the decompression layer to buffer +lots of data. +Most formats only require a few hundred bytes of look ahead; +look aheads of a few kilobytes are reasonable. +(The ISO9660 reader sometimes looks ahead by 48k, which +should be considered an upper limit.) +.TP +Read header +The header read is usually the most complex part of any format. +There are a few strategies worth mentioning: +For formats such as tar or cpio, reading and parsing the header is +straightforward since headers alternate with data. +For formats that store all header data at the beginning of the file, +the first header read request may have to read all headers into +memory and store that data, sorted by the location of the file +data. +Subsequent header read requests will skip forward to the +beginning of the file data and return the corresponding header. +.TP +Read Data +The read data interface supports sparse files; this requires that +each call return a block of data specifying the file offset and +size. +This may require you to carefully track the location so that you +can return accurate file offsets for each read. +Remember that the decompressor will return as much data as it has. +Generally, you will want to request one byte, +examine the return value to see how much data is available, and +possibly trim that to the amount you can use. +You should invoke consume for each block just before you return it. +.TP +Skip All Data +The skip data call should skip over all file data and trailing padding. +This is called automatically by the API layer just before each +header read. +It is also called in response to the client calling the public +\fB\%data_skip\fP() +function. +.TP +Cleanup +On cleanup, the format should release all of its allocated memory. +.RE +.SS API Layer +XXX to do XXX +.SH WRITE ARCHITECTURE +.ad l +The write API has a similar set of four layers: +an API layer, a format layer, a compression layer, and an I/O layer. +The registration here is much simpler because only +one format and one compression can be registered at a time. +.SS I/O Layer and Client Callbacks +XXX To be written XXX +.SS Compression Layer +XXX To be written XXX +.SS Format Layer +XXX To be written XXX +.SS API Layer +XXX To be written XXX +.SH WRITE_DISK ARCHITECTURE +.ad l +The write_disk API is intended to look just like the write API +to clients. +Since it does not handle multiple formats or compression, it +is not layered internally. +.SH GENERAL SERVICES +.ad l +The +\fB\%archive_read\fP, +\fB\%archive_write\fP, +and +\fB\%archive_write_disk\fP +objects all contain an initial +\fB\%archive\fP +object which provides common support for a set of standard services. +(Recall that ANSI/ISO C90 guarantees that you can cast freely between +a pointer to a structure and a pointer to the first element of that +structure.) +The +\fB\%archive\fP +object has a magic value that indicates which API this object +is associated with, +slots for storing error information, +and function pointers for virtualized API functions. +.SH MISCELLANEOUS NOTES +.ad l +Connecting existing archiving libraries into libarchive is generally +quite difficult. +In particular, many existing libraries strongly assume that you +are reading from a file; they seek forwards and backwards as necessary +to locate various pieces of information. +In contrast, libarchive never seeks backwards in its input, which +sometimes requires very different approaches. +.PP +For example, libarchive's ISO9660 support operates very differently +from most ISO9660 readers. +The libarchive support utilizes a work-queue design that +keeps a list of known entries sorted by their location in the input. +Whenever libarchive's ISO9660 implementation is asked for the next +header, checks this list to find the next item on the disk. +Directories are parsed when they are encountered and new +items are added to the list. +This design relies heavily on the ISO9660 image being optimized so that +directories always occur earlier on the disk than the files they +describe. +.PP +Depending on the specific format, such approaches may not be possible. +The ZIP format specification, for example, allows archivers to store +key information only at the end of the file. +In theory, it is possible to create ZIP archives that cannot +be read without seeking. +Fortunately, such archives are very rare, and libarchive can read +most ZIP archives, though it cannot always extract as much information +as a dedicated ZIP program. +.SH SEE ALSO +.ad l +\fBarchive_entry\fP(3), +\fBarchive_read\fP(3), +\fBarchive_write\fP(3), +\fBarchive_write_disk\fP(3), +\fBlibarchive\fP(3) +.SH HISTORY +.ad l +The +\fB\%libarchive\fP +library first appeared in +FreeBSD 5.3. +.SH AUTHORS +.ad l +-nosplit +The +\fB\%libarchive\fP +library was written by +Tim Kientzle \% diff --git a/dependencies/libarchive-3.4.2/doc/man/mtree.5 b/dependencies/libarchive-3.4.2/doc/man/mtree.5 new file mode 100644 index 0000000..8e33309 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/mtree.5 @@ -0,0 +1,345 @@ +.TH MTREE 5 "September 4, 2013" "" +.SH NAME +.ad l +\fB\%mtree\fP +\- format of mtree dir hierarchy files +.SH DESCRIPTION +.ad l +The +\fB\%mtree\fP +format is a textual format that describes a collection of filesystem objects. +Such files are typically used to create or verify directory hierarchies. +.SS General Format +An +\fB\%mtree\fP +file consists of a series of lines, each providing information +about a single filesystem object. +Leading whitespace is always ignored. +.PP +When encoding file or pathnames, any backslash character or +character outside of the 95 printable ASCII characters must be +encoded as a backslash followed by three +octal digits. +When reading mtree files, any appearance of a backslash +followed by three octal digits should be converted into the +corresponding character. +.PP +Each line is interpreted independently as one of the following types: +.RS 5 +.TP +Blank +Blank lines are ignored. +.TP +Comment +Lines beginning with +\fB#\fP +are ignored. +.TP +Special +Lines beginning with +\fB/\fP +are special commands that influence +the interpretation of later lines. +.TP +Relative +If the first whitespace-delimited word has no +\fB/\fP +characters, +it is the name of a file in the current directory. +Any relative entry that describes a directory changes the +current directory. +.TP +dot-dot +As a special case, a relative entry with the filename +\fI\& ..\fP +changes the current directory to the parent directory. +Options on dot-dot entries are always ignored. +.TP +Full +If the first whitespace-delimited word has a +\fB/\fP +character after +the first character, it is the pathname of a file relative to the +starting directory. +There can be multiple full entries describing the same file. +.RE +.PP +Some tools that process +\fB\%mtree\fP +files may require that multiple lines describing the same file +occur consecutively. +It is not permitted for the same file to be mentioned using +both a relative and a full file specification. +.SS Special commands +Two special commands are currently defined: +.RS 5 +.TP +\fB/set\fP +This command defines default values for one or more keywords. +It is followed on the same line by one or more whitespace-separated +keyword definitions. +These definitions apply to all following files that do not specify +a value for that keyword. +.TP +\fB/unset\fP +This command removes any default value set by a previous +\fB/set\fP +command. +It is followed on the same line by one or more keywords +separated by whitespace. +.RE +.SS Keywords +After the filename, a full or relative entry consists of zero +or more whitespace-separated keyword definitions. +Each such definition consists of a key from the following +list immediately followed by an '=' sign +and a value. +Software programs reading mtree files should warn about +unrecognized keywords. +.PP +Currently supported keywords are as follows: +.RS 5 +.TP +\fBcksum\fP +The checksum of the file using the default algorithm specified by +the +\fBcksum\fP(1) +utility. +.TP +\fBdevice\fP +The device number for +.B block +or +.B char +file types. +The value must be one of the following forms: +.RS 5 +.TP +\fIformat\fP, \fImajor\fP, \fIminor\fP Bo, \fIsubunit\fP Bc +A device with +\fImajor\fP, minor +and optional +\fIsubunit\fP +fields. +Their meaning is specified by the operating's system +\fIformat\fP. +See below for valid formats. +.TP +\fInumber\fP +Opaque number (as stored on the file system). +.RE +.PP +The following values for +\fIformat\fP +are recognized: +.B native , +.B 386bsd , +.B 4bsd , +.B bsdos , +.B freebsd , +.B hpux , +.B isc , +.B linux , +.B netbsd , +.B osf1 , +.B sco , +.B solaris , +.B sunos , +.B svr3 , +.B svr4 , +and +.B ultrix . +.PP +See +\fBmknod\fP(8) +for more details. +.TP +\fBcontents\fP +The full pathname of a file that holds the contents of this file. +.TP +\fBflags\fP +The file flags as a symbolic name. +See +\fBchflags\fP(1) +for information on these names. +If no flags are to be set the string +``none'' +may be used to override the current default. +.TP +\fBgid\fP +The file group as a numeric value. +.TP +\fBgname\fP +The file group as a symbolic name. +.TP +\fBignore\fP +Ignore any file hierarchy below this file. +.TP +\fBinode\fP +The inode number. +.TP +\fBlink\fP +The target of the symbolic link when type=link. +.TP +\fBmd5\fP +The MD5 message digest of the file. +.TP +\fBmd5digest\fP +A synonym for +\fBmd5\fP. +.TP +\fBmode\fP +The current file's permissions as a numeric (octal) or symbolic +value. +.TP +\fBnlink\fP +The number of hard links the file is expected to have. +.TP +\fBnochange\fP +Make sure this file or directory exists but otherwise ignore all attributes. +.TP +\fBoptional\fP +The file is optional; do not complain about the file if it is not in +the file hierarchy. +.TP +\fBresdevice\fP +The +``resident'' +device number of the file, e.g. the ID of the device that +contains the file. +Its format is the same as the one for +\fBdevice\fP. +.TP +\fBripemd160digest\fP +The +Tn RIPEMD160 +message digest of the file. +.TP +\fBrmd160\fP +A synonym for +\fBripemd160digest\fP. +.TP +\fBrmd160digest\fP +A synonym for +\fBripemd160digest\fP. +.TP +\fBsha1\fP +The +Tn FIPS +160-1 +(``Tn SHA-1'') +message digest of the file. +.TP +\fBsha1digest\fP +A synonym for +\fBsha1\fP. +.TP +\fBsha256\fP +The +Tn FIPS +180-2 +(``Tn SHA-256'') +message digest of the file. +.TP +\fBsha256digest\fP +A synonym for +\fBsha256\fP. +.TP +\fBsha384\fP +The +Tn FIPS +180-2 +(``Tn SHA-384'') +message digest of the file. +.TP +\fBsha384digest\fP +A synonym for +\fBsha384\fP. +.TP +\fBsha512\fP +The +Tn FIPS +180-2 +(``Tn SHA-512'') +message digest of the file. +.TP +\fBsha512digest\fP +A synonym for +\fBsha512\fP. +.TP +\fBsize\fP +The size, in bytes, of the file. +.TP +\fBtime\fP +The last modification time of the file. +.TP +\fBtype\fP +The type of the file; may be set to any one of the following: +.PP +.RS 5 +.TP +\fBblock\fP +block special device +.TP +\fBchar\fP +character special device +.TP +\fBdir\fP +directory +.TP +\fBfifo\fP +fifo +.TP +\fBfile\fP +regular file +.TP +\fBlink\fP +symbolic link +.TP +\fBsocket\fP +socket +.RE +.TP +\fBuid\fP +The file owner as a numeric value. +.TP +\fBuname\fP +The file owner as a symbolic name. +.RE +.SH SEE ALSO +.ad l +\fBcksum\fP(1), +\fBfind\fP(1), +\fBmtree\fP(8) +.SH HISTORY +.ad l +The +\fB\%mtree\fP +utility appeared in +Bx 4.3 Reno. +The +Tn MD5 +digest capability was added in +FreeBSD 2.1, +in response to the widespread use of programs which can spoof +\fBcksum\fP(1). +The +Tn SHA-1 +and +Tn RIPEMD160 +digests were added in +FreeBSD 4.0, +as new attacks have demonstrated weaknesses in +Tn MD5. +The +Tn SHA-256 +digest was added in +FreeBSD 6.0. +Support for file flags was added in +FreeBSD 4.0, +and mostly comes from +NetBSD. +The +``full'' +entry format was added by +NetBSD. diff --git a/dependencies/libarchive-3.4.2/doc/man/tar.5 b/dependencies/libarchive-3.4.2/doc/man/tar.5 new file mode 100644 index 0000000..e8fed3e --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/man/tar.5 @@ -0,0 +1,1011 @@ +.TH TAR 5 "December 27, 2016" "" +.SH NAME +.ad l +\fB\%tar\fP +\- format of tape archive files +.SH DESCRIPTION +.ad l +The +\fB\%tar\fP +archive format collects any number of files, directories, and other +file system objects (symbolic links, device nodes, etc.) into a single +stream of bytes. +The format was originally designed to be used with +tape drives that operate with fixed-size blocks, but is widely used as +a general packaging mechanism. +.SS General Format +A +\fB\%tar\fP +archive consists of a series of 512-byte records. +Each file system object requires a header record which stores basic metadata +(pathname, owner, permissions, etc.) and zero or more records containing any +file data. +The end of the archive is indicated by two records consisting +entirely of zero bytes. +.PP +For compatibility with tape drives that use fixed block sizes, +programs that read or write tar files always read or write a fixed +number of records with each I/O operation. +These +``blocks'' +are always a multiple of the record size. +The maximum block size supported by early +implementations was 10240 bytes or 20 records. +This is still the default for most implementations +although block sizes of 1MiB (2048 records) or larger are +commonly used with modern high-speed tape drives. +(Note: the terms +``block'' +and +``record'' +here are not entirely standard; this document follows the +convention established by John Gilmore in documenting +\fB\%pdtar\fP.) +.SS Old-Style Archive Format +The original tar archive format has been extended many times to +include additional information that various implementors found +necessary. +This section describes the variant implemented by the tar command +included in +At v7, +which seems to be the earliest widely-used version of the tar program. +.PP +The header record for an old-style +\fB\%tar\fP +archive consists of the following: +.RS 4 +.nf +struct header_old_tar { + char name[100]; + char mode[8]; + char uid[8]; + char gid[8]; + char size[12]; + char mtime[12]; + char checksum[8]; + char linkflag[1]; + char linkname[100]; + char pad[255]; +}; +.RE +All unused bytes in the header record are filled with nulls. +.RS 5 +.TP +\fIname\fP +Pathname, stored as a null-terminated string. +Early tar implementations only stored regular files (including +hardlinks to those files). +One common early convention used a trailing "/" character to indicate +a directory name, allowing directory permissions and owner information +to be archived and restored. +.TP +\fImode\fP +File mode, stored as an octal number in ASCII. +.TP +\fIuid\fP, \fIgid\fP +User id and group id of owner, as octal numbers in ASCII. +.TP +\fIsize\fP +Size of file, as octal number in ASCII. +For regular files only, this indicates the amount of data +that follows the header. +In particular, this field was ignored by early tar implementations +when extracting hardlinks. +Modern writers should always store a zero length for hardlink entries. +.TP +\fImtime\fP +Modification time of file, as an octal number in ASCII. +This indicates the number of seconds since the start of the epoch, +00:00:00 UTC January 1, 1970. +Note that negative values should be avoided +here, as they are handled inconsistently. +.TP +\fIchecksum\fP +Header checksum, stored as an octal number in ASCII. +To compute the checksum, set the checksum field to all spaces, +then sum all bytes in the header using unsigned arithmetic. +This field should be stored as six octal digits followed by a null and a space +character. +Note that many early implementations of tar used signed arithmetic +for the checksum field, which can cause interoperability problems +when transferring archives between systems. +Modern robust readers compute the checksum both ways and accept the +header if either computation matches. +.TP +\fIlinkflag\fP, \fIlinkname\fP +In order to preserve hardlinks and conserve tape, a file +with multiple links is only written to the archive the first +time it is encountered. +The next time it is encountered, the +\fIlinkflag\fP +is set to an ASCII +Sq 1 +and the +\fIlinkname\fP +field holds the first name under which this file appears. +(Note that regular files have a null value in the +\fIlinkflag\fP +field.) +.RE +.PP +Early tar implementations varied in how they terminated these fields. +The tar command in +At v7 +used the following conventions (this is also documented in early BSD manpages): +the pathname must be null-terminated; +the mode, uid, and gid fields must end in a space and a null byte; +the size and mtime fields must end in a space; +the checksum is terminated by a null and a space. +Early implementations filled the numeric fields with leading spaces. +This seems to have been common practice until the +IEEE Std 1003.1-1988 (``POSIX.1'') +standard was released. +For best portability, modern implementations should fill the numeric +fields with leading zeros. +.SS Pre-POSIX Archives +An early draft of +IEEE Std 1003.1-1988 (``POSIX.1'') +served as the basis for John Gilmore's +\fB\%pdtar\fP +program and many system implementations from the late 1980s +and early 1990s. +These archives generally follow the POSIX ustar +format described below with the following variations: +.RS 5 +.IP \(bu +The magic value consists of the five characters +``ustar'' +followed by a space. +The version field contains a space character followed by a null. +.IP \(bu +The numeric fields are generally filled with leading spaces +(not leading zeros as recommended in the final standard). +.IP \(bu +The prefix field is often not used, limiting pathnames to +the 100 characters of old-style archives. +.RE +.SS POSIX ustar Archives +IEEE Std 1003.1-1988 (``POSIX.1'') +defined a standard tar file format to be read and written +by compliant implementations of +\fBtar\fP(1). +This format is often called the +``ustar'' +format, after the magic value used +in the header. +(The name is an acronym for +``Unix Standard TAR''.) +It extends the historic format with new fields: +.RS 4 +.nf +struct header_posix_ustar { + char name[100]; + char mode[8]; + char uid[8]; + char gid[8]; + char size[12]; + char mtime[12]; + char checksum[8]; + char typeflag[1]; + char linkname[100]; + char magic[6]; + char version[2]; + char uname[32]; + char gname[32]; + char devmajor[8]; + char devminor[8]; + char prefix[155]; + char pad[12]; +}; +.RE +.RS 5 +.TP +\fItypeflag\fP +Type of entry. +POSIX extended the earlier +\fIlinkflag\fP +field with several new type values: +.RS 5 +.TP +``0'' +Regular file. +NUL should be treated as a synonym, for compatibility purposes. +.TP +``1'' +Hard link. +.TP +``2'' +Symbolic link. +.TP +``3'' +Character device node. +.TP +``4'' +Block device node. +.TP +``5'' +Directory. +.TP +``6'' +FIFO node. +.TP +``7'' +Reserved. +.TP +Other +A POSIX-compliant implementation must treat any unrecognized typeflag value +as a regular file. +In particular, writers should ensure that all entries +have a valid filename so that they can be restored by readers that do not +support the corresponding extension. +Uppercase letters "A" through "Z" are reserved for custom extensions. +Note that sockets and whiteout entries are not archivable. +.RE +It is worth noting that the +\fIsize\fP +field, in particular, has different meanings depending on the type. +For regular files, of course, it indicates the amount of data +following the header. +For directories, it may be used to indicate the total size of all +files in the directory, for use by operating systems that pre-allocate +directory space. +For all other types, it should be set to zero by writers and ignored +by readers. +.TP +\fImagic\fP +Contains the magic value +``ustar'' +followed by a NUL byte to indicate that this is a POSIX standard archive. +Full compliance requires the uname and gname fields be properly set. +.TP +\fIversion\fP +Version. +This should be +``00'' +(two copies of the ASCII digit zero) for POSIX standard archives. +.TP +\fIuname\fP, \fIgname\fP +User and group names, as null-terminated ASCII strings. +These should be used in preference to the uid/gid values +when they are set and the corresponding names exist on +the system. +.TP +\fIdevmajor\fP, \fIdevminor\fP +Major and minor numbers for character device or block device entry. +.TP +\fIname\fP, \fIprefix\fP +If the pathname is too long to fit in the 100 bytes provided by the standard +format, it can be split at any +\fI/\fP +character with the first portion going into the prefix field. +If the prefix field is not empty, the reader will prepend +the prefix value and a +\fI/\fP +character to the regular name field to obtain the full pathname. +The standard does not require a trailing +\fI/\fP +character on directory names, though most implementations still +include this for compatibility reasons. +.RE +.PP +Note that all unused bytes must be set to +.BR NUL. +.PP +Field termination is specified slightly differently by POSIX +than by previous implementations. +The +\fImagic\fP, +\fIuname\fP, +and +\fIgname\fP +fields must have a trailing +.BR NUL. +The +\fIpathname\fP, +\fIlinkname\fP, +and +\fIprefix\fP +fields must have a trailing +.BR NUL +unless they fill the entire field. +(In particular, it is possible to store a 256-character pathname if it +happens to have a +\fI/\fP +as the 156th character.) +POSIX requires numeric fields to be zero-padded in the front, and requires +them to be terminated with either space or +.BR NUL +characters. +.PP +Currently, most tar implementations comply with the ustar +format, occasionally extending it by adding new fields to the +blank area at the end of the header record. +.SS Numeric Extensions +There have been several attempts to extend the range of sizes +or times supported by modifying how numbers are stored in the +header. +.PP +One obvious extension to increase the size of files is to +eliminate the terminating characters from the various +numeric fields. +For example, the standard only allows the size field to contain +11 octal digits, reserving the twelfth byte for a trailing +NUL character. +Allowing 12 octal digits allows file sizes up to 64 GB. +.PP +Another extension, utilized by GNU tar, star, and other newer +\fB\%tar\fP +implementations, permits binary numbers in the standard numeric fields. +This is flagged by setting the high bit of the first byte. +The remainder of the field is treated as a signed twos-complement +value. +This permits 95-bit values for the length and time fields +and 63-bit values for the uid, gid, and device numbers. +In particular, this provides a consistent way to handle +negative time values. +GNU tar supports this extension for the +length, mtime, ctime, and atime fields. +Joerg Schilling's star program and the libarchive library support +this extension for all numeric fields. +Note that this extension is largely obsoleted by the extended +attribute record provided by the pax interchange format. +.PP +Another early GNU extension allowed base-64 values rather than octal. +This extension was short-lived and is no longer supported by any +implementation. +.SS Pax Interchange Format +There are many attributes that cannot be portably stored in a +POSIX ustar archive. +IEEE Std 1003.1-2001 (``POSIX.1'') +defined a +``pax interchange format'' +that uses two new types of entries to hold text-formatted +metadata that applies to following entries. +Note that a pax interchange format archive is a ustar archive in every +respect. +The new data is stored in ustar-compatible archive entries that use the +``x'' +or +``g'' +typeflag. +In particular, older implementations that do not fully support these +extensions will extract the metadata into regular files, where the +metadata can be examined as necessary. +.PP +An entry in a pax interchange format archive consists of one or +two standard ustar entries, each with its own header and data. +The first optional entry stores the extended attributes +for the following entry. +This optional first entry has an "x" typeflag and a size field that +indicates the total size of the extended attributes. +The extended attributes themselves are stored as a series of text-format +lines encoded in the portable UTF-8 encoding. +Each line consists of a decimal number, a space, a key string, an equals +sign, a value string, and a new line. +The decimal number indicates the length of the entire line, including the +initial length field and the trailing newline. +An example of such a field is: +.RS 4 +25 ctime=1084839148.1212\en +.RE +Keys in all lowercase are standard keys. +Vendors can add their own keys by prefixing them with an all uppercase +vendor name and a period. +Note that, unlike the historic header, numeric values are stored using +decimal, not octal. +A description of some common keys follows: +.RS 5 +.TP +\fBatime\fP, \fBctime\fP, \fBmtime\fP +File access, inode change, and modification times. +These fields can be negative or include a decimal point and a fractional value. +.TP +\fBhdrcharset\fP +The character set used by the pax extension values. +By default, all textual values in the pax extended attributes +are assumed to be in UTF-8, including pathnames, user names, +and group names. +In some cases, it is not possible to translate local +conventions into UTF-8. +If this key is present and the value is the six-character ASCII string +``BINARY'', +then all textual values are assumed to be in a platform-dependent +multi-byte encoding. +Note that there are only two valid values for this key: +``BINARY'' +or +``ISO-IR\ 10646\ 2000\ UTF-8''. +No other values are permitted by the standard, and +the latter value should generally not be used as it is the +default when this key is not specified. +In particular, this flag should not be used as a general +mechanism to allow filenames to be stored in arbitrary +encodings. +.TP +\fBuname\fP, \fBuid\fP, \fBgname\fP, \fBgid\fP +User name, group name, and numeric UID and GID values. +The user name and group name stored here are encoded in UTF8 +and can thus include non-ASCII characters. +The UID and GID fields can be of arbitrary length. +.TP +\fBlinkpath\fP +The full path of the linked-to file. +Note that this is encoded in UTF8 and can thus include non-ASCII characters. +.TP +\fBpath\fP +The full pathname of the entry. +Note that this is encoded in UTF8 and can thus include non-ASCII characters. +.TP +\fBrealtime.*\fP, \fBsecurity.*\fP +These keys are reserved and may be used for future standardization. +.TP +\fBsize\fP +The size of the file. +Note that there is no length limit on this field, allowing conforming +archives to store files much larger than the historic 8GB limit. +.TP +\fBSCHILY.*\fP +Vendor-specific attributes used by Joerg Schilling's +\fB\%star\fP +implementation. +.TP +\fBSCHILY.acl.access\fP, \fBSCHILY.acl.default\fP, \fBSCHILY.acl.ace\fP +Stores the access, default and NFSv4 ACLs as textual strings in a format +that is an extension of the format specified by POSIX.1e draft 17. +In particular, each user or group access specification can include +an additional colon-separated field with the numeric UID or GID. +This allows ACLs to be restored on systems that may not have complete +user or group information available (such as when NIS/YP or LDAP services +are temporarily unavailable). +.TP +\fBSCHILY.devminor\fP, \fBSCHILY.devmajor\fP +The full minor and major numbers for device nodes. +.TP +\fBSCHILY.fflags\fP +The file flags. +.TP +\fBSCHILY.realsize\fP +The full size of the file on disk. +XXX explain? XXX +.TP +\fBSCHILY.dev\fP, \fBSCHILY.ino\fP, \fBSCHILY.nlinks\fP +The device number, inode number, and link count for the entry. +In particular, note that a pax interchange format archive using Joerg +Schilling's +\fBSCHILY.*\fP +extensions can store all of the data from +\fIstruct\fP stat. +.TP +\fBLIBARCHIVE.*\fP +Vendor-specific attributes used by the +\fB\%libarchive\fP +library and programs that use it. +.TP +\fBLIBARCHIVE.creationtime\fP +The time when the file was created. +(This should not be confused with the POSIX +``ctime'' +attribute, which refers to the time when the file +metadata was last changed.) +.TP +\fBLIBARCHIVE.xattr\fP. \fInamespace\fP. \fIkey\fP +Libarchive stores POSIX.1e-style extended attributes using +keys of this form. +The +\fIkey\fP +value is URL-encoded: +All non-ASCII characters and the two special characters +``='' +and +``%'' +are encoded as +``%'' +followed by two uppercase hexadecimal digits. +The value of this key is the extended attribute value +encoded in base 64. +XXX Detail the base-64 format here XXX +.TP +\fBVENDOR.*\fP +XXX document other vendor-specific extensions XXX +.RE +.PP +Any values stored in an extended attribute override the corresponding +values in the regular tar header. +Note that compliant readers should ignore the regular fields when they +are overridden. +This is important, as existing archivers are known to store non-compliant +values in the standard header fields in this situation. +There are no limits on length for any of these fields. +In particular, numeric fields can be arbitrarily large. +All text fields are encoded in UTF8. +Compliant writers should store only portable 7-bit ASCII characters in +the standard ustar header and use extended +attributes whenever a text value contains non-ASCII characters. +.PP +In addition to the +\fBx\fP +entry described above, the pax interchange format +also supports a +\fBg\fP +entry. +The +\fBg\fP +entry is identical in format, but specifies attributes that serve as +defaults for all subsequent archive entries. +The +\fBg\fP +entry is not widely used. +.PP +Besides the new +\fBx\fP +and +\fBg\fP +entries, the pax interchange format has a few other minor variations +from the earlier ustar format. +The most troubling one is that hardlinks are permitted to have +data following them. +This allows readers to restore any hardlink to a file without +having to rewind the archive to find an earlier entry. +However, it creates complications for robust readers, as it is no longer +clear whether or not they should ignore the size field for hardlink entries. +.SS GNU Tar Archives +The GNU tar program started with a pre-POSIX format similar to that +described earlier and has extended it using several different mechanisms: +It added new fields to the empty space in the header (some of which was later +used by POSIX for conflicting purposes); +it allowed the header to be continued over multiple records; +and it defined new entries that modify following entries +(similar in principle to the +\fBx\fP +entry described above, but each GNU special entry is single-purpose, +unlike the general-purpose +\fBx\fP +entry). +As a result, GNU tar archives are not POSIX compatible, although +more lenient POSIX-compliant readers can successfully extract most +GNU tar archives. +.RS 4 +.nf +struct header_gnu_tar { + char name[100]; + char mode[8]; + char uid[8]; + char gid[8]; + char size[12]; + char mtime[12]; + char checksum[8]; + char typeflag[1]; + char linkname[100]; + char magic[6]; + char version[2]; + char uname[32]; + char gname[32]; + char devmajor[8]; + char devminor[8]; + char atime[12]; + char ctime[12]; + char offset[12]; + char longnames[4]; + char unused[1]; + struct { + char offset[12]; + char numbytes[12]; + } sparse[4]; + char isextended[1]; + char realsize[12]; + char pad[17]; +}; +.RE +.RS 5 +.TP +\fItypeflag\fP +GNU tar uses the following special entry types, in addition to +those defined by POSIX: +.RS 5 +.TP +7 +GNU tar treats type "7" records identically to type "0" records, +except on one obscure RTOS where they are used to indicate the +pre-allocation of a contiguous file on disk. +.TP +D +This indicates a directory entry. +Unlike the POSIX-standard "5" +typeflag, the header is followed by data records listing the names +of files in this directory. +Each name is preceded by an ASCII "Y" +if the file is stored in this archive or "N" if the file is not +stored in this archive. +Each name is terminated with a null, and +an extra null marks the end of the name list. +The purpose of this +entry is to support incremental backups; a program restoring from +such an archive may wish to delete files on disk that did not exist +in the directory when the archive was made. +.PP +Note that the "D" typeflag specifically violates POSIX, which requires +that unrecognized typeflags be restored as normal files. +In this case, restoring the "D" entry as a file could interfere +with subsequent creation of the like-named directory. +.TP +K +The data for this entry is a long linkname for the following regular entry. +.TP +L +The data for this entry is a long pathname for the following regular entry. +.TP +M +This is a continuation of the last file on the previous volume. +GNU multi-volume archives guarantee that each volume begins with a valid +entry header. +To ensure this, a file may be split, with part stored at the end of one volume, +and part stored at the beginning of the next volume. +The "M" typeflag indicates that this entry continues an existing file. +Such entries can only occur as the first or second entry +in an archive (the latter only if the first entry is a volume label). +The +\fIsize\fP +field specifies the size of this entry. +The +\fIoffset\fP +field at bytes 369-380 specifies the offset where this file fragment +begins. +The +\fIrealsize\fP +field specifies the total size of the file (which must equal +\fIsize\fP +plus +\fIoffset\fP). +When extracting, GNU tar checks that the header file name is the one it is +expecting, that the header offset is in the correct sequence, and that +the sum of offset and size is equal to realsize. +.TP +N +Type "N" records are no longer generated by GNU tar. +They contained a +list of files to be renamed or symlinked after extraction; this was +originally used to support long names. +The contents of this record +are a text description of the operations to be done, in the form +``Rename %s to %s\en'' +or +``Symlink %s to %s\en ;'' +in either case, both +filenames are escaped using K&R C syntax. +Due to security concerns, "N" records are now generally ignored +when reading archives. +.TP +S +This is a +``sparse'' +regular file. +Sparse files are stored as a series of fragments. +The header contains a list of fragment offset/length pairs. +If more than four such entries are required, the header is +extended as necessary with +``extra'' +header extensions (an older format that is no longer used), or +``sparse'' +extensions. +.TP +V +The +\fIname\fP +field should be interpreted as a tape/volume header name. +This entry should generally be ignored on extraction. +.RE +.TP +\fImagic\fP +The magic field holds the five characters +``ustar'' +followed by a space. +Note that POSIX ustar archives have a trailing null. +.TP +\fIversion\fP +The version field holds a space character followed by a null. +Note that POSIX ustar archives use two copies of the ASCII digit +``0''. +.TP +\fIatime\fP, \fIctime\fP +The time the file was last accessed and the time of +last change of file information, stored in octal as with +\fImtime\fP. +.TP +\fIlongnames\fP +This field is apparently no longer used. +.TP +Sparse \fIoffset\fP / \fInumbytes\fP +Each such structure specifies a single fragment of a sparse +file. +The two fields store values as octal numbers. +The fragments are each padded to a multiple of 512 bytes +in the archive. +On extraction, the list of fragments is collected from the +header (including any extension headers), and the data +is then read and written to the file at appropriate offsets. +.TP +\fIisextended\fP +If this is set to non-zero, the header will be followed by additional +``sparse header'' +records. +Each such record contains information about as many as 21 additional +sparse blocks as shown here: +.RS 4 +.nf +struct gnu_sparse_header { + struct { + char offset[12]; + char numbytes[12]; + } sparse[21]; + char isextended[1]; + char padding[7]; +}; +.RE +.TP +\fIrealsize\fP +A binary representation of the file's complete size, with a much larger range +than the POSIX file size. +In particular, with +\fBM\fP +type files, the current entry is only a portion of the file. +In that case, the POSIX size field will indicate the size of this +entry; the +\fIrealsize\fP +field will indicate the total size of the file. +.RE +.SS GNU tar pax archives +GNU tar 1.14 (XXX check this XXX) and later will write +pax interchange format archives when you specify the +\fB\--posix\fP +flag. +This format follows the pax interchange format closely, +using some +\fBSCHILY\fP +tags and introducing new keywords to store sparse file information. +There have been three iterations of the sparse file support, referred to +as +``0.0'', +``0.1'', +and +``1.0''. +.RS 5 +.TP +\fBGNU.sparse.numblocks\fP, \fBGNU.sparse.offset\fP, \fBGNU.sparse.numbytes\fP, \fBGNU.sparse.size\fP +The +``0.0'' +format used an initial +\fBGNU.sparse.numblocks\fP +attribute to indicate the number of blocks in the file, a pair of +\fBGNU.sparse.offset\fP +and +\fBGNU.sparse.numbytes\fP +to indicate the offset and size of each block, +and a single +\fBGNU.sparse.size\fP +to indicate the full size of the file. +This is not the same as the size in the tar header because the +latter value does not include the size of any holes. +This format required that the order of attributes be preserved and +relied on readers accepting multiple appearances of the same attribute +names, which is not officially permitted by the standards. +.TP +\fBGNU.sparse.map\fP +The +``0.1'' +format used a single attribute that stored a comma-separated +list of decimal numbers. +Each pair of numbers indicated the offset and size, respectively, +of a block of data. +This does not work well if the archive is extracted by an archiver +that does not recognize this extension, since many pax implementations +simply discard unrecognized attributes. +.TP +\fBGNU.sparse.major\fP, \fBGNU.sparse.minor\fP, \fBGNU.sparse.name\fP, \fBGNU.sparse.realsize\fP +The +``1.0'' +format stores the sparse block map in one or more 512-byte blocks +prepended to the file data in the entry body. +The pax attributes indicate the existence of this map +(via the +\fBGNU.sparse.major\fP +and +\fBGNU.sparse.minor\fP +fields) +and the full size of the file. +The +\fBGNU.sparse.name\fP +holds the true name of the file. +To avoid confusion, the name stored in the regular tar header +is a modified name so that extraction errors will be apparent +to users. +.RE +.SS Solaris Tar +XXX More Details Needed XXX +.PP +Solaris tar (beginning with SunOS XXX 5.7 ?? XXX) supports an +``extended'' +format that is fundamentally similar to pax interchange format, +with the following differences: +.RS 5 +.IP \(bu +Extended attributes are stored in an entry whose type is +\fBX\fP, +not +\fBx\fP, +as used by pax interchange format. +The detailed format of this entry appears to be the same +as detailed above for the +\fBx\fP +entry. +.IP \(bu +An additional +\fBA\fP +header is used to store an ACL for the following regular entry. +The body of this entry contains a seven-digit octal number +followed by a zero byte, followed by the +textual ACL description. +The octal value is the number of ACL entries +plus a constant that indicates the ACL type: 01000000 +for POSIX.1e ACLs and 03000000 for NFSv4 ACLs. +.RE +.SS AIX Tar +XXX More details needed XXX +.PP +AIX Tar uses a ustar-formatted header with the type +\fBA\fP +for storing coded ACL information. +Unlike the Solaris format, AIX tar writes this header after the +regular file body to which it applies. +The pathname in this header is either +\fBNFS4\fP +or +\fBAIXC\fP +to indicate the type of ACL stored. +The actual ACL is stored in platform-specific binary format. +.SS Mac OS X Tar +The tar distributed with Apple's Mac OS X stores most regular files +as two separate files in the tar archive. +The two files have the same name except that the first +one has +``._'' +prepended to the last path element. +This special file stores an AppleDouble-encoded +binary blob with additional metadata about the second file, +including ACL, extended attributes, and resources. +To recreate the original file on disk, each +separate file can be extracted and the Mac OS X +\fB\%copyfile\fP() +function can be used to unpack the separate +metadata file and apply it to th regular file. +Conversely, the same function provides a +``pack'' +option to encode the extended metadata from +a file into a separate file whose contents +can then be put into a tar archive. +.PP +Note that the Apple extended attributes interact +badly with long filenames. +Since each file is stored with the full name, +a separate set of extensions needs to be included +in the archive for each one, doubling the overhead +required for files with long names. +.SS Summary of tar type codes +The following list is a condensed summary of the type codes +used in tar header records generated by different tar implementations. +More details about specific implementations can be found above: +.RS 5 +.TP +NUL +Early tar programs stored a zero byte for regular files. +.TP +\fB0\fP +POSIX standard type code for a regular file. +.TP +\fB1\fP +POSIX standard type code for a hard link description. +.TP +\fB2\fP +POSIX standard type code for a symbolic link description. +.TP +\fB3\fP +POSIX standard type code for a character device node. +.TP +\fB4\fP +POSIX standard type code for a block device node. +.TP +\fB5\fP +POSIX standard type code for a directory. +.TP +\fB6\fP +POSIX standard type code for a FIFO. +.TP +\fB7\fP +POSIX reserved. +.TP +\fB7\fP +GNU tar used for pre-allocated files on some systems. +.TP +\fBA\fP +Solaris tar ACL description stored prior to a regular file header. +.TP +\fBA\fP +AIX tar ACL description stored after the file body. +.TP +\fBD\fP +GNU tar directory dump. +.TP +\fBK\fP +GNU tar long linkname for the following header. +.TP +\fBL\fP +GNU tar long pathname for the following header. +.TP +\fBM\fP +GNU tar multivolume marker, indicating the file is a continuation of a file from the previous volume. +.TP +\fBN\fP +GNU tar long filename support. +Deprecated. +.TP +\fBS\fP +GNU tar sparse regular file. +.TP +\fBV\fP +GNU tar tape/volume header name. +.TP +\fBX\fP +Solaris tar general-purpose extension header. +.TP +\fBg\fP +POSIX pax interchange format global extensions. +.TP +\fBx\fP +POSIX pax interchange format per-file extensions. +.RE +.SH SEE ALSO +.ad l +\fBar\fP(1), +\fBpax\fP(1), +\fBtar\fP(1) +.SH STANDARDS +.ad l +The +\fB\%tar\fP +utility is no longer a part of POSIX or the Single Unix Standard. +It last appeared in +Version 2 of the Single UNIX Specification (``SUSv2''). +It has been supplanted in subsequent standards by +\fBpax\fP(1). +The ustar format is currently part of the specification for the +\fBpax\fP(1) +utility. +The pax interchange file format is new with +IEEE Std 1003.1-2001 (``POSIX.1''). +.SH HISTORY +.ad l +A +\fB\%tar\fP +command appeared in Seventh Edition Unix, which was released in January, 1979. +It replaced the +\fB\%tp\fP +program from Fourth Edition Unix which in turn replaced the +\fB\%tap\fP +program from First Edition Unix. +John Gilmore's +\fB\%pdtar\fP +public-domain implementation (circa 1987) was highly influential +and formed the basis of +\fB\%GNU\fP tar +(circa 1988). +Joerg Shilling's +\fB\%star\fP +archiver is another open-source (CDDL) archiver (originally developed +circa 1985) which features complete support for pax interchange +format. +.PP +This documentation was written as part of the +\fB\%libarchive\fP +and +\fB\%bsdtar\fP +project by +Tim Kientzle \% diff --git a/dependencies/libarchive-3.4.2/doc/mdoc2man.awk b/dependencies/libarchive-3.4.2/doc/mdoc2man.awk new file mode 100755 index 0000000..726f628 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/mdoc2man.awk @@ -0,0 +1,391 @@ +#!/usr/bin/awk +# +# Copyright (c) 2003 Peter Stuge +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +# Dramatically overhauled by Tim Kientzle. This version almost +# handles library-style pages with Fn, Ft, etc commands. Still +# a lot of problems... + +BEGIN { + displaylines = 0 + trailer = "" + out = "" + sep = "" + nextsep = " " +} + +# Add a word with appropriate preceding whitespace +# Maintain a short queue of the expected upcoming word separators. +function add(str) { + out=out sep str + sep = nextsep + nextsep = " " +} + +# Add a word with no following whitespace +# Use for opening punctuation such as '(' +function addopen(str) { + add(str) + sep = "" +} + +# Add a word with no preceding whitespace +# Use for closing punctuation such as ')' or '.' +function addclose(str) { + sep = "" + add(str) +} + +# Add a word with no space before or after +# Use for separating punctuation such as '=' +function addpunct(str) { + sep = "" + add(str) + sep = "" +} + +# Emit the current line so far +function endline() { + addclose(trailer) + trailer = "" + if(length(out) > 0) { + print out + out="" + } + if(displaylines > 0) { + displaylines = displaylines - 1 + if (displaylines == 0) + dispend() + } + # First word on next line has no preceding whitespace + sep = "" +} + +function linecmd(cmd) { + endline() + add(cmd) + endline() +} + +function breakline() { + linecmd(".br") +} + +# Start an indented display +function dispstart() { + linecmd(".RS 4") +} + +# End an indented display +function dispend() { + linecmd(".RE") +} + +# Collect rest of input line +function wtail() { + retval="" + while(w 0) { + sub("^[ \t]*", "", l) + if (match(l, "^\"")) { + l = substr(l, 2) + o = index(l, "\"") + if (o > 0) { + w = substr(l, 1, o-1) + l = substr(l, o+1) + dest[n++] = w + } else { + dest[n++] = l + l = "" + } + } else { + o = match(l, "[ \t]") + if (o > 0) { + w = substr(l, 1, o-1) + l = substr(l, o+1) + dest[n++] = w + } else { + dest[n++] = l + l = "" + } + } + } + return n-1 +} + +! /^\./ { + out = $0 + endline() + next +} + +/^\.\\"/ { next } + +{ + sub("^\\.","") + nwords=splitwords($0, words) + # TODO: Instead of iterating 'w' over the array, have a separate + # function that returns 'next word' and use that. This will allow + # proper handling of double-quoted arguments as well. + for(w=1;w<=nwords;w++) { + if(match(words[w],"^Li$")) { # Literal; rest of line is unformatted + dispstart() + displaylines = 1 + } else if(match(words[w],"^Dl$")) { # Display literal + dispstart() + displaylines = 1 + } else if(match(words[w],"^Bd$")) { # Begin display + if(match(words[w+1],"-literal")) { + dispstart() + linecmd(".nf") + displaylines=10000 + w=nwords + } + } else if(match(words[w],"^Ed$")) { # End display + displaylines = 0 + dispend() + } else if(match(words[w],"^Ns$")) { # Suppress space after next word + nextsep = "" + } else if(match(words[w],"^No$")) { # Normal text + add(words[++w]) + } else if(match(words[w],"^Dq$")) { # Quote + addopen("``") + add(words[++w]) + while(w") + } else if(match(words[w],"^Dd$")) { + date=wtail() + next + } else if(match(words[w],"^Dt$")) { + id=wtail() + next + } else if(match(words[w],"^Ox$")) { + add("OpenBSD") + } else if(match(words[w],"^Fx$")) { + add("FreeBSD") + } else if(match(words[w],"^Nx$")) { + add("NetBSD") + } else if(match(words[w],"^St$")) { + if (match(words[w+1], "^-p1003.1$")) { + w++ + add("IEEE Std 1003.1 (``POSIX.1'')") + } else if(match(words[w+1], "^-p1003.1-96$")) { + w++ + add("ISO/IEC 9945-1:1996 (``POSIX.1'')") + } else if(match(words[w+1], "^-p1003.1-88$")) { + w++ + add("IEEE Std 1003.1-1988 (``POSIX.1'')") + } else if(match(words[w+1], "^-p1003.1-2001$")) { + w++ + add("IEEE Std 1003.1-2001 (``POSIX.1'')") + } else if(match(words[w+1], "^-susv2$")) { + w++ + add("Version 2 of the Single UNIX Specification (``SUSv2'')") + } + } else if(match(words[w],"^Ex$")) { + if (match(words[w+1], "^-std$")) { + w++ + add("The \\fB" name "\\fP utility exits 0 on success, and >0 if an error occurs.") + } + } else if(match(words[w],"^Os$")) { + add(".TH " id " \"" date "\" \"" wtail() "\"") + } else if(match(words[w],"^Sh$")) { + section=wtail() + add(".SH " section) + linecmd(".ad l") + } else if(match(words[w],"^Xr$")) { + add("\\fB" words[++w] "\\fP(" words[++w] ")" words[++w]) + } else if(match(words[w],"^Nm$")) { + if(match(section,"SYNOPSIS")) + breakline() + if(w >= nwords) + n=name + else if (match(words[w+1], "^[A-Z][a-z]$")) + n=name + else if (match(words[w+1], "^[.,;:]$")) + n=name + else { + n=words[++w] + if(!length(name)) + name=n + } + if(!length(n)) + n=name + add("\\fB\\%" n "\\fP") + } else if(match(words[w],"^Nd$")) { + add("\\- " wtail()) + } else if(match(words[w],"^Fl$")) { + add("\\fB\\-" words[++w] "\\fP") + } else if(match(words[w],"^Ar$")) { + addopen("\\fI") + if(w==nwords) + add("file ...\\fP") + else + add(words[++w] "\\fP") + } else if(match(words[w],"^Cm$")) { + add("\\fB" words[++w] "\\fP") + } else if(match(words[w],"^Op$")) { + addopen("[") + option=1 + trailer="]" trailer + } else if(match(words[w],"^Pp$")) { + linecmd(".PP") + } else if(match(words[w],"^An$")) { + endline() + } else if(match(words[w],"^Ss$")) { + add(".SS") + } else if(match(words[w],"^Ft$")) { + if (match(section, "SYNOPSIS")) { + breakline() + } + add("\\fI" wtail() "\\fP") + if (match(section, "SYNOPSIS")) { + breakline() + } + } else if(match(words[w],"^Fn$")) { + ++w + F = "\\fB\\%" words[w] "\\fP(" + Fsep = "" + while(w\\fP") + } else if(match(words[w],"^Pa$")) { + addopen("\\fI") + w++ + if(match(words[w],"^\\.")) + add("\\&") + add(words[w] "\\fP") + } else if(match(words[w],"^Dv$")) { + add(".BR") + } else if(match(words[w],"^Em|Ev$")) { + add(".IR") + } else if(match(words[w],"^Pq$")) { + addopen("(") + trailer=")" trailer + } else if(match(words[w],"^Aq$")) { + addopen("\\%<") + trailer=">" trailer + } else if(match(words[w],"^Brq$")) { + addopen("{") + trailer="}" trailer + } else if(match(words[w],"^S[xy]$")) { + add(".B " wtail()) + } else if(match(words[w],"^Ic$")) { + add("\\fB") + trailer="\\fP" trailer + } else if(match(words[w],"^Bl$")) { + oldoptlist=optlist + linecmd(".RS 5") + if(match(words[w+1],"-bullet")) + optlist=1 + else if(match(words[w+1],"-enum")) { + optlist=2 + enum=0 + } else if(match(words[w+1],"-tag")) + optlist=3 + else if(match(words[w+1],"-item")) + optlist=4 + else if(match(words[w+1],"-bullet")) + optlist=1 + w=nwords + } else if(match(words[w],"^El$")) { + linecmd(".RE") + optlist=oldoptlist + } else if(match(words[w],"^It$")&&optlist) { + if(optlist==1) + add(".IP \\(bu") + else if(optlist==2) + add(".IP " ++enum ".") + else if(optlist==3) { + add(".TP") + endline() + if(match(words[w+1],"^Pa$|^Ev$")) { + add(".B") + w++ + } + } else if(optlist==4) + add(".IP") + } else if(match(words[w],"^Xo$")) { + # TODO: Figure out how to handle this + } else if(match(words[w],"^Xc$")) { + # TODO: Figure out how to handle this + } else if(match(words[w],"^[=]$")) { + addpunct(words[w]) + } else if(match(words[w],"^[[{(]$")) { + addopen(words[w]) + } else if(match(words[w],"^[\\])}.,;:]$")) { + addclose(words[w]) + } else { + add(words[w]) + } + } + if(match(out,"^\\.[^a-zA-Z]")) + sub("^\\.","",out) + endline() +} diff --git a/dependencies/libarchive-3.4.2/doc/mdoc2wiki.awk b/dependencies/libarchive-3.4.2/doc/mdoc2wiki.awk new file mode 100755 index 0000000..eb89ba0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/mdoc2wiki.awk @@ -0,0 +1,488 @@ +#!/usr/bin/awk +# +# Copyright (c) 2003 Peter Stuge +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +# Dramatically overhauled by Tim Kientzle. This version almost +# handles library-style pages with Fn, Ft, etc commands. Still +# a lot of problems... + +BEGIN { + displaylines = 0 + listdepth = 0 + trailer = "" + out = "" + sep = "" + nextsep = " " + spaces = " " + + NORMAL_STATE = 0 + PRETAG_STATE = 1 + STATE = NORMAL_STATE +} + +# Add a word with appropriate preceding whitespace +# Maintain a short queue of the expected upcoming word separators. +function add(str) { + out=out sep str + sep = nextsep + nextsep = " " +} + +# Add a word with no following whitespace +# Use for opening punctuation such as '(' +function addopen(str) { + add(str) + sep = "" +} + +# Add a word with no preceding whitespace +# Use for closing punctuation such as ')' or '.' +function addclose(str) { + sep = "" + add(str) +} + +# Add a word with no space before or after +# Use for separating punctuation such as '=' +function addpunct(str) { + sep = "" + add(str) + sep = "" +} + +# Emit the current line so far +function endline() { + addclose(trailer) + trailer = "" + if(length(out) > 0) { + if (STATE == PRETAG_STATE) { + print out + } else { + print out " " + } + out="" + } + if(displaylines > 0) { + displaylines = displaylines - 1 + if (displaylines == 0) + dispend() + } + # First word on next line has no preceding whitespace + sep = "" +} + +function linecmd(cmd) { + endline() + add(cmd) + endline() +} + +function breakline() { + linecmd("
") +} + +function crossref(name, sect, other) { + if (name == "cpio" && sect == 1) { + n = "ManPageBsdcpio1" + } else if (name == "cpio" && sect == 5) { + n = "ManPageCpio5" + } else if (name == "mtree" && sect == 5) { + n = "ManPageMtree5" + } else if (name == "tar" && sect == 1) { + n = "ManPageBsdtar1" + } else if (name == "tar" && sect == 5) { + n = "ManPageTar5" + } else if (!match(name, "^archive") && !match(name, "^libarchive")) { + n = name "(" sect ")|http://www.freebsd.org/cgi/man.cgi?query=" name "&sektion=" sect + } else { + n = "ManPage" + numbits = split(name, namebits, "[_-]") + for (i = 1; i <= numbits; ++i) { + p = namebits[i] + n = n toupper(substr(p, 0, 1)) substr(p, 2) + } + n = n sect + } + n = "[[" n "]]" + if (length other > 0) + n = n other + return n +} + +# Start an indented display +function dispstart() { + endline() + print "```text" +} + +# End an indented display +function dispend() { + endline() + print "```" +} + +# Collect rest of input line +function wtail() { + retval="" + while(w 0) { + sub("^[ \t]*", "", l) + if (match(l, "^\"")) { + l = substr(l, 2) + o = index(l, "\"") + if (o > 0) { + w = substr(l, 1, o-1) + l = substr(l, o+1) + dest[n++] = w + } else { + dest[n++] = l + l = "" + } + } else { + o = match(l, "[ \t]") + if (o > 0) { + w = substr(l, 1, o-1) + l = substr(l, o+1) + dest[n++] = w + } else { + dest[n++] = l + l = "" + } + } + } + return n-1 +} + +! /^\./ { + out = $0 + endline() + next +} + +/^\.\\"/ { next } + +{ + gsub("\\\\e", "\\") + sub("^\\.","") + nwords=splitwords($0, words) + # TODO: Instead of iterating 'w' over the array, have a separate + # function that returns 'next word' and use that. This will allow + # proper handling of double-quoted arguments as well. + for(w=1;w<=nwords;w++) { + if(match(words[w],"^Li$")) { # Literal; rest of line is unformatted + dispstart() + displaylines = 1 + } else if(match(words[w],"^Dl$")) { # Display literal + dispstart() + displaylines = 1 + } else if(match(words[w],"^Bd$")) { # Begin display + STATE = PRETAG_STATE + if(match(words[w+1],"-literal")) { + dispstart() + displaylines=10000 + w=nwords + } + } else if(match(words[w],"^Ed$")) { # End display + displaylines = 0 + dispend() + STATE = NORMAL_STATE + } else if(match(words[w],"^Ns$")) { # Suppress space before next word + sep="" + } else if(match(words[w],"^No$")) { # Normal text + add(words[++w]) + } else if(match(words[w],"^Dq$")) { # Quote + addopen("\"") + add(words[++w]) + while(w[") + } else if(match(words[w],"^Oc$")) { + addclose("]") + } else if(match(words[w],"^Ao$")) { + addopen("<") + } else if(match(words[w],"^Ac$")) { + addclose(">") + } else if(match(words[w],"^Dd$")) { + date=wtail() + next + } else if(match(words[w],"^Dt$")) { + id=words[++w] "(" words[++w] ")" + next + } else if(match(words[w],"^Ox$")) { + add("OpenBSD") + } else if(match(words[w],"^Fx$")) { + add("FreeBSD") + } else if(match(words[w],"^Bx$")) { + add("BSD") + } else if(match(words[w],"^Nx$")) { + add("NetBSD") + } else if(match(words[w],"^St$")) { + if (match(words[w+1], "^-p1003.1$")) { + w++ + add("IEEE Std 1003.1 (``POSIX.1'')") + } else if(match(words[w+1], "^-p1003.1-96$")) { + w++ + add("ISO/IEC 9945-1:1996 (``POSIX.1'')") + } else if(match(words[w+1], "^-p1003.1-88$")) { + w++ + add("IEEE Std 1003.1-1988 (``POSIX.1'')") + } else if(match(words[w+1], "^-p1003.1-2001$")) { + w++ + add("IEEE Std 1003.1-2001 (``POSIX.1'')") + } else if(match(words[w+1], "^-susv2$")) { + w++ + add("Version 2 of the Single UNIX Specification (``SUSv2'')") + } + } else if(match(words[w],"^Ex$")) { + if (match(words[w+1], "^-std$")) { + w++ + add("The '''" name "''' utility exits 0 on success, and >0 if an error occurs.") + } + } else if(match(words[w],"^Os$")) { + add(id " manual page") + } else if(match(words[w],"^Sh$")) { + section=wtail() + linecmd("== " section " ==") + } else if(match(words[w],"^Xr$")) { + add(crossref(words[w+1], words[w+2], words[w+3])) + w = w + 3 + } else if(match(words[w],"^Nm$")) { + if(match(section,"SYNOPSIS")) + breakline() + if(w >= nwords) + n=name + else if (match(words[w+1], "^[A-Z][a-z]$")) + n=name + else if (match(words[w+1], "^[.,;:]$")) + n=name + else { + n=words[++w] + if(!length(name)) + name=n + } + if(!length(n)) + n=name + if (displaylines == 0) + add("'''" n "'''") + else + add(n) + } else if(match(words[w],"^Nd$")) { + add("- " wtail()) + } else if(match(words[w],"^Fl$")) { + addopen("-") + } else if(match(words[w],"^Ar$")) { + if(w==nwords) + add("''file ...''") + else { + ++w + gsub("<", "\\<", words[w]) + if (displaylines > 0) + add(words[w]) + else + add("''" words[w] "''") + } + } else if(match(words[w],"^Cm$")) { + ++w + if (displaylines == 0) { + add("'''" words[w] "'''") + } else + add(words[w]) + } else if(match(words[w],"^Op$")) { + addopen("[") + option=1 + trailer="]" trailer + } else if(match(words[w],"^Pp$")) { + ++w + endline() + print "" + } else if(match(words[w],"^An$")) { + if (match(words[w+1],"-nosplit")) + ++w + endline() + } else if(match(words[w],"^Ss$")) { + add("===") + trailer="===" + } else if(match(words[w],"^Ft$")) { + if (match(section, "SYNOPSIS")) { + breakline() + } + l = wtail() + add("''" l "''") + if (match(section, "SYNOPSIS")) { + breakline() + } + } else if(match(words[w],"^Fn$")) { + ++w + F = "'''" words[w] "'''(" + Fsep = "" + while(w#include <" words[w] ">'''") + } else if(match(words[w],"^Pa$")) { + w++ +# if(match(words[w],"^\\.")) +# add("\\&") + if (displaylines == 0) + add("''" words[w] "''") + else + add(words[w]) + } else if(match(words[w],"^Dv$")) { + linecmd() + } else if(match(words[w],"^Em|Ev$")) { + add(".IR") + } else if(match(words[w],"^Pq$")) { + addopen("(") + trailer=")" trailer + } else if(match(words[w],"^Aq$")) { + addopen(" <") + trailer=">" trailer + } else if(match(words[w],"^Brq$")) { + addopen("{") + trailer="}" trailer + } else if(match(words[w],"^S[xy]$")) { + add(".B " wtail()) + } else if(match(words[w],"^Tn$")) { + n=wtail() + add("'''" n "'''") + } else if(match(words[w],"^Ic$")) { + add("''") + trailer="''" trailer + } else if(match(words[w],"^Bl$")) { + ++listdepth + listnext[listdepth]="" + if(match(words[w+1],"-bullet")) { + optlist[listdepth]=1 + addopen("
    ") + listclose[listdepth]="
" + } else if(match(words[w+1],"-enum")) { + optlist[listdepth]=2 + enum=0 + addopen("
    ") + listclose[listdepth]="
" + } else if(match(words[w+1],"-tag")) { + optlist[listdepth]=3 + addopen("
") + listclose[listdepth]="
" + } else if(match(words[w+1],"-item")) { + optlist[listdepth]=4 + addopen("
    ") + listclose[listdepth]="
" + } + w=nwords + } else if(match(words[w],"^El$")) { + addclose(listnext[listdepth]) + addclose(listclose[listdepth]) + listclose[listdepth]="" + listdepth-- + } else if(match(words[w],"^It$")) { + addclose(listnext[listdepth]) + if(optlist[listdepth]==1) { + addpunct("
  • ") + listnext[listdepth] = "
  • " + } else if(optlist[listdepth]==2) { + addpunct("
  • ") + listnext[listdepth] = "
  • " + } else if(optlist[listdepth]==3) { + addpunct("
    ") + listnext[listdepth] = "
    " + if(match(words[w+1],"^Xo$")) { + # Suppress trailer + w++ + } else if(match(words[w+1],"^Pa$|^Ev$")) { + addopen("'''") + w++ + add(words[++w] "'''") + trailer = listnext[listdepth] "
    " trailer + listnext[listdepth] = "
    " + } else { + trailer = listnext[listdepth] "
    " trailer + listnext[listdepth] = "
    " + } + } else if(optlist[listdepth]==4) { + addpunct("
  • ") + listnext[listdepth] = "
  • " + } + } else if(match(words[w], "^Vt$")) { + w++ + add("''" words[w] "''") + } else if(match(words[w],"^Xo$")) { + # TODO: Figure out how to handle this + } else if(match(words[w],"^Xc$")) { + # TODO: Figure out how to handle this + if (optlist[listdepth] == 3) { + addclose(listnext[listdepth]) + addopen("
    ") + listnext[listdepth] = "
    " + } + } else if(match(words[w],"^[=]$")) { + addpunct(words[w]) + } else if(match(words[w],"^[[{(]$")) { + addopen(words[w]) + } else if(match(words[w],"^[\\])}.,;:]$")) { + addclose(words[w]) + } else { + sub("\\\\&", "", words[w]) + add(words[w]) + } + } + if(match(out,"^\\.[^a-zA-Z]")) + sub("^\\.","",out) + endline() +} diff --git a/dependencies/libarchive-3.4.2/doc/pdf/.ignore_me b/dependencies/libarchive-3.4.2/doc/pdf/.ignore_me new file mode 100644 index 0000000..d285484 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/pdf/.ignore_me @@ -0,0 +1,2 @@ +*** PLEASE DO NOT DELETE THIS FILE! *** +This file is used to track an otherwise empty directory in git. diff --git a/dependencies/libarchive-3.4.2/doc/pdf/Makefile b/dependencies/libarchive-3.4.2/doc/pdf/Makefile new file mode 100644 index 0000000..b5bf21e --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/pdf/Makefile @@ -0,0 +1,133 @@ + +default: all + + +archive_entry.3.pdf: ../../libarchive/archive_entry.3 + groff -mdoc -T ps ../../libarchive/archive_entry.3 | ps2pdf - - > archive_entry.3.pdf + +archive_entry_acl.3.pdf: ../../libarchive/archive_entry_acl.3 + groff -mdoc -T ps ../../libarchive/archive_entry_acl.3 | ps2pdf - - > archive_entry_acl.3.pdf + +archive_entry_linkify.3.pdf: ../../libarchive/archive_entry_linkify.3 + groff -mdoc -T ps ../../libarchive/archive_entry_linkify.3 | ps2pdf - - > archive_entry_linkify.3.pdf + +archive_entry_misc.3.pdf: ../../libarchive/archive_entry_misc.3 + groff -mdoc -T ps ../../libarchive/archive_entry_misc.3 | ps2pdf - - > archive_entry_misc.3.pdf + +archive_entry_paths.3.pdf: ../../libarchive/archive_entry_paths.3 + groff -mdoc -T ps ../../libarchive/archive_entry_paths.3 | ps2pdf - - > archive_entry_paths.3.pdf + +archive_entry_perms.3.pdf: ../../libarchive/archive_entry_perms.3 + groff -mdoc -T ps ../../libarchive/archive_entry_perms.3 | ps2pdf - - > archive_entry_perms.3.pdf + +archive_entry_stat.3.pdf: ../../libarchive/archive_entry_stat.3 + groff -mdoc -T ps ../../libarchive/archive_entry_stat.3 | ps2pdf - - > archive_entry_stat.3.pdf + +archive_entry_time.3.pdf: ../../libarchive/archive_entry_time.3 + groff -mdoc -T ps ../../libarchive/archive_entry_time.3 | ps2pdf - - > archive_entry_time.3.pdf + +archive_read.3.pdf: ../../libarchive/archive_read.3 + groff -mdoc -T ps ../../libarchive/archive_read.3 | ps2pdf - - > archive_read.3.pdf + +archive_read_add_passphrase.3.pdf: ../../libarchive/archive_read_add_passphrase.3 + groff -mdoc -T ps ../../libarchive/archive_read_add_passphrase.3 | ps2pdf - - > archive_read_add_passphrase.3.pdf + +archive_read_data.3.pdf: ../../libarchive/archive_read_data.3 + groff -mdoc -T ps ../../libarchive/archive_read_data.3 | ps2pdf - - > archive_read_data.3.pdf + +archive_read_disk.3.pdf: ../../libarchive/archive_read_disk.3 + groff -mdoc -T ps ../../libarchive/archive_read_disk.3 | ps2pdf - - > archive_read_disk.3.pdf + +archive_read_extract.3.pdf: ../../libarchive/archive_read_extract.3 + groff -mdoc -T ps ../../libarchive/archive_read_extract.3 | ps2pdf - - > archive_read_extract.3.pdf + +archive_read_filter.3.pdf: ../../libarchive/archive_read_filter.3 + groff -mdoc -T ps ../../libarchive/archive_read_filter.3 | ps2pdf - - > archive_read_filter.3.pdf + +archive_read_format.3.pdf: ../../libarchive/archive_read_format.3 + groff -mdoc -T ps ../../libarchive/archive_read_format.3 | ps2pdf - - > archive_read_format.3.pdf + +archive_read_free.3.pdf: ../../libarchive/archive_read_free.3 + groff -mdoc -T ps ../../libarchive/archive_read_free.3 | ps2pdf - - > archive_read_free.3.pdf + +archive_read_header.3.pdf: ../../libarchive/archive_read_header.3 + groff -mdoc -T ps ../../libarchive/archive_read_header.3 | ps2pdf - - > archive_read_header.3.pdf + +archive_read_new.3.pdf: ../../libarchive/archive_read_new.3 + groff -mdoc -T ps ../../libarchive/archive_read_new.3 | ps2pdf - - > archive_read_new.3.pdf + +archive_read_open.3.pdf: ../../libarchive/archive_read_open.3 + groff -mdoc -T ps ../../libarchive/archive_read_open.3 | ps2pdf - - > archive_read_open.3.pdf + +archive_read_set_options.3.pdf: ../../libarchive/archive_read_set_options.3 + groff -mdoc -T ps ../../libarchive/archive_read_set_options.3 | ps2pdf - - > archive_read_set_options.3.pdf + +archive_util.3.pdf: ../../libarchive/archive_util.3 + groff -mdoc -T ps ../../libarchive/archive_util.3 | ps2pdf - - > archive_util.3.pdf + +archive_write.3.pdf: ../../libarchive/archive_write.3 + groff -mdoc -T ps ../../libarchive/archive_write.3 | ps2pdf - - > archive_write.3.pdf + +archive_write_blocksize.3.pdf: ../../libarchive/archive_write_blocksize.3 + groff -mdoc -T ps ../../libarchive/archive_write_blocksize.3 | ps2pdf - - > archive_write_blocksize.3.pdf + +archive_write_data.3.pdf: ../../libarchive/archive_write_data.3 + groff -mdoc -T ps ../../libarchive/archive_write_data.3 | ps2pdf - - > archive_write_data.3.pdf + +archive_write_disk.3.pdf: ../../libarchive/archive_write_disk.3 + groff -mdoc -T ps ../../libarchive/archive_write_disk.3 | ps2pdf - - > archive_write_disk.3.pdf + +archive_write_filter.3.pdf: ../../libarchive/archive_write_filter.3 + groff -mdoc -T ps ../../libarchive/archive_write_filter.3 | ps2pdf - - > archive_write_filter.3.pdf + +archive_write_finish_entry.3.pdf: ../../libarchive/archive_write_finish_entry.3 + groff -mdoc -T ps ../../libarchive/archive_write_finish_entry.3 | ps2pdf - - > archive_write_finish_entry.3.pdf + +archive_write_format.3.pdf: ../../libarchive/archive_write_format.3 + groff -mdoc -T ps ../../libarchive/archive_write_format.3 | ps2pdf - - > archive_write_format.3.pdf + +archive_write_free.3.pdf: ../../libarchive/archive_write_free.3 + groff -mdoc -T ps ../../libarchive/archive_write_free.3 | ps2pdf - - > archive_write_free.3.pdf + +archive_write_header.3.pdf: ../../libarchive/archive_write_header.3 + groff -mdoc -T ps ../../libarchive/archive_write_header.3 | ps2pdf - - > archive_write_header.3.pdf + +archive_write_new.3.pdf: ../../libarchive/archive_write_new.3 + groff -mdoc -T ps ../../libarchive/archive_write_new.3 | ps2pdf - - > archive_write_new.3.pdf + +archive_write_open.3.pdf: ../../libarchive/archive_write_open.3 + groff -mdoc -T ps ../../libarchive/archive_write_open.3 | ps2pdf - - > archive_write_open.3.pdf + +archive_write_set_options.3.pdf: ../../libarchive/archive_write_set_options.3 + groff -mdoc -T ps ../../libarchive/archive_write_set_options.3 | ps2pdf - - > archive_write_set_options.3.pdf + +archive_write_set_passphrase.3.pdf: ../../libarchive/archive_write_set_passphrase.3 + groff -mdoc -T ps ../../libarchive/archive_write_set_passphrase.3 | ps2pdf - - > archive_write_set_passphrase.3.pdf + +cpio.5.pdf: ../../libarchive/cpio.5 + groff -mdoc -T ps ../../libarchive/cpio.5 | ps2pdf - - > cpio.5.pdf + +libarchive-formats.5.pdf: ../../libarchive/libarchive-formats.5 + groff -mdoc -T ps ../../libarchive/libarchive-formats.5 | ps2pdf - - > libarchive-formats.5.pdf + +libarchive.3.pdf: ../../libarchive/libarchive.3 + groff -mdoc -T ps ../../libarchive/libarchive.3 | ps2pdf - - > libarchive.3.pdf + +libarchive_changes.3.pdf: ../../libarchive/libarchive_changes.3 + groff -mdoc -T ps ../../libarchive/libarchive_changes.3 | ps2pdf - - > libarchive_changes.3.pdf + +libarchive_internals.3.pdf: ../../libarchive/libarchive_internals.3 + groff -mdoc -T ps ../../libarchive/libarchive_internals.3 | ps2pdf - - > libarchive_internals.3.pdf + +mtree.5.pdf: ../../libarchive/mtree.5 + groff -mdoc -T ps ../../libarchive/mtree.5 | ps2pdf - - > mtree.5.pdf + +tar.5.pdf: ../../libarchive/tar.5 + groff -mdoc -T ps ../../libarchive/tar.5 | ps2pdf - - > tar.5.pdf + +bsdtar.1.pdf: ../../tar/bsdtar.1 + groff -mdoc -T ps ../../tar/bsdtar.1 | ps2pdf - - > bsdtar.1.pdf + +bsdcpio.1.pdf: ../../cpio/bsdcpio.1 + groff -mdoc -T ps ../../cpio/bsdcpio.1 | ps2pdf - - > bsdcpio.1.pdf +all: archive_entry.3.pdf archive_entry_acl.3.pdf archive_entry_linkify.3.pdf archive_entry_misc.3.pdf archive_entry_paths.3.pdf archive_entry_perms.3.pdf archive_entry_stat.3.pdf archive_entry_time.3.pdf archive_read.3.pdf archive_read_add_passphrase.3.pdf archive_read_data.3.pdf archive_read_disk.3.pdf archive_read_extract.3.pdf archive_read_filter.3.pdf archive_read_format.3.pdf archive_read_free.3.pdf archive_read_header.3.pdf archive_read_new.3.pdf archive_read_open.3.pdf archive_read_set_options.3.pdf archive_util.3.pdf archive_write.3.pdf archive_write_blocksize.3.pdf archive_write_data.3.pdf archive_write_disk.3.pdf archive_write_filter.3.pdf archive_write_finish_entry.3.pdf archive_write_format.3.pdf archive_write_free.3.pdf archive_write_header.3.pdf archive_write_new.3.pdf archive_write_open.3.pdf archive_write_set_options.3.pdf archive_write_set_passphrase.3.pdf cpio.5.pdf libarchive-formats.5.pdf libarchive.3.pdf libarchive_changes.3.pdf libarchive_internals.3.pdf mtree.5.pdf tar.5.pdf bsdtar.1.pdf bsdcpio.1.pdf diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_entry.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_entry.3.pdf new file mode 100644 index 0000000..724b586 Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_entry.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_entry_acl.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_entry_acl.3.pdf new file mode 100644 index 0000000..7bcfc77 Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_entry_acl.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_entry_linkify.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_entry_linkify.3.pdf new file mode 100644 index 0000000..5ac98ea Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_entry_linkify.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_entry_misc.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_entry_misc.3.pdf new file mode 100644 index 0000000..728c003 Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_entry_misc.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_entry_paths.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_entry_paths.3.pdf new file mode 100644 index 0000000..0a67baa Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_entry_paths.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_entry_perms.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_entry_perms.3.pdf new file mode 100644 index 0000000..9949f9e Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_entry_perms.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_entry_stat.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_entry_stat.3.pdf new file mode 100644 index 0000000..292c88a Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_entry_stat.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_entry_time.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_entry_time.3.pdf new file mode 100644 index 0000000..53c92f9 Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_entry_time.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_read.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_read.3.pdf new file mode 100644 index 0000000..5425238 Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_read.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_read_add_passphrase.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_read_add_passphrase.3.pdf new file mode 100644 index 0000000..cff07e0 Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_read_add_passphrase.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_read_data.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_read_data.3.pdf new file mode 100644 index 0000000..6e79739 Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_read_data.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_read_disk.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_read_disk.3.pdf new file mode 100644 index 0000000..7ff8f5e Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_read_disk.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_read_extract.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_read_extract.3.pdf new file mode 100644 index 0000000..9a5cc1e Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_read_extract.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_read_filter.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_read_filter.3.pdf new file mode 100644 index 0000000..f8206b4 Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_read_filter.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_read_format.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_read_format.3.pdf new file mode 100644 index 0000000..54bf0df Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_read_format.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_read_free.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_read_free.3.pdf new file mode 100644 index 0000000..5507fde Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_read_free.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_read_header.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_read_header.3.pdf new file mode 100644 index 0000000..254272b Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_read_header.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_read_new.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_read_new.3.pdf new file mode 100644 index 0000000..34295f3 Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_read_new.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_read_open.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_read_open.3.pdf new file mode 100644 index 0000000..e9006e5 Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_read_open.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_read_set_options.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_read_set_options.3.pdf new file mode 100644 index 0000000..cc6694e Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_read_set_options.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_util.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_util.3.pdf new file mode 100644 index 0000000..b9a9060 Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_util.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_write.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_write.3.pdf new file mode 100644 index 0000000..326a1f0 Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_write.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_write_blocksize.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_write_blocksize.3.pdf new file mode 100644 index 0000000..61078a5 Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_write_blocksize.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_write_data.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_write_data.3.pdf new file mode 100644 index 0000000..ac5c443 Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_write_data.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_write_disk.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_write_disk.3.pdf new file mode 100644 index 0000000..66249b2 Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_write_disk.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_write_filter.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_write_filter.3.pdf new file mode 100644 index 0000000..ccfba0d Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_write_filter.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_write_finish_entry.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_write_finish_entry.3.pdf new file mode 100644 index 0000000..62ab88d Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_write_finish_entry.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_write_format.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_write_format.3.pdf new file mode 100644 index 0000000..e3d75a1 Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_write_format.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_write_free.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_write_free.3.pdf new file mode 100644 index 0000000..5bb87fb Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_write_free.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_write_header.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_write_header.3.pdf new file mode 100644 index 0000000..710078f Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_write_header.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_write_new.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_write_new.3.pdf new file mode 100644 index 0000000..4622de7 Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_write_new.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_write_open.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_write_open.3.pdf new file mode 100644 index 0000000..5e5bb7b Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_write_open.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_write_set_options.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_write_set_options.3.pdf new file mode 100644 index 0000000..cf7d87a Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_write_set_options.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/archive_write_set_passphrase.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/archive_write_set_passphrase.3.pdf new file mode 100644 index 0000000..e3b4ffc Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/archive_write_set_passphrase.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/bsdcpio.1.pdf b/dependencies/libarchive-3.4.2/doc/pdf/bsdcpio.1.pdf new file mode 100644 index 0000000..a9e916d Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/bsdcpio.1.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/bsdtar.1.pdf b/dependencies/libarchive-3.4.2/doc/pdf/bsdtar.1.pdf new file mode 100644 index 0000000..aaa6977 Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/bsdtar.1.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/cpio.5.pdf b/dependencies/libarchive-3.4.2/doc/pdf/cpio.5.pdf new file mode 100644 index 0000000..4119aa5 Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/cpio.5.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/libarchive-formats.5.pdf b/dependencies/libarchive-3.4.2/doc/pdf/libarchive-formats.5.pdf new file mode 100644 index 0000000..a596422 Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/libarchive-formats.5.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/libarchive.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/libarchive.3.pdf new file mode 100644 index 0000000..2bf16b5 Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/libarchive.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/libarchive_changes.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/libarchive_changes.3.pdf new file mode 100644 index 0000000..9049b7e Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/libarchive_changes.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/libarchive_internals.3.pdf b/dependencies/libarchive-3.4.2/doc/pdf/libarchive_internals.3.pdf new file mode 100644 index 0000000..9b23729 Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/libarchive_internals.3.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/mtree.5.pdf b/dependencies/libarchive-3.4.2/doc/pdf/mtree.5.pdf new file mode 100644 index 0000000..9d8b589 Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/mtree.5.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/pdf/tar.5.pdf b/dependencies/libarchive-3.4.2/doc/pdf/tar.5.pdf new file mode 100644 index 0000000..14d06c8 Binary files /dev/null and b/dependencies/libarchive-3.4.2/doc/pdf/tar.5.pdf differ diff --git a/dependencies/libarchive-3.4.2/doc/text/.ignore_me b/dependencies/libarchive-3.4.2/doc/text/.ignore_me new file mode 100644 index 0000000..d285484 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/.ignore_me @@ -0,0 +1,2 @@ +*** PLEASE DO NOT DELETE THIS FILE! *** +This file is used to track an otherwise empty directory in git. diff --git a/dependencies/libarchive-3.4.2/doc/text/Makefile b/dependencies/libarchive-3.4.2/doc/text/Makefile new file mode 100644 index 0000000..cace75d --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/Makefile @@ -0,0 +1,133 @@ + +default: all + + +archive_entry.3.txt: ../../libarchive/archive_entry.3 + nroff -mdoc ../../libarchive/archive_entry.3 | col -b > archive_entry.3.txt + +archive_entry_acl.3.txt: ../../libarchive/archive_entry_acl.3 + nroff -mdoc ../../libarchive/archive_entry_acl.3 | col -b > archive_entry_acl.3.txt + +archive_entry_linkify.3.txt: ../../libarchive/archive_entry_linkify.3 + nroff -mdoc ../../libarchive/archive_entry_linkify.3 | col -b > archive_entry_linkify.3.txt + +archive_entry_misc.3.txt: ../../libarchive/archive_entry_misc.3 + nroff -mdoc ../../libarchive/archive_entry_misc.3 | col -b > archive_entry_misc.3.txt + +archive_entry_paths.3.txt: ../../libarchive/archive_entry_paths.3 + nroff -mdoc ../../libarchive/archive_entry_paths.3 | col -b > archive_entry_paths.3.txt + +archive_entry_perms.3.txt: ../../libarchive/archive_entry_perms.3 + nroff -mdoc ../../libarchive/archive_entry_perms.3 | col -b > archive_entry_perms.3.txt + +archive_entry_stat.3.txt: ../../libarchive/archive_entry_stat.3 + nroff -mdoc ../../libarchive/archive_entry_stat.3 | col -b > archive_entry_stat.3.txt + +archive_entry_time.3.txt: ../../libarchive/archive_entry_time.3 + nroff -mdoc ../../libarchive/archive_entry_time.3 | col -b > archive_entry_time.3.txt + +archive_read.3.txt: ../../libarchive/archive_read.3 + nroff -mdoc ../../libarchive/archive_read.3 | col -b > archive_read.3.txt + +archive_read_add_passphrase.3.txt: ../../libarchive/archive_read_add_passphrase.3 + nroff -mdoc ../../libarchive/archive_read_add_passphrase.3 | col -b > archive_read_add_passphrase.3.txt + +archive_read_data.3.txt: ../../libarchive/archive_read_data.3 + nroff -mdoc ../../libarchive/archive_read_data.3 | col -b > archive_read_data.3.txt + +archive_read_disk.3.txt: ../../libarchive/archive_read_disk.3 + nroff -mdoc ../../libarchive/archive_read_disk.3 | col -b > archive_read_disk.3.txt + +archive_read_extract.3.txt: ../../libarchive/archive_read_extract.3 + nroff -mdoc ../../libarchive/archive_read_extract.3 | col -b > archive_read_extract.3.txt + +archive_read_filter.3.txt: ../../libarchive/archive_read_filter.3 + nroff -mdoc ../../libarchive/archive_read_filter.3 | col -b > archive_read_filter.3.txt + +archive_read_format.3.txt: ../../libarchive/archive_read_format.3 + nroff -mdoc ../../libarchive/archive_read_format.3 | col -b > archive_read_format.3.txt + +archive_read_free.3.txt: ../../libarchive/archive_read_free.3 + nroff -mdoc ../../libarchive/archive_read_free.3 | col -b > archive_read_free.3.txt + +archive_read_header.3.txt: ../../libarchive/archive_read_header.3 + nroff -mdoc ../../libarchive/archive_read_header.3 | col -b > archive_read_header.3.txt + +archive_read_new.3.txt: ../../libarchive/archive_read_new.3 + nroff -mdoc ../../libarchive/archive_read_new.3 | col -b > archive_read_new.3.txt + +archive_read_open.3.txt: ../../libarchive/archive_read_open.3 + nroff -mdoc ../../libarchive/archive_read_open.3 | col -b > archive_read_open.3.txt + +archive_read_set_options.3.txt: ../../libarchive/archive_read_set_options.3 + nroff -mdoc ../../libarchive/archive_read_set_options.3 | col -b > archive_read_set_options.3.txt + +archive_util.3.txt: ../../libarchive/archive_util.3 + nroff -mdoc ../../libarchive/archive_util.3 | col -b > archive_util.3.txt + +archive_write.3.txt: ../../libarchive/archive_write.3 + nroff -mdoc ../../libarchive/archive_write.3 | col -b > archive_write.3.txt + +archive_write_blocksize.3.txt: ../../libarchive/archive_write_blocksize.3 + nroff -mdoc ../../libarchive/archive_write_blocksize.3 | col -b > archive_write_blocksize.3.txt + +archive_write_data.3.txt: ../../libarchive/archive_write_data.3 + nroff -mdoc ../../libarchive/archive_write_data.3 | col -b > archive_write_data.3.txt + +archive_write_disk.3.txt: ../../libarchive/archive_write_disk.3 + nroff -mdoc ../../libarchive/archive_write_disk.3 | col -b > archive_write_disk.3.txt + +archive_write_filter.3.txt: ../../libarchive/archive_write_filter.3 + nroff -mdoc ../../libarchive/archive_write_filter.3 | col -b > archive_write_filter.3.txt + +archive_write_finish_entry.3.txt: ../../libarchive/archive_write_finish_entry.3 + nroff -mdoc ../../libarchive/archive_write_finish_entry.3 | col -b > archive_write_finish_entry.3.txt + +archive_write_format.3.txt: ../../libarchive/archive_write_format.3 + nroff -mdoc ../../libarchive/archive_write_format.3 | col -b > archive_write_format.3.txt + +archive_write_free.3.txt: ../../libarchive/archive_write_free.3 + nroff -mdoc ../../libarchive/archive_write_free.3 | col -b > archive_write_free.3.txt + +archive_write_header.3.txt: ../../libarchive/archive_write_header.3 + nroff -mdoc ../../libarchive/archive_write_header.3 | col -b > archive_write_header.3.txt + +archive_write_new.3.txt: ../../libarchive/archive_write_new.3 + nroff -mdoc ../../libarchive/archive_write_new.3 | col -b > archive_write_new.3.txt + +archive_write_open.3.txt: ../../libarchive/archive_write_open.3 + nroff -mdoc ../../libarchive/archive_write_open.3 | col -b > archive_write_open.3.txt + +archive_write_set_options.3.txt: ../../libarchive/archive_write_set_options.3 + nroff -mdoc ../../libarchive/archive_write_set_options.3 | col -b > archive_write_set_options.3.txt + +archive_write_set_passphrase.3.txt: ../../libarchive/archive_write_set_passphrase.3 + nroff -mdoc ../../libarchive/archive_write_set_passphrase.3 | col -b > archive_write_set_passphrase.3.txt + +cpio.5.txt: ../../libarchive/cpio.5 + nroff -mdoc ../../libarchive/cpio.5 | col -b > cpio.5.txt + +libarchive-formats.5.txt: ../../libarchive/libarchive-formats.5 + nroff -mdoc ../../libarchive/libarchive-formats.5 | col -b > libarchive-formats.5.txt + +libarchive.3.txt: ../../libarchive/libarchive.3 + nroff -mdoc ../../libarchive/libarchive.3 | col -b > libarchive.3.txt + +libarchive_changes.3.txt: ../../libarchive/libarchive_changes.3 + nroff -mdoc ../../libarchive/libarchive_changes.3 | col -b > libarchive_changes.3.txt + +libarchive_internals.3.txt: ../../libarchive/libarchive_internals.3 + nroff -mdoc ../../libarchive/libarchive_internals.3 | col -b > libarchive_internals.3.txt + +mtree.5.txt: ../../libarchive/mtree.5 + nroff -mdoc ../../libarchive/mtree.5 | col -b > mtree.5.txt + +tar.5.txt: ../../libarchive/tar.5 + nroff -mdoc ../../libarchive/tar.5 | col -b > tar.5.txt + +bsdtar.1.txt: ../../tar/bsdtar.1 + nroff -mdoc ../../tar/bsdtar.1 | col -b > bsdtar.1.txt + +bsdcpio.1.txt: ../../cpio/bsdcpio.1 + nroff -mdoc ../../cpio/bsdcpio.1 | col -b > bsdcpio.1.txt +all: archive_entry.3.txt archive_entry_acl.3.txt archive_entry_linkify.3.txt archive_entry_misc.3.txt archive_entry_paths.3.txt archive_entry_perms.3.txt archive_entry_stat.3.txt archive_entry_time.3.txt archive_read.3.txt archive_read_add_passphrase.3.txt archive_read_data.3.txt archive_read_disk.3.txt archive_read_extract.3.txt archive_read_filter.3.txt archive_read_format.3.txt archive_read_free.3.txt archive_read_header.3.txt archive_read_new.3.txt archive_read_open.3.txt archive_read_set_options.3.txt archive_util.3.txt archive_write.3.txt archive_write_blocksize.3.txt archive_write_data.3.txt archive_write_disk.3.txt archive_write_filter.3.txt archive_write_finish_entry.3.txt archive_write_format.3.txt archive_write_free.3.txt archive_write_header.3.txt archive_write_new.3.txt archive_write_open.3.txt archive_write_set_options.3.txt archive_write_set_passphrase.3.txt cpio.5.txt libarchive-formats.5.txt libarchive.3.txt libarchive_changes.3.txt libarchive_internals.3.txt mtree.5.txt tar.5.txt bsdtar.1.txt bsdcpio.1.txt diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_entry.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_entry.3.txt new file mode 100644 index 0000000..8e4600d --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_entry.3.txt @@ -0,0 +1,92 @@ +ARCHIVE_ENTRY(3) BSD Library Functions Manual ARCHIVE_ENTRY(3) + +NAME + archive_entry_clear, archive_entry_clone, archive_entry_free, + archive_entry_new -- functions for managing archive entry descriptions + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + struct archive_entry * + archive_entry_clear(struct archive_entry *); + + struct archive_entry * + archive_entry_clone(struct archive_entry *); + + void + archive_entry_free(struct archive_entry *); + + struct archive_entry * + archive_entry_new(void); + +DESCRIPTION + These functions create and manipulate data objects that represent entries + within an archive. You can think of a struct archive_entry as a heavy- + duty version of struct stat: it includes everything from struct stat plus + associated pathname, textual group and user names, etc. These objects + are used by libarchive(3) to represent the metadata associated with a + particular entry in an archive. + + Create and Destroy + There are functions to allocate, destroy, clear, and copy archive_entry + objects: + archive_entry_clear() + Erases the object, resetting all internal fields to the same + state as a newly-created object. This is provided to allow you + to quickly recycle objects without thrashing the heap. + archive_entry_clone() + A deep copy operation; all text fields are duplicated. + archive_entry_free() + Releases the struct archive_entry object. + archive_entry_new() + Allocate and return a blank struct archive_entry object. + + Function groups + Due to high number of functions, the accessor functions can be found in + man pages grouped by the purpose. + + archive_entry_acl(3) Access Control List manipulation + + archive_entry_paths(3) Path name manipulation + + archive_entry_perms(3) User, group and mode manipulation + + archive_entry_stat(3) Functions not in the other groups and copying + to/from struct stat. + + archive_entry_time(3) Time field manipulation + + Most of the functions set or read entries in an object. Such functions + have one of the following forms: + archive_entry_set_XXXX() + Stores the provided data in the object. In particular, for + strings, the pointer is stored, not the referenced string. + archive_entry_copy_XXXX() + As above, except that the referenced data is copied into the + object. + archive_entry_XXXX() + Returns the specified data. In the case of strings, a const- + qualified pointer to the string is returned. + String data can be set or accessed as wide character strings or normal + char strings. The functions that use wide character strings are suffixed + with _w. Note that these are different representations of the same data: + For example, if you store a narrow string and read the corresponding wide + string, the object will transparently convert formats using the current + locale. Similarly, if you store a wide string and then store a narrow + string for the same data, the previously-set wide string will be dis- + carded in favor of the new data. + +SEE ALSO + archive_entry_acl(3), archive_entry_paths(3), archive_entry_perms(3), + archive_entry_time(3), libarchive(3) + +HISTORY + The libarchive library first appeared in FreeBSD 5.3. + +AUTHORS + The libarchive library was written by Tim Kientzle . + +BSD February 2, 2012 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_entry_acl.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_entry_acl.3.txt new file mode 100644 index 0000000..34281cf --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_entry_acl.3.txt @@ -0,0 +1,291 @@ +ARCHIVE_ENTRY_ACL(3) BSD Library Functions Manual ARCHIVE_ENTRY_ACL(3) + +NAME + archive_entry_acl_add_entry, archive_entry_acl_add_entry_w, + archive_entry_acl_clear, archive_entry_acl_count, + archive_entry_acl_from_text, archive_entry_acl_from_text_w, + archive_entry_acl_next, archive_entry_acl_reset, + archive_entry_acl_to_text, archive_entry_acl_to_text_w, + archive_entry_acl_types -- functions for manipulating Access Control + Lists in archive entry descriptions + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + void + archive_entry_acl_add_entry(struct archive_entry *a, int type, + int permset, int tag, int qualifier, const char *name); + + void + archive_entry_acl_add_entry_w(struct archive_entry *a, int type, + int permset, int tag, int qualifier, const wchar_t *name); + + void + archive_entry_acl_clear(struct archive_entry *a); + + int + archive_entry_acl_count(struct archive_entry *a, int type); + + int + archive_entry_acl_from_text(struct archive_entry *a, const char *text, + int type); + + int + archive_entry_acl_from_text_w(struct archive_entry *a, + const wchar_t *text, int type); + + int + archive_entry_acl_next(struct archive_entry *a, int type, int *ret_type, + int *ret_permset, int *ret_tag, int *ret_qual, + const char **ret_name); + + int + archive_entry_acl_reset(struct archive_entry *a, int type); + + char * + archive_entry_acl_to_text(struct archive_entry *a, ssize_t *len_p, + int flags); + + wchar_t * + archive_entry_acl_to_text_w(struct archive_entry *a, ssize_t *len_p, + int flags); + + int + archive_entry_acl_types(struct archive_entry *a); + +DESCRIPTION + The ``Access Control Lists (ACLs)'' extend the standard Unix permission + model. The ACL interface of libarchive supports both POSIX.1e and NFSv4 + style ACLs. Use of ACLs is restricted by various levels of ACL support + in operating systems, file systems and archive formats. + + POSIX.1e Access Control Lists + A POSIX.1e ACL consists of a number of independent entries. Each entry + specifies the permission set as a bitmask of basic permissions. Valid + permissions in the permset are: + ARCHIVE_ENTRY_ACL_READ (r) + ARCHIVE_ENTRY_ACL_WRITE (w) + ARCHIVE_ENTRY_ACL_EXECUTE (x) + The permissions correspond to the normal Unix permissions. + + The tag specifies the principal to which the permission applies. Valid + values are: + ARCHIVE_ENTRY_ACL_USER The user specified by the name field. + ARCHIVE_ENTRY_ACL_USER_OBJ The owner of the file. + ARCHIVE_ENTRY_ACL_GROUP The group specified by the name field. + ARCHIVE_ENTRY_ACL_GROUP_OBJ The group which owns the file. + ARCHIVE_ENTRY_ACL_MASK The maximum permissions to be obtained + via group permissions. + ARCHIVE_ENTRY_ACL_OTHER Any principal who is not the file + owner or a member of the owning group. + + The principals ARCHIVE_ENTRY_ACL_USER_OBJ, ARCHIVE_ENTRY_ACL_GROUP_OBJ + and ARCHIVE_ENTRY_ACL_OTHER are equivalent to user, group and other in + the classic Unix permission model and specify non-extended ACL entries. + + All files have an access ACL (ARCHIVE_ENTRY_ACL_TYPE_ACCESS). This spec- + ifies the permissions required for access to the file itself. Directo- + ries have an additional ACL (ARCHIVE_ENTRY_ACL_TYPE_DEFAULT), which con- + trols the initial access ACL for newly-created directory entries. + + NFSv4 Access Control Lists + A NFSv4 ACL consists of multiple individual entries called Access Control + Entries (ACEs). + + There are four possible types of a NFSv4 ACE: + ARCHIVE_ENTRY_ACL_TYPE_ALLOW Allow principal to perform actions + requiring given permissions. + ARCHIVE_ENTRY_ACL_TYPE_DENY Prevent principal from performing + actions requiring given permissions. + ARCHIVE_ENTRY_ACL_TYPE_AUDIT Log access attempts by principal which + require given permissions. + ARCHIVE_ENTRY_ACL_TYPE_ALARM Trigger a system alarm on access + attempts by principal which require + given permissions. + + The tag specifies the principal to which the permission applies. Valid + values are: + ARCHIVE_ENTRY_ACL_USER The user specified by the name field. + ARCHIVE_ENTRY_ACL_USER_OBJ The owner of the file. + ARCHIVE_ENTRY_ACL_GROUP The group specified by the name field. + ARCHIVE_ENTRY_ACL_GROUP_OBJ The group which owns the file. + ARCHIVE_ENTRY_ACL_EVERYONE Any principal who is not the file + owner or a member of the owning group. + + Entries with the ARCHIVE_ENTRY_ACL_USER or ARCHIVE_ENTRY_ACL_GROUP tag + store the user and group name in the name string and optionally the user + or group ID in the qualifier integer. + + NFSv4 ACE permissions and flags are stored in the same permset bitfield. + Some permissions share the same constant and permission character but + have different effect on directories than on files. The following ACE + permissions are supported: + ARCHIVE_ENTRY_ACL_READ_DATA (r) + Read data (file). + ARCHIVE_ENTRY_ACL_LIST_DIRECTORY (r) + List entries (directory). + ARCHIVE_ENTRY_ACL_WRITE_DATA (w) + Write data (file). + ARCHIVE_ENTRY_ACL_ADD_FILE (w) + Create files (directory). + ARCHIVE_ENTRY_ACL_EXECUTE (x) + Execute file or change into a directory. + ARCHIVE_ENTRY_ACL_APPEND_DATA (p) + Append data (file). + ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY (p) + Create subdirectories (directory). + ARCHIVE_ENTRY_ACL_DELETE_CHILD (D) + Remove files and subdirectories inside a directory. + ARCHIVE_ENTRY_ACL_DELETE (d) + Remove file or directory. + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES (a) + Read file or directory attributes. + ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES (A) + Write file or directory attributes. + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS (R) + Read named file or directory attributes. + ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS (W) + Write named file or directory attributes. + ARCHIVE_ENTRY_ACL_READ_ACL (c) + Read file or directory ACL. + ARCHIVE_ENTRY_ACL_WRITE_ACL (C) + Write file or directory ACL. + ARCHIVE_ENTRY_ACL_WRITE_OWNER (o) + Change owner of a file or directory. + ARCHIVE_ENTRY_ACL_SYNCHRONIZE (s) + Use synchronous I/O. + + The following NFSv4 ACL inheritance flags are supported: + ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT (f) + Inherit parent directory ACE to files. + ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT (d) + Inherit parent directory ACE to subdirectories. + ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY (i) + Only inherit, do not apply the permission on the directory + itself. + ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT (n) + Do not propagate inherit flags. Only first-level entries + inherit ACLs. + ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS (S) + Trigger alarm or audit on successful access. + ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS (F) + Trigger alarm or audit on failed access. + ARCHIVE_ENTRY_ACL_ENTRY_INHERITED (I) + Mark that ACE was inherited. + + Functions + archive_entry_acl_add_entry() and archive_entry_acl_add_entry_w() add a + single ACL entry. For the access ACL and non-extended principals, the + classic Unix permissions are updated. An archive entry cannot contain + both POSIX.1e and NFSv4 ACL entries. + + archive_entry_acl_clear() removes all ACL entries and resets the enumera- + tion pointer. + + archive_entry_acl_count() counts the ACL entries that have the given type + mask. type can be the bitwise-or of + ARCHIVE_ENTRY_ACL_TYPE_ACCESS + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT + for POSIX.1e ACLs and + ARCHIVE_ENTRY_ACL_TYPE_ALLOW + ARCHIVE_ENTRY_ACL_TYPE_DENY + ARCHIVE_ENTRY_ACL_TYPE_AUDIT + ARCHIVE_ENTRY_ACL_TYPE_ALARM + for NFSv4 ACLs. For POSIX.1e ACLs if ARCHIVE_ENTRY_ACL_TYPE_ACCESS is + included and at least one extended ACL entry is found, the three non- + extended ACLs are added. + + archive_entry_acl_from_text() and archive_entry_acl_from_text_w() add new + (or merge with existing) ACL entries from (wide) text. The argument type + may take one of the following values: + ARCHIVE_ENTRY_ACL_TYPE_ACCESS + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT + ARCHIVE_ENTRY_ACL_TYPE_NFS4 + Supports all formats that can be created with archive_entry_acl_to_text() + or respectively archive_entry_acl_to_text_w(). Existing ACL entries are + preserved. To get a clean new ACL from text archive_entry_acl_clear() + must be called first. Entries prefixed with ``default:'' are treated as + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT unless type is + ARCHIVE_ENTRY_ACL_TYPE_NFS4. Invalid entries, non-parseable ACL entries + and entries beginning with the '#' character (comments) are skipped. + + archive_entry_acl_next() return the next entry of the ACL list. This + functions may only be called after archive_entry_acl_reset() has indi- + cated the presence of extended ACL entries. + + archive_entry_acl_reset() prepare reading the list of ACL entries with + archive_entry_acl_next(). The function returns 0 if no non-extended ACLs + are found. In this case, the access permissions should be obtained by + archive_entry_mode(3) or set using chmod(2). Otherwise, the function + returns the same value as archive_entry_acl_count(). + + archive_entry_acl_to_text() and archive_entry_acl_to_text_w() convert the + ACL entries for the given type into a (wide) string of ACL entries sepa- + rated by newline. If the pointer len_p is not NULL, then the function + shall return the length of the string (not including the NULL terminator) + in the location pointed to by len_p. The flag argument is a bitwise-or. + + The following flags are effective only on POSIX.1e ACL: + ARCHIVE_ENTRY_ACL_TYPE_ACCESS + Output access ACLs. + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT + Output POSIX.1e default ACLs. + ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT + Prefix each default ACL entry with the word ``default:''. + ARCHIVE_ENTRY_ACL_STYLE_SOLARIS + The mask and other ACLs don not contain a double colon. + + The following flags are effecive only on NFSv4 ACL: + ARCHIVE_ENTRY_ACL_STYLE_COMPACT + Do not output minus characters for unset permissions and + flags in NFSv4 ACL permission and flag fields. + + The following flags are effective on both POSIX.1e and NFSv4 ACL: + ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID + Add an additional colon-separated field containing the user + or group id. + ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA + Separate ACL entries with comma instead of newline. + + If the archive entry contains NFSv4 ACLs, all types of NFSv4 ACLs are + returned. It the entry contains POSIX.1e ACLs and none of the flags + ARCHIVE_ENTRY_ACL_TYPE_ACCESS or ARCHIVE_ENTRY_ACL_TYPE_DEFAULT are spec- + ified, both access and default entries are returned and default entries + are prefixed with ``default:''. + + archive_entry_acl_types() get ACL entry types contained in an archive + entry's ACL. As POSIX.1e and NFSv4 ACL entries cannot be mixed, this + function is a very efficient way to detect if an ACL already contains + POSIX.1e or NFSv4 ACL entries. + +RETURN VALUES + archive_entry_acl_count() and archive_entry_acl_reset() returns the num- + ber of ACL entries that match the given type mask. For POSIX.1e ACLS if + the type mask includes ARCHIVE_ENTRY_ACL_TYPE_ACCESS and at least one + extended ACL entry exists, the three classic Unix permissions are + counted. + + archive_entry_acl_from_text() and archive_entry_acl_from_text_w() return + ARCHIVE_OK if all entries were successfully parsed and ARCHIVE_WARN if + one or more entries were invalid or non-parseable. + + archive_entry_acl_next() returns ARCHIVE_OK on success, ARCHIVE_EOF if no + more ACL entries exist and ARCHIVE_WARN if archive_entry_acl_reset() has + not been called first. + + archive_entry_acl_to_text() returns a string representing the ACL entries + matching the given type and flags on success or NULL on error. + + archive_entry_acl_to_text_w() returns a wide string representing the ACL + entries matching the given type and flags on success or NULL on error. + + archive_entry_acl_types() returns a bitmask of ACL entry types or 0 if + archive entry has no ACL entries. + +SEE ALSO + archive_entry(3), libarchive(3) + +BSD February 15, 2017 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_entry_linkify.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_entry_linkify.3.txt new file mode 100644 index 0000000..abbcd61 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_entry_linkify.3.txt @@ -0,0 +1,113 @@ +ARCHIVE_ENTRY_LINKIFY(3) BSD Library Functions Manual ARCHIVE_ENTRY_LINKIFY(3) + +NAME + archive_entry_linkresolver, archive_entry_linkresolver_new, + archive_entry_linkresolver_set_strategy, archive_entry_linkresolver_free, + archive_entry_linkify -- hardlink resolver functions + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + struct archive_entry_linkresolver * + archive_entry_linkresolver_new(void); + + void + archive_entry_linkresolver_set_strategy(struct archive_entry_linkresolver *resolver, + int format); + + void + archive_entry_linkresolver_free(struct archive_entry_linkresolver *resolver); + + void + archive_entry_linkify(struct archive_entry_linkresolver *resolver, + struct archive_entry **entry, struct archive_entry **sparse); + +DESCRIPTION + Programs that want to create archives have to deal with hardlinks. + Hardlinks are handled in different ways by the archive formats. The + basic strategies are: + + 1. Ignore hardlinks and store the body for each reference (old cpio, + zip). + + 2. Store the body the first time an inode is seen (ustar, pax). + + 3. Store the body the last time an inode is seen (new cpio). + + The archive_entry_linkresolver functions help by providing a unified + interface and handling the complexity behind the scene. + + The archive_entry_linkresolver functions assume that archive_entry + instances have valid nlinks, inode and device values. The inode and + device value is used to match entries. The nlinks value is used to + determined if all references have been found and if the internal refer- + ences can be recycled. + + The archive_entry_linkresolver_new() function allocates a new link + resolver. The instance can be freed using + archive_entry_linkresolver_free(). All deferred entries are flushed and + the internal storage is freed. + + The archive_entry_linkresolver_set_strategy() function selects the opti- + mal hardlink strategy for the given format. The format code can be + obtained from archive_format(3). The function can be called more than + once, but it is recommended to flush all deferred entries first. + + The archive_entry_linkify() function is the core of + archive_entry_linkresolver. The entry() argument points to the + archive_entry that should be written. Depending on the strategy one of + the following actions is taken: + + 1. For the simple archive formats *entry is left unmodified and *sparse + is set to NULL. + + 2. For tar like archive formats, *sparse is set to NULL. If *entry is + NULL, no action is taken. If the hardlink count of *entry is larger + than 1 and the file type is a regular file or symbolic link, the + internal list is searched for a matching inode. If such an inode is + found, the link count is decremented and the file size of *entry is + set to 0 to notify that no body should be written. If no such inode + is found, a copy of the entry is added to the internal cache with a + link count reduced by one. + + 3. For new cpio like archive formats a value for *entry of NULL is used + to flush deferred entries. In that case *entry is set to an arbi- + trary deferred entry and the entry itself is removed from the inter- + nal list. If the internal list is empty, *entry is set to NULL. In + either case, *sparse is set to NULL and the function returns. If + the hardlink count of *entry is one or the file type is a directory + or device, *sparse is set to NULL and no further action is taken. + Otherwise, the internal list is searched for a matching inode. If + such an inode is not found, the entry is added to the internal list, + both *entry and *sparse are set to NULL and the function returns. + If such an inode is found, the link count is decremented. If it + remains larger than one, the existing entry on the internal list is + swapped with *entry after retaining the link count. The existing + entry is returned in *entry. If the link count reached one, the new + entry is also removed from the internal list and returned in + *sparse. Otherwise *sparse is set to NULL. + + The general usage is therefore: + + 1. For each new archive entry, call archive_entry_linkify(). + + 2. Keep in mind that the entries returned may have a size of 0 now. + + 3. If *entry is not NULL, archive it. + + 4. If *sparse is not NULL, archive it. + + 5. After all entries have been written to disk, call + archive_entry_linkify() with *entry set to NULL and archive the + returned entry as long as it is not NULL. + +RETURN VALUES + archive_entry_linkresolver_new() returns NULL on malloc(3) failures. + +SEE ALSO + archive_entry(3) + +BSD February 2, 2012 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_entry_misc.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_entry_misc.3.txt new file mode 100644 index 0000000..7cc9676 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_entry_misc.3.txt @@ -0,0 +1,36 @@ +ARCHIVE_ENTRY_MISC(3) BSD Library Functions Manual ARCHIVE_ENTRY_MISC(3) + +NAME + archive_entry_symlink_type, archive_entry_set_symlink_type -- miscella- + neous functions for manipulating properties of archive_entry + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + int + archive_entry_symlink_type(struct archive_entry *a); + + void + archive_entry_set_symlink_type(struct archive_entry *a, int); + +DESCRIPTION + The function archive_entry_symlink_type() returns and the function + archive_entry_set_symlink_type() sets the type of the symbolic link + stored in an archive entry. These functions have special meaning on + operating systems that support multiple symbolic link types (e.g. Micro- + soft Windows). + + Supported values are: + AE_SYMLINK_TYPE_UNDEFINED Symbolic link target type is not defined + (default on unix systems) + AE_SYMLINK_TYPE_FILE Symbolic link points to a file + AE_SYMLINK_TYPE_DIRECTORY Symbolic link points to a directory + +SEE ALSO + archive_entry(3), archive_entry_paths(3), archive_entry_stat(3), + libarchive(3) + +BSD April 15, 2019 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_entry_paths.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_entry_paths.3.txt new file mode 100644 index 0000000..9e639f8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_entry_paths.3.txt @@ -0,0 +1,136 @@ +ARCHIVE_ENTRY_PATHS(3) BSD Library Functions Manual ARCHIVE_ENTRY_PATHS(3) + +NAME + archive_entry_hardlink, archive_entry_hardlink_w, + archive_entry_set_hardlink, archive_entry_copy_hardlink, + archive_entry_copy_hardlink_w, archive_entry_update_hardlink_utf8, + archive_entry_set_link, archive_entry_copy_link, + archive_entry_copy_link_w, archive_entry_update_link_utf8, + archive_entry_pathname, archive_entry_pathname_w, + archive_entry_set_pathname, archive_entry_copy_pathname, + archive_entry_copy_pathname_w, archive_entry_update_pathname_utf8, + archive_entry_sourcepath, archive_entry_copy_sourcepath, + archive_entry_symlink, archive_entry_symlink_w, + archive_entry_set_symlink, archive_entry_copy_symlink, + archive_entry_copy_symlink_w, archive_entry_update_symlink_utf8 -- func- + tions for manipulating path names in archive entry descriptions + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + const char * + archive_entry_hardlink(struct archive_entry *a); + + const wchar_t * + archive_entry_hardlink_w(struct archive_entry *a); + + void + archive_entry_set_hardlink(struct archive_entry *a, const char *path); + + void + archive_entry_copy_hardlink(struct archive_entry *a, const char *path); + + void + archive_entry_copy_hardlink_w(struct archive_entry *a, const, wchar_t, + *path"); + + int + archive_entry_update_hardlink_utf8(struct archive_entry *a, + const char *path); + + void + archive_entry_set_link(struct archive_entry *a, const char *path); + + void + archive_entry_copy_link(struct archive_entry *a, const char *path); + + void + archive_entry_copy_link_w(struct archive_entry *a, const wchar_t *path); + + int + archive_entry_update_link_utf8(struct archive_entry *a, + const char *path); + + const char * + archive_entry_pathname(struct archive_entry *a); + + const wchar_t * + archive_entry_pathname_w(struct archive_entry *a); + + void + archive_entry_set_pathname(struct archive_entry *a, const char *path); + + void + archive_entry_copy_pathname(struct archive_entry *a, const char *path); + + void + archive_entry_copy_pathname_w(struct archive_entry *a, + const wchar_t *path); + + int + archive_entry_update_pathname_utf8(struct archive_entry *a, + const char *path); + + const char * + archive_entry_sourcepath(struct archive_entry *a); + + void + archive_entry_copy_sourcepath(struct archive_entry *a, const char *path); + + const char * + archive_entry_symlink(struct archive_entry *a); + + const wchar_t * + archive_entry_symlink_w(struct archive_entry *a); + + void + archive_entry_set_symlink(struct archive_entry *a, const char *path); + + void + archive_entry_copy_symlink(struct archive_entry *a, const char *path); + + void + archive_entry_copy_symlink_w(struct archive_entry *a, + const wchar_t *path); + + int + archive_entry_update_symlink_utf8(struct archive_entry *a, + const char *path); + +DESCRIPTION + Path names supported by archive_entry(3): + hardlink Destination of the hardlink. + link Update only. For a symlink, update the destination. Other- + wise, make the entry a hardlink and alter the destination for + that. + pathname Path in the archive + sourcepath Path on the disk for use by archive_read_disk(3). + symlink Destination of the symbolic link. + + Path names can be provided in one of three different ways: + + char * Multibyte strings in the current locale. + + wchar_t * Wide character strings in the current locale. The accessor + functions are named XXX_w(). + + UTF-8 Unicode strings encoded as UTF-8. These are convenience func- + tions to update both the multibyte and wide character strings + at the same time. + + The sourcepath is a pure filesystem concept and never stored in an ar- + chive directly. + + For that reason, it is only available as multibyte string. The link path + is a convenience function for conditionally setting hardlink or symlink + destination. It doesn't have a corresponding get accessor function. + + archive_entry_set_XXX() is an alias for archive_entry_copy_XXX(). + +SEE ALSO + archive_entry(3), libarchive(3) + +BSD February 2, 2012 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_entry_perms.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_entry_perms.3.txt new file mode 100644 index 0000000..e5b09ec --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_entry_perms.3.txt @@ -0,0 +1,169 @@ +ARCHIVE_ENTRY_PERMS(3) BSD Library Functions Manual ARCHIVE_ENTRY_PERMS(3) + +NAME + archive_entry_gid, archive_entry_set_gid, archive_entry_uid, + archive_entry_set_uid, archive_entry_perm, archive_entry_set_perm, + archive_entry_strmode, archive_entry_uname, archive_entry_uname_w, + archive_entry_set_uname, archive_entry_copy_uname, + archive_entry_copy_uname_w, archive_entry_update_uname_utf8, + archive_entry_gname, archive_entry_gname_w, archive_entry_set_gname, + archive_entry_copy_gname, archive_entry_copy_gname_w, + archive_entry_update_gname_utf8, archive_entry_fflags, + archive_entry_fflags_text, archive_entry_set_fflags, + archive_entry_copy_fflags_text, archive_entry_copy_fflags_text_w -- func- + tions for manipulating ownership and permissions in archive entry + descriptions + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + gid_t + archive_entry_gid(struct archive_entry *a); + + void + archive_entry_set_gid(struct archive_entry *a, gid_t gid); + + uid_t + archive_entry_uid(struct archive_entry *a); + + void + archive_entry_set_uid(struct archive_entry *a, uid_t uid); + + mode_t + archive_entry_perm(struct archive_entry *a); + + void + archive_entry_set_perm(struct archive_entry *a, mode_t mode); + + const char * + archive_entry_strmode(struct archive_entry *a); + + const char * + archive_entry_gname(struct archive_entry *a); + + const wchar_t * + archive_entry_gname_w(struct archive_entry *a); + + void + archive_entry_set_gname(struct archive_entry *a, const char *a); + + void + archive_entry_copy_gname(struct archive_entry *a, const char *name); + + void + archive_entry_copy_gname_w(struct archive_entry *a, const wchar_t *name); + + int + archive_entry_update_gname_utf8(struct archive_entry *a, + const char *name); + + const char * + archive_entry_uname(struct archive_entry *a); + + const wchar_t * + archive_entry_uname_w(struct archive_entry *a); + + void + archive_entry_set_uname(struct archive_entry *a, const char *name); + + void + archive_entry_copy_uname(struct archive_entry *a, const char *name); + + void + archive_entry_copy_uname_w(struct archive_entry *a, const wchar_t *name); + + int + archive_entry_update_uname_utf8(struct archive_entry *a, + const char *name); + + void + archive_entry_fflags(struct archive_entry *a, unsigned long *set_bits, + unsigned long *clear_bits); + + const char * + archive_entry_fflags_text(struct archive_entry *a); + + void + archive_entry_set_fflags(struct archive_entry *a, unsigned long set_bits, + unsigned long clear_bits); + + const char * + archive_entry_copy_fflags_text(struct archive_entry *a, + const char *text); + + const wchar_t * + archive_entry_copy_fflags_text_w(struct archive_entry *a, + const wchar_t *text); + +DESCRIPTION + User id, group id and mode + The functions archive_entry_uid(), archive_entry_gid(), and + archive_entry_perm() can be used to extract the user id, group id and + permission from the given entry. The corresponding functions + archive_entry_set_uid(), archive_entry_set_gid(), and + archive_entry_set_perm() store the given user id, group id and permission + in the entry. The permission is also set as a side effect of calling + archive_entry_set_mode(). + + archive_entry_strmode() returns a string representation of the permission + as used by the long mode of ls(1). + + User and group name + User and group names can be provided in one of three different ways: + + char * Multibyte strings in the current locale. + + wchar_t * Wide character strings in the current locale. The accessor + functions are named XXX_w(). + + UTF-8 Unicode strings encoded as UTF-8. These are convenience func- + tions to update both the multibyte and wide character strings + at the same time. + + archive_entry_set_XXX() is an alias for archive_entry_copy_XXX(). + + File Flags + File flags are transparently converted between a bitmap representation + and a textual format. For example, if you set the bitmap and ask for + text, the library will build a canonical text format. However, if you + set a text format and request a text format, you will get back the same + text, even if it is ill-formed. If you need to canonicalize a textual + flags string, you should first set the text form, then request the bitmap + form, then use that to set the bitmap form. Setting the bitmap format + will clear the internal text representation and force it to be recon- + structed when you next request the text form. + + The bitmap format consists of two integers, one containing bits that + should be set, the other specifying bits that should be cleared. Bits + not mentioned in either bitmap will be ignored. Usually, the bitmap of + bits to be cleared will be set to zero. In unusual circumstances, you + can force a fully-specified set of file flags by setting the bitmap of + flags to clear to the complement of the bitmap of flags to set. (This + differs from fflagstostr(3), which only includes names for set bits.) + Converting a bitmap to a textual string is a platform-specific operation; + bits that are not meaningful on the current platform will be ignored. + + The canonical text format is a comma-separated list of flag names. The + archive_entry_copy_fflags_text() and archive_entry_copy_fflags_text_w() + functions parse the provided text and set the internal bitmap values. + This is a platform-specific operation; names that are not meaningful on + the current platform will be ignored. The function returns a pointer to + the start of the first name that was not recognized, or NULL if every + name was recognized. Note that every name -- including names that follow + an unrecognized name -- will be evaluated, and the bitmaps will be set to + reflect every name that is recognized. (In particular, this differs from + strtofflags(3), which stops parsing at the first unrecognized name.) + +SEE ALSO + archive_entry(3), archive_entry_acl(3), archive_read_disk(3), + archive_write_disk(3), libarchive(3) + +BUGS + The platform types uid_t and gid_t are often 16 or 32 bit wide. In this + case it is possible that the ids can not be correctly restored from ar- + chives and get truncated. + +BSD February 2, 2012 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_entry_stat.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_entry_stat.3.txt new file mode 100644 index 0000000..ef69bb6 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_entry_stat.3.txt @@ -0,0 +1,190 @@ +ARCHIVE_ENTRY_STAT(3) BSD Library Functions Manual ARCHIVE_ENTRY_STAT(3) + +NAME + archive_entry_stat, archive_entry_copy_stat, archive_entry_filetype, + archive_entry_set_filetype, archive_entry_mode, archive_entry_set_mode, + archive_entry_size, archive_entry_size_is_set, archive_entry_set_size, + archive_entry_unset_size, archive_entry_dev, archive_entry_set_dev, + archive_entry_dev_is_set, archive_entry_devmajor, + archive_entry_set_devmajor, archive_entry_devminor, + archive_entry_set_devminor, archive_entry_ino, archive_entry_set_ino, + archive_entry_ino_is_set, archive_entry_ino64, archive_entry_set_ino64, + archive_entry_nlink, archive_entry_rdev, archive_entry_set_rdev, + archive_entry_rdevmajor, archive_entry_set_rdevmajor, + archive_entry_rdevminor, archive_entry_set_rdevminor -- accessor func- + tions for manipulating archive entry descriptions + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + const struct stat * + archive_entry_stat(struct archive_entry *a); + + void + archive_entry_copy_stat(struct archive_entry *a, const struct stat *sb); + + mode_t + archive_entry_filetype(struct archive_entry *a); + + void + archive_entry_set_filetype(struct archive_entry *a, unsigned int type); + + mode_t + archive_entry_mode(struct archive_entry *a); + + void + archive_entry_set_mode(struct archive_entry *a, mode_t mode); + + int64_t + archive_entry_size(struct archive_entry *a); + + int + archive_entry_size_is_set(struct archive_entry *a); + + void + archive_entry_set_size(struct archive_entry *a, int64_t size); + + void + archive_entry_unset_size(struct archive_entry *a); + + dev_t + archive_entry_dev(struct archive_entry *a); + + void + archive_entry_set_dev(struct archive_entry *a, dev_t dev); + + int + archive_entry_dev_is_set(struct archive_entry *a); + + dev_t + archive_entry_devmajor(struct archive_entry *a); + + void + archive_entry_set_devmajor(struct archive_entry *a, dev_t major); + + dev_t + archive_entry_devminor(struct archive_entry *a); + + void + archive_entry_set_devminor(struct archive_entry *a, dev_t minor); + + ino_t + archive_entry_ino(struct archive_entry *a); + + void + archive_entry_set_ino(struct archive_entry *a, unsigned long ino); + + int + archive_entry_ino_is_set(struct archive_entry *a); + + int64_t + archive_entry_ino64(struct archive_entry *a); + + void + archive_entry_set_ino64(struct archive_entry *a, int64_t ino); + + unsigned int + archive_entry_nlink(struct archive_entry *a); + + void + archive_entry_set_nlink(struct archive_entry *a, unsigned int count); + + dev_t + archive_entry_rdev(struct archive_entry *a); + + dev_t + archive_entry_rdevmajor(struct archive_entry *a); + + dev_t + archive_entry_rdevminor(struct archive_entry *a); + + void + archive_entry_set_rdev(struct archive_entry *a, dev_t dev); + + void + archive_entry_set_rdevmajor(struct archive_entry *a, dev_t major); + + void + archive_entry_set_rdevminor(struct archive_entry *a, dev_t minor); + +DESCRIPTION + Copying to and from struct stat + The function archive_entry_stat() converts the various fields stored in + the archive entry to the format used by stat(2). The return value + remains valid until either archive_entry_clear() or archive_entry_free() + is called. It is not affected by calls to the set accessor functions. + It currently sets the following values in struct stat: st_atime, + st_ctime, st_dev, st_gid, st_ino, st_mode, st_mtime, st_nlink, st_rdev, + st_size, st_uid. In addition, st_birthtime and high-precision informa- + tion for time-related fields will be included on platforms that support + it. + + The function archive_entry_copy_stat() copies fields from the platform's + struct stat. Fields not provided by struct stat are unchanged. + + General accessor functions + The functions archive_entry_filetype() and archive_entry_set_filetype() + get respectively set the filetype. The file type is one of the following + constants: + AE_IFREG Regular file + AE_IFLNK Symbolic link + AE_IFSOCK Socket + AE_IFCHR Character device + AE_IFBLK Block device + AE_IFDIR Directory + AE_IFIFO Named pipe (fifo) + Not all file types are supported by all platforms. The constants used by + stat(2) may have different numeric values from the corresponding con- + stants above. + + The functions archive_entry_mode() and archive_entry_set_mode() get/set a + combination of file type and permissions and provide the equivalent of + st_mode. Use of archive_entry_filetype() and archive_entry_perm() for + getting and archive_entry_set_filetype() and archive_entry_set_perm() for + setting is recommended. + + The function archive_entry_size() returns the file size, if it has been + set, and 0 otherwise. archive_entry_size() can be used to query that + status. archive_entry_set_size() and archive_entry_unset_size() set and + unset the size, respectively. + + The number of references (hardlinks) can be obtained by calling + archive_entry_nlinks() and set with archive_entry_set_nlinks(). + + Identifying unique files + The functions archive_entry_dev() and archive_entry_ino64() are used by + archive_entry_linkify(3) to find hardlinks. The pair of device and inode + is supposed to identify hardlinked files. + + The device major and minor number can be obtained independently using + archive_entry_devmajor() and archive_entry_devminor(). The device can be + set either via archive_entry_set_dev() or by the combination of major and + minor number using archive_entry_set_devmajor() and + archive_entry_set_devminor(). + + The inode number can be obtained using archive_entry_ino(). This is a + legacy interface that uses the platform ino_t, which may be very small. + To set the inode number, archive_entry_set_ino64() is the preferred + interface. + + Accessor functions for block and character devices + Block and character devices are characterised either using a device num- + ber or a pair of major and minor number. The combined device number can + be obtained with archive_device_rdev() and set with + archive_device_set_rdev(). The major and minor numbers are accessed by + archive_device_rdevmajor(), archive_device_rdevminor() + archive_device_set_rdevmajor() and archive_device_set_rdevminor(). + + The process of splitting the combined device number into major and minor + number and the reverse process of combing them differs between platforms. + Some archive formats use the combined form, while other formats use the + split form. + +SEE ALSO + stat(2), archive_entry_acl(3), archive_entry_perms(3), + archive_entry_time(3), libarchive(3) + +BSD February 2, 2012 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_entry_time.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_entry_time.3.txt new file mode 100644 index 0000000..d2d5328 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_entry_time.3.txt @@ -0,0 +1,110 @@ +ARCHIVE_ENTRY_TIME(3) BSD Library Functions Manual ARCHIVE_ENTRY_TIME(3) + +NAME + archive_entry_atime, archive_entry_atime_nsec, + archive_entry_atime_is_set, archive_entry_set_atime, + archive_entry_unset_atime, archive_entry_birthtime, + archive_entry_birthtime_nsec, archive_entry_birthtime_is_set, + archive_entry_set_birthtime, archive_entry_unset_birthtime, + archive_entry_ctime, archive_entry_ctime_nsec, + archive_entry_ctime_is_set, archive_entry_set_ctime, + archive_entry_unset_ctime, archive_entry_mtime, archive_entry_mtime_nsec, + archive_entry_mtime_is_set, archive_entry_set_mtime, + archive_entry_unset_mtime -- functions for manipulating times in archive + entry descriptions + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + time_t + archive_entry_atime(struct archive_entry *a); + + long + archive_entry_atime_nsec(struct archive_entry *a); + + int + archive_entry_atime_is_set(struct archive_entry *a); + + void + archive_entry_set_atime(struct archive_entry *a, time_t sec, + long nanosec); + + void + archive_entry_unset_atime(struct archive_entry *a); + + time_t + archive_entry_birthtime(struct archive_entry *a); + + long + archive_entry_birthtime_nsec(struct archive_entry *a); + + int + archive_entry_birthtime_is_set(struct archive_entry *a); + + void + archive_entry_set_birthtime(struct archive_entry *a, time_t sec, + long nanosec); + + void + archive_entry_unset_birthtime(struct archive_entry *a); + + time_t + archive_entry_ctime(struct archive_entry *a); + + long + archive_entry_ctime_nsec(struct archive_entry *a); + + int + archive_entry_ctime_is_set(struct archive_entry *a); + + void + archive_entry_set_ctime(struct archive_entry *a, time_t sec, + long nanosec); + + void + archive_entry_unset_ctime(struct archive_entry *a); + + time_t + archive_entry_mtime(struct archive_entry *a); + + long + archive_entry_mtime_nsec(struct archive_entry *a); + + int + archive_entry_mtime_is_set(struct archive_entry *a); + + void + archive_entry_set_mtime(struct archive_entry *a, time_t sec, + long nanosec); + + void + archive_entry_unset_mtime(struct archive_entry *a); + +DESCRIPTION + These functions create and manipulate the time fields in an + archive_entry. Supported time fields are atime (access time), birthtime + (creation time), ctime (last time an inode property was changed) and + mtime (modification time). + + libarchive(3) provides a high-resolution interface. The timestamps are + truncated automatically depending on the archive format (for archiving) + or the filesystem capabilities (for restoring). + + All timestamp fields are optional. The XXX_unset() functions can be used + to mark the corresponding field as missing. The current state can be + queried using XXX_is_set(). Unset time fields have a second and nanosec- + ond field of 0. + +SEE ALSO + archive_entry(3), libarchive(3) + +HISTORY + The libarchive library first appeared in FreeBSD 5.3. + +AUTHORS + The libarchive library was written by Tim Kientzle . + +BSD February 2, 2012 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_read.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_read.3.txt new file mode 100644 index 0000000..0481d95 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_read.3.txt @@ -0,0 +1,156 @@ +ARCHIVE_READ(3) BSD Library Functions Manual ARCHIVE_READ(3) + +NAME + archive_read -- functions for reading streaming archives + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + +DESCRIPTION + These functions provide a complete API for reading streaming archives. + The general process is to first create the struct archive object, set + options, initialize the reader, iterate over the archive headers and + associated data, then close the archive and release all resources. + + Create archive object + See archive_read_new(3). + + To read an archive, you must first obtain an initialized struct archive + object from archive_read_new(). + + Enable filters and formats + See archive_read_filter(3) and archive_read_format(3). + + You can then modify this object for the desired operations with the vari- + ous archive_read_set_XXX() and archive_read_support_XXX() functions. In + particular, you will need to invoke appropriate + archive_read_support_XXX() functions to enable the corresponding compres- + sion and format support. Note that these latter functions perform two + distinct operations: they cause the corresponding support code to be + linked into your program, and they enable the corresponding auto-detect + code. Unless you have specific constraints, you will generally want to + invoke archive_read_support_filter_all() and + archive_read_support_format_all() to enable auto-detect for all formats + and compression types currently supported by the library. + + Set options + See archive_read_set_options(3). + + Open archive + See archive_read_open(3). + + Once you have prepared the struct archive object, you call + archive_read_open() to actually open the archive and prepare it for read- + ing. There are several variants of this function; the most basic expects + you to provide pointers to several functions that can provide blocks of + bytes from the archive. There are convenience forms that allow you to + specify a filename, file descriptor, FILE * object, or a block of memory + from which to read the archive data. Note that the core library makes no + assumptions about the size of the blocks read; callback functions are + free to read whatever block size is most appropriate for the medium. + + Consume archive + See archive_read_header(3), archive_read_data(3) and + archive_read_extract(3). + + Each archive entry consists of a header followed by a certain amount of + data. You can obtain the next header with archive_read_next_header(), + which returns a pointer to an struct archive_entry structure with infor- + mation about the current archive element. If the entry is a regular + file, then the header will be followed by the file data. You can use + archive_read_data() (which works much like the read(2) system call) to + read this data from the archive, or archive_read_data_block() which pro- + vides a slightly more efficient interface. You may prefer to use the + higher-level archive_read_data_skip(), which reads and discards the data + for this entry, archive_read_data_into_fd(), which copies the data to the + provided file descriptor, or archive_read_extract(), which recreates the + specified entry on disk and copies data from the archive. In particular, + note that archive_read_extract() uses the struct archive_entry structure + that you provide it, which may differ from the entry just read from the + archive. In particular, many applications will want to override the + pathname, file permissions, or ownership. + + Release resources + See archive_read_free(3). + + Once you have finished reading data from the archive, you should call + archive_read_close() to close the archive, then call archive_read_free() + to release all resources, including all memory allocated by the library. + +EXAMPLES + The following illustrates basic usage of the library. In this example, + the callback functions are simply wrappers around the standard open(2), + read(2), and close(2) system calls. + + void + list_archive(const char *name) + { + struct mydata *mydata; + struct archive *a; + struct archive_entry *entry; + + mydata = malloc(sizeof(struct mydata)); + a = archive_read_new(); + mydata->name = name; + archive_read_support_filter_all(a); + archive_read_support_format_all(a); + archive_read_open(a, mydata, myopen, myread, myclose); + while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { + printf("%s\n",archive_entry_pathname(entry)); + archive_read_data_skip(a); + } + archive_read_free(a); + free(mydata); + } + + la_ssize_t + myread(struct archive *a, void *client_data, const void **buff) + { + struct mydata *mydata = client_data; + + *buff = mydata->buff; + return (read(mydata->fd, mydata->buff, 10240)); + } + + int + myopen(struct archive *a, void *client_data) + { + struct mydata *mydata = client_data; + + mydata->fd = open(mydata->name, O_RDONLY); + return (mydata->fd >= 0 ? ARCHIVE_OK : ARCHIVE_FATAL); + } + + int + myclose(struct archive *a, void *client_data) + { + struct mydata *mydata = client_data; + + if (mydata->fd > 0) + close(mydata->fd); + return (ARCHIVE_OK); + } + +SEE ALSO + tar(1), archive_read_data(3), archive_read_extract(3), + archive_read_filter(3), archive_read_format(3), archive_read_header(3), + archive_read_new(3), archive_read_open(3), archive_read_set_options(3), + archive_util(3), libarchive(3), tar(5) + +HISTORY + The libarchive library first appeared in FreeBSD 5.3. + +AUTHORS + The libarchive library was written by Tim Kientzle . + +BUGS + Many traditional archiver programs treat empty files as valid empty ar- + chives. For example, many implementations of tar(1) allow you to append + entries to an empty file. Of course, it is impossible to determine the + format of an empty file by inspecting the contents, so this library + treats empty files as having a special ``empty'' format. + +BSD February 2, 2012 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_read_add_passphrase.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_read_add_passphrase.3.txt new file mode 100644 index 0000000..67d572e --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_read_add_passphrase.3.txt @@ -0,0 +1,35 @@ +ARCHIVE_READ_ADD_PASS... BSD Library Functions Manual ARCHIVE_READ_ADD_PASS... + +NAME + archive_read_add_passphrase, archive_read_set_passphrase_callback -- + functions for reading encrypted archives + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + int + archive_read_add_passphrase(struct archive *, const char *passphrase); + + int + archive_read_set_passphrase_callback(struct archive *, void *client_data, + archive_passphrase_callback *); + +DESCRIPTION + archive_read_add_passphrase() + Register passphrases for reading an encryption archive. If + passphrase is NULL or empty, this function will do nothing and + ARCHIVE_FAILED will be returned. Otherwise, ARCHIVE_OK will be + returned. + + archive_read_set_passphrase_callback() + Register a callback function that will be invoked to get a + passphrase for decryption after trying all the passphrases regis- + tered by the archive_read_add_passphrase() function failed. + +SEE ALSO + tar(1), archive_read(3), archive_read_set_options(3), libarchive(3) + +BSD September 14, 2014 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_read_data.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_read_data.3.txt new file mode 100644 index 0000000..9cda859 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_read_data.3.txt @@ -0,0 +1,73 @@ +ARCHIVE_READ_DATA(3) BSD Library Functions Manual ARCHIVE_READ_DATA(3) + +NAME + archive_read_data, archive_read_data_block, archive_read_data_skip, + archive_read_data_into_fd -- functions for reading streaming archives + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + la_ssize_t + archive_read_data(struct archive *, void *buff, size_t len); + + int + archive_read_data_block(struct archive *, const void **buff, size_t *len, + off_t *offset); + + int + archive_read_data_skip(struct archive *); + + int + archive_read_data_into_fd(struct archive *, int fd); + +DESCRIPTION + archive_read_data() + Read data associated with the header just read. Internally, this + is a convenience function that calls archive_read_data_block() + and fills any gaps with nulls so that callers see a single con- + tinuous stream of data. + archive_read_data_block() + Return the next available block of data for this entry. Unlike + archive_read_data(), the archive_read_data_block() function + avoids copying data and allows you to correctly handle sparse + files, as supported by some archive formats. The library guaran- + tees that offsets will increase and that blocks will not overlap. + Note that the blocks returned from this function can be much + larger than the block size read from disk, due to compression and + internal buffer optimizations. + archive_read_data_skip() + A convenience function that repeatedly calls + archive_read_data_block() to skip all of the data for this ar- + chive entry. Note that this function is invoked automatically by + archive_read_next_header2() if the previous entry was not com- + pletely consumed. + archive_read_data_into_fd() + A convenience function that repeatedly calls + archive_read_data_block() to copy the entire entry to the pro- + vided file descriptor. + +RETURN VALUES + Most functions return zero on success, non-zero on error. The possible + return codes include: ARCHIVE_OK (the operation succeeded), ARCHIVE_WARN + (the operation succeeded but a non-critical error was encountered), + ARCHIVE_EOF (end-of-archive was encountered), ARCHIVE_RETRY (the opera- + tion failed but can be retried), and ARCHIVE_FATAL (there was a fatal + error; the archive should be closed immediately). + + archive_read_data() returns a count of bytes actually read or zero at the + end of the entry. On error, a value of ARCHIVE_FATAL, ARCHIVE_WARN, or + ARCHIVE_RETRY is returned. + +ERRORS + Detailed error codes and textual descriptions are available from the + archive_errno() and archive_error_string() functions. + +SEE ALSO + tar(1), archive_read(3), archive_read_extract(3), archive_read_filter(3), + archive_read_format(3), archive_read_header(3), archive_read_open(3), + archive_read_set_options(3), archive_util(3), libarchive(3), tar(5) + +BSD February 2, 2012 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_read_disk.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_read_disk.3.txt new file mode 100644 index 0000000..925fa71 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_read_disk.3.txt @@ -0,0 +1,233 @@ +ARCHIVE_READ_DISK(3) BSD Library Functions Manual ARCHIVE_READ_DISK(3) + +NAME + archive_read_disk_new, archive_read_disk_set_behavior, + archive_read_disk_set_symlink_logical, + archive_read_disk_set_symlink_physical, + archive_read_disk_set_symlink_hybrid, archive_read_disk_entry_from_file, + archive_read_disk_gname, archive_read_disk_uname, + archive_read_disk_set_uname_lookup, archive_read_disk_set_gname_lookup, + archive_read_disk_set_standard_lookup -- functions for reading objects + from disk + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + struct archive * + archive_read_disk_new(void); + + int + archive_read_disk_set_behavior(struct archive *, int); + + int + archive_read_disk_set_symlink_logical(struct archive *); + + int + archive_read_disk_set_symlink_physical(struct archive *); + + int + archive_read_disk_set_symlink_hybrid(struct archive *); + + const char * + archive_read_disk_gname(struct archive *, gid_t); + + const char * + archive_read_disk_uname(struct archive *, uid_t); + + int + archive_read_disk_set_gname_lookup(struct archive *, void *, + const char *(*lookup)(void *, gid_t), void (*cleanup)(void *)); + + int + archive_read_disk_set_uname_lookup(struct archive *, void *, + const char *(*lookup)(void *, uid_t), void (*cleanup)(void *)); + + int + archive_read_disk_set_standard_lookup(struct archive *); + + int + archive_read_disk_entry_from_file(struct archive *, + struct archive_entry *, int fd, const struct stat *); + +DESCRIPTION + These functions provide an API for reading information about objects on + disk. In particular, they provide an interface for populating struct + archive_entry objects. + + archive_read_disk_new() + Allocates and initializes a struct archive object suitable for + reading object information from disk. + + archive_read_disk_set_behavior() + Configures various behavior options when reading entries from + disk. The flags field consists of a bitwise OR of one or more of + the following values: + ARCHIVE_READDISK_HONOR_NODUMP + Skip files and directories with the nodump file attribute + (file flag) set. By default, the nodump file attribute + is ignored. + ARCHIVE_READDISK_MAC_COPYFILE + Mac OS X specific. Read metadata (ACLs and extended + attributes) with copyfile(3). By default, metadata is + read using copyfile(3). + ARCHIVE_READDISK_NO_ACL + Do not read Access Control Lists. By default, ACLs are + read from disk. + ARCHIVE_READDISK_NO_FFLAGS + Do not read file attributes (file flags). By default, + file attributes are read from disk. See chattr(1) + (Linux) or chflags(1) (FreeBSD, Mac OS X) for more infor- + mation on file attributes. + ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS + Do not traverse mount points. By default, mount points + are traversed. + ARCHIVE_READDISK_NO_XATTR + Do not read extended file attributes (xattrs). By + default, extended file attributes are read from disk. + See xattr(7) (Linux), xattr(2) (Mac OS X), or + getextattr(8) (FreeBSD) for more information on extended + file attributes. + ARCHIVE_READDISK_RESTORE_ATIME + Restore access time of traversed files. By default, + access time of traversed files is not restored. + + archive_read_disk_set_symlink_logical(), + archive_read_disk_set_symlink_physical(), + archive_read_disk_set_symlink_hybrid() + This sets the mode used for handling symbolic links. The + ``logical'' mode follows all symbolic links. The ``physical'' + mode does not follow any symbolic links. The ``hybrid'' mode + currently behaves identically to the ``logical'' mode. + + archive_read_disk_gname(), archive_read_disk_uname() + Returns a user or group name given a gid or uid value. By + default, these always return a NULL string. + + archive_read_disk_set_gname_lookup(), + archive_read_disk_set_uname_lookup() + These allow you to override the functions used for user and group + name lookups. You may also provide a void * pointer to a private + data structure and a cleanup function for that data. The cleanup + function will be invoked when the struct archive object is + destroyed or when new lookup functions are registered. + + archive_read_disk_set_standard_lookup() + This convenience function installs a standard set of user and + group name lookup functions. These functions use getpwuid(3) and + getgrgid(3) to convert ids to names, defaulting to NULL if the + names cannot be looked up. These functions also implement a sim- + ple memory cache to reduce the number of calls to getpwuid(3) and + getgrgid(3). + + archive_read_disk_entry_from_file() + Populates a struct archive_entry object with information about a + particular file. The archive_entry object must have already been + created with archive_entry_new(3) and at least one of the source + path or path fields must already be set. (If both are set, the + source path will be used.) + + Information is read from disk using the path name from the struct + archive_entry object. If a file descriptor is provided, some + information will be obtained using that file descriptor, on plat- + forms that support the appropriate system calls. + + If a pointer to a struct stat is provided, information from that + structure will be used instead of reading from the disk where + appropriate. This can provide performance benefits in scenarios + where struct stat information has already been read from the disk + as a side effect of some other operation. (For example, direc- + tory traversal libraries often provide this information.) + + Where necessary, user and group ids are converted to user and + group names using the currently-registered lookup functions + above. This affects the file ownership fields and ACL values in + the struct archive_entry object. + More information about the struct archive object and the overall design + of the library can be found in the libarchive(3) overview. + +EXAMPLES + The following illustrates basic usage of the library by showing how to + use it to copy an item on disk into an archive. + + void + file_to_archive(struct archive *a, const char *name) + { + char buff[8192]; + size_t bytes_read; + struct archive *ard; + struct archive_entry *entry; + int fd; + + ard = archive_read_disk_new(); + archive_read_disk_set_standard_lookup(ard); + entry = archive_entry_new(); + fd = open(name, O_RDONLY); + if (fd < 0) + return; + archive_entry_copy_pathname(entry, name); + archive_read_disk_entry_from_file(ard, entry, fd, NULL); + archive_write_header(a, entry); + while ((bytes_read = read(fd, buff, sizeof(buff))) > 0) + archive_write_data(a, buff, bytes_read); + archive_write_finish_entry(a); + archive_read_free(ard); + archive_entry_free(entry); + } + +RETURN VALUES + Most functions return ARCHIVE_OK (zero) on success, or one of several + negative error codes for errors. Specific error codes include: + ARCHIVE_RETRY for operations that might succeed if retried, ARCHIVE_WARN + for unusual conditions that do not prevent further operations, and + ARCHIVE_FATAL for serious errors that make remaining operations impossi- + ble. + + archive_read_disk_new() returns a pointer to a newly-allocated struct + archive object or NULL if the allocation failed for any reason. + + archive_read_disk_gname() and archive_read_disk_uname() return const char + * pointers to the textual name or NULL if the lookup failed for any rea- + son. The returned pointer points to internal storage that may be reused + on the next call to either of these functions; callers should copy the + string if they need to continue accessing it. + +ERRORS + Detailed error codes and textual descriptions are available from the + archive_errno() and archive_error_string() functions. + +SEE ALSO + tar(1), archive_read(3), archive_util(3), archive_write(3), + archive_write_disk(3), libarchive(3) + +HISTORY + The libarchive library first appeared in FreeBSD 5.3. The + archive_read_disk interface was added to libarchive 2.6 and first + appeared in FreeBSD 8.0. + +AUTHORS + The libarchive library was written by Tim Kientzle + . + +BUGS + The ``standard'' user name and group name lookup functions are not the + defaults because getgrgid(3) and getpwuid(3) are sometimes too large for + particular applications. The current design allows the application + author to use a more compact implementation when appropriate. + + The full list of metadata read from disk by + archive_read_disk_entry_from_file() is necessarily system-dependent. + + The archive_read_disk_entry_from_file() function reads as much informa- + tion as it can from disk. Some method should be provided to limit this + so that clients who do not need ACLs, for instance, can avoid the extra + work needed to look up such information. + + This API should provide a set of methods for walking a directory tree. + That would make it a direct parallel of the archive_read(3) API. When + such methods are implemented, the ``hybrid'' symbolic link mode will make + sense. + +BSD April 3, 2017 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_read_extract.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_read_extract.3.txt new file mode 100644 index 0000000..1cccb51 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_read_extract.3.txt @@ -0,0 +1,74 @@ +ARCHIVE_READ_EXTRACT(3) BSD Library Functions Manual ARCHIVE_READ_EXTRACT(3) + +NAME + archive_read_extract, archive_read_extract2, + archive_read_extract_set_progress_callback -- functions for reading + streaming archives + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + int + archive_read_extract(struct archive *, struct archive_entry *, + int flags); + + int + archive_read_extract2(struct archive *src, struct archive_entry *, + struct archive *dest); + + void + archive_read_extract_set_progress_callback(struct archive *, + void (*func)(void *), void *user_data); + +DESCRIPTION + archive_read_extract(), archive_read_extract_set_skip_file() + A convenience function that wraps the corresponding + archive_write_disk(3) interfaces. The first call to + archive_read_extract() creates a restore object using + archive_write_disk_new(3) and + archive_write_disk_set_standard_lookup(3), then transparently + invokes archive_write_disk_set_options(3), + archive_write_header(3), archive_write_data(3), and + archive_write_finish_entry(3) to create the entry on disk and + copy data into it. The flags argument is passed unmodified to + archive_write_disk_set_options(3). + archive_read_extract2() + This is another version of archive_read_extract() that allows you + to provide your own restore object. In particular, this allows + you to override the standard lookup functions using + archive_write_disk_set_group_lookup(3), and + archive_write_disk_set_user_lookup(3). Note that + archive_read_extract2() does not accept a flags argument; you + should use archive_write_disk_set_options() to set the restore + options yourself. + archive_read_extract_set_progress_callback() + Sets a pointer to a user-defined callback that can be used for + updating progress displays during extraction. The progress func- + tion will be invoked during the extraction of large regular + files. The progress function will be invoked with the pointer + provided to this call. Generally, the data pointed to should + include a reference to the archive object and the archive_entry + object so that various statistics can be retrieved for the + progress display. + +RETURN VALUES + Most functions return zero on success, non-zero on error. The possible + return codes include: ARCHIVE_OK (the operation succeeded), ARCHIVE_WARN + (the operation succeeded but a non-critical error was encountered), + ARCHIVE_EOF (end-of-archive was encountered), ARCHIVE_RETRY (the opera- + tion failed but can be retried), and ARCHIVE_FATAL (there was a fatal + error; the archive should be closed immediately). + +ERRORS + Detailed error codes and textual descriptions are available from the + archive_errno() and archive_error_string() functions. + +SEE ALSO + tar(1), archive_read(3), archive_read_data(3), archive_read_filter(3), + archive_read_format(3), archive_read_open(3), + archive_read_set_options(3), archive_util(3), libarchive(3), tar(5) + +BSD February 2, 2012 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_read_filter.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_read_filter.3.txt new file mode 100644 index 0000000..9cfb5f8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_read_filter.3.txt @@ -0,0 +1,115 @@ +ARCHIVE_READ_FILTER(3) BSD Library Functions Manual ARCHIVE_READ_FILTER(3) + +NAME + archive_read_support_filter_all, archive_read_support_filter_bzip2, + archive_read_support_filter_compress, archive_read_support_filter_gzip, + archive_read_support_filter_lz4, archive_read_support_filter_lzma, + archive_read_support_filter_none, archive_read_support_filter_rpm, + archive_read_support_filter_uu, archive_read_support_filter_xz, + archive_read_support_filter_zstd, archive_read_support_filter_program, + archive_read_support_filter_program_signature -- functions for reading + streaming archives + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + int + archive_read_support_filter_all(struct archive *); + + int + archive_read_support_filter_bzip2(struct archive *); + + int + archive_read_support_filter_compress(struct archive *); + + int + archive_read_support_filter_grzip(struct archive *); + + int + archive_read_support_filter_gzip(struct archive *); + + int + archive_read_support_filter_lrzip(struct archive *); + + int + archive_read_support_filter_lz4(struct archive *); + + int + archive_read_support_filter_lzma(struct archive *); + + int + archive_read_support_filter_lzop(struct archive *); + + int + archive_read_support_filter_none(struct archive *); + + int + archive_read_support_filter_rpm(struct archive *); + + int + archive_read_support_filter_uu(struct archive *); + + int + archive_read_support_filter_xz(struct archive *); + + int + archive_read_support_filter_zstd(struct archive *); + + int + archive_read_support_filter_program(struct archive *, const char *cmd); + + int + archive_read_support_filter_program_signature(struct archive *, + const char *cmd, const void *signature, size_t signature_length); + +DESCRIPTION + archive_read_support_filter_bzip2(), + archive_read_support_filter_compress(), + archive_read_support_filter_grzip(), + archive_read_support_filter_gzip(), + archive_read_support_filter_lrzip(), + archive_read_support_filter_lz4(), + archive_read_support_filter_lzma(), + archive_read_support_filter_lzop(), + archive_read_support_filter_none(), + archive_read_support_filter_rpm(), + archive_read_support_filter_uu(), + archive_read_support_filter_xz(), + archive_read_support_filter_zstd(), + Enables auto-detection code and decompression support for the + specified compression. These functions may fall back on external + programs if an appropriate library was not available at build + time. Decompression using an external program is usually slower + than decompression through built-in libraries. Note that + ``none'' is always enabled by default. + archive_read_support_filter_all() + Enables all available decompression filters. + archive_read_support_filter_program() + Data is fed through the specified external program before being + dearchived. Note that this disables automatic detection of the + compression format, so it makes no sense to specify this in con- + junction with any other decompression option. + archive_read_support_filter_program_signature() + This feeds data through the specified external program but only + if the initial bytes of the data match the specified signature + value. + +RETURN VALUES + These functions return ARCHIVE_OK if the compression is fully supported, + ARCHIVE_WARN if the compression is supported only through an external + program. + + archive_read_support_filter_none() always succeeds. + +ERRORS + Detailed error codes and textual descriptions are available from the + archive_errno() and archive_error_string() functions. + +SEE ALSO + archive_read(3), archive_read_data(3), archive_read_format(3), + archive_read_format(3), libarchive(3) + +BSD August 14, 2014 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_read_format.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_read_format.3.txt new file mode 100644 index 0000000..c5eb5c7 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_read_format.3.txt @@ -0,0 +1,129 @@ +ARCHIVE_READ_FORMAT(3) BSD Library Functions Manual ARCHIVE_READ_FORMAT(3) + +NAME + archive_read_support_format_7zip, archive_read_support_format_all, + archive_read_support_format_ar, archive_read_support_format_by_code, + archive_read_support_format_cab, archive_read_support_format_cpio, + archive_read_support_format_empty, archive_read_support_format_iso9660, + archive_read_support_format_lha, archive_read_support_format_mtree, + archive_read_support_format_rar, archive_read_support_format_raw, + archive_read_support_format_tar, archive_read_support_format_xar, + archive_read_support_format_zip -- functions for reading streaming ar- + chives + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + int + archive_read_support_format_7zip(struct archive *); + + int + archive_read_support_format_all(struct archive *); + + int + archive_read_support_format_ar(struct archive *); + + int + archive_read_support_format_by_code(struct archive *, int); + + int + archive_read_support_format_cab(struct archive *); + + int + archive_read_support_format_cpio(struct archive *); + + int + archive_read_support_format_empty(struct archive *); + + int + archive_read_support_format_iso9660(struct archive *); + + int + archive_read_support_format_lha(struct archive *); + + int + archive_read_support_format_mtree(struct archive *); + + int + archive_read_support_format_rar(struct archive *); + + int + archive_read_support_format_raw(struct archive *); + + int + archive_read_support_format_tar(struct archive *); + + int + archive_read_support_format_xar(struct archive *); + + int + archive_read_support_format_zip(struct archive *); + +DESCRIPTION + archive_read_support_format_7zip(), archive_read_support_format_ar(), + archive_read_support_format_cab(), + archive_read_support_format_cpio(), + archive_read_support_format_iso9660(), + archive_read_support_format_lha(), + archive_read_support_format_mtree(), + archive_read_support_format_rar(), + archive_read_support_format_raw(), + archive_read_support_format_tar(), + archive_read_support_format_xar(), + archive_read_support_format_zip() + Enables support---including auto-detection code---for the speci- + fied archive format. For example, + archive_read_support_format_tar() enables support for a variety + of standard tar formats, old-style tar, ustar, pax interchange + format, and many common variants. + archive_read_support_format_all() + Enables support for all available formats except the ``raw'' for- + mat (see below). + archive_read_support_format_by_code() + Enables a single format specified by the format code. This can + be useful when reading a single archive twice; use + archive_format() after reading the first time and pass the + resulting code to this function to selectively enable only the + necessary format support. Note: In statically-linked executa- + bles, this will cause your program to include support for every + format. If executable size is a concern, you may wish to avoid + using this function. + archive_read_support_format_empty() + Enables support for treating empty files as empty archives. + Because empty files are valid for several different formats, it + is not possible to accurately determine a format for an empty + file based purely on contents. So empty files are treated by + libarchive as a distinct format. + archive_read_support_format_raw() + The ``raw'' format handler allows libarchive to be used to read + arbitrary data. It treats any data stream as an archive with a + single entry. The pathname of this entry is ``data''; all other + entry fields are unset. This is not enabled by + archive_read_support_format_all() in order to avoid erroneous + handling of damaged archives. + +RETURN VALUES + These functions return ARCHIVE_OK on success, or ARCHIVE_FATAL. + +ERRORS + Detailed error codes and textual descriptions are available from the + archive_errno() and archive_error_string() functions. + +SEE ALSO + tar(1), archive_read_data(3), archive_read_filter(3), + archive_read_set_options(3), archive_util(3), libarchive(3), tar(5) + +BUGS + Many traditional archiver programs treat empty files as valid empty ar- + chives. For example, many implementations of tar(1) allow you to append + entries to an empty file. Of course, it is impossible to determine the + format of an empty file by inspecting the contents, so this library + treats empty files as having a special ``empty'' format. + + Using the ``raw'' handler together with any other handler will often work + but can produce surprising results. + +BSD February 2, 2012 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_read_free.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_read_free.3.txt new file mode 100644 index 0000000..ae2ea19 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_read_free.3.txt @@ -0,0 +1,52 @@ +ARCHIVE_READ_FREE(3) BSD Library Functions Manual ARCHIVE_READ_FREE(3) + +NAME + archive_read_close, archive_read_finish, archive_read_free -- functions + for reading streaming archives + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + int + archive_read_close(struct archive *); + + int + archive_read_finish(struct archive *); + + int + archive_read_free(struct archive *); + +DESCRIPTION + archive_read_close() + Complete the archive and invoke the close callback. + archive_read_finish() + This is a deprecated synonym for archive_read_free(). The new + name was introduced with libarchive 3.0. Applications that need + to compile with either libarchive 2 or libarchive 3 should con- + tinue to use the archive_read_finish() name. Both names will be + supported until libarchive 4.0 is released, which is not expected + to occur earlier than 2013. + archive_read_free() + Invokes archive_read_close() if it was not invoked manually, then + release all resources. Note: In libarchive 1.x, this function + was declared to return void, which made it impossible to detect + certain errors when archive_read_close() was invoked implicitly + from this function. The declaration is corrected beginning with + libarchive 2.0. + +RETURN VALUES + These functions return ARCHIVE_OK on success, or ARCHIVE_FATAL. + +ERRORS + Detailed error codes and textual descriptions are available from the + archive_errno() and archive_error_string() functions. + +SEE ALSO + archive_read_data(3), archive_read_filter(3), archive_read_format(3), + archive_read_new(3), archive_read_open(3), archive_read_set_options(3), + archive_util(3), libarchive(3) + +BSD February 2, 2012 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_read_header.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_read_header.3.txt new file mode 100644 index 0000000..0998d35 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_read_header.3.txt @@ -0,0 +1,45 @@ +ARCHIVE_READ_HEADER(3) BSD Library Functions Manual ARCHIVE_READ_HEADER(3) + +NAME + archive_read_next_header, archive_read_next_header2 -- functions for + reading streaming archives + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + int + archive_read_next_header(struct archive *, struct archive_entry **); + + int + archive_read_next_header2(struct archive *, struct archive_entry *); + +DESCRIPTION + archive_read_next_header() + Read the header for the next entry and return a pointer to a + struct archive_entry. This is a convenience wrapper around + archive_read_next_header2() that reuses an internal struct + archive_entry object for each request. + archive_read_next_header2() + Read the header for the next entry and populate the provided + struct archive_entry. + +RETURN VALUES + These functions return ARCHIVE_OK (the operation succeeded), ARCHIVE_WARN + (the operation succeeded but a non-critical error was encountered), + ARCHIVE_EOF (end-of-archive was encountered), ARCHIVE_RETRY (the opera- + tion failed but can be retried), and ARCHIVE_FATAL (there was a fatal + error; the archive should be closed immediately). + +ERRORS + Detailed error codes and textual descriptions are available from the + archive_errno() and archive_error_string() functions. + +SEE ALSO + tar(1), archive_read(3), archive_read_data(3), archive_read_extract(3), + archive_read_filter(3), archive_read_format(3), archive_read_open(3), + archive_read_set_options(3), archive_util(3), libarchive(3), tar(5) + +BSD February 2, 2012 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_read_new.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_read_new.3.txt new file mode 100644 index 0000000..302bedd --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_read_new.3.txt @@ -0,0 +1,27 @@ +ARCHIVE_READ_NEW(3) BSD Library Functions Manual ARCHIVE_READ_NEW(3) + +NAME + archive_read_new -- functions for reading streaming archives + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + struct archive * + archive_read_new(void); + +DESCRIPTION + Allocates and initializes a struct archive object suitable for reading + from an archive. NULL is returned on error. + + A complete description of the struct archive object can be found in the + overview manual page for libarchive(3). + +SEE ALSO + tar(1), archive_read_data(3), archive_read_filter(3), + archive_read_format(3), archive_read_set_options(3), archive_util(3), + libarchive(3), tar(5) + +BSD February 2, 2012 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_read_open.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_read_open.3.txt new file mode 100644 index 0000000..3960485 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_read_open.3.txt @@ -0,0 +1,130 @@ +ARCHIVE_READ_OPEN(3) BSD Library Functions Manual ARCHIVE_READ_OPEN(3) + +NAME + archive_read_open, archive_read_open2, archive_read_open_fd, + archive_read_open_FILE, archive_read_open_filename, + archive_read_open_memory -- functions for reading streaming archives + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + int + archive_read_open(struct archive *, void *client_data, + archive_open_callback *, archive_read_callback *, + archive_close_callback *); + + int + archive_read_open2(struct archive *, void *client_data, + archive_open_callback *, archive_read_callback *, + archive_skip_callback *, archive_close_callback *); + + int + archive_read_open_FILE(struct archive *, FILE *file); + + int + archive_read_open_fd(struct archive *, int fd, size_t block_size); + + int + archive_read_open_filename(struct archive *, const char *filename, + size_t block_size); + + int + archive_read_open_memory(struct archive *, const void *buff, + size_t size); + +DESCRIPTION + archive_read_open() + The same as archive_read_open2(), except that the skip callback + is assumed to be NULL. + archive_read_open2() + Freeze the settings, open the archive, and prepare for reading + entries. This is the most generic version of this call, which + accepts four callback functions. Most clients will want to use + archive_read_open_filename(), archive_read_open_FILE(), + archive_read_open_fd(), or archive_read_open_memory() instead. + The library invokes the client-provided functions to obtain raw + bytes from the archive. + archive_read_open_FILE() + Like archive_read_open(), except that it accepts a FILE * + pointer. This function should not be used with tape drives or + other devices that require strict I/O blocking. + archive_read_open_fd() + Like archive_read_open(), except that it accepts a file descrip- + tor and block size rather than a set of function pointers. Note + that the file descriptor will not be automatically closed at end- + of-archive. This function is safe for use with tape drives or + other blocked devices. + archive_read_open_file() + This is a deprecated synonym for archive_read_open_filename(). + archive_read_open_filename() + Like archive_read_open(), except that it accepts a simple file- + name and a block size. A NULL filename represents standard + input. This function is safe for use with tape drives or other + blocked devices. + archive_read_open_memory() + Like archive_read_open(), except that it accepts a pointer and + size of a block of memory containing the archive data. + + A complete description of the struct archive and struct archive_entry + objects can be found in the overview manual page for libarchive(3). + +CLIENT CALLBACKS + The callback functions must match the following prototypes: + + typedef la_ssize_t archive_read_callback(struct archive *, + void *client_data, const void **buffer) + + typedef la_int64_t archive_skip_callback(struct archive *, + void *client_data, off_t request) + + typedef int archive_open_callback(struct archive *, void + *client_data) + + typedef int archive_close_callback(struct archive *, void + *client_data) + + The open callback is invoked by archive_open(). It should return + ARCHIVE_OK if the underlying file or data source is successfully opened. + If the open fails, it should call archive_set_error() to register an + error code and message and return ARCHIVE_FATAL. + + The read callback is invoked whenever the library requires raw bytes from + the archive. The read callback should read data into a buffer, set the + const void **buffer argument to point to the available data, and return a + count of the number of bytes available. The library will invoke the read + callback again only after it has consumed this data. The library imposes + no constraints on the size of the data blocks returned. On end-of-file, + the read callback should return zero. On error, the read callback should + invoke archive_set_error() to register an error code and message and + return -1. + + The skip callback is invoked when the library wants to ignore a block of + data. The return value is the number of bytes actually skipped, which + may differ from the request. If the callback cannot skip data, it should + return zero. If the skip callback is not provided (the function pointer + is NULL ), the library will invoke the read function instead and simply + discard the result. A skip callback can provide significant performance + gains when reading uncompressed archives from slow disk drives or other + media that can skip quickly. + + The close callback is invoked by archive_close when the archive process- + ing is complete. The callback should return ARCHIVE_OK on success. On + failure, the callback should invoke archive_set_error() to register an + error code and message and return ARCHIVE_FATAL. + +RETURN VALUES + These functions return ARCHIVE_OK on success, or ARCHIVE_FATAL. + +ERRORS + Detailed error codes and textual descriptions are available from the + archive_errno() and archive_error_string() functions. + +SEE ALSO + tar(1), archive_read(3), archive_read_data(3), archive_read_filter(3), + archive_read_format(3), archive_read_set_options(3), archive_util(3), + libarchive(3), tar(5) + +BSD February 2, 2012 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_read_set_options.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_read_set_options.3.txt new file mode 100644 index 0000000..ff159a2 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_read_set_options.3.txt @@ -0,0 +1,133 @@ +ARCHIVE_READ_OPTIONS(3) BSD Library Functions Manual ARCHIVE_READ_OPTIONS(3) + +NAME + archive_read_set_filter_option, archive_read_set_format_option, + archive_read_set_option, archive_read_set_options -- functions control- + ling options for reading archives + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + int + archive_read_set_filter_option(struct archive *, const char *module, + const char *option, const char *value); + + int + archive_read_set_format_option(struct archive *, const char *module, + const char *option, const char *value); + + int + archive_read_set_option(struct archive *, const char *module, + const char *option, const char *value); + + int + archive_read_set_options(struct archive *, const char *options); + +DESCRIPTION + These functions provide a way for libarchive clients to configure spe- + cific read modules. + + archive_read_set_filter_option(), archive_read_set_format_option() + Specifies an option that will be passed to currently-registered + filters (including decompression filters) or format readers. + + If option and value are both NULL, these functions will do noth- + ing and ARCHIVE_OK will be returned. If option is NULL but value + is not, these functions will do nothing and ARCHIVE_FAILED will + be returned. + + If module is not NULL, option and value will be provided to the + filter or reader named module. The return value will be that of + the module. If there is no such module, ARCHIVE_FAILED will be + returned. + + If module is NULL, option and value will be provided to every + registered module. If any module returns ARCHIVE_FATAL, this + value will be returned immediately. Otherwise, ARCHIVE_OK will + be returned if any module accepts the option, and ARCHIVE_FAILED + in all other cases. + + archive_read_set_option() + Calls archive_read_set_format_option(), then + archive_read_set_filter_option(). If either function returns + ARCHIVE_FATAL, ARCHIVE_FATAL will be returned immediately. Oth- + erwise, greater of the two values will be returned. + + archive_read_set_options() + options is a comma-separated list of options. If options is NULL + or empty, ARCHIVE_OK will be returned immediately. + + Calls archive_read_set_option() with each option in turn. If any + archive_read_set_option() call returns ARCHIVE_FATAL, + ARCHIVE_FATAL will be returned immediately. + + Individual options have one of the following forms: + option=value + The option/value pair will be provided to every module. + Modules that do not accept an option with this name will + ignore it. + option The option will be provided to every module with a value + of ``1''. + !option + The option will be provided to every module with a NULL + value. + module:option=value, module:option, module:!option + As above, but the corresponding option and value will be + provided only to modules whose name matches module. + +OPTIONS + Format cab + hdrcharset + The value is used as a character set name that will be + used when translating file names. + Format cpio + hdrcharset + The value is used as a character set name that will be + used when translating file names. + Format iso9660 + joliet Support Joliet extensions. Defaults to enabled, use + !joliet to disable. + rockridge + Support RockRidge extensions. Defaults to enabled, use + !rockridge to disable. + Format lha + hdrcharset + The value is used as a character set name that will be + used when translating file names. + Format mtree + checkfs + Allow reading information missing from the mtree from the + file system. Disabled by default. + Format rar + hdrcharset + The value is used as a character set name that will be + used when translating file names. + Format tar + compat-2x + Libarchive 2.x incorrectly encoded Unicode filenames on + some platforms. This option mimics the libarchive 2.x + filename handling so that such archives can be read cor- + rectly. + hdrcharset + The value is used as a character set name that will be + used when translating file names. + mac-ext + Support Mac OS metadata extension that records data in + special files beginning with a period and underscore. + Defaults to enabled on Mac OS, disabled on other plat- + forms. Use !mac-ext to disable. + read_concatenated_archives + Ignore zeroed blocks in the archive, which occurs when + multiple tar archives have been concatenated together. + Without this option, only the contents of the first con- + catenated archive would be read. + +ERRORS + Detailed error codes and textual descriptions are available from the + archive_errno() and archive_error_string() functions. + +SEE ALSO + tar(1), archive_read(3), archive_write_set_options(3), libarchive(3) + +BSD January 31, 2020 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_util.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_util.3.txt new file mode 100644 index 0000000..77c41bd --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_util.3.txt @@ -0,0 +1,150 @@ +ARCHIVE_UTIL(3) BSD Library Functions Manual ARCHIVE_UTIL(3) + +NAME + archive_clear_error, archive_compression, archive_compression_name, + archive_copy_error, archive_errno, archive_error_string, + archive_file_count, archive_filter_code, archive_filter_count, + archive_filter_name, archive_format, archive_format_name, + archive_position, archive_set_error -- libarchive utility functions + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + void + archive_clear_error(struct archive *); + + int + archive_compression(struct archive *); + + const char * + archive_compression_name(struct archive *); + + void + archive_copy_error(struct archive *, struct archive *); + + int + archive_errno(struct archive *); + + const char * + archive_error_string(struct archive *); + + int + archive_file_count(struct archive *); + + int + archive_filter_code(struct archive *, int); + + int + archive_filter_count(struct archive *, int); + + const char * + archive_filter_name(struct archive *, int); + + int + archive_format(struct archive *); + + const char * + archive_format_name(struct archive *); + + int64_t + archive_position(struct archive *, int); + + void + archive_set_error(struct archive *, int error_code, const char *fmt, + ...); + +DESCRIPTION + These functions provide access to various information about the struct + archive object used in the libarchive(3) library. + archive_clear_error() + Clears any error information left over from a previous call. Not + generally used in client code. + archive_compression() + Synonym for archive_filter_code(a, 0). + archive_compression_name() + Synonym for archive_filter_name(a, 0). + archive_copy_error() + Copies error information from one archive to another. + archive_errno() + Returns a numeric error code (see errno(2)) indicating the reason + for the most recent error return. Note that this can not be + reliably used to detect whether an error has occurred. It should + be used only after another libarchive function has returned an + error status. + archive_error_string() + Returns a textual error message suitable for display. The error + message here is usually more specific than that obtained from + passing the result of archive_errno() to strerror(3). + archive_file_count() + Returns a count of the number of files processed by this archive + object. The count is incremented by calls to + archive_write_header(3) or archive_read_next_header(3). + archive_filter_code() + Returns a numeric code identifying the indicated filter. See + archive_filter_count() for details of the numbering. + archive_filter_count() + Returns the number of filters in the current pipeline. For read + archive handles, these filters are added automatically by the + automatic format detection. For write archive handles, these + filters are added by calls to the various + archive_write_add_filter_XXX() functions. Filters in the result- + ing pipeline are numbered so that filter 0 is the filter closest + to the format handler. As a convenience, functions that expect a + filter number will accept -1 as a synonym for the highest-num- + bered filter. + + For example, when reading a uuencoded gzipped tar archive, there + are three filters: filter 0 is the gunzip filter, filter 1 is the + uudecode filter, and filter 2 is the pseudo-filter that wraps the + archive read functions. In this case, requesting + archive_position(a, -1) would be a synonym for + archive_position(a, 2) which would return the number of bytes + currently read from the archive, while archive_position(a, 1) + would return the number of bytes after uudecoding, and + archive_position(a, 0) would return the number of bytes after + decompression. + archive_filter_name() + Returns a textual name identifying the indicated filter. See + archive_filter_count() for details of the numbering. + archive_format() + Returns a numeric code indicating the format of the current ar- + chive entry. This value is set by a successful call to + archive_read_next_header(). Note that it is common for this + value to change from entry to entry. For example, a tar archive + might have several entries that utilize GNU tar extensions and + several entries that do not. These entries will have different + format codes. + archive_format_name() + A textual description of the format of the current entry. + archive_position() + Returns the number of bytes read from or written to the indicated + filter. In particular, archive_position(a, 0) returns the number + of bytes read or written by the format handler, while + archive_position(a, -1) returns the number of bytes read or writ- + ten to the archive. See archive_filter_count() for details of + the numbering here. + archive_set_error() + Sets the numeric error code and error description that will be + returned by archive_errno() and archive_error_string(). This + function should be used within I/O callbacks to set system-spe- + cific error codes and error descriptions. This function accepts + a printf-like format string and arguments. However, you should + be careful to use only the following printf format specifiers: + ``%c'', ``%d'', ``%jd'', ``%jo'', ``%ju'', ``%jx'', ``%ld'', + ``%lo'', ``%lu'', ``%lx'', ``%o'', ``%u'', ``%s'', ``%x'', + ``%%''. Field-width specifiers and other printf features are not + uniformly supported and should not be used. + +SEE ALSO + archive_read(3), archive_write(3), libarchive(3), printf(3) + +HISTORY + The libarchive library first appeared in FreeBSD 5.3. + +AUTHORS + The libarchive library was written by Tim Kientzle . + +BSD February 2, 2012 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_write.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_write.3.txt new file mode 100644 index 0000000..ce77dab --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_write.3.txt @@ -0,0 +1,192 @@ +ARCHIVE_WRITE(3) BSD Library Functions Manual ARCHIVE_WRITE(3) + +NAME + archive_write -- functions for creating archives + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + +DESCRIPTION + These functions provide a complete API for creating streaming archive + files. The general process is to first create the struct archive object, + set any desired options, initialize the archive, append entries, then + close the archive and release all resources. + + Create archive object + See archive_write_new(3). + + To write an archive, you must first obtain an initialized struct archive + object from archive_write_new(). + + Enable filters and formats, configure block size and padding + See archive_write_filter(3), archive_write_format(3) and + archive_write_blocksize(3). + + You can then modify this object for the desired operations with the vari- + ous archive_write_set_XXX() functions. In particular, you will need to + invoke appropriate archive_write_add_XXX() and archive_write_set_XXX() + functions to enable the corresponding compression and format support. + + Set options + See archive_write_set_options(3). + + Open archive + See archive_write_open(3). + + Once you have prepared the struct archive object, you call + archive_write_open() to actually open the archive and prepare it for + writing. There are several variants of this function; the most basic + expects you to provide pointers to several functions that can provide + blocks of bytes from the archive. There are convenience forms that allow + you to specify a filename, file descriptor, FILE * object, or a block of + memory from which to write the archive data. + + Produce archive + See archive_write_header(3) and archive_write_data(3). + + Individual archive entries are written in a three-step process: You first + initialize a struct archive_entry structure with information about the + new entry. At a minimum, you should set the pathname of the entry and + provide a struct stat with a valid st_mode field, which specifies the + type of object and st_size field, which specifies the size of the data + portion of the object. + + Release resources + See archive_write_free(3). + + After all entries have been written, use the archive_write_free() func- + tion to release all resources. + +EXAMPLES + The following sketch illustrates basic usage of the library. In this + example, the callback functions are simply wrappers around the standard + open(2), write(2), and close(2) system calls. + + #ifdef __linux__ + #define _FILE_OFFSET_BITS 64 + #endif + #include + #include + #include + #include + #include + #include + + struct mydata { + const char *name; + int fd; + }; + + int + myopen(struct archive *a, void *client_data) + { + struct mydata *mydata = client_data; + + mydata->fd = open(mydata->name, O_WRONLY | O_CREAT, 0644); + if (mydata->fd >= 0) + return (ARCHIVE_OK); + else + return (ARCHIVE_FATAL); + } + + la_ssize_t + mywrite(struct archive *a, void *client_data, const void *buff, size_t n) + { + struct mydata *mydata = client_data; + + return (write(mydata->fd, buff, n)); + } + + int + myclose(struct archive *a, void *client_data) + { + struct mydata *mydata = client_data; + + if (mydata->fd > 0) + close(mydata->fd); + return (0); + } + + void + write_archive(const char *outname, const char **filename) + { + struct mydata *mydata = malloc(sizeof(struct mydata)); + struct archive *a; + struct archive_entry *entry; + struct stat st; + char buff[8192]; + int len; + int fd; + + a = archive_write_new(); + mydata->name = outname; + /* Set archive format and filter according to output file extension. + * If it fails, set default format. Platform depended function. + * See supported formats in archive_write_set_format_filter_by_ext.c */ + if (archive_write_set_format_filter_by_ext(a, outname) != ARCHIVE_OK) { + archive_write_add_filter_gzip(a); + archive_write_set_format_ustar(a); + } + archive_write_open(a, mydata, myopen, mywrite, myclose); + while (*filename) { + stat(*filename, &st); + entry = archive_entry_new(); + archive_entry_copy_stat(entry, &st); + archive_entry_set_pathname(entry, *filename); + archive_write_header(a, entry); + if ((fd = open(*filename, O_RDONLY)) != -1) { + len = read(fd, buff, sizeof(buff)); + while (len > 0) { + archive_write_data(a, buff, len); + len = read(fd, buff, sizeof(buff)); + } + close(fd); + } + archive_entry_free(entry); + filename++; + } + archive_write_free(a); + } + + int main(int argc, const char **argv) + { + const char *outname; + argv++; + outname = *argv++; + write_archive(outname, argv); + return 0; + } + +SEE ALSO + tar(1), archive_write_set_options(3), libarchive(3), cpio(5), mtree(5), + tar(5) + +HISTORY + The libarchive library first appeared in FreeBSD 5.3. + +AUTHORS + The libarchive library was written by Tim Kientzle . + +BUGS + There are many peculiar bugs in historic tar implementations that may + cause certain programs to reject archives written by this library. For + example, several historic implementations calculated header checksums + incorrectly and will thus reject valid archives; GNU tar does not fully + support pax interchange format; some old tar implementations required + specific field terminations. + + The default pax interchange format eliminates most of the historic tar + limitations and provides a generic key/value attribute facility for ven- + dor-defined extensions. One oversight in POSIX is the failure to provide + a standard attribute for large device numbers. This library uses + ``SCHILY.devminor'' and ``SCHILY.devmajor'' for device numbers that + exceed the range supported by the backwards-compatible ustar header. + These keys are compatible with Joerg Schilling's star archiver. Other + implementations may not recognize these keys and will thus be unable to + correctly restore device nodes with large device numbers from archives + created by this library. + +BSD February 2, 2012 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_write_blocksize.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_write_blocksize.3.txt new file mode 100644 index 0000000..ee161af --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_write_blocksize.3.txt @@ -0,0 +1,74 @@ +ARCHIVE_WRITE_BLOCKSI... BSD Library Functions Manual ARCHIVE_WRITE_BLOCKSI... + +NAME + archive_write_get_bytes_per_block, archive_write_set_bytes_per_block, + archive_write_get_bytes_in_last_block, + archive_write_set_bytes_in_last_block -- functions for creating archives + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + int + archive_write_get_bytes_per_block(struct archive *); + + int + archive_write_set_bytes_per_block(struct archive *, int bytes_per_block); + + int + archive_write_get_bytes_in_last_block(struct archive *); + + int + archive_write_set_bytes_in_last_block(struct archive *, int); + +DESCRIPTION + archive_write_set_bytes_per_block() + Sets the block size used for writing the archive data. Every + call to the write callback function, except possibly the last + one, will use this value for the length. The default is to use a + block size of 10240 bytes. Note that a block size of zero will + suppress internal blocking and cause writes to be sent directly + to the write callback as they occur. + + archive_write_get_bytes_per_block() + Retrieve the block size to be used for writing. A value of -1 + here indicates that the library should use default values. A + value of zero indicates that internal blocking is suppressed. + + archive_write_set_bytes_in_last_block() + Sets the block size used for writing the last block. If this + value is zero, the last block will be padded to the same size as + the other blocks. Otherwise, the final block will be padded to a + multiple of this size. In particular, setting it to 1 will cause + the final block to not be padded. For compressed output, any + padding generated by this option is applied only after the com- + pression. The uncompressed data is always unpadded. The default + is to pad the last block to the full block size (note that + archive_write_open_filename() will set this based on the file + type). Unlike the other ``set'' functions, this function can be + called after the archive is opened. + + archive_write_get_bytes_in_last_block() + Retrieve the currently-set value for last block size. A value of + -1 here indicates that the library should use default values. + +RETURN VALUES + archive_write_set_bytes_per_block() and + archive_write_set_bytes_in_last_block() return ARCHIVE_OK on success, or + ARCHIVE_FATAL. + + archive_write_get_bytes_per_block() and + archive_write_get_bytes_in_last_block() return currently configured block + size (-1 indicates the default block size), or ARCHIVE_FATAL. + +ERRORS + Detailed error codes and textual descriptions are available from the + archive_errno() and archive_error_string() functions. + +SEE ALSO + tar(1), archive_write_set_options(3), libarchive(3), cpio(5), mtree(5), + tar(5) + +BSD February 2, 2012 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_write_data.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_write_data.3.txt new file mode 100644 index 0000000..b152279 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_write_data.3.txt @@ -0,0 +1,52 @@ +ARCHIVE_WRITE_DATA(3) BSD Library Functions Manual ARCHIVE_WRITE_DATA(3) + +NAME + archive_write_data, archive_write_data_block -- functions for creating + archives + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + la_ssize_t + archive_write_data(struct archive *, const void *, size_t); + + la_ssize_t + archive_write_data_block(struct archive *, const void *, size_t size, + int64_t offset); + +DESCRIPTION + archive_write_data() + Write data corresponding to the header just written. + + archive_write_data_block() + Write data corresponding to the header just written. This is + like archive_write_data() except that it performs a seek on the + file being written to the specified offset before writing the + data. This is useful when restoring sparse files from archive + formats that support sparse files. Returns number of bytes writ- + ten or -1 on error. (Note: This is currently not supported for + archive_write handles, only for archive_write_disk handles. + +RETURN VALUES + This function returns the number of bytes actually written, or a negative + error code on error. + +ERRORS + Detailed error codes and textual descriptions are available from the + archive_errno() and archive_error_string() functions. + +BUGS + In libarchive 3.x, this function sometimes returns zero on success + instead of returning the number of bytes written. Specifically, this + occurs when writing to an archive_write_disk handle. Clients should + treat any value less than zero as an error and consider any non-negative + value as success. + +SEE ALSO + tar(1), archive_write_finish_entry(3), archive_write_set_options(3), + libarchive(3), cpio(5), mtree(5), tar(5) + +BSD February 28, 2017 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_write_disk.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_write_disk.3.txt new file mode 100644 index 0000000..d27016e --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_write_disk.3.txt @@ -0,0 +1,239 @@ +ARCHIVE_WRITE_DISK(3) BSD Library Functions Manual ARCHIVE_WRITE_DISK(3) + +NAME + archive_write_disk_new, archive_write_disk_set_options, + archive_write_disk_set_skip_file, archive_write_disk_set_group_lookup, + archive_write_disk_set_standard_lookup, + archive_write_disk_set_user_lookup -- functions for creating objects on + disk + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + struct archive * + archive_write_disk_new(void); + + int + archive_write_disk_set_options(struct archive *, int flags); + + int + archive_write_disk_set_skip_file(struct archive *, dev_t, ino_t); + + int + archive_write_disk_set_group_lookup(struct archive *, void *, + gid_t (*)(void *, const char *gname, gid_t gid), + void (*cleanup)(void *)); + + int + archive_write_disk_set_standard_lookup(struct archive *); + + int + archive_write_disk_set_user_lookup(struct archive *, void *, + uid_t (*)(void *, const char *uname, uid_t uid), + void (*cleanup)(void *)); + +DESCRIPTION + These functions provide a complete API for creating objects on disk from + struct archive_entry descriptions. They are most naturally used when + extracting objects from an archive using the archive_read() interface. + The general process is to read struct archive_entry objects from an ar- + chive, then write those objects to a struct archive object created using + the archive_write_disk() family functions. This interface is deliber- + ately very similar to the archive_write() interface used to write objects + to a streaming archive. + + archive_write_disk_new() + Allocates and initializes a struct archive object suitable for + writing objects to disk. + + archive_write_disk_set_skip_file() + Records the device and inode numbers of a file that should not be + overwritten. This is typically used to ensure that an extraction + process does not overwrite the archive from which objects are + being read. This capability is technically unnecessary but can + be a significant performance optimization in practice. + + archive_write_disk_set_options() + The options field consists of a bitwise OR of one or more of the + following values: + ARCHIVE_EXTRACT_ACL + Attempt to restore Access Control Lists. By default, + extended ACLs are ignored. + ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS + Before removing a file system object prior to replacing + it, clear platform-specific file flags which might pre- + vent its removal. + ARCHIVE_EXTRACT_FFLAGS + Attempt to restore file attributes (file flags). By + default, file attributes are ignored. See chattr(1) + (Linux) or chflags(1) (FreeBSD, Mac OS X) for more infor- + mation on file attributes. + ARCHIVE_EXTRACT_MAC_METADATA + Mac OS X specific. Restore metadata using copyfile(3). + By default, copyfile(3) metadata is ignored. + ARCHIVE_EXTRACT_NO_OVERWRITE + Existing files on disk will not be overwritten. By + default, existing regular files are truncated and over- + written; existing directories will have their permissions + updated; other pre-existing objects are unlinked and + recreated from scratch. + ARCHIVE_EXTRACT_OWNER + The user and group IDs should be set on the restored + file. By default, the user and group IDs are not + restored. + ARCHIVE_EXTRACT_PERM + Full permissions (including SGID, SUID, and sticky bits) + should be restored exactly as specified, without obeying + the current umask. Note that SUID and SGID bits can only + be restored if the user and group ID of the object on + disk are correct. If ARCHIVE_EXTRACT_OWNER is not speci- + fied, then SUID and SGID bits will only be restored if + the default user and group IDs of newly-created objects + on disk happen to match those specified in the archive + entry. By default, only basic permissions are restored, + and umask is obeyed. + ARCHIVE_EXTRACT_SAFE_WRITES + Extract files atomically, by first creating a unique tem- + porary file and then renaming it to its required destina- + tion name. This avoids a race where an application might + see a partial file (or no file) during extraction. + ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS + Refuse to extract an absolute path. The default is to + not refuse such paths. + ARCHIVE_EXTRACT_SECURE_NODOTDOT + Refuse to extract a path that contains a .. element any- + where within it. The default is to not refuse such + paths. Note that paths ending in .. always cause an + error, regardless of this flag. + ARCHIVE_EXTRACT_SECURE_SYMLINKS + Refuse to extract any object whose final location would + be altered by a symlink on disk. This is intended to + help guard against a variety of mischief caused by ar- + chives that (deliberately or otherwise) extract files + outside of the current directory. The default is not to + perform this check. If + ARCHIVE_EXTRACT_SPARSE + Scan data for blocks of NUL bytes and try to recreate + them with holes. This results in sparse files, indepen- + dent of whether the archive format supports or uses them. + ARCHIVE_EXTRACT_UNLINK is specified together with this + option, the library will remove any intermediate symlinks + it finds and return an error only if such symlink could + not be removed. + ARCHIVE_EXTRACT_TIME + The timestamps (mtime, ctime, and atime) should be + restored. By default, they are ignored. Note that + restoring of atime is not currently supported. + ARCHIVE_EXTRACT_UNLINK + Existing files on disk will be unlinked before any + attempt to create them. In some cases, this can prove to + be a significant performance improvement. By default, + existing files are truncated and rewritten, but the file + is not recreated. In particular, the default behavior + does not break existing hard links. + ARCHIVE_EXTRACT_XATTR + Attempt to restore extended file attributes. By default, + they are ignored. See xattr(7) (Linux), xattr(2) (Mac OS + X), or getextattr(8) (FreeBSD) for more information on + extended file attributes. + + archive_write_disk_set_group_lookup(), + archive_write_disk_set_user_lookup() + The struct archive_entry objects contain both names and ids that + can be used to identify users and groups. These names and ids + describe the ownership of the file itself and also appear in ACL + lists. By default, the library uses the ids and ignores the + names, but this can be overridden by registering user and group + lookup functions. To register, you must provide a lookup func- + tion which accepts both a name and id and returns a suitable id. + You may also provide a void * pointer to a private data structure + and a cleanup function for that data. The cleanup function will + be invoked when the struct archive object is destroyed. + + archive_write_disk_set_standard_lookup() + This convenience function installs a standard set of user and + group lookup functions. These functions use getpwnam(3) and + getgrnam(3) to convert names to ids, defaulting to the ids if the + names cannot be looked up. These functions also implement a sim- + ple memory cache to reduce the number of calls to getpwnam(3) and + getgrnam(3). + More information about the struct archive object and the overall design + of the library can be found in the libarchive(3) overview. Many of these + functions are also documented under archive_write(3). + +RETURN VALUES + Most functions return ARCHIVE_OK (zero) on success, or one of several + non-zero error codes for errors. Specific error codes include: + ARCHIVE_RETRY for operations that might succeed if retried, ARCHIVE_WARN + for unusual conditions that do not prevent further operations, and + ARCHIVE_FATAL for serious errors that make remaining operations impossi- + ble. + + archive_write_disk_new() returns a pointer to a newly-allocated struct + archive object. + + archive_write_data() returns a count of the number of bytes actually + written, or -1 on error. + +ERRORS + Detailed error codes and textual descriptions are available from the + archive_errno() and archive_error_string() functions. + +SEE ALSO + tar(1), archive_read(3), archive_write(3), libarchive(3) + +HISTORY + The libarchive library first appeared in FreeBSD 5.3. The + archive_write_disk interface was added to libarchive 2.0 and first + appeared in FreeBSD 6.3. + +AUTHORS + The libarchive library was written by Tim Kientzle . + +BUGS + Directories are actually extracted in two distinct phases. Directories + are created during archive_write_header(), but final permissions are not + set until archive_write_close(). This separation is necessary to cor- + rectly handle borderline cases such as a non-writable directory contain- + ing files, but can cause unexpected results. In particular, directory + permissions are not fully restored until the archive is closed. If you + use chdir(2) to change the current directory between calls to + archive_read_extract() or before calling archive_read_close(), you may + confuse the permission-setting logic with the result that directory per- + missions are restored incorrectly. + + The library attempts to create objects with filenames longer than + PATH_MAX by creating prefixes of the full path and changing the current + directory. Currently, this logic is limited in scope; the fixup pass + does not work correctly for such objects and the symlink security check + option disables the support for very long pathnames. + + Restoring the path aa/../bb does create each intermediate directory. In + particular, the directory aa is created as well as the final object bb. + In theory, this can be exploited to create an entire directory hierarchy + with a single request. Of course, this does not work if the + ARCHIVE_EXTRACT_NODOTDOT option is specified. + + Implicit directories are always created obeying the current umask. + Explicit objects are created obeying the current umask unless + ARCHIVE_EXTRACT_PERM is specified, in which case they current umask is + ignored. + + SGID and SUID bits are restored only if the correct user and group could + be set. If ARCHIVE_EXTRACT_OWNER is not specified, then no attempt is + made to set the ownership. In this case, SGID and SUID bits are restored + only if the user and group of the final object happen to match those + specified in the entry. + + The ``standard'' user-id and group-id lookup functions are not the + defaults because getgrnam(3) and getpwnam(3) are sometimes too large for + particular applications. The current design allows the application + author to use a more compact implementation when appropriate. + + There should be a corresponding archive_read_disk interface that walks a + directory hierarchy and returns archive entry objects. + +BSD January 19, 2020 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_write_filter.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_write_filter.3.txt new file mode 100644 index 0000000..341c8bf --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_write_filter.3.txt @@ -0,0 +1,101 @@ +ARCHIVE_WRITE_FILTER(3) BSD Library Functions Manual ARCHIVE_WRITE_FILTER(3) + +NAME + archive_write_add_filter_b64encode, archive_write_add_filter_by_name, + archive_write_add_filter_bzip2, archive_write_add_filter_compress, + archive_write_add_filter_grzip, archive_write_add_filter_gzip, + archive_write_add_filter_lrzip, archive_write_add_filter_lz4, + archive_write_add_filter_lzip, archive_write_add_filter_lzma, + archive_write_add_filter_lzop, archive_write_add_filter_none, + archive_write_add_filter_program, archive_write_add_filter_uuencode, + archive_write_add_filter_xz, archive_write_add_filter_zstd -- functions + enabling output filters + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + int + archive_write_add_filter_b64encode(struct archive *); + + int + archive_write_add_filter_bzip2(struct archive *); + + int + archive_write_add_filter_compress(struct archive *); + + int + archive_write_add_filter_grzip(struct archive *); + + int + archive_write_add_filter_gzip(struct archive *); + + int + archive_write_add_filter_lrzip(struct archive *); + + int + archive_write_add_filter_lz4(struct archive *); + + int + archive_write_add_filter_lzip(struct archive *); + + int + archive_write_add_filter_lzma(struct archive *); + + int + archive_write_add_filter_lzop(struct archive *); + + int + archive_write_add_filter_none(struct archive *); + + int + archive_write_add_filter_program(struct archive *, const char * cmd); + + int + archive_write_add_filter_uuencode(struct archive *); + + int + archive_write_add_filter_xz(struct archive *); + + int + archive_write_add_filter_zstd(struct archive *); + +DESCRIPTION + archive_write_add_filter_bzip2(), archive_write_add_filter_compress(), + archive_write_add_filter_grzip(), + archive_write_add_filter_gzip(), + archive_write_add_filter_lrzip(), archive_write_add_filter_lz4(), + archive_write_add_filter_lzip(), archive_write_add_filter_lzma(), + archive_write_add_filter_lzop(), archive_write_add_filter_xz(), + archive_write_add_filter_zstd(), + The resulting archive will be compressed as specified. Note that + the compressed output is always properly blocked. + + archive_write_add_filter_b64encode(), + archive_write_add_filter_uuencode(), + The output will be encoded as specified. The encoded output is + always properly blocked. + + archive_write_add_filter_none() + This is never necessary. It is provided only for backwards com- + patibility. + + archive_write_add_filter_program() + The archive will be fed into the specified compression program. + The output of that program is blocked and written to the client + write callbacks. + +RETURN VALUES + These functions return ARCHIVE_OK on success, or ARCHIVE_FATAL. + +ERRORS + Detailed error codes and textual descriptions are available from the + archive_errno() and archive_error_string() functions. + +SEE ALSO + tar(1), archive_write(3), archive_write_format(3), + archive_write_set_options(3), libarchive(3), cpio(5), mtree(5), tar(5) + +BSD August 14, 2014 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_write_finish_entry.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_write_finish_entry.3.txt new file mode 100644 index 0000000..165a60d --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_write_finish_entry.3.txt @@ -0,0 +1,37 @@ +ARCHIVE_WRITE_FINISH_... BSD Library Functions Manual ARCHIVE_WRITE_FINISH_... + +NAME + archive_write_finish_entry -- functions for creating archives + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + int + archive_write_finish_entry(struct archive *); + +DESCRIPTION + Close out the entry just written. In particular, this writes out the + final padding required by some formats. Ordinarily, clients never need + to call this, as it is called automatically by archive_write_header() and + archive_write_close() as needed. For archive_write_disk handles, this + flushes pending file attribute changes like modification time. + +RETURN VALUES + This function returns ARCHIVE_OK on success, or one of several non-zero + error codes for errors. Specific error codes include: ARCHIVE_RETRY for + operations that might succeed if retried, ARCHIVE_WARN for unusual condi- + tions that do not prevent further operations, and ARCHIVE_FATAL for seri- + ous errors that make remaining operations impossible. + +ERRORS + Detailed error codes and textual descriptions are available from the + archive_errno() and archive_error_string() functions. + +SEE ALSO + tar(1), archive_write_data(3), archive_write_set_options(3), + libarchive(3), cpio(5), mtree(5), tar(5) + +BSD February 28, 2017 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_write_format.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_write_format.3.txt new file mode 100644 index 0000000..e45c1e5 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_write_format.3.txt @@ -0,0 +1,146 @@ +ARCHIVE_WRITE_FORMAT(3) BSD Library Functions Manual ARCHIVE_WRITE_FORMAT(3) + +NAME + archive_write_set_format, archive_write_set_format_7zip, + archive_write_set_format_ar, archive_write_set_format_ar_bsd, + archive_write_set_format_ar_svr4, archive_write_set_format_by_name, + archive_write_set_format_cpio, archive_write_set_format_cpio_newc, + archive_write_set_format_filter_by_ext, + archive_write_set_format_filter_by_ext_def, + archive_write_set_format_gnutar, archive_write_set_format_iso9660, + archive_write_set_format_mtree, archive_write_set_format_mtree_classic, + archive_write_set_format_mtree_default, archive_write_set_format_pax, + archive_write_set_format_pax_restricted, archive_write_set_format_raw, + archive_write_set_format_shar, archive_write_set_format_shar_dump, + archive_write_set_format_ustar, archive_write_set_format_v7tar, + archive_write_set_format_warc, archive_write_set_format_xar, + archive_write_set_format_zip -- functions for creating archives + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + int + archive_write_set_format(struct archive *, int code); + + int + archive_write_set_format_7zip(struct archive *); + + int + archive_write_set_format_ar(struct archive *); + + int + archive_write_set_format_ar_bsd(struct archive *); + + int + archive_write_set_format_ar_svr4(struct archive *); + + int + archive_write_set_format_by_name(struct archive *, const char *name); + + int + archive_write_set_format_cpio(struct archive *); + + int + archive_write_set_format_cpio_newc(struct archive *); + + int + archive_write_set_format_filter_by_ext(struct archive *, + const char *filename); + + int + archive_write_set_format_filter_by_ext_def(struct archive *, + const char *filename, const char *def_ext); + + int + archive_write_set_format_gnutar(struct archive *); + + int + archive_write_set_format_iso9660(struct archive *); + + int + archive_write_set_format_mtree(struct archive *); + + int + archive_write_set_format_pax(struct archive *); + + int + archive_write_set_format_pax_restricted(struct archive *); + + int + archive_write_set_format_raw(struct archive *); + + int + archive_write_set_format_shar(struct archive *); + + int + archive_write_set_format_shar_dump(struct archive *); + + int + archive_write_set_format_ustar(struct archive *); + + int + archive_write_set_format_v7tar(struct archive *); + + int + archive_write_set_format_warc(struct archive *); + + int + archive_write_set_format_xar(struct archive *); + + int + archive_write_set_format_zip(struct archive *); + +DESCRIPTION + These functions set the format that will be used for the archive. + + The library can write a variety of common archive formats. + + archive_write_set_format() + Sets the format based on the format code (see archive.h for the + full list of format codes). In particular, this can be used in + conjunction with archive_format() to create a new archive with + the same format as an existing archive. + + archive_write_set_format_by_name() + Sets the corresponding format based on the common name. + + archive_write_set_format_filter_by_ext(), + archive_write_set_format_filter_by_ext_def() + Sets both filters and format based on the output filename. Sup- + ported extensions: .7z, .zip, .jar, .cpio, .iso, .a, .ar, .tar, + .tgz, .tar.gz, .tar.bz2, .tar.xz + + archive_write_set_format_7zip() archive_write_set_format_ar_bsd(), + archive_write_set_format_ar_svr4(), + archive_write_set_format_cpio() + archive_write_set_format_cpio_newc() + archive_write_set_format_gnutar() + archive_write_set_format_iso9660() + archive_write_set_format_mtree() + archive_write_set_format_mtree_classic() + archive_write_set_format_pax() + archive_write_set_format_pax_restricted() + archive_write_set_format_raw() archive_write_set_format_shar() + archive_write_set_format_shar_dump() + archive_write_set_format_ustar() archive_write_set_format_v7tar() + archive_write_set_format_warc() archive_write_set_format_xar() + archive_write_set_format_zip() + Set the format as specified. More details on the formats sup- + ported by libarchive can be found in the libarchive-formats(5) + manual page. + +RETURN VALUES + These functions return ARCHIVE_OK on success, or ARCHIVE_FATAL. + +ERRORS + Detailed error codes and textual descriptions are available from the + archive_errno() and archive_error_string() functions. + +SEE ALSO + tar(1), archive_write(3), archive_write_set_options(3), libarchive(3), + cpio(5), libarchive-formats(5), mtree(5), tar(5) + +BSD February 14, 2013 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_write_free.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_write_free.3.txt new file mode 100644 index 0000000..3e4703d --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_write_free.3.txt @@ -0,0 +1,58 @@ +ARCHIVE_WRITE_FREE(3) BSD Library Functions Manual ARCHIVE_WRITE_FREE(3) + +NAME + archive_write_fail, archive_write_close, archive_write_finish, + archive_write_free -- functions for creating archives + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + int + archive_write_fail(struct archive *); + + int + archive_write_close(struct archive *); + + int + archive_write_finish(struct archive *); + + int + archive_write_free(struct archive *); + +DESCRIPTION + archive_write_fail() + Always returns ARCHIVE_FATAL. This marks the archive object as + being unusable; after calling this function, the only call that + can succeed is archive_write_free() to release the resources. + This can be used to speed recovery when the archive creation must + be aborted. Note that the created archive is likely to be mal- + formed in this case; + + archive_write_close() + Complete the archive and invoke the close callback. + + archive_write_finish() + This is a deprecated synonym for archive_write_free(). + + archive_write_free() + Invokes archive_write_close() if necessary, then releases all + resources. If you need detailed information about + archive_write_close() failures, you should be careful to call it + separately, as you cannot obtain error information after + archive_write_free() returns. + +RETURN VALUES + These functions return ARCHIVE_OK on success, or ARCHIVE_FATAL. + +ERRORS + Detailed error codes and textual descriptions are available from the + archive_errno() and archive_error_string() functions. + +SEE ALSO + tar(1), archive_write_set_options(3), libarchive(3), cpio(5), mtree(5), + tar(5) + +BSD February 2, 2012 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_write_header.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_write_header.3.txt new file mode 100644 index 0000000..9989271 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_write_header.3.txt @@ -0,0 +1,35 @@ +ARCHIVE_WRITE_HEADER(3) BSD Library Functions Manual ARCHIVE_WRITE_HEADER(3) + +NAME + archive_write_header -- functions for creating archives + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + int + archive_write_header(struct archive *, struct archive_entry *); + +DESCRIPTION + Build and write a header using the data in the provided struct + archive_entry structure. See archive_entry(3) for information on creat- + ing and populating struct archive_entry objects. + +RETURN VALUES + This function returns ARCHIVE_OK on success, or one of the following on + error: ARCHIVE_RETRY for operations that might succeed if retried, + ARCHIVE_WARN for unusual conditions that do not prevent further opera- + tions, and ARCHIVE_FATAL for serious errors that make remaining opera- + tions impossible. + +ERRORS + Detailed error codes and textual descriptions are available from the + archive_errno() and archive_error_string() functions. + +SEE ALSO + tar(1), archive_write_set_options(3), libarchive(3), cpio(5), mtree(5), + tar(5) + +BSD February 2, 2012 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_write_new.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_write_new.3.txt new file mode 100644 index 0000000..5b8ac3c --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_write_new.3.txt @@ -0,0 +1,26 @@ +ARCHIVE_WRITE_NEW(3) BSD Library Functions Manual ARCHIVE_WRITE_NEW(3) + +NAME + archive_write_new -- functions for creating archives + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + struct archive * + archive_write_new(void); + +DESCRIPTION + Allocates and initializes a struct archive object suitable for writing a + tar archive. NULL is returned on error. + + A complete description of the struct archive object can be found in the + overview manual page for libarchive(3). + +SEE ALSO + tar(1), archive_write(3), archive_write_set_options(3), libarchive(3), + cpio(5), mtree(5), tar(5) + +BSD February 2, 2012 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_write_open.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_write_open.3.txt new file mode 100644 index 0000000..59cfa61 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_write_open.3.txt @@ -0,0 +1,135 @@ +ARCHIVE_WRITE_OPEN(3) BSD Library Functions Manual ARCHIVE_WRITE_OPEN(3) + +NAME + archive_write_open, archive_write_open_fd, archive_write_open_FILE, + archive_write_open_filename, archive_write_open_memory -- functions for + creating archives + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + int + archive_write_open(struct archive *, void *client_data, + archive_open_callback *, archive_write_callback *, + archive_close_callback *); + + int + archive_write_open_fd(struct archive *, int fd); + + int + archive_write_open_FILE(struct archive *, FILE *file); + + int + archive_write_open_filename(struct archive *, const char *filename); + + int + archive_write_open_memory(struct archive *, void *buffer, + size_t bufferSize, size_t *outUsed); + +DESCRIPTION + archive_write_open() + Freeze the settings, open the archive, and prepare for writing + entries. This is the most generic form of this function, which + accepts pointers to three callback functions which will be + invoked by the compression layer to write the constructed ar- + chive. This does not alter the default archive padding. + + archive_write_open_fd() + A convenience form of archive_write_open() that accepts a file + descriptor. The archive_write_open_fd() function is safe for use + with tape drives or other block-oriented devices. + + archive_write_open_FILE() + A convenience form of archive_write_open() that accepts a FILE * + pointer. Note that archive_write_open_FILE() is not safe for + writing to tape drives or other devices that require correct + blocking. + + archive_write_open_file() + A deprecated synonym for archive_write_open_filename(). + + archive_write_open_filename() + A convenience form of archive_write_open() that accepts a file- + name. A NULL argument indicates that the output should be writ- + ten to standard output; an argument of ``-'' will open a file + with that name. If you have not invoked + archive_write_set_bytes_in_last_block(), then + archive_write_open_filename() will adjust the last-block padding + depending on the file: it will enable padding when writing to + standard output or to a character or block device node, it will + disable padding otherwise. You can override this by manually + invoking archive_write_set_bytes_in_last_block() before calling + archive_write_open(). The archive_write_open_filename() function + is safe for use with tape drives or other block-oriented devices. + + archive_write_open_memory() + A convenience form of archive_write_open() that accepts a pointer + to a block of memory that will receive the archive. The final + size_t * argument points to a variable that will be updated after + each write to reflect how much of the buffer is currently in use. + You should be careful to ensure that this variable remains allo- + cated until after the archive is closed. This function will dis- + able padding unless you have specifically set the block size. + More information about the struct archive object and the overall design + of the library can be found in the libarchive(3) overview. + + Note that the convenience forms above vary in how they block the output. + See archive_write_blocksize(3) if you need to control the block size used + for writes or the end-of-file padding behavior. + +CLIENT CALLBACKS + To use this library, you will need to define and register callback func- + tions that will be invoked to write data to the resulting archive. These + functions are registered by calling archive_write_open(): + + typedef int archive_open_callback(struct archive *, void + *client_data) + + The open callback is invoked by archive_write_open(). It should return + ARCHIVE_OK if the underlying file or data source is successfully opened. + If the open fails, it should call archive_set_error() to register an + error code and message and return ARCHIVE_FATAL. + + typedef la_ssize_t archive_write_callback(struct archive *, + void *client_data, const void *buffer, size_t length) + + The write callback is invoked whenever the library needs to write raw + bytes to the archive. For correct blocking, each call to the write call- + back function should translate into a single write(2) system call. This + is especially critical when writing archives to tape drives. On success, + the write callback should return the number of bytes actually written. + On error, the callback should invoke archive_set_error() to register an + error code and message and return -1. + + typedef int archive_close_callback(struct archive *, void + *client_data) + + The close callback is invoked by archive_close when the archive process- + ing is complete. The callback should return ARCHIVE_OK on success. On + failure, the callback should invoke archive_set_error() to register an + error code and message and return ARCHIVE_FATAL. + + Note that if the client-provided write callback function returns a non- + zero value, that error will be propagated back to the caller through + whatever API function resulted in that call, which may include + archive_write_header(), archive_write_data(), archive_write_close(), + archive_write_finish(), or archive_write_free(). The client callback can + call archive_set_error() to provide values that can then be retrieved by + archive_errno() and archive_error_string(). + +RETURN VALUES + These functions return ARCHIVE_OK on success, or ARCHIVE_FATAL. + +ERRORS + Detailed error codes and textual descriptions are available from the + archive_errno() and archive_error_string() functions. + +SEE ALSO + tar(1), archive_write(3), archive_write_blocksize(3), + archive_write_filter(3), archive_write_format(3), archive_write_new(3), + archive_write_set_options(3), libarchive(3), cpio(5), mtree(5), tar(5) + +BSD February 2, 2012 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_write_set_options.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_write_set_options.3.txt new file mode 100644 index 0000000..97538b9 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_write_set_options.3.txt @@ -0,0 +1,484 @@ +ARCHIVE_WRITE_OPTIONS(3) BSD Library Functions Manual ARCHIVE_WRITE_OPTIONS(3) + +NAME + archive_write_set_filter_option, archive_write_set_format_option, + archive_write_set_option, archive_write_set_options -- functions control- + ling options for writing archives + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + int + archive_write_set_filter_option(struct archive *, const char *module, + const char *option, const char *value); + + int + archive_write_set_format_option(struct archive *, const char *module, + const char *option, const char *value); + + int + archive_write_set_option(struct archive *, const char *module, + const char *option, const char *value); + + int + archive_write_set_options(struct archive *, const char *options); + +DESCRIPTION + These functions provide a way for libarchive clients to configure spe- + cific write modules. + + archive_write_set_filter_option(), archive_write_set_format_option() + Specifies an option that will be passed to the currently-regis- + tered filters (including decompression filters) or format read- + ers. + + If option and value are both NULL, these functions will do noth- + ing and ARCHIVE_OK will be returned. If option is NULL but value + is not, these functions will do nothing and ARCHIVE_FAILED will + be returned. + + If module is not NULL, option and value will be provided to the + filter or reader named module. The return value will be either + ARCHIVE_OK if the option was successfully handled or ARCHIVE_WARN + if the option was unrecognized by the module or could otherwise + not be handled. If there is no such module, ARCHIVE_FAILED will + be returned. + + If module is NULL, option and value will be provided to every + registered module. If any module returns ARCHIVE_FATAL, this + value will be returned immediately. Otherwise, ARCHIVE_OK will + be returned if any module accepts the option, and ARCHIVE_FAILED + in all other cases. + + archive_write_set_option() + Calls archive_write_set_format_option(), then + archive_write_set_filter_option(). If either function returns + ARCHIVE_FATAL, ARCHIVE_FATAL will be returned immediately. Oth- + erwise, the greater of the two values will be returned. + + archive_write_set_options() + options is a comma-separated list of options. If options is NULL + or empty, ARCHIVE_OK will be returned immediately. + + Individual options have one of the following forms: + option=value + The option/value pair will be provided to every module. + Modules that do not accept an option with this name will + ignore it. + option The option will be provided to every module with a value + of ``1''. + !option + The option will be provided to every module with a NULL + value. + module:option=value, module:option, module:!option + As above, but the corresponding option and value will be + provided only to modules whose name matches module. + +OPTIONS + Filter b64encode + mode The value is interpreted as octal digits specifying the + file mode. + name The value specifies the file name. + Filter bzip2 + compression-level + The value is interpreted as a decimal integer specifying + the bzip2 compression level. Supported values are from 1 + to 9. + Filter gzip + compression-level + The value is interpreted as a decimal integer specifying + the gzip compression level. Supported values are from 0 + to 9. + timestamp + Store timestamp. This is enabled by default. + Filter lrzip + compression=type + Use type as compression method. Supported values are + ``bzip2'', ``gzipi'', ``lzo'' (ultra fast), and ``zpaq'' + (best, extremely slow). + compression-level + The value is interpreted as a decimal integer specifying + the lrzip compression level. Supported values are from 1 + to 9. + Filter lz4 + compression-level + The value is interpreted as a decimal integer specifying + the lz4 compression level. Supported values are from 0 to + 9. + stream-checksum + Enable stream checksum. This is enabled by default. + block-checksum + Enable block checksum. This is disabled by default. + block-size + The value is interpreted as a decimal integer specifying + the lz4 compression block size. Supported values are from + 4 to 7 (default). + block-dependence + Use the previous block of the block being compressed for + a compression dictionary to improve compression ratio. + This is disabled by default. + Filter lzop + compression-level + The value is interpreted as a decimal integer specifying + the lzop compression level. Supported values are from 1 + to 9. + Filter uuencode + mode The value is interpreted as octal digits specifying the + file mode. + name The value specifies the file name. + Filter xz + compression-level + The value is interpreted as a decimal integer specifying + the compression level. Supported values are from 0 to 9. + threads + The value is interpreted as a decimal integer specifying + the number of threads for multi-threaded lzma compres- + sion. If supported, the default value is read from + lzma_cputhreads(). + Filter zstd + compression-level + The value is interpreted as a decimal integer specifying + the compression level. Supported values are from 1 to 22. + Format 7zip + compression + The value is one of ``store'', ``deflate'', ``bzip2'', + ``lzma1'', ``lzma2'' or ``ppmd'' to indicate how the fol- + lowing entries should be compressed. Note that this set- + ting is ignored for directories, symbolic links, and + other special entries. + compression-level + The value is interpreted as a decimal integer specifying + the compression level. Values between 0 and 9 are sup- + ported. The interpretation of the compression level + depends on the chosen compression method. + Format cpio + hdrcharset + The value is used as a character set name that will be + used when translating file names. + Format gnutar + hdrcharset + The value is used as a character set name that will be + used when translating file, group and user names. + Format iso9660 - volume metadata + These options are used to set standard ISO9660 metadata. + abstract-file=filename + The file with the specified name will be identified in + the ISO9660 metadata as holding the abstract for this + volume. Default: none. + application-id=filename + The file with the specified name will be identified in + the ISO9660 metadata as holding the application identi- + fier for this volume. Default: none. + biblio-file=filename + The file with the specified name will be identified in + the ISO9660 metadata as holding the bibliography for this + volume. Default: none. + copyright-file=filename + The file with the specified name will be identified in + the ISO9660 metadata as holding the copyright for this + volume. Default: none. + publisher=filename + The file with the specified name will be identified in + the ISO9660 metadata as holding the publisher information + for this volume. Default: none. + volume-id=string + The specified string will be used as the Volume Identi- + fier in the ISO9660 metadata. It is limited to 32 bytes. + Default: none. + Format iso9660 - boot support + These options are used to make an ISO9660 image that can be + directly booted on various systems. + boot=filename + The file matching this name will be used as the El Torito + boot image file. + boot-catalog=name + The name that will be used for the El Torito boot cata- + log. Default: boot.catalog + boot-info-table + The boot image file provided by the boot=filename option + will be edited with appropriate boot information in bytes + 8 through 64. Default: disabled + boot-load-seg=hexadecimal-number + The load segment for a no-emulation boot image. + boot-load-size=decimal-number + The number of "virtual" 512-byte sectors to be loaded + from a no-emulation boot image. Some very old BIOSes can + only load very small images, setting this value to 4 will + often allow such BIOSes to load the first part of the + boot image (which will then need to be intelligent enough + to load the rest of itself). This should not be needed + unless you are trying to support systems with very old + BIOSes. This defaults to the full size of the image. + boot-type=value + Specifies the boot semantics used by the El Torito boot + image: If the value is fd, then the boot image is assumed + to be a bootable floppy image. If the value is hd, then + the boot image is assumed to be a bootable hard disk + image. If the value is no-emulation, the boot image is + used without floppy or hard disk emulation. If the boot + image is exactly 1.2MB, 1.44MB, or 2.88MB, then the + default is fd, otherwise the default is no-emulation. + Format iso9660 - filename and size extensions + Various extensions to the base ISO9660 format. + allow-ldots + If enabled, allows filenames to begin with a leading + period. If disabled, filenames that begin with a leading + period will have that period replaced by an underscore + character in the standard ISO9660 namespace. This does + not impact names stored in the Rockridge or Joliet exten- + sion area. Default: disabled. + allow-lowercase + If enabled, allows filenames to contain lowercase charac- + ters. If disabled, filenames will be forced to upper- + case. This does not impact names stored in the Rockridge + or Joliet extension area. Default: disabled. + allow-multidot + If enabled, allows filenames to contain multiple period + characters, in violation of the ISO9660 specification. + If disabled, additional periods will be converted to + underscore characters. This does not impact names stored + in the Rockridge or Joliet extension area. Default: dis- + abled. + allow-period + If enabled, allows filenames to contain trailing period + characters, in violation of the ISO9660 specification. + If disabled, trailing periods will be converted to under- + score characters. This does not impact names stored in + the Rockridge or Joliet extension area. Default: dis- + abled. + allow-pvd-lowercase + If enabled, the Primary Volume Descriptor may contain + lowercase ASCII characters, in violation of the ISO9660 + specification. If disabled, characters will be converted + to uppercase ASCII. Default: disabled. + allow-sharp-tilde + If enabled, sharp and tilde characters will be permitted + in filenames, in violation if the ISO9660 specification. + If disabled, such characters will be converted to under- + score characters. Default: disabled. + allow-vernum + If enabled, version numbers will be included with files. + If disabled, version numbers will be suppressed, in vio- + lation of the ISO9660 standard. This does not impact + names stored in the Rockridge or Joliet extension area. + Default: enabled. + iso-level + This enables support for file size and file name exten- + sions in the core ISO9660 area. The name extensions + specified here do not affect the names stored in the + Rockridge or Joliet extension areas. + iso-level=1 + The most compliant form of ISO9660 image. File- + names are limited to 8.3 uppercase format, direc- + tory names are limited to 8 uppercase characters, + files are limited to 4 GiB, the complete ISO9660 + image cannot exceed 4 GiB. + iso-level=2 + Filenames are limited to 30 uppercase characters + with a 30-character extension, directory names + are limited to 30 characters, files are limited + to 4 GiB. + iso-level=3 + As with iso-level=2, except that files may exceed + 4 GiB. + iso-level=4 + As with iso-level=3, except that filenames may be + up to 193 characters and may include arbitrary + 8-bit characters. + joliet Microsoft's Joliet extensions store a completely separate + set of directory information about each file. In partic- + ular, this information includes Unicode filenames of up + to 255 characters. Default: enabled. + limit-depth + If enabled, libarchive will use directory relocation + records to ensure that no pathname exceeds the ISO9660 + limit of 8 directory levels. If disabled, no relocation + will occur. Default: enabled. + limit-dirs + If enabled, libarchive will cause an error if there are + more than 65536 directories. If disabled, there is no + limit on the number of directories. Default: enabled + pad If enabled, 300 kiB of zero bytes will be appended to the + end of the archive. Default: enabled + relaxed-filenames + If enabled, all 7-bit ASCII characters are permitted in + filenames (except lowercase characters unless + allow-lowercase is also specified). This violates + ISO9660 standards. This does not impact names stored in + the Rockridge or Joliet extension area. Default: dis- + abled. + rockridge + The Rockridge extensions store an additional set of + POSIX-style file information with each file, including + mtime, atime, ctime, permissions, and long filenames with + arbitrary 8-bit characters. These extensions also sup- + port symbolic links and other POSIX file types. Default: + enabled. + Format iso9660 - zisofs support + The zisofs extensions permit each file to be independently com- + pressed using a gzip-compatible compression. This can provide + significant size savings, but requires the reading system to have + support for these extensions. These extensions are disabled by + default. + compression-level=number + The compression level used by the deflate compressor. + Ranges from 0 (least effort) to 9 (most effort). + Default: 6 + zisofs Synonym for zisofs=direct. + zisofs=direct + Compress each file in the archive. Unlike + zisofs=indirect, this is handled entirely within + libarchive and does not require a separate utility. For + best results, libarchive tests each file and will store + the file uncompressed if the compression does not actu- + ally save any space. In particular, files under 2k will + never be compressed. Note that boot image files are + never compressed. + zisofs=indirect + Recognizes files that have already been compressed with + the mkzftree utility and sets up the necessary file meta- + data so that readers will correctly identify these as + zisofs-compressed files. + zisofs-exclude=filename + Specifies a filename that should not be compressed when + using zisofs=direct. This option can be provided multi- + ple times to suppress compression on many files. + Format mtree + cksum, device, flags, gid, gname, indent, link, md5, mode, nlink, + rmd160, sha1, sha256, sha384, sha512, size, time, uid, + uname + Enable a particular keyword in the mtree output. Prefix + with an exclamation mark to disable the corresponding + keyword. The default is equivalent to ``device, flags, + gid, gname, link, mode, nlink, size, time, type, uid, + uname''. + all Enables all of the above keywords. + use-set + Enables generation of /set lines that specify default + values for the following files and/or directories. + indent XXX needs explanation XXX + Format newc + hdrcharset + The value is used as a character set name that will be + used when translating file names. + Format pax + hdrcharset + The value is used as a character set name that will be + used when translating file, group and user names. The + value is one of ``BINARY'' or ``UTF-8''. With ``BINARY'' + there is no character conversion, with ``UTF-8'' names + are converted to UTF-8. + xattrheader + When storing extended attributes, this option configures + which headers should be written. The value is one of + ``all'', ``LIBARCHIVE'', or ``SCHILY''. By default, both + ``LIBARCHIVE.xattr'' and ``SCHILY.xattr'' headers are + written. + Format ustar + hdrcharset + The value is used as a character set name that will be + used when translating file, group and user names. + Format v7tar + hdrcharset + The value is used as a character set name that will be + used when translating file, group and user names. + Format warc + omit-warcinfo + Set to ``true'' to disable output of the warcinfo record. + Format xar + checksum=type + Use type as file checksum method. Supported values are + ``none'', ``md5'', and ``sha1'' (default). + compression=type + Use type as compression method. Supported values are + ``none'', ``bzip2'', ``gzip'' (default), ``lzma'' and + ``xz''. + compression_level + The value is a decimal integer from 1 to 9 specifying the + compression level. + toc-checksum=type + Use type as table of contents checksum method. Supported + values are ``none'', ``md5'' and ``sha1'' (default). + Format zip + compression + The value is either ``store'' or ``deflate'' to indicate + how the following entries should be compressed. Note + that this setting is ignored for directories, symbolic + links, and other special entries. + compression-level + The value is interpreted as a decimal integer specifying + the compression level. Values between 0 and 9 are sup- + ported. A compression level of 0 switches the compres- + sion method to ``store'', other values will enable + ``deflate'' compression with the given level. + encryption + Enable encryption using traditional zip encryption. + encryption=type + Use type as encryption type. Supported values are + ``zipcrypt'' (traditional zip encryption), ``aes128'' + (WinZip AES-128 encryption) and ``aes256'' (WinZip + AES-256 encryption). + experimental + This boolean option enables or disables experimental Zip + features that may not be compatible with other Zip imple- + mentations. + fakecrc32 + This boolean option disables CRC calculations. All CRC + fields are set to zero. It should not be used except for + testing purposes. + hdrcharset + The value is used as a character set name that will be + used when translating file names. + zip64 Zip64 extensions provide additional file size information + for entries larger than 4 GiB. They also provide + extended file offset and archive size information when + archives exceed 4 GiB. By default, the Zip writer selec- + tively enables these extensions only as needed. In par- + ticular, if the file size is unknown, the Zip writer will + include Zip64 extensions to guard against the possibility + that the file might be larger than 4 GiB. + + Setting this boolean option will force the writer to use + Zip64 extensions even for small files that would not oth- + erwise require them. This is primarily useful for test- + ing. + + Disabling this option with !zip64 will force the Zip + writer to avoid Zip64 extensions: It will reject files + with size greater than 4 GiB, it will reject any new + entries once the total archive size reaches 4 GiB, and it + will not use Zip64 extensions for files with unknown + size. In particular, this can improve compatibility when + generating archives where the entry sizes are not known + in advance. + +EXAMPLES + The following example creates an archive write handle to create a gzip- + compressed ISO9660 format image. The two options here specify that the + ISO9660 archive will use kernel.img as the boot image for El Torito boot- + ing, and that the gzip compressor should use the maximum compression + level. + + a = archive_write_new(); + archive_write_add_filter_gzip(a); + archive_write_set_format_iso9660(a); + archive_write_set_options(a, "boot=kernel.img,compression=9"); + archive_write_open_filename(a, filename, blocksize); + +ERRORS + More detailed error codes and textual descriptions are available from the + archive_errno() and archive_error_string() functions. + +SEE ALSO + tar(1), archive_read_set_options(3), archive_write(3), libarchive(3) + +HISTORY + The libarchive library first appeared in FreeBSD 5.3. + +AUTHORS + The options support for libarchive was originally implemented by + Michihiro NAKAJIMA. + +BUGS +BSD January 31, 2020 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/archive_write_set_passphrase.3.txt b/dependencies/libarchive-3.4.2/doc/text/archive_write_set_passphrase.3.txt new file mode 100644 index 0000000..9717d80 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/archive_write_set_passphrase.3.txt @@ -0,0 +1,35 @@ +ARCHIVE_WRITE_SET_PAS... BSD Library Functions Manual ARCHIVE_WRITE_SET_PAS... + +NAME + archive_write_set_passphrase, archive_write_set_passphrase_callback -- + functions for writing encrypted archives + +LIBRARY + Streaming Archive Library (libarchive, -larchive) + +SYNOPSIS + #include + + int + archive_write_set_passphrase(struct archive *, const char *passphrase); + + int + archive_write_set_passphrase_callback(struct archive *, + void *client_data, archive_passphrase_callback *); + +DESCRIPTION + archive_write_set_passphrase() + Set a passphrase for writing an encrypted archive. If passphrase + is NULL or empty, this function will do nothing and + ARCHIVE_FAILED will be returned. Otherwise, ARCHIVE_OK will be + returned. + + archive_write_set_passphrase_callback() + Register a callback function that will be invoked to get a + passphrase for encryption if the passphrase was not set by the + archive_write_set_passphrase() function. + +SEE ALSO + tar(1), archive_write(3), archive_write_set_options(3), libarchive(3) + +BSD September 21, 2014 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/bsdcpio.1.txt b/dependencies/libarchive-3.4.2/doc/text/bsdcpio.1.txt new file mode 100644 index 0000000..78b9757 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/bsdcpio.1.txt @@ -0,0 +1,284 @@ +CPIO(1) BSD General Commands Manual CPIO(1) + +NAME + cpio -- copy files to and from archives + +SYNOPSIS + cpio -i [options] [pattern ...] [< archive] + cpio -o [options] < name-list [> archive] + cpio -p [options] dest-dir < name-list + +DESCRIPTION + cpio copies files between archives and directories. This implementation + can extract from tar, pax, cpio, zip, jar, ar, and ISO 9660 cdrom images + and can create tar, pax, cpio, ar, and shar archives. + + The first option to cpio is a mode indicator from the following list: + -i Input. Read an archive from standard input (unless overridden) + and extract the contents to disk or (if the -t option is speci- + fied) list the contents to standard output. If one or more file + patterns are specified, only files matching one of the patterns + will be extracted. + -o Output. Read a list of filenames from standard input and produce + a new archive on standard output (unless overridden) containing + the specified items. + -p Pass-through. Read a list of filenames from standard input and + copy the files to the specified directory. + +OPTIONS + Unless specifically stated otherwise, options are applicable in all oper- + ating modes. + + -0, --null + Read filenames separated by NUL characters instead of newlines. + This is necessary if any of the filenames being read might con- + tain newlines. + + -A (o mode only) Append to the specified archive. (Not yet imple- + mented.) + + -a (o and p modes) Reset access times on files after they are read. + + -B (o mode only) Block output to records of 5120 bytes. + + -C size + (o mode only) Block output to records of size bytes. + + -c (o mode only) Use the old POSIX portable character format. + Equivalent to --format odc. + + -d, --make-directories + (i and p modes) Create directories as necessary. + + -E file + (i mode only) Read list of file name patterns from file to list + and extract. + + -F file, --file file + Read archive from or write archive to file. + + -f pattern + (i mode only) Ignore files that match pattern. + + -H format, --format format + (o mode only) Produce the output archive in the specified format. + Supported formats include: + + cpio Synonym for odc. + newc The SVR4 portable cpio format. + odc The old POSIX.1 portable octet-oriented cpio format. + pax The POSIX.1 pax format, an extension of the ustar for- + mat. + ustar The POSIX.1 tar format. + + The default format is odc. See libarchive-formats(5) for more + complete information about the formats currently supported by the + underlying libarchive(3) library. + + -h, --help + Print usage information. + + -I file + Read archive from file. + + -i, --extract + Input mode. See above for description. + + --insecure + (i and p mode only) Disable security checks during extraction or + copying. This allows extraction via symbolic links, absolute + paths, and path names containing '..' in the name. + + -J, --xz + (o mode only) Compress the file with xz-compatible compression + before writing it. In input mode, this option is ignored; xz + compression is recognized automatically on input. + + -j Synonym for -y. + + -L (o and p modes) All symbolic links will be followed. Normally, + symbolic links are archived and copied as symbolic links. With + this option, the target of the link will be archived or copied + instead. + + -l, --link + (p mode only) Create links from the target directory to the orig- + inal files, instead of copying. + + --lrzip + (o mode only) Compress the resulting archive with lrzip(1). In + input mode, this option is ignored. + + --lz4 (o mode only) Compress the archive with lz4-compatible compres- + sion before writing it. In input mode, this option is ignored; + lz4 compression is recognized automatically on input. + + --zstd (o mode only) Compress the archive with zstd-compatible compres- + sion before writing it. In input mode, this option is ignored; + zstd compression is recognized automatically on input. + + --lzma (o mode only) Compress the file with lzma-compatible compression + before writing it. In input mode, this option is ignored; lzma + compression is recognized automatically on input. + + --lzop (o mode only) Compress the resulting archive with lzop(1). In + input mode, this option is ignored. + + --passphrase passphrase + The passphrase is used to extract or create an encrypted archive. + Currently, zip is only a format that cpio can handle encrypted + archives. You shouldn't use this option unless you realize how + insecure use of this option is. + + -m, --preserve-modification-time + (i and p modes) Set file modification time on created files to + match those in the source. + + -n, --numeric-uid-gid + (i mode, only with -t) Display numeric uid and gid. By default, + cpio displays the user and group names when they are provided in + the archive, or looks up the user and group names in the system + password database. + + --no-preserve-owner + (i mode only) Do not attempt to restore file ownership. This is + the default when run by non-root users. + + -O file + Write archive to file. + + -o, --create + Output mode. See above for description. + + -p, --pass-through + Pass-through mode. See above for description. + + --preserve-owner + (i mode only) Restore file ownership. This is the default when + run by the root user. + + --quiet + Suppress unnecessary messages. + + -R [user][:][group], --owner [user][:][group] + Set the owner and/or group on files in the output. If group is + specified with no user (for example, -R :wheel) then the group + will be set but not the user. If the user is specified with a + trailing colon and no group (for example, -R root:) then the + group will be set to the user's default group. If the user is + specified with no trailing colon, then the user will be set but + not the group. In -i and -p modes, this option can only be used + by the super-user. (For compatibility, a period can be used in + place of the colon.) + + -r (All modes.) Rename files interactively. For each file, a + prompt is written to /dev/tty containing the name of the file and + a line is read from /dev/tty. If the line read is blank, the + file is skipped. If the line contains a single period, the file + is processed normally. Otherwise, the line is taken to be the + new name of the file. + + -t, --list + (i mode only) List the contents of the archive to stdout; do not + restore the contents to disk. + + -u, --unconditional + (i and p modes) Unconditionally overwrite existing files. Ordi- + narily, an older file will not overwrite a newer file on disk. + + -V, --dot + Print a dot to stderr for each file as it is processed. Super- + seded by -v. + + -v, --verbose + Print the name of each file to stderr as it is processed. With + -t, provide a detailed listing of each file. + + --version + Print the program version information and exit. + + -y (o mode only) Compress the archive with bzip2-compatible compres- + sion before writing it. In input mode, this option is ignored; + bzip2 compression is recognized automatically on input. + + -Z (o mode only) Compress the archive with compress-compatible com- + pression before writing it. In input mode, this option is + ignored; compression is recognized automatically on input. + + -z (o mode only) Compress the archive with gzip-compatible compres- + sion before writing it. In input mode, this option is ignored; + gzip compression is recognized automatically on input. + +EXIT STATUS + The cpio utility exits 0 on success, and >0 if an error occurs. + +ENVIRONMENT + The following environment variables affect the execution of cpio: + + LANG The locale to use. See environ(7) for more information. + + TZ The timezone to use when displaying dates. See environ(7) for + more information. + +EXAMPLES + The cpio command is traditionally used to copy file hierarchies in con- + junction with the find(1) command. The first example here simply copies + all files from src to dest: + find src | cpio -pmud dest + + By carefully selecting options to the find(1) command and combining it + with other standard utilities, it is possible to exercise very fine con- + trol over which files are copied. This next example copies files from + src to dest that are more than 2 days old and whose names match a partic- + ular pattern: + find src -mtime +2 | grep foo[bar] | cpio -pdmu dest + + This example copies files from src to dest that are more than 2 days old + and which contain the word ``foobar'': + find src -mtime +2 | xargs grep -l foobar | cpio -pdmu dest + +COMPATIBILITY + The mode options i, o, and p and the options a, B, c, d, f, l, m, r, t, + u, and v comply with SUSv2. + + The old POSIX.1 standard specified that only -i, -o, and -p were inter- + preted as command-line options. Each took a single argument of a list of + modifier characters. For example, the standard syntax allows -imu but + does not support -miu or -i -m -u, since m and u are only modifiers to + -i, they are not command-line options in their own right. The syntax + supported by this implementation is backwards-compatible with the stan- + dard. For best compatibility, scripts should limit themselves to the + standard syntax. + +SEE ALSO + bzip2(1), gzip(1), mt(1), pax(1), tar(1), libarchive(3), cpio(5), + libarchive-formats(5), tar(5) + +STANDARDS + There is no current POSIX standard for the cpio command; it appeared in + ISO/IEC 9945-1:1996 (``POSIX.1'') but was dropped from IEEE Std + 1003.1-2001 (``POSIX.1''). + + The cpio, ustar, and pax interchange file formats are defined by IEEE Std + 1003.1-2001 (``POSIX.1'') for the pax command. + +HISTORY + The original cpio and find utilities were written by Dick Haight while + working in AT&T's Unix Support Group. They first appeared in 1977 in + PWB/UNIX 1.0, the ``Programmer's Work Bench'' system developed for use + within AT&T. They were first released outside of AT&T as part of System + III Unix in 1981. As a result, cpio actually predates tar, even though + it was not well-known outside of AT&T until some time later. + + This is a complete re-implementation based on the libarchive(3) library. + +BUGS + The cpio archive format has several basic limitations: It does not store + user and group names, only numbers. As a result, it cannot be reliably + used to transfer files between systems with dissimilar user and group + numbering. Older cpio formats limit the user and group numbers to 16 or + 18 bits, which is insufficient for modern systems. The cpio archive for- + mats cannot support files over 4 gigabytes, except for the ``odc'' vari- + ant, which can support files up to 8 gigabytes. + +BSD September 16, 2014 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/bsdtar.1.txt b/dependencies/libarchive-3.4.2/doc/text/bsdtar.1.txt new file mode 100644 index 0000000..e653b93 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/bsdtar.1.txt @@ -0,0 +1,841 @@ +TAR(1) BSD General Commands Manual TAR(1) + +NAME + tar -- manipulate tape archives + +SYNOPSIS + tar [bundled-flags ] [ | ...] + tar {-c} [options] [files | directories] + tar {-r | -u} -f archive-file [options] [files | directories] + tar {-t | -x} [options] [patterns] + +DESCRIPTION + tar creates and manipulates streaming archive files. This implementation + can extract from tar, pax, cpio, zip, jar, ar, xar, rpm, 7-zip, and ISO + 9660 cdrom images and can create tar, pax, cpio, ar, zip, 7-zip, and shar + archives. + + The first synopsis form shows a ``bundled'' option word. This usage is + provided for compatibility with historical implementations. See COMPATI- + BILITY below for details. + + The other synopsis forms show the preferred usage. The first option to + tar is a mode indicator from the following list: + -c Create a new archive containing the specified items. The long + option form is --create. + -r Like -c, but new entries are appended to the archive. Note that + this only works on uncompressed archives stored in regular files. + The -f option is required. The long option form is --append. + -t List archive contents to stdout. The long option form is --list. + -u Like -r, but new entries are added only if they have a modifica- + tion date newer than the corresponding entry in the archive. + Note that this only works on uncompressed archives stored in reg- + ular files. The -f option is required. The long form is + --update. + -x Extract to disk from the archive. If a file with the same name + appears more than once in the archive, each copy will be + extracted, with later copies overwriting (replacing) earlier + copies. The long option form is --extract. + + In -c, -r, or -u mode, each specified file or directory is added to the + archive in the order specified on the command line. By default, the con- + tents of each directory are also archived. + + In extract or list mode, the entire command line is read and parsed + before the archive is opened. The pathnames or patterns on the command + line indicate which items in the archive should be processed. Patterns + are shell-style globbing patterns as documented in tcsh(1). + +OPTIONS + Unless specifically stated otherwise, options are applicable in all oper- + ating modes. + + @archive + (c and r modes only) The specified archive is opened and the + entries in it will be appended to the current archive. As a sim- + ple example, + tar -c -f - newfile @original.tar + writes a new archive to standard output containing a file newfile + and all of the entries from original.tar. In contrast, + tar -c -f - newfile original.tar + creates a new archive with only two entries. Similarly, + tar -czf - --format pax @- + reads an archive from standard input (whose format will be deter- + mined automatically) and converts it into a gzip-compressed pax- + format archive on stdout. In this way, tar can be used to con- + vert archives from one format to another. + + -a, --auto-compress + (c mode only) Use the archive suffix to decide a set of the for- + mat and the compressions. As a simple example, + tar -a -cf archive.tgz source.c source.h + creates a new archive with restricted pax format and gzip com- + pression, + tar -a -cf archive.tar.bz2.uu source.c source.h + creates a new archive with restricted pax format and bzip2 com- + pression and uuencode compression, + tar -a -cf archive.zip source.c source.h + creates a new archive with zip format, + tar -a -jcf archive.tgz source.c source.h + ignores the ``-j'' option, and creates a new archive with + restricted pax format and gzip compression, + tar -a -jcf archive.xxx source.c source.h + if it is unknown suffix or no suffix, creates a new archive with + restricted pax format and bzip2 compression. + + --acls (c, r, u, x modes only) Archive or extract POSIX.1e or NFSv4 + ACLs. This is the reverse of --no-acls and the default behavior + in c, r, and u modes (except on Mac OS X) or if tar is run in x + mode as root. On Mac OS X this option translates extended ACLs + to NFSv4 ACLs. To store extended ACLs the --mac-metadata option + is preferred. + + -B, --read-full-blocks + Ignored for compatibility with other tar(1) implementations. + + -b blocksize, --block-size blocksize + Specify the block size, in 512-byte records, for tape drive I/O. + As a rule, this argument is only needed when reading from or + writing to tape drives, and usually not even then as the default + block size of 20 records (10240 bytes) is very common. + + -C directory, --cd directory, --directory directory + In c and r mode, this changes the directory before adding the + following files. In x mode, change directories after opening the + archive but before extracting entries from the archive. + + --chroot + (x mode only) chroot() to the current directory after processing + any -C options and before extracting any files. + + --clear-nochange-fflags + (x mode only) Before removing file system objects to replace + them, clear platform-specific file attributes or file flags that + might prevent removal. + + --exclude pattern + Do not process files or directories that match the specified pat- + tern. Note that exclusions take precedence over patterns or + filenames specified on the command line. + + --exclude-vcs + Do not process files or directories internally used by the ver- + sion control systems 'Arch', 'Bazaar', 'CVS', 'Darcs', + 'Mercurial', 'RCS', 'SCCS', 'SVN' and 'git'. + + --fflags + (c, r, u, x modes only) Archive or extract platform-specific file + attributes or file flags. This is the reverse of --no-fflags and + the default behavior in c, r, and u modes or if tar is run in x + mode as root. + + --format format + (c, r, u mode only) Use the specified format for the created ar- + chive. Supported formats include ``cpio'', ``pax'', ``shar'', + and ``ustar''. Other formats may also be supported; see + libarchive-formats(5) for more information about currently-sup- + ported formats. In r and u modes, when extending an existing ar- + chive, the format specified here must be compatible with the for- + mat of the existing archive on disk. + + -f file, --file file + Read the archive from or write the archive to the specified file. + The filename can be - for standard input or standard output. The + default varies by system; on FreeBSD, the default is /dev/sa0; on + Linux, the default is /dev/st0. + + --gid id + Use the provided group id number. On extract, this overrides the + group id in the archive; the group name in the archive will be + ignored. On create, this overrides the group id read from disk; + if --gname is not also specified, the group name will be set to + match the group id. + + --gname name + Use the provided group name. On extract, this overrides the + group name in the archive; if the provided group name does not + exist on the system, the group id (from the archive or from the + --gid option) will be used instead. On create, this sets the + group name that will be stored in the archive; the name will not + be verified against the system group database. + + -H (c and r modes only) Symbolic links named on the command line + will be followed; the target of the link will be archived, not + the link itself. + + -h (c and r modes only) Synonym for -L. + + -I Synonym for -T. + + --help Show usage. + + --hfsCompression + (x mode only) Mac OS X specific (v10.6 or later). Compress + extracted regular files with HFS+ compression. + + --ignore-zeros + An alias of --options read_concatenated_archives for compatibil- + ity with GNU tar. + + --include pattern + Process only files or directories that match the specified pat- + tern. Note that exclusions specified with --exclude take prece- + dence over inclusions. If no inclusions are explicitly speci- + fied, all entries are processed by default. The --include option + is especially useful when filtering archives. For example, the + command + tar -c -f new.tar --include='*foo*' @old.tgz + creates a new archive new.tar containing only the entries from + old.tgz containing the string 'foo'. + + -J, --xz + (c mode only) Compress the resulting archive with xz(1). In + extract or list modes, this option is ignored. Note that this + tar implementation recognizes XZ compression automatically when + reading archives. + + -j, --bzip, --bzip2, --bunzip2 + (c mode only) Compress the resulting archive with bzip2(1). In + extract or list modes, this option is ignored. Note that this + tar implementation recognizes bzip2 compression automatically + when reading archives. + + -k, --keep-old-files + (x mode only) Do not overwrite existing files. In particular, if + a file appears more than once in an archive, later copies will + not overwrite earlier copies. + + --keep-newer-files + (x mode only) Do not overwrite existing files that are newer than + the versions appearing in the archive being extracted. + + -L, --dereference + (c and r modes only) All symbolic links will be followed. Nor- + mally, symbolic links are archived as such. With this option, + the target of the link will be archived instead. + + -l, --check-links + (c and r modes only) Issue a warning message unless all links to + each file are archived. + + --lrzip + (c mode only) Compress the resulting archive with lrzip(1). In + extract or list modes, this option is ignored. Note that this + tar implementation recognizes lrzip compression automatically + when reading archives. + + --lz4 (c mode only) Compress the archive with lz4-compatible compres- + sion before writing it. In extract or list modes, this option is + ignored. Note that this tar implementation recognizes lz4 com- + pression automatically when reading archives. + + --zstd (c mode only) Compress the archive with zstd-compatible compres- + sion before writing it. In extract or list modes, this option is + ignored. Note that this tar implementation recognizes zstd com- + pression automatically when reading archives. + + --lzma (c mode only) Compress the resulting archive with the original + LZMA algorithm. In extract or list modes, this option is + ignored. Use of this option is discouraged and new archives + should be created with --xz instead. Note that this tar imple- + mentation recognizes LZMA compression automatically when reading + archives. + + --lzop (c mode only) Compress the resulting archive with lzop(1). In + extract or list modes, this option is ignored. Note that this + tar implementation recognizes LZO compression automatically when + reading archives. + + -m, --modification-time + (x mode only) Do not extract modification time. By default, the + modification time is set to the time stored in the archive. + + --mac-metadata + (c, r, u and x mode only) Mac OS X specific. Archive or extract + extended ACLs and extended file attributes using copyfile(3) in + AppleDouble format. This is the reverse of --no-mac-metadata. + and the default behavior in c, r, and u modes or if tar is run in + x mode as root. + + -n, --norecurse, --no-recursion + Do not operate recursively on the content of directories. + + --newer date + (c, r, u modes only) Only include files and directories newer + than the specified date. This compares ctime entries. + + --newer-mtime date + (c, r, u modes only) Like --newer, except it compares mtime + entries instead of ctime entries. + + --newer-than file + (c, r, u modes only) Only include files and directories newer + than the specified file. This compares ctime entries. + + --newer-mtime-than file + (c, r, u modes only) Like --newer-than, except it compares mtime + entries instead of ctime entries. + + --nodump + (c and r modes only) Honor the nodump file flag by skipping this + file. + + --nopreserveHFSCompression + (x mode only) Mac OS X specific (v10.6 or later). Do not compress + extracted regular files which were compressed with HFS+ compres- + sion before archived. By default, compress the regular files + again with HFS+ compression. + + --null (use with -I or -T) Filenames or patterns are separated by null + characters, not by newlines. This is often used to read file- + names output by the -print0 option to find(1). + + --no-acls + (c, r, u, x modes only) Do not archive or extract POSIX.1e or + NFSv4 ACLs. This is the reverse of --acls and the default behav- + ior if tar is run as non-root in x mode (on Mac OS X as any user + in c, r, u and x modes). + + --no-fflags + (c, r, u, x modes only) Do not archive or extract file attributes + or file flags. This is the reverse of --fflags and the default + behavior if tar is run as non-root in x mode. + + --no-mac-metadata + (x mode only) Mac OS X specific. Do not archive or extract ACLs + and extended file attributes using copyfile(3) in AppleDouble + format. This is the reverse of --mac-metadata. and the default + behavior if tar is run as non-root in x mode. + + --no-safe-writes + (x mode only) Do not create temporary files and use rename(2) to + replace the original ones. This is the reverse of --safe-writes. + + --no-same-owner + (x mode only) Do not extract owner and group IDs. This is the + reverse of --same-owner and the default behavior if tar is run as + non-root. + + --no-same-permissions + (x mode only) Do not extract full permissions (SGID, SUID, sticky + bit, file attributes or file flags, extended file attributes and + ACLs). This is the reverse of -p and the default behavior if tar + is run as non-root. + + --no-xattrs + (c, r, u, x modes only) Do not archive or extract extended file + attributes. This is the reverse of --xattrs and the default + behavior if tar is run as non-root in x mode. + + --numeric-owner + This is equivalent to --uname "" --gname "". On extract, it + causes user and group names in the archive to be ignored in favor + of the numeric user and group ids. On create, it causes user and + group names to not be stored in the archive. + + -O, --to-stdout + (x, t modes only) In extract (-x) mode, files will be written to + standard out rather than being extracted to disk. In list (-t) + mode, the file listing will be written to stderr rather than the + usual stdout. + + -o (x mode) Use the user and group of the user running the program + rather than those specified in the archive. Note that this has + no significance unless -p is specified, and the program is being + run by the root user. In this case, the file modes and flags + from the archive will be restored, but ACLs or owner information + in the archive will be discarded. + + -o (c, r, u mode) A synonym for --format ustar + + --older date + (c, r, u modes only) Only include files and directories older + than the specified date. This compares ctime entries. + + --older-mtime date + (c, r, u modes only) Like --older, except it compares mtime + entries instead of ctime entries. + + --older-than file + (c, r, u modes only) Only include files and directories older + than the specified file. This compares ctime entries. + + --older-mtime-than file + (c, r, u modes only) Like --older-than, except it compares mtime + entries instead of ctime entries. + + --one-file-system + (c, r, and u modes) Do not cross mount points. + + --options options + Select optional behaviors for particular modules. The argument + is a text string containing comma-separated keywords and values. + These are passed to the modules that handle particular formats to + control how those formats will behave. Each option has one of + the following forms: + key=value + The key will be set to the specified value in every mod- + ule that supports it. Modules that do not support this + key will ignore it. + key The key will be enabled in every module that supports it. + This is equivalent to key=1. + !key The key will be disabled in every module that supports + it. + module:key=value, module:key, module:!key + As above, but the corresponding key and value will be + provided only to modules whose name matches module. + + The complete list of supported modules and keys for create and + append modes is in archive_write_set_options(3) and for extract + and list modes in archive_read_set_options(3). + + Examples of supported options: + iso9660:joliet + Support Joliet extensions. This is enabled by default, + use !joliet or iso9660:!joliet to disable. + iso9660:rockridge + Support Rock Ridge extensions. This is enabled by + default, use !rockridge or iso9660:!rockridge to disable. + gzip:compression-level + A decimal integer from 1 to 9 specifying the gzip com- + pression level. + gzip:timestamp + Store timestamp. This is enabled by default, use + !timestamp or gzip:!timestamp to disable. + lrzip:compression=type + Use type as compression method. Supported values are + bzip2, gzip, lzo (ultra fast), and zpaq (best, extremely + slow). + lrzip:compression-level + A decimal integer from 1 to 9 specifying the lrzip com- + pression level. + lz4:compression-level + A decimal integer from 1 to 9 specifying the lzop com- + pression level. + lz4:stream-checksum + Enable stream checksum. This is by default, use + lz4:!stream-checksum to disable. + lz4:block-checksum + Enable block checksum (Disabled by default). + lz4:block-size + A decimal integer from 4 to 7 specifying the lz4 compres- + sion block size (7 is set by default). + lz4:block-dependence + Use the previous block of the block being compressed for + a compression dictionary to improve compression ratio. + zstd:compression-level + A decimal integer from 1 to 22 specifying the zstd com- + pression level. + lzop:compression-level + A decimal integer from 1 to 9 specifying the lzop com- + pression level. + xz:compression-level + A decimal integer from 0 to 9 specifying the xz compres- + sion level. + mtree:keyword + The mtree writer module allows you to specify which mtree + keywords will be included in the output. Supported key- + words include: cksum, device, flags, gid, gname, indent, + link, md5, mode, nlink, rmd160, sha1, sha256, sha384, + sha512, size, time, uid, uname. The default is equiva- + lent to: ``device, flags, gid, gname, link, mode, nlink, + size, time, type, uid, uname''. + mtree:all + Enables all of the above keywords. You can also use + mtree:!all to disable all keywords. + mtree:use-set + Enable generation of /set lines in the output. + mtree:indent + Produce human-readable output by indenting options and + splitting lines to fit into 80 columns. + zip:compression=type + Use type as compression method. Supported values are + store (uncompressed) and deflate (gzip algorithm). + zip:encryption + Enable encryption using traditional zip encryption. + zip:encryption=type + Use type as encryption type. Supported values are + zipcrypt (traditional zip encryption), aes128 (WinZip + AES-128 encryption) and aes256 (WinZip AES-256 encryp- + tion). + read_concatenated_archives + Ignore zeroed blocks in the archive, which occurs when + multiple tar archives have been concatenated together. + Without this option, only the contents of the first con- + catenated archive would be read. This option is compara- + ble to the -i, --ignore-zeros option of GNU tar. + If a provided option is not supported by any module, that is a + fatal error. + + -P, --absolute-paths + Preserve pathnames. By default, absolute pathnames (those that + begin with a / character) have the leading slash removed both + when creating archives and extracting from them. Also, tar will + refuse to extract archive entries whose pathnames contain .. or + whose target directory would be altered by a symlink. This + option suppresses these behaviors. + + -p, --insecure, --preserve-permissions + (x mode only) Preserve file permissions. Attempt to restore the + full permissions, including file modes, file attributes or file + flags, extended file attributes and ACLs, if available, for each + item extracted from the archive. This is the reverse of + --no-same-permissions and the default if tar is being run as + root. It can be partially overridden by also specifying + --no-acls, --no-fflags, --no-mac-metadata or --no-xattrs. + + --passphrase passphrase + The passphrase is used to extract or create an encrypted archive. + Currently, zip is the only supported format that supports encryp- + tion. You shouldn't use this option unless you realize how inse- + cure use of this option is. + + --posix + (c, r, u mode only) Synonym for --format pax + + -q, --fast-read + (x and t mode only) Extract or list only the first archive entry + that matches each pattern or filename operand. Exit as soon as + each specified pattern or filename has been matched. By default, + the archive is always read to the very end, since there can be + multiple entries with the same name and, by convention, later + entries overwrite earlier entries. This option is provided as a + performance optimization. + + -S (x mode only) Extract files as sparse files. For every block on + disk, check first if it contains only NULL bytes and seek over it + otherwise. This works similar to the conv=sparse option of dd. + + -s pattern + Modify file or archive member names according to pattern. The + pattern has the format /old/new/[ghHprRsS] where old is a basic + regular expression, new is the replacement string of the matched + part, and the optional trailing letters modify how the replace- + ment is handled. If old is not matched, the pattern is skipped. + Within new, ~ is substituted with the match, \1 to \9 with the + content of the corresponding captured group. The optional trail- + ing g specifies that matching should continue after the matched + part and stop on the first unmatched pattern. The optional + trailing s specifies that the pattern applies to the value of + symbolic links. The optional trailing p specifies that after a + successful substitution the original path name and the new path + name should be printed to standard error. Optional trailing H, + R, or S characters suppress substitutions for hardlink targets, + regular filenames, or symlink targets, respectively. Optional + trailing h, r, or s characters enable substitutions for hardlink + targets, regular filenames, or symlink targets, respectively. + The default is hrs which applies substitutions to all names. In + particular, it is never necessary to specify h, r, or s. + + --safe-writes + (x mode only) Extract files atomically. By default tar unlinks + the original file with the same name as the extracted file (if it + exists), and then creates it immediately under the same name and + writes to it. For a short period of time, applications trying to + access the file might not find it, or see incomplete results. If + --safe-writes is enabled, tar first creates a unique temporary + file, then writes the new contents to the temporary file, and + finally renames the temporary file to its final name atomically + using rename(2). This guarantees that an application accessing + the file, will either see the old contents or the new contents at + all times. + + --same-owner + (x mode only) Extract owner and group IDs. This is the reverse + of --no-same-owner and the default behavior if tar is run as + root. + + --strip-components count + Remove the specified number of leading path elements. Pathnames + with fewer elements will be silently skipped. Note that the + pathname is edited after checking inclusion/exclusion patterns + but before security checks. + + -T filename, --files-from filename + In x or t mode, tar will read the list of names to be extracted + from filename. In c mode, tar will read names to be archived + from filename. The special name ``-C'' on a line by itself will + cause the current directory to be changed to the directory speci- + fied on the following line. Names are terminated by newlines + unless --null is specified. Note that --null also disables the + special handling of lines containing ``-C''. Note: If you are + generating lists of files using find(1), you probably want to use + -n as well. + + --totals + (c, r, u modes only) After archiving all files, print a summary + to stderr. + + -U, --unlink, --unlink-first + (x mode only) Unlink files before creating them. This can be a + minor performance optimization if most files already exist, but + can make things slower if most files do not already exist. This + flag also causes tar to remove intervening directory symlinks + instead of reporting an error. See the SECURITY section below + for more details. + + --uid id + Use the provided user id number and ignore the user name from the + archive. On create, if --uname is not also specified, the user + name will be set to match the user id. + + --uname name + Use the provided user name. On extract, this overrides the user + name in the archive; if the provided user name does not exist on + the system, it will be ignored and the user id (from the archive + or from the --uid option) will be used instead. On create, this + sets the user name that will be stored in the archive; the name + is not verified against the system user database. + + --use-compress-program program + Pipe the input (in x or t mode) or the output (in c mode) through + program instead of using the builtin compression support. + + -v, --verbose + Produce verbose output. In create and extract modes, tar will + list each file name as it is read from or written to the archive. + In list mode, tar will produce output similar to that of ls(1). + An additional -v option will also provide ls-like details in cre- + ate and extract mode. + + --version + Print version of tar and libarchive, and exit. + + -w, --confirmation, --interactive + Ask for confirmation for every action. + + -X filename, --exclude-from filename + Read a list of exclusion patterns from the specified file. See + --exclude for more information about the handling of exclusions. + + --xattrs + (c, r, u, x modes only) Archive or extract extended file + attributes. This is the reverse of --no-xattrs and the default + behavior in c, r, and u modes or if tar is run in x mode as root. + + -y (c mode only) Compress the resulting archive with bzip2(1). In + extract or list modes, this option is ignored. Note that this + tar implementation recognizes bzip2 compression automatically + when reading archives. + + -Z, --compress, --uncompress + (c mode only) Compress the resulting archive with compress(1). + In extract or list modes, this option is ignored. Note that this + tar implementation recognizes compress compression automatically + when reading archives. + + -z, --gunzip, --gzip + (c mode only) Compress the resulting archive with gzip(1). In + extract or list modes, this option is ignored. Note that this + tar implementation recognizes gzip compression automatically when + reading archives. + +ENVIRONMENT + The following environment variables affect the execution of tar: + + TAR_READER_OPTIONS + The default options for format readers and compression read- + ers. The --options option overrides this. + + TAR_WRITER_OPTIONS + The default options for format writers and compression writ- + ers. The --options option overrides this. + + LANG The locale to use. See environ(7) for more information. + + TAPE The default device. The -f option overrides this. Please see + the description of the -f option above for more details. + + TZ The timezone to use when displaying dates. See environ(7) for + more information. + +EXIT STATUS + The tar utility exits 0 on success, and >0 if an error occurs. + +EXAMPLES + The following creates a new archive called file.tar.gz that contains two + files source.c and source.h: + tar -czf file.tar.gz source.c source.h + + To view a detailed table of contents for this archive: + tar -tvf file.tar.gz + + To extract all entries from the archive on the default tape drive: + tar -x + + To examine the contents of an ISO 9660 cdrom image: + tar -tf image.iso + + To move file hierarchies, invoke tar as + tar -cf - -C srcdir . | tar -xpf - -C destdir + or more traditionally + cd srcdir ; tar -cf - . | (cd destdir ; tar -xpf -) + + In create mode, the list of files and directories to be archived can also + include directory change instructions of the form -Cfoo/baz and archive + inclusions of the form @archive-file. For example, the command line + tar -c -f new.tar foo1 @old.tgz -C/tmp foo2 + will create a new archive new.tar. tar will read the file foo1 from the + current directory and add it to the output archive. It will then read + each entry from old.tgz and add those entries to the output archive. + Finally, it will switch to the /tmp directory and add foo2 to the output + archive. + + An input file in mtree(5) format can be used to create an output archive + with arbitrary ownership, permissions, or names that differ from existing + data on disk: + + $ cat input.mtree + #mtree + usr/bin uid=0 gid=0 mode=0755 type=dir + usr/bin/ls uid=0 gid=0 mode=0755 type=file content=myls + $ tar -cvf output.tar @input.mtree + + The --newer and --newer-mtime switches accept a variety of common date + and time specifications, including ``12 Mar 2005 7:14:29pm'', + ``2005-03-12 19:14'', ``5 minutes ago'', and ``19:14 PST May 1''. + + The --options argument can be used to control various details of archive + generation or reading. For example, you can generate mtree output which + only contains type, time, and uid keywords: + tar -cf file.tar --format=mtree --options='!all,type,time,uid' dir + or you can set the compression level used by gzip or xz compression: + tar -czf file.tar --options='compression-level=9'. + For more details, see the explanation of the archive_read_set_options() + and archive_write_set_options() API calls that are described in + archive_read(3) and archive_write(3). + +COMPATIBILITY + The bundled-arguments format is supported for compatibility with historic + implementations. It consists of an initial word (with no leading - char- + acter) in which each character indicates an option. Arguments follow as + separate words. The order of the arguments must match the order of the + corresponding characters in the bundled command word. For example, + tar tbf 32 file.tar + specifies three flags t, b, and f. The b and f flags both require argu- + ments, so there must be two additional items on the command line. The 32 + is the argument to the b flag, and file.tar is the argument to the f + flag. + + The mode options c, r, t, u, and x and the options b, f, l, m, o, v, and + w comply with SUSv2. + + For maximum portability, scripts that invoke tar should use the bundled- + argument format above, should limit themselves to the c, t, and x modes, + and the b, f, m, v, and w options. + + Additional long options are provided to improve compatibility with other + tar implementations. + +SECURITY + Certain security issues are common to many archiving programs, including + tar. In particular, carefully-crafted archives can request that tar + extract files to locations outside of the target directory. This can + potentially be used to cause unwitting users to overwrite files they did + not intend to overwrite. If the archive is being extracted by the supe- + ruser, any file on the system can potentially be overwritten. There are + three ways this can happen. Although tar has mechanisms to protect + against each one, savvy users should be aware of the implications: + + o Archive entries can have absolute pathnames. By default, tar + removes the leading / character from filenames before restoring + them to guard against this problem. + + o Archive entries can have pathnames that include .. components. + By default, tar will not extract files containing .. components + in their pathname. + + o Archive entries can exploit symbolic links to restore files to + other directories. An archive can restore a symbolic link to + another directory, then use that link to restore a file into that + directory. To guard against this, tar checks each extracted path + for symlinks. If the final path element is a symlink, it will be + removed and replaced with the archive entry. If -U is specified, + any intermediate symlink will also be unconditionally removed. + If neither -U nor -P is specified, tar will refuse to extract the + entry. + To protect yourself, you should be wary of any archives that come from + untrusted sources. You should examine the contents of an archive with + tar -tf filename + before extraction. You should use the -k option to ensure that tar will + not overwrite any existing files or the -U option to remove any pre- + existing files. You should generally not extract archives while running + with super-user privileges. Note that the -P option to tar disables the + security checks above and allows you to extract an archive while preserv- + ing any absolute pathnames, .. components, or symlinks to other directo- + ries. + +SEE ALSO + bzip2(1), compress(1), cpio(1), gzip(1), mt(1), pax(1), shar(1), xz(1), + libarchive(3), libarchive-formats(5), tar(5) + +STANDARDS + There is no current POSIX standard for the tar command; it appeared in + ISO/IEC 9945-1:1996 (``POSIX.1'') but was dropped from IEEE Std + 1003.1-2001 (``POSIX.1''). The options supported by this implementation + were developed by surveying a number of existing tar implementations as + well as the old POSIX specification for tar and the current POSIX speci- + fication for pax. + + The ustar and pax interchange file formats are defined by IEEE Std + 1003.1-2001 (``POSIX.1'') for the pax command. + +HISTORY + A tar command appeared in Seventh Edition Unix, which was released in + January, 1979. There have been numerous other implementations, many of + which extended the file format. John Gilmore's pdtar public-domain + implementation (circa November, 1987) was quite influential, and formed + the basis of GNU tar. GNU tar was included as the standard system tar in + FreeBSD beginning with FreeBSD 1.0. + + This is a complete re-implementation based on the libarchive(3) library. + It was first released with FreeBSD 5.4 in May, 2005. + +BUGS + This program follows ISO/IEC 9945-1:1996 (``POSIX.1'') for the definition + of the -l option. Note that GNU tar prior to version 1.15 treated -l as + a synonym for the --one-file-system option. + + The -C dir option may differ from historic implementations. + + All archive output is written in correctly-sized blocks, even if the out- + put is being compressed. Whether or not the last output block is padded + to a full block size varies depending on the format and the output + device. For tar and cpio formats, the last block of output is padded to + a full block size if the output is being written to standard output or to + a character or block device such as a tape drive. If the output is being + written to a regular file, the last block will not be padded. Many com- + pressors, including gzip(1) and bzip2(1), complain about the null padding + when decompressing an archive created by tar, although they still extract + it correctly. + + The compression and decompression is implemented internally, so there may + be insignificant differences between the compressed output generated by + tar -czf - file + and that generated by + tar -cf - file | gzip + + The default should be to read and write archives to the standard I/O + paths, but tradition (and POSIX) dictates otherwise. + + The r and u modes require that the archive be uncompressed and located in + a regular file on disk. Other archives can be modified using c mode with + the @archive-file extension. + + To archive a file called @foo or -foo you must specify it as ./@foo or + ./-foo, respectively. + + In create mode, a leading ./ is always removed. A leading / is stripped + unless the -P option is specified. + + There needs to be better support for file selection on both create and + extract. + + There is not yet any support for multi-volume archives. + + Converting between dissimilar archive formats (such as tar and cpio) + using the @- convention can cause hard link information to be lost. + (This is a consequence of the incompatible ways that different archive + formats store hardlink information.) + +BSD January 31, 2020 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/cpio.5.txt b/dependencies/libarchive-3.4.2/doc/text/cpio.5.txt new file mode 100644 index 0000000..3efa5d1 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/cpio.5.txt @@ -0,0 +1,235 @@ +CPIO(5) BSD File Formats Manual CPIO(5) + +NAME + cpio -- format of cpio archive files + +DESCRIPTION + The cpio archive format collects any number of files, directories, and + other file system objects (symbolic links, device nodes, etc.) into a + single stream of bytes. + + General Format + Each file system object in a cpio archive comprises a header record with + basic numeric metadata followed by the full pathname of the entry and the + file data. The header record stores a series of integer values that gen- + erally follow the fields in struct stat. (See stat(2) for details.) The + variants differ primarily in how they store those integers (binary, + octal, or hexadecimal). The header is followed by the pathname of the + entry (the length of the pathname is stored in the header) and any file + data. The end of the archive is indicated by a special record with the + pathname ``TRAILER!!!''. + + PWB format + XXX Any documentation of the original PWB/UNIX 1.0 format? XXX + + Old Binary Format + The old binary cpio format stores numbers as 2-byte and 4-byte binary + values. Each entry begins with a header in the following format: + + struct header_old_cpio { + unsigned short c_magic; + unsigned short c_dev; + unsigned short c_ino; + unsigned short c_mode; + unsigned short c_uid; + unsigned short c_gid; + unsigned short c_nlink; + unsigned short c_rdev; + unsigned short c_mtime[2]; + unsigned short c_namesize; + unsigned short c_filesize[2]; + }; + + The unsigned short fields here are 16-bit integer values; the unsigned + int fields are 32-bit integer values. The fields are as follows + + magic The integer value octal 070707. This value can be used to deter- + mine whether this archive is written with little-endian or big- + endian integers. + + dev, ino + The device and inode numbers from the disk. These are used by + programs that read cpio archives to determine when two entries + refer to the same file. Programs that synthesize cpio archives + should be careful to set these to distinct values for each entry. + + mode The mode specifies both the regular permissions and the file + type. It consists of several bit fields as follows: + 0170000 This masks the file type bits. + 0140000 File type value for sockets. + 0120000 File type value for symbolic links. For symbolic links, + the link body is stored as file data. + 0100000 File type value for regular files. + 0060000 File type value for block special devices. + 0040000 File type value for directories. + 0020000 File type value for character special devices. + 0010000 File type value for named pipes or FIFOs. + 0004000 SUID bit. + 0002000 SGID bit. + 0001000 Sticky bit. On some systems, this modifies the behavior + of executables and/or directories. + 0000777 The lower 9 bits specify read/write/execute permissions + for world, group, and user following standard POSIX con- + ventions. + + uid, gid + The numeric user id and group id of the owner. + + nlink The number of links to this file. Directories always have a + value of at least two here. Note that hardlinked files include + file data with every copy in the archive. + + rdev For block special and character special entries, this field con- + tains the associated device number. For all other entry types, + it should be set to zero by writers and ignored by readers. + + mtime Modification time of the file, indicated as the number of seconds + since the start of the epoch, 00:00:00 UTC January 1, 1970. The + four-byte integer is stored with the most-significant 16 bits + first followed by the least-significant 16 bits. Each of the two + 16 bit values are stored in machine-native byte order. + + namesize + The number of bytes in the pathname that follows the header. + This count includes the trailing NUL byte. + + filesize + The size of the file. Note that this archive format is limited + to four gigabyte file sizes. See mtime above for a description + of the storage of four-byte integers. + + The pathname immediately follows the fixed header. If the namesize is + odd, an additional NUL byte is added after the pathname. The file data + is then appended, padded with NUL bytes to an even length. + + Hardlinked files are not given special treatment; the full file contents + are included with each copy of the file. + + Portable ASCII Format + Version 2 of the Single UNIX Specification (``SUSv2'') standardized an + ASCII variant that is portable across all platforms. It is commonly + known as the ``old character'' format or as the ``odc'' format. It + stores the same numeric fields as the old binary format, but represents + them as 6-character or 11-character octal values. + + struct cpio_odc_header { + char c_magic[6]; + char c_dev[6]; + char c_ino[6]; + char c_mode[6]; + char c_uid[6]; + char c_gid[6]; + char c_nlink[6]; + char c_rdev[6]; + char c_mtime[11]; + char c_namesize[6]; + char c_filesize[11]; + }; + + The fields are identical to those in the old binary format. The name and + file body follow the fixed header. Unlike the old binary format, there + is no additional padding after the pathname or file contents. If the + files being archived are themselves entirely ASCII, then the resulting + archive will be entirely ASCII, except for the NUL byte that terminates + the name field. + + New ASCII Format + The "new" ASCII format uses 8-byte hexadecimal fields for all numbers and + separates device numbers into separate fields for major and minor num- + bers. + + struct cpio_newc_header { + char c_magic[6]; + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; + }; + + Except as specified below, the fields here match those specified for the + old binary format above. + + magic The string ``070701''. + + check This field is always set to zero by writers and ignored by read- + ers. See the next section for more details. + + The pathname is followed by NUL bytes so that the total size of the fixed + header plus pathname is a multiple of four. Likewise, the file data is + padded to a multiple of four bytes. Note that this format supports only + 4 gigabyte files (unlike the older ASCII format, which supports 8 giga- + byte files). + + In this format, hardlinked files are handled by setting the filesize to + zero for each entry except the last one that appears in the archive. + + New CRC Format + The CRC format is identical to the new ASCII format described in the pre- + vious section except that the magic field is set to ``070702'' and the + check field is set to the sum of all bytes in the file data. This sum is + computed treating all bytes as unsigned values and using unsigned arith- + metic. Only the least-significant 32 bits of the sum are stored. + + HP variants + The cpio implementation distributed with HPUX used XXXX but stored device + numbers differently XXX. + + Other Extensions and Variants + Sun Solaris uses additional file types to store extended file data, + including ACLs and extended attributes, as special entries in cpio ar- + chives. + + XXX Others? XXX + +SEE ALSO + cpio(1), tar(5) + +STANDARDS + The cpio utility is no longer a part of POSIX or the Single Unix Stan- + dard. It last appeared in Version 2 of the Single UNIX Specification + (``SUSv2''). It has been supplanted in subsequent standards by pax(1). + The portable ASCII format is currently part of the specification for the + pax(1) utility. + +HISTORY + The original cpio utility was written by Dick Haight while working in + AT&T's Unix Support Group. It appeared in 1977 as part of PWB/UNIX 1.0, + the ``Programmer's Work Bench'' derived from Version 6 AT&T UNIX that was + used internally at AT&T. Both the old binary and old character formats + were in use by 1980, according to the System III source released by SCO + under their ``Ancient Unix'' license. The character format was adopted + as part of IEEE Std 1003.1-1988 (``POSIX.1''). XXX when did "newc" + appear? Who invented it? When did HP come out with their variant? When + did Sun introduce ACLs and extended attributes? XXX + +BUGS + The ``CRC'' format is mis-named, as it uses a simple checksum and not a + cyclic redundancy check. + + The old binary format is limited to 16 bits for user id, group id, + device, and inode numbers. It is limited to 4 gigabyte file sizes. + + The old ASCII format is limited to 18 bits for the user id, group id, + device, and inode numbers. It is limited to 8 gigabyte file sizes. + + The new ASCII format is limited to 4 gigabyte file sizes. + + None of the cpio formats store user or group names, which are essential + when moving files between systems with dissimilar user or group number- + ing. + + Especially when writing older cpio variants, it may be necessary to map + actual device/inode values to synthesized values that fit the available + fields. With very large filesystems, this may be necessary even for the + newer formats. + +BSD December 23, 2011 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/libarchive-formats.5.txt b/dependencies/libarchive-3.4.2/doc/text/libarchive-formats.5.txt new file mode 100644 index 0000000..18e0dc4 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/libarchive-formats.5.txt @@ -0,0 +1,333 @@ +LIBARCHIVE-FORMATS(5) BSD File Formats Manual LIBARCHIVE-FORMATS(5) + +NAME + libarchive-formats -- archive formats supported by the libarchive library + +DESCRIPTION + The libarchive(3) library reads and writes a variety of streaming archive + formats. Generally speaking, all of these archive formats consist of a + series of ``entries''. Each entry stores a single file system object, + such as a file, directory, or symbolic link. + + The following provides a brief description of each format supported by + libarchive, with some information about recognized extensions or limita- + tions of the current library support. Note that just because a format is + supported by libarchive does not imply that a program that uses + libarchive will support that format. Applications that use libarchive + specify which formats they wish to support, though many programs do use + libarchive convenience functions to enable all supported formats. + + Tar Formats + The libarchive(3) library can read most tar archives. It can write + POSIX-standard ``ustar'' and ``pax interchange'' formats as well as v7 + tar format and a subset of the legacy GNU tar format. + + All tar formats store each entry in one or more 512-byte records. The + first record is used for file metadata, including filename, timestamp, + and mode information, and the file data is stored in subsequent records. + Later variants have extended this by either appropriating undefined areas + of the header record, extending the header to multiple records, or by + storing special entries that modify the interpretation of subsequent + entries. + + gnutar The libarchive(3) library can read most GNU-format tar archives. + It currently supports the most popular GNU extensions, including + modern long filename and linkname support, as well as atime and + ctime data. The libarchive library does not support multi-volume + archives, nor the old GNU long filename format. It can read GNU + sparse file entries, including the new POSIX-based formats. + + The libarchive(3) library can write GNU tar format, including + long filename and linkname support, as well as atime and ctime + data. + + pax The libarchive(3) library can read and write POSIX-compliant pax + interchange format archives. Pax interchange format archives are + an extension of the older ustar format that adds a separate entry + with additional attributes stored as key/value pairs immediately + before each regular entry. The presence of these additional + entries is the only difference between pax interchange format and + the older ustar format. The extended attributes are of unlimited + length and are stored as UTF-8 Unicode strings. Keywords defined + in the standard are in all lowercase; vendors are allowed to + define custom keys by preceding them with the vendor name in all + uppercase. When writing pax archives, libarchive uses many of + the SCHILY keys defined by Joerg Schilling's ``star'' archiver + and a few LIBARCHIVE keys. The libarchive library can read most + of the SCHILY keys and most of the GNU keys introduced by GNU + tar. It silently ignores any keywords that it does not under- + stand. + + The pax interchange format converts filenames to Unicode and + stores them using the UTF-8 encoding. Prior to libarchive 3.0, + libarchive erroneously assumed that the system wide-character + routines natively supported Unicode. This caused it to mis-han- + dle non-ASCII filenames on systems that did not satisfy this + assumption. + + restricted pax + The libarchive library can also write pax archives in which it + attempts to suppress the extended attributes entry whenever pos- + sible. The result will be identical to a ustar archive unless + the extended attributes entry is required to store a long file + name, long linkname, extended ACL, file flags, or if any of the + standard ustar data (user name, group name, UID, GID, etc) cannot + be fully represented in the ustar header. In all cases, the + result can be dearchived by any program that can read POSIX-com- + pliant pax interchange format archives. Programs that correctly + read ustar format (see below) will also be able to read this for- + mat; any extended attributes will be extracted as separate files + stored in PaxHeader directories. + + ustar The libarchive library can both read and write this format. This + format has the following limitations: + o Device major and minor numbers are limited to 21 bits. Nodes + with larger numbers will not be added to the archive. + o Path names in the archive are limited to 255 bytes. (Shorter + if there is no / character in exactly the right place.) + o Symbolic links and hard links are stored in the archive with + the name of the referenced file. This name is limited to 100 + bytes. + o Extended attributes, file flags, and other extended security + information cannot be stored. + o Archive entries are limited to 8 gigabytes in size. + Note that the pax interchange format has none of these restric- + tions. The ustar format is old and widely supported. It is rec- + ommended when compatibility is the primary concern. + + v7 The libarchive library can read and write the legacy v7 tar for- + mat. This format has the following limitations: + o Only regular files, directories, and symbolic links can be + archived. Block and character device nodes, FIFOs, and sock- + ets cannot be archived. + o Path names in the archive are limited to 100 bytes. + o Symbolic links and hard links are stored in the archive with + the name of the referenced file. This name is limited to 100 + bytes. + o User and group information are stored as numeric IDs; there + is no provision for storing user or group names. + o Extended attributes, file flags, and other extended security + information cannot be stored. + o Archive entries are limited to 8 gigabytes in size. + Generally, users should prefer the ustar format for portability + as the v7 tar format is both less useful and less portable. + + The libarchive library also reads a variety of commonly-used extensions + to the basic tar format. These extensions are recognized automatically + whenever they appear. + + Numeric extensions. + The POSIX standards require fixed-length numeric fields to be + written with some character position reserved for terminators. + Libarchive allows these fields to be written without terminator + characters. This extends the allowable range; in particular, + ustar archives with this extension can support entries up to 64 + gigabytes in size. Libarchive also recognizes base-256 values in + most numeric fields. This essentially removes all limitations on + file size, modification time, and device numbers. + + Solaris extensions + Libarchive recognizes ACL and extended attribute records written + by Solaris tar. + + The first tar program appeared in Seventh Edition Unix in 1979. The + first official standard for the tar file format was the ``ustar'' (Unix + Standard Tar) format defined by POSIX in 1988. POSIX.1-2001 extended the + ustar format to create the ``pax interchange'' format. + + Cpio Formats + The libarchive library can read a number of common cpio variants and can + write ``odc'' and ``newc'' format archives. A cpio archive stores each + entry as a fixed-size header followed by a variable-length filename and + variable-length data. Unlike the tar format, the cpio format does only + minimal padding of the header or file data. There are several cpio vari- + ants, which differ primarily in how they store the initial header: some + store the values as octal or hexadecimal numbers in ASCII, others as + binary values of varying byte order and length. + + binary The libarchive library transparently reads both big-endian and + little-endian variants of the original binary cpio format. This + format used 32-bit binary values for file size and mtime, and + 16-bit binary values for the other fields. + + odc The libarchive library can both read and write this POSIX-stan- + dard format, which is officially known as the ``cpio interchange + format'' or the ``octet-oriented cpio archive format'' and some- + times unofficially referred to as the ``old character format''. + This format stores the header contents as octal values in ASCII. + It is standard, portable, and immune from byte-order confusion. + File sizes and mtime are limited to 33 bits (8GB file size), + other fields are limited to 18 bits. + + SVR4/newc + The libarchive library can read both CRC and non-CRC variants of + this format. The SVR4 format uses eight-digit hexadecimal values + for all header fields. This limits file size to 4GB, and also + limits the mtime and other fields to 32 bits. The SVR4 format + can optionally include a CRC of the file contents, although + libarchive does not currently verify this CRC. + + Cpio first appeared in PWB/UNIX 1.0, which was released within AT&T in + 1977. PWB/UNIX 1.0 formed the basis of System III Unix, released outside + of AT&T in 1981. This makes cpio older than tar, although cpio was not + included in Version 7 AT&T Unix. As a result, the tar command became + much better known in universities and research groups that used Version + 7. The combination of the find and cpio utilities provided very precise + control over file selection. Unfortunately, the format has many limita- + tions that make it unsuitable for widespread use. Only the POSIX format + permits files over 4GB, and its 18-bit limit for most other fields makes + it unsuitable for modern systems. In addition, cpio formats only store + numeric UID/GID values (not usernames and group names), which can make it + very difficult to correctly transfer archives across systems with dissim- + ilar user numbering. + + Shar Formats + A ``shell archive'' is a shell script that, when executed on a POSIX-com- + pliant system, will recreate a collection of file system objects. The + libarchive library can write two different kinds of shar archives: + + shar The traditional shar format uses a limited set of POSIX commands, + including echo(1), mkdir(1), and sed(1). It is suitable for + portably archiving small collections of plain text files. How- + ever, it is not generally well-suited for large archives (many + implementations of sh(1) have limits on the size of a script) nor + should it be used with non-text files. + + shardump + This format is similar to shar but encodes files using + uuencode(1) so that the result will be a plain text file regard- + less of the file contents. It also includes additional shell + commands that attempt to reproduce as many file attributes as + possible, including owner, mode, and flags. The additional com- + mands used to restore file attributes make shardump archives less + portable than plain shar archives. + + ISO9660 format + Libarchive can read and extract from files containing ISO9660-compliant + CDROM images. In many cases, this can remove the need to burn a physical + CDROM just in order to read the files contained in an ISO9660 image. It + also avoids security and complexity issues that come with virtual mounts + and loopback devices. Libarchive supports the most common Rockridge + extensions and has partial support for Joliet extensions. If both exten- + sions are present, the Joliet extensions will be used and the Rockridge + extensions will be ignored. In particular, this can create problems with + hardlinks and symlinks, which are supported by Rockridge but not by + Joliet. + + Libarchive reads ISO9660 images using a streaming strategy. This allows + it to read compressed images directly (decompressing on the fly) and + allows it to read images directly from network sockets, pipes, and other + non-seekable data sources. This strategy works well for optimized + ISO9660 images created by many popular programs. Such programs collect + all directory information at the beginning of the ISO9660 image so it can + be read from a physical disk with a minimum of seeking. However, not all + ISO9660 images can be read in this fashion. + + Libarchive can also write ISO9660 images. Such images are fully opti- + mized with the directory information preceding all file data. This is + done by storing all file data to a temporary file while collecting direc- + tory information in memory. When the image is finished, libarchive + writes out the directory structure followed by the file data. The loca- + tion used for the temporary file can be changed by the usual environment + variables. + + Zip format + Libarchive can read and write zip format archives that have uncompressed + entries and entries compressed with the ``deflate'' algorithm. Other zip + compression algorithms are not supported. It can extract jar archives, + archives that use Zip64 extensions and self-extracting zip archives. + Libarchive can use either of two different strategies for reading Zip ar- + chives: a streaming strategy which is fast and can handle extremely large + archives, and a seeking strategy which can correctly process self- + extracting Zip archives and archives with deleted members or other in- + place modifications. + + The streaming reader processes Zip archives as they are read. It can + read archives of arbitrary size from tape or network sockets, and can + decode Zip archives that have been separately compressed or encoded. + However, self-extracting Zip archives and archives with certain types of + modifications cannot be correctly handled. Such archives require that + the reader first process the Central Directory, which is ordinarily + located at the end of a Zip archive and is thus inaccessible to the + streaming reader. If the program using libarchive has enabled seek sup- + port, then libarchive will use this to processes the central directory + first. + + In particular, the seeking reader must be used to correctly handle self- + extracting archives. Such archives consist of a program followed by a + regular Zip archive. The streaming reader cannot parse the initial pro- + gram portion, but the seeking reader starts by reading the Central Direc- + tory from the end of the archive. Similarly, Zip archives that have been + modified in-place can have deleted entries or other garbage data that can + only be accurately detected by first reading the Central Directory. + + Archive (library) file format + The Unix archive format (commonly created by the ar(1) archiver) is a + general-purpose format which is used almost exclusively for object files + to be read by the link editor ld(1). The ar format has never been stan- + dardised. There are two common variants: the GNU format derived from + SVR4, and the BSD format, which first appeared in 4.4BSD. The two differ + primarily in their handling of filenames longer than 15 characters: the + GNU/SVR4 variant writes a filename table at the beginning of the archive; + the BSD format stores each long filename in an extension area adjacent to + the entry. Libarchive can read both extensions, including archives that + may include both types of long filenames. Programs using libarchive can + write GNU/SVR4 format if they provide an entry called // containing a + filename table to be written into the archive before any of the entries. + Any entries whose names are not in the filename table will be written + using BSD-style long filenames. This can cause problems for programs + such as GNU ld that do not support the BSD-style long filenames. + + mtree + Libarchive can read and write files in mtree(5) format. This format is + not a true archive format, but rather a textual description of a file + hierarchy in which each line specifies the name of a file and provides + specific metadata about that file. Libarchive can read all of the key- + words supported by both the NetBSD and FreeBSD versions of mtree(8), + although many of the keywords cannot currently be stored in an + archive_entry object. When writing, libarchive supports use of the + archive_write_set_options(3) interface to specify which keywords should + be included in the output. If libarchive was compiled with access to + suitable cryptographic libraries (such as the OpenSSL libraries), it can + compute hash entries such as sha512 or md5 from file data being written + to the mtree writer. + + When reading an mtree file, libarchive will locate the corresponding + files on disk using the contents keyword if present or the regular file- + name. If it can locate and open the file on disk, it will use that to + fill in any metadata that is missing from the mtree file and will read + the file contents and return those to the program using libarchive. If + it cannot locate and open the file on disk, libarchive will return an + error for any attempt to read the entry body. + + 7-Zip + Libarchive can read and write 7-Zip format archives. TODO: Need more + information + + CAB + Libarchive can read Microsoft Cabinet ( ``CAB'') format archives. TODO: + Need more information. + + LHA + TODO: Information about libarchive's LHA support + + RAR + Libarchive has limited support for reading RAR format archives. Cur- + rently, libarchive can read RARv3 format archives which have been either + created uncompressed, or compressed using any of the compression methods + supported by the RARv3 format. Libarchive can also read self-extracting + RAR archives. + + Warc + Libarchive can read and write ``web archives''. TODO: Need more informa- + tion + + XAR + Libarchive can read and write the XAR format used by many Apple tools. + TODO: Need more information + +SEE ALSO + ar(1), cpio(1), mkisofs(1), shar(1), tar(1), zip(1), zlib(3), cpio(5), + mtree(5), tar(5) + +BSD December 27, 2016 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/libarchive.3.txt b/dependencies/libarchive-3.4.2/doc/text/libarchive.3.txt new file mode 100644 index 0000000..3f461d8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/libarchive.3.txt @@ -0,0 +1,156 @@ +LIBARCHIVE(3) BSD Library Functions Manual LIBARCHIVE(3) + +NAME + libarchive -- functions for reading and writing streaming archives + +OVERVIEW + The libarchive library provides a flexible interface for reading and + writing archives in various formats such as tar and cpio. libarchive + also supports reading and writing archives compressed using various com- + pression filters such as gzip and bzip2. The library is inherently + stream-oriented; readers serially iterate through the archive, writers + serially add things to the archive. In particular, note that there is + currently no built-in support for random access nor for in-place modifi- + cation. + + When reading an archive, the library automatically detects the format and + the compression. The library currently has read support for: + o old-style tar archives, + o most variants of the POSIX ``ustar'' format, + o the POSIX ``pax interchange'' format, + o GNU-format tar archives, + o most common cpio archive formats, + o ISO9660 CD images (including RockRidge and Joliet extensions), + o Zip archives, + o ar archives (including GNU/SysV and BSD extensions), + o Microsoft CAB archives, + o LHA archives, + o mtree file tree descriptions, + o RAR archives, + o XAR archives. + The library automatically detects archives compressed with gzip(1), + bzip2(1), xz(1), lzip(1), or compress(1) and decompresses them transpar- + ently. It can similarly detect and decode archives processed with + uuencode(1) or which have an rpm(1) header. + + When writing an archive, you can specify the compression to be used and + the format to use. The library can write + o POSIX-standard ``ustar'' archives, + o POSIX ``pax interchange format'' archives, + o POSIX octet-oriented cpio archives, + o Zip archive, + o two different variants of shar archives, + o ISO9660 CD images, + o 7-Zip archives, + o ar archives, + o mtree file tree descriptions, + o XAR archives. + Pax interchange format is an extension of the tar archive format that + eliminates essentially all of the limitations of historic tar formats in + a standard fashion that is supported by POSIX-compliant pax(1) implemen- + tations on many systems as well as several newer implementations of + tar(1). Note that the default write format will suppress the pax + extended attributes for most entries; explicitly requesting pax format + will enable those attributes for all entries. + + The read and write APIs are accessed through the archive_read_XXX() func- + tions and the archive_write_XXX() functions, respectively, and either can + be used independently of the other. + + The rest of this manual page provides an overview of the library opera- + tion. More detailed information can be found in the individual manual + pages for each API or utility function. + +READING AN ARCHIVE + See archive_read(3). + +WRITING AN ARCHIVE + See archive_write(3). + +WRITING ENTRIES TO DISK + The archive_write_disk(3) API allows you to write archive_entry(3) + objects to disk using the same API used by archive_write(3). The + archive_write_disk(3) API is used internally by archive_read_extract(); + using it directly can provide greater control over how entries get writ- + ten to disk. This API also makes it possible to share code between ar- + chive-to-archive copy and archive-to-disk extraction operations. + +READING ENTRIES FROM DISK + The archive_read_disk(3) supports for populating archive_entry(3) objects + from information in the filesystem. This includes the information acces- + sible from the stat(2) system call as well as ACLs, extended attributes, + and other metadata. The archive_read_disk(3) API also supports iterating + over directory trees, which allows directories of files to be read using + an API compatible with the archive_read(3) API. + +DESCRIPTION + Detailed descriptions of each function are provided by the corresponding + manual pages. + + All of the functions utilize an opaque struct archive datatype that pro- + vides access to the archive contents. + + The struct archive_entry structure contains a complete description of a + single archive entry. It uses an opaque interface that is fully docu- + mented in archive_entry(3). + + Users familiar with historic formats should be aware that the newer vari- + ants have eliminated most restrictions on the length of textual fields. + Clients should not assume that filenames, link names, user names, or + group names are limited in length. In particular, pax interchange format + can easily accommodate pathnames in arbitrary character sets that exceed + PATH_MAX. + +RETURN VALUES + Most functions return ARCHIVE_OK (zero) on success, non-zero on error. + The return value indicates the general severity of the error, ranging + from ARCHIVE_WARN, which indicates a minor problem that should probably + be reported to the user, to ARCHIVE_FATAL, which indicates a serious + problem that will prevent any further operations on this archive. On + error, the archive_errno() function can be used to retrieve a numeric + error code (see errno(2)). The archive_error_string() returns a textual + error message suitable for display. + + archive_read_new() and archive_write_new() return pointers to an allo- + cated and initialized struct archive object. + + archive_read_data() and archive_write_data() return a count of the number + of bytes actually read or written. A value of zero indicates the end of + the data for this entry. A negative value indicates an error, in which + case the archive_errno() and archive_error_string() functions can be used + to obtain more information. + +ENVIRONMENT + There are character set conversions within the archive_entry(3) functions + that are impacted by the currently-selected locale. + +SEE ALSO + tar(1), archive_entry(3), archive_read(3), archive_util(3), + archive_write(3), tar(5) + +HISTORY + The libarchive library first appeared in FreeBSD 5.3. + +AUTHORS + The libarchive library was originally written by Tim Kientzle + . + +BUGS + Some archive formats support information that is not supported by struct + archive_entry. Such information cannot be fully archived or restored + using this library. This includes, for example, comments, character + sets, or the arbitrary key/value pairs that can appear in pax interchange + format archives. + + Conversely, of course, not all of the information that can be stored in + an struct archive_entry is supported by all formats. For example, cpio + formats do not support nanosecond timestamps; old tar formats do not sup- + port large device numbers. + + The ISO9660 reader cannot yet read all ISO9660 images; it should learn + how to seek. + + The AR writer requires the client program to use two passes, unlike all + other libarchive writers. + +BSD March 18, 2012 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/libarchive_changes.3.txt b/dependencies/libarchive-3.4.2/doc/text/libarchive_changes.3.txt new file mode 100644 index 0000000..54b6bb8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/libarchive_changes.3.txt @@ -0,0 +1,260 @@ +LIBARCHIVE_CHANGES(3) BSD Library Functions Manual LIBARCHIVE_CHANGES(3) + +NAME + libarchive_changes -- changes in libarchive interface + +CHANGES IN LIBARCHIVE 3 + This page describes user-visible changes in libarchive3, and lists public + functions and other symbols changed, deprecated or removed in + libarchive3, along with their replacements if any. + + Multiple Filters + Libarchive2 permitted a single (input or output) filter active on an ar- + chive. Libarchive3 extends this into a variable-length stack. Where + archive_write_set_compression_XXX() would replace any existing filter, + archive_write_add_filter_XXX() extends the write pipeline with another + filter. + + Character Set Handling + Libarchive2 assumed that the local platform uses Unicode as the native + wchar_t encoding, which is true on Windows, modern Linux, and a few other + systems, but is certainly not universal. As a result, pax format ar- + chives were written incorrectly on some systems, since pax format + requires UTF-8 and libarchive 2 incorrectly assumed that wchar_t strings + can be easily converted to UTF-8. + + Libarchive3 uses the standard iconv library to convert between character + sets and is introducing the notion of a ``default character set for the + archive''. To support this, archive_entry objects can now be bound to a + particular archive when they are created. The automatic character set + conversions performed by archive_entry objects when reading and writing + filenames, usernames, and other strings will now use an appropriate + default character set: + + If the archive_entry object is bound to an archive, it will use the + default character set for that archive. + + The platform default character encoding (as returned by + nl_langinfo(CHARSET)) will be used if nothing else is specified. + + Libarchive3 also introduces charset options to many of the archive read- + ers and writers to control the character set that will be used for file- + names written in those archives. When possible, this will be set auto- + matically based on information in the archive itself. Combining this + with the notion of a default character set for the archive should allow + you to configure libarchive to read archives from other platforms and + have the filenames and other information transparently converted to the + character encoding suitable for your application. + + Prototype Changes + These changes break binary compatibility; libarchive3 has a new shared + library version to reflect these changes. The library now uses portable + wide types such as int64_t instead of less-portable types such as off_t, + gid_t, uid_t, and ino_t. + + There are a few cases where these changes will affect your source code: + + o In some cases, libarchive's wider types will introduce the possibil- + ity of truncation: for example, on a system with a 16-bit uid_t, you + risk having uid 65536 be truncated to uid 0, which can cause serious + security problems. + + o Typedef function pointer types will be incompatible. For example, + if you define custom skip callbacks, you may have to use code simi- + lar to the following if you want to support building against + libarchive2 and libarchive3: + + #if ARCHIVE_VERSION_NUMBER < 3000000 + typedef off_t myoff_t; + #else + typedef int64_t myoff_t; + #endif + + myoff_t + my_skip_function(struct archive *a, void *v, myoff_t o) + { + ... implementation ... + } + + Affected functions: + + o archive_entry_gid(), archive_entry_set_gid() + o archive_entry_uid(), archive_entry_set_uid() + o archive_entry_ino(), archive_entry_set_ino() + o archive_read_data_block(), archive_write_data_block() + o archive_read_disk_gname(), archive_read_disk_uname() + o archive_read_disk_set_gname_lookup(), + archive_read_disk_set_group_lookup(), + archive_read_disk_set_uname_lookup(), + archive_read_disk_set_user_lookup() + o archive_skip_callback() + o archive_read_extract_set_skip_file(), + archive_write_disk_set_skip_file(), archive_write_set_skip_file() + o archive_write_disk_set_group_lookup(), + archive_write_disk_set_user_lookup() + + Where these functions or their arguments took or returned gid_t, ino_t, + off_t, or uid_t they now take or return int64_t or equivalent. + + Deprecated Symbols + Symbols deprecated in libarchive3 will be removed in libarchive4. These + symbols, along with their replacements if any, are listed below: + + archive_position_compressed(), archive_position_uncompressed() + archive_filter_bytes() + + archive_compression() + archive_filter_code() + + archive_compression_name() + archive_filter_name() + + archive_read_finish(), archive_write_finish() + archive_read_free(), archive_write_free() + + archive_read_open_file(), archive_write_open_file() + archive_read_open_filename(), archive_write_open_filename() + + archive_read_support_compression_all() + archive_read_support_filter_all() + + archive_read_support_compression_bzip2() + archive_read_support_filter_bzip2() + + archive_read_support_compression_compress() + archive_read_support_filter_compress() + + archive_read_support_compression_gzip() + archive_read_support_filter_gzip() + + archive_read_support_compression_lzip() + archive_read_support_filter_lzip() + + archive_read_support_compression_lzma() + archive_read_support_filter_lzma() + + archive_read_support_compression_none() + archive_read_support_filter_none() + + archive_read_support_compression_program() + archive_read_support_filter_program() + + archive_read_support_compression_program_signature() + archive_read_support_filter_program_signature() + + archive_read_support_compression_rpm() + archive_read_support_filter_rpm() + + archive_read_support_compression_uu() + archive_read_support_filter_uu() + + archive_read_support_compression_xz() + archive_read_support_filter_xz() + + archive_write_set_compression_bzip2() + archive_write_add_filter_bzip2() + + archive_write_set_compression_compress() + archive_write_add_filter_compress() + + archive_write_set_compression_gzip() + archive_write_add_filter_gzip() + + archive_write_set_compression_lzip() + archive_write_add_filter_lzip() + + archive_write_set_compression_lzma() + archive_write_add_filter_lzma() + + archive_write_set_compression_none() + archive_write_add_filter_none() + + archive_write_set_compression_program() + archive_write_add_filter_program() + + archive_write_set_compression_filter() + archive_write_add_filter_filter() + + Removed Symbols + These symbols, listed below along with their replacements if any, were + deprecated in libarchive2, and are not part of libarchive3. + + archive_api_feature() + archive_version_number() + + archive_api_version() + archive_version_number() + + archive_version() + archive_version_string() + + archive_version_stamp() + archive_version_number() + + archive_read_set_filter_options() + archive_read_set_options() or archive_read_set_filter_option() + + archive_read_set_format_options() + archive_read_set_options() or archive_read_set_format_option() + + archive_write_set_filter_options() + archive_write_set_options() or archive_write_set_filter_option() + + archive_write_set_format_options() + archive_write_set_options() or archive_write_set_format_option() + + ARCHIVE_API_FEATURE + ARCHIVE_VERSION_NUMBER + + ARCHIVE_API_VERSION + ARCHIVE_VERSION_NUMBER + + ARCHIVE_VERSION_STAMP + ARCHIVE_VERSION_NUMBER + + ARCHIVE_LIBRARY_VERSION + ARCHIVE_VERSION_STRING + + ARCHIVE_COMPRESSION_NONE + ARCHIVE_FILTER_NONE + + ARCHIVE_COMPRESSION_GZIP + ARCHIVE_FILTER_GZIP + + ARCHIVE_COMPRESSION_BZIP2 + ARCHIVE_FILTER_BZIP2 + + ARCHIVE_COMPRESSION_COMPRESS + ARCHIVE_FILTER_COMPRESS + + ARCHIVE_COMPRESSION_PROGRAM + ARCHIVE_FILTER_PROGRAM + + ARCHIVE_COMPRESSION_LZMA + ARCHIVE_FILTER_LZMA + + ARCHIVE_COMPRESSION_XZ + ARCHIVE_FILTER_XZ + + ARCHIVE_COMPRESSION_UU + ARCHIVE_FILTER_UU + + ARCHIVE_COMPRESSION_RPM + ARCHIVE_FILTER_RPM + + ARCHIVE_COMPRESSION_LZIP + ARCHIVE_FILTER_LZIP + + ARCHIVE_BYTES_PER_RECORD + 512 + + ARCHIVE_DEFAULT_BYTES_PER_BLOCK + 10240 + +SEE ALSO + archive_read(3), archive_read_filter(3), archive_read_format(3), + archive_read_set_options(3), archive_util(3), archive_write(3), + archive_write_filter(3), archive_write_format(3), + archive_write_set_options(3), libarchive(3) + +BSD December 23, 2011 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/libarchive_internals.3.txt b/dependencies/libarchive-3.4.2/doc/text/libarchive_internals.3.txt new file mode 100644 index 0000000..e58faae --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/libarchive_internals.3.txt @@ -0,0 +1,247 @@ +LIBARCHIVE_INTERNALS(3) BSD Library Functions Manual LIBARCHIVE_INTERNALS(3) + +NAME + libarchive_internals -- description of libarchive internal interfaces + +OVERVIEW + The libarchive library provides a flexible interface for reading and + writing streaming archive files such as tar and cpio. Internally, it + follows a modular layered design that should make it easy to add new ar- + chive and compression formats. + +GENERAL ARCHITECTURE + Externally, libarchive exposes most operations through an opaque, object- + style interface. The archive_entry(3) objects store information about a + single filesystem object. The rest of the library provides facilities to + write archive_entry(3) objects to archive files, read them from archive + files, and write them to disk. (There are plans to add a facility to + read archive_entry(3) objects from disk as well.) + + The read and write APIs each have four layers: a public API layer, a for- + mat layer that understands the archive file format, a compression layer, + and an I/O layer. The I/O layer is completely exposed to clients who can + replace it entirely with their own functions. + + In order to provide as much consistency as possible for clients, some + public functions are virtualized. Eventually, it should be possible for + clients to open an archive or disk writer, and then use a single set of + code to select and write entries, regardless of the target. + +READ ARCHITECTURE + From the outside, clients use the archive_read(3) API to manipulate an + archive object to read entries and bodies from an archive stream. Inter- + nally, the archive object is cast to an archive_read object, which holds + all read-specific data. The API has four layers: The lowest layer is the + I/O layer. This layer can be overridden by clients, but most clients use + the packaged I/O callbacks provided, for example, by + archive_read_open_memory(3), and archive_read_open_fd(3). The compres- + sion layer calls the I/O layer to read bytes and decompresses them for + the format layer. The format layer unpacks a stream of uncompressed + bytes and creates archive_entry objects from the incoming data. The API + layer tracks overall state (for example, it prevents clients from reading + data before reading a header) and invokes the format and compression + layer operations through registered function pointers. In particular, + the API layer drives the format-detection process: When opening the ar- + chive, it reads an initial block of data and offers it to each registered + compression handler. The one with the highest bid is initialized with + the first block. Similarly, the format handlers are polled to see which + handler is the best for each archive. (Prior to 2.4.0, the format bid- + ders were invoked for each entry, but this design hindered error recov- + ery.) + + I/O Layer and Client Callbacks + The read API goes to some lengths to be nice to clients. As a result, + there are few restrictions on the behavior of the client callbacks. + + The client read callback is expected to provide a block of data on each + call. A zero-length return does indicate end of file, but otherwise + blocks may be as small as one byte or as large as the entire file. In + particular, blocks may be of different sizes. + + The client skip callback returns the number of bytes actually skipped, + which may be much smaller than the skip requested. The only requirement + is that the skip not be larger. In particular, clients are allowed to + return zero for any skip that they don't want to handle. The skip call- + back must never be invoked with a negative value. + + Keep in mind that not all clients are reading from disk: clients reading + from networks may provide different-sized blocks on every request and + cannot skip at all; advanced clients may use mmap(2) to read the entire + file into memory at once and return the entire file to libarchive as a + single block; other clients may begin asynchronous I/O operations for the + next block on each request. + + Decompresssion Layer + The decompression layer not only handles decompression, it also buffers + data so that the format handlers see a much nicer I/O model. The decom- + pression API is a two stage peek/consume model. A read_ahead request + specifies a minimum read amount; the decompression layer must provide a + pointer to at least that much data. If more data is immediately avail- + able, it should return more: the format layer handles bulk data reads by + asking for a minimum of one byte and then copying as much data as is + available. + + A subsequent call to the consume() function advances the read pointer. + Note that data returned from a read_ahead() call is guaranteed to remain + in place until the next call to read_ahead(). Intervening calls to + consume() should not cause the data to move. + + Skip requests must always be handled exactly. Decompression handlers + that cannot seek forward should not register a skip handler; the API + layer fills in a generic skip handler that reads and discards data. + + A decompression handler has a specific lifecycle: + Registration/Configuration + When the client invokes the public support function, the decom- + pression handler invokes the internal + __archive_read_register_compression() function to provide bid and + initialization functions. This function returns NULL on error or + else a pointer to a struct decompressor_t. This structure con- + tains a void * config slot that can be used for storing any cus- + tomization information. + Bid The bid function is invoked with a pointer and size of a block of + data. The decompressor can access its config data through the + decompressor element of the archive_read object. The bid func- + tion is otherwise stateless. In particular, it must not perform + any I/O operations. + + The value returned by the bid function indicates its suitability + for handling this data stream. A bid of zero will ensure that + this decompressor is never invoked. Return zero if magic number + checks fail. Otherwise, your initial implementation should + return the number of bits actually checked. For example, if you + verify two full bytes and three bits of another byte, bid 19. + Note that the initial block may be very short; be careful to only + inspect the data you are given. (The current decompressors + require two bytes for correct bidding.) + Initialize + The winning bidder will have its init function called. This + function should initialize the remaining slots of the struct + decompressor_t object pointed to by the decompressor element of + the archive_read object. In particular, it should allocate any + working data it needs in the data slot of that structure. The + init function is called with the block of data that was used for + tasting. At this point, the decompressor is responsible for all + I/O requests to the client callbacks. The decompressor is free + to read more data as and when necessary. + Satisfy I/O requests + The format handler will invoke the read_ahead, consume, and skip + functions as needed. + Finish The finish method is called only once when the archive is closed. + It should release anything stored in the data and config slots of + the decompressor object. It should not invoke the client close + callback. + + Format Layer + The read formats have a similar lifecycle to the decompression handlers: + Registration + Allocate your private data and initialize your pointers. + Bid Formats bid by invoking the read_ahead() decompression method but + not calling the consume() method. This allows each bidder to + look ahead in the input stream. Bidders should not look further + ahead than necessary, as long look aheads put pressure on the + decompression layer to buffer lots of data. Most formats only + require a few hundred bytes of look ahead; look aheads of a few + kilobytes are reasonable. (The ISO9660 reader sometimes looks + ahead by 48k, which should be considered an upper limit.) + Read header + The header read is usually the most complex part of any format. + There are a few strategies worth mentioning: For formats such as + tar or cpio, reading and parsing the header is straightforward + since headers alternate with data. For formats that store all + header data at the beginning of the file, the first header read + request may have to read all headers into memory and store that + data, sorted by the location of the file data. Subsequent header + read requests will skip forward to the beginning of the file data + and return the corresponding header. + Read Data + The read data interface supports sparse files; this requires that + each call return a block of data specifying the file offset and + size. This may require you to carefully track the location so + that you can return accurate file offsets for each read. Remem- + ber that the decompressor will return as much data as it has. + Generally, you will want to request one byte, examine the return + value to see how much data is available, and possibly trim that + to the amount you can use. You should invoke consume for each + block just before you return it. + Skip All Data + The skip data call should skip over all file data and trailing + padding. This is called automatically by the API layer just + before each header read. It is also called in response to the + client calling the public data_skip() function. + Cleanup + On cleanup, the format should release all of its allocated mem- + ory. + + API Layer + XXX to do XXX + +WRITE ARCHITECTURE + The write API has a similar set of four layers: an API layer, a format + layer, a compression layer, and an I/O layer. The registration here is + much simpler because only one format and one compression can be regis- + tered at a time. + + I/O Layer and Client Callbacks + XXX To be written XXX + + Compression Layer + XXX To be written XXX + + Format Layer + XXX To be written XXX + + API Layer + XXX To be written XXX + +WRITE_DISK ARCHITECTURE + The write_disk API is intended to look just like the write API to + clients. Since it does not handle multiple formats or compression, it is + not layered internally. + +GENERAL SERVICES + The archive_read, archive_write, and archive_write_disk objects all con- + tain an initial archive object which provides common support for a set of + standard services. (Recall that ANSI/ISO C90 guarantees that you can + cast freely between a pointer to a structure and a pointer to the first + element of that structure.) The archive object has a magic value that + indicates which API this object is associated with, slots for storing + error information, and function pointers for virtualized API functions. + +MISCELLANEOUS NOTES + Connecting existing archiving libraries into libarchive is generally + quite difficult. In particular, many existing libraries strongly assume + that you are reading from a file; they seek forwards and backwards as + necessary to locate various pieces of information. In contrast, + libarchive never seeks backwards in its input, which sometimes requires + very different approaches. + + For example, libarchive's ISO9660 support operates very differently from + most ISO9660 readers. The libarchive support utilizes a work-queue + design that keeps a list of known entries sorted by their location in the + input. Whenever libarchive's ISO9660 implementation is asked for the + next header, checks this list to find the next item on the disk. Direc- + tories are parsed when they are encountered and new items are added to + the list. This design relies heavily on the ISO9660 image being opti- + mized so that directories always occur earlier on the disk than the files + they describe. + + Depending on the specific format, such approaches may not be possible. + The ZIP format specification, for example, allows archivers to store key + information only at the end of the file. In theory, it is possible to + create ZIP archives that cannot be read without seeking. Fortunately, + such archives are very rare, and libarchive can read most ZIP archives, + though it cannot always extract as much information as a dedicated ZIP + program. + +SEE ALSO + archive_entry(3), archive_read(3), archive_write(3), + archive_write_disk(3), libarchive(3) + +HISTORY + The libarchive library first appeared in FreeBSD 5.3. + +AUTHORS + The libarchive library was written by Tim Kientzle . + +BSD January 26, 2011 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/mtree.5.txt b/dependencies/libarchive-3.4.2/doc/text/mtree.5.txt new file mode 100644 index 0000000..f4558d5 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/mtree.5.txt @@ -0,0 +1,184 @@ +MTREE(5) BSD File Formats Manual MTREE(5) + +NAME + mtree -- format of mtree dir hierarchy files + +DESCRIPTION + The mtree format is a textual format that describes a collection of + filesystem objects. Such files are typically used to create or verify + directory hierarchies. + + General Format + An mtree file consists of a series of lines, each providing information + about a single filesystem object. Leading whitespace is always ignored. + + When encoding file or pathnames, any backslash character or character + outside of the 95 printable ASCII characters must be encoded as a back- + slash followed by three octal digits. When reading mtree files, any + appearance of a backslash followed by three octal digits should be con- + verted into the corresponding character. + + Each line is interpreted independently as one of the following types: + + Blank Blank lines are ignored. + + Comment Lines beginning with # are ignored. + + Special Lines beginning with / are special commands that influence + the interpretation of later lines. + + Relative If the first whitespace-delimited word has no / characters, + it is the name of a file in the current directory. Any rela- + tive entry that describes a directory changes the current + directory. + + dot-dot As a special case, a relative entry with the filename .. + changes the current directory to the parent directory. + Options on dot-dot entries are always ignored. + + Full If the first whitespace-delimited word has a / character + after the first character, it is the pathname of a file rela- + tive to the starting directory. There can be multiple full + entries describing the same file. + + Some tools that process mtree files may require that multiple lines + describing the same file occur consecutively. It is not permitted for + the same file to be mentioned using both a relative and a full file spec- + ification. + + Special commands + Two special commands are currently defined: + + /set This command defines default values for one or more keywords. + It is followed on the same line by one or more whitespace- + separated keyword definitions. These definitions apply to + all following files that do not specify a value for that key- + word. + + /unset This command removes any default value set by a previous /set + command. It is followed on the same line by one or more key- + words separated by whitespace. + + Keywords + After the filename, a full or relative entry consists of zero or more + whitespace-separated keyword definitions. Each such definition consists + of a key from the following list immediately followed by an '=' sign and + a value. Software programs reading mtree files should warn about unrec- + ognized keywords. + + Currently supported keywords are as follows: + + cksum The checksum of the file using the default algorithm speci- + fied by the cksum(1) utility. + + device The device number for block or char file types. The value + must be one of the following forms: + + format,major,minor[,subunit] + A device with major, minor and optional subunit fields. + Their meaning is specified by the operating's system + format. See below for valid formats. + + number + Opaque number (as stored on the file system). + + The following values for format are recognized: native, + 386bsd, 4bsd, bsdos, freebsd, hpux, isc, linux, netbsd, osf1, + sco, solaris, sunos, svr3, svr4, and ultrix. + + See mknod(8) for more details. + + contents The full pathname of a file that holds the contents of this + file. + + flags The file flags as a symbolic name. See chflags(1) for infor- + mation on these names. If no flags are to be set the string + ``none'' may be used to override the current default. + + gid The file group as a numeric value. + + gname The file group as a symbolic name. + + ignore Ignore any file hierarchy below this file. + + inode The inode number. + + link The target of the symbolic link when type=link. + + md5 The MD5 message digest of the file. + + md5digest A synonym for md5. + + mode The current file's permissions as a numeric (octal) or sym- + bolic value. + + nlink The number of hard links the file is expected to have. + + nochange Make sure this file or directory exists but otherwise ignore + all attributes. + + optional The file is optional; do not complain about the file if it is + not in the file hierarchy. + + resdevice The ``resident'' device number of the file, e.g. the ID of + the device that contains the file. Its format is the same as + the one for device. + + ripemd160digest + The RIPEMD160 message digest of the file. + + rmd160 A synonym for ripemd160digest. + + rmd160digest + A synonym for ripemd160digest. + + sha1 The FIPS 160-1 (``SHA-1'') message digest of the file. + + sha1digest A synonym for sha1. + + sha256 The FIPS 180-2 (``SHA-256'') message digest of the file. + + sha256digest + A synonym for sha256. + + sha384 The FIPS 180-2 (``SHA-384'') message digest of the file. + + sha384digest + A synonym for sha384. + + sha512 The FIPS 180-2 (``SHA-512'') message digest of the file. + + sha512digest + A synonym for sha512. + + size The size, in bytes, of the file. + + time The last modification time of the file. + + type The type of the file; may be set to any one of the following: + + block block special device + char character special device + dir directory + fifo fifo + file regular file + link symbolic link + socket socket + + uid The file owner as a numeric value. + + uname The file owner as a symbolic name. + +SEE ALSO + cksum(1), find(1), mtree(8) + +HISTORY + The mtree utility appeared in 4.3BSD-Reno. The MD5 digest capability was + added in FreeBSD 2.1, in response to the widespread use of programs which + can spoof cksum(1). The SHA-1 and RIPEMD160 digests were added in + FreeBSD 4.0, as new attacks have demonstrated weaknesses in MD5. The + SHA-256 digest was added in FreeBSD 6.0. Support for file flags was + added in FreeBSD 4.0, and mostly comes from NetBSD. The ``full'' entry + format was added by NetBSD. + +BSD September 4, 2013 BSD diff --git a/dependencies/libarchive-3.4.2/doc/text/tar.5.txt b/dependencies/libarchive-3.4.2/doc/text/tar.5.txt new file mode 100644 index 0000000..6d3c762 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/text/tar.5.txt @@ -0,0 +1,676 @@ +TAR(5) BSD File Formats Manual TAR(5) + +NAME + tar -- format of tape archive files + +DESCRIPTION + The tar archive format collects any number of files, directories, and + other file system objects (symbolic links, device nodes, etc.) into a + single stream of bytes. The format was originally designed to be used + with tape drives that operate with fixed-size blocks, but is widely used + as a general packaging mechanism. + + General Format + A tar archive consists of a series of 512-byte records. Each file system + object requires a header record which stores basic metadata (pathname, + owner, permissions, etc.) and zero or more records containing any file + data. The end of the archive is indicated by two records consisting + entirely of zero bytes. + + For compatibility with tape drives that use fixed block sizes, programs + that read or write tar files always read or write a fixed number of + records with each I/O operation. These ``blocks'' are always a multiple + of the record size. The maximum block size supported by early implemen- + tations was 10240 bytes or 20 records. This is still the default for + most implementations although block sizes of 1MiB (2048 records) or + larger are commonly used with modern high-speed tape drives. (Note: the + terms ``block'' and ``record'' here are not entirely standard; this docu- + ment follows the convention established by John Gilmore in documenting + pdtar.) + + Old-Style Archive Format + The original tar archive format has been extended many times to include + additional information that various implementors found necessary. This + section describes the variant implemented by the tar command included in + Version 7 AT&T UNIX, which seems to be the earliest widely-used version + of the tar program. + + The header record for an old-style tar archive consists of the following: + + struct header_old_tar { + char name[100]; + char mode[8]; + char uid[8]; + char gid[8]; + char size[12]; + char mtime[12]; + char checksum[8]; + char linkflag[1]; + char linkname[100]; + char pad[255]; + }; + All unused bytes in the header record are filled with nulls. + + name Pathname, stored as a null-terminated string. Early tar imple- + mentations only stored regular files (including hardlinks to + those files). One common early convention used a trailing "/" + character to indicate a directory name, allowing directory per- + missions and owner information to be archived and restored. + + mode File mode, stored as an octal number in ASCII. + + uid, gid + User id and group id of owner, as octal numbers in ASCII. + + size Size of file, as octal number in ASCII. For regular files only, + this indicates the amount of data that follows the header. In + particular, this field was ignored by early tar implementations + when extracting hardlinks. Modern writers should always store a + zero length for hardlink entries. + + mtime Modification time of file, as an octal number in ASCII. This + indicates the number of seconds since the start of the epoch, + 00:00:00 UTC January 1, 1970. Note that negative values should + be avoided here, as they are handled inconsistently. + + checksum + Header checksum, stored as an octal number in ASCII. To compute + the checksum, set the checksum field to all spaces, then sum all + bytes in the header using unsigned arithmetic. This field should + be stored as six octal digits followed by a null and a space + character. Note that many early implementations of tar used + signed arithmetic for the checksum field, which can cause inter- + operability problems when transferring archives between systems. + Modern robust readers compute the checksum both ways and accept + the header if either computation matches. + + linkflag, linkname + In order to preserve hardlinks and conserve tape, a file with + multiple links is only written to the archive the first time it + is encountered. The next time it is encountered, the linkflag is + set to an ASCII '1' and the linkname field holds the first name + under which this file appears. (Note that regular files have a + null value in the linkflag field.) + + Early tar implementations varied in how they terminated these fields. + The tar command in Version 7 AT&T UNIX used the following conventions + (this is also documented in early BSD manpages): the pathname must be + null-terminated; the mode, uid, and gid fields must end in a space and a + null byte; the size and mtime fields must end in a space; the checksum is + terminated by a null and a space. Early implementations filled the + numeric fields with leading spaces. This seems to have been common prac- + tice until the IEEE Std 1003.1-1988 (``POSIX.1'') standard was released. + For best portability, modern implementations should fill the numeric + fields with leading zeros. + + Pre-POSIX Archives + An early draft of IEEE Std 1003.1-1988 (``POSIX.1'') served as the basis + for John Gilmore's pdtar program and many system implementations from the + late 1980s and early 1990s. These archives generally follow the POSIX + ustar format described below with the following variations: + o The magic value consists of the five characters ``ustar'' fol- + lowed by a space. The version field contains a space character + followed by a null. + o The numeric fields are generally filled with leading spaces (not + leading zeros as recommended in the final standard). + o The prefix field is often not used, limiting pathnames to the 100 + characters of old-style archives. + + POSIX ustar Archives + IEEE Std 1003.1-1988 (``POSIX.1'') defined a standard tar file format to + be read and written by compliant implementations of tar(1). This format + is often called the ``ustar'' format, after the magic value used in the + header. (The name is an acronym for ``Unix Standard TAR''.) It extends + the historic format with new fields: + + struct header_posix_ustar { + char name[100]; + char mode[8]; + char uid[8]; + char gid[8]; + char size[12]; + char mtime[12]; + char checksum[8]; + char typeflag[1]; + char linkname[100]; + char magic[6]; + char version[2]; + char uname[32]; + char gname[32]; + char devmajor[8]; + char devminor[8]; + char prefix[155]; + char pad[12]; + }; + + typeflag + Type of entry. POSIX extended the earlier linkflag field with + several new type values: + ``0'' Regular file. NUL should be treated as a synonym, for + compatibility purposes. + ``1'' Hard link. + ``2'' Symbolic link. + ``3'' Character device node. + ``4'' Block device node. + ``5'' Directory. + ``6'' FIFO node. + ``7'' Reserved. + Other A POSIX-compliant implementation must treat any unrecog- + nized typeflag value as a regular file. In particular, + writers should ensure that all entries have a valid file- + name so that they can be restored by readers that do not + support the corresponding extension. Uppercase letters + "A" through "Z" are reserved for custom extensions. Note + that sockets and whiteout entries are not archivable. + It is worth noting that the size field, in particular, has dif- + ferent meanings depending on the type. For regular files, of + course, it indicates the amount of data following the header. + For directories, it may be used to indicate the total size of all + files in the directory, for use by operating systems that pre- + allocate directory space. For all other types, it should be set + to zero by writers and ignored by readers. + + magic Contains the magic value ``ustar'' followed by a NUL byte to + indicate that this is a POSIX standard archive. Full compliance + requires the uname and gname fields be properly set. + + version + Version. This should be ``00'' (two copies of the ASCII digit + zero) for POSIX standard archives. + + uname, gname + User and group names, as null-terminated ASCII strings. These + should be used in preference to the uid/gid values when they are + set and the corresponding names exist on the system. + + devmajor, devminor + Major and minor numbers for character device or block device + entry. + + name, prefix + If the pathname is too long to fit in the 100 bytes provided by + the standard format, it can be split at any / character with the + first portion going into the prefix field. If the prefix field + is not empty, the reader will prepend the prefix value and a / + character to the regular name field to obtain the full pathname. + The standard does not require a trailing / character on directory + names, though most implementations still include this for compat- + ibility reasons. + + Note that all unused bytes must be set to NUL. + + Field termination is specified slightly differently by POSIX than by pre- + vious implementations. The magic, uname, and gname fields must have a + trailing NUL. The pathname, linkname, and prefix fields must have a + trailing NUL unless they fill the entire field. (In particular, it is + possible to store a 256-character pathname if it happens to have a / as + the 156th character.) POSIX requires numeric fields to be zero-padded in + the front, and requires them to be terminated with either space or NUL + characters. + + Currently, most tar implementations comply with the ustar format, occa- + sionally extending it by adding new fields to the blank area at the end + of the header record. + + Numeric Extensions + There have been several attempts to extend the range of sizes or times + supported by modifying how numbers are stored in the header. + + One obvious extension to increase the size of files is to eliminate the + terminating characters from the various numeric fields. For example, the + standard only allows the size field to contain 11 octal digits, reserving + the twelfth byte for a trailing NUL character. Allowing 12 octal digits + allows file sizes up to 64 GB. + + Another extension, utilized by GNU tar, star, and other newer tar imple- + mentations, permits binary numbers in the standard numeric fields. This + is flagged by setting the high bit of the first byte. The remainder of + the field is treated as a signed twos-complement value. This permits + 95-bit values for the length and time fields and 63-bit values for the + uid, gid, and device numbers. In particular, this provides a consistent + way to handle negative time values. GNU tar supports this extension for + the length, mtime, ctime, and atime fields. Joerg Schilling's star pro- + gram and the libarchive library support this extension for all numeric + fields. Note that this extension is largely obsoleted by the extended + attribute record provided by the pax interchange format. + + Another early GNU extension allowed base-64 values rather than octal. + This extension was short-lived and is no longer supported by any imple- + mentation. + + Pax Interchange Format + There are many attributes that cannot be portably stored in a POSIX ustar + archive. IEEE Std 1003.1-2001 (``POSIX.1'') defined a ``pax interchange + format'' that uses two new types of entries to hold text-formatted meta- + data that applies to following entries. Note that a pax interchange for- + mat archive is a ustar archive in every respect. The new data is stored + in ustar-compatible archive entries that use the ``x'' or ``g'' typeflag. + In particular, older implementations that do not fully support these + extensions will extract the metadata into regular files, where the meta- + data can be examined as necessary. + + An entry in a pax interchange format archive consists of one or two stan- + dard ustar entries, each with its own header and data. The first + optional entry stores the extended attributes for the following entry. + This optional first entry has an "x" typeflag and a size field that indi- + cates the total size of the extended attributes. The extended attributes + themselves are stored as a series of text-format lines encoded in the + portable UTF-8 encoding. Each line consists of a decimal number, a + space, a key string, an equals sign, a value string, and a new line. The + decimal number indicates the length of the entire line, including the + initial length field and the trailing newline. An example of such a + field is: + 25 ctime=1084839148.1212\n + Keys in all lowercase are standard keys. Vendors can add their own keys + by prefixing them with an all uppercase vendor name and a period. Note + that, unlike the historic header, numeric values are stored using deci- + mal, not octal. A description of some common keys follows: + + atime, ctime, mtime + File access, inode change, and modification times. These fields + can be negative or include a decimal point and a fractional + value. + + hdrcharset + The character set used by the pax extension values. By default, + all textual values in the pax extended attributes are assumed to + be in UTF-8, including pathnames, user names, and group names. + In some cases, it is not possible to translate local conventions + into UTF-8. If this key is present and the value is the six- + character ASCII string ``BINARY'', then all textual values are + assumed to be in a platform-dependent multi-byte encoding. Note + that there are only two valid values for this key: ``BINARY'' or + ``ISO-IR 10646 2000 UTF-8''. No other values are permitted by + the standard, and the latter value should generally not be used + as it is the default when this key is not specified. In particu- + lar, this flag should not be used as a general mechanism to allow + filenames to be stored in arbitrary encodings. + + uname, uid, gname, gid + User name, group name, and numeric UID and GID values. The user + name and group name stored here are encoded in UTF8 and can thus + include non-ASCII characters. The UID and GID fields can be of + arbitrary length. + + linkpath + The full path of the linked-to file. Note that this is encoded + in UTF8 and can thus include non-ASCII characters. + + path The full pathname of the entry. Note that this is encoded in + UTF8 and can thus include non-ASCII characters. + + realtime.*, security.* + These keys are reserved and may be used for future standardiza- + tion. + + size The size of the file. Note that there is no length limit on this + field, allowing conforming archives to store files much larger + than the historic 8GB limit. + + SCHILY.* + Vendor-specific attributes used by Joerg Schilling's star imple- + mentation. + + SCHILY.acl.access, SCHILY.acl.default, SCHILY.acl.ace + Stores the access, default and NFSv4 ACLs as textual strings in a + format that is an extension of the format specified by POSIX.1e + draft 17. In particular, each user or group access specification + can include an additional colon-separated field with the numeric + UID or GID. This allows ACLs to be restored on systems that may + not have complete user or group information available (such as + when NIS/YP or LDAP services are temporarily unavailable). + + SCHILY.devminor, SCHILY.devmajor + The full minor and major numbers for device nodes. + + SCHILY.fflags + The file flags. + + SCHILY.realsize + The full size of the file on disk. XXX explain? XXX + + SCHILY.dev, SCHILY.ino, SCHILY.nlinks + The device number, inode number, and link count for the entry. + In particular, note that a pax interchange format archive using + Joerg Schilling's SCHILY.* extensions can store all of the data + from struct stat. + + LIBARCHIVE.* + Vendor-specific attributes used by the libarchive library and + programs that use it. + + LIBARCHIVE.creationtime + The time when the file was created. (This should not be confused + with the POSIX ``ctime'' attribute, which refers to the time when + the file metadata was last changed.) + + LIBARCHIVE.xattr.namespace.key + Libarchive stores POSIX.1e-style extended attributes using keys + of this form. The key value is URL-encoded: All non-ASCII char- + acters and the two special characters ``='' and ``%'' are encoded + as ``%'' followed by two uppercase hexadecimal digits. The value + of this key is the extended attribute value encoded in base 64. + XXX Detail the base-64 format here XXX + + VENDOR.* + XXX document other vendor-specific extensions XXX + + Any values stored in an extended attribute override the corresponding + values in the regular tar header. Note that compliant readers should + ignore the regular fields when they are overridden. This is important, + as existing archivers are known to store non-compliant values in the + standard header fields in this situation. There are no limits on length + for any of these fields. In particular, numeric fields can be arbitrar- + ily large. All text fields are encoded in UTF8. Compliant writers + should store only portable 7-bit ASCII characters in the standard ustar + header and use extended attributes whenever a text value contains non- + ASCII characters. + + In addition to the x entry described above, the pax interchange format + also supports a g entry. The g entry is identical in format, but speci- + fies attributes that serve as defaults for all subsequent archive + entries. The g entry is not widely used. + + Besides the new x and g entries, the pax interchange format has a few + other minor variations from the earlier ustar format. The most troubling + one is that hardlinks are permitted to have data following them. This + allows readers to restore any hardlink to a file without having to rewind + the archive to find an earlier entry. However, it creates complications + for robust readers, as it is no longer clear whether or not they should + ignore the size field for hardlink entries. + + GNU Tar Archives + The GNU tar program started with a pre-POSIX format similar to that + described earlier and has extended it using several different mechanisms: + It added new fields to the empty space in the header (some of which was + later used by POSIX for conflicting purposes); it allowed the header to + be continued over multiple records; and it defined new entries that mod- + ify following entries (similar in principle to the x entry described + above, but each GNU special entry is single-purpose, unlike the general- + purpose x entry). As a result, GNU tar archives are not POSIX compati- + ble, although more lenient POSIX-compliant readers can successfully + extract most GNU tar archives. + + struct header_gnu_tar { + char name[100]; + char mode[8]; + char uid[8]; + char gid[8]; + char size[12]; + char mtime[12]; + char checksum[8]; + char typeflag[1]; + char linkname[100]; + char magic[6]; + char version[2]; + char uname[32]; + char gname[32]; + char devmajor[8]; + char devminor[8]; + char atime[12]; + char ctime[12]; + char offset[12]; + char longnames[4]; + char unused[1]; + struct { + char offset[12]; + char numbytes[12]; + } sparse[4]; + char isextended[1]; + char realsize[12]; + char pad[17]; + }; + + typeflag + GNU tar uses the following special entry types, in addition to + those defined by POSIX: + + 7 GNU tar treats type "7" records identically to type "0" + records, except on one obscure RTOS where they are used + to indicate the pre-allocation of a contiguous file on + disk. + + D This indicates a directory entry. Unlike the POSIX-stan- + dard "5" typeflag, the header is followed by data records + listing the names of files in this directory. Each name + is preceded by an ASCII "Y" if the file is stored in this + archive or "N" if the file is not stored in this archive. + Each name is terminated with a null, and an extra null + marks the end of the name list. The purpose of this + entry is to support incremental backups; a program + restoring from such an archive may wish to delete files + on disk that did not exist in the directory when the ar- + chive was made. + + Note that the "D" typeflag specifically violates POSIX, + which requires that unrecognized typeflags be restored as + normal files. In this case, restoring the "D" entry as a + file could interfere with subsequent creation of the + like-named directory. + + K The data for this entry is a long linkname for the fol- + lowing regular entry. + + L The data for this entry is a long pathname for the fol- + lowing regular entry. + + M This is a continuation of the last file on the previous + volume. GNU multi-volume archives guarantee that each + volume begins with a valid entry header. To ensure this, + a file may be split, with part stored at the end of one + volume, and part stored at the beginning of the next vol- + ume. The "M" typeflag indicates that this entry contin- + ues an existing file. Such entries can only occur as the + first or second entry in an archive (the latter only if + the first entry is a volume label). The size field spec- + ifies the size of this entry. The offset field at bytes + 369-380 specifies the offset where this file fragment + begins. The realsize field specifies the total size of + the file (which must equal size plus offset). When + extracting, GNU tar checks that the header file name is + the one it is expecting, that the header offset is in the + correct sequence, and that the sum of offset and size is + equal to realsize. + + N Type "N" records are no longer generated by GNU tar. + They contained a list of files to be renamed or symlinked + after extraction; this was originally used to support + long names. The contents of this record are a text + description of the operations to be done, in the form + ``Rename %s to %s\n'' or ``Symlink %s to %s\n''; in + either case, both filenames are escaped using K&R C syn- + tax. Due to security concerns, "N" records are now gen- + erally ignored when reading archives. + + S This is a ``sparse'' regular file. Sparse files are + stored as a series of fragments. The header contains a + list of fragment offset/length pairs. If more than four + such entries are required, the header is extended as nec- + essary with ``extra'' header extensions (an older format + that is no longer used), or ``sparse'' extensions. + + V The name field should be interpreted as a tape/volume + header name. This entry should generally be ignored on + extraction. + + magic The magic field holds the five characters ``ustar'' followed by a + space. Note that POSIX ustar archives have a trailing null. + + version + The version field holds a space character followed by a null. + Note that POSIX ustar archives use two copies of the ASCII digit + ``0''. + + atime, ctime + The time the file was last accessed and the time of last change + of file information, stored in octal as with mtime. + + longnames + This field is apparently no longer used. + + Sparse offset / numbytes + Each such structure specifies a single fragment of a sparse file. + The two fields store values as octal numbers. The fragments are + each padded to a multiple of 512 bytes in the archive. On + extraction, the list of fragments is collected from the header + (including any extension headers), and the data is then read and + written to the file at appropriate offsets. + + isextended + If this is set to non-zero, the header will be followed by addi- + tional ``sparse header'' records. Each such record contains + information about as many as 21 additional sparse blocks as shown + here: + + struct gnu_sparse_header { + struct { + char offset[12]; + char numbytes[12]; + } sparse[21]; + char isextended[1]; + char padding[7]; + }; + + realsize + A binary representation of the file's complete size, with a much + larger range than the POSIX file size. In particular, with M + type files, the current entry is only a portion of the file. In + that case, the POSIX size field will indicate the size of this + entry; the realsize field will indicate the total size of the + file. + + GNU tar pax archives + GNU tar 1.14 (XXX check this XXX) and later will write pax interchange + format archives when you specify the --posix flag. This format follows + the pax interchange format closely, using some SCHILY tags and introduc- + ing new keywords to store sparse file information. There have been three + iterations of the sparse file support, referred to as ``0.0'', ``0.1'', + and ``1.0''. + + GNU.sparse.numblocks, GNU.sparse.offset, GNU.sparse.numbytes, + GNU.sparse.size + The ``0.0'' format used an initial GNU.sparse.numblocks attribute + to indicate the number of blocks in the file, a pair of + GNU.sparse.offset and GNU.sparse.numbytes to indicate the offset + and size of each block, and a single GNU.sparse.size to indicate + the full size of the file. This is not the same as the size in + the tar header because the latter value does not include the size + of any holes. This format required that the order of attributes + be preserved and relied on readers accepting multiple appearances + of the same attribute names, which is not officially permitted by + the standards. + + GNU.sparse.map + The ``0.1'' format used a single attribute that stored a comma- + separated list of decimal numbers. Each pair of numbers indi- + cated the offset and size, respectively, of a block of data. + This does not work well if the archive is extracted by an + archiver that does not recognize this extension, since many pax + implementations simply discard unrecognized attributes. + + GNU.sparse.major, GNU.sparse.minor, GNU.sparse.name, GNU.sparse.realsize + The ``1.0'' format stores the sparse block map in one or more + 512-byte blocks prepended to the file data in the entry body. + The pax attributes indicate the existence of this map (via the + GNU.sparse.major and GNU.sparse.minor fields) and the full size + of the file. The GNU.sparse.name holds the true name of the + file. To avoid confusion, the name stored in the regular tar + header is a modified name so that extraction errors will be + apparent to users. + + Solaris Tar + XXX More Details Needed XXX + + Solaris tar (beginning with SunOS XXX 5.7 ?? XXX) supports an + ``extended'' format that is fundamentally similar to pax interchange for- + mat, with the following differences: + o Extended attributes are stored in an entry whose type is X, not + x, as used by pax interchange format. The detailed format of + this entry appears to be the same as detailed above for the x + entry. + o An additional A header is used to store an ACL for the following + regular entry. The body of this entry contains a seven-digit + octal number followed by a zero byte, followed by the textual ACL + description. The octal value is the number of ACL entries plus a + constant that indicates the ACL type: 01000000 for POSIX.1e ACLs + and 03000000 for NFSv4 ACLs. + + AIX Tar + XXX More details needed XXX + + AIX Tar uses a ustar-formatted header with the type A for storing coded + ACL information. Unlike the Solaris format, AIX tar writes this header + after the regular file body to which it applies. The pathname in this + header is either NFS4 or AIXC to indicate the type of ACL stored. The + actual ACL is stored in platform-specific binary format. + + Mac OS X Tar + The tar distributed with Apple's Mac OS X stores most regular files as + two separate files in the tar archive. The two files have the same name + except that the first one has ``._'' prepended to the last path element. + This special file stores an AppleDouble-encoded binary blob with addi- + tional metadata about the second file, including ACL, extended + attributes, and resources. To recreate the original file on disk, each + separate file can be extracted and the Mac OS X copyfile() function can + be used to unpack the separate metadata file and apply it to th regular + file. Conversely, the same function provides a ``pack'' option to encode + the extended metadata from a file into a separate file whose contents can + then be put into a tar archive. + + Note that the Apple extended attributes interact badly with long file- + names. Since each file is stored with the full name, a separate set of + extensions needs to be included in the archive for each one, doubling the + overhead required for files with long names. + + Summary of tar type codes + The following list is a condensed summary of the type codes used in tar + header records generated by different tar implementations. More details + about specific implementations can be found above: + NUL Early tar programs stored a zero byte for regular files. + 0 POSIX standard type code for a regular file. + 1 POSIX standard type code for a hard link description. + 2 POSIX standard type code for a symbolic link description. + 3 POSIX standard type code for a character device node. + 4 POSIX standard type code for a block device node. + 5 POSIX standard type code for a directory. + 6 POSIX standard type code for a FIFO. + 7 POSIX reserved. + 7 GNU tar used for pre-allocated files on some systems. + A Solaris tar ACL description stored prior to a regular file header. + A AIX tar ACL description stored after the file body. + D GNU tar directory dump. + K GNU tar long linkname for the following header. + L GNU tar long pathname for the following header. + M GNU tar multivolume marker, indicating the file is a continuation of + a file from the previous volume. + N GNU tar long filename support. Deprecated. + S GNU tar sparse regular file. + V GNU tar tape/volume header name. + X Solaris tar general-purpose extension header. + g POSIX pax interchange format global extensions. + x POSIX pax interchange format per-file extensions. + +SEE ALSO + ar(1), pax(1), tar(1) + +STANDARDS + The tar utility is no longer a part of POSIX or the Single Unix Standard. + It last appeared in Version 2 of the Single UNIX Specification + (``SUSv2''). It has been supplanted in subsequent standards by pax(1). + The ustar format is currently part of the specification for the pax(1) + utility. The pax interchange file format is new with IEEE Std + 1003.1-2001 (``POSIX.1''). + +HISTORY + A tar command appeared in Seventh Edition Unix, which was released in + January, 1979. It replaced the tp program from Fourth Edition Unix which + in turn replaced the tap program from First Edition Unix. John Gilmore's + pdtar public-domain implementation (circa 1987) was highly influential + and formed the basis of GNU tar (circa 1988). Joerg Shilling's star + archiver is another open-source (CDDL) archiver (originally developed + circa 1985) which features complete support for pax interchange format. + + This documentation was written as part of the libarchive and bsdtar + project by Tim Kientzle . + +BSD December 27, 2016 BSD diff --git a/dependencies/libarchive-3.4.2/doc/update.sh b/dependencies/libarchive-3.4.2/doc/update.sh new file mode 100755 index 0000000..1038da1 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/update.sh @@ -0,0 +1,119 @@ +#!/bin/sh + +set -e + +# +# Simple script to repopulate the 'doc' tree from +# the mdoc man pages stored in each project. +# + +# Collect list of man pages, relative to my subdirs +test -d man || mkdir man +cd man +MANPAGES=`for d in libarchive tar cpio;do ls ../../$d/*.[135];done | grep -v '\.so\.'` +cd .. + +# Build Makefile in 'man' directory +cd man +chmod +w . +rm -f *.[135] Makefile +echo > Makefile +echo "default: all" >>Makefile +echo >>Makefile +all="all:" +for f in $MANPAGES; do + outname="`basename $f`" + echo >> Makefile + echo $outname: ../mdoc2man.awk $f >> Makefile + echo " awk -f ../mdoc2man.awk < $f > $outname" >> Makefile + all="$all $outname" +done +echo $all >>Makefile +cd .. + +# Rebuild Makefile in 'text' directory +test -d text || mkdir text +cd text +chmod +w . +rm -f *.txt Makefile +echo > Makefile +echo "default: all" >>Makefile +echo >>Makefile +all="all:" +for f in $MANPAGES; do + outname="`basename $f`.txt" + echo >> Makefile + echo $outname: $f >> Makefile + echo " nroff -mdoc $f | col -b > $outname" >> Makefile + all="$all $outname" +done +echo $all >>Makefile +cd .. + +# Rebuild Makefile in 'pdf' directory +test -d pdf || mkdir pdf +cd pdf +chmod +w . +rm -f *.pdf Makefile +echo > Makefile +echo "default: all" >>Makefile +echo >>Makefile +all="all:" +for f in $MANPAGES; do + outname="`basename $f`.pdf" + echo >> Makefile + echo $outname: $f >> Makefile + echo " groff -mdoc -T ps $f | ps2pdf - - > $outname" >> Makefile + all="$all $outname" +done +echo $all >>Makefile +cd .. + +# Build Makefile in 'html' directory +test -d html || mkdir html +cd html +chmod +w . +rm -f *.html Makefile +echo > Makefile +echo "default: all" >>Makefile +echo >>Makefile +all="all:" +for f in $MANPAGES; do + outname="`basename $f`.html" + echo >> Makefile + echo $outname: $f >> Makefile + echo " groff -mdoc -T html $f > $outname" >> Makefile + all="$all $outname" +done +echo $all >>Makefile +cd .. + +# Build Makefile in 'wiki' directory +test -d wiki || mkdir wiki +cd wiki +chmod +w . +rm -f *.wiki Makefile +echo > Makefile +echo "default: all" >>Makefile +echo >>Makefile +all="all:" +for f in $MANPAGES; do + outname="`basename $f | awk '{ac=split($0,a,"[_.-]");o="ManPage";for(w=0;w<=ac;++w){o=o toupper(substr(a[w],1,1)) substr(a[w],2)};print o}'`.wiki" + echo >> Makefile + echo $outname: ../mdoc2wiki.awk $f >> Makefile + echo " awk -f ../mdoc2wiki.awk < $f > $outname" >> Makefile + all="$all $outname" +done +echo $all >>Makefile +cd .. + +# Convert all of the manpages to -man format +(cd man && make) +# Format all of the manpages to text +(cd text && make) +# Format all of the manpages to PDF +(cd pdf && make) +# Format all of the manpages to HTML +(cd html && make) +# Format all of the manpages to wiki syntax +(cd wiki && make) diff --git a/dependencies/libarchive-3.4.2/doc/wiki/.ignore_me b/dependencies/libarchive-3.4.2/doc/wiki/.ignore_me new file mode 100644 index 0000000..d285484 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/.ignore_me @@ -0,0 +1,2 @@ +*** PLEASE DO NOT DELETE THIS FILE! *** +This file is used to track an otherwise empty directory in git. diff --git a/dependencies/libarchive-3.4.2/doc/wiki/Makefile b/dependencies/libarchive-3.4.2/doc/wiki/Makefile new file mode 100644 index 0000000..0b8cb5d --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/Makefile @@ -0,0 +1,133 @@ + +default: all + + +ManPageArchiveEntry3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_entry.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_entry.3 > ManPageArchiveEntry3.wiki + +ManPageArchiveEntryAcl3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_entry_acl.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_entry_acl.3 > ManPageArchiveEntryAcl3.wiki + +ManPageArchiveEntryLinkify3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_entry_linkify.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_entry_linkify.3 > ManPageArchiveEntryLinkify3.wiki + +ManPageArchiveEntryMisc3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_entry_misc.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_entry_misc.3 > ManPageArchiveEntryMisc3.wiki + +ManPageArchiveEntryPaths3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_entry_paths.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_entry_paths.3 > ManPageArchiveEntryPaths3.wiki + +ManPageArchiveEntryPerms3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_entry_perms.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_entry_perms.3 > ManPageArchiveEntryPerms3.wiki + +ManPageArchiveEntryStat3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_entry_stat.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_entry_stat.3 > ManPageArchiveEntryStat3.wiki + +ManPageArchiveEntryTime3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_entry_time.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_entry_time.3 > ManPageArchiveEntryTime3.wiki + +ManPageArchiveRead3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_read.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_read.3 > ManPageArchiveRead3.wiki + +ManPageArchiveReadAddPassphrase3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_read_add_passphrase.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_read_add_passphrase.3 > ManPageArchiveReadAddPassphrase3.wiki + +ManPageArchiveReadData3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_read_data.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_read_data.3 > ManPageArchiveReadData3.wiki + +ManPageArchiveReadDisk3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_read_disk.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_read_disk.3 > ManPageArchiveReadDisk3.wiki + +ManPageArchiveReadExtract3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_read_extract.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_read_extract.3 > ManPageArchiveReadExtract3.wiki + +ManPageArchiveReadFilter3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_read_filter.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_read_filter.3 > ManPageArchiveReadFilter3.wiki + +ManPageArchiveReadFormat3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_read_format.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_read_format.3 > ManPageArchiveReadFormat3.wiki + +ManPageArchiveReadFree3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_read_free.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_read_free.3 > ManPageArchiveReadFree3.wiki + +ManPageArchiveReadHeader3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_read_header.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_read_header.3 > ManPageArchiveReadHeader3.wiki + +ManPageArchiveReadNew3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_read_new.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_read_new.3 > ManPageArchiveReadNew3.wiki + +ManPageArchiveReadOpen3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_read_open.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_read_open.3 > ManPageArchiveReadOpen3.wiki + +ManPageArchiveReadSetOptions3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_read_set_options.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_read_set_options.3 > ManPageArchiveReadSetOptions3.wiki + +ManPageArchiveUtil3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_util.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_util.3 > ManPageArchiveUtil3.wiki + +ManPageArchiveWrite3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_write.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_write.3 > ManPageArchiveWrite3.wiki + +ManPageArchiveWriteBlocksize3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_write_blocksize.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_write_blocksize.3 > ManPageArchiveWriteBlocksize3.wiki + +ManPageArchiveWriteData3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_write_data.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_write_data.3 > ManPageArchiveWriteData3.wiki + +ManPageArchiveWriteDisk3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_write_disk.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_write_disk.3 > ManPageArchiveWriteDisk3.wiki + +ManPageArchiveWriteFilter3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_write_filter.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_write_filter.3 > ManPageArchiveWriteFilter3.wiki + +ManPageArchiveWriteFinishEntry3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_write_finish_entry.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_write_finish_entry.3 > ManPageArchiveWriteFinishEntry3.wiki + +ManPageArchiveWriteFormat3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_write_format.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_write_format.3 > ManPageArchiveWriteFormat3.wiki + +ManPageArchiveWriteFree3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_write_free.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_write_free.3 > ManPageArchiveWriteFree3.wiki + +ManPageArchiveWriteHeader3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_write_header.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_write_header.3 > ManPageArchiveWriteHeader3.wiki + +ManPageArchiveWriteNew3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_write_new.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_write_new.3 > ManPageArchiveWriteNew3.wiki + +ManPageArchiveWriteOpen3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_write_open.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_write_open.3 > ManPageArchiveWriteOpen3.wiki + +ManPageArchiveWriteSetOptions3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_write_set_options.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_write_set_options.3 > ManPageArchiveWriteSetOptions3.wiki + +ManPageArchiveWriteSetPassphrase3.wiki: ../mdoc2wiki.awk ../../libarchive/archive_write_set_passphrase.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/archive_write_set_passphrase.3 > ManPageArchiveWriteSetPassphrase3.wiki + +ManPageCpio5.wiki: ../mdoc2wiki.awk ../../libarchive/cpio.5 + awk -f ../mdoc2wiki.awk < ../../libarchive/cpio.5 > ManPageCpio5.wiki + +ManPageLibarchiveFormats5.wiki: ../mdoc2wiki.awk ../../libarchive/libarchive-formats.5 + awk -f ../mdoc2wiki.awk < ../../libarchive/libarchive-formats.5 > ManPageLibarchiveFormats5.wiki + +ManPageLibarchive3.wiki: ../mdoc2wiki.awk ../../libarchive/libarchive.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/libarchive.3 > ManPageLibarchive3.wiki + +ManPageLibarchiveChanges3.wiki: ../mdoc2wiki.awk ../../libarchive/libarchive_changes.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/libarchive_changes.3 > ManPageLibarchiveChanges3.wiki + +ManPageLibarchiveInternals3.wiki: ../mdoc2wiki.awk ../../libarchive/libarchive_internals.3 + awk -f ../mdoc2wiki.awk < ../../libarchive/libarchive_internals.3 > ManPageLibarchiveInternals3.wiki + +ManPageMtree5.wiki: ../mdoc2wiki.awk ../../libarchive/mtree.5 + awk -f ../mdoc2wiki.awk < ../../libarchive/mtree.5 > ManPageMtree5.wiki + +ManPageTar5.wiki: ../mdoc2wiki.awk ../../libarchive/tar.5 + awk -f ../mdoc2wiki.awk < ../../libarchive/tar.5 > ManPageTar5.wiki + +ManPageBsdtar1.wiki: ../mdoc2wiki.awk ../../tar/bsdtar.1 + awk -f ../mdoc2wiki.awk < ../../tar/bsdtar.1 > ManPageBsdtar1.wiki + +ManPageBsdcpio1.wiki: ../mdoc2wiki.awk ../../cpio/bsdcpio.1 + awk -f ../mdoc2wiki.awk < ../../cpio/bsdcpio.1 > ManPageBsdcpio1.wiki +all: ManPageArchiveEntry3.wiki ManPageArchiveEntryAcl3.wiki ManPageArchiveEntryLinkify3.wiki ManPageArchiveEntryMisc3.wiki ManPageArchiveEntryPaths3.wiki ManPageArchiveEntryPerms3.wiki ManPageArchiveEntryStat3.wiki ManPageArchiveEntryTime3.wiki ManPageArchiveRead3.wiki ManPageArchiveReadAddPassphrase3.wiki ManPageArchiveReadData3.wiki ManPageArchiveReadDisk3.wiki ManPageArchiveReadExtract3.wiki ManPageArchiveReadFilter3.wiki ManPageArchiveReadFormat3.wiki ManPageArchiveReadFree3.wiki ManPageArchiveReadHeader3.wiki ManPageArchiveReadNew3.wiki ManPageArchiveReadOpen3.wiki ManPageArchiveReadSetOptions3.wiki ManPageArchiveUtil3.wiki ManPageArchiveWrite3.wiki ManPageArchiveWriteBlocksize3.wiki ManPageArchiveWriteData3.wiki ManPageArchiveWriteDisk3.wiki ManPageArchiveWriteFilter3.wiki ManPageArchiveWriteFinishEntry3.wiki ManPageArchiveWriteFormat3.wiki ManPageArchiveWriteFree3.wiki ManPageArchiveWriteHeader3.wiki ManPageArchiveWriteNew3.wiki ManPageArchiveWriteOpen3.wiki ManPageArchiveWriteSetOptions3.wiki ManPageArchiveWriteSetPassphrase3.wiki ManPageCpio5.wiki ManPageLibarchiveFormats5.wiki ManPageLibarchive3.wiki ManPageLibarchiveChanges3.wiki ManPageLibarchiveInternals3.wiki ManPageMtree5.wiki ManPageTar5.wiki ManPageBsdtar1.wiki ManPageBsdcpio1.wiki diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveEntry3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveEntry3.wiki new file mode 100644 index 0000000..db4177c --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveEntry3.wiki @@ -0,0 +1,123 @@ +ARCHIVE_ENTRY(3) manual page +== NAME == +'''archive_entry_clear''', +'''archive_entry_clone''', +'''archive_entry_free''', +'''archive_entry_new''' +- functions for managing archive entry descriptions +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''struct archive_entry *'' +
    +'''archive_entry_clear'''(''struct archive_entry *''); +
    +''struct archive_entry *'' +
    +'''archive_entry_clone'''(''struct archive_entry *''); +
    +''void'' +
    +'''archive_entry_free'''(''struct archive_entry *''); +
    +''struct archive_entry *'' +
    +'''archive_entry_new'''(''void''); +== DESCRIPTION == +These functions create and manipulate data objects that +represent entries within an archive. +You can think of a +'''struct archive_entry''' +as a heavy-duty version of +'''struct stat :''' +it includes everything from +'''struct stat''' +plus associated pathname, textual group and user names, etc. +These objects are used by +[[ManPageibarchive3]] +to represent the metadata associated with a particular +entry in an archive. +=== Create and Destroy=== +There are functions to allocate, destroy, clear, and copy +''archive_entry'' +objects: +
    +
    '''archive_entry_clear'''()
    +Erases the object, resetting all internal fields to the +same state as a newly-created object. +This is provided to allow you to quickly recycle objects +without thrashing the heap. +
    '''archive_entry_clone'''()
    +A deep copy operation; all text fields are duplicated. +
    '''archive_entry_free'''()
    +Releases the +'''struct archive_entry''' +object. +
    '''archive_entry_new'''()
    +Allocate and return a blank +'''struct archive_entry''' +object. +
    +=== Function groups=== +Due to high number of functions, the accessor functions can be found in +man pages grouped by the purpose. +
    +
    [[ManPagerchiventrycl3]]
    +Access Control List manipulation +
    [[ManPagerchiventryaths3]]
    +Path name manipulation +
    [[ManPagerchiventryerms3]]
    +User, group and mode manipulation +
    [[ManPagerchiventrytat3]]
    +Functions not in the other groups and copying to/from +''struct'' stat. +
    [[ManPagerchiventryime3]]
    +Time field manipulation +
    + +Most of the functions set or read entries in an object. +Such functions have one of the following forms: +
    +
    '''archive_entry_set_XXXX'''()
    +Stores the provided data in the object. +In particular, for strings, the pointer is stored, +not the referenced string. +
    '''archive_entry_copy_XXXX'''()
    +As above, except that the referenced data is copied +into the object. +
    '''archive_entry_XXXX'''()
    +Returns the specified data. +In the case of strings, a const-qualified pointer to +the string is returned. +
    +String data can be set or accessed as wide character strings +or normal +''char'' +strings. +The functions that use wide character strings are suffixed with +'''_w'''. +Note that these are different representations of the same data: +For example, if you store a narrow string and read the corresponding +wide string, the object will transparently convert formats +using the current locale. +Similarly, if you store a wide string and then store a +narrow string for the same data, the previously-set wide string will +be discarded in favor of the new data. +== SEE ALSO == +[[ManPagerchiventrycl3]], +[[ManPagerchiventryaths3]], +[[ManPagerchiventryerms3]], +[[ManPagerchiventryime3]], +[[ManPageibarchive3]] +== HISTORY == +The +'''libarchive''' +library first appeared in +FreeBSD 5.3. +== AUTHORS == +The +'''libarchive''' +library was written by +Tim Kientzle <kientzle@acm.org.> diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveEntryAcl3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveEntryAcl3.wiki new file mode 100644 index 0000000..7e7ed25 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveEntryAcl3.wiki @@ -0,0 +1,458 @@ +ARCHIVE_ENTRY_ACL(3) manual page +== NAME == +'''archive_entry_acl_add_entry''', +'''archive_entry_acl_add_entry_w''', +'''archive_entry_acl_clear''', +'''archive_entry_acl_count''', +'''archive_entry_acl_from_text''', +'''archive_entry_acl_from_text_w''', +'''archive_entry_acl_next''', +'''archive_entry_acl_reset''', +'''archive_entry_acl_to_text''', +'''archive_entry_acl_to_text_w''', +'''archive_entry_acl_types''' +- functions for manipulating Access Control Lists in archive entry descriptions +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''void'' +
    +'''archive_entry_acl_add_entry'''(''struct archive_entry *a'', ''int type'', ''int permset'', ''int tag'', ''int qualifier'', ''const char *name''); +
    +''void'' +
    +'''archive_entry_acl_add_entry_w'''(''struct archive_entry *a'', ''int type'', ''int permset'', ''int tag'', ''int qualifier'', ''const wchar_t *name''); +
    +''void'' +
    +'''archive_entry_acl_clear'''(''struct archive_entry *a''); +
    +''int'' +
    +'''archive_entry_acl_count'''(''struct archive_entry *a'', ''int type''); +
    +''int'' +
    +'''archive_entry_acl_from_text'''(''struct archive_entry *a'', ''const char *text'', ''int type''); +
    +''int'' +
    +'''archive_entry_acl_from_text_w'''(''struct archive_entry *a'', ''const wchar_t *text'', ''int type''); +
    +''int'' +
    +'''archive_entry_acl_next'''(''struct archive_entry *a'', ''int type'', ''int *ret_type'', ''int *ret_permset'', ''int *ret_tag'', ''int *ret_qual'', ''const char **ret_name''); +
    +''int'' +
    +'''archive_entry_acl_reset'''(''struct archive_entry *a'', ''int type''); +
    +''char *'' +
    +'''archive_entry_acl_to_text'''(''struct archive_entry *a'', ''ssize_t *len_p'', ''int flags''); +
    +''wchar_t *'' +
    +'''archive_entry_acl_to_text_w'''(''struct archive_entry *a'', ''ssize_t *len_p'', ''int flags''); +
    +''int'' +
    +'''archive_entry_acl_types'''(''struct archive_entry *a''); +== DESCRIPTION == +The +"Access Control Lists (ACLs)" +extend the standard Unix permission model. +The ACL interface of +'''libarchive''' +supports both POSIX.1e and NFSv4 style ACLs. +Use of ACLs is restricted by +various levels of ACL support in operating systems, file systems and archive +formats. +=== POSIX.1e Access Control Lists=== +A POSIX.1e ACL consists of a number of independent entries. +Each entry specifies the permission set as a bitmask of basic permissions. +Valid permissions in the +are: +
    +
    +ARCHIVE_ENTRY_ACL_READ (.B r ) +
    +ARCHIVE_ENTRY_ACL_WRITE (.B w ) +
    +ARCHIVE_ENTRY_ACL_EXECUTE (.B x ) +
    +The permissions correspond to the normal Unix permissions. + +The +specifies the principal to which the permission applies. +Valid values are: +
    +ARCHIVE_ENTRY_ACL_USER +The user specified by the name field. +
    +ARCHIVE_ENTRY_ACL_USER_OBJ +The owner of the file. +
    +ARCHIVE_ENTRY_ACL_GROUP +The group specified by the name field. +
    +ARCHIVE_ENTRY_ACL_GROUP_OBJ +The group which owns the file. +
    +ARCHIVE_ENTRY_ACL_MASK +The maximum permissions to be obtained via group permissions. +
    +ARCHIVE_ENTRY_ACL_OTHER +Any principal who is not the file owner or a member of the owning group. +
    + +The principals +ARCHIVE_ENTRY_ACL_USER_OBJ, +ARCHIVE_ENTRY_ACL_GROUP_OBJ +and +ARCHIVE_ENTRY_ACL_OTHER +are equivalent to user, group and other in the classic Unix permission +model and specify non-extended ACL entries. + +All files have an access ACL +() +ARCHIVE_ENTRY_ACL_TYPE_ACCESS. +This specifies the permissions required for access to the file itself. +Directories have an additional ACL +() +ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, +which controls the initial access ACL for newly-created directory entries. +=== NFSv4 Access Control Lists=== +A NFSv4 ACL consists of multiple individual entries called Access Control +Entries (ACEs). + +There are four possible types of a NFSv4 ACE: +
    +ARCHIVE_ENTRY_ACL_TYPE_ALLOW +Allow principal to perform actions requiring given permissions. +
    +ARCHIVE_ENTRY_ACL_TYPE_DENY +Prevent principal from performing actions requiring given permissions. +
    +ARCHIVE_ENTRY_ACL_TYPE_AUDIT +Log access attempts by principal which require given permissions. +
    +ARCHIVE_ENTRY_ACL_TYPE_ALARM +Trigger a system alarm on access attempts by principal which require given +permissions. +
    + +The +specifies the principal to which the permission applies. +Valid values are: +
    +ARCHIVE_ENTRY_ACL_USER +The user specified by the name field. +
    +ARCHIVE_ENTRY_ACL_USER_OBJ +The owner of the file. +
    +ARCHIVE_ENTRY_ACL_GROUP +The group specified by the name field. +
    +ARCHIVE_ENTRY_ACL_GROUP_OBJ +The group which owns the file. +
    +ARCHIVE_ENTRY_ACL_EVERYONE +Any principal who is not the file owner or a member of the owning group. +
    + +Entries with the +ARCHIVE_ENTRY_ACL_USER +or +ARCHIVE_ENTRY_ACL_GROUP +tag store the user and group name in the +string and optionally the user or group ID in the +integer. + +NFSv4 ACE permissions and flags are stored in the same +bitfield. +Some permissions share the same constant and permission character +but have different effect on directories than on files. +The following ACE permissions are supported: +
    +
    +ARCHIVE_ENTRY_ACL_READ_DATA (.B r ) +Read data (file). +
    +ARCHIVE_ENTRY_ACL_LIST_DIRECTORY (.B r ) +List entries (directory). +
    ARCHIVE_ENTRY_ACL_WRITE_DATA (.B w )
    +Write data (file). +
    ARCHIVE_ENTRY_ACL_ADD_FILE (.B w )
    +Create files (directory). +
    +ARCHIVE_ENTRY_ACL_EXECUTE (.B x ) +Execute file or change into a directory. +
    +ARCHIVE_ENTRY_ACL_APPEND_DATA (.B p ) +Append data (file). +
    +ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY (.B p ) +Create subdirectories (directory). +
    +ARCHIVE_ENTRY_ACL_DELETE_CHILD (.B D ) +Remove files and subdirectories inside a directory. +
    +ARCHIVE_ENTRY_ACL_DELETE (.B d ) +Remove file or directory. +
    +ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES (.B a ) +Read file or directory attributes. +
    +ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES (.B A ) +Write file or directory attributes. +
    +ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS (.B R ) +Read named file or directory attributes. +
    +ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS (.B W ) +Write named file or directory attributes. +
    +ARCHIVE_ENTRY_ACL_READ_ACL (.B c ) +Read file or directory ACL. +
    +ARCHIVE_ENTRY_ACL_WRITE_ACL (.B C ) +Write file or directory ACL. +
    +ARCHIVE_ENTRY_ACL_WRITE_OWNER (.B o ) +Change owner of a file or directory. +
    +ARCHIVE_ENTRY_ACL_SYNCHRONIZE (.B s ) +Use synchronous I/O. +
    + +The following NFSv4 ACL inheritance flags are supported: +
    +
    +ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT (.B f ) +Inherit parent directory ACE to files. +
    +ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT (.B d ) +Inherit parent directory ACE to subdirectories. +
    +ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY (.B i ) +Only inherit, do not apply the permission on the directory itself. +
    +ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT (.B n ) +Do not propagate inherit flags. +Only first-level entries inherit ACLs. +
    +ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS (.B S ) +Trigger alarm or audit on successful access. +
    +ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS (.B F ) +Trigger alarm or audit on failed access. +
    +ARCHIVE_ENTRY_ACL_ENTRY_INHERITED (.B I ) +Mark that ACE was inherited. +
    +=== Functions=== +'''archive_entry_acl_add_entry'''() +and +'''archive_entry_acl_add_entry_w'''() +add a single ACL entry. +For the access ACL and non-extended principals, the classic Unix permissions +are updated. +An archive entry cannot contain both POSIX.1e and NFSv4 ACL entries. + +'''archive_entry_acl_clear'''() +removes all ACL entries and resets the enumeration pointer. + +'''archive_entry_acl_count'''() +counts the ACL entries that have the given type mask. +can be the bitwise-or of +
    +
    +ARCHIVE_ENTRY_ACL_TYPE_ACCESS +
    +ARCHIVE_ENTRY_ACL_TYPE_DEFAULT +
    +for POSIX.1e ACLs and +
    +
    +ARCHIVE_ENTRY_ACL_TYPE_ALLOW +
    +ARCHIVE_ENTRY_ACL_TYPE_DENY +
    +ARCHIVE_ENTRY_ACL_TYPE_AUDIT +
    +ARCHIVE_ENTRY_ACL_TYPE_ALARM +
    +for NFSv4 ACLs. +For POSIX.1e ACLs if +ARCHIVE_ENTRY_ACL_TYPE_ACCESS +is included and at least one extended ACL entry is found, +the three non-extended ACLs are added. + +'''archive_entry_acl_from_text'''() +and +'''archive_entry_acl_from_text_w'''() +add new +(or merge with existing) +ACL entries from +(wide) +text. +The argument +may take one of the following values: +
    +
    +ARCHIVE_ENTRY_ACL_TYPE_ACCESS +
    +ARCHIVE_ENTRY_ACL_TYPE_DEFAULT +
    +ARCHIVE_ENTRY_ACL_TYPE_NFS4 +
    +Supports all formats that can be created with +'''archive_entry_acl_to_text'''() +or respectively +'''archive_entry_acl_to_text_w'''(). +Existing ACL entries are preserved. +To get a clean new ACL from text +'''archive_entry_acl_clear'''() +must be called first. +Entries prefixed with +"default:" +are treated as +ARCHIVE_ENTRY_ACL_TYPE_DEFAULT +unless +is +ARCHIVE_ENTRY_ACL_TYPE_NFS4. +Invalid entries, non-parseable ACL entries and entries beginning with +the +Sq # +character +(comments) +are skipped. + +'''archive_entry_acl_next'''() +return the next entry of the ACL list. +This functions may only be called after +'''archive_entry_acl_reset'''() +has indicated the presence of extended ACL entries. + +'''archive_entry_acl_reset'''() +prepare reading the list of ACL entries with +'''archive_entry_acl_next'''(). +The function returns 0 if no non-extended ACLs are found. +In this case, the access permissions should be obtained by +[[ManPagerchiventryode3]] +or set using +[[chmod(2)|http://www.freebsd.org/cgi/man.cgi?query=chmod&sektion=2]]. +Otherwise, the function returns the same value as +'''archive_entry_acl_count'''(). + +'''archive_entry_acl_to_text'''() +and +'''archive_entry_acl_to_text_w'''() +convert the ACL entries for the given type into a +(wide) +string of ACL entries separated by newline. +If the pointer +is not NULL, then the function shall return the length of the string +(not including the NULL terminator) +in the location pointed to by +. +The +argument is a bitwise-or. + +The following flags are effective only on POSIX.1e ACL: +
    +
    +ARCHIVE_ENTRY_ACL_TYPE_ACCESS +Output access ACLs. +
    +ARCHIVE_ENTRY_ACL_TYPE_DEFAULT +Output POSIX.1e default ACLs. +
    +ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT +Prefix each default ACL entry with the word +"default:". +
    +ARCHIVE_ENTRY_ACL_STYLE_SOLARIS +The mask and other ACLs don not contain a double colon. +
    + +The following flags are effecive only on NFSv4 ACL: +
    +
    +ARCHIVE_ENTRY_ACL_STYLE_COMPACT +Do not output minus characters for unset permissions and flags in NFSv4 ACL +permission and flag fields. +
    + +The following flags are effective on both POSIX.1e and NFSv4 ACL: +
    +
    +ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID +Add an additional colon-separated field containing the user or group id. +
    +ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA +Separate ACL entries with comma instead of newline. +
    + +If the archive entry contains NFSv4 ACLs, all types of NFSv4 ACLs are returned. +It the entry contains POSIX.1e ACLs and none of the flags +ARCHIVE_ENTRY_ACL_TYPE_ACCESS +or +ARCHIVE_ENTRY_ACL_TYPE_DEFAULT +are specified, both access and default entries are returned and default entries +are prefixed with +"default:". + +'''archive_entry_acl_types'''() +get ACL entry types contained in an archive entry's ACL. +As POSIX.1e and NFSv4 +ACL entries cannot be mixed, this function is a very efficient way to detect if +an ACL already contains POSIX.1e or NFSv4 ACL entries. +== RETURN VALUES == +'''archive_entry_acl_count'''() +and +'''archive_entry_acl_reset'''() +returns the number of ACL entries that match the given type mask. +For POSIX.1e ACLS if the type mask includes +ARCHIVE_ENTRY_ACL_TYPE_ACCESS +and at least one extended ACL entry exists, the three classic Unix +permissions are counted. + +'''archive_entry_acl_from_text'''() +and +'''archive_entry_acl_from_text_w'''() +return +ARCHIVE_OK +if all entries were successfully parsed and +ARCHIVE_WARN +if one or more entries were invalid or non-parseable. + +'''archive_entry_acl_next'''() +returns +ARCHIVE_OK +on success, +ARCHIVE_EOF +if no more ACL entries exist +and +ARCHIVE_WARN +if +'''archive_entry_acl_reset'''() +has not been called first. + +'''archive_entry_acl_to_text'''() +returns a string representing the ACL entries matching the given type and +flags on success or NULL on error. + +'''archive_entry_acl_to_text_w'''() +returns a wide string representing the ACL entries matching the given type +and flags on success or NULL on error. + +'''archive_entry_acl_types'''() +returns a bitmask of ACL entry types or 0 if archive entry has no ACL entries. +== SEE ALSO == +[[ManPagerchiventry3]], +[[ManPageibarchive3]] diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveEntryLinkify3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveEntryLinkify3.wiki new file mode 100644 index 0000000..1e35c59 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveEntryLinkify3.wiki @@ -0,0 +1,197 @@ +ARCHIVE_ENTRY_LINKIFY(3) manual page +== NAME == +'''archive_entry_linkresolver''', +'''archive_entry_linkresolver_new''', +'''archive_entry_linkresolver_set_strategy''', +'''archive_entry_linkresolver_free''', +'''archive_entry_linkify''' +- hardlink resolver functions +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''struct archive_entry_linkresolver *'' +
    +'''archive_entry_linkresolver_new'''(''void''); +
    +''void'' +
    +'''archive_entry_linkresolver_set_strategy'''(''struct archive_entry_linkresolver *resolver'', ''int format''); +
    +''void'' +
    +'''archive_entry_linkresolver_free'''(''struct archive_entry_linkresolver *resolver''); +
    +''void'' +
    +'''archive_entry_linkify'''(''struct archive_entry_linkresolver *resolver'', ''struct archive_entry **entry'', ''struct archive_entry **sparse''); +== DESCRIPTION == +Programs that want to create archives have to deal with hardlinks. +Hardlinks are handled in different ways by the archive formats. +The basic strategies are: +
      +
    1. +Ignore hardlinks and store the body for each reference (old cpio, zip). +
    2. +Store the body the first time an inode is seen (ustar, pax). +
    3. +Store the body the last time an inode is seen (new cpio). +
    + +The +'''archive_entry_linkresolver''' +functions help by providing a unified interface and handling the complexity +behind the scene. + +The +'''archive_entry_linkresolver''' +functions assume that +''archive_entry'' +instances have valid nlinks, inode and device values. +The inode and device value is used to match entries. +The nlinks value is used to determined if all references have been found and +if the internal references can be recycled. + +The +'''archive_entry_linkresolver_new'''() +function allocates a new link resolver. +The instance can be freed using +'''archive_entry_linkresolver_free'''(). +All deferred entries are flushed and the internal storage is freed. + +The +'''archive_entry_linkresolver_set_strategy'''() +function selects the optimal hardlink strategy for the given format. +The format code can be obtained from +[[ManPagerchiveormat3]]. +The function can be called more than once, but it is recommended to +flush all deferred entries first. + +The +'''archive_entry_linkify'''() +function is the core of +'''archive_entry_linkresolver'''. +The +'''entry'''() +argument points to the +''archive_entry'' +that should be written. +Depending on the strategy one of the following actions is taken: +
      +
    1. +For the simple archive formats +''*entry'' +is left unmodified and +''*sparse'' +is set to +NULL. +
    2. +For tar like archive formats, +''*sparse'' +is set to +NULL. +If +''*entry'' +is +NULL, +no action is taken. +If the hardlink count of +''*entry'' +is larger than 1 and the file type is a regular file or symbolic link, +the internal list is searched for a matching inode. +If such an inode is found, the link count is decremented and the file size +of +''*entry'' +is set to 0 to notify that no body should be written. +If no such inode is found, a copy of the entry is added to the internal cache +with a link count reduced by one. +
    3. +For new cpio like archive formats a value for +''*entry'' +of +NULL +is used to flush deferred entries. +In that case +''*entry'' +is set to an arbitrary deferred entry and the entry itself is removed from the +internal list. +If the internal list is empty, +''*entry'' +is set to +NULL. +In either case, +''*sparse'' +is set to +NULL +and the function returns. +If the hardlink count of +''*entry'' +is one or the file type is a directory or device, +''*sparse'' +is set to +NULL +and no further action is taken. +Otherwise, the internal list is searched for a matching inode. +If such an inode is not found, the entry is added to the internal list, +both +''*entry'' +and +''*sparse'' +are set to +NULL +and the function returns. +If such an inode is found, the link count is decremented. +If it remains larger than one, the existing entry on the internal list +is swapped with +''*entry'' +after retaining the link count. +The existing entry is returned in +''*entry''. +If the link count reached one, the new entry is also removed from the +internal list and returned in +''*sparse''. +Otherwise +''*sparse'' +is set to +NULL. +
    + +The general usage is therefore: +
      +
    1. +For each new archive entry, call +'''archive_entry_linkify'''(). +
    2. +Keep in mind that the entries returned may have a size of 0 now. +
    3. +If +''*entry'' +is not +NULL, +archive it. +
    4. +If +''*sparse'' +is not +NULL, +archive it. +
    5. +After all entries have been written to disk, call +'''archive_entry_linkify'''() +with +''*entry'' +set to +NULL +and archive the returned entry as long as it is not +NULL. +
    +== RETURN VALUES == +'''archive_entry_linkresolver_new'''() +returns +NULL +on +[[malloc(3)|http://www.freebsd.org/cgi/man.cgi?query=malloc&sektion=3]] +failures. +== SEE ALSO == +[[ManPagerchiventry3]] diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveEntryMisc3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveEntryMisc3.wiki new file mode 100644 index 0000000..02a91fd --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveEntryMisc3.wiki @@ -0,0 +1,41 @@ +ARCHIVE_ENTRY_MISC(3) manual page +== NAME == +'''archive_entry_symlink_type''', +'''archive_entry_set_symlink_type''' +- miscellaneous functions for manipulating properties of archive_entry +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''int'' +
    +'''archive_entry_symlink_type'''(''struct archive_entry *a''); +
    +''void'' +
    +'''archive_entry_set_symlink_type'''(''struct archive_entry *a'', ''int''); +== DESCRIPTION == +The function +'''archive_entry_symlink_type'''() +returns and the function +'''archive_entry_set_symlink_type'''() +sets the type of the symbolic link stored in an archive entry. +These functions +have special meaning on operating systems that support multiple symbolic link +types (e.g. Microsoft Windows). + +Supported values are: +
    +
    AE_SYMLINK_TYPE_UNDEFINED
    +Symbolic link target type is not defined (default on unix systems) +
    AE_SYMLINK_TYPE_FILE
    +Symbolic link points to a file +
    AE_SYMLINK_TYPE_DIRECTORY
    +Symbolic link points to a directory +
    +== SEE ALSO == +[[ManPagerchiventry3]], +[[ManPagerchiventryaths3]], +[[ManPagerchiventrytat3]], +[[ManPageibarchive3]] diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveEntryPaths3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveEntryPaths3.wiki new file mode 100644 index 0000000..64ccef9 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveEntryPaths3.wiki @@ -0,0 +1,175 @@ +ARCHIVE_ENTRY_PATHS(3) manual page +== NAME == +'''archive_entry_hardlink''', +'''archive_entry_hardlink_w''', +'''archive_entry_set_hardlink''', +'''archive_entry_copy_hardlink''', +'''archive_entry_copy_hardlink_w''', +'''archive_entry_update_hardlink_utf8''', +'''archive_entry_set_link''', +'''archive_entry_copy_link''', +'''archive_entry_copy_link_w''', +'''archive_entry_update_link_utf8''', +'''archive_entry_pathname''', +'''archive_entry_pathname_w''', +'''archive_entry_set_pathname''', +'''archive_entry_copy_pathname''', +'''archive_entry_copy_pathname_w''', +'''archive_entry_update_pathname_utf8''', +'''archive_entry_sourcepath''', +'''archive_entry_copy_sourcepath''', +'''archive_entry_symlink''', +'''archive_entry_symlink_w''', +'''archive_entry_set_symlink''', +'''archive_entry_copy_symlink''', +'''archive_entry_copy_symlink_w''', +'''archive_entry_update_symlink_utf8''' +- functions for manipulating path names in archive entry descriptions +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''const char *'' +
    +'''archive_entry_hardlink'''(''struct archive_entry *a''); +
    +''const wchar_t *'' +
    +'''archive_entry_hardlink_w'''(''struct archive_entry *a''); +
    +''void'' +
    +'''archive_entry_set_hardlink'''(''struct archive_entry *a'', ''const char *path''); +
    +''void'' +
    +'''archive_entry_copy_hardlink'''(''struct archive_entry *a'', ''const char *path''); +
    +''void'' +
    +'''archive_entry_copy_hardlink_w'''(''struct archive_entry *a '', ''const'', ''wchar_t'', ''*path"''); +
    +''int'' +
    +'''archive_entry_update_hardlink_utf8'''(''struct archive_entry *a'', ''const char *path''); +
    +''void'' +
    +'''archive_entry_set_link'''(''struct archive_entry *a'', ''const char *path''); +
    +''void'' +
    +'''archive_entry_copy_link'''(''struct archive_entry *a'', '' const char *path''); +
    +''void'' +
    +'''archive_entry_copy_link_w'''(''struct archive_entry *a'', '' const wchar_t *path''); +
    +''int'' +
    +'''archive_entry_update_link_utf8'''(''struct archive_entry *a'', '' const char *path''); +
    +''const char *'' +
    +'''archive_entry_pathname'''(''struct archive_entry *a''); +
    +''const wchar_t *'' +
    +'''archive_entry_pathname_w'''(''struct archive_entry *a''); +
    +''void'' +
    +'''archive_entry_set_pathname'''(''struct archive_entry *a'', ''const char *path''); +
    +''void'' +
    +'''archive_entry_copy_pathname'''(''struct archive_entry *a'', ''const char *path''); +
    +''void'' +
    +'''archive_entry_copy_pathname_w'''(''struct archive_entry *a'', ''const wchar_t *path''); +
    +''int'' +
    +'''archive_entry_update_pathname_utf8'''(''struct archive_entry *a'', ''const char *path''); +
    +''const char *'' +
    +'''archive_entry_sourcepath'''(''struct archive_entry *a''); +
    +''void'' +
    +'''archive_entry_copy_sourcepath'''(''struct archive_entry *a'', ''const char *path''); +
    +''const char *'' +
    +'''archive_entry_symlink'''(''struct archive_entry *a''); +
    +''const wchar_t *'' +
    +'''archive_entry_symlink_w'''(''struct archive_entry *a''); +
    +''void'' +
    +'''archive_entry_set_symlink'''(''struct archive_entry *a'', ''const char *path''); +
    +''void'' +
    +'''archive_entry_copy_symlink'''(''struct archive_entry *a'', ''const char *path''); +
    +''void'' +
    +'''archive_entry_copy_symlink_w'''(''struct archive_entry *a'', ''const wchar_t *path''); +
    +''int'' +
    +'''archive_entry_update_symlink_utf8'''(''struct archive_entry *a'', ''const char *path''); +== DESCRIPTION == +Path names supported by +[[ManPagerchiventry3]]: +
    +
    hardlink
    +Destination of the hardlink. +
    link
    +Update only. +For a symlink, update the destination. +Otherwise, make the entry a hardlink and alter +the destination for that. +
    pathname
    +Path in the archive +
    sourcepath
    +Path on the disk for use by +[[ManPagerchiveeadisk3]]. +
    symlink
    +Destination of the symbolic link. +
    + +Path names can be provided in one of three different ways: +
    +
    char *
    +Multibyte strings in the current locale. +
    wchar_t *
    +Wide character strings in the current locale. +The accessor functions are named +'''XXX_w'''(). +
    UTF-8
    +Unicode strings encoded as UTF-8. +These are convenience functions to update both the multibyte and wide +character strings at the same time. +
    + +The sourcepath is a pure filesystem concept and never stored in an +archive directly. + +For that reason, it is only available as multibyte string. +The link path is a convenience function for conditionally setting +hardlink or symlink destination. +It doesn't have a corresponding get accessor function. + +'''archive_entry_set_XXX'''() +is an alias for +'''archive_entry_copy_XXX'''(). +== SEE ALSO == +[[ManPagerchiventry3]], +[[ManPageibarchive3]] diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveEntryPerms3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveEntryPerms3.wiki new file mode 100644 index 0000000..f18ee60 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveEntryPerms3.wiki @@ -0,0 +1,222 @@ +ARCHIVE_ENTRY_PERMS(3) manual page +== NAME == +'''archive_entry_gid''', +'''archive_entry_set_gid''', +'''archive_entry_uid''', +'''archive_entry_set_uid''', +'''archive_entry_perm''', +'''archive_entry_set_perm''', +'''archive_entry_strmode''', +'''archive_entry_uname''', +'''archive_entry_uname_w''', +'''archive_entry_set_uname''', +'''archive_entry_copy_uname''', +'''archive_entry_copy_uname_w''', +'''archive_entry_update_uname_utf8''', +'''archive_entry_gname''', +'''archive_entry_gname_w''', +'''archive_entry_set_gname''', +'''archive_entry_copy_gname''', +'''archive_entry_copy_gname_w''', +'''archive_entry_update_gname_utf8''', +'''archive_entry_fflags''', +'''archive_entry_fflags_text''', +'''archive_entry_set_fflags''', +'''archive_entry_copy_fflags_text''', +'''archive_entry_copy_fflags_text_w''' +- functions for manipulating ownership and permissions in archive entry descriptions +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''gid_t'' +
    +'''archive_entry_gid'''(''struct archive_entry *a''); +
    +''void'' +
    +'''archive_entry_set_gid'''(''struct archive_entry *a'', ''gid_t gid''); +
    +''uid_t'' +
    +'''archive_entry_uid'''(''struct archive_entry *a''); +
    +''void'' +
    +'''archive_entry_set_uid'''(''struct archive_entry *a'', ''uid_t uid''); +
    +''mode_t'' +
    +'''archive_entry_perm'''(''struct archive_entry *a''); +
    +''void'' +
    +'''archive_entry_set_perm'''(''struct archive_entry *a'', ''mode_t mode''); +
    +''const char *'' +
    +'''archive_entry_strmode'''(''struct archive_entry *a''); +
    +''const char *'' +
    +'''archive_entry_gname'''(''struct archive_entry *a''); +
    +''const wchar_t *'' +
    +'''archive_entry_gname_w'''(''struct archive_entry *a''); +
    +''void'' +
    +'''archive_entry_set_gname'''(''struct archive_entry *a'', ''const char *a''); +
    +''void'' +
    +'''archive_entry_copy_gname'''(''struct archive_entry *a'', ''const char *name''); +
    +''void'' +
    +'''archive_entry_copy_gname_w'''(''struct archive_entry *a'', ''const wchar_t *name''); +
    +''int'' +
    +'''archive_entry_update_gname_utf8'''(''struct archive_entry *a'', ''const char *name''); +
    +''const char *'' +
    +'''archive_entry_uname'''(''struct archive_entry *a''); +
    +''const wchar_t *'' +
    +'''archive_entry_uname_w'''(''struct archive_entry *a''); +
    +''void'' +
    +'''archive_entry_set_uname'''(''struct archive_entry *a'', ''const char *name''); +
    +''void'' +
    +'''archive_entry_copy_uname'''(''struct archive_entry *a'', ''const char *name''); +
    +''void'' +
    +'''archive_entry_copy_uname_w'''(''struct archive_entry *a'', ''const wchar_t *name''); +
    +''int'' +
    +'''archive_entry_update_uname_utf8'''(''struct archive_entry *a'', ''const char *name''); +
    +''void'' +
    +'''archive_entry_fflags'''(''struct archive_entry *a'', ''unsigned long *set_bits'', ''unsigned long *clear_bits''); +
    +''const char *'' +
    +'''archive_entry_fflags_text'''(''struct archive_entry *a''); +
    +''void'' +
    +'''archive_entry_set_fflags'''(''struct archive_entry *a'', ''unsigned long set_bits'', ''unsigned long clear_bits''); +
    +''const char *'' +
    +'''archive_entry_copy_fflags_text'''(''struct archive_entry *a'', ''const char *text''); +
    +''const wchar_t *'' +
    +'''archive_entry_copy_fflags_text_w'''(''struct archive_entry *a'', ''const wchar_t *text''); +== DESCRIPTION == +=== User id, group id and mode=== +The functions +'''archive_entry_uid'''(), +'''archive_entry_gid'''(), +and +'''archive_entry_perm'''() +can be used to extract the user id, group id and permission from the given entry. +The corresponding functions +'''archive_entry_set_uid'''(), +'''archive_entry_set_gid'''(), +and +'''archive_entry_set_perm'''() +store the given user id, group id and permission in the entry. +The permission is also set as a side effect of calling +'''archive_entry_set_mode'''(). + +'''archive_entry_strmode'''() +returns a string representation of the permission as used by the long mode of +[[ls(1)|http://www.freebsd.org/cgi/man.cgi?query=ls&sektion=1]]. +=== User and group name=== +User and group names can be provided in one of three different ways: +
    +
    char *
    +Multibyte strings in the current locale. +
    wchar_t *
    +Wide character strings in the current locale. +The accessor functions are named +'''XXX_w'''(). +
    UTF-8
    +Unicode strings encoded as UTF-8. +These are convenience functions to update both the multibyte and wide +character strings at the same time. +
    + +'''archive_entry_set_XXX'''() +is an alias for +'''archive_entry_copy_XXX'''(). +=== File Flags=== +File flags are transparently converted between a bitmap +representation and a textual format. +For example, if you set the bitmap and ask for text, the library +will build a canonical text format. +However, if you set a text format and request a text format, +you will get back the same text, even if it is ill-formed. +If you need to canonicalize a textual flags string, you should first set the +text form, then request the bitmap form, then use that to set the bitmap form. +Setting the bitmap format will clear the internal text representation +and force it to be reconstructed when you next request the text form. + +The bitmap format consists of two integers, one containing bits +that should be set, the other specifying bits that should be +cleared. +Bits not mentioned in either bitmap will be ignored. +Usually, the bitmap of bits to be cleared will be set to zero. +In unusual circumstances, you can force a fully-specified set +of file flags by setting the bitmap of flags to clear to the complement +of the bitmap of flags to set. +(This differs from +[[fflagstostr(3)|http://www.freebsd.org/cgi/man.cgi?query=fflagstostr&sektion=3]], +which only includes names for set bits.) +Converting a bitmap to a textual string is a platform-specific +operation; bits that are not meaningful on the current platform +will be ignored. + +The canonical text format is a comma-separated list of flag names. +The +'''archive_entry_copy_fflags_text'''() +and +'''archive_entry_copy_fflags_text_w'''() +functions parse the provided text and set the internal bitmap values. +This is a platform-specific operation; names that are not meaningful +on the current platform will be ignored. +The function returns a pointer to the start of the first name that was not +recognized, or NULL if every name was recognized. +Note that every name \(em including names that follow an unrecognized +name \(em will be evaluated, and the bitmaps will be set to reflect +every name that is recognized. +(In particular, this differs from +[[strtofflags(3)|http://www.freebsd.org/cgi/man.cgi?query=strtofflags&sektion=3]], +which stops parsing at the first unrecognized name.) +== SEE ALSO == +[[ManPagerchiventry3]], +[[ManPagerchiventrycl3]], +[[ManPagerchiveeadisk3]], +[[ManPagerchiveriteisk3]], +[[ManPageibarchive3]] +== BUGS == +The platform types +''uid_t'' +and +''gid_t'' +are often 16 or 32 bit wide. +In this case it is possible that the ids can not be correctly restored +from archives and get truncated. diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveEntryStat3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveEntryStat3.wiki new file mode 100644 index 0000000..1d3f96d --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveEntryStat3.wiki @@ -0,0 +1,308 @@ +ARCHIVE_ENTRY_STAT(3) manual page +== NAME == +'''archive_entry_stat''', +'''archive_entry_copy_stat''', +'''archive_entry_filetype''', +'''archive_entry_set_filetype''', +'''archive_entry_mode''', +'''archive_entry_set_mode''', +'''archive_entry_size''', +'''archive_entry_size_is_set''', +'''archive_entry_set_size''', +'''archive_entry_unset_size''', +'''archive_entry_dev''', +'''archive_entry_set_dev''', +'''archive_entry_dev_is_set''', +'''archive_entry_devmajor''', +'''archive_entry_set_devmajor''', +'''archive_entry_devminor''', +'''archive_entry_set_devminor''', +'''archive_entry_ino''', +'''archive_entry_set_ino''', +'''archive_entry_ino_is_set''', +'''archive_entry_ino64''', +'''archive_entry_set_ino64''', +'''archive_entry_nlink''', +'''archive_entry_rdev''', +'''archive_entry_set_rdev''', +'''archive_entry_rdevmajor''', +'''archive_entry_set_rdevmajor''', +'''archive_entry_rdevminor''', +'''archive_entry_set_rdevminor''' +- accessor functions for manipulating archive entry descriptions +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''const struct stat *'' +
    +'''archive_entry_stat'''(''struct archive_entry *a''); +
    +''void'' +
    +'''archive_entry_copy_stat'''(''struct archive_entry *a'', ''const struct stat *sb''); +
    +''mode_t'' +
    +'''archive_entry_filetype'''(''struct archive_entry *a''); +
    +''void'' +
    +'''archive_entry_set_filetype'''(''struct archive_entry *a'', ''unsigned int type''); +
    +''mode_t'' +
    +'''archive_entry_mode'''(''struct archive_entry *a''); +
    +''void'' +
    +'''archive_entry_set_mode'''(''struct archive_entry *a'', ''mode_t mode''); +
    +''int64_t'' +
    +'''archive_entry_size'''(''struct archive_entry *a''); +
    +''int'' +
    +'''archive_entry_size_is_set'''(''struct archive_entry *a''); +
    +''void'' +
    +'''archive_entry_set_size'''(''struct archive_entry *a'', ''int64_t size''); +
    +''void'' +
    +'''archive_entry_unset_size'''(''struct archive_entry *a''); +
    +''dev_t'' +
    +'''archive_entry_dev'''(''struct archive_entry *a''); +
    +''void'' +
    +'''archive_entry_set_dev'''(''struct archive_entry *a'', ''dev_t dev''); +
    +''int'' +
    +'''archive_entry_dev_is_set'''(''struct archive_entry *a''); +
    +''dev_t'' +
    +'''archive_entry_devmajor'''(''struct archive_entry *a''); +
    +''void'' +
    +'''archive_entry_set_devmajor'''(''struct archive_entry *a'', ''dev_t major''); +
    +''dev_t'' +
    +'''archive_entry_devminor'''(''struct archive_entry *a''); +
    +''void'' +
    +'''archive_entry_set_devminor'''(''struct archive_entry *a'', ''dev_t minor''); +
    +''ino_t'' +
    +'''archive_entry_ino'''(''struct archive_entry *a''); +
    +''void'' +
    +'''archive_entry_set_ino'''(''struct archive_entry *a'', ''unsigned long ino''); +
    +''int'' +
    +'''archive_entry_ino_is_set'''(''struct archive_entry *a''); +
    +''int64_t'' +
    +'''archive_entry_ino64'''(''struct archive_entry *a''); +
    +''void'' +
    +'''archive_entry_set_ino64'''(''struct archive_entry *a'', ''int64_t ino''); +
    +''unsigned int'' +
    +'''archive_entry_nlink'''(''struct archive_entry *a''); +
    +''void'' +
    +'''archive_entry_set_nlink'''(''struct archive_entry *a'', ''unsigned int count''); +
    +''dev_t'' +
    +'''archive_entry_rdev'''(''struct archive_entry *a''); +
    +''dev_t'' +
    +'''archive_entry_rdevmajor'''(''struct archive_entry *a''); +
    +''dev_t'' +
    +'''archive_entry_rdevminor'''(''struct archive_entry *a''); +
    +''void'' +
    +'''archive_entry_set_rdev'''(''struct archive_entry *a'', ''dev_t dev''); +
    +''void'' +
    +'''archive_entry_set_rdevmajor'''(''struct archive_entry *a'', ''dev_t major''); +
    +''void'' +
    +'''archive_entry_set_rdevminor'''(''struct archive_entry *a'', ''dev_t minor''); +== DESCRIPTION == +=== Copying to and from ''struct'' stat=== +The function +'''archive_entry_stat'''() +converts the various fields stored in the archive entry to the format +used by +[[stat(2)|http://www.freebsd.org/cgi/man.cgi?query=stat&sektion=2]]. +The return value remains valid until either +'''archive_entry_clear'''() +or +'''archive_entry_free'''() +is called. +It is not affected by calls to the set accessor functions. +It currently sets the following values in +''struct'' stat: +''st_atime'', +''st_ctime'', +''st_dev'', +''st_gid'', +''st_ino'', +''st_mode'', +''st_mtime'', +''st_nlink'', +''st_rdev'', +''st_size'', +''st_uid''. +In addition, +''st_birthtime'' +and high-precision information for time-related fields +will be included on platforms that support it. + +The function +'''archive_entry_copy_stat'''() +copies fields from the platform's +''struct'' stat. +Fields not provided by +''struct'' stat +are unchanged. +=== General accessor functions=== +The functions +'''archive_entry_filetype'''() +and +'''archive_entry_set_filetype'''() +get respectively set the filetype. +The file type is one of the following constants: +
    +
    AE_IFREG
    +Regular file +
    AE_IFLNK
    +Symbolic link +
    AE_IFSOCK
    +Socket +
    AE_IFCHR
    +Character device +
    AE_IFBLK
    +Block device +
    AE_IFDIR
    +Directory +
    AE_IFIFO
    +Named pipe (fifo) +
    +Not all file types are supported by all platforms. +The constants used by +[[stat(2)|http://www.freebsd.org/cgi/man.cgi?query=stat&sektion=2]] +may have different numeric values from the +corresponding constants above. + +The functions +'''archive_entry_mode'''() +and +'''archive_entry_set_mode'''() +get/set a combination of file type and permissions and provide the +equivalent of +''st_mode''. +Use of +'''archive_entry_filetype'''() +and +'''archive_entry_perm'''() +for getting and +'''archive_entry_set_filetype'''() +and +'''archive_entry_set_perm'''() +for setting is recommended. + +The function +'''archive_entry_size'''() +returns the file size, if it has been set, and 0 otherwise. +'''archive_entry_size'''() +can be used to query that status. +'''archive_entry_set_size'''() +and +'''archive_entry_unset_size'''() +set and unset the size, respectively. + +The number of references (hardlinks) can be obtained by calling +'''archive_entry_nlinks'''() +and set with +'''archive_entry_set_nlinks'''(). +=== Identifying unique files=== +The functions +'''archive_entry_dev'''() +and +'''archive_entry_ino64'''() +are used by +[[ManPagerchiventryinkify3]] +to find hardlinks. +The pair of device and inode is supposed to identify hardlinked files. + +The device major and minor number can be obtained independently using +'''archive_entry_devmajor'''() +and +'''archive_entry_devminor'''(). +The device can be set either via +'''archive_entry_set_dev'''() +or by the combination of major and minor number using +'''archive_entry_set_devmajor'''() +and +'''archive_entry_set_devminor'''(). + +The inode number can be obtained using +'''archive_entry_ino'''(). +This is a legacy interface that uses the platform +''ino_t'', +which may be very small. +To set the inode number, +'''archive_entry_set_ino64'''() +is the preferred interface. +=== Accessor functions for block and character devices=== +Block and character devices are characterised either using a device number +or a pair of major and minor number. +The combined device number can be obtained with +'''archive_device_rdev'''() +and set with +'''archive_device_set_rdev'''(). +The major and minor numbers are accessed by +'''archive_device_rdevmajor'''(), +'''archive_device_rdevminor'''() +'''archive_device_set_rdevmajor'''() +and +'''archive_device_set_rdevminor'''(). + +The process of splitting the combined device number into major and +minor number and the reverse process of combing them differs between +platforms. +Some archive formats use the combined form, while other formats use +the split form. +== SEE ALSO == +[[stat(2)|http://www.freebsd.org/cgi/man.cgi?query=stat&sektion=2]], +[[ManPagerchiventrycl3]], +[[ManPagerchiventryerms3]], +[[ManPagerchiventryime3]], +[[ManPageibarchive3]] diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveEntryTime3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveEntryTime3.wiki new file mode 100644 index 0000000..f46aa84 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveEntryTime3.wiki @@ -0,0 +1,138 @@ +ARCHIVE_ENTRY_TIME(3) manual page +== NAME == +'''archive_entry_atime''', +'''archive_entry_atime_nsec''', +'''archive_entry_atime_is_set''', +'''archive_entry_set_atime''', +'''archive_entry_unset_atime''', +'''archive_entry_birthtime''', +'''archive_entry_birthtime_nsec''', +'''archive_entry_birthtime_is_set''', +'''archive_entry_set_birthtime''', +'''archive_entry_unset_birthtime''', +'''archive_entry_ctime''', +'''archive_entry_ctime_nsec''', +'''archive_entry_ctime_is_set''', +'''archive_entry_set_ctime''', +'''archive_entry_unset_ctime''', +'''archive_entry_mtime''', +'''archive_entry_mtime_nsec''', +'''archive_entry_mtime_is_set''', +'''archive_entry_set_mtime''', +'''archive_entry_unset_mtime''' +- functions for manipulating times in archive entry descriptions +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''time_t'' +
    +'''archive_entry_atime'''(''struct archive_entry *a''); +
    +''long'' +
    +'''archive_entry_atime_nsec'''(''struct archive_entry *a''); +
    +''int'' +
    +'''archive_entry_atime_is_set'''(''struct archive_entry *a''); +
    +''void'' +
    +'''archive_entry_set_atime'''(''struct archive_entry *a'', ''time_t sec'', ''long nanosec''); +
    +''void'' +
    +'''archive_entry_unset_atime'''(''struct archive_entry *a''); +
    +''time_t'' +
    +'''archive_entry_birthtime'''(''struct archive_entry *a''); +
    +''long'' +
    +'''archive_entry_birthtime_nsec'''(''struct archive_entry *a''); +
    +''int'' +
    +'''archive_entry_birthtime_is_set'''(''struct archive_entry *a''); +
    +''void'' +
    +'''archive_entry_set_birthtime'''(''struct archive_entry *a'', ''time_t sec'', ''long nanosec''); +
    +''void'' +
    +'''archive_entry_unset_birthtime'''(''struct archive_entry *a''); +
    +''time_t'' +
    +'''archive_entry_ctime'''(''struct archive_entry *a''); +
    +''long'' +
    +'''archive_entry_ctime_nsec'''(''struct archive_entry *a''); +
    +''int'' +
    +'''archive_entry_ctime_is_set'''(''struct archive_entry *a''); +
    +''void'' +
    +'''archive_entry_set_ctime'''(''struct archive_entry *a'', ''time_t sec'', ''long nanosec''); +
    +''void'' +
    +'''archive_entry_unset_ctime'''(''struct archive_entry *a''); +
    +''time_t'' +
    +'''archive_entry_mtime'''(''struct archive_entry *a''); +
    +''long'' +
    +'''archive_entry_mtime_nsec'''(''struct archive_entry *a''); +
    +''int'' +
    +'''archive_entry_mtime_is_set'''(''struct archive_entry *a''); +
    +''void'' +
    +'''archive_entry_set_mtime'''(''struct archive_entry *a'', ''time_t sec'', ''long nanosec''); +
    +''void'' +
    +'''archive_entry_unset_mtime'''(''struct archive_entry *a''); +== DESCRIPTION == +These functions create and manipulate the time fields in an +''archive_entry''. +Supported time fields are atime (access time), birthtime (creation time), +ctime (last time an inode property was changed) and mtime (modification time). + +[[ManPageibarchive3]] +provides a high-resolution interface. +The timestamps are truncated automatically depending on the archive format +(for archiving) or the filesystem capabilities (for restoring). + +All timestamp fields are optional. +The +'''XXX_unset'''() +functions can be used to mark the corresponding field as missing. +The current state can be queried using +'''XXX_is_set'''(). +Unset time fields have a second and nanosecond field of 0. +== SEE ALSO == +[[ManPagerchiventry3]], +[[ManPageibarchive3]] +== HISTORY == +The +'''libarchive''' +library first appeared in +FreeBSD 5.3. +== AUTHORS == +The +'''libarchive''' +library was written by +Tim Kientzle <kientzle@acm.org.> diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveRead3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveRead3.wiki new file mode 100644 index 0000000..34cdb7f --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveRead3.wiki @@ -0,0 +1,208 @@ +ARCHIVE_READ(3) manual page +== NAME == +'''archive_read''' +- functions for reading streaming archives +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +== DESCRIPTION == +These functions provide a complete API for reading streaming archives. +The general process is to first create the +'''struct archive''' +object, set options, initialize the reader, iterate over the archive +headers and associated data, then close the archive and release all +resources. +=== Create archive object=== +See +[[ManPagerchiveeadew3]]. + +To read an archive, you must first obtain an initialized +'''struct archive''' +object from +'''archive_read_new'''(). +=== Enable filters and formats=== +See +[[ManPagerchiveeadilter3]] +and +[[ManPagerchiveeadormat3]]. + +You can then modify this object for the desired operations with the +various +'''archive_read_set_XXX'''() +and +'''archive_read_support_XXX'''() +functions. +In particular, you will need to invoke appropriate +'''archive_read_support_XXX'''() +functions to enable the corresponding compression and format +support. +Note that these latter functions perform two distinct operations: +they cause the corresponding support code to be linked into your +program, and they enable the corresponding auto-detect code. +Unless you have specific constraints, you will generally want +to invoke +'''archive_read_support_filter_all'''() +and +'''archive_read_support_format_all'''() +to enable auto-detect for all formats and compression types +currently supported by the library. +=== Set options=== +See +[[ManPagerchiveeadetptions3]]. +=== Open archive=== +See +[[ManPagerchiveeadpen3]]. + +Once you have prepared the +'''struct archive''' +object, you call +'''archive_read_open'''() +to actually open the archive and prepare it for reading. +There are several variants of this function; +the most basic expects you to provide pointers to several +functions that can provide blocks of bytes from the archive. +There are convenience forms that allow you to +specify a filename, file descriptor, +''FILE *'' +object, or a block of memory from which to read the archive data. +Note that the core library makes no assumptions about the +size of the blocks read; +callback functions are free to read whatever block size is +most appropriate for the medium. +=== Consume archive=== +See +[[ManPagerchiveeadeader3]], +[[ManPagerchiveeadata3]] +and +[[ManPagerchiveeadxtract3]]. + +Each archive entry consists of a header followed by a certain +amount of data. +You can obtain the next header with +'''archive_read_next_header'''(), +which returns a pointer to an +'''struct archive_entry''' +structure with information about the current archive element. +If the entry is a regular file, then the header will be followed +by the file data. +You can use +'''archive_read_data'''() +(which works much like the +[[read(2)|http://www.freebsd.org/cgi/man.cgi?query=read&sektion=2]] +system call) +to read this data from the archive, or +'''archive_read_data_block'''() +which provides a slightly more efficient interface. +You may prefer to use the higher-level +'''archive_read_data_skip'''(), +which reads and discards the data for this entry, +'''archive_read_data_into_fd'''(), +which copies the data to the provided file descriptor, or +'''archive_read_extract'''(), +which recreates the specified entry on disk and copies data +from the archive. +In particular, note that +'''archive_read_extract'''() +uses the +'''struct archive_entry''' +structure that you provide it, which may differ from the +entry just read from the archive. +In particular, many applications will want to override the +pathname, file permissions, or ownership. +=== Release resources=== +See +[[ManPagerchiveeadree3]]. + +Once you have finished reading data from the archive, you +should call +'''archive_read_close'''() +to close the archive, then call +'''archive_read_free'''() +to release all resources, including all memory allocated by the library. +== EXAMPLES == +The following illustrates basic usage of the library. +In this example, +the callback functions are simply wrappers around the standard +[[open(2)|http://www.freebsd.org/cgi/man.cgi?query=open&sektion=2]], +[[read(2)|http://www.freebsd.org/cgi/man.cgi?query=read&sektion=2]], +and +[[close(2)|http://www.freebsd.org/cgi/man.cgi?query=close&sektion=2]] +system calls. +```text +void +list_archive(const char *name) +{ + struct mydata *mydata; + struct archive *a; + struct archive_entry *entry; + mydata = malloc(sizeof(struct mydata)); + a = archive_read_new(); + mydata->name = name; + archive_read_support_filter_all(a); + archive_read_support_format_all(a); + archive_read_open(a, mydata, myopen, myread, myclose); + while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { + printf("%s\en",archive_entry_pathname(entry)); + archive_read_data_skip(a); + } + archive_read_free(a); + free(mydata); +} +la_ssize_t +myread(struct archive *a, void *client_data, const void **buff) +{ + struct mydata *mydata = client_data; + *buff = mydata->buff; + return (read(mydata->fd, mydata->buff, 10240)); +} +int +myopen(struct archive *a, void *client_data) +{ + struct mydata *mydata = client_data; + mydata->fd = open(mydata->name, O_RDONLY); + return (mydata->fd >= 0 ? ARCHIVE_OK : ARCHIVE_FATAL); +} +int +myclose(struct archive *a, void *client_data) +{ + struct mydata *mydata = client_data; + if (mydata->fd > 0) + close(mydata->fd); + return (ARCHIVE_OK); +} +``` +== SEE ALSO == +[[ManPageBsdtar1]], +[[ManPagerchiveeadata3]], +[[ManPagerchiveeadxtract3]], +[[ManPagerchiveeadilter3]], +[[ManPagerchiveeadormat3]], +[[ManPagerchiveeadeader3]], +[[ManPagerchiveeadew3]], +[[ManPagerchiveeadpen3]], +[[ManPagerchiveeadetptions3]], +[[ManPagerchivetil3]], +[[ManPageibarchive3]], +[[ManPageTar5]] +== HISTORY == +The +'''libarchive''' +library first appeared in +FreeBSD 5.3. +== AUTHORS == +The +'''libarchive''' +library was written by +Tim Kientzle <kientzle@acm.org.> +== BUGS == +Many traditional archiver programs treat +empty files as valid empty archives. +For example, many implementations of +[[ManPageBsdtar1]] +allow you to append entries to an empty file. +Of course, it is impossible to determine the format of an empty file +by inspecting the contents, so this library treats empty files as +having a special +"empty" +format. diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadAddPassphrase3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadAddPassphrase3.wiki new file mode 100644 index 0000000..f05a683 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadAddPassphrase3.wiki @@ -0,0 +1,42 @@ +ARCHIVE_READ_ADD_PASSPHRASE(3) manual page +== NAME == +'''archive_read_add_passphrase''', +'''archive_read_set_passphrase_callback''' +- functions for reading encrypted archives +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''int'' +
    +'''archive_read_add_passphrase'''(''struct archive *'', ''const char *passphrase''); +
    +''int'' +
    +'''archive_read_set_passphrase_callback'''(''struct archive *'', ''void *client_data'', ''archive_passphrase_callback *''); +== DESCRIPTION == +
    +
    '''archive_read_add_passphrase'''()
    +Register passphrases for reading an encryption archive. +If +''passphrase'' +is +NULL +or empty, this function will do nothing and +'''ARCHIVE_FAILED''' +will be returned. +Otherwise, +'''ARCHIVE_OK''' +will be returned. +
    '''archive_read_set_passphrase_callback'''()
    +Register a callback function that will be invoked to get a passphrase +for decryption after trying all the passphrases registered by the +'''archive_read_add_passphrase'''() +function failed. +
    +== SEE ALSO == +[[ManPageBsdtar1]], +[[ManPagerchiveead3]], +[[ManPagerchiveeadetptions3]], +[[ManPageibarchive3]] diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadData3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadData3.wiki new file mode 100644 index 0000000..e39bbdc --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadData3.wiki @@ -0,0 +1,101 @@ +ARCHIVE_READ_DATA(3) manual page +== NAME == +'''archive_read_data''', +'''archive_read_data_block''', +'''archive_read_data_skip''', +'''archive_read_data_into_fd''' +- functions for reading streaming archives +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''la_ssize_t'' +
    +'''archive_read_data'''(''struct archive *'', ''void *buff'', ''size_t len''); +
    +''int'' +
    +'''archive_read_data_block'''(''struct archive *'', ''const void **buff'', ''size_t *len'', ''off_t *offset''); +
    +''int'' +
    +'''archive_read_data_skip'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_data_into_fd'''(''struct archive *'', ''int fd''); +== DESCRIPTION == +
    +
    '''archive_read_data'''()
    +Read data associated with the header just read. +Internally, this is a convenience function that calls +'''archive_read_data_block'''() +and fills any gaps with nulls so that callers see a single +continuous stream of data. +
    '''archive_read_data_block'''()
    +Return the next available block of data for this entry. +Unlike +'''archive_read_data'''(), +the +'''archive_read_data_block'''() +function avoids copying data and allows you to correctly handle +sparse files, as supported by some archive formats. +The library guarantees that offsets will increase and that blocks +will not overlap. +Note that the blocks returned from this function can be much larger +than the block size read from disk, due to compression +and internal buffer optimizations. +
    '''archive_read_data_skip'''()
    +A convenience function that repeatedly calls +'''archive_read_data_block'''() +to skip all of the data for this archive entry. +Note that this function is invoked automatically by +'''archive_read_next_header2'''() +if the previous entry was not completely consumed. +
    '''archive_read_data_into_fd'''()
    +A convenience function that repeatedly calls +'''archive_read_data_block'''() +to copy the entire entry to the provided file descriptor. +
    +== RETURN VALUES == +Most functions return zero on success, non-zero on error. +The possible return codes include: +'''ARCHIVE_OK''' +(the operation succeeded), +'''ARCHIVE_WARN''' +(the operation succeeded but a non-critical error was encountered), +'''ARCHIVE_EOF''' +(end-of-archive was encountered), +'''ARCHIVE_RETRY''' +(the operation failed but can be retried), +and +'''ARCHIVE_FATAL''' +(there was a fatal error; the archive should be closed immediately). + +'''archive_read_data'''() +returns a count of bytes actually read or zero at the end of the entry. +On error, a value of +'''ARCHIVE_FATAL''', +'''ARCHIVE_WARN''', +or +'''ARCHIVE_RETRY''' +is returned. +== ERRORS == +Detailed error codes and textual descriptions are available from the +'''archive_errno'''() +and +'''archive_error_string'''() +functions. +== SEE ALSO == +[[ManPageBsdtar1]], +[[ManPagerchiveead3]], +[[ManPagerchiveeadxtract3]], +[[ManPagerchiveeadilter3]], +[[ManPagerchiveeadormat3]], +[[ManPagerchiveeadeader3]], +[[ManPagerchiveeadpen3]], +[[ManPagerchiveeadetptions3]], +[[ManPagerchivetil3]], +[[ManPageibarchive3]], +[[ManPageTar5]] diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadDisk3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadDisk3.wiki new file mode 100644 index 0000000..238274c --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadDisk3.wiki @@ -0,0 +1,321 @@ +ARCHIVE_READ_DISK(3) manual page +== NAME == +'''archive_read_disk_new''', +'''archive_read_disk_set_behavior''', +'''archive_read_disk_set_symlink_logical''', +'''archive_read_disk_set_symlink_physical''', +'''archive_read_disk_set_symlink_hybrid''', +'''archive_read_disk_entry_from_file''', +'''archive_read_disk_gname''', +'''archive_read_disk_uname''', +'''archive_read_disk_set_uname_lookup''', +'''archive_read_disk_set_gname_lookup''', +'''archive_read_disk_set_standard_lookup''' +- functions for reading objects from disk +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''struct archive *'' +
    +'''archive_read_disk_new'''(''void''); +
    +''int'' +
    +'''archive_read_disk_set_behavior'''(''struct archive *'', ''int''); +
    +''int'' +
    +'''archive_read_disk_set_symlink_logical'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_disk_set_symlink_physical'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_disk_set_symlink_hybrid'''(''struct archive *''); +
    +''const char *'' +
    +'''archive_read_disk_gname'''(''struct archive *'', ''gid_t''); +
    +''const char *'' +
    +'''archive_read_disk_uname'''(''struct archive *'', ''uid_t''); +
    +''int'' +
    +'''archive_read_disk_set_gname_lookup'''(''struct archive *'', ''void *'', ''const char *(*lookup)(void *, gid_t)'', ''void (*cleanup)(void *)''); +
    +''int'' +
    +'''archive_read_disk_set_uname_lookup'''(''struct archive *'', ''void *'', ''const char *(*lookup)(void *, uid_t)'', ''void (*cleanup)(void *)''); +
    +''int'' +
    +'''archive_read_disk_set_standard_lookup'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_disk_entry_from_file'''(''struct archive *'', ''struct archive_entry *'', ''int fd'', ''const struct stat *''); +== DESCRIPTION == +These functions provide an API for reading information about +objects on disk. +In particular, they provide an interface for populating +'''struct archive_entry''' +objects. +
    +
    '''archive_read_disk_new'''()
    +Allocates and initializes a +'''struct archive''' +object suitable for reading object information from disk. +
    '''archive_read_disk_set_behavior'''()
    +Configures various behavior options when reading entries from disk. +The flags field consists of a bitwise OR of one or more of the +following values: +
    +
    '''ARCHIVE_READDISK_HONOR_NODUMP'''
    +Skip files and directories with the nodump file attribute (file flag) set. +By default, the nodump file attribute is ignored. +
    '''ARCHIVE_READDISK_MAC_COPYFILE'''
    +Mac OS X specific. +Read metadata (ACLs and extended attributes) with +[[copyfile(3)|http://www.freebsd.org/cgi/man.cgi?query=copyfile&sektion=3]]. +By default, metadata is read using +[[copyfile(3)|http://www.freebsd.org/cgi/man.cgi?query=copyfile&sektion=3]]. +
    '''ARCHIVE_READDISK_NO_ACL'''
    +Do not read Access Control Lists. +By default, ACLs are read from disk. +
    '''ARCHIVE_READDISK_NO_FFLAGS'''
    +Do not read file attributes (file flags). +By default, file attributes are read from disk. +See +[[chattr(1)|http://www.freebsd.org/cgi/man.cgi?query=chattr&sektion=1]] +(Linux) +or +[[chflags(1)|http://www.freebsd.org/cgi/man.cgi?query=chflags&sektion=1]] +(FreeBSD, Mac OS X) +for more information on file attributes. +
    '''ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS'''
    +Do not traverse mount points. +By default, mount points are traversed. +
    '''ARCHIVE_READDISK_NO_XATTR'''
    +Do not read extended file attributes (xattrs). +By default, extended file attributes are read from disk. +See +[[xattr(7)|http://www.freebsd.org/cgi/man.cgi?query=xattr&sektion=7]] +(Linux,) +[[xattr(2)|http://www.freebsd.org/cgi/man.cgi?query=xattr&sektion=2]] +(Mac OS X,) +or +[[getextattr(8)|http://www.freebsd.org/cgi/man.cgi?query=getextattr&sektion=8]] +(FreeBSD) +for more information on extended file attributes. +
    '''ARCHIVE_READDISK_RESTORE_ATIME'''
    +Restore access time of traversed files. +By default, access time of traversed files is not restored. +
    +
    +'''archive_read_disk_set_symlink_logical'''(), +'''archive_read_disk_set_symlink_physical'''(), +'''archive_read_disk_set_symlink_hybrid'''() +
    +This sets the mode used for handling symbolic links. +The +"logical" +mode follows all symbolic links. +The +"physical" +mode does not follow any symbolic links. +The +"hybrid" +mode currently behaves identically to the +"logical" +mode. +
    +'''archive_read_disk_gname'''(), +'''archive_read_disk_uname'''() +
    +Returns a user or group name given a gid or uid value. +By default, these always return a NULL string. +
    +'''archive_read_disk_set_gname_lookup'''(), +'''archive_read_disk_set_uname_lookup'''() +
    +These allow you to override the functions used for +user and group name lookups. +You may also provide a +'''void *''' +pointer to a private data structure and a cleanup function for +that data. +The cleanup function will be invoked when the +'''struct archive''' +object is destroyed or when new lookup functions are registered. +
    '''archive_read_disk_set_standard_lookup'''()
    +This convenience function installs a standard set of user +and group name lookup functions. +These functions use +[[getpwuid(3)|http://www.freebsd.org/cgi/man.cgi?query=getpwuid&sektion=3]] +and +[[getgrgid(3)|http://www.freebsd.org/cgi/man.cgi?query=getgrgid&sektion=3]] +to convert ids to names, defaulting to NULL if the names cannot +be looked up. +These functions also implement a simple memory cache to reduce +the number of calls to +[[getpwuid(3)|http://www.freebsd.org/cgi/man.cgi?query=getpwuid&sektion=3]] +and +[[getgrgid(3)|http://www.freebsd.org/cgi/man.cgi?query=getgrgid&sektion=3]]. +
    '''archive_read_disk_entry_from_file'''()
    +Populates a +'''struct archive_entry''' +object with information about a particular file. +The +'''archive_entry''' +object must have already been created with +[[ManPagerchiventryew3]] +and at least one of the source path or path fields must already be set. +(If both are set, the source path will be used.) + +Information is read from disk using the path name from the +'''struct archive_entry''' +object. +If a file descriptor is provided, some information will be obtained using +that file descriptor, on platforms that support the appropriate +system calls. + +If a pointer to a +'''struct stat''' +is provided, information from that structure will be used instead +of reading from the disk where appropriate. +This can provide performance benefits in scenarios where +'''struct stat''' +information has already been read from the disk as a side effect +of some other operation. +(For example, directory traversal libraries often provide this information.) + +Where necessary, user and group ids are converted to user and group names +using the currently-registered lookup functions above. +This affects the file ownership fields and ACL values in the +'''struct archive_entry''' +object. +
    +More information about the +''struct'' archive +object and the overall design of the library can be found in the +[[ManPageibarchive3]] +overview. +== EXAMPLES == +The following illustrates basic usage of the library by +showing how to use it to copy an item on disk into an archive. +```text +void +file_to_archive(struct archive *a, const char *name) +{ + char buff[8192]; + size_t bytes_read; + struct archive *ard; + struct archive_entry *entry; + int fd; + ard = archive_read_disk_new(); + archive_read_disk_set_standard_lookup(ard); + entry = archive_entry_new(); + fd = open(name, O_RDONLY); + if (fd < 0) + return; + archive_entry_copy_pathname(entry, name); + archive_read_disk_entry_from_file(ard, entry, fd, NULL); + archive_write_header(a, entry); + while ((bytes_read = read(fd, buff, sizeof(buff))) > 0) + archive_write_data(a, buff, bytes_read); + archive_write_finish_entry(a); + archive_read_free(ard); + archive_entry_free(entry); +} +``` +== RETURN VALUES == +Most functions return +'''ARCHIVE_OK''' +(zero) on success, or one of several negative +error codes for errors. +Specific error codes include: +'''ARCHIVE_RETRY''' +for operations that might succeed if retried, +'''ARCHIVE_WARN''' +for unusual conditions that do not prevent further operations, and +'''ARCHIVE_FATAL''' +for serious errors that make remaining operations impossible. + +'''archive_read_disk_new'''() +returns a pointer to a newly-allocated +'''struct archive''' +object or NULL if the allocation failed for any reason. + +'''archive_read_disk_gname'''() +and +'''archive_read_disk_uname'''() +return +'''const char *''' +pointers to the textual name or NULL if the lookup failed for any reason. +The returned pointer points to internal storage that +may be reused on the next call to either of these functions; +callers should copy the string if they need to continue accessing it. +== ERRORS == +Detailed error codes and textual descriptions are available from the +'''archive_errno'''() +and +'''archive_error_string'''() +functions. +== SEE ALSO == +[[ManPageBsdtar1]], +[[ManPagerchiveead3]], +[[ManPagerchivetil3]], +[[ManPagerchiverite3]], +[[ManPagerchiveriteisk3]], +[[ManPageibarchive3]] +== HISTORY == +The +'''libarchive''' +library first appeared in +FreeBSD 5.3. +The +'''archive_read_disk''' +interface was added to +'''libarchive''' 2.6 +and first appeared in +FreeBSD 8.0. +== AUTHORS == +The +'''libarchive''' +library was written by +Tim Kientzle <kientzle@FreeBSD.org.> +== BUGS == +The +"standard" +user name and group name lookup functions are not the defaults because +[[getgrgid(3)|http://www.freebsd.org/cgi/man.cgi?query=getgrgid&sektion=3]] +and +[[getpwuid(3)|http://www.freebsd.org/cgi/man.cgi?query=getpwuid&sektion=3]] +are sometimes too large for particular applications. +The current design allows the application author to use a more +compact implementation when appropriate. + +The full list of metadata read from disk by +'''archive_read_disk_entry_from_file'''() +is necessarily system-dependent. + +The +'''archive_read_disk_entry_from_file'''() +function reads as much information as it can from disk. +Some method should be provided to limit this so that clients who +do not need ACLs, for instance, can avoid the extra work needed +to look up such information. + +This API should provide a set of methods for walking a directory tree. +That would make it a direct parallel of the +[[ManPagerchiveead3]] +API. +When such methods are implemented, the +"hybrid" +symbolic link mode will make sense. diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadExtract3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadExtract3.wiki new file mode 100644 index 0000000..9a5b82b --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadExtract3.wiki @@ -0,0 +1,102 @@ +ARCHIVE_READ_EXTRACT(3) manual page +== NAME == +'''archive_read_extract''', +'''archive_read_extract2''', +'''archive_read_extract_set_progress_callback''' +- functions for reading streaming archives +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''int'' +
    +'''archive_read_extract'''(''struct archive *'', ''struct archive_entry *'', ''int flags''); +
    +''int'' +
    +'''archive_read_extract2'''(''struct archive *src'', ''struct archive_entry *'', ''struct archive *dest''); +
    +''void'' +
    +'''archive_read_extract_set_progress_callback'''(''struct archive *'', ''void (*func)(void *)'', ''void *user_data''); +== DESCRIPTION == +
    +
    '''archive_read_extract'''(), '''archive_read_extract_set_skip_file'''()
    +A convenience function that wraps the corresponding +[[ManPagerchiveriteisk3]] +interfaces. +The first call to +'''archive_read_extract'''() +creates a restore object using +[[ManPagerchiveriteiskew3]] +and +[[ManPagerchiveriteiskettandardookup3]], +then transparently invokes +[[ManPagerchiveriteisketptions3]], +[[ManPagerchiveriteeader3]], +[[ManPagerchiveriteata3]], +and +[[ManPagerchiveriteinishntry3]] +to create the entry on disk and copy data into it. +The +''flags'' +argument is passed unmodified to +[[ManPagerchiveriteisketptions3]]. +
    '''archive_read_extract2'''()
    +This is another version of +'''archive_read_extract'''() +that allows you to provide your own restore object. +In particular, this allows you to override the standard lookup functions +using +[[ManPagerchiveriteisketroupookup3]], +and +[[ManPagerchiveriteisketserookup3]]. +Note that +'''archive_read_extract2'''() +does not accept a +''flags'' +argument; you should use +'''archive_write_disk_set_options'''() +to set the restore options yourself. +
    '''archive_read_extract_set_progress_callback'''()
    +Sets a pointer to a user-defined callback that can be used +for updating progress displays during extraction. +The progress function will be invoked during the extraction of large +regular files. +The progress function will be invoked with the pointer provided to this call. +Generally, the data pointed to should include a reference to the archive +object and the archive_entry object so that various statistics +can be retrieved for the progress display. +
    +== RETURN VALUES == +Most functions return zero on success, non-zero on error. +The possible return codes include: +'''ARCHIVE_OK''' +(the operation succeeded), +'''ARCHIVE_WARN''' +(the operation succeeded but a non-critical error was encountered), +'''ARCHIVE_EOF''' +(end-of-archive was encountered), +'''ARCHIVE_RETRY''' +(the operation failed but can be retried), +and +'''ARCHIVE_FATAL''' +(there was a fatal error; the archive should be closed immediately). +== ERRORS == +Detailed error codes and textual descriptions are available from the +'''archive_errno'''() +and +'''archive_error_string'''() +functions. +== SEE ALSO == +[[ManPageBsdtar1]], +[[ManPagerchiveead3]], +[[ManPagerchiveeadata3]], +[[ManPagerchiveeadilter3]], +[[ManPagerchiveeadormat3]], +[[ManPagerchiveeadpen3]], +[[ManPagerchiveeadetptions3]], +[[ManPagerchivetil3]], +[[ManPageibarchive3]], +[[ManPageTar5]] diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadFilter3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadFilter3.wiki new file mode 100644 index 0000000..85b0cd3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadFilter3.wiki @@ -0,0 +1,143 @@ +ARCHIVE_READ_FILTER(3) manual page +== NAME == +'''archive_read_support_filter_all''', +'''archive_read_support_filter_bzip2''', +'''archive_read_support_filter_compress''', +'''archive_read_support_filter_gzip''', +'''archive_read_support_filter_lz4''', +'''archive_read_support_filter_lzma''', +'''archive_read_support_filter_none''', +'''archive_read_support_filter_rpm''', +'''archive_read_support_filter_uu''', +'''archive_read_support_filter_xz''', +'''archive_read_support_filter_zstd''', +'''archive_read_support_filter_program''', +'''archive_read_support_filter_program_signature''' +- functions for reading streaming archives +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''int'' +
    +'''archive_read_support_filter_all'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_filter_bzip2'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_filter_compress'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_filter_grzip'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_filter_gzip'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_filter_lrzip'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_filter_lz4'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_filter_lzma'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_filter_lzop'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_filter_none'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_filter_rpm'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_filter_uu'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_filter_xz'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_filter_zstd'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_filter_program'''(''struct archive *'', ''const char *cmd''); +
    +''int'' +
    +'''archive_read_support_filter_program_signature'''(''struct archive *'', ''const char *cmd'', ''const void *signature'', ''size_t signature_length''); +== DESCRIPTION == +
    +
    +'''archive_read_support_filter_bzip2'''(), +'''archive_read_support_filter_compress'''(), +'''archive_read_support_filter_grzip'''(), +'''archive_read_support_filter_gzip'''(), +'''archive_read_support_filter_lrzip'''(), +'''archive_read_support_filter_lz4'''(), +'''archive_read_support_filter_lzma'''(), +'''archive_read_support_filter_lzop'''(), +'''archive_read_support_filter_none'''(), +'''archive_read_support_filter_rpm'''(), +'''archive_read_support_filter_uu'''(), +'''archive_read_support_filter_xz'''(), +'''archive_read_support_filter_zstd'''(), +
    +Enables auto-detection code and decompression support for the +specified compression. +These functions may fall back on external programs if an appropriate +library was not available at build time. +Decompression using an external program is usually slower than +decompression through built-in libraries. +Note that +"none" +is always enabled by default. +
    '''archive_read_support_filter_all'''()
    +Enables all available decompression filters. +
    '''archive_read_support_filter_program'''()
    +Data is fed through the specified external program before being dearchived. +Note that this disables automatic detection of the compression format, +so it makes no sense to specify this in conjunction with any other +decompression option. +
    '''archive_read_support_filter_program_signature'''()
    +This feeds data through the specified external program +but only if the initial bytes of the data match the specified +signature value. +
    +== RETURN VALUES == +These functions return +'''ARCHIVE_OK''' +if the compression is fully supported, +'''ARCHIVE_WARN''' +if the compression is supported only through an external program. + +'''archive_read_support_filter_none'''() +always succeeds. +== ERRORS == +Detailed error codes and textual descriptions are available from the +'''archive_errno'''() +and +'''archive_error_string'''() +functions. +== SEE ALSO == +[[ManPagerchiveead3]], +[[ManPagerchiveeadata3]], +[[ManPagerchiveeadormat3]], +[[ManPagerchiveeadormat3]], +[[ManPageibarchive3]] diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadFormat3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadFormat3.wiki new file mode 100644 index 0000000..13d17ad --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadFormat3.wiki @@ -0,0 +1,174 @@ +ARCHIVE_READ_FORMAT(3) manual page +== NAME == +'''archive_read_support_format_7zip''', +'''archive_read_support_format_all''', +'''archive_read_support_format_ar''', +'''archive_read_support_format_by_code''', +'''archive_read_support_format_cab''', +'''archive_read_support_format_cpio''', +'''archive_read_support_format_empty''', +'''archive_read_support_format_iso9660''', +'''archive_read_support_format_lha''', +'''archive_read_support_format_mtree''', +'''archive_read_support_format_rar''', +'''archive_read_support_format_raw''', +'''archive_read_support_format_tar''', +'''archive_read_support_format_xar''', +'''archive_read_support_format_zip''' +- functions for reading streaming archives +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''int'' +
    +'''archive_read_support_format_7zip'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_format_all'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_format_ar'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_format_by_code'''(''struct archive *'', ''int''); +
    +''int'' +
    +'''archive_read_support_format_cab'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_format_cpio'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_format_empty'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_format_iso9660'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_format_lha'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_format_mtree'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_format_rar'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_format_raw'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_format_tar'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_format_xar'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_support_format_zip'''(''struct archive *''); +== DESCRIPTION == +
    +
    +'''archive_read_support_format_7zip'''(), +'''archive_read_support_format_ar'''(), +'''archive_read_support_format_cab'''(), +'''archive_read_support_format_cpio'''(), +'''archive_read_support_format_iso9660'''(), +'''archive_read_support_format_lha'''(), +'''archive_read_support_format_mtree'''(), +'''archive_read_support_format_rar'''(), +'''archive_read_support_format_raw'''(), +'''archive_read_support_format_tar'''(), +'''archive_read_support_format_xar'''(), +'''archive_read_support_format_zip'''() +
    +Enables support---including auto-detection code---for the +specified archive format. +For example, +'''archive_read_support_format_tar'''() +enables support for a variety of standard tar formats, old-style tar, +ustar, pax interchange format, and many common variants. +
    '''archive_read_support_format_all'''()
    +Enables support for all available formats except the +"raw" +format (see below). +
    '''archive_read_support_format_by_code'''()
    +Enables a single format specified by the format code. +This can be useful when reading a single archive twice; +use +'''archive_format'''() +after reading the first time and pass the resulting code +to this function to selectively enable only the necessary +format support. +Note: In statically-linked executables, this will cause +your program to include support for every format. +If executable size is a concern, you may wish to avoid +using this function. +
    '''archive_read_support_format_empty'''()
    +Enables support for treating empty files as empty archives. +Because empty files are valid for several different formats, +it is not possible to accurately determine a format for +an empty file based purely on contents. +So empty files are treated by libarchive as a distinct +format. +
    '''archive_read_support_format_raw'''()
    +The +"raw" +format handler allows libarchive to be used to read arbitrary data. +It treats any data stream as an archive with a single entry. +The pathname of this entry is +"data ;" +all other entry fields are unset. +This is not enabled by +'''archive_read_support_format_all'''() +in order to avoid erroneous handling of damaged archives. +
    +== RETURN VALUES == +These functions return +'''ARCHIVE_OK''' +on success, or +'''ARCHIVE_FATAL'''. +== ERRORS == +Detailed error codes and textual descriptions are available from the +'''archive_errno'''() +and +'''archive_error_string'''() +functions. +== SEE ALSO == +[[ManPageBsdtar1]], +[[ManPagerchiveeadata3]], +[[ManPagerchiveeadilter3]], +[[ManPagerchiveeadetptions3]], +[[ManPagerchivetil3]], +[[ManPageibarchive3]], +[[ManPageTar5]] +== BUGS == +Many traditional archiver programs treat +empty files as valid empty archives. +For example, many implementations of +[[ManPageBsdtar1]] +allow you to append entries to an empty file. +Of course, it is impossible to determine the format of an empty file +by inspecting the contents, so this library treats empty files as +having a special +"empty" +format. + +Using the +"raw" +handler together with any other handler will often work +but can produce surprising results. diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadFree3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadFree3.wiki new file mode 100644 index 0000000..d85030d --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadFree3.wiki @@ -0,0 +1,68 @@ +ARCHIVE_READ_FREE(3) manual page +== NAME == +'''archive_read_close''', +'''archive_read_finish''', +'''archive_read_free''' +- functions for reading streaming archives +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''int'' +
    +'''archive_read_close'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_finish'''(''struct archive *''); +
    +''int'' +
    +'''archive_read_free'''(''struct archive *''); +== DESCRIPTION == +
    +
    '''archive_read_close'''()
    +Complete the archive and invoke the close callback. +
    '''archive_read_finish'''()
    +This is a deprecated synonym for +'''archive_read_free'''(). +The new name was introduced with libarchive 3.0. +Applications that need to compile with either libarchive 2 +or libarchive 3 should continue to use the +'''archive_read_finish'''() +name. +Both names will be supported until libarchive 4.0 is +released, which is not expected to occur earlier +than 2013. +
    '''archive_read_free'''()
    +Invokes +'''archive_read_close'''() +if it was not invoked manually, then release all resources. +Note: In libarchive 1.x, this function was declared to return +''void ,'' +which made it impossible to detect certain errors when +'''archive_read_close'''() +was invoked implicitly from this function. +The declaration is corrected beginning with libarchive 2.0. +
    +== RETURN VALUES == +These functions return +'''ARCHIVE_OK''' +on success, or +'''ARCHIVE_FATAL'''. +== ERRORS == +Detailed error codes and textual descriptions are available from the +'''archive_errno'''() +and +'''archive_error_string'''() +functions. +== SEE ALSO == +[[ManPagerchiveeadata3]], +[[ManPagerchiveeadilter3]], +[[ManPagerchiveeadormat3]], +[[ManPagerchiveeadew3]], +[[ManPagerchiveeadpen3]], +[[ManPagerchiveeadetptions3]], +[[ManPagerchivetil3]], +[[ManPageibarchive3]] diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadHeader3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadHeader3.wiki new file mode 100644 index 0000000..f2d39a8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadHeader3.wiki @@ -0,0 +1,63 @@ +ARCHIVE_READ_HEADER(3) manual page +== NAME == +'''archive_read_next_header''', +'''archive_read_next_header2''' +- functions for reading streaming archives +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''int'' +
    +'''archive_read_next_header'''(''struct archive *'', ''struct archive_entry **''); +
    +''int'' +
    +'''archive_read_next_header2'''(''struct archive *'', ''struct archive_entry *''); +== DESCRIPTION == +
    +
    '''archive_read_next_header'''()
    +Read the header for the next entry and return a pointer to +a +'''struct archive_entry .''' +This is a convenience wrapper around +'''archive_read_next_header2'''() +that reuses an internal +'''struct archive_entry''' +object for each request. +
    '''archive_read_next_header2'''()
    +Read the header for the next entry and populate the provided +'''struct archive_entry .''' +
    +== RETURN VALUES == +These functions return +'''ARCHIVE_OK''' +(the operation succeeded), +'''ARCHIVE_WARN''' +(the operation succeeded but a non-critical error was encountered), +'''ARCHIVE_EOF''' +(end-of-archive was encountered), +'''ARCHIVE_RETRY''' +(the operation failed but can be retried), +and +'''ARCHIVE_FATAL''' +(there was a fatal error; the archive should be closed immediately). +== ERRORS == +Detailed error codes and textual descriptions are available from the +'''archive_errno'''() +and +'''archive_error_string'''() +functions. +== SEE ALSO == +[[ManPageBsdtar1]], +[[ManPagerchiveead3]], +[[ManPagerchiveeadata3]], +[[ManPagerchiveeadxtract3]], +[[ManPagerchiveeadilter3]], +[[ManPagerchiveeadormat3]], +[[ManPagerchiveeadpen3]], +[[ManPagerchiveeadetptions3]], +[[ManPagerchivetil3]], +[[ManPageibarchive3]], +[[ManPageTar5]] diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadNew3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadNew3.wiki new file mode 100644 index 0000000..67c4f1f --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadNew3.wiki @@ -0,0 +1,32 @@ +ARCHIVE_READ_NEW(3) manual page +== NAME == +'''archive_read_new''' +- functions for reading streaming archives +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''struct archive *'' +
    +'''archive_read_new'''(''void''); +== DESCRIPTION == +Allocates and initializes a +'''struct archive''' +object suitable for reading from an archive. +NULL +is returned on error. + +A complete description of the +'''struct archive''' +object can be found in the overview manual page for +[[ManPageibarchive3]]. +== SEE ALSO == +[[ManPageBsdtar1]], +[[ManPagerchiveeadata3]], +[[ManPagerchiveeadilter3]], +[[ManPagerchiveeadormat3]], +[[ManPagerchiveeadetptions3]], +[[ManPagerchivetil3]], +[[ManPageibarchive3]], +[[ManPageTar5]] diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadOpen3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadOpen3.wiki new file mode 100644 index 0000000..afaca2b --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadOpen3.wiki @@ -0,0 +1,190 @@ +ARCHIVE_READ_OPEN(3) manual page +== NAME == +'''archive_read_open''', +'''archive_read_open2''', +'''archive_read_open_fd''', +'''archive_read_open_FILE''', +'''archive_read_open_filename''', +'''archive_read_open_memory''' +- functions for reading streaming archives +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''int'' +
    +'''archive_read_open'''(''struct archive *'', ''void *client_data'', ''archive_open_callback *'', ''archive_read_callback *'', ''archive_close_callback *''); +
    +''int'' +
    +'''archive_read_open2'''(''struct archive *'', ''void *client_data'', ''archive_open_callback *'', ''archive_read_callback *'', ''archive_skip_callback *'', ''archive_close_callback *''); +
    +''int'' +
    +'''archive_read_open_FILE'''(''struct archive *'', ''FILE *file''); +
    +''int'' +
    +'''archive_read_open_fd'''(''struct archive *'', ''int fd'', ''size_t block_size''); +
    +''int'' +
    +'''archive_read_open_filename'''(''struct archive *'', ''const char *filename'', ''size_t block_size''); +
    +''int'' +
    +'''archive_read_open_memory'''(''struct archive *'', ''const void *buff'', ''size_t size''); +== DESCRIPTION == +
    +
    '''archive_read_open'''()
    +The same as +'''archive_read_open2'''(), +except that the skip callback is assumed to be +NULL. +
    '''archive_read_open2'''()
    +Freeze the settings, open the archive, and prepare for reading entries. +This is the most generic version of this call, which accepts +four callback functions. +Most clients will want to use +'''archive_read_open_filename'''(), +'''archive_read_open_FILE'''(), +'''archive_read_open_fd'''(), +or +'''archive_read_open_memory'''() +instead. +The library invokes the client-provided functions to obtain +raw bytes from the archive. +
    '''archive_read_open_FILE'''()
    +Like +'''archive_read_open'''(), +except that it accepts a +''FILE *'' +pointer. +This function should not be used with tape drives or other devices +that require strict I/O blocking. +
    '''archive_read_open_fd'''()
    +Like +'''archive_read_open'''(), +except that it accepts a file descriptor and block size rather than +a set of function pointers. +Note that the file descriptor will not be automatically closed at +end-of-archive. +This function is safe for use with tape drives or other blocked devices. +
    '''archive_read_open_file'''()
    +This is a deprecated synonym for +'''archive_read_open_filename'''(). +
    '''archive_read_open_filename'''()
    +Like +'''archive_read_open'''(), +except that it accepts a simple filename and a block size. +A NULL filename represents standard input. +This function is safe for use with tape drives or other blocked devices. +
    '''archive_read_open_memory'''()
    +Like +'''archive_read_open'''(), +except that it accepts a pointer and size of a block of +memory containing the archive data. +
    + +A complete description of the +'''struct archive''' +and +'''struct archive_entry''' +objects can be found in the overview manual page for +[[ManPageibarchive3]]. +== CLIENT CALLBACKS == +The callback functions must match the following prototypes: +
      +
    • +''typedef la_ssize_t'' +'''archive_read_callback'''(''struct archive *'', ''void *client_data'', ''const void **buffer'') +
    • +''typedef la_int64_t'' +'''archive_skip_callback'''(''struct archive *'', ''void *client_data'', ''off_t request'') +
    • +''typedef int'' +'''archive_open_callback'''(''struct archive *'', ''void *client_data'') +
    • +''typedef int'' +'''archive_close_callback'''(''struct archive *'', ''void *client_data'') +
    + +The open callback is invoked by +'''archive_open'''(). +It should return +'''ARCHIVE_OK''' +if the underlying file or data source is successfully +opened. +If the open fails, it should call +'''archive_set_error'''() +to register an error code and message and return +'''ARCHIVE_FATAL'''. + +The read callback is invoked whenever the library +requires raw bytes from the archive. +The read callback should read data into a buffer, +set the +```text +const void **buffer +``` +argument to point to the available data, and +return a count of the number of bytes available. +The library will invoke the read callback again +only after it has consumed this data. +The library imposes no constraints on the size +of the data blocks returned. +On end-of-file, the read callback should +return zero. +On error, the read callback should invoke +'''archive_set_error'''() +to register an error code and message and +return -1. + +The skip callback is invoked when the +library wants to ignore a block of data. +The return value is the number of bytes actually +skipped, which may differ from the request. +If the callback cannot skip data, it should return +zero. +If the skip callback is not provided (the +function pointer is +NULL ), +the library will invoke the read function +instead and simply discard the result. +A skip callback can provide significant +performance gains when reading uncompressed +archives from slow disk drives or other media +that can skip quickly. + +The close callback is invoked by archive_close when +the archive processing is complete. +The callback should return +'''ARCHIVE_OK''' +on success. +On failure, the callback should invoke +'''archive_set_error'''() +to register an error code and message and +return +'''ARCHIVE_FATAL'''. +== RETURN VALUES == +These functions return +'''ARCHIVE_OK''' +on success, or +'''ARCHIVE_FATAL'''. +== ERRORS == +Detailed error codes and textual descriptions are available from the +'''archive_errno'''() +and +'''archive_error_string'''() +functions. +== SEE ALSO == +[[ManPageBsdtar1]], +[[ManPagerchiveead3]], +[[ManPagerchiveeadata3]], +[[ManPagerchiveeadilter3]], +[[ManPagerchiveeadormat3]], +[[ManPagerchiveeadetptions3]], +[[ManPagerchivetil3]], +[[ManPageibarchive3]], +[[ManPageTar5]] diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadSetOptions3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadSetOptions3.wiki new file mode 100644 index 0000000..bb739bc --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveReadSetOptions3.wiki @@ -0,0 +1,218 @@ +ARCHIVE_READ_OPTIONS(3) manual page +== NAME == +'''archive_read_set_filter_option''', +'''archive_read_set_format_option''', +'''archive_read_set_option''', +'''archive_read_set_options''' +- functions controlling options for reading archives +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +
    +''int'' +
    +'''archive_read_set_filter_option'''(''struct archive *'', ''const char *module'', ''const char *option'', ''const char *value''); +
    +''int'' +
    +'''archive_read_set_format_option'''(''struct archive *'', ''const char *module'', ''const char *option'', ''const char *value''); +
    +''int'' +
    +'''archive_read_set_option'''(''struct archive *'', ''const char *module'', ''const char *option'', ''const char *value''); +
    +''int'' +
    +'''archive_read_set_options'''(''struct archive *'', ''const char *options''); +== DESCRIPTION == +These functions provide a way for libarchive clients to configure +specific read modules. +
    +
    +'''archive_read_set_filter_option'''(), +'''archive_read_set_format_option'''() +
    +Specifies an option that will be passed to currently-registered +filters (including decompression filters) or format readers. + +If +''option'' +and +''value'' +are both +NULL, +these functions will do nothing and +'''ARCHIVE_OK''' +will be returned. +If +''option'' +is +NULL +but +''value'' +is not, these functions will do nothing and +'''ARCHIVE_FAILED''' +will be returned. + +If +''module'' +is not +NULL, +''option'' +and +''value'' +will be provided to the filter or reader named +''module''. +The return value will be that of the module. +If there is no such module, +'''ARCHIVE_FAILED''' +will be returned. + +If +''module'' +is +NULL, +''option'' +and +''value'' +will be provided to every registered module. +If any module returns +'''ARCHIVE_FATAL''', +this value will be returned immediately. +Otherwise, +'''ARCHIVE_OK''' +will be returned if any module accepts the option, and +'''ARCHIVE_FAILED''' +in all other cases. +
    +'''archive_read_set_option'''() +
    +Calls +'''archive_read_set_format_option'''(), +then +'''archive_read_set_filter_option'''(). +If either function returns +'''ARCHIVE_FATAL''', +'''ARCHIVE_FATAL''' +will be returned +immediately. +Otherwise, greater of the two values will be returned. +
    +'''archive_read_set_options'''() +
    +''options'' +is a comma-separated list of options. +If +''options'' +is +NULL +or empty, +'''ARCHIVE_OK''' +will be returned immediately. + +Calls +'''archive_read_set_option'''() +with each option in turn. +If any +'''archive_read_set_option'''() +call returns +'''ARCHIVE_FATAL''', +'''ARCHIVE_FATAL''' +will be returned immediately. + +Individual options have one of the following forms: +
    +
    ''option=value''
    +The option/value pair will be provided to every module. +Modules that do not accept an option with this name will ignore it. +
    ''option''
    +The option will be provided to every module with a value of +"1". +
    ''!option''
    +The option will be provided to every module with a NULL value. +
    ''module:option=value'', ''module:option'', ''module:!option''
    +As above, but the corresponding option and value will be provided +only to modules whose name matches +''module''. +
    +
    +== OPTIONS == +
    +
    Format cab
    +
    +
    '''hdrcharset'''
    +The value is used as a character set name that will be +used when translating file names. +
    +
    Format cpio
    +
    +
    '''hdrcharset'''
    +The value is used as a character set name that will be +used when translating file names. +
    +
    Format iso9660
    +
    +
    '''joliet'''
    +Support Joliet extensions. +Defaults to enabled, use +'''!joliet''' +to disable. +
    '''rockridge'''
    +Support RockRidge extensions. +Defaults to enabled, use +'''!rockridge''' +to disable. +
    +
    Format lha
    +
    +
    '''hdrcharset'''
    +The value is used as a character set name that will be +used when translating file names. +
    +
    Format mtree
    +
    +
    '''checkfs'''
    +Allow reading information missing from the mtree from the file system. +Disabled by default. +
    +
    Format rar
    +
    +
    '''hdrcharset'''
    +The value is used as a character set name that will be +used when translating file names. +
    +
    Format tar
    +
    +
    '''compat-2x'''
    +Libarchive 2.x incorrectly encoded Unicode filenames on +some platforms. +This option mimics the libarchive 2.x filename handling +so that such archives can be read correctly. +
    '''hdrcharset'''
    +The value is used as a character set name that will be +used when translating file names. +
    '''mac-ext'''
    +Support Mac OS metadata extension that records data in special +files beginning with a period and underscore. +Defaults to enabled on Mac OS, disabled on other platforms. +Use +'''!mac-ext''' +to disable. +
    '''read_concatenated_archives'''
    +Ignore zeroed blocks in the archive, which occurs when multiple tar archives +have been concatenated together. +Without this option, only the contents of +the first concatenated archive would be read. +
    +
    +== ERRORS == +Detailed error codes and textual descriptions are available from the +'''archive_errno'''() +and +'''archive_error_string'''() +functions. +== SEE ALSO == +[[ManPageBsdtar1]], +[[ManPagerchiveead3]], +[[ManPagerchiveriteetptions3]], +[[ManPageibarchive3]] diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveUtil3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveUtil3.wiki new file mode 100644 index 0000000..8869fbb --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveUtil3.wiki @@ -0,0 +1,218 @@ +ARCHIVE_UTIL(3) manual page +== NAME == +'''archive_clear_error''', +'''archive_compression''', +'''archive_compression_name''', +'''archive_copy_error''', +'''archive_errno''', +'''archive_error_string''', +'''archive_file_count''', +'''archive_filter_code''', +'''archive_filter_count''', +'''archive_filter_name''', +'''archive_format''', +'''archive_format_name''', +'''archive_position''', +'''archive_set_error''' +- libarchive utility functions +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''void'' +
    +'''archive_clear_error'''(''struct archive *''); +
    +''int'' +
    +'''archive_compression'''(''struct archive *''); +
    +''const char *'' +
    +'''archive_compression_name'''(''struct archive *''); +
    +''void'' +
    +'''archive_copy_error'''(''struct archive *'', ''struct archive *''); +
    +''int'' +
    +'''archive_errno'''(''struct archive *''); +
    +''const char *'' +
    +'''archive_error_string'''(''struct archive *''); +
    +''int'' +
    +'''archive_file_count'''(''struct archive *''); +
    +''int'' +
    +'''archive_filter_code'''(''struct archive *'', ''int''); +
    +''int'' +
    +'''archive_filter_count'''(''struct archive *'', ''int''); +
    +''const char *'' +
    +'''archive_filter_name'''(''struct archive *'', ''int''); +
    +''int'' +
    +'''archive_format'''(''struct archive *''); +
    +''const char *'' +
    +'''archive_format_name'''(''struct archive *''); +
    +''int64_t'' +
    +'''archive_position'''(''struct archive *'', ''int''); +
    +''void'' +
    +'''archive_set_error'''(''struct archive *'', ''int error_code'', ''const char *fmt'', ''...''); +== DESCRIPTION == +These functions provide access to various information about the +'''struct archive''' +object used in the +[[ManPageibarchive3]] +library. +
    +
    '''archive_clear_error'''()
    +Clears any error information left over from a previous call. +Not generally used in client code. +
    '''archive_compression'''()
    +Synonym for +'''archive_filter_code'''(''a'', ''0''). +
    '''archive_compression_name'''()
    +Synonym for +'''archive_filter_name'''(''a'', ''0''). +
    '''archive_copy_error'''()
    +Copies error information from one archive to another. +
    '''archive_errno'''()
    +Returns a numeric error code (see +[[errno(2)|http://www.freebsd.org/cgi/man.cgi?query=errno&sektion=2]]) +indicating the reason for the most recent error return. +Note that this can not be reliably used to detect whether an +error has occurred. +It should be used only after another libarchive function +has returned an error status. +
    '''archive_error_string'''()
    +Returns a textual error message suitable for display. +The error message here is usually more specific than that +obtained from passing the result of +'''archive_errno'''() +to +[[strerror(3)|http://www.freebsd.org/cgi/man.cgi?query=strerror&sektion=3]]. +
    '''archive_file_count'''()
    +Returns a count of the number of files processed by this archive object. +The count is incremented by calls to +[[ManPagerchiveriteeader3]] +or +[[ManPagerchiveeadexteader3]]. +
    '''archive_filter_code'''()
    +Returns a numeric code identifying the indicated filter. +See +'''archive_filter_count'''() +for details of the numbering. +
    '''archive_filter_count'''()
    +Returns the number of filters in the current pipeline. +For read archive handles, these filters are added automatically +by the automatic format detection. +For write archive handles, these filters are added by calls to the various +'''archive_write_add_filter_XXX'''() +functions. +Filters in the resulting pipeline are numbered so that filter 0 +is the filter closest to the format handler. +As a convenience, functions that expect a filter number will +accept -1 as a synonym for the highest-numbered filter. + +For example, when reading a uuencoded gzipped tar archive, there +are three filters: +filter 0 is the gunzip filter, +filter 1 is the uudecode filter, +and filter 2 is the pseudo-filter that wraps the archive read functions. +In this case, requesting +'''archive_position'''(''a'', ''-1'') +would be a synonym for +'''archive_position'''(''a'', ''2'') +which would return the number of bytes currently read from the archive, while +'''archive_position'''(''a'', ''1'') +would return the number of bytes after uudecoding, and +'''archive_position'''(''a'', ''0'') +would return the number of bytes after decompression. +
    '''archive_filter_name'''()
    +Returns a textual name identifying the indicated filter. +See +'''archive_filter_count'''() +for details of the numbering. +
    '''archive_format'''()
    +Returns a numeric code indicating the format of the current +archive entry. +This value is set by a successful call to +'''archive_read_next_header'''(). +Note that it is common for this value to change from +entry to entry. +For example, a tar archive might have several entries that +utilize GNU tar extensions and several entries that do not. +These entries will have different format codes. +
    '''archive_format_name'''()
    +A textual description of the format of the current entry. +
    '''archive_position'''()
    +Returns the number of bytes read from or written to the indicated filter. +In particular, +'''archive_position'''(''a'', ''0'') +returns the number of bytes read or written by the format handler, while +'''archive_position'''(''a'', ''-1'') +returns the number of bytes read or written to the archive. +See +'''archive_filter_count'''() +for details of the numbering here. +
    '''archive_set_error'''()
    +Sets the numeric error code and error description that will be returned +by +'''archive_errno'''() +and +'''archive_error_string'''(). +This function should be used within I/O callbacks to set system-specific +error codes and error descriptions. +This function accepts a printf-like format string and arguments. +However, you should be careful to use only the following printf +format specifiers: +"%c", +"%d", +"%jd", +"%jo", +"%ju", +"%jx", +"%ld", +"%lo", +"%lu", +"%lx", +"%o", +"%u", +"%s", +"%x", +"%%". +Field-width specifiers and other printf features are +not uniformly supported and should not be used. +
    +== SEE ALSO == +[[ManPagerchiveead3]], +[[ManPagerchiverite3]], +[[ManPageibarchive3]], +[[printf(3)|http://www.freebsd.org/cgi/man.cgi?query=printf&sektion=3]] +== HISTORY == +The +'''libarchive''' +library first appeared in +FreeBSD 5.3. +== AUTHORS == +The +'''libarchive''' +library was written by +Tim Kientzle <kientzle@acm.org.> diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWrite3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWrite3.wiki new file mode 100644 index 0000000..708ec27 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWrite3.wiki @@ -0,0 +1,222 @@ +ARCHIVE_WRITE(3) manual page +== NAME == +'''archive_write''' +- functions for creating archives +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +== DESCRIPTION == +These functions provide a complete API for creating streaming +archive files. +The general process is to first create the +'''struct archive''' +object, set any desired options, initialize the archive, append entries, then +close the archive and release all resources. +=== Create archive object=== +See +[[ManPagerchiveriteew3]]. + +To write an archive, you must first obtain an initialized +'''struct archive''' +object from +'''archive_write_new'''(). +=== Enable filters and formats, configure block size and padding=== +See +[[ManPagerchiveriteilter3]], +[[ManPagerchiveriteormat3]] +and +[[ManPagerchiveritelocksize3]]. + +You can then modify this object for the desired operations with the +various +'''archive_write_set_XXX'''() +functions. +In particular, you will need to invoke appropriate +'''archive_write_add_XXX'''() +and +'''archive_write_set_XXX'''() +functions to enable the corresponding compression and format +support. +=== Set options=== +See +[[ManPagerchiveriteetptions3]]. +=== Open archive=== +See +[[ManPagerchiveritepen3]]. + +Once you have prepared the +'''struct archive''' +object, you call +'''archive_write_open'''() +to actually open the archive and prepare it for writing. +There are several variants of this function; +the most basic expects you to provide pointers to several +functions that can provide blocks of bytes from the archive. +There are convenience forms that allow you to +specify a filename, file descriptor, +''FILE *'' +object, or a block of memory from which to write the archive data. +=== Produce archive=== +See +[[ManPagerchiveriteeader3]] +and +[[ManPagerchiveriteata3]]. + +Individual archive entries are written in a three-step +process: +You first initialize a +'''struct archive_entry''' +structure with information about the new entry. +At a minimum, you should set the pathname of the +entry and provide a +''struct'' stat +with a valid +''st_mode'' +field, which specifies the type of object and +''st_size'' +field, which specifies the size of the data portion of the object. +=== Release resources=== +See +[[ManPagerchiveriteree3]]. + +After all entries have been written, use the +'''archive_write_free'''() +function to release all resources. +== EXAMPLES == +The following sketch illustrates basic usage of the library. +In this example, +the callback functions are simply wrappers around the standard +[[open(2)|http://www.freebsd.org/cgi/man.cgi?query=open&sektion=2]], +[[write(2)|http://www.freebsd.org/cgi/man.cgi?query=write&sektion=2]], +and +[[close(2)|http://www.freebsd.org/cgi/man.cgi?query=close&sektion=2]] +system calls. +```text +#ifdef __linux__ +#define _FILE_OFFSET_BITS 64 +#endif +#include +#include +#include +#include +#include +#include +struct mydata { + const char *name; + int fd; +}; +int +myopen(struct archive *a, void *client_data) +{ + struct mydata *mydata = client_data; + mydata->fd = open(mydata->name, O_WRONLY | O_CREAT, 0644); + if (mydata->fd >= 0) + return (ARCHIVE_OK); + else + return (ARCHIVE_FATAL); +} +la_ssize_t +mywrite(struct archive *a, void *client_data, const void *buff, size_t n) +{ + struct mydata *mydata = client_data; + return (write(mydata->fd, buff, n)); +} +int +myclose(struct archive *a, void *client_data) +{ + struct mydata *mydata = client_data; + if (mydata->fd > 0) + close(mydata->fd); + return (0); +} +void +write_archive(const char *outname, const char **filename) +{ + struct mydata *mydata = malloc(sizeof(struct mydata)); + struct archive *a; + struct archive_entry *entry; + struct stat st; + char buff[8192]; + int len; + int fd; + a = archive_write_new(); + mydata->name = outname; + /* Set archive format and filter according to output file extension. + * If it fails, set default format. Platform depended function. + * See supported formats in archive_write_set_format_filter_by_ext.c */ + if (archive_write_set_format_filter_by_ext(a, outname) != ARCHIVE_OK) { + archive_write_add_filter_gzip(a); + archive_write_set_format_ustar(a); + } + archive_write_open(a, mydata, myopen, mywrite, myclose); + while (*filename) { + stat(*filename, &st); + entry = archive_entry_new(); + archive_entry_copy_stat(entry, &st); + archive_entry_set_pathname(entry, *filename); + archive_write_header(a, entry); + if ((fd = open(*filename, O_RDONLY)) != -1) { + len = read(fd, buff, sizeof(buff)); + while (len > 0) { + archive_write_data(a, buff, len); + len = read(fd, buff, sizeof(buff)); + } + close(fd); + } + archive_entry_free(entry); + filename++; + } + archive_write_free(a); +} +int main(int argc, const char **argv) +{ + const char *outname; + argv++; + outname = *argv++; + write_archive(outname, argv); + return 0; +} +``` +== SEE ALSO == +[[ManPageBsdtar1]], +[[ManPagerchiveriteetptions3]], +[[ManPageibarchive3]], +[[ManPageCpio5]], +[[ManPageMtree5]], +[[ManPageTar5]] +== HISTORY == +The +'''libarchive''' +library first appeared in +FreeBSD 5.3. +== AUTHORS == +The +'''libarchive''' +library was written by +Tim Kientzle <kientzle@acm.org.> +== BUGS == +There are many peculiar bugs in historic tar implementations that may cause +certain programs to reject archives written by this library. +For example, several historic implementations calculated header checksums +incorrectly and will thus reject valid archives; GNU tar does not fully support +pax interchange format; some old tar implementations required specific +field terminations. + +The default pax interchange format eliminates most of the historic +tar limitations and provides a generic key/value attribute facility +for vendor-defined extensions. +One oversight in POSIX is the failure to provide a standard attribute +for large device numbers. +This library uses +"SCHILY.devminor" +and +"SCHILY.devmajor" +for device numbers that exceed the range supported by the backwards-compatible +ustar header. +These keys are compatible with Joerg Schilling's +'''star''' +archiver. +Other implementations may not recognize these keys and will thus be unable +to correctly restore device nodes with large device numbers from archives +created by this library. diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteBlocksize3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteBlocksize3.wiki new file mode 100644 index 0000000..00beced --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteBlocksize3.wiki @@ -0,0 +1,93 @@ +ARCHIVE_WRITE_BLOCKSIZE(3) manual page +== NAME == +'''archive_write_get_bytes_per_block''', +'''archive_write_set_bytes_per_block''', +'''archive_write_get_bytes_in_last_block''', +'''archive_write_set_bytes_in_last_block''' +- functions for creating archives +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''int'' +
    +'''archive_write_get_bytes_per_block'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_set_bytes_per_block'''(''struct archive *'', ''int bytes_per_block''); +
    +''int'' +
    +'''archive_write_get_bytes_in_last_block'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_set_bytes_in_last_block'''(''struct archive *'', ''int''); +== DESCRIPTION == +
    +
    '''archive_write_set_bytes_per_block'''()
    +Sets the block size used for writing the archive data. +Every call to the write callback function, except possibly the last one, will +use this value for the length. +The default is to use a block size of 10240 bytes. +Note that a block size of zero will suppress internal blocking +and cause writes to be sent directly to the write callback as they occur. +
    '''archive_write_get_bytes_per_block'''()
    +Retrieve the block size to be used for writing. +A value of -1 here indicates that the library should use default values. +A value of zero indicates that internal blocking is suppressed. +
    '''archive_write_set_bytes_in_last_block'''()
    +Sets the block size used for writing the last block. +If this value is zero, the last block will be padded to the same size +as the other blocks. +Otherwise, the final block will be padded to a multiple of this size. +In particular, setting it to 1 will cause the final block to not be padded. +For compressed output, any padding generated by this option +is applied only after the compression. +The uncompressed data is always unpadded. +The default is to pad the last block to the full block size (note that +'''archive_write_open_filename'''() +will set this based on the file type). +Unlike the other +"set" +functions, this function can be called after the archive is opened. +
    '''archive_write_get_bytes_in_last_block'''()
    +Retrieve the currently-set value for last block size. +A value of -1 here indicates that the library should use default values. +
    +== RETURN VALUES == +'''archive_write_set_bytes_per_block'''() +and +'''archive_write_set_bytes_in_last_block'''() +return +'''ARCHIVE_OK''' +on success, or +'''ARCHIVE_FATAL'''. + +'''archive_write_get_bytes_per_block'''() +and +'''archive_write_get_bytes_in_last_block'''() +return currently configured block size +Po +```text +-1 +``` +indicates the default block size +Pc, +or +'''ARCHIVE_FATAL'''. +== ERRORS == +Detailed error codes and textual descriptions are available from the +'''archive_errno'''() +and +'''archive_error_string'''() +functions. +== SEE ALSO == +[[ManPageBsdtar1]], +[[ManPagerchiveriteetptions3]], +[[ManPageibarchive3]], +[[ManPageCpio5]], +[[ManPageMtree5]], +[[ManPageTar5]] diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteData3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteData3.wiki new file mode 100644 index 0000000..8670f8a --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteData3.wiki @@ -0,0 +1,61 @@ +ARCHIVE_WRITE_DATA(3) manual page +== NAME == +'''archive_write_data''', +'''archive_write_data_block''' +- functions for creating archives +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''la_ssize_t'' +
    +'''archive_write_data'''(''struct archive *'', ''const void *'', ''size_t''); +
    +''la_ssize_t'' +
    +'''archive_write_data_block'''(''struct archive *'', ''const void *'', ''size_t size'', ''int64_t offset''); +== DESCRIPTION == +
    +
    '''archive_write_data'''()
    +Write data corresponding to the header just written. +
    '''archive_write_data_block'''()
    +Write data corresponding to the header just written. +This is like +'''archive_write_data'''() +except that it performs a seek on the file being +written to the specified offset before writing the data. +This is useful when restoring sparse files from archive +formats that support sparse files. +Returns number of bytes written or -1 on error. +(Note: This is currently not supported for +'''archive_write''' +handles, only for +'''archive_write_disk''' +handles. +
    +== RETURN VALUES == +This function returns the number of bytes actually written, or +a negative error code on error. +== ERRORS == +Detailed error codes and textual descriptions are available from the +'''archive_errno'''() +and +'''archive_error_string'''() +functions. +== BUGS == +In libarchive 3.x, this function sometimes returns +zero on success instead of returning the number of bytes written. +Specifically, this occurs when writing to an +''archive_write_disk'' +handle. +Clients should treat any value less than zero as an error +and consider any non-negative value as success. +== SEE ALSO == +[[ManPageBsdtar1]], +[[ManPagerchiveriteinishntry3]], +[[ManPagerchiveriteetptions3]], +[[ManPageibarchive3]], +[[ManPageCpio5]], +[[ManPageMtree5]], +[[ManPageTar5]] diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteDisk3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteDisk3.wiki new file mode 100644 index 0000000..e3eea00 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteDisk3.wiki @@ -0,0 +1,335 @@ +ARCHIVE_WRITE_DISK(3) manual page +== NAME == +'''archive_write_disk_new''', +'''archive_write_disk_set_options''', +'''archive_write_disk_set_skip_file''', +'''archive_write_disk_set_group_lookup''', +'''archive_write_disk_set_standard_lookup''', +'''archive_write_disk_set_user_lookup''' +- functions for creating objects on disk +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''struct archive *'' +
    +'''archive_write_disk_new'''(''void''); +
    +''int'' +
    +'''archive_write_disk_set_options'''(''struct archive *'', ''int flags''); +
    +''int'' +
    +'''archive_write_disk_set_skip_file'''(''struct archive *'', ''dev_t'', ''ino_t''); +
    +''int'' +
    +'''archive_write_disk_set_group_lookup'''(''struct archive *'', ''void *'', ''gid_t (*)(void *, const char *gname, gid_t gid)'', ''void (*cleanup)(void *)''); +
    +''int'' +
    +'''archive_write_disk_set_standard_lookup'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_disk_set_user_lookup'''(''struct archive *'', ''void *'', ''uid_t (*)(void *, const char *uname, uid_t uid)'', ''void (*cleanup)(void *)''); +== DESCRIPTION == +These functions provide a complete API for creating objects on +disk from +'''struct archive_entry''' +descriptions. +They are most naturally used when extracting objects from an archive +using the +'''archive_read'''() +interface. +The general process is to read +'''struct archive_entry''' +objects from an archive, then write those objects to a +'''struct archive''' +object created using the +'''archive_write_disk'''() +family functions. +This interface is deliberately very similar to the +'''archive_write'''() +interface used to write objects to a streaming archive. +
    +
    '''archive_write_disk_new'''()
    +Allocates and initializes a +'''struct archive''' +object suitable for writing objects to disk. +
    '''archive_write_disk_set_skip_file'''()
    +Records the device and inode numbers of a file that should not be +overwritten. +This is typically used to ensure that an extraction process does not +overwrite the archive from which objects are being read. +This capability is technically unnecessary but can be a significant +performance optimization in practice. +
    '''archive_write_disk_set_options'''()
    +The options field consists of a bitwise OR of one or more of the +following values: +
    +
    '''ARCHIVE_EXTRACT_ACL'''
    +Attempt to restore Access Control Lists. +By default, extended ACLs are ignored. +
    '''ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS'''
    +Before removing a file system object prior to replacing it, clear +platform-specific file flags which might prevent its removal. +
    '''ARCHIVE_EXTRACT_FFLAGS'''
    +Attempt to restore file attributes (file flags). +By default, file attributes are ignored. +See +[[chattr(1)|http://www.freebsd.org/cgi/man.cgi?query=chattr&sektion=1]] +(Linux) +or +[[chflags(1)|http://www.freebsd.org/cgi/man.cgi?query=chflags&sektion=1]] +(FreeBSD, Mac OS X) +for more information on file attributes. +
    '''ARCHIVE_EXTRACT_MAC_METADATA'''
    +Mac OS X specific. +Restore metadata using +[[copyfile(3)|http://www.freebsd.org/cgi/man.cgi?query=copyfile&sektion=3]]. +By default, +[[copyfile(3)|http://www.freebsd.org/cgi/man.cgi?query=copyfile&sektion=3]] +metadata is ignored. +
    '''ARCHIVE_EXTRACT_NO_OVERWRITE'''
    +Existing files on disk will not be overwritten. +By default, existing regular files are truncated and overwritten; +existing directories will have their permissions updated; +other pre-existing objects are unlinked and recreated from scratch. +
    '''ARCHIVE_EXTRACT_OWNER'''
    +The user and group IDs should be set on the restored file. +By default, the user and group IDs are not restored. +
    '''ARCHIVE_EXTRACT_PERM'''
    +Full permissions (including SGID, SUID, and sticky bits) should +be restored exactly as specified, without obeying the +current umask. +Note that SUID and SGID bits can only be restored if the +user and group ID of the object on disk are correct. +If +'''ARCHIVE_EXTRACT_OWNER''' +is not specified, then SUID and SGID bits will only be restored +if the default user and group IDs of newly-created objects on disk +happen to match those specified in the archive entry. +By default, only basic permissions are restored, and umask is obeyed. +
    '''ARCHIVE_EXTRACT_SAFE_WRITES'''
    +Extract files atomically, by first creating a unique temporary file and then +renaming it to its required destination name. +This avoids a race where an application might see a partial file (or no +file) during extraction. +
    '''ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS'''
    +Refuse to extract an absolute path. +The default is to not refuse such paths. +
    '''ARCHIVE_EXTRACT_SECURE_NODOTDOT'''
    +Refuse to extract a path that contains a +''..'' +element anywhere within it. +The default is to not refuse such paths. +Note that paths ending in +''..'' +always cause an error, regardless of this flag. +
    '''ARCHIVE_EXTRACT_SECURE_SYMLINKS'''
    +Refuse to extract any object whose final location would be altered +by a symlink on disk. +This is intended to help guard against a variety of mischief +caused by archives that (deliberately or otherwise) extract +files outside of the current directory. +The default is not to perform this check. +If +
    '''ARCHIVE_EXTRACT_SPARSE'''
    +Scan data for blocks of NUL bytes and try to recreate them with holes. +This results in sparse files, independent of whether the archive format +supports or uses them. +'''ARCHIVE_EXTRACT_UNLINK''' +is specified together with this option, the library will +remove any intermediate symlinks it finds and return an +error only if such symlink could not be removed. +
    '''ARCHIVE_EXTRACT_TIME'''
    +The timestamps (mtime, ctime, and atime) should be restored. +By default, they are ignored. +Note that restoring of atime is not currently supported. +
    '''ARCHIVE_EXTRACT_UNLINK'''
    +Existing files on disk will be unlinked before any attempt to +create them. +In some cases, this can prove to be a significant performance improvement. +By default, existing files are truncated and rewritten, but +the file is not recreated. +In particular, the default behavior does not break existing hard links. +
    '''ARCHIVE_EXTRACT_XATTR'''
    +Attempt to restore extended file attributes. +By default, they are ignored. +See +[[xattr(7)|http://www.freebsd.org/cgi/man.cgi?query=xattr&sektion=7]] +(Linux,) +[[xattr(2)|http://www.freebsd.org/cgi/man.cgi?query=xattr&sektion=2]] +(Mac OS X,) +or +[[getextattr(8)|http://www.freebsd.org/cgi/man.cgi?query=getextattr&sektion=8]] +(FreeBSD) +for more information on extended file attributes. +
    +
    +'''archive_write_disk_set_group_lookup'''(), +'''archive_write_disk_set_user_lookup'''() +
    +The +'''struct archive_entry''' +objects contain both names and ids that can be used to identify users +and groups. +These names and ids describe the ownership of the file itself and +also appear in ACL lists. +By default, the library uses the ids and ignores the names, but +this can be overridden by registering user and group lookup functions. +To register, you must provide a lookup function which +accepts both a name and id and returns a suitable id. +You may also provide a +'''void *''' +pointer to a private data structure and a cleanup function for +that data. +The cleanup function will be invoked when the +'''struct archive''' +object is destroyed. +
    '''archive_write_disk_set_standard_lookup'''()
    +This convenience function installs a standard set of user +and group lookup functions. +These functions use +[[getpwnam(3)|http://www.freebsd.org/cgi/man.cgi?query=getpwnam&sektion=3]] +and +[[getgrnam(3)|http://www.freebsd.org/cgi/man.cgi?query=getgrnam&sektion=3]] +to convert names to ids, defaulting to the ids if the names cannot +be looked up. +These functions also implement a simple memory cache to reduce +the number of calls to +[[getpwnam(3)|http://www.freebsd.org/cgi/man.cgi?query=getpwnam&sektion=3]] +and +[[getgrnam(3)|http://www.freebsd.org/cgi/man.cgi?query=getgrnam&sektion=3]]. +
    +More information about the +''struct'' archive +object and the overall design of the library can be found in the +[[ManPageibarchive3]] +overview. +Many of these functions are also documented under +[[ManPagerchiverite3]]. +== RETURN VALUES == +Most functions return +'''ARCHIVE_OK''' +(zero) on success, or one of several non-zero +error codes for errors. +Specific error codes include: +'''ARCHIVE_RETRY''' +for operations that might succeed if retried, +'''ARCHIVE_WARN''' +for unusual conditions that do not prevent further operations, and +'''ARCHIVE_FATAL''' +for serious errors that make remaining operations impossible. + +'''archive_write_disk_new'''() +returns a pointer to a newly-allocated +'''struct archive''' +object. + +'''archive_write_data'''() +returns a count of the number of bytes actually written, +or +```text +-1 +``` +on error. +== ERRORS == +Detailed error codes and textual descriptions are available from the +'''archive_errno'''() +and +'''archive_error_string'''() +functions. +== SEE ALSO == +[[ManPageBsdtar1]], +[[ManPagerchiveead3]], +[[ManPagerchiverite3]], +[[ManPageibarchive3]] +== HISTORY == +The +'''libarchive''' +library first appeared in +FreeBSD 5.3. +The +'''archive_write_disk''' +interface was added to +'''libarchive''' 2.0 +and first appeared in +FreeBSD 6.3. +== AUTHORS == +The +'''libarchive''' +library was written by +Tim Kientzle <kientzle@acm.org.> +== BUGS == +Directories are actually extracted in two distinct phases. +Directories are created during +'''archive_write_header'''(), +but final permissions are not set until +'''archive_write_close'''(). +This separation is necessary to correctly handle borderline +cases such as a non-writable directory containing +files, but can cause unexpected results. +In particular, directory permissions are not fully +restored until the archive is closed. +If you use +[[chdir(2)|http://www.freebsd.org/cgi/man.cgi?query=chdir&sektion=2]] +to change the current directory between calls to +'''archive_read_extract'''() +or before calling +'''archive_read_close'''(), +you may confuse the permission-setting logic with +the result that directory permissions are restored +incorrectly. + +The library attempts to create objects with filenames longer than +'''PATH_MAX''' +by creating prefixes of the full path and changing the current directory. +Currently, this logic is limited in scope; the fixup pass does +not work correctly for such objects and the symlink security check +option disables the support for very long pathnames. + +Restoring the path +''aa/../bb'' +does create each intermediate directory. +In particular, the directory +''aa'' +is created as well as the final object +''bb''. +In theory, this can be exploited to create an entire directory hierarchy +with a single request. +Of course, this does not work if the +'''ARCHIVE_EXTRACT_NODOTDOT''' +option is specified. + +Implicit directories are always created obeying the current umask. +Explicit objects are created obeying the current umask unless +'''ARCHIVE_EXTRACT_PERM''' +is specified, in which case they current umask is ignored. + +SGID and SUID bits are restored only if the correct user and +group could be set. +If +'''ARCHIVE_EXTRACT_OWNER''' +is not specified, then no attempt is made to set the ownership. +In this case, SGID and SUID bits are restored only if the +user and group of the final object happen to match those specified +in the entry. + +The +"standard" +user-id and group-id lookup functions are not the defaults because +[[getgrnam(3)|http://www.freebsd.org/cgi/man.cgi?query=getgrnam&sektion=3]] +and +[[getpwnam(3)|http://www.freebsd.org/cgi/man.cgi?query=getpwnam&sektion=3]] +are sometimes too large for particular applications. +The current design allows the application author to use a more +compact implementation when appropriate. + +There should be a corresponding +'''archive_read_disk''' +interface that walks a directory hierarchy and returns archive +entry objects. diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteFilter3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteFilter3.wiki new file mode 100644 index 0000000..84d7816 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteFilter3.wiki @@ -0,0 +1,134 @@ +ARCHIVE_WRITE_FILTER(3) manual page +== NAME == +'''archive_write_add_filter_b64encode''', +'''archive_write_add_filter_by_name''', +'''archive_write_add_filter_bzip2''', +'''archive_write_add_filter_compress''', +'''archive_write_add_filter_grzip''', +'''archive_write_add_filter_gzip''', +'''archive_write_add_filter_lrzip''', +'''archive_write_add_filter_lz4''', +'''archive_write_add_filter_lzip''', +'''archive_write_add_filter_lzma''', +'''archive_write_add_filter_lzop''', +'''archive_write_add_filter_none''', +'''archive_write_add_filter_program''', +'''archive_write_add_filter_uuencode''', +'''archive_write_add_filter_xz''', +'''archive_write_add_filter_zstd''' +- functions enabling output filters +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''int'' +
    +'''archive_write_add_filter_b64encode'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_add_filter_bzip2'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_add_filter_compress'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_add_filter_grzip'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_add_filter_gzip'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_add_filter_lrzip'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_add_filter_lz4'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_add_filter_lzip'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_add_filter_lzma'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_add_filter_lzop'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_add_filter_none'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_add_filter_program'''(''struct archive *'', ''const char * cmd''); +
    +''int'' +
    +'''archive_write_add_filter_uuencode'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_add_filter_xz'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_add_filter_zstd'''(''struct archive *''); +== DESCRIPTION == +
    +
    +'''archive_write_add_filter_bzip2'''(), +'''archive_write_add_filter_compress'''(), +'''archive_write_add_filter_grzip'''(), +'''archive_write_add_filter_gzip'''(), +'''archive_write_add_filter_lrzip'''(), +'''archive_write_add_filter_lz4'''(), +'''archive_write_add_filter_lzip'''(), +'''archive_write_add_filter_lzma'''(), +'''archive_write_add_filter_lzop'''(), +'''archive_write_add_filter_xz'''(), +'''archive_write_add_filter_zstd'''(), +
    +The resulting archive will be compressed as specified. +Note that the compressed output is always properly blocked. +
    +'''archive_write_add_filter_b64encode'''(), +'''archive_write_add_filter_uuencode'''(), +
    +The output will be encoded as specified. +The encoded output is always properly blocked. +
    '''archive_write_add_filter_none'''()
    +This is never necessary. +It is provided only for backwards compatibility. +
    '''archive_write_add_filter_program'''()
    +The archive will be fed into the specified compression program. +The output of that program is blocked and written to the client +write callbacks. +
    +== RETURN VALUES == +These functions return +'''ARCHIVE_OK''' +on success, or +'''ARCHIVE_FATAL'''. +== ERRORS == +Detailed error codes and textual descriptions are available from the +'''archive_errno'''() +and +'''archive_error_string'''() +functions. +== SEE ALSO == +[[ManPageBsdtar1]], +[[ManPagerchiverite3]], +[[ManPagerchiveriteormat3]], +[[ManPagerchiveriteetptions3]], +[[ManPageibarchive3]], +[[ManPageCpio5]], +[[ManPageMtree5]], +[[ManPageTar5]] diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteFinishEntry3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteFinishEntry3.wiki new file mode 100644 index 0000000..a1f2a32 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteFinishEntry3.wiki @@ -0,0 +1,50 @@ +ARCHIVE_WRITE_FINISH_ENTRY(3) manual page +== NAME == +'''archive_write_finish_entry''' +- functions for creating archives +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''int'' +
    +'''archive_write_finish_entry'''(''struct archive *''); +== DESCRIPTION == +Close out the entry just written. +In particular, this writes out the final padding required by some formats. +Ordinarily, clients never need to call this, as it +is called automatically by +'''archive_write_header'''() +and +'''archive_write_close'''() +as needed. +For +'''archive_write_disk''' +handles, this flushes pending file attribute changes like modification time. +== RETURN VALUES == +This function returns +'''ARCHIVE_OK''' +on success, or one of several non-zero +error codes for errors. +Specific error codes include: +'''ARCHIVE_RETRY''' +for operations that might succeed if retried, +'''ARCHIVE_WARN''' +for unusual conditions that do not prevent further operations, and +'''ARCHIVE_FATAL''' +for serious errors that make remaining operations impossible. +== ERRORS == +Detailed error codes and textual descriptions are available from the +'''archive_errno'''() +and +'''archive_error_string'''() +functions. +== SEE ALSO == +[[ManPageBsdtar1]], +[[ManPagerchiveriteata3]], +[[ManPagerchiveriteetptions3]], +[[ManPageibarchive3]], +[[ManPageCpio5]], +[[ManPageMtree5]], +[[ManPageTar5]] diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteFormat3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteFormat3.wiki new file mode 100644 index 0000000..2a92d79 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteFormat3.wiki @@ -0,0 +1,190 @@ +ARCHIVE_WRITE_FORMAT(3) manual page +== NAME == +'''archive_write_set_format''', +'''archive_write_set_format_7zip''', +'''archive_write_set_format_ar''', +'''archive_write_set_format_ar_bsd''', +'''archive_write_set_format_ar_svr4''', +'''archive_write_set_format_by_name''', +'''archive_write_set_format_cpio''', +'''archive_write_set_format_cpio_newc''', +'''archive_write_set_format_filter_by_ext''', +'''archive_write_set_format_filter_by_ext_def''', +'''archive_write_set_format_gnutar''', +'''archive_write_set_format_iso9660''', +'''archive_write_set_format_mtree''', +'''archive_write_set_format_mtree_classic''', +'''archive_write_set_format_mtree_default''', +'''archive_write_set_format_pax''', +'''archive_write_set_format_pax_restricted''', +'''archive_write_set_format_raw''', +'''archive_write_set_format_shar''', +'''archive_write_set_format_shar_dump''', +'''archive_write_set_format_ustar''', +'''archive_write_set_format_v7tar''', +'''archive_write_set_format_warc''', +'''archive_write_set_format_xar''', +'''archive_write_set_format_zip''' +- functions for creating archives +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''int'' +
    +'''archive_write_set_format'''(''struct archive *'', ''int code''); +
    +''int'' +
    +'''archive_write_set_format_7zip'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_set_format_ar'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_set_format_ar_bsd'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_set_format_ar_svr4'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_set_format_by_name'''(''struct archive *'', ''const char *name''); +
    +''int'' +
    +'''archive_write_set_format_cpio'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_set_format_cpio_newc'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_set_format_filter_by_ext'''(''struct archive *'', ''const char *filename''); +
    +''int'' +
    +'''archive_write_set_format_filter_by_ext_def'''(''struct archive *'', ''const char *filename'', ''const char *def_ext''); +
    +''int'' +
    +'''archive_write_set_format_gnutar'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_set_format_iso9660'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_set_format_mtree'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_set_format_pax'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_set_format_pax_restricted'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_set_format_raw'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_set_format_shar'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_set_format_shar_dump'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_set_format_ustar'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_set_format_v7tar'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_set_format_warc'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_set_format_xar'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_set_format_zip'''(''struct archive *''); +== DESCRIPTION == +These functions set the format that will be used for the archive. + +The library can write a variety of common archive formats. +
    +
    '''archive_write_set_format'''()
    +Sets the format based on the format code (see +''archive.h'' +for the full list of format codes). +In particular, this can be used in conjunction with +'''archive_format'''() +to create a new archive with the same format as an existing archive. +
    '''archive_write_set_format_by_name'''()
    +Sets the corresponding format based on the common name. +
    +'''archive_write_set_format_filter_by_ext'''(), +'''archive_write_set_format_filter_by_ext_def'''() +
    +Sets both filters and format based on the output filename. +Supported extensions: .7z, .zip, .jar, .cpio, .iso, .a, .ar, .tar, .tgz, .tar.gz, .tar.bz2, .tar.xz +
    +'''archive_write_set_format_7zip'''() +'''archive_write_set_format_ar_bsd'''(), +'''archive_write_set_format_ar_svr4'''(), +'''archive_write_set_format_cpio'''() +'''archive_write_set_format_cpio_newc'''() +'''archive_write_set_format_gnutar'''() +'''archive_write_set_format_iso9660'''() +'''archive_write_set_format_mtree'''() +'''archive_write_set_format_mtree_classic'''() +'''archive_write_set_format_pax'''() +'''archive_write_set_format_pax_restricted'''() +'''archive_write_set_format_raw'''() +'''archive_write_set_format_shar'''() +'''archive_write_set_format_shar_dump'''() +'''archive_write_set_format_ustar'''() +'''archive_write_set_format_v7tar'''() +'''archive_write_set_format_warc'''() +'''archive_write_set_format_xar'''() +'''archive_write_set_format_zip'''() +
    +Set the format as specified. +More details on the formats supported by libarchive can be found in the +[[ManPageibarchiveormats5]] +manual page. +
    +== RETURN VALUES == +These functions return +'''ARCHIVE_OK''' +on success, or +'''ARCHIVE_FATAL'''. +== ERRORS == +Detailed error codes and textual descriptions are available from the +'''archive_errno'''() +and +'''archive_error_string'''() +functions. +== SEE ALSO == +[[ManPageBsdtar1]], +[[ManPagerchiverite3]], +[[ManPagerchiveriteetptions3]], +[[ManPageibarchive3]], +[[ManPageCpio5]], +[[ManPageibarchiveormats5]], +[[ManPageMtree5]], +[[ManPageTar5]] diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteFree3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteFree3.wiki new file mode 100644 index 0000000..06341bf --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteFree3.wiki @@ -0,0 +1,73 @@ +ARCHIVE_WRITE_FREE(3) manual page +== NAME == +'''archive_write_fail''', +'''archive_write_close''', +'''archive_write_finish''', +'''archive_write_free''' +- functions for creating archives +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''int'' +
    +'''archive_write_fail'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_close'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_finish'''(''struct archive *''); +
    +''int'' +
    +'''archive_write_free'''(''struct archive *''); +== DESCRIPTION == +
    +
    '''archive_write_fail'''()
    +Always returns +'''ARCHIVE_FATAL'''. +This marks the archive object as being unusable; +after calling this function, the only call that can succeed is +'''archive_write_free'''() +to release the resources. +This can be used to speed recovery when the archive creation +must be aborted. +Note that the created archive is likely to be malformed in this case; +
    '''archive_write_close'''()
    +Complete the archive and invoke the close callback. +
    '''archive_write_finish'''()
    +This is a deprecated synonym for +'''archive_write_free'''(). +
    '''archive_write_free'''()
    +Invokes +'''archive_write_close'''() +if necessary, then releases all resources. +If you need detailed information about +'''archive_write_close'''() +failures, you should be careful to call it separately, as +you cannot obtain error information after +'''archive_write_free'''() +returns. +
    +== RETURN VALUES == +These functions return +'''ARCHIVE_OK''' +on success, or +'''ARCHIVE_FATAL'''. +== ERRORS == +Detailed error codes and textual descriptions are available from the +'''archive_errno'''() +and +'''archive_error_string'''() +functions. +== SEE ALSO == +[[ManPageBsdtar1]], +[[ManPagerchiveriteetptions3]], +[[ManPageibarchive3]], +[[ManPageCpio5]], +[[ManPageMtree5]], +[[ManPageTar5]] diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteHeader3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteHeader3.wiki new file mode 100644 index 0000000..7087ede --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteHeader3.wiki @@ -0,0 +1,44 @@ +ARCHIVE_WRITE_HEADER(3) manual page +== NAME == +'''archive_write_header''' +- functions for creating archives +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''int'' +
    +'''archive_write_header'''(''struct archive *'', ''struct archive_entry *''); +== DESCRIPTION == +Build and write a header using the data in the provided +'''struct archive_entry''' +structure. +See +[[ManPagerchiventry3]] +for information on creating and populating +'''struct archive_entry''' +objects. +== RETURN VALUES == +This function returns +'''ARCHIVE_OK''' +on success, or one of the following on error: +'''ARCHIVE_RETRY''' +for operations that might succeed if retried, +'''ARCHIVE_WARN''' +for unusual conditions that do not prevent further operations, and +'''ARCHIVE_FATAL''' +for serious errors that make remaining operations impossible. +== ERRORS == +Detailed error codes and textual descriptions are available from the +'''archive_errno'''() +and +'''archive_error_string'''() +functions. +== SEE ALSO == +[[ManPageBsdtar1]], +[[ManPagerchiveriteetptions3]], +[[ManPageibarchive3]], +[[ManPageCpio5]], +[[ManPageMtree5]], +[[ManPageTar5]] diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteNew3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteNew3.wiki new file mode 100644 index 0000000..b9c787c --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteNew3.wiki @@ -0,0 +1,31 @@ +ARCHIVE_WRITE_NEW(3) manual page +== NAME == +'''archive_write_new''' +- functions for creating archives +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''struct archive *'' +
    +'''archive_write_new'''(''void''); +== DESCRIPTION == +Allocates and initializes a +'''struct archive''' +object suitable for writing a tar archive. +NULL +is returned on error. + +A complete description of the +'''struct archive''' +object can be found in the overview manual page for +[[ManPageibarchive3]]. +== SEE ALSO == +[[ManPageBsdtar1]], +[[ManPagerchiverite3]], +[[ManPagerchiveriteetptions3]], +[[ManPageibarchive3]], +[[ManPageCpio5]], +[[ManPageMtree5]], +[[ManPageTar5]] diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteOpen3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteOpen3.wiki new file mode 100644 index 0000000..579aaf3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteOpen3.wiki @@ -0,0 +1,208 @@ +ARCHIVE_WRITE_OPEN(3) manual page +== NAME == +'''archive_write_open''', +'''archive_write_open_fd''', +'''archive_write_open_FILE''', +'''archive_write_open_filename''', +'''archive_write_open_memory''' +- functions for creating archives +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''int'' +
    +'''archive_write_open'''(''struct archive *'', ''void *client_data'', ''archive_open_callback *'', ''archive_write_callback *'', ''archive_close_callback *''); +
    +''int'' +
    +'''archive_write_open_fd'''(''struct archive *'', ''int fd''); +
    +''int'' +
    +'''archive_write_open_FILE'''(''struct archive *'', ''FILE *file''); +
    +''int'' +
    +'''archive_write_open_filename'''(''struct archive *'', ''const char *filename''); +
    +''int'' +
    +'''archive_write_open_memory'''(''struct archive *'', ''void *buffer'', ''size_t bufferSize'', ''size_t *outUsed''); +== DESCRIPTION == +
    +
    '''archive_write_open'''()
    +Freeze the settings, open the archive, and prepare for writing entries. +This is the most generic form of this function, which accepts +pointers to three callback functions which will be invoked by +the compression layer to write the constructed archive. +This does not alter the default archive padding. +
    '''archive_write_open_fd'''()
    +A convenience form of +'''archive_write_open'''() +that accepts a file descriptor. +The +'''archive_write_open_fd'''() +function is safe for use with tape drives or other +block-oriented devices. +
    '''archive_write_open_FILE'''()
    +A convenience form of +'''archive_write_open'''() +that accepts a +''FILE *'' +pointer. +Note that +'''archive_write_open_FILE'''() +is not safe for writing to tape drives or other devices +that require correct blocking. +
    '''archive_write_open_file'''()
    +A deprecated synonym for +'''archive_write_open_filename'''(). +
    '''archive_write_open_filename'''()
    +A convenience form of +'''archive_write_open'''() +that accepts a filename. +A NULL argument indicates that the output should be written to standard output; +an argument of +"-" +will open a file with that name. +If you have not invoked +'''archive_write_set_bytes_in_last_block'''(), +then +'''archive_write_open_filename'''() +will adjust the last-block padding depending on the file: +it will enable padding when writing to standard output or +to a character or block device node, it will disable padding otherwise. +You can override this by manually invoking +'''archive_write_set_bytes_in_last_block'''() +before calling +'''archive_write_open'''(). +The +'''archive_write_open_filename'''() +function is safe for use with tape drives or other +block-oriented devices. +
    '''archive_write_open_memory'''()
    +A convenience form of +'''archive_write_open'''() +that accepts a pointer to a block of memory that will receive +the archive. +The final +''size_t *'' +argument points to a variable that will be updated +after each write to reflect how much of the buffer +is currently in use. +You should be careful to ensure that this variable +remains allocated until after the archive is +closed. +This function will disable padding unless you +have specifically set the block size. +
    +More information about the +''struct'' archive +object and the overall design of the library can be found in the +[[ManPageibarchive3]] +overview. + +Note that the convenience forms above vary in how +they block the output. +See +[[ManPagerchiveritelocksize3]] +if you need to control the block size used for writes +or the end-of-file padding behavior. +== CLIENT CALLBACKS == +To use this library, you will need to define and register +callback functions that will be invoked to write data to the +resulting archive. +These functions are registered by calling +'''archive_write_open'''(): +
      +
    • +''typedef int'' +'''archive_open_callback'''(''struct archive *'', ''void *client_data'') +
    + +The open callback is invoked by +'''archive_write_open'''(). +It should return +'''ARCHIVE_OK''' +if the underlying file or data source is successfully +opened. +If the open fails, it should call +'''archive_set_error'''() +to register an error code and message and return +'''ARCHIVE_FATAL'''. +
      +
    • +''typedef la_ssize_t'' +'''archive_write_callback'''(''struct archive *'', ''void *client_data'', ''const void *buffer'', ''size_t length'') +
    + +The write callback is invoked whenever the library +needs to write raw bytes to the archive. +For correct blocking, each call to the write callback function +should translate into a single +[[write(2)|http://www.freebsd.org/cgi/man.cgi?query=write&sektion=2]] +system call. +This is especially critical when writing archives to tape drives. +On success, the write callback should return the +number of bytes actually written. +On error, the callback should invoke +'''archive_set_error'''() +to register an error code and message and return -1. +
      +
    • +''typedef int'' +'''archive_close_callback'''(''struct archive *'', ''void *client_data'') +
    + +The close callback is invoked by archive_close when +the archive processing is complete. +The callback should return +'''ARCHIVE_OK''' +on success. +On failure, the callback should invoke +'''archive_set_error'''() +to register an error code and message and +return +'''ARCHIVE_FATAL'''. + +Note that if the client-provided write callback function +returns a non-zero value, that error will be propagated back to the caller +through whatever API function resulted in that call, which +may include +'''archive_write_header'''(), +'''archive_write_data'''(), +'''archive_write_close'''(), +'''archive_write_finish'''(), +or +'''archive_write_free'''(). +The client callback can call +'''archive_set_error'''() +to provide values that can then be retrieved by +'''archive_errno'''() +and +'''archive_error_string'''(). +== RETURN VALUES == +These functions return +'''ARCHIVE_OK''' +on success, or +'''ARCHIVE_FATAL'''. +== ERRORS == +Detailed error codes and textual descriptions are available from the +'''archive_errno'''() +and +'''archive_error_string'''() +functions. +== SEE ALSO == +[[ManPageBsdtar1]], +[[ManPagerchiverite3]], +[[ManPagerchiveritelocksize3]], +[[ManPagerchiveriteilter3]], +[[ManPagerchiveriteormat3]], +[[ManPagerchiveriteew3]], +[[ManPagerchiveriteetptions3]], +[[ManPageibarchive3]], +[[ManPageCpio5]], +[[ManPageMtree5]], +[[ManPageTar5]] diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteSetOptions3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteSetOptions3.wiki new file mode 100644 index 0000000..ceae9bf --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteSetOptions3.wiki @@ -0,0 +1,663 @@ +ARCHIVE_WRITE_OPTIONS(3) manual page +== NAME == +'''archive_write_set_filter_option''', +'''archive_write_set_format_option''', +'''archive_write_set_option''', +'''archive_write_set_options''' +- functions controlling options for writing archives +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +
    +''int'' +
    +'''archive_write_set_filter_option'''(''struct archive *'', ''const char *module'', ''const char *option'', ''const char *value''); +
    +''int'' +
    +'''archive_write_set_format_option'''(''struct archive *'', ''const char *module'', ''const char *option'', ''const char *value''); +
    +''int'' +
    +'''archive_write_set_option'''(''struct archive *'', ''const char *module'', ''const char *option'', ''const char *value''); +
    +''int'' +
    +'''archive_write_set_options'''(''struct archive *'', ''const char *options''); +== DESCRIPTION == +These functions provide a way for libarchive clients to configure +specific write modules. +
    +
    +'''archive_write_set_filter_option'''(), +'''archive_write_set_format_option'''() +
    +Specifies an option that will be passed to the currently-registered +filters (including decompression filters) or format readers. + +If +''option'' +and +''value'' +are both +NULL, +these functions will do nothing and +'''ARCHIVE_OK''' +will be returned. +If +''option'' +is +NULL +but +''value'' +is not, these functions will do nothing and +'''ARCHIVE_FAILED''' +will be returned. + +If +''module'' +is not +NULL, +''option'' +and +''value'' +will be provided to the filter or reader named +''module''. +The return value will be either +'''ARCHIVE_OK''' +if the option was successfully handled or +'''ARCHIVE_WARN''' +if the option was unrecognized by the module or could otherwise +not be handled. +If there is no such module, +'''ARCHIVE_FAILED''' +will be returned. + +If +''module'' +is +NULL, +''option'' +and +''value'' +will be provided to every registered module. +If any module returns +'''ARCHIVE_FATAL''', +this value will be returned immediately. +Otherwise, +'''ARCHIVE_OK''' +will be returned if any module accepts the option, and +'''ARCHIVE_FAILED''' +in all other cases. +
    '''archive_write_set_option'''()
    +Calls +'''archive_write_set_format_option'''(), +then +'''archive_write_set_filter_option'''(). +If either function returns +'''ARCHIVE_FATAL''', +'''ARCHIVE_FATAL''' +will be returned +immediately. +Otherwise, the greater of the two values will be returned. +
    '''archive_write_set_options'''()
    +''options'' +is a comma-separated list of options. +If +''options'' +is +NULL +or empty, +'''ARCHIVE_OK''' +will be returned immediately. + +Individual options have one of the following forms: +
    +
    ''option=value''
    +The option/value pair will be provided to every module. +Modules that do not accept an option with this name will ignore it. +
    ''option''
    +The option will be provided to every module with a value of +"1". +
    ''!option''
    +The option will be provided to every module with a NULL value. +
    ''module:option=value'', ''module:option'', ''module:!option''
    +As above, but the corresponding option and value will be provided +only to modules whose name matches +''module''. +
    +
    +== OPTIONS == +
    +
    Filter b64encode
    +
    +
    '''mode'''
    +The value is interpreted as octal digits specifying the file mode. +
    '''name'''
    +The value specifies the file name. +
    +
    Filter bzip2
    +
    +
    '''compression-level'''
    +The value is interpreted as a decimal integer specifying the +bzip2 compression level. Supported values are from 1 to 9. +
    +
    Filter gzip
    +
    +
    '''compression-level'''
    +The value is interpreted as a decimal integer specifying the +gzip compression level. Supported values are from 0 to 9. +
    '''timestamp'''
    +Store timestamp. This is enabled by default. +
    +
    Filter lrzip
    +
    +
    '''compression'''=''type''
    +Use +''type'' +as compression method. +Supported values are +"bzip2", +"gzipi", +"lzo" +(ultra fast,) +and +"zpaq" +(best, extremely slow.) +
    '''compression-level'''
    +The value is interpreted as a decimal integer specifying the +lrzip compression level. Supported values are from 1 to 9. +
    +
    Filter lz4
    +
    +
    '''compression-level'''
    +The value is interpreted as a decimal integer specifying the +lz4 compression level. Supported values are from 0 to 9. +
    '''stream-checksum'''
    +Enable stream checksum. This is enabled by default. +
    '''block-checksum'''
    +Enable block checksum. This is disabled by default. +
    '''block-size'''
    +The value is interpreted as a decimal integer specifying the +lz4 compression block size. Supported values are from 4 to 7 +(default.) +
    '''block-dependence'''
    +Use the previous block of the block being compressed for +a compression dictionary to improve compression ratio. +This is disabled by default. +
    +
    Filter lzop
    +
    +
    '''compression-level'''
    +The value is interpreted as a decimal integer specifying the +lzop compression level. Supported values are from 1 to 9. +
    +
    Filter uuencode
    +
    +
    '''mode'''
    +The value is interpreted as octal digits specifying the file mode. +
    '''name'''
    +The value specifies the file name. +
    +
    Filter xz
    +
    +
    '''compression-level'''
    +The value is interpreted as a decimal integer specifying the +compression level. Supported values are from 0 to 9. +
    '''threads'''
    +The value is interpreted as a decimal integer specifying the +number of threads for multi-threaded lzma compression. +If supported, the default value is read from +'''lzma_cputhreads'''(). +
    +
    Filter zstd
    +
    +
    '''compression-level'''
    +The value is interpreted as a decimal integer specifying the +compression level. Supported values are from 1 to 22. +
    +
    Format 7zip
    +
    +
    '''compression'''
    +The value is one of +"store", +"deflate", +"bzip2", +"lzma1", +"lzma2" +or +"ppmd" +to indicate how the following entries should be compressed. +Note that this setting is ignored for directories, symbolic links, +and other special entries. +
    '''compression-level'''
    +The value is interpreted as a decimal integer specifying the +compression level. +Values between 0 and 9 are supported. +The interpretation of the compression level depends on the chosen +compression method. +
    +
    Format cpio
    +
    +
    '''hdrcharset'''
    +The value is used as a character set name that will be +used when translating file names. +
    +
    Format gnutar
    +
    +
    '''hdrcharset'''
    +The value is used as a character set name that will be +used when translating file, group and user names. +
    +
    Format iso9660 - volume metadata
    +These options are used to set standard ISO9660 metadata. +
    +
    '''abstract-file'''=''filename''
    +The file with the specified name will be identified in the ISO9660 metadata +as holding the abstract for this volume. +Default: none. +
    '''application-id'''=''filename''
    +The file with the specified name will be identified in the ISO9660 metadata +as holding the application identifier for this volume. +Default: none. +
    '''biblio-file'''=''filename''
    +The file with the specified name will be identified in the ISO9660 metadata +as holding the bibliography for this volume. +Default: none. +
    '''copyright-file'''=''filename''
    +The file with the specified name will be identified in the ISO9660 metadata +as holding the copyright for this volume. +Default: none. +
    '''publisher'''=''filename''
    +The file with the specified name will be identified in the ISO9660 metadata +as holding the publisher information for this volume. +Default: none. +
    '''volume-id'''=''string''
    +The specified string will be used as the Volume Identifier in the ISO9660 metadata. +It is limited to 32 bytes. +Default: none. +
    +
    Format iso9660 - boot support
    +These options are used to make an ISO9660 image that can be directly +booted on various systems. +
    +
    '''boot'''=''filename''
    +The file matching this name will be used as the El Torito boot image file. +
    '''boot-catalog'''=''name''
    +The name that will be used for the El Torito boot catalog. +Default: +''boot.catalog'' +
    '''boot-info-table'''
    +The boot image file provided by the +'''boot'''=''filename'' +option will be edited with appropriate boot information in bytes 8 through 64. +Default: disabled +
    '''boot-load-seg'''=''hexadecimal-number''
    +The load segment for a no-emulation boot image. +
    '''boot-load-size'''=''decimal-number''
    +The number of "virtual" 512-byte sectors to be loaded from a no-emulation boot image. +Some very old BIOSes can only load very small images, setting this +value to 4 will often allow such BIOSes to load the first part of +the boot image (which will then need to be intelligent enough to +load the rest of itself). +This should not be needed unless you are trying to support systems with very old BIOSes. +This defaults to the full size of the image. +
    '''boot-type'''=''value''
    +Specifies the boot semantics used by the El Torito boot image: +If the +''value'' +is +'''fd''', +then the boot image is assumed to be a bootable floppy image. +If the +''value'' +is +'''hd''', +then the boot image is assumed to be a bootable hard disk image. +If the +''value'' +is +'''no-emulation''', +the boot image is used without floppy or hard disk emulation. +If the boot image is exactly 1.2MB, 1.44MB, or 2.88MB, then +the default is +'''fd''', +otherwise the default is +'''no-emulation'''. +
    +
    Format iso9660 - filename and size extensions
    +Various extensions to the base ISO9660 format. +
    +
    '''allow-ldots'''
    +If enabled, allows filenames to begin with a leading period. +If disabled, filenames that begin with a leading period will have +that period replaced by an underscore character in the standard ISO9660 +namespace. +This does not impact names stored in the Rockridge or Joliet extension area. +Default: disabled. +
    '''allow-lowercase'''
    +If enabled, allows filenames to contain lowercase characters. +If disabled, filenames will be forced to uppercase. +This does not impact names stored in the Rockridge or Joliet extension area. +Default: disabled. +
    '''allow-multidot'''
    +If enabled, allows filenames to contain multiple period characters, in violation of the ISO9660 specification. +If disabled, additional periods will be converted to underscore characters. +This does not impact names stored in the Rockridge or Joliet extension area. +Default: disabled. +
    '''allow-period'''
    +If enabled, allows filenames to contain trailing period characters, in violation of the ISO9660 specification. +If disabled, trailing periods will be converted to underscore characters. +This does not impact names stored in the Rockridge or Joliet extension area. +Default: disabled. +
    '''allow-pvd-lowercase'''
    +If enabled, the Primary Volume Descriptor may contain lowercase ASCII characters, in violation of the ISO9660 specification. +If disabled, characters will be converted to uppercase ASCII. +Default: disabled. +
    '''allow-sharp-tilde'''
    +If enabled, sharp and tilde characters will be permitted in filenames, in violation if the ISO9660 specification. +If disabled, such characters will be converted to underscore characters. +Default: disabled. +
    '''allow-vernum'''
    +If enabled, version numbers will be included with files. +If disabled, version numbers will be suppressed, in violation of the ISO9660 standard. +This does not impact names stored in the Rockridge or Joliet extension area. +Default: enabled. +
    '''iso-level'''
    +This enables support for file size and file name extensions in the +core ISO9660 area. +The name extensions specified here do not affect the names stored in the Rockridge or Joliet extension areas. +
    +
    '''iso-level=1'''
    +The most compliant form of ISO9660 image. +Filenames are limited to 8.3 uppercase format, +directory names are limited to 8 uppercase characters, +files are limited to 4 GiB, +the complete ISO9660 image cannot exceed 4 GiB. +
    '''iso-level=2'''
    +Filenames are limited to 30 uppercase characters with a 30-character extension, +directory names are limited to 30 characters, +files are limited to 4 GiB. +
    '''iso-level=3'''
    +As with +'''iso-level=2''', +except that files may exceed 4 GiB. +
    '''iso-level=4'''
    +As with +'''iso-level=3''', +except that filenames may be up to 193 characters +and may include arbitrary 8-bit characters. +
    +
    '''joliet'''
    +Microsoft's Joliet extensions store a completely separate set of directory information about each file. +In particular, this information includes Unicode filenames of up to 255 characters. +Default: enabled. +
    '''limit-depth'''
    +If enabled, libarchive will use directory relocation records to ensure that +no pathname exceeds the ISO9660 limit of 8 directory levels. +If disabled, no relocation will occur. +Default: enabled. +
    '''limit-dirs'''
    +If enabled, libarchive will cause an error if there are more than +65536 directories. +If disabled, there is no limit on the number of directories. +Default: enabled +
    '''pad'''
    +If enabled, 300 kiB of zero bytes will be appended to the end of the archive. +Default: enabled +
    '''relaxed-filenames'''
    +If enabled, all 7-bit ASCII characters are permitted in filenames +(except lowercase characters unless +'''allow-lowercase''' +is also specified). +This violates ISO9660 standards. +This does not impact names stored in the Rockridge or Joliet extension area. +Default: disabled. +
    '''rockridge'''
    +The Rockridge extensions store an additional set of POSIX-style file +information with each file, including mtime, atime, ctime, permissions, +and long filenames with arbitrary 8-bit characters. +These extensions also support symbolic links and other POSIX file types. +Default: enabled. +
    +
    Format iso9660 - zisofs support
    +The zisofs extensions permit each file to be independently compressed +using a gzip-compatible compression. +This can provide significant size savings, but requires the reading +system to have support for these extensions. +These extensions are disabled by default. +
    +
    '''compression-level'''=number
    +The compression level used by the deflate compressor. +Ranges from 0 (least effort) to 9 (most effort). +Default: 6 +
    '''zisofs'''
    +Synonym for +'''zisofs=direct'''. +
    '''zisofs=direct'''
    +Compress each file in the archive. +Unlike +'''zisofs=indirect''', +this is handled entirely within libarchive and does not require a +separate utility. +For best results, libarchive tests each file and will store +the file uncompressed if the compression does not actually save any space. +In particular, files under 2k will never be compressed. +Note that boot image files are never compressed. +
    '''zisofs=indirect'''
    +Recognizes files that have already been compressed with the +'''mkzftree''' +utility and sets up the necessary file metadata so that +readers will correctly identify these as zisofs-compressed files. +
    '''zisofs-exclude'''=''filename''
    +Specifies a filename that should not be compressed when using +'''zisofs=direct'''. +This option can be provided multiple times to suppress compression +on many files. +
    +
    Format mtree
    +
    +
    '''cksum''', '''device''', '''flags''', '''gid''', '''gname''', '''indent''', '''link''', '''md5''', '''mode''', '''nlink''', '''rmd160''', '''sha1''', '''sha256''', '''sha384''', '''sha512''', '''size''', '''time''', '''uid''', '''uname'''
    +Enable a particular keyword in the mtree output. +Prefix with an exclamation mark to disable the corresponding keyword. +The default is equivalent to +"device, flags, gid, gname, link, mode, nlink, size, time, type, uid, uname". +
    '''all'''
    +Enables all of the above keywords. +
    '''use-set'''
    +Enables generation of +'''/set''' +lines that specify default values for the following files and/or directories. +
    '''indent'''
    +XXX needs explanation XXX +
    +
    Format newc
    +
    +
    '''hdrcharset'''
    +The value is used as a character set name that will be +used when translating file names. +
    +
    Format pax
    +
    +
    '''hdrcharset'''
    +The value is used as a character set name that will be +used when translating file, group and user names. +The value is one of +"BINARY" +or +"UTF-8". +With +"BINARY" +there is no character conversion, with +"UTF-8" +names are converted to UTF-8. +
    '''xattrheader'''
    +When storing extended attributes, this option configures which +headers should be written. The value is one of +"all", +"LIBARCHIVE", +or +"SCHILY". +By default, both +"LIBARCHIVE.xattr" +and +"SCHILY.xattr" +headers are written. +
    +
    Format ustar
    +
    +
    '''hdrcharset'''
    +The value is used as a character set name that will be +used when translating file, group and user names. +
    +
    Format v7tar
    +
    +
    '''hdrcharset'''
    +The value is used as a character set name that will be +used when translating file, group and user names. +
    +
    Format warc
    +
    +
    '''omit-warcinfo'''
    +Set to +"true" +to disable output of the warcinfo record. +
    +
    Format xar
    +
    +
    '''checksum'''=''type''
    +Use +''type'' +as file checksum method. +Supported values are +"none", +"md5", +and +"sha1" +(default.) +
    '''compression'''=''type''
    +Use +''type'' +as compression method. +Supported values are +"none", +"bzip2", +"gzip" +(default,) +"lzma" +and +"xz". +
    '''compression_level'''
    +The value is a decimal integer from 1 to 9 specifying the compression level. +
    '''toc-checksum'''=''type''
    +Use +''type'' +as table of contents checksum method. +Supported values are +"none", +"md5" +and +"sha1" +(default.) +
    +
    Format zip
    +
    +
    '''compression'''
    +The value is either +"store" +or +"deflate" +to indicate how the following entries should be compressed. +Note that this setting is ignored for directories, symbolic links, +and other special entries. +
    '''compression-level'''
    +The value is interpreted as a decimal integer specifying the +compression level. +Values between 0 and 9 are supported. +A compression level of 0 switches the compression method to +"store", +other values will enable +"deflate" +compression with the given level. +
    '''encryption'''
    +Enable encryption using traditional zip encryption. +
    '''encryption'''=''type''
    +Use +''type'' +as encryption type. +Supported values are +"zipcrypt" +(traditional zip encryption,) +"aes128" +(WinZip AES-128 encryption) +and +"aes256" +(WinZip AES-256 encryption.) +
    '''experimental'''
    +This boolean option enables or disables experimental Zip features +that may not be compatible with other Zip implementations. +
    '''fakecrc32'''
    +This boolean option disables CRC calculations. +All CRC fields are set to zero. +It should not be used except for testing purposes. +
    '''hdrcharset'''
    +The value is used as a character set name that will be +used when translating file names. +
    '''zip64'''
    +Zip64 extensions provide additional file size information +for entries larger than 4 GiB. +They also provide extended file offset and archive size information +when archives exceed 4 GiB. +By default, the Zip writer selectively enables these extensions only as needed. +In particular, if the file size is unknown, the Zip writer will +include Zip64 extensions to guard against the possibility that the +file might be larger than 4 GiB. + +Setting this boolean option will force the writer to use Zip64 extensions +even for small files that would not otherwise require them. +This is primarily useful for testing. + +Disabling this option with +'''!zip64''' +will force the Zip writer to avoid Zip64 extensions: +It will reject files with size greater than 4 GiB, +it will reject any new entries once the total archive size reaches 4 GiB, +and it will not use Zip64 extensions for files with unknown size. +In particular, this can improve compatibility when generating archives +where the entry sizes are not known in advance. +
    +
    +== EXAMPLES == +The following example creates an archive write handle to +create a gzip-compressed ISO9660 format image. +The two options here specify that the ISO9660 archive will use +''kernel.img'' +as the boot image for El Torito booting, and that the gzip +compressor should use the maximum compression level. +```text +a = archive_write_new(); +archive_write_add_filter_gzip(a); +archive_write_set_format_iso9660(a); +archive_write_set_options(a, "boot=kernel.img,compression=9"); +archive_write_open_filename(a, filename, blocksize); +``` +== ERRORS == +More detailed error codes and textual descriptions are available from the +'''archive_errno'''() +and +'''archive_error_string'''() +functions. +== SEE ALSO == +[[ManPageBsdtar1]], +[[ManPagerchiveeadetptions3]], +[[ManPagerchiverite3]], +[[ManPageibarchive3]] +== HISTORY == +The +'''libarchive''' +library first appeared in +FreeBSD 5.3. +== AUTHORS == +The options support for libarchive was originally implemented by +Michihiro NAKAJIMA. +== BUGS == diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteSetPassphrase3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteSetPassphrase3.wiki new file mode 100644 index 0000000..f61d67c --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageArchiveWriteSetPassphrase3.wiki @@ -0,0 +1,42 @@ +ARCHIVE_WRITE_SET_PASSPHRASE(3) manual page +== NAME == +'''archive_write_set_passphrase''', +'''archive_write_set_passphrase_callback''' +- functions for writing encrypted archives +== LIBRARY == +Streaming Archive Library (libarchive, -larchive) +== SYNOPSIS == +'''#include ''' +
    +''int'' +
    +'''archive_write_set_passphrase'''(''struct archive *'', ''const char *passphrase''); +
    +''int'' +
    +'''archive_write_set_passphrase_callback'''(''struct archive *'', ''void *client_data'', ''archive_passphrase_callback *''); +== DESCRIPTION == +
    +
    '''archive_write_set_passphrase'''()
    +Set a passphrase for writing an encrypted archive. +If +''passphrase'' +is +NULL +or empty, this function will do nothing and +'''ARCHIVE_FAILED''' +will be returned. +Otherwise, +'''ARCHIVE_OK''' +will be returned. +
    '''archive_write_set_passphrase_callback'''()
    +Register a callback function that will be invoked to get a passphrase +for encryption if the passphrase was not set by the +'''archive_write_set_passphrase'''() +function. +
    +== SEE ALSO == +[[ManPageBsdtar1]], +[[ManPagerchiverite3]], +[[ManPagerchiveriteetptions3]], +[[ManPageibarchive3]] diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageBsdcpio1.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageBsdcpio1.wiki new file mode 100644 index 0000000..fce973e --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageBsdcpio1.wiki @@ -0,0 +1,416 @@ +CPIO(1) manual page +== NAME == +'''cpio''' +- copy files to and from archives +== SYNOPSIS == +
    +'''cpio''' +-i +[''options''] +[''pattern'' ...] +[''<'' archive] +
    +'''cpio''' +-o +[''options''] +''<'' name-list +[''>'' archive] +
    +'''cpio''' +-p +[''options''] +''dest-dir'' +''<'' name-list +== DESCRIPTION == +'''cpio''' +copies files between archives and directories. +This implementation can extract from tar, pax, cpio, zip, jar, ar, +and ISO 9660 cdrom images and can create tar, pax, cpio, ar, +and shar archives. + +The first option to +'''cpio''' +is a mode indicator from the following list: +
    +
    -i
    +Input. +Read an archive from standard input (unless overridden) and extract the +contents to disk or (if the +-t +option is specified) +list the contents to standard output. +If one or more file patterns are specified, only files matching +one of the patterns will be extracted. +
    -o
    +Output. +Read a list of filenames from standard input and produce a new archive +on standard output (unless overridden) containing the specified items. +
    -p
    +Pass-through. +Read a list of filenames from standard input and copy the files to the +specified directory. +
    +== OPTIONS == +Unless specifically stated otherwise, options are applicable in +all operating modes. +
    +
    -0, --null
    +Read filenames separated by NUL characters instead of newlines. +This is necessary if any of the filenames being read might contain newlines. +
    -A
    +(o mode only) +Append to the specified archive. +(Not yet implemented.) +
    -a
    +(o and p modes) +Reset access times on files after they are read. +
    -B
    +(o mode only) +Block output to records of 5120 bytes. +
    -C ''size''
    +(o mode only) +Block output to records of +''size'' +bytes. +
    -c
    +(o mode only) +Use the old POSIX portable character format. +Equivalent to +--format ''odc''. +
    -d, --make-directories
    +(i and p modes) +Create directories as necessary. +
    -E ''file''
    +(i mode only) +Read list of file name patterns from +''file'' +to list and extract. +
    -F ''file'', --file ''file''
    +Read archive from or write archive to +''file''. +
    -f ''pattern''
    +(i mode only) +Ignore files that match +''pattern''. +
    -H ''format'', --format ''format''
    +(o mode only) +Produce the output archive in the specified format. +Supported formats include: + +
    +
    ''cpio''
    +Synonym for +''odc''. +
    ''newc''
    +The SVR4 portable cpio format. +
    ''odc''
    +The old POSIX.1 portable octet-oriented cpio format. +
    ''pax''
    +The POSIX.1 pax format, an extension of the ustar format. +
    ''ustar''
    +The POSIX.1 tar format. +
    + +The default format is +''odc''. +See +[[ManPageibarchiveormats5]] +for more complete information about the +formats currently supported by the underlying +[[ManPageibarchive3]] +library. +
    -h, --help
    +Print usage information. +
    -I ''file''
    +Read archive from +''file''. +
    -i, --extract
    +Input mode. +See above for description. +
    --insecure
    +(i and p mode only) +Disable security checks during extraction or copying. +This allows extraction via symbolic links, absolute paths, +and path names containing +Sq .. +in the name. +
    -J, --xz
    +(o mode only) +Compress the file with xz-compatible compression before writing it. +In input mode, this option is ignored; xz compression is recognized +automatically on input. +
    -j
    +Synonym for +-y. +
    -L
    +(o and p modes) +All symbolic links will be followed. +Normally, symbolic links are archived and copied as symbolic links. +With this option, the target of the link will be archived or copied instead. +
    -l, --link
    +(p mode only) +Create links from the target directory to the original files, +instead of copying. +
    --lrzip
    +(o mode only) +Compress the resulting archive with +[[lrzip(1)|http://www.freebsd.org/cgi/man.cgi?query=lrzip&sektion=1]]. +In input mode, this option is ignored. +
    --lz4
    +(o mode only) +Compress the archive with lz4-compatible compression before writing it. +In input mode, this option is ignored; lz4 compression is recognized +automatically on input. +
    --zstd
    +(o mode only) +Compress the archive with zstd-compatible compression before writing it. +In input mode, this option is ignored; zstd compression is recognized +automatically on input. +
    --lzma
    +(o mode only) +Compress the file with lzma-compatible compression before writing it. +In input mode, this option is ignored; lzma compression is recognized +automatically on input. +
    --lzop
    +(o mode only) +Compress the resulting archive with +[[lzop(1)|http://www.freebsd.org/cgi/man.cgi?query=lzop&sektion=1]]. +In input mode, this option is ignored. +
    --passphrase ''passphrase''
    +The +''passphrase'' +is used to extract or create an encrypted archive. +Currently, zip is only a format that +'''cpio''' +can handle encrypted archives. +You shouldn't use this option unless you realize how insecure +use of this option is. +
    -m, --preserve-modification-time
    +(i and p modes) +Set file modification time on created files to match +those in the source. +
    -n, --numeric-uid-gid
    +(i mode, only with +-t) +Display numeric uid and gid. +By default, +'''cpio''' +displays the user and group names when they are provided in the +archive, or looks up the user and group names in the system +password database. +
    --no-preserve-owner
    +(i mode only) +Do not attempt to restore file ownership. +This is the default when run by non-root users. +
    -O ''file''
    +Write archive to +''file''. +
    -o, --create
    +Output mode. +See above for description. +
    -p, --pass-through
    +Pass-through mode. +See above for description. +
    --preserve-owner
    +(i mode only) +Restore file ownership. +This is the default when run by the root user. +
    --quiet
    +Suppress unnecessary messages. +
    -R [user][:][group], --owner [user][:][group]
    +Set the owner and/or group on files in the output. +If group is specified with no user +(for example, +-R '':wheel'') +then the group will be set but not the user. +If the user is specified with a trailing colon and no group +(for example, +-R ''root:'') +then the group will be set to the user's default group. +If the user is specified with no trailing colon, then +the user will be set but not the group. +In +-i +and +-p +modes, this option can only be used by the super-user. +(For compatibility, a period can be used in place of the colon.) +
    -r
    +(All modes.) +Rename files interactively. +For each file, a prompt is written to +''/dev/tty'' +containing the name of the file and a line is read from +''/dev/tty''. +If the line read is blank, the file is skipped. +If the line contains a single period, the file is processed normally. +Otherwise, the line is taken to be the new name of the file. +
    -t, --list
    +(i mode only) +List the contents of the archive to stdout; +do not restore the contents to disk. +
    -u, --unconditional
    +(i and p modes) +Unconditionally overwrite existing files. +Ordinarily, an older file will not overwrite a newer file on disk. +
    -V, --dot
    +Print a dot to stderr for each file as it is processed. +Superseded by +-v. +
    -v, --verbose
    +Print the name of each file to stderr as it is processed. +With +-t, +provide a detailed listing of each file. +
    --version
    +Print the program version information and exit. +
    -y
    +(o mode only) +Compress the archive with bzip2-compatible compression before writing it. +In input mode, this option is ignored; +bzip2 compression is recognized automatically on input. +
    -Z
    +(o mode only) +Compress the archive with compress-compatible compression before writing it. +In input mode, this option is ignored; +compression is recognized automatically on input. +
    -z
    +(o mode only) +Compress the archive with gzip-compatible compression before writing it. +In input mode, this option is ignored; +gzip compression is recognized automatically on input. +
    +== EXIT STATUS == +The '''cpio''' utility exits 0 on success, and >0 if an error occurs. +== ENVIRONMENT == +The following environment variables affect the execution of +'''cpio''': +
    +
    '''LANG'''
    +The locale to use. +See +[[environ(7)|http://www.freebsd.org/cgi/man.cgi?query=environ&sektion=7]] +for more information. +
    '''TZ'''
    +The timezone to use when displaying dates. +See +[[environ(7)|http://www.freebsd.org/cgi/man.cgi?query=environ&sektion=7]] +for more information. +
    +== EXAMPLES == +The +'''cpio''' +command is traditionally used to copy file hierarchies in conjunction +with the +[[find(1)|http://www.freebsd.org/cgi/man.cgi?query=find&sektion=1]] +command. +The first example here simply copies all files from +''src'' +to +''dest'': +```text +find src | cpio -pmud dest +``` + +By carefully selecting options to the +[[find(1)|http://www.freebsd.org/cgi/man.cgi?query=find&sektion=1]] +command and combining it with other standard utilities, +it is possible to exercise very fine control over which files are copied. +This next example copies files from +''src'' +to +''dest'' +that are more than 2 days old and whose names match a particular pattern: +```text +find src -mtime +2 | grep foo[bar] | cpio -pdmu dest +``` + +This example copies files from +''src'' +to +''dest'' +that are more than 2 days old and which contain the word +"foobar": +```text +find src -mtime +2 | xargs grep -l foobar | cpio -pdmu dest +``` +== COMPATIBILITY == +The mode options i, o, and p and the options +a, B, c, d, f, l, m, r, t, u, and v comply with SUSv2. + +The old POSIX.1 standard specified that only +-i, +-o, +and +-p +were interpreted as command-line options. +Each took a single argument of a list of modifier +characters. +For example, the standard syntax allows +-imu +but does not support +-miu +or +-i -m -u, +since +''m'' +and +''u'' +are only modifiers to +-i, +they are not command-line options in their own right. +The syntax supported by this implementation is backwards-compatible +with the standard. +For best compatibility, scripts should limit themselves to the +standard syntax. +== SEE ALSO == +[[bzip2(1)|http://www.freebsd.org/cgi/man.cgi?query=bzip2&sektion=1]], +[[gzip(1)|http://www.freebsd.org/cgi/man.cgi?query=gzip&sektion=1]], +[[mt(1)|http://www.freebsd.org/cgi/man.cgi?query=mt&sektion=1]], +[[pax(1)|http://www.freebsd.org/cgi/man.cgi?query=pax&sektion=1]], +[[ManPageBsdtar1]], +[[ManPageibarchive3]], +[[ManPageCpio5]], +[[ManPageibarchiveormats5]], +[[ManPageTar5]] +== STANDARDS == +There is no current POSIX standard for the cpio command; it appeared +in +ISO/IEC 9945-1:1996 (``POSIX.1'') +but was dropped from +IEEE Std 1003.1-2001 (``POSIX.1''). + +The cpio, ustar, and pax interchange file formats are defined by +IEEE Std 1003.1-2001 (``POSIX.1'') +for the pax command. +== HISTORY == +The original +'''cpio''' +and +'''find''' +utilities were written by Dick Haight +while working in AT&T's Unix Support Group. +They first appeared in 1977 in PWB/UNIX 1.0, the +"Programmer's Work Bench" +system developed for use within AT&T. +They were first released outside of AT&T as part of System III Unix in 1981. +As a result, +'''cpio''' +actually predates +'''tar''', +even though it was not well-known outside of AT&T until some time later. + +This is a complete re-implementation based on the +[[ManPageibarchive3]] +library. +== BUGS == +The cpio archive format has several basic limitations: +It does not store user and group names, only numbers. +As a result, it cannot be reliably used to transfer +files between systems with dissimilar user and group numbering. +Older cpio formats limit the user and group numbers to +16 or 18 bits, which is insufficient for modern systems. +The cpio archive formats cannot support files over 4 gigabytes, +except for the +"odc" +variant, which can support files up to 8 gigabytes. diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageBsdtar1.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageBsdtar1.wiki new file mode 100644 index 0000000..8b35562 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageBsdtar1.wiki @@ -0,0 +1,1339 @@ +TAR(1) manual page +== NAME == +'''tar''' +- manipulate tape archives +== SYNOPSIS == +
    +'''tar''' +[''bundled-flags'' <args>] +[<''file''> | <''pattern''> ...] +
    +'''tar''' +{-c} +[''options''] +[''files'' | ''directories''] +
    +'''tar''' +{-r | -u} +-f ''archive-file'' +[''options''] +[''files'' | ''directories''] +
    +'''tar''' +{-t | -x} +[''options''] +[''patterns''] +== DESCRIPTION == +'''tar''' +creates and manipulates streaming archive files. +This implementation can extract from tar, pax, cpio, zip, jar, ar, xar, +rpm, 7-zip, and ISO 9660 cdrom images and can create tar, pax, cpio, ar, zip, +7-zip, and shar archives. + +The first synopsis form shows a +"bundled" +option word. +This usage is provided for compatibility with historical implementations. +See COMPATIBILITY below for details. + +The other synopsis forms show the preferred usage. +The first option to +'''tar''' +is a mode indicator from the following list: +
    +
    -c
    +Create a new archive containing the specified items. +The long option form is +--create. +
    -r
    +Like +-c, +but new entries are appended to the archive. +Note that this only works on uncompressed archives stored in regular files. +The +-f +option is required. +The long option form is +--append. +
    -t
    +List archive contents to stdout. +The long option form is +--list. +
    -u
    +Like +-r, +but new entries are added only if they have a modification date +newer than the corresponding entry in the archive. +Note that this only works on uncompressed archives stored in regular files. +The +-f +option is required. +The long form is +--update. +
    -x
    +Extract to disk from the archive. +If a file with the same name appears more than once in the archive, +each copy will be extracted, with later copies overwriting (replacing) +earlier copies. +The long option form is +--extract. +
    + +In +-c, +-r, +or +-u +mode, each specified file or directory is added to the +archive in the order specified on the command line. +By default, the contents of each directory are also archived. + +In extract or list mode, the entire command line +is read and parsed before the archive is opened. +The pathnames or patterns on the command line indicate +which items in the archive should be processed. +Patterns are shell-style globbing patterns as +documented in +[[tcsh(1)|http://www.freebsd.org/cgi/man.cgi?query=tcsh&sektion=1]]. +== OPTIONS == +Unless specifically stated otherwise, options are applicable in +all operating modes. +
    +
    '''@'''''archive''
    +(c and r modes only) +The specified archive is opened and the entries +in it will be appended to the current archive. +As a simple example, +```text +tar -c -f - newfile @original.tar +``` +writes a new archive to standard output containing a file +''newfile'' +and all of the entries from +''original.tar''. +In contrast, +```text +tar -c -f - newfile original.tar +``` +creates a new archive with only two entries. +Similarly, +```text +tar -czf - --format pax @- +``` +reads an archive from standard input (whose format will be determined +automatically) and converts it into a gzip-compressed +pax-format archive on stdout. +In this way, +'''tar''' +can be used to convert archives from one format to another. +
    -a, --auto-compress
    +(c mode only) +Use the archive suffix to decide a set of the format and +the compressions. +As a simple example, +```text +tar -a -cf archive.tgz source.c source.h +``` +creates a new archive with restricted pax format and gzip compression, +```text +tar -a -cf archive.tar.bz2.uu source.c source.h +``` +creates a new archive with restricted pax format and bzip2 compression +and uuencode compression, +```text +tar -a -cf archive.zip source.c source.h +``` +creates a new archive with zip format, +```text +tar -a -jcf archive.tgz source.c source.h +``` +ignores the +"-j" +option, and creates a new archive with restricted pax format +and gzip compression, +```text +tar -a -jcf archive.xxx source.c source.h +``` +if it is unknown suffix or no suffix, creates a new archive with +restricted pax format and bzip2 compression. +
    --acls
    +(c, r, u, x modes only) +Archive or extract POSIX.1e or NFSv4 ACLs. +This is the reverse of +--no-acls +and the default behavior in c, r, and u modes (except on Mac OS X) or if +'''tar''' +is run in x mode as root. +On Mac OS X this option translates extended ACLs to NFSv4 ACLs. +To store extended ACLs the +--mac-metadata +option is preferred. +
    -B, --read-full-blocks
    +Ignored for compatibility with other +[[ManPageBsdtar1]] +implementations. +
    -b ''blocksize'', --block-size ''blocksize''
    +Specify the block size, in 512-byte records, for tape drive I/O. +As a rule, this argument is only needed when reading from or writing +to tape drives, and usually not even then as the default block size of +20 records (10240 bytes) is very common. +
    -C ''directory'', --cd ''directory'', --directory ''directory''
    +In c and r mode, this changes the directory before adding +the following files. +In x mode, change directories after opening the archive +but before extracting entries from the archive. +
    --chroot
    +(x mode only) +'''chroot'''() +to the current directory after processing any +-C +options and before extracting any files. +
    --clear-nochange-fflags
    +(x mode only) +Before removing file system objects to replace them, clear platform-specific +file attributes or file flags that might prevent removal. +
    --exclude ''pattern''
    +Do not process files or directories that match the +specified pattern. +Note that exclusions take precedence over patterns or filenames +specified on the command line. +
    --exclude-vcs
    +Do not process files or directories internally used by the +version control systems +Sq Arch, +Sq Bazaar, +Sq CVS, +Sq Darcs, +Sq Mercurial, +Sq RCS, +Sq SCCS, +Sq SVN +and +Sq git. +
    --fflags
    +(c, r, u, x modes only) +Archive or extract platform-specific file attributes or file flags. +This is the reverse of +--no-fflags +and the default behavior in c, r, and u modes or if +'''tar''' +is run in x mode as root. +
    --format ''format''
    +(c, r, u mode only) +Use the specified format for the created archive. +Supported formats include +"cpio", +"pax", +"shar", +and +"ustar". +Other formats may also be supported; see +[[ManPageibarchiveormats5]] +for more information about currently-supported formats. +In r and u modes, when extending an existing archive, the format specified +here must be compatible with the format of the existing archive on disk. +
    -f ''file'', --file ''file''
    +Read the archive from or write the archive to the specified file. +The filename can be +''-'' +for standard input or standard output. +The default varies by system; +on +FreeBSD, +the default is +''/dev/sa0''; +on Linux, the default is +''/dev/st0''. +
    --gid ''id''
    +Use the provided group id number. +On extract, this overrides the group id in the archive; +the group name in the archive will be ignored. +On create, this overrides the group id read from disk; +if +--gname +is not also specified, the group name will be set to +match the group id. +
    --gname ''name''
    +Use the provided group name. +On extract, this overrides the group name in the archive; +if the provided group name does not exist on the system, +the group id +(from the archive or from the +--gid +option) +will be used instead. +On create, this sets the group name that will be stored +in the archive; +the name will not be verified against the system group database. +
    -H
    +(c and r modes only) +Symbolic links named on the command line will be followed; the +target of the link will be archived, not the link itself. +
    -h
    +(c and r modes only) +Synonym for +-L. +
    -I
    +Synonym for +-T. +
    --help
    +Show usage. +
    --hfsCompression
    +(x mode only) +Mac OS X specific (v10.6 or later). Compress extracted regular files with HFS+ +compression. +
    --ignore-zeros
    +An alias of +--options '''read_concatenated_archives''' +for compatibility with GNU tar. +
    --include ''pattern''
    +Process only files or directories that match the specified pattern. +Note that exclusions specified with +--exclude +take precedence over inclusions. +If no inclusions are explicitly specified, all entries are processed by +default. +The +--include +option is especially useful when filtering archives. +For example, the command +```text +tar -c -f new.tar --include='*foo*' @old.tgz +``` +creates a new archive +''new.tar'' +containing only the entries from +''old.tgz'' +containing the string +Sq foo. +
    -J, --xz
    +(c mode only) +Compress the resulting archive with +[[xz(1)|http://www.freebsd.org/cgi/man.cgi?query=xz&sektion=1]]. +In extract or list modes, this option is ignored. +Note that this +'''tar''' +implementation recognizes XZ compression automatically when reading archives. +
    -j, --bzip, --bzip2, --bunzip2
    +(c mode only) +Compress the resulting archive with +[[bzip2(1)|http://www.freebsd.org/cgi/man.cgi?query=bzip2&sektion=1]]. +In extract or list modes, this option is ignored. +Note that this +'''tar''' +implementation recognizes bzip2 compression automatically when reading +archives. +
    -k, --keep-old-files
    +(x mode only) +Do not overwrite existing files. +In particular, if a file appears more than once in an archive, +later copies will not overwrite earlier copies. +
    --keep-newer-files
    +(x mode only) +Do not overwrite existing files that are newer than the +versions appearing in the archive being extracted. +
    -L, --dereference
    +(c and r modes only) +All symbolic links will be followed. +Normally, symbolic links are archived as such. +With this option, the target of the link will be archived instead. +
    -l, --check-links
    +(c and r modes only) +Issue a warning message unless all links to each file are archived. +
    --lrzip
    +(c mode only) +Compress the resulting archive with +[[lrzip(1)|http://www.freebsd.org/cgi/man.cgi?query=lrzip&sektion=1]]. +In extract or list modes, this option is ignored. +Note that this +'''tar''' +implementation recognizes lrzip compression automatically when reading +archives. +
    --lz4
    +(c mode only) +Compress the archive with lz4-compatible compression before writing it. +In extract or list modes, this option is ignored. +Note that this +'''tar''' +implementation recognizes lz4 compression automatically when reading archives. +
    --zstd
    +(c mode only) +Compress the archive with zstd-compatible compression before writing it. +In extract or list modes, this option is ignored. +Note that this +'''tar''' +implementation recognizes zstd compression automatically when reading archives. +
    --lzma
    +(c mode only) Compress the resulting archive with the original LZMA algorithm. +In extract or list modes, this option is ignored. +Use of this option is discouraged and new archives should be created with +--xz +instead. +Note that this +'''tar''' +implementation recognizes LZMA compression automatically when reading archives. +
    --lzop
    +(c mode only) +Compress the resulting archive with +[[lzop(1)|http://www.freebsd.org/cgi/man.cgi?query=lzop&sektion=1]]. +In extract or list modes, this option is ignored. +Note that this +'''tar''' +implementation recognizes LZO compression automatically when reading archives. +
    -m, --modification-time
    +(x mode only) +Do not extract modification time. +By default, the modification time is set to the time stored in the archive. +
    --mac-metadata
    +(c, r, u and x mode only) +Mac OS X specific. +Archive or extract extended ACLs and extended file +attributes using +[[copyfile(3)|http://www.freebsd.org/cgi/man.cgi?query=copyfile&sektion=3]] +in AppleDouble format. +This is the reverse of +--no-mac-metadata. +and the default behavior in c, r, and u modes or if +'''tar''' +is run in x mode as root. +
    -n, --norecurse, --no-recursion
    +Do not operate recursively on the content of directories. +
    --newer ''date''
    +(c, r, u modes only) +Only include files and directories newer than the specified date. +This compares ctime entries. +
    --newer-mtime ''date''
    +(c, r, u modes only) +Like +--newer, +except it compares mtime entries instead of ctime entries. +
    --newer-than ''file''
    +(c, r, u modes only) +Only include files and directories newer than the specified file. +This compares ctime entries. +
    --newer-mtime-than ''file''
    +(c, r, u modes only) +Like +--newer-than, +except it compares mtime entries instead of ctime entries. +
    --nodump
    +(c and r modes only) +Honor the nodump file flag by skipping this file. +
    --nopreserveHFSCompression
    +(x mode only) +Mac OS X specific (v10.6 or later). Do not compress extracted regular files +which were compressed with HFS+ compression before archived. +By default, compress the regular files again with HFS+ compression. +
    --null
    +(use with +-I +or +-T) +Filenames or patterns are separated by null characters, +not by newlines. +This is often used to read filenames output by the +-print0 +option to +[[find(1)|http://www.freebsd.org/cgi/man.cgi?query=find&sektion=1]]. +
    --no-acls
    +(c, r, u, x modes only) +Do not archive or extract POSIX.1e or NFSv4 ACLs. +This is the reverse of +--acls +and the default behavior if +'''tar''' +is run as non-root in x mode (on Mac OS X as any user in c, r, u and x modes). +
    --no-fflags
    +(c, r, u, x modes only) +Do not archive or extract file attributes or file flags. +This is the reverse of +--fflags +and the default behavior if +'''tar''' +is run as non-root in x mode. +
    --no-mac-metadata
    +(x mode only) +Mac OS X specific. +Do not archive or extract ACLs and extended file attributes +using +[[copyfile(3)|http://www.freebsd.org/cgi/man.cgi?query=copyfile&sektion=3]] +in AppleDouble format. +This is the reverse of +--mac-metadata. +and the default behavior if +'''tar''' +is run as non-root in x mode. +
    --no-safe-writes
    +(x mode only) +Do not create temporary files and use +[[rename(2)|http://www.freebsd.org/cgi/man.cgi?query=rename&sektion=2]] +to replace the original ones. +This is the reverse of +--safe-writes. +
    --no-same-owner
    +(x mode only) +Do not extract owner and group IDs. +This is the reverse of +--same-owner +and the default behavior if +'''tar''' +is run as non-root. +
    --no-same-permissions
    +(x mode only) +Do not extract full permissions (SGID, SUID, sticky bit, +file attributes or file flags, extended file attributes and ACLs). +This is the reverse of +-p +and the default behavior if +'''tar''' +is run as non-root. +
    --no-xattrs
    +(c, r, u, x modes only) +Do not archive or extract extended file attributes. +This is the reverse of +--xattrs +and the default behavior if +'''tar''' +is run as non-root in x mode. +
    --numeric-owner
    +This is equivalent to +--uname +Qq +--gname +Qq. +On extract, it causes user and group names in the archive +to be ignored in favor of the numeric user and group ids. +On create, it causes user and group names to not be stored +in the archive. +
    -O, --to-stdout
    +(x, t modes only) +In extract (-x) mode, files will be written to standard out rather than +being extracted to disk. +In list (-t) mode, the file listing will be written to stderr rather than +the usual stdout. +
    -o
    +(x mode) +Use the user and group of the user running the program rather +than those specified in the archive. +Note that this has no significance unless +-p +is specified, and the program is being run by the root user. +In this case, the file modes and flags from +the archive will be restored, but ACLs or owner information in +the archive will be discarded. +
    -o
    +(c, r, u mode) +A synonym for +--format ''ustar'' +
    --older ''date''
    +(c, r, u modes only) +Only include files and directories older than the specified date. +This compares ctime entries. +
    --older-mtime ''date''
    +(c, r, u modes only) +Like +--older, +except it compares mtime entries instead of ctime entries. +
    --older-than ''file''
    +(c, r, u modes only) +Only include files and directories older than the specified file. +This compares ctime entries. +
    --older-mtime-than ''file''
    +(c, r, u modes only) +Like +--older-than, +except it compares mtime entries instead of ctime entries. +
    --one-file-system
    +(c, r, and u modes) +Do not cross mount points. +
    --options ''options''
    +Select optional behaviors for particular modules. +The argument is a text string containing comma-separated +keywords and values. +These are passed to the modules that handle particular +formats to control how those formats will behave. +Each option has one of the following forms: +
    +
    ''key=value''
    +The key will be set to the specified value in every module that supports it. +Modules that do not support this key will ignore it. +
    ''key''
    +The key will be enabled in every module that supports it. +This is equivalent to +''key'''''=1'''. +
    ''!key''
    +The key will be disabled in every module that supports it. +
    ''module:key=value'', ''module:key'', ''module:!key''
    +As above, but the corresponding key and value will be provided +only to modules whose name matches +''module''. +
    + +The complete list of supported modules and keys +for create and append modes is in +[[ManPagerchiveriteetptions3]] +and for extract and list modes in +[[ManPagerchiveeadetptions3]]. + +Examples of supported options: +
    +
    '''iso9660:joliet'''
    +Support Joliet extensions. +This is enabled by default, use +'''!joliet''' +or +'''iso9660:!joliet''' +to disable. +
    '''iso9660:rockridge'''
    +Support Rock Ridge extensions. +This is enabled by default, use +'''!rockridge''' +or +'''iso9660:!rockridge''' +to disable. +
    '''gzip:compression-level'''
    +A decimal integer from 1 to 9 specifying the gzip compression level. +
    '''gzip:timestamp'''
    +Store timestamp. +This is enabled by default, use +'''!timestamp''' +or +'''gzip:!timestamp''' +to disable. +
    '''lrzip:compression'''=''type''
    +Use +''type'' +as compression method. +Supported values are bzip2, gzip, lzo (ultra fast), +and zpaq (best, extremely slow). +
    '''lrzip:compression-level'''
    +A decimal integer from 1 to 9 specifying the lrzip compression level. +
    '''lz4:compression-level'''
    +A decimal integer from 1 to 9 specifying the lzop compression level. +
    '''lz4:stream-checksum'''
    +Enable stream checksum. +This is by default, use +'''lz4:!stream-checksum''' +to disable. +
    '''lz4:block-checksum'''
    +Enable block checksum (Disabled by default). +
    '''lz4:block-size'''
    +A decimal integer from 4 to 7 specifying the lz4 compression block size +(7 is set by default). +
    '''lz4:block-dependence'''
    +Use the previous block of the block being compressed for +a compression dictionary to improve compression ratio. +
    '''zstd:compression-level'''
    +A decimal integer from 1 to 22 specifying the zstd compression level. +
    '''lzop:compression-level'''
    +A decimal integer from 1 to 9 specifying the lzop compression level. +
    '''xz:compression-level'''
    +A decimal integer from 0 to 9 specifying the xz compression level. +
    '''mtree:'''''keyword''
    +The mtree writer module allows you to specify which mtree keywords +will be included in the output. +Supported keywords include: +'''cksum''', '''device''', '''flags''', '''gid''', '''gname''', '''indent''', +'''link''', '''md5''', '''mode''', '''nlink''', '''rmd160''', '''sha1''', '''sha256''', +'''sha384''', '''sha512''', '''size''', '''time''', '''uid''', '''uname'''. +The default is equivalent to: +"device, flags, gid, gname, link, mode, nlink, size, time, type, uid, uname". +
    '''mtree:all'''
    +Enables all of the above keywords. +You can also use +'''mtree:!all''' +to disable all keywords. +
    '''mtree:use-set'''
    +Enable generation of +'''/set''' +lines in the output. +
    '''mtree:indent'''
    +Produce human-readable output by indenting options and splitting lines +to fit into 80 columns. +
    '''zip:compression'''=''type''
    +Use +''type'' +as compression method. +Supported values are store (uncompressed) and deflate (gzip algorithm). +
    '''zip:encryption'''
    +Enable encryption using traditional zip encryption. +
    '''zip:encryption'''=''type''
    +Use +''type'' +as encryption type. +Supported values are zipcrypt (traditional zip encryption), +aes128 (WinZip AES-128 encryption) and aes256 (WinZip AES-256 encryption). +
    '''read_concatenated_archives'''
    +Ignore zeroed blocks in the archive, which occurs when multiple tar archives +have been concatenated together. +Without this option, only the contents of +the first concatenated archive would be read. +This option is comparable to the +-i, --ignore-zeros +option of GNU tar. +
    +If a provided option is not supported by any module, that +is a fatal error. +
    -P, --absolute-paths
    +Preserve pathnames. +By default, absolute pathnames (those that begin with a / +character) have the leading slash removed both when creating archives +and extracting from them. +Also, +'''tar''' +will refuse to extract archive entries whose pathnames contain +''..'' +or whose target directory would be altered by a symlink. +This option suppresses these behaviors. +
    -p, --insecure, --preserve-permissions
    +(x mode only) +Preserve file permissions. +Attempt to restore the full permissions, including file modes, file attributes +or file flags, extended file attributes and ACLs, if available, for each item +extracted from the archive. +This is the reverse of +--no-same-permissions +and the default if +'''tar''' +is being run as root. +It can be partially overridden by also specifying +--no-acls, +--no-fflags, +--no-mac-metadata +or +--no-xattrs. +
    --passphrase ''passphrase''
    +The +''passphrase'' +is used to extract or create an encrypted archive. +Currently, zip is the only supported format that supports encryption. +You shouldn't use this option unless you realize how insecure +use of this option is. +
    --posix
    +(c, r, u mode only) +Synonym for +--format ''pax'' +
    -q, --fast-read
    +(x and t mode only) +Extract or list only the first archive entry that matches each pattern +or filename operand. +Exit as soon as each specified pattern or filename has been matched. +By default, the archive is always read to the very end, since +there can be multiple entries with the same name and, by convention, +later entries overwrite earlier entries. +This option is provided as a performance optimization. +
    -S
    +(x mode only) +Extract files as sparse files. +For every block on disk, check first if it contains only NULL bytes and seek +over it otherwise. +This works similar to the conv=sparse option of dd. +
    -s ''pattern''
    +Modify file or archive member names according to +''pattern''. +The pattern has the format +''/old/new/''[ghHprRsS] +where +''old'' +is a basic regular expression, +''new'' +is the replacement string of the matched part, +and the optional trailing letters modify +how the replacement is handled. +If +''old'' +is not matched, the pattern is skipped. +Within +''new'', +~ is substituted with the match, \e1 to \e9 with the content of +the corresponding captured group. +The optional trailing g specifies that matching should continue +after the matched part and stop on the first unmatched pattern. +The optional trailing s specifies that the pattern applies to the value +of symbolic links. +The optional trailing p specifies that after a successful substitution +the original path name and the new path name should be printed to +standard error. +Optional trailing H, R, or S characters suppress substitutions +for hardlink targets, regular filenames, or symlink targets, +respectively. +Optional trailing h, r, or s characters enable substitutions +for hardlink targets, regular filenames, or symlink targets, +respectively. +The default is +''hrs'' +which applies substitutions to all names. +In particular, it is never necessary to specify h, r, or s. +
    --safe-writes
    +(x mode only) +Extract files atomically. +By default +'''tar''' +unlinks the original file with the same name as the extracted file (if it +exists), and then creates it immediately under the same name and writes to +it. +For a short period of time, applications trying to access the file might +not find it, or see incomplete results. +If +--safe-writes +is enabled, +'''tar''' +first creates a unique temporary file, then writes the new contents to +the temporary file, and finally renames the temporary file to its final +name atomically using +[[rename(2)|http://www.freebsd.org/cgi/man.cgi?query=rename&sektion=2]]. +This guarantees that an application accessing the file, will either see +the old contents or the new contents at all times. +
    --same-owner
    +(x mode only) +Extract owner and group IDs. +This is the reverse of +--no-same-owner +and the default behavior if +'''tar''' +is run as root. +
    --strip-components ''count''
    +Remove the specified number of leading path elements. +Pathnames with fewer elements will be silently skipped. +Note that the pathname is edited after checking inclusion/exclusion patterns +but before security checks. +
    -T ''filename'', --files-from ''filename''
    +In x or t mode, +'''tar''' +will read the list of names to be extracted from +''filename''. +In c mode, +'''tar''' +will read names to be archived from +''filename''. +The special name +"-C" +on a line by itself will cause the current directory to be changed to +the directory specified on the following line. +Names are terminated by newlines unless +--null +is specified. +Note that +--null +also disables the special handling of lines containing +"-C". +Note: If you are generating lists of files using +[[find(1)|http://www.freebsd.org/cgi/man.cgi?query=find&sektion=1]], +you probably want to use +-n +as well. +
    --totals
    +(c, r, u modes only) +After archiving all files, print a summary to stderr. +
    -U, --unlink, --unlink-first
    +(x mode only) +Unlink files before creating them. +This can be a minor performance optimization if most files +already exist, but can make things slower if most files +do not already exist. +This flag also causes +'''tar''' +to remove intervening directory symlinks instead of +reporting an error. +See the SECURITY section below for more details. +
    --uid ''id''
    +Use the provided user id number and ignore the user +name from the archive. +On create, if +--uname +is not also specified, the user name will be set to +match the user id. +
    --uname ''name''
    +Use the provided user name. +On extract, this overrides the user name in the archive; +if the provided user name does not exist on the system, +it will be ignored and the user id +(from the archive or from the +--uid +option) +will be used instead. +On create, this sets the user name that will be stored +in the archive; +the name is not verified against the system user database. +
    --use-compress-program ''program''
    +Pipe the input (in x or t mode) or the output (in c mode) through +''program'' +instead of using the builtin compression support. +
    -v, --verbose
    +Produce verbose output. +In create and extract modes, +'''tar''' +will list each file name as it is read from or written to +the archive. +In list mode, +'''tar''' +will produce output similar to that of +[[ls(1)|http://www.freebsd.org/cgi/man.cgi?query=ls&sektion=1]]. +An additional +-v +option will also provide ls-like details in create and extract mode. +
    --version
    +Print version of +'''tar''' +and +'''libarchive''', +and exit. +
    -w, --confirmation, --interactive
    +Ask for confirmation for every action. +
    -X ''filename'', --exclude-from ''filename''
    +Read a list of exclusion patterns from the specified file. +See +--exclude +for more information about the handling of exclusions. +
    --xattrs
    +(c, r, u, x modes only) +Archive or extract extended file attributes. +This is the reverse of +--no-xattrs +and the default behavior in c, r, and u modes or if +'''tar''' +is run in x mode as root. +
    -y
    +(c mode only) +Compress the resulting archive with +[[bzip2(1)|http://www.freebsd.org/cgi/man.cgi?query=bzip2&sektion=1]]. +In extract or list modes, this option is ignored. +Note that this +'''tar''' +implementation recognizes bzip2 compression automatically when reading +archives. +
    -Z, --compress, --uncompress
    +(c mode only) +Compress the resulting archive with +[[compress(1)|http://www.freebsd.org/cgi/man.cgi?query=compress&sektion=1]]. +In extract or list modes, this option is ignored. +Note that this +'''tar''' +implementation recognizes compress compression automatically when reading +archives. +
    -z, --gunzip, --gzip
    +(c mode only) +Compress the resulting archive with +[[gzip(1)|http://www.freebsd.org/cgi/man.cgi?query=gzip&sektion=1]]. +In extract or list modes, this option is ignored. +Note that this +'''tar''' +implementation recognizes gzip compression automatically when reading +archives. +
    +== ENVIRONMENT == +The following environment variables affect the execution of +'''tar''': +
    +
    '''TAR_READER_OPTIONS'''
    +The default options for format readers and compression readers. +The +--options +option overrides this. +
    '''TAR_WRITER_OPTIONS'''
    +The default options for format writers and compression writers. +The +--options +option overrides this. +
    '''LANG'''
    +The locale to use. +See +[[environ(7)|http://www.freebsd.org/cgi/man.cgi?query=environ&sektion=7]] +for more information. +
    '''TAPE'''
    +The default device. +The +-f +option overrides this. +Please see the description of the +-f +option above for more details. +
    '''TZ'''
    +The timezone to use when displaying dates. +See +[[environ(7)|http://www.freebsd.org/cgi/man.cgi?query=environ&sektion=7]] +for more information. +
    +== EXIT STATUS == +The '''tar''' utility exits 0 on success, and >0 if an error occurs. +== EXAMPLES == +The following creates a new archive +called +''file.tar.gz'' +that contains two files +''source.c'' +and +''source.h'': +```text +tar -czf file.tar.gz source.c source.h +``` + +To view a detailed table of contents for this +archive: +```text +tar -tvf file.tar.gz +``` + +To extract all entries from the archive on +the default tape drive: +```text +tar -x +``` + +To examine the contents of an ISO 9660 cdrom image: +```text +tar -tf image.iso +``` + +To move file hierarchies, invoke +'''tar''' +as +```text +tar -cf - -C srcdir . | tar -xpf - -C destdir +``` +or more traditionally +```text +cd srcdir ; tar -cf - . | (cd destdir ; tar -xpf -) +``` + +In create mode, the list of files and directories to be archived +can also include directory change instructions of the form +'''-C'''''foo/baz'' +and archive inclusions of the form +'''@'''''archive-file''. +For example, the command line +```text +tar -c -f new.tar foo1 @old.tgz -C/tmp foo2 +``` +will create a new archive +''new.tar''. +'''tar''' +will read the file +''foo1'' +from the current directory and add it to the output archive. +It will then read each entry from +''old.tgz'' +and add those entries to the output archive. +Finally, it will switch to the +''/tmp'' +directory and add +''foo2'' +to the output archive. + +An input file in +[[ManPageMtree5]] +format can be used to create an output archive with arbitrary ownership, +permissions, or names that differ from existing data on disk: +```text +$ cat input.mtree +#mtree +usr/bin uid=0 gid=0 mode=0755 type=dir +usr/bin/ls uid=0 gid=0 mode=0755 type=file content=myls +$ tar -cvf output.tar @input.mtree +``` + +The +--newer +and +--newer-mtime +switches accept a variety of common date and time specifications, including +"12 Mar 2005 7:14:29pm", +"2005-03-12 19:14", +"5 minutes ago", +and +"19:14 PST May 1". + +The +--options +argument can be used to control various details of archive generation +or reading. +For example, you can generate mtree output which only contains +'''type''', '''time''', +and +'''uid''' +keywords: +```text +tar -cf file.tar --format=mtree --options='!all,type,time,uid' dir +``` +or you can set the compression level used by gzip or xz compression: +```text +tar -czf file.tar --options='compression-level=9'. +``` +For more details, see the explanation of the +'''archive_read_set_options'''() +and +'''archive_write_set_options'''() +API calls that are described in +[[ManPagerchiveead3]] +and +[[ManPagerchiverite3]]. +== COMPATIBILITY == +The bundled-arguments format is supported for compatibility +with historic implementations. +It consists of an initial word (with no leading - character) in which +each character indicates an option. +Arguments follow as separate words. +The order of the arguments must match the order +of the corresponding characters in the bundled command word. +For example, +```text +tar tbf 32 file.tar +``` +specifies three flags +'''t''', +'''b''', +and +'''f'''. +The +'''b''' +and +'''f''' +flags both require arguments, +so there must be two additional items +on the command line. +The +''32'' +is the argument to the +'''b''' +flag, and +''file.tar'' +is the argument to the +'''f''' +flag. + +The mode options c, r, t, u, and x and the options +b, f, l, m, o, v, and w comply with SUSv2. + +For maximum portability, scripts that invoke +'''tar''' +should use the bundled-argument format above, should limit +themselves to the +'''c''', +'''t''', +and +'''x''' +modes, and the +'''b''', +'''f''', +'''m''', +'''v''', +and +'''w''' +options. + +Additional long options are provided to improve compatibility with other +tar implementations. +== SECURITY == +Certain security issues are common to many archiving programs, including +'''tar'''. +In particular, carefully-crafted archives can request that +'''tar''' +extract files to locations outside of the target directory. +This can potentially be used to cause unwitting users to overwrite +files they did not intend to overwrite. +If the archive is being extracted by the superuser, any file +on the system can potentially be overwritten. +There are three ways this can happen. +Although +'''tar''' +has mechanisms to protect against each one, +savvy users should be aware of the implications: +
      +
    • +Archive entries can have absolute pathnames. +By default, +'''tar''' +removes the leading +''/'' +character from filenames before restoring them to guard against this problem. +
    • +Archive entries can have pathnames that include +''..'' +components. +By default, +'''tar''' +will not extract files containing +''..'' +components in their pathname. +
    • +Archive entries can exploit symbolic links to restore +files to other directories. +An archive can restore a symbolic link to another directory, +then use that link to restore a file into that directory. +To guard against this, +'''tar''' +checks each extracted path for symlinks. +If the final path element is a symlink, it will be removed +and replaced with the archive entry. +If +-U +is specified, any intermediate symlink will also be unconditionally removed. +If neither +-U +nor +-P +is specified, +'''tar''' +will refuse to extract the entry. +
    +To protect yourself, you should be wary of any archives that +come from untrusted sources. +You should examine the contents of an archive with +```text +tar -tf filename +``` +before extraction. +You should use the +-k +option to ensure that +'''tar''' +will not overwrite any existing files or the +-U +option to remove any pre-existing files. +You should generally not extract archives while running with super-user +privileges. +Note that the +-P +option to +'''tar''' +disables the security checks above and allows you to extract +an archive while preserving any absolute pathnames, +''..'' +components, or symlinks to other directories. +== SEE ALSO == +[[bzip2(1)|http://www.freebsd.org/cgi/man.cgi?query=bzip2&sektion=1]], +[[compress(1)|http://www.freebsd.org/cgi/man.cgi?query=compress&sektion=1]], +[[ManPageBsdcpio1]], +[[gzip(1)|http://www.freebsd.org/cgi/man.cgi?query=gzip&sektion=1]], +[[mt(1)|http://www.freebsd.org/cgi/man.cgi?query=mt&sektion=1]], +[[pax(1)|http://www.freebsd.org/cgi/man.cgi?query=pax&sektion=1]], +[[shar(1)|http://www.freebsd.org/cgi/man.cgi?query=shar&sektion=1]], +[[xz(1)|http://www.freebsd.org/cgi/man.cgi?query=xz&sektion=1]], +[[ManPageibarchive3]], +[[ManPageibarchiveormats5]], +[[ManPageTar5]] +== STANDARDS == +There is no current POSIX standard for the tar command; it appeared +in +ISO/IEC 9945-1:1996 (``POSIX.1'') +but was dropped from +IEEE Std 1003.1-2001 (``POSIX.1''). +The options supported by this implementation were developed by surveying a +number of existing tar implementations as well as the old POSIX specification +for tar and the current POSIX specification for pax. + +The ustar and pax interchange file formats are defined by +IEEE Std 1003.1-2001 (``POSIX.1'') +for the pax command. +== HISTORY == +A +'''tar''' +command appeared in Seventh Edition Unix, which was released in January, 1979. +There have been numerous other implementations, +many of which extended the file format. +John Gilmore's +'''pdtar''' +public-domain implementation (circa November, 1987) +was quite influential, and formed the basis of GNU tar. +GNU tar was included as the standard system tar +in +FreeBSD +beginning with +FreeBSD 1.0. + +This is a complete re-implementation based on the +[[ManPageibarchive3]] +library. +It was first released with +FreeBSD 5.4 +in May, 2005. +== BUGS == +This program follows +ISO/IEC 9945-1:1996 (``POSIX.1'') +for the definition of the +-l +option. +Note that GNU tar prior to version 1.15 treated +-l +as a synonym for the +--one-file-system +option. + +The +-C ''dir'' +option may differ from historic implementations. + +All archive output is written in correctly-sized blocks, even +if the output is being compressed. +Whether or not the last output block is padded to a full +block size varies depending on the format and the +output device. +For tar and cpio formats, the last block of output is padded +to a full block size if the output is being +written to standard output or to a character or block device such as +a tape drive. +If the output is being written to a regular file, the last block +will not be padded. +Many compressors, including +[[gzip(1)|http://www.freebsd.org/cgi/man.cgi?query=gzip&sektion=1]] +and +[[bzip2(1)|http://www.freebsd.org/cgi/man.cgi?query=bzip2&sektion=1]], +complain about the null padding when decompressing an archive created by +'''tar''', +although they still extract it correctly. + +The compression and decompression is implemented internally, so +there may be insignificant differences between the compressed output +generated by +```text +tar -czf - file +``` +and that generated by +```text +tar -cf - file | gzip +``` + +The default should be to read and write archives to the standard I/O paths, +but tradition (and POSIX) dictates otherwise. + +The +'''r''' +and +'''u''' +modes require that the archive be uncompressed +and located in a regular file on disk. +Other archives can be modified using +'''c''' +mode with the +''@archive-file'' +extension. + +To archive a file called +''@foo'' +or +''-foo'' +you must specify it as +''./@foo'' +or +''./-foo'', +respectively. + +In create mode, a leading +''./'' +is always removed. +A leading +''/'' +is stripped unless the +-P +option is specified. + +There needs to be better support for file selection on both create +and extract. + +There is not yet any support for multi-volume archives. + +Converting between dissimilar archive formats (such as tar and cpio) using the +'''@'''''-'' +convention can cause hard link information to be lost. +(This is a consequence of the incompatible ways that different archive +formats store hardlink information.) diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageCpio5.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageCpio5.wiki new file mode 100644 index 0000000..3835302 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageCpio5.wiki @@ -0,0 +1,297 @@ +CPIO(5) manual page +== NAME == +'''cpio''' +- format of cpio archive files +== DESCRIPTION == +The +'''cpio''' +archive format collects any number of files, directories, and other +file system objects (symbolic links, device nodes, etc.) into a single +stream of bytes. +=== General Format=== +Each file system object in a +'''cpio''' +archive comprises a header record with basic numeric metadata +followed by the full pathname of the entry and the file data. +The header record stores a series of integer values that generally +follow the fields in +''struct'' stat. +(See +[[stat(2)|http://www.freebsd.org/cgi/man.cgi?query=stat&sektion=2]] +for details.) +The variants differ primarily in how they store those integers +(binary, octal, or hexadecimal). +The header is followed by the pathname of the +entry (the length of the pathname is stored in the header) +and any file data. +The end of the archive is indicated by a special record with +the pathname +"TRAILER!!!". +=== PWB format=== +XXX Any documentation of the original PWB/UNIX 1.0 format? XXX +=== Old Binary Format=== +The old binary +'''cpio''' +format stores numbers as 2-byte and 4-byte binary values. +Each entry begins with a header in the following format: +```text +struct header_old_cpio { + unsigned short c_magic; + unsigned short c_dev; + unsigned short c_ino; + unsigned short c_mode; + unsigned short c_uid; + unsigned short c_gid; + unsigned short c_nlink; + unsigned short c_rdev; + unsigned short c_mtime[2]; + unsigned short c_namesize; + unsigned short c_filesize[2]; +}; +``` + +The +''unsigned'' short +fields here are 16-bit integer values; the +''unsigned'' int +fields are 32-bit integer values. +The fields are as follows +
    +
    ''magic''
    +The integer value octal 070707. +This value can be used to determine whether this archive is +written with little-endian or big-endian integers. +
    ''dev'', ''ino''
    +The device and inode numbers from the disk. +These are used by programs that read +'''cpio''' +archives to determine when two entries refer to the same file. +Programs that synthesize +'''cpio''' +archives should be careful to set these to distinct values for each entry. +
    ''mode''
    +The mode specifies both the regular permissions and the file type. +It consists of several bit fields as follows: +
    +
    0170000
    +This masks the file type bits. +
    0140000
    +File type value for sockets. +
    0120000
    +File type value for symbolic links. +For symbolic links, the link body is stored as file data. +
    0100000
    +File type value for regular files. +
    0060000
    +File type value for block special devices. +
    0040000
    +File type value for directories. +
    0020000
    +File type value for character special devices. +
    0010000
    +File type value for named pipes or FIFOs. +
    0004000
    +SUID bit. +
    0002000
    +SGID bit. +
    0001000
    +Sticky bit. +On some systems, this modifies the behavior of executables and/or directories. +
    0000777
    +The lower 9 bits specify read/write/execute permissions +for world, group, and user following standard POSIX conventions. +
    +
    ''uid'', ''gid''
    +The numeric user id and group id of the owner. +
    ''nlink''
    +The number of links to this file. +Directories always have a value of at least two here. +Note that hardlinked files include file data with every copy in the archive. +
    ''rdev''
    +For block special and character special entries, +this field contains the associated device number. +For all other entry types, it should be set to zero by writers +and ignored by readers. +
    ''mtime''
    +Modification time of the file, indicated as the number +of seconds since the start of the epoch, +00:00:00 UTC January 1, 1970. +The four-byte integer is stored with the most-significant 16 bits first +followed by the least-significant 16 bits. +Each of the two 16 bit values are stored in machine-native byte order. +
    ''namesize''
    +The number of bytes in the pathname that follows the header. +This count includes the trailing NUL byte. +
    ''filesize''
    +The size of the file. +Note that this archive format is limited to +four gigabyte file sizes. +See +''mtime'' +above for a description of the storage of four-byte integers. +
    + +The pathname immediately follows the fixed header. +If the +'''namesize''' +is odd, an additional NUL byte is added after the pathname. +The file data is then appended, padded with NUL +bytes to an even length. + +Hardlinked files are not given special treatment; +the full file contents are included with each copy of the +file. +=== Portable ASCII Format=== +Version 2 of the Single UNIX Specification (``SUSv2'') +standardized an ASCII variant that is portable across all +platforms. +It is commonly known as the +"old character" +format or as the +"odc" +format. +It stores the same numeric fields as the old binary format, but +represents them as 6-character or 11-character octal values. +```text +struct cpio_odc_header { + char c_magic[6]; + char c_dev[6]; + char c_ino[6]; + char c_mode[6]; + char c_uid[6]; + char c_gid[6]; + char c_nlink[6]; + char c_rdev[6]; + char c_mtime[11]; + char c_namesize[6]; + char c_filesize[11]; +}; +``` + +The fields are identical to those in the old binary format. +The name and file body follow the fixed header. +Unlike the old binary format, there is no additional padding +after the pathname or file contents. +If the files being archived are themselves entirely ASCII, then +the resulting archive will be entirely ASCII, except for the +NUL byte that terminates the name field. +=== New ASCII Format=== +The "new" ASCII format uses 8-byte hexadecimal fields for +all numbers and separates device numbers into separate fields +for major and minor numbers. +```text +struct cpio_newc_header { + char c_magic[6]; + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; +}; +``` + +Except as specified below, the fields here match those specified +for the old binary format above. +
    +
    ''magic''
    +The string +"070701". +
    ''check''
    +This field is always set to zero by writers and ignored by readers. +See the next section for more details. +
    + +The pathname is followed by NUL bytes so that the total size +of the fixed header plus pathname is a multiple of four. +Likewise, the file data is padded to a multiple of four bytes. +Note that this format supports only 4 gigabyte files (unlike the +older ASCII format, which supports 8 gigabyte files). + +In this format, hardlinked files are handled by setting the +filesize to zero for each entry except the last one that +appears in the archive. +=== New CRC Format=== +The CRC format is identical to the new ASCII format described +in the previous section except that the magic field is set +to +"070702" +and the +''check'' +field is set to the sum of all bytes in the file data. +This sum is computed treating all bytes as unsigned values +and using unsigned arithmetic. +Only the least-significant 32 bits of the sum are stored. +=== HP variants=== +The +'''cpio''' +implementation distributed with HPUX used XXXX but stored +device numbers differently XXX. +=== Other Extensions and Variants=== +Sun Solaris uses additional file types to store extended file +data, including ACLs and extended attributes, as special +entries in cpio archives. + +XXX Others? XXX +== SEE ALSO == +[[ManPageBsdcpio1]], +[[ManPageTar5]] +== STANDARDS == +The +'''cpio''' +utility is no longer a part of POSIX or the Single Unix Standard. +It last appeared in +Version 2 of the Single UNIX Specification (``SUSv2''). +It has been supplanted in subsequent standards by +[[pax(1)|http://www.freebsd.org/cgi/man.cgi?query=pax&sektion=1]]. +The portable ASCII format is currently part of the specification for the +[[pax(1)|http://www.freebsd.org/cgi/man.cgi?query=pax&sektion=1]] +utility. +== HISTORY == +The original cpio utility was written by Dick Haight +while working in AT&T's Unix Support Group. +It appeared in 1977 as part of PWB/UNIX 1.0, the +"Programmer's Work Bench" +derived from +At v6 +that was used internally at AT&T. +Both the old binary and old character formats were in use +by 1980, according to the System III source released +by SCO under their +"Ancient Unix" +license. +The character format was adopted as part of +IEEE Std 1003.1-1988 (``POSIX.1''). +XXX when did "newc" appear? Who invented it? When did HP come out with their variant? When did Sun introduce ACLs and extended attributes? XXX +== BUGS == +The +"CRC" +format is mis-named, as it uses a simple checksum and +not a cyclic redundancy check. + +The old binary format is limited to 16 bits for user id, +group id, device, and inode numbers. +It is limited to 4 gigabyte file sizes. + +The old ASCII format is limited to 18 bits for +the user id, group id, device, and inode numbers. +It is limited to 8 gigabyte file sizes. + +The new ASCII format is limited to 4 gigabyte file sizes. + +None of the cpio formats store user or group names, +which are essential when moving files between systems with +dissimilar user or group numbering. + +Especially when writing older cpio variants, it may be necessary +to map actual device/inode values to synthesized values that +fit the available fields. +With very large filesystems, this may be necessary even for +the newer formats. diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageLibarchive3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageLibarchive3.wiki new file mode 100644 index 0000000..2d7ae34 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageLibarchive3.wiki @@ -0,0 +1,257 @@ +LIBARCHIVE(3) manual page +== NAME == +'''libarchive''' +- functions for reading and writing streaming archives +== OVERVIEW == +The +'''libarchive''' +library provides a flexible interface for reading and writing +archives in various formats such as tar and cpio. +'''libarchive''' +also supports reading and writing archives compressed using +various compression filters such as gzip and bzip2. +The library is inherently stream-oriented; readers serially iterate through +the archive, writers serially add things to the archive. +In particular, note that there is currently no built-in support for +random access nor for in-place modification. + +When reading an archive, the library automatically detects the +format and the compression. +The library currently has read support for: +
      +
    • +old-style tar archives, +
    • +most variants of the POSIX +"ustar" +format, +
    • +the POSIX +"pax interchange" +format, +
    • +GNU-format tar archives, +
    • +most common cpio archive formats, +
    • +ISO9660 CD images (including RockRidge and Joliet extensions), +
    • +Zip archives, +
    • +ar archives (including GNU/SysV and BSD extensions), +
    • +Microsoft CAB archives, +
    • +LHA archives, +
    • +mtree file tree descriptions, +
    • +RAR archives, +
    • +XAR archives. +
    +The library automatically detects archives compressed with +[[gzip(1)|http://www.freebsd.org/cgi/man.cgi?query=gzip&sektion=1]], +[[bzip2(1)|http://www.freebsd.org/cgi/man.cgi?query=bzip2&sektion=1]], +[[xz(1)|http://www.freebsd.org/cgi/man.cgi?query=xz&sektion=1]], +[[lzip(1)|http://www.freebsd.org/cgi/man.cgi?query=lzip&sektion=1]], +or +[[compress(1)|http://www.freebsd.org/cgi/man.cgi?query=compress&sektion=1]] +and decompresses them transparently. +It can similarly detect and decode archives processed with +[[uuencode(1)|http://www.freebsd.org/cgi/man.cgi?query=uuencode&sektion=1]] +or which have an +[[rpm(1)|http://www.freebsd.org/cgi/man.cgi?query=rpm&sektion=1]] +header. + +When writing an archive, you can specify the compression +to be used and the format to use. +The library can write +
      +
    • +POSIX-standard +"ustar" +archives, +
    • +POSIX +"pax interchange format" +archives, +
    • +POSIX octet-oriented cpio archives, +
    • +Zip archive, +
    • +two different variants of shar archives, +
    • +ISO9660 CD images, +
    • +7-Zip archives, +
    • +ar archives, +
    • +mtree file tree descriptions, +
    • +XAR archives. +
    +Pax interchange format is an extension of the tar archive format that +eliminates essentially all of the limitations of historic tar formats +in a standard fashion that is supported +by POSIX-compliant +[[pax(1)|http://www.freebsd.org/cgi/man.cgi?query=pax&sektion=1]] +implementations on many systems as well as several newer implementations of +[[ManPageBsdtar1]]. +Note that the default write format will suppress the pax extended +attributes for most entries; explicitly requesting pax format will +enable those attributes for all entries. + +The read and write APIs are accessed through the +'''archive_read_XXX'''() +functions and the +'''archive_write_XXX'''() +functions, respectively, and either can be used independently +of the other. + +The rest of this manual page provides an overview of the library +operation. +More detailed information can be found in the individual manual +pages for each API or utility function. +== READING AN ARCHIVE == +See +[[ManPagerchiveead3]]. +== WRITING AN ARCHIVE == +See +[[ManPagerchiverite3]]. +== WRITING ENTRIES TO DISK == +The +[[ManPagerchiveriteisk3]] +API allows you to write +[[ManPagerchiventry3]] +objects to disk using the same API used by +[[ManPagerchiverite3]]. +The +[[ManPagerchiveriteisk3]] +API is used internally by +'''archive_read_extract'''('';'') +using it directly can provide greater control over how entries +get written to disk. +This API also makes it possible to share code between +archive-to-archive copy and archive-to-disk extraction +operations. +== READING ENTRIES FROM DISK == +The +[[ManPagerchiveeadisk3]] +supports for populating +[[ManPagerchiventry3]] +objects from information in the filesystem. +This includes the information accessible from the +[[stat(2)|http://www.freebsd.org/cgi/man.cgi?query=stat&sektion=2]] +system call as well as ACLs, extended attributes, +and other metadata. +The +[[ManPagerchiveeadisk3]] +API also supports iterating over directory trees, +which allows directories of files to be read using +an API compatible with +the +[[ManPagerchiveead3]] +API. +== DESCRIPTION == +Detailed descriptions of each function are provided by the +corresponding manual pages. + +All of the functions utilize an opaque +'''struct archive''' +datatype that provides access to the archive contents. + +The +'''struct archive_entry''' +structure contains a complete description of a single archive +entry. +It uses an opaque interface that is fully documented in +[[ManPagerchiventry3]]. + +Users familiar with historic formats should be aware that the newer +variants have eliminated most restrictions on the length of textual fields. +Clients should not assume that filenames, link names, user names, or +group names are limited in length. +In particular, pax interchange format can easily accommodate pathnames +in arbitrary character sets that exceed +''PATH_MAX''. +== RETURN VALUES == +Most functions return +'''ARCHIVE_OK''' +(zero) on success, non-zero on error. +The return value indicates the general severity of the error, ranging +from +'''ARCHIVE_WARN''', +which indicates a minor problem that should probably be reported +to the user, to +'''ARCHIVE_FATAL''', +which indicates a serious problem that will prevent any further +operations on this archive. +On error, the +'''archive_errno'''() +function can be used to retrieve a numeric error code (see +[[errno(2)|http://www.freebsd.org/cgi/man.cgi?query=errno&sektion=2]]). +The +'''archive_error_string'''() +returns a textual error message suitable for display. + +'''archive_read_new'''() +and +'''archive_write_new'''() +return pointers to an allocated and initialized +'''struct archive''' +object. + +'''archive_read_data'''() +and +'''archive_write_data'''() +return a count of the number of bytes actually read or written. +A value of zero indicates the end of the data for this entry. +A negative value indicates an error, in which case the +'''archive_errno'''() +and +'''archive_error_string'''() +functions can be used to obtain more information. +== ENVIRONMENT == +There are character set conversions within the +[[ManPagerchiventry3]] +functions that are impacted by the currently-selected locale. +== SEE ALSO == +[[ManPageBsdtar1]], +[[ManPagerchiventry3]], +[[ManPagerchiveead3]], +[[ManPagerchivetil3]], +[[ManPagerchiverite3]], +[[ManPageTar5]] +== HISTORY == +The +'''libarchive''' +library first appeared in +FreeBSD 5.3. +== AUTHORS == +The +'''libarchive''' +library was originally written by +Tim Kientzle <kientzle@acm.org.> +== BUGS == +Some archive formats support information that is not supported by +'''struct archive_entry .''' +Such information cannot be fully archived or restored using this library. +This includes, for example, comments, character sets, +or the arbitrary key/value pairs that can appear in +pax interchange format archives. + +Conversely, of course, not all of the information that can be +stored in an +'''struct archive_entry''' +is supported by all formats. +For example, cpio formats do not support nanosecond timestamps; +old tar formats do not support large device numbers. + +The ISO9660 reader cannot yet read all ISO9660 images; +it should learn how to seek. + +The AR writer requires the client program to use +two passes, unlike all other libarchive writers. diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageLibarchiveChanges3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageLibarchiveChanges3.wiki new file mode 100644 index 0000000..2ccb83c --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageLibarchiveChanges3.wiki @@ -0,0 +1,303 @@ +LIBARCHIVE_CHANGES(3) manual page +== NAME == +'''libarchive_changes''' +- changes in libarchive interface +== CHANGES IN LIBARCHIVE 3 == +This page describes user-visible changes in libarchive3, and lists +public functions and other symbols changed, deprecated or removed +in libarchive3, along with their replacements if any. +=== Multiple Filters=== +Libarchive2 permitted a single (input or output) filter active +on an archive. +Libarchive3 extends this into a variable-length stack. +Where +'''archive_write_set_compression_XXX'''() +would replace any existing filter, +'''archive_write_add_filter_XXX'''() +extends the write pipeline with another filter. +=== Character Set Handling=== +Libarchive2 assumed that the local platform uses +'''Unicode''' +as the native +'''wchar_t''' +encoding, which is true on +'''Windows ,''' +modern +'''Linux ,''' +and a few other systems, but is certainly not universal. +As a result, pax format archives were written incorrectly on some +systems, since pax format requires +'''UTF-8''' +and libarchive 2 incorrectly +assumed that +'''wchar_t''' +strings can be easily converted to +'''UTF-8 .''' + +Libarchive3 uses the standard iconv library to convert between character +sets and is introducing the notion of a +"default character set for the archive". +To support this, +'''archive_entry''' +objects can now be bound to a particular archive when they are created. +The automatic character set conversions performed by +'''archive_entry''' +objects when reading and writing filenames, usernames, and other strings +will now use an appropriate default character set: + +If the +'''archive_entry''' +object is bound to an archive, it will use the +default character set for that archive. + +The platform default character encoding (as returned by +'''nl_langinfo'''(''CHARSET'', '')'') +will be used if nothing else is specified. + +Libarchive3 also introduces charset options to many of the archive +readers and writers to control the character set that will be used for +filenames written in those archives. +When possible, this will be set automatically based on information in +the archive itself. +Combining this with the notion of a default character set for the +archive should allow you to configure libarchive to read archives from +other platforms and have the filenames and other information +transparently converted to the character encoding suitable for your +application. +=== Prototype Changes=== +These changes break binary compatibility; libarchive3 has a new shared +library version to reflect these changes. +The library now uses portable wide types such as +'''int64_t''' +instead of less-portable types such as +'''off_t ,''' +'''gid_t ,''' +'''uid_t ,''' +and +'''ino_t .''' + +There are a few cases where these changes will affect your source code: +
      +
    • +In some cases, libarchive's wider types will introduce the possibility +of truncation: for example, on a system with a 16-bit +'''uid_t , you risk having uid''' +```text +65536 +``` +be truncated to uid +```text +0, +``` +which can cause serious security problems. +
    • +Typedef function pointer types will be incompatible. +For example, if you define custom skip callbacks, you may have to use +code similar to the following if you want to support building against +libarchive2 and libarchive3: +```text +#if ARCHIVE_VERSION_NUMBER < 3000000 +typedef off_t myoff_t; +#else +typedef int64_t myoff_t; +#endif +myoff_t +my_skip_function(struct archive *a, void *v, myoff_t o) +{ + ... implementation ... +} +``` +
    + +Affected functions: + +
      +
    • +'''archive_entry_gid'''(), +'''archive_entry_set_gid'''() +
    • +'''archive_entry_uid'''(), +'''archive_entry_set_uid'''() +
    • +'''archive_entry_ino'''(), +'''archive_entry_set_ino'''() +
    • +'''archive_read_data_block'''(), +'''archive_write_data_block'''() +
    • +'''archive_read_disk_gname'''(), +'''archive_read_disk_uname'''() +
    • +'''archive_read_disk_set_gname_lookup'''(), +'''archive_read_disk_set_group_lookup'''(), +'''archive_read_disk_set_uname_lookup'''(), +'''archive_read_disk_set_user_lookup'''() +
    • +'''archive_skip_callback'''() +
    • +'''archive_read_extract_set_skip_file'''(), +'''archive_write_disk_set_skip_file'''(), +'''archive_write_set_skip_file'''() +
    • +'''archive_write_disk_set_group_lookup'''(), +'''archive_write_disk_set_user_lookup'''() +
    + +Where these functions or their arguments took or returned +'''gid_t ,''' +'''ino_t ,''' +'''off_t ,''' +or +'''uid_t''' +they now take or return +'''int64_t''' +or equivalent. +=== Deprecated Symbols=== +Symbols deprecated in libarchive3 will be removed in libarchive4. +These symbols, along with their replacements if any, are listed below: +
    +
    '''archive_position_compressed'''(), '''archive_position_uncompressed'''()
    +'''archive_filter_bytes'''() +
    '''archive_compression'''()
    +'''archive_filter_code'''() +
    '''archive_compression_name'''()
    +'''archive_filter_name'''() +
    '''archive_read_finish'''(), '''archive_write_finish'''()
    +'''archive_read_free'''(), +'''archive_write_free'''() +
    '''archive_read_open_file'''(), '''archive_write_open_file'''()
    +'''archive_read_open_filename'''(), +'''archive_write_open_filename'''() +
    '''archive_read_support_compression_all'''()
    +'''archive_read_support_filter_all'''() +
    '''archive_read_support_compression_bzip2'''()
    +'''archive_read_support_filter_bzip2'''() +
    '''archive_read_support_compression_compress'''()
    +'''archive_read_support_filter_compress'''() +
    '''archive_read_support_compression_gzip'''()
    +'''archive_read_support_filter_gzip'''() +
    '''archive_read_support_compression_lzip'''()
    +'''archive_read_support_filter_lzip'''() +
    '''archive_read_support_compression_lzma'''()
    +'''archive_read_support_filter_lzma'''() +
    '''archive_read_support_compression_none'''()
    +'''archive_read_support_filter_none'''() +
    '''archive_read_support_compression_program'''()
    +'''archive_read_support_filter_program'''() +
    '''archive_read_support_compression_program_signature'''()
    +'''archive_read_support_filter_program_signature'''() +
    '''archive_read_support_compression_rpm'''()
    +'''archive_read_support_filter_rpm'''() +
    '''archive_read_support_compression_uu'''()
    +'''archive_read_support_filter_uu'''() +
    '''archive_read_support_compression_xz'''()
    +'''archive_read_support_filter_xz'''() +
    '''archive_write_set_compression_bzip2'''()
    +'''archive_write_add_filter_bzip2'''() +
    '''archive_write_set_compression_compress'''()
    +'''archive_write_add_filter_compress'''() +
    '''archive_write_set_compression_gzip'''()
    +'''archive_write_add_filter_gzip'''() +
    '''archive_write_set_compression_lzip'''()
    +'''archive_write_add_filter_lzip'''() +
    '''archive_write_set_compression_lzma'''()
    +'''archive_write_add_filter_lzma'''() +
    '''archive_write_set_compression_none'''()
    +'''archive_write_add_filter_none'''() +
    '''archive_write_set_compression_program'''()
    +'''archive_write_add_filter_program'''() +
    '''archive_write_set_compression_filter'''()
    +'''archive_write_add_filter_filter'''() +
    +=== Removed Symbols=== +These symbols, listed below along with their replacements if any, +were deprecated in libarchive2, and are not part of libarchive3. +
    +
    '''archive_api_feature'''()
    +'''archive_version_number'''() +
    '''archive_api_version'''()
    +'''archive_version_number'''() +
    '''archive_version'''()
    +'''archive_version_string'''() +
    '''archive_version_stamp'''()
    +'''archive_version_number'''() +
    '''archive_read_set_filter_options'''()
    +'''archive_read_set_options'''() +or +'''archive_read_set_filter_option'''() +
    '''archive_read_set_format_options'''()
    +'''archive_read_set_options'''() +or +'''archive_read_set_format_option'''() +
    '''archive_write_set_filter_options'''()
    +'''archive_write_set_options'''() +or +'''archive_write_set_filter_option'''() +
    '''archive_write_set_format_options'''()
    +'''archive_write_set_options'''() +or +'''archive_write_set_format_option'''() +
    +ARCHIVE_API_FEATURE +ARCHIVE_VERSION_NUMBER +
    +ARCHIVE_API_VERSION +ARCHIVE_VERSION_NUMBER +
    +ARCHIVE_VERSION_STAMP +ARCHIVE_VERSION_NUMBER +
    +ARCHIVE_LIBRARY_VERSION +ARCHIVE_VERSION_STRING +
    +ARCHIVE_COMPRESSION_NONE +ARCHIVE_FILTER_NONE +
    +ARCHIVE_COMPRESSION_GZIP +ARCHIVE_FILTER_GZIP +
    +ARCHIVE_COMPRESSION_BZIP2 +ARCHIVE_FILTER_BZIP2 +
    +ARCHIVE_COMPRESSION_COMPRESS +ARCHIVE_FILTER_COMPRESS +
    +ARCHIVE_COMPRESSION_PROGRAM +ARCHIVE_FILTER_PROGRAM +
    +ARCHIVE_COMPRESSION_LZMA +ARCHIVE_FILTER_LZMA +
    +ARCHIVE_COMPRESSION_XZ +ARCHIVE_FILTER_XZ +
    +ARCHIVE_COMPRESSION_UU +ARCHIVE_FILTER_UU +
    +ARCHIVE_COMPRESSION_RPM +ARCHIVE_FILTER_RPM +
    +ARCHIVE_COMPRESSION_LZIP +ARCHIVE_FILTER_LZIP +
    +ARCHIVE_BYTES_PER_RECORD +```text +512 +``` +
    +ARCHIVE_DEFAULT_BYTES_PER_BLOCK +```text +10240 +``` +
    +== SEE ALSO == +[[ManPagerchiveead3]], +[[ManPagerchiveeadilter3]], +[[ManPagerchiveeadormat3]], +[[ManPagerchiveeadetptions3]], +[[ManPagerchivetil3]], +[[ManPagerchiverite3]], +[[ManPagerchiveriteilter3]], +[[ManPagerchiveriteormat3]], +[[ManPagerchiveriteetptions3]], +[[ManPageibarchive3]] diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageLibarchiveFormats5.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageLibarchiveFormats5.wiki new file mode 100644 index 0000000..7623d91 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageLibarchiveFormats5.wiki @@ -0,0 +1,437 @@ +LIBARCHIVE-FORMATS(5) manual page +== NAME == +'''libarchive-formats''' +- archive formats supported by the libarchive library +== DESCRIPTION == +The +[[ManPageibarchive3]] +library reads and writes a variety of streaming archive formats. +Generally speaking, all of these archive formats consist of a series of +"entries". +Each entry stores a single file system object, such as a file, directory, +or symbolic link. + +The following provides a brief description of each format supported +by libarchive, with some information about recognized extensions or +limitations of the current library support. +Note that just because a format is supported by libarchive does not +imply that a program that uses libarchive will support that format. +Applications that use libarchive specify which formats they wish +to support, though many programs do use libarchive convenience +functions to enable all supported formats. +=== Tar Formats=== +The +[[ManPageibarchive3]] +library can read most tar archives. +It can write POSIX-standard +"ustar" +and +"pax interchange" +formats as well as v7 tar format and a subset of the legacy GNU tar format. + +All tar formats store each entry in one or more 512-byte records. +The first record is used for file metadata, including filename, +timestamp, and mode information, and the file data is stored in +subsequent records. +Later variants have extended this by either appropriating undefined +areas of the header record, extending the header to multiple records, +or by storing special entries that modify the interpretation of +subsequent entries. +
    +
    '''gnutar'''
    +The +[[ManPageibarchive3]] +library can read most GNU-format tar archives. +It currently supports the most popular GNU extensions, including +modern long filename and linkname support, as well as atime and ctime data. +The libarchive library does not support multi-volume +archives, nor the old GNU long filename format. +It can read GNU sparse file entries, including the new POSIX-based +formats. + +The +[[ManPageibarchive3]] +library can write GNU tar format, including long filename +and linkname support, as well as atime and ctime data. +
    '''pax'''
    +The +[[ManPageibarchive3]] +library can read and write POSIX-compliant pax interchange format +archives. +Pax interchange format archives are an extension of the older ustar +format that adds a separate entry with additional attributes stored +as key/value pairs immediately before each regular entry. +The presence of these additional entries is the only difference between +pax interchange format and the older ustar format. +The extended attributes are of unlimited length and are stored +as UTF-8 Unicode strings. +Keywords defined in the standard are in all lowercase; vendors are allowed +to define custom keys by preceding them with the vendor name in all uppercase. +When writing pax archives, libarchive uses many of the SCHILY keys +defined by Joerg Schilling's +"star" +archiver and a few LIBARCHIVE keys. +The libarchive library can read most of the SCHILY keys +and most of the GNU keys introduced by GNU tar. +It silently ignores any keywords that it does not understand. + +The pax interchange format converts filenames to Unicode +and stores them using the UTF-8 encoding. +Prior to libarchive 3.0, libarchive erroneously assumed +that the system wide-character routines natively supported +Unicode. +This caused it to mis-handle non-ASCII filenames on systems +that did not satisfy this assumption. +
    '''restricted''' pax
    +The libarchive library can also write pax archives in which it +attempts to suppress the extended attributes entry whenever +possible. +The result will be identical to a ustar archive unless the +extended attributes entry is required to store a long file +name, long linkname, extended ACL, file flags, or if any of the standard +ustar data (user name, group name, UID, GID, etc) cannot be fully +represented in the ustar header. +In all cases, the result can be dearchived by any program that +can read POSIX-compliant pax interchange format archives. +Programs that correctly read ustar format (see below) will also be +able to read this format; any extended attributes will be extracted as +separate files stored in +''PaxHeader'' +directories. +
    '''ustar'''
    +The libarchive library can both read and write this format. +This format has the following limitations: +
      +
    • +Device major and minor numbers are limited to 21 bits. +Nodes with larger numbers will not be added to the archive. +
    • +Path names in the archive are limited to 255 bytes. +(Shorter if there is no / character in exactly the right place.) +
    • +Symbolic links and hard links are stored in the archive with +the name of the referenced file. +This name is limited to 100 bytes. +
    • +Extended attributes, file flags, and other extended +security information cannot be stored. +
    • +Archive entries are limited to 8 gigabytes in size. +
    +Note that the pax interchange format has none of these restrictions. +The ustar format is old and widely supported. +It is recommended when compatibility is the primary concern. +
    '''v7'''
    +The libarchive library can read and write the legacy v7 tar format. +This format has the following limitations: +
      +
    • +Only regular files, directories, and symbolic links can be archived. +Block and character device nodes, FIFOs, and sockets cannot be archived. +
    • +Path names in the archive are limited to 100 bytes. +
    • +Symbolic links and hard links are stored in the archive with +the name of the referenced file. +This name is limited to 100 bytes. +
    • +User and group information are stored as numeric IDs; there +is no provision for storing user or group names. +
    • +Extended attributes, file flags, and other extended +security information cannot be stored. +
    • +Archive entries are limited to 8 gigabytes in size. +
    +Generally, users should prefer the ustar format for portability +as the v7 tar format is both less useful and less portable. +
    + +The libarchive library also reads a variety of commonly-used extensions to +the basic tar format. +These extensions are recognized automatically whenever they appear. +
    +
    Numeric extensions.
    +The POSIX standards require fixed-length numeric fields to be written with +some character position reserved for terminators. +Libarchive allows these fields to be written without terminator characters. +This extends the allowable range; in particular, ustar archives with this +extension can support entries up to 64 gigabytes in size. +Libarchive also recognizes base-256 values in most numeric fields. +This essentially removes all limitations on file size, modification time, +and device numbers. +
    Solaris extensions
    +Libarchive recognizes ACL and extended attribute records written +by Solaris tar. +
    + +The first tar program appeared in Seventh Edition Unix in 1979. +The first official standard for the tar file format was the +"ustar" +(Unix Standard Tar) format defined by POSIX in 1988. +POSIX.1-2001 extended the ustar format to create the +"pax interchange" +format. +=== Cpio Formats=== +The libarchive library can read a number of common cpio variants and can write +"odc" +and +"newc" +format archives. +A cpio archive stores each entry as a fixed-size header followed +by a variable-length filename and variable-length data. +Unlike the tar format, the cpio format does only minimal padding +of the header or file data. +There are several cpio variants, which differ primarily in +how they store the initial header: some store the values as +octal or hexadecimal numbers in ASCII, others as binary values of +varying byte order and length. +
    +
    '''binary'''
    +The libarchive library transparently reads both big-endian and little-endian +variants of the original binary cpio format. +This format used 32-bit binary values for file size and mtime, +and 16-bit binary values for the other fields. +
    '''odc'''
    +The libarchive library can both read and write this +POSIX-standard format, which is officially known as the +"cpio interchange format" +or the +"octet-oriented cpio archive format" +and sometimes unofficially referred to as the +"old character format". +This format stores the header contents as octal values in ASCII. +It is standard, portable, and immune from byte-order confusion. +File sizes and mtime are limited to 33 bits (8GB file size), +other fields are limited to 18 bits. +
    '''SVR4/newc'''
    +The libarchive library can read both CRC and non-CRC variants of +this format. +The SVR4 format uses eight-digit hexadecimal values for +all header fields. +This limits file size to 4GB, and also limits the mtime and +other fields to 32 bits. +The SVR4 format can optionally include a CRC of the file +contents, although libarchive does not currently verify this CRC. +
    + +Cpio first appeared in PWB/UNIX 1.0, which was released within +AT&T in 1977. +PWB/UNIX 1.0 formed the basis of System III Unix, released outside +of AT&T in 1981. +This makes cpio older than tar, although cpio was not included +in Version 7 AT&T Unix. +As a result, the tar command became much better known in universities +and research groups that used Version 7. +The combination of the +'''find''' +and +'''cpio''' +utilities provided very precise control over file selection. +Unfortunately, the format has many limitations that make it unsuitable +for widespread use. +Only the POSIX format permits files over 4GB, and its 18-bit +limit for most other fields makes it unsuitable for modern systems. +In addition, cpio formats only store numeric UID/GID values (not +usernames and group names), which can make it very difficult to correctly +transfer archives across systems with dissimilar user numbering. +=== Shar Formats=== +A +"shell archive" +is a shell script that, when executed on a POSIX-compliant +system, will recreate a collection of file system objects. +The libarchive library can write two different kinds of shar archives: +
    +
    '''shar'''
    +The traditional shar format uses a limited set of POSIX +commands, including +[[echo(1)|http://www.freebsd.org/cgi/man.cgi?query=echo&sektion=1]], +[[mkdir(1)|http://www.freebsd.org/cgi/man.cgi?query=mkdir&sektion=1]], +and +[[sed(1)|http://www.freebsd.org/cgi/man.cgi?query=sed&sektion=1]]. +It is suitable for portably archiving small collections of plain text files. +However, it is not generally well-suited for large archives +(many implementations of +[[sh(1)|http://www.freebsd.org/cgi/man.cgi?query=sh&sektion=1]] +have limits on the size of a script) nor should it be used with non-text files. +
    '''shardump'''
    +This format is similar to shar but encodes files using +[[uuencode(1)|http://www.freebsd.org/cgi/man.cgi?query=uuencode&sektion=1]] +so that the result will be a plain text file regardless of the file contents. +It also includes additional shell commands that attempt to reproduce as +many file attributes as possible, including owner, mode, and flags. +The additional commands used to restore file attributes make +shardump archives less portable than plain shar archives. +
    +=== ISO9660 format=== +Libarchive can read and extract from files containing ISO9660-compliant +CDROM images. +In many cases, this can remove the need to burn a physical CDROM +just in order to read the files contained in an ISO9660 image. +It also avoids security and complexity issues that come with +virtual mounts and loopback devices. +Libarchive supports the most common Rockridge extensions and has partial +support for Joliet extensions. +If both extensions are present, the Joliet extensions will be +used and the Rockridge extensions will be ignored. +In particular, this can create problems with hardlinks and symlinks, +which are supported by Rockridge but not by Joliet. + +Libarchive reads ISO9660 images using a streaming strategy. +This allows it to read compressed images directly +(decompressing on the fly) and allows it to read images +directly from network sockets, pipes, and other non-seekable +data sources. +This strategy works well for optimized ISO9660 images created +by many popular programs. +Such programs collect all directory information at the beginning +of the ISO9660 image so it can be read from a physical disk +with a minimum of seeking. +However, not all ISO9660 images can be read in this fashion. + +Libarchive can also write ISO9660 images. +Such images are fully optimized with the directory information +preceding all file data. +This is done by storing all file data to a temporary file +while collecting directory information in memory. +When the image is finished, libarchive writes out the +directory structure followed by the file data. +The location used for the temporary file can be changed +by the usual environment variables. +=== Zip format=== +Libarchive can read and write zip format archives that have +uncompressed entries and entries compressed with the +"deflate" +algorithm. +Other zip compression algorithms are not supported. +It can extract jar archives, archives that use Zip64 extensions and +self-extracting zip archives. +Libarchive can use either of two different strategies for +reading Zip archives: +a streaming strategy which is fast and can handle extremely +large archives, and a seeking strategy which can correctly +process self-extracting Zip archives and archives with +deleted members or other in-place modifications. + +The streaming reader processes Zip archives as they are read. +It can read archives of arbitrary size from tape or +network sockets, and can decode Zip archives that have +been separately compressed or encoded. +However, self-extracting Zip archives and archives with +certain types of modifications cannot be correctly +handled. +Such archives require that the reader first process the +Central Directory, which is ordinarily located +at the end of a Zip archive and is thus inaccessible +to the streaming reader. +If the program using libarchive has enabled seek support, then +libarchive will use this to processes the central directory first. + +In particular, the seeking reader must be used to +correctly handle self-extracting archives. +Such archives consist of a program followed by a regular +Zip archive. +The streaming reader cannot parse the initial program +portion, but the seeking reader starts by reading the +Central Directory from the end of the archive. +Similarly, Zip archives that have been modified in-place +can have deleted entries or other garbage data that +can only be accurately detected by first reading the +Central Directory. +=== Archive (library) file format=== +The Unix archive format (commonly created by the +[[ar(1)|http://www.freebsd.org/cgi/man.cgi?query=ar&sektion=1]] +archiver) is a general-purpose format which is +used almost exclusively for object files to be +read by the link editor +[[ld(1)|http://www.freebsd.org/cgi/man.cgi?query=ld&sektion=1]]. +The ar format has never been standardised. +There are two common variants: +the GNU format derived from SVR4, +and the BSD format, which first appeared in 4.4BSD. +The two differ primarily in their handling of filenames +longer than 15 characters: +the GNU/SVR4 variant writes a filename table at the beginning of the archive; +the BSD format stores each long filename in an extension +area adjacent to the entry. +Libarchive can read both extensions, +including archives that may include both types of long filenames. +Programs using libarchive can write GNU/SVR4 format +if they provide an entry called +''//'' +containing a filename table to be written into the archive +before any of the entries. +Any entries whose names are not in the filename table +will be written using BSD-style long filenames. +This can cause problems for programs such as +GNU ld that do not support the BSD-style long filenames. +=== mtree=== +Libarchive can read and write files in +[[ManPageMtree5]] +format. +This format is not a true archive format, but rather a textual description +of a file hierarchy in which each line specifies the name of a file and +provides specific metadata about that file. +Libarchive can read all of the keywords supported by both +the NetBSD and FreeBSD versions of +[[mtree(8)|http://www.freebsd.org/cgi/man.cgi?query=mtree&sektion=8]], +although many of the keywords cannot currently be stored in an +'''archive_entry''' +object. +When writing, libarchive supports use of the +[[ManPagerchiveriteetptions3]] +interface to specify which keywords should be included in the +output. +If libarchive was compiled with access to suitable +cryptographic libraries (such as the OpenSSL libraries), +it can compute hash entries such as +'''sha512''' +or +'''md5''' +from file data being written to the mtree writer. + +When reading an mtree file, libarchive will locate the corresponding +files on disk using the +'''contents''' +keyword if present or the regular filename. +If it can locate and open the file on disk, it will use that +to fill in any metadata that is missing from the mtree file +and will read the file contents and return those to the program +using libarchive. +If it cannot locate and open the file on disk, libarchive +will return an error for any attempt to read the entry +body. +=== 7-Zip=== +Libarchive can read and write 7-Zip format archives. +TODO: Need more information +=== CAB=== +Libarchive can read Microsoft Cabinet ( +"CAB )" +format archives. +TODO: Need more information. +=== LHA=== +TODO: Information about libarchive's LHA support +=== RAR=== +Libarchive has limited support for reading RAR format archives. +Currently, libarchive can read RARv3 format archives +which have been either created uncompressed, or compressed using +any of the compression methods supported by the RARv3 format. +Libarchive can also read self-extracting RAR archives. +=== Warc=== +Libarchive can read and write +"web archives". +TODO: Need more information +=== XAR=== +Libarchive can read and write the XAR format used by many Apple tools. +TODO: Need more information +== SEE ALSO == +[[ar(1)|http://www.freebsd.org/cgi/man.cgi?query=ar&sektion=1]], +[[ManPageBsdcpio1]], +[[mkisofs(1)|http://www.freebsd.org/cgi/man.cgi?query=mkisofs&sektion=1]], +[[shar(1)|http://www.freebsd.org/cgi/man.cgi?query=shar&sektion=1]], +[[ManPageBsdtar1]], +[[zip(1)|http://www.freebsd.org/cgi/man.cgi?query=zip&sektion=1]], +[[zlib(3)|http://www.freebsd.org/cgi/man.cgi?query=zlib&sektion=3]], +[[ManPageCpio5]], +[[ManPageMtree5]], +[[ManPageTar5]] diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageLibarchiveInternals3.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageLibarchiveInternals3.wiki new file mode 100644 index 0000000..cf913b7 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageLibarchiveInternals3.wiki @@ -0,0 +1,336 @@ +LIBARCHIVE_INTERNALS(3) manual page +== NAME == +'''libarchive_internals''' +- description of libarchive internal interfaces +== OVERVIEW == +The +'''libarchive''' +library provides a flexible interface for reading and writing +streaming archive files such as tar and cpio. +Internally, it follows a modular layered design that should +make it easy to add new archive and compression formats. +== GENERAL ARCHITECTURE == +Externally, libarchive exposes most operations through an +opaque, object-style interface. +The +[[ManPagerchiventry3]] +objects store information about a single filesystem object. +The rest of the library provides facilities to write +[[ManPagerchiventry3]] +objects to archive files, +read them from archive files, +and write them to disk. +(There are plans to add a facility to read +[[ManPagerchiventry3]] +objects from disk as well.) + +The read and write APIs each have four layers: a public API +layer, a format layer that understands the archive file format, +a compression layer, and an I/O layer. +The I/O layer is completely exposed to clients who can replace +it entirely with their own functions. + +In order to provide as much consistency as possible for clients, +some public functions are virtualized. +Eventually, it should be possible for clients to open +an archive or disk writer, and then use a single set of +code to select and write entries, regardless of the target. +== READ ARCHITECTURE == +From the outside, clients use the +[[ManPagerchiveead3]] +API to manipulate an +'''archive''' +object to read entries and bodies from an archive stream. +Internally, the +'''archive''' +object is cast to an +'''archive_read''' +object, which holds all read-specific data. +The API has four layers: +The lowest layer is the I/O layer. +This layer can be overridden by clients, but most clients use +the packaged I/O callbacks provided, for example, by +[[ManPagerchiveeadpenemory3]], +and +[[ManPagerchiveeadpend3]]. +The compression layer calls the I/O layer to +read bytes and decompresses them for the format layer. +The format layer unpacks a stream of uncompressed bytes and +creates +'''archive_entry''' +objects from the incoming data. +The API layer tracks overall state +(for example, it prevents clients from reading data before reading a header) +and invokes the format and compression layer operations +through registered function pointers. +In particular, the API layer drives the format-detection process: +When opening the archive, it reads an initial block of data +and offers it to each registered compression handler. +The one with the highest bid is initialized with the first block. +Similarly, the format handlers are polled to see which handler +is the best for each archive. +(Prior to 2.4.0, the format bidders were invoked for each +entry, but this design hindered error recovery.) +=== I/O Layer and Client Callbacks=== +The read API goes to some lengths to be nice to clients. +As a result, there are few restrictions on the behavior of +the client callbacks. + +The client read callback is expected to provide a block +of data on each call. +A zero-length return does indicate end of file, but otherwise +blocks may be as small as one byte or as large as the entire file. +In particular, blocks may be of different sizes. + +The client skip callback returns the number of bytes actually +skipped, which may be much smaller than the skip requested. +The only requirement is that the skip not be larger. +In particular, clients are allowed to return zero for any +skip that they don't want to handle. +The skip callback must never be invoked with a negative value. + +Keep in mind that not all clients are reading from disk: +clients reading from networks may provide different-sized +blocks on every request and cannot skip at all; +advanced clients may use +[[mmap(2)|http://www.freebsd.org/cgi/man.cgi?query=mmap&sektion=2]] +to read the entire file into memory at once and return the +entire file to libarchive as a single block; +other clients may begin asynchronous I/O operations for the +next block on each request. +=== Decompresssion Layer=== +The decompression layer not only handles decompression, +it also buffers data so that the format handlers see a +much nicer I/O model. +The decompression API is a two stage peek/consume model. +A read_ahead request specifies a minimum read amount; +the decompression layer must provide a pointer to at least +that much data. +If more data is immediately available, it should return more: +the format layer handles bulk data reads by asking for a minimum +of one byte and then copying as much data as is available. + +A subsequent call to the +'''consume'''() +function advances the read pointer. +Note that data returned from a +'''read_ahead'''() +call is guaranteed to remain in place until +the next call to +'''read_ahead'''(). +Intervening calls to +'''consume'''() +should not cause the data to move. + +Skip requests must always be handled exactly. +Decompression handlers that cannot seek forward should +not register a skip handler; +the API layer fills in a generic skip handler that reads and discards data. + +A decompression handler has a specific lifecycle: +
    +
    Registration/Configuration
    +When the client invokes the public support function, +the decompression handler invokes the internal +'''__archive_read_register_compression'''() +function to provide bid and initialization functions. +This function returns +'''NULL''' +on error or else a pointer to a +'''struct''' decompressor_t. +This structure contains a +''void'' * config +slot that can be used for storing any customization information. +
    Bid
    +The bid function is invoked with a pointer and size of a block of data. +The decompressor can access its config data +through the +''decompressor'' +element of the +'''archive_read''' +object. +The bid function is otherwise stateless. +In particular, it must not perform any I/O operations. + +The value returned by the bid function indicates its suitability +for handling this data stream. +A bid of zero will ensure that this decompressor is never invoked. +Return zero if magic number checks fail. +Otherwise, your initial implementation should return the number of bits +actually checked. +For example, if you verify two full bytes and three bits of another +byte, bid 19. +Note that the initial block may be very short; +be careful to only inspect the data you are given. +(The current decompressors require two bytes for correct bidding.) +
    Initialize
    +The winning bidder will have its init function called. +This function should initialize the remaining slots of the +''struct'' decompressor_t +object pointed to by the +''decompressor'' +element of the +''archive_read'' +object. +In particular, it should allocate any working data it needs +in the +''data'' +slot of that structure. +The init function is called with the block of data that +was used for tasting. +At this point, the decompressor is responsible for all I/O +requests to the client callbacks. +The decompressor is free to read more data as and when +necessary. +
    Satisfy I/O requests
    +The format handler will invoke the +''read_ahead'', +''consume'', +and +''skip'' +functions as needed. +
    Finish
    +The finish method is called only once when the archive is closed. +It should release anything stored in the +''data'' +and +''config'' +slots of the +''decompressor'' +object. +It should not invoke the client close callback. +
    +=== Format Layer=== +The read formats have a similar lifecycle to the decompression handlers: +
    +
    Registration
    +Allocate your private data and initialize your pointers. +
    Bid
    +Formats bid by invoking the +'''read_ahead'''() +decompression method but not calling the +'''consume'''() +method. +This allows each bidder to look ahead in the input stream. +Bidders should not look further ahead than necessary, as long +look aheads put pressure on the decompression layer to buffer +lots of data. +Most formats only require a few hundred bytes of look ahead; +look aheads of a few kilobytes are reasonable. +(The ISO9660 reader sometimes looks ahead by 48k, which +should be considered an upper limit.) +
    Read header
    +The header read is usually the most complex part of any format. +There are a few strategies worth mentioning: +For formats such as tar or cpio, reading and parsing the header is +straightforward since headers alternate with data. +For formats that store all header data at the beginning of the file, +the first header read request may have to read all headers into +memory and store that data, sorted by the location of the file +data. +Subsequent header read requests will skip forward to the +beginning of the file data and return the corresponding header. +
    Read Data
    +The read data interface supports sparse files; this requires that +each call return a block of data specifying the file offset and +size. +This may require you to carefully track the location so that you +can return accurate file offsets for each read. +Remember that the decompressor will return as much data as it has. +Generally, you will want to request one byte, +examine the return value to see how much data is available, and +possibly trim that to the amount you can use. +You should invoke consume for each block just before you return it. +
    Skip All Data
    +The skip data call should skip over all file data and trailing padding. +This is called automatically by the API layer just before each +header read. +It is also called in response to the client calling the public +'''data_skip'''() +function. +
    Cleanup
    +On cleanup, the format should release all of its allocated memory. +
    +=== API Layer=== +XXX to do XXX +== WRITE ARCHITECTURE == +The write API has a similar set of four layers: +an API layer, a format layer, a compression layer, and an I/O layer. +The registration here is much simpler because only +one format and one compression can be registered at a time. +=== I/O Layer and Client Callbacks=== +XXX To be written XXX +=== Compression Layer=== +XXX To be written XXX +=== Format Layer=== +XXX To be written XXX +=== API Layer=== +XXX To be written XXX +== WRITE_DISK ARCHITECTURE == +The write_disk API is intended to look just like the write API +to clients. +Since it does not handle multiple formats or compression, it +is not layered internally. +== GENERAL SERVICES == +The +'''archive_read''', +'''archive_write''', +and +'''archive_write_disk''' +objects all contain an initial +'''archive''' +object which provides common support for a set of standard services. +(Recall that ANSI/ISO C90 guarantees that you can cast freely between +a pointer to a structure and a pointer to the first element of that +structure.) +The +'''archive''' +object has a magic value that indicates which API this object +is associated with, +slots for storing error information, +and function pointers for virtualized API functions. +== MISCELLANEOUS NOTES == +Connecting existing archiving libraries into libarchive is generally +quite difficult. +In particular, many existing libraries strongly assume that you +are reading from a file; they seek forwards and backwards as necessary +to locate various pieces of information. +In contrast, libarchive never seeks backwards in its input, which +sometimes requires very different approaches. + +For example, libarchive's ISO9660 support operates very differently +from most ISO9660 readers. +The libarchive support utilizes a work-queue design that +keeps a list of known entries sorted by their location in the input. +Whenever libarchive's ISO9660 implementation is asked for the next +header, checks this list to find the next item on the disk. +Directories are parsed when they are encountered and new +items are added to the list. +This design relies heavily on the ISO9660 image being optimized so that +directories always occur earlier on the disk than the files they +describe. + +Depending on the specific format, such approaches may not be possible. +The ZIP format specification, for example, allows archivers to store +key information only at the end of the file. +In theory, it is possible to create ZIP archives that cannot +be read without seeking. +Fortunately, such archives are very rare, and libarchive can read +most ZIP archives, though it cannot always extract as much information +as a dedicated ZIP program. +== SEE ALSO == +[[ManPagerchiventry3]], +[[ManPagerchiveead3]], +[[ManPagerchiverite3]], +[[ManPagerchiveriteisk3]], +[[ManPageibarchive3]] +== HISTORY == +The +'''libarchive''' +library first appeared in +FreeBSD 5.3. +== AUTHORS == +The +'''libarchive''' +library was written by +Tim Kientzle <kientzle@acm.org.> diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageMtree5.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageMtree5.wiki new file mode 100644 index 0000000..c761e91 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageMtree5.wiki @@ -0,0 +1,292 @@ +MTREE(5) manual page +== NAME == +'''mtree''' +- format of mtree dir hierarchy files +== DESCRIPTION == +The +'''mtree''' +format is a textual format that describes a collection of filesystem objects. +Such files are typically used to create or verify directory hierarchies. +=== General Format=== +An +'''mtree''' +file consists of a series of lines, each providing information +about a single filesystem object. +Leading whitespace is always ignored. + +When encoding file or pathnames, any backslash character or +character outside of the 95 printable ASCII characters must be +encoded as a backslash followed by three +octal digits. +When reading mtree files, any appearance of a backslash +followed by three octal digits should be converted into the +corresponding character. + +Each line is interpreted independently as one of the following types: +
    +
    Blank
    +Blank lines are ignored. +
    Comment
    +Lines beginning with +'''#''' +are ignored. +
    Special
    +Lines beginning with +'''/''' +are special commands that influence +the interpretation of later lines. +
    Relative
    +If the first whitespace-delimited word has no +'''/''' +characters, +it is the name of a file in the current directory. +Any relative entry that describes a directory changes the +current directory. +
    dot-dot
    +As a special case, a relative entry with the filename +''..'' +changes the current directory to the parent directory. +Options on dot-dot entries are always ignored. +
    Full
    +If the first whitespace-delimited word has a +'''/''' +character after +the first character, it is the pathname of a file relative to the +starting directory. +There can be multiple full entries describing the same file. +
    + +Some tools that process +'''mtree''' +files may require that multiple lines describing the same file +occur consecutively. +It is not permitted for the same file to be mentioned using +both a relative and a full file specification. +=== Special commands=== +Two special commands are currently defined: +
    +
    '''/set'''
    +This command defines default values for one or more keywords. +It is followed on the same line by one or more whitespace-separated +keyword definitions. +These definitions apply to all following files that do not specify +a value for that keyword. +
    '''/unset'''
    +This command removes any default value set by a previous +'''/set''' +command. +It is followed on the same line by one or more keywords +separated by whitespace. +
    +=== Keywords=== +After the filename, a full or relative entry consists of zero +or more whitespace-separated keyword definitions. +Each such definition consists of a key from the following +list immediately followed by an '=' sign +and a value. +Software programs reading mtree files should warn about +unrecognized keywords. + +Currently supported keywords are as follows: +
    +
    '''cksum'''
    +The checksum of the file using the default algorithm specified by +the +[[cksum(1)|http://www.freebsd.org/cgi/man.cgi?query=cksum&sektion=1]] +utility. +
    '''device'''
    +The device number for +.B block +or +.B char +file types. +The value must be one of the following forms: +
    +
    ''format'',''major'',''minor''Bo,''subunit'' Bc
    +A device with +''major'', minor +and optional +''subunit'' +fields. +Their meaning is specified by the operating's system +''format''. +See below for valid formats. +
    ''number''
    +Opaque number (as stored on the file system). +
    + +The following values for +''format'' +are recognized: +.B native , +.B 386bsd , +.B 4bsd , +.B bsdos , +.B freebsd , +.B hpux , +.B isc , +.B linux , +.B netbsd , +.B osf1 , +.B sco , +.B solaris , +.B sunos , +.B svr3 , +.B svr4 , +and +.B ultrix . + +See +[[mknod(8)|http://www.freebsd.org/cgi/man.cgi?query=mknod&sektion=8]] +for more details. +
    '''contents'''
    +The full pathname of a file that holds the contents of this file. +
    '''flags'''
    +The file flags as a symbolic name. +See +[[chflags(1)|http://www.freebsd.org/cgi/man.cgi?query=chflags&sektion=1]] +for information on these names. +If no flags are to be set the string +"none" +may be used to override the current default. +
    '''gid'''
    +The file group as a numeric value. +
    '''gname'''
    +The file group as a symbolic name. +
    '''ignore'''
    +Ignore any file hierarchy below this file. +
    '''inode'''
    +The inode number. +
    '''link'''
    +The target of the symbolic link when type=link. +
    '''md5'''
    +The MD5 message digest of the file. +
    '''md5digest'''
    +A synonym for +'''md5'''. +
    '''mode'''
    +The current file's permissions as a numeric (octal) or symbolic +value. +
    '''nlink'''
    +The number of hard links the file is expected to have. +
    '''nochange'''
    +Make sure this file or directory exists but otherwise ignore all attributes. +
    '''optional'''
    +The file is optional; do not complain about the file if it is not in +the file hierarchy. +
    '''resdevice'''
    +The +"resident" +device number of the file, e.g. the ID of the device that +contains the file. +Its format is the same as the one for +'''device'''. +
    '''ripemd160digest'''
    +The +'''RIPEMD160''' +message digest of the file. +
    '''rmd160'''
    +A synonym for +'''ripemd160digest'''. +
    '''rmd160digest'''
    +A synonym for +'''ripemd160digest'''. +
    '''sha1'''
    +The +'''FIPS''' +160-1 +("Tn SHA-1") +message digest of the file. +
    '''sha1digest'''
    +A synonym for +'''sha1'''. +
    '''sha256'''
    +The +'''FIPS''' +180-2 +("Tn SHA-256") +message digest of the file. +
    '''sha256digest'''
    +A synonym for +'''sha256'''. +
    '''sha384'''
    +The +'''FIPS''' +180-2 +("Tn SHA-384") +message digest of the file. +
    '''sha384digest'''
    +A synonym for +'''sha384'''. +
    '''sha512'''
    +The +'''FIPS''' +180-2 +("Tn SHA-512") +message digest of the file. +
    '''sha512digest'''
    +A synonym for +'''sha512'''. +
    '''size'''
    +The size, in bytes, of the file. +
    '''time'''
    +The last modification time of the file. +
    '''type'''
    +The type of the file; may be set to any one of the following: + +
    +
    '''block'''
    +block special device +
    '''char'''
    +character special device +
    '''dir'''
    +directory +
    '''fifo'''
    +fifo +
    '''file'''
    +regular file +
    '''link'''
    +symbolic link +
    '''socket'''
    +socket +
    +
    '''uid'''
    +The file owner as a numeric value. +
    '''uname'''
    +The file owner as a symbolic name. +
    +== SEE ALSO == +[[cksum(1)|http://www.freebsd.org/cgi/man.cgi?query=cksum&sektion=1]], +[[find(1)|http://www.freebsd.org/cgi/man.cgi?query=find&sektion=1]], +[[mtree(8)|http://www.freebsd.org/cgi/man.cgi?query=mtree&sektion=8]] +== HISTORY == +The +'''mtree''' +utility appeared in +BSD 4.3 Reno. +The +'''MD5''' +digest capability was added in +FreeBSD 2.1, +in response to the widespread use of programs which can spoof +[[cksum(1)|http://www.freebsd.org/cgi/man.cgi?query=cksum&sektion=1]]. +The +'''SHA-1''' +and +'''RIPEMD160''' +digests were added in +FreeBSD 4.0, +as new attacks have demonstrated weaknesses in +'''MD5 .''' +The +'''SHA-256''' +digest was added in +FreeBSD 6.0. +Support for file flags was added in +FreeBSD 4.0, +and mostly comes from +NetBSD. +The +"full" +entry format was added by +NetBSD. diff --git a/dependencies/libarchive-3.4.2/doc/wiki/ManPageTar5.wiki b/dependencies/libarchive-3.4.2/doc/wiki/ManPageTar5.wiki new file mode 100644 index 0000000..c705a26 --- /dev/null +++ b/dependencies/libarchive-3.4.2/doc/wiki/ManPageTar5.wiki @@ -0,0 +1,922 @@ +TAR(5) manual page +== NAME == +'''tar''' +- format of tape archive files +== DESCRIPTION == +The +'''tar''' +archive format collects any number of files, directories, and other +file system objects (symbolic links, device nodes, etc.) into a single +stream of bytes. +The format was originally designed to be used with +tape drives that operate with fixed-size blocks, but is widely used as +a general packaging mechanism. +=== General Format=== +A +'''tar''' +archive consists of a series of 512-byte records. +Each file system object requires a header record which stores basic metadata +(pathname, owner, permissions, etc.) and zero or more records containing any +file data. +The end of the archive is indicated by two records consisting +entirely of zero bytes. + +For compatibility with tape drives that use fixed block sizes, +programs that read or write tar files always read or write a fixed +number of records with each I/O operation. +These +"blocks" +are always a multiple of the record size. +The maximum block size supported by early +implementations was 10240 bytes or 20 records. +This is still the default for most implementations +although block sizes of 1MiB (2048 records) or larger are +commonly used with modern high-speed tape drives. +(Note: the terms +"block" +and +"record" +here are not entirely standard; this document follows the +convention established by John Gilmore in documenting +'''pdtar'''.) +=== Old-Style Archive Format=== +The original tar archive format has been extended many times to +include additional information that various implementors found +necessary. +This section describes the variant implemented by the tar command +included in +At v7, +which seems to be the earliest widely-used version of the tar program. + +The header record for an old-style +'''tar''' +archive consists of the following: +```text +struct header_old_tar { + char name[100]; + char mode[8]; + char uid[8]; + char gid[8]; + char size[12]; + char mtime[12]; + char checksum[8]; + char linkflag[1]; + char linkname[100]; + char pad[255]; +}; +``` +All unused bytes in the header record are filled with nulls. +
    +
    ''name''
    +Pathname, stored as a null-terminated string. +Early tar implementations only stored regular files (including +hardlinks to those files). +One common early convention used a trailing "/" character to indicate +a directory name, allowing directory permissions and owner information +to be archived and restored. +
    ''mode''
    +File mode, stored as an octal number in ASCII. +
    ''uid'', ''gid''
    +User id and group id of owner, as octal numbers in ASCII. +
    ''size''
    +Size of file, as octal number in ASCII. +For regular files only, this indicates the amount of data +that follows the header. +In particular, this field was ignored by early tar implementations +when extracting hardlinks. +Modern writers should always store a zero length for hardlink entries. +
    ''mtime''
    +Modification time of file, as an octal number in ASCII. +This indicates the number of seconds since the start of the epoch, +00:00:00 UTC January 1, 1970. +Note that negative values should be avoided +here, as they are handled inconsistently. +
    ''checksum''
    +Header checksum, stored as an octal number in ASCII. +To compute the checksum, set the checksum field to all spaces, +then sum all bytes in the header using unsigned arithmetic. +This field should be stored as six octal digits followed by a null and a space +character. +Note that many early implementations of tar used signed arithmetic +for the checksum field, which can cause interoperability problems +when transferring archives between systems. +Modern robust readers compute the checksum both ways and accept the +header if either computation matches. +
    ''linkflag'', ''linkname''
    +In order to preserve hardlinks and conserve tape, a file +with multiple links is only written to the archive the first +time it is encountered. +The next time it is encountered, the +''linkflag'' +is set to an ASCII +Sq 1 +and the +''linkname'' +field holds the first name under which this file appears. +(Note that regular files have a null value in the +''linkflag'' +field.) +
    + +Early tar implementations varied in how they terminated these fields. +The tar command in +At v7 +used the following conventions (this is also documented in early BSD manpages): +the pathname must be null-terminated; +the mode, uid, and gid fields must end in a space and a null byte; +the size and mtime fields must end in a space; +the checksum is terminated by a null and a space. +Early implementations filled the numeric fields with leading spaces. +This seems to have been common practice until the +IEEE Std 1003.1-1988 (``POSIX.1'') +standard was released. +For best portability, modern implementations should fill the numeric +fields with leading zeros. +=== Pre-POSIX Archives=== +An early draft of +IEEE Std 1003.1-1988 (``POSIX.1'') +served as the basis for John Gilmore's +'''pdtar''' +program and many system implementations from the late 1980s +and early 1990s. +These archives generally follow the POSIX ustar +format described below with the following variations: +
      +
    • +The magic value consists of the five characters +"ustar" +followed by a space. +The version field contains a space character followed by a null. +
    • +The numeric fields are generally filled with leading spaces +(not leading zeros as recommended in the final standard). +
    • +The prefix field is often not used, limiting pathnames to +the 100 characters of old-style archives. +
    +=== POSIX ustar Archives=== +IEEE Std 1003.1-1988 (``POSIX.1'') +defined a standard tar file format to be read and written +by compliant implementations of +[[ManPageBsdtar1]]. +This format is often called the +"ustar" +format, after the magic value used +in the header. +(The name is an acronym for +"Unix Standard TAR".) +It extends the historic format with new fields: +```text +struct header_posix_ustar { + char name[100]; + char mode[8]; + char uid[8]; + char gid[8]; + char size[12]; + char mtime[12]; + char checksum[8]; + char typeflag[1]; + char linkname[100]; + char magic[6]; + char version[2]; + char uname[32]; + char gname[32]; + char devmajor[8]; + char devminor[8]; + char prefix[155]; + char pad[12]; +}; +``` +
    +
    ''typeflag''
    +Type of entry. +POSIX extended the earlier +''linkflag'' +field with several new type values: +
    +
    "0"
    +Regular file. +NUL should be treated as a synonym, for compatibility purposes. +
    "1"
    +Hard link. +
    "2"
    +Symbolic link. +
    "3"
    +Character device node. +
    "4"
    +Block device node. +
    "5"
    +Directory. +
    "6"
    +FIFO node. +
    "7"
    +Reserved. +
    Other
    +A POSIX-compliant implementation must treat any unrecognized typeflag value +as a regular file. +In particular, writers should ensure that all entries +have a valid filename so that they can be restored by readers that do not +support the corresponding extension. +Uppercase letters "A" through "Z" are reserved for custom extensions. +Note that sockets and whiteout entries are not archivable. +
    +It is worth noting that the +''size'' +field, in particular, has different meanings depending on the type. +For regular files, of course, it indicates the amount of data +following the header. +For directories, it may be used to indicate the total size of all +files in the directory, for use by operating systems that pre-allocate +directory space. +For all other types, it should be set to zero by writers and ignored +by readers. +
    ''magic''
    +Contains the magic value +"ustar" +followed by a NUL byte to indicate that this is a POSIX standard archive. +Full compliance requires the uname and gname fields be properly set. +
    ''version''
    +Version. +This should be +"00" +(two copies of the ASCII digit zero) for POSIX standard archives. +
    ''uname'', ''gname''
    +User and group names, as null-terminated ASCII strings. +These should be used in preference to the uid/gid values +when they are set and the corresponding names exist on +the system. +
    ''devmajor'', ''devminor''
    +Major and minor numbers for character device or block device entry. +
    ''name'', ''prefix''
    +If the pathname is too long to fit in the 100 bytes provided by the standard +format, it can be split at any +''/'' +character with the first portion going into the prefix field. +If the prefix field is not empty, the reader will prepend +the prefix value and a +''/'' +character to the regular name field to obtain the full pathname. +The standard does not require a trailing +''/'' +character on directory names, though most implementations still +include this for compatibility reasons. +
    + +Note that all unused bytes must be set to +NUL. + +Field termination is specified slightly differently by POSIX +than by previous implementations. +The +''magic'', +''uname'', +and +''gname'' +fields must have a trailing +NUL. +The +''pathname'', +''linkname'', +and +''prefix'' +fields must have a trailing +NUL +unless they fill the entire field. +(In particular, it is possible to store a 256-character pathname if it +happens to have a +''/'' +as the 156th character.) +POSIX requires numeric fields to be zero-padded in the front, and requires +them to be terminated with either space or +NUL +characters. + +Currently, most tar implementations comply with the ustar +format, occasionally extending it by adding new fields to the +blank area at the end of the header record. +=== Numeric Extensions=== +There have been several attempts to extend the range of sizes +or times supported by modifying how numbers are stored in the +header. + +One obvious extension to increase the size of files is to +eliminate the terminating characters from the various +numeric fields. +For example, the standard only allows the size field to contain +11 octal digits, reserving the twelfth byte for a trailing +NUL character. +Allowing 12 octal digits allows file sizes up to 64 GB. + +Another extension, utilized by GNU tar, star, and other newer +'''tar''' +implementations, permits binary numbers in the standard numeric fields. +This is flagged by setting the high bit of the first byte. +The remainder of the field is treated as a signed twos-complement +value. +This permits 95-bit values for the length and time fields +and 63-bit values for the uid, gid, and device numbers. +In particular, this provides a consistent way to handle +negative time values. +GNU tar supports this extension for the +length, mtime, ctime, and atime fields. +Joerg Schilling's star program and the libarchive library support +this extension for all numeric fields. +Note that this extension is largely obsoleted by the extended +attribute record provided by the pax interchange format. + +Another early GNU extension allowed base-64 values rather than octal. +This extension was short-lived and is no longer supported by any +implementation. +=== Pax Interchange Format=== +There are many attributes that cannot be portably stored in a +POSIX ustar archive. +IEEE Std 1003.1-2001 (``POSIX.1'') +defined a +"pax interchange format" +that uses two new types of entries to hold text-formatted +metadata that applies to following entries. +Note that a pax interchange format archive is a ustar archive in every +respect. +The new data is stored in ustar-compatible archive entries that use the +"x" +or +"g" +typeflag. +In particular, older implementations that do not fully support these +extensions will extract the metadata into regular files, where the +metadata can be examined as necessary. + +An entry in a pax interchange format archive consists of one or +two standard ustar entries, each with its own header and data. +The first optional entry stores the extended attributes +for the following entry. +This optional first entry has an "x" typeflag and a size field that +indicates the total size of the extended attributes. +The extended attributes themselves are stored as a series of text-format +lines encoded in the portable UTF-8 encoding. +Each line consists of a decimal number, a space, a key string, an equals +sign, a value string, and a new line. +The decimal number indicates the length of the entire line, including the +initial length field and the trailing newline. +An example of such a field is: +```text +25 ctime=1084839148.1212\n +``` +Keys in all lowercase are standard keys. +Vendors can add their own keys by prefixing them with an all uppercase +vendor name and a period. +Note that, unlike the historic header, numeric values are stored using +decimal, not octal. +A description of some common keys follows: +
    +
    '''atime''', '''ctime''', '''mtime'''
    +File access, inode change, and modification times. +These fields can be negative or include a decimal point and a fractional value. +
    '''hdrcharset'''
    +The character set used by the pax extension values. +By default, all textual values in the pax extended attributes +are assumed to be in UTF-8, including pathnames, user names, +and group names. +In some cases, it is not possible to translate local +conventions into UTF-8. +If this key is present and the value is the six-character ASCII string +"BINARY", +then all textual values are assumed to be in a platform-dependent +multi-byte encoding. +Note that there are only two valid values for this key: +"BINARY" +or +"ISO-IR\ 10646\ 2000\ UTF-8". +No other values are permitted by the standard, and +the latter value should generally not be used as it is the +default when this key is not specified. +In particular, this flag should not be used as a general +mechanism to allow filenames to be stored in arbitrary +encodings. +
    '''uname''', '''uid''', '''gname''', '''gid'''
    +User name, group name, and numeric UID and GID values. +The user name and group name stored here are encoded in UTF8 +and can thus include non-ASCII characters. +The UID and GID fields can be of arbitrary length. +
    '''linkpath'''
    +The full path of the linked-to file. +Note that this is encoded in UTF8 and can thus include non-ASCII characters. +
    '''path'''
    +The full pathname of the entry. +Note that this is encoded in UTF8 and can thus include non-ASCII characters. +
    '''realtime.*''', '''security.*'''
    +These keys are reserved and may be used for future standardization. +
    '''size'''
    +The size of the file. +Note that there is no length limit on this field, allowing conforming +archives to store files much larger than the historic 8GB limit. +
    '''SCHILY.*'''
    +Vendor-specific attributes used by Joerg Schilling's +'''star''' +implementation. +
    '''SCHILY.acl.access''', '''SCHILY.acl.default''', '''SCHILY.acl.ace'''
    +Stores the access, default and NFSv4 ACLs as textual strings in a format +that is an extension of the format specified by POSIX.1e draft 17. +In particular, each user or group access specification can include +an additional colon-separated field with the numeric UID or GID. +This allows ACLs to be restored on systems that may not have complete +user or group information available (such as when NIS/YP or LDAP services +are temporarily unavailable). +
    '''SCHILY.devminor''', '''SCHILY.devmajor'''
    +The full minor and major numbers for device nodes. +
    '''SCHILY.fflags'''
    +The file flags. +
    '''SCHILY.realsize'''
    +The full size of the file on disk. +XXX explain? XXX +
    '''SCHILY.dev''', '''SCHILY.ino''', '''SCHILY.nlinks'''
    +The device number, inode number, and link count for the entry. +In particular, note that a pax interchange format archive using Joerg +Schilling's +'''SCHILY.*''' +extensions can store all of the data from +''struct'' stat. +
    '''LIBARCHIVE.*'''
    +Vendor-specific attributes used by the +'''libarchive''' +library and programs that use it. +
    '''LIBARCHIVE.creationtime'''
    +The time when the file was created. +(This should not be confused with the POSIX +"ctime" +attribute, which refers to the time when the file +metadata was last changed.) +
    '''LIBARCHIVE.xattr'''.''namespace''.''key''
    +Libarchive stores POSIX.1e-style extended attributes using +keys of this form. +The +''key'' +value is URL-encoded: +All non-ASCII characters and the two special characters +"=" +and +"%" +are encoded as +"%" +followed by two uppercase hexadecimal digits. +The value of this key is the extended attribute value +encoded in base 64. +XXX Detail the base-64 format here XXX +
    '''VENDOR.*'''
    +XXX document other vendor-specific extensions XXX +
    + +Any values stored in an extended attribute override the corresponding +values in the regular tar header. +Note that compliant readers should ignore the regular fields when they +are overridden. +This is important, as existing archivers are known to store non-compliant +values in the standard header fields in this situation. +There are no limits on length for any of these fields. +In particular, numeric fields can be arbitrarily large. +All text fields are encoded in UTF8. +Compliant writers should store only portable 7-bit ASCII characters in +the standard ustar header and use extended +attributes whenever a text value contains non-ASCII characters. + +In addition to the +'''x''' +entry described above, the pax interchange format +also supports a +'''g''' +entry. +The +'''g''' +entry is identical in format, but specifies attributes that serve as +defaults for all subsequent archive entries. +The +'''g''' +entry is not widely used. + +Besides the new +'''x''' +and +'''g''' +entries, the pax interchange format has a few other minor variations +from the earlier ustar format. +The most troubling one is that hardlinks are permitted to have +data following them. +This allows readers to restore any hardlink to a file without +having to rewind the archive to find an earlier entry. +However, it creates complications for robust readers, as it is no longer +clear whether or not they should ignore the size field for hardlink entries. +=== GNU Tar Archives=== +The GNU tar program started with a pre-POSIX format similar to that +described earlier and has extended it using several different mechanisms: +It added new fields to the empty space in the header (some of which was later +used by POSIX for conflicting purposes); +it allowed the header to be continued over multiple records; +and it defined new entries that modify following entries +(similar in principle to the +'''x''' +entry described above, but each GNU special entry is single-purpose, +unlike the general-purpose +'''x''' +entry). +As a result, GNU tar archives are not POSIX compatible, although +more lenient POSIX-compliant readers can successfully extract most +GNU tar archives. +```text +struct header_gnu_tar { + char name[100]; + char mode[8]; + char uid[8]; + char gid[8]; + char size[12]; + char mtime[12]; + char checksum[8]; + char typeflag[1]; + char linkname[100]; + char magic[6]; + char version[2]; + char uname[32]; + char gname[32]; + char devmajor[8]; + char devminor[8]; + char atime[12]; + char ctime[12]; + char offset[12]; + char longnames[4]; + char unused[1]; + struct { + char offset[12]; + char numbytes[12]; + } sparse[4]; + char isextended[1]; + char realsize[12]; + char pad[17]; +}; +``` +
    +
    ''typeflag''
    +GNU tar uses the following special entry types, in addition to +those defined by POSIX: +
    +
    7
    +GNU tar treats type "7" records identically to type "0" records, +except on one obscure RTOS where they are used to indicate the +pre-allocation of a contiguous file on disk. +
    D
    +This indicates a directory entry. +Unlike the POSIX-standard "5" +typeflag, the header is followed by data records listing the names +of files in this directory. +Each name is preceded by an ASCII "Y" +if the file is stored in this archive or "N" if the file is not +stored in this archive. +Each name is terminated with a null, and +an extra null marks the end of the name list. +The purpose of this +entry is to support incremental backups; a program restoring from +such an archive may wish to delete files on disk that did not exist +in the directory when the archive was made. + +Note that the "D" typeflag specifically violates POSIX, which requires +that unrecognized typeflags be restored as normal files. +In this case, restoring the "D" entry as a file could interfere +with subsequent creation of the like-named directory. +
    K
    +The data for this entry is a long linkname for the following regular entry. +
    L
    +The data for this entry is a long pathname for the following regular entry. +
    M
    +This is a continuation of the last file on the previous volume. +GNU multi-volume archives guarantee that each volume begins with a valid +entry header. +To ensure this, a file may be split, with part stored at the end of one volume, +and part stored at the beginning of the next volume. +The "M" typeflag indicates that this entry continues an existing file. +Such entries can only occur as the first or second entry +in an archive (the latter only if the first entry is a volume label). +The +''size'' +field specifies the size of this entry. +The +''offset'' +field at bytes 369-380 specifies the offset where this file fragment +begins. +The +''realsize'' +field specifies the total size of the file (which must equal +''size'' +plus +''offset''). +When extracting, GNU tar checks that the header file name is the one it is +expecting, that the header offset is in the correct sequence, and that +the sum of offset and size is equal to realsize. +
    N
    +Type "N" records are no longer generated by GNU tar. +They contained a +list of files to be renamed or symlinked after extraction; this was +originally used to support long names. +The contents of this record +are a text description of the operations to be done, in the form +"Rename %s to %s\n" +or +"Symlink %s to %s\n ;" +in either case, both +filenames are escaped using K&R C syntax. +Due to security concerns, "N" records are now generally ignored +when reading archives. +
    S
    +This is a +"sparse" +regular file. +Sparse files are stored as a series of fragments. +The header contains a list of fragment offset/length pairs. +If more than four such entries are required, the header is +extended as necessary with +"extra" +header extensions (an older format that is no longer used), or +"sparse" +extensions. +
    V
    +The +''name'' +field should be interpreted as a tape/volume header name. +This entry should generally be ignored on extraction. +
    +
    ''magic''
    +The magic field holds the five characters +"ustar" +followed by a space. +Note that POSIX ustar archives have a trailing null. +
    ''version''
    +The version field holds a space character followed by a null. +Note that POSIX ustar archives use two copies of the ASCII digit +"0". +
    ''atime'', ''ctime''
    +The time the file was last accessed and the time of +last change of file information, stored in octal as with +''mtime''. +
    ''longnames''
    +This field is apparently no longer used. +
    Sparse ''offset'' / ''numbytes''
    +Each such structure specifies a single fragment of a sparse +file. +The two fields store values as octal numbers. +The fragments are each padded to a multiple of 512 bytes +in the archive. +On extraction, the list of fragments is collected from the +header (including any extension headers), and the data +is then read and written to the file at appropriate offsets. +
    ''isextended''
    +If this is set to non-zero, the header will be followed by additional +"sparse header" +records. +Each such record contains information about as many as 21 additional +sparse blocks as shown here: +```text +struct gnu_sparse_header { + struct { + char offset[12]; + char numbytes[12]; + } sparse[21]; + char isextended[1]; + char padding[7]; +}; +``` +
    ''realsize''
    +A binary representation of the file's complete size, with a much larger range +than the POSIX file size. +In particular, with +'''M''' +type files, the current entry is only a portion of the file. +In that case, the POSIX size field will indicate the size of this +entry; the +''realsize'' +field will indicate the total size of the file. +
    +=== GNU tar pax archives=== +GNU tar 1.14 (XXX check this XXX) and later will write +pax interchange format archives when you specify the +--posix +flag. +This format follows the pax interchange format closely, +using some +'''SCHILY''' +tags and introducing new keywords to store sparse file information. +There have been three iterations of the sparse file support, referred to +as +"0.0", +"0.1", +and +"1.0". +
    +
    '''GNU.sparse.numblocks''', '''GNU.sparse.offset''', '''GNU.sparse.numbytes''', '''GNU.sparse.size'''
    +The +"0.0" +format used an initial +'''GNU.sparse.numblocks''' +attribute to indicate the number of blocks in the file, a pair of +'''GNU.sparse.offset''' +and +'''GNU.sparse.numbytes''' +to indicate the offset and size of each block, +and a single +'''GNU.sparse.size''' +to indicate the full size of the file. +This is not the same as the size in the tar header because the +latter value does not include the size of any holes. +This format required that the order of attributes be preserved and +relied on readers accepting multiple appearances of the same attribute +names, which is not officially permitted by the standards. +
    '''GNU.sparse.map'''
    +The +"0.1" +format used a single attribute that stored a comma-separated +list of decimal numbers. +Each pair of numbers indicated the offset and size, respectively, +of a block of data. +This does not work well if the archive is extracted by an archiver +that does not recognize this extension, since many pax implementations +simply discard unrecognized attributes. +
    '''GNU.sparse.major''', '''GNU.sparse.minor''', '''GNU.sparse.name''', '''GNU.sparse.realsize'''
    +The +"1.0" +format stores the sparse block map in one or more 512-byte blocks +prepended to the file data in the entry body. +The pax attributes indicate the existence of this map +(via the +'''GNU.sparse.major''' +and +'''GNU.sparse.minor''' +fields) +and the full size of the file. +The +'''GNU.sparse.name''' +holds the true name of the file. +To avoid confusion, the name stored in the regular tar header +is a modified name so that extraction errors will be apparent +to users. +
    +=== Solaris Tar=== +XXX More Details Needed XXX + +Solaris tar (beginning with SunOS XXX 5.7 ?? XXX) supports an +"extended" +format that is fundamentally similar to pax interchange format, +with the following differences: +
      +
    • +Extended attributes are stored in an entry whose type is +'''X''', +not +'''x''', +as used by pax interchange format. +The detailed format of this entry appears to be the same +as detailed above for the +'''x''' +entry. +
    • +An additional +'''A''' +header is used to store an ACL for the following regular entry. +The body of this entry contains a seven-digit octal number +followed by a zero byte, followed by the +textual ACL description. +The octal value is the number of ACL entries +plus a constant that indicates the ACL type: 01000000 +for POSIX.1e ACLs and 03000000 for NFSv4 ACLs. +
    +=== AIX Tar=== +XXX More details needed XXX + +AIX Tar uses a ustar-formatted header with the type +'''A''' +for storing coded ACL information. +Unlike the Solaris format, AIX tar writes this header after the +regular file body to which it applies. +The pathname in this header is either +'''NFS4''' +or +'''AIXC''' +to indicate the type of ACL stored. +The actual ACL is stored in platform-specific binary format. +=== Mac OS X Tar=== +The tar distributed with Apple's Mac OS X stores most regular files +as two separate files in the tar archive. +The two files have the same name except that the first +one has +"._" +prepended to the last path element. +This special file stores an AppleDouble-encoded +binary blob with additional metadata about the second file, +including ACL, extended attributes, and resources. +To recreate the original file on disk, each +separate file can be extracted and the Mac OS X +'''copyfile'''() +function can be used to unpack the separate +metadata file and apply it to th regular file. +Conversely, the same function provides a +"pack" +option to encode the extended metadata from +a file into a separate file whose contents +can then be put into a tar archive. + +Note that the Apple extended attributes interact +badly with long filenames. +Since each file is stored with the full name, +a separate set of extensions needs to be included +in the archive for each one, doubling the overhead +required for files with long names. +=== Summary of tar type codes=== +The following list is a condensed summary of the type codes +used in tar header records generated by different tar implementations. +More details about specific implementations can be found above: +
    +
    NUL
    +Early tar programs stored a zero byte for regular files. +
    '''0'''
    +POSIX standard type code for a regular file. +
    '''1'''
    +POSIX standard type code for a hard link description. +
    '''2'''
    +POSIX standard type code for a symbolic link description. +
    '''3'''
    +POSIX standard type code for a character device node. +
    '''4'''
    +POSIX standard type code for a block device node. +
    '''5'''
    +POSIX standard type code for a directory. +
    '''6'''
    +POSIX standard type code for a FIFO. +
    '''7'''
    +POSIX reserved. +
    '''7'''
    +GNU tar used for pre-allocated files on some systems. +
    '''A'''
    +Solaris tar ACL description stored prior to a regular file header. +
    '''A'''
    +AIX tar ACL description stored after the file body. +
    '''D'''
    +GNU tar directory dump. +
    '''K'''
    +GNU tar long linkname for the following header. +
    '''L'''
    +GNU tar long pathname for the following header. +
    '''M'''
    +GNU tar multivolume marker, indicating the file is a continuation of a file from the previous volume. +
    '''N'''
    +GNU tar long filename support. +Deprecated. +
    '''S'''
    +GNU tar sparse regular file. +
    '''V'''
    +GNU tar tape/volume header name. +
    '''X'''
    +Solaris tar general-purpose extension header. +
    '''g'''
    +POSIX pax interchange format global extensions. +
    '''x'''
    +POSIX pax interchange format per-file extensions. +
    +== SEE ALSO == +[[ar(1)|http://www.freebsd.org/cgi/man.cgi?query=ar&sektion=1]], +[[pax(1)|http://www.freebsd.org/cgi/man.cgi?query=pax&sektion=1]], +[[ManPageBsdtar1]] +== STANDARDS == +The +'''tar''' +utility is no longer a part of POSIX or the Single Unix Standard. +It last appeared in +Version 2 of the Single UNIX Specification (``SUSv2''). +It has been supplanted in subsequent standards by +[[pax(1)|http://www.freebsd.org/cgi/man.cgi?query=pax&sektion=1]]. +The ustar format is currently part of the specification for the +[[pax(1)|http://www.freebsd.org/cgi/man.cgi?query=pax&sektion=1]] +utility. +The pax interchange file format is new with +IEEE Std 1003.1-2001 (``POSIX.1''). +== HISTORY == +A +'''tar''' +command appeared in Seventh Edition Unix, which was released in January, 1979. +It replaced the +'''tp''' +program from Fourth Edition Unix which in turn replaced the +'''tap''' +program from First Edition Unix. +John Gilmore's +'''pdtar''' +public-domain implementation (circa 1987) was highly influential +and formed the basis of +'''GNU''' tar +(circa 1988). +Joerg Shilling's +'''star''' +archiver is another open-source (CDDL) archiver (originally developed +circa 1985) which features complete support for pax interchange +format. + +This documentation was written as part of the +'''libarchive''' +and +'''bsdtar''' +project by +Tim Kientzle <kientzle@FreeBSD.org.> diff --git a/dependencies/libarchive-3.4.2/examples/minitar/README b/dependencies/libarchive-3.4.2/examples/minitar/README new file mode 100644 index 0000000..83f646c --- /dev/null +++ b/dependencies/libarchive-3.4.2/examples/minitar/README @@ -0,0 +1,12 @@ +"minitar" is a minimal example of a program that uses libarchive to +read/write various archive formats. It's a more ambitious version of +'untar.c' that includes compile-time options to enable/disable various +features, including non-tar formats, archive creation, and automatic +decompression support. + +I use this as a test bed to check for "link pollution," ensuring that +a program using libarchive does not pull in unnecessary code. + +The "minitar" program is also a good starting point for anyone who +wants to use libarchive for their own purposes, as it demonstrates +basic usage of the library. diff --git a/dependencies/libarchive-3.4.2/examples/minitar/minitar.c b/dependencies/libarchive-3.4.2/examples/minitar/minitar.c new file mode 100644 index 0000000..881f94b --- /dev/null +++ b/dependencies/libarchive-3.4.2/examples/minitar/minitar.c @@ -0,0 +1,471 @@ +/*- + * This file is in the public domain. + * Do with it as you will. + */ + +/*- + * This is a compact "tar" program whose primary goal is small size. + * Statically linked, it can be very small indeed. This serves a number + * of goals: + * o a testbed for libarchive (to check for link pollution), + * o a useful tool for space-constrained systems (boot floppies, etc), + * o a place to experiment with new implementation ideas for bsdtar, + * o a small program to demonstrate libarchive usage. + * + * Use the following macros to suppress features: + * NO_BZIP2 - Implies NO_BZIP2_CREATE and NO_BZIP2_EXTRACT + * NO_BZIP2_CREATE - Suppress bzip2 compression support. + * NO_BZIP2_EXTRACT - Suppress bzip2 auto-detection and decompression. + * NO_COMPRESS - Implies NO_COMPRESS_CREATE and NO_COMPRESS_EXTRACT + * NO_COMPRESS_CREATE - Suppress compress(1) compression support + * NO_COMPRESS_EXTRACT - Suppress compress(1) auto-detect and decompression. + * NO_CREATE - Suppress all archive creation support. + * NO_CPIO_EXTRACT - Suppress auto-detect and dearchiving of cpio archives. + * NO_GZIP - Implies NO_GZIP_CREATE and NO_GZIP_EXTRACT + * NO_GZIP_CREATE - Suppress gzip compression support. + * NO_GZIP_EXTRACT - Suppress gzip auto-detection and decompression. + * NO_LOOKUP - Try to avoid getpw/getgr routines, which can be very large + * NO_TAR_EXTRACT - Suppress tar extraction + * + * With all of the above macros defined (except NO_TAR_EXTRACT), you + * get a very small program that can recognize and extract essentially + * any uncompressed tar archive. On FreeBSD 5.1, this minimal program + * is under 64k, statically linked, which compares rather favorably to + * main(){printf("hello, world");} + * which is over 60k statically linked on the same operating system. + * Without any of the above macros, you get a static executable of + * about 180k with a lot of very sophisticated modern features. + * Obviously, it's trivial to add support for ISO, Zip, mtree, + * lzma/xz, etc. Just fill in the appropriate setup calls. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* + * NO_CREATE implies NO_BZIP2_CREATE and NO_GZIP_CREATE and NO_COMPRESS_CREATE. + */ +#ifdef NO_CREATE +#undef NO_BZIP2_CREATE +#define NO_BZIP2_CREATE +#undef NO_COMPRESS_CREATE +#define NO_COMPRESS_CREATE +#undef NO_GZIP_CREATE +#define NO_GZIP_CREATE +#endif + +/* + * The combination of NO_BZIP2_CREATE and NO_BZIP2_EXTRACT is + * equivalent to NO_BZIP2. + */ +#ifdef NO_BZIP2_CREATE +#ifdef NO_BZIP2_EXTRACT +#undef NO_BZIP2 +#define NO_BZIP2 +#endif +#endif + +#ifdef NO_BZIP2 +#undef NO_BZIP2_EXTRACT +#define NO_BZIP2_EXTRACT +#undef NO_BZIP2_CREATE +#define NO_BZIP2_CREATE +#endif + +/* + * The combination of NO_COMPRESS_CREATE and NO_COMPRESS_EXTRACT is + * equivalent to NO_COMPRESS. + */ +#ifdef NO_COMPRESS_CREATE +#ifdef NO_COMPRESS_EXTRACT +#undef NO_COMPRESS +#define NO_COMPRESS +#endif +#endif + +#ifdef NO_COMPRESS +#undef NO_COMPRESS_EXTRACT +#define NO_COMPRESS_EXTRACT +#undef NO_COMPRESS_CREATE +#define NO_COMPRESS_CREATE +#endif + +/* + * The combination of NO_GZIP_CREATE and NO_GZIP_EXTRACT is + * equivalent to NO_GZIP. + */ +#ifdef NO_GZIP_CREATE +#ifdef NO_GZIP_EXTRACT +#undef NO_GZIP +#define NO_GZIP +#endif +#endif + +#ifdef NO_GZIP +#undef NO_GZIP_EXTRACT +#define NO_GZIP_EXTRACT +#undef NO_GZIP_CREATE +#define NO_GZIP_CREATE +#endif + +#ifndef NO_CREATE +static void create(const char *filename, int compress, const char **argv); +#endif +static void errmsg(const char *); +static void extract(const char *filename, int do_extract, int flags); +static int copy_data(struct archive *, struct archive *); +static void msg(const char *); +static void usage(void); + +static int verbose = 0; + +int +main(int argc, const char **argv) +{ + const char *filename = NULL; + int compress, flags, mode, opt; + + (void)argc; + mode = 'x'; + verbose = 0; + compress = '\0'; + flags = ARCHIVE_EXTRACT_TIME; + + /* Among other sins, getopt(3) pulls in printf(3). */ + while (*++argv != NULL && **argv == '-') { + const char *p = *argv + 1; + + while ((opt = *p++) != '\0') { + switch (opt) { +#ifndef NO_CREATE + case 'c': + mode = opt; + break; +#endif + case 'f': + if (*p != '\0') + filename = p; + else + filename = *++argv; + p += strlen(p); + break; +#ifndef NO_BZIP2_CREATE + case 'j': + compress = opt; + break; +#endif + case 'p': + flags |= ARCHIVE_EXTRACT_PERM; + flags |= ARCHIVE_EXTRACT_ACL; + flags |= ARCHIVE_EXTRACT_FFLAGS; + break; + case 't': + mode = opt; + break; + case 'v': + verbose++; + break; + case 'x': + mode = opt; + break; +#ifndef NO_BZIP2_CREATE + case 'y': + compress = opt; + break; +#endif +#ifndef NO_COMPRESS_CREATE + case 'Z': + compress = opt; + break; +#endif +#ifndef NO_GZIP_CREATE + case 'z': + compress = opt; + break; +#endif + default: + usage(); + } + } + } + + switch (mode) { +#ifndef NO_CREATE + case 'c': + create(filename, compress, argv); + break; +#endif + case 't': + extract(filename, 0, flags); + break; + case 'x': + extract(filename, 1, flags); + break; + } + + return (0); +} + + +#ifndef NO_CREATE +static char buff[16384]; + +static void +create(const char *filename, int compress, const char **argv) +{ + struct archive *a; + struct archive_entry *entry; + ssize_t len; + int fd; + + a = archive_write_new(); + switch (compress) { +#ifndef NO_BZIP2_CREATE + case 'j': case 'y': + archive_write_add_filter_bzip2(a); + break; +#endif +#ifndef NO_COMPRESS_CREATE + case 'Z': + archive_write_add_filter_compress(a); + break; +#endif +#ifndef NO_GZIP_CREATE + case 'z': + archive_write_add_filter_gzip(a); + break; +#endif + default: + archive_write_add_filter_none(a); + break; + } + archive_write_set_format_ustar(a); + if (filename != NULL && strcmp(filename, "-") == 0) + filename = NULL; + archive_write_open_filename(a, filename); + + while (*argv != NULL) { + struct archive *disk = archive_read_disk_new(); +#ifndef NO_LOOKUP + archive_read_disk_set_standard_lookup(disk); +#endif + int r; + + r = archive_read_disk_open(disk, *argv); + if (r != ARCHIVE_OK) { + errmsg(archive_error_string(disk)); + errmsg("\n"); + exit(1); + } + + for (;;) { + int needcr = 0; + + entry = archive_entry_new(); + r = archive_read_next_header2(disk, entry); + if (r == ARCHIVE_EOF) + break; + if (r != ARCHIVE_OK) { + errmsg(archive_error_string(disk)); + errmsg("\n"); + exit(1); + } + archive_read_disk_descend(disk); + if (verbose) { + msg("a "); + msg(archive_entry_pathname(entry)); + needcr = 1; + } + r = archive_write_header(a, entry); + if (r < ARCHIVE_OK) { + errmsg(": "); + errmsg(archive_error_string(a)); + needcr = 1; + } + if (r == ARCHIVE_FATAL) + exit(1); + if (r > ARCHIVE_FAILED) { +#if 0 + /* Ideally, we would be able to use + * the same code to copy a body from + * an archive_read_disk to an + * archive_write that we use for + * copying data from an archive_read + * to an archive_write_disk. + * Unfortunately, this doesn't quite + * work yet. */ + copy_data(disk, a); +#else + /* For now, we use a simpler loop to copy data + * into the target archive. */ + fd = open(archive_entry_sourcepath(entry), O_RDONLY); + len = read(fd, buff, sizeof(buff)); + while (len > 0) { + archive_write_data(a, buff, len); + len = read(fd, buff, sizeof(buff)); + } + close(fd); +#endif + } + archive_entry_free(entry); + if (needcr) + msg("\n"); + } + archive_read_close(disk); + archive_read_free(disk); + argv++; + } + archive_write_close(a); + archive_write_free(a); +} +#endif + +static void +extract(const char *filename, int do_extract, int flags) +{ + struct archive *a; + struct archive *ext; + struct archive_entry *entry; + int r; + + a = archive_read_new(); + ext = archive_write_disk_new(); + archive_write_disk_set_options(ext, flags); +#ifndef NO_BZIP2_EXTRACT + archive_read_support_filter_bzip2(a); +#endif +#ifndef NO_GZIP_EXTRACT + archive_read_support_filter_gzip(a); +#endif +#ifndef NO_COMPRESS_EXTRACT + archive_read_support_filter_compress(a); +#endif +#ifndef NO_TAR_EXTRACT + archive_read_support_format_tar(a); +#endif +#ifndef NO_CPIO_EXTRACT + archive_read_support_format_cpio(a); +#endif +#ifndef NO_LOOKUP + archive_write_disk_set_standard_lookup(ext); +#endif + if (filename != NULL && strcmp(filename, "-") == 0) + filename = NULL; + if ((r = archive_read_open_filename(a, filename, 10240))) { + errmsg(archive_error_string(a)); + errmsg("\n"); + exit(r); + } + for (;;) { + int needcr = 0; + r = archive_read_next_header(a, &entry); + if (r == ARCHIVE_EOF) + break; + if (r != ARCHIVE_OK) { + errmsg(archive_error_string(a)); + errmsg("\n"); + exit(1); + } + if (verbose && do_extract) + msg("x "); + if (verbose || !do_extract) { + msg(archive_entry_pathname(entry)); + msg(" "); + needcr = 1; + } + if (do_extract) { + r = archive_write_header(ext, entry); + if (r != ARCHIVE_OK) { + errmsg(archive_error_string(a)); + needcr = 1; + } + else { + r = copy_data(a, ext); + if (r != ARCHIVE_OK) + needcr = 1; + } + } + if (needcr) + msg("\n"); + } + archive_read_close(a); + archive_read_free(a); + + archive_write_close(ext); + archive_write_free(ext); + exit(0); +} + +static int +copy_data(struct archive *ar, struct archive *aw) +{ + int r; + const void *buff; + size_t size; + int64_t offset; + + for (;;) { + r = archive_read_data_block(ar, &buff, &size, &offset); + if (r == ARCHIVE_EOF) + return (ARCHIVE_OK); + if (r != ARCHIVE_OK) { + errmsg(archive_error_string(ar)); + return (r); + } + r = archive_write_data_block(aw, buff, size, offset); + if (r != ARCHIVE_OK) { + errmsg(archive_error_string(ar)); + return (r); + } + } +} + +static void +msg(const char *m) +{ + write(1, m, strlen(m)); +} + +static void +errmsg(const char *m) +{ + if (m == NULL) { + m = "Error: No error description provided.\n"; + } + write(2, m, strlen(m)); +} + +static void +usage(void) +{ +/* Many program options depend on compile options. */ + const char *m = "Usage: minitar [-" +#ifndef NO_CREATE + "c" +#endif +#ifndef NO_BZIP2 + "j" +#endif + "tvx" +#ifndef NO_BZIP2 + "y" +#endif +#ifndef NO_COMPRESS + "Z" +#endif +#ifndef NO_GZIP + "z" +#endif + "] [-f file] [file]\n"; + + errmsg(m); + exit(1); +} diff --git a/dependencies/libarchive-3.4.2/examples/tarfilter.c b/dependencies/libarchive-3.4.2/examples/tarfilter.c new file mode 100644 index 0000000..0d323e1 --- /dev/null +++ b/dependencies/libarchive-3.4.2/examples/tarfilter.c @@ -0,0 +1,113 @@ +/* + * This file is in the public domain. + * + * Feel free to use it as you wish. + */ + +/* + * This example program reads an archive from stdin (which can be in + * any format recognized by libarchive) and writes certain entries to + * an uncompressed ustar archive on stdout. This is a template for + * many kinds of archive manipulation: converting formats, resetting + * ownership, inserting entries, removing entries, etc. + * + * To compile: + * gcc -Wall -o tarfilter tarfilter.c -larchive -lz -lbz2 + */ + +#include +#include +#include +#include +#include +#include + +static void +die(char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + exit(1); +} + +int +main(int argc, char **argv) +{ + char buff[8192]; + ssize_t len; + int r; + mode_t m; + struct archive *ina; + struct archive *outa; + struct archive_entry *entry; + + /* Read an archive from stdin, with automatic format detection. */ + ina = archive_read_new(); + if (ina == NULL) + die("Couldn't create archive reader."); + if (archive_read_support_filter_all(ina) != ARCHIVE_OK) + die("Couldn't enable decompression"); + if (archive_read_support_format_all(ina) != ARCHIVE_OK) + die("Couldn't enable read formats"); + if (archive_read_open_fd(ina, 0, 10240) != ARCHIVE_OK) + die("Couldn't open input archive"); + + /* Write an uncompressed ustar archive to stdout. */ + outa = archive_write_new(); + if (outa == NULL) + die("Couldn't create archive writer."); + if (archive_write_set_compression_none(outa) != ARCHIVE_OK) + die("Couldn't enable compression"); + if (archive_write_set_format_ustar(outa) != ARCHIVE_OK) + die("Couldn't set output format"); + if (archive_write_open_fd(outa, 1) != ARCHIVE_OK) + die("Couldn't open output archive"); + + /* Examine each entry in the input archive. */ + while ((r = archive_read_next_header(ina, &entry)) == ARCHIVE_OK) { + fprintf(stderr, "%s: ", archive_entry_pathname(entry)); + + /* Skip anything that isn't a regular file. */ + if (!S_ISREG(archive_entry_mode(entry))) { + fprintf(stderr, "skipped\n"); + continue; + } + + /* Make everything owned by root/wheel. */ + archive_entry_set_uid(entry, 0); + archive_entry_set_uname(entry, "root"); + archive_entry_set_gid(entry, 0); + archive_entry_set_gname(entry, "wheel"); + + /* Make everything permission 0744, strip SUID, etc. */ + m = archive_entry_mode(entry); + archive_entry_set_mode(entry, (m & ~07777) | 0744); + + /* Copy input entries to output archive. */ + if (archive_write_header(outa, entry) != ARCHIVE_OK) + die("Error writing output archive"); + if (archive_entry_size(entry) > 0) { + len = archive_read_data(ina, buff, sizeof(buff)); + while (len > 0) { + if (archive_write_data(outa, buff, len) != len) + die("Error writing output archive"); + len = archive_read_data(ina, buff, sizeof(buff)); + } + if (len < 0) + die("Error reading input archive"); + } + fprintf(stderr, "copied\n"); + } + if (r != ARCHIVE_EOF) + die("Error reading archive"); + /* Close the archives. */ + if (archive_read_free(ina) != ARCHIVE_OK) + die("Error closing input archive"); + if (archive_write_free(outa) != ARCHIVE_OK) + die("Error closing output archive"); + return (0); +} diff --git a/dependencies/libarchive-3.4.2/examples/untar.c b/dependencies/libarchive-3.4.2/examples/untar.c new file mode 100644 index 0000000..dab75d2 --- /dev/null +++ b/dependencies/libarchive-3.4.2/examples/untar.c @@ -0,0 +1,268 @@ +/* + * This file is in the public domain. + * Use it as you wish. + */ + +/* + * This is a compact tar extraction program using libarchive whose + * primary goal is small executable size. Statically linked, it can + * be very small, depending in large part on how cleanly factored your + * system libraries are. Note that this uses the standard libarchive, + * without any special recompilation. The only functional concession + * is that this program uses the uid/gid from the archive instead of + * doing uname/gname lookups. (Add a call to + * archive_write_disk_set_standard_lookup() to enable uname/gname + * lookups, but be aware that this can add 500k or more to a static + * executable, depending on the system libraries, since user/group + * lookups frequently pull in password, YP/LDAP, networking, and DNS + * resolver libraries.) + * + * To build: + * $ gcc -static -Wall -o untar untar.c -larchive + * $ strip untar + * + * NOTE: On some systems, you may need to add additional flags + * to ensure that untar.c is compiled the same way as libarchive + * was compiled. In particular, Linux users will probably + * have to add -D_FILE_OFFSET_BITS=64 to the command line above. + * + * For fun, statically compile the following simple hello.c program + * using the same flags as for untar and compare the size: + * + * #include + * int main(int argc, char **argv) { + * printf("hello, world\n"); + * return(0); + * } + * + * You may be even more surprised by the compiled size of true.c listed here: + * + * int main(int argc, char **argv) { + * return (0); + * } + * + * On a slightly customized FreeBSD 5 system that I used around + * 2005, hello above compiled to 89k compared to untar of 69k. So at + * that time, libarchive's tar reader and extract-to-disk routines + * compiled to less code than printf(). + * + * On my FreeBSD development system today (August, 2009): + * hello: 195024 bytes + * true: 194912 bytes + * untar: 259924 bytes + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +static void errmsg(const char *); +static void extract(const char *filename, int do_extract, int flags); +static void fail(const char *, const char *, int); +static int copy_data(struct archive *, struct archive *); +static void msg(const char *); +static void usage(void); +static void warn(const char *, const char *); + +static int verbose = 0; + +int +main(int argc, const char **argv) +{ + const char *filename = NULL; + int compress, flags, mode, opt; + + (void)argc; + mode = 'x'; + verbose = 0; + compress = '\0'; + flags = ARCHIVE_EXTRACT_TIME; + + /* Among other sins, getopt(3) pulls in printf(3). */ + while (*++argv != NULL && **argv == '-') { + const char *p = *argv + 1; + + while ((opt = *p++) != '\0') { + switch (opt) { + case 'f': + if (*p != '\0') + filename = p; + else + filename = *++argv; + p += strlen(p); + break; + case 'p': + flags |= ARCHIVE_EXTRACT_PERM; + flags |= ARCHIVE_EXTRACT_ACL; + flags |= ARCHIVE_EXTRACT_FFLAGS; + break; + case 't': + mode = opt; + break; + case 'v': + verbose++; + break; + case 'x': + mode = opt; + break; + default: + usage(); + } + } + } + + switch (mode) { + case 't': + extract(filename, 0, flags); + break; + case 'x': + extract(filename, 1, flags); + break; + } + + return (0); +} + + +static void +extract(const char *filename, int do_extract, int flags) +{ + struct archive *a; + struct archive *ext; + struct archive_entry *entry; + int r; + + a = archive_read_new(); + ext = archive_write_disk_new(); + archive_write_disk_set_options(ext, flags); + /* + * Note: archive_write_disk_set_standard_lookup() is useful + * here, but it requires library routines that can add 500k or + * more to a static executable. + */ + archive_read_support_format_tar(a); + /* + * On my system, enabling other archive formats adds 20k-30k + * each. Enabling gzip decompression adds about 20k. + * Enabling bzip2 is more expensive because the libbz2 library + * isn't very well factored. + */ + if (filename != NULL && strcmp(filename, "-") == 0) + filename = NULL; + if ((r = archive_read_open_filename(a, filename, 10240))) + fail("archive_read_open_filename()", + archive_error_string(a), r); + for (;;) { + r = archive_read_next_header(a, &entry); + if (r == ARCHIVE_EOF) + break; + if (r != ARCHIVE_OK) + fail("archive_read_next_header()", + archive_error_string(a), 1); + if (verbose && do_extract) + msg("x "); + if (verbose || !do_extract) + msg(archive_entry_pathname(entry)); + if (do_extract) { + r = archive_write_header(ext, entry); + if (r != ARCHIVE_OK) + warn("archive_write_header()", + archive_error_string(ext)); + else { + copy_data(a, ext); + r = archive_write_finish_entry(ext); + if (r != ARCHIVE_OK) + fail("archive_write_finish_entry()", + archive_error_string(ext), 1); + } + + } + if (verbose || !do_extract) + msg("\n"); + } + archive_read_close(a); + archive_read_free(a); + + archive_write_close(ext); + archive_write_free(ext); + exit(0); +} + +static int +copy_data(struct archive *ar, struct archive *aw) +{ + int r; + const void *buff; + size_t size; +#if ARCHIVE_VERSION_NUMBER >= 3000000 + int64_t offset; +#else + off_t offset; +#endif + + for (;;) { + r = archive_read_data_block(ar, &buff, &size, &offset); + if (r == ARCHIVE_EOF) + return (ARCHIVE_OK); + if (r != ARCHIVE_OK) + return (r); + r = archive_write_data_block(aw, buff, size, offset); + if (r != ARCHIVE_OK) { + warn("archive_write_data_block()", + archive_error_string(aw)); + return (r); + } + } +} + +/* + * These reporting functions use low-level I/O; on some systems, this + * is a significant code reduction. Of course, on many server and + * desktop operating systems, malloc() and even crt rely on printf(), + * which in turn pulls in most of the rest of stdio, so this is not an + * optimization at all there. (If you're going to pay 100k or more + * for printf() anyway, you may as well use it!) + */ +static void +msg(const char *m) +{ + write(1, m, strlen(m)); +} + +static void +errmsg(const char *m) +{ + write(2, m, strlen(m)); +} + +static void +warn(const char *f, const char *m) +{ + errmsg(f); + errmsg(" failed: "); + errmsg(m); + errmsg("\n"); +} + +static void +fail(const char *f, const char *m, int r) +{ + warn(f, m); + exit(r); +} + +static void +usage(void) +{ + const char *m = "Usage: untar [-tvx] [-f file] [file]\n"; + errmsg(m); + exit(1); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/CMakeLists.txt b/dependencies/libarchive-3.4.2/libarchive/CMakeLists.txt new file mode 100644 index 0000000..fa43288 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/CMakeLists.txt @@ -0,0 +1,265 @@ + +############################################ +# +# How to build libarchive +# +############################################ + +# Public headers +SET(include_HEADERS + archive.h + archive_entry.h +) + +# Sources and private headers +SET(libarchive_SOURCES + archive_acl.c + archive_acl_private.h + archive_check_magic.c + archive_cmdline.c + archive_cmdline_private.h + archive_crc32.h + archive_cryptor.c + archive_cryptor_private.h + archive_digest.c + archive_digest_private.h + archive_endian.h + archive_entry.c + archive_entry.h + archive_entry_copy_stat.c + archive_entry_link_resolver.c + archive_entry_locale.h + archive_entry_private.h + archive_entry_sparse.c + archive_entry_stat.c + archive_entry_strmode.c + archive_entry_xattr.c + archive_getdate.c + archive_getdate.h + archive_hmac.c + archive_hmac_private.h + archive_match.c + archive_openssl_evp_private.h + archive_openssl_hmac_private.h + archive_options.c + archive_options_private.h + archive_pack_dev.h + archive_pack_dev.c + archive_pathmatch.c + archive_pathmatch.h + archive_platform.h + archive_platform_acl.h + archive_platform_xattr.h + archive_ppmd_private.h + archive_ppmd8.c + archive_ppmd8_private.h + archive_ppmd7.c + archive_ppmd7_private.h + archive_private.h + archive_random.c + archive_random_private.h + archive_rb.c + archive_rb.h + archive_read.c + archive_read_add_passphrase.c + archive_read_append_filter.c + archive_read_data_into_fd.c + archive_read_disk_entry_from_file.c + archive_read_disk_posix.c + archive_read_disk_private.h + archive_read_disk_set_standard_lookup.c + archive_read_extract.c + archive_read_extract2.c + archive_read_open_fd.c + archive_read_open_file.c + archive_read_open_filename.c + archive_read_open_memory.c + archive_read_private.h + archive_read_set_format.c + archive_read_set_options.c + archive_read_support_filter_all.c + archive_read_support_filter_bzip2.c + archive_read_support_filter_compress.c + archive_read_support_filter_gzip.c + archive_read_support_filter_grzip.c + archive_read_support_filter_lrzip.c + archive_read_support_filter_lz4.c + archive_read_support_filter_lzop.c + archive_read_support_filter_none.c + archive_read_support_filter_program.c + archive_read_support_filter_rpm.c + archive_read_support_filter_uu.c + archive_read_support_filter_xz.c + archive_read_support_filter_zstd.c + archive_read_support_format_7zip.c + archive_read_support_format_all.c + archive_read_support_format_ar.c + archive_read_support_format_by_code.c + archive_read_support_format_cab.c + archive_read_support_format_cpio.c + archive_read_support_format_empty.c + archive_read_support_format_iso9660.c + archive_read_support_format_lha.c + archive_read_support_format_mtree.c + archive_read_support_format_rar.c + archive_read_support_format_rar5.c + archive_read_support_format_raw.c + archive_read_support_format_tar.c + archive_read_support_format_warc.c + archive_read_support_format_xar.c + archive_read_support_format_zip.c + archive_string.c + archive_string.h + archive_string_composition.h + archive_string_sprintf.c + archive_util.c + archive_version_details.c + archive_virtual.c + archive_write.c + archive_write_disk_posix.c + archive_write_disk_private.h + archive_write_disk_set_standard_lookup.c + archive_write_private.h + archive_write_open_fd.c + archive_write_open_file.c + archive_write_open_filename.c + archive_write_open_memory.c + archive_write_add_filter.c + archive_write_add_filter_b64encode.c + archive_write_add_filter_by_name.c + archive_write_add_filter_bzip2.c + archive_write_add_filter_compress.c + archive_write_add_filter_grzip.c + archive_write_add_filter_gzip.c + archive_write_add_filter_lrzip.c + archive_write_add_filter_lz4.c + archive_write_add_filter_lzop.c + archive_write_add_filter_none.c + archive_write_add_filter_program.c + archive_write_add_filter_uuencode.c + archive_write_add_filter_xz.c + archive_write_add_filter_zstd.c + archive_write_set_format.c + archive_write_set_format_7zip.c + archive_write_set_format_ar.c + archive_write_set_format_by_name.c + archive_write_set_format_cpio.c + archive_write_set_format_cpio_newc.c + archive_write_set_format_filter_by_ext.c + archive_write_set_format_gnutar.c + archive_write_set_format_iso9660.c + archive_write_set_format_mtree.c + archive_write_set_format_pax.c + archive_write_set_format_private.h + archive_write_set_format_raw.c + archive_write_set_format_shar.c + archive_write_set_format_ustar.c + archive_write_set_format_v7tar.c + archive_write_set_format_warc.c + archive_write_set_format_xar.c + archive_write_set_format_zip.c + archive_write_set_options.c + archive_write_set_passphrase.c + archive_xxhash.h + filter_fork_posix.c + filter_fork.h + xxhash.c +) + +# Man pages +SET(libarchive_MANS + archive_entry.3 + archive_entry_acl.3 + archive_entry_linkify.3 + archive_entry_misc.3 + archive_entry_paths.3 + archive_entry_perms.3 + archive_entry_stat.3 + archive_entry_time.3 + archive_read.3 + archive_read_add_passphrase.3 + archive_read_data.3 + archive_read_disk.3 + archive_read_extract.3 + archive_read_filter.3 + archive_read_format.3 + archive_read_free.3 + archive_read_header.3 + archive_read_new.3 + archive_read_open.3 + archive_read_set_options.3 + archive_util.3 + archive_write.3 + archive_write_blocksize.3 + archive_write_data.3 + archive_write_disk.3 + archive_write_filter.3 + archive_write_finish_entry.3 + archive_write_format.3 + archive_write_free.3 + archive_write_header.3 + archive_write_new.3 + archive_write_open.3 + archive_write_set_options.3 + archive_write_set_passphrase.3 + cpio.5 + libarchive.3 + libarchive_changes.3 + libarchive_internals.3 + libarchive-formats.5 + mtree.5 + tar.5 +) + +IF(WIN32 AND NOT CYGWIN) + LIST(APPEND libarchive_SOURCES archive_entry_copy_bhfi.c) + LIST(APPEND libarchive_SOURCES archive_read_disk_windows.c) + LIST(APPEND libarchive_SOURCES archive_windows.c) + LIST(APPEND libarchive_SOURCES archive_windows.h) + LIST(APPEND libarchive_SOURCES archive_write_disk_windows.c) + LIST(APPEND libarchive_SOURCES filter_fork_windows.c) +ENDIF(WIN32 AND NOT CYGWIN) + +IF(ARCHIVE_BLAKE2) + LIST(APPEND libarchive_SOURCES archive_blake2sp_ref.c) + LIST(APPEND libarchive_SOURCES archive_blake2s_ref.c) +ENDIF(ARCHIVE_BLAKE2) + +IF(ARCHIVE_ACL_DARWIN) + LIST(APPEND libarchive_SOURCES archive_disk_acl_darwin.c) +ELSEIF(ARCHIVE_ACL_FREEBSD) + LIST(APPEND libarchive_SOURCES archive_disk_acl_freebsd.c) +ELSEIF(ARCHIVE_ACL_LIBACL) + LIST(APPEND libarchive_SOURCES archive_disk_acl_linux.c) +ELSEIF(ARCHIVE_ACL_SUNOS) + LIST(APPEND libarchive_SOURCES archive_disk_acl_sunos.c) +ENDIF() + +# Libarchive is a shared library +#ADD_LIBRARY(archive SHARED ${libarchive_SOURCES} ${include_HEADERS}) +#TARGET_INCLUDE_DIRECTORIES(archive PUBLIC .) +#TARGET_LINK_LIBRARIES(archive ${ADDITIONAL_LIBS}) +#SET_TARGET_PROPERTIES(archive PROPERTIES SOVERSION ${SOVERSION}) + +# archive_static is a static library +ADD_LIBRARY(archive_static STATIC ${libarchive_SOURCES} ${include_HEADERS}) +TARGET_LINK_LIBRARIES(archive_static ${ADDITIONAL_LIBS}) +SET_TARGET_PROPERTIES(archive_static PROPERTIES COMPILE_DEFINITIONS + LIBARCHIVE_STATIC) +# On Posix systems, libarchive.so and libarchive.a can co-exist. +IF(NOT WIN32 OR CYGWIN) + SET_TARGET_PROPERTIES(archive_static PROPERTIES OUTPUT_NAME archive) +ENDIF(NOT WIN32 OR CYGWIN) + +IF(ENABLE_INSTALL) + # How to install the libraries + #INSTALL(TARGETS archive archive_static + INSTALL(TARGETS archive_static + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib) + INSTALL_MAN(${libarchive_MANS}) + INSTALL(FILES ${include_HEADERS} DESTINATION include) +ENDIF() + +add_subdirectory(test) diff --git a/dependencies/libarchive-3.4.2/libarchive/archive.h b/dependencies/libarchive-3.4.2/libarchive/archive.h new file mode 100644 index 0000000..55818ea --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive.h @@ -0,0 +1,1197 @@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: src/lib/libarchive/archive.h.in,v 1.50 2008/05/26 17:00:22 kientzle Exp $ + */ + +#ifndef ARCHIVE_H_INCLUDED +#define ARCHIVE_H_INCLUDED + +/* + * The version number is expressed as a single integer that makes it + * easy to compare versions at build time: for version a.b.c, the + * version number is printf("%d%03d%03d",a,b,c). For example, if you + * know your application requires version 2.12.108 or later, you can + * assert that ARCHIVE_VERSION_NUMBER >= 2012108. + */ +/* Note: Compiler will complain if this does not match archive_entry.h! */ +#define ARCHIVE_VERSION_NUMBER 3004002 + +#include +#include /* for wchar_t */ +#include /* For FILE * */ +#include /* For time_t */ + +/* + * Note: archive.h is for use outside of libarchive; the configuration + * headers (config.h, archive_platform.h, etc.) are purely internal. + * Do NOT use HAVE_XXX configuration macros to control the behavior of + * this header! If you must conditionalize, use predefined compiler and/or + * platform macros. + */ +#if defined(__BORLANDC__) && __BORLANDC__ >= 0x560 +# include +#elif !defined(__WATCOMC__) && !defined(_MSC_VER) && !defined(__INTERIX) && !defined(__BORLANDC__) && !defined(_SCO_DS) && !defined(__osf__) && !defined(__CLANG_INTTYPES_H) +# include +#endif + +/* Get appropriate definitions of 64-bit integer */ +#if !defined(__LA_INT64_T_DEFINED) +/* Older code relied on the __LA_INT64_T macro; after 4.0 we'll switch to the typedef exclusively. */ +# if ARCHIVE_VERSION_NUMBER < 4000000 +#define __LA_INT64_T la_int64_t +# endif +#define __LA_INT64_T_DEFINED +# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__) +typedef __int64 la_int64_t; +# else +# include /* ssize_t */ +# if defined(_SCO_DS) || defined(__osf__) +typedef long long la_int64_t; +# else +typedef int64_t la_int64_t; +# endif +# endif +#endif + +/* The la_ssize_t should match the type used in 'struct stat' */ +#if !defined(__LA_SSIZE_T_DEFINED) +/* Older code relied on the __LA_SSIZE_T macro; after 4.0 we'll switch to the typedef exclusively. */ +# if ARCHIVE_VERSION_NUMBER < 4000000 +#define __LA_SSIZE_T la_ssize_t +# endif +#define __LA_SSIZE_T_DEFINED +# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__) +# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_) +typedef ssize_t la_ssize_t; +# elif defined(_WIN64) +typedef __int64 la_ssize_t; +# else +typedef long la_ssize_t; +# endif +# else +# include /* ssize_t */ +typedef ssize_t la_ssize_t; +# endif +#endif + +/* Large file support for Android */ +#ifdef __ANDROID__ +#include "android_lf.h" +#endif + +/* + * On Windows, define LIBARCHIVE_STATIC if you're building or using a + * .lib. The default here assumes you're building a DLL. Only + * libarchive source should ever define __LIBARCHIVE_BUILD. + */ +#if ((defined __WIN32__) || (defined _WIN32) || defined(__CYGWIN__)) && (!defined LIBARCHIVE_STATIC) +# ifdef __LIBARCHIVE_BUILD +# ifdef __GNUC__ +# define __LA_DECL __attribute__((dllexport)) extern +# else +# define __LA_DECL __declspec(dllexport) +# endif +# else +# ifdef __GNUC__ +# define __LA_DECL +# else +# define __LA_DECL __declspec(dllimport) +# endif +# endif +#else +/* Static libraries or non-Windows needs no special declaration. */ +# define __LA_DECL +#endif + +#if defined(__GNUC__) && __GNUC__ >= 3 && !defined(__MINGW32__) +#define __LA_PRINTF(fmtarg, firstvararg) \ + __attribute__((__format__ (__printf__, fmtarg, firstvararg))) +#else +#define __LA_PRINTF(fmtarg, firstvararg) /* nothing */ +#endif + +#if defined(__GNUC__) && __GNUC__ >= 3 && __GNUC_MINOR__ >= 1 +# define __LA_DEPRECATED __attribute__((deprecated)) +#else +# define __LA_DEPRECATED +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The version number is provided as both a macro and a function. + * The macro identifies the installed header; the function identifies + * the library version (which may not be the same if you're using a + * dynamically-linked version of the library). Of course, if the + * header and library are very different, you should expect some + * strangeness. Don't do that. + */ +__LA_DECL int archive_version_number(void); + +/* + * Textual name/version of the library, useful for version displays. + */ +#define ARCHIVE_VERSION_ONLY_STRING "3.4.2" +#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING +__LA_DECL const char * archive_version_string(void); + +/* + * Detailed textual name/version of the library and its dependencies. + * This has the form: + * "libarchive x.y.z zlib/a.b.c liblzma/d.e.f ... etc ..." + * the list of libraries described here will vary depending on how + * libarchive was compiled. + */ +__LA_DECL const char * archive_version_details(void); + +/* + * Returns NULL if libarchive was compiled without the associated library. + * Otherwise, returns the version number that libarchive was compiled + * against. + */ +__LA_DECL const char * archive_zlib_version(void); +__LA_DECL const char * archive_liblzma_version(void); +__LA_DECL const char * archive_bzlib_version(void); +__LA_DECL const char * archive_liblz4_version(void); +__LA_DECL const char * archive_libzstd_version(void); + +/* Declare our basic types. */ +struct archive; +struct archive_entry; + +/* + * Error codes: Use archive_errno() and archive_error_string() + * to retrieve details. Unless specified otherwise, all functions + * that return 'int' use these codes. + */ +#define ARCHIVE_EOF 1 /* Found end of archive. */ +#define ARCHIVE_OK 0 /* Operation was successful. */ +#define ARCHIVE_RETRY (-10) /* Retry might succeed. */ +#define ARCHIVE_WARN (-20) /* Partial success. */ +/* For example, if write_header "fails", then you can't push data. */ +#define ARCHIVE_FAILED (-25) /* Current operation cannot complete. */ +/* But if write_header is "fatal," then this archive is dead and useless. */ +#define ARCHIVE_FATAL (-30) /* No more operations are possible. */ + +/* + * As far as possible, archive_errno returns standard platform errno codes. + * Of course, the details vary by platform, so the actual definitions + * here are stored in "archive_platform.h". The symbols are listed here + * for reference; as a rule, clients should not need to know the exact + * platform-dependent error code. + */ +/* Unrecognized or invalid file format. */ +/* #define ARCHIVE_ERRNO_FILE_FORMAT */ +/* Illegal usage of the library. */ +/* #define ARCHIVE_ERRNO_PROGRAMMER_ERROR */ +/* Unknown or unclassified error. */ +/* #define ARCHIVE_ERRNO_MISC */ + +/* + * Callbacks are invoked to automatically read/skip/write/open/close the + * archive. You can provide your own for complex tasks (like breaking + * archives across multiple tapes) or use standard ones built into the + * library. + */ + +/* Returns pointer and size of next block of data from archive. */ +typedef la_ssize_t archive_read_callback(struct archive *, + void *_client_data, const void **_buffer); + +/* Skips at most request bytes from archive and returns the skipped amount. + * This may skip fewer bytes than requested; it may even skip zero bytes. + * If you do skip fewer bytes than requested, libarchive will invoke your + * read callback and discard data as necessary to make up the full skip. + */ +typedef la_int64_t archive_skip_callback(struct archive *, + void *_client_data, la_int64_t request); + +/* Seeks to specified location in the file and returns the position. + * Whence values are SEEK_SET, SEEK_CUR, SEEK_END from stdio.h. + * Return ARCHIVE_FATAL if the seek fails for any reason. + */ +typedef la_int64_t archive_seek_callback(struct archive *, + void *_client_data, la_int64_t offset, int whence); + +/* Returns size actually written, zero on EOF, -1 on error. */ +typedef la_ssize_t archive_write_callback(struct archive *, + void *_client_data, + const void *_buffer, size_t _length); + +typedef int archive_open_callback(struct archive *, void *_client_data); + +typedef int archive_close_callback(struct archive *, void *_client_data); + +/* Switches from one client data object to the next/prev client data object. + * This is useful for reading from different data blocks such as a set of files + * that make up one large file. + */ +typedef int archive_switch_callback(struct archive *, void *_client_data1, + void *_client_data2); + +/* + * Returns a passphrase used for encryption or decryption, NULL on nothing + * to do and give it up. + */ +typedef const char *archive_passphrase_callback(struct archive *, + void *_client_data); + +/* + * Codes to identify various stream filters. + */ +#define ARCHIVE_FILTER_NONE 0 +#define ARCHIVE_FILTER_GZIP 1 +#define ARCHIVE_FILTER_BZIP2 2 +#define ARCHIVE_FILTER_COMPRESS 3 +#define ARCHIVE_FILTER_PROGRAM 4 +#define ARCHIVE_FILTER_LZMA 5 +#define ARCHIVE_FILTER_XZ 6 +#define ARCHIVE_FILTER_UU 7 +#define ARCHIVE_FILTER_RPM 8 +#define ARCHIVE_FILTER_LZIP 9 +#define ARCHIVE_FILTER_LRZIP 10 +#define ARCHIVE_FILTER_LZOP 11 +#define ARCHIVE_FILTER_GRZIP 12 +#define ARCHIVE_FILTER_LZ4 13 +#define ARCHIVE_FILTER_ZSTD 14 + +#if ARCHIVE_VERSION_NUMBER < 4000000 +#define ARCHIVE_COMPRESSION_NONE ARCHIVE_FILTER_NONE +#define ARCHIVE_COMPRESSION_GZIP ARCHIVE_FILTER_GZIP +#define ARCHIVE_COMPRESSION_BZIP2 ARCHIVE_FILTER_BZIP2 +#define ARCHIVE_COMPRESSION_COMPRESS ARCHIVE_FILTER_COMPRESS +#define ARCHIVE_COMPRESSION_PROGRAM ARCHIVE_FILTER_PROGRAM +#define ARCHIVE_COMPRESSION_LZMA ARCHIVE_FILTER_LZMA +#define ARCHIVE_COMPRESSION_XZ ARCHIVE_FILTER_XZ +#define ARCHIVE_COMPRESSION_UU ARCHIVE_FILTER_UU +#define ARCHIVE_COMPRESSION_RPM ARCHIVE_FILTER_RPM +#define ARCHIVE_COMPRESSION_LZIP ARCHIVE_FILTER_LZIP +#define ARCHIVE_COMPRESSION_LRZIP ARCHIVE_FILTER_LRZIP +#endif + +/* + * Codes returned by archive_format. + * + * Top 16 bits identifies the format family (e.g., "tar"); lower + * 16 bits indicate the variant. This is updated by read_next_header. + * Note that the lower 16 bits will often vary from entry to entry. + * In some cases, this variation occurs as libarchive learns more about + * the archive (for example, later entries might utilize extensions that + * weren't necessary earlier in the archive; in this case, libarchive + * will change the format code to indicate the extended format that + * was used). In other cases, it's because different tools have + * modified the archive and so different parts of the archive + * actually have slightly different formats. (Both tar and cpio store + * format codes in each entry, so it is quite possible for each + * entry to be in a different format.) + */ +#define ARCHIVE_FORMAT_BASE_MASK 0xff0000 +#define ARCHIVE_FORMAT_CPIO 0x10000 +#define ARCHIVE_FORMAT_CPIO_POSIX (ARCHIVE_FORMAT_CPIO | 1) +#define ARCHIVE_FORMAT_CPIO_BIN_LE (ARCHIVE_FORMAT_CPIO | 2) +#define ARCHIVE_FORMAT_CPIO_BIN_BE (ARCHIVE_FORMAT_CPIO | 3) +#define ARCHIVE_FORMAT_CPIO_SVR4_NOCRC (ARCHIVE_FORMAT_CPIO | 4) +#define ARCHIVE_FORMAT_CPIO_SVR4_CRC (ARCHIVE_FORMAT_CPIO | 5) +#define ARCHIVE_FORMAT_CPIO_AFIO_LARGE (ARCHIVE_FORMAT_CPIO | 6) +#define ARCHIVE_FORMAT_SHAR 0x20000 +#define ARCHIVE_FORMAT_SHAR_BASE (ARCHIVE_FORMAT_SHAR | 1) +#define ARCHIVE_FORMAT_SHAR_DUMP (ARCHIVE_FORMAT_SHAR | 2) +#define ARCHIVE_FORMAT_TAR 0x30000 +#define ARCHIVE_FORMAT_TAR_USTAR (ARCHIVE_FORMAT_TAR | 1) +#define ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE (ARCHIVE_FORMAT_TAR | 2) +#define ARCHIVE_FORMAT_TAR_PAX_RESTRICTED (ARCHIVE_FORMAT_TAR | 3) +#define ARCHIVE_FORMAT_TAR_GNUTAR (ARCHIVE_FORMAT_TAR | 4) +#define ARCHIVE_FORMAT_ISO9660 0x40000 +#define ARCHIVE_FORMAT_ISO9660_ROCKRIDGE (ARCHIVE_FORMAT_ISO9660 | 1) +#define ARCHIVE_FORMAT_ZIP 0x50000 +#define ARCHIVE_FORMAT_EMPTY 0x60000 +#define ARCHIVE_FORMAT_AR 0x70000 +#define ARCHIVE_FORMAT_AR_GNU (ARCHIVE_FORMAT_AR | 1) +#define ARCHIVE_FORMAT_AR_BSD (ARCHIVE_FORMAT_AR | 2) +#define ARCHIVE_FORMAT_MTREE 0x80000 +#define ARCHIVE_FORMAT_RAW 0x90000 +#define ARCHIVE_FORMAT_XAR 0xA0000 +#define ARCHIVE_FORMAT_LHA 0xB0000 +#define ARCHIVE_FORMAT_CAB 0xC0000 +#define ARCHIVE_FORMAT_RAR 0xD0000 +#define ARCHIVE_FORMAT_7ZIP 0xE0000 +#define ARCHIVE_FORMAT_WARC 0xF0000 +#define ARCHIVE_FORMAT_RAR_V5 0x100000 + +/* + * Codes returned by archive_read_format_capabilities(). + * + * This list can be extended with values between 0 and 0xffff. + * The original purpose of this list was to let different archive + * format readers expose their general capabilities in terms of + * encryption. + */ +#define ARCHIVE_READ_FORMAT_CAPS_NONE (0) /* no special capabilities */ +#define ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA (1<<0) /* reader can detect encrypted data */ +#define ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA (1<<1) /* reader can detect encryptable metadata (pathname, mtime, etc.) */ + +/* + * Codes returned by archive_read_has_encrypted_entries(). + * + * In case the archive does not support encryption detection at all + * ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned. If the reader + * for some other reason (e.g. not enough bytes read) cannot say if + * there are encrypted entries, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW + * is returned. + */ +#define ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED -2 +#define ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW -1 + +/*- + * Basic outline for reading an archive: + * 1) Ask archive_read_new for an archive reader object. + * 2) Update any global properties as appropriate. + * In particular, you'll certainly want to call appropriate + * archive_read_support_XXX functions. + * 3) Call archive_read_open_XXX to open the archive + * 4) Repeatedly call archive_read_next_header to get information about + * successive archive entries. Call archive_read_data to extract + * data for entries of interest. + * 5) Call archive_read_free to end processing. + */ +__LA_DECL struct archive *archive_read_new(void); + +/* + * The archive_read_support_XXX calls enable auto-detect for this + * archive handle. They also link in the necessary support code. + * For example, if you don't want bzlib linked in, don't invoke + * support_compression_bzip2(). The "all" functions provide the + * obvious shorthand. + */ + +#if ARCHIVE_VERSION_NUMBER < 4000000 +__LA_DECL int archive_read_support_compression_all(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_bzip2(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_compress(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_gzip(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_lzip(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_lzma(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_none(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_program(struct archive *, + const char *command) __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_program_signature + (struct archive *, const char *, + const void * /* match */, size_t) __LA_DEPRECATED; + +__LA_DECL int archive_read_support_compression_rpm(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_uu(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_xz(struct archive *) + __LA_DEPRECATED; +#endif + +__LA_DECL int archive_read_support_filter_all(struct archive *); +__LA_DECL int archive_read_support_filter_bzip2(struct archive *); +__LA_DECL int archive_read_support_filter_compress(struct archive *); +__LA_DECL int archive_read_support_filter_gzip(struct archive *); +__LA_DECL int archive_read_support_filter_grzip(struct archive *); +__LA_DECL int archive_read_support_filter_lrzip(struct archive *); +__LA_DECL int archive_read_support_filter_lz4(struct archive *); +__LA_DECL int archive_read_support_filter_lzip(struct archive *); +__LA_DECL int archive_read_support_filter_lzma(struct archive *); +__LA_DECL int archive_read_support_filter_lzop(struct archive *); +__LA_DECL int archive_read_support_filter_none(struct archive *); +__LA_DECL int archive_read_support_filter_program(struct archive *, + const char *command); +__LA_DECL int archive_read_support_filter_program_signature + (struct archive *, const char * /* cmd */, + const void * /* match */, size_t); +__LA_DECL int archive_read_support_filter_rpm(struct archive *); +__LA_DECL int archive_read_support_filter_uu(struct archive *); +__LA_DECL int archive_read_support_filter_xz(struct archive *); +__LA_DECL int archive_read_support_filter_zstd(struct archive *); + +__LA_DECL int archive_read_support_format_7zip(struct archive *); +__LA_DECL int archive_read_support_format_all(struct archive *); +__LA_DECL int archive_read_support_format_ar(struct archive *); +__LA_DECL int archive_read_support_format_by_code(struct archive *, int); +__LA_DECL int archive_read_support_format_cab(struct archive *); +__LA_DECL int archive_read_support_format_cpio(struct archive *); +__LA_DECL int archive_read_support_format_empty(struct archive *); +__LA_DECL int archive_read_support_format_gnutar(struct archive *); +__LA_DECL int archive_read_support_format_iso9660(struct archive *); +__LA_DECL int archive_read_support_format_lha(struct archive *); +__LA_DECL int archive_read_support_format_mtree(struct archive *); +__LA_DECL int archive_read_support_format_rar(struct archive *); +__LA_DECL int archive_read_support_format_rar5(struct archive *); +__LA_DECL int archive_read_support_format_raw(struct archive *); +__LA_DECL int archive_read_support_format_tar(struct archive *); +__LA_DECL int archive_read_support_format_warc(struct archive *); +__LA_DECL int archive_read_support_format_xar(struct archive *); +/* archive_read_support_format_zip() enables both streamable and seekable + * zip readers. */ +__LA_DECL int archive_read_support_format_zip(struct archive *); +/* Reads Zip archives as stream from beginning to end. Doesn't + * correctly handle SFX ZIP files or ZIP archives that have been modified + * in-place. */ +__LA_DECL int archive_read_support_format_zip_streamable(struct archive *); +/* Reads starting from central directory; requires seekable input. */ +__LA_DECL int archive_read_support_format_zip_seekable(struct archive *); + +/* Functions to manually set the format and filters to be used. This is + * useful to bypass the bidding process when the format and filters to use + * is known in advance. + */ +__LA_DECL int archive_read_set_format(struct archive *, int); +__LA_DECL int archive_read_append_filter(struct archive *, int); +__LA_DECL int archive_read_append_filter_program(struct archive *, + const char *); +__LA_DECL int archive_read_append_filter_program_signature + (struct archive *, const char *, const void * /* match */, size_t); + +/* Set various callbacks. */ +__LA_DECL int archive_read_set_open_callback(struct archive *, + archive_open_callback *); +__LA_DECL int archive_read_set_read_callback(struct archive *, + archive_read_callback *); +__LA_DECL int archive_read_set_seek_callback(struct archive *, + archive_seek_callback *); +__LA_DECL int archive_read_set_skip_callback(struct archive *, + archive_skip_callback *); +__LA_DECL int archive_read_set_close_callback(struct archive *, + archive_close_callback *); +/* Callback used to switch between one data object to the next */ +__LA_DECL int archive_read_set_switch_callback(struct archive *, + archive_switch_callback *); + +/* This sets the first data object. */ +__LA_DECL int archive_read_set_callback_data(struct archive *, void *); +/* This sets data object at specified index */ +__LA_DECL int archive_read_set_callback_data2(struct archive *, void *, + unsigned int); +/* This adds a data object at the specified index. */ +__LA_DECL int archive_read_add_callback_data(struct archive *, void *, + unsigned int); +/* This appends a data object to the end of list */ +__LA_DECL int archive_read_append_callback_data(struct archive *, void *); +/* This prepends a data object to the beginning of list */ +__LA_DECL int archive_read_prepend_callback_data(struct archive *, void *); + +/* Opening freezes the callbacks. */ +__LA_DECL int archive_read_open1(struct archive *); + +/* Convenience wrappers around the above. */ +__LA_DECL int archive_read_open(struct archive *, void *_client_data, + archive_open_callback *, archive_read_callback *, + archive_close_callback *); +__LA_DECL int archive_read_open2(struct archive *, void *_client_data, + archive_open_callback *, archive_read_callback *, + archive_skip_callback *, archive_close_callback *); + +/* + * A variety of shortcuts that invoke archive_read_open() with + * canned callbacks suitable for common situations. The ones that + * accept a block size handle tape blocking correctly. + */ +/* Use this if you know the filename. Note: NULL indicates stdin. */ +__LA_DECL int archive_read_open_filename(struct archive *, + const char *_filename, size_t _block_size); +/* Use this for reading multivolume files by filenames. + * NOTE: Must be NULL terminated. Sorting is NOT done. */ +__LA_DECL int archive_read_open_filenames(struct archive *, + const char **_filenames, size_t _block_size); +__LA_DECL int archive_read_open_filename_w(struct archive *, + const wchar_t *_filename, size_t _block_size); +/* archive_read_open_file() is a deprecated synonym for ..._open_filename(). */ +__LA_DECL int archive_read_open_file(struct archive *, + const char *_filename, size_t _block_size) __LA_DEPRECATED; +/* Read an archive that's stored in memory. */ +__LA_DECL int archive_read_open_memory(struct archive *, + const void * buff, size_t size); +/* A more involved version that is only used for internal testing. */ +__LA_DECL int archive_read_open_memory2(struct archive *a, const void *buff, + size_t size, size_t read_size); +/* Read an archive that's already open, using the file descriptor. */ +__LA_DECL int archive_read_open_fd(struct archive *, int _fd, + size_t _block_size); +/* Read an archive that's already open, using a FILE *. */ +/* Note: DO NOT use this with tape drives. */ +__LA_DECL int archive_read_open_FILE(struct archive *, FILE *_file); + +/* Parses and returns next entry header. */ +__LA_DECL int archive_read_next_header(struct archive *, + struct archive_entry **); + +/* Parses and returns next entry header using the archive_entry passed in */ +__LA_DECL int archive_read_next_header2(struct archive *, + struct archive_entry *); + +/* + * Retrieve the byte offset in UNCOMPRESSED data where last-read + * header started. + */ +__LA_DECL la_int64_t archive_read_header_position(struct archive *); + +/* + * Returns 1 if the archive contains at least one encrypted entry. + * If the archive format not support encryption at all + * ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned. + * If for any other reason (e.g. not enough data read so far) + * we cannot say whether there are encrypted entries, then + * ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned. + * In general, this function will return values below zero when the + * reader is uncertain or totally incapable of encryption support. + * When this function returns 0 you can be sure that the reader + * supports encryption detection but no encrypted entries have + * been found yet. + * + * NOTE: If the metadata/header of an archive is also encrypted, you + * cannot rely on the number of encrypted entries. That is why this + * function does not return the number of encrypted entries but# + * just shows that there are some. + */ +__LA_DECL int archive_read_has_encrypted_entries(struct archive *); + +/* + * Returns a bitmask of capabilities that are supported by the archive format reader. + * If the reader has no special capabilities, ARCHIVE_READ_FORMAT_CAPS_NONE is returned. + */ +__LA_DECL int archive_read_format_capabilities(struct archive *); + +/* Read data from the body of an entry. Similar to read(2). */ +__LA_DECL la_ssize_t archive_read_data(struct archive *, + void *, size_t); + +/* Seek within the body of an entry. Similar to lseek(2). */ +__LA_DECL la_int64_t archive_seek_data(struct archive *, la_int64_t, int); + +/* + * A zero-copy version of archive_read_data that also exposes the file offset + * of each returned block. Note that the client has no way to specify + * the desired size of the block. The API does guarantee that offsets will + * be strictly increasing and that returned blocks will not overlap. + */ +__LA_DECL int archive_read_data_block(struct archive *a, + const void **buff, size_t *size, la_int64_t *offset); + +/*- + * Some convenience functions that are built on archive_read_data: + * 'skip': skips entire entry + * 'into_buffer': writes data into memory buffer that you provide + * 'into_fd': writes data to specified filedes + */ +__LA_DECL int archive_read_data_skip(struct archive *); +__LA_DECL int archive_read_data_into_fd(struct archive *, int fd); + +/* + * Set read options. + */ +/* Apply option to the format only. */ +__LA_DECL int archive_read_set_format_option(struct archive *_a, + const char *m, const char *o, + const char *v); +/* Apply option to the filter only. */ +__LA_DECL int archive_read_set_filter_option(struct archive *_a, + const char *m, const char *o, + const char *v); +/* Apply option to both the format and the filter. */ +__LA_DECL int archive_read_set_option(struct archive *_a, + const char *m, const char *o, + const char *v); +/* Apply option string to both the format and the filter. */ +__LA_DECL int archive_read_set_options(struct archive *_a, + const char *opts); + +/* + * Add a decryption passphrase. + */ +__LA_DECL int archive_read_add_passphrase(struct archive *, const char *); +__LA_DECL int archive_read_set_passphrase_callback(struct archive *, + void *client_data, archive_passphrase_callback *); + + +/*- + * Convenience function to recreate the current entry (whose header + * has just been read) on disk. + * + * This does quite a bit more than just copy data to disk. It also: + * - Creates intermediate directories as required. + * - Manages directory permissions: non-writable directories will + * be initially created with write permission enabled; when the + * archive is closed, dir permissions are edited to the values specified + * in the archive. + * - Checks hardlinks: hardlinks will not be extracted unless the + * linked-to file was also extracted within the same session. (TODO) + */ + +/* The "flags" argument selects optional behavior, 'OR' the flags you want. */ + +/* Default: Do not try to set owner/group. */ +#define ARCHIVE_EXTRACT_OWNER (0x0001) +/* Default: Do obey umask, do not restore SUID/SGID/SVTX bits. */ +#define ARCHIVE_EXTRACT_PERM (0x0002) +/* Default: Do not restore mtime/atime. */ +#define ARCHIVE_EXTRACT_TIME (0x0004) +/* Default: Replace existing files. */ +#define ARCHIVE_EXTRACT_NO_OVERWRITE (0x0008) +/* Default: Try create first, unlink only if create fails with EEXIST. */ +#define ARCHIVE_EXTRACT_UNLINK (0x0010) +/* Default: Do not restore ACLs. */ +#define ARCHIVE_EXTRACT_ACL (0x0020) +/* Default: Do not restore fflags. */ +#define ARCHIVE_EXTRACT_FFLAGS (0x0040) +/* Default: Do not restore xattrs. */ +#define ARCHIVE_EXTRACT_XATTR (0x0080) +/* Default: Do not try to guard against extracts redirected by symlinks. */ +/* Note: With ARCHIVE_EXTRACT_UNLINK, will remove any intermediate symlink. */ +#define ARCHIVE_EXTRACT_SECURE_SYMLINKS (0x0100) +/* Default: Do not reject entries with '..' as path elements. */ +#define ARCHIVE_EXTRACT_SECURE_NODOTDOT (0x0200) +/* Default: Create parent directories as needed. */ +#define ARCHIVE_EXTRACT_NO_AUTODIR (0x0400) +/* Default: Overwrite files, even if one on disk is newer. */ +#define ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER (0x0800) +/* Detect blocks of 0 and write holes instead. */ +#define ARCHIVE_EXTRACT_SPARSE (0x1000) +/* Default: Do not restore Mac extended metadata. */ +/* This has no effect except on Mac OS. */ +#define ARCHIVE_EXTRACT_MAC_METADATA (0x2000) +/* Default: Use HFS+ compression if it was compressed. */ +/* This has no effect except on Mac OS v10.6 or later. */ +#define ARCHIVE_EXTRACT_NO_HFS_COMPRESSION (0x4000) +/* Default: Do not use HFS+ compression if it was not compressed. */ +/* This has no effect except on Mac OS v10.6 or later. */ +#define ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED (0x8000) +/* Default: Do not reject entries with absolute paths */ +#define ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS (0x10000) +/* Default: Do not clear no-change flags when unlinking object */ +#define ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS (0x20000) +/* Default: Do not extract atomically (using rename) */ +#define ARCHIVE_EXTRACT_SAFE_WRITES (0x40000) + +__LA_DECL int archive_read_extract(struct archive *, struct archive_entry *, + int flags); +__LA_DECL int archive_read_extract2(struct archive *, struct archive_entry *, + struct archive * /* dest */); +__LA_DECL void archive_read_extract_set_progress_callback(struct archive *, + void (*_progress_func)(void *), void *_user_data); + +/* Record the dev/ino of a file that will not be written. This is + * generally set to the dev/ino of the archive being read. */ +__LA_DECL void archive_read_extract_set_skip_file(struct archive *, + la_int64_t, la_int64_t); + +/* Close the file and release most resources. */ +__LA_DECL int archive_read_close(struct archive *); +/* Release all resources and destroy the object. */ +/* Note that archive_read_free will call archive_read_close for you. */ +__LA_DECL int archive_read_free(struct archive *); +#if ARCHIVE_VERSION_NUMBER < 4000000 +/* Synonym for archive_read_free() for backwards compatibility. */ +__LA_DECL int archive_read_finish(struct archive *) __LA_DEPRECATED; +#endif + +/*- + * To create an archive: + * 1) Ask archive_write_new for an archive writer object. + * 2) Set any global properties. In particular, you should set + * the compression and format to use. + * 3) Call archive_write_open to open the file (most people + * will use archive_write_open_file or archive_write_open_fd, + * which provide convenient canned I/O callbacks for you). + * 4) For each entry: + * - construct an appropriate struct archive_entry structure + * - archive_write_header to write the header + * - archive_write_data to write the entry data + * 5) archive_write_close to close the output + * 6) archive_write_free to cleanup the writer and release resources + */ +__LA_DECL struct archive *archive_write_new(void); +__LA_DECL int archive_write_set_bytes_per_block(struct archive *, + int bytes_per_block); +__LA_DECL int archive_write_get_bytes_per_block(struct archive *); +/* XXX This is badly misnamed; suggestions appreciated. XXX */ +__LA_DECL int archive_write_set_bytes_in_last_block(struct archive *, + int bytes_in_last_block); +__LA_DECL int archive_write_get_bytes_in_last_block(struct archive *); + +/* The dev/ino of a file that won't be archived. This is used + * to avoid recursively adding an archive to itself. */ +__LA_DECL int archive_write_set_skip_file(struct archive *, + la_int64_t, la_int64_t); + +#if ARCHIVE_VERSION_NUMBER < 4000000 +__LA_DECL int archive_write_set_compression_bzip2(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_compress(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_gzip(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_lzip(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_lzma(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_none(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_program(struct archive *, + const char *cmd) __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_xz(struct archive *) + __LA_DEPRECATED; +#endif + +/* A convenience function to set the filter based on the code. */ +__LA_DECL int archive_write_add_filter(struct archive *, int filter_code); +__LA_DECL int archive_write_add_filter_by_name(struct archive *, + const char *name); +__LA_DECL int archive_write_add_filter_b64encode(struct archive *); +__LA_DECL int archive_write_add_filter_bzip2(struct archive *); +__LA_DECL int archive_write_add_filter_compress(struct archive *); +__LA_DECL int archive_write_add_filter_grzip(struct archive *); +__LA_DECL int archive_write_add_filter_gzip(struct archive *); +__LA_DECL int archive_write_add_filter_lrzip(struct archive *); +__LA_DECL int archive_write_add_filter_lz4(struct archive *); +__LA_DECL int archive_write_add_filter_lzip(struct archive *); +__LA_DECL int archive_write_add_filter_lzma(struct archive *); +__LA_DECL int archive_write_add_filter_lzop(struct archive *); +__LA_DECL int archive_write_add_filter_none(struct archive *); +__LA_DECL int archive_write_add_filter_program(struct archive *, + const char *cmd); +__LA_DECL int archive_write_add_filter_uuencode(struct archive *); +__LA_DECL int archive_write_add_filter_xz(struct archive *); +__LA_DECL int archive_write_add_filter_zstd(struct archive *); + + +/* A convenience function to set the format based on the code or name. */ +__LA_DECL int archive_write_set_format(struct archive *, int format_code); +__LA_DECL int archive_write_set_format_by_name(struct archive *, + const char *name); +/* To minimize link pollution, use one or more of the following. */ +__LA_DECL int archive_write_set_format_7zip(struct archive *); +__LA_DECL int archive_write_set_format_ar_bsd(struct archive *); +__LA_DECL int archive_write_set_format_ar_svr4(struct archive *); +__LA_DECL int archive_write_set_format_cpio(struct archive *); +__LA_DECL int archive_write_set_format_cpio_newc(struct archive *); +__LA_DECL int archive_write_set_format_gnutar(struct archive *); +__LA_DECL int archive_write_set_format_iso9660(struct archive *); +__LA_DECL int archive_write_set_format_mtree(struct archive *); +__LA_DECL int archive_write_set_format_mtree_classic(struct archive *); +/* TODO: int archive_write_set_format_old_tar(struct archive *); */ +__LA_DECL int archive_write_set_format_pax(struct archive *); +__LA_DECL int archive_write_set_format_pax_restricted(struct archive *); +__LA_DECL int archive_write_set_format_raw(struct archive *); +__LA_DECL int archive_write_set_format_shar(struct archive *); +__LA_DECL int archive_write_set_format_shar_dump(struct archive *); +__LA_DECL int archive_write_set_format_ustar(struct archive *); +__LA_DECL int archive_write_set_format_v7tar(struct archive *); +__LA_DECL int archive_write_set_format_warc(struct archive *); +__LA_DECL int archive_write_set_format_xar(struct archive *); +__LA_DECL int archive_write_set_format_zip(struct archive *); +__LA_DECL int archive_write_set_format_filter_by_ext(struct archive *a, const char *filename); +__LA_DECL int archive_write_set_format_filter_by_ext_def(struct archive *a, const char *filename, const char * def_ext); +__LA_DECL int archive_write_zip_set_compression_deflate(struct archive *); +__LA_DECL int archive_write_zip_set_compression_store(struct archive *); +__LA_DECL int archive_write_open(struct archive *, void *, + archive_open_callback *, archive_write_callback *, + archive_close_callback *); +__LA_DECL int archive_write_open_fd(struct archive *, int _fd); +__LA_DECL int archive_write_open_filename(struct archive *, const char *_file); +__LA_DECL int archive_write_open_filename_w(struct archive *, + const wchar_t *_file); +/* A deprecated synonym for archive_write_open_filename() */ +__LA_DECL int archive_write_open_file(struct archive *, const char *_file) + __LA_DEPRECATED; +__LA_DECL int archive_write_open_FILE(struct archive *, FILE *); +/* _buffSize is the size of the buffer, _used refers to a variable that + * will be updated after each write into the buffer. */ +__LA_DECL int archive_write_open_memory(struct archive *, + void *_buffer, size_t _buffSize, size_t *_used); + +/* + * Note that the library will truncate writes beyond the size provided + * to archive_write_header or pad if the provided data is short. + */ +__LA_DECL int archive_write_header(struct archive *, + struct archive_entry *); +__LA_DECL la_ssize_t archive_write_data(struct archive *, + const void *, size_t); + +/* This interface is currently only available for archive_write_disk handles. */ +__LA_DECL la_ssize_t archive_write_data_block(struct archive *, + const void *, size_t, la_int64_t); + +__LA_DECL int archive_write_finish_entry(struct archive *); +__LA_DECL int archive_write_close(struct archive *); +/* Marks the archive as FATAL so that a subsequent free() operation + * won't try to close() cleanly. Provides a fast abort capability + * when the client discovers that things have gone wrong. */ +__LA_DECL int archive_write_fail(struct archive *); +/* This can fail if the archive wasn't already closed, in which case + * archive_write_free() will implicitly call archive_write_close(). */ +__LA_DECL int archive_write_free(struct archive *); +#if ARCHIVE_VERSION_NUMBER < 4000000 +/* Synonym for archive_write_free() for backwards compatibility. */ +__LA_DECL int archive_write_finish(struct archive *) __LA_DEPRECATED; +#endif + +/* + * Set write options. + */ +/* Apply option to the format only. */ +__LA_DECL int archive_write_set_format_option(struct archive *_a, + const char *m, const char *o, + const char *v); +/* Apply option to the filter only. */ +__LA_DECL int archive_write_set_filter_option(struct archive *_a, + const char *m, const char *o, + const char *v); +/* Apply option to both the format and the filter. */ +__LA_DECL int archive_write_set_option(struct archive *_a, + const char *m, const char *o, + const char *v); +/* Apply option string to both the format and the filter. */ +__LA_DECL int archive_write_set_options(struct archive *_a, + const char *opts); + +/* + * Set a encryption passphrase. + */ +__LA_DECL int archive_write_set_passphrase(struct archive *_a, const char *p); +__LA_DECL int archive_write_set_passphrase_callback(struct archive *, + void *client_data, archive_passphrase_callback *); + +/*- + * ARCHIVE_WRITE_DISK API + * + * To create objects on disk: + * 1) Ask archive_write_disk_new for a new archive_write_disk object. + * 2) Set any global properties. In particular, you probably + * want to set the options. + * 3) For each entry: + * - construct an appropriate struct archive_entry structure + * - archive_write_header to create the file/dir/etc on disk + * - archive_write_data to write the entry data + * 4) archive_write_free to cleanup the writer and release resources + * + * In particular, you can use this in conjunction with archive_read() + * to pull entries out of an archive and create them on disk. + */ +__LA_DECL struct archive *archive_write_disk_new(void); +/* This file will not be overwritten. */ +__LA_DECL int archive_write_disk_set_skip_file(struct archive *, + la_int64_t, la_int64_t); +/* Set flags to control how the next item gets created. + * This accepts a bitmask of ARCHIVE_EXTRACT_XXX flags defined above. */ +__LA_DECL int archive_write_disk_set_options(struct archive *, + int flags); +/* + * The lookup functions are given uname/uid (or gname/gid) pairs and + * return a uid (gid) suitable for this system. These are used for + * restoring ownership and for setting ACLs. The default functions + * are naive, they just return the uid/gid. These are small, so reasonable + * for applications that don't need to preserve ownership; they + * are probably also appropriate for applications that are doing + * same-system backup and restore. + */ +/* + * The "standard" lookup functions use common system calls to lookup + * the uname/gname, falling back to the uid/gid if the names can't be + * found. They cache lookups and are reasonably fast, but can be very + * large, so they are not used unless you ask for them. In + * particular, these match the specifications of POSIX "pax" and old + * POSIX "tar". + */ +__LA_DECL int archive_write_disk_set_standard_lookup(struct archive *); +/* + * If neither the default (naive) nor the standard (big) functions suit + * your needs, you can write your own and register them. Be sure to + * include a cleanup function if you have allocated private data. + */ +__LA_DECL int archive_write_disk_set_group_lookup(struct archive *, + void * /* private_data */, + la_int64_t (*)(void *, const char *, la_int64_t), + void (* /* cleanup */)(void *)); +__LA_DECL int archive_write_disk_set_user_lookup(struct archive *, + void * /* private_data */, + la_int64_t (*)(void *, const char *, la_int64_t), + void (* /* cleanup */)(void *)); +__LA_DECL la_int64_t archive_write_disk_gid(struct archive *, const char *, la_int64_t); +__LA_DECL la_int64_t archive_write_disk_uid(struct archive *, const char *, la_int64_t); + +/* + * ARCHIVE_READ_DISK API + * + * This is still evolving and somewhat experimental. + */ +__LA_DECL struct archive *archive_read_disk_new(void); +/* The names for symlink modes here correspond to an old BSD + * command-line argument convention: -L, -P, -H */ +/* Follow all symlinks. */ +__LA_DECL int archive_read_disk_set_symlink_logical(struct archive *); +/* Follow no symlinks. */ +__LA_DECL int archive_read_disk_set_symlink_physical(struct archive *); +/* Follow symlink initially, then not. */ +__LA_DECL int archive_read_disk_set_symlink_hybrid(struct archive *); +/* TODO: Handle Linux stat32/stat64 ugliness. */ +__LA_DECL int archive_read_disk_entry_from_file(struct archive *, + struct archive_entry *, int /* fd */, const struct stat *); +/* Look up gname for gid or uname for uid. */ +/* Default implementations are very, very stupid. */ +__LA_DECL const char *archive_read_disk_gname(struct archive *, la_int64_t); +__LA_DECL const char *archive_read_disk_uname(struct archive *, la_int64_t); +/* "Standard" implementation uses getpwuid_r, getgrgid_r and caches the + * results for performance. */ +__LA_DECL int archive_read_disk_set_standard_lookup(struct archive *); +/* You can install your own lookups if you like. */ +__LA_DECL int archive_read_disk_set_gname_lookup(struct archive *, + void * /* private_data */, + const char *(* /* lookup_fn */)(void *, la_int64_t), + void (* /* cleanup_fn */)(void *)); +__LA_DECL int archive_read_disk_set_uname_lookup(struct archive *, + void * /* private_data */, + const char *(* /* lookup_fn */)(void *, la_int64_t), + void (* /* cleanup_fn */)(void *)); +/* Start traversal. */ +__LA_DECL int archive_read_disk_open(struct archive *, const char *); +__LA_DECL int archive_read_disk_open_w(struct archive *, const wchar_t *); +/* + * Request that current entry be visited. If you invoke it on every + * directory, you'll get a physical traversal. This is ignored if the + * current entry isn't a directory or a link to a directory. So, if + * you invoke this on every returned path, you'll get a full logical + * traversal. + */ +__LA_DECL int archive_read_disk_descend(struct archive *); +__LA_DECL int archive_read_disk_can_descend(struct archive *); +__LA_DECL int archive_read_disk_current_filesystem(struct archive *); +__LA_DECL int archive_read_disk_current_filesystem_is_synthetic(struct archive *); +__LA_DECL int archive_read_disk_current_filesystem_is_remote(struct archive *); +/* Request that the access time of the entry visited by traversal be restored. */ +__LA_DECL int archive_read_disk_set_atime_restored(struct archive *); +/* + * Set behavior. The "flags" argument selects optional behavior. + */ +/* Request that the access time of the entry visited by traversal be restored. + * This is the same as archive_read_disk_set_atime_restored. */ +#define ARCHIVE_READDISK_RESTORE_ATIME (0x0001) +/* Default: Do not skip an entry which has nodump flags. */ +#define ARCHIVE_READDISK_HONOR_NODUMP (0x0002) +/* Default: Skip a mac resource fork file whose prefix is "._" because of + * using copyfile. */ +#define ARCHIVE_READDISK_MAC_COPYFILE (0x0004) +/* Default: Traverse mount points. */ +#define ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS (0x0008) +/* Default: Xattrs are read from disk. */ +#define ARCHIVE_READDISK_NO_XATTR (0x0010) +/* Default: ACLs are read from disk. */ +#define ARCHIVE_READDISK_NO_ACL (0x0020) +/* Default: File flags are read from disk. */ +#define ARCHIVE_READDISK_NO_FFLAGS (0x0040) + +__LA_DECL int archive_read_disk_set_behavior(struct archive *, + int flags); + +/* + * Set archive_match object that will be used in archive_read_disk to + * know whether an entry should be skipped. The callback function + * _excluded_func will be invoked when an entry is skipped by the result + * of archive_match. + */ +__LA_DECL int archive_read_disk_set_matching(struct archive *, + struct archive *_matching, void (*_excluded_func) + (struct archive *, void *, struct archive_entry *), + void *_client_data); +__LA_DECL int archive_read_disk_set_metadata_filter_callback(struct archive *, + int (*_metadata_filter_func)(struct archive *, void *, + struct archive_entry *), void *_client_data); + +/* Simplified cleanup interface; + * This calls archive_read_free() or archive_write_free() as needed. */ +__LA_DECL int archive_free(struct archive *); + +/* + * Accessor functions to read/set various information in + * the struct archive object: + */ + +/* Number of filters in the current filter pipeline. */ +/* Filter #0 is the one closest to the format, -1 is a synonym for the + * last filter, which is always the pseudo-filter that wraps the + * client callbacks. */ +__LA_DECL int archive_filter_count(struct archive *); +__LA_DECL la_int64_t archive_filter_bytes(struct archive *, int); +__LA_DECL int archive_filter_code(struct archive *, int); +__LA_DECL const char * archive_filter_name(struct archive *, int); + +#if ARCHIVE_VERSION_NUMBER < 4000000 +/* These don't properly handle multiple filters, so are deprecated and + * will eventually be removed. */ +/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, -1); */ +__LA_DECL la_int64_t archive_position_compressed(struct archive *) + __LA_DEPRECATED; +/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, 0); */ +__LA_DECL la_int64_t archive_position_uncompressed(struct archive *) + __LA_DEPRECATED; +/* As of libarchive 3.0, this is an alias for archive_filter_name(a, 0); */ +__LA_DECL const char *archive_compression_name(struct archive *) + __LA_DEPRECATED; +/* As of libarchive 3.0, this is an alias for archive_filter_code(a, 0); */ +__LA_DECL int archive_compression(struct archive *) + __LA_DEPRECATED; +#endif + +__LA_DECL int archive_errno(struct archive *); +__LA_DECL const char *archive_error_string(struct archive *); +__LA_DECL const char *archive_format_name(struct archive *); +__LA_DECL int archive_format(struct archive *); +__LA_DECL void archive_clear_error(struct archive *); +__LA_DECL void archive_set_error(struct archive *, int _err, + const char *fmt, ...) __LA_PRINTF(3, 4); +__LA_DECL void archive_copy_error(struct archive *dest, + struct archive *src); +__LA_DECL int archive_file_count(struct archive *); + +/* + * ARCHIVE_MATCH API + */ +__LA_DECL struct archive *archive_match_new(void); +__LA_DECL int archive_match_free(struct archive *); + +/* + * Test if archive_entry is excluded. + * This is a convenience function. This is the same as calling all + * archive_match_path_excluded, archive_match_time_excluded + * and archive_match_owner_excluded. + */ +__LA_DECL int archive_match_excluded(struct archive *, + struct archive_entry *); + +/* + * Test if pathname is excluded. The conditions are set by following functions. + */ +__LA_DECL int archive_match_path_excluded(struct archive *, + struct archive_entry *); +/* Control recursive inclusion of directory content when directory is included. Default on. */ +__LA_DECL int archive_match_set_inclusion_recursion(struct archive *, int); +/* Add exclusion pathname pattern. */ +__LA_DECL int archive_match_exclude_pattern(struct archive *, const char *); +__LA_DECL int archive_match_exclude_pattern_w(struct archive *, + const wchar_t *); +/* Add exclusion pathname pattern from file. */ +__LA_DECL int archive_match_exclude_pattern_from_file(struct archive *, + const char *, int _nullSeparator); +__LA_DECL int archive_match_exclude_pattern_from_file_w(struct archive *, + const wchar_t *, int _nullSeparator); +/* Add inclusion pathname pattern. */ +__LA_DECL int archive_match_include_pattern(struct archive *, const char *); +__LA_DECL int archive_match_include_pattern_w(struct archive *, + const wchar_t *); +/* Add inclusion pathname pattern from file. */ +__LA_DECL int archive_match_include_pattern_from_file(struct archive *, + const char *, int _nullSeparator); +__LA_DECL int archive_match_include_pattern_from_file_w(struct archive *, + const wchar_t *, int _nullSeparator); +/* + * How to get statistic information for inclusion patterns. + */ +/* Return the amount number of unmatched inclusion patterns. */ +__LA_DECL int archive_match_path_unmatched_inclusions(struct archive *); +/* Return the pattern of unmatched inclusion with ARCHIVE_OK. + * Return ARCHIVE_EOF if there is no inclusion pattern. */ +__LA_DECL int archive_match_path_unmatched_inclusions_next( + struct archive *, const char **); +__LA_DECL int archive_match_path_unmatched_inclusions_next_w( + struct archive *, const wchar_t **); + +/* + * Test if a file is excluded by its time stamp. + * The conditions are set by following functions. + */ +__LA_DECL int archive_match_time_excluded(struct archive *, + struct archive_entry *); + +/* + * Flags to tell a matching type of time stamps. These are used for + * following functions. + */ +/* Time flag: mtime to be tested. */ +#define ARCHIVE_MATCH_MTIME (0x0100) +/* Time flag: ctime to be tested. */ +#define ARCHIVE_MATCH_CTIME (0x0200) +/* Comparison flag: Match the time if it is newer than. */ +#define ARCHIVE_MATCH_NEWER (0x0001) +/* Comparison flag: Match the time if it is older than. */ +#define ARCHIVE_MATCH_OLDER (0x0002) +/* Comparison flag: Match the time if it is equal to. */ +#define ARCHIVE_MATCH_EQUAL (0x0010) +/* Set inclusion time. */ +__LA_DECL int archive_match_include_time(struct archive *, int _flag, + time_t _sec, long _nsec); +/* Set inclusion time by a date string. */ +__LA_DECL int archive_match_include_date(struct archive *, int _flag, + const char *_datestr); +__LA_DECL int archive_match_include_date_w(struct archive *, int _flag, + const wchar_t *_datestr); +/* Set inclusion time by a particular file. */ +__LA_DECL int archive_match_include_file_time(struct archive *, + int _flag, const char *_pathname); +__LA_DECL int archive_match_include_file_time_w(struct archive *, + int _flag, const wchar_t *_pathname); +/* Add exclusion entry. */ +__LA_DECL int archive_match_exclude_entry(struct archive *, + int _flag, struct archive_entry *); + +/* + * Test if a file is excluded by its uid ,gid, uname or gname. + * The conditions are set by following functions. + */ +__LA_DECL int archive_match_owner_excluded(struct archive *, + struct archive_entry *); +/* Add inclusion uid, gid, uname and gname. */ +__LA_DECL int archive_match_include_uid(struct archive *, la_int64_t); +__LA_DECL int archive_match_include_gid(struct archive *, la_int64_t); +__LA_DECL int archive_match_include_uname(struct archive *, const char *); +__LA_DECL int archive_match_include_uname_w(struct archive *, + const wchar_t *); +__LA_DECL int archive_match_include_gname(struct archive *, const char *); +__LA_DECL int archive_match_include_gname_w(struct archive *, + const wchar_t *); + +/* Utility functions */ +/* Convenience function to sort a NULL terminated list of strings */ +__LA_DECL int archive_utility_string_sort(char **); + +#ifdef __cplusplus +} +#endif + +/* These are meaningless outside of this header. */ +#undef __LA_DECL + +#endif /* !ARCHIVE_H_INCLUDED */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_acl.c b/dependencies/libarchive-3.4.2/libarchive/archive_acl.c new file mode 100644 index 0000000..952e20d --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_acl.c @@ -0,0 +1,2097 @@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * Copyright (c) 2016 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_WCHAR_H +#include +#endif + +#include "archive_acl_private.h" +#include "archive_entry.h" +#include "archive_private.h" + +#undef max +#define max(a, b) ((a)>(b)?(a):(b)) + +#ifndef HAVE_WMEMCMP +/* Good enough for simple equality testing, but not for sorting. */ +#define wmemcmp(a,b,i) memcmp((a), (b), (i) * sizeof(wchar_t)) +#endif + +static int acl_special(struct archive_acl *acl, + int type, int permset, int tag); +static struct archive_acl_entry *acl_new_entry(struct archive_acl *acl, + int type, int permset, int tag, int id); +static int archive_acl_add_entry_len_l(struct archive_acl *acl, + int type, int permset, int tag, int id, const char *name, + size_t len, struct archive_string_conv *sc); +static int archive_acl_text_want_type(struct archive_acl *acl, int flags); +static ssize_t archive_acl_text_len(struct archive_acl *acl, int want_type, + int flags, int wide, struct archive *a, + struct archive_string_conv *sc); +static int isint_w(const wchar_t *start, const wchar_t *end, int *result); +static int ismode_w(const wchar_t *start, const wchar_t *end, int *result); +static int is_nfs4_flags_w(const wchar_t *start, const wchar_t *end, + int *result); +static int is_nfs4_perms_w(const wchar_t *start, const wchar_t *end, + int *result); +static void next_field_w(const wchar_t **wp, const wchar_t **start, + const wchar_t **end, wchar_t *sep); +static void append_entry_w(wchar_t **wp, const wchar_t *prefix, int type, + int tag, int flags, const wchar_t *wname, int perm, int id); +static void append_id_w(wchar_t **wp, int id); +static int isint(const char *start, const char *end, int *result); +static int ismode(const char *start, const char *end, int *result); +static int is_nfs4_flags(const char *start, const char *end, + int *result); +static int is_nfs4_perms(const char *start, const char *end, + int *result); +static void next_field(const char **p, const char **start, + const char **end, char *sep); +static void append_entry(char **p, const char *prefix, int type, + int tag, int flags, const char *name, int perm, int id); +static void append_id(char **p, int id); + +static const struct { + const int perm; + const char c; + const wchar_t wc; +} nfsv4_acl_perm_map[] = { + { ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, 'r', + L'r' }, + { ARCHIVE_ENTRY_ACL_WRITE_DATA | ARCHIVE_ENTRY_ACL_ADD_FILE, 'w', + L'w' }, + { ARCHIVE_ENTRY_ACL_EXECUTE, 'x', L'x' }, + { ARCHIVE_ENTRY_ACL_APPEND_DATA | ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, + 'p', L'p' }, + { ARCHIVE_ENTRY_ACL_DELETE, 'd', L'd' }, + { ARCHIVE_ENTRY_ACL_DELETE_CHILD, 'D', L'D' }, + { ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, 'a', L'a' }, + { ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, 'A', L'A' }, + { ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, 'R', L'R' }, + { ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, 'W', L'W' }, + { ARCHIVE_ENTRY_ACL_READ_ACL, 'c', L'c' }, + { ARCHIVE_ENTRY_ACL_WRITE_ACL, 'C', L'C' }, + { ARCHIVE_ENTRY_ACL_WRITE_OWNER, 'o', L'o' }, + { ARCHIVE_ENTRY_ACL_SYNCHRONIZE, 's', L's' } +}; + +static const int nfsv4_acl_perm_map_size = (int)(sizeof(nfsv4_acl_perm_map) / + sizeof(nfsv4_acl_perm_map[0])); + +static const struct { + const int perm; + const char c; + const wchar_t wc; +} nfsv4_acl_flag_map[] = { + { ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, 'f', L'f' }, + { ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, 'd', L'd' }, + { ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, 'i', L'i' }, + { ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, 'n', L'n' }, + { ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, 'S', L'S' }, + { ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, 'F', L'F' }, + { ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, 'I', L'I' } +}; + +static const int nfsv4_acl_flag_map_size = (int)(sizeof(nfsv4_acl_flag_map) / + sizeof(nfsv4_acl_flag_map[0])); + +void +archive_acl_clear(struct archive_acl *acl) +{ + struct archive_acl_entry *ap; + + while (acl->acl_head != NULL) { + ap = acl->acl_head->next; + archive_mstring_clean(&acl->acl_head->name); + free(acl->acl_head); + acl->acl_head = ap; + } + free(acl->acl_text_w); + acl->acl_text_w = NULL; + free(acl->acl_text); + acl->acl_text = NULL; + acl->acl_p = NULL; + acl->acl_types = 0; + acl->acl_state = 0; /* Not counting. */ +} + +void +archive_acl_copy(struct archive_acl *dest, struct archive_acl *src) +{ + struct archive_acl_entry *ap, *ap2; + + archive_acl_clear(dest); + + dest->mode = src->mode; + ap = src->acl_head; + while (ap != NULL) { + ap2 = acl_new_entry(dest, + ap->type, ap->permset, ap->tag, ap->id); + if (ap2 != NULL) + archive_mstring_copy(&ap2->name, &ap->name); + ap = ap->next; + } +} + +int +archive_acl_add_entry(struct archive_acl *acl, + int type, int permset, int tag, int id, const char *name) +{ + struct archive_acl_entry *ap; + + if (acl_special(acl, type, permset, tag) == 0) + return ARCHIVE_OK; + ap = acl_new_entry(acl, type, permset, tag, id); + if (ap == NULL) { + /* XXX Error XXX */ + return ARCHIVE_FAILED; + } + if (name != NULL && *name != '\0') + archive_mstring_copy_mbs(&ap->name, name); + else + archive_mstring_clean(&ap->name); + return ARCHIVE_OK; +} + +int +archive_acl_add_entry_w_len(struct archive_acl *acl, + int type, int permset, int tag, int id, const wchar_t *name, size_t len) +{ + struct archive_acl_entry *ap; + + if (acl_special(acl, type, permset, tag) == 0) + return ARCHIVE_OK; + ap = acl_new_entry(acl, type, permset, tag, id); + if (ap == NULL) { + /* XXX Error XXX */ + return ARCHIVE_FAILED; + } + if (name != NULL && *name != L'\0' && len > 0) + archive_mstring_copy_wcs_len(&ap->name, name, len); + else + archive_mstring_clean(&ap->name); + return ARCHIVE_OK; +} + +static int +archive_acl_add_entry_len_l(struct archive_acl *acl, + int type, int permset, int tag, int id, const char *name, size_t len, + struct archive_string_conv *sc) +{ + struct archive_acl_entry *ap; + int r; + + if (acl_special(acl, type, permset, tag) == 0) + return ARCHIVE_OK; + ap = acl_new_entry(acl, type, permset, tag, id); + if (ap == NULL) { + /* XXX Error XXX */ + return ARCHIVE_FAILED; + } + if (name != NULL && *name != '\0' && len > 0) { + r = archive_mstring_copy_mbs_len_l(&ap->name, name, len, sc); + } else { + r = 0; + archive_mstring_clean(&ap->name); + } + if (r == 0) + return (ARCHIVE_OK); + else if (errno == ENOMEM) + return (ARCHIVE_FATAL); + else + return (ARCHIVE_WARN); +} + +/* + * If this ACL entry is part of the standard POSIX permissions set, + * store the permissions in the stat structure and return zero. + */ +static int +acl_special(struct archive_acl *acl, int type, int permset, int tag) +{ + if (type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS + && ((permset & ~007) == 0)) { + switch (tag) { + case ARCHIVE_ENTRY_ACL_USER_OBJ: + acl->mode &= ~0700; + acl->mode |= (permset & 7) << 6; + return (0); + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + acl->mode &= ~0070; + acl->mode |= (permset & 7) << 3; + return (0); + case ARCHIVE_ENTRY_ACL_OTHER: + acl->mode &= ~0007; + acl->mode |= permset & 7; + return (0); + } + } + return (1); +} + +/* + * Allocate and populate a new ACL entry with everything but the + * name. + */ +static struct archive_acl_entry * +acl_new_entry(struct archive_acl *acl, + int type, int permset, int tag, int id) +{ + struct archive_acl_entry *ap, *aq; + + /* Type argument must be a valid NFS4 or POSIX.1e type. + * The type must agree with anything already set and + * the permset must be compatible. */ + if (type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + if (acl->acl_types & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + return (NULL); + } + if (permset & + ~(ARCHIVE_ENTRY_ACL_PERMS_NFS4 + | ARCHIVE_ENTRY_ACL_INHERITANCE_NFS4)) { + return (NULL); + } + } else if (type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) { + if (acl->acl_types & ~ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) { + return (NULL); + } + if (permset & ~ARCHIVE_ENTRY_ACL_PERMS_POSIX1E) { + return (NULL); + } + } else { + return (NULL); + } + + /* Verify the tag is valid and compatible with NFS4 or POSIX.1e. */ + switch (tag) { + case ARCHIVE_ENTRY_ACL_USER: + case ARCHIVE_ENTRY_ACL_USER_OBJ: + case ARCHIVE_ENTRY_ACL_GROUP: + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + /* Tags valid in both NFS4 and POSIX.1e */ + break; + case ARCHIVE_ENTRY_ACL_MASK: + case ARCHIVE_ENTRY_ACL_OTHER: + /* Tags valid only in POSIX.1e. */ + if (type & ~ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) { + return (NULL); + } + break; + case ARCHIVE_ENTRY_ACL_EVERYONE: + /* Tags valid only in NFS4. */ + if (type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + return (NULL); + } + break; + default: + /* No other values are valid. */ + return (NULL); + } + + free(acl->acl_text_w); + acl->acl_text_w = NULL; + free(acl->acl_text); + acl->acl_text = NULL; + + /* + * If there's a matching entry already in the list, overwrite it. + * NFSv4 entries may be repeated and are not overwritten. + * + * TODO: compare names of no id is provided (needs more rework) + */ + ap = acl->acl_head; + aq = NULL; + while (ap != NULL) { + if (((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0) && + ap->type == type && ap->tag == tag && ap->id == id) { + if (id != -1 || (tag != ARCHIVE_ENTRY_ACL_USER && + tag != ARCHIVE_ENTRY_ACL_GROUP)) { + ap->permset = permset; + return (ap); + } + } + aq = ap; + ap = ap->next; + } + + /* Add a new entry to the end of the list. */ + ap = (struct archive_acl_entry *)calloc(1, sizeof(*ap)); + if (ap == NULL) + return (NULL); + if (aq == NULL) + acl->acl_head = ap; + else + aq->next = ap; + ap->type = type; + ap->tag = tag; + ap->id = id; + ap->permset = permset; + acl->acl_types |= type; + return (ap); +} + +/* + * Return a count of entries matching "want_type". + */ +int +archive_acl_count(struct archive_acl *acl, int want_type) +{ + int count; + struct archive_acl_entry *ap; + + count = 0; + ap = acl->acl_head; + while (ap != NULL) { + if ((ap->type & want_type) != 0) + count++; + ap = ap->next; + } + + if (count > 0 && ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)) + count += 3; + return (count); +} + +/* + * Return a bitmask of stored ACL types in an ACL list + */ +int +archive_acl_types(struct archive_acl *acl) +{ + return (acl->acl_types); +} + +/* + * Prepare for reading entries from the ACL data. Returns a count + * of entries matching "want_type", or zero if there are no + * non-extended ACL entries of that type. + */ +int +archive_acl_reset(struct archive_acl *acl, int want_type) +{ + int count, cutoff; + + count = archive_acl_count(acl, want_type); + + /* + * If the only entries are the three standard ones, + * then don't return any ACL data. (In this case, + * client can just use chmod(2) to set permissions.) + */ + if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) + cutoff = 3; + else + cutoff = 0; + + if (count > cutoff) + acl->acl_state = ARCHIVE_ENTRY_ACL_USER_OBJ; + else + acl->acl_state = 0; + acl->acl_p = acl->acl_head; + return (count); +} + + +/* + * Return the next ACL entry in the list. Fake entries for the + * standard permissions and include them in the returned list. + */ +int +archive_acl_next(struct archive *a, struct archive_acl *acl, int want_type, + int *type, int *permset, int *tag, int *id, const char **name) +{ + *name = NULL; + *id = -1; + + /* + * The acl_state is either zero (no entries available), -1 + * (reading from list), or an entry type (retrieve that type + * from ae_stat.aest_mode). + */ + if (acl->acl_state == 0) + return (ARCHIVE_WARN); + + /* The first three access entries are special. */ + if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { + switch (acl->acl_state) { + case ARCHIVE_ENTRY_ACL_USER_OBJ: + *permset = (acl->mode >> 6) & 7; + *type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; + *tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + acl->acl_state = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + return (ARCHIVE_OK); + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + *permset = (acl->mode >> 3) & 7; + *type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; + *tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + acl->acl_state = ARCHIVE_ENTRY_ACL_OTHER; + return (ARCHIVE_OK); + case ARCHIVE_ENTRY_ACL_OTHER: + *permset = acl->mode & 7; + *type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; + *tag = ARCHIVE_ENTRY_ACL_OTHER; + acl->acl_state = -1; + acl->acl_p = acl->acl_head; + return (ARCHIVE_OK); + default: + break; + } + } + + while (acl->acl_p != NULL && (acl->acl_p->type & want_type) == 0) + acl->acl_p = acl->acl_p->next; + if (acl->acl_p == NULL) { + acl->acl_state = 0; + *type = 0; + *permset = 0; + *tag = 0; + *id = -1; + *name = NULL; + return (ARCHIVE_EOF); /* End of ACL entries. */ + } + *type = acl->acl_p->type; + *permset = acl->acl_p->permset; + *tag = acl->acl_p->tag; + *id = acl->acl_p->id; + if (archive_mstring_get_mbs(a, &acl->acl_p->name, name) != 0) { + if (errno == ENOMEM) + return (ARCHIVE_FATAL); + *name = NULL; + } + acl->acl_p = acl->acl_p->next; + return (ARCHIVE_OK); +} + +/* + * Determine what type of ACL do we want + */ +static int +archive_acl_text_want_type(struct archive_acl *acl, int flags) +{ + int want_type; + + /* Check if ACL is NFSv4 */ + if ((acl->acl_types & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + /* NFSv4 should never mix with POSIX.1e */ + if ((acl->acl_types & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) + return (0); + else + return (ARCHIVE_ENTRY_ACL_TYPE_NFS4); + } + + /* Now deal with POSIX.1e ACLs */ + + want_type = 0; + if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) + want_type |= ARCHIVE_ENTRY_ACL_TYPE_ACCESS; + if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) + want_type |= ARCHIVE_ENTRY_ACL_TYPE_DEFAULT; + + /* By default we want both access and default ACLs */ + if (want_type == 0) + return (ARCHIVE_ENTRY_ACL_TYPE_POSIX1E); + + return (want_type); +} + +/* + * Calculate ACL text string length + */ +static ssize_t +archive_acl_text_len(struct archive_acl *acl, int want_type, int flags, + int wide, struct archive *a, struct archive_string_conv *sc) { + struct archive_acl_entry *ap; + const char *name; + const wchar_t *wname; + int count, idlen, tmp, r; + ssize_t length; + size_t len; + + count = 0; + length = 0; + for (ap = acl->acl_head; ap != NULL; ap = ap->next) { + if ((ap->type & want_type) == 0) + continue; + /* + * Filemode-mapping ACL entries are stored exclusively in + * ap->mode so they should not be in the list + */ + if ((ap->type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) + && (ap->tag == ARCHIVE_ENTRY_ACL_USER_OBJ + || ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ + || ap->tag == ARCHIVE_ENTRY_ACL_OTHER)) + continue; + count++; + if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0 + && (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) + length += 8; /* "default:" */ + switch (ap->tag) { + case ARCHIVE_ENTRY_ACL_USER_OBJ: + if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + length += 6; /* "owner@" */ + break; + } + /* FALLTHROUGH */ + case ARCHIVE_ENTRY_ACL_USER: + case ARCHIVE_ENTRY_ACL_MASK: + length += 4; /* "user", "mask" */ + break; + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + length += 6; /* "group@" */ + break; + } + /* FALLTHROUGH */ + case ARCHIVE_ENTRY_ACL_GROUP: + case ARCHIVE_ENTRY_ACL_OTHER: + length += 5; /* "group", "other" */ + break; + case ARCHIVE_ENTRY_ACL_EVERYONE: + length += 9; /* "everyone@" */ + break; + } + length += 1; /* colon after tag */ + if (ap->tag == ARCHIVE_ENTRY_ACL_USER || + ap->tag == ARCHIVE_ENTRY_ACL_GROUP) { + if (wide) { + r = archive_mstring_get_wcs(a, &ap->name, + &wname); + if (r == 0 && wname != NULL) + length += wcslen(wname); + else if (r < 0 && errno == ENOMEM) + return (0); + else + length += sizeof(uid_t) * 3 + 1; + } else { + r = archive_mstring_get_mbs_l(&ap->name, &name, + &len, sc); + if (r != 0) + return (0); + if (len > 0 && name != NULL) + length += len; + else + length += sizeof(uid_t) * 3 + 1; + } + length += 1; /* colon after user or group name */ + } else if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) + length += 1; /* 2nd colon empty user,group or other */ + + if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) != 0) + && ((want_type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) + && (ap->tag == ARCHIVE_ENTRY_ACL_OTHER + || ap->tag == ARCHIVE_ENTRY_ACL_MASK)) { + /* Solaris has no colon after other: and mask: */ + length = length - 1; + } + + if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + /* rwxpdDaARWcCos:fdinSFI:deny */ + length += 27; + if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DENY) == 0) + length += 1; /* allow, alarm, audit */ + } else + length += 3; /* rwx */ + + if ((ap->tag == ARCHIVE_ENTRY_ACL_USER || + ap->tag == ARCHIVE_ENTRY_ACL_GROUP) && + (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0) { + length += 1; /* colon */ + /* ID digit count */ + idlen = 1; + tmp = ap->id; + while (tmp > 9) { + tmp = tmp / 10; + idlen++; + } + length += idlen; + } + length ++; /* entry separator */ + } + + /* Add filemode-mapping access entries to the length */ + if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { + if ((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) != 0) { + /* "user::rwx\ngroup::rwx\nother:rwx\n" */ + length += 31; + } else { + /* "user::rwx\ngroup::rwx\nother::rwx\n" */ + length += 32; + } + } else if (count == 0) + return (0); + + /* The terminating character is included in count */ + return (length); +} + +/* + * Generate a wide text version of the ACL. The flags parameter controls + * the type and style of the generated ACL. + */ +wchar_t * +archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags, + struct archive *a) +{ + int count; + ssize_t length; + size_t len; + const wchar_t *wname; + const wchar_t *prefix; + wchar_t separator; + struct archive_acl_entry *ap; + int id, r, want_type; + wchar_t *wp, *ws; + + want_type = archive_acl_text_want_type(acl, flags); + + /* Both NFSv4 and POSIX.1 types found */ + if (want_type == 0) + return (NULL); + + if (want_type == ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) + flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT; + + length = archive_acl_text_len(acl, want_type, flags, 1, a, NULL); + + if (length == 0) + return (NULL); + + if (flags & ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA) + separator = L','; + else + separator = L'\n'; + + /* Now, allocate the string and actually populate it. */ + wp = ws = (wchar_t *)malloc(length * sizeof(wchar_t)); + if (wp == NULL) { + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (NULL); + } + count = 0; + + if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { + append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_USER_OBJ, flags, NULL, + acl->mode & 0700, -1); + *wp++ = separator; + append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, flags, NULL, + acl->mode & 0070, -1); + *wp++ = separator; + append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_OTHER, flags, NULL, + acl->mode & 0007, -1); + count += 3; + } + + for (ap = acl->acl_head; ap != NULL; ap = ap->next) { + if ((ap->type & want_type) == 0) + continue; + /* + * Filemode-mapping ACL entries are stored exclusively in + * ap->mode so they should not be in the list + */ + if ((ap->type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) + && (ap->tag == ARCHIVE_ENTRY_ACL_USER_OBJ + || ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ + || ap->tag == ARCHIVE_ENTRY_ACL_OTHER)) + continue; + if (ap->type == ARCHIVE_ENTRY_ACL_TYPE_DEFAULT && + (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0) + prefix = L"default:"; + else + prefix = NULL; + r = archive_mstring_get_wcs(a, &ap->name, &wname); + if (r == 0) { + if (count > 0) + *wp++ = separator; + if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) + id = ap->id; + else + id = -1; + append_entry_w(&wp, prefix, ap->type, ap->tag, flags, + wname, ap->permset, id); + count++; + } else if (r < 0 && errno == ENOMEM) { + free(ws); + return (NULL); + } + } + + /* Add terminating character */ + *wp++ = L'\0'; + + len = wcslen(ws); + + if ((ssize_t)len > (length - 1)) + __archive_errx(1, "Buffer overrun"); + + if (text_len != NULL) + *text_len = len; + + return (ws); +} + +static void +append_id_w(wchar_t **wp, int id) +{ + if (id < 0) + id = 0; + if (id > 9) + append_id_w(wp, id / 10); + *(*wp)++ = L"0123456789"[id % 10]; +} + +static void +append_entry_w(wchar_t **wp, const wchar_t *prefix, int type, + int tag, int flags, const wchar_t *wname, int perm, int id) +{ + int i; + + if (prefix != NULL) { + wcscpy(*wp, prefix); + *wp += wcslen(*wp); + } + switch (tag) { + case ARCHIVE_ENTRY_ACL_USER_OBJ: + wname = NULL; + id = -1; + if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + wcscpy(*wp, L"owner@"); + break; + } + /* FALLTHROUGH */ + case ARCHIVE_ENTRY_ACL_USER: + wcscpy(*wp, L"user"); + break; + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + wname = NULL; + id = -1; + if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + wcscpy(*wp, L"group@"); + break; + } + /* FALLTHROUGH */ + case ARCHIVE_ENTRY_ACL_GROUP: + wcscpy(*wp, L"group"); + break; + case ARCHIVE_ENTRY_ACL_MASK: + wcscpy(*wp, L"mask"); + wname = NULL; + id = -1; + break; + case ARCHIVE_ENTRY_ACL_OTHER: + wcscpy(*wp, L"other"); + wname = NULL; + id = -1; + break; + case ARCHIVE_ENTRY_ACL_EVERYONE: + wcscpy(*wp, L"everyone@"); + wname = NULL; + id = -1; + break; + } + *wp += wcslen(*wp); + *(*wp)++ = L':'; + if (((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) || + tag == ARCHIVE_ENTRY_ACL_USER || + tag == ARCHIVE_ENTRY_ACL_GROUP) { + if (wname != NULL) { + wcscpy(*wp, wname); + *wp += wcslen(*wp); + } else if (tag == ARCHIVE_ENTRY_ACL_USER + || tag == ARCHIVE_ENTRY_ACL_GROUP) { + append_id_w(wp, id); + if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0) + id = -1; + } + /* Solaris style has no second colon after other and mask */ + if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) == 0) + || (tag != ARCHIVE_ENTRY_ACL_OTHER + && tag != ARCHIVE_ENTRY_ACL_MASK)) + *(*wp)++ = L':'; + } + if ((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) { + /* POSIX.1e ACL perms */ + *(*wp)++ = (perm & 0444) ? L'r' : L'-'; + *(*wp)++ = (perm & 0222) ? L'w' : L'-'; + *(*wp)++ = (perm & 0111) ? L'x' : L'-'; + } else { + /* NFSv4 ACL perms */ + for (i = 0; i < nfsv4_acl_perm_map_size; i++) { + if (perm & nfsv4_acl_perm_map[i].perm) + *(*wp)++ = nfsv4_acl_perm_map[i].wc; + else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0) + *(*wp)++ = L'-'; + } + *(*wp)++ = L':'; + for (i = 0; i < nfsv4_acl_flag_map_size; i++) { + if (perm & nfsv4_acl_flag_map[i].perm) + *(*wp)++ = nfsv4_acl_flag_map[i].wc; + else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0) + *(*wp)++ = L'-'; + } + *(*wp)++ = L':'; + switch (type) { + case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: + wcscpy(*wp, L"allow"); + break; + case ARCHIVE_ENTRY_ACL_TYPE_DENY: + wcscpy(*wp, L"deny"); + break; + case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: + wcscpy(*wp, L"audit"); + break; + case ARCHIVE_ENTRY_ACL_TYPE_ALARM: + wcscpy(*wp, L"alarm"); + break; + default: + break; + } + *wp += wcslen(*wp); + } + if (id != -1) { + *(*wp)++ = L':'; + append_id_w(wp, id); + } +} + +/* + * Generate a text version of the ACL. The flags parameter controls + * the type and style of the generated ACL. + */ +char * +archive_acl_to_text_l(struct archive_acl *acl, ssize_t *text_len, int flags, + struct archive_string_conv *sc) +{ + int count; + ssize_t length; + size_t len; + const char *name; + const char *prefix; + char separator; + struct archive_acl_entry *ap; + int id, r, want_type; + char *p, *s; + + want_type = archive_acl_text_want_type(acl, flags); + + /* Both NFSv4 and POSIX.1 types found */ + if (want_type == 0) + return (NULL); + + if (want_type == ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) + flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT; + + length = archive_acl_text_len(acl, want_type, flags, 0, NULL, sc); + + if (length == 0) + return (NULL); + + if (flags & ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA) + separator = ','; + else + separator = '\n'; + + /* Now, allocate the string and actually populate it. */ + p = s = (char *)malloc(length * sizeof(char)); + if (p == NULL) { + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (NULL); + } + count = 0; + + if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { + append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_USER_OBJ, flags, NULL, + acl->mode & 0700, -1); + *p++ = separator; + append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, flags, NULL, + acl->mode & 0070, -1); + *p++ = separator; + append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_OTHER, flags, NULL, + acl->mode & 0007, -1); + count += 3; + } + + for (ap = acl->acl_head; ap != NULL; ap = ap->next) { + if ((ap->type & want_type) == 0) + continue; + /* + * Filemode-mapping ACL entries are stored exclusively in + * ap->mode so they should not be in the list + */ + if ((ap->type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) + && (ap->tag == ARCHIVE_ENTRY_ACL_USER_OBJ + || ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ + || ap->tag == ARCHIVE_ENTRY_ACL_OTHER)) + continue; + if (ap->type == ARCHIVE_ENTRY_ACL_TYPE_DEFAULT && + (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0) + prefix = "default:"; + else + prefix = NULL; + r = archive_mstring_get_mbs_l( + &ap->name, &name, &len, sc); + if (r != 0) { + free(s); + return (NULL); + } + if (count > 0) + *p++ = separator; + if (name == NULL || + (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)) { + id = ap->id; + } else { + id = -1; + } + append_entry(&p, prefix, ap->type, ap->tag, flags, name, + ap->permset, id); + count++; + } + + /* Add terminating character */ + *p++ = '\0'; + + len = strlen(s); + + if ((ssize_t)len > (length - 1)) + __archive_errx(1, "Buffer overrun"); + + if (text_len != NULL) + *text_len = len; + + return (s); +} + +static void +append_id(char **p, int id) +{ + if (id < 0) + id = 0; + if (id > 9) + append_id(p, id / 10); + *(*p)++ = "0123456789"[id % 10]; +} + +static void +append_entry(char **p, const char *prefix, int type, + int tag, int flags, const char *name, int perm, int id) +{ + int i; + + if (prefix != NULL) { + strcpy(*p, prefix); + *p += strlen(*p); + } + switch (tag) { + case ARCHIVE_ENTRY_ACL_USER_OBJ: + name = NULL; + id = -1; + if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + strcpy(*p, "owner@"); + break; + } + /* FALLTHROUGH */ + case ARCHIVE_ENTRY_ACL_USER: + strcpy(*p, "user"); + break; + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + name = NULL; + id = -1; + if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + strcpy(*p, "group@"); + break; + } + /* FALLTHROUGH */ + case ARCHIVE_ENTRY_ACL_GROUP: + strcpy(*p, "group"); + break; + case ARCHIVE_ENTRY_ACL_MASK: + strcpy(*p, "mask"); + name = NULL; + id = -1; + break; + case ARCHIVE_ENTRY_ACL_OTHER: + strcpy(*p, "other"); + name = NULL; + id = -1; + break; + case ARCHIVE_ENTRY_ACL_EVERYONE: + strcpy(*p, "everyone@"); + name = NULL; + id = -1; + break; + } + *p += strlen(*p); + *(*p)++ = ':'; + if (((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) || + tag == ARCHIVE_ENTRY_ACL_USER || + tag == ARCHIVE_ENTRY_ACL_GROUP) { + if (name != NULL) { + strcpy(*p, name); + *p += strlen(*p); + } else if (tag == ARCHIVE_ENTRY_ACL_USER + || tag == ARCHIVE_ENTRY_ACL_GROUP) { + append_id(p, id); + if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0) + id = -1; + } + /* Solaris style has no second colon after other and mask */ + if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) == 0) + || (tag != ARCHIVE_ENTRY_ACL_OTHER + && tag != ARCHIVE_ENTRY_ACL_MASK)) + *(*p)++ = ':'; + } + if ((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) { + /* POSIX.1e ACL perms */ + *(*p)++ = (perm & 0444) ? 'r' : '-'; + *(*p)++ = (perm & 0222) ? 'w' : '-'; + *(*p)++ = (perm & 0111) ? 'x' : '-'; + } else { + /* NFSv4 ACL perms */ + for (i = 0; i < nfsv4_acl_perm_map_size; i++) { + if (perm & nfsv4_acl_perm_map[i].perm) + *(*p)++ = nfsv4_acl_perm_map[i].c; + else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0) + *(*p)++ = '-'; + } + *(*p)++ = ':'; + for (i = 0; i < nfsv4_acl_flag_map_size; i++) { + if (perm & nfsv4_acl_flag_map[i].perm) + *(*p)++ = nfsv4_acl_flag_map[i].c; + else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0) + *(*p)++ = '-'; + } + *(*p)++ = ':'; + switch (type) { + case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: + strcpy(*p, "allow"); + break; + case ARCHIVE_ENTRY_ACL_TYPE_DENY: + strcpy(*p, "deny"); + break; + case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: + strcpy(*p, "audit"); + break; + case ARCHIVE_ENTRY_ACL_TYPE_ALARM: + strcpy(*p, "alarm"); + break; + } + *p += strlen(*p); + } + if (id != -1) { + *(*p)++ = ':'; + append_id(p, id); + } +} + +/* + * Parse a wide ACL text string. + * + * The want_type argument may be one of the following: + * ARCHIVE_ENTRY_ACL_TYPE_ACCESS - text is a POSIX.1e ACL of type ACCESS + * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - text is a POSIX.1e ACL of type DEFAULT + * ARCHIVE_ENTRY_ACL_TYPE_NFS4 - text is as a NFSv4 ACL + * + * POSIX.1e ACL entries prefixed with "default:" are treated as + * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT unless type is ARCHIVE_ENTRY_ACL_TYPE_NFS4 + */ +int +archive_acl_from_text_w(struct archive_acl *acl, const wchar_t *text, + int want_type) +{ + struct { + const wchar_t *start; + const wchar_t *end; + } field[6], name; + + const wchar_t *s, *st; + + int numfields, fields, n, r, sol, ret; + int type, types, tag, permset, id; + size_t len; + wchar_t sep; + + ret = ARCHIVE_OK; + types = 0; + + switch (want_type) { + case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E: + want_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; + __LA_FALLTHROUGH; + case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: + case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: + numfields = 5; + break; + case ARCHIVE_ENTRY_ACL_TYPE_NFS4: + numfields = 6; + break; + default: + return (ARCHIVE_FATAL); + } + + while (text != NULL && *text != L'\0') { + /* + * Parse the fields out of the next entry, + * advance 'text' to start of next entry. + */ + fields = 0; + do { + const wchar_t *start, *end; + next_field_w(&text, &start, &end, &sep); + if (fields < numfields) { + field[fields].start = start; + field[fields].end = end; + } + ++fields; + } while (sep == L':'); + + /* Set remaining fields to blank. */ + for (n = fields; n < numfields; ++n) + field[n].start = field[n].end = NULL; + + if (field[0].start != NULL && *(field[0].start) == L'#') { + /* Comment, skip entry */ + continue; + } + + n = 0; + sol = 0; + id = -1; + permset = 0; + name.start = name.end = NULL; + + if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + /* POSIX.1e ACLs */ + /* + * Default keyword "default:user::rwx" + * if found, we have one more field + * + * We also support old Solaris extension: + * "defaultuser::rwx" is the default ACL corresponding + * to "user::rwx", etc. valid only for first field + */ + s = field[0].start; + len = field[0].end - field[0].start; + if (*s == L'd' && (len == 1 || (len >= 7 + && wmemcmp((s + 1), L"efault", 6) == 0))) { + type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT; + if (len > 7) + field[0].start += 7; + else + n = 1; + } else + type = want_type; + + /* Check for a numeric ID in field n+1 or n+3. */ + isint_w(field[n + 1].start, field[n + 1].end, &id); + /* Field n+3 is optional. */ + if (id == -1 && fields > n+3) + isint_w(field[n + 3].start, field[n + 3].end, + &id); + + tag = 0; + s = field[n].start; + st = field[n].start + 1; + len = field[n].end - field[n].start; + + switch (*s) { + case L'u': + if (len == 1 || (len == 4 + && wmemcmp(st, L"ser", 3) == 0)) + tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + break; + case L'g': + if (len == 1 || (len == 5 + && wmemcmp(st, L"roup", 4) == 0)) + tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + break; + case L'o': + if (len == 1 || (len == 5 + && wmemcmp(st, L"ther", 4) == 0)) + tag = ARCHIVE_ENTRY_ACL_OTHER; + break; + case L'm': + if (len == 1 || (len == 4 + && wmemcmp(st, L"ask", 3) == 0)) + tag = ARCHIVE_ENTRY_ACL_MASK; + break; + default: + break; + } + + switch (tag) { + case ARCHIVE_ENTRY_ACL_OTHER: + case ARCHIVE_ENTRY_ACL_MASK: + if (fields == (n + 2) + && field[n + 1].start < field[n + 1].end + && ismode_w(field[n + 1].start, + field[n + 1].end, &permset)) { + /* This is Solaris-style "other:rwx" */ + sol = 1; + } else if (fields == (n + 3) && + field[n + 1].start < field[n + 1].end) { + /* Invalid mask or other field */ + ret = ARCHIVE_WARN; + continue; + } + break; + case ARCHIVE_ENTRY_ACL_USER_OBJ: + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + if (id != -1 || + field[n + 1].start < field[n + 1].end) { + name = field[n + 1]; + if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ) + tag = ARCHIVE_ENTRY_ACL_USER; + else + tag = ARCHIVE_ENTRY_ACL_GROUP; + } + break; + default: + /* Invalid tag, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + + /* + * Without "default:" we expect mode in field 2 + * Exception: Solaris other and mask fields + */ + if (permset == 0 && !ismode_w(field[n + 2 - sol].start, + field[n + 2 - sol].end, &permset)) { + /* Invalid mode, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + } else { + /* NFS4 ACLs */ + s = field[0].start; + len = field[0].end - field[0].start; + tag = 0; + + switch (len) { + case 4: + if (wmemcmp(s, L"user", 4) == 0) + tag = ARCHIVE_ENTRY_ACL_USER; + break; + case 5: + if (wmemcmp(s, L"group", 5) == 0) + tag = ARCHIVE_ENTRY_ACL_GROUP; + break; + case 6: + if (wmemcmp(s, L"owner@", 6) == 0) + tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + else if (wmemcmp(s, L"group@", len) == 0) + tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + break; + case 9: + if (wmemcmp(s, L"everyone@", 9) == 0) + tag = ARCHIVE_ENTRY_ACL_EVERYONE; + default: + break; + } + + if (tag == 0) { + /* Invalid tag, skip entry */ + ret = ARCHIVE_WARN; + continue; + } else if (tag == ARCHIVE_ENTRY_ACL_USER || + tag == ARCHIVE_ENTRY_ACL_GROUP) { + n = 1; + name = field[1]; + isint_w(name.start, name.end, &id); + } else + n = 0; + + if (!is_nfs4_perms_w(field[1 + n].start, + field[1 + n].end, &permset)) { + /* Invalid NFSv4 perms, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + if (!is_nfs4_flags_w(field[2 + n].start, + field[2 + n].end, &permset)) { + /* Invalid NFSv4 flags, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + s = field[3 + n].start; + len = field[3 + n].end - field[3 + n].start; + type = 0; + if (len == 4) { + if (wmemcmp(s, L"deny", 4) == 0) + type = ARCHIVE_ENTRY_ACL_TYPE_DENY; + } else if (len == 5) { + if (wmemcmp(s, L"allow", 5) == 0) + type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; + else if (wmemcmp(s, L"audit", 5) == 0) + type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT; + else if (wmemcmp(s, L"alarm", 5) == 0) + type = ARCHIVE_ENTRY_ACL_TYPE_ALARM; + } + if (type == 0) { + /* Invalid entry type, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + isint_w(field[4 + n].start, field[4 + n].end, &id); + } + + /* Add entry to the internal list. */ + r = archive_acl_add_entry_w_len(acl, type, permset, + tag, id, name.start, name.end - name.start); + if (r < ARCHIVE_WARN) + return (r); + if (r != ARCHIVE_OK) + ret = ARCHIVE_WARN; + types |= type; + } + + /* Reset ACL */ + archive_acl_reset(acl, types); + + return (ret); +} + +/* + * Parse a string to a positive decimal integer. Returns true if + * the string is non-empty and consists only of decimal digits, + * false otherwise. + */ +static int +isint_w(const wchar_t *start, const wchar_t *end, int *result) +{ + int n = 0; + if (start >= end) + return (0); + while (start < end) { + if (*start < '0' || *start > '9') + return (0); + if (n > (INT_MAX / 10) || + (n == INT_MAX / 10 && (*start - '0') > INT_MAX % 10)) { + n = INT_MAX; + } else { + n *= 10; + n += *start - '0'; + } + start++; + } + *result = n; + return (1); +} + +/* + * Parse a string as a mode field. Returns true if + * the string is non-empty and consists only of mode characters, + * false otherwise. + */ +static int +ismode_w(const wchar_t *start, const wchar_t *end, int *permset) +{ + const wchar_t *p; + + if (start >= end) + return (0); + p = start; + *permset = 0; + while (p < end) { + switch (*p++) { + case L'r': case L'R': + *permset |= ARCHIVE_ENTRY_ACL_READ; + break; + case L'w': case L'W': + *permset |= ARCHIVE_ENTRY_ACL_WRITE; + break; + case L'x': case L'X': + *permset |= ARCHIVE_ENTRY_ACL_EXECUTE; + break; + case L'-': + break; + default: + return (0); + } + } + return (1); +} + +/* + * Parse a string as a NFS4 ACL permission field. + * Returns true if the string is non-empty and consists only of NFS4 ACL + * permission characters, false otherwise + */ +static int +is_nfs4_perms_w(const wchar_t *start, const wchar_t *end, int *permset) +{ + const wchar_t *p = start; + + while (p < end) { + switch (*p++) { + case L'r': + *permset |= ARCHIVE_ENTRY_ACL_READ_DATA; + break; + case L'w': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_DATA; + break; + case L'x': + *permset |= ARCHIVE_ENTRY_ACL_EXECUTE; + break; + case L'p': + *permset |= ARCHIVE_ENTRY_ACL_APPEND_DATA; + break; + case L'D': + *permset |= ARCHIVE_ENTRY_ACL_DELETE_CHILD; + break; + case L'd': + *permset |= ARCHIVE_ENTRY_ACL_DELETE; + break; + case L'a': + *permset |= ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES; + break; + case L'A': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES; + break; + case L'R': + *permset |= ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS; + break; + case L'W': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS; + break; + case L'c': + *permset |= ARCHIVE_ENTRY_ACL_READ_ACL; + break; + case L'C': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_ACL; + break; + case L'o': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_OWNER; + break; + case L's': + *permset |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE; + break; + case L'-': + break; + default: + return(0); + } + } + return (1); +} + +/* + * Parse a string as a NFS4 ACL flags field. + * Returns true if the string is non-empty and consists only of NFS4 ACL + * flag characters, false otherwise + */ +static int +is_nfs4_flags_w(const wchar_t *start, const wchar_t *end, int *permset) +{ + const wchar_t *p = start; + + while (p < end) { + switch(*p++) { + case L'f': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT; + break; + case L'd': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT; + break; + case L'i': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY; + break; + case L'n': + *permset |= + ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT; + break; + case L'S': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS; + break; + case L'F': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS; + break; + case L'I': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERITED; + break; + case L'-': + break; + default: + return (0); + } + } + return (1); +} + +/* + * Match "[:whitespace:]*(.*)[:whitespace:]*[:,\n]". *wp is updated + * to point to just after the separator. *start points to the first + * character of the matched text and *end just after the last + * character of the matched identifier. In particular *end - *start + * is the length of the field body, not including leading or trailing + * whitespace. + */ +static void +next_field_w(const wchar_t **wp, const wchar_t **start, + const wchar_t **end, wchar_t *sep) +{ + /* Skip leading whitespace to find start of field. */ + while (**wp == L' ' || **wp == L'\t' || **wp == L'\n') { + (*wp)++; + } + *start = *wp; + + /* Scan for the separator. */ + while (**wp != L'\0' && **wp != L',' && **wp != L':' && + **wp != L'\n' && **wp != L'#') { + (*wp)++; + } + *sep = **wp; + + /* Locate end of field, trim trailing whitespace if necessary */ + if (*wp == *start) { + *end = *wp; + } else { + *end = *wp - 1; + while (**end == L' ' || **end == L'\t' || **end == L'\n') { + (*end)--; + } + (*end)++; + } + + /* Handle in-field comments */ + if (*sep == L'#') { + while (**wp != L'\0' && **wp != L',' && **wp != L'\n') { + (*wp)++; + } + *sep = **wp; + } + + /* Adjust scanner location. */ + if (**wp != L'\0') + (*wp)++; +} + +/* + * Parse an ACL text string. + * + * The want_type argument may be one of the following: + * ARCHIVE_ENTRY_ACL_TYPE_ACCESS - text is a POSIX.1e ACL of type ACCESS + * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - text is a POSIX.1e ACL of type DEFAULT + * ARCHIVE_ENTRY_ACL_TYPE_NFS4 - text is as a NFSv4 ACL + * + * POSIX.1e ACL entries prefixed with "default:" are treated as + * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT unless type is ARCHIVE_ENTRY_ACL_TYPE_NFS4 + */ +int +archive_acl_from_text_l(struct archive_acl *acl, const char *text, + int want_type, struct archive_string_conv *sc) +{ + struct { + const char *start; + const char *end; + } field[6], name; + + const char *s, *st; + int numfields, fields, n, r, sol, ret; + int type, types, tag, permset, id; + size_t len; + char sep; + + switch (want_type) { + case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E: + want_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; + __LA_FALLTHROUGH; + case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: + case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: + numfields = 5; + break; + case ARCHIVE_ENTRY_ACL_TYPE_NFS4: + numfields = 6; + break; + default: + return (ARCHIVE_FATAL); + } + + ret = ARCHIVE_OK; + types = 0; + + while (text != NULL && *text != '\0') { + /* + * Parse the fields out of the next entry, + * advance 'text' to start of next entry. + */ + fields = 0; + do { + const char *start, *end; + next_field(&text, &start, &end, &sep); + if (fields < numfields) { + field[fields].start = start; + field[fields].end = end; + } + ++fields; + } while (sep == ':'); + + /* Set remaining fields to blank. */ + for (n = fields; n < numfields; ++n) + field[n].start = field[n].end = NULL; + + if (field[0].start != NULL && *(field[0].start) == '#') { + /* Comment, skip entry */ + continue; + } + + n = 0; + sol = 0; + id = -1; + permset = 0; + name.start = name.end = NULL; + + if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + /* POSIX.1e ACLs */ + /* + * Default keyword "default:user::rwx" + * if found, we have one more field + * + * We also support old Solaris extension: + * "defaultuser::rwx" is the default ACL corresponding + * to "user::rwx", etc. valid only for first field + */ + s = field[0].start; + len = field[0].end - field[0].start; + if (*s == 'd' && (len == 1 || (len >= 7 + && memcmp((s + 1), "efault", 6) == 0))) { + type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT; + if (len > 7) + field[0].start += 7; + else + n = 1; + } else + type = want_type; + + /* Check for a numeric ID in field n+1 or n+3. */ + isint(field[n + 1].start, field[n + 1].end, &id); + /* Field n+3 is optional. */ + if (id == -1 && fields > (n + 3)) + isint(field[n + 3].start, field[n + 3].end, + &id); + + tag = 0; + s = field[n].start; + st = field[n].start + 1; + len = field[n].end - field[n].start; + + if (len == 0) { + ret = ARCHIVE_WARN; + continue; + } + + switch (*s) { + case 'u': + if (len == 1 || (len == 4 + && memcmp(st, "ser", 3) == 0)) + tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + break; + case 'g': + if (len == 1 || (len == 5 + && memcmp(st, "roup", 4) == 0)) + tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + break; + case 'o': + if (len == 1 || (len == 5 + && memcmp(st, "ther", 4) == 0)) + tag = ARCHIVE_ENTRY_ACL_OTHER; + break; + case 'm': + if (len == 1 || (len == 4 + && memcmp(st, "ask", 3) == 0)) + tag = ARCHIVE_ENTRY_ACL_MASK; + break; + default: + break; + } + + switch (tag) { + case ARCHIVE_ENTRY_ACL_OTHER: + case ARCHIVE_ENTRY_ACL_MASK: + if (fields == (n + 2) + && field[n + 1].start < field[n + 1].end + && ismode(field[n + 1].start, + field[n + 1].end, &permset)) { + /* This is Solaris-style "other:rwx" */ + sol = 1; + } else if (fields == (n + 3) && + field[n + 1].start < field[n + 1].end) { + /* Invalid mask or other field */ + ret = ARCHIVE_WARN; + continue; + } + break; + case ARCHIVE_ENTRY_ACL_USER_OBJ: + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + if (id != -1 || + field[n + 1].start < field[n + 1].end) { + name = field[n + 1]; + if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ) + tag = ARCHIVE_ENTRY_ACL_USER; + else + tag = ARCHIVE_ENTRY_ACL_GROUP; + } + break; + default: + /* Invalid tag, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + + /* + * Without "default:" we expect mode in field 3 + * Exception: Solaris other and mask fields + */ + if (permset == 0 && !ismode(field[n + 2 - sol].start, + field[n + 2 - sol].end, &permset)) { + /* Invalid mode, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + } else { + /* NFS4 ACLs */ + s = field[0].start; + len = field[0].end - field[0].start; + tag = 0; + + switch (len) { + case 4: + if (memcmp(s, "user", 4) == 0) + tag = ARCHIVE_ENTRY_ACL_USER; + break; + case 5: + if (memcmp(s, "group", 5) == 0) + tag = ARCHIVE_ENTRY_ACL_GROUP; + break; + case 6: + if (memcmp(s, "owner@", 6) == 0) + tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + else if (memcmp(s, "group@", 6) == 0) + tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + break; + case 9: + if (memcmp(s, "everyone@", 9) == 0) + tag = ARCHIVE_ENTRY_ACL_EVERYONE; + break; + default: + break; + } + + if (tag == 0) { + /* Invalid tag, skip entry */ + ret = ARCHIVE_WARN; + continue; + } else if (tag == ARCHIVE_ENTRY_ACL_USER || + tag == ARCHIVE_ENTRY_ACL_GROUP) { + n = 1; + name = field[1]; + isint(name.start, name.end, &id); + } else + n = 0; + + if (!is_nfs4_perms(field[1 + n].start, + field[1 + n].end, &permset)) { + /* Invalid NFSv4 perms, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + if (!is_nfs4_flags(field[2 + n].start, + field[2 + n].end, &permset)) { + /* Invalid NFSv4 flags, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + s = field[3 + n].start; + len = field[3 + n].end - field[3 + n].start; + type = 0; + if (len == 4) { + if (memcmp(s, "deny", 4) == 0) + type = ARCHIVE_ENTRY_ACL_TYPE_DENY; + } else if (len == 5) { + if (memcmp(s, "allow", 5) == 0) + type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; + else if (memcmp(s, "audit", 5) == 0) + type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT; + else if (memcmp(s, "alarm", 5) == 0) + type = ARCHIVE_ENTRY_ACL_TYPE_ALARM; + } + if (type == 0) { + /* Invalid entry type, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + isint(field[4 + n].start, field[4 + n].end, + &id); + } + + /* Add entry to the internal list. */ + r = archive_acl_add_entry_len_l(acl, type, permset, + tag, id, name.start, name.end - name.start, sc); + if (r < ARCHIVE_WARN) + return (r); + if (r != ARCHIVE_OK) + ret = ARCHIVE_WARN; + types |= type; + } + + /* Reset ACL */ + archive_acl_reset(acl, types); + + return (ret); +} + +/* + * Parse a string to a positive decimal integer. Returns true if + * the string is non-empty and consists only of decimal digits, + * false otherwise. + */ +static int +isint(const char *start, const char *end, int *result) +{ + int n = 0; + if (start >= end) + return (0); + while (start < end) { + if (*start < '0' || *start > '9') + return (0); + if (n > (INT_MAX / 10) || + (n == INT_MAX / 10 && (*start - '0') > INT_MAX % 10)) { + n = INT_MAX; + } else { + n *= 10; + n += *start - '0'; + } + start++; + } + *result = n; + return (1); +} + +/* + * Parse a string as a mode field. Returns true if + * the string is non-empty and consists only of mode characters, + * false otherwise. + */ +static int +ismode(const char *start, const char *end, int *permset) +{ + const char *p; + + if (start >= end) + return (0); + p = start; + *permset = 0; + while (p < end) { + switch (*p++) { + case 'r': case 'R': + *permset |= ARCHIVE_ENTRY_ACL_READ; + break; + case 'w': case 'W': + *permset |= ARCHIVE_ENTRY_ACL_WRITE; + break; + case 'x': case 'X': + *permset |= ARCHIVE_ENTRY_ACL_EXECUTE; + break; + case '-': + break; + default: + return (0); + } + } + return (1); +} + +/* + * Parse a string as a NFS4 ACL permission field. + * Returns true if the string is non-empty and consists only of NFS4 ACL + * permission characters, false otherwise + */ +static int +is_nfs4_perms(const char *start, const char *end, int *permset) +{ + const char *p = start; + + while (p < end) { + switch (*p++) { + case 'r': + *permset |= ARCHIVE_ENTRY_ACL_READ_DATA; + break; + case 'w': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_DATA; + break; + case 'x': + *permset |= ARCHIVE_ENTRY_ACL_EXECUTE; + break; + case 'p': + *permset |= ARCHIVE_ENTRY_ACL_APPEND_DATA; + break; + case 'D': + *permset |= ARCHIVE_ENTRY_ACL_DELETE_CHILD; + break; + case 'd': + *permset |= ARCHIVE_ENTRY_ACL_DELETE; + break; + case 'a': + *permset |= ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES; + break; + case 'A': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES; + break; + case 'R': + *permset |= ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS; + break; + case 'W': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS; + break; + case 'c': + *permset |= ARCHIVE_ENTRY_ACL_READ_ACL; + break; + case 'C': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_ACL; + break; + case 'o': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_OWNER; + break; + case 's': + *permset |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE; + break; + case '-': + break; + default: + return(0); + } + } + return (1); +} + +/* + * Parse a string as a NFS4 ACL flags field. + * Returns true if the string is non-empty and consists only of NFS4 ACL + * flag characters, false otherwise + */ +static int +is_nfs4_flags(const char *start, const char *end, int *permset) +{ + const char *p = start; + + while (p < end) { + switch(*p++) { + case 'f': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT; + break; + case 'd': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT; + break; + case 'i': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY; + break; + case 'n': + *permset |= + ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT; + break; + case 'S': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS; + break; + case 'F': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS; + break; + case 'I': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERITED; + break; + case '-': + break; + default: + return (0); + } + } + return (1); +} + +/* + * Match "[:whitespace:]*(.*)[:whitespace:]*[:,\n]". *wp is updated + * to point to just after the separator. *start points to the first + * character of the matched text and *end just after the last + * character of the matched identifier. In particular *end - *start + * is the length of the field body, not including leading or trailing + * whitespace. + */ +static void +next_field(const char **p, const char **start, + const char **end, char *sep) +{ + /* Skip leading whitespace to find start of field. */ + while (**p == ' ' || **p == '\t' || **p == '\n') { + (*p)++; + } + *start = *p; + + /* Scan for the separator. */ + while (**p != '\0' && **p != ',' && **p != ':' && **p != '\n' && + **p != '#') { + (*p)++; + } + *sep = **p; + + /* Locate end of field, trim trailing whitespace if necessary */ + if (*p == *start) { + *end = *p; + } else { + *end = *p - 1; + while (**end == ' ' || **end == '\t' || **end == '\n') { + (*end)--; + } + (*end)++; + } + + /* Handle in-field comments */ + if (*sep == '#') { + while (**p != '\0' && **p != ',' && **p != '\n') { + (*p)++; + } + *sep = **p; + } + + /* Adjust scanner location. */ + if (**p != '\0') + (*p)++; +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_acl_private.h b/dependencies/libarchive-3.4.2/libarchive/archive_acl_private.h new file mode 100644 index 0000000..af10816 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_acl_private.h @@ -0,0 +1,83 @@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef ARCHIVE_ACL_PRIVATE_H_INCLUDED +#define ARCHIVE_ACL_PRIVATE_H_INCLUDED + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif + +#include "archive_string.h" + +struct archive_acl_entry { + struct archive_acl_entry *next; + int type; /* E.g., access or default */ + int tag; /* E.g., user/group/other/mask */ + int permset; /* r/w/x bits */ + int id; /* uid/gid for user/group */ + struct archive_mstring name; /* uname/gname */ +}; + +struct archive_acl { + mode_t mode; + struct archive_acl_entry *acl_head; + struct archive_acl_entry *acl_p; + int acl_state; /* See acl_next for details. */ + wchar_t *acl_text_w; + char *acl_text; + int acl_types; +}; + +void archive_acl_clear(struct archive_acl *); +void archive_acl_copy(struct archive_acl *, struct archive_acl *); +int archive_acl_count(struct archive_acl *, int); +int archive_acl_types(struct archive_acl *); +int archive_acl_reset(struct archive_acl *, int); +int archive_acl_next(struct archive *, struct archive_acl *, int, + int *, int *, int *, int *, const char **); + +int archive_acl_add_entry(struct archive_acl *, int, int, int, int, const char *); +int archive_acl_add_entry_w_len(struct archive_acl *, + int, int, int, int, const wchar_t *, size_t); +int archive_acl_add_entry_len(struct archive_acl *, + int, int, int, int, const char *, size_t); + +wchar_t *archive_acl_to_text_w(struct archive_acl *, ssize_t *, int, + struct archive *); +char *archive_acl_to_text_l(struct archive_acl *, ssize_t *, int, + struct archive_string_conv *); + +/* + * ACL text parser. + */ +int archive_acl_from_text_w(struct archive_acl *, const wchar_t * /* wtext */, + int /* type */); +int archive_acl_from_text_l(struct archive_acl *, const char * /* text */, + int /* type */, struct archive_string_conv *); + +#endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_blake2.h b/dependencies/libarchive-3.4.2/libarchive/archive_blake2.h new file mode 100644 index 0000000..dd6fe6f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_blake2.h @@ -0,0 +1,195 @@ +/* + BLAKE2 reference source code package - reference C implementations + + Copyright 2012, Samuel Neves . You may use this under the + terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at + your option. The terms of these licenses can be found at: + + - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + - OpenSSL license : https://www.openssl.org/source/license.html + - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + + More information about the BLAKE2 hash function can be found at + https://blake2.net. +*/ + +#ifndef ARCHIVE_BLAKE2_H +#define ARCHIVE_BLAKE2_H + +#include +#include + +#if defined(_MSC_VER) +#define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop)) +#else +#define BLAKE2_PACKED(x) x __attribute__((packed)) +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + + enum blake2s_constant + { + BLAKE2S_BLOCKBYTES = 64, + BLAKE2S_OUTBYTES = 32, + BLAKE2S_KEYBYTES = 32, + BLAKE2S_SALTBYTES = 8, + BLAKE2S_PERSONALBYTES = 8 + }; + + enum blake2b_constant + { + BLAKE2B_BLOCKBYTES = 128, + BLAKE2B_OUTBYTES = 64, + BLAKE2B_KEYBYTES = 64, + BLAKE2B_SALTBYTES = 16, + BLAKE2B_PERSONALBYTES = 16 + }; + + typedef struct blake2s_state__ + { + uint32_t h[8]; + uint32_t t[2]; + uint32_t f[2]; + uint8_t buf[BLAKE2S_BLOCKBYTES]; + size_t buflen; + size_t outlen; + uint8_t last_node; + } blake2s_state; + + typedef struct blake2b_state__ + { + uint64_t h[8]; + uint64_t t[2]; + uint64_t f[2]; + uint8_t buf[BLAKE2B_BLOCKBYTES]; + size_t buflen; + size_t outlen; + uint8_t last_node; + } blake2b_state; + + typedef struct blake2sp_state__ + { + blake2s_state S[8][1]; + blake2s_state R[1]; + uint8_t buf[8 * BLAKE2S_BLOCKBYTES]; + size_t buflen; + size_t outlen; + } blake2sp_state; + + typedef struct blake2bp_state__ + { + blake2b_state S[4][1]; + blake2b_state R[1]; + uint8_t buf[4 * BLAKE2B_BLOCKBYTES]; + size_t buflen; + size_t outlen; + } blake2bp_state; + + BLAKE2_PACKED(struct blake2s_param__ + { + uint8_t digest_length; /* 1 */ + uint8_t key_length; /* 2 */ + uint8_t fanout; /* 3 */ + uint8_t depth; /* 4 */ + uint32_t leaf_length; /* 8 */ + uint32_t node_offset; /* 12 */ + uint16_t xof_length; /* 14 */ + uint8_t node_depth; /* 15 */ + uint8_t inner_length; /* 16 */ + /* uint8_t reserved[0]; */ + uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */ + uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */ + }); + + typedef struct blake2s_param__ blake2s_param; + + BLAKE2_PACKED(struct blake2b_param__ + { + uint8_t digest_length; /* 1 */ + uint8_t key_length; /* 2 */ + uint8_t fanout; /* 3 */ + uint8_t depth; /* 4 */ + uint32_t leaf_length; /* 8 */ + uint32_t node_offset; /* 12 */ + uint32_t xof_length; /* 16 */ + uint8_t node_depth; /* 17 */ + uint8_t inner_length; /* 18 */ + uint8_t reserved[14]; /* 32 */ + uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */ + uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */ + }); + + typedef struct blake2b_param__ blake2b_param; + + typedef struct blake2xs_state__ + { + blake2s_state S[1]; + blake2s_param P[1]; + } blake2xs_state; + + typedef struct blake2xb_state__ + { + blake2b_state S[1]; + blake2b_param P[1]; + } blake2xb_state; + + /* Padded structs result in a compile-time error */ + enum { + BLAKE2_DUMMY_1 = 1/(sizeof(blake2s_param) == BLAKE2S_OUTBYTES), + BLAKE2_DUMMY_2 = 1/(sizeof(blake2b_param) == BLAKE2B_OUTBYTES) + }; + + /* Streaming API */ + int blake2s_init( blake2s_state *S, size_t outlen ); + int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen ); + int blake2s_init_param( blake2s_state *S, const blake2s_param *P ); + int blake2s_update( blake2s_state *S, const void *in, size_t inlen ); + int blake2s_final( blake2s_state *S, void *out, size_t outlen ); + + int blake2b_init( blake2b_state *S, size_t outlen ); + int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen ); + int blake2b_init_param( blake2b_state *S, const blake2b_param *P ); + int blake2b_update( blake2b_state *S, const void *in, size_t inlen ); + int blake2b_final( blake2b_state *S, void *out, size_t outlen ); + + int blake2sp_init( blake2sp_state *S, size_t outlen ); + int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen ); + int blake2sp_update( blake2sp_state *S, const void *in, size_t inlen ); + int blake2sp_final( blake2sp_state *S, void *out, size_t outlen ); + + int blake2bp_init( blake2bp_state *S, size_t outlen ); + int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen ); + int blake2bp_update( blake2bp_state *S, const void *in, size_t inlen ); + int blake2bp_final( blake2bp_state *S, void *out, size_t outlen ); + + /* Variable output length API */ + int blake2xs_init( blake2xs_state *S, const size_t outlen ); + int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen ); + int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen ); + int blake2xs_final(blake2xs_state *S, void *out, size_t outlen); + + int blake2xb_init( blake2xb_state *S, const size_t outlen ); + int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen ); + int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen ); + int blake2xb_final(blake2xb_state *S, void *out, size_t outlen); + + /* Simple API */ + int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); + int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); + + int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); + int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); + + int blake2xs( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); + int blake2xb( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); + + /* This is simply an alias for blake2b */ + int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_blake2_impl.h b/dependencies/libarchive-3.4.2/libarchive/archive_blake2_impl.h new file mode 100644 index 0000000..0f05def --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_blake2_impl.h @@ -0,0 +1,161 @@ +/* + BLAKE2 reference source code package - reference C implementations + + Copyright 2012, Samuel Neves . You may use this under the + terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at + your option. The terms of these licenses can be found at: + + - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + - OpenSSL license : https://www.openssl.org/source/license.html + - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + + More information about the BLAKE2 hash function can be found at + https://blake2.net. +*/ + +#ifndef ARCHIVE_BLAKE2_IMPL_H +#define ARCHIVE_BLAKE2_IMPL_H + +#include +#include + +#if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) + #if defined(_MSC_VER) + #define BLAKE2_INLINE __inline + #elif defined(__GNUC__) + #define BLAKE2_INLINE __inline__ + #else + #define BLAKE2_INLINE + #endif +#else + #define BLAKE2_INLINE inline +#endif + +static BLAKE2_INLINE uint32_t load32( const void *src ) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + uint32_t w; + memcpy(&w, src, sizeof w); + return w; +#else + const uint8_t *p = ( const uint8_t * )src; + return (( uint32_t )( p[0] ) << 0) | + (( uint32_t )( p[1] ) << 8) | + (( uint32_t )( p[2] ) << 16) | + (( uint32_t )( p[3] ) << 24) ; +#endif +} + +static BLAKE2_INLINE uint64_t load64( const void *src ) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + uint64_t w; + memcpy(&w, src, sizeof w); + return w; +#else + const uint8_t *p = ( const uint8_t * )src; + return (( uint64_t )( p[0] ) << 0) | + (( uint64_t )( p[1] ) << 8) | + (( uint64_t )( p[2] ) << 16) | + (( uint64_t )( p[3] ) << 24) | + (( uint64_t )( p[4] ) << 32) | + (( uint64_t )( p[5] ) << 40) | + (( uint64_t )( p[6] ) << 48) | + (( uint64_t )( p[7] ) << 56) ; +#endif +} + +static BLAKE2_INLINE uint16_t load16( const void *src ) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + uint16_t w; + memcpy(&w, src, sizeof w); + return w; +#else + const uint8_t *p = ( const uint8_t * )src; + return ( uint16_t )((( uint32_t )( p[0] ) << 0) | + (( uint32_t )( p[1] ) << 8)); +#endif +} + +static BLAKE2_INLINE void store16( void *dst, uint16_t w ) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + memcpy(dst, &w, sizeof w); +#else + uint8_t *p = ( uint8_t * )dst; + *p++ = ( uint8_t )w; w >>= 8; + *p++ = ( uint8_t )w; +#endif +} + +static BLAKE2_INLINE void store32( void *dst, uint32_t w ) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + memcpy(dst, &w, sizeof w); +#else + uint8_t *p = ( uint8_t * )dst; + p[0] = (uint8_t)(w >> 0); + p[1] = (uint8_t)(w >> 8); + p[2] = (uint8_t)(w >> 16); + p[3] = (uint8_t)(w >> 24); +#endif +} + +static BLAKE2_INLINE void store64( void *dst, uint64_t w ) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + memcpy(dst, &w, sizeof w); +#else + uint8_t *p = ( uint8_t * )dst; + p[0] = (uint8_t)(w >> 0); + p[1] = (uint8_t)(w >> 8); + p[2] = (uint8_t)(w >> 16); + p[3] = (uint8_t)(w >> 24); + p[4] = (uint8_t)(w >> 32); + p[5] = (uint8_t)(w >> 40); + p[6] = (uint8_t)(w >> 48); + p[7] = (uint8_t)(w >> 56); +#endif +} + +static BLAKE2_INLINE uint64_t load48( const void *src ) +{ + const uint8_t *p = ( const uint8_t * )src; + return (( uint64_t )( p[0] ) << 0) | + (( uint64_t )( p[1] ) << 8) | + (( uint64_t )( p[2] ) << 16) | + (( uint64_t )( p[3] ) << 24) | + (( uint64_t )( p[4] ) << 32) | + (( uint64_t )( p[5] ) << 40) ; +} + +static BLAKE2_INLINE void store48( void *dst, uint64_t w ) +{ + uint8_t *p = ( uint8_t * )dst; + p[0] = (uint8_t)(w >> 0); + p[1] = (uint8_t)(w >> 8); + p[2] = (uint8_t)(w >> 16); + p[3] = (uint8_t)(w >> 24); + p[4] = (uint8_t)(w >> 32); + p[5] = (uint8_t)(w >> 40); +} + +static BLAKE2_INLINE uint32_t rotr32( const uint32_t w, const unsigned c ) +{ + return ( w >> c ) | ( w << ( 32 - c ) ); +} + +static BLAKE2_INLINE uint64_t rotr64( const uint64_t w, const unsigned c ) +{ + return ( w >> c ) | ( w << ( 64 - c ) ); +} + +/* prevents compiler optimizing out memset() */ +static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n) +{ + static void *(*const volatile memset_v)(void *, int, size_t) = &memset; + memset_v(v, 0, n); +} + +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_blake2s_ref.c b/dependencies/libarchive-3.4.2/libarchive/archive_blake2s_ref.c new file mode 100644 index 0000000..d92ffd0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_blake2s_ref.c @@ -0,0 +1,367 @@ +/* + BLAKE2 reference source code package - reference C implementations + + Copyright 2012, Samuel Neves . You may use this under the + terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at + your option. The terms of these licenses can be found at: + + - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + - OpenSSL license : https://www.openssl.org/source/license.html + - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + + More information about the BLAKE2 hash function can be found at + https://blake2.net. +*/ + +#include +#include +#include + +#include "archive_blake2.h" +#include "archive_blake2_impl.h" + +static const uint32_t blake2s_IV[8] = +{ + 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL, + 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL +}; + +static const uint8_t blake2s_sigma[10][16] = +{ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , + { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , + { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , + { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , + { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , + { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , + { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , + { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , + { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , +}; + +static void blake2s_set_lastnode( blake2s_state *S ) +{ + S->f[1] = (uint32_t)-1; +} + +/* Some helper functions, not necessarily useful */ +static int blake2s_is_lastblock( const blake2s_state *S ) +{ + return S->f[0] != 0; +} + +static void blake2s_set_lastblock( blake2s_state *S ) +{ + if( S->last_node ) blake2s_set_lastnode( S ); + + S->f[0] = (uint32_t)-1; +} + +static void blake2s_increment_counter( blake2s_state *S, const uint32_t inc ) +{ + S->t[0] += inc; + S->t[1] += ( S->t[0] < inc ); +} + +static void blake2s_init0( blake2s_state *S ) +{ + size_t i; + memset( S, 0, sizeof( blake2s_state ) ); + + for( i = 0; i < 8; ++i ) S->h[i] = blake2s_IV[i]; +} + +/* init2 xors IV with input parameter block */ +int blake2s_init_param( blake2s_state *S, const blake2s_param *P ) +{ + const unsigned char *p = ( const unsigned char * )( P ); + size_t i; + + blake2s_init0( S ); + + /* IV XOR ParamBlock */ + for( i = 0; i < 8; ++i ) + S->h[i] ^= load32( &p[i * 4] ); + + S->outlen = P->digest_length; + return 0; +} + + +/* Sequential blake2s initialization */ +int blake2s_init( blake2s_state *S, size_t outlen ) +{ + blake2s_param P[1]; + + /* Move interval verification here? */ + if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1; + + P->digest_length = (uint8_t)outlen; + P->key_length = 0; + P->fanout = 1; + P->depth = 1; + store32( &P->leaf_length, 0 ); + store32( &P->node_offset, 0 ); + store16( &P->xof_length, 0 ); + P->node_depth = 0; + P->inner_length = 0; + /* memset(P->reserved, 0, sizeof(P->reserved) ); */ + memset( P->salt, 0, sizeof( P->salt ) ); + memset( P->personal, 0, sizeof( P->personal ) ); + return blake2s_init_param( S, P ); +} + +int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen ) +{ + blake2s_param P[1]; + + if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1; + + if ( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1; + + P->digest_length = (uint8_t)outlen; + P->key_length = (uint8_t)keylen; + P->fanout = 1; + P->depth = 1; + store32( &P->leaf_length, 0 ); + store32( &P->node_offset, 0 ); + store16( &P->xof_length, 0 ); + P->node_depth = 0; + P->inner_length = 0; + /* memset(P->reserved, 0, sizeof(P->reserved) ); */ + memset( P->salt, 0, sizeof( P->salt ) ); + memset( P->personal, 0, sizeof( P->personal ) ); + + if( blake2s_init_param( S, P ) < 0 ) return -1; + + { + uint8_t block[BLAKE2S_BLOCKBYTES]; + memset( block, 0, BLAKE2S_BLOCKBYTES ); + memcpy( block, key, keylen ); + blake2s_update( S, block, BLAKE2S_BLOCKBYTES ); + secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */ + } + return 0; +} + +#define G(r,i,a,b,c,d) \ + do { \ + a = a + b + m[blake2s_sigma[r][2*i+0]]; \ + d = rotr32(d ^ a, 16); \ + c = c + d; \ + b = rotr32(b ^ c, 12); \ + a = a + b + m[blake2s_sigma[r][2*i+1]]; \ + d = rotr32(d ^ a, 8); \ + c = c + d; \ + b = rotr32(b ^ c, 7); \ + } while(0) + +#define ROUND(r) \ + do { \ + G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ + G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ + G(r,2,v[ 2],v[ 6],v[10],v[14]); \ + G(r,3,v[ 3],v[ 7],v[11],v[15]); \ + G(r,4,v[ 0],v[ 5],v[10],v[15]); \ + G(r,5,v[ 1],v[ 6],v[11],v[12]); \ + G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ + G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ + } while(0) + +static void blake2s_compress( blake2s_state *S, const uint8_t in[BLAKE2S_BLOCKBYTES] ) +{ + uint32_t m[16]; + uint32_t v[16]; + size_t i; + + for( i = 0; i < 16; ++i ) { + m[i] = load32( in + i * sizeof( m[i] ) ); + } + + for( i = 0; i < 8; ++i ) { + v[i] = S->h[i]; + } + + v[ 8] = blake2s_IV[0]; + v[ 9] = blake2s_IV[1]; + v[10] = blake2s_IV[2]; + v[11] = blake2s_IV[3]; + v[12] = S->t[0] ^ blake2s_IV[4]; + v[13] = S->t[1] ^ blake2s_IV[5]; + v[14] = S->f[0] ^ blake2s_IV[6]; + v[15] = S->f[1] ^ blake2s_IV[7]; + + ROUND( 0 ); + ROUND( 1 ); + ROUND( 2 ); + ROUND( 3 ); + ROUND( 4 ); + ROUND( 5 ); + ROUND( 6 ); + ROUND( 7 ); + ROUND( 8 ); + ROUND( 9 ); + + for( i = 0; i < 8; ++i ) { + S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; + } +} + +#undef G +#undef ROUND + +int blake2s_update( blake2s_state *S, const void *pin, size_t inlen ) +{ + const unsigned char * in = (const unsigned char *)pin; + if( inlen > 0 ) + { + size_t left = S->buflen; + size_t fill = BLAKE2S_BLOCKBYTES - left; + if( inlen > fill ) + { + S->buflen = 0; + memcpy( S->buf + left, in, fill ); /* Fill buffer */ + blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES ); + blake2s_compress( S, S->buf ); /* Compress */ + in += fill; inlen -= fill; + while(inlen > BLAKE2S_BLOCKBYTES) { + blake2s_increment_counter(S, BLAKE2S_BLOCKBYTES); + blake2s_compress( S, in ); + in += BLAKE2S_BLOCKBYTES; + inlen -= BLAKE2S_BLOCKBYTES; + } + } + memcpy( S->buf + S->buflen, in, inlen ); + S->buflen += inlen; + } + return 0; +} + +int blake2s_final( blake2s_state *S, void *out, size_t outlen ) +{ + uint8_t buffer[BLAKE2S_OUTBYTES] = {0}; + size_t i; + + if( out == NULL || outlen < S->outlen ) + return -1; + + if( blake2s_is_lastblock( S ) ) + return -1; + + blake2s_increment_counter( S, ( uint32_t )S->buflen ); + blake2s_set_lastblock( S ); + memset( S->buf + S->buflen, 0, BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */ + blake2s_compress( S, S->buf ); + + for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */ + store32( buffer + sizeof( S->h[i] ) * i, S->h[i] ); + + memcpy( out, buffer, outlen ); + secure_zero_memory(buffer, sizeof(buffer)); + return 0; +} + +int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) +{ + blake2s_state S[1]; + + /* Verify parameters */ + if ( NULL == in && inlen > 0 ) return -1; + + if ( NULL == out ) return -1; + + if ( NULL == key && keylen > 0) return -1; + + if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1; + + if( keylen > BLAKE2S_KEYBYTES ) return -1; + + if( keylen > 0 ) + { + if( blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1; + } + else + { + if( blake2s_init( S, outlen ) < 0 ) return -1; + } + + blake2s_update( S, ( const uint8_t * )in, inlen ); + blake2s_final( S, out, outlen ); + return 0; +} + +#if defined(SUPERCOP) +int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen ) +{ + return blake2s( out, BLAKE2S_OUTBYTES, in, inlen, NULL, 0 ); +} +#endif + +#if defined(BLAKE2S_SELFTEST) +#include +#include "blake2-kat.h" +int main( void ) +{ + uint8_t key[BLAKE2S_KEYBYTES]; + uint8_t buf[BLAKE2_KAT_LENGTH]; + size_t i, step; + + for( i = 0; i < BLAKE2S_KEYBYTES; ++i ) + key[i] = ( uint8_t )i; + + for( i = 0; i < BLAKE2_KAT_LENGTH; ++i ) + buf[i] = ( uint8_t )i; + + /* Test simple API */ + for( i = 0; i < BLAKE2_KAT_LENGTH; ++i ) + { + uint8_t hash[BLAKE2S_OUTBYTES]; + blake2s( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES ); + + if( 0 != memcmp( hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES ) ) + { + goto fail; + } + } + + /* Test streaming API */ + for(step = 1; step < BLAKE2S_BLOCKBYTES; ++step) { + for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) { + uint8_t hash[BLAKE2S_OUTBYTES]; + blake2s_state S; + uint8_t * p = buf; + size_t mlen = i; + int err = 0; + + if( (err = blake2s_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) { + goto fail; + } + + while (mlen >= step) { + if ( (err = blake2s_update(&S, p, step)) < 0 ) { + goto fail; + } + mlen -= step; + p += step; + } + if ( (err = blake2s_update(&S, p, mlen)) < 0) { + goto fail; + } + if ( (err = blake2s_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) { + goto fail; + } + + if (0 != memcmp(hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES)) { + goto fail; + } + } + } + + puts( "ok" ); + return 0; +fail: + puts("error"); + return -1; +} +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_blake2sp_ref.c b/dependencies/libarchive-3.4.2/libarchive/archive_blake2sp_ref.c new file mode 100644 index 0000000..aef1010 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_blake2sp_ref.c @@ -0,0 +1,359 @@ +/* + BLAKE2 reference source code package - reference C implementations + + Copyright 2012, Samuel Neves . You may use this under the + terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at + your option. The terms of these licenses can be found at: + + - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + - OpenSSL license : https://www.openssl.org/source/license.html + - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + + More information about the BLAKE2 hash function can be found at + https://blake2.net. +*/ + +#include +#include +#include + +#if defined(_OPENMP) +#include +#endif + +#include "archive_blake2.h" +#include "archive_blake2_impl.h" + +#define PARALLELISM_DEGREE 8 + +/* + blake2sp_init_param defaults to setting the expecting output length + from the digest_length parameter block field. + + In some cases, however, we do not want this, as the output length + of these instances is given by inner_length instead. +*/ +static int blake2sp_init_leaf_param( blake2s_state *S, const blake2s_param *P ) +{ + int err = blake2s_init_param(S, P); + S->outlen = P->inner_length; + return err; +} + +static int blake2sp_init_leaf( blake2s_state *S, size_t outlen, size_t keylen, uint32_t offset ) +{ + blake2s_param P[1]; + P->digest_length = (uint8_t)outlen; + P->key_length = (uint8_t)keylen; + P->fanout = PARALLELISM_DEGREE; + P->depth = 2; + store32( &P->leaf_length, 0 ); + store32( &P->node_offset, offset ); + store16( &P->xof_length, 0 ); + P->node_depth = 0; + P->inner_length = BLAKE2S_OUTBYTES; + memset( P->salt, 0, sizeof( P->salt ) ); + memset( P->personal, 0, sizeof( P->personal ) ); + return blake2sp_init_leaf_param( S, P ); +} + +static int blake2sp_init_root( blake2s_state *S, size_t outlen, size_t keylen ) +{ + blake2s_param P[1]; + P->digest_length = (uint8_t)outlen; + P->key_length = (uint8_t)keylen; + P->fanout = PARALLELISM_DEGREE; + P->depth = 2; + store32( &P->leaf_length, 0 ); + store32( &P->node_offset, 0 ); + store16( &P->xof_length, 0 ); + P->node_depth = 1; + P->inner_length = BLAKE2S_OUTBYTES; + memset( P->salt, 0, sizeof( P->salt ) ); + memset( P->personal, 0, sizeof( P->personal ) ); + return blake2s_init_param( S, P ); +} + + +int blake2sp_init( blake2sp_state *S, size_t outlen ) +{ + size_t i; + + if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1; + + memset( S->buf, 0, sizeof( S->buf ) ); + S->buflen = 0; + S->outlen = outlen; + + if( blake2sp_init_root( S->R, outlen, 0 ) < 0 ) + return -1; + + for( i = 0; i < PARALLELISM_DEGREE; ++i ) + if( blake2sp_init_leaf( S->S[i], outlen, 0, (uint32_t)i ) < 0 ) return -1; + + S->R->last_node = 1; + S->S[PARALLELISM_DEGREE - 1]->last_node = 1; + return 0; +} + +int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen ) +{ + size_t i; + + if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1; + + if( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1; + + memset( S->buf, 0, sizeof( S->buf ) ); + S->buflen = 0; + S->outlen = outlen; + + if( blake2sp_init_root( S->R, outlen, keylen ) < 0 ) + return -1; + + for( i = 0; i < PARALLELISM_DEGREE; ++i ) + if( blake2sp_init_leaf( S->S[i], outlen, keylen, (uint32_t)i ) < 0 ) return -1; + + S->R->last_node = 1; + S->S[PARALLELISM_DEGREE - 1]->last_node = 1; + { + uint8_t block[BLAKE2S_BLOCKBYTES]; + memset( block, 0, BLAKE2S_BLOCKBYTES ); + memcpy( block, key, keylen ); + + for( i = 0; i < PARALLELISM_DEGREE; ++i ) + blake2s_update( S->S[i], block, BLAKE2S_BLOCKBYTES ); + + secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */ + } + return 0; +} + + +int blake2sp_update( blake2sp_state *S, const void *pin, size_t inlen ) +{ + const unsigned char * in = (const unsigned char *)pin; + size_t left = S->buflen; + size_t fill = sizeof( S->buf ) - left; + size_t i; + + if( left && inlen >= fill ) + { + memcpy( S->buf + left, in, fill ); + + for( i = 0; i < PARALLELISM_DEGREE; ++i ) + blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES ); + + in += fill; + inlen -= fill; + left = 0; + } + +#if defined(_OPENMP) + #pragma omp parallel shared(S), num_threads(PARALLELISM_DEGREE) +#else + for( i = 0; i < PARALLELISM_DEGREE; ++i ) +#endif + { +#if defined(_OPENMP) + size_t i = omp_get_thread_num(); +#endif + size_t inlen__ = inlen; + const unsigned char *in__ = ( const unsigned char * )in; + in__ += i * BLAKE2S_BLOCKBYTES; + + while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES ) + { + blake2s_update( S->S[i], in__, BLAKE2S_BLOCKBYTES ); + in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES; + inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES; + } + } + + in += inlen - inlen % ( PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES ); + inlen %= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES; + + if( inlen > 0 ) + memcpy( S->buf + left, in, inlen ); + + S->buflen = left + inlen; + return 0; +} + + +int blake2sp_final( blake2sp_state *S, void *out, size_t outlen ) +{ + uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES]; + size_t i; + + if(out == NULL || outlen < S->outlen) { + return -1; + } + + for( i = 0; i < PARALLELISM_DEGREE; ++i ) + { + if( S->buflen > i * BLAKE2S_BLOCKBYTES ) + { + size_t left = S->buflen - i * BLAKE2S_BLOCKBYTES; + + if( left > BLAKE2S_BLOCKBYTES ) left = BLAKE2S_BLOCKBYTES; + + blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, left ); + } + + blake2s_final( S->S[i], hash[i], BLAKE2S_OUTBYTES ); + } + + for( i = 0; i < PARALLELISM_DEGREE; ++i ) + blake2s_update( S->R, hash[i], BLAKE2S_OUTBYTES ); + + return blake2s_final( S->R, out, S->outlen ); +} + + +int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) +{ + uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES]; + blake2s_state S[PARALLELISM_DEGREE][1]; + blake2s_state FS[1]; + size_t i; + + /* Verify parameters */ + if ( NULL == in && inlen > 0 ) return -1; + + if ( NULL == out ) return -1; + + if ( NULL == key && keylen > 0) return -1; + + if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1; + + if( keylen > BLAKE2S_KEYBYTES ) return -1; + + for( i = 0; i < PARALLELISM_DEGREE; ++i ) + if( blake2sp_init_leaf( S[i], outlen, keylen, (uint32_t)i ) < 0 ) return -1; + + S[PARALLELISM_DEGREE - 1]->last_node = 1; /* mark last node */ + + if( keylen > 0 ) + { + uint8_t block[BLAKE2S_BLOCKBYTES]; + memset( block, 0, BLAKE2S_BLOCKBYTES ); + memcpy( block, key, keylen ); + + for( i = 0; i < PARALLELISM_DEGREE; ++i ) + blake2s_update( S[i], block, BLAKE2S_BLOCKBYTES ); + + secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */ + } + +#if defined(_OPENMP) + #pragma omp parallel shared(S,hash), num_threads(PARALLELISM_DEGREE) +#else + + for( i = 0; i < PARALLELISM_DEGREE; ++i ) +#endif + { +#if defined(_OPENMP) + size_t i = omp_get_thread_num(); +#endif + size_t inlen__ = inlen; + const unsigned char *in__ = ( const unsigned char * )in; + in__ += i * BLAKE2S_BLOCKBYTES; + + while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES ) + { + blake2s_update( S[i], in__, BLAKE2S_BLOCKBYTES ); + in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES; + inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES; + } + + if( inlen__ > i * BLAKE2S_BLOCKBYTES ) + { + const size_t left = inlen__ - i * BLAKE2S_BLOCKBYTES; + const size_t len = left <= BLAKE2S_BLOCKBYTES ? left : BLAKE2S_BLOCKBYTES; + blake2s_update( S[i], in__, len ); + } + + blake2s_final( S[i], hash[i], BLAKE2S_OUTBYTES ); + } + + if( blake2sp_init_root( FS, outlen, keylen ) < 0 ) + return -1; + + FS->last_node = 1; + + for( i = 0; i < PARALLELISM_DEGREE; ++i ) + blake2s_update( FS, hash[i], BLAKE2S_OUTBYTES ); + + return blake2s_final( FS, out, outlen ); +} + + + +#if defined(BLAKE2SP_SELFTEST) +#include +#include "blake2-kat.h" +int main( void ) +{ + uint8_t key[BLAKE2S_KEYBYTES]; + uint8_t buf[BLAKE2_KAT_LENGTH]; + size_t i, step; + + for( i = 0; i < BLAKE2S_KEYBYTES; ++i ) + key[i] = ( uint8_t )i; + + for( i = 0; i < BLAKE2_KAT_LENGTH; ++i ) + buf[i] = ( uint8_t )i; + + /* Test simple API */ + for( i = 0; i < BLAKE2_KAT_LENGTH; ++i ) + { + uint8_t hash[BLAKE2S_OUTBYTES]; + blake2sp( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES ); + + if( 0 != memcmp( hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES ) ) + { + goto fail; + } + } + + /* Test streaming API */ + for(step = 1; step < BLAKE2S_BLOCKBYTES; ++step) { + for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) { + uint8_t hash[BLAKE2S_OUTBYTES]; + blake2sp_state S; + uint8_t * p = buf; + size_t mlen = i; + int err = 0; + + if( (err = blake2sp_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) { + goto fail; + } + + while (mlen >= step) { + if ( (err = blake2sp_update(&S, p, step)) < 0 ) { + goto fail; + } + mlen -= step; + p += step; + } + if ( (err = blake2sp_update(&S, p, mlen)) < 0) { + goto fail; + } + if ( (err = blake2sp_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) { + goto fail; + } + + if (0 != memcmp(hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES)) { + goto fail; + } + } + } + + puts( "ok" ); + return 0; +fail: + puts("error"); + return -1; +} +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_check_magic.c b/dependencies/libarchive-3.4.2/libarchive/archive_check_magic.c new file mode 100644 index 0000000..288ce23 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_check_magic.c @@ -0,0 +1,175 @@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_check_magic.c 201089 2009-12-28 02:20:23Z kientzle $"); + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#if defined(_WIN32) && !defined(__CYGWIN__) +#include +#include +#endif + +#include "archive_private.h" + +static void +errmsg(const char *m) +{ + size_t s = strlen(m); + ssize_t written; + + while (s > 0) { + written = write(2, m, strlen(m)); + if (written <= 0) + return; + m += written; + s -= written; + } +} + +static __LA_DEAD void +diediedie(void) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG) + /* Cause a breakpoint exception */ + DebugBreak(); +#endif + abort(); /* Terminate the program abnormally. */ +} + +static const char * +state_name(unsigned s) +{ + switch (s) { + case ARCHIVE_STATE_NEW: return ("new"); + case ARCHIVE_STATE_HEADER: return ("header"); + case ARCHIVE_STATE_DATA: return ("data"); + case ARCHIVE_STATE_EOF: return ("eof"); + case ARCHIVE_STATE_CLOSED: return ("closed"); + case ARCHIVE_STATE_FATAL: return ("fatal"); + default: return ("??"); + } +} + +static const char * +archive_handle_type_name(unsigned m) +{ + switch (m) { + case ARCHIVE_WRITE_MAGIC: return ("archive_write"); + case ARCHIVE_READ_MAGIC: return ("archive_read"); + case ARCHIVE_WRITE_DISK_MAGIC: return ("archive_write_disk"); + case ARCHIVE_READ_DISK_MAGIC: return ("archive_read_disk"); + case ARCHIVE_MATCH_MAGIC: return ("archive_match"); + default: return NULL; + } +} + + +static char * +write_all_states(char *buff, unsigned int states) +{ + unsigned int lowbit; + + buff[0] = '\0'; + + /* A trick for computing the lowest set bit. */ + while ((lowbit = states & (1 + ~states)) != 0) { + states &= ~lowbit; /* Clear the low bit. */ + strcat(buff, state_name(lowbit)); + if (states != 0) + strcat(buff, "/"); + } + return buff; +} + +/* + * Check magic value and current state. + * Magic value mismatches are fatal and result in calls to abort(). + * State mismatches return ARCHIVE_FATAL. + * Otherwise, returns ARCHIVE_OK. + * + * This is designed to catch serious programming errors that violate + * the libarchive API. + */ +int +__archive_check_magic(struct archive *a, unsigned int magic, + unsigned int state, const char *function) +{ + char states1[64]; + char states2[64]; + const char *handle_type; + + /* + * If this isn't some form of archive handle, + * then the library user has screwed up so bad that + * we don't even have a reliable way to report an error. + */ + handle_type = archive_handle_type_name(a->magic); + + if (!handle_type) { + errmsg("PROGRAMMER ERROR: Function "); + errmsg(function); + errmsg(" invoked with invalid archive handle.\n"); + diediedie(); + } + + if (a->magic != magic) { + archive_set_error(a, -1, + "PROGRAMMER ERROR: Function '%s' invoked" + " on '%s' archive object, which is not supported.", + function, + handle_type); + a->state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } + + if ((a->state & state) == 0) { + /* If we're already FATAL, don't overwrite the error. */ + if (a->state != ARCHIVE_STATE_FATAL) + archive_set_error(a, -1, + "INTERNAL ERROR: Function '%s' invoked with" + " archive structure in state '%s'," + " should be in state '%s'", + function, + write_all_states(states1, a->state), + write_all_states(states2, state)); + a->state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } + return ARCHIVE_OK; +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_cmdline.c b/dependencies/libarchive-3.4.2/libarchive/archive_cmdline.c new file mode 100644 index 0000000..5c519cd --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_cmdline.c @@ -0,0 +1,227 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STDLIB_H +# include +#endif + +#include "archive.h" +#include "archive_cmdline_private.h" +#include "archive_string.h" + +static int cmdline_set_path(struct archive_cmdline *, const char *); +static int cmdline_add_arg(struct archive_cmdline *, const char *); + +static ssize_t +extract_quotation(struct archive_string *as, const char *p) +{ + const char *s; + + for (s = p + 1; *s;) { + if (*s == '\\') { + if (s[1] != '\0') { + archive_strappend_char(as, s[1]); + s += 2; + } else + s++; + } else if (*s == '"') + break; + else { + archive_strappend_char(as, s[0]); + s++; + } + } + if (*s != '"') + return (ARCHIVE_FAILED);/* Invalid sequence. */ + return ((ssize_t)(s + 1 - p)); +} + +static ssize_t +get_argument(struct archive_string *as, const char *p) +{ + const char *s = p; + + archive_string_empty(as); + + /* Skip beginning space characters. */ + while (*s != '\0' && *s == ' ') + s++; + /* Copy non-space characters. */ + while (*s != '\0' && *s != ' ') { + if (*s == '\\') { + if (s[1] != '\0') { + archive_strappend_char(as, s[1]); + s += 2; + } else { + s++;/* Ignore this character.*/ + break; + } + } else if (*s == '"') { + ssize_t q = extract_quotation(as, s); + if (q < 0) + return (ARCHIVE_FAILED);/* Invalid sequence. */ + s += q; + } else { + archive_strappend_char(as, s[0]); + s++; + } + } + return ((ssize_t)(s - p)); +} + +/* + * Set up command line arguments. + * Returns ARCHIVE_OK if everything okey. + * Returns ARCHIVE_FAILED if there is a lack of the `"' terminator or an + * empty command line. + * Returns ARCHIVE_FATAL if no memory. + */ +int +__archive_cmdline_parse(struct archive_cmdline *data, const char *cmd) +{ + struct archive_string as; + const char *p; + ssize_t al; + int r; + + archive_string_init(&as); + + /* Get first argument as a command path. */ + al = get_argument(&as, cmd); + if (al < 0) { + r = ARCHIVE_FAILED;/* Invalid sequence. */ + goto exit_function; + } + if (archive_strlen(&as) == 0) { + r = ARCHIVE_FAILED;/* An empty command path. */ + goto exit_function; + } + r = cmdline_set_path(data, as.s); + if (r != ARCHIVE_OK) + goto exit_function; + p = strrchr(as.s, '/'); + if (p == NULL) + p = as.s; + else + p++; + r = cmdline_add_arg(data, p); + if (r != ARCHIVE_OK) + goto exit_function; + cmd += al; + + for (;;) { + al = get_argument(&as, cmd); + if (al < 0) { + r = ARCHIVE_FAILED;/* Invalid sequence. */ + goto exit_function; + } + if (al == 0) + break; + cmd += al; + if (archive_strlen(&as) == 0 && *cmd == '\0') + break; + r = cmdline_add_arg(data, as.s); + if (r != ARCHIVE_OK) + goto exit_function; + } + r = ARCHIVE_OK; +exit_function: + archive_string_free(&as); + return (r); +} + +/* + * Set the program path. + */ +static int +cmdline_set_path(struct archive_cmdline *data, const char *path) +{ + char *newptr; + + newptr = realloc(data->path, strlen(path) + 1); + if (newptr == NULL) + return (ARCHIVE_FATAL); + data->path = newptr; + strcpy(data->path, path); + return (ARCHIVE_OK); +} + +/* + * Add a argument for the program. + */ +static int +cmdline_add_arg(struct archive_cmdline *data, const char *arg) +{ + char **newargv; + + if (data->path == NULL) + return (ARCHIVE_FAILED); + + newargv = realloc(data->argv, (data->argc + 2) * sizeof(char *)); + if (newargv == NULL) + return (ARCHIVE_FATAL); + data->argv = newargv; + data->argv[data->argc] = strdup(arg); + if (data->argv[data->argc] == NULL) + return (ARCHIVE_FATAL); + /* Set the terminator of argv. */ + data->argv[++data->argc] = NULL; + return (ARCHIVE_OK); +} + +struct archive_cmdline * +__archive_cmdline_allocate(void) +{ + return (struct archive_cmdline *) + calloc(1, sizeof(struct archive_cmdline)); +} + +/* + * Release the resources. + */ +int +__archive_cmdline_free(struct archive_cmdline *data) +{ + + if (data) { + free(data->path); + if (data->argv != NULL) { + int i; + for (i = 0; data->argv[i] != NULL; i++) + free(data->argv[i]); + free(data->argv); + } + free(data); + } + return (ARCHIVE_OK); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_cmdline_private.h b/dependencies/libarchive-3.4.2/libarchive/archive_cmdline_private.h new file mode 100644 index 0000000..57a1949 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_cmdline_private.h @@ -0,0 +1,47 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef ARCHIVE_CMDLINE_PRIVATE_H +#define ARCHIVE_CMDLINE_PRIVATE_H + +#ifndef __LIBARCHIVE_BUILD +#ifndef __LIBARCHIVE_TEST +#error This header is only to be used internally to libarchive. +#endif +#endif + +struct archive_cmdline { + char *path; + char **argv; + int argc; +}; + +struct archive_cmdline *__archive_cmdline_allocate(void); +int __archive_cmdline_parse(struct archive_cmdline *, const char *); +int __archive_cmdline_free(struct archive_cmdline *); + +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_crc32.h b/dependencies/libarchive-3.4.2/libarchive/archive_crc32.h new file mode 100644 index 0000000..4f1aed3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_crc32.h @@ -0,0 +1,83 @@ +/*- + * Copyright (c) 2009 Joerg Sonnenberger + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: head/lib/libarchive/archive_crc32.h 201102 2009-12-28 03:11:36Z kientzle $ + */ + +#ifndef ARCHIVE_CRC32_H +#define ARCHIVE_CRC32_H + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif + +/* + * When zlib is unavailable, we should still be able to validate + * uncompressed zip archives. That requires us to be able to compute + * the CRC32 check value. This is a drop-in compatible replacement + * for crc32() from zlib. It's slower than the zlib implementation, + * but still pretty fast: This runs about 300MB/s on my 3GHz P4 + * compared to about 800MB/s for the zlib implementation. + */ +static unsigned long +crc32(unsigned long crc, const void *_p, size_t len) +{ + unsigned long crc2, b, i; + const unsigned char *p = _p; + static volatile int crc_tbl_inited = 0; + static unsigned long crc_tbl[256]; + + if (!crc_tbl_inited) { + for (b = 0; b < 256; ++b) { + crc2 = b; + for (i = 8; i > 0; --i) { + if (crc2 & 1) + crc2 = (crc2 >> 1) ^ 0xedb88320UL; + else + crc2 = (crc2 >> 1); + } + crc_tbl[b] = crc2; + } + crc_tbl_inited = 1; + } + + crc = crc ^ 0xffffffffUL; + /* A use of this loop is about 20% - 30% faster than + * no use version in any optimization option of gcc. */ + for (;len >= 8; len -= 8) { + crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8); + crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8); + crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8); + crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8); + crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8); + crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8); + crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8); + crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8); + } + while (len--) + crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8); + return (crc ^ 0xffffffffUL); +} + +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_cryptor.c b/dependencies/libarchive-3.4.2/libarchive/archive_cryptor.c new file mode 100644 index 0000000..8ab2b09 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_cryptor.c @@ -0,0 +1,519 @@ +/*- +* Copyright (c) 2014 Michihiro NAKAJIMA +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "archive_platform.h" + +#ifdef HAVE_STRING_H +#include +#endif +#include "archive.h" +#include "archive_cryptor_private.h" + +/* + * On systems that do not support any recognized crypto libraries, + * this file will normally define no usable symbols. + * + * But some compilers and linkers choke on empty object files, so + * define a public symbol that will always exist. This could + * be removed someday if this file gains another always-present + * symbol definition. + */ +int __libarchive_cryptor_build_hack(void) { + return 0; +} + +#ifdef ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto + +static int +pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt, + size_t salt_len, unsigned rounds, uint8_t *derived_key, + size_t derived_key_len) +{ + CCKeyDerivationPBKDF(kCCPBKDF2, (const char *)pw, + pw_len, salt, salt_len, kCCPRFHmacAlgSHA1, rounds, + derived_key, derived_key_len); + return 0; +} + +#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) +#ifdef _MSC_VER +#pragma comment(lib, "Bcrypt.lib") +#endif + +static int +pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt, + size_t salt_len, unsigned rounds, uint8_t *derived_key, + size_t derived_key_len) +{ + NTSTATUS status; + BCRYPT_ALG_HANDLE hAlg; + + status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA1_ALGORITHM, + MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG); + if (!BCRYPT_SUCCESS(status)) + return -1; + + status = BCryptDeriveKeyPBKDF2(hAlg, + (PUCHAR)(uintptr_t)pw, (ULONG)pw_len, + (PUCHAR)(uintptr_t)salt, (ULONG)salt_len, rounds, + (PUCHAR)derived_key, (ULONG)derived_key_len, 0); + + BCryptCloseAlgorithmProvider(hAlg, 0); + + return (BCRYPT_SUCCESS(status)) ? 0: -1; +} + +#elif defined(HAVE_LIBMBEDCRYPTO) && defined(HAVE_MBEDTLS_PKCS5_H) + +static int +pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt, + size_t salt_len, unsigned rounds, uint8_t *derived_key, + size_t derived_key_len) +{ + mbedtls_md_context_t ctx; + const mbedtls_md_info_t *info; + int ret; + + mbedtls_md_init(&ctx); + info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); + if (info == NULL) { + mbedtls_md_free(&ctx); + return (-1); + } + ret = mbedtls_md_setup(&ctx, info, 1); + if (ret != 0) { + mbedtls_md_free(&ctx); + return (-1); + } + ret = mbedtls_pkcs5_pbkdf2_hmac(&ctx, (const unsigned char *)pw, + pw_len, salt, salt_len, rounds, derived_key_len, derived_key); + + mbedtls_md_free(&ctx); + return (ret); +} + +#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_PBKDF2_H) + +static int +pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt, + size_t salt_len, unsigned rounds, uint8_t *derived_key, + size_t derived_key_len) { + pbkdf2_hmac_sha1((unsigned)pw_len, (const uint8_t *)pw, rounds, + salt_len, salt, derived_key_len, derived_key); + return 0; +} + +#elif defined(HAVE_LIBCRYPTO) && defined(HAVE_PKCS5_PBKDF2_HMAC_SHA1) + +static int +pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt, + size_t salt_len, unsigned rounds, uint8_t *derived_key, + size_t derived_key_len) { + + PKCS5_PBKDF2_HMAC_SHA1(pw, pw_len, salt, salt_len, rounds, + derived_key_len, derived_key); + return 0; +} + +#else + +/* Stub */ +static int +pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt, + size_t salt_len, unsigned rounds, uint8_t *derived_key, + size_t derived_key_len) { + (void)pw; /* UNUSED */ + (void)pw_len; /* UNUSED */ + (void)salt; /* UNUSED */ + (void)salt_len; /* UNUSED */ + (void)rounds; /* UNUSED */ + (void)derived_key; /* UNUSED */ + (void)derived_key_len; /* UNUSED */ + return -1; /* UNSUPPORTED */ +} + +#endif + +#ifdef ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto +# if MAC_OS_X_VERSION_MAX_ALLOWED < 1090 +# define kCCAlgorithmAES kCCAlgorithmAES128 +# endif + +static int +aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len) +{ + CCCryptorStatus r; + + ctx->key_len = key_len; + memcpy(ctx->key, key, key_len); + memset(ctx->nonce, 0, sizeof(ctx->nonce)); + ctx->encr_pos = AES_BLOCK_SIZE; + r = CCCryptorCreateWithMode(kCCEncrypt, kCCModeECB, kCCAlgorithmAES, + ccNoPadding, NULL, key, key_len, NULL, 0, 0, 0, &ctx->ctx); + return (r == kCCSuccess)? 0: -1; +} + +static int +aes_ctr_encrypt_counter(archive_crypto_ctx *ctx) +{ + CCCryptorRef ref = ctx->ctx; + CCCryptorStatus r; + + r = CCCryptorReset(ref, NULL); + if (r != kCCSuccess && r != kCCUnimplemented) + return -1; + r = CCCryptorUpdate(ref, ctx->nonce, AES_BLOCK_SIZE, ctx->encr_buf, + AES_BLOCK_SIZE, NULL); + return (r == kCCSuccess)? 0: -1; +} + +static int +aes_ctr_release(archive_crypto_ctx *ctx) +{ + memset(ctx->key, 0, ctx->key_len); + memset(ctx->nonce, 0, sizeof(ctx->nonce)); + return 0; +} + +#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) + +static int +aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len) +{ + BCRYPT_ALG_HANDLE hAlg; + BCRYPT_KEY_HANDLE hKey; + DWORD keyObj_len, aes_key_len; + PBYTE keyObj; + ULONG result; + NTSTATUS status; + BCRYPT_KEY_LENGTHS_STRUCT key_lengths; + + ctx->hAlg = NULL; + ctx->hKey = NULL; + ctx->keyObj = NULL; + switch (key_len) { + case 16: aes_key_len = 128; break; + case 24: aes_key_len = 192; break; + case 32: aes_key_len = 256; break; + default: return -1; + } + status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_AES_ALGORITHM, + MS_PRIMITIVE_PROVIDER, 0); + if (!BCRYPT_SUCCESS(status)) + return -1; + status = BCryptGetProperty(hAlg, BCRYPT_KEY_LENGTHS, (PUCHAR)&key_lengths, + sizeof(key_lengths), &result, 0); + if (!BCRYPT_SUCCESS(status)) { + BCryptCloseAlgorithmProvider(hAlg, 0); + return -1; + } + if (key_lengths.dwMinLength > aes_key_len + || key_lengths.dwMaxLength < aes_key_len) { + BCryptCloseAlgorithmProvider(hAlg, 0); + return -1; + } + status = BCryptGetProperty(hAlg, BCRYPT_OBJECT_LENGTH, (PUCHAR)&keyObj_len, + sizeof(keyObj_len), &result, 0); + if (!BCRYPT_SUCCESS(status)) { + BCryptCloseAlgorithmProvider(hAlg, 0); + return -1; + } + keyObj = (PBYTE)HeapAlloc(GetProcessHeap(), 0, keyObj_len); + if (keyObj == NULL) { + BCryptCloseAlgorithmProvider(hAlg, 0); + return -1; + } + status = BCryptSetProperty(hAlg, BCRYPT_CHAINING_MODE, + (PUCHAR)BCRYPT_CHAIN_MODE_ECB, sizeof(BCRYPT_CHAIN_MODE_ECB), 0); + if (!BCRYPT_SUCCESS(status)) { + BCryptCloseAlgorithmProvider(hAlg, 0); + HeapFree(GetProcessHeap(), 0, keyObj); + return -1; + } + status = BCryptGenerateSymmetricKey(hAlg, &hKey, + keyObj, keyObj_len, + (PUCHAR)(uintptr_t)key, (ULONG)key_len, 0); + if (!BCRYPT_SUCCESS(status)) { + BCryptCloseAlgorithmProvider(hAlg, 0); + HeapFree(GetProcessHeap(), 0, keyObj); + return -1; + } + + ctx->hAlg = hAlg; + ctx->hKey = hKey; + ctx->keyObj = keyObj; + ctx->keyObj_len = keyObj_len; + ctx->encr_pos = AES_BLOCK_SIZE; + + return 0; +} + +static int +aes_ctr_encrypt_counter(archive_crypto_ctx *ctx) +{ + NTSTATUS status; + ULONG result; + + status = BCryptEncrypt(ctx->hKey, (PUCHAR)ctx->nonce, AES_BLOCK_SIZE, + NULL, NULL, 0, (PUCHAR)ctx->encr_buf, AES_BLOCK_SIZE, + &result, 0); + return BCRYPT_SUCCESS(status) ? 0 : -1; +} + +static int +aes_ctr_release(archive_crypto_ctx *ctx) +{ + + if (ctx->hAlg != NULL) { + BCryptCloseAlgorithmProvider(ctx->hAlg, 0); + ctx->hAlg = NULL; + BCryptDestroyKey(ctx->hKey); + ctx->hKey = NULL; + HeapFree(GetProcessHeap(), 0, ctx->keyObj); + ctx->keyObj = NULL; + } + memset(ctx, 0, sizeof(*ctx)); + return 0; +} + +#elif defined(HAVE_LIBMBEDCRYPTO) && defined(HAVE_MBEDTLS_AES_H) + +static int +aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len) +{ + mbedtls_aes_init(&ctx->ctx); + ctx->key_len = key_len; + memcpy(ctx->key, key, key_len); + memset(ctx->nonce, 0, sizeof(ctx->nonce)); + ctx->encr_pos = AES_BLOCK_SIZE; + return 0; +} + +static int +aes_ctr_encrypt_counter(archive_crypto_ctx *ctx) +{ + if (mbedtls_aes_setkey_enc(&ctx->ctx, ctx->key, + ctx->key_len * 8) != 0) + return (-1); + if (mbedtls_aes_crypt_ecb(&ctx->ctx, MBEDTLS_AES_ENCRYPT, ctx->nonce, + ctx->encr_buf) != 0) + return (-1); + return 0; +} + +static int +aes_ctr_release(archive_crypto_ctx *ctx) +{ + mbedtls_aes_free(&ctx->ctx); + memset(ctx, 0, sizeof(*ctx)); + return 0; +} + +#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_AES_H) + +static int +aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len) +{ + ctx->key_len = key_len; + memcpy(ctx->key, key, key_len); + memset(ctx->nonce, 0, sizeof(ctx->nonce)); + ctx->encr_pos = AES_BLOCK_SIZE; + memset(&ctx->ctx, 0, sizeof(ctx->ctx)); + return 0; +} + +static int +aes_ctr_encrypt_counter(archive_crypto_ctx *ctx) +{ + aes_set_encrypt_key(&ctx->ctx, ctx->key_len, ctx->key); + aes_encrypt(&ctx->ctx, AES_BLOCK_SIZE, ctx->encr_buf, ctx->nonce); + return 0; +} + +static int +aes_ctr_release(archive_crypto_ctx *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + return 0; +} + +#elif defined(HAVE_LIBCRYPTO) + +static int +aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len) +{ + if ((ctx->ctx = EVP_CIPHER_CTX_new()) == NULL) + return -1; + + switch (key_len) { + case 16: ctx->type = EVP_aes_128_ecb(); break; + case 24: ctx->type = EVP_aes_192_ecb(); break; + case 32: ctx->type = EVP_aes_256_ecb(); break; + default: ctx->type = NULL; return -1; + } + + ctx->key_len = key_len; + memcpy(ctx->key, key, key_len); + memset(ctx->nonce, 0, sizeof(ctx->nonce)); + ctx->encr_pos = AES_BLOCK_SIZE; +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) + if (!EVP_CIPHER_CTX_reset(ctx->ctx)) { + EVP_CIPHER_CTX_free(ctx->ctx); + ctx->ctx = NULL; + } +#else + EVP_CIPHER_CTX_init(ctx->ctx); +#endif + return 0; +} + +static int +aes_ctr_encrypt_counter(archive_crypto_ctx *ctx) +{ + int outl = 0; + int r; + + r = EVP_EncryptInit_ex(ctx->ctx, ctx->type, NULL, ctx->key, NULL); + if (r == 0) + return -1; + r = EVP_EncryptUpdate(ctx->ctx, ctx->encr_buf, &outl, ctx->nonce, + AES_BLOCK_SIZE); + if (r == 0 || outl != AES_BLOCK_SIZE) + return -1; + return 0; +} + +static int +aes_ctr_release(archive_crypto_ctx *ctx) +{ + EVP_CIPHER_CTX_free(ctx->ctx); + memset(ctx->key, 0, ctx->key_len); + memset(ctx->nonce, 0, sizeof(ctx->nonce)); + return 0; +} + +#else + +#define ARCHIVE_CRYPTOR_STUB +/* Stub */ +static int +aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len) +{ + (void)ctx; /* UNUSED */ + (void)key; /* UNUSED */ + (void)key_len; /* UNUSED */ + return -1; +} + +static int +aes_ctr_encrypt_counter(archive_crypto_ctx *ctx) +{ + (void)ctx; /* UNUSED */ + return -1; +} + +static int +aes_ctr_release(archive_crypto_ctx *ctx) +{ + (void)ctx; /* UNUSED */ + return 0; +} + +#endif + +#ifdef ARCHIVE_CRYPTOR_STUB +static int +aes_ctr_update(archive_crypto_ctx *ctx, const uint8_t * const in, + size_t in_len, uint8_t * const out, size_t *out_len) +{ + (void)ctx; /* UNUSED */ + (void)in; /* UNUSED */ + (void)in_len; /* UNUSED */ + (void)out; /* UNUSED */ + (void)out_len; /* UNUSED */ + aes_ctr_encrypt_counter(ctx); /* UNUSED */ /* Fix unused function warning */ + return -1; +} + +#else +static void +aes_ctr_increase_counter(archive_crypto_ctx *ctx) +{ + uint8_t *const nonce = ctx->nonce; + int j; + + for (j = 0; j < 8; j++) { + if (++nonce[j]) + break; + } +} + +static int +aes_ctr_update(archive_crypto_ctx *ctx, const uint8_t * const in, + size_t in_len, uint8_t * const out, size_t *out_len) +{ + uint8_t *const ebuf = ctx->encr_buf; + unsigned pos = ctx->encr_pos; + unsigned max = (unsigned)((in_len < *out_len)? in_len: *out_len); + unsigned i; + + for (i = 0; i < max; ) { + if (pos == AES_BLOCK_SIZE) { + aes_ctr_increase_counter(ctx); + if (aes_ctr_encrypt_counter(ctx) != 0) + return -1; + while (max -i >= AES_BLOCK_SIZE) { + for (pos = 0; pos < AES_BLOCK_SIZE; pos++) + out[i+pos] = in[i+pos] ^ ebuf[pos]; + i += AES_BLOCK_SIZE; + aes_ctr_increase_counter(ctx); + if (aes_ctr_encrypt_counter(ctx) != 0) + return -1; + } + pos = 0; + if (i >= max) + break; + } + out[i] = in[i] ^ ebuf[pos++]; + i++; + } + ctx->encr_pos = pos; + *out_len = i; + + return 0; +} +#endif /* ARCHIVE_CRYPTOR_STUB */ + + +const struct archive_cryptor __archive_cryptor = +{ + &pbkdf2_sha1, + &aes_ctr_init, + &aes_ctr_update, + &aes_ctr_release, + &aes_ctr_init, + &aes_ctr_update, + &aes_ctr_release, +}; diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_cryptor_private.h b/dependencies/libarchive-3.4.2/libarchive/archive_cryptor_private.h new file mode 100644 index 0000000..64a2055 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_cryptor_private.h @@ -0,0 +1,179 @@ +/*- +* Copyright (c) 2014 Michihiro NAKAJIMA +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef ARCHIVE_CRYPTOR_PRIVATE_H_INCLUDED +#define ARCHIVE_CRYPTOR_PRIVATE_H_INCLUDED + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif +/* + * On systems that do not support any recognized crypto libraries, + * the archive_cryptor.c file will normally define no usable symbols. + * + * But some compilers and linkers choke on empty object files, so + * define a public symbol that will always exist. This could + * be removed someday if this file gains another always-present + * symbol definition. + */ +int __libarchive_cryptor_build_hack(void); + +#ifdef __APPLE__ +# include +# if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 +# define ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto +# endif +#endif + +#ifdef ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto +#include +#include +#define AES_BLOCK_SIZE 16 +#define AES_MAX_KEY_SIZE kCCKeySizeAES256 + +typedef struct { + CCCryptorRef ctx; + uint8_t key[AES_MAX_KEY_SIZE]; + unsigned key_len; + uint8_t nonce[AES_BLOCK_SIZE]; + uint8_t encr_buf[AES_BLOCK_SIZE]; + unsigned encr_pos; +} archive_crypto_ctx; + +#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) +#include + +/* Common in other bcrypt implementations, but missing from VS2008. */ +#ifndef BCRYPT_SUCCESS +#define BCRYPT_SUCCESS(r) ((NTSTATUS)(r) == STATUS_SUCCESS) +#endif + +#define AES_MAX_KEY_SIZE 32 +#define AES_BLOCK_SIZE 16 +typedef struct { + BCRYPT_ALG_HANDLE hAlg; + BCRYPT_KEY_HANDLE hKey; + PBYTE keyObj; + DWORD keyObj_len; + uint8_t nonce[AES_BLOCK_SIZE]; + uint8_t encr_buf[AES_BLOCK_SIZE]; + unsigned encr_pos; +} archive_crypto_ctx; + +#elif defined(HAVE_LIBMBEDCRYPTO) && defined(HAVE_MBEDTLS_AES_H) +#include +#include +#include + +#define AES_MAX_KEY_SIZE 32 +#define AES_BLOCK_SIZE 16 + +typedef struct { + mbedtls_aes_context ctx; + uint8_t key[AES_MAX_KEY_SIZE]; + unsigned key_len; + uint8_t nonce[AES_BLOCK_SIZE]; + uint8_t encr_buf[AES_BLOCK_SIZE]; + unsigned encr_pos; +} archive_crypto_ctx; + +#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_AES_H) +#if defined(HAVE_NETTLE_PBKDF2_H) +#include +#endif +#include + +typedef struct { + struct aes_ctx ctx; + uint8_t key[AES_MAX_KEY_SIZE]; + unsigned key_len; + uint8_t nonce[AES_BLOCK_SIZE]; + uint8_t encr_buf[AES_BLOCK_SIZE]; + unsigned encr_pos; +} archive_crypto_ctx; + +#elif defined(HAVE_LIBCRYPTO) +#include "archive_openssl_evp_private.h" +#define AES_BLOCK_SIZE 16 +#define AES_MAX_KEY_SIZE 32 + +typedef struct { + EVP_CIPHER_CTX *ctx; + const EVP_CIPHER *type; + uint8_t key[AES_MAX_KEY_SIZE]; + unsigned key_len; + uint8_t nonce[AES_BLOCK_SIZE]; + uint8_t encr_buf[AES_BLOCK_SIZE]; + unsigned encr_pos; +} archive_crypto_ctx; + +#else + +#define AES_BLOCK_SIZE 16 +#define AES_MAX_KEY_SIZE 32 +typedef int archive_crypto_ctx; + +#endif + +/* defines */ +#define archive_pbkdf2_sha1(pw, pw_len, salt, salt_len, rounds, dk, dk_len)\ + __archive_cryptor.pbkdf2sha1(pw, pw_len, salt, salt_len, rounds, dk, dk_len) + +#define archive_decrypto_aes_ctr_init(ctx, key, key_len) \ + __archive_cryptor.decrypto_aes_ctr_init(ctx, key, key_len) +#define archive_decrypto_aes_ctr_update(ctx, in, in_len, out, out_len) \ + __archive_cryptor.decrypto_aes_ctr_update(ctx, in, in_len, out, out_len) +#define archive_decrypto_aes_ctr_release(ctx) \ + __archive_cryptor.decrypto_aes_ctr_release(ctx) + +#define archive_encrypto_aes_ctr_init(ctx, key, key_len) \ + __archive_cryptor.encrypto_aes_ctr_init(ctx, key, key_len) +#define archive_encrypto_aes_ctr_update(ctx, in, in_len, out, out_len) \ + __archive_cryptor.encrypto_aes_ctr_update(ctx, in, in_len, out, out_len) +#define archive_encrypto_aes_ctr_release(ctx) \ + __archive_cryptor.encrypto_aes_ctr_release(ctx) + +/* Minimal interface to cryptographic functionality for internal use in + * libarchive */ +struct archive_cryptor +{ + /* PKCS5 PBKDF2 HMAC-SHA1 */ + int (*pbkdf2sha1)(const char *pw, size_t pw_len, const uint8_t *salt, + size_t salt_len, unsigned rounds, uint8_t *derived_key, + size_t derived_key_len); + /* AES CTR mode(little endian version) */ + int (*decrypto_aes_ctr_init)(archive_crypto_ctx *, const uint8_t *, size_t); + int (*decrypto_aes_ctr_update)(archive_crypto_ctx *, const uint8_t *, + size_t, uint8_t *, size_t *); + int (*decrypto_aes_ctr_release)(archive_crypto_ctx *); + int (*encrypto_aes_ctr_init)(archive_crypto_ctx *, const uint8_t *, size_t); + int (*encrypto_aes_ctr_update)(archive_crypto_ctx *, const uint8_t *, + size_t, uint8_t *, size_t *); + int (*encrypto_aes_ctr_release)(archive_crypto_ctx *); +}; + +extern const struct archive_cryptor __archive_cryptor; + +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_digest.c b/dependencies/libarchive-3.4.2/libarchive/archive_digest.c new file mode 100644 index 0000000..34c58ac --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_digest.c @@ -0,0 +1,1691 @@ +/*- +* Copyright (c) 2003-2007 Tim Kientzle +* Copyright (c) 2011 Andres Mejia +* Copyright (c) 2011 Michihiro NAKAJIMA +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "archive_platform.h" + +#include "archive.h" +#include "archive_digest_private.h" + +/* In particular, force the configure probe to break if it tries + * to test a combination of OpenSSL and libmd. */ +#if defined(ARCHIVE_CRYPTO_OPENSSL) && defined(ARCHIVE_CRYPTO_LIBMD) +#error Cannot use both OpenSSL and libmd. +#endif + +/* + * Message digest functions for Windows platform. + */ +#if defined(ARCHIVE_CRYPTO_MD5_WIN) ||\ + defined(ARCHIVE_CRYPTO_SHA1_WIN) ||\ + defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\ + defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\ + defined(ARCHIVE_CRYPTO_SHA512_WIN) + +/* + * Initialize a Message digest. + */ +static int +win_crypto_init(Digest_CTX *ctx, ALG_ID algId) +{ + + ctx->valid = 0; + if (!CryptAcquireContext(&ctx->cryptProv, NULL, NULL, + PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { + if (GetLastError() != (DWORD)NTE_BAD_KEYSET) + return (ARCHIVE_FAILED); + if (!CryptAcquireContext(&ctx->cryptProv, NULL, NULL, + PROV_RSA_FULL, CRYPT_NEWKEYSET)) + return (ARCHIVE_FAILED); + } + + if (!CryptCreateHash(ctx->cryptProv, algId, 0, 0, &ctx->hash)) { + CryptReleaseContext(ctx->cryptProv, 0); + return (ARCHIVE_FAILED); + } + + ctx->valid = 1; + return (ARCHIVE_OK); +} + +/* + * Update a Message digest. + */ +static int +win_crypto_Update(Digest_CTX *ctx, const unsigned char *buf, size_t len) +{ + + if (!ctx->valid) + return (ARCHIVE_FAILED); + + CryptHashData(ctx->hash, + (unsigned char *)(uintptr_t)buf, + (DWORD)len, 0); + return (ARCHIVE_OK); +} + +static int +win_crypto_Final(unsigned char *buf, size_t bufsize, Digest_CTX *ctx) +{ + DWORD siglen = (DWORD)bufsize; + + if (!ctx->valid) + return (ARCHIVE_FAILED); + + CryptGetHashParam(ctx->hash, HP_HASHVAL, buf, &siglen, 0); + CryptDestroyHash(ctx->hash); + CryptReleaseContext(ctx->cryptProv, 0); + ctx->valid = 0; + return (ARCHIVE_OK); +} + +#endif /* defined(ARCHIVE_CRYPTO_*_WIN) */ + + +/* MD5 implementations */ +#if defined(ARCHIVE_CRYPTO_MD5_LIBC) + +static int +__archive_libc_md5init(archive_md5_ctx *ctx) +{ + MD5Init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_libc_md5update(archive_md5_ctx *ctx, const void *indata, + size_t insize) +{ + MD5Update(ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_libc_md5final(archive_md5_ctx *ctx, void *md) +{ + MD5Final(md, ctx); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_MD5_LIBMD) + +static int +__archive_libmd_md5init(archive_md5_ctx *ctx) +{ + MD5Init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_libmd_md5update(archive_md5_ctx *ctx, const void *indata, + size_t insize) +{ + MD5Update(ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_libmd_md5final(archive_md5_ctx *ctx, void *md) +{ + MD5Final(md, ctx); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM) + +static int +__archive_libsystem_md5init(archive_md5_ctx *ctx) +{ + CC_MD5_Init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_libsystem_md5update(archive_md5_ctx *ctx, const void *indata, + size_t insize) +{ + CC_MD5_Update(ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_libsystem_md5final(archive_md5_ctx *ctx, void *md) +{ + CC_MD5_Final(md, ctx); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_MD5_MBEDTLS) + +static int +__archive_mbedtls_md5init(archive_md5_ctx *ctx) +{ + mbedtls_md5_init(ctx); + if (mbedtls_md5_starts_ret(ctx) == 0) + return (ARCHIVE_OK); + else + return (ARCHIVE_FATAL); +} + +static int +__archive_mbedtls_md5update(archive_md5_ctx *ctx, const void *indata, + size_t insize) +{ + if (mbedtls_md5_update_ret(ctx, indata, insize) == 0) + return (ARCHIVE_OK); + else + return (ARCHIVE_FATAL); +} + +static int +__archive_mbedtls_md5final(archive_md5_ctx *ctx, void *md) +{ + if (mbedtls_md5_finish_ret(ctx, md) == 0) { + mbedtls_md5_free(ctx); + return (ARCHIVE_OK); + } else { + mbedtls_md5_free(ctx); + return (ARCHIVE_FATAL); + } +} + +#elif defined(ARCHIVE_CRYPTO_MD5_NETTLE) + +static int +__archive_nettle_md5init(archive_md5_ctx *ctx) +{ + md5_init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_nettle_md5update(archive_md5_ctx *ctx, const void *indata, + size_t insize) +{ + md5_update(ctx, insize, indata); + return (ARCHIVE_OK); +} + +static int +__archive_nettle_md5final(archive_md5_ctx *ctx, void *md) +{ + md5_digest(ctx, MD5_DIGEST_SIZE, md); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_MD5_OPENSSL) + +static int +__archive_openssl_md5init(archive_md5_ctx *ctx) +{ + if ((*ctx = EVP_MD_CTX_new()) == NULL) + return (ARCHIVE_FAILED); + EVP_DigestInit(*ctx, EVP_md5()); + return (ARCHIVE_OK); +} + +static int +__archive_openssl_md5update(archive_md5_ctx *ctx, const void *indata, + size_t insize) +{ + EVP_DigestUpdate(*ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_openssl_md5final(archive_md5_ctx *ctx, void *md) +{ + /* HACK: archive_write_set_format_xar.c is finalizing empty contexts, so + * this is meant to cope with that. Real fix is probably to fix + * archive_write_set_format_xar.c + */ + if (*ctx) { + EVP_DigestFinal(*ctx, md, NULL); + EVP_MD_CTX_free(*ctx); + *ctx = NULL; + } + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_MD5_WIN) + +static int +__archive_windowsapi_md5init(archive_md5_ctx *ctx) +{ + return (win_crypto_init(ctx, CALG_MD5)); +} + +static int +__archive_windowsapi_md5update(archive_md5_ctx *ctx, const void *indata, + size_t insize) +{ + return (win_crypto_Update(ctx, indata, insize)); +} + +static int +__archive_windowsapi_md5final(archive_md5_ctx *ctx, void *md) +{ + return (win_crypto_Final(md, 16, ctx)); +} + +#else + +static int +__archive_stub_md5init(archive_md5_ctx *ctx) +{ + (void)ctx; /* UNUSED */ + return (ARCHIVE_FAILED); +} + +static int +__archive_stub_md5update(archive_md5_ctx *ctx, const void *indata, + size_t insize) +{ + (void)ctx; /* UNUSED */ + (void)indata; /* UNUSED */ + (void)insize; /* UNUSED */ + return (ARCHIVE_FAILED); +} + +static int +__archive_stub_md5final(archive_md5_ctx *ctx, void *md) +{ + (void)ctx; /* UNUSED */ + (void)md; /* UNUSED */ + return (ARCHIVE_FAILED); +} + +#endif + +/* RIPEMD160 implementations */ +#if defined(ARCHIVE_CRYPTO_RMD160_LIBC) + +static int +__archive_libc_ripemd160init(archive_rmd160_ctx *ctx) +{ + RMD160Init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_libc_ripemd160update(archive_rmd160_ctx *ctx, const void *indata, + size_t insize) +{ + RMD160Update(ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_libc_ripemd160final(archive_rmd160_ctx *ctx, void *md) +{ + RMD160Final(md, ctx); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_RMD160_LIBMD) + +static int +__archive_libmd_ripemd160init(archive_rmd160_ctx *ctx) +{ + RIPEMD160_Init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_libmd_ripemd160update(archive_rmd160_ctx *ctx, const void *indata, + size_t insize) +{ + RIPEMD160_Update(ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_libmd_ripemd160final(archive_rmd160_ctx *ctx, void *md) +{ + RIPEMD160_Final(md, ctx); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_RMD160_MBEDTLS) + +static int +__archive_mbedtls_ripemd160init(archive_rmd160_ctx *ctx) +{ + mbedtls_ripemd160_init(ctx); + if (mbedtls_ripemd160_starts_ret(ctx) == 0) + return (ARCHIVE_OK); + else + return (ARCHIVE_FATAL); +} + +static int +__archive_mbedtls_ripemd160update(archive_rmd160_ctx *ctx, const void *indata, + size_t insize) +{ + if (mbedtls_ripemd160_update_ret(ctx, indata, insize) == 0) + return (ARCHIVE_OK); + else + return (ARCHIVE_FATAL); +} + +static int +__archive_mbedtls_ripemd160final(archive_rmd160_ctx *ctx, void *md) +{ + if (mbedtls_ripemd160_finish_ret(ctx, md) == 0) { + mbedtls_ripemd160_free(ctx); + return (ARCHIVE_OK); + } else { + mbedtls_ripemd160_free(ctx); + return (ARCHIVE_FATAL); + } +} + +#elif defined(ARCHIVE_CRYPTO_RMD160_NETTLE) + +static int +__archive_nettle_ripemd160init(archive_rmd160_ctx *ctx) +{ + ripemd160_init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_nettle_ripemd160update(archive_rmd160_ctx *ctx, const void *indata, + size_t insize) +{ + ripemd160_update(ctx, insize, indata); + return (ARCHIVE_OK); +} + +static int +__archive_nettle_ripemd160final(archive_rmd160_ctx *ctx, void *md) +{ + ripemd160_digest(ctx, RIPEMD160_DIGEST_SIZE, md); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_RMD160_OPENSSL) + +static int +__archive_openssl_ripemd160init(archive_rmd160_ctx *ctx) +{ + if ((*ctx = EVP_MD_CTX_new()) == NULL) + return (ARCHIVE_FAILED); + EVP_DigestInit(*ctx, EVP_ripemd160()); + return (ARCHIVE_OK); +} + +static int +__archive_openssl_ripemd160update(archive_rmd160_ctx *ctx, const void *indata, + size_t insize) +{ + EVP_DigestUpdate(*ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_openssl_ripemd160final(archive_rmd160_ctx *ctx, void *md) +{ + if (*ctx) { + EVP_DigestFinal(*ctx, md, NULL); + EVP_MD_CTX_free(*ctx); + *ctx = NULL; + } + return (ARCHIVE_OK); +} + +#else + +static int +__archive_stub_ripemd160init(archive_rmd160_ctx *ctx) +{ + (void)ctx; /* UNUSED */ + return (ARCHIVE_FAILED); +} + +static int +__archive_stub_ripemd160update(archive_rmd160_ctx *ctx, const void *indata, + size_t insize) +{ + (void)ctx; /* UNUSED */ + (void)indata; /* UNUSED */ + (void)insize; /* UNUSED */ + return (ARCHIVE_FAILED); +} + +static int +__archive_stub_ripemd160final(archive_rmd160_ctx *ctx, void *md) +{ + (void)ctx; /* UNUSED */ + (void)md; /* UNUSED */ + return (ARCHIVE_FAILED); +} + +#endif + +/* SHA1 implementations */ +#if defined(ARCHIVE_CRYPTO_SHA1_LIBC) + +static int +__archive_libc_sha1init(archive_sha1_ctx *ctx) +{ + SHA1Init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_libc_sha1update(archive_sha1_ctx *ctx, const void *indata, + size_t insize) +{ + SHA1Update(ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_libc_sha1final(archive_sha1_ctx *ctx, void *md) +{ + SHA1Final(md, ctx); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_SHA1_LIBMD) + +static int +__archive_libmd_sha1init(archive_sha1_ctx *ctx) +{ + SHA1_Init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_libmd_sha1update(archive_sha1_ctx *ctx, const void *indata, + size_t insize) +{ + SHA1_Update(ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_libmd_sha1final(archive_sha1_ctx *ctx, void *md) +{ + SHA1_Final(md, ctx); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM) + +static int +__archive_libsystem_sha1init(archive_sha1_ctx *ctx) +{ + CC_SHA1_Init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_libsystem_sha1update(archive_sha1_ctx *ctx, const void *indata, + size_t insize) +{ + CC_SHA1_Update(ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_libsystem_sha1final(archive_sha1_ctx *ctx, void *md) +{ + CC_SHA1_Final(md, ctx); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_SHA1_MBEDTLS) + +static int +__archive_mbedtls_sha1init(archive_sha1_ctx *ctx) +{ + mbedtls_sha1_init(ctx); + if (mbedtls_sha1_starts_ret(ctx) == 0) + return (ARCHIVE_OK); + else + return (ARCHIVE_FATAL); +} + +static int +__archive_mbedtls_sha1update(archive_sha1_ctx *ctx, const void *indata, + size_t insize) +{ + if (mbedtls_sha1_update_ret(ctx, indata, insize) == 0) + return (ARCHIVE_OK); + else + return (ARCHIVE_FATAL); +} + +static int +__archive_mbedtls_sha1final(archive_sha1_ctx *ctx, void *md) +{ + if (mbedtls_sha1_finish_ret(ctx, md) == 0) { + mbedtls_sha1_free(ctx); + return (ARCHIVE_OK); + } else { + mbedtls_sha1_free(ctx); + return (ARCHIVE_FATAL); + } +} + +#elif defined(ARCHIVE_CRYPTO_SHA1_NETTLE) + +static int +__archive_nettle_sha1init(archive_sha1_ctx *ctx) +{ + sha1_init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_nettle_sha1update(archive_sha1_ctx *ctx, const void *indata, + size_t insize) +{ + sha1_update(ctx, insize, indata); + return (ARCHIVE_OK); +} + +static int +__archive_nettle_sha1final(archive_sha1_ctx *ctx, void *md) +{ + sha1_digest(ctx, SHA1_DIGEST_SIZE, md); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_SHA1_OPENSSL) + +static int +__archive_openssl_sha1init(archive_sha1_ctx *ctx) +{ + if ((*ctx = EVP_MD_CTX_new()) == NULL) + return (ARCHIVE_FAILED); + EVP_DigestInit(*ctx, EVP_sha1()); + return (ARCHIVE_OK); +} + +static int +__archive_openssl_sha1update(archive_sha1_ctx *ctx, const void *indata, + size_t insize) +{ + EVP_DigestUpdate(*ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_openssl_sha1final(archive_sha1_ctx *ctx, void *md) +{ + /* HACK: archive_write_set_format_xar.c is finalizing empty contexts, so + * this is meant to cope with that. Real fix is probably to fix + * archive_write_set_format_xar.c + */ + if (*ctx) { + EVP_DigestFinal(*ctx, md, NULL); + EVP_MD_CTX_free(*ctx); + *ctx = NULL; + } + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_SHA1_WIN) + +static int +__archive_windowsapi_sha1init(archive_sha1_ctx *ctx) +{ + return (win_crypto_init(ctx, CALG_SHA1)); +} + +static int +__archive_windowsapi_sha1update(archive_sha1_ctx *ctx, const void *indata, + size_t insize) +{ + return (win_crypto_Update(ctx, indata, insize)); +} + +static int +__archive_windowsapi_sha1final(archive_sha1_ctx *ctx, void *md) +{ + return (win_crypto_Final(md, 20, ctx)); +} + +#else + +static int +__archive_stub_sha1init(archive_sha1_ctx *ctx) +{ + (void)ctx; /* UNUSED */ + return (ARCHIVE_FAILED); +} + +static int +__archive_stub_sha1update(archive_sha1_ctx *ctx, const void *indata, + size_t insize) +{ + (void)ctx; /* UNUSED */ + (void)indata; /* UNUSED */ + (void)insize; /* UNUSED */ + return (ARCHIVE_FAILED); +} + +static int +__archive_stub_sha1final(archive_sha1_ctx *ctx, void *md) +{ + (void)ctx; /* UNUSED */ + (void)md; /* UNUSED */ + return (ARCHIVE_FAILED); +} + +#endif + +/* SHA256 implementations */ +#if defined(ARCHIVE_CRYPTO_SHA256_LIBC) + +static int +__archive_libc_sha256init(archive_sha256_ctx *ctx) +{ + SHA256_Init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_libc_sha256update(archive_sha256_ctx *ctx, const void *indata, + size_t insize) +{ + SHA256_Update(ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_libc_sha256final(archive_sha256_ctx *ctx, void *md) +{ + SHA256_Final(md, ctx); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_SHA256_LIBC2) + +static int +__archive_libc2_sha256init(archive_sha256_ctx *ctx) +{ + SHA256Init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_libc2_sha256update(archive_sha256_ctx *ctx, const void *indata, + size_t insize) +{ + SHA256Update(ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_libc2_sha256final(archive_sha256_ctx *ctx, void *md) +{ + SHA256Final(md, ctx); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_SHA256_LIBC3) + +static int +__archive_libc3_sha256init(archive_sha256_ctx *ctx) +{ + SHA256Init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_libc3_sha256update(archive_sha256_ctx *ctx, const void *indata, + size_t insize) +{ + SHA256Update(ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_libc3_sha256final(archive_sha256_ctx *ctx, void *md) +{ + SHA256Final(md, ctx); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_SHA256_LIBMD) + +static int +__archive_libmd_sha256init(archive_sha256_ctx *ctx) +{ + SHA256_Init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_libmd_sha256update(archive_sha256_ctx *ctx, const void *indata, + size_t insize) +{ + SHA256_Update(ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_libmd_sha256final(archive_sha256_ctx *ctx, void *md) +{ + SHA256_Final(md, ctx); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM) + +static int +__archive_libsystem_sha256init(archive_sha256_ctx *ctx) +{ + CC_SHA256_Init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_libsystem_sha256update(archive_sha256_ctx *ctx, const void *indata, + size_t insize) +{ + CC_SHA256_Update(ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_libsystem_sha256final(archive_sha256_ctx *ctx, void *md) +{ + CC_SHA256_Final(md, ctx); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_SHA256_MBEDTLS) + +static int +__archive_mbedtls_sha256init(archive_sha256_ctx *ctx) +{ + mbedtls_sha256_init(ctx); + if (mbedtls_sha256_starts_ret(ctx, 0) == 0) + return (ARCHIVE_OK); + else + return (ARCHIVE_FATAL); +} + +static int +__archive_mbedtls_sha256update(archive_sha256_ctx *ctx, const void *indata, + size_t insize) +{ + if (mbedtls_sha256_update_ret(ctx, indata, insize) == 0) + return (ARCHIVE_OK); + else + return (ARCHIVE_FATAL); +} + +static int +__archive_mbedtls_sha256final(archive_sha256_ctx *ctx, void *md) +{ + if (mbedtls_sha256_finish_ret(ctx, md) == 0) { + mbedtls_sha256_free(ctx); + return (ARCHIVE_OK); + } else { + mbedtls_sha256_free(ctx); + return (ARCHIVE_FATAL); + } +} + +#elif defined(ARCHIVE_CRYPTO_SHA256_NETTLE) + +static int +__archive_nettle_sha256init(archive_sha256_ctx *ctx) +{ + sha256_init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_nettle_sha256update(archive_sha256_ctx *ctx, const void *indata, + size_t insize) +{ + sha256_update(ctx, insize, indata); + return (ARCHIVE_OK); +} + +static int +__archive_nettle_sha256final(archive_sha256_ctx *ctx, void *md) +{ + sha256_digest(ctx, SHA256_DIGEST_SIZE, md); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_SHA256_OPENSSL) + +static int +__archive_openssl_sha256init(archive_sha256_ctx *ctx) +{ + if ((*ctx = EVP_MD_CTX_new()) == NULL) + return (ARCHIVE_FAILED); + EVP_DigestInit(*ctx, EVP_sha256()); + return (ARCHIVE_OK); +} + +static int +__archive_openssl_sha256update(archive_sha256_ctx *ctx, const void *indata, + size_t insize) +{ + EVP_DigestUpdate(*ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_openssl_sha256final(archive_sha256_ctx *ctx, void *md) +{ + if (*ctx) { + EVP_DigestFinal(*ctx, md, NULL); + EVP_MD_CTX_free(*ctx); + *ctx = NULL; + } + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_SHA256_WIN) + +static int +__archive_windowsapi_sha256init(archive_sha256_ctx *ctx) +{ + return (win_crypto_init(ctx, CALG_SHA_256)); +} + +static int +__archive_windowsapi_sha256update(archive_sha256_ctx *ctx, const void *indata, + size_t insize) +{ + return (win_crypto_Update(ctx, indata, insize)); +} + +static int +__archive_windowsapi_sha256final(archive_sha256_ctx *ctx, void *md) +{ + return (win_crypto_Final(md, 32, ctx)); +} + +#else + +static int +__archive_stub_sha256init(archive_sha256_ctx *ctx) +{ + (void)ctx; /* UNUSED */ + return (ARCHIVE_FAILED); +} + +static int +__archive_stub_sha256update(archive_sha256_ctx *ctx, const void *indata, + size_t insize) +{ + (void)ctx; /* UNUSED */ + (void)indata; /* UNUSED */ + (void)insize; /* UNUSED */ + return (ARCHIVE_FAILED); +} + +static int +__archive_stub_sha256final(archive_sha256_ctx *ctx, void *md) +{ + (void)ctx; /* UNUSED */ + (void)md; /* UNUSED */ + return (ARCHIVE_FAILED); +} + +#endif + +/* SHA384 implementations */ +#if defined(ARCHIVE_CRYPTO_SHA384_LIBC) + +static int +__archive_libc_sha384init(archive_sha384_ctx *ctx) +{ + SHA384_Init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_libc_sha384update(archive_sha384_ctx *ctx, const void *indata, + size_t insize) +{ + SHA384_Update(ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_libc_sha384final(archive_sha384_ctx *ctx, void *md) +{ + SHA384_Final(md, ctx); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_SHA384_LIBC2) + +static int +__archive_libc2_sha384init(archive_sha384_ctx *ctx) +{ + SHA384Init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_libc2_sha384update(archive_sha384_ctx *ctx, const void *indata, + size_t insize) +{ + SHA384Update(ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_libc2_sha384final(archive_sha384_ctx *ctx, void *md) +{ + SHA384Final(md, ctx); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_SHA384_LIBC3) + +static int +__archive_libc3_sha384init(archive_sha384_ctx *ctx) +{ + SHA384Init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_libc3_sha384update(archive_sha384_ctx *ctx, const void *indata, + size_t insize) +{ + SHA384Update(ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_libc3_sha384final(archive_sha384_ctx *ctx, void *md) +{ + SHA384Final(md, ctx); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM) + +static int +__archive_libsystem_sha384init(archive_sha384_ctx *ctx) +{ + CC_SHA384_Init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_libsystem_sha384update(archive_sha384_ctx *ctx, const void *indata, + size_t insize) +{ + CC_SHA384_Update(ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_libsystem_sha384final(archive_sha384_ctx *ctx, void *md) +{ + CC_SHA384_Final(md, ctx); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_SHA384_MBEDTLS) + +static int +__archive_mbedtls_sha384init(archive_sha384_ctx *ctx) +{ + mbedtls_sha512_init(ctx); + if (mbedtls_sha512_starts_ret(ctx, 1) == 0) + return (ARCHIVE_OK); + else + return (ARCHIVE_FATAL); +} + +static int +__archive_mbedtls_sha384update(archive_sha384_ctx *ctx, const void *indata, + size_t insize) +{ + if (mbedtls_sha512_update_ret(ctx, indata, insize) == 0) + return (ARCHIVE_OK); + else + return (ARCHIVE_FATAL); +} + +static int +__archive_mbedtls_sha384final(archive_sha384_ctx *ctx, void *md) +{ + if (mbedtls_sha512_finish_ret(ctx, md) == 0) { + mbedtls_sha512_free(ctx); + return (ARCHIVE_OK); + } else { + mbedtls_sha512_free(ctx); + return (ARCHIVE_FATAL); + } +} + +#elif defined(ARCHIVE_CRYPTO_SHA384_NETTLE) + +static int +__archive_nettle_sha384init(archive_sha384_ctx *ctx) +{ + sha384_init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_nettle_sha384update(archive_sha384_ctx *ctx, const void *indata, + size_t insize) +{ + sha384_update(ctx, insize, indata); + return (ARCHIVE_OK); +} + +static int +__archive_nettle_sha384final(archive_sha384_ctx *ctx, void *md) +{ + sha384_digest(ctx, SHA384_DIGEST_SIZE, md); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_SHA384_OPENSSL) + +static int +__archive_openssl_sha384init(archive_sha384_ctx *ctx) +{ + if ((*ctx = EVP_MD_CTX_new()) == NULL) + return (ARCHIVE_FAILED); + EVP_DigestInit(*ctx, EVP_sha384()); + return (ARCHIVE_OK); +} + +static int +__archive_openssl_sha384update(archive_sha384_ctx *ctx, const void *indata, + size_t insize) +{ + EVP_DigestUpdate(*ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_openssl_sha384final(archive_sha384_ctx *ctx, void *md) +{ + if (*ctx) { + EVP_DigestFinal(*ctx, md, NULL); + EVP_MD_CTX_free(*ctx); + *ctx = NULL; + } + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_SHA384_WIN) + +static int +__archive_windowsapi_sha384init(archive_sha384_ctx *ctx) +{ + return (win_crypto_init(ctx, CALG_SHA_384)); +} + +static int +__archive_windowsapi_sha384update(archive_sha384_ctx *ctx, const void *indata, + size_t insize) +{ + return (win_crypto_Update(ctx, indata, insize)); +} + +static int +__archive_windowsapi_sha384final(archive_sha384_ctx *ctx, void *md) +{ + return (win_crypto_Final(md, 48, ctx)); +} + +#else + +static int +__archive_stub_sha384init(archive_sha384_ctx *ctx) +{ + (void)ctx; /* UNUSED */ + return (ARCHIVE_FAILED); +} + +static int +__archive_stub_sha384update(archive_sha384_ctx *ctx, const void *indata, + size_t insize) +{ + (void)ctx; /* UNUSED */ + (void)indata; /* UNUSED */ + (void)insize; /* UNUSED */ + return (ARCHIVE_FAILED); +} + +static int +__archive_stub_sha384final(archive_sha384_ctx *ctx, void *md) +{ + (void)ctx; /* UNUSED */ + (void)md; /* UNUSED */ + return (ARCHIVE_FAILED); +} + +#endif + +/* SHA512 implementations */ +#if defined(ARCHIVE_CRYPTO_SHA512_LIBC) + +static int +__archive_libc_sha512init(archive_sha512_ctx *ctx) +{ + SHA512_Init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_libc_sha512update(archive_sha512_ctx *ctx, const void *indata, + size_t insize) +{ + SHA512_Update(ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_libc_sha512final(archive_sha512_ctx *ctx, void *md) +{ + SHA512_Final(md, ctx); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_SHA512_LIBC2) + +static int +__archive_libc2_sha512init(archive_sha512_ctx *ctx) +{ + SHA512Init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_libc2_sha512update(archive_sha512_ctx *ctx, const void *indata, + size_t insize) +{ + SHA512Update(ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_libc2_sha512final(archive_sha512_ctx *ctx, void *md) +{ + SHA512Final(md, ctx); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_SHA512_LIBC3) + +static int +__archive_libc3_sha512init(archive_sha512_ctx *ctx) +{ + SHA512Init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_libc3_sha512update(archive_sha512_ctx *ctx, const void *indata, + size_t insize) +{ + SHA512Update(ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_libc3_sha512final(archive_sha512_ctx *ctx, void *md) +{ + SHA512Final(md, ctx); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_SHA512_LIBMD) + +static int +__archive_libmd_sha512init(archive_sha512_ctx *ctx) +{ + SHA512_Init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_libmd_sha512update(archive_sha512_ctx *ctx, const void *indata, + size_t insize) +{ + SHA512_Update(ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_libmd_sha512final(archive_sha512_ctx *ctx, void *md) +{ + SHA512_Final(md, ctx); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM) + +static int +__archive_libsystem_sha512init(archive_sha512_ctx *ctx) +{ + CC_SHA512_Init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_libsystem_sha512update(archive_sha512_ctx *ctx, const void *indata, + size_t insize) +{ + CC_SHA512_Update(ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_libsystem_sha512final(archive_sha512_ctx *ctx, void *md) +{ + CC_SHA512_Final(md, ctx); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_SHA512_MBEDTLS) + +static int +__archive_mbedtls_sha512init(archive_sha512_ctx *ctx) +{ + mbedtls_sha512_init(ctx); + if (mbedtls_sha512_starts_ret(ctx, 0) == 0) + return (ARCHIVE_OK); + else + return (ARCHIVE_FATAL); +} + +static int +__archive_mbedtls_sha512update(archive_sha512_ctx *ctx, const void *indata, + size_t insize) +{ + if (mbedtls_sha512_update_ret(ctx, indata, insize) == 0) + return (ARCHIVE_OK); + else + return (ARCHIVE_FATAL); +} + +static int +__archive_mbedtls_sha512final(archive_sha512_ctx *ctx, void *md) +{ + if (mbedtls_sha512_finish_ret(ctx, md) == 0) { + mbedtls_sha512_free(ctx); + return (ARCHIVE_OK); + } else { + mbedtls_sha512_free(ctx); + return (ARCHIVE_FATAL); + } +} + +#elif defined(ARCHIVE_CRYPTO_SHA512_NETTLE) + +static int +__archive_nettle_sha512init(archive_sha512_ctx *ctx) +{ + sha512_init(ctx); + return (ARCHIVE_OK); +} + +static int +__archive_nettle_sha512update(archive_sha512_ctx *ctx, const void *indata, + size_t insize) +{ + sha512_update(ctx, insize, indata); + return (ARCHIVE_OK); +} + +static int +__archive_nettle_sha512final(archive_sha512_ctx *ctx, void *md) +{ + sha512_digest(ctx, SHA512_DIGEST_SIZE, md); + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_SHA512_OPENSSL) + +static int +__archive_openssl_sha512init(archive_sha512_ctx *ctx) +{ + if ((*ctx = EVP_MD_CTX_new()) == NULL) + return (ARCHIVE_FAILED); + EVP_DigestInit(*ctx, EVP_sha512()); + return (ARCHIVE_OK); +} + +static int +__archive_openssl_sha512update(archive_sha512_ctx *ctx, const void *indata, + size_t insize) +{ + EVP_DigestUpdate(*ctx, indata, insize); + return (ARCHIVE_OK); +} + +static int +__archive_openssl_sha512final(archive_sha512_ctx *ctx, void *md) +{ + if (*ctx) { + EVP_DigestFinal(*ctx, md, NULL); + EVP_MD_CTX_free(*ctx); + *ctx = NULL; + } + return (ARCHIVE_OK); +} + +#elif defined(ARCHIVE_CRYPTO_SHA512_WIN) + +static int +__archive_windowsapi_sha512init(archive_sha512_ctx *ctx) +{ + return (win_crypto_init(ctx, CALG_SHA_512)); +} + +static int +__archive_windowsapi_sha512update(archive_sha512_ctx *ctx, const void *indata, + size_t insize) +{ + return (win_crypto_Update(ctx, indata, insize)); +} + +static int +__archive_windowsapi_sha512final(archive_sha512_ctx *ctx, void *md) +{ + return (win_crypto_Final(md, 64, ctx)); +} + +#else + +static int +__archive_stub_sha512init(archive_sha512_ctx *ctx) +{ + (void)ctx; /* UNUSED */ + return (ARCHIVE_FAILED); +} + +static int +__archive_stub_sha512update(archive_sha512_ctx *ctx, const void *indata, + size_t insize) +{ + (void)ctx; /* UNUSED */ + (void)indata; /* UNUSED */ + (void)insize; /* UNUSED */ + return (ARCHIVE_FAILED); +} + +static int +__archive_stub_sha512final(archive_sha512_ctx *ctx, void *md) +{ + (void)ctx; /* UNUSED */ + (void)md; /* UNUSED */ + return (ARCHIVE_FAILED); +} + +#endif + +/* NOTE: Message Digest functions are set based on availability and by the + * following order of preference. + * 1. libc + * 2. libc2 + * 3. libc3 + * 4. libSystem + * 5. Nettle + * 6. OpenSSL + * 7. libmd + * 8. Windows API + */ +const struct archive_digest __archive_digest = +{ +/* MD5 */ +#if defined(ARCHIVE_CRYPTO_MD5_LIBC) + &__archive_libc_md5init, + &__archive_libc_md5update, + &__archive_libc_md5final, +#elif defined(ARCHIVE_CRYPTO_MD5_LIBMD) + &__archive_libmd_md5init, + &__archive_libmd_md5update, + &__archive_libmd_md5final, +#elif defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM) + &__archive_libsystem_md5init, + &__archive_libsystem_md5update, + &__archive_libsystem_md5final, +#elif defined(ARCHIVE_CRYPTO_MD5_MBEDTLS) + &__archive_mbedtls_md5init, + &__archive_mbedtls_md5update, + &__archive_mbedtls_md5final, +#elif defined(ARCHIVE_CRYPTO_MD5_NETTLE) + &__archive_nettle_md5init, + &__archive_nettle_md5update, + &__archive_nettle_md5final, +#elif defined(ARCHIVE_CRYPTO_MD5_OPENSSL) + &__archive_openssl_md5init, + &__archive_openssl_md5update, + &__archive_openssl_md5final, +#elif defined(ARCHIVE_CRYPTO_MD5_WIN) + &__archive_windowsapi_md5init, + &__archive_windowsapi_md5update, + &__archive_windowsapi_md5final, +#elif !defined(ARCHIVE_MD5_COMPILE_TEST) + &__archive_stub_md5init, + &__archive_stub_md5update, + &__archive_stub_md5final, +#endif + +/* RIPEMD160 */ +#if defined(ARCHIVE_CRYPTO_RMD160_LIBC) + &__archive_libc_ripemd160init, + &__archive_libc_ripemd160update, + &__archive_libc_ripemd160final, +#elif defined(ARCHIVE_CRYPTO_RMD160_LIBMD) + &__archive_libmd_ripemd160init, + &__archive_libmd_ripemd160update, + &__archive_libmd_ripemd160final, +#elif defined(ARCHIVE_CRYPTO_RMD160_MBEDTLS) + &__archive_mbedtls_ripemd160init, + &__archive_mbedtls_ripemd160update, + &__archive_mbedtls_ripemd160final, +#elif defined(ARCHIVE_CRYPTO_RMD160_NETTLE) + &__archive_nettle_ripemd160init, + &__archive_nettle_ripemd160update, + &__archive_nettle_ripemd160final, +#elif defined(ARCHIVE_CRYPTO_RMD160_OPENSSL) + &__archive_openssl_ripemd160init, + &__archive_openssl_ripemd160update, + &__archive_openssl_ripemd160final, +#elif !defined(ARCHIVE_RMD160_COMPILE_TEST) + &__archive_stub_ripemd160init, + &__archive_stub_ripemd160update, + &__archive_stub_ripemd160final, +#endif + +/* SHA1 */ +#if defined(ARCHIVE_CRYPTO_SHA1_LIBC) + &__archive_libc_sha1init, + &__archive_libc_sha1update, + &__archive_libc_sha1final, +#elif defined(ARCHIVE_CRYPTO_SHA1_LIBMD) + &__archive_libmd_sha1init, + &__archive_libmd_sha1update, + &__archive_libmd_sha1final, +#elif defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM) + &__archive_libsystem_sha1init, + &__archive_libsystem_sha1update, + &__archive_libsystem_sha1final, +#elif defined(ARCHIVE_CRYPTO_SHA1_MBEDTLS) + &__archive_mbedtls_sha1init, + &__archive_mbedtls_sha1update, + &__archive_mbedtls_sha1final, +#elif defined(ARCHIVE_CRYPTO_SHA1_NETTLE) + &__archive_nettle_sha1init, + &__archive_nettle_sha1update, + &__archive_nettle_sha1final, +#elif defined(ARCHIVE_CRYPTO_SHA1_OPENSSL) + &__archive_openssl_sha1init, + &__archive_openssl_sha1update, + &__archive_openssl_sha1final, +#elif defined(ARCHIVE_CRYPTO_SHA1_WIN) + &__archive_windowsapi_sha1init, + &__archive_windowsapi_sha1update, + &__archive_windowsapi_sha1final, +#elif !defined(ARCHIVE_SHA1_COMPILE_TEST) + &__archive_stub_sha1init, + &__archive_stub_sha1update, + &__archive_stub_sha1final, +#endif + +/* SHA256 */ +#if defined(ARCHIVE_CRYPTO_SHA256_LIBC) + &__archive_libc_sha256init, + &__archive_libc_sha256update, + &__archive_libc_sha256final, +#elif defined(ARCHIVE_CRYPTO_SHA256_LIBC2) + &__archive_libc2_sha256init, + &__archive_libc2_sha256update, + &__archive_libc2_sha256final, +#elif defined(ARCHIVE_CRYPTO_SHA256_LIBC3) + &__archive_libc3_sha256init, + &__archive_libc3_sha256update, + &__archive_libc3_sha256final, +#elif defined(ARCHIVE_CRYPTO_SHA256_LIBMD) + &__archive_libmd_sha256init, + &__archive_libmd_sha256update, + &__archive_libmd_sha256final, +#elif defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM) + &__archive_libsystem_sha256init, + &__archive_libsystem_sha256update, + &__archive_libsystem_sha256final, +#elif defined(ARCHIVE_CRYPTO_SHA256_MBEDTLS) + &__archive_mbedtls_sha256init, + &__archive_mbedtls_sha256update, + &__archive_mbedtls_sha256final, +#elif defined(ARCHIVE_CRYPTO_SHA256_NETTLE) + &__archive_nettle_sha256init, + &__archive_nettle_sha256update, + &__archive_nettle_sha256final, +#elif defined(ARCHIVE_CRYPTO_SHA256_OPENSSL) + &__archive_openssl_sha256init, + &__archive_openssl_sha256update, + &__archive_openssl_sha256final, +#elif defined(ARCHIVE_CRYPTO_SHA256_WIN) + &__archive_windowsapi_sha256init, + &__archive_windowsapi_sha256update, + &__archive_windowsapi_sha256final, +#elif !defined(ARCHIVE_SHA256_COMPILE_TEST) + &__archive_stub_sha256init, + &__archive_stub_sha256update, + &__archive_stub_sha256final, +#endif + +/* SHA384 */ +#if defined(ARCHIVE_CRYPTO_SHA384_LIBC) + &__archive_libc_sha384init, + &__archive_libc_sha384update, + &__archive_libc_sha384final, +#elif defined(ARCHIVE_CRYPTO_SHA384_LIBC2) + &__archive_libc2_sha384init, + &__archive_libc2_sha384update, + &__archive_libc2_sha384final, +#elif defined(ARCHIVE_CRYPTO_SHA384_LIBC3) + &__archive_libc3_sha384init, + &__archive_libc3_sha384update, + &__archive_libc3_sha384final, +#elif defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM) + &__archive_libsystem_sha384init, + &__archive_libsystem_sha384update, + &__archive_libsystem_sha384final, +#elif defined(ARCHIVE_CRYPTO_SHA384_MBEDTLS) + &__archive_mbedtls_sha384init, + &__archive_mbedtls_sha384update, + &__archive_mbedtls_sha384final, +#elif defined(ARCHIVE_CRYPTO_SHA384_NETTLE) + &__archive_nettle_sha384init, + &__archive_nettle_sha384update, + &__archive_nettle_sha384final, +#elif defined(ARCHIVE_CRYPTO_SHA384_OPENSSL) + &__archive_openssl_sha384init, + &__archive_openssl_sha384update, + &__archive_openssl_sha384final, +#elif defined(ARCHIVE_CRYPTO_SHA384_WIN) + &__archive_windowsapi_sha384init, + &__archive_windowsapi_sha384update, + &__archive_windowsapi_sha384final, +#elif !defined(ARCHIVE_SHA384_COMPILE_TEST) + &__archive_stub_sha384init, + &__archive_stub_sha384update, + &__archive_stub_sha384final, +#endif + +/* SHA512 */ +#if defined(ARCHIVE_CRYPTO_SHA512_LIBC) + &__archive_libc_sha512init, + &__archive_libc_sha512update, + &__archive_libc_sha512final +#elif defined(ARCHIVE_CRYPTO_SHA512_LIBC2) + &__archive_libc2_sha512init, + &__archive_libc2_sha512update, + &__archive_libc2_sha512final +#elif defined(ARCHIVE_CRYPTO_SHA512_LIBC3) + &__archive_libc3_sha512init, + &__archive_libc3_sha512update, + &__archive_libc3_sha512final +#elif defined(ARCHIVE_CRYPTO_SHA512_LIBMD) + &__archive_libmd_sha512init, + &__archive_libmd_sha512update, + &__archive_libmd_sha512final +#elif defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM) + &__archive_libsystem_sha512init, + &__archive_libsystem_sha512update, + &__archive_libsystem_sha512final +#elif defined(ARCHIVE_CRYPTO_SHA512_MBEDTLS) + &__archive_mbedtls_sha512init, + &__archive_mbedtls_sha512update, + &__archive_mbedtls_sha512final +#elif defined(ARCHIVE_CRYPTO_SHA512_NETTLE) + &__archive_nettle_sha512init, + &__archive_nettle_sha512update, + &__archive_nettle_sha512final +#elif defined(ARCHIVE_CRYPTO_SHA512_OPENSSL) + &__archive_openssl_sha512init, + &__archive_openssl_sha512update, + &__archive_openssl_sha512final +#elif defined(ARCHIVE_CRYPTO_SHA512_WIN) + &__archive_windowsapi_sha512init, + &__archive_windowsapi_sha512update, + &__archive_windowsapi_sha512final +#elif !defined(ARCHIVE_SHA512_COMPILE_TEST) + &__archive_stub_sha512init, + &__archive_stub_sha512update, + &__archive_stub_sha512final +#endif +}; diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_digest_private.h b/dependencies/libarchive-3.4.2/libarchive/archive_digest_private.h new file mode 100644 index 0000000..15312ee --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_digest_private.h @@ -0,0 +1,412 @@ +/*- +* Copyright (c) 2003-2007 Tim Kientzle +* Copyright (c) 2011 Andres Mejia +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef ARCHIVE_DIGEST_PRIVATE_H_INCLUDED +#define ARCHIVE_DIGEST_PRIVATE_H_INCLUDED + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif +/* + * Crypto support in various Operating Systems: + * + * NetBSD: + * - MD5 and SHA1 in libc: without _ after algorithm name + * - SHA2 in libc: with _ after algorithm name + * + * OpenBSD: + * - MD5, SHA1 and SHA2 in libc: without _ after algorithm name + * - OpenBSD 4.4 and earlier have SHA2 in libc with _ after algorithm name + * + * DragonFly and FreeBSD: + * - MD5 libmd: without _ after algorithm name + * - SHA1, SHA256 and SHA512 in libmd: with _ after algorithm name + * + * Mac OS X (10.4 and later): + * - MD5, SHA1 and SHA2 in libSystem: with CC_ prefix and _ after algorithm name + * + * OpenSSL: + * - MD5, SHA1 and SHA2 in libcrypto: with _ after algorithm name + * + * Windows: + * - MD5, SHA1 and SHA2 in archive_crypto.c using Windows crypto API + */ + +/* libc crypto headers */ +#if defined(ARCHIVE_CRYPTO_MD5_LIBC) +#include +#endif +#if defined(ARCHIVE_CRYPTO_RMD160_LIBC) +#include +#endif +#if defined(ARCHIVE_CRYPTO_SHA1_LIBC) +#include +#endif +#if defined(ARCHIVE_CRYPTO_SHA256_LIBC) ||\ + defined(ARCHIVE_CRYPTO_SHA256_LIBC2) ||\ + defined(ARCHIVE_CRYPTO_SHA256_LIBC3) ||\ + defined(ARCHIVE_CRYPTO_SHA384_LIBC) ||\ + defined(ARCHIVE_CRYPTO_SHA384_LIBC2) ||\ + defined(ARCHIVE_CRYPTO_SHA384_LIBC3) ||\ + defined(ARCHIVE_CRYPTO_SHA512_LIBC) ||\ + defined(ARCHIVE_CRYPTO_SHA512_LIBC2) ||\ + defined(ARCHIVE_CRYPTO_SHA512_LIBC3) +#include +#endif + +/* libmd crypto headers */ +#if defined(ARCHIVE_CRYPTO_MD5_LIBMD) ||\ + defined(ARCHIVE_CRYPTO_RMD160_LIBMD) ||\ + defined(ARCHIVE_CRYPTO_SHA1_LIBMD) ||\ + defined(ARCHIVE_CRYPTO_SHA256_LIBMD) ||\ + defined(ARCHIVE_CRYPTO_SHA512_LIBMD) +#define ARCHIVE_CRYPTO_LIBMD 1 +#endif + +#if defined(ARCHIVE_CRYPTO_MD5_LIBMD) +#include +#endif +#if defined(ARCHIVE_CRYPTO_RMD160_LIBMD) +#include +#endif +#if defined(ARCHIVE_CRYPTO_SHA1_LIBMD) +#include +#endif +#if defined(ARCHIVE_CRYPTO_SHA256_LIBMD) +#include +#endif +#if defined(ARCHIVE_CRYPTO_SHA512_LIBMD) +#include +#endif + +/* libSystem crypto headers */ +#if defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM) ||\ + defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM) ||\ + defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM) ||\ + defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM) ||\ + defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM) +#include +#endif + +/* mbed TLS crypto headers */ +#if defined(ARCHIVE_CRYPTO_MD5_MBEDTLS) +#include +#endif +#if defined(ARCHIVE_CRYPTO_RMD160_MBEDTLS) +#include +#endif +#if defined(ARCHIVE_CRYPTO_SHA1_MBEDTLS) +#include +#endif +#if defined(ARCHIVE_CRYPTO_SHA256_MBEDTLS) +#include +#endif +#if defined(ARCHIVE_CRYPTO_SHA384_MBEDTLS) ||\ + defined(ARCHIVE_CRYPTO_SHA512_MBEDTLS) +#include +#endif + +/* Nettle crypto headers */ +#if defined(ARCHIVE_CRYPTO_MD5_NETTLE) +#include +#endif +#if defined(ARCHIVE_CRYPTO_RMD160_NETTLE) +#include +#endif +#if defined(ARCHIVE_CRYPTO_SHA1_NETTLE) ||\ + defined(ARCHIVE_CRYPTO_SHA256_NETTLE) ||\ + defined(ARCHIVE_CRYPTO_SHA384_NETTLE) ||\ + defined(ARCHIVE_CRYPTO_SHA512_NETTLE) +#include +#endif + +/* OpenSSL crypto headers */ +#if defined(ARCHIVE_CRYPTO_MD5_OPENSSL) ||\ + defined(ARCHIVE_CRYPTO_RMD160_OPENSSL) ||\ + defined(ARCHIVE_CRYPTO_SHA1_OPENSSL) ||\ + defined(ARCHIVE_CRYPTO_SHA256_OPENSSL) ||\ + defined(ARCHIVE_CRYPTO_SHA384_OPENSSL) ||\ + defined(ARCHIVE_CRYPTO_SHA512_OPENSSL) +#define ARCHIVE_CRYPTO_OPENSSL 1 +#include "archive_openssl_evp_private.h" +#endif + +/* Windows crypto headers */ +#if defined(ARCHIVE_CRYPTO_MD5_WIN) ||\ + defined(ARCHIVE_CRYPTO_SHA1_WIN) ||\ + defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\ + defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\ + defined(ARCHIVE_CRYPTO_SHA512_WIN) +#include +#include +typedef struct { + int valid; + HCRYPTPROV cryptProv; + HCRYPTHASH hash; +} Digest_CTX; +#endif + +/* typedefs */ +#if defined(ARCHIVE_CRYPTO_MD5_LIBC) +typedef MD5_CTX archive_md5_ctx; +#elif defined(ARCHIVE_CRYPTO_MD5_LIBMD) +typedef MD5_CTX archive_md5_ctx; +#elif defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM) +typedef CC_MD5_CTX archive_md5_ctx; +#elif defined(ARCHIVE_CRYPTO_MD5_MBEDTLS) +typedef mbedtls_md5_context archive_md5_ctx; +#elif defined(ARCHIVE_CRYPTO_MD5_NETTLE) +typedef struct md5_ctx archive_md5_ctx; +#elif defined(ARCHIVE_CRYPTO_MD5_OPENSSL) +typedef EVP_MD_CTX *archive_md5_ctx; +#elif defined(ARCHIVE_CRYPTO_MD5_WIN) +typedef Digest_CTX archive_md5_ctx; +#else +typedef unsigned char archive_md5_ctx; +#endif + +#if defined(ARCHIVE_CRYPTO_RMD160_LIBC) +typedef RMD160_CTX archive_rmd160_ctx; +#elif defined(ARCHIVE_CRYPTO_RMD160_LIBMD) +typedef RIPEMD160_CTX archive_rmd160_ctx; +#elif defined(ARCHIVE_CRYPTO_RMD160_MBEDTLS) +typedef mbedtls_ripemd160_context archive_rmd160_ctx; +#elif defined(ARCHIVE_CRYPTO_RMD160_NETTLE) +typedef struct ripemd160_ctx archive_rmd160_ctx; +#elif defined(ARCHIVE_CRYPTO_RMD160_OPENSSL) +typedef EVP_MD_CTX *archive_rmd160_ctx; +#else +typedef unsigned char archive_rmd160_ctx; +#endif + +#if defined(ARCHIVE_CRYPTO_SHA1_LIBC) +typedef SHA1_CTX archive_sha1_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA1_LIBMD) +typedef SHA1_CTX archive_sha1_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM) +typedef CC_SHA1_CTX archive_sha1_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA1_MBEDTLS) +typedef mbedtls_sha1_context archive_sha1_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA1_NETTLE) +typedef struct sha1_ctx archive_sha1_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA1_OPENSSL) +typedef EVP_MD_CTX *archive_sha1_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA1_WIN) +typedef Digest_CTX archive_sha1_ctx; +#else +typedef unsigned char archive_sha1_ctx; +#endif + +#if defined(ARCHIVE_CRYPTO_SHA256_LIBC) +typedef SHA256_CTX archive_sha256_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA256_LIBC2) +typedef SHA256_CTX archive_sha256_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA256_LIBC3) +typedef SHA2_CTX archive_sha256_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA256_LIBMD) +typedef SHA256_CTX archive_sha256_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM) +typedef CC_SHA256_CTX archive_sha256_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA256_MBEDTLS) +typedef mbedtls_sha256_context archive_sha256_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA256_NETTLE) +typedef struct sha256_ctx archive_sha256_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA256_OPENSSL) +typedef EVP_MD_CTX *archive_sha256_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA256_WIN) +typedef Digest_CTX archive_sha256_ctx; +#else +typedef unsigned char archive_sha256_ctx; +#endif + +#if defined(ARCHIVE_CRYPTO_SHA384_LIBC) +typedef SHA384_CTX archive_sha384_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA384_LIBC2) +typedef SHA384_CTX archive_sha384_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA384_LIBC3) +typedef SHA2_CTX archive_sha384_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM) +typedef CC_SHA512_CTX archive_sha384_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA384_MBEDTLS) +typedef mbedtls_sha512_context archive_sha384_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA384_NETTLE) +typedef struct sha384_ctx archive_sha384_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA384_OPENSSL) +typedef EVP_MD_CTX *archive_sha384_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA384_WIN) +typedef Digest_CTX archive_sha384_ctx; +#else +typedef unsigned char archive_sha384_ctx; +#endif + +#if defined(ARCHIVE_CRYPTO_SHA512_LIBC) +typedef SHA512_CTX archive_sha512_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA512_LIBC2) +typedef SHA512_CTX archive_sha512_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA512_LIBC3) +typedef SHA2_CTX archive_sha512_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA512_LIBMD) +typedef SHA512_CTX archive_sha512_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM) +typedef CC_SHA512_CTX archive_sha512_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA512_MBEDTLS) +typedef mbedtls_sha512_context archive_sha512_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA512_NETTLE) +typedef struct sha512_ctx archive_sha512_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA512_OPENSSL) +typedef EVP_MD_CTX *archive_sha512_ctx; +#elif defined(ARCHIVE_CRYPTO_SHA512_WIN) +typedef Digest_CTX archive_sha512_ctx; +#else +typedef unsigned char archive_sha512_ctx; +#endif + +/* defines */ +#if defined(ARCHIVE_CRYPTO_MD5_LIBC) ||\ + defined(ARCHIVE_CRYPTO_MD5_LIBMD) || \ + defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM) ||\ + defined(ARCHIVE_CRYPTO_MD5_MBEDTLS) ||\ + defined(ARCHIVE_CRYPTO_MD5_NETTLE) ||\ + defined(ARCHIVE_CRYPTO_MD5_OPENSSL) ||\ + defined(ARCHIVE_CRYPTO_MD5_WIN) +#define ARCHIVE_HAS_MD5 +#endif +#define archive_md5_init(ctx)\ + __archive_digest.md5init(ctx) +#define archive_md5_final(ctx, md)\ + __archive_digest.md5final(ctx, md) +#define archive_md5_update(ctx, buf, n)\ + __archive_digest.md5update(ctx, buf, n) + +#if defined(ARCHIVE_CRYPTO_RMD160_LIBC) ||\ + defined(ARCHIVE_CRYPTO_RMD160_MBEDTLS) ||\ + defined(ARCHIVE_CRYPTO_RMD160_NETTLE) ||\ + defined(ARCHIVE_CRYPTO_RMD160_OPENSSL) +#define ARCHIVE_HAS_RMD160 +#endif +#define archive_rmd160_init(ctx)\ + __archive_digest.rmd160init(ctx) +#define archive_rmd160_final(ctx, md)\ + __archive_digest.rmd160final(ctx, md) +#define archive_rmd160_update(ctx, buf, n)\ + __archive_digest.rmd160update(ctx, buf, n) + +#if defined(ARCHIVE_CRYPTO_SHA1_LIBC) ||\ + defined(ARCHIVE_CRYPTO_SHA1_LIBMD) || \ + defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM) ||\ + defined(ARCHIVE_CRYPTO_SHA1_MBEDTLS) ||\ + defined(ARCHIVE_CRYPTO_SHA1_NETTLE) ||\ + defined(ARCHIVE_CRYPTO_SHA1_OPENSSL) ||\ + defined(ARCHIVE_CRYPTO_SHA1_WIN) +#define ARCHIVE_HAS_SHA1 +#endif +#define archive_sha1_init(ctx)\ + __archive_digest.sha1init(ctx) +#define archive_sha1_final(ctx, md)\ + __archive_digest.sha1final(ctx, md) +#define archive_sha1_update(ctx, buf, n)\ + __archive_digest.sha1update(ctx, buf, n) + +#if defined(ARCHIVE_CRYPTO_SHA256_LIBC) ||\ + defined(ARCHIVE_CRYPTO_SHA256_LIBC2) ||\ + defined(ARCHIVE_CRYPTO_SHA256_LIBC3) ||\ + defined(ARCHIVE_CRYPTO_SHA256_LIBMD) ||\ + defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM) ||\ + defined(ARCHIVE_CRYPTO_SHA256_MBEDTLS) ||\ + defined(ARCHIVE_CRYPTO_SHA256_NETTLE) ||\ + defined(ARCHIVE_CRYPTO_SHA256_OPENSSL) ||\ + defined(ARCHIVE_CRYPTO_SHA256_WIN) +#define ARCHIVE_HAS_SHA256 +#endif +#define archive_sha256_init(ctx)\ + __archive_digest.sha256init(ctx) +#define archive_sha256_final(ctx, md)\ + __archive_digest.sha256final(ctx, md) +#define archive_sha256_update(ctx, buf, n)\ + __archive_digest.sha256update(ctx, buf, n) + +#if defined(ARCHIVE_CRYPTO_SHA384_LIBC) ||\ + defined(ARCHIVE_CRYPTO_SHA384_LIBC2) ||\ + defined(ARCHIVE_CRYPTO_SHA384_LIBC3) ||\ + defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM) ||\ + defined(ARCHIVE_CRYPTO_SHA384_MBEDTLS) ||\ + defined(ARCHIVE_CRYPTO_SHA384_NETTLE) ||\ + defined(ARCHIVE_CRYPTO_SHA384_OPENSSL) ||\ + defined(ARCHIVE_CRYPTO_SHA384_WIN) +#define ARCHIVE_HAS_SHA384 +#endif +#define archive_sha384_init(ctx)\ + __archive_digest.sha384init(ctx) +#define archive_sha384_final(ctx, md)\ + __archive_digest.sha384final(ctx, md) +#define archive_sha384_update(ctx, buf, n)\ + __archive_digest.sha384update(ctx, buf, n) + +#if defined(ARCHIVE_CRYPTO_SHA512_LIBC) ||\ + defined(ARCHIVE_CRYPTO_SHA512_LIBC2) ||\ + defined(ARCHIVE_CRYPTO_SHA512_LIBC3) ||\ + defined(ARCHIVE_CRYPTO_SHA512_LIBMD) ||\ + defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM) ||\ + defined(ARCHIVE_CRYPTO_SHA512_MBEDTLS) ||\ + defined(ARCHIVE_CRYPTO_SHA512_NETTLE) ||\ + defined(ARCHIVE_CRYPTO_SHA512_OPENSSL) ||\ + defined(ARCHIVE_CRYPTO_SHA512_WIN) +#define ARCHIVE_HAS_SHA512 +#endif +#define archive_sha512_init(ctx)\ + __archive_digest.sha512init(ctx) +#define archive_sha512_final(ctx, md)\ + __archive_digest.sha512final(ctx, md) +#define archive_sha512_update(ctx, buf, n)\ + __archive_digest.sha512update(ctx, buf, n) + +/* Minimal interface to digest functionality for internal use in libarchive */ +struct archive_digest +{ + /* Message Digest */ + int (*md5init)(archive_md5_ctx *ctx); + int (*md5update)(archive_md5_ctx *, const void *, size_t); + int (*md5final)(archive_md5_ctx *, void *); + int (*rmd160init)(archive_rmd160_ctx *); + int (*rmd160update)(archive_rmd160_ctx *, const void *, size_t); + int (*rmd160final)(archive_rmd160_ctx *, void *); + int (*sha1init)(archive_sha1_ctx *); + int (*sha1update)(archive_sha1_ctx *, const void *, size_t); + int (*sha1final)(archive_sha1_ctx *, void *); + int (*sha256init)(archive_sha256_ctx *); + int (*sha256update)(archive_sha256_ctx *, const void *, size_t); + int (*sha256final)(archive_sha256_ctx *, void *); + int (*sha384init)(archive_sha384_ctx *); + int (*sha384update)(archive_sha384_ctx *, const void *, size_t); + int (*sha384final)(archive_sha384_ctx *, void *); + int (*sha512init)(archive_sha512_ctx *); + int (*sha512update)(archive_sha512_ctx *, const void *, size_t); + int (*sha512final)(archive_sha512_ctx *, void *); +}; + +extern const struct archive_digest __archive_digest; + +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_disk_acl_darwin.c b/dependencies/libarchive-3.4.2/libarchive/archive_disk_acl_darwin.c new file mode 100644 index 0000000..48ad016 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_disk_acl_darwin.c @@ -0,0 +1,559 @@ +/*- + * Copyright (c) 2017 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +#if ARCHIVE_ACL_DARWIN + +#ifdef HAVE_FCNTL_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_MEMBERSHIP_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_ACL_H +#define _ACL_PRIVATE /* For debugging */ +#include +#endif + +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_read_disk_private.h" +#include "archive_write_disk_private.h" + +typedef struct { + const int a_perm; /* Libarchive permission or flag */ + const int p_perm; /* Platform permission or flag */ +} acl_perm_map_t; + +static const acl_perm_map_t acl_nfs4_perm_map[] = { + {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA}, + {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY}, + {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE}, + {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, + {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE}, + {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY}, + {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD}, + {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY}, + {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY}, + {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER}, +#if HAVE_DECL_ACL_SYNCHRONIZE + {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE} +#endif +}; + +static const int acl_nfs4_perm_map_size = + (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0])); + +static const acl_perm_map_t acl_nfs4_flag_map[] = { + {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}, + {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT} +}; + +static const int acl_nfs4_flag_map_size = + (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0])); + +static int translate_guid(struct archive *a, acl_entry_t acl_entry, + int *ae_id, int *ae_tag, const char **ae_name) +{ + void *q; + uid_t ugid; + int r, idtype; + + q = acl_get_qualifier(acl_entry); + if (q == NULL) + return (1); + r = mbr_uuid_to_id((const unsigned char *)q, &ugid, &idtype); + if (r != 0) { + acl_free(q); + return (1); + } + if (idtype == ID_TYPE_UID) { + *ae_tag = ARCHIVE_ENTRY_ACL_USER; + *ae_id = ugid; + *ae_name = archive_read_disk_uname(a, *ae_id); + } else if (idtype == ID_TYPE_GID) { + *ae_tag = ARCHIVE_ENTRY_ACL_GROUP; + *ae_id = ugid; + *ae_name = archive_read_disk_gname(a, *ae_id); + } else + r = 1; + + acl_free(q); + return (r); +} + +static void +add_trivial_nfs4_acl(struct archive_entry *entry) +{ + mode_t mode; + int i; + const int rperm = ARCHIVE_ENTRY_ACL_READ_DATA; + const int wperm = ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_APPEND_DATA; + const int eperm = ARCHIVE_ENTRY_ACL_EXECUTE; + const int pubset = ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE; + const int ownset = pubset | ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_WRITE_ACL | + ARCHIVE_ENTRY_ACL_WRITE_OWNER; + + struct { + const int type; + const int tag; + int permset; + } tacl_entry[] = { + {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, 0}, + {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_USER_OBJ, 0}, + {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0}, + {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, ownset}, + {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_GROUP_OBJ, pubset}, + {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EVERYONE, pubset} + }; + + mode = archive_entry_mode(entry); + + /* Permissions for everyone@ */ + if (mode & 0004) + tacl_entry[5].permset |= rperm; + if (mode & 0002) + tacl_entry[5].permset |= wperm; + if (mode & 0001) + tacl_entry[5].permset |= eperm; + + /* Permissions for group@ */ + if (mode & 0040) + tacl_entry[4].permset |= rperm; + else if (mode & 0004) + tacl_entry[2].permset |= rperm; + if (mode & 0020) + tacl_entry[4].permset |= wperm; + else if (mode & 0002) + tacl_entry[2].permset |= wperm; + if (mode & 0010) + tacl_entry[4].permset |= eperm; + else if (mode & 0001) + tacl_entry[2].permset |= eperm; + + /* Permissions for owner@ */ + if (mode & 0400) { + tacl_entry[3].permset |= rperm; + if (!(mode & 0040) && (mode & 0004)) + tacl_entry[0].permset |= rperm; + } else if ((mode & 0040) || (mode & 0004)) + tacl_entry[1].permset |= rperm; + if (mode & 0200) { + tacl_entry[3].permset |= wperm; + if (!(mode & 0020) && (mode & 0002)) + tacl_entry[0].permset |= wperm; + } else if ((mode & 0020) || (mode & 0002)) + tacl_entry[1].permset |= wperm; + if (mode & 0100) { + tacl_entry[3].permset |= eperm; + if (!(mode & 0010) && (mode & 0001)) + tacl_entry[0].permset |= eperm; + } else if ((mode & 0010) || (mode & 0001)) + tacl_entry[1].permset |= eperm; + + for (i = 0; i < 6; i++) { + if (tacl_entry[i].permset != 0) { + archive_entry_acl_add_entry(entry, + tacl_entry[i].type, tacl_entry[i].permset, + tacl_entry[i].tag, -1, NULL); + } + } + + return; +} + +static int +translate_acl(struct archive_read_disk *a, + struct archive_entry *entry, acl_t acl) +{ + acl_tag_t acl_tag; + acl_flagset_t acl_flagset; + acl_entry_t acl_entry; + acl_permset_t acl_permset; + int i, entry_acl_type; + int r, s, ae_id, ae_tag, ae_perm; + const char *ae_name; + + s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry); + if (s == -1) { + archive_set_error(&a->archive, errno, + "Failed to get first ACL entry"); + return (ARCHIVE_WARN); + } + + while (s == 0) { + ae_id = -1; + ae_name = NULL; + ae_perm = 0; + + if (acl_get_tag_type(acl_entry, &acl_tag) != 0) { + archive_set_error(&a->archive, errno, + "Failed to get ACL tag type"); + return (ARCHIVE_WARN); + } + switch (acl_tag) { + case ACL_EXTENDED_ALLOW: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; + r = translate_guid(&a->archive, acl_entry, + &ae_id, &ae_tag, &ae_name); + break; + case ACL_EXTENDED_DENY: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY; + r = translate_guid(&a->archive, acl_entry, + &ae_id, &ae_tag, &ae_name); + break; + default: + /* Skip types that libarchive can't support. */ + s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); + continue; + } + + /* Skip if translate_guid() above failed */ + if (r != 0) { + s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); + continue; + } + + /* + * Libarchive stores "flag" (NFSv4 inheritance bits) + * in the ae_perm bitmap. + * + * acl_get_flagset_np() fails with non-NFSv4 ACLs + */ + if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) { + archive_set_error(&a->archive, errno, + "Failed to get flagset from a NFSv4 ACL entry"); + return (ARCHIVE_WARN); + } + for (i = 0; i < acl_nfs4_flag_map_size; ++i) { + r = acl_get_flag_np(acl_flagset, + acl_nfs4_flag_map[i].p_perm); + if (r == -1) { + archive_set_error(&a->archive, errno, + "Failed to check flag in a NFSv4 " + "ACL flagset"); + return (ARCHIVE_WARN); + } else if (r) + ae_perm |= acl_nfs4_flag_map[i].a_perm; + } + + if (acl_get_permset(acl_entry, &acl_permset) != 0) { + archive_set_error(&a->archive, errno, + "Failed to get ACL permission set"); + return (ARCHIVE_WARN); + } + + for (i = 0; i < acl_nfs4_perm_map_size; ++i) { + /* + * acl_get_perm() is spelled differently on different + * platforms; see above. + */ + r = acl_get_perm_np(acl_permset, + acl_nfs4_perm_map[i].p_perm); + if (r == -1) { + archive_set_error(&a->archive, errno, + "Failed to check permission in an ACL " + "permission set"); + return (ARCHIVE_WARN); + } else if (r) + ae_perm |= acl_nfs4_perm_map[i].a_perm; + } + +#if !HAVE_DECL_ACL_SYNCHRONIZE + /* On Mac OS X without ACL_SYNCHRONIZE assume it is set */ + ae_perm |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE; +#endif + + archive_entry_acl_add_entry(entry, entry_acl_type, + ae_perm, ae_tag, + ae_id, ae_name); + + s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); + } + return (ARCHIVE_OK); +} + +static int +set_acl(struct archive *a, int fd, const char *name, + struct archive_acl *abstract_acl, + int ae_requested_type, const char *tname) +{ + acl_t acl; + acl_entry_t acl_entry; + acl_permset_t acl_permset; + acl_flagset_t acl_flagset; + int ret; + int ae_type, ae_permset, ae_tag, ae_id; + uuid_t ae_uuid; + uid_t ae_uid; + gid_t ae_gid; + const char *ae_name; + int entries; + int i; + + ret = ARCHIVE_OK; + entries = archive_acl_reset(abstract_acl, ae_requested_type); + if (entries == 0) + return (ARCHIVE_OK); + + if (ae_requested_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + errno = ENOENT; + archive_set_error(a, errno, "Unsupported ACL type"); + return (ARCHIVE_FAILED); + } + + acl = acl_init(entries); + if (acl == (acl_t)NULL) { + archive_set_error(a, errno, + "Failed to initialize ACL working storage"); + return (ARCHIVE_FAILED); + } + + while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type, + &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) { + /* + * Mac OS doesn't support NFSv4 ACLs for + * owner@, group@ and everyone@. + * We skip any of these ACLs found. + */ + if (ae_tag == ARCHIVE_ENTRY_ACL_USER_OBJ || + ae_tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ || + ae_tag == ARCHIVE_ENTRY_ACL_EVERYONE) + continue; + + if (acl_create_entry(&acl, &acl_entry) != 0) { + archive_set_error(a, errno, + "Failed to create a new ACL entry"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + switch (ae_type) { + case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: + acl_set_tag_type(acl_entry, ACL_EXTENDED_ALLOW); + break; + case ARCHIVE_ENTRY_ACL_TYPE_DENY: + acl_set_tag_type(acl_entry, ACL_EXTENDED_DENY); + break; + default: + /* We don't support any other types on MacOS */ + continue; + } + + switch (ae_tag) { + case ARCHIVE_ENTRY_ACL_USER: + ae_uid = archive_write_disk_uid(a, ae_name, ae_id); + if (mbr_uid_to_uuid(ae_uid, ae_uuid) != 0) + continue; + if (acl_set_qualifier(acl_entry, &ae_uuid) != 0) + continue; + break; + case ARCHIVE_ENTRY_ACL_GROUP: + ae_gid = archive_write_disk_gid(a, ae_name, ae_id); + if (mbr_gid_to_uuid(ae_gid, ae_uuid) != 0) + continue; + if (acl_set_qualifier(acl_entry, &ae_uuid) != 0) + continue; + break; + default: + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unsupported ACL tag"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + if (acl_get_permset(acl_entry, &acl_permset) != 0) { + archive_set_error(a, errno, + "Failed to get ACL permission set"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + if (acl_clear_perms(acl_permset) != 0) { + archive_set_error(a, errno, + "Failed to clear ACL permissions"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + for (i = 0; i < acl_nfs4_perm_map_size; ++i) { + if (ae_permset & acl_nfs4_perm_map[i].a_perm) { + if (acl_add_perm(acl_permset, + acl_nfs4_perm_map[i].p_perm) != 0) { + archive_set_error(a, errno, + "Failed to add ACL permission"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + } + } + + /* + * acl_get_flagset_np() fails with non-NFSv4 ACLs + */ + if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) { + archive_set_error(a, errno, + "Failed to get flagset from an NFSv4 ACL entry"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + if (acl_clear_flags_np(acl_flagset) != 0) { + archive_set_error(a, errno, + "Failed to clear flags from an NFSv4 ACL flagset"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + for (i = 0; i < acl_nfs4_flag_map_size; ++i) { + if (ae_permset & acl_nfs4_flag_map[i].a_perm) { + if (acl_add_flag_np(acl_flagset, + acl_nfs4_flag_map[i].p_perm) != 0) { + archive_set_error(a, errno, + "Failed to add flag to " + "NFSv4 ACL flagset"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + } + } + } + + if (fd >= 0) { + if (acl_set_fd_np(fd, acl, ACL_TYPE_EXTENDED) == 0) + ret = ARCHIVE_OK; + else { + if (errno == EOPNOTSUPP) { + /* Filesystem doesn't support ACLs */ + ret = ARCHIVE_OK; + } else { + archive_set_error(a, errno, + "Failed to set acl on fd: %s", tname); + ret = ARCHIVE_WARN; + } + } + } else if (acl_set_link_np(name, ACL_TYPE_EXTENDED, acl) != 0) { + if (errno == EOPNOTSUPP) { + /* Filesystem doesn't support ACLs */ + ret = ARCHIVE_OK; + } else { + archive_set_error(a, errno, "Failed to set acl: %s", + tname); + ret = ARCHIVE_WARN; + } + } +exit_free: + acl_free(acl); + return (ret); +} + +int +archive_read_disk_entry_setup_acls(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + const char *accpath; + acl_t acl; + int r; + + accpath = NULL; + + if (*fd < 0) { + accpath = archive_read_disk_entry_setup_path(a, entry, fd); + if (accpath == NULL) + return (ARCHIVE_WARN); + } + + archive_entry_acl_clear(entry); + + acl = NULL; + + if (*fd >= 0) + acl = acl_get_fd_np(*fd, ACL_TYPE_EXTENDED); + else if (!a->follow_symlinks) + acl = acl_get_link_np(accpath, ACL_TYPE_EXTENDED); + else + acl = acl_get_file(accpath, ACL_TYPE_EXTENDED); + + if (acl != NULL) { + r = translate_acl(a, entry, acl); + acl_free(acl); + acl = NULL; + + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, errno, + "Couldn't translate NFSv4 ACLs"); + } + + /* + * Because Mac OS doesn't support owner@, group@ and everyone@ + * ACLs we need to add NFSv4 ACLs mirroring the file mode to + * the archive entry. Otherwise extraction on non-Mac platforms + * would lead to an invalid file mode. + */ + if ((archive_entry_acl_types(entry) & + ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) + add_trivial_nfs4_acl(entry); + + return (r); + } + return (ARCHIVE_OK); +} + +int +archive_write_disk_set_acls(struct archive *a, int fd, const char *name, + struct archive_acl *abstract_acl, __LA_MODE_T mode) +{ + int ret = ARCHIVE_OK; + + (void)mode; /* UNUSED */ + + if ((archive_acl_types(abstract_acl) & + ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + ret = set_acl(a, fd, name, abstract_acl, + ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4"); + } + return (ret); +} +#endif /* ARCHIVE_ACL_DARWIN */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_disk_acl_freebsd.c b/dependencies/libarchive-3.4.2/libarchive/archive_disk_acl_freebsd.c new file mode 100644 index 0000000..aba41e5 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_disk_acl_freebsd.c @@ -0,0 +1,702 @@ +/*- + * Copyright (c) 2003-2009 Tim Kientzle + * Copyright (c) 2010-2012 Michihiro NAKAJIMA + * Copyright (c) 2017 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +#if ARCHIVE_ACL_FREEBSD + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_ACL_H +#define _ACL_PRIVATE /* For debugging */ +#include +#endif + +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_read_disk_private.h" +#include "archive_write_disk_private.h" + +typedef struct { + const int a_perm; /* Libarchive permission or flag */ + const int p_perm; /* Platform permission or flag */ +} acl_perm_map_t; + +static const acl_perm_map_t acl_posix_perm_map[] = { + {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, + {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE}, + {ARCHIVE_ENTRY_ACL_READ, ACL_READ}, +}; + +static const int acl_posix_perm_map_size = + (int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0])); + +#if ARCHIVE_ACL_FREEBSD_NFS4 +static const acl_perm_map_t acl_nfs4_perm_map[] = { + {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, + {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA}, + {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY}, + {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE}, + {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY}, + {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD}, + {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE}, + {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER}, + {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE} +}; + +static const int acl_nfs4_perm_map_size = + (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0])); + +static const acl_perm_map_t acl_nfs4_flag_map[] = { + {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}, + {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS}, + {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS}, +#ifdef ACL_ENTRY_INHERITED + {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED} +#endif +}; + +static const int acl_nfs4_flag_map_size = + (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0])); +#endif /* ARCHIVE_ACL_FREEBSD_NFS4 */ + +static int +translate_acl(struct archive_read_disk *a, + struct archive_entry *entry, acl_t acl, int default_entry_acl_type) +{ +#if ARCHIVE_ACL_FREEBSD_NFS4 + int brand; + acl_flagset_t acl_flagset; + acl_entry_type_t acl_type; +#endif + acl_tag_t acl_tag; + acl_entry_t acl_entry; + acl_permset_t acl_permset; + int i, entry_acl_type, perm_map_size; + const acl_perm_map_t *perm_map; + int r, s, ae_id, ae_tag, ae_perm; + void *q; + const char *ae_name; + +#if ARCHIVE_ACL_FREEBSD_NFS4 + // FreeBSD "brands" ACLs as POSIX.1e or NFSv4 + // Make sure the "brand" on this ACL is consistent + // with the default_entry_acl_type bits provided. + if (acl_get_brand_np(acl, &brand) != 0) { + archive_set_error(&a->archive, errno, + "Failed to read ACL brand"); + return (ARCHIVE_WARN); + } + switch (brand) { + case ACL_BRAND_POSIX: + switch (default_entry_acl_type) { + case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: + case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid ACL entry type for POSIX.1e ACL"); + return (ARCHIVE_WARN); + } + break; + case ACL_BRAND_NFS4: + if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid ACL entry type for NFSv4 ACL"); + return (ARCHIVE_WARN); + } + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Unknown ACL brand"); + return (ARCHIVE_WARN); + } +#endif + + s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry); + if (s == -1) { + archive_set_error(&a->archive, errno, + "Failed to get first ACL entry"); + return (ARCHIVE_WARN); + } + + while (s == 1) { + ae_id = -1; + ae_name = NULL; + ae_perm = 0; + + if (acl_get_tag_type(acl_entry, &acl_tag) != 0) { + archive_set_error(&a->archive, errno, + "Failed to get ACL tag type"); + return (ARCHIVE_WARN); + } + switch (acl_tag) { + case ACL_USER: + q = acl_get_qualifier(acl_entry); + if (q != NULL) { + ae_id = (int)*(uid_t *)q; + acl_free(q); + ae_name = archive_read_disk_uname(&a->archive, + ae_id); + } + ae_tag = ARCHIVE_ENTRY_ACL_USER; + break; + case ACL_GROUP: + q = acl_get_qualifier(acl_entry); + if (q != NULL) { + ae_id = (int)*(gid_t *)q; + acl_free(q); + ae_name = archive_read_disk_gname(&a->archive, + ae_id); + } + ae_tag = ARCHIVE_ENTRY_ACL_GROUP; + break; + case ACL_MASK: + ae_tag = ARCHIVE_ENTRY_ACL_MASK; + break; + case ACL_USER_OBJ: + ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + break; + case ACL_GROUP_OBJ: + ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + break; + case ACL_OTHER: + ae_tag = ARCHIVE_ENTRY_ACL_OTHER; + break; +#if ARCHIVE_ACL_FREEBSD_NFS4 + case ACL_EVERYONE: + ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE; + break; +#endif + default: + /* Skip types that libarchive can't support. */ + s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); + continue; + } + + // XXX acl_type maps to allow/deny/audit/YYYY bits + entry_acl_type = default_entry_acl_type; + +#if ARCHIVE_ACL_FREEBSD_NFS4 + if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + /* + * acl_get_entry_type_np() fails with non-NFSv4 ACLs + */ + if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) { + archive_set_error(&a->archive, errno, "Failed " + "to get ACL type from a NFSv4 ACL entry"); + return (ARCHIVE_WARN); + } + switch (acl_type) { + case ACL_ENTRY_TYPE_ALLOW: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; + break; + case ACL_ENTRY_TYPE_DENY: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY; + break; + case ACL_ENTRY_TYPE_AUDIT: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT; + break; + case ACL_ENTRY_TYPE_ALARM: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM; + break; + default: + archive_set_error(&a->archive, errno, + "Invalid NFSv4 ACL entry type"); + return (ARCHIVE_WARN); + } + + /* + * Libarchive stores "flag" (NFSv4 inheritance bits) + * in the ae_perm bitmap. + * + * acl_get_flagset_np() fails with non-NFSv4 ACLs + */ + if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) { + archive_set_error(&a->archive, errno, + "Failed to get flagset from a NFSv4 " + "ACL entry"); + return (ARCHIVE_WARN); + } + for (i = 0; i < acl_nfs4_flag_map_size; ++i) { + r = acl_get_flag_np(acl_flagset, + acl_nfs4_flag_map[i].p_perm); + if (r == -1) { + archive_set_error(&a->archive, errno, + "Failed to check flag in a NFSv4 " + "ACL flagset"); + return (ARCHIVE_WARN); + } else if (r) + ae_perm |= acl_nfs4_flag_map[i].a_perm; + } + } +#endif + + if (acl_get_permset(acl_entry, &acl_permset) != 0) { + archive_set_error(&a->archive, errno, + "Failed to get ACL permission set"); + return (ARCHIVE_WARN); + } + +#if ARCHIVE_ACL_FREEBSD_NFS4 + if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + perm_map_size = acl_nfs4_perm_map_size; + perm_map = acl_nfs4_perm_map; + } else { +#endif + perm_map_size = acl_posix_perm_map_size; + perm_map = acl_posix_perm_map; +#if ARCHIVE_ACL_FREEBSD_NFS4 + } +#endif + + for (i = 0; i < perm_map_size; ++i) { + r = acl_get_perm_np(acl_permset, perm_map[i].p_perm); + if (r == -1) { + archive_set_error(&a->archive, errno, + "Failed to check permission in an ACL " + "permission set"); + return (ARCHIVE_WARN); + } else if (r) + ae_perm |= perm_map[i].a_perm; + } + + archive_entry_acl_add_entry(entry, entry_acl_type, + ae_perm, ae_tag, + ae_id, ae_name); + + s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); + if (s == -1) { + archive_set_error(&a->archive, errno, + "Failed to get next ACL entry"); + return (ARCHIVE_WARN); + } + } + return (ARCHIVE_OK); +} + +static int +set_acl(struct archive *a, int fd, const char *name, + struct archive_acl *abstract_acl, + int ae_requested_type, const char *tname) +{ + int acl_type = 0; + acl_t acl; + acl_entry_t acl_entry; + acl_permset_t acl_permset; +#if ARCHIVE_ACL_FREEBSD_NFS4 + acl_flagset_t acl_flagset; + int r; +#endif + int ret; + int ae_type, ae_permset, ae_tag, ae_id; + int perm_map_size; + const acl_perm_map_t *perm_map; + uid_t ae_uid; + gid_t ae_gid; + const char *ae_name; + int entries; + int i; + + ret = ARCHIVE_OK; + entries = archive_acl_reset(abstract_acl, ae_requested_type); + if (entries == 0) + return (ARCHIVE_OK); + + + switch (ae_requested_type) { + case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: + acl_type = ACL_TYPE_ACCESS; + break; + case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: + acl_type = ACL_TYPE_DEFAULT; + break; +#if ARCHIVE_ACL_FREEBSD_NFS4 + case ARCHIVE_ENTRY_ACL_TYPE_NFS4: + acl_type = ACL_TYPE_NFS4; + break; +#endif + default: + errno = ENOENT; + archive_set_error(a, errno, "Unsupported ACL type"); + return (ARCHIVE_FAILED); + } + + acl = acl_init(entries); + if (acl == (acl_t)NULL) { + archive_set_error(a, errno, + "Failed to initialize ACL working storage"); + return (ARCHIVE_FAILED); + } + + while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type, + &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) { + if (acl_create_entry(&acl, &acl_entry) != 0) { + archive_set_error(a, errno, + "Failed to create a new ACL entry"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + switch (ae_tag) { + case ARCHIVE_ENTRY_ACL_USER: + ae_uid = archive_write_disk_uid(a, ae_name, ae_id); + acl_set_tag_type(acl_entry, ACL_USER); + acl_set_qualifier(acl_entry, &ae_uid); + break; + case ARCHIVE_ENTRY_ACL_GROUP: + ae_gid = archive_write_disk_gid(a, ae_name, ae_id); + acl_set_tag_type(acl_entry, ACL_GROUP); + acl_set_qualifier(acl_entry, &ae_gid); + break; + case ARCHIVE_ENTRY_ACL_USER_OBJ: + acl_set_tag_type(acl_entry, ACL_USER_OBJ); + break; + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + acl_set_tag_type(acl_entry, ACL_GROUP_OBJ); + break; + case ARCHIVE_ENTRY_ACL_MASK: + acl_set_tag_type(acl_entry, ACL_MASK); + break; + case ARCHIVE_ENTRY_ACL_OTHER: + acl_set_tag_type(acl_entry, ACL_OTHER); + break; +#if ARCHIVE_ACL_FREEBSD_NFS4 + case ARCHIVE_ENTRY_ACL_EVERYONE: + acl_set_tag_type(acl_entry, ACL_EVERYONE); + break; +#endif + default: + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unsupported ACL tag"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + +#if ARCHIVE_ACL_FREEBSD_NFS4 + r = 0; + switch (ae_type) { + case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: + r = acl_set_entry_type_np(acl_entry, + ACL_ENTRY_TYPE_ALLOW); + break; + case ARCHIVE_ENTRY_ACL_TYPE_DENY: + r = acl_set_entry_type_np(acl_entry, + ACL_ENTRY_TYPE_DENY); + break; + case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: + r = acl_set_entry_type_np(acl_entry, + ACL_ENTRY_TYPE_AUDIT); + break; + case ARCHIVE_ENTRY_ACL_TYPE_ALARM: + r = acl_set_entry_type_np(acl_entry, + ACL_ENTRY_TYPE_ALARM); + break; + case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: + case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: + // These don't translate directly into the system ACL. + break; + default: + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unsupported ACL entry type"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + if (r != 0) { + archive_set_error(a, errno, + "Failed to set ACL entry type"); + ret = ARCHIVE_FAILED; + goto exit_free; + } +#endif + + if (acl_get_permset(acl_entry, &acl_permset) != 0) { + archive_set_error(a, errno, + "Failed to get ACL permission set"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + if (acl_clear_perms(acl_permset) != 0) { + archive_set_error(a, errno, + "Failed to clear ACL permissions"); + ret = ARCHIVE_FAILED; + goto exit_free; + } +#if ARCHIVE_ACL_FREEBSD_NFS4 + if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + perm_map_size = acl_nfs4_perm_map_size; + perm_map = acl_nfs4_perm_map; + } else { +#endif + perm_map_size = acl_posix_perm_map_size; + perm_map = acl_posix_perm_map; +#if ARCHIVE_ACL_FREEBSD_NFS4 + } +#endif + + for (i = 0; i < perm_map_size; ++i) { + if (ae_permset & perm_map[i].a_perm) { + if (acl_add_perm(acl_permset, + perm_map[i].p_perm) != 0) { + archive_set_error(a, errno, + "Failed to add ACL permission"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + } + } + +#if ARCHIVE_ACL_FREEBSD_NFS4 + if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + /* + * acl_get_flagset_np() fails with non-NFSv4 ACLs + */ + if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) { + archive_set_error(a, errno, + "Failed to get flagset from an NFSv4 " + "ACL entry"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + if (acl_clear_flags_np(acl_flagset) != 0) { + archive_set_error(a, errno, + "Failed to clear flags from an NFSv4 " + "ACL flagset"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + for (i = 0; i < acl_nfs4_flag_map_size; ++i) { + if (ae_permset & acl_nfs4_flag_map[i].a_perm) { + if (acl_add_flag_np(acl_flagset, + acl_nfs4_flag_map[i].p_perm) != 0) { + archive_set_error(a, errno, + "Failed to add flag to " + "NFSv4 ACL flagset"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + } + } + } +#endif + } + + /* Try restoring the ACL through 'fd' if we can. */ + if (fd >= 0) { + if (acl_set_fd_np(fd, acl, acl_type) == 0) + ret = ARCHIVE_OK; + else { + if (errno == EOPNOTSUPP) { + /* Filesystem doesn't support ACLs */ + ret = ARCHIVE_OK; + } else { + archive_set_error(a, errno, + "Failed to set acl on fd: %s", tname); + ret = ARCHIVE_WARN; + } + } + } +#if HAVE_ACL_SET_LINK_NP + else if (acl_set_link_np(name, acl_type, acl) != 0) +#else + /* FreeBSD older than 8.0 */ + else if (acl_set_file(name, acl_type, acl) != 0) +#endif + { + if (errno == EOPNOTSUPP) { + /* Filesystem doesn't support ACLs */ + ret = ARCHIVE_OK; + } else { + archive_set_error(a, errno, "Failed to set acl: %s", + tname); + ret = ARCHIVE_WARN; + } + } +exit_free: + acl_free(acl); + return (ret); +} + +int +archive_read_disk_entry_setup_acls(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + const char *accpath; + acl_t acl; + int r; + + accpath = NULL; + + if (*fd < 0) { + accpath = archive_read_disk_entry_setup_path(a, entry, fd); + if (accpath == NULL) + return (ARCHIVE_WARN); + } + + archive_entry_acl_clear(entry); + + acl = NULL; + +#if ARCHIVE_ACL_FREEBSD_NFS4 + /* Try NFSv4 ACL first. */ + if (*fd >= 0) + acl = acl_get_fd_np(*fd, ACL_TYPE_NFS4); + else if (!a->follow_symlinks) + acl = acl_get_link_np(accpath, ACL_TYPE_NFS4); + else + acl = acl_get_file(accpath, ACL_TYPE_NFS4); + + /* Ignore "trivial" ACLs that just mirror the file mode. */ + if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) { + acl_free(acl); + acl = NULL; + return (ARCHIVE_OK); + } + + if (acl != NULL) { + r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4); + acl_free(acl); + acl = NULL; + + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, errno, + "Couldn't translate NFSv4 ACLs"); + } + + return (r); + } +#endif + + /* Retrieve access ACL from file. */ + if (*fd >= 0) + acl = acl_get_fd_np(*fd, ACL_TYPE_ACCESS); +#if HAVE_ACL_GET_LINK_NP + else if (!a->follow_symlinks) + acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS); +#else + else if ((!a->follow_symlinks) + && (archive_entry_filetype(entry) == AE_IFLNK)) + /* We can't get the ACL of a symlink, so we assume it can't + have one. */ + acl = NULL; +#endif + else + acl = acl_get_file(accpath, ACL_TYPE_ACCESS); + +#if HAVE_ACL_IS_TRIVIAL_NP + /* Ignore "trivial" ACLs that just mirror the file mode. */ + if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) { + acl_free(acl); + acl = NULL; + } +#endif + + if (acl != NULL) { + r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + acl_free(acl); + acl = NULL; + + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, errno, + "Couldn't translate access ACLs"); + return (r); + } + } + + /* Only directories can have default ACLs. */ + if (S_ISDIR(archive_entry_mode(entry))) { + if (*fd >= 0) + acl = acl_get_fd_np(*fd, ACL_TYPE_DEFAULT); + else + acl = acl_get_file(accpath, ACL_TYPE_DEFAULT); + if (acl != NULL) { + r = translate_acl(a, entry, acl, + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT); + acl_free(acl); + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, errno, + "Couldn't translate default ACLs"); + return (r); + } + } + } + return (ARCHIVE_OK); +} + +int +archive_write_disk_set_acls(struct archive *a, int fd, const char *name, + struct archive_acl *abstract_acl, __LA_MODE_T mode) +{ + int ret = ARCHIVE_OK; + + (void)mode; /* UNUSED */ + + if ((archive_acl_types(abstract_acl) + & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) { + if ((archive_acl_types(abstract_acl) + & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { + ret = set_acl(a, fd, name, abstract_acl, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access"); + if (ret != ARCHIVE_OK) + return (ret); + } + if ((archive_acl_types(abstract_acl) + & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) + ret = set_acl(a, fd, name, abstract_acl, + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default"); + + /* Simultaneous POSIX.1e and NFSv4 is not supported */ + return (ret); + } +#if ARCHIVE_ACL_FREEBSD_NFS4 + else if ((archive_acl_types(abstract_acl) & + ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + ret = set_acl(a, fd, name, abstract_acl, + ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4"); + } +#endif + return (ret); +} +#endif /* ARCHIVE_ACL_FREEBSD */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_disk_acl_linux.c b/dependencies/libarchive-3.4.2/libarchive/archive_disk_acl_linux.c new file mode 100644 index 0000000..3928f3d --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_disk_acl_linux.c @@ -0,0 +1,743 @@ +/*- + * Copyright (c) 2003-2009 Tim Kientzle + * Copyright (c) 2010-2012 Michihiro NAKAJIMA + * Copyright (c) 2017 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +#if ARCHIVE_ACL_LIBACL || ARCHIVE_ACL_LIBRICHACL + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#if HAVE_ACL_LIBACL_H +#include +#endif +#ifdef HAVE_SYS_ACL_H +#include +#endif +#ifdef HAVE_SYS_RICHACL_H +#include +#endif + +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_read_disk_private.h" +#include "archive_write_disk_private.h" + +typedef struct { + const int a_perm; /* Libarchive permission or flag */ + const int p_perm; /* Platform permission or flag */ +} acl_perm_map_t; + +#if ARCHIVE_ACL_LIBACL +static const acl_perm_map_t acl_posix_perm_map[] = { + {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, + {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE}, + {ARCHIVE_ENTRY_ACL_READ, ACL_READ}, +}; + +static const int acl_posix_perm_map_size = + (int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0])); +#endif /* ARCHIVE_ACL_LIBACL */ + +#if ARCHIVE_ACL_LIBRICHACL +static const acl_perm_map_t acl_nfs4_perm_map[] = { + {ARCHIVE_ENTRY_ACL_EXECUTE, RICHACE_EXECUTE}, + {ARCHIVE_ENTRY_ACL_READ_DATA, RICHACE_READ_DATA}, + {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, RICHACE_LIST_DIRECTORY}, + {ARCHIVE_ENTRY_ACL_WRITE_DATA, RICHACE_WRITE_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_FILE, RICHACE_ADD_FILE}, + {ARCHIVE_ENTRY_ACL_APPEND_DATA, RICHACE_APPEND_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, RICHACE_ADD_SUBDIRECTORY}, + {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, RICHACE_READ_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, RICHACE_WRITE_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_DELETE_CHILD, RICHACE_DELETE_CHILD}, + {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, RICHACE_READ_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, RICHACE_WRITE_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_DELETE, RICHACE_DELETE}, + {ARCHIVE_ENTRY_ACL_READ_ACL, RICHACE_READ_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_ACL, RICHACE_WRITE_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_OWNER, RICHACE_WRITE_OWNER}, + {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, RICHACE_SYNCHRONIZE} +}; + +static const int acl_nfs4_perm_map_size = + (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0])); + +static const acl_perm_map_t acl_nfs4_flag_map[] = { + {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, RICHACE_FILE_INHERIT_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, RICHACE_DIRECTORY_INHERIT_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, RICHACE_NO_PROPAGATE_INHERIT_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, RICHACE_INHERIT_ONLY_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, RICHACE_INHERITED_ACE} +}; + +static const int acl_nfs4_flag_map_size = + (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0])); +#endif /* ARCHIVE_ACL_LIBRICHACL */ + +#if ARCHIVE_ACL_LIBACL +/* + * Translate POSIX.1e ACLs into libarchive internal structure + */ +static int +translate_acl(struct archive_read_disk *a, + struct archive_entry *entry, acl_t acl, int default_entry_acl_type) +{ + acl_tag_t acl_tag; + acl_entry_t acl_entry; + acl_permset_t acl_permset; + int i, entry_acl_type; + int r, s, ae_id, ae_tag, ae_perm; + void *q; + const char *ae_name; + + s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry); + if (s == -1) { + archive_set_error(&a->archive, errno, + "Failed to get first ACL entry"); + return (ARCHIVE_WARN); + } + + while (s == 1) { + ae_id = -1; + ae_name = NULL; + ae_perm = 0; + + if (acl_get_tag_type(acl_entry, &acl_tag) != 0) { + archive_set_error(&a->archive, errno, + "Failed to get ACL tag type"); + return (ARCHIVE_WARN); + } + switch (acl_tag) { + case ACL_USER: + q = acl_get_qualifier(acl_entry); + if (q != NULL) { + ae_id = (int)*(uid_t *)q; + acl_free(q); + ae_name = archive_read_disk_uname(&a->archive, + ae_id); + } + ae_tag = ARCHIVE_ENTRY_ACL_USER; + break; + case ACL_GROUP: + q = acl_get_qualifier(acl_entry); + if (q != NULL) { + ae_id = (int)*(gid_t *)q; + acl_free(q); + ae_name = archive_read_disk_gname(&a->archive, + ae_id); + } + ae_tag = ARCHIVE_ENTRY_ACL_GROUP; + break; + case ACL_MASK: + ae_tag = ARCHIVE_ENTRY_ACL_MASK; + break; + case ACL_USER_OBJ: + ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + break; + case ACL_GROUP_OBJ: + ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + break; + case ACL_OTHER: + ae_tag = ARCHIVE_ENTRY_ACL_OTHER; + break; + default: + /* Skip types that libarchive can't support. */ + s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); + continue; + } + + // XXX acl_type maps to allow/deny/audit/YYYY bits + entry_acl_type = default_entry_acl_type; + + if (acl_get_permset(acl_entry, &acl_permset) != 0) { + archive_set_error(&a->archive, errno, + "Failed to get ACL permission set"); + return (ARCHIVE_WARN); + } + + for (i = 0; i < acl_posix_perm_map_size; ++i) { + r = acl_get_perm(acl_permset, + acl_posix_perm_map[i].p_perm); + if (r == -1) { + archive_set_error(&a->archive, errno, + "Failed to check permission in an ACL " + "permission set"); + return (ARCHIVE_WARN); + } else if (r) + ae_perm |= acl_posix_perm_map[i].a_perm; + } + + archive_entry_acl_add_entry(entry, entry_acl_type, + ae_perm, ae_tag, + ae_id, ae_name); + + s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); + if (s == -1) { + archive_set_error(&a->archive, errno, + "Failed to get next ACL entry"); + return (ARCHIVE_WARN); + } + } + return (ARCHIVE_OK); +} +#endif /* ARCHIVE_ACL_LIBACL */ + +#if ARCHIVE_ACL_LIBRICHACL +/* + * Translate RichACL into libarchive internal ACL + */ +static int +translate_richacl(struct archive_read_disk *a, struct archive_entry *entry, + struct richacl *richacl) +{ + int ae_id, ae_tag, ae_perm; + int entry_acl_type, i; + const char *ae_name; + + struct richace *richace; + + richacl_for_each_entry(richace, richacl) { + ae_name = NULL; + ae_tag = 0; + ae_perm = 0; + ae_id = -1; + + switch (richace->e_type) { + case RICHACE_ACCESS_ALLOWED_ACE_TYPE: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; + break; + case RICHACE_ACCESS_DENIED_ACE_TYPE: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY; + break; + default: /* Unknown entry type, skip */ + continue; + } + + /* Unsupported */ + if (richace->e_flags & RICHACE_UNMAPPED_WHO) + continue; + + if (richace->e_flags & RICHACE_SPECIAL_WHO) { + switch (richace->e_id) { + case RICHACE_OWNER_SPECIAL_ID: + ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + break; + case RICHACE_GROUP_SPECIAL_ID: + ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + break; + case RICHACE_EVERYONE_SPECIAL_ID: + ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE; + break; + default: /* Unknown special ID type */ + continue; + } + } else { + ae_id = richace->e_id; + if (richace->e_flags & RICHACE_IDENTIFIER_GROUP) { + ae_tag = ARCHIVE_ENTRY_ACL_GROUP; + ae_name = archive_read_disk_gname(&a->archive, + (gid_t)(richace->e_id)); + } else { + ae_tag = ARCHIVE_ENTRY_ACL_USER; + ae_name = archive_read_disk_uname(&a->archive, + (uid_t)(richace->e_id)); + } + } + for (i = 0; i < acl_nfs4_flag_map_size; ++i) { + if ((richace->e_flags & + acl_nfs4_flag_map[i].p_perm) != 0) + ae_perm |= acl_nfs4_flag_map[i].a_perm; + } + for (i = 0; i < acl_nfs4_perm_map_size; ++i) { + if ((richace->e_mask & + acl_nfs4_perm_map[i].p_perm) != 0) + ae_perm |= + acl_nfs4_perm_map[i].a_perm; + } + + archive_entry_acl_add_entry(entry, entry_acl_type, + ae_perm, ae_tag, ae_id, ae_name); + } + return (ARCHIVE_OK); +} +#endif /* ARCHIVE_ACL_LIBRICHACL */ + +#if ARCHIVE_ACL_LIBRICHACL +static int +_richacl_mode_to_mask(short mode) +{ + int mask = 0; + + if (mode & S_IROTH) + mask |= RICHACE_POSIX_MODE_READ; + if (mode & S_IWOTH) + mask |= RICHACE_POSIX_MODE_WRITE; + if (mode & S_IXOTH) + mask |= RICHACE_POSIX_MODE_EXEC; + + return (mask); +} + +static void +_richacl_mode_to_masks(struct richacl *richacl, __LA_MODE_T mode) +{ + richacl->a_owner_mask = _richacl_mode_to_mask((mode & 0700) >> 6); + richacl->a_group_mask = _richacl_mode_to_mask((mode & 0070) >> 3); + richacl->a_other_mask = _richacl_mode_to_mask(mode & 0007); +} +#endif /* ARCHIVE_ACL_LIBRICHACL */ + +#if ARCHIVE_ACL_LIBRICHACL +static int +set_richacl(struct archive *a, int fd, const char *name, + struct archive_acl *abstract_acl, __LA_MODE_T mode, + int ae_requested_type, const char *tname) +{ + int ae_type, ae_permset, ae_tag, ae_id; + uid_t ae_uid; + gid_t ae_gid; + const char *ae_name; + int entries; + int i; + int ret; + int e = 0; + struct richacl *richacl = NULL; + struct richace *richace; + + ret = ARCHIVE_OK; + entries = archive_acl_reset(abstract_acl, ae_requested_type); + if (entries == 0) + return (ARCHIVE_OK); + + if (ae_requested_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + errno = ENOENT; + archive_set_error(a, errno, "Unsupported ACL type"); + return (ARCHIVE_FAILED); + } + + richacl = richacl_alloc(entries); + if (richacl == NULL) { + archive_set_error(a, errno, + "Failed to initialize RichACL working storage"); + return (ARCHIVE_FAILED); + } + + e = 0; + + while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type, + &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) { + richace = &(richacl->a_entries[e]); + + richace->e_flags = 0; + richace->e_mask = 0; + + switch (ae_tag) { + case ARCHIVE_ENTRY_ACL_USER: + ae_uid = archive_write_disk_uid(a, ae_name, ae_id); + richace->e_id = ae_uid; + break; + case ARCHIVE_ENTRY_ACL_GROUP: + ae_gid = archive_write_disk_gid(a, ae_name, ae_id); + richace->e_id = ae_gid; + richace->e_flags |= RICHACE_IDENTIFIER_GROUP; + break; + case ARCHIVE_ENTRY_ACL_USER_OBJ: + richace->e_flags |= RICHACE_SPECIAL_WHO; + richace->e_id = RICHACE_OWNER_SPECIAL_ID; + break; + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + richace->e_flags |= RICHACE_SPECIAL_WHO; + richace->e_id = RICHACE_GROUP_SPECIAL_ID; + break; + case ARCHIVE_ENTRY_ACL_EVERYONE: + richace->e_flags |= RICHACE_SPECIAL_WHO; + richace->e_id = RICHACE_EVERYONE_SPECIAL_ID; + break; + default: + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unsupported ACL tag"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + switch (ae_type) { + case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: + richace->e_type = + RICHACE_ACCESS_ALLOWED_ACE_TYPE; + break; + case ARCHIVE_ENTRY_ACL_TYPE_DENY: + richace->e_type = + RICHACE_ACCESS_DENIED_ACE_TYPE; + break; + case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: + case ARCHIVE_ENTRY_ACL_TYPE_ALARM: + break; + default: + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unsupported ACL entry type"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + for (i = 0; i < acl_nfs4_perm_map_size; ++i) { + if (ae_permset & acl_nfs4_perm_map[i].a_perm) + richace->e_mask |= acl_nfs4_perm_map[i].p_perm; + } + + for (i = 0; i < acl_nfs4_flag_map_size; ++i) { + if (ae_permset & + acl_nfs4_flag_map[i].a_perm) + richace->e_flags |= acl_nfs4_flag_map[i].p_perm; + } + e++; + } + + /* Fill RichACL masks */ + _richacl_mode_to_masks(richacl, mode); + + if (fd >= 0) { + if (richacl_set_fd(fd, richacl) == 0) + ret = ARCHIVE_OK; + else { + if (errno == EOPNOTSUPP) { + /* Filesystem doesn't support ACLs */ + ret = ARCHIVE_OK; + } else { + archive_set_error(a, errno, + "Failed to set richacl on fd: %s", tname); + ret = ARCHIVE_WARN; + } + } + } else if (richacl_set_file(name, richacl) != 0) { + if (errno == EOPNOTSUPP) { + /* Filesystem doesn't support ACLs */ + ret = ARCHIVE_OK; + } else { + archive_set_error(a, errno, "Failed to set richacl: %s", + tname); + ret = ARCHIVE_WARN; + } + } +exit_free: + richacl_free(richacl); + return (ret); +} +#endif /* ARCHIVE_ACL_RICHACL */ + +#if ARCHIVE_ACL_LIBACL +static int +set_acl(struct archive *a, int fd, const char *name, + struct archive_acl *abstract_acl, + int ae_requested_type, const char *tname) +{ + int acl_type = 0; + int ae_type, ae_permset, ae_tag, ae_id; + uid_t ae_uid; + gid_t ae_gid; + const char *ae_name; + int entries; + int i; + int ret; + acl_t acl = NULL; + acl_entry_t acl_entry; + acl_permset_t acl_permset; + + ret = ARCHIVE_OK; + entries = archive_acl_reset(abstract_acl, ae_requested_type); + if (entries == 0) + return (ARCHIVE_OK); + + switch (ae_requested_type) { + case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: + acl_type = ACL_TYPE_ACCESS; + break; + case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: + acl_type = ACL_TYPE_DEFAULT; + break; + default: + errno = ENOENT; + archive_set_error(a, errno, "Unsupported ACL type"); + return (ARCHIVE_FAILED); + } + + acl = acl_init(entries); + if (acl == (acl_t)NULL) { + archive_set_error(a, errno, + "Failed to initialize ACL working storage"); + return (ARCHIVE_FAILED); + } + + while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type, + &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) { + + if (acl_create_entry(&acl, &acl_entry) != 0) { + archive_set_error(a, errno, + "Failed to create a new ACL entry"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + switch (ae_tag) { + case ARCHIVE_ENTRY_ACL_USER: + ae_uid = archive_write_disk_uid(a, ae_name, ae_id); + acl_set_tag_type(acl_entry, ACL_USER); + acl_set_qualifier(acl_entry, &ae_uid); + break; + case ARCHIVE_ENTRY_ACL_GROUP: + ae_gid = archive_write_disk_gid(a, ae_name, ae_id); + acl_set_tag_type(acl_entry, ACL_GROUP); + acl_set_qualifier(acl_entry, &ae_gid); + break; + case ARCHIVE_ENTRY_ACL_USER_OBJ: + acl_set_tag_type(acl_entry, ACL_USER_OBJ); + break; + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + acl_set_tag_type(acl_entry, ACL_GROUP_OBJ); + break; + case ARCHIVE_ENTRY_ACL_MASK: + acl_set_tag_type(acl_entry, ACL_MASK); + break; + case ARCHIVE_ENTRY_ACL_OTHER: + acl_set_tag_type(acl_entry, ACL_OTHER); + break; + default: + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unsupported ACL tag"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + if (acl_get_permset(acl_entry, &acl_permset) != 0) { + archive_set_error(a, errno, + "Failed to get ACL permission set"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + if (acl_clear_perms(acl_permset) != 0) { + archive_set_error(a, errno, + "Failed to clear ACL permissions"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + for (i = 0; i < acl_posix_perm_map_size; ++i) { + if (ae_permset & acl_posix_perm_map[i].a_perm) { + if (acl_add_perm(acl_permset, + acl_posix_perm_map[i].p_perm) != 0) { + archive_set_error(a, errno, + "Failed to add ACL permission"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + } + } + + } + + if (fd >= 0 && ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) { + if (acl_set_fd(fd, acl) == 0) + ret = ARCHIVE_OK; + else { + if (errno == EOPNOTSUPP) { + /* Filesystem doesn't support ACLs */ + ret = ARCHIVE_OK; + } else { + archive_set_error(a, errno, + "Failed to set acl on fd: %s", tname); + ret = ARCHIVE_WARN; + } + } + } else if (acl_set_file(name, acl_type, acl) != 0) { + if (errno == EOPNOTSUPP) { + /* Filesystem doesn't support ACLs */ + ret = ARCHIVE_OK; + } else { + archive_set_error(a, errno, "Failed to set acl: %s", + tname); + ret = ARCHIVE_WARN; + } + } +exit_free: + acl_free(acl); + return (ret); +} +#endif /* ARCHIVE_ACL_LIBACL */ + +int +archive_read_disk_entry_setup_acls(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + const char *accpath; + int r; +#if ARCHIVE_ACL_LIBACL + acl_t acl; +#endif +#if ARCHIVE_ACL_LIBRICHACL + struct richacl *richacl; + mode_t mode; +#endif + + accpath = NULL; + r = ARCHIVE_OK; + + /* For default ACLs we need reachable accpath */ + if (*fd < 0 || S_ISDIR(archive_entry_mode(entry))) { + accpath = archive_read_disk_entry_setup_path(a, entry, fd); + if (accpath == NULL) + return (ARCHIVE_WARN); + } + + archive_entry_acl_clear(entry); + +#if ARCHIVE_ACL_LIBACL + acl = NULL; +#endif +#if ARCHIVE_ACL_LIBRICHACL + richacl = NULL; +#endif + +#if ARCHIVE_ACL_LIBRICHACL + /* Try NFSv4 ACL first. */ + if (*fd >= 0) + richacl = richacl_get_fd(*fd); + else if ((!a->follow_symlinks) + && (archive_entry_filetype(entry) == AE_IFLNK)) + /* We can't get the ACL of a symlink, so we assume it can't + have one */ + richacl = NULL; + else + richacl = richacl_get_file(accpath); + + /* Ignore "trivial" ACLs that just mirror the file mode. */ + if (richacl != NULL) { + mode = archive_entry_mode(entry); + if (richacl_equiv_mode(richacl, &mode) == 0) { + richacl_free(richacl); + richacl = NULL; + return (ARCHIVE_OK); + } + } + + if (richacl != NULL) { + r = translate_richacl(a, entry, richacl); + richacl_free(richacl); + richacl = NULL; + + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, errno, + "Couldn't translate NFSv4 ACLs"); + } + + return (r); + } +#endif /* ARCHIVE_ACL_LIBRICHACL */ + +#if ARCHIVE_ACL_LIBACL + /* Retrieve access ACL from file. */ + if (*fd >= 0) + acl = acl_get_fd(*fd); + else if ((!a->follow_symlinks) + && (archive_entry_filetype(entry) == AE_IFLNK)) + /* We can't get the ACL of a symlink, so we assume it can't + have one. */ + acl = NULL; + else + acl = acl_get_file(accpath, ACL_TYPE_ACCESS); + + if (acl != NULL) { + r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + acl_free(acl); + acl = NULL; + + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, errno, + "Couldn't translate access ACLs"); + return (r); + } + } + + /* Only directories can have default ACLs. */ + if (S_ISDIR(archive_entry_mode(entry))) { + acl = acl_get_file(accpath, ACL_TYPE_DEFAULT); + if (acl != NULL) { + r = translate_acl(a, entry, acl, + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT); + acl_free(acl); + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, errno, + "Couldn't translate default ACLs"); + return (r); + } + } + } +#endif /* ARCHIVE_ACL_LIBACL */ + return (r); +} + +int +archive_write_disk_set_acls(struct archive *a, int fd, const char *name, + struct archive_acl *abstract_acl, __LA_MODE_T mode) +{ + int ret = ARCHIVE_OK; + +#if !ARCHIVE_ACL_LIBRICHACL + (void)mode; /* UNUSED */ +#endif + +#if ARCHIVE_ACL_LIBRICHACL + if ((archive_acl_types(abstract_acl) + & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + ret = set_richacl(a, fd, name, abstract_acl, mode, + ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4"); + } +#if ARCHIVE_ACL_LIBACL + else +#endif +#endif /* ARCHIVE_ACL_LIBRICHACL */ +#if ARCHIVE_ACL_LIBACL + if ((archive_acl_types(abstract_acl) + & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) { + if ((archive_acl_types(abstract_acl) + & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { + ret = set_acl(a, fd, name, abstract_acl, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access"); + if (ret != ARCHIVE_OK) + return (ret); + } + if ((archive_acl_types(abstract_acl) + & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) + ret = set_acl(a, fd, name, abstract_acl, + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default"); + } +#endif /* ARCHIVE_ACL_LIBACL */ + return (ret); +} +#endif /* ARCHIVE_ACL_LIBACL || ARCHIVE_ACL_LIBRICHACL */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_disk_acl_sunos.c b/dependencies/libarchive-3.4.2/libarchive/archive_disk_acl_sunos.c new file mode 100644 index 0000000..b0f5dfa --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_disk_acl_sunos.c @@ -0,0 +1,819 @@ +/*- + * Copyright (c) 2017 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +#if ARCHIVE_ACL_SUNOS + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_ACL_H +#define _ACL_PRIVATE /* For debugging */ +#include +#endif + +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_read_disk_private.h" +#include "archive_write_disk_private.h" + +typedef struct { + const int a_perm; /* Libarchive permission or flag */ + const int p_perm; /* Platform permission or flag */ +} acl_perm_map_t; + +static const acl_perm_map_t acl_posix_perm_map[] = { + {ARCHIVE_ENTRY_ACL_EXECUTE, S_IXOTH }, + {ARCHIVE_ENTRY_ACL_WRITE, S_IWOTH }, + {ARCHIVE_ENTRY_ACL_READ, S_IROTH } +}; + +static const int acl_posix_perm_map_size = + (int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0])); + +#if ARCHIVE_ACL_SUNOS_NFS4 +static const acl_perm_map_t acl_nfs4_perm_map[] = { + {ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE}, + {ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA}, + {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY}, + {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE}, + {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY}, + {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD}, + {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE}, + {ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER}, + {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE} +}; + +static const int acl_nfs4_perm_map_size = + (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0])); + +static const acl_perm_map_t acl_nfs4_flag_map[] = { + {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG}, + {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG}, +#ifdef ACE_INHERITED_ACE + {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE} +#endif +}; + +const int acl_nfs4_flag_map_size = + (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0])); + +#endif /* ARCHIVE_ACL_SUNOS_NFS4 */ + +static void * +sunacl_get(int cmd, int *aclcnt, int fd, const char *path) +{ + int cnt, cntcmd; + size_t size; + void *aclp; + + if (cmd == GETACL) { + cntcmd = GETACLCNT; + size = sizeof(aclent_t); + } +#if ARCHIVE_ACL_SUNOS_NFS4 + else if (cmd == ACE_GETACL) { + cntcmd = ACE_GETACLCNT; + size = sizeof(ace_t); + } +#endif + else { + errno = EINVAL; + *aclcnt = -1; + return (NULL); + } + + aclp = NULL; + cnt = -2; + + while (cnt == -2 || (cnt == -1 && errno == ENOSPC)) { + if (path != NULL) + cnt = acl(path, cntcmd, 0, NULL); + else + cnt = facl(fd, cntcmd, 0, NULL); + + if (cnt > 0) { + if (aclp == NULL) + aclp = malloc(cnt * size); + else + aclp = realloc(NULL, cnt * size); + if (aclp != NULL) { + if (path != NULL) + cnt = acl(path, cmd, cnt, aclp); + else + cnt = facl(fd, cmd, cnt, aclp); + } + } else { + free(aclp); + aclp = NULL; + break; + } + } + + *aclcnt = cnt; + return (aclp); +} + +/* + * Check if acl is trivial + * This is a FreeBSD acl_is_trivial_np() implementation for Solaris + */ +static int +sun_acl_is_trivial(void *aclp, int aclcnt, mode_t mode, int is_nfs4, + int is_dir, int *trivialp) +{ +#if ARCHIVE_ACL_SUNOS_NFS4 + int i, p; + const uint32_t rperm = ACE_READ_DATA; + const uint32_t wperm = ACE_WRITE_DATA | ACE_APPEND_DATA; + const uint32_t eperm = ACE_EXECUTE; + const uint32_t pubset = ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS | + ACE_READ_ACL | ACE_SYNCHRONIZE; + const uint32_t ownset = pubset | ACE_WRITE_ATTRIBUTES | + ACE_WRITE_NAMED_ATTRS | ACE_WRITE_ACL | ACE_WRITE_OWNER; + + ace_t *ace; + ace_t tace[6]; +#endif + + if (aclp == NULL || trivialp == NULL) + return (-1); + + *trivialp = 0; + + /* + * POSIX.1e ACLs marked with ACL_IS_TRIVIAL are compatible with + * FreeBSD acl_is_trivial_np(). On Solaris they have 4 entries, + * including mask. + */ + if (!is_nfs4) { + if (aclcnt == 4) + *trivialp = 1; + return (0); + } + +#if ARCHIVE_ACL_SUNOS_NFS4 + /* + * Continue with checking NFSv4 ACLs + * + * Create list of trivial ace's to be compared + */ + + /* owner@ allow pre */ + tace[0].a_flags = ACE_OWNER; + tace[0].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; + tace[0].a_access_mask = 0; + + /* owner@ deny */ + tace[1].a_flags = ACE_OWNER; + tace[1].a_type = ACE_ACCESS_DENIED_ACE_TYPE; + tace[1].a_access_mask = 0; + + /* group@ deny */ + tace[2].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP; + tace[2].a_type = ACE_ACCESS_DENIED_ACE_TYPE; + tace[2].a_access_mask = 0; + + /* owner@ allow */ + tace[3].a_flags = ACE_OWNER; + tace[3].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; + tace[3].a_access_mask = ownset; + + /* group@ allow */ + tace[4].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP; + tace[4].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; + tace[4].a_access_mask = pubset; + + /* everyone@ allow */ + tace[5].a_flags = ACE_EVERYONE; + tace[5].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; + tace[5].a_access_mask = pubset; + + /* Permissions for everyone@ */ + if (mode & 0004) + tace[5].a_access_mask |= rperm; + if (mode & 0002) + tace[5].a_access_mask |= wperm; + if (mode & 0001) + tace[5].a_access_mask |= eperm; + + /* Permissions for group@ */ + if (mode & 0040) + tace[4].a_access_mask |= rperm; + else if (mode & 0004) + tace[2].a_access_mask |= rperm; + if (mode & 0020) + tace[4].a_access_mask |= wperm; + else if (mode & 0002) + tace[2].a_access_mask |= wperm; + if (mode & 0010) + tace[4].a_access_mask |= eperm; + else if (mode & 0001) + tace[2].a_access_mask |= eperm; + + /* Permissions for owner@ */ + if (mode & 0400) { + tace[3].a_access_mask |= rperm; + if (!(mode & 0040) && (mode & 0004)) + tace[0].a_access_mask |= rperm; + } else if ((mode & 0040) || (mode & 0004)) + tace[1].a_access_mask |= rperm; + if (mode & 0200) { + tace[3].a_access_mask |= wperm; + if (!(mode & 0020) && (mode & 0002)) + tace[0].a_access_mask |= wperm; + } else if ((mode & 0020) || (mode & 0002)) + tace[1].a_access_mask |= wperm; + if (mode & 0100) { + tace[3].a_access_mask |= eperm; + if (!(mode & 0010) && (mode & 0001)) + tace[0].a_access_mask |= eperm; + } else if ((mode & 0010) || (mode & 0001)) + tace[1].a_access_mask |= eperm; + + /* Check if the acl count matches */ + p = 3; + for (i = 0; i < 3; i++) { + if (tace[i].a_access_mask != 0) + p++; + } + if (aclcnt != p) + return (0); + + p = 0; + for (i = 0; i < 6; i++) { + if (tace[i].a_access_mask != 0) { + ace = &((ace_t *)aclp)[p]; + /* + * Illumos added ACE_DELETE_CHILD to write perms for + * directories. We have to check against that, too. + */ + if (ace->a_flags != tace[i].a_flags || + ace->a_type != tace[i].a_type || + (ace->a_access_mask != tace[i].a_access_mask && + (!is_dir || (tace[i].a_access_mask & wperm) == 0 || + ace->a_access_mask != + (tace[i].a_access_mask | ACE_DELETE_CHILD)))) + return (0); + p++; + } + } + + *trivialp = 1; +#else /* !ARCHIVE_ACL_SUNOS_NFS4 */ + (void)is_dir; /* UNUSED */ + (void)aclp; /* UNUSED */ +#endif /* !ARCHIVE_ACL_SUNOS_NFS4 */ + return (0); +} + +/* + * Translate Solaris POSIX.1e and NFSv4 ACLs into libarchive internal ACL + */ +static int +translate_acl(struct archive_read_disk *a, + struct archive_entry *entry, void *aclp, int aclcnt, + int default_entry_acl_type) +{ + int e, i; + int ae_id, ae_tag, ae_perm; + int entry_acl_type; + const char *ae_name; + aclent_t *aclent; +#if ARCHIVE_ACL_SUNOS_NFS4 + ace_t *ace; +#endif + + if (aclcnt <= 0) + return (ARCHIVE_OK); + + for (e = 0; e < aclcnt; e++) { + ae_name = NULL; + ae_tag = 0; + ae_perm = 0; + +#if ARCHIVE_ACL_SUNOS_NFS4 + if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + ace = &((ace_t *)aclp)[e]; + ae_id = ace->a_who; + + switch(ace->a_type) { + case ACE_ACCESS_ALLOWED_ACE_TYPE: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; + break; + case ACE_ACCESS_DENIED_ACE_TYPE: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY; + break; + case ACE_SYSTEM_AUDIT_ACE_TYPE: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; + break; + case ACE_SYSTEM_ALARM_ACE_TYPE: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM; + break; + default: + /* Unknown entry type, skip */ + continue; + } + + if ((ace->a_flags & ACE_OWNER) != 0) + ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + else if ((ace->a_flags & ACE_GROUP) != 0) + ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + else if ((ace->a_flags & ACE_EVERYONE) != 0) + ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE; + else if ((ace->a_flags & ACE_IDENTIFIER_GROUP) != 0) { + ae_tag = ARCHIVE_ENTRY_ACL_GROUP; + ae_name = archive_read_disk_gname(&a->archive, + ae_id); + } else { + ae_tag = ARCHIVE_ENTRY_ACL_USER; + ae_name = archive_read_disk_uname(&a->archive, + ae_id); + } + + for (i = 0; i < acl_nfs4_flag_map_size; ++i) { + if ((ace->a_flags & + acl_nfs4_flag_map[i].p_perm) != 0) + ae_perm |= acl_nfs4_flag_map[i].a_perm; + } + + for (i = 0; i < acl_nfs4_perm_map_size; ++i) { + if ((ace->a_access_mask & + acl_nfs4_perm_map[i].p_perm) != 0) + ae_perm |= acl_nfs4_perm_map[i].a_perm; + } + } else +#endif /* ARCHIVE_ACL_SUNOS_NFS4 */ + if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) { + aclent = &((aclent_t *)aclp)[e]; + if ((aclent->a_type & ACL_DEFAULT) != 0) + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT; + else + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; + ae_id = aclent->a_id; + + switch(aclent->a_type) { + case DEF_USER: + case USER: + ae_name = archive_read_disk_uname(&a->archive, + ae_id); + ae_tag = ARCHIVE_ENTRY_ACL_USER; + break; + case DEF_GROUP: + case GROUP: + ae_name = archive_read_disk_gname(&a->archive, + ae_id); + ae_tag = ARCHIVE_ENTRY_ACL_GROUP; + break; + case DEF_CLASS_OBJ: + case CLASS_OBJ: + ae_tag = ARCHIVE_ENTRY_ACL_MASK; + break; + case DEF_USER_OBJ: + case USER_OBJ: + ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + break; + case DEF_GROUP_OBJ: + case GROUP_OBJ: + ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + break; + case DEF_OTHER_OBJ: + case OTHER_OBJ: + ae_tag = ARCHIVE_ENTRY_ACL_OTHER; + break; + default: + /* Unknown tag type, skip */ + continue; + } + + for (i = 0; i < acl_posix_perm_map_size; ++i) { + if ((aclent->a_perm & + acl_posix_perm_map[i].p_perm) != 0) + ae_perm |= acl_posix_perm_map[i].a_perm; + } + } else + return (ARCHIVE_WARN); + + archive_entry_acl_add_entry(entry, entry_acl_type, + ae_perm, ae_tag, ae_id, ae_name); + } + return (ARCHIVE_OK); +} + +static int +set_acl(struct archive *a, int fd, const char *name, + struct archive_acl *abstract_acl, + int ae_requested_type, const char *tname) +{ + aclent_t *aclent; +#if ARCHIVE_ACL_SUNOS_NFS4 + ace_t *ace; +#endif + int cmd, e, r; + void *aclp; + int ret; + int ae_type, ae_permset, ae_tag, ae_id; + int perm_map_size; + const acl_perm_map_t *perm_map; + uid_t ae_uid; + gid_t ae_gid; + const char *ae_name; + int entries; + int i; + + ret = ARCHIVE_OK; + entries = archive_acl_reset(abstract_acl, ae_requested_type); + if (entries == 0) + return (ARCHIVE_OK); + + + switch (ae_requested_type) { + case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E: + cmd = SETACL; + aclp = malloc(entries * sizeof(aclent_t)); + break; +#if ARCHIVE_ACL_SUNOS_NFS4 + case ARCHIVE_ENTRY_ACL_TYPE_NFS4: + cmd = ACE_SETACL; + aclp = malloc(entries * sizeof(ace_t)); + + break; +#endif + default: + errno = ENOENT; + archive_set_error(a, errno, "Unsupported ACL type"); + return (ARCHIVE_FAILED); + } + + if (aclp == NULL) { + archive_set_error(a, errno, + "Can't allocate memory for acl buffer"); + return (ARCHIVE_FAILED); + } + + e = 0; + + while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type, + &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) { + aclent = NULL; +#if ARCHIVE_ACL_SUNOS_NFS4 + ace = NULL; +#endif + if (cmd == SETACL) { + aclent = &((aclent_t *)aclp)[e]; + aclent->a_id = -1; + aclent->a_type = 0; + aclent->a_perm = 0; + } +#if ARCHIVE_ACL_SUNOS_NFS4 + else { /* cmd == ACE_SETACL */ + ace = &((ace_t *)aclp)[e]; + ace->a_who = -1; + ace->a_access_mask = 0; + ace->a_flags = 0; + } +#endif /* ARCHIVE_ACL_SUNOS_NFS4 */ + + switch (ae_tag) { + case ARCHIVE_ENTRY_ACL_USER: + ae_uid = archive_write_disk_uid(a, ae_name, ae_id); + if (aclent != NULL) { + aclent->a_id = ae_uid; + aclent->a_type |= USER; + } +#if ARCHIVE_ACL_SUNOS_NFS4 + else { + ace->a_who = ae_uid; + } +#endif + break; + case ARCHIVE_ENTRY_ACL_GROUP: + ae_gid = archive_write_disk_gid(a, ae_name, ae_id); + if (aclent != NULL) { + aclent->a_id = ae_gid; + aclent->a_type |= GROUP; + } +#if ARCHIVE_ACL_SUNOS_NFS4 + else { + ace->a_who = ae_gid; + ace->a_flags |= ACE_IDENTIFIER_GROUP; + } +#endif + break; + case ARCHIVE_ENTRY_ACL_USER_OBJ: + if (aclent != NULL) + aclent->a_type |= USER_OBJ; +#if ARCHIVE_ACL_SUNOS_NFS4 + else { + ace->a_flags |= ACE_OWNER; + } +#endif + break; + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + if (aclent != NULL) + aclent->a_type |= GROUP_OBJ; +#if ARCHIVE_ACL_SUNOS_NFS4 + else { + ace->a_flags |= ACE_GROUP; + ace->a_flags |= ACE_IDENTIFIER_GROUP; + } +#endif + break; + case ARCHIVE_ENTRY_ACL_MASK: + if (aclent != NULL) + aclent->a_type |= CLASS_OBJ; + break; + case ARCHIVE_ENTRY_ACL_OTHER: + if (aclent != NULL) + aclent->a_type |= OTHER_OBJ; + break; +#if ARCHIVE_ACL_SUNOS_NFS4 + case ARCHIVE_ENTRY_ACL_EVERYONE: + if (ace != NULL) + ace->a_flags |= ACE_EVERYONE; + break; +#endif + default: + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unsupported ACL tag"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + r = 0; + switch (ae_type) { +#if ARCHIVE_ACL_SUNOS_NFS4 + case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: + if (ace != NULL) + ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; + else + r = -1; + break; + case ARCHIVE_ENTRY_ACL_TYPE_DENY: + if (ace != NULL) + ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE; + else + r = -1; + break; + case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: + if (ace != NULL) + ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE; + else + r = -1; + break; + case ARCHIVE_ENTRY_ACL_TYPE_ALARM: + if (ace != NULL) + ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE; + else + r = -1; + break; +#endif + case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: + if (aclent == NULL) + r = -1; + break; + case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: + if (aclent != NULL) + aclent->a_type |= ACL_DEFAULT; + else + r = -1; + break; + default: + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unsupported ACL entry type"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + if (r != 0) { + errno = EINVAL; + archive_set_error(a, errno, + "Failed to set ACL entry type"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + +#if ARCHIVE_ACL_SUNOS_NFS4 + if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + perm_map_size = acl_nfs4_perm_map_size; + perm_map = acl_nfs4_perm_map; + } else { +#endif + perm_map_size = acl_posix_perm_map_size; + perm_map = acl_posix_perm_map; +#if ARCHIVE_ACL_SUNOS_NFS4 + } +#endif + for (i = 0; i < perm_map_size; ++i) { + if (ae_permset & perm_map[i].a_perm) { +#if ARCHIVE_ACL_SUNOS_NFS4 + if (ae_requested_type == + ARCHIVE_ENTRY_ACL_TYPE_NFS4) + ace->a_access_mask |= + perm_map[i].p_perm; + else +#endif + aclent->a_perm |= perm_map[i].p_perm; + } + } + +#if ARCHIVE_ACL_SUNOS_NFS4 + if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + for (i = 0; i < acl_nfs4_flag_map_size; ++i) { + if (ae_permset & acl_nfs4_flag_map[i].a_perm) { + ace->a_flags |= + acl_nfs4_flag_map[i].p_perm; + } + } + } +#endif + e++; + } + + /* Try restoring the ACL through 'fd' if we can. */ + if (fd >= 0) { + if (facl(fd, cmd, entries, aclp) == 0) + ret = ARCHIVE_OK; + else { + if (errno == EOPNOTSUPP) { + /* Filesystem doesn't support ACLs */ + ret = ARCHIVE_OK; + } else { + archive_set_error(a, errno, + "Failed to set acl on fd: %s", tname); + ret = ARCHIVE_WARN; + } + } + } else if (acl(name, cmd, entries, aclp) != 0) { + if (errno == EOPNOTSUPP) { + /* Filesystem doesn't support ACLs */ + ret = ARCHIVE_OK; + } else { + archive_set_error(a, errno, "Failed to set acl: %s", + tname); + ret = ARCHIVE_WARN; + } + } +exit_free: + free(aclp); + return (ret); +} + +int +archive_read_disk_entry_setup_acls(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + const char *accpath; + void *aclp; + int aclcnt; + int r; + + accpath = NULL; + + if (*fd < 0) { + accpath = archive_read_disk_entry_setup_path(a, entry, fd); + if (accpath == NULL) + return (ARCHIVE_WARN); + } + + archive_entry_acl_clear(entry); + + aclp = NULL; + +#if ARCHIVE_ACL_SUNOS_NFS4 + if (*fd >= 0) + aclp = sunacl_get(ACE_GETACL, &aclcnt, *fd, NULL); + else if ((!a->follow_symlinks) + && (archive_entry_filetype(entry) == AE_IFLNK)) + /* We can't get the ACL of a symlink, so we assume it can't + have one. */ + aclp = NULL; + else + aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, accpath); + + if (aclp != NULL && sun_acl_is_trivial(aclp, aclcnt, + archive_entry_mode(entry), 1, S_ISDIR(archive_entry_mode(entry)), + &r) == 0 && r == 1) { + free(aclp); + aclp = NULL; + return (ARCHIVE_OK); + } + + if (aclp != NULL) { + r = translate_acl(a, entry, aclp, aclcnt, + ARCHIVE_ENTRY_ACL_TYPE_NFS4); + free(aclp); + aclp = NULL; + + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, errno, + "Couldn't translate NFSv4 ACLs"); + } + return (r); + } +#endif /* ARCHIVE_ACL_SUNOS_NFS4 */ + + /* Retrieve POSIX.1e ACLs from file. */ + if (*fd >= 0) + aclp = sunacl_get(GETACL, &aclcnt, *fd, NULL); + else if ((!a->follow_symlinks) + && (archive_entry_filetype(entry) == AE_IFLNK)) + /* We can't get the ACL of a symlink, so we assume it can't + have one. */ + aclp = NULL; + else + aclp = sunacl_get(GETACL, &aclcnt, 0, accpath); + + /* Ignore "trivial" ACLs that just mirror the file mode. */ + if (aclp != NULL && sun_acl_is_trivial(aclp, aclcnt, + archive_entry_mode(entry), 0, S_ISDIR(archive_entry_mode(entry)), + &r) == 0 && r == 1) { + free(aclp); + aclp = NULL; + } + + if (aclp != NULL) + { + r = translate_acl(a, entry, aclp, aclcnt, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + free(aclp); + aclp = NULL; + + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, errno, + "Couldn't translate access ACLs"); + return (r); + } + } + + return (ARCHIVE_OK); +} + +int +archive_write_disk_set_acls(struct archive *a, int fd, const char *name, + struct archive_acl *abstract_acl, __LA_MODE_T mode) +{ + int ret = ARCHIVE_OK; + + (void)mode; /* UNUSED */ + + if ((archive_acl_types(abstract_acl) + & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) { + /* Solaris writes POSIX.1e access and default ACLs together */ + ret = set_acl(a, fd, name, abstract_acl, + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, "posix1e"); + + /* Simultaneous POSIX.1e and NFSv4 is not supported */ + return (ret); + } +#if ARCHIVE_ACL_SUNOS_NFS4 + else if ((archive_acl_types(abstract_acl) & + ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + ret = set_acl(a, fd, name, abstract_acl, + ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4"); + } +#endif + return (ret); +} +#endif /* ARCHIVE_ACL_SUNOS */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_endian.h b/dependencies/libarchive-3.4.2/libarchive/archive_endian.h new file mode 100644 index 0000000..e6d3f2c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_endian.h @@ -0,0 +1,195 @@ +/*- + * Copyright (c) 2002 Thomas Moestl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: head/lib/libarchive/archive_endian.h 201085 2009-12-28 02:17:15Z kientzle $ + * + * Borrowed from FreeBSD's + */ + +#ifndef ARCHIVE_ENDIAN_H_INCLUDED +#define ARCHIVE_ENDIAN_H_INCLUDED + +/* Note: This is a purely internal header! */ +/* Do not use this outside of libarchive internal code! */ + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif + +/* + * Disabling inline keyword for compilers known to choke on it: + * - Watcom C++ in C code. (For any version?) + * - SGI MIPSpro + * - Microsoft Visual C++ 6.0 (supposedly newer versions too) + * - IBM VisualAge 6 (XL v6) + * - Sun WorkShop C (SunPro) before 5.9 + */ +#if defined(__WATCOMC__) || defined(__sgi) || defined(__hpux) || defined(__BORLANDC__) +#define inline +#elif defined(__IBMC__) && __IBMC__ < 700 +#define inline +#elif defined(__SUNPRO_C) && __SUNPRO_C < 0x590 +#define inline +#elif defined(_MSC_VER) || defined(__osf__) +#define inline __inline +#endif + +/* Alignment-agnostic encode/decode bytestream to/from little/big endian. */ + +static inline uint16_t +archive_be16dec(const void *pp) +{ + unsigned char const *p = (unsigned char const *)pp; + + /* Store into unsigned temporaries before left shifting, to avoid + promotion to signed int and then left shifting into the sign bit, + which is undefined behaviour. */ + unsigned int p1 = p[1]; + unsigned int p0 = p[0]; + + return ((p0 << 8) | p1); +} + +static inline uint32_t +archive_be32dec(const void *pp) +{ + unsigned char const *p = (unsigned char const *)pp; + + /* Store into unsigned temporaries before left shifting, to avoid + promotion to signed int and then left shifting into the sign bit, + which is undefined behaviour. */ + unsigned int p3 = p[3]; + unsigned int p2 = p[2]; + unsigned int p1 = p[1]; + unsigned int p0 = p[0]; + + return ((p0 << 24) | (p1 << 16) | (p2 << 8) | p3); +} + +static inline uint64_t +archive_be64dec(const void *pp) +{ + unsigned char const *p = (unsigned char const *)pp; + + return (((uint64_t)archive_be32dec(p) << 32) | archive_be32dec(p + 4)); +} + +static inline uint16_t +archive_le16dec(const void *pp) +{ + unsigned char const *p = (unsigned char const *)pp; + + /* Store into unsigned temporaries before left shifting, to avoid + promotion to signed int and then left shifting into the sign bit, + which is undefined behaviour. */ + unsigned int p1 = p[1]; + unsigned int p0 = p[0]; + + return ((p1 << 8) | p0); +} + +static inline uint32_t +archive_le32dec(const void *pp) +{ + unsigned char const *p = (unsigned char const *)pp; + + /* Store into unsigned temporaries before left shifting, to avoid + promotion to signed int and then left shifting into the sign bit, + which is undefined behaviour. */ + unsigned int p3 = p[3]; + unsigned int p2 = p[2]; + unsigned int p1 = p[1]; + unsigned int p0 = p[0]; + + return ((p3 << 24) | (p2 << 16) | (p1 << 8) | p0); +} + +static inline uint64_t +archive_le64dec(const void *pp) +{ + unsigned char const *p = (unsigned char const *)pp; + + return (((uint64_t)archive_le32dec(p + 4) << 32) | archive_le32dec(p)); +} + +static inline void +archive_be16enc(void *pp, uint16_t u) +{ + unsigned char *p = (unsigned char *)pp; + + p[0] = (u >> 8) & 0xff; + p[1] = u & 0xff; +} + +static inline void +archive_be32enc(void *pp, uint32_t u) +{ + unsigned char *p = (unsigned char *)pp; + + p[0] = (u >> 24) & 0xff; + p[1] = (u >> 16) & 0xff; + p[2] = (u >> 8) & 0xff; + p[3] = u & 0xff; +} + +static inline void +archive_be64enc(void *pp, uint64_t u) +{ + unsigned char *p = (unsigned char *)pp; + + archive_be32enc(p, (uint32_t)(u >> 32)); + archive_be32enc(p + 4, (uint32_t)(u & 0xffffffff)); +} + +static inline void +archive_le16enc(void *pp, uint16_t u) +{ + unsigned char *p = (unsigned char *)pp; + + p[0] = u & 0xff; + p[1] = (u >> 8) & 0xff; +} + +static inline void +archive_le32enc(void *pp, uint32_t u) +{ + unsigned char *p = (unsigned char *)pp; + + p[0] = u & 0xff; + p[1] = (u >> 8) & 0xff; + p[2] = (u >> 16) & 0xff; + p[3] = (u >> 24) & 0xff; +} + +static inline void +archive_le64enc(void *pp, uint64_t u) +{ + unsigned char *p = (unsigned char *)pp; + + archive_le32enc(p, (uint32_t)(u & 0xffffffff)); + archive_le32enc(p + 4, (uint32_t)(u >> 32)); +} + +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_entry.3 b/dependencies/libarchive-3.4.2/libarchive/archive_entry.3 new file mode 100644 index 0000000..2f62a4b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_entry.3 @@ -0,0 +1,149 @@ +.\" Copyright (c) 2003-2007 Tim Kientzle +.\" Copyright (c) 2010 Joerg Sonnenberger +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 2, 2012 +.Dt ARCHIVE_ENTRY 3 +.Os +.Sh NAME +.Nm archive_entry_clear , +.Nm archive_entry_clone , +.Nm archive_entry_free , +.Nm archive_entry_new +.Nd functions for managing archive entry descriptions +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive_entry.h +.Ft "struct archive_entry *" +.Fn archive_entry_clear "struct archive_entry *" +.Ft struct archive_entry * +.Fn archive_entry_clone "struct archive_entry *" +.Ft void +.Fn archive_entry_free "struct archive_entry *" +.Ft struct archive_entry * +.Fn archive_entry_new "void" +.Sh DESCRIPTION +These functions create and manipulate data objects that +represent entries within an archive. +You can think of a +.Tn struct archive_entry +as a heavy-duty version of +.Tn struct stat : +it includes everything from +.Tn struct stat +plus associated pathname, textual group and user names, etc. +These objects are used by +.Xr libarchive 3 +to represent the metadata associated with a particular +entry in an archive. +.Ss Create and Destroy +There are functions to allocate, destroy, clear, and copy +.Va archive_entry +objects: +.Bl -tag -compact -width indent +.It Fn archive_entry_clear +Erases the object, resetting all internal fields to the +same state as a newly-created object. +This is provided to allow you to quickly recycle objects +without thrashing the heap. +.It Fn archive_entry_clone +A deep copy operation; all text fields are duplicated. +.It Fn archive_entry_free +Releases the +.Tn struct archive_entry +object. +.It Fn archive_entry_new +Allocate and return a blank +.Tn struct archive_entry +object. +.El +.Ss Function groups +Due to high number of functions, the accessor functions can be found in +man pages grouped by the purpose. +.Bl -tag -width ".Xr archive_entry_perms 3" +.It Xr archive_entry_acl 3 +Access Control List manipulation +.It Xr archive_entry_paths 3 +Path name manipulation +.It Xr archive_entry_perms 3 +User, group and mode manipulation +.It Xr archive_entry_stat 3 +Functions not in the other groups and copying to/from +.Vt struct stat . +.It Xr archive_entry_time 3 +Time field manipulation +.El +.Pp +Most of the functions set or read entries in an object. +Such functions have one of the following forms: +.Bl -tag -compact -width indent +.It Fn archive_entry_set_XXXX +Stores the provided data in the object. +In particular, for strings, the pointer is stored, +not the referenced string. +.It Fn archive_entry_copy_XXXX +As above, except that the referenced data is copied +into the object. +.It Fn archive_entry_XXXX +Returns the specified data. +In the case of strings, a const-qualified pointer to +the string is returned. +.El +String data can be set or accessed as wide character strings +or normal +.Va char +strings. +The functions that use wide character strings are suffixed with +.Cm _w . +Note that these are different representations of the same data: +For example, if you store a narrow string and read the corresponding +wide string, the object will transparently convert formats +using the current locale. +Similarly, if you store a wide string and then store a +narrow string for the same data, the previously-set wide string will +be discarded in favor of the new data. +.\" .Sh EXAMPLE +.\" .Sh RETURN VALUES +.\" .Sh ERRORS +.Sh SEE ALSO +.Xr archive_entry_acl 3 , +.Xr archive_entry_paths 3 , +.Xr archive_entry_perms 3 , +.Xr archive_entry_time 3 , +.Xr libarchive 3 +.Sh HISTORY +The +.Nm libarchive +library first appeared in +.Fx 5.3 . +.Sh AUTHORS +.An -nosplit +The +.Nm libarchive +library was written by +.An Tim Kientzle Aq kientzle@acm.org . +.\" .Sh BUGS diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_entry.c b/dependencies/libarchive-3.4.2/libarchive/archive_entry.c new file mode 100644 index 0000000..a15e98c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_entry.c @@ -0,0 +1,2066 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2016 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_entry.c 201096 2009-12-28 02:41:27Z kientzle $"); + +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#if MAJOR_IN_MKDEV +#include +#define HAVE_MAJOR +#elif MAJOR_IN_SYSMACROS +#include +#define HAVE_MAJOR +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_LINUX_FS_H +#include /* for Linux file flags */ +#endif +/* + * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h. + * As the include guards don't agree, the order of include is important. + */ +#ifdef HAVE_LINUX_EXT2_FS_H +#include /* for Linux file flags */ +#endif +#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__) +#include /* for Linux file flags */ +#endif +#include +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_WCHAR_H +#include +#endif + +#include "archive.h" +#include "archive_acl_private.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_private.h" +#include "archive_entry_private.h" + +#if !defined(HAVE_MAJOR) && !defined(major) +/* Replacement for major/minor/makedev. */ +#define major(x) ((int)(0x00ff & ((x) >> 8))) +#define minor(x) ((int)(0xffff00ff & (x))) +#define makedev(maj,min) ((0xff00 & ((maj)<<8)) | (0xffff00ff & (min))) +#endif + +/* Play games to come up with a suitable makedev() definition. */ +#ifdef __QNXNTO__ +/* QNX. */ +#include +#define ae_makedev(maj, min) makedev(ND_LOCAL_NODE, (maj), (min)) +#elif defined makedev +/* There's a "makedev" macro. */ +#define ae_makedev(maj, min) makedev((maj), (min)) +#elif defined mkdev || ((defined _WIN32 || defined __WIN32__) && !defined(__CYGWIN__)) +/* Windows. */ +#define ae_makedev(maj, min) mkdev((maj), (min)) +#else +/* There's a "makedev" function. */ +#define ae_makedev(maj, min) makedev((maj), (min)) +#endif + +/* + * This adjustment is needed to support the following idiom for adding + * 1000ns to the stored time: + * archive_entry_set_atime(archive_entry_atime(), + * archive_entry_atime_nsec() + 1000) + * The additional if() here compensates for ambiguity in the C standard, + * which permits two possible interpretations of a % b when a is negative. + */ +#define FIX_NS(t,ns) \ + do { \ + t += ns / 1000000000; \ + ns %= 1000000000; \ + if (ns < 0) { --t; ns += 1000000000; } \ + } while (0) + +static char * ae_fflagstostr(unsigned long bitset, unsigned long bitclear); +static const wchar_t *ae_wcstofflags(const wchar_t *stringp, + unsigned long *setp, unsigned long *clrp); +static const char *ae_strtofflags(const char *stringp, + unsigned long *setp, unsigned long *clrp); + +#ifndef HAVE_WCSCPY +static wchar_t * wcscpy(wchar_t *s1, const wchar_t *s2) +{ + wchar_t *dest = s1; + while ((*s1 = *s2) != L'\0') + ++s1, ++s2; + return dest; +} +#endif +#ifndef HAVE_WCSLEN +static size_t wcslen(const wchar_t *s) +{ + const wchar_t *p = s; + while (*p != L'\0') + ++p; + return p - s; +} +#endif +#ifndef HAVE_WMEMCMP +/* Good enough for simple equality testing, but not for sorting. */ +#define wmemcmp(a,b,i) memcmp((a), (b), (i) * sizeof(wchar_t)) +#endif + +/**************************************************************************** + * + * Public Interface + * + ****************************************************************************/ + +struct archive_entry * +archive_entry_clear(struct archive_entry *entry) +{ + if (entry == NULL) + return (NULL); + archive_mstring_clean(&entry->ae_fflags_text); + archive_mstring_clean(&entry->ae_gname); + archive_mstring_clean(&entry->ae_hardlink); + archive_mstring_clean(&entry->ae_pathname); + archive_mstring_clean(&entry->ae_sourcepath); + archive_mstring_clean(&entry->ae_symlink); + archive_mstring_clean(&entry->ae_uname); + archive_entry_copy_mac_metadata(entry, NULL, 0); + archive_acl_clear(&entry->acl); + archive_entry_xattr_clear(entry); + archive_entry_sparse_clear(entry); + free(entry->stat); + entry->ae_symlink_type = AE_SYMLINK_TYPE_UNDEFINED; + memset(entry, 0, sizeof(*entry)); + return entry; +} + +struct archive_entry * +archive_entry_clone(struct archive_entry *entry) +{ + struct archive_entry *entry2; + struct ae_xattr *xp; + struct ae_sparse *sp; + size_t s; + const void *p; + + /* Allocate new structure and copy over all of the fields. */ + /* TODO: Should we copy the archive over? Or require a new archive + * as an argument? */ + entry2 = archive_entry_new2(entry->archive); + if (entry2 == NULL) + return (NULL); + entry2->ae_stat = entry->ae_stat; + entry2->ae_fflags_set = entry->ae_fflags_set; + entry2->ae_fflags_clear = entry->ae_fflags_clear; + + /* TODO: XXX If clone can have a different archive, what do we do here if + * character sets are different? XXX */ + archive_mstring_copy(&entry2->ae_fflags_text, &entry->ae_fflags_text); + archive_mstring_copy(&entry2->ae_gname, &entry->ae_gname); + archive_mstring_copy(&entry2->ae_hardlink, &entry->ae_hardlink); + archive_mstring_copy(&entry2->ae_pathname, &entry->ae_pathname); + archive_mstring_copy(&entry2->ae_sourcepath, &entry->ae_sourcepath); + archive_mstring_copy(&entry2->ae_symlink, &entry->ae_symlink); + entry2->ae_set = entry->ae_set; + archive_mstring_copy(&entry2->ae_uname, &entry->ae_uname); + + /* Copy symlink type */ + entry2->ae_symlink_type = entry->ae_symlink_type; + + /* Copy encryption status */ + entry2->encryption = entry->encryption; + + /* Copy ACL data over. */ + archive_acl_copy(&entry2->acl, &entry->acl); + + /* Copy Mac OS metadata. */ + p = archive_entry_mac_metadata(entry, &s); + archive_entry_copy_mac_metadata(entry2, p, s); + + /* Copy xattr data over. */ + xp = entry->xattr_head; + while (xp != NULL) { + archive_entry_xattr_add_entry(entry2, + xp->name, xp->value, xp->size); + xp = xp->next; + } + + /* Copy sparse data over. */ + sp = entry->sparse_head; + while (sp != NULL) { + archive_entry_sparse_add_entry(entry2, + sp->offset, sp->length); + sp = sp->next; + } + + return (entry2); +} + +void +archive_entry_free(struct archive_entry *entry) +{ + archive_entry_clear(entry); + free(entry); +} + +struct archive_entry * +archive_entry_new(void) +{ + return archive_entry_new2(NULL); +} + +struct archive_entry * +archive_entry_new2(struct archive *a) +{ + struct archive_entry *entry; + + entry = (struct archive_entry *)calloc(1, sizeof(*entry)); + if (entry == NULL) + return (NULL); + entry->archive = a; + entry->ae_symlink_type = AE_SYMLINK_TYPE_UNDEFINED; + return (entry); +} + +/* + * Functions for reading fields from an archive_entry. + */ + +time_t +archive_entry_atime(struct archive_entry *entry) +{ + return (entry->ae_stat.aest_atime); +} + +long +archive_entry_atime_nsec(struct archive_entry *entry) +{ + return (entry->ae_stat.aest_atime_nsec); +} + +int +archive_entry_atime_is_set(struct archive_entry *entry) +{ + return (entry->ae_set & AE_SET_ATIME); +} + +time_t +archive_entry_birthtime(struct archive_entry *entry) +{ + return (entry->ae_stat.aest_birthtime); +} + +long +archive_entry_birthtime_nsec(struct archive_entry *entry) +{ + return (entry->ae_stat.aest_birthtime_nsec); +} + +int +archive_entry_birthtime_is_set(struct archive_entry *entry) +{ + return (entry->ae_set & AE_SET_BIRTHTIME); +} + +time_t +archive_entry_ctime(struct archive_entry *entry) +{ + return (entry->ae_stat.aest_ctime); +} + +int +archive_entry_ctime_is_set(struct archive_entry *entry) +{ + return (entry->ae_set & AE_SET_CTIME); +} + +long +archive_entry_ctime_nsec(struct archive_entry *entry) +{ + return (entry->ae_stat.aest_ctime_nsec); +} + +dev_t +archive_entry_dev(struct archive_entry *entry) +{ + if (entry->ae_stat.aest_dev_is_broken_down) + return ae_makedev(entry->ae_stat.aest_devmajor, + entry->ae_stat.aest_devminor); + else + return (entry->ae_stat.aest_dev); +} + +int +archive_entry_dev_is_set(struct archive_entry *entry) +{ + return (entry->ae_set & AE_SET_DEV); +} + +dev_t +archive_entry_devmajor(struct archive_entry *entry) +{ + if (entry->ae_stat.aest_dev_is_broken_down) + return (entry->ae_stat.aest_devmajor); + else + return major(entry->ae_stat.aest_dev); +} + +dev_t +archive_entry_devminor(struct archive_entry *entry) +{ + if (entry->ae_stat.aest_dev_is_broken_down) + return (entry->ae_stat.aest_devminor); + else + return minor(entry->ae_stat.aest_dev); +} + +mode_t +archive_entry_filetype(struct archive_entry *entry) +{ + return (AE_IFMT & entry->acl.mode); +} + +void +archive_entry_fflags(struct archive_entry *entry, + unsigned long *set, unsigned long *clear) +{ + *set = entry->ae_fflags_set; + *clear = entry->ae_fflags_clear; +} + +/* + * Note: if text was provided, this just returns that text. If you + * really need the text to be rebuilt in a canonical form, set the + * text, ask for the bitmaps, then set the bitmaps. (Setting the + * bitmaps clears any stored text.) This design is deliberate: if + * we're editing archives, we don't want to discard flags just because + * they aren't supported on the current system. The bitmap<->text + * conversions are platform-specific (see below). + */ +const char * +archive_entry_fflags_text(struct archive_entry *entry) +{ + const char *f; + char *p; + + if (archive_mstring_get_mbs(entry->archive, + &entry->ae_fflags_text, &f) == 0) { + if (f != NULL) + return (f); + } else if (errno == ENOMEM) + __archive_errx(1, "No memory"); + + if (entry->ae_fflags_set == 0 && entry->ae_fflags_clear == 0) + return (NULL); + + p = ae_fflagstostr(entry->ae_fflags_set, entry->ae_fflags_clear); + if (p == NULL) + return (NULL); + + archive_mstring_copy_mbs(&entry->ae_fflags_text, p); + free(p); + if (archive_mstring_get_mbs(entry->archive, + &entry->ae_fflags_text, &f) == 0) + return (f); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (NULL); +} + +la_int64_t +archive_entry_gid(struct archive_entry *entry) +{ + return (entry->ae_stat.aest_gid); +} + +const char * +archive_entry_gname(struct archive_entry *entry) +{ + const char *p; + if (archive_mstring_get_mbs(entry->archive, &entry->ae_gname, &p) == 0) + return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (NULL); +} + +const char * +archive_entry_gname_utf8(struct archive_entry *entry) +{ + const char *p; + if (archive_mstring_get_utf8(entry->archive, &entry->ae_gname, &p) == 0) + return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (NULL); +} + + +const wchar_t * +archive_entry_gname_w(struct archive_entry *entry) +{ + const wchar_t *p; + if (archive_mstring_get_wcs(entry->archive, &entry->ae_gname, &p) == 0) + return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (NULL); +} + +int +_archive_entry_gname_l(struct archive_entry *entry, + const char **p, size_t *len, struct archive_string_conv *sc) +{ + return (archive_mstring_get_mbs_l(&entry->ae_gname, p, len, sc)); +} + +const char * +archive_entry_hardlink(struct archive_entry *entry) +{ + const char *p; + if ((entry->ae_set & AE_SET_HARDLINK) == 0) + return (NULL); + if (archive_mstring_get_mbs( + entry->archive, &entry->ae_hardlink, &p) == 0) + return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (NULL); +} + +const char * +archive_entry_hardlink_utf8(struct archive_entry *entry) +{ + const char *p; + if ((entry->ae_set & AE_SET_HARDLINK) == 0) + return (NULL); + if (archive_mstring_get_utf8( + entry->archive, &entry->ae_hardlink, &p) == 0) + return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (NULL); +} + +const wchar_t * +archive_entry_hardlink_w(struct archive_entry *entry) +{ + const wchar_t *p; + if ((entry->ae_set & AE_SET_HARDLINK) == 0) + return (NULL); + if (archive_mstring_get_wcs( + entry->archive, &entry->ae_hardlink, &p) == 0) + return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (NULL); +} + +int +_archive_entry_hardlink_l(struct archive_entry *entry, + const char **p, size_t *len, struct archive_string_conv *sc) +{ + if ((entry->ae_set & AE_SET_HARDLINK) == 0) { + *p = NULL; + *len = 0; + return (0); + } + return (archive_mstring_get_mbs_l(&entry->ae_hardlink, p, len, sc)); +} + +la_int64_t +archive_entry_ino(struct archive_entry *entry) +{ + return (entry->ae_stat.aest_ino); +} + +int +archive_entry_ino_is_set(struct archive_entry *entry) +{ + return (entry->ae_set & AE_SET_INO); +} + +la_int64_t +archive_entry_ino64(struct archive_entry *entry) +{ + return (entry->ae_stat.aest_ino); +} + +mode_t +archive_entry_mode(struct archive_entry *entry) +{ + return (entry->acl.mode); +} + +time_t +archive_entry_mtime(struct archive_entry *entry) +{ + return (entry->ae_stat.aest_mtime); +} + +long +archive_entry_mtime_nsec(struct archive_entry *entry) +{ + return (entry->ae_stat.aest_mtime_nsec); +} + +int +archive_entry_mtime_is_set(struct archive_entry *entry) +{ + return (entry->ae_set & AE_SET_MTIME); +} + +unsigned int +archive_entry_nlink(struct archive_entry *entry) +{ + return (entry->ae_stat.aest_nlink); +} + +const char * +archive_entry_pathname(struct archive_entry *entry) +{ + const char *p; + if (archive_mstring_get_mbs( + entry->archive, &entry->ae_pathname, &p) == 0) + return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (NULL); +} + +const char * +archive_entry_pathname_utf8(struct archive_entry *entry) +{ + const char *p; + if (archive_mstring_get_utf8( + entry->archive, &entry->ae_pathname, &p) == 0) + return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (NULL); +} + +const wchar_t * +archive_entry_pathname_w(struct archive_entry *entry) +{ + const wchar_t *p; + if (archive_mstring_get_wcs( + entry->archive, &entry->ae_pathname, &p) == 0) + return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (NULL); +} + +int +_archive_entry_pathname_l(struct archive_entry *entry, + const char **p, size_t *len, struct archive_string_conv *sc) +{ + return (archive_mstring_get_mbs_l(&entry->ae_pathname, p, len, sc)); +} + +mode_t +archive_entry_perm(struct archive_entry *entry) +{ + return (~AE_IFMT & entry->acl.mode); +} + +dev_t +archive_entry_rdev(struct archive_entry *entry) +{ + if (entry->ae_stat.aest_rdev_is_broken_down) + return ae_makedev(entry->ae_stat.aest_rdevmajor, + entry->ae_stat.aest_rdevminor); + else + return (entry->ae_stat.aest_rdev); +} + +dev_t +archive_entry_rdevmajor(struct archive_entry *entry) +{ + if (entry->ae_stat.aest_rdev_is_broken_down) + return (entry->ae_stat.aest_rdevmajor); + else + return major(entry->ae_stat.aest_rdev); +} + +dev_t +archive_entry_rdevminor(struct archive_entry *entry) +{ + if (entry->ae_stat.aest_rdev_is_broken_down) + return (entry->ae_stat.aest_rdevminor); + else + return minor(entry->ae_stat.aest_rdev); +} + +la_int64_t +archive_entry_size(struct archive_entry *entry) +{ + return (entry->ae_stat.aest_size); +} + +int +archive_entry_size_is_set(struct archive_entry *entry) +{ + return (entry->ae_set & AE_SET_SIZE); +} + +const char * +archive_entry_sourcepath(struct archive_entry *entry) +{ + const char *p; + if (archive_mstring_get_mbs( + entry->archive, &entry->ae_sourcepath, &p) == 0) + return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (NULL); +} + +const wchar_t * +archive_entry_sourcepath_w(struct archive_entry *entry) +{ + const wchar_t *p; + if (archive_mstring_get_wcs( + entry->archive, &entry->ae_sourcepath, &p) == 0) + return (p); + return (NULL); +} + +const char * +archive_entry_symlink(struct archive_entry *entry) +{ + const char *p; + if ((entry->ae_set & AE_SET_SYMLINK) == 0) + return (NULL); + if (archive_mstring_get_mbs( + entry->archive, &entry->ae_symlink, &p) == 0) + return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (NULL); +} + +int +archive_entry_symlink_type(struct archive_entry *entry) +{ + return (entry->ae_symlink_type); +} + +const char * +archive_entry_symlink_utf8(struct archive_entry *entry) +{ + const char *p; + if ((entry->ae_set & AE_SET_SYMLINK) == 0) + return (NULL); + if (archive_mstring_get_utf8( + entry->archive, &entry->ae_symlink, &p) == 0) + return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (NULL); +} + +const wchar_t * +archive_entry_symlink_w(struct archive_entry *entry) +{ + const wchar_t *p; + if ((entry->ae_set & AE_SET_SYMLINK) == 0) + return (NULL); + if (archive_mstring_get_wcs( + entry->archive, &entry->ae_symlink, &p) == 0) + return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (NULL); +} + +int +_archive_entry_symlink_l(struct archive_entry *entry, + const char **p, size_t *len, struct archive_string_conv *sc) +{ + if ((entry->ae_set & AE_SET_SYMLINK) == 0) { + *p = NULL; + *len = 0; + return (0); + } + return (archive_mstring_get_mbs_l( &entry->ae_symlink, p, len, sc)); +} + +la_int64_t +archive_entry_uid(struct archive_entry *entry) +{ + return (entry->ae_stat.aest_uid); +} + +const char * +archive_entry_uname(struct archive_entry *entry) +{ + const char *p; + if (archive_mstring_get_mbs(entry->archive, &entry->ae_uname, &p) == 0) + return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (NULL); +} + +const char * +archive_entry_uname_utf8(struct archive_entry *entry) +{ + const char *p; + if (archive_mstring_get_utf8(entry->archive, &entry->ae_uname, &p) == 0) + return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (NULL); +} + +const wchar_t * +archive_entry_uname_w(struct archive_entry *entry) +{ + const wchar_t *p; + if (archive_mstring_get_wcs(entry->archive, &entry->ae_uname, &p) == 0) + return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (NULL); +} + +int +_archive_entry_uname_l(struct archive_entry *entry, + const char **p, size_t *len, struct archive_string_conv *sc) +{ + return (archive_mstring_get_mbs_l(&entry->ae_uname, p, len, sc)); +} + +int +archive_entry_is_data_encrypted(struct archive_entry *entry) +{ + return ((entry->encryption & AE_ENCRYPTION_DATA) == AE_ENCRYPTION_DATA); +} + +int +archive_entry_is_metadata_encrypted(struct archive_entry *entry) +{ + return ((entry->encryption & AE_ENCRYPTION_METADATA) == AE_ENCRYPTION_METADATA); +} + +int +archive_entry_is_encrypted(struct archive_entry *entry) +{ + return (entry->encryption & (AE_ENCRYPTION_DATA|AE_ENCRYPTION_METADATA)); +} + +/* + * Functions to set archive_entry properties. + */ + +void +archive_entry_set_filetype(struct archive_entry *entry, unsigned int type) +{ + entry->stat_valid = 0; + entry->acl.mode &= ~AE_IFMT; + entry->acl.mode |= AE_IFMT & type; +} + +void +archive_entry_set_fflags(struct archive_entry *entry, + unsigned long set, unsigned long clear) +{ + archive_mstring_clean(&entry->ae_fflags_text); + entry->ae_fflags_set = set; + entry->ae_fflags_clear = clear; +} + +const char * +archive_entry_copy_fflags_text(struct archive_entry *entry, + const char *flags) +{ + archive_mstring_copy_mbs(&entry->ae_fflags_text, flags); + return (ae_strtofflags(flags, + &entry->ae_fflags_set, &entry->ae_fflags_clear)); +} + +const wchar_t * +archive_entry_copy_fflags_text_w(struct archive_entry *entry, + const wchar_t *flags) +{ + archive_mstring_copy_wcs(&entry->ae_fflags_text, flags); + return (ae_wcstofflags(flags, + &entry->ae_fflags_set, &entry->ae_fflags_clear)); +} + +void +archive_entry_set_gid(struct archive_entry *entry, la_int64_t g) +{ + entry->stat_valid = 0; + entry->ae_stat.aest_gid = g; +} + +void +archive_entry_set_gname(struct archive_entry *entry, const char *name) +{ + archive_mstring_copy_mbs(&entry->ae_gname, name); +} + +void +archive_entry_set_gname_utf8(struct archive_entry *entry, const char *name) +{ + archive_mstring_copy_utf8(&entry->ae_gname, name); +} + +void +archive_entry_copy_gname(struct archive_entry *entry, const char *name) +{ + archive_mstring_copy_mbs(&entry->ae_gname, name); +} + +void +archive_entry_copy_gname_w(struct archive_entry *entry, const wchar_t *name) +{ + archive_mstring_copy_wcs(&entry->ae_gname, name); +} + +int +archive_entry_update_gname_utf8(struct archive_entry *entry, const char *name) +{ + if (archive_mstring_update_utf8(entry->archive, + &entry->ae_gname, name) == 0) + return (1); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (0); +} + +int +_archive_entry_copy_gname_l(struct archive_entry *entry, + const char *name, size_t len, struct archive_string_conv *sc) +{ + return (archive_mstring_copy_mbs_len_l(&entry->ae_gname, name, len, sc)); +} + +void +archive_entry_set_ino(struct archive_entry *entry, la_int64_t ino) +{ + entry->stat_valid = 0; + entry->ae_set |= AE_SET_INO; + entry->ae_stat.aest_ino = ino; +} + +void +archive_entry_set_ino64(struct archive_entry *entry, la_int64_t ino) +{ + entry->stat_valid = 0; + entry->ae_set |= AE_SET_INO; + entry->ae_stat.aest_ino = ino; +} + +void +archive_entry_set_hardlink(struct archive_entry *entry, const char *target) +{ + archive_mstring_copy_mbs(&entry->ae_hardlink, target); + if (target != NULL) + entry->ae_set |= AE_SET_HARDLINK; + else + entry->ae_set &= ~AE_SET_HARDLINK; +} + +void +archive_entry_set_hardlink_utf8(struct archive_entry *entry, const char *target) +{ + archive_mstring_copy_utf8(&entry->ae_hardlink, target); + if (target != NULL) + entry->ae_set |= AE_SET_HARDLINK; + else + entry->ae_set &= ~AE_SET_HARDLINK; +} + +void +archive_entry_copy_hardlink(struct archive_entry *entry, const char *target) +{ + archive_mstring_copy_mbs(&entry->ae_hardlink, target); + if (target != NULL) + entry->ae_set |= AE_SET_HARDLINK; + else + entry->ae_set &= ~AE_SET_HARDLINK; +} + +void +archive_entry_copy_hardlink_w(struct archive_entry *entry, const wchar_t *target) +{ + archive_mstring_copy_wcs(&entry->ae_hardlink, target); + if (target != NULL) + entry->ae_set |= AE_SET_HARDLINK; + else + entry->ae_set &= ~AE_SET_HARDLINK; +} + +int +archive_entry_update_hardlink_utf8(struct archive_entry *entry, const char *target) +{ + if (target != NULL) + entry->ae_set |= AE_SET_HARDLINK; + else + entry->ae_set &= ~AE_SET_HARDLINK; + if (archive_mstring_update_utf8(entry->archive, + &entry->ae_hardlink, target) == 0) + return (1); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (0); +} + +int +_archive_entry_copy_hardlink_l(struct archive_entry *entry, + const char *target, size_t len, struct archive_string_conv *sc) +{ + int r; + + r = archive_mstring_copy_mbs_len_l(&entry->ae_hardlink, + target, len, sc); + if (target != NULL && r == 0) + entry->ae_set |= AE_SET_HARDLINK; + else + entry->ae_set &= ~AE_SET_HARDLINK; + return (r); +} + +void +archive_entry_set_atime(struct archive_entry *entry, time_t t, long ns) +{ + FIX_NS(t, ns); + entry->stat_valid = 0; + entry->ae_set |= AE_SET_ATIME; + entry->ae_stat.aest_atime = t; + entry->ae_stat.aest_atime_nsec = ns; +} + +void +archive_entry_unset_atime(struct archive_entry *entry) +{ + archive_entry_set_atime(entry, 0, 0); + entry->ae_set &= ~AE_SET_ATIME; +} + +void +archive_entry_set_birthtime(struct archive_entry *entry, time_t t, long ns) +{ + FIX_NS(t, ns); + entry->stat_valid = 0; + entry->ae_set |= AE_SET_BIRTHTIME; + entry->ae_stat.aest_birthtime = t; + entry->ae_stat.aest_birthtime_nsec = ns; +} + +void +archive_entry_unset_birthtime(struct archive_entry *entry) +{ + archive_entry_set_birthtime(entry, 0, 0); + entry->ae_set &= ~AE_SET_BIRTHTIME; +} + +void +archive_entry_set_ctime(struct archive_entry *entry, time_t t, long ns) +{ + FIX_NS(t, ns); + entry->stat_valid = 0; + entry->ae_set |= AE_SET_CTIME; + entry->ae_stat.aest_ctime = t; + entry->ae_stat.aest_ctime_nsec = ns; +} + +void +archive_entry_unset_ctime(struct archive_entry *entry) +{ + archive_entry_set_ctime(entry, 0, 0); + entry->ae_set &= ~AE_SET_CTIME; +} + +void +archive_entry_set_dev(struct archive_entry *entry, dev_t d) +{ + entry->stat_valid = 0; + entry->ae_set |= AE_SET_DEV; + entry->ae_stat.aest_dev_is_broken_down = 0; + entry->ae_stat.aest_dev = d; +} + +void +archive_entry_set_devmajor(struct archive_entry *entry, dev_t m) +{ + entry->stat_valid = 0; + entry->ae_set |= AE_SET_DEV; + entry->ae_stat.aest_dev_is_broken_down = 1; + entry->ae_stat.aest_devmajor = m; +} + +void +archive_entry_set_devminor(struct archive_entry *entry, dev_t m) +{ + entry->stat_valid = 0; + entry->ae_set |= AE_SET_DEV; + entry->ae_stat.aest_dev_is_broken_down = 1; + entry->ae_stat.aest_devminor = m; +} + +/* Set symlink if symlink is already set, else set hardlink. */ +void +archive_entry_set_link(struct archive_entry *entry, const char *target) +{ + if (entry->ae_set & AE_SET_SYMLINK) + archive_mstring_copy_mbs(&entry->ae_symlink, target); + else + archive_mstring_copy_mbs(&entry->ae_hardlink, target); +} + +void +archive_entry_set_link_utf8(struct archive_entry *entry, const char *target) +{ + if (entry->ae_set & AE_SET_SYMLINK) + archive_mstring_copy_utf8(&entry->ae_symlink, target); + else + archive_mstring_copy_utf8(&entry->ae_hardlink, target); +} + +/* Set symlink if symlink is already set, else set hardlink. */ +void +archive_entry_copy_link(struct archive_entry *entry, const char *target) +{ + if (entry->ae_set & AE_SET_SYMLINK) + archive_mstring_copy_mbs(&entry->ae_symlink, target); + else + archive_mstring_copy_mbs(&entry->ae_hardlink, target); +} + +/* Set symlink if symlink is already set, else set hardlink. */ +void +archive_entry_copy_link_w(struct archive_entry *entry, const wchar_t *target) +{ + if (entry->ae_set & AE_SET_SYMLINK) + archive_mstring_copy_wcs(&entry->ae_symlink, target); + else + archive_mstring_copy_wcs(&entry->ae_hardlink, target); +} + +int +archive_entry_update_link_utf8(struct archive_entry *entry, const char *target) +{ + int r; + if (entry->ae_set & AE_SET_SYMLINK) + r = archive_mstring_update_utf8(entry->archive, + &entry->ae_symlink, target); + else + r = archive_mstring_update_utf8(entry->archive, + &entry->ae_hardlink, target); + if (r == 0) + return (1); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (0); +} + +int +_archive_entry_copy_link_l(struct archive_entry *entry, + const char *target, size_t len, struct archive_string_conv *sc) +{ + int r; + + if (entry->ae_set & AE_SET_SYMLINK) + r = archive_mstring_copy_mbs_len_l(&entry->ae_symlink, + target, len, sc); + else + r = archive_mstring_copy_mbs_len_l(&entry->ae_hardlink, + target, len, sc); + return (r); +} + +void +archive_entry_set_mode(struct archive_entry *entry, mode_t m) +{ + entry->stat_valid = 0; + entry->acl.mode = m; +} + +void +archive_entry_set_mtime(struct archive_entry *entry, time_t t, long ns) +{ + FIX_NS(t, ns); + entry->stat_valid = 0; + entry->ae_set |= AE_SET_MTIME; + entry->ae_stat.aest_mtime = t; + entry->ae_stat.aest_mtime_nsec = ns; +} + +void +archive_entry_unset_mtime(struct archive_entry *entry) +{ + archive_entry_set_mtime(entry, 0, 0); + entry->ae_set &= ~AE_SET_MTIME; +} + +void +archive_entry_set_nlink(struct archive_entry *entry, unsigned int nlink) +{ + entry->stat_valid = 0; + entry->ae_stat.aest_nlink = nlink; +} + +void +archive_entry_set_pathname(struct archive_entry *entry, const char *name) +{ + archive_mstring_copy_mbs(&entry->ae_pathname, name); +} + +void +archive_entry_set_pathname_utf8(struct archive_entry *entry, const char *name) +{ + archive_mstring_copy_utf8(&entry->ae_pathname, name); +} + +void +archive_entry_copy_pathname(struct archive_entry *entry, const char *name) +{ + archive_mstring_copy_mbs(&entry->ae_pathname, name); +} + +void +archive_entry_copy_pathname_w(struct archive_entry *entry, const wchar_t *name) +{ + archive_mstring_copy_wcs(&entry->ae_pathname, name); +} + +int +archive_entry_update_pathname_utf8(struct archive_entry *entry, const char *name) +{ + if (archive_mstring_update_utf8(entry->archive, + &entry->ae_pathname, name) == 0) + return (1); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (0); +} + +int +_archive_entry_copy_pathname_l(struct archive_entry *entry, + const char *name, size_t len, struct archive_string_conv *sc) +{ + return (archive_mstring_copy_mbs_len_l(&entry->ae_pathname, + name, len, sc)); +} + +void +archive_entry_set_perm(struct archive_entry *entry, mode_t p) +{ + entry->stat_valid = 0; + entry->acl.mode &= AE_IFMT; + entry->acl.mode |= ~AE_IFMT & p; +} + +void +archive_entry_set_rdev(struct archive_entry *entry, dev_t m) +{ + entry->stat_valid = 0; + entry->ae_stat.aest_rdev = m; + entry->ae_stat.aest_rdev_is_broken_down = 0; +} + +void +archive_entry_set_rdevmajor(struct archive_entry *entry, dev_t m) +{ + entry->stat_valid = 0; + entry->ae_stat.aest_rdev_is_broken_down = 1; + entry->ae_stat.aest_rdevmajor = m; +} + +void +archive_entry_set_rdevminor(struct archive_entry *entry, dev_t m) +{ + entry->stat_valid = 0; + entry->ae_stat.aest_rdev_is_broken_down = 1; + entry->ae_stat.aest_rdevminor = m; +} + +void +archive_entry_set_size(struct archive_entry *entry, la_int64_t s) +{ + entry->stat_valid = 0; + entry->ae_stat.aest_size = s; + entry->ae_set |= AE_SET_SIZE; +} + +void +archive_entry_unset_size(struct archive_entry *entry) +{ + archive_entry_set_size(entry, 0); + entry->ae_set &= ~AE_SET_SIZE; +} + +void +archive_entry_copy_sourcepath(struct archive_entry *entry, const char *path) +{ + archive_mstring_copy_mbs(&entry->ae_sourcepath, path); +} + +void +archive_entry_copy_sourcepath_w(struct archive_entry *entry, const wchar_t *path) +{ + archive_mstring_copy_wcs(&entry->ae_sourcepath, path); +} + +void +archive_entry_set_symlink(struct archive_entry *entry, const char *linkname) +{ + archive_mstring_copy_mbs(&entry->ae_symlink, linkname); + if (linkname != NULL) + entry->ae_set |= AE_SET_SYMLINK; + else + entry->ae_set &= ~AE_SET_SYMLINK; +} + +void +archive_entry_set_symlink_type(struct archive_entry *entry, int type) +{ + entry->ae_symlink_type = type; +} + +void +archive_entry_set_symlink_utf8(struct archive_entry *entry, const char *linkname) +{ + archive_mstring_copy_utf8(&entry->ae_symlink, linkname); + if (linkname != NULL) + entry->ae_set |= AE_SET_SYMLINK; + else + entry->ae_set &= ~AE_SET_SYMLINK; +} + +void +archive_entry_copy_symlink(struct archive_entry *entry, const char *linkname) +{ + archive_mstring_copy_mbs(&entry->ae_symlink, linkname); + if (linkname != NULL) + entry->ae_set |= AE_SET_SYMLINK; + else + entry->ae_set &= ~AE_SET_SYMLINK; +} + +void +archive_entry_copy_symlink_w(struct archive_entry *entry, const wchar_t *linkname) +{ + archive_mstring_copy_wcs(&entry->ae_symlink, linkname); + if (linkname != NULL) + entry->ae_set |= AE_SET_SYMLINK; + else + entry->ae_set &= ~AE_SET_SYMLINK; +} + +int +archive_entry_update_symlink_utf8(struct archive_entry *entry, const char *linkname) +{ + if (linkname != NULL) + entry->ae_set |= AE_SET_SYMLINK; + else + entry->ae_set &= ~AE_SET_SYMLINK; + if (archive_mstring_update_utf8(entry->archive, + &entry->ae_symlink, linkname) == 0) + return (1); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (0); +} + +int +_archive_entry_copy_symlink_l(struct archive_entry *entry, + const char *linkname, size_t len, struct archive_string_conv *sc) +{ + int r; + + r = archive_mstring_copy_mbs_len_l(&entry->ae_symlink, + linkname, len, sc); + if (linkname != NULL && r == 0) + entry->ae_set |= AE_SET_SYMLINK; + else + entry->ae_set &= ~AE_SET_SYMLINK; + return (r); +} + +void +archive_entry_set_uid(struct archive_entry *entry, la_int64_t u) +{ + entry->stat_valid = 0; + entry->ae_stat.aest_uid = u; +} + +void +archive_entry_set_uname(struct archive_entry *entry, const char *name) +{ + archive_mstring_copy_mbs(&entry->ae_uname, name); +} + +void +archive_entry_set_uname_utf8(struct archive_entry *entry, const char *name) +{ + archive_mstring_copy_utf8(&entry->ae_uname, name); +} + +void +archive_entry_copy_uname(struct archive_entry *entry, const char *name) +{ + archive_mstring_copy_mbs(&entry->ae_uname, name); +} + +void +archive_entry_copy_uname_w(struct archive_entry *entry, const wchar_t *name) +{ + archive_mstring_copy_wcs(&entry->ae_uname, name); +} + +int +archive_entry_update_uname_utf8(struct archive_entry *entry, const char *name) +{ + if (archive_mstring_update_utf8(entry->archive, + &entry->ae_uname, name) == 0) + return (1); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (0); +} + +void +archive_entry_set_is_data_encrypted(struct archive_entry *entry, char is_encrypted) +{ + if (is_encrypted) { + entry->encryption |= AE_ENCRYPTION_DATA; + } else { + entry->encryption &= ~AE_ENCRYPTION_DATA; + } +} + +void +archive_entry_set_is_metadata_encrypted(struct archive_entry *entry, char is_encrypted) +{ + if (is_encrypted) { + entry->encryption |= AE_ENCRYPTION_METADATA; + } else { + entry->encryption &= ~AE_ENCRYPTION_METADATA; + } +} + +int +_archive_entry_copy_uname_l(struct archive_entry *entry, + const char *name, size_t len, struct archive_string_conv *sc) +{ + return (archive_mstring_copy_mbs_len_l(&entry->ae_uname, + name, len, sc)); +} + +const void * +archive_entry_mac_metadata(struct archive_entry *entry, size_t *s) +{ + *s = entry->mac_metadata_size; + return entry->mac_metadata; +} + +void +archive_entry_copy_mac_metadata(struct archive_entry *entry, + const void *p, size_t s) +{ + free(entry->mac_metadata); + if (p == NULL || s == 0) { + entry->mac_metadata = NULL; + entry->mac_metadata_size = 0; + } else { + entry->mac_metadata_size = s; + entry->mac_metadata = malloc(s); + if (entry->mac_metadata == NULL) + abort(); + memcpy(entry->mac_metadata, p, s); + } +} + +/* + * ACL management. The following would, of course, be a lot simpler + * if: 1) the last draft of POSIX.1e were a really thorough and + * complete standard that addressed the needs of ACL archiving and 2) + * everyone followed it faithfully. Alas, neither is true, so the + * following is a lot more complex than might seem necessary to the + * uninitiated. + */ + +struct archive_acl * +archive_entry_acl(struct archive_entry *entry) +{ + return &entry->acl; +} + +void +archive_entry_acl_clear(struct archive_entry *entry) +{ + archive_acl_clear(&entry->acl); +} + +/* + * Add a single ACL entry to the internal list of ACL data. + */ +int +archive_entry_acl_add_entry(struct archive_entry *entry, + int type, int permset, int tag, int id, const char *name) +{ + return archive_acl_add_entry(&entry->acl, type, permset, tag, id, name); +} + +/* + * As above, but with a wide-character name. + */ +int +archive_entry_acl_add_entry_w(struct archive_entry *entry, + int type, int permset, int tag, int id, const wchar_t *name) +{ + return archive_acl_add_entry_w_len(&entry->acl, + type, permset, tag, id, name, wcslen(name)); +} + +/* + * Return a bitmask of ACL types in an archive entry ACL list + */ +int +archive_entry_acl_types(struct archive_entry *entry) +{ + return (archive_acl_types(&entry->acl)); +} + +/* + * Return a count of entries matching "want_type". + */ +int +archive_entry_acl_count(struct archive_entry *entry, int want_type) +{ + return archive_acl_count(&entry->acl, want_type); +} + +/* + * Prepare for reading entries from the ACL data. Returns a count + * of entries matching "want_type", or zero if there are no + * non-extended ACL entries of that type. + */ +int +archive_entry_acl_reset(struct archive_entry *entry, int want_type) +{ + return archive_acl_reset(&entry->acl, want_type); +} + +/* + * Return the next ACL entry in the list. Fake entries for the + * standard permissions and include them in the returned list. + */ +int +archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type, + int *permset, int *tag, int *id, const char **name) +{ + int r; + r = archive_acl_next(entry->archive, &entry->acl, want_type, type, + permset, tag, id, name); + if (r == ARCHIVE_FATAL && errno == ENOMEM) + __archive_errx(1, "No memory"); + return (r); +} + +/* + * Generate a text version of the ACL. The flags parameter controls + * the style of the generated ACL. + */ +wchar_t * +archive_entry_acl_to_text_w(struct archive_entry *entry, la_ssize_t *len, + int flags) +{ + return (archive_acl_to_text_w(&entry->acl, len, flags, + entry->archive)); +} + +char * +archive_entry_acl_to_text(struct archive_entry *entry, la_ssize_t *len, + int flags) +{ + return (archive_acl_to_text_l(&entry->acl, len, flags, NULL)); +} + +char * +_archive_entry_acl_to_text_l(struct archive_entry *entry, ssize_t *len, + int flags, struct archive_string_conv *sc) +{ + return (archive_acl_to_text_l(&entry->acl, len, flags, sc)); +} + +/* + * ACL text parser. + */ +int +archive_entry_acl_from_text_w(struct archive_entry *entry, + const wchar_t *wtext, int type) +{ + return (archive_acl_from_text_w(&entry->acl, wtext, type)); +} + +int +archive_entry_acl_from_text(struct archive_entry *entry, + const char *text, int type) +{ + return (archive_acl_from_text_l(&entry->acl, text, type, NULL)); +} + +int +_archive_entry_acl_from_text_l(struct archive_entry *entry, const char *text, + int type, struct archive_string_conv *sc) +{ + return (archive_acl_from_text_l(&entry->acl, text, type, sc)); +} + +/* Deprecated */ +static int +archive_entry_acl_text_compat(int *flags) +{ + if ((*flags & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) == 0) + return (1); + + /* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID */ + if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0) + *flags |= ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID; + + /* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT */ + if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0) + *flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT; + + *flags |= ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA; + + return (0); +} + +/* Deprecated */ +const wchar_t * +archive_entry_acl_text_w(struct archive_entry *entry, int flags) +{ + free(entry->acl.acl_text_w); + entry->acl.acl_text_w = NULL; + if (archive_entry_acl_text_compat(&flags) == 0) + entry->acl.acl_text_w = archive_acl_to_text_w(&entry->acl, + NULL, flags, entry->archive); + return (entry->acl.acl_text_w); +} + +/* Deprecated */ +const char * +archive_entry_acl_text(struct archive_entry *entry, int flags) +{ + free(entry->acl.acl_text); + entry->acl.acl_text = NULL; + if (archive_entry_acl_text_compat(&flags) == 0) + entry->acl.acl_text = archive_acl_to_text_l(&entry->acl, NULL, + flags, NULL); + + return (entry->acl.acl_text); +} + +/* Deprecated */ +int +_archive_entry_acl_text_l(struct archive_entry *entry, int flags, + const char **acl_text, size_t *len, struct archive_string_conv *sc) +{ + free(entry->acl.acl_text); + entry->acl.acl_text = NULL; + + if (archive_entry_acl_text_compat(&flags) == 0) + entry->acl.acl_text = archive_acl_to_text_l(&entry->acl, + (ssize_t *)len, flags, sc); + + *acl_text = entry->acl.acl_text; + + return (0); +} + +/* + * Following code is modified from UC Berkeley sources, and + * is subject to the following copyright notice. + */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Supported file flags on FreeBSD and Mac OS: + * sappnd,sappend SF_APPEND + * arch,archived SF_ARCHIVED + * schg,schange,simmutable SF_IMMUTABLE + * sunlnk,sunlink SF_NOUNLINK (FreeBSD only) + * uappnd,uappend UF_APPEND + * compressed UF_COMPRESSED (Mac OS only) + * hidden,uhidden UF_HIDDEN + * uchg,uchange,uimmutable UF_IMMUTABLE + * nodump UF_NODUMP + * uunlnk,uunlink UF_NOUNLINK (FreeBSD only) + * offline,uoffline UF_OFFLINE (FreeBSD only) + * opaque UF_OPAQUE + * rdonly,urdonly,readonly UF_READONLY (FreeBSD only) + * reparse,ureparse UF_REPARSE (FreeBSD only) + * sparse,usparse UF_SPARSE (FreeBSD only) + * system,usystem UF_SYSTEM (FreeBSD only) + * + * See chflags(2) for more information + * + * Supported file attributes on Linux: + * a append only FS_APPEND_FL sappnd + * A no atime updates FS_NOATIME_FL atime + * c compress FS_COMPR_FL compress + * C no copy on write FS_NOCOW_FL cow + * d no dump FS_NODUMP_FL dump + * D synchronous directory updates FS_DIRSYNC_FL dirsync + * i immutable FS_IMMUTABLE_FL schg + * j data journalling FS_JOURNAL_DATA_FL journal + * P project hierarchy FS_PROJINHERIT_FL projinherit + * s secure deletion FS_SECRM_FL securedeletion + * S synchronous updates FS_SYNC_FL sync + * t no tail-merging FS_NOTAIL_FL tail + * T top of directory hierarchy FS_TOPDIR_FL topdir + * u undeletable FS_UNRM_FL undel + * + * See ioctl_iflags(2) for more information + * + * Equivalent file flags supported on FreeBSD / Mac OS and Linux: + * SF_APPEND FS_APPEND_FL sappnd + * SF_IMMUTABLE FS_IMMUTABLE_FL schg + * UF_NODUMP FS_NODUMP_FL nodump + */ + +static const struct flag { + const char *name; + const wchar_t *wname; + unsigned long set; + unsigned long clear; +} fileflags[] = { + /* Preferred (shorter) names per flag first, all prefixed by "no" */ +#ifdef SF_APPEND + { "nosappnd", L"nosappnd", SF_APPEND, 0}, + { "nosappend", L"nosappend", SF_APPEND, 0}, +#endif +#if defined(FS_APPEND_FL) /* 'a' */ + { "nosappnd", L"nosappnd", FS_APPEND_FL, 0}, + { "nosappend", L"nosappend", FS_APPEND_FL, 0}, +#elif defined(EXT2_APPEND_FL) /* 'a' */ + { "nosappnd", L"nosappnd", EXT2_APPEND_FL, 0}, + { "nosappend", L"nosappend", EXT2_APPEND_FL, 0}, +#endif +#ifdef SF_ARCHIVED + { "noarch", L"noarch", SF_ARCHIVED, 0}, + { "noarchived", L"noarchived", SF_ARCHIVED, 0}, +#endif +#ifdef SF_IMMUTABLE + { "noschg", L"noschg", SF_IMMUTABLE, 0}, + { "noschange", L"noschange", SF_IMMUTABLE, 0}, + { "nosimmutable", L"nosimmutable", SF_IMMUTABLE, 0}, +#endif +#if defined(FS_IMMUTABLE_FL) /* 'i' */ + { "noschg", L"noschg", FS_IMMUTABLE_FL, 0}, + { "noschange", L"noschange", FS_IMMUTABLE_FL, 0}, + { "nosimmutable", L"nosimmutable", FS_IMMUTABLE_FL, 0}, +#elif defined(EXT2_IMMUTABLE_FL) /* 'i' */ + { "noschg", L"noschg", EXT2_IMMUTABLE_FL, 0}, + { "noschange", L"noschange", EXT2_IMMUTABLE_FL, 0}, + { "nosimmutable", L"nosimmutable", EXT2_IMMUTABLE_FL, 0}, +#endif +#ifdef SF_NOUNLINK + { "nosunlnk", L"nosunlnk", SF_NOUNLINK, 0}, + { "nosunlink", L"nosunlink", SF_NOUNLINK, 0}, +#endif +#ifdef UF_APPEND + { "nouappnd", L"nouappnd", UF_APPEND, 0}, + { "nouappend", L"nouappend", UF_APPEND, 0}, +#endif +#ifdef UF_IMMUTABLE + { "nouchg", L"nouchg", UF_IMMUTABLE, 0}, + { "nouchange", L"nouchange", UF_IMMUTABLE, 0}, + { "nouimmutable", L"nouimmutable", UF_IMMUTABLE, 0}, +#endif +#ifdef UF_NODUMP + { "nodump", L"nodump", 0, UF_NODUMP}, +#endif +#if defined(FS_NODUMP_FL) /* 'd' */ + { "nodump", L"nodump", 0, FS_NODUMP_FL}, +#elif defined(EXT2_NODUMP_FL) + { "nodump", L"nodump", 0, EXT2_NODUMP_FL}, +#endif +#ifdef UF_OPAQUE + { "noopaque", L"noopaque", UF_OPAQUE, 0}, +#endif +#ifdef UF_NOUNLINK + { "nouunlnk", L"nouunlnk", UF_NOUNLINK, 0}, + { "nouunlink", L"nouunlink", UF_NOUNLINK, 0}, +#endif +#ifdef UF_COMPRESSED + /* Mac OS */ + { "nocompressed", L"nocompressed", UF_COMPRESSED, 0}, +#endif +#ifdef UF_HIDDEN + { "nohidden", L"nohidden", UF_HIDDEN, 0}, + { "nouhidden", L"nouhidden", UF_HIDDEN, 0}, +#endif +#ifdef FILE_ATTRIBUTE_HIDDEN + { "nohidden", L"nohidden", FILE_ATTRIBUTE_HIDDEN, 0}, + { "nouhidden", L"nouhidden", FILE_ATTRIBUTE_HIDDEN, 0}, +#endif +#ifdef UF_OFFLINE + { "nooffline", L"nooffline", UF_OFFLINE, 0}, + { "nouoffline", L"nouoffline", UF_OFFLINE, 0}, +#endif +#ifdef UF_READONLY + { "nordonly", L"nordonly", UF_READONLY, 0}, + { "nourdonly", L"nourdonly", UF_READONLY, 0}, + { "noreadonly", L"noreadonly", UF_READONLY, 0}, +#endif +#ifdef FILE_ATTRIBUTE_READONLY + { "nordonly", L"nordonly", FILE_ATTRIBUTE_READONLY, 0}, + { "nourdonly", L"nourdonly", FILE_ATTRIBUTE_READONLY, 0}, + { "noreadonly", L"noreadonly", FILE_ATTRIBUTE_READONLY, 0}, +#endif +#ifdef UF_SPARSE + { "nosparse", L"nosparse", UF_SPARSE, 0}, + { "nousparse", L"nousparse", UF_SPARSE, 0}, +#endif +#ifdef UF_REPARSE + { "noreparse", L"noreparse", UF_REPARSE, 0}, + { "noureparse", L"noureparse", UF_REPARSE, 0}, +#endif +#ifdef UF_SYSTEM + { "nosystem", L"nosystem", UF_SYSTEM, 0}, + { "nousystem", L"nousystem", UF_SYSTEM, 0}, +#endif +#ifdef FILE_ATTRIBUTE_SYSTEM + { "nosystem", L"nosystem", FILE_ATTRIBUTE_SYSTEM, 0}, + { "nousystem", L"nousystem", FILE_ATTRIBUTE_SYSTEM, 0}, +#endif +#if defined(FS_UNRM_FL) /* 'u' */ + { "noundel", L"noundel", FS_UNRM_FL, 0}, +#elif defined(EXT2_UNRM_FL) + { "noundel", L"noundel", EXT2_UNRM_FL, 0}, +#endif + +#if defined(FS_COMPR_FL) /* 'c' */ + { "nocompress", L"nocompress", FS_COMPR_FL, 0}, +#elif defined(EXT2_COMPR_FL) + { "nocompress", L"nocompress", EXT2_COMPR_FL, 0}, +#endif + +#if defined(FS_NOATIME_FL) /* 'A' */ + { "noatime", L"noatime", 0, FS_NOATIME_FL}, +#elif defined(EXT2_NOATIME_FL) + { "noatime", L"noatime", 0, EXT2_NOATIME_FL}, +#endif +#if defined(FS_DIRSYNC_FL) /* 'D' */ + { "nodirsync", L"nodirsync", FS_DIRSYNC_FL, 0}, +#elif defined(EXT2_DIRSYNC_FL) + { "nodirsync", L"nodirsync", EXT2_DIRSYNC_FL, 0}, +#endif +#if defined(FS_JOURNAL_DATA_FL) /* 'j' */ + { "nojournal-data",L"nojournal-data", FS_JOURNAL_DATA_FL, 0}, + { "nojournal", L"nojournal", FS_JOURNAL_DATA_FL, 0}, +#elif defined(EXT3_JOURNAL_DATA_FL) + { "nojournal-data",L"nojournal-data", EXT3_JOURNAL_DATA_FL, 0}, + { "nojournal", L"nojournal", EXT3_JOURNAL_DATA_FL, 0}, +#endif +#if defined(FS_SECRM_FL) /* 's' */ + { "nosecdel", L"nosecdel", FS_SECRM_FL, 0}, + { "nosecuredeletion",L"nosecuredeletion",FS_SECRM_FL, 0}, +#elif defined(EXT2_SECRM_FL) + { "nosecdel", L"nosecdel", EXT2_SECRM_FL, 0}, + { "nosecuredeletion",L"nosecuredeletion",EXT2_SECRM_FL, 0}, +#endif +#if defined(FS_SYNC_FL) /* 'S' */ + { "nosync", L"nosync", FS_SYNC_FL, 0}, +#elif defined(EXT2_SYNC_FL) + { "nosync", L"nosync", EXT2_SYNC_FL, 0}, +#endif +#if defined(FS_NOTAIL_FL) /* 't' */ + { "notail", L"notail", 0, FS_NOTAIL_FL}, +#elif defined(EXT2_NOTAIL_FL) + { "notail", L"notail", 0, EXT2_NOTAIL_FL}, +#endif +#if defined(FS_TOPDIR_FL) /* 'T' */ + { "notopdir", L"notopdir", FS_TOPDIR_FL, 0}, +#elif defined(EXT2_TOPDIR_FL) + { "notopdir", L"notopdir", EXT2_TOPDIR_FL, 0}, +#endif +#ifdef FS_NOCOW_FL /* 'C' */ + { "nocow", L"nocow", 0, FS_NOCOW_FL}, +#endif +#ifdef FS_PROJINHERIT_FL /* 'P' */ + { "noprojinherit",L"noprojinherit", FS_PROJINHERIT_FL, 0}, +#endif + { NULL, NULL, 0, 0} +}; + +/* + * fflagstostr -- + * Convert file flags to a comma-separated string. If no flags + * are set, return the empty string. + */ +static char * +ae_fflagstostr(unsigned long bitset, unsigned long bitclear) +{ + char *string, *dp; + const char *sp; + unsigned long bits; + const struct flag *flag; + size_t length; + + bits = bitset | bitclear; + length = 0; + for (flag = fileflags; flag->name != NULL; flag++) + if (bits & (flag->set | flag->clear)) { + length += strlen(flag->name) + 1; + bits &= ~(flag->set | flag->clear); + } + + if (length == 0) + return (NULL); + string = (char *)malloc(length); + if (string == NULL) + return (NULL); + + dp = string; + for (flag = fileflags; flag->name != NULL; flag++) { + if (bitset & flag->set || bitclear & flag->clear) { + sp = flag->name + 2; + } else if (bitset & flag->clear || bitclear & flag->set) { + sp = flag->name; + } else + continue; + bitset &= ~(flag->set | flag->clear); + bitclear &= ~(flag->set | flag->clear); + if (dp > string) + *dp++ = ','; + while ((*dp++ = *sp++) != '\0') + ; + dp--; + } + + *dp = '\0'; + return (string); +} + +/* + * strtofflags -- + * Take string of arguments and return file flags. This + * version works a little differently than strtofflags(3). + * In particular, it always tests every token, skipping any + * unrecognized tokens. It returns a pointer to the first + * unrecognized token, or NULL if every token was recognized. + * This version is also const-correct and does not modify the + * provided string. + */ +static const char * +ae_strtofflags(const char *s, unsigned long *setp, unsigned long *clrp) +{ + const char *start, *end; + const struct flag *flag; + unsigned long set, clear; + const char *failed; + + set = clear = 0; + start = s; + failed = NULL; + /* Find start of first token. */ + while (*start == '\t' || *start == ' ' || *start == ',') + start++; + while (*start != '\0') { + size_t length; + /* Locate end of token. */ + end = start; + while (*end != '\0' && *end != '\t' && + *end != ' ' && *end != ',') + end++; + length = end - start; + for (flag = fileflags; flag->name != NULL; flag++) { + size_t flag_length = strlen(flag->name); + if (length == flag_length + && memcmp(start, flag->name, length) == 0) { + /* Matched "noXXXX", so reverse the sense. */ + clear |= flag->set; + set |= flag->clear; + break; + } else if (length == flag_length - 2 + && memcmp(start, flag->name + 2, length) == 0) { + /* Matched "XXXX", so don't reverse. */ + set |= flag->set; + clear |= flag->clear; + break; + } + } + /* Ignore unknown flag names. */ + if (flag->name == NULL && failed == NULL) + failed = start; + + /* Find start of next token. */ + start = end; + while (*start == '\t' || *start == ' ' || *start == ',') + start++; + + } + + if (setp) + *setp = set; + if (clrp) + *clrp = clear; + + /* Return location of first failure. */ + return (failed); +} + +/* + * wcstofflags -- + * Take string of arguments and return file flags. This + * version works a little differently than strtofflags(3). + * In particular, it always tests every token, skipping any + * unrecognized tokens. It returns a pointer to the first + * unrecognized token, or NULL if every token was recognized. + * This version is also const-correct and does not modify the + * provided string. + */ +static const wchar_t * +ae_wcstofflags(const wchar_t *s, unsigned long *setp, unsigned long *clrp) +{ + const wchar_t *start, *end; + const struct flag *flag; + unsigned long set, clear; + const wchar_t *failed; + + set = clear = 0; + start = s; + failed = NULL; + /* Find start of first token. */ + while (*start == L'\t' || *start == L' ' || *start == L',') + start++; + while (*start != L'\0') { + size_t length; + /* Locate end of token. */ + end = start; + while (*end != L'\0' && *end != L'\t' && + *end != L' ' && *end != L',') + end++; + length = end - start; + for (flag = fileflags; flag->wname != NULL; flag++) { + size_t flag_length = wcslen(flag->wname); + if (length == flag_length + && wmemcmp(start, flag->wname, length) == 0) { + /* Matched "noXXXX", so reverse the sense. */ + clear |= flag->set; + set |= flag->clear; + break; + } else if (length == flag_length - 2 + && wmemcmp(start, flag->wname + 2, length) == 0) { + /* Matched "XXXX", so don't reverse. */ + set |= flag->set; + clear |= flag->clear; + break; + } + } + /* Ignore unknown flag names. */ + if (flag->wname == NULL && failed == NULL) + failed = start; + + /* Find start of next token. */ + start = end; + while (*start == L'\t' || *start == L' ' || *start == L',') + start++; + + } + + if (setp) + *setp = set; + if (clrp) + *clrp = clear; + + /* Return location of first failure. */ + return (failed); +} + + +#ifdef TEST +#include +int +main(int argc, char **argv) +{ + struct archive_entry *entry = archive_entry_new(); + unsigned long set, clear; + const wchar_t *remainder; + + remainder = archive_entry_copy_fflags_text_w(entry, L"nosappnd dump archive,,,,,,,"); + archive_entry_fflags(entry, &set, &clear); + + wprintf(L"set=0x%lX clear=0x%lX remainder='%ls'\n", set, clear, remainder); + + wprintf(L"new flags='%s'\n", archive_entry_fflags_text(entry)); + return (0); +} +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_entry.h b/dependencies/libarchive-3.4.2/libarchive/archive_entry.h new file mode 100644 index 0000000..42af208 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_entry.h @@ -0,0 +1,708 @@ +/*- + * Copyright (c) 2003-2008 Tim Kientzle + * Copyright (c) 2016 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: head/lib/libarchive/archive_entry.h 201096 2009-12-28 02:41:27Z kientzle $ + */ + +#ifndef ARCHIVE_ENTRY_H_INCLUDED +#define ARCHIVE_ENTRY_H_INCLUDED + +/* Note: Compiler will complain if this does not match archive.h! */ +#define ARCHIVE_VERSION_NUMBER 3004002 + +/* + * Note: archive_entry.h is for use outside of libarchive; the + * configuration headers (config.h, archive_platform.h, etc.) are + * purely internal. Do NOT use HAVE_XXX configuration macros to + * control the behavior of this header! If you must conditionalize, + * use predefined compiler and/or platform macros. + */ + +#include +#include /* for wchar_t */ +#include +#include + +#if defined(_WIN32) && !defined(__CYGWIN__) +#include +#endif + +/* Get a suitable 64-bit integer type. */ +#if !defined(__LA_INT64_T_DEFINED) +# if ARCHIVE_VERSION_NUMBER < 4000000 +#define __LA_INT64_T la_int64_t +# endif +#define __LA_INT64_T_DEFINED +# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__) +typedef __int64 la_int64_t; +# else +#include +# if defined(_SCO_DS) || defined(__osf__) +typedef long long la_int64_t; +# else +typedef int64_t la_int64_t; +# endif +# endif +#endif + +/* The la_ssize_t should match the type used in 'struct stat' */ +#if !defined(__LA_SSIZE_T_DEFINED) +/* Older code relied on the __LA_SSIZE_T macro; after 4.0 we'll switch to the typedef exclusively. */ +# if ARCHIVE_VERSION_NUMBER < 4000000 +#define __LA_SSIZE_T la_ssize_t +# endif +#define __LA_SSIZE_T_DEFINED +# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__) +# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_) +typedef ssize_t la_ssize_t; +# elif defined(_WIN64) +typedef __int64 la_ssize_t; +# else +typedef long la_ssize_t; +# endif +# else +# include /* ssize_t */ +typedef ssize_t la_ssize_t; +# endif +#endif + +/* Get a suitable definition for mode_t */ +#if ARCHIVE_VERSION_NUMBER >= 3999000 +/* Switch to plain 'int' for libarchive 4.0. It's less broken than 'mode_t' */ +# define __LA_MODE_T int +#elif defined(_WIN32) && !defined(__CYGWIN__) && !defined(__BORLANDC__) && !defined(__WATCOMC__) +# define __LA_MODE_T unsigned short +#else +# define __LA_MODE_T mode_t +#endif + +/* Large file support for Android */ +#ifdef __ANDROID__ +#include "android_lf.h" +#endif + +/* + * On Windows, define LIBARCHIVE_STATIC if you're building or using a + * .lib. The default here assumes you're building a DLL. Only + * libarchive source should ever define __LIBARCHIVE_BUILD. + */ +#if ((defined __WIN32__) || (defined _WIN32) || defined(__CYGWIN__)) && (!defined LIBARCHIVE_STATIC) +# ifdef __LIBARCHIVE_BUILD +# ifdef __GNUC__ +# define __LA_DECL __attribute__((dllexport)) extern +# else +# define __LA_DECL __declspec(dllexport) +# endif +# else +# ifdef __GNUC__ +# define __LA_DECL +# else +# define __LA_DECL __declspec(dllimport) +# endif +# endif +#else +/* Static libraries on all platforms and shared libraries on non-Windows. */ +# define __LA_DECL +#endif + +#if defined(__GNUC__) && __GNUC__ >= 3 && __GNUC_MINOR__ >= 1 +# define __LA_DEPRECATED __attribute__((deprecated)) +#else +# define __LA_DEPRECATED +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Description of an archive entry. + * + * You can think of this as "struct stat" with some text fields added in. + * + * TODO: Add "comment", "charset", and possibly other entries that are + * supported by "pax interchange" format. However, GNU, ustar, cpio, + * and other variants don't support these features, so they're not an + * excruciatingly high priority right now. + * + * TODO: "pax interchange" format allows essentially arbitrary + * key/value attributes to be attached to any entry. Supporting + * such extensions may make this library useful for special + * applications (e.g., a package manager could attach special + * package-management attributes to each entry). + */ +struct archive; +struct archive_entry; + +/* + * File-type constants. These are returned from archive_entry_filetype() + * and passed to archive_entry_set_filetype(). + * + * These values match S_XXX defines on every platform I've checked, + * including Windows, AIX, Linux, Solaris, and BSD. They're + * (re)defined here because platforms generally don't define the ones + * they don't support. For example, Windows doesn't define S_IFLNK or + * S_IFBLK. Instead of having a mass of conditional logic and system + * checks to define any S_XXX values that aren't supported locally, + * I've just defined a new set of such constants so that + * libarchive-based applications can manipulate and identify archive + * entries properly even if the hosting platform can't store them on + * disk. + * + * These values are also used directly within some portable formats, + * such as cpio. If you find a platform that varies from these, the + * correct solution is to leave these alone and translate from these + * portable values to platform-native values when entries are read from + * or written to disk. + */ +/* + * In libarchive 4.0, we can drop the casts here. + * They're needed to work around Borland C's broken mode_t. + */ +#define AE_IFMT ((__LA_MODE_T)0170000) +#define AE_IFREG ((__LA_MODE_T)0100000) +#define AE_IFLNK ((__LA_MODE_T)0120000) +#define AE_IFSOCK ((__LA_MODE_T)0140000) +#define AE_IFCHR ((__LA_MODE_T)0020000) +#define AE_IFBLK ((__LA_MODE_T)0060000) +#define AE_IFDIR ((__LA_MODE_T)0040000) +#define AE_IFIFO ((__LA_MODE_T)0010000) + +/* + * Symlink types + */ +#define AE_SYMLINK_TYPE_UNDEFINED 0 +#define AE_SYMLINK_TYPE_FILE 1 +#define AE_SYMLINK_TYPE_DIRECTORY 2 + +/* + * Basic object manipulation + */ + +__LA_DECL struct archive_entry *archive_entry_clear(struct archive_entry *); +/* The 'clone' function does a deep copy; all of the strings are copied too. */ +__LA_DECL struct archive_entry *archive_entry_clone(struct archive_entry *); +__LA_DECL void archive_entry_free(struct archive_entry *); +__LA_DECL struct archive_entry *archive_entry_new(void); + +/* + * This form of archive_entry_new2() will pull character-set + * conversion information from the specified archive handle. The + * older archive_entry_new(void) form is equivalent to calling + * archive_entry_new2(NULL) and will result in the use of an internal + * default character-set conversion. + */ +__LA_DECL struct archive_entry *archive_entry_new2(struct archive *); + +/* + * Retrieve fields from an archive_entry. + * + * There are a number of implicit conversions among these fields. For + * example, if a regular string field is set and you read the _w wide + * character field, the entry will implicitly convert narrow-to-wide + * using the current locale. Similarly, dev values are automatically + * updated when you write devmajor or devminor and vice versa. + * + * In addition, fields can be "set" or "unset." Unset string fields + * return NULL, non-string fields have _is_set() functions to test + * whether they've been set. You can "unset" a string field by + * assigning NULL; non-string fields have _unset() functions to + * unset them. + * + * Note: There is one ambiguity in the above; string fields will + * also return NULL when implicit character set conversions fail. + * This is usually what you want. + */ +__LA_DECL time_t archive_entry_atime(struct archive_entry *); +__LA_DECL long archive_entry_atime_nsec(struct archive_entry *); +__LA_DECL int archive_entry_atime_is_set(struct archive_entry *); +__LA_DECL time_t archive_entry_birthtime(struct archive_entry *); +__LA_DECL long archive_entry_birthtime_nsec(struct archive_entry *); +__LA_DECL int archive_entry_birthtime_is_set(struct archive_entry *); +__LA_DECL time_t archive_entry_ctime(struct archive_entry *); +__LA_DECL long archive_entry_ctime_nsec(struct archive_entry *); +__LA_DECL int archive_entry_ctime_is_set(struct archive_entry *); +__LA_DECL dev_t archive_entry_dev(struct archive_entry *); +__LA_DECL int archive_entry_dev_is_set(struct archive_entry *); +__LA_DECL dev_t archive_entry_devmajor(struct archive_entry *); +__LA_DECL dev_t archive_entry_devminor(struct archive_entry *); +__LA_DECL __LA_MODE_T archive_entry_filetype(struct archive_entry *); +__LA_DECL void archive_entry_fflags(struct archive_entry *, + unsigned long * /* set */, + unsigned long * /* clear */); +__LA_DECL const char *archive_entry_fflags_text(struct archive_entry *); +__LA_DECL la_int64_t archive_entry_gid(struct archive_entry *); +__LA_DECL const char *archive_entry_gname(struct archive_entry *); +__LA_DECL const char *archive_entry_gname_utf8(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_gname_w(struct archive_entry *); +__LA_DECL const char *archive_entry_hardlink(struct archive_entry *); +__LA_DECL const char *archive_entry_hardlink_utf8(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_hardlink_w(struct archive_entry *); +__LA_DECL la_int64_t archive_entry_ino(struct archive_entry *); +__LA_DECL la_int64_t archive_entry_ino64(struct archive_entry *); +__LA_DECL int archive_entry_ino_is_set(struct archive_entry *); +__LA_DECL __LA_MODE_T archive_entry_mode(struct archive_entry *); +__LA_DECL time_t archive_entry_mtime(struct archive_entry *); +__LA_DECL long archive_entry_mtime_nsec(struct archive_entry *); +__LA_DECL int archive_entry_mtime_is_set(struct archive_entry *); +__LA_DECL unsigned int archive_entry_nlink(struct archive_entry *); +__LA_DECL const char *archive_entry_pathname(struct archive_entry *); +__LA_DECL const char *archive_entry_pathname_utf8(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_pathname_w(struct archive_entry *); +__LA_DECL __LA_MODE_T archive_entry_perm(struct archive_entry *); +__LA_DECL dev_t archive_entry_rdev(struct archive_entry *); +__LA_DECL dev_t archive_entry_rdevmajor(struct archive_entry *); +__LA_DECL dev_t archive_entry_rdevminor(struct archive_entry *); +__LA_DECL const char *archive_entry_sourcepath(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_sourcepath_w(struct archive_entry *); +__LA_DECL la_int64_t archive_entry_size(struct archive_entry *); +__LA_DECL int archive_entry_size_is_set(struct archive_entry *); +__LA_DECL const char *archive_entry_strmode(struct archive_entry *); +__LA_DECL const char *archive_entry_symlink(struct archive_entry *); +__LA_DECL const char *archive_entry_symlink_utf8(struct archive_entry *); +__LA_DECL int archive_entry_symlink_type(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_symlink_w(struct archive_entry *); +__LA_DECL la_int64_t archive_entry_uid(struct archive_entry *); +__LA_DECL const char *archive_entry_uname(struct archive_entry *); +__LA_DECL const char *archive_entry_uname_utf8(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_uname_w(struct archive_entry *); +__LA_DECL int archive_entry_is_data_encrypted(struct archive_entry *); +__LA_DECL int archive_entry_is_metadata_encrypted(struct archive_entry *); +__LA_DECL int archive_entry_is_encrypted(struct archive_entry *); + +/* + * Set fields in an archive_entry. + * + * Note: Before libarchive 2.4, there were 'set' and 'copy' versions + * of the string setters. 'copy' copied the actual string, 'set' just + * stored the pointer. In libarchive 2.4 and later, strings are + * always copied. + */ + +__LA_DECL void archive_entry_set_atime(struct archive_entry *, time_t, long); +__LA_DECL void archive_entry_unset_atime(struct archive_entry *); +#if defined(_WIN32) && !defined(__CYGWIN__) +__LA_DECL void archive_entry_copy_bhfi(struct archive_entry *, BY_HANDLE_FILE_INFORMATION *); +#endif +__LA_DECL void archive_entry_set_birthtime(struct archive_entry *, time_t, long); +__LA_DECL void archive_entry_unset_birthtime(struct archive_entry *); +__LA_DECL void archive_entry_set_ctime(struct archive_entry *, time_t, long); +__LA_DECL void archive_entry_unset_ctime(struct archive_entry *); +__LA_DECL void archive_entry_set_dev(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_devmajor(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_devminor(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_filetype(struct archive_entry *, unsigned int); +__LA_DECL void archive_entry_set_fflags(struct archive_entry *, + unsigned long /* set */, unsigned long /* clear */); +/* Returns pointer to start of first invalid token, or NULL if none. */ +/* Note that all recognized tokens are processed, regardless. */ +__LA_DECL const char *archive_entry_copy_fflags_text(struct archive_entry *, + const char *); +__LA_DECL const wchar_t *archive_entry_copy_fflags_text_w(struct archive_entry *, + const wchar_t *); +__LA_DECL void archive_entry_set_gid(struct archive_entry *, la_int64_t); +__LA_DECL void archive_entry_set_gname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_gname_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_gname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_gname_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_gname_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_hardlink(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_hardlink_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_hardlink(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_hardlink_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_hardlink_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_ino(struct archive_entry *, la_int64_t); +__LA_DECL void archive_entry_set_ino64(struct archive_entry *, la_int64_t); +__LA_DECL void archive_entry_set_link(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_link_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_link(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_link_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_link_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_mode(struct archive_entry *, __LA_MODE_T); +__LA_DECL void archive_entry_set_mtime(struct archive_entry *, time_t, long); +__LA_DECL void archive_entry_unset_mtime(struct archive_entry *); +__LA_DECL void archive_entry_set_nlink(struct archive_entry *, unsigned int); +__LA_DECL void archive_entry_set_pathname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_pathname_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_pathname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_pathname_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_pathname_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_perm(struct archive_entry *, __LA_MODE_T); +__LA_DECL void archive_entry_set_rdev(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_rdevmajor(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_rdevminor(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_size(struct archive_entry *, la_int64_t); +__LA_DECL void archive_entry_unset_size(struct archive_entry *); +__LA_DECL void archive_entry_copy_sourcepath(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_sourcepath_w(struct archive_entry *, const wchar_t *); +__LA_DECL void archive_entry_set_symlink(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_symlink_type(struct archive_entry *, int); +__LA_DECL void archive_entry_set_symlink_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_symlink(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_symlink_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_symlink_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_uid(struct archive_entry *, la_int64_t); +__LA_DECL void archive_entry_set_uname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_uname_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_uname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_uname_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_uname_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_is_data_encrypted(struct archive_entry *, char is_encrypted); +__LA_DECL void archive_entry_set_is_metadata_encrypted(struct archive_entry *, char is_encrypted); +/* + * Routines to bulk copy fields to/from a platform-native "struct + * stat." Libarchive used to just store a struct stat inside of each + * archive_entry object, but this created issues when trying to + * manipulate archives on systems different than the ones they were + * created on. + * + * TODO: On Linux and other LFS systems, provide both stat32 and + * stat64 versions of these functions and all of the macro glue so + * that archive_entry_stat is magically defined to + * archive_entry_stat32 or archive_entry_stat64 as appropriate. + */ +__LA_DECL const struct stat *archive_entry_stat(struct archive_entry *); +__LA_DECL void archive_entry_copy_stat(struct archive_entry *, const struct stat *); + +/* + * Storage for Mac OS-specific AppleDouble metadata information. + * Apple-format tar files store a separate binary blob containing + * encoded metadata with ACL, extended attributes, etc. + * This provides a place to store that blob. + */ + +__LA_DECL const void * archive_entry_mac_metadata(struct archive_entry *, size_t *); +__LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const void *, size_t); + +/* + * ACL routines. This used to simply store and return text-format ACL + * strings, but that proved insufficient for a number of reasons: + * = clients need control over uname/uid and gname/gid mappings + * = there are many different ACL text formats + * = would like to be able to read/convert archives containing ACLs + * on platforms that lack ACL libraries + * + * This last point, in particular, forces me to implement a reasonably + * complete set of ACL support routines. + */ + +/* + * Permission bits. + */ +#define ARCHIVE_ENTRY_ACL_EXECUTE 0x00000001 +#define ARCHIVE_ENTRY_ACL_WRITE 0x00000002 +#define ARCHIVE_ENTRY_ACL_READ 0x00000004 +#define ARCHIVE_ENTRY_ACL_READ_DATA 0x00000008 +#define ARCHIVE_ENTRY_ACL_LIST_DIRECTORY 0x00000008 +#define ARCHIVE_ENTRY_ACL_WRITE_DATA 0x00000010 +#define ARCHIVE_ENTRY_ACL_ADD_FILE 0x00000010 +#define ARCHIVE_ENTRY_ACL_APPEND_DATA 0x00000020 +#define ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY 0x00000020 +#define ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS 0x00000040 +#define ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS 0x00000080 +#define ARCHIVE_ENTRY_ACL_DELETE_CHILD 0x00000100 +#define ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES 0x00000200 +#define ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES 0x00000400 +#define ARCHIVE_ENTRY_ACL_DELETE 0x00000800 +#define ARCHIVE_ENTRY_ACL_READ_ACL 0x00001000 +#define ARCHIVE_ENTRY_ACL_WRITE_ACL 0x00002000 +#define ARCHIVE_ENTRY_ACL_WRITE_OWNER 0x00004000 +#define ARCHIVE_ENTRY_ACL_SYNCHRONIZE 0x00008000 + +#define ARCHIVE_ENTRY_ACL_PERMS_POSIX1E \ + (ARCHIVE_ENTRY_ACL_EXECUTE \ + | ARCHIVE_ENTRY_ACL_WRITE \ + | ARCHIVE_ENTRY_ACL_READ) + +#define ARCHIVE_ENTRY_ACL_PERMS_NFS4 \ + (ARCHIVE_ENTRY_ACL_EXECUTE \ + | ARCHIVE_ENTRY_ACL_READ_DATA \ + | ARCHIVE_ENTRY_ACL_LIST_DIRECTORY \ + | ARCHIVE_ENTRY_ACL_WRITE_DATA \ + | ARCHIVE_ENTRY_ACL_ADD_FILE \ + | ARCHIVE_ENTRY_ACL_APPEND_DATA \ + | ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY \ + | ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS \ + | ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS \ + | ARCHIVE_ENTRY_ACL_DELETE_CHILD \ + | ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES \ + | ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES \ + | ARCHIVE_ENTRY_ACL_DELETE \ + | ARCHIVE_ENTRY_ACL_READ_ACL \ + | ARCHIVE_ENTRY_ACL_WRITE_ACL \ + | ARCHIVE_ENTRY_ACL_WRITE_OWNER \ + | ARCHIVE_ENTRY_ACL_SYNCHRONIZE) + +/* + * Inheritance values (NFS4 ACLs only); included in permset. + */ +#define ARCHIVE_ENTRY_ACL_ENTRY_INHERITED 0x01000000 +#define ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT 0x02000000 +#define ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT 0x04000000 +#define ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT 0x08000000 +#define ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY 0x10000000 +#define ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS 0x20000000 +#define ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS 0x40000000 + +#define ARCHIVE_ENTRY_ACL_INHERITANCE_NFS4 \ + (ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT \ + | ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT \ + | ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT \ + | ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY \ + | ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS \ + | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS \ + | ARCHIVE_ENTRY_ACL_ENTRY_INHERITED) + +/* We need to be able to specify combinations of these. */ +#define ARCHIVE_ENTRY_ACL_TYPE_ACCESS 0x00000100 /* POSIX.1e only */ +#define ARCHIVE_ENTRY_ACL_TYPE_DEFAULT 0x00000200 /* POSIX.1e only */ +#define ARCHIVE_ENTRY_ACL_TYPE_ALLOW 0x00000400 /* NFS4 only */ +#define ARCHIVE_ENTRY_ACL_TYPE_DENY 0x00000800 /* NFS4 only */ +#define ARCHIVE_ENTRY_ACL_TYPE_AUDIT 0x00001000 /* NFS4 only */ +#define ARCHIVE_ENTRY_ACL_TYPE_ALARM 0x00002000 /* NFS4 only */ +#define ARCHIVE_ENTRY_ACL_TYPE_POSIX1E (ARCHIVE_ENTRY_ACL_TYPE_ACCESS \ + | ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) +#define ARCHIVE_ENTRY_ACL_TYPE_NFS4 (ARCHIVE_ENTRY_ACL_TYPE_ALLOW \ + | ARCHIVE_ENTRY_ACL_TYPE_DENY \ + | ARCHIVE_ENTRY_ACL_TYPE_AUDIT \ + | ARCHIVE_ENTRY_ACL_TYPE_ALARM) + +/* Tag values mimic POSIX.1e */ +#define ARCHIVE_ENTRY_ACL_USER 10001 /* Specified user. */ +#define ARCHIVE_ENTRY_ACL_USER_OBJ 10002 /* User who owns the file. */ +#define ARCHIVE_ENTRY_ACL_GROUP 10003 /* Specified group. */ +#define ARCHIVE_ENTRY_ACL_GROUP_OBJ 10004 /* Group who owns the file. */ +#define ARCHIVE_ENTRY_ACL_MASK 10005 /* Modify group access (POSIX.1e only) */ +#define ARCHIVE_ENTRY_ACL_OTHER 10006 /* Public (POSIX.1e only) */ +#define ARCHIVE_ENTRY_ACL_EVERYONE 10107 /* Everyone (NFS4 only) */ + +/* + * Set the ACL by clearing it and adding entries one at a time. + * Unlike the POSIX.1e ACL routines, you must specify the type + * (access/default) for each entry. Internally, the ACL data is just + * a soup of entries. API calls here allow you to retrieve just the + * entries of interest. This design (which goes against the spirit of + * POSIX.1e) is useful for handling archive formats that combine + * default and access information in a single ACL list. + */ +__LA_DECL void archive_entry_acl_clear(struct archive_entry *); +__LA_DECL int archive_entry_acl_add_entry(struct archive_entry *, + int /* type */, int /* permset */, int /* tag */, + int /* qual */, const char * /* name */); +__LA_DECL int archive_entry_acl_add_entry_w(struct archive_entry *, + int /* type */, int /* permset */, int /* tag */, + int /* qual */, const wchar_t * /* name */); + +/* + * To retrieve the ACL, first "reset", then repeatedly ask for the + * "next" entry. The want_type parameter allows you to request only + * certain types of entries. + */ +__LA_DECL int archive_entry_acl_reset(struct archive_entry *, int /* want_type */); +__LA_DECL int archive_entry_acl_next(struct archive_entry *, int /* want_type */, + int * /* type */, int * /* permset */, int * /* tag */, + int * /* qual */, const char ** /* name */); + +/* + * Construct a text-format ACL. The flags argument is a bitmask that + * can include any of the following: + * + * Flags only for archive entries with POSIX.1e ACL: + * ARCHIVE_ENTRY_ACL_TYPE_ACCESS - Include POSIX.1e "access" entries. + * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - Include POSIX.1e "default" entries. + * ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT - Include "default:" before each + * default ACL entry. + * ARCHIVE_ENTRY_ACL_STYLE_SOLARIS - Output only one colon after "other" and + * "mask" entries. + * + * Flags only for archive entries with NFSv4 ACL: + * ARCHIVE_ENTRY_ACL_STYLE_COMPACT - Do not output the minus character for + * unset permissions and flags in NFSv4 ACL permission and flag fields + * + * Flags for for archive entries with POSIX.1e ACL or NFSv4 ACL: + * ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in + * each ACL entry. + * ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA - Separate entries with comma + * instead of newline. + */ +#define ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 0x00000001 +#define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 0x00000002 +#define ARCHIVE_ENTRY_ACL_STYLE_SOLARIS 0x00000004 +#define ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA 0x00000008 +#define ARCHIVE_ENTRY_ACL_STYLE_COMPACT 0x00000010 + +__LA_DECL wchar_t *archive_entry_acl_to_text_w(struct archive_entry *, + la_ssize_t * /* len */, int /* flags */); +__LA_DECL char *archive_entry_acl_to_text(struct archive_entry *, + la_ssize_t * /* len */, int /* flags */); +__LA_DECL int archive_entry_acl_from_text_w(struct archive_entry *, + const wchar_t * /* wtext */, int /* type */); +__LA_DECL int archive_entry_acl_from_text(struct archive_entry *, + const char * /* text */, int /* type */); + +/* Deprecated constants */ +#define OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 1024 +#define OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048 + +/* Deprecated functions */ +__LA_DECL const wchar_t *archive_entry_acl_text_w(struct archive_entry *, + int /* flags */) __LA_DEPRECATED; +__LA_DECL const char *archive_entry_acl_text(struct archive_entry *, + int /* flags */) __LA_DEPRECATED; + +/* Return bitmask of ACL types in an archive entry */ +__LA_DECL int archive_entry_acl_types(struct archive_entry *); + +/* Return a count of entries matching 'want_type' */ +__LA_DECL int archive_entry_acl_count(struct archive_entry *, int /* want_type */); + +/* Return an opaque ACL object. */ +/* There's not yet anything clients can actually do with this... */ +struct archive_acl; +__LA_DECL struct archive_acl *archive_entry_acl(struct archive_entry *); + +/* + * extended attributes + */ + +__LA_DECL void archive_entry_xattr_clear(struct archive_entry *); +__LA_DECL void archive_entry_xattr_add_entry(struct archive_entry *, + const char * /* name */, const void * /* value */, + size_t /* size */); + +/* + * To retrieve the xattr list, first "reset", then repeatedly ask for the + * "next" entry. + */ + +__LA_DECL int archive_entry_xattr_count(struct archive_entry *); +__LA_DECL int archive_entry_xattr_reset(struct archive_entry *); +__LA_DECL int archive_entry_xattr_next(struct archive_entry *, + const char ** /* name */, const void ** /* value */, size_t *); + +/* + * sparse + */ + +__LA_DECL void archive_entry_sparse_clear(struct archive_entry *); +__LA_DECL void archive_entry_sparse_add_entry(struct archive_entry *, + la_int64_t /* offset */, la_int64_t /* length */); + +/* + * To retrieve the xattr list, first "reset", then repeatedly ask for the + * "next" entry. + */ + +__LA_DECL int archive_entry_sparse_count(struct archive_entry *); +__LA_DECL int archive_entry_sparse_reset(struct archive_entry *); +__LA_DECL int archive_entry_sparse_next(struct archive_entry *, + la_int64_t * /* offset */, la_int64_t * /* length */); + +/* + * Utility to match up hardlinks. + * + * The 'struct archive_entry_linkresolver' is a cache of archive entries + * for files with multiple links. Here's how to use it: + * 1. Create a lookup object with archive_entry_linkresolver_new() + * 2. Tell it the archive format you're using. + * 3. Hand each archive_entry to archive_entry_linkify(). + * That function will return 0, 1, or 2 entries that should + * be written. + * 4. Call archive_entry_linkify(resolver, NULL) until + * no more entries are returned. + * 5. Call archive_entry_linkresolver_free(resolver) to free resources. + * + * The entries returned have their hardlink and size fields updated + * appropriately. If an entry is passed in that does not refer to + * a file with multiple links, it is returned unchanged. The intention + * is that you should be able to simply filter all entries through + * this machine. + * + * To make things more efficient, be sure that each entry has a valid + * nlinks value. The hardlink cache uses this to track when all links + * have been found. If the nlinks value is zero, it will keep every + * name in the cache indefinitely, which can use a lot of memory. + * + * Note that archive_entry_size() is reset to zero if the file + * body should not be written to the archive. Pay attention! + */ +struct archive_entry_linkresolver; + +/* + * There are three different strategies for marking hardlinks. + * The descriptions below name them after the best-known + * formats that rely on each strategy: + * + * "Old cpio" is the simplest, it always returns any entry unmodified. + * As far as I know, only cpio formats use this. Old cpio archives + * store every link with the full body; the onus is on the dearchiver + * to detect and properly link the files as they are restored. + * "tar" is also pretty simple; it caches a copy the first time it sees + * any link. Subsequent appearances are modified to be hardlink + * references to the first one without any body. Used by all tar + * formats, although the newest tar formats permit the "old cpio" strategy + * as well. This strategy is very simple for the dearchiver, + * and reasonably straightforward for the archiver. + * "new cpio" is trickier. It stores the body only with the last + * occurrence. The complication is that we might not + * see every link to a particular file in a single session, so + * there's no easy way to know when we've seen the last occurrence. + * The solution here is to queue one link until we see the next. + * At the end of the session, you can enumerate any remaining + * entries by calling archive_entry_linkify(NULL) and store those + * bodies. If you have a file with three links l1, l2, and l3, + * you'll get the following behavior if you see all three links: + * linkify(l1) => NULL (the resolver stores l1 internally) + * linkify(l2) => l1 (resolver stores l2, you write l1) + * linkify(l3) => l2, l3 (all links seen, you can write both). + * If you only see l1 and l2, you'll get this behavior: + * linkify(l1) => NULL + * linkify(l2) => l1 + * linkify(NULL) => l2 (at end, you retrieve remaining links) + * As the name suggests, this strategy is used by newer cpio variants. + * It's noticeably more complex for the archiver, slightly more complex + * for the dearchiver than the tar strategy, but makes it straightforward + * to restore a file using any link by simply continuing to scan until + * you see a link that is stored with a body. In contrast, the tar + * strategy requires you to rescan the archive from the beginning to + * correctly extract an arbitrary link. + */ + +__LA_DECL struct archive_entry_linkresolver *archive_entry_linkresolver_new(void); +__LA_DECL void archive_entry_linkresolver_set_strategy( + struct archive_entry_linkresolver *, int /* format_code */); +__LA_DECL void archive_entry_linkresolver_free(struct archive_entry_linkresolver *); +__LA_DECL void archive_entry_linkify(struct archive_entry_linkresolver *, + struct archive_entry **, struct archive_entry **); +__LA_DECL struct archive_entry *archive_entry_partial_links( + struct archive_entry_linkresolver *res, unsigned int *links); +#ifdef __cplusplus +} +#endif + +/* This is meaningless outside of this header. */ +#undef __LA_DECL + +#endif /* !ARCHIVE_ENTRY_H_INCLUDED */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_entry_acl.3 b/dependencies/libarchive-3.4.2/libarchive/archive_entry_acl.3 new file mode 100644 index 0000000..50dd642 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_entry_acl.3 @@ -0,0 +1,458 @@ +.\" Copyright (c) 2010 Joerg Sonnenberger +.\" Copyright (c) 2016 Martin Matuska +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd February 15, 2017 +.Dt ARCHIVE_ENTRY_ACL 3 +.Os +.Sh NAME +.Nm archive_entry_acl_add_entry , +.Nm archive_entry_acl_add_entry_w , +.Nm archive_entry_acl_clear , +.Nm archive_entry_acl_count , +.Nm archive_entry_acl_from_text , +.Nm archive_entry_acl_from_text_w , +.Nm archive_entry_acl_next , +.Nm archive_entry_acl_reset , +.Nm archive_entry_acl_to_text , +.Nm archive_entry_acl_to_text_w , +.Nm archive_entry_acl_types +.Nd functions for manipulating Access Control Lists in archive entry descriptions +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive_entry.h +.Ft void +.Fo archive_entry_acl_add_entry +.Fa "struct archive_entry *a" +.Fa "int type" +.Fa "int permset" +.Fa "int tag" +.Fa "int qualifier" +.Fa "const char *name" +.Fc +.Ft void +.Fo archive_entry_acl_add_entry_w +.Fa "struct archive_entry *a" +.Fa "int type" +.Fa "int permset" +.Fa "int tag" +.Fa "int qualifier" +.Fa "const wchar_t *name" +.Fc +.Ft void +.Fn archive_entry_acl_clear "struct archive_entry *a" +.Ft int +.Fn archive_entry_acl_count "struct archive_entry *a" "int type" +.Ft int +.Fo archive_entry_acl_from_text +.Fa "struct archive_entry *a" +.Fa "const char *text" +.Fa "int type" +.Fc +.Ft int +.Fo archive_entry_acl_from_text_w +.Fa "struct archive_entry *a" +.Fa "const wchar_t *text" +.Fa "int type" +.Fc +.Ft int +.Fo archive_entry_acl_next +.Fa "struct archive_entry *a" +.Fa "int type" +.Fa "int *ret_type" +.Fa "int *ret_permset" +.Fa "int *ret_tag" +.Fa "int *ret_qual" +.Fa "const char **ret_name" +.Fc +.Ft int +.Fn archive_entry_acl_reset "struct archive_entry *a" "int type" +.Ft char * +.Fo archive_entry_acl_to_text +.Fa "struct archive_entry *a" +.Fa "ssize_t *len_p" +.Fa "int flags" +.Fc +.Ft wchar_t * +.Fo archive_entry_acl_to_text_w +.Fa "struct archive_entry *a" +.Fa "ssize_t *len_p" +.Fa "int flags" +.Fc +.Ft int +.Fn archive_entry_acl_types "struct archive_entry *a" +.\" enum? +.Sh DESCRIPTION +The +.Dq Access Control Lists (ACLs) +extend the standard Unix permission model. +The ACL interface of +.Nm libarchive +supports both POSIX.1e and NFSv4 style ACLs. +Use of ACLs is restricted by +various levels of ACL support in operating systems, file systems and archive +formats. +.Ss POSIX.1e Access Control Lists +A POSIX.1e ACL consists of a number of independent entries. +Each entry specifies the permission set as a bitmask of basic permissions. +Valid permissions in the +.Fa permset +are: +.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_EXECUTE" +.It Dv ARCHIVE_ENTRY_ACL_READ ( Sy r ) +.It Dv ARCHIVE_ENTRY_ACL_WRITE ( Sy w ) +.It Dv ARCHIVE_ENTRY_ACL_EXECUTE ( Sy x ) +.El +The permissions correspond to the normal Unix permissions. +.Pp +The +.Fa tag +specifies the principal to which the permission applies. +Valid values are: +.Bl -hang -offset indent -compact -width "ARCHIVE_ENTRY_ACL_GROUP_OBJ" +.It Dv ARCHIVE_ENTRY_ACL_USER +The user specified by the name field. +.It Dv ARCHIVE_ENTRY_ACL_USER_OBJ +The owner of the file. +.It Dv ARCHIVE_ENTRY_ACL_GROUP +The group specified by the name field. +.It Dv ARCHIVE_ENTRY_ACL_GROUP_OBJ +The group which owns the file. +.It Dv ARCHIVE_ENTRY_ACL_MASK +The maximum permissions to be obtained via group permissions. +.It Dv ARCHIVE_ENTRY_ACL_OTHER +Any principal who is not the file owner or a member of the owning group. +.El +.Pp +The principals +.Dv ARCHIVE_ENTRY_ACL_USER_OBJ , +.Dv ARCHIVE_ENTRY_ACL_GROUP_OBJ +and +.Dv ARCHIVE_ENTRY_ACL_OTHER +are equivalent to user, group and other in the classic Unix permission +model and specify non-extended ACL entries. +.Pp +All files have an access ACL +.Pq Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS . +This specifies the permissions required for access to the file itself. +Directories have an additional ACL +.Pq Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT , +which controls the initial access ACL for newly-created directory entries. +.Ss NFSv4 Access Control Lists +A NFSv4 ACL consists of multiple individual entries called Access Control +Entries (ACEs). +.Pp +There are four possible types of a NFSv4 ACE: +.Bl -hang -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYE_ALLOW" +.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALLOW +Allow principal to perform actions requiring given permissions. +.It Dv ARCHIVE_ENTRY_ACL_TYPE_DENY +Prevent principal from performing actions requiring given permissions. +.It Dv ARCHIVE_ENTRY_ACL_TYPE_AUDIT +Log access attempts by principal which require given permissions. +.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALARM +Trigger a system alarm on access attempts by principal which require given +permissions. +.El +.Pp +The +.Fa tag +specifies the principal to which the permission applies. +Valid values are: +.Bl -hang -offset indent -compact -width "ARCHIVE_ENTRY_ACL_GROUP_OBJ" +.It Dv ARCHIVE_ENTRY_ACL_USER +The user specified by the name field. +.It Dv ARCHIVE_ENTRY_ACL_USER_OBJ +The owner of the file. +.It Dv ARCHIVE_ENTRY_ACL_GROUP +The group specified by the name field. +.It Dv ARCHIVE_ENTRY_ACL_GROUP_OBJ +The group which owns the file. +.It Dv ARCHIVE_ENTRY_ACL_EVERYONE +Any principal who is not the file owner or a member of the owning group. +.El +.Pp +Entries with the +.Dv ARCHIVE_ENTRY_ACL_USER +or +.Dv ARCHIVE_ENTRY_ACL_GROUP +tag store the user and group name in the +.Fa name +string and optionally the user or group ID in the +.Fa qualifier +integer. +.Pp +NFSv4 ACE permissions and flags are stored in the same +.Fa permset +bitfield. +Some permissions share the same constant and permission character +but have different effect on directories than on files. +The following ACE permissions are supported: +.Bl -tag -offset indent -compact -width ARCHIV +.It Dv ARCHIVE_ENTRY_ACL_READ_DATA ( Sy r ) +Read data (file). +.It Dv ARCHIVE_ENTRY_ACL_LIST_DIRECTORY ( Sy r ) +List entries (directory). +.It ARCHIVE_ENTRY_ACL_WRITE_DATA ( Sy w ) +Write data (file). +.It ARCHIVE_ENTRY_ACL_ADD_FILE ( Sy w ) +Create files (directory). +.It Dv ARCHIVE_ENTRY_ACL_EXECUTE ( Sy x ) +Execute file or change into a directory. +.It Dv ARCHIVE_ENTRY_ACL_APPEND_DATA ( Sy p ) +Append data (file). +.It Dv ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY ( Sy p ) +Create subdirectories (directory). +.It Dv ARCHIVE_ENTRY_ACL_DELETE_CHILD ( Sy D ) +Remove files and subdirectories inside a directory. +.It Dv ARCHIVE_ENTRY_ACL_DELETE ( Sy d ) +Remove file or directory. +.It Dv ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES ( Sy a ) +Read file or directory attributes. +.It Dv ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES ( Sy A ) +Write file or directory attributes. +.It Dv ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS ( Sy R ) +Read named file or directory attributes. +.It Dv ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS ( Sy W ) +Write named file or directory attributes. +.It Dv ARCHIVE_ENTRY_ACL_READ_ACL ( Sy c ) +Read file or directory ACL. +.It Dv ARCHIVE_ENTRY_ACL_WRITE_ACL ( Sy C ) +Write file or directory ACL. +.It Dv ARCHIVE_ENTRY_ACL_WRITE_OWNER ( Sy o ) +Change owner of a file or directory. +.It Dv ARCHIVE_ENTRY_ACL_SYNCHRONIZE ( Sy s ) +Use synchronous I/O. +.El +.Pp +The following NFSv4 ACL inheritance flags are supported: +.Bl -tag -offset indent -compact -width ARCHIV +.It Dv ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT ( Sy f ) +Inherit parent directory ACE to files. +.It Dv ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT ( Sy d ) +Inherit parent directory ACE to subdirectories. +.It Dv ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY ( Sy i ) +Only inherit, do not apply the permission on the directory itself. +.It Dv ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT ( Sy n ) +Do not propagate inherit flags. +Only first-level entries inherit ACLs. +.It Dv ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS ( Sy S ) +Trigger alarm or audit on successful access. +.It Dv ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS ( Sy F ) +Trigger alarm or audit on failed access. +.It Dv ARCHIVE_ENTRY_ACL_ENTRY_INHERITED ( Sy I ) +Mark that ACE was inherited. +.El +.Ss Functions +.Fn archive_entry_acl_add_entry +and +.Fn archive_entry_acl_add_entry_w +add a single ACL entry. +For the access ACL and non-extended principals, the classic Unix permissions +are updated. +An archive entry cannot contain both POSIX.1e and NFSv4 ACL entries. +.Pp +.Fn archive_entry_acl_clear +removes all ACL entries and resets the enumeration pointer. +.Pp +.Fn archive_entry_acl_count +counts the ACL entries that have the given type mask. +.Fa type +can be the bitwise-or of +.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYPE_DEFAULT" +.It Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS +.It Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT +.El +for POSIX.1e ACLs and +.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYPE_ALLOW" +.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALLOW +.It Dv ARCHIVE_ENTRY_ACL_TYPE_DENY +.It Dv ARCHIVE_ENTRY_ACL_TYPE_AUDIT +.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALARM +.El +for NFSv4 ACLs. +For POSIX.1e ACLs if +.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS +is included and at least one extended ACL entry is found, +the three non-extended ACLs are added. +.Pp +.Fn archive_entry_acl_from_text +and +.Fn archive_entry_acl_from_text_w +add new +.Pq or merge with existing +ACL entries from +.Pq wide +text. +The argument +.Fa type +may take one of the following values: +.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYPE_DEFAULT" +.It Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS +.It Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT +.It Dv ARCHIVE_ENTRY_ACL_TYPE_NFS4 +.El +Supports all formats that can be created with +.Fn archive_entry_acl_to_text +or respectively +.Fn archive_entry_acl_to_text_w . +Existing ACL entries are preserved. +To get a clean new ACL from text +.Fn archive_entry_acl_clear +must be called first. +Entries prefixed with +.Dq default: +are treated as +.Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT +unless +.Fa type +is +.Dv ARCHIVE_ENTRY_ACL_TYPE_NFS4 . +Invalid entries, non-parseable ACL entries and entries beginning with +the +.Sq # +character +.Pq comments +are skipped. +.Pp +.Fn archive_entry_acl_next +return the next entry of the ACL list. +This functions may only be called after +.Fn archive_entry_acl_reset +has indicated the presence of extended ACL entries. +.Pp +.Fn archive_entry_acl_reset +prepare reading the list of ACL entries with +.Fn archive_entry_acl_next . +The function returns 0 if no non-extended ACLs are found. +In this case, the access permissions should be obtained by +.Xr archive_entry_mode 3 +or set using +.Xr chmod 2 . +Otherwise, the function returns the same value as +.Fn archive_entry_acl_count . +.Pp +.Fn archive_entry_acl_to_text +and +.Fn archive_entry_acl_to_text_w +convert the ACL entries for the given type into a +.Pq wide +string of ACL entries separated by newline. +If the pointer +.Fa len_p +is not NULL, then the function shall return the length of the string +.Pq not including the NULL terminator +in the location pointed to by +.Fa len_p . +The +.Fa flag +argument is a bitwise-or. +.Pp +The following flags are effective only on POSIX.1e ACL: +.Bl -tag -offset indent -compact -width ARCHIV +.It Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS +Output access ACLs. +.It Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT +Output POSIX.1e default ACLs. +.It Dv ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT +Prefix each default ACL entry with the word +.Dq default: . +.It Dv ARCHIVE_ENTRY_ACL_STYLE_SOLARIS +The mask and other ACLs don not contain a double colon. +.El +.Pp +The following flags are effecive only on NFSv4 ACL: +.Bl -tag -offset indent -compact -width ARCHIV +.It Dv ARCHIVE_ENTRY_ACL_STYLE_COMPACT +Do not output minus characters for unset permissions and flags in NFSv4 ACL +permission and flag fields. +.El +.Pp +The following flags are effective on both POSIX.1e and NFSv4 ACL: +.Bl -tag -offset indent -compact -width ARCHIV +.It Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID +Add an additional colon-separated field containing the user or group id. +.It Dv ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA +Separate ACL entries with comma instead of newline. +.El +.Pp +If the archive entry contains NFSv4 ACLs, all types of NFSv4 ACLs are returned. +It the entry contains POSIX.1e ACLs and none of the flags +.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS +or +.Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT +are specified, both access and default entries are returned and default entries +are prefixed with +.Dq default: . +.Pp +.Fn archive_entry_acl_types +get ACL entry types contained in an archive entry's ACL. +As POSIX.1e and NFSv4 +ACL entries cannot be mixed, this function is a very efficient way to detect if +an ACL already contains POSIX.1e or NFSv4 ACL entries. +.Sh RETURN VALUES +.Fn archive_entry_acl_count +and +.Fn archive_entry_acl_reset +returns the number of ACL entries that match the given type mask. +For POSIX.1e ACLS if the type mask includes +.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS +and at least one extended ACL entry exists, the three classic Unix +permissions are counted. +.Pp +.Fn archive_entry_acl_from_text +and +.Fn archive_entry_acl_from_text_w +return +.Dv ARCHIVE_OK +if all entries were successfully parsed and +.Dv ARCHIVE_WARN +if one or more entries were invalid or non-parseable. +.Pp +.Fn archive_entry_acl_next +returns +.Dv ARCHIVE_OK +on success, +.Dv ARCHIVE_EOF +if no more ACL entries exist +and +.Dv ARCHIVE_WARN +if +.Fn archive_entry_acl_reset +has not been called first. +.Pp +.Fn archive_entry_acl_to_text +returns a string representing the ACL entries matching the given type and +flags on success or NULL on error. +.Pp +.Fn archive_entry_acl_to_text_w +returns a wide string representing the ACL entries matching the given type +and flags on success or NULL on error. +.Pp +.Fn archive_entry_acl_types +returns a bitmask of ACL entry types or 0 if archive entry has no ACL entries. +.Sh SEE ALSO +.Xr archive_entry 3 , +.Xr libarchive 3 diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_entry_copy_bhfi.c b/dependencies/libarchive-3.4.2/libarchive/archive_entry_copy_bhfi.c new file mode 100644 index 0000000..77bf38e --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_entry_copy_bhfi.c @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#include "archive_private.h" +#include "archive_entry.h" + +#if defined(_WIN32) && !defined(__CYGWIN__) + +#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) + +__inline static void +fileTimeToUtc(const FILETIME *filetime, time_t *t, long *ns) +{ + ULARGE_INTEGER utc; + + utc.HighPart = filetime->dwHighDateTime; + utc.LowPart = filetime->dwLowDateTime; + if (utc.QuadPart >= EPOC_TIME) { + utc.QuadPart -= EPOC_TIME; + *t = (time_t)(utc.QuadPart / 10000000); /* milli seconds base */ + *ns = (long)(utc.QuadPart % 10000000) * 100;/* nano seconds base */ + } else { + *t = 0; + *ns = 0; + } +} + +void +archive_entry_copy_bhfi(struct archive_entry *entry, + BY_HANDLE_FILE_INFORMATION *bhfi) +{ + time_t secs; + long nsecs; + + fileTimeToUtc(&bhfi->ftLastAccessTime, &secs, &nsecs); + archive_entry_set_atime(entry, secs, nsecs); + fileTimeToUtc(&bhfi->ftLastWriteTime, &secs, &nsecs); + archive_entry_set_mtime(entry, secs, nsecs); + fileTimeToUtc(&bhfi->ftCreationTime, &secs, &nsecs); + archive_entry_set_birthtime(entry, secs, nsecs); + archive_entry_set_ctime(entry, secs, nsecs); + archive_entry_set_dev(entry, bhfi->dwVolumeSerialNumber); + archive_entry_set_ino64(entry, (((int64_t)bhfi->nFileIndexHigh) << 32) + + bhfi->nFileIndexLow); + archive_entry_set_nlink(entry, bhfi->nNumberOfLinks); + archive_entry_set_size(entry, (((int64_t)bhfi->nFileSizeHigh) << 32) + + bhfi->nFileSizeLow); + /* archive_entry_set_mode(entry, st->st_mode); */ +} +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_entry_copy_stat.c b/dependencies/libarchive-3.4.2/libarchive/archive_entry_copy_stat.c new file mode 100644 index 0000000..ac83868 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_entry_copy_stat.c @@ -0,0 +1,83 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_entry_copy_stat.c 189466 2009-03-07 00:52:02Z kientzle $"); + +#ifdef HAVE_SYS_STAT_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" + +void +archive_entry_copy_stat(struct archive_entry *entry, const struct stat *st) +{ +#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC + archive_entry_set_atime(entry, st->st_atime, st->st_atimespec.tv_nsec); + archive_entry_set_ctime(entry, st->st_ctime, st->st_ctimespec.tv_nsec); + archive_entry_set_mtime(entry, st->st_mtime, st->st_mtimespec.tv_nsec); +#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC + archive_entry_set_atime(entry, st->st_atime, st->st_atim.tv_nsec); + archive_entry_set_ctime(entry, st->st_ctime, st->st_ctim.tv_nsec); + archive_entry_set_mtime(entry, st->st_mtime, st->st_mtim.tv_nsec); +#elif HAVE_STRUCT_STAT_ST_MTIME_NSEC + archive_entry_set_atime(entry, st->st_atime, st->st_atime_nsec); + archive_entry_set_ctime(entry, st->st_ctime, st->st_ctime_nsec); + archive_entry_set_mtime(entry, st->st_mtime, st->st_mtime_nsec); +#elif HAVE_STRUCT_STAT_ST_MTIME_N + archive_entry_set_atime(entry, st->st_atime, st->st_atime_n); + archive_entry_set_ctime(entry, st->st_ctime, st->st_ctime_n); + archive_entry_set_mtime(entry, st->st_mtime, st->st_mtime_n); +#elif HAVE_STRUCT_STAT_ST_UMTIME + archive_entry_set_atime(entry, st->st_atime, st->st_uatime * 1000); + archive_entry_set_ctime(entry, st->st_ctime, st->st_uctime * 1000); + archive_entry_set_mtime(entry, st->st_mtime, st->st_umtime * 1000); +#elif HAVE_STRUCT_STAT_ST_MTIME_USEC + archive_entry_set_atime(entry, st->st_atime, st->st_atime_usec * 1000); + archive_entry_set_ctime(entry, st->st_ctime, st->st_ctime_usec * 1000); + archive_entry_set_mtime(entry, st->st_mtime, st->st_mtime_usec * 1000); +#else + archive_entry_set_atime(entry, st->st_atime, 0); + archive_entry_set_ctime(entry, st->st_ctime, 0); + archive_entry_set_mtime(entry, st->st_mtime, 0); +#endif +#if HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC + archive_entry_set_birthtime(entry, st->st_birthtime, st->st_birthtimespec.tv_nsec); +#elif HAVE_STRUCT_STAT_ST_BIRTHTIME + archive_entry_set_birthtime(entry, st->st_birthtime, 0); +#else + archive_entry_unset_birthtime(entry); +#endif + archive_entry_set_dev(entry, st->st_dev); + archive_entry_set_gid(entry, st->st_gid); + archive_entry_set_uid(entry, st->st_uid); + archive_entry_set_ino(entry, st->st_ino); + archive_entry_set_nlink(entry, st->st_nlink); + archive_entry_set_rdev(entry, st->st_rdev); + archive_entry_set_size(entry, st->st_size); + archive_entry_set_mode(entry, st->st_mode); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_entry_link_resolver.c b/dependencies/libarchive-3.4.2/libarchive/archive_entry_link_resolver.c new file mode 100644 index 0000000..c7d5949 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_entry_link_resolver.c @@ -0,0 +1,447 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_entry_link_resolver.c 201100 2009-12-28 03:05:31Z kientzle $"); + +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" + +/* + * This is mostly a pretty straightforward hash table implementation. + * The only interesting bit is the different strategies used to + * match up links. These strategies match those used by various + * archiving formats: + * tar - content stored with first link, remainder refer back to it. + * This requires us to match each subsequent link up with the + * first appearance. + * cpio - Old cpio just stored body with each link, match-ups were + * implicit. This is trivial. + * new cpio - New cpio only stores body with last link, match-ups + * are implicit. This is actually quite tricky; see the notes + * below. + */ + +/* Users pass us a format code, we translate that into a strategy here. */ +#define ARCHIVE_ENTRY_LINKIFY_LIKE_TAR 0 +#define ARCHIVE_ENTRY_LINKIFY_LIKE_MTREE 1 +#define ARCHIVE_ENTRY_LINKIFY_LIKE_OLD_CPIO 2 +#define ARCHIVE_ENTRY_LINKIFY_LIKE_NEW_CPIO 3 + +/* Initial size of link cache. */ +#define links_cache_initial_size 1024 + +struct links_entry { + struct links_entry *next; + struct links_entry *previous; + struct archive_entry *canonical; + struct archive_entry *entry; + size_t hash; + unsigned int links; /* # links not yet seen */ +}; + +struct archive_entry_linkresolver { + struct links_entry **buckets; + struct links_entry *spare; + unsigned long number_entries; + size_t number_buckets; + int strategy; +}; + +#define NEXT_ENTRY_DEFERRED 1 +#define NEXT_ENTRY_PARTIAL 2 +#define NEXT_ENTRY_ALL (NEXT_ENTRY_DEFERRED | NEXT_ENTRY_PARTIAL) + +static struct links_entry *find_entry(struct archive_entry_linkresolver *, + struct archive_entry *); +static void grow_hash(struct archive_entry_linkresolver *); +static struct links_entry *insert_entry(struct archive_entry_linkresolver *, + struct archive_entry *); +static struct links_entry *next_entry(struct archive_entry_linkresolver *, + int); + +struct archive_entry_linkresolver * +archive_entry_linkresolver_new(void) +{ + struct archive_entry_linkresolver *res; + + /* Check for positive power-of-two */ + if (links_cache_initial_size == 0 || + (links_cache_initial_size & (links_cache_initial_size - 1)) != 0) + return (NULL); + + res = calloc(1, sizeof(struct archive_entry_linkresolver)); + if (res == NULL) + return (NULL); + res->number_buckets = links_cache_initial_size; + res->buckets = calloc(res->number_buckets, sizeof(res->buckets[0])); + if (res->buckets == NULL) { + free(res); + return (NULL); + } + return (res); +} + +void +archive_entry_linkresolver_set_strategy(struct archive_entry_linkresolver *res, + int fmt) +{ + int fmtbase = fmt & ARCHIVE_FORMAT_BASE_MASK; + + switch (fmtbase) { + case ARCHIVE_FORMAT_7ZIP: + case ARCHIVE_FORMAT_AR: + case ARCHIVE_FORMAT_ZIP: + res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_OLD_CPIO; + break; + case ARCHIVE_FORMAT_CPIO: + switch (fmt) { + case ARCHIVE_FORMAT_CPIO_SVR4_NOCRC: + case ARCHIVE_FORMAT_CPIO_SVR4_CRC: + res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_NEW_CPIO; + break; + default: + res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_OLD_CPIO; + break; + } + break; + case ARCHIVE_FORMAT_MTREE: + res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_MTREE; + break; + case ARCHIVE_FORMAT_ISO9660: + case ARCHIVE_FORMAT_SHAR: + case ARCHIVE_FORMAT_TAR: + case ARCHIVE_FORMAT_XAR: + res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_TAR; + break; + default: + res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_OLD_CPIO; + break; + } +} + +void +archive_entry_linkresolver_free(struct archive_entry_linkresolver *res) +{ + struct links_entry *le; + + if (res == NULL) + return; + + while ((le = next_entry(res, NEXT_ENTRY_ALL)) != NULL) + archive_entry_free(le->entry); + free(res->buckets); + free(res); +} + +void +archive_entry_linkify(struct archive_entry_linkresolver *res, + struct archive_entry **e, struct archive_entry **f) +{ + struct links_entry *le; + struct archive_entry *t; + + *f = NULL; /* Default: Don't return a second entry. */ + + if (*e == NULL) { + le = next_entry(res, NEXT_ENTRY_DEFERRED); + if (le != NULL) { + *e = le->entry; + le->entry = NULL; + } + return; + } + + /* If it has only one link, then we're done. */ + if (archive_entry_nlink(*e) == 1) + return; + /* Directories, devices never have hardlinks. */ + if (archive_entry_filetype(*e) == AE_IFDIR + || archive_entry_filetype(*e) == AE_IFBLK + || archive_entry_filetype(*e) == AE_IFCHR) + return; + + switch (res->strategy) { + case ARCHIVE_ENTRY_LINKIFY_LIKE_TAR: + le = find_entry(res, *e); + if (le != NULL) { + archive_entry_unset_size(*e); + archive_entry_copy_hardlink(*e, + archive_entry_pathname(le->canonical)); + } else + insert_entry(res, *e); + return; + case ARCHIVE_ENTRY_LINKIFY_LIKE_MTREE: + le = find_entry(res, *e); + if (le != NULL) { + archive_entry_copy_hardlink(*e, + archive_entry_pathname(le->canonical)); + } else + insert_entry(res, *e); + return; + case ARCHIVE_ENTRY_LINKIFY_LIKE_OLD_CPIO: + /* This one is trivial. */ + return; + case ARCHIVE_ENTRY_LINKIFY_LIKE_NEW_CPIO: + le = find_entry(res, *e); + if (le != NULL) { + /* + * Put the new entry in le, return the + * old entry from le. + */ + t = *e; + *e = le->entry; + le->entry = t; + /* Make the old entry into a hardlink. */ + archive_entry_unset_size(*e); + archive_entry_copy_hardlink(*e, + archive_entry_pathname(le->canonical)); + /* If we ran out of links, return the + * final entry as well. */ + if (le->links == 0) { + *f = le->entry; + le->entry = NULL; + } + } else { + /* + * If we haven't seen it, tuck it away + * for future use. + */ + le = insert_entry(res, *e); + if (le == NULL) + /* XXX We should return an error code XXX */ + return; + le->entry = *e; + *e = NULL; + } + return; + default: + break; + } + return; +} + +static struct links_entry * +find_entry(struct archive_entry_linkresolver *res, + struct archive_entry *entry) +{ + struct links_entry *le; + size_t hash, bucket; + dev_t dev; + int64_t ino; + + /* Free a held entry. */ + if (res->spare != NULL) { + archive_entry_free(res->spare->canonical); + archive_entry_free(res->spare->entry); + free(res->spare); + res->spare = NULL; + } + + dev = archive_entry_dev(entry); + ino = archive_entry_ino64(entry); + hash = (size_t)(dev ^ ino); + + /* Try to locate this entry in the links cache. */ + bucket = hash & (res->number_buckets - 1); + for (le = res->buckets[bucket]; le != NULL; le = le->next) { + if (le->hash == hash + && dev == archive_entry_dev(le->canonical) + && ino == archive_entry_ino64(le->canonical)) { + /* + * Decrement link count each time and release + * the entry if it hits zero. This saves + * memory and is necessary for detecting + * missed links. + */ + --le->links; + if (le->links > 0) + return (le); + /* Remove it from this hash bucket. */ + if (le->previous != NULL) + le->previous->next = le->next; + if (le->next != NULL) + le->next->previous = le->previous; + if (res->buckets[bucket] == le) + res->buckets[bucket] = le->next; + res->number_entries--; + /* Defer freeing this entry. */ + res->spare = le; + return (le); + } + } + return (NULL); +} + +static struct links_entry * +next_entry(struct archive_entry_linkresolver *res, int mode) +{ + struct links_entry *le; + size_t bucket; + + /* Free a held entry. */ + if (res->spare != NULL) { + archive_entry_free(res->spare->canonical); + archive_entry_free(res->spare->entry); + free(res->spare); + res->spare = NULL; + } + + /* Look for next non-empty bucket in the links cache. */ + for (bucket = 0; bucket < res->number_buckets; bucket++) { + for (le = res->buckets[bucket]; le != NULL; le = le->next) { + if (le->entry != NULL && + (mode & NEXT_ENTRY_DEFERRED) == 0) + continue; + if (le->entry == NULL && + (mode & NEXT_ENTRY_PARTIAL) == 0) + continue; + /* Remove it from this hash bucket. */ + if (le->next != NULL) + le->next->previous = le->previous; + if (le->previous != NULL) + le->previous->next = le->next; + else + res->buckets[bucket] = le->next; + res->number_entries--; + /* Defer freeing this entry. */ + res->spare = le; + return (le); + } + } + return (NULL); +} + +static struct links_entry * +insert_entry(struct archive_entry_linkresolver *res, + struct archive_entry *entry) +{ + struct links_entry *le; + size_t hash, bucket; + + /* Add this entry to the links cache. */ + le = calloc(1, sizeof(struct links_entry)); + if (le == NULL) + return (NULL); + le->canonical = archive_entry_clone(entry); + + /* If the links cache is getting too full, enlarge the hash table. */ + if (res->number_entries > res->number_buckets * 2) + grow_hash(res); + + hash = (size_t)(archive_entry_dev(entry) ^ archive_entry_ino64(entry)); + bucket = hash & (res->number_buckets - 1); + + /* If we could allocate the entry, record it. */ + if (res->buckets[bucket] != NULL) + res->buckets[bucket]->previous = le; + res->number_entries++; + le->next = res->buckets[bucket]; + le->previous = NULL; + res->buckets[bucket] = le; + le->hash = hash; + le->links = archive_entry_nlink(entry) - 1; + return (le); +} + +static void +grow_hash(struct archive_entry_linkresolver *res) +{ + struct links_entry *le, **new_buckets; + size_t new_size; + size_t i, bucket; + + /* Try to enlarge the bucket list. */ + new_size = res->number_buckets * 2; + if (new_size < res->number_buckets) + return; + new_buckets = calloc(new_size, sizeof(struct links_entry *)); + + if (new_buckets == NULL) + return; + + for (i = 0; i < res->number_buckets; i++) { + while (res->buckets[i] != NULL) { + /* Remove entry from old bucket. */ + le = res->buckets[i]; + res->buckets[i] = le->next; + + /* Add entry to new bucket. */ + bucket = le->hash & (new_size - 1); + + if (new_buckets[bucket] != NULL) + new_buckets[bucket]->previous = le; + le->next = new_buckets[bucket]; + le->previous = NULL; + new_buckets[bucket] = le; + } + } + free(res->buckets); + res->buckets = new_buckets; + res->number_buckets = new_size; +} + +struct archive_entry * +archive_entry_partial_links(struct archive_entry_linkresolver *res, + unsigned int *links) +{ + struct archive_entry *e; + struct links_entry *le; + + /* Free a held entry. */ + if (res->spare != NULL) { + archive_entry_free(res->spare->canonical); + archive_entry_free(res->spare->entry); + free(res->spare); + res->spare = NULL; + } + + le = next_entry(res, NEXT_ENTRY_PARTIAL); + if (le != NULL) { + e = le->canonical; + if (links != NULL) + *links = le->links; + le->canonical = NULL; + } else { + e = NULL; + if (links != NULL) + *links = 0; + } + return (e); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_entry_linkify.3 b/dependencies/libarchive-3.4.2/libarchive/archive_entry_linkify.3 new file mode 100644 index 0000000..8c19fdd --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_entry_linkify.3 @@ -0,0 +1,224 @@ +.\" Copyright (c) 2010 Joerg Sonnenberger +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd February 2, 2012 +.Dt ARCHIVE_ENTRY_LINKIFY 3 +.Os +.Sh NAME +.Nm archive_entry_linkresolver , +.Nm archive_entry_linkresolver_new , +.Nm archive_entry_linkresolver_set_strategy , +.Nm archive_entry_linkresolver_free , +.Nm archive_entry_linkify +.Nd hardlink resolver functions +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive_entry.h +.Ft struct archive_entry_linkresolver * +.Fn archive_entry_linkresolver_new void +.Ft void +.Fo archive_entry_linkresolver_set_strategy +.Fa "struct archive_entry_linkresolver *resolver" +.Fa "int format" +.Fc +.Ft void +.Fo archive_entry_linkresolver_free +.Fa "struct archive_entry_linkresolver *resolver" +.Fc +.Ft void +.Fo archive_entry_linkify +.Fa "struct archive_entry_linkresolver *resolver" +.Fa "struct archive_entry **entry" +.Fa "struct archive_entry **sparse" +.Fc +.Sh DESCRIPTION +Programs that want to create archives have to deal with hardlinks. +Hardlinks are handled in different ways by the archive formats. +The basic strategies are: +.Bl -enum +.It +Ignore hardlinks and store the body for each reference (old cpio, zip). +.It +Store the body the first time an inode is seen (ustar, pax). +.It +Store the body the last time an inode is seen (new cpio). +.El +.Pp +The +.Nm +functions help by providing a unified interface and handling the complexity +behind the scene. +.Pp +The +.Nm +functions assume that +.Vt archive_entry +instances have valid nlinks, inode and device values. +The inode and device value is used to match entries. +The nlinks value is used to determined if all references have been found and +if the internal references can be recycled. +.Pp +The +.Fn archive_entry_linkresolver_new +function allocates a new link resolver. +The instance can be freed using +.Fn archive_entry_linkresolver_free . +All deferred entries are flushed and the internal storage is freed. +.Pp +The +.Fn archive_entry_linkresolver_set_strategy +function selects the optimal hardlink strategy for the given format. +The format code can be obtained from +.Xr archive_format 3 . +The function can be called more than once, but it is recommended to +flush all deferred entries first. +.Pp +The +.Fn archive_entry_linkify +function is the core of +.Nm . +The +.Fn entry +argument points to the +.Vt archive_entry +that should be written. +Depending on the strategy one of the following actions is taken: +.Bl -enum +.It +For the simple archive formats +.Va *entry +is left unmodified and +.Va *sparse +is set to +.Dv NULL . +.It +For tar like archive formats, +.Va *sparse +is set to +.Dv NULL . +If +.Va *entry +is +.Dv NULL , +no action is taken. +If the hardlink count of +.Va *entry +is larger than 1 and the file type is a regular file or symbolic link, +the internal list is searched for a matching inode. +If such an inode is found, the link count is decremented and the file size +of +.Va *entry +is set to 0 to notify that no body should be written. +If no such inode is found, a copy of the entry is added to the internal cache +with a link count reduced by one. +.It +For new cpio like archive formats a value for +.Va *entry +of +.Dv NULL +is used to flush deferred entries. +In that case +.Va *entry +is set to an arbitrary deferred entry and the entry itself is removed from the +internal list. +If the internal list is empty, +.Va *entry +is set to +.Dv NULL . +In either case, +.Va *sparse +is set to +.Dv NULL +and the function returns. +If the hardlink count of +.Va *entry +is one or the file type is a directory or device, +.Va *sparse +is set to +.Dv NULL +and no further action is taken. +Otherwise, the internal list is searched for a matching inode. +If such an inode is not found, the entry is added to the internal list, +both +.Va *entry +and +.Va *sparse +are set to +.Dv NULL +and the function returns. +If such an inode is found, the link count is decremented. +If it remains larger than one, the existing entry on the internal list +is swapped with +.Va *entry +after retaining the link count. +The existing entry is returned in +.Va *entry . +If the link count reached one, the new entry is also removed from the +internal list and returned in +.Va *sparse . +Otherwise +.Va *sparse +is set to +.Dv NULL . +.El +.Pp +The general usage is therefore: +.Bl -enum +.It +For each new archive entry, call +.Fn archive_entry_linkify . +.It +Keep in mind that the entries returned may have a size of 0 now. +.It +If +.Va *entry +is not +.Dv NULL , +archive it. +.It +If +.Va *sparse +is not +.Dv NULL , +archive it. +.It +After all entries have been written to disk, call +.Fn archive_entry_linkify +with +.Va *entry +set to +.Dv NULL +and archive the returned entry as long as it is not +.Dv NULL . +.El +.Sh RETURN VALUES +.Fn archive_entry_linkresolver_new +returns +.Dv NULL +on +.Xr malloc 3 +failures. +.Sh SEE ALSO +.Xr archive_entry 3 diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_entry_locale.h b/dependencies/libarchive-3.4.2/libarchive/archive_entry_locale.h new file mode 100644 index 0000000..803c036 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_entry_locale.h @@ -0,0 +1,92 @@ +/*- + * Copyright (c) 2011 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef ARCHIVE_ENTRY_LOCALE_H_INCLUDED +#define ARCHIVE_ENTRY_LOCALE_H_INCLUDED + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif + +struct archive_entry; +struct archive_string_conv; + +/* + * Utility functions to set and get entry attributes by translating + * character-set. These are designed for use in format readers and writers. + * + * The return code and interface of these are quite different from other + * functions for archive_entry defined in archive_entry.h. + * Common return code are: + * Return 0 if the string conversion succeeded. + * Return -1 if the string conversion failed. + */ + +#define archive_entry_gname_l _archive_entry_gname_l +int _archive_entry_gname_l(struct archive_entry *, + const char **, size_t *, struct archive_string_conv *); +#define archive_entry_hardlink_l _archive_entry_hardlink_l +int _archive_entry_hardlink_l(struct archive_entry *, + const char **, size_t *, struct archive_string_conv *); +#define archive_entry_pathname_l _archive_entry_pathname_l +int _archive_entry_pathname_l(struct archive_entry *, + const char **, size_t *, struct archive_string_conv *); +#define archive_entry_symlink_l _archive_entry_symlink_l +int _archive_entry_symlink_l(struct archive_entry *, + const char **, size_t *, struct archive_string_conv *); +#define archive_entry_uname_l _archive_entry_uname_l +int _archive_entry_uname_l(struct archive_entry *, + const char **, size_t *, struct archive_string_conv *); +#define archive_entry_acl_text_l _archive_entry_acl_text_l +int _archive_entry_acl_text_l(struct archive_entry *, int, +const char **, size_t *, struct archive_string_conv *) __LA_DEPRECATED; +#define archive_entry_acl_to_text_l _archive_entry_acl_to_text_l +char *_archive_entry_acl_to_text_l(struct archive_entry *, ssize_t *, int, + struct archive_string_conv *); +#define archive_entry_acl_from_text_l _archive_entry_acl_from_text_l +int _archive_entry_acl_from_text_l(struct archive_entry *, const char* text, + int type, struct archive_string_conv *); +#define archive_entry_copy_gname_l _archive_entry_copy_gname_l +int _archive_entry_copy_gname_l(struct archive_entry *, + const char *, size_t, struct archive_string_conv *); +#define archive_entry_copy_hardlink_l _archive_entry_copy_hardlink_l +int _archive_entry_copy_hardlink_l(struct archive_entry *, + const char *, size_t, struct archive_string_conv *); +#define archive_entry_copy_link_l _archive_entry_copy_link_l +int _archive_entry_copy_link_l(struct archive_entry *, + const char *, size_t, struct archive_string_conv *); +#define archive_entry_copy_pathname_l _archive_entry_copy_pathname_l +int _archive_entry_copy_pathname_l(struct archive_entry *, + const char *, size_t, struct archive_string_conv *); +#define archive_entry_copy_symlink_l _archive_entry_copy_symlink_l +int _archive_entry_copy_symlink_l(struct archive_entry *, + const char *, size_t, struct archive_string_conv *); +#define archive_entry_copy_uname_l _archive_entry_copy_uname_l +int _archive_entry_copy_uname_l(struct archive_entry *, + const char *, size_t, struct archive_string_conv *); + +#endif /* ARCHIVE_ENTRY_LOCALE_H_INCLUDED */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_entry_misc.3 b/dependencies/libarchive-3.4.2/libarchive/archive_entry_misc.3 new file mode 100644 index 0000000..dfab7dd --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_entry_misc.3 @@ -0,0 +1,63 @@ +.\" Copyright (c) 2019 Martin Matuska +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd April 15, 2019 +.Dt ARCHIVE_ENTRY_MISC 3 +.Os +.Sh NAME +.Nm archive_entry_symlink_type , +.Nm archive_entry_set_symlink_type +.Nd miscellaneous functions for manipulating properties of archive_entry +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive_entry.h +.Ft int +.Fn archive_entry_symlink_type "struct archive_entry *a" +.Ft void +.Fn archive_entry_set_symlink_type "struct archive_entry *a" "int" +.Sh DESCRIPTION +The function +.Fn archive_entry_symlink_type +returns and the function +.Fn archive_entry_set_symlink_type +sets the type of the symbolic link stored in an archive entry. +These functions +have special meaning on operating systems that support multiple symbolic link +types (e.g. Microsoft Windows). +.Pp +Supported values are: +.Bl -tag -width "AE_SYMLINK_TYPE_DIRECTORY" -compact +.It AE_SYMLINK_TYPE_UNDEFINED +Symbolic link target type is not defined (default on unix systems) +.It AE_SYMLINK_TYPE_FILE +Symbolic link points to a file +.It AE_SYMLINK_TYPE_DIRECTORY +Symbolic link points to a directory +.El +.Sh SEE ALSO +.Xr archive_entry 3 , +.Xr archive_entry_paths 3 , +.Xr archive_entry_stat 3 , +.Xr libarchive 3 diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_entry_paths.3 b/dependencies/libarchive-3.4.2/libarchive/archive_entry_paths.3 new file mode 100644 index 0000000..0f849c9 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_entry_paths.3 @@ -0,0 +1,153 @@ +.\" Copyright (c) 2010 Joerg Sonnenberger +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd February 2, 2012 +.Dt ARCHIVE_ENTRY_PATHS 3 +.Os +.Sh NAME +.Nm archive_entry_hardlink , +.Nm archive_entry_hardlink_w , +.Nm archive_entry_set_hardlink , +.Nm archive_entry_copy_hardlink , +.Nm archive_entry_copy_hardlink_w , +.Nm archive_entry_update_hardlink_utf8 , +.Nm archive_entry_set_link , +.Nm archive_entry_copy_link , +.Nm archive_entry_copy_link_w , +.Nm archive_entry_update_link_utf8 , +.Nm archive_entry_pathname , +.Nm archive_entry_pathname_w , +.Nm archive_entry_set_pathname , +.Nm archive_entry_copy_pathname , +.Nm archive_entry_copy_pathname_w , +.Nm archive_entry_update_pathname_utf8 , +.Nm archive_entry_sourcepath , +.Nm archive_entry_copy_sourcepath , +.Nm archive_entry_symlink , +.Nm archive_entry_symlink_w , +.Nm archive_entry_set_symlink , +.Nm archive_entry_copy_symlink , +.Nm archive_entry_copy_symlink_w , +.Nm archive_entry_update_symlink_utf8 +.Nd functions for manipulating path names in archive entry descriptions +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive_entry.h +.Ft const char * +.Fn archive_entry_hardlink "struct archive_entry *a" +.Ft const wchar_t * +.Fn archive_entry_hardlink_w "struct archive_entry *a" +.Ft void +.Fn archive_entry_set_hardlink "struct archive_entry *a" "const char *path" +.Ft void +.Fn archive_entry_copy_hardlink "struct archive_entry *a" "const char *path" +.Ft void +.Fn archive_entry_copy_hardlink_w "struct archive_entry *a "const wchar_t *path" +.Ft int +.Fn archive_entry_update_hardlink_utf8 "struct archive_entry *a" "const char *path" +.Ft void +.Fn archive_entry_set_link "struct archive_entry *a" "const char *path" +.Ft void +.Fn archive_entry_copy_link "struct archive_entry *a" " const char *path" +.Ft void +.Fn archive_entry_copy_link_w "struct archive_entry *a" " const wchar_t *path" +.Ft int +.Fn archive_entry_update_link_utf8 "struct archive_entry *a" " const char *path" +.Ft const char * +.Fn archive_entry_pathname "struct archive_entry *a" +.Ft const wchar_t * +.Fn archive_entry_pathname_w "struct archive_entry *a" +.Ft void +.Fn archive_entry_set_pathname "struct archive_entry *a" "const char *path" +.Ft void +.Fn archive_entry_copy_pathname "struct archive_entry *a" "const char *path" +.Ft void +.Fn archive_entry_copy_pathname_w "struct archive_entry *a" "const wchar_t *path" +.Ft int +.Fn archive_entry_update_pathname_utf8 "struct archive_entry *a" "const char *path" +.Ft const char * +.Fn archive_entry_sourcepath "struct archive_entry *a" +.Ft void +.Fn archive_entry_copy_sourcepath "struct archive_entry *a" "const char *path" +.Ft const char * +.Fn archive_entry_symlink "struct archive_entry *a" +.Ft const wchar_t * +.Fn archive_entry_symlink_w "struct archive_entry *a" +.Ft void +.Fn archive_entry_set_symlink "struct archive_entry *a" "const char *path" +.Ft void +.Fn archive_entry_copy_symlink "struct archive_entry *a" "const char *path" +.Ft void +.Fn archive_entry_copy_symlink_w "struct archive_entry *a" "const wchar_t *path" +.Ft int +.Fn archive_entry_update_symlink_utf8 "struct archive_entry *a" "const char *path" +.Sh DESCRIPTION +Path names supported by +.Xr archive_entry 3 : +.Bl -tag -width "sourcepath" -compact +.It hardlink +Destination of the hardlink. +.It link +Update only. +For a symlink, update the destination. +Otherwise, make the entry a hardlink and alter +the destination for that. +.It pathname +Path in the archive +.It sourcepath +Path on the disk for use by +.Xr archive_read_disk 3 . +.It symlink +Destination of the symbolic link. +.El +.Pp +Path names can be provided in one of three different ways: +.Bl -tag -width "wchar_t *" +.It char * +Multibyte strings in the current locale. +.It wchar_t * +Wide character strings in the current locale. +The accessor functions are named +.Fn XXX_w . +.It UTF-8 +Unicode strings encoded as UTF-8. +These are convenience functions to update both the multibyte and wide +character strings at the same time. +.El +.Pp +The sourcepath is a pure filesystem concept and never stored in an +archive directly. +.Pp +For that reason, it is only available as multibyte string. +The link path is a convenience function for conditionally setting +hardlink or symlink destination. +It doesn't have a corresponding get accessor function. +.Pp +.Fn archive_entry_set_XXX +is an alias for +.Fn archive_entry_copy_XXX . +.Sh SEE ALSO +.Xr archive_entry 3 , +.Xr libarchive 3 diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_entry_perms.3 b/dependencies/libarchive-3.4.2/libarchive/archive_entry_perms.3 new file mode 100644 index 0000000..0291b7b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_entry_perms.3 @@ -0,0 +1,209 @@ +.\" Copyright (c) 2003-2007 Tim Kientzle +.\" Copyright (c) 2010 Joerg Sonnenberger +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd February 2, 2012 +.Dt ARCHIVE_ENTRY_PERMS 3 +.Os +.Sh NAME +.Nm archive_entry_gid , +.Nm archive_entry_set_gid , +.Nm archive_entry_uid , +.Nm archive_entry_set_uid , +.Nm archive_entry_perm , +.Nm archive_entry_set_perm , +.Nm archive_entry_strmode , +.Nm archive_entry_uname , +.Nm archive_entry_uname_w , +.Nm archive_entry_set_uname , +.Nm archive_entry_copy_uname , +.Nm archive_entry_copy_uname_w , +.Nm archive_entry_update_uname_utf8 , +.Nm archive_entry_gname , +.Nm archive_entry_gname_w , +.Nm archive_entry_set_gname , +.Nm archive_entry_copy_gname , +.Nm archive_entry_copy_gname_w , +.Nm archive_entry_update_gname_utf8 , +.Nm archive_entry_fflags , +.Nm archive_entry_fflags_text , +.Nm archive_entry_set_fflags , +.Nm archive_entry_copy_fflags_text , +.Nm archive_entry_copy_fflags_text_w +.Nd functions for manipulating ownership and permissions in archive entry descriptions +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive_entry.h +.Ft gid_t +.Fn archive_entry_gid "struct archive_entry *a" +.Ft void +.Fn archive_entry_set_gid "struct archive_entry *a" "gid_t gid" +.Ft uid_t +.Fn archive_entry_uid "struct archive_entry *a" +.Ft void +.Fn archive_entry_set_uid "struct archive_entry *a" "uid_t uid" +.Ft mode_t +.Fn archive_entry_perm "struct archive_entry *a" +.Ft void +.Fn archive_entry_set_perm "struct archive_entry *a" "mode_t mode" +.Ft const char * +.Fn archive_entry_strmode "struct archive_entry *a" +.Ft const char * +.Fn archive_entry_gname "struct archive_entry *a" +.Ft const wchar_t * +.Fn archive_entry_gname_w "struct archive_entry *a" +.Ft void +.Fn archive_entry_set_gname "struct archive_entry *a" "const char *a" +.Ft void +.Fn archive_entry_copy_gname "struct archive_entry *a" "const char *name" +.Ft void +.Fn archive_entry_copy_gname_w "struct archive_entry *a" "const wchar_t *name" +.Ft int +.Fn archive_entry_update_gname_utf8 "struct archive_entry *a" "const char *name" +.Ft const char * +.Fn archive_entry_uname "struct archive_entry *a" +.Ft const wchar_t * +.Fn archive_entry_uname_w "struct archive_entry *a" +.Ft void +.Fn archive_entry_set_uname "struct archive_entry *a" "const char *name" +.Ft void +.Fn archive_entry_copy_uname "struct archive_entry *a" "const char *name" +.Ft void +.Fn archive_entry_copy_uname_w "struct archive_entry *a" "const wchar_t *name" +.Ft int +.Fn archive_entry_update_uname_utf8 "struct archive_entry *a" "const char *name" +.Ft void +.Fo archive_entry_fflags +.Fa "struct archive_entry *a" +.Fa "unsigned long *set_bits" +.Fa "unsigned long *clear_bits" +.Fc +.Ft const char * +.Fn archive_entry_fflags_text "struct archive_entry *a" +.Ft void +.Fo archive_entry_set_fflags +.Fa "struct archive_entry *a" +.Fa "unsigned long set_bits" +.Fa "unsigned long clear_bits" +.Fc +.Ft const char * +.Fn archive_entry_copy_fflags_text "struct archive_entry *a" "const char *text" +.Ft const wchar_t * +.Fn archive_entry_copy_fflags_text_w "struct archive_entry *a" "const wchar_t *text" +.Sh DESCRIPTION +.Ss User id, group id and mode +The functions +.Fn archive_entry_uid , +.Fn archive_entry_gid , +and +.Fn archive_entry_perm +can be used to extract the user id, group id and permission from the given entry. +The corresponding functions +.Fn archive_entry_set_uid , +.Fn archive_entry_set_gid , +and +.Fn archive_entry_set_perm +store the given user id, group id and permission in the entry. +The permission is also set as a side effect of calling +.Fn archive_entry_set_mode . +.Pp +.Fn archive_entry_strmode +returns a string representation of the permission as used by the long mode of +.Xr ls 1 . +.Ss User and group name +User and group names can be provided in one of three different ways: +.Bl -tag -width "wchar_t *" +.It char * +Multibyte strings in the current locale. +.It wchar_t * +Wide character strings in the current locale. +The accessor functions are named +.Fn XXX_w . +.It UTF-8 +Unicode strings encoded as UTF-8. +These are convenience functions to update both the multibyte and wide +character strings at the same time. +.El +.Pp +.Fn archive_entry_set_XXX +is an alias for +.Fn archive_entry_copy_XXX . +.Ss File Flags +File flags are transparently converted between a bitmap +representation and a textual format. +For example, if you set the bitmap and ask for text, the library +will build a canonical text format. +However, if you set a text format and request a text format, +you will get back the same text, even if it is ill-formed. +If you need to canonicalize a textual flags string, you should first set the +text form, then request the bitmap form, then use that to set the bitmap form. +Setting the bitmap format will clear the internal text representation +and force it to be reconstructed when you next request the text form. +.Pp +The bitmap format consists of two integers, one containing bits +that should be set, the other specifying bits that should be +cleared. +Bits not mentioned in either bitmap will be ignored. +Usually, the bitmap of bits to be cleared will be set to zero. +In unusual circumstances, you can force a fully-specified set +of file flags by setting the bitmap of flags to clear to the complement +of the bitmap of flags to set. +(This differs from +.Xr fflagstostr 3 , +which only includes names for set bits.) +Converting a bitmap to a textual string is a platform-specific +operation; bits that are not meaningful on the current platform +will be ignored. +.Pp +The canonical text format is a comma-separated list of flag names. +The +.Fn archive_entry_copy_fflags_text +and +.Fn archive_entry_copy_fflags_text_w +functions parse the provided text and set the internal bitmap values. +This is a platform-specific operation; names that are not meaningful +on the current platform will be ignored. +The function returns a pointer to the start of the first name that was not +recognized, or NULL if every name was recognized. +Note that every name \(em including names that follow an unrecognized +name \(em will be evaluated, and the bitmaps will be set to reflect +every name that is recognized. +(In particular, this differs from +.Xr strtofflags 3 , +which stops parsing at the first unrecognized name.) +.Sh SEE ALSO +.Xr archive_entry 3 , +.Xr archive_entry_acl 3 , +.Xr archive_read_disk 3 , +.Xr archive_write_disk 3 , +.Xr libarchive 3 +.Sh BUGS +The platform types +.Vt uid_t +and +.Vt gid_t +are often 16 or 32 bit wide. +In this case it is possible that the ids can not be correctly restored +from archives and get truncated. diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_entry_private.h b/dependencies/libarchive-3.4.2/libarchive/archive_entry_private.h new file mode 100644 index 0000000..2b9a084 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_entry_private.h @@ -0,0 +1,184 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: head/lib/libarchive/archive_entry_private.h 201096 2009-12-28 02:41:27Z kientzle $ + */ + +#ifndef ARCHIVE_ENTRY_PRIVATE_H_INCLUDED +#define ARCHIVE_ENTRY_PRIVATE_H_INCLUDED + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif + +#include "archive_acl_private.h" +#include "archive_string.h" + +struct ae_xattr { + struct ae_xattr *next; + + char *name; + void *value; + size_t size; +}; + +struct ae_sparse { + struct ae_sparse *next; + + int64_t offset; + int64_t length; +}; + +/* + * Description of an archive entry. + * + * Basically, this is a "struct stat" with a few text fields added in. + * + * TODO: Add "comment", "charset", and possibly other entries + * that are supported by "pax interchange" format. However, GNU, ustar, + * cpio, and other variants don't support these features, so they're not an + * excruciatingly high priority right now. + * + * TODO: "pax interchange" format allows essentially arbitrary + * key/value attributes to be attached to any entry. Supporting + * such extensions may make this library useful for special + * applications (e.g., a package manager could attach special + * package-management attributes to each entry). There are tricky + * API issues involved, so this is not going to happen until + * there's a real demand for it. + * + * TODO: Design a good API for handling sparse files. + */ +struct archive_entry { + struct archive *archive; + + /* + * Note that ae_stat.st_mode & AE_IFMT can be 0! + * + * This occurs when the actual file type of the object is not + * in the archive. For example, 'tar' archives store + * hardlinks without marking the type of the underlying + * object. + */ + + /* + * We have a "struct aest" for holding file metadata rather than just + * a "struct stat" because on some platforms the "struct stat" has + * fields which are too narrow to hold the range of possible values; + * we don't want to lose information if we read an archive and write + * out another (e.g., in "tar -cf new.tar @old.tar"). + * + * The "stat" pointer points to some form of platform-specific struct + * stat; it is declared as a void * rather than a struct stat * as + * some platforms have multiple varieties of stat structures. + */ + void *stat; + int stat_valid; /* Set to 0 whenever a field in aest changes. */ + + struct aest { + int64_t aest_atime; + uint32_t aest_atime_nsec; + int64_t aest_ctime; + uint32_t aest_ctime_nsec; + int64_t aest_mtime; + uint32_t aest_mtime_nsec; + int64_t aest_birthtime; + uint32_t aest_birthtime_nsec; + int64_t aest_gid; + int64_t aest_ino; + uint32_t aest_nlink; + uint64_t aest_size; + int64_t aest_uid; + /* + * Because converting between device codes and + * major/minor values is platform-specific and + * inherently a bit risky, we only do that conversion + * lazily. That way, we will do a better job of + * preserving information in those cases where no + * conversion is actually required. + */ + int aest_dev_is_broken_down; + dev_t aest_dev; + dev_t aest_devmajor; + dev_t aest_devminor; + int aest_rdev_is_broken_down; + dev_t aest_rdev; + dev_t aest_rdevmajor; + dev_t aest_rdevminor; + } ae_stat; + + int ae_set; /* bitmap of fields that are currently set */ +#define AE_SET_HARDLINK 1 +#define AE_SET_SYMLINK 2 +#define AE_SET_ATIME 4 +#define AE_SET_CTIME 8 +#define AE_SET_MTIME 16 +#define AE_SET_BIRTHTIME 32 +#define AE_SET_SIZE 64 +#define AE_SET_INO 128 +#define AE_SET_DEV 256 + + /* + * Use aes here so that we get transparent mbs<->wcs conversions. + */ + struct archive_mstring ae_fflags_text; /* Text fflags per fflagstostr(3) */ + unsigned long ae_fflags_set; /* Bitmap fflags */ + unsigned long ae_fflags_clear; + struct archive_mstring ae_gname; /* Name of owning group */ + struct archive_mstring ae_hardlink; /* Name of target for hardlink */ + struct archive_mstring ae_pathname; /* Name of entry */ + struct archive_mstring ae_symlink; /* symlink contents */ + struct archive_mstring ae_uname; /* Name of owner */ + + /* Not used within libarchive; useful for some clients. */ + struct archive_mstring ae_sourcepath; /* Path this entry is sourced from. */ + +#define AE_ENCRYPTION_NONE 0 +#define AE_ENCRYPTION_DATA 1 +#define AE_ENCRYPTION_METADATA 2 + char encryption; + + void *mac_metadata; + size_t mac_metadata_size; + + /* ACL support. */ + struct archive_acl acl; + + /* extattr support. */ + struct ae_xattr *xattr_head; + struct ae_xattr *xattr_p; + + /* sparse support. */ + struct ae_sparse *sparse_head; + struct ae_sparse *sparse_tail; + struct ae_sparse *sparse_p; + + /* Miscellaneous. */ + char strmode[12]; + + /* Symlink type support */ + int ae_symlink_type; +}; + +#endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_entry_sparse.c b/dependencies/libarchive-3.4.2/libarchive/archive_entry_sparse.c new file mode 100644 index 0000000..74917b3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_entry_sparse.c @@ -0,0 +1,156 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2010-2011 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#include "archive.h" +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_entry_private.h" + +/* + * sparse handling + */ + +void +archive_entry_sparse_clear(struct archive_entry *entry) +{ + struct ae_sparse *sp; + + while (entry->sparse_head != NULL) { + sp = entry->sparse_head->next; + free(entry->sparse_head); + entry->sparse_head = sp; + } + entry->sparse_tail = NULL; +} + +void +archive_entry_sparse_add_entry(struct archive_entry *entry, + la_int64_t offset, la_int64_t length) +{ + struct ae_sparse *sp; + + if (offset < 0 || length < 0) + /* Invalid value */ + return; + if (offset > INT64_MAX - length || + offset + length > archive_entry_size(entry)) + /* A value of "length" parameter is too large. */ + return; + if ((sp = entry->sparse_tail) != NULL) { + if (sp->offset + sp->length > offset) + /* Invalid value. */ + return; + if (sp->offset + sp->length == offset) { + if (sp->offset + sp->length + length < 0) + /* A value of "length" parameter is + * too large. */ + return; + /* Expand existing sparse block size. */ + sp->length += length; + return; + } + } + + if ((sp = (struct ae_sparse *)malloc(sizeof(*sp))) == NULL) + /* XXX Error XXX */ + return; + + sp->offset = offset; + sp->length = length; + sp->next = NULL; + + if (entry->sparse_head == NULL) + entry->sparse_head = entry->sparse_tail = sp; + else { + /* Add a new sparse block to the tail of list. */ + if (entry->sparse_tail != NULL) + entry->sparse_tail->next = sp; + entry->sparse_tail = sp; + } +} + + +/* + * returns number of the sparse entries + */ +int +archive_entry_sparse_count(struct archive_entry *entry) +{ + struct ae_sparse *sp; + int count = 0; + + for (sp = entry->sparse_head; sp != NULL; sp = sp->next) + count++; + + /* + * Sanity check if this entry is exactly sparse. + * If amount of sparse blocks is just one and it indicates the whole + * file data, we should remove it and return zero. + */ + if (count == 1) { + sp = entry->sparse_head; + if (sp->offset == 0 && + sp->length >= archive_entry_size(entry)) { + count = 0; + archive_entry_sparse_clear(entry); + } + } + + return (count); +} + +int +archive_entry_sparse_reset(struct archive_entry * entry) +{ + entry->sparse_p = entry->sparse_head; + + return archive_entry_sparse_count(entry); +} + +int +archive_entry_sparse_next(struct archive_entry * entry, + la_int64_t *offset, la_int64_t *length) +{ + if (entry->sparse_p) { + *offset = entry->sparse_p->offset; + *length = entry->sparse_p->length; + + entry->sparse_p = entry->sparse_p->next; + + return (ARCHIVE_OK); + } else { + *offset = 0; + *length = 0; + return (ARCHIVE_WARN); + } +} + +/* + * end of sparse handling + */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_entry_stat.3 b/dependencies/libarchive-3.4.2/libarchive/archive_entry_stat.3 new file mode 100644 index 0000000..aa5c8e0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_entry_stat.3 @@ -0,0 +1,274 @@ +.\" Copyright (c) 2010 Joerg Sonnenberger +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd February 2, 2012 +.Dt ARCHIVE_ENTRY_STAT 3 +.Os +.Sh NAME +.Nm archive_entry_stat , +.Nm archive_entry_copy_stat , +.Nm archive_entry_filetype , +.Nm archive_entry_set_filetype , +.Nm archive_entry_mode , +.Nm archive_entry_set_mode , +.Nm archive_entry_size , +.Nm archive_entry_size_is_set , +.Nm archive_entry_set_size , +.Nm archive_entry_unset_size , +.Nm archive_entry_dev , +.Nm archive_entry_set_dev , +.Nm archive_entry_dev_is_set , +.Nm archive_entry_devmajor , +.Nm archive_entry_set_devmajor , +.Nm archive_entry_devminor , +.Nm archive_entry_set_devminor , +.Nm archive_entry_ino , +.Nm archive_entry_set_ino , +.Nm archive_entry_ino_is_set , +.Nm archive_entry_ino64 , +.Nm archive_entry_set_ino64 , +.Nm archive_entry_nlink , +.Nm archive_entry_rdev , +.Nm archive_entry_set_rdev , +.Nm archive_entry_rdevmajor , +.Nm archive_entry_set_rdevmajor , +.Nm archive_entry_rdevminor , +.Nm archive_entry_set_rdevminor +.Nd accessor functions for manipulating archive entry descriptions +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive_entry.h +.Ft const struct stat * +.Fn archive_entry_stat "struct archive_entry *a" +.Ft void +.Fn archive_entry_copy_stat "struct archive_entry *a" "const struct stat *sb" +.Ft mode_t +.Fn archive_entry_filetype "struct archive_entry *a" +.Ft void +.Fn archive_entry_set_filetype "struct archive_entry *a" "unsigned int type" +.Ft mode_t +.Fn archive_entry_mode "struct archive_entry *a" +.Ft void +.Fn archive_entry_set_mode "struct archive_entry *a" "mode_t mode" +.Ft int64_t +.Fn archive_entry_size "struct archive_entry *a" +.Ft int +.Fn archive_entry_size_is_set "struct archive_entry *a" +.Ft void +.Fn archive_entry_set_size "struct archive_entry *a" "int64_t size" +.Ft void +.Fn archive_entry_unset_size "struct archive_entry *a" +.Ft dev_t +.Fn archive_entry_dev "struct archive_entry *a" +.Ft void +.Fn archive_entry_set_dev "struct archive_entry *a" "dev_t dev" +.Ft int +.Fn archive_entry_dev_is_set "struct archive_entry *a" +.Ft dev_t +.Fn archive_entry_devmajor "struct archive_entry *a" +.Ft void +.Fn archive_entry_set_devmajor "struct archive_entry *a" "dev_t major" +.Ft dev_t +.Fn archive_entry_devminor "struct archive_entry *a" +.Ft void +.Fn archive_entry_set_devminor "struct archive_entry *a" "dev_t minor" +.Ft ino_t +.Fn archive_entry_ino "struct archive_entry *a" +.Ft void +.Fn archive_entry_set_ino "struct archive_entry *a" "unsigned long ino" +.Ft int +.Fn archive_entry_ino_is_set "struct archive_entry *a" +.Ft int64_t +.Fn archive_entry_ino64 "struct archive_entry *a" +.Ft void +.Fn archive_entry_set_ino64 "struct archive_entry *a" "int64_t ino" +.Ft unsigned int +.Fn archive_entry_nlink "struct archive_entry *a" +.Ft void +.Fn archive_entry_set_nlink "struct archive_entry *a" "unsigned int count" +.Ft dev_t +.Fn archive_entry_rdev "struct archive_entry *a" +.Ft dev_t +.Fn archive_entry_rdevmajor "struct archive_entry *a" +.Ft dev_t +.Fn archive_entry_rdevminor "struct archive_entry *a" +.Ft void +.Fn archive_entry_set_rdev "struct archive_entry *a" "dev_t dev" +.Ft void +.Fn archive_entry_set_rdevmajor "struct archive_entry *a" "dev_t major" +.Ft void +.Fn archive_entry_set_rdevminor "struct archive_entry *a" "dev_t minor" +.Sh DESCRIPTION +.Ss Copying to and from Vt struct stat +The function +.Fn archive_entry_stat +converts the various fields stored in the archive entry to the format +used by +.Xr stat 2 . +The return value remains valid until either +.Fn archive_entry_clear +or +.Fn archive_entry_free +is called. +It is not affected by calls to the set accessor functions. +It currently sets the following values in +.Vt struct stat : +.Vt st_atime , +.Vt st_ctime , +.Vt st_dev , +.Vt st_gid , +.Vt st_ino , +.Vt st_mode , +.Vt st_mtime , +.Vt st_nlink , +.Vt st_rdev , +.Vt st_size , +.Vt st_uid . +In addition, +.Vt st_birthtime +and high-precision information for time-related fields +will be included on platforms that support it. +.Pp +The function +.Fn archive_entry_copy_stat +copies fields from the platform's +.Vt struct stat . +Fields not provided by +.Vt struct stat +are unchanged. +.Ss General accessor functions +The functions +.Fn archive_entry_filetype +and +.Fn archive_entry_set_filetype +get respectively set the filetype. +The file type is one of the following constants: +.Bl -tag -width "AE_IFSOCK" -compact -offset indent +.It AE_IFREG +Regular file +.It AE_IFLNK +Symbolic link +.It AE_IFSOCK +Socket +.It AE_IFCHR +Character device +.It AE_IFBLK +Block device +.It AE_IFDIR +Directory +.It AE_IFIFO +Named pipe (fifo) +.El +Not all file types are supported by all platforms. +The constants used by +.Xr stat 2 +may have different numeric values from the +corresponding constants above. +.Pp +The functions +.Fn archive_entry_mode +and +.Fn archive_entry_set_mode +get/set a combination of file type and permissions and provide the +equivalent of +.Va st_mode . +Use of +.Fn archive_entry_filetype +and +.Fn archive_entry_perm +for getting and +.Fn archive_entry_set_filetype +and +.Fn archive_entry_set_perm +for setting is recommended. +.Pp +The function +.Fn archive_entry_size +returns the file size, if it has been set, and 0 otherwise. +.Fn archive_entry_size +can be used to query that status. +.Fn archive_entry_set_size +and +.Fn archive_entry_unset_size +set and unset the size, respectively. +.Pp +The number of references (hardlinks) can be obtained by calling +.Fn archive_entry_nlinks +and set with +.Fn archive_entry_set_nlinks . +.Ss Identifying unique files +The functions +.Fn archive_entry_dev +and +.Fn archive_entry_ino64 +are used by +.Xr archive_entry_linkify 3 +to find hardlinks. +The pair of device and inode is supposed to identify hardlinked files. +.Pp +The device major and minor number can be obtained independently using +.Fn archive_entry_devmajor +and +.Fn archive_entry_devminor . +The device can be set either via +.Fn archive_entry_set_dev +or by the combination of major and minor number using +.Fn archive_entry_set_devmajor +and +.Fn archive_entry_set_devminor . +.Pp +The inode number can be obtained using +.Fn archive_entry_ino . +This is a legacy interface that uses the platform +.Vt ino_t , +which may be very small. +To set the inode number, +.Fn archive_entry_set_ino64 +is the preferred interface. +.Ss Accessor functions for block and character devices +Block and character devices are characterised either using a device number +or a pair of major and minor number. +The combined device number can be obtained with +.Fn archive_device_rdev +and set with +.Fn archive_device_set_rdev . +The major and minor numbers are accessed by +.Fn archive_device_rdevmajor , +.Fn archive_device_rdevminor +.Fn archive_device_set_rdevmajor +and +.Fn archive_device_set_rdevminor . +.Pp +The process of splitting the combined device number into major and +minor number and the reverse process of combing them differs between +platforms. +Some archive formats use the combined form, while other formats use +the split form. +.Sh SEE ALSO +.Xr stat 2 , +.Xr archive_entry_acl 3 , +.Xr archive_entry_perms 3 , +.Xr archive_entry_time 3 , +.Xr libarchive 3 diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_entry_stat.c b/dependencies/libarchive-3.4.2/libarchive/archive_entry_stat.c new file mode 100644 index 0000000..71a407b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_entry_stat.c @@ -0,0 +1,118 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_entry_stat.c 201100 2009-12-28 03:05:31Z kientzle $"); + +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif + +#include "archive_entry.h" +#include "archive_entry_private.h" + +const struct stat * +archive_entry_stat(struct archive_entry *entry) +{ + struct stat *st; + if (entry->stat == NULL) { + entry->stat = calloc(1, sizeof(*st)); + if (entry->stat == NULL) + return (NULL); + entry->stat_valid = 0; + } + + /* + * If none of the underlying fields have been changed, we + * don't need to regenerate. In theory, we could use a bitmap + * here to flag only those items that have changed, but the + * extra complexity probably isn't worth it. It will be very + * rare for anyone to change just one field then request a new + * stat structure. + */ + if (entry->stat_valid) + return (entry->stat); + + st = entry->stat; + /* + * Use the public interfaces to extract items, so that + * the appropriate conversions get invoked. + */ + st->st_atime = archive_entry_atime(entry); +#if HAVE_STRUCT_STAT_ST_BIRTHTIME + st->st_birthtime = archive_entry_birthtime(entry); +#endif + st->st_ctime = archive_entry_ctime(entry); + st->st_mtime = archive_entry_mtime(entry); + st->st_dev = archive_entry_dev(entry); + st->st_gid = (gid_t)archive_entry_gid(entry); + st->st_uid = (uid_t)archive_entry_uid(entry); + st->st_ino = (ino_t)archive_entry_ino64(entry); + st->st_nlink = archive_entry_nlink(entry); + st->st_rdev = archive_entry_rdev(entry); + st->st_size = (off_t)archive_entry_size(entry); + st->st_mode = archive_entry_mode(entry); + + /* + * On systems that support high-res timestamps, copy that + * information into struct stat. + */ +#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC + st->st_atimespec.tv_nsec = archive_entry_atime_nsec(entry); + st->st_ctimespec.tv_nsec = archive_entry_ctime_nsec(entry); + st->st_mtimespec.tv_nsec = archive_entry_mtime_nsec(entry); +#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC + st->st_atim.tv_nsec = archive_entry_atime_nsec(entry); + st->st_ctim.tv_nsec = archive_entry_ctime_nsec(entry); + st->st_mtim.tv_nsec = archive_entry_mtime_nsec(entry); +#elif HAVE_STRUCT_STAT_ST_MTIME_N + st->st_atime_n = archive_entry_atime_nsec(entry); + st->st_ctime_n = archive_entry_ctime_nsec(entry); + st->st_mtime_n = archive_entry_mtime_nsec(entry); +#elif HAVE_STRUCT_STAT_ST_UMTIME + st->st_uatime = archive_entry_atime_nsec(entry) / 1000; + st->st_uctime = archive_entry_ctime_nsec(entry) / 1000; + st->st_umtime = archive_entry_mtime_nsec(entry) / 1000; +#elif HAVE_STRUCT_STAT_ST_MTIME_USEC + st->st_atime_usec = archive_entry_atime_nsec(entry) / 1000; + st->st_ctime_usec = archive_entry_ctime_nsec(entry) / 1000; + st->st_mtime_usec = archive_entry_mtime_nsec(entry) / 1000; +#endif +#if HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC + st->st_birthtimespec.tv_nsec = archive_entry_birthtime_nsec(entry); +#endif + + /* + * TODO: On Linux, store 32 or 64 here depending on whether + * the cached stat structure is a stat32 or a stat64. This + * will allow us to support both variants interchangeably. + */ + entry->stat_valid = 1; + + return (st); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_entry_strmode.c b/dependencies/libarchive-3.4.2/libarchive/archive_entry_strmode.c new file mode 100644 index 0000000..af2517a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_entry_strmode.c @@ -0,0 +1,87 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: src/lib/libarchive/archive_entry_strmode.c,v 1.4 2008/06/15 05:14:01 kientzle Exp $"); + +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive_entry.h" +#include "archive_entry_private.h" + +const char * +archive_entry_strmode(struct archive_entry *entry) +{ + static const mode_t permbits[] = + { 0400, 0200, 0100, 0040, 0020, 0010, 0004, 0002, 0001 }; + char *bp = entry->strmode; + mode_t mode; + int i; + + /* Fill in a default string, then selectively override. */ + strcpy(bp, "?rwxrwxrwx "); + + mode = archive_entry_mode(entry); + switch (archive_entry_filetype(entry)) { + case AE_IFREG: bp[0] = '-'; break; + case AE_IFBLK: bp[0] = 'b'; break; + case AE_IFCHR: bp[0] = 'c'; break; + case AE_IFDIR: bp[0] = 'd'; break; + case AE_IFLNK: bp[0] = 'l'; break; + case AE_IFSOCK: bp[0] = 's'; break; + case AE_IFIFO: bp[0] = 'p'; break; + default: + if (archive_entry_hardlink(entry) != NULL) { + bp[0] = 'h'; + break; + } + } + + for (i = 0; i < 9; i++) + if (!(mode & permbits[i])) + bp[i+1] = '-'; + + if (mode & S_ISUID) { + if (mode & 0100) bp[3] = 's'; + else bp[3] = 'S'; + } + if (mode & S_ISGID) { + if (mode & 0010) bp[6] = 's'; + else bp[6] = 'S'; + } + if (mode & S_ISVTX) { + if (mode & 0001) bp[9] = 't'; + else bp[9] = 'T'; + } + if (archive_entry_acl_types(entry) != 0) + bp[10] = '+'; + + return (bp); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_entry_time.3 b/dependencies/libarchive-3.4.2/libarchive/archive_entry_time.3 new file mode 100644 index 0000000..d0563ea --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_entry_time.3 @@ -0,0 +1,129 @@ +.\" Copyright (c) 2003-2007 Tim Kientzle +.\" Copyright (c) 2010 Joerg Sonnenberger +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 2, 2012 +.Dt ARCHIVE_ENTRY_TIME 3 +.Os +.Sh NAME +.Nm archive_entry_atime , +.Nm archive_entry_atime_nsec , +.Nm archive_entry_atime_is_set , +.Nm archive_entry_set_atime , +.Nm archive_entry_unset_atime , +.Nm archive_entry_birthtime , +.Nm archive_entry_birthtime_nsec , +.Nm archive_entry_birthtime_is_set , +.Nm archive_entry_set_birthtime , +.Nm archive_entry_unset_birthtime , +.Nm archive_entry_ctime , +.Nm archive_entry_ctime_nsec , +.Nm archive_entry_ctime_is_set , +.Nm archive_entry_set_ctime , +.Nm archive_entry_unset_ctime , +.Nm archive_entry_mtime , +.Nm archive_entry_mtime_nsec , +.Nm archive_entry_mtime_is_set , +.Nm archive_entry_set_mtime , +.Nm archive_entry_unset_mtime +.Nd functions for manipulating times in archive entry descriptions +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive_entry.h +.Ft time_t +.Fn archive_entry_atime "struct archive_entry *a" +.Ft long +.Fn archive_entry_atime_nsec "struct archive_entry *a" +.Ft int +.Fn archive_entry_atime_is_set "struct archive_entry *a" +.Ft void +.Fn archive_entry_set_atime "struct archive_entry *a" "time_t sec" "long nanosec" +.Ft void +.Fn archive_entry_unset_atime "struct archive_entry *a" +.Ft time_t +.Fn archive_entry_birthtime "struct archive_entry *a" +.Ft long +.Fn archive_entry_birthtime_nsec "struct archive_entry *a" +.Ft int +.Fn archive_entry_birthtime_is_set "struct archive_entry *a" +.Ft void +.Fn archive_entry_set_birthtime "struct archive_entry *a" "time_t sec" "long nanosec" +.Ft void +.Fn archive_entry_unset_birthtime "struct archive_entry *a" +.Ft time_t +.Fn archive_entry_ctime "struct archive_entry *a" +.Ft long +.Fn archive_entry_ctime_nsec "struct archive_entry *a" +.Ft int +.Fn archive_entry_ctime_is_set "struct archive_entry *a" +.Ft void +.Fn archive_entry_set_ctime "struct archive_entry *a" "time_t sec" "long nanosec" +.Ft void +.Fn archive_entry_unset_ctime "struct archive_entry *a" +.Ft time_t +.Fn archive_entry_mtime "struct archive_entry *a" +.Ft long +.Fn archive_entry_mtime_nsec "struct archive_entry *a" +.Ft int +.Fn archive_entry_mtime_is_set "struct archive_entry *a" +.Ft void +.Fn archive_entry_set_mtime "struct archive_entry *a" "time_t sec" "long nanosec" +.Ft void +.Fn archive_entry_unset_mtime "struct archive_entry *a" +.Sh DESCRIPTION +These functions create and manipulate the time fields in an +.Vt archive_entry . +Supported time fields are atime (access time), birthtime (creation time), +ctime (last time an inode property was changed) and mtime (modification time). +.Pp +.Xr libarchive 3 +provides a high-resolution interface. +The timestamps are truncated automatically depending on the archive format +(for archiving) or the filesystem capabilities (for restoring). +.Pp +All timestamp fields are optional. +The +.Fn XXX_unset +functions can be used to mark the corresponding field as missing. +The current state can be queried using +.Fn XXX_is_set . +Unset time fields have a second and nanosecond field of 0. +.Sh SEE ALSO +.Xr archive_entry 3 , +.Xr libarchive 3 +.Sh HISTORY +The +.Nm libarchive +library first appeared in +.Fx 5.3 . +.Sh AUTHORS +.An -nosplit +The +.Nm libarchive +library was written by +.An Tim Kientzle Aq kientzle@acm.org . +.\" .Sh BUGS diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_entry_xattr.c b/dependencies/libarchive-3.4.2/libarchive/archive_entry_xattr.c new file mode 100644 index 0000000..5fe726b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_entry_xattr.c @@ -0,0 +1,156 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_entry_xattr.c 201096 2009-12-28 02:41:27Z kientzle $"); + +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_LINUX_FS_H +#include /* for Linux file flags */ +#endif +/* + * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h. + * As the include guards don't agree, the order of include is important. + */ +#ifdef HAVE_LINUX_EXT2_FS_H +#include /* for Linux file flags */ +#endif +#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__) +#include /* for Linux file flags */ +#endif +#include +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_WCHAR_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_entry_private.h" + +/* + * extended attribute handling + */ + +void +archive_entry_xattr_clear(struct archive_entry *entry) +{ + struct ae_xattr *xp; + + while (entry->xattr_head != NULL) { + xp = entry->xattr_head->next; + free(entry->xattr_head->name); + free(entry->xattr_head->value); + free(entry->xattr_head); + entry->xattr_head = xp; + } + + entry->xattr_head = NULL; +} + +void +archive_entry_xattr_add_entry(struct archive_entry *entry, + const char *name, const void *value, size_t size) +{ + struct ae_xattr *xp; + + if ((xp = (struct ae_xattr *)malloc(sizeof(struct ae_xattr))) == NULL) + __archive_errx(1, "Out of memory"); + + if ((xp->name = strdup(name)) == NULL) + __archive_errx(1, "Out of memory"); + + if ((xp->value = malloc(size)) != NULL) { + memcpy(xp->value, value, size); + xp->size = size; + } else + xp->size = 0; + + xp->next = entry->xattr_head; + entry->xattr_head = xp; +} + + +/* + * returns number of the extended attribute entries + */ +int +archive_entry_xattr_count(struct archive_entry *entry) +{ + struct ae_xattr *xp; + int count = 0; + + for (xp = entry->xattr_head; xp != NULL; xp = xp->next) + count++; + + return count; +} + +int +archive_entry_xattr_reset(struct archive_entry * entry) +{ + entry->xattr_p = entry->xattr_head; + + return archive_entry_xattr_count(entry); +} + +int +archive_entry_xattr_next(struct archive_entry * entry, + const char **name, const void **value, size_t *size) +{ + if (entry->xattr_p) { + *name = entry->xattr_p->name; + *value = entry->xattr_p->value; + *size = entry->xattr_p->size; + + entry->xattr_p = entry->xattr_p->next; + + return (ARCHIVE_OK); + } else { + *name = NULL; + *value = NULL; + *size = (size_t)0; + return (ARCHIVE_WARN); + } +} + +/* + * end of xattr handling + */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_getdate.c b/dependencies/libarchive-3.4.2/libarchive/archive_getdate.c new file mode 100644 index 0000000..3ec5bba --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_getdate.c @@ -0,0 +1,1165 @@ +/* + * This code is in the public domain and has no copyright. + * + * This is a plain C recursive-descent translation of an old + * public-domain YACC grammar that has been used for parsing dates in + * very many open-source projects. + * + * Since the original authors were generous enough to donate their + * work to the public domain, I feel compelled to match their + * generosity. + * + * Tim Kientzle, February 2009. + */ + +/* + * Header comment from original getdate.y: + */ + +/* +** Originally written by Steven M. Bellovin while +** at the University of North Carolina at Chapel Hill. Later tweaked by +** a couple of people on Usenet. Completely overhauled by Rich $alz +** and Jim Berets in August, 1990; +** +** This grammar has 10 shift/reduce conflicts. +** +** This code is in the public domain and has no copyright. +*/ + +#include "archive_platform.h" +#ifdef __FreeBSD__ +#include +__FBSDID("$FreeBSD$"); +#endif + +#include +#include +#include +#include +#include + +#define __LIBARCHIVE_BUILD 1 +#include "archive_getdate.h" + +/* Basic time units. */ +#define EPOCH 1970 +#define MINUTE (60L) +#define HOUR (60L * MINUTE) +#define DAY (24L * HOUR) + +/* Daylight-savings mode: on, off, or not yet known. */ +enum DSTMODE { DSTon, DSToff, DSTmaybe }; +/* Meridian: am or pm. */ +enum { tAM, tPM }; +/* Token types returned by nexttoken() */ +enum { tAGO = 260, tDAY, tDAYZONE, tAMPM, tMONTH, tMONTH_UNIT, tSEC_UNIT, + tUNUMBER, tZONE, tDST }; +struct token { int token; time_t value; }; + +/* + * Parser state. + */ +struct gdstate { + struct token *tokenp; /* Pointer to next token. */ + /* HaveXxxx counts how many of this kind of phrase we've seen; + * it's a fatal error to have more than one time, zone, day, + * or date phrase. */ + int HaveYear; + int HaveMonth; + int HaveDay; + int HaveWeekDay; /* Day of week */ + int HaveTime; /* Hour/minute/second */ + int HaveZone; /* timezone and/or DST info */ + int HaveRel; /* time offset; we can have more than one */ + /* Absolute time values. */ + time_t Timezone; /* Seconds offset from GMT */ + time_t Day; + time_t Hour; + time_t Minutes; + time_t Month; + time_t Seconds; + time_t Year; + /* DST selection */ + enum DSTMODE DSTmode; + /* Day of week accounting, e.g., "3rd Tuesday" */ + time_t DayOrdinal; /* "3" in "3rd Tuesday" */ + time_t DayNumber; /* "Tuesday" in "3rd Tuesday" */ + /* Relative time values: hour/day/week offsets are measured in + * seconds, month/year are counted in months. */ + time_t RelMonth; + time_t RelSeconds; +}; + +/* + * A series of functions that recognize certain common time phrases. + * Each function returns 1 if it managed to make sense of some of the + * tokens, zero otherwise. + */ + +/* + * hour:minute or hour:minute:second with optional AM, PM, or numeric + * timezone offset + */ +static int +timephrase(struct gdstate *gds) +{ + if (gds->tokenp[0].token == tUNUMBER + && gds->tokenp[1].token == ':' + && gds->tokenp[2].token == tUNUMBER + && gds->tokenp[3].token == ':' + && gds->tokenp[4].token == tUNUMBER) { + /* "12:14:18" or "22:08:07" */ + ++gds->HaveTime; + gds->Hour = gds->tokenp[0].value; + gds->Minutes = gds->tokenp[2].value; + gds->Seconds = gds->tokenp[4].value; + gds->tokenp += 5; + } + else if (gds->tokenp[0].token == tUNUMBER + && gds->tokenp[1].token == ':' + && gds->tokenp[2].token == tUNUMBER) { + /* "12:14" or "22:08" */ + ++gds->HaveTime; + gds->Hour = gds->tokenp[0].value; + gds->Minutes = gds->tokenp[2].value; + gds->Seconds = 0; + gds->tokenp += 3; + } + else if (gds->tokenp[0].token == tUNUMBER + && gds->tokenp[1].token == tAMPM) { + /* "7" is a time if it's followed by "am" or "pm" */ + ++gds->HaveTime; + gds->Hour = gds->tokenp[0].value; + gds->Minutes = gds->Seconds = 0; + /* We'll handle the AM/PM below. */ + gds->tokenp += 1; + } else { + /* We can't handle this. */ + return 0; + } + + if (gds->tokenp[0].token == tAMPM) { + /* "7:12pm", "12:20:13am" */ + if (gds->Hour == 12) + gds->Hour = 0; + if (gds->tokenp[0].value == tPM) + gds->Hour += 12; + gds->tokenp += 1; + } + if (gds->tokenp[0].token == '+' + && gds->tokenp[1].token == tUNUMBER) { + /* "7:14+0700" */ + gds->HaveZone++; + gds->DSTmode = DSToff; + gds->Timezone = - ((gds->tokenp[1].value / 100) * HOUR + + (gds->tokenp[1].value % 100) * MINUTE); + gds->tokenp += 2; + } + if (gds->tokenp[0].token == '-' + && gds->tokenp[1].token == tUNUMBER) { + /* "19:14:12-0530" */ + gds->HaveZone++; + gds->DSTmode = DSToff; + gds->Timezone = + ((gds->tokenp[1].value / 100) * HOUR + + (gds->tokenp[1].value % 100) * MINUTE); + gds->tokenp += 2; + } + return 1; +} + +/* + * Timezone name, possibly including DST. + */ +static int +zonephrase(struct gdstate *gds) +{ + if (gds->tokenp[0].token == tZONE + && gds->tokenp[1].token == tDST) { + gds->HaveZone++; + gds->Timezone = gds->tokenp[0].value; + gds->DSTmode = DSTon; + gds->tokenp += 1; + return 1; + } + + if (gds->tokenp[0].token == tZONE) { + gds->HaveZone++; + gds->Timezone = gds->tokenp[0].value; + gds->DSTmode = DSToff; + gds->tokenp += 1; + return 1; + } + + if (gds->tokenp[0].token == tDAYZONE) { + gds->HaveZone++; + gds->Timezone = gds->tokenp[0].value; + gds->DSTmode = DSTon; + gds->tokenp += 1; + return 1; + } + return 0; +} + +/* + * Year/month/day in various combinations. + */ +static int +datephrase(struct gdstate *gds) +{ + if (gds->tokenp[0].token == tUNUMBER + && gds->tokenp[1].token == '/' + && gds->tokenp[2].token == tUNUMBER + && gds->tokenp[3].token == '/' + && gds->tokenp[4].token == tUNUMBER) { + gds->HaveYear++; + gds->HaveMonth++; + gds->HaveDay++; + if (gds->tokenp[0].value >= 13) { + /* First number is big: 2004/01/29, 99/02/17 */ + gds->Year = gds->tokenp[0].value; + gds->Month = gds->tokenp[2].value; + gds->Day = gds->tokenp[4].value; + } else if ((gds->tokenp[4].value >= 13) + || (gds->tokenp[2].value >= 13)) { + /* Last number is big: 01/07/98 */ + /* Middle number is big: 01/29/04 */ + gds->Month = gds->tokenp[0].value; + gds->Day = gds->tokenp[2].value; + gds->Year = gds->tokenp[4].value; + } else { + /* No significant clues: 02/03/04 */ + gds->Month = gds->tokenp[0].value; + gds->Day = gds->tokenp[2].value; + gds->Year = gds->tokenp[4].value; + } + gds->tokenp += 5; + return 1; + } + + if (gds->tokenp[0].token == tUNUMBER + && gds->tokenp[1].token == '/' + && gds->tokenp[2].token == tUNUMBER) { + /* "1/15" */ + gds->HaveMonth++; + gds->HaveDay++; + gds->Month = gds->tokenp[0].value; + gds->Day = gds->tokenp[2].value; + gds->tokenp += 3; + return 1; + } + + if (gds->tokenp[0].token == tUNUMBER + && gds->tokenp[1].token == '-' + && gds->tokenp[2].token == tUNUMBER + && gds->tokenp[3].token == '-' + && gds->tokenp[4].token == tUNUMBER) { + /* ISO 8601 format. yyyy-mm-dd. */ + gds->HaveYear++; + gds->HaveMonth++; + gds->HaveDay++; + gds->Year = gds->tokenp[0].value; + gds->Month = gds->tokenp[2].value; + gds->Day = gds->tokenp[4].value; + gds->tokenp += 5; + return 1; + } + + if (gds->tokenp[0].token == tUNUMBER + && gds->tokenp[1].token == '-' + && gds->tokenp[2].token == tMONTH + && gds->tokenp[3].token == '-' + && gds->tokenp[4].token == tUNUMBER) { + gds->HaveYear++; + gds->HaveMonth++; + gds->HaveDay++; + if (gds->tokenp[0].value > 31) { + /* e.g. 1992-Jun-17 */ + gds->Year = gds->tokenp[0].value; + gds->Month = gds->tokenp[2].value; + gds->Day = gds->tokenp[4].value; + } else { + /* e.g. 17-JUN-1992. */ + gds->Day = gds->tokenp[0].value; + gds->Month = gds->tokenp[2].value; + gds->Year = gds->tokenp[4].value; + } + gds->tokenp += 5; + return 1; + } + + if (gds->tokenp[0].token == tMONTH + && gds->tokenp[1].token == tUNUMBER + && gds->tokenp[2].token == ',' + && gds->tokenp[3].token == tUNUMBER) { + /* "June 17, 2001" */ + gds->HaveYear++; + gds->HaveMonth++; + gds->HaveDay++; + gds->Month = gds->tokenp[0].value; + gds->Day = gds->tokenp[1].value; + gds->Year = gds->tokenp[3].value; + gds->tokenp += 4; + return 1; + } + + if (gds->tokenp[0].token == tMONTH + && gds->tokenp[1].token == tUNUMBER) { + /* "May 3" */ + gds->HaveMonth++; + gds->HaveDay++; + gds->Month = gds->tokenp[0].value; + gds->Day = gds->tokenp[1].value; + gds->tokenp += 2; + return 1; + } + + if (gds->tokenp[0].token == tUNUMBER + && gds->tokenp[1].token == tMONTH + && gds->tokenp[2].token == tUNUMBER) { + /* "12 Sept 1997" */ + gds->HaveYear++; + gds->HaveMonth++; + gds->HaveDay++; + gds->Day = gds->tokenp[0].value; + gds->Month = gds->tokenp[1].value; + gds->Year = gds->tokenp[2].value; + gds->tokenp += 3; + return 1; + } + + if (gds->tokenp[0].token == tUNUMBER + && gds->tokenp[1].token == tMONTH) { + /* "12 Sept" */ + gds->HaveMonth++; + gds->HaveDay++; + gds->Day = gds->tokenp[0].value; + gds->Month = gds->tokenp[1].value; + gds->tokenp += 2; + return 1; + } + + return 0; +} + +/* + * Relative time phrase: "tomorrow", "yesterday", "+1 hour", etc. + */ +static int +relunitphrase(struct gdstate *gds) +{ + if (gds->tokenp[0].token == '-' + && gds->tokenp[1].token == tUNUMBER + && gds->tokenp[2].token == tSEC_UNIT) { + /* "-3 hours" */ + gds->HaveRel++; + gds->RelSeconds -= gds->tokenp[1].value * gds->tokenp[2].value; + gds->tokenp += 3; + return 1; + } + if (gds->tokenp[0].token == '+' + && gds->tokenp[1].token == tUNUMBER + && gds->tokenp[2].token == tSEC_UNIT) { + /* "+1 minute" */ + gds->HaveRel++; + gds->RelSeconds += gds->tokenp[1].value * gds->tokenp[2].value; + gds->tokenp += 3; + return 1; + } + if (gds->tokenp[0].token == tUNUMBER + && gds->tokenp[1].token == tSEC_UNIT) { + /* "1 day" */ + gds->HaveRel++; + gds->RelSeconds += gds->tokenp[0].value * gds->tokenp[1].value; + gds->tokenp += 2; + return 1; + } + if (gds->tokenp[0].token == '-' + && gds->tokenp[1].token == tUNUMBER + && gds->tokenp[2].token == tMONTH_UNIT) { + /* "-3 months" */ + gds->HaveRel++; + gds->RelMonth -= gds->tokenp[1].value * gds->tokenp[2].value; + gds->tokenp += 3; + return 1; + } + if (gds->tokenp[0].token == '+' + && gds->tokenp[1].token == tUNUMBER + && gds->tokenp[2].token == tMONTH_UNIT) { + /* "+5 years" */ + gds->HaveRel++; + gds->RelMonth += gds->tokenp[1].value * gds->tokenp[2].value; + gds->tokenp += 3; + return 1; + } + if (gds->tokenp[0].token == tUNUMBER + && gds->tokenp[1].token == tMONTH_UNIT) { + /* "2 years" */ + gds->HaveRel++; + gds->RelMonth += gds->tokenp[0].value * gds->tokenp[1].value; + gds->tokenp += 2; + return 1; + } + if (gds->tokenp[0].token == tSEC_UNIT) { + /* "now", "tomorrow" */ + gds->HaveRel++; + gds->RelSeconds += gds->tokenp[0].value; + gds->tokenp += 1; + return 1; + } + if (gds->tokenp[0].token == tMONTH_UNIT) { + /* "month" */ + gds->HaveRel++; + gds->RelMonth += gds->tokenp[0].value; + gds->tokenp += 1; + return 1; + } + return 0; +} + +/* + * Day of the week specification. + */ +static int +dayphrase(struct gdstate *gds) +{ + if (gds->tokenp[0].token == tDAY) { + /* "tues", "wednesday," */ + gds->HaveWeekDay++; + gds->DayOrdinal = 1; + gds->DayNumber = gds->tokenp[0].value; + gds->tokenp += 1; + if (gds->tokenp[0].token == ',') + gds->tokenp += 1; + return 1; + } + if (gds->tokenp[0].token == tUNUMBER + && gds->tokenp[1].token == tDAY) { + /* "second tues" "3 wed" */ + gds->HaveWeekDay++; + gds->DayOrdinal = gds->tokenp[0].value; + gds->DayNumber = gds->tokenp[1].value; + gds->tokenp += 2; + return 1; + } + return 0; +} + +/* + * Try to match a phrase using one of the above functions. + * This layer also deals with a couple of generic issues. + */ +static int +phrase(struct gdstate *gds) +{ + if (timephrase(gds)) + return 1; + if (zonephrase(gds)) + return 1; + if (datephrase(gds)) + return 1; + if (dayphrase(gds)) + return 1; + if (relunitphrase(gds)) { + if (gds->tokenp[0].token == tAGO) { + gds->RelSeconds = -gds->RelSeconds; + gds->RelMonth = -gds->RelMonth; + gds->tokenp += 1; + } + return 1; + } + + /* Bare numbers sometimes have meaning. */ + if (gds->tokenp[0].token == tUNUMBER) { + if (gds->HaveTime && !gds->HaveYear && !gds->HaveRel) { + gds->HaveYear++; + gds->Year = gds->tokenp[0].value; + gds->tokenp += 1; + return 1; + } + + if(gds->tokenp[0].value > 10000) { + /* "20040301" */ + gds->HaveYear++; + gds->HaveMonth++; + gds->HaveDay++; + gds->Day= (gds->tokenp[0].value)%100; + gds->Month= (gds->tokenp[0].value/100)%100; + gds->Year = gds->tokenp[0].value/10000; + gds->tokenp += 1; + return 1; + } + + if (gds->tokenp[0].value < 24) { + gds->HaveTime++; + gds->Hour = gds->tokenp[0].value; + gds->Minutes = 0; + gds->Seconds = 0; + gds->tokenp += 1; + return 1; + } + + if ((gds->tokenp[0].value / 100 < 24) + && (gds->tokenp[0].value % 100 < 60)) { + /* "513" is same as "5:13" */ + gds->Hour = gds->tokenp[0].value / 100; + gds->Minutes = gds->tokenp[0].value % 100; + gds->Seconds = 0; + gds->tokenp += 1; + return 1; + } + } + + return 0; +} + +/* + * A dictionary of time words. + */ +static struct LEXICON { + size_t abbrev; + const char *name; + int type; + time_t value; +} const TimeWords[] = { + /* am/pm */ + { 0, "am", tAMPM, tAM }, + { 0, "pm", tAMPM, tPM }, + + /* Month names. */ + { 3, "january", tMONTH, 1 }, + { 3, "february", tMONTH, 2 }, + { 3, "march", tMONTH, 3 }, + { 3, "april", tMONTH, 4 }, + { 3, "may", tMONTH, 5 }, + { 3, "june", tMONTH, 6 }, + { 3, "july", tMONTH, 7 }, + { 3, "august", tMONTH, 8 }, + { 3, "september", tMONTH, 9 }, + { 3, "october", tMONTH, 10 }, + { 3, "november", tMONTH, 11 }, + { 3, "december", tMONTH, 12 }, + + /* Days of the week. */ + { 2, "sunday", tDAY, 0 }, + { 3, "monday", tDAY, 1 }, + { 2, "tuesday", tDAY, 2 }, + { 3, "wednesday", tDAY, 3 }, + { 2, "thursday", tDAY, 4 }, + { 2, "friday", tDAY, 5 }, + { 2, "saturday", tDAY, 6 }, + + /* Timezones: Offsets are in seconds. */ + { 0, "gmt", tZONE, 0*HOUR }, /* Greenwich Mean */ + { 0, "ut", tZONE, 0*HOUR }, /* Universal (Coordinated) */ + { 0, "utc", tZONE, 0*HOUR }, + { 0, "wet", tZONE, 0*HOUR }, /* Western European */ + { 0, "bst", tDAYZONE, 0*HOUR }, /* British Summer */ + { 0, "wat", tZONE, 1*HOUR }, /* West Africa */ + { 0, "at", tZONE, 2*HOUR }, /* Azores */ + /* { 0, "bst", tZONE, 3*HOUR }, */ /* Brazil Standard: Conflict */ + /* { 0, "gst", tZONE, 3*HOUR }, */ /* Greenland Standard: Conflict*/ + { 0, "nft", tZONE, 3*HOUR+30*MINUTE }, /* Newfoundland */ + { 0, "nst", tZONE, 3*HOUR+30*MINUTE }, /* Newfoundland Standard */ + { 0, "ndt", tDAYZONE, 3*HOUR+30*MINUTE }, /* Newfoundland Daylight */ + { 0, "ast", tZONE, 4*HOUR }, /* Atlantic Standard */ + { 0, "adt", tDAYZONE, 4*HOUR }, /* Atlantic Daylight */ + { 0, "est", tZONE, 5*HOUR }, /* Eastern Standard */ + { 0, "edt", tDAYZONE, 5*HOUR }, /* Eastern Daylight */ + { 0, "cst", tZONE, 6*HOUR }, /* Central Standard */ + { 0, "cdt", tDAYZONE, 6*HOUR }, /* Central Daylight */ + { 0, "mst", tZONE, 7*HOUR }, /* Mountain Standard */ + { 0, "mdt", tDAYZONE, 7*HOUR }, /* Mountain Daylight */ + { 0, "pst", tZONE, 8*HOUR }, /* Pacific Standard */ + { 0, "pdt", tDAYZONE, 8*HOUR }, /* Pacific Daylight */ + { 0, "yst", tZONE, 9*HOUR }, /* Yukon Standard */ + { 0, "ydt", tDAYZONE, 9*HOUR }, /* Yukon Daylight */ + { 0, "hst", tZONE, 10*HOUR }, /* Hawaii Standard */ + { 0, "hdt", tDAYZONE, 10*HOUR }, /* Hawaii Daylight */ + { 0, "cat", tZONE, 10*HOUR }, /* Central Alaska */ + { 0, "ahst", tZONE, 10*HOUR }, /* Alaska-Hawaii Standard */ + { 0, "nt", tZONE, 11*HOUR }, /* Nome */ + { 0, "idlw", tZONE, 12*HOUR }, /* Intl Date Line West */ + { 0, "cet", tZONE, -1*HOUR }, /* Central European */ + { 0, "met", tZONE, -1*HOUR }, /* Middle European */ + { 0, "mewt", tZONE, -1*HOUR }, /* Middle European Winter */ + { 0, "mest", tDAYZONE, -1*HOUR }, /* Middle European Summer */ + { 0, "swt", tZONE, -1*HOUR }, /* Swedish Winter */ + { 0, "sst", tDAYZONE, -1*HOUR }, /* Swedish Summer */ + { 0, "fwt", tZONE, -1*HOUR }, /* French Winter */ + { 0, "fst", tDAYZONE, -1*HOUR }, /* French Summer */ + { 0, "eet", tZONE, -2*HOUR }, /* Eastern Eur, USSR Zone 1 */ + { 0, "bt", tZONE, -3*HOUR }, /* Baghdad, USSR Zone 2 */ + { 0, "it", tZONE, -3*HOUR-30*MINUTE },/* Iran */ + { 0, "zp4", tZONE, -4*HOUR }, /* USSR Zone 3 */ + { 0, "zp5", tZONE, -5*HOUR }, /* USSR Zone 4 */ + { 0, "ist", tZONE, -5*HOUR-30*MINUTE },/* Indian Standard */ + { 0, "zp6", tZONE, -6*HOUR }, /* USSR Zone 5 */ + /* { 0, "nst", tZONE, -6.5*HOUR }, */ /* North Sumatra: Conflict */ + /* { 0, "sst", tZONE, -7*HOUR }, */ /* So Sumatra, USSR 6: Conflict */ + { 0, "wast", tZONE, -7*HOUR }, /* West Australian Standard */ + { 0, "wadt", tDAYZONE, -7*HOUR }, /* West Australian Daylight */ + { 0, "jt", tZONE, -7*HOUR-30*MINUTE },/* Java (3pm in Cronusland!)*/ + { 0, "cct", tZONE, -8*HOUR }, /* China Coast, USSR Zone 7 */ + { 0, "jst", tZONE, -9*HOUR }, /* Japan Std, USSR Zone 8 */ + { 0, "cast", tZONE, -9*HOUR-30*MINUTE },/* Ctrl Australian Std */ + { 0, "cadt", tDAYZONE, -9*HOUR-30*MINUTE },/* Ctrl Australian Daylt */ + { 0, "east", tZONE, -10*HOUR }, /* Eastern Australian Std */ + { 0, "eadt", tDAYZONE, -10*HOUR }, /* Eastern Australian Daylt */ + { 0, "gst", tZONE, -10*HOUR }, /* Guam Std, USSR Zone 9 */ + { 0, "nzt", tZONE, -12*HOUR }, /* New Zealand */ + { 0, "nzst", tZONE, -12*HOUR }, /* New Zealand Standard */ + { 0, "nzdt", tDAYZONE, -12*HOUR }, /* New Zealand Daylight */ + { 0, "idle", tZONE, -12*HOUR }, /* Intl Date Line East */ + + { 0, "dst", tDST, 0 }, + + /* Time units. */ + { 4, "years", tMONTH_UNIT, 12 }, + { 5, "months", tMONTH_UNIT, 1 }, + { 9, "fortnights", tSEC_UNIT, 14 * DAY }, + { 4, "weeks", tSEC_UNIT, 7 * DAY }, + { 3, "days", tSEC_UNIT, DAY }, + { 4, "hours", tSEC_UNIT, HOUR }, + { 3, "minutes", tSEC_UNIT, MINUTE }, + { 3, "seconds", tSEC_UNIT, 1 }, + + /* Relative-time words. */ + { 0, "tomorrow", tSEC_UNIT, DAY }, + { 0, "yesterday", tSEC_UNIT, -DAY }, + { 0, "today", tSEC_UNIT, 0 }, + { 0, "now", tSEC_UNIT, 0 }, + { 0, "last", tUNUMBER, -1 }, + { 0, "this", tSEC_UNIT, 0 }, + { 0, "next", tUNUMBER, 2 }, + { 0, "first", tUNUMBER, 1 }, + { 0, "1st", tUNUMBER, 1 }, +/* { 0, "second", tUNUMBER, 2 }, */ + { 0, "2nd", tUNUMBER, 2 }, + { 0, "third", tUNUMBER, 3 }, + { 0, "3rd", tUNUMBER, 3 }, + { 0, "fourth", tUNUMBER, 4 }, + { 0, "4th", tUNUMBER, 4 }, + { 0, "fifth", tUNUMBER, 5 }, + { 0, "5th", tUNUMBER, 5 }, + { 0, "sixth", tUNUMBER, 6 }, + { 0, "seventh", tUNUMBER, 7 }, + { 0, "eighth", tUNUMBER, 8 }, + { 0, "ninth", tUNUMBER, 9 }, + { 0, "tenth", tUNUMBER, 10 }, + { 0, "eleventh", tUNUMBER, 11 }, + { 0, "twelfth", tUNUMBER, 12 }, + { 0, "ago", tAGO, 1 }, + + /* Military timezones. */ + { 0, "a", tZONE, 1*HOUR }, + { 0, "b", tZONE, 2*HOUR }, + { 0, "c", tZONE, 3*HOUR }, + { 0, "d", tZONE, 4*HOUR }, + { 0, "e", tZONE, 5*HOUR }, + { 0, "f", tZONE, 6*HOUR }, + { 0, "g", tZONE, 7*HOUR }, + { 0, "h", tZONE, 8*HOUR }, + { 0, "i", tZONE, 9*HOUR }, + { 0, "k", tZONE, 10*HOUR }, + { 0, "l", tZONE, 11*HOUR }, + { 0, "m", tZONE, 12*HOUR }, + { 0, "n", tZONE, -1*HOUR }, + { 0, "o", tZONE, -2*HOUR }, + { 0, "p", tZONE, -3*HOUR }, + { 0, "q", tZONE, -4*HOUR }, + { 0, "r", tZONE, -5*HOUR }, + { 0, "s", tZONE, -6*HOUR }, + { 0, "t", tZONE, -7*HOUR }, + { 0, "u", tZONE, -8*HOUR }, + { 0, "v", tZONE, -9*HOUR }, + { 0, "w", tZONE, -10*HOUR }, + { 0, "x", tZONE, -11*HOUR }, + { 0, "y", tZONE, -12*HOUR }, + { 0, "z", tZONE, 0*HOUR }, + + /* End of table. */ + { 0, NULL, 0, 0 } +}; + +/* + * Year is either: + * = A number from 0 to 99, which means a year from 1970 to 2069, or + * = The actual year (>=100). + */ +static time_t +Convert(time_t Month, time_t Day, time_t Year, + time_t Hours, time_t Minutes, time_t Seconds, + time_t Timezone, enum DSTMODE DSTmode) +{ + signed char DaysInMonth[12] = { + 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 + }; + time_t Julian; + int i; + struct tm *ltime; +#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S) + struct tm tmbuf; +#endif +#if defined(HAVE__LOCALTIME64_S) + errno_t terr; + __time64_t tmptime; +#endif + + if (Year < 69) + Year += 2000; + else if (Year < 100) + Year += 1900; + DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) + ? 29 : 28; + /* Checking for 2038 bogusly assumes that time_t is 32 bits. But + I'm too lazy to try to check for time_t overflow in another way. */ + if (Year < EPOCH || Year > 2038 + || Month < 1 || Month > 12 + /* Lint fluff: "conversion from long may lose accuracy" */ + || Day < 1 || Day > DaysInMonth[(int)--Month] + || Hours < 0 || Hours > 23 + || Minutes < 0 || Minutes > 59 + || Seconds < 0 || Seconds > 59) + return -1; + + Julian = Day - 1; + for (i = 0; i < Month; i++) + Julian += DaysInMonth[i]; + for (i = EPOCH; i < Year; i++) + Julian += 365 + (i % 4 == 0); + Julian *= DAY; + Julian += Timezone; + Julian += Hours * HOUR + Minutes * MINUTE + Seconds; +#if defined(HAVE_LOCALTIME_R) + ltime = localtime_r(&Julian, &tmbuf); +#elif defined(HAVE__LOCALTIME64_S) + tmptime = Julian; + terr = _localtime64_s(&tmbuf, &tmptime); + if (terr) + ltime = NULL; + else + ltime = &tmbuf; +#else + ltime = localtime(&Julian); +#endif + if (DSTmode == DSTon + || (DSTmode == DSTmaybe && ltime->tm_isdst)) + Julian -= HOUR; + return Julian; +} + +static time_t +DSTcorrect(time_t Start, time_t Future) +{ + time_t StartDay; + time_t FutureDay; + struct tm *ltime; +#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S) + struct tm tmbuf; +#endif +#if defined(HAVE__LOCALTIME64_S) + errno_t terr; + __time64_t tmptime; +#endif + +#if defined(HAVE_LOCALTIME_R) + ltime = localtime_r(&Start, &tmbuf); +#elif defined(HAVE__LOCALTIME64_S) + tmptime = Start; + terr = _localtime64_s(&tmbuf, &tmptime); + if (terr) + ltime = NULL; + else + ltime = &tmbuf; +#else + ltime = localtime(&Start); +#endif + StartDay = (ltime->tm_hour + 1) % 24; +#if defined(HAVE_LOCALTIME_R) + ltime = localtime_r(&Future, &tmbuf); +#elif defined(HAVE__LOCALTIME64_S) + tmptime = Future; + terr = _localtime64_s(&tmbuf, &tmptime); + if (terr) + ltime = NULL; + else + ltime = &tmbuf; +#else + ltime = localtime(&Future); +#endif + FutureDay = (ltime->tm_hour + 1) % 24; + return (Future - Start) + (StartDay - FutureDay) * HOUR; +} + + +static time_t +RelativeDate(time_t Start, time_t zone, int dstmode, + time_t DayOrdinal, time_t DayNumber) +{ + struct tm *tm; + time_t t, now; +#if defined(HAVE_GMTIME_R) || defined(HAVE__GMTIME64_S) + struct tm tmbuf; +#endif +#if defined(HAVE__GMTIME64_S) + errno_t terr; + __time64_t tmptime; +#endif + + t = Start - zone; +#if defined(HAVE_GMTIME_R) + tm = gmtime_r(&t, &tmbuf); +#elif defined(HAVE__GMTIME64_S) + tmptime = t; + terr = _gmtime64_s(&tmbuf, &tmptime); + if (terr) + tm = NULL; + else + tm = &tmbuf; +#else + tm = gmtime(&t); +#endif + now = Start; + now += DAY * ((DayNumber - tm->tm_wday + 7) % 7); + now += 7 * DAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1); + if (dstmode == DSTmaybe) + return DSTcorrect(Start, now); + return now - Start; +} + + +static time_t +RelativeMonth(time_t Start, time_t Timezone, time_t RelMonth) +{ + struct tm *tm; + time_t Month; + time_t Year; +#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S) + struct tm tmbuf; +#endif +#if defined(HAVE__LOCALTIME64_S) + errno_t terr; + __time64_t tmptime; +#endif + + if (RelMonth == 0) + return 0; +#if defined(HAVE_LOCALTIME_R) + tm = localtime_r(&Start, &tmbuf); +#elif defined(HAVE__LOCALTIME64_S) + tmptime = Start; + terr = _localtime64_s(&tmbuf, &tmptime); + if (terr) + tm = NULL; + else + tm = &tmbuf; +#else + tm = localtime(&Start); +#endif + Month = 12 * (tm->tm_year + 1900) + tm->tm_mon + RelMonth; + Year = Month / 12; + Month = Month % 12 + 1; + return DSTcorrect(Start, + Convert(Month, (time_t)tm->tm_mday, Year, + (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec, + Timezone, DSTmaybe)); +} + +/* + * Tokenizer. + */ +static int +nexttoken(const char **in, time_t *value) +{ + char c; + char buff[64]; + + for ( ; ; ) { + while (isspace((unsigned char)**in)) + ++*in; + + /* Skip parenthesized comments. */ + if (**in == '(') { + int Count = 0; + do { + c = *(*in)++; + if (c == '\0') + return c; + if (c == '(') + Count++; + else if (c == ')') + Count--; + } while (Count > 0); + continue; + } + + /* Try the next token in the word table first. */ + /* This allows us to match "2nd", for example. */ + { + const char *src = *in; + const struct LEXICON *tp; + unsigned i = 0; + + /* Force to lowercase and strip '.' characters. */ + while (*src != '\0' + && (isalnum((unsigned char)*src) || *src == '.') + && i < sizeof(buff)-1) { + if (*src != '.') { + if (isupper((unsigned char)*src)) + buff[i++] = tolower((unsigned char)*src); + else + buff[i++] = *src; + } + src++; + } + buff[i] = '\0'; + + /* + * Find the first match. If the word can be + * abbreviated, make sure we match at least + * the minimum abbreviation. + */ + for (tp = TimeWords; tp->name; tp++) { + size_t abbrev = tp->abbrev; + if (abbrev == 0) + abbrev = strlen(tp->name); + if (strlen(buff) >= abbrev + && strncmp(tp->name, buff, strlen(buff)) + == 0) { + /* Skip over token. */ + *in = src; + /* Return the match. */ + *value = tp->value; + return tp->type; + } + } + } + + /* + * Not in the word table, maybe it's a number. Note: + * Because '-' and '+' have other special meanings, I + * don't deal with signed numbers here. + */ + if (isdigit((unsigned char)(c = **in))) { + for (*value = 0; isdigit((unsigned char)(c = *(*in)++)); ) + *value = 10 * *value + c - '0'; + (*in)--; + return (tUNUMBER); + } + + return *(*in)++; + } +} + +#define TM_YEAR_ORIGIN 1900 + +/* Yield A - B, measured in seconds. */ +static long +difftm (struct tm *a, struct tm *b) +{ + int ay = a->tm_year + (TM_YEAR_ORIGIN - 1); + int by = b->tm_year + (TM_YEAR_ORIGIN - 1); + int days = ( + /* difference in day of year */ + a->tm_yday - b->tm_yday + /* + intervening leap days */ + + ((ay >> 2) - (by >> 2)) + - (ay/100 - by/100) + + ((ay/100 >> 2) - (by/100 >> 2)) + /* + difference in years * 365 */ + + (long)(ay-by) * 365 + ); + return (days * DAY + (a->tm_hour - b->tm_hour) * HOUR + + (a->tm_min - b->tm_min) * MINUTE + + (a->tm_sec - b->tm_sec)); +} + +/* + * + * The public function. + * + * TODO: tokens[] array should be dynamically sized. + */ +time_t +__archive_get_date(time_t now, const char *p) +{ + struct token tokens[256]; + struct gdstate _gds; + struct token *lasttoken; + struct gdstate *gds; + struct tm local, *tm; + struct tm gmt, *gmt_ptr; + time_t Start; + time_t tod; + long tzone; +#if defined(HAVE__LOCALTIME64_S) || defined(HAVE__GMTIME64_S) + errno_t terr; + __time64_t tmptime; +#endif + + /* Clear out the parsed token array. */ + memset(tokens, 0, sizeof(tokens)); + /* Initialize the parser state. */ + memset(&_gds, 0, sizeof(_gds)); + gds = &_gds; + + /* Look up the current time. */ +#if defined(HAVE_LOCALTIME_R) + tm = localtime_r(&now, &local); +#elif defined(HAVE__LOCALTIME64_S) + tmptime = now; + terr = _localtime64_s(&local, &tmptime); + if (terr) + tm = NULL; + else + tm = &local; +#else + memset(&local, 0, sizeof(local)); + tm = localtime(&now); +#endif + if (tm == NULL) + return -1; +#if !defined(HAVE_LOCALTIME_R) && !defined(HAVE__LOCALTIME64_S) + local = *tm; +#endif + + /* Look up UTC if we can and use that to determine the current + * timezone offset. */ +#if defined(HAVE_GMTIME_R) + gmt_ptr = gmtime_r(&now, &gmt); +#elif defined(HAVE__GMTIME64_S) + tmptime = now; + terr = _gmtime64_s(&gmt, &tmptime); + if (terr) + gmt_ptr = NULL; + else + gmt_ptr = &gmt; +#else + memset(&gmt, 0, sizeof(gmt)); + gmt_ptr = gmtime(&now); + if (gmt_ptr != NULL) { + /* Copy, in case localtime and gmtime use the same buffer. */ + gmt = *gmt_ptr; + } +#endif + if (gmt_ptr != NULL) + tzone = difftm (&gmt, &local); + else + /* This system doesn't understand timezones; fake it. */ + tzone = 0; + if(local.tm_isdst) + tzone += HOUR; + + /* Tokenize the input string. */ + lasttoken = tokens; + while ((lasttoken->token = nexttoken(&p, &lasttoken->value)) != 0) { + ++lasttoken; + if (lasttoken > tokens + 255) + return -1; + } + gds->tokenp = tokens; + + /* Match phrases until we run out of input tokens. */ + while (gds->tokenp < lasttoken) { + if (!phrase(gds)) + return -1; + } + + /* Use current local timezone if none was specified. */ + if (!gds->HaveZone) { + gds->Timezone = tzone; + gds->DSTmode = DSTmaybe; + } + + /* If a timezone was specified, use that for generating the default + * time components instead of the local timezone. */ + if (gds->HaveZone && gmt_ptr != NULL) { + now -= gds->Timezone; +#if defined(HAVE_GMTIME_R) + gmt_ptr = gmtime_r(&now, &gmt); +#elif defined(HAVE__GMTIME64_S) + tmptime = now; + terr = _gmtime64_s(&gmt, &tmptime); + if (terr) + gmt_ptr = NULL; + else + gmt_ptr = &gmt; +#else + gmt_ptr = gmtime(&now); +#endif + if (gmt_ptr != NULL) + local = *gmt_ptr; + now += gds->Timezone; + } + + if (!gds->HaveYear) + gds->Year = local.tm_year + 1900; + if (!gds->HaveMonth) + gds->Month = local.tm_mon + 1; + if (!gds->HaveDay) + gds->Day = local.tm_mday; + /* Note: No default for hour/min/sec; a specifier that just + * gives date always refers to 00:00 on that date. */ + + /* If we saw more than one time, timezone, weekday, year, month, + * or day, then give up. */ + if (gds->HaveTime > 1 || gds->HaveZone > 1 || gds->HaveWeekDay > 1 + || gds->HaveYear > 1 || gds->HaveMonth > 1 || gds->HaveDay > 1) + return -1; + + /* Compute an absolute time based on whatever absolute information + * we collected. */ + if (gds->HaveYear || gds->HaveMonth || gds->HaveDay + || gds->HaveTime || gds->HaveWeekDay) { + Start = Convert(gds->Month, gds->Day, gds->Year, + gds->Hour, gds->Minutes, gds->Seconds, + gds->Timezone, gds->DSTmode); + if (Start < 0) + return -1; + } else { + Start = now; + if (!gds->HaveRel) + Start -= local.tm_hour * HOUR + local.tm_min * MINUTE + + local.tm_sec; + } + + /* Add the relative offset. */ + Start += gds->RelSeconds; + Start += RelativeMonth(Start, gds->Timezone, gds->RelMonth); + + /* Adjust for day-of-week offsets. */ + if (gds->HaveWeekDay + && !(gds->HaveYear || gds->HaveMonth || gds->HaveDay)) { + tod = RelativeDate(Start, gds->Timezone, + gds->DSTmode, gds->DayOrdinal, gds->DayNumber); + Start += tod; + } + + /* -1 is an error indicator, so return 0 instead of -1 if + * that's the actual time. */ + return Start == -1 ? 0 : Start; +} + + +#if defined(TEST) + +/* ARGSUSED */ +int +main(int argc, char **argv) +{ + time_t d; + time_t now = time(NULL); + + while (*++argv != NULL) { + (void)printf("Input: %s\n", *argv); + d = get_date(now, *argv); + if (d == -1) + (void)printf("Bad format - couldn't convert.\n"); + else + (void)printf("Output: %s\n", ctime(&d)); + } + exit(0); + /* NOTREACHED */ +} +#endif /* defined(TEST) */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_getdate.h b/dependencies/libarchive-3.4.2/libarchive/archive_getdate.h new file mode 100644 index 0000000..900a8f6 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_getdate.h @@ -0,0 +1,39 @@ +/*- + * Copyright (c) 2003-2015 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef ARCHIVE_GETDATE_H_INCLUDED +#define ARCHIVE_GETDATE_H_INCLUDED + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif + +#include + +time_t __archive_get_date(time_t now, const char *); + +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_hmac.c b/dependencies/libarchive-3.4.2/libarchive/archive_hmac.c new file mode 100644 index 0000000..2a9d04c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_hmac.c @@ -0,0 +1,305 @@ +/*- +* Copyright (c) 2014 Michihiro NAKAJIMA +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "archive_platform.h" + +#ifdef HAVE_STRING_H +#include +#endif +#include "archive.h" +#include "archive_hmac_private.h" + +/* + * On systems that do not support any recognized crypto libraries, + * the archive_hmac.c file is expected to define no usable symbols. + * + * But some compilers and linkers choke on empty object files, so + * define a public symbol that will always exist. This could + * be removed someday if this file gains another always-present + * symbol definition. + */ +int __libarchive_hmac_build_hack(void) { + return 0; +} + + +#ifdef ARCHIVE_HMAC_USE_Apple_CommonCrypto + +static int +__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) +{ + CCHmacInit(ctx, kCCHmacAlgSHA1, key, key_len); + return 0; +} + +static void +__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, + size_t data_len) +{ + CCHmacUpdate(ctx, data, data_len); +} + +static void +__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) +{ + CCHmacFinal(ctx, out); + *out_len = 20; +} + +static void +__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); +} + +#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) + +#ifndef BCRYPT_HASH_REUSABLE_FLAG +# define BCRYPT_HASH_REUSABLE_FLAG 0x00000020 +#endif + +static int +__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) +{ +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif + BCRYPT_ALG_HANDLE hAlg; + BCRYPT_HASH_HANDLE hHash; + DWORD hash_len; + PBYTE hash; + ULONG result; + NTSTATUS status; + + ctx->hAlg = NULL; + status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA1_ALGORITHM, + MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG); + if (!BCRYPT_SUCCESS(status)) + return -1; + status = BCryptGetProperty(hAlg, BCRYPT_HASH_LENGTH, (PUCHAR)&hash_len, + sizeof(hash_len), &result, 0); + if (!BCRYPT_SUCCESS(status)) { + BCryptCloseAlgorithmProvider(hAlg, 0); + return -1; + } + hash = (PBYTE)HeapAlloc(GetProcessHeap(), 0, hash_len); + if (hash == NULL) { + BCryptCloseAlgorithmProvider(hAlg, 0); + return -1; + } + status = BCryptCreateHash(hAlg, &hHash, NULL, 0, + (PUCHAR)key, (ULONG)key_len, BCRYPT_HASH_REUSABLE_FLAG); + if (!BCRYPT_SUCCESS(status)) { + BCryptCloseAlgorithmProvider(hAlg, 0); + HeapFree(GetProcessHeap(), 0, hash); + return -1; + } + + ctx->hAlg = hAlg; + ctx->hHash = hHash; + ctx->hash_len = hash_len; + ctx->hash = hash; + + return 0; +} + +static void +__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, + size_t data_len) +{ + BCryptHashData(ctx->hHash, (PUCHAR)(uintptr_t)data, (ULONG)data_len, 0); +} + +static void +__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) +{ + BCryptFinishHash(ctx->hHash, ctx->hash, ctx->hash_len, 0); + if (ctx->hash_len == *out_len) + memcpy(out, ctx->hash, *out_len); +} + +static void +__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) +{ + if (ctx->hAlg != NULL) { + BCryptCloseAlgorithmProvider(ctx->hAlg, 0); + HeapFree(GetProcessHeap(), 0, ctx->hash); + ctx->hAlg = NULL; + } +} + +#elif defined(HAVE_LIBMBEDCRYPTO) && defined(HAVE_MBEDTLS_MD_H) + +static int +__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) +{ + const mbedtls_md_info_t *info; + int ret; + + mbedtls_md_init(ctx); + info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); + if (info == NULL) { + mbedtls_md_free(ctx); + return (-1); + } + ret = mbedtls_md_setup(ctx, info, 1); + if (ret != 0) { + mbedtls_md_free(ctx); + return (-1); + } + ret = mbedtls_md_hmac_starts(ctx, key, key_len); + if (ret != 0) { + mbedtls_md_free(ctx); + return (-1); + } + return 0; +} + +static void +__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, + size_t data_len) +{ + mbedtls_md_hmac_update(ctx, data, data_len); +} + +static void __hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) +{ + (void)out_len; /* UNUSED */ + + mbedtls_md_hmac_finish(ctx, out); +} + +static void __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) +{ + mbedtls_md_free(ctx); + memset(ctx, 0, sizeof(*ctx)); +} + +#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_HMAC_H) + +static int +__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) +{ + hmac_sha1_set_key(ctx, key_len, key); + return 0; +} + +static void +__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, + size_t data_len) +{ + hmac_sha1_update(ctx, data_len, data); +} + +static void +__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) +{ + hmac_sha1_digest(ctx, (unsigned)*out_len, out); +} + +static void +__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); +} + +#elif defined(HAVE_LIBCRYPTO) + +static int +__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) +{ + *ctx = HMAC_CTX_new(); + if (*ctx == NULL) + return -1; + HMAC_Init_ex(*ctx, key, key_len, EVP_sha1(), NULL); + return 0; +} + +static void +__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, + size_t data_len) +{ + HMAC_Update(*ctx, data, data_len); +} + +static void +__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) +{ + unsigned int len = (unsigned int)*out_len; + + HMAC_Final(*ctx, out, &len); + *out_len = len; +} + +static void +__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) +{ + HMAC_CTX_free(*ctx); + *ctx = NULL; +} + +#else + +/* Stub */ +static int +__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) +{ + (void)ctx;/* UNUSED */ + (void)key;/* UNUSED */ + (void)key_len;/* UNUSED */ + return -1; +} + +static void +__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, + size_t data_len) +{ + (void)ctx;/* UNUSED */ + (void)data;/* UNUSED */ + (void)data_len;/* UNUSED */ +} + +static void +__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) +{ + (void)ctx;/* UNUSED */ + (void)out;/* UNUSED */ + (void)out_len;/* UNUSED */ +} + +static void +__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) +{ + (void)ctx;/* UNUSED */ +} + +#endif + +const struct archive_hmac __archive_hmac = { + &__hmac_sha1_init, + &__hmac_sha1_update, + &__hmac_sha1_final, + &__hmac_sha1_cleanup, +}; diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_hmac_private.h b/dependencies/libarchive-3.4.2/libarchive/archive_hmac_private.h new file mode 100644 index 0000000..13a67d4 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_hmac_private.h @@ -0,0 +1,110 @@ +/*- +* Copyright (c) 2014 Michihiro NAKAJIMA +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef ARCHIVE_HMAC_PRIVATE_H_INCLUDED +#define ARCHIVE_HMAC_PRIVATE_H_INCLUDED + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif +/* + * On systems that do not support any recognized crypto libraries, + * the archive_hmac.c file is expected to define no usable symbols. + * + * But some compilers and linkers choke on empty object files, so + * define a public symbol that will always exist. This could + * be removed someday if this file gains another always-present + * symbol definition. + */ +int __libarchive_hmac_build_hack(void); + +#ifdef __APPLE__ +# include +# if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 +# define ARCHIVE_HMAC_USE_Apple_CommonCrypto +# endif +#endif + +#ifdef ARCHIVE_HMAC_USE_Apple_CommonCrypto +#include + +typedef CCHmacContext archive_hmac_sha1_ctx; + +#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) +#include + +typedef struct { + BCRYPT_ALG_HANDLE hAlg; + BCRYPT_HASH_HANDLE hHash; + DWORD hash_len; + PBYTE hash; + +} archive_hmac_sha1_ctx; + +#elif defined(HAVE_LIBMBEDCRYPTO) && defined(HAVE_MBEDTLS_MD_H) +#include + +typedef mbedtls_md_context_t archive_hmac_sha1_ctx; + +#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_HMAC_H) +#include + +typedef struct hmac_sha1_ctx archive_hmac_sha1_ctx; + +#elif defined(HAVE_LIBCRYPTO) +#include "archive_openssl_hmac_private.h" + +typedef HMAC_CTX* archive_hmac_sha1_ctx; + +#else + +typedef int archive_hmac_sha1_ctx; + +#endif + + +/* HMAC */ +#define archive_hmac_sha1_init(ctx, key, key_len)\ + __archive_hmac.__hmac_sha1_init(ctx, key, key_len) +#define archive_hmac_sha1_update(ctx, data, data_len)\ + __archive_hmac.__hmac_sha1_update(ctx, data, data_len) +#define archive_hmac_sha1_final(ctx, out, out_len)\ + __archive_hmac.__hmac_sha1_final(ctx, out, out_len) +#define archive_hmac_sha1_cleanup(ctx)\ + __archive_hmac.__hmac_sha1_cleanup(ctx) + + +struct archive_hmac { + /* HMAC */ + int (*__hmac_sha1_init)(archive_hmac_sha1_ctx *, const uint8_t *, + size_t); + void (*__hmac_sha1_update)(archive_hmac_sha1_ctx *, const uint8_t *, + size_t); + void (*__hmac_sha1_final)(archive_hmac_sha1_ctx *, uint8_t *, size_t *); + void (*__hmac_sha1_cleanup)(archive_hmac_sha1_ctx *); +}; + +extern const struct archive_hmac __archive_hmac; +#endif /* ARCHIVE_HMAC_PRIVATE_H_INCLUDED */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_match.c b/dependencies/libarchive-3.4.2/libarchive/archive_match.c new file mode 100644 index 0000000..04747b1 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_match.c @@ -0,0 +1,1875 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_entry.h" +#include "archive_getdate.h" +#include "archive_pathmatch.h" +#include "archive_rb.h" +#include "archive_string.h" + +struct match { + struct match *next; + int matches; + struct archive_mstring pattern; +}; + +struct match_list { + struct match *first; + struct match **last; + int count; + int unmatched_count; + struct match *unmatched_next; + int unmatched_eof; +}; + +struct match_file { + struct archive_rb_node node; + struct match_file *next; + struct archive_mstring pathname; + int flag; + time_t mtime_sec; + long mtime_nsec; + time_t ctime_sec; + long ctime_nsec; +}; + +struct entry_list { + struct match_file *first; + struct match_file **last; + int count; +}; + +struct id_array { + size_t size;/* Allocated size */ + size_t count; + int64_t *ids; +}; + +#define PATTERN_IS_SET 1 +#define TIME_IS_SET 2 +#define ID_IS_SET 4 + +struct archive_match { + struct archive archive; + + /* exclusion/inclusion set flag. */ + int setflag; + + /* Recursively include directory content? */ + int recursive_include; + + /* + * Matching filename patterns. + */ + struct match_list exclusions; + struct match_list inclusions; + + /* + * Matching time stamps. + */ + time_t now; + int newer_mtime_filter; + time_t newer_mtime_sec; + long newer_mtime_nsec; + int newer_ctime_filter; + time_t newer_ctime_sec; + long newer_ctime_nsec; + int older_mtime_filter; + time_t older_mtime_sec; + long older_mtime_nsec; + int older_ctime_filter; + time_t older_ctime_sec; + long older_ctime_nsec; + /* + * Matching time stamps with its filename. + */ + struct archive_rb_tree exclusion_tree; + struct entry_list exclusion_entry_list; + + /* + * Matching file owners. + */ + struct id_array inclusion_uids; + struct id_array inclusion_gids; + struct match_list inclusion_unames; + struct match_list inclusion_gnames; +}; + +static int add_pattern_from_file(struct archive_match *, + struct match_list *, int, const void *, int); +static int add_entry(struct archive_match *, int, + struct archive_entry *); +static int add_owner_id(struct archive_match *, struct id_array *, + int64_t); +static int add_owner_name(struct archive_match *, struct match_list *, + int, const void *); +static int add_pattern_mbs(struct archive_match *, struct match_list *, + const char *); +static int add_pattern_wcs(struct archive_match *, struct match_list *, + const wchar_t *); +static int cmp_key_mbs(const struct archive_rb_node *, const void *); +static int cmp_key_wcs(const struct archive_rb_node *, const void *); +static int cmp_node_mbs(const struct archive_rb_node *, + const struct archive_rb_node *); +static int cmp_node_wcs(const struct archive_rb_node *, + const struct archive_rb_node *); +static void entry_list_add(struct entry_list *, struct match_file *); +static void entry_list_free(struct entry_list *); +static void entry_list_init(struct entry_list *); +static int error_nomem(struct archive_match *); +static void match_list_add(struct match_list *, struct match *); +static void match_list_free(struct match_list *); +static void match_list_init(struct match_list *); +static int match_list_unmatched_inclusions_next(struct archive_match *, + struct match_list *, int, const void **); +static int match_owner_id(struct id_array *, int64_t); +#if !defined(_WIN32) || defined(__CYGWIN__) +static int match_owner_name_mbs(struct archive_match *, + struct match_list *, const char *); +#else +static int match_owner_name_wcs(struct archive_match *, + struct match_list *, const wchar_t *); +#endif +static int match_path_exclusion(struct archive_match *, + struct match *, int, const void *); +static int match_path_inclusion(struct archive_match *, + struct match *, int, const void *); +static int owner_excluded(struct archive_match *, + struct archive_entry *); +static int path_excluded(struct archive_match *, int, const void *); +static int set_timefilter(struct archive_match *, int, time_t, long, + time_t, long); +static int set_timefilter_pathname_mbs(struct archive_match *, + int, const char *); +static int set_timefilter_pathname_wcs(struct archive_match *, + int, const wchar_t *); +static int set_timefilter_date(struct archive_match *, int, const char *); +static int set_timefilter_date_w(struct archive_match *, int, + const wchar_t *); +static int time_excluded(struct archive_match *, + struct archive_entry *); +static int validate_time_flag(struct archive *, int, const char *); + +#define get_date __archive_get_date + +static const struct archive_rb_tree_ops rb_ops_mbs = { + cmp_node_mbs, cmp_key_mbs +}; + +static const struct archive_rb_tree_ops rb_ops_wcs = { + cmp_node_wcs, cmp_key_wcs +}; + +/* + * The matching logic here needs to be re-thought. I started out to + * try to mimic gtar's matching logic, but it's not entirely + * consistent. In particular 'tar -t' and 'tar -x' interpret patterns + * on the command line as anchored, but --exclude doesn't. + */ + +static int +error_nomem(struct archive_match *a) +{ + archive_set_error(&(a->archive), ENOMEM, "No memory"); + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); +} + +/* + * Create an ARCHIVE_MATCH object. + */ +struct archive * +archive_match_new(void) +{ + struct archive_match *a; + + a = (struct archive_match *)calloc(1, sizeof(*a)); + if (a == NULL) + return (NULL); + a->archive.magic = ARCHIVE_MATCH_MAGIC; + a->archive.state = ARCHIVE_STATE_NEW; + a->recursive_include = 1; + match_list_init(&(a->inclusions)); + match_list_init(&(a->exclusions)); + __archive_rb_tree_init(&(a->exclusion_tree), &rb_ops_mbs); + entry_list_init(&(a->exclusion_entry_list)); + match_list_init(&(a->inclusion_unames)); + match_list_init(&(a->inclusion_gnames)); + time(&a->now); + return (&(a->archive)); +} + +/* + * Free an ARCHIVE_MATCH object. + */ +int +archive_match_free(struct archive *_a) +{ + struct archive_match *a; + + if (_a == NULL) + return (ARCHIVE_OK); + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_match_free"); + a = (struct archive_match *)_a; + match_list_free(&(a->inclusions)); + match_list_free(&(a->exclusions)); + entry_list_free(&(a->exclusion_entry_list)); + free(a->inclusion_uids.ids); + free(a->inclusion_gids.ids); + match_list_free(&(a->inclusion_unames)); + match_list_free(&(a->inclusion_gnames)); + free(a); + return (ARCHIVE_OK); +} + +/* + * Convenience function to perform all exclusion tests. + * + * Returns 1 if archive entry is excluded. + * Returns 0 if archive entry is not excluded. + * Returns <0 if something error happened. + */ +int +archive_match_excluded(struct archive *_a, struct archive_entry *entry) +{ + struct archive_match *a; + int r; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_excluded_ae"); + + a = (struct archive_match *)_a; + if (entry == NULL) { + archive_set_error(&(a->archive), EINVAL, "entry is NULL"); + return (ARCHIVE_FAILED); + } + + r = 0; + if (a->setflag & PATTERN_IS_SET) { +#if defined(_WIN32) && !defined(__CYGWIN__) + r = path_excluded(a, 0, archive_entry_pathname_w(entry)); +#else + r = path_excluded(a, 1, archive_entry_pathname(entry)); +#endif + if (r != 0) + return (r); + } + + if (a->setflag & TIME_IS_SET) { + r = time_excluded(a, entry); + if (r != 0) + return (r); + } + + if (a->setflag & ID_IS_SET) + r = owner_excluded(a, entry); + return (r); +} + +/* + * Utility functions to manage exclusion/inclusion patterns + */ + +int +archive_match_exclude_pattern(struct archive *_a, const char *pattern) +{ + struct archive_match *a; + int r; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_exclude_pattern"); + a = (struct archive_match *)_a; + + if (pattern == NULL || *pattern == '\0') { + archive_set_error(&(a->archive), EINVAL, "pattern is empty"); + return (ARCHIVE_FAILED); + } + if ((r = add_pattern_mbs(a, &(a->exclusions), pattern)) != ARCHIVE_OK) + return (r); + return (ARCHIVE_OK); +} + +int +archive_match_exclude_pattern_w(struct archive *_a, const wchar_t *pattern) +{ + struct archive_match *a; + int r; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_exclude_pattern_w"); + a = (struct archive_match *)_a; + + if (pattern == NULL || *pattern == L'\0') { + archive_set_error(&(a->archive), EINVAL, "pattern is empty"); + return (ARCHIVE_FAILED); + } + if ((r = add_pattern_wcs(a, &(a->exclusions), pattern)) != ARCHIVE_OK) + return (r); + return (ARCHIVE_OK); +} + +int +archive_match_exclude_pattern_from_file(struct archive *_a, + const char *pathname, int nullSeparator) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_exclude_pattern_from_file"); + a = (struct archive_match *)_a; + + return add_pattern_from_file(a, &(a->exclusions), 1, pathname, + nullSeparator); +} + +int +archive_match_exclude_pattern_from_file_w(struct archive *_a, + const wchar_t *pathname, int nullSeparator) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_exclude_pattern_from_file_w"); + a = (struct archive_match *)_a; + + return add_pattern_from_file(a, &(a->exclusions), 0, pathname, + nullSeparator); +} + +int +archive_match_include_pattern(struct archive *_a, const char *pattern) +{ + struct archive_match *a; + int r; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_include_pattern"); + a = (struct archive_match *)_a; + + if (pattern == NULL || *pattern == '\0') { + archive_set_error(&(a->archive), EINVAL, "pattern is empty"); + return (ARCHIVE_FAILED); + } + if ((r = add_pattern_mbs(a, &(a->inclusions), pattern)) != ARCHIVE_OK) + return (r); + return (ARCHIVE_OK); +} + +int +archive_match_include_pattern_w(struct archive *_a, const wchar_t *pattern) +{ + struct archive_match *a; + int r; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_include_pattern_w"); + a = (struct archive_match *)_a; + + if (pattern == NULL || *pattern == L'\0') { + archive_set_error(&(a->archive), EINVAL, "pattern is empty"); + return (ARCHIVE_FAILED); + } + if ((r = add_pattern_wcs(a, &(a->inclusions), pattern)) != ARCHIVE_OK) + return (r); + return (ARCHIVE_OK); +} + +int +archive_match_include_pattern_from_file(struct archive *_a, + const char *pathname, int nullSeparator) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_include_pattern_from_file"); + a = (struct archive_match *)_a; + + return add_pattern_from_file(a, &(a->inclusions), 1, pathname, + nullSeparator); +} + +int +archive_match_include_pattern_from_file_w(struct archive *_a, + const wchar_t *pathname, int nullSeparator) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_include_pattern_from_file_w"); + a = (struct archive_match *)_a; + + return add_pattern_from_file(a, &(a->inclusions), 0, pathname, + nullSeparator); +} + +/* + * Test functions for pathname patterns. + * + * Returns 1 if archive entry is excluded. + * Returns 0 if archive entry is not excluded. + * Returns <0 if something error happened. + */ +int +archive_match_path_excluded(struct archive *_a, + struct archive_entry *entry) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_path_excluded"); + + a = (struct archive_match *)_a; + if (entry == NULL) { + archive_set_error(&(a->archive), EINVAL, "entry is NULL"); + return (ARCHIVE_FAILED); + } + + /* If we don't have exclusion/inclusion pattern set at all, + * the entry is always not excluded. */ + if ((a->setflag & PATTERN_IS_SET) == 0) + return (0); +#if defined(_WIN32) && !defined(__CYGWIN__) + return (path_excluded(a, 0, archive_entry_pathname_w(entry))); +#else + return (path_excluded(a, 1, archive_entry_pathname(entry))); +#endif +} + +/* + * When recursive inclusion of directory content is enabled, + * an inclusion pattern that matches a directory will also + * include everything beneath that directory. Enabled by default. + * + * For compatibility with GNU tar, exclusion patterns always + * match if a subset of the full patch matches (i.e., they are + * are not rooted at the beginning of the path) and thus there + * is no corresponding non-recursive exclusion mode. + */ +int +archive_match_set_inclusion_recursion(struct archive *_a, int enabled) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_set_inclusion_recursion"); + a = (struct archive_match *)_a; + a->recursive_include = enabled; + return (ARCHIVE_OK); +} + +/* + * Utility functions to get statistic information for inclusion patterns. + */ +int +archive_match_path_unmatched_inclusions(struct archive *_a) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions"); + a = (struct archive_match *)_a; + + return (a->inclusions.unmatched_count); +} + +int +archive_match_path_unmatched_inclusions_next(struct archive *_a, + const char **_p) +{ + struct archive_match *a; + const void *v; + int r; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions_next"); + a = (struct archive_match *)_a; + + r = match_list_unmatched_inclusions_next(a, &(a->inclusions), 1, &v); + *_p = (const char *)v; + return (r); +} + +int +archive_match_path_unmatched_inclusions_next_w(struct archive *_a, + const wchar_t **_p) +{ + struct archive_match *a; + const void *v; + int r; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions_next_w"); + a = (struct archive_match *)_a; + + r = match_list_unmatched_inclusions_next(a, &(a->inclusions), 0, &v); + *_p = (const wchar_t *)v; + return (r); +} + +/* + * Add inclusion/exclusion patterns. + */ +static int +add_pattern_mbs(struct archive_match *a, struct match_list *list, + const char *pattern) +{ + struct match *match; + size_t len; + + match = calloc(1, sizeof(*match)); + if (match == NULL) + return (error_nomem(a)); + /* Both "foo/" and "foo" should match "foo/bar". */ + len = strlen(pattern); + if (len && pattern[len - 1] == '/') + --len; + archive_mstring_copy_mbs_len(&(match->pattern), pattern, len); + match_list_add(list, match); + a->setflag |= PATTERN_IS_SET; + return (ARCHIVE_OK); +} + +static int +add_pattern_wcs(struct archive_match *a, struct match_list *list, + const wchar_t *pattern) +{ + struct match *match; + size_t len; + + match = calloc(1, sizeof(*match)); + if (match == NULL) + return (error_nomem(a)); + /* Both "foo/" and "foo" should match "foo/bar". */ + len = wcslen(pattern); + if (len && pattern[len - 1] == L'/') + --len; + archive_mstring_copy_wcs_len(&(match->pattern), pattern, len); + match_list_add(list, match); + a->setflag |= PATTERN_IS_SET; + return (ARCHIVE_OK); +} + +static int +add_pattern_from_file(struct archive_match *a, struct match_list *mlist, + int mbs, const void *pathname, int nullSeparator) +{ + struct archive *ar; + struct archive_entry *ae; + struct archive_string as; + const void *buff; + size_t size; + int64_t offset; + int r; + + ar = archive_read_new(); + if (ar == NULL) { + archive_set_error(&(a->archive), ENOMEM, "No memory"); + return (ARCHIVE_FATAL); + } + r = archive_read_support_format_raw(ar); + r = archive_read_support_format_empty(ar); + if (r != ARCHIVE_OK) { + archive_copy_error(&(a->archive), ar); + archive_read_free(ar); + return (r); + } + if (mbs) + r = archive_read_open_filename(ar, pathname, 512*20); + else + r = archive_read_open_filename_w(ar, pathname, 512*20); + if (r != ARCHIVE_OK) { + archive_copy_error(&(a->archive), ar); + archive_read_free(ar); + return (r); + } + r = archive_read_next_header(ar, &ae); + if (r != ARCHIVE_OK) { + archive_read_free(ar); + if (r == ARCHIVE_EOF) { + return (ARCHIVE_OK); + } else { + archive_copy_error(&(a->archive), ar); + return (r); + } + } + + archive_string_init(&as); + + while ((r = archive_read_data_block(ar, &buff, &size, &offset)) + == ARCHIVE_OK) { + const char *b = (const char *)buff; + + while (size) { + const char *s = (const char *)b; + size_t length = 0; + int found_separator = 0; + + while (length < size) { + if (nullSeparator) { + if (*b == '\0') { + found_separator = 1; + break; + } + } else { + if (*b == 0x0d || *b == 0x0a) { + found_separator = 1; + break; + } + } + b++; + length++; + } + if (!found_separator) { + archive_strncat(&as, s, length); + /* Read next data block. */ + break; + } + b++; + size -= length + 1; + archive_strncat(&as, s, length); + + /* If the line is not empty, add the pattern. */ + if (archive_strlen(&as) > 0) { + /* Add pattern. */ + r = add_pattern_mbs(a, mlist, as.s); + if (r != ARCHIVE_OK) { + archive_read_free(ar); + archive_string_free(&as); + return (r); + } + archive_string_empty(&as); + } + } + } + + /* If an error occurred, report it immediately. */ + if (r < ARCHIVE_OK) { + archive_copy_error(&(a->archive), ar); + archive_read_free(ar); + archive_string_free(&as); + return (r); + } + + /* If the line is not empty, add the pattern. */ + if (r == ARCHIVE_EOF && archive_strlen(&as) > 0) { + /* Add pattern. */ + r = add_pattern_mbs(a, mlist, as.s); + if (r != ARCHIVE_OK) { + archive_read_free(ar); + archive_string_free(&as); + return (r); + } + } + archive_read_free(ar); + archive_string_free(&as); + return (ARCHIVE_OK); +} + +/* + * Test if pathname is excluded by inclusion/exclusion patterns. + */ +static int +path_excluded(struct archive_match *a, int mbs, const void *pathname) +{ + struct match *match; + struct match *matched; + int r; + + if (a == NULL) + return (0); + + /* Mark off any unmatched inclusions. */ + /* In particular, if a filename does appear in the archive and + * is explicitly included and excluded, then we don't report + * it as missing even though we don't extract it. + */ + matched = NULL; + for (match = a->inclusions.first; match != NULL; + match = match->next){ + if (match->matches == 0 && + (r = match_path_inclusion(a, match, mbs, pathname)) != 0) { + if (r < 0) + return (r); + a->inclusions.unmatched_count--; + match->matches++; + matched = match; + } + } + + /* Exclusions take priority */ + for (match = a->exclusions.first; match != NULL; + match = match->next){ + r = match_path_exclusion(a, match, mbs, pathname); + if (r) + return (r); + } + + /* It's not excluded and we found an inclusion above, so it's + * included. */ + if (matched != NULL) + return (0); + + + /* We didn't find an unmatched inclusion, check the remaining ones. */ + for (match = a->inclusions.first; match != NULL; + match = match->next){ + /* We looked at previously-unmatched inclusions already. */ + if (match->matches > 0 && + (r = match_path_inclusion(a, match, mbs, pathname)) != 0) { + if (r < 0) + return (r); + match->matches++; + return (0); + } + } + + /* If there were inclusions, default is to exclude. */ + if (a->inclusions.first != NULL) + return (1); + + /* No explicit inclusions, default is to match. */ + return (0); +} + +/* + * This is a little odd, but it matches the default behavior of + * gtar. In particular, 'a*b' will match 'foo/a1111/222b/bar' + * + */ +static int +match_path_exclusion(struct archive_match *a, struct match *m, + int mbs, const void *pn) +{ + int flag = PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END; + int r; + + if (mbs) { + const char *p; + r = archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p); + if (r == 0) + return (archive_pathmatch(p, (const char *)pn, flag)); + } else { + const wchar_t *p; + r = archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p); + if (r == 0) + return (archive_pathmatch_w(p, (const wchar_t *)pn, + flag)); + } + if (errno == ENOMEM) + return (error_nomem(a)); + return (0); +} + +/* + * Again, mimic gtar: inclusions are always anchored (have to match + * the beginning of the path) even though exclusions are not anchored. + */ +static int +match_path_inclusion(struct archive_match *a, struct match *m, + int mbs, const void *pn) +{ + /* Recursive operation requires only a prefix match. */ + int flag = a->recursive_include ? + PATHMATCH_NO_ANCHOR_END : + 0; + int r; + + if (mbs) { + const char *p; + r = archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p); + if (r == 0) + return (archive_pathmatch(p, (const char *)pn, flag)); + } else { + const wchar_t *p; + r = archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p); + if (r == 0) + return (archive_pathmatch_w(p, (const wchar_t *)pn, + flag)); + } + if (errno == ENOMEM) + return (error_nomem(a)); + return (0); +} + +static void +match_list_init(struct match_list *list) +{ + list->first = NULL; + list->last = &(list->first); + list->count = 0; +} + +static void +match_list_free(struct match_list *list) +{ + struct match *p, *q; + + for (p = list->first; p != NULL; ) { + q = p; + p = p->next; + archive_mstring_clean(&(q->pattern)); + free(q); + } +} + +static void +match_list_add(struct match_list *list, struct match *m) +{ + *list->last = m; + list->last = &(m->next); + list->count++; + list->unmatched_count++; +} + +static int +match_list_unmatched_inclusions_next(struct archive_match *a, + struct match_list *list, int mbs, const void **vp) +{ + struct match *m; + + *vp = NULL; + if (list->unmatched_eof) { + list->unmatched_eof = 0; + return (ARCHIVE_EOF); + } + if (list->unmatched_next == NULL) { + if (list->unmatched_count == 0) + return (ARCHIVE_EOF); + list->unmatched_next = list->first; + } + + for (m = list->unmatched_next; m != NULL; m = m->next) { + int r; + + if (m->matches) + continue; + if (mbs) { + const char *p; + r = archive_mstring_get_mbs(&(a->archive), + &(m->pattern), &p); + if (r < 0 && errno == ENOMEM) + return (error_nomem(a)); + if (p == NULL) + p = ""; + *vp = p; + } else { + const wchar_t *p; + r = archive_mstring_get_wcs(&(a->archive), + &(m->pattern), &p); + if (r < 0 && errno == ENOMEM) + return (error_nomem(a)); + if (p == NULL) + p = L""; + *vp = p; + } + list->unmatched_next = m->next; + if (list->unmatched_next == NULL) + /* To return EOF next time. */ + list->unmatched_eof = 1; + return (ARCHIVE_OK); + } + list->unmatched_next = NULL; + return (ARCHIVE_EOF); +} + +/* + * Utility functions to manage inclusion timestamps. + */ +int +archive_match_include_time(struct archive *_a, int flag, time_t sec, + long nsec) +{ + int r; + + r = validate_time_flag(_a, flag, "archive_match_include_time"); + if (r != ARCHIVE_OK) + return (r); + return set_timefilter((struct archive_match *)_a, flag, + sec, nsec, sec, nsec); +} + +int +archive_match_include_date(struct archive *_a, int flag, + const char *datestr) +{ + int r; + + r = validate_time_flag(_a, flag, "archive_match_include_date"); + if (r != ARCHIVE_OK) + return (r); + return set_timefilter_date((struct archive_match *)_a, flag, datestr); +} + +int +archive_match_include_date_w(struct archive *_a, int flag, + const wchar_t *datestr) +{ + int r; + + r = validate_time_flag(_a, flag, "archive_match_include_date_w"); + if (r != ARCHIVE_OK) + return (r); + + return set_timefilter_date_w((struct archive_match *)_a, flag, datestr); +} + +int +archive_match_include_file_time(struct archive *_a, int flag, + const char *pathname) +{ + int r; + + r = validate_time_flag(_a, flag, "archive_match_include_file_time"); + if (r != ARCHIVE_OK) + return (r); + return set_timefilter_pathname_mbs((struct archive_match *)_a, + flag, pathname); +} + +int +archive_match_include_file_time_w(struct archive *_a, int flag, + const wchar_t *pathname) +{ + int r; + + r = validate_time_flag(_a, flag, "archive_match_include_file_time_w"); + if (r != ARCHIVE_OK) + return (r); + return set_timefilter_pathname_wcs((struct archive_match *)_a, + flag, pathname); +} + +int +archive_match_exclude_entry(struct archive *_a, int flag, + struct archive_entry *entry) +{ + struct archive_match *a; + int r; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_time_include_entry"); + a = (struct archive_match *)_a; + + if (entry == NULL) { + archive_set_error(&(a->archive), EINVAL, "entry is NULL"); + return (ARCHIVE_FAILED); + } + r = validate_time_flag(_a, flag, "archive_match_exclude_entry"); + if (r != ARCHIVE_OK) + return (r); + return (add_entry(a, flag, entry)); +} + +/* + * Test function for time stamps. + * + * Returns 1 if archive entry is excluded. + * Returns 0 if archive entry is not excluded. + * Returns <0 if something error happened. + */ +int +archive_match_time_excluded(struct archive *_a, + struct archive_entry *entry) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_time_excluded_ae"); + + a = (struct archive_match *)_a; + if (entry == NULL) { + archive_set_error(&(a->archive), EINVAL, "entry is NULL"); + return (ARCHIVE_FAILED); + } + + /* If we don't have inclusion time set at all, the entry is always + * not excluded. */ + if ((a->setflag & TIME_IS_SET) == 0) + return (0); + return (time_excluded(a, entry)); +} + +static int +validate_time_flag(struct archive *_a, int flag, const char *_fn) +{ + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, _fn); + + /* Check a type of time. */ + if (flag & + ((~(ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME)) & 0xff00)) { + archive_set_error(_a, EINVAL, "Invalid time flag"); + return (ARCHIVE_FAILED); + } + if ((flag & (ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME)) == 0) { + archive_set_error(_a, EINVAL, "No time flag"); + return (ARCHIVE_FAILED); + } + + /* Check a type of comparison. */ + if (flag & + ((~(ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER + | ARCHIVE_MATCH_EQUAL)) & 0x00ff)) { + archive_set_error(_a, EINVAL, "Invalid comparison flag"); + return (ARCHIVE_FAILED); + } + if ((flag & (ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER + | ARCHIVE_MATCH_EQUAL)) == 0) { + archive_set_error(_a, EINVAL, "No comparison flag"); + return (ARCHIVE_FAILED); + } + + return (ARCHIVE_OK); +} + +#define JUST_EQUAL(t) (((t) & (ARCHIVE_MATCH_EQUAL |\ + ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER)) == ARCHIVE_MATCH_EQUAL) +static int +set_timefilter(struct archive_match *a, int timetype, + time_t mtime_sec, long mtime_nsec, time_t ctime_sec, long ctime_nsec) +{ + if (timetype & ARCHIVE_MATCH_MTIME) { + if ((timetype & ARCHIVE_MATCH_NEWER) || JUST_EQUAL(timetype)) { + a->newer_mtime_filter = timetype; + a->newer_mtime_sec = mtime_sec; + a->newer_mtime_nsec = mtime_nsec; + a->setflag |= TIME_IS_SET; + } + if ((timetype & ARCHIVE_MATCH_OLDER) || JUST_EQUAL(timetype)) { + a->older_mtime_filter = timetype; + a->older_mtime_sec = mtime_sec; + a->older_mtime_nsec = mtime_nsec; + a->setflag |= TIME_IS_SET; + } + } + if (timetype & ARCHIVE_MATCH_CTIME) { + if ((timetype & ARCHIVE_MATCH_NEWER) || JUST_EQUAL(timetype)) { + a->newer_ctime_filter = timetype; + a->newer_ctime_sec = ctime_sec; + a->newer_ctime_nsec = ctime_nsec; + a->setflag |= TIME_IS_SET; + } + if ((timetype & ARCHIVE_MATCH_OLDER) || JUST_EQUAL(timetype)) { + a->older_ctime_filter = timetype; + a->older_ctime_sec = ctime_sec; + a->older_ctime_nsec = ctime_nsec; + a->setflag |= TIME_IS_SET; + } + } + return (ARCHIVE_OK); +} + +static int +set_timefilter_date(struct archive_match *a, int timetype, const char *datestr) +{ + time_t t; + + if (datestr == NULL || *datestr == '\0') { + archive_set_error(&(a->archive), EINVAL, "date is empty"); + return (ARCHIVE_FAILED); + } + t = get_date(a->now, datestr); + if (t == (time_t)-1) { + archive_set_error(&(a->archive), EINVAL, "invalid date string"); + return (ARCHIVE_FAILED); + } + return set_timefilter(a, timetype, t, 0, t, 0); +} + +static int +set_timefilter_date_w(struct archive_match *a, int timetype, + const wchar_t *datestr) +{ + struct archive_string as; + time_t t; + + if (datestr == NULL || *datestr == L'\0') { + archive_set_error(&(a->archive), EINVAL, "date is empty"); + return (ARCHIVE_FAILED); + } + + archive_string_init(&as); + if (archive_string_append_from_wcs(&as, datestr, wcslen(datestr)) < 0) { + archive_string_free(&as); + if (errno == ENOMEM) + return (error_nomem(a)); + archive_set_error(&(a->archive), -1, + "Failed to convert WCS to MBS"); + return (ARCHIVE_FAILED); + } + t = get_date(a->now, as.s); + archive_string_free(&as); + if (t == (time_t)-1) { + archive_set_error(&(a->archive), EINVAL, "invalid date string"); + return (ARCHIVE_FAILED); + } + return set_timefilter(a, timetype, t, 0, t, 0); +} + +#if defined(_WIN32) && !defined(__CYGWIN__) +#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) +static int +set_timefilter_find_data(struct archive_match *a, int timetype, + DWORD ftLastWriteTime_dwHighDateTime, DWORD ftLastWriteTime_dwLowDateTime, + DWORD ftCreationTime_dwHighDateTime, DWORD ftCreationTime_dwLowDateTime) +{ + ULARGE_INTEGER utc; + time_t ctime_sec, mtime_sec; + long ctime_ns, mtime_ns; + + utc.HighPart = ftCreationTime_dwHighDateTime; + utc.LowPart = ftCreationTime_dwLowDateTime; + if (utc.QuadPart >= EPOC_TIME) { + utc.QuadPart -= EPOC_TIME; + ctime_sec = (time_t)(utc.QuadPart / 10000000); + ctime_ns = (long)(utc.QuadPart % 10000000) * 100; + } else { + ctime_sec = 0; + ctime_ns = 0; + } + utc.HighPart = ftLastWriteTime_dwHighDateTime; + utc.LowPart = ftLastWriteTime_dwLowDateTime; + if (utc.QuadPart >= EPOC_TIME) { + utc.QuadPart -= EPOC_TIME; + mtime_sec = (time_t)(utc.QuadPart / 10000000); + mtime_ns = (long)(utc.QuadPart % 10000000) * 100; + } else { + mtime_sec = 0; + mtime_ns = 0; + } + return set_timefilter(a, timetype, + mtime_sec, mtime_ns, ctime_sec, ctime_ns); +} + +static int +set_timefilter_pathname_mbs(struct archive_match *a, int timetype, + const char *path) +{ + /* NOTE: stat() on Windows cannot handle nano seconds. */ + HANDLE h; + WIN32_FIND_DATAA d; + + if (path == NULL || *path == '\0') { + archive_set_error(&(a->archive), EINVAL, "pathname is empty"); + return (ARCHIVE_FAILED); + } + h = FindFirstFileA(path, &d); + if (h == INVALID_HANDLE_VALUE) { + la_dosmaperr(GetLastError()); + archive_set_error(&(a->archive), errno, + "Failed to FindFirstFileA"); + return (ARCHIVE_FAILED); + } + FindClose(h); + return set_timefilter_find_data(a, timetype, + d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime, + d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime); +} + +static int +set_timefilter_pathname_wcs(struct archive_match *a, int timetype, + const wchar_t *path) +{ + HANDLE h; + WIN32_FIND_DATAW d; + + if (path == NULL || *path == L'\0') { + archive_set_error(&(a->archive), EINVAL, "pathname is empty"); + return (ARCHIVE_FAILED); + } + h = FindFirstFileW(path, &d); + if (h == INVALID_HANDLE_VALUE) { + la_dosmaperr(GetLastError()); + archive_set_error(&(a->archive), errno, + "Failed to FindFirstFile"); + return (ARCHIVE_FAILED); + } + FindClose(h); + return set_timefilter_find_data(a, timetype, + d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime, + d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime); +} + +#else /* _WIN32 && !__CYGWIN__ */ + +static int +set_timefilter_stat(struct archive_match *a, int timetype, struct stat *st) +{ + struct archive_entry *ae; + time_t ctime_sec, mtime_sec; + long ctime_ns, mtime_ns; + + ae = archive_entry_new(); + if (ae == NULL) + return (error_nomem(a)); + archive_entry_copy_stat(ae, st); + ctime_sec = archive_entry_ctime(ae); + ctime_ns = archive_entry_ctime_nsec(ae); + mtime_sec = archive_entry_mtime(ae); + mtime_ns = archive_entry_mtime_nsec(ae); + archive_entry_free(ae); + return set_timefilter(a, timetype, mtime_sec, mtime_ns, + ctime_sec, ctime_ns); +} + +static int +set_timefilter_pathname_mbs(struct archive_match *a, int timetype, + const char *path) +{ + struct stat st; + + if (path == NULL || *path == '\0') { + archive_set_error(&(a->archive), EINVAL, "pathname is empty"); + return (ARCHIVE_FAILED); + } + if (la_stat(path, &st) != 0) { + archive_set_error(&(a->archive), errno, "Failed to stat()"); + return (ARCHIVE_FAILED); + } + return (set_timefilter_stat(a, timetype, &st)); +} + +static int +set_timefilter_pathname_wcs(struct archive_match *a, int timetype, + const wchar_t *path) +{ + struct archive_string as; + int r; + + if (path == NULL || *path == L'\0') { + archive_set_error(&(a->archive), EINVAL, "pathname is empty"); + return (ARCHIVE_FAILED); + } + + /* Convert WCS filename to MBS filename. */ + archive_string_init(&as); + if (archive_string_append_from_wcs(&as, path, wcslen(path)) < 0) { + archive_string_free(&as); + if (errno == ENOMEM) + return (error_nomem(a)); + archive_set_error(&(a->archive), -1, + "Failed to convert WCS to MBS"); + return (ARCHIVE_FAILED); + } + + r = set_timefilter_pathname_mbs(a, timetype, as.s); + archive_string_free(&as); + + return (r); +} +#endif /* _WIN32 && !__CYGWIN__ */ + +/* + * Call back functions for archive_rb. + */ +static int +cmp_node_mbs(const struct archive_rb_node *n1, + const struct archive_rb_node *n2) +{ + struct match_file *f1 = (struct match_file *)(uintptr_t)n1; + struct match_file *f2 = (struct match_file *)(uintptr_t)n2; + const char *p1, *p2; + + archive_mstring_get_mbs(NULL, &(f1->pathname), &p1); + archive_mstring_get_mbs(NULL, &(f2->pathname), &p2); + if (p1 == NULL) + return (1); + if (p2 == NULL) + return (-1); + return (strcmp(p1, p2)); +} + +static int +cmp_key_mbs(const struct archive_rb_node *n, const void *key) +{ + struct match_file *f = (struct match_file *)(uintptr_t)n; + const char *p; + + archive_mstring_get_mbs(NULL, &(f->pathname), &p); + if (p == NULL) + return (-1); + return (strcmp(p, (const char *)key)); +} + +static int +cmp_node_wcs(const struct archive_rb_node *n1, + const struct archive_rb_node *n2) +{ + struct match_file *f1 = (struct match_file *)(uintptr_t)n1; + struct match_file *f2 = (struct match_file *)(uintptr_t)n2; + const wchar_t *p1, *p2; + + archive_mstring_get_wcs(NULL, &(f1->pathname), &p1); + archive_mstring_get_wcs(NULL, &(f2->pathname), &p2); + if (p1 == NULL) + return (1); + if (p2 == NULL) + return (-1); + return (wcscmp(p1, p2)); +} + +static int +cmp_key_wcs(const struct archive_rb_node *n, const void *key) +{ + struct match_file *f = (struct match_file *)(uintptr_t)n; + const wchar_t *p; + + archive_mstring_get_wcs(NULL, &(f->pathname), &p); + if (p == NULL) + return (-1); + return (wcscmp(p, (const wchar_t *)key)); +} + +static void +entry_list_init(struct entry_list *list) +{ + list->first = NULL; + list->last = &(list->first); + list->count = 0; +} + +static void +entry_list_free(struct entry_list *list) +{ + struct match_file *p, *q; + + for (p = list->first; p != NULL; ) { + q = p; + p = p->next; + archive_mstring_clean(&(q->pathname)); + free(q); + } +} + +static void +entry_list_add(struct entry_list *list, struct match_file *file) +{ + *list->last = file; + list->last = &(file->next); + list->count++; +} + +static int +add_entry(struct archive_match *a, int flag, + struct archive_entry *entry) +{ + struct match_file *f; + const void *pathname; + int r; + + f = calloc(1, sizeof(*f)); + if (f == NULL) + return (error_nomem(a)); + +#if defined(_WIN32) && !defined(__CYGWIN__) + pathname = archive_entry_pathname_w(entry); + if (pathname == NULL) { + free(f); + archive_set_error(&(a->archive), EINVAL, "pathname is NULL"); + return (ARCHIVE_FAILED); + } + archive_mstring_copy_wcs(&(f->pathname), pathname); + a->exclusion_tree.rbt_ops = &rb_ops_wcs; +#else + (void)rb_ops_wcs; + pathname = archive_entry_pathname(entry); + if (pathname == NULL) { + free(f); + archive_set_error(&(a->archive), EINVAL, "pathname is NULL"); + return (ARCHIVE_FAILED); + } + archive_mstring_copy_mbs(&(f->pathname), pathname); + a->exclusion_tree.rbt_ops = &rb_ops_mbs; +#endif + f->flag = flag; + f->mtime_sec = archive_entry_mtime(entry); + f->mtime_nsec = archive_entry_mtime_nsec(entry); + f->ctime_sec = archive_entry_ctime(entry); + f->ctime_nsec = archive_entry_ctime_nsec(entry); + r = __archive_rb_tree_insert_node(&(a->exclusion_tree), &(f->node)); + if (!r) { + struct match_file *f2; + + /* Get the duplicated file. */ + f2 = (struct match_file *)__archive_rb_tree_find_node( + &(a->exclusion_tree), pathname); + + /* + * We always overwrite comparison condition. + * If you do not want to overwrite it, you should not + * call archive_match_exclude_entry(). We cannot know + * what behavior you really expect since overwriting + * condition might be different with the flag. + */ + if (f2 != NULL) { + f2->flag = f->flag; + f2->mtime_sec = f->mtime_sec; + f2->mtime_nsec = f->mtime_nsec; + f2->ctime_sec = f->ctime_sec; + f2->ctime_nsec = f->ctime_nsec; + } + /* Release the duplicated file. */ + archive_mstring_clean(&(f->pathname)); + free(f); + return (ARCHIVE_OK); + } + entry_list_add(&(a->exclusion_entry_list), f); + a->setflag |= TIME_IS_SET; + return (ARCHIVE_OK); +} + +/* + * Test if entry is excluded by its timestamp. + */ +static int +time_excluded(struct archive_match *a, struct archive_entry *entry) +{ + struct match_file *f; + const void *pathname; + time_t sec; + long nsec; + + /* + * If this file/dir is excluded by a time comparison, skip it. + */ + if (a->newer_ctime_filter) { + /* If ctime is not set, use mtime instead. */ + if (archive_entry_ctime_is_set(entry)) + sec = archive_entry_ctime(entry); + else + sec = archive_entry_mtime(entry); + if (sec < a->newer_ctime_sec) + return (1); /* Too old, skip it. */ + if (sec == a->newer_ctime_sec) { + if (archive_entry_ctime_is_set(entry)) + nsec = archive_entry_ctime_nsec(entry); + else + nsec = archive_entry_mtime_nsec(entry); + if (nsec < a->newer_ctime_nsec) + return (1); /* Too old, skip it. */ + if (nsec == a->newer_ctime_nsec && + (a->newer_ctime_filter & ARCHIVE_MATCH_EQUAL) + == 0) + return (1); /* Equal, skip it. */ + } + } + if (a->older_ctime_filter) { + /* If ctime is not set, use mtime instead. */ + if (archive_entry_ctime_is_set(entry)) + sec = archive_entry_ctime(entry); + else + sec = archive_entry_mtime(entry); + if (sec > a->older_ctime_sec) + return (1); /* Too new, skip it. */ + if (sec == a->older_ctime_sec) { + if (archive_entry_ctime_is_set(entry)) + nsec = archive_entry_ctime_nsec(entry); + else + nsec = archive_entry_mtime_nsec(entry); + if (nsec > a->older_ctime_nsec) + return (1); /* Too new, skip it. */ + if (nsec == a->older_ctime_nsec && + (a->older_ctime_filter & ARCHIVE_MATCH_EQUAL) + == 0) + return (1); /* Equal, skip it. */ + } + } + if (a->newer_mtime_filter) { + sec = archive_entry_mtime(entry); + if (sec < a->newer_mtime_sec) + return (1); /* Too old, skip it. */ + if (sec == a->newer_mtime_sec) { + nsec = archive_entry_mtime_nsec(entry); + if (nsec < a->newer_mtime_nsec) + return (1); /* Too old, skip it. */ + if (nsec == a->newer_mtime_nsec && + (a->newer_mtime_filter & ARCHIVE_MATCH_EQUAL) + == 0) + return (1); /* Equal, skip it. */ + } + } + if (a->older_mtime_filter) { + sec = archive_entry_mtime(entry); + if (sec > a->older_mtime_sec) + return (1); /* Too new, skip it. */ + nsec = archive_entry_mtime_nsec(entry); + if (sec == a->older_mtime_sec) { + if (nsec > a->older_mtime_nsec) + return (1); /* Too new, skip it. */ + if (nsec == a->older_mtime_nsec && + (a->older_mtime_filter & ARCHIVE_MATCH_EQUAL) + == 0) + return (1); /* Equal, skip it. */ + } + } + + /* If there is no exclusion list, include the file. */ + if (a->exclusion_entry_list.count == 0) + return (0); + +#if defined(_WIN32) && !defined(__CYGWIN__) + pathname = archive_entry_pathname_w(entry); + a->exclusion_tree.rbt_ops = &rb_ops_wcs; +#else + (void)rb_ops_wcs; + pathname = archive_entry_pathname(entry); + a->exclusion_tree.rbt_ops = &rb_ops_mbs; +#endif + if (pathname == NULL) + return (0); + + f = (struct match_file *)__archive_rb_tree_find_node( + &(a->exclusion_tree), pathname); + /* If the file wasn't rejected, include it. */ + if (f == NULL) + return (0); + + if (f->flag & ARCHIVE_MATCH_CTIME) { + sec = archive_entry_ctime(entry); + if (f->ctime_sec > sec) { + if (f->flag & ARCHIVE_MATCH_OLDER) + return (1); + } else if (f->ctime_sec < sec) { + if (f->flag & ARCHIVE_MATCH_NEWER) + return (1); + } else { + nsec = archive_entry_ctime_nsec(entry); + if (f->ctime_nsec > nsec) { + if (f->flag & ARCHIVE_MATCH_OLDER) + return (1); + } else if (f->ctime_nsec < nsec) { + if (f->flag & ARCHIVE_MATCH_NEWER) + return (1); + } else if (f->flag & ARCHIVE_MATCH_EQUAL) + return (1); + } + } + if (f->flag & ARCHIVE_MATCH_MTIME) { + sec = archive_entry_mtime(entry); + if (f->mtime_sec > sec) { + if (f->flag & ARCHIVE_MATCH_OLDER) + return (1); + } else if (f->mtime_sec < sec) { + if (f->flag & ARCHIVE_MATCH_NEWER) + return (1); + } else { + nsec = archive_entry_mtime_nsec(entry); + if (f->mtime_nsec > nsec) { + if (f->flag & ARCHIVE_MATCH_OLDER) + return (1); + } else if (f->mtime_nsec < nsec) { + if (f->flag & ARCHIVE_MATCH_NEWER) + return (1); + } else if (f->flag & ARCHIVE_MATCH_EQUAL) + return (1); + } + } + return (0); +} + +/* + * Utility functions to manage inclusion owners + */ + +int +archive_match_include_uid(struct archive *_a, la_int64_t uid) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_include_uid"); + a = (struct archive_match *)_a; + return (add_owner_id(a, &(a->inclusion_uids), uid)); +} + +int +archive_match_include_gid(struct archive *_a, la_int64_t gid) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_include_gid"); + a = (struct archive_match *)_a; + return (add_owner_id(a, &(a->inclusion_gids), gid)); +} + +int +archive_match_include_uname(struct archive *_a, const char *uname) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_include_uname"); + a = (struct archive_match *)_a; + return (add_owner_name(a, &(a->inclusion_unames), 1, uname)); +} + +int +archive_match_include_uname_w(struct archive *_a, const wchar_t *uname) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_include_uname_w"); + a = (struct archive_match *)_a; + return (add_owner_name(a, &(a->inclusion_unames), 0, uname)); +} + +int +archive_match_include_gname(struct archive *_a, const char *gname) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_include_gname"); + a = (struct archive_match *)_a; + return (add_owner_name(a, &(a->inclusion_gnames), 1, gname)); +} + +int +archive_match_include_gname_w(struct archive *_a, const wchar_t *gname) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_include_gname_w"); + a = (struct archive_match *)_a; + return (add_owner_name(a, &(a->inclusion_gnames), 0, gname)); +} + +/* + * Test function for owner(uid, gid, uname, gname). + * + * Returns 1 if archive entry is excluded. + * Returns 0 if archive entry is not excluded. + * Returns <0 if something error happened. + */ +int +archive_match_owner_excluded(struct archive *_a, + struct archive_entry *entry) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_id_excluded_ae"); + + a = (struct archive_match *)_a; + if (entry == NULL) { + archive_set_error(&(a->archive), EINVAL, "entry is NULL"); + return (ARCHIVE_FAILED); + } + + /* If we don't have inclusion id set at all, the entry is always + * not excluded. */ + if ((a->setflag & ID_IS_SET) == 0) + return (0); + return (owner_excluded(a, entry)); +} + +static int +add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id) +{ + unsigned i; + + if (ids->count + 1 >= ids->size) { + void *p; + + if (ids->size == 0) + ids->size = 8; + else + ids->size *= 2; + p = realloc(ids->ids, sizeof(*ids->ids) * ids->size); + if (p == NULL) + return (error_nomem(a)); + ids->ids = (int64_t *)p; + } + + /* Find an insert point. */ + for (i = 0; i < ids->count; i++) { + if (ids->ids[i] >= id) + break; + } + + /* Add owner id. */ + if (i == ids->count) + ids->ids[ids->count++] = id; + else if (ids->ids[i] != id) { + memmove(&(ids->ids[i+1]), &(ids->ids[i]), + (ids->count - i) * sizeof(ids->ids[0])); + ids->ids[i] = id; + ids->count++; + } + a->setflag |= ID_IS_SET; + return (ARCHIVE_OK); +} + +static int +match_owner_id(struct id_array *ids, int64_t id) +{ + unsigned b, m, t; + + t = 0; + b = (unsigned)ids->count; + while (t < b) { + m = (t + b)>>1; + if (ids->ids[m] == id) + return (1); + if (ids->ids[m] < id) + t = m + 1; + else + b = m; + } + return (0); +} + +static int +add_owner_name(struct archive_match *a, struct match_list *list, + int mbs, const void *name) +{ + struct match *match; + + match = calloc(1, sizeof(*match)); + if (match == NULL) + return (error_nomem(a)); + if (mbs) + archive_mstring_copy_mbs(&(match->pattern), name); + else + archive_mstring_copy_wcs(&(match->pattern), name); + match_list_add(list, match); + a->setflag |= ID_IS_SET; + return (ARCHIVE_OK); +} + +#if !defined(_WIN32) || defined(__CYGWIN__) +static int +match_owner_name_mbs(struct archive_match *a, struct match_list *list, + const char *name) +{ + struct match *m; + const char *p; + + if (name == NULL || *name == '\0') + return (0); + for (m = list->first; m; m = m->next) { + if (archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p) + < 0 && errno == ENOMEM) + return (error_nomem(a)); + if (p != NULL && strcmp(p, name) == 0) { + m->matches++; + return (1); + } + } + return (0); +} +#else +static int +match_owner_name_wcs(struct archive_match *a, struct match_list *list, + const wchar_t *name) +{ + struct match *m; + const wchar_t *p; + + if (name == NULL || *name == L'\0') + return (0); + for (m = list->first; m; m = m->next) { + if (archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p) + < 0 && errno == ENOMEM) + return (error_nomem(a)); + if (p != NULL && wcscmp(p, name) == 0) { + m->matches++; + return (1); + } + } + return (0); +} +#endif + +/* + * Test if entry is excluded by uid, gid, uname or gname. + */ +static int +owner_excluded(struct archive_match *a, struct archive_entry *entry) +{ + int r; + + if (a->inclusion_uids.count) { + if (!match_owner_id(&(a->inclusion_uids), + archive_entry_uid(entry))) + return (1); + } + + if (a->inclusion_gids.count) { + if (!match_owner_id(&(a->inclusion_gids), + archive_entry_gid(entry))) + return (1); + } + + if (a->inclusion_unames.count) { +#if defined(_WIN32) && !defined(__CYGWIN__) + r = match_owner_name_wcs(a, &(a->inclusion_unames), + archive_entry_uname_w(entry)); +#else + r = match_owner_name_mbs(a, &(a->inclusion_unames), + archive_entry_uname(entry)); +#endif + if (!r) + return (1); + else if (r < 0) + return (r); + } + + if (a->inclusion_gnames.count) { +#if defined(_WIN32) && !defined(__CYGWIN__) + r = match_owner_name_wcs(a, &(a->inclusion_gnames), + archive_entry_gname_w(entry)); +#else + r = match_owner_name_mbs(a, &(a->inclusion_gnames), + archive_entry_gname(entry)); +#endif + if (!r) + return (1); + else if (r < 0) + return (r); + } + return (0); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_openssl_evp_private.h b/dependencies/libarchive-3.4.2/libarchive/archive_openssl_evp_private.h new file mode 100644 index 0000000..ebb0670 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_openssl_evp_private.h @@ -0,0 +1,53 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ARCHIVE_OPENSSL_EVP_PRIVATE_H_INCLUDED +#define ARCHIVE_OPENSSL_EVP_PRIVATE_H_INCLUDED + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif + +#include +#include + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#include /* malloc, free */ +#include /* memset */ +static inline EVP_MD_CTX *EVP_MD_CTX_new(void) +{ + EVP_MD_CTX *ctx = (EVP_MD_CTX *)calloc(1, sizeof(EVP_MD_CTX)); + return ctx; +} + +static inline void EVP_MD_CTX_free(EVP_MD_CTX *ctx) +{ + EVP_MD_CTX_cleanup(ctx); + memset(ctx, 0, sizeof(*ctx)); + free(ctx); +} +#endif + +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_openssl_hmac_private.h b/dependencies/libarchive-3.4.2/libarchive/archive_openssl_hmac_private.h new file mode 100644 index 0000000..25c8dda --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_openssl_hmac_private.h @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ARCHIVE_OPENSSL_HMAC_PRIVATE_H_INCLUDED +#define ARCHIVE_OPENSSL_HMAC_PRIVATE_H_INCLUDED + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif + +#include +#include + +#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ + (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L) +#include /* malloc, free */ +#include /* memset */ +static inline HMAC_CTX *HMAC_CTX_new(void) +{ + HMAC_CTX *ctx = (HMAC_CTX *)calloc(1, sizeof(HMAC_CTX)); + return ctx; +} + +static inline void HMAC_CTX_free(HMAC_CTX *ctx) +{ + HMAC_CTX_cleanup(ctx); + memset(ctx, 0, sizeof(*ctx)); + free(ctx); +} +#endif + +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_options.c b/dependencies/libarchive-3.4.2/libarchive/archive_options.c new file mode 100644 index 0000000..6496025 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_options.c @@ -0,0 +1,218 @@ +/*- + * Copyright (c) 2011 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif + +#include "archive_options_private.h" + +static const char * +parse_option(const char **str, + const char **mod, const char **opt, const char **val); + +int +_archive_set_option(struct archive *a, + const char *m, const char *o, const char *v, + int magic, const char *fn, option_handler use_option) +{ + const char *mp, *op, *vp; + int r; + + archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn); + + mp = (m != NULL && m[0] != '\0') ? m : NULL; + op = (o != NULL && o[0] != '\0') ? o : NULL; + vp = (v != NULL && v[0] != '\0') ? v : NULL; + + if (op == NULL && vp == NULL) + return (ARCHIVE_OK); + if (op == NULL) { + archive_set_error(a, ARCHIVE_ERRNO_MISC, "Empty option"); + return (ARCHIVE_FAILED); + } + + r = use_option(a, mp, op, vp); + if (r == ARCHIVE_WARN - 1) { + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unknown module name: `%s'", mp); + return (ARCHIVE_FAILED); + } + if (r == ARCHIVE_WARN) { + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Undefined option: `%s%s%s%s%s%s'", + vp?"":"!", mp?mp:"", mp?":":"", op, vp?"=":"", vp?vp:""); + return (ARCHIVE_FAILED); + } + return (r); +} + +int +_archive_set_either_option(struct archive *a, const char *m, const char *o, const char *v, + option_handler use_format_option, option_handler use_filter_option) +{ + int r1, r2; + + if (o == NULL && v == NULL) + return (ARCHIVE_OK); + if (o == NULL) + return (ARCHIVE_FAILED); + + r1 = use_format_option(a, m, o, v); + if (r1 == ARCHIVE_FATAL) + return (ARCHIVE_FATAL); + + r2 = use_filter_option(a, m, o, v); + if (r2 == ARCHIVE_FATAL) + return (ARCHIVE_FATAL); + + if (r2 == ARCHIVE_WARN - 1) + return r1; + return r1 > r2 ? r1 : r2; +} + +int +_archive_set_options(struct archive *a, const char *options, + int magic, const char *fn, option_handler use_option) +{ + int allok = 1, anyok = 0, ignore_mod_err = 0, r; + char *data; + const char *s, *mod, *opt, *val; + + archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn); + + if (options == NULL || options[0] == '\0') + return ARCHIVE_OK; + + if ((data = strdup(options)) == NULL) { + archive_set_error(a, + ENOMEM, "Out of memory adding file to list"); + return (ARCHIVE_FATAL); + } + s = (const char *)data; + + do { + mod = opt = val = NULL; + + parse_option(&s, &mod, &opt, &val); + if (mod == NULL && opt != NULL && + strcmp("__ignore_wrong_module_name__", opt) == 0) { + /* Ignore module name error */ + if (val != NULL) { + ignore_mod_err = 1; + anyok = 1; + } + continue; + } + + r = use_option(a, mod, opt, val); + if (r == ARCHIVE_FATAL) { + free(data); + return (ARCHIVE_FATAL); + } + if (r == ARCHIVE_FAILED && mod != NULL) { + free(data); + return (ARCHIVE_FAILED); + } + if (r == ARCHIVE_WARN - 1) { + if (ignore_mod_err) + continue; + /* The module name is wrong. */ + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unknown module name: `%s'", mod); + free(data); + return (ARCHIVE_FAILED); + } + if (r == ARCHIVE_WARN) { + /* The option name is wrong. No-one used this. */ + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Undefined option: `%s%s%s'", + mod?mod:"", mod?":":"", opt); + free(data); + return (ARCHIVE_FAILED); + } + if (r == ARCHIVE_OK) + anyok = 1; + else + allok = 0; + } while (s != NULL); + + free(data); + return allok ? ARCHIVE_OK : anyok ? ARCHIVE_WARN : ARCHIVE_FAILED; +} + +static const char * +parse_option(const char **s, const char **m, const char **o, const char **v) +{ + const char *end, *mod, *opt, *val; + char *p; + + end = NULL; + mod = NULL; + opt = *s; + val = "1"; + + p = strchr(opt, ','); + + if (p != NULL) { + *p = '\0'; + end = ((const char *)p) + 1; + } + + if (0 == strlen(opt)) { + *s = end; + *m = NULL; + *o = NULL; + *v = NULL; + return end; + } + + p = strchr(opt, ':'); + if (p != NULL) { + *p = '\0'; + mod = opt; + opt = ++p; + } + + p = strchr(opt, '='); + if (p != NULL) { + *p = '\0'; + val = ++p; + } else if (opt[0] == '!') { + ++opt; + val = NULL; + } + + *s = end; + *m = mod; + *o = opt; + *v = val; + + return end; +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_options_private.h b/dependencies/libarchive-3.4.2/libarchive/archive_options_private.h new file mode 100644 index 0000000..9a7f808 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_options_private.h @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2011 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ARCHIVE_OPTIONS_PRIVATE_H_INCLUDED +#define ARCHIVE_OPTIONS_PRIVATE_H_INCLUDED + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#include "archive_private.h" + +typedef int (*option_handler)(struct archive *a, + const char *mod, const char *opt, const char *val); + +int +_archive_set_option(struct archive *a, + const char *mod, const char *opt, const char *val, + int magic, const char *fn, option_handler use_option); + +int +_archive_set_options(struct archive *a, const char *options, + int magic, const char *fn, option_handler use_option); + +int +_archive_set_either_option(struct archive *a, + const char *m, const char *o, const char *v, + option_handler use_format_option, option_handler use_filter_option); + +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_pack_dev.c b/dependencies/libarchive-3.4.2/libarchive/archive_pack_dev.c new file mode 100644 index 0000000..f8286d8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_pack_dev.c @@ -0,0 +1,336 @@ +/* $NetBSD: pack_dev.c,v 1.12 2013/06/14 16:28:20 tsutsui Exp $ */ + +/*- + * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Originally from NetBSD's mknod(8) source. */ + +#include "archive_platform.h" + +#if HAVE_SYS_CDEFS_H +#include +#endif +#if !defined(lint) +__RCSID("$NetBSD$"); +#endif /* not lint */ + +#ifdef HAVE_LIMITS_H +#include +#endif + +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#if MAJOR_IN_MKDEV +#include +#define HAVE_MAJOR +#elif MAJOR_IN_SYSMACROS +#include +#define HAVE_MAJOR +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "archive_pack_dev.h" + +static pack_t pack_netbsd; +static pack_t pack_freebsd; +static pack_t pack_8_8; +static pack_t pack_12_20; +static pack_t pack_14_18; +static pack_t pack_8_24; +static pack_t pack_bsdos; +static int compare_format(const void *, const void *); + +static const char iMajorError[] = "invalid major number"; +static const char iMinorError[] = "invalid minor number"; +static const char tooManyFields[] = "too many fields for format"; + +/* This is blatantly stolen from libarchive/archive_entry.c, + * in an attempt to get this to play nice on MinGW... */ +#if !defined(HAVE_MAJOR) && !defined(major) +/* Replacement for major/minor/makedev. */ +#define major(x) ((int)(0x00ff & ((x) >> 8))) +#define minor(x) ((int)(0xffff00ff & (x))) +#define makedev(maj,min) ((0xff00 & ((maj)<<8)) | (0xffff00ff & (min))) +#endif + +/* Play games to come up with a suitable makedev() definition. */ +#ifdef __QNXNTO__ +/* QNX. */ +#include +#define apd_makedev(maj, min) makedev(ND_LOCAL_NODE, (maj), (min)) +#elif defined makedev +/* There's a "makedev" macro. */ +#define apd_makedev(maj, min) makedev((maj), (min)) +#elif defined mkdev || ((defined _WIN32 || defined __WIN32__) && !defined(__CYGWIN__)) +/* Windows. */ +#define apd_makedev(maj, min) mkdev((maj), (min)) +#else +/* There's a "makedev" function. */ +#define apd_makedev(maj, min) makedev((maj), (min)) +#endif + +/* exported */ +dev_t +pack_native(int n, unsigned long numbers[], const char **error) +{ + dev_t dev = 0; + + if (n == 2) { + dev = apd_makedev(numbers[0], numbers[1]); + if ((unsigned long)major(dev) != numbers[0]) + *error = iMajorError; + else if ((unsigned long)minor(dev) != numbers[1]) + *error = iMinorError; + } else + *error = tooManyFields; + return (dev); +} + + +static dev_t +pack_netbsd(int n, unsigned long numbers[], const char **error) +{ + dev_t dev = 0; + + if (n == 2) { + dev = makedev_netbsd(numbers[0], numbers[1]); + if ((unsigned long)major_netbsd(dev) != numbers[0]) + *error = iMajorError; + else if ((unsigned long)minor_netbsd(dev) != numbers[1]) + *error = iMinorError; + } else + *error = tooManyFields; + return (dev); +} + + +#define major_freebsd(x) ((int32_t)(((x) & 0x0000ff00) >> 8)) +#define minor_freebsd(x) ((int32_t)(((x) & 0xffff00ff) >> 0)) +#define makedev_freebsd(x,y) ((dev_t)((((x) << 8) & 0x0000ff00) | \ + (((y) << 0) & 0xffff00ff))) + +static dev_t +pack_freebsd(int n, unsigned long numbers[], const char **error) +{ + dev_t dev = 0; + + if (n == 2) { + dev = makedev_freebsd(numbers[0], numbers[1]); + if ((unsigned long)major_freebsd(dev) != numbers[0]) + *error = iMajorError; + if ((unsigned long)minor_freebsd(dev) != numbers[1]) + *error = iMinorError; + } else + *error = tooManyFields; + return (dev); +} + + +#define major_8_8(x) ((int32_t)(((x) & 0x0000ff00) >> 8)) +#define minor_8_8(x) ((int32_t)(((x) & 0x000000ff) >> 0)) +#define makedev_8_8(x,y) ((dev_t)((((x) << 8) & 0x0000ff00) | \ + (((y) << 0) & 0x000000ff))) + +static dev_t +pack_8_8(int n, unsigned long numbers[], const char **error) +{ + dev_t dev = 0; + + if (n == 2) { + dev = makedev_8_8(numbers[0], numbers[1]); + if ((unsigned long)major_8_8(dev) != numbers[0]) + *error = iMajorError; + if ((unsigned long)minor_8_8(dev) != numbers[1]) + *error = iMinorError; + } else + *error = tooManyFields; + return (dev); +} + + +#define major_12_20(x) ((int32_t)(((x) & 0xfff00000) >> 20)) +#define minor_12_20(x) ((int32_t)(((x) & 0x000fffff) >> 0)) +#define makedev_12_20(x,y) ((dev_t)((((x) << 20) & 0xfff00000) | \ + (((y) << 0) & 0x000fffff))) + +static dev_t +pack_12_20(int n, unsigned long numbers[], const char **error) +{ + dev_t dev = 0; + + if (n == 2) { + dev = makedev_12_20(numbers[0], numbers[1]); + if ((unsigned long)major_12_20(dev) != numbers[0]) + *error = iMajorError; + if ((unsigned long)minor_12_20(dev) != numbers[1]) + *error = iMinorError; + } else + *error = tooManyFields; + return (dev); +} + + +#define major_14_18(x) ((int32_t)(((x) & 0xfffc0000) >> 18)) +#define minor_14_18(x) ((int32_t)(((x) & 0x0003ffff) >> 0)) +#define makedev_14_18(x,y) ((dev_t)((((x) << 18) & 0xfffc0000) | \ + (((y) << 0) & 0x0003ffff))) + +static dev_t +pack_14_18(int n, unsigned long numbers[], const char **error) +{ + dev_t dev = 0; + + if (n == 2) { + dev = makedev_14_18(numbers[0], numbers[1]); + if ((unsigned long)major_14_18(dev) != numbers[0]) + *error = iMajorError; + if ((unsigned long)minor_14_18(dev) != numbers[1]) + *error = iMinorError; + } else + *error = tooManyFields; + return (dev); +} + + +#define major_8_24(x) ((int32_t)(((x) & 0xff000000) >> 24)) +#define minor_8_24(x) ((int32_t)(((x) & 0x00ffffff) >> 0)) +#define makedev_8_24(x,y) ((dev_t)((((x) << 24) & 0xff000000) | \ + (((y) << 0) & 0x00ffffff))) + +static dev_t +pack_8_24(int n, unsigned long numbers[], const char **error) +{ + dev_t dev = 0; + + if (n == 2) { + dev = makedev_8_24(numbers[0], numbers[1]); + if ((unsigned long)major_8_24(dev) != numbers[0]) + *error = iMajorError; + if ((unsigned long)minor_8_24(dev) != numbers[1]) + *error = iMinorError; + } else + *error = tooManyFields; + return (dev); +} + + +#define major_12_12_8(x) ((int32_t)(((x) & 0xfff00000) >> 20)) +#define unit_12_12_8(x) ((int32_t)(((x) & 0x000fff00) >> 8)) +#define subunit_12_12_8(x) ((int32_t)(((x) & 0x000000ff) >> 0)) +#define makedev_12_12_8(x,y,z) ((dev_t)((((x) << 20) & 0xfff00000) | \ + (((y) << 8) & 0x000fff00) | \ + (((z) << 0) & 0x000000ff))) + +static dev_t +pack_bsdos(int n, unsigned long numbers[], const char **error) +{ + dev_t dev = 0; + + if (n == 2) { + dev = makedev_12_20(numbers[0], numbers[1]); + if ((unsigned long)major_12_20(dev) != numbers[0]) + *error = iMajorError; + if ((unsigned long)minor_12_20(dev) != numbers[1]) + *error = iMinorError; + } else if (n == 3) { + dev = makedev_12_12_8(numbers[0], numbers[1], numbers[2]); + if ((unsigned long)major_12_12_8(dev) != numbers[0]) + *error = iMajorError; + if ((unsigned long)unit_12_12_8(dev) != numbers[1]) + *error = "invalid unit number"; + if ((unsigned long)subunit_12_12_8(dev) != numbers[2]) + *error = "invalid subunit number"; + } else + *error = tooManyFields; + return (dev); +} + + + /* list of formats and pack functions */ + /* this list must be sorted lexically */ +static const struct format { + const char *name; + pack_t *pack; +} formats[] = { + {"386bsd", pack_8_8}, + {"4bsd", pack_8_8}, + {"bsdos", pack_bsdos}, + {"freebsd", pack_freebsd}, + {"hpux", pack_8_24}, + {"isc", pack_8_8}, + {"linux", pack_8_8}, + {"native", pack_native}, + {"netbsd", pack_netbsd}, + {"osf1", pack_12_20}, + {"sco", pack_8_8}, + {"solaris", pack_14_18}, + {"sunos", pack_8_8}, + {"svr3", pack_8_8}, + {"svr4", pack_14_18}, + {"ultrix", pack_8_8}, +}; + +static int +compare_format(const void *key, const void *element) +{ + const char *name; + const struct format *format; + + name = key; + format = element; + + return (strcmp(name, format->name)); +} + + +pack_t * +pack_find(const char *name) +{ + struct format *format; + + format = bsearch(name, formats, + sizeof(formats)/sizeof(formats[0]), + sizeof(formats[0]), compare_format); + if (format == 0) + return (NULL); + return (format->pack); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_pack_dev.h b/dependencies/libarchive-3.4.2/libarchive/archive_pack_dev.h new file mode 100644 index 0000000..eaf23e3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_pack_dev.h @@ -0,0 +1,49 @@ +/* $NetBSD: pack_dev.h,v 1.8 2013/06/14 16:28:20 tsutsui Exp $ */ + +/*- + * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Originally from NetBSD's mknod(8) source. */ + +#ifndef ARCHIVE_PACK_DEV_H +#define ARCHIVE_PACK_DEV_H + +typedef dev_t pack_t(int, unsigned long [], const char **); + +pack_t *pack_find(const char *); +pack_t pack_native; + +#define major_netbsd(x) ((int32_t)((((x) & 0x000fff00) >> 8))) +#define minor_netbsd(x) ((int32_t)((((x) & 0xfff00000) >> 12) | \ + (((x) & 0x000000ff) >> 0))) +#define makedev_netbsd(x,y) ((dev_t)((((x) << 8) & 0x000fff00) | \ + (((y) << 12) & 0xfff00000) | \ + (((y) << 0) & 0x000000ff))) + +#endif /* ARCHIVE_PACK_DEV_H */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_pathmatch.c b/dependencies/libarchive-3.4.2/libarchive/archive_pathmatch.c new file mode 100644 index 0000000..619e2b6 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_pathmatch.c @@ -0,0 +1,459 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_WCHAR_H +#include +#endif + +#include "archive_pathmatch.h" + +/* + * Check whether a character 'c' is matched by a list specification [...]: + * * Leading '!' or '^' negates the class. + * * - is a range of characters + * * \ removes any special meaning for + * + * Some interesting boundary cases: + * a-d-e is one range (a-d) followed by two single characters - and e. + * \a-\d is same as a-d + * a\-d is three single characters: a, d, - + * Trailing - is not special (so [a-] is two characters a and -). + * Initial - is not special ([a-] is same as [-a] is same as [\\-a]) + * This function never sees a trailing \. + * [] always fails + * [!] always succeeds + */ +static int +pm_list(const char *start, const char *end, const char c, int flags) +{ + const char *p = start; + char rangeStart = '\0', nextRangeStart; + int match = 1, nomatch = 0; + + /* This will be used soon... */ + (void)flags; /* UNUSED */ + + /* If this is a negated class, return success for nomatch. */ + if ((*p == '!' || *p == '^') && p < end) { + match = 0; + nomatch = 1; + ++p; + } + + while (p < end) { + nextRangeStart = '\0'; + switch (*p) { + case '-': + /* Trailing or initial '-' is not special. */ + if ((rangeStart == '\0') || (p == end - 1)) { + if (*p == c) + return (match); + } else { + char rangeEnd = *++p; + if (rangeEnd == '\\') + rangeEnd = *++p; + if ((rangeStart <= c) && (c <= rangeEnd)) + return (match); + } + break; + case '\\': + ++p; + /* Fall through */ + default: + if (*p == c) + return (match); + nextRangeStart = *p; /* Possible start of range. */ + } + rangeStart = nextRangeStart; + ++p; + } + return (nomatch); +} + +static int +pm_list_w(const wchar_t *start, const wchar_t *end, const wchar_t c, int flags) +{ + const wchar_t *p = start; + wchar_t rangeStart = L'\0', nextRangeStart; + int match = 1, nomatch = 0; + + /* This will be used soon... */ + (void)flags; /* UNUSED */ + + /* If this is a negated class, return success for nomatch. */ + if ((*p == L'!' || *p == L'^') && p < end) { + match = 0; + nomatch = 1; + ++p; + } + + while (p < end) { + nextRangeStart = L'\0'; + switch (*p) { + case L'-': + /* Trailing or initial '-' is not special. */ + if ((rangeStart == L'\0') || (p == end - 1)) { + if (*p == c) + return (match); + } else { + wchar_t rangeEnd = *++p; + if (rangeEnd == L'\\') + rangeEnd = *++p; + if ((rangeStart <= c) && (c <= rangeEnd)) + return (match); + } + break; + case L'\\': + ++p; + /* Fall through */ + default: + if (*p == c) + return (match); + nextRangeStart = *p; /* Possible start of range. */ + } + rangeStart = nextRangeStart; + ++p; + } + return (nomatch); +} + +/* + * If s is pointing to "./", ".//", "./././" or the like, skip it. + */ +static const char * +pm_slashskip(const char *s) { + while ((*s == '/') + || (s[0] == '.' && s[1] == '/') + || (s[0] == '.' && s[1] == '\0')) + ++s; + return (s); +} + +static const wchar_t * +pm_slashskip_w(const wchar_t *s) { + while ((*s == L'/') + || (s[0] == L'.' && s[1] == L'/') + || (s[0] == L'.' && s[1] == L'\0')) + ++s; + return (s); +} + +static int +pm(const char *p, const char *s, int flags) +{ + const char *end; + + /* + * Ignore leading './', './/', '././', etc. + */ + if (s[0] == '.' && s[1] == '/') + s = pm_slashskip(s + 1); + if (p[0] == '.' && p[1] == '/') + p = pm_slashskip(p + 1); + + for (;;) { + switch (*p) { + case '\0': + if (s[0] == '/') { + if (flags & PATHMATCH_NO_ANCHOR_END) + return (1); + /* "dir" == "dir/" == "dir/." */ + s = pm_slashskip(s); + } + return (*s == '\0'); + case '?': + /* ? always succeeds, unless we hit end of 's' */ + if (*s == '\0') + return (0); + break; + case '*': + /* "*" == "**" == "***" ... */ + while (*p == '*') + ++p; + /* Trailing '*' always succeeds. */ + if (*p == '\0') + return (1); + while (*s) { + if (archive_pathmatch(p, s, flags)) + return (1); + ++s; + } + return (0); + case '[': + /* + * Find the end of the [...] character class, + * ignoring \] that might occur within the class. + */ + end = p + 1; + while (*end != '\0' && *end != ']') { + if (*end == '\\' && end[1] != '\0') + ++end; + ++end; + } + if (*end == ']') { + /* We found [...], try to match it. */ + if (!pm_list(p + 1, end, *s, flags)) + return (0); + p = end; /* Jump to trailing ']' char. */ + break; + } else + /* No final ']', so just match '['. */ + if (*p != *s) + return (0); + break; + case '\\': + /* Trailing '\\' matches itself. */ + if (p[1] == '\0') { + if (*s != '\\') + return (0); + } else { + ++p; + if (*p != *s) + return (0); + } + break; + case '/': + if (*s != '/' && *s != '\0') + return (0); + /* Note: pattern "/\./" won't match "/"; + * pm_slashskip() correctly stops at backslash. */ + p = pm_slashskip(p); + s = pm_slashskip(s); + if (*p == '\0' && (flags & PATHMATCH_NO_ANCHOR_END)) + return (1); + --p; /* Counteract the increment below. */ + --s; + break; + case '$': + /* '$' is special only at end of pattern and only + * if PATHMATCH_NO_ANCHOR_END is specified. */ + if (p[1] == '\0' && (flags & PATHMATCH_NO_ANCHOR_END)){ + /* "dir" == "dir/" == "dir/." */ + return (*pm_slashskip(s) == '\0'); + } + /* Otherwise, '$' is not special. */ + /* FALL THROUGH */ + default: + if (*p != *s) + return (0); + break; + } + ++p; + ++s; + } +} + +static int +pm_w(const wchar_t *p, const wchar_t *s, int flags) +{ + const wchar_t *end; + + /* + * Ignore leading './', './/', '././', etc. + */ + if (s[0] == L'.' && s[1] == L'/') + s = pm_slashskip_w(s + 1); + if (p[0] == L'.' && p[1] == L'/') + p = pm_slashskip_w(p + 1); + + for (;;) { + switch (*p) { + case L'\0': + if (s[0] == L'/') { + if (flags & PATHMATCH_NO_ANCHOR_END) + return (1); + /* "dir" == "dir/" == "dir/." */ + s = pm_slashskip_w(s); + } + return (*s == L'\0'); + case L'?': + /* ? always succeeds, unless we hit end of 's' */ + if (*s == L'\0') + return (0); + break; + case L'*': + /* "*" == "**" == "***" ... */ + while (*p == L'*') + ++p; + /* Trailing '*' always succeeds. */ + if (*p == L'\0') + return (1); + while (*s) { + if (archive_pathmatch_w(p, s, flags)) + return (1); + ++s; + } + return (0); + case L'[': + /* + * Find the end of the [...] character class, + * ignoring \] that might occur within the class. + */ + end = p + 1; + while (*end != L'\0' && *end != L']') { + if (*end == L'\\' && end[1] != L'\0') + ++end; + ++end; + } + if (*end == L']') { + /* We found [...], try to match it. */ + if (!pm_list_w(p + 1, end, *s, flags)) + return (0); + p = end; /* Jump to trailing ']' char. */ + break; + } else + /* No final ']', so just match '['. */ + if (*p != *s) + return (0); + break; + case L'\\': + /* Trailing '\\' matches itself. */ + if (p[1] == L'\0') { + if (*s != L'\\') + return (0); + } else { + ++p; + if (*p != *s) + return (0); + } + break; + case L'/': + if (*s != L'/' && *s != L'\0') + return (0); + /* Note: pattern "/\./" won't match "/"; + * pm_slashskip() correctly stops at backslash. */ + p = pm_slashskip_w(p); + s = pm_slashskip_w(s); + if (*p == L'\0' && (flags & PATHMATCH_NO_ANCHOR_END)) + return (1); + --p; /* Counteract the increment below. */ + --s; + break; + case L'$': + /* '$' is special only at end of pattern and only + * if PATHMATCH_NO_ANCHOR_END is specified. */ + if (p[1] == L'\0' && (flags & PATHMATCH_NO_ANCHOR_END)){ + /* "dir" == "dir/" == "dir/." */ + return (*pm_slashskip_w(s) == L'\0'); + } + /* Otherwise, '$' is not special. */ + /* FALL THROUGH */ + default: + if (*p != *s) + return (0); + break; + } + ++p; + ++s; + } +} + +/* Main entry point. */ +int +__archive_pathmatch(const char *p, const char *s, int flags) +{ + /* Empty pattern only matches the empty string. */ + if (p == NULL || *p == '\0') + return (s == NULL || *s == '\0'); + + /* Leading '^' anchors the start of the pattern. */ + if (*p == '^') { + ++p; + flags &= ~PATHMATCH_NO_ANCHOR_START; + } + + if (*p == '/' && *s != '/') + return (0); + + /* Certain patterns anchor implicitly. */ + if (*p == '*' || *p == '/') { + while (*p == '/') + ++p; + while (*s == '/') + ++s; + return (pm(p, s, flags)); + } + + /* If start is unanchored, try to match start of each path element. */ + if (flags & PATHMATCH_NO_ANCHOR_START) { + for ( ; s != NULL; s = strchr(s, '/')) { + if (*s == '/') + s++; + if (pm(p, s, flags)) + return (1); + } + return (0); + } + + /* Default: Match from beginning. */ + return (pm(p, s, flags)); +} + +int +__archive_pathmatch_w(const wchar_t *p, const wchar_t *s, int flags) +{ + /* Empty pattern only matches the empty string. */ + if (p == NULL || *p == L'\0') + return (s == NULL || *s == L'\0'); + + /* Leading '^' anchors the start of the pattern. */ + if (*p == L'^') { + ++p; + flags &= ~PATHMATCH_NO_ANCHOR_START; + } + + if (*p == L'/' && *s != L'/') + return (0); + + /* Certain patterns anchor implicitly. */ + if (*p == L'*' || *p == L'/') { + while (*p == L'/') + ++p; + while (*s == L'/') + ++s; + return (pm_w(p, s, flags)); + } + + /* If start is unanchored, try to match start of each path element. */ + if (flags & PATHMATCH_NO_ANCHOR_START) { + for ( ; s != NULL; s = wcschr(s, L'/')) { + if (*s == L'/') + s++; + if (pm_w(p, s, flags)) + return (1); + } + return (0); + } + + /* Default: Match from beginning. */ + return (pm_w(p, s, flags)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_pathmatch.h b/dependencies/libarchive-3.4.2/libarchive/archive_pathmatch.h new file mode 100644 index 0000000..9995142 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_pathmatch.h @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef ARCHIVE_PATHMATCH_H +#define ARCHIVE_PATHMATCH_H + +#ifndef __LIBARCHIVE_BUILD +#ifndef __LIBARCHIVE_TEST +#error This header is only to be used internally to libarchive. +#endif +#endif + +/* Don't anchor at beginning unless the pattern starts with "^" */ +#define PATHMATCH_NO_ANCHOR_START 1 +/* Don't anchor at end unless the pattern ends with "$" */ +#define PATHMATCH_NO_ANCHOR_END 2 + +/* Note that "^" and "$" are not special unless you set the corresponding + * flag above. */ + +int __archive_pathmatch(const char *p, const char *s, int flags); +int __archive_pathmatch_w(const wchar_t *p, const wchar_t *s, int flags); + +#define archive_pathmatch(p, s, f) __archive_pathmatch(p, s, f) +#define archive_pathmatch_w(p, s, f) __archive_pathmatch_w(p, s, f) + +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_platform.h b/dependencies/libarchive-3.4.2/libarchive/archive_platform.h new file mode 100644 index 0000000..b8bcb52 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_platform.h @@ -0,0 +1,202 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: head/lib/libarchive/archive_platform.h 201090 2009-12-28 02:22:04Z kientzle $ + */ + +/* !!ONLY FOR USE INTERNALLY TO LIBARCHIVE!! */ + +/* + * This header is the first thing included in any of the libarchive + * source files. As far as possible, platform-specific issues should + * be dealt with here and not within individual source files. I'm + * actively trying to minimize #if blocks within the main source, + * since they obfuscate the code. + */ + +#ifndef ARCHIVE_PLATFORM_H_INCLUDED +#define ARCHIVE_PLATFORM_H_INCLUDED + +/* archive.h and archive_entry.h require this. */ +#define __LIBARCHIVE_BUILD 1 + +#if defined(PLATFORM_CONFIG_H) +/* Use hand-built config.h in environments that need it. */ +#include PLATFORM_CONFIG_H +#elif defined(HAVE_CONFIG_H) +/* Most POSIX platforms use the 'configure' script to build config.h */ +#include "config.h" +#else +/* Warn if the library hasn't been (automatically or manually) configured. */ +#error Oops: No config.h and no pre-built configuration in archive_platform.h. +#endif + +/* On macOS check for some symbols based on the deployment target version. */ +#if defined(__APPLE__) +# undef HAVE_FUTIMENS +# undef HAVE_UTIMENSAT +# include +# if MAC_OS_X_VERSION_MIN_REQUIRED >= 101300 +# define HAVE_FUTIMENS 1 +# define HAVE_UTIMENSAT 1 +# endif +#endif + +/* It should be possible to get rid of this by extending the feature-test + * macros to cover Windows API functions, probably along with non-trivial + * refactoring of code to find structures that sit more cleanly on top of + * either Windows or Posix APIs. */ +#if (defined(__WIN32__) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__) +#include "archive_windows.h" +#else +#define la_stat(path,stref) stat(path,stref) +#endif + +/* + * The config files define a lot of feature macros. The following + * uses those macros to select/define replacements and include key + * headers as required. + */ + +/* Get a real definition for __FBSDID or __RCSID if we can */ +#if HAVE_SYS_CDEFS_H +#include +#endif + +/* If not, define them so as to avoid dangling semicolons. */ +#ifndef __FBSDID +#define __FBSDID(a) struct _undefined_hack +#endif +#ifndef __RCSID +#define __RCSID(a) struct _undefined_hack +#endif + +/* Try to get standard C99-style integer type definitions. */ +#if HAVE_INTTYPES_H +#include +#endif +#if HAVE_STDINT_H +#include +#endif + +/* Borland warns about its own constants! */ +#if defined(__BORLANDC__) +# if HAVE_DECL_UINT64_MAX +# undef UINT64_MAX +# undef HAVE_DECL_UINT64_MAX +# endif +# if HAVE_DECL_UINT64_MIN +# undef UINT64_MIN +# undef HAVE_DECL_UINT64_MIN +# endif +# if HAVE_DECL_INT64_MAX +# undef INT64_MAX +# undef HAVE_DECL_INT64_MAX +# endif +# if HAVE_DECL_INT64_MIN +# undef INT64_MIN +# undef HAVE_DECL_INT64_MIN +# endif +#endif + +/* Some platforms lack the standard *_MAX definitions. */ +#if !HAVE_DECL_SIZE_MAX +#define SIZE_MAX (~(size_t)0) +#endif +#if !HAVE_DECL_SSIZE_MAX +#define SSIZE_MAX ((ssize_t)(SIZE_MAX >> 1)) +#endif +#if !HAVE_DECL_UINT32_MAX +#define UINT32_MAX (~(uint32_t)0) +#endif +#if !HAVE_DECL_INT32_MAX +#define INT32_MAX ((int32_t)(UINT32_MAX >> 1)) +#endif +#if !HAVE_DECL_INT32_MIN +#define INT32_MIN ((int32_t)(~INT32_MAX)) +#endif +#if !HAVE_DECL_UINT64_MAX +#define UINT64_MAX (~(uint64_t)0) +#endif +#if !HAVE_DECL_INT64_MAX +#define INT64_MAX ((int64_t)(UINT64_MAX >> 1)) +#endif +#if !HAVE_DECL_INT64_MIN +#define INT64_MIN ((int64_t)(~INT64_MAX)) +#endif +#if !HAVE_DECL_UINTMAX_MAX +#define UINTMAX_MAX (~(uintmax_t)0) +#endif +#if !HAVE_DECL_INTMAX_MAX +#define INTMAX_MAX ((intmax_t)(UINTMAX_MAX >> 1)) +#endif +#if !HAVE_DECL_INTMAX_MIN +#define INTMAX_MIN ((intmax_t)(~INTMAX_MAX)) +#endif + +/* + * If we can't restore metadata using a file descriptor, then + * for compatibility's sake, close files before trying to restore metadata. + */ +#if defined(HAVE_FCHMOD) || defined(HAVE_FUTIMES) || defined(HAVE_ACL_SET_FD) || defined(HAVE_ACL_SET_FD_NP) || defined(HAVE_FCHOWN) +#define CAN_RESTORE_METADATA_FD +#endif + +/* + * glibc 2.24 deprecates readdir_r + */ +#if defined(HAVE_READDIR_R) && (!defined(__GLIBC__) || !defined(__GLIBC_MINOR__) || __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 24)) +#define USE_READDIR_R 1 +#else +#undef USE_READDIR_R +#endif + +/* Set up defaults for internal error codes. */ +#ifndef ARCHIVE_ERRNO_FILE_FORMAT +#if HAVE_EFTYPE +#define ARCHIVE_ERRNO_FILE_FORMAT EFTYPE +#else +#if HAVE_EILSEQ +#define ARCHIVE_ERRNO_FILE_FORMAT EILSEQ +#else +#define ARCHIVE_ERRNO_FILE_FORMAT EINVAL +#endif +#endif +#endif + +#ifndef ARCHIVE_ERRNO_PROGRAMMER +#define ARCHIVE_ERRNO_PROGRAMMER EINVAL +#endif + +#ifndef ARCHIVE_ERRNO_MISC +#define ARCHIVE_ERRNO_MISC (-1) +#endif + +#if defined(__GNUC__) && (__GNUC__ >= 7) +#define __LA_FALLTHROUGH __attribute__((fallthrough)) +#else +#define __LA_FALLTHROUGH +#endif + +#endif /* !ARCHIVE_PLATFORM_H_INCLUDED */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_platform_acl.h b/dependencies/libarchive-3.4.2/libarchive/archive_platform_acl.h new file mode 100644 index 0000000..264e6de --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_platform_acl.h @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 2017 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* !!ONLY FOR USE INTERNALLY TO LIBARCHIVE!! */ + +#ifndef ARCHIVE_PLATFORM_ACL_H_INCLUDED +#define ARCHIVE_PLATFORM_ACL_H_INCLUDED + +#ifndef __LIBARCHIVE_BUILD +#ifndef __LIBARCHIVE_TEST_COMMON +#error This header is only to be used internally to libarchive. +#endif +#endif + +/* + * Determine what ACL types are supported + */ +#if ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_SUNOS || ARCHIVE_ACL_LIBACL +#define ARCHIVE_ACL_POSIX1E 1 +#endif + +#if ARCHIVE_ACL_FREEBSD_NFS4 || ARCHIVE_ACL_SUNOS_NFS4 || \ + ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL +#define ARCHIVE_ACL_NFS4 1 +#endif + +#if ARCHIVE_ACL_POSIX1E || ARCHIVE_ACL_NFS4 +#define ARCHIVE_ACL_SUPPORT 1 +#endif + +#endif /* ARCHIVE_PLATFORM_ACL_H_INCLUDED */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_platform_xattr.h b/dependencies/libarchive-3.4.2/libarchive/archive_platform_xattr.h new file mode 100644 index 0000000..ad4b90a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_platform_xattr.h @@ -0,0 +1,47 @@ +/*- + * Copyright (c) 2017 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* !!ONLY FOR USE INTERNALLY TO LIBARCHIVE!! */ + +#ifndef ARCHIVE_PLATFORM_XATTR_H_INCLUDED +#define ARCHIVE_PLATFORM_XATTR_H_INCLUDED + +#ifndef __LIBARCHIVE_BUILD +#ifndef __LIBARCHIVE_TEST_COMMON +#error This header is only to be used internally to libarchive. +#endif +#endif + +/* + * Determine if we support extended attributes + */ +#if ARCHIVE_XATTR_LINUX || ARCHIVE_XATTR_DARWIN || ARCHIVE_XATTR_FREEBSD || \ + ARCHIVE_XATTR_AIX +#define ARCHIVE_XATTR_SUPPORT 1 +#endif + +#endif /* ARCHIVE_PLATFORM_XATTR_H_INCLUDED */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_ppmd7.c b/dependencies/libarchive-3.4.2/libarchive/archive_ppmd7.c new file mode 100644 index 0000000..4029395 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_ppmd7.c @@ -0,0 +1,1168 @@ +/* Ppmd7.c -- PPMdH codec +2010-03-12 : Igor Pavlov : Public domain +This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ + +#include "archive_platform.h" + +#include + +#include "archive_ppmd7_private.h" + +#ifdef PPMD_32BIT + #define Ppmd7_GetPtr(p, ptr) (ptr) + #define Ppmd7_GetContext(p, ptr) (ptr) + #define Ppmd7_GetStats(p, ctx) ((ctx)->Stats) +#else + #define Ppmd7_GetPtr(p, offs) ((void *)((p)->Base + (offs))) + #define Ppmd7_GetContext(p, offs) ((CPpmd7_Context *)Ppmd7_GetPtr((p), (offs))) + #define Ppmd7_GetStats(p, ctx) ((CPpmd_State *)Ppmd7_GetPtr((p), ((ctx)->Stats))) +#endif + +#define Ppmd7_GetBinSumm(p) \ + &p->BinSumm[Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \ + p->NS2BSIndx[Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \ + (p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \ + 2 * p->HB2Flag[Ppmd7Context_OneState(p->MinContext)->Symbol] + \ + ((p->RunLength >> 26) & 0x20)] + +#define kTopValue (1 << 24) +#define MAX_FREQ 124 +#define UNIT_SIZE 12 + +#define U2B(nu) ((UInt32)(nu) * UNIT_SIZE) +#define U2I(nu) (p->Units2Indx[(nu) - 1]) +#define I2U(indx) (p->Indx2Units[indx]) + +#ifdef PPMD_32BIT + #define REF(ptr) (ptr) +#else + #define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base)) +#endif + +#define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr)) + +#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref)) +#define STATS(ctx) Ppmd7_GetStats(p, ctx) +#define ONE_STATE(ctx) Ppmd7Context_OneState(ctx) +#define SUFFIX(ctx) CTX((ctx)->Suffix) + +static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051}; +static const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 }; + +typedef CPpmd7_Context * CTX_PTR; + +struct CPpmd7_Node_; + +typedef + #ifdef PPMD_32BIT + struct CPpmd7_Node_ * + #else + UInt32 + #endif + CPpmd7_Node_Ref; + +typedef struct CPpmd7_Node_ +{ + UInt16 Stamp; /* must be at offset 0 as CPpmd7_Context::NumStats. Stamp=0 means free */ + UInt16 NU; + CPpmd7_Node_Ref Next; /* must be at offset >= 4 */ + CPpmd7_Node_Ref Prev; +} CPpmd7_Node; + +#ifdef PPMD_32BIT + #define NODE(ptr) (ptr) +#else + #define NODE(offs) ((CPpmd7_Node *)(p->Base + (offs))) +#endif + +static void Ppmd7_Update1(CPpmd7 *p); +static void Ppmd7_Update1_0(CPpmd7 *p); +static void Ppmd7_Update2(CPpmd7 *p); +static void Ppmd7_UpdateBin(CPpmd7 *p); +static CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, + UInt32 *scale); + +/* ----------- Base ----------- */ + +static void Ppmd7_Construct(CPpmd7 *p) +{ + unsigned i, k, m; + + p->Base = 0; + + for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++) + { + unsigned step = (i >= 12 ? 4 : (i >> 2) + 1); + do { p->Units2Indx[k++] = (Byte)i; } while(--step); + p->Indx2Units[i] = (Byte)k; + } + + p->NS2BSIndx[0] = (0 << 1); + p->NS2BSIndx[1] = (1 << 1); + memset(p->NS2BSIndx + 2, (2 << 1), 9); + memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11); + + for (i = 0; i < 3; i++) + p->NS2Indx[i] = (Byte)i; + for (m = i, k = 1; i < 256; i++) + { + p->NS2Indx[i] = (Byte)m; + if (--k == 0) + k = (++m) - 2; + } + + memset(p->HB2Flag, 0, 0x40); + memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40); +} + +static void Ppmd7_Free(CPpmd7 *p) +{ + free(p->Base); + p->Size = 0; + p->Base = 0; +} + +static Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size) +{ + if (p->Base == 0 || p->Size != size) + { + /* RestartModel() below assumes that p->Size >= UNIT_SIZE + (see the calculation of m->MinContext). */ + if (size < UNIT_SIZE) { + return False; + } + Ppmd7_Free(p); + p->AlignOffset = + #ifdef PPMD_32BIT + (4 - size) & 3; + #else + 4 - (size & 3); + #endif + if ((p->Base = (Byte *)malloc(p->AlignOffset + size + #ifndef PPMD_32BIT + + UNIT_SIZE + #endif + )) == 0) + return False; + p->Size = size; + } + return True; +} + +static void InsertNode(CPpmd7 *p, void *node, unsigned indx) +{ + *((CPpmd_Void_Ref *)node) = p->FreeList[indx]; + p->FreeList[indx] = REF(node); +} + +static void *RemoveNode(CPpmd7 *p, unsigned indx) +{ + CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]); + p->FreeList[indx] = *node; + return node; +} + +static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx) +{ + unsigned i, nu = I2U(oldIndx) - I2U(newIndx); + ptr = (Byte *)ptr + U2B(I2U(newIndx)); + if (I2U(i = U2I(nu)) != nu) + { + unsigned k = I2U(--i); + InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1); + } + InsertNode(p, ptr, i); +} + +static void GlueFreeBlocks(CPpmd7 *p) +{ + #ifdef PPMD_32BIT + CPpmd7_Node headItem; + CPpmd7_Node_Ref head = &headItem; + #else + CPpmd7_Node_Ref head = p->AlignOffset + p->Size; + #endif + + CPpmd7_Node_Ref n = head; + unsigned i; + + p->GlueCount = 255; + + /* create doubly-linked list of free blocks */ + for (i = 0; i < PPMD_NUM_INDEXES; i++) + { + UInt16 nu = I2U(i); + CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i]; + p->FreeList[i] = 0; + while (next != 0) + { + CPpmd7_Node *node = NODE(next); + node->Next = n; + n = NODE(n)->Prev = next; + next = *(const CPpmd7_Node_Ref *)node; + node->Stamp = 0; + node->NU = (UInt16)nu; + } + } + NODE(head)->Stamp = 1; + NODE(head)->Next = n; + NODE(n)->Prev = head; + if (p->LoUnit != p->HiUnit) + ((CPpmd7_Node *)p->LoUnit)->Stamp = 1; + + /* Glue free blocks */ + while (n != head) + { + CPpmd7_Node *node = NODE(n); + UInt32 nu = (UInt32)node->NU; + for (;;) + { + CPpmd7_Node *node2 = NODE(n) + nu; + nu += node2->NU; + if (node2->Stamp != 0 || nu >= 0x10000) + break; + NODE(node2->Prev)->Next = node2->Next; + NODE(node2->Next)->Prev = node2->Prev; + node->NU = (UInt16)nu; + } + n = node->Next; + } + + /* Fill lists of free blocks */ + for (n = NODE(head)->Next; n != head;) + { + CPpmd7_Node *node = NODE(n); + unsigned nu; + CPpmd7_Node_Ref next = node->Next; + for (nu = node->NU; nu > 128; nu -= 128, node += 128) + InsertNode(p, node, PPMD_NUM_INDEXES - 1); + if (I2U(i = U2I(nu)) != nu) + { + unsigned k = I2U(--i); + InsertNode(p, node + k, nu - k - 1); + } + InsertNode(p, node, i); + n = next; + } +} + +static void *AllocUnitsRare(CPpmd7 *p, unsigned indx) +{ + unsigned i; + void *retVal; + if (p->GlueCount == 0) + { + GlueFreeBlocks(p); + if (p->FreeList[indx] != 0) + return RemoveNode(p, indx); + } + i = indx; + do + { + if (++i == PPMD_NUM_INDEXES) + { + UInt32 numBytes = U2B(I2U(indx)); + p->GlueCount--; + return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL); + } + } + while (p->FreeList[i] == 0); + retVal = RemoveNode(p, i); + SplitBlock(p, retVal, i, indx); + return retVal; +} + +static void *AllocUnits(CPpmd7 *p, unsigned indx) +{ + UInt32 numBytes; + if (p->FreeList[indx] != 0) + return RemoveNode(p, indx); + numBytes = U2B(I2U(indx)); + if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit)) + { + void *retVal = p->LoUnit; + p->LoUnit += numBytes; + return retVal; + } + return AllocUnitsRare(p, indx); +} + +#define MyMem12Cpy(dest, src, num) \ + { UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \ + do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while(--n); } + +static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU) +{ + unsigned i0 = U2I(oldNU); + unsigned i1 = U2I(newNU); + if (i0 == i1) + return oldPtr; + if (p->FreeList[i1] != 0) + { + void *ptr = RemoveNode(p, i1); + MyMem12Cpy(ptr, oldPtr, newNU); + InsertNode(p, oldPtr, i0); + return ptr; + } + SplitBlock(p, oldPtr, i0, i1); + return oldPtr; +} + +#define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16))) + +static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v) +{ + (p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF); + (p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF); +} + +static void RestartModel(CPpmd7 *p) +{ + unsigned i, k, m; + + memset(p->FreeList, 0, sizeof(p->FreeList)); + p->Text = p->Base + p->AlignOffset; + p->HiUnit = p->Text + p->Size; + p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE; + p->GlueCount = 0; + + p->OrderFall = p->MaxOrder; + p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1; + p->PrevSuccess = 0; + + p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */ + p->MinContext->Suffix = 0; + p->MinContext->NumStats = 256; + p->MinContext->SummFreq = 256 + 1; + p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */ + p->LoUnit += U2B(256 / 2); + p->MinContext->Stats = REF(p->FoundState); + for (i = 0; i < 256; i++) + { + CPpmd_State *s = &p->FoundState[i]; + s->Symbol = (Byte)i; + s->Freq = 1; + SetSuccessor(s, 0); + } + + for (i = 0; i < 128; i++) + for (k = 0; k < 8; k++) + { + UInt16 *dest = p->BinSumm[i] + k; + UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 2)); + for (m = 0; m < 64; m += 8) + dest[m] = val; + } + + for (i = 0; i < 25; i++) + for (k = 0; k < 16; k++) + { + CPpmd_See *s = &p->See[i][k]; + s->Summ = (UInt16)((5 * i + 10) << (s->Shift = PPMD_PERIOD_BITS - 4)); + s->Count = 4; + } +} + +static void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder) +{ + p->MaxOrder = maxOrder; + RestartModel(p); + p->DummySee.Shift = PPMD_PERIOD_BITS; + p->DummySee.Summ = 0; /* unused */ + p->DummySee.Count = 64; /* unused */ +} + +static CTX_PTR CreateSuccessors(CPpmd7 *p, Bool skip) +{ + CPpmd_State upState; + CTX_PTR c = p->MinContext; + CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState); + CPpmd_State *ps[PPMD7_MAX_ORDER]; + unsigned numPs = 0; + + if (!skip) + ps[numPs++] = p->FoundState; + + while (c->Suffix) + { + CPpmd_Void_Ref successor; + CPpmd_State *s; + c = SUFFIX(c); + if (c->NumStats != 1) + { + for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++); + } + else + s = ONE_STATE(c); + successor = SUCCESSOR(s); + if (successor != upBranch) + { + c = CTX(successor); + if (numPs == 0) + return c; + break; + } + ps[numPs++] = s; + } + + upState.Symbol = *(const Byte *)Ppmd7_GetPtr(p, upBranch); + SetSuccessor(&upState, upBranch + 1); + + if (c->NumStats == 1) + upState.Freq = ONE_STATE(c)->Freq; + else + { + UInt32 cf, s0; + CPpmd_State *s; + for (s = STATS(c); s->Symbol != upState.Symbol; s++); + cf = s->Freq - 1; + s0 = c->SummFreq - c->NumStats - cf; + upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((2 * cf + 3 * s0 - 1) / (2 * s0)))); + } + + while (numPs != 0) + { + /* Create Child */ + CTX_PTR c1; /* = AllocContext(p); */ + if (p->HiUnit != p->LoUnit) + c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); + else if (p->FreeList[0] != 0) + c1 = (CTX_PTR)RemoveNode(p, 0); + else + { + c1 = (CTX_PTR)AllocUnitsRare(p, 0); + if (!c1) + return NULL; + } + c1->NumStats = 1; + *ONE_STATE(c1) = upState; + c1->Suffix = REF(c); + SetSuccessor(ps[--numPs], REF(c1)); + c = c1; + } + + return c; +} + +static void SwapStates(CPpmd_State *t1, CPpmd_State *t2) +{ + CPpmd_State tmp = *t1; + *t1 = *t2; + *t2 = tmp; +} + +static void UpdateModel(CPpmd7 *p) +{ + CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState); + CTX_PTR c; + unsigned s0, ns; + + if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0) + { + c = SUFFIX(p->MinContext); + + if (c->NumStats == 1) + { + CPpmd_State *s = ONE_STATE(c); + if (s->Freq < 32) + s->Freq++; + } + else + { + CPpmd_State *s = STATS(c); + if (s->Symbol != p->FoundState->Symbol) + { + do { s++; } while (s->Symbol != p->FoundState->Symbol); + if (s[0].Freq >= s[-1].Freq) + { + SwapStates(&s[0], &s[-1]); + s--; + } + } + if (s->Freq < MAX_FREQ - 9) + { + s->Freq += 2; + c->SummFreq += 2; + } + } + } + + if (p->OrderFall == 0) + { + p->MinContext = p->MaxContext = CreateSuccessors(p, True); + if (p->MinContext == 0) + { + RestartModel(p); + return; + } + SetSuccessor(p->FoundState, REF(p->MinContext)); + return; + } + + *p->Text++ = p->FoundState->Symbol; + successor = REF(p->Text); + if (p->Text >= p->UnitsStart) + { + RestartModel(p); + return; + } + + if (fSuccessor) + { + if (fSuccessor <= successor) + { + CTX_PTR cs = CreateSuccessors(p, False); + if (cs == NULL) + { + RestartModel(p); + return; + } + fSuccessor = REF(cs); + } + if (--p->OrderFall == 0) + { + successor = fSuccessor; + p->Text -= (p->MaxContext != p->MinContext); + } + } + else + { + SetSuccessor(p->FoundState, successor); + fSuccessor = REF(p->MinContext); + } + + s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - (p->FoundState->Freq - 1); + + for (c = p->MaxContext; c != p->MinContext; c = SUFFIX(c)) + { + unsigned ns1; + UInt32 cf, sf; + if ((ns1 = c->NumStats) != 1) + { + if ((ns1 & 1) == 0) + { + /* Expand for one UNIT */ + unsigned oldNU = ns1 >> 1; + unsigned i = U2I(oldNU); + if (i != U2I(oldNU + 1)) + { + void *ptr = AllocUnits(p, i + 1); + void *oldPtr; + if (!ptr) + { + RestartModel(p); + return; + } + oldPtr = STATS(c); + MyMem12Cpy(ptr, oldPtr, oldNU); + InsertNode(p, oldPtr, i); + c->Stats = STATS_REF(ptr); + } + } + c->SummFreq = (UInt16)(c->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) & (c->SummFreq <= 8 * ns1))); + } + else + { + CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0); + if (!s) + { + RestartModel(p); + return; + } + *s = *ONE_STATE(c); + c->Stats = REF(s); + if (s->Freq < MAX_FREQ / 4 - 1) + s->Freq <<= 1; + else + s->Freq = MAX_FREQ - 4; + c->SummFreq = (UInt16)(s->Freq + p->InitEsc + (ns > 3)); + } + cf = 2 * (UInt32)p->FoundState->Freq * (c->SummFreq + 6); + sf = (UInt32)s0 + c->SummFreq; + if (cf < 6 * sf) + { + cf = 1 + (cf > sf) + (cf >= 4 * sf); + c->SummFreq += 3; + } + else + { + cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf); + c->SummFreq = (UInt16)(c->SummFreq + cf); + } + { + CPpmd_State *s = STATS(c) + ns1; + SetSuccessor(s, successor); + s->Symbol = p->FoundState->Symbol; + s->Freq = (Byte)cf; + c->NumStats = (UInt16)(ns1 + 1); + } + } + p->MaxContext = p->MinContext = CTX(fSuccessor); +} + +static void Rescale(CPpmd7 *p) +{ + unsigned i, adder, sumFreq, escFreq; + CPpmd_State *stats = STATS(p->MinContext); + CPpmd_State *s = p->FoundState; + { + CPpmd_State tmp = *s; + for (; s != stats; s--) + s[0] = s[-1]; + *s = tmp; + } + escFreq = p->MinContext->SummFreq - s->Freq; + s->Freq += 4; + adder = (p->OrderFall != 0); + s->Freq = (Byte)((s->Freq + adder) >> 1); + sumFreq = s->Freq; + + i = p->MinContext->NumStats - 1; + do + { + escFreq -= (++s)->Freq; + s->Freq = (Byte)((s->Freq + adder) >> 1); + sumFreq += s->Freq; + if (s[0].Freq > s[-1].Freq) + { + CPpmd_State *s1 = s; + CPpmd_State tmp = *s1; + do + s1[0] = s1[-1]; + while (--s1 != stats && tmp.Freq > s1[-1].Freq); + *s1 = tmp; + } + } + while (--i); + + if (s->Freq == 0) + { + unsigned numStats = p->MinContext->NumStats; + unsigned n0, n1; + do { i++; } while ((--s)->Freq == 0); + escFreq += i; + p->MinContext->NumStats = (UInt16)(p->MinContext->NumStats - i); + if (p->MinContext->NumStats == 1) + { + CPpmd_State tmp = *stats; + do + { + tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1)); + escFreq >>= 1; + } + while (escFreq > 1); + InsertNode(p, stats, U2I(((numStats + 1) >> 1))); + *(p->FoundState = ONE_STATE(p->MinContext)) = tmp; + return; + } + n0 = (numStats + 1) >> 1; + n1 = (p->MinContext->NumStats + 1) >> 1; + if (n0 != n1) + p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1)); + } + p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1)); + p->FoundState = STATS(p->MinContext); +} + +static CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq) +{ + CPpmd_See *see; + unsigned nonMasked = p->MinContext->NumStats - numMasked; + if (p->MinContext->NumStats != 256) + { + see = p->See[p->NS2Indx[nonMasked - 1]] + + (nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) + + 2 * (p->MinContext->SummFreq < 11 * p->MinContext->NumStats) + + 4 * (numMasked > nonMasked) + + p->HiBitsFlag; + { + unsigned r = (see->Summ >> see->Shift); + see->Summ = (UInt16)(see->Summ - r); + *escFreq = r + (r == 0); + } + } + else + { + see = &p->DummySee; + *escFreq = 1; + } + return see; +} + +static void NextContext(CPpmd7 *p) +{ + CTX_PTR c = CTX(SUCCESSOR(p->FoundState)); + if (p->OrderFall == 0 && (Byte *)c > p->Text) + p->MinContext = p->MaxContext = c; + else + UpdateModel(p); +} + +static void Ppmd7_Update1(CPpmd7 *p) +{ + CPpmd_State *s = p->FoundState; + s->Freq += 4; + p->MinContext->SummFreq += 4; + if (s[0].Freq > s[-1].Freq) + { + SwapStates(&s[0], &s[-1]); + p->FoundState = --s; + if (s->Freq > MAX_FREQ) + Rescale(p); + } + NextContext(p); +} + +static void Ppmd7_Update1_0(CPpmd7 *p) +{ + p->PrevSuccess = (2 * p->FoundState->Freq > p->MinContext->SummFreq); + p->RunLength += p->PrevSuccess; + p->MinContext->SummFreq += 4; + if ((p->FoundState->Freq += 4) > MAX_FREQ) + Rescale(p); + NextContext(p); +} + +static void Ppmd7_UpdateBin(CPpmd7 *p) +{ + p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 128 ? 1: 0)); + p->PrevSuccess = 1; + p->RunLength++; + NextContext(p); +} + +static void Ppmd7_Update2(CPpmd7 *p) +{ + p->MinContext->SummFreq += 4; + if ((p->FoundState->Freq += 4) > MAX_FREQ) + Rescale(p); + p->RunLength = p->InitRL; + UpdateModel(p); +} + +/* ---------- Decode ---------- */ + +static Bool Ppmd_RangeDec_Init(CPpmd7z_RangeDec *p) +{ + unsigned i; + p->Low = p->Bottom = 0; + p->Range = 0xFFFFFFFF; + for (i = 0; i < 4; i++) + p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream); + return (p->Code < 0xFFFFFFFF); +} + +static Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p) +{ + if (p->Stream->Read((void *)p->Stream) != 0) + return False; + return Ppmd_RangeDec_Init(p); +} + +static Bool PpmdRAR_RangeDec_Init(CPpmd7z_RangeDec *p) +{ + if (!Ppmd_RangeDec_Init(p)) + return False; + p->Bottom = 0x8000; + return True; +} + +static UInt32 Range_GetThreshold(void *pp, UInt32 total) +{ + CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp; + return (p->Code - p->Low) / (p->Range /= total); +} + +static void Range_Normalize(CPpmd7z_RangeDec *p) +{ + while (1) + { + if((p->Low ^ (p->Low + p->Range)) >= kTopValue) + { + if(p->Range >= p->Bottom) + break; + else + p->Range = ((uint32_t)(-(int32_t)p->Low)) & (p->Bottom - 1); + } + p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream); + p->Range <<= 8; + p->Low <<= 8; + } +} + +static void Range_Decode_7z(void *pp, UInt32 start, UInt32 size) +{ + CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp; + p->Code -= start * p->Range; + p->Range *= size; + Range_Normalize(p); +} + +static void Range_Decode_RAR(void *pp, UInt32 start, UInt32 size) +{ + CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp; + p->Low += start * p->Range; + p->Range *= size; + Range_Normalize(p); +} + +static UInt32 Range_DecodeBit_7z(void *pp, UInt32 size0) +{ + CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp; + UInt32 newBound = (p->Range >> 14) * size0; + UInt32 symbol; + if (p->Code < newBound) + { + symbol = 0; + p->Range = newBound; + } + else + { + symbol = 1; + p->Code -= newBound; + p->Range -= newBound; + } + Range_Normalize(p); + return symbol; +} + +static UInt32 Range_DecodeBit_RAR(void *pp, UInt32 size0) +{ + CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp; + UInt32 bit, value = p->p.GetThreshold(p, PPMD_BIN_SCALE); + if(value < size0) + { + bit = 0; + p->p.Decode(p, 0, size0); + } + else + { + bit = 1; + p->p.Decode(p, size0, PPMD_BIN_SCALE - size0); + } + return bit; +} + +static void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p) +{ + p->p.GetThreshold = Range_GetThreshold; + p->p.Decode = Range_Decode_7z; + p->p.DecodeBit = Range_DecodeBit_7z; +} + +static void PpmdRAR_RangeDec_CreateVTable(CPpmd7z_RangeDec *p) +{ + p->p.GetThreshold = Range_GetThreshold; + p->p.Decode = Range_Decode_RAR; + p->p.DecodeBit = Range_DecodeBit_RAR; +} + +#define MASK(sym) ((signed char *)charMask)[sym] + +static int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc) +{ + size_t charMask[256 / sizeof(size_t)]; + if (p->MinContext->NumStats != 1) + { + CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext); + unsigned i; + UInt32 count, hiCnt; + if ((count = rc->GetThreshold(rc, p->MinContext->SummFreq)) < (hiCnt = s->Freq)) + { + Byte symbol; + rc->Decode(rc, 0, s->Freq); + p->FoundState = s; + symbol = s->Symbol; + Ppmd7_Update1_0(p); + return symbol; + } + p->PrevSuccess = 0; + i = p->MinContext->NumStats - 1; + do + { + if ((hiCnt += (++s)->Freq) > count) + { + Byte symbol; + rc->Decode(rc, hiCnt - s->Freq, s->Freq); + p->FoundState = s; + symbol = s->Symbol; + Ppmd7_Update1(p); + return symbol; + } + } + while (--i); + if (count >= p->MinContext->SummFreq) + return -2; + p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]; + rc->Decode(rc, hiCnt, p->MinContext->SummFreq - hiCnt); + PPMD_SetAllBitsIn256Bytes(charMask); + MASK(s->Symbol) = 0; + i = p->MinContext->NumStats - 1; + do { MASK((--s)->Symbol) = 0; } while (--i); + } + else + { + UInt16 *prob = Ppmd7_GetBinSumm(p); + if (rc->DecodeBit(rc, *prob) == 0) + { + Byte symbol; + *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob); + symbol = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol; + Ppmd7_UpdateBin(p); + return symbol; + } + *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob); + p->InitEsc = PPMD7_kExpEscape[*prob >> 10]; + PPMD_SetAllBitsIn256Bytes(charMask); + MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0; + p->PrevSuccess = 0; + } + for (;;) + { + CPpmd_State *ps[256], *s; + UInt32 freqSum, count, hiCnt; + CPpmd_See *see; + unsigned i, num, numMasked = p->MinContext->NumStats; + do + { + p->OrderFall++; + if (!p->MinContext->Suffix) + return -1; + p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix); + } + while (p->MinContext->NumStats == numMasked); + hiCnt = 0; + s = Ppmd7_GetStats(p, p->MinContext); + i = 0; + num = p->MinContext->NumStats - numMasked; + do + { + int k = (int)(MASK(s->Symbol)); + hiCnt += (s->Freq & k); + ps[i] = s++; + i -= k; + } + while (i != num); + + see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum); + freqSum += hiCnt; + count = rc->GetThreshold(rc, freqSum); + + if (count < hiCnt) + { + Byte symbol; + CPpmd_State **pps = ps; + for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++); + s = *pps; + rc->Decode(rc, hiCnt - s->Freq, s->Freq); + Ppmd_See_Update(see); + p->FoundState = s; + symbol = s->Symbol; + Ppmd7_Update2(p); + return symbol; + } + if (count >= freqSum) + return -2; + rc->Decode(rc, hiCnt, freqSum - hiCnt); + see->Summ = (UInt16)(see->Summ + freqSum); + do { MASK(ps[--i]->Symbol) = 0; } while (i != 0); + } +} + +/* ---------- Encode ---------- Ppmd7Enc.c */ + +#define kTopValue (1 << 24) + +static void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p) +{ + p->Low = 0; + p->Range = 0xFFFFFFFF; + p->Cache = 0; + p->CacheSize = 1; +} + +static void RangeEnc_ShiftLow(CPpmd7z_RangeEnc *p) +{ + if ((UInt32)p->Low < (UInt32)0xFF000000 || (unsigned)(p->Low >> 32) != 0) + { + Byte temp = p->Cache; + do + { + p->Stream->Write(p->Stream, (Byte)(temp + (Byte)(p->Low >> 32))); + temp = 0xFF; + } + while(--p->CacheSize != 0); + p->Cache = (Byte)((UInt32)p->Low >> 24); + } + p->CacheSize++; + p->Low = ((UInt32)p->Low << 8) & 0xFFFFFFFF; +} + +static void RangeEnc_Encode(CPpmd7z_RangeEnc *p, UInt32 start, UInt32 size, UInt32 total) +{ + p->Low += (UInt64)start * (UInt64)(p->Range /= total); + p->Range *= size; + while (p->Range < kTopValue) + { + p->Range <<= 8; + RangeEnc_ShiftLow(p); + } +} + +static void RangeEnc_EncodeBit_0(CPpmd7z_RangeEnc *p, UInt32 size0) +{ + p->Range = (p->Range >> 14) * size0; + while (p->Range < kTopValue) + { + p->Range <<= 8; + RangeEnc_ShiftLow(p); + } +} + +static void RangeEnc_EncodeBit_1(CPpmd7z_RangeEnc *p, UInt32 size0) +{ + UInt32 newBound = (p->Range >> 14) * size0; + p->Low += newBound; + p->Range -= newBound; + while (p->Range < kTopValue) + { + p->Range <<= 8; + RangeEnc_ShiftLow(p); + } +} + +static void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p) +{ + unsigned i; + for (i = 0; i < 5; i++) + RangeEnc_ShiftLow(p); +} + + +#define MASK(sym) ((signed char *)charMask)[sym] + +static void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol) +{ + size_t charMask[256 / sizeof(size_t)]; + if (p->MinContext->NumStats != 1) + { + CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext); + UInt32 sum; + unsigned i; + if (s->Symbol == symbol) + { + RangeEnc_Encode(rc, 0, s->Freq, p->MinContext->SummFreq); + p->FoundState = s; + Ppmd7_Update1_0(p); + return; + } + p->PrevSuccess = 0; + sum = s->Freq; + i = p->MinContext->NumStats - 1; + do + { + if ((++s)->Symbol == symbol) + { + RangeEnc_Encode(rc, sum, s->Freq, p->MinContext->SummFreq); + p->FoundState = s; + Ppmd7_Update1(p); + return; + } + sum += s->Freq; + } + while (--i); + + p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]; + PPMD_SetAllBitsIn256Bytes(charMask); + MASK(s->Symbol) = 0; + i = p->MinContext->NumStats - 1; + do { MASK((--s)->Symbol) = 0; } while (--i); + RangeEnc_Encode(rc, sum, p->MinContext->SummFreq - sum, p->MinContext->SummFreq); + } + else + { + UInt16 *prob = Ppmd7_GetBinSumm(p); + CPpmd_State *s = Ppmd7Context_OneState(p->MinContext); + if (s->Symbol == symbol) + { + RangeEnc_EncodeBit_0(rc, *prob); + *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob); + p->FoundState = s; + Ppmd7_UpdateBin(p); + return; + } + else + { + RangeEnc_EncodeBit_1(rc, *prob); + *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob); + p->InitEsc = PPMD7_kExpEscape[*prob >> 10]; + PPMD_SetAllBitsIn256Bytes(charMask); + MASK(s->Symbol) = 0; + p->PrevSuccess = 0; + } + } + for (;;) + { + UInt32 escFreq; + CPpmd_See *see; + CPpmd_State *s; + UInt32 sum; + unsigned i, numMasked = p->MinContext->NumStats; + do + { + p->OrderFall++; + if (!p->MinContext->Suffix) + return; /* EndMarker (symbol = -1) */ + p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix); + } + while (p->MinContext->NumStats == numMasked); + + see = Ppmd7_MakeEscFreq(p, numMasked, &escFreq); + s = Ppmd7_GetStats(p, p->MinContext); + sum = 0; + i = p->MinContext->NumStats; + do + { + int cur = s->Symbol; + if (cur == symbol) + { + UInt32 low = sum; + CPpmd_State *s1 = s; + do + { + sum += (s->Freq & (int)(MASK(s->Symbol))); + s++; + } + while (--i); + RangeEnc_Encode(rc, low, s1->Freq, sum + escFreq); + Ppmd_See_Update(see); + p->FoundState = s1; + Ppmd7_Update2(p); + return; + } + sum += (s->Freq & (int)(MASK(cur))); + MASK(cur) = 0; + s++; + } + while (--i); + + RangeEnc_Encode(rc, sum, escFreq, sum + escFreq); + see->Summ = (UInt16)(see->Summ + sum + escFreq); + } +} + +const IPpmd7 __archive_ppmd7_functions = +{ + &Ppmd7_Construct, + &Ppmd7_Alloc, + &Ppmd7_Free, + &Ppmd7_Init, + &Ppmd7z_RangeDec_CreateVTable, + &PpmdRAR_RangeDec_CreateVTable, + &Ppmd7z_RangeDec_Init, + &PpmdRAR_RangeDec_Init, + &Ppmd7_DecodeSymbol, + &Ppmd7z_RangeEnc_Init, + &Ppmd7z_RangeEnc_FlushData, + &Ppmd7_EncodeSymbol +}; diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_ppmd7_private.h b/dependencies/libarchive-3.4.2/libarchive/archive_ppmd7_private.h new file mode 100644 index 0000000..71b9544 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_ppmd7_private.h @@ -0,0 +1,119 @@ +/* Ppmd7.h -- PPMdH compression codec +2010-03-12 : Igor Pavlov : Public domain +This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ + +/* This code supports virtual RangeDecoder and includes the implementation +of RangeCoder from 7z, instead of RangeCoder from original PPMd var.H. +If you need the compatibility with original PPMd var.H, you can use external RangeDecoder */ + +#ifndef ARCHIVE_PPMD7_PRIVATE_H_INCLUDED +#define ARCHIVE_PPMD7_PRIVATE_H_INCLUDED + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif + +#include "archive_ppmd_private.h" + +#define PPMD7_MIN_ORDER 2 +#define PPMD7_MAX_ORDER 64 + +#define PPMD7_MIN_MEM_SIZE (1 << 11) +#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFFu - 12 * 3) + +struct CPpmd7_Context_; + +typedef + #ifdef PPMD_32BIT + struct CPpmd7_Context_ * + #else + UInt32 + #endif + CPpmd7_Context_Ref; + +typedef struct CPpmd7_Context_ +{ + UInt16 NumStats; + UInt16 SummFreq; + CPpmd_State_Ref Stats; + CPpmd7_Context_Ref Suffix; +} CPpmd7_Context; + +#define Ppmd7Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq) + +typedef struct +{ + CPpmd7_Context *MinContext, *MaxContext; + CPpmd_State *FoundState; + unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder, HiBitsFlag; + Int32 RunLength, InitRL; /* must be 32-bit at least */ + + UInt32 Size; + UInt32 GlueCount; + Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart; + UInt32 AlignOffset; + + Byte Indx2Units[PPMD_NUM_INDEXES]; + Byte Units2Indx[128]; + CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES]; + Byte NS2Indx[256], NS2BSIndx[256], HB2Flag[256]; + CPpmd_See DummySee, See[25][16]; + UInt16 BinSumm[128][64]; +} CPpmd7; + +/* ---------- Decode ---------- */ + +typedef struct +{ + UInt32 (*GetThreshold)(void *p, UInt32 total); + void (*Decode)(void *p, UInt32 start, UInt32 size); + UInt32 (*DecodeBit)(void *p, UInt32 size0); +} IPpmd7_RangeDec; + +typedef struct +{ + IPpmd7_RangeDec p; + UInt32 Range; + UInt32 Code; + UInt32 Low; + UInt32 Bottom; + IByteIn *Stream; +} CPpmd7z_RangeDec; + +/* ---------- Encode ---------- */ + +typedef struct +{ + UInt64 Low; + UInt32 Range; + Byte Cache; + UInt64 CacheSize; + IByteOut *Stream; +} CPpmd7z_RangeEnc; + +typedef struct +{ + /* Base Functions */ + void (*Ppmd7_Construct)(CPpmd7 *p); + Bool (*Ppmd7_Alloc)(CPpmd7 *p, UInt32 size); + void (*Ppmd7_Free)(CPpmd7 *p); + void (*Ppmd7_Init)(CPpmd7 *p, unsigned maxOrder); + #define Ppmd7_WasAllocated(p) ((p)->Base != NULL) + + /* Decode Functions */ + void (*Ppmd7z_RangeDec_CreateVTable)(CPpmd7z_RangeDec *p); + void (*PpmdRAR_RangeDec_CreateVTable)(CPpmd7z_RangeDec *p); + Bool (*Ppmd7z_RangeDec_Init)(CPpmd7z_RangeDec *p); + Bool (*PpmdRAR_RangeDec_Init)(CPpmd7z_RangeDec *p); + #define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0) + int (*Ppmd7_DecodeSymbol)(CPpmd7 *p, IPpmd7_RangeDec *rc); + + /* Encode Functions */ + void (*Ppmd7z_RangeEnc_Init)(CPpmd7z_RangeEnc *p); + void (*Ppmd7z_RangeEnc_FlushData)(CPpmd7z_RangeEnc *p); + + void (*Ppmd7_EncodeSymbol)(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol); +} IPpmd7; + +extern const IPpmd7 __archive_ppmd7_functions; +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_ppmd8.c b/dependencies/libarchive-3.4.2/libarchive/archive_ppmd8.c new file mode 100644 index 0000000..d177939 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_ppmd8.c @@ -0,0 +1,1287 @@ +/* Ppmd8.c -- PPMdI codec +2016-05-21 : Igor Pavlov : Public domain +This code is based on PPMd var.I (2002): Dmitry Shkarin : Public domain */ + +#include "archive_platform.h" + +#include + +#include "archive_ppmd8_private.h" + +const Byte PPMD8_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 }; +static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051}; + +#define MAX_FREQ 124 +#define UNIT_SIZE 12 + +#define U2B(nu) ((UInt32)(nu) * UNIT_SIZE) +#define U2I(nu) (p->Units2Indx[(nu) - 1]) +#define I2U(indx) (p->Indx2Units[indx]) + +#ifdef PPMD_32BIT + #define REF(ptr) (ptr) +#else + #define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base)) +#endif + +#define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr)) + +#define CTX(ref) ((CPpmd8_Context *)Ppmd8_GetContext(p, ref)) +#define STATS(ctx) Ppmd8_GetStats(p, ctx) +#define ONE_STATE(ctx) Ppmd8Context_OneState(ctx) +#define SUFFIX(ctx) CTX((ctx)->Suffix) + +#define kTop (1 << 24) +#define kBot (1 << 15) + +typedef CPpmd8_Context * CTX_PTR; + +struct CPpmd8_Node_; + +typedef + #ifdef PPMD_32BIT + struct CPpmd8_Node_ * + #else + UInt32 + #endif + CPpmd8_Node_Ref; + +typedef struct CPpmd8_Node_ +{ + UInt32 Stamp; + CPpmd8_Node_Ref Next; + UInt32 NU; +} CPpmd8_Node; + +#ifdef PPMD_32BIT + #define NODE(ptr) (ptr) +#else + #define NODE(offs) ((CPpmd8_Node *)(p->Base + (offs))) +#endif + +#define EMPTY_NODE 0xFFFFFFFF + +void Ppmd8_Construct(CPpmd8 *p) +{ + unsigned i, k, m; + + p->Base = 0; + + for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++) + { + unsigned step = (i >= 12 ? 4 : (i >> 2) + 1); + do { p->Units2Indx[k++] = (Byte)i; } while (--step); + p->Indx2Units[i] = (Byte)k; + } + + p->NS2BSIndx[0] = (0 << 1); + p->NS2BSIndx[1] = (1 << 1); + memset(p->NS2BSIndx + 2, (2 << 1), 9); + memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11); + + for (i = 0; i < 5; i++) + p->NS2Indx[i] = (Byte)i; + for (m = i, k = 1; i < 260; i++) + { + p->NS2Indx[i] = (Byte)m; + if (--k == 0) + k = (++m) - 4; + } +} + +void Ppmd8_Free(CPpmd8 *p) +{ + free(p->Base); + p->Size = 0; + p->Base = 0; +} + +Bool Ppmd8_Alloc(CPpmd8 *p, UInt32 size) +{ + if (p->Base == 0 || p->Size != size) + { + Ppmd8_Free(p); + p->AlignOffset = + #ifdef PPMD_32BIT + (4 - size) & 3; + #else + 4 - (size & 3); + #endif + if ((p->Base = (Byte *)malloc(p->AlignOffset + size)) == 0) + return False; + p->Size = size; + } + return True; +} + +static void InsertNode(CPpmd8 *p, void *node, unsigned indx) +{ + ((CPpmd8_Node *)node)->Stamp = EMPTY_NODE; + ((CPpmd8_Node *)node)->Next = (CPpmd8_Node_Ref)p->FreeList[indx]; + ((CPpmd8_Node *)node)->NU = I2U(indx); + p->FreeList[indx] = REF(node); + p->Stamps[indx]++; +} + +static void *RemoveNode(CPpmd8 *p, unsigned indx) +{ + CPpmd8_Node *node = NODE((CPpmd8_Node_Ref)p->FreeList[indx]); + p->FreeList[indx] = node->Next; + p->Stamps[indx]--; + return node; +} + +static void SplitBlock(CPpmd8 *p, void *ptr, unsigned oldIndx, unsigned newIndx) +{ + unsigned i, nu = I2U(oldIndx) - I2U(newIndx); + ptr = (Byte *)ptr + U2B(I2U(newIndx)); + if (I2U(i = U2I(nu)) != nu) + { + unsigned k = I2U(--i); + InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1); + } + InsertNode(p, ptr, i); +} + +static void GlueFreeBlocks(CPpmd8 *p) +{ + CPpmd8_Node_Ref head = 0; + CPpmd8_Node_Ref *prev = &head; + unsigned i; + + p->GlueCount = 1 << 13; + memset(p->Stamps, 0, sizeof(p->Stamps)); + + /* Order-0 context is always at top UNIT, so we don't need guard NODE at the end. + All blocks up to p->LoUnit can be free, so we need guard NODE at LoUnit. */ + if (p->LoUnit != p->HiUnit) + ((CPpmd8_Node *)p->LoUnit)->Stamp = 0; + + /* Glue free blocks */ + for (i = 0; i < PPMD_NUM_INDEXES; i++) + { + CPpmd8_Node_Ref next = (CPpmd8_Node_Ref)p->FreeList[i]; + p->FreeList[i] = 0; + while (next != 0) + { + CPpmd8_Node *node = NODE(next); + if (node->NU != 0) + { + CPpmd8_Node *node2; + *prev = next; + prev = &(node->Next); + while ((node2 = node + node->NU)->Stamp == EMPTY_NODE) + { + node->NU += node2->NU; + node2->NU = 0; + } + } + next = node->Next; + } + } + *prev = 0; + + /* Fill lists of free blocks */ + while (head != 0) + { + CPpmd8_Node *node = NODE(head); + unsigned nu; + head = node->Next; + nu = node->NU; + if (nu == 0) + continue; + for (; nu > 128; nu -= 128, node += 128) + InsertNode(p, node, PPMD_NUM_INDEXES - 1); + if (I2U(i = U2I(nu)) != nu) + { + unsigned k = I2U(--i); + InsertNode(p, node + k, nu - k - 1); + } + InsertNode(p, node, i); + } +} + +static void *AllocUnitsRare(CPpmd8 *p, unsigned indx) +{ + unsigned i; + void *retVal; + if (p->GlueCount == 0) + { + GlueFreeBlocks(p); + if (p->FreeList[indx] != 0) + return RemoveNode(p, indx); + } + i = indx; + do + { + if (++i == PPMD_NUM_INDEXES) + { + UInt32 numBytes = U2B(I2U(indx)); + p->GlueCount--; + return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL); + } + } + while (p->FreeList[i] == 0); + retVal = RemoveNode(p, i); + SplitBlock(p, retVal, i, indx); + return retVal; +} + +static void *AllocUnits(CPpmd8 *p, unsigned indx) +{ + UInt32 numBytes; + if (p->FreeList[indx] != 0) + return RemoveNode(p, indx); + numBytes = U2B(I2U(indx)); + if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit)) + { + void *retVal = p->LoUnit; + p->LoUnit += numBytes; + return retVal; + } + return AllocUnitsRare(p, indx); +} + +#define MyMem12Cpy(dest, src, num) \ + { UInt32 *d = (UInt32 *)dest; const UInt32 *z = (const UInt32 *)src; UInt32 n = num; \ + do { d[0] = z[0]; d[1] = z[1]; d[2] = z[2]; z += 3; d += 3; } while (--n); } + +static void *ShrinkUnits(CPpmd8 *p, void *oldPtr, unsigned oldNU, unsigned newNU) +{ + unsigned i0 = U2I(oldNU); + unsigned i1 = U2I(newNU); + if (i0 == i1) + return oldPtr; + if (p->FreeList[i1] != 0) + { + void *ptr = RemoveNode(p, i1); + MyMem12Cpy(ptr, oldPtr, newNU); + InsertNode(p, oldPtr, i0); + return ptr; + } + SplitBlock(p, oldPtr, i0, i1); + return oldPtr; +} + +static void FreeUnits(CPpmd8 *p, void *ptr, unsigned nu) +{ + InsertNode(p, ptr, U2I(nu)); +} + +static void SpecialFreeUnit(CPpmd8 *p, void *ptr) +{ + if ((Byte *)ptr != p->UnitsStart) + InsertNode(p, ptr, 0); + else + { + #ifdef PPMD8_FREEZE_SUPPORT + *(UInt32 *)ptr = EMPTY_NODE; /* it's used for (Flags == 0xFF) check in RemoveBinContexts */ + #endif + p->UnitsStart += UNIT_SIZE; + } +} + +static void *MoveUnitsUp(CPpmd8 *p, void *oldPtr, unsigned nu) +{ + unsigned indx = U2I(nu); + void *ptr; + if ((Byte *)oldPtr > p->UnitsStart + 16 * 1024 || REF(oldPtr) > p->FreeList[indx]) + return oldPtr; + ptr = RemoveNode(p, indx); + MyMem12Cpy(ptr, oldPtr, nu); + if ((Byte*)oldPtr != p->UnitsStart) + InsertNode(p, oldPtr, indx); + else + p->UnitsStart += U2B(I2U(indx)); + return ptr; +} + +static void ExpandTextArea(CPpmd8 *p) +{ + UInt32 count[PPMD_NUM_INDEXES]; + unsigned i; + memset(count, 0, sizeof(count)); + if (p->LoUnit != p->HiUnit) + ((CPpmd8_Node *)p->LoUnit)->Stamp = 0; + + { + CPpmd8_Node *node = (CPpmd8_Node *)p->UnitsStart; + for (; node->Stamp == EMPTY_NODE; node += node->NU) + { + node->Stamp = 0; + count[U2I(node->NU)]++; + } + p->UnitsStart = (Byte *)node; + } + + for (i = 0; i < PPMD_NUM_INDEXES; i++) + { + CPpmd8_Node_Ref *next = (CPpmd8_Node_Ref *)&p->FreeList[i]; + while (count[i] != 0) + { + CPpmd8_Node *node = NODE(*next); + while (node->Stamp == 0) + { + *next = node->Next; + node = NODE(*next); + p->Stamps[i]--; + if (--count[i] == 0) + break; + } + next = &node->Next; + } + } +} + +#define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16))) + +static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v) +{ + (p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF); + (p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF); +} + +#define RESET_TEXT(offs) { p->Text = p->Base + p->AlignOffset + (offs); } + +static void RestartModel(CPpmd8 *p) +{ + unsigned i, k, m, r; + + memset(p->FreeList, 0, sizeof(p->FreeList)); + memset(p->Stamps, 0, sizeof(p->Stamps)); + RESET_TEXT(0); + p->HiUnit = p->Text + p->Size; + p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE; + p->GlueCount = 0; + + p->OrderFall = p->MaxOrder; + p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1; + p->PrevSuccess = 0; + + p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */ + p->MinContext->Suffix = 0; + p->MinContext->NumStats = 255; + p->MinContext->Flags = 0; + p->MinContext->SummFreq = 256 + 1; + p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */ + p->LoUnit += U2B(256 / 2); + p->MinContext->Stats = REF(p->FoundState); + for (i = 0; i < 256; i++) + { + CPpmd_State *s = &p->FoundState[i]; + s->Symbol = (Byte)i; + s->Freq = 1; + SetSuccessor(s, 0); + } + + for (i = m = 0; m < 25; m++) + { + while (p->NS2Indx[i] == m) + i++; + for (k = 0; k < 8; k++) + { + UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 1)); + UInt16 *dest = p->BinSumm[m] + k; + for (r = 0; r < 64; r += 8) + dest[r] = val; + } + } + + for (i = m = 0; m < 24; m++) + { + while (p->NS2Indx[i + 3] == m + 3) + i++; + for (k = 0; k < 32; k++) + { + CPpmd_See *s = &p->See[m][k]; + s->Summ = (UInt16)((2 * i + 5) << (s->Shift = PPMD_PERIOD_BITS - 4)); + s->Count = 7; + } + } +} + +void Ppmd8_Init(CPpmd8 *p, unsigned maxOrder, unsigned restoreMethod) +{ + p->MaxOrder = maxOrder; + p->RestoreMethod = restoreMethod; + RestartModel(p); + p->DummySee.Shift = PPMD_PERIOD_BITS; + p->DummySee.Summ = 0; /* unused */ + p->DummySee.Count = 64; /* unused */ +} + +static void Refresh(CPpmd8 *p, CTX_PTR ctx, unsigned oldNU, unsigned scale) +{ + unsigned i = ctx->NumStats, escFreq, sumFreq, flags; + CPpmd_State *s = (CPpmd_State *)ShrinkUnits(p, STATS(ctx), oldNU, (i + 2) >> 1); + ctx->Stats = REF(s); + #ifdef PPMD8_FREEZE_SUPPORT + /* fixed over Shkarin's code. Fixed code is not compatible with original code for some files in FREEZE mode. */ + scale |= (ctx->SummFreq >= ((UInt32)1 << 15)); + #endif + flags = (ctx->Flags & (0x10 + 0x04 * scale)) + 0x08 * (s->Symbol >= 0x40); + escFreq = ctx->SummFreq - s->Freq; + sumFreq = (s->Freq = (Byte)((s->Freq + scale) >> scale)); + do + { + escFreq -= (++s)->Freq; + sumFreq += (s->Freq = (Byte)((s->Freq + scale) >> scale)); + flags |= 0x08 * (s->Symbol >= 0x40); + } + while (--i); + ctx->SummFreq = (UInt16)(sumFreq + ((escFreq + scale) >> scale)); + ctx->Flags = (Byte)flags; +} + +static void SwapStates(CPpmd_State *t1, CPpmd_State *t2) +{ + CPpmd_State tmp = *t1; + *t1 = *t2; + *t2 = tmp; +} + +static CPpmd_Void_Ref CutOff(CPpmd8 *p, CTX_PTR ctx, unsigned order) +{ + int i; + unsigned tmp; + CPpmd_State *s; + + if (!ctx->NumStats) + { + s = ONE_STATE(ctx); + if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) >= p->UnitsStart) + { + if (order < p->MaxOrder) + SetSuccessor(s, CutOff(p, CTX(SUCCESSOR(s)), order + 1)); + else + SetSuccessor(s, 0); + if (SUCCESSOR(s) || order <= 9) /* O_BOUND */ + return REF(ctx); + } + SpecialFreeUnit(p, ctx); + return 0; + } + + ctx->Stats = STATS_REF(MoveUnitsUp(p, STATS(ctx), tmp = ((unsigned)ctx->NumStats + 2) >> 1)); + + for (s = STATS(ctx) + (i = ctx->NumStats); s >= STATS(ctx); s--) + if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) < p->UnitsStart) + { + CPpmd_State *s2 = STATS(ctx) + (i--); + SetSuccessor(s, 0); + SwapStates(s, s2); + } + else if (order < p->MaxOrder) + SetSuccessor(s, CutOff(p, CTX(SUCCESSOR(s)), order + 1)); + else + SetSuccessor(s, 0); + + if (i != ctx->NumStats && order) + { + ctx->NumStats = (Byte)i; + s = STATS(ctx); + if (i < 0) + { + FreeUnits(p, s, tmp); + SpecialFreeUnit(p, ctx); + return 0; + } + if (i == 0) + { + ctx->Flags = (Byte)((ctx->Flags & 0x10) + 0x08 * (s->Symbol >= 0x40)); + *ONE_STATE(ctx) = *s; + FreeUnits(p, s, tmp); + /* 9.31: the code was fixed. It's was not BUG, if Freq <= MAX_FREQ = 124 */ + ONE_STATE(ctx)->Freq = (Byte)(((unsigned)ONE_STATE(ctx)->Freq + 11) >> 3); + } + else + Refresh(p, ctx, tmp, ctx->SummFreq > 16 * i); + } + return REF(ctx); +} + +#ifdef PPMD8_FREEZE_SUPPORT +static CPpmd_Void_Ref RemoveBinContexts(CPpmd8 *p, CTX_PTR ctx, unsigned order) +{ + CPpmd_State *s; + if (!ctx->NumStats) + { + s = ONE_STATE(ctx); + if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) >= p->UnitsStart && order < p->MaxOrder) + SetSuccessor(s, RemoveBinContexts(p, CTX(SUCCESSOR(s)), order + 1)); + else + SetSuccessor(s, 0); + /* Suffix context can be removed already, since different (high-order) + Successors may refer to same context. So we check Flags == 0xFF (Stamp == EMPTY_NODE) */ + if (!SUCCESSOR(s) && (!SUFFIX(ctx)->NumStats || SUFFIX(ctx)->Flags == 0xFF)) + { + FreeUnits(p, ctx, 1); + return 0; + } + else + return REF(ctx); + } + + for (s = STATS(ctx) + ctx->NumStats; s >= STATS(ctx); s--) + if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) >= p->UnitsStart && order < p->MaxOrder) + SetSuccessor(s, RemoveBinContexts(p, CTX(SUCCESSOR(s)), order + 1)); + else + SetSuccessor(s, 0); + + return REF(ctx); +} +#endif + +static UInt32 GetUsedMemory(const CPpmd8 *p) +{ + UInt32 v = 0; + unsigned i; + for (i = 0; i < PPMD_NUM_INDEXES; i++) + v += p->Stamps[i] * I2U(i); + return p->Size - (UInt32)(p->HiUnit - p->LoUnit) - (UInt32)(p->UnitsStart - p->Text) - U2B(v); +} + +#ifdef PPMD8_FREEZE_SUPPORT + #define RESTORE_MODEL(c1, fSuccessor) RestoreModel(p, c1, fSuccessor) +#else + #define RESTORE_MODEL(c1, fSuccessor) RestoreModel(p, c1) +#endif + +static void RestoreModel(CPpmd8 *p, CTX_PTR c1 + #ifdef PPMD8_FREEZE_SUPPORT + , CTX_PTR fSuccessor + #endif + ) +{ + CTX_PTR c; + CPpmd_State *s; + RESET_TEXT(0); + for (c = p->MaxContext; c != c1; c = SUFFIX(c)) + if (--(c->NumStats) == 0) + { + s = STATS(c); + c->Flags = (Byte)((c->Flags & 0x10) + 0x08 * (s->Symbol >= 0x40)); + *ONE_STATE(c) = *s; + SpecialFreeUnit(p, s); + ONE_STATE(c)->Freq = (Byte)(((unsigned)ONE_STATE(c)->Freq + 11) >> 3); + } + else + Refresh(p, c, (c->NumStats+3) >> 1, 0); + + for (; c != p->MinContext; c = SUFFIX(c)) + if (!c->NumStats) + ONE_STATE(c)->Freq = (Byte)(ONE_STATE(c)->Freq - (ONE_STATE(c)->Freq >> 1)); + else if ((c->SummFreq += 4) > 128 + 4 * c->NumStats) + Refresh(p, c, (c->NumStats + 2) >> 1, 1); + + #ifdef PPMD8_FREEZE_SUPPORT + if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE) + { + p->MaxContext = fSuccessor; + p->GlueCount += !(p->Stamps[1] & 1); + } + else if (p->RestoreMethod == PPMD8_RESTORE_METHOD_FREEZE) + { + while (p->MaxContext->Suffix) + p->MaxContext = SUFFIX(p->MaxContext); + RemoveBinContexts(p, p->MaxContext, 0); + p->RestoreMethod++; + p->GlueCount = 0; + p->OrderFall = p->MaxOrder; + } + else + #endif + if (p->RestoreMethod == PPMD8_RESTORE_METHOD_RESTART || GetUsedMemory(p) < (p->Size >> 1)) + RestartModel(p); + else + { + while (p->MaxContext->Suffix) + p->MaxContext = SUFFIX(p->MaxContext); + do + { + CutOff(p, p->MaxContext, 0); + ExpandTextArea(p); + } + while (GetUsedMemory(p) > 3 * (p->Size >> 2)); + p->GlueCount = 0; + p->OrderFall = p->MaxOrder; + } +} + +static CTX_PTR CreateSuccessors(CPpmd8 *p, Bool skip, CPpmd_State *s1, CTX_PTR c) +{ + CPpmd_State upState; + Byte flags; + CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState); + /* fixed over Shkarin's code. Maybe it could work without + 1 too. */ + CPpmd_State *ps[PPMD8_MAX_ORDER + 1]; + unsigned numPs = 0; + + if (!skip) + ps[numPs++] = p->FoundState; + + while (c->Suffix) + { + CPpmd_Void_Ref successor; + CPpmd_State *s; + c = SUFFIX(c); + if (s1) + { + s = s1; + s1 = NULL; + } + else if (c->NumStats != 0) + { + for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++); + if (s->Freq < MAX_FREQ - 9) + { + s->Freq++; + c->SummFreq++; + } + } + else + { + s = ONE_STATE(c); + s->Freq = (Byte)(s->Freq + (!SUFFIX(c)->NumStats & (s->Freq < 24))); + } + successor = SUCCESSOR(s); + if (successor != upBranch) + { + c = CTX(successor); + if (numPs == 0) + return c; + break; + } + ps[numPs++] = s; + } + + upState.Symbol = *(const Byte *)Ppmd8_GetPtr(p, upBranch); + SetSuccessor(&upState, upBranch + 1); + flags = (Byte)(0x10 * (p->FoundState->Symbol >= 0x40) + 0x08 * (upState.Symbol >= 0x40)); + + if (c->NumStats == 0) + upState.Freq = ONE_STATE(c)->Freq; + else + { + UInt32 cf, s0; + CPpmd_State *s; + for (s = STATS(c); s->Symbol != upState.Symbol; s++); + cf = s->Freq - 1; + s0 = c->SummFreq - c->NumStats - cf; + upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((cf + 2 * s0 - 3) / s0))); + } + + do + { + /* Create Child */ + CTX_PTR c1; /* = AllocContext(p); */ + if (p->HiUnit != p->LoUnit) + c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); + else if (p->FreeList[0] != 0) + c1 = (CTX_PTR)RemoveNode(p, 0); + else + { + c1 = (CTX_PTR)AllocUnitsRare(p, 0); + if (!c1) + return NULL; + } + c1->NumStats = 0; + c1->Flags = flags; + *ONE_STATE(c1) = upState; + c1->Suffix = REF(c); + SetSuccessor(ps[--numPs], REF(c1)); + c = c1; + } + while (numPs != 0); + + return c; +} + +static CTX_PTR ReduceOrder(CPpmd8 *p, CPpmd_State *s1, CTX_PTR c) +{ + CPpmd_State *s = NULL; + CTX_PTR c1 = c; + CPpmd_Void_Ref upBranch = REF(p->Text); + + #ifdef PPMD8_FREEZE_SUPPORT + /* The BUG in Shkarin's code was fixed: ps could overflow in CUT_OFF mode. */ + CPpmd_State *ps[PPMD8_MAX_ORDER + 1]; + unsigned numPs = 0; + ps[numPs++] = p->FoundState; + #endif + + SetSuccessor(p->FoundState, upBranch); + p->OrderFall++; + + for (;;) + { + if (s1) + { + c = SUFFIX(c); + s = s1; + s1 = NULL; + } + else + { + if (!c->Suffix) + { + #ifdef PPMD8_FREEZE_SUPPORT + if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE) + { + do { SetSuccessor(ps[--numPs], REF(c)); } while (numPs); + RESET_TEXT(1); + p->OrderFall = 1; + } + #endif + return c; + } + c = SUFFIX(c); + if (c->NumStats) + { + if ((s = STATS(c))->Symbol != p->FoundState->Symbol) + do { s++; } while (s->Symbol != p->FoundState->Symbol); + if (s->Freq < MAX_FREQ - 9) + { + s->Freq += 2; + c->SummFreq += 2; + } + } + else + { + s = ONE_STATE(c); + s->Freq = (Byte)(s->Freq + (s->Freq < 32)); + } + } + if (SUCCESSOR(s)) + break; + #ifdef PPMD8_FREEZE_SUPPORT + ps[numPs++] = s; + #endif + SetSuccessor(s, upBranch); + p->OrderFall++; + } + + #ifdef PPMD8_FREEZE_SUPPORT + if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE) + { + c = CTX(SUCCESSOR(s)); + do { SetSuccessor(ps[--numPs], REF(c)); } while (numPs); + RESET_TEXT(1); + p->OrderFall = 1; + return c; + } + else + #endif + if (SUCCESSOR(s) <= upBranch) + { + CTX_PTR successor; + CPpmd_State *s2 = p->FoundState; + p->FoundState = s; + + successor = CreateSuccessors(p, False, NULL, c); + if (successor == NULL) + SetSuccessor(s, 0); + else + SetSuccessor(s, REF(successor)); + p->FoundState = s2; + } + + if (p->OrderFall == 1 && c1 == p->MaxContext) + { + SetSuccessor(p->FoundState, SUCCESSOR(s)); + p->Text--; + } + if (SUCCESSOR(s) == 0) + return NULL; + return CTX(SUCCESSOR(s)); +} + +static void UpdateModel(CPpmd8 *p) +{ + CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState); + CTX_PTR c; + unsigned s0, ns, fFreq = p->FoundState->Freq; + Byte flag, fSymbol = p->FoundState->Symbol; + CPpmd_State *s = NULL; + + if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0) + { + c = SUFFIX(p->MinContext); + + if (c->NumStats == 0) + { + s = ONE_STATE(c); + if (s->Freq < 32) + s->Freq++; + } + else + { + s = STATS(c); + if (s->Symbol != p->FoundState->Symbol) + { + do { s++; } while (s->Symbol != p->FoundState->Symbol); + if (s[0].Freq >= s[-1].Freq) + { + SwapStates(&s[0], &s[-1]); + s--; + } + } + if (s->Freq < MAX_FREQ - 9) + { + s->Freq += 2; + c->SummFreq += 2; + } + } + } + + c = p->MaxContext; + if (p->OrderFall == 0 && fSuccessor) + { + CTX_PTR cs = CreateSuccessors(p, True, s, p->MinContext); + if (cs == 0) + { + SetSuccessor(p->FoundState, 0); + RESTORE_MODEL(c, CTX(fSuccessor)); + } + else + { + SetSuccessor(p->FoundState, REF(cs)); + p->MaxContext = cs; + } + return; + } + + *p->Text++ = p->FoundState->Symbol; + successor = REF(p->Text); + if (p->Text >= p->UnitsStart) + { + RESTORE_MODEL(c, CTX(fSuccessor)); /* check it */ + return; + } + + if (!fSuccessor) + { + CTX_PTR cs = ReduceOrder(p, s, p->MinContext); + if (cs == NULL) + { + RESTORE_MODEL(c, 0); + return; + } + fSuccessor = REF(cs); + } + else if ((Byte *)Ppmd8_GetPtr(p, fSuccessor) < p->UnitsStart) + { + CTX_PTR cs = CreateSuccessors(p, False, s, p->MinContext); + if (cs == NULL) + { + RESTORE_MODEL(c, 0); + return; + } + fSuccessor = REF(cs); + } + + if (--p->OrderFall == 0) + { + successor = fSuccessor; + p->Text -= (p->MaxContext != p->MinContext); + } + #ifdef PPMD8_FREEZE_SUPPORT + else if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE) + { + successor = fSuccessor; + RESET_TEXT(0); + p->OrderFall = 0; + } + #endif + + s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - fFreq; + flag = (Byte)(0x08 * (fSymbol >= 0x40)); + + for (; c != p->MinContext; c = SUFFIX(c)) + { + unsigned ns1; + UInt32 cf, sf; + if ((ns1 = c->NumStats) != 0) + { + if ((ns1 & 1) != 0) + { + /* Expand for one UNIT */ + unsigned oldNU = (ns1 + 1) >> 1; + unsigned i = U2I(oldNU); + if (i != U2I(oldNU + 1)) + { + void *ptr = AllocUnits(p, i + 1); + void *oldPtr; + if (!ptr) + { + RESTORE_MODEL(c, CTX(fSuccessor)); + return; + } + oldPtr = STATS(c); + MyMem12Cpy(ptr, oldPtr, oldNU); + InsertNode(p, oldPtr, i); + c->Stats = STATS_REF(ptr); + } + } + c->SummFreq = (UInt16)(c->SummFreq + (3 * ns1 + 1 < ns)); + } + else + { + CPpmd_State *s2 = (CPpmd_State*)AllocUnits(p, 0); + if (!s2) + { + RESTORE_MODEL(c, CTX(fSuccessor)); + return; + } + *s2 = *ONE_STATE(c); + c->Stats = REF(s2); + if (s2->Freq < MAX_FREQ / 4 - 1) + s2->Freq <<= 1; + else + s2->Freq = MAX_FREQ - 4; + c->SummFreq = (UInt16)(s2->Freq + p->InitEsc + (ns > 2)); + } + cf = 2 * fFreq * (c->SummFreq + 6); + sf = (UInt32)s0 + c->SummFreq; + if (cf < 6 * sf) + { + cf = 1 + (cf > sf) + (cf >= 4 * sf); + c->SummFreq += 4; + } + else + { + cf = 4 + (cf > 9 * sf) + (cf > 12 * sf) + (cf > 15 * sf); + c->SummFreq = (UInt16)(c->SummFreq + cf); + } + { + CPpmd_State *s2 = STATS(c) + ns1 + 1; + SetSuccessor(s2, successor); + s2->Symbol = fSymbol; + s2->Freq = (Byte)cf; + c->Flags |= flag; + c->NumStats = (Byte)(ns1 + 1); + } + } + p->MaxContext = p->MinContext = CTX(fSuccessor); +} + +static void Rescale(CPpmd8 *p) +{ + unsigned i, adder, sumFreq, escFreq; + CPpmd_State *stats = STATS(p->MinContext); + CPpmd_State *s = p->FoundState; + { + CPpmd_State tmp = *s; + for (; s != stats; s--) + s[0] = s[-1]; + *s = tmp; + } + escFreq = p->MinContext->SummFreq - s->Freq; + s->Freq += 4; + adder = (p->OrderFall != 0 + #ifdef PPMD8_FREEZE_SUPPORT + || p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE + #endif + ); + s->Freq = (Byte)((s->Freq + adder) >> 1); + sumFreq = s->Freq; + + i = p->MinContext->NumStats; + do + { + escFreq -= (++s)->Freq; + s->Freq = (Byte)((s->Freq + adder) >> 1); + sumFreq += s->Freq; + if (s[0].Freq > s[-1].Freq) + { + CPpmd_State *s1 = s; + CPpmd_State tmp = *s1; + do + s1[0] = s1[-1]; + while (--s1 != stats && tmp.Freq > s1[-1].Freq); + *s1 = tmp; + } + } + while (--i); + + if (s->Freq == 0) + { + unsigned numStats = p->MinContext->NumStats; + unsigned n0, n1; + do { i++; } while ((--s)->Freq == 0); + escFreq += i; + p->MinContext->NumStats = (Byte)(p->MinContext->NumStats - i); + if (p->MinContext->NumStats == 0) + { + CPpmd_State tmp = *stats; + tmp.Freq = (Byte)((2 * tmp.Freq + escFreq - 1) / escFreq); + if (tmp.Freq > MAX_FREQ / 3) + tmp.Freq = MAX_FREQ / 3; + InsertNode(p, stats, U2I((numStats + 2) >> 1)); + p->MinContext->Flags = (Byte)((p->MinContext->Flags & 0x10) + 0x08 * (tmp.Symbol >= 0x40)); + *(p->FoundState = ONE_STATE(p->MinContext)) = tmp; + return; + } + n0 = (numStats + 2) >> 1; + n1 = (p->MinContext->NumStats + 2) >> 1; + if (n0 != n1) + p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1)); + p->MinContext->Flags &= ~0x08; + p->MinContext->Flags |= 0x08 * ((s = STATS(p->MinContext))->Symbol >= 0x40); + i = p->MinContext->NumStats; + do { p->MinContext->Flags |= 0x08*((++s)->Symbol >= 0x40); } while (--i); + } + p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1)); + p->MinContext->Flags |= 0x4; + p->FoundState = STATS(p->MinContext); +} + +CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked1, UInt32 *escFreq) +{ + CPpmd_See *see; + if (p->MinContext->NumStats != 0xFF) + { + see = p->See[(unsigned)p->NS2Indx[(unsigned)p->MinContext->NumStats + 2] - 3] + + (p->MinContext->SummFreq > 11 * ((unsigned)p->MinContext->NumStats + 1)) + + 2 * (unsigned)(2 * (unsigned)p->MinContext->NumStats < + ((unsigned)SUFFIX(p->MinContext)->NumStats + numMasked1)) + + p->MinContext->Flags; + { + unsigned r = (see->Summ >> see->Shift); + see->Summ = (UInt16)(see->Summ - r); + *escFreq = r + (r == 0); + } + } + else + { + see = &p->DummySee; + *escFreq = 1; + } + return see; +} + +static void NextContext(CPpmd8 *p) +{ + CTX_PTR c = CTX(SUCCESSOR(p->FoundState)); + if (p->OrderFall == 0 && (Byte *)c >= p->UnitsStart) + p->MinContext = p->MaxContext = c; + else + { + UpdateModel(p); + p->MinContext = p->MaxContext; + } +} + +void Ppmd8_Update1(CPpmd8 *p) +{ + CPpmd_State *s = p->FoundState; + s->Freq += 4; + p->MinContext->SummFreq += 4; + if (s[0].Freq > s[-1].Freq) + { + SwapStates(&s[0], &s[-1]); + p->FoundState = --s; + if (s->Freq > MAX_FREQ) + Rescale(p); + } + NextContext(p); +} + +void Ppmd8_Update1_0(CPpmd8 *p) +{ + p->PrevSuccess = (2 * p->FoundState->Freq >= p->MinContext->SummFreq); + p->RunLength += p->PrevSuccess; + p->MinContext->SummFreq += 4; + if ((p->FoundState->Freq += 4) > MAX_FREQ) + Rescale(p); + NextContext(p); +} + +void Ppmd8_UpdateBin(CPpmd8 *p) +{ + p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 196)); + p->PrevSuccess = 1; + p->RunLength++; + NextContext(p); +} + +void Ppmd8_Update2(CPpmd8 *p) +{ + p->MinContext->SummFreq += 4; + if ((p->FoundState->Freq += 4) > MAX_FREQ) + Rescale(p); + p->RunLength = p->InitRL; + UpdateModel(p); + p->MinContext = p->MaxContext; +} + +/* Ppmd8Dec.c -- PPMdI Decoder +2010-04-16 : Igor Pavlov : Public domain +This code is based on: + PPMd var.I (2002): Dmitry Shkarin : Public domain + Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ + +Bool Ppmd8_RangeDec_Init(CPpmd8 *p) +{ + unsigned i; + p->Low = 0; + p->Range = 0xFFFFFFFF; + p->Code = 0; + for (i = 0; i < 4; i++) + p->Code = (p->Code << 8) | p->Stream.In->Read(p->Stream.In); + return (p->Code < 0xFFFFFFFF); +} + +static UInt32 RangeDec_GetThreshold(CPpmd8 *p, UInt32 total) +{ + return p->Code / (p->Range /= total); +} + +static void RangeDec_Decode(CPpmd8 *p, UInt32 start, UInt32 size) +{ + start *= p->Range; + p->Low += start; + p->Code -= start; + p->Range *= size; + + while ((p->Low ^ (p->Low + p->Range)) < kTop || + (p->Range < kBot && ((p->Range = (0 - p->Low) & (kBot - 1)), 1))) + { + p->Code = (p->Code << 8) | p->Stream.In->Read(p->Stream.In); + p->Range <<= 8; + p->Low <<= 8; + } +} + +#define MASK(sym) ((signed char *)charMask)[sym] + +int Ppmd8_DecodeSymbol(CPpmd8 *p) +{ + size_t charMask[256 / sizeof(size_t)]; + if (p->MinContext->NumStats != 0) + { + CPpmd_State *s = Ppmd8_GetStats(p, p->MinContext); + unsigned i; + UInt32 count, hiCnt; + if ((count = RangeDec_GetThreshold(p, p->MinContext->SummFreq)) < (hiCnt = s->Freq)) + { + Byte symbol; + RangeDec_Decode(p, 0, s->Freq); + p->FoundState = s; + symbol = s->Symbol; + Ppmd8_Update1_0(p); + return symbol; + } + p->PrevSuccess = 0; + i = p->MinContext->NumStats; + do + { + if ((hiCnt += (++s)->Freq) > count) + { + Byte symbol; + RangeDec_Decode(p, hiCnt - s->Freq, s->Freq); + p->FoundState = s; + symbol = s->Symbol; + Ppmd8_Update1(p); + return symbol; + } + } + while (--i); + if (count >= p->MinContext->SummFreq) + return -2; + RangeDec_Decode(p, hiCnt, p->MinContext->SummFreq - hiCnt); + PPMD_SetAllBitsIn256Bytes(charMask); + MASK(s->Symbol) = 0; + i = p->MinContext->NumStats; + do { MASK((--s)->Symbol) = 0; } while (--i); + } + else + { + UInt16 *prob = Ppmd8_GetBinSumm(p); + if (((p->Code / (p->Range >>= 14)) < *prob)) + { + Byte symbol; + RangeDec_Decode(p, 0, *prob); + *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob); + symbol = (p->FoundState = Ppmd8Context_OneState(p->MinContext))->Symbol; + Ppmd8_UpdateBin(p); + return symbol; + } + RangeDec_Decode(p, *prob, (1 << 14) - *prob); + *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob); + p->InitEsc = PPMD8_kExpEscape[*prob >> 10]; + PPMD_SetAllBitsIn256Bytes(charMask); + MASK(Ppmd8Context_OneState(p->MinContext)->Symbol) = 0; + p->PrevSuccess = 0; + } + for (;;) + { + CPpmd_State *ps[256], *s; + UInt32 freqSum, count, hiCnt; + CPpmd_See *see; + unsigned i, num, numMasked = p->MinContext->NumStats; + do + { + p->OrderFall++; + if (!p->MinContext->Suffix) + return -1; + p->MinContext = Ppmd8_GetContext(p, p->MinContext->Suffix); + } + while (p->MinContext->NumStats == numMasked); + hiCnt = 0; + s = Ppmd8_GetStats(p, p->MinContext); + i = 0; + num = p->MinContext->NumStats - numMasked; + do + { + int k = (int)(MASK(s->Symbol)); + hiCnt += (s->Freq & k); + ps[i] = s++; + i -= k; + } + while (i != num); + + see = Ppmd8_MakeEscFreq(p, numMasked, &freqSum); + freqSum += hiCnt; + count = RangeDec_GetThreshold(p, freqSum); + + if (count < hiCnt) + { + Byte symbol; + CPpmd_State **pps = ps; + for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++); + s = *pps; + RangeDec_Decode(p, hiCnt - s->Freq, s->Freq); + Ppmd_See_Update(see); + p->FoundState = s; + symbol = s->Symbol; + Ppmd8_Update2(p); + return symbol; + } + if (count >= freqSum) + return -2; + RangeDec_Decode(p, hiCnt, freqSum - hiCnt); + see->Summ = (UInt16)(see->Summ + freqSum); + do { MASK(ps[--i]->Symbol) = 0; } while (i != 0); + } +} + +/* H->I changes: + NS2Indx + GlewCount, and Glue method + BinSum + See / EscFreq + CreateSuccessors updates more suffix contexts + UpdateModel consts. + PrevSuccess Update +*/ + +const IPpmd8 __archive_ppmd8_functions = +{ + &Ppmd8_Construct, + &Ppmd8_Alloc, + &Ppmd8_Free, + &Ppmd8_Init, + &Ppmd8_RangeDec_Init, + &Ppmd8_DecodeSymbol, +}; diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_ppmd8_private.h b/dependencies/libarchive-3.4.2/libarchive/archive_ppmd8_private.h new file mode 100644 index 0000000..454b75f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_ppmd8_private.h @@ -0,0 +1,148 @@ +/* Ppmd8.h -- PPMdI codec +2011-01-27 : Igor Pavlov : Public domain +This code is based on: + PPMd var.I (2002): Dmitry Shkarin : Public domain + Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ + +#ifndef ARCHIVE_PPMD8_PRIVATE_H_INCLUDED +#define ARCHIVE_PPMD8_PRIVATE_H_INCLUDED + +#include "archive_ppmd_private.h" + +#define PPMD8_MIN_ORDER 2 +#define PPMD8_MAX_ORDER 16 + +struct CPpmd8_Context_; + +typedef + #ifdef PPMD_32BIT + struct CPpmd8_Context_ * + #else + UInt32 + #endif + CPpmd8_Context_Ref; + +#pragma pack(push, 1) + +typedef struct CPpmd8_Context_ +{ + Byte NumStats; + Byte Flags; + UInt16 SummFreq; + CPpmd_State_Ref Stats; + CPpmd8_Context_Ref Suffix; +} CPpmd8_Context; + +#pragma pack(pop) + +#define Ppmd8Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq) + +/* The BUG in Shkarin's code for FREEZE mode was fixed, but that fixed + code is not compatible with original code for some files compressed + in FREEZE mode. So we disable FREEZE mode support. */ + +enum +{ + PPMD8_RESTORE_METHOD_RESTART, + PPMD8_RESTORE_METHOD_CUT_OFF + #ifdef PPMD8_FREEZE_SUPPORT + , PPMD8_RESTORE_METHOD_FREEZE + #endif +}; + +typedef struct +{ + CPpmd8_Context *MinContext, *MaxContext; + CPpmd_State *FoundState; + unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder; + Int32 RunLength, InitRL; /* must be 32-bit at least */ + + UInt32 Size; + UInt32 GlueCount; + Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart; + UInt32 AlignOffset; + unsigned RestoreMethod; + + /* Range Coder */ + UInt32 Range; + UInt32 Code; + UInt32 Low; + union + { + IByteIn *In; + IByteOut *Out; + } Stream; + + Byte Indx2Units[PPMD_NUM_INDEXES]; + Byte Units2Indx[128]; + CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES]; + UInt32 Stamps[PPMD_NUM_INDEXES]; + + Byte NS2BSIndx[256], NS2Indx[260]; + CPpmd_See DummySee, See[24][32]; + UInt16 BinSumm[25][64]; +} CPpmd8; + +void Ppmd8_Construct(CPpmd8 *p); +Bool Ppmd8_Alloc(CPpmd8 *p, UInt32 size); +void Ppmd8_Free(CPpmd8 *p); +void Ppmd8_Init(CPpmd8 *p, unsigned maxOrder, unsigned restoreMethod); +#define Ppmd8_WasAllocated(p) ((p)->Base != NULL) + + +/* ---------- Internal Functions ---------- */ + +extern const Byte PPMD8_kExpEscape[16]; + +#ifdef PPMD_32BIT + #define Ppmd8_GetPtr(p, ptr) (ptr) + #define Ppmd8_GetContext(p, ptr) (ptr) + #define Ppmd8_GetStats(p, ctx) ((ctx)->Stats) +#else + #define Ppmd8_GetPtr(p, offs) ((void *)((p)->Base + (offs))) + #define Ppmd8_GetContext(p, offs) ((CPpmd8_Context *)Ppmd8_GetPtr((p), (offs))) + #define Ppmd8_GetStats(p, ctx) ((CPpmd_State *)Ppmd8_GetPtr((p), ((ctx)->Stats))) +#endif + +void Ppmd8_Update1(CPpmd8 *p); +void Ppmd8_Update1_0(CPpmd8 *p); +void Ppmd8_Update2(CPpmd8 *p); +void Ppmd8_UpdateBin(CPpmd8 *p); + +#define Ppmd8_GetBinSumm(p) \ + &p->BinSumm[p->NS2Indx[Ppmd8Context_OneState(p->MinContext)->Freq - 1]][ \ + p->NS2BSIndx[Ppmd8_GetContext(p, p->MinContext->Suffix)->NumStats] + \ + p->PrevSuccess + p->MinContext->Flags + ((p->RunLength >> 26) & 0x20)] + +CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked, UInt32 *scale); + + +/* ---------- Decode ---------- */ + +Bool Ppmd8_RangeDec_Init(CPpmd8 *p); +#define Ppmd8_RangeDec_IsFinishedOK(p) ((p)->Code == 0) +int Ppmd8_DecodeSymbol(CPpmd8 *p); /* returns: -1 as EndMarker, -2 as DataError */ + +/* ---------- Encode ---------- */ + +#define Ppmd8_RangeEnc_Init(p) { (p)->Low = 0; (p)->Range = 0xFFFFFFFF; } +void Ppmd8_RangeEnc_FlushData(CPpmd8 *p); +void Ppmd8_EncodeSymbol(CPpmd8 *p, int symbol); /* symbol = -1 means EndMarker */ + +typedef struct +{ + /* Base Functions */ + void (*Ppmd8_Construct)(CPpmd8 *p); + Bool (*Ppmd8_Alloc)(CPpmd8 *p, UInt32 size); + void (*Ppmd8_Free)(CPpmd8 *p); + void (*Ppmd8_Init)(CPpmd8 *p, unsigned max_order, unsigned restore_method); + #define Ppmd7_WasAllocated(p) ((p)->Base != NULL) + + /* Decode Functions */ + int (*Ppmd8_RangeDec_Init)(CPpmd8 *p); + int (*Ppmd8_DecodeSymbol)(CPpmd8 *p); +} IPpmd8; + +extern const IPpmd8 __archive_ppmd8_functions; + +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_ppmd_private.h b/dependencies/libarchive-3.4.2/libarchive/archive_ppmd_private.h new file mode 100644 index 0000000..582803e --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_ppmd_private.h @@ -0,0 +1,151 @@ +/* Ppmd.h -- PPMD codec common code +2010-03-12 : Igor Pavlov : Public domain +This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ + +#ifndef ARCHIVE_PPMD_PRIVATE_H_INCLUDED +#define ARCHIVE_PPMD_PRIVATE_H_INCLUDED + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif + +#include + +#include "archive_read_private.h" + +/*** Begin defined in Types.h ***/ + +#if !defined(ZCONF_H) +typedef unsigned char Byte; +#endif +typedef short Int16; +typedef unsigned short UInt16; + +#ifdef _LZMA_UINT32_IS_ULONG +typedef long Int32; +typedef unsigned long UInt32; +#else +typedef int Int32; +typedef unsigned int UInt32; +#endif + +#ifdef _SZ_NO_INT_64 + +/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. + NOTES: Some code will work incorrectly in that case! */ + +typedef long Int64; +typedef unsigned long UInt64; + +#else + +#if defined(_MSC_VER) || defined(__BORLANDC__) +typedef __int64 Int64; +typedef unsigned __int64 UInt64; +#define UINT64_CONST(n) n +#else +typedef long long int Int64; +typedef unsigned long long int UInt64; +#define UINT64_CONST(n) n ## ULL +#endif + +#endif + +typedef int Bool; +#define True 1 +#define False 0 + +/* The following interfaces use first parameter as pointer to structure */ + +typedef struct +{ + struct archive_read *a; + Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */ +} IByteIn; + +typedef struct +{ + struct archive_write *a; + void (*Write)(void *p, Byte b); +} IByteOut; + +/*** End defined in Types.h ***/ +/*** Begin defined in CpuArch.h ***/ + +#if defined(_M_IX86) || defined(__i386__) +#define MY_CPU_X86 +#endif + +#if defined(MY_CPU_X86) || defined(_M_ARM) +#define MY_CPU_32BIT +#endif + +#ifdef MY_CPU_32BIT +#define PPMD_32BIT +#endif + +/*** End defined in CpuArch.h ***/ + +#define PPMD_INT_BITS 7 +#define PPMD_PERIOD_BITS 7 +#define PPMD_BIN_SCALE (1 << (PPMD_INT_BITS + PPMD_PERIOD_BITS)) + +#define PPMD_GET_MEAN_SPEC(summ, shift, round) (((summ) + (1 << ((shift) - (round)))) >> (shift)) +#define PPMD_GET_MEAN(summ) PPMD_GET_MEAN_SPEC((summ), PPMD_PERIOD_BITS, 2) +#define PPMD_UPDATE_PROB_0(prob) ((prob) + (1 << PPMD_INT_BITS) - PPMD_GET_MEAN(prob)) +#define PPMD_UPDATE_PROB_1(prob) ((prob) - PPMD_GET_MEAN(prob)) + +#define PPMD_N1 4 +#define PPMD_N2 4 +#define PPMD_N3 4 +#define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * PPMD_N3) / 4) +#define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4) + +/* SEE-contexts for PPM-contexts with masked symbols */ +typedef struct +{ + UInt16 Summ; /* Freq */ + Byte Shift; /* Speed of Freq change; low Shift is for fast change */ + Byte Count; /* Count to next change of Shift */ +} CPpmd_See; + +#define Ppmd_See_Update(p) if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \ + { (p)->Summ <<= 1; (p)->Count = (Byte)(3 << (p)->Shift++); } + +typedef struct +{ + Byte Symbol; + Byte Freq; + UInt16 SuccessorLow; + UInt16 SuccessorHigh; +} CPpmd_State; + +typedef + #ifdef PPMD_32BIT + CPpmd_State * + #else + UInt32 + #endif + CPpmd_State_Ref; + +typedef + #ifdef PPMD_32BIT + void * + #else + UInt32 + #endif + CPpmd_Void_Ref; + +typedef + #ifdef PPMD_32BIT + Byte * + #else + UInt32 + #endif + CPpmd_Byte_Ref; + +#define PPMD_SetAllBitsIn256Bytes(p) \ + { unsigned j; for (j = 0; j < 256 / sizeof(p[0]); j += 8) { \ + p[j+7] = p[j+6] = p[j+5] = p[j+4] = p[j+3] = p[j+2] = p[j+1] = p[j+0] = ~(size_t)0; }} + +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_private.h b/dependencies/libarchive-3.4.2/libarchive/archive_private.h new file mode 100644 index 0000000..937a87b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_private.h @@ -0,0 +1,176 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: head/lib/libarchive/archive_private.h 201098 2009-12-28 02:58:14Z kientzle $ + */ + +#ifndef ARCHIVE_PRIVATE_H_INCLUDED +#define ARCHIVE_PRIVATE_H_INCLUDED + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif + +#if HAVE_ICONV_H +#include +#endif + +#include "archive.h" +#include "archive_string.h" + +#if defined(__GNUC__) && (__GNUC__ > 2 || \ + (__GNUC__ == 2 && __GNUC_MINOR__ >= 5)) +#define __LA_DEAD __attribute__((__noreturn__)) +#else +#define __LA_DEAD +#endif + +#define ARCHIVE_WRITE_MAGIC (0xb0c5c0deU) +#define ARCHIVE_READ_MAGIC (0xdeb0c5U) +#define ARCHIVE_WRITE_DISK_MAGIC (0xc001b0c5U) +#define ARCHIVE_READ_DISK_MAGIC (0xbadb0c5U) +#define ARCHIVE_MATCH_MAGIC (0xcad11c9U) + +#define ARCHIVE_STATE_NEW 1U +#define ARCHIVE_STATE_HEADER 2U +#define ARCHIVE_STATE_DATA 4U +#define ARCHIVE_STATE_EOF 0x10U +#define ARCHIVE_STATE_CLOSED 0x20U +#define ARCHIVE_STATE_FATAL 0x8000U +#define ARCHIVE_STATE_ANY (0xFFFFU & ~ARCHIVE_STATE_FATAL) + +struct archive_vtable { + int (*archive_close)(struct archive *); + int (*archive_free)(struct archive *); + int (*archive_write_header)(struct archive *, + struct archive_entry *); + int (*archive_write_finish_entry)(struct archive *); + ssize_t (*archive_write_data)(struct archive *, + const void *, size_t); + ssize_t (*archive_write_data_block)(struct archive *, + const void *, size_t, int64_t); + + int (*archive_read_next_header)(struct archive *, + struct archive_entry **); + int (*archive_read_next_header2)(struct archive *, + struct archive_entry *); + int (*archive_read_data_block)(struct archive *, + const void **, size_t *, int64_t *); + + int (*archive_filter_count)(struct archive *); + int64_t (*archive_filter_bytes)(struct archive *, int); + int (*archive_filter_code)(struct archive *, int); + const char * (*archive_filter_name)(struct archive *, int); +}; + +struct archive_string_conv; + +struct archive { + /* + * The magic/state values are used to sanity-check the + * client's usage. If an API function is called at a + * ridiculous time, or the client passes us an invalid + * pointer, these values allow me to catch that. + */ + unsigned int magic; + unsigned int state; + + /* + * Some public API functions depend on the "real" type of the + * archive object. + */ + struct archive_vtable *vtable; + + int archive_format; + const char *archive_format_name; + + int compression_code; /* Currently active compression. */ + const char *compression_name; + + /* Number of file entries processed. */ + int file_count; + + int archive_error_number; + const char *error; + struct archive_string error_string; + + char *current_code; + unsigned current_codepage; /* Current ACP(ANSI CodePage). */ + unsigned current_oemcp; /* Current OEMCP(OEM CodePage). */ + struct archive_string_conv *sconv; + + /* + * Used by archive_read_data() to track blocks and copy + * data to client buffers, filling gaps with zero bytes. + */ + const char *read_data_block; + int64_t read_data_offset; + int64_t read_data_output_offset; + size_t read_data_remaining; + + /* + * Used by formats/filters to determine the amount of data + * requested from a call to archive_read_data(). This is only + * useful when the format/filter has seek support. + */ + char read_data_is_posix_read; + size_t read_data_requested; +}; + +/* Check magic value and state; return(ARCHIVE_FATAL) if it isn't valid. */ +int __archive_check_magic(struct archive *, unsigned int magic, + unsigned int state, const char *func); +#define archive_check_magic(a, expected_magic, allowed_states, function_name) \ + do { \ + int magic_test = __archive_check_magic((a), (expected_magic), \ + (allowed_states), (function_name)); \ + if (magic_test == ARCHIVE_FATAL) \ + return ARCHIVE_FATAL; \ + } while (0) + +void __archive_errx(int retvalue, const char *msg) __LA_DEAD; + +void __archive_ensure_cloexec_flag(int fd); +int __archive_mktemp(const char *tmpdir); +#if defined(_WIN32) && !defined(__CYGWIN__) +int __archive_mkstemp(wchar_t *template); +#else +int __archive_mkstemp(char *template); +#endif + +int __archive_clean(struct archive *); + +void __archive_reset_read_data(struct archive *); + +#define err_combine(a,b) ((a) < (b) ? (a) : (b)) + +#if defined(__BORLANDC__) || (defined(_MSC_VER) && _MSC_VER <= 1300) +# define ARCHIVE_LITERAL_LL(x) x##i64 +# define ARCHIVE_LITERAL_ULL(x) x##ui64 +#else +# define ARCHIVE_LITERAL_LL(x) x##ll +# define ARCHIVE_LITERAL_ULL(x) x##ull +#endif + +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_random.c b/dependencies/libarchive-3.4.2/libarchive/archive_random.c new file mode 100644 index 0000000..65ea691 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_random.c @@ -0,0 +1,272 @@ +/*- + * Copyright (c) 2014 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_STDLIB_H +#include +#endif + +#if !defined(HAVE_ARC4RANDOM_BUF) && (!defined(_WIN32) || defined(__CYGWIN__)) + +#ifdef HAVE_FCNTL +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_PTHREAD_H +#include +#endif + +static void arc4random_buf(void *, size_t); + +#endif /* HAVE_ARC4RANDOM_BUF */ + +#include "archive.h" +#include "archive_random_private.h" + +#if defined(HAVE_WINCRYPT_H) && !defined(__CYGWIN__) +#include +#endif + +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + +/* + * Random number generator function. + * This simply calls arc4random_buf function if the platform provides it. + */ + +int +archive_random(void *buf, size_t nbytes) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + HCRYPTPROV hProv; + BOOL success; + + success = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT); + if (!success && GetLastError() == (DWORD)NTE_BAD_KEYSET) { + success = CryptAcquireContext(&hProv, NULL, NULL, + PROV_RSA_FULL, CRYPT_NEWKEYSET); + } + if (success) { + success = CryptGenRandom(hProv, (DWORD)nbytes, (BYTE*)buf); + CryptReleaseContext(hProv, 0); + if (success) + return ARCHIVE_OK; + } + /* TODO: Does this case really happen? */ + return ARCHIVE_FAILED; +#else + arc4random_buf(buf, nbytes); + return ARCHIVE_OK; +#endif +} + +#if !defined(HAVE_ARC4RANDOM_BUF) && (!defined(_WIN32) || defined(__CYGWIN__)) + +/* $OpenBSD: arc4random.c,v 1.24 2013/06/11 16:59:50 deraadt Exp $ */ +/* + * Copyright (c) 1996, David Mazieres + * Copyright (c) 2008, Damien Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Arc4 random number generator for OpenBSD. + * + * This code is derived from section 17.1 of Applied Cryptography, + * second edition, which describes a stream cipher allegedly + * compatible with RSA Labs "RC4" cipher (the actual description of + * which is a trade secret). The same algorithm is used as a stream + * cipher called "arcfour" in Tatu Ylonen's ssh package. + * + * RC4 is a registered trademark of RSA Laboratories. + */ + +#ifdef __GNUC__ +#define inline __inline +#else /* !__GNUC__ */ +#define inline +#endif /* !__GNUC__ */ + +struct arc4_stream { + uint8_t i; + uint8_t j; + uint8_t s[256]; +}; + +#define RANDOMDEV "/dev/urandom" +#define KEYSIZE 128 +#ifdef HAVE_PTHREAD_H +static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER; +#define _ARC4_LOCK() pthread_mutex_lock(&arc4random_mtx); +#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx); +#else +#define _ARC4_LOCK() +#define _ARC4_UNLOCK() +#endif + +static int rs_initialized; +static struct arc4_stream rs; +static pid_t arc4_stir_pid; +static int arc4_count; + +static inline uint8_t arc4_getbyte(void); +static void arc4_stir(void); + +static inline void +arc4_init(void) +{ + int n; + + for (n = 0; n < 256; n++) + rs.s[n] = n; + rs.i = 0; + rs.j = 0; +} + +static inline void +arc4_addrandom(u_char *dat, int datlen) +{ + int n; + uint8_t si; + + rs.i--; + for (n = 0; n < 256; n++) { + rs.i = (rs.i + 1); + si = rs.s[rs.i]; + rs.j = (rs.j + si + dat[n % datlen]); + rs.s[rs.i] = rs.s[rs.j]; + rs.s[rs.j] = si; + } + rs.j = rs.i; +} + +static void +arc4_stir(void) +{ + int done, fd, i; + struct { + struct timeval tv; + pid_t pid; + u_char rnd[KEYSIZE]; + } rdat; + + if (!rs_initialized) { + arc4_init(); + rs_initialized = 1; + } + done = 0; + fd = open(RANDOMDEV, O_RDONLY | O_CLOEXEC, 0); + if (fd >= 0) { + if (read(fd, &rdat, KEYSIZE) == KEYSIZE) + done = 1; + (void)close(fd); + } + if (!done) { + (void)gettimeofday(&rdat.tv, NULL); + rdat.pid = getpid(); + /* We'll just take whatever was on the stack too... */ + } + + arc4_addrandom((u_char *)&rdat, KEYSIZE); + + /* + * Discard early keystream, as per recommendations in: + * "(Not So) Random Shuffles of RC4" by Ilya Mironov. + * As per the Network Operations Division, cryptographic requirements + * published on wikileaks on March 2017. + */ + + for (i = 0; i < 3072; i++) + (void)arc4_getbyte(); + arc4_count = 1600000; +} + +static void +arc4_stir_if_needed(void) +{ + pid_t pid = getpid(); + + if (arc4_count <= 0 || !rs_initialized || arc4_stir_pid != pid) { + arc4_stir_pid = pid; + arc4_stir(); + } +} + +static inline uint8_t +arc4_getbyte(void) +{ + uint8_t si, sj; + + rs.i = (rs.i + 1); + si = rs.s[rs.i]; + rs.j = (rs.j + si); + sj = rs.s[rs.j]; + rs.s[rs.i] = sj; + rs.s[rs.j] = si; + return (rs.s[(si + sj) & 0xff]); +} + +static void +arc4random_buf(void *_buf, size_t n) +{ + u_char *buf = (u_char *)_buf; + _ARC4_LOCK(); + arc4_stir_if_needed(); + while (n--) { + if (--arc4_count <= 0) + arc4_stir(); + buf[n] = arc4_getbyte(); + } + _ARC4_UNLOCK(); +} + +#endif /* !HAVE_ARC4RANDOM_BUF */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_random_private.h b/dependencies/libarchive-3.4.2/libarchive/archive_random_private.h new file mode 100644 index 0000000..08b91b3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_random_private.h @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 2014 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ARCHIVE_RANDOM_PRIVATE_H_INCLUDED +#define ARCHIVE_RANDOM_PRIVATE_H_INCLUDED + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif + +/* Random number generator. */ +int archive_random(void *buf, size_t nbytes); + +#endif /* ARCHIVE_RANDOM_PRIVATE_H_INCLUDED */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_rb.c b/dependencies/libarchive-3.4.2/libarchive/archive_rb.c new file mode 100644 index 0000000..cf58ac3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_rb.c @@ -0,0 +1,709 @@ +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Matt Thomas . + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Based on: NetBSD: rb.c,v 1.6 2010/04/30 13:58:09 joerg Exp + */ + +#include "archive_platform.h" + +#include + +#include "archive_rb.h" + +/* Keep in sync with archive_rb.h */ +#define RB_DIR_LEFT 0 +#define RB_DIR_RIGHT 1 +#define RB_DIR_OTHER 1 +#define rb_left rb_nodes[RB_DIR_LEFT] +#define rb_right rb_nodes[RB_DIR_RIGHT] + +#define RB_FLAG_POSITION 0x2 +#define RB_FLAG_RED 0x1 +#define RB_FLAG_MASK (RB_FLAG_POSITION|RB_FLAG_RED) +#define RB_FATHER(rb) \ + ((struct archive_rb_node *)((rb)->rb_info & ~RB_FLAG_MASK)) +#define RB_SET_FATHER(rb, father) \ + ((void)((rb)->rb_info = (uintptr_t)(father)|((rb)->rb_info & RB_FLAG_MASK))) + +#define RB_SENTINEL_P(rb) ((rb) == NULL) +#define RB_LEFT_SENTINEL_P(rb) RB_SENTINEL_P((rb)->rb_left) +#define RB_RIGHT_SENTINEL_P(rb) RB_SENTINEL_P((rb)->rb_right) +#define RB_FATHER_SENTINEL_P(rb) RB_SENTINEL_P(RB_FATHER((rb))) +#define RB_CHILDLESS_P(rb) \ + (RB_SENTINEL_P(rb) || (RB_LEFT_SENTINEL_P(rb) && RB_RIGHT_SENTINEL_P(rb))) +#define RB_TWOCHILDREN_P(rb) \ + (!RB_SENTINEL_P(rb) && !RB_LEFT_SENTINEL_P(rb) && !RB_RIGHT_SENTINEL_P(rb)) + +#define RB_POSITION(rb) \ + (((rb)->rb_info & RB_FLAG_POSITION) ? RB_DIR_RIGHT : RB_DIR_LEFT) +#define RB_RIGHT_P(rb) (RB_POSITION(rb) == RB_DIR_RIGHT) +#define RB_LEFT_P(rb) (RB_POSITION(rb) == RB_DIR_LEFT) +#define RB_RED_P(rb) (!RB_SENTINEL_P(rb) && ((rb)->rb_info & RB_FLAG_RED) != 0) +#define RB_BLACK_P(rb) (RB_SENTINEL_P(rb) || ((rb)->rb_info & RB_FLAG_RED) == 0) +#define RB_MARK_RED(rb) ((void)((rb)->rb_info |= RB_FLAG_RED)) +#define RB_MARK_BLACK(rb) ((void)((rb)->rb_info &= ~RB_FLAG_RED)) +#define RB_INVERT_COLOR(rb) ((void)((rb)->rb_info ^= RB_FLAG_RED)) +#define RB_ROOT_P(rbt, rb) ((rbt)->rbt_root == (rb)) +#define RB_SET_POSITION(rb, position) \ + ((void)((position) ? ((rb)->rb_info |= RB_FLAG_POSITION) : \ + ((rb)->rb_info &= ~RB_FLAG_POSITION))) +#define RB_ZERO_PROPERTIES(rb) ((void)((rb)->rb_info &= ~RB_FLAG_MASK)) +#define RB_COPY_PROPERTIES(dst, src) \ + ((void)((dst)->rb_info ^= ((dst)->rb_info ^ (src)->rb_info) & RB_FLAG_MASK)) +#define RB_SWAP_PROPERTIES(a, b) do { \ + uintptr_t xorinfo = ((a)->rb_info ^ (b)->rb_info) & RB_FLAG_MASK; \ + (a)->rb_info ^= xorinfo; \ + (b)->rb_info ^= xorinfo; \ + } while (/*CONSTCOND*/ 0) + +static void __archive_rb_tree_insert_rebalance(struct archive_rb_tree *, + struct archive_rb_node *); +static void __archive_rb_tree_removal_rebalance(struct archive_rb_tree *, + struct archive_rb_node *, unsigned int); + +#define RB_SENTINEL_NODE NULL + +#define T 1 +#define F 0 + +void +__archive_rb_tree_init(struct archive_rb_tree *rbt, + const struct archive_rb_tree_ops *ops) +{ + rbt->rbt_ops = ops; + *((struct archive_rb_node **)&rbt->rbt_root) = RB_SENTINEL_NODE; +} + +struct archive_rb_node * +__archive_rb_tree_find_node(struct archive_rb_tree *rbt, const void *key) +{ + archive_rbto_compare_key_fn compare_key = rbt->rbt_ops->rbto_compare_key; + struct archive_rb_node *parent = rbt->rbt_root; + + while (!RB_SENTINEL_P(parent)) { + const signed int diff = (*compare_key)(parent, key); + if (diff == 0) + return parent; + parent = parent->rb_nodes[diff > 0]; + } + + return NULL; +} + +struct archive_rb_node * +__archive_rb_tree_find_node_geq(struct archive_rb_tree *rbt, const void *key) +{ + archive_rbto_compare_key_fn compare_key = rbt->rbt_ops->rbto_compare_key; + struct archive_rb_node *parent = rbt->rbt_root; + struct archive_rb_node *last = NULL; + + while (!RB_SENTINEL_P(parent)) { + const signed int diff = (*compare_key)(parent, key); + if (diff == 0) + return parent; + if (diff < 0) + last = parent; + parent = parent->rb_nodes[diff > 0]; + } + + return last; +} + +struct archive_rb_node * +__archive_rb_tree_find_node_leq(struct archive_rb_tree *rbt, const void *key) +{ + archive_rbto_compare_key_fn compare_key = rbt->rbt_ops->rbto_compare_key; + struct archive_rb_node *parent = rbt->rbt_root; + struct archive_rb_node *last = NULL; + + while (!RB_SENTINEL_P(parent)) { + const signed int diff = (*compare_key)(parent, key); + if (diff == 0) + return parent; + if (diff > 0) + last = parent; + parent = parent->rb_nodes[diff > 0]; + } + + return last; +} + +int +__archive_rb_tree_insert_node(struct archive_rb_tree *rbt, + struct archive_rb_node *self) +{ + archive_rbto_compare_nodes_fn compare_nodes = rbt->rbt_ops->rbto_compare_nodes; + struct archive_rb_node *parent, *tmp; + unsigned int position; + int rebalance; + + tmp = rbt->rbt_root; + /* + * This is a hack. Because rbt->rbt_root is just a + * struct archive_rb_node *, just like rb_node->rb_nodes[RB_DIR_LEFT], + * we can use this fact to avoid a lot of tests for root and know + * that even at root, updating + * RB_FATHER(rb_node)->rb_nodes[RB_POSITION(rb_node)] will + * update rbt->rbt_root. + */ + parent = (struct archive_rb_node *)(void *)&rbt->rbt_root; + position = RB_DIR_LEFT; + + /* + * Find out where to place this new leaf. + */ + while (!RB_SENTINEL_P(tmp)) { + const signed int diff = (*compare_nodes)(tmp, self); + if (diff == 0) { + /* + * Node already exists; don't insert. + */ + return F; + } + parent = tmp; + position = (diff > 0); + tmp = parent->rb_nodes[position]; + } + + /* + * Initialize the node and insert as a leaf into the tree. + */ + RB_SET_FATHER(self, parent); + RB_SET_POSITION(self, position); + if (parent == (struct archive_rb_node *)(void *)&rbt->rbt_root) { + RB_MARK_BLACK(self); /* root is always black */ + rebalance = F; + } else { + /* + * All new nodes are colored red. We only need to rebalance + * if our parent is also red. + */ + RB_MARK_RED(self); + rebalance = RB_RED_P(parent); + } + self->rb_left = parent->rb_nodes[position]; + self->rb_right = parent->rb_nodes[position]; + parent->rb_nodes[position] = self; + + /* + * Rebalance tree after insertion + */ + if (rebalance) + __archive_rb_tree_insert_rebalance(rbt, self); + + return T; +} + +/* + * Swap the location and colors of 'self' and its child @ which. The child + * can not be a sentinel node. This is our rotation function. However, + * since it preserves coloring, it great simplifies both insertion and + * removal since rotation almost always involves the exchanging of colors + * as a separate step. + */ +/*ARGSUSED*/ +static void +__archive_rb_tree_reparent_nodes( + struct archive_rb_node *old_father, const unsigned int which) +{ + const unsigned int other = which ^ RB_DIR_OTHER; + struct archive_rb_node * const grandpa = RB_FATHER(old_father); + struct archive_rb_node * const old_child = old_father->rb_nodes[which]; + struct archive_rb_node * const new_father = old_child; + struct archive_rb_node * const new_child = old_father; + + if (new_father == NULL) + return; + /* + * Exchange descendant linkages. + */ + grandpa->rb_nodes[RB_POSITION(old_father)] = new_father; + new_child->rb_nodes[which] = old_child->rb_nodes[other]; + new_father->rb_nodes[other] = new_child; + + /* + * Update ancestor linkages + */ + RB_SET_FATHER(new_father, grandpa); + RB_SET_FATHER(new_child, new_father); + + /* + * Exchange properties between new_father and new_child. The only + * change is that new_child's position is now on the other side. + */ + RB_SWAP_PROPERTIES(new_father, new_child); + RB_SET_POSITION(new_child, other); + + /* + * Make sure to reparent the new child to ourself. + */ + if (!RB_SENTINEL_P(new_child->rb_nodes[which])) { + RB_SET_FATHER(new_child->rb_nodes[which], new_child); + RB_SET_POSITION(new_child->rb_nodes[which], which); + } + +} + +static void +__archive_rb_tree_insert_rebalance(struct archive_rb_tree *rbt, + struct archive_rb_node *self) +{ + struct archive_rb_node * father = RB_FATHER(self); + struct archive_rb_node * grandpa; + struct archive_rb_node * uncle; + unsigned int which; + unsigned int other; + + for (;;) { + /* + * We are red and our parent is red, therefore we must have a + * grandfather and he must be black. + */ + grandpa = RB_FATHER(father); + which = (father == grandpa->rb_right); + other = which ^ RB_DIR_OTHER; + uncle = grandpa->rb_nodes[other]; + + if (RB_BLACK_P(uncle)) + break; + + /* + * Case 1: our uncle is red + * Simply invert the colors of our parent and + * uncle and make our grandparent red. And + * then solve the problem up at his level. + */ + RB_MARK_BLACK(uncle); + RB_MARK_BLACK(father); + if (RB_ROOT_P(rbt, grandpa)) { + /* + * If our grandpa is root, don't bother + * setting him to red, just return. + */ + return; + } + RB_MARK_RED(grandpa); + self = grandpa; + father = RB_FATHER(self); + if (RB_BLACK_P(father)) { + /* + * If our great-grandpa is black, we're done. + */ + return; + } + } + + /* + * Case 2&3: our uncle is black. + */ + if (self == father->rb_nodes[other]) { + /* + * Case 2: we are on the same side as our uncle + * Swap ourselves with our parent so this case + * becomes case 3. Basically our parent becomes our + * child. + */ + __archive_rb_tree_reparent_nodes(father, other); + } + /* + * Case 3: we are opposite a child of a black uncle. + * Swap our parent and grandparent. Since our grandfather + * is black, our father will become black and our new sibling + * (former grandparent) will become red. + */ + __archive_rb_tree_reparent_nodes(grandpa, which); + + /* + * Final step: Set the root to black. + */ + RB_MARK_BLACK(rbt->rbt_root); +} + +static void +__archive_rb_tree_prune_node(struct archive_rb_tree *rbt, + struct archive_rb_node *self, int rebalance) +{ + const unsigned int which = RB_POSITION(self); + struct archive_rb_node *father = RB_FATHER(self); + + /* + * Since we are childless, we know that self->rb_left is pointing + * to the sentinel node. + */ + father->rb_nodes[which] = self->rb_left; + + /* + * Rebalance if requested. + */ + if (rebalance) + __archive_rb_tree_removal_rebalance(rbt, father, which); +} + +/* + * When deleting an interior node + */ +static void +__archive_rb_tree_swap_prune_and_rebalance(struct archive_rb_tree *rbt, + struct archive_rb_node *self, struct archive_rb_node *standin) +{ + const unsigned int standin_which = RB_POSITION(standin); + unsigned int standin_other = standin_which ^ RB_DIR_OTHER; + struct archive_rb_node *standin_son; + struct archive_rb_node *standin_father = RB_FATHER(standin); + int rebalance = RB_BLACK_P(standin); + + if (standin_father == self) { + /* + * As a child of self, any children would be opposite of + * our parent. + */ + standin_son = standin->rb_nodes[standin_which]; + } else { + /* + * Since we aren't a child of self, any children would be + * on the same side as our parent. + */ + standin_son = standin->rb_nodes[standin_other]; + } + + if (RB_RED_P(standin_son)) { + /* + * We know we have a red child so if we flip it to black + * we don't have to rebalance. + */ + RB_MARK_BLACK(standin_son); + rebalance = F; + + if (standin_father != self) { + /* + * Change the son's parentage to point to his grandpa. + */ + RB_SET_FATHER(standin_son, standin_father); + RB_SET_POSITION(standin_son, standin_which); + } + } + + if (standin_father == self) { + /* + * If we are about to delete the standin's father, then when + * we call rebalance, we need to use ourselves as our father. + * Otherwise remember our original father. Also, since we are + * our standin's father we only need to reparent the standin's + * brother. + * + * | R --> S | + * | Q S --> Q T | + * | t --> | + * + * Have our son/standin adopt his brother as his new son. + */ + standin_father = standin; + } else { + /* + * | R --> S . | + * | / \ | T --> / \ | / | + * | ..... | S --> ..... | T | + * + * Sever standin's connection to his father. + */ + standin_father->rb_nodes[standin_which] = standin_son; + /* + * Adopt the far son. + */ + standin->rb_nodes[standin_other] = self->rb_nodes[standin_other]; + RB_SET_FATHER(standin->rb_nodes[standin_other], standin); + /* + * Use standin_other because we need to preserve standin_which + * for the removal_rebalance. + */ + standin_other = standin_which; + } + + /* + * Move the only remaining son to our standin. If our standin is our + * son, this will be the only son needed to be moved. + */ + standin->rb_nodes[standin_other] = self->rb_nodes[standin_other]; + RB_SET_FATHER(standin->rb_nodes[standin_other], standin); + + /* + * Now copy the result of self to standin and then replace + * self with standin in the tree. + */ + RB_COPY_PROPERTIES(standin, self); + RB_SET_FATHER(standin, RB_FATHER(self)); + RB_FATHER(standin)->rb_nodes[RB_POSITION(standin)] = standin; + + if (rebalance) + __archive_rb_tree_removal_rebalance(rbt, standin_father, standin_which); +} + +/* + * We could do this by doing + * __archive_rb_tree_node_swap(rbt, self, which); + * __archive_rb_tree_prune_node(rbt, self, F); + * + * But it's more efficient to just evaluate and recolor the child. + */ +static void +__archive_rb_tree_prune_blackred_branch( + struct archive_rb_node *self, unsigned int which) +{ + struct archive_rb_node *father = RB_FATHER(self); + struct archive_rb_node *son = self->rb_nodes[which]; + + /* + * Remove ourselves from the tree and give our former child our + * properties (position, color, root). + */ + RB_COPY_PROPERTIES(son, self); + father->rb_nodes[RB_POSITION(son)] = son; + RB_SET_FATHER(son, father); +} +/* + * + */ +void +__archive_rb_tree_remove_node(struct archive_rb_tree *rbt, + struct archive_rb_node *self) +{ + struct archive_rb_node *standin; + unsigned int which; + + /* + * In the following diagrams, we (the node to be removed) are S. Red + * nodes are lowercase. T could be either red or black. + * + * Remember the major axiom of the red-black tree: the number of + * black nodes from the root to each leaf is constant across all + * leaves, only the number of red nodes varies. + * + * Thus removing a red leaf doesn't require any other changes to a + * red-black tree. So if we must remove a node, attempt to rearrange + * the tree so we can remove a red node. + * + * The simplest case is a childless red node or a childless root node: + * + * | T --> T | or | R --> * | + * | s --> * | + */ + if (RB_CHILDLESS_P(self)) { + const int rebalance = RB_BLACK_P(self) && !RB_ROOT_P(rbt, self); + __archive_rb_tree_prune_node(rbt, self, rebalance); + return; + } + if (!RB_TWOCHILDREN_P(self)) { + /* + * The next simplest case is the node we are deleting is + * black and has one red child. + * + * | T --> T --> T | + * | S --> R --> R | + * | r --> s --> * | + */ + which = RB_LEFT_SENTINEL_P(self) ? RB_DIR_RIGHT : RB_DIR_LEFT; + __archive_rb_tree_prune_blackred_branch(self, which); + return; + } + + /* + * We invert these because we prefer to remove from the inside of + * the tree. + */ + which = RB_POSITION(self) ^ RB_DIR_OTHER; + + /* + * Let's find the node closes to us opposite of our parent + * Now swap it with ourself, "prune" it, and rebalance, if needed. + */ + standin = __archive_rb_tree_iterate(rbt, self, which); + __archive_rb_tree_swap_prune_and_rebalance(rbt, self, standin); +} + +static void +__archive_rb_tree_removal_rebalance(struct archive_rb_tree *rbt, + struct archive_rb_node *parent, unsigned int which) +{ + + while (RB_BLACK_P(parent->rb_nodes[which])) { + unsigned int other = which ^ RB_DIR_OTHER; + struct archive_rb_node *brother = parent->rb_nodes[other]; + + if (brother == NULL) + return;/* The tree may be broken. */ + /* + * For cases 1, 2a, and 2b, our brother's children must + * be black and our father must be black + */ + if (RB_BLACK_P(parent) + && RB_BLACK_P(brother->rb_left) + && RB_BLACK_P(brother->rb_right)) { + if (RB_RED_P(brother)) { + /* + * Case 1: Our brother is red, swap its + * position (and colors) with our parent. + * This should now be case 2b (unless C or E + * has a red child which is case 3; thus no + * explicit branch to case 2b). + * + * B -> D + * A d -> b E + * C E -> A C + */ + __archive_rb_tree_reparent_nodes(parent, other); + brother = parent->rb_nodes[other]; + if (brother == NULL) + return;/* The tree may be broken. */ + } else { + /* + * Both our parent and brother are black. + * Change our brother to red, advance up rank + * and go through the loop again. + * + * B -> *B + * *A D -> A d + * C E -> C E + */ + RB_MARK_RED(brother); + if (RB_ROOT_P(rbt, parent)) + return; /* root == parent == black */ + which = RB_POSITION(parent); + parent = RB_FATHER(parent); + continue; + } + } + /* + * Avoid an else here so that case 2a above can hit either + * case 2b, 3, or 4. + */ + if (RB_RED_P(parent) + && RB_BLACK_P(brother) + && RB_BLACK_P(brother->rb_left) + && RB_BLACK_P(brother->rb_right)) { + /* + * We are black, our father is red, our brother and + * both nephews are black. Simply invert/exchange the + * colors of our father and brother (to black and red + * respectively). + * + * | f --> F | + * | * B --> * b | + * | N N --> N N | + */ + RB_MARK_BLACK(parent); + RB_MARK_RED(brother); + break; /* We're done! */ + } else { + /* + * Our brother must be black and have at least one + * red child (it may have two). + */ + if (RB_BLACK_P(brother->rb_nodes[other])) { + /* + * Case 3: our brother is black, our near + * nephew is red, and our far nephew is black. + * Swap our brother with our near nephew. + * This result in a tree that matches case 4. + * (Our father could be red or black). + * + * | F --> F | + * | x B --> x B | + * | n --> n | + */ + __archive_rb_tree_reparent_nodes(brother, which); + brother = parent->rb_nodes[other]; + } + /* + * Case 4: our brother is black and our far nephew + * is red. Swap our father and brother locations and + * change our far nephew to black. (these can be + * done in either order so we change the color first). + * The result is a valid red-black tree and is a + * terminal case. (again we don't care about the + * father's color) + * + * If the father is red, we will get a red-black-black + * tree: + * | f -> f --> b | + * | B -> B --> F N | + * | n -> N --> | + * + * If the father is black, we will get an all black + * tree: + * | F -> F --> B | + * | B -> B --> F N | + * | n -> N --> | + * + * If we had two red nephews, then after the swap, + * our former father would have a red grandson. + */ + if (brother->rb_nodes[other] == NULL) + return;/* The tree may be broken. */ + RB_MARK_BLACK(brother->rb_nodes[other]); + __archive_rb_tree_reparent_nodes(parent, other); + break; /* We're done! */ + } + } +} + +struct archive_rb_node * +__archive_rb_tree_iterate(struct archive_rb_tree *rbt, + struct archive_rb_node *self, const unsigned int direction) +{ + const unsigned int other = direction ^ RB_DIR_OTHER; + + if (self == NULL) { + self = rbt->rbt_root; + if (RB_SENTINEL_P(self)) + return NULL; + while (!RB_SENTINEL_P(self->rb_nodes[direction])) + self = self->rb_nodes[direction]; + return self; + } + /* + * We can't go any further in this direction. We proceed up in the + * opposite direction until our parent is in direction we want to go. + */ + if (RB_SENTINEL_P(self->rb_nodes[direction])) { + while (!RB_ROOT_P(rbt, self)) { + if (other == (unsigned int)RB_POSITION(self)) + return RB_FATHER(self); + self = RB_FATHER(self); + } + return NULL; + } + + /* + * Advance down one in current direction and go down as far as possible + * in the opposite direction. + */ + self = self->rb_nodes[direction]; + while (!RB_SENTINEL_P(self->rb_nodes[other])) + self = self->rb_nodes[other]; + return self; +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_rb.h b/dependencies/libarchive-3.4.2/libarchive/archive_rb.h new file mode 100644 index 0000000..8851f10 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_rb.h @@ -0,0 +1,113 @@ +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Matt Thomas . + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Based on NetBSD: rb.h,v 1.13 2009/08/16 10:57:01 yamt Exp + */ + +#ifndef ARCHIVE_RB_H_INCLUDED +#define ARCHIVE_RB_H_INCLUDED + +struct archive_rb_node { + struct archive_rb_node *rb_nodes[2]; + /* + * rb_info contains the two flags and the parent back pointer. + * We put the two flags in the low two bits since we know that + * rb_node will have an alignment of 4 or 8 bytes. + */ + uintptr_t rb_info; +}; + +#define ARCHIVE_RB_DIR_LEFT 0 +#define ARCHIVE_RB_DIR_RIGHT 1 + +#define ARCHIVE_RB_TREE_MIN(T) \ + __archive_rb_tree_iterate((T), NULL, ARCHIVE_RB_DIR_LEFT) +#define ARCHIVE_RB_TREE_MAX(T) \ + __archive_rb_tree_iterate((T), NULL, ARCHIVE_RB_DIR_RIGHT) +#define ARCHIVE_RB_TREE_NEXT(T, N) \ + __archive_rb_tree_iterate((T), (N), ARCHIVE_RB_DIR_RIGHT) +#define ARCHIVE_RB_TREE_PREV(T, N) \ + __archive_rb_tree_iterate((T), (N), ARCHIVE_RB_DIR_LEFT) +#define ARCHIVE_RB_TREE_FOREACH(N, T) \ + for ((N) = ARCHIVE_RB_TREE_MIN(T); (N); \ + (N) = ARCHIVE_RB_TREE_NEXT((T), (N))) +#define ARCHIVE_RB_TREE_FOREACH_REVERSE(N, T) \ + for ((N) = ARCHIVE_RB_TREE_MAX(T); (N); \ + (N) = ARCHIVE_RB_TREE_PREV((T), (N))) +#define ARCHIVE_RB_TREE_FOREACH_SAFE(N, T, S) \ + for ((N) = ARCHIVE_RB_TREE_MIN(T); \ + (N) && ((S) = ARCHIVE_RB_TREE_NEXT((T), (N)), 1); \ + (N) = (S)) +#define ARCHIVE_RB_TREE_FOREACH_REVERSE_SAFE(N, T, S) \ + for ((N) = ARCHIVE_RB_TREE_MAX(T); \ + (N) && ((S) = ARCHIVE_RB_TREE_PREV((T), (N)), 1); \ + (N) = (S)) + +/* + * archive_rbto_compare_nodes_fn: + * return a positive value if the first node < the second node. + * return a negative value if the first node > the second node. + * return 0 if they are considered same. + * + * archive_rbto_compare_key_fn: + * return a positive value if the node < the key. + * return a negative value if the node > the key. + * return 0 if they are considered same. + */ + +typedef signed int (*const archive_rbto_compare_nodes_fn)(const struct archive_rb_node *, + const struct archive_rb_node *); +typedef signed int (*const archive_rbto_compare_key_fn)(const struct archive_rb_node *, + const void *); + +struct archive_rb_tree_ops { + archive_rbto_compare_nodes_fn rbto_compare_nodes; + archive_rbto_compare_key_fn rbto_compare_key; +}; + +struct archive_rb_tree { + struct archive_rb_node *rbt_root; + const struct archive_rb_tree_ops *rbt_ops; +}; + +void __archive_rb_tree_init(struct archive_rb_tree *, + const struct archive_rb_tree_ops *); +int __archive_rb_tree_insert_node(struct archive_rb_tree *, + struct archive_rb_node *); +struct archive_rb_node * + __archive_rb_tree_find_node(struct archive_rb_tree *, const void *); +struct archive_rb_node * + __archive_rb_tree_find_node_geq(struct archive_rb_tree *, const void *); +struct archive_rb_node * + __archive_rb_tree_find_node_leq(struct archive_rb_tree *, const void *); +void __archive_rb_tree_remove_node(struct archive_rb_tree *, struct archive_rb_node *); +struct archive_rb_node * + __archive_rb_tree_iterate(struct archive_rb_tree *, + struct archive_rb_node *, const unsigned int); + +#endif /* ARCHIVE_RB_H_*/ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read.3 b/dependencies/libarchive-3.4.2/libarchive/archive_read.3 new file mode 100644 index 0000000..cbedd0a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read.3 @@ -0,0 +1,252 @@ +.\" Copyright (c) 2003-2007 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 2, 2012 +.Dt ARCHIVE_READ 3 +.Os +.Sh NAME +.Nm archive_read +.Nd functions for reading streaming archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive.h +.Sh DESCRIPTION +These functions provide a complete API for reading streaming archives. +The general process is to first create the +.Tn struct archive +object, set options, initialize the reader, iterate over the archive +headers and associated data, then close the archive and release all +resources. +.\" +.Ss Create archive object +See +.Xr archive_read_new 3 . +.Pp +To read an archive, you must first obtain an initialized +.Tn struct archive +object from +.Fn archive_read_new . +.\" +.Ss Enable filters and formats +See +.Xr archive_read_filter 3 +and +.Xr archive_read_format 3 . +.Pp +You can then modify this object for the desired operations with the +various +.Fn archive_read_set_XXX +and +.Fn archive_read_support_XXX +functions. +In particular, you will need to invoke appropriate +.Fn archive_read_support_XXX +functions to enable the corresponding compression and format +support. +Note that these latter functions perform two distinct operations: +they cause the corresponding support code to be linked into your +program, and they enable the corresponding auto-detect code. +Unless you have specific constraints, you will generally want +to invoke +.Fn archive_read_support_filter_all +and +.Fn archive_read_support_format_all +to enable auto-detect for all formats and compression types +currently supported by the library. +.\" +.Ss Set options +See +.Xr archive_read_set_options 3 . +.\" +.Ss Open archive +See +.Xr archive_read_open 3 . +.Pp +Once you have prepared the +.Tn struct archive +object, you call +.Fn archive_read_open +to actually open the archive and prepare it for reading. +There are several variants of this function; +the most basic expects you to provide pointers to several +functions that can provide blocks of bytes from the archive. +There are convenience forms that allow you to +specify a filename, file descriptor, +.Ft "FILE *" +object, or a block of memory from which to read the archive data. +Note that the core library makes no assumptions about the +size of the blocks read; +callback functions are free to read whatever block size is +most appropriate for the medium. +.\" +.Ss Consume archive +See +.Xr archive_read_header 3 , +.Xr archive_read_data 3 +and +.Xr archive_read_extract 3 . +.Pp +Each archive entry consists of a header followed by a certain +amount of data. +You can obtain the next header with +.Fn archive_read_next_header , +which returns a pointer to an +.Tn struct archive_entry +structure with information about the current archive element. +If the entry is a regular file, then the header will be followed +by the file data. +You can use +.Fn archive_read_data +(which works much like the +.Xr read 2 +system call) +to read this data from the archive, or +.Fn archive_read_data_block +which provides a slightly more efficient interface. +You may prefer to use the higher-level +.Fn archive_read_data_skip , +which reads and discards the data for this entry, +.Fn archive_read_data_into_fd , +which copies the data to the provided file descriptor, or +.Fn archive_read_extract , +which recreates the specified entry on disk and copies data +from the archive. +In particular, note that +.Fn archive_read_extract +uses the +.Tn struct archive_entry +structure that you provide it, which may differ from the +entry just read from the archive. +In particular, many applications will want to override the +pathname, file permissions, or ownership. +.\" +.Ss Release resources +See +.Xr archive_read_free 3 . +.Pp +Once you have finished reading data from the archive, you +should call +.Fn archive_read_close +to close the archive, then call +.Fn archive_read_free +to release all resources, including all memory allocated by the library. +.\" +.Sh EXAMPLES +The following illustrates basic usage of the library. +In this example, +the callback functions are simply wrappers around the standard +.Xr open 2 , +.Xr read 2 , +and +.Xr close 2 +system calls. +.Bd -literal -offset indent +void +list_archive(const char *name) +{ + struct mydata *mydata; + struct archive *a; + struct archive_entry *entry; + + mydata = malloc(sizeof(struct mydata)); + a = archive_read_new(); + mydata->name = name; + archive_read_support_filter_all(a); + archive_read_support_format_all(a); + archive_read_open(a, mydata, myopen, myread, myclose); + while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { + printf("%s\en",archive_entry_pathname(entry)); + archive_read_data_skip(a); + } + archive_read_free(a); + free(mydata); +} + +la_ssize_t +myread(struct archive *a, void *client_data, const void **buff) +{ + struct mydata *mydata = client_data; + + *buff = mydata->buff; + return (read(mydata->fd, mydata->buff, 10240)); +} + +int +myopen(struct archive *a, void *client_data) +{ + struct mydata *mydata = client_data; + + mydata->fd = open(mydata->name, O_RDONLY); + return (mydata->fd >= 0 ? ARCHIVE_OK : ARCHIVE_FATAL); +} + +int +myclose(struct archive *a, void *client_data) +{ + struct mydata *mydata = client_data; + + if (mydata->fd > 0) + close(mydata->fd); + return (ARCHIVE_OK); +} +.Ed +.\" .Sh ERRORS +.Sh SEE ALSO +.Xr tar 1 , +.Xr archive_read_data 3 , +.Xr archive_read_extract 3 , +.Xr archive_read_filter 3 , +.Xr archive_read_format 3 , +.Xr archive_read_header 3 , +.Xr archive_read_new 3 , +.Xr archive_read_open 3 , +.Xr archive_read_set_options 3 , +.Xr archive_util 3 , +.Xr libarchive 3 , +.Xr tar 5 +.Sh HISTORY +The +.Nm libarchive +library first appeared in +.Fx 5.3 . +.Sh AUTHORS +.An -nosplit +The +.Nm libarchive +library was written by +.An Tim Kientzle Aq kientzle@acm.org . +.Sh BUGS +Many traditional archiver programs treat +empty files as valid empty archives. +For example, many implementations of +.Xr tar 1 +allow you to append entries to an empty file. +Of course, it is impossible to determine the format of an empty file +by inspecting the contents, so this library treats empty files as +having a special +.Dq empty +format. diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read.c b/dependencies/libarchive-3.4.2/libarchive/archive_read.c new file mode 100644 index 0000000..4a933b2 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read.c @@ -0,0 +1,1751 @@ +/*- + * Copyright (c) 2003-2011 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file contains the "essential" portions of the read API, that + * is, stuff that will probably always be used by any client that + * actually needs to read an archive. Optional pieces have been, as + * far as possible, separated out into separate files to avoid + * needlessly bloating statically-linked clients. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_read.c 201157 2009-12-29 05:30:23Z kientzle $"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_read_private.h" + +#define minimum(a, b) (a < b ? a : b) + +static int choose_filters(struct archive_read *); +static int choose_format(struct archive_read *); +static int close_filters(struct archive_read *); +static struct archive_vtable *archive_read_vtable(void); +static int64_t _archive_filter_bytes(struct archive *, int); +static int _archive_filter_code(struct archive *, int); +static const char *_archive_filter_name(struct archive *, int); +static int _archive_filter_count(struct archive *); +static int _archive_read_close(struct archive *); +static int _archive_read_data_block(struct archive *, + const void **, size_t *, int64_t *); +static int _archive_read_free(struct archive *); +static int _archive_read_next_header(struct archive *, + struct archive_entry **); +static int _archive_read_next_header2(struct archive *, + struct archive_entry *); +static int64_t advance_file_pointer(struct archive_read_filter *, int64_t); + +static struct archive_vtable * +archive_read_vtable(void) +{ + static struct archive_vtable av; + static int inited = 0; + + if (!inited) { + av.archive_filter_bytes = _archive_filter_bytes; + av.archive_filter_code = _archive_filter_code; + av.archive_filter_name = _archive_filter_name; + av.archive_filter_count = _archive_filter_count; + av.archive_read_data_block = _archive_read_data_block; + av.archive_read_next_header = _archive_read_next_header; + av.archive_read_next_header2 = _archive_read_next_header2; + av.archive_free = _archive_read_free; + av.archive_close = _archive_read_close; + inited = 1; + } + return (&av); +} + +/* + * Allocate, initialize and return a struct archive object. + */ +struct archive * +archive_read_new(void) +{ + struct archive_read *a; + + a = (struct archive_read *)calloc(1, sizeof(*a)); + if (a == NULL) + return (NULL); + a->archive.magic = ARCHIVE_READ_MAGIC; + + a->archive.state = ARCHIVE_STATE_NEW; + a->entry = archive_entry_new2(&a->archive); + a->archive.vtable = archive_read_vtable(); + + a->passphrases.last = &a->passphrases.first; + + return (&a->archive); +} + +/* + * Record the do-not-extract-to file. This belongs in archive_read_extract.c. + */ +void +archive_read_extract_set_skip_file(struct archive *_a, la_int64_t d, + la_int64_t i) +{ + struct archive_read *a = (struct archive_read *)_a; + + if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_ANY, "archive_read_extract_set_skip_file")) + return; + a->skip_file_set = 1; + a->skip_file_dev = d; + a->skip_file_ino = i; +} + +/* + * Open the archive + */ +int +archive_read_open(struct archive *a, void *client_data, + archive_open_callback *client_opener, archive_read_callback *client_reader, + archive_close_callback *client_closer) +{ + /* Old archive_read_open() is just a thin shell around + * archive_read_open1. */ + archive_read_set_open_callback(a, client_opener); + archive_read_set_read_callback(a, client_reader); + archive_read_set_close_callback(a, client_closer); + archive_read_set_callback_data(a, client_data); + return archive_read_open1(a); +} + + +int +archive_read_open2(struct archive *a, void *client_data, + archive_open_callback *client_opener, + archive_read_callback *client_reader, + archive_skip_callback *client_skipper, + archive_close_callback *client_closer) +{ + /* Old archive_read_open2() is just a thin shell around + * archive_read_open1. */ + archive_read_set_callback_data(a, client_data); + archive_read_set_open_callback(a, client_opener); + archive_read_set_read_callback(a, client_reader); + archive_read_set_skip_callback(a, client_skipper); + archive_read_set_close_callback(a, client_closer); + return archive_read_open1(a); +} + +static ssize_t +client_read_proxy(struct archive_read_filter *self, const void **buff) +{ + ssize_t r; + r = (self->archive->client.reader)(&self->archive->archive, + self->data, buff); + return (r); +} + +static int64_t +client_skip_proxy(struct archive_read_filter *self, int64_t request) +{ + if (request < 0) + __archive_errx(1, "Negative skip requested."); + if (request == 0) + return 0; + + if (self->archive->client.skipper != NULL) { + /* Seek requests over 1GiB are broken down into + * multiple seeks. This avoids overflows when the + * requests get passed through 32-bit arguments. */ + int64_t skip_limit = (int64_t)1 << 30; + int64_t total = 0; + for (;;) { + int64_t get, ask = request; + if (ask > skip_limit) + ask = skip_limit; + get = (self->archive->client.skipper) + (&self->archive->archive, self->data, ask); + total += get; + if (get == 0 || get == request) + return (total); + if (get > request) + return ARCHIVE_FATAL; + request -= get; + } + } else if (self->archive->client.seeker != NULL + && request > 64 * 1024) { + /* If the client provided a seeker but not a skipper, + * we can use the seeker to skip forward. + * + * Note: This isn't always a good idea. The client + * skipper is allowed to skip by less than requested + * if it needs to maintain block alignment. The + * seeker is not allowed to play such games, so using + * the seeker here may be a performance loss compared + * to just reading and discarding. That's why we + * only do this for skips of over 64k. + */ + int64_t before = self->position; + int64_t after = (self->archive->client.seeker) + (&self->archive->archive, self->data, request, SEEK_CUR); + if (after != before + request) + return ARCHIVE_FATAL; + return after - before; + } + return 0; +} + +static int64_t +client_seek_proxy(struct archive_read_filter *self, int64_t offset, int whence) +{ + /* DO NOT use the skipper here! If we transparently handled + * forward seek here by using the skipper, that will break + * other libarchive code that assumes a successful forward + * seek means it can also seek backwards. + */ + if (self->archive->client.seeker == NULL) { + archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, + "Current client reader does not support seeking a device"); + return (ARCHIVE_FAILED); + } + return (self->archive->client.seeker)(&self->archive->archive, + self->data, offset, whence); +} + +static int +client_close_proxy(struct archive_read_filter *self) +{ + int r = ARCHIVE_OK, r2; + unsigned int i; + + if (self->archive->client.closer == NULL) + return (r); + for (i = 0; i < self->archive->client.nodes; i++) + { + r2 = (self->archive->client.closer) + ((struct archive *)self->archive, + self->archive->client.dataset[i].data); + if (r > r2) + r = r2; + } + return (r); +} + +static int +client_open_proxy(struct archive_read_filter *self) +{ + int r = ARCHIVE_OK; + if (self->archive->client.opener != NULL) + r = (self->archive->client.opener)( + (struct archive *)self->archive, self->data); + return (r); +} + +static int +client_switch_proxy(struct archive_read_filter *self, unsigned int iindex) +{ + int r1 = ARCHIVE_OK, r2 = ARCHIVE_OK; + void *data2 = NULL; + + /* Don't do anything if already in the specified data node */ + if (self->archive->client.cursor == iindex) + return (ARCHIVE_OK); + + self->archive->client.cursor = iindex; + data2 = self->archive->client.dataset[self->archive->client.cursor].data; + if (self->archive->client.switcher != NULL) + { + r1 = r2 = (self->archive->client.switcher) + ((struct archive *)self->archive, self->data, data2); + self->data = data2; + } + else + { + /* Attempt to call close and open instead */ + if (self->archive->client.closer != NULL) + r1 = (self->archive->client.closer) + ((struct archive *)self->archive, self->data); + self->data = data2; + if (self->archive->client.opener != NULL) + r2 = (self->archive->client.opener) + ((struct archive *)self->archive, self->data); + } + return (r1 < r2) ? r1 : r2; +} + +int +archive_read_set_open_callback(struct archive *_a, + archive_open_callback *client_opener) +{ + struct archive_read *a = (struct archive_read *)_a; + archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, + "archive_read_set_open_callback"); + a->client.opener = client_opener; + return ARCHIVE_OK; +} + +int +archive_read_set_read_callback(struct archive *_a, + archive_read_callback *client_reader) +{ + struct archive_read *a = (struct archive_read *)_a; + archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, + "archive_read_set_read_callback"); + a->client.reader = client_reader; + return ARCHIVE_OK; +} + +int +archive_read_set_skip_callback(struct archive *_a, + archive_skip_callback *client_skipper) +{ + struct archive_read *a = (struct archive_read *)_a; + archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, + "archive_read_set_skip_callback"); + a->client.skipper = client_skipper; + return ARCHIVE_OK; +} + +int +archive_read_set_seek_callback(struct archive *_a, + archive_seek_callback *client_seeker) +{ + struct archive_read *a = (struct archive_read *)_a; + archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, + "archive_read_set_seek_callback"); + a->client.seeker = client_seeker; + return ARCHIVE_OK; +} + +int +archive_read_set_close_callback(struct archive *_a, + archive_close_callback *client_closer) +{ + struct archive_read *a = (struct archive_read *)_a; + archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, + "archive_read_set_close_callback"); + a->client.closer = client_closer; + return ARCHIVE_OK; +} + +int +archive_read_set_switch_callback(struct archive *_a, + archive_switch_callback *client_switcher) +{ + struct archive_read *a = (struct archive_read *)_a; + archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, + "archive_read_set_switch_callback"); + a->client.switcher = client_switcher; + return ARCHIVE_OK; +} + +int +archive_read_set_callback_data(struct archive *_a, void *client_data) +{ + return archive_read_set_callback_data2(_a, client_data, 0); +} + +int +archive_read_set_callback_data2(struct archive *_a, void *client_data, + unsigned int iindex) +{ + struct archive_read *a = (struct archive_read *)_a; + archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, + "archive_read_set_callback_data2"); + + if (a->client.nodes == 0) + { + a->client.dataset = (struct archive_read_data_node *) + calloc(1, sizeof(*a->client.dataset)); + if (a->client.dataset == NULL) + { + archive_set_error(&a->archive, ENOMEM, + "No memory."); + return ARCHIVE_FATAL; + } + a->client.nodes = 1; + } + + if (iindex > a->client.nodes - 1) + { + archive_set_error(&a->archive, EINVAL, + "Invalid index specified."); + return ARCHIVE_FATAL; + } + a->client.dataset[iindex].data = client_data; + a->client.dataset[iindex].begin_position = -1; + a->client.dataset[iindex].total_size = -1; + return ARCHIVE_OK; +} + +int +archive_read_add_callback_data(struct archive *_a, void *client_data, + unsigned int iindex) +{ + struct archive_read *a = (struct archive_read *)_a; + void *p; + unsigned int i; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, + "archive_read_add_callback_data"); + if (iindex > a->client.nodes) { + archive_set_error(&a->archive, EINVAL, + "Invalid index specified."); + return ARCHIVE_FATAL; + } + p = realloc(a->client.dataset, sizeof(*a->client.dataset) + * (++(a->client.nodes))); + if (p == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory."); + return ARCHIVE_FATAL; + } + a->client.dataset = (struct archive_read_data_node *)p; + for (i = a->client.nodes - 1; i > iindex; i--) { + a->client.dataset[i].data = a->client.dataset[i-1].data; + a->client.dataset[i].begin_position = -1; + a->client.dataset[i].total_size = -1; + } + a->client.dataset[iindex].data = client_data; + a->client.dataset[iindex].begin_position = -1; + a->client.dataset[iindex].total_size = -1; + return ARCHIVE_OK; +} + +int +archive_read_append_callback_data(struct archive *_a, void *client_data) +{ + struct archive_read *a = (struct archive_read *)_a; + return archive_read_add_callback_data(_a, client_data, a->client.nodes); +} + +int +archive_read_prepend_callback_data(struct archive *_a, void *client_data) +{ + return archive_read_add_callback_data(_a, client_data, 0); +} + +int +archive_read_open1(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter *filter, *tmp; + int slot, e = ARCHIVE_OK; + unsigned int i; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, + "archive_read_open"); + archive_clear_error(&a->archive); + + if (a->client.reader == NULL) { + archive_set_error(&a->archive, EINVAL, + "No reader function provided to archive_read_open"); + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } + + /* Open data source. */ + if (a->client.opener != NULL) { + e = (a->client.opener)(&a->archive, a->client.dataset[0].data); + if (e != 0) { + /* If the open failed, call the closer to clean up. */ + if (a->client.closer) { + for (i = 0; i < a->client.nodes; i++) + (a->client.closer)(&a->archive, + a->client.dataset[i].data); + } + return (e); + } + } + + filter = calloc(1, sizeof(*filter)); + if (filter == NULL) + return (ARCHIVE_FATAL); + filter->bidder = NULL; + filter->upstream = NULL; + filter->archive = a; + filter->data = a->client.dataset[0].data; + filter->open = client_open_proxy; + filter->read = client_read_proxy; + filter->skip = client_skip_proxy; + filter->seek = client_seek_proxy; + filter->close = client_close_proxy; + filter->sswitch = client_switch_proxy; + filter->name = "none"; + filter->code = ARCHIVE_FILTER_NONE; + + a->client.dataset[0].begin_position = 0; + if (!a->filter || !a->bypass_filter_bidding) + { + a->filter = filter; + /* Build out the input pipeline. */ + e = choose_filters(a); + if (e < ARCHIVE_WARN) { + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } + } + else + { + /* Need to add "NONE" type filter at the end of the filter chain */ + tmp = a->filter; + while (tmp->upstream) + tmp = tmp->upstream; + tmp->upstream = filter; + } + + if (!a->format) + { + slot = choose_format(a); + if (slot < 0) { + close_filters(a); + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } + a->format = &(a->formats[slot]); + } + + a->archive.state = ARCHIVE_STATE_HEADER; + + /* Ensure libarchive starts from the first node in a multivolume set */ + client_switch_proxy(a->filter, 0); + return (e); +} + +/* + * Allow each registered stream transform to bid on whether + * it wants to handle this stream. Repeat until we've finished + * building the pipeline. + */ + +/* We won't build a filter pipeline with more stages than this. */ +#define MAX_NUMBER_FILTERS 25 + +static int +choose_filters(struct archive_read *a) +{ + int number_bidders, i, bid, best_bid, number_filters; + struct archive_read_filter_bidder *bidder, *best_bidder; + struct archive_read_filter *filter; + ssize_t avail; + int r; + + for (number_filters = 0; number_filters < MAX_NUMBER_FILTERS; ++number_filters) { + number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]); + + best_bid = 0; + best_bidder = NULL; + + bidder = a->bidders; + for (i = 0; i < number_bidders; i++, bidder++) { + if (bidder->bid != NULL) { + bid = (bidder->bid)(bidder, a->filter); + if (bid > best_bid) { + best_bid = bid; + best_bidder = bidder; + } + } + } + + /* If no bidder, we're done. */ + if (best_bidder == NULL) { + /* Verify the filter by asking it for some data. */ + __archive_read_filter_ahead(a->filter, 1, &avail); + if (avail < 0) { + __archive_read_free_filters(a); + return (ARCHIVE_FATAL); + } + a->archive.compression_name = a->filter->name; + a->archive.compression_code = a->filter->code; + return (ARCHIVE_OK); + } + + filter + = (struct archive_read_filter *)calloc(1, sizeof(*filter)); + if (filter == NULL) + return (ARCHIVE_FATAL); + filter->bidder = best_bidder; + filter->archive = a; + filter->upstream = a->filter; + a->filter = filter; + r = (best_bidder->init)(a->filter); + if (r != ARCHIVE_OK) { + __archive_read_free_filters(a); + return (ARCHIVE_FATAL); + } + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Input requires too many filters for decoding"); + return (ARCHIVE_FATAL); +} + +int +__archive_read_header(struct archive_read *a, struct archive_entry *entry) +{ + if (a->filter->read_header) + return a->filter->read_header(a->filter, entry); + else + return (ARCHIVE_OK); +} + +/* + * Read header of next entry. + */ +static int +_archive_read_next_header2(struct archive *_a, struct archive_entry *entry) +{ + struct archive_read *a = (struct archive_read *)_a; + int r1 = ARCHIVE_OK, r2; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_read_next_header"); + + archive_entry_clear(entry); + archive_clear_error(&a->archive); + + /* + * If client didn't consume entire data, skip any remainder + * (This is especially important for GNU incremental directories.) + */ + if (a->archive.state == ARCHIVE_STATE_DATA) { + r1 = archive_read_data_skip(&a->archive); + if (r1 == ARCHIVE_EOF) + archive_set_error(&a->archive, EIO, + "Premature end-of-file."); + if (r1 == ARCHIVE_EOF || r1 == ARCHIVE_FATAL) { + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } + } + + /* Record start-of-header offset in uncompressed stream. */ + a->header_position = a->filter->position; + + ++_a->file_count; + r2 = (a->format->read_header)(a, entry); + + /* + * EOF and FATAL are persistent at this layer. By + * modifying the state, we guarantee that future calls to + * read a header or read data will fail. + */ + switch (r2) { + case ARCHIVE_EOF: + a->archive.state = ARCHIVE_STATE_EOF; + --_a->file_count;/* Revert a file counter. */ + break; + case ARCHIVE_OK: + a->archive.state = ARCHIVE_STATE_DATA; + break; + case ARCHIVE_WARN: + a->archive.state = ARCHIVE_STATE_DATA; + break; + case ARCHIVE_RETRY: + break; + case ARCHIVE_FATAL: + a->archive.state = ARCHIVE_STATE_FATAL; + break; + } + + __archive_reset_read_data(&a->archive); + + a->data_start_node = a->client.cursor; + /* EOF always wins; otherwise return the worst error. */ + return (r2 < r1 || r2 == ARCHIVE_EOF) ? r2 : r1; +} + +static int +_archive_read_next_header(struct archive *_a, struct archive_entry **entryp) +{ + int ret; + struct archive_read *a = (struct archive_read *)_a; + *entryp = NULL; + ret = _archive_read_next_header2(_a, a->entry); + *entryp = a->entry; + return ret; +} + +/* + * Allow each registered format to bid on whether it wants to handle + * the next entry. Return index of winning bidder. + */ +static int +choose_format(struct archive_read *a) +{ + int slots; + int i; + int bid, best_bid; + int best_bid_slot; + + slots = sizeof(a->formats) / sizeof(a->formats[0]); + best_bid = -1; + best_bid_slot = -1; + + /* Set up a->format for convenience of bidders. */ + a->format = &(a->formats[0]); + for (i = 0; i < slots; i++, a->format++) { + if (a->format->bid) { + bid = (a->format->bid)(a, best_bid); + if (bid == ARCHIVE_FATAL) + return (ARCHIVE_FATAL); + if (a->filter->position != 0) + __archive_read_seek(a, 0, SEEK_SET); + if ((bid > best_bid) || (best_bid_slot < 0)) { + best_bid = bid; + best_bid_slot = i; + } + } + } + + /* + * There were no bidders; this is a serious programmer error + * and demands a quick and definitive abort. + */ + if (best_bid_slot < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "No formats registered"); + return (ARCHIVE_FATAL); + } + + /* + * There were bidders, but no non-zero bids; this means we + * can't support this stream. + */ + if (best_bid < 1) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Unrecognized archive format"); + return (ARCHIVE_FATAL); + } + + return (best_bid_slot); +} + +/* + * Return the file offset (within the uncompressed data stream) where + * the last header started. + */ +la_int64_t +archive_read_header_position(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_ANY, "archive_read_header_position"); + return (a->header_position); +} + +/* + * Returns 1 if the archive contains at least one encrypted entry. + * If the archive format not support encryption at all + * ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned. + * If for any other reason (e.g. not enough data read so far) + * we cannot say whether there are encrypted entries, then + * ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned. + * In general, this function will return values below zero when the + * reader is uncertain or totally incapable of encryption support. + * When this function returns 0 you can be sure that the reader + * supports encryption detection but no encrypted entries have + * been found yet. + * + * NOTE: If the metadata/header of an archive is also encrypted, you + * cannot rely on the number of encrypted entries. That is why this + * function does not return the number of encrypted entries but# + * just shows that there are some. + */ +int +archive_read_has_encrypted_entries(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + int format_supports_encryption = archive_read_format_capabilities(_a) + & (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA | ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA); + + if (!_a || !format_supports_encryption) { + /* Format in general doesn't support encryption */ + return ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED; + } + + /* A reader potentially has read enough data now. */ + if (a->format && a->format->has_encrypted_entries) { + return (a->format->has_encrypted_entries)(a); + } + + /* For any other reason we cannot say how many entries are there. */ + return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW; +} + +/* + * Returns a bitmask of capabilities that are supported by the archive format reader. + * If the reader has no special capabilities, ARCHIVE_READ_FORMAT_CAPS_NONE is returned. + */ +int +archive_read_format_capabilities(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + if (a && a->format && a->format->format_capabilties) { + return (a->format->format_capabilties)(a); + } + return ARCHIVE_READ_FORMAT_CAPS_NONE; +} + +/* + * Read data from an archive entry, using a read(2)-style interface. + * This is a convenience routine that just calls + * archive_read_data_block and copies the results into the client + * buffer, filling any gaps with zero bytes. Clients using this + * API can be completely ignorant of sparse-file issues; sparse files + * will simply be padded with nulls. + * + * DO NOT intermingle calls to this function and archive_read_data_block + * to read a single entry body. + */ +la_ssize_t +archive_read_data(struct archive *_a, void *buff, size_t s) +{ + struct archive *a = (struct archive *)_a; + char *dest; + const void *read_buf; + size_t bytes_read; + size_t len; + int r; + + bytes_read = 0; + dest = (char *)buff; + + while (s > 0) { + if (a->read_data_offset == a->read_data_output_offset && + a->read_data_remaining == 0) { + read_buf = a->read_data_block; + a->read_data_is_posix_read = 1; + a->read_data_requested = s; + r = archive_read_data_block(a, &read_buf, + &a->read_data_remaining, &a->read_data_offset); + a->read_data_block = read_buf; + if (r == ARCHIVE_EOF) + return (bytes_read); + /* + * Error codes are all negative, so the status + * return here cannot be confused with a valid + * byte count. (ARCHIVE_OK is zero.) + */ + if (r < ARCHIVE_OK) + return (r); + } + + if (a->read_data_offset < a->read_data_output_offset) { + archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, + "Encountered out-of-order sparse blocks"); + return (ARCHIVE_RETRY); + } + + /* Compute the amount of zero padding needed. */ + if (a->read_data_output_offset + (int64_t)s < + a->read_data_offset) { + len = s; + } else if (a->read_data_output_offset < + a->read_data_offset) { + len = (size_t)(a->read_data_offset - + a->read_data_output_offset); + } else + len = 0; + + /* Add zeroes. */ + memset(dest, 0, len); + s -= len; + a->read_data_output_offset += len; + dest += len; + bytes_read += len; + + /* Copy data if there is any space left. */ + if (s > 0) { + len = a->read_data_remaining; + if (len > s) + len = s; + if (len) + memcpy(dest, a->read_data_block, len); + s -= len; + a->read_data_block += len; + a->read_data_remaining -= len; + a->read_data_output_offset += len; + a->read_data_offset += len; + dest += len; + bytes_read += len; + } + } + a->read_data_is_posix_read = 0; + a->read_data_requested = 0; + return (bytes_read); +} + +/* + * Reset the read_data_* variables, used for starting a new entry. + */ +void __archive_reset_read_data(struct archive * a) +{ + a->read_data_output_offset = 0; + a->read_data_remaining = 0; + a->read_data_is_posix_read = 0; + a->read_data_requested = 0; + + /* extra resets, from rar.c */ + a->read_data_block = NULL; + a->read_data_offset = 0; +} + +/* + * Skip over all remaining data in this entry. + */ +int +archive_read_data_skip(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + int r; + const void *buff; + size_t size; + int64_t offset; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, + "archive_read_data_skip"); + + if (a->format->read_data_skip != NULL) + r = (a->format->read_data_skip)(a); + else { + while ((r = archive_read_data_block(&a->archive, + &buff, &size, &offset)) + == ARCHIVE_OK) + ; + } + + if (r == ARCHIVE_EOF) + r = ARCHIVE_OK; + + a->archive.state = ARCHIVE_STATE_HEADER; + return (r); +} + +la_int64_t +archive_seek_data(struct archive *_a, int64_t offset, int whence) +{ + struct archive_read *a = (struct archive_read *)_a; + archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, + "archive_seek_data_block"); + + if (a->format->seek_data == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "Internal error: " + "No format_seek_data_block function registered"); + return (ARCHIVE_FATAL); + } + + return (a->format->seek_data)(a, offset, whence); +} + +/* + * Read the next block of entry data from the archive. + * This is a zero-copy interface; the client receives a pointer, + * size, and file offset of the next available block of data. + * + * Returns ARCHIVE_OK if the operation is successful, ARCHIVE_EOF if + * the end of entry is encountered. + */ +static int +_archive_read_data_block(struct archive *_a, + const void **buff, size_t *size, int64_t *offset) +{ + struct archive_read *a = (struct archive_read *)_a; + archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, + "archive_read_data_block"); + + if (a->format->read_data == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "Internal error: " + "No format->read_data function registered"); + return (ARCHIVE_FATAL); + } + + return (a->format->read_data)(a, buff, size, offset); +} + +static int +close_filters(struct archive_read *a) +{ + struct archive_read_filter *f = a->filter; + int r = ARCHIVE_OK; + /* Close each filter in the pipeline. */ + while (f != NULL) { + struct archive_read_filter *t = f->upstream; + if (!f->closed && f->close != NULL) { + int r1 = (f->close)(f); + f->closed = 1; + if (r1 < r) + r = r1; + } + free(f->buffer); + f->buffer = NULL; + f = t; + } + return r; +} + +void +__archive_read_free_filters(struct archive_read *a) +{ + /* Make sure filters are closed and their buffers are freed */ + close_filters(a); + + while (a->filter != NULL) { + struct archive_read_filter *t = a->filter->upstream; + free(a->filter); + a->filter = t; + } +} + +/* + * return the count of # of filters in use + */ +static int +_archive_filter_count(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter *p = a->filter; + int count = 0; + while(p) { + count++; + p = p->upstream; + } + return count; +} + +/* + * Close the file and all I/O. + */ +static int +_archive_read_close(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + int r = ARCHIVE_OK, r1 = ARCHIVE_OK; + + archive_check_magic(&a->archive, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_close"); + if (a->archive.state == ARCHIVE_STATE_CLOSED) + return (ARCHIVE_OK); + archive_clear_error(&a->archive); + a->archive.state = ARCHIVE_STATE_CLOSED; + + /* TODO: Clean up the formatters. */ + + /* Release the filter objects. */ + r1 = close_filters(a); + if (r1 < r) + r = r1; + + return (r); +} + +/* + * Release memory and other resources. + */ +static int +_archive_read_free(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_passphrase *p; + int i, n; + int slots; + int r = ARCHIVE_OK; + + if (_a == NULL) + return (ARCHIVE_OK); + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_free"); + if (a->archive.state != ARCHIVE_STATE_CLOSED + && a->archive.state != ARCHIVE_STATE_FATAL) + r = archive_read_close(&a->archive); + + /* Call cleanup functions registered by optional components. */ + if (a->cleanup_archive_extract != NULL) + r = (a->cleanup_archive_extract)(a); + + /* Cleanup format-specific data. */ + slots = sizeof(a->formats) / sizeof(a->formats[0]); + for (i = 0; i < slots; i++) { + a->format = &(a->formats[i]); + if (a->formats[i].cleanup) + (a->formats[i].cleanup)(a); + } + + /* Free the filters */ + __archive_read_free_filters(a); + + /* Release the bidder objects. */ + n = sizeof(a->bidders)/sizeof(a->bidders[0]); + for (i = 0; i < n; i++) { + if (a->bidders[i].free != NULL) { + int r1 = (a->bidders[i].free)(&a->bidders[i]); + if (r1 < r) + r = r1; + } + } + + /* Release passphrase list. */ + p = a->passphrases.first; + while (p != NULL) { + struct archive_read_passphrase *np = p->next; + + /* A passphrase should be cleaned. */ + memset(p->passphrase, 0, strlen(p->passphrase)); + free(p->passphrase); + free(p); + p = np; + } + + archive_string_free(&a->archive.error_string); + archive_entry_free(a->entry); + a->archive.magic = 0; + __archive_clean(&a->archive); + free(a->client.dataset); + free(a); + return (r); +} + +static struct archive_read_filter * +get_filter(struct archive *_a, int n) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter *f = a->filter; + /* We use n == -1 for 'the last filter', which is always the + * client proxy. */ + if (n == -1 && f != NULL) { + struct archive_read_filter *last = f; + f = f->upstream; + while (f != NULL) { + last = f; + f = f->upstream; + } + return (last); + } + if (n < 0) + return NULL; + while (n > 0 && f != NULL) { + f = f->upstream; + --n; + } + return (f); +} + +static int +_archive_filter_code(struct archive *_a, int n) +{ + struct archive_read_filter *f = get_filter(_a, n); + return f == NULL ? -1 : f->code; +} + +static const char * +_archive_filter_name(struct archive *_a, int n) +{ + struct archive_read_filter *f = get_filter(_a, n); + return f != NULL ? f->name : NULL; +} + +static int64_t +_archive_filter_bytes(struct archive *_a, int n) +{ + struct archive_read_filter *f = get_filter(_a, n); + return f == NULL ? -1 : f->position; +} + +/* + * Used internally by read format handlers to register their bid and + * initialization functions. + */ +int +__archive_read_register_format(struct archive_read *a, + void *format_data, + const char *name, + int (*bid)(struct archive_read *, int), + int (*options)(struct archive_read *, const char *, const char *), + int (*read_header)(struct archive_read *, struct archive_entry *), + int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *), + int (*read_data_skip)(struct archive_read *), + int64_t (*seek_data)(struct archive_read *, int64_t, int), + int (*cleanup)(struct archive_read *), + int (*format_capabilities)(struct archive_read *), + int (*has_encrypted_entries)(struct archive_read *)) +{ + int i, number_slots; + + archive_check_magic(&a->archive, + ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, + "__archive_read_register_format"); + + number_slots = sizeof(a->formats) / sizeof(a->formats[0]); + + for (i = 0; i < number_slots; i++) { + if (a->formats[i].bid == bid) + return (ARCHIVE_WARN); /* We've already installed */ + if (a->formats[i].bid == NULL) { + a->formats[i].bid = bid; + a->formats[i].options = options; + a->formats[i].read_header = read_header; + a->formats[i].read_data = read_data; + a->formats[i].read_data_skip = read_data_skip; + a->formats[i].seek_data = seek_data; + a->formats[i].cleanup = cleanup; + a->formats[i].data = format_data; + a->formats[i].name = name; + a->formats[i].format_capabilties = format_capabilities; + a->formats[i].has_encrypted_entries = has_encrypted_entries; + return (ARCHIVE_OK); + } + } + + archive_set_error(&a->archive, ENOMEM, + "Not enough slots for format registration"); + return (ARCHIVE_FATAL); +} + +/* + * Used internally by decompression routines to register their bid and + * initialization functions. + */ +int +__archive_read_get_bidder(struct archive_read *a, + struct archive_read_filter_bidder **bidder) +{ + int i, number_slots; + + number_slots = sizeof(a->bidders) / sizeof(a->bidders[0]); + + for (i = 0; i < number_slots; i++) { + if (a->bidders[i].bid == NULL) { + memset(a->bidders + i, 0, sizeof(a->bidders[0])); + *bidder = (a->bidders + i); + return (ARCHIVE_OK); + } + } + + archive_set_error(&a->archive, ENOMEM, + "Not enough slots for filter registration"); + return (ARCHIVE_FATAL); +} + +/* + * The next section implements the peek/consume internal I/O + * system used by archive readers. This system allows simple + * read-ahead for consumers while preserving zero-copy operation + * most of the time. + * + * The two key operations: + * * The read-ahead function returns a pointer to a block of data + * that satisfies a minimum request. + * * The consume function advances the file pointer. + * + * In the ideal case, filters generate blocks of data + * and __archive_read_ahead() just returns pointers directly into + * those blocks. Then __archive_read_consume() just bumps those + * pointers. Only if your request would span blocks does the I/O + * layer use a copy buffer to provide you with a contiguous block of + * data. + * + * A couple of useful idioms: + * * "I just want some data." Ask for 1 byte and pay attention to + * the "number of bytes available" from __archive_read_ahead(). + * Consume whatever you actually use. + * * "I want to output a large block of data." As above, ask for 1 byte, + * emit all that's available (up to whatever limit you have), consume + * it all, then repeat until you're done. This effectively means that + * you're passing along the blocks that came from your provider. + * * "I want to peek ahead by a large amount." Ask for 4k or so, then + * double and repeat until you get an error or have enough. Note + * that the I/O layer will likely end up expanding its copy buffer + * to fit your request, so use this technique cautiously. This + * technique is used, for example, by some of the format tasting + * code that has uncertain look-ahead needs. + */ + +/* + * Looks ahead in the input stream: + * * If 'avail' pointer is provided, that returns number of bytes available + * in the current buffer, which may be much larger than requested. + * * If end-of-file, *avail gets set to zero. + * * If error, *avail gets error code. + * * If request can be met, returns pointer to data. + * * If minimum request cannot be met, returns NULL. + * + * Note: If you just want "some data", ask for 1 byte and pay attention + * to *avail, which will have the actual amount available. If you + * know exactly how many bytes you need, just ask for that and treat + * a NULL return as an error. + * + * Important: This does NOT move the file pointer. See + * __archive_read_consume() below. + */ +const void * +__archive_read_ahead(struct archive_read *a, size_t min, ssize_t *avail) +{ + return (__archive_read_filter_ahead(a->filter, min, avail)); +} + +const void * +__archive_read_filter_ahead(struct archive_read_filter *filter, + size_t min, ssize_t *avail) +{ + ssize_t bytes_read; + size_t tocopy; + + if (filter->fatal) { + if (avail) + *avail = ARCHIVE_FATAL; + return (NULL); + } + + /* + * Keep pulling more data until we can satisfy the request. + */ + for (;;) { + + /* + * If we can satisfy from the copy buffer (and the + * copy buffer isn't empty), we're done. In particular, + * note that min == 0 is a perfectly well-defined + * request. + */ + if (filter->avail >= min && filter->avail > 0) { + if (avail != NULL) + *avail = filter->avail; + return (filter->next); + } + + /* + * We can satisfy directly from client buffer if everything + * currently in the copy buffer is still in the client buffer. + */ + if (filter->client_total >= filter->client_avail + filter->avail + && filter->client_avail + filter->avail >= min) { + /* "Roll back" to client buffer. */ + filter->client_avail += filter->avail; + filter->client_next -= filter->avail; + /* Copy buffer is now empty. */ + filter->avail = 0; + filter->next = filter->buffer; + /* Return data from client buffer. */ + if (avail != NULL) + *avail = filter->client_avail; + return (filter->client_next); + } + + /* Move data forward in copy buffer if necessary. */ + if (filter->next > filter->buffer && + filter->next + min > filter->buffer + filter->buffer_size) { + if (filter->avail > 0) + memmove(filter->buffer, filter->next, + filter->avail); + filter->next = filter->buffer; + } + + /* If we've used up the client data, get more. */ + if (filter->client_avail <= 0) { + if (filter->end_of_file) { + if (avail != NULL) + *avail = 0; + return (NULL); + } + bytes_read = (filter->read)(filter, + &filter->client_buff); + if (bytes_read < 0) { /* Read error. */ + filter->client_total = filter->client_avail = 0; + filter->client_next = + filter->client_buff = NULL; + filter->fatal = 1; + if (avail != NULL) + *avail = ARCHIVE_FATAL; + return (NULL); + } + if (bytes_read == 0) { + /* Check for another client object first */ + if (filter->archive->client.cursor != + filter->archive->client.nodes - 1) { + if (client_switch_proxy(filter, + filter->archive->client.cursor + 1) + == ARCHIVE_OK) + continue; + } + /* Premature end-of-file. */ + filter->client_total = filter->client_avail = 0; + filter->client_next = + filter->client_buff = NULL; + filter->end_of_file = 1; + /* Return whatever we do have. */ + if (avail != NULL) + *avail = filter->avail; + return (NULL); + } + filter->client_total = bytes_read; + filter->client_avail = filter->client_total; + filter->client_next = filter->client_buff; + } else { + /* + * We can't satisfy the request from the copy + * buffer or the existing client data, so we + * need to copy more client data over to the + * copy buffer. + */ + + /* Ensure the buffer is big enough. */ + if (min > filter->buffer_size) { + size_t s, t; + char *p; + + /* Double the buffer; watch for overflow. */ + s = t = filter->buffer_size; + if (s == 0) + s = min; + while (s < min) { + t *= 2; + if (t <= s) { /* Integer overflow! */ + archive_set_error( + &filter->archive->archive, + ENOMEM, + "Unable to allocate copy" + " buffer"); + filter->fatal = 1; + if (avail != NULL) + *avail = ARCHIVE_FATAL; + return (NULL); + } + s = t; + } + /* Now s >= min, so allocate a new buffer. */ + p = (char *)malloc(s); + if (p == NULL) { + archive_set_error( + &filter->archive->archive, + ENOMEM, + "Unable to allocate copy buffer"); + filter->fatal = 1; + if (avail != NULL) + *avail = ARCHIVE_FATAL; + return (NULL); + } + /* Move data into newly-enlarged buffer. */ + if (filter->avail > 0) + memmove(p, filter->next, filter->avail); + free(filter->buffer); + filter->next = filter->buffer = p; + filter->buffer_size = s; + } + + /* We can add client data to copy buffer. */ + /* First estimate: copy to fill rest of buffer. */ + tocopy = (filter->buffer + filter->buffer_size) + - (filter->next + filter->avail); + /* Don't waste time buffering more than we need to. */ + if (tocopy + filter->avail > min) + tocopy = min - filter->avail; + /* Don't copy more than is available. */ + if (tocopy > filter->client_avail) + tocopy = filter->client_avail; + + memcpy(filter->next + filter->avail, + filter->client_next, tocopy); + /* Remove this data from client buffer. */ + filter->client_next += tocopy; + filter->client_avail -= tocopy; + /* add it to copy buffer. */ + filter->avail += tocopy; + } + } +} + +/* + * Move the file pointer forward. + */ +int64_t +__archive_read_consume(struct archive_read *a, int64_t request) +{ + return (__archive_read_filter_consume(a->filter, request)); +} + +int64_t +__archive_read_filter_consume(struct archive_read_filter * filter, + int64_t request) +{ + int64_t skipped; + + if (request < 0) + return ARCHIVE_FATAL; + if (request == 0) + return 0; + + skipped = advance_file_pointer(filter, request); + if (skipped == request) + return (skipped); + /* We hit EOF before we satisfied the skip request. */ + if (skipped < 0) /* Map error code to 0 for error message below. */ + skipped = 0; + archive_set_error(&filter->archive->archive, + ARCHIVE_ERRNO_MISC, + "Truncated input file (needed %jd bytes, only %jd available)", + (intmax_t)request, (intmax_t)skipped); + return (ARCHIVE_FATAL); +} + +/* + * Advance the file pointer by the amount requested. + * Returns the amount actually advanced, which may be less than the + * request if EOF is encountered first. + * Returns a negative value if there's an I/O error. + */ +static int64_t +advance_file_pointer(struct archive_read_filter *filter, int64_t request) +{ + int64_t bytes_skipped, total_bytes_skipped = 0; + ssize_t bytes_read; + size_t min; + + if (filter->fatal) + return (-1); + + /* Use up the copy buffer first. */ + if (filter->avail > 0) { + min = (size_t)minimum(request, (int64_t)filter->avail); + filter->next += min; + filter->avail -= min; + request -= min; + filter->position += min; + total_bytes_skipped += min; + } + + /* Then use up the client buffer. */ + if (filter->client_avail > 0) { + min = (size_t)minimum(request, (int64_t)filter->client_avail); + filter->client_next += min; + filter->client_avail -= min; + request -= min; + filter->position += min; + total_bytes_skipped += min; + } + if (request == 0) + return (total_bytes_skipped); + + /* If there's an optimized skip function, use it. */ + if (filter->skip != NULL) { + bytes_skipped = (filter->skip)(filter, request); + if (bytes_skipped < 0) { /* error */ + filter->fatal = 1; + return (bytes_skipped); + } + filter->position += bytes_skipped; + total_bytes_skipped += bytes_skipped; + request -= bytes_skipped; + if (request == 0) + return (total_bytes_skipped); + } + + /* Use ordinary reads as necessary to complete the request. */ + for (;;) { + bytes_read = (filter->read)(filter, &filter->client_buff); + if (bytes_read < 0) { + filter->client_buff = NULL; + filter->fatal = 1; + return (bytes_read); + } + + if (bytes_read == 0) { + if (filter->archive->client.cursor != + filter->archive->client.nodes - 1) { + if (client_switch_proxy(filter, + filter->archive->client.cursor + 1) + == ARCHIVE_OK) + continue; + } + filter->client_buff = NULL; + filter->end_of_file = 1; + return (total_bytes_skipped); + } + + if (bytes_read >= request) { + filter->client_next = + ((const char *)filter->client_buff) + request; + filter->client_avail = (size_t)(bytes_read - request); + filter->client_total = bytes_read; + total_bytes_skipped += request; + filter->position += request; + return (total_bytes_skipped); + } + + filter->position += bytes_read; + total_bytes_skipped += bytes_read; + request -= bytes_read; + } +} + +/** + * Returns ARCHIVE_FAILED if seeking isn't supported. + */ +int64_t +__archive_read_seek(struct archive_read *a, int64_t offset, int whence) +{ + return __archive_read_filter_seek(a->filter, offset, whence); +} + +int64_t +__archive_read_filter_seek(struct archive_read_filter *filter, int64_t offset, + int whence) +{ + struct archive_read_client *client; + int64_t r; + unsigned int cursor; + + if (filter->closed || filter->fatal) + return (ARCHIVE_FATAL); + if (filter->seek == NULL) + return (ARCHIVE_FAILED); + + client = &(filter->archive->client); + switch (whence) { + case SEEK_CUR: + /* Adjust the offset and use SEEK_SET instead */ + offset += filter->position; + __LA_FALLTHROUGH; + case SEEK_SET: + cursor = 0; + while (1) + { + if (client->dataset[cursor].begin_position < 0 || + client->dataset[cursor].total_size < 0 || + client->dataset[cursor].begin_position + + client->dataset[cursor].total_size - 1 > offset || + cursor + 1 >= client->nodes) + break; + r = client->dataset[cursor].begin_position + + client->dataset[cursor].total_size; + client->dataset[++cursor].begin_position = r; + } + while (1) { + r = client_switch_proxy(filter, cursor); + if (r != ARCHIVE_OK) + return r; + if ((r = client_seek_proxy(filter, 0, SEEK_END)) < 0) + return r; + client->dataset[cursor].total_size = r; + if (client->dataset[cursor].begin_position + + client->dataset[cursor].total_size - 1 > offset || + cursor + 1 >= client->nodes) + break; + r = client->dataset[cursor].begin_position + + client->dataset[cursor].total_size; + client->dataset[++cursor].begin_position = r; + } + offset -= client->dataset[cursor].begin_position; + if (offset < 0 + || offset > client->dataset[cursor].total_size) + return ARCHIVE_FATAL; + if ((r = client_seek_proxy(filter, offset, SEEK_SET)) < 0) + return r; + break; + + case SEEK_END: + cursor = 0; + while (1) { + if (client->dataset[cursor].begin_position < 0 || + client->dataset[cursor].total_size < 0 || + cursor + 1 >= client->nodes) + break; + r = client->dataset[cursor].begin_position + + client->dataset[cursor].total_size; + client->dataset[++cursor].begin_position = r; + } + while (1) { + r = client_switch_proxy(filter, cursor); + if (r != ARCHIVE_OK) + return r; + if ((r = client_seek_proxy(filter, 0, SEEK_END)) < 0) + return r; + client->dataset[cursor].total_size = r; + r = client->dataset[cursor].begin_position + + client->dataset[cursor].total_size; + if (cursor + 1 >= client->nodes) + break; + client->dataset[++cursor].begin_position = r; + } + while (1) { + if (r + offset >= + client->dataset[cursor].begin_position) + break; + offset += client->dataset[cursor].total_size; + if (cursor == 0) + break; + cursor--; + r = client->dataset[cursor].begin_position + + client->dataset[cursor].total_size; + } + offset = (r + offset) - client->dataset[cursor].begin_position; + if ((r = client_switch_proxy(filter, cursor)) != ARCHIVE_OK) + return r; + r = client_seek_proxy(filter, offset, SEEK_SET); + if (r < ARCHIVE_OK) + return r; + break; + + default: + return (ARCHIVE_FATAL); + } + r += client->dataset[cursor].begin_position; + + if (r >= 0) { + /* + * Ouch. Clearing the buffer like this hurts, especially + * at bid time. A lot of our efficiency at bid time comes + * from having bidders reuse the data we've already read. + * + * TODO: If the seek request is in data we already + * have, then don't call the seek callback. + * + * TODO: Zip seeks to end-of-file at bid time. If + * other formats also start doing this, we may need to + * find a way for clients to fudge the seek offset to + * a block boundary. + * + * Hmmm... If whence was SEEK_END, we know the file + * size is (r - offset). Can we use that to simplify + * the TODO items above? + */ + filter->avail = filter->client_avail = 0; + filter->next = filter->buffer; + filter->position = r; + filter->end_of_file = 0; + } + return r; +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_add_passphrase.3 b/dependencies/libarchive-3.4.2/libarchive/archive_read_add_passphrase.3 new file mode 100644 index 0000000..ca60d4f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_add_passphrase.3 @@ -0,0 +1,74 @@ +.\" Copyright (c) 2014 Michihiro NAKAJIMA +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd September 14, 2014 +.Dt ARCHIVE_READ_ADD_PASSPHRASE 3 +.Os +.Sh NAME +.Nm archive_read_add_passphrase , +.Nm archive_read_set_passphrase_callback +.Nd functions for reading encrypted archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive.h +.Ft int +.Fo archive_read_add_passphrase +.Fa "struct archive *" +.Fa "const char *passphrase" +.Fc +.Ft int +.Fo archive_read_set_passphrase_callback +.Fa "struct archive *" +.Fa "void *client_data" +.Fa "archive_passphrase_callback *" +.Fc +.Sh DESCRIPTION +.Bl -tag -width indent +.It Fn archive_read_add_passphrase +Register passphrases for reading an encryption archive. +If +.Ar passphrase +is +.Dv NULL +or empty, this function will do nothing and +.Cm ARCHIVE_FAILED +will be returned. +Otherwise, +.Cm ARCHIVE_OK +will be returned. +.It Fn archive_read_set_passphrase_callback +Register a callback function that will be invoked to get a passphrase +for decryption after trying all the passphrases registered by the +.Fn archive_read_add_passphrase +function failed. +.El +.\" .Sh ERRORS +.Sh SEE ALSO +.Xr tar 1 , +.Xr archive_read 3 , +.Xr archive_read_set_options 3 , +.Xr libarchive 3 diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_add_passphrase.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_add_passphrase.c new file mode 100644 index 0000000..cf821b5 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_add_passphrase.c @@ -0,0 +1,186 @@ +/*- + * Copyright (c) 2014 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#include "archive_read_private.h" + +static void +add_passphrase_to_tail(struct archive_read *a, + struct archive_read_passphrase *p) +{ + *a->passphrases.last = p; + a->passphrases.last = &p->next; + p->next = NULL; +} + +static struct archive_read_passphrase * +remove_passphrases_from_head(struct archive_read *a) +{ + struct archive_read_passphrase *p; + + p = a->passphrases.first; + if (p != NULL) + a->passphrases.first = p->next; + return (p); +} + +static void +insert_passphrase_to_head(struct archive_read *a, + struct archive_read_passphrase *p) +{ + p->next = a->passphrases.first; + a->passphrases.first = p; +} + +static struct archive_read_passphrase * +new_read_passphrase(struct archive_read *a, const char *passphrase) +{ + struct archive_read_passphrase *p; + + p = malloc(sizeof(*p)); + if (p == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (NULL); + } + p->passphrase = strdup(passphrase); + if (p->passphrase == NULL) { + free(p); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (NULL); + } + return (p); +} + +int +archive_read_add_passphrase(struct archive *_a, const char *passphrase) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_passphrase *p; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, + "archive_read_add_passphrase"); + + if (passphrase == NULL || passphrase[0] == '\0') { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Empty passphrase is unacceptable"); + return (ARCHIVE_FAILED); + } + + p = new_read_passphrase(a, passphrase); + if (p == NULL) + return (ARCHIVE_FATAL); + add_passphrase_to_tail(a, p); + + return (ARCHIVE_OK); +} + +int +archive_read_set_passphrase_callback(struct archive *_a, void *client_data, + archive_passphrase_callback *cb) +{ + struct archive_read *a = (struct archive_read *)_a; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, + "archive_read_set_passphrase_callback"); + + a->passphrases.callback = cb; + a->passphrases.client_data = client_data; + return (ARCHIVE_OK); +} + +/* + * Call this in advance when you start to get a passphrase for decryption + * for a entry. + */ +void +__archive_read_reset_passphrase(struct archive_read *a) +{ + + a->passphrases.candidate = -1; +} + +/* + * Get a passphrase for decryption. + */ +const char * +__archive_read_next_passphrase(struct archive_read *a) +{ + struct archive_read_passphrase *p; + const char *passphrase; + + if (a->passphrases.candidate < 0) { + /* Count out how many passphrases we have. */ + int cnt = 0; + + for (p = a->passphrases.first; p != NULL; p = p->next) + cnt++; + a->passphrases.candidate = cnt; + p = a->passphrases.first; + } else if (a->passphrases.candidate > 1) { + /* Rotate a passphrase list. */ + a->passphrases.candidate--; + p = remove_passphrases_from_head(a); + add_passphrase_to_tail(a, p); + /* Pick a new passphrase candidate up. */ + p = a->passphrases.first; + } else if (a->passphrases.candidate == 1) { + /* This case is that all candidates failed to decrypt. */ + a->passphrases.candidate = 0; + if (a->passphrases.first->next != NULL) { + /* Rotate a passphrase list. */ + p = remove_passphrases_from_head(a); + add_passphrase_to_tail(a, p); + } + p = NULL; + } else /* There is no passphrase candidate. */ + p = NULL; + + if (p != NULL) + passphrase = p->passphrase; + else if (a->passphrases.callback != NULL) { + /* Get a passphrase through a call-back function + * since we tried all passphrases out or we don't + * have it. */ + passphrase = a->passphrases.callback(&a->archive, + a->passphrases.client_data); + if (passphrase != NULL) { + p = new_read_passphrase(a, passphrase); + if (p == NULL) + return (NULL); + insert_passphrase_to_head(a, p); + a->passphrases.candidate = 1; + } + } else + passphrase = NULL; + + return (passphrase); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_append_filter.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_append_filter.c new file mode 100644 index 0000000..da7c55b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_append_filter.c @@ -0,0 +1,204 @@ +/*- + * Copyright (c) 2003-2012 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_read_private.h" + +int +archive_read_append_filter(struct archive *_a, int code) +{ + int r1, r2, number_bidders, i; + char str[20]; + struct archive_read_filter_bidder *bidder; + struct archive_read_filter *filter; + struct archive_read *a = (struct archive_read *)_a; + + r2 = (ARCHIVE_OK); + switch (code) + { + case ARCHIVE_FILTER_NONE: + /* No filter to add, so do nothing. + * NOTE: An initial "NONE" type filter is always set at the end of the + * filter chain. + */ + r1 = (ARCHIVE_OK); + break; + case ARCHIVE_FILTER_GZIP: + strcpy(str, "gzip"); + r1 = archive_read_support_filter_gzip(_a); + break; + case ARCHIVE_FILTER_BZIP2: + strcpy(str, "bzip2"); + r1 = archive_read_support_filter_bzip2(_a); + break; + case ARCHIVE_FILTER_COMPRESS: + strcpy(str, "compress (.Z)"); + r1 = archive_read_support_filter_compress(_a); + break; + case ARCHIVE_FILTER_PROGRAM: + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "Cannot append program filter using archive_read_append_filter"); + return (ARCHIVE_FATAL); + case ARCHIVE_FILTER_LZMA: + strcpy(str, "lzma"); + r1 = archive_read_support_filter_lzma(_a); + break; + case ARCHIVE_FILTER_XZ: + strcpy(str, "xz"); + r1 = archive_read_support_filter_xz(_a); + break; + case ARCHIVE_FILTER_UU: + strcpy(str, "uu"); + r1 = archive_read_support_filter_uu(_a); + break; + case ARCHIVE_FILTER_RPM: + strcpy(str, "rpm"); + r1 = archive_read_support_filter_rpm(_a); + break; + case ARCHIVE_FILTER_LZ4: + strcpy(str, "lz4"); + r1 = archive_read_support_filter_lz4(_a); + break; + case ARCHIVE_FILTER_ZSTD: + strcpy(str, "zstd"); + r1 = archive_read_support_filter_zstd(_a); + break; + case ARCHIVE_FILTER_LZIP: + strcpy(str, "lzip"); + r1 = archive_read_support_filter_lzip(_a); + break; + case ARCHIVE_FILTER_LRZIP: + strcpy(str, "lrzip"); + r1 = archive_read_support_filter_lrzip(_a); + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "Invalid filter code specified"); + return (ARCHIVE_FATAL); + } + + if (code != ARCHIVE_FILTER_NONE) + { + number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]); + + bidder = a->bidders; + for (i = 0; i < number_bidders; i++, bidder++) + { + if (!bidder->name || !strcmp(bidder->name, str)) + break; + } + if (!bidder->name || strcmp(bidder->name, str)) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "Internal error: Unable to append filter"); + return (ARCHIVE_FATAL); + } + + filter + = (struct archive_read_filter *)calloc(1, sizeof(*filter)); + if (filter == NULL) + { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + filter->bidder = bidder; + filter->archive = a; + filter->upstream = a->filter; + a->filter = filter; + r2 = (bidder->init)(a->filter); + if (r2 != ARCHIVE_OK) { + __archive_read_free_filters(a); + return (ARCHIVE_FATAL); + } + } + + a->bypass_filter_bidding = 1; + return (r1 < r2) ? r1 : r2; +} + +int +archive_read_append_filter_program(struct archive *_a, const char *cmd) +{ + return (archive_read_append_filter_program_signature(_a, cmd, NULL, 0)); +} + +int +archive_read_append_filter_program_signature(struct archive *_a, + const char *cmd, const void *signature, size_t signature_len) +{ + int r, number_bidders, i; + struct archive_read_filter_bidder *bidder; + struct archive_read_filter *filter; + struct archive_read *a = (struct archive_read *)_a; + + if (archive_read_support_filter_program_signature(_a, cmd, signature, + signature_len) != (ARCHIVE_OK)) + return (ARCHIVE_FATAL); + + number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]); + + bidder = a->bidders; + for (i = 0; i < number_bidders; i++, bidder++) + { + /* Program bidder name set to filter name after initialization */ + if (bidder->data && !bidder->name) + break; + } + if (!bidder->data) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "Internal error: Unable to append program filter"); + return (ARCHIVE_FATAL); + } + + filter + = (struct archive_read_filter *)calloc(1, sizeof(*filter)); + if (filter == NULL) + { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + filter->bidder = bidder; + filter->archive = a; + filter->upstream = a->filter; + a->filter = filter; + r = (bidder->init)(a->filter); + if (r != ARCHIVE_OK) { + __archive_read_free_filters(a); + return (ARCHIVE_FATAL); + } + bidder->name = a->filter->name; + + a->bypass_filter_bidding = 1; + return r; +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_data.3 b/dependencies/libarchive-3.4.2/libarchive/archive_read_data.3 new file mode 100644 index 0000000..78c0c90 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_data.3 @@ -0,0 +1,130 @@ +.\" Copyright (c) 2003-2011 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 2, 2012 +.Dt ARCHIVE_READ_DATA 3 +.Os +.Sh NAME +.Nm archive_read_data , +.Nm archive_read_data_block , +.Nm archive_read_data_skip , +.Nm archive_read_data_into_fd +.Nd functions for reading streaming archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive.h +.Ft la_ssize_t +.Fn archive_read_data "struct archive *" "void *buff" "size_t len" +.Ft int +.Fo archive_read_data_block +.Fa "struct archive *" +.Fa "const void **buff" +.Fa "size_t *len" +.Fa "off_t *offset" +.Fc +.Ft int +.Fn archive_read_data_skip "struct archive *" +.Ft int +.Fn archive_read_data_into_fd "struct archive *" "int fd" +.\" +.Sh DESCRIPTION +.Bl -tag -compact -width indent +.It Fn archive_read_data +Read data associated with the header just read. +Internally, this is a convenience function that calls +.Fn archive_read_data_block +and fills any gaps with nulls so that callers see a single +continuous stream of data. +.It Fn archive_read_data_block +Return the next available block of data for this entry. +Unlike +.Fn archive_read_data , +the +.Fn archive_read_data_block +function avoids copying data and allows you to correctly handle +sparse files, as supported by some archive formats. +The library guarantees that offsets will increase and that blocks +will not overlap. +Note that the blocks returned from this function can be much larger +than the block size read from disk, due to compression +and internal buffer optimizations. +.It Fn archive_read_data_skip +A convenience function that repeatedly calls +.Fn archive_read_data_block +to skip all of the data for this archive entry. +Note that this function is invoked automatically by +.Fn archive_read_next_header2 +if the previous entry was not completely consumed. +.It Fn archive_read_data_into_fd +A convenience function that repeatedly calls +.Fn archive_read_data_block +to copy the entire entry to the provided file descriptor. +.El +.\" +.Sh RETURN VALUES +Most functions return zero on success, non-zero on error. +The possible return codes include: +.Cm ARCHIVE_OK +(the operation succeeded), +.Cm ARCHIVE_WARN +(the operation succeeded but a non-critical error was encountered), +.Cm ARCHIVE_EOF +(end-of-archive was encountered), +.Cm ARCHIVE_RETRY +(the operation failed but can be retried), +and +.Cm ARCHIVE_FATAL +(there was a fatal error; the archive should be closed immediately). +.Pp +.Fn archive_read_data +returns a count of bytes actually read or zero at the end of the entry. +On error, a value of +.Cm ARCHIVE_FATAL , +.Cm ARCHIVE_WARN , +or +.Cm ARCHIVE_RETRY +is returned. +.\" +.Sh ERRORS +Detailed error codes and textual descriptions are available from the +.Fn archive_errno +and +.Fn archive_error_string +functions. +.\" +.Sh SEE ALSO +.Xr tar 1 , +.Xr archive_read 3 , +.Xr archive_read_extract 3 , +.Xr archive_read_filter 3 , +.Xr archive_read_format 3 , +.Xr archive_read_header 3 , +.Xr archive_read_open 3 , +.Xr archive_read_set_options 3 , +.Xr archive_util 3 , +.Xr libarchive 3 , +.Xr tar 5 diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_data_into_fd.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_data_into_fd.c new file mode 100644 index 0000000..b4398f1 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_data_into_fd.c @@ -0,0 +1,139 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_data_into_fd.c,v 1.16 2008/05/23 05:01:29 cperciva Exp $"); + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" + +/* Maximum amount of data to write at one time. */ +#define MAX_WRITE (1024 * 1024) + +/* + * This implementation minimizes copying of data and is sparse-file aware. + */ +static int +pad_to(struct archive *a, int fd, int can_lseek, + size_t nulls_size, const char *nulls, + int64_t target_offset, int64_t actual_offset) +{ + size_t to_write; + ssize_t bytes_written; + + if (can_lseek) { + actual_offset = lseek(fd, + target_offset - actual_offset, SEEK_CUR); + if (actual_offset != target_offset) { + archive_set_error(a, errno, "Seek error"); + return (ARCHIVE_FATAL); + } + return (ARCHIVE_OK); + } + while (target_offset > actual_offset) { + to_write = nulls_size; + if (target_offset < actual_offset + (int64_t)nulls_size) + to_write = (size_t)(target_offset - actual_offset); + bytes_written = write(fd, nulls, to_write); + if (bytes_written < 0) { + archive_set_error(a, errno, "Write error"); + return (ARCHIVE_FATAL); + } + actual_offset += bytes_written; + } + return (ARCHIVE_OK); +} + + +int +archive_read_data_into_fd(struct archive *a, int fd) +{ + struct stat st; + int r, r2; + const void *buff; + size_t size, bytes_to_write; + ssize_t bytes_written; + int64_t target_offset; + int64_t actual_offset = 0; + int can_lseek; + char *nulls = NULL; + size_t nulls_size = 16384; + + archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, + "archive_read_data_into_fd"); + + can_lseek = (fstat(fd, &st) == 0) && S_ISREG(st.st_mode); + if (!can_lseek) + nulls = calloc(1, nulls_size); + + while ((r = archive_read_data_block(a, &buff, &size, &target_offset)) == + ARCHIVE_OK) { + const char *p = buff; + if (target_offset > actual_offset) { + r = pad_to(a, fd, can_lseek, nulls_size, nulls, + target_offset, actual_offset); + if (r != ARCHIVE_OK) + break; + actual_offset = target_offset; + } + while (size > 0) { + bytes_to_write = size; + if (bytes_to_write > MAX_WRITE) + bytes_to_write = MAX_WRITE; + bytes_written = write(fd, p, bytes_to_write); + if (bytes_written < 0) { + archive_set_error(a, errno, "Write error"); + r = ARCHIVE_FATAL; + goto cleanup; + } + actual_offset += bytes_written; + p += bytes_written; + size -= bytes_written; + } + } + + if (r == ARCHIVE_EOF && target_offset > actual_offset) { + r2 = pad_to(a, fd, can_lseek, nulls_size, nulls, + target_offset, actual_offset); + if (r2 != ARCHIVE_OK) + r = r2; + } + +cleanup: + free(nulls); + if (r != ARCHIVE_EOF) + return (r); + return (ARCHIVE_OK); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_disk.3 b/dependencies/libarchive-3.4.2/libarchive/archive_read_disk.3 new file mode 100644 index 0000000..82d6a5c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_disk.3 @@ -0,0 +1,346 @@ +.\" Copyright (c) 2003-2009 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd April 3, 2017 +.Dt ARCHIVE_READ_DISK 3 +.Os +.Sh NAME +.Nm archive_read_disk_new , +.Nm archive_read_disk_set_behavior , +.Nm archive_read_disk_set_symlink_logical , +.Nm archive_read_disk_set_symlink_physical , +.Nm archive_read_disk_set_symlink_hybrid , +.Nm archive_read_disk_entry_from_file , +.Nm archive_read_disk_gname , +.Nm archive_read_disk_uname , +.Nm archive_read_disk_set_uname_lookup , +.Nm archive_read_disk_set_gname_lookup , +.Nm archive_read_disk_set_standard_lookup +.Nd functions for reading objects from disk +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive.h +.Ft struct archive * +.Fn archive_read_disk_new "void" +.Ft int +.Fn archive_read_disk_set_behavior "struct archive *" "int" +.Ft int +.Fn archive_read_disk_set_symlink_logical "struct archive *" +.Ft int +.Fn archive_read_disk_set_symlink_physical "struct archive *" +.Ft int +.Fn archive_read_disk_set_symlink_hybrid "struct archive *" +.Ft const char * +.Fn archive_read_disk_gname "struct archive *" "gid_t" +.Ft const char * +.Fn archive_read_disk_uname "struct archive *" "uid_t" +.Ft int +.Fo archive_read_disk_set_gname_lookup +.Fa "struct archive *" +.Fa "void *" +.Fa "const char *(*lookup)(void *, gid_t)" +.Fa "void (*cleanup)(void *)" +.Fc +.Ft int +.Fo archive_read_disk_set_uname_lookup +.Fa "struct archive *" +.Fa "void *" +.Fa "const char *(*lookup)(void *, uid_t)" +.Fa "void (*cleanup)(void *)" +.Fc +.Ft int +.Fn archive_read_disk_set_standard_lookup "struct archive *" +.Ft int +.Fo archive_read_disk_entry_from_file +.Fa "struct archive *" +.Fa "struct archive_entry *" +.Fa "int fd" +.Fa "const struct stat *" +.Fc +.Sh DESCRIPTION +These functions provide an API for reading information about +objects on disk. +In particular, they provide an interface for populating +.Tn struct archive_entry +objects. +.Bl -tag -width indent +.It Fn archive_read_disk_new +Allocates and initializes a +.Tn struct archive +object suitable for reading object information from disk. +.It Fn archive_read_disk_set_behavior +Configures various behavior options when reading entries from disk. +The flags field consists of a bitwise OR of one or more of the +following values: +.Bl -tag -compact -width "indent" +.It Cm ARCHIVE_READDISK_HONOR_NODUMP +Skip files and directories with the nodump file attribute (file flag) set. +By default, the nodump file attribute is ignored. +.It Cm ARCHIVE_READDISK_MAC_COPYFILE +Mac OS X specific. +Read metadata (ACLs and extended attributes) with +.Xr copyfile 3 . +By default, metadata is read using +.Xr copyfile 3 . +.It Cm ARCHIVE_READDISK_NO_ACL +Do not read Access Control Lists. +By default, ACLs are read from disk. +.It Cm ARCHIVE_READDISK_NO_FFLAGS +Do not read file attributes (file flags). +By default, file attributes are read from disk. +See +.Xr chattr 1 +.Pq Linux +or +.Xr chflags 1 +.Pq FreeBSD, Mac OS X +for more information on file attributes. +.It Cm ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS +Do not traverse mount points. +By default, mount points are traversed. +.It Cm ARCHIVE_READDISK_NO_XATTR +Do not read extended file attributes (xattrs). +By default, extended file attributes are read from disk. +See +.Xr xattr 7 +.Pq Linux , +.Xr xattr 2 +.Pq Mac OS X , +or +.Xr getextattr 8 +.Pq FreeBSD +for more information on extended file attributes. +.It Cm ARCHIVE_READDISK_RESTORE_ATIME +Restore access time of traversed files. +By default, access time of traversed files is not restored. +.El +.It Xo +.Fn archive_read_disk_set_symlink_logical , +.Fn archive_read_disk_set_symlink_physical , +.Fn archive_read_disk_set_symlink_hybrid +.Xc +This sets the mode used for handling symbolic links. +The +.Dq logical +mode follows all symbolic links. +The +.Dq physical +mode does not follow any symbolic links. +The +.Dq hybrid +mode currently behaves identically to the +.Dq logical +mode. +.It Xo +.Fn archive_read_disk_gname , +.Fn archive_read_disk_uname +.Xc +Returns a user or group name given a gid or uid value. +By default, these always return a NULL string. +.It Xo +.Fn archive_read_disk_set_gname_lookup , +.Fn archive_read_disk_set_uname_lookup +.Xc +These allow you to override the functions used for +user and group name lookups. +You may also provide a +.Tn void * +pointer to a private data structure and a cleanup function for +that data. +The cleanup function will be invoked when the +.Tn struct archive +object is destroyed or when new lookup functions are registered. +.It Fn archive_read_disk_set_standard_lookup +This convenience function installs a standard set of user +and group name lookup functions. +These functions use +.Xr getpwuid 3 +and +.Xr getgrgid 3 +to convert ids to names, defaulting to NULL if the names cannot +be looked up. +These functions also implement a simple memory cache to reduce +the number of calls to +.Xr getpwuid 3 +and +.Xr getgrgid 3 . +.It Fn archive_read_disk_entry_from_file +Populates a +.Tn struct archive_entry +object with information about a particular file. +The +.Tn archive_entry +object must have already been created with +.Xr archive_entry_new 3 +and at least one of the source path or path fields must already be set. +(If both are set, the source path will be used.) +.Pp +Information is read from disk using the path name from the +.Tn struct archive_entry +object. +If a file descriptor is provided, some information will be obtained using +that file descriptor, on platforms that support the appropriate +system calls. +.Pp +If a pointer to a +.Tn struct stat +is provided, information from that structure will be used instead +of reading from the disk where appropriate. +This can provide performance benefits in scenarios where +.Tn struct stat +information has already been read from the disk as a side effect +of some other operation. +(For example, directory traversal libraries often provide this information.) +.Pp +Where necessary, user and group ids are converted to user and group names +using the currently-registered lookup functions above. +This affects the file ownership fields and ACL values in the +.Tn struct archive_entry +object. +.El +More information about the +.Va struct archive +object and the overall design of the library can be found in the +.Xr libarchive 3 +overview. +.Sh EXAMPLES +The following illustrates basic usage of the library by +showing how to use it to copy an item on disk into an archive. +.Bd -literal -offset indent +void +file_to_archive(struct archive *a, const char *name) +{ + char buff[8192]; + size_t bytes_read; + struct archive *ard; + struct archive_entry *entry; + int fd; + + ard = archive_read_disk_new(); + archive_read_disk_set_standard_lookup(ard); + entry = archive_entry_new(); + fd = open(name, O_RDONLY); + if (fd < 0) + return; + archive_entry_copy_pathname(entry, name); + archive_read_disk_entry_from_file(ard, entry, fd, NULL); + archive_write_header(a, entry); + while ((bytes_read = read(fd, buff, sizeof(buff))) > 0) + archive_write_data(a, buff, bytes_read); + archive_write_finish_entry(a); + archive_read_free(ard); + archive_entry_free(entry); +} +.Ed +.Sh RETURN VALUES +Most functions return +.Cm ARCHIVE_OK +(zero) on success, or one of several negative +error codes for errors. +Specific error codes include: +.Cm ARCHIVE_RETRY +for operations that might succeed if retried, +.Cm ARCHIVE_WARN +for unusual conditions that do not prevent further operations, and +.Cm ARCHIVE_FATAL +for serious errors that make remaining operations impossible. +.Pp +.Fn archive_read_disk_new +returns a pointer to a newly-allocated +.Tn struct archive +object or NULL if the allocation failed for any reason. +.Pp +.Fn archive_read_disk_gname +and +.Fn archive_read_disk_uname +return +.Tn const char * +pointers to the textual name or NULL if the lookup failed for any reason. +The returned pointer points to internal storage that +may be reused on the next call to either of these functions; +callers should copy the string if they need to continue accessing it. +.\" +.Sh ERRORS +Detailed error codes and textual descriptions are available from the +.Fn archive_errno +and +.Fn archive_error_string +functions. +.\" +.Sh SEE ALSO +.Xr tar 1 , +.Xr archive_read 3 , +.Xr archive_util 3 , +.Xr archive_write 3 , +.Xr archive_write_disk 3 , +.Xr libarchive 3 +.Sh HISTORY +The +.Nm libarchive +library first appeared in +.Fx 5.3 . +The +.Nm archive_read_disk +interface was added to +.Nm libarchive 2.6 +and first appeared in +.Fx 8.0 . +.Sh AUTHORS +.An -nosplit +The +.Nm libarchive +library was written by +.An Tim Kientzle Aq kientzle@FreeBSD.org . +.Sh BUGS +The +.Dq standard +user name and group name lookup functions are not the defaults because +.Xr getgrgid 3 +and +.Xr getpwuid 3 +are sometimes too large for particular applications. +The current design allows the application author to use a more +compact implementation when appropriate. +.Pp +The full list of metadata read from disk by +.Fn archive_read_disk_entry_from_file +is necessarily system-dependent. +.Pp +The +.Fn archive_read_disk_entry_from_file +function reads as much information as it can from disk. +Some method should be provided to limit this so that clients who +do not need ACLs, for instance, can avoid the extra work needed +to look up such information. +.Pp +This API should provide a set of methods for walking a directory tree. +That would make it a direct parallel of the +.Xr archive_read 3 +API. +When such methods are implemented, the +.Dq hybrid +symbolic link mode will make sense. diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_disk_entry_from_file.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_disk_entry_from_file.c new file mode 100644 index 0000000..2a8cec8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_disk_entry_from_file.c @@ -0,0 +1,1044 @@ +/*- + * Copyright (c) 2003-2009 Tim Kientzle + * Copyright (c) 2010-2012 Michihiro NAKAJIMA + * Copyright (c) 2016 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD"); + +/* This is the tree-walking code for POSIX systems. */ +#if !defined(_WIN32) || defined(__CYGWIN__) + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_EXTATTR_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#if defined(HAVE_SYS_XATTR_H) +#include +#elif defined(HAVE_ATTR_XATTR_H) +#include +#endif +#ifdef HAVE_SYS_EA_H +#include +#endif +#ifdef HAVE_COPYFILE_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_LINUX_TYPES_H +#include +#endif +#ifdef HAVE_LINUX_FIEMAP_H +#include +#endif +#ifdef HAVE_LINUX_FS_H +#include +#endif +/* + * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h. + * As the include guards don't agree, the order of include is important. + */ +#ifdef HAVE_LINUX_EXT2_FS_H +#include /* for Linux file flags */ +#endif +#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__) +#include /* Linux file flags, broken on Cygwin */ +#endif +#ifdef HAVE_PATHS_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_read_disk_private.h" + +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + +static int setup_mac_metadata(struct archive_read_disk *, + struct archive_entry *, int *fd); +static int setup_xattrs(struct archive_read_disk *, + struct archive_entry *, int *fd); +static int setup_sparse(struct archive_read_disk *, + struct archive_entry *, int *fd); +#if defined(HAVE_LINUX_FIEMAP_H) +static int setup_sparse_fiemap(struct archive_read_disk *, + struct archive_entry *, int *fd); +#endif + +#if !ARCHIVE_ACL_SUPPORT +int +archive_read_disk_entry_setup_acls(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + (void)a; /* UNUSED */ + (void)entry; /* UNUSED */ + (void)fd; /* UNUSED */ + return (ARCHIVE_OK); +} +#endif + +/* + * Enter working directory and return working pathname of archive_entry. + * If a pointer to an integer is provided and its value is below zero + * open a file descriptor on this pathname. + */ +const char * +archive_read_disk_entry_setup_path(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + const char *path; + + path = archive_entry_sourcepath(entry); + + if (path == NULL || (a->tree != NULL && + a->tree_enter_working_dir(a->tree) != 0)) + path = archive_entry_pathname(entry); + if (path == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Couldn't determine path"); + } else if (fd != NULL && *fd < 0 && a->tree != NULL && + (a->follow_symlinks || archive_entry_filetype(entry) != AE_IFLNK)) { + *fd = a->open_on_current_dir(a->tree, path, + O_RDONLY | O_NONBLOCK); + } + return (path); +} + +int +archive_read_disk_entry_from_file(struct archive *_a, + struct archive_entry *entry, + int fd, + const struct stat *st) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + const char *path, *name; + struct stat s; + int initial_fd = fd; + int r, r1; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_ANY, + "archive_read_disk_entry_from_file"); + + archive_clear_error(_a); + path = archive_entry_sourcepath(entry); + if (path == NULL) + path = archive_entry_pathname(entry); + + if (a->tree == NULL) { + if (st == NULL) { +#if HAVE_FSTAT + if (fd >= 0) { + if (fstat(fd, &s) != 0) { + archive_set_error(&a->archive, errno, + "Can't fstat"); + return (ARCHIVE_FAILED); + } + } else +#endif +#if HAVE_LSTAT + if (!a->follow_symlinks) { + if (lstat(path, &s) != 0) { + archive_set_error(&a->archive, errno, + "Can't lstat %s", path); + return (ARCHIVE_FAILED); + } + } else +#endif + if (la_stat(path, &s) != 0) { + archive_set_error(&a->archive, errno, + "Can't stat %s", path); + return (ARCHIVE_FAILED); + } + st = &s; + } + archive_entry_copy_stat(entry, st); + } + + /* Lookup uname/gname */ + name = archive_read_disk_uname(_a, archive_entry_uid(entry)); + if (name != NULL) + archive_entry_copy_uname(entry, name); + name = archive_read_disk_gname(_a, archive_entry_gid(entry)); + if (name != NULL) + archive_entry_copy_gname(entry, name); + +#ifdef HAVE_STRUCT_STAT_ST_FLAGS + /* On FreeBSD, we get flags for free with the stat. */ + /* TODO: Does this belong in copy_stat()? */ + if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0 && st->st_flags != 0) + archive_entry_set_fflags(entry, st->st_flags, 0); +#endif + +#if (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \ + (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)) + /* Linux requires an extra ioctl to pull the flags. Although + * this is an extra step, it has a nice side-effect: We get an + * open file descriptor which we can use in the subsequent lookups. */ + if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0 && + (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) { + if (fd < 0) { + if (a->tree != NULL) + fd = a->open_on_current_dir(a->tree, path, + O_RDONLY | O_NONBLOCK | O_CLOEXEC); + else + fd = open(path, O_RDONLY | O_NONBLOCK | + O_CLOEXEC); + __archive_ensure_cloexec_flag(fd); + } + if (fd >= 0) { + int stflags; + r = ioctl(fd, +#if defined(FS_IOC_GETFLAGS) + FS_IOC_GETFLAGS, +#else + EXT2_IOC_GETFLAGS, +#endif + &stflags); + if (r == 0 && stflags != 0) + archive_entry_set_fflags(entry, stflags, 0); + } + } +#endif + +#if defined(HAVE_READLINK) || defined(HAVE_READLINKAT) + if (S_ISLNK(st->st_mode)) { + size_t linkbuffer_len = st->st_size; + char *linkbuffer; + int lnklen; + + linkbuffer = malloc(linkbuffer_len + 1); + if (linkbuffer == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Couldn't read link data"); + return (ARCHIVE_FAILED); + } + if (a->tree != NULL) { +#ifdef HAVE_READLINKAT + lnklen = readlinkat(a->tree_current_dir_fd(a->tree), + path, linkbuffer, linkbuffer_len); +#else + if (a->tree_enter_working_dir(a->tree) != 0) { + archive_set_error(&a->archive, errno, + "Couldn't read link data"); + free(linkbuffer); + return (ARCHIVE_FAILED); + } + lnklen = readlink(path, linkbuffer, linkbuffer_len); +#endif /* HAVE_READLINKAT */ + } else + lnklen = readlink(path, linkbuffer, linkbuffer_len); + if (lnklen < 0) { + archive_set_error(&a->archive, errno, + "Couldn't read link data"); + free(linkbuffer); + return (ARCHIVE_FAILED); + } + linkbuffer[lnklen] = '\0'; + archive_entry_set_symlink(entry, linkbuffer); + free(linkbuffer); + } +#endif /* HAVE_READLINK || HAVE_READLINKAT */ + + r = 0; + if ((a->flags & ARCHIVE_READDISK_NO_ACL) == 0) + r = archive_read_disk_entry_setup_acls(a, entry, &fd); + if ((a->flags & ARCHIVE_READDISK_NO_XATTR) == 0) { + r1 = setup_xattrs(a, entry, &fd); + if (r1 < r) + r = r1; + } + if (a->flags & ARCHIVE_READDISK_MAC_COPYFILE) { + r1 = setup_mac_metadata(a, entry, &fd); + if (r1 < r) + r = r1; + } + r1 = setup_sparse(a, entry, &fd); + if (r1 < r) + r = r1; + + /* If we opened the file earlier in this function, close it. */ + if (initial_fd != fd) + close(fd); + return (r); +} + +#if defined(__APPLE__) && defined(HAVE_COPYFILE_H) +/* + * The Mac OS "copyfile()" API copies the extended metadata for a + * file into a separate file in AppleDouble format (see RFC 1740). + * + * Mac OS tar and cpio implementations store this extended + * metadata as a separate entry just before the regular entry + * with a "._" prefix added to the filename. + * + * Note that this is currently done unconditionally; the tar program has + * an option to discard this information before the archive is written. + * + * TODO: If there's a failure, report it and return ARCHIVE_WARN. + */ +static int +setup_mac_metadata(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + int tempfd = -1; + int copyfile_flags = COPYFILE_NOFOLLOW | COPYFILE_ACL | COPYFILE_XATTR; + struct stat copyfile_stat; + int ret = ARCHIVE_OK; + void *buff = NULL; + int have_attrs; + const char *name, *tempdir; + struct archive_string tempfile; + + (void)fd; /* UNUSED */ + + name = archive_read_disk_entry_setup_path(a, entry, NULL); + if (name == NULL) + return (ARCHIVE_WARN); + + /* Short-circuit if there's nothing to do. */ + have_attrs = copyfile(name, NULL, 0, copyfile_flags | COPYFILE_CHECK); + if (have_attrs == -1) { + archive_set_error(&a->archive, errno, + "Could not check extended attributes"); + return (ARCHIVE_WARN); + } + if (have_attrs == 0) + return (ARCHIVE_OK); + + tempdir = NULL; + if (issetugid() == 0) + tempdir = getenv("TMPDIR"); + if (tempdir == NULL) + tempdir = _PATH_TMP; + archive_string_init(&tempfile); + archive_strcpy(&tempfile, tempdir); + archive_strcat(&tempfile, "tar.md.XXXXXX"); + tempfd = mkstemp(tempfile.s); + if (tempfd < 0) { + archive_set_error(&a->archive, errno, + "Could not open extended attribute file"); + ret = ARCHIVE_WARN; + goto cleanup; + } + __archive_ensure_cloexec_flag(tempfd); + + /* XXX I wish copyfile() could pack directly to a memory + * buffer; that would avoid the temp file here. For that + * matter, it would be nice if fcopyfile() actually worked, + * that would reduce the many open/close races here. */ + if (copyfile(name, tempfile.s, 0, copyfile_flags | COPYFILE_PACK)) { + archive_set_error(&a->archive, errno, + "Could not pack extended attributes"); + ret = ARCHIVE_WARN; + goto cleanup; + } + if (fstat(tempfd, ©file_stat)) { + archive_set_error(&a->archive, errno, + "Could not check size of extended attributes"); + ret = ARCHIVE_WARN; + goto cleanup; + } + buff = malloc(copyfile_stat.st_size); + if (buff == NULL) { + archive_set_error(&a->archive, errno, + "Could not allocate memory for extended attributes"); + ret = ARCHIVE_WARN; + goto cleanup; + } + if (copyfile_stat.st_size != read(tempfd, buff, copyfile_stat.st_size)) { + archive_set_error(&a->archive, errno, + "Could not read extended attributes into memory"); + ret = ARCHIVE_WARN; + goto cleanup; + } + archive_entry_copy_mac_metadata(entry, buff, copyfile_stat.st_size); + +cleanup: + if (tempfd >= 0) { + close(tempfd); + unlink(tempfile.s); + } + archive_string_free(&tempfile); + free(buff); + return (ret); +} + +#else + +/* + * Stub implementation for non-Mac systems. + */ +static int +setup_mac_metadata(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + (void)a; /* UNUSED */ + (void)entry; /* UNUSED */ + (void)fd; /* UNUSED */ + return (ARCHIVE_OK); +} +#endif + +#if ARCHIVE_XATTR_LINUX || ARCHIVE_XATTR_DARWIN || ARCHIVE_XATTR_AIX + +/* + * Linux, Darwin and AIX extended attribute support. + * + * TODO: By using a stack-allocated buffer for the first + * call to getxattr(), we might be able to avoid the second + * call entirely. We only need the second call if the + * stack-allocated buffer is too small. But a modest buffer + * of 1024 bytes or so will often be big enough. Same applies + * to listxattr(). + */ + + +static int +setup_xattr(struct archive_read_disk *a, + struct archive_entry *entry, const char *name, int fd, const char *accpath) +{ + ssize_t size; + void *value = NULL; + + + if (fd >= 0) { +#if ARCHIVE_XATTR_LINUX + size = fgetxattr(fd, name, NULL, 0); +#elif ARCHIVE_XATTR_DARWIN + size = fgetxattr(fd, name, NULL, 0, 0, 0); +#elif ARCHIVE_XATTR_AIX + size = fgetea(fd, name, NULL, 0); +#endif + } else if (!a->follow_symlinks) { +#if ARCHIVE_XATTR_LINUX + size = lgetxattr(accpath, name, NULL, 0); +#elif ARCHIVE_XATTR_DARWIN + size = getxattr(accpath, name, NULL, 0, 0, XATTR_NOFOLLOW); +#elif ARCHIVE_XATTR_AIX + size = lgetea(accpath, name, NULL, 0); +#endif + } else { +#if ARCHIVE_XATTR_LINUX + size = getxattr(accpath, name, NULL, 0); +#elif ARCHIVE_XATTR_DARWIN + size = getxattr(accpath, name, NULL, 0, 0, 0); +#elif ARCHIVE_XATTR_AIX + size = getea(accpath, name, NULL, 0); +#endif + } + + if (size == -1) { + archive_set_error(&a->archive, errno, + "Couldn't query extended attribute"); + return (ARCHIVE_WARN); + } + + if (size > 0 && (value = malloc(size)) == NULL) { + archive_set_error(&a->archive, errno, "Out of memory"); + return (ARCHIVE_FATAL); + } + + + if (fd >= 0) { +#if ARCHIVE_XATTR_LINUX + size = fgetxattr(fd, name, value, size); +#elif ARCHIVE_XATTR_DARWIN + size = fgetxattr(fd, name, value, size, 0, 0); +#elif ARCHIVE_XATTR_AIX + size = fgetea(fd, name, value, size); +#endif + } else if (!a->follow_symlinks) { +#if ARCHIVE_XATTR_LINUX + size = lgetxattr(accpath, name, value, size); +#elif ARCHIVE_XATTR_DARWIN + size = getxattr(accpath, name, value, size, 0, XATTR_NOFOLLOW); +#elif ARCHIVE_XATTR_AIX + size = lgetea(accpath, name, value, size); +#endif + } else { +#if ARCHIVE_XATTR_LINUX + size = getxattr(accpath, name, value, size); +#elif ARCHIVE_XATTR_DARWIN + size = getxattr(accpath, name, value, size, 0, 0); +#elif ARCHIVE_XATTR_AIX + size = getea(accpath, name, value, size); +#endif + } + + if (size == -1) { + archive_set_error(&a->archive, errno, + "Couldn't read extended attribute"); + return (ARCHIVE_WARN); + } + + archive_entry_xattr_add_entry(entry, name, value, size); + + free(value); + return (ARCHIVE_OK); +} + +static int +setup_xattrs(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + char *list, *p; + const char *path; + ssize_t list_size; + + path = NULL; + + if (*fd < 0) { + path = archive_read_disk_entry_setup_path(a, entry, fd); + if (path == NULL) + return (ARCHIVE_WARN); + } + + if (*fd >= 0) { +#if ARCHIVE_XATTR_LINUX + list_size = flistxattr(*fd, NULL, 0); +#elif ARCHIVE_XATTR_DARWIN + list_size = flistxattr(*fd, NULL, 0, 0); +#elif ARCHIVE_XATTR_AIX + list_size = flistea(*fd, NULL, 0); +#endif + } else if (!a->follow_symlinks) { +#if ARCHIVE_XATTR_LINUX + list_size = llistxattr(path, NULL, 0); +#elif ARCHIVE_XATTR_DARWIN + list_size = listxattr(path, NULL, 0, XATTR_NOFOLLOW); +#elif ARCHIVE_XATTR_AIX + list_size = llistea(path, NULL, 0); +#endif + } else { +#if ARCHIVE_XATTR_LINUX + list_size = listxattr(path, NULL, 0); +#elif ARCHIVE_XATTR_DARWIN + list_size = listxattr(path, NULL, 0, 0); +#elif ARCHIVE_XATTR_AIX + list_size = listea(path, NULL, 0); +#endif + } + + if (list_size == -1) { + if (errno == ENOTSUP || errno == ENOSYS) + return (ARCHIVE_OK); + archive_set_error(&a->archive, errno, + "Couldn't list extended attributes"); + return (ARCHIVE_WARN); + } + + if (list_size == 0) + return (ARCHIVE_OK); + + if ((list = malloc(list_size)) == NULL) { + archive_set_error(&a->archive, errno, "Out of memory"); + return (ARCHIVE_FATAL); + } + + if (*fd >= 0) { +#if ARCHIVE_XATTR_LINUX + list_size = flistxattr(*fd, list, list_size); +#elif ARCHIVE_XATTR_DARWIN + list_size = flistxattr(*fd, list, list_size, 0); +#elif ARCHIVE_XATTR_AIX + list_size = flistea(*fd, list, list_size); +#endif + } else if (!a->follow_symlinks) { +#if ARCHIVE_XATTR_LINUX + list_size = llistxattr(path, list, list_size); +#elif ARCHIVE_XATTR_DARWIN + list_size = listxattr(path, list, list_size, XATTR_NOFOLLOW); +#elif ARCHIVE_XATTR_AIX + list_size = llistea(path, list, list_size); +#endif + } else { +#if ARCHIVE_XATTR_LINUX + list_size = listxattr(path, list, list_size); +#elif ARCHIVE_XATTR_DARWIN + list_size = listxattr(path, list, list_size, 0); +#elif ARCHIVE_XATTR_AIX + list_size = listea(path, list, list_size); +#endif + } + + if (list_size == -1) { + archive_set_error(&a->archive, errno, + "Couldn't retrieve extended attributes"); + free(list); + return (ARCHIVE_WARN); + } + + for (p = list; (p - list) < list_size; p += strlen(p) + 1) { +#if ARCHIVE_XATTR_LINUX + /* Linux: skip POSIX.1e ACL extended attributes */ + if (strncmp(p, "system.", 7) == 0 && + (strcmp(p + 7, "posix_acl_access") == 0 || + strcmp(p + 7, "posix_acl_default") == 0)) + continue; + if (strncmp(p, "trusted.SGI_", 12) == 0 && + (strcmp(p + 12, "ACL_DEFAULT") == 0 || + strcmp(p + 12, "ACL_FILE") == 0)) + continue; + + /* Linux: xfsroot namespace is obsolete and unsupported */ + if (strncmp(p, "xfsroot.", 8) == 0) + continue; +#endif + setup_xattr(a, entry, p, *fd, path); + } + + free(list); + return (ARCHIVE_OK); +} + +#elif ARCHIVE_XATTR_FREEBSD + +/* + * FreeBSD extattr interface. + */ + +/* TODO: Implement this. Follow the Linux model above, but + * with FreeBSD-specific system calls, of course. Be careful + * to not include the system extattrs that hold ACLs; we handle + * those separately. + */ +static int +setup_xattr(struct archive_read_disk *a, struct archive_entry *entry, + int namespace, const char *name, const char *fullname, int fd, + const char *path); + +static int +setup_xattr(struct archive_read_disk *a, struct archive_entry *entry, + int namespace, const char *name, const char *fullname, int fd, + const char *accpath) +{ + ssize_t size; + void *value = NULL; + + if (fd >= 0) + size = extattr_get_fd(fd, namespace, name, NULL, 0); + else if (!a->follow_symlinks) + size = extattr_get_link(accpath, namespace, name, NULL, 0); + else + size = extattr_get_file(accpath, namespace, name, NULL, 0); + + if (size == -1) { + archive_set_error(&a->archive, errno, + "Couldn't query extended attribute"); + return (ARCHIVE_WARN); + } + + if (size > 0 && (value = malloc(size)) == NULL) { + archive_set_error(&a->archive, errno, "Out of memory"); + return (ARCHIVE_FATAL); + } + + if (fd >= 0) + size = extattr_get_fd(fd, namespace, name, value, size); + else if (!a->follow_symlinks) + size = extattr_get_link(accpath, namespace, name, value, size); + else + size = extattr_get_file(accpath, namespace, name, value, size); + + if (size == -1) { + free(value); + archive_set_error(&a->archive, errno, + "Couldn't read extended attribute"); + return (ARCHIVE_WARN); + } + + archive_entry_xattr_add_entry(entry, fullname, value, size); + + free(value); + return (ARCHIVE_OK); +} + +static int +setup_xattrs(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + char buff[512]; + char *list, *p; + ssize_t list_size; + const char *path; + int namespace = EXTATTR_NAMESPACE_USER; + + path = NULL; + + if (*fd < 0) { + path = archive_read_disk_entry_setup_path(a, entry, fd); + if (path == NULL) + return (ARCHIVE_WARN); + } + + if (*fd >= 0) + list_size = extattr_list_fd(*fd, namespace, NULL, 0); + else if (!a->follow_symlinks) + list_size = extattr_list_link(path, namespace, NULL, 0); + else + list_size = extattr_list_file(path, namespace, NULL, 0); + + if (list_size == -1 && errno == EOPNOTSUPP) + return (ARCHIVE_OK); + if (list_size == -1) { + archive_set_error(&a->archive, errno, + "Couldn't list extended attributes"); + return (ARCHIVE_WARN); + } + + if (list_size == 0) + return (ARCHIVE_OK); + + if ((list = malloc(list_size)) == NULL) { + archive_set_error(&a->archive, errno, "Out of memory"); + return (ARCHIVE_FATAL); + } + + if (*fd >= 0) + list_size = extattr_list_fd(*fd, namespace, list, list_size); + else if (!a->follow_symlinks) + list_size = extattr_list_link(path, namespace, list, list_size); + else + list_size = extattr_list_file(path, namespace, list, list_size); + + if (list_size == -1) { + archive_set_error(&a->archive, errno, + "Couldn't retrieve extended attributes"); + free(list); + return (ARCHIVE_WARN); + } + + p = list; + while ((p - list) < list_size) { + size_t len = 255 & (int)*p; + char *name; + + strcpy(buff, "user."); + name = buff + strlen(buff); + memcpy(name, p + 1, len); + name[len] = '\0'; + setup_xattr(a, entry, namespace, name, buff, *fd, path); + p += 1 + len; + } + + free(list); + return (ARCHIVE_OK); +} + +#else + +/* + * Generic (stub) extended attribute support. + */ +static int +setup_xattrs(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + (void)a; /* UNUSED */ + (void)entry; /* UNUSED */ + (void)fd; /* UNUSED */ + return (ARCHIVE_OK); +} + +#endif + +#if defined(HAVE_LINUX_FIEMAP_H) + +/* + * Linux FIEMAP sparse interface. + * + * The FIEMAP ioctl returns an "extent" for each physical allocation + * on disk. We need to process those to generate a more compact list + * of logical file blocks. We also need to be very careful to use + * FIEMAP_FLAG_SYNC here, since there are reports that Linux sometimes + * does not report allocations for newly-written data that hasn't + * been synced to disk. + * + * It's important to return a minimal sparse file list because we want + * to not trigger sparse file extensions if we don't have to, since + * not all readers support them. + */ + +static int +setup_sparse_fiemap(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + char buff[4096]; + struct fiemap *fm; + struct fiemap_extent *fe; + int64_t size; + int count, do_fiemap, iters; + int exit_sts = ARCHIVE_OK; + const char *path; + + if (archive_entry_filetype(entry) != AE_IFREG + || archive_entry_size(entry) <= 0 + || archive_entry_hardlink(entry) != NULL) + return (ARCHIVE_OK); + + if (*fd < 0) { + path = archive_read_disk_entry_setup_path(a, entry, NULL); + if (path == NULL) + return (ARCHIVE_FAILED); + + if (a->tree != NULL) + *fd = a->open_on_current_dir(a->tree, path, + O_RDONLY | O_NONBLOCK | O_CLOEXEC); + else + *fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC); + if (*fd < 0) { + archive_set_error(&a->archive, errno, + "Can't open `%s'", path); + return (ARCHIVE_FAILED); + } + __archive_ensure_cloexec_flag(*fd); + } + + /* Initialize buffer to avoid the error valgrind complains about. */ + memset(buff, 0, sizeof(buff)); + count = (sizeof(buff) - sizeof(*fm))/sizeof(*fe); + fm = (struct fiemap *)buff; + fm->fm_start = 0; + fm->fm_length = ~0ULL;; + fm->fm_flags = FIEMAP_FLAG_SYNC; + fm->fm_extent_count = count; + do_fiemap = 1; + size = archive_entry_size(entry); + for (iters = 0; ; ++iters) { + int i, r; + + r = ioctl(*fd, FS_IOC_FIEMAP, fm); + if (r < 0) { + /* When something error happens, it is better we + * should return ARCHIVE_OK because an earlier + * version(<2.6.28) cannot perform FS_IOC_FIEMAP. */ + goto exit_setup_sparse_fiemap; + } + if (fm->fm_mapped_extents == 0) { + if (iters == 0) { + /* Fully sparse file; insert a zero-length "data" entry */ + archive_entry_sparse_add_entry(entry, 0, 0); + } + break; + } + fe = fm->fm_extents; + for (i = 0; i < (int)fm->fm_mapped_extents; i++, fe++) { + if (!(fe->fe_flags & FIEMAP_EXTENT_UNWRITTEN)) { + /* The fe_length of the last block does not + * adjust itself to its size files. */ + int64_t length = fe->fe_length; + if (fe->fe_logical + length > (uint64_t)size) + length -= fe->fe_logical + length - size; + if (fe->fe_logical == 0 && length == size) { + /* This is not sparse. */ + do_fiemap = 0; + break; + } + if (length > 0) + archive_entry_sparse_add_entry(entry, + fe->fe_logical, length); + } + if (fe->fe_flags & FIEMAP_EXTENT_LAST) + do_fiemap = 0; + } + if (do_fiemap) { + fe = fm->fm_extents + fm->fm_mapped_extents -1; + fm->fm_start = fe->fe_logical + fe->fe_length; + } else + break; + } +exit_setup_sparse_fiemap: + return (exit_sts); +} + +#if !defined(SEEK_HOLE) || !defined(SEEK_DATA) +static int +setup_sparse(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + return setup_sparse_fiemap(a, entry, fd); +} +#endif +#endif /* defined(HAVE_LINUX_FIEMAP_H) */ + +#if defined(SEEK_HOLE) && defined(SEEK_DATA) + +/* + * SEEK_HOLE sparse interface (FreeBSD, Linux, Solaris) + */ + +static int +setup_sparse(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + int64_t size; + off_t initial_off; + off_t off_s, off_e; + int exit_sts = ARCHIVE_OK; + int check_fully_sparse = 0; + const char *path; + + if (archive_entry_filetype(entry) != AE_IFREG + || archive_entry_size(entry) <= 0 + || archive_entry_hardlink(entry) != NULL) + return (ARCHIVE_OK); + + /* Does filesystem support the reporting of hole ? */ + if (*fd < 0) + path = archive_read_disk_entry_setup_path(a, entry, fd); + else + path = NULL; + + if (*fd >= 0) { +#ifdef _PC_MIN_HOLE_SIZE + if (fpathconf(*fd, _PC_MIN_HOLE_SIZE) <= 0) + return (ARCHIVE_OK); +#endif + initial_off = lseek(*fd, 0, SEEK_CUR); + if (initial_off != 0) + lseek(*fd, 0, SEEK_SET); + } else { + if (path == NULL) + return (ARCHIVE_FAILED); +#ifdef _PC_MIN_HOLE_SIZE + if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0) + return (ARCHIVE_OK); +#endif + *fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC); + if (*fd < 0) { + archive_set_error(&a->archive, errno, + "Can't open `%s'", path); + return (ARCHIVE_FAILED); + } + __archive_ensure_cloexec_flag(*fd); + initial_off = 0; + } + +#ifndef _PC_MIN_HOLE_SIZE + /* Check if the underlying filesystem supports seek hole */ + off_s = lseek(*fd, 0, SEEK_HOLE); + if (off_s < 0) +#if defined(HAVE_LINUX_FIEMAP_H) + return setup_sparse_fiemap(a, entry, fd); +#else + goto exit_setup_sparse; +#endif + else if (off_s > 0) + lseek(*fd, 0, SEEK_SET); +#endif + + off_s = 0; + size = archive_entry_size(entry); + while (off_s < size) { + off_s = lseek(*fd, off_s, SEEK_DATA); + if (off_s == (off_t)-1) { + if (errno == ENXIO) { + /* no more hole */ + if (archive_entry_sparse_count(entry) == 0) { + /* Potentially a fully-sparse file. */ + check_fully_sparse = 1; + } + break; + } + archive_set_error(&a->archive, errno, + "lseek(SEEK_HOLE) failed"); + exit_sts = ARCHIVE_FAILED; + goto exit_setup_sparse; + } + off_e = lseek(*fd, off_s, SEEK_HOLE); + if (off_e == (off_t)-1) { + if (errno == ENXIO) { + off_e = lseek(*fd, 0, SEEK_END); + if (off_e != (off_t)-1) + break;/* no more data */ + } + archive_set_error(&a->archive, errno, + "lseek(SEEK_DATA) failed"); + exit_sts = ARCHIVE_FAILED; + goto exit_setup_sparse; + } + if (off_s == 0 && off_e == size) + break;/* This is not sparse. */ + archive_entry_sparse_add_entry(entry, off_s, + off_e - off_s); + off_s = off_e; + } + + if (check_fully_sparse) { + if (lseek(*fd, 0, SEEK_HOLE) == 0 && + lseek(*fd, 0, SEEK_END) == size) { + /* Fully sparse file; insert a zero-length "data" entry */ + archive_entry_sparse_add_entry(entry, 0, 0); + } + } +exit_setup_sparse: + lseek(*fd, initial_off, SEEK_SET); + return (exit_sts); +} + +#elif !defined(HAVE_LINUX_FIEMAP_H) + +/* + * Generic (stub) sparse support. + */ +static int +setup_sparse(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + (void)a; /* UNUSED */ + (void)entry; /* UNUSED */ + (void)fd; /* UNUSED */ + return (ARCHIVE_OK); +} + +#endif + +#endif /* !defined(_WIN32) || defined(__CYGWIN__) */ + diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_disk_posix.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_disk_posix.c new file mode 100644 index 0000000..52fec7b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_disk_posix.c @@ -0,0 +1,2722 @@ +/*- + * Copyright (c) 2003-2009 Tim Kientzle + * Copyright (c) 2010-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* This is the tree-walking code for POSIX systems. */ +#if !defined(_WIN32) || defined(__CYGWIN__) + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#ifdef HAVE_SYS_MOUNT_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_SYS_STATFS_H +#include +#endif +#ifdef HAVE_SYS_STATVFS_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_LINUX_MAGIC_H +#include +#endif +#ifdef HAVE_LINUX_FS_H +#include +#endif +/* + * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h. + * As the include guards don't agree, the order of include is important. + */ +#ifdef HAVE_LINUX_EXT2_FS_H +#include /* for Linux file flags */ +#endif +#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__) +#include /* Linux file flags, broken on Cygwin */ +#endif +#ifdef HAVE_DIRECT_H +#include +#endif +#ifdef HAVE_DIRENT_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#include "archive.h" +#include "archive_string.h" +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_read_disk_private.h" + +#ifndef HAVE_FCHDIR +#error fchdir function required. +#endif +#ifndef O_BINARY +#define O_BINARY 0 +#endif +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + +/*- + * This is a new directory-walking system that addresses a number + * of problems I've had with fts(3). In particular, it has no + * pathname-length limits (other than the size of 'int'), handles + * deep logical traversals, uses considerably less memory, and has + * an opaque interface (easier to modify in the future). + * + * Internally, it keeps a single list of "tree_entry" items that + * represent filesystem objects that require further attention. + * Non-directories are not kept in memory: they are pulled from + * readdir(), returned to the client, then freed as soon as possible. + * Any directory entry to be traversed gets pushed onto the stack. + * + * There is surprisingly little information that needs to be kept for + * each item on the stack. Just the name, depth (represented here as the + * string length of the parent directory's pathname), and some markers + * indicating how to get back to the parent (via chdir("..") for a + * regular dir or via fchdir(2) for a symlink). + */ +/* + * TODO: + * 1) Loop checking. + * 3) Arbitrary logical traversals by closing/reopening intermediate fds. + */ + +struct restore_time { + const char *name; + time_t mtime; + long mtime_nsec; + time_t atime; + long atime_nsec; + mode_t filetype; + int noatime; +}; + +struct tree_entry { + int depth; + struct tree_entry *next; + struct tree_entry *parent; + struct archive_string name; + size_t dirname_length; + int64_t dev; + int64_t ino; + int flags; + int filesystem_id; + /* How to return back to the parent of a symlink. */ + int symlink_parent_fd; + /* How to restore time of a directory. */ + struct restore_time restore_time; +}; + +struct filesystem { + int64_t dev; + int synthetic; + int remote; + int noatime; +#if defined(USE_READDIR_R) + size_t name_max; +#endif + long incr_xfer_size; + long max_xfer_size; + long min_xfer_size; + long xfer_align; + + /* + * Buffer used for reading file contents. + */ + /* Exactly allocated memory pointer. */ + unsigned char *allocation_ptr; + /* Pointer adjusted to the filesystem alignment . */ + unsigned char *buff; + size_t buff_size; +}; + +/* Definitions for tree_entry.flags bitmap. */ +#define isDir 1 /* This entry is a regular directory. */ +#define isDirLink 2 /* This entry is a symbolic link to a directory. */ +#define needsFirstVisit 4 /* This is an initial entry. */ +#define needsDescent 8 /* This entry needs to be previsited. */ +#define needsOpen 16 /* This is a directory that needs to be opened. */ +#define needsAscent 32 /* This entry needs to be postvisited. */ + +/* + * Local data for this package. + */ +struct tree { + struct tree_entry *stack; + struct tree_entry *current; + DIR *d; +#define INVALID_DIR_HANDLE NULL + struct dirent *de; +#if defined(USE_READDIR_R) + struct dirent *dirent; + size_t dirent_allocated; +#endif + int flags; + int visit_type; + /* Error code from last failed operation. */ + int tree_errno; + + /* Dynamically-sized buffer for holding path */ + struct archive_string path; + + /* Last path element */ + const char *basename; + /* Leading dir length */ + size_t dirname_length; + + int depth; + int openCount; + int maxOpenCount; + int initial_dir_fd; + int working_dir_fd; + + struct stat lst; + struct stat st; + int descend; + int nlink; + /* How to restore time of a file. */ + struct restore_time restore_time; + + struct entry_sparse { + int64_t length; + int64_t offset; + } *sparse_list, *current_sparse; + int sparse_count; + int sparse_list_size; + + char initial_symlink_mode; + char symlink_mode; + struct filesystem *current_filesystem; + struct filesystem *filesystem_table; + int initial_filesystem_id; + int current_filesystem_id; + int max_filesystem_id; + int allocated_filesystem; + + int entry_fd; + int entry_eof; + int64_t entry_remaining_bytes; + int64_t entry_total; + unsigned char *entry_buff; + size_t entry_buff_size; +}; + +/* Definitions for tree.flags bitmap. */ +#define hasStat 16 /* The st entry is valid. */ +#define hasLstat 32 /* The lst entry is valid. */ +#define onWorkingDir 64 /* We are on the working dir where we are + * reading directory entry at this time. */ +#define needsRestoreTimes 128 +#define onInitialDir 256 /* We are on the initial dir. */ + +static int +tree_dir_next_posix(struct tree *t); + +#ifdef HAVE_DIRENT_D_NAMLEN +/* BSD extension; avoids need for a strlen() call. */ +#define D_NAMELEN(dp) (dp)->d_namlen +#else +#define D_NAMELEN(dp) (strlen((dp)->d_name)) +#endif + +/* Initiate/terminate a tree traversal. */ +static struct tree *tree_open(const char *, int, int); +static struct tree *tree_reopen(struct tree *, const char *, int); +static void tree_close(struct tree *); +static void tree_free(struct tree *); +static void tree_push(struct tree *, const char *, int, int64_t, int64_t, + struct restore_time *); +static int tree_enter_initial_dir(struct tree *); +static int tree_enter_working_dir(struct tree *); +static int tree_current_dir_fd(struct tree *); + +/* + * tree_next() returns Zero if there is no next entry, non-zero if + * there is. Note that directories are visited three times. + * Directories are always visited first as part of enumerating their + * parent; that is a "regular" visit. If tree_descend() is invoked at + * that time, the directory is added to a work list and will + * subsequently be visited two more times: once just after descending + * into the directory ("postdescent") and again just after ascending + * back to the parent ("postascent"). + * + * TREE_ERROR_DIR is returned if the descent failed (because the + * directory couldn't be opened, for instance). This is returned + * instead of TREE_POSTDESCENT/TREE_POSTASCENT. TREE_ERROR_DIR is not a + * fatal error, but it does imply that the relevant subtree won't be + * visited. TREE_ERROR_FATAL is returned for an error that left the + * traversal completely hosed. Right now, this is only returned for + * chdir() failures during ascent. + */ +#define TREE_REGULAR 1 +#define TREE_POSTDESCENT 2 +#define TREE_POSTASCENT 3 +#define TREE_ERROR_DIR -1 +#define TREE_ERROR_FATAL -2 + +static int tree_next(struct tree *); + +/* + * Return information about the current entry. + */ + +/* + * The current full pathname, length of the full pathname, and a name + * that can be used to access the file. Because tree does use chdir + * extensively, the access path is almost never the same as the full + * current path. + * + * TODO: On platforms that support it, use openat()-style operations + * to eliminate the chdir() operations entirely while still supporting + * arbitrarily deep traversals. This makes access_path troublesome to + * support, of course, which means we'll need a rich enough interface + * that clients can function without it. (In particular, we'll need + * tree_current_open() that returns an open file descriptor.) + * + */ +static const char *tree_current_path(struct tree *); +static const char *tree_current_access_path(struct tree *); + +/* + * Request the lstat() or stat() data for the current path. Since the + * tree package needs to do some of this anyway, and caches the + * results, you should take advantage of it here if you need it rather + * than make a redundant stat() or lstat() call of your own. + */ +static const struct stat *tree_current_stat(struct tree *); +static const struct stat *tree_current_lstat(struct tree *); +static int tree_current_is_symblic_link_target(struct tree *); + +/* The following functions use tricks to avoid a certain number of + * stat()/lstat() calls. */ +/* "is_physical_dir" is equivalent to S_ISDIR(tree_current_lstat()->st_mode) */ +static int tree_current_is_physical_dir(struct tree *); +/* "is_dir" is equivalent to S_ISDIR(tree_current_stat()->st_mode) */ +static int tree_current_is_dir(struct tree *); +static int update_current_filesystem(struct archive_read_disk *a, + int64_t dev); +static int setup_current_filesystem(struct archive_read_disk *); +static int tree_target_is_same_as_parent(struct tree *, const struct stat *); + +static int _archive_read_disk_open(struct archive *, const char *); +static int _archive_read_free(struct archive *); +static int _archive_read_close(struct archive *); +static int _archive_read_data_block(struct archive *, + const void **, size_t *, int64_t *); +static int _archive_read_next_header(struct archive *, + struct archive_entry **); +static int _archive_read_next_header2(struct archive *, + struct archive_entry *); +static const char *trivial_lookup_gname(void *, int64_t gid); +static const char *trivial_lookup_uname(void *, int64_t uid); +static int setup_sparse(struct archive_read_disk *, struct archive_entry *); +static int close_and_restore_time(int fd, struct tree *, + struct restore_time *); +static int open_on_current_dir(struct tree *, const char *, int); +static int tree_dup(int); + + +static struct archive_vtable * +archive_read_disk_vtable(void) +{ + static struct archive_vtable av; + static int inited = 0; + + if (!inited) { + av.archive_free = _archive_read_free; + av.archive_close = _archive_read_close; + av.archive_read_data_block = _archive_read_data_block; + av.archive_read_next_header = _archive_read_next_header; + av.archive_read_next_header2 = _archive_read_next_header2; + inited = 1; + } + return (&av); +} + +const char * +archive_read_disk_gname(struct archive *_a, la_int64_t gid) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_read_disk_gname")) + return (NULL); + if (a->lookup_gname == NULL) + return (NULL); + return ((*a->lookup_gname)(a->lookup_gname_data, gid)); +} + +const char * +archive_read_disk_uname(struct archive *_a, la_int64_t uid) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_read_disk_uname")) + return (NULL); + if (a->lookup_uname == NULL) + return (NULL); + return ((*a->lookup_uname)(a->lookup_uname_data, uid)); +} + +int +archive_read_disk_set_gname_lookup(struct archive *_a, + void *private_data, + const char * (*lookup_gname)(void *private, la_int64_t gid), + void (*cleanup_gname)(void *private)) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + archive_check_magic(&a->archive, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_read_disk_set_gname_lookup"); + + if (a->cleanup_gname != NULL && a->lookup_gname_data != NULL) + (a->cleanup_gname)(a->lookup_gname_data); + + a->lookup_gname = lookup_gname; + a->cleanup_gname = cleanup_gname; + a->lookup_gname_data = private_data; + return (ARCHIVE_OK); +} + +int +archive_read_disk_set_uname_lookup(struct archive *_a, + void *private_data, + const char * (*lookup_uname)(void *private, la_int64_t uid), + void (*cleanup_uname)(void *private)) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + archive_check_magic(&a->archive, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_read_disk_set_uname_lookup"); + + if (a->cleanup_uname != NULL && a->lookup_uname_data != NULL) + (a->cleanup_uname)(a->lookup_uname_data); + + a->lookup_uname = lookup_uname; + a->cleanup_uname = cleanup_uname; + a->lookup_uname_data = private_data; + return (ARCHIVE_OK); +} + +/* + * Create a new archive_read_disk object and initialize it with global state. + */ +struct archive * +archive_read_disk_new(void) +{ + struct archive_read_disk *a; + + a = (struct archive_read_disk *)calloc(1, sizeof(*a)); + if (a == NULL) + return (NULL); + a->archive.magic = ARCHIVE_READ_DISK_MAGIC; + a->archive.state = ARCHIVE_STATE_NEW; + a->archive.vtable = archive_read_disk_vtable(); + a->entry = archive_entry_new2(&a->archive); + a->lookup_uname = trivial_lookup_uname; + a->lookup_gname = trivial_lookup_gname; + a->flags = ARCHIVE_READDISK_MAC_COPYFILE; + a->open_on_current_dir = open_on_current_dir; + a->tree_current_dir_fd = tree_current_dir_fd; + a->tree_enter_working_dir = tree_enter_working_dir; + return (&a->archive); +} + +static int +_archive_read_free(struct archive *_a) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + int r; + + if (_a == NULL) + return (ARCHIVE_OK); + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_free"); + + if (a->archive.state != ARCHIVE_STATE_CLOSED) + r = _archive_read_close(&a->archive); + else + r = ARCHIVE_OK; + + tree_free(a->tree); + if (a->cleanup_gname != NULL && a->lookup_gname_data != NULL) + (a->cleanup_gname)(a->lookup_gname_data); + if (a->cleanup_uname != NULL && a->lookup_uname_data != NULL) + (a->cleanup_uname)(a->lookup_uname_data); + archive_string_free(&a->archive.error_string); + archive_entry_free(a->entry); + a->archive.magic = 0; + __archive_clean(&a->archive); + free(a); + return (r); +} + +static int +_archive_read_close(struct archive *_a) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_close"); + + if (a->archive.state != ARCHIVE_STATE_FATAL) + a->archive.state = ARCHIVE_STATE_CLOSED; + + tree_close(a->tree); + + return (ARCHIVE_OK); +} + +static void +setup_symlink_mode(struct archive_read_disk *a, char symlink_mode, + int follow_symlinks) +{ + a->symlink_mode = symlink_mode; + a->follow_symlinks = follow_symlinks; + if (a->tree != NULL) { + a->tree->initial_symlink_mode = a->symlink_mode; + a->tree->symlink_mode = a->symlink_mode; + } +} + +int +archive_read_disk_set_symlink_logical(struct archive *_a) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_read_disk_set_symlink_logical"); + setup_symlink_mode(a, 'L', 1); + return (ARCHIVE_OK); +} + +int +archive_read_disk_set_symlink_physical(struct archive *_a) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_read_disk_set_symlink_physical"); + setup_symlink_mode(a, 'P', 0); + return (ARCHIVE_OK); +} + +int +archive_read_disk_set_symlink_hybrid(struct archive *_a) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_read_disk_set_symlink_hybrid"); + setup_symlink_mode(a, 'H', 1);/* Follow symlinks initially. */ + return (ARCHIVE_OK); +} + +int +archive_read_disk_set_atime_restored(struct archive *_a) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_read_disk_restore_atime"); +#ifdef HAVE_UTIMES + a->flags |= ARCHIVE_READDISK_RESTORE_ATIME; + if (a->tree != NULL) + a->tree->flags |= needsRestoreTimes; + return (ARCHIVE_OK); +#else + /* Display warning and unset flag */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Cannot restore access time on this system"); + a->flags &= ~ARCHIVE_READDISK_RESTORE_ATIME; + return (ARCHIVE_WARN); +#endif +} + +int +archive_read_disk_set_behavior(struct archive *_a, int flags) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + int r = ARCHIVE_OK; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_read_disk_honor_nodump"); + + a->flags = flags; + + if (flags & ARCHIVE_READDISK_RESTORE_ATIME) + r = archive_read_disk_set_atime_restored(_a); + else { + if (a->tree != NULL) + a->tree->flags &= ~needsRestoreTimes; + } + return (r); +} + +/* + * Trivial implementations of gname/uname lookup functions. + * These are normally overridden by the client, but these stub + * versions ensure that we always have something that works. + */ +static const char * +trivial_lookup_gname(void *private_data, int64_t gid) +{ + (void)private_data; /* UNUSED */ + (void)gid; /* UNUSED */ + return (NULL); +} + +static const char * +trivial_lookup_uname(void *private_data, int64_t uid) +{ + (void)private_data; /* UNUSED */ + (void)uid; /* UNUSED */ + return (NULL); +} + +/* + * Allocate memory for the reading buffer adjusted to the filesystem + * alignment. + */ +static int +setup_suitable_read_buffer(struct archive_read_disk *a) +{ + struct tree *t = a->tree; + struct filesystem *cf = t->current_filesystem; + size_t asize; + size_t s; + + if (cf->allocation_ptr == NULL) { + /* If we couldn't get a filesystem alignment, + * we use 4096 as default value but we won't use + * O_DIRECT to open() and openat() operations. */ + long xfer_align = (cf->xfer_align == -1)?4096:cf->xfer_align; + + if (cf->max_xfer_size != -1) + asize = cf->max_xfer_size + xfer_align; + else { + long incr = cf->incr_xfer_size; + /* Some platform does not set a proper value to + * incr_xfer_size.*/ + if (incr < 0) + incr = cf->min_xfer_size; + if (cf->min_xfer_size < 0) { + incr = xfer_align; + asize = xfer_align; + } else + asize = cf->min_xfer_size; + + /* Increase a buffer size up to 64K bytes in + * a proper increment size. */ + while (asize < 1024*64) + asize += incr; + /* Take a margin to adjust to the filesystem + * alignment. */ + asize += xfer_align; + } + cf->allocation_ptr = malloc(asize); + if (cf->allocation_ptr == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Couldn't allocate memory"); + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } + + /* + * Calculate proper address for the filesystem. + */ + s = (uintptr_t)cf->allocation_ptr; + s %= xfer_align; + if (s > 0) + s = xfer_align - s; + + /* + * Set a read buffer pointer in the proper alignment of + * the current filesystem. + */ + cf->buff = cf->allocation_ptr + s; + cf->buff_size = asize - xfer_align; + } + return (ARCHIVE_OK); +} + +static int +_archive_read_data_block(struct archive *_a, const void **buff, + size_t *size, int64_t *offset) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + struct tree *t = a->tree; + int r; + ssize_t bytes; + int64_t sparse_bytes; + size_t buffbytes; + int empty_sparse_region = 0; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA, + "archive_read_data_block"); + + if (t->entry_eof || t->entry_remaining_bytes <= 0) { + r = ARCHIVE_EOF; + goto abort_read_data; + } + + /* + * Open the current file. + */ + if (t->entry_fd < 0) { + int flags = O_RDONLY | O_BINARY | O_CLOEXEC; + + /* + * Eliminate or reduce cache effects if we can. + * + * Carefully consider this to be enabled. + */ +#if defined(O_DIRECT) && 0/* Disabled for now */ + if (t->current_filesystem->xfer_align != -1 && + t->nlink == 1) + flags |= O_DIRECT; +#endif +#if defined(O_NOATIME) + /* + * Linux has O_NOATIME flag; use it if we need. + */ + if ((t->flags & needsRestoreTimes) != 0 && + t->restore_time.noatime == 0) + flags |= O_NOATIME; +#endif + t->entry_fd = open_on_current_dir(t, + tree_current_access_path(t), flags); + __archive_ensure_cloexec_flag(t->entry_fd); +#if defined(O_NOATIME) + /* + * When we did open the file with O_NOATIME flag, + * if successful, set 1 to t->restore_time.noatime + * not to restore an atime of the file later. + * if failed by EPERM, retry it without O_NOATIME flag. + */ + if (flags & O_NOATIME) { + if (t->entry_fd >= 0) + t->restore_time.noatime = 1; + else if (errno == EPERM) + flags &= ~O_NOATIME; + } +#endif + if (t->entry_fd < 0) { + archive_set_error(&a->archive, errno, + "Couldn't open %s", tree_current_path(t)); + r = ARCHIVE_FAILED; + tree_enter_initial_dir(t); + goto abort_read_data; + } + tree_enter_initial_dir(t); + } + + /* + * Allocate read buffer if not allocated. + */ + if (t->current_filesystem->allocation_ptr == NULL) { + r = setup_suitable_read_buffer(a); + if (r != ARCHIVE_OK) { + a->archive.state = ARCHIVE_STATE_FATAL; + goto abort_read_data; + } + } + t->entry_buff = t->current_filesystem->buff; + t->entry_buff_size = t->current_filesystem->buff_size; + + buffbytes = t->entry_buff_size; + if ((int64_t)buffbytes > t->current_sparse->length) + buffbytes = t->current_sparse->length; + + if (t->current_sparse->length == 0) + empty_sparse_region = 1; + + /* + * Skip hole. + * TODO: Should we consider t->current_filesystem->xfer_align? + */ + if (t->current_sparse->offset > t->entry_total) { + if (lseek(t->entry_fd, + (off_t)t->current_sparse->offset, SEEK_SET) < 0) { + archive_set_error(&a->archive, errno, "Seek error"); + r = ARCHIVE_FATAL; + a->archive.state = ARCHIVE_STATE_FATAL; + goto abort_read_data; + } + sparse_bytes = t->current_sparse->offset - t->entry_total; + t->entry_remaining_bytes -= sparse_bytes; + t->entry_total += sparse_bytes; + } + + /* + * Read file contents. + */ + if (buffbytes > 0) { + bytes = read(t->entry_fd, t->entry_buff, buffbytes); + if (bytes < 0) { + archive_set_error(&a->archive, errno, "Read error"); + r = ARCHIVE_FATAL; + a->archive.state = ARCHIVE_STATE_FATAL; + goto abort_read_data; + } + } else + bytes = 0; + /* + * Return an EOF unless we've read a leading empty sparse region, which + * is used to represent fully-sparse files. + */ + if (bytes == 0 && !empty_sparse_region) { + /* Get EOF */ + t->entry_eof = 1; + r = ARCHIVE_EOF; + goto abort_read_data; + } + *buff = t->entry_buff; + *size = bytes; + *offset = t->entry_total; + t->entry_total += bytes; + t->entry_remaining_bytes -= bytes; + if (t->entry_remaining_bytes == 0) { + /* Close the current file descriptor */ + close_and_restore_time(t->entry_fd, t, &t->restore_time); + t->entry_fd = -1; + t->entry_eof = 1; + } + t->current_sparse->offset += bytes; + t->current_sparse->length -= bytes; + if (t->current_sparse->length == 0 && !t->entry_eof) + t->current_sparse++; + return (ARCHIVE_OK); + +abort_read_data: + *buff = NULL; + *size = 0; + *offset = t->entry_total; + if (t->entry_fd >= 0) { + /* Close the current file descriptor */ + close_and_restore_time(t->entry_fd, t, &t->restore_time); + t->entry_fd = -1; + } + return (r); +} + +static int +next_entry(struct archive_read_disk *a, struct tree *t, + struct archive_entry *entry) +{ + const struct stat *st; /* info to use for this entry */ + const struct stat *lst;/* lstat() information */ + const char *name; + int delayed, delayed_errno, descend, r; + struct archive_string delayed_str; + + delayed = ARCHIVE_OK; + delayed_errno = 0; + archive_string_init(&delayed_str); + + st = NULL; + lst = NULL; + t->descend = 0; + do { + switch (tree_next(t)) { + case TREE_ERROR_FATAL: + archive_set_error(&a->archive, t->tree_errno, + "%s: Unable to continue traversing directory tree", + tree_current_path(t)); + a->archive.state = ARCHIVE_STATE_FATAL; + tree_enter_initial_dir(t); + return (ARCHIVE_FATAL); + case TREE_ERROR_DIR: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "%s: Couldn't visit directory", + tree_current_path(t)); + tree_enter_initial_dir(t); + return (ARCHIVE_FAILED); + case 0: + tree_enter_initial_dir(t); + return (ARCHIVE_EOF); + case TREE_POSTDESCENT: + case TREE_POSTASCENT: + break; + case TREE_REGULAR: + lst = tree_current_lstat(t); + if (lst == NULL) { + if (errno == ENOENT && t->depth > 0) { + delayed = ARCHIVE_WARN; + delayed_errno = errno; + if (delayed_str.length == 0) { + archive_string_sprintf(&delayed_str, + "%s", tree_current_path(t)); + } else { + archive_string_sprintf(&delayed_str, + " %s", tree_current_path(t)); + } + } else { + archive_set_error(&a->archive, errno, + "%s: Cannot stat", + tree_current_path(t)); + tree_enter_initial_dir(t); + return (ARCHIVE_FAILED); + } + } + break; + } + } while (lst == NULL); + +#ifdef __APPLE__ + if (a->flags & ARCHIVE_READDISK_MAC_COPYFILE) { + /* If we're using copyfile(), ignore "._XXX" files. */ + const char *bname = strrchr(tree_current_path(t), '/'); + if (bname == NULL) + bname = tree_current_path(t); + else + ++bname; + if (bname[0] == '.' && bname[1] == '_') + return (ARCHIVE_RETRY); + } +#endif + + archive_entry_copy_pathname(entry, tree_current_path(t)); + /* + * Perform path matching. + */ + if (a->matching) { + r = archive_match_path_excluded(a->matching, entry); + if (r < 0) { + archive_set_error(&(a->archive), errno, + "Failed : %s", archive_error_string(a->matching)); + return (r); + } + if (r) { + if (a->excluded_cb_func) + a->excluded_cb_func(&(a->archive), + a->excluded_cb_data, entry); + return (ARCHIVE_RETRY); + } + } + + /* + * Distinguish 'L'/'P'/'H' symlink following. + */ + switch(t->symlink_mode) { + case 'H': + /* 'H': After the first item, rest like 'P'. */ + t->symlink_mode = 'P'; + /* 'H': First item (from command line) like 'L'. */ + /* FALLTHROUGH */ + case 'L': + /* 'L': Do descend through a symlink to dir. */ + descend = tree_current_is_dir(t); + /* 'L': Follow symlinks to files. */ + a->symlink_mode = 'L'; + a->follow_symlinks = 1; + /* 'L': Archive symlinks as targets, if we can. */ + st = tree_current_stat(t); + if (st != NULL && !tree_target_is_same_as_parent(t, st)) + break; + /* If stat fails, we have a broken symlink; + * in that case, don't follow the link. */ + /* FALLTHROUGH */ + default: + /* 'P': Don't descend through a symlink to dir. */ + descend = tree_current_is_physical_dir(t); + /* 'P': Don't follow symlinks to files. */ + a->symlink_mode = 'P'; + a->follow_symlinks = 0; + /* 'P': Archive symlinks as symlinks. */ + st = lst; + break; + } + + if (update_current_filesystem(a, st->st_dev) != ARCHIVE_OK) { + a->archive.state = ARCHIVE_STATE_FATAL; + tree_enter_initial_dir(t); + return (ARCHIVE_FATAL); + } + if (t->initial_filesystem_id == -1) + t->initial_filesystem_id = t->current_filesystem_id; + if (a->flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) { + if (t->initial_filesystem_id != t->current_filesystem_id) + descend = 0; + } + t->descend = descend; + + /* + * Honor nodump flag. + * If the file is marked with nodump flag, do not return this entry. + */ + if (a->flags & ARCHIVE_READDISK_HONOR_NODUMP) { +#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP) + if (st->st_flags & UF_NODUMP) + return (ARCHIVE_RETRY); +#elif (defined(FS_IOC_GETFLAGS) && defined(FS_NODUMP_FL) && \ + defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \ + (defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL) && \ + defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)) + if (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode)) { + int stflags; + + t->entry_fd = open_on_current_dir(t, + tree_current_access_path(t), + O_RDONLY | O_NONBLOCK | O_CLOEXEC); + __archive_ensure_cloexec_flag(t->entry_fd); + if (t->entry_fd >= 0) { + r = ioctl(t->entry_fd, +#ifdef FS_IOC_GETFLAGS + FS_IOC_GETFLAGS, +#else + EXT2_IOC_GETFLAGS, +#endif + &stflags); +#ifdef FS_NODUMP_FL + if (r == 0 && (stflags & FS_NODUMP_FL) != 0) +#else + if (r == 0 && (stflags & EXT2_NODUMP_FL) != 0) +#endif + return (ARCHIVE_RETRY); + } + } +#endif + } + + archive_entry_copy_stat(entry, st); + + /* Save the times to be restored. This must be in before + * calling archive_read_disk_descend() or any chance of it, + * especially, invoking a callback. */ + t->restore_time.mtime = archive_entry_mtime(entry); + t->restore_time.mtime_nsec = archive_entry_mtime_nsec(entry); + t->restore_time.atime = archive_entry_atime(entry); + t->restore_time.atime_nsec = archive_entry_atime_nsec(entry); + t->restore_time.filetype = archive_entry_filetype(entry); + t->restore_time.noatime = t->current_filesystem->noatime; + + /* + * Perform time matching. + */ + if (a->matching) { + r = archive_match_time_excluded(a->matching, entry); + if (r < 0) { + archive_set_error(&(a->archive), errno, + "Failed : %s", archive_error_string(a->matching)); + return (r); + } + if (r) { + if (a->excluded_cb_func) + a->excluded_cb_func(&(a->archive), + a->excluded_cb_data, entry); + return (ARCHIVE_RETRY); + } + } + + /* Lookup uname/gname */ + name = archive_read_disk_uname(&(a->archive), archive_entry_uid(entry)); + if (name != NULL) + archive_entry_copy_uname(entry, name); + name = archive_read_disk_gname(&(a->archive), archive_entry_gid(entry)); + if (name != NULL) + archive_entry_copy_gname(entry, name); + + /* + * Perform owner matching. + */ + if (a->matching) { + r = archive_match_owner_excluded(a->matching, entry); + if (r < 0) { + archive_set_error(&(a->archive), errno, + "Failed : %s", archive_error_string(a->matching)); + return (r); + } + if (r) { + if (a->excluded_cb_func) + a->excluded_cb_func(&(a->archive), + a->excluded_cb_data, entry); + return (ARCHIVE_RETRY); + } + } + + /* + * Invoke a meta data filter callback. + */ + if (a->metadata_filter_func) { + if (!a->metadata_filter_func(&(a->archive), + a->metadata_filter_data, entry)) + return (ARCHIVE_RETRY); + } + + /* + * Populate the archive_entry with metadata from the disk. + */ + archive_entry_copy_sourcepath(entry, tree_current_access_path(t)); + r = archive_read_disk_entry_from_file(&(a->archive), entry, + t->entry_fd, st); + + if (r == ARCHIVE_OK) { + r = delayed; + if (r != ARCHIVE_OK) { + archive_string_sprintf(&delayed_str, ": %s", + "File removed before we read it"); + archive_set_error(&(a->archive), delayed_errno, + "%s", delayed_str.s); + } + } + archive_string_free(&delayed_str); + + return (r); +} + +static int +_archive_read_next_header(struct archive *_a, struct archive_entry **entryp) +{ + int ret; + struct archive_read_disk *a = (struct archive_read_disk *)_a; + *entryp = NULL; + ret = _archive_read_next_header2(_a, a->entry); + *entryp = a->entry; + return ret; +} + +static int +_archive_read_next_header2(struct archive *_a, struct archive_entry *entry) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + struct tree *t; + int r; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_read_next_header2"); + + t = a->tree; + if (t->entry_fd >= 0) { + close_and_restore_time(t->entry_fd, t, &t->restore_time); + t->entry_fd = -1; + } + + archive_entry_clear(entry); + + for (;;) { + r = next_entry(a, t, entry); + if (t->entry_fd >= 0) { + close(t->entry_fd); + t->entry_fd = -1; + } + + if (r == ARCHIVE_RETRY) { + archive_entry_clear(entry); + continue; + } + break; + } + + /* Return to the initial directory. */ + tree_enter_initial_dir(t); + + /* + * EOF and FATAL are persistent at this layer. By + * modifying the state, we guarantee that future calls to + * read a header or read data will fail. + */ + switch (r) { + case ARCHIVE_EOF: + a->archive.state = ARCHIVE_STATE_EOF; + break; + case ARCHIVE_OK: + case ARCHIVE_WARN: + /* Overwrite the sourcepath based on the initial directory. */ + archive_entry_copy_sourcepath(entry, tree_current_path(t)); + t->entry_total = 0; + if (archive_entry_filetype(entry) == AE_IFREG) { + t->nlink = archive_entry_nlink(entry); + t->entry_remaining_bytes = archive_entry_size(entry); + t->entry_eof = (t->entry_remaining_bytes == 0)? 1: 0; + if (!t->entry_eof && + setup_sparse(a, entry) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } else { + t->entry_remaining_bytes = 0; + t->entry_eof = 1; + } + a->archive.state = ARCHIVE_STATE_DATA; + break; + case ARCHIVE_RETRY: + break; + case ARCHIVE_FATAL: + a->archive.state = ARCHIVE_STATE_FATAL; + break; + } + + __archive_reset_read_data(&a->archive); + return (r); +} + +static int +setup_sparse(struct archive_read_disk *a, struct archive_entry *entry) +{ + struct tree *t = a->tree; + int64_t length, offset; + int i; + + t->sparse_count = archive_entry_sparse_reset(entry); + if (t->sparse_count+1 > t->sparse_list_size) { + free(t->sparse_list); + t->sparse_list_size = t->sparse_count + 1; + t->sparse_list = malloc(sizeof(t->sparse_list[0]) * + t->sparse_list_size); + if (t->sparse_list == NULL) { + t->sparse_list_size = 0; + archive_set_error(&a->archive, ENOMEM, + "Can't allocate data"); + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } + } + for (i = 0; i < t->sparse_count; i++) { + archive_entry_sparse_next(entry, &offset, &length); + t->sparse_list[i].offset = offset; + t->sparse_list[i].length = length; + } + if (i == 0) { + t->sparse_list[i].offset = 0; + t->sparse_list[i].length = archive_entry_size(entry); + } else { + t->sparse_list[i].offset = archive_entry_size(entry); + t->sparse_list[i].length = 0; + } + t->current_sparse = t->sparse_list; + + return (ARCHIVE_OK); +} + +int +archive_read_disk_set_matching(struct archive *_a, struct archive *_ma, + void (*_excluded_func)(struct archive *, void *, struct archive_entry *), + void *_client_data) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_read_disk_set_matching"); + a->matching = _ma; + a->excluded_cb_func = _excluded_func; + a->excluded_cb_data = _client_data; + return (ARCHIVE_OK); +} + +int +archive_read_disk_set_metadata_filter_callback(struct archive *_a, + int (*_metadata_filter_func)(struct archive *, void *, + struct archive_entry *), void *_client_data) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_ANY, + "archive_read_disk_set_metadata_filter_callback"); + + a->metadata_filter_func = _metadata_filter_func; + a->metadata_filter_data = _client_data; + return (ARCHIVE_OK); +} + +int +archive_read_disk_can_descend(struct archive *_a) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + struct tree *t = a->tree; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_read_disk_can_descend"); + + return (t->visit_type == TREE_REGULAR && t->descend); +} + +/* + * Called by the client to mark the directory just returned from + * tree_next() as needing to be visited. + */ +int +archive_read_disk_descend(struct archive *_a) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + struct tree *t = a->tree; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_read_disk_descend"); + + if (t->visit_type != TREE_REGULAR || !t->descend) + return (ARCHIVE_OK); + + /* + * We must not treat the initial specified path as a physical dir, + * because if we do then we will try and ascend out of it by opening + * ".." which is (a) wrong and (b) causes spurious permissions errors + * if ".." is not readable by us. Instead, treat it as if it were a + * symlink. (This uses an extra fd, but it can only happen once at the + * top level of a traverse.) But we can't necessarily assume t->st is + * valid here (though t->lst is), which complicates the logic a + * little. + */ + if (tree_current_is_physical_dir(t)) { + tree_push(t, t->basename, t->current_filesystem_id, + t->lst.st_dev, t->lst.st_ino, &t->restore_time); + if (t->stack->parent->parent != NULL) + t->stack->flags |= isDir; + else + t->stack->flags |= isDirLink; + } else if (tree_current_is_dir(t)) { + tree_push(t, t->basename, t->current_filesystem_id, + t->st.st_dev, t->st.st_ino, &t->restore_time); + t->stack->flags |= isDirLink; + } + t->descend = 0; + return (ARCHIVE_OK); +} + +int +archive_read_disk_open(struct archive *_a, const char *pathname) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_NEW | ARCHIVE_STATE_CLOSED, + "archive_read_disk_open"); + archive_clear_error(&a->archive); + + return (_archive_read_disk_open(_a, pathname)); +} + +int +archive_read_disk_open_w(struct archive *_a, const wchar_t *pathname) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + struct archive_string path; + int ret; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_NEW | ARCHIVE_STATE_CLOSED, + "archive_read_disk_open_w"); + archive_clear_error(&a->archive); + + /* Make a char string from a wchar_t string. */ + archive_string_init(&path); + if (archive_string_append_from_wcs(&path, pathname, + wcslen(pathname)) != 0) { + if (errno == ENOMEM) + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + else + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't convert a path to a char string"); + a->archive.state = ARCHIVE_STATE_FATAL; + ret = ARCHIVE_FATAL; + } else + ret = _archive_read_disk_open(_a, path.s); + + archive_string_free(&path); + return (ret); +} + +static int +_archive_read_disk_open(struct archive *_a, const char *pathname) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + + if (a->tree != NULL) + a->tree = tree_reopen(a->tree, pathname, + a->flags & ARCHIVE_READDISK_RESTORE_ATIME); + else + a->tree = tree_open(pathname, a->symlink_mode, + a->flags & ARCHIVE_READDISK_RESTORE_ATIME); + if (a->tree == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate tar data"); + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } + a->archive.state = ARCHIVE_STATE_HEADER; + + return (ARCHIVE_OK); +} + +/* + * Return a current filesystem ID which is index of the filesystem entry + * you've visited through archive_read_disk. + */ +int +archive_read_disk_current_filesystem(struct archive *_a) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA, + "archive_read_disk_current_filesystem"); + + return (a->tree->current_filesystem_id); +} + +static int +update_current_filesystem(struct archive_read_disk *a, int64_t dev) +{ + struct tree *t = a->tree; + int i, fid; + + if (t->current_filesystem != NULL && + t->current_filesystem->dev == dev) + return (ARCHIVE_OK); + + for (i = 0; i < t->max_filesystem_id; i++) { + if (t->filesystem_table[i].dev == dev) { + /* There is the filesystem ID we've already generated. */ + t->current_filesystem_id = i; + t->current_filesystem = &(t->filesystem_table[i]); + return (ARCHIVE_OK); + } + } + + /* + * This is the new filesystem which we have to generate a new ID for. + */ + fid = t->max_filesystem_id++; + if (t->max_filesystem_id > t->allocated_filesystem) { + size_t s; + void *p; + + s = t->max_filesystem_id * 2; + p = realloc(t->filesystem_table, + s * sizeof(*t->filesystem_table)); + if (p == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate tar data"); + return (ARCHIVE_FATAL); + } + t->filesystem_table = (struct filesystem *)p; + t->allocated_filesystem = s; + } + t->current_filesystem_id = fid; + t->current_filesystem = &(t->filesystem_table[fid]); + t->current_filesystem->dev = dev; + t->current_filesystem->allocation_ptr = NULL; + t->current_filesystem->buff = NULL; + + /* Setup the current filesystem properties which depend on + * platform specific. */ + return (setup_current_filesystem(a)); +} + +/* + * Returns 1 if current filesystem is generated filesystem, 0 if it is not + * or -1 if it is unknown. + */ +int +archive_read_disk_current_filesystem_is_synthetic(struct archive *_a) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA, + "archive_read_disk_current_filesystem"); + + return (a->tree->current_filesystem->synthetic); +} + +/* + * Returns 1 if current filesystem is remote filesystem, 0 if it is not + * or -1 if it is unknown. + */ +int +archive_read_disk_current_filesystem_is_remote(struct archive *_a) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA, + "archive_read_disk_current_filesystem"); + + return (a->tree->current_filesystem->remote); +} + +#if defined(_PC_REC_INCR_XFER_SIZE) && defined(_PC_REC_MAX_XFER_SIZE) &&\ + defined(_PC_REC_MIN_XFER_SIZE) && defined(_PC_REC_XFER_ALIGN) +static int +get_xfer_size(struct tree *t, int fd, const char *path) +{ + t->current_filesystem->xfer_align = -1; + errno = 0; + if (fd >= 0) { + t->current_filesystem->incr_xfer_size = + fpathconf(fd, _PC_REC_INCR_XFER_SIZE); + t->current_filesystem->max_xfer_size = + fpathconf(fd, _PC_REC_MAX_XFER_SIZE); + t->current_filesystem->min_xfer_size = + fpathconf(fd, _PC_REC_MIN_XFER_SIZE); + t->current_filesystem->xfer_align = + fpathconf(fd, _PC_REC_XFER_ALIGN); + } else if (path != NULL) { + t->current_filesystem->incr_xfer_size = + pathconf(path, _PC_REC_INCR_XFER_SIZE); + t->current_filesystem->max_xfer_size = + pathconf(path, _PC_REC_MAX_XFER_SIZE); + t->current_filesystem->min_xfer_size = + pathconf(path, _PC_REC_MIN_XFER_SIZE); + t->current_filesystem->xfer_align = + pathconf(path, _PC_REC_XFER_ALIGN); + } + /* At least we need an alignment size. */ + if (t->current_filesystem->xfer_align == -1) + return ((errno == EINVAL)?1:-1); + else + return (0); +} +#else +static int +get_xfer_size(struct tree *t, int fd, const char *path) +{ + (void)t; /* UNUSED */ + (void)fd; /* UNUSED */ + (void)path; /* UNUSED */ + return (1);/* Not supported */ +} +#endif + +#if defined(HAVE_STATFS) && defined(HAVE_FSTATFS) && defined(MNT_LOCAL) \ + && !defined(ST_LOCAL) + +/* + * Gather current filesystem properties on FreeBSD, OpenBSD and Mac OS X. + */ +static int +setup_current_filesystem(struct archive_read_disk *a) +{ + struct tree *t = a->tree; + struct statfs sfs; +#if defined(HAVE_GETVFSBYNAME) && defined(VFCF_SYNTHETIC) +/* TODO: configure should set GETVFSBYNAME_ARG_TYPE to make + * this accurate; some platforms have both and we need the one that's + * used by getvfsbyname() + * + * Then the following would become: + * #if defined(GETVFSBYNAME_ARG_TYPE) + * GETVFSBYNAME_ARG_TYPE vfc; + * #endif + */ +# if defined(HAVE_STRUCT_XVFSCONF) + struct xvfsconf vfc; +# else + struct vfsconf vfc; +# endif +#endif + int r, xr = 0; +#if !defined(HAVE_STRUCT_STATFS_F_NAMEMAX) + long nm; +#endif + + t->current_filesystem->synthetic = -1; + t->current_filesystem->remote = -1; + if (tree_current_is_symblic_link_target(t)) { +#if defined(HAVE_OPENAT) + /* + * Get file system statistics on any directory + * where current is. + */ + int fd = openat(tree_current_dir_fd(t), + tree_current_access_path(t), O_RDONLY | O_CLOEXEC); + __archive_ensure_cloexec_flag(fd); + if (fd < 0) { + archive_set_error(&a->archive, errno, + "openat failed"); + return (ARCHIVE_FAILED); + } + r = fstatfs(fd, &sfs); + if (r == 0) + xr = get_xfer_size(t, fd, NULL); + close(fd); +#else + if (tree_enter_working_dir(t) != 0) { + archive_set_error(&a->archive, errno, "fchdir failed"); + return (ARCHIVE_FAILED); + } + r = statfs(tree_current_access_path(t), &sfs); + if (r == 0) + xr = get_xfer_size(t, -1, tree_current_access_path(t)); +#endif + } else { + r = fstatfs(tree_current_dir_fd(t), &sfs); + if (r == 0) + xr = get_xfer_size(t, tree_current_dir_fd(t), NULL); + } + if (r == -1 || xr == -1) { + archive_set_error(&a->archive, errno, "statfs failed"); + return (ARCHIVE_FAILED); + } else if (xr == 1) { + /* pathconf(_PC_REX_*) operations are not supported. */ + t->current_filesystem->xfer_align = sfs.f_bsize; + t->current_filesystem->max_xfer_size = -1; + t->current_filesystem->min_xfer_size = sfs.f_iosize; + t->current_filesystem->incr_xfer_size = sfs.f_iosize; + } + if (sfs.f_flags & MNT_LOCAL) + t->current_filesystem->remote = 0; + else + t->current_filesystem->remote = 1; + +#if defined(HAVE_GETVFSBYNAME) && defined(VFCF_SYNTHETIC) + r = getvfsbyname(sfs.f_fstypename, &vfc); + if (r == -1) { + archive_set_error(&a->archive, errno, "getvfsbyname failed"); + return (ARCHIVE_FAILED); + } + if (vfc.vfc_flags & VFCF_SYNTHETIC) + t->current_filesystem->synthetic = 1; + else + t->current_filesystem->synthetic = 0; +#endif + +#if defined(MNT_NOATIME) + if (sfs.f_flags & MNT_NOATIME) + t->current_filesystem->noatime = 1; + else +#endif + t->current_filesystem->noatime = 0; + +#if defined(USE_READDIR_R) + /* Set maximum filename length. */ +#if defined(HAVE_STRUCT_STATFS_F_NAMEMAX) + t->current_filesystem->name_max = sfs.f_namemax; +#else +# if defined(_PC_NAME_MAX) + /* Mac OS X does not have f_namemax in struct statfs. */ + if (tree_current_is_symblic_link_target(t)) { + if (tree_enter_working_dir(t) != 0) { + archive_set_error(&a->archive, errno, "fchdir failed"); + return (ARCHIVE_FAILED); + } + nm = pathconf(tree_current_access_path(t), _PC_NAME_MAX); + } else + nm = fpathconf(tree_current_dir_fd(t), _PC_NAME_MAX); +# else + nm = -1; +# endif + if (nm == -1) + t->current_filesystem->name_max = NAME_MAX; + else + t->current_filesystem->name_max = nm; +#endif +#endif /* USE_READDIR_R */ + return (ARCHIVE_OK); +} + +#elif (defined(HAVE_STATVFS) || defined(HAVE_FSTATVFS)) && defined(ST_LOCAL) + +/* + * Gather current filesystem properties on NetBSD + */ +static int +setup_current_filesystem(struct archive_read_disk *a) +{ + struct tree *t = a->tree; + struct statvfs sfs; + int r, xr = 0; + + t->current_filesystem->synthetic = -1; + if (tree_enter_working_dir(t) != 0) { + archive_set_error(&a->archive, errno, "fchdir failed"); + return (ARCHIVE_FAILED); + } + if (tree_current_is_symblic_link_target(t)) { + r = statvfs(tree_current_access_path(t), &sfs); + if (r == 0) + xr = get_xfer_size(t, -1, tree_current_access_path(t)); + } else { +#ifdef HAVE_FSTATVFS + r = fstatvfs(tree_current_dir_fd(t), &sfs); + if (r == 0) + xr = get_xfer_size(t, tree_current_dir_fd(t), NULL); +#else + r = statvfs(".", &sfs); + if (r == 0) + xr = get_xfer_size(t, -1, "."); +#endif + } + if (r == -1 || xr == -1) { + t->current_filesystem->remote = -1; + archive_set_error(&a->archive, errno, "statvfs failed"); + return (ARCHIVE_FAILED); + } else if (xr == 1) { + /* Usually come here unless NetBSD supports _PC_REC_XFER_ALIGN + * for pathconf() function. */ + t->current_filesystem->xfer_align = sfs.f_frsize; + t->current_filesystem->max_xfer_size = -1; +#if defined(HAVE_STRUCT_STATVFS_F_IOSIZE) + t->current_filesystem->min_xfer_size = sfs.f_iosize; + t->current_filesystem->incr_xfer_size = sfs.f_iosize; +#else + t->current_filesystem->min_xfer_size = sfs.f_bsize; + t->current_filesystem->incr_xfer_size = sfs.f_bsize; +#endif + } + if (sfs.f_flag & ST_LOCAL) + t->current_filesystem->remote = 0; + else + t->current_filesystem->remote = 1; + +#if defined(ST_NOATIME) + if (sfs.f_flag & ST_NOATIME) + t->current_filesystem->noatime = 1; + else +#endif + t->current_filesystem->noatime = 0; + + /* Set maximum filename length. */ + t->current_filesystem->name_max = sfs.f_namemax; + return (ARCHIVE_OK); +} + +#elif defined(HAVE_SYS_STATFS_H) && defined(HAVE_LINUX_MAGIC_H) &&\ + defined(HAVE_STATFS) && defined(HAVE_FSTATFS) +/* + * Note: statfs is deprecated since LSB 3.2 + */ + +#ifndef CIFS_SUPER_MAGIC +#define CIFS_SUPER_MAGIC 0xFF534D42 +#endif +#ifndef DEVFS_SUPER_MAGIC +#define DEVFS_SUPER_MAGIC 0x1373 +#endif + +/* + * Gather current filesystem properties on Linux + */ +static int +setup_current_filesystem(struct archive_read_disk *a) +{ + struct tree *t = a->tree; + struct statfs sfs; +#if defined(HAVE_STATVFS) + struct statvfs svfs; +#endif + int r, vr = 0, xr = 0; + + if (tree_current_is_symblic_link_target(t)) { +#if defined(HAVE_OPENAT) + /* + * Get file system statistics on any directory + * where current is. + */ + int fd = openat(tree_current_dir_fd(t), + tree_current_access_path(t), O_RDONLY | O_CLOEXEC); + __archive_ensure_cloexec_flag(fd); + if (fd < 0) { + archive_set_error(&a->archive, errno, + "openat failed"); + return (ARCHIVE_FAILED); + } +#if defined(HAVE_FSTATVFS) + vr = fstatvfs(fd, &svfs);/* for f_flag, mount flags */ +#endif + r = fstatfs(fd, &sfs); + if (r == 0) + xr = get_xfer_size(t, fd, NULL); + close(fd); +#else + if (tree_enter_working_dir(t) != 0) { + archive_set_error(&a->archive, errno, "fchdir failed"); + return (ARCHIVE_FAILED); + } +#if defined(HAVE_STATVFS) + vr = statvfs(tree_current_access_path(t), &svfs); +#endif + r = statfs(tree_current_access_path(t), &sfs); + if (r == 0) + xr = get_xfer_size(t, -1, tree_current_access_path(t)); +#endif + } else { +#ifdef HAVE_FSTATFS +#if defined(HAVE_FSTATVFS) + vr = fstatvfs(tree_current_dir_fd(t), &svfs); +#endif + r = fstatfs(tree_current_dir_fd(t), &sfs); + if (r == 0) + xr = get_xfer_size(t, tree_current_dir_fd(t), NULL); +#else + if (tree_enter_working_dir(t) != 0) { + archive_set_error(&a->archive, errno, "fchdir failed"); + return (ARCHIVE_FAILED); + } +#if defined(HAVE_STATVFS) + vr = statvfs(".", &svfs); +#endif + r = statfs(".", &sfs); + if (r == 0) + xr = get_xfer_size(t, -1, "."); +#endif + } + if (r == -1 || xr == -1 || vr == -1) { + t->current_filesystem->synthetic = -1; + t->current_filesystem->remote = -1; + archive_set_error(&a->archive, errno, "statfs failed"); + return (ARCHIVE_FAILED); + } else if (xr == 1) { + /* pathconf(_PC_REX_*) operations are not supported. */ +#if defined(HAVE_STATVFS) + t->current_filesystem->xfer_align = svfs.f_frsize; + t->current_filesystem->max_xfer_size = -1; + t->current_filesystem->min_xfer_size = svfs.f_bsize; + t->current_filesystem->incr_xfer_size = svfs.f_bsize; +#else + t->current_filesystem->xfer_align = sfs.f_frsize; + t->current_filesystem->max_xfer_size = -1; + t->current_filesystem->min_xfer_size = sfs.f_bsize; + t->current_filesystem->incr_xfer_size = sfs.f_bsize; +#endif + } + switch (sfs.f_type) { + case AFS_SUPER_MAGIC: + case CIFS_SUPER_MAGIC: + case CODA_SUPER_MAGIC: + case NCP_SUPER_MAGIC:/* NetWare */ + case NFS_SUPER_MAGIC: + case SMB_SUPER_MAGIC: + t->current_filesystem->remote = 1; + t->current_filesystem->synthetic = 0; + break; + case DEVFS_SUPER_MAGIC: + case PROC_SUPER_MAGIC: + case USBDEVICE_SUPER_MAGIC: + t->current_filesystem->remote = 0; + t->current_filesystem->synthetic = 1; + break; + default: + t->current_filesystem->remote = 0; + t->current_filesystem->synthetic = 0; + break; + } + +#if defined(ST_NOATIME) +#if defined(HAVE_STATVFS) + if (svfs.f_flag & ST_NOATIME) +#else + if (sfs.f_flag & ST_NOATIME) +#endif + t->current_filesystem->noatime = 1; + else +#endif + t->current_filesystem->noatime = 0; + +#if defined(USE_READDIR_R) + /* Set maximum filename length. */ + t->current_filesystem->name_max = sfs.f_namelen; +#endif + return (ARCHIVE_OK); +} + +#elif defined(HAVE_SYS_STATVFS_H) &&\ + (defined(HAVE_STATVFS) || defined(HAVE_FSTATVFS)) + +/* + * Gather current filesystem properties on other posix platform. + */ +static int +setup_current_filesystem(struct archive_read_disk *a) +{ + struct tree *t = a->tree; + struct statvfs sfs; + int r, xr = 0; + + t->current_filesystem->synthetic = -1;/* Not supported */ + t->current_filesystem->remote = -1;/* Not supported */ + if (tree_current_is_symblic_link_target(t)) { +#if defined(HAVE_OPENAT) + /* + * Get file system statistics on any directory + * where current is. + */ + int fd = openat(tree_current_dir_fd(t), + tree_current_access_path(t), O_RDONLY | O_CLOEXEC); + __archive_ensure_cloexec_flag(fd); + if (fd < 0) { + archive_set_error(&a->archive, errno, + "openat failed"); + return (ARCHIVE_FAILED); + } + r = fstatvfs(fd, &sfs); + if (r == 0) + xr = get_xfer_size(t, fd, NULL); + close(fd); +#else + if (tree_enter_working_dir(t) != 0) { + archive_set_error(&a->archive, errno, "fchdir failed"); + return (ARCHIVE_FAILED); + } + r = statvfs(tree_current_access_path(t), &sfs); + if (r == 0) + xr = get_xfer_size(t, -1, tree_current_access_path(t)); +#endif + } else { +#ifdef HAVE_FSTATVFS + r = fstatvfs(tree_current_dir_fd(t), &sfs); + if (r == 0) + xr = get_xfer_size(t, tree_current_dir_fd(t), NULL); +#else + if (tree_enter_working_dir(t) != 0) { + archive_set_error(&a->archive, errno, "fchdir failed"); + return (ARCHIVE_FAILED); + } + r = statvfs(".", &sfs); + if (r == 0) + xr = get_xfer_size(t, -1, "."); +#endif + } + if (r == -1 || xr == -1) { + t->current_filesystem->synthetic = -1; + t->current_filesystem->remote = -1; + archive_set_error(&a->archive, errno, "statvfs failed"); + return (ARCHIVE_FAILED); + } else if (xr == 1) { + /* pathconf(_PC_REX_*) operations are not supported. */ + t->current_filesystem->xfer_align = sfs.f_frsize; + t->current_filesystem->max_xfer_size = -1; + t->current_filesystem->min_xfer_size = sfs.f_bsize; + t->current_filesystem->incr_xfer_size = sfs.f_bsize; + } + +#if defined(ST_NOATIME) + if (sfs.f_flag & ST_NOATIME) + t->current_filesystem->noatime = 1; + else +#endif + t->current_filesystem->noatime = 0; + +#if defined(USE_READDIR_R) + /* Set maximum filename length. */ + t->current_filesystem->name_max = sfs.f_namemax; +#endif + return (ARCHIVE_OK); +} + +#else + +/* + * Generic: Gather current filesystem properties. + * TODO: Is this generic function really needed? + */ +static int +setup_current_filesystem(struct archive_read_disk *a) +{ + struct tree *t = a->tree; +#if defined(_PC_NAME_MAX) && defined(USE_READDIR_R) + long nm; +#endif + t->current_filesystem->synthetic = -1;/* Not supported */ + t->current_filesystem->remote = -1;/* Not supported */ + t->current_filesystem->noatime = 0; + (void)get_xfer_size(t, -1, ".");/* Dummy call to avoid build error. */ + t->current_filesystem->xfer_align = -1;/* Unknown */ + t->current_filesystem->max_xfer_size = -1; + t->current_filesystem->min_xfer_size = -1; + t->current_filesystem->incr_xfer_size = -1; + +#if defined(USE_READDIR_R) + /* Set maximum filename length. */ +# if defined(_PC_NAME_MAX) + if (tree_current_is_symblic_link_target(t)) { + if (tree_enter_working_dir(t) != 0) { + archive_set_error(&a->archive, errno, "fchdir failed"); + return (ARCHIVE_FAILED); + } + nm = pathconf(tree_current_access_path(t), _PC_NAME_MAX); + } else + nm = fpathconf(tree_current_dir_fd(t), _PC_NAME_MAX); + if (nm == -1) +# endif /* _PC_NAME_MAX */ + /* + * Some systems (HP-UX or others?) incorrectly defined + * NAME_MAX macro to be a smaller value. + */ +# if defined(NAME_MAX) && NAME_MAX >= 255 + t->current_filesystem->name_max = NAME_MAX; +# else + /* No way to get a trusted value of maximum filename + * length. */ + t->current_filesystem->name_max = PATH_MAX; +# endif /* NAME_MAX */ +# if defined(_PC_NAME_MAX) + else + t->current_filesystem->name_max = nm; +# endif /* _PC_NAME_MAX */ +#endif /* USE_READDIR_R */ + return (ARCHIVE_OK); +} + +#endif + +static int +close_and_restore_time(int fd, struct tree *t, struct restore_time *rt) +{ +#ifndef HAVE_UTIMES + (void)t; /* UNUSED */ + (void)rt; /* UNUSED */ + return (close(fd)); +#else +#if defined(HAVE_FUTIMENS) && !defined(__CYGWIN__) + struct timespec timespecs[2]; +#endif + struct timeval times[2]; + + if ((t->flags & needsRestoreTimes) == 0 || rt->noatime) { + if (fd >= 0) + return (close(fd)); + else + return (0); + } + +#if defined(HAVE_FUTIMENS) && !defined(__CYGWIN__) + timespecs[1].tv_sec = rt->mtime; + timespecs[1].tv_nsec = rt->mtime_nsec; + + timespecs[0].tv_sec = rt->atime; + timespecs[0].tv_nsec = rt->atime_nsec; + /* futimens() is defined in POSIX.1-2008. */ + if (futimens(fd, timespecs) == 0) + return (close(fd)); +#endif + + times[1].tv_sec = rt->mtime; + times[1].tv_usec = rt->mtime_nsec / 1000; + + times[0].tv_sec = rt->atime; + times[0].tv_usec = rt->atime_nsec / 1000; + +#if !defined(HAVE_FUTIMENS) && defined(HAVE_FUTIMES) && !defined(__CYGWIN__) + if (futimes(fd, times) == 0) + return (close(fd)); +#endif + close(fd); +#if defined(HAVE_FUTIMESAT) + if (futimesat(tree_current_dir_fd(t), rt->name, times) == 0) + return (0); +#endif +#ifdef HAVE_LUTIMES + if (lutimes(rt->name, times) != 0) +#else + if (AE_IFLNK != rt->filetype && utimes(rt->name, times) != 0) +#endif + return (-1); +#endif + return (0); +} + +static int +open_on_current_dir(struct tree *t, const char *path, int flags) +{ +#ifdef HAVE_OPENAT + return (openat(tree_current_dir_fd(t), path, flags)); +#else + if (tree_enter_working_dir(t) != 0) + return (-1); + return (open(path, flags)); +#endif +} + +static int +tree_dup(int fd) +{ + int new_fd; +#ifdef F_DUPFD_CLOEXEC + static volatile int can_dupfd_cloexec = 1; + + if (can_dupfd_cloexec) { + new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 0); + if (new_fd != -1) + return (new_fd); + /* Linux 2.6.18 - 2.6.23 declare F_DUPFD_CLOEXEC, + * but it cannot be used. So we have to try dup(). */ + /* We won't try F_DUPFD_CLOEXEC. */ + can_dupfd_cloexec = 0; + } +#endif /* F_DUPFD_CLOEXEC */ + new_fd = dup(fd); + __archive_ensure_cloexec_flag(new_fd); + return (new_fd); +} + +/* + * Add a directory path to the current stack. + */ +static void +tree_push(struct tree *t, const char *path, int filesystem_id, + int64_t dev, int64_t ino, struct restore_time *rt) +{ + struct tree_entry *te; + + te = calloc(1, sizeof(*te)); + te->next = t->stack; + te->parent = t->current; + if (te->parent) + te->depth = te->parent->depth + 1; + t->stack = te; + archive_string_init(&te->name); + te->symlink_parent_fd = -1; + archive_strcpy(&te->name, path); + te->flags = needsDescent | needsOpen | needsAscent; + te->filesystem_id = filesystem_id; + te->dev = dev; + te->ino = ino; + te->dirname_length = t->dirname_length; + te->restore_time.name = te->name.s; + if (rt != NULL) { + te->restore_time.mtime = rt->mtime; + te->restore_time.mtime_nsec = rt->mtime_nsec; + te->restore_time.atime = rt->atime; + te->restore_time.atime_nsec = rt->atime_nsec; + te->restore_time.filetype = rt->filetype; + te->restore_time.noatime = rt->noatime; + } +} + +/* + * Append a name to the current dir path. + */ +static void +tree_append(struct tree *t, const char *name, size_t name_length) +{ + size_t size_needed; + + t->path.s[t->dirname_length] = '\0'; + t->path.length = t->dirname_length; + /* Strip trailing '/' from name, unless entire name is "/". */ + while (name_length > 1 && name[name_length - 1] == '/') + name_length--; + + /* Resize pathname buffer as needed. */ + size_needed = name_length + t->dirname_length + 2; + archive_string_ensure(&t->path, size_needed); + /* Add a separating '/' if it's needed. */ + if (t->dirname_length > 0 && t->path.s[archive_strlen(&t->path)-1] != '/') + archive_strappend_char(&t->path, '/'); + t->basename = t->path.s + archive_strlen(&t->path); + archive_strncat(&t->path, name, name_length); + t->restore_time.name = t->basename; +} + +/* + * Open a directory tree for traversal. + */ +static struct tree * +tree_open(const char *path, int symlink_mode, int restore_time) +{ + struct tree *t; + + if ((t = calloc(1, sizeof(*t))) == NULL) + return (NULL); + archive_string_init(&t->path); + archive_string_ensure(&t->path, 31); + t->initial_symlink_mode = symlink_mode; + return (tree_reopen(t, path, restore_time)); +} + +static struct tree * +tree_reopen(struct tree *t, const char *path, int restore_time) +{ +#if defined(O_PATH) + /* Linux */ + const int o_flag = O_PATH; +#elif defined(O_SEARCH) + /* SunOS */ + const int o_flag = O_SEARCH; +#elif defined(__FreeBSD__) && defined(O_EXEC) + /* FreeBSD */ + const int o_flag = O_EXEC; +#endif + + t->flags = (restore_time != 0)?needsRestoreTimes:0; + t->flags |= onInitialDir; + t->visit_type = 0; + t->tree_errno = 0; + t->dirname_length = 0; + t->depth = 0; + t->descend = 0; + t->current = NULL; + t->d = INVALID_DIR_HANDLE; + t->symlink_mode = t->initial_symlink_mode; + archive_string_empty(&t->path); + t->entry_fd = -1; + t->entry_eof = 0; + t->entry_remaining_bytes = 0; + t->initial_filesystem_id = -1; + + /* First item is set up a lot like a symlink traversal. */ + tree_push(t, path, 0, 0, 0, NULL); + t->stack->flags = needsFirstVisit; + t->maxOpenCount = t->openCount = 1; + t->initial_dir_fd = open(".", O_RDONLY | O_CLOEXEC); +#if defined(O_PATH) || defined(O_SEARCH) || \ + (defined(__FreeBSD__) && defined(O_EXEC)) + /* + * Most likely reason to fail opening "." is that it's not readable, + * so try again for execute. The consequences of not opening this are + * unhelpful and unnecessary errors later. + */ + if (t->initial_dir_fd < 0) + t->initial_dir_fd = open(".", o_flag | O_CLOEXEC); +#endif + __archive_ensure_cloexec_flag(t->initial_dir_fd); + t->working_dir_fd = tree_dup(t->initial_dir_fd); + return (t); +} + +static int +tree_descent(struct tree *t) +{ + int flag, new_fd, r = 0; + + t->dirname_length = archive_strlen(&t->path); + flag = O_RDONLY | O_CLOEXEC; +#if defined(O_DIRECTORY) + flag |= O_DIRECTORY; +#endif + new_fd = open_on_current_dir(t, t->stack->name.s, flag); + __archive_ensure_cloexec_flag(new_fd); + if (new_fd < 0) { + t->tree_errno = errno; + r = TREE_ERROR_DIR; + } else { + t->depth++; + /* If it is a link, set up fd for the ascent. */ + if (t->stack->flags & isDirLink) { + t->stack->symlink_parent_fd = t->working_dir_fd; + t->openCount++; + if (t->openCount > t->maxOpenCount) + t->maxOpenCount = t->openCount; + } else + close(t->working_dir_fd); + /* Renew the current working directory. */ + t->working_dir_fd = new_fd; + t->flags &= ~onWorkingDir; + } + return (r); +} + +/* + * We've finished a directory; ascend back to the parent. + */ +static int +tree_ascend(struct tree *t) +{ + struct tree_entry *te; + int new_fd, r = 0, prev_dir_fd; + + te = t->stack; + prev_dir_fd = t->working_dir_fd; + if (te->flags & isDirLink) + new_fd = te->symlink_parent_fd; + else { + new_fd = open_on_current_dir(t, "..", O_RDONLY | O_CLOEXEC); + __archive_ensure_cloexec_flag(new_fd); + } + if (new_fd < 0) { + t->tree_errno = errno; + r = TREE_ERROR_FATAL; + } else { + /* Renew the current working directory. */ + t->working_dir_fd = new_fd; + t->flags &= ~onWorkingDir; + /* Current directory has been changed, we should + * close an fd of previous working directory. */ + close_and_restore_time(prev_dir_fd, t, &te->restore_time); + if (te->flags & isDirLink) { + t->openCount--; + te->symlink_parent_fd = -1; + } + t->depth--; + } + return (r); +} + +/* + * Return to the initial directory where tree_open() was performed. + */ +static int +tree_enter_initial_dir(struct tree *t) +{ + int r = 0; + + if ((t->flags & onInitialDir) == 0) { + r = fchdir(t->initial_dir_fd); + if (r == 0) { + t->flags &= ~onWorkingDir; + t->flags |= onInitialDir; + } + } + return (r); +} + +/* + * Restore working directory of directory traversals. + */ +static int +tree_enter_working_dir(struct tree *t) +{ + int r = 0; + + /* + * Change the current directory if really needed. + * Sometimes this is unneeded when we did not do + * descent. + */ + if (t->depth > 0 && (t->flags & onWorkingDir) == 0) { + r = fchdir(t->working_dir_fd); + if (r == 0) { + t->flags &= ~onInitialDir; + t->flags |= onWorkingDir; + } + } + return (r); +} + +static int +tree_current_dir_fd(struct tree *t) +{ + return (t->working_dir_fd); +} + +/* + * Pop the working stack. + */ +static void +tree_pop(struct tree *t) +{ + struct tree_entry *te; + + t->path.s[t->dirname_length] = '\0'; + t->path.length = t->dirname_length; + if (t->stack == t->current && t->current != NULL) + t->current = t->current->parent; + te = t->stack; + t->stack = te->next; + t->dirname_length = te->dirname_length; + t->basename = t->path.s + t->dirname_length; + while (t->basename[0] == '/') + t->basename++; + archive_string_free(&te->name); + free(te); +} + +/* + * Get the next item in the tree traversal. + */ +static int +tree_next(struct tree *t) +{ + int r; + + while (t->stack != NULL) { + /* If there's an open dir, get the next entry from there. */ + if (t->d != INVALID_DIR_HANDLE) { + r = tree_dir_next_posix(t); + if (r == 0) + continue; + return (r); + } + + if (t->stack->flags & needsFirstVisit) { + /* Top stack item needs a regular visit. */ + t->current = t->stack; + tree_append(t, t->stack->name.s, + archive_strlen(&(t->stack->name))); + /* t->dirname_length = t->path_length; */ + /* tree_pop(t); */ + t->stack->flags &= ~needsFirstVisit; + return (t->visit_type = TREE_REGULAR); + } else if (t->stack->flags & needsDescent) { + /* Top stack item is dir to descend into. */ + t->current = t->stack; + tree_append(t, t->stack->name.s, + archive_strlen(&(t->stack->name))); + t->stack->flags &= ~needsDescent; + r = tree_descent(t); + if (r != 0) { + tree_pop(t); + t->visit_type = r; + } else + t->visit_type = TREE_POSTDESCENT; + return (t->visit_type); + } else if (t->stack->flags & needsOpen) { + t->stack->flags &= ~needsOpen; + r = tree_dir_next_posix(t); + if (r == 0) + continue; + return (r); + } else if (t->stack->flags & needsAscent) { + /* Top stack item is dir and we're done with it. */ + r = tree_ascend(t); + tree_pop(t); + t->visit_type = r != 0 ? r : TREE_POSTASCENT; + return (t->visit_type); + } else { + /* Top item on stack is dead. */ + tree_pop(t); + t->flags &= ~hasLstat; + t->flags &= ~hasStat; + } + } + return (t->visit_type = 0); +} + +static int +tree_dir_next_posix(struct tree *t) +{ + int r; + const char *name; + size_t namelen; + + if (t->d == NULL) { +#if defined(USE_READDIR_R) + size_t dirent_size; +#endif + +#if defined(HAVE_FDOPENDIR) + t->d = fdopendir(tree_dup(t->working_dir_fd)); +#else /* HAVE_FDOPENDIR */ + if (tree_enter_working_dir(t) == 0) { + t->d = opendir("."); +#if HAVE_DIRFD || defined(dirfd) + __archive_ensure_cloexec_flag(dirfd(t->d)); +#endif + } +#endif /* HAVE_FDOPENDIR */ + if (t->d == NULL) { + r = tree_ascend(t); /* Undo "chdir" */ + tree_pop(t); + t->tree_errno = errno; + t->visit_type = r != 0 ? r : TREE_ERROR_DIR; + return (t->visit_type); + } +#if defined(USE_READDIR_R) + dirent_size = offsetof(struct dirent, d_name) + + t->filesystem_table[t->current->filesystem_id].name_max + 1; + if (t->dirent == NULL || t->dirent_allocated < dirent_size) { + free(t->dirent); + t->dirent = malloc(dirent_size); + if (t->dirent == NULL) { + closedir(t->d); + t->d = INVALID_DIR_HANDLE; + (void)tree_ascend(t); + tree_pop(t); + t->tree_errno = ENOMEM; + t->visit_type = TREE_ERROR_DIR; + return (t->visit_type); + } + t->dirent_allocated = dirent_size; + } +#endif /* USE_READDIR_R */ + } + for (;;) { + errno = 0; +#if defined(USE_READDIR_R) + r = readdir_r(t->d, t->dirent, &t->de); +#ifdef _AIX + /* Note: According to the man page, return value 9 indicates + * that the readdir_r was not successful and the error code + * is set to the global errno variable. And then if the end + * of directory entries was reached, the return value is 9 + * and the third parameter is set to NULL and errno is + * unchanged. */ + if (r == 9) + r = errno; +#endif /* _AIX */ + if (r != 0 || t->de == NULL) { +#else + t->de = readdir(t->d); + if (t->de == NULL) { + r = errno; +#endif + closedir(t->d); + t->d = INVALID_DIR_HANDLE; + if (r != 0) { + t->tree_errno = r; + t->visit_type = TREE_ERROR_DIR; + return (t->visit_type); + } else + return (0); + } + name = t->de->d_name; + namelen = D_NAMELEN(t->de); + t->flags &= ~hasLstat; + t->flags &= ~hasStat; + if (name[0] == '.' && name[1] == '\0') + continue; + if (name[0] == '.' && name[1] == '.' && name[2] == '\0') + continue; + tree_append(t, name, namelen); + return (t->visit_type = TREE_REGULAR); + } +} + + +/* + * Get the stat() data for the entry just returned from tree_next(). + */ +static const struct stat * +tree_current_stat(struct tree *t) +{ + if (!(t->flags & hasStat)) { +#ifdef HAVE_FSTATAT + if (fstatat(tree_current_dir_fd(t), + tree_current_access_path(t), &t->st, 0) != 0) +#else + if (tree_enter_working_dir(t) != 0) + return NULL; + if (la_stat(tree_current_access_path(t), &t->st) != 0) +#endif + return NULL; + t->flags |= hasStat; + } + return (&t->st); +} + +/* + * Get the lstat() data for the entry just returned from tree_next(). + */ +static const struct stat * +tree_current_lstat(struct tree *t) +{ + if (!(t->flags & hasLstat)) { +#ifdef HAVE_FSTATAT + if (fstatat(tree_current_dir_fd(t), + tree_current_access_path(t), &t->lst, + AT_SYMLINK_NOFOLLOW) != 0) +#else + if (tree_enter_working_dir(t) != 0) + return NULL; + if (lstat(tree_current_access_path(t), &t->lst) != 0) +#endif + return NULL; + t->flags |= hasLstat; + } + return (&t->lst); +} + +/* + * Test whether current entry is a dir or link to a dir. + */ +static int +tree_current_is_dir(struct tree *t) +{ + const struct stat *st; + /* + * If we already have lstat() info, then try some + * cheap tests to determine if this is a dir. + */ + if (t->flags & hasLstat) { + /* If lstat() says it's a dir, it must be a dir. */ + st = tree_current_lstat(t); + if (st == NULL) + return 0; + if (S_ISDIR(st->st_mode)) + return 1; + /* Not a dir; might be a link to a dir. */ + /* If it's not a link, then it's not a link to a dir. */ + if (!S_ISLNK(st->st_mode)) + return 0; + /* + * It's a link, but we don't know what it's a link to, + * so we'll have to use stat(). + */ + } + + st = tree_current_stat(t); + /* If we can't stat it, it's not a dir. */ + if (st == NULL) + return 0; + /* Use the definitive test. Hopefully this is cached. */ + return (S_ISDIR(st->st_mode)); +} + +/* + * Test whether current entry is a physical directory. Usually, we + * already have at least one of stat() or lstat() in memory, so we + * use tricks to try to avoid an extra trip to the disk. + */ +static int +tree_current_is_physical_dir(struct tree *t) +{ + const struct stat *st; + + /* + * If stat() says it isn't a dir, then it's not a dir. + * If stat() data is cached, this check is free, so do it first. + */ + if (t->flags & hasStat) { + st = tree_current_stat(t); + if (st == NULL) + return (0); + if (!S_ISDIR(st->st_mode)) + return (0); + } + + /* + * Either stat() said it was a dir (in which case, we have + * to determine whether it's really a link to a dir) or + * stat() info wasn't available. So we use lstat(), which + * hopefully is already cached. + */ + + st = tree_current_lstat(t); + /* If we can't stat it, it's not a dir. */ + if (st == NULL) + return 0; + /* Use the definitive test. Hopefully this is cached. */ + return (S_ISDIR(st->st_mode)); +} + +/* + * Test whether the same file has been in the tree as its parent. + */ +static int +tree_target_is_same_as_parent(struct tree *t, const struct stat *st) +{ + struct tree_entry *te; + + for (te = t->current->parent; te != NULL; te = te->parent) { + if (te->dev == (int64_t)st->st_dev && + te->ino == (int64_t)st->st_ino) + return (1); + } + return (0); +} + +/* + * Test whether the current file is symbolic link target and + * on the other filesystem. + */ +static int +tree_current_is_symblic_link_target(struct tree *t) +{ + static const struct stat *lst, *st; + + lst = tree_current_lstat(t); + st = tree_current_stat(t); + return (st != NULL && lst != NULL && + (int64_t)st->st_dev == t->current_filesystem->dev && + st->st_dev != lst->st_dev); +} + +/* + * Return the access path for the entry just returned from tree_next(). + */ +static const char * +tree_current_access_path(struct tree *t) +{ + return (t->basename); +} + +/* + * Return the full path for the entry just returned from tree_next(). + */ +static const char * +tree_current_path(struct tree *t) +{ + return (t->path.s); +} + +/* + * Terminate the traversal. + */ +static void +tree_close(struct tree *t) +{ + + if (t == NULL) + return; + if (t->entry_fd >= 0) { + close_and_restore_time(t->entry_fd, t, &t->restore_time); + t->entry_fd = -1; + } + /* Close the handle of readdir(). */ + if (t->d != INVALID_DIR_HANDLE) { + closedir(t->d); + t->d = INVALID_DIR_HANDLE; + } + /* Release anything remaining in the stack. */ + while (t->stack != NULL) { + if (t->stack->flags & isDirLink) + close(t->stack->symlink_parent_fd); + tree_pop(t); + } + if (t->working_dir_fd >= 0) { + close(t->working_dir_fd); + t->working_dir_fd = -1; + } + if (t->initial_dir_fd >= 0) { + close(t->initial_dir_fd); + t->initial_dir_fd = -1; + } +} + +/* + * Release any resources. + */ +static void +tree_free(struct tree *t) +{ + int i; + + if (t == NULL) + return; + archive_string_free(&t->path); +#if defined(USE_READDIR_R) + free(t->dirent); +#endif + free(t->sparse_list); + for (i = 0; i < t->max_filesystem_id; i++) + free(t->filesystem_table[i].allocation_ptr); + free(t->filesystem_table); + free(t); +} + +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_disk_private.h b/dependencies/libarchive-3.4.2/libarchive/archive_read_disk_private.h new file mode 100644 index 0000000..bc8abc1 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_disk_private.h @@ -0,0 +1,98 @@ +/*- + * Copyright (c) 2003-2009 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: head/lib/libarchive/archive_read_disk_private.h 201105 2009-12-28 03:20:54Z kientzle $ + */ + +#ifndef ARCHIVE_READ_DISK_PRIVATE_H_INCLUDED +#define ARCHIVE_READ_DISK_PRIVATE_H_INCLUDED + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif + +#include "archive_platform_acl.h" + +struct tree; +struct archive_entry; + +struct archive_read_disk { + struct archive archive; + + /* Reused by archive_read_next_header() */ + struct archive_entry *entry; + + /* + * Symlink mode is one of 'L'ogical, 'P'hysical, or 'H'ybrid, + * following an old BSD convention. 'L' follows all symlinks, + * 'P' follows none, 'H' follows symlinks only for the first + * item. + */ + char symlink_mode; + + /* + * Since symlink interaction changes, we need to track whether + * we're following symlinks for the current item. 'L' mode above + * sets this true, 'P' sets it false, 'H' changes it as we traverse. + */ + char follow_symlinks; /* Either 'L' or 'P'. */ + + /* Directory traversals. */ + struct tree *tree; + int (*open_on_current_dir)(struct tree*, const char *, int); + int (*tree_current_dir_fd)(struct tree*); + int (*tree_enter_working_dir)(struct tree*); + + /* Bitfield with ARCHIVE_READDISK_* tunables */ + int flags; + + const char * (*lookup_gname)(void *private, int64_t gid); + void (*cleanup_gname)(void *private); + void *lookup_gname_data; + const char * (*lookup_uname)(void *private, int64_t uid); + void (*cleanup_uname)(void *private); + void *lookup_uname_data; + + int (*metadata_filter_func)(struct archive *, void *, + struct archive_entry *); + void *metadata_filter_data; + + /* ARCHIVE_MATCH object. */ + struct archive *matching; + /* Callback function, this will be invoked when ARCHIVE_MATCH + * archive_match_*_excluded_ae return true. */ + void (*excluded_cb_func)(struct archive *, void *, + struct archive_entry *); + void *excluded_cb_data; +}; + +const char * +archive_read_disk_entry_setup_path(struct archive_read_disk *, + struct archive_entry *, int *); + +int +archive_read_disk_entry_setup_acls(struct archive_read_disk *, + struct archive_entry *, int *); +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_disk_set_standard_lookup.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_disk_set_standard_lookup.c new file mode 100644 index 0000000..c7fd247 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_disk_set_standard_lookup.c @@ -0,0 +1,313 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_set_standard_lookup.c 201109 2009-12-28 03:30:31Z kientzle $"); + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_GRP_H +#include +#endif +#ifdef HAVE_PWD_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive.h" + +#if defined(_WIN32) && !defined(__CYGWIN__) +int +archive_read_disk_set_standard_lookup(struct archive *a) +{ + archive_set_error(a, -1, "Standard lookups not available on Windows"); + return (ARCHIVE_FATAL); +} +#else /* ! (_WIN32 && !__CYGWIN__) */ +#define name_cache_size 127 + +static const char * const NO_NAME = "(noname)"; + +struct name_cache { + struct archive *archive; + char *buff; + size_t buff_size; + int probes; + int hits; + size_t size; + struct { + id_t id; + const char *name; + } cache[name_cache_size]; +}; + +static const char * lookup_gname(void *, int64_t); +static const char * lookup_uname(void *, int64_t); +static void cleanup(void *); +static const char * lookup_gname_helper(struct name_cache *, id_t gid); +static const char * lookup_uname_helper(struct name_cache *, id_t uid); + +/* + * Installs functions that use getpwuid()/getgrgid()---along with + * a simple cache to accelerate such lookups---into the archive_read_disk + * object. This is in a separate file because getpwuid()/getgrgid() + * can pull in a LOT of library code (including NIS/LDAP functions, which + * pull in DNS resolvers, etc). This can easily top 500kB, which makes + * it inappropriate for some space-constrained applications. + * + * Applications that are size-sensitive may want to just use the + * real default functions (defined in archive_read_disk.c) that just + * use the uid/gid without the lookup. Or define your own custom functions + * if you prefer. + */ +int +archive_read_disk_set_standard_lookup(struct archive *a) +{ + struct name_cache *ucache = malloc(sizeof(struct name_cache)); + struct name_cache *gcache = malloc(sizeof(struct name_cache)); + + if (ucache == NULL || gcache == NULL) { + archive_set_error(a, ENOMEM, + "Can't allocate uname/gname lookup cache"); + free(ucache); + free(gcache); + return (ARCHIVE_FATAL); + } + + memset(ucache, 0, sizeof(*ucache)); + ucache->archive = a; + ucache->size = name_cache_size; + memset(gcache, 0, sizeof(*gcache)); + gcache->archive = a; + gcache->size = name_cache_size; + + archive_read_disk_set_gname_lookup(a, gcache, lookup_gname, cleanup); + archive_read_disk_set_uname_lookup(a, ucache, lookup_uname, cleanup); + + return (ARCHIVE_OK); +} + +static void +cleanup(void *data) +{ + struct name_cache *cache = (struct name_cache *)data; + size_t i; + + if (cache != NULL) { + for (i = 0; i < cache->size; i++) { + if (cache->cache[i].name != NULL && + cache->cache[i].name != NO_NAME) + free((void *)(uintptr_t)cache->cache[i].name); + } + free(cache->buff); + free(cache); + } +} + +/* + * Lookup uid/gid from uname/gname, return NULL if no match. + */ +static const char * +lookup_name(struct name_cache *cache, + const char * (*lookup_fn)(struct name_cache *, id_t), id_t id) +{ + const char *name; + int slot; + + + cache->probes++; + + slot = id % cache->size; + if (cache->cache[slot].name != NULL) { + if (cache->cache[slot].id == id) { + cache->hits++; + if (cache->cache[slot].name == NO_NAME) + return (NULL); + return (cache->cache[slot].name); + } + if (cache->cache[slot].name != NO_NAME) + free((void *)(uintptr_t)cache->cache[slot].name); + cache->cache[slot].name = NULL; + } + + name = (lookup_fn)(cache, id); + if (name == NULL) { + /* Cache and return the negative response. */ + cache->cache[slot].name = NO_NAME; + cache->cache[slot].id = id; + return (NULL); + } + + cache->cache[slot].name = name; + cache->cache[slot].id = id; + return (cache->cache[slot].name); +} + +static const char * +lookup_uname(void *data, int64_t uid) +{ + struct name_cache *uname_cache = (struct name_cache *)data; + return (lookup_name(uname_cache, + &lookup_uname_helper, (id_t)uid)); +} + +#if HAVE_GETPWUID_R +static const char * +lookup_uname_helper(struct name_cache *cache, id_t id) +{ + struct passwd pwent, *result; + char * nbuff; + size_t nbuff_size; + int r; + + if (cache->buff_size == 0) { + cache->buff_size = 256; + cache->buff = malloc(cache->buff_size); + } + if (cache->buff == NULL) + return (NULL); + for (;;) { + result = &pwent; /* Old getpwuid_r ignores last arg. */ + r = getpwuid_r((uid_t)id, &pwent, + cache->buff, cache->buff_size, &result); + if (r == 0) + break; + if (r != ERANGE) + break; + /* ERANGE means our buffer was too small, but POSIX + * doesn't tell us how big the buffer should be, so + * we just double it and try again. Because the buffer + * is kept around in the cache object, we shouldn't + * have to do this very often. */ + nbuff_size = cache->buff_size * 2; + nbuff = realloc(cache->buff, nbuff_size); + if (nbuff == NULL) + break; + cache->buff = nbuff; + cache->buff_size = nbuff_size; + } + if (r != 0) { + archive_set_error(cache->archive, errno, + "Can't lookup user for id %d", (int)id); + return (NULL); + } + if (result == NULL) + return (NULL); + + return strdup(result->pw_name); +} +#else +static const char * +lookup_uname_helper(struct name_cache *cache, id_t id) +{ + struct passwd *result; + (void)cache; /* UNUSED */ + + result = getpwuid((uid_t)id); + + if (result == NULL) + return (NULL); + + return strdup(result->pw_name); +} +#endif + +static const char * +lookup_gname(void *data, int64_t gid) +{ + struct name_cache *gname_cache = (struct name_cache *)data; + return (lookup_name(gname_cache, + &lookup_gname_helper, (id_t)gid)); +} + +#if HAVE_GETGRGID_R +static const char * +lookup_gname_helper(struct name_cache *cache, id_t id) +{ + struct group grent, *result; + char * nbuff; + size_t nbuff_size; + int r; + + if (cache->buff_size == 0) { + cache->buff_size = 256; + cache->buff = malloc(cache->buff_size); + } + if (cache->buff == NULL) + return (NULL); + for (;;) { + result = &grent; /* Old getgrgid_r ignores last arg. */ + r = getgrgid_r((gid_t)id, &grent, + cache->buff, cache->buff_size, &result); + if (r == 0) + break; + if (r != ERANGE) + break; + /* ERANGE means our buffer was too small, but POSIX + * doesn't tell us how big the buffer should be, so + * we just double it and try again. */ + nbuff_size = cache->buff_size * 2; + nbuff = realloc(cache->buff, nbuff_size); + if (nbuff == NULL) + break; + cache->buff = nbuff; + cache->buff_size = nbuff_size; + } + if (r != 0) { + archive_set_error(cache->archive, errno, + "Can't lookup group for id %d", (int)id); + return (NULL); + } + if (result == NULL) + return (NULL); + + return strdup(result->gr_name); +} +#else +static const char * +lookup_gname_helper(struct name_cache *cache, id_t id) +{ + struct group *result; + (void)cache; /* UNUSED */ + + result = getgrgid((gid_t)id); + + if (result == NULL) + return (NULL); + + return strdup(result->gr_name); +} +#endif + +#endif /* ! (_WIN32 && !__CYGWIN__) */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_disk_windows.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_disk_windows.c new file mode 100644 index 0000000..fdd376f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_disk_windows.c @@ -0,0 +1,2477 @@ +/*- + * Copyright (c) 2003-2009 Tim Kientzle + * Copyright (c) 2010-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#if defined(_WIN32) && !defined(__CYGWIN__) + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#include + +#include "archive.h" +#include "archive_string.h" +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_read_disk_private.h" + +#ifndef O_BINARY +#define O_BINARY 0 +#endif +#ifndef IO_REPARSE_TAG_SYMLINK +/* Old SDKs do not provide IO_REPARSE_TAG_SYMLINK */ +#define IO_REPARSE_TAG_SYMLINK 0xA000000CL +#endif + +/*- + * This is a new directory-walking system that addresses a number + * of problems I've had with fts(3). In particular, it has no + * pathname-length limits (other than the size of 'int'), handles + * deep logical traversals, uses considerably less memory, and has + * an opaque interface (easier to modify in the future). + * + * Internally, it keeps a single list of "tree_entry" items that + * represent filesystem objects that require further attention. + * Non-directories are not kept in memory: they are pulled from + * readdir(), returned to the client, then freed as soon as possible. + * Any directory entry to be traversed gets pushed onto the stack. + * + * There is surprisingly little information that needs to be kept for + * each item on the stack. Just the name, depth (represented here as the + * string length of the parent directory's pathname), and some markers + * indicating how to get back to the parent (via chdir("..") for a + * regular dir or via fchdir(2) for a symlink). + */ + +struct restore_time { + const wchar_t *full_path; + FILETIME lastWriteTime; + FILETIME lastAccessTime; + mode_t filetype; +}; + +struct tree_entry { + int depth; + struct tree_entry *next; + struct tree_entry *parent; + size_t full_path_dir_length; + struct archive_wstring name; + struct archive_wstring full_path; + size_t dirname_length; + int64_t dev; + int64_t ino; + int flags; + int filesystem_id; + /* How to restore time of a directory. */ + struct restore_time restore_time; +}; + +struct filesystem { + int64_t dev; + int synthetic; + int remote; + DWORD bytesPerSector; +}; + +/* Definitions for tree_entry.flags bitmap. */ +#define isDir 1 /* This entry is a regular directory. */ +#define isDirLink 2 /* This entry is a symbolic link to a directory. */ +#define needsFirstVisit 4 /* This is an initial entry. */ +#define needsDescent 8 /* This entry needs to be previsited. */ +#define needsOpen 16 /* This is a directory that needs to be opened. */ +#define needsAscent 32 /* This entry needs to be postvisited. */ + +/* + * On Windows, "first visit" is handled as a pattern to be handed to + * _findfirst(). This is consistent with Windows conventions that + * file patterns are handled within the application. On Posix, + * "first visit" is just returned to the client. + */ + +#define MAX_OVERLAPPED 8 +#define READ_BUFFER_SIZE (1024 * 64) /* Default to 64KB per https://technet.microsoft.com/en-us/library/cc938632.aspx */ +#define DIRECT_IO 0/* Disabled */ +#define ASYNC_IO 1/* Enabled */ + +/* + * Local data for this package. + */ +struct tree { + struct tree_entry *stack; + struct tree_entry *current; + HANDLE d; + WIN32_FIND_DATAW _findData; + WIN32_FIND_DATAW *findData; + int flags; + int visit_type; + /* Error code from last failed operation. */ + int tree_errno; + + /* A full path with "\\?\" prefix. */ + struct archive_wstring full_path; + size_t full_path_dir_length; + /* Dynamically-sized buffer for holding path */ + struct archive_wstring path; + + /* Last path element */ + const wchar_t *basename; + /* Leading dir length */ + size_t dirname_length; + + int depth; + + BY_HANDLE_FILE_INFORMATION lst; + BY_HANDLE_FILE_INFORMATION st; + int descend; + /* How to restore time of a file. */ + struct restore_time restore_time; + + struct entry_sparse { + int64_t length; + int64_t offset; + } *sparse_list, *current_sparse; + int sparse_count; + int sparse_list_size; + + char initial_symlink_mode; + char symlink_mode; + struct filesystem *current_filesystem; + struct filesystem *filesystem_table; + int initial_filesystem_id; + int current_filesystem_id; + int max_filesystem_id; + int allocated_filesystem; + + HANDLE entry_fh; + int entry_eof; + int64_t entry_remaining_bytes; + int64_t entry_total; + + int ol_idx_doing; + int ol_idx_done; + int ol_num_doing; + int ol_num_done; + int64_t ol_remaining_bytes; + int64_t ol_total; + struct la_overlapped { + OVERLAPPED ol; + struct archive * _a; + unsigned char *buff; + size_t buff_size; + int64_t offset; + size_t bytes_expected; + size_t bytes_transferred; + } ol[MAX_OVERLAPPED]; + int direct_io; + int async_io; +}; + +#define bhfi_dev(bhfi) ((bhfi)->dwVolumeSerialNumber) +/* Treat FileIndex as i-node. We should remove a sequence number + * which is high-16-bits of nFileIndexHigh. */ +#define bhfi_ino(bhfi) \ + ((((int64_t)((bhfi)->nFileIndexHigh & 0x0000FFFFUL)) << 32) \ + + (bhfi)->nFileIndexLow) + +/* Definitions for tree.flags bitmap. */ +#define hasStat 16 /* The st entry is valid. */ +#define hasLstat 32 /* The lst entry is valid. */ +#define needsRestoreTimes 128 + +static int +tree_dir_next_windows(struct tree *t, const wchar_t *pattern); + +/* Initiate/terminate a tree traversal. */ +static struct tree *tree_open(const wchar_t *, int, int); +static struct tree *tree_reopen(struct tree *, const wchar_t *, int); +static void tree_close(struct tree *); +static void tree_free(struct tree *); +static void tree_push(struct tree *, const wchar_t *, const wchar_t *, + int, int64_t, int64_t, struct restore_time *); + +/* + * tree_next() returns Zero if there is no next entry, non-zero if + * there is. Note that directories are visited three times. + * Directories are always visited first as part of enumerating their + * parent; that is a "regular" visit. If tree_descend() is invoked at + * that time, the directory is added to a work list and will + * subsequently be visited two more times: once just after descending + * into the directory ("postdescent") and again just after ascending + * back to the parent ("postascent"). + * + * TREE_ERROR_DIR is returned if the descent failed (because the + * directory couldn't be opened, for instance). This is returned + * instead of TREE_POSTDESCENT/TREE_POSTASCENT. TREE_ERROR_DIR is not a + * fatal error, but it does imply that the relevant subtree won't be + * visited. TREE_ERROR_FATAL is returned for an error that left the + * traversal completely hosed. Right now, this is only returned for + * chdir() failures during ascent. + */ +#define TREE_REGULAR 1 +#define TREE_POSTDESCENT 2 +#define TREE_POSTASCENT 3 +#define TREE_ERROR_DIR -1 +#define TREE_ERROR_FATAL -2 + +static int tree_next(struct tree *); + +/* + * Return information about the current entry. + */ + +/* + * The current full pathname, length of the full pathname, and a name + * that can be used to access the file. Because tree does use chdir + * extensively, the access path is almost never the same as the full + * current path. + * + */ +static const wchar_t *tree_current_path(struct tree *); +static const wchar_t *tree_current_access_path(struct tree *); + +/* + * Request the lstat() or stat() data for the current path. Since the + * tree package needs to do some of this anyway, and caches the + * results, you should take advantage of it here if you need it rather + * than make a redundant stat() or lstat() call of your own. + */ +static const BY_HANDLE_FILE_INFORMATION *tree_current_stat(struct tree *); +static const BY_HANDLE_FILE_INFORMATION *tree_current_lstat(struct tree *); + +/* The following functions use tricks to avoid a certain number of + * stat()/lstat() calls. */ +/* "is_physical_dir" is equivalent to S_ISDIR(tree_current_lstat()->st_mode) */ +static int tree_current_is_physical_dir(struct tree *); +/* "is_physical_link" is equivalent to S_ISLNK(tree_current_lstat()->st_mode) */ +static int tree_current_is_physical_link(struct tree *); +/* Instead of archive_entry_copy_stat for BY_HANDLE_FILE_INFORMATION */ +static void tree_archive_entry_copy_bhfi(struct archive_entry *, + struct tree *, const BY_HANDLE_FILE_INFORMATION *); +/* "is_dir" is equivalent to S_ISDIR(tree_current_stat()->st_mode) */ +static int tree_current_is_dir(struct tree *); +static int update_current_filesystem(struct archive_read_disk *a, + int64_t dev); +static int setup_current_filesystem(struct archive_read_disk *); +static int tree_target_is_same_as_parent(struct tree *, + const BY_HANDLE_FILE_INFORMATION *); + +static int _archive_read_disk_open_w(struct archive *, const wchar_t *); +static int _archive_read_free(struct archive *); +static int _archive_read_close(struct archive *); +static int _archive_read_data_block(struct archive *, + const void **, size_t *, int64_t *); +static int _archive_read_next_header(struct archive *, + struct archive_entry **); +static int _archive_read_next_header2(struct archive *, + struct archive_entry *); +static const char *trivial_lookup_gname(void *, int64_t gid); +static const char *trivial_lookup_uname(void *, int64_t uid); +static int setup_sparse(struct archive_read_disk *, struct archive_entry *); +static int close_and_restore_time(HANDLE, struct tree *, + struct restore_time *); +static int setup_sparse_from_disk(struct archive_read_disk *, + struct archive_entry *, HANDLE); +static int la_linkname_from_handle(HANDLE, wchar_t **, int *); +static int la_linkname_from_pathw(const wchar_t *, wchar_t **, int *); +static void entry_symlink_from_pathw(struct archive_entry *, + const wchar_t *path); + +typedef struct _REPARSE_DATA_BUFFER { + ULONG ReparseTag; + USHORT ReparseDataLength; + USHORT Reserved; + union { + struct { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + ULONG Flags; + WCHAR PathBuffer[1]; + } SymbolicLinkReparseBuffer; + struct { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + WCHAR PathBuffer[1]; + } MountPointReparseBuffer; + struct { + UCHAR DataBuffer[1]; + } GenericReparseBuffer; + } DUMMYUNIONNAME; +} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; + +/* + * Reads the target of a symbolic link + * + * Returns 0 on success and -1 on failure + * outbuf is allocated in the function + */ +static int +la_linkname_from_handle(HANDLE h, wchar_t **linkname, int *linktype) +{ + DWORD inbytes; + REPARSE_DATA_BUFFER *buf; + BY_HANDLE_FILE_INFORMATION st; + size_t len; + BOOL ret; + BYTE *indata; + wchar_t *tbuf; + + ret = GetFileInformationByHandle(h, &st); + if (ret == 0 || + (st.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0) { + return (-1); + } + + indata = malloc(MAXIMUM_REPARSE_DATA_BUFFER_SIZE); + ret = DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, indata, + 1024, &inbytes, NULL); + if (ret == 0) { + la_dosmaperr(GetLastError()); + free(indata); + return (-1); + } + + buf = (REPARSE_DATA_BUFFER *) indata; + if (buf->ReparseTag != IO_REPARSE_TAG_SYMLINK) { + free(indata); + /* File is not a symbolic link */ + errno = EINVAL; + return (-1); + } + + len = buf->SymbolicLinkReparseBuffer.SubstituteNameLength; + if (len <= 0) { + free(indata); + return (-1); + } + + tbuf = malloc(len + 1 * sizeof(wchar_t)); + if (tbuf == NULL) { + free(indata); + return (-1); + } + + memcpy(tbuf, &((BYTE *)buf->SymbolicLinkReparseBuffer.PathBuffer) + [buf->SymbolicLinkReparseBuffer.SubstituteNameOffset], len); + free(indata); + + tbuf[len / sizeof(wchar_t)] = L'\0'; + + *linkname = tbuf; + + /* + * Translate backslashes to slashes for libarchive internal use + */ + while(*tbuf != L'\0') { + if (*tbuf == L'\\') + *tbuf = L'/'; + tbuf++; + } + + if ((st.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) + *linktype = AE_SYMLINK_TYPE_FILE; + else + *linktype = AE_SYMLINK_TYPE_DIRECTORY; + + return (0); +} + +/* + * Returns AE_SYMLINK_TYPE_FILE, AE_SYMLINK_TYPE_DIRECTORY or -1 on error + */ +static int +la_linkname_from_pathw(const wchar_t *path, wchar_t **outbuf, int *linktype) +{ + HANDLE h; + const DWORD flag = FILE_FLAG_BACKUP_SEMANTICS | + FILE_FLAG_OPEN_REPARSE_POINT; + int ret; + + h = CreateFileW(path, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, flag, + NULL); + if (h == INVALID_HANDLE_VALUE) { + la_dosmaperr(GetLastError()); + return (-1); + } + + ret = la_linkname_from_handle(h, outbuf, linktype); + CloseHandle(h); + + return (ret); +} + +static void +entry_symlink_from_pathw(struct archive_entry *entry, const wchar_t *path) +{ + wchar_t *linkname = NULL; + int ret, linktype; + + ret = la_linkname_from_pathw(path, &linkname, &linktype); + if (ret != 0) + return; + if (linktype >= 0) { + archive_entry_copy_symlink_w(entry, linkname); + archive_entry_set_symlink_type(entry, linktype); + } + free(linkname); + + return; +} + +static struct archive_vtable * +archive_read_disk_vtable(void) +{ + static struct archive_vtable av; + static int inited = 0; + + if (!inited) { + av.archive_free = _archive_read_free; + av.archive_close = _archive_read_close; + av.archive_read_data_block = _archive_read_data_block; + av.archive_read_next_header = _archive_read_next_header; + av.archive_read_next_header2 = _archive_read_next_header2; + inited = 1; + } + return (&av); +} + +const char * +archive_read_disk_gname(struct archive *_a, la_int64_t gid) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_read_disk_gname")) + return (NULL); + if (a->lookup_gname == NULL) + return (NULL); + return ((*a->lookup_gname)(a->lookup_gname_data, gid)); +} + +const char * +archive_read_disk_uname(struct archive *_a, la_int64_t uid) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_read_disk_uname")) + return (NULL); + if (a->lookup_uname == NULL) + return (NULL); + return ((*a->lookup_uname)(a->lookup_uname_data, uid)); +} + +int +archive_read_disk_set_gname_lookup(struct archive *_a, + void *private_data, + const char * (*lookup_gname)(void *private, la_int64_t gid), + void (*cleanup_gname)(void *private)) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + archive_check_magic(&a->archive, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_read_disk_set_gname_lookup"); + + if (a->cleanup_gname != NULL && a->lookup_gname_data != NULL) + (a->cleanup_gname)(a->lookup_gname_data); + + a->lookup_gname = lookup_gname; + a->cleanup_gname = cleanup_gname; + a->lookup_gname_data = private_data; + return (ARCHIVE_OK); +} + +int +archive_read_disk_set_uname_lookup(struct archive *_a, + void *private_data, + const char * (*lookup_uname)(void *private, int64_t uid), + void (*cleanup_uname)(void *private)) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + archive_check_magic(&a->archive, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_read_disk_set_uname_lookup"); + + if (a->cleanup_uname != NULL && a->lookup_uname_data != NULL) + (a->cleanup_uname)(a->lookup_uname_data); + + a->lookup_uname = lookup_uname; + a->cleanup_uname = cleanup_uname; + a->lookup_uname_data = private_data; + return (ARCHIVE_OK); +} + +/* + * Create a new archive_read_disk object and initialize it with global state. + */ +struct archive * +archive_read_disk_new(void) +{ + struct archive_read_disk *a; + + a = (struct archive_read_disk *)calloc(1, sizeof(*a)); + if (a == NULL) + return (NULL); + a->archive.magic = ARCHIVE_READ_DISK_MAGIC; + a->archive.state = ARCHIVE_STATE_NEW; + a->archive.vtable = archive_read_disk_vtable(); + a->entry = archive_entry_new2(&a->archive); + a->lookup_uname = trivial_lookup_uname; + a->lookup_gname = trivial_lookup_gname; + a->flags = ARCHIVE_READDISK_MAC_COPYFILE; + return (&a->archive); +} + +static int +_archive_read_free(struct archive *_a) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + int r; + + if (_a == NULL) + return (ARCHIVE_OK); + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_free"); + + if (a->archive.state != ARCHIVE_STATE_CLOSED) + r = _archive_read_close(&a->archive); + else + r = ARCHIVE_OK; + + tree_free(a->tree); + if (a->cleanup_gname != NULL && a->lookup_gname_data != NULL) + (a->cleanup_gname)(a->lookup_gname_data); + if (a->cleanup_uname != NULL && a->lookup_uname_data != NULL) + (a->cleanup_uname)(a->lookup_uname_data); + archive_string_free(&a->archive.error_string); + archive_entry_free(a->entry); + a->archive.magic = 0; + free(a); + return (r); +} + +static int +_archive_read_close(struct archive *_a) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_close"); + + if (a->archive.state != ARCHIVE_STATE_FATAL) + a->archive.state = ARCHIVE_STATE_CLOSED; + + tree_close(a->tree); + + return (ARCHIVE_OK); +} + +static void +setup_symlink_mode(struct archive_read_disk *a, char symlink_mode, + int follow_symlinks) +{ + a->symlink_mode = symlink_mode; + a->follow_symlinks = follow_symlinks; + if (a->tree != NULL) { + a->tree->initial_symlink_mode = a->symlink_mode; + a->tree->symlink_mode = a->symlink_mode; + } +} + +int +archive_read_disk_set_symlink_logical(struct archive *_a) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_read_disk_set_symlink_logical"); + setup_symlink_mode(a, 'L', 1); + return (ARCHIVE_OK); +} + +int +archive_read_disk_set_symlink_physical(struct archive *_a) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_read_disk_set_symlink_physical"); + setup_symlink_mode(a, 'P', 0); + return (ARCHIVE_OK); +} + +int +archive_read_disk_set_symlink_hybrid(struct archive *_a) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_read_disk_set_symlink_hybrid"); + setup_symlink_mode(a, 'H', 1);/* Follow symlinks initially. */ + return (ARCHIVE_OK); +} + +int +archive_read_disk_set_atime_restored(struct archive *_a) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_read_disk_restore_atime"); + a->flags |= ARCHIVE_READDISK_RESTORE_ATIME; + if (a->tree != NULL) + a->tree->flags |= needsRestoreTimes; + return (ARCHIVE_OK); +} + +int +archive_read_disk_set_behavior(struct archive *_a, int flags) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + int r = ARCHIVE_OK; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_read_disk_honor_nodump"); + + a->flags = flags; + + if (flags & ARCHIVE_READDISK_RESTORE_ATIME) + r = archive_read_disk_set_atime_restored(_a); + else { + if (a->tree != NULL) + a->tree->flags &= ~needsRestoreTimes; + } + return (r); +} + +/* + * Trivial implementations of gname/uname lookup functions. + * These are normally overridden by the client, but these stub + * versions ensure that we always have something that works. + */ +static const char * +trivial_lookup_gname(void *private_data, int64_t gid) +{ + (void)private_data; /* UNUSED */ + (void)gid; /* UNUSED */ + return (NULL); +} + +static const char * +trivial_lookup_uname(void *private_data, int64_t uid) +{ + (void)private_data; /* UNUSED */ + (void)uid; /* UNUSED */ + return (NULL); +} + +static int64_t +align_num_per_sector(struct tree *t, int64_t size) +{ + int64_t surplus; + + size += t->current_filesystem->bytesPerSector -1; + surplus = size % t->current_filesystem->bytesPerSector; + size -= surplus; + return (size); +} + +static int +start_next_async_read(struct archive_read_disk *a, struct tree *t) +{ + struct la_overlapped *olp; + DWORD buffbytes, rbytes; + + if (t->ol_remaining_bytes == 0) + return (ARCHIVE_EOF); + + olp = &(t->ol[t->ol_idx_doing]); + t->ol_idx_doing = (t->ol_idx_doing + 1) % MAX_OVERLAPPED; + + /* Allocate read buffer. */ + if (olp->buff == NULL) { + void *p; + size_t s = (size_t)align_num_per_sector(t, READ_BUFFER_SIZE); + p = VirtualAlloc(NULL, s, MEM_COMMIT, PAGE_READWRITE); + if (p == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Couldn't allocate memory"); + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } + olp->buff = p; + olp->buff_size = s; + olp->_a = &a->archive; + olp->ol.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); + if (olp->ol.hEvent == NULL) { + la_dosmaperr(GetLastError()); + archive_set_error(&a->archive, errno, + "CreateEvent failed"); + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } + } else + ResetEvent(olp->ol.hEvent); + + buffbytes = (DWORD)olp->buff_size; + if (buffbytes > t->current_sparse->length) + buffbytes = (DWORD)t->current_sparse->length; + + /* Skip hole. */ + if (t->current_sparse->offset > t->ol_total) { + t->ol_remaining_bytes -= + t->current_sparse->offset - t->ol_total; + } + + olp->offset = t->current_sparse->offset; + olp->ol.Offset = (DWORD)(olp->offset & 0xffffffff); + olp->ol.OffsetHigh = (DWORD)(olp->offset >> 32); + + if (t->ol_remaining_bytes > buffbytes) { + olp->bytes_expected = buffbytes; + t->ol_remaining_bytes -= buffbytes; + } else { + olp->bytes_expected = (size_t)t->ol_remaining_bytes; + t->ol_remaining_bytes = 0; + } + olp->bytes_transferred = 0; + t->current_sparse->offset += buffbytes; + t->current_sparse->length -= buffbytes; + t->ol_total = t->current_sparse->offset; + if (t->current_sparse->length == 0 && t->ol_remaining_bytes > 0) + t->current_sparse++; + + if (!ReadFile(t->entry_fh, olp->buff, buffbytes, &rbytes, &(olp->ol))) { + DWORD lasterr; + + lasterr = GetLastError(); + if (lasterr == ERROR_HANDLE_EOF) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Reading file truncated"); + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } else if (lasterr != ERROR_IO_PENDING) { + if (lasterr == ERROR_NO_DATA) + errno = EAGAIN; + else if (lasterr == ERROR_ACCESS_DENIED) + errno = EBADF; + else + la_dosmaperr(lasterr); + archive_set_error(&a->archive, errno, "Read error"); + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } + } else + olp->bytes_transferred = rbytes; + t->ol_num_doing++; + + return (t->ol_remaining_bytes == 0)? ARCHIVE_EOF: ARCHIVE_OK; +} + +static void +cancel_async(struct tree *t) +{ + if (t->ol_num_doing != t->ol_num_done) { + CancelIo(t->entry_fh); + t->ol_num_doing = t->ol_num_done = 0; + } +} + +static int +_archive_read_data_block(struct archive *_a, const void **buff, + size_t *size, int64_t *offset) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + struct tree *t = a->tree; + struct la_overlapped *olp; + DWORD bytes_transferred; + int r = ARCHIVE_FATAL; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA, + "archive_read_data_block"); + + if (t->entry_eof || t->entry_remaining_bytes <= 0) { + r = ARCHIVE_EOF; + goto abort_read_data; + } + + /* + * Make a request to read the file in asynchronous. + */ + if (t->ol_num_doing == 0) { + do { + r = start_next_async_read(a, t); + if (r == ARCHIVE_FATAL) + goto abort_read_data; + if (!t->async_io) + break; + } while (r == ARCHIVE_OK && t->ol_num_doing < MAX_OVERLAPPED); + } else { + if ((r = start_next_async_read(a, t)) == ARCHIVE_FATAL) + goto abort_read_data; + } + + olp = &(t->ol[t->ol_idx_done]); + t->ol_idx_done = (t->ol_idx_done + 1) % MAX_OVERLAPPED; + if (olp->bytes_transferred) + bytes_transferred = (DWORD)olp->bytes_transferred; + else if (!GetOverlappedResult(t->entry_fh, &(olp->ol), + &bytes_transferred, TRUE)) { + la_dosmaperr(GetLastError()); + archive_set_error(&a->archive, errno, + "GetOverlappedResult failed"); + a->archive.state = ARCHIVE_STATE_FATAL; + r = ARCHIVE_FATAL; + goto abort_read_data; + } + t->ol_num_done++; + + if (bytes_transferred == 0 || + olp->bytes_expected != bytes_transferred) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Reading file truncated"); + a->archive.state = ARCHIVE_STATE_FATAL; + r = ARCHIVE_FATAL; + goto abort_read_data; + } + + *buff = olp->buff; + *size = bytes_transferred; + *offset = olp->offset; + if (olp->offset > t->entry_total) + t->entry_remaining_bytes -= olp->offset - t->entry_total; + t->entry_total = olp->offset + *size; + t->entry_remaining_bytes -= *size; + if (t->entry_remaining_bytes == 0) { + /* Close the current file descriptor */ + close_and_restore_time(t->entry_fh, t, &t->restore_time); + t->entry_fh = INVALID_HANDLE_VALUE; + t->entry_eof = 1; + } + return (ARCHIVE_OK); + +abort_read_data: + *buff = NULL; + *size = 0; + *offset = t->entry_total; + if (t->entry_fh != INVALID_HANDLE_VALUE) { + cancel_async(t); + /* Close the current file descriptor */ + close_and_restore_time(t->entry_fh, t, &t->restore_time); + t->entry_fh = INVALID_HANDLE_VALUE; + } + return (r); +} + +static int +next_entry(struct archive_read_disk *a, struct tree *t, + struct archive_entry *entry) +{ + const BY_HANDLE_FILE_INFORMATION *st; + const BY_HANDLE_FILE_INFORMATION *lst; + const char*name; + int descend, r; + + st = NULL; + lst = NULL; + t->descend = 0; + do { + switch (tree_next(t)) { + case TREE_ERROR_FATAL: + archive_set_error(&a->archive, t->tree_errno, + "%ls: Unable to continue traversing directory tree", + tree_current_path(t)); + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + case TREE_ERROR_DIR: + archive_set_error(&a->archive, t->tree_errno, + "%ls: Couldn't visit directory", + tree_current_path(t)); + return (ARCHIVE_FAILED); + case 0: + return (ARCHIVE_EOF); + case TREE_POSTDESCENT: + case TREE_POSTASCENT: + break; + case TREE_REGULAR: + lst = tree_current_lstat(t); + if (lst == NULL) { + archive_set_error(&a->archive, t->tree_errno, + "%ls: Cannot stat", + tree_current_path(t)); + return (ARCHIVE_FAILED); + } + break; + } + } while (lst == NULL); + + archive_entry_copy_pathname_w(entry, tree_current_path(t)); + + /* + * Perform path matching. + */ + if (a->matching) { + r = archive_match_path_excluded(a->matching, entry); + if (r < 0) { + archive_set_error(&(a->archive), errno, + "Failed : %s", archive_error_string(a->matching)); + return (r); + } + if (r) { + if (a->excluded_cb_func) + a->excluded_cb_func(&(a->archive), + a->excluded_cb_data, entry); + return (ARCHIVE_RETRY); + } + } + + /* + * Distinguish 'L'/'P'/'H' symlink following. + */ + switch(t->symlink_mode) { + case 'H': + /* 'H': After the first item, rest like 'P'. */ + t->symlink_mode = 'P'; + /* 'H': First item (from command line) like 'L'. */ + /* FALLTHROUGH */ + case 'L': + /* 'L': Do descend through a symlink to dir. */ + descend = tree_current_is_dir(t); + /* 'L': Follow symlinks to files. */ + a->symlink_mode = 'L'; + a->follow_symlinks = 1; + /* 'L': Archive symlinks as targets, if we can. */ + st = tree_current_stat(t); + if (st != NULL && !tree_target_is_same_as_parent(t, st)) + break; + /* If stat fails, we have a broken symlink; + * in that case, don't follow the link. */ + /* FALLTHROUGH */ + default: + /* 'P': Don't descend through a symlink to dir. */ + descend = tree_current_is_physical_dir(t); + /* 'P': Don't follow symlinks to files. */ + a->symlink_mode = 'P'; + a->follow_symlinks = 0; + /* 'P': Archive symlinks as symlinks. */ + st = lst; + break; + } + + if (update_current_filesystem(a, bhfi_dev(st)) != ARCHIVE_OK) { + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } + if (t->initial_filesystem_id == -1) + t->initial_filesystem_id = t->current_filesystem_id; + if (a->flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) { + if (t->initial_filesystem_id != t->current_filesystem_id) + return (ARCHIVE_RETRY); + } + t->descend = descend; + + tree_archive_entry_copy_bhfi(entry, t, st); + + /* Save the times to be restored. This must be in before + * calling archive_read_disk_descend() or any chance of it, + * especially, invoking a callback. */ + t->restore_time.lastWriteTime = st->ftLastWriteTime; + t->restore_time.lastAccessTime = st->ftLastAccessTime; + t->restore_time.filetype = archive_entry_filetype(entry); + + /* + * Perform time matching. + */ + if (a->matching) { + r = archive_match_time_excluded(a->matching, entry); + if (r < 0) { + archive_set_error(&(a->archive), errno, + "Failed : %s", archive_error_string(a->matching)); + return (r); + } + if (r) { + if (a->excluded_cb_func) + a->excluded_cb_func(&(a->archive), + a->excluded_cb_data, entry); + return (ARCHIVE_RETRY); + } + } + + /* Lookup uname/gname */ + name = archive_read_disk_uname(&(a->archive), archive_entry_uid(entry)); + if (name != NULL) + archive_entry_copy_uname(entry, name); + name = archive_read_disk_gname(&(a->archive), archive_entry_gid(entry)); + if (name != NULL) + archive_entry_copy_gname(entry, name); + + /* + * Perform owner matching. + */ + if (a->matching) { + r = archive_match_owner_excluded(a->matching, entry); + if (r < 0) { + archive_set_error(&(a->archive), errno, + "Failed : %s", archive_error_string(a->matching)); + return (r); + } + if (r) { + if (a->excluded_cb_func) + a->excluded_cb_func(&(a->archive), + a->excluded_cb_data, entry); + return (ARCHIVE_RETRY); + } + } + + /* + * File attributes + */ + if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0) { + const int supported_attrs = + FILE_ATTRIBUTE_READONLY | + FILE_ATTRIBUTE_HIDDEN | + FILE_ATTRIBUTE_SYSTEM; + DWORD file_attrs = st->dwFileAttributes & supported_attrs; + if (file_attrs != 0) + archive_entry_set_fflags(entry, file_attrs, 0); + } + + /* + * Invoke a meta data filter callback. + */ + if (a->metadata_filter_func) { + if (!a->metadata_filter_func(&(a->archive), + a->metadata_filter_data, entry)) + return (ARCHIVE_RETRY); + } + + archive_entry_copy_sourcepath_w(entry, tree_current_access_path(t)); + + r = ARCHIVE_OK; + if (archive_entry_filetype(entry) == AE_IFREG && + archive_entry_size(entry) > 0) { + DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; + if (t->async_io) + flags |= FILE_FLAG_OVERLAPPED; + if (t->direct_io) + flags |= FILE_FLAG_NO_BUFFERING; + else + flags |= FILE_FLAG_SEQUENTIAL_SCAN; + t->entry_fh = CreateFileW(tree_current_access_path(t), + GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, flags, NULL); + if (t->entry_fh == INVALID_HANDLE_VALUE) { + la_dosmaperr(GetLastError()); + archive_set_error(&a->archive, errno, + "Couldn't open %ls", tree_current_path(a->tree)); + return (ARCHIVE_FAILED); + } + + /* Find sparse data from the disk. */ + if (archive_entry_hardlink(entry) == NULL && + (st->dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) != 0) + r = setup_sparse_from_disk(a, entry, t->entry_fh); + } + return (r); +} + +static int +_archive_read_next_header(struct archive *_a, struct archive_entry **entryp) +{ + int ret; + struct archive_read_disk *a = (struct archive_read_disk *)_a; + *entryp = NULL; + ret = _archive_read_next_header2(_a, a->entry); + *entryp = a->entry; + return ret; +} + +static int +_archive_read_next_header2(struct archive *_a, struct archive_entry *entry) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + struct tree *t; + int r; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_read_next_header2"); + + t = a->tree; + if (t->entry_fh != INVALID_HANDLE_VALUE) { + cancel_async(t); + close_and_restore_time(t->entry_fh, t, &t->restore_time); + t->entry_fh = INVALID_HANDLE_VALUE; + } + + archive_entry_clear(entry); + + while ((r = next_entry(a, t, entry)) == ARCHIVE_RETRY) + archive_entry_clear(entry); + + /* + * EOF and FATAL are persistent at this layer. By + * modifying the state, we guarantee that future calls to + * read a header or read data will fail. + */ + switch (r) { + case ARCHIVE_EOF: + a->archive.state = ARCHIVE_STATE_EOF; + break; + case ARCHIVE_OK: + case ARCHIVE_WARN: + t->entry_total = 0; + if (archive_entry_filetype(entry) == AE_IFREG) { + t->entry_remaining_bytes = archive_entry_size(entry); + t->entry_eof = (t->entry_remaining_bytes == 0)? 1: 0; + if (!t->entry_eof && + setup_sparse(a, entry) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } else { + t->entry_remaining_bytes = 0; + t->entry_eof = 1; + } + t->ol_idx_doing = t->ol_idx_done = 0; + t->ol_num_doing = t->ol_num_done = 0; + t->ol_remaining_bytes = t->entry_remaining_bytes; + t->ol_total = 0; + a->archive.state = ARCHIVE_STATE_DATA; + break; + case ARCHIVE_RETRY: + break; + case ARCHIVE_FATAL: + a->archive.state = ARCHIVE_STATE_FATAL; + break; + } + + __archive_reset_read_data(&a->archive); + return (r); +} + +static int +setup_sparse(struct archive_read_disk *a, struct archive_entry *entry) +{ + struct tree *t = a->tree; + int64_t aligned, length, offset; + int i; + + t->sparse_count = archive_entry_sparse_reset(entry); + if (t->sparse_count+1 > t->sparse_list_size) { + free(t->sparse_list); + t->sparse_list_size = t->sparse_count + 1; + t->sparse_list = malloc(sizeof(t->sparse_list[0]) * + t->sparse_list_size); + if (t->sparse_list == NULL) { + t->sparse_list_size = 0; + archive_set_error(&a->archive, ENOMEM, + "Can't allocate data"); + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } + } + /* + * Get sparse list and make sure those offsets and lengths are + * aligned by a sector size. + */ + for (i = 0; i < t->sparse_count; i++) { + archive_entry_sparse_next(entry, &offset, &length); + aligned = align_num_per_sector(t, offset); + if (aligned != offset) { + aligned -= t->current_filesystem->bytesPerSector; + length += offset - aligned; + } + t->sparse_list[i].offset = aligned; + aligned = align_num_per_sector(t, length); + t->sparse_list[i].length = aligned; + } + + aligned = align_num_per_sector(t, archive_entry_size(entry)); + if (i == 0) { + t->sparse_list[i].offset = 0; + t->sparse_list[i].length = aligned; + } else { + int j, last = i; + + t->sparse_list[i].offset = aligned; + t->sparse_list[i].length = 0; + for (i = 0; i < last; i++) { + if ((t->sparse_list[i].offset + + t->sparse_list[i].length) <= + t->sparse_list[i+1].offset) + continue; + /* + * Now sparse_list[i+1] is overlapped by sparse_list[i]. + * Merge those two. + */ + length = t->sparse_list[i+1].offset - + t->sparse_list[i].offset; + t->sparse_list[i+1].offset = t->sparse_list[i].offset; + t->sparse_list[i+1].length += length; + /* Remove sparse_list[i]. */ + for (j = i; j < last; j++) { + t->sparse_list[j].offset = + t->sparse_list[j+1].offset; + t->sparse_list[j].length = + t->sparse_list[j+1].length; + } + last--; + } + } + t->current_sparse = t->sparse_list; + + return (ARCHIVE_OK); +} + +int +archive_read_disk_set_matching(struct archive *_a, struct archive *_ma, + void (*_excluded_func)(struct archive *, void *, struct archive_entry *), + void *_client_data) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_read_disk_set_matching"); + a->matching = _ma; + a->excluded_cb_func = _excluded_func; + a->excluded_cb_data = _client_data; + return (ARCHIVE_OK); +} + +int +archive_read_disk_set_metadata_filter_callback(struct archive *_a, + int (*_metadata_filter_func)(struct archive *, void *, + struct archive_entry *), void *_client_data) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_ANY, + "archive_read_disk_set_metadata_filter_callback"); + + a->metadata_filter_func = _metadata_filter_func; + a->metadata_filter_data = _client_data; + return (ARCHIVE_OK); +} + +int +archive_read_disk_can_descend(struct archive *_a) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + struct tree *t = a->tree; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_read_disk_can_descend"); + + return (t->visit_type == TREE_REGULAR && t->descend); +} + +/* + * Called by the client to mark the directory just returned from + * tree_next() as needing to be visited. + */ +int +archive_read_disk_descend(struct archive *_a) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + struct tree *t = a->tree; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_read_disk_descend"); + + if (t->visit_type != TREE_REGULAR || !t->descend) + return (ARCHIVE_OK); + + if (tree_current_is_physical_dir(t)) { + tree_push(t, t->basename, t->full_path.s, + t->current_filesystem_id, + bhfi_dev(&(t->lst)), bhfi_ino(&(t->lst)), + &t->restore_time); + t->stack->flags |= isDir; + } else if (tree_current_is_dir(t)) { + tree_push(t, t->basename, t->full_path.s, + t->current_filesystem_id, + bhfi_dev(&(t->st)), bhfi_ino(&(t->st)), + &t->restore_time); + t->stack->flags |= isDirLink; + } + t->descend = 0; + return (ARCHIVE_OK); +} + +int +archive_read_disk_open(struct archive *_a, const char *pathname) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + struct archive_wstring wpath; + int ret; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_NEW | ARCHIVE_STATE_CLOSED, + "archive_read_disk_open"); + archive_clear_error(&a->archive); + + /* Make a wchar_t string from a char string. */ + archive_string_init(&wpath); + if (archive_wstring_append_from_mbs(&wpath, pathname, + strlen(pathname)) != 0) { + if (errno == ENOMEM) + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + else + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't convert a path to a wchar_t string"); + a->archive.state = ARCHIVE_STATE_FATAL; + ret = ARCHIVE_FATAL; + } else + ret = _archive_read_disk_open_w(_a, wpath.s); + + archive_wstring_free(&wpath); + return (ret); +} + +int +archive_read_disk_open_w(struct archive *_a, const wchar_t *pathname) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_NEW | ARCHIVE_STATE_CLOSED, + "archive_read_disk_open_w"); + archive_clear_error(&a->archive); + + return (_archive_read_disk_open_w(_a, pathname)); +} + +static int +_archive_read_disk_open_w(struct archive *_a, const wchar_t *pathname) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + + if (a->tree != NULL) + a->tree = tree_reopen(a->tree, pathname, + a->flags & ARCHIVE_READDISK_RESTORE_ATIME); + else + a->tree = tree_open(pathname, a->symlink_mode, + a->flags & ARCHIVE_READDISK_RESTORE_ATIME); + if (a->tree == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate directory traversal data"); + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } + a->archive.state = ARCHIVE_STATE_HEADER; + + return (ARCHIVE_OK); +} + +/* + * Return a current filesystem ID which is index of the filesystem entry + * you've visited through archive_read_disk. + */ +int +archive_read_disk_current_filesystem(struct archive *_a) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA, + "archive_read_disk_current_filesystem"); + + return (a->tree->current_filesystem_id); +} + +static int +update_current_filesystem(struct archive_read_disk *a, int64_t dev) +{ + struct tree *t = a->tree; + int i, fid; + + if (t->current_filesystem != NULL && + t->current_filesystem->dev == dev) + return (ARCHIVE_OK); + + for (i = 0; i < t->max_filesystem_id; i++) { + if (t->filesystem_table[i].dev == dev) { + /* There is the filesystem ID we've already generated. */ + t->current_filesystem_id = i; + t->current_filesystem = &(t->filesystem_table[i]); + return (ARCHIVE_OK); + } + } + + /* + * There is a new filesystem, we generate a new ID for. + */ + fid = t->max_filesystem_id++; + if (t->max_filesystem_id > t->allocated_filesystem) { + size_t s; + void *p; + + s = t->max_filesystem_id * 2; + p = realloc(t->filesystem_table, + s * sizeof(*t->filesystem_table)); + if (p == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate tar data"); + return (ARCHIVE_FATAL); + } + t->filesystem_table = (struct filesystem *)p; + t->allocated_filesystem = (int)s; + } + t->current_filesystem_id = fid; + t->current_filesystem = &(t->filesystem_table[fid]); + t->current_filesystem->dev = dev; + + return (setup_current_filesystem(a)); +} + +/* + * Returns 1 if current filesystem is generated filesystem, 0 if it is not + * or -1 if it is unknown. + */ +int +archive_read_disk_current_filesystem_is_synthetic(struct archive *_a) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA, + "archive_read_disk_current_filesystem"); + + return (a->tree->current_filesystem->synthetic); +} + +/* + * Returns 1 if current filesystem is remote filesystem, 0 if it is not + * or -1 if it is unknown. + */ +int +archive_read_disk_current_filesystem_is_remote(struct archive *_a) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA, + "archive_read_disk_current_filesystem"); + + return (a->tree->current_filesystem->remote); +} + +/* + * If symlink is broken, statfs or statvfs will fail. + * Use its directory path instead. + */ +static wchar_t * +safe_path_for_statfs(struct tree *t) +{ + const wchar_t *path; + wchar_t *cp, *p = NULL; + + path = tree_current_access_path(t); + if (tree_current_stat(t) == NULL) { + p = _wcsdup(path); + cp = wcsrchr(p, '/'); + if (cp != NULL && wcslen(cp) >= 2) { + cp[1] = '.'; + cp[2] = '\0'; + path = p; + } + } else + p = _wcsdup(path); + return (p); +} + +/* + * Get conditions of synthetic and remote on Windows + */ +static int +setup_current_filesystem(struct archive_read_disk *a) +{ + struct tree *t = a->tree; + wchar_t vol[256]; + wchar_t *path; + + t->current_filesystem->synthetic = -1;/* Not supported */ + path = safe_path_for_statfs(t); + if (!GetVolumePathNameW(path, vol, sizeof(vol)/sizeof(vol[0]))) { + free(path); + t->current_filesystem->remote = -1; + t->current_filesystem->bytesPerSector = 0; + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "GetVolumePathName failed: %d", (int)GetLastError()); + return (ARCHIVE_FAILED); + } + free(path); + switch (GetDriveTypeW(vol)) { + case DRIVE_UNKNOWN: + case DRIVE_NO_ROOT_DIR: + t->current_filesystem->remote = -1; + break; + case DRIVE_REMOTE: + t->current_filesystem->remote = 1; + break; + default: + t->current_filesystem->remote = 0; + break; + } + + if (!GetDiskFreeSpaceW(vol, NULL, + &(t->current_filesystem->bytesPerSector), NULL, NULL)) { + t->current_filesystem->bytesPerSector = 0; + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "GetDiskFreeSpace failed: %d", (int)GetLastError()); + return (ARCHIVE_FAILED); + } + + return (ARCHIVE_OK); +} + +static int +close_and_restore_time(HANDLE h, struct tree *t, struct restore_time *rt) +{ + HANDLE handle; + int r = 0; + + if (h == INVALID_HANDLE_VALUE && AE_IFLNK == rt->filetype) + return (0); + + /* Close a file descriptor. + * It will not be used for SetFileTime() because it has been opened + * by a read only mode. + */ + if (h != INVALID_HANDLE_VALUE) + CloseHandle(h); + if ((t->flags & needsRestoreTimes) == 0) + return (r); + + handle = CreateFileW(rt->full_path, FILE_WRITE_ATTRIBUTES, + 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (handle == INVALID_HANDLE_VALUE) { + errno = EINVAL; + return (-1); + } + + if (SetFileTime(handle, NULL, &rt->lastAccessTime, + &rt->lastWriteTime) == 0) { + errno = EINVAL; + r = -1; + } else + r = 0; + CloseHandle(handle); + return (r); +} + +/* + * Add a directory path to the current stack. + */ +static void +tree_push(struct tree *t, const wchar_t *path, const wchar_t *full_path, + int filesystem_id, int64_t dev, int64_t ino, struct restore_time *rt) +{ + struct tree_entry *te; + + te = calloc(1, sizeof(*te)); + te->next = t->stack; + te->parent = t->current; + if (te->parent) + te->depth = te->parent->depth + 1; + t->stack = te; + archive_string_init(&te->name); + archive_wstrcpy(&te->name, path); + archive_string_init(&te->full_path); + archive_wstrcpy(&te->full_path, full_path); + te->flags = needsDescent | needsOpen | needsAscent; + te->filesystem_id = filesystem_id; + te->dev = dev; + te->ino = ino; + te->dirname_length = t->dirname_length; + te->full_path_dir_length = t->full_path_dir_length; + te->restore_time.full_path = te->full_path.s; + if (rt != NULL) { + te->restore_time.lastWriteTime = rt->lastWriteTime; + te->restore_time.lastAccessTime = rt->lastAccessTime; + te->restore_time.filetype = rt->filetype; + } +} + +/* + * Append a name to the current dir path. + */ +static void +tree_append(struct tree *t, const wchar_t *name, size_t name_length) +{ + size_t size_needed; + + t->path.s[t->dirname_length] = L'\0'; + t->path.length = t->dirname_length; + /* Strip trailing '/' from name, unless entire name is "/". */ + while (name_length > 1 && name[name_length - 1] == L'/') + name_length--; + + /* Resize pathname buffer as needed. */ + size_needed = name_length + t->dirname_length + 2; + archive_wstring_ensure(&t->path, size_needed); + /* Add a separating '/' if it's needed. */ + if (t->dirname_length > 0 && + t->path.s[archive_strlen(&t->path)-1] != L'/') + archive_wstrappend_wchar(&t->path, L'/'); + t->basename = t->path.s + archive_strlen(&t->path); + archive_wstrncat(&t->path, name, name_length); + t->restore_time.full_path = t->basename; + if (t->full_path_dir_length > 0) { + t->full_path.s[t->full_path_dir_length] = L'\0'; + t->full_path.length = t->full_path_dir_length; + size_needed = name_length + t->full_path_dir_length + 2; + archive_wstring_ensure(&t->full_path, size_needed); + /* Add a separating '\' if it's needed. */ + if (t->full_path.s[archive_strlen(&t->full_path)-1] != L'\\') + archive_wstrappend_wchar(&t->full_path, L'\\'); + archive_wstrncat(&t->full_path, name, name_length); + t->restore_time.full_path = t->full_path.s; + } +} + +/* + * Open a directory tree for traversal. + */ +static struct tree * +tree_open(const wchar_t *path, int symlink_mode, int restore_time) +{ + struct tree *t; + + t = calloc(1, sizeof(*t)); + archive_string_init(&(t->full_path)); + archive_string_init(&t->path); + archive_wstring_ensure(&t->path, 15); + t->initial_symlink_mode = symlink_mode; + return (tree_reopen(t, path, restore_time)); +} + +static struct tree * +tree_reopen(struct tree *t, const wchar_t *path, int restore_time) +{ + struct archive_wstring ws; + wchar_t *pathname, *p, *base; + + t->flags = (restore_time != 0)?needsRestoreTimes:0; + t->visit_type = 0; + t->tree_errno = 0; + t->full_path_dir_length = 0; + t->dirname_length = 0; + t->depth = 0; + t->descend = 0; + t->current = NULL; + t->d = INVALID_HANDLE_VALUE; + t->symlink_mode = t->initial_symlink_mode; + archive_string_empty(&(t->full_path)); + archive_string_empty(&t->path); + t->entry_fh = INVALID_HANDLE_VALUE; + t->entry_eof = 0; + t->entry_remaining_bytes = 0; + t->initial_filesystem_id = -1; + + /* Get wchar_t strings from char strings. */ + archive_string_init(&ws); + archive_wstrcpy(&ws, path); + pathname = ws.s; + /* Get a full-path-name. */ + p = __la_win_permissive_name_w(pathname); + if (p == NULL) + goto failed; + archive_wstrcpy(&(t->full_path), p); + free(p); + + /* Convert path separators from '\' to '/' */ + for (p = pathname; *p != L'\0'; ++p) { + if (*p == L'\\') + *p = L'/'; + } + base = pathname; + + /* First item is set up a lot like a symlink traversal. */ + /* printf("Looking for wildcard in %s\n", path); */ + if ((base[0] == L'/' && base[1] == L'/' && + base[2] == L'?' && base[3] == L'/' && + (wcschr(base+4, L'*') || wcschr(base+4, L'?'))) || + (!(base[0] == L'/' && base[1] == L'/' && + base[2] == L'?' && base[3] == L'/') && + (wcschr(base, L'*') || wcschr(base, L'?')))) { + // It has a wildcard in it... + // Separate the last element. + p = wcsrchr(base, L'/'); + if (p != NULL) { + *p = L'\0'; + tree_append(t, base, p - base); + t->dirname_length = archive_strlen(&t->path); + base = p + 1; + } + p = wcsrchr(t->full_path.s, L'\\'); + if (p != NULL) { + *p = L'\0'; + t->full_path.length = wcslen(t->full_path.s); + t->full_path_dir_length = archive_strlen(&t->full_path); + } + } + tree_push(t, base, t->full_path.s, 0, 0, 0, NULL); + archive_wstring_free(&ws); + t->stack->flags = needsFirstVisit; + /* + * Debug flag for Direct IO(No buffering) or Async IO. + * Those dependent on environment variable switches + * will be removed until next release. + */ + { + const char *e; + if ((e = getenv("LIBARCHIVE_DIRECT_IO")) != NULL) { + if (e[0] == '0') + t->direct_io = 0; + else + t->direct_io = 1; + fprintf(stderr, "LIBARCHIVE_DIRECT_IO=%s\n", + (t->direct_io)?"Enabled":"Disabled"); + } else + t->direct_io = DIRECT_IO; + if ((e = getenv("LIBARCHIVE_ASYNC_IO")) != NULL) { + if (e[0] == '0') + t->async_io = 0; + else + t->async_io = 1; + fprintf(stderr, "LIBARCHIVE_ASYNC_IO=%s\n", + (t->async_io)?"Enabled":"Disabled"); + } else + t->async_io = ASYNC_IO; + } + return (t); +failed: + archive_wstring_free(&ws); + tree_free(t); + return (NULL); +} + +static int +tree_descent(struct tree *t) +{ + t->dirname_length = archive_strlen(&t->path); + t->full_path_dir_length = archive_strlen(&t->full_path); + t->depth++; + return (0); +} + +/* + * We've finished a directory; ascend back to the parent. + */ +static int +tree_ascend(struct tree *t) +{ + struct tree_entry *te; + + te = t->stack; + t->depth--; + close_and_restore_time(INVALID_HANDLE_VALUE, t, &te->restore_time); + return (0); +} + +/* + * Pop the working stack. + */ +static void +tree_pop(struct tree *t) +{ + struct tree_entry *te; + + t->full_path.s[t->full_path_dir_length] = L'\0'; + t->full_path.length = t->full_path_dir_length; + t->path.s[t->dirname_length] = L'\0'; + t->path.length = t->dirname_length; + if (t->stack == t->current && t->current != NULL) + t->current = t->current->parent; + te = t->stack; + t->stack = te->next; + t->dirname_length = te->dirname_length; + t->basename = t->path.s + t->dirname_length; + t->full_path_dir_length = te->full_path_dir_length; + while (t->basename[0] == L'/') + t->basename++; + archive_wstring_free(&te->name); + archive_wstring_free(&te->full_path); + free(te); +} + +/* + * Get the next item in the tree traversal. + */ +static int +tree_next(struct tree *t) +{ + int r; + + while (t->stack != NULL) { + /* If there's an open dir, get the next entry from there. */ + if (t->d != INVALID_HANDLE_VALUE) { + r = tree_dir_next_windows(t, NULL); + if (r == 0) + continue; + return (r); + } + + if (t->stack->flags & needsFirstVisit) { + wchar_t *d = t->stack->name.s; + t->stack->flags &= ~needsFirstVisit; + if (!(d[0] == L'/' && d[1] == L'/' && + d[2] == L'?' && d[3] == L'/') && + (wcschr(d, L'*') || wcschr(d, L'?'))) { + r = tree_dir_next_windows(t, d); + if (r == 0) + continue; + return (r); + } else { + HANDLE h = FindFirstFileW(d, &t->_findData); + if (h == INVALID_HANDLE_VALUE) { + la_dosmaperr(GetLastError()); + t->tree_errno = errno; + t->visit_type = TREE_ERROR_DIR; + return (t->visit_type); + } + t->findData = &t->_findData; + FindClose(h); + } + /* Top stack item needs a regular visit. */ + t->current = t->stack; + tree_append(t, t->stack->name.s, + archive_strlen(&(t->stack->name))); + //t->dirname_length = t->path_length; + //tree_pop(t); + t->stack->flags &= ~needsFirstVisit; + return (t->visit_type = TREE_REGULAR); + } else if (t->stack->flags & needsDescent) { + /* Top stack item is dir to descend into. */ + t->current = t->stack; + tree_append(t, t->stack->name.s, + archive_strlen(&(t->stack->name))); + t->stack->flags &= ~needsDescent; + r = tree_descent(t); + if (r != 0) { + tree_pop(t); + t->visit_type = r; + } else + t->visit_type = TREE_POSTDESCENT; + return (t->visit_type); + } else if (t->stack->flags & needsOpen) { + t->stack->flags &= ~needsOpen; + r = tree_dir_next_windows(t, L"*"); + if (r == 0) + continue; + return (r); + } else if (t->stack->flags & needsAscent) { + /* Top stack item is dir and we're done with it. */ + r = tree_ascend(t); + tree_pop(t); + t->visit_type = r != 0 ? r : TREE_POSTASCENT; + return (t->visit_type); + } else { + /* Top item on stack is dead. */ + tree_pop(t); + t->flags &= ~hasLstat; + t->flags &= ~hasStat; + } + } + return (t->visit_type = 0); +} + +static int +tree_dir_next_windows(struct tree *t, const wchar_t *pattern) +{ + const wchar_t *name; + size_t namelen; + int r; + + for (;;) { + if (pattern != NULL) { + struct archive_wstring pt; + + archive_string_init(&pt); + archive_wstring_ensure(&pt, + archive_strlen(&(t->full_path)) + + 2 + wcslen(pattern)); + archive_wstring_copy(&pt, &(t->full_path)); + archive_wstrappend_wchar(&pt, L'\\'); + archive_wstrcat(&pt, pattern); + t->d = FindFirstFileW(pt.s, &t->_findData); + archive_wstring_free(&pt); + if (t->d == INVALID_HANDLE_VALUE) { + la_dosmaperr(GetLastError()); + t->tree_errno = errno; + r = tree_ascend(t); /* Undo "chdir" */ + tree_pop(t); + t->visit_type = r != 0 ? r : TREE_ERROR_DIR; + return (t->visit_type); + } + t->findData = &t->_findData; + pattern = NULL; + } else if (!FindNextFileW(t->d, &t->_findData)) { + FindClose(t->d); + t->d = INVALID_HANDLE_VALUE; + t->findData = NULL; + return (0); + } + name = t->findData->cFileName; + namelen = wcslen(name); + t->flags &= ~hasLstat; + t->flags &= ~hasStat; + if (name[0] == L'.' && name[1] == L'\0') + continue; + if (name[0] == L'.' && name[1] == L'.' && name[2] == L'\0') + continue; + tree_append(t, name, namelen); + return (t->visit_type = TREE_REGULAR); + } +} + +#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) +static void +fileTimeToUtc(const FILETIME *filetime, time_t *t, long *ns) +{ + ULARGE_INTEGER utc; + + utc.HighPart = filetime->dwHighDateTime; + utc.LowPart = filetime->dwLowDateTime; + if (utc.QuadPart >= EPOC_TIME) { + utc.QuadPart -= EPOC_TIME; + /* milli seconds base */ + *t = (time_t)(utc.QuadPart / 10000000); + /* nano seconds base */ + *ns = (long)(utc.QuadPart % 10000000) * 100; + } else { + *t = 0; + *ns = 0; + } +} + +static void +entry_copy_bhfi(struct archive_entry *entry, const wchar_t *path, + const WIN32_FIND_DATAW *findData, + const BY_HANDLE_FILE_INFORMATION *bhfi) +{ + time_t secs; + long nsecs; + mode_t mode; + + fileTimeToUtc(&bhfi->ftLastAccessTime, &secs, &nsecs); + archive_entry_set_atime(entry, secs, nsecs); + fileTimeToUtc(&bhfi->ftLastWriteTime, &secs, &nsecs); + archive_entry_set_mtime(entry, secs, nsecs); + fileTimeToUtc(&bhfi->ftCreationTime, &secs, &nsecs); + archive_entry_set_birthtime(entry, secs, nsecs); + archive_entry_set_ctime(entry, secs, nsecs); + archive_entry_set_dev(entry, bhfi_dev(bhfi)); + archive_entry_set_ino64(entry, bhfi_ino(bhfi)); + if (bhfi->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + archive_entry_set_nlink(entry, bhfi->nNumberOfLinks + 1); + else + archive_entry_set_nlink(entry, bhfi->nNumberOfLinks); + archive_entry_set_size(entry, + (((int64_t)bhfi->nFileSizeHigh) << 32) + + bhfi->nFileSizeLow); + archive_entry_set_uid(entry, 0); + archive_entry_set_gid(entry, 0); + archive_entry_set_rdev(entry, 0); + + mode = S_IRUSR | S_IRGRP | S_IROTH; + if ((bhfi->dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0) + mode |= S_IWUSR | S_IWGRP | S_IWOTH; + if ((bhfi->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) && + findData != NULL && + findData->dwReserved0 == IO_REPARSE_TAG_SYMLINK) { + mode |= S_IFLNK; + entry_symlink_from_pathw(entry, path); + } else if (bhfi->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH; + else { + const wchar_t *p; + + mode |= S_IFREG; + p = wcsrchr(path, L'.'); + if (p != NULL && wcslen(p) == 4) { + switch (p[1]) { + case L'B': case L'b': + if ((p[2] == L'A' || p[2] == L'a' ) && + (p[3] == L'T' || p[3] == L't' )) + mode |= S_IXUSR | S_IXGRP | S_IXOTH; + break; + case L'C': case L'c': + if (((p[2] == L'M' || p[2] == L'm' ) && + (p[3] == L'D' || p[3] == L'd' ))) + mode |= S_IXUSR | S_IXGRP | S_IXOTH; + break; + case L'E': case L'e': + if ((p[2] == L'X' || p[2] == L'x' ) && + (p[3] == L'E' || p[3] == L'e' )) + mode |= S_IXUSR | S_IXGRP | S_IXOTH; + break; + default: + break; + } + } + } + archive_entry_set_mode(entry, mode); +} + +static void +tree_archive_entry_copy_bhfi(struct archive_entry *entry, struct tree *t, + const BY_HANDLE_FILE_INFORMATION *bhfi) +{ + entry_copy_bhfi(entry, tree_current_path(t), t->findData, bhfi); +} + +static int +tree_current_file_information(struct tree *t, BY_HANDLE_FILE_INFORMATION *st, + int sim_lstat) +{ + HANDLE h; + int r; + DWORD flag = FILE_FLAG_BACKUP_SEMANTICS; + + if (sim_lstat && tree_current_is_physical_link(t)) + flag |= FILE_FLAG_OPEN_REPARSE_POINT; + h = CreateFileW(tree_current_access_path(t), 0, FILE_SHARE_READ, NULL, + OPEN_EXISTING, flag, NULL); + if (h == INVALID_HANDLE_VALUE) { + la_dosmaperr(GetLastError()); + t->tree_errno = errno; + return (0); + } + r = GetFileInformationByHandle(h, st); + CloseHandle(h); + return (r); +} + +/* + * Get the stat() data for the entry just returned from tree_next(). + */ +static const BY_HANDLE_FILE_INFORMATION * +tree_current_stat(struct tree *t) +{ + if (!(t->flags & hasStat)) { + if (!tree_current_file_information(t, &t->st, 0)) + return NULL; + t->flags |= hasStat; + } + return (&t->st); +} + +/* + * Get the lstat() data for the entry just returned from tree_next(). + */ +static const BY_HANDLE_FILE_INFORMATION * +tree_current_lstat(struct tree *t) +{ + if (!(t->flags & hasLstat)) { + if (!tree_current_file_information(t, &t->lst, 1)) + return NULL; + t->flags |= hasLstat; + } + return (&t->lst); +} + +/* + * Test whether current entry is a dir or link to a dir. + */ +static int +tree_current_is_dir(struct tree *t) +{ + if (t->findData) + return (t->findData->dwFileAttributes + & FILE_ATTRIBUTE_DIRECTORY); + return (0); +} + +/* + * Test whether current entry is a physical directory. Usually, we + * already have at least one of stat() or lstat() in memory, so we + * use tricks to try to avoid an extra trip to the disk. + */ +static int +tree_current_is_physical_dir(struct tree *t) +{ + if (tree_current_is_physical_link(t)) + return (0); + return (tree_current_is_dir(t)); +} + +/* + * Test whether current entry is a symbolic link. + */ +static int +tree_current_is_physical_link(struct tree *t) +{ + if (t->findData) + return ((t->findData->dwFileAttributes + & FILE_ATTRIBUTE_REPARSE_POINT) && + (t->findData->dwReserved0 + == IO_REPARSE_TAG_SYMLINK)); + return (0); +} + +/* + * Test whether the same file has been in the tree as its parent. + */ +static int +tree_target_is_same_as_parent(struct tree *t, + const BY_HANDLE_FILE_INFORMATION *st) +{ + struct tree_entry *te; + int64_t dev = bhfi_dev(st); + int64_t ino = bhfi_ino(st); + + for (te = t->current->parent; te != NULL; te = te->parent) { + if (te->dev == dev && te->ino == ino) + return (1); + } + return (0); +} + +/* + * Return the access path for the entry just returned from tree_next(). + */ +static const wchar_t * +tree_current_access_path(struct tree *t) +{ + return (t->full_path.s); +} + +/* + * Return the full path for the entry just returned from tree_next(). + */ +static const wchar_t * +tree_current_path(struct tree *t) +{ + return (t->path.s); +} + +/* + * Terminate the traversal. + */ +static void +tree_close(struct tree *t) +{ + + if (t == NULL) + return; + if (t->entry_fh != INVALID_HANDLE_VALUE) { + cancel_async(t); + close_and_restore_time(t->entry_fh, t, &t->restore_time); + t->entry_fh = INVALID_HANDLE_VALUE; + } + /* Close the handle of FindFirstFileW */ + if (t->d != INVALID_HANDLE_VALUE) { + FindClose(t->d); + t->d = INVALID_HANDLE_VALUE; + t->findData = NULL; + } + /* Release anything remaining in the stack. */ + while (t->stack != NULL) + tree_pop(t); +} + +/* + * Release any resources. + */ +static void +tree_free(struct tree *t) +{ + int i; + + if (t == NULL) + return; + archive_wstring_free(&t->path); + archive_wstring_free(&t->full_path); + free(t->sparse_list); + free(t->filesystem_table); + for (i = 0; i < MAX_OVERLAPPED; i++) { + if (t->ol[i].buff) + VirtualFree(t->ol[i].buff, 0, MEM_RELEASE); + CloseHandle(t->ol[i].ol.hEvent); + } + free(t); +} + + +/* + * Populate the archive_entry with metadata from the disk. + */ +int +archive_read_disk_entry_from_file(struct archive *_a, + struct archive_entry *entry, int fd, const struct stat *st) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + const wchar_t *path; + const wchar_t *wname; + const char *name; + HANDLE h; + BY_HANDLE_FILE_INFORMATION bhfi; + DWORD fileAttributes = 0; + int r; + + archive_clear_error(_a); + wname = archive_entry_sourcepath_w(entry); + if (wname == NULL) + wname = archive_entry_pathname_w(entry); + if (wname == NULL) { + archive_set_error(&a->archive, EINVAL, + "Can't get a wide character version of the path"); + return (ARCHIVE_FAILED); + } + path = __la_win_permissive_name_w(wname); + + if (st == NULL) { + /* + * Get metadata through GetFileInformationByHandle(). + */ + if (fd >= 0) { + h = (HANDLE)_get_osfhandle(fd); + r = GetFileInformationByHandle(h, &bhfi); + if (r == 0) { + la_dosmaperr(GetLastError()); + archive_set_error(&a->archive, errno, + "Can't GetFileInformationByHandle"); + return (ARCHIVE_FAILED); + } + entry_copy_bhfi(entry, path, NULL, &bhfi); + } else { + WIN32_FIND_DATAW findData; + DWORD flag, desiredAccess; + + h = FindFirstFileW(path, &findData); + if (h == INVALID_HANDLE_VALUE) { + la_dosmaperr(GetLastError()); + archive_set_error(&a->archive, errno, + "Can't FindFirstFileW"); + return (ARCHIVE_FAILED); + } + FindClose(h); + + flag = FILE_FLAG_BACKUP_SEMANTICS; + if (!a->follow_symlinks && + (findData.dwFileAttributes + & FILE_ATTRIBUTE_REPARSE_POINT) && + (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK)) { + flag |= FILE_FLAG_OPEN_REPARSE_POINT; + desiredAccess = 0; + } else if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + desiredAccess = 0; + } else + desiredAccess = GENERIC_READ; + + h = CreateFileW(path, desiredAccess, FILE_SHARE_READ, NULL, + OPEN_EXISTING, flag, NULL); + if (h == INVALID_HANDLE_VALUE) { + la_dosmaperr(GetLastError()); + archive_set_error(&a->archive, errno, + "Can't CreateFileW"); + return (ARCHIVE_FAILED); + } + r = GetFileInformationByHandle(h, &bhfi); + if (r == 0) { + la_dosmaperr(GetLastError()); + archive_set_error(&a->archive, errno, + "Can't GetFileInformationByHandle"); + CloseHandle(h); + return (ARCHIVE_FAILED); + } + entry_copy_bhfi(entry, path, &findData, &bhfi); + } + fileAttributes = bhfi.dwFileAttributes; + } else { + archive_entry_copy_stat(entry, st); + if (st->st_mode & S_IFLNK) + entry_symlink_from_pathw(entry, path); + h = INVALID_HANDLE_VALUE; + } + + /* Lookup uname/gname */ + name = archive_read_disk_uname(_a, archive_entry_uid(entry)); + if (name != NULL) + archive_entry_copy_uname(entry, name); + name = archive_read_disk_gname(_a, archive_entry_gid(entry)); + if (name != NULL) + archive_entry_copy_gname(entry, name); + + /* + * File attributes + */ + if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0) { + const int supported_attrs = + FILE_ATTRIBUTE_READONLY | + FILE_ATTRIBUTE_HIDDEN | + FILE_ATTRIBUTE_SYSTEM; + DWORD file_attrs = fileAttributes & supported_attrs; + if (file_attrs != 0) + archive_entry_set_fflags(entry, file_attrs, 0); + } + + /* + * Can this file be sparse file ? + */ + if (archive_entry_filetype(entry) != AE_IFREG + || archive_entry_size(entry) <= 0 + || archive_entry_hardlink(entry) != NULL) { + if (h != INVALID_HANDLE_VALUE && fd < 0) + CloseHandle(h); + return (ARCHIVE_OK); + } + + if (h == INVALID_HANDLE_VALUE) { + if (fd >= 0) { + h = (HANDLE)_get_osfhandle(fd); + } else { + h = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (h == INVALID_HANDLE_VALUE) { + la_dosmaperr(GetLastError()); + archive_set_error(&a->archive, errno, + "Can't CreateFileW"); + return (ARCHIVE_FAILED); + } + } + r = GetFileInformationByHandle(h, &bhfi); + if (r == 0) { + la_dosmaperr(GetLastError()); + archive_set_error(&a->archive, errno, + "Can't GetFileInformationByHandle"); + if (h != INVALID_HANDLE_VALUE && fd < 0) + CloseHandle(h); + return (ARCHIVE_FAILED); + } + fileAttributes = bhfi.dwFileAttributes; + } + + /* Sparse file must be set a mark, FILE_ATTRIBUTE_SPARSE_FILE */ + if ((fileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) == 0) { + if (fd < 0) + CloseHandle(h); + return (ARCHIVE_OK); + } + + r = setup_sparse_from_disk(a, entry, h); + if (fd < 0) + CloseHandle(h); + + return (r); +} + +/* + * Windows sparse interface. + */ +#if defined(__MINGW32__) && !defined(FSCTL_QUERY_ALLOCATED_RANGES) +#define FSCTL_QUERY_ALLOCATED_RANGES 0x940CF +typedef struct { + LARGE_INTEGER FileOffset; + LARGE_INTEGER Length; +} FILE_ALLOCATED_RANGE_BUFFER; +#endif + +static int +setup_sparse_from_disk(struct archive_read_disk *a, + struct archive_entry *entry, HANDLE handle) +{ + FILE_ALLOCATED_RANGE_BUFFER range, *outranges = NULL; + size_t outranges_size; + int64_t entry_size = archive_entry_size(entry); + int exit_sts = ARCHIVE_OK; + + range.FileOffset.QuadPart = 0; + range.Length.QuadPart = entry_size; + outranges_size = 2048; + outranges = (FILE_ALLOCATED_RANGE_BUFFER *)malloc(outranges_size); + if (outranges == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Couldn't allocate memory"); + exit_sts = ARCHIVE_FATAL; + goto exit_setup_sparse; + } + + for (;;) { + DWORD retbytes; + BOOL ret; + + for (;;) { + ret = DeviceIoControl(handle, + FSCTL_QUERY_ALLOCATED_RANGES, + &range, sizeof(range), outranges, + (DWORD)outranges_size, &retbytes, NULL); + if (ret == 0 && GetLastError() == ERROR_MORE_DATA) { + free(outranges); + outranges_size *= 2; + outranges = (FILE_ALLOCATED_RANGE_BUFFER *) + malloc(outranges_size); + if (outranges == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Couldn't allocate memory"); + exit_sts = ARCHIVE_FATAL; + goto exit_setup_sparse; + } + continue; + } else + break; + } + if (ret != 0) { + if (retbytes > 0) { + DWORD i, n; + + n = retbytes / sizeof(outranges[0]); + if (n == 1 && + outranges[0].FileOffset.QuadPart == 0 && + outranges[0].Length.QuadPart == entry_size) + break;/* This is not sparse. */ + for (i = 0; i < n; i++) + archive_entry_sparse_add_entry(entry, + outranges[i].FileOffset.QuadPart, + outranges[i].Length.QuadPart); + range.FileOffset.QuadPart = + outranges[n-1].FileOffset.QuadPart + + outranges[n-1].Length.QuadPart; + range.Length.QuadPart = + entry_size - range.FileOffset.QuadPart; + if (range.Length.QuadPart > 0) + continue; + } else { + /* The entire file is a hole. Add one data block of size 0 at the end. */ + archive_entry_sparse_add_entry(entry, + entry_size, + 0); + } + break; + } else { + la_dosmaperr(GetLastError()); + archive_set_error(&a->archive, errno, + "DeviceIoControl Failed: %lu", GetLastError()); + exit_sts = ARCHIVE_FAILED; + goto exit_setup_sparse; + } + } +exit_setup_sparse: + free(outranges); + + return (exit_sts); +} + +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_extract.3 b/dependencies/libarchive-3.4.2/libarchive/archive_read_extract.3 new file mode 100644 index 0000000..858f397 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_extract.3 @@ -0,0 +1,137 @@ +.\" Copyright (c) 2003-2011 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 2, 2012 +.Dt ARCHIVE_READ_EXTRACT 3 +.Os +.Sh NAME +.Nm archive_read_extract , +.Nm archive_read_extract2 , +.Nm archive_read_extract_set_progress_callback +.Nd functions for reading streaming archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive.h +.Ft int +.Fo archive_read_extract +.Fa "struct archive *" +.Fa "struct archive_entry *" +.Fa "int flags" +.Fc +.Ft int +.Fo archive_read_extract2 +.Fa "struct archive *src" +.Fa "struct archive_entry *" +.Fa "struct archive *dest" +.Fc +.Ft void +.Fo archive_read_extract_set_progress_callback +.Fa "struct archive *" +.Fa "void (*func)(void *)" +.Fa "void *user_data" +.Fc +.Sh DESCRIPTION +.Bl -tag -compact -width indent +.It Fn archive_read_extract , Fn archive_read_extract_set_skip_file +A convenience function that wraps the corresponding +.Xr archive_write_disk 3 +interfaces. +The first call to +.Fn archive_read_extract +creates a restore object using +.Xr archive_write_disk_new 3 +and +.Xr archive_write_disk_set_standard_lookup 3 , +then transparently invokes +.Xr archive_write_disk_set_options 3 , +.Xr archive_write_header 3 , +.Xr archive_write_data 3 , +and +.Xr archive_write_finish_entry 3 +to create the entry on disk and copy data into it. +The +.Va flags +argument is passed unmodified to +.Xr archive_write_disk_set_options 3 . +.It Fn archive_read_extract2 +This is another version of +.Fn archive_read_extract +that allows you to provide your own restore object. +In particular, this allows you to override the standard lookup functions +using +.Xr archive_write_disk_set_group_lookup 3 , +and +.Xr archive_write_disk_set_user_lookup 3 . +Note that +.Fn archive_read_extract2 +does not accept a +.Va flags +argument; you should use +.Fn archive_write_disk_set_options +to set the restore options yourself. +.It Fn archive_read_extract_set_progress_callback +Sets a pointer to a user-defined callback that can be used +for updating progress displays during extraction. +The progress function will be invoked during the extraction of large +regular files. +The progress function will be invoked with the pointer provided to this call. +Generally, the data pointed to should include a reference to the archive +object and the archive_entry object so that various statistics +can be retrieved for the progress display. +.El +.\" +.Sh RETURN VALUES +Most functions return zero on success, non-zero on error. +The possible return codes include: +.Cm ARCHIVE_OK +(the operation succeeded), +.Cm ARCHIVE_WARN +(the operation succeeded but a non-critical error was encountered), +.Cm ARCHIVE_EOF +(end-of-archive was encountered), +.Cm ARCHIVE_RETRY +(the operation failed but can be retried), +and +.Cm ARCHIVE_FATAL +(there was a fatal error; the archive should be closed immediately). +.Sh ERRORS +Detailed error codes and textual descriptions are available from the +.Fn archive_errno +and +.Fn archive_error_string +functions. +.Sh SEE ALSO +.Xr tar 1 , +.Xr archive_read 3 , +.Xr archive_read_data 3 , +.Xr archive_read_filter 3 , +.Xr archive_read_format 3 , +.Xr archive_read_open 3 , +.Xr archive_read_set_options 3 , +.Xr archive_util 3 , +.Xr libarchive 3 , +.Xr tar 5 diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_extract.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_extract.c new file mode 100644 index 0000000..b7973fa --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_extract.c @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_extract.c,v 1.61 2008/05/26 17:00:22 kientzle Exp $"); + +#ifdef HAVE_ERRNO_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_read_private.h" + +int +archive_read_extract(struct archive *_a, struct archive_entry *entry, int flags) +{ + struct archive_read_extract *extract; + struct archive_read * a = (struct archive_read *)_a; + + extract = __archive_read_get_extract(a); + if (extract == NULL) + return (ARCHIVE_FATAL); + + /* If we haven't initialized the archive_write_disk object, do it now. */ + if (extract->ad == NULL) { + extract->ad = archive_write_disk_new(); + if (extract->ad == NULL) { + archive_set_error(&a->archive, ENOMEM, "Can't extract"); + return (ARCHIVE_FATAL); + } + archive_write_disk_set_standard_lookup(extract->ad); + } + + archive_write_disk_set_options(extract->ad, flags); + return (archive_read_extract2(&a->archive, entry, extract->ad)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_extract2.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_extract2.c new file mode 100644 index 0000000..4febd8c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_extract2.c @@ -0,0 +1,155 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_extract.c,v 1.61 2008/05/26 17:00:22 kientzle Exp $"); + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_read_private.h" + +static int copy_data(struct archive *ar, struct archive *aw); +static int archive_read_extract_cleanup(struct archive_read *); + + +/* Retrieve an extract object without initialising the associated + * archive_write_disk object. + */ +struct archive_read_extract * +__archive_read_get_extract(struct archive_read *a) +{ + if (a->extract == NULL) { + a->extract = (struct archive_read_extract *)calloc(1, sizeof(*a->extract)); + if (a->extract == NULL) { + archive_set_error(&a->archive, ENOMEM, "Can't extract"); + return (NULL); + } + a->cleanup_archive_extract = archive_read_extract_cleanup; + } + return (a->extract); +} + +/* + * Cleanup function for archive_extract. + */ +static int +archive_read_extract_cleanup(struct archive_read *a) +{ + int ret = ARCHIVE_OK; + + if (a->extract->ad != NULL) { + ret = archive_write_free(a->extract->ad); + } + free(a->extract); + a->extract = NULL; + return (ret); +} + +int +archive_read_extract2(struct archive *_a, struct archive_entry *entry, + struct archive *ad) +{ + struct archive_read *a = (struct archive_read *)_a; + int r, r2; + + /* Set up for this particular entry. */ + if (a->skip_file_set) + archive_write_disk_set_skip_file(ad, + a->skip_file_dev, a->skip_file_ino); + r = archive_write_header(ad, entry); + if (r < ARCHIVE_WARN) + r = ARCHIVE_WARN; + if (r != ARCHIVE_OK) + /* If _write_header failed, copy the error. */ + archive_copy_error(&a->archive, ad); + else if (!archive_entry_size_is_set(entry) || archive_entry_size(entry) > 0) + /* Otherwise, pour data into the entry. */ + r = copy_data(_a, ad); + r2 = archive_write_finish_entry(ad); + if (r2 < ARCHIVE_WARN) + r2 = ARCHIVE_WARN; + /* Use the first message. */ + if (r2 != ARCHIVE_OK && r == ARCHIVE_OK) + archive_copy_error(&a->archive, ad); + /* Use the worst error return. */ + if (r2 < r) + r = r2; + return (r); +} + +void +archive_read_extract_set_progress_callback(struct archive *_a, + void (*progress_func)(void *), void *user_data) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_extract *extract = __archive_read_get_extract(a); + if (extract != NULL) { + extract->extract_progress = progress_func; + extract->extract_progress_user_data = user_data; + } +} + +static int +copy_data(struct archive *ar, struct archive *aw) +{ + int64_t offset; + const void *buff; + struct archive_read_extract *extract; + size_t size; + int r; + + extract = __archive_read_get_extract((struct archive_read *)ar); + if (extract == NULL) + return (ARCHIVE_FATAL); + for (;;) { + r = archive_read_data_block(ar, &buff, &size, &offset); + if (r == ARCHIVE_EOF) + return (ARCHIVE_OK); + if (r != ARCHIVE_OK) + return (r); + r = (int)archive_write_data_block(aw, buff, size, offset); + if (r < ARCHIVE_WARN) + r = ARCHIVE_WARN; + if (r < ARCHIVE_OK) { + archive_set_error(ar, archive_errno(aw), + "%s", archive_error_string(aw)); + return (r); + } + if (extract->extract_progress) + (extract->extract_progress) + (extract->extract_progress_user_data); + } +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_filter.3 b/dependencies/libarchive-3.4.2/libarchive/archive_read_filter.3 new file mode 100644 index 0000000..1ba5fcb --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_filter.3 @@ -0,0 +1,154 @@ +.\" Copyright (c) 2003-2011 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd August 14, 2014 +.Dt ARCHIVE_READ_FILTER 3 +.Os +.Sh NAME +.Nm archive_read_support_filter_all , +.Nm archive_read_support_filter_bzip2 , +.Nm archive_read_support_filter_compress , +.Nm archive_read_support_filter_gzip , +.Nm archive_read_support_filter_lz4 , +.Nm archive_read_support_filter_lzma , +.Nm archive_read_support_filter_none , +.Nm archive_read_support_filter_rpm , +.Nm archive_read_support_filter_uu , +.Nm archive_read_support_filter_xz , +.Nm archive_read_support_filter_zstd , +.Nm archive_read_support_filter_program , +.Nm archive_read_support_filter_program_signature +.Nd functions for reading streaming archives +.\" +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive.h +.Ft int +.Fn archive_read_support_filter_all "struct archive *" +.Ft int +.Fn archive_read_support_filter_bzip2 "struct archive *" +.Ft int +.Fn archive_read_support_filter_compress "struct archive *" +.Ft int +.Fn archive_read_support_filter_grzip "struct archive *" +.Ft int +.Fn archive_read_support_filter_gzip "struct archive *" +.Ft int +.Fn archive_read_support_filter_lrzip "struct archive *" +.Ft int +.Fn archive_read_support_filter_lz4 "struct archive *" +.Ft int +.Fn archive_read_support_filter_lzma "struct archive *" +.Ft int +.Fn archive_read_support_filter_lzop "struct archive *" +.Ft int +.Fn archive_read_support_filter_none "struct archive *" +.Ft int +.Fn archive_read_support_filter_rpm "struct archive *" +.Ft int +.Fn archive_read_support_filter_uu "struct archive *" +.Ft int +.Fn archive_read_support_filter_xz "struct archive *" +.Ft int +.Fn archive_read_support_filter_zstd "struct archive *" +.Ft int +.Fo archive_read_support_filter_program +.Fa "struct archive *" +.Fa "const char *cmd" +.Fc +.Ft int +.Fo archive_read_support_filter_program_signature +.Fa "struct archive *" +.Fa "const char *cmd" +.Fa "const void *signature" +.Fa "size_t signature_length" +.Fc +.\" +.Sh DESCRIPTION +.Bl -tag -compact -width indent +.It Xo +.Fn archive_read_support_filter_bzip2 , +.Fn archive_read_support_filter_compress , +.Fn archive_read_support_filter_grzip , +.Fn archive_read_support_filter_gzip , +.Fn archive_read_support_filter_lrzip , +.Fn archive_read_support_filter_lz4 , +.Fn archive_read_support_filter_lzma , +.Fn archive_read_support_filter_lzop , +.Fn archive_read_support_filter_none , +.Fn archive_read_support_filter_rpm , +.Fn archive_read_support_filter_uu , +.Fn archive_read_support_filter_xz , +.Fn archive_read_support_filter_zstd , +.Xc +Enables auto-detection code and decompression support for the +specified compression. +These functions may fall back on external programs if an appropriate +library was not available at build time. +Decompression using an external program is usually slower than +decompression through built-in libraries. +Note that +.Dq none +is always enabled by default. +.It Fn archive_read_support_filter_all +Enables all available decompression filters. +.It Fn archive_read_support_filter_program +Data is fed through the specified external program before being dearchived. +Note that this disables automatic detection of the compression format, +so it makes no sense to specify this in conjunction with any other +decompression option. +.It Fn archive_read_support_filter_program_signature +This feeds data through the specified external program +but only if the initial bytes of the data match the specified +signature value. +.El +.\" +.\". Sh EXAMPLE +.\" +.Sh RETURN VALUES +These functions return +.Cm ARCHIVE_OK +if the compression is fully supported, +.Cm ARCHIVE_WARN +if the compression is supported only through an external program. +.Pp +.Fn archive_read_support_filter_none +always succeeds. +.\" +.Sh ERRORS +Detailed error codes and textual descriptions are available from the +.Fn archive_errno +and +.Fn archive_error_string +functions. +.\" +.Sh SEE ALSO +.Xr archive_read 3 , +.Xr archive_read_data 3 , +.Xr archive_read_format 3 , +.Xr archive_read_format 3 , +.Xr libarchive 3 diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_format.3 b/dependencies/libarchive-3.4.2/libarchive/archive_read_format.3 new file mode 100644 index 0000000..f3804ce --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_format.3 @@ -0,0 +1,177 @@ +.\" Copyright (c) 2003-2011 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 2, 2012 +.Dt ARCHIVE_READ_FORMAT 3 +.Os +.Sh NAME +.Nm archive_read_support_format_7zip , +.Nm archive_read_support_format_all , +.Nm archive_read_support_format_ar , +.Nm archive_read_support_format_by_code , +.Nm archive_read_support_format_cab , +.Nm archive_read_support_format_cpio , +.Nm archive_read_support_format_empty , +.Nm archive_read_support_format_iso9660 , +.Nm archive_read_support_format_lha , +.Nm archive_read_support_format_mtree , +.Nm archive_read_support_format_rar , +.Nm archive_read_support_format_raw , +.Nm archive_read_support_format_tar , +.Nm archive_read_support_format_xar , +.Nm archive_read_support_format_zip +.Nd functions for reading streaming archives +.\" +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive.h +.Ft int +.Fn archive_read_support_format_7zip "struct archive *" +.Ft int +.Fn archive_read_support_format_all "struct archive *" +.Ft int +.Fn archive_read_support_format_ar "struct archive *" +.Ft int +.Fn archive_read_support_format_by_code "struct archive *" "int" +.Ft int +.Fn archive_read_support_format_cab "struct archive *" +.Ft int +.Fn archive_read_support_format_cpio "struct archive *" +.Ft int +.Fn archive_read_support_format_empty "struct archive *" +.Ft int +.Fn archive_read_support_format_iso9660 "struct archive *" +.Ft int +.Fn archive_read_support_format_lha "struct archive *" +.Ft int +.Fn archive_read_support_format_mtree "struct archive *" +.Ft int +.Fn archive_read_support_format_rar "struct archive *" +.Ft int +.Fn archive_read_support_format_raw "struct archive *" +.Ft int +.Fn archive_read_support_format_tar "struct archive *" +.Ft int +.Fn archive_read_support_format_xar "struct archive *" +.Ft int +.Fn archive_read_support_format_zip "struct archive *" +.\" +.Sh DESCRIPTION +.Bl -tag -compact -width indent +.It Xo +.Fn archive_read_support_format_7zip , +.Fn archive_read_support_format_ar , +.Fn archive_read_support_format_cab , +.Fn archive_read_support_format_cpio , +.Fn archive_read_support_format_iso9660 , +.Fn archive_read_support_format_lha , +.Fn archive_read_support_format_mtree , +.Fn archive_read_support_format_rar , +.Fn archive_read_support_format_raw , +.Fn archive_read_support_format_tar , +.Fn archive_read_support_format_xar , +.Fn archive_read_support_format_zip +.Xc +Enables support---including auto-detection code---for the +specified archive format. +For example, +.Fn archive_read_support_format_tar +enables support for a variety of standard tar formats, old-style tar, +ustar, pax interchange format, and many common variants. +.It Fn archive_read_support_format_all +Enables support for all available formats except the +.Dq raw +format (see below). +.It Fn archive_read_support_format_by_code +Enables a single format specified by the format code. +This can be useful when reading a single archive twice; +use +.Fn archive_format +after reading the first time and pass the resulting code +to this function to selectively enable only the necessary +format support. +Note: In statically-linked executables, this will cause +your program to include support for every format. +If executable size is a concern, you may wish to avoid +using this function. +.It Fn archive_read_support_format_empty +Enables support for treating empty files as empty archives. +Because empty files are valid for several different formats, +it is not possible to accurately determine a format for +an empty file based purely on contents. +So empty files are treated by libarchive as a distinct +format. +.It Fn archive_read_support_format_raw +The +.Dq raw +format handler allows libarchive to be used to read arbitrary data. +It treats any data stream as an archive with a single entry. +The pathname of this entry is +.Dq data ; +all other entry fields are unset. +This is not enabled by +.Fn archive_read_support_format_all +in order to avoid erroneous handling of damaged archives. +.El +.\" .Sh EXAMPLE +.Sh RETURN VALUES +These functions return +.Cm ARCHIVE_OK +on success, or +.Cm ARCHIVE_FATAL . +.\" +.Sh ERRORS +Detailed error codes and textual descriptions are available from the +.Fn archive_errno +and +.Fn archive_error_string +functions. +.\" +.Sh SEE ALSO +.Xr tar 1 , +.Xr archive_read_data 3 , +.Xr archive_read_filter 3 , +.Xr archive_read_set_options 3 , +.Xr archive_util 3 , +.Xr libarchive 3 , +.Xr tar 5 +.Sh BUGS +Many traditional archiver programs treat +empty files as valid empty archives. +For example, many implementations of +.Xr tar 1 +allow you to append entries to an empty file. +Of course, it is impossible to determine the format of an empty file +by inspecting the contents, so this library treats empty files as +having a special +.Dq empty +format. +.Pp +Using the +.Dq raw +handler together with any other handler will often work +but can produce surprising results. diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_free.3 b/dependencies/libarchive-3.4.2/libarchive/archive_read_free.3 new file mode 100644 index 0000000..8371c3a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_free.3 @@ -0,0 +1,93 @@ +.\" Copyright (c) 2003-2011 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 2, 2012 +.Dt ARCHIVE_READ_FREE 3 +.Os +.Sh NAME +.Nm archive_read_close , +.Nm archive_read_finish , +.Nm archive_read_free +.Nd functions for reading streaming archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive.h +.Ft int +.Fn archive_read_close "struct archive *" +.Ft int +.Fn archive_read_finish "struct archive *" +.Ft int +.Fn archive_read_free "struct archive *" +.\" +.Sh DESCRIPTION +.Bl -tag -compact -width indent +.It Fn archive_read_close +Complete the archive and invoke the close callback. +.It Fn archive_read_finish +This is a deprecated synonym for +.Fn archive_read_free . +The new name was introduced with libarchive 3.0. +Applications that need to compile with either libarchive 2 +or libarchive 3 should continue to use the +.Fn archive_read_finish +name. +Both names will be supported until libarchive 4.0 is +released, which is not expected to occur earlier +than 2013. +.It Fn archive_read_free +Invokes +.Fn archive_read_close +if it was not invoked manually, then release all resources. +Note: In libarchive 1.x, this function was declared to return +.Ft void , +which made it impossible to detect certain errors when +.Fn archive_read_close +was invoked implicitly from this function. +The declaration is corrected beginning with libarchive 2.0. +.El +.Sh RETURN VALUES +These functions return +.Cm ARCHIVE_OK +on success, or +.Cm ARCHIVE_FATAL . +.\" +.Sh ERRORS +Detailed error codes and textual descriptions are available from the +.Fn archive_errno +and +.Fn archive_error_string +functions. +.\" +.Sh SEE ALSO +.Xr archive_read_data 3 , +.Xr archive_read_filter 3 , +.Xr archive_read_format 3 , +.Xr archive_read_new 3 , +.Xr archive_read_open 3 , +.Xr archive_read_set_options 3 , +.Xr archive_util 3 , +.Xr libarchive 3 diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_header.3 b/dependencies/libarchive-3.4.2/libarchive/archive_read_header.3 new file mode 100644 index 0000000..1e97f3a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_header.3 @@ -0,0 +1,91 @@ +.\" Copyright (c) 2003-2011 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 2, 2012 +.Dt ARCHIVE_READ_HEADER 3 +.Os +.Sh NAME +.Nm archive_read_next_header , +.Nm archive_read_next_header2 +.Nd functions for reading streaming archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive.h +.Ft int +.Fn archive_read_next_header "struct archive *" "struct archive_entry **" +.Ft int +.Fn archive_read_next_header2 "struct archive *" "struct archive_entry *" +.\" +.Sh DESCRIPTION +.Bl -tag -compact -width indent +.It Fn archive_read_next_header +Read the header for the next entry and return a pointer to +a +.Tn struct archive_entry . +This is a convenience wrapper around +.Fn archive_read_next_header2 +that reuses an internal +.Tn struct archive_entry +object for each request. +.It Fn archive_read_next_header2 +Read the header for the next entry and populate the provided +.Tn struct archive_entry . +.El +.\" +.Sh RETURN VALUES +These functions return +.Cm ARCHIVE_OK +(the operation succeeded), +.Cm ARCHIVE_WARN +(the operation succeeded but a non-critical error was encountered), +.Cm ARCHIVE_EOF +(end-of-archive was encountered), +.Cm ARCHIVE_RETRY +(the operation failed but can be retried), +and +.Cm ARCHIVE_FATAL +(there was a fatal error; the archive should be closed immediately). +.\" +.Sh ERRORS +Detailed error codes and textual descriptions are available from the +.Fn archive_errno +and +.Fn archive_error_string +functions. +.\" +.Sh SEE ALSO +.Xr tar 1 , +.Xr archive_read 3 , +.Xr archive_read_data 3 , +.Xr archive_read_extract 3 , +.Xr archive_read_filter 3 , +.Xr archive_read_format 3 , +.Xr archive_read_open 3 , +.Xr archive_read_set_options 3 , +.Xr archive_util 3 , +.Xr libarchive 3 , +.Xr tar 5 diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_new.3 b/dependencies/libarchive-3.4.2/libarchive/archive_read_new.3 new file mode 100644 index 0000000..8bb6b84 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_new.3 @@ -0,0 +1,59 @@ +.\" Copyright (c) 2003-2011 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 2, 2012 +.Dt ARCHIVE_READ_NEW 3 +.Os +.Sh NAME +.Nm archive_read_new +.Nd functions for reading streaming archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive.h +.Ft struct archive * +.Fn archive_read_new "void" +.Sh DESCRIPTION +Allocates and initializes a +.Tn struct archive +object suitable for reading from an archive. +.Dv NULL +is returned on error. +.Pp +A complete description of the +.Tn struct archive +object can be found in the overview manual page for +.Xr libarchive 3 . +.\" .Sh ERRORS +.Sh SEE ALSO +.Xr tar 1 , +.Xr archive_read_data 3 , +.Xr archive_read_filter 3 , +.Xr archive_read_format 3 , +.Xr archive_read_set_options 3 , +.Xr archive_util 3 , +.Xr libarchive 3 , +.Xr tar 5 diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_open.3 b/dependencies/libarchive-3.4.2/libarchive/archive_read_open.3 new file mode 100644 index 0000000..f676778 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_open.3 @@ -0,0 +1,233 @@ +.\" Copyright (c) 2003-2011 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 2, 2012 +.Dt ARCHIVE_READ_OPEN 3 +.Os +.Sh NAME +.Nm archive_read_open , +.Nm archive_read_open2 , +.Nm archive_read_open_fd , +.Nm archive_read_open_FILE , +.Nm archive_read_open_filename , +.Nm archive_read_open_memory +.Nd functions for reading streaming archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive.h +.Ft int +.Fo archive_read_open +.Fa "struct archive *" +.Fa "void *client_data" +.Fa "archive_open_callback *" +.Fa "archive_read_callback *" +.Fa "archive_close_callback *" +.Fc +.Ft int +.Fo archive_read_open2 +.Fa "struct archive *" +.Fa "void *client_data" +.Fa "archive_open_callback *" +.Fa "archive_read_callback *" +.Fa "archive_skip_callback *" +.Fa "archive_close_callback *" +.Fc +.Ft int +.Fn archive_read_open_FILE "struct archive *" "FILE *file" +.Ft int +.Fn archive_read_open_fd "struct archive *" "int fd" "size_t block_size" +.Ft int +.Fo archive_read_open_filename +.Fa "struct archive *" +.Fa "const char *filename" +.Fa "size_t block_size" +.Fc +.Ft int +.Fn archive_read_open_memory "struct archive *" "const void *buff" "size_t size" +.Sh DESCRIPTION +.Bl -tag -compact -width indent +.It Fn archive_read_open +The same as +.Fn archive_read_open2 , +except that the skip callback is assumed to be +.Dv NULL . +.It Fn archive_read_open2 +Freeze the settings, open the archive, and prepare for reading entries. +This is the most generic version of this call, which accepts +four callback functions. +Most clients will want to use +.Fn archive_read_open_filename , +.Fn archive_read_open_FILE , +.Fn archive_read_open_fd , +or +.Fn archive_read_open_memory +instead. +The library invokes the client-provided functions to obtain +raw bytes from the archive. +.It Fn archive_read_open_FILE +Like +.Fn archive_read_open , +except that it accepts a +.Ft "FILE *" +pointer. +This function should not be used with tape drives or other devices +that require strict I/O blocking. +.It Fn archive_read_open_fd +Like +.Fn archive_read_open , +except that it accepts a file descriptor and block size rather than +a set of function pointers. +Note that the file descriptor will not be automatically closed at +end-of-archive. +This function is safe for use with tape drives or other blocked devices. +.It Fn archive_read_open_file +This is a deprecated synonym for +.Fn archive_read_open_filename . +.It Fn archive_read_open_filename +Like +.Fn archive_read_open , +except that it accepts a simple filename and a block size. +A NULL filename represents standard input. +This function is safe for use with tape drives or other blocked devices. +.It Fn archive_read_open_memory +Like +.Fn archive_read_open , +except that it accepts a pointer and size of a block of +memory containing the archive data. +.El +.Pp +A complete description of the +.Tn struct archive +and +.Tn struct archive_entry +objects can be found in the overview manual page for +.Xr libarchive 3 . +.Sh CLIENT CALLBACKS +The callback functions must match the following prototypes: +.Bl -item -offset indent +.It +.Ft typedef la_ssize_t +.Fo archive_read_callback +.Fa "struct archive *" +.Fa "void *client_data" +.Fa "const void **buffer" +.Fc +.It +.Ft typedef la_int64_t +.Fo archive_skip_callback +.Fa "struct archive *" +.Fa "void *client_data" +.Fa "off_t request" +.Fc +.It +.Ft typedef int +.Fn archive_open_callback "struct archive *" "void *client_data" +.It +.Ft typedef int +.Fn archive_close_callback "struct archive *" "void *client_data" +.El +.Pp +The open callback is invoked by +.Fn archive_open . +It should return +.Cm ARCHIVE_OK +if the underlying file or data source is successfully +opened. +If the open fails, it should call +.Fn archive_set_error +to register an error code and message and return +.Cm ARCHIVE_FATAL . +.Pp +The read callback is invoked whenever the library +requires raw bytes from the archive. +The read callback should read data into a buffer, +set the +.Li const void **buffer +argument to point to the available data, and +return a count of the number of bytes available. +The library will invoke the read callback again +only after it has consumed this data. +The library imposes no constraints on the size +of the data blocks returned. +On end-of-file, the read callback should +return zero. +On error, the read callback should invoke +.Fn archive_set_error +to register an error code and message and +return -1. +.Pp +The skip callback is invoked when the +library wants to ignore a block of data. +The return value is the number of bytes actually +skipped, which may differ from the request. +If the callback cannot skip data, it should return +zero. +If the skip callback is not provided (the +function pointer is +.Dv NULL ), +the library will invoke the read function +instead and simply discard the result. +A skip callback can provide significant +performance gains when reading uncompressed +archives from slow disk drives or other media +that can skip quickly. +.Pp +The close callback is invoked by archive_close when +the archive processing is complete. +The callback should return +.Cm ARCHIVE_OK +on success. +On failure, the callback should invoke +.Fn archive_set_error +to register an error code and message and +return +.Cm ARCHIVE_FATAL . +.\" .Sh EXAMPLE +.\" +.Sh RETURN VALUES +These functions return +.Cm ARCHIVE_OK +on success, or +.Cm ARCHIVE_FATAL . +.\" +.Sh ERRORS +Detailed error codes and textual descriptions are available from the +.Fn archive_errno +and +.Fn archive_error_string +functions. +.\" +.Sh SEE ALSO +.Xr tar 1 , +.Xr archive_read 3 , +.Xr archive_read_data 3 , +.Xr archive_read_filter 3 , +.Xr archive_read_format 3 , +.Xr archive_read_set_options 3 , +.Xr archive_util 3 , +.Xr libarchive 3 , +.Xr tar 5 diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_open_fd.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_open_fd.c new file mode 100644 index 0000000..f59cd07 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_open_fd.c @@ -0,0 +1,211 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_open_fd.c 201103 2009-12-28 03:13:49Z kientzle $"); + +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_IO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "archive.h" + +struct read_fd_data { + int fd; + size_t block_size; + char use_lseek; + void *buffer; +}; + +static int file_close(struct archive *, void *); +static ssize_t file_read(struct archive *, void *, const void **buff); +static int64_t file_seek(struct archive *, void *, int64_t request, int); +static int64_t file_skip(struct archive *, void *, int64_t request); + +int +archive_read_open_fd(struct archive *a, int fd, size_t block_size) +{ + struct stat st; + struct read_fd_data *mine; + void *b; + + archive_clear_error(a); + if (fstat(fd, &st) != 0) { + archive_set_error(a, errno, "Can't stat fd %d", fd); + return (ARCHIVE_FATAL); + } + + mine = (struct read_fd_data *)calloc(1, sizeof(*mine)); + b = malloc(block_size); + if (mine == NULL || b == NULL) { + archive_set_error(a, ENOMEM, "No memory"); + free(mine); + free(b); + return (ARCHIVE_FATAL); + } + mine->block_size = block_size; + mine->buffer = b; + mine->fd = fd; + /* + * Skip support is a performance optimization for anything + * that supports lseek(). On FreeBSD, only regular files and + * raw disk devices support lseek() and there's no portable + * way to determine if a device is a raw disk device, so we + * only enable this optimization for regular files. + */ + if (S_ISREG(st.st_mode)) { + archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino); + mine->use_lseek = 1; + } +#if defined(__CYGWIN__) || defined(_WIN32) + setmode(mine->fd, O_BINARY); +#endif + + archive_read_set_read_callback(a, file_read); + archive_read_set_skip_callback(a, file_skip); + archive_read_set_seek_callback(a, file_seek); + archive_read_set_close_callback(a, file_close); + archive_read_set_callback_data(a, mine); + return (archive_read_open1(a)); +} + +static ssize_t +file_read(struct archive *a, void *client_data, const void **buff) +{ + struct read_fd_data *mine = (struct read_fd_data *)client_data; + ssize_t bytes_read; + + *buff = mine->buffer; + for (;;) { + bytes_read = read(mine->fd, mine->buffer, mine->block_size); + if (bytes_read < 0) { + if (errno == EINTR) + continue; + archive_set_error(a, errno, "Error reading fd %d", + mine->fd); + } + return (bytes_read); + } +} + +static int64_t +file_skip(struct archive *a, void *client_data, int64_t request) +{ + struct read_fd_data *mine = (struct read_fd_data *)client_data; + int64_t skip = request; + int64_t old_offset, new_offset; + int skip_bits = sizeof(skip) * 8 - 1; /* off_t is a signed type. */ + + if (!mine->use_lseek) + return (0); + + /* Reduce a request that would overflow the 'skip' variable. */ + if (sizeof(request) > sizeof(skip)) { + int64_t max_skip = + (((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1; + if (request > max_skip) + skip = max_skip; + } + + /* Reduce request to the next smallest multiple of block_size */ + request = (request / mine->block_size) * mine->block_size; + if (request == 0) + return (0); + + if (((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0) && + ((new_offset = lseek(mine->fd, skip, SEEK_CUR)) >= 0)) + return (new_offset - old_offset); + + /* If seek failed once, it will probably fail again. */ + mine->use_lseek = 0; + + /* Let libarchive recover with read+discard. */ + if (errno == ESPIPE) + return (0); + + /* + * There's been an error other than ESPIPE. This is most + * likely caused by a programmer error (too large request) + * or a corrupted archive file. + */ + archive_set_error(a, errno, "Error seeking"); + return (-1); +} + +/* + * TODO: Store the offset and use it in the read callback. + */ +static int64_t +file_seek(struct archive *a, void *client_data, int64_t request, int whence) +{ + struct read_fd_data *mine = (struct read_fd_data *)client_data; + int64_t r; + + /* We use off_t here because lseek() is declared that way. */ + /* See above for notes about when off_t is less than 64 bits. */ + r = lseek(mine->fd, request, whence); + if (r >= 0) + return r; + + if (errno == ESPIPE) { + archive_set_error(a, errno, + "A file descriptor(%d) is not seekable(PIPE)", mine->fd); + return (ARCHIVE_FAILED); + } else { + /* If the input is corrupted or truncated, fail. */ + archive_set_error(a, errno, + "Error seeking in a file descriptor(%d)", mine->fd); + return (ARCHIVE_FATAL); + } +} + +static int +file_close(struct archive *a, void *client_data) +{ + struct read_fd_data *mine = (struct read_fd_data *)client_data; + + (void)a; /* UNUSED */ + free(mine->buffer); + free(mine); + return (ARCHIVE_OK); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_open_file.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_open_file.c new file mode 100644 index 0000000..101dae6 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_open_file.c @@ -0,0 +1,180 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_open_file.c 201093 2009-12-28 02:28:44Z kientzle $"); + +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_IO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "archive.h" + +struct read_FILE_data { + FILE *f; + size_t block_size; + void *buffer; + char can_skip; +}; + +static int file_close(struct archive *, void *); +static ssize_t file_read(struct archive *, void *, const void **buff); +static int64_t file_skip(struct archive *, void *, int64_t request); + +int +archive_read_open_FILE(struct archive *a, FILE *f) +{ + struct stat st; + struct read_FILE_data *mine; + size_t block_size = 128 * 1024; + void *b; + + archive_clear_error(a); + mine = (struct read_FILE_data *)malloc(sizeof(*mine)); + b = malloc(block_size); + if (mine == NULL || b == NULL) { + archive_set_error(a, ENOMEM, "No memory"); + free(mine); + free(b); + return (ARCHIVE_FATAL); + } + mine->block_size = block_size; + mine->buffer = b; + mine->f = f; + /* + * If we can't fstat() the file, it may just be that it's not + * a file. (On some platforms, FILE * objects can wrap I/O + * streams that don't support fileno()). As a result, fileno() + * should be used cautiously.) + */ + if (fstat(fileno(mine->f), &st) == 0 && S_ISREG(st.st_mode)) { + archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino); + /* Enable the seek optimization only for regular files. */ + mine->can_skip = 1; + } else + mine->can_skip = 0; + +#if defined(__CYGWIN__) || defined(_WIN32) + setmode(fileno(mine->f), O_BINARY); +#endif + + archive_read_set_read_callback(a, file_read); + archive_read_set_skip_callback(a, file_skip); + archive_read_set_close_callback(a, file_close); + archive_read_set_callback_data(a, mine); + return (archive_read_open1(a)); +} + +static ssize_t +file_read(struct archive *a, void *client_data, const void **buff) +{ + struct read_FILE_data *mine = (struct read_FILE_data *)client_data; + size_t bytes_read; + + *buff = mine->buffer; + bytes_read = fread(mine->buffer, 1, mine->block_size, mine->f); + if (bytes_read < mine->block_size && ferror(mine->f)) { + archive_set_error(a, errno, "Error reading file"); + } + return (bytes_read); +} + +static int64_t +file_skip(struct archive *a, void *client_data, int64_t request) +{ + struct read_FILE_data *mine = (struct read_FILE_data *)client_data; +#if HAVE_FSEEKO + off_t skip = (off_t)request; +#elif HAVE__FSEEKI64 + int64_t skip = request; +#else + long skip = (long)request; +#endif + int skip_bits = sizeof(skip) * 8 - 1; + + (void)a; /* UNUSED */ + + /* + * If we can't skip, return 0 as the amount we did step and + * the caller will work around by reading and discarding. + */ + if (!mine->can_skip) + return (0); + if (request == 0) + return (0); + + /* If request is too big for a long or an off_t, reduce it. */ + if (sizeof(request) > sizeof(skip)) { + int64_t max_skip = + (((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1; + if (request > max_skip) + skip = max_skip; + } + +#ifdef __ANDROID__ + /* fileno() isn't safe on all platforms ... see above. */ + if (lseek(fileno(mine->f), skip, SEEK_CUR) < 0) +#elif HAVE_FSEEKO + if (fseeko(mine->f, skip, SEEK_CUR) != 0) +#elif HAVE__FSEEKI64 + if (_fseeki64(mine->f, skip, SEEK_CUR) != 0) +#else + if (fseek(mine->f, skip, SEEK_CUR) != 0) +#endif + { + mine->can_skip = 0; + return (0); + } + return (request); +} + +static int +file_close(struct archive *a, void *client_data) +{ + struct read_FILE_data *mine = (struct read_FILE_data *)client_data; + + (void)a; /* UNUSED */ + free(mine->buffer); + free(mine); + return (ARCHIVE_OK); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_open_filename.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_open_filename.c new file mode 100644 index 0000000..86635e2 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_open_filename.c @@ -0,0 +1,582 @@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_open_filename.c 201093 2009-12-28 02:28:44Z kientzle $"); + +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_IO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#include +#elif defined(__NetBSD__) || defined(__OpenBSD__) +#include +#include +#elif defined(__DragonFly__) +#include +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_string.h" + +#ifndef O_BINARY +#define O_BINARY 0 +#endif +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + +struct read_file_data { + int fd; + size_t block_size; + void *buffer; + mode_t st_mode; /* Mode bits for opened file. */ + char use_lseek; + enum fnt_e { FNT_STDIN, FNT_MBS, FNT_WCS } filename_type; + union { + char m[1];/* MBS filename. */ + wchar_t w[1];/* WCS filename. */ + } filename; /* Must be last! */ +}; + +static int file_open(struct archive *, void *); +static int file_close(struct archive *, void *); +static int file_close2(struct archive *, void *); +static int file_switch(struct archive *, void *, void *); +static ssize_t file_read(struct archive *, void *, const void **buff); +static int64_t file_seek(struct archive *, void *, int64_t request, int); +static int64_t file_skip(struct archive *, void *, int64_t request); +static int64_t file_skip_lseek(struct archive *, void *, int64_t request); + +int +archive_read_open_file(struct archive *a, const char *filename, + size_t block_size) +{ + return (archive_read_open_filename(a, filename, block_size)); +} + +int +archive_read_open_filename(struct archive *a, const char *filename, + size_t block_size) +{ + const char *filenames[2]; + filenames[0] = filename; + filenames[1] = NULL; + return archive_read_open_filenames(a, filenames, block_size); +} + +int +archive_read_open_filenames(struct archive *a, const char **filenames, + size_t block_size) +{ + struct read_file_data *mine; + const char *filename = NULL; + if (filenames) + filename = *(filenames++); + + archive_clear_error(a); + do + { + if (filename == NULL) + filename = ""; + mine = (struct read_file_data *)calloc(1, + sizeof(*mine) + strlen(filename)); + if (mine == NULL) + goto no_memory; + strcpy(mine->filename.m, filename); + mine->block_size = block_size; + mine->fd = -1; + mine->buffer = NULL; + mine->st_mode = mine->use_lseek = 0; + if (filename == NULL || filename[0] == '\0') { + mine->filename_type = FNT_STDIN; + } else + mine->filename_type = FNT_MBS; + if (archive_read_append_callback_data(a, mine) != (ARCHIVE_OK)) + return (ARCHIVE_FATAL); + if (filenames == NULL) + break; + filename = *(filenames++); + } while (filename != NULL && filename[0] != '\0'); + archive_read_set_open_callback(a, file_open); + archive_read_set_read_callback(a, file_read); + archive_read_set_skip_callback(a, file_skip); + archive_read_set_close_callback(a, file_close); + archive_read_set_switch_callback(a, file_switch); + archive_read_set_seek_callback(a, file_seek); + + return (archive_read_open1(a)); +no_memory: + archive_set_error(a, ENOMEM, "No memory"); + return (ARCHIVE_FATAL); +} + +int +archive_read_open_filename_w(struct archive *a, const wchar_t *wfilename, + size_t block_size) +{ + struct read_file_data *mine = (struct read_file_data *)calloc(1, + sizeof(*mine) + wcslen(wfilename) * sizeof(wchar_t)); + if (!mine) + { + archive_set_error(a, ENOMEM, "No memory"); + return (ARCHIVE_FATAL); + } + mine->fd = -1; + mine->block_size = block_size; + + if (wfilename == NULL || wfilename[0] == L'\0') { + mine->filename_type = FNT_STDIN; + } else { +#if defined(_WIN32) && !defined(__CYGWIN__) + mine->filename_type = FNT_WCS; + wcscpy(mine->filename.w, wfilename); +#else + /* + * POSIX system does not support a wchar_t interface for + * open() system call, so we have to translate a wchar_t + * filename to multi-byte one and use it. + */ + struct archive_string fn; + + archive_string_init(&fn); + if (archive_string_append_from_wcs(&fn, wfilename, + wcslen(wfilename)) != 0) { + if (errno == ENOMEM) + archive_set_error(a, errno, + "Can't allocate memory"); + else + archive_set_error(a, EINVAL, + "Failed to convert a wide-character" + " filename to a multi-byte filename"); + archive_string_free(&fn); + free(mine); + return (ARCHIVE_FATAL); + } + mine->filename_type = FNT_MBS; + strcpy(mine->filename.m, fn.s); + archive_string_free(&fn); +#endif + } + if (archive_read_append_callback_data(a, mine) != (ARCHIVE_OK)) + return (ARCHIVE_FATAL); + archive_read_set_open_callback(a, file_open); + archive_read_set_read_callback(a, file_read); + archive_read_set_skip_callback(a, file_skip); + archive_read_set_close_callback(a, file_close); + archive_read_set_switch_callback(a, file_switch); + archive_read_set_seek_callback(a, file_seek); + + return (archive_read_open1(a)); +} + +static int +file_open(struct archive *a, void *client_data) +{ + struct stat st; + struct read_file_data *mine = (struct read_file_data *)client_data; + void *buffer; + const char *filename = NULL; + const wchar_t *wfilename = NULL; + int fd = -1; + int is_disk_like = 0; +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + off_t mediasize = 0; /* FreeBSD-specific, so off_t okay here. */ +#elif defined(__NetBSD__) || defined(__OpenBSD__) + struct disklabel dl; +#elif defined(__DragonFly__) + struct partinfo pi; +#endif + + archive_clear_error(a); + if (mine->filename_type == FNT_STDIN) { + /* We used to delegate stdin support by + * directly calling archive_read_open_fd(a,0,block_size) + * here, but that doesn't (and shouldn't) handle the + * end-of-file flush when reading stdout from a pipe. + * Basically, read_open_fd() is intended for folks who + * are willing to handle such details themselves. This + * API is intended to be a little smarter for folks who + * want easy handling of the common case. + */ + fd = 0; +#if defined(__CYGWIN__) || defined(_WIN32) + setmode(0, O_BINARY); +#endif + filename = ""; + } else if (mine->filename_type == FNT_MBS) { + filename = mine->filename.m; + fd = open(filename, O_RDONLY | O_BINARY | O_CLOEXEC); + __archive_ensure_cloexec_flag(fd); + if (fd < 0) { + archive_set_error(a, errno, + "Failed to open '%s'", filename); + return (ARCHIVE_FATAL); + } + } else { +#if defined(_WIN32) && !defined(__CYGWIN__) + wfilename = mine->filename.w; + fd = _wopen(wfilename, O_RDONLY | O_BINARY); + if (fd < 0 && errno == ENOENT) { + wchar_t *fullpath; + fullpath = __la_win_permissive_name_w(wfilename); + if (fullpath != NULL) { + fd = _wopen(fullpath, O_RDONLY | O_BINARY); + free(fullpath); + } + } + if (fd < 0) { + archive_set_error(a, errno, + "Failed to open '%S'", wfilename); + return (ARCHIVE_FATAL); + } +#else + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unexpedted operation in archive_read_open_filename"); + goto fail; +#endif + } + if (fstat(fd, &st) != 0) { + if (mine->filename_type == FNT_WCS) + archive_set_error(a, errno, "Can't stat '%S'", + wfilename); + else + archive_set_error(a, errno, "Can't stat '%s'", + filename); + goto fail; + } + + /* + * Determine whether the input looks like a disk device or a + * tape device. The results are used below to select an I/O + * strategy: + * = "disk-like" devices support arbitrary lseek() and will + * support I/O requests of any size. So we get easy skipping + * and can cheat on block sizes to get better performance. + * = "tape-like" devices require strict blocking and use + * specialized ioctls for seeking. + * = "socket-like" devices cannot seek at all but can improve + * performance by using nonblocking I/O to read "whatever is + * available right now". + * + * Right now, we only specially recognize disk-like devices, + * but it should be straightforward to add probes and strategy + * here for tape-like and socket-like devices. + */ + if (S_ISREG(st.st_mode)) { + /* Safety: Tell the extractor not to overwrite the input. */ + archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino); + /* Regular files act like disks. */ + is_disk_like = 1; + } +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + /* FreeBSD: if it supports DIOCGMEDIASIZE ioctl, it's disk-like. */ + else if (S_ISCHR(st.st_mode) && + ioctl(fd, DIOCGMEDIASIZE, &mediasize) == 0 && + mediasize > 0) { + is_disk_like = 1; + } +#elif defined(__NetBSD__) || defined(__OpenBSD__) + /* Net/OpenBSD: if it supports DIOCGDINFO ioctl, it's disk-like. */ + else if ((S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) && + ioctl(fd, DIOCGDINFO, &dl) == 0 && + dl.d_partitions[DISKPART(st.st_rdev)].p_size > 0) { + is_disk_like = 1; + } +#elif defined(__DragonFly__) + /* DragonFly BSD: if it supports DIOCGPART ioctl, it's disk-like. */ + else if (S_ISCHR(st.st_mode) && + ioctl(fd, DIOCGPART, &pi) == 0 && + pi.media_size > 0) { + is_disk_like = 1; + } +#elif defined(__linux__) + /* Linux: All block devices are disk-like. */ + else if (S_ISBLK(st.st_mode) && + lseek(fd, 0, SEEK_CUR) == 0 && + lseek(fd, 0, SEEK_SET) == 0 && + lseek(fd, 0, SEEK_END) > 0 && + lseek(fd, 0, SEEK_SET) == 0) { + is_disk_like = 1; + } +#endif + /* TODO: Add an "is_tape_like" variable and appropriate tests. */ + + /* Disk-like devices prefer power-of-two block sizes. */ + /* Use provided block_size as a guide so users have some control. */ + if (is_disk_like) { + size_t new_block_size = 64 * 1024; + while (new_block_size < mine->block_size + && new_block_size < 64 * 1024 * 1024) + new_block_size *= 2; + mine->block_size = new_block_size; + } + buffer = malloc(mine->block_size); + if (buffer == NULL) { + archive_set_error(a, ENOMEM, "No memory"); + goto fail; + } + mine->buffer = buffer; + mine->fd = fd; + /* Remember mode so close can decide whether to flush. */ + mine->st_mode = st.st_mode; + + /* Disk-like inputs can use lseek(). */ + if (is_disk_like) + mine->use_lseek = 1; + + return (ARCHIVE_OK); +fail: + /* + * Don't close file descriptors not opened or ones pointing referring + * to `FNT_STDIN`. + */ + if (fd != -1 && fd != 0) + close(fd); + return (ARCHIVE_FATAL); +} + +static ssize_t +file_read(struct archive *a, void *client_data, const void **buff) +{ + struct read_file_data *mine = (struct read_file_data *)client_data; + ssize_t bytes_read; + + /* TODO: If a recent lseek() operation has left us + * mis-aligned, read and return a short block to try to get + * us back in alignment. */ + + /* TODO: Someday, try mmap() here; if that succeeds, give + * the entire file to libarchive as a single block. That + * could be a lot faster than block-by-block manual I/O. */ + + /* TODO: We might be able to improve performance on pipes and + * sockets by setting non-blocking I/O and just accepting + * whatever we get here instead of waiting for a full block + * worth of data. */ + + *buff = mine->buffer; + for (;;) { + bytes_read = read(mine->fd, mine->buffer, mine->block_size); + if (bytes_read < 0) { + if (errno == EINTR) + continue; + else if (mine->filename_type == FNT_STDIN) + archive_set_error(a, errno, + "Error reading stdin"); + else if (mine->filename_type == FNT_MBS) + archive_set_error(a, errno, + "Error reading '%s'", mine->filename.m); + else + archive_set_error(a, errno, + "Error reading '%S'", mine->filename.w); + } + return (bytes_read); + } +} + +/* + * Regular files and disk-like block devices can use simple lseek + * without needing to round the request to the block size. + * + * TODO: This can leave future reads mis-aligned. Since we know the + * offset here, we should store it and use it in file_read() above + * to determine whether we should perform a short read to get back + * into alignment. Long series of mis-aligned reads can negatively + * impact disk throughput. (Of course, the performance impact should + * be carefully tested; extra code complexity is only worthwhile if + * it does provide measurable improvement.) + * + * TODO: Be lazy about the actual seek. There are a few pathological + * cases where libarchive makes a bunch of seek requests in a row + * without any intervening reads. This isn't a huge performance + * problem, since the kernel handles seeks lazily already, but + * it would be very slightly faster if we simply remembered the + * seek request here and then actually performed the seek at the + * top of the read callback above. + */ +static int64_t +file_skip_lseek(struct archive *a, void *client_data, int64_t request) +{ + struct read_file_data *mine = (struct read_file_data *)client_data; +#if defined(_WIN32) && !defined(__CYGWIN__) + /* We use _lseeki64() on Windows. */ + int64_t old_offset, new_offset; +#else + off_t old_offset, new_offset; +#endif + + /* We use off_t here because lseek() is declared that way. */ + + /* TODO: Deal with case where off_t isn't 64 bits. + * This shouldn't be a problem on Linux or other POSIX + * systems, since the configuration logic for libarchive + * tries to obtain a 64-bit off_t. + */ + if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0 && + (new_offset = lseek(mine->fd, request, SEEK_CUR)) >= 0) + return (new_offset - old_offset); + + /* If lseek() fails, don't bother trying again. */ + mine->use_lseek = 0; + + /* Let libarchive recover with read+discard */ + if (errno == ESPIPE) + return (0); + + /* If the input is corrupted or truncated, fail. */ + if (mine->filename_type == FNT_STDIN) + archive_set_error(a, errno, "Error seeking in stdin"); + else if (mine->filename_type == FNT_MBS) + archive_set_error(a, errno, "Error seeking in '%s'", + mine->filename.m); + else + archive_set_error(a, errno, "Error seeking in '%S'", + mine->filename.w); + return (-1); +} + + +/* + * TODO: Implement another file_skip_XXXX that uses MTIO ioctls to + * accelerate operation on tape drives. + */ + +static int64_t +file_skip(struct archive *a, void *client_data, int64_t request) +{ + struct read_file_data *mine = (struct read_file_data *)client_data; + + /* Delegate skip requests. */ + if (mine->use_lseek) + return (file_skip_lseek(a, client_data, request)); + + /* If we can't skip, return 0; libarchive will read+discard instead. */ + return (0); +} + +/* + * TODO: Store the offset and use it in the read callback. + */ +static int64_t +file_seek(struct archive *a, void *client_data, int64_t request, int whence) +{ + struct read_file_data *mine = (struct read_file_data *)client_data; + int64_t r; + + /* We use off_t here because lseek() is declared that way. */ + /* See above for notes about when off_t is less than 64 bits. */ + r = lseek(mine->fd, request, whence); + if (r >= 0) + return r; + + /* If the input is corrupted or truncated, fail. */ + if (mine->filename_type == FNT_STDIN) + archive_set_error(a, errno, "Error seeking in stdin"); + else if (mine->filename_type == FNT_MBS) + archive_set_error(a, errno, "Error seeking in '%s'", + mine->filename.m); + else + archive_set_error(a, errno, "Error seeking in '%S'", + mine->filename.w); + return (ARCHIVE_FATAL); +} + +static int +file_close2(struct archive *a, void *client_data) +{ + struct read_file_data *mine = (struct read_file_data *)client_data; + + (void)a; /* UNUSED */ + + /* Only flush and close if open succeeded. */ + if (mine->fd >= 0) { + /* + * Sometimes, we should flush the input before closing. + * Regular files: faster to just close without flush. + * Disk-like devices: Ditto. + * Tapes: must not flush (user might need to + * read the "next" item on a non-rewind device). + * Pipes and sockets: must flush (otherwise, the + * program feeding the pipe or socket may complain). + * Here, I flush everything except for regular files and + * device nodes. + */ + if (!S_ISREG(mine->st_mode) + && !S_ISCHR(mine->st_mode) + && !S_ISBLK(mine->st_mode)) { + ssize_t bytesRead; + do { + bytesRead = read(mine->fd, mine->buffer, + mine->block_size); + } while (bytesRead > 0); + } + /* If a named file was opened, then it needs to be closed. */ + if (mine->filename_type != FNT_STDIN) + close(mine->fd); + } + free(mine->buffer); + mine->buffer = NULL; + mine->fd = -1; + return (ARCHIVE_OK); +} + +static int +file_close(struct archive *a, void *client_data) +{ + struct read_file_data *mine = (struct read_file_data *)client_data; + file_close2(a, client_data); + free(mine); + return (ARCHIVE_OK); +} + +static int +file_switch(struct archive *a, void *client_data1, void *client_data2) +{ + file_close2(a, client_data1); + return file_open(a, client_data2); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_open_memory.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_open_memory.c new file mode 100644 index 0000000..311be47 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_open_memory.c @@ -0,0 +1,186 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_open_memory.c,v 1.6 2007/07/06 15:51:59 kientzle Exp $"); + +#include +#include +#include + +#include "archive.h" + +/* + * Glue to read an archive from a block of memory. + * + * This is mostly a huge help in building test harnesses; + * test programs can build archives in memory and read them + * back again without having to mess with files on disk. + */ + +struct read_memory_data { + const unsigned char *start; + const unsigned char *p; + const unsigned char *end; + ssize_t read_size; +}; + +static int memory_read_close(struct archive *, void *); +static int memory_read_open(struct archive *, void *); +static int64_t memory_read_seek(struct archive *, void *, int64_t offset, int whence); +static int64_t memory_read_skip(struct archive *, void *, int64_t request); +static ssize_t memory_read(struct archive *, void *, const void **buff); + +int +archive_read_open_memory(struct archive *a, const void *buff, size_t size) +{ + return archive_read_open_memory2(a, buff, size, size); +} + +/* + * Don't use _open_memory2() in production code; the archive_read_open_memory() + * version is the one you really want. This is just here so that + * test harnesses can exercise block operations inside the library. + */ +int +archive_read_open_memory2(struct archive *a, const void *buff, + size_t size, size_t read_size) +{ + struct read_memory_data *mine; + + mine = (struct read_memory_data *)calloc(1, sizeof(*mine)); + if (mine == NULL) { + archive_set_error(a, ENOMEM, "No memory"); + return (ARCHIVE_FATAL); + } + mine->start = mine->p = (const unsigned char *)buff; + mine->end = mine->start + size; + mine->read_size = read_size; + archive_read_set_open_callback(a, memory_read_open); + archive_read_set_read_callback(a, memory_read); + archive_read_set_seek_callback(a, memory_read_seek); + archive_read_set_skip_callback(a, memory_read_skip); + archive_read_set_close_callback(a, memory_read_close); + archive_read_set_callback_data(a, mine); + return (archive_read_open1(a)); +} + +/* + * There's nothing to open. + */ +static int +memory_read_open(struct archive *a, void *client_data) +{ + (void)a; /* UNUSED */ + (void)client_data; /* UNUSED */ + return (ARCHIVE_OK); +} + +/* + * This is scary simple: Just advance a pointer. Limiting + * to read_size is not technically necessary, but it exercises + * more of the internal logic when used with a small block size + * in a test harness. Production use should not specify a block + * size; then this is much faster. + */ +static ssize_t +memory_read(struct archive *a, void *client_data, const void **buff) +{ + struct read_memory_data *mine = (struct read_memory_data *)client_data; + ssize_t size; + + (void)a; /* UNUSED */ + *buff = mine->p; + size = mine->end - mine->p; + if (size > mine->read_size) + size = mine->read_size; + mine->p += size; + return (size); +} + +/* + * Advancing is just as simple. Again, this is doing more than + * necessary in order to better exercise internal code when used + * as a test harness. + */ +static int64_t +memory_read_skip(struct archive *a, void *client_data, int64_t skip) +{ + struct read_memory_data *mine = (struct read_memory_data *)client_data; + + (void)a; /* UNUSED */ + if ((int64_t)skip > (int64_t)(mine->end - mine->p)) + skip = mine->end - mine->p; + /* Round down to block size. */ + skip /= mine->read_size; + skip *= mine->read_size; + mine->p += skip; + return (skip); +} + +/* + * Seeking. + */ +static int64_t +memory_read_seek(struct archive *a, void *client_data, int64_t offset, int whence) +{ + struct read_memory_data *mine = (struct read_memory_data *)client_data; + + (void)a; /* UNUSED */ + switch (whence) { + case SEEK_SET: + mine->p = mine->start + offset; + break; + case SEEK_CUR: + mine->p += offset; + break; + case SEEK_END: + mine->p = mine->end + offset; + break; + default: + return ARCHIVE_FATAL; + } + if (mine->p < mine->start) { + mine->p = mine->start; + return ARCHIVE_FAILED; + } + if (mine->p > mine->end) { + mine->p = mine->end; + return ARCHIVE_FAILED; + } + return (mine->p - mine->start); +} + +/* + * Close is just cleaning up our one small bit of data. + */ +static int +memory_read_close(struct archive *a, void *client_data) +{ + struct read_memory_data *mine = (struct read_memory_data *)client_data; + (void)a; /* UNUSED */ + free(mine); + return (ARCHIVE_OK); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_private.h b/dependencies/libarchive-3.4.2/libarchive/archive_read_private.h new file mode 100644 index 0000000..c842e6f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_private.h @@ -0,0 +1,266 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: head/lib/libarchive/archive_read_private.h 201088 2009-12-28 02:18:55Z kientzle $ + */ + +#ifndef ARCHIVE_READ_PRIVATE_H_INCLUDED +#define ARCHIVE_READ_PRIVATE_H_INCLUDED + +#ifndef __LIBARCHIVE_BUILD +#ifndef __LIBARCHIVE_TEST +#error This header is only to be used internally to libarchive. +#endif +#endif + +#include "archive.h" +#include "archive_string.h" +#include "archive_private.h" + +struct archive_read; +struct archive_read_filter_bidder; +struct archive_read_filter; + +/* + * How bidding works for filters: + * * The bid manager initializes the client-provided reader as the + * first filter. + * * It invokes the bidder for each registered filter with the + * current head filter. + * * The bidders can use archive_read_filter_ahead() to peek ahead + * at the incoming data to compose their bids. + * * The bid manager creates a new filter structure for the winning + * bidder and gives the winning bidder a chance to initialize it. + * * The new filter becomes the new top filter and we repeat the + * process. + * This ends only when no bidder provides a non-zero bid. Then + * we perform a similar dance with the registered format handlers. + */ +struct archive_read_filter_bidder { + /* Configuration data for the bidder. */ + void *data; + /* Name of the filter */ + const char *name; + /* Taste the upstream filter to see if we handle this. */ + int (*bid)(struct archive_read_filter_bidder *, + struct archive_read_filter *); + /* Initialize a newly-created filter. */ + int (*init)(struct archive_read_filter *); + /* Set an option for the filter bidder. */ + int (*options)(struct archive_read_filter_bidder *, + const char *key, const char *value); + /* Release the bidder's configuration data. */ + int (*free)(struct archive_read_filter_bidder *); +}; + +/* + * This structure is allocated within the archive_read core + * and initialized by archive_read and the init() method of the + * corresponding bidder above. + */ +struct archive_read_filter { + int64_t position; + /* Essentially all filters will need these values, so + * just declare them here. */ + struct archive_read_filter_bidder *bidder; /* My bidder. */ + struct archive_read_filter *upstream; /* Who I read from. */ + struct archive_read *archive; /* Associated archive. */ + /* Open a block for reading */ + int (*open)(struct archive_read_filter *self); + /* Return next block. */ + ssize_t (*read)(struct archive_read_filter *, const void **); + /* Skip forward this many bytes. */ + int64_t (*skip)(struct archive_read_filter *self, int64_t request); + /* Seek to an absolute location. */ + int64_t (*seek)(struct archive_read_filter *self, int64_t offset, int whence); + /* Close (just this filter) and free(self). */ + int (*close)(struct archive_read_filter *self); + /* Function that handles switching from reading one block to the next/prev */ + int (*sswitch)(struct archive_read_filter *self, unsigned int iindex); + /* Read any header metadata if available. */ + int (*read_header)(struct archive_read_filter *self, struct archive_entry *entry); + /* My private data. */ + void *data; + + const char *name; + int code; + + /* Used by reblocking logic. */ + char *buffer; + size_t buffer_size; + char *next; /* Current read location. */ + size_t avail; /* Bytes in my buffer. */ + const void *client_buff; /* Client buffer information. */ + size_t client_total; + const char *client_next; + size_t client_avail; + char end_of_file; + char closed; + char fatal; +}; + +/* + * The client looks a lot like a filter, so we just wrap it here. + * + * TODO: Make archive_read_filter and archive_read_client identical so + * that users of the library can easily register their own + * transformation filters. This will probably break the API/ABI and + * so should be deferred at least until libarchive 3.0. + */ +struct archive_read_data_node { + int64_t begin_position; + int64_t total_size; + void *data; +}; +struct archive_read_client { + archive_open_callback *opener; + archive_read_callback *reader; + archive_skip_callback *skipper; + archive_seek_callback *seeker; + archive_close_callback *closer; + archive_switch_callback *switcher; + unsigned int nodes; + unsigned int cursor; + int64_t position; + struct archive_read_data_node *dataset; +}; +struct archive_read_passphrase { + char *passphrase; + struct archive_read_passphrase *next; +}; + +struct archive_read_extract { + struct archive *ad; /* archive_write_disk object */ + + /* Progress function invoked during extract. */ + void (*extract_progress)(void *); + void *extract_progress_user_data; +}; + +struct archive_read { + struct archive archive; + + struct archive_entry *entry; + + /* Dev/ino of the archive being read/written. */ + int skip_file_set; + int64_t skip_file_dev; + int64_t skip_file_ino; + + /* Callbacks to open/read/write/close client archive streams. */ + struct archive_read_client client; + + /* Registered filter bidders. */ + struct archive_read_filter_bidder bidders[16]; + + /* Last filter in chain */ + struct archive_read_filter *filter; + + /* Whether to bypass filter bidding process */ + int bypass_filter_bidding; + + /* File offset of beginning of most recently-read header. */ + int64_t header_position; + + /* Nodes and offsets of compressed data block */ + unsigned int data_start_node; + unsigned int data_end_node; + + /* + * Format detection is mostly the same as compression + * detection, with one significant difference: The bidders + * use the read_ahead calls above to examine the stream rather + * than having the supervisor hand them a block of data to + * examine. + */ + + struct archive_format_descriptor { + void *data; + const char *name; + int (*bid)(struct archive_read *, int best_bid); + int (*options)(struct archive_read *, const char *key, + const char *value); + int (*read_header)(struct archive_read *, struct archive_entry *); + int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *); + int (*read_data_skip)(struct archive_read *); + int64_t (*seek_data)(struct archive_read *, int64_t, int); + int (*cleanup)(struct archive_read *); + int (*format_capabilties)(struct archive_read *); + int (*has_encrypted_entries)(struct archive_read *); + } formats[16]; + struct archive_format_descriptor *format; /* Active format. */ + + /* + * Various information needed by archive_extract. + */ + struct archive_read_extract *extract; + int (*cleanup_archive_extract)(struct archive_read *); + + /* + * Decryption passphrase. + */ + struct { + struct archive_read_passphrase *first; + struct archive_read_passphrase **last; + int candidate; + archive_passphrase_callback *callback; + void *client_data; + } passphrases; +}; + +int __archive_read_register_format(struct archive_read *a, + void *format_data, + const char *name, + int (*bid)(struct archive_read *, int), + int (*options)(struct archive_read *, const char *, const char *), + int (*read_header)(struct archive_read *, struct archive_entry *), + int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *), + int (*read_data_skip)(struct archive_read *), + int64_t (*seek_data)(struct archive_read *, int64_t, int), + int (*cleanup)(struct archive_read *), + int (*format_capabilities)(struct archive_read *), + int (*has_encrypted_entries)(struct archive_read *)); + +int __archive_read_get_bidder(struct archive_read *a, + struct archive_read_filter_bidder **bidder); + +const void *__archive_read_ahead(struct archive_read *, size_t, ssize_t *); +const void *__archive_read_filter_ahead(struct archive_read_filter *, + size_t, ssize_t *); +int64_t __archive_read_seek(struct archive_read*, int64_t, int); +int64_t __archive_read_filter_seek(struct archive_read_filter *, int64_t, int); +int64_t __archive_read_consume(struct archive_read *, int64_t); +int64_t __archive_read_filter_consume(struct archive_read_filter *, int64_t); +int __archive_read_header(struct archive_read *, struct archive_entry *); +int __archive_read_program(struct archive_read_filter *, const char *); +void __archive_read_free_filters(struct archive_read *); +struct archive_read_extract *__archive_read_get_extract(struct archive_read *); + + +/* + * Get a decryption passphrase. + */ +void __archive_read_reset_passphrase(struct archive_read *a); +const char * __archive_read_next_passphrase(struct archive_read *a); +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_set_format.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_set_format.c new file mode 100644 index 0000000..1d3e49d --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_set_format.c @@ -0,0 +1,108 @@ +/*- + * Copyright (c) 2003-2012 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_read_private.h" + +int +archive_read_set_format(struct archive *_a, int code) +{ + int r1, r2, slots, i; + char str[10]; + struct archive_read *a = (struct archive_read *)_a; + + if ((r1 = archive_read_support_format_by_code(_a, code)) < (ARCHIVE_OK)) + return r1; + + r1 = r2 = (ARCHIVE_OK); + if (a->format) + r2 = (ARCHIVE_WARN); + switch (code & ARCHIVE_FORMAT_BASE_MASK) + { + case ARCHIVE_FORMAT_7ZIP: + strcpy(str, "7zip"); + break; + case ARCHIVE_FORMAT_AR: + strcpy(str, "ar"); + break; + case ARCHIVE_FORMAT_CAB: + strcpy(str, "cab"); + break; + case ARCHIVE_FORMAT_CPIO: + strcpy(str, "cpio"); + break; + case ARCHIVE_FORMAT_ISO9660: + strcpy(str, "iso9660"); + break; + case ARCHIVE_FORMAT_LHA: + strcpy(str, "lha"); + break; + case ARCHIVE_FORMAT_MTREE: + strcpy(str, "mtree"); + break; + case ARCHIVE_FORMAT_RAR: + strcpy(str, "rar"); + break; + case ARCHIVE_FORMAT_RAR_V5: + strcpy(str, "rar5"); + break; + case ARCHIVE_FORMAT_TAR: + strcpy(str, "tar"); + break; + case ARCHIVE_FORMAT_XAR: + strcpy(str, "xar"); + break; + case ARCHIVE_FORMAT_ZIP: + strcpy(str, "zip"); + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "Invalid format code specified"); + return (ARCHIVE_FATAL); + } + + slots = sizeof(a->formats) / sizeof(a->formats[0]); + a->format = &(a->formats[0]); + for (i = 0; i < slots; i++, a->format++) { + if (!a->format->name || !strcmp(a->format->name, str)) + break; + } + if (!a->format->name || strcmp(a->format->name, str)) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "Internal error: Unable to set format"); + r1 = (ARCHIVE_FATAL); + } + + return (r1 < r2) ? r1 : r2; +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_set_options.3 b/dependencies/libarchive-3.4.2/libarchive/archive_read_set_options.3 new file mode 100644 index 0000000..78d9999 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_set_options.3 @@ -0,0 +1,262 @@ +.\" Copyright (c) 2011 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd January 31, 2020 +.Dt ARCHIVE_READ_OPTIONS 3 +.Os +.Sh NAME +.Nm archive_read_set_filter_option , +.Nm archive_read_set_format_option , +.Nm archive_read_set_option , +.Nm archive_read_set_options +.Nd functions controlling options for reading archives +.\" +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.Ft int +.Fo archive_read_set_filter_option +.Fa "struct archive *" +.Fa "const char *module" +.Fa "const char *option" +.Fa "const char *value" +.Fc +.Ft int +.Fo archive_read_set_format_option +.Fa "struct archive *" +.Fa "const char *module" +.Fa "const char *option" +.Fa "const char *value" +.Fc +.Ft int +.Fo archive_read_set_option +.Fa "struct archive *" +.Fa "const char *module" +.Fa "const char *option" +.Fa "const char *value" +.Fc +.Ft int +.Fo archive_read_set_options +.Fa "struct archive *" +.Fa "const char *options" +.Fc +.Sh DESCRIPTION +These functions provide a way for libarchive clients to configure +specific read modules. +.Bl -tag -width indent +.It Xo +.Fn archive_read_set_filter_option , +.Fn archive_read_set_format_option +.Xc +Specifies an option that will be passed to currently-registered +filters (including decompression filters) or format readers. +.Pp +If +.Ar option +and +.Ar value +are both +.Dv NULL , +these functions will do nothing and +.Cm ARCHIVE_OK +will be returned. +If +.Ar option +is +.Dv NULL +but +.Ar value +is not, these functions will do nothing and +.Cm ARCHIVE_FAILED +will be returned. +.Pp +If +.Ar module +is not +.Dv NULL , +.Ar option +and +.Ar value +will be provided to the filter or reader named +.Ar module . +The return value will be that of the module. +If there is no such module, +.Cm ARCHIVE_FAILED +will be returned. +.Pp +If +.Ar module +is +.Dv NULL , +.Ar option +and +.Ar value +will be provided to every registered module. +If any module returns +.Cm ARCHIVE_FATAL , +this value will be returned immediately. +Otherwise, +.Cm ARCHIVE_OK +will be returned if any module accepts the option, and +.Cm ARCHIVE_FAILED +in all other cases. +.\" +.It Xo +.Fn archive_read_set_option +.Xc +Calls +.Fn archive_read_set_format_option , +then +.Fn archive_read_set_filter_option . +If either function returns +.Cm ARCHIVE_FATAL , +.Cm ARCHIVE_FATAL +will be returned +immediately. +Otherwise, greater of the two values will be returned. +.\" +.It Xo +.Fn archive_read_set_options +.Xc +.Ar options +is a comma-separated list of options. +If +.Ar options +is +.Dv NULL +or empty, +.Cm ARCHIVE_OK +will be returned immediately. +.Pp +Calls +.Fn archive_read_set_option +with each option in turn. +If any +.Fn archive_read_set_option +call returns +.Cm ARCHIVE_FATAL , +.Cm ARCHIVE_FATAL +will be returned immediately. +.Pp +Individual options have one of the following forms: +.Bl -tag -compact -width indent +.It Ar option=value +The option/value pair will be provided to every module. +Modules that do not accept an option with this name will ignore it. +.It Ar option +The option will be provided to every module with a value of +.Dq 1 . +.It Ar !option +The option will be provided to every module with a NULL value. +.It Ar module:option=value , Ar module:option , Ar module:!option +As above, but the corresponding option and value will be provided +only to modules whose name matches +.Ar module . +.El +.El +.\" +.Sh OPTIONS +.Bl -tag -compact -width indent +.It Format cab +.Bl -tag -compact -width indent +.It Cm hdrcharset +The value is used as a character set name that will be +used when translating file names. +.El +.It Format cpio +.Bl -tag -compact -width indent +.It Cm hdrcharset +The value is used as a character set name that will be +used when translating file names. +.El +.It Format iso9660 +.Bl -tag -compact -width indent +.It Cm joliet +Support Joliet extensions. +Defaults to enabled, use +.Cm !joliet +to disable. +.It Cm rockridge +Support RockRidge extensions. +Defaults to enabled, use +.Cm !rockridge +to disable. +.El +.It Format lha +.Bl -tag -compact -width indent +.It Cm hdrcharset +The value is used as a character set name that will be +used when translating file names. +.El +.It Format mtree +.Bl -tag -compact -width indent +.It Cm checkfs +Allow reading information missing from the mtree from the file system. +Disabled by default. +.El +.It Format rar +.Bl -tag -compact -width indent +.It Cm hdrcharset +The value is used as a character set name that will be +used when translating file names. +.El +.It Format tar +.Bl -tag -compact -width indent +.It Cm compat-2x +Libarchive 2.x incorrectly encoded Unicode filenames on +some platforms. +This option mimics the libarchive 2.x filename handling +so that such archives can be read correctly. +.It Cm hdrcharset +The value is used as a character set name that will be +used when translating file names. +.It Cm mac-ext +Support Mac OS metadata extension that records data in special +files beginning with a period and underscore. +Defaults to enabled on Mac OS, disabled on other platforms. +Use +.Cm !mac-ext +to disable. +.It Cm read_concatenated_archives +Ignore zeroed blocks in the archive, which occurs when multiple tar archives +have been concatenated together. +Without this option, only the contents of +the first concatenated archive would be read. +.El +.El +.\" +.Sh ERRORS +Detailed error codes and textual descriptions are available from the +.Fn archive_errno +and +.Fn archive_error_string +functions. +.\" +.Sh SEE ALSO +.Xr tar 1 , +.Xr archive_read 3 , +.Xr archive_write_set_options 3 , +.Xr libarchive 3 diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_set_options.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_set_options.c new file mode 100644 index 0000000..2e2eea6 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_set_options.c @@ -0,0 +1,155 @@ +/*- + * Copyright (c) 2011 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#include "archive_read_private.h" +#include "archive_options_private.h" + +static int archive_set_format_option(struct archive *a, + const char *m, const char *o, const char *v); +static int archive_set_filter_option(struct archive *a, + const char *m, const char *o, const char *v); +static int archive_set_option(struct archive *a, + const char *m, const char *o, const char *v); + +int +archive_read_set_format_option(struct archive *a, const char *m, const char *o, + const char *v) +{ + return _archive_set_option(a, m, o, v, + ARCHIVE_READ_MAGIC, "archive_read_set_format_option", + archive_set_format_option); +} + +int +archive_read_set_filter_option(struct archive *a, const char *m, const char *o, + const char *v) +{ + return _archive_set_option(a, m, o, v, + ARCHIVE_READ_MAGIC, "archive_read_set_filter_option", + archive_set_filter_option); +} + +int +archive_read_set_option(struct archive *a, const char *m, const char *o, + const char *v) +{ + return _archive_set_option(a, m, o, v, + ARCHIVE_READ_MAGIC, "archive_read_set_option", + archive_set_option); +} + +int +archive_read_set_options(struct archive *a, const char *options) +{ + return _archive_set_options(a, options, + ARCHIVE_READ_MAGIC, "archive_read_set_options", + archive_set_option); +} + +static int +archive_set_format_option(struct archive *_a, const char *m, const char *o, + const char *v) +{ + struct archive_read *a = (struct archive_read *)_a; + size_t i; + int r, rv = ARCHIVE_WARN, matched_modules = 0; + + for (i = 0; i < sizeof(a->formats)/sizeof(a->formats[0]); i++) { + struct archive_format_descriptor *format = &a->formats[i]; + + if (format->options == NULL || format->name == NULL) + /* This format does not support option. */ + continue; + if (m != NULL) { + if (strcmp(format->name, m) != 0) + continue; + ++matched_modules; + } + + a->format = format; + r = format->options(a, o, v); + a->format = NULL; + + if (r == ARCHIVE_FATAL) + return (ARCHIVE_FATAL); + + if (r == ARCHIVE_OK) + rv = ARCHIVE_OK; + } + /* If the format name didn't match, return a special code for + * _archive_set_option[s]. */ + if (m != NULL && matched_modules == 0) + return ARCHIVE_WARN - 1; + return (rv); +} + +static int +archive_set_filter_option(struct archive *_a, const char *m, const char *o, + const char *v) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter *filter; + struct archive_read_filter_bidder *bidder; + int r, rv = ARCHIVE_WARN, matched_modules = 0; + + for (filter = a->filter; filter != NULL; filter = filter->upstream) { + bidder = filter->bidder; + if (bidder == NULL) + continue; + if (bidder->options == NULL) + /* This bidder does not support option */ + continue; + if (m != NULL) { + if (strcmp(filter->name, m) != 0) + continue; + ++matched_modules; + } + + r = bidder->options(bidder, o, v); + + if (r == ARCHIVE_FATAL) + return (ARCHIVE_FATAL); + + if (r == ARCHIVE_OK) + rv = ARCHIVE_OK; + } + /* If the filter name didn't match, return a special code for + * _archive_set_option[s]. */ + if (m != NULL && matched_modules == 0) + return ARCHIVE_WARN - 1; + return (rv); +} + +static int +archive_set_option(struct archive *a, const char *m, const char *o, + const char *v) +{ + return _archive_set_either_option(a, m, o, v, + archive_set_format_option, + archive_set_filter_option); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_all.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_all.c new file mode 100644 index 0000000..edb508c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_all.c @@ -0,0 +1,85 @@ +/*- + * Copyright (c) 2003-2011 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#include "archive.h" +#include "archive_private.h" + +#if ARCHIVE_VERSION_NUMBER < 4000000 +/* Deprecated; remove in libarchive 4.0 */ +int +archive_read_support_compression_all(struct archive *a) +{ + return archive_read_support_filter_all(a); +} +#endif + +int +archive_read_support_filter_all(struct archive *a) +{ + archive_check_magic(a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_filter_all"); + + /* Bzip falls back to "bunzip2" command-line */ + archive_read_support_filter_bzip2(a); + /* The decompress code doesn't use an outside library. */ + archive_read_support_filter_compress(a); + /* Gzip decompress falls back to "gzip -d" command-line. */ + archive_read_support_filter_gzip(a); + /* Lzip falls back to "unlzip" command-line program. */ + archive_read_support_filter_lzip(a); + /* The LZMA file format has a very weak signature, so it + * may not be feasible to keep this here, but we'll try. + * This will come back out if there are problems. */ + /* Lzma falls back to "unlzma" command-line program. */ + archive_read_support_filter_lzma(a); + /* Xz falls back to "unxz" command-line program. */ + archive_read_support_filter_xz(a); + /* The decode code doesn't use an outside library. */ + archive_read_support_filter_uu(a); + /* The decode code doesn't use an outside library. */ + archive_read_support_filter_rpm(a); + /* The decode code always uses "lrzip -q -d" command-line. */ + archive_read_support_filter_lrzip(a); + /* Lzop decompress falls back to "lzop -d" command-line. */ + archive_read_support_filter_lzop(a); + /* The decode code always uses "grzip -d" command-line. */ + archive_read_support_filter_grzip(a); + /* Lz4 falls back to "lz4 -d" command-line program. */ + archive_read_support_filter_lz4(a); + /* Zstd falls back to "zstd -d" command-line program. */ + archive_read_support_filter_zstd(a); + + /* Note: We always return ARCHIVE_OK here, even if some of the + * above return ARCHIVE_WARN. The intent here is to enable + * "as much as possible." Clients who need specific + * compression should enable those individually so they can + * verify the level of support. */ + /* Clear any warning messages set by the above functions. */ + archive_clear_error(a); + return (ARCHIVE_OK); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_bzip2.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_bzip2.c new file mode 100644 index 0000000..3885a7c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_bzip2.c @@ -0,0 +1,371 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_BZLIB_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_read_private.h" + +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) +struct private_data { + bz_stream stream; + char *out_block; + size_t out_block_size; + char valid; /* True = decompressor is initialized */ + char eof; /* True = found end of compressed data. */ +}; + +/* Bzip2 filter */ +static ssize_t bzip2_filter_read(struct archive_read_filter *, const void **); +static int bzip2_filter_close(struct archive_read_filter *); +#endif + +/* + * Note that we can detect bzip2 archives even if we can't decompress + * them. (In fact, we like detecting them because we can give better + * error messages.) So the bid framework here gets compiled even + * if bzlib is unavailable. + */ +static int bzip2_reader_bid(struct archive_read_filter_bidder *, struct archive_read_filter *); +static int bzip2_reader_init(struct archive_read_filter *); +static int bzip2_reader_free(struct archive_read_filter_bidder *); + +#if ARCHIVE_VERSION_NUMBER < 4000000 +/* Deprecated; remove in libarchive 4.0 */ +int +archive_read_support_compression_bzip2(struct archive *a) +{ + return archive_read_support_filter_bzip2(a); +} +#endif + +int +archive_read_support_filter_bzip2(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter_bidder *reader; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_filter_bzip2"); + + if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + reader->data = NULL; + reader->name = "bzip2"; + reader->bid = bzip2_reader_bid; + reader->init = bzip2_reader_init; + reader->options = NULL; + reader->free = bzip2_reader_free; +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) + return (ARCHIVE_OK); +#else + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "Using external bzip2 program"); + return (ARCHIVE_WARN); +#endif +} + +static int +bzip2_reader_free(struct archive_read_filter_bidder *self){ + (void)self; /* UNUSED */ + return (ARCHIVE_OK); +} + +/* + * Test whether we can handle this data. + * + * This logic returns zero if any part of the signature fails. It + * also tries to Do The Right Thing if a very short buffer prevents us + * from verifying as much as we would like. + */ +static int +bzip2_reader_bid(struct archive_read_filter_bidder *self, struct archive_read_filter *filter) +{ + const unsigned char *buffer; + ssize_t avail; + int bits_checked; + + (void)self; /* UNUSED */ + + /* Minimal bzip2 archive is 14 bytes. */ + buffer = __archive_read_filter_ahead(filter, 14, &avail); + if (buffer == NULL) + return (0); + + /* First three bytes must be "BZh" */ + bits_checked = 0; + if (memcmp(buffer, "BZh", 3) != 0) + return (0); + bits_checked += 24; + + /* Next follows a compression flag which must be an ASCII digit. */ + if (buffer[3] < '1' || buffer[3] > '9') + return (0); + bits_checked += 5; + + /* After BZh[1-9], there must be either a data block + * which begins with 0x314159265359 or an end-of-data + * marker of 0x177245385090. */ + if (memcmp(buffer + 4, "\x31\x41\x59\x26\x53\x59", 6) == 0) + bits_checked += 48; + else if (memcmp(buffer + 4, "\x17\x72\x45\x38\x50\x90", 6) == 0) + bits_checked += 48; + else + return (0); + + return (bits_checked); +} + +#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR) + +/* + * If we don't have the library on this system, we can't actually do the + * decompression. We can, however, still detect compressed archives + * and emit a useful message. + */ +static int +bzip2_reader_init(struct archive_read_filter *self) +{ + int r; + + r = __archive_read_program(self, "bzip2 -d"); + /* Note: We set the format here even if __archive_read_program() + * above fails. We do, after all, know what the format is + * even if we weren't able to read it. */ + self->code = ARCHIVE_FILTER_BZIP2; + self->name = "bzip2"; + return (r); +} + + +#else + +/* + * Setup the callbacks. + */ +static int +bzip2_reader_init(struct archive_read_filter *self) +{ + static const size_t out_block_size = 64 * 1024; + void *out_block; + struct private_data *state; + + self->code = ARCHIVE_FILTER_BZIP2; + self->name = "bzip2"; + + state = (struct private_data *)calloc(sizeof(*state), 1); + out_block = (unsigned char *)malloc(out_block_size); + if (state == NULL || out_block == NULL) { + archive_set_error(&self->archive->archive, ENOMEM, + "Can't allocate data for bzip2 decompression"); + free(out_block); + free(state); + return (ARCHIVE_FATAL); + } + + self->data = state; + state->out_block_size = out_block_size; + state->out_block = out_block; + self->read = bzip2_filter_read; + self->skip = NULL; /* not supported */ + self->close = bzip2_filter_close; + + return (ARCHIVE_OK); +} + +/* + * Return the next block of decompressed data. + */ +static ssize_t +bzip2_filter_read(struct archive_read_filter *self, const void **p) +{ + struct private_data *state; + size_t decompressed; + const char *read_buf; + ssize_t ret; + + state = (struct private_data *)self->data; + + if (state->eof) { + *p = NULL; + return (0); + } + + /* Empty our output buffer. */ + state->stream.next_out = state->out_block; + state->stream.avail_out = state->out_block_size; + + /* Try to fill the output buffer. */ + for (;;) { + if (!state->valid) { + if (bzip2_reader_bid(self->bidder, self->upstream) == 0) { + state->eof = 1; + *p = state->out_block; + decompressed = state->stream.next_out + - state->out_block; + return (decompressed); + } + /* Initialize compression library. */ + ret = BZ2_bzDecompressInit(&(state->stream), + 0 /* library verbosity */, + 0 /* don't use low-mem algorithm */); + + /* If init fails, try low-memory algorithm instead. */ + if (ret == BZ_MEM_ERROR) + ret = BZ2_bzDecompressInit(&(state->stream), + 0 /* library verbosity */, + 1 /* do use low-mem algo */); + + if (ret != BZ_OK) { + const char *detail = NULL; + int err = ARCHIVE_ERRNO_MISC; + switch (ret) { + case BZ_PARAM_ERROR: + detail = "invalid setup parameter"; + break; + case BZ_MEM_ERROR: + err = ENOMEM; + detail = "out of memory"; + break; + case BZ_CONFIG_ERROR: + detail = "mis-compiled library"; + break; + } + archive_set_error(&self->archive->archive, err, + "Internal error initializing decompressor%s%s", + detail == NULL ? "" : ": ", + detail); + return (ARCHIVE_FATAL); + } + state->valid = 1; + } + + /* stream.next_in is really const, but bzlib + * doesn't declare it so. */ + read_buf = + __archive_read_filter_ahead(self->upstream, 1, &ret); + if (read_buf == NULL) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "truncated bzip2 input"); + return (ARCHIVE_FATAL); + } + state->stream.next_in = (char *)(uintptr_t)read_buf; + state->stream.avail_in = ret; + /* There is no more data, return whatever we have. */ + if (ret == 0) { + state->eof = 1; + *p = state->out_block; + decompressed = state->stream.next_out + - state->out_block; + return (decompressed); + } + + /* Decompress as much as we can in one pass. */ + ret = BZ2_bzDecompress(&(state->stream)); + __archive_read_filter_consume(self->upstream, + state->stream.next_in - read_buf); + + switch (ret) { + case BZ_STREAM_END: /* Found end of stream. */ + switch (BZ2_bzDecompressEnd(&(state->stream))) { + case BZ_OK: + break; + default: + archive_set_error(&(self->archive->archive), + ARCHIVE_ERRNO_MISC, + "Failed to clean up decompressor"); + return (ARCHIVE_FATAL); + } + state->valid = 0; + /* FALLTHROUGH */ + case BZ_OK: /* Decompressor made some progress. */ + /* If we filled our buffer, update stats and return. */ + if (state->stream.avail_out == 0) { + *p = state->out_block; + decompressed = state->stream.next_out + - state->out_block; + return (decompressed); + } + break; + default: /* Return an error. */ + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, "bzip decompression failed"); + return (ARCHIVE_FATAL); + } + } +} + +/* + * Clean up the decompressor. + */ +static int +bzip2_filter_close(struct archive_read_filter *self) +{ + struct private_data *state; + int ret = ARCHIVE_OK; + + state = (struct private_data *)self->data; + + if (state->valid) { + switch (BZ2_bzDecompressEnd(&state->stream)) { + case BZ_OK: + break; + default: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Failed to clean up decompressor"); + ret = ARCHIVE_FATAL; + } + state->valid = 0; + } + + free(state->out_block); + free(state); + return (ret); +} + +#endif /* HAVE_BZLIB_H && BZ_CONFIG_ERROR */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_compress.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_compress.c new file mode 100644 index 0000000..e05132d --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_compress.c @@ -0,0 +1,465 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This code borrows heavily from "compress" source code, which is + * protected by the following copyright. (Clause 3 dropped by request + * of the Regents.) + */ + +/*- + * Copyright (c) 1985, 1986, 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Diomidis Spinellis and James A. Woods, derived from original + * work by Spencer Thomas and Joseph Orost. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_read_private.h" + +/* + * Because LZW decompression is pretty simple, I've just implemented + * the whole decompressor here (cribbing from "compress" source code, + * of course), rather than relying on an external library. I have + * made an effort to clarify and simplify the algorithm, so the + * names and structure here don't exactly match those used by compress. + */ + +struct private_data { + /* Input variables. */ + const unsigned char *next_in; + size_t avail_in; + size_t consume_unnotified; + int bit_buffer; + int bits_avail; + size_t bytes_in_section; + + /* Output variables. */ + size_t out_block_size; + void *out_block; + + /* Decompression status variables. */ + int use_reset_code; + int end_of_stream; /* EOF status. */ + int maxcode; /* Largest code. */ + int maxcode_bits; /* Length of largest code. */ + int section_end_code; /* When to increase bits. */ + int bits; /* Current code length. */ + int oldcode; /* Previous code. */ + int finbyte; /* Last byte of prev code. */ + + /* Dictionary. */ + int free_ent; /* Next dictionary entry. */ + unsigned char suffix[65536]; + uint16_t prefix[65536]; + + /* + * Scratch area for expanding dictionary entries. Note: + * "worst" case here comes from compressing /dev/zero: the + * last code in the dictionary will code a sequence of + * 65536-256 zero bytes. Thus, we need stack space to expand + * a 65280-byte dictionary entry. (Of course, 32640:1 + * compression could also be considered the "best" case. ;-) + */ + unsigned char *stackp; + unsigned char stack[65300]; +}; + +static int compress_bidder_bid(struct archive_read_filter_bidder *, struct archive_read_filter *); +static int compress_bidder_init(struct archive_read_filter *); +static int compress_bidder_free(struct archive_read_filter_bidder *); + +static ssize_t compress_filter_read(struct archive_read_filter *, const void **); +static int compress_filter_close(struct archive_read_filter *); + +static int getbits(struct archive_read_filter *, int n); +static int next_code(struct archive_read_filter *); + +#if ARCHIVE_VERSION_NUMBER < 4000000 +/* Deprecated; remove in libarchive 4.0 */ +int +archive_read_support_compression_compress(struct archive *a) +{ + return archive_read_support_filter_compress(a); +} +#endif + +int +archive_read_support_filter_compress(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter_bidder *bidder; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_filter_compress"); + + if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + bidder->data = NULL; + bidder->name = "compress (.Z)"; + bidder->bid = compress_bidder_bid; + bidder->init = compress_bidder_init; + bidder->options = NULL; + bidder->free = compress_bidder_free; + return (ARCHIVE_OK); +} + +/* + * Test whether we can handle this data. + * This logic returns zero if any part of the signature fails. + */ +static int +compress_bidder_bid(struct archive_read_filter_bidder *self, + struct archive_read_filter *filter) +{ + const unsigned char *buffer; + ssize_t avail; + int bits_checked; + + (void)self; /* UNUSED */ + + /* Shortest valid compress file is 3 bytes. */ + buffer = __archive_read_filter_ahead(filter, 3, &avail); + + if (buffer == NULL) + return (0); + + bits_checked = 0; + /* First two bytes are the magic value */ + if (buffer[0] != 0x1F || buffer[1] != 0x9D) + return (0); + /* Third byte holds compression parameters. */ + if (buffer[2] & 0x20) /* Reserved bit, must be zero. */ + return (0); + if (buffer[2] & 0x40) /* Reserved bit, must be zero. */ + return (0); + bits_checked += 18; + + return (bits_checked); +} + +/* + * Setup the callbacks. + */ +static int +compress_bidder_init(struct archive_read_filter *self) +{ + struct private_data *state; + static const size_t out_block_size = 64 * 1024; + void *out_block; + int code; + + self->code = ARCHIVE_FILTER_COMPRESS; + self->name = "compress (.Z)"; + + state = (struct private_data *)calloc(sizeof(*state), 1); + out_block = malloc(out_block_size); + if (state == NULL || out_block == NULL) { + free(out_block); + free(state); + archive_set_error(&self->archive->archive, ENOMEM, + "Can't allocate data for %s decompression", + self->name); + return (ARCHIVE_FATAL); + } + + self->data = state; + state->out_block_size = out_block_size; + state->out_block = out_block; + self->read = compress_filter_read; + self->skip = NULL; /* not supported */ + self->close = compress_filter_close; + + /* XXX MOVE THE FOLLOWING OUT OF INIT() XXX */ + + (void)getbits(self, 8); /* Skip first signature byte. */ + (void)getbits(self, 8); /* Skip second signature byte. */ + + /* Get compression parameters. */ + code = getbits(self, 8); + if ((code & 0x1f) > 16) { + archive_set_error(&self->archive->archive, -1, + "Invalid compressed data"); + return (ARCHIVE_FATAL); + } + state->maxcode_bits = code & 0x1f; + state->maxcode = (1 << state->maxcode_bits); + state->use_reset_code = code & 0x80; + + /* Initialize decompressor. */ + state->free_ent = 256; + state->stackp = state->stack; + if (state->use_reset_code) + state->free_ent++; + state->bits = 9; + state->section_end_code = (1<bits) - 1; + state->oldcode = -1; + for (code = 255; code >= 0; code--) { + state->prefix[code] = 0; + state->suffix[code] = code; + } + next_code(self); + + return (ARCHIVE_OK); +} + +/* + * Return a block of data from the decompression buffer. Decompress more + * as necessary. + */ +static ssize_t +compress_filter_read(struct archive_read_filter *self, const void **pblock) +{ + struct private_data *state; + unsigned char *p, *start, *end; + int ret; + + state = (struct private_data *)self->data; + if (state->end_of_stream) { + *pblock = NULL; + return (0); + } + p = start = (unsigned char *)state->out_block; + end = start + state->out_block_size; + + while (p < end && !state->end_of_stream) { + if (state->stackp > state->stack) { + *p++ = *--state->stackp; + } else { + ret = next_code(self); + if (ret == -1) + state->end_of_stream = ret; + else if (ret != ARCHIVE_OK) + return (ret); + } + } + + *pblock = start; + return (p - start); +} + +/* + * Clean up the reader. + */ +static int +compress_bidder_free(struct archive_read_filter_bidder *self) +{ + self->data = NULL; + return (ARCHIVE_OK); +} + +/* + * Close and release the filter. + */ +static int +compress_filter_close(struct archive_read_filter *self) +{ + struct private_data *state = (struct private_data *)self->data; + + free(state->out_block); + free(state); + return (ARCHIVE_OK); +} + +/* + * Process the next code and fill the stack with the expansion + * of the code. Returns ARCHIVE_FATAL if there is a fatal I/O or + * format error, ARCHIVE_EOF if we hit end of data, ARCHIVE_OK otherwise. + */ +static int +next_code(struct archive_read_filter *self) +{ + struct private_data *state = (struct private_data *)self->data; + int code, newcode; + + static int debug_buff[1024]; + static unsigned debug_index; + + code = newcode = getbits(self, state->bits); + if (code < 0) + return (code); + + debug_buff[debug_index++] = code; + if (debug_index >= sizeof(debug_buff)/sizeof(debug_buff[0])) + debug_index = 0; + + /* If it's a reset code, reset the dictionary. */ + if ((code == 256) && state->use_reset_code) { + /* + * The original 'compress' implementation blocked its + * I/O in a manner that resulted in junk bytes being + * inserted after every reset. The next section skips + * this junk. (Yes, the number of *bytes* to skip is + * a function of the current *bit* length.) + */ + int skip_bytes = state->bits - + (state->bytes_in_section % state->bits); + skip_bytes %= state->bits; + state->bits_avail = 0; /* Discard rest of this byte. */ + while (skip_bytes-- > 0) { + code = getbits(self, 8); + if (code < 0) + return (code); + } + /* Now, actually do the reset. */ + state->bytes_in_section = 0; + state->bits = 9; + state->section_end_code = (1 << state->bits) - 1; + state->free_ent = 257; + state->oldcode = -1; + return (next_code(self)); + } + + if (code > state->free_ent + || (code == state->free_ent && state->oldcode < 0)) { + /* An invalid code is a fatal error. */ + archive_set_error(&(self->archive->archive), -1, + "Invalid compressed data"); + return (ARCHIVE_FATAL); + } + + /* Special case for KwKwK string. */ + if (code >= state->free_ent) { + *state->stackp++ = state->finbyte; + code = state->oldcode; + } + + /* Generate output characters in reverse order. */ + while (code >= 256) { + *state->stackp++ = state->suffix[code]; + code = state->prefix[code]; + } + *state->stackp++ = state->finbyte = code; + + /* Generate the new entry. */ + code = state->free_ent; + if (code < state->maxcode && state->oldcode >= 0) { + state->prefix[code] = state->oldcode; + state->suffix[code] = state->finbyte; + ++state->free_ent; + } + if (state->free_ent > state->section_end_code) { + state->bits++; + state->bytes_in_section = 0; + if (state->bits == state->maxcode_bits) + state->section_end_code = state->maxcode; + else + state->section_end_code = (1 << state->bits) - 1; + } + + /* Remember previous code. */ + state->oldcode = newcode; + return (ARCHIVE_OK); +} + +/* + * Return next 'n' bits from stream. + * + * -1 indicates end of available data. + */ +static int +getbits(struct archive_read_filter *self, int n) +{ + struct private_data *state = (struct private_data *)self->data; + int code; + ssize_t ret; + static const int mask[] = { + 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff, + 0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff + }; + + while (state->bits_avail < n) { + if (state->avail_in <= 0) { + if (state->consume_unnotified) { + __archive_read_filter_consume(self->upstream, + state->consume_unnotified); + state->consume_unnotified = 0; + } + state->next_in + = __archive_read_filter_ahead(self->upstream, + 1, &ret); + if (ret == 0) + return (-1); + if (ret < 0 || state->next_in == NULL) + return (ARCHIVE_FATAL); + state->consume_unnotified = state->avail_in = ret; + } + state->bit_buffer |= *state->next_in++ << state->bits_avail; + state->avail_in--; + state->bits_avail += 8; + state->bytes_in_section++; + } + + code = state->bit_buffer; + state->bit_buffer >>= n; + state->bits_avail -= n; + + return (code & mask[n]); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_grzip.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_grzip.c new file mode 100644 index 0000000..84c86ae --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_grzip.c @@ -0,0 +1,121 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); + + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_read_private.h" + +static const unsigned char grzip_magic[] = { + 0x47, 0x52, 0x5a, 0x69, 0x70, 0x49, 0x49, 0x00, + 0x02, 0x04, 0x3a, 0x29 }; + +static int grzip_bidder_bid(struct archive_read_filter_bidder *, + struct archive_read_filter *); +static int grzip_bidder_init(struct archive_read_filter *); + + +static int +grzip_reader_free(struct archive_read_filter_bidder *self) +{ + (void)self; /* UNUSED */ + return (ARCHIVE_OK); +} + +int +archive_read_support_filter_grzip(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter_bidder *reader; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_filter_grzip"); + + if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + reader->data = NULL; + reader->bid = grzip_bidder_bid; + reader->init = grzip_bidder_init; + reader->options = NULL; + reader->free = grzip_reader_free; + /* This filter always uses an external program. */ + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "Using external grzip program for grzip decompression"); + return (ARCHIVE_WARN); +} + +/* + * Bidder just verifies the header and returns the number of verified bits. + */ +static int +grzip_bidder_bid(struct archive_read_filter_bidder *self, + struct archive_read_filter *filter) +{ + const unsigned char *p; + ssize_t avail; + + (void)self; /* UNUSED */ + + p = __archive_read_filter_ahead(filter, sizeof(grzip_magic), &avail); + if (p == NULL || avail == 0) + return (0); + + if (memcmp(p, grzip_magic, sizeof(grzip_magic))) + return (0); + + return (sizeof(grzip_magic) * 8); +} + +static int +grzip_bidder_init(struct archive_read_filter *self) +{ + int r; + + r = __archive_read_program(self, "grzip -d"); + /* Note: We set the format here even if __archive_read_program() + * above fails. We do, after all, know what the format is + * even if we weren't able to read it. */ + self->code = ARCHIVE_FILTER_GRZIP; + self->name = "grzip"; + return (r); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_gzip.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_gzip.c new file mode 100644 index 0000000..9fa9e2b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_gzip.c @@ -0,0 +1,535 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); + + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_ZLIB_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_endian.h" +#include "archive_private.h" +#include "archive_read_private.h" + +#ifdef HAVE_ZLIB_H +struct private_data { + z_stream stream; + char in_stream; + unsigned char *out_block; + size_t out_block_size; + int64_t total_out; + unsigned long crc; + uint32_t mtime; + char *name; + char eof; /* True = found end of compressed data. */ +}; + +/* Gzip Filter. */ +static ssize_t gzip_filter_read(struct archive_read_filter *, const void **); +static int gzip_filter_close(struct archive_read_filter *); +#endif + +/* + * Note that we can detect gzip archives even if we can't decompress + * them. (In fact, we like detecting them because we can give better + * error messages.) So the bid framework here gets compiled even + * if zlib is unavailable. + * + * TODO: If zlib is unavailable, gzip_bidder_init() should + * use the compress_program framework to try to fire up an external + * gzip program. + */ +static int gzip_bidder_bid(struct archive_read_filter_bidder *, + struct archive_read_filter *); +static int gzip_bidder_init(struct archive_read_filter *); + +#if ARCHIVE_VERSION_NUMBER < 4000000 +/* Deprecated; remove in libarchive 4.0 */ +int +archive_read_support_compression_gzip(struct archive *a) +{ + return archive_read_support_filter_gzip(a); +} +#endif + +int +archive_read_support_filter_gzip(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter_bidder *bidder; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_filter_gzip"); + + if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + bidder->data = NULL; + bidder->name = "gzip"; + bidder->bid = gzip_bidder_bid; + bidder->init = gzip_bidder_init; + bidder->options = NULL; + bidder->free = NULL; /* No data, so no cleanup necessary. */ + /* Signal the extent of gzip support with the return value here. */ +#if HAVE_ZLIB_H + return (ARCHIVE_OK); +#else + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "Using external gzip program"); + return (ARCHIVE_WARN); +#endif +} + +/* + * Read and verify the header. + * + * Returns zero if the header couldn't be validated, else returns + * number of bytes in header. If pbits is non-NULL, it receives a + * count of bits verified, suitable for use by bidder. + */ +static ssize_t +peek_at_header(struct archive_read_filter *filter, int *pbits, +#ifdef HAVE_ZLIB_H + struct private_data *state +#else + void *state +#endif + ) +{ + const unsigned char *p; + ssize_t avail, len; + int bits = 0; + int header_flags; +#ifndef HAVE_ZLIB_H + (void)state; /* UNUSED */ +#endif + + /* Start by looking at the first ten bytes of the header, which + * is all fixed layout. */ + len = 10; + p = __archive_read_filter_ahead(filter, len, &avail); + if (p == NULL || avail == 0) + return (0); + /* We only support deflation- third byte must be 0x08. */ + if (memcmp(p, "\x1F\x8B\x08", 3) != 0) + return (0); + bits += 24; + if ((p[3] & 0xE0)!= 0) /* No reserved flags set. */ + return (0); + bits += 3; + header_flags = p[3]; + /* Bytes 4-7 are mod time in little endian. */ +#ifdef HAVE_ZLIB_H + if (state) + state->mtime = archive_le32dec(p + 4); +#endif + /* Byte 8 is deflate flags. */ + /* XXXX TODO: return deflate flags back to consume_header for use + in initializing the decompressor. */ + /* Byte 9 is OS. */ + + /* Optional extra data: 2 byte length plus variable body. */ + if (header_flags & 4) { + p = __archive_read_filter_ahead(filter, len + 2, &avail); + if (p == NULL) + return (0); + len += ((int)p[len + 1] << 8) | (int)p[len]; + len += 2; + } + + /* Null-terminated optional filename. */ + if (header_flags & 8) { +#ifdef HAVE_ZLIB_H + ssize_t file_start = len; +#endif + do { + ++len; + if (avail < len) + p = __archive_read_filter_ahead(filter, + len, &avail); + if (p == NULL) + return (0); + } while (p[len - 1] != 0); + +#ifdef HAVE_ZLIB_H + if (state) { + /* Reset the name in case of repeat header reads. */ + free(state->name); + state->name = strdup((const char *)&p[file_start]); + } +#endif + } + + /* Null-terminated optional comment. */ + if (header_flags & 16) { + do { + ++len; + if (avail < len) + p = __archive_read_filter_ahead(filter, + len, &avail); + if (p == NULL) + return (0); + } while (p[len - 1] != 0); + } + + /* Optional header CRC */ + if ((header_flags & 2)) { + p = __archive_read_filter_ahead(filter, len + 2, &avail); + if (p == NULL) + return (0); +#if 0 + int hcrc = ((int)p[len + 1] << 8) | (int)p[len]; + int crc = /* XXX TODO: Compute header CRC. */; + if (crc != hcrc) + return (0); + bits += 16; +#endif + len += 2; + } + + if (pbits != NULL) + *pbits = bits; + return (len); +} + +/* + * Bidder just verifies the header and returns the number of verified bits. + */ +static int +gzip_bidder_bid(struct archive_read_filter_bidder *self, + struct archive_read_filter *filter) +{ + int bits_checked; + + (void)self; /* UNUSED */ + + if (peek_at_header(filter, &bits_checked, NULL)) + return (bits_checked); + return (0); +} + +#ifndef HAVE_ZLIB_H + +/* + * If we don't have the library on this system, we can't do the + * decompression directly. We can, however, try to run "gzip -d" + * in case that's available. + */ +static int +gzip_bidder_init(struct archive_read_filter *self) +{ + int r; + + r = __archive_read_program(self, "gzip -d"); + /* Note: We set the format here even if __archive_read_program() + * above fails. We do, after all, know what the format is + * even if we weren't able to read it. */ + self->code = ARCHIVE_FILTER_GZIP; + self->name = "gzip"; + return (r); +} + +#else + +static int +gzip_read_header(struct archive_read_filter *self, struct archive_entry *entry) +{ + struct private_data *state; + + state = (struct private_data *)self->data; + + /* A mtime of 0 is considered invalid/missing. */ + if (state->mtime != 0) + archive_entry_set_mtime(entry, state->mtime, 0); + + /* If the name is available, extract it. */ + if (state->name) + archive_entry_set_pathname(entry, state->name); + + return (ARCHIVE_OK); +} + +/* + * Initialize the filter object. + */ +static int +gzip_bidder_init(struct archive_read_filter *self) +{ + struct private_data *state; + static const size_t out_block_size = 64 * 1024; + void *out_block; + + self->code = ARCHIVE_FILTER_GZIP; + self->name = "gzip"; + + state = (struct private_data *)calloc(sizeof(*state), 1); + out_block = (unsigned char *)malloc(out_block_size); + if (state == NULL || out_block == NULL) { + free(out_block); + free(state); + archive_set_error(&self->archive->archive, ENOMEM, + "Can't allocate data for gzip decompression"); + return (ARCHIVE_FATAL); + } + + self->data = state; + state->out_block_size = out_block_size; + state->out_block = out_block; + self->read = gzip_filter_read; + self->skip = NULL; /* not supported */ + self->close = gzip_filter_close; +#ifdef HAVE_ZLIB_H + self->read_header = gzip_read_header; +#endif + + state->in_stream = 0; /* We're not actually within a stream yet. */ + + return (ARCHIVE_OK); +} + +static int +consume_header(struct archive_read_filter *self) +{ + struct private_data *state; + ssize_t avail; + size_t len; + int ret; + + state = (struct private_data *)self->data; + + /* If this is a real header, consume it. */ + len = peek_at_header(self->upstream, NULL, state); + if (len == 0) + return (ARCHIVE_EOF); + __archive_read_filter_consume(self->upstream, len); + + /* Initialize CRC accumulator. */ + state->crc = crc32(0L, NULL, 0); + + /* Initialize compression library. */ + state->stream.next_in = (unsigned char *)(uintptr_t) + __archive_read_filter_ahead(self->upstream, 1, &avail); + state->stream.avail_in = (uInt)avail; + ret = inflateInit2(&(state->stream), + -15 /* Don't check for zlib header */); + + /* Decipher the error code. */ + switch (ret) { + case Z_OK: + state->in_stream = 1; + return (ARCHIVE_OK); + case Z_STREAM_ERROR: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Internal error initializing compression library: " + "invalid setup parameter"); + break; + case Z_MEM_ERROR: + archive_set_error(&self->archive->archive, ENOMEM, + "Internal error initializing compression library: " + "out of memory"); + break; + case Z_VERSION_ERROR: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Internal error initializing compression library: " + "invalid library version"); + break; + default: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Internal error initializing compression library: " + " Zlib error %d", ret); + break; + } + return (ARCHIVE_FATAL); +} + +static int +consume_trailer(struct archive_read_filter *self) +{ + struct private_data *state; + const unsigned char *p; + ssize_t avail; + + state = (struct private_data *)self->data; + + state->in_stream = 0; + switch (inflateEnd(&(state->stream))) { + case Z_OK: + break; + default: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Failed to clean up gzip decompressor"); + return (ARCHIVE_FATAL); + } + + /* GZip trailer is a fixed 8 byte structure. */ + p = __archive_read_filter_ahead(self->upstream, 8, &avail); + if (p == NULL || avail == 0) + return (ARCHIVE_FATAL); + + /* XXX TODO: Verify the length and CRC. */ + + /* We've verified the trailer, so consume it now. */ + __archive_read_filter_consume(self->upstream, 8); + + return (ARCHIVE_OK); +} + +static ssize_t +gzip_filter_read(struct archive_read_filter *self, const void **p) +{ + struct private_data *state; + size_t decompressed; + ssize_t avail_in, max_in; + int ret; + + state = (struct private_data *)self->data; + + /* Empty our output buffer. */ + state->stream.next_out = state->out_block; + state->stream.avail_out = (uInt)state->out_block_size; + + /* Try to fill the output buffer. */ + while (state->stream.avail_out > 0 && !state->eof) { + /* If we're not in a stream, read a header + * and initialize the decompression library. */ + if (!state->in_stream) { + ret = consume_header(self); + if (ret == ARCHIVE_EOF) { + state->eof = 1; + break; + } + if (ret < ARCHIVE_OK) + return (ret); + } + + /* Peek at the next available data. */ + /* ZLib treats stream.next_in as const but doesn't declare + * it so, hence this ugly cast. */ + state->stream.next_in = (unsigned char *)(uintptr_t) + __archive_read_filter_ahead(self->upstream, 1, &avail_in); + if (state->stream.next_in == NULL) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "truncated gzip input"); + return (ARCHIVE_FATAL); + } + if (UINT_MAX >= SSIZE_MAX) + max_in = SSIZE_MAX; + else + max_in = UINT_MAX; + if (avail_in > max_in) + avail_in = max_in; + state->stream.avail_in = (uInt)avail_in; + + /* Decompress and consume some of that data. */ + ret = inflate(&(state->stream), 0); + switch (ret) { + case Z_OK: /* Decompressor made some progress. */ + __archive_read_filter_consume(self->upstream, + avail_in - state->stream.avail_in); + break; + case Z_STREAM_END: /* Found end of stream. */ + __archive_read_filter_consume(self->upstream, + avail_in - state->stream.avail_in); + /* Consume the stream trailer; release the + * decompression library. */ + ret = consume_trailer(self); + if (ret < ARCHIVE_OK) + return (ret); + break; + default: + /* Return an error. */ + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "gzip decompression failed"); + return (ARCHIVE_FATAL); + } + } + + /* We've read as much as we can. */ + decompressed = state->stream.next_out - state->out_block; + state->total_out += decompressed; + if (decompressed == 0) + *p = NULL; + else + *p = state->out_block; + return (decompressed); +} + +/* + * Clean up the decompressor. + */ +static int +gzip_filter_close(struct archive_read_filter *self) +{ + struct private_data *state; + int ret; + + state = (struct private_data *)self->data; + ret = ARCHIVE_OK; + + if (state->in_stream) { + switch (inflateEnd(&(state->stream))) { + case Z_OK: + break; + default: + archive_set_error(&(self->archive->archive), + ARCHIVE_ERRNO_MISC, + "Failed to clean up gzip compressor"); + ret = ARCHIVE_FATAL; + } + } + + free(state->name); + free(state->out_block); + free(state); + return (ret); +} + +#endif /* HAVE_ZLIB_H */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_lrzip.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_lrzip.c new file mode 100644 index 0000000..c82a8e2 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_lrzip.c @@ -0,0 +1,132 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); + + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_read_private.h" + +#define LRZIP_HEADER_MAGIC "LRZI" +#define LRZIP_HEADER_MAGIC_LEN 4 + +static int lrzip_bidder_bid(struct archive_read_filter_bidder *, + struct archive_read_filter *); +static int lrzip_bidder_init(struct archive_read_filter *); + + +static int +lrzip_reader_free(struct archive_read_filter_bidder *self) +{ + (void)self; /* UNUSED */ + return (ARCHIVE_OK); +} + +int +archive_read_support_filter_lrzip(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter_bidder *reader; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_filter_lrzip"); + + if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + reader->data = NULL; + reader->name = "lrzip"; + reader->bid = lrzip_bidder_bid; + reader->init = lrzip_bidder_init; + reader->options = NULL; + reader->free = lrzip_reader_free; + /* This filter always uses an external program. */ + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "Using external lrzip program for lrzip decompression"); + return (ARCHIVE_WARN); +} + +/* + * Bidder just verifies the header and returns the number of verified bits. + */ +static int +lrzip_bidder_bid(struct archive_read_filter_bidder *self, + struct archive_read_filter *filter) +{ + const unsigned char *p; + ssize_t avail, len; + int i; + + (void)self; /* UNUSED */ + /* Start by looking at the first six bytes of the header, which + * is all fixed layout. */ + len = 6; + p = __archive_read_filter_ahead(filter, len, &avail); + if (p == NULL || avail == 0) + return (0); + + if (memcmp(p, LRZIP_HEADER_MAGIC, LRZIP_HEADER_MAGIC_LEN)) + return (0); + + /* current major version is always 0, verify this */ + if (p[LRZIP_HEADER_MAGIC_LEN]) + return 0; + /* support only v0.6+ lrzip for sanity */ + i = p[LRZIP_HEADER_MAGIC_LEN + 1]; + if ((i < 6) || (i > 10)) + return 0; + + return (int)len; +} + +static int +lrzip_bidder_init(struct archive_read_filter *self) +{ + int r; + + r = __archive_read_program(self, "lrzip -d -q"); + /* Note: We set the format here even if __archive_read_program() + * above fails. We do, after all, know what the format is + * even if we weren't able to read it. */ + self->code = ARCHIVE_FILTER_LRZIP; + self->name = "lrzip"; + return (r); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_lz4.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_lz4.c new file mode 100644 index 0000000..43ee6c2 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_lz4.c @@ -0,0 +1,742 @@ +/*- + * Copyright (c) 2014 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_LZ4_H +#include +#endif + +#include "archive.h" +#include "archive_endian.h" +#include "archive_private.h" +#include "archive_read_private.h" +#include "archive_xxhash.h" + +#define LZ4_MAGICNUMBER 0x184d2204 +#define LZ4_SKIPPABLED 0x184d2a50 +#define LZ4_LEGACY 0x184c2102 + +#if defined(HAVE_LIBLZ4) +struct private_data { + enum { SELECT_STREAM, + READ_DEFAULT_STREAM, + READ_DEFAULT_BLOCK, + READ_LEGACY_STREAM, + READ_LEGACY_BLOCK, + } stage; + struct { + unsigned block_independence:1; + unsigned block_checksum:3; + unsigned stream_size:1; + unsigned stream_checksum:1; + unsigned preset_dictionary:1; + int block_maximum_size; + } flags; + int64_t stream_size; + uint32_t dict_id; + char *out_block; + size_t out_block_size; + + /* Bytes read but not yet consumed via __archive_read_consume() */ + size_t unconsumed; + size_t decoded_size; + void *xxh32_state; + + char valid; /* True = decompressor is initialized */ + char eof; /* True = found end of compressed data. */ +}; + +#define LEGACY_BLOCK_SIZE (8 * 1024 * 1024) + +/* Lz4 filter */ +static ssize_t lz4_filter_read(struct archive_read_filter *, const void **); +static int lz4_filter_close(struct archive_read_filter *); +#endif + +/* + * Note that we can detect lz4 archives even if we can't decompress + * them. (In fact, we like detecting them because we can give better + * error messages.) So the bid framework here gets compiled even + * if liblz4 is unavailable. + */ +static int lz4_reader_bid(struct archive_read_filter_bidder *, struct archive_read_filter *); +static int lz4_reader_init(struct archive_read_filter *); +static int lz4_reader_free(struct archive_read_filter_bidder *); +#if defined(HAVE_LIBLZ4) +static ssize_t lz4_filter_read_default_stream(struct archive_read_filter *, + const void **); +static ssize_t lz4_filter_read_legacy_stream(struct archive_read_filter *, + const void **); +#endif + +int +archive_read_support_filter_lz4(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter_bidder *reader; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_filter_lz4"); + + if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + reader->data = NULL; + reader->name = "lz4"; + reader->bid = lz4_reader_bid; + reader->init = lz4_reader_init; + reader->options = NULL; + reader->free = lz4_reader_free; +#if defined(HAVE_LIBLZ4) + return (ARCHIVE_OK); +#else + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "Using external lz4 program"); + return (ARCHIVE_WARN); +#endif +} + +static int +lz4_reader_free(struct archive_read_filter_bidder *self){ + (void)self; /* UNUSED */ + return (ARCHIVE_OK); +} + +/* + * Test whether we can handle this data. + * + * This logic returns zero if any part of the signature fails. It + * also tries to Do The Right Thing if a very short buffer prevents us + * from verifying as much as we would like. + */ +static int +lz4_reader_bid(struct archive_read_filter_bidder *self, + struct archive_read_filter *filter) +{ + const unsigned char *buffer; + ssize_t avail; + int bits_checked; + uint32_t number; + + (void)self; /* UNUSED */ + + /* Minimal lz4 archive is 11 bytes. */ + buffer = __archive_read_filter_ahead(filter, 11, &avail); + if (buffer == NULL) + return (0); + + /* First four bytes must be LZ4 magic numbers. */ + bits_checked = 0; + if ((number = archive_le32dec(buffer)) == LZ4_MAGICNUMBER) { + unsigned char flag, BD; + + bits_checked += 32; + /* Next follows a stream descriptor. */ + /* Descriptor Flags. */ + flag = buffer[4]; + /* A version number must be "01". */ + if (((flag & 0xc0) >> 6) != 1) + return (0); + /* A reserved bit must be "0". */ + if (flag & 2) + return (0); + bits_checked += 8; + BD = buffer[5]; + /* A block maximum size should be more than 3. */ + if (((BD & 0x70) >> 4) < 4) + return (0); + /* Reserved bits must be "0". */ + if (BD & ~0x70) + return (0); + bits_checked += 8; + } else if (number == LZ4_LEGACY) { + bits_checked += 32; + } + + return (bits_checked); +} + +#if !defined(HAVE_LIBLZ4) + +/* + * If we don't have the library on this system, we can't actually do the + * decompression. We can, however, still detect compressed archives + * and emit a useful message. + */ +static int +lz4_reader_init(struct archive_read_filter *self) +{ + int r; + + r = __archive_read_program(self, "lz4 -d -q"); + /* Note: We set the format here even if __archive_read_program() + * above fails. We do, after all, know what the format is + * even if we weren't able to read it. */ + self->code = ARCHIVE_FILTER_LZ4; + self->name = "lz4"; + return (r); +} + + +#else + +/* + * Setup the callbacks. + */ +static int +lz4_reader_init(struct archive_read_filter *self) +{ + struct private_data *state; + + self->code = ARCHIVE_FILTER_LZ4; + self->name = "lz4"; + + state = (struct private_data *)calloc(sizeof(*state), 1); + if (state == NULL) { + archive_set_error(&self->archive->archive, ENOMEM, + "Can't allocate data for lz4 decompression"); + return (ARCHIVE_FATAL); + } + + self->data = state; + state->stage = SELECT_STREAM; + self->read = lz4_filter_read; + self->skip = NULL; /* not supported */ + self->close = lz4_filter_close; + + return (ARCHIVE_OK); +} + +static int +lz4_allocate_out_block(struct archive_read_filter *self) +{ + struct private_data *state = (struct private_data *)self->data; + size_t out_block_size = state->flags.block_maximum_size; + void *out_block; + + if (!state->flags.block_independence) + out_block_size += 64 * 1024; + if (state->out_block_size < out_block_size) { + free(state->out_block); + out_block = (unsigned char *)malloc(out_block_size); + state->out_block_size = out_block_size; + if (out_block == NULL) { + archive_set_error(&self->archive->archive, ENOMEM, + "Can't allocate data for lz4 decompression"); + return (ARCHIVE_FATAL); + } + state->out_block = out_block; + } + if (!state->flags.block_independence) + memset(state->out_block, 0, 64 * 1024); + return (ARCHIVE_OK); +} + +static int +lz4_allocate_out_block_for_legacy(struct archive_read_filter *self) +{ + struct private_data *state = (struct private_data *)self->data; + size_t out_block_size = LEGACY_BLOCK_SIZE; + void *out_block; + + if (state->out_block_size < out_block_size) { + free(state->out_block); + out_block = (unsigned char *)malloc(out_block_size); + state->out_block_size = out_block_size; + if (out_block == NULL) { + archive_set_error(&self->archive->archive, ENOMEM, + "Can't allocate data for lz4 decompression"); + return (ARCHIVE_FATAL); + } + state->out_block = out_block; + } + return (ARCHIVE_OK); +} + +/* + * Return the next block of decompressed data. + */ +static ssize_t +lz4_filter_read(struct archive_read_filter *self, const void **p) +{ + struct private_data *state = (struct private_data *)self->data; + ssize_t ret; + + if (state->eof) { + *p = NULL; + return (0); + } + + __archive_read_filter_consume(self->upstream, state->unconsumed); + state->unconsumed = 0; + + switch (state->stage) { + case SELECT_STREAM: + break; + case READ_DEFAULT_STREAM: + case READ_LEGACY_STREAM: + /* Reading a lz4 stream already failed. */ + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, "Invalid sequence."); + return (ARCHIVE_FATAL); + case READ_DEFAULT_BLOCK: + ret = lz4_filter_read_default_stream(self, p); + if (ret != 0 || state->stage != SELECT_STREAM) + return ret; + break; + case READ_LEGACY_BLOCK: + ret = lz4_filter_read_legacy_stream(self, p); + if (ret != 0 || state->stage != SELECT_STREAM) + return ret; + break; + default: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, "Program error."); + return (ARCHIVE_FATAL); + break; + } + + while (state->stage == SELECT_STREAM) { + const char *read_buf; + + /* Read a magic number. */ + read_buf = __archive_read_filter_ahead(self->upstream, 4, + NULL); + if (read_buf == NULL) { + state->eof = 1; + *p = NULL; + return (0); + } + uint32_t number = archive_le32dec(read_buf); + __archive_read_filter_consume(self->upstream, 4); + if (number == LZ4_MAGICNUMBER) + return lz4_filter_read_default_stream(self, p); + else if (number == LZ4_LEGACY) + return lz4_filter_read_legacy_stream(self, p); + else if ((number & ~0xF) == LZ4_SKIPPABLED) { + read_buf = __archive_read_filter_ahead( + self->upstream, 4, NULL); + if (read_buf == NULL) { + archive_set_error( + &self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Malformed lz4 data"); + return (ARCHIVE_FATAL); + } + uint32_t skip_bytes = archive_le32dec(read_buf); + __archive_read_filter_consume(self->upstream, + 4 + skip_bytes); + } else { + /* Ignore following unrecognized data. */ + state->eof = 1; + *p = NULL; + return (0); + } + } + state->eof = 1; + *p = NULL; + return (0); +} + +static int +lz4_filter_read_descriptor(struct archive_read_filter *self) +{ + struct private_data *state = (struct private_data *)self->data; + const char *read_buf; + ssize_t bytes_remaining; + ssize_t descriptor_bytes; + unsigned char flag, bd; + unsigned int chsum, chsum_verifier; + + /* Make sure we have 2 bytes for flags. */ + read_buf = __archive_read_filter_ahead(self->upstream, 2, + &bytes_remaining); + if (read_buf == NULL) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "truncated lz4 input"); + return (ARCHIVE_FATAL); + } + + /* + Parse flags. + */ + flag = (unsigned char)read_buf[0]; + /* Verify version number. */ + if ((flag & 0xc0) != 1<<6) + goto malformed_error; + /* A reserved bit must be zero. */ + if (flag & 0x02) + goto malformed_error; + state->flags.block_independence = (flag & 0x20) != 0; + state->flags.block_checksum = (flag & 0x10)?4:0; + state->flags.stream_size = (flag & 0x08) != 0; + state->flags.stream_checksum = (flag & 0x04) != 0; + state->flags.preset_dictionary = (flag & 0x01) != 0; + + /* BD */ + bd = (unsigned char)read_buf[1]; + /* Reserved bits must be zero. */ + if (bd & 0x8f) + goto malformed_error; + /* Get a maximum block size. */ + switch (read_buf[1] >> 4) { + case 4: /* 64 KB */ + state->flags.block_maximum_size = 64 * 1024; + break; + case 5: /* 256 KB */ + state->flags.block_maximum_size = 256 * 1024; + break; + case 6: /* 1 MB */ + state->flags.block_maximum_size = 1024 * 1024; + break; + case 7: /* 4 MB */ + state->flags.block_maximum_size = 4 * 1024 * 1024; + break; + default: + goto malformed_error; + } + + /* Read the whole descriptor in a stream block. */ + descriptor_bytes = 3; + if (state->flags.stream_size) + descriptor_bytes += 8; + if (state->flags.preset_dictionary) + descriptor_bytes += 4; + if (bytes_remaining < descriptor_bytes) { + read_buf = __archive_read_filter_ahead(self->upstream, + descriptor_bytes, &bytes_remaining); + if (read_buf == NULL) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "truncated lz4 input"); + return (ARCHIVE_FATAL); + } + } + /* Check if a descriptor is corrupted */ + chsum = __archive_xxhash.XXH32(read_buf, (int)descriptor_bytes -1, 0); + chsum = (chsum >> 8) & 0xff; + chsum_verifier = read_buf[descriptor_bytes-1] & 0xff; + if (chsum != chsum_verifier) + goto malformed_error; + + __archive_read_filter_consume(self->upstream, descriptor_bytes); + + /* Make sure we have a large enough buffer for uncompressed data. */ + if (lz4_allocate_out_block(self) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + if (state->flags.stream_checksum) + state->xxh32_state = __archive_xxhash.XXH32_init(0); + + state->decoded_size = 0; + /* Success */ + return (ARCHIVE_OK); +malformed_error: + archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, + "malformed lz4 data"); + return (ARCHIVE_FATAL); +} + +static ssize_t +lz4_filter_read_data_block(struct archive_read_filter *self, const void **p) +{ + struct private_data *state = (struct private_data *)self->data; + ssize_t compressed_size; + const char *read_buf; + ssize_t bytes_remaining; + int checksum_size; + ssize_t uncompressed_size; + size_t prefix64k; + + *p = NULL; + + /* Make sure we have 4 bytes for a block size. */ + read_buf = __archive_read_filter_ahead(self->upstream, 4, + &bytes_remaining); + if (read_buf == NULL) + goto truncated_error; + compressed_size = archive_le32dec(read_buf); + if ((compressed_size & 0x7fffffff) > state->flags.block_maximum_size) + goto malformed_error; + /* A compressed size == 0 means the end of stream blocks. */ + if (compressed_size == 0) { + __archive_read_filter_consume(self->upstream, 4); + return 0; + } + + checksum_size = state->flags.block_checksum; + /* Check if the block is uncompressed. */ + if (compressed_size & 0x80000000U) { + compressed_size &= 0x7fffffff; + uncompressed_size = compressed_size; + } else + uncompressed_size = 0;/* Unknown yet. */ + + /* + Unfortunately, lz4 decompression API requires a whole block + for its decompression speed, so we read a whole block and allocate + a huge buffer used for decoded data. + */ + read_buf = __archive_read_filter_ahead(self->upstream, + 4 + compressed_size + checksum_size, &bytes_remaining); + if (read_buf == NULL) + goto truncated_error; + + /* Optional processing, checking a block sum. */ + if (checksum_size) { + unsigned int chsum = __archive_xxhash.XXH32( + read_buf + 4, (int)compressed_size, 0); + unsigned int chsum_block = + archive_le32dec(read_buf + 4 + compressed_size); + if (chsum != chsum_block) + goto malformed_error; + } + + + /* If the block is uncompressed, there is nothing to do. */ + if (uncompressed_size) { + /* Prepare a prefix 64k block for next block. */ + if (!state->flags.block_independence) { + prefix64k = 64 * 1024; + if (uncompressed_size < (ssize_t)prefix64k) { + memcpy(state->out_block + + prefix64k - uncompressed_size, + read_buf + 4, + uncompressed_size); + memset(state->out_block, 0, + prefix64k - uncompressed_size); + } else { + memcpy(state->out_block, + read_buf + 4 + + uncompressed_size - prefix64k, + prefix64k); + } + state->decoded_size = 0; + } + state->unconsumed = 4 + uncompressed_size + checksum_size; + *p = read_buf + 4; + return uncompressed_size; + } + + /* + Decompress a block data. + */ + if (state->flags.block_independence) { + prefix64k = 0; + uncompressed_size = LZ4_decompress_safe(read_buf + 4, + state->out_block, (int)compressed_size, + state->flags.block_maximum_size); + } else { + prefix64k = 64 * 1024; + if (state->decoded_size) { + if (state->decoded_size < prefix64k) { + memmove(state->out_block + + prefix64k - state->decoded_size, + state->out_block + prefix64k, + state->decoded_size); + memset(state->out_block, 0, + prefix64k - state->decoded_size); + } else { + memmove(state->out_block, + state->out_block + state->decoded_size, + prefix64k); + } + } +#if LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 7 + uncompressed_size = LZ4_decompress_safe_usingDict( + read_buf + 4, + state->out_block + prefix64k, (int)compressed_size, + state->flags.block_maximum_size, + state->out_block, + prefix64k); +#else + uncompressed_size = LZ4_decompress_safe_withPrefix64k( + read_buf + 4, + state->out_block + prefix64k, (int)compressed_size, + state->flags.block_maximum_size); +#endif + } + + /* Check if an error occurred in the decompression process. */ + if (uncompressed_size < 0) { + archive_set_error(&(self->archive->archive), + ARCHIVE_ERRNO_MISC, "lz4 decompression failed"); + return (ARCHIVE_FATAL); + } + + state->unconsumed = 4 + compressed_size + checksum_size; + *p = state->out_block + prefix64k; + state->decoded_size = uncompressed_size; + return uncompressed_size; + +malformed_error: + archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, + "malformed lz4 data"); + return (ARCHIVE_FATAL); +truncated_error: + archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, + "truncated lz4 input"); + return (ARCHIVE_FATAL); +} + +static ssize_t +lz4_filter_read_default_stream(struct archive_read_filter *self, const void **p) +{ + struct private_data *state = (struct private_data *)self->data; + const char *read_buf; + ssize_t bytes_remaining; + ssize_t ret; + + if (state->stage == SELECT_STREAM) { + state->stage = READ_DEFAULT_STREAM; + /* First, read a descriptor. */ + if((ret = lz4_filter_read_descriptor(self)) != ARCHIVE_OK) + return (ret); + state->stage = READ_DEFAULT_BLOCK; + } + /* Decompress a block. */ + ret = lz4_filter_read_data_block(self, p); + + /* If the end of block is detected, change the filter status + to read next stream. */ + if (ret == 0 && *p == NULL) + state->stage = SELECT_STREAM; + + /* Optional processing, checking a stream sum. */ + if (state->flags.stream_checksum) { + if (state->stage == SELECT_STREAM) { + unsigned int checksum; + unsigned int checksum_stream; + read_buf = __archive_read_filter_ahead(self->upstream, + 4, &bytes_remaining); + if (read_buf == NULL) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, "truncated lz4 input"); + return (ARCHIVE_FATAL); + } + checksum = archive_le32dec(read_buf); + __archive_read_filter_consume(self->upstream, 4); + checksum_stream = __archive_xxhash.XXH32_digest( + state->xxh32_state); + state->xxh32_state = NULL; + if (checksum != checksum_stream) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "lz4 stream checksum error"); + return (ARCHIVE_FATAL); + } + } else if (ret > 0) + __archive_xxhash.XXH32_update(state->xxh32_state, + *p, (int)ret); + } + return (ret); +} + +static ssize_t +lz4_filter_read_legacy_stream(struct archive_read_filter *self, const void **p) +{ + struct private_data *state = (struct private_data *)self->data; + uint32_t compressed; + const char *read_buf; + ssize_t ret; + + *p = NULL; + ret = lz4_allocate_out_block_for_legacy(self); + if (ret != ARCHIVE_OK) + return ret; + + /* Make sure we have 4 bytes for a block size. */ + read_buf = __archive_read_filter_ahead(self->upstream, 4, NULL); + if (read_buf == NULL) { + if (state->stage == SELECT_STREAM) { + state->stage = READ_LEGACY_STREAM; + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "truncated lz4 input"); + return (ARCHIVE_FATAL); + } + state->stage = SELECT_STREAM; + return 0; + } + state->stage = READ_LEGACY_BLOCK; + compressed = archive_le32dec(read_buf); + if (compressed > LZ4_COMPRESSBOUND(LEGACY_BLOCK_SIZE)) { + state->stage = SELECT_STREAM; + return 0; + } + + /* Make sure we have a whole block. */ + read_buf = __archive_read_filter_ahead(self->upstream, + 4 + compressed, NULL); + if (read_buf == NULL) { + archive_set_error(&(self->archive->archive), + ARCHIVE_ERRNO_MISC, "truncated lz4 input"); + return (ARCHIVE_FATAL); + } + ret = LZ4_decompress_safe(read_buf + 4, state->out_block, + compressed, (int)state->out_block_size); + if (ret < 0) { + archive_set_error(&(self->archive->archive), + ARCHIVE_ERRNO_MISC, "lz4 decompression failed"); + return (ARCHIVE_FATAL); + } + *p = state->out_block; + state->unconsumed = 4 + compressed; + return ret; +} + +/* + * Clean up the decompressor. + */ +static int +lz4_filter_close(struct archive_read_filter *self) +{ + struct private_data *state; + int ret = ARCHIVE_OK; + + state = (struct private_data *)self->data; + free(state->xxh32_state); + free(state->out_block); + free(state); + return (ret); +} + +#endif /* HAVE_LIBLZ4 */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_lzop.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_lzop.c new file mode 100644 index 0000000..a1c392f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_lzop.c @@ -0,0 +1,494 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_LZO_LZOCONF_H +#include +#endif +#ifdef HAVE_LZO_LZO1X_H +#include +#endif +#ifdef HAVE_ZLIB_H +#include /* for crc32 and adler32 */ +#endif + +#include "archive.h" +#if !defined(HAVE_ZLIB_H) &&\ + defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) +#include "archive_crc32.h" +#endif +#include "archive_endian.h" +#include "archive_private.h" +#include "archive_read_private.h" + +#ifndef HAVE_ZLIB_H +#define adler32 lzo_adler32 +#endif + +#define LZOP_HEADER_MAGIC "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a" +#define LZOP_HEADER_MAGIC_LEN 9 + +#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) +struct read_lzop { + unsigned char *out_block; + size_t out_block_size; + int64_t total_out; + int flags; + uint32_t compressed_cksum; + uint32_t uncompressed_cksum; + size_t compressed_size; + size_t uncompressed_size; + size_t unconsumed_bytes; + char in_stream; + char eof; /* True = found end of compressed data. */ +}; + +#define FILTER 0x0800 +#define CRC32_HEADER 0x1000 +#define EXTRA_FIELD 0x0040 +#define ADLER32_UNCOMPRESSED 0x0001 +#define ADLER32_COMPRESSED 0x0002 +#define CRC32_UNCOMPRESSED 0x0100 +#define CRC32_COMPRESSED 0x0200 +#define MAX_BLOCK_SIZE (64 * 1024 * 1024) + +static ssize_t lzop_filter_read(struct archive_read_filter *, const void **); +static int lzop_filter_close(struct archive_read_filter *); +#endif + +static int lzop_bidder_bid(struct archive_read_filter_bidder *, + struct archive_read_filter *); +static int lzop_bidder_init(struct archive_read_filter *); + +int +archive_read_support_filter_lzop(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter_bidder *reader; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_filter_lzop"); + + if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + reader->data = NULL; + reader->bid = lzop_bidder_bid; + reader->init = lzop_bidder_init; + reader->options = NULL; + reader->free = NULL; + /* Signal the extent of lzop support with the return value here. */ +#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) + return (ARCHIVE_OK); +#else + /* Return ARCHIVE_WARN since this always uses an external program. */ + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "Using external lzop program for lzop decompression"); + return (ARCHIVE_WARN); +#endif +} + +/* + * Bidder just verifies the header and returns the number of verified bits. + */ +static int +lzop_bidder_bid(struct archive_read_filter_bidder *self, + struct archive_read_filter *filter) +{ + const unsigned char *p; + ssize_t avail; + + (void)self; /* UNUSED */ + + p = __archive_read_filter_ahead(filter, LZOP_HEADER_MAGIC_LEN, &avail); + if (p == NULL || avail == 0) + return (0); + + if (memcmp(p, LZOP_HEADER_MAGIC, LZOP_HEADER_MAGIC_LEN)) + return (0); + + return (LZOP_HEADER_MAGIC_LEN * 8); +} + +#if !defined(HAVE_LZO_LZOCONF_H) || !defined(HAVE_LZO_LZO1X_H) +/* + * If we don't have the library on this system, we can't do the + * decompression directly. We can, however, try to run "lzop -d" + * in case that's available. + */ +static int +lzop_bidder_init(struct archive_read_filter *self) +{ + int r; + + r = __archive_read_program(self, "lzop -d"); + /* Note: We set the format here even if __archive_read_program() + * above fails. We do, after all, know what the format is + * even if we weren't able to read it. */ + self->code = ARCHIVE_FILTER_LZOP; + self->name = "lzop"; + return (r); +} +#else +/* + * Initialize the filter object. + */ +static int +lzop_bidder_init(struct archive_read_filter *self) +{ + struct read_lzop *state; + + self->code = ARCHIVE_FILTER_LZOP; + self->name = "lzop"; + + state = (struct read_lzop *)calloc(sizeof(*state), 1); + if (state == NULL) { + archive_set_error(&self->archive->archive, ENOMEM, + "Can't allocate data for lzop decompression"); + return (ARCHIVE_FATAL); + } + + self->data = state; + self->read = lzop_filter_read; + self->skip = NULL; /* not supported */ + self->close = lzop_filter_close; + + return (ARCHIVE_OK); +} + +static int +consume_header(struct archive_read_filter *self) +{ + struct read_lzop *state = (struct read_lzop *)self->data; + const unsigned char *p, *_p; + unsigned checksum, flags, len, method, version; + + /* + * Check LZOP magic code. + */ + p = __archive_read_filter_ahead(self->upstream, + LZOP_HEADER_MAGIC_LEN, NULL); + if (p == NULL) + return (ARCHIVE_EOF); + + if (memcmp(p, LZOP_HEADER_MAGIC, LZOP_HEADER_MAGIC_LEN)) + return (ARCHIVE_EOF); + __archive_read_filter_consume(self->upstream, + LZOP_HEADER_MAGIC_LEN); + + p = __archive_read_filter_ahead(self->upstream, 29, NULL); + if (p == NULL) + goto truncated; + _p = p; + version = archive_be16dec(p); + p += 4;/* version(2 bytes) + library version(2 bytes) */ + + if (version >= 0x940) { + unsigned reqversion = archive_be16dec(p); p += 2; + if (reqversion < 0x900) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, "Invalid required version"); + return (ARCHIVE_FAILED); + } + } + + method = *p++; + if (method < 1 || method > 3) { + archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, + "Unsupported method"); + return (ARCHIVE_FAILED); + } + + if (version >= 0x940) { + unsigned level = *p++; +#if 0 + unsigned default_level[] = {0, 3, 1, 9}; +#endif + if (level == 0) + /* Method is 1..3 here due to check above. */ +#if 0 /* Avoid an error Clang Static Analyzer claims + "Value stored to 'level' is never read". */ + level = default_level[method]; +#else + ;/* NOP */ +#endif + else if (level > 9) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, "Invalid level"); + return (ARCHIVE_FAILED); + } + } + + flags = archive_be32dec(p); p += 4; + + if (flags & FILTER) + p += 4; /* Skip filter */ + p += 4; /* Skip mode */ + if (version >= 0x940) + p += 8; /* Skip mtime */ + else + p += 4; /* Skip mtime */ + len = *p++; /* Read filename length */ + len += p - _p; + /* Make sure we have all bytes we need to calculate checksum. */ + p = __archive_read_filter_ahead(self->upstream, len + 4, NULL); + if (p == NULL) + goto truncated; + if (flags & CRC32_HEADER) + checksum = crc32(crc32(0, NULL, 0), p, len); + else + checksum = adler32(adler32(0, NULL, 0), p, len); + if (archive_be32dec(p + len) != checksum) + goto corrupted; + __archive_read_filter_consume(self->upstream, len + 4); + if (flags & EXTRA_FIELD) { + /* Skip extra field */ + p = __archive_read_filter_ahead(self->upstream, 4, NULL); + if (p == NULL) + goto truncated; + len = archive_be32dec(p); + __archive_read_filter_consume(self->upstream, len + 4 + 4); + } + state->flags = flags; + state->in_stream = 1; + return (ARCHIVE_OK); +truncated: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data"); + return (ARCHIVE_FAILED); +corrupted: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Corrupted lzop header"); + return (ARCHIVE_FAILED); +} + +static int +consume_block_info(struct archive_read_filter *self) +{ + struct read_lzop *state = (struct read_lzop *)self->data; + const unsigned char *p; + unsigned flags = state->flags; + + p = __archive_read_filter_ahead(self->upstream, 4, NULL); + if (p == NULL) + goto truncated; + state->uncompressed_size = archive_be32dec(p); + __archive_read_filter_consume(self->upstream, 4); + if (state->uncompressed_size == 0) + return (ARCHIVE_EOF); + if (state->uncompressed_size > MAX_BLOCK_SIZE) + goto corrupted; + + p = __archive_read_filter_ahead(self->upstream, 4, NULL); + if (p == NULL) + goto truncated; + state->compressed_size = archive_be32dec(p); + __archive_read_filter_consume(self->upstream, 4); + if (state->compressed_size > state->uncompressed_size) + goto corrupted; + + if (flags & (CRC32_UNCOMPRESSED | ADLER32_UNCOMPRESSED)) { + p = __archive_read_filter_ahead(self->upstream, 4, NULL); + if (p == NULL) + goto truncated; + state->compressed_cksum = state->uncompressed_cksum = + archive_be32dec(p); + __archive_read_filter_consume(self->upstream, 4); + } + if ((flags & (CRC32_COMPRESSED | ADLER32_COMPRESSED)) && + state->compressed_size < state->uncompressed_size) { + p = __archive_read_filter_ahead(self->upstream, 4, NULL); + if (p == NULL) + goto truncated; + state->compressed_cksum = archive_be32dec(p); + __archive_read_filter_consume(self->upstream, 4); + } + return (ARCHIVE_OK); +truncated: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data"); + return (ARCHIVE_FAILED); +corrupted: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Corrupted lzop header"); + return (ARCHIVE_FAILED); +} + +static ssize_t +lzop_filter_read(struct archive_read_filter *self, const void **p) +{ + struct read_lzop *state = (struct read_lzop *)self->data; + const void *b; + lzo_uint out_size; + uint32_t cksum; + int ret, r; + + if (state->unconsumed_bytes) { + __archive_read_filter_consume(self->upstream, + state->unconsumed_bytes); + state->unconsumed_bytes = 0; + } + if (state->eof) + return (0); + + for (;;) { + if (!state->in_stream) { + ret = consume_header(self); + if (ret < ARCHIVE_OK) + return (ret); + if (ret == ARCHIVE_EOF) { + state->eof = 1; + return (0); + } + } + ret = consume_block_info(self); + if (ret < ARCHIVE_OK) + return (ret); + if (ret == ARCHIVE_EOF) + state->in_stream = 0; + else + break; + } + + if (state->out_block == NULL || + state->out_block_size < state->uncompressed_size) { + void *new_block; + + new_block = realloc(state->out_block, state->uncompressed_size); + if (new_block == NULL) { + archive_set_error(&self->archive->archive, ENOMEM, + "Can't allocate data for lzop decompression"); + return (ARCHIVE_FATAL); + } + state->out_block = new_block; + state->out_block_size = state->uncompressed_size; + } + + b = __archive_read_filter_ahead(self->upstream, + state->compressed_size, NULL); + if (b == NULL) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data"); + return (ARCHIVE_FATAL); + } + if (state->flags & CRC32_COMPRESSED) + cksum = crc32(crc32(0, NULL, 0), b, state->compressed_size); + else if (state->flags & ADLER32_COMPRESSED) + cksum = adler32(adler32(0, NULL, 0), b, state->compressed_size); + else + cksum = state->compressed_cksum; + if (cksum != state->compressed_cksum) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, "Corrupted data"); + return (ARCHIVE_FATAL); + } + + /* + * If the both uncompressed size and compressed size are the same, + * we do not decompress this block. + */ + if (state->uncompressed_size == state->compressed_size) { + *p = b; + state->total_out += state->compressed_size; + state->unconsumed_bytes = state->compressed_size; + return ((ssize_t)state->uncompressed_size); + } + + /* + * Drive lzo uncompression. + */ + out_size = (lzo_uint)state->uncompressed_size; + r = lzo1x_decompress_safe(b, (lzo_uint)state->compressed_size, + state->out_block, &out_size, NULL); + switch (r) { + case LZO_E_OK: + if (out_size == state->uncompressed_size) + break; + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, "Corrupted data"); + return (ARCHIVE_FATAL); + case LZO_E_OUT_OF_MEMORY: + archive_set_error(&self->archive->archive, ENOMEM, + "lzop decompression failed: out of memory"); + return (ARCHIVE_FATAL); + default: + archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, + "lzop decompression failed: %d", r); + return (ARCHIVE_FATAL); + } + + if (state->flags & CRC32_UNCOMPRESSED) + cksum = crc32(crc32(0, NULL, 0), state->out_block, + state->uncompressed_size); + else if (state->flags & ADLER32_UNCOMPRESSED) + cksum = adler32(adler32(0, NULL, 0), state->out_block, + state->uncompressed_size); + else + cksum = state->uncompressed_cksum; + if (cksum != state->uncompressed_cksum) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, "Corrupted data"); + return (ARCHIVE_FATAL); + } + + __archive_read_filter_consume(self->upstream, state->compressed_size); + *p = state->out_block; + state->total_out += out_size; + return ((ssize_t)out_size); +} + +/* + * Clean up the decompressor. + */ +static int +lzop_filter_close(struct archive_read_filter *self) +{ + struct read_lzop *state = (struct read_lzop *)self->data; + + free(state->out_block); + free(state); + return (ARCHIVE_OK); +} + +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_none.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_none.c new file mode 100644 index 0000000..95e5cfd --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_none.c @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#include "archive.h" +#include "archive_private.h" + +#if ARCHIVE_VERSION_NUMBER < 4000000 +/* Deprecated; remove in libarchive 4.0 */ +int +archive_read_support_compression_none(struct archive *a) +{ + return archive_read_support_filter_none(a); +} +#endif + +/* + * Uncompressed streams are handled implicitly by the read core, + * so this is now a no-op. + */ +int +archive_read_support_filter_none(struct archive *a) +{ + archive_check_magic(a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_filter_none"); + + return (ARCHIVE_OK); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_program.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_program.c new file mode 100644 index 0000000..b8bf128 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_program.c @@ -0,0 +1,518 @@ +/*- + * Copyright (c) 2007 Joerg Sonnenberger + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_SYS_WAIT_H +# include +#endif +#ifdef HAVE_ERRNO_H +# include +#endif +#ifdef HAVE_FCNTL_H +# include +#endif +#ifdef HAVE_LIMITS_H +# include +#endif +#ifdef HAVE_SIGNAL_H +# include +#endif +#ifdef HAVE_STDLIB_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_string.h" +#include "archive_read_private.h" +#include "filter_fork.h" + + +#if ARCHIVE_VERSION_NUMBER < 4000000 +/* Deprecated; remove in libarchive 4.0 */ +int +archive_read_support_compression_program(struct archive *a, const char *cmd) +{ + return archive_read_support_filter_program(a, cmd); +} + +int +archive_read_support_compression_program_signature(struct archive *a, + const char *cmd, const void *signature, size_t signature_len) +{ + return archive_read_support_filter_program_signature(a, + cmd, signature, signature_len); +} +#endif + +int +archive_read_support_filter_program(struct archive *a, const char *cmd) +{ + return (archive_read_support_filter_program_signature(a, cmd, NULL, 0)); +} + +/* + * The bidder object stores the command and the signature to watch for. + * The 'inhibit' entry here is used to ensure that unchecked filters never + * bid twice in the same pipeline. + */ +struct program_bidder { + char *description; + char *cmd; + void *signature; + size_t signature_len; + int inhibit; +}; + +static int program_bidder_bid(struct archive_read_filter_bidder *, + struct archive_read_filter *upstream); +static int program_bidder_init(struct archive_read_filter *); +static int program_bidder_free(struct archive_read_filter_bidder *); + +/* + * The actual filter needs to track input and output data. + */ +struct program_filter { + struct archive_string description; +#if defined(_WIN32) && !defined(__CYGWIN__) + HANDLE child; +#else + pid_t child; +#endif + int exit_status; + int waitpid_return; + int child_stdin, child_stdout; + + char *out_buf; + size_t out_buf_len; +}; + +static ssize_t program_filter_read(struct archive_read_filter *, + const void **); +static int program_filter_close(struct archive_read_filter *); +static void free_state(struct program_bidder *); + +static int +set_bidder_signature(struct archive_read_filter_bidder *bidder, + struct program_bidder *state, const void *signature, size_t signature_len) +{ + + if (signature != NULL && signature_len > 0) { + state->signature_len = signature_len; + state->signature = malloc(signature_len); + memcpy(state->signature, signature, signature_len); + } + + /* + * Fill in the bidder object. + */ + bidder->data = state; + bidder->bid = program_bidder_bid; + bidder->init = program_bidder_init; + bidder->options = NULL; + bidder->free = program_bidder_free; + return (ARCHIVE_OK); +} + +int +archive_read_support_filter_program_signature(struct archive *_a, + const char *cmd, const void *signature, size_t signature_len) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter_bidder *bidder; + struct program_bidder *state; + + /* + * Get a bidder object from the read core. + */ + if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* + * Allocate our private state. + */ + state = (struct program_bidder *)calloc(1, sizeof (*state)); + if (state == NULL) + goto memerr; + state->cmd = strdup(cmd); + if (state->cmd == NULL) + goto memerr; + + return set_bidder_signature(bidder, state, signature, signature_len); +memerr: + free_state(state); + archive_set_error(_a, ENOMEM, "Can't allocate memory"); + return (ARCHIVE_FATAL); +} + +static int +program_bidder_free(struct archive_read_filter_bidder *self) +{ + struct program_bidder *state = (struct program_bidder *)self->data; + + free_state(state); + return (ARCHIVE_OK); +} + +static void +free_state(struct program_bidder *state) +{ + + if (state) { + free(state->cmd); + free(state->signature); + free(state); + } +} + +/* + * If we do have a signature, bid only if that matches. + * + * If there's no signature, we bid INT_MAX the first time + * we're called, then never bid again. + */ +static int +program_bidder_bid(struct archive_read_filter_bidder *self, + struct archive_read_filter *upstream) +{ + struct program_bidder *state = self->data; + const char *p; + + /* If we have a signature, use that to match. */ + if (state->signature_len > 0) { + p = __archive_read_filter_ahead(upstream, + state->signature_len, NULL); + if (p == NULL) + return (0); + /* No match, so don't bid. */ + if (memcmp(p, state->signature, state->signature_len) != 0) + return (0); + return ((int)state->signature_len * 8); + } + + /* Otherwise, bid once and then never bid again. */ + if (state->inhibit) + return (0); + state->inhibit = 1; + return (INT_MAX); +} + +/* + * Shut down the child, return ARCHIVE_OK if it exited normally. + * + * Note that the return value is sticky; if we're called again, + * we won't reap the child again, but we will return the same status + * (including error message if the child came to a bad end). + */ +static int +child_stop(struct archive_read_filter *self, struct program_filter *state) +{ + /* Close our side of the I/O with the child. */ + if (state->child_stdin != -1) { + close(state->child_stdin); + state->child_stdin = -1; + } + if (state->child_stdout != -1) { + close(state->child_stdout); + state->child_stdout = -1; + } + + if (state->child != 0) { + /* Reap the child. */ + do { + state->waitpid_return + = waitpid(state->child, &state->exit_status, 0); + } while (state->waitpid_return == -1 && errno == EINTR); +#if defined(_WIN32) && !defined(__CYGWIN__) + CloseHandle(state->child); +#endif + state->child = 0; + } + + if (state->waitpid_return < 0) { + /* waitpid() failed? This is ugly. */ + archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, + "Child process exited badly"); + return (ARCHIVE_WARN); + } + +#if !defined(_WIN32) || defined(__CYGWIN__) + if (WIFSIGNALED(state->exit_status)) { +#ifdef SIGPIPE + /* If the child died because we stopped reading before + * it was done, that's okay. Some archive formats + * have padding at the end that we routinely ignore. */ + /* The alternative to this would be to add a step + * before close(child_stdout) above to read from the + * child until the child has no more to write. */ + if (WTERMSIG(state->exit_status) == SIGPIPE) + return (ARCHIVE_OK); +#endif + archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, + "Child process exited with signal %d", + WTERMSIG(state->exit_status)); + return (ARCHIVE_WARN); + } +#endif /* !_WIN32 || __CYGWIN__ */ + + if (WIFEXITED(state->exit_status)) { + if (WEXITSTATUS(state->exit_status) == 0) + return (ARCHIVE_OK); + + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Child process exited with status %d", + WEXITSTATUS(state->exit_status)); + return (ARCHIVE_WARN); + } + + return (ARCHIVE_WARN); +} + +/* + * Use select() to decide whether the child is ready for read or write. + */ +static ssize_t +child_read(struct archive_read_filter *self, char *buf, size_t buf_len) +{ + struct program_filter *state = self->data; + ssize_t ret, requested, avail; + const char *p; +#if defined(_WIN32) && !defined(__CYGWIN__) + HANDLE handle = (HANDLE)_get_osfhandle(state->child_stdout); +#endif + + requested = buf_len > SSIZE_MAX ? SSIZE_MAX : buf_len; + + for (;;) { + do { +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Avoid infinity wait. + * Note: If there is no data in the pipe, ReadFile() + * called in read() never returns and so we won't + * write remaining encoded data to the pipe. + * Note: This way may cause performance problem. + * we are looking forward to great code to resolve + * this. */ + DWORD pipe_avail = -1; + int cnt = 2; + + while (PeekNamedPipe(handle, NULL, 0, NULL, + &pipe_avail, NULL) != 0 && pipe_avail == 0 && + cnt--) + Sleep(5); + if (pipe_avail == 0) { + ret = -1; + errno = EAGAIN; + break; + } +#endif + ret = read(state->child_stdout, buf, requested); + } while (ret == -1 && errno == EINTR); + + if (ret > 0) + return (ret); + if (ret == 0 || (ret == -1 && errno == EPIPE)) + /* Child has closed its output; reap the child + * and return the status. */ + return (child_stop(self, state)); + if (ret == -1 && errno != EAGAIN) + return (-1); + + if (state->child_stdin == -1) { + /* Block until child has some I/O ready. */ + __archive_check_child(state->child_stdin, + state->child_stdout); + continue; + } + + /* Get some more data from upstream. */ + p = __archive_read_filter_ahead(self->upstream, 1, &avail); + if (p == NULL) { + close(state->child_stdin); + state->child_stdin = -1; + fcntl(state->child_stdout, F_SETFL, 0); + if (avail < 0) + return (avail); + continue; + } + + do { + ret = write(state->child_stdin, p, avail); + } while (ret == -1 && errno == EINTR); + + if (ret > 0) { + /* Consume whatever we managed to write. */ + __archive_read_filter_consume(self->upstream, ret); + } else if (ret == -1 && errno == EAGAIN) { + /* Block until child has some I/O ready. */ + __archive_check_child(state->child_stdin, + state->child_stdout); + } else { + /* Write failed. */ + close(state->child_stdin); + state->child_stdin = -1; + fcntl(state->child_stdout, F_SETFL, 0); + /* If it was a bad error, we're done; otherwise + * it was EPIPE or EOF, and we can still read + * from the child. */ + if (ret == -1 && errno != EPIPE) + return (-1); + } + } +} + +int +__archive_read_program(struct archive_read_filter *self, const char *cmd) +{ + struct program_filter *state; + static const size_t out_buf_len = 65536; + char *out_buf; + const char *prefix = "Program: "; + pid_t child; + size_t l; + + l = strlen(prefix) + strlen(cmd) + 1; + state = (struct program_filter *)calloc(1, sizeof(*state)); + out_buf = (char *)malloc(out_buf_len); + if (state == NULL || out_buf == NULL || + archive_string_ensure(&state->description, l) == NULL) { + archive_set_error(&self->archive->archive, ENOMEM, + "Can't allocate input data"); + if (state != NULL) { + archive_string_free(&state->description); + free(state); + } + free(out_buf); + return (ARCHIVE_FATAL); + } + archive_strcpy(&state->description, prefix); + archive_strcat(&state->description, cmd); + + self->code = ARCHIVE_FILTER_PROGRAM; + self->name = state->description.s; + + state->out_buf = out_buf; + state->out_buf_len = out_buf_len; + + child = __archive_create_child(cmd, &state->child_stdin, + &state->child_stdout); + if (child == -1) { + free(state->out_buf); + archive_string_free(&state->description); + free(state); + archive_set_error(&self->archive->archive, EINVAL, + "Can't initialize filter; unable to run program \"%s\"", + cmd); + return (ARCHIVE_FATAL); + } +#if defined(_WIN32) && !defined(__CYGWIN__) + state->child = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, child); + if (state->child == NULL) { + child_stop(self, state); + free(state->out_buf); + archive_string_free(&state->description); + free(state); + archive_set_error(&self->archive->archive, EINVAL, + "Can't initialize filter; unable to run program \"%s\"", + cmd); + return (ARCHIVE_FATAL); + } +#else + state->child = child; +#endif + + self->data = state; + self->read = program_filter_read; + self->skip = NULL; + self->close = program_filter_close; + + /* XXX Check that we can read at least one byte? */ + return (ARCHIVE_OK); +} + +static int +program_bidder_init(struct archive_read_filter *self) +{ + struct program_bidder *bidder_state; + + bidder_state = (struct program_bidder *)self->bidder->data; + return (__archive_read_program(self, bidder_state->cmd)); +} + +static ssize_t +program_filter_read(struct archive_read_filter *self, const void **buff) +{ + struct program_filter *state; + ssize_t bytes; + size_t total; + char *p; + + state = (struct program_filter *)self->data; + + total = 0; + p = state->out_buf; + while (state->child_stdout != -1 && total < state->out_buf_len) { + bytes = child_read(self, p, state->out_buf_len - total); + if (bytes < 0) + /* No recovery is possible if we can no longer + * read from the child. */ + return (ARCHIVE_FATAL); + if (bytes == 0) + /* We got EOF from the child. */ + break; + total += bytes; + p += bytes; + } + + *buff = state->out_buf; + return (total); +} + +static int +program_filter_close(struct archive_read_filter *self) +{ + struct program_filter *state; + int e; + + state = (struct program_filter *)self->data; + e = child_stop(self, state); + + /* Release our private data. */ + free(state->out_buf); + archive_string_free(&state->description); + free(state); + + return (e); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_rpm.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_rpm.c new file mode 100644 index 0000000..e7e58e5 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_rpm.c @@ -0,0 +1,289 @@ +/*- + * Copyright (c) 2009 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif + +#include "archive.h" +#include "archive_endian.h" +#include "archive_private.h" +#include "archive_read_private.h" + +struct rpm { + int64_t total_in; + size_t hpos; + size_t hlen; + unsigned char header[16]; + enum { + ST_LEAD, /* Skipping 'Lead' section. */ + ST_HEADER, /* Reading 'Header' section; + * first 16 bytes. */ + ST_HEADER_DATA, /* Skipping 'Header' section. */ + ST_PADDING, /* Skipping padding data after the + * 'Header' section. */ + ST_ARCHIVE /* Reading 'Archive' section. */ + } state; + int first_header; +}; +#define RPM_LEAD_SIZE 96 /* Size of 'Lead' section. */ + +static int rpm_bidder_bid(struct archive_read_filter_bidder *, + struct archive_read_filter *); +static int rpm_bidder_init(struct archive_read_filter *); + +static ssize_t rpm_filter_read(struct archive_read_filter *, + const void **); +static int rpm_filter_close(struct archive_read_filter *); + +#if ARCHIVE_VERSION_NUMBER < 4000000 +/* Deprecated; remove in libarchive 4.0 */ +int +archive_read_support_compression_rpm(struct archive *a) +{ + return archive_read_support_filter_rpm(a); +} +#endif + +int +archive_read_support_filter_rpm(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter_bidder *bidder; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_filter_rpm"); + + if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + bidder->data = NULL; + bidder->name = "rpm"; + bidder->bid = rpm_bidder_bid; + bidder->init = rpm_bidder_init; + bidder->options = NULL; + bidder->free = NULL; + return (ARCHIVE_OK); +} + +static int +rpm_bidder_bid(struct archive_read_filter_bidder *self, + struct archive_read_filter *filter) +{ + const unsigned char *b; + ssize_t avail; + int bits_checked; + + (void)self; /* UNUSED */ + + b = __archive_read_filter_ahead(filter, 8, &avail); + if (b == NULL) + return (0); + + bits_checked = 0; + /* + * Verify Header Magic Bytes : 0XED 0XAB 0XEE 0XDB + */ + if (memcmp(b, "\xED\xAB\xEE\xDB", 4) != 0) + return (0); + bits_checked += 32; + /* + * Check major version. + */ + if (b[4] != 3 && b[4] != 4) + return (0); + bits_checked += 8; + /* + * Check package type; binary or source. + */ + if (b[6] != 0) + return (0); + bits_checked += 8; + if (b[7] != 0 && b[7] != 1) + return (0); + bits_checked += 8; + + return (bits_checked); +} + +static int +rpm_bidder_init(struct archive_read_filter *self) +{ + struct rpm *rpm; + + self->code = ARCHIVE_FILTER_RPM; + self->name = "rpm"; + self->read = rpm_filter_read; + self->skip = NULL; /* not supported */ + self->close = rpm_filter_close; + + rpm = (struct rpm *)calloc(sizeof(*rpm), 1); + if (rpm == NULL) { + archive_set_error(&self->archive->archive, ENOMEM, + "Can't allocate data for rpm"); + return (ARCHIVE_FATAL); + } + + self->data = rpm; + rpm->state = ST_LEAD; + + return (ARCHIVE_OK); +} + +static ssize_t +rpm_filter_read(struct archive_read_filter *self, const void **buff) +{ + struct rpm *rpm; + const unsigned char *b; + ssize_t avail_in, total; + size_t used, n; + uint32_t section; + uint32_t bytes; + + rpm = (struct rpm *)self->data; + *buff = NULL; + total = avail_in = 0; + b = NULL; + used = 0; + do { + if (b == NULL) { + b = __archive_read_filter_ahead(self->upstream, 1, + &avail_in); + if (b == NULL) { + if (avail_in < 0) + return (ARCHIVE_FATAL); + else + break; + } + } + + switch (rpm->state) { + case ST_LEAD: + if (rpm->total_in + avail_in < RPM_LEAD_SIZE) + used += avail_in; + else { + n = (size_t)(RPM_LEAD_SIZE - rpm->total_in); + used += n; + b += n; + rpm->state = ST_HEADER; + rpm->hpos = 0; + rpm->hlen = 0; + rpm->first_header = 1; + } + break; + case ST_HEADER: + n = 16 - rpm->hpos; + if (n > avail_in - used) + n = avail_in - used; + memcpy(rpm->header+rpm->hpos, b, n); + b += n; + used += n; + rpm->hpos += n; + + if (rpm->hpos == 16) { + if (rpm->header[0] != 0x8e || + rpm->header[1] != 0xad || + rpm->header[2] != 0xe8 || + rpm->header[3] != 0x01) { + if (rpm->first_header) { + archive_set_error( + &self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Unrecoginized rpm header"); + return (ARCHIVE_FATAL); + } + rpm->state = ST_ARCHIVE; + *buff = rpm->header; + total = rpm->hpos; + break; + } + /* Calculate 'Header' length. */ + section = archive_be32dec(rpm->header+8); + bytes = archive_be32dec(rpm->header+12); + rpm->hlen = 16 + section * 16 + bytes; + rpm->state = ST_HEADER_DATA; + rpm->first_header = 0; + } + break; + case ST_HEADER_DATA: + n = rpm->hlen - rpm->hpos; + if (n > avail_in - used) + n = avail_in - used; + b += n; + used += n; + rpm->hpos += n; + if (rpm->hpos == rpm->hlen) + rpm->state = ST_PADDING; + break; + case ST_PADDING: + while (used < (size_t)avail_in) { + if (*b != 0) { + /* Read next header. */ + rpm->state = ST_HEADER; + rpm->hpos = 0; + rpm->hlen = 0; + break; + } + b++; + used++; + } + break; + case ST_ARCHIVE: + *buff = b; + total = avail_in; + used = avail_in; + break; + } + if (used == (size_t)avail_in) { + rpm->total_in += used; + __archive_read_filter_consume(self->upstream, used); + b = NULL; + used = 0; + } + } while (total == 0 && avail_in > 0); + + if (used > 0 && b != NULL) { + rpm->total_in += used; + __archive_read_filter_consume(self->upstream, used); + } + return (total); +} + +static int +rpm_filter_close(struct archive_read_filter *self) +{ + struct rpm *rpm; + + rpm = (struct rpm *)self->data; + free(rpm); + + return (ARCHIVE_OK); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_uu.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_uu.c new file mode 100644 index 0000000..67ddffb --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_uu.c @@ -0,0 +1,685 @@ +/*- + * Copyright (c) 2009-2011 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_read_private.h" + +/* Maximum lookahead during bid phase */ +#define UUENCODE_BID_MAX_READ 128*1024 /* in bytes */ + +struct uudecode { + int64_t total; + unsigned char *in_buff; +#define IN_BUFF_SIZE (1024) + int in_cnt; + size_t in_allocated; + unsigned char *out_buff; +#define OUT_BUFF_SIZE (64 * 1024) + int state; +#define ST_FIND_HEAD 0 +#define ST_READ_UU 1 +#define ST_UUEND 2 +#define ST_READ_BASE64 3 +#define ST_IGNORE 4 +}; + +static int uudecode_bidder_bid(struct archive_read_filter_bidder *, + struct archive_read_filter *filter); +static int uudecode_bidder_init(struct archive_read_filter *); + +static ssize_t uudecode_filter_read(struct archive_read_filter *, + const void **); +static int uudecode_filter_close(struct archive_read_filter *); + +#if ARCHIVE_VERSION_NUMBER < 4000000 +/* Deprecated; remove in libarchive 4.0 */ +int +archive_read_support_compression_uu(struct archive *a) +{ + return archive_read_support_filter_uu(a); +} +#endif + +int +archive_read_support_filter_uu(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter_bidder *bidder; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_filter_uu"); + + if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + bidder->data = NULL; + bidder->name = "uu"; + bidder->bid = uudecode_bidder_bid; + bidder->init = uudecode_bidder_init; + bidder->options = NULL; + bidder->free = NULL; + return (ARCHIVE_OK); +} + +static const unsigned char ascii[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\n', 0, 0, '\r', 0, 0, /* 00 - 0F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 - 3F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* 70 - 7F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */ +}; + +static const unsigned char uuchar[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 0F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 - 3F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 6F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 70 - 7F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */ +}; + +static const unsigned char base64[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 0F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, /* 20 - 2F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, /* 30 - 3F */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 50 - 5F */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 70 - 7F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */ +}; + +static const int base64num[128] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 0F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 62, 0, 0, 0, 63, /* 20 - 2F */ + 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 0, 0, 0, 0, 0, 0, /* 30 - 3F */ + 0, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, /* 40 - 4F */ + 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 0, 0, 0, 0, 0, /* 50 - 5F */ + 0, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, /* 60 - 6F */ + 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 0, 0, 0, 0, 0, /* 70 - 7F */ +}; + +static ssize_t +get_line(const unsigned char *b, ssize_t avail, ssize_t *nlsize) +{ + ssize_t len; + + len = 0; + while (len < avail) { + switch (ascii[*b]) { + case 0: /* Non-ascii character or control character. */ + if (nlsize != NULL) + *nlsize = 0; + return (-1); + case '\r': + if (avail-len > 1 && b[1] == '\n') { + if (nlsize != NULL) + *nlsize = 2; + return (len+2); + } + /* FALL THROUGH */ + case '\n': + if (nlsize != NULL) + *nlsize = 1; + return (len+1); + case 1: + b++; + len++; + break; + } + } + if (nlsize != NULL) + *nlsize = 0; + return (avail); +} + +static ssize_t +bid_get_line(struct archive_read_filter *filter, + const unsigned char **b, ssize_t *avail, ssize_t *ravail, + ssize_t *nl, size_t* nbytes_read) +{ + ssize_t len; + int quit; + + quit = 0; + if (*avail == 0) { + *nl = 0; + len = 0; + } else + len = get_line(*b, *avail, nl); + + /* + * Read bytes more while it does not reach the end of line. + */ + while (*nl == 0 && len == *avail && !quit && + *nbytes_read < UUENCODE_BID_MAX_READ) { + ssize_t diff = *ravail - *avail; + size_t nbytes_req = (*ravail+1023) & ~1023U; + ssize_t tested; + + /* Increase reading bytes if it is not enough to at least + * new two lines. */ + if (nbytes_req < (size_t)*ravail + 160) + nbytes_req <<= 1; + + *b = __archive_read_filter_ahead(filter, nbytes_req, avail); + if (*b == NULL) { + if (*ravail >= *avail) + return (0); + /* Reading bytes reaches the end of a stream. */ + *b = __archive_read_filter_ahead(filter, *avail, avail); + quit = 1; + } + *nbytes_read = *avail; + *ravail = *avail; + *b += diff; + *avail -= diff; + tested = len;/* Skip some bytes we already determinated. */ + len = get_line(*b + tested, *avail - tested, nl); + if (len >= 0) + len += tested; + } + return (len); +} + +#define UUDECODE(c) (((c) - 0x20) & 0x3f) + +static int +uudecode_bidder_bid(struct archive_read_filter_bidder *self, + struct archive_read_filter *filter) +{ + const unsigned char *b; + ssize_t avail, ravail; + ssize_t len, nl; + int l; + int firstline; + size_t nbytes_read; + + (void)self; /* UNUSED */ + + b = __archive_read_filter_ahead(filter, 1, &avail); + if (b == NULL) + return (0); + + firstline = 20; + ravail = avail; + nbytes_read = avail; + for (;;) { + len = bid_get_line(filter, &b, &avail, &ravail, &nl, &nbytes_read); + if (len < 0 || nl == 0) + return (0); /* No match found. */ + if (len - nl >= 11 && memcmp(b, "begin ", 6) == 0) + l = 6; + else if (len -nl >= 18 && memcmp(b, "begin-base64 ", 13) == 0) + l = 13; + else + l = 0; + + if (l > 0 && (b[l] < '0' || b[l] > '7' || + b[l+1] < '0' || b[l+1] > '7' || + b[l+2] < '0' || b[l+2] > '7' || b[l+3] != ' ')) + l = 0; + + b += len; + avail -= len; + if (l) + break; + firstline = 0; + + /* Do not read more than UUENCODE_BID_MAX_READ bytes */ + if (nbytes_read >= UUENCODE_BID_MAX_READ) + return (0); + } + if (!avail) + return (0); + len = bid_get_line(filter, &b, &avail, &ravail, &nl, &nbytes_read); + if (len < 0 || nl == 0) + return (0);/* There are non-ascii characters. */ + avail -= len; + + if (l == 6) { + /* "begin " */ + if (!uuchar[*b]) + return (0); + /* Get a length of decoded bytes. */ + l = UUDECODE(*b++); len--; + if (l > 45) + /* Normally, maximum length is 45(character 'M'). */ + return (0); + if (l > len - nl) + return (0); /* Line too short. */ + while (l) { + if (!uuchar[*b++]) + return (0); + --len; + --l; + } + if (len-nl == 1 && + (uuchar[*b] || /* Check sum. */ + (*b >= 'a' && *b <= 'z'))) {/* Padding data(MINIX). */ + ++b; + --len; + } + b += nl; + if (avail && uuchar[*b]) + return (firstline+30); + } else if (l == 13) { + /* "begin-base64 " */ + while (len-nl > 0) { + if (!base64[*b++]) + return (0); + --len; + } + b += nl; + + if (avail >= 5 && memcmp(b, "====\n", 5) == 0) + return (firstline+40); + if (avail >= 6 && memcmp(b, "====\r\n", 6) == 0) + return (firstline+40); + if (avail > 0 && base64[*b]) + return (firstline+30); + } + + return (0); +} + +static int +uudecode_bidder_init(struct archive_read_filter *self) +{ + struct uudecode *uudecode; + void *out_buff; + void *in_buff; + + self->code = ARCHIVE_FILTER_UU; + self->name = "uu"; + self->read = uudecode_filter_read; + self->skip = NULL; /* not supported */ + self->close = uudecode_filter_close; + + uudecode = (struct uudecode *)calloc(sizeof(*uudecode), 1); + out_buff = malloc(OUT_BUFF_SIZE); + in_buff = malloc(IN_BUFF_SIZE); + if (uudecode == NULL || out_buff == NULL || in_buff == NULL) { + archive_set_error(&self->archive->archive, ENOMEM, + "Can't allocate data for uudecode"); + free(uudecode); + free(out_buff); + free(in_buff); + return (ARCHIVE_FATAL); + } + + self->data = uudecode; + uudecode->in_buff = in_buff; + uudecode->in_cnt = 0; + uudecode->in_allocated = IN_BUFF_SIZE; + uudecode->out_buff = out_buff; + uudecode->state = ST_FIND_HEAD; + + return (ARCHIVE_OK); +} + +static int +ensure_in_buff_size(struct archive_read_filter *self, + struct uudecode *uudecode, size_t size) +{ + + if (size > uudecode->in_allocated) { + unsigned char *ptr; + size_t newsize; + + /* + * Calculate a new buffer size for in_buff. + * Increase its value until it has enough size we need. + */ + newsize = uudecode->in_allocated; + do { + if (newsize < IN_BUFF_SIZE*32) + newsize <<= 1; + else + newsize += IN_BUFF_SIZE; + } while (size > newsize); + /* Allocate the new buffer. */ + ptr = malloc(newsize); + if (ptr == NULL) { + free(ptr); + archive_set_error(&self->archive->archive, + ENOMEM, + "Can't allocate data for uudecode"); + return (ARCHIVE_FATAL); + } + /* Move the remaining data in in_buff into the new buffer. */ + if (uudecode->in_cnt) + memmove(ptr, uudecode->in_buff, uudecode->in_cnt); + /* Replace in_buff with the new buffer. */ + free(uudecode->in_buff); + uudecode->in_buff = ptr; + uudecode->in_allocated = newsize; + } + return (ARCHIVE_OK); +} + +static ssize_t +uudecode_filter_read(struct archive_read_filter *self, const void **buff) +{ + struct uudecode *uudecode; + const unsigned char *b, *d; + unsigned char *out; + ssize_t avail_in, ravail; + ssize_t used; + ssize_t total; + ssize_t len, llen, nl; + + uudecode = (struct uudecode *)self->data; + +read_more: + d = __archive_read_filter_ahead(self->upstream, 1, &avail_in); + if (d == NULL && avail_in < 0) + return (ARCHIVE_FATAL); + /* Quiet a code analyzer; make sure avail_in must be zero + * when d is NULL. */ + if (d == NULL) + avail_in = 0; + used = 0; + total = 0; + out = uudecode->out_buff; + ravail = avail_in; + if (uudecode->state == ST_IGNORE) { + used = avail_in; + goto finish; + } + if (uudecode->in_cnt) { + /* + * If there is remaining data which is saved by + * previous calling, use it first. + */ + if (ensure_in_buff_size(self, uudecode, + avail_in + uudecode->in_cnt) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + memcpy(uudecode->in_buff + uudecode->in_cnt, + d, avail_in); + d = uudecode->in_buff; + avail_in += uudecode->in_cnt; + uudecode->in_cnt = 0; + } + for (;used < avail_in; d += llen, used += llen) { + int64_t l, body; + + b = d; + len = get_line(b, avail_in - used, &nl); + if (len < 0) { + /* Non-ascii character is found. */ + if (uudecode->state == ST_FIND_HEAD && + (uudecode->total > 0 || total > 0)) { + uudecode->state = ST_IGNORE; + used = avail_in; + goto finish; + } + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Insufficient compressed data"); + return (ARCHIVE_FATAL); + } + llen = len; + if ((nl == 0) && (uudecode->state != ST_UUEND)) { + if (total == 0 && ravail <= 0) { + /* There is nothing more to read, fail */ + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Missing format data"); + return (ARCHIVE_FATAL); + } + /* + * Save remaining data which does not contain + * NL('\n','\r'). + */ + if (ensure_in_buff_size(self, uudecode, len) + != ARCHIVE_OK) + return (ARCHIVE_FATAL); + if (uudecode->in_buff != b) + memmove(uudecode->in_buff, b, len); + uudecode->in_cnt = (int)len; + if (total == 0) { + /* Do not return 0; it means end-of-file. + * We should try to read bytes more. */ + __archive_read_filter_consume( + self->upstream, ravail); + goto read_more; + } + used += len; + break; + } + switch (uudecode->state) { + default: + case ST_FIND_HEAD: + /* Do not read more than UUENCODE_BID_MAX_READ bytes */ + if (total + len >= UUENCODE_BID_MAX_READ) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid format data"); + return (ARCHIVE_FATAL); + } + if (len - nl >= 11 && memcmp(b, "begin ", 6) == 0) + l = 6; + else if (len - nl >= 18 && + memcmp(b, "begin-base64 ", 13) == 0) + l = 13; + else + l = 0; + if (l != 0 && b[l] >= '0' && b[l] <= '7' && + b[l+1] >= '0' && b[l+1] <= '7' && + b[l+2] >= '0' && b[l+2] <= '7' && b[l+3] == ' ') { + if (l == 6) + uudecode->state = ST_READ_UU; + else + uudecode->state = ST_READ_BASE64; + } + break; + case ST_READ_UU: + if (total + len * 2 > OUT_BUFF_SIZE) + goto finish; + body = len - nl; + if (!uuchar[*b] || body <= 0) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Insufficient compressed data"); + return (ARCHIVE_FATAL); + } + /* Get length of undecoded bytes of current line. */ + l = UUDECODE(*b++); + body--; + if (l > body) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Insufficient compressed data"); + return (ARCHIVE_FATAL); + } + if (l == 0) { + uudecode->state = ST_UUEND; + break; + } + while (l > 0) { + int n = 0; + + if (!uuchar[b[0]] || !uuchar[b[1]]) + break; + n = UUDECODE(*b++) << 18; + n |= UUDECODE(*b++) << 12; + *out++ = n >> 16; total++; + --l; + + if (l > 0) { + if (!uuchar[b[0]]) + break; + n |= UUDECODE(*b++) << 6; + *out++ = (n >> 8) & 0xFF; total++; + --l; + } + if (l > 0) { + if (!uuchar[b[0]]) + break; + n |= UUDECODE(*b++); + *out++ = n & 0xFF; total++; + --l; + } + } + if (l) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Insufficient compressed data"); + return (ARCHIVE_FATAL); + } + break; + case ST_UUEND: + if (len - nl == 3 && memcmp(b, "end ", 3) == 0) + uudecode->state = ST_FIND_HEAD; + else { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Insufficient compressed data"); + return (ARCHIVE_FATAL); + } + break; + case ST_READ_BASE64: + if (total + len * 2 > OUT_BUFF_SIZE) + goto finish; + l = len - nl; + if (l >= 3 && b[0] == '=' && b[1] == '=' && + b[2] == '=') { + uudecode->state = ST_FIND_HEAD; + break; + } + while (l > 0) { + int n = 0; + + if (!base64[b[0]] || !base64[b[1]]) + break; + n = base64num[*b++] << 18; + n |= base64num[*b++] << 12; + *out++ = n >> 16; total++; + l -= 2; + + if (l > 0) { + if (*b == '=') + break; + if (!base64[*b]) + break; + n |= base64num[*b++] << 6; + *out++ = (n >> 8) & 0xFF; total++; + --l; + } + if (l > 0) { + if (*b == '=') + break; + if (!base64[*b]) + break; + n |= base64num[*b++]; + *out++ = n & 0xFF; total++; + --l; + } + } + if (l && *b != '=') { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Insufficient compressed data"); + return (ARCHIVE_FATAL); + } + break; + } + } +finish: + if (ravail < avail_in) + used -= avail_in - ravail; + __archive_read_filter_consume(self->upstream, used); + + *buff = uudecode->out_buff; + uudecode->total += total; + return (total); +} + +static int +uudecode_filter_close(struct archive_read_filter *self) +{ + struct uudecode *uudecode; + + uudecode = (struct uudecode *)self->data; + free(uudecode->in_buff); + free(uudecode->out_buff); + free(uudecode); + + return (ARCHIVE_OK); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_xz.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_xz.c new file mode 100644 index 0000000..11807cf --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_xz.c @@ -0,0 +1,796 @@ +/*- + * Copyright (c) 2009-2011 Michihiro NAKAJIMA + * Copyright (c) 2003-2008 Tim Kientzle and Miklos Vajna + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#if HAVE_LZMA_H +#include +#endif + +#include "archive.h" +#include "archive_endian.h" +#include "archive_private.h" +#include "archive_read_private.h" + +#if HAVE_LZMA_H && HAVE_LIBLZMA + +struct private_data { + lzma_stream stream; + unsigned char *out_block; + size_t out_block_size; + int64_t total_out; + char eof; /* True = found end of compressed data. */ + char in_stream; + + /* Following variables are used for lzip only. */ + char lzip_ver; + uint32_t crc32; + int64_t member_in; + int64_t member_out; +}; + +#if LZMA_VERSION_MAJOR >= 5 +/* Effectively disable the limiter. */ +#define LZMA_MEMLIMIT UINT64_MAX +#else +/* NOTE: This needs to check memory size which running system has. */ +#define LZMA_MEMLIMIT (1U << 30) +#endif + +/* Combined lzip/lzma/xz filter */ +static ssize_t xz_filter_read(struct archive_read_filter *, const void **); +static int xz_filter_close(struct archive_read_filter *); +static int xz_lzma_bidder_init(struct archive_read_filter *); + +#endif + +/* + * Note that we can detect xz and lzma compressed files even if we + * can't decompress them. (In fact, we like detecting them because we + * can give better error messages.) So the bid framework here gets + * compiled even if no lzma library is available. + */ +static int xz_bidder_bid(struct archive_read_filter_bidder *, + struct archive_read_filter *); +static int xz_bidder_init(struct archive_read_filter *); +static int lzma_bidder_bid(struct archive_read_filter_bidder *, + struct archive_read_filter *); +static int lzma_bidder_init(struct archive_read_filter *); +static int lzip_has_member(struct archive_read_filter *); +static int lzip_bidder_bid(struct archive_read_filter_bidder *, + struct archive_read_filter *); +static int lzip_bidder_init(struct archive_read_filter *); + +#if ARCHIVE_VERSION_NUMBER < 4000000 +/* Deprecated; remove in libarchive 4.0 */ +int +archive_read_support_compression_xz(struct archive *a) +{ + return archive_read_support_filter_xz(a); +} +#endif + +int +archive_read_support_filter_xz(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter_bidder *bidder; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_filter_xz"); + + if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + bidder->data = NULL; + bidder->name = "xz"; + bidder->bid = xz_bidder_bid; + bidder->init = xz_bidder_init; + bidder->options = NULL; + bidder->free = NULL; +#if HAVE_LZMA_H && HAVE_LIBLZMA + return (ARCHIVE_OK); +#else + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "Using external xz program for xz decompression"); + return (ARCHIVE_WARN); +#endif +} + +#if ARCHIVE_VERSION_NUMBER < 4000000 +int +archive_read_support_compression_lzma(struct archive *a) +{ + return archive_read_support_filter_lzma(a); +} +#endif + +int +archive_read_support_filter_lzma(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter_bidder *bidder; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_filter_lzma"); + + if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + bidder->data = NULL; + bidder->name = "lzma"; + bidder->bid = lzma_bidder_bid; + bidder->init = lzma_bidder_init; + bidder->options = NULL; + bidder->free = NULL; +#if HAVE_LZMA_H && HAVE_LIBLZMA + return (ARCHIVE_OK); +#else + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "Using external lzma program for lzma decompression"); + return (ARCHIVE_WARN); +#endif +} + + +#if ARCHIVE_VERSION_NUMBER < 4000000 +int +archive_read_support_compression_lzip(struct archive *a) +{ + return archive_read_support_filter_lzip(a); +} +#endif + +int +archive_read_support_filter_lzip(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter_bidder *bidder; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_filter_lzip"); + + if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + bidder->data = NULL; + bidder->name = "lzip"; + bidder->bid = lzip_bidder_bid; + bidder->init = lzip_bidder_init; + bidder->options = NULL; + bidder->free = NULL; +#if HAVE_LZMA_H && HAVE_LIBLZMA + return (ARCHIVE_OK); +#else + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "Using external lzip program for lzip decompression"); + return (ARCHIVE_WARN); +#endif +} + +/* + * Test whether we can handle this data. + */ +static int +xz_bidder_bid(struct archive_read_filter_bidder *self, + struct archive_read_filter *filter) +{ + const unsigned char *buffer; + ssize_t avail; + + (void)self; /* UNUSED */ + + buffer = __archive_read_filter_ahead(filter, 6, &avail); + if (buffer == NULL) + return (0); + + /* + * Verify Header Magic Bytes : FD 37 7A 58 5A 00 + */ + if (memcmp(buffer, "\xFD\x37\x7A\x58\x5A\x00", 6) != 0) + return (0); + + return (48); +} + +/* + * Test whether we can handle this data. + * + * LZMA has a rather poor file signature. Zeros do not + * make good signature bytes as a rule, and the only non-zero byte + * here is an ASCII character. For example, an uncompressed tar + * archive whose first file is ']' would satisfy this check. It may + * be necessary to exclude LZMA from compression_all() because of + * this. Clients of libarchive would then have to explicitly enable + * LZMA checking instead of (or in addition to) compression_all() when + * they have other evidence (file name, command-line option) to go on. + */ +static int +lzma_bidder_bid(struct archive_read_filter_bidder *self, + struct archive_read_filter *filter) +{ + const unsigned char *buffer; + ssize_t avail; + uint32_t dicsize; + uint64_t uncompressed_size; + int bits_checked; + + (void)self; /* UNUSED */ + + buffer = __archive_read_filter_ahead(filter, 14, &avail); + if (buffer == NULL) + return (0); + + /* First byte of raw LZMA stream is commonly 0x5d. + * The first byte is a special number, which consists of + * three parameters of LZMA compression, a number of literal + * context bits(which is from 0 to 8, default is 3), a number + * of literal pos bits(which is from 0 to 4, default is 0), + * a number of pos bits(which is from 0 to 4, default is 2). + * The first byte is made by + * (pos bits * 5 + literal pos bit) * 9 + * literal contest bit, + * and so the default value in this field is + * (2 * 5 + 0) * 9 + 3 = 0x5d. + * lzma of LZMA SDK has options to change those parameters. + * It means a range of this field is from 0 to 224. And lzma of + * XZ Utils with option -e records 0x5e in this field. */ + /* NOTE: If this checking of the first byte increases false + * recognition, we should allow only 0x5d and 0x5e for the first + * byte of LZMA stream. */ + bits_checked = 0; + if (buffer[0] > (4 * 5 + 4) * 9 + 8) + return (0); + /* Most likely value in the first byte of LZMA stream. */ + if (buffer[0] == 0x5d || buffer[0] == 0x5e) + bits_checked += 8; + + /* Sixth through fourteenth bytes are uncompressed size, + * stored in little-endian order. `-1' means uncompressed + * size is unknown and lzma of XZ Utils always records `-1' + * in this field. */ + uncompressed_size = archive_le64dec(buffer+5); + if (uncompressed_size == (uint64_t)ARCHIVE_LITERAL_LL(-1)) + bits_checked += 64; + + /* Second through fifth bytes are dictionary size, stored in + * little-endian order. The minimum dictionary size is + * 1 << 12(4KiB) which the lzma of LZMA SDK uses with option + * -d12 and the maximum dictionary size is 1 << 27(128MiB) + * which the one uses with option -d27. + * NOTE: A comment of LZMA SDK source code says this dictionary + * range is from 1 << 12 to 1 << 30. */ + dicsize = archive_le32dec(buffer+1); + switch (dicsize) { + case 0x00001000:/* lzma of LZMA SDK option -d12. */ + case 0x00002000:/* lzma of LZMA SDK option -d13. */ + case 0x00004000:/* lzma of LZMA SDK option -d14. */ + case 0x00008000:/* lzma of LZMA SDK option -d15. */ + case 0x00010000:/* lzma of XZ Utils option -0 and -1. + * lzma of LZMA SDK option -d16. */ + case 0x00020000:/* lzma of LZMA SDK option -d17. */ + case 0x00040000:/* lzma of LZMA SDK option -d18. */ + case 0x00080000:/* lzma of XZ Utils option -2. + * lzma of LZMA SDK option -d19. */ + case 0x00100000:/* lzma of XZ Utils option -3. + * lzma of LZMA SDK option -d20. */ + case 0x00200000:/* lzma of XZ Utils option -4. + * lzma of LZMA SDK option -d21. */ + case 0x00400000:/* lzma of XZ Utils option -5. + * lzma of LZMA SDK option -d22. */ + case 0x00800000:/* lzma of XZ Utils option -6. + * lzma of LZMA SDK option -d23. */ + case 0x01000000:/* lzma of XZ Utils option -7. + * lzma of LZMA SDK option -d24. */ + case 0x02000000:/* lzma of XZ Utils option -8. + * lzma of LZMA SDK option -d25. */ + case 0x04000000:/* lzma of XZ Utils option -9. + * lzma of LZMA SDK option -d26. */ + case 0x08000000:/* lzma of LZMA SDK option -d27. */ + bits_checked += 32; + break; + default: + /* If a memory usage for encoding was not enough on + * the platform where LZMA stream was made, lzma of + * XZ Utils automatically decreased the dictionary + * size to enough memory for encoding by 1Mi bytes + * (1 << 20).*/ + if (dicsize <= 0x03F00000 && dicsize >= 0x00300000 && + (dicsize & ((1 << 20)-1)) == 0 && + bits_checked == 8 + 64) { + bits_checked += 32; + break; + } + /* Otherwise dictionary size is unlikely. But it is + * possible that someone makes lzma stream with + * liblzma/LZMA SDK in one's dictionary size. */ + return (0); + } + + /* TODO: The above test is still very weak. It would be + * good to do better. */ + + return (bits_checked); +} + +static int +lzip_has_member(struct archive_read_filter *filter) +{ + const unsigned char *buffer; + ssize_t avail; + int bits_checked; + int log2dic; + + buffer = __archive_read_filter_ahead(filter, 6, &avail); + if (buffer == NULL) + return (0); + + /* + * Verify Header Magic Bytes : 4C 5A 49 50 (`LZIP') + */ + bits_checked = 0; + if (memcmp(buffer, "LZIP", 4) != 0) + return (0); + bits_checked += 32; + + /* A version number must be 0 or 1 */ + if (buffer[4] != 0 && buffer[4] != 1) + return (0); + bits_checked += 8; + + /* Dictionary size. */ + log2dic = buffer[5] & 0x1f; + if (log2dic < 12 || log2dic > 27) + return (0); + bits_checked += 8; + + return (bits_checked); +} + +static int +lzip_bidder_bid(struct archive_read_filter_bidder *self, + struct archive_read_filter *filter) +{ + + (void)self; /* UNUSED */ + return (lzip_has_member(filter)); +} + +#if HAVE_LZMA_H && HAVE_LIBLZMA + +/* + * liblzma 4.999.7 and later support both lzma and xz streams. + */ +static int +xz_bidder_init(struct archive_read_filter *self) +{ + self->code = ARCHIVE_FILTER_XZ; + self->name = "xz"; + return (xz_lzma_bidder_init(self)); +} + +static int +lzma_bidder_init(struct archive_read_filter *self) +{ + self->code = ARCHIVE_FILTER_LZMA; + self->name = "lzma"; + return (xz_lzma_bidder_init(self)); +} + +static int +lzip_bidder_init(struct archive_read_filter *self) +{ + self->code = ARCHIVE_FILTER_LZIP; + self->name = "lzip"; + return (xz_lzma_bidder_init(self)); +} + +/* + * Set an error code and choose an error message + */ +static void +set_error(struct archive_read_filter *self, int ret) +{ + + switch (ret) { + case LZMA_STREAM_END: /* Found end of stream. */ + case LZMA_OK: /* Decompressor made some progress. */ + break; + case LZMA_MEM_ERROR: + archive_set_error(&self->archive->archive, ENOMEM, + "Lzma library error: Cannot allocate memory"); + break; + case LZMA_MEMLIMIT_ERROR: + archive_set_error(&self->archive->archive, ENOMEM, + "Lzma library error: Out of memory"); + break; + case LZMA_FORMAT_ERROR: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Lzma library error: format not recognized"); + break; + case LZMA_OPTIONS_ERROR: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Lzma library error: Invalid options"); + break; + case LZMA_DATA_ERROR: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Lzma library error: Corrupted input data"); + break; + case LZMA_BUF_ERROR: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Lzma library error: No progress is possible"); + break; + default: + /* Return an error. */ + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Lzma decompression failed: Unknown error"); + break; + } +} + +/* + * Setup the callbacks. + */ +static int +xz_lzma_bidder_init(struct archive_read_filter *self) +{ + static const size_t out_block_size = 64 * 1024; + void *out_block; + struct private_data *state; + int ret; + + state = (struct private_data *)calloc(sizeof(*state), 1); + out_block = (unsigned char *)malloc(out_block_size); + if (state == NULL || out_block == NULL) { + archive_set_error(&self->archive->archive, ENOMEM, + "Can't allocate data for xz decompression"); + free(out_block); + free(state); + return (ARCHIVE_FATAL); + } + + self->data = state; + state->out_block_size = out_block_size; + state->out_block = out_block; + self->read = xz_filter_read; + self->skip = NULL; /* not supported */ + self->close = xz_filter_close; + + state->stream.avail_in = 0; + + state->stream.next_out = state->out_block; + state->stream.avail_out = state->out_block_size; + + state->crc32 = 0; + if (self->code == ARCHIVE_FILTER_LZIP) { + /* + * We have to read a lzip header and use it to initialize + * compression library, thus we cannot initialize the + * library for lzip here. + */ + state->in_stream = 0; + return (ARCHIVE_OK); + } else + state->in_stream = 1; + + /* Initialize compression library. */ + if (self->code == ARCHIVE_FILTER_XZ) + ret = lzma_stream_decoder(&(state->stream), + LZMA_MEMLIMIT,/* memlimit */ + LZMA_CONCATENATED); + else + ret = lzma_alone_decoder(&(state->stream), + LZMA_MEMLIMIT);/* memlimit */ + + if (ret == LZMA_OK) + return (ARCHIVE_OK); + + /* Library setup failed: Choose an error message and clean up. */ + set_error(self, ret); + + free(state->out_block); + free(state); + self->data = NULL; + return (ARCHIVE_FATAL); +} + +static int +lzip_init(struct archive_read_filter *self) +{ + struct private_data *state; + const unsigned char *h; + lzma_filter filters[2]; + unsigned char props[5]; + ssize_t avail_in; + uint32_t dicsize; + int log2dic, ret; + + state = (struct private_data *)self->data; + h = __archive_read_filter_ahead(self->upstream, 6, &avail_in); + if (h == NULL) + return (ARCHIVE_FATAL); + + /* Get a version number. */ + state->lzip_ver = h[4]; + + /* + * Setup lzma property. + */ + props[0] = 0x5d; + + /* Get dictionary size. */ + log2dic = h[5] & 0x1f; + if (log2dic < 12 || log2dic > 27) + return (ARCHIVE_FATAL); + dicsize = 1U << log2dic; + if (log2dic > 12) + dicsize -= (dicsize / 16) * (h[5] >> 5); + archive_le32enc(props+1, dicsize); + + /* Consume lzip header. */ + __archive_read_filter_consume(self->upstream, 6); + state->member_in = 6; + + filters[0].id = LZMA_FILTER_LZMA1; + filters[0].options = NULL; + filters[1].id = LZMA_VLI_UNKNOWN; + filters[1].options = NULL; + + ret = lzma_properties_decode(&filters[0], NULL, props, sizeof(props)); + if (ret != LZMA_OK) { + set_error(self, ret); + return (ARCHIVE_FATAL); + } + ret = lzma_raw_decoder(&(state->stream), filters); + free(filters[0].options); + if (ret != LZMA_OK) { + set_error(self, ret); + return (ARCHIVE_FATAL); + } + return (ARCHIVE_OK); +} + +static int +lzip_tail(struct archive_read_filter *self) +{ + struct private_data *state; + const unsigned char *f; + ssize_t avail_in; + int tail; + + state = (struct private_data *)self->data; + if (state->lzip_ver == 0) + tail = 12; + else + tail = 20; + f = __archive_read_filter_ahead(self->upstream, tail, &avail_in); + if (f == NULL && avail_in < 0) + return (ARCHIVE_FATAL); + if (f == NULL || avail_in < tail) { + archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, + "Lzip: Remaining data is less bytes"); + return (ARCHIVE_FAILED); + } + + /* Check the crc32 value of the uncompressed data of the current + * member */ + if (state->crc32 != archive_le32dec(f)) { + archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, + "Lzip: CRC32 error"); + return (ARCHIVE_FAILED); + } + + /* Check the uncompressed size of the current member */ + if ((uint64_t)state->member_out != archive_le64dec(f + 4)) { + archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, + "Lzip: Uncompressed size error"); + return (ARCHIVE_FAILED); + } + + /* Check the total size of the current member */ + if (state->lzip_ver == 1 && + (uint64_t)state->member_in + tail != archive_le64dec(f + 12)) { + archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, + "Lzip: Member size error"); + return (ARCHIVE_FAILED); + } + __archive_read_filter_consume(self->upstream, tail); + + /* If current lzip data consists of multi member, try decompressing + * a next member. */ + if (lzip_has_member(self->upstream) != 0) { + state->in_stream = 0; + state->crc32 = 0; + state->member_out = 0; + state->member_in = 0; + state->eof = 0; + } + return (ARCHIVE_OK); +} + +/* + * Return the next block of decompressed data. + */ +static ssize_t +xz_filter_read(struct archive_read_filter *self, const void **p) +{ + struct private_data *state; + size_t decompressed; + ssize_t avail_in; + int ret; + + state = (struct private_data *)self->data; + + /* Empty our output buffer. */ + state->stream.next_out = state->out_block; + state->stream.avail_out = state->out_block_size; + + /* Try to fill the output buffer. */ + while (state->stream.avail_out > 0 && !state->eof) { + if (!state->in_stream) { + /* + * Initialize liblzma for lzip + */ + ret = lzip_init(self); + if (ret != ARCHIVE_OK) + return (ret); + state->in_stream = 1; + } + state->stream.next_in = + __archive_read_filter_ahead(self->upstream, 1, &avail_in); + if (state->stream.next_in == NULL && avail_in < 0) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "truncated input"); + return (ARCHIVE_FATAL); + } + state->stream.avail_in = avail_in; + + /* Decompress as much as we can in one pass. */ + ret = lzma_code(&(state->stream), + (state->stream.avail_in == 0)? LZMA_FINISH: LZMA_RUN); + switch (ret) { + case LZMA_STREAM_END: /* Found end of stream. */ + state->eof = 1; + /* FALL THROUGH */ + case LZMA_OK: /* Decompressor made some progress. */ + __archive_read_filter_consume(self->upstream, + avail_in - state->stream.avail_in); + state->member_in += + avail_in - state->stream.avail_in; + break; + default: + set_error(self, ret); + return (ARCHIVE_FATAL); + } + } + + decompressed = state->stream.next_out - state->out_block; + state->total_out += decompressed; + state->member_out += decompressed; + if (decompressed == 0) + *p = NULL; + else { + *p = state->out_block; + if (self->code == ARCHIVE_FILTER_LZIP) { + state->crc32 = lzma_crc32(state->out_block, + decompressed, state->crc32); + if (state->eof) { + ret = lzip_tail(self); + if (ret != ARCHIVE_OK) + return (ret); + } + } + } + return (decompressed); +} + +/* + * Clean up the decompressor. + */ +static int +xz_filter_close(struct archive_read_filter *self) +{ + struct private_data *state; + + state = (struct private_data *)self->data; + lzma_end(&(state->stream)); + free(state->out_block); + free(state); + return (ARCHIVE_OK); +} + +#else + +/* + * + * If we have no suitable library on this system, we can't actually do + * the decompression. We can, however, still detect compressed + * archives and emit a useful message. + * + */ +static int +lzma_bidder_init(struct archive_read_filter *self) +{ + int r; + + r = __archive_read_program(self, "lzma -d -qq"); + /* Note: We set the format here even if __archive_read_program() + * above fails. We do, after all, know what the format is + * even if we weren't able to read it. */ + self->code = ARCHIVE_FILTER_LZMA; + self->name = "lzma"; + return (r); +} + +static int +xz_bidder_init(struct archive_read_filter *self) +{ + int r; + + r = __archive_read_program(self, "xz -d -qq"); + /* Note: We set the format here even if __archive_read_program() + * above fails. We do, after all, know what the format is + * even if we weren't able to read it. */ + self->code = ARCHIVE_FILTER_XZ; + self->name = "xz"; + return (r); +} + +static int +lzip_bidder_init(struct archive_read_filter *self) +{ + int r; + + r = __archive_read_program(self, "lzip -d -q"); + /* Note: We set the format here even if __archive_read_program() + * above fails. We do, after all, know what the format is + * even if we weren't able to read it. */ + self->code = ARCHIVE_FILTER_LZIP; + self->name = "lzip"; + return (r); +} + +#endif /* HAVE_LZMA_H */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_zstd.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_zstd.c new file mode 100644 index 0000000..c8bb36b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_filter_zstd.c @@ -0,0 +1,292 @@ +/*- + * Copyright (c) 2009-2011 Sean Purcell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif + +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#if HAVE_ZSTD_H +#include +#endif + +#include "archive.h" +#include "archive_endian.h" +#include "archive_private.h" +#include "archive_read_private.h" + +#if HAVE_ZSTD_H && HAVE_LIBZSTD + +struct private_data { + ZSTD_DStream *dstream; + unsigned char *out_block; + size_t out_block_size; + int64_t total_out; + char in_frame; /* True = in the middle of a zstd frame. */ + char eof; /* True = found end of compressed data. */ +}; + +/* Zstd Filter. */ +static ssize_t zstd_filter_read(struct archive_read_filter *, const void**); +static int zstd_filter_close(struct archive_read_filter *); +#endif + +/* + * Note that we can detect zstd compressed files even if we can't decompress + * them. (In fact, we like detecting them because we can give better error + * messages.) So the bid framework here gets compiled even if no zstd library + * is available. + */ +static int zstd_bidder_bid(struct archive_read_filter_bidder *, + struct archive_read_filter *); +static int zstd_bidder_init(struct archive_read_filter *); + +int +archive_read_support_filter_zstd(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter_bidder *bidder; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_filter_zstd"); + + if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + bidder->data = NULL; + bidder->name = "zstd"; + bidder->bid = zstd_bidder_bid; + bidder->init = zstd_bidder_init; + bidder->options = NULL; + bidder->free = NULL; +#if HAVE_ZSTD_H && HAVE_LIBZSTD + return (ARCHIVE_OK); +#else + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "Using external zstd program for zstd decompression"); + return (ARCHIVE_WARN); +#endif +} + +/* + * Test whether we can handle this data. + */ +static int +zstd_bidder_bid(struct archive_read_filter_bidder *self, + struct archive_read_filter *filter) +{ + const unsigned char *buffer; + ssize_t avail; + unsigned prefix; + + /* Zstd frame magic values */ + const unsigned zstd_magic = 0xFD2FB528U; + + (void) self; /* UNUSED */ + + buffer = __archive_read_filter_ahead(filter, 4, &avail); + if (buffer == NULL) + return (0); + + prefix = archive_le32dec(buffer); + if (prefix == zstd_magic) + return (32); + + return (0); +} + +#if !(HAVE_ZSTD_H && HAVE_LIBZSTD) + +/* + * If we don't have the library on this system, we can't do the + * decompression directly. We can, however, try to run "zstd -d" + * in case that's available. + */ +static int +zstd_bidder_init(struct archive_read_filter *self) +{ + int r; + + r = __archive_read_program(self, "zstd -d -qq"); + /* Note: We set the format here even if __archive_read_program() + * above fails. We do, after all, know what the format is + * even if we weren't able to read it. */ + self->code = ARCHIVE_FILTER_ZSTD; + self->name = "zstd"; + return (r); +} + +#else + +/* + * Initialize the filter object + */ +static int +zstd_bidder_init(struct archive_read_filter *self) +{ + struct private_data *state; + const size_t out_block_size = ZSTD_DStreamOutSize(); + void *out_block; + ZSTD_DStream *dstream; + + self->code = ARCHIVE_FILTER_ZSTD; + self->name = "zstd"; + + state = (struct private_data *)calloc(sizeof(*state), 1); + out_block = (unsigned char *)malloc(out_block_size); + dstream = ZSTD_createDStream(); + + if (state == NULL || out_block == NULL || dstream == NULL) { + free(out_block); + free(state); + ZSTD_freeDStream(dstream); /* supports free on NULL */ + archive_set_error(&self->archive->archive, ENOMEM, + "Can't allocate data for zstd decompression"); + return (ARCHIVE_FATAL); + } + + self->data = state; + + state->out_block_size = out_block_size; + state->out_block = out_block; + state->dstream = dstream; + self->read = zstd_filter_read; + self->skip = NULL; /* not supported */ + self->close = zstd_filter_close; + + state->eof = 0; + state->in_frame = 0; + + return (ARCHIVE_OK); +} + +static ssize_t +zstd_filter_read(struct archive_read_filter *self, const void **p) +{ + struct private_data *state; + size_t decompressed; + ssize_t avail_in; + ZSTD_outBuffer out; + ZSTD_inBuffer in; + + state = (struct private_data *)self->data; + + out = (ZSTD_outBuffer) { state->out_block, state->out_block_size, 0 }; + + /* Try to fill the output buffer. */ + while (out.pos < out.size && !state->eof) { + if (!state->in_frame) { + const size_t ret = ZSTD_initDStream(state->dstream); + if (ZSTD_isError(ret)) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Error initializing zstd decompressor: %s", + ZSTD_getErrorName(ret)); + return (ARCHIVE_FATAL); + } + } + in.src = __archive_read_filter_ahead(self->upstream, 1, + &avail_in); + if (avail_in < 0) { + return avail_in; + } + if (in.src == NULL && avail_in == 0) { + if (!state->in_frame) { + /* end of stream */ + state->eof = 1; + break; + } else { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Truncated zstd input"); + return (ARCHIVE_FATAL); + } + } + in.size = avail_in; + in.pos = 0; + + { + const size_t ret = + ZSTD_decompressStream(state->dstream, &out, &in); + + if (ZSTD_isError(ret)) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Zstd decompression failed: %s", + ZSTD_getErrorName(ret)); + return (ARCHIVE_FATAL); + } + + /* Decompressor made some progress */ + __archive_read_filter_consume(self->upstream, in.pos); + + /* ret guaranteed to be > 0 if frame isn't done yet */ + state->in_frame = (ret != 0); + } + } + + decompressed = out.pos; + state->total_out += decompressed; + if (decompressed == 0) + *p = NULL; + else + *p = state->out_block; + return (decompressed); +} + +/* + * Clean up the decompressor. + */ +static int +zstd_filter_close(struct archive_read_filter *self) +{ + struct private_data *state; + + state = (struct private_data *)self->data; + + ZSTD_freeDStream(state->dstream); + free(state->out_block); + free(state); + + return (ARCHIVE_OK); +} + +#endif /* HAVE_ZLIB_H && HAVE_LIBZSTD */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_7zip.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_7zip.c new file mode 100644 index 0000000..6ce9d1a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_7zip.c @@ -0,0 +1,3873 @@ +/*- + * Copyright (c) 2011 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_BZLIB_H +#include +#endif +#ifdef HAVE_LZMA_H +#include +#endif +#ifdef HAVE_ZLIB_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_ppmd7_private.h" +#include "archive_private.h" +#include "archive_read_private.h" +#include "archive_endian.h" + +#ifndef HAVE_ZLIB_H +#include "archive_crc32.h" +#endif + +#define _7ZIP_SIGNATURE "7z\xBC\xAF\x27\x1C" +#define SFX_MIN_ADDR 0x27000 +#define SFX_MAX_ADDR 0x60000 + + +/* + * Codec ID + */ +#define _7Z_COPY 0 +#define _7Z_LZMA 0x030101 +#define _7Z_LZMA2 0x21 +#define _7Z_DEFLATE 0x040108 +#define _7Z_BZ2 0x040202 +#define _7Z_PPMD 0x030401 +#define _7Z_DELTA 0x03 +#define _7Z_CRYPTO_MAIN_ZIP 0x06F10101 /* Main Zip crypto algo */ +#define _7Z_CRYPTO_RAR_29 0x06F10303 /* Rar29 AES-128 + (modified SHA-1) */ +#define _7Z_CRYPTO_AES_256_SHA_256 0x06F10701 /* AES-256 + SHA-256 */ + + +#define _7Z_X86 0x03030103 +#define _7Z_X86_BCJ2 0x0303011B +#define _7Z_POWERPC 0x03030205 +#define _7Z_IA64 0x03030401 +#define _7Z_ARM 0x03030501 +#define _7Z_ARMTHUMB 0x03030701 +#define _7Z_SPARC 0x03030805 + +/* + * 7-Zip header property IDs. + */ +#define kEnd 0x00 +#define kHeader 0x01 +#define kArchiveProperties 0x02 +#define kAdditionalStreamsInfo 0x03 +#define kMainStreamsInfo 0x04 +#define kFilesInfo 0x05 +#define kPackInfo 0x06 +#define kUnPackInfo 0x07 +#define kSubStreamsInfo 0x08 +#define kSize 0x09 +#define kCRC 0x0A +#define kFolder 0x0B +#define kCodersUnPackSize 0x0C +#define kNumUnPackStream 0x0D +#define kEmptyStream 0x0E +#define kEmptyFile 0x0F +#define kAnti 0x10 +#define kName 0x11 +#define kCTime 0x12 +#define kATime 0x13 +#define kMTime 0x14 +#define kAttributes 0x15 +#define kEncodedHeader 0x17 +#define kDummy 0x19 + +struct _7z_digests { + unsigned char *defineds; + uint32_t *digests; +}; + + +struct _7z_folder { + uint64_t numCoders; + struct _7z_coder { + unsigned long codec; + uint64_t numInStreams; + uint64_t numOutStreams; + uint64_t propertiesSize; + unsigned char *properties; + } *coders; + uint64_t numBindPairs; + struct { + uint64_t inIndex; + uint64_t outIndex; + } *bindPairs; + uint64_t numPackedStreams; + uint64_t *packedStreams; + uint64_t numInStreams; + uint64_t numOutStreams; + uint64_t *unPackSize; + unsigned char digest_defined; + uint32_t digest; + uint64_t numUnpackStreams; + uint32_t packIndex; + /* Unoperated bytes. */ + uint64_t skipped_bytes; +}; + +struct _7z_coders_info { + uint64_t numFolders; + struct _7z_folder *folders; + uint64_t dataStreamIndex; +}; + +struct _7z_pack_info { + uint64_t pos; + uint64_t numPackStreams; + uint64_t *sizes; + struct _7z_digests digest; + /* Calculated from pos and numPackStreams. */ + uint64_t *positions; +}; + +struct _7z_substream_info { + size_t unpack_streams; + uint64_t *unpackSizes; + unsigned char *digestsDefined; + uint32_t *digests; +}; + +struct _7z_stream_info { + struct _7z_pack_info pi; + struct _7z_coders_info ci; + struct _7z_substream_info ss; +}; + +struct _7z_header_info { + uint64_t dataIndex; + + unsigned char *emptyStreamBools; + unsigned char *emptyFileBools; + unsigned char *antiBools; + unsigned char *attrBools; +}; + +struct _7zip_entry { + size_t name_len; + unsigned char *utf16name; +#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG) + const wchar_t *wname; +#endif + uint32_t folderIndex; + uint32_t ssIndex; + unsigned flg; +#define MTIME_IS_SET (1<<0) +#define ATIME_IS_SET (1<<1) +#define CTIME_IS_SET (1<<2) +#define CRC32_IS_SET (1<<3) +#define HAS_STREAM (1<<4) + + time_t mtime; + time_t atime; + time_t ctime; + long mtime_ns; + long atime_ns; + long ctime_ns; + uint32_t mode; + uint32_t attr; +}; + +struct _7zip { + /* Structural information about the archive. */ + struct _7z_stream_info si; + + int header_is_being_read; + int header_is_encoded; + uint64_t header_bytes_remaining; + unsigned long header_crc32; + /* Header offset to check that reading points of the file contents + * will not exceed the header. */ + uint64_t header_offset; + /* Base offset of the archive file for a seek in case reading SFX. */ + uint64_t seek_base; + + /* List of entries */ + size_t entries_remaining; + uint64_t numFiles; + struct _7zip_entry *entries; + struct _7zip_entry *entry; + unsigned char *entry_names; + + /* entry_bytes_remaining is the number of bytes we expect. */ + int64_t entry_offset; + uint64_t entry_bytes_remaining; + + /* Running CRC32 of the decompressed data */ + unsigned long entry_crc32; + + /* Flags to mark progress of decompression. */ + char end_of_entry; + + /* Uncompressed buffer control. */ +#define UBUFF_SIZE (64 * 1024) + unsigned char *uncompressed_buffer; + unsigned char *uncompressed_buffer_pointer; + size_t uncompressed_buffer_size; + size_t uncompressed_buffer_bytes_remaining; + + /* Offset of the compressed data. */ + int64_t stream_offset; + + /* + * Decompressing control data. + */ + unsigned folder_index; + uint64_t folder_outbytes_remaining; + unsigned pack_stream_index; + unsigned pack_stream_remaining; + uint64_t pack_stream_inbytes_remaining; + size_t pack_stream_bytes_unconsumed; + + /* The codec information of a folder. */ + unsigned long codec; + unsigned long codec2; + + /* + * Decompressor controllers. + */ + /* Decoding LZMA1 and LZMA2 data. */ +#ifdef HAVE_LZMA_H + lzma_stream lzstream; + int lzstream_valid; +#endif + /* Decoding bzip2 data. */ +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) + bz_stream bzstream; + int bzstream_valid; +#endif + /* Decoding deflate data. */ +#ifdef HAVE_ZLIB_H + z_stream stream; + int stream_valid; +#endif + /* Decoding PPMd data. */ + int ppmd7_stat; + CPpmd7 ppmd7_context; + CPpmd7z_RangeDec range_dec; + IByteIn bytein; + struct { + const unsigned char *next_in; + int64_t avail_in; + int64_t total_in; + unsigned char *next_out; + int64_t avail_out; + int64_t total_out; + int overconsumed; + } ppstream; + int ppmd7_valid; + + /* Decoding BCJ and BCJ2 data. */ + uint32_t bcj_state; + size_t odd_bcj_size; + unsigned char odd_bcj[4]; + /* Decoding BCJ data. */ + size_t bcj_prevPosT; + uint32_t bcj_prevMask; + uint32_t bcj_ip; + + /* Decoding BCJ2 data. */ + size_t main_stream_bytes_remaining; + unsigned char *sub_stream_buff[3]; + size_t sub_stream_size[3]; + size_t sub_stream_bytes_remaining[3]; + unsigned char *tmp_stream_buff; + size_t tmp_stream_buff_size; + size_t tmp_stream_bytes_avail; + size_t tmp_stream_bytes_remaining; +#ifdef _LZMA_PROB32 +#define CProb uint32_t +#else +#define CProb uint16_t +#endif + CProb bcj2_p[256 + 2]; + uint8_t bcj2_prevByte; + uint32_t bcj2_range; + uint32_t bcj2_code; + uint64_t bcj2_outPos; + + /* Filename character-set conversion data. */ + struct archive_string_conv *sconv; + + char format_name[64]; + + /* Custom value that is non-zero if this archive contains encrypted entries. */ + int has_encrypted_entries; +}; + +/* Maximum entry size. This limitation prevents reading intentional + * corrupted 7-zip files on assuming there are not so many entries in + * the files. */ +#define UMAX_ENTRY ARCHIVE_LITERAL_ULL(100000000) + +static int archive_read_format_7zip_has_encrypted_entries(struct archive_read *); +static int archive_read_support_format_7zip_capabilities(struct archive_read *a); +static int archive_read_format_7zip_bid(struct archive_read *, int); +static int archive_read_format_7zip_cleanup(struct archive_read *); +static int archive_read_format_7zip_read_data(struct archive_read *, + const void **, size_t *, int64_t *); +static int archive_read_format_7zip_read_data_skip(struct archive_read *); +static int archive_read_format_7zip_read_header(struct archive_read *, + struct archive_entry *); +static int check_7zip_header_in_sfx(const char *); +static unsigned long decode_codec_id(const unsigned char *, size_t); +static int decode_encoded_header_info(struct archive_read *, + struct _7z_stream_info *); +static int decompress(struct archive_read *, struct _7zip *, + void *, size_t *, const void *, size_t *); +static ssize_t extract_pack_stream(struct archive_read *, size_t); +static void fileTimeToUtc(uint64_t, time_t *, long *); +static uint64_t folder_uncompressed_size(struct _7z_folder *); +static void free_CodersInfo(struct _7z_coders_info *); +static void free_Digest(struct _7z_digests *); +static void free_Folder(struct _7z_folder *); +static void free_Header(struct _7z_header_info *); +static void free_PackInfo(struct _7z_pack_info *); +static void free_StreamsInfo(struct _7z_stream_info *); +static void free_SubStreamsInfo(struct _7z_substream_info *); +static int free_decompression(struct archive_read *, struct _7zip *); +static ssize_t get_uncompressed_data(struct archive_read *, const void **, + size_t, size_t); +static const unsigned char * header_bytes(struct archive_read *, size_t); +static int init_decompression(struct archive_read *, struct _7zip *, + const struct _7z_coder *, const struct _7z_coder *); +static int parse_7zip_uint64(struct archive_read *, uint64_t *); +static int read_Bools(struct archive_read *, unsigned char *, size_t); +static int read_CodersInfo(struct archive_read *, + struct _7z_coders_info *); +static int read_Digests(struct archive_read *, struct _7z_digests *, + size_t); +static int read_Folder(struct archive_read *, struct _7z_folder *); +static int read_Header(struct archive_read *, struct _7z_header_info *, + int); +static int read_PackInfo(struct archive_read *, struct _7z_pack_info *); +static int read_StreamsInfo(struct archive_read *, + struct _7z_stream_info *); +static int read_SubStreamsInfo(struct archive_read *, + struct _7z_substream_info *, struct _7z_folder *, size_t); +static int read_Times(struct archive_read *, struct _7z_header_info *, + int); +static void read_consume(struct archive_read *); +static ssize_t read_stream(struct archive_read *, const void **, size_t, + size_t); +static int seek_pack(struct archive_read *); +static int64_t skip_stream(struct archive_read *, size_t); +static int skip_sfx(struct archive_read *, ssize_t); +static int slurp_central_directory(struct archive_read *, struct _7zip *, + struct _7z_header_info *); +static int setup_decode_folder(struct archive_read *, struct _7z_folder *, + int); +static void x86_Init(struct _7zip *); +static size_t x86_Convert(struct _7zip *, uint8_t *, size_t); +static ssize_t Bcj2_Decode(struct _7zip *, uint8_t *, size_t); + + +int +archive_read_support_format_7zip(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct _7zip *zip; + int r; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_format_7zip"); + + zip = calloc(1, sizeof(*zip)); + if (zip == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate 7zip data"); + return (ARCHIVE_FATAL); + } + + /* + * Until enough data has been read, we cannot tell about + * any encrypted entries yet. + */ + zip->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW; + + + r = __archive_read_register_format(a, + zip, + "7zip", + archive_read_format_7zip_bid, + NULL, + archive_read_format_7zip_read_header, + archive_read_format_7zip_read_data, + archive_read_format_7zip_read_data_skip, + NULL, + archive_read_format_7zip_cleanup, + archive_read_support_format_7zip_capabilities, + archive_read_format_7zip_has_encrypted_entries); + + if (r != ARCHIVE_OK) + free(zip); + return (ARCHIVE_OK); +} + +static int +archive_read_support_format_7zip_capabilities(struct archive_read * a) +{ + (void)a; /* UNUSED */ + return (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA | + ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA); +} + + +static int +archive_read_format_7zip_has_encrypted_entries(struct archive_read *_a) +{ + if (_a && _a->format) { + struct _7zip * zip = (struct _7zip *)_a->format->data; + if (zip) { + return zip->has_encrypted_entries; + } + } + return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW; +} + +static int +archive_read_format_7zip_bid(struct archive_read *a, int best_bid) +{ + const char *p; + + /* If someone has already bid more than 32, then avoid + trashing the look-ahead buffers with a seek. */ + if (best_bid > 32) + return (-1); + + if ((p = __archive_read_ahead(a, 6, NULL)) == NULL) + return (0); + + /* If first six bytes are the 7-Zip signature, + * return the bid right now. */ + if (memcmp(p, _7ZIP_SIGNATURE, 6) == 0) + return (48); + + /* + * It may a 7-Zip SFX archive file. If first two bytes are + * 'M' and 'Z' available on Windows or first four bytes are + * "\x7F\x45LF" available on posix like system, seek the 7-Zip + * signature. Although we will perform a seek when reading + * a header, what we do not use __archive_read_seek() here is + * due to a bidding performance. + */ + if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) { + ssize_t offset = SFX_MIN_ADDR; + ssize_t window = 4096; + ssize_t bytes_avail; + while (offset + window <= (SFX_MAX_ADDR)) { + const char *buff = __archive_read_ahead(a, + offset + window, &bytes_avail); + if (buff == NULL) { + /* Remaining bytes are less than window. */ + window >>= 1; + if (window < 0x40) + return (0); + continue; + } + p = buff + offset; + while (p + 32 < buff + bytes_avail) { + int step = check_7zip_header_in_sfx(p); + if (step == 0) + return (48); + p += step; + } + offset = p - buff; + } + } + return (0); +} + +static int +check_7zip_header_in_sfx(const char *p) +{ + switch ((unsigned char)p[5]) { + case 0x1C: + if (memcmp(p, _7ZIP_SIGNATURE, 6) != 0) + return (6); + /* + * Test the CRC because its extraction code has 7-Zip + * Magic Code, so we should do this in order not to + * make a mis-detection. + */ + if (crc32(0, (const unsigned char *)p + 12, 20) + != archive_le32dec(p + 8)) + return (6); + /* Hit the header! */ + return (0); + case 0x37: return (5); + case 0x7A: return (4); + case 0xBC: return (3); + case 0xAF: return (2); + case 0x27: return (1); + default: return (6); + } +} + +static int +skip_sfx(struct archive_read *a, ssize_t bytes_avail) +{ + const void *h; + const char *p, *q; + size_t skip, offset; + ssize_t bytes, window; + + /* + * If bytes_avail > SFX_MIN_ADDR we do not have to call + * __archive_read_seek() at this time since we have + * already had enough data. + */ + if (bytes_avail > SFX_MIN_ADDR) + __archive_read_consume(a, SFX_MIN_ADDR); + else if (__archive_read_seek(a, SFX_MIN_ADDR, SEEK_SET) < 0) + return (ARCHIVE_FATAL); + + offset = 0; + window = 1; + while (offset + window <= SFX_MAX_ADDR - SFX_MIN_ADDR) { + h = __archive_read_ahead(a, window, &bytes); + if (h == NULL) { + /* Remaining bytes are less than window. */ + window >>= 1; + if (window < 0x40) + goto fatal; + continue; + } + if (bytes < 6) { + /* This case might happen when window == 1. */ + window = 4096; + continue; + } + p = (const char *)h; + q = p + bytes; + + /* + * Scan ahead until we find something that looks + * like the 7-Zip header. + */ + while (p + 32 < q) { + int step = check_7zip_header_in_sfx(p); + if (step == 0) { + struct _7zip *zip = + (struct _7zip *)a->format->data; + skip = p - (const char *)h; + __archive_read_consume(a, skip); + zip->seek_base = SFX_MIN_ADDR + offset + skip; + return (ARCHIVE_OK); + } + p += step; + } + skip = p - (const char *)h; + __archive_read_consume(a, skip); + offset += skip; + if (window == 1) + window = 4096; + } +fatal: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Couldn't find out 7-Zip header"); + return (ARCHIVE_FATAL); +} + +static int +archive_read_format_7zip_read_header(struct archive_read *a, + struct archive_entry *entry) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + struct _7zip_entry *zip_entry; + int r, ret = ARCHIVE_OK; + struct _7z_folder *folder = 0; + uint64_t fidx = 0; + + /* + * It should be sufficient to call archive_read_next_header() for + * a reader to determine if an entry is encrypted or not. If the + * encryption of an entry is only detectable when calling + * archive_read_data(), so be it. We'll do the same check there + * as well. + */ + if (zip->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) { + zip->has_encrypted_entries = 0; + } + + a->archive.archive_format = ARCHIVE_FORMAT_7ZIP; + if (a->archive.archive_format_name == NULL) + a->archive.archive_format_name = "7-Zip"; + + if (zip->entries == NULL) { + struct _7z_header_info header; + + memset(&header, 0, sizeof(header)); + r = slurp_central_directory(a, zip, &header); + free_Header(&header); + if (r != ARCHIVE_OK) + return (r); + zip->entries_remaining = (size_t)zip->numFiles; + zip->entry = zip->entries; + } else { + ++zip->entry; + } + zip_entry = zip->entry; + + if (zip->entries_remaining <= 0 || zip_entry == NULL) + return ARCHIVE_EOF; + --zip->entries_remaining; + + zip->entry_offset = 0; + zip->end_of_entry = 0; + zip->entry_crc32 = crc32(0, NULL, 0); + + /* Setup a string conversion for a filename. */ + if (zip->sconv == NULL) { + zip->sconv = archive_string_conversion_from_charset( + &a->archive, "UTF-16LE", 1); + if (zip->sconv == NULL) + return (ARCHIVE_FATAL); + } + + /* Figure out if the entry is encrypted by looking at the folder + that is associated to the current 7zip entry. If the folder + has a coder with a _7Z_CRYPTO codec then the folder is encrypted. + Hence the entry must also be encrypted. */ + if (zip_entry && zip_entry->folderIndex < zip->si.ci.numFolders) { + folder = &(zip->si.ci.folders[zip_entry->folderIndex]); + for (fidx=0; folder && fidxnumCoders; fidx++) { + switch(folder->coders[fidx].codec) { + case _7Z_CRYPTO_MAIN_ZIP: + case _7Z_CRYPTO_RAR_29: + case _7Z_CRYPTO_AES_256_SHA_256: { + archive_entry_set_is_data_encrypted(entry, 1); + zip->has_encrypted_entries = 1; + break; + } + } + } + } + + /* Now that we've checked for encryption, if there were still no + * encrypted entries found we can say for sure that there are none. + */ + if (zip->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) { + zip->has_encrypted_entries = 0; + } + + if (archive_entry_copy_pathname_l(entry, + (const char *)zip_entry->utf16name, + zip_entry->name_len, zip->sconv) != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Pathname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Pathname cannot be converted " + "from %s to current locale.", + archive_string_conversion_charset_name(zip->sconv)); + ret = ARCHIVE_WARN; + } + + /* Populate some additional entry fields: */ + archive_entry_set_mode(entry, zip_entry->mode); + if (zip_entry->flg & MTIME_IS_SET) + archive_entry_set_mtime(entry, zip_entry->mtime, + zip_entry->mtime_ns); + if (zip_entry->flg & CTIME_IS_SET) + archive_entry_set_ctime(entry, zip_entry->ctime, + zip_entry->ctime_ns); + if (zip_entry->flg & ATIME_IS_SET) + archive_entry_set_atime(entry, zip_entry->atime, + zip_entry->atime_ns); + if (zip_entry->ssIndex != (uint32_t)-1) { + zip->entry_bytes_remaining = + zip->si.ss.unpackSizes[zip_entry->ssIndex]; + archive_entry_set_size(entry, zip->entry_bytes_remaining); + } else { + zip->entry_bytes_remaining = 0; + archive_entry_set_size(entry, 0); + } + + /* If there's no body, force read_data() to return EOF immediately. */ + if (zip->entry_bytes_remaining < 1) + zip->end_of_entry = 1; + + if ((zip_entry->mode & AE_IFMT) == AE_IFLNK) { + unsigned char *symname = NULL; + size_t symsize = 0; + + /* + * Symbolic-name is recorded as its contents. We have to + * read the contents at this time. + */ + while (zip->entry_bytes_remaining > 0) { + const void *buff; + unsigned char *mem; + size_t size; + int64_t offset; + + r = archive_read_format_7zip_read_data(a, &buff, + &size, &offset); + if (r < ARCHIVE_WARN) { + free(symname); + return (r); + } + mem = realloc(symname, symsize + size + 1); + if (mem == NULL) { + free(symname); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Symname"); + return (ARCHIVE_FATAL); + } + symname = mem; + memcpy(symname+symsize, buff, size); + symsize += size; + } + if (symsize == 0) { + /* If there is no symname, handle it as a regular + * file. */ + zip_entry->mode &= ~AE_IFMT; + zip_entry->mode |= AE_IFREG; + archive_entry_set_mode(entry, zip_entry->mode); + } else { + symname[symsize] = '\0'; + archive_entry_copy_symlink(entry, + (const char *)symname); + } + free(symname); + archive_entry_set_size(entry, 0); + } + + /* Set up a more descriptive format name. */ + sprintf(zip->format_name, "7-Zip"); + a->archive.archive_format_name = zip->format_name; + + return (ret); +} + +static int +archive_read_format_7zip_read_data(struct archive_read *a, + const void **buff, size_t *size, int64_t *offset) +{ + struct _7zip *zip; + ssize_t bytes; + int ret = ARCHIVE_OK; + + zip = (struct _7zip *)(a->format->data); + + if (zip->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) { + zip->has_encrypted_entries = 0; + } + + if (zip->pack_stream_bytes_unconsumed) + read_consume(a); + + *offset = zip->entry_offset; + *size = 0; + *buff = NULL; + /* + * If we hit end-of-entry last time, clean up and return + * ARCHIVE_EOF this time. + */ + if (zip->end_of_entry) + return (ARCHIVE_EOF); + + bytes = read_stream(a, buff, + (size_t)zip->entry_bytes_remaining, 0); + if (bytes < 0) + return ((int)bytes); + if (bytes == 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated 7-Zip file body"); + return (ARCHIVE_FATAL); + } + zip->entry_bytes_remaining -= bytes; + if (zip->entry_bytes_remaining == 0) + zip->end_of_entry = 1; + + /* Update checksum */ + if ((zip->entry->flg & CRC32_IS_SET) && bytes) + zip->entry_crc32 = crc32(zip->entry_crc32, *buff, + (unsigned)bytes); + + /* If we hit the end, swallow any end-of-data marker. */ + if (zip->end_of_entry) { + /* Check computed CRC against file contents. */ + if ((zip->entry->flg & CRC32_IS_SET) && + zip->si.ss.digests[zip->entry->ssIndex] != + zip->entry_crc32) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "7-Zip bad CRC: 0x%lx should be 0x%lx", + (unsigned long)zip->entry_crc32, + (unsigned long)zip->si.ss.digests[ + zip->entry->ssIndex]); + ret = ARCHIVE_WARN; + } + } + + *size = bytes; + *offset = zip->entry_offset; + zip->entry_offset += bytes; + + return (ret); +} + +static int +archive_read_format_7zip_read_data_skip(struct archive_read *a) +{ + struct _7zip *zip; + int64_t bytes_skipped; + + zip = (struct _7zip *)(a->format->data); + + if (zip->pack_stream_bytes_unconsumed) + read_consume(a); + + /* If we've already read to end of data, we're done. */ + if (zip->end_of_entry) + return (ARCHIVE_OK); + + /* + * If the length is at the beginning, we can skip the + * compressed data much more quickly. + */ + bytes_skipped = skip_stream(a, (size_t)zip->entry_bytes_remaining); + if (bytes_skipped < 0) + return (ARCHIVE_FATAL); + zip->entry_bytes_remaining = 0; + + /* This entry is finished and done. */ + zip->end_of_entry = 1; + return (ARCHIVE_OK); +} + +static int +archive_read_format_7zip_cleanup(struct archive_read *a) +{ + struct _7zip *zip; + + zip = (struct _7zip *)(a->format->data); + free_StreamsInfo(&(zip->si)); + free(zip->entries); + free(zip->entry_names); + free_decompression(a, zip); + free(zip->uncompressed_buffer); + free(zip->sub_stream_buff[0]); + free(zip->sub_stream_buff[1]); + free(zip->sub_stream_buff[2]); + free(zip->tmp_stream_buff); + free(zip); + (a->format->data) = NULL; + return (ARCHIVE_OK); +} + +static void +read_consume(struct archive_read *a) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + + if (zip->pack_stream_bytes_unconsumed) { + __archive_read_consume(a, zip->pack_stream_bytes_unconsumed); + zip->stream_offset += zip->pack_stream_bytes_unconsumed; + zip->pack_stream_bytes_unconsumed = 0; + } +} + +#ifdef HAVE_LZMA_H + +/* + * Set an error code and choose an error message for liblzma. + */ +static void +set_error(struct archive_read *a, int ret) +{ + + switch (ret) { + case LZMA_STREAM_END: /* Found end of stream. */ + case LZMA_OK: /* Decompressor made some progress. */ + break; + case LZMA_MEM_ERROR: + archive_set_error(&a->archive, ENOMEM, + "Lzma library error: Cannot allocate memory"); + break; + case LZMA_MEMLIMIT_ERROR: + archive_set_error(&a->archive, ENOMEM, + "Lzma library error: Out of memory"); + break; + case LZMA_FORMAT_ERROR: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Lzma library error: format not recognized"); + break; + case LZMA_OPTIONS_ERROR: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Lzma library error: Invalid options"); + break; + case LZMA_DATA_ERROR: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Lzma library error: Corrupted input data"); + break; + case LZMA_BUF_ERROR: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Lzma library error: No progress is possible"); + break; + default: + /* Return an error. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Lzma decompression failed: Unknown error"); + break; + } +} + +#endif + +static unsigned long +decode_codec_id(const unsigned char *codecId, size_t id_size) +{ + unsigned i; + unsigned long id = 0; + + for (i = 0; i < id_size; i++) { + id <<= 8; + id += codecId[i]; + } + return (id); +} + +static Byte +ppmd_read(void *p) +{ + struct archive_read *a = ((IByteIn*)p)->a; + struct _7zip *zip = (struct _7zip *)(a->format->data); + Byte b; + + if (zip->ppstream.avail_in == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated RAR file data"); + zip->ppstream.overconsumed = 1; + return (0); + } + b = *zip->ppstream.next_in++; + zip->ppstream.avail_in--; + zip->ppstream.total_in++; + return (b); +} + +static int +init_decompression(struct archive_read *a, struct _7zip *zip, + const struct _7z_coder *coder1, const struct _7z_coder *coder2) +{ + int r; + + zip->codec = coder1->codec; + zip->codec2 = -1; + + switch (zip->codec) { + case _7Z_COPY: + case _7Z_BZ2: + case _7Z_DEFLATE: + case _7Z_PPMD: + if (coder2 != NULL) { + if (coder2->codec != _7Z_X86 && + coder2->codec != _7Z_X86_BCJ2) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Unsupported filter %lx for %lx", + coder2->codec, coder1->codec); + return (ARCHIVE_FAILED); + } + zip->codec2 = coder2->codec; + zip->bcj_state = 0; + if (coder2->codec == _7Z_X86) + x86_Init(zip); + } + break; + default: + break; + } + + switch (zip->codec) { + case _7Z_COPY: + break; + + case _7Z_LZMA: case _7Z_LZMA2: +#ifdef HAVE_LZMA_H +#if LZMA_VERSION_MAJOR >= 5 +/* Effectively disable the limiter. */ +#define LZMA_MEMLIMIT UINT64_MAX +#else +/* NOTE: This needs to check memory size which running system has. */ +#define LZMA_MEMLIMIT (1U << 30) +#endif + { + lzma_options_delta delta_opt; + lzma_filter filters[LZMA_FILTERS_MAX], *ff; + int fi = 0; + + if (zip->lzstream_valid) { + lzma_end(&(zip->lzstream)); + zip->lzstream_valid = 0; + } + + /* + * NOTE: liblzma incompletely handle the BCJ+LZMA compressed + * data made by 7-Zip because 7-Zip does not add End-Of- + * Payload Marker(EOPM) at the end of LZMA compressed data, + * and so liblzma cannot know the end of the compressed data + * without EOPM. So consequently liblzma will not return last + * three or four bytes of uncompressed data because + * LZMA_FILTER_X86 filter does not handle input data if its + * data size is less than five bytes. If liblzma detect EOPM + * or know the uncompressed data size, liblzma will flush out + * the remaining that three or four bytes of uncompressed + * data. That is why we have to use our converting program + * for BCJ+LZMA. If we were able to tell the uncompressed + * size to liblzma when using lzma_raw_decoder() liblzma + * could correctly deal with BCJ+LZMA. But unfortunately + * there is no way to do that. + * Discussion about this can be found at XZ Utils forum. + */ + if (coder2 != NULL) { + zip->codec2 = coder2->codec; + + filters[fi].options = NULL; + switch (zip->codec2) { + case _7Z_X86: + if (zip->codec == _7Z_LZMA2) { + filters[fi].id = LZMA_FILTER_X86; + fi++; + } else + /* Use our filter. */ + x86_Init(zip); + break; + case _7Z_X86_BCJ2: + /* Use our filter. */ + zip->bcj_state = 0; + break; + case _7Z_DELTA: + if (coder2->propertiesSize != 1) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Invalid Delta parameter"); + return (ARCHIVE_FAILED); + } + filters[fi].id = LZMA_FILTER_DELTA; + memset(&delta_opt, 0, sizeof(delta_opt)); + delta_opt.type = LZMA_DELTA_TYPE_BYTE; + delta_opt.dist = + (uint32_t)coder2->properties[0] + 1; + filters[fi].options = &delta_opt; + fi++; + break; + /* Following filters have not been tested yet. */ + case _7Z_POWERPC: + filters[fi].id = LZMA_FILTER_POWERPC; + fi++; + break; + case _7Z_IA64: + filters[fi].id = LZMA_FILTER_IA64; + fi++; + break; + case _7Z_ARM: + filters[fi].id = LZMA_FILTER_ARM; + fi++; + break; + case _7Z_ARMTHUMB: + filters[fi].id = LZMA_FILTER_ARMTHUMB; + fi++; + break; + case _7Z_SPARC: + filters[fi].id = LZMA_FILTER_SPARC; + fi++; + break; + default: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Unexpected codec ID: %lX", zip->codec2); + return (ARCHIVE_FAILED); + } + } + + if (zip->codec == _7Z_LZMA2) + filters[fi].id = LZMA_FILTER_LZMA2; + else + filters[fi].id = LZMA_FILTER_LZMA1; + filters[fi].options = NULL; + ff = &filters[fi]; + r = lzma_properties_decode(&filters[fi], NULL, + coder1->properties, (size_t)coder1->propertiesSize); + if (r != LZMA_OK) { + set_error(a, r); + return (ARCHIVE_FAILED); + } + fi++; + + filters[fi].id = LZMA_VLI_UNKNOWN; + filters[fi].options = NULL; + r = lzma_raw_decoder(&(zip->lzstream), filters); + free(ff->options); + if (r != LZMA_OK) { + set_error(a, r); + return (ARCHIVE_FAILED); + } + zip->lzstream_valid = 1; + zip->lzstream.total_in = 0; + zip->lzstream.total_out = 0; + break; + } +#else + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "LZMA codec is unsupported"); + return (ARCHIVE_FAILED); +#endif + case _7Z_BZ2: +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) + if (zip->bzstream_valid) { + BZ2_bzDecompressEnd(&(zip->bzstream)); + zip->bzstream_valid = 0; + } + r = BZ2_bzDecompressInit(&(zip->bzstream), 0, 0); + if (r == BZ_MEM_ERROR) + r = BZ2_bzDecompressInit(&(zip->bzstream), 0, 1); + if (r != BZ_OK) { + int err = ARCHIVE_ERRNO_MISC; + const char *detail = NULL; + switch (r) { + case BZ_PARAM_ERROR: + detail = "invalid setup parameter"; + break; + case BZ_MEM_ERROR: + err = ENOMEM; + detail = "out of memory"; + break; + case BZ_CONFIG_ERROR: + detail = "mis-compiled library"; + break; + } + archive_set_error(&a->archive, err, + "Internal error initializing decompressor: %s", + detail != NULL ? detail : "??"); + zip->bzstream_valid = 0; + return (ARCHIVE_FAILED); + } + zip->bzstream_valid = 1; + zip->bzstream.total_in_lo32 = 0; + zip->bzstream.total_in_hi32 = 0; + zip->bzstream.total_out_lo32 = 0; + zip->bzstream.total_out_hi32 = 0; + break; +#else + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "BZ2 codec is unsupported"); + return (ARCHIVE_FAILED); +#endif + case _7Z_DEFLATE: +#ifdef HAVE_ZLIB_H + if (zip->stream_valid) + r = inflateReset(&(zip->stream)); + else + r = inflateInit2(&(zip->stream), + -15 /* Don't check for zlib header */); + if (r != Z_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Couldn't initialize zlib stream."); + return (ARCHIVE_FAILED); + } + zip->stream_valid = 1; + zip->stream.total_in = 0; + zip->stream.total_out = 0; + break; +#else + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "DEFLATE codec is unsupported"); + return (ARCHIVE_FAILED); +#endif + case _7Z_PPMD: + { + unsigned order; + uint32_t msize; + + if (zip->ppmd7_valid) { + __archive_ppmd7_functions.Ppmd7_Free( + &zip->ppmd7_context); + zip->ppmd7_valid = 0; + } + + if (coder1->propertiesSize < 5) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Malformed PPMd parameter"); + return (ARCHIVE_FAILED); + } + order = coder1->properties[0]; + msize = archive_le32dec(&(coder1->properties[1])); + if (order < PPMD7_MIN_ORDER || order > PPMD7_MAX_ORDER || + msize < PPMD7_MIN_MEM_SIZE || msize > PPMD7_MAX_MEM_SIZE) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Malformed PPMd parameter"); + return (ARCHIVE_FAILED); + } + __archive_ppmd7_functions.Ppmd7_Construct(&zip->ppmd7_context); + r = __archive_ppmd7_functions.Ppmd7_Alloc( + &zip->ppmd7_context, msize); + if (r == 0) { + archive_set_error(&a->archive, ENOMEM, + "Coludn't allocate memory for PPMd"); + return (ARCHIVE_FATAL); + } + __archive_ppmd7_functions.Ppmd7_Init( + &zip->ppmd7_context, order); + __archive_ppmd7_functions.Ppmd7z_RangeDec_CreateVTable( + &zip->range_dec); + zip->ppmd7_valid = 1; + zip->ppmd7_stat = 0; + zip->ppstream.overconsumed = 0; + zip->ppstream.total_in = 0; + zip->ppstream.total_out = 0; + break; + } + case _7Z_X86: + case _7Z_X86_BCJ2: + case _7Z_POWERPC: + case _7Z_IA64: + case _7Z_ARM: + case _7Z_ARMTHUMB: + case _7Z_SPARC: + case _7Z_DELTA: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Unexpected codec ID: %lX", zip->codec); + return (ARCHIVE_FAILED); + case _7Z_CRYPTO_MAIN_ZIP: + case _7Z_CRYPTO_RAR_29: + case _7Z_CRYPTO_AES_256_SHA_256: + if (a->entry) { + archive_entry_set_is_metadata_encrypted(a->entry, 1); + archive_entry_set_is_data_encrypted(a->entry, 1); + zip->has_encrypted_entries = 1; + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Crypto codec not supported yet (ID: 0x%lX)", zip->codec); + return (ARCHIVE_FAILED); + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Unknown codec ID: %lX", zip->codec); + return (ARCHIVE_FAILED); + } + + return (ARCHIVE_OK); +} + +static int +decompress(struct archive_read *a, struct _7zip *zip, + void *buff, size_t *outbytes, const void *b, size_t *used) +{ + const uint8_t *t_next_in; + uint8_t *t_next_out; + size_t o_avail_in, o_avail_out; + size_t t_avail_in, t_avail_out; + uint8_t *bcj2_next_out; + size_t bcj2_avail_out; + int r, ret = ARCHIVE_OK; + + t_avail_in = o_avail_in = *used; + t_avail_out = o_avail_out = *outbytes; + t_next_in = b; + t_next_out = buff; + + if (zip->codec != _7Z_LZMA2 && zip->codec2 == _7Z_X86) { + int i; + + /* Do not copy out the BCJ remaining bytes when the output + * buffer size is less than five bytes. */ + if (o_avail_in != 0 && t_avail_out < 5 && zip->odd_bcj_size) { + *used = 0; + *outbytes = 0; + return (ret); + } + for (i = 0; zip->odd_bcj_size > 0 && t_avail_out; i++) { + *t_next_out++ = zip->odd_bcj[i]; + t_avail_out--; + zip->odd_bcj_size--; + } + if (o_avail_in == 0 || t_avail_out == 0) { + *used = o_avail_in - t_avail_in; + *outbytes = o_avail_out - t_avail_out; + if (o_avail_in == 0) + ret = ARCHIVE_EOF; + return (ret); + } + } + + bcj2_next_out = t_next_out; + bcj2_avail_out = t_avail_out; + if (zip->codec2 == _7Z_X86_BCJ2) { + /* + * Decord a remaining decompressed main stream for BCJ2. + */ + if (zip->tmp_stream_bytes_remaining) { + ssize_t bytes; + size_t remaining = zip->tmp_stream_bytes_remaining; + bytes = Bcj2_Decode(zip, t_next_out, t_avail_out); + if (bytes < 0) { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "BCJ2 conversion Failed"); + return (ARCHIVE_FAILED); + } + zip->main_stream_bytes_remaining -= + remaining - zip->tmp_stream_bytes_remaining; + t_avail_out -= bytes; + if (o_avail_in == 0 || t_avail_out == 0) { + *used = 0; + *outbytes = o_avail_out - t_avail_out; + if (o_avail_in == 0 && + zip->tmp_stream_bytes_remaining) + ret = ARCHIVE_EOF; + return (ret); + } + t_next_out += bytes; + bcj2_next_out = t_next_out; + bcj2_avail_out = t_avail_out; + } + t_next_out = zip->tmp_stream_buff; + t_avail_out = zip->tmp_stream_buff_size; + } + + switch (zip->codec) { + case _7Z_COPY: + { + size_t bytes = + (t_avail_in > t_avail_out)?t_avail_out:t_avail_in; + + memcpy(t_next_out, t_next_in, bytes); + t_avail_in -= bytes; + t_avail_out -= bytes; + if (o_avail_in == 0) + ret = ARCHIVE_EOF; + break; + } +#ifdef HAVE_LZMA_H + case _7Z_LZMA: case _7Z_LZMA2: + zip->lzstream.next_in = t_next_in; + zip->lzstream.avail_in = t_avail_in; + zip->lzstream.next_out = t_next_out; + zip->lzstream.avail_out = t_avail_out; + + r = lzma_code(&(zip->lzstream), LZMA_RUN); + switch (r) { + case LZMA_STREAM_END: /* Found end of stream. */ + lzma_end(&(zip->lzstream)); + zip->lzstream_valid = 0; + ret = ARCHIVE_EOF; + break; + case LZMA_OK: /* Decompressor made some progress. */ + break; + default: + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Decompression failed(%d)", + r); + return (ARCHIVE_FAILED); + } + t_avail_in = zip->lzstream.avail_in; + t_avail_out = zip->lzstream.avail_out; + break; +#endif +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) + case _7Z_BZ2: + zip->bzstream.next_in = (char *)(uintptr_t)t_next_in; + zip->bzstream.avail_in = t_avail_in; + zip->bzstream.next_out = (char *)(uintptr_t)t_next_out; + zip->bzstream.avail_out = t_avail_out; + r = BZ2_bzDecompress(&(zip->bzstream)); + switch (r) { + case BZ_STREAM_END: /* Found end of stream. */ + switch (BZ2_bzDecompressEnd(&(zip->bzstream))) { + case BZ_OK: + break; + default: + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Failed to clean up decompressor"); + return (ARCHIVE_FAILED); + } + zip->bzstream_valid = 0; + ret = ARCHIVE_EOF; + break; + case BZ_OK: /* Decompressor made some progress. */ + break; + default: + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "bzip decompression failed"); + return (ARCHIVE_FAILED); + } + t_avail_in = zip->bzstream.avail_in; + t_avail_out = zip->bzstream.avail_out; + break; +#endif +#ifdef HAVE_ZLIB_H + case _7Z_DEFLATE: + zip->stream.next_in = (Bytef *)(uintptr_t)t_next_in; + zip->stream.avail_in = (uInt)t_avail_in; + zip->stream.next_out = t_next_out; + zip->stream.avail_out = (uInt)t_avail_out; + r = inflate(&(zip->stream), 0); + switch (r) { + case Z_STREAM_END: /* Found end of stream. */ + ret = ARCHIVE_EOF; + break; + case Z_OK: /* Decompressor made some progress.*/ + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "File decompression failed (%d)", r); + return (ARCHIVE_FAILED); + } + t_avail_in = zip->stream.avail_in; + t_avail_out = zip->stream.avail_out; + break; +#endif + case _7Z_PPMD: + { + uint64_t flush_bytes; + + if (!zip->ppmd7_valid || zip->ppmd7_stat < 0 || + t_avail_out <= 0) { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Decompression internal error"); + return (ARCHIVE_FAILED); + } + zip->ppstream.next_in = t_next_in; + zip->ppstream.avail_in = t_avail_in; + zip->ppstream.next_out = t_next_out; + zip->ppstream.avail_out = t_avail_out; + if (zip->ppmd7_stat == 0) { + zip->bytein.a = a; + zip->bytein.Read = &ppmd_read; + zip->range_dec.Stream = &zip->bytein; + r = __archive_ppmd7_functions.Ppmd7z_RangeDec_Init( + &(zip->range_dec)); + if (r == 0) { + zip->ppmd7_stat = -1; + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Failed to initialize PPMd range decorder"); + return (ARCHIVE_FAILED); + } + if (zip->ppstream.overconsumed) { + zip->ppmd7_stat = -1; + return (ARCHIVE_FAILED); + } + zip->ppmd7_stat = 1; + } + + if (t_avail_in == 0) + /* XXX Flush out remaining decoded data XXX */ + flush_bytes = zip->folder_outbytes_remaining; + else + flush_bytes = 0; + + do { + int sym; + + sym = __archive_ppmd7_functions.Ppmd7_DecodeSymbol( + &(zip->ppmd7_context), &(zip->range_dec.p)); + if (sym < 0) { + zip->ppmd7_stat = -1; + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Failed to decode PPMd"); + return (ARCHIVE_FAILED); + } + if (zip->ppstream.overconsumed) { + zip->ppmd7_stat = -1; + return (ARCHIVE_FAILED); + } + *zip->ppstream.next_out++ = (unsigned char)sym; + zip->ppstream.avail_out--; + zip->ppstream.total_out++; + if (flush_bytes) + flush_bytes--; + } while (zip->ppstream.avail_out && + (zip->ppstream.avail_in || flush_bytes)); + + t_avail_in = (size_t)zip->ppstream.avail_in; + t_avail_out = (size_t)zip->ppstream.avail_out; + break; + } + default: + archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, + "Decompression internal error"); + return (ARCHIVE_FAILED); + } + if (ret != ARCHIVE_OK && ret != ARCHIVE_EOF) + return (ret); + + *used = o_avail_in - t_avail_in; + *outbytes = o_avail_out - t_avail_out; + + /* + * Decord BCJ. + */ + if (zip->codec != _7Z_LZMA2 && zip->codec2 == _7Z_X86) { + size_t l = x86_Convert(zip, buff, *outbytes); + zip->odd_bcj_size = *outbytes - l; + if (zip->odd_bcj_size > 0 && zip->odd_bcj_size <= 4 && + o_avail_in && ret != ARCHIVE_EOF) { + memcpy(zip->odd_bcj, ((unsigned char *)buff) + l, + zip->odd_bcj_size); + *outbytes = l; + } else + zip->odd_bcj_size = 0; + } + + /* + * Decord BCJ2 with a decompressed main stream. + */ + if (zip->codec2 == _7Z_X86_BCJ2) { + ssize_t bytes; + + zip->tmp_stream_bytes_avail = + zip->tmp_stream_buff_size - t_avail_out; + if (zip->tmp_stream_bytes_avail > + zip->main_stream_bytes_remaining) + zip->tmp_stream_bytes_avail = + zip->main_stream_bytes_remaining; + zip->tmp_stream_bytes_remaining = zip->tmp_stream_bytes_avail; + bytes = Bcj2_Decode(zip, bcj2_next_out, bcj2_avail_out); + if (bytes < 0) { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, "BCJ2 conversion Failed"); + return (ARCHIVE_FAILED); + } + zip->main_stream_bytes_remaining -= + zip->tmp_stream_bytes_avail + - zip->tmp_stream_bytes_remaining; + bcj2_avail_out -= bytes; + *outbytes = o_avail_out - bcj2_avail_out; + } + + return (ret); +} + +static int +free_decompression(struct archive_read *a, struct _7zip *zip) +{ + int r = ARCHIVE_OK; + +#if !defined(HAVE_ZLIB_H) &&\ + !(defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)) + (void)a;/* UNUSED */ +#endif +#ifdef HAVE_LZMA_H + if (zip->lzstream_valid) + lzma_end(&(zip->lzstream)); +#endif +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) + if (zip->bzstream_valid) { + if (BZ2_bzDecompressEnd(&(zip->bzstream)) != BZ_OK) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Failed to clean up bzip2 decompressor"); + r = ARCHIVE_FATAL; + } + zip->bzstream_valid = 0; + } +#endif +#ifdef HAVE_ZLIB_H + if (zip->stream_valid) { + if (inflateEnd(&(zip->stream)) != Z_OK) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Failed to clean up zlib decompressor"); + r = ARCHIVE_FATAL; + } + zip->stream_valid = 0; + } +#endif + if (zip->ppmd7_valid) { + __archive_ppmd7_functions.Ppmd7_Free( + &zip->ppmd7_context); + zip->ppmd7_valid = 0; + } + return (r); +} + +static int +parse_7zip_uint64(struct archive_read *a, uint64_t *val) +{ + const unsigned char *p; + unsigned char avail, mask; + int i; + + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + avail = *p; + mask = 0x80; + *val = 0; + for (i = 0; i < 8; i++) { + if (avail & mask) { + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + *val |= ((uint64_t)*p) << (8 * i); + mask >>= 1; + continue; + } + *val += ((uint64_t)(avail & (mask -1))) << (8 * i); + break; + } + return (0); +} + +static int +read_Bools(struct archive_read *a, unsigned char *data, size_t num) +{ + const unsigned char *p; + unsigned i, mask = 0, avail = 0; + + for (i = 0; i < num; i++) { + if (mask == 0) { + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + avail = *p; + mask = 0x80; + } + data[i] = (avail & mask)?1:0; + mask >>= 1; + } + return (0); +} + +static void +free_Digest(struct _7z_digests *d) +{ + free(d->defineds); + free(d->digests); +} + +static int +read_Digests(struct archive_read *a, struct _7z_digests *d, size_t num) +{ + const unsigned char *p; + unsigned i; + + if (num == 0) + return (-1); + memset(d, 0, sizeof(*d)); + + d->defineds = malloc(num); + if (d->defineds == NULL) + return (-1); + /* + * Read Bools. + */ + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + if (*p == 0) { + if (read_Bools(a, d->defineds, num) < 0) + return (-1); + } else + /* All are defined */ + memset(d->defineds, 1, num); + + d->digests = calloc(num, sizeof(*d->digests)); + if (d->digests == NULL) + return (-1); + for (i = 0; i < num; i++) { + if (d->defineds[i]) { + if ((p = header_bytes(a, 4)) == NULL) + return (-1); + d->digests[i] = archive_le32dec(p); + } + } + + return (0); +} + +static void +free_PackInfo(struct _7z_pack_info *pi) +{ + free(pi->sizes); + free(pi->positions); + free_Digest(&(pi->digest)); +} + +static int +read_PackInfo(struct archive_read *a, struct _7z_pack_info *pi) +{ + const unsigned char *p; + unsigned i; + + memset(pi, 0, sizeof(*pi)); + + /* + * Read PackPos. + */ + if (parse_7zip_uint64(a, &(pi->pos)) < 0) + return (-1); + + /* + * Read NumPackStreams. + */ + if (parse_7zip_uint64(a, &(pi->numPackStreams)) < 0) + return (-1); + if (pi->numPackStreams == 0) + return (-1); + if (UMAX_ENTRY < pi->numPackStreams) + return (-1); + + /* + * Read PackSizes[num] + */ + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + if (*p == kEnd) + /* PackSizes[num] are not present. */ + return (0); + if (*p != kSize) + return (-1); + pi->sizes = calloc((size_t)pi->numPackStreams, sizeof(uint64_t)); + pi->positions = calloc((size_t)pi->numPackStreams, sizeof(uint64_t)); + if (pi->sizes == NULL || pi->positions == NULL) + return (-1); + + for (i = 0; i < pi->numPackStreams; i++) { + if (parse_7zip_uint64(a, &(pi->sizes[i])) < 0) + return (-1); + } + + /* + * Read PackStreamDigests[num] + */ + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + if (*p == kEnd) { + /* PackStreamDigests[num] are not present. */ + pi->digest.defineds = + calloc((size_t)pi->numPackStreams, sizeof(*pi->digest.defineds)); + pi->digest.digests = + calloc((size_t)pi->numPackStreams, sizeof(*pi->digest.digests)); + if (pi->digest.defineds == NULL || pi->digest.digests == NULL) + return (-1); + return (0); + } + + if (*p != kCRC) + return (-1); + + if (read_Digests(a, &(pi->digest), (size_t)pi->numPackStreams) < 0) + return (-1); + + /* + * Must be marked by kEnd. + */ + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + if (*p != kEnd) + return (-1); + return (0); +} + +static void +free_Folder(struct _7z_folder *f) +{ + unsigned i; + + if (f->coders) { + for (i = 0; i< f->numCoders; i++) { + free(f->coders[i].properties); + } + free(f->coders); + } + free(f->bindPairs); + free(f->packedStreams); + free(f->unPackSize); +} + +static int +read_Folder(struct archive_read *a, struct _7z_folder *f) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + const unsigned char *p; + uint64_t numInStreamsTotal = 0; + uint64_t numOutStreamsTotal = 0; + unsigned i; + + memset(f, 0, sizeof(*f)); + + /* + * Read NumCoders. + */ + if (parse_7zip_uint64(a, &(f->numCoders)) < 0) + return (-1); + if (f->numCoders > 4) + /* Too many coders. */ + return (-1); + + f->coders = calloc((size_t)f->numCoders, sizeof(*f->coders)); + if (f->coders == NULL) + return (-1); + for (i = 0; i< f->numCoders; i++) { + size_t codec_size; + int simple, attr; + + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + /* + * 0:3 CodecIdSize + * 4: 0 - IsSimple + * 1 - Is not Simple + * 5: 0 - No Attributes + * 1 - There are Attributes; + * 7: Must be zero. + */ + codec_size = *p & 0xf; + simple = (*p & 0x10)?0:1; + attr = *p & 0x20; + if (*p & 0x80) + return (-1);/* Not supported. */ + + /* + * Read Decompression Method IDs. + */ + if ((p = header_bytes(a, codec_size)) == NULL) + return (-1); + + f->coders[i].codec = decode_codec_id(p, codec_size); + + if (simple) { + f->coders[i].numInStreams = 1; + f->coders[i].numOutStreams = 1; + } else { + if (parse_7zip_uint64( + a, &(f->coders[i].numInStreams)) < 0) + return (-1); + if (UMAX_ENTRY < f->coders[i].numInStreams) + return (-1); + if (parse_7zip_uint64( + a, &(f->coders[i].numOutStreams)) < 0) + return (-1); + if (UMAX_ENTRY < f->coders[i].numOutStreams) + return (-1); + } + + if (attr) { + if (parse_7zip_uint64( + a, &(f->coders[i].propertiesSize)) < 0) + return (-1); + if ((p = header_bytes( + a, (size_t)f->coders[i].propertiesSize)) == NULL) + return (-1); + f->coders[i].properties = + malloc((size_t)f->coders[i].propertiesSize); + if (f->coders[i].properties == NULL) + return (-1); + memcpy(f->coders[i].properties, p, + (size_t)f->coders[i].propertiesSize); + } + + numInStreamsTotal += f->coders[i].numInStreams; + numOutStreamsTotal += f->coders[i].numOutStreams; + } + + if (numOutStreamsTotal == 0 || + numInStreamsTotal < numOutStreamsTotal-1) + return (-1); + + f->numBindPairs = numOutStreamsTotal - 1; + if (zip->header_bytes_remaining < f->numBindPairs) + return (-1); + if (f->numBindPairs > 0) { + f->bindPairs = + calloc((size_t)f->numBindPairs, sizeof(*f->bindPairs)); + if (f->bindPairs == NULL) + return (-1); + } else + f->bindPairs = NULL; + for (i = 0; i < f->numBindPairs; i++) { + if (parse_7zip_uint64(a, &(f->bindPairs[i].inIndex)) < 0) + return (-1); + if (UMAX_ENTRY < f->bindPairs[i].inIndex) + return (-1); + if (parse_7zip_uint64(a, &(f->bindPairs[i].outIndex)) < 0) + return (-1); + if (UMAX_ENTRY < f->bindPairs[i].outIndex) + return (-1); + } + + f->numPackedStreams = numInStreamsTotal - f->numBindPairs; + f->packedStreams = + calloc((size_t)f->numPackedStreams, sizeof(*f->packedStreams)); + if (f->packedStreams == NULL) + return (-1); + if (f->numPackedStreams == 1) { + for (i = 0; i < numInStreamsTotal; i++) { + unsigned j; + for (j = 0; j < f->numBindPairs; j++) { + if (f->bindPairs[j].inIndex == i) + break; + } + if (j == f->numBindPairs) + break; + } + if (i == numInStreamsTotal) + return (-1); + f->packedStreams[0] = i; + } else { + for (i = 0; i < f->numPackedStreams; i++) { + if (parse_7zip_uint64(a, &(f->packedStreams[i])) < 0) + return (-1); + if (UMAX_ENTRY < f->packedStreams[i]) + return (-1); + } + } + f->numInStreams = numInStreamsTotal; + f->numOutStreams = numOutStreamsTotal; + + return (0); +} + +static void +free_CodersInfo(struct _7z_coders_info *ci) +{ + unsigned i; + + if (ci->folders) { + for (i = 0; i < ci->numFolders; i++) + free_Folder(&(ci->folders[i])); + free(ci->folders); + } +} + +static int +read_CodersInfo(struct archive_read *a, struct _7z_coders_info *ci) +{ + const unsigned char *p; + struct _7z_digests digest; + unsigned i; + + memset(ci, 0, sizeof(*ci)); + memset(&digest, 0, sizeof(digest)); + + if ((p = header_bytes(a, 1)) == NULL) + goto failed; + if (*p != kFolder) + goto failed; + + /* + * Read NumFolders. + */ + if (parse_7zip_uint64(a, &(ci->numFolders)) < 0) + goto failed; + if (UMAX_ENTRY < ci->numFolders) + return (-1); + + /* + * Read External. + */ + if ((p = header_bytes(a, 1)) == NULL) + goto failed; + switch (*p) { + case 0: + ci->folders = + calloc((size_t)ci->numFolders, sizeof(*ci->folders)); + if (ci->folders == NULL) + return (-1); + for (i = 0; i < ci->numFolders; i++) { + if (read_Folder(a, &(ci->folders[i])) < 0) + goto failed; + } + break; + case 1: + if (parse_7zip_uint64(a, &(ci->dataStreamIndex)) < 0) + return (-1); + if (UMAX_ENTRY < ci->dataStreamIndex) + return (-1); + if (ci->numFolders > 0) { + archive_set_error(&a->archive, -1, + "Malformed 7-Zip archive"); + goto failed; + } + break; + default: + archive_set_error(&a->archive, -1, + "Malformed 7-Zip archive"); + goto failed; + } + + if ((p = header_bytes(a, 1)) == NULL) + goto failed; + if (*p != kCodersUnPackSize) + goto failed; + + for (i = 0; i < ci->numFolders; i++) { + struct _7z_folder *folder = &(ci->folders[i]); + unsigned j; + + folder->unPackSize = + calloc((size_t)folder->numOutStreams, sizeof(*folder->unPackSize)); + if (folder->unPackSize == NULL) + goto failed; + for (j = 0; j < folder->numOutStreams; j++) { + if (parse_7zip_uint64(a, &(folder->unPackSize[j])) < 0) + goto failed; + } + } + + /* + * Read CRCs. + */ + if ((p = header_bytes(a, 1)) == NULL) + goto failed; + if (*p == kEnd) + return (0); + if (*p != kCRC) + goto failed; + if (read_Digests(a, &digest, (size_t)ci->numFolders) < 0) + goto failed; + for (i = 0; i < ci->numFolders; i++) { + ci->folders[i].digest_defined = digest.defineds[i]; + ci->folders[i].digest = digest.digests[i]; + } + + /* + * Must be kEnd. + */ + if ((p = header_bytes(a, 1)) == NULL) + goto failed; + if (*p != kEnd) + goto failed; + free_Digest(&digest); + return (0); +failed: + free_Digest(&digest); + return (-1); +} + +static uint64_t +folder_uncompressed_size(struct _7z_folder *f) +{ + int n = (int)f->numOutStreams; + unsigned pairs = (unsigned)f->numBindPairs; + + while (--n >= 0) { + unsigned i; + for (i = 0; i < pairs; i++) { + if (f->bindPairs[i].outIndex == (uint64_t)n) + break; + } + if (i >= pairs) + return (f->unPackSize[n]); + } + return (0); +} + +static void +free_SubStreamsInfo(struct _7z_substream_info *ss) +{ + free(ss->unpackSizes); + free(ss->digestsDefined); + free(ss->digests); +} + +static int +read_SubStreamsInfo(struct archive_read *a, struct _7z_substream_info *ss, + struct _7z_folder *f, size_t numFolders) +{ + const unsigned char *p; + uint64_t *usizes; + size_t unpack_streams; + int type; + unsigned i; + uint32_t numDigests; + + memset(ss, 0, sizeof(*ss)); + + for (i = 0; i < numFolders; i++) + f[i].numUnpackStreams = 1; + + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + type = *p; + + if (type == kNumUnPackStream) { + unpack_streams = 0; + for (i = 0; i < numFolders; i++) { + if (parse_7zip_uint64(a, &(f[i].numUnpackStreams)) < 0) + return (-1); + if (UMAX_ENTRY < f[i].numUnpackStreams) + return (-1); + if (unpack_streams > SIZE_MAX - UMAX_ENTRY) { + return (-1); + } + unpack_streams += (size_t)f[i].numUnpackStreams; + } + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + type = *p; + } else + unpack_streams = numFolders; + + ss->unpack_streams = unpack_streams; + if (unpack_streams) { + ss->unpackSizes = calloc(unpack_streams, + sizeof(*ss->unpackSizes)); + ss->digestsDefined = calloc(unpack_streams, + sizeof(*ss->digestsDefined)); + ss->digests = calloc(unpack_streams, + sizeof(*ss->digests)); + if (ss->unpackSizes == NULL || ss->digestsDefined == NULL || + ss->digests == NULL) + return (-1); + } + + usizes = ss->unpackSizes; + for (i = 0; i < numFolders; i++) { + unsigned pack; + uint64_t sum; + + if (f[i].numUnpackStreams == 0) + continue; + + sum = 0; + if (type == kSize) { + for (pack = 1; pack < f[i].numUnpackStreams; pack++) { + if (parse_7zip_uint64(a, usizes) < 0) + return (-1); + sum += *usizes++; + } + } + *usizes++ = folder_uncompressed_size(&f[i]) - sum; + } + + if (type == kSize) { + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + type = *p; + } + + for (i = 0; i < unpack_streams; i++) { + ss->digestsDefined[i] = 0; + ss->digests[i] = 0; + } + + numDigests = 0; + for (i = 0; i < numFolders; i++) { + if (f[i].numUnpackStreams != 1 || !f[i].digest_defined) + numDigests += (uint32_t)f[i].numUnpackStreams; + } + + if (type == kCRC) { + struct _7z_digests tmpDigests; + unsigned char *digestsDefined = ss->digestsDefined; + uint32_t * digests = ss->digests; + int di = 0; + + memset(&tmpDigests, 0, sizeof(tmpDigests)); + if (read_Digests(a, &(tmpDigests), numDigests) < 0) { + free_Digest(&tmpDigests); + return (-1); + } + for (i = 0; i < numFolders; i++) { + if (f[i].numUnpackStreams == 1 && f[i].digest_defined) { + *digestsDefined++ = 1; + *digests++ = f[i].digest; + } else { + unsigned j; + + for (j = 0; j < f[i].numUnpackStreams; + j++, di++) { + *digestsDefined++ = + tmpDigests.defineds[di]; + *digests++ = + tmpDigests.digests[di]; + } + } + } + free_Digest(&tmpDigests); + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + type = *p; + } + + /* + * Must be kEnd. + */ + if (type != kEnd) + return (-1); + return (0); +} + +static void +free_StreamsInfo(struct _7z_stream_info *si) +{ + free_PackInfo(&(si->pi)); + free_CodersInfo(&(si->ci)); + free_SubStreamsInfo(&(si->ss)); +} + +static int +read_StreamsInfo(struct archive_read *a, struct _7z_stream_info *si) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + const unsigned char *p; + unsigned i; + + memset(si, 0, sizeof(*si)); + + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + if (*p == kPackInfo) { + uint64_t packPos; + + if (read_PackInfo(a, &(si->pi)) < 0) + return (-1); + + if (si->pi.positions == NULL || si->pi.sizes == NULL) + return (-1); + /* + * Calculate packed stream positions. + */ + packPos = si->pi.pos; + for (i = 0; i < si->pi.numPackStreams; i++) { + si->pi.positions[i] = packPos; + packPos += si->pi.sizes[i]; + if (packPos > zip->header_offset) + return (-1); + } + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + } + if (*p == kUnPackInfo) { + uint32_t packIndex; + struct _7z_folder *f; + + if (read_CodersInfo(a, &(si->ci)) < 0) + return (-1); + + /* + * Calculate packed stream indexes. + */ + packIndex = 0; + f = si->ci.folders; + for (i = 0; i < si->ci.numFolders; i++) { + f[i].packIndex = packIndex; + packIndex += (uint32_t)f[i].numPackedStreams; + if (packIndex > si->pi.numPackStreams) + return (-1); + } + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + } + + if (*p == kSubStreamsInfo) { + if (read_SubStreamsInfo(a, &(si->ss), + si->ci.folders, (size_t)si->ci.numFolders) < 0) + return (-1); + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + } + + /* + * Must be kEnd. + */ + if (*p != kEnd) + return (-1); + return (0); +} + +static void +free_Header(struct _7z_header_info *h) +{ + free(h->emptyStreamBools); + free(h->emptyFileBools); + free(h->antiBools); + free(h->attrBools); +} + +static int +read_Header(struct archive_read *a, struct _7z_header_info *h, + int check_header_id) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + const unsigned char *p; + struct _7z_folder *folders; + struct _7z_stream_info *si = &(zip->si); + struct _7zip_entry *entries; + uint32_t folderIndex, indexInFolder; + unsigned i; + int eindex, empty_streams, sindex; + + if (check_header_id) { + /* + * Read Header. + */ + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + if (*p != kHeader) + return (-1); + } + + /* + * Read ArchiveProperties. + */ + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + if (*p == kArchiveProperties) { + for (;;) { + uint64_t size; + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + if (*p == 0) + break; + if (parse_7zip_uint64(a, &size) < 0) + return (-1); + } + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + } + + /* + * Read MainStreamsInfo. + */ + if (*p == kMainStreamsInfo) { + if (read_StreamsInfo(a, &(zip->si)) < 0) + return (-1); + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + } + if (*p == kEnd) + return (0); + + /* + * Read FilesInfo. + */ + if (*p != kFilesInfo) + return (-1); + + if (parse_7zip_uint64(a, &(zip->numFiles)) < 0) + return (-1); + if (UMAX_ENTRY < zip->numFiles) + return (-1); + + zip->entries = calloc((size_t)zip->numFiles, sizeof(*zip->entries)); + if (zip->entries == NULL) + return (-1); + entries = zip->entries; + + empty_streams = 0; + for (;;) { + int type; + uint64_t size; + size_t ll; + + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + type = *p; + if (type == kEnd) + break; + + if (parse_7zip_uint64(a, &size) < 0) + return (-1); + if (zip->header_bytes_remaining < size) + return (-1); + ll = (size_t)size; + + switch (type) { + case kEmptyStream: + if (h->emptyStreamBools != NULL) + return (-1); + h->emptyStreamBools = calloc((size_t)zip->numFiles, + sizeof(*h->emptyStreamBools)); + if (h->emptyStreamBools == NULL) + return (-1); + if (read_Bools( + a, h->emptyStreamBools, (size_t)zip->numFiles) < 0) + return (-1); + empty_streams = 0; + for (i = 0; i < zip->numFiles; i++) { + if (h->emptyStreamBools[i]) + empty_streams++; + } + break; + case kEmptyFile: + if (empty_streams <= 0) { + /* Unexcepted sequence. Skip this. */ + if (header_bytes(a, ll) == NULL) + return (-1); + break; + } + if (h->emptyFileBools != NULL) + return (-1); + h->emptyFileBools = calloc(empty_streams, + sizeof(*h->emptyFileBools)); + if (h->emptyFileBools == NULL) + return (-1); + if (read_Bools(a, h->emptyFileBools, empty_streams) < 0) + return (-1); + break; + case kAnti: + if (empty_streams <= 0) { + /* Unexcepted sequence. Skip this. */ + if (header_bytes(a, ll) == NULL) + return (-1); + break; + } + if (h->antiBools != NULL) + return (-1); + h->antiBools = calloc(empty_streams, + sizeof(*h->antiBools)); + if (h->antiBools == NULL) + return (-1); + if (read_Bools(a, h->antiBools, empty_streams) < 0) + return (-1); + break; + case kCTime: + case kATime: + case kMTime: + if (read_Times(a, h, type) < 0) + return (-1); + break; + case kName: + { + unsigned char *np; + size_t nl, nb; + + /* Skip one byte. */ + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + ll--; + + if ((ll & 1) || ll < zip->numFiles * 4) + return (-1); + + if (zip->entry_names != NULL) + return (-1); + zip->entry_names = malloc(ll); + if (zip->entry_names == NULL) + return (-1); + np = zip->entry_names; + nb = ll; + /* + * Copy whole file names. + * NOTE: This loop prevents from expanding + * the uncompressed buffer in order not to + * use extra memory resource. + */ + while (nb) { + size_t b; + if (nb > UBUFF_SIZE) + b = UBUFF_SIZE; + else + b = nb; + if ((p = header_bytes(a, b)) == NULL) + return (-1); + memcpy(np, p, b); + np += b; + nb -= b; + } + np = zip->entry_names; + nl = ll; + + for (i = 0; i < zip->numFiles; i++) { + entries[i].utf16name = np; +#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG) + entries[i].wname = (wchar_t *)np; +#endif + + /* Find a terminator. */ + while (nl >= 2 && (np[0] || np[1])) { + np += 2; + nl -= 2; + } + if (nl < 2) + return (-1);/* Terminator not found */ + entries[i].name_len = np - entries[i].utf16name; + np += 2; + nl -= 2; + } + break; + } + case kAttributes: + { + int allAreDefined; + + if ((p = header_bytes(a, 2)) == NULL) + return (-1); + allAreDefined = *p; + if (h->attrBools != NULL) + return (-1); + h->attrBools = calloc((size_t)zip->numFiles, + sizeof(*h->attrBools)); + if (h->attrBools == NULL) + return (-1); + if (allAreDefined) + memset(h->attrBools, 1, (size_t)zip->numFiles); + else { + if (read_Bools(a, h->attrBools, + (size_t)zip->numFiles) < 0) + return (-1); + } + for (i = 0; i < zip->numFiles; i++) { + if (h->attrBools[i]) { + if ((p = header_bytes(a, 4)) == NULL) + return (-1); + entries[i].attr = archive_le32dec(p); + } + } + break; + } + case kDummy: + if (ll == 0) + break; + __LA_FALLTHROUGH; + default: + if (header_bytes(a, ll) == NULL) + return (-1); + break; + } + } + + /* + * Set up entry's attributes. + */ + folders = si->ci.folders; + eindex = sindex = 0; + folderIndex = indexInFolder = 0; + for (i = 0; i < zip->numFiles; i++) { + if (h->emptyStreamBools == NULL || h->emptyStreamBools[i] == 0) + entries[i].flg |= HAS_STREAM; + /* The high 16 bits of attributes is a posix file mode. */ + entries[i].mode = entries[i].attr >> 16; + if (entries[i].flg & HAS_STREAM) { + if ((size_t)sindex >= si->ss.unpack_streams) + return (-1); + if (entries[i].mode == 0) + entries[i].mode = AE_IFREG | 0666; + if (si->ss.digestsDefined[sindex]) + entries[i].flg |= CRC32_IS_SET; + entries[i].ssIndex = sindex; + sindex++; + } else { + int dir; + if (h->emptyFileBools == NULL) + dir = 1; + else { + if (h->emptyFileBools[eindex]) + dir = 0; + else + dir = 1; + eindex++; + } + if (entries[i].mode == 0) { + if (dir) + entries[i].mode = AE_IFDIR | 0777; + else + entries[i].mode = AE_IFREG | 0666; + } else if (dir && + (entries[i].mode & AE_IFMT) != AE_IFDIR) { + entries[i].mode &= ~AE_IFMT; + entries[i].mode |= AE_IFDIR; + } + if ((entries[i].mode & AE_IFMT) == AE_IFDIR && + entries[i].name_len >= 2 && + (entries[i].utf16name[entries[i].name_len-2] != '/' || + entries[i].utf16name[entries[i].name_len-1] != 0)) { + entries[i].utf16name[entries[i].name_len] = '/'; + entries[i].utf16name[entries[i].name_len+1] = 0; + entries[i].name_len += 2; + } + entries[i].ssIndex = -1; + } + if (entries[i].attr & 0x01) + entries[i].mode &= ~0222;/* Read only. */ + + if ((entries[i].flg & HAS_STREAM) == 0 && indexInFolder == 0) { + /* + * The entry is an empty file or a directory file, + * those both have no contents. + */ + entries[i].folderIndex = -1; + continue; + } + if (indexInFolder == 0) { + for (;;) { + if (folderIndex >= si->ci.numFolders) + return (-1); + if (folders[folderIndex].numUnpackStreams) + break; + folderIndex++; + } + } + entries[i].folderIndex = folderIndex; + if ((entries[i].flg & HAS_STREAM) == 0) + continue; + indexInFolder++; + if (indexInFolder >= folders[folderIndex].numUnpackStreams) { + folderIndex++; + indexInFolder = 0; + } + } + + return (0); +} + +#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) +static void +fileTimeToUtc(uint64_t fileTime, time_t *timep, long *ns) +{ + + if (fileTime >= EPOC_TIME) { + fileTime -= EPOC_TIME; + /* milli seconds base */ + *timep = (time_t)(fileTime / 10000000); + /* nano seconds base */ + *ns = (long)(fileTime % 10000000) * 100; + } else { + *timep = 0; + *ns = 0; + } +} + +static int +read_Times(struct archive_read *a, struct _7z_header_info *h, int type) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + const unsigned char *p; + struct _7zip_entry *entries = zip->entries; + unsigned char *timeBools; + int allAreDefined; + unsigned i; + + timeBools = calloc((size_t)zip->numFiles, sizeof(*timeBools)); + if (timeBools == NULL) + return (-1); + + /* Read allAreDefined. */ + if ((p = header_bytes(a, 1)) == NULL) + goto failed; + allAreDefined = *p; + if (allAreDefined) + memset(timeBools, 1, (size_t)zip->numFiles); + else { + if (read_Bools(a, timeBools, (size_t)zip->numFiles) < 0) + goto failed; + } + + /* Read external. */ + if ((p = header_bytes(a, 1)) == NULL) + goto failed; + if (*p) { + if (parse_7zip_uint64(a, &(h->dataIndex)) < 0) + goto failed; + if (UMAX_ENTRY < h->dataIndex) + goto failed; + } + + for (i = 0; i < zip->numFiles; i++) { + if (!timeBools[i]) + continue; + if ((p = header_bytes(a, 8)) == NULL) + goto failed; + switch (type) { + case kCTime: + fileTimeToUtc(archive_le64dec(p), + &(entries[i].ctime), + &(entries[i].ctime_ns)); + entries[i].flg |= CTIME_IS_SET; + break; + case kATime: + fileTimeToUtc(archive_le64dec(p), + &(entries[i].atime), + &(entries[i].atime_ns)); + entries[i].flg |= ATIME_IS_SET; + break; + case kMTime: + fileTimeToUtc(archive_le64dec(p), + &(entries[i].mtime), + &(entries[i].mtime_ns)); + entries[i].flg |= MTIME_IS_SET; + break; + } + } + + free(timeBools); + return (0); +failed: + free(timeBools); + return (-1); +} + +static int +decode_encoded_header_info(struct archive_read *a, struct _7z_stream_info *si) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + + errno = 0; + if (read_StreamsInfo(a, si) < 0) { + if (errno == ENOMEM) + archive_set_error(&a->archive, -1, + "Couldn't allocate memory"); + else + archive_set_error(&a->archive, -1, + "Malformed 7-Zip archive"); + return (ARCHIVE_FATAL); + } + + if (si->pi.numPackStreams == 0 || si->ci.numFolders == 0) { + archive_set_error(&a->archive, -1, "Malformed 7-Zip archive"); + return (ARCHIVE_FATAL); + } + + if (zip->header_offset < si->pi.pos + si->pi.sizes[0] || + (int64_t)(si->pi.pos + si->pi.sizes[0]) < 0 || + si->pi.sizes[0] == 0 || (int64_t)si->pi.pos < 0) { + archive_set_error(&a->archive, -1, "Malformed Header offset"); + return (ARCHIVE_FATAL); + } + + return (ARCHIVE_OK); +} + +static const unsigned char * +header_bytes(struct archive_read *a, size_t rbytes) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + const unsigned char *p; + + if (zip->header_bytes_remaining < rbytes) + return (NULL); + if (zip->pack_stream_bytes_unconsumed) + read_consume(a); + + if (zip->header_is_encoded == 0) { + p = __archive_read_ahead(a, rbytes, NULL); + if (p == NULL) + return (NULL); + zip->header_bytes_remaining -= rbytes; + zip->pack_stream_bytes_unconsumed = rbytes; + } else { + const void *buff; + ssize_t bytes; + + bytes = read_stream(a, &buff, rbytes, rbytes); + if (bytes <= 0) + return (NULL); + zip->header_bytes_remaining -= bytes; + p = buff; + } + + /* Update checksum */ + zip->header_crc32 = crc32(zip->header_crc32, p, (unsigned)rbytes); + return (p); +} + +static int +slurp_central_directory(struct archive_read *a, struct _7zip *zip, + struct _7z_header_info *header) +{ + const unsigned char *p; + uint64_t next_header_offset; + uint64_t next_header_size; + uint32_t next_header_crc; + ssize_t bytes_avail; + int check_header_crc, r; + + if ((p = __archive_read_ahead(a, 32, &bytes_avail)) == NULL) + return (ARCHIVE_FATAL); + + if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) { + /* This is an executable ? Must be self-extracting... */ + r = skip_sfx(a, bytes_avail); + if (r < ARCHIVE_WARN) + return (r); + if ((p = __archive_read_ahead(a, 32, &bytes_avail)) == NULL) + return (ARCHIVE_FATAL); + } + zip->seek_base += 32; + + if (memcmp(p, _7ZIP_SIGNATURE, 6) != 0) { + archive_set_error(&a->archive, -1, "Not 7-Zip archive file"); + return (ARCHIVE_FATAL); + } + + /* CRC check. */ + if (crc32(0, (const unsigned char *)p + 12, 20) + != archive_le32dec(p + 8)) { + archive_set_error(&a->archive, -1, "Header CRC error"); + return (ARCHIVE_FATAL); + } + + next_header_offset = archive_le64dec(p + 12); + next_header_size = archive_le64dec(p + 20); + next_header_crc = archive_le32dec(p + 28); + + if (next_header_size == 0) + /* There is no entry in an archive file. */ + return (ARCHIVE_EOF); + + if (((int64_t)next_header_offset) < 0) { + archive_set_error(&a->archive, -1, "Malformed 7-Zip archive"); + return (ARCHIVE_FATAL); + } + __archive_read_consume(a, 32); + if (next_header_offset != 0) { + if (bytes_avail >= (ssize_t)next_header_offset) + __archive_read_consume(a, next_header_offset); + else if (__archive_read_seek(a, + next_header_offset + zip->seek_base, SEEK_SET) < 0) + return (ARCHIVE_FATAL); + } + zip->stream_offset = next_header_offset; + zip->header_offset = next_header_offset; + zip->header_bytes_remaining = next_header_size; + zip->header_crc32 = 0; + zip->header_is_encoded = 0; + zip->header_is_being_read = 1; + zip->has_encrypted_entries = 0; + check_header_crc = 1; + + if ((p = header_bytes(a, 1)) == NULL) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated 7-Zip file body"); + return (ARCHIVE_FATAL); + } + /* Parse ArchiveProperties. */ + switch (p[0]) { + case kEncodedHeader: + /* + * The archive has an encoded header and we have to decode it + * in order to parse the header correctly. + */ + r = decode_encoded_header_info(a, &(zip->si)); + + /* Check the EncodedHeader CRC.*/ + if (r == 0 && zip->header_crc32 != next_header_crc) { + archive_set_error(&a->archive, -1, + "Damaged 7-Zip archive"); + r = -1; + } + if (r == 0) { + if (zip->si.ci.folders[0].digest_defined) + next_header_crc = zip->si.ci.folders[0].digest; + else + check_header_crc = 0; + if (zip->pack_stream_bytes_unconsumed) + read_consume(a); + r = setup_decode_folder(a, zip->si.ci.folders, 1); + if (r == 0) { + zip->header_bytes_remaining = + zip->folder_outbytes_remaining; + r = seek_pack(a); + } + } + /* Clean up StreamsInfo. */ + free_StreamsInfo(&(zip->si)); + memset(&(zip->si), 0, sizeof(zip->si)); + if (r < 0) + return (ARCHIVE_FATAL); + zip->header_is_encoded = 1; + zip->header_crc32 = 0; + /* FALL THROUGH */ + case kHeader: + /* + * Parse the header. + */ + errno = 0; + r = read_Header(a, header, zip->header_is_encoded); + if (r < 0) { + if (errno == ENOMEM) + archive_set_error(&a->archive, -1, + "Couldn't allocate memory"); + else + archive_set_error(&a->archive, -1, + "Damaged 7-Zip archive"); + return (ARCHIVE_FATAL); + } + + /* + * Must be kEnd. + */ + if ((p = header_bytes(a, 1)) == NULL ||*p != kEnd) { + archive_set_error(&a->archive, -1, + "Malformed 7-Zip archive"); + return (ARCHIVE_FATAL); + } + + /* Check the Header CRC.*/ + if (check_header_crc && zip->header_crc32 != next_header_crc) { + archive_set_error(&a->archive, -1, + "Malformed 7-Zip archive"); + return (ARCHIVE_FATAL); + } + break; + default: + archive_set_error(&a->archive, -1, + "Unexpected Property ID = %X", p[0]); + return (ARCHIVE_FATAL); + } + + /* Clean up variables be used for decoding the archive header */ + zip->pack_stream_remaining = 0; + zip->pack_stream_index = 0; + zip->folder_outbytes_remaining = 0; + zip->uncompressed_buffer_bytes_remaining = 0; + zip->pack_stream_bytes_unconsumed = 0; + zip->header_is_being_read = 0; + + return (ARCHIVE_OK); +} + +static ssize_t +get_uncompressed_data(struct archive_read *a, const void **buff, size_t size, + size_t minimum) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + ssize_t bytes_avail; + + if (zip->codec == _7Z_COPY && zip->codec2 == (unsigned long)-1) { + /* Copy mode. */ + + *buff = __archive_read_ahead(a, minimum, &bytes_avail); + if (bytes_avail <= 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated 7-Zip file data"); + return (ARCHIVE_FATAL); + } + if ((size_t)bytes_avail > + zip->uncompressed_buffer_bytes_remaining) + bytes_avail = (ssize_t) + zip->uncompressed_buffer_bytes_remaining; + if ((size_t)bytes_avail > size) + bytes_avail = (ssize_t)size; + + zip->pack_stream_bytes_unconsumed = bytes_avail; + } else if (zip->uncompressed_buffer_pointer == NULL) { + /* Decompression has failed. */ + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, "Damaged 7-Zip archive"); + return (ARCHIVE_FATAL); + } else { + /* Packed mode. */ + if (minimum > zip->uncompressed_buffer_bytes_remaining) { + /* + * If remaining uncompressed data size is less than + * the minimum size, fill the buffer up to the + * minimum size. + */ + if (extract_pack_stream(a, minimum) < 0) + return (ARCHIVE_FATAL); + } + if (size > zip->uncompressed_buffer_bytes_remaining) + bytes_avail = (ssize_t) + zip->uncompressed_buffer_bytes_remaining; + else + bytes_avail = (ssize_t)size; + *buff = zip->uncompressed_buffer_pointer; + zip->uncompressed_buffer_pointer += bytes_avail; + } + zip->uncompressed_buffer_bytes_remaining -= bytes_avail; + return (bytes_avail); +} + +static ssize_t +extract_pack_stream(struct archive_read *a, size_t minimum) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + ssize_t bytes_avail; + int r; + + if (zip->codec == _7Z_COPY && zip->codec2 == (unsigned long)-1) { + if (minimum == 0) + minimum = 1; + if (__archive_read_ahead(a, minimum, &bytes_avail) == NULL + || bytes_avail <= 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated 7-Zip file body"); + return (ARCHIVE_FATAL); + } + if (bytes_avail > (ssize_t)zip->pack_stream_inbytes_remaining) + bytes_avail = (ssize_t)zip->pack_stream_inbytes_remaining; + zip->pack_stream_inbytes_remaining -= bytes_avail; + if (bytes_avail > (ssize_t)zip->folder_outbytes_remaining) + bytes_avail = (ssize_t)zip->folder_outbytes_remaining; + zip->folder_outbytes_remaining -= bytes_avail; + zip->uncompressed_buffer_bytes_remaining = bytes_avail; + return (ARCHIVE_OK); + } + + /* If the buffer hasn't been allocated, allocate it now. */ + if (zip->uncompressed_buffer == NULL) { + zip->uncompressed_buffer_size = UBUFF_SIZE; + if (zip->uncompressed_buffer_size < minimum) { + zip->uncompressed_buffer_size = minimum + 1023; + zip->uncompressed_buffer_size &= ~0x3ff; + } + zip->uncompressed_buffer = + malloc(zip->uncompressed_buffer_size); + if (zip->uncompressed_buffer == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for 7-Zip decompression"); + return (ARCHIVE_FATAL); + } + zip->uncompressed_buffer_bytes_remaining = 0; + } else if (zip->uncompressed_buffer_size < minimum || + zip->uncompressed_buffer_bytes_remaining < minimum) { + /* + * Make sure the uncompressed buffer can have bytes + * at least `minimum' bytes. + * NOTE: This case happen when reading the header. + */ + size_t used; + if (zip->uncompressed_buffer_pointer != 0) + used = zip->uncompressed_buffer_pointer - + zip->uncompressed_buffer; + else + used = 0; + if (zip->uncompressed_buffer_size < minimum) { + /* + * Expand the uncompressed buffer up to + * the minimum size. + */ + void *p; + size_t new_size; + + new_size = minimum + 1023; + new_size &= ~0x3ff; + p = realloc(zip->uncompressed_buffer, new_size); + if (p == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for 7-Zip decompression"); + return (ARCHIVE_FATAL); + } + zip->uncompressed_buffer = (unsigned char *)p; + zip->uncompressed_buffer_size = new_size; + } + /* + * Move unconsumed bytes to the head. + */ + if (used) { + memmove(zip->uncompressed_buffer, + zip->uncompressed_buffer + used, + zip->uncompressed_buffer_bytes_remaining); + } + } else + zip->uncompressed_buffer_bytes_remaining = 0; + zip->uncompressed_buffer_pointer = NULL; + for (;;) { + size_t bytes_in, bytes_out; + const void *buff_in; + unsigned char *buff_out; + int end_of_data; + + /* + * Note: '1' here is a performance optimization. + * Recall that the decompression layer returns a count of + * available bytes; asking for more than that forces the + * decompressor to combine reads by copying data. + */ + buff_in = __archive_read_ahead(a, 1, &bytes_avail); + if (bytes_avail <= 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated 7-Zip file body"); + return (ARCHIVE_FATAL); + } + + buff_out = zip->uncompressed_buffer + + zip->uncompressed_buffer_bytes_remaining; + bytes_out = zip->uncompressed_buffer_size + - zip->uncompressed_buffer_bytes_remaining; + bytes_in = bytes_avail; + if (bytes_in > zip->pack_stream_inbytes_remaining) + bytes_in = (size_t)zip->pack_stream_inbytes_remaining; + /* Drive decompression. */ + r = decompress(a, zip, buff_out, &bytes_out, + buff_in, &bytes_in); + switch (r) { + case ARCHIVE_OK: + end_of_data = 0; + break; + case ARCHIVE_EOF: + end_of_data = 1; + break; + default: + return (ARCHIVE_FATAL); + } + zip->pack_stream_inbytes_remaining -= bytes_in; + if (bytes_out > zip->folder_outbytes_remaining) + bytes_out = (size_t)zip->folder_outbytes_remaining; + zip->folder_outbytes_remaining -= bytes_out; + zip->uncompressed_buffer_bytes_remaining += bytes_out; + zip->pack_stream_bytes_unconsumed = bytes_in; + + /* + * Continue decompression until uncompressed_buffer is full. + */ + if (zip->uncompressed_buffer_bytes_remaining == + zip->uncompressed_buffer_size) + break; + if (zip->codec2 == _7Z_X86 && zip->odd_bcj_size && + zip->uncompressed_buffer_bytes_remaining + 5 > + zip->uncompressed_buffer_size) + break; + if (zip->pack_stream_inbytes_remaining == 0 && + zip->folder_outbytes_remaining == 0) + break; + if (end_of_data || (bytes_in == 0 && bytes_out == 0)) { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, "Damaged 7-Zip archive"); + return (ARCHIVE_FATAL); + } + read_consume(a); + } + if (zip->uncompressed_buffer_bytes_remaining < minimum) { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, "Damaged 7-Zip archive"); + return (ARCHIVE_FATAL); + } + zip->uncompressed_buffer_pointer = zip->uncompressed_buffer; + return (ARCHIVE_OK); +} + +static int +seek_pack(struct archive_read *a) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + int64_t pack_offset; + + if (zip->pack_stream_remaining <= 0) { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, "Damaged 7-Zip archive"); + return (ARCHIVE_FATAL); + } + zip->pack_stream_inbytes_remaining = + zip->si.pi.sizes[zip->pack_stream_index]; + pack_offset = zip->si.pi.positions[zip->pack_stream_index]; + if (zip->stream_offset != pack_offset) { + if (0 > __archive_read_seek(a, pack_offset + zip->seek_base, + SEEK_SET)) + return (ARCHIVE_FATAL); + zip->stream_offset = pack_offset; + } + zip->pack_stream_index++; + zip->pack_stream_remaining--; + return (ARCHIVE_OK); +} + +static ssize_t +read_stream(struct archive_read *a, const void **buff, size_t size, + size_t minimum) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + uint64_t skip_bytes = 0; + ssize_t r; + + if (zip->uncompressed_buffer_bytes_remaining == 0) { + if (zip->pack_stream_inbytes_remaining > 0) { + r = extract_pack_stream(a, 0); + if (r < 0) + return (r); + return (get_uncompressed_data(a, buff, size, minimum)); + } else if (zip->folder_outbytes_remaining > 0) { + /* Extract a remaining pack stream. */ + r = extract_pack_stream(a, 0); + if (r < 0) + return (r); + return (get_uncompressed_data(a, buff, size, minimum)); + } + } else + return (get_uncompressed_data(a, buff, size, minimum)); + + /* + * Current pack stream has been consumed. + */ + if (zip->pack_stream_remaining == 0) { + if (zip->header_is_being_read) { + /* Invalid sequence. This might happen when + * reading a malformed archive. */ + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, "Malformed 7-Zip archive"); + return (ARCHIVE_FATAL); + } + + /* + * All current folder's pack streams have been + * consumed. Switch to next folder. + */ + if (zip->folder_index == 0 && + (zip->si.ci.folders[zip->entry->folderIndex].skipped_bytes + || zip->folder_index != zip->entry->folderIndex)) { + zip->folder_index = zip->entry->folderIndex; + skip_bytes = + zip->si.ci.folders[zip->folder_index].skipped_bytes; + } + + if (zip->folder_index >= zip->si.ci.numFolders) { + /* + * We have consumed all folders and its pack streams. + */ + *buff = NULL; + return (0); + } + r = setup_decode_folder(a, + &(zip->si.ci.folders[zip->folder_index]), 0); + if (r != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + zip->folder_index++; + } + + /* + * Switch to next pack stream. + */ + r = seek_pack(a); + if (r < 0) + return (r); + + /* Extract a new pack stream. */ + r = extract_pack_stream(a, 0); + if (r < 0) + return (r); + + /* + * Skip the bytes we already has skipped in skip_stream(). + */ + while (skip_bytes) { + ssize_t skipped; + + if (zip->uncompressed_buffer_bytes_remaining == 0) { + if (zip->pack_stream_inbytes_remaining > 0) { + r = extract_pack_stream(a, 0); + if (r < 0) + return (r); + } else if (zip->folder_outbytes_remaining > 0) { + /* Extract a remaining pack stream. */ + r = extract_pack_stream(a, 0); + if (r < 0) + return (r); + } else { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated 7-Zip file body"); + return (ARCHIVE_FATAL); + } + } + skipped = get_uncompressed_data( + a, buff, (size_t)skip_bytes, 0); + if (skipped < 0) + return (skipped); + skip_bytes -= skipped; + if (zip->pack_stream_bytes_unconsumed) + read_consume(a); + } + + return (get_uncompressed_data(a, buff, size, minimum)); +} + +static int +setup_decode_folder(struct archive_read *a, struct _7z_folder *folder, + int header) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + const struct _7z_coder *coder1, *coder2; + const char *cname = (header)?"archive header":"file content"; + unsigned i; + int r, found_bcj2 = 0; + + /* + * Release the memory which the previous folder used for BCJ2. + */ + for (i = 0; i < 3; i++) { + free(zip->sub_stream_buff[i]); + zip->sub_stream_buff[i] = NULL; + } + + /* + * Initialize a stream reader. + */ + zip->pack_stream_remaining = (unsigned)folder->numPackedStreams; + zip->pack_stream_index = (unsigned)folder->packIndex; + zip->folder_outbytes_remaining = folder_uncompressed_size(folder); + zip->uncompressed_buffer_bytes_remaining = 0; + + /* + * Check coder types. + */ + for (i = 0; i < folder->numCoders; i++) { + switch(folder->coders[i].codec) { + case _7Z_CRYPTO_MAIN_ZIP: + case _7Z_CRYPTO_RAR_29: + case _7Z_CRYPTO_AES_256_SHA_256: { + /* For entry that is associated with this folder, mark + it as encrypted (data+metadata). */ + zip->has_encrypted_entries = 1; + if (a->entry) { + archive_entry_set_is_data_encrypted(a->entry, 1); + archive_entry_set_is_metadata_encrypted(a->entry, 1); + } + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "The %s is encrypted, " + "but currently not supported", cname); + return (ARCHIVE_FATAL); + } + case _7Z_X86_BCJ2: { + found_bcj2++; + break; + } + } + } + /* Now that we've checked for encryption, if there were still no + * encrypted entries found we can say for sure that there are none. + */ + if (zip->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) { + zip->has_encrypted_entries = 0; + } + + if ((folder->numCoders > 2 && !found_bcj2) || found_bcj2 > 1) { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "The %s is encoded with many filters, " + "but currently not supported", cname); + return (ARCHIVE_FATAL); + } + coder1 = &(folder->coders[0]); + if (folder->numCoders == 2) + coder2 = &(folder->coders[1]); + else + coder2 = NULL; + + if (found_bcj2) { + /* + * Preparation to decode BCJ2. + * Decoding BCJ2 requires four sources. Those are at least, + * as far as I know, two types of the storage form. + */ + const struct _7z_coder *fc = folder->coders; + static const struct _7z_coder coder_copy = {0, 1, 1, 0, NULL}; + const struct _7z_coder *scoder[3] = + {&coder_copy, &coder_copy, &coder_copy}; + const void *buff; + ssize_t bytes; + unsigned char *b[3] = {NULL, NULL, NULL}; + uint64_t sunpack[3] ={-1, -1, -1}; + size_t s[3] = {0, 0, 0}; + int idx[3] = {0, 1, 2}; + + if (folder->numCoders == 4 && fc[3].codec == _7Z_X86_BCJ2 && + folder->numInStreams == 7 && folder->numOutStreams == 4 && + zip->pack_stream_remaining == 4) { + /* Source type 1 made by 7zr or 7z with -m options. */ + if (folder->bindPairs[0].inIndex == 5) { + /* The form made by 7zr */ + idx[0] = 1; idx[1] = 2; idx[2] = 0; + scoder[1] = &(fc[1]); + scoder[2] = &(fc[0]); + sunpack[1] = folder->unPackSize[1]; + sunpack[2] = folder->unPackSize[0]; + coder1 = &(fc[2]); + } else { + /* + * NOTE: Some patterns do not work. + * work: + * 7z a -m0=BCJ2 -m1=COPY -m2=COPY + * -m3=(any) + * 7z a -m0=BCJ2 -m1=COPY -m2=(any) + * -m3=COPY + * 7z a -m0=BCJ2 -m1=(any) -m2=COPY + * -m3=COPY + * not work: + * other patterns. + * + * We have to handle this like `pipe' or + * our libarchive7s filter frame work, + * decoding the BCJ2 main stream sequentially, + * m3 -> m2 -> m1 -> BCJ2. + * + */ + if (fc[0].codec == _7Z_COPY && + fc[1].codec == _7Z_COPY) + coder1 = &(folder->coders[2]); + else if (fc[0].codec == _7Z_COPY && + fc[2].codec == _7Z_COPY) + coder1 = &(folder->coders[1]); + else if (fc[1].codec == _7Z_COPY && + fc[2].codec == _7Z_COPY) + coder1 = &(folder->coders[0]); + else { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Unsupported form of " + "BCJ2 streams"); + return (ARCHIVE_FATAL); + } + } + coder2 = &(fc[3]); + zip->main_stream_bytes_remaining = + (size_t)folder->unPackSize[2]; + } else if (coder2 != NULL && coder2->codec == _7Z_X86_BCJ2 && + zip->pack_stream_remaining == 4 && + folder->numInStreams == 5 && folder->numOutStreams == 2) { + /* Source type 0 made by 7z */ + zip->main_stream_bytes_remaining = + (size_t)folder->unPackSize[0]; + } else { + /* We got an unexpected form. */ + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Unsupported form of BCJ2 streams"); + return (ARCHIVE_FATAL); + } + + /* Skip the main stream at this time. */ + if ((r = seek_pack(a)) < 0) + return (r); + zip->pack_stream_bytes_unconsumed = + (size_t)zip->pack_stream_inbytes_remaining; + read_consume(a); + + /* Read following three sub streams. */ + for (i = 0; i < 3; i++) { + const struct _7z_coder *coder = scoder[i]; + + if ((r = seek_pack(a)) < 0) { + free(b[0]); free(b[1]); free(b[2]); + return (r); + } + + if (sunpack[i] == (uint64_t)-1) + zip->folder_outbytes_remaining = + zip->pack_stream_inbytes_remaining; + else + zip->folder_outbytes_remaining = sunpack[i]; + + r = init_decompression(a, zip, coder, NULL); + if (r != ARCHIVE_OK) { + free(b[0]); free(b[1]); free(b[2]); + return (ARCHIVE_FATAL); + } + + /* Allocate memory for the decoded data of a sub + * stream. */ + b[i] = malloc((size_t)zip->folder_outbytes_remaining); + if (b[i] == NULL) { + free(b[0]); free(b[1]); free(b[2]); + archive_set_error(&a->archive, ENOMEM, + "No memory for 7-Zip decompression"); + return (ARCHIVE_FATAL); + } + + /* Extract a sub stream. */ + while (zip->pack_stream_inbytes_remaining > 0) { + r = (int)extract_pack_stream(a, 0); + if (r < 0) { + free(b[0]); free(b[1]); free(b[2]); + return (r); + } + bytes = get_uncompressed_data(a, &buff, + zip->uncompressed_buffer_bytes_remaining, + 0); + if (bytes < 0) { + free(b[0]); free(b[1]); free(b[2]); + return ((int)bytes); + } + memcpy(b[i]+s[i], buff, bytes); + s[i] += bytes; + if (zip->pack_stream_bytes_unconsumed) + read_consume(a); + } + } + + /* Set the sub streams to the right place. */ + for (i = 0; i < 3; i++) { + zip->sub_stream_buff[i] = b[idx[i]]; + zip->sub_stream_size[i] = s[idx[i]]; + zip->sub_stream_bytes_remaining[i] = s[idx[i]]; + } + + /* Allocate memory used for decoded main stream bytes. */ + if (zip->tmp_stream_buff == NULL) { + zip->tmp_stream_buff_size = 32 * 1024; + zip->tmp_stream_buff = + malloc(zip->tmp_stream_buff_size); + if (zip->tmp_stream_buff == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for 7-Zip decompression"); + return (ARCHIVE_FATAL); + } + } + zip->tmp_stream_bytes_avail = 0; + zip->tmp_stream_bytes_remaining = 0; + zip->odd_bcj_size = 0; + zip->bcj2_outPos = 0; + + /* + * Reset a stream reader in order to read the main stream + * of BCJ2. + */ + zip->pack_stream_remaining = 1; + zip->pack_stream_index = (unsigned)folder->packIndex; + zip->folder_outbytes_remaining = + folder_uncompressed_size(folder); + zip->uncompressed_buffer_bytes_remaining = 0; + } + + /* + * Initialize the decompressor for the new folder's pack streams. + */ + r = init_decompression(a, zip, coder1, coder2); + if (r != ARCHIVE_OK) + return (ARCHIVE_FATAL); + return (ARCHIVE_OK); +} + +static int64_t +skip_stream(struct archive_read *a, size_t skip_bytes) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + const void *p; + int64_t skipped_bytes; + size_t bytes = skip_bytes; + + if (zip->folder_index == 0) { + /* + * Optimization for a list mode. + * Avoid unnecessary decoding operations. + */ + zip->si.ci.folders[zip->entry->folderIndex].skipped_bytes + += skip_bytes; + return (skip_bytes); + } + + while (bytes) { + skipped_bytes = read_stream(a, &p, bytes, 0); + if (skipped_bytes < 0) + return (skipped_bytes); + if (skipped_bytes == 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated 7-Zip file body"); + return (ARCHIVE_FATAL); + } + bytes -= (size_t)skipped_bytes; + if (zip->pack_stream_bytes_unconsumed) + read_consume(a); + } + return (skip_bytes); +} + +/* + * Brought from LZMA SDK. + * + * Bra86.c -- Converter for x86 code (BCJ) + * 2008-10-04 : Igor Pavlov : Public domain + * + */ + +#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) + +static void +x86_Init(struct _7zip *zip) +{ + zip->bcj_state = 0; + zip->bcj_prevPosT = (size_t)0 - 1; + zip->bcj_prevMask = 0; + zip->bcj_ip = 5; +} + +static size_t +x86_Convert(struct _7zip *zip, uint8_t *data, size_t size) +{ + static const uint8_t kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; + static const uint8_t kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; + size_t bufferPos, prevPosT; + uint32_t ip, prevMask; + + if (size < 5) + return 0; + + bufferPos = 0; + prevPosT = zip->bcj_prevPosT; + prevMask = zip->bcj_prevMask; + ip = zip->bcj_ip; + + for (;;) { + uint8_t *p = data + bufferPos; + uint8_t *limit = data + size - 4; + + for (; p < limit; p++) + if ((*p & 0xFE) == 0xE8) + break; + bufferPos = (size_t)(p - data); + if (p >= limit) + break; + prevPosT = bufferPos - prevPosT; + if (prevPosT > 3) + prevMask = 0; + else { + prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7; + if (prevMask != 0) { + unsigned char b = + p[4 - kMaskToBitNumber[prevMask]]; + if (!kMaskToAllowedStatus[prevMask] || + Test86MSByte(b)) { + prevPosT = bufferPos; + prevMask = ((prevMask << 1) & 0x7) | 1; + bufferPos++; + continue; + } + } + } + prevPosT = bufferPos; + + if (Test86MSByte(p[4])) { + uint32_t src = ((uint32_t)p[4] << 24) | + ((uint32_t)p[3] << 16) | ((uint32_t)p[2] << 8) | + ((uint32_t)p[1]); + uint32_t dest; + for (;;) { + uint8_t b; + int b_index; + + dest = src - (ip + (uint32_t)bufferPos); + if (prevMask == 0) + break; + b_index = kMaskToBitNumber[prevMask] * 8; + b = (uint8_t)(dest >> (24 - b_index)); + if (!Test86MSByte(b)) + break; + src = dest ^ ((1 << (32 - b_index)) - 1); + } + p[4] = (uint8_t)(~(((dest >> 24) & 1) - 1)); + p[3] = (uint8_t)(dest >> 16); + p[2] = (uint8_t)(dest >> 8); + p[1] = (uint8_t)dest; + bufferPos += 5; + } else { + prevMask = ((prevMask << 1) & 0x7) | 1; + bufferPos++; + } + } + zip->bcj_prevPosT = prevPosT; + zip->bcj_prevMask = prevMask; + zip->bcj_ip += (uint32_t)bufferPos; + return (bufferPos); +} + +/* + * Brought from LZMA SDK. + * + * Bcj2.c -- Converter for x86 code (BCJ2) + * 2008-10-04 : Igor Pavlov : Public domain + * + */ + +#define SZ_ERROR_DATA ARCHIVE_FAILED + +#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80) +#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)) + +#define kNumTopBits 24 +#define kTopValue ((uint32_t)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +#define RC_READ_BYTE (*buffer++) +#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; } +#define RC_INIT2 zip->bcj2_code = 0; zip->bcj2_range = 0xFFFFFFFF; \ + { int ii; for (ii = 0; ii < 5; ii++) { RC_TEST; zip->bcj2_code = (zip->bcj2_code << 8) | RC_READ_BYTE; }} + +#define NORMALIZE if (zip->bcj2_range < kTopValue) { RC_TEST; zip->bcj2_range <<= 8; zip->bcj2_code = (zip->bcj2_code << 8) | RC_READ_BYTE; } + +#define IF_BIT_0(p) ttt = *(p); bound = (zip->bcj2_range >> kNumBitModelTotalBits) * ttt; if (zip->bcj2_code < bound) +#define UPDATE_0(p) zip->bcj2_range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE; +#define UPDATE_1(p) zip->bcj2_range -= bound; zip->bcj2_code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE; + +static ssize_t +Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize) +{ + size_t inPos = 0, outPos = 0; + const uint8_t *buf0, *buf1, *buf2, *buf3; + size_t size0, size1, size2, size3; + const uint8_t *buffer, *bufferLim; + unsigned int i, j; + + size0 = zip->tmp_stream_bytes_remaining; + buf0 = zip->tmp_stream_buff + zip->tmp_stream_bytes_avail - size0; + size1 = zip->sub_stream_bytes_remaining[0]; + buf1 = zip->sub_stream_buff[0] + zip->sub_stream_size[0] - size1; + size2 = zip->sub_stream_bytes_remaining[1]; + buf2 = zip->sub_stream_buff[1] + zip->sub_stream_size[1] - size2; + size3 = zip->sub_stream_bytes_remaining[2]; + buf3 = zip->sub_stream_buff[2] + zip->sub_stream_size[2] - size3; + + buffer = buf3; + bufferLim = buffer + size3; + + if (zip->bcj_state == 0) { + /* + * Initialize. + */ + zip->bcj2_prevByte = 0; + for (i = 0; + i < sizeof(zip->bcj2_p) / sizeof(zip->bcj2_p[0]); i++) + zip->bcj2_p[i] = kBitModelTotal >> 1; + RC_INIT2; + zip->bcj_state = 1; + } + + /* + * Gather the odd bytes of a previous call. + */ + for (i = 0; zip->odd_bcj_size > 0 && outPos < outSize; i++) { + outBuf[outPos++] = zip->odd_bcj[i]; + zip->odd_bcj_size--; + } + + if (outSize == 0) { + zip->bcj2_outPos += outPos; + return (outPos); + } + + for (;;) { + uint8_t b; + CProb *prob; + uint32_t bound; + uint32_t ttt; + + size_t limit = size0 - inPos; + if (outSize - outPos < limit) + limit = outSize - outPos; + + if (zip->bcj_state == 1) { + while (limit != 0) { + uint8_t bb = buf0[inPos]; + outBuf[outPos++] = bb; + if (IsJ(zip->bcj2_prevByte, bb)) { + zip->bcj_state = 2; + break; + } + inPos++; + zip->bcj2_prevByte = bb; + limit--; + } + } + + if (limit == 0 || outPos == outSize) + break; + zip->bcj_state = 1; + + b = buf0[inPos++]; + + if (b == 0xE8) + prob = zip->bcj2_p + zip->bcj2_prevByte; + else if (b == 0xE9) + prob = zip->bcj2_p + 256; + else + prob = zip->bcj2_p + 257; + + IF_BIT_0(prob) { + UPDATE_0(prob) + zip->bcj2_prevByte = b; + } else { + uint32_t dest; + const uint8_t *v; + uint8_t out[4]; + + UPDATE_1(prob) + if (b == 0xE8) { + v = buf1; + if (size1 < 4) + return SZ_ERROR_DATA; + buf1 += 4; + size1 -= 4; + } else { + v = buf2; + if (size2 < 4) + return SZ_ERROR_DATA; + buf2 += 4; + size2 -= 4; + } + dest = (((uint32_t)v[0] << 24) | + ((uint32_t)v[1] << 16) | + ((uint32_t)v[2] << 8) | + ((uint32_t)v[3])) - + ((uint32_t)zip->bcj2_outPos + (uint32_t)outPos + 4); + out[0] = (uint8_t)dest; + out[1] = (uint8_t)(dest >> 8); + out[2] = (uint8_t)(dest >> 16); + out[3] = zip->bcj2_prevByte = (uint8_t)(dest >> 24); + + for (i = 0; i < 4 && outPos < outSize; i++) + outBuf[outPos++] = out[i]; + if (i < 4) { + /* + * Save odd bytes which we could not add into + * the output buffer because of out of space. + */ + zip->odd_bcj_size = 4 -i; + for (; i < 4; i++) { + j = i - 4 + (unsigned)zip->odd_bcj_size; + zip->odd_bcj[j] = out[i]; + } + break; + } + } + } + zip->tmp_stream_bytes_remaining -= inPos; + zip->sub_stream_bytes_remaining[0] = size1; + zip->sub_stream_bytes_remaining[1] = size2; + zip->sub_stream_bytes_remaining[2] = bufferLim - buffer; + zip->bcj2_outPos += outPos; + + return ((ssize_t)outPos); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_all.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_all.c new file mode 100644 index 0000000..dea558b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_all.c @@ -0,0 +1,89 @@ +/*- + * Copyright (c) 2003-2011 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_all.c 174991 2007-12-30 04:58:22Z kientzle $"); + +#include "archive.h" +#include "archive_private.h" + +int +archive_read_support_format_all(struct archive *a) +{ + archive_check_magic(a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_format_all"); + + /* TODO: It would be nice to compute the ordering + * here automatically so that people who enable just + * a few formats can still get the benefits. That + * may just require the format registration to include + * a "maximum read-ahead" value (anything that uses seek + * would be essentially infinite read-ahead). The core + * bid management can then sort the bidders before calling + * them. + * + * If you implement the above, please return the list below + * to alphabetic order. + */ + + /* + * These bidders are all pretty cheap; they just examine a + * small initial part of the archive. If one of these bids + * high, we can maybe avoid running any of the more expensive + * bidders below. + */ + archive_read_support_format_ar(a); + archive_read_support_format_cpio(a); + archive_read_support_format_empty(a); + archive_read_support_format_lha(a); + archive_read_support_format_mtree(a); + archive_read_support_format_tar(a); + archive_read_support_format_xar(a); + archive_read_support_format_warc(a); + + /* + * Install expensive bidders last. By doing them last, we + * increase the chance that a high bid from someone else will + * make it unnecessary for these to do anything at all. + */ + /* These three have potentially large look-ahead. */ + archive_read_support_format_7zip(a); + archive_read_support_format_cab(a); + archive_read_support_format_rar(a); + archive_read_support_format_rar5(a); + archive_read_support_format_iso9660(a); + /* Seek is really bad, since it forces the read-ahead + * logic to discard buffered data. */ + archive_read_support_format_zip(a); + + /* Note: We always return ARCHIVE_OK here, even if some of the + * above return ARCHIVE_WARN. The intent here is to enable + * "as much as possible." Clients who need specific + * compression should enable those individually so they can + * verify the level of support. */ + /* Clear any warning messages set by the above functions. */ + archive_clear_error(a); + return (ARCHIVE_OK); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_ar.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_ar.c new file mode 100644 index 0000000..296b7db --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_ar.c @@ -0,0 +1,638 @@ +/*- + * Copyright (c) 2007 Kai Wang + * Copyright (c) 2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_ar.c 201101 2009-12-28 03:06:27Z kientzle $"); + +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_read_private.h" + +struct ar { + int64_t entry_bytes_remaining; + /* unconsumed is purely to track data we've gotten from readahead, + * but haven't yet marked as consumed. Must be paired with + * entry_bytes_remaining usage/modification. + */ + size_t entry_bytes_unconsumed; + int64_t entry_offset; + int64_t entry_padding; + char *strtab; + size_t strtab_size; + char read_global_header; +}; + +/* + * Define structure of the "ar" header. + */ +#define AR_name_offset 0 +#define AR_name_size 16 +#define AR_date_offset 16 +#define AR_date_size 12 +#define AR_uid_offset 28 +#define AR_uid_size 6 +#define AR_gid_offset 34 +#define AR_gid_size 6 +#define AR_mode_offset 40 +#define AR_mode_size 8 +#define AR_size_offset 48 +#define AR_size_size 10 +#define AR_fmag_offset 58 +#define AR_fmag_size 2 + +static int archive_read_format_ar_bid(struct archive_read *a, int); +static int archive_read_format_ar_cleanup(struct archive_read *a); +static int archive_read_format_ar_read_data(struct archive_read *a, + const void **buff, size_t *size, int64_t *offset); +static int archive_read_format_ar_skip(struct archive_read *a); +static int archive_read_format_ar_read_header(struct archive_read *a, + struct archive_entry *e); +static uint64_t ar_atol8(const char *p, unsigned char_cnt); +static uint64_t ar_atol10(const char *p, unsigned char_cnt); +static int ar_parse_gnu_filename_table(struct archive_read *a); +static int ar_parse_common_header(struct ar *ar, struct archive_entry *, + const char *h); + +int +archive_read_support_format_ar(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct ar *ar; + int r; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_format_ar"); + + ar = (struct ar *)calloc(1, sizeof(*ar)); + if (ar == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate ar data"); + return (ARCHIVE_FATAL); + } + ar->strtab = NULL; + + r = __archive_read_register_format(a, + ar, + "ar", + archive_read_format_ar_bid, + NULL, + archive_read_format_ar_read_header, + archive_read_format_ar_read_data, + archive_read_format_ar_skip, + NULL, + archive_read_format_ar_cleanup, + NULL, + NULL); + + if (r != ARCHIVE_OK) { + free(ar); + return (r); + } + return (ARCHIVE_OK); +} + +static int +archive_read_format_ar_cleanup(struct archive_read *a) +{ + struct ar *ar; + + ar = (struct ar *)(a->format->data); + free(ar->strtab); + free(ar); + (a->format->data) = NULL; + return (ARCHIVE_OK); +} + +static int +archive_read_format_ar_bid(struct archive_read *a, int best_bid) +{ + const void *h; + + (void)best_bid; /* UNUSED */ + + /* + * Verify the 8-byte file signature. + * TODO: Do we need to check more than this? + */ + if ((h = __archive_read_ahead(a, 8, NULL)) == NULL) + return (-1); + if (memcmp(h, "!\n", 8) == 0) { + return (64); + } + return (-1); +} + +static int +_ar_read_header(struct archive_read *a, struct archive_entry *entry, + struct ar *ar, const char *h, size_t *unconsumed) +{ + char filename[AR_name_size + 1]; + uint64_t number; /* Used to hold parsed numbers before validation. */ + size_t bsd_name_length, entry_size; + char *p, *st; + const void *b; + int r; + + /* Verify the magic signature on the file header. */ + if (strncmp(h + AR_fmag_offset, "`\n", 2) != 0) { + archive_set_error(&a->archive, EINVAL, + "Incorrect file header signature"); + return (ARCHIVE_FATAL); + } + + /* Copy filename into work buffer. */ + strncpy(filename, h + AR_name_offset, AR_name_size); + filename[AR_name_size] = '\0'; + + /* + * Guess the format variant based on the filename. + */ + if (a->archive.archive_format == ARCHIVE_FORMAT_AR) { + /* We don't already know the variant, so let's guess. */ + /* + * Biggest clue is presence of '/': GNU starts special + * filenames with '/', appends '/' as terminator to + * non-special names, so anything with '/' should be + * GNU except for BSD long filenames. + */ + if (strncmp(filename, "#1/", 3) == 0) + a->archive.archive_format = ARCHIVE_FORMAT_AR_BSD; + else if (strchr(filename, '/') != NULL) + a->archive.archive_format = ARCHIVE_FORMAT_AR_GNU; + else if (strncmp(filename, "__.SYMDEF", 9) == 0) + a->archive.archive_format = ARCHIVE_FORMAT_AR_BSD; + /* + * XXX Do GNU/SVR4 'ar' programs ever omit trailing '/' + * if name exactly fills 16-byte field? If so, we + * can't assume entries without '/' are BSD. XXX + */ + } + + /* Update format name from the code. */ + if (a->archive.archive_format == ARCHIVE_FORMAT_AR_GNU) + a->archive.archive_format_name = "ar (GNU/SVR4)"; + else if (a->archive.archive_format == ARCHIVE_FORMAT_AR_BSD) + a->archive.archive_format_name = "ar (BSD)"; + else + a->archive.archive_format_name = "ar"; + + /* + * Remove trailing spaces from the filename. GNU and BSD + * variants both pad filename area out with spaces. + * This will only be wrong if GNU/SVR4 'ar' implementations + * omit trailing '/' for 16-char filenames and we have + * a 16-char filename that ends in ' '. + */ + p = filename + AR_name_size - 1; + while (p >= filename && *p == ' ') { + *p = '\0'; + p--; + } + + /* + * Remove trailing slash unless first character is '/'. + * (BSD entries never end in '/', so this will only trim + * GNU-format entries. GNU special entries start with '/' + * and are not terminated in '/', so we don't trim anything + * that starts with '/'.) + */ + if (filename[0] != '/' && p > filename && *p == '/') { + *p = '\0'; + } + + if (p < filename) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Found entry with empty filename"); + return (ARCHIVE_FATAL); + } + + /* + * '//' is the GNU filename table. + * Later entries can refer to names in this table. + */ + if (strcmp(filename, "//") == 0) { + /* This must come before any call to _read_ahead. */ + ar_parse_common_header(ar, entry, h); + archive_entry_copy_pathname(entry, filename); + archive_entry_set_filetype(entry, AE_IFREG); + /* Get the size of the filename table. */ + number = ar_atol10(h + AR_size_offset, AR_size_size); + if (number > SIZE_MAX || number > 1024 * 1024 * 1024) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Filename table too large"); + return (ARCHIVE_FATAL); + } + entry_size = (size_t)number; + if (entry_size == 0) { + archive_set_error(&a->archive, EINVAL, + "Invalid string table"); + return (ARCHIVE_FATAL); + } + if (ar->strtab != NULL) { + archive_set_error(&a->archive, EINVAL, + "More than one string tables exist"); + return (ARCHIVE_FATAL); + } + + /* Read the filename table into memory. */ + st = malloc(entry_size); + if (st == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate filename table buffer"); + return (ARCHIVE_FATAL); + } + ar->strtab = st; + ar->strtab_size = entry_size; + + if (*unconsumed) { + __archive_read_consume(a, *unconsumed); + *unconsumed = 0; + } + + if ((b = __archive_read_ahead(a, entry_size, NULL)) == NULL) + return (ARCHIVE_FATAL); + memcpy(st, b, entry_size); + __archive_read_consume(a, entry_size); + /* All contents are consumed. */ + ar->entry_bytes_remaining = 0; + archive_entry_set_size(entry, ar->entry_bytes_remaining); + + /* Parse the filename table. */ + return (ar_parse_gnu_filename_table(a)); + } + + /* + * GNU variant handles long filenames by storing / + * to indicate a name stored in the filename table. + * XXX TODO: Verify that it's all digits... Don't be fooled + * by "/9xyz" XXX + */ + if (filename[0] == '/' && filename[1] >= '0' && filename[1] <= '9') { + number = ar_atol10(h + AR_name_offset + 1, AR_name_size - 1); + /* + * If we can't look up the real name, warn and return + * the entry with the wrong name. + */ + if (ar->strtab == NULL || number >= ar->strtab_size) { + archive_set_error(&a->archive, EINVAL, + "Can't find long filename for GNU/SVR4 archive entry"); + archive_entry_copy_pathname(entry, filename); + /* Parse the time, owner, mode, size fields. */ + ar_parse_common_header(ar, entry, h); + return (ARCHIVE_FATAL); + } + + archive_entry_copy_pathname(entry, &ar->strtab[(size_t)number]); + /* Parse the time, owner, mode, size fields. */ + return (ar_parse_common_header(ar, entry, h)); + } + + /* + * BSD handles long filenames by storing "#1/" followed by the + * length of filename as a decimal number, then prepends the + * the filename to the file contents. + */ + if (strncmp(filename, "#1/", 3) == 0) { + /* Parse the time, owner, mode, size fields. */ + /* This must occur before _read_ahead is called again. */ + ar_parse_common_header(ar, entry, h); + + /* Parse the size of the name, adjust the file size. */ + number = ar_atol10(h + AR_name_offset + 3, AR_name_size - 3); + /* Sanity check the filename length: + * = Must be <= SIZE_MAX - 1 + * = Must be <= 1MB + * = Cannot be bigger than the entire entry + */ + if (number > SIZE_MAX - 1 + || number > 1024 * 1024 + || (int64_t)number > ar->entry_bytes_remaining) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Bad input file size"); + return (ARCHIVE_FATAL); + } + bsd_name_length = (size_t)number; + ar->entry_bytes_remaining -= bsd_name_length; + /* Adjust file size reported to client. */ + archive_entry_set_size(entry, ar->entry_bytes_remaining); + + if (*unconsumed) { + __archive_read_consume(a, *unconsumed); + *unconsumed = 0; + } + + /* Read the long name into memory. */ + if ((b = __archive_read_ahead(a, bsd_name_length, NULL)) == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Truncated input file"); + return (ARCHIVE_FATAL); + } + /* Store it in the entry. */ + p = (char *)malloc(bsd_name_length + 1); + if (p == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate fname buffer"); + return (ARCHIVE_FATAL); + } + strncpy(p, b, bsd_name_length); + p[bsd_name_length] = '\0'; + + __archive_read_consume(a, bsd_name_length); + + archive_entry_copy_pathname(entry, p); + free(p); + return (ARCHIVE_OK); + } + + /* + * "/" is the SVR4/GNU archive symbol table. + * "/SYM64/" is the SVR4/GNU 64-bit variant archive symbol table. + */ + if (strcmp(filename, "/") == 0 || strcmp(filename, "/SYM64/") == 0) { + archive_entry_copy_pathname(entry, filename); + /* Parse the time, owner, mode, size fields. */ + r = ar_parse_common_header(ar, entry, h); + /* Force the file type to a regular file. */ + archive_entry_set_filetype(entry, AE_IFREG); + return (r); + } + + /* + * "__.SYMDEF" is a BSD archive symbol table. + */ + if (strcmp(filename, "__.SYMDEF") == 0) { + archive_entry_copy_pathname(entry, filename); + /* Parse the time, owner, mode, size fields. */ + return (ar_parse_common_header(ar, entry, h)); + } + + /* + * Otherwise, this is a standard entry. The filename + * has already been trimmed as much as possible, based + * on our current knowledge of the format. + */ + archive_entry_copy_pathname(entry, filename); + return (ar_parse_common_header(ar, entry, h)); +} + +static int +archive_read_format_ar_read_header(struct archive_read *a, + struct archive_entry *entry) +{ + struct ar *ar = (struct ar*)(a->format->data); + size_t unconsumed; + const void *header_data; + int ret; + + if (!ar->read_global_header) { + /* + * We are now at the beginning of the archive, + * so we need first consume the ar global header. + */ + __archive_read_consume(a, 8); + ar->read_global_header = 1; + /* Set a default format code for now. */ + a->archive.archive_format = ARCHIVE_FORMAT_AR; + } + + /* Read the header for the next file entry. */ + if ((header_data = __archive_read_ahead(a, 60, NULL)) == NULL) + /* Broken header. */ + return (ARCHIVE_EOF); + + unconsumed = 60; + + ret = _ar_read_header(a, entry, ar, (const char *)header_data, &unconsumed); + + if (unconsumed) + __archive_read_consume(a, unconsumed); + + return ret; +} + + +static int +ar_parse_common_header(struct ar *ar, struct archive_entry *entry, + const char *h) +{ + uint64_t n; + + /* Copy remaining header */ + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_mtime(entry, + (time_t)ar_atol10(h + AR_date_offset, AR_date_size), 0L); + archive_entry_set_uid(entry, + (uid_t)ar_atol10(h + AR_uid_offset, AR_uid_size)); + archive_entry_set_gid(entry, + (gid_t)ar_atol10(h + AR_gid_offset, AR_gid_size)); + archive_entry_set_mode(entry, + (mode_t)ar_atol8(h + AR_mode_offset, AR_mode_size)); + n = ar_atol10(h + AR_size_offset, AR_size_size); + + ar->entry_offset = 0; + ar->entry_padding = n % 2; + archive_entry_set_size(entry, n); + ar->entry_bytes_remaining = n; + return (ARCHIVE_OK); +} + +static int +archive_read_format_ar_read_data(struct archive_read *a, + const void **buff, size_t *size, int64_t *offset) +{ + ssize_t bytes_read; + struct ar *ar; + + ar = (struct ar *)(a->format->data); + + if (ar->entry_bytes_unconsumed) { + __archive_read_consume(a, ar->entry_bytes_unconsumed); + ar->entry_bytes_unconsumed = 0; + } + + if (ar->entry_bytes_remaining > 0) { + *buff = __archive_read_ahead(a, 1, &bytes_read); + if (bytes_read == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Truncated ar archive"); + return (ARCHIVE_FATAL); + } + if (bytes_read < 0) + return (ARCHIVE_FATAL); + if (bytes_read > ar->entry_bytes_remaining) + bytes_read = (ssize_t)ar->entry_bytes_remaining; + *size = bytes_read; + ar->entry_bytes_unconsumed = bytes_read; + *offset = ar->entry_offset; + ar->entry_offset += bytes_read; + ar->entry_bytes_remaining -= bytes_read; + return (ARCHIVE_OK); + } else { + int64_t skipped = __archive_read_consume(a, ar->entry_padding); + if (skipped >= 0) { + ar->entry_padding -= skipped; + } + if (ar->entry_padding) { + if (skipped >= 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Truncated ar archive- failed consuming padding"); + } + return (ARCHIVE_FATAL); + } + *buff = NULL; + *size = 0; + *offset = ar->entry_offset; + return (ARCHIVE_EOF); + } +} + +static int +archive_read_format_ar_skip(struct archive_read *a) +{ + int64_t bytes_skipped; + struct ar* ar; + + ar = (struct ar *)(a->format->data); + + bytes_skipped = __archive_read_consume(a, + ar->entry_bytes_remaining + ar->entry_padding + + ar->entry_bytes_unconsumed); + if (bytes_skipped < 0) + return (ARCHIVE_FATAL); + + ar->entry_bytes_remaining = 0; + ar->entry_bytes_unconsumed = 0; + ar->entry_padding = 0; + + return (ARCHIVE_OK); +} + +static int +ar_parse_gnu_filename_table(struct archive_read *a) +{ + struct ar *ar; + char *p; + size_t size; + + ar = (struct ar*)(a->format->data); + size = ar->strtab_size; + + for (p = ar->strtab; p < ar->strtab + size - 1; ++p) { + if (*p == '/') { + *p++ = '\0'; + if (*p != '\n') + goto bad_string_table; + *p = '\0'; + } + } + /* + * GNU ar always pads the table to an even size. + * The pad character is either '\n' or '`'. + */ + if (p != ar->strtab + size && *p != '\n' && *p != '`') + goto bad_string_table; + + /* Enforce zero termination. */ + ar->strtab[size - 1] = '\0'; + + return (ARCHIVE_OK); + +bad_string_table: + archive_set_error(&a->archive, EINVAL, + "Invalid string table"); + free(ar->strtab); + ar->strtab = NULL; + return (ARCHIVE_FATAL); +} + +static uint64_t +ar_atol8(const char *p, unsigned char_cnt) +{ + uint64_t l, limit, last_digit_limit; + unsigned int digit, base; + + base = 8; + limit = UINT64_MAX / base; + last_digit_limit = UINT64_MAX % base; + + while ((*p == ' ' || *p == '\t') && char_cnt-- > 0) + p++; + + l = 0; + digit = *p - '0'; + while (*p >= '0' && digit < base && char_cnt-- > 0) { + if (l>limit || (l == limit && digit > last_digit_limit)) { + l = UINT64_MAX; /* Truncate on overflow. */ + break; + } + l = (l * base) + digit; + digit = *++p - '0'; + } + return (l); +} + +static uint64_t +ar_atol10(const char *p, unsigned char_cnt) +{ + uint64_t l, limit, last_digit_limit; + unsigned int base, digit; + + base = 10; + limit = UINT64_MAX / base; + last_digit_limit = UINT64_MAX % base; + + while ((*p == ' ' || *p == '\t') && char_cnt-- > 0) + p++; + l = 0; + digit = *p - '0'; + while (*p >= '0' && digit < base && char_cnt-- > 0) { + if (l > limit || (l == limit && digit > last_digit_limit)) { + l = UINT64_MAX; /* Truncate on overflow. */ + break; + } + l = (l * base) + digit; + digit = *++p - '0'; + } + return (l); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_by_code.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_by_code.c new file mode 100644 index 0000000..034353d --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_by_code.c @@ -0,0 +1,77 @@ +/*- + * Copyright (c) 2003-2011 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#include "archive.h" +#include "archive_private.h" + +int +archive_read_support_format_by_code(struct archive *a, int format_code) +{ + archive_check_magic(a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_format_by_code"); + + switch (format_code & ARCHIVE_FORMAT_BASE_MASK) { + case ARCHIVE_FORMAT_7ZIP: + return archive_read_support_format_7zip(a); + break; + case ARCHIVE_FORMAT_AR: + return archive_read_support_format_ar(a); + break; + case ARCHIVE_FORMAT_CAB: + return archive_read_support_format_cab(a); + break; + case ARCHIVE_FORMAT_CPIO: + return archive_read_support_format_cpio(a); + break; + case ARCHIVE_FORMAT_ISO9660: + return archive_read_support_format_iso9660(a); + break; + case ARCHIVE_FORMAT_LHA: + return archive_read_support_format_lha(a); + break; + case ARCHIVE_FORMAT_MTREE: + return archive_read_support_format_mtree(a); + break; + case ARCHIVE_FORMAT_RAR: + return archive_read_support_format_rar(a); + break; + case ARCHIVE_FORMAT_RAR_V5: + return archive_read_support_format_rar5(a); + break; + case ARCHIVE_FORMAT_TAR: + return archive_read_support_format_tar(a); + break; + case ARCHIVE_FORMAT_XAR: + return archive_read_support_format_xar(a); + break; + case ARCHIVE_FORMAT_ZIP: + return archive_read_support_format_zip(a); + break; + } + return (ARCHIVE_FATAL); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_cab.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_cab.c new file mode 100644 index 0000000..a647530 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_cab.c @@ -0,0 +1,3227 @@ +/*- + * Copyright (c) 2010-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_ZLIB_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_private.h" +#include "archive_read_private.h" +#include "archive_endian.h" + + +struct lzx_dec { + /* Decoding status. */ + int state; + + /* + * Window to see last decoded data, from 32KBi to 2MBi. + */ + int w_size; + int w_mask; + /* Window buffer, which is a loop buffer. */ + unsigned char *w_buff; + /* The insert position to the window. */ + int w_pos; + /* The position where we can copy decoded code from the window. */ + int copy_pos; + /* The length how many bytes we can copy decoded code from + * the window. */ + int copy_len; + /* Translation reversal for x86 processor CALL byte sequence(E8). + * This is used for LZX only. */ + uint32_t translation_size; + char translation; + char block_type; +#define VERBATIM_BLOCK 1 +#define ALIGNED_OFFSET_BLOCK 2 +#define UNCOMPRESSED_BLOCK 3 + size_t block_size; + size_t block_bytes_avail; + /* Repeated offset. */ + int r0, r1, r2; + unsigned char rbytes[4]; + int rbytes_avail; + int length_header; + int position_slot; + int offset_bits; + + struct lzx_pos_tbl { + int base; + int footer_bits; + } *pos_tbl; + /* + * Bit stream reader. + */ + struct lzx_br { +#define CACHE_TYPE uint64_t +#define CACHE_BITS (8 * sizeof(CACHE_TYPE)) + /* Cache buffer. */ + CACHE_TYPE cache_buffer; + /* Indicates how many bits avail in cache_buffer. */ + int cache_avail; + unsigned char odd; + char have_odd; + } br; + + /* + * Huffman coding. + */ + struct huffman { + int len_size; + int freq[17]; + unsigned char *bitlen; + + /* + * Use a index table. It's faster than searching a huffman + * coding tree, which is a binary tree. But a use of a large + * index table causes L1 cache read miss many times. + */ + int max_bits; + int tbl_bits; + int tree_used; + /* Direct access table. */ + uint16_t *tbl; + } at, lt, mt, pt; + + int loop; + int error; +}; + +static const int slots[] = { + 30, 32, 34, 36, 38, 42, 50, 66, 98, 162, 290 +}; +#define SLOT_BASE 15 +#define SLOT_MAX 21/*->25*/ + +struct lzx_stream { + const unsigned char *next_in; + int64_t avail_in; + int64_t total_in; + unsigned char *next_out; + int64_t avail_out; + int64_t total_out; + struct lzx_dec *ds; +}; + +/* + * Cabinet file definitions. + */ +/* CFHEADER offset */ +#define CFHEADER_signature 0 +#define CFHEADER_cbCabinet 8 +#define CFHEADER_coffFiles 16 +#define CFHEADER_versionMinor 24 +#define CFHEADER_versionMajor 25 +#define CFHEADER_cFolders 26 +#define CFHEADER_cFiles 28 +#define CFHEADER_flags 30 +#define CFHEADER_setID 32 +#define CFHEADER_iCabinet 34 +#define CFHEADER_cbCFHeader 36 +#define CFHEADER_cbCFFolder 38 +#define CFHEADER_cbCFData 39 + +/* CFFOLDER offset */ +#define CFFOLDER_coffCabStart 0 +#define CFFOLDER_cCFData 4 +#define CFFOLDER_typeCompress 6 +#define CFFOLDER_abReserve 8 + +/* CFFILE offset */ +#define CFFILE_cbFile 0 +#define CFFILE_uoffFolderStart 4 +#define CFFILE_iFolder 8 +#define CFFILE_date_time 10 +#define CFFILE_attribs 14 + +/* CFDATA offset */ +#define CFDATA_csum 0 +#define CFDATA_cbData 4 +#define CFDATA_cbUncomp 6 + +static const char * const compression_name[] = { + "NONE", + "MSZIP", + "Quantum", + "LZX", +}; + +struct cfdata { + /* Sum value of this CFDATA. */ + uint32_t sum; + uint16_t compressed_size; + uint16_t compressed_bytes_remaining; + uint16_t uncompressed_size; + uint16_t uncompressed_bytes_remaining; + /* To know how many bytes we have decompressed. */ + uint16_t uncompressed_avail; + /* Offset from the beginning of compressed data of this CFDATA */ + uint16_t read_offset; + int64_t unconsumed; + /* To keep memory image of this CFDATA to compute the sum. */ + size_t memimage_size; + unsigned char *memimage; + /* Result of calculation of sum. */ + uint32_t sum_calculated; + unsigned char sum_extra[4]; + int sum_extra_avail; + const void *sum_ptr; +}; + +struct cffolder { + uint32_t cfdata_offset_in_cab; + uint16_t cfdata_count; + uint16_t comptype; +#define COMPTYPE_NONE 0x0000 +#define COMPTYPE_MSZIP 0x0001 +#define COMPTYPE_QUANTUM 0x0002 +#define COMPTYPE_LZX 0x0003 + uint16_t compdata; + const char *compname; + /* At the time reading CFDATA */ + struct cfdata cfdata; + int cfdata_index; + /* Flags to mark progress of decompression. */ + char decompress_init; +}; + +struct cffile { + uint32_t uncompressed_size; + uint32_t offset; + time_t mtime; + uint16_t folder; +#define iFoldCONTINUED_FROM_PREV 0xFFFD +#define iFoldCONTINUED_TO_NEXT 0xFFFE +#define iFoldCONTINUED_PREV_AND_NEXT 0xFFFF + unsigned char attr; +#define ATTR_RDONLY 0x01 +#define ATTR_NAME_IS_UTF 0x80 + struct archive_string pathname; +}; + +struct cfheader { + /* Total bytes of all file size in a Cabinet. */ + uint32_t total_bytes; + uint32_t files_offset; + uint16_t folder_count; + uint16_t file_count; + uint16_t flags; +#define PREV_CABINET 0x0001 +#define NEXT_CABINET 0x0002 +#define RESERVE_PRESENT 0x0004 + uint16_t setid; + uint16_t cabinet; + /* Version number. */ + unsigned char major; + unsigned char minor; + unsigned char cffolder; + unsigned char cfdata; + /* All folders in a cabinet. */ + struct cffolder *folder_array; + /* All files in a cabinet. */ + struct cffile *file_array; + int file_index; +}; + +struct cab { + /* entry_bytes_remaining is the number of bytes we expect. */ + int64_t entry_offset; + int64_t entry_bytes_remaining; + int64_t entry_unconsumed; + int64_t entry_compressed_bytes_read; + int64_t entry_uncompressed_bytes_read; + struct cffolder *entry_cffolder; + struct cffile *entry_cffile; + struct cfdata *entry_cfdata; + + /* Offset from beginning of a cabinet file. */ + int64_t cab_offset; + struct cfheader cfheader; + struct archive_wstring ws; + + /* Flag to mark progress that an archive was read their first header.*/ + char found_header; + char end_of_archive; + char end_of_entry; + char end_of_entry_cleanup; + char read_data_invoked; + int64_t bytes_skipped; + + unsigned char *uncompressed_buffer; + size_t uncompressed_buffer_size; + + int init_default_conversion; + struct archive_string_conv *sconv; + struct archive_string_conv *sconv_default; + struct archive_string_conv *sconv_utf8; + char format_name[64]; + +#ifdef HAVE_ZLIB_H + z_stream stream; + char stream_valid; +#endif + struct lzx_stream xstrm; +}; + +static int archive_read_format_cab_bid(struct archive_read *, int); +static int archive_read_format_cab_options(struct archive_read *, + const char *, const char *); +static int archive_read_format_cab_read_header(struct archive_read *, + struct archive_entry *); +static int archive_read_format_cab_read_data(struct archive_read *, + const void **, size_t *, int64_t *); +static int archive_read_format_cab_read_data_skip(struct archive_read *); +static int archive_read_format_cab_cleanup(struct archive_read *); + +static int cab_skip_sfx(struct archive_read *); +static time_t cab_dos_time(const unsigned char *); +static int cab_read_data(struct archive_read *, const void **, + size_t *, int64_t *); +static int cab_read_header(struct archive_read *); +static uint32_t cab_checksum_cfdata_4(const void *, size_t bytes, uint32_t); +static uint32_t cab_checksum_cfdata(const void *, size_t bytes, uint32_t); +static void cab_checksum_update(struct archive_read *, size_t); +static int cab_checksum_finish(struct archive_read *); +static int cab_next_cfdata(struct archive_read *); +static const void *cab_read_ahead_cfdata(struct archive_read *, ssize_t *); +static const void *cab_read_ahead_cfdata_none(struct archive_read *, ssize_t *); +static const void *cab_read_ahead_cfdata_deflate(struct archive_read *, + ssize_t *); +static const void *cab_read_ahead_cfdata_lzx(struct archive_read *, + ssize_t *); +static int64_t cab_consume_cfdata(struct archive_read *, int64_t); +static int64_t cab_minimum_consume_cfdata(struct archive_read *, int64_t); +static int lzx_decode_init(struct lzx_stream *, int); +static int lzx_read_blocks(struct lzx_stream *, int); +static int lzx_decode_blocks(struct lzx_stream *, int); +static void lzx_decode_free(struct lzx_stream *); +static void lzx_translation(struct lzx_stream *, void *, size_t, uint32_t); +static void lzx_cleanup_bitstream(struct lzx_stream *); +static int lzx_decode(struct lzx_stream *, int); +static int lzx_read_pre_tree(struct lzx_stream *); +static int lzx_read_bitlen(struct lzx_stream *, struct huffman *, int); +static int lzx_huffman_init(struct huffman *, size_t, int); +static void lzx_huffman_free(struct huffman *); +static int lzx_make_huffman_table(struct huffman *); +static inline int lzx_decode_huffman(struct huffman *, unsigned); + + +int +archive_read_support_format_cab(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct cab *cab; + int r; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_format_cab"); + + cab = (struct cab *)calloc(1, sizeof(*cab)); + if (cab == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate CAB data"); + return (ARCHIVE_FATAL); + } + archive_string_init(&cab->ws); + archive_wstring_ensure(&cab->ws, 256); + + r = __archive_read_register_format(a, + cab, + "cab", + archive_read_format_cab_bid, + archive_read_format_cab_options, + archive_read_format_cab_read_header, + archive_read_format_cab_read_data, + archive_read_format_cab_read_data_skip, + NULL, + archive_read_format_cab_cleanup, + NULL, + NULL); + + if (r != ARCHIVE_OK) + free(cab); + return (ARCHIVE_OK); +} + +static int +find_cab_magic(const char *p) +{ + switch (p[4]) { + case 0: + /* + * Note: Self-Extraction program has 'MSCF' string in their + * program. If we were finding 'MSCF' string only, we got + * wrong place for Cabinet header, thus, we have to check + * following four bytes which are reserved and must be set + * to zero. + */ + if (memcmp(p, "MSCF\0\0\0\0", 8) == 0) + return 0; + return 5; + case 'F': return 1; + case 'C': return 2; + case 'S': return 3; + case 'M': return 4; + default: return 5; + } +} + +static int +archive_read_format_cab_bid(struct archive_read *a, int best_bid) +{ + const char *p; + ssize_t bytes_avail, offset, window; + + /* If there's already a better bid than we can ever + make, don't bother testing. */ + if (best_bid > 64) + return (-1); + + if ((p = __archive_read_ahead(a, 8, NULL)) == NULL) + return (-1); + + if (memcmp(p, "MSCF\0\0\0\0", 8) == 0) + return (64); + + /* + * Attempt to handle self-extracting archives + * by noting a PE header and searching forward + * up to 128k for a 'MSCF' marker. + */ + if (p[0] == 'M' && p[1] == 'Z') { + offset = 0; + window = 4096; + while (offset < (1024 * 128)) { + const char *h = __archive_read_ahead(a, offset + window, + &bytes_avail); + if (h == NULL) { + /* Remaining bytes are less than window. */ + window >>= 1; + if (window < 128) + return (0); + continue; + } + p = h + offset; + while (p + 8 < h + bytes_avail) { + int next; + if ((next = find_cab_magic(p)) == 0) + return (64); + p += next; + } + offset = p - h; + } + } + return (0); +} + +static int +archive_read_format_cab_options(struct archive_read *a, + const char *key, const char *val) +{ + struct cab *cab; + int ret = ARCHIVE_FAILED; + + cab = (struct cab *)(a->format->data); + if (strcmp(key, "hdrcharset") == 0) { + if (val == NULL || val[0] == 0) + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "cab: hdrcharset option needs a character-set name"); + else { + cab->sconv = archive_string_conversion_from_charset( + &a->archive, val, 0); + if (cab->sconv != NULL) + ret = ARCHIVE_OK; + else + ret = ARCHIVE_FATAL; + } + return (ret); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +static int +cab_skip_sfx(struct archive_read *a) +{ + const char *p, *q; + size_t skip; + ssize_t bytes, window; + + window = 4096; + for (;;) { + const char *h = __archive_read_ahead(a, window, &bytes); + if (h == NULL) { + /* Remaining size are less than window. */ + window >>= 1; + if (window < 128) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Couldn't find out CAB header"); + return (ARCHIVE_FATAL); + } + continue; + } + p = h; + q = p + bytes; + + /* + * Scan ahead until we find something that looks + * like the cab header. + */ + while (p + 8 < q) { + int next; + if ((next = find_cab_magic(p)) == 0) { + skip = p - h; + __archive_read_consume(a, skip); + return (ARCHIVE_OK); + } + p += next; + } + skip = p - h; + __archive_read_consume(a, skip); + } +} + +static int +truncated_error(struct archive_read *a) +{ + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated CAB header"); + return (ARCHIVE_FATAL); +} + +static ssize_t +cab_strnlen(const unsigned char *p, size_t maxlen) +{ + size_t i; + + for (i = 0; i <= maxlen; i++) { + if (p[i] == 0) + break; + } + if (i > maxlen) + return (-1);/* invalid */ + return ((ssize_t)i); +} + +/* Read bytes as much as remaining. */ +static const void * +cab_read_ahead_remaining(struct archive_read *a, size_t min, ssize_t *avail) +{ + const void *p; + + while (min > 0) { + p = __archive_read_ahead(a, min, avail); + if (p != NULL) + return (p); + min--; + } + return (NULL); +} + +/* Convert a path separator '\' -> '/' */ +static int +cab_convert_path_separator_1(struct archive_string *fn, unsigned char attr) +{ + size_t i; + int mb; + + /* Easy check if we have '\' in multi-byte string. */ + mb = 0; + for (i = 0; i < archive_strlen(fn); i++) { + if (fn->s[i] == '\\') { + if (mb) { + /* This may be second byte of multi-byte + * character. */ + break; + } + fn->s[i] = '/'; + mb = 0; + } else if ((fn->s[i] & 0x80) && !(attr & ATTR_NAME_IS_UTF)) + mb = 1; + else + mb = 0; + } + if (i == archive_strlen(fn)) + return (0); + return (-1); +} + +/* + * Replace a character '\' with '/' in wide character. + */ +static void +cab_convert_path_separator_2(struct cab *cab, struct archive_entry *entry) +{ + const wchar_t *wp; + size_t i; + + /* If a conversion to wide character failed, force the replacement. */ + if ((wp = archive_entry_pathname_w(entry)) != NULL) { + archive_wstrcpy(&(cab->ws), wp); + for (i = 0; i < archive_strlen(&(cab->ws)); i++) { + if (cab->ws.s[i] == L'\\') + cab->ws.s[i] = L'/'; + } + archive_entry_copy_pathname_w(entry, cab->ws.s); + } +} + +/* + * Read CFHEADER, CFFOLDER and CFFILE. + */ +static int +cab_read_header(struct archive_read *a) +{ + const unsigned char *p; + struct cab *cab; + struct cfheader *hd; + size_t bytes, used; + ssize_t len; + int64_t skip; + int err, i; + int cur_folder, prev_folder; + uint32_t offset32; + + a->archive.archive_format = ARCHIVE_FORMAT_CAB; + if (a->archive.archive_format_name == NULL) + a->archive.archive_format_name = "CAB"; + + if ((p = __archive_read_ahead(a, 42, NULL)) == NULL) + return (truncated_error(a)); + + cab = (struct cab *)(a->format->data); + if (cab->found_header == 0 && + p[0] == 'M' && p[1] == 'Z') { + /* This is an executable? Must be self-extracting... */ + err = cab_skip_sfx(a); + if (err < ARCHIVE_WARN) + return (err); + + /* Re-read header after processing the SFX. */ + if ((p = __archive_read_ahead(a, 42, NULL)) == NULL) + return (truncated_error(a)); + } + + cab->cab_offset = 0; + /* + * Read CFHEADER. + */ + hd = &cab->cfheader; + if (p[CFHEADER_signature+0] != 'M' || p[CFHEADER_signature+1] != 'S' || + p[CFHEADER_signature+2] != 'C' || p[CFHEADER_signature+3] != 'F') { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Couldn't find out CAB header"); + return (ARCHIVE_FATAL); + } + hd->total_bytes = archive_le32dec(p + CFHEADER_cbCabinet); + hd->files_offset = archive_le32dec(p + CFHEADER_coffFiles); + hd->minor = p[CFHEADER_versionMinor]; + hd->major = p[CFHEADER_versionMajor]; + hd->folder_count = archive_le16dec(p + CFHEADER_cFolders); + if (hd->folder_count == 0) + goto invalid; + hd->file_count = archive_le16dec(p + CFHEADER_cFiles); + if (hd->file_count == 0) + goto invalid; + hd->flags = archive_le16dec(p + CFHEADER_flags); + hd->setid = archive_le16dec(p + CFHEADER_setID); + hd->cabinet = archive_le16dec(p + CFHEADER_iCabinet); + used = CFHEADER_iCabinet + 2; + if (hd->flags & RESERVE_PRESENT) { + uint16_t cfheader; + cfheader = archive_le16dec(p + CFHEADER_cbCFHeader); + if (cfheader > 60000U) + goto invalid; + hd->cffolder = p[CFHEADER_cbCFFolder]; + hd->cfdata = p[CFHEADER_cbCFData]; + used += 4;/* cbCFHeader, cbCFFolder and cbCFData */ + used += cfheader;/* abReserve */ + } else + hd->cffolder = 0;/* Avoid compiling warning. */ + if (hd->flags & PREV_CABINET) { + /* How many bytes are used for szCabinetPrev. */ + if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL) + return (truncated_error(a)); + if ((len = cab_strnlen(p + used, 255)) <= 0) + goto invalid; + used += len + 1; + /* How many bytes are used for szDiskPrev. */ + if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL) + return (truncated_error(a)); + if ((len = cab_strnlen(p + used, 255)) <= 0) + goto invalid; + used += len + 1; + } + if (hd->flags & NEXT_CABINET) { + /* How many bytes are used for szCabinetNext. */ + if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL) + return (truncated_error(a)); + if ((len = cab_strnlen(p + used, 255)) <= 0) + goto invalid; + used += len + 1; + /* How many bytes are used for szDiskNext. */ + if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL) + return (truncated_error(a)); + if ((len = cab_strnlen(p + used, 255)) <= 0) + goto invalid; + used += len + 1; + } + __archive_read_consume(a, used); + cab->cab_offset += used; + used = 0; + + /* + * Read CFFOLDER. + */ + hd->folder_array = (struct cffolder *)calloc( + hd->folder_count, sizeof(struct cffolder)); + if (hd->folder_array == NULL) + goto nomem; + + bytes = 8; + if (hd->flags & RESERVE_PRESENT) + bytes += hd->cffolder; + bytes *= hd->folder_count; + if ((p = __archive_read_ahead(a, bytes, NULL)) == NULL) + return (truncated_error(a)); + offset32 = 0; + for (i = 0; i < hd->folder_count; i++) { + struct cffolder *folder = &(hd->folder_array[i]); + folder->cfdata_offset_in_cab = + archive_le32dec(p + CFFOLDER_coffCabStart); + folder->cfdata_count = archive_le16dec(p+CFFOLDER_cCFData); + folder->comptype = + archive_le16dec(p+CFFOLDER_typeCompress) & 0x0F; + folder->compdata = + archive_le16dec(p+CFFOLDER_typeCompress) >> 8; + /* Get a compression name. */ + if (folder->comptype < + sizeof(compression_name) / sizeof(compression_name[0])) + folder->compname = compression_name[folder->comptype]; + else + folder->compname = "UNKNOWN"; + p += 8; + used += 8; + if (hd->flags & RESERVE_PRESENT) { + p += hd->cffolder;/* abReserve */ + used += hd->cffolder; + } + /* + * Sanity check if each data is acceptable. + */ + if (offset32 >= folder->cfdata_offset_in_cab) + goto invalid; + offset32 = folder->cfdata_offset_in_cab; + + /* Set a request to initialize zlib for the CFDATA of + * this folder. */ + folder->decompress_init = 0; + } + __archive_read_consume(a, used); + cab->cab_offset += used; + + /* + * Read CFFILE. + */ + /* Seek read pointer to the offset of CFFILE if needed. */ + skip = (int64_t)hd->files_offset - cab->cab_offset; + if (skip < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid offset of CFFILE %jd < %jd", + (intmax_t)hd->files_offset, (intmax_t)cab->cab_offset); + return (ARCHIVE_FATAL); + } + if (skip) { + __archive_read_consume(a, skip); + cab->cab_offset += skip; + } + /* Allocate memory for CFDATA */ + hd->file_array = (struct cffile *)calloc( + hd->file_count, sizeof(struct cffile)); + if (hd->file_array == NULL) + goto nomem; + + prev_folder = -1; + for (i = 0; i < hd->file_count; i++) { + struct cffile *file = &(hd->file_array[i]); + ssize_t avail; + + if ((p = __archive_read_ahead(a, 16, NULL)) == NULL) + return (truncated_error(a)); + file->uncompressed_size = archive_le32dec(p + CFFILE_cbFile); + file->offset = archive_le32dec(p + CFFILE_uoffFolderStart); + file->folder = archive_le16dec(p + CFFILE_iFolder); + file->mtime = cab_dos_time(p + CFFILE_date_time); + file->attr = (uint8_t)archive_le16dec(p + CFFILE_attribs); + __archive_read_consume(a, 16); + + cab->cab_offset += 16; + if ((p = cab_read_ahead_remaining(a, 256, &avail)) == NULL) + return (truncated_error(a)); + if ((len = cab_strnlen(p, avail-1)) <= 0) + goto invalid; + + /* Copy a pathname. */ + archive_string_init(&(file->pathname)); + archive_strncpy(&(file->pathname), p, len); + __archive_read_consume(a, len + 1); + cab->cab_offset += len + 1; + + /* + * Sanity check if each data is acceptable. + */ + if (file->uncompressed_size > 0x7FFF8000) + goto invalid;/* Too large */ + if ((int64_t)file->offset + (int64_t)file->uncompressed_size + > ARCHIVE_LITERAL_LL(0x7FFF8000)) + goto invalid;/* Too large */ + switch (file->folder) { + case iFoldCONTINUED_TO_NEXT: + /* This must be last file in a folder. */ + if (i != hd->file_count -1) + goto invalid; + cur_folder = hd->folder_count -1; + break; + case iFoldCONTINUED_PREV_AND_NEXT: + /* This must be only one file in a folder. */ + if (hd->file_count != 1) + goto invalid; + /* FALL THROUGH */ + case iFoldCONTINUED_FROM_PREV: + /* This must be first file in a folder. */ + if (i != 0) + goto invalid; + prev_folder = cur_folder = 0; + offset32 = file->offset; + break; + default: + if (file->folder >= hd->folder_count) + goto invalid; + cur_folder = file->folder; + break; + } + /* Dot not back track. */ + if (cur_folder < prev_folder) + goto invalid; + if (cur_folder != prev_folder) + offset32 = 0; + prev_folder = cur_folder; + + /* Make sure there are not any blanks from last file + * contents. */ + if (offset32 != file->offset) + goto invalid; + offset32 += file->uncompressed_size; + + /* CFDATA is available for file contents. */ + if (file->uncompressed_size > 0 && + hd->folder_array[cur_folder].cfdata_count == 0) + goto invalid; + } + + if (hd->cabinet != 0 || hd->flags & (PREV_CABINET | NEXT_CABINET)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Multivolume cabinet file is unsupported"); + return (ARCHIVE_WARN); + } + return (ARCHIVE_OK); +invalid: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid CAB header"); + return (ARCHIVE_FATAL); +nomem: + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for CAB data"); + return (ARCHIVE_FATAL); +} + +static int +archive_read_format_cab_read_header(struct archive_read *a, + struct archive_entry *entry) +{ + struct cab *cab; + struct cfheader *hd; + struct cffolder *prev_folder; + struct cffile *file; + struct archive_string_conv *sconv; + int err = ARCHIVE_OK, r; + + cab = (struct cab *)(a->format->data); + if (cab->found_header == 0) { + err = cab_read_header(a); + if (err < ARCHIVE_WARN) + return (err); + /* We've found the header. */ + cab->found_header = 1; + } + hd = &cab->cfheader; + + if (hd->file_index >= hd->file_count) { + cab->end_of_archive = 1; + return (ARCHIVE_EOF); + } + file = &hd->file_array[hd->file_index++]; + + cab->end_of_entry = 0; + cab->end_of_entry_cleanup = 0; + cab->entry_compressed_bytes_read = 0; + cab->entry_uncompressed_bytes_read = 0; + cab->entry_unconsumed = 0; + cab->entry_cffile = file; + + /* + * Choose a proper folder. + */ + prev_folder = cab->entry_cffolder; + switch (file->folder) { + case iFoldCONTINUED_FROM_PREV: + case iFoldCONTINUED_PREV_AND_NEXT: + cab->entry_cffolder = &hd->folder_array[0]; + break; + case iFoldCONTINUED_TO_NEXT: + cab->entry_cffolder = &hd->folder_array[hd->folder_count-1]; + break; + default: + cab->entry_cffolder = &hd->folder_array[file->folder]; + break; + } + /* If a cffolder of this file is changed, reset a cfdata to read + * file contents from next cfdata. */ + if (prev_folder != cab->entry_cffolder) + cab->entry_cfdata = NULL; + + /* If a pathname is UTF-8, prepare a string conversion object + * for UTF-8 and use it. */ + if (file->attr & ATTR_NAME_IS_UTF) { + if (cab->sconv_utf8 == NULL) { + cab->sconv_utf8 = + archive_string_conversion_from_charset( + &(a->archive), "UTF-8", 1); + if (cab->sconv_utf8 == NULL) + return (ARCHIVE_FATAL); + } + sconv = cab->sconv_utf8; + } else if (cab->sconv != NULL) { + /* Choose the conversion specified by the option. */ + sconv = cab->sconv; + } else { + /* Choose the default conversion. */ + if (!cab->init_default_conversion) { + cab->sconv_default = + archive_string_default_conversion_for_read( + &(a->archive)); + cab->init_default_conversion = 1; + } + sconv = cab->sconv_default; + } + + /* + * Set a default value and common data + */ + r = cab_convert_path_separator_1(&(file->pathname), file->attr); + if (archive_entry_copy_pathname_l(entry, file->pathname.s, + archive_strlen(&(file->pathname)), sconv) != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Pathname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Pathname cannot be converted " + "from %s to current locale.", + archive_string_conversion_charset_name(sconv)); + err = ARCHIVE_WARN; + } + if (r < 0) { + /* Convert a path separator '\' -> '/' */ + cab_convert_path_separator_2(cab, entry); + } + + archive_entry_set_size(entry, file->uncompressed_size); + if (file->attr & ATTR_RDONLY) + archive_entry_set_mode(entry, AE_IFREG | 0555); + else + archive_entry_set_mode(entry, AE_IFREG | 0666); + archive_entry_set_mtime(entry, file->mtime, 0); + + cab->entry_bytes_remaining = file->uncompressed_size; + cab->entry_offset = 0; + /* We don't need compress data. */ + if (file->uncompressed_size == 0) + cab->end_of_entry_cleanup = cab->end_of_entry = 1; + + /* Set up a more descriptive format name. */ + sprintf(cab->format_name, "CAB %d.%d (%s)", + hd->major, hd->minor, cab->entry_cffolder->compname); + a->archive.archive_format_name = cab->format_name; + + return (err); +} + +static int +archive_read_format_cab_read_data(struct archive_read *a, + const void **buff, size_t *size, int64_t *offset) +{ + struct cab *cab = (struct cab *)(a->format->data); + int r; + + switch (cab->entry_cffile->folder) { + case iFoldCONTINUED_FROM_PREV: + case iFoldCONTINUED_TO_NEXT: + case iFoldCONTINUED_PREV_AND_NEXT: + *buff = NULL; + *size = 0; + *offset = 0; + archive_clear_error(&a->archive); + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Cannot restore this file split in multivolume."); + return (ARCHIVE_FAILED); + default: + break; + } + if (cab->read_data_invoked == 0) { + if (cab->bytes_skipped) { + if (cab->entry_cfdata == NULL) { + r = cab_next_cfdata(a); + if (r < 0) + return (r); + } + if (cab_consume_cfdata(a, cab->bytes_skipped) < 0) + return (ARCHIVE_FATAL); + cab->bytes_skipped = 0; + } + cab->read_data_invoked = 1; + } + if (cab->entry_unconsumed) { + /* Consume as much as the compressor actually used. */ + r = (int)cab_consume_cfdata(a, cab->entry_unconsumed); + cab->entry_unconsumed = 0; + if (r < 0) + return (r); + } + if (cab->end_of_archive || cab->end_of_entry) { + if (!cab->end_of_entry_cleanup) { + /* End-of-entry cleanup done. */ + cab->end_of_entry_cleanup = 1; + } + *offset = cab->entry_offset; + *size = 0; + *buff = NULL; + return (ARCHIVE_EOF); + } + + return (cab_read_data(a, buff, size, offset)); +} + +static uint32_t +cab_checksum_cfdata_4(const void *p, size_t bytes, uint32_t seed) +{ + const unsigned char *b; + unsigned u32num; + uint32_t sum; + + u32num = (unsigned)bytes / 4; + sum = seed; + b = p; + for (;u32num > 0; --u32num) { + sum ^= archive_le32dec(b); + b += 4; + } + return (sum); +} + +static uint32_t +cab_checksum_cfdata(const void *p, size_t bytes, uint32_t seed) +{ + const unsigned char *b; + uint32_t sum; + uint32_t t; + + sum = cab_checksum_cfdata_4(p, bytes, seed); + b = p; + b += bytes & ~3; + t = 0; + switch (bytes & 3) { + case 3: + t |= ((uint32_t)(*b++)) << 16; + /* FALL THROUGH */ + case 2: + t |= ((uint32_t)(*b++)) << 8; + /* FALL THROUGH */ + case 1: + t |= *b; + /* FALL THROUGH */ + default: + break; + } + sum ^= t; + + return (sum); +} + +static void +cab_checksum_update(struct archive_read *a, size_t bytes) +{ + struct cab *cab = (struct cab *)(a->format->data); + struct cfdata *cfdata = cab->entry_cfdata; + const unsigned char *p; + size_t sumbytes; + + if (cfdata->sum == 0 || cfdata->sum_ptr == NULL) + return; + /* + * Calculate the sum of this CFDATA. + * Make sure CFDATA must be calculated in four bytes. + */ + p = cfdata->sum_ptr; + sumbytes = bytes; + if (cfdata->sum_extra_avail) { + while (cfdata->sum_extra_avail < 4 && sumbytes > 0) { + cfdata->sum_extra[ + cfdata->sum_extra_avail++] = *p++; + sumbytes--; + } + if (cfdata->sum_extra_avail == 4) { + cfdata->sum_calculated = cab_checksum_cfdata_4( + cfdata->sum_extra, 4, cfdata->sum_calculated); + cfdata->sum_extra_avail = 0; + } + } + if (sumbytes) { + int odd = sumbytes & 3; + if (sumbytes - odd > 0) + cfdata->sum_calculated = cab_checksum_cfdata_4( + p, sumbytes - odd, cfdata->sum_calculated); + if (odd) + memcpy(cfdata->sum_extra, p + sumbytes - odd, odd); + cfdata->sum_extra_avail = odd; + } + cfdata->sum_ptr = NULL; +} + +static int +cab_checksum_finish(struct archive_read *a) +{ + struct cab *cab = (struct cab *)(a->format->data); + struct cfdata *cfdata = cab->entry_cfdata; + int l; + + /* Do not need to compute a sum. */ + if (cfdata->sum == 0) + return (ARCHIVE_OK); + + /* + * Calculate the sum of remaining CFDATA. + */ + if (cfdata->sum_extra_avail) { + cfdata->sum_calculated = + cab_checksum_cfdata(cfdata->sum_extra, + cfdata->sum_extra_avail, cfdata->sum_calculated); + cfdata->sum_extra_avail = 0; + } + + l = 4; + if (cab->cfheader.flags & RESERVE_PRESENT) + l += cab->cfheader.cfdata; + cfdata->sum_calculated = cab_checksum_cfdata( + cfdata->memimage + CFDATA_cbData, l, cfdata->sum_calculated); + if (cfdata->sum_calculated != cfdata->sum) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Checksum error CFDATA[%d] %x:%x in %d bytes", + cab->entry_cffolder->cfdata_index -1, + cfdata->sum, cfdata->sum_calculated, + cfdata->compressed_size); + return (ARCHIVE_FAILED); + } + return (ARCHIVE_OK); +} + +/* + * Read CFDATA if needed. + */ +static int +cab_next_cfdata(struct archive_read *a) +{ + struct cab *cab = (struct cab *)(a->format->data); + struct cfdata *cfdata = cab->entry_cfdata; + + /* There are remaining bytes in current CFDATA, use it first. */ + if (cfdata != NULL && cfdata->uncompressed_bytes_remaining > 0) + return (ARCHIVE_OK); + + if (cfdata == NULL) { + int64_t skip; + + cab->entry_cffolder->cfdata_index = 0; + + /* Seek read pointer to the offset of CFDATA if needed. */ + skip = cab->entry_cffolder->cfdata_offset_in_cab + - cab->cab_offset; + if (skip < 0) { + int folder_index; + switch (cab->entry_cffile->folder) { + case iFoldCONTINUED_FROM_PREV: + case iFoldCONTINUED_PREV_AND_NEXT: + folder_index = 0; + break; + case iFoldCONTINUED_TO_NEXT: + folder_index = cab->cfheader.folder_count-1; + break; + default: + folder_index = cab->entry_cffile->folder; + break; + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid offset of CFDATA in folder(%d) %jd < %jd", + folder_index, + (intmax_t)cab->entry_cffolder->cfdata_offset_in_cab, + (intmax_t)cab->cab_offset); + return (ARCHIVE_FATAL); + } + if (skip > 0) { + if (__archive_read_consume(a, skip) < 0) + return (ARCHIVE_FATAL); + cab->cab_offset = + cab->entry_cffolder->cfdata_offset_in_cab; + } + } + + /* + * Read a CFDATA. + */ + if (cab->entry_cffolder->cfdata_index < + cab->entry_cffolder->cfdata_count) { + const unsigned char *p; + int l; + + cfdata = &(cab->entry_cffolder->cfdata); + cab->entry_cffolder->cfdata_index++; + cab->entry_cfdata = cfdata; + cfdata->sum_calculated = 0; + cfdata->sum_extra_avail = 0; + cfdata->sum_ptr = NULL; + l = 8; + if (cab->cfheader.flags & RESERVE_PRESENT) + l += cab->cfheader.cfdata; + if ((p = __archive_read_ahead(a, l, NULL)) == NULL) + return (truncated_error(a)); + cfdata->sum = archive_le32dec(p + CFDATA_csum); + cfdata->compressed_size = archive_le16dec(p + CFDATA_cbData); + cfdata->compressed_bytes_remaining = cfdata->compressed_size; + cfdata->uncompressed_size = + archive_le16dec(p + CFDATA_cbUncomp); + cfdata->uncompressed_bytes_remaining = + cfdata->uncompressed_size; + cfdata->uncompressed_avail = 0; + cfdata->read_offset = 0; + cfdata->unconsumed = 0; + + /* + * Sanity check if data size is acceptable. + */ + if (cfdata->compressed_size == 0 || + cfdata->compressed_size > (0x8000+6144)) + goto invalid; + if (cfdata->uncompressed_size > 0x8000) + goto invalid; + if (cfdata->uncompressed_size == 0) { + switch (cab->entry_cffile->folder) { + case iFoldCONTINUED_PREV_AND_NEXT: + case iFoldCONTINUED_TO_NEXT: + break; + case iFoldCONTINUED_FROM_PREV: + default: + goto invalid; + } + } + /* If CFDATA is not last in a folder, an uncompressed + * size must be 0x8000(32KBi) */ + if ((cab->entry_cffolder->cfdata_index < + cab->entry_cffolder->cfdata_count) && + cfdata->uncompressed_size != 0x8000) + goto invalid; + + /* A compressed data size and an uncompressed data size must + * be the same in no compression mode. */ + if (cab->entry_cffolder->comptype == COMPTYPE_NONE && + cfdata->compressed_size != cfdata->uncompressed_size) + goto invalid; + + /* + * Save CFDATA image for sum check. + */ + if (cfdata->memimage_size < (size_t)l) { + free(cfdata->memimage); + cfdata->memimage = malloc(l); + if (cfdata->memimage == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for CAB data"); + return (ARCHIVE_FATAL); + } + cfdata->memimage_size = l; + } + memcpy(cfdata->memimage, p, l); + + /* Consume bytes as much as we used. */ + __archive_read_consume(a, l); + cab->cab_offset += l; + } else if (cab->entry_cffolder->cfdata_count > 0) { + /* Run out of all CFDATA in a folder. */ + cfdata->compressed_size = 0; + cfdata->uncompressed_size = 0; + cfdata->compressed_bytes_remaining = 0; + cfdata->uncompressed_bytes_remaining = 0; + } else { + /* Current folder does not have any CFDATA. */ + cfdata = &(cab->entry_cffolder->cfdata); + cab->entry_cfdata = cfdata; + memset(cfdata, 0, sizeof(*cfdata)); + } + return (ARCHIVE_OK); +invalid: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid CFDATA"); + return (ARCHIVE_FATAL); +} + +/* + * Read ahead CFDATA. + */ +static const void * +cab_read_ahead_cfdata(struct archive_read *a, ssize_t *avail) +{ + struct cab *cab = (struct cab *)(a->format->data); + int err; + + err = cab_next_cfdata(a); + if (err < ARCHIVE_OK) { + *avail = err; + return (NULL); + } + + switch (cab->entry_cffolder->comptype) { + case COMPTYPE_NONE: + return (cab_read_ahead_cfdata_none(a, avail)); + case COMPTYPE_MSZIP: + return (cab_read_ahead_cfdata_deflate(a, avail)); + case COMPTYPE_LZX: + return (cab_read_ahead_cfdata_lzx(a, avail)); + default: /* Unsupported compression. */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Unsupported CAB compression : %s", + cab->entry_cffolder->compname); + *avail = ARCHIVE_FAILED; + return (NULL); + } +} + +/* + * Read ahead CFDATA as uncompressed data. + */ +static const void * +cab_read_ahead_cfdata_none(struct archive_read *a, ssize_t *avail) +{ + struct cab *cab = (struct cab *)(a->format->data); + struct cfdata *cfdata; + const void *d; + + cfdata = cab->entry_cfdata; + + /* + * Note: '1' here is a performance optimization. + * Recall that the decompression layer returns a count of + * available bytes; asking for more than that forces the + * decompressor to combine reads by copying data. + */ + d = __archive_read_ahead(a, 1, avail); + if (*avail <= 0) { + *avail = truncated_error(a); + return (NULL); + } + if (*avail > cfdata->uncompressed_bytes_remaining) + *avail = cfdata->uncompressed_bytes_remaining; + cfdata->uncompressed_avail = cfdata->uncompressed_size; + cfdata->unconsumed = *avail; + cfdata->sum_ptr = d; + return (d); +} + +/* + * Read ahead CFDATA as deflate data. + */ +#ifdef HAVE_ZLIB_H +static const void * +cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail) +{ + struct cab *cab = (struct cab *)(a->format->data); + struct cfdata *cfdata; + const void *d; + int r, mszip; + uint16_t uavail; + char eod = 0; + + cfdata = cab->entry_cfdata; + /* If the buffer hasn't been allocated, allocate it now. */ + if (cab->uncompressed_buffer == NULL) { + cab->uncompressed_buffer_size = 0x8000; + cab->uncompressed_buffer + = (unsigned char *)malloc(cab->uncompressed_buffer_size); + if (cab->uncompressed_buffer == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for CAB reader"); + *avail = ARCHIVE_FATAL; + return (NULL); + } + } + + uavail = cfdata->uncompressed_avail; + if (uavail == cfdata->uncompressed_size) { + d = cab->uncompressed_buffer + cfdata->read_offset; + *avail = uavail - cfdata->read_offset; + return (d); + } + + if (!cab->entry_cffolder->decompress_init) { + cab->stream.next_in = NULL; + cab->stream.avail_in = 0; + cab->stream.total_in = 0; + cab->stream.next_out = NULL; + cab->stream.avail_out = 0; + cab->stream.total_out = 0; + if (cab->stream_valid) + r = inflateReset(&cab->stream); + else + r = inflateInit2(&cab->stream, + -15 /* Don't check for zlib header */); + if (r != Z_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't initialize deflate decompression."); + *avail = ARCHIVE_FATAL; + return (NULL); + } + /* Stream structure has been set up. */ + cab->stream_valid = 1; + /* We've initialized decompression for this stream. */ + cab->entry_cffolder->decompress_init = 1; + } + + if (cfdata->compressed_bytes_remaining == cfdata->compressed_size) + mszip = 2; + else + mszip = 0; + eod = 0; + cab->stream.total_out = uavail; + /* + * We always uncompress all data in current CFDATA. + */ + while (!eod && cab->stream.total_out < cfdata->uncompressed_size) { + ssize_t bytes_avail; + + cab->stream.next_out = + cab->uncompressed_buffer + cab->stream.total_out; + cab->stream.avail_out = + cfdata->uncompressed_size - cab->stream.total_out; + + d = __archive_read_ahead(a, 1, &bytes_avail); + if (bytes_avail <= 0) { + *avail = truncated_error(a); + return (NULL); + } + if (bytes_avail > cfdata->compressed_bytes_remaining) + bytes_avail = cfdata->compressed_bytes_remaining; + /* + * A bug in zlib.h: stream.next_in should be marked 'const' + * but isn't (the library never alters data through the + * next_in pointer, only reads it). The result: this ugly + * cast to remove 'const'. + */ + cab->stream.next_in = (Bytef *)(uintptr_t)d; + cab->stream.avail_in = (uInt)bytes_avail; + cab->stream.total_in = 0; + + /* Cut out a tow-byte MSZIP signature(0x43, 0x4b). */ + if (mszip > 0) { + if (bytes_avail <= 0) + goto nomszip; + if (bytes_avail <= mszip) { + if (mszip == 2) { + if (cab->stream.next_in[0] != 0x43) + goto nomszip; + if (bytes_avail > 1 && + cab->stream.next_in[1] != 0x4b) + goto nomszip; + } else if (cab->stream.next_in[0] != 0x4b) + goto nomszip; + cfdata->unconsumed = bytes_avail; + cfdata->sum_ptr = d; + if (cab_minimum_consume_cfdata( + a, cfdata->unconsumed) < 0) { + *avail = ARCHIVE_FATAL; + return (NULL); + } + mszip -= (int)bytes_avail; + continue; + } + if (mszip == 1 && cab->stream.next_in[0] != 0x4b) + goto nomszip; + else if (mszip == 2 && (cab->stream.next_in[0] != 0x43 || + cab->stream.next_in[1] != 0x4b)) + goto nomszip; + cab->stream.next_in += mszip; + cab->stream.avail_in -= mszip; + cab->stream.total_in += mszip; + mszip = 0; + } + + r = inflate(&cab->stream, 0); + switch (r) { + case Z_OK: + break; + case Z_STREAM_END: + eod = 1; + break; + default: + goto zlibfailed; + } + cfdata->unconsumed = cab->stream.total_in; + cfdata->sum_ptr = d; + if (cab_minimum_consume_cfdata(a, cfdata->unconsumed) < 0) { + *avail = ARCHIVE_FATAL; + return (NULL); + } + } + uavail = (uint16_t)cab->stream.total_out; + + if (uavail < cfdata->uncompressed_size) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid uncompressed size (%d < %d)", + uavail, cfdata->uncompressed_size); + *avail = ARCHIVE_FATAL; + return (NULL); + } + + /* + * Note: I suspect there is a bug in makecab.exe because, in rare + * case, compressed bytes are still remaining regardless we have + * gotten all uncompressed bytes, which size is recorded in CFDATA, + * as much as we need, and we have to use the garbage so as to + * correctly compute the sum of CFDATA accordingly. + */ + if (cfdata->compressed_bytes_remaining > 0) { + ssize_t bytes_avail; + + d = __archive_read_ahead(a, cfdata->compressed_bytes_remaining, + &bytes_avail); + if (bytes_avail <= 0) { + *avail = truncated_error(a); + return (NULL); + } + cfdata->unconsumed = cfdata->compressed_bytes_remaining; + cfdata->sum_ptr = d; + if (cab_minimum_consume_cfdata(a, cfdata->unconsumed) < 0) { + *avail = ARCHIVE_FATAL; + return (NULL); + } + } + + /* + * Set dictionary data for decompressing of next CFDATA, which + * in the same folder. This is why we always do decompress CFDATA + * even if beginning CFDATA or some of CFDATA are not used in + * skipping file data. + */ + if (cab->entry_cffolder->cfdata_index < + cab->entry_cffolder->cfdata_count) { + r = inflateReset(&cab->stream); + if (r != Z_OK) + goto zlibfailed; + r = inflateSetDictionary(&cab->stream, + cab->uncompressed_buffer, cfdata->uncompressed_size); + if (r != Z_OK) + goto zlibfailed; + } + + d = cab->uncompressed_buffer + cfdata->read_offset; + *avail = uavail - cfdata->read_offset; + cfdata->uncompressed_avail = uavail; + + return (d); + +zlibfailed: + switch (r) { + case Z_MEM_ERROR: + archive_set_error(&a->archive, ENOMEM, + "Out of memory for deflate decompression"); + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Deflate decompression failed (%d)", r); + break; + } + *avail = ARCHIVE_FATAL; + return (NULL); +nomszip: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "CFDATA incorrect(no MSZIP signature)"); + *avail = ARCHIVE_FATAL; + return (NULL); +} + +#else /* HAVE_ZLIB_H */ + +static const void * +cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail) +{ + *avail = ARCHIVE_FATAL; + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "libarchive compiled without deflate support (no libz)"); + return (NULL); +} + +#endif /* HAVE_ZLIB_H */ + +static const void * +cab_read_ahead_cfdata_lzx(struct archive_read *a, ssize_t *avail) +{ + struct cab *cab = (struct cab *)(a->format->data); + struct cfdata *cfdata; + const void *d; + int r; + uint16_t uavail; + + cfdata = cab->entry_cfdata; + /* If the buffer hasn't been allocated, allocate it now. */ + if (cab->uncompressed_buffer == NULL) { + cab->uncompressed_buffer_size = 0x8000; + cab->uncompressed_buffer + = (unsigned char *)malloc(cab->uncompressed_buffer_size); + if (cab->uncompressed_buffer == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for CAB reader"); + *avail = ARCHIVE_FATAL; + return (NULL); + } + } + + uavail = cfdata->uncompressed_avail; + if (uavail == cfdata->uncompressed_size) { + d = cab->uncompressed_buffer + cfdata->read_offset; + *avail = uavail - cfdata->read_offset; + return (d); + } + + if (!cab->entry_cffolder->decompress_init) { + r = lzx_decode_init(&cab->xstrm, + cab->entry_cffolder->compdata); + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't initialize LZX decompression."); + *avail = ARCHIVE_FATAL; + return (NULL); + } + /* We've initialized decompression for this stream. */ + cab->entry_cffolder->decompress_init = 1; + } + + /* Clean up remaining bits of previous CFDATA. */ + lzx_cleanup_bitstream(&cab->xstrm); + cab->xstrm.total_out = uavail; + while (cab->xstrm.total_out < cfdata->uncompressed_size) { + ssize_t bytes_avail; + + cab->xstrm.next_out = + cab->uncompressed_buffer + cab->xstrm.total_out; + cab->xstrm.avail_out = + cfdata->uncompressed_size - cab->xstrm.total_out; + + d = __archive_read_ahead(a, 1, &bytes_avail); + if (bytes_avail <= 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated CAB file data"); + *avail = ARCHIVE_FATAL; + return (NULL); + } + if (bytes_avail > cfdata->compressed_bytes_remaining) + bytes_avail = cfdata->compressed_bytes_remaining; + + cab->xstrm.next_in = d; + cab->xstrm.avail_in = bytes_avail; + cab->xstrm.total_in = 0; + r = lzx_decode(&cab->xstrm, + cfdata->compressed_bytes_remaining == bytes_avail); + switch (r) { + case ARCHIVE_OK: + case ARCHIVE_EOF: + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "LZX decompression failed (%d)", r); + *avail = ARCHIVE_FATAL; + return (NULL); + } + cfdata->unconsumed = cab->xstrm.total_in; + cfdata->sum_ptr = d; + if (cab_minimum_consume_cfdata(a, cfdata->unconsumed) < 0) { + *avail = ARCHIVE_FATAL; + return (NULL); + } + } + + uavail = (uint16_t)cab->xstrm.total_out; + /* + * Make sure a read pointer advances to next CFDATA. + */ + if (cfdata->compressed_bytes_remaining > 0) { + ssize_t bytes_avail; + + d = __archive_read_ahead(a, cfdata->compressed_bytes_remaining, + &bytes_avail); + if (bytes_avail <= 0) { + *avail = truncated_error(a); + return (NULL); + } + cfdata->unconsumed = cfdata->compressed_bytes_remaining; + cfdata->sum_ptr = d; + if (cab_minimum_consume_cfdata(a, cfdata->unconsumed) < 0) { + *avail = ARCHIVE_FATAL; + return (NULL); + } + } + + /* + * Translation reversal of x86 processor CALL byte sequence(E8). + */ + lzx_translation(&cab->xstrm, cab->uncompressed_buffer, + cfdata->uncompressed_size, + (cab->entry_cffolder->cfdata_index-1) * 0x8000); + + d = cab->uncompressed_buffer + cfdata->read_offset; + *avail = uavail - cfdata->read_offset; + cfdata->uncompressed_avail = uavail; + + return (d); +} + +/* + * Consume CFDATA. + * We always decompress CFDATA to consume CFDATA as much as we need + * in uncompressed bytes because all CFDATA in a folder are related + * so we do not skip any CFDATA without decompressing. + * Note: If the folder of a CFFILE is iFoldCONTINUED_PREV_AND_NEXT or + * iFoldCONTINUED_FROM_PREV, we won't decompress because a CFDATA for + * the CFFILE is remaining bytes of previous Multivolume CAB file. + */ +static int64_t +cab_consume_cfdata(struct archive_read *a, int64_t consumed_bytes) +{ + struct cab *cab = (struct cab *)(a->format->data); + struct cfdata *cfdata; + int64_t cbytes, rbytes; + int err; + + rbytes = cab_minimum_consume_cfdata(a, consumed_bytes); + if (rbytes < 0) + return (ARCHIVE_FATAL); + + cfdata = cab->entry_cfdata; + while (rbytes > 0) { + ssize_t avail; + + if (cfdata->compressed_size == 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid CFDATA"); + return (ARCHIVE_FATAL); + } + cbytes = cfdata->uncompressed_bytes_remaining; + if (cbytes > rbytes) + cbytes = rbytes; + rbytes -= cbytes; + + if (cfdata->uncompressed_avail == 0 && + (cab->entry_cffile->folder == iFoldCONTINUED_PREV_AND_NEXT || + cab->entry_cffile->folder == iFoldCONTINUED_FROM_PREV)) { + /* We have not read any data yet. */ + if (cbytes == cfdata->uncompressed_bytes_remaining) { + /* Skip whole current CFDATA. */ + __archive_read_consume(a, + cfdata->compressed_size); + cab->cab_offset += cfdata->compressed_size; + cfdata->compressed_bytes_remaining = 0; + cfdata->uncompressed_bytes_remaining = 0; + err = cab_next_cfdata(a); + if (err < 0) + return (err); + cfdata = cab->entry_cfdata; + if (cfdata->uncompressed_size == 0) { + switch (cab->entry_cffile->folder) { + case iFoldCONTINUED_PREV_AND_NEXT: + case iFoldCONTINUED_TO_NEXT: + case iFoldCONTINUED_FROM_PREV: + rbytes = 0; + break; + default: + break; + } + } + continue; + } + cfdata->read_offset += (uint16_t)cbytes; + cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes; + break; + } else if (cbytes == 0) { + err = cab_next_cfdata(a); + if (err < 0) + return (err); + cfdata = cab->entry_cfdata; + if (cfdata->uncompressed_size == 0) { + switch (cab->entry_cffile->folder) { + case iFoldCONTINUED_PREV_AND_NEXT: + case iFoldCONTINUED_TO_NEXT: + case iFoldCONTINUED_FROM_PREV: + return (ARCHIVE_FATAL); + default: + break; + } + } + continue; + } + while (cbytes > 0) { + (void)cab_read_ahead_cfdata(a, &avail); + if (avail <= 0) + return (ARCHIVE_FATAL); + if (avail > cbytes) + avail = (ssize_t)cbytes; + if (cab_minimum_consume_cfdata(a, avail) < 0) + return (ARCHIVE_FATAL); + cbytes -= avail; + } + } + return (consumed_bytes); +} + +/* + * Consume CFDATA as much as we have already gotten and + * compute the sum of CFDATA. + */ +static int64_t +cab_minimum_consume_cfdata(struct archive_read *a, int64_t consumed_bytes) +{ + struct cab *cab = (struct cab *)(a->format->data); + struct cfdata *cfdata; + int64_t cbytes, rbytes; + int err; + + cfdata = cab->entry_cfdata; + rbytes = consumed_bytes; + if (cab->entry_cffolder->comptype == COMPTYPE_NONE) { + if (consumed_bytes < cfdata->unconsumed) + cbytes = consumed_bytes; + else + cbytes = cfdata->unconsumed; + rbytes -= cbytes; + cfdata->read_offset += (uint16_t)cbytes; + cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes; + cfdata->unconsumed -= cbytes; + } else { + cbytes = cfdata->uncompressed_avail - cfdata->read_offset; + if (cbytes > 0) { + if (consumed_bytes < cbytes) + cbytes = consumed_bytes; + rbytes -= cbytes; + cfdata->read_offset += (uint16_t)cbytes; + cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes; + } + + if (cfdata->unconsumed) { + cbytes = cfdata->unconsumed; + cfdata->unconsumed = 0; + } else + cbytes = 0; + } + if (cbytes) { + /* Compute the sum. */ + cab_checksum_update(a, (size_t)cbytes); + + /* Consume as much as the compressor actually used. */ + __archive_read_consume(a, cbytes); + cab->cab_offset += cbytes; + cfdata->compressed_bytes_remaining -= (uint16_t)cbytes; + if (cfdata->compressed_bytes_remaining == 0) { + err = cab_checksum_finish(a); + if (err < 0) + return (err); + } + } + return (rbytes); +} + +/* + * Returns ARCHIVE_OK if successful, ARCHIVE_FATAL otherwise, sets + * cab->end_of_entry if it consumes all of the data. + */ +static int +cab_read_data(struct archive_read *a, const void **buff, + size_t *size, int64_t *offset) +{ + struct cab *cab = (struct cab *)(a->format->data); + ssize_t bytes_avail; + + if (cab->entry_bytes_remaining == 0) { + *buff = NULL; + *size = 0; + *offset = cab->entry_offset; + cab->end_of_entry = 1; + return (ARCHIVE_OK); + } + + *buff = cab_read_ahead_cfdata(a, &bytes_avail); + if (bytes_avail <= 0) { + *buff = NULL; + *size = 0; + *offset = 0; + if (bytes_avail == 0 && + cab->entry_cfdata->uncompressed_size == 0) { + /* All of CFDATA in a folder has been handled. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Invalid CFDATA"); + return (ARCHIVE_FATAL); + } else + return ((int)bytes_avail); + } + if (bytes_avail > cab->entry_bytes_remaining) + bytes_avail = (ssize_t)cab->entry_bytes_remaining; + + *size = bytes_avail; + *offset = cab->entry_offset; + cab->entry_offset += bytes_avail; + cab->entry_bytes_remaining -= bytes_avail; + if (cab->entry_bytes_remaining == 0) + cab->end_of_entry = 1; + cab->entry_unconsumed = bytes_avail; + if (cab->entry_cffolder->comptype == COMPTYPE_NONE) { + /* Don't consume more than current entry used. */ + if (cab->entry_cfdata->unconsumed > cab->entry_unconsumed) + cab->entry_cfdata->unconsumed = cab->entry_unconsumed; + } + return (ARCHIVE_OK); +} + +static int +archive_read_format_cab_read_data_skip(struct archive_read *a) +{ + struct cab *cab; + int64_t bytes_skipped; + int r; + + cab = (struct cab *)(a->format->data); + + if (cab->end_of_archive) + return (ARCHIVE_EOF); + + if (!cab->read_data_invoked) { + cab->bytes_skipped += cab->entry_bytes_remaining; + cab->entry_bytes_remaining = 0; + /* This entry is finished and done. */ + cab->end_of_entry_cleanup = cab->end_of_entry = 1; + return (ARCHIVE_OK); + } + + if (cab->entry_unconsumed) { + /* Consume as much as the compressor actually used. */ + r = (int)cab_consume_cfdata(a, cab->entry_unconsumed); + cab->entry_unconsumed = 0; + if (r < 0) + return (r); + } else if (cab->entry_cfdata == NULL) { + r = cab_next_cfdata(a); + if (r < 0) + return (r); + } + + /* if we've already read to end of data, we're done. */ + if (cab->end_of_entry_cleanup) + return (ARCHIVE_OK); + + /* + * If the length is at the beginning, we can skip the + * compressed data much more quickly. + */ + bytes_skipped = cab_consume_cfdata(a, cab->entry_bytes_remaining); + if (bytes_skipped < 0) + return (ARCHIVE_FATAL); + + /* If the compression type is none(uncompressed), we've already + * consumed data as much as the current entry size. */ + if (cab->entry_cffolder->comptype == COMPTYPE_NONE && + cab->entry_cfdata != NULL) + cab->entry_cfdata->unconsumed = 0; + + /* This entry is finished and done. */ + cab->end_of_entry_cleanup = cab->end_of_entry = 1; + return (ARCHIVE_OK); +} + +static int +archive_read_format_cab_cleanup(struct archive_read *a) +{ + struct cab *cab = (struct cab *)(a->format->data); + struct cfheader *hd = &cab->cfheader; + int i; + + if (hd->folder_array != NULL) { + for (i = 0; i < hd->folder_count; i++) + free(hd->folder_array[i].cfdata.memimage); + free(hd->folder_array); + } + if (hd->file_array != NULL) { + for (i = 0; i < cab->cfheader.file_count; i++) + archive_string_free(&(hd->file_array[i].pathname)); + free(hd->file_array); + } +#ifdef HAVE_ZLIB_H + if (cab->stream_valid) + inflateEnd(&cab->stream); +#endif + lzx_decode_free(&cab->xstrm); + archive_wstring_free(&cab->ws); + free(cab->uncompressed_buffer); + free(cab); + (a->format->data) = NULL; + return (ARCHIVE_OK); +} + +/* Convert an MSDOS-style date/time into Unix-style time. */ +static time_t +cab_dos_time(const unsigned char *p) +{ + int msTime, msDate; + struct tm ts; + + msDate = archive_le16dec(p); + msTime = archive_le16dec(p+2); + + memset(&ts, 0, sizeof(ts)); + ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */ + ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */ + ts.tm_mday = msDate & 0x1f; /* Day of month. */ + ts.tm_hour = (msTime >> 11) & 0x1f; + ts.tm_min = (msTime >> 5) & 0x3f; + ts.tm_sec = (msTime << 1) & 0x3e; + ts.tm_isdst = -1; + return (mktime(&ts)); +} + +/***************************************************************** + * + * LZX decompression code. + * + *****************************************************************/ + +/* + * Initialize LZX decoder. + * + * Returns ARCHIVE_OK if initialization was successful. + * Returns ARCHIVE_FAILED if w_bits has unsupported value. + * Returns ARCHIVE_FATAL if initialization failed; memory allocation + * error occurred. + */ +static int +lzx_decode_init(struct lzx_stream *strm, int w_bits) +{ + struct lzx_dec *ds; + int slot, w_size, w_slot; + int base, footer; + int base_inc[18]; + + if (strm->ds == NULL) { + strm->ds = calloc(1, sizeof(*strm->ds)); + if (strm->ds == NULL) + return (ARCHIVE_FATAL); + } + ds = strm->ds; + ds->error = ARCHIVE_FAILED; + + /* Allow bits from 15(32KBi) up to 21(2MBi) */ + if (w_bits < SLOT_BASE || w_bits > SLOT_MAX) + return (ARCHIVE_FAILED); + + ds->error = ARCHIVE_FATAL; + + /* + * Alloc window + */ + w_size = ds->w_size; + w_slot = slots[w_bits - SLOT_BASE]; + ds->w_size = 1U << w_bits; + ds->w_mask = ds->w_size -1; + if (ds->w_buff == NULL || w_size != ds->w_size) { + free(ds->w_buff); + ds->w_buff = malloc(ds->w_size); + if (ds->w_buff == NULL) + return (ARCHIVE_FATAL); + free(ds->pos_tbl); + ds->pos_tbl = malloc(sizeof(ds->pos_tbl[0]) * w_slot); + if (ds->pos_tbl == NULL) + return (ARCHIVE_FATAL); + lzx_huffman_free(&(ds->mt)); + } + + for (footer = 0; footer < 18; footer++) + base_inc[footer] = 1 << footer; + base = footer = 0; + for (slot = 0; slot < w_slot; slot++) { + int n; + if (footer == 0) + base = slot; + else + base += base_inc[footer]; + if (footer < 17) { + footer = -2; + for (n = base; n; n >>= 1) + footer++; + if (footer <= 0) + footer = 0; + } + ds->pos_tbl[slot].base = base; + ds->pos_tbl[slot].footer_bits = footer; + } + + ds->w_pos = 0; + ds->state = 0; + ds->br.cache_buffer = 0; + ds->br.cache_avail = 0; + ds->r0 = ds->r1 = ds->r2 = 1; + + /* Initialize aligned offset tree. */ + if (lzx_huffman_init(&(ds->at), 8, 8) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Initialize pre-tree. */ + if (lzx_huffman_init(&(ds->pt), 20, 10) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Initialize Main tree. */ + if (lzx_huffman_init(&(ds->mt), 256+(w_slot<<3), 16) + != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Initialize Length tree. */ + if (lzx_huffman_init(&(ds->lt), 249, 16) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + ds->error = 0; + + return (ARCHIVE_OK); +} + +/* + * Release LZX decoder. + */ +static void +lzx_decode_free(struct lzx_stream *strm) +{ + + if (strm->ds == NULL) + return; + free(strm->ds->w_buff); + free(strm->ds->pos_tbl); + lzx_huffman_free(&(strm->ds->at)); + lzx_huffman_free(&(strm->ds->pt)); + lzx_huffman_free(&(strm->ds->mt)); + lzx_huffman_free(&(strm->ds->lt)); + free(strm->ds); + strm->ds = NULL; +} + +/* + * E8 Call Translation reversal. + */ +static void +lzx_translation(struct lzx_stream *strm, void *p, size_t size, uint32_t offset) +{ + struct lzx_dec *ds = strm->ds; + unsigned char *b, *end; + + if (!ds->translation || size <= 10) + return; + b = p; + end = b + size - 10; + while (b < end && (b = memchr(b, 0xE8, end - b)) != NULL) { + size_t i = b - (unsigned char *)p; + int32_t cp, displacement, value; + + cp = (int32_t)(offset + (uint32_t)i); + value = archive_le32dec(&b[1]); + if (value >= -cp && value < (int32_t)ds->translation_size) { + if (value >= 0) + displacement = value - cp; + else + displacement = value + ds->translation_size; + archive_le32enc(&b[1], (uint32_t)displacement); + } + b += 5; + } +} + +/* + * Bit stream reader. + */ +/* Check that the cache buffer has enough bits. */ +#define lzx_br_has(br, n) ((br)->cache_avail >= n) +/* Get compressed data by bit. */ +#define lzx_br_bits(br, n) \ + (((uint32_t)((br)->cache_buffer >> \ + ((br)->cache_avail - (n)))) & cache_masks[n]) +#define lzx_br_bits_forced(br, n) \ + (((uint32_t)((br)->cache_buffer << \ + ((n) - (br)->cache_avail))) & cache_masks[n]) +/* Read ahead to make sure the cache buffer has enough compressed data we + * will use. + * True : completed, there is enough data in the cache buffer. + * False : we met that strm->next_in is empty, we have to get following + * bytes. */ +#define lzx_br_read_ahead_0(strm, br, n) \ + (lzx_br_has((br), (n)) || lzx_br_fillup(strm, br)) +/* True : the cache buffer has some bits as much as we need. + * False : there are no enough bits in the cache buffer to be used, + * we have to get following bytes if we could. */ +#define lzx_br_read_ahead(strm, br, n) \ + (lzx_br_read_ahead_0((strm), (br), (n)) || lzx_br_has((br), (n))) + +/* Notify how many bits we consumed. */ +#define lzx_br_consume(br, n) ((br)->cache_avail -= (n)) +#define lzx_br_consume_unaligned_bits(br) ((br)->cache_avail &= ~0x0f) + +#define lzx_br_is_unaligned(br) ((br)->cache_avail & 0x0f) + +static const uint32_t cache_masks[] = { + 0x00000000, 0x00000001, 0x00000003, 0x00000007, + 0x0000000F, 0x0000001F, 0x0000003F, 0x0000007F, + 0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF, + 0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF, + 0x0000FFFF, 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, + 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, + 0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, + 0x0FFFFFFF, 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF +}; + +/* + * Shift away used bits in the cache data and fill it up with following bits. + * Call this when cache buffer does not have enough bits you need. + * + * Returns 1 if the cache buffer is full. + * Returns 0 if the cache buffer is not full; input buffer is empty. + */ +static int +lzx_br_fillup(struct lzx_stream *strm, struct lzx_br *br) +{ +/* + * x86 processor family can read misaligned data without an access error. + */ + int n = CACHE_BITS - br->cache_avail; + + for (;;) { + switch (n >> 4) { + case 4: + if (strm->avail_in >= 8) { + br->cache_buffer = + ((uint64_t)strm->next_in[1]) << 56 | + ((uint64_t)strm->next_in[0]) << 48 | + ((uint64_t)strm->next_in[3]) << 40 | + ((uint64_t)strm->next_in[2]) << 32 | + ((uint32_t)strm->next_in[5]) << 24 | + ((uint32_t)strm->next_in[4]) << 16 | + ((uint32_t)strm->next_in[7]) << 8 | + (uint32_t)strm->next_in[6]; + strm->next_in += 8; + strm->avail_in -= 8; + br->cache_avail += 8 * 8; + return (1); + } + break; + case 3: + if (strm->avail_in >= 6) { + br->cache_buffer = + (br->cache_buffer << 48) | + ((uint64_t)strm->next_in[1]) << 40 | + ((uint64_t)strm->next_in[0]) << 32 | + ((uint32_t)strm->next_in[3]) << 24 | + ((uint32_t)strm->next_in[2]) << 16 | + ((uint32_t)strm->next_in[5]) << 8 | + (uint32_t)strm->next_in[4]; + strm->next_in += 6; + strm->avail_in -= 6; + br->cache_avail += 6 * 8; + return (1); + } + break; + case 0: + /* We have enough compressed data in + * the cache buffer.*/ + return (1); + default: + break; + } + if (strm->avail_in < 2) { + /* There is not enough compressed data to + * fill up the cache buffer. */ + if (strm->avail_in == 1) { + br->odd = *strm->next_in++; + strm->avail_in--; + br->have_odd = 1; + } + return (0); + } + br->cache_buffer = + (br->cache_buffer << 16) | + archive_le16dec(strm->next_in); + strm->next_in += 2; + strm->avail_in -= 2; + br->cache_avail += 16; + n -= 16; + } +} + +static void +lzx_br_fixup(struct lzx_stream *strm, struct lzx_br *br) +{ + int n = CACHE_BITS - br->cache_avail; + + if (br->have_odd && n >= 16 && strm->avail_in > 0) { + br->cache_buffer = + (br->cache_buffer << 16) | + ((uint16_t)(*strm->next_in)) << 8 | br->odd; + strm->next_in++; + strm->avail_in--; + br->cache_avail += 16; + br->have_odd = 0; + } +} + +static void +lzx_cleanup_bitstream(struct lzx_stream *strm) +{ + strm->ds->br.cache_avail = 0; + strm->ds->br.have_odd = 0; +} + +/* + * Decode LZX. + * + * 1. Returns ARCHIVE_OK if output buffer or input buffer are empty. + * Please set available buffer and call this function again. + * 2. Returns ARCHIVE_EOF if decompression has been completed. + * 3. Returns ARCHIVE_FAILED if an error occurred; compressed data + * is broken or you do not set 'last' flag properly. + */ +#define ST_RD_TRANSLATION 0 +#define ST_RD_TRANSLATION_SIZE 1 +#define ST_RD_BLOCK_TYPE 2 +#define ST_RD_BLOCK_SIZE 3 +#define ST_RD_ALIGNMENT 4 +#define ST_RD_R0 5 +#define ST_RD_R1 6 +#define ST_RD_R2 7 +#define ST_COPY_UNCOMP1 8 +#define ST_COPY_UNCOMP2 9 +#define ST_RD_ALIGNED_OFFSET 10 +#define ST_RD_VERBATIM 11 +#define ST_RD_PRE_MAIN_TREE_256 12 +#define ST_MAIN_TREE_256 13 +#define ST_RD_PRE_MAIN_TREE_REM 14 +#define ST_MAIN_TREE_REM 15 +#define ST_RD_PRE_LENGTH_TREE 16 +#define ST_LENGTH_TREE 17 +#define ST_MAIN 18 +#define ST_LENGTH 19 +#define ST_OFFSET 20 +#define ST_REAL_POS 21 +#define ST_COPY 22 + +static int +lzx_decode(struct lzx_stream *strm, int last) +{ + struct lzx_dec *ds = strm->ds; + int64_t avail_in; + int r; + + if (ds->error) + return (ds->error); + + avail_in = strm->avail_in; + lzx_br_fixup(strm, &(ds->br)); + do { + if (ds->state < ST_MAIN) + r = lzx_read_blocks(strm, last); + else { + int64_t bytes_written = strm->avail_out; + r = lzx_decode_blocks(strm, last); + bytes_written -= strm->avail_out; + strm->next_out += bytes_written; + strm->total_out += bytes_written; + } + } while (r == 100); + strm->total_in += avail_in - strm->avail_in; + return (r); +} + +static int +lzx_read_blocks(struct lzx_stream *strm, int last) +{ + struct lzx_dec *ds = strm->ds; + struct lzx_br *br = &(ds->br); + int i, r; + + for (;;) { + switch (ds->state) { + case ST_RD_TRANSLATION: + if (!lzx_br_read_ahead(strm, br, 1)) { + ds->state = ST_RD_TRANSLATION; + if (last) + goto failed; + return (ARCHIVE_OK); + } + ds->translation = lzx_br_bits(br, 1); + lzx_br_consume(br, 1); + /* FALL THROUGH */ + case ST_RD_TRANSLATION_SIZE: + if (ds->translation) { + if (!lzx_br_read_ahead(strm, br, 32)) { + ds->state = ST_RD_TRANSLATION_SIZE; + if (last) + goto failed; + return (ARCHIVE_OK); + } + ds->translation_size = lzx_br_bits(br, 16); + lzx_br_consume(br, 16); + ds->translation_size <<= 16; + ds->translation_size |= lzx_br_bits(br, 16); + lzx_br_consume(br, 16); + } + /* FALL THROUGH */ + case ST_RD_BLOCK_TYPE: + if (!lzx_br_read_ahead(strm, br, 3)) { + ds->state = ST_RD_BLOCK_TYPE; + if (last) + goto failed; + return (ARCHIVE_OK); + } + ds->block_type = lzx_br_bits(br, 3); + lzx_br_consume(br, 3); + /* Check a block type. */ + switch (ds->block_type) { + case VERBATIM_BLOCK: + case ALIGNED_OFFSET_BLOCK: + case UNCOMPRESSED_BLOCK: + break; + default: + goto failed;/* Invalid */ + } + /* FALL THROUGH */ + case ST_RD_BLOCK_SIZE: + if (!lzx_br_read_ahead(strm, br, 24)) { + ds->state = ST_RD_BLOCK_SIZE; + if (last) + goto failed; + return (ARCHIVE_OK); + } + ds->block_size = lzx_br_bits(br, 8); + lzx_br_consume(br, 8); + ds->block_size <<= 16; + ds->block_size |= lzx_br_bits(br, 16); + lzx_br_consume(br, 16); + if (ds->block_size == 0) + goto failed; + ds->block_bytes_avail = ds->block_size; + if (ds->block_type != UNCOMPRESSED_BLOCK) { + if (ds->block_type == VERBATIM_BLOCK) + ds->state = ST_RD_VERBATIM; + else + ds->state = ST_RD_ALIGNED_OFFSET; + break; + } + /* FALL THROUGH */ + case ST_RD_ALIGNMENT: + /* + * Handle an Uncompressed Block. + */ + /* Skip padding to align following field on + * 16-bit boundary. */ + if (lzx_br_is_unaligned(br)) + lzx_br_consume_unaligned_bits(br); + else { + if (lzx_br_read_ahead(strm, br, 16)) + lzx_br_consume(br, 16); + else { + ds->state = ST_RD_ALIGNMENT; + if (last) + goto failed; + return (ARCHIVE_OK); + } + } + /* Preparation to read repeated offsets R0,R1 and R2. */ + ds->rbytes_avail = 0; + ds->state = ST_RD_R0; + /* FALL THROUGH */ + case ST_RD_R0: + case ST_RD_R1: + case ST_RD_R2: + do { + uint16_t u16; + /* Drain bits in the cache buffer of + * bit-stream. */ + if (lzx_br_has(br, 32)) { + u16 = lzx_br_bits(br, 16); + lzx_br_consume(br, 16); + archive_le16enc(ds->rbytes, u16); + u16 = lzx_br_bits(br, 16); + lzx_br_consume(br, 16); + archive_le16enc(ds->rbytes+2, u16); + ds->rbytes_avail = 4; + } else if (lzx_br_has(br, 16)) { + u16 = lzx_br_bits(br, 16); + lzx_br_consume(br, 16); + archive_le16enc(ds->rbytes, u16); + ds->rbytes_avail = 2; + } + if (ds->rbytes_avail < 4 && ds->br.have_odd) { + ds->rbytes[ds->rbytes_avail++] = + ds->br.odd; + ds->br.have_odd = 0; + } + while (ds->rbytes_avail < 4) { + if (strm->avail_in <= 0) { + if (last) + goto failed; + return (ARCHIVE_OK); + } + ds->rbytes[ds->rbytes_avail++] = + *strm->next_in++; + strm->avail_in--; + } + ds->rbytes_avail = 0; + if (ds->state == ST_RD_R0) { + ds->r0 = archive_le32dec(ds->rbytes); + if (ds->r0 < 0) + goto failed; + ds->state = ST_RD_R1; + } else if (ds->state == ST_RD_R1) { + ds->r1 = archive_le32dec(ds->rbytes); + if (ds->r1 < 0) + goto failed; + ds->state = ST_RD_R2; + } else if (ds->state == ST_RD_R2) { + ds->r2 = archive_le32dec(ds->rbytes); + if (ds->r2 < 0) + goto failed; + /* We've gotten all repeated offsets. */ + ds->state = ST_COPY_UNCOMP1; + } + } while (ds->state != ST_COPY_UNCOMP1); + /* FALL THROUGH */ + case ST_COPY_UNCOMP1: + /* + * Copy bytes form next_in to next_out directly. + */ + while (ds->block_bytes_avail) { + int l; + + if (strm->avail_out <= 0) + /* Output buffer is empty. */ + return (ARCHIVE_OK); + if (strm->avail_in <= 0) { + /* Input buffer is empty. */ + if (last) + goto failed; + return (ARCHIVE_OK); + } + l = (int)ds->block_bytes_avail; + if (l > ds->w_size - ds->w_pos) + l = ds->w_size - ds->w_pos; + if (l > strm->avail_out) + l = (int)strm->avail_out; + if (l > strm->avail_in) + l = (int)strm->avail_in; + memcpy(strm->next_out, strm->next_in, l); + memcpy(&(ds->w_buff[ds->w_pos]), + strm->next_in, l); + strm->next_in += l; + strm->avail_in -= l; + strm->next_out += l; + strm->avail_out -= l; + strm->total_out += l; + ds->w_pos = (ds->w_pos + l) & ds->w_mask; + ds->block_bytes_avail -= l; + } + /* FALL THROUGH */ + case ST_COPY_UNCOMP2: + /* Re-align; skip padding byte. */ + if (ds->block_size & 1) { + if (strm->avail_in <= 0) { + /* Input buffer is empty. */ + ds->state = ST_COPY_UNCOMP2; + if (last) + goto failed; + return (ARCHIVE_OK); + } + strm->next_in++; + strm->avail_in --; + } + /* This block ended. */ + ds->state = ST_RD_BLOCK_TYPE; + return (ARCHIVE_EOF); + /********************/ + case ST_RD_ALIGNED_OFFSET: + /* + * Read Aligned offset tree. + */ + if (!lzx_br_read_ahead(strm, br, 3 * ds->at.len_size)) { + ds->state = ST_RD_ALIGNED_OFFSET; + if (last) + goto failed; + return (ARCHIVE_OK); + } + memset(ds->at.freq, 0, sizeof(ds->at.freq)); + for (i = 0; i < ds->at.len_size; i++) { + ds->at.bitlen[i] = lzx_br_bits(br, 3); + ds->at.freq[ds->at.bitlen[i]]++; + lzx_br_consume(br, 3); + } + if (!lzx_make_huffman_table(&ds->at)) + goto failed; + /* FALL THROUGH */ + case ST_RD_VERBATIM: + ds->loop = 0; + /* FALL THROUGH */ + case ST_RD_PRE_MAIN_TREE_256: + /* + * Read Pre-tree for first 256 elements of main tree. + */ + if (!lzx_read_pre_tree(strm)) { + ds->state = ST_RD_PRE_MAIN_TREE_256; + if (last) + goto failed; + return (ARCHIVE_OK); + } + if (!lzx_make_huffman_table(&ds->pt)) + goto failed; + ds->loop = 0; + /* FALL THROUGH */ + case ST_MAIN_TREE_256: + /* + * Get path lengths of first 256 elements of main tree. + */ + r = lzx_read_bitlen(strm, &ds->mt, 256); + if (r < 0) + goto failed; + else if (!r) { + ds->state = ST_MAIN_TREE_256; + if (last) + goto failed; + return (ARCHIVE_OK); + } + ds->loop = 0; + /* FALL THROUGH */ + case ST_RD_PRE_MAIN_TREE_REM: + /* + * Read Pre-tree for remaining elements of main tree. + */ + if (!lzx_read_pre_tree(strm)) { + ds->state = ST_RD_PRE_MAIN_TREE_REM; + if (last) + goto failed; + return (ARCHIVE_OK); + } + if (!lzx_make_huffman_table(&ds->pt)) + goto failed; + ds->loop = 256; + /* FALL THROUGH */ + case ST_MAIN_TREE_REM: + /* + * Get path lengths of remaining elements of main tree. + */ + r = lzx_read_bitlen(strm, &ds->mt, -1); + if (r < 0) + goto failed; + else if (!r) { + ds->state = ST_MAIN_TREE_REM; + if (last) + goto failed; + return (ARCHIVE_OK); + } + if (!lzx_make_huffman_table(&ds->mt)) + goto failed; + ds->loop = 0; + /* FALL THROUGH */ + case ST_RD_PRE_LENGTH_TREE: + /* + * Read Pre-tree for remaining elements of main tree. + */ + if (!lzx_read_pre_tree(strm)) { + ds->state = ST_RD_PRE_LENGTH_TREE; + if (last) + goto failed; + return (ARCHIVE_OK); + } + if (!lzx_make_huffman_table(&ds->pt)) + goto failed; + ds->loop = 0; + /* FALL THROUGH */ + case ST_LENGTH_TREE: + /* + * Get path lengths of remaining elements of main tree. + */ + r = lzx_read_bitlen(strm, &ds->lt, -1); + if (r < 0) + goto failed; + else if (!r) { + ds->state = ST_LENGTH_TREE; + if (last) + goto failed; + return (ARCHIVE_OK); + } + if (!lzx_make_huffman_table(&ds->lt)) + goto failed; + ds->state = ST_MAIN; + return (100); + } + } +failed: + return (ds->error = ARCHIVE_FAILED); +} + +static int +lzx_decode_blocks(struct lzx_stream *strm, int last) +{ + struct lzx_dec *ds = strm->ds; + struct lzx_br bre = ds->br; + struct huffman *at = &(ds->at), *lt = &(ds->lt), *mt = &(ds->mt); + const struct lzx_pos_tbl *pos_tbl = ds->pos_tbl; + unsigned char *noutp = strm->next_out; + unsigned char *endp = noutp + strm->avail_out; + unsigned char *w_buff = ds->w_buff; + unsigned char *at_bitlen = at->bitlen; + unsigned char *lt_bitlen = lt->bitlen; + unsigned char *mt_bitlen = mt->bitlen; + size_t block_bytes_avail = ds->block_bytes_avail; + int at_max_bits = at->max_bits; + int lt_max_bits = lt->max_bits; + int mt_max_bits = mt->max_bits; + int c, copy_len = ds->copy_len, copy_pos = ds->copy_pos; + int w_pos = ds->w_pos, w_mask = ds->w_mask, w_size = ds->w_size; + int length_header = ds->length_header; + int offset_bits = ds->offset_bits; + int position_slot = ds->position_slot; + int r0 = ds->r0, r1 = ds->r1, r2 = ds->r2; + int state = ds->state; + char block_type = ds->block_type; + + for (;;) { + switch (state) { + case ST_MAIN: + for (;;) { + if (block_bytes_avail == 0) { + /* This block ended. */ + ds->state = ST_RD_BLOCK_TYPE; + ds->br = bre; + ds->block_bytes_avail = + block_bytes_avail; + ds->copy_len = copy_len; + ds->copy_pos = copy_pos; + ds->length_header = length_header; + ds->position_slot = position_slot; + ds->r0 = r0; ds->r1 = r1; ds->r2 = r2; + ds->w_pos = w_pos; + strm->avail_out = endp - noutp; + return (ARCHIVE_EOF); + } + if (noutp >= endp) + /* Output buffer is empty. */ + goto next_data; + + if (!lzx_br_read_ahead(strm, &bre, + mt_max_bits)) { + if (!last) + goto next_data; + /* Remaining bits are less than + * maximum bits(mt.max_bits) but maybe + * it still remains as much as we need, + * so we should try to use it with + * dummy bits. */ + c = lzx_decode_huffman(mt, + lzx_br_bits_forced( + &bre, mt_max_bits)); + lzx_br_consume(&bre, mt_bitlen[c]); + if (!lzx_br_has(&bre, 0)) + goto failed;/* Over read. */ + } else { + c = lzx_decode_huffman(mt, + lzx_br_bits(&bre, mt_max_bits)); + lzx_br_consume(&bre, mt_bitlen[c]); + } + if (c > UCHAR_MAX) + break; + /* + * 'c' is exactly literal code. + */ + /* Save a decoded code to reference it + * afterward. */ + w_buff[w_pos] = c; + w_pos = (w_pos + 1) & w_mask; + /* Store the decoded code to output buffer. */ + *noutp++ = c; + block_bytes_avail--; + } + /* + * Get a match code, its length and offset. + */ + c -= UCHAR_MAX + 1; + length_header = c & 7; + position_slot = c >> 3; + /* FALL THROUGH */ + case ST_LENGTH: + /* + * Get a length. + */ + if (length_header == 7) { + if (!lzx_br_read_ahead(strm, &bre, + lt_max_bits)) { + if (!last) { + state = ST_LENGTH; + goto next_data; + } + c = lzx_decode_huffman(lt, + lzx_br_bits_forced( + &bre, lt_max_bits)); + lzx_br_consume(&bre, lt_bitlen[c]); + if (!lzx_br_has(&bre, 0)) + goto failed;/* Over read. */ + } else { + c = lzx_decode_huffman(lt, + lzx_br_bits(&bre, lt_max_bits)); + lzx_br_consume(&bre, lt_bitlen[c]); + } + copy_len = c + 7 + 2; + } else + copy_len = length_header + 2; + if ((size_t)copy_len > block_bytes_avail) + goto failed; + /* + * Get an offset. + */ + switch (position_slot) { + case 0: /* Use repeated offset 0. */ + copy_pos = r0; + state = ST_REAL_POS; + continue; + case 1: /* Use repeated offset 1. */ + copy_pos = r1; + /* Swap repeated offset. */ + r1 = r0; + r0 = copy_pos; + state = ST_REAL_POS; + continue; + case 2: /* Use repeated offset 2. */ + copy_pos = r2; + /* Swap repeated offset. */ + r2 = r0; + r0 = copy_pos; + state = ST_REAL_POS; + continue; + default: + offset_bits = + pos_tbl[position_slot].footer_bits; + break; + } + /* FALL THROUGH */ + case ST_OFFSET: + /* + * Get the offset, which is a distance from + * current window position. + */ + if (block_type == ALIGNED_OFFSET_BLOCK && + offset_bits >= 3) { + int offbits = offset_bits - 3; + + if (!lzx_br_read_ahead(strm, &bre, offbits)) { + state = ST_OFFSET; + if (last) + goto failed; + goto next_data; + } + copy_pos = lzx_br_bits(&bre, offbits) << 3; + + /* Get an aligned number. */ + if (!lzx_br_read_ahead(strm, &bre, + offbits + at_max_bits)) { + if (!last) { + state = ST_OFFSET; + goto next_data; + } + lzx_br_consume(&bre, offbits); + c = lzx_decode_huffman(at, + lzx_br_bits_forced(&bre, + at_max_bits)); + lzx_br_consume(&bre, at_bitlen[c]); + if (!lzx_br_has(&bre, 0)) + goto failed;/* Over read. */ + } else { + lzx_br_consume(&bre, offbits); + c = lzx_decode_huffman(at, + lzx_br_bits(&bre, at_max_bits)); + lzx_br_consume(&bre, at_bitlen[c]); + } + /* Add an aligned number. */ + copy_pos += c; + } else { + if (!lzx_br_read_ahead(strm, &bre, + offset_bits)) { + state = ST_OFFSET; + if (last) + goto failed; + goto next_data; + } + copy_pos = lzx_br_bits(&bre, offset_bits); + lzx_br_consume(&bre, offset_bits); + } + copy_pos += pos_tbl[position_slot].base -2; + + /* Update repeated offset LRU queue. */ + r2 = r1; + r1 = r0; + r0 = copy_pos; + /* FALL THROUGH */ + case ST_REAL_POS: + /* + * Compute a real position in window. + */ + copy_pos = (w_pos - copy_pos) & w_mask; + /* FALL THROUGH */ + case ST_COPY: + /* + * Copy several bytes as extracted data from the window + * into the output buffer. + */ + for (;;) { + const unsigned char *s; + int l; + + l = copy_len; + if (copy_pos > w_pos) { + if (l > w_size - copy_pos) + l = w_size - copy_pos; + } else { + if (l > w_size - w_pos) + l = w_size - w_pos; + } + if (noutp + l >= endp) + l = (int)(endp - noutp); + s = w_buff + copy_pos; + if (l >= 8 && ((copy_pos + l < w_pos) + || (w_pos + l < copy_pos))) { + memcpy(w_buff + w_pos, s, l); + memcpy(noutp, s, l); + } else { + unsigned char *d; + int li; + + d = w_buff + w_pos; + for (li = 0; li < l; li++) + noutp[li] = d[li] = s[li]; + } + noutp += l; + copy_pos = (copy_pos + l) & w_mask; + w_pos = (w_pos + l) & w_mask; + block_bytes_avail -= l; + if (copy_len <= l) + /* A copy of current pattern ended. */ + break; + copy_len -= l; + if (noutp >= endp) { + /* Output buffer is empty. */ + state = ST_COPY; + goto next_data; + } + } + state = ST_MAIN; + break; + } + } +failed: + return (ds->error = ARCHIVE_FAILED); +next_data: + ds->br = bre; + ds->block_bytes_avail = block_bytes_avail; + ds->copy_len = copy_len; + ds->copy_pos = copy_pos; + ds->length_header = length_header; + ds->offset_bits = offset_bits; + ds->position_slot = position_slot; + ds->r0 = r0; ds->r1 = r1; ds->r2 = r2; + ds->state = state; + ds->w_pos = w_pos; + strm->avail_out = endp - noutp; + return (ARCHIVE_OK); +} + +static int +lzx_read_pre_tree(struct lzx_stream *strm) +{ + struct lzx_dec *ds = strm->ds; + struct lzx_br *br = &(ds->br); + int i; + + if (ds->loop == 0) + memset(ds->pt.freq, 0, sizeof(ds->pt.freq)); + for (i = ds->loop; i < ds->pt.len_size; i++) { + if (!lzx_br_read_ahead(strm, br, 4)) { + ds->loop = i; + return (0); + } + ds->pt.bitlen[i] = lzx_br_bits(br, 4); + ds->pt.freq[ds->pt.bitlen[i]]++; + lzx_br_consume(br, 4); + } + ds->loop = i; + return (1); +} + +/* + * Read a bunch of bit-lengths from pre-tree. + */ +static int +lzx_read_bitlen(struct lzx_stream *strm, struct huffman *d, int end) +{ + struct lzx_dec *ds = strm->ds; + struct lzx_br *br = &(ds->br); + int c, i, j, ret, same; + unsigned rbits; + + i = ds->loop; + if (i == 0) + memset(d->freq, 0, sizeof(d->freq)); + ret = 0; + if (end < 0) + end = d->len_size; + while (i < end) { + ds->loop = i; + if (!lzx_br_read_ahead(strm, br, ds->pt.max_bits)) + goto getdata; + rbits = lzx_br_bits(br, ds->pt.max_bits); + c = lzx_decode_huffman(&(ds->pt), rbits); + switch (c) { + case 17:/* several zero lengths, from 4 to 19. */ + if (!lzx_br_read_ahead(strm, br, ds->pt.bitlen[c]+4)) + goto getdata; + lzx_br_consume(br, ds->pt.bitlen[c]); + same = lzx_br_bits(br, 4) + 4; + if (i + same > end) + return (-1);/* Invalid */ + lzx_br_consume(br, 4); + for (j = 0; j < same; j++) + d->bitlen[i++] = 0; + break; + case 18:/* many zero lengths, from 20 to 51. */ + if (!lzx_br_read_ahead(strm, br, ds->pt.bitlen[c]+5)) + goto getdata; + lzx_br_consume(br, ds->pt.bitlen[c]); + same = lzx_br_bits(br, 5) + 20; + if (i + same > end) + return (-1);/* Invalid */ + lzx_br_consume(br, 5); + memset(d->bitlen + i, 0, same); + i += same; + break; + case 19:/* a few same lengths. */ + if (!lzx_br_read_ahead(strm, br, + ds->pt.bitlen[c]+1+ds->pt.max_bits)) + goto getdata; + lzx_br_consume(br, ds->pt.bitlen[c]); + same = lzx_br_bits(br, 1) + 4; + if (i + same > end) + return (-1); + lzx_br_consume(br, 1); + rbits = lzx_br_bits(br, ds->pt.max_bits); + c = lzx_decode_huffman(&(ds->pt), rbits); + lzx_br_consume(br, ds->pt.bitlen[c]); + c = (d->bitlen[i] - c + 17) % 17; + if (c < 0) + return (-1);/* Invalid */ + for (j = 0; j < same; j++) + d->bitlen[i++] = c; + d->freq[c] += same; + break; + default: + lzx_br_consume(br, ds->pt.bitlen[c]); + c = (d->bitlen[i] - c + 17) % 17; + if (c < 0) + return (-1);/* Invalid */ + d->freq[c]++; + d->bitlen[i++] = c; + break; + } + } + ret = 1; +getdata: + ds->loop = i; + return (ret); +} + +static int +lzx_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits) +{ + + if (hf->bitlen == NULL || hf->len_size != (int)len_size) { + free(hf->bitlen); + hf->bitlen = calloc(len_size, sizeof(hf->bitlen[0])); + if (hf->bitlen == NULL) + return (ARCHIVE_FATAL); + hf->len_size = (int)len_size; + } else + memset(hf->bitlen, 0, len_size * sizeof(hf->bitlen[0])); + if (hf->tbl == NULL) { + hf->tbl = malloc(((size_t)1 << tbl_bits) * sizeof(hf->tbl[0])); + if (hf->tbl == NULL) + return (ARCHIVE_FATAL); + hf->tbl_bits = tbl_bits; + } + return (ARCHIVE_OK); +} + +static void +lzx_huffman_free(struct huffman *hf) +{ + free(hf->bitlen); + free(hf->tbl); +} + +/* + * Make a huffman coding table. + */ +static int +lzx_make_huffman_table(struct huffman *hf) +{ + uint16_t *tbl; + const unsigned char *bitlen; + int bitptn[17], weight[17]; + int i, maxbits = 0, ptn, tbl_size, w; + int len_avail; + + /* + * Initialize bit patterns. + */ + ptn = 0; + for (i = 1, w = 1 << 15; i <= 16; i++, w >>= 1) { + bitptn[i] = ptn; + weight[i] = w; + if (hf->freq[i]) { + ptn += hf->freq[i] * w; + maxbits = i; + } + } + if ((ptn & 0xffff) != 0 || maxbits > hf->tbl_bits) + return (0);/* Invalid */ + + hf->max_bits = maxbits; + + /* + * Cut out extra bits which we won't house in the table. + * This preparation reduces the same calculation in the for-loop + * making the table. + */ + if (maxbits < 16) { + int ebits = 16 - maxbits; + for (i = 1; i <= maxbits; i++) { + bitptn[i] >>= ebits; + weight[i] >>= ebits; + } + } + + /* + * Make the table. + */ + tbl_size = 1 << hf->tbl_bits; + tbl = hf->tbl; + bitlen = hf->bitlen; + len_avail = hf->len_size; + hf->tree_used = 0; + for (i = 0; i < len_avail; i++) { + uint16_t *p; + int len, cnt; + + if (bitlen[i] == 0) + continue; + /* Get a bit pattern */ + len = bitlen[i]; + if (len > tbl_size) + return (0); + ptn = bitptn[len]; + cnt = weight[len]; + /* Calculate next bit pattern */ + if ((bitptn[len] = ptn + cnt) > tbl_size) + return (0);/* Invalid */ + /* Update the table */ + p = &(tbl[ptn]); + while (--cnt >= 0) + p[cnt] = (uint16_t)i; + } + return (1); +} + +static inline int +lzx_decode_huffman(struct huffman *hf, unsigned rbits) +{ + int c; + c = hf->tbl[rbits]; + if (c < hf->len_size) + return (c); + return (0); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_cpio.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_cpio.c new file mode 100644 index 0000000..1c96e6a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_cpio.c @@ -0,0 +1,1086 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2010-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_cpio.c 201163 2009-12-29 05:50:34Z kientzle $"); + +#ifdef HAVE_ERRNO_H +#include +#endif +/* #include */ /* See archive_platform.h */ +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_private.h" +#include "archive_read_private.h" + +#define bin_magic_offset 0 +#define bin_magic_size 2 +#define bin_dev_offset 2 +#define bin_dev_size 2 +#define bin_ino_offset 4 +#define bin_ino_size 2 +#define bin_mode_offset 6 +#define bin_mode_size 2 +#define bin_uid_offset 8 +#define bin_uid_size 2 +#define bin_gid_offset 10 +#define bin_gid_size 2 +#define bin_nlink_offset 12 +#define bin_nlink_size 2 +#define bin_rdev_offset 14 +#define bin_rdev_size 2 +#define bin_mtime_offset 16 +#define bin_mtime_size 4 +#define bin_namesize_offset 20 +#define bin_namesize_size 2 +#define bin_filesize_offset 22 +#define bin_filesize_size 4 +#define bin_header_size 26 + +#define odc_magic_offset 0 +#define odc_magic_size 6 +#define odc_dev_offset 6 +#define odc_dev_size 6 +#define odc_ino_offset 12 +#define odc_ino_size 6 +#define odc_mode_offset 18 +#define odc_mode_size 6 +#define odc_uid_offset 24 +#define odc_uid_size 6 +#define odc_gid_offset 30 +#define odc_gid_size 6 +#define odc_nlink_offset 36 +#define odc_nlink_size 6 +#define odc_rdev_offset 42 +#define odc_rdev_size 6 +#define odc_mtime_offset 48 +#define odc_mtime_size 11 +#define odc_namesize_offset 59 +#define odc_namesize_size 6 +#define odc_filesize_offset 65 +#define odc_filesize_size 11 +#define odc_header_size 76 + +#define newc_magic_offset 0 +#define newc_magic_size 6 +#define newc_ino_offset 6 +#define newc_ino_size 8 +#define newc_mode_offset 14 +#define newc_mode_size 8 +#define newc_uid_offset 22 +#define newc_uid_size 8 +#define newc_gid_offset 30 +#define newc_gid_size 8 +#define newc_nlink_offset 38 +#define newc_nlink_size 8 +#define newc_mtime_offset 46 +#define newc_mtime_size 8 +#define newc_filesize_offset 54 +#define newc_filesize_size 8 +#define newc_devmajor_offset 62 +#define newc_devmajor_size 8 +#define newc_devminor_offset 70 +#define newc_devminor_size 8 +#define newc_rdevmajor_offset 78 +#define newc_rdevmajor_size 8 +#define newc_rdevminor_offset 86 +#define newc_rdevminor_size 8 +#define newc_namesize_offset 94 +#define newc_namesize_size 8 +#define newc_checksum_offset 102 +#define newc_checksum_size 8 +#define newc_header_size 110 + +/* + * An afio large ASCII header, which they named itself. + * afio utility uses this header, if a file size is larger than 2G bytes + * or inode/uid/gid is bigger than 65535(0xFFFF) or mtime is bigger than + * 0x7fffffff, which we cannot record to odc header because of its limit. + * If not, uses odc header. + */ +#define afiol_magic_offset 0 +#define afiol_magic_size 6 +#define afiol_dev_offset 6 +#define afiol_dev_size 8 /* hex */ +#define afiol_ino_offset 14 +#define afiol_ino_size 16 /* hex */ +#define afiol_ino_m_offset 30 /* 'm' */ +#define afiol_mode_offset 31 +#define afiol_mode_size 6 /* oct */ +#define afiol_uid_offset 37 +#define afiol_uid_size 8 /* hex */ +#define afiol_gid_offset 45 +#define afiol_gid_size 8 /* hex */ +#define afiol_nlink_offset 53 +#define afiol_nlink_size 8 /* hex */ +#define afiol_rdev_offset 61 +#define afiol_rdev_size 8 /* hex */ +#define afiol_mtime_offset 69 +#define afiol_mtime_size 16 /* hex */ +#define afiol_mtime_n_offset 85 /* 'n' */ +#define afiol_namesize_offset 86 +#define afiol_namesize_size 4 /* hex */ +#define afiol_flag_offset 90 +#define afiol_flag_size 4 /* hex */ +#define afiol_xsize_offset 94 +#define afiol_xsize_size 4 /* hex */ +#define afiol_xsize_s_offset 98 /* 's' */ +#define afiol_filesize_offset 99 +#define afiol_filesize_size 16 /* hex */ +#define afiol_filesize_c_offset 115 /* ':' */ +#define afiol_header_size 116 + + +struct links_entry { + struct links_entry *next; + struct links_entry *previous; + unsigned int links; + dev_t dev; + int64_t ino; + char *name; +}; + +#define CPIO_MAGIC 0x13141516 +struct cpio { + int magic; + int (*read_header)(struct archive_read *, struct cpio *, + struct archive_entry *, size_t *, size_t *); + struct links_entry *links_head; + int64_t entry_bytes_remaining; + int64_t entry_bytes_unconsumed; + int64_t entry_offset; + int64_t entry_padding; + + struct archive_string_conv *opt_sconv; + struct archive_string_conv *sconv_default; + int init_default_conversion; +}; + +static int64_t atol16(const char *, unsigned); +static int64_t atol8(const char *, unsigned); +static int archive_read_format_cpio_bid(struct archive_read *, int); +static int archive_read_format_cpio_options(struct archive_read *, + const char *, const char *); +static int archive_read_format_cpio_cleanup(struct archive_read *); +static int archive_read_format_cpio_read_data(struct archive_read *, + const void **, size_t *, int64_t *); +static int archive_read_format_cpio_read_header(struct archive_read *, + struct archive_entry *); +static int archive_read_format_cpio_skip(struct archive_read *); +static int64_t be4(const unsigned char *); +static int find_odc_header(struct archive_read *); +static int find_newc_header(struct archive_read *); +static int header_bin_be(struct archive_read *, struct cpio *, + struct archive_entry *, size_t *, size_t *); +static int header_bin_le(struct archive_read *, struct cpio *, + struct archive_entry *, size_t *, size_t *); +static int header_newc(struct archive_read *, struct cpio *, + struct archive_entry *, size_t *, size_t *); +static int header_odc(struct archive_read *, struct cpio *, + struct archive_entry *, size_t *, size_t *); +static int header_afiol(struct archive_read *, struct cpio *, + struct archive_entry *, size_t *, size_t *); +static int is_octal(const char *, size_t); +static int is_hex(const char *, size_t); +static int64_t le4(const unsigned char *); +static int record_hardlink(struct archive_read *a, + struct cpio *cpio, struct archive_entry *entry); + +int +archive_read_support_format_cpio(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct cpio *cpio; + int r; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_format_cpio"); + + cpio = (struct cpio *)calloc(1, sizeof(*cpio)); + if (cpio == NULL) { + archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data"); + return (ARCHIVE_FATAL); + } + cpio->magic = CPIO_MAGIC; + + r = __archive_read_register_format(a, + cpio, + "cpio", + archive_read_format_cpio_bid, + archive_read_format_cpio_options, + archive_read_format_cpio_read_header, + archive_read_format_cpio_read_data, + archive_read_format_cpio_skip, + NULL, + archive_read_format_cpio_cleanup, + NULL, + NULL); + + if (r != ARCHIVE_OK) + free(cpio); + return (ARCHIVE_OK); +} + + +static int +archive_read_format_cpio_bid(struct archive_read *a, int best_bid) +{ + const unsigned char *p; + struct cpio *cpio; + int bid; + + (void)best_bid; /* UNUSED */ + + cpio = (struct cpio *)(a->format->data); + + if ((p = __archive_read_ahead(a, 6, NULL)) == NULL) + return (-1); + + bid = 0; + if (memcmp(p, "070707", 6) == 0) { + /* ASCII cpio archive (odc, POSIX.1) */ + cpio->read_header = header_odc; + bid += 48; + /* + * XXX TODO: More verification; Could check that only octal + * digits appear in appropriate header locations. XXX + */ + } else if (memcmp(p, "070727", 6) == 0) { + /* afio large ASCII cpio archive */ + cpio->read_header = header_odc; + bid += 48; + /* + * XXX TODO: More verification; Could check that almost hex + * digits appear in appropriate header locations. XXX + */ + } else if (memcmp(p, "070701", 6) == 0) { + /* ASCII cpio archive (SVR4 without CRC) */ + cpio->read_header = header_newc; + bid += 48; + /* + * XXX TODO: More verification; Could check that only hex + * digits appear in appropriate header locations. XXX + */ + } else if (memcmp(p, "070702", 6) == 0) { + /* ASCII cpio archive (SVR4 with CRC) */ + /* XXX TODO: Flag that we should check the CRC. XXX */ + cpio->read_header = header_newc; + bid += 48; + /* + * XXX TODO: More verification; Could check that only hex + * digits appear in appropriate header locations. XXX + */ + } else if (p[0] * 256 + p[1] == 070707) { + /* big-endian binary cpio archives */ + cpio->read_header = header_bin_be; + bid += 16; + /* Is more verification possible here? */ + } else if (p[0] + p[1] * 256 == 070707) { + /* little-endian binary cpio archives */ + cpio->read_header = header_bin_le; + bid += 16; + /* Is more verification possible here? */ + } else + return (ARCHIVE_WARN); + + return (bid); +} + +static int +archive_read_format_cpio_options(struct archive_read *a, + const char *key, const char *val) +{ + struct cpio *cpio; + int ret = ARCHIVE_FAILED; + + cpio = (struct cpio *)(a->format->data); + if (strcmp(key, "compat-2x") == 0) { + /* Handle filenames as libarchive 2.x */ + cpio->init_default_conversion = (val != NULL)?1:0; + return (ARCHIVE_OK); + } else if (strcmp(key, "hdrcharset") == 0) { + if (val == NULL || val[0] == 0) + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "cpio: hdrcharset option needs a character-set name"); + else { + cpio->opt_sconv = + archive_string_conversion_from_charset( + &a->archive, val, 0); + if (cpio->opt_sconv != NULL) + ret = ARCHIVE_OK; + else + ret = ARCHIVE_FATAL; + } + return (ret); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +static int +archive_read_format_cpio_read_header(struct archive_read *a, + struct archive_entry *entry) +{ + struct cpio *cpio; + const void *h, *hl; + struct archive_string_conv *sconv; + size_t namelength; + size_t name_pad; + int r; + + cpio = (struct cpio *)(a->format->data); + sconv = cpio->opt_sconv; + if (sconv == NULL) { + if (!cpio->init_default_conversion) { + cpio->sconv_default = + archive_string_default_conversion_for_read( + &(a->archive)); + cpio->init_default_conversion = 1; + } + sconv = cpio->sconv_default; + } + + r = (cpio->read_header(a, cpio, entry, &namelength, &name_pad)); + + if (r < ARCHIVE_WARN) + return (r); + + /* Read name from buffer. */ + h = __archive_read_ahead(a, namelength + name_pad, NULL); + if (h == NULL) + return (ARCHIVE_FATAL); + if (archive_entry_copy_pathname_l(entry, + (const char *)h, namelength, sconv) != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Pathname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Pathname can't be converted from %s to current locale.", + archive_string_conversion_charset_name(sconv)); + r = ARCHIVE_WARN; + } + cpio->entry_offset = 0; + + __archive_read_consume(a, namelength + name_pad); + + /* If this is a symlink, read the link contents. */ + if (archive_entry_filetype(entry) == AE_IFLNK) { + if (cpio->entry_bytes_remaining > 1024 * 1024) { + archive_set_error(&a->archive, ENOMEM, + "Rejecting malformed cpio archive: symlink contents exceed 1 megabyte"); + return (ARCHIVE_FATAL); + } + hl = __archive_read_ahead(a, + (size_t)cpio->entry_bytes_remaining, NULL); + if (hl == NULL) + return (ARCHIVE_FATAL); + if (archive_entry_copy_symlink_l(entry, (const char *)hl, + (size_t)cpio->entry_bytes_remaining, sconv) != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Linkname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Linkname can't be converted from %s to " + "current locale.", + archive_string_conversion_charset_name(sconv)); + r = ARCHIVE_WARN; + } + __archive_read_consume(a, cpio->entry_bytes_remaining); + cpio->entry_bytes_remaining = 0; + } + + /* XXX TODO: If the full mode is 0160200, then this is a Solaris + * ACL description for the following entry. Read this body + * and parse it as a Solaris-style ACL, then read the next + * header. XXX */ + + /* Compare name to "TRAILER!!!" to test for end-of-archive. */ + if (namelength == 11 && strncmp((const char *)h, "TRAILER!!!", + 11) == 0) { + /* TODO: Store file location of start of block. */ + archive_clear_error(&a->archive); + return (ARCHIVE_EOF); + } + + /* Detect and record hardlinks to previously-extracted entries. */ + if (record_hardlink(a, cpio, entry) != ARCHIVE_OK) { + return (ARCHIVE_FATAL); + } + + return (r); +} + +static int +archive_read_format_cpio_read_data(struct archive_read *a, + const void **buff, size_t *size, int64_t *offset) +{ + ssize_t bytes_read; + struct cpio *cpio; + + cpio = (struct cpio *)(a->format->data); + + if (cpio->entry_bytes_unconsumed) { + __archive_read_consume(a, cpio->entry_bytes_unconsumed); + cpio->entry_bytes_unconsumed = 0; + } + + if (cpio->entry_bytes_remaining > 0) { + *buff = __archive_read_ahead(a, 1, &bytes_read); + if (bytes_read <= 0) + return (ARCHIVE_FATAL); + if (bytes_read > cpio->entry_bytes_remaining) + bytes_read = (ssize_t)cpio->entry_bytes_remaining; + *size = bytes_read; + cpio->entry_bytes_unconsumed = bytes_read; + *offset = cpio->entry_offset; + cpio->entry_offset += bytes_read; + cpio->entry_bytes_remaining -= bytes_read; + return (ARCHIVE_OK); + } else { + if (cpio->entry_padding != + __archive_read_consume(a, cpio->entry_padding)) { + return (ARCHIVE_FATAL); + } + cpio->entry_padding = 0; + *buff = NULL; + *size = 0; + *offset = cpio->entry_offset; + return (ARCHIVE_EOF); + } +} + +static int +archive_read_format_cpio_skip(struct archive_read *a) +{ + struct cpio *cpio = (struct cpio *)(a->format->data); + int64_t to_skip = cpio->entry_bytes_remaining + cpio->entry_padding + + cpio->entry_bytes_unconsumed; + + if (to_skip != __archive_read_consume(a, to_skip)) { + return (ARCHIVE_FATAL); + } + cpio->entry_bytes_remaining = 0; + cpio->entry_padding = 0; + cpio->entry_bytes_unconsumed = 0; + return (ARCHIVE_OK); +} + +/* + * Skip forward to the next cpio newc header by searching for the + * 07070[12] string. This should be generalized and merged with + * find_odc_header below. + */ +static int +is_hex(const char *p, size_t len) +{ + while (len-- > 0) { + if ((*p >= '0' && *p <= '9') + || (*p >= 'a' && *p <= 'f') + || (*p >= 'A' && *p <= 'F')) + ++p; + else + return (0); + } + return (1); +} + +static int +find_newc_header(struct archive_read *a) +{ + const void *h; + const char *p, *q; + size_t skip, skipped = 0; + ssize_t bytes; + + for (;;) { + h = __archive_read_ahead(a, newc_header_size, &bytes); + if (h == NULL) + return (ARCHIVE_FATAL); + p = h; + q = p + bytes; + + /* Try the typical case first, then go into the slow search.*/ + if (memcmp("07070", p, 5) == 0 + && (p[5] == '1' || p[5] == '2') + && is_hex(p, newc_header_size)) + return (ARCHIVE_OK); + + /* + * Scan ahead until we find something that looks + * like a newc header. + */ + while (p + newc_header_size <= q) { + switch (p[5]) { + case '1': + case '2': + if (memcmp("07070", p, 5) == 0 + && is_hex(p, newc_header_size)) { + skip = p - (const char *)h; + __archive_read_consume(a, skip); + skipped += skip; + if (skipped > 0) { + archive_set_error(&a->archive, + 0, + "Skipped %d bytes before " + "finding valid header", + (int)skipped); + return (ARCHIVE_WARN); + } + return (ARCHIVE_OK); + } + p += 2; + break; + case '0': + p++; + break; + default: + p += 6; + break; + } + } + skip = p - (const char *)h; + __archive_read_consume(a, skip); + skipped += skip; + } +} + +static int +header_newc(struct archive_read *a, struct cpio *cpio, + struct archive_entry *entry, size_t *namelength, size_t *name_pad) +{ + const void *h; + const char *header; + int r; + + r = find_newc_header(a); + if (r < ARCHIVE_WARN) + return (r); + + /* Read fixed-size portion of header. */ + h = __archive_read_ahead(a, newc_header_size, NULL); + if (h == NULL) + return (ARCHIVE_FATAL); + + /* Parse out hex fields. */ + header = (const char *)h; + + if (memcmp(header + newc_magic_offset, "070701", 6) == 0) { + a->archive.archive_format = ARCHIVE_FORMAT_CPIO_SVR4_NOCRC; + a->archive.archive_format_name = "ASCII cpio (SVR4 with no CRC)"; + } else if (memcmp(header + newc_magic_offset, "070702", 6) == 0) { + a->archive.archive_format = ARCHIVE_FORMAT_CPIO_SVR4_CRC; + a->archive.archive_format_name = "ASCII cpio (SVR4 with CRC)"; + } else { + /* TODO: Abort here? */ + } + + archive_entry_set_devmajor(entry, + (dev_t)atol16(header + newc_devmajor_offset, newc_devmajor_size)); + archive_entry_set_devminor(entry, + (dev_t)atol16(header + newc_devminor_offset, newc_devminor_size)); + archive_entry_set_ino(entry, atol16(header + newc_ino_offset, newc_ino_size)); + archive_entry_set_mode(entry, + (mode_t)atol16(header + newc_mode_offset, newc_mode_size)); + archive_entry_set_uid(entry, atol16(header + newc_uid_offset, newc_uid_size)); + archive_entry_set_gid(entry, atol16(header + newc_gid_offset, newc_gid_size)); + archive_entry_set_nlink(entry, + (unsigned int)atol16(header + newc_nlink_offset, newc_nlink_size)); + archive_entry_set_rdevmajor(entry, + (dev_t)atol16(header + newc_rdevmajor_offset, newc_rdevmajor_size)); + archive_entry_set_rdevminor(entry, + (dev_t)atol16(header + newc_rdevminor_offset, newc_rdevminor_size)); + archive_entry_set_mtime(entry, atol16(header + newc_mtime_offset, newc_mtime_size), 0); + *namelength = (size_t)atol16(header + newc_namesize_offset, newc_namesize_size); + /* Pad name to 2 more than a multiple of 4. */ + *name_pad = (2 - *namelength) & 3; + + /* Make sure that the padded name length fits into size_t. */ + if (*name_pad > SIZE_MAX - *namelength) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "cpio archive has invalid namelength"); + return (ARCHIVE_FATAL); + } + + /* + * Note: entry_bytes_remaining is at least 64 bits and + * therefore guaranteed to be big enough for a 33-bit file + * size. + */ + cpio->entry_bytes_remaining = + atol16(header + newc_filesize_offset, newc_filesize_size); + archive_entry_set_size(entry, cpio->entry_bytes_remaining); + /* Pad file contents to a multiple of 4. */ + cpio->entry_padding = 3 & -cpio->entry_bytes_remaining; + __archive_read_consume(a, newc_header_size); + return (r); +} + +/* + * Skip forward to the next cpio odc header by searching for the + * 070707 string. This is a hand-optimized search that could + * probably be easily generalized to handle all character-based + * cpio variants. + */ +static int +is_octal(const char *p, size_t len) +{ + while (len-- > 0) { + if (*p < '0' || *p > '7') + return (0); + ++p; + } + return (1); +} + +static int +is_afio_large(const char *h, size_t len) +{ + if (len < afiol_header_size) + return (0); + if (h[afiol_ino_m_offset] != 'm' + || h[afiol_mtime_n_offset] != 'n' + || h[afiol_xsize_s_offset] != 's' + || h[afiol_filesize_c_offset] != ':') + return (0); + if (!is_hex(h + afiol_dev_offset, afiol_ino_m_offset - afiol_dev_offset)) + return (0); + if (!is_hex(h + afiol_mode_offset, afiol_mtime_n_offset - afiol_mode_offset)) + return (0); + if (!is_hex(h + afiol_namesize_offset, afiol_xsize_s_offset - afiol_namesize_offset)) + return (0); + if (!is_hex(h + afiol_filesize_offset, afiol_filesize_size)) + return (0); + return (1); +} + +static int +find_odc_header(struct archive_read *a) +{ + const void *h; + const char *p, *q; + size_t skip, skipped = 0; + ssize_t bytes; + + for (;;) { + h = __archive_read_ahead(a, odc_header_size, &bytes); + if (h == NULL) + return (ARCHIVE_FATAL); + p = h; + q = p + bytes; + + /* Try the typical case first, then go into the slow search.*/ + if (memcmp("070707", p, 6) == 0 && is_octal(p, odc_header_size)) + return (ARCHIVE_OK); + if (memcmp("070727", p, 6) == 0 && is_afio_large(p, bytes)) { + a->archive.archive_format = ARCHIVE_FORMAT_CPIO_AFIO_LARGE; + return (ARCHIVE_OK); + } + + /* + * Scan ahead until we find something that looks + * like an odc header. + */ + while (p + odc_header_size <= q) { + switch (p[5]) { + case '7': + if ((memcmp("070707", p, 6) == 0 + && is_octal(p, odc_header_size)) + || (memcmp("070727", p, 6) == 0 + && is_afio_large(p, q - p))) { + skip = p - (const char *)h; + __archive_read_consume(a, skip); + skipped += skip; + if (p[4] == '2') + a->archive.archive_format = + ARCHIVE_FORMAT_CPIO_AFIO_LARGE; + if (skipped > 0) { + archive_set_error(&a->archive, + 0, + "Skipped %d bytes before " + "finding valid header", + (int)skipped); + return (ARCHIVE_WARN); + } + return (ARCHIVE_OK); + } + p += 2; + break; + case '0': + p++; + break; + default: + p += 6; + break; + } + } + skip = p - (const char *)h; + __archive_read_consume(a, skip); + skipped += skip; + } +} + +static int +header_odc(struct archive_read *a, struct cpio *cpio, + struct archive_entry *entry, size_t *namelength, size_t *name_pad) +{ + const void *h; + int r; + const char *header; + + a->archive.archive_format = ARCHIVE_FORMAT_CPIO_POSIX; + a->archive.archive_format_name = "POSIX octet-oriented cpio"; + + /* Find the start of the next header. */ + r = find_odc_header(a); + if (r < ARCHIVE_WARN) + return (r); + + if (a->archive.archive_format == ARCHIVE_FORMAT_CPIO_AFIO_LARGE) { + int r2 = (header_afiol(a, cpio, entry, namelength, name_pad)); + if (r2 == ARCHIVE_OK) + return (r); + else + return (r2); + } + + /* Read fixed-size portion of header. */ + h = __archive_read_ahead(a, odc_header_size, NULL); + if (h == NULL) + return (ARCHIVE_FATAL); + + /* Parse out octal fields. */ + header = (const char *)h; + + archive_entry_set_dev(entry, + (dev_t)atol8(header + odc_dev_offset, odc_dev_size)); + archive_entry_set_ino(entry, atol8(header + odc_ino_offset, odc_ino_size)); + archive_entry_set_mode(entry, + (mode_t)atol8(header + odc_mode_offset, odc_mode_size)); + archive_entry_set_uid(entry, atol8(header + odc_uid_offset, odc_uid_size)); + archive_entry_set_gid(entry, atol8(header + odc_gid_offset, odc_gid_size)); + archive_entry_set_nlink(entry, + (unsigned int)atol8(header + odc_nlink_offset, odc_nlink_size)); + archive_entry_set_rdev(entry, + (dev_t)atol8(header + odc_rdev_offset, odc_rdev_size)); + archive_entry_set_mtime(entry, atol8(header + odc_mtime_offset, odc_mtime_size), 0); + *namelength = (size_t)atol8(header + odc_namesize_offset, odc_namesize_size); + *name_pad = 0; /* No padding of filename. */ + + /* + * Note: entry_bytes_remaining is at least 64 bits and + * therefore guaranteed to be big enough for a 33-bit file + * size. + */ + cpio->entry_bytes_remaining = + atol8(header + odc_filesize_offset, odc_filesize_size); + archive_entry_set_size(entry, cpio->entry_bytes_remaining); + cpio->entry_padding = 0; + __archive_read_consume(a, odc_header_size); + return (r); +} + +/* + * NOTE: if a filename suffix is ".z", it is the file gziped by afio. + * it would be nice that we can show uncompressed file size and we can + * uncompressed file contents automatically, unfortunately we have nothing + * to get a uncompressed file size while reading each header. It means + * we also cannot uncompress file contents under our framework. + */ +static int +header_afiol(struct archive_read *a, struct cpio *cpio, + struct archive_entry *entry, size_t *namelength, size_t *name_pad) +{ + const void *h; + const char *header; + + a->archive.archive_format = ARCHIVE_FORMAT_CPIO_AFIO_LARGE; + a->archive.archive_format_name = "afio large ASCII"; + + /* Read fixed-size portion of header. */ + h = __archive_read_ahead(a, afiol_header_size, NULL); + if (h == NULL) + return (ARCHIVE_FATAL); + + /* Parse out octal fields. */ + header = (const char *)h; + + archive_entry_set_dev(entry, + (dev_t)atol16(header + afiol_dev_offset, afiol_dev_size)); + archive_entry_set_ino(entry, atol16(header + afiol_ino_offset, afiol_ino_size)); + archive_entry_set_mode(entry, + (mode_t)atol8(header + afiol_mode_offset, afiol_mode_size)); + archive_entry_set_uid(entry, atol16(header + afiol_uid_offset, afiol_uid_size)); + archive_entry_set_gid(entry, atol16(header + afiol_gid_offset, afiol_gid_size)); + archive_entry_set_nlink(entry, + (unsigned int)atol16(header + afiol_nlink_offset, afiol_nlink_size)); + archive_entry_set_rdev(entry, + (dev_t)atol16(header + afiol_rdev_offset, afiol_rdev_size)); + archive_entry_set_mtime(entry, atol16(header + afiol_mtime_offset, afiol_mtime_size), 0); + *namelength = (size_t)atol16(header + afiol_namesize_offset, afiol_namesize_size); + *name_pad = 0; /* No padding of filename. */ + + cpio->entry_bytes_remaining = + atol16(header + afiol_filesize_offset, afiol_filesize_size); + archive_entry_set_size(entry, cpio->entry_bytes_remaining); + cpio->entry_padding = 0; + __archive_read_consume(a, afiol_header_size); + return (ARCHIVE_OK); +} + + +static int +header_bin_le(struct archive_read *a, struct cpio *cpio, + struct archive_entry *entry, size_t *namelength, size_t *name_pad) +{ + const void *h; + const unsigned char *header; + + a->archive.archive_format = ARCHIVE_FORMAT_CPIO_BIN_LE; + a->archive.archive_format_name = "cpio (little-endian binary)"; + + /* Read fixed-size portion of header. */ + h = __archive_read_ahead(a, bin_header_size, NULL); + if (h == NULL) { + archive_set_error(&a->archive, 0, + "End of file trying to read next cpio header"); + return (ARCHIVE_FATAL); + } + + /* Parse out binary fields. */ + header = (const unsigned char *)h; + + archive_entry_set_dev(entry, header[bin_dev_offset] + header[bin_dev_offset + 1] * 256); + archive_entry_set_ino(entry, header[bin_ino_offset] + header[bin_ino_offset + 1] * 256); + archive_entry_set_mode(entry, header[bin_mode_offset] + header[bin_mode_offset + 1] * 256); + archive_entry_set_uid(entry, header[bin_uid_offset] + header[bin_uid_offset + 1] * 256); + archive_entry_set_gid(entry, header[bin_gid_offset] + header[bin_gid_offset + 1] * 256); + archive_entry_set_nlink(entry, header[bin_nlink_offset] + header[bin_nlink_offset + 1] * 256); + archive_entry_set_rdev(entry, header[bin_rdev_offset] + header[bin_rdev_offset + 1] * 256); + archive_entry_set_mtime(entry, le4(header + bin_mtime_offset), 0); + *namelength = header[bin_namesize_offset] + header[bin_namesize_offset + 1] * 256; + *name_pad = *namelength & 1; /* Pad to even. */ + + cpio->entry_bytes_remaining = le4(header + bin_filesize_offset); + archive_entry_set_size(entry, cpio->entry_bytes_remaining); + cpio->entry_padding = cpio->entry_bytes_remaining & 1; /* Pad to even. */ + __archive_read_consume(a, bin_header_size); + return (ARCHIVE_OK); +} + +static int +header_bin_be(struct archive_read *a, struct cpio *cpio, + struct archive_entry *entry, size_t *namelength, size_t *name_pad) +{ + const void *h; + const unsigned char *header; + + a->archive.archive_format = ARCHIVE_FORMAT_CPIO_BIN_BE; + a->archive.archive_format_name = "cpio (big-endian binary)"; + + /* Read fixed-size portion of header. */ + h = __archive_read_ahead(a, bin_header_size, NULL); + if (h == NULL) { + archive_set_error(&a->archive, 0, + "End of file trying to read next cpio header"); + return (ARCHIVE_FATAL); + } + + /* Parse out binary fields. */ + header = (const unsigned char *)h; + + archive_entry_set_dev(entry, header[bin_dev_offset] * 256 + header[bin_dev_offset + 1]); + archive_entry_set_ino(entry, header[bin_ino_offset] * 256 + header[bin_ino_offset + 1]); + archive_entry_set_mode(entry, header[bin_mode_offset] * 256 + header[bin_mode_offset + 1]); + archive_entry_set_uid(entry, header[bin_uid_offset] * 256 + header[bin_uid_offset + 1]); + archive_entry_set_gid(entry, header[bin_gid_offset] * 256 + header[bin_gid_offset + 1]); + archive_entry_set_nlink(entry, header[bin_nlink_offset] * 256 + header[bin_nlink_offset + 1]); + archive_entry_set_rdev(entry, header[bin_rdev_offset] * 256 + header[bin_rdev_offset + 1]); + archive_entry_set_mtime(entry, be4(header + bin_mtime_offset), 0); + *namelength = header[bin_namesize_offset] * 256 + header[bin_namesize_offset + 1]; + *name_pad = *namelength & 1; /* Pad to even. */ + + cpio->entry_bytes_remaining = be4(header + bin_filesize_offset); + archive_entry_set_size(entry, cpio->entry_bytes_remaining); + cpio->entry_padding = cpio->entry_bytes_remaining & 1; /* Pad to even. */ + __archive_read_consume(a, bin_header_size); + return (ARCHIVE_OK); +} + +static int +archive_read_format_cpio_cleanup(struct archive_read *a) +{ + struct cpio *cpio; + + cpio = (struct cpio *)(a->format->data); + /* Free inode->name map */ + while (cpio->links_head != NULL) { + struct links_entry *lp = cpio->links_head->next; + + free(cpio->links_head->name); + free(cpio->links_head); + cpio->links_head = lp; + } + free(cpio); + (a->format->data) = NULL; + return (ARCHIVE_OK); +} + +static int64_t +le4(const unsigned char *p) +{ + return ((p[0] << 16) + (((int64_t)p[1]) << 24) + (p[2] << 0) + (p[3] << 8)); +} + + +static int64_t +be4(const unsigned char *p) +{ + return ((((int64_t)p[0]) << 24) + (p[1] << 16) + (p[2] << 8) + (p[3])); +} + +/* + * Note that this implementation does not (and should not!) obey + * locale settings; you cannot simply substitute strtol here, since + * it does obey locale. + */ +static int64_t +atol8(const char *p, unsigned char_cnt) +{ + int64_t l; + int digit; + + l = 0; + while (char_cnt-- > 0) { + if (*p >= '0' && *p <= '7') + digit = *p - '0'; + else + return (l); + p++; + l <<= 3; + l |= digit; + } + return (l); +} + +static int64_t +atol16(const char *p, unsigned char_cnt) +{ + int64_t l; + int digit; + + l = 0; + while (char_cnt-- > 0) { + if (*p >= 'a' && *p <= 'f') + digit = *p - 'a' + 10; + else if (*p >= 'A' && *p <= 'F') + digit = *p - 'A' + 10; + else if (*p >= '0' && *p <= '9') + digit = *p - '0'; + else + return (l); + p++; + l <<= 4; + l |= digit; + } + return (l); +} + +static int +record_hardlink(struct archive_read *a, + struct cpio *cpio, struct archive_entry *entry) +{ + struct links_entry *le; + dev_t dev; + int64_t ino; + + if (archive_entry_nlink(entry) <= 1) + return (ARCHIVE_OK); + + dev = archive_entry_dev(entry); + ino = archive_entry_ino64(entry); + + /* + * First look in the list of multiply-linked files. If we've + * already dumped it, convert this entry to a hard link entry. + */ + for (le = cpio->links_head; le; le = le->next) { + if (le->dev == dev && le->ino == ino) { + archive_entry_copy_hardlink(entry, le->name); + + if (--le->links <= 0) { + if (le->previous != NULL) + le->previous->next = le->next; + if (le->next != NULL) + le->next->previous = le->previous; + if (cpio->links_head == le) + cpio->links_head = le->next; + free(le->name); + free(le); + } + + return (ARCHIVE_OK); + } + } + + le = (struct links_entry *)malloc(sizeof(struct links_entry)); + if (le == NULL) { + archive_set_error(&a->archive, + ENOMEM, "Out of memory adding file to list"); + return (ARCHIVE_FATAL); + } + if (cpio->links_head != NULL) + cpio->links_head->previous = le; + le->next = cpio->links_head; + le->previous = NULL; + cpio->links_head = le; + le->dev = dev; + le->ino = ino; + le->links = archive_entry_nlink(entry) - 1; + le->name = strdup(archive_entry_pathname(entry)); + if (le->name == NULL) { + archive_set_error(&a->archive, + ENOMEM, "Out of memory adding file to list"); + return (ARCHIVE_FATAL); + } + + return (ARCHIVE_OK); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_empty.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_empty.c new file mode 100644 index 0000000..c641eb9 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_empty.c @@ -0,0 +1,96 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_empty.c 191524 2009-04-26 18:24:14Z kientzle $"); + +#include "archive.h" +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_read_private.h" + +static int archive_read_format_empty_bid(struct archive_read *, int); +static int archive_read_format_empty_read_data(struct archive_read *, + const void **, size_t *, int64_t *); +static int archive_read_format_empty_read_header(struct archive_read *, + struct archive_entry *); +int +archive_read_support_format_empty(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + int r; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_format_empty"); + + r = __archive_read_register_format(a, + NULL, + NULL, + archive_read_format_empty_bid, + NULL, + archive_read_format_empty_read_header, + archive_read_format_empty_read_data, + NULL, + NULL, + NULL, + NULL, + NULL); + + return (r); +} + + +static int +archive_read_format_empty_bid(struct archive_read *a, int best_bid) +{ + if (best_bid < 1 && __archive_read_ahead(a, 1, NULL) == NULL) + return (1); + return (-1); +} + +static int +archive_read_format_empty_read_header(struct archive_read *a, + struct archive_entry *entry) +{ + (void)a; /* UNUSED */ + (void)entry; /* UNUSED */ + + a->archive.archive_format = ARCHIVE_FORMAT_EMPTY; + a->archive.archive_format_name = "Empty file"; + + return (ARCHIVE_EOF); +} + +static int +archive_read_format_empty_read_data(struct archive_read *a, + const void **buff, size_t *size, int64_t *offset) +{ + (void)a; /* UNUSED */ + (void)buff; /* UNUSED */ + (void)size; /* UNUSED */ + (void)offset; /* UNUSED */ + + return (ARCHIVE_EOF); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_iso9660.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_iso9660.c new file mode 100644 index 0000000..db14d41 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_iso9660.c @@ -0,0 +1,3278 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2009 Andreas Henriksson + * Copyright (c) 2009-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_iso9660.c 201246 2009-12-30 05:30:35Z kientzle $"); + +#ifdef HAVE_ERRNO_H +#include +#endif +/* #include */ /* See archive_platform.h */ +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#include +#ifdef HAVE_ZLIB_H +#include +#endif + +#include "archive.h" +#include "archive_endian.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_private.h" +#include "archive_read_private.h" +#include "archive_string.h" + +/* + * An overview of ISO 9660 format: + * + * Each disk is laid out as follows: + * * 32k reserved for private use + * * Volume descriptor table. Each volume descriptor + * is 2k and specifies basic format information. + * The "Primary Volume Descriptor" (PVD) is defined by the + * standard and should always be present; other volume + * descriptors include various vendor-specific extensions. + * * Files and directories. Each file/dir is specified by + * an "extent" (starting sector and length in bytes). + * Dirs are just files with directory records packed one + * after another. The PVD contains a single dir entry + * specifying the location of the root directory. Everything + * else follows from there. + * + * This module works by first reading the volume descriptors, then + * building a list of directory entries, sorted by starting + * sector. At each step, I look for the earliest dir entry that + * hasn't yet been read, seek forward to that location and read + * that entry. If it's a dir, I slurp in the new dir entries and + * add them to the heap; if it's a regular file, I return the + * corresponding archive_entry and wait for the client to request + * the file body. This strategy allows us to read most compliant + * CDs with a single pass through the data, as required by libarchive. + */ +#define LOGICAL_BLOCK_SIZE 2048 +#define SYSTEM_AREA_BLOCK 16 + +/* Structure of on-disk primary volume descriptor. */ +#define PVD_type_offset 0 +#define PVD_type_size 1 +#define PVD_id_offset (PVD_type_offset + PVD_type_size) +#define PVD_id_size 5 +#define PVD_version_offset (PVD_id_offset + PVD_id_size) +#define PVD_version_size 1 +#define PVD_reserved1_offset (PVD_version_offset + PVD_version_size) +#define PVD_reserved1_size 1 +#define PVD_system_id_offset (PVD_reserved1_offset + PVD_reserved1_size) +#define PVD_system_id_size 32 +#define PVD_volume_id_offset (PVD_system_id_offset + PVD_system_id_size) +#define PVD_volume_id_size 32 +#define PVD_reserved2_offset (PVD_volume_id_offset + PVD_volume_id_size) +#define PVD_reserved2_size 8 +#define PVD_volume_space_size_offset (PVD_reserved2_offset + PVD_reserved2_size) +#define PVD_volume_space_size_size 8 +#define PVD_reserved3_offset (PVD_volume_space_size_offset + PVD_volume_space_size_size) +#define PVD_reserved3_size 32 +#define PVD_volume_set_size_offset (PVD_reserved3_offset + PVD_reserved3_size) +#define PVD_volume_set_size_size 4 +#define PVD_volume_sequence_number_offset (PVD_volume_set_size_offset + PVD_volume_set_size_size) +#define PVD_volume_sequence_number_size 4 +#define PVD_logical_block_size_offset (PVD_volume_sequence_number_offset + PVD_volume_sequence_number_size) +#define PVD_logical_block_size_size 4 +#define PVD_path_table_size_offset (PVD_logical_block_size_offset + PVD_logical_block_size_size) +#define PVD_path_table_size_size 8 +#define PVD_type_1_path_table_offset (PVD_path_table_size_offset + PVD_path_table_size_size) +#define PVD_type_1_path_table_size 4 +#define PVD_opt_type_1_path_table_offset (PVD_type_1_path_table_offset + PVD_type_1_path_table_size) +#define PVD_opt_type_1_path_table_size 4 +#define PVD_type_m_path_table_offset (PVD_opt_type_1_path_table_offset + PVD_opt_type_1_path_table_size) +#define PVD_type_m_path_table_size 4 +#define PVD_opt_type_m_path_table_offset (PVD_type_m_path_table_offset + PVD_type_m_path_table_size) +#define PVD_opt_type_m_path_table_size 4 +#define PVD_root_directory_record_offset (PVD_opt_type_m_path_table_offset + PVD_opt_type_m_path_table_size) +#define PVD_root_directory_record_size 34 +#define PVD_volume_set_id_offset (PVD_root_directory_record_offset + PVD_root_directory_record_size) +#define PVD_volume_set_id_size 128 +#define PVD_publisher_id_offset (PVD_volume_set_id_offset + PVD_volume_set_id_size) +#define PVD_publisher_id_size 128 +#define PVD_preparer_id_offset (PVD_publisher_id_offset + PVD_publisher_id_size) +#define PVD_preparer_id_size 128 +#define PVD_application_id_offset (PVD_preparer_id_offset + PVD_preparer_id_size) +#define PVD_application_id_size 128 +#define PVD_copyright_file_id_offset (PVD_application_id_offset + PVD_application_id_size) +#define PVD_copyright_file_id_size 37 +#define PVD_abstract_file_id_offset (PVD_copyright_file_id_offset + PVD_copyright_file_id_size) +#define PVD_abstract_file_id_size 37 +#define PVD_bibliographic_file_id_offset (PVD_abstract_file_id_offset + PVD_abstract_file_id_size) +#define PVD_bibliographic_file_id_size 37 +#define PVD_creation_date_offset (PVD_bibliographic_file_id_offset + PVD_bibliographic_file_id_size) +#define PVD_creation_date_size 17 +#define PVD_modification_date_offset (PVD_creation_date_offset + PVD_creation_date_size) +#define PVD_modification_date_size 17 +#define PVD_expiration_date_offset (PVD_modification_date_offset + PVD_modification_date_size) +#define PVD_expiration_date_size 17 +#define PVD_effective_date_offset (PVD_expiration_date_offset + PVD_expiration_date_size) +#define PVD_effective_date_size 17 +#define PVD_file_structure_version_offset (PVD_effective_date_offset + PVD_effective_date_size) +#define PVD_file_structure_version_size 1 +#define PVD_reserved4_offset (PVD_file_structure_version_offset + PVD_file_structure_version_size) +#define PVD_reserved4_size 1 +#define PVD_application_data_offset (PVD_reserved4_offset + PVD_reserved4_size) +#define PVD_application_data_size 512 +#define PVD_reserved5_offset (PVD_application_data_offset + PVD_application_data_size) +#define PVD_reserved5_size (2048 - PVD_reserved5_offset) + +/* TODO: It would make future maintenance easier to just hardcode the + * above values. In particular, ECMA119 states the offsets as part of + * the standard. That would eliminate the need for the following check.*/ +#if PVD_reserved5_offset != 1395 +#error PVD offset and size definitions are wrong. +#endif + + +/* Structure of optional on-disk supplementary volume descriptor. */ +#define SVD_type_offset 0 +#define SVD_type_size 1 +#define SVD_id_offset (SVD_type_offset + SVD_type_size) +#define SVD_id_size 5 +#define SVD_version_offset (SVD_id_offset + SVD_id_size) +#define SVD_version_size 1 +/* ... */ +#define SVD_reserved1_offset 72 +#define SVD_reserved1_size 8 +#define SVD_volume_space_size_offset 80 +#define SVD_volume_space_size_size 8 +#define SVD_escape_sequences_offset (SVD_volume_space_size_offset + SVD_volume_space_size_size) +#define SVD_escape_sequences_size 32 +/* ... */ +#define SVD_logical_block_size_offset 128 +#define SVD_logical_block_size_size 4 +#define SVD_type_L_path_table_offset 140 +#define SVD_type_M_path_table_offset 148 +/* ... */ +#define SVD_root_directory_record_offset 156 +#define SVD_root_directory_record_size 34 +#define SVD_file_structure_version_offset 881 +#define SVD_reserved2_offset 882 +#define SVD_reserved2_size 1 +#define SVD_reserved3_offset 1395 +#define SVD_reserved3_size 653 +/* ... */ +/* FIXME: validate correctness of last SVD entry offset. */ + +/* Structure of an on-disk directory record. */ +/* Note: ISO9660 stores each multi-byte integer twice, once in + * each byte order. The sizes here are the size of just one + * of the two integers. (This is why the offset of a field isn't + * the same as the offset+size of the previous field.) */ +#define DR_length_offset 0 +#define DR_length_size 1 +#define DR_ext_attr_length_offset 1 +#define DR_ext_attr_length_size 1 +#define DR_extent_offset 2 +#define DR_extent_size 4 +#define DR_size_offset 10 +#define DR_size_size 4 +#define DR_date_offset 18 +#define DR_date_size 7 +#define DR_flags_offset 25 +#define DR_flags_size 1 +#define DR_file_unit_size_offset 26 +#define DR_file_unit_size_size 1 +#define DR_interleave_offset 27 +#define DR_interleave_size 1 +#define DR_volume_sequence_number_offset 28 +#define DR_volume_sequence_number_size 2 +#define DR_name_len_offset 32 +#define DR_name_len_size 1 +#define DR_name_offset 33 + +#ifdef HAVE_ZLIB_H +static const unsigned char zisofs_magic[8] = { + 0x37, 0xE4, 0x53, 0x96, 0xC9, 0xDB, 0xD6, 0x07 +}; + +struct zisofs { + /* Set 1 if this file compressed by paged zlib */ + int pz; + int pz_log2_bs; /* Log2 of block size */ + uint64_t pz_uncompressed_size; + + int initialized; + unsigned char *uncompressed_buffer; + size_t uncompressed_buffer_size; + + uint32_t pz_offset; + unsigned char header[16]; + size_t header_avail; + int header_passed; + unsigned char *block_pointers; + size_t block_pointers_alloc; + size_t block_pointers_size; + size_t block_pointers_avail; + size_t block_off; + uint32_t block_avail; + + z_stream stream; + int stream_valid; +}; +#else +struct zisofs { + /* Set 1 if this file compressed by paged zlib */ + int pz; +}; +#endif + +struct content { + uint64_t offset;/* Offset on disk. */ + uint64_t size; /* File size in bytes. */ + struct content *next; +}; + +/* In-memory storage for a directory record. */ +struct file_info { + struct file_info *use_next; + struct file_info *parent; + struct file_info *next; + struct file_info *re_next; + int subdirs; + uint64_t key; /* Heap Key. */ + uint64_t offset; /* Offset on disk. */ + uint64_t size; /* File size in bytes. */ + uint32_t ce_offset; /* Offset of CE. */ + uint32_t ce_size; /* Size of CE. */ + char rr_moved; /* Flag to rr_moved. */ + char rr_moved_has_re_only; + char re; /* Having RRIP "RE" extension. */ + char re_descendant; + uint64_t cl_offset; /* Having RRIP "CL" extension. */ + int birthtime_is_set; + time_t birthtime; /* File created time. */ + time_t mtime; /* File last modified time. */ + time_t atime; /* File last accessed time. */ + time_t ctime; /* File attribute change time. */ + uint64_t rdev; /* Device number. */ + mode_t mode; + uid_t uid; + gid_t gid; + int64_t number; + int nlinks; + struct archive_string name; /* Pathname */ + unsigned char *utf16be_name; + size_t utf16be_bytes; + char name_continues; /* Non-zero if name continues */ + struct archive_string symlink; + char symlink_continues; /* Non-zero if link continues */ + /* Set 1 if this file compressed by paged zlib(zisofs) */ + int pz; + int pz_log2_bs; /* Log2 of block size */ + uint64_t pz_uncompressed_size; + /* Set 1 if this file is multi extent. */ + int multi_extent; + struct { + struct content *first; + struct content **last; + } contents; + struct { + struct file_info *first; + struct file_info **last; + } rede_files; +}; + +struct heap_queue { + struct file_info **files; + int allocated; + int used; +}; + +struct iso9660 { + int magic; +#define ISO9660_MAGIC 0x96609660 + + int opt_support_joliet; + int opt_support_rockridge; + + struct archive_string pathname; + char seenRockridge; /* Set true if RR extensions are used. */ + char seenSUSP; /* Set true if SUSP is being used. */ + char seenJoliet; + + unsigned char suspOffset; + struct file_info *rr_moved; + struct read_ce_queue { + struct read_ce_req { + uint64_t offset;/* Offset of CE on disk. */ + struct file_info *file; + } *reqs; + int cnt; + int allocated; + } read_ce_req; + + int64_t previous_number; + struct archive_string previous_pathname; + + struct file_info *use_files; + struct heap_queue pending_files; + struct { + struct file_info *first; + struct file_info **last; + } cache_files; + struct { + struct file_info *first; + struct file_info **last; + } re_files; + + uint64_t current_position; + ssize_t logical_block_size; + uint64_t volume_size; /* Total size of volume in bytes. */ + int32_t volume_block;/* Total size of volume in logical blocks. */ + + struct vd { + int location; /* Location of Extent. */ + uint32_t size; + } primary, joliet; + + int64_t entry_sparse_offset; + int64_t entry_bytes_remaining; + size_t entry_bytes_unconsumed; + struct zisofs entry_zisofs; + struct content *entry_content; + struct archive_string_conv *sconv_utf16be; + /* + * Buffers for a full pathname in UTF-16BE in Joliet extensions. + */ +#define UTF16_NAME_MAX 1024 + unsigned char *utf16be_path; + size_t utf16be_path_len; + unsigned char *utf16be_previous_path; + size_t utf16be_previous_path_len; + /* Null buffer used in bidder to improve its performance. */ + unsigned char null[2048]; +}; + +static int archive_read_format_iso9660_bid(struct archive_read *, int); +static int archive_read_format_iso9660_options(struct archive_read *, + const char *, const char *); +static int archive_read_format_iso9660_cleanup(struct archive_read *); +static int archive_read_format_iso9660_read_data(struct archive_read *, + const void **, size_t *, int64_t *); +static int archive_read_format_iso9660_read_data_skip(struct archive_read *); +static int archive_read_format_iso9660_read_header(struct archive_read *, + struct archive_entry *); +static const char *build_pathname(struct archive_string *, struct file_info *, int); +static int build_pathname_utf16be(unsigned char *, size_t, size_t *, + struct file_info *); +#if DEBUG +static void dump_isodirrec(FILE *, const unsigned char *isodirrec); +#endif +static time_t time_from_tm(struct tm *); +static time_t isodate17(const unsigned char *); +static time_t isodate7(const unsigned char *); +static int isBootRecord(struct iso9660 *, const unsigned char *); +static int isVolumePartition(struct iso9660 *, const unsigned char *); +static int isVDSetTerminator(struct iso9660 *, const unsigned char *); +static int isJolietSVD(struct iso9660 *, const unsigned char *); +static int isSVD(struct iso9660 *, const unsigned char *); +static int isEVD(struct iso9660 *, const unsigned char *); +static int isPVD(struct iso9660 *, const unsigned char *); +static int next_cache_entry(struct archive_read *, struct iso9660 *, + struct file_info **); +static int next_entry_seek(struct archive_read *, struct iso9660 *, + struct file_info **); +static struct file_info * + parse_file_info(struct archive_read *a, + struct file_info *parent, const unsigned char *isodirrec, + size_t reclen); +static int parse_rockridge(struct archive_read *a, + struct file_info *file, const unsigned char *start, + const unsigned char *end); +static int register_CE(struct archive_read *a, int32_t location, + struct file_info *file); +static int read_CE(struct archive_read *a, struct iso9660 *iso9660); +static void parse_rockridge_NM1(struct file_info *, + const unsigned char *, int); +static void parse_rockridge_SL1(struct file_info *, + const unsigned char *, int); +static void parse_rockridge_TF1(struct file_info *, + const unsigned char *, int); +static void parse_rockridge_ZF1(struct file_info *, + const unsigned char *, int); +static void register_file(struct iso9660 *, struct file_info *); +static void release_files(struct iso9660 *); +static unsigned toi(const void *p, int n); +static inline void re_add_entry(struct iso9660 *, struct file_info *); +static inline struct file_info * re_get_entry(struct iso9660 *); +static inline int rede_add_entry(struct file_info *); +static inline struct file_info * rede_get_entry(struct file_info *); +static inline void cache_add_entry(struct iso9660 *iso9660, + struct file_info *file); +static inline struct file_info *cache_get_entry(struct iso9660 *iso9660); +static int heap_add_entry(struct archive_read *a, struct heap_queue *heap, + struct file_info *file, uint64_t key); +static struct file_info *heap_get_entry(struct heap_queue *heap); + +#define add_entry(arch, iso9660, file) \ + heap_add_entry(arch, &((iso9660)->pending_files), file, file->offset) +#define next_entry(iso9660) \ + heap_get_entry(&((iso9660)->pending_files)) + +int +archive_read_support_format_iso9660(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct iso9660 *iso9660; + int r; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_format_iso9660"); + + iso9660 = (struct iso9660 *)calloc(1, sizeof(*iso9660)); + if (iso9660 == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate iso9660 data"); + return (ARCHIVE_FATAL); + } + iso9660->magic = ISO9660_MAGIC; + iso9660->cache_files.first = NULL; + iso9660->cache_files.last = &(iso9660->cache_files.first); + iso9660->re_files.first = NULL; + iso9660->re_files.last = &(iso9660->re_files.first); + /* Enable to support Joliet extensions by default. */ + iso9660->opt_support_joliet = 1; + /* Enable to support Rock Ridge extensions by default. */ + iso9660->opt_support_rockridge = 1; + + r = __archive_read_register_format(a, + iso9660, + "iso9660", + archive_read_format_iso9660_bid, + archive_read_format_iso9660_options, + archive_read_format_iso9660_read_header, + archive_read_format_iso9660_read_data, + archive_read_format_iso9660_read_data_skip, + NULL, + archive_read_format_iso9660_cleanup, + NULL, + NULL); + + if (r != ARCHIVE_OK) { + free(iso9660); + return (r); + } + return (ARCHIVE_OK); +} + + +static int +archive_read_format_iso9660_bid(struct archive_read *a, int best_bid) +{ + struct iso9660 *iso9660; + ssize_t bytes_read; + const unsigned char *p; + int seenTerminator; + + /* If there's already a better bid than we can ever + make, don't bother testing. */ + if (best_bid > 48) + return (-1); + + iso9660 = (struct iso9660 *)(a->format->data); + + /* + * Skip the first 32k (reserved area) and get the first + * 8 sectors of the volume descriptor table. Of course, + * if the I/O layer gives us more, we'll take it. + */ +#define RESERVED_AREA (SYSTEM_AREA_BLOCK * LOGICAL_BLOCK_SIZE) + p = __archive_read_ahead(a, + RESERVED_AREA + 8 * LOGICAL_BLOCK_SIZE, + &bytes_read); + if (p == NULL) + return (-1); + + /* Skip the reserved area. */ + bytes_read -= RESERVED_AREA; + p += RESERVED_AREA; + + /* Check each volume descriptor. */ + seenTerminator = 0; + for (; bytes_read > LOGICAL_BLOCK_SIZE; + bytes_read -= LOGICAL_BLOCK_SIZE, p += LOGICAL_BLOCK_SIZE) { + /* Do not handle undefined Volume Descriptor Type. */ + if (p[0] >= 4 && p[0] <= 254) + return (0); + /* Standard Identifier must be "CD001" */ + if (memcmp(p + 1, "CD001", 5) != 0) + return (0); + if (isPVD(iso9660, p)) + continue; + if (!iso9660->joliet.location) { + if (isJolietSVD(iso9660, p)) + continue; + } + if (isBootRecord(iso9660, p)) + continue; + if (isEVD(iso9660, p)) + continue; + if (isSVD(iso9660, p)) + continue; + if (isVolumePartition(iso9660, p)) + continue; + if (isVDSetTerminator(iso9660, p)) { + seenTerminator = 1; + break; + } + return (0); + } + /* + * ISO 9660 format must have Primary Volume Descriptor and + * Volume Descriptor Set Terminator. + */ + if (seenTerminator && iso9660->primary.location > 16) + return (48); + + /* We didn't find a valid PVD; return a bid of zero. */ + return (0); +} + +static int +archive_read_format_iso9660_options(struct archive_read *a, + const char *key, const char *val) +{ + struct iso9660 *iso9660; + + iso9660 = (struct iso9660 *)(a->format->data); + + if (strcmp(key, "joliet") == 0) { + if (val == NULL || strcmp(val, "off") == 0 || + strcmp(val, "ignore") == 0 || + strcmp(val, "disable") == 0 || + strcmp(val, "0") == 0) + iso9660->opt_support_joliet = 0; + else + iso9660->opt_support_joliet = 1; + return (ARCHIVE_OK); + } + if (strcmp(key, "rockridge") == 0 || + strcmp(key, "Rockridge") == 0) { + iso9660->opt_support_rockridge = val != NULL; + return (ARCHIVE_OK); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +static int +isNull(struct iso9660 *iso9660, const unsigned char *h, unsigned offset, +unsigned bytes) +{ + + while (bytes >= sizeof(iso9660->null)) { + if (!memcmp(iso9660->null, h + offset, sizeof(iso9660->null))) + return (0); + offset += sizeof(iso9660->null); + bytes -= sizeof(iso9660->null); + } + if (bytes) + return memcmp(iso9660->null, h + offset, bytes) == 0; + else + return (1); +} + +static int +isBootRecord(struct iso9660 *iso9660, const unsigned char *h) +{ + (void)iso9660; /* UNUSED */ + + /* Type of the Volume Descriptor Boot Record must be 0. */ + if (h[0] != 0) + return (0); + + /* Volume Descriptor Version must be 1. */ + if (h[6] != 1) + return (0); + + return (1); +} + +static int +isVolumePartition(struct iso9660 *iso9660, const unsigned char *h) +{ + int32_t location; + + /* Type of the Volume Partition Descriptor must be 3. */ + if (h[0] != 3) + return (0); + + /* Volume Descriptor Version must be 1. */ + if (h[6] != 1) + return (0); + /* Unused Field */ + if (h[7] != 0) + return (0); + + location = archive_le32dec(h + 72); + if (location <= SYSTEM_AREA_BLOCK || + location >= iso9660->volume_block) + return (0); + if ((uint32_t)location != archive_be32dec(h + 76)) + return (0); + + return (1); +} + +static int +isVDSetTerminator(struct iso9660 *iso9660, const unsigned char *h) +{ + (void)iso9660; /* UNUSED */ + + /* Type of the Volume Descriptor Set Terminator must be 255. */ + if (h[0] != 255) + return (0); + + /* Volume Descriptor Version must be 1. */ + if (h[6] != 1) + return (0); + + /* Reserved field must be 0. */ + if (!isNull(iso9660, h, 7, 2048-7)) + return (0); + + return (1); +} + +static int +isJolietSVD(struct iso9660 *iso9660, const unsigned char *h) +{ + const unsigned char *p; + ssize_t logical_block_size; + int32_t volume_block; + + /* Check if current sector is a kind of Supplementary Volume + * Descriptor. */ + if (!isSVD(iso9660, h)) + return (0); + + /* FIXME: do more validations according to joliet spec. */ + + /* check if this SVD contains joliet extension! */ + p = h + SVD_escape_sequences_offset; + /* N.B. Joliet spec says p[1] == '\\', but.... */ + if (p[0] == '%' && p[1] == '/') { + int level = 0; + + if (p[2] == '@') + level = 1; + else if (p[2] == 'C') + level = 2; + else if (p[2] == 'E') + level = 3; + else /* not joliet */ + return (0); + + iso9660->seenJoliet = level; + + } else /* not joliet */ + return (0); + + logical_block_size = + archive_le16dec(h + SVD_logical_block_size_offset); + volume_block = archive_le32dec(h + SVD_volume_space_size_offset); + + iso9660->logical_block_size = logical_block_size; + iso9660->volume_block = volume_block; + iso9660->volume_size = logical_block_size * (uint64_t)volume_block; + /* Read Root Directory Record in Volume Descriptor. */ + p = h + SVD_root_directory_record_offset; + iso9660->joliet.location = archive_le32dec(p + DR_extent_offset); + iso9660->joliet.size = archive_le32dec(p + DR_size_offset); + + return (48); +} + +static int +isSVD(struct iso9660 *iso9660, const unsigned char *h) +{ + const unsigned char *p; + ssize_t logical_block_size; + int32_t volume_block; + int32_t location; + + (void)iso9660; /* UNUSED */ + + /* Type 2 means it's a SVD. */ + if (h[SVD_type_offset] != 2) + return (0); + + /* Reserved field must be 0. */ + if (!isNull(iso9660, h, SVD_reserved1_offset, SVD_reserved1_size)) + return (0); + if (!isNull(iso9660, h, SVD_reserved2_offset, SVD_reserved2_size)) + return (0); + if (!isNull(iso9660, h, SVD_reserved3_offset, SVD_reserved3_size)) + return (0); + + /* File structure version must be 1 for ISO9660/ECMA119. */ + if (h[SVD_file_structure_version_offset] != 1) + return (0); + + logical_block_size = + archive_le16dec(h + SVD_logical_block_size_offset); + if (logical_block_size <= 0) + return (0); + + volume_block = archive_le32dec(h + SVD_volume_space_size_offset); + if (volume_block <= SYSTEM_AREA_BLOCK+4) + return (0); + + /* Location of Occurrence of Type L Path Table must be + * available location, + * >= SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */ + location = archive_le32dec(h+SVD_type_L_path_table_offset); + if (location < SYSTEM_AREA_BLOCK+2 || location >= volume_block) + return (0); + + /* The Type M Path Table must be at a valid location (WinISO + * and probably other programs omit this, so we allow zero) + * + * >= SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */ + location = archive_be32dec(h+SVD_type_M_path_table_offset); + if ((location > 0 && location < SYSTEM_AREA_BLOCK+2) + || location >= volume_block) + return (0); + + /* Read Root Directory Record in Volume Descriptor. */ + p = h + SVD_root_directory_record_offset; + if (p[DR_length_offset] != 34) + return (0); + + return (48); +} + +static int +isEVD(struct iso9660 *iso9660, const unsigned char *h) +{ + const unsigned char *p; + ssize_t logical_block_size; + int32_t volume_block; + int32_t location; + + (void)iso9660; /* UNUSED */ + + /* Type of the Enhanced Volume Descriptor must be 2. */ + if (h[PVD_type_offset] != 2) + return (0); + + /* EVD version must be 2. */ + if (h[PVD_version_offset] != 2) + return (0); + + /* Reserved field must be 0. */ + if (h[PVD_reserved1_offset] != 0) + return (0); + + /* Reserved field must be 0. */ + if (!isNull(iso9660, h, PVD_reserved2_offset, PVD_reserved2_size)) + return (0); + + /* Reserved field must be 0. */ + if (!isNull(iso9660, h, PVD_reserved3_offset, PVD_reserved3_size)) + return (0); + + /* Logical block size must be > 0. */ + /* I've looked at Ecma 119 and can't find any stronger + * restriction on this field. */ + logical_block_size = + archive_le16dec(h + PVD_logical_block_size_offset); + if (logical_block_size <= 0) + return (0); + + volume_block = + archive_le32dec(h + PVD_volume_space_size_offset); + if (volume_block <= SYSTEM_AREA_BLOCK+4) + return (0); + + /* File structure version must be 2 for ISO9660:1999. */ + if (h[PVD_file_structure_version_offset] != 2) + return (0); + + /* Location of Occurrence of Type L Path Table must be + * available location, + * >= SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */ + location = archive_le32dec(h+PVD_type_1_path_table_offset); + if (location < SYSTEM_AREA_BLOCK+2 || location >= volume_block) + return (0); + + /* Location of Occurrence of Type M Path Table must be + * available location, + * >= SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */ + location = archive_be32dec(h+PVD_type_m_path_table_offset); + if ((location > 0 && location < SYSTEM_AREA_BLOCK+2) + || location >= volume_block) + return (0); + + /* Reserved field must be 0. */ + if (!isNull(iso9660, h, PVD_reserved4_offset, PVD_reserved4_size)) + return (0); + + /* Reserved field must be 0. */ + if (!isNull(iso9660, h, PVD_reserved5_offset, PVD_reserved5_size)) + return (0); + + /* Read Root Directory Record in Volume Descriptor. */ + p = h + PVD_root_directory_record_offset; + if (p[DR_length_offset] != 34) + return (0); + + return (48); +} + +static int +isPVD(struct iso9660 *iso9660, const unsigned char *h) +{ + const unsigned char *p; + ssize_t logical_block_size; + int32_t volume_block; + int32_t location; + int i; + + /* Type of the Primary Volume Descriptor must be 1. */ + if (h[PVD_type_offset] != 1) + return (0); + + /* PVD version must be 1. */ + if (h[PVD_version_offset] != 1) + return (0); + + /* Reserved field must be 0. */ + if (h[PVD_reserved1_offset] != 0) + return (0); + + /* Reserved field must be 0. */ + if (!isNull(iso9660, h, PVD_reserved2_offset, PVD_reserved2_size)) + return (0); + + /* Reserved field must be 0. */ + if (!isNull(iso9660, h, PVD_reserved3_offset, PVD_reserved3_size)) + return (0); + + /* Logical block size must be > 0. */ + /* I've looked at Ecma 119 and can't find any stronger + * restriction on this field. */ + logical_block_size = + archive_le16dec(h + PVD_logical_block_size_offset); + if (logical_block_size <= 0) + return (0); + + volume_block = archive_le32dec(h + PVD_volume_space_size_offset); + if (volume_block <= SYSTEM_AREA_BLOCK+4) + return (0); + + /* File structure version must be 1 for ISO9660/ECMA119. */ + if (h[PVD_file_structure_version_offset] != 1) + return (0); + + /* Location of Occurrence of Type L Path Table must be + * available location, + * > SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */ + location = archive_le32dec(h+PVD_type_1_path_table_offset); + if (location < SYSTEM_AREA_BLOCK+2 || location >= volume_block) + return (0); + + /* The Type M Path Table must also be at a valid location + * (although ECMA 119 requires a Type M Path Table, WinISO and + * probably other programs omit it, so we permit a zero here) + * + * >= SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */ + location = archive_be32dec(h+PVD_type_m_path_table_offset); + if ((location > 0 && location < SYSTEM_AREA_BLOCK+2) + || location >= volume_block) + return (0); + + /* Reserved field must be 0. */ + /* But accept NetBSD/FreeBSD "makefs" images with 0x20 here. */ + for (i = 0; i < PVD_reserved4_size; ++i) + if (h[PVD_reserved4_offset + i] != 0 + && h[PVD_reserved4_offset + i] != 0x20) + return (0); + + /* Reserved field must be 0. */ + if (!isNull(iso9660, h, PVD_reserved5_offset, PVD_reserved5_size)) + return (0); + + /* XXX TODO: Check other values for sanity; reject more + * malformed PVDs. XXX */ + + /* Read Root Directory Record in Volume Descriptor. */ + p = h + PVD_root_directory_record_offset; + if (p[DR_length_offset] != 34) + return (0); + + if (!iso9660->primary.location) { + iso9660->logical_block_size = logical_block_size; + iso9660->volume_block = volume_block; + iso9660->volume_size = + logical_block_size * (uint64_t)volume_block; + iso9660->primary.location = + archive_le32dec(p + DR_extent_offset); + iso9660->primary.size = archive_le32dec(p + DR_size_offset); + } + + return (48); +} + +static int +read_children(struct archive_read *a, struct file_info *parent) +{ + struct iso9660 *iso9660; + const unsigned char *b, *p; + struct file_info *multi; + size_t step, skip_size; + + iso9660 = (struct iso9660 *)(a->format->data); + /* flush any remaining bytes from the last round to ensure + * we're positioned */ + if (iso9660->entry_bytes_unconsumed) { + __archive_read_consume(a, iso9660->entry_bytes_unconsumed); + iso9660->entry_bytes_unconsumed = 0; + } + if (iso9660->current_position > parent->offset) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Ignoring out-of-order directory (%s) %jd > %jd", + parent->name.s, + (intmax_t)iso9660->current_position, + (intmax_t)parent->offset); + return (ARCHIVE_WARN); + } + if (parent->offset + parent->size > iso9660->volume_size) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Directory is beyond end-of-media: %s", + parent->name.s); + return (ARCHIVE_WARN); + } + if (iso9660->current_position < parent->offset) { + int64_t skipsize; + + skipsize = parent->offset - iso9660->current_position; + skipsize = __archive_read_consume(a, skipsize); + if (skipsize < 0) + return ((int)skipsize); + iso9660->current_position = parent->offset; + } + + step = (size_t)(((parent->size + iso9660->logical_block_size -1) / + iso9660->logical_block_size) * iso9660->logical_block_size); + b = __archive_read_ahead(a, step, NULL); + if (b == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to read full block when scanning " + "ISO9660 directory list"); + return (ARCHIVE_FATAL); + } + iso9660->current_position += step; + multi = NULL; + skip_size = step; + while (step) { + p = b; + b += iso9660->logical_block_size; + step -= iso9660->logical_block_size; + for (; *p != 0 && p < b && p + *p <= b; p += *p) { + struct file_info *child; + + /* N.B.: these special directory identifiers + * are 8 bit "values" even on a + * Joliet CD with UCS-2 (16bit) encoding. + */ + + /* Skip '.' entry. */ + if (*(p + DR_name_len_offset) == 1 + && *(p + DR_name_offset) == '\0') + continue; + /* Skip '..' entry. */ + if (*(p + DR_name_len_offset) == 1 + && *(p + DR_name_offset) == '\001') + continue; + child = parse_file_info(a, parent, p, b - p); + if (child == NULL) { + __archive_read_consume(a, skip_size); + return (ARCHIVE_FATAL); + } + if (child->cl_offset == 0 && + (child->multi_extent || multi != NULL)) { + struct content *con; + + if (multi == NULL) { + multi = child; + multi->contents.first = NULL; + multi->contents.last = + &(multi->contents.first); + } + con = malloc(sizeof(struct content)); + if (con == NULL) { + archive_set_error( + &a->archive, ENOMEM, + "No memory for multi extent"); + __archive_read_consume(a, skip_size); + return (ARCHIVE_FATAL); + } + con->offset = child->offset; + con->size = child->size; + con->next = NULL; + *multi->contents.last = con; + multi->contents.last = &(con->next); + if (multi == child) { + if (add_entry(a, iso9660, child) + != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } else { + multi->size += child->size; + if (!child->multi_extent) + multi = NULL; + } + } else + if (add_entry(a, iso9660, child) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + } + + __archive_read_consume(a, skip_size); + + /* Read data which recorded by RRIP "CE" extension. */ + if (read_CE(a, iso9660) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + return (ARCHIVE_OK); +} + +static int +choose_volume(struct archive_read *a, struct iso9660 *iso9660) +{ + struct file_info *file; + int64_t skipsize; + struct vd *vd; + const void *block; + char seenJoliet; + + vd = &(iso9660->primary); + if (!iso9660->opt_support_joliet) + iso9660->seenJoliet = 0; + if (iso9660->seenJoliet && + vd->location > iso9660->joliet.location) + /* This condition is unlikely; by way of caution. */ + vd = &(iso9660->joliet); + + skipsize = LOGICAL_BLOCK_SIZE * (int64_t)vd->location; + skipsize = __archive_read_consume(a, skipsize); + if (skipsize < 0) + return ((int)skipsize); + iso9660->current_position = skipsize; + + block = __archive_read_ahead(a, vd->size, NULL); + if (block == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to read full block when scanning " + "ISO9660 directory list"); + return (ARCHIVE_FATAL); + } + + /* + * While reading Root Directory, flag seenJoliet must be zero to + * avoid converting special name 0x00(Current Directory) and + * next byte to UCS2. + */ + seenJoliet = iso9660->seenJoliet;/* Save flag. */ + iso9660->seenJoliet = 0; + file = parse_file_info(a, NULL, block, vd->size); + if (file == NULL) + return (ARCHIVE_FATAL); + iso9660->seenJoliet = seenJoliet; + + /* + * If the iso image has both RockRidge and Joliet, we preferentially + * use RockRidge Extensions rather than Joliet ones. + */ + if (vd == &(iso9660->primary) && iso9660->seenRockridge + && iso9660->seenJoliet) + iso9660->seenJoliet = 0; + + if (vd == &(iso9660->primary) && !iso9660->seenRockridge + && iso9660->seenJoliet) { + /* Switch reading data from primary to joliet. */ + vd = &(iso9660->joliet); + skipsize = LOGICAL_BLOCK_SIZE * (int64_t)vd->location; + skipsize -= iso9660->current_position; + skipsize = __archive_read_consume(a, skipsize); + if (skipsize < 0) + return ((int)skipsize); + iso9660->current_position += skipsize; + + block = __archive_read_ahead(a, vd->size, NULL); + if (block == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to read full block when scanning " + "ISO9660 directory list"); + return (ARCHIVE_FATAL); + } + iso9660->seenJoliet = 0; + file = parse_file_info(a, NULL, block, vd->size); + if (file == NULL) + return (ARCHIVE_FATAL); + iso9660->seenJoliet = seenJoliet; + } + + /* Store the root directory in the pending list. */ + if (add_entry(a, iso9660, file) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + if (iso9660->seenRockridge) { + a->archive.archive_format = ARCHIVE_FORMAT_ISO9660_ROCKRIDGE; + a->archive.archive_format_name = + "ISO9660 with Rockridge extensions"; + } + + return (ARCHIVE_OK); +} + +static int +archive_read_format_iso9660_read_header(struct archive_read *a, + struct archive_entry *entry) +{ + struct iso9660 *iso9660; + struct file_info *file; + int r, rd_r = ARCHIVE_OK; + + iso9660 = (struct iso9660 *)(a->format->data); + + if (!a->archive.archive_format) { + a->archive.archive_format = ARCHIVE_FORMAT_ISO9660; + a->archive.archive_format_name = "ISO9660"; + } + + if (iso9660->current_position == 0) { + r = choose_volume(a, iso9660); + if (r != ARCHIVE_OK) + return (r); + } + + file = NULL;/* Eliminate a warning. */ + /* Get the next entry that appears after the current offset. */ + r = next_entry_seek(a, iso9660, &file); + if (r != ARCHIVE_OK) + return (r); + + if (iso9660->seenJoliet) { + /* + * Convert UTF-16BE of a filename to local locale MBS + * and store the result into a filename field. + */ + if (iso9660->sconv_utf16be == NULL) { + iso9660->sconv_utf16be = + archive_string_conversion_from_charset( + &(a->archive), "UTF-16BE", 1); + if (iso9660->sconv_utf16be == NULL) + /* Couldn't allocate memory */ + return (ARCHIVE_FATAL); + } + if (iso9660->utf16be_path == NULL) { + iso9660->utf16be_path = malloc(UTF16_NAME_MAX); + if (iso9660->utf16be_path == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory"); + return (ARCHIVE_FATAL); + } + } + if (iso9660->utf16be_previous_path == NULL) { + iso9660->utf16be_previous_path = malloc(UTF16_NAME_MAX); + if (iso9660->utf16be_previous_path == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory"); + return (ARCHIVE_FATAL); + } + } + + iso9660->utf16be_path_len = 0; + if (build_pathname_utf16be(iso9660->utf16be_path, + UTF16_NAME_MAX, &(iso9660->utf16be_path_len), file) != 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Pathname is too long"); + return (ARCHIVE_FATAL); + } + + r = archive_entry_copy_pathname_l(entry, + (const char *)iso9660->utf16be_path, + iso9660->utf16be_path_len, + iso9660->sconv_utf16be); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "No memory for Pathname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Pathname cannot be converted " + "from %s to current locale.", + archive_string_conversion_charset_name( + iso9660->sconv_utf16be)); + + rd_r = ARCHIVE_WARN; + } + } else { + const char *path = build_pathname(&iso9660->pathname, file, 0); + if (path == NULL) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Pathname is too long"); + return (ARCHIVE_FATAL); + } else { + archive_string_empty(&iso9660->pathname); + archive_entry_set_pathname(entry, path); + } + } + + iso9660->entry_bytes_remaining = file->size; + /* Offset for sparse-file-aware clients. */ + iso9660->entry_sparse_offset = 0; + + if (file->offset + file->size > iso9660->volume_size) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "File is beyond end-of-media: %s", + archive_entry_pathname(entry)); + iso9660->entry_bytes_remaining = 0; + return (ARCHIVE_WARN); + } + + /* Set up the entry structure with information about this entry. */ + archive_entry_set_mode(entry, file->mode); + archive_entry_set_uid(entry, file->uid); + archive_entry_set_gid(entry, file->gid); + archive_entry_set_nlink(entry, file->nlinks); + if (file->birthtime_is_set) + archive_entry_set_birthtime(entry, file->birthtime, 0); + else + archive_entry_unset_birthtime(entry); + archive_entry_set_mtime(entry, file->mtime, 0); + archive_entry_set_ctime(entry, file->ctime, 0); + archive_entry_set_atime(entry, file->atime, 0); + /* N.B.: Rock Ridge supports 64-bit device numbers. */ + archive_entry_set_rdev(entry, (dev_t)file->rdev); + archive_entry_set_size(entry, iso9660->entry_bytes_remaining); + if (file->symlink.s != NULL) + archive_entry_copy_symlink(entry, file->symlink.s); + + /* Note: If the input isn't seekable, we can't rewind to + * return the same body again, so if the next entry refers to + * the same data, we have to return it as a hardlink to the + * original entry. */ + if (file->number != -1 && + file->number == iso9660->previous_number) { + if (iso9660->seenJoliet) { + r = archive_entry_copy_hardlink_l(entry, + (const char *)iso9660->utf16be_previous_path, + iso9660->utf16be_previous_path_len, + iso9660->sconv_utf16be); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "No memory for Linkname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Linkname cannot be converted " + "from %s to current locale.", + archive_string_conversion_charset_name( + iso9660->sconv_utf16be)); + rd_r = ARCHIVE_WARN; + } + } else + archive_entry_set_hardlink(entry, + iso9660->previous_pathname.s); + archive_entry_unset_size(entry); + iso9660->entry_bytes_remaining = 0; + return (rd_r); + } + + if ((file->mode & AE_IFMT) != AE_IFDIR && + file->offset < iso9660->current_position) { + int64_t r64; + + r64 = __archive_read_seek(a, file->offset, SEEK_SET); + if (r64 != (int64_t)file->offset) { + /* We can't seek backwards to extract it, so issue + * a warning. Note that this can only happen if + * this entry was added to the heap after we passed + * this offset, that is, only if the directory + * mentioning this entry is later than the body of + * the entry. Such layouts are very unusual; most + * ISO9660 writers lay out and record all directory + * information first, then store all file bodies. */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Ignoring out-of-order file @%jx (%s) %jd < %jd", + (intmax_t)file->number, + iso9660->pathname.s, + (intmax_t)file->offset, + (intmax_t)iso9660->current_position); + iso9660->entry_bytes_remaining = 0; + return (ARCHIVE_WARN); + } + iso9660->current_position = (uint64_t)r64; + } + + /* Initialize zisofs variables. */ + iso9660->entry_zisofs.pz = file->pz; + if (file->pz) { +#ifdef HAVE_ZLIB_H + struct zisofs *zisofs; + + zisofs = &iso9660->entry_zisofs; + zisofs->initialized = 0; + zisofs->pz_log2_bs = file->pz_log2_bs; + zisofs->pz_uncompressed_size = file->pz_uncompressed_size; + zisofs->pz_offset = 0; + zisofs->header_avail = 0; + zisofs->header_passed = 0; + zisofs->block_pointers_avail = 0; +#endif + archive_entry_set_size(entry, file->pz_uncompressed_size); + } + + iso9660->previous_number = file->number; + if (iso9660->seenJoliet) { + memcpy(iso9660->utf16be_previous_path, iso9660->utf16be_path, + iso9660->utf16be_path_len); + iso9660->utf16be_previous_path_len = iso9660->utf16be_path_len; + } else + archive_strcpy( + &iso9660->previous_pathname, iso9660->pathname.s); + + /* Reset entry_bytes_remaining if the file is multi extent. */ + iso9660->entry_content = file->contents.first; + if (iso9660->entry_content != NULL) + iso9660->entry_bytes_remaining = iso9660->entry_content->size; + + if (archive_entry_filetype(entry) == AE_IFDIR) { + /* Overwrite nlinks by proper link number which is + * calculated from number of sub directories. */ + archive_entry_set_nlink(entry, 2 + file->subdirs); + /* Directory data has been read completely. */ + iso9660->entry_bytes_remaining = 0; + } + + if (rd_r != ARCHIVE_OK) + return (rd_r); + return (ARCHIVE_OK); +} + +static int +archive_read_format_iso9660_read_data_skip(struct archive_read *a) +{ + /* Because read_next_header always does an explicit skip + * to the next entry, we don't need to do anything here. */ + (void)a; /* UNUSED */ + return (ARCHIVE_OK); +} + +#ifdef HAVE_ZLIB_H + +static int +zisofs_read_data(struct archive_read *a, + const void **buff, size_t *size, int64_t *offset) +{ + struct iso9660 *iso9660; + struct zisofs *zisofs; + const unsigned char *p; + size_t avail; + ssize_t bytes_read; + size_t uncompressed_size; + int r; + + iso9660 = (struct iso9660 *)(a->format->data); + zisofs = &iso9660->entry_zisofs; + + p = __archive_read_ahead(a, 1, &bytes_read); + if (bytes_read <= 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated zisofs file body"); + return (ARCHIVE_FATAL); + } + if (bytes_read > iso9660->entry_bytes_remaining) + bytes_read = (ssize_t)iso9660->entry_bytes_remaining; + avail = bytes_read; + uncompressed_size = 0; + + if (!zisofs->initialized) { + size_t ceil, xsize; + + /* Allocate block pointers buffer. */ + ceil = (size_t)((zisofs->pz_uncompressed_size + + (((int64_t)1) << zisofs->pz_log2_bs) - 1) + >> zisofs->pz_log2_bs); + xsize = (ceil + 1) * 4; + if (zisofs->block_pointers_alloc < xsize) { + size_t alloc; + + if (zisofs->block_pointers != NULL) + free(zisofs->block_pointers); + alloc = ((xsize >> 10) + 1) << 10; + zisofs->block_pointers = malloc(alloc); + if (zisofs->block_pointers == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for zisofs decompression"); + return (ARCHIVE_FATAL); + } + zisofs->block_pointers_alloc = alloc; + } + zisofs->block_pointers_size = xsize; + + /* Allocate uncompressed data buffer. */ + xsize = (size_t)1UL << zisofs->pz_log2_bs; + if (zisofs->uncompressed_buffer_size < xsize) { + if (zisofs->uncompressed_buffer != NULL) + free(zisofs->uncompressed_buffer); + zisofs->uncompressed_buffer = malloc(xsize); + if (zisofs->uncompressed_buffer == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for zisofs decompression"); + return (ARCHIVE_FATAL); + } + } + zisofs->uncompressed_buffer_size = xsize; + + /* + * Read the file header, and check the magic code of zisofs. + */ + if (zisofs->header_avail < sizeof(zisofs->header)) { + xsize = sizeof(zisofs->header) - zisofs->header_avail; + if (avail < xsize) + xsize = avail; + memcpy(zisofs->header + zisofs->header_avail, p, xsize); + zisofs->header_avail += xsize; + avail -= xsize; + p += xsize; + } + if (!zisofs->header_passed && + zisofs->header_avail == sizeof(zisofs->header)) { + int err = 0; + + if (memcmp(zisofs->header, zisofs_magic, + sizeof(zisofs_magic)) != 0) + err = 1; + if (archive_le32dec(zisofs->header + 8) + != zisofs->pz_uncompressed_size) + err = 1; + if (zisofs->header[12] != 4) + err = 1; + if (zisofs->header[13] != zisofs->pz_log2_bs) + err = 1; + if (err) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Illegal zisofs file body"); + return (ARCHIVE_FATAL); + } + zisofs->header_passed = 1; + } + /* + * Read block pointers. + */ + if (zisofs->header_passed && + zisofs->block_pointers_avail < zisofs->block_pointers_size) { + xsize = zisofs->block_pointers_size + - zisofs->block_pointers_avail; + if (avail < xsize) + xsize = avail; + memcpy(zisofs->block_pointers + + zisofs->block_pointers_avail, p, xsize); + zisofs->block_pointers_avail += xsize; + avail -= xsize; + p += xsize; + if (zisofs->block_pointers_avail + == zisofs->block_pointers_size) { + /* We've got all block pointers and initialize + * related variables. */ + zisofs->block_off = 0; + zisofs->block_avail = 0; + /* Complete a initialization */ + zisofs->initialized = 1; + } + } + + if (!zisofs->initialized) + goto next_data; /* We need more data. */ + } + + /* + * Get block offsets from block pointers. + */ + if (zisofs->block_avail == 0) { + uint32_t bst, bed; + + if (zisofs->block_off + 4 >= zisofs->block_pointers_size) { + /* There isn't a pair of offsets. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Illegal zisofs block pointers"); + return (ARCHIVE_FATAL); + } + bst = archive_le32dec( + zisofs->block_pointers + zisofs->block_off); + if (bst != zisofs->pz_offset + (bytes_read - avail)) { + /* TODO: Should we seek offset of current file + * by bst ? */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Illegal zisofs block pointers(cannot seek)"); + return (ARCHIVE_FATAL); + } + bed = archive_le32dec( + zisofs->block_pointers + zisofs->block_off + 4); + if (bed < bst) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Illegal zisofs block pointers"); + return (ARCHIVE_FATAL); + } + zisofs->block_avail = bed - bst; + zisofs->block_off += 4; + + /* Initialize compression library for new block. */ + if (zisofs->stream_valid) + r = inflateReset(&zisofs->stream); + else + r = inflateInit(&zisofs->stream); + if (r != Z_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't initialize zisofs decompression."); + return (ARCHIVE_FATAL); + } + zisofs->stream_valid = 1; + zisofs->stream.total_in = 0; + zisofs->stream.total_out = 0; + } + + /* + * Make uncompressed data. + */ + if (zisofs->block_avail == 0) { + memset(zisofs->uncompressed_buffer, 0, + zisofs->uncompressed_buffer_size); + uncompressed_size = zisofs->uncompressed_buffer_size; + } else { + zisofs->stream.next_in = (Bytef *)(uintptr_t)(const void *)p; + if (avail > zisofs->block_avail) + zisofs->stream.avail_in = zisofs->block_avail; + else + zisofs->stream.avail_in = (uInt)avail; + zisofs->stream.next_out = zisofs->uncompressed_buffer; + zisofs->stream.avail_out = + (uInt)zisofs->uncompressed_buffer_size; + + r = inflate(&zisofs->stream, 0); + switch (r) { + case Z_OK: /* Decompressor made some progress.*/ + case Z_STREAM_END: /* Found end of stream. */ + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "zisofs decompression failed (%d)", r); + return (ARCHIVE_FATAL); + } + uncompressed_size = + zisofs->uncompressed_buffer_size - zisofs->stream.avail_out; + avail -= zisofs->stream.next_in - p; + zisofs->block_avail -= (uint32_t)(zisofs->stream.next_in - p); + } +next_data: + bytes_read -= avail; + *buff = zisofs->uncompressed_buffer; + *size = uncompressed_size; + *offset = iso9660->entry_sparse_offset; + iso9660->entry_sparse_offset += uncompressed_size; + iso9660->entry_bytes_remaining -= bytes_read; + iso9660->current_position += bytes_read; + zisofs->pz_offset += (uint32_t)bytes_read; + iso9660->entry_bytes_unconsumed += bytes_read; + + return (ARCHIVE_OK); +} + +#else /* HAVE_ZLIB_H */ + +static int +zisofs_read_data(struct archive_read *a, + const void **buff, size_t *size, int64_t *offset) +{ + + (void)buff;/* UNUSED */ + (void)size;/* UNUSED */ + (void)offset;/* UNUSED */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "zisofs is not supported on this platform."); + return (ARCHIVE_FAILED); +} + +#endif /* HAVE_ZLIB_H */ + +static int +archive_read_format_iso9660_read_data(struct archive_read *a, + const void **buff, size_t *size, int64_t *offset) +{ + ssize_t bytes_read; + struct iso9660 *iso9660; + + iso9660 = (struct iso9660 *)(a->format->data); + + if (iso9660->entry_bytes_unconsumed) { + __archive_read_consume(a, iso9660->entry_bytes_unconsumed); + iso9660->entry_bytes_unconsumed = 0; + } + + if (iso9660->entry_bytes_remaining <= 0) { + if (iso9660->entry_content != NULL) + iso9660->entry_content = iso9660->entry_content->next; + if (iso9660->entry_content == NULL) { + *buff = NULL; + *size = 0; + *offset = iso9660->entry_sparse_offset; + return (ARCHIVE_EOF); + } + /* Seek forward to the start of the entry. */ + if (iso9660->current_position < iso9660->entry_content->offset) { + int64_t step; + + step = iso9660->entry_content->offset - + iso9660->current_position; + step = __archive_read_consume(a, step); + if (step < 0) + return ((int)step); + iso9660->current_position = + iso9660->entry_content->offset; + } + if (iso9660->entry_content->offset < iso9660->current_position) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Ignoring out-of-order file (%s) %jd < %jd", + iso9660->pathname.s, + (intmax_t)iso9660->entry_content->offset, + (intmax_t)iso9660->current_position); + *buff = NULL; + *size = 0; + *offset = iso9660->entry_sparse_offset; + return (ARCHIVE_WARN); + } + iso9660->entry_bytes_remaining = iso9660->entry_content->size; + } + if (iso9660->entry_zisofs.pz) + return (zisofs_read_data(a, buff, size, offset)); + + *buff = __archive_read_ahead(a, 1, &bytes_read); + if (bytes_read == 0) + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Truncated input file"); + if (*buff == NULL) + return (ARCHIVE_FATAL); + if (bytes_read > iso9660->entry_bytes_remaining) + bytes_read = (ssize_t)iso9660->entry_bytes_remaining; + *size = bytes_read; + *offset = iso9660->entry_sparse_offset; + iso9660->entry_sparse_offset += bytes_read; + iso9660->entry_bytes_remaining -= bytes_read; + iso9660->entry_bytes_unconsumed = bytes_read; + iso9660->current_position += bytes_read; + return (ARCHIVE_OK); +} + +static int +archive_read_format_iso9660_cleanup(struct archive_read *a) +{ + struct iso9660 *iso9660; + int r = ARCHIVE_OK; + + iso9660 = (struct iso9660 *)(a->format->data); + release_files(iso9660); + free(iso9660->read_ce_req.reqs); + archive_string_free(&iso9660->pathname); + archive_string_free(&iso9660->previous_pathname); + free(iso9660->pending_files.files); +#ifdef HAVE_ZLIB_H + free(iso9660->entry_zisofs.uncompressed_buffer); + free(iso9660->entry_zisofs.block_pointers); + if (iso9660->entry_zisofs.stream_valid) { + if (inflateEnd(&iso9660->entry_zisofs.stream) != Z_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to clean up zlib decompressor"); + r = ARCHIVE_FATAL; + } + } +#endif + free(iso9660->utf16be_path); + free(iso9660->utf16be_previous_path); + free(iso9660); + (a->format->data) = NULL; + return (r); +} + +/* + * This routine parses a single ISO directory record, makes sense + * of any extensions, and stores the result in memory. + */ +static struct file_info * +parse_file_info(struct archive_read *a, struct file_info *parent, + const unsigned char *isodirrec, size_t reclen) +{ + struct iso9660 *iso9660; + struct file_info *file, *filep; + size_t name_len; + const unsigned char *rr_start, *rr_end; + const unsigned char *p; + size_t dr_len; + uint64_t fsize, offset; + int32_t location; + int flags; + + iso9660 = (struct iso9660 *)(a->format->data); + + if (reclen != 0) + dr_len = (size_t)isodirrec[DR_length_offset]; + /* + * Sanity check that reclen is not zero and dr_len is greater than + * reclen but at least 34 + */ + if (reclen == 0 || reclen < dr_len || dr_len < 34) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid length of directory record"); + return (NULL); + } + name_len = (size_t)isodirrec[DR_name_len_offset]; + location = archive_le32dec(isodirrec + DR_extent_offset); + fsize = toi(isodirrec + DR_size_offset, DR_size_size); + /* Sanity check that name_len doesn't exceed dr_len. */ + if (dr_len - 33 < name_len || name_len == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid length of file identifier"); + return (NULL); + } + /* Sanity check that location doesn't exceed volume block. + * Don't check lower limit of location; it's possibility + * the location has negative value when file type is symbolic + * link or file size is zero. As far as I know latest mkisofs + * do that. + */ + if (location > 0 && + (location + ((fsize + iso9660->logical_block_size -1) + / iso9660->logical_block_size)) + > (uint32_t)iso9660->volume_block) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid location of extent of file"); + return (NULL); + } + /* Sanity check that location doesn't have a negative value + * when the file is not empty. it's too large. */ + if (fsize != 0 && location < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid location of extent of file"); + return (NULL); + } + + /* Sanity check that this entry does not create a cycle. */ + offset = iso9660->logical_block_size * (uint64_t)location; + for (filep = parent; filep != NULL; filep = filep->parent) { + if (filep->offset == offset) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Directory structure contains loop"); + return (NULL); + } + } + + /* Create a new file entry and copy data from the ISO dir record. */ + file = (struct file_info *)calloc(1, sizeof(*file)); + if (file == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for file entry"); + return (NULL); + } + file->parent = parent; + file->offset = offset; + file->size = fsize; + file->mtime = isodate7(isodirrec + DR_date_offset); + file->ctime = file->atime = file->mtime; + file->rede_files.first = NULL; + file->rede_files.last = &(file->rede_files.first); + + p = isodirrec + DR_name_offset; + /* Rockridge extensions (if any) follow name. Compute this + * before fidgeting the name_len below. */ + rr_start = p + name_len + (name_len & 1 ? 0 : 1); + rr_end = isodirrec + dr_len; + + if (iso9660->seenJoliet) { + /* Joliet names are max 64 chars (128 bytes) according to spec, + * but genisoimage/mkisofs allows recording longer Joliet + * names which are 103 UCS2 characters(206 bytes) by their + * option '-joliet-long'. + */ + if (name_len > 206) + name_len = 206; + name_len &= ~1; + + /* trim trailing first version and dot from filename. + * + * Remember we were in UTF-16BE land! + * SEPARATOR 1 (.) and SEPARATOR 2 (;) are both + * 16 bits big endian characters on Joliet. + * + * TODO: sanitize filename? + * Joliet allows any UCS-2 char except: + * *, /, :, ;, ? and \. + */ + /* Chop off trailing ';1' from files. */ + if (name_len > 4 && p[name_len-4] == 0 && p[name_len-3] == ';' + && p[name_len-2] == 0 && p[name_len-1] == '1') + name_len -= 4; +#if 0 /* XXX: this somehow manages to strip of single-character file extensions, like '.c'. */ + /* Chop off trailing '.' from filenames. */ + if (name_len > 2 && p[name_len-2] == 0 && p[name_len-1] == '.') + name_len -= 2; +#endif + if ((file->utf16be_name = malloc(name_len)) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for file name"); + goto fail; + } + memcpy(file->utf16be_name, p, name_len); + file->utf16be_bytes = name_len; + } else { + /* Chop off trailing ';1' from files. */ + if (name_len > 2 && p[name_len - 2] == ';' && + p[name_len - 1] == '1') + name_len -= 2; + /* Chop off trailing '.' from filenames. */ + if (name_len > 1 && p[name_len - 1] == '.') + --name_len; + + archive_strncpy(&file->name, (const char *)p, name_len); + } + + flags = isodirrec[DR_flags_offset]; + if (flags & 0x02) + file->mode = AE_IFDIR | 0700; + else + file->mode = AE_IFREG | 0400; + if (flags & 0x80) + file->multi_extent = 1; + else + file->multi_extent = 0; + /* + * Use a location for the file number, which is treated as an inode + * number to find out hardlink target. If Rockridge extensions is + * being used, the file number will be overwritten by FILE SERIAL + * NUMBER of RRIP "PX" extension. + * Note: Old mkisofs did not record that FILE SERIAL NUMBER + * in ISO images. + * Note2: xorriso set 0 to the location of a symlink file. + */ + if (file->size == 0 && location >= 0) { + /* If file->size is zero, its location points wrong place, + * and so we should not use it for the file number. + * When the location has negative value, it can be used + * for the file number. + */ + file->number = -1; + /* Do not appear before any directory entries. */ + file->offset = -1; + } else + file->number = (int64_t)(uint32_t)location; + + /* Rockridge extensions overwrite information from above. */ + if (iso9660->opt_support_rockridge) { + if (parent == NULL && rr_end - rr_start >= 7) { + p = rr_start; + if (memcmp(p, "SP\x07\x01\xbe\xef", 6) == 0) { + /* + * SP extension stores the suspOffset + * (Number of bytes to skip between + * filename and SUSP records.) + * It is mandatory by the SUSP standard + * (IEEE 1281). + * + * It allows SUSP to coexist with + * non-SUSP uses of the System + * Use Area by placing non-SUSP data + * before SUSP data. + * + * SP extension must be in the root + * directory entry, disable all SUSP + * processing if not found. + */ + iso9660->suspOffset = p[6]; + iso9660->seenSUSP = 1; + rr_start += 7; + } + } + if (iso9660->seenSUSP) { + int r; + + file->name_continues = 0; + file->symlink_continues = 0; + rr_start += iso9660->suspOffset; + r = parse_rockridge(a, file, rr_start, rr_end); + if (r != ARCHIVE_OK) + goto fail; + /* + * A file size of symbolic link files in ISO images + * made by makefs is not zero and its location is + * the same as those of next regular file. That is + * the same as hard like file and it causes unexpected + * error. + */ + if (file->size > 0 && + (file->mode & AE_IFMT) == AE_IFLNK) { + file->size = 0; + file->number = -1; + file->offset = -1; + } + } else + /* If there isn't SUSP, disable parsing + * rock ridge extensions. */ + iso9660->opt_support_rockridge = 0; + } + + file->nlinks = 1;/* Reset nlink. we'll calculate it later. */ + /* Tell file's parent how many children that parent has. */ + if (parent != NULL && (flags & 0x02)) + parent->subdirs++; + + if (iso9660->seenRockridge) { + if (parent != NULL && parent->parent == NULL && + (flags & 0x02) && iso9660->rr_moved == NULL && + file->name.s && + (strcmp(file->name.s, "rr_moved") == 0 || + strcmp(file->name.s, ".rr_moved") == 0)) { + iso9660->rr_moved = file; + file->rr_moved = 1; + file->rr_moved_has_re_only = 1; + file->re = 0; + parent->subdirs--; + } else if (file->re) { + /* + * Sanity check: file's parent is rr_moved. + */ + if (parent == NULL || parent->rr_moved == 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Invalid Rockridge RE"); + goto fail; + } + /* + * Sanity check: file does not have "CL" extension. + */ + if (file->cl_offset) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Invalid Rockridge RE and CL"); + goto fail; + } + /* + * Sanity check: The file type must be a directory. + */ + if ((flags & 0x02) == 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Invalid Rockridge RE"); + goto fail; + } + } else if (parent != NULL && parent->rr_moved) + file->rr_moved_has_re_only = 0; + else if (parent != NULL && (flags & 0x02) && + (parent->re || parent->re_descendant)) + file->re_descendant = 1; + if (file->cl_offset) { + struct file_info *r; + + if (parent == NULL || parent->parent == NULL) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Invalid Rockridge CL"); + goto fail; + } + /* + * Sanity check: The file type must be a regular file. + */ + if ((flags & 0x02) != 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Invalid Rockridge CL"); + goto fail; + } + parent->subdirs++; + /* Overwrite an offset and a number of this "CL" entry + * to appear before other dirs. "+1" to those is to + * make sure to appear after "RE" entry which this + * "CL" entry should be connected with. */ + file->offset = file->number = file->cl_offset + 1; + + /* + * Sanity check: cl_offset does not point at its + * the parents or itself. + */ + for (r = parent; r; r = r->parent) { + if (r->offset == file->cl_offset) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Invalid Rockridge CL"); + goto fail; + } + } + if (file->cl_offset == file->offset || + parent->rr_moved) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Invalid Rockridge CL"); + goto fail; + } + } + } + +#if DEBUG + /* DEBUGGING: Warn about attributes I don't yet fully support. */ + if ((flags & ~0x02) != 0) { + fprintf(stderr, "\n ** Unrecognized flag: "); + dump_isodirrec(stderr, isodirrec); + fprintf(stderr, "\n"); + } else if (toi(isodirrec + DR_volume_sequence_number_offset, 2) != 1) { + fprintf(stderr, "\n ** Unrecognized sequence number: "); + dump_isodirrec(stderr, isodirrec); + fprintf(stderr, "\n"); + } else if (*(isodirrec + DR_file_unit_size_offset) != 0) { + fprintf(stderr, "\n ** Unexpected file unit size: "); + dump_isodirrec(stderr, isodirrec); + fprintf(stderr, "\n"); + } else if (*(isodirrec + DR_interleave_offset) != 0) { + fprintf(stderr, "\n ** Unexpected interleave: "); + dump_isodirrec(stderr, isodirrec); + fprintf(stderr, "\n"); + } else if (*(isodirrec + DR_ext_attr_length_offset) != 0) { + fprintf(stderr, "\n ** Unexpected extended attribute length: "); + dump_isodirrec(stderr, isodirrec); + fprintf(stderr, "\n"); + } +#endif + register_file(iso9660, file); + return (file); +fail: + archive_string_free(&file->name); + free(file); + return (NULL); +} + +static int +parse_rockridge(struct archive_read *a, struct file_info *file, + const unsigned char *p, const unsigned char *end) +{ + struct iso9660 *iso9660; + int entry_seen = 0; + + iso9660 = (struct iso9660 *)(a->format->data); + + while (p + 4 <= end /* Enough space for another entry. */ + && p[0] >= 'A' && p[0] <= 'Z' /* Sanity-check 1st char of name. */ + && p[1] >= 'A' && p[1] <= 'Z' /* Sanity-check 2nd char of name. */ + && p[2] >= 4 /* Sanity-check length. */ + && p + p[2] <= end) { /* Sanity-check length. */ + const unsigned char *data = p + 4; + int data_length = p[2] - 4; + int version = p[3]; + + switch(p[0]) { + case 'C': + if (p[1] == 'E') { + if (version == 1 && data_length == 24) { + /* + * CE extension comprises: + * 8 byte sector containing extension + * 8 byte offset w/in above sector + * 8 byte length of continuation + */ + int32_t location = + archive_le32dec(data); + file->ce_offset = + archive_le32dec(data+8); + file->ce_size = + archive_le32dec(data+16); + if (register_CE(a, location, file) + != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + } + else if (p[1] == 'L') { + if (version == 1 && data_length == 8) { + file->cl_offset = (uint64_t) + iso9660->logical_block_size * + (uint64_t)archive_le32dec(data); + iso9660->seenRockridge = 1; + } + } + break; + case 'N': + if (p[1] == 'M') { + if (version == 1) { + parse_rockridge_NM1(file, + data, data_length); + iso9660->seenRockridge = 1; + } + } + break; + case 'P': + /* + * PD extension is padding; + * contents are always ignored. + * + * PL extension won't appear; + * contents are always ignored. + */ + if (p[1] == 'N') { + if (version == 1 && data_length == 16) { + file->rdev = toi(data,4); + file->rdev <<= 32; + file->rdev |= toi(data + 8, 4); + iso9660->seenRockridge = 1; + } + } + else if (p[1] == 'X') { + /* + * PX extension comprises: + * 8 bytes for mode, + * 8 bytes for nlinks, + * 8 bytes for uid, + * 8 bytes for gid, + * 8 bytes for inode. + */ + if (version == 1) { + if (data_length >= 8) + file->mode + = toi(data, 4); + if (data_length >= 16) + file->nlinks + = toi(data + 8, 4); + if (data_length >= 24) + file->uid + = toi(data + 16, 4); + if (data_length >= 32) + file->gid + = toi(data + 24, 4); + if (data_length >= 40) + file->number + = toi(data + 32, 4); + iso9660->seenRockridge = 1; + } + } + break; + case 'R': + if (p[1] == 'E' && version == 1) { + file->re = 1; + iso9660->seenRockridge = 1; + } + else if (p[1] == 'R' && version == 1) { + /* + * RR extension comprises: + * one byte flag value + * This extension is obsolete, + * so contents are always ignored. + */ + } + break; + case 'S': + if (p[1] == 'L') { + if (version == 1) { + parse_rockridge_SL1(file, + data, data_length); + iso9660->seenRockridge = 1; + } + } + else if (p[1] == 'T' + && data_length == 0 && version == 1) { + /* + * ST extension marks end of this + * block of SUSP entries. + * + * It allows SUSP to coexist with + * non-SUSP uses of the System + * Use Area by placing non-SUSP data + * after SUSP data. + */ + iso9660->seenSUSP = 0; + iso9660->seenRockridge = 0; + return (ARCHIVE_OK); + } + break; + case 'T': + if (p[1] == 'F') { + if (version == 1) { + parse_rockridge_TF1(file, + data, data_length); + iso9660->seenRockridge = 1; + } + } + break; + case 'Z': + if (p[1] == 'F') { + if (version == 1) + parse_rockridge_ZF1(file, + data, data_length); + } + break; + default: + break; + } + + p += p[2]; + entry_seen = 1; + } + + if (entry_seen) + return (ARCHIVE_OK); + else { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Tried to parse Rockridge extensions, but none found"); + return (ARCHIVE_WARN); + } +} + +static int +register_CE(struct archive_read *a, int32_t location, + struct file_info *file) +{ + struct iso9660 *iso9660; + struct read_ce_queue *heap; + struct read_ce_req *p; + uint64_t offset, parent_offset; + int hole, parent; + + iso9660 = (struct iso9660 *)(a->format->data); + offset = ((uint64_t)location) * (uint64_t)iso9660->logical_block_size; + if (((file->mode & AE_IFMT) == AE_IFREG && + offset >= file->offset) || + offset < iso9660->current_position || + (((uint64_t)file->ce_offset) + file->ce_size) + > (uint64_t)iso9660->logical_block_size || + offset + file->ce_offset + file->ce_size + > iso9660->volume_size) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid parameter in SUSP \"CE\" extension"); + return (ARCHIVE_FATAL); + } + + /* Expand our CE list as necessary. */ + heap = &(iso9660->read_ce_req); + if (heap->cnt >= heap->allocated) { + int new_size; + + if (heap->allocated < 16) + new_size = 16; + else + new_size = heap->allocated * 2; + /* Overflow might keep us from growing the list. */ + if (new_size <= heap->allocated) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + p = calloc(new_size, sizeof(p[0])); + if (p == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + if (heap->reqs != NULL) { + memcpy(p, heap->reqs, heap->cnt * sizeof(*p)); + free(heap->reqs); + } + heap->reqs = p; + heap->allocated = new_size; + } + + /* + * Start with hole at end, walk it up tree to find insertion point. + */ + hole = heap->cnt++; + while (hole > 0) { + parent = (hole - 1)/2; + parent_offset = heap->reqs[parent].offset; + if (offset >= parent_offset) { + heap->reqs[hole].offset = offset; + heap->reqs[hole].file = file; + return (ARCHIVE_OK); + } + /* Move parent into hole <==> move hole up tree. */ + heap->reqs[hole] = heap->reqs[parent]; + hole = parent; + } + heap->reqs[0].offset = offset; + heap->reqs[0].file = file; + return (ARCHIVE_OK); +} + +static void +next_CE(struct read_ce_queue *heap) +{ + uint64_t a_offset, b_offset, c_offset; + int a, b, c; + struct read_ce_req tmp; + + if (heap->cnt < 1) + return; + + /* + * Move the last item in the heap to the root of the tree + */ + heap->reqs[0] = heap->reqs[--(heap->cnt)]; + + /* + * Rebalance the heap. + */ + a = 0; /* Starting element and its offset */ + a_offset = heap->reqs[a].offset; + for (;;) { + b = a + a + 1; /* First child */ + if (b >= heap->cnt) + return; + b_offset = heap->reqs[b].offset; + c = b + 1; /* Use second child if it is smaller. */ + if (c < heap->cnt) { + c_offset = heap->reqs[c].offset; + if (c_offset < b_offset) { + b = c; + b_offset = c_offset; + } + } + if (a_offset <= b_offset) + return; + tmp = heap->reqs[a]; + heap->reqs[a] = heap->reqs[b]; + heap->reqs[b] = tmp; + a = b; + } +} + + +static int +read_CE(struct archive_read *a, struct iso9660 *iso9660) +{ + struct read_ce_queue *heap; + const unsigned char *b, *p, *end; + struct file_info *file; + size_t step; + int r; + + /* Read data which RRIP "CE" extension points. */ + heap = &(iso9660->read_ce_req); + step = iso9660->logical_block_size; + while (heap->cnt && + heap->reqs[0].offset == iso9660->current_position) { + b = __archive_read_ahead(a, step, NULL); + if (b == NULL) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Failed to read full block when scanning " + "ISO9660 directory list"); + return (ARCHIVE_FATAL); + } + do { + file = heap->reqs[0].file; + if (file->ce_offset + file->ce_size > step) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Malformed CE information"); + return (ARCHIVE_FATAL); + } + p = b + file->ce_offset; + end = p + file->ce_size; + next_CE(heap); + r = parse_rockridge(a, file, p, end); + if (r != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } while (heap->cnt && + heap->reqs[0].offset == iso9660->current_position); + /* NOTE: Do not move this consume's code to front of + * do-while loop. Registration of nested CE extension + * might cause error because of current position. */ + __archive_read_consume(a, step); + iso9660->current_position += step; + } + return (ARCHIVE_OK); +} + +static void +parse_rockridge_NM1(struct file_info *file, + const unsigned char *data, int data_length) +{ + if (!file->name_continues) + archive_string_empty(&file->name); + file->name_continues = 0; + if (data_length < 1) + return; + /* + * NM version 1 extension comprises: + * 1 byte flag, value is one of: + * = 0: remainder is name + * = 1: remainder is name, next NM entry continues name + * = 2: "." + * = 4: ".." + * = 32: Implementation specific + * All other values are reserved. + */ + switch(data[0]) { + case 0: + if (data_length < 2) + return; + archive_strncat(&file->name, + (const char *)data + 1, data_length - 1); + break; + case 1: + if (data_length < 2) + return; + archive_strncat(&file->name, + (const char *)data + 1, data_length - 1); + file->name_continues = 1; + break; + case 2: + archive_strcat(&file->name, "."); + break; + case 4: + archive_strcat(&file->name, ".."); + break; + default: + return; + } + +} + +static void +parse_rockridge_TF1(struct file_info *file, const unsigned char *data, + int data_length) +{ + char flag; + /* + * TF extension comprises: + * one byte flag + * create time (optional) + * modify time (optional) + * access time (optional) + * attribute time (optional) + * Time format and presence of fields + * is controlled by flag bits. + */ + if (data_length < 1) + return; + flag = data[0]; + ++data; + --data_length; + if (flag & 0x80) { + /* Use 17-byte time format. */ + if ((flag & 1) && data_length >= 17) { + /* Create time. */ + file->birthtime_is_set = 1; + file->birthtime = isodate17(data); + data += 17; + data_length -= 17; + } + if ((flag & 2) && data_length >= 17) { + /* Modify time. */ + file->mtime = isodate17(data); + data += 17; + data_length -= 17; + } + if ((flag & 4) && data_length >= 17) { + /* Access time. */ + file->atime = isodate17(data); + data += 17; + data_length -= 17; + } + if ((flag & 8) && data_length >= 17) { + /* Attribute change time. */ + file->ctime = isodate17(data); + } + } else { + /* Use 7-byte time format. */ + if ((flag & 1) && data_length >= 7) { + /* Create time. */ + file->birthtime_is_set = 1; + file->birthtime = isodate7(data); + data += 7; + data_length -= 7; + } + if ((flag & 2) && data_length >= 7) { + /* Modify time. */ + file->mtime = isodate7(data); + data += 7; + data_length -= 7; + } + if ((flag & 4) && data_length >= 7) { + /* Access time. */ + file->atime = isodate7(data); + data += 7; + data_length -= 7; + } + if ((flag & 8) && data_length >= 7) { + /* Attribute change time. */ + file->ctime = isodate7(data); + } + } +} + +static void +parse_rockridge_SL1(struct file_info *file, const unsigned char *data, + int data_length) +{ + const char *separator = ""; + + if (!file->symlink_continues || file->symlink.length < 1) + archive_string_empty(&file->symlink); + file->symlink_continues = 0; + + /* + * Defined flag values: + * 0: This is the last SL record for this symbolic link + * 1: this symbolic link field continues in next SL entry + * All other values are reserved. + */ + if (data_length < 1) + return; + switch(*data) { + case 0: + break; + case 1: + file->symlink_continues = 1; + break; + default: + return; + } + ++data; /* Skip flag byte. */ + --data_length; + + /* + * SL extension body stores "components". + * Basically, this is a complicated way of storing + * a POSIX path. It also interferes with using + * symlinks for storing non-path data. + * + * Each component is 2 bytes (flag and length) + * possibly followed by name data. + */ + while (data_length >= 2) { + unsigned char flag = *data++; + unsigned char nlen = *data++; + data_length -= 2; + + archive_strcat(&file->symlink, separator); + separator = "/"; + + switch(flag) { + case 0: /* Usual case, this is text. */ + if (data_length < nlen) + return; + archive_strncat(&file->symlink, + (const char *)data, nlen); + break; + case 0x01: /* Text continues in next component. */ + if (data_length < nlen) + return; + archive_strncat(&file->symlink, + (const char *)data, nlen); + separator = ""; + break; + case 0x02: /* Current dir. */ + archive_strcat(&file->symlink, "."); + break; + case 0x04: /* Parent dir. */ + archive_strcat(&file->symlink, ".."); + break; + case 0x08: /* Root of filesystem. */ + archive_strcat(&file->symlink, "/"); + separator = ""; + break; + case 0x10: /* Undefined (historically "volume root" */ + archive_string_empty(&file->symlink); + archive_strcat(&file->symlink, "ROOT"); + break; + case 0x20: /* Undefined (historically "hostname") */ + archive_strcat(&file->symlink, "hostname"); + break; + default: + /* TODO: issue a warning ? */ + return; + } + data += nlen; + data_length -= nlen; + } +} + +static void +parse_rockridge_ZF1(struct file_info *file, const unsigned char *data, + int data_length) +{ + + if (data[0] == 0x70 && data[1] == 0x7a && data_length == 12) { + /* paged zlib */ + file->pz = 1; + file->pz_log2_bs = data[3]; + file->pz_uncompressed_size = archive_le32dec(&data[4]); + } +} + +static void +register_file(struct iso9660 *iso9660, struct file_info *file) +{ + + file->use_next = iso9660->use_files; + iso9660->use_files = file; +} + +static void +release_files(struct iso9660 *iso9660) +{ + struct content *con, *connext; + struct file_info *file; + + file = iso9660->use_files; + while (file != NULL) { + struct file_info *next = file->use_next; + + archive_string_free(&file->name); + archive_string_free(&file->symlink); + free(file->utf16be_name); + con = file->contents.first; + while (con != NULL) { + connext = con->next; + free(con); + con = connext; + } + free(file); + file = next; + } +} + +static int +next_entry_seek(struct archive_read *a, struct iso9660 *iso9660, + struct file_info **pfile) +{ + struct file_info *file; + int r; + + r = next_cache_entry(a, iso9660, pfile); + if (r != ARCHIVE_OK) + return (r); + file = *pfile; + + /* Don't waste time seeking for zero-length bodies. */ + if (file->size == 0) + file->offset = iso9660->current_position; + + /* flush any remaining bytes from the last round to ensure + * we're positioned */ + if (iso9660->entry_bytes_unconsumed) { + __archive_read_consume(a, iso9660->entry_bytes_unconsumed); + iso9660->entry_bytes_unconsumed = 0; + } + + /* Seek forward to the start of the entry. */ + if (iso9660->current_position < file->offset) { + int64_t step; + + step = file->offset - iso9660->current_position; + step = __archive_read_consume(a, step); + if (step < 0) + return ((int)step); + iso9660->current_position = file->offset; + } + + /* We found body of file; handle it now. */ + return (ARCHIVE_OK); +} + +static int +next_cache_entry(struct archive_read *a, struct iso9660 *iso9660, + struct file_info **pfile) +{ + struct file_info *file; + struct { + struct file_info *first; + struct file_info **last; + } empty_files; + int64_t number; + int count; + + file = cache_get_entry(iso9660); + if (file != NULL) { + *pfile = file; + return (ARCHIVE_OK); + } + + for (;;) { + struct file_info *re, *d; + + *pfile = file = next_entry(iso9660); + if (file == NULL) { + /* + * If directory entries all which are descendant of + * rr_moved are still remaining, expose their. + */ + if (iso9660->re_files.first != NULL && + iso9660->rr_moved != NULL && + iso9660->rr_moved->rr_moved_has_re_only) + /* Expose "rr_moved" entry. */ + cache_add_entry(iso9660, iso9660->rr_moved); + while ((re = re_get_entry(iso9660)) != NULL) { + /* Expose its descendant dirs. */ + while ((d = rede_get_entry(re)) != NULL) + cache_add_entry(iso9660, d); + } + if (iso9660->cache_files.first != NULL) + return (next_cache_entry(a, iso9660, pfile)); + return (ARCHIVE_EOF); + } + + if (file->cl_offset) { + struct file_info *first_re = NULL; + int nexted_re = 0; + + /* + * Find "RE" dir for the current file, which + * has "CL" flag. + */ + while ((re = re_get_entry(iso9660)) + != first_re) { + if (first_re == NULL) + first_re = re; + if (re->offset == file->cl_offset) { + re->parent->subdirs--; + re->parent = file->parent; + re->re = 0; + if (re->parent->re_descendant) { + nexted_re = 1; + re->re_descendant = 1; + if (rede_add_entry(re) < 0) + goto fatal_rr; + /* Move a list of descendants + * to a new ancestor. */ + while ((d = rede_get_entry( + re)) != NULL) + if (rede_add_entry(d) + < 0) + goto fatal_rr; + break; + } + /* Replace the current file + * with "RE" dir */ + *pfile = file = re; + /* Expose its descendant */ + while ((d = rede_get_entry( + file)) != NULL) + cache_add_entry( + iso9660, d); + break; + } else + re_add_entry(iso9660, re); + } + if (nexted_re) { + /* + * Do not expose this at this time + * because we have not gotten its full-path + * name yet. + */ + continue; + } + } else if ((file->mode & AE_IFMT) == AE_IFDIR) { + int r; + + /* Read file entries in this dir. */ + r = read_children(a, file); + if (r != ARCHIVE_OK) + return (r); + + /* + * Handle a special dir of Rockridge extensions, + * "rr_moved". + */ + if (file->rr_moved) { + /* + * If this has only the subdirectories which + * have "RE" flags, do not expose at this time. + */ + if (file->rr_moved_has_re_only) + continue; + /* Otherwise expose "rr_moved" entry. */ + } else if (file->re) { + /* + * Do not expose this at this time + * because we have not gotten its full-path + * name yet. + */ + re_add_entry(iso9660, file); + continue; + } else if (file->re_descendant) { + /* + * If the top level "RE" entry of this entry + * is not exposed, we, accordingly, should not + * expose this entry at this time because + * we cannot make its proper full-path name. + */ + if (rede_add_entry(file) == 0) + continue; + /* Otherwise we can expose this entry because + * it seems its top level "RE" has already been + * exposed. */ + } + } + break; + } + + if ((file->mode & AE_IFMT) != AE_IFREG || file->number == -1) + return (ARCHIVE_OK); + + count = 0; + number = file->number; + iso9660->cache_files.first = NULL; + iso9660->cache_files.last = &(iso9660->cache_files.first); + empty_files.first = NULL; + empty_files.last = &empty_files.first; + /* Collect files which has the same file serial number. + * Peek pending_files so that file which number is different + * is not put back. */ + while (iso9660->pending_files.used > 0 && + (iso9660->pending_files.files[0]->number == -1 || + iso9660->pending_files.files[0]->number == number)) { + if (file->number == -1) { + /* This file has the same offset + * but it's wrong offset which empty files + * and symlink files have. + * NOTE: This wrong offset was recorded by + * old mkisofs utility. If ISO images is + * created by latest mkisofs, this does not + * happen. + */ + file->next = NULL; + *empty_files.last = file; + empty_files.last = &(file->next); + } else { + count++; + cache_add_entry(iso9660, file); + } + file = next_entry(iso9660); + } + + if (count == 0) { + *pfile = file; + return ((file == NULL)?ARCHIVE_EOF:ARCHIVE_OK); + } + if (file->number == -1) { + file->next = NULL; + *empty_files.last = file; + empty_files.last = &(file->next); + } else { + count++; + cache_add_entry(iso9660, file); + } + + if (count > 1) { + /* The count is the same as number of hardlink, + * so much so that each nlinks of files in cache_file + * is overwritten by value of the count. + */ + for (file = iso9660->cache_files.first; + file != NULL; file = file->next) + file->nlinks = count; + } + /* If there are empty files, that files are added + * to the tail of the cache_files. */ + if (empty_files.first != NULL) { + *iso9660->cache_files.last = empty_files.first; + iso9660->cache_files.last = empty_files.last; + } + *pfile = cache_get_entry(iso9660); + return ((*pfile == NULL)?ARCHIVE_EOF:ARCHIVE_OK); + +fatal_rr: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to connect 'CL' pointer to 'RE' rr_moved pointer of " + "Rockridge extensions: current position = %jd, CL offset = %jd", + (intmax_t)iso9660->current_position, (intmax_t)file->cl_offset); + return (ARCHIVE_FATAL); +} + +static inline void +re_add_entry(struct iso9660 *iso9660, struct file_info *file) +{ + file->re_next = NULL; + *iso9660->re_files.last = file; + iso9660->re_files.last = &(file->re_next); +} + +static inline struct file_info * +re_get_entry(struct iso9660 *iso9660) +{ + struct file_info *file; + + if ((file = iso9660->re_files.first) != NULL) { + iso9660->re_files.first = file->re_next; + if (iso9660->re_files.first == NULL) + iso9660->re_files.last = + &(iso9660->re_files.first); + } + return (file); +} + +static inline int +rede_add_entry(struct file_info *file) +{ + struct file_info *re; + + /* + * Find "RE" entry. + */ + re = file->parent; + while (re != NULL && !re->re) + re = re->parent; + if (re == NULL) + return (-1); + + file->re_next = NULL; + *re->rede_files.last = file; + re->rede_files.last = &(file->re_next); + return (0); +} + +static inline struct file_info * +rede_get_entry(struct file_info *re) +{ + struct file_info *file; + + if ((file = re->rede_files.first) != NULL) { + re->rede_files.first = file->re_next; + if (re->rede_files.first == NULL) + re->rede_files.last = + &(re->rede_files.first); + } + return (file); +} + +static inline void +cache_add_entry(struct iso9660 *iso9660, struct file_info *file) +{ + file->next = NULL; + *iso9660->cache_files.last = file; + iso9660->cache_files.last = &(file->next); +} + +static inline struct file_info * +cache_get_entry(struct iso9660 *iso9660) +{ + struct file_info *file; + + if ((file = iso9660->cache_files.first) != NULL) { + iso9660->cache_files.first = file->next; + if (iso9660->cache_files.first == NULL) + iso9660->cache_files.last = + &(iso9660->cache_files.first); + } + return (file); +} + +static int +heap_add_entry(struct archive_read *a, struct heap_queue *heap, + struct file_info *file, uint64_t key) +{ + uint64_t file_key, parent_key; + int hole, parent; + + /* Expand our pending files list as necessary. */ + if (heap->used >= heap->allocated) { + struct file_info **new_pending_files; + int new_size = heap->allocated * 2; + + if (heap->allocated < 1024) + new_size = 1024; + /* Overflow might keep us from growing the list. */ + if (new_size <= heap->allocated) { + archive_set_error(&a->archive, + ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + new_pending_files = (struct file_info **) + malloc(new_size * sizeof(new_pending_files[0])); + if (new_pending_files == NULL) { + archive_set_error(&a->archive, + ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + if (heap->allocated) + memcpy(new_pending_files, heap->files, + heap->allocated * sizeof(new_pending_files[0])); + free(heap->files); + heap->files = new_pending_files; + heap->allocated = new_size; + } + + file_key = file->key = key; + + /* + * Start with hole at end, walk it up tree to find insertion point. + */ + hole = heap->used++; + while (hole > 0) { + parent = (hole - 1)/2; + parent_key = heap->files[parent]->key; + if (file_key >= parent_key) { + heap->files[hole] = file; + return (ARCHIVE_OK); + } + /* Move parent into hole <==> move hole up tree. */ + heap->files[hole] = heap->files[parent]; + hole = parent; + } + heap->files[0] = file; + + return (ARCHIVE_OK); +} + +static struct file_info * +heap_get_entry(struct heap_queue *heap) +{ + uint64_t a_key, b_key, c_key; + int a, b, c; + struct file_info *r, *tmp; + + if (heap->used < 1) + return (NULL); + + /* + * The first file in the list is the earliest; we'll return this. + */ + r = heap->files[0]; + + /* + * Move the last item in the heap to the root of the tree + */ + heap->files[0] = heap->files[--(heap->used)]; + + /* + * Rebalance the heap. + */ + a = 0; /* Starting element and its heap key */ + a_key = heap->files[a]->key; + for (;;) { + b = a + a + 1; /* First child */ + if (b >= heap->used) + return (r); + b_key = heap->files[b]->key; + c = b + 1; /* Use second child if it is smaller. */ + if (c < heap->used) { + c_key = heap->files[c]->key; + if (c_key < b_key) { + b = c; + b_key = c_key; + } + } + if (a_key <= b_key) + return (r); + tmp = heap->files[a]; + heap->files[a] = heap->files[b]; + heap->files[b] = tmp; + a = b; + } +} + +static unsigned int +toi(const void *p, int n) +{ + const unsigned char *v = (const unsigned char *)p; + if (n > 1) + return v[0] + 256 * toi(v + 1, n - 1); + if (n == 1) + return v[0]; + return (0); +} + +static time_t +isodate7(const unsigned char *v) +{ + struct tm tm; + int offset; + time_t t; + + memset(&tm, 0, sizeof(tm)); + tm.tm_year = v[0]; + tm.tm_mon = v[1] - 1; + tm.tm_mday = v[2]; + tm.tm_hour = v[3]; + tm.tm_min = v[4]; + tm.tm_sec = v[5]; + /* v[6] is the signed timezone offset, in 1/4-hour increments. */ + offset = ((const signed char *)v)[6]; + if (offset > -48 && offset < 52) { + tm.tm_hour -= offset / 4; + tm.tm_min -= (offset % 4) * 15; + } + t = time_from_tm(&tm); + if (t == (time_t)-1) + return ((time_t)0); + return (t); +} + +static time_t +isodate17(const unsigned char *v) +{ + struct tm tm; + int offset; + time_t t; + + memset(&tm, 0, sizeof(tm)); + tm.tm_year = (v[0] - '0') * 1000 + (v[1] - '0') * 100 + + (v[2] - '0') * 10 + (v[3] - '0') + - 1900; + tm.tm_mon = (v[4] - '0') * 10 + (v[5] - '0'); + tm.tm_mday = (v[6] - '0') * 10 + (v[7] - '0'); + tm.tm_hour = (v[8] - '0') * 10 + (v[9] - '0'); + tm.tm_min = (v[10] - '0') * 10 + (v[11] - '0'); + tm.tm_sec = (v[12] - '0') * 10 + (v[13] - '0'); + /* v[16] is the signed timezone offset, in 1/4-hour increments. */ + offset = ((const signed char *)v)[16]; + if (offset > -48 && offset < 52) { + tm.tm_hour -= offset / 4; + tm.tm_min -= (offset % 4) * 15; + } + t = time_from_tm(&tm); + if (t == (time_t)-1) + return ((time_t)0); + return (t); +} + +static time_t +time_from_tm(struct tm *t) +{ +#if HAVE_TIMEGM + /* Use platform timegm() if available. */ + return (timegm(t)); +#elif HAVE__MKGMTIME64 + return (_mkgmtime64(t)); +#else + /* Else use direct calculation using POSIX assumptions. */ + /* First, fix up tm_yday based on the year/month/day. */ + if (mktime(t) == (time_t)-1) + return ((time_t)-1); + /* Then we can compute timegm() from first principles. */ + return (t->tm_sec + + t->tm_min * 60 + + t->tm_hour * 3600 + + t->tm_yday * 86400 + + (t->tm_year - 70) * 31536000 + + ((t->tm_year - 69) / 4) * 86400 + - ((t->tm_year - 1) / 100) * 86400 + + ((t->tm_year + 299) / 400) * 86400); +#endif +} + +static const char * +build_pathname(struct archive_string *as, struct file_info *file, int depth) +{ + // Plain ISO9660 only allows 8 dir levels; if we get + // to 1000, then something is very, very wrong. + if (depth > 1000) { + return NULL; + } + if (file->parent != NULL && archive_strlen(&file->parent->name) > 0) { + if (build_pathname(as, file->parent, depth + 1) == NULL) { + return NULL; + } + archive_strcat(as, "/"); + } + if (archive_strlen(&file->name) == 0) + archive_strcat(as, "."); + else + archive_string_concat(as, &file->name); + return (as->s); +} + +static int +build_pathname_utf16be(unsigned char *p, size_t max, size_t *len, + struct file_info *file) +{ + if (file->parent != NULL && file->parent->utf16be_bytes > 0) { + if (build_pathname_utf16be(p, max, len, file->parent) != 0) + return (-1); + p[*len] = 0; + p[*len + 1] = '/'; + *len += 2; + } + if (file->utf16be_bytes == 0) { + if (*len + 2 > max) + return (-1);/* Path is too long! */ + p[*len] = 0; + p[*len + 1] = '.'; + *len += 2; + } else { + if (*len + file->utf16be_bytes > max) + return (-1);/* Path is too long! */ + memcpy(p + *len, file->utf16be_name, file->utf16be_bytes); + *len += file->utf16be_bytes; + } + return (0); +} + +#if DEBUG +static void +dump_isodirrec(FILE *out, const unsigned char *isodirrec) +{ + fprintf(out, " l %d,", + toi(isodirrec + DR_length_offset, DR_length_size)); + fprintf(out, " a %d,", + toi(isodirrec + DR_ext_attr_length_offset, DR_ext_attr_length_size)); + fprintf(out, " ext 0x%x,", + toi(isodirrec + DR_extent_offset, DR_extent_size)); + fprintf(out, " s %d,", + toi(isodirrec + DR_size_offset, DR_extent_size)); + fprintf(out, " f 0x%x,", + toi(isodirrec + DR_flags_offset, DR_flags_size)); + fprintf(out, " u %d,", + toi(isodirrec + DR_file_unit_size_offset, DR_file_unit_size_size)); + fprintf(out, " ilv %d,", + toi(isodirrec + DR_interleave_offset, DR_interleave_size)); + fprintf(out, " seq %d,", + toi(isodirrec + DR_volume_sequence_number_offset, + DR_volume_sequence_number_size)); + fprintf(out, " nl %d:", + toi(isodirrec + DR_name_len_offset, DR_name_len_size)); + fprintf(out, " `%.*s'", + toi(isodirrec + DR_name_len_offset, DR_name_len_size), + isodirrec + DR_name_offset); +} +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_lha.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_lha.c new file mode 100644 index 0000000..bff0f01 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_lha.c @@ -0,0 +1,2912 @@ +/*- + * Copyright (c) 2008-2014 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_private.h" +#include "archive_read_private.h" +#include "archive_endian.h" + + +#define MAXMATCH 256 /* Maximum match length. */ +#define MINMATCH 3 /* Minimum match length. */ +/* + * Literal table format: + * +0 +256 +510 + * +---------------+-------------------------+ + * | literal code | match length | + * | 0 ... 255 | MINMATCH ... MAXMATCH | + * +---------------+-------------------------+ + * <--- LT_BITLEN_SIZE ---> + */ +/* Literal table size. */ +#define LT_BITLEN_SIZE (UCHAR_MAX + 1 + MAXMATCH - MINMATCH + 1) +/* Position table size. + * Note: this used for both position table and pre literal table.*/ +#define PT_BITLEN_SIZE (3 + 16) + +struct lzh_dec { + /* Decoding status. */ + int state; + + /* + * Window to see last 8Ki(lh5),32Ki(lh6),64Ki(lh7) bytes of decoded + * data. + */ + int w_size; + int w_mask; + /* Window buffer, which is a loop buffer. */ + unsigned char *w_buff; + /* The insert position to the window. */ + int w_pos; + /* The position where we can copy decoded code from the window. */ + int copy_pos; + /* The length how many bytes we can copy decoded code from + * the window. */ + int copy_len; + + /* + * Bit stream reader. + */ + struct lzh_br { +#define CACHE_TYPE uint64_t +#define CACHE_BITS (8 * sizeof(CACHE_TYPE)) + /* Cache buffer. */ + CACHE_TYPE cache_buffer; + /* Indicates how many bits avail in cache_buffer. */ + int cache_avail; + } br; + + /* + * Huffman coding. + */ + struct huffman { + int len_size; + int len_avail; + int len_bits; + int freq[17]; + unsigned char *bitlen; + + /* + * Use a index table. It's faster than searching a huffman + * coding tree, which is a binary tree. But a use of a large + * index table causes L1 cache read miss many times. + */ +#define HTBL_BITS 10 + int max_bits; + int shift_bits; + int tbl_bits; + int tree_used; + int tree_avail; + /* Direct access table. */ + uint16_t *tbl; + /* Binary tree table for extra bits over the direct access. */ + struct htree_t { + uint16_t left; + uint16_t right; + } *tree; + } lt, pt; + + int blocks_avail; + int pos_pt_len_size; + int pos_pt_len_bits; + int literal_pt_len_size; + int literal_pt_len_bits; + int reading_position; + int loop; + int error; +}; + +struct lzh_stream { + const unsigned char *next_in; + int avail_in; + int64_t total_in; + const unsigned char *ref_ptr; + int avail_out; + int64_t total_out; + struct lzh_dec *ds; +}; + +struct lha { + /* entry_bytes_remaining is the number of bytes we expect. */ + int64_t entry_offset; + int64_t entry_bytes_remaining; + int64_t entry_unconsumed; + uint16_t entry_crc_calculated; + + size_t header_size; /* header size */ + unsigned char level; /* header level */ + char method[3]; /* compress type */ + int64_t compsize; /* compressed data size */ + int64_t origsize; /* original file size */ + int setflag; +#define BIRTHTIME_IS_SET 1 +#define ATIME_IS_SET 2 +#define UNIX_MODE_IS_SET 4 +#define CRC_IS_SET 8 + time_t birthtime; + long birthtime_tv_nsec; + time_t mtime; + long mtime_tv_nsec; + time_t atime; + long atime_tv_nsec; + mode_t mode; + int64_t uid; + int64_t gid; + struct archive_string uname; + struct archive_string gname; + uint16_t header_crc; + uint16_t crc; + /* dirname and filename could be in different codepages */ + struct archive_string_conv *sconv_dir; + struct archive_string_conv *sconv_fname; + struct archive_string_conv *opt_sconv; + + struct archive_string dirname; + struct archive_string filename; + struct archive_wstring ws; + + unsigned char dos_attr; + + /* Flag to mark progress that an archive was read their first header.*/ + char found_first_header; + /* Flag to mark that indicates an empty directory. */ + char directory; + + /* Flags to mark progress of decompression. */ + char decompress_init; + char end_of_entry; + char end_of_entry_cleanup; + char entry_is_compressed; + + char format_name[64]; + + struct lzh_stream strm; +}; + +/* + * LHA header common member offset. + */ +#define H_METHOD_OFFSET 2 /* Compress type. */ +#define H_ATTR_OFFSET 19 /* DOS attribute. */ +#define H_LEVEL_OFFSET 20 /* Header Level. */ +#define H_SIZE 22 /* Minimum header size. */ + +static int archive_read_format_lha_bid(struct archive_read *, int); +static int archive_read_format_lha_options(struct archive_read *, + const char *, const char *); +static int archive_read_format_lha_read_header(struct archive_read *, + struct archive_entry *); +static int archive_read_format_lha_read_data(struct archive_read *, + const void **, size_t *, int64_t *); +static int archive_read_format_lha_read_data_skip(struct archive_read *); +static int archive_read_format_lha_cleanup(struct archive_read *); + +static void lha_replace_path_separator(struct lha *, + struct archive_entry *); +static int lha_read_file_header_0(struct archive_read *, struct lha *); +static int lha_read_file_header_1(struct archive_read *, struct lha *); +static int lha_read_file_header_2(struct archive_read *, struct lha *); +static int lha_read_file_header_3(struct archive_read *, struct lha *); +static int lha_read_file_extended_header(struct archive_read *, + struct lha *, uint16_t *, int, size_t, size_t *); +static size_t lha_check_header_format(const void *); +static int lha_skip_sfx(struct archive_read *); +static time_t lha_dos_time(const unsigned char *); +static time_t lha_win_time(uint64_t, long *); +static unsigned char lha_calcsum(unsigned char, const void *, + int, size_t); +static int lha_parse_linkname(struct archive_wstring *, + struct archive_wstring *); +static int lha_read_data_none(struct archive_read *, const void **, + size_t *, int64_t *); +static int lha_read_data_lzh(struct archive_read *, const void **, + size_t *, int64_t *); +static void lha_crc16_init(void); +static uint16_t lha_crc16(uint16_t, const void *, size_t); +static int lzh_decode_init(struct lzh_stream *, const char *); +static void lzh_decode_free(struct lzh_stream *); +static int lzh_decode(struct lzh_stream *, int); +static int lzh_br_fillup(struct lzh_stream *, struct lzh_br *); +static int lzh_huffman_init(struct huffman *, size_t, int); +static void lzh_huffman_free(struct huffman *); +static int lzh_read_pt_bitlen(struct lzh_stream *, int start, int end); +static int lzh_make_fake_table(struct huffman *, uint16_t); +static int lzh_make_huffman_table(struct huffman *); +static inline int lzh_decode_huffman(struct huffman *, unsigned); +static int lzh_decode_huffman_tree(struct huffman *, unsigned, int); + + +int +archive_read_support_format_lha(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct lha *lha; + int r; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_format_lha"); + + lha = (struct lha *)calloc(1, sizeof(*lha)); + if (lha == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate lha data"); + return (ARCHIVE_FATAL); + } + archive_string_init(&lha->ws); + + r = __archive_read_register_format(a, + lha, + "lha", + archive_read_format_lha_bid, + archive_read_format_lha_options, + archive_read_format_lha_read_header, + archive_read_format_lha_read_data, + archive_read_format_lha_read_data_skip, + NULL, + archive_read_format_lha_cleanup, + NULL, + NULL); + + if (r != ARCHIVE_OK) + free(lha); + return (ARCHIVE_OK); +} + +static size_t +lha_check_header_format(const void *h) +{ + const unsigned char *p = h; + size_t next_skip_bytes; + + switch (p[H_METHOD_OFFSET+3]) { + /* + * "-lh0-" ... "-lh7-" "-lhd-" + * "-lzs-" "-lz5-" + */ + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + case 'd': + case 's': + next_skip_bytes = 4; + + /* b0 == 0 means the end of an LHa archive file. */ + if (p[0] == 0) + break; + if (p[H_METHOD_OFFSET] != '-' || p[H_METHOD_OFFSET+1] != 'l' + || p[H_METHOD_OFFSET+4] != '-') + break; + + if (p[H_METHOD_OFFSET+2] == 'h') { + /* "-lh?-" */ + if (p[H_METHOD_OFFSET+3] == 's') + break; + if (p[H_LEVEL_OFFSET] == 0) + return (0); + if (p[H_LEVEL_OFFSET] <= 3 && p[H_ATTR_OFFSET] == 0x20) + return (0); + } + if (p[H_METHOD_OFFSET+2] == 'z') { + /* LArc extensions: -lzs-,-lz4- and -lz5- */ + if (p[H_LEVEL_OFFSET] != 0) + break; + if (p[H_METHOD_OFFSET+3] == 's' + || p[H_METHOD_OFFSET+3] == '4' + || p[H_METHOD_OFFSET+3] == '5') + return (0); + } + break; + case 'h': next_skip_bytes = 1; break; + case 'z': next_skip_bytes = 1; break; + case 'l': next_skip_bytes = 2; break; + case '-': next_skip_bytes = 3; break; + default : next_skip_bytes = 4; break; + } + + return (next_skip_bytes); +} + +static int +archive_read_format_lha_bid(struct archive_read *a, int best_bid) +{ + const char *p; + const void *buff; + ssize_t bytes_avail, offset, window; + size_t next; + + /* If there's already a better bid than we can ever + make, don't bother testing. */ + if (best_bid > 30) + return (-1); + + if ((p = __archive_read_ahead(a, H_SIZE, NULL)) == NULL) + return (-1); + + if (lha_check_header_format(p) == 0) + return (30); + + if (p[0] == 'M' && p[1] == 'Z') { + /* PE file */ + offset = 0; + window = 4096; + while (offset < (1024 * 20)) { + buff = __archive_read_ahead(a, offset + window, + &bytes_avail); + if (buff == NULL) { + /* Remaining bytes are less than window. */ + window >>= 1; + if (window < (H_SIZE + 3)) + return (0); + continue; + } + p = (const char *)buff + offset; + while (p + H_SIZE < (const char *)buff + bytes_avail) { + if ((next = lha_check_header_format(p)) == 0) + return (30); + p += next; + } + offset = p - (const char *)buff; + } + } + return (0); +} + +static int +archive_read_format_lha_options(struct archive_read *a, + const char *key, const char *val) +{ + struct lha *lha; + int ret = ARCHIVE_FAILED; + + lha = (struct lha *)(a->format->data); + if (strcmp(key, "hdrcharset") == 0) { + if (val == NULL || val[0] == 0) + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "lha: hdrcharset option needs a character-set name"); + else { + lha->opt_sconv = + archive_string_conversion_from_charset( + &a->archive, val, 0); + if (lha->opt_sconv != NULL) + ret = ARCHIVE_OK; + else + ret = ARCHIVE_FATAL; + } + return (ret); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +static int +lha_skip_sfx(struct archive_read *a) +{ + const void *h; + const char *p, *q; + size_t next, skip; + ssize_t bytes, window; + + window = 4096; + for (;;) { + h = __archive_read_ahead(a, window, &bytes); + if (h == NULL) { + /* Remaining bytes are less than window. */ + window >>= 1; + if (window < (H_SIZE + 3)) + goto fatal; + continue; + } + if (bytes < H_SIZE) + goto fatal; + p = h; + q = p + bytes; + + /* + * Scan ahead until we find something that looks + * like the lha header. + */ + while (p + H_SIZE < q) { + if ((next = lha_check_header_format(p)) == 0) { + skip = p - (const char *)h; + __archive_read_consume(a, skip); + return (ARCHIVE_OK); + } + p += next; + } + skip = p - (const char *)h; + __archive_read_consume(a, skip); + } +fatal: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Couldn't find out LHa header"); + return (ARCHIVE_FATAL); +} + +static int +truncated_error(struct archive_read *a) +{ + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated LHa header"); + return (ARCHIVE_FATAL); +} + +static int +archive_read_format_lha_read_header(struct archive_read *a, + struct archive_entry *entry) +{ + struct archive_wstring linkname; + struct archive_wstring pathname; + struct lha *lha; + const unsigned char *p; + const char *signature; + int err; + struct archive_mstring conv_buffer; + const wchar_t *conv_buffer_p; + + lha_crc16_init(); + + a->archive.archive_format = ARCHIVE_FORMAT_LHA; + if (a->archive.archive_format_name == NULL) + a->archive.archive_format_name = "lha"; + + lha = (struct lha *)(a->format->data); + lha->decompress_init = 0; + lha->end_of_entry = 0; + lha->end_of_entry_cleanup = 0; + lha->entry_unconsumed = 0; + + if ((p = __archive_read_ahead(a, H_SIZE, NULL)) == NULL) { + /* + * LHa archiver added 0 to the tail of its archive file as + * the mark of the end of the archive. + */ + signature = __archive_read_ahead(a, sizeof(signature[0]), NULL); + if (signature == NULL || signature[0] == 0) + return (ARCHIVE_EOF); + return (truncated_error(a)); + } + + signature = (const char *)p; + if (lha->found_first_header == 0 && + signature[0] == 'M' && signature[1] == 'Z') { + /* This is an executable? Must be self-extracting... */ + err = lha_skip_sfx(a); + if (err < ARCHIVE_WARN) + return (err); + + if ((p = __archive_read_ahead(a, sizeof(*p), NULL)) == NULL) + return (truncated_error(a)); + signature = (const char *)p; + } + /* signature[0] == 0 means the end of an LHa archive file. */ + if (signature[0] == 0) + return (ARCHIVE_EOF); + + /* + * Check the header format and method type. + */ + if (lha_check_header_format(p) != 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Bad LHa file"); + return (ARCHIVE_FATAL); + } + + /* We've found the first header. */ + lha->found_first_header = 1; + /* Set a default value and common data */ + lha->header_size = 0; + lha->level = p[H_LEVEL_OFFSET]; + lha->method[0] = p[H_METHOD_OFFSET+1]; + lha->method[1] = p[H_METHOD_OFFSET+2]; + lha->method[2] = p[H_METHOD_OFFSET+3]; + if (memcmp(lha->method, "lhd", 3) == 0) + lha->directory = 1; + else + lha->directory = 0; + if (memcmp(lha->method, "lh0", 3) == 0 || + memcmp(lha->method, "lz4", 3) == 0) + lha->entry_is_compressed = 0; + else + lha->entry_is_compressed = 1; + + lha->compsize = 0; + lha->origsize = 0; + lha->setflag = 0; + lha->birthtime = 0; + lha->birthtime_tv_nsec = 0; + lha->mtime = 0; + lha->mtime_tv_nsec = 0; + lha->atime = 0; + lha->atime_tv_nsec = 0; + lha->mode = (lha->directory)? 0777 : 0666; + lha->uid = 0; + lha->gid = 0; + archive_string_empty(&lha->dirname); + archive_string_empty(&lha->filename); + lha->dos_attr = 0; + if (lha->opt_sconv != NULL) { + lha->sconv_dir = lha->opt_sconv; + lha->sconv_fname = lha->opt_sconv; + } else { + lha->sconv_dir = NULL; + lha->sconv_fname = NULL; + } + + switch (p[H_LEVEL_OFFSET]) { + case 0: + err = lha_read_file_header_0(a, lha); + break; + case 1: + err = lha_read_file_header_1(a, lha); + break; + case 2: + err = lha_read_file_header_2(a, lha); + break; + case 3: + err = lha_read_file_header_3(a, lha); + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Unsupported LHa header level %d", p[H_LEVEL_OFFSET]); + err = ARCHIVE_FATAL; + break; + } + if (err < ARCHIVE_WARN) + return (err); + + + if (!lha->directory && archive_strlen(&lha->filename) == 0) + /* The filename has not been set */ + return (truncated_error(a)); + + /* + * Make a pathname from a dirname and a filename, after converting to Unicode. + * This is because codepages might differ between dirname and filename. + */ + archive_string_init(&pathname); + archive_string_init(&linkname); + archive_string_init(&conv_buffer.aes_mbs); + archive_string_init(&conv_buffer.aes_mbs_in_locale); + archive_string_init(&conv_buffer.aes_utf8); + archive_string_init(&conv_buffer.aes_wcs); + if (0 != archive_mstring_copy_mbs_len_l(&conv_buffer, lha->dirname.s, lha->dirname.length, lha->sconv_dir)) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Pathname cannot be converted " + "from %s to Unicode.", + archive_string_conversion_charset_name(lha->sconv_dir)); + err = ARCHIVE_FATAL; + } else if (0 != archive_mstring_get_wcs(&a->archive, &conv_buffer, &conv_buffer_p)) + err = ARCHIVE_FATAL; + if (err == ARCHIVE_FATAL) { + archive_mstring_clean(&conv_buffer); + archive_wstring_free(&pathname); + archive_wstring_free(&linkname); + return (err); + } + archive_wstring_copy(&pathname, &conv_buffer.aes_wcs); + + archive_string_empty(&conv_buffer.aes_mbs); + archive_string_empty(&conv_buffer.aes_mbs_in_locale); + archive_string_empty(&conv_buffer.aes_utf8); + archive_wstring_empty(&conv_buffer.aes_wcs); + if (0 != archive_mstring_copy_mbs_len_l(&conv_buffer, lha->filename.s, lha->filename.length, lha->sconv_fname)) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Pathname cannot be converted " + "from %s to Unicode.", + archive_string_conversion_charset_name(lha->sconv_fname)); + err = ARCHIVE_FATAL; + } + else if (0 != archive_mstring_get_wcs(&a->archive, &conv_buffer, &conv_buffer_p)) + err = ARCHIVE_FATAL; + if (err == ARCHIVE_FATAL) { + archive_mstring_clean(&conv_buffer); + archive_wstring_free(&pathname); + archive_wstring_free(&linkname); + return (err); + } + archive_wstring_concat(&pathname, &conv_buffer.aes_wcs); + archive_mstring_clean(&conv_buffer); + + if ((lha->mode & AE_IFMT) == AE_IFLNK) { + /* + * Extract the symlink-name if it's included in the pathname. + */ + if (!lha_parse_linkname(&linkname, &pathname)) { + /* We couldn't get the symlink-name. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Unknown symlink-name"); + archive_wstring_free(&pathname); + archive_wstring_free(&linkname); + return (ARCHIVE_FAILED); + } + } else { + /* + * Make sure a file-type is set. + * The mode has been overridden if it is in the extended data. + */ + lha->mode = (lha->mode & ~AE_IFMT) | + ((lha->directory)? AE_IFDIR: AE_IFREG); + } + if ((lha->setflag & UNIX_MODE_IS_SET) == 0 && + (lha->dos_attr & 1) != 0) + lha->mode &= ~(0222);/* read only. */ + + /* + * Set basic file parameters. + */ + archive_entry_copy_pathname_w(entry, pathname.s); + archive_wstring_free(&pathname); + if (archive_strlen(&linkname) > 0) { + archive_entry_copy_symlink_w(entry, linkname.s); + } else + archive_entry_set_symlink(entry, NULL); + archive_wstring_free(&linkname); + /* + * When a header level is 0, there is a possibility that + * a pathname and a symlink has '\' character, a directory + * separator in DOS/Windows. So we should convert it to '/'. + */ + if (p[H_LEVEL_OFFSET] == 0) + lha_replace_path_separator(lha, entry); + + archive_entry_set_mode(entry, lha->mode); + archive_entry_set_uid(entry, lha->uid); + archive_entry_set_gid(entry, lha->gid); + if (archive_strlen(&lha->uname) > 0) + archive_entry_set_uname(entry, lha->uname.s); + if (archive_strlen(&lha->gname) > 0) + archive_entry_set_gname(entry, lha->gname.s); + if (lha->setflag & BIRTHTIME_IS_SET) { + archive_entry_set_birthtime(entry, lha->birthtime, + lha->birthtime_tv_nsec); + archive_entry_set_ctime(entry, lha->birthtime, + lha->birthtime_tv_nsec); + } else { + archive_entry_unset_birthtime(entry); + archive_entry_unset_ctime(entry); + } + archive_entry_set_mtime(entry, lha->mtime, lha->mtime_tv_nsec); + if (lha->setflag & ATIME_IS_SET) + archive_entry_set_atime(entry, lha->atime, + lha->atime_tv_nsec); + else + archive_entry_unset_atime(entry); + if (lha->directory || archive_entry_symlink(entry) != NULL) + archive_entry_unset_size(entry); + else + archive_entry_set_size(entry, lha->origsize); + + /* + * Prepare variables used to read a file content. + */ + lha->entry_bytes_remaining = lha->compsize; + if (lha->entry_bytes_remaining < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid LHa entry size"); + return (ARCHIVE_FATAL); + } + lha->entry_offset = 0; + lha->entry_crc_calculated = 0; + + /* + * This file does not have a content. + */ + if (lha->directory || lha->compsize == 0) + lha->end_of_entry = 1; + + sprintf(lha->format_name, "lha -%c%c%c-", + lha->method[0], lha->method[1], lha->method[2]); + a->archive.archive_format_name = lha->format_name; + + return (err); +} + +/* + * Replace a DOS path separator '\' by a character '/'. + * Some multi-byte character set have a character '\' in its second byte. + */ +static void +lha_replace_path_separator(struct lha *lha, struct archive_entry *entry) +{ + const wchar_t *wp; + size_t i; + + if ((wp = archive_entry_pathname_w(entry)) != NULL) { + archive_wstrcpy(&(lha->ws), wp); + for (i = 0; i < archive_strlen(&(lha->ws)); i++) { + if (lha->ws.s[i] == L'\\') + lha->ws.s[i] = L'/'; + } + archive_entry_copy_pathname_w(entry, lha->ws.s); + } + + if ((wp = archive_entry_symlink_w(entry)) != NULL) { + archive_wstrcpy(&(lha->ws), wp); + for (i = 0; i < archive_strlen(&(lha->ws)); i++) { + if (lha->ws.s[i] == L'\\') + lha->ws.s[i] = L'/'; + } + archive_entry_copy_symlink_w(entry, lha->ws.s); + } +} + +/* + * Header 0 format + * + * +0 +1 +2 +7 +11 + * +---------------+----------+----------------+-------------------+ + * |header size(*1)|header sum|compression type|compressed size(*2)| + * +---------------+----------+----------------+-------------------+ + * <---------------------(*1)----------* + * + * +11 +15 +17 +19 +20 +21 + * +-----------------+---------+---------+--------------+----------------+ + * |uncompressed size|time(DOS)|date(DOS)|attribute(DOS)|header level(=0)| + * +-----------------+---------+---------+--------------+----------------+ + * *--------------------------------(*1)---------------------------------* + * + * +21 +22 +22+(*3) +22+(*3)+2 +22+(*3)+2+(*4) + * +---------------+---------+----------+----------------+------------------+ + * |name length(*3)|file name|file CRC16|extra header(*4)| compressed data | + * +---------------+---------+----------+----------------+------------------+ + * <--(*3)-> <------(*2)------> + * *----------------------(*1)--------------------------> + * + */ +#define H0_HEADER_SIZE_OFFSET 0 +#define H0_HEADER_SUM_OFFSET 1 +#define H0_COMP_SIZE_OFFSET 7 +#define H0_ORIG_SIZE_OFFSET 11 +#define H0_DOS_TIME_OFFSET 15 +#define H0_NAME_LEN_OFFSET 21 +#define H0_FILE_NAME_OFFSET 22 +#define H0_FIXED_SIZE 24 +static int +lha_read_file_header_0(struct archive_read *a, struct lha *lha) +{ + const unsigned char *p; + int extdsize, namelen; + unsigned char headersum, sum_calculated; + + if ((p = __archive_read_ahead(a, H0_FIXED_SIZE, NULL)) == NULL) + return (truncated_error(a)); + lha->header_size = p[H0_HEADER_SIZE_OFFSET] + 2; + headersum = p[H0_HEADER_SUM_OFFSET]; + lha->compsize = archive_le32dec(p + H0_COMP_SIZE_OFFSET); + lha->origsize = archive_le32dec(p + H0_ORIG_SIZE_OFFSET); + lha->mtime = lha_dos_time(p + H0_DOS_TIME_OFFSET); + namelen = p[H0_NAME_LEN_OFFSET]; + extdsize = (int)lha->header_size - H0_FIXED_SIZE - namelen; + if ((namelen > 221 || extdsize < 0) && extdsize != -2) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid LHa header"); + return (ARCHIVE_FATAL); + } + if ((p = __archive_read_ahead(a, lha->header_size, NULL)) == NULL) + return (truncated_error(a)); + + archive_strncpy(&lha->filename, p + H0_FILE_NAME_OFFSET, namelen); + /* When extdsize == -2, A CRC16 value is not present in the header. */ + if (extdsize >= 0) { + lha->crc = archive_le16dec(p + H0_FILE_NAME_OFFSET + namelen); + lha->setflag |= CRC_IS_SET; + } + sum_calculated = lha_calcsum(0, p, 2, lha->header_size - 2); + + /* Read an extended header */ + if (extdsize > 0) { + /* This extended data is set by 'LHa for UNIX' only. + * Maybe fixed size. + */ + p += H0_FILE_NAME_OFFSET + namelen + 2; + if (p[0] == 'U' && extdsize == 12) { + /* p[1] is a minor version. */ + lha->mtime = archive_le32dec(&p[2]); + lha->mode = archive_le16dec(&p[6]); + lha->uid = archive_le16dec(&p[8]); + lha->gid = archive_le16dec(&p[10]); + lha->setflag |= UNIX_MODE_IS_SET; + } + } + __archive_read_consume(a, lha->header_size); + + if (sum_calculated != headersum) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "LHa header sum error"); + return (ARCHIVE_FATAL); + } + + return (ARCHIVE_OK); +} + +/* + * Header 1 format + * + * +0 +1 +2 +7 +11 + * +---------------+----------+----------------+-------------+ + * |header size(*1)|header sum|compression type|skip size(*2)| + * +---------------+----------+----------------+-------------+ + * <---------------(*1)----------* + * + * +11 +15 +17 +19 +20 +21 + * +-----------------+---------+---------+--------------+----------------+ + * |uncompressed size|time(DOS)|date(DOS)|attribute(DOS)|header level(=1)| + * +-----------------+---------+---------+--------------+----------------+ + * *-------------------------------(*1)----------------------------------* + * + * +21 +22 +22+(*3) +22+(*3)+2 +22+(*3)+3 +22+(*3)+3+(*4) + * +---------------+---------+----------+-----------+-----------+ + * |name length(*3)|file name|file CRC16| creator |padding(*4)| + * +---------------+---------+----------+-----------+-----------+ + * <--(*3)-> + * *----------------------------(*1)----------------------------* + * + * +22+(*3)+3+(*4) +22+(*3)+3+(*4)+2 +22+(*3)+3+(*4)+2+(*5) + * +----------------+---------------------+------------------------+ + * |next header size| extended header(*5) | compressed data | + * +----------------+---------------------+------------------------+ + * *------(*1)-----> <--------------------(*2)--------------------> + */ +#define H1_HEADER_SIZE_OFFSET 0 +#define H1_HEADER_SUM_OFFSET 1 +#define H1_COMP_SIZE_OFFSET 7 +#define H1_ORIG_SIZE_OFFSET 11 +#define H1_DOS_TIME_OFFSET 15 +#define H1_NAME_LEN_OFFSET 21 +#define H1_FILE_NAME_OFFSET 22 +#define H1_FIXED_SIZE 27 +static int +lha_read_file_header_1(struct archive_read *a, struct lha *lha) +{ + const unsigned char *p; + size_t extdsize; + int i, err, err2; + int namelen, padding; + unsigned char headersum, sum_calculated; + + err = ARCHIVE_OK; + + if ((p = __archive_read_ahead(a, H1_FIXED_SIZE, NULL)) == NULL) + return (truncated_error(a)); + + lha->header_size = p[H1_HEADER_SIZE_OFFSET] + 2; + headersum = p[H1_HEADER_SUM_OFFSET]; + /* Note: An extended header size is included in a compsize. */ + lha->compsize = archive_le32dec(p + H1_COMP_SIZE_OFFSET); + lha->origsize = archive_le32dec(p + H1_ORIG_SIZE_OFFSET); + lha->mtime = lha_dos_time(p + H1_DOS_TIME_OFFSET); + namelen = p[H1_NAME_LEN_OFFSET]; + /* Calculate a padding size. The result will be normally 0 only(?) */ + padding = ((int)lha->header_size) - H1_FIXED_SIZE - namelen; + + if (namelen > 230 || padding < 0) + goto invalid; + + if ((p = __archive_read_ahead(a, lha->header_size, NULL)) == NULL) + return (truncated_error(a)); + + for (i = 0; i < namelen; i++) { + if (p[i + H1_FILE_NAME_OFFSET] == 0xff) + goto invalid;/* Invalid filename. */ + } + archive_strncpy(&lha->filename, p + H1_FILE_NAME_OFFSET, namelen); + lha->crc = archive_le16dec(p + H1_FILE_NAME_OFFSET + namelen); + lha->setflag |= CRC_IS_SET; + + sum_calculated = lha_calcsum(0, p, 2, lha->header_size - 2); + /* Consume used bytes but not include `next header size' data + * since it will be consumed in lha_read_file_extended_header(). */ + __archive_read_consume(a, lha->header_size - 2); + + /* Read extended headers */ + err2 = lha_read_file_extended_header(a, lha, NULL, 2, + (size_t)(lha->compsize + 2), &extdsize); + if (err2 < ARCHIVE_WARN) + return (err2); + if (err2 < err) + err = err2; + /* Get a real compressed file size. */ + lha->compsize -= extdsize - 2; + + if (lha->compsize < 0) + goto invalid; /* Invalid compressed file size */ + + if (sum_calculated != headersum) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "LHa header sum error"); + return (ARCHIVE_FATAL); + } + return (err); +invalid: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid LHa header"); + return (ARCHIVE_FATAL); +} + +/* + * Header 2 format + * + * +0 +2 +7 +11 +15 + * +---------------+----------------+-------------------+-----------------+ + * |header size(*1)|compression type|compressed size(*2)|uncompressed size| + * +---------------+----------------+-------------------+-----------------+ + * <--------------------------------(*1)---------------------------------* + * + * +15 +19 +20 +21 +23 +24 + * +-----------------+------------+----------------+----------+-----------+ + * |data/time(time_t)| 0x20 fixed |header level(=2)|file CRC16| creator | + * +-----------------+------------+----------------+----------+-----------+ + * *---------------------------------(*1)---------------------------------* + * + * +24 +26 +26+(*3) +26+(*3)+(*4) + * +----------------+-------------------+-------------+-------------------+ + * |next header size|extended header(*3)| padding(*4) | compressed data | + * +----------------+-------------------+-------------+-------------------+ + * *--------------------------(*1)-------------------> <------(*2)-------> + * + */ +#define H2_HEADER_SIZE_OFFSET 0 +#define H2_COMP_SIZE_OFFSET 7 +#define H2_ORIG_SIZE_OFFSET 11 +#define H2_TIME_OFFSET 15 +#define H2_CRC_OFFSET 21 +#define H2_FIXED_SIZE 24 +static int +lha_read_file_header_2(struct archive_read *a, struct lha *lha) +{ + const unsigned char *p; + size_t extdsize; + int err, padding; + uint16_t header_crc; + + if ((p = __archive_read_ahead(a, H2_FIXED_SIZE, NULL)) == NULL) + return (truncated_error(a)); + + lha->header_size =archive_le16dec(p + H2_HEADER_SIZE_OFFSET); + lha->compsize = archive_le32dec(p + H2_COMP_SIZE_OFFSET); + lha->origsize = archive_le32dec(p + H2_ORIG_SIZE_OFFSET); + lha->mtime = archive_le32dec(p + H2_TIME_OFFSET); + lha->crc = archive_le16dec(p + H2_CRC_OFFSET); + lha->setflag |= CRC_IS_SET; + + if (lha->header_size < H2_FIXED_SIZE) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid LHa header size"); + return (ARCHIVE_FATAL); + } + + header_crc = lha_crc16(0, p, H2_FIXED_SIZE); + __archive_read_consume(a, H2_FIXED_SIZE); + + /* Read extended headers */ + err = lha_read_file_extended_header(a, lha, &header_crc, 2, + lha->header_size - H2_FIXED_SIZE, &extdsize); + if (err < ARCHIVE_WARN) + return (err); + + /* Calculate a padding size. The result will be normally 0 or 1. */ + padding = (int)lha->header_size - (int)(H2_FIXED_SIZE + extdsize); + if (padding > 0) { + if ((p = __archive_read_ahead(a, padding, NULL)) == NULL) + return (truncated_error(a)); + header_crc = lha_crc16(header_crc, p, padding); + __archive_read_consume(a, padding); + } + + if (header_crc != lha->header_crc) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "LHa header CRC error"); + return (ARCHIVE_FATAL); + } + return (err); +} + +/* + * Header 3 format + * + * +0 +2 +7 +11 +15 + * +------------+----------------+-------------------+-----------------+ + * | 0x04 fixed |compression type|compressed size(*2)|uncompressed size| + * +------------+----------------+-------------------+-----------------+ + * <-------------------------------(*1)-------------------------------* + * + * +15 +19 +20 +21 +23 +24 + * +-----------------+------------+----------------+----------+-----------+ + * |date/time(time_t)| 0x20 fixed |header level(=3)|file CRC16| creator | + * +-----------------+------------+----------------+----------+-----------+ + * *--------------------------------(*1)----------------------------------* + * + * +24 +28 +32 +32+(*3) + * +---------------+----------------+-------------------+-----------------+ + * |header size(*1)|next header size|extended header(*3)| compressed data | + * +---------------+----------------+-------------------+-----------------+ + * *------------------------(*1)-----------------------> <------(*2)-----> + * + */ +#define H3_FIELD_LEN_OFFSET 0 +#define H3_COMP_SIZE_OFFSET 7 +#define H3_ORIG_SIZE_OFFSET 11 +#define H3_TIME_OFFSET 15 +#define H3_CRC_OFFSET 21 +#define H3_HEADER_SIZE_OFFSET 24 +#define H3_FIXED_SIZE 28 +static int +lha_read_file_header_3(struct archive_read *a, struct lha *lha) +{ + const unsigned char *p; + size_t extdsize; + int err; + uint16_t header_crc; + + if ((p = __archive_read_ahead(a, H3_FIXED_SIZE, NULL)) == NULL) + return (truncated_error(a)); + + if (archive_le16dec(p + H3_FIELD_LEN_OFFSET) != 4) + goto invalid; + lha->header_size =archive_le32dec(p + H3_HEADER_SIZE_OFFSET); + lha->compsize = archive_le32dec(p + H3_COMP_SIZE_OFFSET); + lha->origsize = archive_le32dec(p + H3_ORIG_SIZE_OFFSET); + lha->mtime = archive_le32dec(p + H3_TIME_OFFSET); + lha->crc = archive_le16dec(p + H3_CRC_OFFSET); + lha->setflag |= CRC_IS_SET; + + if (lha->header_size < H3_FIXED_SIZE + 4) + goto invalid; + header_crc = lha_crc16(0, p, H3_FIXED_SIZE); + __archive_read_consume(a, H3_FIXED_SIZE); + + /* Read extended headers */ + err = lha_read_file_extended_header(a, lha, &header_crc, 4, + lha->header_size - H3_FIXED_SIZE, &extdsize); + if (err < ARCHIVE_WARN) + return (err); + + if (header_crc != lha->header_crc) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "LHa header CRC error"); + return (ARCHIVE_FATAL); + } + return (err); +invalid: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid LHa header"); + return (ARCHIVE_FATAL); +} + +/* + * Extended header format + * + * +0 +2 +3 -- used in header 1 and 2 + * +0 +4 +5 -- used in header 3 + * +--------------+---------+-------------------+--------------+-- + * |ex-header size|header id| data |ex-header size| ....... + * +--------------+---------+-------------------+--------------+-- + * <-------------( ex-header size)------------> <-- next extended header --* + * + * If the ex-header size is zero, it is the make of the end of extended + * headers. + * + */ +static int +lha_read_file_extended_header(struct archive_read *a, struct lha *lha, + uint16_t *crc, int sizefield_length, size_t limitsize, size_t *total_size) +{ + const void *h; + const unsigned char *extdheader; + size_t extdsize; + size_t datasize; + unsigned int i; + unsigned char extdtype; + +#define EXT_HEADER_CRC 0x00 /* Header CRC and information*/ +#define EXT_FILENAME 0x01 /* Filename */ +#define EXT_DIRECTORY 0x02 /* Directory name */ +#define EXT_DOS_ATTR 0x40 /* MS-DOS attribute */ +#define EXT_TIMESTAMP 0x41 /* Windows time stamp */ +#define EXT_FILESIZE 0x42 /* Large file size */ +#define EXT_TIMEZONE 0x43 /* Time zone */ +#define EXT_UTF16_FILENAME 0x44 /* UTF-16 filename */ +#define EXT_UTF16_DIRECTORY 0x45 /* UTF-16 directory name */ +#define EXT_CODEPAGE 0x46 /* Codepage */ +#define EXT_UNIX_MODE 0x50 /* File permission */ +#define EXT_UNIX_GID_UID 0x51 /* gid,uid */ +#define EXT_UNIX_GNAME 0x52 /* Group name */ +#define EXT_UNIX_UNAME 0x53 /* User name */ +#define EXT_UNIX_MTIME 0x54 /* Modified time */ +#define EXT_OS2_NEW_ATTR 0x7f /* new attribute(OS/2 only) */ +#define EXT_NEW_ATTR 0xff /* new attribute */ + + *total_size = sizefield_length; + + for (;;) { + /* Read an extended header size. */ + if ((h = + __archive_read_ahead(a, sizefield_length, NULL)) == NULL) + return (truncated_error(a)); + /* Check if the size is the zero indicates the end of the + * extended header. */ + if (sizefield_length == sizeof(uint16_t)) + extdsize = archive_le16dec(h); + else + extdsize = archive_le32dec(h); + if (extdsize == 0) { + /* End of extended header */ + if (crc != NULL) + *crc = lha_crc16(*crc, h, sizefield_length); + __archive_read_consume(a, sizefield_length); + return (ARCHIVE_OK); + } + + /* Sanity check to the extended header size. */ + if (((uint64_t)*total_size + extdsize) > + (uint64_t)limitsize || + extdsize <= (size_t)sizefield_length) + goto invalid; + + /* Read the extended header. */ + if ((h = __archive_read_ahead(a, extdsize, NULL)) == NULL) + return (truncated_error(a)); + *total_size += extdsize; + + extdheader = (const unsigned char *)h; + /* Get the extended header type. */ + extdtype = extdheader[sizefield_length]; + /* Calculate an extended data size. */ + datasize = extdsize - (1 + sizefield_length); + /* Skip an extended header size field and type field. */ + extdheader += sizefield_length + 1; + + if (crc != NULL && extdtype != EXT_HEADER_CRC) + *crc = lha_crc16(*crc, h, extdsize); + switch (extdtype) { + case EXT_HEADER_CRC: + /* We only use a header CRC. Following data will not + * be used. */ + if (datasize >= 2) { + lha->header_crc = archive_le16dec(extdheader); + if (crc != NULL) { + static const char zeros[2] = {0, 0}; + *crc = lha_crc16(*crc, h, + extdsize - datasize); + /* CRC value itself as zero */ + *crc = lha_crc16(*crc, zeros, 2); + *crc = lha_crc16(*crc, + extdheader+2, datasize - 2); + } + } + break; + case EXT_FILENAME: + if (datasize == 0) { + /* maybe directory header */ + archive_string_empty(&lha->filename); + break; + } + if (extdheader[0] == '\0') + goto invalid; + archive_strncpy(&lha->filename, + (const char *)extdheader, datasize); + break; + case EXT_UTF16_FILENAME: + if (datasize == 0) { + /* maybe directory header */ + archive_string_empty(&lha->filename); + break; + } else if (datasize & 1) { + /* UTF-16 characters take always 2 or 4 bytes */ + goto invalid; + } + if (extdheader[0] == '\0') + goto invalid; + archive_string_empty(&lha->filename); + archive_array_append(&lha->filename, + (const char *)extdheader, datasize); + /* Setup a string conversion for a filename. */ + lha->sconv_fname = + archive_string_conversion_from_charset(&a->archive, + "UTF-16LE", 1); + if (lha->sconv_fname == NULL) + return (ARCHIVE_FATAL); + break; + case EXT_DIRECTORY: + if (datasize == 0 || extdheader[0] == '\0') + /* no directory name data. exit this case. */ + goto invalid; + + archive_strncpy(&lha->dirname, + (const char *)extdheader, datasize); + /* + * Convert directory delimiter from 0xFF + * to '/' for local system. + */ + for (i = 0; i < lha->dirname.length; i++) { + if ((unsigned char)lha->dirname.s[i] == 0xFF) + lha->dirname.s[i] = '/'; + } + /* Is last character directory separator? */ + if (lha->dirname.s[lha->dirname.length-1] != '/') + /* invalid directory data */ + goto invalid; + break; + case EXT_UTF16_DIRECTORY: + /* UTF-16 characters take always 2 or 4 bytes */ + if (datasize == 0 || (datasize & 1) || + extdheader[0] == '\0') { + /* no directory name data. exit this case. */ + goto invalid; + } + + archive_string_empty(&lha->dirname); + archive_array_append(&lha->dirname, + (const char *)extdheader, datasize); + lha->sconv_dir = + archive_string_conversion_from_charset(&a->archive, + "UTF-16LE", 1); + if (lha->sconv_dir == NULL) + return (ARCHIVE_FATAL); + else { + /* + * Convert directory delimiter from 0xFFFF + * to '/' for local system. + */ + uint16_t dirSep; + uint16_t d = 1; + if (archive_be16dec(&d) == 1) + dirSep = 0x2F00; + else + dirSep = 0x002F; + + /* UTF-16LE character */ + uint16_t *utf16name = + (uint16_t *)lha->dirname.s; + for (i = 0; i < lha->dirname.length / 2; i++) { + if (utf16name[i] == 0xFFFF) { + utf16name[i] = dirSep; + } + } + /* Is last character directory separator? */ + if (utf16name[lha->dirname.length / 2 - 1] != + dirSep) { + /* invalid directory data */ + goto invalid; + } + } + break; + case EXT_DOS_ATTR: + if (datasize == 2) + lha->dos_attr = (unsigned char) + (archive_le16dec(extdheader) & 0xff); + break; + case EXT_TIMESTAMP: + if (datasize == (sizeof(uint64_t) * 3)) { + lha->birthtime = lha_win_time( + archive_le64dec(extdheader), + &lha->birthtime_tv_nsec); + extdheader += sizeof(uint64_t); + lha->mtime = lha_win_time( + archive_le64dec(extdheader), + &lha->mtime_tv_nsec); + extdheader += sizeof(uint64_t); + lha->atime = lha_win_time( + archive_le64dec(extdheader), + &lha->atime_tv_nsec); + lha->setflag |= BIRTHTIME_IS_SET | + ATIME_IS_SET; + } + break; + case EXT_FILESIZE: + if (datasize == sizeof(uint64_t) * 2) { + lha->compsize = archive_le64dec(extdheader); + extdheader += sizeof(uint64_t); + lha->origsize = archive_le64dec(extdheader); + } + break; + case EXT_CODEPAGE: + /* Get an archived filename charset from codepage. + * This overwrites the charset specified by + * hdrcharset option. */ + if (datasize == sizeof(uint32_t)) { + struct archive_string cp; + const char *charset; + + archive_string_init(&cp); + switch (archive_le32dec(extdheader)) { + case 65001: /* UTF-8 */ + charset = "UTF-8"; + break; + default: + archive_string_sprintf(&cp, "CP%d", + (int)archive_le32dec(extdheader)); + charset = cp.s; + break; + } + lha->sconv_dir = + archive_string_conversion_from_charset( + &(a->archive), charset, 1); + lha->sconv_fname = + archive_string_conversion_from_charset( + &(a->archive), charset, 1); + archive_string_free(&cp); + if (lha->sconv_dir == NULL) + return (ARCHIVE_FATAL); + if (lha->sconv_fname == NULL) + return (ARCHIVE_FATAL); + } + break; + case EXT_UNIX_MODE: + if (datasize == sizeof(uint16_t)) { + lha->mode = archive_le16dec(extdheader); + lha->setflag |= UNIX_MODE_IS_SET; + } + break; + case EXT_UNIX_GID_UID: + if (datasize == (sizeof(uint16_t) * 2)) { + lha->gid = archive_le16dec(extdheader); + lha->uid = archive_le16dec(extdheader+2); + } + break; + case EXT_UNIX_GNAME: + if (datasize > 0) + archive_strncpy(&lha->gname, + (const char *)extdheader, datasize); + break; + case EXT_UNIX_UNAME: + if (datasize > 0) + archive_strncpy(&lha->uname, + (const char *)extdheader, datasize); + break; + case EXT_UNIX_MTIME: + if (datasize == sizeof(uint32_t)) + lha->mtime = archive_le32dec(extdheader); + break; + case EXT_OS2_NEW_ATTR: + /* This extended header is OS/2 depend. */ + if (datasize == 16) { + lha->dos_attr = (unsigned char) + (archive_le16dec(extdheader) & 0xff); + lha->mode = archive_le16dec(extdheader+2); + lha->gid = archive_le16dec(extdheader+4); + lha->uid = archive_le16dec(extdheader+6); + lha->birthtime = archive_le32dec(extdheader+8); + lha->atime = archive_le32dec(extdheader+12); + lha->setflag |= UNIX_MODE_IS_SET + | BIRTHTIME_IS_SET | ATIME_IS_SET; + } + break; + case EXT_NEW_ATTR: + if (datasize == 20) { + lha->mode = (mode_t)archive_le32dec(extdheader); + lha->gid = archive_le32dec(extdheader+4); + lha->uid = archive_le32dec(extdheader+8); + lha->birthtime = archive_le32dec(extdheader+12); + lha->atime = archive_le32dec(extdheader+16); + lha->setflag |= UNIX_MODE_IS_SET + | BIRTHTIME_IS_SET | ATIME_IS_SET; + } + break; + case EXT_TIMEZONE: /* Not supported */ + break; + default: + break; + } + + __archive_read_consume(a, extdsize); + } +invalid: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid extended LHa header"); + return (ARCHIVE_FATAL); +} + +static int +lha_end_of_entry(struct archive_read *a) +{ + struct lha *lha = (struct lha *)(a->format->data); + int r = ARCHIVE_EOF; + + if (!lha->end_of_entry_cleanup) { + if ((lha->setflag & CRC_IS_SET) && + lha->crc != lha->entry_crc_calculated) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "LHa data CRC error"); + r = ARCHIVE_WARN; + } + + /* End-of-entry cleanup done. */ + lha->end_of_entry_cleanup = 1; + } + return (r); +} + +static int +archive_read_format_lha_read_data(struct archive_read *a, + const void **buff, size_t *size, int64_t *offset) +{ + struct lha *lha = (struct lha *)(a->format->data); + int r; + + if (lha->entry_unconsumed) { + /* Consume as much as the decompressor actually used. */ + __archive_read_consume(a, lha->entry_unconsumed); + lha->entry_unconsumed = 0; + } + if (lha->end_of_entry) { + *offset = lha->entry_offset; + *size = 0; + *buff = NULL; + return (lha_end_of_entry(a)); + } + + if (lha->entry_is_compressed) + r = lha_read_data_lzh(a, buff, size, offset); + else + /* No compression. */ + r = lha_read_data_none(a, buff, size, offset); + return (r); +} + +/* + * Read a file content in no compression. + * + * Returns ARCHIVE_OK if successful, ARCHIVE_FATAL otherwise, sets + * lha->end_of_entry if it consumes all of the data. + */ +static int +lha_read_data_none(struct archive_read *a, const void **buff, + size_t *size, int64_t *offset) +{ + struct lha *lha = (struct lha *)(a->format->data); + ssize_t bytes_avail; + + if (lha->entry_bytes_remaining == 0) { + *buff = NULL; + *size = 0; + *offset = lha->entry_offset; + lha->end_of_entry = 1; + return (ARCHIVE_OK); + } + /* + * Note: '1' here is a performance optimization. + * Recall that the decompression layer returns a count of + * available bytes; asking for more than that forces the + * decompressor to combine reads by copying data. + */ + *buff = __archive_read_ahead(a, 1, &bytes_avail); + if (bytes_avail <= 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated LHa file data"); + return (ARCHIVE_FATAL); + } + if (bytes_avail > lha->entry_bytes_remaining) + bytes_avail = (ssize_t)lha->entry_bytes_remaining; + lha->entry_crc_calculated = + lha_crc16(lha->entry_crc_calculated, *buff, bytes_avail); + *size = bytes_avail; + *offset = lha->entry_offset; + lha->entry_offset += bytes_avail; + lha->entry_bytes_remaining -= bytes_avail; + if (lha->entry_bytes_remaining == 0) + lha->end_of_entry = 1; + lha->entry_unconsumed = bytes_avail; + return (ARCHIVE_OK); +} + +/* + * Read a file content in LZHUFF encoding. + * + * Returns ARCHIVE_OK if successful, returns ARCHIVE_WARN if compression is + * unsupported, ARCHIVE_FATAL otherwise, sets lha->end_of_entry if it consumes + * all of the data. + */ +static int +lha_read_data_lzh(struct archive_read *a, const void **buff, + size_t *size, int64_t *offset) +{ + struct lha *lha = (struct lha *)(a->format->data); + ssize_t bytes_avail; + int r; + + /* If we haven't yet read any data, initialize the decompressor. */ + if (!lha->decompress_init) { + r = lzh_decode_init(&(lha->strm), lha->method); + switch (r) { + case ARCHIVE_OK: + break; + case ARCHIVE_FAILED: + /* Unsupported compression. */ + *buff = NULL; + *size = 0; + *offset = 0; + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Unsupported lzh compression method -%c%c%c-", + lha->method[0], lha->method[1], lha->method[2]); + /* We know compressed size; just skip it. */ + archive_read_format_lha_read_data_skip(a); + return (ARCHIVE_WARN); + default: + archive_set_error(&a->archive, ENOMEM, + "Couldn't allocate memory " + "for lzh decompression"); + return (ARCHIVE_FATAL); + } + /* We've initialized decompression for this stream. */ + lha->decompress_init = 1; + lha->strm.avail_out = 0; + lha->strm.total_out = 0; + } + + /* + * Note: '1' here is a performance optimization. + * Recall that the decompression layer returns a count of + * available bytes; asking for more than that forces the + * decompressor to combine reads by copying data. + */ + lha->strm.next_in = __archive_read_ahead(a, 1, &bytes_avail); + if (bytes_avail <= 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated LHa file body"); + return (ARCHIVE_FATAL); + } + if (bytes_avail > lha->entry_bytes_remaining) + bytes_avail = (ssize_t)lha->entry_bytes_remaining; + + lha->strm.avail_in = (int)bytes_avail; + lha->strm.total_in = 0; + lha->strm.avail_out = 0; + + r = lzh_decode(&(lha->strm), bytes_avail == lha->entry_bytes_remaining); + switch (r) { + case ARCHIVE_OK: + break; + case ARCHIVE_EOF: + lha->end_of_entry = 1; + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Bad lzh data"); + return (ARCHIVE_FAILED); + } + lha->entry_unconsumed = lha->strm.total_in; + lha->entry_bytes_remaining -= lha->strm.total_in; + + if (lha->strm.avail_out) { + *offset = lha->entry_offset; + *size = lha->strm.avail_out; + *buff = lha->strm.ref_ptr; + lha->entry_crc_calculated = + lha_crc16(lha->entry_crc_calculated, *buff, *size); + lha->entry_offset += *size; + } else { + *offset = lha->entry_offset; + *size = 0; + *buff = NULL; + if (lha->end_of_entry) + return (lha_end_of_entry(a)); + } + return (ARCHIVE_OK); +} + +/* + * Skip a file content. + */ +static int +archive_read_format_lha_read_data_skip(struct archive_read *a) +{ + struct lha *lha; + int64_t bytes_skipped; + + lha = (struct lha *)(a->format->data); + + if (lha->entry_unconsumed) { + /* Consume as much as the decompressor actually used. */ + __archive_read_consume(a, lha->entry_unconsumed); + lha->entry_unconsumed = 0; + } + + /* if we've already read to end of data, we're done. */ + if (lha->end_of_entry_cleanup) + return (ARCHIVE_OK); + + /* + * If the length is at the beginning, we can skip the + * compressed data much more quickly. + */ + bytes_skipped = __archive_read_consume(a, lha->entry_bytes_remaining); + if (bytes_skipped < 0) + return (ARCHIVE_FATAL); + + /* This entry is finished and done. */ + lha->end_of_entry_cleanup = lha->end_of_entry = 1; + return (ARCHIVE_OK); +} + +static int +archive_read_format_lha_cleanup(struct archive_read *a) +{ + struct lha *lha = (struct lha *)(a->format->data); + + lzh_decode_free(&(lha->strm)); + archive_string_free(&(lha->dirname)); + archive_string_free(&(lha->filename)); + archive_string_free(&(lha->uname)); + archive_string_free(&(lha->gname)); + archive_wstring_free(&(lha->ws)); + free(lha); + (a->format->data) = NULL; + return (ARCHIVE_OK); +} + +/* + * 'LHa for UNIX' utility has archived a symbolic-link name after + * a pathname with '|' character. + * This function extracts the symbolic-link name from the pathname. + * + * example. + * 1. a symbolic-name is 'aaa/bb/cc' + * 2. a filename is 'xxx/bbb' + * then a archived pathname is 'xxx/bbb|aaa/bb/cc' + */ +static int +lha_parse_linkname(struct archive_wstring *linkname, + struct archive_wstring *pathname) +{ + wchar_t * linkptr; + size_t symlen; + + linkptr = wcschr(pathname->s, L'|'); + if (linkptr != NULL) { + symlen = wcslen(linkptr + 1); + archive_wstrncpy(linkname, linkptr+1, symlen); + + *linkptr = 0; + pathname->length = wcslen(pathname->s); + + return (1); + } + return (0); +} + +/* Convert an MSDOS-style date/time into Unix-style time. */ +static time_t +lha_dos_time(const unsigned char *p) +{ + int msTime, msDate; + struct tm ts; + + msTime = archive_le16dec(p); + msDate = archive_le16dec(p+2); + + memset(&ts, 0, sizeof(ts)); + ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */ + ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */ + ts.tm_mday = msDate & 0x1f; /* Day of month. */ + ts.tm_hour = (msTime >> 11) & 0x1f; + ts.tm_min = (msTime >> 5) & 0x3f; + ts.tm_sec = (msTime << 1) & 0x3e; + ts.tm_isdst = -1; + return (mktime(&ts)); +} + +/* Convert an MS-Windows-style date/time into Unix-style time. */ +static time_t +lha_win_time(uint64_t wintime, long *ns) +{ +#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) + + if (wintime >= EPOC_TIME) { + wintime -= EPOC_TIME; /* 1970-01-01 00:00:00 (UTC) */ + if (ns != NULL) + *ns = (long)(wintime % 10000000) * 100; + return (wintime / 10000000); + } else { + if (ns != NULL) + *ns = 0; + return (0); + } +} + +static unsigned char +lha_calcsum(unsigned char sum, const void *pp, int offset, size_t size) +{ + unsigned char const *p = (unsigned char const *)pp; + + p += offset; + for (;size > 0; --size) + sum += *p++; + return (sum); +} + +static uint16_t crc16tbl[2][256]; +static void +lha_crc16_init(void) +{ + unsigned int i; + static int crc16init = 0; + + if (crc16init) + return; + crc16init = 1; + + for (i = 0; i < 256; i++) { + unsigned int j; + uint16_t crc = (uint16_t)i; + for (j = 8; j; j--) + crc = (crc >> 1) ^ ((crc & 1) * 0xA001); + crc16tbl[0][i] = crc; + } + + for (i = 0; i < 256; i++) { + crc16tbl[1][i] = (crc16tbl[0][i] >> 8) + ^ crc16tbl[0][crc16tbl[0][i] & 0xff]; + } +} + +static uint16_t +lha_crc16(uint16_t crc, const void *pp, size_t len) +{ + const unsigned char *p = (const unsigned char *)pp; + const uint16_t *buff; + const union { + uint32_t i; + char c[4]; + } u = { 0x01020304 }; + + if (len == 0) + return crc; + + /* Process unaligned address. */ + if (((uintptr_t)p) & (uintptr_t)0x1) { + crc = (crc >> 8) ^ crc16tbl[0][(crc ^ *p++) & 0xff]; + len--; + } + buff = (const uint16_t *)p; + /* + * Modern C compiler such as GCC does not unroll automatically yet + * without unrolling pragma, and Clang is so. So we should + * unroll this loop for its performance. + */ + for (;len >= 8; len -= 8) { + /* This if statement expects compiler optimization will + * remove the statement which will not be executed. */ +#undef bswap16 +#if defined(_MSC_VER) && _MSC_VER >= 1400 /* Visual Studio */ +# define bswap16(x) _byteswap_ushort(x) +#elif defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || __GNUC__ > 4) +/* GCC 4.8 and later has __builtin_bswap16() */ +# define bswap16(x) __builtin_bswap16(x) +#elif defined(__clang__) +/* All clang versions have __builtin_bswap16() */ +# define bswap16(x) __builtin_bswap16(x) +#else +# define bswap16(x) ((((x) >> 8) & 0xff) | ((x) << 8)) +#endif +#define CRC16W do { \ + if(u.c[0] == 1) { /* Big endian */ \ + crc ^= bswap16(*buff); buff++; \ + } else \ + crc ^= *buff++; \ + crc = crc16tbl[1][crc & 0xff] ^ crc16tbl[0][crc >> 8];\ +} while (0) + CRC16W; + CRC16W; + CRC16W; + CRC16W; +#undef CRC16W +#undef bswap16 + } + + p = (const unsigned char *)buff; + for (;len; len--) { + crc = (crc >> 8) ^ crc16tbl[0][(crc ^ *p++) & 0xff]; + } + return crc; +} + +/* + * Initialize LZHUF decoder. + * + * Returns ARCHIVE_OK if initialization was successful. + * Returns ARCHIVE_FAILED if method is unsupported. + * Returns ARCHIVE_FATAL if initialization failed; memory allocation + * error occurred. + */ +static int +lzh_decode_init(struct lzh_stream *strm, const char *method) +{ + struct lzh_dec *ds; + int w_bits, w_size; + + if (strm->ds == NULL) { + strm->ds = calloc(1, sizeof(*strm->ds)); + if (strm->ds == NULL) + return (ARCHIVE_FATAL); + } + ds = strm->ds; + ds->error = ARCHIVE_FAILED; + if (method == NULL || method[0] != 'l' || method[1] != 'h') + return (ARCHIVE_FAILED); + switch (method[2]) { + case '5': + w_bits = 13;/* 8KiB for window */ + break; + case '6': + w_bits = 15;/* 32KiB for window */ + break; + case '7': + w_bits = 16;/* 64KiB for window */ + break; + default: + return (ARCHIVE_FAILED);/* Not supported. */ + } + ds->error = ARCHIVE_FATAL; + /* Expand a window size up to 128 KiB for decompressing process + * performance whatever its original window size is. */ + ds->w_size = 1U << 17; + ds->w_mask = ds->w_size -1; + if (ds->w_buff == NULL) { + ds->w_buff = malloc(ds->w_size); + if (ds->w_buff == NULL) + return (ARCHIVE_FATAL); + } + w_size = 1U << w_bits; + memset(ds->w_buff + ds->w_size - w_size, 0x20, w_size); + ds->w_pos = 0; + ds->state = 0; + ds->pos_pt_len_size = w_bits + 1; + ds->pos_pt_len_bits = (w_bits == 15 || w_bits == 16)? 5: 4; + ds->literal_pt_len_size = PT_BITLEN_SIZE; + ds->literal_pt_len_bits = 5; + ds->br.cache_buffer = 0; + ds->br.cache_avail = 0; + + if (lzh_huffman_init(&(ds->lt), LT_BITLEN_SIZE, 16) + != ARCHIVE_OK) + return (ARCHIVE_FATAL); + ds->lt.len_bits = 9; + if (lzh_huffman_init(&(ds->pt), PT_BITLEN_SIZE, 16) + != ARCHIVE_OK) + return (ARCHIVE_FATAL); + ds->error = 0; + + return (ARCHIVE_OK); +} + +/* + * Release LZHUF decoder. + */ +static void +lzh_decode_free(struct lzh_stream *strm) +{ + + if (strm->ds == NULL) + return; + free(strm->ds->w_buff); + lzh_huffman_free(&(strm->ds->lt)); + lzh_huffman_free(&(strm->ds->pt)); + free(strm->ds); + strm->ds = NULL; +} + +/* + * Bit stream reader. + */ +/* Check that the cache buffer has enough bits. */ +#define lzh_br_has(br, n) ((br)->cache_avail >= n) +/* Get compressed data by bit. */ +#define lzh_br_bits(br, n) \ + (((uint16_t)((br)->cache_buffer >> \ + ((br)->cache_avail - (n)))) & cache_masks[n]) +#define lzh_br_bits_forced(br, n) \ + (((uint16_t)((br)->cache_buffer << \ + ((n) - (br)->cache_avail))) & cache_masks[n]) +/* Read ahead to make sure the cache buffer has enough compressed data we + * will use. + * True : completed, there is enough data in the cache buffer. + * False : we met that strm->next_in is empty, we have to get following + * bytes. */ +#define lzh_br_read_ahead_0(strm, br, n) \ + (lzh_br_has(br, (n)) || lzh_br_fillup(strm, br)) +/* True : the cache buffer has some bits as much as we need. + * False : there are no enough bits in the cache buffer to be used, + * we have to get following bytes if we could. */ +#define lzh_br_read_ahead(strm, br, n) \ + (lzh_br_read_ahead_0((strm), (br), (n)) || lzh_br_has((br), (n))) + +/* Notify how many bits we consumed. */ +#define lzh_br_consume(br, n) ((br)->cache_avail -= (n)) +#define lzh_br_unconsume(br, n) ((br)->cache_avail += (n)) + +static const uint16_t cache_masks[] = { + 0x0000, 0x0001, 0x0003, 0x0007, + 0x000F, 0x001F, 0x003F, 0x007F, + 0x00FF, 0x01FF, 0x03FF, 0x07FF, + 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF +}; + +/* + * Shift away used bits in the cache data and fill it up with following bits. + * Call this when cache buffer does not have enough bits you need. + * + * Returns 1 if the cache buffer is full. + * Returns 0 if the cache buffer is not full; input buffer is empty. + */ +static int +lzh_br_fillup(struct lzh_stream *strm, struct lzh_br *br) +{ + int n = CACHE_BITS - br->cache_avail; + + for (;;) { + const int x = n >> 3; + if (strm->avail_in >= x) { + switch (x) { + case 8: + br->cache_buffer = + ((uint64_t)strm->next_in[0]) << 56 | + ((uint64_t)strm->next_in[1]) << 48 | + ((uint64_t)strm->next_in[2]) << 40 | + ((uint64_t)strm->next_in[3]) << 32 | + ((uint32_t)strm->next_in[4]) << 24 | + ((uint32_t)strm->next_in[5]) << 16 | + ((uint32_t)strm->next_in[6]) << 8 | + (uint32_t)strm->next_in[7]; + strm->next_in += 8; + strm->avail_in -= 8; + br->cache_avail += 8 * 8; + return (1); + case 7: + br->cache_buffer = + (br->cache_buffer << 56) | + ((uint64_t)strm->next_in[0]) << 48 | + ((uint64_t)strm->next_in[1]) << 40 | + ((uint64_t)strm->next_in[2]) << 32 | + ((uint32_t)strm->next_in[3]) << 24 | + ((uint32_t)strm->next_in[4]) << 16 | + ((uint32_t)strm->next_in[5]) << 8 | + (uint32_t)strm->next_in[6]; + strm->next_in += 7; + strm->avail_in -= 7; + br->cache_avail += 7 * 8; + return (1); + case 6: + br->cache_buffer = + (br->cache_buffer << 48) | + ((uint64_t)strm->next_in[0]) << 40 | + ((uint64_t)strm->next_in[1]) << 32 | + ((uint32_t)strm->next_in[2]) << 24 | + ((uint32_t)strm->next_in[3]) << 16 | + ((uint32_t)strm->next_in[4]) << 8 | + (uint32_t)strm->next_in[5]; + strm->next_in += 6; + strm->avail_in -= 6; + br->cache_avail += 6 * 8; + return (1); + case 0: + /* We have enough compressed data in + * the cache buffer.*/ + return (1); + default: + break; + } + } + if (strm->avail_in == 0) { + /* There is not enough compressed data to fill up the + * cache buffer. */ + return (0); + } + br->cache_buffer = + (br->cache_buffer << 8) | *strm->next_in++; + strm->avail_in--; + br->cache_avail += 8; + n -= 8; + } +} + +/* + * Decode LZHUF. + * + * 1. Returns ARCHIVE_OK if output buffer or input buffer are empty. + * Please set available buffer and call this function again. + * 2. Returns ARCHIVE_EOF if decompression has been completed. + * 3. Returns ARCHIVE_FAILED if an error occurred; compressed data + * is broken or you do not set 'last' flag properly. + * 4. 'last' flag is very important, you must set 1 to the flag if there + * is no input data. The lha compressed data format does not provide how + * to know the compressed data is really finished. + * Note: lha command utility check if the total size of output bytes is + * reached the uncompressed size recorded in its header. it does not mind + * that the decoding process is properly finished. + * GNU ZIP can decompress another compressed file made by SCO LZH compress. + * it handles EOF as null to fill read buffer with zero until the decoding + * process meet 2 bytes of zeros at reading a size of a next chunk, so the + * zeros are treated as the mark of the end of the data although the zeros + * is dummy, not the file data. + */ +static int lzh_read_blocks(struct lzh_stream *, int); +static int lzh_decode_blocks(struct lzh_stream *, int); +#define ST_RD_BLOCK 0 +#define ST_RD_PT_1 1 +#define ST_RD_PT_2 2 +#define ST_RD_PT_3 3 +#define ST_RD_PT_4 4 +#define ST_RD_LITERAL_1 5 +#define ST_RD_LITERAL_2 6 +#define ST_RD_LITERAL_3 7 +#define ST_RD_POS_DATA_1 8 +#define ST_GET_LITERAL 9 +#define ST_GET_POS_1 10 +#define ST_GET_POS_2 11 +#define ST_COPY_DATA 12 + +static int +lzh_decode(struct lzh_stream *strm, int last) +{ + struct lzh_dec *ds = strm->ds; + int avail_in; + int r; + + if (ds->error) + return (ds->error); + + avail_in = strm->avail_in; + do { + if (ds->state < ST_GET_LITERAL) + r = lzh_read_blocks(strm, last); + else + r = lzh_decode_blocks(strm, last); + } while (r == 100); + strm->total_in += avail_in - strm->avail_in; + return (r); +} + +static void +lzh_emit_window(struct lzh_stream *strm, size_t s) +{ + strm->ref_ptr = strm->ds->w_buff; + strm->avail_out = (int)s; + strm->total_out += s; +} + +static int +lzh_read_blocks(struct lzh_stream *strm, int last) +{ + struct lzh_dec *ds = strm->ds; + struct lzh_br *br = &(ds->br); + int c = 0, i; + unsigned rbits; + + for (;;) { + switch (ds->state) { + case ST_RD_BLOCK: + /* + * Read a block number indicates how many blocks + * we will handle. The block is composed of a + * literal and a match, sometimes a literal only + * in particular, there are no reference data at + * the beginning of the decompression. + */ + if (!lzh_br_read_ahead_0(strm, br, 16)) { + if (!last) + /* We need following data. */ + return (ARCHIVE_OK); + if (lzh_br_has(br, 8)) { + /* + * It seems there are extra bits. + * 1. Compressed data is broken. + * 2. `last' flag does not properly + * set. + */ + goto failed; + } + if (ds->w_pos > 0) { + lzh_emit_window(strm, ds->w_pos); + ds->w_pos = 0; + return (ARCHIVE_OK); + } + /* End of compressed data; we have completely + * handled all compressed data. */ + return (ARCHIVE_EOF); + } + ds->blocks_avail = lzh_br_bits(br, 16); + if (ds->blocks_avail == 0) + goto failed; + lzh_br_consume(br, 16); + /* + * Read a literal table compressed in huffman + * coding. + */ + ds->pt.len_size = ds->literal_pt_len_size; + ds->pt.len_bits = ds->literal_pt_len_bits; + ds->reading_position = 0; + /* FALL THROUGH */ + case ST_RD_PT_1: + /* Note: ST_RD_PT_1, ST_RD_PT_2 and ST_RD_PT_4 are + * used in reading both a literal table and a + * position table. */ + if (!lzh_br_read_ahead(strm, br, ds->pt.len_bits)) { + if (last) + goto failed;/* Truncated data. */ + ds->state = ST_RD_PT_1; + return (ARCHIVE_OK); + } + ds->pt.len_avail = lzh_br_bits(br, ds->pt.len_bits); + lzh_br_consume(br, ds->pt.len_bits); + /* FALL THROUGH */ + case ST_RD_PT_2: + if (ds->pt.len_avail == 0) { + /* There is no bitlen. */ + if (!lzh_br_read_ahead(strm, br, + ds->pt.len_bits)) { + if (last) + goto failed;/* Truncated data.*/ + ds->state = ST_RD_PT_2; + return (ARCHIVE_OK); + } + if (!lzh_make_fake_table(&(ds->pt), + lzh_br_bits(br, ds->pt.len_bits))) + goto failed;/* Invalid data. */ + lzh_br_consume(br, ds->pt.len_bits); + if (ds->reading_position) + ds->state = ST_GET_LITERAL; + else + ds->state = ST_RD_LITERAL_1; + break; + } else if (ds->pt.len_avail > ds->pt.len_size) + goto failed;/* Invalid data. */ + ds->loop = 0; + memset(ds->pt.freq, 0, sizeof(ds->pt.freq)); + if (ds->pt.len_avail < 3 || + ds->pt.len_size == ds->pos_pt_len_size) { + ds->state = ST_RD_PT_4; + break; + } + /* FALL THROUGH */ + case ST_RD_PT_3: + ds->loop = lzh_read_pt_bitlen(strm, ds->loop, 3); + if (ds->loop < 3) { + if (ds->loop < 0 || last) + goto failed;/* Invalid data. */ + /* Not completed, get following data. */ + ds->state = ST_RD_PT_3; + return (ARCHIVE_OK); + } + /* There are some null in bitlen of the literal. */ + if (!lzh_br_read_ahead(strm, br, 2)) { + if (last) + goto failed;/* Truncated data. */ + ds->state = ST_RD_PT_3; + return (ARCHIVE_OK); + } + c = lzh_br_bits(br, 2); + lzh_br_consume(br, 2); + if (c > ds->pt.len_avail - 3) + goto failed;/* Invalid data. */ + for (i = 3; c-- > 0 ;) + ds->pt.bitlen[i++] = 0; + ds->loop = i; + /* FALL THROUGH */ + case ST_RD_PT_4: + ds->loop = lzh_read_pt_bitlen(strm, ds->loop, + ds->pt.len_avail); + if (ds->loop < ds->pt.len_avail) { + if (ds->loop < 0 || last) + goto failed;/* Invalid data. */ + /* Not completed, get following data. */ + ds->state = ST_RD_PT_4; + return (ARCHIVE_OK); + } + if (!lzh_make_huffman_table(&(ds->pt))) + goto failed;/* Invalid data */ + if (ds->reading_position) { + ds->state = ST_GET_LITERAL; + break; + } + /* FALL THROUGH */ + case ST_RD_LITERAL_1: + if (!lzh_br_read_ahead(strm, br, ds->lt.len_bits)) { + if (last) + goto failed;/* Truncated data. */ + ds->state = ST_RD_LITERAL_1; + return (ARCHIVE_OK); + } + ds->lt.len_avail = lzh_br_bits(br, ds->lt.len_bits); + lzh_br_consume(br, ds->lt.len_bits); + /* FALL THROUGH */ + case ST_RD_LITERAL_2: + if (ds->lt.len_avail == 0) { + /* There is no bitlen. */ + if (!lzh_br_read_ahead(strm, br, + ds->lt.len_bits)) { + if (last) + goto failed;/* Truncated data.*/ + ds->state = ST_RD_LITERAL_2; + return (ARCHIVE_OK); + } + if (!lzh_make_fake_table(&(ds->lt), + lzh_br_bits(br, ds->lt.len_bits))) + goto failed;/* Invalid data */ + lzh_br_consume(br, ds->lt.len_bits); + ds->state = ST_RD_POS_DATA_1; + break; + } else if (ds->lt.len_avail > ds->lt.len_size) + goto failed;/* Invalid data */ + ds->loop = 0; + memset(ds->lt.freq, 0, sizeof(ds->lt.freq)); + /* FALL THROUGH */ + case ST_RD_LITERAL_3: + i = ds->loop; + while (i < ds->lt.len_avail) { + if (!lzh_br_read_ahead(strm, br, + ds->pt.max_bits)) { + if (last) + goto failed;/* Truncated data.*/ + ds->loop = i; + ds->state = ST_RD_LITERAL_3; + return (ARCHIVE_OK); + } + rbits = lzh_br_bits(br, ds->pt.max_bits); + c = lzh_decode_huffman(&(ds->pt), rbits); + if (c > 2) { + /* Note: 'c' will never be more than + * eighteen since it's limited by + * PT_BITLEN_SIZE, which is being set + * to ds->pt.len_size through + * ds->literal_pt_len_size. */ + lzh_br_consume(br, ds->pt.bitlen[c]); + c -= 2; + ds->lt.freq[c]++; + ds->lt.bitlen[i++] = c; + } else if (c == 0) { + lzh_br_consume(br, ds->pt.bitlen[c]); + ds->lt.bitlen[i++] = 0; + } else { + /* c == 1 or c == 2 */ + int n = (c == 1)?4:9; + if (!lzh_br_read_ahead(strm, br, + ds->pt.bitlen[c] + n)) { + if (last) /* Truncated data. */ + goto failed; + ds->loop = i; + ds->state = ST_RD_LITERAL_3; + return (ARCHIVE_OK); + } + lzh_br_consume(br, ds->pt.bitlen[c]); + c = lzh_br_bits(br, n); + lzh_br_consume(br, n); + c += (n == 4)?3:20; + if (i + c > ds->lt.len_avail) + goto failed;/* Invalid data */ + memset(&(ds->lt.bitlen[i]), 0, c); + i += c; + } + } + if (i > ds->lt.len_avail || + !lzh_make_huffman_table(&(ds->lt))) + goto failed;/* Invalid data */ + /* FALL THROUGH */ + case ST_RD_POS_DATA_1: + /* + * Read a position table compressed in huffman + * coding. + */ + ds->pt.len_size = ds->pos_pt_len_size; + ds->pt.len_bits = ds->pos_pt_len_bits; + ds->reading_position = 1; + ds->state = ST_RD_PT_1; + break; + case ST_GET_LITERAL: + return (100); + } + } +failed: + return (ds->error = ARCHIVE_FAILED); +} + +static int +lzh_decode_blocks(struct lzh_stream *strm, int last) +{ + struct lzh_dec *ds = strm->ds; + struct lzh_br bre = ds->br; + struct huffman *lt = &(ds->lt); + struct huffman *pt = &(ds->pt); + unsigned char *w_buff = ds->w_buff; + unsigned char *lt_bitlen = lt->bitlen; + unsigned char *pt_bitlen = pt->bitlen; + int blocks_avail = ds->blocks_avail, c = 0; + int copy_len = ds->copy_len, copy_pos = ds->copy_pos; + int w_pos = ds->w_pos, w_mask = ds->w_mask, w_size = ds->w_size; + int lt_max_bits = lt->max_bits, pt_max_bits = pt->max_bits; + int state = ds->state; + + for (;;) { + switch (state) { + case ST_GET_LITERAL: + for (;;) { + if (blocks_avail == 0) { + /* We have decoded all blocks. + * Let's handle next blocks. */ + ds->state = ST_RD_BLOCK; + ds->br = bre; + ds->blocks_avail = 0; + ds->w_pos = w_pos; + ds->copy_pos = 0; + return (100); + } + + /* lzh_br_read_ahead() always try to fill the + * cache buffer up. In specific situation we + * are close to the end of the data, the cache + * buffer will not be full and thus we have to + * determine if the cache buffer has some bits + * as much as we need after lzh_br_read_ahead() + * failed. */ + if (!lzh_br_read_ahead(strm, &bre, + lt_max_bits)) { + if (!last) + goto next_data; + /* Remaining bits are less than + * maximum bits(lt.max_bits) but maybe + * it still remains as much as we need, + * so we should try to use it with + * dummy bits. */ + c = lzh_decode_huffman(lt, + lzh_br_bits_forced(&bre, + lt_max_bits)); + lzh_br_consume(&bre, lt_bitlen[c]); + if (!lzh_br_has(&bre, 0)) + goto failed;/* Over read. */ + } else { + c = lzh_decode_huffman(lt, + lzh_br_bits(&bre, lt_max_bits)); + lzh_br_consume(&bre, lt_bitlen[c]); + } + blocks_avail--; + if (c > UCHAR_MAX) + /* Current block is a match data. */ + break; + /* + * 'c' is exactly a literal code. + */ + /* Save a decoded code to reference it + * afterward. */ + w_buff[w_pos] = c; + if (++w_pos >= w_size) { + w_pos = 0; + lzh_emit_window(strm, w_size); + goto next_data; + } + } + /* 'c' is the length of a match pattern we have + * already extracted, which has be stored in + * window(ds->w_buff). */ + copy_len = c - (UCHAR_MAX + 1) + MINMATCH; + /* FALL THROUGH */ + case ST_GET_POS_1: + /* + * Get a reference position. + */ + if (!lzh_br_read_ahead(strm, &bre, pt_max_bits)) { + if (!last) { + state = ST_GET_POS_1; + ds->copy_len = copy_len; + goto next_data; + } + copy_pos = lzh_decode_huffman(pt, + lzh_br_bits_forced(&bre, pt_max_bits)); + lzh_br_consume(&bre, pt_bitlen[copy_pos]); + if (!lzh_br_has(&bre, 0)) + goto failed;/* Over read. */ + } else { + copy_pos = lzh_decode_huffman(pt, + lzh_br_bits(&bre, pt_max_bits)); + lzh_br_consume(&bre, pt_bitlen[copy_pos]); + } + /* FALL THROUGH */ + case ST_GET_POS_2: + if (copy_pos > 1) { + /* We need an additional adjustment number to + * the position. */ + int p = copy_pos - 1; + if (!lzh_br_read_ahead(strm, &bre, p)) { + if (last) + goto failed;/* Truncated data.*/ + state = ST_GET_POS_2; + ds->copy_len = copy_len; + ds->copy_pos = copy_pos; + goto next_data; + } + copy_pos = (1 << p) + lzh_br_bits(&bre, p); + lzh_br_consume(&bre, p); + } + /* The position is actually a distance from the last + * code we had extracted and thus we have to convert + * it to a position of the window. */ + copy_pos = (w_pos - copy_pos - 1) & w_mask; + /* FALL THROUGH */ + case ST_COPY_DATA: + /* + * Copy `copy_len' bytes as extracted data from + * the window into the output buffer. + */ + for (;;) { + int l; + + l = copy_len; + if (copy_pos > w_pos) { + if (l > w_size - copy_pos) + l = w_size - copy_pos; + } else { + if (l > w_size - w_pos) + l = w_size - w_pos; + } + if ((copy_pos + l < w_pos) + || (w_pos + l < copy_pos)) { + /* No overlap. */ + memcpy(w_buff + w_pos, + w_buff + copy_pos, l); + } else { + const unsigned char *s; + unsigned char *d; + int li; + + d = w_buff + w_pos; + s = w_buff + copy_pos; + for (li = 0; li < l-1;) { + d[li] = s[li];li++; + d[li] = s[li];li++; + } + if (li < l) + d[li] = s[li]; + } + w_pos += l; + if (w_pos == w_size) { + w_pos = 0; + lzh_emit_window(strm, w_size); + if (copy_len <= l) + state = ST_GET_LITERAL; + else { + state = ST_COPY_DATA; + ds->copy_len = copy_len - l; + ds->copy_pos = + (copy_pos + l) & w_mask; + } + goto next_data; + } + if (copy_len <= l) + /* A copy of current pattern ended. */ + break; + copy_len -= l; + copy_pos = (copy_pos + l) & w_mask; + } + state = ST_GET_LITERAL; + break; + } + } +failed: + return (ds->error = ARCHIVE_FAILED); +next_data: + ds->br = bre; + ds->blocks_avail = blocks_avail; + ds->state = state; + ds->w_pos = w_pos; + return (ARCHIVE_OK); +} + +static int +lzh_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits) +{ + int bits; + + if (hf->bitlen == NULL) { + hf->bitlen = malloc(len_size * sizeof(hf->bitlen[0])); + if (hf->bitlen == NULL) + return (ARCHIVE_FATAL); + } + if (hf->tbl == NULL) { + if (tbl_bits < HTBL_BITS) + bits = tbl_bits; + else + bits = HTBL_BITS; + hf->tbl = malloc(((size_t)1 << bits) * sizeof(hf->tbl[0])); + if (hf->tbl == NULL) + return (ARCHIVE_FATAL); + } + if (hf->tree == NULL && tbl_bits > HTBL_BITS) { + hf->tree_avail = 1 << (tbl_bits - HTBL_BITS + 4); + hf->tree = malloc(hf->tree_avail * sizeof(hf->tree[0])); + if (hf->tree == NULL) + return (ARCHIVE_FATAL); + } + hf->len_size = (int)len_size; + hf->tbl_bits = tbl_bits; + return (ARCHIVE_OK); +} + +static void +lzh_huffman_free(struct huffman *hf) +{ + free(hf->bitlen); + free(hf->tbl); + free(hf->tree); +} + +static const char bitlen_tbl[0x400] = { + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 16, 0 +}; +static int +lzh_read_pt_bitlen(struct lzh_stream *strm, int start, int end) +{ + struct lzh_dec *ds = strm->ds; + struct lzh_br *br = &(ds->br); + int c, i; + + for (i = start; i < end; ) { + /* + * bit pattern the number we need + * 000 -> 0 + * 001 -> 1 + * 010 -> 2 + * ... + * 110 -> 6 + * 1110 -> 7 + * 11110 -> 8 + * ... + * 1111111111110 -> 16 + */ + if (!lzh_br_read_ahead(strm, br, 3)) + return (i); + if ((c = lzh_br_bits(br, 3)) == 7) { + if (!lzh_br_read_ahead(strm, br, 13)) + return (i); + c = bitlen_tbl[lzh_br_bits(br, 13) & 0x3FF]; + if (c) + lzh_br_consume(br, c - 3); + else + return (-1);/* Invalid data. */ + } else + lzh_br_consume(br, 3); + ds->pt.bitlen[i++] = c; + ds->pt.freq[c]++; + } + return (i); +} + +static int +lzh_make_fake_table(struct huffman *hf, uint16_t c) +{ + if (c >= hf->len_size) + return (0); + hf->tbl[0] = c; + hf->max_bits = 0; + hf->shift_bits = 0; + hf->bitlen[hf->tbl[0]] = 0; + return (1); +} + +/* + * Make a huffman coding table. + */ +static int +lzh_make_huffman_table(struct huffman *hf) +{ + uint16_t *tbl; + const unsigned char *bitlen; + int bitptn[17], weight[17]; + int i, maxbits = 0, ptn, tbl_size, w; + int diffbits, len_avail; + + /* + * Initialize bit patterns. + */ + ptn = 0; + for (i = 1, w = 1 << 15; i <= 16; i++, w >>= 1) { + bitptn[i] = ptn; + weight[i] = w; + if (hf->freq[i]) { + ptn += hf->freq[i] * w; + maxbits = i; + } + } + if (ptn != 0x10000 || maxbits > hf->tbl_bits) + return (0);/* Invalid */ + + hf->max_bits = maxbits; + + /* + * Cut out extra bits which we won't house in the table. + * This preparation reduces the same calculation in the for-loop + * making the table. + */ + if (maxbits < 16) { + int ebits = 16 - maxbits; + for (i = 1; i <= maxbits; i++) { + bitptn[i] >>= ebits; + weight[i] >>= ebits; + } + } + if (maxbits > HTBL_BITS) { + unsigned htbl_max; + uint16_t *p; + + diffbits = maxbits - HTBL_BITS; + for (i = 1; i <= HTBL_BITS; i++) { + bitptn[i] >>= diffbits; + weight[i] >>= diffbits; + } + htbl_max = bitptn[HTBL_BITS] + + weight[HTBL_BITS] * hf->freq[HTBL_BITS]; + p = &(hf->tbl[htbl_max]); + while (p < &hf->tbl[1U<shift_bits = diffbits; + + /* + * Make the table. + */ + tbl_size = 1 << HTBL_BITS; + tbl = hf->tbl; + bitlen = hf->bitlen; + len_avail = hf->len_avail; + hf->tree_used = 0; + for (i = 0; i < len_avail; i++) { + uint16_t *p; + int len, cnt; + uint16_t bit; + int extlen; + struct htree_t *ht; + + if (bitlen[i] == 0) + continue; + /* Get a bit pattern */ + len = bitlen[i]; + ptn = bitptn[len]; + cnt = weight[len]; + if (len <= HTBL_BITS) { + /* Calculate next bit pattern */ + if ((bitptn[len] = ptn + cnt) > tbl_size) + return (0);/* Invalid */ + /* Update the table */ + p = &(tbl[ptn]); + if (cnt > 7) { + uint16_t *pc; + + cnt -= 8; + pc = &p[cnt]; + pc[0] = (uint16_t)i; + pc[1] = (uint16_t)i; + pc[2] = (uint16_t)i; + pc[3] = (uint16_t)i; + pc[4] = (uint16_t)i; + pc[5] = (uint16_t)i; + pc[6] = (uint16_t)i; + pc[7] = (uint16_t)i; + if (cnt > 7) { + cnt -= 8; + memcpy(&p[cnt], pc, + 8 * sizeof(uint16_t)); + pc = &p[cnt]; + while (cnt > 15) { + cnt -= 16; + memcpy(&p[cnt], pc, + 16 * sizeof(uint16_t)); + } + } + if (cnt) + memcpy(p, pc, cnt * sizeof(uint16_t)); + } else { + while (cnt > 1) { + p[--cnt] = (uint16_t)i; + p[--cnt] = (uint16_t)i; + } + if (cnt) + p[--cnt] = (uint16_t)i; + } + continue; + } + + /* + * A bit length is too big to be housed to a direct table, + * so we use a tree model for its extra bits. + */ + bitptn[len] = ptn + cnt; + bit = 1U << (diffbits -1); + extlen = len - HTBL_BITS; + + p = &(tbl[ptn >> diffbits]); + if (*p == 0) { + *p = len_avail + hf->tree_used; + ht = &(hf->tree[hf->tree_used++]); + if (hf->tree_used > hf->tree_avail) + return (0);/* Invalid */ + ht->left = 0; + ht->right = 0; + } else { + if (*p < len_avail || + *p >= (len_avail + hf->tree_used)) + return (0);/* Invalid */ + ht = &(hf->tree[*p - len_avail]); + } + while (--extlen > 0) { + if (ptn & bit) { + if (ht->left < len_avail) { + ht->left = len_avail + hf->tree_used; + ht = &(hf->tree[hf->tree_used++]); + if (hf->tree_used > hf->tree_avail) + return (0);/* Invalid */ + ht->left = 0; + ht->right = 0; + } else { + ht = &(hf->tree[ht->left - len_avail]); + } + } else { + if (ht->right < len_avail) { + ht->right = len_avail + hf->tree_used; + ht = &(hf->tree[hf->tree_used++]); + if (hf->tree_used > hf->tree_avail) + return (0);/* Invalid */ + ht->left = 0; + ht->right = 0; + } else { + ht = &(hf->tree[ht->right - len_avail]); + } + } + bit >>= 1; + } + if (ptn & bit) { + if (ht->left != 0) + return (0);/* Invalid */ + ht->left = (uint16_t)i; + } else { + if (ht->right != 0) + return (0);/* Invalid */ + ht->right = (uint16_t)i; + } + } + return (1); +} + +static int +lzh_decode_huffman_tree(struct huffman *hf, unsigned rbits, int c) +{ + struct htree_t *ht; + int extlen; + + ht = hf->tree; + extlen = hf->shift_bits; + while (c >= hf->len_avail) { + c -= hf->len_avail; + if (extlen-- <= 0 || c >= hf->tree_used) + return (0); + if (rbits & (1U << extlen)) + c = ht[c].left; + else + c = ht[c].right; + } + return (c); +} + +static inline int +lzh_decode_huffman(struct huffman *hf, unsigned rbits) +{ + int c; + /* + * At first search an index table for a bit pattern. + * If it fails, search a huffman tree for. + */ + c = hf->tbl[rbits >> hf->shift_bits]; + if (c < hf->len_avail || hf->len_avail == 0) + return (c); + /* This bit pattern needs to be found out at a huffman tree. */ + return (lzh_decode_huffman_tree(hf, rbits, c)); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_mtree.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_mtree.c new file mode 100644 index 0000000..332944a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_mtree.c @@ -0,0 +1,2025 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2008 Joerg Sonnenberger + * Copyright (c) 2011-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 201165 2009-12-29 05:52:13Z kientzle $"); + +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#include +/* #include */ /* See archive_platform.h */ +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_CTYPE_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_rb.h" +#include "archive_read_private.h" +#include "archive_string.h" +#include "archive_pack_dev.h" + +#ifndef O_BINARY +#define O_BINARY 0 +#endif +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + +#define MTREE_HAS_DEVICE 0x0001 +#define MTREE_HAS_FFLAGS 0x0002 +#define MTREE_HAS_GID 0x0004 +#define MTREE_HAS_GNAME 0x0008 +#define MTREE_HAS_MTIME 0x0010 +#define MTREE_HAS_NLINK 0x0020 +#define MTREE_HAS_PERM 0x0040 +#define MTREE_HAS_SIZE 0x0080 +#define MTREE_HAS_TYPE 0x0100 +#define MTREE_HAS_UID 0x0200 +#define MTREE_HAS_UNAME 0x0400 + +#define MTREE_HAS_OPTIONAL 0x0800 +#define MTREE_HAS_NOCHANGE 0x1000 /* FreeBSD specific */ + +#define MAX_LINE_LEN (1024 * 1024) + +struct mtree_option { + struct mtree_option *next; + char *value; +}; + +struct mtree_entry { + struct archive_rb_node rbnode; + struct mtree_entry *next_dup; + struct mtree_entry *next; + struct mtree_option *options; + char *name; + char full; + char used; +}; + +struct mtree { + struct archive_string line; + size_t buffsize; + char *buff; + int64_t offset; + int fd; + int archive_format; + const char *archive_format_name; + struct mtree_entry *entries; + struct mtree_entry *this_entry; + struct archive_rb_tree entry_rbtree; + struct archive_string current_dir; + struct archive_string contents_name; + + struct archive_entry_linkresolver *resolver; + struct archive_rb_tree rbtree; + + int64_t cur_size; + char checkfs; +}; + +static int bid_keycmp(const char *, const char *, ssize_t); +static int cleanup(struct archive_read *); +static int detect_form(struct archive_read *, int *); +static int mtree_bid(struct archive_read *, int); +static int parse_file(struct archive_read *, struct archive_entry *, + struct mtree *, struct mtree_entry *, int *); +static void parse_escapes(char *, struct mtree_entry *); +static int parse_line(struct archive_read *, struct archive_entry *, + struct mtree *, struct mtree_entry *, int *); +static int parse_keyword(struct archive_read *, struct mtree *, + struct archive_entry *, struct mtree_option *, int *); +static int read_data(struct archive_read *a, + const void **buff, size_t *size, int64_t *offset); +static ssize_t readline(struct archive_read *, struct mtree *, char **, ssize_t); +static int skip(struct archive_read *a); +static int read_header(struct archive_read *, + struct archive_entry *); +static int64_t mtree_atol(char **, int base); + +/* + * There's no standard for TIME_T_MAX/TIME_T_MIN. So we compute them + * here. TODO: Move this to configure time, but be careful + * about cross-compile environments. + */ +static int64_t +get_time_t_max(void) +{ +#if defined(TIME_T_MAX) + return TIME_T_MAX; +#else + /* ISO C allows time_t to be a floating-point type, + but POSIX requires an integer type. The following + should work on any system that follows the POSIX + conventions. */ + if (((time_t)0) < ((time_t)-1)) { + /* Time_t is unsigned */ + return (~(time_t)0); + } else { + /* Time_t is signed. */ + /* Assume it's the same as int64_t or int32_t */ + if (sizeof(time_t) == sizeof(int64_t)) { + return (time_t)INT64_MAX; + } else { + return (time_t)INT32_MAX; + } + } +#endif +} + +static int64_t +get_time_t_min(void) +{ +#if defined(TIME_T_MIN) + return TIME_T_MIN; +#else + if (((time_t)0) < ((time_t)-1)) { + /* Time_t is unsigned */ + return (time_t)0; + } else { + /* Time_t is signed. */ + if (sizeof(time_t) == sizeof(int64_t)) { + return (time_t)INT64_MIN; + } else { + return (time_t)INT32_MIN; + } + } +#endif +} + +static int +archive_read_format_mtree_options(struct archive_read *a, + const char *key, const char *val) +{ + struct mtree *mtree; + + mtree = (struct mtree *)(a->format->data); + if (strcmp(key, "checkfs") == 0) { + /* Allows to read information missing from the mtree from the file system */ + if (val == NULL || val[0] == 0) { + mtree->checkfs = 0; + } else { + mtree->checkfs = 1; + } + return (ARCHIVE_OK); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +static void +free_options(struct mtree_option *head) +{ + struct mtree_option *next; + + for (; head != NULL; head = next) { + next = head->next; + free(head->value); + free(head); + } +} + +static int +mtree_cmp_node(const struct archive_rb_node *n1, + const struct archive_rb_node *n2) +{ + const struct mtree_entry *e1 = (const struct mtree_entry *)n1; + const struct mtree_entry *e2 = (const struct mtree_entry *)n2; + + return (strcmp(e1->name, e2->name)); +} + +static int +mtree_cmp_key(const struct archive_rb_node *n, const void *key) +{ + const struct mtree_entry *e = (const struct mtree_entry *)n; + + return (strcmp(e->name, key)); +} + +int +archive_read_support_format_mtree(struct archive *_a) +{ + static const struct archive_rb_tree_ops rb_ops = { + mtree_cmp_node, mtree_cmp_key, + }; + struct archive_read *a = (struct archive_read *)_a; + struct mtree *mtree; + int r; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_format_mtree"); + + mtree = (struct mtree *)calloc(1, sizeof(*mtree)); + if (mtree == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate mtree data"); + return (ARCHIVE_FATAL); + } + mtree->checkfs = 0; + mtree->fd = -1; + + __archive_rb_tree_init(&mtree->rbtree, &rb_ops); + + r = __archive_read_register_format(a, mtree, "mtree", + mtree_bid, archive_read_format_mtree_options, read_header, read_data, skip, NULL, cleanup, NULL, NULL); + + if (r != ARCHIVE_OK) + free(mtree); + return (ARCHIVE_OK); +} + +static int +cleanup(struct archive_read *a) +{ + struct mtree *mtree; + struct mtree_entry *p, *q; + + mtree = (struct mtree *)(a->format->data); + + p = mtree->entries; + while (p != NULL) { + q = p->next; + free(p->name); + free_options(p->options); + free(p); + p = q; + } + archive_string_free(&mtree->line); + archive_string_free(&mtree->current_dir); + archive_string_free(&mtree->contents_name); + archive_entry_linkresolver_free(mtree->resolver); + + free(mtree->buff); + free(mtree); + (a->format->data) = NULL; + return (ARCHIVE_OK); +} + +static ssize_t +get_line_size(const char *b, ssize_t avail, ssize_t *nlsize) +{ + ssize_t len; + + len = 0; + while (len < avail) { + switch (*b) { + case '\0':/* Non-ascii character or control character. */ + if (nlsize != NULL) + *nlsize = 0; + return (-1); + case '\r': + if (avail-len > 1 && b[1] == '\n') { + if (nlsize != NULL) + *nlsize = 2; + return (len+2); + } + /* FALL THROUGH */ + case '\n': + if (nlsize != NULL) + *nlsize = 1; + return (len+1); + default: + b++; + len++; + break; + } + } + if (nlsize != NULL) + *nlsize = 0; + return (avail); +} + +/* + * <---------------- ravail ---------------------> + * <-- diff ------> <--- avail -----------------> + * <---- len -----------> + * | Previous lines | line being parsed nl extra | + * ^ + * b + * + */ +static ssize_t +next_line(struct archive_read *a, + const char **b, ssize_t *avail, ssize_t *ravail, ssize_t *nl) +{ + ssize_t len; + int quit; + + quit = 0; + if (*avail == 0) { + *nl = 0; + len = 0; + } else + len = get_line_size(*b, *avail, nl); + /* + * Read bytes more while it does not reach the end of line. + */ + while (*nl == 0 && len == *avail && !quit) { + ssize_t diff = *ravail - *avail; + size_t nbytes_req = (*ravail+1023) & ~1023U; + ssize_t tested; + + /* + * Place an arbitrary limit on the line length. + * mtree is almost free-form input and without line length limits, + * it can consume a lot of memory. + */ + if (len >= MAX_LINE_LEN) + return (-1); + + /* Increase reading bytes if it is not enough to at least + * new two lines. */ + if (nbytes_req < (size_t)*ravail + 160) + nbytes_req <<= 1; + + *b = __archive_read_ahead(a, nbytes_req, avail); + if (*b == NULL) { + if (*ravail >= *avail) + return (0); + /* Reading bytes reaches the end of file. */ + *b = __archive_read_ahead(a, *avail, avail); + quit = 1; + } + *ravail = *avail; + *b += diff; + *avail -= diff; + tested = len;/* Skip some bytes we already determinated. */ + len = get_line_size(*b + len, *avail - len, nl); + if (len >= 0) + len += tested; + } + return (len); +} + +/* + * Compare characters with a mtree keyword. + * Returns the length of a mtree keyword if matched. + * Returns 0 if not matched. + */ +static int +bid_keycmp(const char *p, const char *key, ssize_t len) +{ + int match_len = 0; + + while (len > 0 && *p && *key) { + if (*p == *key) { + --len; + ++p; + ++key; + ++match_len; + continue; + } + return (0);/* Not match */ + } + if (*key != '\0') + return (0);/* Not match */ + + /* A following character should be specified characters */ + if (p[0] == '=' || p[0] == ' ' || p[0] == '\t' || + p[0] == '\n' || p[0] == '\r' || + (p[0] == '\\' && (p[1] == '\n' || p[1] == '\r'))) + return (match_len); + return (0);/* Not match */ +} + +/* + * Test whether the characters 'p' has is mtree keyword. + * Returns the length of a detected keyword. + * Returns 0 if any keywords were not found. + */ +static int +bid_keyword(const char *p, ssize_t len) +{ + static const char * const keys_c[] = { + "content", "contents", "cksum", NULL + }; + static const char * const keys_df[] = { + "device", "flags", NULL + }; + static const char * const keys_g[] = { + "gid", "gname", NULL + }; + static const char * const keys_il[] = { + "ignore", "inode", "link", NULL + }; + static const char * const keys_m[] = { + "md5", "md5digest", "mode", NULL + }; + static const char * const keys_no[] = { + "nlink", "nochange", "optional", NULL + }; + static const char * const keys_r[] = { + "resdevice", "rmd160", "rmd160digest", NULL + }; + static const char * const keys_s[] = { + "sha1", "sha1digest", + "sha256", "sha256digest", + "sha384", "sha384digest", + "sha512", "sha512digest", + "size", NULL + }; + static const char * const keys_t[] = { + "tags", "time", "type", NULL + }; + static const char * const keys_u[] = { + "uid", "uname", NULL + }; + const char * const *keys; + int i; + + switch (*p) { + case 'c': keys = keys_c; break; + case 'd': case 'f': keys = keys_df; break; + case 'g': keys = keys_g; break; + case 'i': case 'l': keys = keys_il; break; + case 'm': keys = keys_m; break; + case 'n': case 'o': keys = keys_no; break; + case 'r': keys = keys_r; break; + case 's': keys = keys_s; break; + case 't': keys = keys_t; break; + case 'u': keys = keys_u; break; + default: return (0);/* Unknown key */ + } + + for (i = 0; keys[i] != NULL; i++) { + int l = bid_keycmp(p, keys[i], len); + if (l > 0) + return (l); + } + return (0);/* Unknown key */ +} + +/* + * Test whether there is a set of mtree keywords. + * Returns the number of keyword. + * Returns -1 if we got incorrect sequence. + * This function expects a set of "keyword=value". + * When "unset" is specified, expects a set of "keyword". + */ +static int +bid_keyword_list(const char *p, ssize_t len, int unset, int last_is_path) +{ + int l; + int keycnt = 0; + + while (len > 0 && *p) { + int blank = 0; + + /* Test whether there are blank characters in the line. */ + while (len >0 && (*p == ' ' || *p == '\t')) { + ++p; + --len; + blank = 1; + } + if (*p == '\n' || *p == '\r') + break; + if (p[0] == '\\' && (p[1] == '\n' || p[1] == '\r')) + break; + if (!blank && !last_is_path) /* No blank character. */ + return (-1); + if (last_is_path && len == 0) + return (keycnt); + + if (unset) { + l = bid_keycmp(p, "all", len); + if (l > 0) + return (1); + } + /* Test whether there is a correct key in the line. */ + l = bid_keyword(p, len); + if (l == 0) + return (-1);/* Unknown keyword was found. */ + p += l; + len -= l; + keycnt++; + + /* Skip value */ + if (*p == '=') { + int value = 0; + ++p; + --len; + while (len > 0 && *p != ' ' && *p != '\t') { + ++p; + --len; + value = 1; + } + /* A keyword should have a its value unless + * "/unset" operation. */ + if (!unset && value == 0) + return (-1); + } + } + return (keycnt); +} + +static int +bid_entry(const char *p, ssize_t len, ssize_t nl, int *last_is_path) +{ + int f = 0; + static const unsigned char safe_char[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 0F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */ + /* !"$%&'()*+,-./ EXCLUSION:( )(#) */ + 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */ + /* 0123456789:;<>? EXCLUSION:(=) */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, /* 30 - 3F */ + /* @ABCDEFGHIJKLMNO */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */ + /* PQRSTUVWXYZ[\]^_ */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */ + /* `abcdefghijklmno */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */ + /* pqrstuvwxyz{|}~ */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* 70 - 7F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */ + }; + ssize_t ll; + const char *pp = p; + const char * const pp_end = pp + len; + + *last_is_path = 0; + /* + * Skip the path-name which is quoted. + */ + for (;pp < pp_end; ++pp) { + if (!safe_char[*(const unsigned char *)pp]) { + if (*pp != ' ' && *pp != '\t' && *pp != '\r' + && *pp != '\n') + f = 0; + break; + } + f = 1; + } + ll = pp_end - pp; + + /* If a path-name was not found at the first, try to check + * a mtree format(a.k.a form D) ``NetBSD's mtree -D'' creates, + * which places the path-name at the last. */ + if (f == 0) { + const char *pb = p + len - nl; + int name_len = 0; + int slash; + + /* The form D accepts only a single line for an entry. */ + if (pb-2 >= p && + pb[-1] == '\\' && (pb[-2] == ' ' || pb[-2] == '\t')) + return (-1); + if (pb-1 >= p && pb[-1] == '\\') + return (-1); + + slash = 0; + while (p <= --pb && *pb != ' ' && *pb != '\t') { + if (!safe_char[*(const unsigned char *)pb]) + return (-1); + name_len++; + /* The pathname should have a slash in this + * format. */ + if (*pb == '/') + slash = 1; + } + if (name_len == 0 || slash == 0) + return (-1); + /* If '/' is placed at the first in this field, this is not + * a valid filename. */ + if (pb[1] == '/') + return (-1); + ll = len - nl - name_len; + pp = p; + *last_is_path = 1; + } + + return (bid_keyword_list(pp, ll, 0, *last_is_path)); +} + +#define MAX_BID_ENTRY 3 + +static int +mtree_bid(struct archive_read *a, int best_bid) +{ + const char *signature = "#mtree"; + const char *p; + + (void)best_bid; /* UNUSED */ + + /* Now let's look at the actual header and see if it matches. */ + p = __archive_read_ahead(a, strlen(signature), NULL); + if (p == NULL) + return (-1); + + if (memcmp(p, signature, strlen(signature)) == 0) + return (8 * (int)strlen(signature)); + + /* + * There is not a mtree signature. Let's try to detect mtree format. + */ + return (detect_form(a, NULL)); +} + +static int +detect_form(struct archive_read *a, int *is_form_d) +{ + const char *p; + ssize_t avail, ravail; + ssize_t detected_bytes = 0, len, nl; + int entry_cnt = 0, multiline = 0; + int form_D = 0;/* The archive is generated by `NetBSD mtree -D' + * (In this source we call it `form D') . */ + + if (is_form_d != NULL) + *is_form_d = 0; + p = __archive_read_ahead(a, 1, &avail); + if (p == NULL) + return (-1); + ravail = avail; + for (;;) { + len = next_line(a, &p, &avail, &ravail, &nl); + /* The terminal character of the line should be + * a new line character, '\r\n' or '\n'. */ + if (len <= 0 || nl == 0) + break; + if (!multiline) { + /* Leading whitespace is never significant, + * ignore it. */ + while (len > 0 && (*p == ' ' || *p == '\t')) { + ++p; + --avail; + --len; + } + /* Skip comment or empty line. */ + if (p[0] == '#' || p[0] == '\n' || p[0] == '\r') { + p += len; + avail -= len; + continue; + } + } else { + /* A continuance line; the terminal + * character of previous line was '\' character. */ + if (bid_keyword_list(p, len, 0, 0) <= 0) + break; + if (multiline == 1) + detected_bytes += len; + if (p[len-nl-1] != '\\') { + if (multiline == 1 && + ++entry_cnt >= MAX_BID_ENTRY) + break; + multiline = 0; + } + p += len; + avail -= len; + continue; + } + if (p[0] != '/') { + int last_is_path, keywords; + + keywords = bid_entry(p, len, nl, &last_is_path); + if (keywords >= 0) { + detected_bytes += len; + if (form_D == 0) { + if (last_is_path) + form_D = 1; + else if (keywords > 0) + /* This line is not `form D'. */ + form_D = -1; + } else if (form_D == 1) { + if (!last_is_path && keywords > 0) + /* This this is not `form D' + * and We cannot accept mixed + * format. */ + break; + } + if (!last_is_path && p[len-nl-1] == '\\') + /* This line continues. */ + multiline = 1; + else { + /* We've got plenty of correct lines + * to assume that this file is a mtree + * format. */ + if (++entry_cnt >= MAX_BID_ENTRY) + break; + } + } else + break; + } else if (len > 4 && strncmp(p, "/set", 4) == 0) { + if (bid_keyword_list(p+4, len-4, 0, 0) <= 0) + break; + /* This line continues. */ + if (p[len-nl-1] == '\\') + multiline = 2; + } else if (len > 6 && strncmp(p, "/unset", 6) == 0) { + if (bid_keyword_list(p+6, len-6, 1, 0) <= 0) + break; + /* This line continues. */ + if (p[len-nl-1] == '\\') + multiline = 2; + } else + break; + + /* Test next line. */ + p += len; + avail -= len; + } + if (entry_cnt >= MAX_BID_ENTRY || (entry_cnt > 0 && len == 0)) { + if (is_form_d != NULL) { + if (form_D == 1) + *is_form_d = 1; + } + return (32); + } + + return (0); +} + +/* + * The extended mtree format permits multiple lines specifying + * attributes for each file. For those entries, only the last line + * is actually used. Practically speaking, that means we have + * to read the entire mtree file into memory up front. + * + * The parsing is done in two steps. First, it is decided if a line + * changes the global defaults and if it is, processed accordingly. + * Otherwise, the options of the line are merged with the current + * global options. + */ +static int +add_option(struct archive_read *a, struct mtree_option **global, + const char *value, size_t len) +{ + struct mtree_option *opt; + + if ((opt = malloc(sizeof(*opt))) == NULL) { + archive_set_error(&a->archive, errno, "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + if ((opt->value = malloc(len + 1)) == NULL) { + free(opt); + archive_set_error(&a->archive, errno, "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + memcpy(opt->value, value, len); + opt->value[len] = '\0'; + opt->next = *global; + *global = opt; + return (ARCHIVE_OK); +} + +static void +remove_option(struct mtree_option **global, const char *value, size_t len) +{ + struct mtree_option *iter, *last; + + last = NULL; + for (iter = *global; iter != NULL; last = iter, iter = iter->next) { + if (strncmp(iter->value, value, len) == 0 && + (iter->value[len] == '\0' || + iter->value[len] == '=')) + break; + } + if (iter == NULL) + return; + if (last == NULL) + *global = iter->next; + else + last->next = iter->next; + + free(iter->value); + free(iter); +} + +static int +process_global_set(struct archive_read *a, + struct mtree_option **global, const char *line) +{ + const char *next, *eq; + size_t len; + int r; + + line += 4; + for (;;) { + next = line + strspn(line, " \t\r\n"); + if (*next == '\0') + return (ARCHIVE_OK); + line = next; + next = line + strcspn(line, " \t\r\n"); + eq = strchr(line, '='); + if (eq > next) + len = next - line; + else + len = eq - line; + + remove_option(global, line, len); + r = add_option(a, global, line, next - line); + if (r != ARCHIVE_OK) + return (r); + line = next; + } +} + +static int +process_global_unset(struct archive_read *a, + struct mtree_option **global, const char *line) +{ + const char *next; + size_t len; + + line += 6; + if (strchr(line, '=') != NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "/unset shall not contain `='"); + return ARCHIVE_FATAL; + } + + for (;;) { + next = line + strspn(line, " \t\r\n"); + if (*next == '\0') + return (ARCHIVE_OK); + line = next; + len = strcspn(line, " \t\r\n"); + + if (len == 3 && strncmp(line, "all", 3) == 0) { + free_options(*global); + *global = NULL; + } else { + remove_option(global, line, len); + } + + line += len; + } +} + +static int +process_add_entry(struct archive_read *a, struct mtree *mtree, + struct mtree_option **global, const char *line, ssize_t line_len, + struct mtree_entry **last_entry, int is_form_d) +{ + struct mtree_entry *entry; + struct mtree_option *iter; + const char *next, *eq, *name, *end; + size_t name_len, len; + int r, i; + + if ((entry = malloc(sizeof(*entry))) == NULL) { + archive_set_error(&a->archive, errno, "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + entry->next = NULL; + entry->options = NULL; + entry->name = NULL; + entry->used = 0; + entry->full = 0; + + /* Add this entry to list. */ + if (*last_entry == NULL) + mtree->entries = entry; + else + (*last_entry)->next = entry; + *last_entry = entry; + + if (is_form_d) { + /* Filename is last item on line. */ + /* Adjust line_len to trim trailing whitespace */ + while (line_len > 0) { + char last_character = line[line_len - 1]; + if (last_character == '\r' + || last_character == '\n' + || last_character == '\t' + || last_character == ' ') { + line_len--; + } else { + break; + } + } + /* Name starts after the last whitespace separator */ + name = line; + for (i = 0; i < line_len; i++) { + if (line[i] == '\r' + || line[i] == '\n' + || line[i] == '\t' + || line[i] == ' ') { + name = line + i + 1; + } + } + name_len = line + line_len - name; + end = name; + } else { + /* Filename is first item on line */ + name_len = strcspn(line, " \t\r\n"); + name = line; + line += name_len; + end = line + line_len; + } + /* name/name_len is the name within the line. */ + /* line..end brackets the entire line except the name */ + + if ((entry->name = malloc(name_len + 1)) == NULL) { + archive_set_error(&a->archive, errno, "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + + memcpy(entry->name, name, name_len); + entry->name[name_len] = '\0'; + parse_escapes(entry->name, entry); + + entry->next_dup = NULL; + if (entry->full) { + if (!__archive_rb_tree_insert_node(&mtree->rbtree, &entry->rbnode)) { + struct mtree_entry *alt; + alt = (struct mtree_entry *)__archive_rb_tree_find_node( + &mtree->rbtree, entry->name); + while (alt->next_dup) + alt = alt->next_dup; + alt->next_dup = entry; + } + } + + for (iter = *global; iter != NULL; iter = iter->next) { + r = add_option(a, &entry->options, iter->value, + strlen(iter->value)); + if (r != ARCHIVE_OK) + return (r); + } + + for (;;) { + next = line + strspn(line, " \t\r\n"); + if (*next == '\0') + return (ARCHIVE_OK); + if (next >= end) + return (ARCHIVE_OK); + line = next; + next = line + strcspn(line, " \t\r\n"); + eq = strchr(line, '='); + if (eq == NULL || eq > next) + len = next - line; + else + len = eq - line; + + remove_option(&entry->options, line, len); + r = add_option(a, &entry->options, line, next - line); + if (r != ARCHIVE_OK) + return (r); + line = next; + } +} + +static int +read_mtree(struct archive_read *a, struct mtree *mtree) +{ + ssize_t len; + uintmax_t counter; + char *p, *s; + struct mtree_option *global; + struct mtree_entry *last_entry; + int r, is_form_d; + + mtree->archive_format = ARCHIVE_FORMAT_MTREE; + mtree->archive_format_name = "mtree"; + + global = NULL; + last_entry = NULL; + + (void)detect_form(a, &is_form_d); + + for (counter = 1; ; ++counter) { + r = ARCHIVE_OK; + len = readline(a, mtree, &p, 65536); + if (len == 0) { + mtree->this_entry = mtree->entries; + free_options(global); + return (ARCHIVE_OK); + } + if (len < 0) { + free_options(global); + return ((int)len); + } + /* Leading whitespace is never significant, ignore it. */ + while (*p == ' ' || *p == '\t') { + ++p; + --len; + } + /* Skip content lines and blank lines. */ + if (*p == '#') + continue; + if (*p == '\r' || *p == '\n' || *p == '\0') + continue; + /* Non-printable characters are not allowed */ + for (s = p;s < p + len - 1; s++) { + if (!isprint(*s)) { + r = ARCHIVE_FATAL; + break; + } + } + if (r != ARCHIVE_OK) + break; + if (*p != '/') { + r = process_add_entry(a, mtree, &global, p, len, + &last_entry, is_form_d); + } else if (len > 4 && strncmp(p, "/set", 4) == 0) { + if (p[4] != ' ' && p[4] != '\t') + break; + r = process_global_set(a, &global, p); + } else if (len > 6 && strncmp(p, "/unset", 6) == 0) { + if (p[6] != ' ' && p[6] != '\t') + break; + r = process_global_unset(a, &global, p); + } else + break; + + if (r != ARCHIVE_OK) { + free_options(global); + return r; + } + } + + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Can't parse line %ju", counter); + free_options(global); + return (ARCHIVE_FATAL); +} + +/* + * Read in the entire mtree file into memory on the first request. + * Then use the next unused file to satisfy each header request. + */ +static int +read_header(struct archive_read *a, struct archive_entry *entry) +{ + struct mtree *mtree; + char *p; + int r, use_next; + + mtree = (struct mtree *)(a->format->data); + + if (mtree->fd >= 0) { + close(mtree->fd); + mtree->fd = -1; + } + + if (mtree->entries == NULL) { + mtree->resolver = archive_entry_linkresolver_new(); + if (mtree->resolver == NULL) + return ARCHIVE_FATAL; + archive_entry_linkresolver_set_strategy(mtree->resolver, + ARCHIVE_FORMAT_MTREE); + r = read_mtree(a, mtree); + if (r != ARCHIVE_OK) + return (r); + } + + a->archive.archive_format = mtree->archive_format; + a->archive.archive_format_name = mtree->archive_format_name; + + for (;;) { + if (mtree->this_entry == NULL) + return (ARCHIVE_EOF); + if (strcmp(mtree->this_entry->name, "..") == 0) { + mtree->this_entry->used = 1; + if (archive_strlen(&mtree->current_dir) > 0) { + /* Roll back current path. */ + p = mtree->current_dir.s + + mtree->current_dir.length - 1; + while (p >= mtree->current_dir.s && *p != '/') + --p; + if (p >= mtree->current_dir.s) + --p; + mtree->current_dir.length + = p - mtree->current_dir.s + 1; + } + } + if (!mtree->this_entry->used) { + use_next = 0; + r = parse_file(a, entry, mtree, mtree->this_entry, + &use_next); + if (use_next == 0) + return (r); + } + mtree->this_entry = mtree->this_entry->next; + } +} + +/* + * A single file can have multiple lines contribute specifications. + * Parse as many lines as necessary, then pull additional information + * from a backing file on disk as necessary. + */ +static int +parse_file(struct archive_read *a, struct archive_entry *entry, + struct mtree *mtree, struct mtree_entry *mentry, int *use_next) +{ + const char *path; + struct stat st_storage, *st; + struct mtree_entry *mp; + struct archive_entry *sparse_entry; + int r = ARCHIVE_OK, r1, parsed_kws; + + mentry->used = 1; + + /* Initialize reasonable defaults. */ + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + archive_string_empty(&mtree->contents_name); + + /* Parse options from this line. */ + parsed_kws = 0; + r = parse_line(a, entry, mtree, mentry, &parsed_kws); + + if (mentry->full) { + archive_entry_copy_pathname(entry, mentry->name); + /* + * "Full" entries are allowed to have multiple lines + * and those lines aren't required to be adjacent. We + * don't support multiple lines for "relative" entries + * nor do we make any attempt to merge data from + * separate "relative" and "full" entries. (Merging + * "relative" and "full" entries would require dealing + * with pathname canonicalization, which is a very + * tricky subject.) + */ + mp = (struct mtree_entry *)__archive_rb_tree_find_node( + &mtree->rbtree, mentry->name); + for (; mp; mp = mp->next_dup) { + if (mp->full && !mp->used) { + /* Later lines override earlier ones. */ + mp->used = 1; + r1 = parse_line(a, entry, mtree, mp, &parsed_kws); + if (r1 < r) + r = r1; + } + } + } else { + /* + * Relative entries require us to construct + * the full path and possibly update the + * current directory. + */ + size_t n = archive_strlen(&mtree->current_dir); + if (n > 0) + archive_strcat(&mtree->current_dir, "/"); + archive_strcat(&mtree->current_dir, mentry->name); + archive_entry_copy_pathname(entry, mtree->current_dir.s); + if (archive_entry_filetype(entry) != AE_IFDIR) + mtree->current_dir.length = n; + } + + if (mtree->checkfs) { + /* + * Try to open and stat the file to get the real size + * and other file info. It would be nice to avoid + * this here so that getting a listing of an mtree + * wouldn't require opening every referenced contents + * file. But then we wouldn't know the actual + * contents size, so I don't see a really viable way + * around this. (Also, we may want to someday pull + * other unspecified info from the contents file on + * disk.) + */ + mtree->fd = -1; + if (archive_strlen(&mtree->contents_name) > 0) + path = mtree->contents_name.s; + else + path = archive_entry_pathname(entry); + + if (archive_entry_filetype(entry) == AE_IFREG || + archive_entry_filetype(entry) == AE_IFDIR) { + mtree->fd = open(path, O_RDONLY | O_BINARY | O_CLOEXEC); + __archive_ensure_cloexec_flag(mtree->fd); + if (mtree->fd == -1 && + (errno != ENOENT || + archive_strlen(&mtree->contents_name) > 0)) { + archive_set_error(&a->archive, errno, + "Can't open %s", path); + r = ARCHIVE_WARN; + } + } + + st = &st_storage; + if (mtree->fd >= 0) { + if (fstat(mtree->fd, st) == -1) { + archive_set_error(&a->archive, errno, + "Could not fstat %s", path); + r = ARCHIVE_WARN; + /* If we can't stat it, don't keep it open. */ + close(mtree->fd); + mtree->fd = -1; + st = NULL; + } + } else if (lstat(path, st) == -1) { + st = NULL; + } + + /* + * Check for a mismatch between the type in the specification + * and the type of the contents object on disk. + */ + if (st != NULL) { + if (((st->st_mode & S_IFMT) == S_IFREG && + archive_entry_filetype(entry) == AE_IFREG) +#ifdef S_IFLNK + ||((st->st_mode & S_IFMT) == S_IFLNK && + archive_entry_filetype(entry) == AE_IFLNK) +#endif +#ifdef S_IFSOCK + ||((st->st_mode & S_IFSOCK) == S_IFSOCK && + archive_entry_filetype(entry) == AE_IFSOCK) +#endif +#ifdef S_IFCHR + ||((st->st_mode & S_IFMT) == S_IFCHR && + archive_entry_filetype(entry) == AE_IFCHR) +#endif +#ifdef S_IFBLK + ||((st->st_mode & S_IFMT) == S_IFBLK && + archive_entry_filetype(entry) == AE_IFBLK) +#endif + ||((st->st_mode & S_IFMT) == S_IFDIR && + archive_entry_filetype(entry) == AE_IFDIR) +#ifdef S_IFIFO + ||((st->st_mode & S_IFMT) == S_IFIFO && + archive_entry_filetype(entry) == AE_IFIFO) +#endif + ) { + /* Types match. */ + } else { + /* Types don't match; bail out gracefully. */ + if (mtree->fd >= 0) + close(mtree->fd); + mtree->fd = -1; + if (parsed_kws & MTREE_HAS_OPTIONAL) { + /* It's not an error for an optional + * entry to not match disk. */ + *use_next = 1; + } else if (r == ARCHIVE_OK) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "mtree specification has different" + " type for %s", + archive_entry_pathname(entry)); + r = ARCHIVE_WARN; + } + return (r); + } + } + + /* + * If there is a contents file on disk, pick some of the + * metadata from that file. For most of these, we only + * set it from the contents if it wasn't already parsed + * from the specification. + */ + if (st != NULL) { + if (((parsed_kws & MTREE_HAS_DEVICE) == 0 || + (parsed_kws & MTREE_HAS_NOCHANGE) != 0) && + (archive_entry_filetype(entry) == AE_IFCHR || + archive_entry_filetype(entry) == AE_IFBLK)) + archive_entry_set_rdev(entry, st->st_rdev); + if ((parsed_kws & (MTREE_HAS_GID | MTREE_HAS_GNAME)) + == 0 || + (parsed_kws & MTREE_HAS_NOCHANGE) != 0) + archive_entry_set_gid(entry, st->st_gid); + if ((parsed_kws & (MTREE_HAS_UID | MTREE_HAS_UNAME)) + == 0 || + (parsed_kws & MTREE_HAS_NOCHANGE) != 0) + archive_entry_set_uid(entry, st->st_uid); + if ((parsed_kws & MTREE_HAS_MTIME) == 0 || + (parsed_kws & MTREE_HAS_NOCHANGE) != 0) { +#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC + archive_entry_set_mtime(entry, st->st_mtime, + st->st_mtimespec.tv_nsec); +#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC + archive_entry_set_mtime(entry, st->st_mtime, + st->st_mtim.tv_nsec); +#elif HAVE_STRUCT_STAT_ST_MTIME_N + archive_entry_set_mtime(entry, st->st_mtime, + st->st_mtime_n); +#elif HAVE_STRUCT_STAT_ST_UMTIME + archive_entry_set_mtime(entry, st->st_mtime, + st->st_umtime*1000); +#elif HAVE_STRUCT_STAT_ST_MTIME_USEC + archive_entry_set_mtime(entry, st->st_mtime, + st->st_mtime_usec*1000); +#else + archive_entry_set_mtime(entry, st->st_mtime, 0); +#endif + } + if ((parsed_kws & MTREE_HAS_NLINK) == 0 || + (parsed_kws & MTREE_HAS_NOCHANGE) != 0) + archive_entry_set_nlink(entry, st->st_nlink); + if ((parsed_kws & MTREE_HAS_PERM) == 0 || + (parsed_kws & MTREE_HAS_NOCHANGE) != 0) + archive_entry_set_perm(entry, st->st_mode); + if ((parsed_kws & MTREE_HAS_SIZE) == 0 || + (parsed_kws & MTREE_HAS_NOCHANGE) != 0) + archive_entry_set_size(entry, st->st_size); + archive_entry_set_ino(entry, st->st_ino); + archive_entry_set_dev(entry, st->st_dev); + + archive_entry_linkify(mtree->resolver, &entry, + &sparse_entry); + } else if (parsed_kws & MTREE_HAS_OPTIONAL) { + /* + * Couldn't open the entry, stat it or the on-disk type + * didn't match. If this entry is optional, just + * ignore it and read the next header entry. + */ + *use_next = 1; + return ARCHIVE_OK; + } + } + + mtree->cur_size = archive_entry_size(entry); + mtree->offset = 0; + + return r; +} + +/* + * Each line contains a sequence of keywords. + */ +static int +parse_line(struct archive_read *a, struct archive_entry *entry, + struct mtree *mtree, struct mtree_entry *mp, int *parsed_kws) +{ + struct mtree_option *iter; + int r = ARCHIVE_OK, r1; + + for (iter = mp->options; iter != NULL; iter = iter->next) { + r1 = parse_keyword(a, mtree, entry, iter, parsed_kws); + if (r1 < r) + r = r1; + } + if (r == ARCHIVE_OK && (*parsed_kws & MTREE_HAS_TYPE) == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Missing type keyword in mtree specification"); + return (ARCHIVE_WARN); + } + return (r); +} + +/* + * Device entries have one of the following forms: + * - raw dev_t + * - format,major,minor[,subdevice] + * When parsing succeeded, `pdev' will contain the appropriate dev_t value. + */ + +/* strsep() is not in C90, but strcspn() is. */ +/* Taken from http://unixpapa.com/incnote/string.html */ +static char * +la_strsep(char **sp, const char *sep) +{ + char *p, *s; + if (sp == NULL || *sp == NULL || **sp == '\0') + return(NULL); + s = *sp; + p = s + strcspn(s, sep); + if (*p != '\0') + *p++ = '\0'; + *sp = p; + return(s); +} + +static int +parse_device(dev_t *pdev, struct archive *a, char *val) +{ +#define MAX_PACK_ARGS 3 + unsigned long numbers[MAX_PACK_ARGS]; + char *p, *dev; + int argc; + pack_t *pack; + dev_t result; + const char *error = NULL; + + memset(pdev, 0, sizeof(*pdev)); + if ((dev = strchr(val, ',')) != NULL) { + /* + * Device's major/minor are given in a specified format. + * Decode and pack it accordingly. + */ + *dev++ = '\0'; + if ((pack = pack_find(val)) == NULL) { + archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, + "Unknown format `%s'", val); + return ARCHIVE_WARN; + } + argc = 0; + while ((p = la_strsep(&dev, ",")) != NULL) { + if (*p == '\0') { + archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, + "Missing number"); + return ARCHIVE_WARN; + } + if (argc >= MAX_PACK_ARGS) { + archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, + "Too many arguments"); + return ARCHIVE_WARN; + } + numbers[argc++] = (unsigned long)mtree_atol(&p, 0); + } + if (argc < 2) { + archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, + "Not enough arguments"); + return ARCHIVE_WARN; + } + result = (*pack)(argc, numbers, &error); + if (error != NULL) { + archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, + "%s", error); + return ARCHIVE_WARN; + } + } else { + /* file system raw value. */ + result = (dev_t)mtree_atol(&val, 0); + } + *pdev = result; + return ARCHIVE_OK; +#undef MAX_PACK_ARGS +} + +/* + * Parse a single keyword and its value. + */ +static int +parse_keyword(struct archive_read *a, struct mtree *mtree, + struct archive_entry *entry, struct mtree_option *opt, int *parsed_kws) +{ + char *val, *key; + + key = opt->value; + + if (*key == '\0') + return (ARCHIVE_OK); + + if (strcmp(key, "nochange") == 0) { + *parsed_kws |= MTREE_HAS_NOCHANGE; + return (ARCHIVE_OK); + } + if (strcmp(key, "optional") == 0) { + *parsed_kws |= MTREE_HAS_OPTIONAL; + return (ARCHIVE_OK); + } + if (strcmp(key, "ignore") == 0) { + /* + * The mtree processing is not recursive, so + * recursion will only happen for explicitly listed + * entries. + */ + return (ARCHIVE_OK); + } + + val = strchr(key, '='); + if (val == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Malformed attribute \"%s\" (%d)", key, key[0]); + return (ARCHIVE_WARN); + } + + *val = '\0'; + ++val; + + switch (key[0]) { + case 'c': + if (strcmp(key, "content") == 0 + || strcmp(key, "contents") == 0) { + parse_escapes(val, NULL); + archive_strcpy(&mtree->contents_name, val); + break; + } + if (strcmp(key, "cksum") == 0) + break; + __LA_FALLTHROUGH; + case 'd': + if (strcmp(key, "device") == 0) { + /* stat(2) st_rdev field, e.g. the major/minor IDs + * of a char/block special file */ + int r; + dev_t dev; + + *parsed_kws |= MTREE_HAS_DEVICE; + r = parse_device(&dev, &a->archive, val); + if (r == ARCHIVE_OK) + archive_entry_set_rdev(entry, dev); + return r; + } + __LA_FALLTHROUGH; + case 'f': + if (strcmp(key, "flags") == 0) { + *parsed_kws |= MTREE_HAS_FFLAGS; + archive_entry_copy_fflags_text(entry, val); + break; + } + __LA_FALLTHROUGH; + case 'g': + if (strcmp(key, "gid") == 0) { + *parsed_kws |= MTREE_HAS_GID; + archive_entry_set_gid(entry, mtree_atol(&val, 10)); + break; + } + if (strcmp(key, "gname") == 0) { + *parsed_kws |= MTREE_HAS_GNAME; + archive_entry_copy_gname(entry, val); + break; + } + __LA_FALLTHROUGH; + case 'i': + if (strcmp(key, "inode") == 0) { + archive_entry_set_ino(entry, mtree_atol(&val, 10)); + break; + } + __LA_FALLTHROUGH; + case 'l': + if (strcmp(key, "link") == 0) { + archive_entry_copy_symlink(entry, val); + break; + } + __LA_FALLTHROUGH; + case 'm': + if (strcmp(key, "md5") == 0 || strcmp(key, "md5digest") == 0) + break; + if (strcmp(key, "mode") == 0) { + if (val[0] >= '0' && val[0] <= '7') { + *parsed_kws |= MTREE_HAS_PERM; + archive_entry_set_perm(entry, + (mode_t)mtree_atol(&val, 8)); + } else { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Symbolic or non-octal mode \"%s\" unsupported", val); + return ARCHIVE_WARN; + } + break; + } + __LA_FALLTHROUGH; + case 'n': + if (strcmp(key, "nlink") == 0) { + *parsed_kws |= MTREE_HAS_NLINK; + archive_entry_set_nlink(entry, + (unsigned int)mtree_atol(&val, 10)); + break; + } + __LA_FALLTHROUGH; + case 'r': + if (strcmp(key, "resdevice") == 0) { + /* stat(2) st_dev field, e.g. the device ID where the + * inode resides */ + int r; + dev_t dev; + + r = parse_device(&dev, &a->archive, val); + if (r == ARCHIVE_OK) + archive_entry_set_dev(entry, dev); + return r; + } + if (strcmp(key, "rmd160") == 0 || + strcmp(key, "rmd160digest") == 0) + break; + __LA_FALLTHROUGH; + case 's': + if (strcmp(key, "sha1") == 0 || strcmp(key, "sha1digest") == 0) + break; + if (strcmp(key, "sha256") == 0 || + strcmp(key, "sha256digest") == 0) + break; + if (strcmp(key, "sha384") == 0 || + strcmp(key, "sha384digest") == 0) + break; + if (strcmp(key, "sha512") == 0 || + strcmp(key, "sha512digest") == 0) + break; + if (strcmp(key, "size") == 0) { + archive_entry_set_size(entry, mtree_atol(&val, 10)); + break; + } + __LA_FALLTHROUGH; + case 't': + if (strcmp(key, "tags") == 0) { + /* + * Comma delimited list of tags. + * Ignore the tags for now, but the interface + * should be extended to allow inclusion/exclusion. + */ + break; + } + if (strcmp(key, "time") == 0) { + int64_t m; + int64_t my_time_t_max = get_time_t_max(); + int64_t my_time_t_min = get_time_t_min(); + long ns = 0; + + *parsed_kws |= MTREE_HAS_MTIME; + m = mtree_atol(&val, 10); + /* Replicate an old mtree bug: + * 123456789.1 represents 123456789 + * seconds and 1 nanosecond. */ + if (*val == '.') { + ++val; + ns = (long)mtree_atol(&val, 10); + if (ns < 0) + ns = 0; + else if (ns > 999999999) + ns = 999999999; + } + if (m > my_time_t_max) + m = my_time_t_max; + else if (m < my_time_t_min) + m = my_time_t_min; + archive_entry_set_mtime(entry, (time_t)m, ns); + break; + } + if (strcmp(key, "type") == 0) { + switch (val[0]) { + case 'b': + if (strcmp(val, "block") == 0) { + archive_entry_set_filetype(entry, AE_IFBLK); + break; + } + __LA_FALLTHROUGH; + case 'c': + if (strcmp(val, "char") == 0) { + archive_entry_set_filetype(entry, + AE_IFCHR); + break; + } + __LA_FALLTHROUGH; + case 'd': + if (strcmp(val, "dir") == 0) { + archive_entry_set_filetype(entry, + AE_IFDIR); + break; + } + __LA_FALLTHROUGH; + case 'f': + if (strcmp(val, "fifo") == 0) { + archive_entry_set_filetype(entry, + AE_IFIFO); + break; + } + if (strcmp(val, "file") == 0) { + archive_entry_set_filetype(entry, + AE_IFREG); + break; + } + __LA_FALLTHROUGH; + case 'l': + if (strcmp(val, "link") == 0) { + archive_entry_set_filetype(entry, + AE_IFLNK); + break; + } + __LA_FALLTHROUGH; + default: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Unrecognized file type \"%s\"; " + "assuming \"file\"", val); + archive_entry_set_filetype(entry, AE_IFREG); + return (ARCHIVE_WARN); + } + *parsed_kws |= MTREE_HAS_TYPE; + break; + } + __LA_FALLTHROUGH; + case 'u': + if (strcmp(key, "uid") == 0) { + *parsed_kws |= MTREE_HAS_UID; + archive_entry_set_uid(entry, mtree_atol(&val, 10)); + break; + } + if (strcmp(key, "uname") == 0) { + *parsed_kws |= MTREE_HAS_UNAME; + archive_entry_copy_uname(entry, val); + break; + } + __LA_FALLTHROUGH; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Unrecognized key %s=%s", key, val); + return (ARCHIVE_WARN); + } + return (ARCHIVE_OK); +} + +static int +read_data(struct archive_read *a, const void **buff, size_t *size, + int64_t *offset) +{ + size_t bytes_to_read; + ssize_t bytes_read; + struct mtree *mtree; + + mtree = (struct mtree *)(a->format->data); + if (mtree->fd < 0) { + *buff = NULL; + *offset = 0; + *size = 0; + return (ARCHIVE_EOF); + } + if (mtree->buff == NULL) { + mtree->buffsize = 64 * 1024; + mtree->buff = malloc(mtree->buffsize); + if (mtree->buff == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + } + + *buff = mtree->buff; + *offset = mtree->offset; + if ((int64_t)mtree->buffsize > mtree->cur_size - mtree->offset) + bytes_to_read = (size_t)(mtree->cur_size - mtree->offset); + else + bytes_to_read = mtree->buffsize; + bytes_read = read(mtree->fd, mtree->buff, bytes_to_read); + if (bytes_read < 0) { + archive_set_error(&a->archive, errno, "Can't read"); + return (ARCHIVE_WARN); + } + if (bytes_read == 0) { + *size = 0; + return (ARCHIVE_EOF); + } + mtree->offset += bytes_read; + *size = bytes_read; + return (ARCHIVE_OK); +} + +/* Skip does nothing except possibly close the contents file. */ +static int +skip(struct archive_read *a) +{ + struct mtree *mtree; + + mtree = (struct mtree *)(a->format->data); + if (mtree->fd >= 0) { + close(mtree->fd); + mtree->fd = -1; + } + return (ARCHIVE_OK); +} + +/* + * Since parsing backslash sequences always makes strings shorter, + * we can always do this conversion in-place. + */ +static void +parse_escapes(char *src, struct mtree_entry *mentry) +{ + char *dest = src; + char c; + + if (mentry != NULL && strcmp(src, ".") == 0) + mentry->full = 1; + + while (*src != '\0') { + c = *src++; + if (c == '/' && mentry != NULL) + mentry->full = 1; + if (c == '\\') { + switch (src[0]) { + case '0': + if (src[1] < '0' || src[1] > '7') { + c = 0; + ++src; + break; + } + /* FALLTHROUGH */ + case '1': + case '2': + case '3': + if (src[1] >= '0' && src[1] <= '7' && + src[2] >= '0' && src[2] <= '7') { + c = (src[0] - '0') << 6; + c |= (src[1] - '0') << 3; + c |= (src[2] - '0'); + src += 3; + } + break; + case 'a': + c = '\a'; + ++src; + break; + case 'b': + c = '\b'; + ++src; + break; + case 'f': + c = '\f'; + ++src; + break; + case 'n': + c = '\n'; + ++src; + break; + case 'r': + c = '\r'; + ++src; + break; + case 's': + c = ' '; + ++src; + break; + case 't': + c = '\t'; + ++src; + break; + case 'v': + c = '\v'; + ++src; + break; + case '\\': + c = '\\'; + ++src; + break; + } + } + *dest++ = c; + } + *dest = '\0'; +} + +/* Parse a hex digit. */ +static int +parsedigit(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + else if (c >= 'a' && c <= 'f') + return c - 'a'; + else if (c >= 'A' && c <= 'F') + return c - 'A'; + else + return -1; +} + +/* + * Note that this implementation does not (and should not!) obey + * locale settings; you cannot simply substitute strtol here, since + * it does obey locale. + */ +static int64_t +mtree_atol(char **p, int base) +{ + int64_t l, limit; + int digit, last_digit_limit; + + if (base == 0) { + if (**p != '0') + base = 10; + else if ((*p)[1] == 'x' || (*p)[1] == 'X') { + *p += 2; + base = 16; + } else { + base = 8; + } + } + + if (**p == '-') { + limit = INT64_MIN / base; + last_digit_limit = INT64_MIN % base; + ++(*p); + + l = 0; + digit = parsedigit(**p); + while (digit >= 0 && digit < base) { + if (l < limit || (l == limit && digit > last_digit_limit)) + return INT64_MIN; + l = (l * base) - digit; + digit = parsedigit(*++(*p)); + } + return l; + } else { + limit = INT64_MAX / base; + last_digit_limit = INT64_MAX % base; + + l = 0; + digit = parsedigit(**p); + while (digit >= 0 && digit < base) { + if (l > limit || (l == limit && digit > last_digit_limit)) + return INT64_MAX; + l = (l * base) + digit; + digit = parsedigit(*++(*p)); + } + return l; + } +} + +/* + * Returns length of line (including trailing newline) + * or negative on error. 'start' argument is updated to + * point to first character of line. + */ +static ssize_t +readline(struct archive_read *a, struct mtree *mtree, char **start, + ssize_t limit) +{ + ssize_t bytes_read; + ssize_t total_size = 0; + ssize_t find_off = 0; + const void *t; + void *nl; + char *u; + + /* Accumulate line in a line buffer. */ + for (;;) { + /* Read some more. */ + t = __archive_read_ahead(a, 1, &bytes_read); + if (t == NULL) + return (0); + if (bytes_read < 0) + return (ARCHIVE_FATAL); + nl = memchr(t, '\n', bytes_read); + /* If we found '\n', trim the read to end exactly there. */ + if (nl != NULL) { + bytes_read = ((const char *)nl) - ((const char *)t) + 1; + } + if (total_size + bytes_read + 1 > limit) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Line too long"); + return (ARCHIVE_FATAL); + } + if (archive_string_ensure(&mtree->line, + total_size + bytes_read + 1) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate working buffer"); + return (ARCHIVE_FATAL); + } + /* Append new bytes to string. */ + memcpy(mtree->line.s + total_size, t, bytes_read); + __archive_read_consume(a, bytes_read); + total_size += bytes_read; + mtree->line.s[total_size] = '\0'; + + for (u = mtree->line.s + find_off; *u; ++u) { + if (u[0] == '\n') { + /* Ends with unescaped newline. */ + *start = mtree->line.s; + return total_size; + } else if (u[0] == '#') { + /* Ends with comment sequence #...\n */ + if (nl == NULL) { + /* But we've not found the \n yet */ + break; + } + } else if (u[0] == '\\') { + if (u[1] == '\n') { + /* Trim escaped newline. */ + total_size -= 2; + mtree->line.s[total_size] = '\0'; + break; + } else if (u[1] != '\0') { + /* Skip the two-char escape sequence */ + ++u; + } + } + } + find_off = u - mtree->line.s; + } +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_rar.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_rar.c new file mode 100644 index 0000000..98efbb1 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_rar.c @@ -0,0 +1,2999 @@ +/*- +* Copyright (c) 2003-2007 Tim Kientzle +* Copyright (c) 2011 Andres Mejia +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "archive_platform.h" + +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#include +#ifdef HAVE_ZLIB_H +#include /* crc32 */ +#endif + +#include "archive.h" +#ifndef HAVE_ZLIB_H +#include "archive_crc32.h" +#endif +#include "archive_endian.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_ppmd7_private.h" +#include "archive_private.h" +#include "archive_read_private.h" + +/* RAR signature, also known as the mark header */ +#define RAR_SIGNATURE "\x52\x61\x72\x21\x1A\x07\x00" + +/* Header types */ +#define MARK_HEAD 0x72 +#define MAIN_HEAD 0x73 +#define FILE_HEAD 0x74 +#define COMM_HEAD 0x75 +#define AV_HEAD 0x76 +#define SUB_HEAD 0x77 +#define PROTECT_HEAD 0x78 +#define SIGN_HEAD 0x79 +#define NEWSUB_HEAD 0x7a +#define ENDARC_HEAD 0x7b + +/* Main Header Flags */ +#define MHD_VOLUME 0x0001 +#define MHD_COMMENT 0x0002 +#define MHD_LOCK 0x0004 +#define MHD_SOLID 0x0008 +#define MHD_NEWNUMBERING 0x0010 +#define MHD_AV 0x0020 +#define MHD_PROTECT 0x0040 +#define MHD_PASSWORD 0x0080 +#define MHD_FIRSTVOLUME 0x0100 +#define MHD_ENCRYPTVER 0x0200 + +/* Flags common to all headers */ +#define HD_MARKDELETION 0x4000 +#define HD_ADD_SIZE_PRESENT 0x8000 + +/* File Header Flags */ +#define FHD_SPLIT_BEFORE 0x0001 +#define FHD_SPLIT_AFTER 0x0002 +#define FHD_PASSWORD 0x0004 +#define FHD_COMMENT 0x0008 +#define FHD_SOLID 0x0010 +#define FHD_LARGE 0x0100 +#define FHD_UNICODE 0x0200 +#define FHD_SALT 0x0400 +#define FHD_VERSION 0x0800 +#define FHD_EXTTIME 0x1000 +#define FHD_EXTFLAGS 0x2000 + +/* File dictionary sizes */ +#define DICTIONARY_SIZE_64 0x00 +#define DICTIONARY_SIZE_128 0x20 +#define DICTIONARY_SIZE_256 0x40 +#define DICTIONARY_SIZE_512 0x60 +#define DICTIONARY_SIZE_1024 0x80 +#define DICTIONARY_SIZE_2048 0xA0 +#define DICTIONARY_SIZE_4096 0xC0 +#define FILE_IS_DIRECTORY 0xE0 +#define DICTIONARY_MASK FILE_IS_DIRECTORY + +/* OS Flags */ +#define OS_MSDOS 0 +#define OS_OS2 1 +#define OS_WIN32 2 +#define OS_UNIX 3 +#define OS_MAC_OS 4 +#define OS_BEOS 5 + +/* Compression Methods */ +#define COMPRESS_METHOD_STORE 0x30 +/* LZSS */ +#define COMPRESS_METHOD_FASTEST 0x31 +#define COMPRESS_METHOD_FAST 0x32 +#define COMPRESS_METHOD_NORMAL 0x33 +/* PPMd Variant H */ +#define COMPRESS_METHOD_GOOD 0x34 +#define COMPRESS_METHOD_BEST 0x35 + +#define CRC_POLYNOMIAL 0xEDB88320 + +#define NS_UNIT 10000000 + +#define DICTIONARY_MAX_SIZE 0x400000 + +#define MAINCODE_SIZE 299 +#define OFFSETCODE_SIZE 60 +#define LOWOFFSETCODE_SIZE 17 +#define LENGTHCODE_SIZE 28 +#define HUFFMAN_TABLE_SIZE \ + MAINCODE_SIZE + OFFSETCODE_SIZE + LOWOFFSETCODE_SIZE + LENGTHCODE_SIZE + +#define MAX_SYMBOL_LENGTH 0xF +#define MAX_SYMBOLS 20 + +/* + * Considering L1,L2 cache miss and a calling of write system-call, + * the best size of the output buffer(uncompressed buffer) is 128K. + * If the structure of extracting process is changed, this value + * might be researched again. + */ +#define UNP_BUFFER_SIZE (128 * 1024) + +/* Define this here for non-Windows platforms */ +#if !((defined(__WIN32__) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__)) +#define FILE_ATTRIBUTE_DIRECTORY 0x10 +#endif + +#undef minimum +#define minimum(a, b) ((a)<(b)?(a):(b)) + +/* Fields common to all headers */ +struct rar_header +{ + char crc[2]; + char type; + char flags[2]; + char size[2]; +}; + +/* Fields common to all file headers */ +struct rar_file_header +{ + char pack_size[4]; + char unp_size[4]; + char host_os; + char file_crc[4]; + char file_time[4]; + char unp_ver; + char method; + char name_size[2]; + char file_attr[4]; +}; + +struct huffman_tree_node +{ + int branches[2]; +}; + +struct huffman_table_entry +{ + unsigned int length; + int value; +}; + +struct huffman_code +{ + struct huffman_tree_node *tree; + int numentries; + int numallocatedentries; + int minlength; + int maxlength; + int tablesize; + struct huffman_table_entry *table; +}; + +struct lzss +{ + unsigned char *window; + int mask; + int64_t position; +}; + +struct data_block_offsets +{ + int64_t header_size; + int64_t start_offset; + int64_t end_offset; +}; + +struct rar +{ + /* Entries from main RAR header */ + unsigned main_flags; + unsigned long file_crc; + char reserved1[2]; + char reserved2[4]; + char encryptver; + + /* File header entries */ + char compression_method; + unsigned file_flags; + int64_t packed_size; + int64_t unp_size; + time_t mtime; + long mnsec; + mode_t mode; + char *filename; + char *filename_save; + size_t filename_save_size; + size_t filename_allocated; + + /* File header optional entries */ + char salt[8]; + time_t atime; + long ansec; + time_t ctime; + long cnsec; + time_t arctime; + long arcnsec; + + /* Fields to help with tracking decompression of files. */ + int64_t bytes_unconsumed; + int64_t bytes_remaining; + int64_t bytes_uncopied; + int64_t offset; + int64_t offset_outgoing; + int64_t offset_seek; + char valid; + unsigned int unp_offset; + unsigned int unp_buffer_size; + unsigned char *unp_buffer; + unsigned int dictionary_size; + char start_new_block; + char entry_eof; + unsigned long crc_calculated; + int found_first_header; + char has_endarc_header; + struct data_block_offsets *dbo; + unsigned int cursor; + unsigned int nodes; + char filename_must_match; + + /* LZSS members */ + struct huffman_code maincode; + struct huffman_code offsetcode; + struct huffman_code lowoffsetcode; + struct huffman_code lengthcode; + unsigned char lengthtable[HUFFMAN_TABLE_SIZE]; + struct lzss lzss; + char output_last_match; + unsigned int lastlength; + unsigned int lastoffset; + unsigned int oldoffset[4]; + unsigned int lastlowoffset; + unsigned int numlowoffsetrepeats; + int64_t filterstart; + char start_new_table; + + /* PPMd Variant H members */ + char ppmd_valid; + char ppmd_eod; + char is_ppmd_block; + int ppmd_escape; + CPpmd7 ppmd7_context; + CPpmd7z_RangeDec range_dec; + IByteIn bytein; + + /* + * String conversion object. + */ + int init_default_conversion; + struct archive_string_conv *sconv_default; + struct archive_string_conv *opt_sconv; + struct archive_string_conv *sconv_utf8; + struct archive_string_conv *sconv_utf16be; + + /* + * Bit stream reader. + */ + struct rar_br { +#define CACHE_TYPE uint64_t +#define CACHE_BITS (8 * sizeof(CACHE_TYPE)) + /* Cache buffer. */ + CACHE_TYPE cache_buffer; + /* Indicates how many bits avail in cache_buffer. */ + int cache_avail; + ssize_t avail_in; + const unsigned char *next_in; + } br; + + /* + * Custom field to denote that this archive contains encrypted entries + */ + int has_encrypted_entries; +}; + +static int archive_read_support_format_rar_capabilities(struct archive_read *); +static int archive_read_format_rar_has_encrypted_entries(struct archive_read *); +static int archive_read_format_rar_bid(struct archive_read *, int); +static int archive_read_format_rar_options(struct archive_read *, + const char *, const char *); +static int archive_read_format_rar_read_header(struct archive_read *, + struct archive_entry *); +static int archive_read_format_rar_read_data(struct archive_read *, + const void **, size_t *, int64_t *); +static int archive_read_format_rar_read_data_skip(struct archive_read *a); +static int64_t archive_read_format_rar_seek_data(struct archive_read *, int64_t, + int); +static int archive_read_format_rar_cleanup(struct archive_read *); + +/* Support functions */ +static int read_header(struct archive_read *, struct archive_entry *, char); +static time_t get_time(int); +static int read_exttime(const char *, struct rar *, const char *); +static int read_symlink_stored(struct archive_read *, struct archive_entry *, + struct archive_string_conv *); +static int read_data_stored(struct archive_read *, const void **, size_t *, + int64_t *); +static int read_data_compressed(struct archive_read *, const void **, size_t *, + int64_t *); +static int rar_br_preparation(struct archive_read *, struct rar_br *); +static int parse_codes(struct archive_read *); +static void free_codes(struct archive_read *); +static int read_next_symbol(struct archive_read *, struct huffman_code *); +static int create_code(struct archive_read *, struct huffman_code *, + unsigned char *, int, char); +static int add_value(struct archive_read *, struct huffman_code *, int, int, + int); +static int new_node(struct huffman_code *); +static int make_table(struct archive_read *, struct huffman_code *); +static int make_table_recurse(struct archive_read *, struct huffman_code *, int, + struct huffman_table_entry *, int, int); +static int64_t expand(struct archive_read *, int64_t); +static int copy_from_lzss_window(struct archive_read *, const void **, + int64_t, int); +static const void *rar_read_ahead(struct archive_read *, size_t, ssize_t *); + +/* + * Bit stream reader. + */ +/* Check that the cache buffer has enough bits. */ +#define rar_br_has(br, n) ((br)->cache_avail >= n) +/* Get compressed data by bit. */ +#define rar_br_bits(br, n) \ + (((uint32_t)((br)->cache_buffer >> \ + ((br)->cache_avail - (n)))) & cache_masks[n]) +#define rar_br_bits_forced(br, n) \ + (((uint32_t)((br)->cache_buffer << \ + ((n) - (br)->cache_avail))) & cache_masks[n]) +/* Read ahead to make sure the cache buffer has enough compressed data we + * will use. + * True : completed, there is enough data in the cache buffer. + * False : there is no data in the stream. */ +#define rar_br_read_ahead(a, br, n) \ + ((rar_br_has(br, (n)) || rar_br_fillup(a, br)) || rar_br_has(br, (n))) +/* Notify how many bits we consumed. */ +#define rar_br_consume(br, n) ((br)->cache_avail -= (n)) +#define rar_br_consume_unalined_bits(br) ((br)->cache_avail &= ~7) + +static const uint32_t cache_masks[] = { + 0x00000000, 0x00000001, 0x00000003, 0x00000007, + 0x0000000F, 0x0000001F, 0x0000003F, 0x0000007F, + 0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF, + 0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF, + 0x0000FFFF, 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, + 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, + 0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, + 0x0FFFFFFF, 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF +}; + +/* + * Shift away used bits in the cache data and fill it up with following bits. + * Call this when cache buffer does not have enough bits you need. + * + * Returns 1 if the cache buffer is full. + * Returns 0 if the cache buffer is not full; input buffer is empty. + */ +static int +rar_br_fillup(struct archive_read *a, struct rar_br *br) +{ + struct rar *rar = (struct rar *)(a->format->data); + int n = CACHE_BITS - br->cache_avail; + + for (;;) { + switch (n >> 3) { + case 8: + if (br->avail_in >= 8) { + br->cache_buffer = + ((uint64_t)br->next_in[0]) << 56 | + ((uint64_t)br->next_in[1]) << 48 | + ((uint64_t)br->next_in[2]) << 40 | + ((uint64_t)br->next_in[3]) << 32 | + ((uint32_t)br->next_in[4]) << 24 | + ((uint32_t)br->next_in[5]) << 16 | + ((uint32_t)br->next_in[6]) << 8 | + (uint32_t)br->next_in[7]; + br->next_in += 8; + br->avail_in -= 8; + br->cache_avail += 8 * 8; + rar->bytes_unconsumed += 8; + rar->bytes_remaining -= 8; + return (1); + } + break; + case 7: + if (br->avail_in >= 7) { + br->cache_buffer = + (br->cache_buffer << 56) | + ((uint64_t)br->next_in[0]) << 48 | + ((uint64_t)br->next_in[1]) << 40 | + ((uint64_t)br->next_in[2]) << 32 | + ((uint32_t)br->next_in[3]) << 24 | + ((uint32_t)br->next_in[4]) << 16 | + ((uint32_t)br->next_in[5]) << 8 | + (uint32_t)br->next_in[6]; + br->next_in += 7; + br->avail_in -= 7; + br->cache_avail += 7 * 8; + rar->bytes_unconsumed += 7; + rar->bytes_remaining -= 7; + return (1); + } + break; + case 6: + if (br->avail_in >= 6) { + br->cache_buffer = + (br->cache_buffer << 48) | + ((uint64_t)br->next_in[0]) << 40 | + ((uint64_t)br->next_in[1]) << 32 | + ((uint32_t)br->next_in[2]) << 24 | + ((uint32_t)br->next_in[3]) << 16 | + ((uint32_t)br->next_in[4]) << 8 | + (uint32_t)br->next_in[5]; + br->next_in += 6; + br->avail_in -= 6; + br->cache_avail += 6 * 8; + rar->bytes_unconsumed += 6; + rar->bytes_remaining -= 6; + return (1); + } + break; + case 0: + /* We have enough compressed data in + * the cache buffer.*/ + return (1); + default: + break; + } + if (br->avail_in <= 0) { + + if (rar->bytes_unconsumed > 0) { + /* Consume as much as the decompressor + * actually used. */ + __archive_read_consume(a, rar->bytes_unconsumed); + rar->bytes_unconsumed = 0; + } + br->next_in = rar_read_ahead(a, 1, &(br->avail_in)); + if (br->next_in == NULL) + return (0); + if (br->avail_in == 0) + return (0); + } + br->cache_buffer = + (br->cache_buffer << 8) | *br->next_in++; + br->avail_in--; + br->cache_avail += 8; + n -= 8; + rar->bytes_unconsumed++; + rar->bytes_remaining--; + } +} + +static int +rar_br_preparation(struct archive_read *a, struct rar_br *br) +{ + struct rar *rar = (struct rar *)(a->format->data); + + if (rar->bytes_remaining > 0) { + br->next_in = rar_read_ahead(a, 1, &(br->avail_in)); + if (br->next_in == NULL) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated RAR file data"); + return (ARCHIVE_FATAL); + } + if (br->cache_avail == 0) + (void)rar_br_fillup(a, br); + } + return (ARCHIVE_OK); +} + +/* Find last bit set */ +static inline int +rar_fls(unsigned int word) +{ + word |= (word >> 1); + word |= (word >> 2); + word |= (word >> 4); + word |= (word >> 8); + word |= (word >> 16); + return word - (word >> 1); +} + +/* LZSS functions */ +static inline int64_t +lzss_position(struct lzss *lzss) +{ + return lzss->position; +} + +static inline int +lzss_mask(struct lzss *lzss) +{ + return lzss->mask; +} + +static inline int +lzss_size(struct lzss *lzss) +{ + return lzss->mask + 1; +} + +static inline int +lzss_offset_for_position(struct lzss *lzss, int64_t pos) +{ + return (int)(pos & lzss->mask); +} + +static inline unsigned char * +lzss_pointer_for_position(struct lzss *lzss, int64_t pos) +{ + return &lzss->window[lzss_offset_for_position(lzss, pos)]; +} + +static inline int +lzss_current_offset(struct lzss *lzss) +{ + return lzss_offset_for_position(lzss, lzss->position); +} + +static inline uint8_t * +lzss_current_pointer(struct lzss *lzss) +{ + return lzss_pointer_for_position(lzss, lzss->position); +} + +static inline void +lzss_emit_literal(struct rar *rar, uint8_t literal) +{ + *lzss_current_pointer(&rar->lzss) = literal; + rar->lzss.position++; +} + +static inline void +lzss_emit_match(struct rar *rar, int offset, int length) +{ + int dstoffs = lzss_current_offset(&rar->lzss); + int srcoffs = (dstoffs - offset) & lzss_mask(&rar->lzss); + int l, li, remaining; + unsigned char *d, *s; + + remaining = length; + while (remaining > 0) { + l = remaining; + if (dstoffs > srcoffs) { + if (l > lzss_size(&rar->lzss) - dstoffs) + l = lzss_size(&rar->lzss) - dstoffs; + } else { + if (l > lzss_size(&rar->lzss) - srcoffs) + l = lzss_size(&rar->lzss) - srcoffs; + } + d = &(rar->lzss.window[dstoffs]); + s = &(rar->lzss.window[srcoffs]); + if ((dstoffs + l < srcoffs) || (srcoffs + l < dstoffs)) + memcpy(d, s, l); + else { + for (li = 0; li < l; li++) + d[li] = s[li]; + } + remaining -= l; + dstoffs = (dstoffs + l) & lzss_mask(&(rar->lzss)); + srcoffs = (srcoffs + l) & lzss_mask(&(rar->lzss)); + } + rar->lzss.position += length; +} + +static Byte +ppmd_read(void *p) +{ + struct archive_read *a = ((IByteIn*)p)->a; + struct rar *rar = (struct rar *)(a->format->data); + struct rar_br *br = &(rar->br); + Byte b; + if (!rar_br_read_ahead(a, br, 8)) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated RAR file data"); + rar->valid = 0; + return 0; + } + b = rar_br_bits(br, 8); + rar_br_consume(br, 8); + return b; +} + +int +archive_read_support_format_rar(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct rar *rar; + int r; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, + "archive_read_support_format_rar"); + + rar = (struct rar *)calloc(sizeof(*rar), 1); + if (rar == NULL) + { + archive_set_error(&a->archive, ENOMEM, "Can't allocate rar data"); + return (ARCHIVE_FATAL); + } + + /* + * Until enough data has been read, we cannot tell about + * any encrypted entries yet. + */ + rar->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW; + + r = __archive_read_register_format(a, + rar, + "rar", + archive_read_format_rar_bid, + archive_read_format_rar_options, + archive_read_format_rar_read_header, + archive_read_format_rar_read_data, + archive_read_format_rar_read_data_skip, + archive_read_format_rar_seek_data, + archive_read_format_rar_cleanup, + archive_read_support_format_rar_capabilities, + archive_read_format_rar_has_encrypted_entries); + + if (r != ARCHIVE_OK) + free(rar); + return (r); +} + +static int +archive_read_support_format_rar_capabilities(struct archive_read * a) +{ + (void)a; /* UNUSED */ + return (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA + | ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA); +} + +static int +archive_read_format_rar_has_encrypted_entries(struct archive_read *_a) +{ + if (_a && _a->format) { + struct rar * rar = (struct rar *)_a->format->data; + if (rar) { + return rar->has_encrypted_entries; + } + } + return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW; +} + + +static int +archive_read_format_rar_bid(struct archive_read *a, int best_bid) +{ + const char *p; + + /* If there's already a bid > 30, we'll never win. */ + if (best_bid > 30) + return (-1); + + if ((p = __archive_read_ahead(a, 7, NULL)) == NULL) + return (-1); + + if (memcmp(p, RAR_SIGNATURE, 7) == 0) + return (30); + + if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) { + /* This is a PE file */ + ssize_t offset = 0x10000; + ssize_t window = 4096; + ssize_t bytes_avail; + while (offset + window <= (1024 * 128)) { + const char *buff = __archive_read_ahead(a, offset + window, &bytes_avail); + if (buff == NULL) { + /* Remaining bytes are less than window. */ + window >>= 1; + if (window < 0x40) + return (0); + continue; + } + p = buff + offset; + while (p + 7 < buff + bytes_avail) { + if (memcmp(p, RAR_SIGNATURE, 7) == 0) + return (30); + p += 0x10; + } + offset = p - buff; + } + } + return (0); +} + +static int +skip_sfx(struct archive_read *a) +{ + const void *h; + const char *p, *q; + size_t skip, total; + ssize_t bytes, window; + + total = 0; + window = 4096; + while (total + window <= (1024 * 128)) { + h = __archive_read_ahead(a, window, &bytes); + if (h == NULL) { + /* Remaining bytes are less than window. */ + window >>= 1; + if (window < 0x40) + goto fatal; + continue; + } + if (bytes < 0x40) + goto fatal; + p = h; + q = p + bytes; + + /* + * Scan ahead until we find something that looks + * like the RAR header. + */ + while (p + 7 < q) { + if (memcmp(p, RAR_SIGNATURE, 7) == 0) { + skip = p - (const char *)h; + __archive_read_consume(a, skip); + return (ARCHIVE_OK); + } + p += 0x10; + } + skip = p - (const char *)h; + __archive_read_consume(a, skip); + total += skip; + } +fatal: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Couldn't find out RAR header"); + return (ARCHIVE_FATAL); +} + +static int +archive_read_format_rar_options(struct archive_read *a, + const char *key, const char *val) +{ + struct rar *rar; + int ret = ARCHIVE_FAILED; + + rar = (struct rar *)(a->format->data); + if (strcmp(key, "hdrcharset") == 0) { + if (val == NULL || val[0] == 0) + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "rar: hdrcharset option needs a character-set name"); + else { + rar->opt_sconv = + archive_string_conversion_from_charset( + &a->archive, val, 0); + if (rar->opt_sconv != NULL) + ret = ARCHIVE_OK; + else + ret = ARCHIVE_FATAL; + } + return (ret); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +static int +archive_read_format_rar_read_header(struct archive_read *a, + struct archive_entry *entry) +{ + const void *h; + const char *p; + struct rar *rar; + size_t skip; + char head_type; + int ret; + unsigned flags; + unsigned long crc32_expected; + + a->archive.archive_format = ARCHIVE_FORMAT_RAR; + if (a->archive.archive_format_name == NULL) + a->archive.archive_format_name = "RAR"; + + rar = (struct rar *)(a->format->data); + + /* + * It should be sufficient to call archive_read_next_header() for + * a reader to determine if an entry is encrypted or not. If the + * encryption of an entry is only detectable when calling + * archive_read_data(), so be it. We'll do the same check there + * as well. + */ + if (rar->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) { + rar->has_encrypted_entries = 0; + } + + /* RAR files can be generated without EOF headers, so return ARCHIVE_EOF if + * this fails. + */ + if ((h = __archive_read_ahead(a, 7, NULL)) == NULL) + return (ARCHIVE_EOF); + + p = h; + if (rar->found_first_header == 0 && + ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0)) { + /* This is an executable ? Must be self-extracting... */ + ret = skip_sfx(a); + if (ret < ARCHIVE_WARN) + return (ret); + } + rar->found_first_header = 1; + + while (1) + { + unsigned long crc32_val; + + if ((h = __archive_read_ahead(a, 7, NULL)) == NULL) + return (ARCHIVE_FATAL); + p = h; + + head_type = p[2]; + switch(head_type) + { + case MARK_HEAD: + if (memcmp(p, RAR_SIGNATURE, 7) != 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid marker header"); + return (ARCHIVE_FATAL); + } + __archive_read_consume(a, 7); + break; + + case MAIN_HEAD: + rar->main_flags = archive_le16dec(p + 3); + skip = archive_le16dec(p + 5); + if (skip < 7 + sizeof(rar->reserved1) + sizeof(rar->reserved2)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid header size"); + return (ARCHIVE_FATAL); + } + if ((h = __archive_read_ahead(a, skip, NULL)) == NULL) + return (ARCHIVE_FATAL); + p = h; + memcpy(rar->reserved1, p + 7, sizeof(rar->reserved1)); + memcpy(rar->reserved2, p + 7 + sizeof(rar->reserved1), + sizeof(rar->reserved2)); + if (rar->main_flags & MHD_ENCRYPTVER) { + if (skip < 7 + sizeof(rar->reserved1) + sizeof(rar->reserved2)+1) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid header size"); + return (ARCHIVE_FATAL); + } + rar->encryptver = *(p + 7 + sizeof(rar->reserved1) + + sizeof(rar->reserved2)); + } + + /* Main header is password encrypted, so we cannot read any + file names or any other info about files from the header. */ + if (rar->main_flags & MHD_PASSWORD) + { + archive_entry_set_is_metadata_encrypted(entry, 1); + archive_entry_set_is_data_encrypted(entry, 1); + rar->has_encrypted_entries = 1; + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "RAR encryption support unavailable."); + return (ARCHIVE_FATAL); + } + + crc32_val = crc32(0, (const unsigned char *)p + 2, (unsigned)skip - 2); + if ((crc32_val & 0xffff) != archive_le16dec(p)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Header CRC error"); + return (ARCHIVE_FATAL); + } + __archive_read_consume(a, skip); + break; + + case FILE_HEAD: + return read_header(a, entry, head_type); + + case COMM_HEAD: + case AV_HEAD: + case SUB_HEAD: + case PROTECT_HEAD: + case SIGN_HEAD: + case ENDARC_HEAD: + flags = archive_le16dec(p + 3); + skip = archive_le16dec(p + 5); + if (skip < 7) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid header size too small"); + return (ARCHIVE_FATAL); + } + if (flags & HD_ADD_SIZE_PRESENT) + { + if (skip < 7 + 4) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid header size too small"); + return (ARCHIVE_FATAL); + } + if ((h = __archive_read_ahead(a, skip, NULL)) == NULL) + return (ARCHIVE_FATAL); + p = h; + skip += archive_le32dec(p + 7); + } + + /* Skip over the 2-byte CRC at the beginning of the header. */ + crc32_expected = archive_le16dec(p); + __archive_read_consume(a, 2); + skip -= 2; + + /* Skim the entire header and compute the CRC. */ + crc32_val = 0; + while (skip > 0) { + size_t to_read = skip; + ssize_t did_read; + if (to_read > 32 * 1024) { + to_read = 32 * 1024; + } + if ((h = __archive_read_ahead(a, to_read, &did_read)) == NULL) { + return (ARCHIVE_FATAL); + } + p = h; + crc32_val = crc32(crc32_val, (const unsigned char *)p, (unsigned)did_read); + __archive_read_consume(a, did_read); + skip -= did_read; + } + if ((crc32_val & 0xffff) != crc32_expected) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Header CRC error"); + return (ARCHIVE_FATAL); + } + if (head_type == ENDARC_HEAD) + return (ARCHIVE_EOF); + break; + + case NEWSUB_HEAD: + if ((ret = read_header(a, entry, head_type)) < ARCHIVE_WARN) + return ret; + break; + + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Bad RAR file"); + return (ARCHIVE_FATAL); + } + } +} + +static int +archive_read_format_rar_read_data(struct archive_read *a, const void **buff, + size_t *size, int64_t *offset) +{ + struct rar *rar = (struct rar *)(a->format->data); + int ret; + + if (rar->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) { + rar->has_encrypted_entries = 0; + } + + if (rar->bytes_unconsumed > 0) { + /* Consume as much as the decompressor actually used. */ + __archive_read_consume(a, rar->bytes_unconsumed); + rar->bytes_unconsumed = 0; + } + + *buff = NULL; + if (rar->entry_eof || rar->offset_seek >= rar->unp_size) { + *size = 0; + *offset = rar->offset; + if (*offset < rar->unp_size) + *offset = rar->unp_size; + return (ARCHIVE_EOF); + } + + switch (rar->compression_method) + { + case COMPRESS_METHOD_STORE: + ret = read_data_stored(a, buff, size, offset); + break; + + case COMPRESS_METHOD_FASTEST: + case COMPRESS_METHOD_FAST: + case COMPRESS_METHOD_NORMAL: + case COMPRESS_METHOD_GOOD: + case COMPRESS_METHOD_BEST: + ret = read_data_compressed(a, buff, size, offset); + if (ret != ARCHIVE_OK && ret != ARCHIVE_WARN) { + __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context); + rar->start_new_table = 1; + rar->ppmd_valid = 0; + } + break; + + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Unsupported compression method for RAR file."); + ret = ARCHIVE_FATAL; + break; + } + return (ret); +} + +static int +archive_read_format_rar_read_data_skip(struct archive_read *a) +{ + struct rar *rar; + int64_t bytes_skipped; + int ret; + + rar = (struct rar *)(a->format->data); + + if (rar->bytes_unconsumed > 0) { + /* Consume as much as the decompressor actually used. */ + __archive_read_consume(a, rar->bytes_unconsumed); + rar->bytes_unconsumed = 0; + } + + if (rar->bytes_remaining > 0) { + bytes_skipped = __archive_read_consume(a, rar->bytes_remaining); + if (bytes_skipped < 0) + return (ARCHIVE_FATAL); + } + + /* Compressed data to skip must be read from each header in a multivolume + * archive. + */ + if (rar->main_flags & MHD_VOLUME && rar->file_flags & FHD_SPLIT_AFTER) + { + ret = archive_read_format_rar_read_header(a, a->entry); + if (ret == (ARCHIVE_EOF)) + ret = archive_read_format_rar_read_header(a, a->entry); + if (ret != (ARCHIVE_OK)) + return ret; + return archive_read_format_rar_read_data_skip(a); + } + + return (ARCHIVE_OK); +} + +static int64_t +archive_read_format_rar_seek_data(struct archive_read *a, int64_t offset, + int whence) +{ + int64_t client_offset, ret; + unsigned int i; + struct rar *rar = (struct rar *)(a->format->data); + + if (rar->compression_method == COMPRESS_METHOD_STORE) + { + /* Modify the offset for use with SEEK_SET */ + switch (whence) + { + case SEEK_CUR: + client_offset = rar->offset_seek; + break; + case SEEK_END: + client_offset = rar->unp_size; + break; + case SEEK_SET: + default: + client_offset = 0; + } + client_offset += offset; + if (client_offset < 0) + { + /* Can't seek past beginning of data block */ + return -1; + } + else if (client_offset > rar->unp_size) + { + /* + * Set the returned offset but only seek to the end of + * the data block. + */ + rar->offset_seek = client_offset; + client_offset = rar->unp_size; + } + + client_offset += rar->dbo[0].start_offset; + i = 0; + while (i < rar->cursor) + { + i++; + client_offset += rar->dbo[i].start_offset - rar->dbo[i-1].end_offset; + } + if (rar->main_flags & MHD_VOLUME) + { + /* Find the appropriate offset among the multivolume archive */ + while (1) + { + if (client_offset < rar->dbo[rar->cursor].start_offset && + rar->file_flags & FHD_SPLIT_BEFORE) + { + /* Search backwards for the correct data block */ + if (rar->cursor == 0) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Attempt to seek past beginning of RAR data block"); + return (ARCHIVE_FAILED); + } + rar->cursor--; + client_offset -= rar->dbo[rar->cursor+1].start_offset - + rar->dbo[rar->cursor].end_offset; + if (client_offset < rar->dbo[rar->cursor].start_offset) + continue; + ret = __archive_read_seek(a, rar->dbo[rar->cursor].start_offset - + rar->dbo[rar->cursor].header_size, SEEK_SET); + if (ret < (ARCHIVE_OK)) + return ret; + ret = archive_read_format_rar_read_header(a, a->entry); + if (ret != (ARCHIVE_OK)) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Error during seek of RAR file"); + return (ARCHIVE_FAILED); + } + rar->cursor--; + break; + } + else if (client_offset > rar->dbo[rar->cursor].end_offset && + rar->file_flags & FHD_SPLIT_AFTER) + { + /* Search forward for the correct data block */ + rar->cursor++; + if (rar->cursor < rar->nodes && + client_offset > rar->dbo[rar->cursor].end_offset) + { + client_offset += rar->dbo[rar->cursor].start_offset - + rar->dbo[rar->cursor-1].end_offset; + continue; + } + rar->cursor--; + ret = __archive_read_seek(a, rar->dbo[rar->cursor].end_offset, + SEEK_SET); + if (ret < (ARCHIVE_OK)) + return ret; + ret = archive_read_format_rar_read_header(a, a->entry); + if (ret == (ARCHIVE_EOF)) + { + rar->has_endarc_header = 1; + ret = archive_read_format_rar_read_header(a, a->entry); + } + if (ret != (ARCHIVE_OK)) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Error during seek of RAR file"); + return (ARCHIVE_FAILED); + } + client_offset += rar->dbo[rar->cursor].start_offset - + rar->dbo[rar->cursor-1].end_offset; + continue; + } + break; + } + } + + ret = __archive_read_seek(a, client_offset, SEEK_SET); + if (ret < (ARCHIVE_OK)) + return ret; + rar->bytes_remaining = rar->dbo[rar->cursor].end_offset - ret; + i = rar->cursor; + while (i > 0) + { + i--; + ret -= rar->dbo[i+1].start_offset - rar->dbo[i].end_offset; + } + ret -= rar->dbo[0].start_offset; + + /* Always restart reading the file after a seek */ + __archive_reset_read_data(&a->archive); + + rar->bytes_unconsumed = 0; + rar->offset = 0; + + /* + * If a seek past the end of file was requested, return the requested + * offset. + */ + if (ret == rar->unp_size && rar->offset_seek > rar->unp_size) + return rar->offset_seek; + + /* Return the new offset */ + rar->offset_seek = ret; + return rar->offset_seek; + } + else + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Seeking of compressed RAR files is unsupported"); + } + return (ARCHIVE_FAILED); +} + +static int +archive_read_format_rar_cleanup(struct archive_read *a) +{ + struct rar *rar; + + rar = (struct rar *)(a->format->data); + free_codes(a); + free(rar->filename); + free(rar->filename_save); + free(rar->dbo); + free(rar->unp_buffer); + free(rar->lzss.window); + __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context); + free(rar); + (a->format->data) = NULL; + return (ARCHIVE_OK); +} + +static int +read_header(struct archive_read *a, struct archive_entry *entry, + char head_type) +{ + const void *h; + const char *p, *endp; + struct rar *rar; + struct rar_header rar_header; + struct rar_file_header file_header; + int64_t header_size; + unsigned filename_size, end; + char *filename; + char *strp; + char packed_size[8]; + char unp_size[8]; + int ttime; + struct archive_string_conv *sconv, *fn_sconv; + unsigned long crc32_val; + int ret = (ARCHIVE_OK), ret2; + + rar = (struct rar *)(a->format->data); + + /* Setup a string conversion object for non-rar-unicode filenames. */ + sconv = rar->opt_sconv; + if (sconv == NULL) { + if (!rar->init_default_conversion) { + rar->sconv_default = + archive_string_default_conversion_for_read( + &(a->archive)); + rar->init_default_conversion = 1; + } + sconv = rar->sconv_default; + } + + + if ((h = __archive_read_ahead(a, 7, NULL)) == NULL) + return (ARCHIVE_FATAL); + p = h; + memcpy(&rar_header, p, sizeof(rar_header)); + rar->file_flags = archive_le16dec(rar_header.flags); + header_size = archive_le16dec(rar_header.size); + if (header_size < (int64_t)sizeof(file_header) + 7) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid header size"); + return (ARCHIVE_FATAL); + } + crc32_val = crc32(0, (const unsigned char *)p + 2, 7 - 2); + __archive_read_consume(a, 7); + + if (!(rar->file_flags & FHD_SOLID)) + { + rar->compression_method = 0; + rar->packed_size = 0; + rar->unp_size = 0; + rar->mtime = 0; + rar->ctime = 0; + rar->atime = 0; + rar->arctime = 0; + rar->mode = 0; + memset(&rar->salt, 0, sizeof(rar->salt)); + rar->atime = 0; + rar->ansec = 0; + rar->ctime = 0; + rar->cnsec = 0; + rar->mtime = 0; + rar->mnsec = 0; + rar->arctime = 0; + rar->arcnsec = 0; + } + else + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "RAR solid archive support unavailable."); + return (ARCHIVE_FATAL); + } + + if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL) + return (ARCHIVE_FATAL); + + /* File Header CRC check. */ + crc32_val = crc32(crc32_val, h, (unsigned)(header_size - 7)); + if ((crc32_val & 0xffff) != archive_le16dec(rar_header.crc)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Header CRC error"); + return (ARCHIVE_FATAL); + } + /* If no CRC error, Go on parsing File Header. */ + p = h; + endp = p + header_size - 7; + memcpy(&file_header, p, sizeof(file_header)); + p += sizeof(file_header); + + rar->compression_method = file_header.method; + + ttime = archive_le32dec(file_header.file_time); + rar->mtime = get_time(ttime); + + rar->file_crc = archive_le32dec(file_header.file_crc); + + if (rar->file_flags & FHD_PASSWORD) + { + archive_entry_set_is_data_encrypted(entry, 1); + rar->has_encrypted_entries = 1; + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "RAR encryption support unavailable."); + /* Since it is only the data part itself that is encrypted we can at least + extract information about the currently processed entry and don't need + to return ARCHIVE_FATAL here. */ + /*return (ARCHIVE_FATAL);*/ + } + + if (rar->file_flags & FHD_LARGE) + { + memcpy(packed_size, file_header.pack_size, 4); + memcpy(packed_size + 4, p, 4); /* High pack size */ + p += 4; + memcpy(unp_size, file_header.unp_size, 4); + memcpy(unp_size + 4, p, 4); /* High unpack size */ + p += 4; + rar->packed_size = archive_le64dec(&packed_size); + rar->unp_size = archive_le64dec(&unp_size); + } + else + { + rar->packed_size = archive_le32dec(file_header.pack_size); + rar->unp_size = archive_le32dec(file_header.unp_size); + } + + if (rar->packed_size < 0 || rar->unp_size < 0) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid sizes specified."); + return (ARCHIVE_FATAL); + } + + rar->bytes_remaining = rar->packed_size; + + /* TODO: RARv3 subblocks contain comments. For now the complete block is + * consumed at the end. + */ + if (head_type == NEWSUB_HEAD) { + size_t distance = p - (const char *)h; + header_size += rar->packed_size; + /* Make sure we have the extended data. */ + if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL) + return (ARCHIVE_FATAL); + p = h; + endp = p + header_size - 7; + p += distance; + } + + filename_size = archive_le16dec(file_header.name_size); + if (p + filename_size > endp) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid filename size"); + return (ARCHIVE_FATAL); + } + if (rar->filename_allocated < filename_size * 2 + 2) { + char *newptr; + size_t newsize = filename_size * 2 + 2; + newptr = realloc(rar->filename, newsize); + if (newptr == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Couldn't allocate memory."); + return (ARCHIVE_FATAL); + } + rar->filename = newptr; + rar->filename_allocated = newsize; + } + filename = rar->filename; + memcpy(filename, p, filename_size); + filename[filename_size] = '\0'; + if (rar->file_flags & FHD_UNICODE) + { + if (filename_size != strlen(filename)) + { + unsigned char highbyte, flagbits, flagbyte; + unsigned fn_end, offset; + + end = filename_size; + fn_end = filename_size * 2; + filename_size = 0; + offset = (unsigned)strlen(filename) + 1; + highbyte = *(p + offset++); + flagbits = 0; + flagbyte = 0; + while (offset < end && filename_size < fn_end) + { + if (!flagbits) + { + flagbyte = *(p + offset++); + flagbits = 8; + } + + flagbits -= 2; + switch((flagbyte >> flagbits) & 3) + { + case 0: + filename[filename_size++] = '\0'; + filename[filename_size++] = *(p + offset++); + break; + case 1: + filename[filename_size++] = highbyte; + filename[filename_size++] = *(p + offset++); + break; + case 2: + filename[filename_size++] = *(p + offset + 1); + filename[filename_size++] = *(p + offset); + offset += 2; + break; + case 3: + { + char extra, high; + uint8_t length = *(p + offset++); + + if (length & 0x80) { + extra = *(p + offset++); + high = (char)highbyte; + } else + extra = high = 0; + length = (length & 0x7f) + 2; + while (length && filename_size < fn_end) { + unsigned cp = filename_size >> 1; + filename[filename_size++] = high; + filename[filename_size++] = p[cp] + extra; + length--; + } + } + break; + } + } + if (filename_size > fn_end) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid filename"); + return (ARCHIVE_FATAL); + } + filename[filename_size++] = '\0'; + /* + * Do not increment filename_size here as the computations below + * add the space for the terminating NUL explicitly. + */ + filename[filename_size] = '\0'; + + /* Decoded unicode form is UTF-16BE, so we have to update a string + * conversion object for it. */ + if (rar->sconv_utf16be == NULL) { + rar->sconv_utf16be = archive_string_conversion_from_charset( + &a->archive, "UTF-16BE", 1); + if (rar->sconv_utf16be == NULL) + return (ARCHIVE_FATAL); + } + fn_sconv = rar->sconv_utf16be; + + strp = filename; + while (memcmp(strp, "\x00\x00", 2)) + { + if (!memcmp(strp, "\x00\\", 2)) + *(strp + 1) = '/'; + strp += 2; + } + p += offset; + } else { + /* + * If FHD_UNICODE is set but no unicode data, this file name form + * is UTF-8, so we have to update a string conversion object for + * it accordingly. + */ + if (rar->sconv_utf8 == NULL) { + rar->sconv_utf8 = archive_string_conversion_from_charset( + &a->archive, "UTF-8", 1); + if (rar->sconv_utf8 == NULL) + return (ARCHIVE_FATAL); + } + fn_sconv = rar->sconv_utf8; + while ((strp = strchr(filename, '\\')) != NULL) + *strp = '/'; + p += filename_size; + } + } + else + { + fn_sconv = sconv; + while ((strp = strchr(filename, '\\')) != NULL) + *strp = '/'; + p += filename_size; + } + + /* Split file in multivolume RAR. No more need to process header. */ + if (rar->filename_save && + filename_size == rar->filename_save_size && + !memcmp(rar->filename, rar->filename_save, filename_size + 1)) + { + __archive_read_consume(a, header_size - 7); + rar->cursor++; + if (rar->cursor >= rar->nodes) + { + rar->nodes++; + if ((rar->dbo = + realloc(rar->dbo, sizeof(*rar->dbo) * rar->nodes)) == NULL) + { + archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory."); + return (ARCHIVE_FATAL); + } + rar->dbo[rar->cursor].header_size = header_size; + rar->dbo[rar->cursor].start_offset = -1; + rar->dbo[rar->cursor].end_offset = -1; + } + if (rar->dbo[rar->cursor].start_offset < 0) + { + rar->dbo[rar->cursor].start_offset = a->filter->position; + rar->dbo[rar->cursor].end_offset = rar->dbo[rar->cursor].start_offset + + rar->packed_size; + } + return ret; + } + else if (rar->filename_must_match) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Mismatch of file parts split across multi-volume archive"); + return (ARCHIVE_FATAL); + } + + rar->filename_save = (char*)realloc(rar->filename_save, + filename_size + 1); + memcpy(rar->filename_save, rar->filename, filename_size + 1); + rar->filename_save_size = filename_size; + + /* Set info for seeking */ + free(rar->dbo); + if ((rar->dbo = calloc(1, sizeof(*rar->dbo))) == NULL) + { + archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory."); + return (ARCHIVE_FATAL); + } + rar->dbo[0].header_size = header_size; + rar->dbo[0].start_offset = -1; + rar->dbo[0].end_offset = -1; + rar->cursor = 0; + rar->nodes = 1; + + if (rar->file_flags & FHD_SALT) + { + if (p + 8 > endp) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid header size"); + return (ARCHIVE_FATAL); + } + memcpy(rar->salt, p, 8); + p += 8; + } + + if (rar->file_flags & FHD_EXTTIME) { + if (read_exttime(p, rar, endp) < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid header size"); + return (ARCHIVE_FATAL); + } + } + + __archive_read_consume(a, header_size - 7); + rar->dbo[0].start_offset = a->filter->position; + rar->dbo[0].end_offset = rar->dbo[0].start_offset + rar->packed_size; + + switch(file_header.host_os) + { + case OS_MSDOS: + case OS_OS2: + case OS_WIN32: + rar->mode = archive_le32dec(file_header.file_attr); + if (rar->mode & FILE_ATTRIBUTE_DIRECTORY) + rar->mode = AE_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH; + else + rar->mode = AE_IFREG; + rar->mode |= S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; + break; + + case OS_UNIX: + case OS_MAC_OS: + case OS_BEOS: + rar->mode = archive_le32dec(file_header.file_attr); + break; + + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Unknown file attributes from RAR file's host OS"); + return (ARCHIVE_FATAL); + } + + rar->bytes_uncopied = rar->bytes_unconsumed = 0; + rar->lzss.position = rar->offset = 0; + rar->offset_seek = 0; + rar->dictionary_size = 0; + rar->offset_outgoing = 0; + rar->br.cache_avail = 0; + rar->br.avail_in = 0; + rar->crc_calculated = 0; + rar->entry_eof = 0; + rar->valid = 1; + rar->is_ppmd_block = 0; + rar->start_new_table = 1; + free(rar->unp_buffer); + rar->unp_buffer = NULL; + rar->unp_offset = 0; + rar->unp_buffer_size = UNP_BUFFER_SIZE; + memset(rar->lengthtable, 0, sizeof(rar->lengthtable)); + __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context); + rar->ppmd_valid = rar->ppmd_eod = 0; + + /* Don't set any archive entries for non-file header types */ + if (head_type == NEWSUB_HEAD) + return ret; + + archive_entry_set_mtime(entry, rar->mtime, rar->mnsec); + archive_entry_set_ctime(entry, rar->ctime, rar->cnsec); + archive_entry_set_atime(entry, rar->atime, rar->ansec); + archive_entry_set_size(entry, rar->unp_size); + archive_entry_set_mode(entry, rar->mode); + + if (archive_entry_copy_pathname_l(entry, filename, filename_size, fn_sconv)) + { + if (errno == ENOMEM) + { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Pathname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Pathname cannot be converted from %s to current locale.", + archive_string_conversion_charset_name(fn_sconv)); + ret = (ARCHIVE_WARN); + } + + if (((rar->mode) & AE_IFMT) == AE_IFLNK) + { + /* Make sure a symbolic-link file does not have its body. */ + rar->bytes_remaining = 0; + archive_entry_set_size(entry, 0); + + /* Read a symbolic-link name. */ + if ((ret2 = read_symlink_stored(a, entry, sconv)) < (ARCHIVE_WARN)) + return ret2; + if (ret > ret2) + ret = ret2; + } + + if (rar->bytes_remaining == 0) + rar->entry_eof = 1; + + return ret; +} + +static time_t +get_time(int ttime) +{ + struct tm tm; + tm.tm_sec = 2 * (ttime & 0x1f); + tm.tm_min = (ttime >> 5) & 0x3f; + tm.tm_hour = (ttime >> 11) & 0x1f; + tm.tm_mday = (ttime >> 16) & 0x1f; + tm.tm_mon = ((ttime >> 21) & 0x0f) - 1; + tm.tm_year = ((ttime >> 25) & 0x7f) + 80; + tm.tm_isdst = -1; + return mktime(&tm); +} + +static int +read_exttime(const char *p, struct rar *rar, const char *endp) +{ + unsigned rmode, flags, rem, j, count; + int ttime, i; + struct tm *tm; + time_t t; + long nsec; +#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S) + struct tm tmbuf; +#endif +#if defined(HAVE__LOCALTIME64_S) + errno_t terr; + __time64_t tmptime; +#endif + + if (p + 2 > endp) + return (-1); + flags = archive_le16dec(p); + p += 2; + + for (i = 3; i >= 0; i--) + { + t = 0; + if (i == 3) + t = rar->mtime; + rmode = flags >> i * 4; + if (rmode & 8) + { + if (!t) + { + if (p + 4 > endp) + return (-1); + ttime = archive_le32dec(p); + t = get_time(ttime); + p += 4; + } + rem = 0; + count = rmode & 3; + if (p + count > endp) + return (-1); + for (j = 0; j < count; j++) + { + rem = (((unsigned)(unsigned char)*p) << 16) | (rem >> 8); + p++; + } +#if defined(HAVE_LOCALTIME_R) + tm = localtime_r(&t, &tmbuf); +#elif defined(HAVE__LOCALTIME64_S) + tmptime = t; + terr = _localtime64_s(&tmbuf, &tmptime); + if (terr) + tm = NULL; + else + tm = &tmbuf; +#else + tm = localtime(&t); +#endif + nsec = tm->tm_sec + rem / NS_UNIT; + if (rmode & 4) + { + tm->tm_sec++; + t = mktime(tm); + } + if (i == 3) + { + rar->mtime = t; + rar->mnsec = nsec; + } + else if (i == 2) + { + rar->ctime = t; + rar->cnsec = nsec; + } + else if (i == 1) + { + rar->atime = t; + rar->ansec = nsec; + } + else + { + rar->arctime = t; + rar->arcnsec = nsec; + } + } + } + return (0); +} + +static int +read_symlink_stored(struct archive_read *a, struct archive_entry *entry, + struct archive_string_conv *sconv) +{ + const void *h; + const char *p; + struct rar *rar; + int ret = (ARCHIVE_OK); + + rar = (struct rar *)(a->format->data); + if ((h = rar_read_ahead(a, (size_t)rar->packed_size, NULL)) == NULL) + return (ARCHIVE_FATAL); + p = h; + + if (archive_entry_copy_symlink_l(entry, + p, (size_t)rar->packed_size, sconv)) + { + if (errno == ENOMEM) + { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for link"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "link cannot be converted from %s to current locale.", + archive_string_conversion_charset_name(sconv)); + ret = (ARCHIVE_WARN); + } + __archive_read_consume(a, rar->packed_size); + return ret; +} + +static int +read_data_stored(struct archive_read *a, const void **buff, size_t *size, + int64_t *offset) +{ + struct rar *rar; + ssize_t bytes_avail; + + rar = (struct rar *)(a->format->data); + if (rar->bytes_remaining == 0 && + !(rar->main_flags & MHD_VOLUME && rar->file_flags & FHD_SPLIT_AFTER)) + { + *buff = NULL; + *size = 0; + *offset = rar->offset; + if (rar->file_crc != rar->crc_calculated) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "File CRC error"); + return (ARCHIVE_FATAL); + } + rar->entry_eof = 1; + return (ARCHIVE_EOF); + } + + *buff = rar_read_ahead(a, 1, &bytes_avail); + if (bytes_avail <= 0) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated RAR file data"); + return (ARCHIVE_FATAL); + } + + *size = bytes_avail; + *offset = rar->offset; + rar->offset += bytes_avail; + rar->offset_seek += bytes_avail; + rar->bytes_remaining -= bytes_avail; + rar->bytes_unconsumed = bytes_avail; + /* Calculate File CRC. */ + rar->crc_calculated = crc32(rar->crc_calculated, *buff, + (unsigned)bytes_avail); + return (ARCHIVE_OK); +} + +static int +read_data_compressed(struct archive_read *a, const void **buff, size_t *size, + int64_t *offset) +{ + struct rar *rar; + int64_t start, end, actualend; + size_t bs; + int ret = (ARCHIVE_OK), sym, code, lzss_offset, length, i; + + rar = (struct rar *)(a->format->data); + + do { + if (!rar->valid) + return (ARCHIVE_FATAL); + if (rar->ppmd_eod || + (rar->dictionary_size && rar->offset >= rar->unp_size)) + { + if (rar->unp_offset > 0) { + /* + * We have unprocessed extracted data. write it out. + */ + *buff = rar->unp_buffer; + *size = rar->unp_offset; + *offset = rar->offset_outgoing; + rar->offset_outgoing += *size; + /* Calculate File CRC. */ + rar->crc_calculated = crc32(rar->crc_calculated, *buff, + (unsigned)*size); + rar->unp_offset = 0; + return (ARCHIVE_OK); + } + *buff = NULL; + *size = 0; + *offset = rar->offset; + if (rar->file_crc != rar->crc_calculated) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "File CRC error"); + return (ARCHIVE_FATAL); + } + rar->entry_eof = 1; + return (ARCHIVE_EOF); + } + + if (!rar->is_ppmd_block && rar->dictionary_size && rar->bytes_uncopied > 0) + { + if (rar->bytes_uncopied > (rar->unp_buffer_size - rar->unp_offset)) + bs = rar->unp_buffer_size - rar->unp_offset; + else + bs = (size_t)rar->bytes_uncopied; + ret = copy_from_lzss_window(a, buff, rar->offset, (int)bs); + if (ret != ARCHIVE_OK) + return (ret); + rar->offset += bs; + rar->bytes_uncopied -= bs; + if (*buff != NULL) { + rar->unp_offset = 0; + *size = rar->unp_buffer_size; + *offset = rar->offset_outgoing; + rar->offset_outgoing += *size; + /* Calculate File CRC. */ + rar->crc_calculated = crc32(rar->crc_calculated, *buff, + (unsigned)*size); + return (ret); + } + continue; + } + + if (!rar->br.next_in && + (ret = rar_br_preparation(a, &(rar->br))) < ARCHIVE_WARN) + return (ret); + if (rar->start_new_table && ((ret = parse_codes(a)) < (ARCHIVE_WARN))) + return (ret); + + if (rar->is_ppmd_block) + { + if ((sym = __archive_ppmd7_functions.Ppmd7_DecodeSymbol( + &rar->ppmd7_context, &rar->range_dec.p)) < 0) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid symbol"); + return (ARCHIVE_FATAL); + } + if(sym != rar->ppmd_escape) + { + lzss_emit_literal(rar, sym); + rar->bytes_uncopied++; + } + else + { + if ((code = __archive_ppmd7_functions.Ppmd7_DecodeSymbol( + &rar->ppmd7_context, &rar->range_dec.p)) < 0) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid symbol"); + return (ARCHIVE_FATAL); + } + + switch(code) + { + case 0: + rar->start_new_table = 1; + return read_data_compressed(a, buff, size, offset); + + case 2: + rar->ppmd_eod = 1;/* End Of ppmd Data. */ + continue; + + case 3: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Parsing filters is unsupported."); + return (ARCHIVE_FAILED); + + case 4: + lzss_offset = 0; + for (i = 2; i >= 0; i--) + { + if ((code = __archive_ppmd7_functions.Ppmd7_DecodeSymbol( + &rar->ppmd7_context, &rar->range_dec.p)) < 0) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid symbol"); + return (ARCHIVE_FATAL); + } + lzss_offset |= code << (i * 8); + } + if ((length = __archive_ppmd7_functions.Ppmd7_DecodeSymbol( + &rar->ppmd7_context, &rar->range_dec.p)) < 0) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid symbol"); + return (ARCHIVE_FATAL); + } + lzss_emit_match(rar, lzss_offset + 2, length + 32); + rar->bytes_uncopied += length + 32; + break; + + case 5: + if ((length = __archive_ppmd7_functions.Ppmd7_DecodeSymbol( + &rar->ppmd7_context, &rar->range_dec.p)) < 0) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid symbol"); + return (ARCHIVE_FATAL); + } + lzss_emit_match(rar, 1, length + 4); + rar->bytes_uncopied += length + 4; + break; + + default: + lzss_emit_literal(rar, sym); + rar->bytes_uncopied++; + } + } + } + else + { + start = rar->offset; + end = start + rar->dictionary_size; + rar->filterstart = INT64_MAX; + + if ((actualend = expand(a, end)) < 0) + return ((int)actualend); + + rar->bytes_uncopied = actualend - start; + if (rar->bytes_uncopied == 0) { + /* Broken RAR files cause this case. + * NOTE: If this case were possible on a normal RAR file + * we would find out where it was actually bad and + * what we would do to solve it. */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Internal error extracting RAR file"); + return (ARCHIVE_FATAL); + } + } + if (rar->bytes_uncopied > (rar->unp_buffer_size - rar->unp_offset)) + bs = rar->unp_buffer_size - rar->unp_offset; + else + bs = (size_t)rar->bytes_uncopied; + ret = copy_from_lzss_window(a, buff, rar->offset, (int)bs); + if (ret != ARCHIVE_OK) + return (ret); + rar->offset += bs; + rar->bytes_uncopied -= bs; + /* + * If *buff is NULL, it means unp_buffer is not full. + * So we have to continue extracting a RAR file. + */ + } while (*buff == NULL); + + rar->unp_offset = 0; + *size = rar->unp_buffer_size; + *offset = rar->offset_outgoing; + rar->offset_outgoing += *size; + /* Calculate File CRC. */ + rar->crc_calculated = crc32(rar->crc_calculated, *buff, (unsigned)*size); + return ret; +} + +static int +parse_codes(struct archive_read *a) +{ + int i, j, val, n, r; + unsigned char bitlengths[MAX_SYMBOLS], zerocount, ppmd_flags; + unsigned int maxorder; + struct huffman_code precode; + struct rar *rar = (struct rar *)(a->format->data); + struct rar_br *br = &(rar->br); + + free_codes(a); + + /* Skip to the next byte */ + rar_br_consume_unalined_bits(br); + + /* PPMd block flag */ + if (!rar_br_read_ahead(a, br, 1)) + goto truncated_data; + if ((rar->is_ppmd_block = rar_br_bits(br, 1)) != 0) + { + rar_br_consume(br, 1); + if (!rar_br_read_ahead(a, br, 7)) + goto truncated_data; + ppmd_flags = rar_br_bits(br, 7); + rar_br_consume(br, 7); + + /* Memory is allocated in MB */ + if (ppmd_flags & 0x20) + { + if (!rar_br_read_ahead(a, br, 8)) + goto truncated_data; + rar->dictionary_size = (rar_br_bits(br, 8) + 1) << 20; + rar_br_consume(br, 8); + } + + if (ppmd_flags & 0x40) + { + if (!rar_br_read_ahead(a, br, 8)) + goto truncated_data; + rar->ppmd_escape = rar->ppmd7_context.InitEsc = rar_br_bits(br, 8); + rar_br_consume(br, 8); + } + else + rar->ppmd_escape = 2; + + if (ppmd_flags & 0x20) + { + maxorder = (ppmd_flags & 0x1F) + 1; + if(maxorder > 16) + maxorder = 16 + (maxorder - 16) * 3; + + if (maxorder == 1) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated RAR file data"); + return (ARCHIVE_FATAL); + } + + /* Make sure ppmd7_contest is freed before Ppmd7_Construct + * because reading a broken file cause this abnormal sequence. */ + __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context); + + rar->bytein.a = a; + rar->bytein.Read = &ppmd_read; + __archive_ppmd7_functions.PpmdRAR_RangeDec_CreateVTable(&rar->range_dec); + rar->range_dec.Stream = &rar->bytein; + __archive_ppmd7_functions.Ppmd7_Construct(&rar->ppmd7_context); + + if (rar->dictionary_size == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid zero dictionary size"); + return (ARCHIVE_FATAL); + } + + if (!__archive_ppmd7_functions.Ppmd7_Alloc(&rar->ppmd7_context, + rar->dictionary_size)) + { + archive_set_error(&a->archive, ENOMEM, + "Out of memory"); + return (ARCHIVE_FATAL); + } + if (!__archive_ppmd7_functions.PpmdRAR_RangeDec_Init(&rar->range_dec)) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Unable to initialize PPMd range decoder"); + return (ARCHIVE_FATAL); + } + __archive_ppmd7_functions.Ppmd7_Init(&rar->ppmd7_context, maxorder); + rar->ppmd_valid = 1; + } + else + { + if (!rar->ppmd_valid) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid PPMd sequence"); + return (ARCHIVE_FATAL); + } + if (!__archive_ppmd7_functions.PpmdRAR_RangeDec_Init(&rar->range_dec)) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Unable to initialize PPMd range decoder"); + return (ARCHIVE_FATAL); + } + } + } + else + { + rar_br_consume(br, 1); + + /* Keep existing table flag */ + if (!rar_br_read_ahead(a, br, 1)) + goto truncated_data; + if (!rar_br_bits(br, 1)) + memset(rar->lengthtable, 0, sizeof(rar->lengthtable)); + rar_br_consume(br, 1); + + memset(&bitlengths, 0, sizeof(bitlengths)); + for (i = 0; i < MAX_SYMBOLS;) + { + if (!rar_br_read_ahead(a, br, 4)) + goto truncated_data; + bitlengths[i++] = rar_br_bits(br, 4); + rar_br_consume(br, 4); + if (bitlengths[i-1] == 0xF) + { + if (!rar_br_read_ahead(a, br, 4)) + goto truncated_data; + zerocount = rar_br_bits(br, 4); + rar_br_consume(br, 4); + if (zerocount) + { + i--; + for (j = 0; j < zerocount + 2 && i < MAX_SYMBOLS; j++) + bitlengths[i++] = 0; + } + } + } + + memset(&precode, 0, sizeof(precode)); + r = create_code(a, &precode, bitlengths, MAX_SYMBOLS, MAX_SYMBOL_LENGTH); + if (r != ARCHIVE_OK) { + free(precode.tree); + free(precode.table); + return (r); + } + + for (i = 0; i < HUFFMAN_TABLE_SIZE;) + { + if ((val = read_next_symbol(a, &precode)) < 0) { + free(precode.tree); + free(precode.table); + return (ARCHIVE_FATAL); + } + if (val < 16) + { + rar->lengthtable[i] = (rar->lengthtable[i] + val) & 0xF; + i++; + } + else if (val < 18) + { + if (i == 0) + { + free(precode.tree); + free(precode.table); + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Internal error extracting RAR file."); + return (ARCHIVE_FATAL); + } + + if(val == 16) { + if (!rar_br_read_ahead(a, br, 3)) { + free(precode.tree); + free(precode.table); + goto truncated_data; + } + n = rar_br_bits(br, 3) + 3; + rar_br_consume(br, 3); + } else { + if (!rar_br_read_ahead(a, br, 7)) { + free(precode.tree); + free(precode.table); + goto truncated_data; + } + n = rar_br_bits(br, 7) + 11; + rar_br_consume(br, 7); + } + + for (j = 0; j < n && i < HUFFMAN_TABLE_SIZE; j++) + { + rar->lengthtable[i] = rar->lengthtable[i-1]; + i++; + } + } + else + { + if(val == 18) { + if (!rar_br_read_ahead(a, br, 3)) { + free(precode.tree); + free(precode.table); + goto truncated_data; + } + n = rar_br_bits(br, 3) + 3; + rar_br_consume(br, 3); + } else { + if (!rar_br_read_ahead(a, br, 7)) { + free(precode.tree); + free(precode.table); + goto truncated_data; + } + n = rar_br_bits(br, 7) + 11; + rar_br_consume(br, 7); + } + + for(j = 0; j < n && i < HUFFMAN_TABLE_SIZE; j++) + rar->lengthtable[i++] = 0; + } + } + free(precode.tree); + free(precode.table); + + r = create_code(a, &rar->maincode, &rar->lengthtable[0], MAINCODE_SIZE, + MAX_SYMBOL_LENGTH); + if (r != ARCHIVE_OK) + return (r); + r = create_code(a, &rar->offsetcode, &rar->lengthtable[MAINCODE_SIZE], + OFFSETCODE_SIZE, MAX_SYMBOL_LENGTH); + if (r != ARCHIVE_OK) + return (r); + r = create_code(a, &rar->lowoffsetcode, + &rar->lengthtable[MAINCODE_SIZE + OFFSETCODE_SIZE], + LOWOFFSETCODE_SIZE, MAX_SYMBOL_LENGTH); + if (r != ARCHIVE_OK) + return (r); + r = create_code(a, &rar->lengthcode, + &rar->lengthtable[MAINCODE_SIZE + OFFSETCODE_SIZE + + LOWOFFSETCODE_SIZE], LENGTHCODE_SIZE, MAX_SYMBOL_LENGTH); + if (r != ARCHIVE_OK) + return (r); + } + + if (!rar->dictionary_size || !rar->lzss.window) + { + /* Seems as though dictionary sizes are not used. Even so, minimize + * memory usage as much as possible. + */ + void *new_window; + unsigned int new_size; + + if (rar->unp_size >= DICTIONARY_MAX_SIZE) + new_size = DICTIONARY_MAX_SIZE; + else + new_size = rar_fls((unsigned int)rar->unp_size) << 1; + if (new_size == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Zero window size is invalid."); + return (ARCHIVE_FATAL); + } + new_window = realloc(rar->lzss.window, new_size); + if (new_window == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Unable to allocate memory for uncompressed data."); + return (ARCHIVE_FATAL); + } + rar->lzss.window = (unsigned char *)new_window; + rar->dictionary_size = new_size; + memset(rar->lzss.window, 0, rar->dictionary_size); + rar->lzss.mask = rar->dictionary_size - 1; + } + + rar->start_new_table = 0; + return (ARCHIVE_OK); +truncated_data: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated RAR file data"); + rar->valid = 0; + return (ARCHIVE_FATAL); +} + +static void +free_codes(struct archive_read *a) +{ + struct rar *rar = (struct rar *)(a->format->data); + free(rar->maincode.tree); + free(rar->offsetcode.tree); + free(rar->lowoffsetcode.tree); + free(rar->lengthcode.tree); + free(rar->maincode.table); + free(rar->offsetcode.table); + free(rar->lowoffsetcode.table); + free(rar->lengthcode.table); + memset(&rar->maincode, 0, sizeof(rar->maincode)); + memset(&rar->offsetcode, 0, sizeof(rar->offsetcode)); + memset(&rar->lowoffsetcode, 0, sizeof(rar->lowoffsetcode)); + memset(&rar->lengthcode, 0, sizeof(rar->lengthcode)); +} + + +static int +read_next_symbol(struct archive_read *a, struct huffman_code *code) +{ + unsigned char bit; + unsigned int bits; + int length, value, node; + struct rar *rar; + struct rar_br *br; + + if (!code->table) + { + if (make_table(a, code) != (ARCHIVE_OK)) + return -1; + } + + rar = (struct rar *)(a->format->data); + br = &(rar->br); + + /* Look ahead (peek) at bits */ + if (!rar_br_read_ahead(a, br, code->tablesize)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated RAR file data"); + rar->valid = 0; + return -1; + } + bits = rar_br_bits(br, code->tablesize); + + length = code->table[bits].length; + value = code->table[bits].value; + + if (length < 0) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid prefix code in bitstream"); + return -1; + } + + if (length <= code->tablesize) + { + /* Skip length bits */ + rar_br_consume(br, length); + return value; + } + + /* Skip tablesize bits */ + rar_br_consume(br, code->tablesize); + + node = value; + while (!(code->tree[node].branches[0] == + code->tree[node].branches[1])) + { + if (!rar_br_read_ahead(a, br, 1)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated RAR file data"); + rar->valid = 0; + return -1; + } + bit = rar_br_bits(br, 1); + rar_br_consume(br, 1); + + if (code->tree[node].branches[bit] < 0) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid prefix code in bitstream"); + return -1; + } + node = code->tree[node].branches[bit]; + } + + return code->tree[node].branches[0]; +} + +static int +create_code(struct archive_read *a, struct huffman_code *code, + unsigned char *lengths, int numsymbols, char maxlength) +{ + int i, j, codebits = 0, symbolsleft = numsymbols; + + code->numentries = 0; + code->numallocatedentries = 0; + if (new_node(code) < 0) { + archive_set_error(&a->archive, ENOMEM, + "Unable to allocate memory for node data."); + return (ARCHIVE_FATAL); + } + code->numentries = 1; + code->minlength = INT_MAX; + code->maxlength = INT_MIN; + codebits = 0; + for(i = 1; i <= maxlength; i++) + { + for(j = 0; j < numsymbols; j++) + { + if (lengths[j] != i) continue; + if (add_value(a, code, j, codebits, i) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + codebits++; + if (--symbolsleft <= 0) + break; + } + if (symbolsleft <= 0) + break; + codebits <<= 1; + } + return (ARCHIVE_OK); +} + +static int +add_value(struct archive_read *a, struct huffman_code *code, int value, + int codebits, int length) +{ + int lastnode, bitpos, bit; + /* int repeatpos, repeatnode, nextnode; */ + + free(code->table); + code->table = NULL; + + if(length > code->maxlength) + code->maxlength = length; + if(length < code->minlength) + code->minlength = length; + + /* + * Dead code, repeatpos was is -1 + * + repeatpos = -1; + if (repeatpos == 0 || (repeatpos >= 0 + && (((codebits >> (repeatpos - 1)) & 3) == 0 + || ((codebits >> (repeatpos - 1)) & 3) == 3))) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid repeat position"); + return (ARCHIVE_FATAL); + } + */ + + lastnode = 0; + for (bitpos = length - 1; bitpos >= 0; bitpos--) + { + bit = (codebits >> bitpos) & 1; + + /* Leaf node check */ + if (code->tree[lastnode].branches[0] == + code->tree[lastnode].branches[1]) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Prefix found"); + return (ARCHIVE_FATAL); + } + + /* + * Dead code, repeatpos was -1, bitpos >=0 + * + if (bitpos == repeatpos) + { + * Open branch check * + if (!(code->tree[lastnode].branches[bit] < 0)) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid repeating code"); + return (ARCHIVE_FATAL); + } + + if ((repeatnode = new_node(code)) < 0) { + archive_set_error(&a->archive, ENOMEM, + "Unable to allocate memory for node data."); + return (ARCHIVE_FATAL); + } + if ((nextnode = new_node(code)) < 0) { + archive_set_error(&a->archive, ENOMEM, + "Unable to allocate memory for node data."); + return (ARCHIVE_FATAL); + } + + * Set branches * + code->tree[lastnode].branches[bit] = repeatnode; + code->tree[repeatnode].branches[bit] = repeatnode; + code->tree[repeatnode].branches[bit^1] = nextnode; + lastnode = nextnode; + + bitpos++; * terminating bit already handled, skip it * + } + else + { + */ + /* Open branch check */ + if (code->tree[lastnode].branches[bit] < 0) + { + if (new_node(code) < 0) { + archive_set_error(&a->archive, ENOMEM, + "Unable to allocate memory for node data."); + return (ARCHIVE_FATAL); + } + code->tree[lastnode].branches[bit] = code->numentries++; + } + + /* set to branch */ + lastnode = code->tree[lastnode].branches[bit]; + /* } */ + } + + if (!(code->tree[lastnode].branches[0] == -1 + && code->tree[lastnode].branches[1] == -2)) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Prefix found"); + return (ARCHIVE_FATAL); + } + + /* Set leaf value */ + code->tree[lastnode].branches[0] = value; + code->tree[lastnode].branches[1] = value; + + return (ARCHIVE_OK); +} + +static int +new_node(struct huffman_code *code) +{ + void *new_tree; + if (code->numallocatedentries == code->numentries) { + int new_num_entries = 256; + if (code->numentries > 0) { + new_num_entries = code->numentries * 2; + } + new_tree = realloc(code->tree, new_num_entries * sizeof(*code->tree)); + if (new_tree == NULL) + return (-1); + code->tree = (struct huffman_tree_node *)new_tree; + code->numallocatedentries = new_num_entries; + } + code->tree[code->numentries].branches[0] = -1; + code->tree[code->numentries].branches[1] = -2; + return 1; +} + +static int +make_table(struct archive_read *a, struct huffman_code *code) +{ + if (code->maxlength < code->minlength || code->maxlength > 10) + code->tablesize = 10; + else + code->tablesize = code->maxlength; + + code->table = + (struct huffman_table_entry *)calloc(1, sizeof(*code->table) + * ((size_t)1 << code->tablesize)); + + return make_table_recurse(a, code, 0, code->table, 0, code->tablesize); +} + +static int +make_table_recurse(struct archive_read *a, struct huffman_code *code, int node, + struct huffman_table_entry *table, int depth, + int maxdepth) +{ + int currtablesize, i, ret = (ARCHIVE_OK); + + if (!code->tree) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Huffman tree was not created."); + return (ARCHIVE_FATAL); + } + if (node < 0 || node >= code->numentries) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid location to Huffman tree specified."); + return (ARCHIVE_FATAL); + } + + currtablesize = 1 << (maxdepth - depth); + + if (code->tree[node].branches[0] == + code->tree[node].branches[1]) + { + for(i = 0; i < currtablesize; i++) + { + table[i].length = depth; + table[i].value = code->tree[node].branches[0]; + } + } + /* + * Dead code, node >= 0 + * + else if (node < 0) + { + for(i = 0; i < currtablesize; i++) + table[i].length = -1; + } + */ + else + { + if(depth == maxdepth) + { + table[0].length = maxdepth + 1; + table[0].value = node; + } + else + { + ret |= make_table_recurse(a, code, code->tree[node].branches[0], table, + depth + 1, maxdepth); + ret |= make_table_recurse(a, code, code->tree[node].branches[1], + table + currtablesize / 2, depth + 1, maxdepth); + } + } + return ret; +} + +static int64_t +expand(struct archive_read *a, int64_t end) +{ + static const unsigned char lengthbases[] = + { 0, 1, 2, 3, 4, 5, 6, + 7, 8, 10, 12, 14, 16, 20, + 24, 28, 32, 40, 48, 56, 64, + 80, 96, 112, 128, 160, 192, 224 }; + static const unsigned char lengthbits[] = + { 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 2, 2, + 2, 2, 3, 3, 3, 3, 4, + 4, 4, 4, 5, 5, 5, 5 }; + static const int lengthb_min = minimum( + (int)(sizeof(lengthbases)/sizeof(lengthbases[0])), + (int)(sizeof(lengthbits)/sizeof(lengthbits[0])) + ); + static const unsigned int offsetbases[] = + { 0, 1, 2, 3, 4, 6, + 8, 12, 16, 24, 32, 48, + 64, 96, 128, 192, 256, 384, + 512, 768, 1024, 1536, 2048, 3072, + 4096, 6144, 8192, 12288, 16384, 24576, + 32768, 49152, 65536, 98304, 131072, 196608, + 262144, 327680, 393216, 458752, 524288, 589824, + 655360, 720896, 786432, 851968, 917504, 983040, + 1048576, 1310720, 1572864, 1835008, 2097152, 2359296, + 2621440, 2883584, 3145728, 3407872, 3670016, 3932160 }; + static const unsigned char offsetbits[] = + { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, + 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, + 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18 }; + static const int offsetb_min = minimum( + (int)(sizeof(offsetbases)/sizeof(offsetbases[0])), + (int)(sizeof(offsetbits)/sizeof(offsetbits[0])) + ); + static const unsigned char shortbases[] = + { 0, 4, 8, 16, 32, 64, 128, 192 }; + static const unsigned char shortbits[] = + { 2, 2, 3, 4, 5, 6, 6, 6 }; + + int symbol, offs, len, offsindex, lensymbol, i, offssymbol, lowoffsetsymbol; + unsigned char newfile; + struct rar *rar = (struct rar *)(a->format->data); + struct rar_br *br = &(rar->br); + + if (rar->filterstart < end) + end = rar->filterstart; + + while (1) + { + if (rar->output_last_match && + lzss_position(&rar->lzss) + rar->lastlength <= end) + { + lzss_emit_match(rar, rar->lastoffset, rar->lastlength); + rar->output_last_match = 0; + } + + if(rar->is_ppmd_block || rar->output_last_match || + lzss_position(&rar->lzss) >= end) + return lzss_position(&rar->lzss); + + if ((symbol = read_next_symbol(a, &rar->maincode)) < 0) + return (ARCHIVE_FATAL); + rar->output_last_match = 0; + + if (symbol < 256) + { + lzss_emit_literal(rar, symbol); + continue; + } + else if (symbol == 256) + { + if (!rar_br_read_ahead(a, br, 1)) + goto truncated_data; + newfile = !rar_br_bits(br, 1); + rar_br_consume(br, 1); + + if(newfile) + { + rar->start_new_block = 1; + if (!rar_br_read_ahead(a, br, 1)) + goto truncated_data; + rar->start_new_table = rar_br_bits(br, 1); + rar_br_consume(br, 1); + return lzss_position(&rar->lzss); + } + else + { + if (parse_codes(a) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + continue; + } + } + else if(symbol==257) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Parsing filters is unsupported."); + return (ARCHIVE_FAILED); + } + else if(symbol==258) + { + if(rar->lastlength == 0) + continue; + + offs = rar->lastoffset; + len = rar->lastlength; + } + else if (symbol <= 262) + { + offsindex = symbol - 259; + offs = rar->oldoffset[offsindex]; + + if ((lensymbol = read_next_symbol(a, &rar->lengthcode)) < 0) + goto bad_data; + if (lensymbol > lengthb_min) + goto bad_data; + len = lengthbases[lensymbol] + 2; + if (lengthbits[lensymbol] > 0) { + if (!rar_br_read_ahead(a, br, lengthbits[lensymbol])) + goto truncated_data; + len += rar_br_bits(br, lengthbits[lensymbol]); + rar_br_consume(br, lengthbits[lensymbol]); + } + + for (i = offsindex; i > 0; i--) + rar->oldoffset[i] = rar->oldoffset[i-1]; + rar->oldoffset[0] = offs; + } + else if(symbol<=270) + { + offs = shortbases[symbol-263] + 1; + if(shortbits[symbol-263] > 0) { + if (!rar_br_read_ahead(a, br, shortbits[symbol-263])) + goto truncated_data; + offs += rar_br_bits(br, shortbits[symbol-263]); + rar_br_consume(br, shortbits[symbol-263]); + } + + len = 2; + + for(i = 3; i > 0; i--) + rar->oldoffset[i] = rar->oldoffset[i-1]; + rar->oldoffset[0] = offs; + } + else + { + if (symbol-271 > lengthb_min) + goto bad_data; + len = lengthbases[symbol-271]+3; + if(lengthbits[symbol-271] > 0) { + if (!rar_br_read_ahead(a, br, lengthbits[symbol-271])) + goto truncated_data; + len += rar_br_bits(br, lengthbits[symbol-271]); + rar_br_consume(br, lengthbits[symbol-271]); + } + + if ((offssymbol = read_next_symbol(a, &rar->offsetcode)) < 0) + goto bad_data; + if (offssymbol > offsetb_min) + goto bad_data; + offs = offsetbases[offssymbol]+1; + if(offsetbits[offssymbol] > 0) + { + if(offssymbol > 9) + { + if(offsetbits[offssymbol] > 4) { + if (!rar_br_read_ahead(a, br, offsetbits[offssymbol] - 4)) + goto truncated_data; + offs += rar_br_bits(br, offsetbits[offssymbol] - 4) << 4; + rar_br_consume(br, offsetbits[offssymbol] - 4); + } + + if(rar->numlowoffsetrepeats > 0) + { + rar->numlowoffsetrepeats--; + offs += rar->lastlowoffset; + } + else + { + if ((lowoffsetsymbol = + read_next_symbol(a, &rar->lowoffsetcode)) < 0) + return (ARCHIVE_FATAL); + if(lowoffsetsymbol == 16) + { + rar->numlowoffsetrepeats = 15; + offs += rar->lastlowoffset; + } + else + { + offs += lowoffsetsymbol; + rar->lastlowoffset = lowoffsetsymbol; + } + } + } + else { + if (!rar_br_read_ahead(a, br, offsetbits[offssymbol])) + goto truncated_data; + offs += rar_br_bits(br, offsetbits[offssymbol]); + rar_br_consume(br, offsetbits[offssymbol]); + } + } + + if (offs >= 0x40000) + len++; + if (offs >= 0x2000) + len++; + + for(i = 3; i > 0; i--) + rar->oldoffset[i] = rar->oldoffset[i-1]; + rar->oldoffset[0] = offs; + } + + rar->lastoffset = offs; + rar->lastlength = len; + rar->output_last_match = 1; + } +truncated_data: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated RAR file data"); + rar->valid = 0; + return (ARCHIVE_FATAL); +bad_data: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Bad RAR file data"); + return (ARCHIVE_FATAL); +} + +static int +copy_from_lzss_window(struct archive_read *a, const void **buffer, + int64_t startpos, int length) +{ + int windowoffs, firstpart; + struct rar *rar = (struct rar *)(a->format->data); + + if (!rar->unp_buffer) + { + if ((rar->unp_buffer = malloc(rar->unp_buffer_size)) == NULL) + { + archive_set_error(&a->archive, ENOMEM, + "Unable to allocate memory for uncompressed data."); + return (ARCHIVE_FATAL); + } + } + + windowoffs = lzss_offset_for_position(&rar->lzss, startpos); + if(windowoffs + length <= lzss_size(&rar->lzss)) { + memcpy(&rar->unp_buffer[rar->unp_offset], &rar->lzss.window[windowoffs], + length); + } else if (length <= lzss_size(&rar->lzss)) { + firstpart = lzss_size(&rar->lzss) - windowoffs; + if (firstpart < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Bad RAR file data"); + return (ARCHIVE_FATAL); + } + if (firstpart < length) { + memcpy(&rar->unp_buffer[rar->unp_offset], + &rar->lzss.window[windowoffs], firstpart); + memcpy(&rar->unp_buffer[rar->unp_offset + firstpart], + &rar->lzss.window[0], length - firstpart); + } else { + memcpy(&rar->unp_buffer[rar->unp_offset], + &rar->lzss.window[windowoffs], length); + } + } else { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Bad RAR file data"); + return (ARCHIVE_FATAL); + } + rar->unp_offset += length; + if (rar->unp_offset >= rar->unp_buffer_size) + *buffer = rar->unp_buffer; + else + *buffer = NULL; + return (ARCHIVE_OK); +} + +static const void * +rar_read_ahead(struct archive_read *a, size_t min, ssize_t *avail) +{ + struct rar *rar = (struct rar *)(a->format->data); + const void *h = __archive_read_ahead(a, min, avail); + int ret; + if (avail) + { + if (a->archive.read_data_is_posix_read && *avail > (ssize_t)a->archive.read_data_requested) + *avail = a->archive.read_data_requested; + if (*avail > rar->bytes_remaining) + *avail = (ssize_t)rar->bytes_remaining; + if (*avail < 0) + return NULL; + else if (*avail == 0 && rar->main_flags & MHD_VOLUME && + rar->file_flags & FHD_SPLIT_AFTER) + { + rar->filename_must_match = 1; + ret = archive_read_format_rar_read_header(a, a->entry); + if (ret == (ARCHIVE_EOF)) + { + rar->has_endarc_header = 1; + ret = archive_read_format_rar_read_header(a, a->entry); + } + rar->filename_must_match = 0; + if (ret != (ARCHIVE_OK)) + return NULL; + return rar_read_ahead(a, min, avail); + } + } + return h; +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_rar5.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_rar5.c new file mode 100644 index 0000000..82729bd --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_rar5.c @@ -0,0 +1,4103 @@ +/*- +* Copyright (c) 2018 Grzegorz Antoniak (http://antoniak.org) +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "archive_platform.h" +#include "archive_endian.h" + +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_ZLIB_H +#include /* crc32 */ +#endif +#ifdef HAVE_LIMITS_H +#include +#endif + +#include "archive.h" +#ifndef HAVE_ZLIB_H +#include "archive_crc32.h" +#endif + +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_ppmd7_private.h" +#include "archive_entry_private.h" + +#ifdef HAVE_BLAKE2_H +#include +#else +#include "archive_blake2.h" +#endif + +/*#define CHECK_CRC_ON_SOLID_SKIP*/ +/*#define DONT_FAIL_ON_CRC_ERROR*/ +/*#define DEBUG*/ + +#define rar5_min(a, b) (((a) > (b)) ? (b) : (a)) +#define rar5_max(a, b) (((a) > (b)) ? (a) : (b)) +#define rar5_countof(X) ((const ssize_t) (sizeof(X) / sizeof(*X))) + +#if defined DEBUG +#define DEBUG_CODE if(1) +#define LOG(...) do { printf("rar5: " __VA_ARGS__); puts(""); } while(0) +#else +#define DEBUG_CODE if(0) +#endif + +/* Real RAR5 magic number is: + * + * 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x01, 0x00 + * "Rar!→•☺·\x00" + * + * Retrieved with `rar5_signature()` by XOR'ing it with 0xA1, because I don't + * want to put this magic sequence in each binary that uses libarchive, so + * applications that scan through the file for this marker won't trigger on + * this "false" one. + * + * The array itself is decrypted in `rar5_init` function. */ + +static unsigned char rar5_signature_xor[] = { 243, 192, 211, 128, 187, 166, 160, 161 }; +static const size_t g_unpack_window_size = 0x20000; + +/* These could have been static const's, but they aren't, because of + * Visual Studio. */ +#define MAX_NAME_IN_CHARS 2048 +#define MAX_NAME_IN_BYTES (4 * MAX_NAME_IN_CHARS) + +struct file_header { + ssize_t bytes_remaining; + ssize_t unpacked_size; + int64_t last_offset; /* Used in sanity checks. */ + int64_t last_size; /* Used in sanity checks. */ + + uint8_t solid : 1; /* Is this a solid stream? */ + uint8_t service : 1; /* Is this file a service data? */ + uint8_t eof : 1; /* Did we finish unpacking the file? */ + uint8_t dir : 1; /* Is this file entry a directory? */ + + /* Optional time fields. */ + uint64_t e_mtime; + uint64_t e_ctime; + uint64_t e_atime; + uint32_t e_unix_ns; + + /* Optional hash fields. */ + uint32_t stored_crc32; + uint32_t calculated_crc32; + uint8_t blake2sp[32]; + blake2sp_state b2state; + char has_blake2; + + /* Optional redir fields */ + uint64_t redir_type; + uint64_t redir_flags; + + ssize_t solid_window_size; /* Used in file format check. */ +}; + +enum EXTRA { + EX_CRYPT = 0x01, + EX_HASH = 0x02, + EX_HTIME = 0x03, + EX_VERSION = 0x04, + EX_REDIR = 0x05, + EX_UOWNER = 0x06, + EX_SUBDATA = 0x07 +}; + +#define REDIR_SYMLINK_IS_DIR 1 + +enum REDIR_TYPE { + REDIR_TYPE_NONE = 0, + REDIR_TYPE_UNIXSYMLINK = 1, + REDIR_TYPE_WINSYMLINK = 2, + REDIR_TYPE_JUNCTION = 3, + REDIR_TYPE_HARDLINK = 4, + REDIR_TYPE_FILECOPY = 5, +}; + +#define OWNER_USER_NAME 0x01 +#define OWNER_GROUP_NAME 0x02 +#define OWNER_USER_UID 0x04 +#define OWNER_GROUP_GID 0x08 +#define OWNER_MAXNAMELEN 256 + +enum FILTER_TYPE { + FILTER_DELTA = 0, /* Generic pattern. */ + FILTER_E8 = 1, /* Intel x86 code. */ + FILTER_E8E9 = 2, /* Intel x86 code. */ + FILTER_ARM = 3, /* ARM code. */ + FILTER_AUDIO = 4, /* Audio filter, not used in RARv5. */ + FILTER_RGB = 5, /* Color palette, not used in RARv5. */ + FILTER_ITANIUM = 6, /* Intel's Itanium, not used in RARv5. */ + FILTER_PPM = 7, /* Predictive pattern matching, not used in + RARv5. */ + FILTER_NONE = 8, +}; + +struct filter_info { + int type; + int channels; + int pos_r; + + int64_t block_start; + ssize_t block_length; + uint16_t width; +}; + +struct data_ready { + char used; + const uint8_t* buf; + size_t size; + int64_t offset; +}; + +struct cdeque { + uint16_t beg_pos; + uint16_t end_pos; + uint16_t cap_mask; + uint16_t size; + size_t* arr; +}; + +struct decode_table { + uint32_t size; + int32_t decode_len[16]; + uint32_t decode_pos[16]; + uint32_t quick_bits; + uint8_t quick_len[1 << 10]; + uint16_t quick_num[1 << 10]; + uint16_t decode_num[306]; +}; + +struct comp_state { + /* Flag used to specify if unpacker needs to reinitialize the + uncompression context. */ + uint8_t initialized : 1; + + /* Flag used when applying filters. */ + uint8_t all_filters_applied : 1; + + /* Flag used to skip file context reinitialization, used when unpacker + is skipping through different multivolume archives. */ + uint8_t switch_multivolume : 1; + + /* Flag used to specify if unpacker has processed the whole data block + or just a part of it. */ + uint8_t block_parsing_finished : 1; + + signed int notused : 4; + + int flags; /* Uncompression flags. */ + int method; /* Uncompression algorithm method. */ + int version; /* Uncompression algorithm version. */ + ssize_t window_size; /* Size of window_buf. */ + uint8_t* window_buf; /* Circular buffer used during + decompression. */ + uint8_t* filtered_buf; /* Buffer used when applying filters. */ + const uint8_t* block_buf; /* Buffer used when merging blocks. */ + size_t window_mask; /* Convenience field; window_size - 1. */ + int64_t write_ptr; /* This amount of data has been unpacked + in the window buffer. */ + int64_t last_write_ptr; /* This amount of data has been stored in + the output file. */ + int64_t last_unstore_ptr; /* Counter of bytes extracted during + unstoring. This is separate from + last_write_ptr because of how SERVICE + base blocks are handled during skipping + in solid multiarchive archives. */ + int64_t solid_offset; /* Additional offset inside the window + buffer, used in unpacking solid + archives. */ + ssize_t cur_block_size; /* Size of current data block. */ + int last_len; /* Flag used in lzss decompression. */ + + /* Decode tables used during lzss uncompression. */ + +#define HUFF_BC 20 + struct decode_table bd; /* huffman bit lengths */ +#define HUFF_NC 306 + struct decode_table ld; /* literals */ +#define HUFF_DC 64 + struct decode_table dd; /* distances */ +#define HUFF_LDC 16 + struct decode_table ldd; /* lower bits of distances */ +#define HUFF_RC 44 + struct decode_table rd; /* repeating distances */ +#define HUFF_TABLE_SIZE (HUFF_NC + HUFF_DC + HUFF_RC + HUFF_LDC) + + /* Circular deque for storing filters. */ + struct cdeque filters; + int64_t last_block_start; /* Used for sanity checking. */ + ssize_t last_block_length; /* Used for sanity checking. */ + + /* Distance cache used during lzss uncompression. */ + int dist_cache[4]; + + /* Data buffer stack. */ + struct data_ready dready[2]; +}; + +/* Bit reader state. */ +struct bit_reader { + int8_t bit_addr; /* Current bit pointer inside current byte. */ + int in_addr; /* Current byte pointer. */ +}; + +/* RARv5 block header structure. Use bf_* functions to get values from + * block_flags_u8 field. I.e. bf_byte_count, etc. */ +struct compressed_block_header { + /* block_flags_u8 contain fields encoded in little-endian bitfield: + * + * - table present flag (shr 7, and 1), + * - last block flag (shr 6, and 1), + * - byte_count (shr 3, and 7), + * - bit_size (shr 0, and 7). + */ + uint8_t block_flags_u8; + uint8_t block_cksum; +}; + +/* RARv5 main header structure. */ +struct main_header { + /* Does the archive contain solid streams? */ + uint8_t solid : 1; + + /* If this a multi-file archive? */ + uint8_t volume : 1; + uint8_t endarc : 1; + uint8_t notused : 5; + + unsigned int vol_no; +}; + +struct generic_header { + uint8_t split_after : 1; + uint8_t split_before : 1; + uint8_t padding : 6; + int size; + int last_header_id; +}; + +struct multivolume { + unsigned int expected_vol_no; + uint8_t* push_buf; +}; + +/* Main context structure. */ +struct rar5 { + int header_initialized; + + /* Set to 1 if current file is positioned AFTER the magic value + * of the archive file. This is used in header reading functions. */ + int skipped_magic; + + /* Set to not zero if we're in skip mode (either by calling + * rar5_data_skip function or when skipping over solid streams). + * Set to 0 when in * extraction mode. This is used during checksum + * calculation functions. */ + int skip_mode; + + /* Set to not zero if we're in block merging mode (i.e. when switching + * to another file in multivolume archive, last block from 1st archive + * needs to be merged with 1st block from 2nd archive). This flag + * guards against recursive use of the merging function, which doesn't + * support recursive calls. */ + int merge_mode; + + /* An offset to QuickOpen list. This is not supported by this unpacker, + * because we're focusing on streaming interface. QuickOpen is designed + * to make things quicker for non-stream interfaces, so it's not our + * use case. */ + uint64_t qlist_offset; + + /* An offset to additional Recovery data. This is not supported by this + * unpacker. Recovery data are additional Reed-Solomon codes that could + * be used to calculate bytes that are missing in archive or are + * corrupted. */ + uint64_t rr_offset; + + /* Various context variables grouped to different structures. */ + struct generic_header generic; + struct main_header main; + struct comp_state cstate; + struct file_header file; + struct bit_reader bits; + struct multivolume vol; + + /* The header of currently processed RARv5 block. Used in main + * decompression logic loop. */ + struct compressed_block_header last_block_hdr; +}; + +/* Forward function declarations. */ + +static void rar5_signature(char *buf); +static int verify_global_checksums(struct archive_read* a); +static int rar5_read_data_skip(struct archive_read *a); +static int push_data_ready(struct archive_read* a, struct rar5* rar, + const uint8_t* buf, size_t size, int64_t offset); + +/* CDE_xxx = Circular Double Ended (Queue) return values. */ +enum CDE_RETURN_VALUES { + CDE_OK, CDE_ALLOC, CDE_PARAM, CDE_OUT_OF_BOUNDS, +}; + +/* Clears the contents of this circular deque. */ +static void cdeque_clear(struct cdeque* d) { + d->size = 0; + d->beg_pos = 0; + d->end_pos = 0; +} + +/* Creates a new circular deque object. Capacity must be power of 2: 8, 16, 32, + * 64, 256, etc. When the user will add another item above current capacity, + * the circular deque will overwrite the oldest entry. */ +static int cdeque_init(struct cdeque* d, int max_capacity_power_of_2) { + if(d == NULL || max_capacity_power_of_2 == 0) + return CDE_PARAM; + + d->cap_mask = max_capacity_power_of_2 - 1; + d->arr = NULL; + + if((max_capacity_power_of_2 & d->cap_mask) != 0) + return CDE_PARAM; + + cdeque_clear(d); + d->arr = malloc(sizeof(void*) * max_capacity_power_of_2); + + return d->arr ? CDE_OK : CDE_ALLOC; +} + +/* Return the current size (not capacity) of circular deque `d`. */ +static size_t cdeque_size(struct cdeque* d) { + return d->size; +} + +/* Returns the first element of current circular deque. Note that this function + * doesn't perform any bounds checking. If you need bounds checking, use + * `cdeque_front()` function instead. */ +static void cdeque_front_fast(struct cdeque* d, void** value) { + *value = (void*) d->arr[d->beg_pos]; +} + +/* Returns the first element of current circular deque. This function + * performs bounds checking. */ +static int cdeque_front(struct cdeque* d, void** value) { + if(d->size > 0) { + cdeque_front_fast(d, value); + return CDE_OK; + } else + return CDE_OUT_OF_BOUNDS; +} + +/* Pushes a new element into the end of this circular deque object. If current + * size will exceed capacity, the oldest element will be overwritten. */ +static int cdeque_push_back(struct cdeque* d, void* item) { + if(d == NULL) + return CDE_PARAM; + + if(d->size == d->cap_mask + 1) + return CDE_OUT_OF_BOUNDS; + + d->arr[d->end_pos] = (size_t) item; + d->end_pos = (d->end_pos + 1) & d->cap_mask; + d->size++; + + return CDE_OK; +} + +/* Pops a front element of this circular deque object and returns its value. + * This function doesn't perform any bounds checking. */ +static void cdeque_pop_front_fast(struct cdeque* d, void** value) { + *value = (void*) d->arr[d->beg_pos]; + d->beg_pos = (d->beg_pos + 1) & d->cap_mask; + d->size--; +} + +/* Pops a front element of this circular deque object and returns its value. + * This function performs bounds checking. */ +static int cdeque_pop_front(struct cdeque* d, void** value) { + if(!d || !value) + return CDE_PARAM; + + if(d->size == 0) + return CDE_OUT_OF_BOUNDS; + + cdeque_pop_front_fast(d, value); + return CDE_OK; +} + +/* Convenience function to cast filter_info** to void **. */ +static void** cdeque_filter_p(struct filter_info** f) { + return (void**) (size_t) f; +} + +/* Convenience function to cast filter_info* to void *. */ +static void* cdeque_filter(struct filter_info* f) { + return (void**) (size_t) f; +} + +/* Destroys this circular deque object. Deallocates the memory of the + * collection buffer, but doesn't deallocate the memory of any pointer passed + * to this deque as a value. */ +static void cdeque_free(struct cdeque* d) { + if(!d) + return; + + if(!d->arr) + return; + + free(d->arr); + + d->arr = NULL; + d->beg_pos = -1; + d->end_pos = -1; + d->cap_mask = 0; +} + +static inline +uint8_t bf_bit_size(const struct compressed_block_header* hdr) { + return hdr->block_flags_u8 & 7; +} + +static inline +uint8_t bf_byte_count(const struct compressed_block_header* hdr) { + return (hdr->block_flags_u8 >> 3) & 7; +} + +static inline +uint8_t bf_is_table_present(const struct compressed_block_header* hdr) { + return (hdr->block_flags_u8 >> 7) & 1; +} + +static inline struct rar5* get_context(struct archive_read* a) { + return (struct rar5*) a->format->data; +} + +/* Convenience functions used by filter implementations. */ +static void circular_memcpy(uint8_t* dst, uint8_t* window, const uint64_t mask, + int64_t start, int64_t end) +{ + if((start & mask) > (end & mask)) { + ssize_t len1 = mask + 1 - (start & mask); + ssize_t len2 = end & mask; + + memcpy(dst, &window[start & mask], len1); + memcpy(dst + len1, window, len2); + } else { + memcpy(dst, &window[start & mask], (size_t) (end - start)); + } +} + +static uint32_t read_filter_data(struct rar5* rar, uint32_t offset) { + uint8_t linear_buf[4]; + circular_memcpy(linear_buf, rar->cstate.window_buf, + rar->cstate.window_mask, offset, offset + 4); + return archive_le32dec(linear_buf); +} + +static void write_filter_data(struct rar5* rar, uint32_t offset, + uint32_t value) +{ + archive_le32enc(&rar->cstate.filtered_buf[offset], value); +} + +/* Allocates a new filter descriptor and adds it to the filter array. */ +static struct filter_info* add_new_filter(struct rar5* rar) { + struct filter_info* f = + (struct filter_info*) calloc(1, sizeof(struct filter_info)); + + if(!f) { + return NULL; + } + + cdeque_push_back(&rar->cstate.filters, cdeque_filter(f)); + return f; +} + +static int run_delta_filter(struct rar5* rar, struct filter_info* flt) { + int i; + ssize_t dest_pos, src_pos = 0; + + for(i = 0; i < flt->channels; i++) { + uint8_t prev_byte = 0; + for(dest_pos = i; + dest_pos < flt->block_length; + dest_pos += flt->channels) + { + uint8_t byte; + + byte = rar->cstate.window_buf[ + (rar->cstate.solid_offset + flt->block_start + + src_pos) & rar->cstate.window_mask]; + + prev_byte -= byte; + rar->cstate.filtered_buf[dest_pos] = prev_byte; + src_pos++; + } + } + + return ARCHIVE_OK; +} + +static int run_e8e9_filter(struct rar5* rar, struct filter_info* flt, + int extended) +{ + const uint32_t file_size = 0x1000000; + ssize_t i; + + circular_memcpy(rar->cstate.filtered_buf, + rar->cstate.window_buf, rar->cstate.window_mask, + rar->cstate.solid_offset + flt->block_start, + rar->cstate.solid_offset + flt->block_start + flt->block_length); + + for(i = 0; i < flt->block_length - 4;) { + uint8_t b = rar->cstate.window_buf[ + (rar->cstate.solid_offset + flt->block_start + + i++) & rar->cstate.window_mask]; + + /* + * 0xE8 = x86's call (function call) + * 0xE9 = x86's jmp (unconditional jump) + */ + if(b == 0xE8 || (extended && b == 0xE9)) { + + uint32_t addr; + uint32_t offset = (i + flt->block_start) % file_size; + + addr = read_filter_data(rar, + (uint32_t)(rar->cstate.solid_offset + + flt->block_start + i) & rar->cstate.window_mask); + + if(addr & 0x80000000) { + if(((addr + offset) & 0x80000000) == 0) { + write_filter_data(rar, (uint32_t)i, + addr + file_size); + } + } else { + if((addr - file_size) & 0x80000000) { + uint32_t naddr = addr - offset; + write_filter_data(rar, (uint32_t)i, + naddr); + } + } + + i += 4; + } + } + + return ARCHIVE_OK; +} + +static int run_arm_filter(struct rar5* rar, struct filter_info* flt) { + ssize_t i = 0; + uint32_t offset; + + circular_memcpy(rar->cstate.filtered_buf, + rar->cstate.window_buf, rar->cstate.window_mask, + rar->cstate.solid_offset + flt->block_start, + rar->cstate.solid_offset + flt->block_start + flt->block_length); + + for(i = 0; i < flt->block_length - 3; i += 4) { + uint8_t* b = &rar->cstate.window_buf[ + (rar->cstate.solid_offset + + flt->block_start + i + 3) & rar->cstate.window_mask]; + + if(*b == 0xEB) { + /* 0xEB = ARM's BL (branch + link) instruction. */ + offset = read_filter_data(rar, + (rar->cstate.solid_offset + flt->block_start + i) & + rar->cstate.window_mask) & 0x00ffffff; + + offset -= (uint32_t) ((i + flt->block_start) / 4); + offset = (offset & 0x00ffffff) | 0xeb000000; + write_filter_data(rar, (uint32_t)i, offset); + } + } + + return ARCHIVE_OK; +} + +static int run_filter(struct archive_read* a, struct filter_info* flt) { + int ret; + struct rar5* rar = get_context(a); + + free(rar->cstate.filtered_buf); + + rar->cstate.filtered_buf = malloc(flt->block_length); + if(!rar->cstate.filtered_buf) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for filter data."); + return ARCHIVE_FATAL; + } + + switch(flt->type) { + case FILTER_DELTA: + ret = run_delta_filter(rar, flt); + break; + + case FILTER_E8: + /* fallthrough */ + case FILTER_E8E9: + ret = run_e8e9_filter(rar, flt, + flt->type == FILTER_E8E9); + break; + + case FILTER_ARM: + ret = run_arm_filter(rar, flt); + break; + + default: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Unsupported filter type: 0x%x", flt->type); + return ARCHIVE_FATAL; + } + + if(ret != ARCHIVE_OK) { + /* Filter has failed. */ + return ret; + } + + if(ARCHIVE_OK != push_data_ready(a, rar, rar->cstate.filtered_buf, + flt->block_length, rar->cstate.last_write_ptr)) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "Stack overflow when submitting unpacked data"); + + return ARCHIVE_FATAL; + } + + rar->cstate.last_write_ptr += flt->block_length; + return ARCHIVE_OK; +} + +/* The `push_data` function submits the selected data range to the user. + * Next call of `use_data` will use the pointer, size and offset arguments + * that are specified here. These arguments are pushed to the FIFO stack here, + * and popped from the stack by the `use_data` function. */ +static void push_data(struct archive_read* a, struct rar5* rar, + const uint8_t* buf, int64_t idx_begin, int64_t idx_end) +{ + const uint64_t wmask = rar->cstate.window_mask; + const ssize_t solid_write_ptr = (rar->cstate.solid_offset + + rar->cstate.last_write_ptr) & wmask; + + idx_begin += rar->cstate.solid_offset; + idx_end += rar->cstate.solid_offset; + + /* Check if our unpacked data is wrapped inside the window circular + * buffer. If it's not wrapped, it can be copied out by using + * a single memcpy, but when it's wrapped, we need to copy the first + * part with one memcpy, and the second part with another memcpy. */ + + if((idx_begin & wmask) > (idx_end & wmask)) { + /* The data is wrapped (begin offset sis bigger than end + * offset). */ + const ssize_t frag1_size = rar->cstate.window_size - + (idx_begin & wmask); + const ssize_t frag2_size = idx_end & wmask; + + /* Copy the first part of the buffer first. */ + push_data_ready(a, rar, buf + solid_write_ptr, frag1_size, + rar->cstate.last_write_ptr); + + /* Copy the second part of the buffer. */ + push_data_ready(a, rar, buf, frag2_size, + rar->cstate.last_write_ptr + frag1_size); + + rar->cstate.last_write_ptr += frag1_size + frag2_size; + } else { + /* Data is not wrapped, so we can just use one call to copy the + * data. */ + push_data_ready(a, rar, + buf + solid_write_ptr, (idx_end - idx_begin) & wmask, + rar->cstate.last_write_ptr); + + rar->cstate.last_write_ptr += idx_end - idx_begin; + } +} + +/* Convenience function that submits the data to the user. It uses the + * unpack window buffer as a source location. */ +static void push_window_data(struct archive_read* a, struct rar5* rar, + int64_t idx_begin, int64_t idx_end) +{ + push_data(a, rar, rar->cstate.window_buf, idx_begin, idx_end); +} + +static int apply_filters(struct archive_read* a) { + struct filter_info* flt; + struct rar5* rar = get_context(a); + int ret; + + rar->cstate.all_filters_applied = 0; + + /* Get the first filter that can be applied to our data. The data + * needs to be fully unpacked before the filter can be run. */ + if(CDE_OK == cdeque_front(&rar->cstate.filters, + cdeque_filter_p(&flt))) { + /* Check if our unpacked data fully covers this filter's + * range. */ + if(rar->cstate.write_ptr > flt->block_start && + rar->cstate.write_ptr >= flt->block_start + + flt->block_length) { + /* Check if we have some data pending to be written + * right before the filter's start offset. */ + if(rar->cstate.last_write_ptr == flt->block_start) { + /* Run the filter specified by descriptor + * `flt`. */ + ret = run_filter(a, flt); + if(ret != ARCHIVE_OK) { + /* Filter failure, return error. */ + return ret; + } + + /* Filter descriptor won't be needed anymore + * after it's used, * so remove it from the + * filter list and free its memory. */ + (void) cdeque_pop_front(&rar->cstate.filters, + cdeque_filter_p(&flt)); + + free(flt); + } else { + /* We can't run filters yet, dump the memory + * right before the filter. */ + push_window_data(a, rar, + rar->cstate.last_write_ptr, + flt->block_start); + } + + /* Return 'filter applied or not needed' state to the + * caller. */ + return ARCHIVE_RETRY; + } + } + + rar->cstate.all_filters_applied = 1; + return ARCHIVE_OK; +} + +static void dist_cache_push(struct rar5* rar, int value) { + int* q = rar->cstate.dist_cache; + + q[3] = q[2]; + q[2] = q[1]; + q[1] = q[0]; + q[0] = value; +} + +static int dist_cache_touch(struct rar5* rar, int idx) { + int* q = rar->cstate.dist_cache; + int i, dist = q[idx]; + + for(i = idx; i > 0; i--) + q[i] = q[i - 1]; + + q[0] = dist; + return dist; +} + +static void free_filters(struct rar5* rar) { + struct cdeque* d = &rar->cstate.filters; + + /* Free any remaining filters. All filters should be naturally + * consumed by the unpacking function, so remaining filters after + * unpacking normally mean that unpacking wasn't successful. + * But still of course we shouldn't leak memory in such case. */ + + /* cdeque_size() is a fast operation, so we can use it as a loop + * expression. */ + while(cdeque_size(d) > 0) { + struct filter_info* f = NULL; + + /* Pop_front will also decrease the collection's size. */ + if (CDE_OK == cdeque_pop_front(d, cdeque_filter_p(&f))) + free(f); + } + + cdeque_clear(d); + + /* Also clear out the variables needed for sanity checking. */ + rar->cstate.last_block_start = 0; + rar->cstate.last_block_length = 0; +} + +static void reset_file_context(struct rar5* rar) { + memset(&rar->file, 0, sizeof(rar->file)); + blake2sp_init(&rar->file.b2state, 32); + + if(rar->main.solid) { + rar->cstate.solid_offset += rar->cstate.write_ptr; + } else { + rar->cstate.solid_offset = 0; + } + + rar->cstate.write_ptr = 0; + rar->cstate.last_write_ptr = 0; + rar->cstate.last_unstore_ptr = 0; + + rar->file.redir_type = REDIR_TYPE_NONE; + rar->file.redir_flags = 0; + + free_filters(rar); +} + +static inline int get_archive_read(struct archive* a, + struct archive_read** ar) +{ + *ar = (struct archive_read*) a; + archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, + "archive_read_support_format_rar5"); + + return ARCHIVE_OK; +} + +static int read_ahead(struct archive_read* a, size_t how_many, + const uint8_t** ptr) +{ + ssize_t avail = -1; + if(!ptr) + return 0; + + *ptr = __archive_read_ahead(a, how_many, &avail); + if(*ptr == NULL) { + return 0; + } + + return 1; +} + +static int consume(struct archive_read* a, int64_t how_many) { + int ret; + + ret = how_many == __archive_read_consume(a, how_many) + ? ARCHIVE_OK + : ARCHIVE_FATAL; + + return ret; +} + +/** + * Read a RAR5 variable sized numeric value. This value will be stored in + * `pvalue`. The `pvalue_len` argument points to a variable that will receive + * the byte count that was consumed in order to decode the `pvalue` value, plus + * one. + * + * pvalue_len is optional and can be NULL. + * + * NOTE: if `pvalue_len` is NOT NULL, the caller needs to manually consume + * the number of bytes that `pvalue_len` value contains. If the `pvalue_len` + * is NULL, this consuming operation is done automatically. + * + * Returns 1 if *pvalue was successfully read. + * Returns 0 if there was an error. In this case, *pvalue contains an + * invalid value. + */ + +static int read_var(struct archive_read* a, uint64_t* pvalue, + uint64_t* pvalue_len) +{ + uint64_t result = 0; + size_t shift, i; + const uint8_t* p; + uint8_t b; + + /* We will read maximum of 8 bytes. We don't have to handle the + * situation to read the RAR5 variable-sized value stored at the end of + * the file, because such situation will never happen. */ + if(!read_ahead(a, 8, &p)) + return 0; + + for(shift = 0, i = 0; i < 8; i++, shift += 7) { + b = p[i]; + + /* Strip the MSB from the input byte and add the resulting + * number to the `result`. */ + result += (b & (uint64_t)0x7F) << shift; + + /* MSB set to 1 means we need to continue decoding process. + * MSB set to 0 means we're done. + * + * This conditional checks for the second case. */ + if((b & 0x80) == 0) { + if(pvalue) { + *pvalue = result; + } + + /* If the caller has passed the `pvalue_len` pointer, + * store the number of consumed bytes in it and do NOT + * consume those bytes, since the caller has all the + * information it needs to perform */ + if(pvalue_len) { + *pvalue_len = 1 + i; + } else { + /* If the caller did not provide the + * `pvalue_len` pointer, it will not have the + * possibility to advance the file pointer, + * because it will not know how many bytes it + * needs to consume. This is why we handle + * such situation here automatically. */ + if(ARCHIVE_OK != consume(a, 1 + i)) { + return 0; + } + } + + /* End of decoding process, return success. */ + return 1; + } + } + + /* The decoded value takes the maximum number of 8 bytes. + * It's a maximum number of bytes, so end decoding process here + * even if the first bit of last byte is 1. */ + if(pvalue) { + *pvalue = result; + } + + if(pvalue_len) { + *pvalue_len = 9; + } else { + if(ARCHIVE_OK != consume(a, 9)) { + return 0; + } + } + + return 1; +} + +static int read_var_sized(struct archive_read* a, size_t* pvalue, + size_t* pvalue_len) +{ + uint64_t v; + uint64_t v_size = 0; + + const int ret = pvalue_len ? read_var(a, &v, &v_size) + : read_var(a, &v, NULL); + + if(ret == 1 && pvalue) { + *pvalue = (size_t) v; + } + + if(pvalue_len) { + /* Possible data truncation should be safe. */ + *pvalue_len = (size_t) v_size; + } + + return ret; +} + +static int read_bits_32(struct rar5* rar, const uint8_t* p, uint32_t* value) { + uint32_t bits = ((uint32_t) p[rar->bits.in_addr]) << 24; + bits |= p[rar->bits.in_addr + 1] << 16; + bits |= p[rar->bits.in_addr + 2] << 8; + bits |= p[rar->bits.in_addr + 3]; + bits <<= rar->bits.bit_addr; + bits |= p[rar->bits.in_addr + 4] >> (8 - rar->bits.bit_addr); + *value = bits; + return ARCHIVE_OK; +} + +static int read_bits_16(struct rar5* rar, const uint8_t* p, uint16_t* value) { + int bits = (int) ((uint32_t) p[rar->bits.in_addr]) << 16; + bits |= (int) p[rar->bits.in_addr + 1] << 8; + bits |= (int) p[rar->bits.in_addr + 2]; + bits >>= (8 - rar->bits.bit_addr); + *value = bits & 0xffff; + return ARCHIVE_OK; +} + +static void skip_bits(struct rar5* rar, int bits) { + const int new_bits = rar->bits.bit_addr + bits; + rar->bits.in_addr += new_bits >> 3; + rar->bits.bit_addr = new_bits & 7; +} + +/* n = up to 16 */ +static int read_consume_bits(struct rar5* rar, const uint8_t* p, int n, + int* value) +{ + uint16_t v; + int ret, num; + + if(n == 0 || n > 16) { + /* This is a programmer error and should never happen + * in runtime. */ + return ARCHIVE_FATAL; + } + + ret = read_bits_16(rar, p, &v); + if(ret != ARCHIVE_OK) + return ret; + + num = (int) v; + num >>= 16 - n; + + skip_bits(rar, n); + + if(value) + *value = num; + + return ARCHIVE_OK; +} + +static int read_u32(struct archive_read* a, uint32_t* pvalue) { + const uint8_t* p; + if(!read_ahead(a, 4, &p)) + return 0; + + *pvalue = archive_le32dec(p); + return ARCHIVE_OK == consume(a, 4) ? 1 : 0; +} + +static int read_u64(struct archive_read* a, uint64_t* pvalue) { + const uint8_t* p; + if(!read_ahead(a, 8, &p)) + return 0; + + *pvalue = archive_le64dec(p); + return ARCHIVE_OK == consume(a, 8) ? 1 : 0; +} + +static int bid_standard(struct archive_read* a) { + const uint8_t* p; + char signature[sizeof(rar5_signature_xor)]; + + rar5_signature(signature); + + if(!read_ahead(a, sizeof(rar5_signature_xor), &p)) + return -1; + + if(!memcmp(signature, p, sizeof(rar5_signature_xor))) + return 30; + + return -1; +} + +static int rar5_bid(struct archive_read* a, int best_bid) { + int my_bid; + + if(best_bid > 30) + return -1; + + my_bid = bid_standard(a); + if(my_bid > -1) { + return my_bid; + } + + return -1; +} + +static int rar5_options(struct archive_read *a, const char *key, + const char *val) { + (void) a; + (void) key; + (void) val; + + /* No options supported in this version. Return the ARCHIVE_WARN code + * to signal the options supervisor that the unpacker didn't handle + * setting this option. */ + + return ARCHIVE_WARN; +} + +static void init_header(struct archive_read* a) { + a->archive.archive_format = ARCHIVE_FORMAT_RAR_V5; + a->archive.archive_format_name = "RAR5"; +} + +static void init_window_mask(struct rar5* rar) { + if (rar->cstate.window_size) + rar->cstate.window_mask = rar->cstate.window_size - 1; + else + rar->cstate.window_mask = 0; +} + +enum HEADER_FLAGS { + HFL_EXTRA_DATA = 0x0001, + HFL_DATA = 0x0002, + HFL_SKIP_IF_UNKNOWN = 0x0004, + HFL_SPLIT_BEFORE = 0x0008, + HFL_SPLIT_AFTER = 0x0010, + HFL_CHILD = 0x0020, + HFL_INHERITED = 0x0040 +}; + +static int process_main_locator_extra_block(struct archive_read* a, + struct rar5* rar) +{ + uint64_t locator_flags; + + enum LOCATOR_FLAGS { + QLIST = 0x01, RECOVERY = 0x02, + }; + + if(!read_var(a, &locator_flags, NULL)) { + return ARCHIVE_EOF; + } + + if(locator_flags & QLIST) { + if(!read_var(a, &rar->qlist_offset, NULL)) { + return ARCHIVE_EOF; + } + + /* qlist is not used */ + } + + if(locator_flags & RECOVERY) { + if(!read_var(a, &rar->rr_offset, NULL)) { + return ARCHIVE_EOF; + } + + /* rr is not used */ + } + + return ARCHIVE_OK; +} + +static int parse_file_extra_hash(struct archive_read* a, struct rar5* rar, + ssize_t* extra_data_size) +{ + size_t hash_type = 0; + size_t value_len; + + enum HASH_TYPE { + BLAKE2sp = 0x00 + }; + + if(!read_var_sized(a, &hash_type, &value_len)) + return ARCHIVE_EOF; + + *extra_data_size -= value_len; + if(ARCHIVE_OK != consume(a, value_len)) { + return ARCHIVE_EOF; + } + + /* The file uses BLAKE2sp checksum algorithm instead of plain old + * CRC32. */ + if(hash_type == BLAKE2sp) { + const uint8_t* p; + const int hash_size = sizeof(rar->file.blake2sp); + + if(!read_ahead(a, hash_size, &p)) + return ARCHIVE_EOF; + + rar->file.has_blake2 = 1; + memcpy(&rar->file.blake2sp, p, hash_size); + + if(ARCHIVE_OK != consume(a, hash_size)) { + return ARCHIVE_EOF; + } + + *extra_data_size -= hash_size; + } else { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Unsupported hash type (0x%x)", (int) hash_type); + return ARCHIVE_FATAL; + } + + return ARCHIVE_OK; +} + +static uint64_t time_win_to_unix(uint64_t win_time) { + const size_t ns_in_sec = 10000000; + const uint64_t sec_to_unix = 11644473600LL; + return win_time / ns_in_sec - sec_to_unix; +} + +static int parse_htime_item(struct archive_read* a, char unix_time, + uint64_t* where, ssize_t* extra_data_size) +{ + if(unix_time) { + uint32_t time_val; + if(!read_u32(a, &time_val)) + return ARCHIVE_EOF; + + *extra_data_size -= 4; + *where = (uint64_t) time_val; + } else { + uint64_t windows_time; + if(!read_u64(a, &windows_time)) + return ARCHIVE_EOF; + + *where = time_win_to_unix(windows_time); + *extra_data_size -= 8; + } + + return ARCHIVE_OK; +} + +static int parse_file_extra_version(struct archive_read* a, + struct archive_entry* e, ssize_t* extra_data_size) +{ + size_t flags = 0; + size_t version = 0; + size_t value_len = 0; + struct archive_string version_string; + struct archive_string name_utf8_string; + const char* cur_filename; + + /* Flags are ignored. */ + if(!read_var_sized(a, &flags, &value_len)) + return ARCHIVE_EOF; + + *extra_data_size -= value_len; + if(ARCHIVE_OK != consume(a, value_len)) + return ARCHIVE_EOF; + + if(!read_var_sized(a, &version, &value_len)) + return ARCHIVE_EOF; + + *extra_data_size -= value_len; + if(ARCHIVE_OK != consume(a, value_len)) + return ARCHIVE_EOF; + + /* extra_data_size should be zero here. */ + + cur_filename = archive_entry_pathname_utf8(e); + if(cur_filename == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "Version entry without file name"); + return ARCHIVE_FATAL; + } + + archive_string_init(&version_string); + archive_string_init(&name_utf8_string); + + /* Prepare a ;123 suffix for the filename, where '123' is the version + * value of this file. */ + archive_string_sprintf(&version_string, ";%zu", version); + + /* Build the new filename. */ + archive_strcat(&name_utf8_string, cur_filename); + archive_strcat(&name_utf8_string, version_string.s); + + /* Apply the new filename into this file's context. */ + archive_entry_update_pathname_utf8(e, name_utf8_string.s); + + /* Free buffers. */ + archive_string_free(&version_string); + archive_string_free(&name_utf8_string); + return ARCHIVE_OK; +} + +static int parse_file_extra_htime(struct archive_read* a, + struct archive_entry* e, struct rar5* rar, ssize_t* extra_data_size) +{ + char unix_time = 0; + size_t flags = 0; + size_t value_len; + + enum HTIME_FLAGS { + IS_UNIX = 0x01, + HAS_MTIME = 0x02, + HAS_CTIME = 0x04, + HAS_ATIME = 0x08, + HAS_UNIX_NS = 0x10, + }; + + if(!read_var_sized(a, &flags, &value_len)) + return ARCHIVE_EOF; + + *extra_data_size -= value_len; + if(ARCHIVE_OK != consume(a, value_len)) { + return ARCHIVE_EOF; + } + + unix_time = flags & IS_UNIX; + + if(flags & HAS_MTIME) { + parse_htime_item(a, unix_time, &rar->file.e_mtime, + extra_data_size); + archive_entry_set_mtime(e, rar->file.e_mtime, 0); + } + + if(flags & HAS_CTIME) { + parse_htime_item(a, unix_time, &rar->file.e_ctime, + extra_data_size); + archive_entry_set_ctime(e, rar->file.e_ctime, 0); + } + + if(flags & HAS_ATIME) { + parse_htime_item(a, unix_time, &rar->file.e_atime, + extra_data_size); + archive_entry_set_atime(e, rar->file.e_atime, 0); + } + + if(flags & HAS_UNIX_NS) { + if(!read_u32(a, &rar->file.e_unix_ns)) + return ARCHIVE_EOF; + + *extra_data_size -= 4; + } + + return ARCHIVE_OK; +} + +static int parse_file_extra_redir(struct archive_read* a, + struct archive_entry* e, struct rar5* rar, ssize_t* extra_data_size) +{ + uint64_t value_size = 0; + size_t target_size = 0; + char target_utf8_buf[MAX_NAME_IN_BYTES]; + const uint8_t* p; + + if(!read_var(a, &rar->file.redir_type, &value_size)) + return ARCHIVE_EOF; + if(ARCHIVE_OK != consume(a, (int64_t)value_size)) + return ARCHIVE_EOF; + *extra_data_size -= value_size; + + if(!read_var(a, &rar->file.redir_flags, &value_size)) + return ARCHIVE_EOF; + if(ARCHIVE_OK != consume(a, (int64_t)value_size)) + return ARCHIVE_EOF; + *extra_data_size -= value_size; + + if(!read_var_sized(a, &target_size, NULL)) + return ARCHIVE_EOF; + *extra_data_size -= target_size + 1; + + if(!read_ahead(a, target_size, &p)) + return ARCHIVE_EOF; + + if(target_size > (MAX_NAME_IN_CHARS - 1)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Link target is too long"); + return ARCHIVE_FATAL; + } + + if(target_size == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "No link target specified"); + return ARCHIVE_FATAL; + } + + memcpy(target_utf8_buf, p, target_size); + target_utf8_buf[target_size] = 0; + + if(ARCHIVE_OK != consume(a, (int64_t)target_size)) + return ARCHIVE_EOF; + + switch(rar->file.redir_type) { + case REDIR_TYPE_UNIXSYMLINK: + case REDIR_TYPE_WINSYMLINK: + archive_entry_set_filetype(e, AE_IFLNK); + archive_entry_update_symlink_utf8(e, target_utf8_buf); + if (rar->file.redir_flags & REDIR_SYMLINK_IS_DIR) { + archive_entry_set_symlink_type(e, + AE_SYMLINK_TYPE_DIRECTORY); + } else { + archive_entry_set_symlink_type(e, + AE_SYMLINK_TYPE_FILE); + } + break; + + case REDIR_TYPE_HARDLINK: + archive_entry_set_filetype(e, AE_IFREG); + archive_entry_update_hardlink_utf8(e, target_utf8_buf); + break; + + default: + /* Unknown redir type, skip it. */ + break; + } + return ARCHIVE_OK; +} + +static int parse_file_extra_owner(struct archive_read* a, + struct archive_entry* e, ssize_t* extra_data_size) +{ + uint64_t flags = 0; + uint64_t value_size = 0; + uint64_t id = 0; + size_t name_len = 0; + size_t name_size = 0; + char namebuf[OWNER_MAXNAMELEN]; + const uint8_t* p; + + if(!read_var(a, &flags, &value_size)) + return ARCHIVE_EOF; + if(ARCHIVE_OK != consume(a, (int64_t)value_size)) + return ARCHIVE_EOF; + *extra_data_size -= value_size; + + if ((flags & OWNER_USER_NAME) != 0) { + if(!read_var_sized(a, &name_size, NULL)) + return ARCHIVE_EOF; + *extra_data_size -= name_size + 1; + + if(!read_ahead(a, name_size, &p)) + return ARCHIVE_EOF; + + if (name_size >= OWNER_MAXNAMELEN) { + name_len = OWNER_MAXNAMELEN - 1; + } else { + name_len = name_size; + } + + memcpy(namebuf, p, name_len); + namebuf[name_len] = 0; + if(ARCHIVE_OK != consume(a, (int64_t)name_size)) + return ARCHIVE_EOF; + + archive_entry_set_uname(e, namebuf); + } + if ((flags & OWNER_GROUP_NAME) != 0) { + if(!read_var_sized(a, &name_size, NULL)) + return ARCHIVE_EOF; + *extra_data_size -= name_size + 1; + + if(!read_ahead(a, name_size, &p)) + return ARCHIVE_EOF; + + if (name_size >= OWNER_MAXNAMELEN) { + name_len = OWNER_MAXNAMELEN - 1; + } else { + name_len = name_size; + } + + memcpy(namebuf, p, name_len); + namebuf[name_len] = 0; + if(ARCHIVE_OK != consume(a, (int64_t)name_size)) + return ARCHIVE_EOF; + + archive_entry_set_gname(e, namebuf); + } + if ((flags & OWNER_USER_UID) != 0) { + if(!read_var(a, &id, &value_size)) + return ARCHIVE_EOF; + if(ARCHIVE_OK != consume(a, (int64_t)value_size)) + return ARCHIVE_EOF; + *extra_data_size -= value_size; + + archive_entry_set_uid(e, (la_int64_t)id); + } + if ((flags & OWNER_GROUP_GID) != 0) { + if(!read_var(a, &id, &value_size)) + return ARCHIVE_EOF; + if(ARCHIVE_OK != consume(a, (int64_t)value_size)) + return ARCHIVE_EOF; + *extra_data_size -= value_size; + + archive_entry_set_gid(e, (la_int64_t)id); + } + return ARCHIVE_OK; +} + +static int process_head_file_extra(struct archive_read* a, + struct archive_entry* e, struct rar5* rar, ssize_t extra_data_size) +{ + size_t extra_field_size; + size_t extra_field_id = 0; + int ret = ARCHIVE_FATAL; + size_t var_size; + + while(extra_data_size > 0) { + if(!read_var_sized(a, &extra_field_size, &var_size)) + return ARCHIVE_EOF; + + extra_data_size -= var_size; + if(ARCHIVE_OK != consume(a, var_size)) { + return ARCHIVE_EOF; + } + + if(!read_var_sized(a, &extra_field_id, &var_size)) + return ARCHIVE_EOF; + + extra_data_size -= var_size; + if(ARCHIVE_OK != consume(a, var_size)) { + return ARCHIVE_EOF; + } + + switch(extra_field_id) { + case EX_HASH: + ret = parse_file_extra_hash(a, rar, + &extra_data_size); + break; + case EX_HTIME: + ret = parse_file_extra_htime(a, e, rar, + &extra_data_size); + break; + case EX_REDIR: + ret = parse_file_extra_redir(a, e, rar, + &extra_data_size); + break; + case EX_UOWNER: + ret = parse_file_extra_owner(a, e, + &extra_data_size); + break; + case EX_VERSION: + ret = parse_file_extra_version(a, e, + &extra_data_size); + break; + case EX_CRYPT: + /* fallthrough */ + case EX_SUBDATA: + /* fallthrough */ + default: + /* Skip unsupported entry. */ + return consume(a, extra_data_size); + } + } + + if(ret != ARCHIVE_OK) { + /* Attribute not implemented. */ + return ret; + } + + return ARCHIVE_OK; +} + +static int process_head_file(struct archive_read* a, struct rar5* rar, + struct archive_entry* entry, size_t block_flags) +{ + ssize_t extra_data_size = 0; + size_t data_size = 0; + size_t file_flags = 0; + size_t file_attr = 0; + size_t compression_info = 0; + size_t host_os = 0; + size_t name_size = 0; + uint64_t unpacked_size, window_size; + uint32_t mtime = 0, crc = 0; + int c_method = 0, c_version = 0; + char name_utf8_buf[MAX_NAME_IN_BYTES]; + const uint8_t* p; + + enum FILE_FLAGS { + DIRECTORY = 0x0001, UTIME = 0x0002, CRC32 = 0x0004, + UNKNOWN_UNPACKED_SIZE = 0x0008, + }; + + enum FILE_ATTRS { + ATTR_READONLY = 0x1, ATTR_HIDDEN = 0x2, ATTR_SYSTEM = 0x4, + ATTR_DIRECTORY = 0x10, + }; + + enum COMP_INFO_FLAGS { + SOLID = 0x0040, + }; + + enum HOST_OS { + HOST_WINDOWS = 0, + HOST_UNIX = 1, + }; + + archive_entry_clear(entry); + + /* Do not reset file context if we're switching archives. */ + if(!rar->cstate.switch_multivolume) { + reset_file_context(rar); + } + + if(block_flags & HFL_EXTRA_DATA) { + size_t edata_size = 0; + if(!read_var_sized(a, &edata_size, NULL)) + return ARCHIVE_EOF; + + /* Intentional type cast from unsigned to signed. */ + extra_data_size = (ssize_t) edata_size; + } + + if(block_flags & HFL_DATA) { + if(!read_var_sized(a, &data_size, NULL)) + return ARCHIVE_EOF; + + rar->file.bytes_remaining = data_size; + } else { + rar->file.bytes_remaining = 0; + + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "no data found in file/service block"); + return ARCHIVE_FATAL; + } + + if(!read_var_sized(a, &file_flags, NULL)) + return ARCHIVE_EOF; + + if(!read_var(a, &unpacked_size, NULL)) + return ARCHIVE_EOF; + + if(file_flags & UNKNOWN_UNPACKED_SIZE) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "Files with unknown unpacked size are not supported"); + return ARCHIVE_FATAL; + } + + rar->file.dir = (uint8_t) ((file_flags & DIRECTORY) > 0); + + if(!read_var_sized(a, &file_attr, NULL)) + return ARCHIVE_EOF; + + if(file_flags & UTIME) { + if(!read_u32(a, &mtime)) + return ARCHIVE_EOF; + } + + if(file_flags & CRC32) { + if(!read_u32(a, &crc)) + return ARCHIVE_EOF; + } + + if(!read_var_sized(a, &compression_info, NULL)) + return ARCHIVE_EOF; + + c_method = (int) (compression_info >> 7) & 0x7; + c_version = (int) (compression_info & 0x3f); + + /* RAR5 seems to limit the dictionary size to 64MB. */ + window_size = (rar->file.dir > 0) ? + 0 : + g_unpack_window_size << ((compression_info >> 10) & 15); + rar->cstate.method = c_method; + rar->cstate.version = c_version + 50; + rar->file.solid = (compression_info & SOLID) > 0; + + /* Archives which declare solid files without initializing the window + * buffer first are invalid. */ + + if(rar->file.solid > 0 && rar->cstate.window_buf == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Declared solid file, but no window buffer " + "initialized yet."); + return ARCHIVE_FATAL; + } + + /* Check if window_size is a sane value. Also, if the file is not + * declared as a directory, disallow window_size == 0. */ + if(window_size > (64 * 1024 * 1024) || + (rar->file.dir == 0 && window_size == 0)) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Declared dictionary size is not supported."); + return ARCHIVE_FATAL; + } + + if(rar->file.solid > 0) { + /* Re-check if current window size is the same as previous + * window size (for solid files only). */ + if(rar->file.solid_window_size > 0 && + rar->file.solid_window_size != (ssize_t) window_size) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Window size for this solid file doesn't match " + "the window size used in previous solid file. "); + return ARCHIVE_FATAL; + } + } + + /* If we're currently switching volumes, ignore the new definition of + * window_size. */ + if(rar->cstate.switch_multivolume == 0) { + /* Values up to 64M should fit into ssize_t on every + * architecture. */ + rar->cstate.window_size = (ssize_t) window_size; + } + + if(rar->file.solid > 0 && rar->file.solid_window_size == 0) { + /* Solid files have to have the same window_size across + whole archive. Remember the window_size parameter + for first solid file found. */ + rar->file.solid_window_size = rar->cstate.window_size; + } + + init_window_mask(rar); + + rar->file.service = 0; + + if(!read_var_sized(a, &host_os, NULL)) + return ARCHIVE_EOF; + + if(host_os == HOST_WINDOWS) { + /* Host OS is Windows */ + + __LA_MODE_T mode; + + if(file_attr & ATTR_DIRECTORY) { + if (file_attr & ATTR_READONLY) { + mode = 0555 | AE_IFDIR; + } else { + mode = 0755 | AE_IFDIR; + } + } else { + if (file_attr & ATTR_READONLY) { + mode = 0444 | AE_IFREG; + } else { + mode = 0644 | AE_IFREG; + } + } + + archive_entry_set_mode(entry, mode); + + if (file_attr & (ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM)) { + char *fflags_text, *ptr; + /* allocate for "rdonly,hidden,system," */ + fflags_text = malloc(22 * sizeof(char)); + if (fflags_text != NULL) { + ptr = fflags_text; + if (file_attr & ATTR_READONLY) { + strcpy(ptr, "rdonly,"); + ptr = ptr + 7; + } + if (file_attr & ATTR_HIDDEN) { + strcpy(ptr, "hidden,"); + ptr = ptr + 7; + } + if (file_attr & ATTR_SYSTEM) { + strcpy(ptr, "system,"); + ptr = ptr + 7; + } + if (ptr > fflags_text) { + /* Delete trailing comma */ + *(ptr - 1) = '\0'; + archive_entry_copy_fflags_text(entry, + fflags_text); + } + free(fflags_text); + } + } + } else if(host_os == HOST_UNIX) { + /* Host OS is Unix */ + archive_entry_set_mode(entry, (__LA_MODE_T) file_attr); + } else { + /* Unknown host OS */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Unsupported Host OS: 0x%x", (int) host_os); + + return ARCHIVE_FATAL; + } + + if(!read_var_sized(a, &name_size, NULL)) + return ARCHIVE_EOF; + + if(!read_ahead(a, name_size, &p)) + return ARCHIVE_EOF; + + if(name_size > (MAX_NAME_IN_CHARS - 1)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Filename is too long"); + + return ARCHIVE_FATAL; + } + + if(name_size == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "No filename specified"); + + return ARCHIVE_FATAL; + } + + memcpy(name_utf8_buf, p, name_size); + name_utf8_buf[name_size] = 0; + if(ARCHIVE_OK != consume(a, name_size)) { + return ARCHIVE_EOF; + } + + archive_entry_update_pathname_utf8(entry, name_utf8_buf); + + if(extra_data_size > 0) { + int ret = process_head_file_extra(a, entry, rar, + extra_data_size); + + /* + * TODO: rewrite or remove useless sanity check + * as extra_data_size is not passed as a pointer + * + if(extra_data_size < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "File extra data size is not zero"); + return ARCHIVE_FATAL; + } + */ + + if(ret != ARCHIVE_OK) + return ret; + } + + if((file_flags & UNKNOWN_UNPACKED_SIZE) == 0) { + rar->file.unpacked_size = (ssize_t) unpacked_size; + if(rar->file.redir_type == REDIR_TYPE_NONE) + archive_entry_set_size(entry, unpacked_size); + } + + if(file_flags & UTIME) { + archive_entry_set_mtime(entry, (time_t) mtime, 0); + } + + if(file_flags & CRC32) { + rar->file.stored_crc32 = crc; + } + + if(!rar->cstate.switch_multivolume) { + /* Do not reinitialize unpacking state if we're switching + * archives. */ + rar->cstate.block_parsing_finished = 1; + rar->cstate.all_filters_applied = 1; + rar->cstate.initialized = 0; + } + + if(rar->generic.split_before > 0) { + /* If now we're standing on a header that has a 'split before' + * mark, it means we're standing on a 'continuation' file + * header. Signal the caller that if it wants to move to + * another file, it must call rar5_read_header() function + * again. */ + + return ARCHIVE_RETRY; + } else { + return ARCHIVE_OK; + } +} + +static int process_head_service(struct archive_read* a, struct rar5* rar, + struct archive_entry* entry, size_t block_flags) +{ + /* Process this SERVICE block the same way as FILE blocks. */ + int ret = process_head_file(a, rar, entry, block_flags); + if(ret != ARCHIVE_OK) + return ret; + + rar->file.service = 1; + + /* But skip the data part automatically. It's no use for the user + * anyway. It contains only service data, not even needed to + * properly unpack the file. */ + ret = rar5_read_data_skip(a); + if(ret != ARCHIVE_OK) + return ret; + + /* After skipping, try parsing another block automatically. */ + return ARCHIVE_RETRY; +} + +static int process_head_main(struct archive_read* a, struct rar5* rar, + struct archive_entry* entry, size_t block_flags) +{ + int ret; + size_t extra_data_size = 0; + size_t extra_field_size = 0; + size_t extra_field_id = 0; + size_t archive_flags = 0; + + enum MAIN_FLAGS { + VOLUME = 0x0001, /* multi-volume archive */ + VOLUME_NUMBER = 0x0002, /* volume number, first vol doesn't + * have it */ + SOLID = 0x0004, /* solid archive */ + PROTECT = 0x0008, /* contains Recovery info */ + LOCK = 0x0010, /* readonly flag, not used */ + }; + + enum MAIN_EXTRA { + // Just one attribute here. + LOCATOR = 0x01, + }; + + (void) entry; + + if(block_flags & HFL_EXTRA_DATA) { + if(!read_var_sized(a, &extra_data_size, NULL)) + return ARCHIVE_EOF; + } else { + extra_data_size = 0; + } + + if(!read_var_sized(a, &archive_flags, NULL)) { + return ARCHIVE_EOF; + } + + rar->main.volume = (archive_flags & VOLUME) > 0; + rar->main.solid = (archive_flags & SOLID) > 0; + + if(archive_flags & VOLUME_NUMBER) { + size_t v = 0; + if(!read_var_sized(a, &v, NULL)) { + return ARCHIVE_EOF; + } + + if (v > UINT_MAX) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid volume number"); + return ARCHIVE_FATAL; + } + + rar->main.vol_no = (unsigned int) v; + } else { + rar->main.vol_no = 0; + } + + if(rar->vol.expected_vol_no > 0 && + rar->main.vol_no != rar->vol.expected_vol_no) + { + /* Returning EOF instead of FATAL because of strange + * libarchive behavior. When opening multiple files via + * archive_read_open_filenames(), after reading up the whole + * last file, the __archive_read_ahead function wraps up to + * the first archive instead of returning EOF. */ + return ARCHIVE_EOF; + } + + if(extra_data_size == 0) { + /* Early return. */ + return ARCHIVE_OK; + } + + if(!read_var_sized(a, &extra_field_size, NULL)) { + return ARCHIVE_EOF; + } + + if(!read_var_sized(a, &extra_field_id, NULL)) { + return ARCHIVE_EOF; + } + + if(extra_field_size == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid extra field size"); + return ARCHIVE_FATAL; + } + + switch(extra_field_id) { + case LOCATOR: + ret = process_main_locator_extra_block(a, rar); + if(ret != ARCHIVE_OK) { + /* Error while parsing main locator extra + * block. */ + return ret; + } + + break; + default: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Unsupported extra type (0x%x)", + (int) extra_field_id); + return ARCHIVE_FATAL; + } + + return ARCHIVE_OK; +} + +static int skip_unprocessed_bytes(struct archive_read* a) { + struct rar5* rar = get_context(a); + int ret; + + if(rar->file.bytes_remaining) { + /* Use different skipping method in block merging mode than in + * normal mode. If merge mode is active, rar5_read_data_skip + * can't be used, because it could allow recursive use of + * merge_block() * function, and this function doesn't support + * recursive use. */ + if(rar->merge_mode) { + /* Discard whole merged block. This is valid in solid + * mode as well, because the code will discard blocks + * only if those blocks are safe to discard (i.e. + * they're not FILE blocks). */ + ret = consume(a, rar->file.bytes_remaining); + if(ret != ARCHIVE_OK) { + return ret; + } + rar->file.bytes_remaining = 0; + } else { + /* If we're not in merge mode, use safe skipping code. + * This will ensure we'll handle solid archives + * properly. */ + ret = rar5_read_data_skip(a); + if(ret != ARCHIVE_OK) { + return ret; + } + } + } + + return ARCHIVE_OK; +} + +static int scan_for_signature(struct archive_read* a); + +/* Base block processing function. A 'base block' is a RARv5 header block + * that tells the reader what kind of data is stored inside the block. + * + * From the birds-eye view a RAR file looks file this: + * + * ... + * + * There are a few types of base blocks. Those types are specified inside + * the 'switch' statement in this function. For example purposes, I'll write + * how a standard RARv5 file could look like here: + * + *
    + * + * The structure above could describe an archive file with 3 files in it, + * one service "QuickOpen" block (that is ignored by this parser), and an + * end of file base block marker. + * + * If the file is stored in multiple archive files ("multiarchive"), it might + * look like this: + * + * .part01.rar:
    + * .part02.rar:
    + * .part03.rar:
    + * + * This example could describe 3 RAR files that contain ONE archived file. + * Or it could describe 3 RAR files that contain 3 different files. Or 3 + * RAR files than contain 2 files. It all depends what metadata is stored in + * the headers of blocks. + * + * Each block contains info about its size, the name of the file it's + * storing inside, and whether this FILE block is a continuation block of + * previous archive ('split before'), and is this FILE block should be + * continued in another archive ('split after'). By parsing the 'split before' + * and 'split after' flags, we're able to tell if multiple base blocks + * are describing one file, or multiple files (with the same filename, for + * example). + * + * One thing to note is that if we're parsing the first block, and + * we see 'split after' flag, then we need to jump over to another + * block to be able to decompress rest of the data. To do this, we need + * to skip the block, then switch to another file, then skip the + * block,
    block, and then we're standing on the proper + * block. + */ + +static int process_base_block(struct archive_read* a, + struct archive_entry* entry) +{ + const size_t SMALLEST_RAR5_BLOCK_SIZE = 3; + + struct rar5* rar = get_context(a); + uint32_t hdr_crc, computed_crc; + size_t raw_hdr_size = 0, hdr_size_len, hdr_size; + size_t header_id = 0; + size_t header_flags = 0; + const uint8_t* p; + int ret; + + enum HEADER_TYPE { + HEAD_MARK = 0x00, HEAD_MAIN = 0x01, HEAD_FILE = 0x02, + HEAD_SERVICE = 0x03, HEAD_CRYPT = 0x04, HEAD_ENDARC = 0x05, + HEAD_UNKNOWN = 0xff, + }; + + /* Skip any unprocessed data for this file. */ + ret = skip_unprocessed_bytes(a); + if(ret != ARCHIVE_OK) + return ret; + + /* Read the expected CRC32 checksum. */ + if(!read_u32(a, &hdr_crc)) { + return ARCHIVE_EOF; + } + + /* Read header size. */ + if(!read_var_sized(a, &raw_hdr_size, &hdr_size_len)) { + return ARCHIVE_EOF; + } + + hdr_size = raw_hdr_size + hdr_size_len; + + /* Sanity check, maximum header size for RAR5 is 2MB. */ + if(hdr_size > (2 * 1024 * 1024)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Base block header is too large"); + + return ARCHIVE_FATAL; + } + + /* Additional sanity checks to weed out invalid files. */ + if(raw_hdr_size == 0 || hdr_size_len == 0 || + hdr_size < SMALLEST_RAR5_BLOCK_SIZE) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Too small block encountered (%zu bytes)", + raw_hdr_size); + + return ARCHIVE_FATAL; + } + + /* Read the whole header data into memory, maximum memory use here is + * 2MB. */ + if(!read_ahead(a, hdr_size, &p)) { + return ARCHIVE_EOF; + } + + /* Verify the CRC32 of the header data. */ + computed_crc = (uint32_t) crc32(0, p, (int) hdr_size); + if(computed_crc != hdr_crc) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Header CRC error"); + + return ARCHIVE_FATAL; + } + + /* If the checksum is OK, we proceed with parsing. */ + if(ARCHIVE_OK != consume(a, hdr_size_len)) { + return ARCHIVE_EOF; + } + + if(!read_var_sized(a, &header_id, NULL)) + return ARCHIVE_EOF; + + if(!read_var_sized(a, &header_flags, NULL)) + return ARCHIVE_EOF; + + rar->generic.split_after = (header_flags & HFL_SPLIT_AFTER) > 0; + rar->generic.split_before = (header_flags & HFL_SPLIT_BEFORE) > 0; + rar->generic.size = (int)hdr_size; + rar->generic.last_header_id = (int)header_id; + rar->main.endarc = 0; + + /* Those are possible header ids in RARv5. */ + switch(header_id) { + case HEAD_MAIN: + ret = process_head_main(a, rar, entry, header_flags); + + /* Main header doesn't have any files in it, so it's + * pointless to return to the caller. Retry to next + * header, which should be HEAD_FILE/HEAD_SERVICE. */ + if(ret == ARCHIVE_OK) + return ARCHIVE_RETRY; + + return ret; + case HEAD_SERVICE: + ret = process_head_service(a, rar, entry, header_flags); + return ret; + case HEAD_FILE: + ret = process_head_file(a, rar, entry, header_flags); + return ret; + case HEAD_CRYPT: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Encryption is not supported"); + return ARCHIVE_FATAL; + case HEAD_ENDARC: + rar->main.endarc = 1; + + /* After encountering an end of file marker, we need + * to take into consideration if this archive is + * continued in another file (i.e. is it part01.rar: + * is there a part02.rar?) */ + if(rar->main.volume) { + /* In case there is part02.rar, position the + * read pointer in a proper place, so we can + * resume parsing. */ + ret = scan_for_signature(a); + if(ret == ARCHIVE_FATAL) { + return ARCHIVE_EOF; + } else { + if(rar->vol.expected_vol_no == + UINT_MAX) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Header error"); + return ARCHIVE_FATAL; + } + + rar->vol.expected_vol_no = + rar->main.vol_no + 1; + return ARCHIVE_OK; + } + } else { + return ARCHIVE_EOF; + } + case HEAD_MARK: + return ARCHIVE_EOF; + default: + if((header_flags & HFL_SKIP_IF_UNKNOWN) == 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Header type error"); + return ARCHIVE_FATAL; + } else { + /* If the block is marked as 'skip if unknown', + * do as the flag says: skip the block + * instead on failing on it. */ + return ARCHIVE_RETRY; + } + } + +#if !defined WIN32 + // Not reached. + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "Internal unpacker error"); + return ARCHIVE_FATAL; +#endif +} + +static int skip_base_block(struct archive_read* a) { + int ret; + struct rar5* rar = get_context(a); + + /* Create a new local archive_entry structure that will be operated on + * by header reader; operations on this archive_entry will be discarded. + */ + struct archive_entry* entry = archive_entry_new(); + ret = process_base_block(a, entry); + + /* Discard operations on this archive_entry structure. */ + archive_entry_free(entry); + if(ret == ARCHIVE_FATAL) + return ret; + + if(rar->generic.last_header_id == 2 && rar->generic.split_before > 0) + return ARCHIVE_OK; + + if(ret == ARCHIVE_OK) + return ARCHIVE_RETRY; + else + return ret; +} + +static int rar5_read_header(struct archive_read *a, + struct archive_entry *entry) +{ + struct rar5* rar = get_context(a); + int ret; + + if(rar->header_initialized == 0) { + init_header(a); + rar->header_initialized = 1; + } + + if(rar->skipped_magic == 0) { + if(ARCHIVE_OK != consume(a, sizeof(rar5_signature_xor))) { + return ARCHIVE_EOF; + } + + rar->skipped_magic = 1; + } + + do { + ret = process_base_block(a, entry); + } while(ret == ARCHIVE_RETRY || + (rar->main.endarc > 0 && ret == ARCHIVE_OK)); + + return ret; +} + +static void init_unpack(struct rar5* rar) { + rar->file.calculated_crc32 = 0; + init_window_mask(rar); + + free(rar->cstate.window_buf); + free(rar->cstate.filtered_buf); + + if(rar->cstate.window_size > 0) { + rar->cstate.window_buf = calloc(1, rar->cstate.window_size); + rar->cstate.filtered_buf = calloc(1, rar->cstate.window_size); + } else { + rar->cstate.window_buf = NULL; + rar->cstate.filtered_buf = NULL; + } + + rar->cstate.write_ptr = 0; + rar->cstate.last_write_ptr = 0; + + memset(&rar->cstate.bd, 0, sizeof(rar->cstate.bd)); + memset(&rar->cstate.ld, 0, sizeof(rar->cstate.ld)); + memset(&rar->cstate.dd, 0, sizeof(rar->cstate.dd)); + memset(&rar->cstate.ldd, 0, sizeof(rar->cstate.ldd)); + memset(&rar->cstate.rd, 0, sizeof(rar->cstate.rd)); +} + +static void update_crc(struct rar5* rar, const uint8_t* p, size_t to_read) { + int verify_crc; + + if(rar->skip_mode) { +#if defined CHECK_CRC_ON_SOLID_SKIP + verify_crc = 1; +#else + verify_crc = 0; +#endif + } else + verify_crc = 1; + + if(verify_crc) { + /* Don't update CRC32 if the file doesn't have the + * `stored_crc32` info filled in. */ + if(rar->file.stored_crc32 > 0) { + rar->file.calculated_crc32 = + crc32(rar->file.calculated_crc32, p, to_read); + } + + /* Check if the file uses an optional BLAKE2sp checksum + * algorithm. */ + if(rar->file.has_blake2 > 0) { + /* Return value of the `update` function is always 0, + * so we can explicitly ignore it here. */ + (void) blake2sp_update(&rar->file.b2state, p, to_read); + } + } +} + +static int create_decode_tables(uint8_t* bit_length, + struct decode_table* table, int size) +{ + int code, upper_limit = 0, i, lc[16]; + uint32_t decode_pos_clone[rar5_countof(table->decode_pos)]; + ssize_t cur_len, quick_data_size; + + memset(&lc, 0, sizeof(lc)); + memset(table->decode_num, 0, sizeof(table->decode_num)); + table->size = size; + table->quick_bits = size == HUFF_NC ? 10 : 7; + + for(i = 0; i < size; i++) { + lc[bit_length[i] & 15]++; + } + + lc[0] = 0; + table->decode_pos[0] = 0; + table->decode_len[0] = 0; + + for(i = 1; i < 16; i++) { + upper_limit += lc[i]; + + table->decode_len[i] = upper_limit << (16 - i); + table->decode_pos[i] = table->decode_pos[i - 1] + lc[i - 1]; + + upper_limit <<= 1; + } + + memcpy(decode_pos_clone, table->decode_pos, sizeof(decode_pos_clone)); + + for(i = 0; i < size; i++) { + uint8_t clen = bit_length[i] & 15; + if(clen > 0) { + int last_pos = decode_pos_clone[clen]; + table->decode_num[last_pos] = i; + decode_pos_clone[clen]++; + } + } + + quick_data_size = (int64_t)1 << table->quick_bits; + cur_len = 1; + for(code = 0; code < quick_data_size; code++) { + int bit_field = code << (16 - table->quick_bits); + int dist, pos; + + while(cur_len < rar5_countof(table->decode_len) && + bit_field >= table->decode_len[cur_len]) { + cur_len++; + } + + table->quick_len[code] = (uint8_t) cur_len; + + dist = bit_field - table->decode_len[cur_len - 1]; + dist >>= (16 - cur_len); + + pos = table->decode_pos[cur_len & 15] + dist; + if(cur_len < rar5_countof(table->decode_pos) && pos < size) { + table->quick_num[code] = table->decode_num[pos]; + } else { + table->quick_num[code] = 0; + } + } + + return ARCHIVE_OK; +} + +static int decode_number(struct archive_read* a, struct decode_table* table, + const uint8_t* p, uint16_t* num) +{ + int i, bits, dist; + uint16_t bitfield; + uint32_t pos; + struct rar5* rar = get_context(a); + + if(ARCHIVE_OK != read_bits_16(rar, p, &bitfield)) { + return ARCHIVE_EOF; + } + + bitfield &= 0xfffe; + + if(bitfield < table->decode_len[table->quick_bits]) { + int code = bitfield >> (16 - table->quick_bits); + skip_bits(rar, table->quick_len[code]); + *num = table->quick_num[code]; + return ARCHIVE_OK; + } + + bits = 15; + + for(i = table->quick_bits + 1; i < 15; i++) { + if(bitfield < table->decode_len[i]) { + bits = i; + break; + } + } + + skip_bits(rar, bits); + + dist = bitfield - table->decode_len[bits - 1]; + dist >>= (16 - bits); + pos = table->decode_pos[bits] + dist; + + if(pos >= table->size) + pos = 0; + + *num = table->decode_num[pos]; + return ARCHIVE_OK; +} + +/* Reads and parses Huffman tables from the beginning of the block. */ +static int parse_tables(struct archive_read* a, struct rar5* rar, + const uint8_t* p) +{ + int ret, value, i, w, idx = 0; + uint8_t bit_length[HUFF_BC], + table[HUFF_TABLE_SIZE], + nibble_mask = 0xF0, + nibble_shift = 4; + + enum { ESCAPE = 15 }; + + /* The data for table generation is compressed using a simple RLE-like + * algorithm when storing zeroes, so we need to unpack it first. */ + for(w = 0, i = 0; w < HUFF_BC;) { + if(i >= rar->cstate.cur_block_size) { + /* Truncated data, can't continue. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated data in huffman tables"); + return ARCHIVE_FATAL; + } + + value = (p[i] & nibble_mask) >> nibble_shift; + + if(nibble_mask == 0x0F) + ++i; + + nibble_mask ^= 0xFF; + nibble_shift ^= 4; + + /* Values smaller than 15 is data, so we write it directly. + * Value 15 is a flag telling us that we need to unpack more + * bytes. */ + if(value == ESCAPE) { + value = (p[i] & nibble_mask) >> nibble_shift; + if(nibble_mask == 0x0F) + ++i; + nibble_mask ^= 0xFF; + nibble_shift ^= 4; + + if(value == 0) { + /* We sometimes need to write the actual value + * of 15, so this case handles that. */ + bit_length[w++] = ESCAPE; + } else { + int k; + + /* Fill zeroes. */ + for(k = 0; (k < value + 2) && (w < HUFF_BC); + k++) { + bit_length[w++] = 0; + } + } + } else { + bit_length[w++] = value; + } + } + + rar->bits.in_addr = i; + rar->bits.bit_addr = nibble_shift ^ 4; + + ret = create_decode_tables(bit_length, &rar->cstate.bd, HUFF_BC); + if(ret != ARCHIVE_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Decoding huffman tables failed"); + return ARCHIVE_FATAL; + } + + for(i = 0; i < HUFF_TABLE_SIZE;) { + uint16_t num; + + if((rar->bits.in_addr + 6) >= rar->cstate.cur_block_size) { + /* Truncated data, can't continue. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated data in huffman tables (#2)"); + return ARCHIVE_FATAL; + } + + ret = decode_number(a, &rar->cstate.bd, p, &num); + if(ret != ARCHIVE_OK) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Decoding huffman tables failed"); + return ARCHIVE_FATAL; + } + + if(num < 16) { + /* 0..15: store directly */ + table[i] = (uint8_t) num; + i++; + } else if(num < 18) { + /* 16..17: repeat previous code */ + uint16_t n; + + if(ARCHIVE_OK != read_bits_16(rar, p, &n)) + return ARCHIVE_EOF; + + if(num == 16) { + n >>= 13; + n += 3; + skip_bits(rar, 3); + } else { + n >>= 9; + n += 11; + skip_bits(rar, 7); + } + + if(i > 0) { + while(n-- > 0 && i < HUFF_TABLE_SIZE) { + table[i] = table[i - 1]; + i++; + } + } else { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Unexpected error when decoding " + "huffman tables"); + return ARCHIVE_FATAL; + } + } else { + /* other codes: fill with zeroes `n` times */ + uint16_t n; + + if(ARCHIVE_OK != read_bits_16(rar, p, &n)) + return ARCHIVE_EOF; + + if(num == 18) { + n >>= 13; + n += 3; + skip_bits(rar, 3); + } else { + n >>= 9; + n += 11; + skip_bits(rar, 7); + } + + while(n-- > 0 && i < HUFF_TABLE_SIZE) + table[i++] = 0; + } + } + + ret = create_decode_tables(&table[idx], &rar->cstate.ld, HUFF_NC); + if(ret != ARCHIVE_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Failed to create literal table"); + return ARCHIVE_FATAL; + } + + idx += HUFF_NC; + + ret = create_decode_tables(&table[idx], &rar->cstate.dd, HUFF_DC); + if(ret != ARCHIVE_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Failed to create distance table"); + return ARCHIVE_FATAL; + } + + idx += HUFF_DC; + + ret = create_decode_tables(&table[idx], &rar->cstate.ldd, HUFF_LDC); + if(ret != ARCHIVE_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Failed to create lower bits of distances table"); + return ARCHIVE_FATAL; + } + + idx += HUFF_LDC; + + ret = create_decode_tables(&table[idx], &rar->cstate.rd, HUFF_RC); + if(ret != ARCHIVE_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Failed to create repeating distances table"); + return ARCHIVE_FATAL; + } + + return ARCHIVE_OK; +} + +/* Parses the block header, verifies its CRC byte, and saves the header + * fields inside the `hdr` pointer. */ +static int parse_block_header(struct archive_read* a, const uint8_t* p, + ssize_t* block_size, struct compressed_block_header* hdr) +{ + uint8_t calculated_cksum; + memcpy(hdr, p, sizeof(struct compressed_block_header)); + + if(bf_byte_count(hdr) > 2) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Unsupported block header size (was %d, max is 2)", + bf_byte_count(hdr)); + return ARCHIVE_FATAL; + } + + /* This should probably use bit reader interface in order to be more + * future-proof. */ + *block_size = 0; + switch(bf_byte_count(hdr)) { + /* 1-byte block size */ + case 0: + *block_size = *(const uint8_t*) &p[2]; + break; + + /* 2-byte block size */ + case 1: + *block_size = archive_le16dec(&p[2]); + break; + + /* 3-byte block size */ + case 2: + *block_size = archive_le32dec(&p[2]); + *block_size &= 0x00FFFFFF; + break; + + /* Other block sizes are not supported. This case is not + * reached, because we have an 'if' guard before the switch + * that makes sure of it. */ + default: + return ARCHIVE_FATAL; + } + + /* Verify the block header checksum. 0x5A is a magic value and is + * always * constant. */ + calculated_cksum = 0x5A + ^ (uint8_t) hdr->block_flags_u8 + ^ (uint8_t) *block_size + ^ (uint8_t) (*block_size >> 8) + ^ (uint8_t) (*block_size >> 16); + + if(calculated_cksum != hdr->block_cksum) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Block checksum error: got 0x%x, expected 0x%x", + hdr->block_cksum, calculated_cksum); + + return ARCHIVE_FATAL; + } + + return ARCHIVE_OK; +} + +/* Convenience function used during filter processing. */ +static int parse_filter_data(struct rar5* rar, const uint8_t* p, + uint32_t* filter_data) +{ + int i, bytes; + uint32_t data = 0; + + if(ARCHIVE_OK != read_consume_bits(rar, p, 2, &bytes)) + return ARCHIVE_EOF; + + bytes++; + + for(i = 0; i < bytes; i++) { + uint16_t byte; + + if(ARCHIVE_OK != read_bits_16(rar, p, &byte)) { + return ARCHIVE_EOF; + } + + /* Cast to uint32_t will ensure the shift operation will not + * produce undefined result. */ + data += ((uint32_t) byte >> 8) << (i * 8); + skip_bits(rar, 8); + } + + *filter_data = data; + return ARCHIVE_OK; +} + +/* Function is used during sanity checking. */ +static int is_valid_filter_block_start(struct rar5* rar, + uint32_t start) +{ + const int64_t block_start = (ssize_t) start + rar->cstate.write_ptr; + const int64_t last_bs = rar->cstate.last_block_start; + const ssize_t last_bl = rar->cstate.last_block_length; + + if(last_bs == 0 || last_bl == 0) { + /* We didn't have any filters yet, so accept this offset. */ + return 1; + } + + if(block_start >= last_bs + last_bl) { + /* Current offset is bigger than last block's end offset, so + * accept current offset. */ + return 1; + } + + /* Any other case is not a normal situation and we should fail. */ + return 0; +} + +/* The function will create a new filter, read its parameters from the input + * stream and add it to the filter collection. */ +static int parse_filter(struct archive_read* ar, const uint8_t* p) { + uint32_t block_start, block_length; + uint16_t filter_type; + struct filter_info* filt = NULL; + struct rar5* rar = get_context(ar); + + /* Read the parameters from the input stream. */ + if(ARCHIVE_OK != parse_filter_data(rar, p, &block_start)) + return ARCHIVE_EOF; + + if(ARCHIVE_OK != parse_filter_data(rar, p, &block_length)) + return ARCHIVE_EOF; + + if(ARCHIVE_OK != read_bits_16(rar, p, &filter_type)) + return ARCHIVE_EOF; + + filter_type >>= 13; + skip_bits(rar, 3); + + /* Perform some sanity checks on this filter parameters. Note that we + * allow only DELTA, E8/E9 and ARM filters here, because rest of + * filters are not used in RARv5. */ + + if(block_length < 4 || + block_length > 0x400000 || + filter_type > FILTER_ARM || + !is_valid_filter_block_start(rar, block_start)) + { + archive_set_error(&ar->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid filter encountered"); + return ARCHIVE_FATAL; + } + + /* Allocate a new filter. */ + filt = add_new_filter(rar); + if(filt == NULL) { + archive_set_error(&ar->archive, ENOMEM, + "Can't allocate memory for a filter descriptor."); + return ARCHIVE_FATAL; + } + + filt->type = filter_type; + filt->block_start = rar->cstate.write_ptr + block_start; + filt->block_length = block_length; + + rar->cstate.last_block_start = filt->block_start; + rar->cstate.last_block_length = filt->block_length; + + /* Read some more data in case this is a DELTA filter. Other filter + * types don't require any additional data over what was already + * read. */ + if(filter_type == FILTER_DELTA) { + int channels; + + if(ARCHIVE_OK != read_consume_bits(rar, p, 5, &channels)) + return ARCHIVE_EOF; + + filt->channels = channels + 1; + } + + return ARCHIVE_OK; +} + +static int decode_code_length(struct rar5* rar, const uint8_t* p, + uint16_t code) +{ + int lbits, length = 2; + if(code < 8) { + lbits = 0; + length += code; + } else { + lbits = code / 4 - 1; + length += (4 | (code & 3)) << lbits; + } + + if(lbits > 0) { + int add; + + if(ARCHIVE_OK != read_consume_bits(rar, p, lbits, &add)) + return -1; + + length += add; + } + + return length; +} + +static int copy_string(struct archive_read* a, int len, int dist) { + struct rar5* rar = get_context(a); + const uint64_t cmask = rar->cstate.window_mask; + const uint64_t write_ptr = rar->cstate.write_ptr + + rar->cstate.solid_offset; + int i; + + if (rar->cstate.window_buf == NULL) + return ARCHIVE_FATAL; + + /* The unpacker spends most of the time in this function. It would be + * a good idea to introduce some optimizations here. + * + * Just remember that this loop treats buffers that overlap differently + * than buffers that do not overlap. This is why a simple memcpy(3) + * call will not be enough. */ + + for(i = 0; i < len; i++) { + const ssize_t write_idx = (write_ptr + i) & cmask; + const ssize_t read_idx = (write_ptr + i - dist) & cmask; + rar->cstate.window_buf[write_idx] = + rar->cstate.window_buf[read_idx]; + } + + rar->cstate.write_ptr += len; + return ARCHIVE_OK; +} + +static int do_uncompress_block(struct archive_read* a, const uint8_t* p) { + struct rar5* rar = get_context(a); + uint16_t num; + int ret; + + const uint64_t cmask = rar->cstate.window_mask; + const struct compressed_block_header* hdr = &rar->last_block_hdr; + const uint8_t bit_size = 1 + bf_bit_size(hdr); + + while(1) { + if(rar->cstate.write_ptr - rar->cstate.last_write_ptr > + (rar->cstate.window_size >> 1)) { + /* Don't allow growing data by more than half of the + * window size at a time. In such case, break the loop; + * next call to this function will continue processing + * from this moment. */ + break; + } + + if(rar->bits.in_addr > rar->cstate.cur_block_size - 1 || + (rar->bits.in_addr == rar->cstate.cur_block_size - 1 && + rar->bits.bit_addr >= bit_size)) + { + /* If the program counter is here, it means the + * function has finished processing the block. */ + rar->cstate.block_parsing_finished = 1; + break; + } + + /* Decode the next literal. */ + if(ARCHIVE_OK != decode_number(a, &rar->cstate.ld, p, &num)) { + return ARCHIVE_EOF; + } + + /* Num holds a decompression literal, or 'command code'. + * + * - Values lower than 256 are just bytes. Those codes + * can be stored in the output buffer directly. + * + * - Code 256 defines a new filter, which is later used to + * ransform the data block accordingly to the filter type. + * The data block needs to be fully uncompressed first. + * + * - Code bigger than 257 and smaller than 262 define + * a repetition pattern that should be copied from + * an already uncompressed chunk of data. + */ + + if(num < 256) { + /* Directly store the byte. */ + int64_t write_idx = rar->cstate.solid_offset + + rar->cstate.write_ptr++; + + rar->cstate.window_buf[write_idx & cmask] = + (uint8_t) num; + continue; + } else if(num >= 262) { + uint16_t dist_slot; + int len = decode_code_length(rar, p, num - 262), + dbits, + dist = 1; + + if(len == -1) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_PROGRAMMER, + "Failed to decode the code length"); + + return ARCHIVE_FATAL; + } + + if(ARCHIVE_OK != decode_number(a, &rar->cstate.dd, p, + &dist_slot)) + { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_PROGRAMMER, + "Failed to decode the distance slot"); + + return ARCHIVE_FATAL; + } + + if(dist_slot < 4) { + dbits = 0; + dist += dist_slot; + } else { + dbits = dist_slot / 2 - 1; + + /* Cast to uint32_t will make sure the shift + * left operation won't produce undefined + * result. Then, the uint32_t type will + * be implicitly casted to int. */ + dist += (uint32_t) (2 | + (dist_slot & 1)) << dbits; + } + + if(dbits > 0) { + if(dbits >= 4) { + uint32_t add = 0; + uint16_t low_dist; + + if(dbits > 4) { + if(ARCHIVE_OK != read_bits_32( + rar, p, &add)) { + /* Return EOF if we + * can't read more + * data. */ + return ARCHIVE_EOF; + } + + skip_bits(rar, dbits - 4); + add = (add >> ( + 36 - dbits)) << 4; + dist += add; + } + + if(ARCHIVE_OK != decode_number(a, + &rar->cstate.ldd, p, &low_dist)) + { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_PROGRAMMER, + "Failed to decode the " + "distance slot"); + + return ARCHIVE_FATAL; + } + + if(dist >= INT_MAX - low_dist - 1) { + /* This only happens in + * invalid archives. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Distance pointer " + "overflow"); + return ARCHIVE_FATAL; + } + + dist += low_dist; + } else { + /* dbits is one of [0,1,2,3] */ + int add; + + if(ARCHIVE_OK != read_consume_bits(rar, + p, dbits, &add)) { + /* Return EOF if we can't read + * more data. */ + return ARCHIVE_EOF; + } + + dist += add; + } + } + + if(dist > 0x100) { + len++; + + if(dist > 0x2000) { + len++; + + if(dist > 0x40000) { + len++; + } + } + } + + dist_cache_push(rar, dist); + rar->cstate.last_len = len; + + if(ARCHIVE_OK != copy_string(a, len, dist)) + return ARCHIVE_FATAL; + + continue; + } else if(num == 256) { + /* Create a filter. */ + ret = parse_filter(a, p); + if(ret != ARCHIVE_OK) + return ret; + + continue; + } else if(num == 257) { + if(rar->cstate.last_len != 0) { + if(ARCHIVE_OK != copy_string(a, + rar->cstate.last_len, + rar->cstate.dist_cache[0])) + { + return ARCHIVE_FATAL; + } + } + + continue; + } else { + /* num < 262 */ + const int idx = num - 258; + const int dist = dist_cache_touch(rar, idx); + + uint16_t len_slot; + int len; + + if(ARCHIVE_OK != decode_number(a, &rar->cstate.rd, p, + &len_slot)) { + return ARCHIVE_FATAL; + } + + len = decode_code_length(rar, p, len_slot); + rar->cstate.last_len = len; + + if(ARCHIVE_OK != copy_string(a, len, dist)) + return ARCHIVE_FATAL; + + continue; + } + + /* The program counter shouldn't reach here. */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Unsupported block code: 0x%x", num); + + return ARCHIVE_FATAL; + } + + return ARCHIVE_OK; +} + +/* Binary search for the RARv5 signature. */ +static int scan_for_signature(struct archive_read* a) { + const uint8_t* p; + const int chunk_size = 512; + ssize_t i; + char signature[sizeof(rar5_signature_xor)]; + + /* If we're here, it means we're on an 'unknown territory' data. + * There's no indication what kind of data we're reading here. + * It could be some text comment, any kind of binary data, + * digital sign, dragons, etc. + * + * We want to find a valid RARv5 magic header inside this unknown + * data. */ + + /* Is it possible in libarchive to just skip everything until the + * end of the file? If so, it would be a better approach than the + * current implementation of this function. */ + + rar5_signature(signature); + + while(1) { + if(!read_ahead(a, chunk_size, &p)) + return ARCHIVE_EOF; + + for(i = 0; i < chunk_size - (int)sizeof(rar5_signature_xor); + i++) { + if(memcmp(&p[i], signature, + sizeof(rar5_signature_xor)) == 0) { + /* Consume the number of bytes we've used to + * search for the signature, as well as the + * number of bytes used by the signature + * itself. After this we should be standing + * on a valid base block header. */ + (void) consume(a, + i + sizeof(rar5_signature_xor)); + return ARCHIVE_OK; + } + } + + consume(a, chunk_size); + } + + return ARCHIVE_FATAL; +} + +/* This function will switch the multivolume archive file to another file, + * i.e. from part03 to part 04. */ +static int advance_multivolume(struct archive_read* a) { + int lret; + struct rar5* rar = get_context(a); + + /* A small state machine that will skip unnecessary data, needed to + * switch from one multivolume to another. Such skipping is needed if + * we want to be an stream-oriented (instead of file-oriented) + * unpacker. + * + * The state machine starts with `rar->main.endarc` == 0. It also + * assumes that current stream pointer points to some base block + * header. + * + * The `endarc` field is being set when the base block parsing + * function encounters the 'end of archive' marker. + */ + + while(1) { + if(rar->main.endarc == 1) { + int looping = 1; + + rar->main.endarc = 0; + + while(looping) { + lret = skip_base_block(a); + switch(lret) { + case ARCHIVE_RETRY: + /* Continue looping. */ + break; + case ARCHIVE_OK: + /* Break loop. */ + looping = 0; + break; + default: + /* Forward any errors to the + * caller. */ + return lret; + } + } + + break; + } else { + /* Skip current base block. In order to properly skip + * it, we really need to simply parse it and discard + * the results. */ + + lret = skip_base_block(a); + if(lret == ARCHIVE_FATAL || lret == ARCHIVE_FAILED) + return lret; + + /* The `skip_base_block` function tells us if we + * should continue with skipping, or we should stop + * skipping. We're trying to skip everything up to + * a base FILE block. */ + + if(lret != ARCHIVE_RETRY) { + /* If there was an error during skipping, or we + * have just skipped a FILE base block... */ + + if(rar->main.endarc == 0) { + return lret; + } else { + continue; + } + } + } + } + + return ARCHIVE_OK; +} + +/* Merges the partial block from the first multivolume archive file, and + * partial block from the second multivolume archive file. The result is + * a chunk of memory containing the whole block, and the stream pointer + * is advanced to the next block in the second multivolume archive file. */ +static int merge_block(struct archive_read* a, ssize_t block_size, + const uint8_t** p) +{ + struct rar5* rar = get_context(a); + ssize_t cur_block_size, partial_offset = 0; + const uint8_t* lp; + int ret; + + if(rar->merge_mode) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "Recursive merge is not allowed"); + + return ARCHIVE_FATAL; + } + + /* Set a flag that we're in the switching mode. */ + rar->cstate.switch_multivolume = 1; + + /* Reallocate the memory which will hold the whole block. */ + if(rar->vol.push_buf) + free((void*) rar->vol.push_buf); + + /* Increasing the allocation block by 8 is due to bit reading functions, + * which are using additional 2 or 4 bytes. Allocating the block size + * by exact value would make bit reader perform reads from invalid + * memory block when reading the last byte from the buffer. */ + rar->vol.push_buf = malloc(block_size + 8); + if(!rar->vol.push_buf) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for a merge block buffer."); + return ARCHIVE_FATAL; + } + + /* Valgrind complains if the extension block for bit reader is not + * initialized, so initialize it. */ + memset(&rar->vol.push_buf[block_size], 0, 8); + + /* A single block can span across multiple multivolume archive files, + * so we use a loop here. This loop will consume enough multivolume + * archive files until the whole block is read. */ + + while(1) { + /* Get the size of current block chunk in this multivolume + * archive file and read it. */ + cur_block_size = rar5_min(rar->file.bytes_remaining, + block_size - partial_offset); + + if(cur_block_size == 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Encountered block size == 0 during block merge"); + return ARCHIVE_FATAL; + } + + if(!read_ahead(a, cur_block_size, &lp)) + return ARCHIVE_EOF; + + /* Sanity check; there should never be a situation where this + * function reads more data than the block's size. */ + if(partial_offset + cur_block_size > block_size) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_PROGRAMMER, + "Consumed too much data when merging blocks."); + return ARCHIVE_FATAL; + } + + /* Merge previous block chunk with current block chunk, + * or create first block chunk if this is our first + * iteration. */ + memcpy(&rar->vol.push_buf[partial_offset], lp, cur_block_size); + + /* Advance the stream read pointer by this block chunk size. */ + if(ARCHIVE_OK != consume(a, cur_block_size)) + return ARCHIVE_EOF; + + /* Update the pointers. `partial_offset` contains information + * about the sum of merged block chunks. */ + partial_offset += cur_block_size; + rar->file.bytes_remaining -= cur_block_size; + + /* If `partial_offset` is the same as `block_size`, this means + * we've merged all block chunks and we have a valid full + * block. */ + if(partial_offset == block_size) { + break; + } + + /* If we don't have any bytes to read, this means we should + * switch to another multivolume archive file. */ + if(rar->file.bytes_remaining == 0) { + rar->merge_mode++; + ret = advance_multivolume(a); + rar->merge_mode--; + if(ret != ARCHIVE_OK) { + return ret; + } + } + } + + *p = rar->vol.push_buf; + + /* If we're here, we can resume unpacking by processing the block + * pointed to by the `*p` memory pointer. */ + + return ARCHIVE_OK; +} + +static int process_block(struct archive_read* a) { + const uint8_t* p; + struct rar5* rar = get_context(a); + int ret; + + /* If we don't have any data to be processed, this most probably means + * we need to switch to the next volume. */ + if(rar->main.volume && rar->file.bytes_remaining == 0) { + ret = advance_multivolume(a); + if(ret != ARCHIVE_OK) + return ret; + } + + if(rar->cstate.block_parsing_finished) { + ssize_t block_size; + ssize_t to_skip; + ssize_t cur_block_size; + + /* The header size won't be bigger than 6 bytes. */ + if(!read_ahead(a, 6, &p)) { + /* Failed to prefetch data block header. */ + return ARCHIVE_EOF; + } + + /* + * Read block_size by parsing block header. Validate the header + * by calculating CRC byte stored inside the header. Size of + * the header is not constant (block size can be stored either + * in 1 or 2 bytes), that's why block size is left out from the + * `compressed_block_header` structure and returned by + * `parse_block_header` as the second argument. */ + + ret = parse_block_header(a, p, &block_size, + &rar->last_block_hdr); + if(ret != ARCHIVE_OK) { + return ret; + } + + /* Skip block header. Next data is huffman tables, + * if present. */ + to_skip = sizeof(struct compressed_block_header) + + bf_byte_count(&rar->last_block_hdr) + 1; + + if(ARCHIVE_OK != consume(a, to_skip)) + return ARCHIVE_EOF; + + rar->file.bytes_remaining -= to_skip; + + /* The block size gives information about the whole block size, + * but the block could be stored in split form when using + * multi-volume archives. In this case, the block size will be + * bigger than the actual data stored in this file. Remaining + * part of the data will be in another file. */ + + cur_block_size = + rar5_min(rar->file.bytes_remaining, block_size); + + if(block_size > rar->file.bytes_remaining) { + /* If current blocks' size is bigger than our data + * size, this means we have a multivolume archive. + * In this case, skip all base headers until the end + * of the file, proceed to next "partXXX.rar" volume, + * find its signature, skip all headers up to the first + * FILE base header, and continue from there. + * + * Note that `merge_block` will update the `rar` + * context structure quite extensively. */ + + ret = merge_block(a, block_size, &p); + if(ret != ARCHIVE_OK) { + return ret; + } + + cur_block_size = block_size; + + /* Current stream pointer should be now directly + * *after* the block that spanned through multiple + * archive files. `p` pointer should have the data of + * the *whole* block (merged from partial blocks + * stored in multiple archives files). */ + } else { + rar->cstate.switch_multivolume = 0; + + /* Read the whole block size into memory. This can take + * up to 8 megabytes of memory in theoretical cases. + * Might be worth to optimize this and use a standard + * chunk of 4kb's. */ + if(!read_ahead(a, 4 + cur_block_size, &p)) { + /* Failed to prefetch block data. */ + return ARCHIVE_EOF; + } + } + + rar->cstate.block_buf = p; + rar->cstate.cur_block_size = cur_block_size; + rar->cstate.block_parsing_finished = 0; + + rar->bits.in_addr = 0; + rar->bits.bit_addr = 0; + + if(bf_is_table_present(&rar->last_block_hdr)) { + /* Load Huffman tables. */ + ret = parse_tables(a, rar, p); + if(ret != ARCHIVE_OK) { + /* Error during decompression of Huffman + * tables. */ + return ret; + } + } + } else { + /* Block parsing not finished, reuse previous memory buffer. */ + p = rar->cstate.block_buf; + } + + /* Uncompress the block, or a part of it, depending on how many bytes + * will be generated by uncompressing the block. + * + * In case too many bytes will be generated, calling this function + * again will resume the uncompression operation. */ + ret = do_uncompress_block(a, p); + if(ret != ARCHIVE_OK) { + return ret; + } + + if(rar->cstate.block_parsing_finished && + rar->cstate.switch_multivolume == 0 && + rar->cstate.cur_block_size > 0) + { + /* If we're processing a normal block, consume the whole + * block. We can do this because we've already read the whole + * block to memory. */ + if(ARCHIVE_OK != consume(a, rar->cstate.cur_block_size)) + return ARCHIVE_FATAL; + + rar->file.bytes_remaining -= rar->cstate.cur_block_size; + } else if(rar->cstate.switch_multivolume) { + /* Don't consume the block if we're doing multivolume + * processing. The volume switching function will consume + * the proper count of bytes instead. */ + rar->cstate.switch_multivolume = 0; + } + + return ARCHIVE_OK; +} + +/* Pops the `buf`, `size` and `offset` from the "data ready" stack. + * + * Returns ARCHIVE_OK when those arguments can be used, ARCHIVE_RETRY + * when there is no data on the stack. */ +static int use_data(struct rar5* rar, const void** buf, size_t* size, + int64_t* offset) +{ + int i; + + for(i = 0; i < rar5_countof(rar->cstate.dready); i++) { + struct data_ready *d = &rar->cstate.dready[i]; + + if(d->used) { + if(buf) *buf = d->buf; + if(size) *size = d->size; + if(offset) *offset = d->offset; + + d->used = 0; + return ARCHIVE_OK; + } + } + + return ARCHIVE_RETRY; +} + +/* Pushes the `buf`, `size` and `offset` arguments to the rar->cstate.dready + * FIFO stack. Those values will be popped from this stack by the `use_data` + * function. */ +static int push_data_ready(struct archive_read* a, struct rar5* rar, + const uint8_t* buf, size_t size, int64_t offset) +{ + int i; + + /* Don't push if we're in skip mode. This is needed because solid + * streams need full processing even if we're skipping data. After + * fully processing the stream, we need to discard the generated bytes, + * because we're interested only in the side effect: building up the + * internal window circular buffer. This window buffer will be used + * later during unpacking of requested data. */ + if(rar->skip_mode) + return ARCHIVE_OK; + + /* Sanity check. */ + if(offset != rar->file.last_offset + rar->file.last_size) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "Sanity check error: output stream is not continuous"); + return ARCHIVE_FATAL; + } + + for(i = 0; i < rar5_countof(rar->cstate.dready); i++) { + struct data_ready* d = &rar->cstate.dready[i]; + if(!d->used) { + d->used = 1; + d->buf = buf; + d->size = size; + d->offset = offset; + + /* These fields are used only in sanity checking. */ + rar->file.last_offset = offset; + rar->file.last_size = size; + + /* Calculate the checksum of this new block before + * submitting data to libarchive's engine. */ + update_crc(rar, d->buf, d->size); + + return ARCHIVE_OK; + } + } + + /* Program counter will reach this code if the `rar->cstate.data_ready` + * stack will be filled up so that no new entries will be allowed. The + * code shouldn't allow such situation to occur. So we treat this case + * as an internal error. */ + + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "Error: premature end of data_ready stack"); + return ARCHIVE_FATAL; +} + +/* This function uncompresses the data that is stored in the base + * block. + * + * The FILE base block looks like this: + * + *
    ... + * + * The
    is a block header, that is parsed in parse_block_header(). + * It's a "compressed_block_header" structure, containing metadata needed + * to know when we should stop looking for more blocks. + * + * contain data needed to set up the huffman tables, needed + * for the actual decompression. + * + * Each consists of series of literals: + * + * ... + * + * Those literals generate the uncompression data. They operate on a circular + * buffer, sometimes writing raw data into it, sometimes referencing + * some previous data inside this buffer, and sometimes declaring a filter + * that will need to be executed on the data stored in the circular buffer. + * It all depends on the literal that is used. + * + * Sometimes blocks produce output data, sometimes they don't. For example, for + * some huge files that use lots of filters, sometimes a block is filled with + * only filter declaration literals. Such blocks won't produce any data in the + * circular buffer. + * + * Sometimes blocks will produce 4 bytes of data, and sometimes 1 megabyte, + * because a literal can reference previously decompressed data. For example, + * there can be a literal that says: 'append a byte 0xFE here', and after + * it another literal can say 'append 1 megabyte of data from circular buffer + * offset 0x12345'. This is how RAR format handles compressing repeated + * patterns. + * + * The RAR compressor creates those literals and the actual efficiency of + * compression depends on what those literals are. The literals can also + * be seen as a kind of a non-turing-complete virtual machine that simply + * tells the decompressor what it should do. + * */ + +static int do_uncompress_file(struct archive_read* a) { + struct rar5* rar = get_context(a); + int ret; + int64_t max_end_pos; + + if(!rar->cstate.initialized) { + /* Don't perform full context reinitialization if we're + * processing a solid archive. */ + if(!rar->main.solid || !rar->cstate.window_buf) { + init_unpack(rar); + } + + rar->cstate.initialized = 1; + } + + if(rar->cstate.all_filters_applied == 1) { + /* We use while(1) here, but standard case allows for just 1 + * iteration. The loop will iterate if process_block() didn't + * generate any data at all. This can happen if the block + * contains only filter definitions (this is common in big + * files). */ + while(1) { + ret = process_block(a); + if(ret == ARCHIVE_EOF || ret == ARCHIVE_FATAL) + return ret; + + if(rar->cstate.last_write_ptr == + rar->cstate.write_ptr) { + /* The block didn't generate any new data, + * so just process a new block. */ + continue; + } + + /* The block has generated some new data, so break + * the loop. */ + break; + } + } + + /* Try to run filters. If filters won't be applied, it means that + * insufficient data was generated. */ + ret = apply_filters(a); + if(ret == ARCHIVE_RETRY) { + return ARCHIVE_OK; + } else if(ret == ARCHIVE_FATAL) { + return ARCHIVE_FATAL; + } + + /* If apply_filters() will return ARCHIVE_OK, we can continue here. */ + + if(cdeque_size(&rar->cstate.filters) > 0) { + /* Check if we can write something before hitting first + * filter. */ + struct filter_info* flt; + + /* Get the block_start offset from the first filter. */ + if(CDE_OK != cdeque_front(&rar->cstate.filters, + cdeque_filter_p(&flt))) + { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_PROGRAMMER, + "Can't read first filter"); + return ARCHIVE_FATAL; + } + + max_end_pos = rar5_min(flt->block_start, + rar->cstate.write_ptr); + } else { + /* There are no filters defined, or all filters were applied. + * This means we can just store the data without any + * postprocessing. */ + max_end_pos = rar->cstate.write_ptr; + } + + if(max_end_pos == rar->cstate.last_write_ptr) { + /* We can't write anything yet. The block uncompression + * function did not generate enough data, and no filter can be + * applied. At the same time we don't have any data that can be + * stored without filter postprocessing. This means we need to + * wait for more data to be generated, so we can apply the + * filters. + * + * Signal the caller that we need more data to be able to do + * anything. + */ + return ARCHIVE_RETRY; + } else { + /* We can write the data before hitting the first filter. + * So let's do it. The push_window_data() function will + * effectively return the selected data block to the user + * application. */ + push_window_data(a, rar, rar->cstate.last_write_ptr, + max_end_pos); + rar->cstate.last_write_ptr = max_end_pos; + } + + return ARCHIVE_OK; +} + +static int uncompress_file(struct archive_read* a) { + int ret; + + while(1) { + /* Sometimes the uncompression function will return a + * 'retry' signal. If this will happen, we have to retry + * the function. */ + ret = do_uncompress_file(a); + if(ret != ARCHIVE_RETRY) + return ret; + } +} + + +static int do_unstore_file(struct archive_read* a, + struct rar5* rar, const void** buf, size_t* size, int64_t* offset) +{ + size_t to_read; + const uint8_t* p; + + if(rar->file.bytes_remaining == 0 && rar->main.volume > 0 && + rar->generic.split_after > 0) + { + int ret; + + rar->cstate.switch_multivolume = 1; + ret = advance_multivolume(a); + rar->cstate.switch_multivolume = 0; + + if(ret != ARCHIVE_OK) { + /* Failed to advance to next multivolume archive + * file. */ + return ret; + } + } + + to_read = rar5_min(rar->file.bytes_remaining, 64 * 1024); + if(to_read == 0) { + return ARCHIVE_EOF; + } + + if(!read_ahead(a, to_read, &p)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "I/O error when unstoring file"); + return ARCHIVE_FATAL; + } + + if(ARCHIVE_OK != consume(a, to_read)) { + return ARCHIVE_EOF; + } + + if(buf) *buf = p; + if(size) *size = to_read; + if(offset) *offset = rar->cstate.last_unstore_ptr; + + rar->file.bytes_remaining -= to_read; + rar->cstate.last_unstore_ptr += to_read; + + update_crc(rar, p, to_read); + return ARCHIVE_OK; +} + +static int do_unpack(struct archive_read* a, struct rar5* rar, + const void** buf, size_t* size, int64_t* offset) +{ + enum COMPRESSION_METHOD { + STORE = 0, FASTEST = 1, FAST = 2, NORMAL = 3, GOOD = 4, + BEST = 5 + }; + + if(rar->file.service > 0) { + return do_unstore_file(a, rar, buf, size, offset); + } else { + switch(rar->cstate.method) { + case STORE: + return do_unstore_file(a, rar, buf, size, + offset); + case FASTEST: + /* fallthrough */ + case FAST: + /* fallthrough */ + case NORMAL: + /* fallthrough */ + case GOOD: + /* fallthrough */ + case BEST: + return uncompress_file(a); + default: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Compression method not supported: 0x%x", + rar->cstate.method); + + return ARCHIVE_FATAL; + } + } + +#if !defined WIN32 + /* Not reached. */ + return ARCHIVE_OK; +#endif +} + +static int verify_checksums(struct archive_read* a) { + int verify_crc; + struct rar5* rar = get_context(a); + + /* Check checksums only when actually unpacking the data. There's no + * need to calculate checksum when we're skipping data in solid archives + * (skipping in solid archives is the same thing as unpacking compressed + * data and discarding the result). */ + + if(!rar->skip_mode) { + /* Always check checksums if we're not in skip mode */ + verify_crc = 1; + } else { + /* We can override the logic above with a compile-time option + * NO_CRC_ON_SOLID_SKIP. This option is used during debugging, + * and it will check checksums of unpacked data even when + * we're skipping it. */ + +#if defined CHECK_CRC_ON_SOLID_SKIP + /* Debug case */ + verify_crc = 1; +#else + /* Normal case */ + verify_crc = 0; +#endif + } + + if(verify_crc) { + /* During unpacking, on each unpacked block we're calling the + * update_crc() function. Since we are here, the unpacking + * process is already over and we can check if calculated + * checksum (CRC32 or BLAKE2sp) is the same as what is stored + * in the archive. */ + if(rar->file.stored_crc32 > 0) { + /* Check CRC32 only when the file contains a CRC32 + * value for this file. */ + + if(rar->file.calculated_crc32 != + rar->file.stored_crc32) { + /* Checksums do not match; the unpacked file + * is corrupted. */ + + DEBUG_CODE { + printf("Checksum error: CRC32 " + "(was: %08x, expected: %08x)\n", + rar->file.calculated_crc32, + rar->file.stored_crc32); + } + +#ifndef DONT_FAIL_ON_CRC_ERROR + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Checksum error: CRC32"); + return ARCHIVE_FATAL; +#endif + } else { + DEBUG_CODE { + printf("Checksum OK: CRC32 " + "(%08x/%08x)\n", + rar->file.stored_crc32, + rar->file.calculated_crc32); + } + } + } + + if(rar->file.has_blake2 > 0) { + /* BLAKE2sp is an optional checksum algorithm that is + * added to RARv5 archives when using the `-htb` switch + * during creation of archive. + * + * We now finalize the hash calculation by calling the + * `final` function. This will generate the final hash + * value we can use to compare it with the BLAKE2sp + * checksum that is stored in the archive. + * + * The return value of this `final` function is not + * very helpful, as it guards only against improper use. + * This is why we're explicitly ignoring it. */ + + uint8_t b2_buf[32]; + (void) blake2sp_final(&rar->file.b2state, b2_buf, 32); + + if(memcmp(&rar->file.blake2sp, b2_buf, 32) != 0) { +#ifndef DONT_FAIL_ON_CRC_ERROR + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Checksum error: BLAKE2"); + + return ARCHIVE_FATAL; +#endif + } + } + } + + /* Finalization for this file has been successfully completed. */ + return ARCHIVE_OK; +} + +static int verify_global_checksums(struct archive_read* a) { + return verify_checksums(a); +} + +/* + * Decryption function for the magic signature pattern. Check the comment near + * the `rar5_signature_xor` symbol to read the rationale behind this. + */ +static void rar5_signature(char *buf) { + size_t i; + + for(i = 0; i < sizeof(rar5_signature_xor); i++) { + buf[i] = rar5_signature_xor[i] ^ 0xA1; + } +} + +static int rar5_read_data(struct archive_read *a, const void **buff, + size_t *size, int64_t *offset) { + int ret; + struct rar5* rar = get_context(a); + + if(rar->file.dir > 0) { + /* Don't process any data if this file entry was declared + * as a directory. This is needed, because entries marked as + * directory doesn't have any dictionary buffer allocated, so + * it's impossible to perform any decompression. */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Can't decompress an entry marked as a directory"); + return ARCHIVE_FAILED; + } + + if(!rar->skip_mode && (rar->cstate.last_write_ptr > rar->file.unpacked_size)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "Unpacker has written too many bytes"); + return ARCHIVE_FATAL; + } + + ret = use_data(rar, buff, size, offset); + if(ret == ARCHIVE_OK) { + return ret; + } + + if(rar->file.eof == 1) { + return ARCHIVE_EOF; + } + + ret = do_unpack(a, rar, buff, size, offset); + if(ret != ARCHIVE_OK) { + return ret; + } + + if(rar->file.bytes_remaining == 0 && + rar->cstate.last_write_ptr == rar->file.unpacked_size) + { + /* If all bytes of current file were processed, run + * finalization. + * + * Finalization will check checksum against proper values. If + * some of the checksums will not match, we'll return an error + * value in the last `archive_read_data` call to signal an error + * to the user. */ + + rar->file.eof = 1; + return verify_global_checksums(a); + } + + return ARCHIVE_OK; +} + +static int rar5_read_data_skip(struct archive_read *a) { + struct rar5* rar = get_context(a); + + if(rar->main.solid) { + /* In solid archives, instead of skipping the data, we need to + * extract it, and dispose the result. The side effect of this + * operation will be setting up the initial window buffer state + * needed to be able to extract the selected file. */ + + int ret; + + /* Make sure to process all blocks in the compressed stream. */ + while(rar->file.bytes_remaining > 0) { + /* Setting the "skip mode" will allow us to skip + * checksum checks during data skipping. Checking the + * checksum of skipped data isn't really necessary and + * it's only slowing things down. + * + * This is incremented instead of setting to 1 because + * this data skipping function can be called + * recursively. */ + rar->skip_mode++; + + /* We're disposing 1 block of data, so we use triple + * NULLs in arguments. */ + ret = rar5_read_data(a, NULL, NULL, NULL); + + /* Turn off "skip mode". */ + rar->skip_mode--; + + if(ret < 0 || ret == ARCHIVE_EOF) { + /* Propagate any potential error conditions + * to the caller. */ + return ret; + } + } + } else { + /* In standard archives, we can just jump over the compressed + * stream. Each file in non-solid archives starts from an empty + * window buffer. */ + + if(ARCHIVE_OK != consume(a, rar->file.bytes_remaining)) { + return ARCHIVE_FATAL; + } + + rar->file.bytes_remaining = 0; + } + + return ARCHIVE_OK; +} + +static int64_t rar5_seek_data(struct archive_read *a, int64_t offset, + int whence) +{ + (void) a; + (void) offset; + (void) whence; + + /* We're a streaming unpacker, and we don't support seeking. */ + + return ARCHIVE_FATAL; +} + +static int rar5_cleanup(struct archive_read *a) { + struct rar5* rar = get_context(a); + + free(rar->cstate.window_buf); + free(rar->cstate.filtered_buf); + + free(rar->vol.push_buf); + + free_filters(rar); + cdeque_free(&rar->cstate.filters); + + free(rar); + a->format->data = NULL; + + return ARCHIVE_OK; +} + +static int rar5_capabilities(struct archive_read * a) { + (void) a; + return 0; +} + +static int rar5_has_encrypted_entries(struct archive_read *_a) { + (void) _a; + + /* Unsupported for now. */ + return ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED; +} + +static int rar5_init(struct rar5* rar) { + memset(rar, 0, sizeof(struct rar5)); + + if(CDE_OK != cdeque_init(&rar->cstate.filters, 8192)) + return ARCHIVE_FATAL; + + return ARCHIVE_OK; +} + +int archive_read_support_format_rar5(struct archive *_a) { + struct archive_read* ar; + int ret; + struct rar5* rar; + + if(ARCHIVE_OK != (ret = get_archive_read(_a, &ar))) + return ret; + + rar = malloc(sizeof(*rar)); + if(rar == NULL) { + archive_set_error(&ar->archive, ENOMEM, + "Can't allocate rar5 data"); + return ARCHIVE_FATAL; + } + + if(ARCHIVE_OK != rar5_init(rar)) { + archive_set_error(&ar->archive, ENOMEM, + "Can't allocate rar5 filter buffer"); + return ARCHIVE_FATAL; + } + + ret = __archive_read_register_format(ar, + rar, + "rar5", + rar5_bid, + rar5_options, + rar5_read_header, + rar5_read_data, + rar5_read_data_skip, + rar5_seek_data, + rar5_cleanup, + rar5_capabilities, + rar5_has_encrypted_entries); + + if(ret != ARCHIVE_OK) { + (void) rar5_cleanup(ar); + } + + return ret; +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_raw.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_raw.c new file mode 100644 index 0000000..ec0520b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_raw.c @@ -0,0 +1,192 @@ +/*- + * Copyright (c) 2003-2009 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_raw.c 201107 2009-12-28 03:25:33Z kientzle $"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_read_private.h" + +struct raw_info { + int64_t offset; /* Current position in the file. */ + int64_t unconsumed; + int end_of_file; +}; + +static int archive_read_format_raw_bid(struct archive_read *, int); +static int archive_read_format_raw_cleanup(struct archive_read *); +static int archive_read_format_raw_read_data(struct archive_read *, + const void **, size_t *, int64_t *); +static int archive_read_format_raw_read_data_skip(struct archive_read *); +static int archive_read_format_raw_read_header(struct archive_read *, + struct archive_entry *); + +int +archive_read_support_format_raw(struct archive *_a) +{ + struct raw_info *info; + struct archive_read *a = (struct archive_read *)_a; + int r; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_format_raw"); + + info = (struct raw_info *)calloc(1, sizeof(*info)); + if (info == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate raw_info data"); + return (ARCHIVE_FATAL); + } + + r = __archive_read_register_format(a, + info, + "raw", + archive_read_format_raw_bid, + NULL, + archive_read_format_raw_read_header, + archive_read_format_raw_read_data, + archive_read_format_raw_read_data_skip, + NULL, + archive_read_format_raw_cleanup, + NULL, + NULL); + if (r != ARCHIVE_OK) + free(info); + return (r); +} + +/* + * Bid 1 if this is a non-empty file. Anyone who can really support + * this should outbid us, so it should generally be safe to use "raw" + * in conjunction with other formats. But, this could really confuse + * folks if there are bid errors or minor file damage, so we don't + * include "raw" as part of support_format_all(). + */ +static int +archive_read_format_raw_bid(struct archive_read *a, int best_bid) +{ + if (best_bid < 1 && __archive_read_ahead(a, 1, NULL) != NULL) + return (1); + return (-1); +} + +/* + * Mock up a fake header. + */ +static int +archive_read_format_raw_read_header(struct archive_read *a, + struct archive_entry *entry) +{ + struct raw_info *info; + + info = (struct raw_info *)(a->format->data); + if (info->end_of_file) + return (ARCHIVE_EOF); + + a->archive.archive_format = ARCHIVE_FORMAT_RAW; + a->archive.archive_format_name = "raw"; + archive_entry_set_pathname(entry, "data"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_perm(entry, 0644); + /* I'm deliberately leaving most fields unset here. */ + + /* Let the filter fill out any fields it might have. */ + return __archive_read_header(a, entry); +} + +static int +archive_read_format_raw_read_data(struct archive_read *a, + const void **buff, size_t *size, int64_t *offset) +{ + struct raw_info *info; + ssize_t avail; + + info = (struct raw_info *)(a->format->data); + + /* Consume the bytes we read last time. */ + if (info->unconsumed) { + __archive_read_consume(a, info->unconsumed); + info->unconsumed = 0; + } + + if (info->end_of_file) + return (ARCHIVE_EOF); + + /* Get whatever bytes are immediately available. */ + *buff = __archive_read_ahead(a, 1, &avail); + if (avail > 0) { + /* Return the bytes we just read */ + *size = avail; + *offset = info->offset; + info->offset += *size; + info->unconsumed = avail; + return (ARCHIVE_OK); + } else if (0 == avail) { + /* Record and return end-of-file. */ + info->end_of_file = 1; + *size = 0; + *offset = info->offset; + return (ARCHIVE_EOF); + } else { + /* Record and return an error. */ + *size = 0; + *offset = info->offset; + return ((int)avail); + } +} + +static int +archive_read_format_raw_read_data_skip(struct archive_read *a) +{ + struct raw_info *info = (struct raw_info *)(a->format->data); + + /* Consume the bytes we read last time. */ + if (info->unconsumed) { + __archive_read_consume(a, info->unconsumed); + info->unconsumed = 0; + } + info->end_of_file = 1; + return (ARCHIVE_OK); +} + +static int +archive_read_format_raw_cleanup(struct archive_read *a) +{ + struct raw_info *info; + + info = (struct raw_info *)(a->format->data); + free(info); + a->format->data = NULL; + return (ARCHIVE_OK); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_tar.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_tar.c new file mode 100644 index 0000000..c63d46f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_tar.c @@ -0,0 +1,2904 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2011-2012 Michihiro NAKAJIMA + * Copyright (c) 2016 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_tar.c 201161 2009-12-29 05:44:39Z kientzle $"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive.h" +#include "archive_acl_private.h" /* For ACL parsing routines. */ +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_private.h" +#include "archive_read_private.h" + +#define tar_min(a,b) ((a) < (b) ? (a) : (b)) + +/* + * Layout of POSIX 'ustar' tar header. + */ +struct archive_entry_header_ustar { + char name[100]; + char mode[8]; + char uid[8]; + char gid[8]; + char size[12]; + char mtime[12]; + char checksum[8]; + char typeflag[1]; + char linkname[100]; /* "old format" header ends here */ + char magic[6]; /* For POSIX: "ustar\0" */ + char version[2]; /* For POSIX: "00" */ + char uname[32]; + char gname[32]; + char rdevmajor[8]; + char rdevminor[8]; + char prefix[155]; +}; + +/* + * Structure of GNU tar header + */ +struct gnu_sparse { + char offset[12]; + char numbytes[12]; +}; + +struct archive_entry_header_gnutar { + char name[100]; + char mode[8]; + char uid[8]; + char gid[8]; + char size[12]; + char mtime[12]; + char checksum[8]; + char typeflag[1]; + char linkname[100]; + char magic[8]; /* "ustar \0" (note blank/blank/null at end) */ + char uname[32]; + char gname[32]; + char rdevmajor[8]; + char rdevminor[8]; + char atime[12]; + char ctime[12]; + char offset[12]; + char longnames[4]; + char unused[1]; + struct gnu_sparse sparse[4]; + char isextended[1]; + char realsize[12]; + /* + * Old GNU format doesn't use POSIX 'prefix' field; they use + * the 'L' (longname) entry instead. + */ +}; + +/* + * Data specific to this format. + */ +struct sparse_block { + struct sparse_block *next; + int64_t offset; + int64_t remaining; + int hole; +}; + +struct tar { + struct archive_string acl_text; + struct archive_string entry_pathname; + /* For "GNU.sparse.name" and other similar path extensions. */ + struct archive_string entry_pathname_override; + struct archive_string entry_linkpath; + struct archive_string entry_uname; + struct archive_string entry_gname; + struct archive_string longlink; + struct archive_string longname; + struct archive_string pax_header; + struct archive_string pax_global; + struct archive_string line; + int pax_hdrcharset_binary; + int header_recursion_depth; + int64_t entry_bytes_remaining; + int64_t entry_offset; + int64_t entry_padding; + int64_t entry_bytes_unconsumed; + int64_t realsize; + int sparse_allowed; + struct sparse_block *sparse_list; + struct sparse_block *sparse_last; + int64_t sparse_offset; + int64_t sparse_numbytes; + int sparse_gnu_major; + int sparse_gnu_minor; + char sparse_gnu_pending; + + struct archive_string localname; + struct archive_string_conv *opt_sconv; + struct archive_string_conv *sconv; + struct archive_string_conv *sconv_acl; + struct archive_string_conv *sconv_default; + int init_default_conversion; + int compat_2x; + int process_mac_extensions; + int read_concatenated_archives; + int realsize_override; +}; + +static int archive_block_is_null(const char *p); +static char *base64_decode(const char *, size_t, size_t *); +static int gnu_add_sparse_entry(struct archive_read *, struct tar *, + int64_t offset, int64_t remaining); + +static void gnu_clear_sparse_list(struct tar *); +static int gnu_sparse_old_read(struct archive_read *, struct tar *, + const struct archive_entry_header_gnutar *header, size_t *); +static int gnu_sparse_old_parse(struct archive_read *, struct tar *, + const struct gnu_sparse *sparse, int length); +static int gnu_sparse_01_parse(struct archive_read *, struct tar *, + const char *); +static ssize_t gnu_sparse_10_read(struct archive_read *, struct tar *, + size_t *); +static int header_Solaris_ACL(struct archive_read *, struct tar *, + struct archive_entry *, const void *, size_t *); +static int header_common(struct archive_read *, struct tar *, + struct archive_entry *, const void *); +static int header_old_tar(struct archive_read *, struct tar *, + struct archive_entry *, const void *); +static int header_pax_extensions(struct archive_read *, struct tar *, + struct archive_entry *, const void *, size_t *); +static int header_pax_global(struct archive_read *, struct tar *, + struct archive_entry *, const void *h, size_t *); +static int header_longlink(struct archive_read *, struct tar *, + struct archive_entry *, const void *h, size_t *); +static int header_longname(struct archive_read *, struct tar *, + struct archive_entry *, const void *h, size_t *); +static int read_mac_metadata_blob(struct archive_read *, struct tar *, + struct archive_entry *, const void *h, size_t *); +static int header_volume(struct archive_read *, struct tar *, + struct archive_entry *, const void *h, size_t *); +static int header_ustar(struct archive_read *, struct tar *, + struct archive_entry *, const void *h); +static int header_gnutar(struct archive_read *, struct tar *, + struct archive_entry *, const void *h, size_t *); +static int archive_read_format_tar_bid(struct archive_read *, int); +static int archive_read_format_tar_options(struct archive_read *, + const char *, const char *); +static int archive_read_format_tar_cleanup(struct archive_read *); +static int archive_read_format_tar_read_data(struct archive_read *a, + const void **buff, size_t *size, int64_t *offset); +static int archive_read_format_tar_skip(struct archive_read *a); +static int archive_read_format_tar_read_header(struct archive_read *, + struct archive_entry *); +static int checksum(struct archive_read *, const void *); +static int pax_attribute(struct archive_read *, struct tar *, + struct archive_entry *, const char *key, const char *value, + size_t value_length); +static int pax_attribute_acl(struct archive_read *, struct tar *, + struct archive_entry *, const char *, int); +static int pax_attribute_xattr(struct archive_entry *, const char *, + const char *); +static int pax_header(struct archive_read *, struct tar *, + struct archive_entry *, struct archive_string *); +static void pax_time(const char *, int64_t *sec, long *nanos); +static ssize_t readline(struct archive_read *, struct tar *, const char **, + ssize_t limit, size_t *); +static int read_body_to_string(struct archive_read *, struct tar *, + struct archive_string *, const void *h, size_t *); +static int solaris_sparse_parse(struct archive_read *, struct tar *, + struct archive_entry *, const char *); +static int64_t tar_atol(const char *, size_t); +static int64_t tar_atol10(const char *, size_t); +static int64_t tar_atol256(const char *, size_t); +static int64_t tar_atol8(const char *, size_t); +static int tar_read_header(struct archive_read *, struct tar *, + struct archive_entry *, size_t *); +static int tohex(int c); +static char *url_decode(const char *); +static void tar_flush_unconsumed(struct archive_read *, size_t *); + + +int +archive_read_support_format_gnutar(struct archive *a) +{ + archive_check_magic(a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_format_gnutar"); + return (archive_read_support_format_tar(a)); +} + + +int +archive_read_support_format_tar(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct tar *tar; + int r; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_format_tar"); + + tar = (struct tar *)calloc(1, sizeof(*tar)); + if (tar == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate tar data"); + return (ARCHIVE_FATAL); + } +#ifdef HAVE_COPYFILE_H + /* Set this by default on Mac OS. */ + tar->process_mac_extensions = 1; +#endif + + r = __archive_read_register_format(a, tar, "tar", + archive_read_format_tar_bid, + archive_read_format_tar_options, + archive_read_format_tar_read_header, + archive_read_format_tar_read_data, + archive_read_format_tar_skip, + NULL, + archive_read_format_tar_cleanup, + NULL, + NULL); + + if (r != ARCHIVE_OK) + free(tar); + return (ARCHIVE_OK); +} + +static int +archive_read_format_tar_cleanup(struct archive_read *a) +{ + struct tar *tar; + + tar = (struct tar *)(a->format->data); + gnu_clear_sparse_list(tar); + archive_string_free(&tar->acl_text); + archive_string_free(&tar->entry_pathname); + archive_string_free(&tar->entry_pathname_override); + archive_string_free(&tar->entry_linkpath); + archive_string_free(&tar->entry_uname); + archive_string_free(&tar->entry_gname); + archive_string_free(&tar->line); + archive_string_free(&tar->pax_global); + archive_string_free(&tar->pax_header); + archive_string_free(&tar->longname); + archive_string_free(&tar->longlink); + archive_string_free(&tar->localname); + free(tar); + (a->format->data) = NULL; + return (ARCHIVE_OK); +} + +/* + * Validate number field + * + * This has to be pretty lenient in order to accommodate the enormous + * variety of tar writers in the world: + * = POSIX (IEEE Std 1003.1-1988) ustar requires octal values with leading + * zeros and allows fields to be terminated with space or null characters + * = Many writers use different termination (in particular, libarchive + * omits terminator bytes to squeeze one or two more digits) + * = Many writers pad with space and omit leading zeros + * = GNU tar and star write base-256 values if numbers are too + * big to be represented in octal + * + * Examples of specific tar headers that we should support: + * = Perl Archive::Tar terminates uid, gid, devminor and devmajor with two + * null bytes, pads size with spaces and other numeric fields with zeroes + * = plexus-archiver prior to 2.6.3 (before switching to commons-compress) + * may have uid and gid fields filled with spaces without any octal digits + * at all and pads all numeric fields with spaces + * + * This should tolerate all variants in use. It will reject a field + * where the writer just left garbage after a trailing NUL. + */ +static int +validate_number_field(const char* p_field, size_t i_size) +{ + unsigned char marker = (unsigned char)p_field[0]; + if (marker == 128 || marker == 255 || marker == 0) { + /* Base-256 marker, there's nothing we can check. */ + return 1; + } else { + /* Must be octal */ + size_t i = 0; + /* Skip any leading spaces */ + while (i < i_size && p_field[i] == ' ') { + ++i; + } + /* Skip octal digits. */ + while (i < i_size && p_field[i] >= '0' && p_field[i] <= '7') { + ++i; + } + /* Any remaining characters must be space or NUL padding. */ + while (i < i_size) { + if (p_field[i] != ' ' && p_field[i] != 0) { + return 0; + } + ++i; + } + return 1; + } +} + +static int +archive_read_format_tar_bid(struct archive_read *a, int best_bid) +{ + int bid; + const char *h; + const struct archive_entry_header_ustar *header; + + (void)best_bid; /* UNUSED */ + + bid = 0; + + /* Now let's look at the actual header and see if it matches. */ + h = __archive_read_ahead(a, 512, NULL); + if (h == NULL) + return (-1); + + /* If it's an end-of-archive mark, we can handle it. */ + if (h[0] == 0 && archive_block_is_null(h)) { + /* + * Usually, I bid the number of bits verified, but + * in this case, 4096 seems excessive so I picked 10 as + * an arbitrary but reasonable-seeming value. + */ + return (10); + } + + /* If it's not an end-of-archive mark, it must have a valid checksum.*/ + if (!checksum(a, h)) + return (0); + bid += 48; /* Checksum is usually 6 octal digits. */ + + header = (const struct archive_entry_header_ustar *)h; + + /* Recognize POSIX formats. */ + if ((memcmp(header->magic, "ustar\0", 6) == 0) + && (memcmp(header->version, "00", 2) == 0)) + bid += 56; + + /* Recognize GNU tar format. */ + if ((memcmp(header->magic, "ustar ", 6) == 0) + && (memcmp(header->version, " \0", 2) == 0)) + bid += 56; + + /* Type flag must be null, digit or A-Z, a-z. */ + if (header->typeflag[0] != 0 && + !( header->typeflag[0] >= '0' && header->typeflag[0] <= '9') && + !( header->typeflag[0] >= 'A' && header->typeflag[0] <= 'Z') && + !( header->typeflag[0] >= 'a' && header->typeflag[0] <= 'z') ) + return (0); + bid += 2; /* 6 bits of variation in an 8-bit field leaves 2 bits. */ + + /* + * Check format of mode/uid/gid/mtime/size/rdevmajor/rdevminor fields. + */ + if (bid > 0 && ( + validate_number_field(header->mode, sizeof(header->mode)) == 0 + || validate_number_field(header->uid, sizeof(header->uid)) == 0 + || validate_number_field(header->gid, sizeof(header->gid)) == 0 + || validate_number_field(header->mtime, sizeof(header->mtime)) == 0 + || validate_number_field(header->size, sizeof(header->size)) == 0 + || validate_number_field(header->rdevmajor, sizeof(header->rdevmajor)) == 0 + || validate_number_field(header->rdevminor, sizeof(header->rdevminor)) == 0)) { + bid = 0; + } + + return (bid); +} + +static int +archive_read_format_tar_options(struct archive_read *a, + const char *key, const char *val) +{ + struct tar *tar; + int ret = ARCHIVE_FAILED; + + tar = (struct tar *)(a->format->data); + if (strcmp(key, "compat-2x") == 0) { + /* Handle UTF-8 filenames as libarchive 2.x */ + tar->compat_2x = (val != NULL && val[0] != 0); + tar->init_default_conversion = tar->compat_2x; + return (ARCHIVE_OK); + } else if (strcmp(key, "hdrcharset") == 0) { + if (val == NULL || val[0] == 0) + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "tar: hdrcharset option needs a character-set name"); + else { + tar->opt_sconv = + archive_string_conversion_from_charset( + &a->archive, val, 0); + if (tar->opt_sconv != NULL) + ret = ARCHIVE_OK; + else + ret = ARCHIVE_FATAL; + } + return (ret); + } else if (strcmp(key, "mac-ext") == 0) { + tar->process_mac_extensions = (val != NULL && val[0] != 0); + return (ARCHIVE_OK); + } else if (strcmp(key, "read_concatenated_archives") == 0) { + tar->read_concatenated_archives = (val != NULL && val[0] != 0); + return (ARCHIVE_OK); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +/* utility function- this exists to centralize the logic of tracking + * how much unconsumed data we have floating around, and to consume + * anything outstanding since we're going to do read_aheads + */ +static void +tar_flush_unconsumed(struct archive_read *a, size_t *unconsumed) +{ + if (*unconsumed) { +/* + void *data = (void *)__archive_read_ahead(a, *unconsumed, NULL); + * this block of code is to poison claimed unconsumed space, ensuring + * things break if it is in use still. + * currently it WILL break things, so enable it only for debugging this issue + if (data) { + memset(data, 0xff, *unconsumed); + } +*/ + __archive_read_consume(a, *unconsumed); + *unconsumed = 0; + } +} + +/* + * The function invoked by archive_read_next_header(). This + * just sets up a few things and then calls the internal + * tar_read_header() function below. + */ +static int +archive_read_format_tar_read_header(struct archive_read *a, + struct archive_entry *entry) +{ + /* + * When converting tar archives to cpio archives, it is + * essential that each distinct file have a distinct inode + * number. To simplify this, we keep a static count here to + * assign fake dev/inode numbers to each tar entry. Note that + * pax format archives may overwrite this with something more + * useful. + * + * Ideally, we would track every file read from the archive so + * that we could assign the same dev/ino pair to hardlinks, + * but the memory required to store a complete lookup table is + * probably not worthwhile just to support the relatively + * obscure tar->cpio conversion case. + */ + static int default_inode; + static int default_dev; + struct tar *tar; + const char *p; + const wchar_t *wp; + int r; + size_t l, unconsumed = 0; + + /* Assign default device/inode values. */ + archive_entry_set_dev(entry, 1 + default_dev); /* Don't use zero. */ + archive_entry_set_ino(entry, ++default_inode); /* Don't use zero. */ + /* Limit generated st_ino number to 16 bits. */ + if (default_inode >= 0xffff) { + ++default_dev; + default_inode = 0; + } + + tar = (struct tar *)(a->format->data); + tar->entry_offset = 0; + gnu_clear_sparse_list(tar); + tar->realsize = -1; /* Mark this as "unset" */ + tar->realsize_override = 0; + + /* Setup default string conversion. */ + tar->sconv = tar->opt_sconv; + if (tar->sconv == NULL) { + if (!tar->init_default_conversion) { + tar->sconv_default = + archive_string_default_conversion_for_read(&(a->archive)); + tar->init_default_conversion = 1; + } + tar->sconv = tar->sconv_default; + } + + r = tar_read_header(a, tar, entry, &unconsumed); + + tar_flush_unconsumed(a, &unconsumed); + + /* + * "non-sparse" files are really just sparse files with + * a single block. + */ + if (tar->sparse_list == NULL) { + if (gnu_add_sparse_entry(a, tar, 0, tar->entry_bytes_remaining) + != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } else { + struct sparse_block *sb; + + for (sb = tar->sparse_list; sb != NULL; sb = sb->next) { + if (!sb->hole) + archive_entry_sparse_add_entry(entry, + sb->offset, sb->remaining); + } + } + + if (r == ARCHIVE_OK && archive_entry_filetype(entry) == AE_IFREG) { + /* + * "Regular" entry with trailing '/' is really + * directory: This is needed for certain old tar + * variants and even for some broken newer ones. + */ + if ((wp = archive_entry_pathname_w(entry)) != NULL) { + l = wcslen(wp); + if (l > 0 && wp[l - 1] == L'/') { + archive_entry_set_filetype(entry, AE_IFDIR); + } + } else if ((p = archive_entry_pathname(entry)) != NULL) { + l = strlen(p); + if (l > 0 && p[l - 1] == '/') { + archive_entry_set_filetype(entry, AE_IFDIR); + } + } + } + return (r); +} + +static int +archive_read_format_tar_read_data(struct archive_read *a, + const void **buff, size_t *size, int64_t *offset) +{ + ssize_t bytes_read; + struct tar *tar; + struct sparse_block *p; + + tar = (struct tar *)(a->format->data); + + for (;;) { + /* Remove exhausted entries from sparse list. */ + while (tar->sparse_list != NULL && + tar->sparse_list->remaining == 0) { + p = tar->sparse_list; + tar->sparse_list = p->next; + free(p); + } + + if (tar->entry_bytes_unconsumed) { + __archive_read_consume(a, tar->entry_bytes_unconsumed); + tar->entry_bytes_unconsumed = 0; + } + + /* If we're at end of file, return EOF. */ + if (tar->sparse_list == NULL || + tar->entry_bytes_remaining == 0) { + if (__archive_read_consume(a, tar->entry_padding) < 0) + return (ARCHIVE_FATAL); + tar->entry_padding = 0; + *buff = NULL; + *size = 0; + *offset = tar->realsize; + return (ARCHIVE_EOF); + } + + *buff = __archive_read_ahead(a, 1, &bytes_read); + if (bytes_read < 0) + return (ARCHIVE_FATAL); + if (*buff == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Truncated tar archive"); + return (ARCHIVE_FATAL); + } + if (bytes_read > tar->entry_bytes_remaining) + bytes_read = (ssize_t)tar->entry_bytes_remaining; + /* Don't read more than is available in the + * current sparse block. */ + if (tar->sparse_list->remaining < bytes_read) + bytes_read = (ssize_t)tar->sparse_list->remaining; + *size = bytes_read; + *offset = tar->sparse_list->offset; + tar->sparse_list->remaining -= bytes_read; + tar->sparse_list->offset += bytes_read; + tar->entry_bytes_remaining -= bytes_read; + tar->entry_bytes_unconsumed = bytes_read; + + if (!tar->sparse_list->hole) + return (ARCHIVE_OK); + /* Current is hole data and skip this. */ + } +} + +static int +archive_read_format_tar_skip(struct archive_read *a) +{ + int64_t bytes_skipped; + int64_t request; + struct sparse_block *p; + struct tar* tar; + + tar = (struct tar *)(a->format->data); + + /* Do not consume the hole of a sparse file. */ + request = 0; + for (p = tar->sparse_list; p != NULL; p = p->next) { + if (!p->hole) { + if (p->remaining >= INT64_MAX - request) { + return ARCHIVE_FATAL; + } + request += p->remaining; + } + } + if (request > tar->entry_bytes_remaining) + request = tar->entry_bytes_remaining; + request += tar->entry_padding + tar->entry_bytes_unconsumed; + + bytes_skipped = __archive_read_consume(a, request); + if (bytes_skipped < 0) + return (ARCHIVE_FATAL); + + tar->entry_bytes_remaining = 0; + tar->entry_bytes_unconsumed = 0; + tar->entry_padding = 0; + + /* Free the sparse list. */ + gnu_clear_sparse_list(tar); + + return (ARCHIVE_OK); +} + +/* + * This function recursively interprets all of the headers associated + * with a single entry. + */ +static int +tar_read_header(struct archive_read *a, struct tar *tar, + struct archive_entry *entry, size_t *unconsumed) +{ + ssize_t bytes; + int err, eof_vol_header; + const char *h; + const struct archive_entry_header_ustar *header; + const struct archive_entry_header_gnutar *gnuheader; + + eof_vol_header = 0; + + /* Loop until we find a workable header record. */ + for (;;) { + tar_flush_unconsumed(a, unconsumed); + + /* Read 512-byte header record */ + h = __archive_read_ahead(a, 512, &bytes); + if (bytes < 0) + return ((int)bytes); + if (bytes == 0) { /* EOF at a block boundary. */ + /* Some writers do omit the block of nulls. */ + return (ARCHIVE_EOF); + } + if (bytes < 512) { /* Short block at EOF; this is bad. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated tar archive"); + return (ARCHIVE_FATAL); + } + *unconsumed = 512; + + /* Header is workable if it's not an end-of-archive mark. */ + if (h[0] != 0 || !archive_block_is_null(h)) + break; + + /* Ensure format is set for archives with only null blocks. */ + if (a->archive.archive_format_name == NULL) { + a->archive.archive_format = ARCHIVE_FORMAT_TAR; + a->archive.archive_format_name = "tar"; + } + + if (!tar->read_concatenated_archives) { + /* Try to consume a second all-null record, as well. */ + tar_flush_unconsumed(a, unconsumed); + h = __archive_read_ahead(a, 512, NULL); + if (h != NULL && h[0] == 0 && archive_block_is_null(h)) + __archive_read_consume(a, 512); + archive_clear_error(&a->archive); + return (ARCHIVE_EOF); + } + + /* + * We're reading concatenated archives, ignore this block and + * loop to get the next. + */ + } + + /* + * Note: If the checksum fails and we return ARCHIVE_RETRY, + * then the client is likely to just retry. This is a very + * crude way to search for the next valid header! + * + * TODO: Improve this by implementing a real header scan. + */ + if (!checksum(a, h)) { + tar_flush_unconsumed(a, unconsumed); + archive_set_error(&a->archive, EINVAL, "Damaged tar archive"); + return (ARCHIVE_RETRY); /* Retryable: Invalid header */ + } + + if (++tar->header_recursion_depth > 32) { + tar_flush_unconsumed(a, unconsumed); + archive_set_error(&a->archive, EINVAL, "Too many special headers"); + return (ARCHIVE_WARN); + } + + /* Determine the format variant. */ + header = (const struct archive_entry_header_ustar *)h; + + switch(header->typeflag[0]) { + case 'A': /* Solaris tar ACL */ + a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE; + a->archive.archive_format_name = "Solaris tar"; + err = header_Solaris_ACL(a, tar, entry, h, unconsumed); + break; + case 'g': /* POSIX-standard 'g' header. */ + a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE; + a->archive.archive_format_name = "POSIX pax interchange format"; + err = header_pax_global(a, tar, entry, h, unconsumed); + if (err == ARCHIVE_EOF) + return (err); + break; + case 'K': /* Long link name (GNU tar, others) */ + err = header_longlink(a, tar, entry, h, unconsumed); + break; + case 'L': /* Long filename (GNU tar, others) */ + err = header_longname(a, tar, entry, h, unconsumed); + break; + case 'V': /* GNU volume header */ + err = header_volume(a, tar, entry, h, unconsumed); + if (err == ARCHIVE_EOF) + eof_vol_header = 1; + break; + case 'X': /* Used by SUN tar; same as 'x'. */ + a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE; + a->archive.archive_format_name = + "POSIX pax interchange format (Sun variant)"; + err = header_pax_extensions(a, tar, entry, h, unconsumed); + break; + case 'x': /* POSIX-standard 'x' header. */ + a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE; + a->archive.archive_format_name = "POSIX pax interchange format"; + err = header_pax_extensions(a, tar, entry, h, unconsumed); + break; + default: + gnuheader = (const struct archive_entry_header_gnutar *)h; + if (memcmp(gnuheader->magic, "ustar \0", 8) == 0) { + a->archive.archive_format = ARCHIVE_FORMAT_TAR_GNUTAR; + a->archive.archive_format_name = "GNU tar format"; + err = header_gnutar(a, tar, entry, h, unconsumed); + } else if (memcmp(header->magic, "ustar", 5) == 0) { + if (a->archive.archive_format != ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE) { + a->archive.archive_format = ARCHIVE_FORMAT_TAR_USTAR; + a->archive.archive_format_name = "POSIX ustar format"; + } + err = header_ustar(a, tar, entry, h); + } else { + a->archive.archive_format = ARCHIVE_FORMAT_TAR; + a->archive.archive_format_name = "tar (non-POSIX)"; + err = header_old_tar(a, tar, entry, h); + } + } + if (err == ARCHIVE_FATAL) + return (err); + + tar_flush_unconsumed(a, unconsumed); + + h = NULL; + header = NULL; + + --tar->header_recursion_depth; + /* Yuck. Apple's design here ends up storing long pathname + * extensions for both the AppleDouble extension entry and the + * regular entry. + */ + if ((err == ARCHIVE_WARN || err == ARCHIVE_OK) && + tar->header_recursion_depth == 0 && + tar->process_mac_extensions) { + int err2 = read_mac_metadata_blob(a, tar, entry, h, unconsumed); + if (err2 < err) + err = err2; + } + + /* We return warnings or success as-is. Anything else is fatal. */ + if (err == ARCHIVE_WARN || err == ARCHIVE_OK) { + if (tar->sparse_gnu_pending) { + if (tar->sparse_gnu_major == 1 && + tar->sparse_gnu_minor == 0) { + ssize_t bytes_read; + + tar->sparse_gnu_pending = 0; + /* Read initial sparse map. */ + bytes_read = gnu_sparse_10_read(a, tar, unconsumed); + if (bytes_read < 0) + return ((int)bytes_read); + tar->entry_bytes_remaining -= bytes_read; + } else { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Unrecognized GNU sparse file format"); + return (ARCHIVE_WARN); + } + tar->sparse_gnu_pending = 0; + } + return (err); + } + if (err == ARCHIVE_EOF) { + if (!eof_vol_header) { + /* EOF when recursively reading a header is bad. */ + archive_set_error(&a->archive, EINVAL, + "Damaged tar archive"); + } else { + /* If we encounter just a GNU volume header treat + * this situation as an empty archive */ + return (ARCHIVE_EOF); + } + } + return (ARCHIVE_FATAL); +} + +/* + * Return true if block checksum is correct. + */ +static int +checksum(struct archive_read *a, const void *h) +{ + const unsigned char *bytes; + const struct archive_entry_header_ustar *header; + int check, sum; + size_t i; + + (void)a; /* UNUSED */ + bytes = (const unsigned char *)h; + header = (const struct archive_entry_header_ustar *)h; + + /* Checksum field must hold an octal number */ + for (i = 0; i < sizeof(header->checksum); ++i) { + char c = header->checksum[i]; + if (c != ' ' && c != '\0' && (c < '0' || c > '7')) + return 0; + } + + /* + * Test the checksum. Note that POSIX specifies _unsigned_ + * bytes for this calculation. + */ + sum = (int)tar_atol(header->checksum, sizeof(header->checksum)); + check = 0; + for (i = 0; i < 148; i++) + check += (unsigned char)bytes[i]; + for (; i < 156; i++) + check += 32; + for (; i < 512; i++) + check += (unsigned char)bytes[i]; + if (sum == check) + return (1); + + /* + * Repeat test with _signed_ bytes, just in case this archive + * was created by an old BSD, Solaris, or HP-UX tar with a + * broken checksum calculation. + */ + check = 0; + for (i = 0; i < 148; i++) + check += (signed char)bytes[i]; + for (; i < 156; i++) + check += 32; + for (; i < 512; i++) + check += (signed char)bytes[i]; + if (sum == check) + return (1); + + return (0); +} + +/* + * Return true if this block contains only nulls. + */ +static int +archive_block_is_null(const char *p) +{ + unsigned i; + + for (i = 0; i < 512; i++) + if (*p++) + return (0); + return (1); +} + +/* + * Interpret 'A' Solaris ACL header + */ +static int +header_Solaris_ACL(struct archive_read *a, struct tar *tar, + struct archive_entry *entry, const void *h, size_t *unconsumed) +{ + const struct archive_entry_header_ustar *header; + size_t size; + int err, acl_type; + int64_t type; + char *acl, *p; + + /* + * read_body_to_string adds a NUL terminator, but we need a little + * more to make sure that we don't overrun acl_text later. + */ + header = (const struct archive_entry_header_ustar *)h; + size = (size_t)tar_atol(header->size, sizeof(header->size)); + err = read_body_to_string(a, tar, &(tar->acl_text), h, unconsumed); + if (err != ARCHIVE_OK) + return (err); + + /* Recursively read next header */ + err = tar_read_header(a, tar, entry, unconsumed); + if ((err != ARCHIVE_OK) && (err != ARCHIVE_WARN)) + return (err); + + /* TODO: Examine the first characters to see if this + * is an AIX ACL descriptor. We'll likely never support + * them, but it would be polite to recognize and warn when + * we do see them. */ + + /* Leading octal number indicates ACL type and number of entries. */ + p = acl = tar->acl_text.s; + type = 0; + while (*p != '\0' && p < acl + size) { + if (*p < '0' || *p > '7') { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Malformed Solaris ACL attribute (invalid digit)"); + return(ARCHIVE_WARN); + } + type <<= 3; + type += *p - '0'; + if (type > 077777777) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Malformed Solaris ACL attribute (count too large)"); + return (ARCHIVE_WARN); + } + p++; + } + switch ((int)type & ~0777777) { + case 01000000: + /* POSIX.1e ACL */ + acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; + break; + case 03000000: + /* NFSv4 ACL */ + acl_type = ARCHIVE_ENTRY_ACL_TYPE_NFS4; + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Malformed Solaris ACL attribute (unsupported type %o)", + (int)type); + return (ARCHIVE_WARN); + } + p++; + + if (p >= acl + size) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Malformed Solaris ACL attribute (body overflow)"); + return(ARCHIVE_WARN); + } + + /* ACL text is null-terminated; find the end. */ + size -= (p - acl); + acl = p; + + while (*p != '\0' && p < acl + size) + p++; + + if (tar->sconv_acl == NULL) { + tar->sconv_acl = archive_string_conversion_from_charset( + &(a->archive), "UTF-8", 1); + if (tar->sconv_acl == NULL) + return (ARCHIVE_FATAL); + } + archive_strncpy(&(tar->localname), acl, p - acl); + err = archive_acl_from_text_l(archive_entry_acl(entry), + tar->localname.s, acl_type, tar->sconv_acl); + if (err != ARCHIVE_OK) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for ACL"); + } else + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Malformed Solaris ACL attribute (unparsable)"); + } + return (err); +} + +/* + * Interpret 'K' long linkname header. + */ +static int +header_longlink(struct archive_read *a, struct tar *tar, + struct archive_entry *entry, const void *h, size_t *unconsumed) +{ + int err; + + err = read_body_to_string(a, tar, &(tar->longlink), h, unconsumed); + if (err != ARCHIVE_OK) + return (err); + err = tar_read_header(a, tar, entry, unconsumed); + if ((err != ARCHIVE_OK) && (err != ARCHIVE_WARN)) + return (err); + /* Set symlink if symlink already set, else hardlink. */ + archive_entry_copy_link(entry, tar->longlink.s); + return (ARCHIVE_OK); +} + +static int +set_conversion_failed_error(struct archive_read *a, + struct archive_string_conv *sconv, const char *name) +{ + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for %s", name); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "%s can't be converted from %s to current locale.", + name, archive_string_conversion_charset_name(sconv)); + return (ARCHIVE_WARN); +} + +/* + * Interpret 'L' long filename header. + */ +static int +header_longname(struct archive_read *a, struct tar *tar, + struct archive_entry *entry, const void *h, size_t *unconsumed) +{ + int err; + + err = read_body_to_string(a, tar, &(tar->longname), h, unconsumed); + if (err != ARCHIVE_OK) + return (err); + /* Read and parse "real" header, then override name. */ + err = tar_read_header(a, tar, entry, unconsumed); + if ((err != ARCHIVE_OK) && (err != ARCHIVE_WARN)) + return (err); + if (archive_entry_copy_pathname_l(entry, tar->longname.s, + archive_strlen(&(tar->longname)), tar->sconv) != 0) + err = set_conversion_failed_error(a, tar->sconv, "Pathname"); + return (err); +} + + +/* + * Interpret 'V' GNU tar volume header. + */ +static int +header_volume(struct archive_read *a, struct tar *tar, + struct archive_entry *entry, const void *h, size_t *unconsumed) +{ + (void)h; + + /* Just skip this and read the next header. */ + return (tar_read_header(a, tar, entry, unconsumed)); +} + +/* + * Read body of an archive entry into an archive_string object. + */ +static int +read_body_to_string(struct archive_read *a, struct tar *tar, + struct archive_string *as, const void *h, size_t *unconsumed) +{ + int64_t size; + const struct archive_entry_header_ustar *header; + const void *src; + + (void)tar; /* UNUSED */ + header = (const struct archive_entry_header_ustar *)h; + size = tar_atol(header->size, sizeof(header->size)); + if ((size > 1048576) || (size < 0)) { + archive_set_error(&a->archive, EINVAL, + "Special header too large"); + return (ARCHIVE_FATAL); + } + + /* Fail if we can't make our buffer big enough. */ + if (archive_string_ensure(as, (size_t)size+1) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory"); + return (ARCHIVE_FATAL); + } + + tar_flush_unconsumed(a, unconsumed); + + /* Read the body into the string. */ + *unconsumed = (size_t)((size + 511) & ~ 511); + src = __archive_read_ahead(a, *unconsumed, NULL); + if (src == NULL) { + *unconsumed = 0; + return (ARCHIVE_FATAL); + } + memcpy(as->s, src, (size_t)size); + as->s[size] = '\0'; + as->length = (size_t)size; + return (ARCHIVE_OK); +} + +/* + * Parse out common header elements. + * + * This would be the same as header_old_tar, except that the + * filename is handled slightly differently for old and POSIX + * entries (POSIX entries support a 'prefix'). This factoring + * allows header_old_tar and header_ustar + * to handle filenames differently, while still putting most of the + * common parsing into one place. + */ +static int +header_common(struct archive_read *a, struct tar *tar, + struct archive_entry *entry, const void *h) +{ + const struct archive_entry_header_ustar *header; + char tartype; + int err = ARCHIVE_OK; + + header = (const struct archive_entry_header_ustar *)h; + if (header->linkname[0]) + archive_strncpy(&(tar->entry_linkpath), + header->linkname, sizeof(header->linkname)); + else + archive_string_empty(&(tar->entry_linkpath)); + + /* Parse out the numeric fields (all are octal) */ + archive_entry_set_mode(entry, + (mode_t)tar_atol(header->mode, sizeof(header->mode))); + archive_entry_set_uid(entry, tar_atol(header->uid, sizeof(header->uid))); + archive_entry_set_gid(entry, tar_atol(header->gid, sizeof(header->gid))); + tar->entry_bytes_remaining = tar_atol(header->size, sizeof(header->size)); + if (tar->entry_bytes_remaining < 0) { + tar->entry_bytes_remaining = 0; + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Tar entry has negative size"); + return (ARCHIVE_FATAL); + } + if (tar->entry_bytes_remaining == INT64_MAX) { + /* Note: tar_atol returns INT64_MAX on overflow */ + tar->entry_bytes_remaining = 0; + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Tar entry size overflow"); + return (ARCHIVE_FATAL); + } + tar->realsize = tar->entry_bytes_remaining; + archive_entry_set_size(entry, tar->entry_bytes_remaining); + archive_entry_set_mtime(entry, tar_atol(header->mtime, sizeof(header->mtime)), 0); + + /* Handle the tar type flag appropriately. */ + tartype = header->typeflag[0]; + + switch (tartype) { + case '1': /* Hard link */ + if (archive_entry_copy_hardlink_l(entry, tar->entry_linkpath.s, + archive_strlen(&(tar->entry_linkpath)), tar->sconv) != 0) { + err = set_conversion_failed_error(a, tar->sconv, + "Linkname"); + if (err == ARCHIVE_FATAL) + return (err); + } + /* + * The following may seem odd, but: Technically, tar + * does not store the file type for a "hard link" + * entry, only the fact that it is a hard link. So, I + * leave the type zero normally. But, pax interchange + * format allows hard links to have data, which + * implies that the underlying entry is a regular + * file. + */ + if (archive_entry_size(entry) > 0) + archive_entry_set_filetype(entry, AE_IFREG); + + /* + * A tricky point: Traditionally, tar readers have + * ignored the size field when reading hardlink + * entries, and some writers put non-zero sizes even + * though the body is empty. POSIX blessed this + * convention in the 1988 standard, but broke with + * this tradition in 2001 by permitting hardlink + * entries to store valid bodies in pax interchange + * format, but not in ustar format. Since there is no + * hard and fast way to distinguish pax interchange + * from earlier archives (the 'x' and 'g' entries are + * optional, after all), we need a heuristic. + */ + if (archive_entry_size(entry) == 0) { + /* If the size is already zero, we're done. */ + } else if (a->archive.archive_format + == ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE) { + /* Definitely pax extended; must obey hardlink size. */ + } else if (a->archive.archive_format == ARCHIVE_FORMAT_TAR + || a->archive.archive_format == ARCHIVE_FORMAT_TAR_GNUTAR) + { + /* Old-style or GNU tar: we must ignore the size. */ + archive_entry_set_size(entry, 0); + tar->entry_bytes_remaining = 0; + } else if (archive_read_format_tar_bid(a, 50) > 50) { + /* + * We don't know if it's pax: If the bid + * function sees a valid ustar header + * immediately following, then let's ignore + * the hardlink size. + */ + archive_entry_set_size(entry, 0); + tar->entry_bytes_remaining = 0; + } + /* + * TODO: There are still two cases I'd like to handle: + * = a ustar non-pax archive with a hardlink entry at + * end-of-archive. (Look for block of nulls following?) + * = a pax archive that has not seen any pax headers + * and has an entry which is a hardlink entry storing + * a body containing an uncompressed tar archive. + * The first is worth addressing; I don't see any reliable + * way to deal with the second possibility. + */ + break; + case '2': /* Symlink */ + archive_entry_set_filetype(entry, AE_IFLNK); + archive_entry_set_size(entry, 0); + tar->entry_bytes_remaining = 0; + if (archive_entry_copy_symlink_l(entry, tar->entry_linkpath.s, + archive_strlen(&(tar->entry_linkpath)), tar->sconv) != 0) { + err = set_conversion_failed_error(a, tar->sconv, + "Linkname"); + if (err == ARCHIVE_FATAL) + return (err); + } + break; + case '3': /* Character device */ + archive_entry_set_filetype(entry, AE_IFCHR); + archive_entry_set_size(entry, 0); + tar->entry_bytes_remaining = 0; + break; + case '4': /* Block device */ + archive_entry_set_filetype(entry, AE_IFBLK); + archive_entry_set_size(entry, 0); + tar->entry_bytes_remaining = 0; + break; + case '5': /* Dir */ + archive_entry_set_filetype(entry, AE_IFDIR); + archive_entry_set_size(entry, 0); + tar->entry_bytes_remaining = 0; + break; + case '6': /* FIFO device */ + archive_entry_set_filetype(entry, AE_IFIFO); + archive_entry_set_size(entry, 0); + tar->entry_bytes_remaining = 0; + break; + case 'D': /* GNU incremental directory type */ + /* + * No special handling is actually required here. + * It might be nice someday to preprocess the file list and + * provide it to the client, though. + */ + archive_entry_set_filetype(entry, AE_IFDIR); + break; + case 'M': /* GNU "Multi-volume" (remainder of file from last archive)*/ + /* + * As far as I can tell, this is just like a regular file + * entry, except that the contents should be _appended_ to + * the indicated file at the indicated offset. This may + * require some API work to fully support. + */ + break; + case 'N': /* Old GNU "long filename" entry. */ + /* The body of this entry is a script for renaming + * previously-extracted entries. Ugh. It will never + * be supported by libarchive. */ + archive_entry_set_filetype(entry, AE_IFREG); + break; + case 'S': /* GNU sparse files */ + /* + * Sparse files are really just regular files with + * sparse information in the extended area. + */ + /* FALLTHROUGH */ + case '0': + /* + * Enable sparse file "read" support only for regular + * files and explicit GNU sparse files. However, we + * don't allow non-standard file types to be sparse. + */ + tar->sparse_allowed = 1; + /* FALLTHROUGH */ + default: /* Regular file and non-standard types */ + /* + * Per POSIX: non-recognized types should always be + * treated as regular files. + */ + archive_entry_set_filetype(entry, AE_IFREG); + break; + } + return (err); +} + +/* + * Parse out header elements for "old-style" tar archives. + */ +static int +header_old_tar(struct archive_read *a, struct tar *tar, + struct archive_entry *entry, const void *h) +{ + const struct archive_entry_header_ustar *header; + int err = ARCHIVE_OK, err2; + + /* Copy filename over (to ensure null termination). */ + header = (const struct archive_entry_header_ustar *)h; + if (archive_entry_copy_pathname_l(entry, + header->name, sizeof(header->name), tar->sconv) != 0) { + err = set_conversion_failed_error(a, tar->sconv, "Pathname"); + if (err == ARCHIVE_FATAL) + return (err); + } + + /* Grab rest of common fields */ + err2 = header_common(a, tar, entry, h); + if (err > err2) + err = err2; + + tar->entry_padding = 0x1ff & (-tar->entry_bytes_remaining); + return (err); +} + +/* + * Read a Mac AppleDouble-encoded blob of file metadata, + * if there is one. + */ +static int +read_mac_metadata_blob(struct archive_read *a, struct tar *tar, + struct archive_entry *entry, const void *h, size_t *unconsumed) +{ + int64_t size; + const void *data; + const char *p, *name; + const wchar_t *wp, *wname; + + (void)h; /* UNUSED */ + + wname = wp = archive_entry_pathname_w(entry); + if (wp != NULL) { + /* Find the last path element. */ + for (; *wp != L'\0'; ++wp) { + if (wp[0] == '/' && wp[1] != L'\0') + wname = wp + 1; + } + /* + * If last path element starts with "._", then + * this is a Mac extension. + */ + if (wname[0] != L'.' || wname[1] != L'_' || wname[2] == L'\0') + return ARCHIVE_OK; + } else { + /* Find the last path element. */ + name = p = archive_entry_pathname(entry); + if (p == NULL) + return (ARCHIVE_FAILED); + for (; *p != '\0'; ++p) { + if (p[0] == '/' && p[1] != '\0') + name = p + 1; + } + /* + * If last path element starts with "._", then + * this is a Mac extension. + */ + if (name[0] != '.' || name[1] != '_' || name[2] == '\0') + return ARCHIVE_OK; + } + + /* Read the body as a Mac OS metadata blob. */ + size = archive_entry_size(entry); + + /* + * TODO: Look beyond the body here to peek at the next header. + * If it's a regular header (not an extension header) + * that has the wrong name, just return the current + * entry as-is, without consuming the body here. + * That would reduce the risk of us mis-identifying + * an ordinary file that just happened to have + * a name starting with "._". + * + * Q: Is the above idea really possible? Even + * when there are GNU or pax extension entries? + */ + data = __archive_read_ahead(a, (size_t)size, NULL); + if (data == NULL) { + *unconsumed = 0; + return (ARCHIVE_FATAL); + } + archive_entry_copy_mac_metadata(entry, data, (size_t)size); + *unconsumed = (size_t)((size + 511) & ~ 511); + tar_flush_unconsumed(a, unconsumed); + return (tar_read_header(a, tar, entry, unconsumed)); +} + +/* + * Parse a file header for a pax extended archive entry. + */ +static int +header_pax_global(struct archive_read *a, struct tar *tar, + struct archive_entry *entry, const void *h, size_t *unconsumed) +{ + int err; + + err = read_body_to_string(a, tar, &(tar->pax_global), h, unconsumed); + if (err != ARCHIVE_OK) + return (err); + err = tar_read_header(a, tar, entry, unconsumed); + return (err); +} + +static int +header_pax_extensions(struct archive_read *a, struct tar *tar, + struct archive_entry *entry, const void *h, size_t *unconsumed) +{ + int err, err2; + + err = read_body_to_string(a, tar, &(tar->pax_header), h, unconsumed); + if (err != ARCHIVE_OK) + return (err); + + /* Parse the next header. */ + err = tar_read_header(a, tar, entry, unconsumed); + if ((err != ARCHIVE_OK) && (err != ARCHIVE_WARN)) + return (err); + + /* + * TODO: Parse global/default options into 'entry' struct here + * before handling file-specific options. + * + * This design (parse standard header, then overwrite with pax + * extended attribute data) usually works well, but isn't ideal; + * it would be better to parse the pax extended attributes first + * and then skip any fields in the standard header that were + * defined in the pax header. + */ + err2 = pax_header(a, tar, entry, &tar->pax_header); + err = err_combine(err, err2); + tar->entry_padding = 0x1ff & (-tar->entry_bytes_remaining); + return (err); +} + + +/* + * Parse a file header for a Posix "ustar" archive entry. This also + * handles "pax" or "extended ustar" entries. + */ +static int +header_ustar(struct archive_read *a, struct tar *tar, + struct archive_entry *entry, const void *h) +{ + const struct archive_entry_header_ustar *header; + struct archive_string *as; + int err = ARCHIVE_OK, r; + + header = (const struct archive_entry_header_ustar *)h; + + /* Copy name into an internal buffer to ensure null-termination. */ + as = &(tar->entry_pathname); + if (header->prefix[0]) { + archive_strncpy(as, header->prefix, sizeof(header->prefix)); + if (as->s[archive_strlen(as) - 1] != '/') + archive_strappend_char(as, '/'); + archive_strncat(as, header->name, sizeof(header->name)); + } else { + archive_strncpy(as, header->name, sizeof(header->name)); + } + if (archive_entry_copy_pathname_l(entry, as->s, archive_strlen(as), + tar->sconv) != 0) { + err = set_conversion_failed_error(a, tar->sconv, "Pathname"); + if (err == ARCHIVE_FATAL) + return (err); + } + + /* Handle rest of common fields. */ + r = header_common(a, tar, entry, h); + if (r == ARCHIVE_FATAL) + return (r); + if (r < err) + err = r; + + /* Handle POSIX ustar fields. */ + if (archive_entry_copy_uname_l(entry, + header->uname, sizeof(header->uname), tar->sconv) != 0) { + err = set_conversion_failed_error(a, tar->sconv, "Uname"); + if (err == ARCHIVE_FATAL) + return (err); + } + + if (archive_entry_copy_gname_l(entry, + header->gname, sizeof(header->gname), tar->sconv) != 0) { + err = set_conversion_failed_error(a, tar->sconv, "Gname"); + if (err == ARCHIVE_FATAL) + return (err); + } + + /* Parse out device numbers only for char and block specials. */ + if (header->typeflag[0] == '3' || header->typeflag[0] == '4') { + archive_entry_set_rdevmajor(entry, (dev_t) + tar_atol(header->rdevmajor, sizeof(header->rdevmajor))); + archive_entry_set_rdevminor(entry, (dev_t) + tar_atol(header->rdevminor, sizeof(header->rdevminor))); + } + + tar->entry_padding = 0x1ff & (-tar->entry_bytes_remaining); + + return (err); +} + + +/* + * Parse the pax extended attributes record. + * + * Returns non-zero if there's an error in the data. + */ +static int +pax_header(struct archive_read *a, struct tar *tar, + struct archive_entry *entry, struct archive_string *in_as) +{ + size_t attr_length, l, line_length, value_length; + char *p; + char *key, *value; + struct archive_string *as; + struct archive_string_conv *sconv; + int err, err2; + char *attr = in_as->s; + + attr_length = in_as->length; + tar->pax_hdrcharset_binary = 0; + archive_string_empty(&(tar->entry_gname)); + archive_string_empty(&(tar->entry_linkpath)); + archive_string_empty(&(tar->entry_pathname)); + archive_string_empty(&(tar->entry_pathname_override)); + archive_string_empty(&(tar->entry_uname)); + err = ARCHIVE_OK; + while (attr_length > 0) { + /* Parse decimal length field at start of line. */ + line_length = 0; + l = attr_length; + p = attr; /* Record start of line. */ + while (l>0) { + if (*p == ' ') { + p++; + l--; + break; + } + if (*p < '0' || *p > '9') { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Ignoring malformed pax extended attributes"); + return (ARCHIVE_WARN); + } + line_length *= 10; + line_length += *p - '0'; + if (line_length > 999999) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Rejecting pax extended attribute > 1MB"); + return (ARCHIVE_WARN); + } + p++; + l--; + } + + /* + * Parsed length must be no bigger than available data, + * at least 1, and the last character of the line must + * be '\n'. + */ + if (line_length > attr_length + || line_length < 1 + || attr[line_length - 1] != '\n') + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Ignoring malformed pax extended attribute"); + return (ARCHIVE_WARN); + } + + /* Null-terminate the line. */ + attr[line_length - 1] = '\0'; + + /* Find end of key and null terminate it. */ + key = p; + if (key[0] == '=') + return (-1); + while (*p && *p != '=') + ++p; + if (*p == '\0') { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid pax extended attributes"); + return (ARCHIVE_WARN); + } + *p = '\0'; + + value = p + 1; + + /* Some values may be binary data */ + value_length = attr + line_length - 1 - value; + + /* Identify this attribute and set it in the entry. */ + err2 = pax_attribute(a, tar, entry, key, value, value_length); + if (err2 == ARCHIVE_FATAL) + return (err2); + err = err_combine(err, err2); + + /* Skip to next line */ + attr += line_length; + attr_length -= line_length; + } + + /* + * PAX format uses UTF-8 as default charset for its metadata + * unless hdrcharset=BINARY is present in its header. + * We apply the charset specified by the hdrcharset option only + * when the hdrcharset attribute(in PAX header) is BINARY because + * we respect the charset described in PAX header and BINARY also + * means that metadata(filename,uname and gname) character-set + * is unknown. + */ + if (tar->pax_hdrcharset_binary) + sconv = tar->opt_sconv; + else { + sconv = archive_string_conversion_from_charset( + &(a->archive), "UTF-8", 1); + if (sconv == NULL) + return (ARCHIVE_FATAL); + if (tar->compat_2x) + archive_string_conversion_set_opt(sconv, + SCONV_SET_OPT_UTF8_LIBARCHIVE2X); + } + + if (archive_strlen(&(tar->entry_gname)) > 0) { + if (archive_entry_copy_gname_l(entry, tar->entry_gname.s, + archive_strlen(&(tar->entry_gname)), sconv) != 0) { + err = set_conversion_failed_error(a, sconv, "Gname"); + if (err == ARCHIVE_FATAL) + return (err); + /* Use a converted an original name. */ + archive_entry_copy_gname(entry, tar->entry_gname.s); + } + } + if (archive_strlen(&(tar->entry_linkpath)) > 0) { + if (archive_entry_copy_link_l(entry, tar->entry_linkpath.s, + archive_strlen(&(tar->entry_linkpath)), sconv) != 0) { + err = set_conversion_failed_error(a, sconv, "Linkname"); + if (err == ARCHIVE_FATAL) + return (err); + /* Use a converted an original name. */ + archive_entry_copy_link(entry, tar->entry_linkpath.s); + } + } + /* + * Some extensions (such as the GNU sparse file extensions) + * deliberately store a synthetic name under the regular 'path' + * attribute and the real file name under a different attribute. + * Since we're supposed to not care about the order, we + * have no choice but to store all of the various filenames + * we find and figure it all out afterwards. This is the + * figuring out part. + */ + as = NULL; + if (archive_strlen(&(tar->entry_pathname_override)) > 0) + as = &(tar->entry_pathname_override); + else if (archive_strlen(&(tar->entry_pathname)) > 0) + as = &(tar->entry_pathname); + if (as != NULL) { + if (archive_entry_copy_pathname_l(entry, as->s, + archive_strlen(as), sconv) != 0) { + err = set_conversion_failed_error(a, sconv, "Pathname"); + if (err == ARCHIVE_FATAL) + return (err); + /* Use a converted an original name. */ + archive_entry_copy_pathname(entry, as->s); + } + } + if (archive_strlen(&(tar->entry_uname)) > 0) { + if (archive_entry_copy_uname_l(entry, tar->entry_uname.s, + archive_strlen(&(tar->entry_uname)), sconv) != 0) { + err = set_conversion_failed_error(a, sconv, "Uname"); + if (err == ARCHIVE_FATAL) + return (err); + /* Use a converted an original name. */ + archive_entry_copy_uname(entry, tar->entry_uname.s); + } + } + return (err); +} + +static int +pax_attribute_xattr(struct archive_entry *entry, + const char *name, const char *value) +{ + char *name_decoded; + void *value_decoded; + size_t value_len; + + if (strlen(name) < 18 || (memcmp(name, "LIBARCHIVE.xattr.", 17)) != 0) + return 3; + + name += 17; + + /* URL-decode name */ + name_decoded = url_decode(name); + if (name_decoded == NULL) + return 2; + + /* Base-64 decode value */ + value_decoded = base64_decode(value, strlen(value), &value_len); + if (value_decoded == NULL) { + free(name_decoded); + return 1; + } + + archive_entry_xattr_add_entry(entry, name_decoded, + value_decoded, value_len); + + free(name_decoded); + free(value_decoded); + return 0; +} + +static int +pax_attribute_schily_xattr(struct archive_entry *entry, + const char *name, const char *value, size_t value_length) +{ + if (strlen(name) < 14 || (memcmp(name, "SCHILY.xattr.", 13)) != 0) + return 1; + + name += 13; + + archive_entry_xattr_add_entry(entry, name, value, value_length); + + return 0; +} + +static int +pax_attribute_acl(struct archive_read *a, struct tar *tar, + struct archive_entry *entry, const char *value, int type) +{ + int r; + const char* errstr; + + switch (type) { + case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: + errstr = "SCHILY.acl.access"; + break; + case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: + errstr = "SCHILY.acl.default"; + break; + case ARCHIVE_ENTRY_ACL_TYPE_NFS4: + errstr = "SCHILY.acl.ace"; + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Unknown ACL type: %d", type); + return(ARCHIVE_FATAL); + } + + if (tar->sconv_acl == NULL) { + tar->sconv_acl = + archive_string_conversion_from_charset( + &(a->archive), "UTF-8", 1); + if (tar->sconv_acl == NULL) + return (ARCHIVE_FATAL); + } + + r = archive_acl_from_text_l(archive_entry_acl(entry), value, type, + tar->sconv_acl); + if (r != ARCHIVE_OK) { + if (r == ARCHIVE_FATAL) { + archive_set_error(&a->archive, ENOMEM, + "%s %s", "Can't allocate memory for ", + errstr); + return (r); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, "%s %s", "Parse error: ", errstr); + } + return (r); +} + +/* + * Parse a single key=value attribute. key/value pointers are + * assumed to point into reasonably long-lived storage. + * + * Note that POSIX reserves all-lowercase keywords. Vendor-specific + * extensions should always have keywords of the form "VENDOR.attribute" + * In particular, it's quite feasible to support many different + * vendor extensions here. I'm using "LIBARCHIVE" for extensions + * unique to this library. + * + * Investigate other vendor-specific extensions and see if + * any of them look useful. + */ +static int +pax_attribute(struct archive_read *a, struct tar *tar, + struct archive_entry *entry, const char *key, const char *value, size_t value_length) +{ + int64_t s; + long n; + int err = ARCHIVE_OK, r; + + if (value == NULL) + value = ""; /* Disable compiler warning; do not pass + * NULL pointer to strlen(). */ + switch (key[0]) { + case 'G': + /* Reject GNU.sparse.* headers on non-regular files. */ + if (strncmp(key, "GNU.sparse", 10) == 0 && + !tar->sparse_allowed) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Non-regular file cannot be sparse"); + return (ARCHIVE_FATAL); + } + + /* GNU "0.0" sparse pax format. */ + if (strcmp(key, "GNU.sparse.numblocks") == 0) { + tar->sparse_offset = -1; + tar->sparse_numbytes = -1; + tar->sparse_gnu_major = 0; + tar->sparse_gnu_minor = 0; + } + if (strcmp(key, "GNU.sparse.offset") == 0) { + tar->sparse_offset = tar_atol10(value, strlen(value)); + if (tar->sparse_numbytes != -1) { + if (gnu_add_sparse_entry(a, tar, + tar->sparse_offset, tar->sparse_numbytes) + != ARCHIVE_OK) + return (ARCHIVE_FATAL); + tar->sparse_offset = -1; + tar->sparse_numbytes = -1; + } + } + if (strcmp(key, "GNU.sparse.numbytes") == 0) { + tar->sparse_numbytes = tar_atol10(value, strlen(value)); + if (tar->sparse_numbytes != -1) { + if (gnu_add_sparse_entry(a, tar, + tar->sparse_offset, tar->sparse_numbytes) + != ARCHIVE_OK) + return (ARCHIVE_FATAL); + tar->sparse_offset = -1; + tar->sparse_numbytes = -1; + } + } + if (strcmp(key, "GNU.sparse.size") == 0) { + tar->realsize = tar_atol10(value, strlen(value)); + archive_entry_set_size(entry, tar->realsize); + tar->realsize_override = 1; + } + + /* GNU "0.1" sparse pax format. */ + if (strcmp(key, "GNU.sparse.map") == 0) { + tar->sparse_gnu_major = 0; + tar->sparse_gnu_minor = 1; + if (gnu_sparse_01_parse(a, tar, value) != ARCHIVE_OK) + return (ARCHIVE_WARN); + } + + /* GNU "1.0" sparse pax format */ + if (strcmp(key, "GNU.sparse.major") == 0) { + tar->sparse_gnu_major = (int)tar_atol10(value, strlen(value)); + tar->sparse_gnu_pending = 1; + } + if (strcmp(key, "GNU.sparse.minor") == 0) { + tar->sparse_gnu_minor = (int)tar_atol10(value, strlen(value)); + tar->sparse_gnu_pending = 1; + } + if (strcmp(key, "GNU.sparse.name") == 0) { + /* + * The real filename; when storing sparse + * files, GNU tar puts a synthesized name into + * the regular 'path' attribute in an attempt + * to limit confusion. ;-) + */ + archive_strcpy(&(tar->entry_pathname_override), value); + } + if (strcmp(key, "GNU.sparse.realsize") == 0) { + tar->realsize = tar_atol10(value, strlen(value)); + archive_entry_set_size(entry, tar->realsize); + tar->realsize_override = 1; + } + break; + case 'L': + /* Our extensions */ +/* TODO: Handle arbitrary extended attributes... */ +/* + if (strcmp(key, "LIBARCHIVE.xxxxxxx") == 0) + archive_entry_set_xxxxxx(entry, value); +*/ + if (strcmp(key, "LIBARCHIVE.creationtime") == 0) { + pax_time(value, &s, &n); + archive_entry_set_birthtime(entry, s, n); + } + if (strcmp(key, "LIBARCHIVE.symlinktype") == 0) { + if (strcmp(value, "file") == 0) { + archive_entry_set_symlink_type(entry, + AE_SYMLINK_TYPE_FILE); + } else if (strcmp(value, "dir") == 0) { + archive_entry_set_symlink_type(entry, + AE_SYMLINK_TYPE_DIRECTORY); + } + } + if (memcmp(key, "LIBARCHIVE.xattr.", 17) == 0) + pax_attribute_xattr(entry, key, value); + break; + case 'S': + /* We support some keys used by the "star" archiver */ + if (strcmp(key, "SCHILY.acl.access") == 0) { + r = pax_attribute_acl(a, tar, entry, value, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + if (r == ARCHIVE_FATAL) + return (r); + } else if (strcmp(key, "SCHILY.acl.default") == 0) { + r = pax_attribute_acl(a, tar, entry, value, + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT); + if (r == ARCHIVE_FATAL) + return (r); + } else if (strcmp(key, "SCHILY.acl.ace") == 0) { + r = pax_attribute_acl(a, tar, entry, value, + ARCHIVE_ENTRY_ACL_TYPE_NFS4); + if (r == ARCHIVE_FATAL) + return (r); + } else if (strcmp(key, "SCHILY.devmajor") == 0) { + archive_entry_set_rdevmajor(entry, + (dev_t)tar_atol10(value, strlen(value))); + } else if (strcmp(key, "SCHILY.devminor") == 0) { + archive_entry_set_rdevminor(entry, + (dev_t)tar_atol10(value, strlen(value))); + } else if (strcmp(key, "SCHILY.fflags") == 0) { + archive_entry_copy_fflags_text(entry, value); + } else if (strcmp(key, "SCHILY.dev") == 0) { + archive_entry_set_dev(entry, + (dev_t)tar_atol10(value, strlen(value))); + } else if (strcmp(key, "SCHILY.ino") == 0) { + archive_entry_set_ino(entry, + tar_atol10(value, strlen(value))); + } else if (strcmp(key, "SCHILY.nlink") == 0) { + archive_entry_set_nlink(entry, (unsigned) + tar_atol10(value, strlen(value))); + } else if (strcmp(key, "SCHILY.realsize") == 0) { + tar->realsize = tar_atol10(value, strlen(value)); + tar->realsize_override = 1; + archive_entry_set_size(entry, tar->realsize); + } else if (strncmp(key, "SCHILY.xattr.", 13) == 0) { + pax_attribute_schily_xattr(entry, key, value, + value_length); + } else if (strcmp(key, "SUN.holesdata") == 0) { + /* A Solaris extension for sparse. */ + r = solaris_sparse_parse(a, tar, entry, value); + if (r < err) { + if (r == ARCHIVE_FATAL) + return (r); + err = r; + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Parse error: SUN.holesdata"); + } + } + break; + case 'a': + if (strcmp(key, "atime") == 0) { + pax_time(value, &s, &n); + archive_entry_set_atime(entry, s, n); + } + break; + case 'c': + if (strcmp(key, "ctime") == 0) { + pax_time(value, &s, &n); + archive_entry_set_ctime(entry, s, n); + } else if (strcmp(key, "charset") == 0) { + /* TODO: Publish charset information in entry. */ + } else if (strcmp(key, "comment") == 0) { + /* TODO: Publish comment in entry. */ + } + break; + case 'g': + if (strcmp(key, "gid") == 0) { + archive_entry_set_gid(entry, + tar_atol10(value, strlen(value))); + } else if (strcmp(key, "gname") == 0) { + archive_strcpy(&(tar->entry_gname), value); + } + break; + case 'h': + if (strcmp(key, "hdrcharset") == 0) { + if (strcmp(value, "BINARY") == 0) + /* Binary mode. */ + tar->pax_hdrcharset_binary = 1; + else if (strcmp(value, "ISO-IR 10646 2000 UTF-8") == 0) + tar->pax_hdrcharset_binary = 0; + } + break; + case 'l': + /* pax interchange doesn't distinguish hardlink vs. symlink. */ + if (strcmp(key, "linkpath") == 0) { + archive_strcpy(&(tar->entry_linkpath), value); + } + break; + case 'm': + if (strcmp(key, "mtime") == 0) { + pax_time(value, &s, &n); + archive_entry_set_mtime(entry, s, n); + } + break; + case 'p': + if (strcmp(key, "path") == 0) { + archive_strcpy(&(tar->entry_pathname), value); + } + break; + case 'r': + /* POSIX has reserved 'realtime.*' */ + break; + case 's': + /* POSIX has reserved 'security.*' */ + /* Someday: if (strcmp(key, "security.acl") == 0) { ... } */ + if (strcmp(key, "size") == 0) { + /* "size" is the size of the data in the entry. */ + tar->entry_bytes_remaining + = tar_atol10(value, strlen(value)); + /* + * The "size" pax header keyword always overrides the + * "size" field in the tar header. + * GNU.sparse.realsize, GNU.sparse.size and + * SCHILY.realsize override this value. + */ + if (!tar->realsize_override) { + archive_entry_set_size(entry, + tar->entry_bytes_remaining); + tar->realsize + = tar->entry_bytes_remaining; + } + } + break; + case 'u': + if (strcmp(key, "uid") == 0) { + archive_entry_set_uid(entry, + tar_atol10(value, strlen(value))); + } else if (strcmp(key, "uname") == 0) { + archive_strcpy(&(tar->entry_uname), value); + } + break; + } + return (err); +} + + + +/* + * parse a decimal time value, which may include a fractional portion + */ +static void +pax_time(const char *p, int64_t *ps, long *pn) +{ + char digit; + int64_t s; + unsigned long l; + int sign; + int64_t limit, last_digit_limit; + + limit = INT64_MAX / 10; + last_digit_limit = INT64_MAX % 10; + + s = 0; + sign = 1; + if (*p == '-') { + sign = -1; + p++; + } + while (*p >= '0' && *p <= '9') { + digit = *p - '0'; + if (s > limit || + (s == limit && digit > last_digit_limit)) { + s = INT64_MAX; + break; + } + s = (s * 10) + digit; + ++p; + } + + *ps = s * sign; + + /* Calculate nanoseconds. */ + *pn = 0; + + if (*p != '.') + return; + + l = 100000000UL; + do { + ++p; + if (*p >= '0' && *p <= '9') + *pn += (*p - '0') * l; + else + break; + } while (l /= 10); +} + +/* + * Parse GNU tar header + */ +static int +header_gnutar(struct archive_read *a, struct tar *tar, + struct archive_entry *entry, const void *h, size_t *unconsumed) +{ + const struct archive_entry_header_gnutar *header; + int64_t t; + int err = ARCHIVE_OK; + + /* + * GNU header is like POSIX ustar, except 'prefix' is + * replaced with some other fields. This also means the + * filename is stored as in old-style archives. + */ + + /* Grab fields common to all tar variants. */ + err = header_common(a, tar, entry, h); + if (err == ARCHIVE_FATAL) + return (err); + + /* Copy filename over (to ensure null termination). */ + header = (const struct archive_entry_header_gnutar *)h; + if (archive_entry_copy_pathname_l(entry, + header->name, sizeof(header->name), tar->sconv) != 0) { + err = set_conversion_failed_error(a, tar->sconv, "Pathname"); + if (err == ARCHIVE_FATAL) + return (err); + } + + /* Fields common to ustar and GNU */ + /* XXX Can the following be factored out since it's common + * to ustar and gnu tar? Is it okay to move it down into + * header_common, perhaps? */ + if (archive_entry_copy_uname_l(entry, + header->uname, sizeof(header->uname), tar->sconv) != 0) { + err = set_conversion_failed_error(a, tar->sconv, "Uname"); + if (err == ARCHIVE_FATAL) + return (err); + } + + if (archive_entry_copy_gname_l(entry, + header->gname, sizeof(header->gname), tar->sconv) != 0) { + err = set_conversion_failed_error(a, tar->sconv, "Gname"); + if (err == ARCHIVE_FATAL) + return (err); + } + + /* Parse out device numbers only for char and block specials */ + if (header->typeflag[0] == '3' || header->typeflag[0] == '4') { + archive_entry_set_rdevmajor(entry, (dev_t) + tar_atol(header->rdevmajor, sizeof(header->rdevmajor))); + archive_entry_set_rdevminor(entry, (dev_t) + tar_atol(header->rdevminor, sizeof(header->rdevminor))); + } else + archive_entry_set_rdev(entry, 0); + + tar->entry_padding = 0x1ff & (-tar->entry_bytes_remaining); + + /* Grab GNU-specific fields. */ + t = tar_atol(header->atime, sizeof(header->atime)); + if (t > 0) + archive_entry_set_atime(entry, t, 0); + t = tar_atol(header->ctime, sizeof(header->ctime)); + if (t > 0) + archive_entry_set_ctime(entry, t, 0); + + if (header->realsize[0] != 0) { + tar->realsize + = tar_atol(header->realsize, sizeof(header->realsize)); + archive_entry_set_size(entry, tar->realsize); + tar->realsize_override = 1; + } + + if (header->sparse[0].offset[0] != 0) { + if (gnu_sparse_old_read(a, tar, header, unconsumed) + != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } else { + if (header->isextended[0] != 0) { + /* XXX WTF? XXX */ + } + } + + return (err); +} + +static int +gnu_add_sparse_entry(struct archive_read *a, struct tar *tar, + int64_t offset, int64_t remaining) +{ + struct sparse_block *p; + + p = (struct sparse_block *)calloc(1, sizeof(*p)); + if (p == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + if (tar->sparse_last != NULL) + tar->sparse_last->next = p; + else + tar->sparse_list = p; + tar->sparse_last = p; + if (remaining < 0 || offset < 0 || offset > INT64_MAX - remaining) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Malformed sparse map data"); + return (ARCHIVE_FATAL); + } + p->offset = offset; + p->remaining = remaining; + return (ARCHIVE_OK); +} + +static void +gnu_clear_sparse_list(struct tar *tar) +{ + struct sparse_block *p; + + while (tar->sparse_list != NULL) { + p = tar->sparse_list; + tar->sparse_list = p->next; + free(p); + } + tar->sparse_last = NULL; +} + +/* + * GNU tar old-format sparse data. + * + * GNU old-format sparse data is stored in a fixed-field + * format. Offset/size values are 11-byte octal fields (same + * format as 'size' field in ustart header). These are + * stored in the header, allocating subsequent header blocks + * as needed. Extending the header in this way is a pretty + * severe POSIX violation; this design has earned GNU tar a + * lot of criticism. + */ + +static int +gnu_sparse_old_read(struct archive_read *a, struct tar *tar, + const struct archive_entry_header_gnutar *header, size_t *unconsumed) +{ + ssize_t bytes_read; + const void *data; + struct extended { + struct gnu_sparse sparse[21]; + char isextended[1]; + char padding[7]; + }; + const struct extended *ext; + + if (gnu_sparse_old_parse(a, tar, header->sparse, 4) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + if (header->isextended[0] == 0) + return (ARCHIVE_OK); + + do { + tar_flush_unconsumed(a, unconsumed); + data = __archive_read_ahead(a, 512, &bytes_read); + if (bytes_read < 0) + return (ARCHIVE_FATAL); + if (bytes_read < 512) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated tar archive " + "detected while reading sparse file data"); + return (ARCHIVE_FATAL); + } + *unconsumed = 512; + ext = (const struct extended *)data; + if (gnu_sparse_old_parse(a, tar, ext->sparse, 21) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } while (ext->isextended[0] != 0); + if (tar->sparse_list != NULL) + tar->entry_offset = tar->sparse_list->offset; + return (ARCHIVE_OK); +} + +static int +gnu_sparse_old_parse(struct archive_read *a, struct tar *tar, + const struct gnu_sparse *sparse, int length) +{ + while (length > 0 && sparse->offset[0] != 0) { + if (gnu_add_sparse_entry(a, tar, + tar_atol(sparse->offset, sizeof(sparse->offset)), + tar_atol(sparse->numbytes, sizeof(sparse->numbytes))) + != ARCHIVE_OK) + return (ARCHIVE_FATAL); + sparse++; + length--; + } + return (ARCHIVE_OK); +} + +/* + * GNU tar sparse format 0.0 + * + * Beginning with GNU tar 1.15, sparse files are stored using + * information in the pax extended header. The GNU tar maintainers + * have gone through a number of variations in the process of working + * out this scheme; fortunately, they're all numbered. + * + * Sparse format 0.0 uses attribute GNU.sparse.numblocks to store the + * number of blocks, and GNU.sparse.offset/GNU.sparse.numbytes to + * store offset/size for each block. The repeated instances of these + * latter fields violate the pax specification (which frowns on + * duplicate keys), so this format was quickly replaced. + */ + +/* + * GNU tar sparse format 0.1 + * + * This version replaced the offset/numbytes attributes with + * a single "map" attribute that stored a list of integers. This + * format had two problems: First, the "map" attribute could be very + * long, which caused problems for some implementations. More + * importantly, the sparse data was lost when extracted by archivers + * that didn't recognize this extension. + */ + +static int +gnu_sparse_01_parse(struct archive_read *a, struct tar *tar, const char *p) +{ + const char *e; + int64_t offset = -1, size = -1; + + for (;;) { + e = p; + while (*e != '\0' && *e != ',') { + if (*e < '0' || *e > '9') + return (ARCHIVE_WARN); + e++; + } + if (offset < 0) { + offset = tar_atol10(p, e - p); + if (offset < 0) + return (ARCHIVE_WARN); + } else { + size = tar_atol10(p, e - p); + if (size < 0) + return (ARCHIVE_WARN); + if (gnu_add_sparse_entry(a, tar, offset, size) + != ARCHIVE_OK) + return (ARCHIVE_FATAL); + offset = -1; + } + if (*e == '\0') + return (ARCHIVE_OK); + p = e + 1; + } +} + +/* + * GNU tar sparse format 1.0 + * + * The idea: The offset/size data is stored as a series of base-10 + * ASCII numbers prepended to the file data, so that dearchivers that + * don't support this format will extract the block map along with the + * data and a separate post-process can restore the sparseness. + * + * Unfortunately, GNU tar 1.16 had a bug that added unnecessary + * padding to the body of the file when using this format. GNU tar + * 1.17 corrected this bug without bumping the version number, so + * it's not possible to support both variants. This code supports + * the later variant at the expense of not supporting the former. + * + * This variant also replaced GNU.sparse.size with GNU.sparse.realsize + * and introduced the GNU.sparse.major/GNU.sparse.minor attributes. + */ + +/* + * Read the next line from the input, and parse it as a decimal + * integer followed by '\n'. Returns positive integer value or + * negative on error. + */ +static int64_t +gnu_sparse_10_atol(struct archive_read *a, struct tar *tar, + int64_t *remaining, size_t *unconsumed) +{ + int64_t l, limit, last_digit_limit; + const char *p; + ssize_t bytes_read; + int base, digit; + + base = 10; + limit = INT64_MAX / base; + last_digit_limit = INT64_MAX % base; + + /* + * Skip any lines starting with '#'; GNU tar specs + * don't require this, but they should. + */ + do { + bytes_read = readline(a, tar, &p, + (ssize_t)tar_min(*remaining, 100), unconsumed); + if (bytes_read <= 0) + return (ARCHIVE_FATAL); + *remaining -= bytes_read; + } while (p[0] == '#'); + + l = 0; + while (bytes_read > 0) { + if (*p == '\n') + return (l); + if (*p < '0' || *p >= '0' + base) + return (ARCHIVE_WARN); + digit = *p - '0'; + if (l > limit || (l == limit && digit > last_digit_limit)) + l = INT64_MAX; /* Truncate on overflow. */ + else + l = (l * base) + digit; + p++; + bytes_read--; + } + /* TODO: Error message. */ + return (ARCHIVE_WARN); +} + +/* + * Returns length (in bytes) of the sparse data description + * that was read. + */ +static ssize_t +gnu_sparse_10_read(struct archive_read *a, struct tar *tar, size_t *unconsumed) +{ + ssize_t bytes_read; + int entries; + int64_t offset, size, to_skip, remaining; + + /* Clear out the existing sparse list. */ + gnu_clear_sparse_list(tar); + + remaining = tar->entry_bytes_remaining; + + /* Parse entries. */ + entries = (int)gnu_sparse_10_atol(a, tar, &remaining, unconsumed); + if (entries < 0) + return (ARCHIVE_FATAL); + /* Parse the individual entries. */ + while (entries-- > 0) { + /* Parse offset/size */ + offset = gnu_sparse_10_atol(a, tar, &remaining, unconsumed); + if (offset < 0) + return (ARCHIVE_FATAL); + size = gnu_sparse_10_atol(a, tar, &remaining, unconsumed); + if (size < 0) + return (ARCHIVE_FATAL); + /* Add a new sparse entry. */ + if (gnu_add_sparse_entry(a, tar, offset, size) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + /* Skip rest of block... */ + tar_flush_unconsumed(a, unconsumed); + bytes_read = (ssize_t)(tar->entry_bytes_remaining - remaining); + to_skip = 0x1ff & -bytes_read; + /* Fail if tar->entry_bytes_remaing would get negative */ + if (to_skip > remaining) + return (ARCHIVE_FATAL); + if (to_skip != __archive_read_consume(a, to_skip)) + return (ARCHIVE_FATAL); + return ((ssize_t)(bytes_read + to_skip)); +} + +/* + * Solaris pax extension for a sparse file. This is recorded with the + * data and hole pairs. The way recording sparse information by Solaris' + * pax simply indicates where data and sparse are, so the stored contents + * consist of both data and hole. + */ +static int +solaris_sparse_parse(struct archive_read *a, struct tar *tar, + struct archive_entry *entry, const char *p) +{ + const char *e; + int64_t start, end; + int hole = 1; + + (void)entry; /* UNUSED */ + + end = 0; + if (*p == ' ') + p++; + else + return (ARCHIVE_WARN); + for (;;) { + e = p; + while (*e != '\0' && *e != ' ') { + if (*e < '0' || *e > '9') + return (ARCHIVE_WARN); + e++; + } + start = end; + end = tar_atol10(p, e - p); + if (end < 0) + return (ARCHIVE_WARN); + if (start < end) { + if (gnu_add_sparse_entry(a, tar, start, + end - start) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + tar->sparse_last->hole = hole; + } + if (*e == '\0') + return (ARCHIVE_OK); + p = e + 1; + hole = hole == 0; + } +} + +/*- + * Convert text->integer. + * + * Traditional tar formats (including POSIX) specify base-8 for + * all of the standard numeric fields. This is a significant limitation + * in practice: + * = file size is limited to 8GB + * = rdevmajor and rdevminor are limited to 21 bits + * = uid/gid are limited to 21 bits + * + * There are two workarounds for this: + * = pax extended headers, which use variable-length string fields + * = GNU tar and STAR both allow either base-8 or base-256 in + * most fields. The high bit is set to indicate base-256. + * + * On read, this implementation supports both extensions. + */ +static int64_t +tar_atol(const char *p, size_t char_cnt) +{ + /* + * Technically, GNU tar considers a field to be in base-256 + * only if the first byte is 0xff or 0x80. + */ + if (*p & 0x80) + return (tar_atol256(p, char_cnt)); + return (tar_atol8(p, char_cnt)); +} + +/* + * Note that this implementation does not (and should not!) obey + * locale settings; you cannot simply substitute strtol here, since + * it does obey locale. + */ +static int64_t +tar_atol_base_n(const char *p, size_t char_cnt, int base) +{ + int64_t l, maxval, limit, last_digit_limit; + int digit, sign; + + maxval = INT64_MAX; + limit = INT64_MAX / base; + last_digit_limit = INT64_MAX % base; + + /* the pointer will not be dereferenced if char_cnt is zero + * due to the way the && operator is evaluated. + */ + while (char_cnt != 0 && (*p == ' ' || *p == '\t')) { + p++; + char_cnt--; + } + + sign = 1; + if (char_cnt != 0 && *p == '-') { + sign = -1; + p++; + char_cnt--; + + maxval = INT64_MIN; + limit = -(INT64_MIN / base); + last_digit_limit = INT64_MIN % base; + } + + l = 0; + if (char_cnt != 0) { + digit = *p - '0'; + while (digit >= 0 && digit < base && char_cnt != 0) { + if (l>limit || (l == limit && digit > last_digit_limit)) { + return maxval; /* Truncate on overflow. */ + } + l = (l * base) + digit; + digit = *++p - '0'; + char_cnt--; + } + } + return (sign < 0) ? -l : l; +} + +static int64_t +tar_atol8(const char *p, size_t char_cnt) +{ + return tar_atol_base_n(p, char_cnt, 8); +} + +static int64_t +tar_atol10(const char *p, size_t char_cnt) +{ + return tar_atol_base_n(p, char_cnt, 10); +} + +/* + * Parse a base-256 integer. This is just a variable-length + * twos-complement signed binary value in big-endian order, except + * that the high-order bit is ignored. The values here can be up to + * 12 bytes, so we need to be careful about overflowing 64-bit + * (8-byte) integers. + * + * This code unashamedly assumes that the local machine uses 8-bit + * bytes and twos-complement arithmetic. + */ +static int64_t +tar_atol256(const char *_p, size_t char_cnt) +{ + uint64_t l; + const unsigned char *p = (const unsigned char *)_p; + unsigned char c, neg; + + /* Extend 7-bit 2s-comp to 8-bit 2s-comp, decide sign. */ + c = *p; + if (c & 0x40) { + neg = 0xff; + c |= 0x80; + l = ~ARCHIVE_LITERAL_ULL(0); + } else { + neg = 0; + c &= 0x7f; + l = 0; + } + + /* If more than 8 bytes, check that we can ignore + * high-order bits without overflow. */ + while (char_cnt > sizeof(int64_t)) { + --char_cnt; + if (c != neg) + return neg ? INT64_MIN : INT64_MAX; + c = *++p; + } + + /* c is first byte that fits; if sign mismatch, return overflow */ + if ((c ^ neg) & 0x80) { + return neg ? INT64_MIN : INT64_MAX; + } + + /* Accumulate remaining bytes. */ + while (--char_cnt > 0) { + l = (l << 8) | c; + c = *++p; + } + l = (l << 8) | c; + /* Return signed twos-complement value. */ + return (int64_t)(l); +} + +/* + * Returns length of line (including trailing newline) + * or negative on error. 'start' argument is updated to + * point to first character of line. This avoids copying + * when possible. + */ +static ssize_t +readline(struct archive_read *a, struct tar *tar, const char **start, + ssize_t limit, size_t *unconsumed) +{ + ssize_t bytes_read; + ssize_t total_size = 0; + const void *t; + const char *s; + void *p; + + tar_flush_unconsumed(a, unconsumed); + + t = __archive_read_ahead(a, 1, &bytes_read); + if (bytes_read <= 0) + return (ARCHIVE_FATAL); + s = t; /* Start of line? */ + p = memchr(t, '\n', bytes_read); + /* If we found '\n' in the read buffer, return pointer to that. */ + if (p != NULL) { + bytes_read = 1 + ((const char *)p) - s; + if (bytes_read > limit) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Line too long"); + return (ARCHIVE_FATAL); + } + *unconsumed = bytes_read; + *start = s; + return (bytes_read); + } + *unconsumed = bytes_read; + /* Otherwise, we need to accumulate in a line buffer. */ + for (;;) { + if (total_size + bytes_read > limit) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Line too long"); + return (ARCHIVE_FATAL); + } + if (archive_string_ensure(&tar->line, total_size + bytes_read) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate working buffer"); + return (ARCHIVE_FATAL); + } + memcpy(tar->line.s + total_size, t, bytes_read); + tar_flush_unconsumed(a, unconsumed); + total_size += bytes_read; + /* If we found '\n', clean up and return. */ + if (p != NULL) { + *start = tar->line.s; + return (total_size); + } + /* Read some more. */ + t = __archive_read_ahead(a, 1, &bytes_read); + if (bytes_read <= 0) + return (ARCHIVE_FATAL); + s = t; /* Start of line? */ + p = memchr(t, '\n', bytes_read); + /* If we found '\n', trim the read. */ + if (p != NULL) { + bytes_read = 1 + ((const char *)p) - s; + } + *unconsumed = bytes_read; + } +} + +/* + * base64_decode - Base64 decode + * + * This accepts most variations of base-64 encoding, including: + * * with or without line breaks + * * with or without the final group padded with '=' or '_' characters + * (The most economical Base-64 variant does not pad the last group and + * omits line breaks; RFC1341 used for MIME requires both.) + */ +static char * +base64_decode(const char *s, size_t len, size_t *out_len) +{ + static const unsigned char digits[64] = { + 'A','B','C','D','E','F','G','H','I','J','K','L','M','N', + 'O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b', + 'c','d','e','f','g','h','i','j','k','l','m','n','o','p', + 'q','r','s','t','u','v','w','x','y','z','0','1','2','3', + '4','5','6','7','8','9','+','/' }; + static unsigned char decode_table[128]; + char *out, *d; + const unsigned char *src = (const unsigned char *)s; + + /* If the decode table is not yet initialized, prepare it. */ + if (decode_table[digits[1]] != 1) { + unsigned i; + memset(decode_table, 0xff, sizeof(decode_table)); + for (i = 0; i < sizeof(digits); i++) + decode_table[digits[i]] = i; + } + + /* Allocate enough space to hold the entire output. */ + /* Note that we may not use all of this... */ + out = (char *)malloc(len - len / 4 + 1); + if (out == NULL) { + *out_len = 0; + return (NULL); + } + d = out; + + while (len > 0) { + /* Collect the next group of (up to) four characters. */ + int v = 0; + int group_size = 0; + while (group_size < 4 && len > 0) { + /* '=' or '_' padding indicates final group. */ + if (*src == '=' || *src == '_') { + len = 0; + break; + } + /* Skip illegal characters (including line breaks) */ + if (*src > 127 || *src < 32 + || decode_table[*src] == 0xff) { + len--; + src++; + continue; + } + v <<= 6; + v |= decode_table[*src++]; + len --; + group_size++; + } + /* Align a short group properly. */ + v <<= 6 * (4 - group_size); + /* Unpack the group we just collected. */ + switch (group_size) { + case 4: d[2] = v & 0xff; + /* FALLTHROUGH */ + case 3: d[1] = (v >> 8) & 0xff; + /* FALLTHROUGH */ + case 2: d[0] = (v >> 16) & 0xff; + break; + case 1: /* this is invalid! */ + break; + } + d += group_size * 3 / 4; + } + + *out_len = d - out; + return (out); +} + +static char * +url_decode(const char *in) +{ + char *out, *d; + const char *s; + + out = (char *)malloc(strlen(in) + 1); + if (out == NULL) + return (NULL); + for (s = in, d = out; *s != '\0'; ) { + if (s[0] == '%' && s[1] != '\0' && s[2] != '\0') { + /* Try to convert % escape */ + int digit1 = tohex(s[1]); + int digit2 = tohex(s[2]); + if (digit1 >= 0 && digit2 >= 0) { + /* Looks good, consume three chars */ + s += 3; + /* Convert output */ + *d++ = ((digit1 << 4) | digit2); + continue; + } + /* Else fall through and treat '%' as normal char */ + } + *d++ = *s++; + } + *d = '\0'; + return (out); +} + +static int +tohex(int c) +{ + if (c >= '0' && c <= '9') + return (c - '0'); + else if (c >= 'A' && c <= 'F') + return (c - 'A' + 10); + else if (c >= 'a' && c <= 'f') + return (c - 'a' + 10); + else + return (-1); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_warc.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_warc.c new file mode 100644 index 0000000..72977b8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_warc.c @@ -0,0 +1,832 @@ +/*- + * Copyright (c) 2014 Sebastian Freundt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +/** + * WARC is standardised by ISO TC46/SC4/WG12 and currently available as + * ISO 28500:2009. + * For the purposes of this file we used the final draft from: + * http://bibnum.bnf.fr/warc/WARC_ISO_28500_version1_latestdraft.pdf + * + * Todo: + * [ ] real-world warcs can contain resources at endpoints ending in / + * e.g. http://bibnum.bnf.fr/warc/ + * if you're lucky their response contains a Content-Location: header + * pointing to a unix-compliant filename, in the example above it's + * Content-Location: http://bibnum.bnf.fr/warc/index.html + * however, that's not mandated and github for example doesn't follow + * this convention. + * We need a set of archive options to control what to do with + * entries like these, at the moment care is taken to skip them. + * + **/ + +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_CTYPE_H +#include +#endif +#ifdef HAVE_TIME_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_read_private.h" + +typedef enum { + WT_NONE, + /* warcinfo */ + WT_INFO, + /* metadata */ + WT_META, + /* resource */ + WT_RSRC, + /* request, unsupported */ + WT_REQ, + /* response, unsupported */ + WT_RSP, + /* revisit, unsupported */ + WT_RVIS, + /* conversion, unsupported */ + WT_CONV, + /* continuation, unsupported at the moment */ + WT_CONT, + /* invalid type */ + LAST_WT +} warc_type_t; + +typedef struct { + size_t len; + const char *str; +} warc_string_t; + +typedef struct { + size_t len; + char *str; +} warc_strbuf_t; + +struct warc_s { + /* content length ahead */ + size_t cntlen; + /* and how much we've processed so far */ + size_t cntoff; + /* and how much we need to consume between calls */ + size_t unconsumed; + + /* string pool */ + warc_strbuf_t pool; + /* previous version */ + unsigned int pver; + /* stringified format name */ + struct archive_string sver; +}; + +static int _warc_bid(struct archive_read *a, int); +static int _warc_cleanup(struct archive_read *a); +static int _warc_read(struct archive_read*, const void**, size_t*, int64_t*); +static int _warc_skip(struct archive_read *a); +static int _warc_rdhdr(struct archive_read *a, struct archive_entry *e); + +/* private routines */ +static unsigned int _warc_rdver(const char buf[10], size_t bsz); +static unsigned int _warc_rdtyp(const char *buf, size_t bsz); +static warc_string_t _warc_rduri(const char *buf, size_t bsz); +static ssize_t _warc_rdlen(const char *buf, size_t bsz); +static time_t _warc_rdrtm(const char *buf, size_t bsz); +static time_t _warc_rdmtm(const char *buf, size_t bsz); +static const char *_warc_find_eoh(const char *buf, size_t bsz); +static const char *_warc_find_eol(const char *buf, size_t bsz); + +int +archive_read_support_format_warc(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct warc_s *w; + int r; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_format_warc"); + + if ((w = calloc(1, sizeof(*w))) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate warc data"); + return (ARCHIVE_FATAL); + } + + r = __archive_read_register_format( + a, w, "warc", + _warc_bid, NULL, _warc_rdhdr, _warc_read, + _warc_skip, NULL, _warc_cleanup, NULL, NULL); + + if (r != ARCHIVE_OK) { + free(w); + return (r); + } + return (ARCHIVE_OK); +} + +static int +_warc_cleanup(struct archive_read *a) +{ + struct warc_s *w = a->format->data; + + if (w->pool.len > 0U) { + free(w->pool.str); + } + archive_string_free(&w->sver); + free(w); + a->format->data = NULL; + return (ARCHIVE_OK); +} + +static int +_warc_bid(struct archive_read *a, int best_bid) +{ + const char *hdr; + ssize_t nrd; + unsigned int ver; + + (void)best_bid; /* UNUSED */ + + /* check first line of file, it should be a record already */ + if ((hdr = __archive_read_ahead(a, 12U, &nrd)) == NULL) { + /* no idea what to do */ + return -1; + } else if (nrd < 12) { + /* nah, not for us, our magic cookie is at least 12 bytes */ + return -1; + } + + /* otherwise snarf the record's version number */ + ver = _warc_rdver(hdr, nrd); + if (ver < 1200U || ver > 10000U) { + /* we only support WARC 0.12 to 1.0 */ + return -1; + } + + /* otherwise be confident */ + return (64); +} + +static int +_warc_rdhdr(struct archive_read *a, struct archive_entry *entry) +{ +#define HDR_PROBE_LEN (12U) + struct warc_s *w = a->format->data; + unsigned int ver; + const char *buf; + ssize_t nrd; + const char *eoh; + /* for the file name, saves some strndup()'ing */ + warc_string_t fnam; + /* warc record type, not that we really use it a lot */ + warc_type_t ftyp; + /* content-length+error monad */ + ssize_t cntlen; + /* record time is the WARC-Date time we reinterpret it as ctime */ + time_t rtime; + /* mtime is the Last-Modified time which will be the entry's mtime */ + time_t mtime; + +start_over: + /* just use read_ahead() they keep track of unconsumed + * bits and bobs for us; no need to put an extra shift in + * and reproduce that functionality here */ + buf = __archive_read_ahead(a, HDR_PROBE_LEN, &nrd); + + if (nrd < 0) { + /* no good */ + archive_set_error( + &a->archive, ARCHIVE_ERRNO_MISC, + "Bad record header"); + return (ARCHIVE_FATAL); + } else if (buf == NULL) { + /* there should be room for at least WARC/bla\r\n + * must be EOF therefore */ + return (ARCHIVE_EOF); + } + /* looks good so far, try and find the end of the header now */ + eoh = _warc_find_eoh(buf, nrd); + if (eoh == NULL) { + /* still no good, the header end might be beyond the + * probe we've requested, but then again who'd cram + * so much stuff into the header *and* be 28500-compliant */ + archive_set_error( + &a->archive, ARCHIVE_ERRNO_MISC, + "Bad record header"); + return (ARCHIVE_FATAL); + } + ver = _warc_rdver(buf, eoh - buf); + /* we currently support WARC 0.12 to 1.0 */ + if (ver == 0U) { + archive_set_error( + &a->archive, ARCHIVE_ERRNO_MISC, + "Invalid record version"); + return (ARCHIVE_FATAL); + } else if (ver < 1200U || ver > 10000U) { + archive_set_error( + &a->archive, ARCHIVE_ERRNO_MISC, + "Unsupported record version: %u.%u", + ver / 10000, (ver % 10000) / 100); + return (ARCHIVE_FATAL); + } + cntlen = _warc_rdlen(buf, eoh - buf); + if (cntlen < 0) { + /* nightmare! the specs say content-length is mandatory + * so I don't feel overly bad stopping the reader here */ + archive_set_error( + &a->archive, EINVAL, + "Bad content length"); + return (ARCHIVE_FATAL); + } + rtime = _warc_rdrtm(buf, eoh - buf); + if (rtime == (time_t)-1) { + /* record time is mandatory as per WARC/1.0, + * so just barf here, fast and loud */ + archive_set_error( + &a->archive, EINVAL, + "Bad record time"); + return (ARCHIVE_FATAL); + } + + /* let the world know we're a WARC archive */ + a->archive.archive_format = ARCHIVE_FORMAT_WARC; + if (ver != w->pver) { + /* stringify this entry's version */ + archive_string_sprintf(&w->sver, + "WARC/%u.%u", ver / 10000, (ver % 10000) / 100); + /* remember the version */ + w->pver = ver; + } + /* start off with the type */ + ftyp = _warc_rdtyp(buf, eoh - buf); + /* and let future calls know about the content */ + w->cntlen = cntlen; + w->cntoff = 0U; + mtime = 0;/* Avoid compiling error on some platform. */ + + switch (ftyp) { + case WT_RSRC: + case WT_RSP: + /* only try and read the filename in the cases that are + * guaranteed to have one */ + fnam = _warc_rduri(buf, eoh - buf); + /* check the last character in the URI to avoid creating + * directory endpoints as files, see Todo above */ + if (fnam.len == 0 || fnam.str[fnam.len - 1] == '/') { + /* break here for now */ + fnam.len = 0U; + fnam.str = NULL; + break; + } + /* bang to our string pool, so we save a + * malloc()+free() roundtrip */ + if (fnam.len + 1U > w->pool.len) { + w->pool.len = ((fnam.len + 64U) / 64U) * 64U; + w->pool.str = realloc(w->pool.str, w->pool.len); + } + memcpy(w->pool.str, fnam.str, fnam.len); + w->pool.str[fnam.len] = '\0'; + /* let no one else know about the pool, it's a secret, shhh */ + fnam.str = w->pool.str; + + /* snarf mtime or deduce from rtime + * this is a custom header added by our writer, it's quite + * hard to believe anyone else would go through with it + * (apart from being part of some http responses of course) */ + if ((mtime = _warc_rdmtm(buf, eoh - buf)) == (time_t)-1) { + mtime = rtime; + } + break; + default: + fnam.len = 0U; + fnam.str = NULL; + break; + } + + /* now eat some of those delicious buffer bits */ + __archive_read_consume(a, eoh - buf); + + switch (ftyp) { + case WT_RSRC: + case WT_RSP: + if (fnam.len > 0U) { + /* populate entry object */ + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_copy_pathname(entry, fnam.str); + archive_entry_set_size(entry, cntlen); + archive_entry_set_perm(entry, 0644); + /* rtime is the new ctime, mtime stays mtime */ + archive_entry_set_ctime(entry, rtime, 0L); + archive_entry_set_mtime(entry, mtime, 0L); + break; + } + /* FALLTHROUGH */ + default: + /* consume the content and start over */ + _warc_skip(a); + goto start_over; + } + return (ARCHIVE_OK); +} + +static int +_warc_read(struct archive_read *a, const void **buf, size_t *bsz, int64_t *off) +{ + struct warc_s *w = a->format->data; + const char *rab; + ssize_t nrd; + + if (w->cntoff >= w->cntlen) { + eof: + /* it's our lucky day, no work, we can leave early */ + *buf = NULL; + *bsz = 0U; + *off = w->cntoff + 4U/*for \r\n\r\n separator*/; + w->unconsumed = 0U; + return (ARCHIVE_EOF); + } + + if (w->unconsumed) { + __archive_read_consume(a, w->unconsumed); + w->unconsumed = 0U; + } + + rab = __archive_read_ahead(a, 1U, &nrd); + if (nrd < 0) { + *bsz = 0U; + /* big catastrophe */ + return (int)nrd; + } else if (nrd == 0) { + goto eof; + } else if ((size_t)nrd > w->cntlen - w->cntoff) { + /* clamp to content-length */ + nrd = w->cntlen - w->cntoff; + } + *off = w->cntoff; + *bsz = nrd; + *buf = rab; + + w->cntoff += nrd; + w->unconsumed = (size_t)nrd; + return (ARCHIVE_OK); +} + +static int +_warc_skip(struct archive_read *a) +{ + struct warc_s *w = a->format->data; + + __archive_read_consume(a, w->cntlen + 4U/*\r\n\r\n separator*/); + w->cntlen = 0U; + w->cntoff = 0U; + return (ARCHIVE_OK); +} + + +/* private routines */ +static void* +deconst(const void *c) +{ + return (char *)0x1 + (((const char *)c) - (const char *)0x1); +} + +static char* +xmemmem(const char *hay, const size_t haysize, + const char *needle, const size_t needlesize) +{ + const char *const eoh = hay + haysize; + const char *const eon = needle + needlesize; + const char *hp; + const char *np; + const char *cand; + unsigned int hsum; + unsigned int nsum; + unsigned int eqp; + + /* trivial checks first + * a 0-sized needle is defined to be found anywhere in haystack + * then run strchr() to find a candidate in HAYSTACK (i.e. a portion + * that happens to begin with *NEEDLE) */ + if (needlesize == 0UL) { + return deconst(hay); + } else if ((hay = memchr(hay, *needle, haysize)) == NULL) { + /* trivial */ + return NULL; + } + + /* First characters of haystack and needle are the same now. Both are + * guaranteed to be at least one character long. Now computes the sum + * of characters values of needle together with the sum of the first + * needle_len characters of haystack. */ + for (hp = hay + 1U, np = needle + 1U, hsum = *hay, nsum = *hay, eqp = 1U; + hp < eoh && np < eon; + hsum ^= *hp, nsum ^= *np, eqp &= *hp == *np, hp++, np++); + + /* HP now references the (NEEDLESIZE + 1)-th character. */ + if (np < eon) { + /* haystack is smaller than needle, :O */ + return NULL; + } else if (eqp) { + /* found a match */ + return deconst(hay); + } + + /* now loop through the rest of haystack, + * updating the sum iteratively */ + for (cand = hay; hp < eoh; hp++) { + hsum ^= *cand++; + hsum ^= *hp; + + /* Since the sum of the characters is already known to be + * equal at that point, it is enough to check just NEEDLESIZE - 1 + * characters for equality, + * also CAND is by design < HP, so no need for range checks */ + if (hsum == nsum && memcmp(cand, needle, needlesize - 1U) == 0) { + return deconst(cand); + } + } + return NULL; +} + +static int +strtoi_lim(const char *str, const char **ep, int llim, int ulim) +{ + int res = 0; + const char *sp; + /* we keep track of the number of digits via rulim */ + int rulim; + + for (sp = str, rulim = ulim > 10 ? ulim : 10; + res * 10 <= ulim && rulim && *sp >= '0' && *sp <= '9'; + sp++, rulim /= 10) { + res *= 10; + res += *sp - '0'; + } + if (sp == str) { + res = -1; + } else if (res < llim || res > ulim) { + res = -2; + } + *ep = (const char*)sp; + return res; +} + +static time_t +time_from_tm(struct tm *t) +{ +#if HAVE_TIMEGM + /* Use platform timegm() if available. */ + return (timegm(t)); +#elif HAVE__MKGMTIME64 + return (_mkgmtime64(t)); +#else + /* Else use direct calculation using POSIX assumptions. */ + /* First, fix up tm_yday based on the year/month/day. */ + if (mktime(t) == (time_t)-1) + return ((time_t)-1); + /* Then we can compute timegm() from first principles. */ + return (t->tm_sec + + t->tm_min * 60 + + t->tm_hour * 3600 + + t->tm_yday * 86400 + + (t->tm_year - 70) * 31536000 + + ((t->tm_year - 69) / 4) * 86400 + - ((t->tm_year - 1) / 100) * 86400 + + ((t->tm_year + 299) / 400) * 86400); +#endif +} + +static time_t +xstrpisotime(const char *s, char **endptr) +{ +/** like strptime() but strictly for ISO 8601 Zulu strings */ + struct tm tm; + time_t res = (time_t)-1; + + /* make sure tm is clean */ + memset(&tm, 0, sizeof(tm)); + + /* as a courtesy to our callers, and since this is a non-standard + * routine, we skip leading whitespace */ + while (*s == ' ' || *s == '\t') + ++s; + + /* read year */ + if ((tm.tm_year = strtoi_lim(s, &s, 1583, 4095)) < 0 || *s++ != '-') { + goto out; + } + /* read month */ + if ((tm.tm_mon = strtoi_lim(s, &s, 1, 12)) < 0 || *s++ != '-') { + goto out; + } + /* read day-of-month */ + if ((tm.tm_mday = strtoi_lim(s, &s, 1, 31)) < 0 || *s++ != 'T') { + goto out; + } + /* read hour */ + if ((tm.tm_hour = strtoi_lim(s, &s, 0, 23)) < 0 || *s++ != ':') { + goto out; + } + /* read minute */ + if ((tm.tm_min = strtoi_lim(s, &s, 0, 59)) < 0 || *s++ != ':') { + goto out; + } + /* read second */ + if ((tm.tm_sec = strtoi_lim(s, &s, 0, 60)) < 0 || *s++ != 'Z') { + goto out; + } + + /* massage TM to fulfill some of POSIX' constraints */ + tm.tm_year -= 1900; + tm.tm_mon--; + + /* now convert our custom tm struct to a unix stamp using UTC */ + res = time_from_tm(&tm); + +out: + if (endptr != NULL) { + *endptr = deconst(s); + } + return res; +} + +static unsigned int +_warc_rdver(const char *buf, size_t bsz) +{ + static const char magic[] = "WARC/"; + const char *c; + unsigned int ver = 0U; + unsigned int end = 0U; + + if (bsz < 12 || memcmp(buf, magic, sizeof(magic) - 1U) != 0) { + /* buffer too small or invalid magic */ + return ver; + } + /* looks good so far, read the version number for a laugh */ + buf += sizeof(magic) - 1U; + + if (isdigit((unsigned char)buf[0U]) && (buf[1U] == '.') && + isdigit((unsigned char)buf[2U])) { + /* we support a maximum of 2 digits in the minor version */ + if (isdigit((unsigned char)buf[3U])) + end = 1U; + /* set up major version */ + ver = (buf[0U] - '0') * 10000U; + /* set up minor version */ + if (end == 1U) { + ver += (buf[2U] - '0') * 1000U; + ver += (buf[3U] - '0') * 100U; + } else + ver += (buf[2U] - '0') * 100U; + /* + * WARC below version 0.12 has a space-separated header + * WARC 0.12 and above terminates the version with a CRLF + */ + c = buf + 3U + end; + if (ver >= 1200U) { + if (memcmp(c, "\r\n", 2U) != 0) + ver = 0U; + } else { + /* ver < 1200U */ + if (*c != ' ' && *c != '\t') + ver = 0U; + } + } + return ver; +} + +static unsigned int +_warc_rdtyp(const char *buf, size_t bsz) +{ + static const char _key[] = "\r\nWARC-Type:"; + const char *val, *eol; + + if ((val = xmemmem(buf, bsz, _key, sizeof(_key) - 1U)) == NULL) { + /* no bother */ + return WT_NONE; + } + val += sizeof(_key) - 1U; + if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL) { + /* no end of line */ + return WT_NONE; + } + + /* overread whitespace */ + while (val < eol && (*val == ' ' || *val == '\t')) + ++val; + + if (val + 8U == eol) { + if (memcmp(val, "resource", 8U) == 0) + return WT_RSRC; + else if (memcmp(val, "response", 8U) == 0) + return WT_RSP; + } + return WT_NONE; +} + +static warc_string_t +_warc_rduri(const char *buf, size_t bsz) +{ + static const char _key[] = "\r\nWARC-Target-URI:"; + const char *val, *uri, *eol, *p; + warc_string_t res = {0U, NULL}; + + if ((val = xmemmem(buf, bsz, _key, sizeof(_key) - 1U)) == NULL) { + /* no bother */ + return res; + } + /* overread whitespace */ + val += sizeof(_key) - 1U; + if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL) { + /* no end of line */ + return res; + } + + while (val < eol && (*val == ' ' || *val == '\t')) + ++val; + + /* overread URL designators */ + if ((uri = xmemmem(val, eol - val, "://", 3U)) == NULL) { + /* not touching that! */ + return res; + } + + /* spaces inside uri are not allowed, CRLF should follow */ + for (p = val; p < eol; p++) { + if (isspace((unsigned char)*p)) + return res; + } + + /* there must be at least space for ftp */ + if (uri < (val + 3U)) + return res; + + /* move uri to point to after :// */ + uri += 3U; + + /* now then, inspect the URI */ + if (memcmp(val, "file", 4U) == 0) { + /* perfect, nothing left to do here */ + + } else if (memcmp(val, "http", 4U) == 0 || + memcmp(val, "ftp", 3U) == 0) { + /* overread domain, and the first / */ + while (uri < eol && *uri++ != '/'); + } else { + /* not sure what to do? best to bugger off */ + return res; + } + res.str = uri; + res.len = eol - uri; + return res; +} + +static ssize_t +_warc_rdlen(const char *buf, size_t bsz) +{ + static const char _key[] = "\r\nContent-Length:"; + const char *val, *eol; + char *on = NULL; + long int len; + + if ((val = xmemmem(buf, bsz, _key, sizeof(_key) - 1U)) == NULL) { + /* no bother */ + return -1; + } + val += sizeof(_key) - 1U; + if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL) { + /* no end of line */ + return -1; + } + + /* skip leading whitespace */ + while (val < eol && (*val == ' ' || *val == '\t')) + val++; + /* there must be at least one digit */ + if (!isdigit((unsigned char)*val)) + return -1; + errno = 0; + len = strtol(val, &on, 10); + if (errno != 0 || on != eol) { + /* line must end here */ + return -1; + } + + return (size_t)len; +} + +static time_t +_warc_rdrtm(const char *buf, size_t bsz) +{ + static const char _key[] = "\r\nWARC-Date:"; + const char *val, *eol; + char *on = NULL; + time_t res; + + if ((val = xmemmem(buf, bsz, _key, sizeof(_key) - 1U)) == NULL) { + /* no bother */ + return (time_t)-1; + } + val += sizeof(_key) - 1U; + if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL ) { + /* no end of line */ + return -1; + } + + /* xstrpisotime() kindly overreads whitespace for us, so use that */ + res = xstrpisotime(val, &on); + if (on != eol) { + /* line must end here */ + return -1; + } + return res; +} + +static time_t +_warc_rdmtm(const char *buf, size_t bsz) +{ + static const char _key[] = "\r\nLast-Modified:"; + const char *val, *eol; + char *on = NULL; + time_t res; + + if ((val = xmemmem(buf, bsz, _key, sizeof(_key) - 1U)) == NULL) { + /* no bother */ + return (time_t)-1; + } + val += sizeof(_key) - 1U; + if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL ) { + /* no end of line */ + return -1; + } + + /* xstrpisotime() kindly overreads whitespace for us, so use that */ + res = xstrpisotime(val, &on); + if (on != eol) { + /* line must end here */ + return -1; + } + return res; +} + +static const char* +_warc_find_eoh(const char *buf, size_t bsz) +{ + static const char _marker[] = "\r\n\r\n"; + const char *hit = xmemmem(buf, bsz, _marker, sizeof(_marker) - 1U); + + if (hit != NULL) { + hit += sizeof(_marker) - 1U; + } + return hit; +} + +static const char* +_warc_find_eol(const char *buf, size_t bsz) +{ + static const char _marker[] = "\r\n"; + const char *hit = xmemmem(buf, bsz, _marker, sizeof(_marker) - 1U); + + return hit; +} +/* archive_read_support_format_warc.c ends here */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_xar.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_xar.c new file mode 100644 index 0000000..7f8be39 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_xar.c @@ -0,0 +1,3319 @@ +/*- + * Copyright (c) 2009 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#if HAVE_LIBXML_XMLREADER_H +#include +#elif HAVE_BSDXML_H +#include +#elif HAVE_EXPAT_H +#include +#endif +#ifdef HAVE_BZLIB_H +#include +#endif +#if HAVE_LZMA_H +#include +#endif +#ifdef HAVE_ZLIB_H +#include +#endif + +#include "archive.h" +#include "archive_digest_private.h" +#include "archive_endian.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_private.h" +#include "archive_read_private.h" + +#if (!defined(HAVE_LIBXML_XMLREADER_H) && \ + !defined(HAVE_BSDXML_H) && !defined(HAVE_EXPAT_H)) ||\ + !defined(HAVE_ZLIB_H) || \ + !defined(ARCHIVE_HAS_MD5) || !defined(ARCHIVE_HAS_SHA1) +/* + * xar needs several external libraries. + * o libxml2 or expat --- XML parser + * o openssl or MD5/SHA1 hash function + * o zlib + * o bzlib2 (option) + * o liblzma (option) + */ +int +archive_read_support_format_xar(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_format_xar"); + + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Xar not supported on this platform"); + return (ARCHIVE_WARN); +} + +#else /* Support xar format */ + +/* #define DEBUG 1 */ +/* #define DEBUG_PRINT_TOC 1 */ +#if DEBUG_PRINT_TOC +#define PRINT_TOC(d, outbytes) do { \ + unsigned char *x = (unsigned char *)(uintptr_t)d; \ + unsigned char c = x[outbytes-1]; \ + x[outbytes - 1] = 0; \ + fprintf(stderr, "%s", x); \ + fprintf(stderr, "%c", c); \ + x[outbytes - 1] = c; \ +} while (0) +#else +#define PRINT_TOC(d, outbytes) +#endif + +#define HEADER_MAGIC 0x78617221 +#define HEADER_SIZE 28 +#define HEADER_VERSION 1 +#define CKSUM_NONE 0 +#define CKSUM_SHA1 1 +#define CKSUM_MD5 2 + +#define MD5_SIZE 16 +#define SHA1_SIZE 20 +#define MAX_SUM_SIZE 20 + +enum enctype { + NONE, + GZIP, + BZIP2, + LZMA, + XZ, +}; + +struct chksumval { + int alg; + size_t len; + unsigned char val[MAX_SUM_SIZE]; +}; + +struct chksumwork { + int alg; +#ifdef ARCHIVE_HAS_MD5 + archive_md5_ctx md5ctx; +#endif +#ifdef ARCHIVE_HAS_SHA1 + archive_sha1_ctx sha1ctx; +#endif +}; + +struct xattr { + struct xattr *next; + struct archive_string name; + uint64_t id; + uint64_t length; + uint64_t offset; + uint64_t size; + enum enctype encoding; + struct chksumval a_sum; + struct chksumval e_sum; + struct archive_string fstype; +}; + +struct xar_file { + struct xar_file *next; + struct xar_file *hdnext; + struct xar_file *parent; + int subdirs; + + unsigned int has; +#define HAS_DATA 0x00001 +#define HAS_PATHNAME 0x00002 +#define HAS_SYMLINK 0x00004 +#define HAS_TIME 0x00008 +#define HAS_UID 0x00010 +#define HAS_GID 0x00020 +#define HAS_MODE 0x00040 +#define HAS_TYPE 0x00080 +#define HAS_DEV 0x00100 +#define HAS_DEVMAJOR 0x00200 +#define HAS_DEVMINOR 0x00400 +#define HAS_INO 0x00800 +#define HAS_FFLAGS 0x01000 +#define HAS_XATTR 0x02000 +#define HAS_ACL 0x04000 +#define HAS_CTIME 0x08000 +#define HAS_MTIME 0x10000 +#define HAS_ATIME 0x20000 + + uint64_t id; + uint64_t length; + uint64_t offset; + uint64_t size; + enum enctype encoding; + struct chksumval a_sum; + struct chksumval e_sum; + struct archive_string pathname; + struct archive_string symlink; + time_t ctime; + time_t mtime; + time_t atime; + struct archive_string uname; + int64_t uid; + struct archive_string gname; + int64_t gid; + mode_t mode; + dev_t dev; + dev_t devmajor; + dev_t devminor; + int64_t ino64; + struct archive_string fflags_text; + unsigned int link; + unsigned int nlink; + struct archive_string hardlink; + struct xattr *xattr_list; +}; + +struct hdlink { + struct hdlink *next; + + unsigned int id; + int cnt; + struct xar_file *files; +}; + +struct heap_queue { + struct xar_file **files; + int allocated; + int used; +}; + +enum xmlstatus { + INIT, + XAR, + TOC, + TOC_CREATION_TIME, + TOC_CHECKSUM, + TOC_CHECKSUM_OFFSET, + TOC_CHECKSUM_SIZE, + TOC_FILE, + FILE_DATA, + FILE_DATA_LENGTH, + FILE_DATA_OFFSET, + FILE_DATA_SIZE, + FILE_DATA_ENCODING, + FILE_DATA_A_CHECKSUM, + FILE_DATA_E_CHECKSUM, + FILE_DATA_CONTENT, + FILE_EA, + FILE_EA_LENGTH, + FILE_EA_OFFSET, + FILE_EA_SIZE, + FILE_EA_ENCODING, + FILE_EA_A_CHECKSUM, + FILE_EA_E_CHECKSUM, + FILE_EA_NAME, + FILE_EA_FSTYPE, + FILE_CTIME, + FILE_MTIME, + FILE_ATIME, + FILE_GROUP, + FILE_GID, + FILE_USER, + FILE_UID, + FILE_MODE, + FILE_DEVICE, + FILE_DEVICE_MAJOR, + FILE_DEVICE_MINOR, + FILE_DEVICENO, + FILE_INODE, + FILE_LINK, + FILE_TYPE, + FILE_NAME, + FILE_ACL, + FILE_ACL_DEFAULT, + FILE_ACL_ACCESS, + FILE_ACL_APPLEEXTENDED, + /* BSD file flags. */ + FILE_FLAGS, + FILE_FLAGS_USER_NODUMP, + FILE_FLAGS_USER_IMMUTABLE, + FILE_FLAGS_USER_APPEND, + FILE_FLAGS_USER_OPAQUE, + FILE_FLAGS_USER_NOUNLINK, + FILE_FLAGS_SYS_ARCHIVED, + FILE_FLAGS_SYS_IMMUTABLE, + FILE_FLAGS_SYS_APPEND, + FILE_FLAGS_SYS_NOUNLINK, + FILE_FLAGS_SYS_SNAPSHOT, + /* Linux file flags. */ + FILE_EXT2, + FILE_EXT2_SecureDeletion, + FILE_EXT2_Undelete, + FILE_EXT2_Compress, + FILE_EXT2_Synchronous, + FILE_EXT2_Immutable, + FILE_EXT2_AppendOnly, + FILE_EXT2_NoDump, + FILE_EXT2_NoAtime, + FILE_EXT2_CompDirty, + FILE_EXT2_CompBlock, + FILE_EXT2_NoCompBlock, + FILE_EXT2_CompError, + FILE_EXT2_BTree, + FILE_EXT2_HashIndexed, + FILE_EXT2_iMagic, + FILE_EXT2_Journaled, + FILE_EXT2_NoTail, + FILE_EXT2_DirSync, + FILE_EXT2_TopDir, + FILE_EXT2_Reserved, + UNKNOWN, +}; + +struct unknown_tag { + struct unknown_tag *next; + struct archive_string name; +}; + +struct xar { + uint64_t offset; /* Current position in the file. */ + int64_t total; + uint64_t h_base; + int end_of_file; +#define OUTBUFF_SIZE (1024 * 64) + unsigned char *outbuff; + + enum xmlstatus xmlsts; + enum xmlstatus xmlsts_unknown; + struct unknown_tag *unknowntags; + int base64text; + + /* + * TOC + */ + uint64_t toc_remaining; + uint64_t toc_total; + uint64_t toc_chksum_offset; + uint64_t toc_chksum_size; + + /* + * For Decoding data. + */ + enum enctype rd_encoding; + z_stream stream; + int stream_valid; +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) + bz_stream bzstream; + int bzstream_valid; +#endif +#if HAVE_LZMA_H && HAVE_LIBLZMA + lzma_stream lzstream; + int lzstream_valid; +#endif + /* + * For Checksum data. + */ + struct chksumwork a_sumwrk; + struct chksumwork e_sumwrk; + + struct xar_file *file; /* current reading file. */ + struct xattr *xattr; /* current reading extended attribute. */ + struct heap_queue file_queue; + struct xar_file *hdlink_orgs; + struct hdlink *hdlink_list; + + int entry_init; + uint64_t entry_total; + uint64_t entry_remaining; + size_t entry_unconsumed; + uint64_t entry_size; + enum enctype entry_encoding; + struct chksumval entry_a_sum; + struct chksumval entry_e_sum; + + struct archive_string_conv *sconv; +}; + +struct xmlattr { + struct xmlattr *next; + char *name; + char *value; +}; + +struct xmlattr_list { + struct xmlattr *first; + struct xmlattr **last; +}; + +static int xar_bid(struct archive_read *, int); +static int xar_read_header(struct archive_read *, + struct archive_entry *); +static int xar_read_data(struct archive_read *, + const void **, size_t *, int64_t *); +static int xar_read_data_skip(struct archive_read *); +static int xar_cleanup(struct archive_read *); +static int move_reading_point(struct archive_read *, uint64_t); +static int rd_contents_init(struct archive_read *, + enum enctype, int, int); +static int rd_contents(struct archive_read *, const void **, + size_t *, size_t *, uint64_t); +static uint64_t atol10(const char *, size_t); +static int64_t atol8(const char *, size_t); +static size_t atohex(unsigned char *, size_t, const char *, size_t); +static time_t parse_time(const char *p, size_t n); +static int heap_add_entry(struct archive_read *a, + struct heap_queue *, struct xar_file *); +static struct xar_file *heap_get_entry(struct heap_queue *); +static int add_link(struct archive_read *, + struct xar *, struct xar_file *); +static void checksum_init(struct archive_read *, int, int); +static void checksum_update(struct archive_read *, const void *, + size_t, const void *, size_t); +static int checksum_final(struct archive_read *, const void *, + size_t, const void *, size_t); +static void checksum_cleanup(struct archive_read *); +static int decompression_init(struct archive_read *, enum enctype); +static int decompress(struct archive_read *, const void **, + size_t *, const void *, size_t *); +static int decompression_cleanup(struct archive_read *); +static void xmlattr_cleanup(struct xmlattr_list *); +static int file_new(struct archive_read *, + struct xar *, struct xmlattr_list *); +static void file_free(struct xar_file *); +static int xattr_new(struct archive_read *, + struct xar *, struct xmlattr_list *); +static void xattr_free(struct xattr *); +static int getencoding(struct xmlattr_list *); +static int getsumalgorithm(struct xmlattr_list *); +static int unknowntag_start(struct archive_read *, + struct xar *, const char *); +static void unknowntag_end(struct xar *, const char *); +static int xml_start(struct archive_read *, + const char *, struct xmlattr_list *); +static void xml_end(void *, const char *); +static void xml_data(void *, const char *, int); +static int xml_parse_file_flags(struct xar *, const char *); +static int xml_parse_file_ext2(struct xar *, const char *); +#if defined(HAVE_LIBXML_XMLREADER_H) +static int xml2_xmlattr_setup(struct archive_read *, + struct xmlattr_list *, xmlTextReaderPtr); +static int xml2_read_cb(void *, char *, int); +static int xml2_close_cb(void *); +static void xml2_error_hdr(void *, const char *, xmlParserSeverities, + xmlTextReaderLocatorPtr); +static int xml2_read_toc(struct archive_read *); +#elif defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H) +struct expat_userData { + int state; + struct archive_read *archive; +}; +static int expat_xmlattr_setup(struct archive_read *, + struct xmlattr_list *, const XML_Char **); +static void expat_start_cb(void *, const XML_Char *, const XML_Char **); +static void expat_end_cb(void *, const XML_Char *); +static void expat_data_cb(void *, const XML_Char *, int); +static int expat_read_toc(struct archive_read *); +#endif + +int +archive_read_support_format_xar(struct archive *_a) +{ + struct xar *xar; + struct archive_read *a = (struct archive_read *)_a; + int r; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_format_xar"); + + xar = (struct xar *)calloc(1, sizeof(*xar)); + if (xar == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate xar data"); + return (ARCHIVE_FATAL); + } + + r = __archive_read_register_format(a, + xar, + "xar", + xar_bid, + NULL, + xar_read_header, + xar_read_data, + xar_read_data_skip, + NULL, + xar_cleanup, + NULL, + NULL); + if (r != ARCHIVE_OK) + free(xar); + return (r); +} + +static int +xar_bid(struct archive_read *a, int best_bid) +{ + const unsigned char *b; + int bid; + + (void)best_bid; /* UNUSED */ + + b = __archive_read_ahead(a, HEADER_SIZE, NULL); + if (b == NULL) + return (-1); + + bid = 0; + /* + * Verify magic code + */ + if (archive_be32dec(b) != HEADER_MAGIC) + return (0); + bid += 32; + /* + * Verify header size + */ + if (archive_be16dec(b+4) != HEADER_SIZE) + return (0); + bid += 16; + /* + * Verify header version + */ + if (archive_be16dec(b+6) != HEADER_VERSION) + return (0); + bid += 16; + /* + * Verify type of checksum + */ + switch (archive_be32dec(b+24)) { + case CKSUM_NONE: + case CKSUM_SHA1: + case CKSUM_MD5: + bid += 32; + break; + default: + return (0); + } + + return (bid); +} + +static int +read_toc(struct archive_read *a) +{ + struct xar *xar; + struct xar_file *file; + const unsigned char *b; + uint64_t toc_compressed_size; + uint64_t toc_uncompressed_size; + uint32_t toc_chksum_alg; + ssize_t bytes; + int r; + + xar = (struct xar *)(a->format->data); + + /* + * Read xar header. + */ + b = __archive_read_ahead(a, HEADER_SIZE, &bytes); + if (bytes < 0) + return ((int)bytes); + if (bytes < HEADER_SIZE) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated archive header"); + return (ARCHIVE_FATAL); + } + + if (archive_be32dec(b) != HEADER_MAGIC) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid header magic"); + return (ARCHIVE_FATAL); + } + if (archive_be16dec(b+6) != HEADER_VERSION) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Unsupported header version(%d)", + archive_be16dec(b+6)); + return (ARCHIVE_FATAL); + } + toc_compressed_size = archive_be64dec(b+8); + xar->toc_remaining = toc_compressed_size; + toc_uncompressed_size = archive_be64dec(b+16); + toc_chksum_alg = archive_be32dec(b+24); + __archive_read_consume(a, HEADER_SIZE); + xar->offset += HEADER_SIZE; + xar->toc_total = 0; + + /* + * Read TOC(Table of Contents). + */ + /* Initialize reading contents. */ + r = move_reading_point(a, HEADER_SIZE); + if (r != ARCHIVE_OK) + return (r); + r = rd_contents_init(a, GZIP, toc_chksum_alg, CKSUM_NONE); + if (r != ARCHIVE_OK) + return (r); + +#ifdef HAVE_LIBXML_XMLREADER_H + r = xml2_read_toc(a); +#elif defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H) + r = expat_read_toc(a); +#endif + if (r != ARCHIVE_OK) + return (r); + + /* Set 'The HEAP' base. */ + xar->h_base = xar->offset; + if (xar->toc_total != toc_uncompressed_size) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "TOC uncompressed size error"); + return (ARCHIVE_FATAL); + } + + /* + * Checksum TOC + */ + if (toc_chksum_alg != CKSUM_NONE) { + r = move_reading_point(a, xar->toc_chksum_offset); + if (r != ARCHIVE_OK) + return (r); + b = __archive_read_ahead(a, + (size_t)xar->toc_chksum_size, &bytes); + if (bytes < 0) + return ((int)bytes); + if ((uint64_t)bytes < xar->toc_chksum_size) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated archive file"); + return (ARCHIVE_FATAL); + } + r = checksum_final(a, b, + (size_t)xar->toc_chksum_size, NULL, 0); + __archive_read_consume(a, xar->toc_chksum_size); + xar->offset += xar->toc_chksum_size; + if (r != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + + /* + * Connect hardlinked files. + */ + for (file = xar->hdlink_orgs; file != NULL; file = file->hdnext) { + struct hdlink **hdlink; + + for (hdlink = &(xar->hdlink_list); *hdlink != NULL; + hdlink = &((*hdlink)->next)) { + if ((*hdlink)->id == file->id) { + struct hdlink *hltmp; + struct xar_file *f2; + int nlink = (*hdlink)->cnt + 1; + + file->nlink = nlink; + for (f2 = (*hdlink)->files; f2 != NULL; + f2 = f2->hdnext) { + f2->nlink = nlink; + archive_string_copy( + &(f2->hardlink), &(file->pathname)); + } + /* Remove resolved files from hdlist_list. */ + hltmp = *hdlink; + *hdlink = hltmp->next; + free(hltmp); + break; + } + } + } + a->archive.archive_format = ARCHIVE_FORMAT_XAR; + a->archive.archive_format_name = "xar"; + + return (ARCHIVE_OK); +} + +static int +xar_read_header(struct archive_read *a, struct archive_entry *entry) +{ + struct xar *xar; + struct xar_file *file; + struct xattr *xattr; + int r; + + xar = (struct xar *)(a->format->data); + r = ARCHIVE_OK; + + if (xar->offset == 0) { + /* Create a character conversion object. */ + if (xar->sconv == NULL) { + xar->sconv = archive_string_conversion_from_charset( + &(a->archive), "UTF-8", 1); + if (xar->sconv == NULL) + return (ARCHIVE_FATAL); + } + + /* Read TOC. */ + r = read_toc(a); + if (r != ARCHIVE_OK) + return (r); + } + + for (;;) { + file = xar->file = heap_get_entry(&(xar->file_queue)); + if (file == NULL) { + xar->end_of_file = 1; + return (ARCHIVE_EOF); + } + if ((file->mode & AE_IFMT) != AE_IFDIR) + break; + if (file->has != (HAS_PATHNAME | HAS_TYPE)) + break; + /* + * If a file type is a directory and it does not have + * any metadata, do not export. + */ + file_free(file); + } + if (file->has & HAS_ATIME) { + archive_entry_set_atime(entry, file->atime, 0); + } + if (file->has & HAS_CTIME) { + archive_entry_set_ctime(entry, file->ctime, 0); + } + if (file->has & HAS_MTIME) { + archive_entry_set_mtime(entry, file->mtime, 0); + } + archive_entry_set_gid(entry, file->gid); + if (file->gname.length > 0 && + archive_entry_copy_gname_l(entry, file->gname.s, + archive_strlen(&(file->gname)), xar->sconv) != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Gname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Gname cannot be converted from %s to current locale.", + archive_string_conversion_charset_name(xar->sconv)); + r = ARCHIVE_WARN; + } + archive_entry_set_uid(entry, file->uid); + if (file->uname.length > 0 && + archive_entry_copy_uname_l(entry, file->uname.s, + archive_strlen(&(file->uname)), xar->sconv) != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Uname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Uname cannot be converted from %s to current locale.", + archive_string_conversion_charset_name(xar->sconv)); + r = ARCHIVE_WARN; + } + archive_entry_set_mode(entry, file->mode); + if (archive_entry_copy_pathname_l(entry, file->pathname.s, + archive_strlen(&(file->pathname)), xar->sconv) != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Pathname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Pathname cannot be converted from %s to current locale.", + archive_string_conversion_charset_name(xar->sconv)); + r = ARCHIVE_WARN; + } + + + if (file->symlink.length > 0 && + archive_entry_copy_symlink_l(entry, file->symlink.s, + archive_strlen(&(file->symlink)), xar->sconv) != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Linkname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Linkname cannot be converted from %s to current locale.", + archive_string_conversion_charset_name(xar->sconv)); + r = ARCHIVE_WARN; + } + /* Set proper nlink. */ + if ((file->mode & AE_IFMT) == AE_IFDIR) + archive_entry_set_nlink(entry, file->subdirs + 2); + else + archive_entry_set_nlink(entry, file->nlink); + archive_entry_set_size(entry, file->size); + if (archive_strlen(&(file->hardlink)) > 0) + archive_entry_set_hardlink(entry, file->hardlink.s); + archive_entry_set_ino64(entry, file->ino64); + if (file->has & HAS_DEV) + archive_entry_set_dev(entry, file->dev); + if (file->has & HAS_DEVMAJOR) + archive_entry_set_devmajor(entry, file->devmajor); + if (file->has & HAS_DEVMINOR) + archive_entry_set_devminor(entry, file->devminor); + if (archive_strlen(&(file->fflags_text)) > 0) + archive_entry_copy_fflags_text(entry, file->fflags_text.s); + + xar->entry_init = 1; + xar->entry_total = 0; + xar->entry_remaining = file->length; + xar->entry_size = file->size; + xar->entry_encoding = file->encoding; + xar->entry_a_sum = file->a_sum; + xar->entry_e_sum = file->e_sum; + /* + * Read extended attributes. + */ + xattr = file->xattr_list; + while (xattr != NULL) { + const void *d; + size_t outbytes = 0; + size_t used = 0; + + r = move_reading_point(a, xattr->offset); + if (r != ARCHIVE_OK) + break; + r = rd_contents_init(a, xattr->encoding, + xattr->a_sum.alg, xattr->e_sum.alg); + if (r != ARCHIVE_OK) + break; + d = NULL; + r = rd_contents(a, &d, &outbytes, &used, xattr->length); + if (r != ARCHIVE_OK) + break; + if (outbytes != xattr->size) { + archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, + "Decompressed size error"); + r = ARCHIVE_FATAL; + break; + } + r = checksum_final(a, + xattr->a_sum.val, xattr->a_sum.len, + xattr->e_sum.val, xattr->e_sum.len); + if (r != ARCHIVE_OK) { + archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, + "Xattr checksum error"); + r = ARCHIVE_WARN; + break; + } + if (xattr->name.s == NULL) { + archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, + "Xattr name error"); + r = ARCHIVE_WARN; + break; + } + archive_entry_xattr_add_entry(entry, + xattr->name.s, d, outbytes); + xattr = xattr->next; + } + if (r != ARCHIVE_OK) { + file_free(file); + return (r); + } + + if (xar->entry_remaining > 0) + /* Move reading point to the beginning of current + * file contents. */ + r = move_reading_point(a, file->offset); + else + r = ARCHIVE_OK; + + file_free(file); + return (r); +} + +static int +xar_read_data(struct archive_read *a, + const void **buff, size_t *size, int64_t *offset) +{ + struct xar *xar; + size_t used = 0; + int r; + + xar = (struct xar *)(a->format->data); + + if (xar->entry_unconsumed) { + __archive_read_consume(a, xar->entry_unconsumed); + xar->entry_unconsumed = 0; + } + + if (xar->end_of_file || xar->entry_remaining <= 0) { + r = ARCHIVE_EOF; + goto abort_read_data; + } + + if (xar->entry_init) { + r = rd_contents_init(a, xar->entry_encoding, + xar->entry_a_sum.alg, xar->entry_e_sum.alg); + if (r != ARCHIVE_OK) { + xar->entry_remaining = 0; + return (r); + } + xar->entry_init = 0; + } + + *buff = NULL; + r = rd_contents(a, buff, size, &used, xar->entry_remaining); + if (r != ARCHIVE_OK) + goto abort_read_data; + + *offset = xar->entry_total; + xar->entry_total += *size; + xar->total += *size; + xar->offset += used; + xar->entry_remaining -= used; + xar->entry_unconsumed = used; + + if (xar->entry_remaining == 0) { + if (xar->entry_total != xar->entry_size) { + archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, + "Decompressed size error"); + r = ARCHIVE_FATAL; + goto abort_read_data; + } + r = checksum_final(a, + xar->entry_a_sum.val, xar->entry_a_sum.len, + xar->entry_e_sum.val, xar->entry_e_sum.len); + if (r != ARCHIVE_OK) + goto abort_read_data; + } + + return (ARCHIVE_OK); +abort_read_data: + *buff = NULL; + *size = 0; + *offset = xar->total; + return (r); +} + +static int +xar_read_data_skip(struct archive_read *a) +{ + struct xar *xar; + int64_t bytes_skipped; + + xar = (struct xar *)(a->format->data); + if (xar->end_of_file) + return (ARCHIVE_EOF); + bytes_skipped = __archive_read_consume(a, xar->entry_remaining + + xar->entry_unconsumed); + if (bytes_skipped < 0) + return (ARCHIVE_FATAL); + xar->offset += bytes_skipped; + xar->entry_unconsumed = 0; + return (ARCHIVE_OK); +} + +static int +xar_cleanup(struct archive_read *a) +{ + struct xar *xar; + struct hdlink *hdlink; + int i; + int r; + + xar = (struct xar *)(a->format->data); + checksum_cleanup(a); + r = decompression_cleanup(a); + hdlink = xar->hdlink_list; + while (hdlink != NULL) { + struct hdlink *next = hdlink->next; + + free(hdlink); + hdlink = next; + } + for (i = 0; i < xar->file_queue.used; i++) + file_free(xar->file_queue.files[i]); + free(xar->file_queue.files); + while (xar->unknowntags != NULL) { + struct unknown_tag *tag; + + tag = xar->unknowntags; + xar->unknowntags = tag->next; + archive_string_free(&(tag->name)); + free(tag); + } + free(xar->outbuff); + free(xar); + a->format->data = NULL; + return (r); +} + +static int +move_reading_point(struct archive_read *a, uint64_t offset) +{ + struct xar *xar; + + xar = (struct xar *)(a->format->data); + if (xar->offset - xar->h_base != offset) { + /* Seek forward to the start of file contents. */ + int64_t step; + + step = offset - (xar->offset - xar->h_base); + if (step > 0) { + step = __archive_read_consume(a, step); + if (step < 0) + return ((int)step); + xar->offset += step; + } else { + int64_t pos = __archive_read_seek(a, xar->h_base + offset, SEEK_SET); + if (pos == ARCHIVE_FAILED) { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Cannot seek."); + return (ARCHIVE_FAILED); + } + xar->offset = pos; + } + } + return (ARCHIVE_OK); +} + +static int +rd_contents_init(struct archive_read *a, enum enctype encoding, + int a_sum_alg, int e_sum_alg) +{ + int r; + + /* Init decompress library. */ + if ((r = decompression_init(a, encoding)) != ARCHIVE_OK) + return (r); + /* Init checksum library. */ + checksum_init(a, a_sum_alg, e_sum_alg); + return (ARCHIVE_OK); +} + +static int +rd_contents(struct archive_read *a, const void **buff, size_t *size, + size_t *used, uint64_t remaining) +{ + const unsigned char *b; + ssize_t bytes; + + /* Get whatever bytes are immediately available. */ + b = __archive_read_ahead(a, 1, &bytes); + if (bytes < 0) + return ((int)bytes); + if (bytes == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Truncated archive file"); + return (ARCHIVE_FATAL); + } + if ((uint64_t)bytes > remaining) + bytes = (ssize_t)remaining; + + /* + * Decompress contents of file. + */ + *used = bytes; + if (decompress(a, buff, size, b, used) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* + * Update checksum of a compressed data and a extracted data. + */ + checksum_update(a, b, *used, *buff, *size); + + return (ARCHIVE_OK); +} + +/* + * Note that this implementation does not (and should not!) obey + * locale settings; you cannot simply substitute strtol here, since + * it does obey locale. + */ + +static uint64_t +atol10(const char *p, size_t char_cnt) +{ + uint64_t l; + int digit; + + if (char_cnt == 0) + return (0); + + l = 0; + digit = *p - '0'; + while (digit >= 0 && digit < 10 && char_cnt-- > 0) { + l = (l * 10) + digit; + digit = *++p - '0'; + } + return (l); +} + +static int64_t +atol8(const char *p, size_t char_cnt) +{ + int64_t l; + int digit; + + if (char_cnt == 0) + return (0); + + l = 0; + while (char_cnt-- > 0) { + if (*p >= '0' && *p <= '7') + digit = *p - '0'; + else + break; + p++; + l <<= 3; + l |= digit; + } + return (l); +} + +static size_t +atohex(unsigned char *b, size_t bsize, const char *p, size_t psize) +{ + size_t fbsize = bsize; + + while (bsize && psize > 1) { + unsigned char x; + + if (p[0] >= 'a' && p[0] <= 'z') + x = (p[0] - 'a' + 0x0a) << 4; + else if (p[0] >= 'A' && p[0] <= 'Z') + x = (p[0] - 'A' + 0x0a) << 4; + else if (p[0] >= '0' && p[0] <= '9') + x = (p[0] - '0') << 4; + else + return (-1); + if (p[1] >= 'a' && p[1] <= 'z') + x |= p[1] - 'a' + 0x0a; + else if (p[1] >= 'A' && p[1] <= 'Z') + x |= p[1] - 'A' + 0x0a; + else if (p[1] >= '0' && p[1] <= '9') + x |= p[1] - '0'; + else + return (-1); + + *b++ = x; + bsize--; + p += 2; + psize -= 2; + } + return (fbsize - bsize); +} + +static time_t +time_from_tm(struct tm *t) +{ +#if HAVE_TIMEGM + /* Use platform timegm() if available. */ + return (timegm(t)); +#elif HAVE__MKGMTIME64 + return (_mkgmtime64(t)); +#else + /* Else use direct calculation using POSIX assumptions. */ + /* First, fix up tm_yday based on the year/month/day. */ + mktime(t); + /* Then we can compute timegm() from first principles. */ + return (t->tm_sec + + t->tm_min * 60 + + t->tm_hour * 3600 + + t->tm_yday * 86400 + + (t->tm_year - 70) * 31536000 + + ((t->tm_year - 69) / 4) * 86400 + - ((t->tm_year - 1) / 100) * 86400 + + ((t->tm_year + 299) / 400) * 86400); +#endif +} + +static time_t +parse_time(const char *p, size_t n) +{ + struct tm tm; + time_t t = 0; + int64_t data; + + memset(&tm, 0, sizeof(tm)); + if (n != 20) + return (t); + data = atol10(p, 4); + if (data < 1900) + return (t); + tm.tm_year = (int)data - 1900; + p += 4; + if (*p++ != '-') + return (t); + data = atol10(p, 2); + if (data < 1 || data > 12) + return (t); + tm.tm_mon = (int)data -1; + p += 2; + if (*p++ != '-') + return (t); + data = atol10(p, 2); + if (data < 1 || data > 31) + return (t); + tm.tm_mday = (int)data; + p += 2; + if (*p++ != 'T') + return (t); + data = atol10(p, 2); + if (data < 0 || data > 23) + return (t); + tm.tm_hour = (int)data; + p += 2; + if (*p++ != ':') + return (t); + data = atol10(p, 2); + if (data < 0 || data > 59) + return (t); + tm.tm_min = (int)data; + p += 2; + if (*p++ != ':') + return (t); + data = atol10(p, 2); + if (data < 0 || data > 60) + return (t); + tm.tm_sec = (int)data; +#if 0 + p += 2; + if (*p != 'Z') + return (t); +#endif + + t = time_from_tm(&tm); + + return (t); +} + +static int +heap_add_entry(struct archive_read *a, + struct heap_queue *heap, struct xar_file *file) +{ + uint64_t file_id, parent_id; + int hole, parent; + + /* Expand our pending files list as necessary. */ + if (heap->used >= heap->allocated) { + struct xar_file **new_pending_files; + int new_size = heap->allocated * 2; + + if (heap->allocated < 1024) + new_size = 1024; + /* Overflow might keep us from growing the list. */ + if (new_size <= heap->allocated) { + archive_set_error(&a->archive, + ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + new_pending_files = (struct xar_file **) + malloc(new_size * sizeof(new_pending_files[0])); + if (new_pending_files == NULL) { + archive_set_error(&a->archive, + ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + memcpy(new_pending_files, heap->files, + heap->allocated * sizeof(new_pending_files[0])); + free(heap->files); + heap->files = new_pending_files; + heap->allocated = new_size; + } + + file_id = file->id; + + /* + * Start with hole at end, walk it up tree to find insertion point. + */ + hole = heap->used++; + while (hole > 0) { + parent = (hole - 1)/2; + parent_id = heap->files[parent]->id; + if (file_id >= parent_id) { + heap->files[hole] = file; + return (ARCHIVE_OK); + } + /* Move parent into hole <==> move hole up tree. */ + heap->files[hole] = heap->files[parent]; + hole = parent; + } + heap->files[0] = file; + + return (ARCHIVE_OK); +} + +static struct xar_file * +heap_get_entry(struct heap_queue *heap) +{ + uint64_t a_id, b_id, c_id; + int a, b, c; + struct xar_file *r, *tmp; + + if (heap->used < 1) + return (NULL); + + /* + * The first file in the list is the earliest; we'll return this. + */ + r = heap->files[0]; + + /* + * Move the last item in the heap to the root of the tree + */ + heap->files[0] = heap->files[--(heap->used)]; + + /* + * Rebalance the heap. + */ + a = 0; /* Starting element and its heap key */ + a_id = heap->files[a]->id; + for (;;) { + b = a + a + 1; /* First child */ + if (b >= heap->used) + return (r); + b_id = heap->files[b]->id; + c = b + 1; /* Use second child if it is smaller. */ + if (c < heap->used) { + c_id = heap->files[c]->id; + if (c_id < b_id) { + b = c; + b_id = c_id; + } + } + if (a_id <= b_id) + return (r); + tmp = heap->files[a]; + heap->files[a] = heap->files[b]; + heap->files[b] = tmp; + a = b; + } +} + +static int +add_link(struct archive_read *a, struct xar *xar, struct xar_file *file) +{ + struct hdlink *hdlink; + + for (hdlink = xar->hdlink_list; hdlink != NULL; hdlink = hdlink->next) { + if (hdlink->id == file->link) { + file->hdnext = hdlink->files; + hdlink->cnt++; + hdlink->files = file; + return (ARCHIVE_OK); + } + } + hdlink = malloc(sizeof(*hdlink)); + if (hdlink == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + file->hdnext = NULL; + hdlink->id = file->link; + hdlink->cnt = 1; + hdlink->files = file; + hdlink->next = xar->hdlink_list; + xar->hdlink_list = hdlink; + return (ARCHIVE_OK); +} + +static void +_checksum_init(struct chksumwork *sumwrk, int sum_alg) +{ + sumwrk->alg = sum_alg; + switch (sum_alg) { + case CKSUM_NONE: + break; + case CKSUM_SHA1: + archive_sha1_init(&(sumwrk->sha1ctx)); + break; + case CKSUM_MD5: + archive_md5_init(&(sumwrk->md5ctx)); + break; + } +} + +static void +_checksum_update(struct chksumwork *sumwrk, const void *buff, size_t size) +{ + + switch (sumwrk->alg) { + case CKSUM_NONE: + break; + case CKSUM_SHA1: + archive_sha1_update(&(sumwrk->sha1ctx), buff, size); + break; + case CKSUM_MD5: + archive_md5_update(&(sumwrk->md5ctx), buff, size); + break; + } +} + +static int +_checksum_final(struct chksumwork *sumwrk, const void *val, size_t len) +{ + unsigned char sum[MAX_SUM_SIZE]; + int r = ARCHIVE_OK; + + switch (sumwrk->alg) { + case CKSUM_NONE: + break; + case CKSUM_SHA1: + archive_sha1_final(&(sumwrk->sha1ctx), sum); + if (len != SHA1_SIZE || + memcmp(val, sum, SHA1_SIZE) != 0) + r = ARCHIVE_FAILED; + break; + case CKSUM_MD5: + archive_md5_final(&(sumwrk->md5ctx), sum); + if (len != MD5_SIZE || + memcmp(val, sum, MD5_SIZE) != 0) + r = ARCHIVE_FAILED; + break; + } + return (r); +} + +static void +checksum_init(struct archive_read *a, int a_sum_alg, int e_sum_alg) +{ + struct xar *xar; + + xar = (struct xar *)(a->format->data); + _checksum_init(&(xar->a_sumwrk), a_sum_alg); + _checksum_init(&(xar->e_sumwrk), e_sum_alg); +} + +static void +checksum_update(struct archive_read *a, const void *abuff, size_t asize, + const void *ebuff, size_t esize) +{ + struct xar *xar; + + xar = (struct xar *)(a->format->data); + _checksum_update(&(xar->a_sumwrk), abuff, asize); + _checksum_update(&(xar->e_sumwrk), ebuff, esize); +} + +static int +checksum_final(struct archive_read *a, const void *a_sum_val, + size_t a_sum_len, const void *e_sum_val, size_t e_sum_len) +{ + struct xar *xar; + int r; + + xar = (struct xar *)(a->format->data); + r = _checksum_final(&(xar->a_sumwrk), a_sum_val, a_sum_len); + if (r == ARCHIVE_OK) + r = _checksum_final(&(xar->e_sumwrk), e_sum_val, e_sum_len); + if (r != ARCHIVE_OK) + archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, + "Sumcheck error"); + return (r); +} + +static int +decompression_init(struct archive_read *a, enum enctype encoding) +{ + struct xar *xar; + const char *detail; + int r; + + xar = (struct xar *)(a->format->data); + xar->rd_encoding = encoding; + switch (encoding) { + case NONE: + break; + case GZIP: + if (xar->stream_valid) + r = inflateReset(&(xar->stream)); + else + r = inflateInit(&(xar->stream)); + if (r != Z_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Couldn't initialize zlib stream."); + return (ARCHIVE_FATAL); + } + xar->stream_valid = 1; + xar->stream.total_in = 0; + xar->stream.total_out = 0; + break; +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) + case BZIP2: + if (xar->bzstream_valid) { + BZ2_bzDecompressEnd(&(xar->bzstream)); + xar->bzstream_valid = 0; + } + r = BZ2_bzDecompressInit(&(xar->bzstream), 0, 0); + if (r == BZ_MEM_ERROR) + r = BZ2_bzDecompressInit(&(xar->bzstream), 0, 1); + if (r != BZ_OK) { + int err = ARCHIVE_ERRNO_MISC; + detail = NULL; + switch (r) { + case BZ_PARAM_ERROR: + detail = "invalid setup parameter"; + break; + case BZ_MEM_ERROR: + err = ENOMEM; + detail = "out of memory"; + break; + case BZ_CONFIG_ERROR: + detail = "mis-compiled library"; + break; + } + archive_set_error(&a->archive, err, + "Internal error initializing decompressor: %s", + detail == NULL ? "??" : detail); + xar->bzstream_valid = 0; + return (ARCHIVE_FATAL); + } + xar->bzstream_valid = 1; + xar->bzstream.total_in_lo32 = 0; + xar->bzstream.total_in_hi32 = 0; + xar->bzstream.total_out_lo32 = 0; + xar->bzstream.total_out_hi32 = 0; + break; +#endif +#if defined(HAVE_LZMA_H) && defined(HAVE_LIBLZMA) +#if LZMA_VERSION_MAJOR >= 5 +/* Effectively disable the limiter. */ +#define LZMA_MEMLIMIT UINT64_MAX +#else +/* NOTE: This needs to check memory size which running system has. */ +#define LZMA_MEMLIMIT (1U << 30) +#endif + case XZ: + case LZMA: + if (xar->lzstream_valid) { + lzma_end(&(xar->lzstream)); + xar->lzstream_valid = 0; + } + if (xar->entry_encoding == XZ) + r = lzma_stream_decoder(&(xar->lzstream), + LZMA_MEMLIMIT,/* memlimit */ + LZMA_CONCATENATED); + else + r = lzma_alone_decoder(&(xar->lzstream), + LZMA_MEMLIMIT);/* memlimit */ + if (r != LZMA_OK) { + switch (r) { + case LZMA_MEM_ERROR: + archive_set_error(&a->archive, + ENOMEM, + "Internal error initializing " + "compression library: " + "Cannot allocate memory"); + break; + case LZMA_OPTIONS_ERROR: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Internal error initializing " + "compression library: " + "Invalid or unsupported options"); + break; + default: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Internal error initializing " + "lzma library"); + break; + } + return (ARCHIVE_FATAL); + } + xar->lzstream_valid = 1; + xar->lzstream.total_in = 0; + xar->lzstream.total_out = 0; + break; +#endif + /* + * Unsupported compression. + */ + default: +#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR) + case BZIP2: +#endif +#if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA) + case LZMA: + case XZ: +#endif + switch (xar->entry_encoding) { + case BZIP2: detail = "bzip2"; break; + case LZMA: detail = "lzma"; break; + case XZ: detail = "xz"; break; + default: detail = "??"; break; + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "%s compression not supported on this platform", + detail); + return (ARCHIVE_FAILED); + } + return (ARCHIVE_OK); +} + +static int +decompress(struct archive_read *a, const void **buff, size_t *outbytes, + const void *b, size_t *used) +{ + struct xar *xar; + void *outbuff; + size_t avail_in, avail_out; + int r; + + xar = (struct xar *)(a->format->data); + avail_in = *used; + outbuff = (void *)(uintptr_t)*buff; + if (outbuff == NULL) { + if (xar->outbuff == NULL) { + xar->outbuff = malloc(OUTBUFF_SIZE); + if (xar->outbuff == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Couldn't allocate memory for out buffer"); + return (ARCHIVE_FATAL); + } + } + outbuff = xar->outbuff; + *buff = outbuff; + avail_out = OUTBUFF_SIZE; + } else + avail_out = *outbytes; + switch (xar->rd_encoding) { + case GZIP: + xar->stream.next_in = (Bytef *)(uintptr_t)b; + xar->stream.avail_in = avail_in; + xar->stream.next_out = (unsigned char *)outbuff; + xar->stream.avail_out = avail_out; + r = inflate(&(xar->stream), 0); + switch (r) { + case Z_OK: /* Decompressor made some progress.*/ + case Z_STREAM_END: /* Found end of stream. */ + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "File decompression failed (%d)", r); + return (ARCHIVE_FATAL); + } + *used = avail_in - xar->stream.avail_in; + *outbytes = avail_out - xar->stream.avail_out; + break; +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) + case BZIP2: + xar->bzstream.next_in = (char *)(uintptr_t)b; + xar->bzstream.avail_in = avail_in; + xar->bzstream.next_out = (char *)outbuff; + xar->bzstream.avail_out = avail_out; + r = BZ2_bzDecompress(&(xar->bzstream)); + switch (r) { + case BZ_STREAM_END: /* Found end of stream. */ + switch (BZ2_bzDecompressEnd(&(xar->bzstream))) { + case BZ_OK: + break; + default: + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Failed to clean up decompressor"); + return (ARCHIVE_FATAL); + } + xar->bzstream_valid = 0; + /* FALLTHROUGH */ + case BZ_OK: /* Decompressor made some progress. */ + break; + default: + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "bzip decompression failed"); + return (ARCHIVE_FATAL); + } + *used = avail_in - xar->bzstream.avail_in; + *outbytes = avail_out - xar->bzstream.avail_out; + break; +#endif +#if defined(HAVE_LZMA_H) && defined(HAVE_LIBLZMA) + case LZMA: + case XZ: + xar->lzstream.next_in = b; + xar->lzstream.avail_in = avail_in; + xar->lzstream.next_out = (unsigned char *)outbuff; + xar->lzstream.avail_out = avail_out; + r = lzma_code(&(xar->lzstream), LZMA_RUN); + switch (r) { + case LZMA_STREAM_END: /* Found end of stream. */ + lzma_end(&(xar->lzstream)); + xar->lzstream_valid = 0; + /* FALLTHROUGH */ + case LZMA_OK: /* Decompressor made some progress. */ + break; + default: + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "%s decompression failed(%d)", + (xar->entry_encoding == XZ)?"xz":"lzma", + r); + return (ARCHIVE_FATAL); + } + *used = avail_in - xar->lzstream.avail_in; + *outbytes = avail_out - xar->lzstream.avail_out; + break; +#endif +#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR) + case BZIP2: +#endif +#if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA) + case LZMA: + case XZ: +#endif + case NONE: + default: + if (outbuff == xar->outbuff) { + *buff = b; + *used = avail_in; + *outbytes = avail_in; + } else { + if (avail_out > avail_in) + avail_out = avail_in; + memcpy(outbuff, b, avail_out); + *used = avail_out; + *outbytes = avail_out; + } + break; + } + return (ARCHIVE_OK); +} + +static int +decompression_cleanup(struct archive_read *a) +{ + struct xar *xar; + int r; + + xar = (struct xar *)(a->format->data); + r = ARCHIVE_OK; + if (xar->stream_valid) { + if (inflateEnd(&(xar->stream)) != Z_OK) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Failed to clean up zlib decompressor"); + r = ARCHIVE_FATAL; + } + } +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) + if (xar->bzstream_valid) { + if (BZ2_bzDecompressEnd(&(xar->bzstream)) != BZ_OK) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Failed to clean up bzip2 decompressor"); + r = ARCHIVE_FATAL; + } + } +#endif +#if defined(HAVE_LZMA_H) && defined(HAVE_LIBLZMA) + if (xar->lzstream_valid) + lzma_end(&(xar->lzstream)); +#elif defined(HAVE_LZMA_H) && defined(HAVE_LIBLZMA) + if (xar->lzstream_valid) { + if (lzmadec_end(&(xar->lzstream)) != LZMADEC_OK) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Failed to clean up lzmadec decompressor"); + r = ARCHIVE_FATAL; + } + } +#endif + return (r); +} + +static void +checksum_cleanup(struct archive_read *a) { + struct xar *xar; + + xar = (struct xar *)(a->format->data); + + _checksum_final(&(xar->a_sumwrk), NULL, 0); + _checksum_final(&(xar->e_sumwrk), NULL, 0); +} + +static void +xmlattr_cleanup(struct xmlattr_list *list) +{ + struct xmlattr *attr, *next; + + attr = list->first; + while (attr != NULL) { + next = attr->next; + free(attr->name); + free(attr->value); + free(attr); + attr = next; + } + list->first = NULL; + list->last = &(list->first); +} + +static int +file_new(struct archive_read *a, struct xar *xar, struct xmlattr_list *list) +{ + struct xar_file *file; + struct xmlattr *attr; + + file = calloc(1, sizeof(*file)); + if (file == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + file->parent = xar->file; + file->mode = 0777 | AE_IFREG; + file->atime = 0; + file->mtime = 0; + xar->file = file; + xar->xattr = NULL; + for (attr = list->first; attr != NULL; attr = attr->next) { + if (strcmp(attr->name, "id") == 0) + file->id = atol10(attr->value, strlen(attr->value)); + } + file->nlink = 1; + if (heap_add_entry(a, &(xar->file_queue), file) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + return (ARCHIVE_OK); +} + +static void +file_free(struct xar_file *file) +{ + struct xattr *xattr; + + archive_string_free(&(file->pathname)); + archive_string_free(&(file->symlink)); + archive_string_free(&(file->uname)); + archive_string_free(&(file->gname)); + archive_string_free(&(file->hardlink)); + xattr = file->xattr_list; + while (xattr != NULL) { + struct xattr *next; + + next = xattr->next; + xattr_free(xattr); + xattr = next; + } + + free(file); +} + +static int +xattr_new(struct archive_read *a, struct xar *xar, struct xmlattr_list *list) +{ + struct xattr *xattr, **nx; + struct xmlattr *attr; + + xattr = calloc(1, sizeof(*xattr)); + if (xattr == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + xar->xattr = xattr; + for (attr = list->first; attr != NULL; attr = attr->next) { + if (strcmp(attr->name, "id") == 0) + xattr->id = atol10(attr->value, strlen(attr->value)); + } + /* Chain to xattr list. */ + for (nx = &(xar->file->xattr_list); + *nx != NULL; nx = &((*nx)->next)) { + if (xattr->id < (*nx)->id) + break; + } + xattr->next = *nx; + *nx = xattr; + + return (ARCHIVE_OK); +} + +static void +xattr_free(struct xattr *xattr) +{ + archive_string_free(&(xattr->name)); + free(xattr); +} + +static int +getencoding(struct xmlattr_list *list) +{ + struct xmlattr *attr; + enum enctype encoding = NONE; + + for (attr = list->first; attr != NULL; attr = attr->next) { + if (strcmp(attr->name, "style") == 0) { + if (strcmp(attr->value, "application/octet-stream") == 0) + encoding = NONE; + else if (strcmp(attr->value, "application/x-gzip") == 0) + encoding = GZIP; + else if (strcmp(attr->value, "application/x-bzip2") == 0) + encoding = BZIP2; + else if (strcmp(attr->value, "application/x-lzma") == 0) + encoding = LZMA; + else if (strcmp(attr->value, "application/x-xz") == 0) + encoding = XZ; + } + } + return (encoding); +} + +static int +getsumalgorithm(struct xmlattr_list *list) +{ + struct xmlattr *attr; + int alg = CKSUM_NONE; + + for (attr = list->first; attr != NULL; attr = attr->next) { + if (strcmp(attr->name, "style") == 0) { + const char *v = attr->value; + if ((v[0] == 'S' || v[0] == 's') && + (v[1] == 'H' || v[1] == 'h') && + (v[2] == 'A' || v[2] == 'a') && + v[3] == '1' && v[4] == '\0') + alg = CKSUM_SHA1; + if ((v[0] == 'M' || v[0] == 'm') && + (v[1] == 'D' || v[1] == 'd') && + v[2] == '5' && v[3] == '\0') + alg = CKSUM_MD5; + } + } + return (alg); +} + +static int +unknowntag_start(struct archive_read *a, struct xar *xar, const char *name) +{ + struct unknown_tag *tag; + + tag = malloc(sizeof(*tag)); + if (tag == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + tag->next = xar->unknowntags; + archive_string_init(&(tag->name)); + archive_strcpy(&(tag->name), name); + if (xar->unknowntags == NULL) { +#if DEBUG + fprintf(stderr, "UNKNOWNTAG_START:%s\n", name); +#endif + xar->xmlsts_unknown = xar->xmlsts; + xar->xmlsts = UNKNOWN; + } + xar->unknowntags = tag; + return (ARCHIVE_OK); +} + +static void +unknowntag_end(struct xar *xar, const char *name) +{ + struct unknown_tag *tag; + + tag = xar->unknowntags; + if (tag == NULL || name == NULL) + return; + if (strcmp(tag->name.s, name) == 0) { + xar->unknowntags = tag->next; + archive_string_free(&(tag->name)); + free(tag); + if (xar->unknowntags == NULL) { +#if DEBUG + fprintf(stderr, "UNKNOWNTAG_END:%s\n", name); +#endif + xar->xmlsts = xar->xmlsts_unknown; + } + } +} + +static int +xml_start(struct archive_read *a, const char *name, struct xmlattr_list *list) +{ + struct xar *xar; + struct xmlattr *attr; + + xar = (struct xar *)(a->format->data); + +#if DEBUG + fprintf(stderr, "xml_sta:[%s]\n", name); + for (attr = list->first; attr != NULL; attr = attr->next) + fprintf(stderr, " attr:\"%s\"=\"%s\"\n", + attr->name, attr->value); +#endif + xar->base64text = 0; + switch (xar->xmlsts) { + case INIT: + if (strcmp(name, "xar") == 0) + xar->xmlsts = XAR; + else + if (unknowntag_start(a, xar, name) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + break; + case XAR: + if (strcmp(name, "toc") == 0) + xar->xmlsts = TOC; + else + if (unknowntag_start(a, xar, name) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + break; + case TOC: + if (strcmp(name, "creation-time") == 0) + xar->xmlsts = TOC_CREATION_TIME; + else if (strcmp(name, "checksum") == 0) + xar->xmlsts = TOC_CHECKSUM; + else if (strcmp(name, "file") == 0) { + if (file_new(a, xar, list) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + xar->xmlsts = TOC_FILE; + } + else + if (unknowntag_start(a, xar, name) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + break; + case TOC_CHECKSUM: + if (strcmp(name, "offset") == 0) + xar->xmlsts = TOC_CHECKSUM_OFFSET; + else if (strcmp(name, "size") == 0) + xar->xmlsts = TOC_CHECKSUM_SIZE; + else + if (unknowntag_start(a, xar, name) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + break; + case TOC_FILE: + if (strcmp(name, "file") == 0) { + if (file_new(a, xar, list) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + else if (strcmp(name, "data") == 0) + xar->xmlsts = FILE_DATA; + else if (strcmp(name, "ea") == 0) { + if (xattr_new(a, xar, list) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + xar->xmlsts = FILE_EA; + } + else if (strcmp(name, "ctime") == 0) + xar->xmlsts = FILE_CTIME; + else if (strcmp(name, "mtime") == 0) + xar->xmlsts = FILE_MTIME; + else if (strcmp(name, "atime") == 0) + xar->xmlsts = FILE_ATIME; + else if (strcmp(name, "group") == 0) + xar->xmlsts = FILE_GROUP; + else if (strcmp(name, "gid") == 0) + xar->xmlsts = FILE_GID; + else if (strcmp(name, "user") == 0) + xar->xmlsts = FILE_USER; + else if (strcmp(name, "uid") == 0) + xar->xmlsts = FILE_UID; + else if (strcmp(name, "mode") == 0) + xar->xmlsts = FILE_MODE; + else if (strcmp(name, "device") == 0) + xar->xmlsts = FILE_DEVICE; + else if (strcmp(name, "deviceno") == 0) + xar->xmlsts = FILE_DEVICENO; + else if (strcmp(name, "inode") == 0) + xar->xmlsts = FILE_INODE; + else if (strcmp(name, "link") == 0) + xar->xmlsts = FILE_LINK; + else if (strcmp(name, "type") == 0) { + xar->xmlsts = FILE_TYPE; + for (attr = list->first; attr != NULL; + attr = attr->next) { + if (strcmp(attr->name, "link") != 0) + continue; + if (strcmp(attr->value, "original") == 0) { + xar->file->hdnext = xar->hdlink_orgs; + xar->hdlink_orgs = xar->file; + } else { + xar->file->link = (unsigned)atol10(attr->value, + strlen(attr->value)); + if (xar->file->link > 0) + if (add_link(a, xar, xar->file) != ARCHIVE_OK) { + return (ARCHIVE_FATAL); + }; + } + } + } + else if (strcmp(name, "name") == 0) { + xar->xmlsts = FILE_NAME; + for (attr = list->first; attr != NULL; + attr = attr->next) { + if (strcmp(attr->name, "enctype") == 0 && + strcmp(attr->value, "base64") == 0) + xar->base64text = 1; + } + } + else if (strcmp(name, "acl") == 0) + xar->xmlsts = FILE_ACL; + else if (strcmp(name, "flags") == 0) + xar->xmlsts = FILE_FLAGS; + else if (strcmp(name, "ext2") == 0) + xar->xmlsts = FILE_EXT2; + else + if (unknowntag_start(a, xar, name) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + break; + case FILE_DATA: + if (strcmp(name, "length") == 0) + xar->xmlsts = FILE_DATA_LENGTH; + else if (strcmp(name, "offset") == 0) + xar->xmlsts = FILE_DATA_OFFSET; + else if (strcmp(name, "size") == 0) + xar->xmlsts = FILE_DATA_SIZE; + else if (strcmp(name, "encoding") == 0) { + xar->xmlsts = FILE_DATA_ENCODING; + xar->file->encoding = getencoding(list); + } + else if (strcmp(name, "archived-checksum") == 0) { + xar->xmlsts = FILE_DATA_A_CHECKSUM; + xar->file->a_sum.alg = getsumalgorithm(list); + } + else if (strcmp(name, "extracted-checksum") == 0) { + xar->xmlsts = FILE_DATA_E_CHECKSUM; + xar->file->e_sum.alg = getsumalgorithm(list); + } + else if (strcmp(name, "content") == 0) + xar->xmlsts = FILE_DATA_CONTENT; + else + if (unknowntag_start(a, xar, name) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + break; + case FILE_DEVICE: + if (strcmp(name, "major") == 0) + xar->xmlsts = FILE_DEVICE_MAJOR; + else if (strcmp(name, "minor") == 0) + xar->xmlsts = FILE_DEVICE_MINOR; + else + if (unknowntag_start(a, xar, name) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + break; + case FILE_DATA_CONTENT: + if (unknowntag_start(a, xar, name) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + break; + case FILE_EA: + if (strcmp(name, "length") == 0) + xar->xmlsts = FILE_EA_LENGTH; + else if (strcmp(name, "offset") == 0) + xar->xmlsts = FILE_EA_OFFSET; + else if (strcmp(name, "size") == 0) + xar->xmlsts = FILE_EA_SIZE; + else if (strcmp(name, "encoding") == 0) { + xar->xmlsts = FILE_EA_ENCODING; + xar->xattr->encoding = getencoding(list); + } else if (strcmp(name, "archived-checksum") == 0) + xar->xmlsts = FILE_EA_A_CHECKSUM; + else if (strcmp(name, "extracted-checksum") == 0) + xar->xmlsts = FILE_EA_E_CHECKSUM; + else if (strcmp(name, "name") == 0) + xar->xmlsts = FILE_EA_NAME; + else if (strcmp(name, "fstype") == 0) + xar->xmlsts = FILE_EA_FSTYPE; + else + if (unknowntag_start(a, xar, name) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + break; + case FILE_ACL: + if (strcmp(name, "appleextended") == 0) + xar->xmlsts = FILE_ACL_APPLEEXTENDED; + else if (strcmp(name, "default") == 0) + xar->xmlsts = FILE_ACL_DEFAULT; + else if (strcmp(name, "access") == 0) + xar->xmlsts = FILE_ACL_ACCESS; + else + if (unknowntag_start(a, xar, name) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + break; + case FILE_FLAGS: + if (!xml_parse_file_flags(xar, name)) + if (unknowntag_start(a, xar, name) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + break; + case FILE_EXT2: + if (!xml_parse_file_ext2(xar, name)) + if (unknowntag_start(a, xar, name) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + break; + case TOC_CREATION_TIME: + case TOC_CHECKSUM_OFFSET: + case TOC_CHECKSUM_SIZE: + case FILE_DATA_LENGTH: + case FILE_DATA_OFFSET: + case FILE_DATA_SIZE: + case FILE_DATA_ENCODING: + case FILE_DATA_A_CHECKSUM: + case FILE_DATA_E_CHECKSUM: + case FILE_EA_LENGTH: + case FILE_EA_OFFSET: + case FILE_EA_SIZE: + case FILE_EA_ENCODING: + case FILE_EA_A_CHECKSUM: + case FILE_EA_E_CHECKSUM: + case FILE_EA_NAME: + case FILE_EA_FSTYPE: + case FILE_CTIME: + case FILE_MTIME: + case FILE_ATIME: + case FILE_GROUP: + case FILE_GID: + case FILE_USER: + case FILE_UID: + case FILE_INODE: + case FILE_DEVICE_MAJOR: + case FILE_DEVICE_MINOR: + case FILE_DEVICENO: + case FILE_MODE: + case FILE_TYPE: + case FILE_LINK: + case FILE_NAME: + case FILE_ACL_DEFAULT: + case FILE_ACL_ACCESS: + case FILE_ACL_APPLEEXTENDED: + case FILE_FLAGS_USER_NODUMP: + case FILE_FLAGS_USER_IMMUTABLE: + case FILE_FLAGS_USER_APPEND: + case FILE_FLAGS_USER_OPAQUE: + case FILE_FLAGS_USER_NOUNLINK: + case FILE_FLAGS_SYS_ARCHIVED: + case FILE_FLAGS_SYS_IMMUTABLE: + case FILE_FLAGS_SYS_APPEND: + case FILE_FLAGS_SYS_NOUNLINK: + case FILE_FLAGS_SYS_SNAPSHOT: + case FILE_EXT2_SecureDeletion: + case FILE_EXT2_Undelete: + case FILE_EXT2_Compress: + case FILE_EXT2_Synchronous: + case FILE_EXT2_Immutable: + case FILE_EXT2_AppendOnly: + case FILE_EXT2_NoDump: + case FILE_EXT2_NoAtime: + case FILE_EXT2_CompDirty: + case FILE_EXT2_CompBlock: + case FILE_EXT2_NoCompBlock: + case FILE_EXT2_CompError: + case FILE_EXT2_BTree: + case FILE_EXT2_HashIndexed: + case FILE_EXT2_iMagic: + case FILE_EXT2_Journaled: + case FILE_EXT2_NoTail: + case FILE_EXT2_DirSync: + case FILE_EXT2_TopDir: + case FILE_EXT2_Reserved: + case UNKNOWN: + if (unknowntag_start(a, xar, name) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + break; + } + return (ARCHIVE_OK); +} + +static void +xml_end(void *userData, const char *name) +{ + struct archive_read *a; + struct xar *xar; + + a = (struct archive_read *)userData; + xar = (struct xar *)(a->format->data); + +#if DEBUG + fprintf(stderr, "xml_end:[%s]\n", name); +#endif + switch (xar->xmlsts) { + case INIT: + break; + case XAR: + if (strcmp(name, "xar") == 0) + xar->xmlsts = INIT; + break; + case TOC: + if (strcmp(name, "toc") == 0) + xar->xmlsts = XAR; + break; + case TOC_CREATION_TIME: + if (strcmp(name, "creation-time") == 0) + xar->xmlsts = TOC; + break; + case TOC_CHECKSUM: + if (strcmp(name, "checksum") == 0) + xar->xmlsts = TOC; + break; + case TOC_CHECKSUM_OFFSET: + if (strcmp(name, "offset") == 0) + xar->xmlsts = TOC_CHECKSUM; + break; + case TOC_CHECKSUM_SIZE: + if (strcmp(name, "size") == 0) + xar->xmlsts = TOC_CHECKSUM; + break; + case TOC_FILE: + if (strcmp(name, "file") == 0) { + if (xar->file->parent != NULL && + ((xar->file->mode & AE_IFMT) == AE_IFDIR)) + xar->file->parent->subdirs++; + xar->file = xar->file->parent; + if (xar->file == NULL) + xar->xmlsts = TOC; + } + break; + case FILE_DATA: + if (strcmp(name, "data") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_DATA_LENGTH: + if (strcmp(name, "length") == 0) + xar->xmlsts = FILE_DATA; + break; + case FILE_DATA_OFFSET: + if (strcmp(name, "offset") == 0) + xar->xmlsts = FILE_DATA; + break; + case FILE_DATA_SIZE: + if (strcmp(name, "size") == 0) + xar->xmlsts = FILE_DATA; + break; + case FILE_DATA_ENCODING: + if (strcmp(name, "encoding") == 0) + xar->xmlsts = FILE_DATA; + break; + case FILE_DATA_A_CHECKSUM: + if (strcmp(name, "archived-checksum") == 0) + xar->xmlsts = FILE_DATA; + break; + case FILE_DATA_E_CHECKSUM: + if (strcmp(name, "extracted-checksum") == 0) + xar->xmlsts = FILE_DATA; + break; + case FILE_DATA_CONTENT: + if (strcmp(name, "content") == 0) + xar->xmlsts = FILE_DATA; + break; + case FILE_EA: + if (strcmp(name, "ea") == 0) { + xar->xmlsts = TOC_FILE; + xar->xattr = NULL; + } + break; + case FILE_EA_LENGTH: + if (strcmp(name, "length") == 0) + xar->xmlsts = FILE_EA; + break; + case FILE_EA_OFFSET: + if (strcmp(name, "offset") == 0) + xar->xmlsts = FILE_EA; + break; + case FILE_EA_SIZE: + if (strcmp(name, "size") == 0) + xar->xmlsts = FILE_EA; + break; + case FILE_EA_ENCODING: + if (strcmp(name, "encoding") == 0) + xar->xmlsts = FILE_EA; + break; + case FILE_EA_A_CHECKSUM: + if (strcmp(name, "archived-checksum") == 0) + xar->xmlsts = FILE_EA; + break; + case FILE_EA_E_CHECKSUM: + if (strcmp(name, "extracted-checksum") == 0) + xar->xmlsts = FILE_EA; + break; + case FILE_EA_NAME: + if (strcmp(name, "name") == 0) + xar->xmlsts = FILE_EA; + break; + case FILE_EA_FSTYPE: + if (strcmp(name, "fstype") == 0) + xar->xmlsts = FILE_EA; + break; + case FILE_CTIME: + if (strcmp(name, "ctime") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_MTIME: + if (strcmp(name, "mtime") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_ATIME: + if (strcmp(name, "atime") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_GROUP: + if (strcmp(name, "group") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_GID: + if (strcmp(name, "gid") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_USER: + if (strcmp(name, "user") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_UID: + if (strcmp(name, "uid") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_MODE: + if (strcmp(name, "mode") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_DEVICE: + if (strcmp(name, "device") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_DEVICE_MAJOR: + if (strcmp(name, "major") == 0) + xar->xmlsts = FILE_DEVICE; + break; + case FILE_DEVICE_MINOR: + if (strcmp(name, "minor") == 0) + xar->xmlsts = FILE_DEVICE; + break; + case FILE_DEVICENO: + if (strcmp(name, "deviceno") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_INODE: + if (strcmp(name, "inode") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_LINK: + if (strcmp(name, "link") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_TYPE: + if (strcmp(name, "type") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_NAME: + if (strcmp(name, "name") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_ACL: + if (strcmp(name, "acl") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_ACL_DEFAULT: + if (strcmp(name, "default") == 0) + xar->xmlsts = FILE_ACL; + break; + case FILE_ACL_ACCESS: + if (strcmp(name, "access") == 0) + xar->xmlsts = FILE_ACL; + break; + case FILE_ACL_APPLEEXTENDED: + if (strcmp(name, "appleextended") == 0) + xar->xmlsts = FILE_ACL; + break; + case FILE_FLAGS: + if (strcmp(name, "flags") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_FLAGS_USER_NODUMP: + if (strcmp(name, "UserNoDump") == 0) + xar->xmlsts = FILE_FLAGS; + break; + case FILE_FLAGS_USER_IMMUTABLE: + if (strcmp(name, "UserImmutable") == 0) + xar->xmlsts = FILE_FLAGS; + break; + case FILE_FLAGS_USER_APPEND: + if (strcmp(name, "UserAppend") == 0) + xar->xmlsts = FILE_FLAGS; + break; + case FILE_FLAGS_USER_OPAQUE: + if (strcmp(name, "UserOpaque") == 0) + xar->xmlsts = FILE_FLAGS; + break; + case FILE_FLAGS_USER_NOUNLINK: + if (strcmp(name, "UserNoUnlink") == 0) + xar->xmlsts = FILE_FLAGS; + break; + case FILE_FLAGS_SYS_ARCHIVED: + if (strcmp(name, "SystemArchived") == 0) + xar->xmlsts = FILE_FLAGS; + break; + case FILE_FLAGS_SYS_IMMUTABLE: + if (strcmp(name, "SystemImmutable") == 0) + xar->xmlsts = FILE_FLAGS; + break; + case FILE_FLAGS_SYS_APPEND: + if (strcmp(name, "SystemAppend") == 0) + xar->xmlsts = FILE_FLAGS; + break; + case FILE_FLAGS_SYS_NOUNLINK: + if (strcmp(name, "SystemNoUnlink") == 0) + xar->xmlsts = FILE_FLAGS; + break; + case FILE_FLAGS_SYS_SNAPSHOT: + if (strcmp(name, "SystemSnapshot") == 0) + xar->xmlsts = FILE_FLAGS; + break; + case FILE_EXT2: + if (strcmp(name, "ext2") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_EXT2_SecureDeletion: + if (strcmp(name, "SecureDeletion") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_Undelete: + if (strcmp(name, "Undelete") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_Compress: + if (strcmp(name, "Compress") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_Synchronous: + if (strcmp(name, "Synchronous") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_Immutable: + if (strcmp(name, "Immutable") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_AppendOnly: + if (strcmp(name, "AppendOnly") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_NoDump: + if (strcmp(name, "NoDump") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_NoAtime: + if (strcmp(name, "NoAtime") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_CompDirty: + if (strcmp(name, "CompDirty") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_CompBlock: + if (strcmp(name, "CompBlock") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_NoCompBlock: + if (strcmp(name, "NoCompBlock") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_CompError: + if (strcmp(name, "CompError") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_BTree: + if (strcmp(name, "BTree") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_HashIndexed: + if (strcmp(name, "HashIndexed") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_iMagic: + if (strcmp(name, "iMagic") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_Journaled: + if (strcmp(name, "Journaled") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_NoTail: + if (strcmp(name, "NoTail") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_DirSync: + if (strcmp(name, "DirSync") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_TopDir: + if (strcmp(name, "TopDir") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_Reserved: + if (strcmp(name, "Reserved") == 0) + xar->xmlsts = FILE_EXT2; + break; + case UNKNOWN: + unknowntag_end(xar, name); + break; + } +} + +static const int base64[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* 00 - 0F */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* 10 - 1F */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 62, -1, -1, -1, 63, /* 20 - 2F */ + 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, -1, -1, -1, -1, -1, -1, /* 30 - 3F */ + -1, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, /* 40 - 4F */ + 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, -1, -1, -1, -1, -1, /* 50 - 5F */ + -1, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, /* 60 - 6F */ + 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, -1, -1, -1, -1, -1, /* 70 - 7F */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* 80 - 8F */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* 90 - 9F */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* A0 - AF */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* B0 - BF */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* C0 - CF */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* D0 - DF */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* E0 - EF */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* F0 - FF */ +}; + +static void +strappend_base64(struct xar *xar, + struct archive_string *as, const char *s, size_t l) +{ + unsigned char buff[256]; + unsigned char *out; + const unsigned char *b; + size_t len; + + (void)xar; /* UNUSED */ + len = 0; + out = buff; + b = (const unsigned char *)s; + while (l > 0) { + int n = 0; + + if (base64[b[0]] < 0 || base64[b[1]] < 0) + break; + n = base64[*b++] << 18; + n |= base64[*b++] << 12; + *out++ = n >> 16; + len++; + l -= 2; + + if (l > 0) { + if (base64[*b] < 0) + break; + n |= base64[*b++] << 6; + *out++ = (n >> 8) & 0xFF; + len++; + --l; + } + if (l > 0) { + if (base64[*b] < 0) + break; + n |= base64[*b++]; + *out++ = n & 0xFF; + len++; + --l; + } + if (len+3 >= sizeof(buff)) { + archive_strncat(as, (const char *)buff, len); + len = 0; + out = buff; + } + } + if (len > 0) + archive_strncat(as, (const char *)buff, len); +} + +static int +is_string(const char *known, const char *data, size_t len) +{ + if (strlen(known) != len) + return -1; + return memcmp(data, known, len); +} + +static void +xml_data(void *userData, const char *s, int len) +{ + struct archive_read *a; + struct xar *xar; + + a = (struct archive_read *)userData; + xar = (struct xar *)(a->format->data); + +#if DEBUG + { + char buff[1024]; + if (len > (int)(sizeof(buff)-1)) + len = (int)(sizeof(buff)-1); + strncpy(buff, s, len); + buff[len] = 0; + fprintf(stderr, "\tlen=%d:\"%s\"\n", len, buff); + } +#endif + switch (xar->xmlsts) { + case TOC_CHECKSUM_OFFSET: + xar->toc_chksum_offset = atol10(s, len); + break; + case TOC_CHECKSUM_SIZE: + xar->toc_chksum_size = atol10(s, len); + break; + default: + break; + } + if (xar->file == NULL) + return; + + switch (xar->xmlsts) { + case FILE_NAME: + if (xar->file->parent != NULL) { + archive_string_concat(&(xar->file->pathname), + &(xar->file->parent->pathname)); + archive_strappend_char(&(xar->file->pathname), '/'); + } + xar->file->has |= HAS_PATHNAME; + if (xar->base64text) { + strappend_base64(xar, + &(xar->file->pathname), s, len); + } else + archive_strncat(&(xar->file->pathname), s, len); + break; + case FILE_LINK: + xar->file->has |= HAS_SYMLINK; + archive_strncpy(&(xar->file->symlink), s, len); + break; + case FILE_TYPE: + if (is_string("file", s, len) == 0 || + is_string("hardlink", s, len) == 0) + xar->file->mode = + (xar->file->mode & ~AE_IFMT) | AE_IFREG; + if (is_string("directory", s, len) == 0) + xar->file->mode = + (xar->file->mode & ~AE_IFMT) | AE_IFDIR; + if (is_string("symlink", s, len) == 0) + xar->file->mode = + (xar->file->mode & ~AE_IFMT) | AE_IFLNK; + if (is_string("character special", s, len) == 0) + xar->file->mode = + (xar->file->mode & ~AE_IFMT) | AE_IFCHR; + if (is_string("block special", s, len) == 0) + xar->file->mode = + (xar->file->mode & ~AE_IFMT) | AE_IFBLK; + if (is_string("socket", s, len) == 0) + xar->file->mode = + (xar->file->mode & ~AE_IFMT) | AE_IFSOCK; + if (is_string("fifo", s, len) == 0) + xar->file->mode = + (xar->file->mode & ~AE_IFMT) | AE_IFIFO; + xar->file->has |= HAS_TYPE; + break; + case FILE_INODE: + xar->file->has |= HAS_INO; + xar->file->ino64 = atol10(s, len); + break; + case FILE_DEVICE_MAJOR: + xar->file->has |= HAS_DEVMAJOR; + xar->file->devmajor = (dev_t)atol10(s, len); + break; + case FILE_DEVICE_MINOR: + xar->file->has |= HAS_DEVMINOR; + xar->file->devminor = (dev_t)atol10(s, len); + break; + case FILE_DEVICENO: + xar->file->has |= HAS_DEV; + xar->file->dev = (dev_t)atol10(s, len); + break; + case FILE_MODE: + xar->file->has |= HAS_MODE; + xar->file->mode = + (xar->file->mode & AE_IFMT) | + ((mode_t)(atol8(s, len)) & ~AE_IFMT); + break; + case FILE_GROUP: + xar->file->has |= HAS_GID; + archive_strncpy(&(xar->file->gname), s, len); + break; + case FILE_GID: + xar->file->has |= HAS_GID; + xar->file->gid = atol10(s, len); + break; + case FILE_USER: + xar->file->has |= HAS_UID; + archive_strncpy(&(xar->file->uname), s, len); + break; + case FILE_UID: + xar->file->has |= HAS_UID; + xar->file->uid = atol10(s, len); + break; + case FILE_CTIME: + xar->file->has |= HAS_TIME | HAS_CTIME; + xar->file->ctime = parse_time(s, len); + break; + case FILE_MTIME: + xar->file->has |= HAS_TIME | HAS_MTIME; + xar->file->mtime = parse_time(s, len); + break; + case FILE_ATIME: + xar->file->has |= HAS_TIME | HAS_ATIME; + xar->file->atime = parse_time(s, len); + break; + case FILE_DATA_LENGTH: + xar->file->has |= HAS_DATA; + xar->file->length = atol10(s, len); + break; + case FILE_DATA_OFFSET: + xar->file->has |= HAS_DATA; + xar->file->offset = atol10(s, len); + break; + case FILE_DATA_SIZE: + xar->file->has |= HAS_DATA; + xar->file->size = atol10(s, len); + break; + case FILE_DATA_A_CHECKSUM: + xar->file->a_sum.len = atohex(xar->file->a_sum.val, + sizeof(xar->file->a_sum.val), s, len); + break; + case FILE_DATA_E_CHECKSUM: + xar->file->e_sum.len = atohex(xar->file->e_sum.val, + sizeof(xar->file->e_sum.val), s, len); + break; + case FILE_EA_LENGTH: + xar->file->has |= HAS_XATTR; + xar->xattr->length = atol10(s, len); + break; + case FILE_EA_OFFSET: + xar->file->has |= HAS_XATTR; + xar->xattr->offset = atol10(s, len); + break; + case FILE_EA_SIZE: + xar->file->has |= HAS_XATTR; + xar->xattr->size = atol10(s, len); + break; + case FILE_EA_A_CHECKSUM: + xar->file->has |= HAS_XATTR; + xar->xattr->a_sum.len = atohex(xar->xattr->a_sum.val, + sizeof(xar->xattr->a_sum.val), s, len); + break; + case FILE_EA_E_CHECKSUM: + xar->file->has |= HAS_XATTR; + xar->xattr->e_sum.len = atohex(xar->xattr->e_sum.val, + sizeof(xar->xattr->e_sum.val), s, len); + break; + case FILE_EA_NAME: + xar->file->has |= HAS_XATTR; + archive_strncpy(&(xar->xattr->name), s, len); + break; + case FILE_EA_FSTYPE: + xar->file->has |= HAS_XATTR; + archive_strncpy(&(xar->xattr->fstype), s, len); + break; + break; + case FILE_ACL_DEFAULT: + case FILE_ACL_ACCESS: + case FILE_ACL_APPLEEXTENDED: + xar->file->has |= HAS_ACL; + /* TODO */ + break; + case INIT: + case XAR: + case TOC: + case TOC_CREATION_TIME: + case TOC_CHECKSUM: + case TOC_CHECKSUM_OFFSET: + case TOC_CHECKSUM_SIZE: + case TOC_FILE: + case FILE_DATA: + case FILE_DATA_ENCODING: + case FILE_DATA_CONTENT: + case FILE_DEVICE: + case FILE_EA: + case FILE_EA_ENCODING: + case FILE_ACL: + case FILE_FLAGS: + case FILE_FLAGS_USER_NODUMP: + case FILE_FLAGS_USER_IMMUTABLE: + case FILE_FLAGS_USER_APPEND: + case FILE_FLAGS_USER_OPAQUE: + case FILE_FLAGS_USER_NOUNLINK: + case FILE_FLAGS_SYS_ARCHIVED: + case FILE_FLAGS_SYS_IMMUTABLE: + case FILE_FLAGS_SYS_APPEND: + case FILE_FLAGS_SYS_NOUNLINK: + case FILE_FLAGS_SYS_SNAPSHOT: + case FILE_EXT2: + case FILE_EXT2_SecureDeletion: + case FILE_EXT2_Undelete: + case FILE_EXT2_Compress: + case FILE_EXT2_Synchronous: + case FILE_EXT2_Immutable: + case FILE_EXT2_AppendOnly: + case FILE_EXT2_NoDump: + case FILE_EXT2_NoAtime: + case FILE_EXT2_CompDirty: + case FILE_EXT2_CompBlock: + case FILE_EXT2_NoCompBlock: + case FILE_EXT2_CompError: + case FILE_EXT2_BTree: + case FILE_EXT2_HashIndexed: + case FILE_EXT2_iMagic: + case FILE_EXT2_Journaled: + case FILE_EXT2_NoTail: + case FILE_EXT2_DirSync: + case FILE_EXT2_TopDir: + case FILE_EXT2_Reserved: + case UNKNOWN: + break; + } +} + +/* + * BSD file flags. + */ +static int +xml_parse_file_flags(struct xar *xar, const char *name) +{ + const char *flag = NULL; + + if (strcmp(name, "UserNoDump") == 0) { + xar->xmlsts = FILE_FLAGS_USER_NODUMP; + flag = "nodump"; + } + else if (strcmp(name, "UserImmutable") == 0) { + xar->xmlsts = FILE_FLAGS_USER_IMMUTABLE; + flag = "uimmutable"; + } + else if (strcmp(name, "UserAppend") == 0) { + xar->xmlsts = FILE_FLAGS_USER_APPEND; + flag = "uappend"; + } + else if (strcmp(name, "UserOpaque") == 0) { + xar->xmlsts = FILE_FLAGS_USER_OPAQUE; + flag = "opaque"; + } + else if (strcmp(name, "UserNoUnlink") == 0) { + xar->xmlsts = FILE_FLAGS_USER_NOUNLINK; + flag = "nouunlink"; + } + else if (strcmp(name, "SystemArchived") == 0) { + xar->xmlsts = FILE_FLAGS_SYS_ARCHIVED; + flag = "archived"; + } + else if (strcmp(name, "SystemImmutable") == 0) { + xar->xmlsts = FILE_FLAGS_SYS_IMMUTABLE; + flag = "simmutable"; + } + else if (strcmp(name, "SystemAppend") == 0) { + xar->xmlsts = FILE_FLAGS_SYS_APPEND; + flag = "sappend"; + } + else if (strcmp(name, "SystemNoUnlink") == 0) { + xar->xmlsts = FILE_FLAGS_SYS_NOUNLINK; + flag = "nosunlink"; + } + else if (strcmp(name, "SystemSnapshot") == 0) { + xar->xmlsts = FILE_FLAGS_SYS_SNAPSHOT; + flag = "snapshot"; + } + + if (flag == NULL) + return (0); + xar->file->has |= HAS_FFLAGS; + if (archive_strlen(&(xar->file->fflags_text)) > 0) + archive_strappend_char(&(xar->file->fflags_text), ','); + archive_strcat(&(xar->file->fflags_text), flag); + return (1); +} + +/* + * Linux file flags. + */ +static int +xml_parse_file_ext2(struct xar *xar, const char *name) +{ + const char *flag = NULL; + + if (strcmp(name, "SecureDeletion") == 0) { + xar->xmlsts = FILE_EXT2_SecureDeletion; + flag = "securedeletion"; + } + else if (strcmp(name, "Undelete") == 0) { + xar->xmlsts = FILE_EXT2_Undelete; + flag = "nouunlink"; + } + else if (strcmp(name, "Compress") == 0) { + xar->xmlsts = FILE_EXT2_Compress; + flag = "compress"; + } + else if (strcmp(name, "Synchronous") == 0) { + xar->xmlsts = FILE_EXT2_Synchronous; + flag = "sync"; + } + else if (strcmp(name, "Immutable") == 0) { + xar->xmlsts = FILE_EXT2_Immutable; + flag = "simmutable"; + } + else if (strcmp(name, "AppendOnly") == 0) { + xar->xmlsts = FILE_EXT2_AppendOnly; + flag = "sappend"; + } + else if (strcmp(name, "NoDump") == 0) { + xar->xmlsts = FILE_EXT2_NoDump; + flag = "nodump"; + } + else if (strcmp(name, "NoAtime") == 0) { + xar->xmlsts = FILE_EXT2_NoAtime; + flag = "noatime"; + } + else if (strcmp(name, "CompDirty") == 0) { + xar->xmlsts = FILE_EXT2_CompDirty; + flag = "compdirty"; + } + else if (strcmp(name, "CompBlock") == 0) { + xar->xmlsts = FILE_EXT2_CompBlock; + flag = "comprblk"; + } + else if (strcmp(name, "NoCompBlock") == 0) { + xar->xmlsts = FILE_EXT2_NoCompBlock; + flag = "nocomprblk"; + } + else if (strcmp(name, "CompError") == 0) { + xar->xmlsts = FILE_EXT2_CompError; + flag = "comperr"; + } + else if (strcmp(name, "BTree") == 0) { + xar->xmlsts = FILE_EXT2_BTree; + flag = "btree"; + } + else if (strcmp(name, "HashIndexed") == 0) { + xar->xmlsts = FILE_EXT2_HashIndexed; + flag = "hashidx"; + } + else if (strcmp(name, "iMagic") == 0) { + xar->xmlsts = FILE_EXT2_iMagic; + flag = "imagic"; + } + else if (strcmp(name, "Journaled") == 0) { + xar->xmlsts = FILE_EXT2_Journaled; + flag = "journal"; + } + else if (strcmp(name, "NoTail") == 0) { + xar->xmlsts = FILE_EXT2_NoTail; + flag = "notail"; + } + else if (strcmp(name, "DirSync") == 0) { + xar->xmlsts = FILE_EXT2_DirSync; + flag = "dirsync"; + } + else if (strcmp(name, "TopDir") == 0) { + xar->xmlsts = FILE_EXT2_TopDir; + flag = "topdir"; + } + else if (strcmp(name, "Reserved") == 0) { + xar->xmlsts = FILE_EXT2_Reserved; + flag = "reserved"; + } + + if (flag == NULL) + return (0); + if (archive_strlen(&(xar->file->fflags_text)) > 0) + archive_strappend_char(&(xar->file->fflags_text), ','); + archive_strcat(&(xar->file->fflags_text), flag); + return (1); +} + +#ifdef HAVE_LIBXML_XMLREADER_H + +static int +xml2_xmlattr_setup(struct archive_read *a, + struct xmlattr_list *list, xmlTextReaderPtr reader) +{ + struct xmlattr *attr; + int r; + + list->first = NULL; + list->last = &(list->first); + r = xmlTextReaderMoveToFirstAttribute(reader); + while (r == 1) { + attr = malloc(sizeof*(attr)); + if (attr == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + attr->name = strdup( + (const char *)xmlTextReaderConstLocalName(reader)); + if (attr->name == NULL) { + free(attr); + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + attr->value = strdup( + (const char *)xmlTextReaderConstValue(reader)); + if (attr->value == NULL) { + free(attr->name); + free(attr); + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + attr->next = NULL; + *list->last = attr; + list->last = &(attr->next); + r = xmlTextReaderMoveToNextAttribute(reader); + } + return (r); +} + +static int +xml2_read_cb(void *context, char *buffer, int len) +{ + struct archive_read *a; + struct xar *xar; + const void *d; + size_t outbytes; + size_t used = 0; + int r; + + a = (struct archive_read *)context; + xar = (struct xar *)(a->format->data); + + if (xar->toc_remaining <= 0) + return (0); + d = buffer; + outbytes = len; + r = rd_contents(a, &d, &outbytes, &used, xar->toc_remaining); + if (r != ARCHIVE_OK) + return (r); + __archive_read_consume(a, used); + xar->toc_remaining -= used; + xar->offset += used; + xar->toc_total += outbytes; + PRINT_TOC(buffer, len); + + return ((int)outbytes); +} + +static int +xml2_close_cb(void *context) +{ + + (void)context; /* UNUSED */ + return (0); +} + +static void +xml2_error_hdr(void *arg, const char *msg, xmlParserSeverities severity, + xmlTextReaderLocatorPtr locator) +{ + struct archive_read *a; + + (void)locator; /* UNUSED */ + a = (struct archive_read *)arg; + switch (severity) { + case XML_PARSER_SEVERITY_VALIDITY_WARNING: + case XML_PARSER_SEVERITY_WARNING: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "XML Parsing error: %s", msg); + break; + case XML_PARSER_SEVERITY_VALIDITY_ERROR: + case XML_PARSER_SEVERITY_ERROR: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "XML Parsing error: %s", msg); + break; + } +} + +static int +xml2_read_toc(struct archive_read *a) +{ + xmlTextReaderPtr reader; + struct xmlattr_list list; + int r; + + reader = xmlReaderForIO(xml2_read_cb, xml2_close_cb, a, NULL, NULL, 0); + if (reader == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Couldn't allocate memory for xml parser"); + return (ARCHIVE_FATAL); + } + xmlTextReaderSetErrorHandler(reader, xml2_error_hdr, a); + + while ((r = xmlTextReaderRead(reader)) == 1) { + const char *name, *value; + int type, empty; + + type = xmlTextReaderNodeType(reader); + name = (const char *)xmlTextReaderConstLocalName(reader); + switch (type) { + case XML_READER_TYPE_ELEMENT: + empty = xmlTextReaderIsEmptyElement(reader); + r = xml2_xmlattr_setup(a, &list, reader); + if (r == ARCHIVE_OK) + r = xml_start(a, name, &list); + xmlattr_cleanup(&list); + if (r != ARCHIVE_OK) + return (r); + if (empty) + xml_end(a, name); + break; + case XML_READER_TYPE_END_ELEMENT: + xml_end(a, name); + break; + case XML_READER_TYPE_TEXT: + value = (const char *)xmlTextReaderConstValue(reader); + xml_data(a, value, strlen(value)); + break; + case XML_READER_TYPE_SIGNIFICANT_WHITESPACE: + default: + break; + } + if (r < 0) + break; + } + xmlFreeTextReader(reader); + xmlCleanupParser(); + + return ((r == 0)?ARCHIVE_OK:ARCHIVE_FATAL); +} + +#elif defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H) + +static int +expat_xmlattr_setup(struct archive_read *a, + struct xmlattr_list *list, const XML_Char **atts) +{ + struct xmlattr *attr; + char *name, *value; + + list->first = NULL; + list->last = &(list->first); + if (atts == NULL) + return (ARCHIVE_OK); + while (atts[0] != NULL && atts[1] != NULL) { + attr = malloc(sizeof*(attr)); + name = strdup(atts[0]); + value = strdup(atts[1]); + if (attr == NULL || name == NULL || value == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + free(attr); + free(name); + free(value); + return (ARCHIVE_FATAL); + } + attr->name = name; + attr->value = value; + attr->next = NULL; + *list->last = attr; + list->last = &(attr->next); + atts += 2; + } + return (ARCHIVE_OK); +} + +static void +expat_start_cb(void *userData, const XML_Char *name, const XML_Char **atts) +{ + struct expat_userData *ud = (struct expat_userData *)userData; + struct archive_read *a = ud->archive; + struct xmlattr_list list; + int r; + + r = expat_xmlattr_setup(a, &list, atts); + if (r == ARCHIVE_OK) + r = xml_start(a, (const char *)name, &list); + xmlattr_cleanup(&list); + ud->state = r; +} + +static void +expat_end_cb(void *userData, const XML_Char *name) +{ + struct expat_userData *ud = (struct expat_userData *)userData; + + xml_end(ud->archive, (const char *)name); +} + +static void +expat_data_cb(void *userData, const XML_Char *s, int len) +{ + struct expat_userData *ud = (struct expat_userData *)userData; + + xml_data(ud->archive, s, len); +} + +static int +expat_read_toc(struct archive_read *a) +{ + struct xar *xar; + XML_Parser parser; + struct expat_userData ud; + + ud.state = ARCHIVE_OK; + ud.archive = a; + + xar = (struct xar *)(a->format->data); + + /* Initialize XML Parser library. */ + parser = XML_ParserCreate(NULL); + if (parser == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Couldn't allocate memory for xml parser"); + return (ARCHIVE_FATAL); + } + XML_SetUserData(parser, &ud); + XML_SetElementHandler(parser, expat_start_cb, expat_end_cb); + XML_SetCharacterDataHandler(parser, expat_data_cb); + xar->xmlsts = INIT; + + while (xar->toc_remaining && ud.state == ARCHIVE_OK) { + enum XML_Status xr; + const void *d; + size_t outbytes; + size_t used; + int r; + + d = NULL; + r = rd_contents(a, &d, &outbytes, &used, xar->toc_remaining); + if (r != ARCHIVE_OK) + return (r); + xar->toc_remaining -= used; + xar->offset += used; + xar->toc_total += outbytes; + PRINT_TOC(d, outbytes); + + xr = XML_Parse(parser, d, outbytes, xar->toc_remaining == 0); + __archive_read_consume(a, used); + if (xr == XML_STATUS_ERROR) { + XML_ParserFree(parser); + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "XML Parsing failed"); + return (ARCHIVE_FATAL); + } + } + XML_ParserFree(parser); + return (ud.state); +} +#endif /* defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H) */ + +#endif /* Support xar format */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_zip.c b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_zip.c new file mode 100644 index 0000000..6581ca0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_read_support_format_zip.c @@ -0,0 +1,4044 @@ +/*- + * Copyright (c) 2004-2013 Tim Kientzle + * Copyright (c) 2011-2012,2014 Michihiro NAKAJIMA + * Copyright (c) 2013 Konrad Kleine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_zip.c 201102 2009-12-28 03:11:36Z kientzle $"); + +/* + * The definitive documentation of the Zip file format is: + * http://www.pkware.com/documents/casestudies/APPNOTE.TXT + * + * The Info-Zip project has pioneered various extensions to better + * support Zip on Unix, including the 0x5455 "UT", 0x5855 "UX", 0x7855 + * "Ux", and 0x7875 "ux" extensions for time and ownership + * information. + * + * History of this code: The streaming Zip reader was first added to + * libarchive in January 2005. Support for seekable input sources was + * added in Nov 2011. Zip64 support (including a significant code + * refactoring) was added in 2014. + */ + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_ZLIB_H +#include +#endif +#ifdef HAVE_BZLIB_H +#include +#endif +#ifdef HAVE_LZMA_H +#include +#endif + +#include "archive.h" +#include "archive_digest_private.h" +#include "archive_cryptor_private.h" +#include "archive_endian.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_hmac_private.h" +#include "archive_private.h" +#include "archive_rb.h" +#include "archive_read_private.h" +#include "archive_ppmd8_private.h" + +#ifndef HAVE_ZLIB_H +#include "archive_crc32.h" +#endif + +struct zip_entry { + struct archive_rb_node node; + struct zip_entry *next; + int64_t local_header_offset; + int64_t compressed_size; + int64_t uncompressed_size; + int64_t gid; + int64_t uid; + struct archive_string rsrcname; + time_t mtime; + time_t atime; + time_t ctime; + uint32_t crc32; + uint16_t mode; + uint16_t zip_flags; /* From GP Flags Field */ + unsigned char compression; + unsigned char system; /* From "version written by" */ + unsigned char flags; /* Our extra markers. */ + unsigned char decdat;/* Used for Decryption check */ + + /* WinZip AES encryption extra field should be available + * when compression is 99. */ + struct { + /* Vendor version: AE-1 - 0x0001, AE-2 - 0x0002 */ + unsigned vendor; +#define AES_VENDOR_AE_1 0x0001 +#define AES_VENDOR_AE_2 0x0002 + /* AES encryption strength: + * 1 - 128 bits, 2 - 192 bits, 2 - 256 bits. */ + unsigned strength; + /* Actual compression method. */ + unsigned char compression; + } aes_extra; +}; + +struct trad_enc_ctx { + uint32_t keys[3]; +}; + +/* Bits used in zip_flags. */ +#define ZIP_ENCRYPTED (1 << 0) +#define ZIP_LENGTH_AT_END (1 << 3) +#define ZIP_STRONG_ENCRYPTED (1 << 6) +#define ZIP_UTF8_NAME (1 << 11) +/* See "7.2 Single Password Symmetric Encryption Method" + in http://www.pkware.com/documents/casestudies/APPNOTE.TXT */ +#define ZIP_CENTRAL_DIRECTORY_ENCRYPTED (1 << 13) + +/* Bits used in flags. */ +#define LA_USED_ZIP64 (1 << 0) +#define LA_FROM_CENTRAL_DIRECTORY (1 << 1) + +/* + * See "WinZip - AES Encryption Information" + * http://www.winzip.com/aes_info.htm + */ +/* Value used in compression method. */ +#define WINZIP_AES_ENCRYPTION 99 +/* Authentication code size. */ +#define AUTH_CODE_SIZE 10 +/**/ +#define MAX_DERIVED_KEY_BUF_SIZE (AES_MAX_KEY_SIZE * 2 + 2) + +struct zip { + /* Structural information about the archive. */ + struct archive_string format_name; + int64_t central_directory_offset; + size_t central_directory_entries_total; + size_t central_directory_entries_on_this_disk; + int has_encrypted_entries; + + /* List of entries (seekable Zip only) */ + struct zip_entry *zip_entries; + struct archive_rb_tree tree; + struct archive_rb_tree tree_rsrc; + + /* Bytes read but not yet consumed via __archive_read_consume() */ + size_t unconsumed; + + /* Information about entry we're currently reading. */ + struct zip_entry *entry; + int64_t entry_bytes_remaining; + + /* These count the number of bytes actually read for the entry. */ + int64_t entry_compressed_bytes_read; + int64_t entry_uncompressed_bytes_read; + + /* Running CRC32 of the decompressed data */ + unsigned long entry_crc32; + unsigned long (*crc32func)(unsigned long, const void *, + size_t); + char ignore_crc32; + + /* Flags to mark progress of decompression. */ + char decompress_init; + char end_of_entry; + + unsigned char *uncompressed_buffer; + size_t uncompressed_buffer_size; + +#ifdef HAVE_ZLIB_H + z_stream stream; + char stream_valid; +#endif + +#if HAVE_LZMA_H && HAVE_LIBLZMA + lzma_stream zipx_lzma_stream; + char zipx_lzma_valid; +#endif + +#ifdef HAVE_BZLIB_H + bz_stream bzstream; + char bzstream_valid; +#endif + + IByteIn zipx_ppmd_stream; + ssize_t zipx_ppmd_read_compressed; + CPpmd8 ppmd8; + char ppmd8_valid; + char ppmd8_stream_failed; + + struct archive_string_conv *sconv; + struct archive_string_conv *sconv_default; + struct archive_string_conv *sconv_utf8; + int init_default_conversion; + int process_mac_extensions; + + char init_decryption; + + /* Decryption buffer. */ + /* + * The decrypted data starts at decrypted_ptr and + * extends for decrypted_bytes_remaining. Decryption + * adds new data to the end of this block, data is returned + * to clients from the beginning. When the block hits the + * end of decrypted_buffer, it has to be shuffled back to + * the beginning of the buffer. + */ + unsigned char *decrypted_buffer; + unsigned char *decrypted_ptr; + size_t decrypted_buffer_size; + size_t decrypted_bytes_remaining; + size_t decrypted_unconsumed_bytes; + + /* Traditional PKWARE decryption. */ + struct trad_enc_ctx tctx; + char tctx_valid; + + /* WinZip AES decryption. */ + /* Contexts used for AES decryption. */ + archive_crypto_ctx cctx; + char cctx_valid; + archive_hmac_sha1_ctx hctx; + char hctx_valid; + + /* Strong encryption's decryption header information. */ + unsigned iv_size; + unsigned alg_id; + unsigned bit_len; + unsigned flags; + unsigned erd_size; + unsigned v_size; + unsigned v_crc32; + uint8_t *iv; + uint8_t *erd; + uint8_t *v_data; +}; + +/* Many systems define min or MIN, but not all. */ +#define zipmin(a,b) ((a) < (b) ? (a) : (b)) + +/* This function is used by Ppmd8_DecodeSymbol during decompression of Ppmd8 + * streams inside ZIP files. It has 2 purposes: one is to fetch the next + * compressed byte from the stream, second one is to increase the counter how + * many compressed bytes were read. */ +static Byte +ppmd_read(void* p) { + /* Get the handle to current decompression context. */ + struct archive_read *a = ((IByteIn*)p)->a; + struct zip *zip = (struct zip*) a->format->data; + ssize_t bytes_avail = 0; + + /* Fetch next byte. */ + const uint8_t* data = __archive_read_ahead(a, 1, &bytes_avail); + if(bytes_avail < 1) { + zip->ppmd8_stream_failed = 1; + return 0; + } + + __archive_read_consume(a, 1); + + /* Increment the counter. */ + ++zip->zipx_ppmd_read_compressed; + + /* Return the next compressed byte. */ + return data[0]; +} + +/* ------------------------------------------------------------------------ */ + +/* + Traditional PKWARE Decryption functions. + */ + +static void +trad_enc_update_keys(struct trad_enc_ctx *ctx, uint8_t c) +{ + uint8_t t; +#define CRC32(c, b) (crc32(c ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL) + + ctx->keys[0] = CRC32(ctx->keys[0], c); + ctx->keys[1] = (ctx->keys[1] + (ctx->keys[0] & 0xff)) * 134775813L + 1; + t = (ctx->keys[1] >> 24) & 0xff; + ctx->keys[2] = CRC32(ctx->keys[2], t); +#undef CRC32 +} + +static uint8_t +trad_enc_decrypt_byte(struct trad_enc_ctx *ctx) +{ + unsigned temp = ctx->keys[2] | 2; + return (uint8_t)((temp * (temp ^ 1)) >> 8) & 0xff; +} + +static void +trad_enc_decrypt_update(struct trad_enc_ctx *ctx, const uint8_t *in, + size_t in_len, uint8_t *out, size_t out_len) +{ + unsigned i, max; + + max = (unsigned)((in_len < out_len)? in_len: out_len); + + for (i = 0; i < max; i++) { + uint8_t t = in[i] ^ trad_enc_decrypt_byte(ctx); + out[i] = t; + trad_enc_update_keys(ctx, t); + } +} + +static int +trad_enc_init(struct trad_enc_ctx *ctx, const char *pw, size_t pw_len, + const uint8_t *key, size_t key_len, uint8_t *crcchk) +{ + uint8_t header[12]; + + if (key_len < 12) { + *crcchk = 0xff; + return -1; + } + + ctx->keys[0] = 305419896L; + ctx->keys[1] = 591751049L; + ctx->keys[2] = 878082192L; + + for (;pw_len; --pw_len) + trad_enc_update_keys(ctx, *pw++); + + trad_enc_decrypt_update(ctx, key, 12, header, 12); + /* Return the last byte for CRC check. */ + *crcchk = header[11]; + return 0; +} + +#if 0 +static void +crypt_derive_key_sha1(const void *p, int size, unsigned char *key, + int key_size) +{ +#define MD_SIZE 20 + archive_sha1_ctx ctx; + unsigned char md1[MD_SIZE]; + unsigned char md2[MD_SIZE * 2]; + unsigned char mkb[64]; + int i; + + archive_sha1_init(&ctx); + archive_sha1_update(&ctx, p, size); + archive_sha1_final(&ctx, md1); + + memset(mkb, 0x36, sizeof(mkb)); + for (i = 0; i < MD_SIZE; i++) + mkb[i] ^= md1[i]; + archive_sha1_init(&ctx); + archive_sha1_update(&ctx, mkb, sizeof(mkb)); + archive_sha1_final(&ctx, md2); + + memset(mkb, 0x5C, sizeof(mkb)); + for (i = 0; i < MD_SIZE; i++) + mkb[i] ^= md1[i]; + archive_sha1_init(&ctx); + archive_sha1_update(&ctx, mkb, sizeof(mkb)); + archive_sha1_final(&ctx, md2 + MD_SIZE); + + if (key_size > 32) + key_size = 32; + memcpy(key, md2, key_size); +#undef MD_SIZE +} +#endif + +/* + * Common code for streaming or seeking modes. + * + * Includes code to read local file headers, decompress data + * from entry bodies, and common API. + */ + +static unsigned long +real_crc32(unsigned long crc, const void *buff, size_t len) +{ + return crc32(crc, buff, (unsigned int)len); +} + +/* Used by "ignorecrc32" option to speed up tests. */ +static unsigned long +fake_crc32(unsigned long crc, const void *buff, size_t len) +{ + (void)crc; /* UNUSED */ + (void)buff; /* UNUSED */ + (void)len; /* UNUSED */ + return 0; +} + +static const struct { + int id; + const char * name; +} compression_methods[] = { + {0, "uncompressed"}, /* The file is stored (no compression) */ + {1, "shrinking"}, /* The file is Shrunk */ + {2, "reduced-1"}, /* The file is Reduced with compression factor 1 */ + {3, "reduced-2"}, /* The file is Reduced with compression factor 2 */ + {4, "reduced-3"}, /* The file is Reduced with compression factor 3 */ + {5, "reduced-4"}, /* The file is Reduced with compression factor 4 */ + {6, "imploded"}, /* The file is Imploded */ + {7, "reserved"}, /* Reserved for Tokenizing compression algorithm */ + {8, "deflation"}, /* The file is Deflated */ + {9, "deflation-64-bit"}, /* Enhanced Deflating using Deflate64(tm) */ + {10, "ibm-terse"},/* PKWARE Data Compression Library Imploding + * (old IBM TERSE) */ + {11, "reserved"}, /* Reserved by PKWARE */ + {12, "bzip"}, /* File is compressed using BZIP2 algorithm */ + {13, "reserved"}, /* Reserved by PKWARE */ + {14, "lzma"}, /* LZMA (EFS) */ + {15, "reserved"}, /* Reserved by PKWARE */ + {16, "reserved"}, /* Reserved by PKWARE */ + {17, "reserved"}, /* Reserved by PKWARE */ + {18, "ibm-terse-new"}, /* File is compressed using IBM TERSE (new) */ + {19, "ibm-lz777"},/* IBM LZ77 z Architecture (PFS) */ + {95, "xz"}, /* XZ compressed data */ + {96, "jpeg"}, /* JPEG compressed data */ + {97, "wav-pack"}, /* WavPack compressed data */ + {98, "ppmd-1"}, /* PPMd version I, Rev 1 */ + {99, "aes"} /* WinZip AES encryption */ +}; + +static const char * +compression_name(const int compression) +{ + static const int num_compression_methods = + sizeof(compression_methods)/sizeof(compression_methods[0]); + int i=0; + + while(compression >= 0 && i < num_compression_methods) { + if (compression_methods[i].id == compression) + return compression_methods[i].name; + i++; + } + return "??"; +} + +/* Convert an MSDOS-style date/time into Unix-style time. */ +static time_t +zip_time(const char *p) +{ + int msTime, msDate; + struct tm ts; + + msTime = (0xff & (unsigned)p[0]) + 256 * (0xff & (unsigned)p[1]); + msDate = (0xff & (unsigned)p[2]) + 256 * (0xff & (unsigned)p[3]); + + memset(&ts, 0, sizeof(ts)); + ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */ + ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */ + ts.tm_mday = msDate & 0x1f; /* Day of month. */ + ts.tm_hour = (msTime >> 11) & 0x1f; + ts.tm_min = (msTime >> 5) & 0x3f; + ts.tm_sec = (msTime << 1) & 0x3e; + ts.tm_isdst = -1; + return mktime(&ts); +} + +/* + * The extra data is stored as a list of + * id1+size1+data1 + id2+size2+data2 ... + * triplets. id and size are 2 bytes each. + */ +static int +process_extra(struct archive_read *a, struct archive_entry *entry, + const char *p, size_t extra_length, struct zip_entry* zip_entry) +{ + unsigned offset = 0; + struct zip *zip = (struct zip *)(a->format->data); + + if (extra_length == 0) { + return ARCHIVE_OK; + } + + if (extra_length < 4) { + size_t i = 0; + /* Some ZIP files may have trailing 0 bytes. Let's check they + * are all 0 and ignore them instead of returning an error. + * + * This is not technically correct, but some ZIP files look + * like this and other tools support those files - so let's + * also support them. + */ + for (; i < extra_length; i++) { + if (p[i] != 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Too-small extra data: " + "Need at least 4 bytes, " + "but only found %d bytes", + (int)extra_length); + return ARCHIVE_FAILED; + } + } + + return ARCHIVE_OK; + } + + while (offset <= extra_length - 4) { + unsigned short headerid = archive_le16dec(p + offset); + unsigned short datasize = archive_le16dec(p + offset + 2); + + offset += 4; + if (offset + datasize > extra_length) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Extra data overflow: " + "Need %d bytes but only found %d bytes", + (int)datasize, (int)(extra_length - offset)); + return ARCHIVE_FAILED; + } +#ifdef DEBUG + fprintf(stderr, "Header id 0x%04x, length %d\n", + headerid, datasize); +#endif + switch (headerid) { + case 0x0001: + /* Zip64 extended information extra field. */ + zip_entry->flags |= LA_USED_ZIP64; + if (zip_entry->uncompressed_size == 0xffffffff) { + uint64_t t = 0; + if (datasize < 8 + || (t = archive_le64dec(p + offset)) > + INT64_MAX) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Malformed 64-bit " + "uncompressed size"); + return ARCHIVE_FAILED; + } + zip_entry->uncompressed_size = t; + offset += 8; + datasize -= 8; + } + if (zip_entry->compressed_size == 0xffffffff) { + uint64_t t = 0; + if (datasize < 8 + || (t = archive_le64dec(p + offset)) > + INT64_MAX) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Malformed 64-bit " + "compressed size"); + return ARCHIVE_FAILED; + } + zip_entry->compressed_size = t; + offset += 8; + datasize -= 8; + } + if (zip_entry->local_header_offset == 0xffffffff) { + uint64_t t = 0; + if (datasize < 8 + || (t = archive_le64dec(p + offset)) > + INT64_MAX) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Malformed 64-bit " + "local header offset"); + return ARCHIVE_FAILED; + } + zip_entry->local_header_offset = t; + offset += 8; + datasize -= 8; + } + /* archive_le32dec(p + offset) gives disk + * on which file starts, but we don't handle + * multi-volume Zip files. */ + break; +#ifdef DEBUG + case 0x0017: + { + /* Strong encryption field. */ + if (archive_le16dec(p + offset) == 2) { + unsigned algId = + archive_le16dec(p + offset + 2); + unsigned bitLen = + archive_le16dec(p + offset + 4); + int flags = + archive_le16dec(p + offset + 6); + fprintf(stderr, "algId=0x%04x, bitLen=%u, " + "flgas=%d\n", algId, bitLen,flags); + } + break; + } +#endif + case 0x5455: + { + /* Extended time field "UT". */ + int flags; + if (datasize == 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Incomplete extended time field"); + return ARCHIVE_FAILED; + } + flags = p[offset]; + offset++; + datasize--; + /* Flag bits indicate which dates are present. */ + if (flags & 0x01) + { +#ifdef DEBUG + fprintf(stderr, "mtime: %lld -> %d\n", + (long long)zip_entry->mtime, + archive_le32dec(p + offset)); +#endif + if (datasize < 4) + break; + zip_entry->mtime = archive_le32dec(p + offset); + offset += 4; + datasize -= 4; + } + if (flags & 0x02) + { + if (datasize < 4) + break; + zip_entry->atime = archive_le32dec(p + offset); + offset += 4; + datasize -= 4; + } + if (flags & 0x04) + { + if (datasize < 4) + break; + zip_entry->ctime = archive_le32dec(p + offset); + offset += 4; + datasize -= 4; + } + break; + } + case 0x5855: + { + /* Info-ZIP Unix Extra Field (old version) "UX". */ + if (datasize >= 8) { + zip_entry->atime = archive_le32dec(p + offset); + zip_entry->mtime = + archive_le32dec(p + offset + 4); + } + if (datasize >= 12) { + zip_entry->uid = + archive_le16dec(p + offset + 8); + zip_entry->gid = + archive_le16dec(p + offset + 10); + } + break; + } + case 0x6c78: + { + /* Experimental 'xl' field */ + /* + * Introduced Dec 2013 to provide a way to + * include external file attributes (and other + * fields that ordinarily appear only in + * central directory) in local file header. + * This provides file type and permission + * information necessary to support full + * streaming extraction. Currently being + * discussed with other Zip developers + * ... subject to change. + * + * Format: + * The field starts with a bitmap that specifies + * which additional fields are included. The + * bitmap is variable length and can be extended in + * the future. + * + * n bytes - feature bitmap: first byte has low-order + * 7 bits. If high-order bit is set, a subsequent + * byte holds the next 7 bits, etc. + * + * if bitmap & 1, 2 byte "version made by" + * if bitmap & 2, 2 byte "internal file attributes" + * if bitmap & 4, 4 byte "external file attributes" + * if bitmap & 8, 2 byte comment length + n byte + * comment + */ + int bitmap, bitmap_last; + + if (datasize < 1) + break; + bitmap_last = bitmap = 0xff & p[offset]; + offset += 1; + datasize -= 1; + + /* We only support first 7 bits of bitmap; skip rest. */ + while ((bitmap_last & 0x80) != 0 + && datasize >= 1) { + bitmap_last = p[offset]; + offset += 1; + datasize -= 1; + } + + if (bitmap & 1) { + /* 2 byte "version made by" */ + if (datasize < 2) + break; + zip_entry->system + = archive_le16dec(p + offset) >> 8; + offset += 2; + datasize -= 2; + } + if (bitmap & 2) { + /* 2 byte "internal file attributes" */ + uint32_t internal_attributes; + if (datasize < 2) + break; + internal_attributes + = archive_le16dec(p + offset); + /* Not used by libarchive at present. */ + (void)internal_attributes; /* UNUSED */ + offset += 2; + datasize -= 2; + } + if (bitmap & 4) { + /* 4 byte "external file attributes" */ + uint32_t external_attributes; + if (datasize < 4) + break; + external_attributes + = archive_le32dec(p + offset); + if (zip_entry->system == 3) { + zip_entry->mode + = external_attributes >> 16; + } else if (zip_entry->system == 0) { + // Interpret MSDOS directory bit + if (0x10 == (external_attributes & + 0x10)) { + zip_entry->mode = + AE_IFDIR | 0775; + } else { + zip_entry->mode = + AE_IFREG | 0664; + } + if (0x01 == (external_attributes & + 0x01)) { + /* Read-only bit; + * strip write permissions */ + zip_entry->mode &= 0555; + } + } else { + zip_entry->mode = 0; + } + offset += 4; + datasize -= 4; + } + if (bitmap & 8) { + /* 2 byte comment length + comment */ + uint32_t comment_length; + if (datasize < 2) + break; + comment_length + = archive_le16dec(p + offset); + offset += 2; + datasize -= 2; + + if (datasize < comment_length) + break; + /* Comment is not supported by libarchive */ + offset += comment_length; + datasize -= comment_length; + } + break; + } + case 0x7075: + { + /* Info-ZIP Unicode Path Extra Field. */ + if (datasize < 5 || entry == NULL) + break; + offset += 5; + datasize -= 5; + + /* The path name in this field is always encoded + * in UTF-8. */ + if (zip->sconv_utf8 == NULL) { + zip->sconv_utf8 = + archive_string_conversion_from_charset( + &a->archive, "UTF-8", 1); + /* If the converter from UTF-8 is not + * available, then the path name from the main + * field will more likely be correct. */ + if (zip->sconv_utf8 == NULL) + break; + } + + /* Make sure the CRC32 of the filename matches. */ + if (!zip->ignore_crc32) { + const char *cp = archive_entry_pathname(entry); + if (cp) { + unsigned long file_crc = + zip->crc32func(0, cp, strlen(cp)); + unsigned long utf_crc = + archive_le32dec(p + offset - 4); + if (file_crc != utf_crc) { +#ifdef DEBUG + fprintf(stderr, + "CRC filename mismatch; " + "CDE is %lx, but UTF8 " + "is outdated with %lx\n", + file_crc, utf_crc); +#endif + break; + } + } + } + + if (archive_entry_copy_pathname_l(entry, + p + offset, datasize, zip->sconv_utf8) != 0) { + /* Ignore the error, and fallback to the path + * name from the main field. */ +#ifdef DEBUG + fprintf(stderr, "Failed to read the ZIP " + "0x7075 extra field path.\n"); +#endif + } + break; + } + case 0x7855: + /* Info-ZIP Unix Extra Field (type 2) "Ux". */ +#ifdef DEBUG + fprintf(stderr, "uid %d gid %d\n", + archive_le16dec(p + offset), + archive_le16dec(p + offset + 2)); +#endif + if (datasize >= 2) + zip_entry->uid = archive_le16dec(p + offset); + if (datasize >= 4) + zip_entry->gid = + archive_le16dec(p + offset + 2); + break; + case 0x7875: + { + /* Info-Zip Unix Extra Field (type 3) "ux". */ + int uidsize = 0, gidsize = 0; + + /* TODO: support arbitrary uidsize/gidsize. */ + if (datasize >= 1 && p[offset] == 1) {/* version=1 */ + if (datasize >= 4) { + /* get a uid size. */ + uidsize = 0xff & (int)p[offset+1]; + if (uidsize == 2) + zip_entry->uid = + archive_le16dec( + p + offset + 2); + else if (uidsize == 4 && datasize >= 6) + zip_entry->uid = + archive_le32dec( + p + offset + 2); + } + if (datasize >= (2 + uidsize + 3)) { + /* get a gid size. */ + gidsize = 0xff & + (int)p[offset+2+uidsize]; + if (gidsize == 2) + zip_entry->gid = + archive_le16dec( + p+offset+2+uidsize+1); + else if (gidsize == 4 && + datasize >= (2 + uidsize + 5)) + zip_entry->gid = + archive_le32dec( + p+offset+2+uidsize+1); + } + } + break; + } + case 0x9901: + /* WinZip AES extra data field. */ + if (datasize < 6) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Incomplete AES field"); + return ARCHIVE_FAILED; + } + if (p[offset + 2] == 'A' && p[offset + 3] == 'E') { + /* Vendor version. */ + zip_entry->aes_extra.vendor = + archive_le16dec(p + offset); + /* AES encryption strength. */ + zip_entry->aes_extra.strength = p[offset + 4]; + /* Actual compression method. */ + zip_entry->aes_extra.compression = + p[offset + 5]; + } + break; + default: + break; + } + offset += datasize; + } + return ARCHIVE_OK; +} + +/* + * Assumes file pointer is at beginning of local file header. + */ +static int +zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry, + struct zip *zip) +{ + const char *p; + const void *h; + const wchar_t *wp; + const char *cp; + size_t len, filename_length, extra_length; + struct archive_string_conv *sconv; + struct zip_entry *zip_entry = zip->entry; + struct zip_entry zip_entry_central_dir; + int ret = ARCHIVE_OK; + char version; + + /* Save a copy of the original for consistency checks. */ + zip_entry_central_dir = *zip_entry; + + zip->decompress_init = 0; + zip->end_of_entry = 0; + zip->entry_uncompressed_bytes_read = 0; + zip->entry_compressed_bytes_read = 0; + zip->entry_crc32 = zip->crc32func(0, NULL, 0); + + /* Setup default conversion. */ + if (zip->sconv == NULL && !zip->init_default_conversion) { + zip->sconv_default = + archive_string_default_conversion_for_read(&(a->archive)); + zip->init_default_conversion = 1; + } + + if ((p = __archive_read_ahead(a, 30, NULL)) == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file header"); + return (ARCHIVE_FATAL); + } + + if (memcmp(p, "PK\003\004", 4) != 0) { + archive_set_error(&a->archive, -1, "Damaged Zip archive"); + return ARCHIVE_FATAL; + } + version = p[4]; + zip_entry->system = p[5]; + zip_entry->zip_flags = archive_le16dec(p + 6); + if (zip_entry->zip_flags & (ZIP_ENCRYPTED | ZIP_STRONG_ENCRYPTED)) { + zip->has_encrypted_entries = 1; + archive_entry_set_is_data_encrypted(entry, 1); + if (zip_entry->zip_flags & ZIP_CENTRAL_DIRECTORY_ENCRYPTED && + zip_entry->zip_flags & ZIP_ENCRYPTED && + zip_entry->zip_flags & ZIP_STRONG_ENCRYPTED) { + archive_entry_set_is_metadata_encrypted(entry, 1); + return ARCHIVE_FATAL; + } + } + zip->init_decryption = (zip_entry->zip_flags & ZIP_ENCRYPTED); + zip_entry->compression = (char)archive_le16dec(p + 8); + zip_entry->mtime = zip_time(p + 10); + zip_entry->crc32 = archive_le32dec(p + 14); + if (zip_entry->zip_flags & ZIP_LENGTH_AT_END) + zip_entry->decdat = p[11]; + else + zip_entry->decdat = p[17]; + zip_entry->compressed_size = archive_le32dec(p + 18); + zip_entry->uncompressed_size = archive_le32dec(p + 22); + filename_length = archive_le16dec(p + 26); + extra_length = archive_le16dec(p + 28); + + __archive_read_consume(a, 30); + + /* Read the filename. */ + if ((h = __archive_read_ahead(a, filename_length, NULL)) == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file header"); + return (ARCHIVE_FATAL); + } + if (zip_entry->zip_flags & ZIP_UTF8_NAME) { + /* The filename is stored to be UTF-8. */ + if (zip->sconv_utf8 == NULL) { + zip->sconv_utf8 = + archive_string_conversion_from_charset( + &a->archive, "UTF-8", 1); + if (zip->sconv_utf8 == NULL) + return (ARCHIVE_FATAL); + } + sconv = zip->sconv_utf8; + } else if (zip->sconv != NULL) + sconv = zip->sconv; + else + sconv = zip->sconv_default; + + if (archive_entry_copy_pathname_l(entry, + h, filename_length, sconv) != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Pathname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Pathname cannot be converted " + "from %s to current locale.", + archive_string_conversion_charset_name(sconv)); + ret = ARCHIVE_WARN; + } + __archive_read_consume(a, filename_length); + + /* Read the extra data. */ + if ((h = __archive_read_ahead(a, extra_length, NULL)) == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file header"); + return (ARCHIVE_FATAL); + } + + if (ARCHIVE_OK != process_extra(a, entry, h, extra_length, + zip_entry)) { + return ARCHIVE_FATAL; + } + __archive_read_consume(a, extra_length); + + /* Work around a bug in Info-Zip: When reading from a pipe, it + * stats the pipe instead of synthesizing a file entry. */ + if ((zip_entry->mode & AE_IFMT) == AE_IFIFO) { + zip_entry->mode &= ~ AE_IFMT; + zip_entry->mode |= AE_IFREG; + } + + /* If the mode is totally empty, set some sane default. */ + if (zip_entry->mode == 0) { + zip_entry->mode |= 0664; + } + + /* Windows archivers sometimes use backslash as the directory + * separator. Normalize to slash. */ + if (zip_entry->system == 0 && + (wp = archive_entry_pathname_w(entry)) != NULL) { + if (wcschr(wp, L'/') == NULL && wcschr(wp, L'\\') != NULL) { + size_t i; + struct archive_wstring s; + archive_string_init(&s); + archive_wstrcpy(&s, wp); + for (i = 0; i < archive_strlen(&s); i++) { + if (s.s[i] == '\\') + s.s[i] = '/'; + } + archive_entry_copy_pathname_w(entry, s.s); + archive_wstring_free(&s); + } + } + + /* Make sure that entries with a trailing '/' are marked as directories + * even if the External File Attributes contains bogus values. If this + * is not a directory and there is no type, assume a regular file. */ + if ((zip_entry->mode & AE_IFMT) != AE_IFDIR) { + int has_slash; + + wp = archive_entry_pathname_w(entry); + if (wp != NULL) { + len = wcslen(wp); + has_slash = len > 0 && wp[len - 1] == L'/'; + } else { + cp = archive_entry_pathname(entry); + len = (cp != NULL)?strlen(cp):0; + has_slash = len > 0 && cp[len - 1] == '/'; + } + /* Correct file type as needed. */ + if (has_slash) { + zip_entry->mode &= ~AE_IFMT; + zip_entry->mode |= AE_IFDIR; + zip_entry->mode |= 0111; + } else if ((zip_entry->mode & AE_IFMT) == 0) { + zip_entry->mode |= AE_IFREG; + } + } + + /* Make sure directories end in '/' */ + if ((zip_entry->mode & AE_IFMT) == AE_IFDIR) { + wp = archive_entry_pathname_w(entry); + if (wp != NULL) { + len = wcslen(wp); + if (len > 0 && wp[len - 1] != L'/') { + struct archive_wstring s; + archive_string_init(&s); + archive_wstrcat(&s, wp); + archive_wstrappend_wchar(&s, L'/'); + archive_entry_copy_pathname_w(entry, s.s); + archive_wstring_free(&s); + } + } else { + cp = archive_entry_pathname(entry); + len = (cp != NULL)?strlen(cp):0; + if (len > 0 && cp[len - 1] != '/') { + struct archive_string s; + archive_string_init(&s); + archive_strcat(&s, cp); + archive_strappend_char(&s, '/'); + archive_entry_set_pathname(entry, s.s); + archive_string_free(&s); + } + } + } + + if (zip_entry->flags & LA_FROM_CENTRAL_DIRECTORY) { + /* If this came from the central dir, its size info + * is definitive, so ignore the length-at-end flag. */ + zip_entry->zip_flags &= ~ZIP_LENGTH_AT_END; + /* If local header is missing a value, use the one from + the central directory. If both have it, warn about + mismatches. */ + if (zip_entry->crc32 == 0) { + zip_entry->crc32 = zip_entry_central_dir.crc32; + } else if (!zip->ignore_crc32 + && zip_entry->crc32 != zip_entry_central_dir.crc32) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Inconsistent CRC32 values"); + ret = ARCHIVE_WARN; + } + if (zip_entry->compressed_size == 0) { + zip_entry->compressed_size + = zip_entry_central_dir.compressed_size; + } else if (zip_entry->compressed_size + != zip_entry_central_dir.compressed_size) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Inconsistent compressed size: " + "%jd in central directory, %jd in local header", + (intmax_t)zip_entry_central_dir.compressed_size, + (intmax_t)zip_entry->compressed_size); + ret = ARCHIVE_WARN; + } + if (zip_entry->uncompressed_size == 0) { + zip_entry->uncompressed_size + = zip_entry_central_dir.uncompressed_size; + } else if (zip_entry->uncompressed_size + != zip_entry_central_dir.uncompressed_size) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Inconsistent uncompressed size: " + "%jd in central directory, %jd in local header", + (intmax_t)zip_entry_central_dir.uncompressed_size, + (intmax_t)zip_entry->uncompressed_size); + ret = ARCHIVE_WARN; + } + } + + /* Populate some additional entry fields: */ + archive_entry_set_mode(entry, zip_entry->mode); + archive_entry_set_uid(entry, zip_entry->uid); + archive_entry_set_gid(entry, zip_entry->gid); + archive_entry_set_mtime(entry, zip_entry->mtime, 0); + archive_entry_set_ctime(entry, zip_entry->ctime, 0); + archive_entry_set_atime(entry, zip_entry->atime, 0); + + if ((zip->entry->mode & AE_IFMT) == AE_IFLNK) { + size_t linkname_length; + + if (zip_entry->compressed_size > 64 * 1024) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Zip file with oversized link entry"); + return ARCHIVE_FATAL; + } + + linkname_length = (size_t)zip_entry->compressed_size; + + archive_entry_set_size(entry, 0); + p = __archive_read_ahead(a, linkname_length, NULL); + if (p == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Truncated Zip file"); + return ARCHIVE_FATAL; + } + + sconv = zip->sconv; + if (sconv == NULL && (zip->entry->zip_flags & ZIP_UTF8_NAME)) + sconv = zip->sconv_utf8; + if (sconv == NULL) + sconv = zip->sconv_default; + if (archive_entry_copy_symlink_l(entry, p, linkname_length, + sconv) != 0) { + if (errno != ENOMEM && sconv == zip->sconv_utf8 && + (zip->entry->zip_flags & ZIP_UTF8_NAME)) + archive_entry_copy_symlink_l(entry, p, + linkname_length, NULL); + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Symlink"); + return (ARCHIVE_FATAL); + } + /* + * Since there is no character-set regulation for + * symlink name, do not report the conversion error + * in an automatic conversion. + */ + if (sconv != zip->sconv_utf8 || + (zip->entry->zip_flags & ZIP_UTF8_NAME) == 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Symlink cannot be converted " + "from %s to current locale.", + archive_string_conversion_charset_name( + sconv)); + ret = ARCHIVE_WARN; + } + } + zip_entry->uncompressed_size = zip_entry->compressed_size = 0; + + if (__archive_read_consume(a, linkname_length) < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Read error skipping symlink target name"); + return ARCHIVE_FATAL; + } + } else if (0 == (zip_entry->zip_flags & ZIP_LENGTH_AT_END) + || zip_entry->uncompressed_size > 0) { + /* Set the size only if it's meaningful. */ + archive_entry_set_size(entry, zip_entry->uncompressed_size); + } + zip->entry_bytes_remaining = zip_entry->compressed_size; + + /* If there's no body, force read_data() to return EOF immediately. */ + if (0 == (zip_entry->zip_flags & ZIP_LENGTH_AT_END) + && zip->entry_bytes_remaining < 1) + zip->end_of_entry = 1; + + /* Set up a more descriptive format name. */ + archive_string_empty(&zip->format_name); + archive_string_sprintf(&zip->format_name, "ZIP %d.%d (%s)", + version / 10, version % 10, + compression_name(zip->entry->compression)); + a->archive.archive_format_name = zip->format_name.s; + + return (ret); +} + +static int +check_authentication_code(struct archive_read *a, const void *_p) +{ + struct zip *zip = (struct zip *)(a->format->data); + + /* Check authentication code. */ + if (zip->hctx_valid) { + const void *p; + uint8_t hmac[20]; + size_t hmac_len = 20; + int cmp; + + archive_hmac_sha1_final(&zip->hctx, hmac, &hmac_len); + if (_p == NULL) { + /* Read authentication code. */ + p = __archive_read_ahead(a, AUTH_CODE_SIZE, NULL); + if (p == NULL) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file data"); + return (ARCHIVE_FATAL); + } + } else { + p = _p; + } + cmp = memcmp(hmac, p, AUTH_CODE_SIZE); + __archive_read_consume(a, AUTH_CODE_SIZE); + if (cmp != 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "ZIP bad Authentication code"); + return (ARCHIVE_WARN); + } + } + return (ARCHIVE_OK); +} + +/* + * Read "uncompressed" data. There are three cases: + * 1) We know the size of the data. This is always true for the + * seeking reader (we've examined the Central Directory already). + * 2) ZIP_LENGTH_AT_END was set, but only the CRC was deferred. + * Info-ZIP seems to do this; we know the size but have to grab + * the CRC from the data descriptor afterwards. + * 3) We're streaming and ZIP_LENGTH_AT_END was specified and + * we have no size information. In this case, we can do pretty + * well by watching for the data descriptor record. The data + * descriptor is 16 bytes and includes a computed CRC that should + * provide a strong check. + * + * TODO: Technically, the PK\007\010 signature is optional. + * In the original spec, the data descriptor contained CRC + * and size fields but had no leading signature. In practice, + * newer writers seem to provide the signature pretty consistently. + * + * For uncompressed data, the PK\007\010 marker seems essential + * to be sure we've actually seen the end of the entry. + * + * Returns ARCHIVE_OK if successful, ARCHIVE_FATAL otherwise, sets + * zip->end_of_entry if it consumes all of the data. + */ +static int +zip_read_data_none(struct archive_read *a, const void **_buff, + size_t *size, int64_t *offset) +{ + struct zip *zip; + const char *buff; + ssize_t bytes_avail; + int r; + + (void)offset; /* UNUSED */ + + zip = (struct zip *)(a->format->data); + + if (zip->entry->zip_flags & ZIP_LENGTH_AT_END) { + const char *p; + ssize_t grabbing_bytes = 24; + + if (zip->hctx_valid) + grabbing_bytes += AUTH_CODE_SIZE; + /* Grab at least 24 bytes. */ + buff = __archive_read_ahead(a, grabbing_bytes, &bytes_avail); + if (bytes_avail < grabbing_bytes) { + /* Zip archives have end-of-archive markers + that are longer than this, so a failure to get at + least 24 bytes really does indicate a truncated + file. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file data"); + return (ARCHIVE_FATAL); + } + /* Check for a complete PK\007\010 signature, followed + * by the correct 4-byte CRC. */ + p = buff; + if (zip->hctx_valid) + p += AUTH_CODE_SIZE; + if (p[0] == 'P' && p[1] == 'K' + && p[2] == '\007' && p[3] == '\010' + && (archive_le32dec(p + 4) == zip->entry_crc32 + || zip->ignore_crc32 + || (zip->hctx_valid + && zip->entry->aes_extra.vendor == AES_VENDOR_AE_2))) { + if (zip->entry->flags & LA_USED_ZIP64) { + uint64_t compressed, uncompressed; + zip->entry->crc32 = archive_le32dec(p + 4); + compressed = archive_le64dec(p + 8); + uncompressed = archive_le64dec(p + 16); + if (compressed > INT64_MAX || uncompressed > + INT64_MAX) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Overflow of 64-bit file sizes"); + return ARCHIVE_FAILED; + } + zip->entry->compressed_size = compressed; + zip->entry->uncompressed_size = uncompressed; + zip->unconsumed = 24; + } else { + zip->entry->crc32 = archive_le32dec(p + 4); + zip->entry->compressed_size = + archive_le32dec(p + 8); + zip->entry->uncompressed_size = + archive_le32dec(p + 12); + zip->unconsumed = 16; + } + if (zip->hctx_valid) { + r = check_authentication_code(a, buff); + if (r != ARCHIVE_OK) + return (r); + } + zip->end_of_entry = 1; + return (ARCHIVE_OK); + } + /* If not at EOF, ensure we consume at least one byte. */ + ++p; + + /* Scan forward until we see where a PK\007\010 signature + * might be. */ + /* Return bytes up until that point. On the next call, + * the code above will verify the data descriptor. */ + while (p < buff + bytes_avail - 4) { + if (p[3] == 'P') { p += 3; } + else if (p[3] == 'K') { p += 2; } + else if (p[3] == '\007') { p += 1; } + else if (p[3] == '\010' && p[2] == '\007' + && p[1] == 'K' && p[0] == 'P') { + if (zip->hctx_valid) + p -= AUTH_CODE_SIZE; + break; + } else { p += 4; } + } + bytes_avail = p - buff; + } else { + if (zip->entry_bytes_remaining == 0) { + zip->end_of_entry = 1; + if (zip->hctx_valid) { + r = check_authentication_code(a, NULL); + if (r != ARCHIVE_OK) + return (r); + } + return (ARCHIVE_OK); + } + /* Grab a bunch of bytes. */ + buff = __archive_read_ahead(a, 1, &bytes_avail); + if (bytes_avail <= 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file data"); + return (ARCHIVE_FATAL); + } + if (bytes_avail > zip->entry_bytes_remaining) + bytes_avail = (ssize_t)zip->entry_bytes_remaining; + } + if (zip->tctx_valid || zip->cctx_valid) { + size_t dec_size = bytes_avail; + + if (dec_size > zip->decrypted_buffer_size) + dec_size = zip->decrypted_buffer_size; + if (zip->tctx_valid) { + trad_enc_decrypt_update(&zip->tctx, + (const uint8_t *)buff, dec_size, + zip->decrypted_buffer, dec_size); + } else { + size_t dsize = dec_size; + archive_hmac_sha1_update(&zip->hctx, + (const uint8_t *)buff, dec_size); + archive_decrypto_aes_ctr_update(&zip->cctx, + (const uint8_t *)buff, dec_size, + zip->decrypted_buffer, &dsize); + } + bytes_avail = dec_size; + buff = (const char *)zip->decrypted_buffer; + } + *size = bytes_avail; + zip->entry_bytes_remaining -= bytes_avail; + zip->entry_uncompressed_bytes_read += bytes_avail; + zip->entry_compressed_bytes_read += bytes_avail; + zip->unconsumed += bytes_avail; + *_buff = buff; + return (ARCHIVE_OK); +} + +static int +consume_optional_marker(struct archive_read *a, struct zip *zip) +{ + if (zip->end_of_entry && (zip->entry->zip_flags & ZIP_LENGTH_AT_END)) { + const char *p; + + if (NULL == (p = __archive_read_ahead(a, 24, NULL))) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP end-of-file record"); + return (ARCHIVE_FATAL); + } + /* Consume the optional PK\007\010 marker. */ + if (p[0] == 'P' && p[1] == 'K' && + p[2] == '\007' && p[3] == '\010') { + p += 4; + zip->unconsumed = 4; + } + if (zip->entry->flags & LA_USED_ZIP64) { + uint64_t compressed, uncompressed; + zip->entry->crc32 = archive_le32dec(p); + compressed = archive_le64dec(p + 4); + uncompressed = archive_le64dec(p + 12); + if (compressed > INT64_MAX || + uncompressed > INT64_MAX) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Overflow of 64-bit file sizes"); + return ARCHIVE_FAILED; + } + zip->entry->compressed_size = compressed; + zip->entry->uncompressed_size = uncompressed; + zip->unconsumed += 20; + } else { + zip->entry->crc32 = archive_le32dec(p); + zip->entry->compressed_size = archive_le32dec(p + 4); + zip->entry->uncompressed_size = archive_le32dec(p + 8); + zip->unconsumed += 12; + } + } + + return (ARCHIVE_OK); +} + +#if HAVE_LZMA_H && HAVE_LIBLZMA +static int +zipx_xz_init(struct archive_read *a, struct zip *zip) +{ + lzma_ret r; + + if(zip->zipx_lzma_valid) { + lzma_end(&zip->zipx_lzma_stream); + zip->zipx_lzma_valid = 0; + } + + memset(&zip->zipx_lzma_stream, 0, sizeof(zip->zipx_lzma_stream)); + r = lzma_stream_decoder(&zip->zipx_lzma_stream, UINT64_MAX, 0); + if (r != LZMA_OK) { + archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, + "xz initialization failed(%d)", + r); + + return (ARCHIVE_FAILED); + } + + zip->zipx_lzma_valid = 1; + + free(zip->uncompressed_buffer); + + zip->uncompressed_buffer_size = 256 * 1024; + zip->uncompressed_buffer = + (uint8_t*) malloc(zip->uncompressed_buffer_size); + if (zip->uncompressed_buffer == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for xz decompression"); + return (ARCHIVE_FATAL); + } + + zip->decompress_init = 1; + return (ARCHIVE_OK); +} + +static int +zipx_lzma_alone_init(struct archive_read *a, struct zip *zip) +{ + lzma_ret r; + const uint8_t* p; + +#pragma pack(push) +#pragma pack(1) + struct _alone_header { + uint8_t bytes[5]; + uint64_t uncompressed_size; + } alone_header; +#pragma pack(pop) + + if(zip->zipx_lzma_valid) { + lzma_end(&zip->zipx_lzma_stream); + zip->zipx_lzma_valid = 0; + } + + /* To unpack ZIPX's "LZMA" (id 14) stream we can use standard liblzma + * that is a part of XZ Utils. The stream format stored inside ZIPX + * file is a modified "lzma alone" file format, that was used by the + * `lzma` utility which was later deprecated in favour of `xz` utility. * Since those formats are nearly the same, we can use a standard + * "lzma alone" decoder from XZ Utils. */ + + memset(&zip->zipx_lzma_stream, 0, sizeof(zip->zipx_lzma_stream)); + r = lzma_alone_decoder(&zip->zipx_lzma_stream, UINT64_MAX); + if (r != LZMA_OK) { + archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, + "lzma initialization failed(%d)", r); + + return (ARCHIVE_FAILED); + } + + /* Flag the cleanup function that we want our lzma-related structures + * to be freed later. */ + zip->zipx_lzma_valid = 1; + + /* The "lzma alone" file format and the stream format inside ZIPx are + * almost the same. Here's an example of a structure of "lzma alone" + * format: + * + * $ cat /bin/ls | lzma | xxd | head -n 1 + * 00000000: 5d00 0080 00ff ffff ffff ffff ff00 2814 + * + * 5 bytes 8 bytes n bytes + * + * + * lzma_params is a 5-byte blob that has to be decoded to extract + * parameters of this LZMA stream. The uncompressed_size field is an + * uint64_t value that contains information about the size of the + * uncompressed file, or UINT64_MAX if this value is unknown. + * The part is the actual lzma-compressed data stream. + * + * Now here's the structure of the stream inside the ZIPX file: + * + * $ cat stream_inside_zipx | xxd | head -n 1 + * 00000000: 0914 0500 5d00 8000 0000 2814 .... .... + * + * 2byte 2byte 5 bytes n bytes + * + * + * This means that the ZIPX file contains an additional magic1 and + * magic2 headers, the lzma_params field contains the same parameter + * set as in the "lzma alone" format, and the field is the + * same as in the "lzma alone" format as well. Note that also the zipx + * format is missing the uncompressed_size field. + * + * So, in order to use the "lzma alone" decoder for the zipx lzma + * stream, we simply need to shuffle around some fields, prepare a new + * lzma alone header, feed it into lzma alone decoder so it will + * initialize itself properly, and then we can start feeding normal + * zipx lzma stream into the decoder. + */ + + /* Read magic1,magic2,lzma_params from the ZIPX stream. */ + if((p = __archive_read_ahead(a, 9, NULL)) == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated lzma data"); + return (ARCHIVE_FATAL); + } + + if(p[2] != 0x05 || p[3] != 0x00) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid lzma data"); + return (ARCHIVE_FATAL); + } + + /* Prepare an lzma alone header: copy the lzma_params blob into + * a proper place into the lzma alone header. */ + memcpy(&alone_header.bytes[0], p + 4, 5); + + /* Initialize the 'uncompressed size' field to unknown; we'll manually + * monitor how many bytes there are still to be uncompressed. */ + alone_header.uncompressed_size = UINT64_MAX; + + if(!zip->uncompressed_buffer) { + zip->uncompressed_buffer_size = 256 * 1024; + zip->uncompressed_buffer = + (uint8_t*) malloc(zip->uncompressed_buffer_size); + + if (zip->uncompressed_buffer == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for lzma decompression"); + return (ARCHIVE_FATAL); + } + } + + zip->zipx_lzma_stream.next_in = (void*) &alone_header; + zip->zipx_lzma_stream.avail_in = sizeof(alone_header); + zip->zipx_lzma_stream.total_in = 0; + zip->zipx_lzma_stream.next_out = zip->uncompressed_buffer; + zip->zipx_lzma_stream.avail_out = zip->uncompressed_buffer_size; + zip->zipx_lzma_stream.total_out = 0; + + /* Feed only the header into the lzma alone decoder. This will + * effectively initialize the decoder, and will not produce any + * output bytes yet. */ + r = lzma_code(&zip->zipx_lzma_stream, LZMA_RUN); + if (r != LZMA_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "lzma stream initialization error"); + return ARCHIVE_FATAL; + } + + /* We've already consumed some bytes, so take this into account. */ + __archive_read_consume(a, 9); + zip->entry_bytes_remaining -= 9; + zip->entry_compressed_bytes_read += 9; + + zip->decompress_init = 1; + return (ARCHIVE_OK); +} + +static int +zip_read_data_zipx_xz(struct archive_read *a, const void **buff, + size_t *size, int64_t *offset) +{ + struct zip* zip = (struct zip *)(a->format->data); + int ret; + lzma_ret lz_ret; + const void* compressed_buf; + ssize_t bytes_avail, in_bytes, to_consume = 0; + + (void) offset; /* UNUSED */ + + /* Initialize decompressor if not yet initialized. */ + if (!zip->decompress_init) { + ret = zipx_xz_init(a, zip); + if (ret != ARCHIVE_OK) + return (ret); + } + + compressed_buf = __archive_read_ahead(a, 1, &bytes_avail); + if (bytes_avail < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated xz file body"); + return (ARCHIVE_FATAL); + } + + in_bytes = zipmin(zip->entry_bytes_remaining, bytes_avail); + zip->zipx_lzma_stream.next_in = compressed_buf; + zip->zipx_lzma_stream.avail_in = in_bytes; + zip->zipx_lzma_stream.total_in = 0; + zip->zipx_lzma_stream.next_out = zip->uncompressed_buffer; + zip->zipx_lzma_stream.avail_out = zip->uncompressed_buffer_size; + zip->zipx_lzma_stream.total_out = 0; + + /* Perform the decompression. */ + lz_ret = lzma_code(&zip->zipx_lzma_stream, LZMA_RUN); + switch(lz_ret) { + case LZMA_DATA_ERROR: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "xz data error (error %d)", (int) lz_ret); + return (ARCHIVE_FATAL); + + case LZMA_NO_CHECK: + case LZMA_OK: + break; + + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "xz unknown error %d", (int) lz_ret); + return (ARCHIVE_FATAL); + + case LZMA_STREAM_END: + lzma_end(&zip->zipx_lzma_stream); + zip->zipx_lzma_valid = 0; + + if((int64_t) zip->zipx_lzma_stream.total_in != + zip->entry_bytes_remaining) + { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xz premature end of stream"); + return (ARCHIVE_FATAL); + } + + zip->end_of_entry = 1; + break; + } + + to_consume = zip->zipx_lzma_stream.total_in; + + __archive_read_consume(a, to_consume); + zip->entry_bytes_remaining -= to_consume; + zip->entry_compressed_bytes_read += to_consume; + zip->entry_uncompressed_bytes_read += zip->zipx_lzma_stream.total_out; + + *size = zip->zipx_lzma_stream.total_out; + *buff = zip->uncompressed_buffer; + + ret = consume_optional_marker(a, zip); + if (ret != ARCHIVE_OK) + return (ret); + + return (ARCHIVE_OK); +} + +static int +zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff, + size_t *size, int64_t *offset) +{ + struct zip* zip = (struct zip *)(a->format->data); + int ret; + lzma_ret lz_ret; + const void* compressed_buf; + ssize_t bytes_avail, in_bytes, to_consume; + + (void) offset; /* UNUSED */ + + /* Initialize decompressor if not yet initialized. */ + if (!zip->decompress_init) { + ret = zipx_lzma_alone_init(a, zip); + if (ret != ARCHIVE_OK) + return (ret); + } + + /* Fetch more compressed data. The same note as in deflate handler + * applies here as well: + * + * Note: '1' here is a performance optimization. Recall that the + * decompression layer returns a count of available bytes; asking for + * more than that forces the decompressor to combine reads by copying + * data. + */ + compressed_buf = __archive_read_ahead(a, 1, &bytes_avail); + if (bytes_avail < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated lzma file body"); + return (ARCHIVE_FATAL); + } + + /* Set decompressor parameters. */ + in_bytes = zipmin(zip->entry_bytes_remaining, bytes_avail); + + zip->zipx_lzma_stream.next_in = compressed_buf; + zip->zipx_lzma_stream.avail_in = in_bytes; + zip->zipx_lzma_stream.total_in = 0; + zip->zipx_lzma_stream.next_out = zip->uncompressed_buffer; + zip->zipx_lzma_stream.avail_out = + /* These lzma_alone streams lack end of stream marker, so let's + * make sure the unpacker won't try to unpack more than it's + * supposed to. */ + zipmin((int64_t) zip->uncompressed_buffer_size, + zip->entry->uncompressed_size - + zip->entry_uncompressed_bytes_read); + zip->zipx_lzma_stream.total_out = 0; + + /* Perform the decompression. */ + lz_ret = lzma_code(&zip->zipx_lzma_stream, LZMA_RUN); + switch(lz_ret) { + case LZMA_DATA_ERROR: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "lzma data error (error %d)", (int) lz_ret); + return (ARCHIVE_FATAL); + + /* This case is optional in lzma alone format. It can happen, + * but most of the files don't have it. (GitHub #1257) */ + case LZMA_STREAM_END: + lzma_end(&zip->zipx_lzma_stream); + zip->zipx_lzma_valid = 0; + if((int64_t) zip->zipx_lzma_stream.total_in != + zip->entry_bytes_remaining) + { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "lzma alone premature end of stream"); + return (ARCHIVE_FATAL); + } + + zip->end_of_entry = 1; + break; + + case LZMA_OK: + break; + + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "lzma unknown error %d", (int) lz_ret); + return (ARCHIVE_FATAL); + } + + to_consume = zip->zipx_lzma_stream.total_in; + + /* Update pointers. */ + __archive_read_consume(a, to_consume); + zip->entry_bytes_remaining -= to_consume; + zip->entry_compressed_bytes_read += to_consume; + zip->entry_uncompressed_bytes_read += zip->zipx_lzma_stream.total_out; + + if(zip->entry_bytes_remaining == 0) { + zip->end_of_entry = 1; + } + + /* Return values. */ + *size = zip->zipx_lzma_stream.total_out; + *buff = zip->uncompressed_buffer; + + /* Behave the same way as during deflate decompression. */ + ret = consume_optional_marker(a, zip); + if (ret != ARCHIVE_OK) + return (ret); + + /* Free lzma decoder handle because we'll no longer need it. */ + if(zip->end_of_entry) { + lzma_end(&zip->zipx_lzma_stream); + zip->zipx_lzma_valid = 0; + } + + /* If we're here, then we're good! */ + return (ARCHIVE_OK); +} +#endif /* HAVE_LZMA_H && HAVE_LIBLZMA */ + +static int +zipx_ppmd8_init(struct archive_read *a, struct zip *zip) +{ + const void* p; + uint32_t val; + uint32_t order; + uint32_t mem; + uint32_t restore_method; + + /* Remove previous decompression context if it exists. */ + if(zip->ppmd8_valid) { + __archive_ppmd8_functions.Ppmd8_Free(&zip->ppmd8); + zip->ppmd8_valid = 0; + } + + /* Create a new decompression context. */ + __archive_ppmd8_functions.Ppmd8_Construct(&zip->ppmd8); + zip->ppmd8_stream_failed = 0; + + /* Setup function pointers required by Ppmd8 decompressor. The + * 'ppmd_read' function will feed new bytes to the decompressor, + * and will increment the 'zip->zipx_ppmd_read_compressed' counter. */ + zip->ppmd8.Stream.In = &zip->zipx_ppmd_stream; + zip->zipx_ppmd_stream.a = a; + zip->zipx_ppmd_stream.Read = &ppmd_read; + + /* Reset number of read bytes to 0. */ + zip->zipx_ppmd_read_compressed = 0; + + /* Read Ppmd8 header (2 bytes). */ + p = __archive_read_ahead(a, 2, NULL); + if(!p) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated file data in PPMd8 stream"); + return (ARCHIVE_FATAL); + } + __archive_read_consume(a, 2); + + /* Decode the stream's compression parameters. */ + val = archive_le16dec(p); + order = (val & 15) + 1; + mem = ((val >> 4) & 0xff) + 1; + restore_method = (val >> 12); + + if(order < 2 || restore_method > 2) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid parameter set in PPMd8 stream (order=%d, " + "restore=%d)", order, restore_method); + return (ARCHIVE_FAILED); + } + + /* Allocate the memory needed to properly decompress the file. */ + if(!__archive_ppmd8_functions.Ppmd8_Alloc(&zip->ppmd8, mem << 20)) { + archive_set_error(&a->archive, ENOMEM, + "Unable to allocate memory for PPMd8 stream: %d bytes", + mem << 20); + return (ARCHIVE_FATAL); + } + + /* Signal the cleanup function to release Ppmd8 context in the + * cleanup phase. */ + zip->ppmd8_valid = 1; + + /* Perform further Ppmd8 initialization. */ + if(!__archive_ppmd8_functions.Ppmd8_RangeDec_Init(&zip->ppmd8)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "PPMd8 stream range decoder initialization error"); + return (ARCHIVE_FATAL); + } + + __archive_ppmd8_functions.Ppmd8_Init(&zip->ppmd8, order, + restore_method); + + /* Allocate the buffer that will hold uncompressed data. */ + free(zip->uncompressed_buffer); + + zip->uncompressed_buffer_size = 256 * 1024; + zip->uncompressed_buffer = + (uint8_t*) malloc(zip->uncompressed_buffer_size); + + if(zip->uncompressed_buffer == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for PPMd8 decompression"); + return ARCHIVE_FATAL; + } + + /* Ppmd8 initialization is done. */ + zip->decompress_init = 1; + + /* We've already read 2 bytes in the output stream. Additionally, + * Ppmd8 initialization code could read some data as well. So we + * are advancing the stream by 2 bytes plus whatever number of + * bytes Ppmd8 init function used. */ + zip->entry_compressed_bytes_read += 2 + zip->zipx_ppmd_read_compressed; + + return ARCHIVE_OK; +} + +static int +zip_read_data_zipx_ppmd(struct archive_read *a, const void **buff, + size_t *size, int64_t *offset) +{ + struct zip* zip = (struct zip *)(a->format->data); + int ret; + size_t consumed_bytes = 0; + ssize_t bytes_avail = 0; + + (void) offset; /* UNUSED */ + + /* If we're here for the first time, initialize Ppmd8 decompression + * context first. */ + if(!zip->decompress_init) { + ret = zipx_ppmd8_init(a, zip); + if(ret != ARCHIVE_OK) + return ret; + } + + /* Fetch for more data. We're reading 1 byte here, but libarchive + * should prefetch more bytes. */ + (void) __archive_read_ahead(a, 1, &bytes_avail); + if(bytes_avail < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated PPMd8 file body"); + return (ARCHIVE_FATAL); + } + + /* This counter will be updated inside ppmd_read(), which at one + * point will be called by Ppmd8_DecodeSymbol. */ + zip->zipx_ppmd_read_compressed = 0; + + /* Decompression loop. */ + do { + int sym = __archive_ppmd8_functions.Ppmd8_DecodeSymbol( + &zip->ppmd8); + if(sym < 0) { + zip->end_of_entry = 1; + break; + } + + /* This field is set by ppmd_read() when there was no more data + * to be read. */ + if(zip->ppmd8_stream_failed) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated PPMd8 file body"); + return (ARCHIVE_FATAL); + } + + zip->uncompressed_buffer[consumed_bytes] = (uint8_t) sym; + ++consumed_bytes; + } while(consumed_bytes < zip->uncompressed_buffer_size); + + /* Update pointers for libarchive. */ + *buff = zip->uncompressed_buffer; + *size = consumed_bytes; + + /* Update pointers so we can continue decompression in another call. */ + zip->entry_bytes_remaining -= zip->zipx_ppmd_read_compressed; + zip->entry_compressed_bytes_read += zip->zipx_ppmd_read_compressed; + zip->entry_uncompressed_bytes_read += consumed_bytes; + + /* If we're at the end of stream, deinitialize Ppmd8 context. */ + if(zip->end_of_entry) { + __archive_ppmd8_functions.Ppmd8_Free(&zip->ppmd8); + zip->ppmd8_valid = 0; + } + + /* Seek for optional marker, same way as in each zip entry. */ + ret = consume_optional_marker(a, zip); + if (ret != ARCHIVE_OK) + return ret; + + return ARCHIVE_OK; +} + +#ifdef HAVE_BZLIB_H +static int +zipx_bzip2_init(struct archive_read *a, struct zip *zip) +{ + int r; + + /* Deallocate already existing BZ2 decompression context if it + * exists. */ + if(zip->bzstream_valid) { + BZ2_bzDecompressEnd(&zip->bzstream); + zip->bzstream_valid = 0; + } + + /* Allocate a new BZ2 decompression context. */ + memset(&zip->bzstream, 0, sizeof(bz_stream)); + r = BZ2_bzDecompressInit(&zip->bzstream, 0, 1); + if(r != BZ_OK) { + archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, + "bzip2 initialization failed(%d)", + r); + + return ARCHIVE_FAILED; + } + + /* Mark the bzstream field to be released in cleanup phase. */ + zip->bzstream_valid = 1; + + /* (Re)allocate the buffer that will contain decompressed bytes. */ + free(zip->uncompressed_buffer); + + zip->uncompressed_buffer_size = 256 * 1024; + zip->uncompressed_buffer = + (uint8_t*) malloc(zip->uncompressed_buffer_size); + if (zip->uncompressed_buffer == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for bzip2 decompression"); + return ARCHIVE_FATAL; + } + + /* Initialization done. */ + zip->decompress_init = 1; + return ARCHIVE_OK; +} + +static int +zip_read_data_zipx_bzip2(struct archive_read *a, const void **buff, + size_t *size, int64_t *offset) +{ + struct zip *zip = (struct zip *)(a->format->data); + ssize_t bytes_avail = 0, in_bytes, to_consume; + const void *compressed_buff; + int r; + uint64_t total_out; + + (void) offset; /* UNUSED */ + + /* Initialize decompression context if we're here for the first time. */ + if(!zip->decompress_init) { + r = zipx_bzip2_init(a, zip); + if(r != ARCHIVE_OK) + return r; + } + + /* Fetch more compressed bytes. */ + compressed_buff = __archive_read_ahead(a, 1, &bytes_avail); + if(bytes_avail < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated bzip2 file body"); + return (ARCHIVE_FATAL); + } + + in_bytes = zipmin(zip->entry_bytes_remaining, bytes_avail); + if(in_bytes < 1) { + /* libbz2 doesn't complain when caller feeds avail_in == 0. + * It will actually return success in this case, which is + * undesirable. This is why we need to make this check + * manually. */ + + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated bzip2 file body"); + return (ARCHIVE_FATAL); + } + + /* Setup buffer boundaries. */ + zip->bzstream.next_in = (char*)(uintptr_t) compressed_buff; + zip->bzstream.avail_in = in_bytes; + zip->bzstream.total_in_hi32 = 0; + zip->bzstream.total_in_lo32 = 0; + zip->bzstream.next_out = (char*) zip->uncompressed_buffer; + zip->bzstream.avail_out = zip->uncompressed_buffer_size; + zip->bzstream.total_out_hi32 = 0; + zip->bzstream.total_out_lo32 = 0; + + /* Perform the decompression. */ + r = BZ2_bzDecompress(&zip->bzstream); + switch(r) { + case BZ_STREAM_END: + /* If we're at the end of the stream, deinitialize the + * decompression context now. */ + switch(BZ2_bzDecompressEnd(&zip->bzstream)) { + case BZ_OK: + break; + default: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Failed to clean up bzip2 " + "decompressor"); + return ARCHIVE_FATAL; + } + + zip->end_of_entry = 1; + break; + case BZ_OK: + /* The decompressor has successfully decoded this + * chunk of data, but more data is still in queue. */ + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "bzip2 decompression failed"); + return ARCHIVE_FATAL; + } + + /* Update the pointers so decompressor can continue decoding. */ + to_consume = zip->bzstream.total_in_lo32; + __archive_read_consume(a, to_consume); + + total_out = ((uint64_t) zip->bzstream.total_out_hi32 << 32) + + zip->bzstream.total_out_lo32; + + zip->entry_bytes_remaining -= to_consume; + zip->entry_compressed_bytes_read += to_consume; + zip->entry_uncompressed_bytes_read += total_out; + + /* Give libarchive its due. */ + *size = total_out; + *buff = zip->uncompressed_buffer; + + /* Seek for optional marker, like in other entries. */ + r = consume_optional_marker(a, zip); + if(r != ARCHIVE_OK) + return r; + + return ARCHIVE_OK; +} + +#endif + +#ifdef HAVE_ZLIB_H +static int +zip_deflate_init(struct archive_read *a, struct zip *zip) +{ + int r; + + /* If we haven't yet read any data, initialize the decompressor. */ + if (!zip->decompress_init) { + if (zip->stream_valid) + r = inflateReset(&zip->stream); + else + r = inflateInit2(&zip->stream, + -15 /* Don't check for zlib header */); + if (r != Z_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't initialize ZIP decompression."); + return (ARCHIVE_FATAL); + } + /* Stream structure has been set up. */ + zip->stream_valid = 1; + /* We've initialized decompression for this stream. */ + zip->decompress_init = 1; + } + return (ARCHIVE_OK); +} + +static int +zip_read_data_deflate(struct archive_read *a, const void **buff, + size_t *size, int64_t *offset) +{ + struct zip *zip; + ssize_t bytes_avail; + const void *compressed_buff, *sp; + int r; + + (void)offset; /* UNUSED */ + + zip = (struct zip *)(a->format->data); + + /* If the buffer hasn't been allocated, allocate it now. */ + if (zip->uncompressed_buffer == NULL) { + zip->uncompressed_buffer_size = 256 * 1024; + zip->uncompressed_buffer + = (unsigned char *)malloc(zip->uncompressed_buffer_size); + if (zip->uncompressed_buffer == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for ZIP decompression"); + return (ARCHIVE_FATAL); + } + } + + r = zip_deflate_init(a, zip); + if (r != ARCHIVE_OK) + return (r); + + /* + * Note: '1' here is a performance optimization. + * Recall that the decompression layer returns a count of + * available bytes; asking for more than that forces the + * decompressor to combine reads by copying data. + */ + compressed_buff = sp = __archive_read_ahead(a, 1, &bytes_avail); + if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END) + && bytes_avail > zip->entry_bytes_remaining) { + bytes_avail = (ssize_t)zip->entry_bytes_remaining; + } + if (bytes_avail < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file body"); + return (ARCHIVE_FATAL); + } + + if (zip->tctx_valid || zip->cctx_valid) { + if (zip->decrypted_bytes_remaining < (size_t)bytes_avail) { + size_t buff_remaining = + (zip->decrypted_buffer + + zip->decrypted_buffer_size) + - (zip->decrypted_ptr + + zip->decrypted_bytes_remaining); + + if (buff_remaining > (size_t)bytes_avail) + buff_remaining = (size_t)bytes_avail; + + if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END) && + zip->entry_bytes_remaining > 0) { + if ((int64_t)(zip->decrypted_bytes_remaining + + buff_remaining) + > zip->entry_bytes_remaining) { + if (zip->entry_bytes_remaining < + (int64_t)zip->decrypted_bytes_remaining) + buff_remaining = 0; + else + buff_remaining = + (size_t)zip->entry_bytes_remaining + - zip->decrypted_bytes_remaining; + } + } + if (buff_remaining > 0) { + if (zip->tctx_valid) { + trad_enc_decrypt_update(&zip->tctx, + compressed_buff, buff_remaining, + zip->decrypted_ptr + + zip->decrypted_bytes_remaining, + buff_remaining); + } else { + size_t dsize = buff_remaining; + archive_decrypto_aes_ctr_update( + &zip->cctx, + compressed_buff, buff_remaining, + zip->decrypted_ptr + + zip->decrypted_bytes_remaining, + &dsize); + } + zip->decrypted_bytes_remaining += + buff_remaining; + } + } + bytes_avail = zip->decrypted_bytes_remaining; + compressed_buff = (const char *)zip->decrypted_ptr; + } + + /* + * A bug in zlib.h: stream.next_in should be marked 'const' + * but isn't (the library never alters data through the + * next_in pointer, only reads it). The result: this ugly + * cast to remove 'const'. + */ + zip->stream.next_in = (Bytef *)(uintptr_t)(const void *)compressed_buff; + zip->stream.avail_in = (uInt)bytes_avail; + zip->stream.total_in = 0; + zip->stream.next_out = zip->uncompressed_buffer; + zip->stream.avail_out = (uInt)zip->uncompressed_buffer_size; + zip->stream.total_out = 0; + + r = inflate(&zip->stream, 0); + switch (r) { + case Z_OK: + break; + case Z_STREAM_END: + zip->end_of_entry = 1; + break; + case Z_MEM_ERROR: + archive_set_error(&a->archive, ENOMEM, + "Out of memory for ZIP decompression"); + return (ARCHIVE_FATAL); + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "ZIP decompression failed (%d)", r); + return (ARCHIVE_FATAL); + } + + /* Consume as much as the compressor actually used. */ + bytes_avail = zip->stream.total_in; + if (zip->tctx_valid || zip->cctx_valid) { + zip->decrypted_bytes_remaining -= bytes_avail; + if (zip->decrypted_bytes_remaining == 0) + zip->decrypted_ptr = zip->decrypted_buffer; + else + zip->decrypted_ptr += bytes_avail; + } + /* Calculate compressed data as much as we used.*/ + if (zip->hctx_valid) + archive_hmac_sha1_update(&zip->hctx, sp, bytes_avail); + __archive_read_consume(a, bytes_avail); + zip->entry_bytes_remaining -= bytes_avail; + zip->entry_compressed_bytes_read += bytes_avail; + + *size = zip->stream.total_out; + zip->entry_uncompressed_bytes_read += zip->stream.total_out; + *buff = zip->uncompressed_buffer; + + if (zip->end_of_entry && zip->hctx_valid) { + r = check_authentication_code(a, NULL); + if (r != ARCHIVE_OK) + return (r); + } + + r = consume_optional_marker(a, zip); + if (r != ARCHIVE_OK) + return (r); + + return (ARCHIVE_OK); +} +#endif + +static int +read_decryption_header(struct archive_read *a) +{ + struct zip *zip = (struct zip *)(a->format->data); + const char *p; + unsigned int remaining_size; + unsigned int ts; + + /* + * Read an initialization vector data field. + */ + p = __archive_read_ahead(a, 2, NULL); + if (p == NULL) + goto truncated; + ts = zip->iv_size; + zip->iv_size = archive_le16dec(p); + __archive_read_consume(a, 2); + if (ts < zip->iv_size) { + free(zip->iv); + zip->iv = NULL; + } + p = __archive_read_ahead(a, zip->iv_size, NULL); + if (p == NULL) + goto truncated; + if (zip->iv == NULL) { + zip->iv = malloc(zip->iv_size); + if (zip->iv == NULL) + goto nomem; + } + memcpy(zip->iv, p, zip->iv_size); + __archive_read_consume(a, zip->iv_size); + + /* + * Read a size of remaining decryption header field. + */ + p = __archive_read_ahead(a, 14, NULL); + if (p == NULL) + goto truncated; + remaining_size = archive_le32dec(p); + if (remaining_size < 16 || remaining_size > (1 << 18)) + goto corrupted; + + /* Check if format version is supported. */ + if (archive_le16dec(p+4) != 3) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Unsupported encryption format version: %u", + archive_le16dec(p+4)); + return (ARCHIVE_FAILED); + } + + /* + * Read an encryption algorithm field. + */ + zip->alg_id = archive_le16dec(p+6); + switch (zip->alg_id) { + case 0x6601:/* DES */ + case 0x6602:/* RC2 */ + case 0x6603:/* 3DES 168 */ + case 0x6609:/* 3DES 112 */ + case 0x660E:/* AES 128 */ + case 0x660F:/* AES 192 */ + case 0x6610:/* AES 256 */ + case 0x6702:/* RC2 (version >= 5.2) */ + case 0x6720:/* Blowfish */ + case 0x6721:/* Twofish */ + case 0x6801:/* RC4 */ + /* Supported encryption algorithm. */ + break; + default: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Unknown encryption algorithm: %u", zip->alg_id); + return (ARCHIVE_FAILED); + } + + /* + * Read a bit length field. + */ + zip->bit_len = archive_le16dec(p+8); + + /* + * Read a flags field. + */ + zip->flags = archive_le16dec(p+10); + switch (zip->flags & 0xf000) { + case 0x0001: /* Password is required to decrypt. */ + case 0x0002: /* Certificates only. */ + case 0x0003: /* Password or certificate required to decrypt. */ + break; + default: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Unknown encryption flag: %u", zip->flags); + return (ARCHIVE_FAILED); + } + if ((zip->flags & 0xf000) == 0 || + (zip->flags & 0xf000) == 0x4000) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Unknown encryption flag: %u", zip->flags); + return (ARCHIVE_FAILED); + } + + /* + * Read an encrypted random data field. + */ + ts = zip->erd_size; + zip->erd_size = archive_le16dec(p+12); + __archive_read_consume(a, 14); + if ((zip->erd_size & 0xf) != 0 || + (zip->erd_size + 16) > remaining_size || + (zip->erd_size + 16) < zip->erd_size) + goto corrupted; + + if (ts < zip->erd_size) { + free(zip->erd); + zip->erd = NULL; + } + p = __archive_read_ahead(a, zip->erd_size, NULL); + if (p == NULL) + goto truncated; + if (zip->erd == NULL) { + zip->erd = malloc(zip->erd_size); + if (zip->erd == NULL) + goto nomem; + } + memcpy(zip->erd, p, zip->erd_size); + __archive_read_consume(a, zip->erd_size); + + /* + * Read a reserved data field. + */ + p = __archive_read_ahead(a, 4, NULL); + if (p == NULL) + goto truncated; + /* Reserved data size should be zero. */ + if (archive_le32dec(p) != 0) + goto corrupted; + __archive_read_consume(a, 4); + + /* + * Read a password validation data field. + */ + p = __archive_read_ahead(a, 2, NULL); + if (p == NULL) + goto truncated; + ts = zip->v_size; + zip->v_size = archive_le16dec(p); + __archive_read_consume(a, 2); + if ((zip->v_size & 0x0f) != 0 || + (zip->erd_size + zip->v_size + 16) > remaining_size || + (zip->erd_size + zip->v_size + 16) < (zip->erd_size + zip->v_size)) + goto corrupted; + if (ts < zip->v_size) { + free(zip->v_data); + zip->v_data = NULL; + } + p = __archive_read_ahead(a, zip->v_size, NULL); + if (p == NULL) + goto truncated; + if (zip->v_data == NULL) { + zip->v_data = malloc(zip->v_size); + if (zip->v_data == NULL) + goto nomem; + } + memcpy(zip->v_data, p, zip->v_size); + __archive_read_consume(a, zip->v_size); + + p = __archive_read_ahead(a, 4, NULL); + if (p == NULL) + goto truncated; + zip->v_crc32 = archive_le32dec(p); + __archive_read_consume(a, 4); + + /*return (ARCHIVE_OK); + * This is not fully implemented yet.*/ + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Encrypted file is unsupported"); + return (ARCHIVE_FAILED); +truncated: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file data"); + return (ARCHIVE_FATAL); +corrupted: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Corrupted ZIP file data"); + return (ARCHIVE_FATAL); +nomem: + archive_set_error(&a->archive, ENOMEM, + "No memory for ZIP decryption"); + return (ARCHIVE_FATAL); +} + +static int +zip_alloc_decryption_buffer(struct archive_read *a) +{ + struct zip *zip = (struct zip *)(a->format->data); + size_t bs = 256 * 1024; + + if (zip->decrypted_buffer == NULL) { + zip->decrypted_buffer_size = bs; + zip->decrypted_buffer = malloc(bs); + if (zip->decrypted_buffer == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for ZIP decryption"); + return (ARCHIVE_FATAL); + } + } + zip->decrypted_ptr = zip->decrypted_buffer; + return (ARCHIVE_OK); +} + +static int +init_traditional_PKWARE_decryption(struct archive_read *a) +{ + struct zip *zip = (struct zip *)(a->format->data); + const void *p; + int retry; + int r; + + if (zip->tctx_valid) + return (ARCHIVE_OK); + + /* + Read the 12 bytes encryption header stored at + the start of the data area. + */ +#define ENC_HEADER_SIZE 12 + if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END) + && zip->entry_bytes_remaining < ENC_HEADER_SIZE) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated Zip encrypted body: only %jd bytes available", + (intmax_t)zip->entry_bytes_remaining); + return (ARCHIVE_FATAL); + } + + p = __archive_read_ahead(a, ENC_HEADER_SIZE, NULL); + if (p == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file data"); + return (ARCHIVE_FATAL); + } + + for (retry = 0;; retry++) { + const char *passphrase; + uint8_t crcchk; + + passphrase = __archive_read_next_passphrase(a); + if (passphrase == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + (retry > 0)? + "Incorrect passphrase": + "Passphrase required for this entry"); + return (ARCHIVE_FAILED); + } + + /* + * Initialize ctx for Traditional PKWARE Decryption. + */ + r = trad_enc_init(&zip->tctx, passphrase, strlen(passphrase), + p, ENC_HEADER_SIZE, &crcchk); + if (r == 0 && crcchk == zip->entry->decdat) + break;/* The passphrase is OK. */ + if (retry > 10000) { + /* Avoid infinity loop. */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Too many incorrect passphrases"); + return (ARCHIVE_FAILED); + } + } + + __archive_read_consume(a, ENC_HEADER_SIZE); + zip->tctx_valid = 1; + if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END)) { + zip->entry_bytes_remaining -= ENC_HEADER_SIZE; + } + /*zip->entry_uncompressed_bytes_read += ENC_HEADER_SIZE;*/ + zip->entry_compressed_bytes_read += ENC_HEADER_SIZE; + zip->decrypted_bytes_remaining = 0; + + return (zip_alloc_decryption_buffer(a)); +#undef ENC_HEADER_SIZE +} + +static int +init_WinZip_AES_decryption(struct archive_read *a) +{ + struct zip *zip = (struct zip *)(a->format->data); + const void *p; + const uint8_t *pv; + size_t key_len, salt_len; + uint8_t derived_key[MAX_DERIVED_KEY_BUF_SIZE]; + int retry; + int r; + + if (zip->cctx_valid || zip->hctx_valid) + return (ARCHIVE_OK); + + switch (zip->entry->aes_extra.strength) { + case 1: salt_len = 8; key_len = 16; break; + case 2: salt_len = 12; key_len = 24; break; + case 3: salt_len = 16; key_len = 32; break; + default: goto corrupted; + } + p = __archive_read_ahead(a, salt_len + 2, NULL); + if (p == NULL) + goto truncated; + + for (retry = 0;; retry++) { + const char *passphrase; + + passphrase = __archive_read_next_passphrase(a); + if (passphrase == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + (retry > 0)? + "Incorrect passphrase": + "Passphrase required for this entry"); + return (ARCHIVE_FAILED); + } + memset(derived_key, 0, sizeof(derived_key)); + r = archive_pbkdf2_sha1(passphrase, strlen(passphrase), + p, salt_len, 1000, derived_key, key_len * 2 + 2); + if (r != 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Decryption is unsupported due to lack of " + "crypto library"); + return (ARCHIVE_FAILED); + } + + /* Check password verification value. */ + pv = ((const uint8_t *)p) + salt_len; + if (derived_key[key_len * 2] == pv[0] && + derived_key[key_len * 2 + 1] == pv[1]) + break;/* The passphrase is OK. */ + if (retry > 10000) { + /* Avoid infinity loop. */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Too many incorrect passphrases"); + return (ARCHIVE_FAILED); + } + } + + r = archive_decrypto_aes_ctr_init(&zip->cctx, derived_key, key_len); + if (r != 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Decryption is unsupported due to lack of crypto library"); + return (ARCHIVE_FAILED); + } + r = archive_hmac_sha1_init(&zip->hctx, derived_key + key_len, key_len); + if (r != 0) { + archive_decrypto_aes_ctr_release(&zip->cctx); + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to initialize HMAC-SHA1"); + return (ARCHIVE_FAILED); + } + zip->cctx_valid = zip->hctx_valid = 1; + __archive_read_consume(a, salt_len + 2); + zip->entry_bytes_remaining -= salt_len + 2 + AUTH_CODE_SIZE; + if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END) + && zip->entry_bytes_remaining < 0) + goto corrupted; + zip->entry_compressed_bytes_read += salt_len + 2 + AUTH_CODE_SIZE; + zip->decrypted_bytes_remaining = 0; + + zip->entry->compression = zip->entry->aes_extra.compression; + return (zip_alloc_decryption_buffer(a)); + +truncated: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file data"); + return (ARCHIVE_FATAL); +corrupted: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Corrupted ZIP file data"); + return (ARCHIVE_FATAL); +} + +static int +archive_read_format_zip_read_data(struct archive_read *a, + const void **buff, size_t *size, int64_t *offset) +{ + int r; + struct zip *zip = (struct zip *)(a->format->data); + + if (zip->has_encrypted_entries == + ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) { + zip->has_encrypted_entries = 0; + } + + *offset = zip->entry_uncompressed_bytes_read; + *size = 0; + *buff = NULL; + + /* If we hit end-of-entry last time, return ARCHIVE_EOF. */ + if (zip->end_of_entry) + return (ARCHIVE_EOF); + + /* Return EOF immediately if this is a non-regular file. */ + if (AE_IFREG != (zip->entry->mode & AE_IFMT)) + return (ARCHIVE_EOF); + + __archive_read_consume(a, zip->unconsumed); + zip->unconsumed = 0; + + if (zip->init_decryption) { + zip->has_encrypted_entries = 1; + if (zip->entry->zip_flags & ZIP_STRONG_ENCRYPTED) + r = read_decryption_header(a); + else if (zip->entry->compression == WINZIP_AES_ENCRYPTION) + r = init_WinZip_AES_decryption(a); + else + r = init_traditional_PKWARE_decryption(a); + if (r != ARCHIVE_OK) + return (r); + zip->init_decryption = 0; + } + + switch(zip->entry->compression) { + case 0: /* No compression. */ + r = zip_read_data_none(a, buff, size, offset); + break; +#ifdef HAVE_BZLIB_H + case 12: /* ZIPx bzip2 compression. */ + r = zip_read_data_zipx_bzip2(a, buff, size, offset); + break; +#endif +#if HAVE_LZMA_H && HAVE_LIBLZMA + case 14: /* ZIPx LZMA compression. */ + r = zip_read_data_zipx_lzma_alone(a, buff, size, offset); + break; + case 95: /* ZIPx XZ compression. */ + r = zip_read_data_zipx_xz(a, buff, size, offset); + break; +#endif + /* PPMd support is built-in, so we don't need any #if guards. */ + case 98: /* ZIPx PPMd compression. */ + r = zip_read_data_zipx_ppmd(a, buff, size, offset); + break; + +#ifdef HAVE_ZLIB_H + case 8: /* Deflate compression. */ + r = zip_read_data_deflate(a, buff, size, offset); + break; +#endif + default: /* Unsupported compression. */ + /* Return a warning. */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Unsupported ZIP compression method (%d: %s)", + zip->entry->compression, compression_name(zip->entry->compression)); + /* We can't decompress this entry, but we will + * be able to skip() it and try the next entry. */ + return (ARCHIVE_FAILED); + break; + } + if (r != ARCHIVE_OK) + return (r); + /* Update checksum */ + if (*size) + zip->entry_crc32 = zip->crc32func(zip->entry_crc32, *buff, + (unsigned)*size); + /* If we hit the end, swallow any end-of-data marker. */ + if (zip->end_of_entry) { + /* Check file size, CRC against these values. */ + if (zip->entry->compressed_size != + zip->entry_compressed_bytes_read) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "ZIP compressed data is wrong size " + "(read %jd, expected %jd)", + (intmax_t)zip->entry_compressed_bytes_read, + (intmax_t)zip->entry->compressed_size); + return (ARCHIVE_WARN); + } + /* Size field only stores the lower 32 bits of the actual + * size. */ + if ((zip->entry->uncompressed_size & UINT32_MAX) + != (zip->entry_uncompressed_bytes_read & UINT32_MAX)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "ZIP uncompressed data is wrong size " + "(read %jd, expected %jd)\n", + (intmax_t)zip->entry_uncompressed_bytes_read, + (intmax_t)zip->entry->uncompressed_size); + return (ARCHIVE_WARN); + } + /* Check computed CRC against header */ + if ((!zip->hctx_valid || + zip->entry->aes_extra.vendor != AES_VENDOR_AE_2) && + zip->entry->crc32 != zip->entry_crc32 + && !zip->ignore_crc32) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "ZIP bad CRC: 0x%lx should be 0x%lx", + (unsigned long)zip->entry_crc32, + (unsigned long)zip->entry->crc32); + return (ARCHIVE_WARN); + } + } + + return (ARCHIVE_OK); +} + +static int +archive_read_format_zip_cleanup(struct archive_read *a) +{ + struct zip *zip; + struct zip_entry *zip_entry, *next_zip_entry; + + zip = (struct zip *)(a->format->data); + +#ifdef HAVE_ZLIB_H + if (zip->stream_valid) + inflateEnd(&zip->stream); +#endif + +#if HAVE_LZMA_H && HAVE_LIBLZMA + if (zip->zipx_lzma_valid) { + lzma_end(&zip->zipx_lzma_stream); + } +#endif + +#ifdef HAVE_BZLIB_H + if (zip->bzstream_valid) { + BZ2_bzDecompressEnd(&zip->bzstream); + } +#endif + + free(zip->uncompressed_buffer); + + if (zip->ppmd8_valid) + __archive_ppmd8_functions.Ppmd8_Free(&zip->ppmd8); + + if (zip->zip_entries) { + zip_entry = zip->zip_entries; + while (zip_entry != NULL) { + next_zip_entry = zip_entry->next; + archive_string_free(&zip_entry->rsrcname); + free(zip_entry); + zip_entry = next_zip_entry; + } + } + free(zip->decrypted_buffer); + if (zip->cctx_valid) + archive_decrypto_aes_ctr_release(&zip->cctx); + if (zip->hctx_valid) + archive_hmac_sha1_cleanup(&zip->hctx); + free(zip->iv); + free(zip->erd); + free(zip->v_data); + archive_string_free(&zip->format_name); + free(zip); + (a->format->data) = NULL; + return (ARCHIVE_OK); +} + +static int +archive_read_format_zip_has_encrypted_entries(struct archive_read *_a) +{ + if (_a && _a->format) { + struct zip * zip = (struct zip *)_a->format->data; + if (zip) { + return zip->has_encrypted_entries; + } + } + return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW; +} + +static int +archive_read_format_zip_options(struct archive_read *a, + const char *key, const char *val) +{ + struct zip *zip; + int ret = ARCHIVE_FAILED; + + zip = (struct zip *)(a->format->data); + if (strcmp(key, "compat-2x") == 0) { + /* Handle filenames as libarchive 2.x */ + zip->init_default_conversion = (val != NULL) ? 1 : 0; + return (ARCHIVE_OK); + } else if (strcmp(key, "hdrcharset") == 0) { + if (val == NULL || val[0] == 0) + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "zip: hdrcharset option needs a character-set name" + ); + else { + zip->sconv = archive_string_conversion_from_charset( + &a->archive, val, 0); + if (zip->sconv != NULL) { + if (strcmp(val, "UTF-8") == 0) + zip->sconv_utf8 = zip->sconv; + ret = ARCHIVE_OK; + } else + ret = ARCHIVE_FATAL; + } + return (ret); + } else if (strcmp(key, "ignorecrc32") == 0) { + /* Mostly useful for testing. */ + if (val == NULL || val[0] == 0) { + zip->crc32func = real_crc32; + zip->ignore_crc32 = 0; + } else { + zip->crc32func = fake_crc32; + zip->ignore_crc32 = 1; + } + return (ARCHIVE_OK); + } else if (strcmp(key, "mac-ext") == 0) { + zip->process_mac_extensions = (val != NULL && val[0] != 0); + return (ARCHIVE_OK); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +int +archive_read_support_format_zip(struct archive *a) +{ + int r; + r = archive_read_support_format_zip_streamable(a); + if (r != ARCHIVE_OK) + return r; + return (archive_read_support_format_zip_seekable(a)); +} + +/* ------------------------------------------------------------------------ */ + +/* + * Streaming-mode support + */ + + +static int +archive_read_support_format_zip_capabilities_streamable(struct archive_read * a) +{ + (void)a; /* UNUSED */ + return (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA | + ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA); +} + +static int +archive_read_format_zip_streamable_bid(struct archive_read *a, int best_bid) +{ + const char *p; + + (void)best_bid; /* UNUSED */ + + if ((p = __archive_read_ahead(a, 4, NULL)) == NULL) + return (-1); + + /* + * Bid of 29 here comes from: + * + 16 bits for "PK", + * + next 16-bit field has 6 options so contributes + * about 16 - log_2(6) ~= 16 - 2.6 ~= 13 bits + * + * So we've effectively verified ~29 total bits of check data. + */ + if (p[0] == 'P' && p[1] == 'K') { + if ((p[2] == '\001' && p[3] == '\002') + || (p[2] == '\003' && p[3] == '\004') + || (p[2] == '\005' && p[3] == '\006') + || (p[2] == '\006' && p[3] == '\006') + || (p[2] == '\007' && p[3] == '\010') + || (p[2] == '0' && p[3] == '0')) + return (29); + } + + /* TODO: It's worth looking ahead a little bit for a valid + * PK signature. In particular, that would make it possible + * to read some UUEncoded SFX files or SFX files coming from + * a network socket. */ + + return (0); +} + +static int +archive_read_format_zip_streamable_read_header(struct archive_read *a, + struct archive_entry *entry) +{ + struct zip *zip; + + a->archive.archive_format = ARCHIVE_FORMAT_ZIP; + if (a->archive.archive_format_name == NULL) + a->archive.archive_format_name = "ZIP"; + + zip = (struct zip *)(a->format->data); + + /* + * It should be sufficient to call archive_read_next_header() for + * a reader to determine if an entry is encrypted or not. If the + * encryption of an entry is only detectable when calling + * archive_read_data(), so be it. We'll do the same check there + * as well. + */ + if (zip->has_encrypted_entries == + ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) + zip->has_encrypted_entries = 0; + + /* Make sure we have a zip_entry structure to use. */ + if (zip->zip_entries == NULL) { + zip->zip_entries = malloc(sizeof(struct zip_entry)); + if (zip->zip_entries == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Out of memory"); + return ARCHIVE_FATAL; + } + } + zip->entry = zip->zip_entries; + memset(zip->entry, 0, sizeof(struct zip_entry)); + + if (zip->cctx_valid) + archive_decrypto_aes_ctr_release(&zip->cctx); + if (zip->hctx_valid) + archive_hmac_sha1_cleanup(&zip->hctx); + zip->tctx_valid = zip->cctx_valid = zip->hctx_valid = 0; + __archive_read_reset_passphrase(a); + + /* Search ahead for the next local file header. */ + __archive_read_consume(a, zip->unconsumed); + zip->unconsumed = 0; + for (;;) { + int64_t skipped = 0; + const char *p, *end; + ssize_t bytes; + + p = __archive_read_ahead(a, 4, &bytes); + if (p == NULL) + return (ARCHIVE_FATAL); + end = p + bytes; + + while (p + 4 <= end) { + if (p[0] == 'P' && p[1] == 'K') { + if (p[2] == '\003' && p[3] == '\004') { + /* Regular file entry. */ + __archive_read_consume(a, skipped); + return zip_read_local_file_header(a, + entry, zip); + } + + /* + * TODO: We cannot restore permissions + * based only on the local file headers. + * Consider scanning the central + * directory and returning additional + * entries for at least directories. + * This would allow us to properly set + * directory permissions. + * + * This won't help us fix symlinks + * and may not help with regular file + * permissions, either. + */ + if (p[2] == '\001' && p[3] == '\002') { + return (ARCHIVE_EOF); + } + + /* End of central directory? Must be an + * empty archive. */ + if ((p[2] == '\005' && p[3] == '\006') + || (p[2] == '\006' && p[3] == '\006')) + return (ARCHIVE_EOF); + } + ++p; + ++skipped; + } + __archive_read_consume(a, skipped); + } +} + +static int +archive_read_format_zip_read_data_skip_streamable(struct archive_read *a) +{ + struct zip *zip; + int64_t bytes_skipped; + + zip = (struct zip *)(a->format->data); + bytes_skipped = __archive_read_consume(a, zip->unconsumed); + zip->unconsumed = 0; + if (bytes_skipped < 0) + return (ARCHIVE_FATAL); + + /* If we've already read to end of data, we're done. */ + if (zip->end_of_entry) + return (ARCHIVE_OK); + + /* So we know we're streaming... */ + if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END) + || zip->entry->compressed_size > 0) { + /* We know the compressed length, so we can just skip. */ + bytes_skipped = __archive_read_consume(a, + zip->entry_bytes_remaining); + if (bytes_skipped < 0) + return (ARCHIVE_FATAL); + return (ARCHIVE_OK); + } + + if (zip->init_decryption) { + int r; + + zip->has_encrypted_entries = 1; + if (zip->entry->zip_flags & ZIP_STRONG_ENCRYPTED) + r = read_decryption_header(a); + else if (zip->entry->compression == WINZIP_AES_ENCRYPTION) + r = init_WinZip_AES_decryption(a); + else + r = init_traditional_PKWARE_decryption(a); + if (r != ARCHIVE_OK) + return (r); + zip->init_decryption = 0; + } + + /* We're streaming and we don't know the length. */ + /* If the body is compressed and we know the format, we can + * find an exact end-of-entry by decompressing it. */ + switch (zip->entry->compression) { +#ifdef HAVE_ZLIB_H + case 8: /* Deflate compression. */ + while (!zip->end_of_entry) { + int64_t offset = 0; + const void *buff = NULL; + size_t size = 0; + int r; + r = zip_read_data_deflate(a, &buff, &size, &offset); + if (r != ARCHIVE_OK) + return (r); + } + return ARCHIVE_OK; +#endif + default: /* Uncompressed or unknown. */ + /* Scan for a PK\007\010 signature. */ + for (;;) { + const char *p, *buff; + ssize_t bytes_avail; + buff = __archive_read_ahead(a, 16, &bytes_avail); + if (bytes_avail < 16) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file data"); + return (ARCHIVE_FATAL); + } + p = buff; + while (p <= buff + bytes_avail - 16) { + if (p[3] == 'P') { p += 3; } + else if (p[3] == 'K') { p += 2; } + else if (p[3] == '\007') { p += 1; } + else if (p[3] == '\010' && p[2] == '\007' + && p[1] == 'K' && p[0] == 'P') { + if (zip->entry->flags & LA_USED_ZIP64) + __archive_read_consume(a, + p - buff + 24); + else + __archive_read_consume(a, + p - buff + 16); + return ARCHIVE_OK; + } else { p += 4; } + } + __archive_read_consume(a, p - buff); + } + } +} + +int +archive_read_support_format_zip_streamable(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct zip *zip; + int r; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_format_zip"); + + zip = (struct zip *)calloc(1, sizeof(*zip)); + if (zip == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate zip data"); + return (ARCHIVE_FATAL); + } + + /* Streamable reader doesn't support mac extensions. */ + zip->process_mac_extensions = 0; + + /* + * Until enough data has been read, we cannot tell about + * any encrypted entries yet. + */ + zip->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW; + zip->crc32func = real_crc32; + + r = __archive_read_register_format(a, + zip, + "zip", + archive_read_format_zip_streamable_bid, + archive_read_format_zip_options, + archive_read_format_zip_streamable_read_header, + archive_read_format_zip_read_data, + archive_read_format_zip_read_data_skip_streamable, + NULL, + archive_read_format_zip_cleanup, + archive_read_support_format_zip_capabilities_streamable, + archive_read_format_zip_has_encrypted_entries); + + if (r != ARCHIVE_OK) + free(zip); + return (ARCHIVE_OK); +} + +/* ------------------------------------------------------------------------ */ + +/* + * Seeking-mode support + */ + +static int +archive_read_support_format_zip_capabilities_seekable(struct archive_read * a) +{ + (void)a; /* UNUSED */ + return (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA | + ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA); +} + +/* + * TODO: This is a performance sink because it forces the read core to + * drop buffered data from the start of file, which will then have to + * be re-read again if this bidder loses. + * + * We workaround this a little by passing in the best bid so far so + * that later bidders can do nothing if they know they'll never + * outbid. But we can certainly do better... + */ +static int +read_eocd(struct zip *zip, const char *p, int64_t current_offset) +{ + /* Sanity-check the EOCD we've found. */ + + /* This must be the first volume. */ + if (archive_le16dec(p + 4) != 0) + return 0; + /* Central directory must be on this volume. */ + if (archive_le16dec(p + 4) != archive_le16dec(p + 6)) + return 0; + /* All central directory entries must be on this volume. */ + if (archive_le16dec(p + 10) != archive_le16dec(p + 8)) + return 0; + /* Central directory can't extend beyond start of EOCD record. */ + if (archive_le32dec(p + 16) + archive_le32dec(p + 12) + > current_offset) + return 0; + + /* Save the central directory location for later use. */ + zip->central_directory_offset = archive_le32dec(p + 16); + + /* This is just a tiny bit higher than the maximum + returned by the streaming Zip bidder. This ensures + that the more accurate seeking Zip parser wins + whenever seek is available. */ + return 32; +} + +/* + * Examine Zip64 EOCD locator: If it's valid, store the information + * from it. + */ +static int +read_zip64_eocd(struct archive_read *a, struct zip *zip, const char *p) +{ + int64_t eocd64_offset; + int64_t eocd64_size; + + /* Sanity-check the locator record. */ + + /* Central dir must be on first volume. */ + if (archive_le32dec(p + 4) != 0) + return 0; + /* Must be only a single volume. */ + if (archive_le32dec(p + 16) != 1) + return 0; + + /* Find the Zip64 EOCD record. */ + eocd64_offset = archive_le64dec(p + 8); + if (__archive_read_seek(a, eocd64_offset, SEEK_SET) < 0) + return 0; + if ((p = __archive_read_ahead(a, 56, NULL)) == NULL) + return 0; + /* Make sure we can read all of it. */ + eocd64_size = archive_le64dec(p + 4) + 12; + if (eocd64_size < 56 || eocd64_size > 16384) + return 0; + if ((p = __archive_read_ahead(a, (size_t)eocd64_size, NULL)) == NULL) + return 0; + + /* Sanity-check the EOCD64 */ + if (archive_le32dec(p + 16) != 0) /* Must be disk #0 */ + return 0; + if (archive_le32dec(p + 20) != 0) /* CD must be on disk #0 */ + return 0; + /* CD can't be split. */ + if (archive_le64dec(p + 24) != archive_le64dec(p + 32)) + return 0; + + /* Save the central directory offset for later use. */ + zip->central_directory_offset = archive_le64dec(p + 48); + + return 32; +} + +static int +archive_read_format_zip_seekable_bid(struct archive_read *a, int best_bid) +{ + struct zip *zip = (struct zip *)a->format->data; + int64_t file_size, current_offset; + const char *p; + int i, tail; + + /* If someone has already bid more than 32, then avoid + trashing the look-ahead buffers with a seek. */ + if (best_bid > 32) + return (-1); + + file_size = __archive_read_seek(a, 0, SEEK_END); + if (file_size <= 0) + return 0; + + /* Search last 16k of file for end-of-central-directory + * record (which starts with PK\005\006) */ + tail = (int)zipmin(1024 * 16, file_size); + current_offset = __archive_read_seek(a, -tail, SEEK_END); + if (current_offset < 0) + return 0; + if ((p = __archive_read_ahead(a, (size_t)tail, NULL)) == NULL) + return 0; + /* Boyer-Moore search backwards from the end, since we want + * to match the last EOCD in the file (there can be more than + * one if there is an uncompressed Zip archive as a member + * within this Zip archive). */ + for (i = tail - 22; i > 0;) { + switch (p[i]) { + case 'P': + if (memcmp(p + i, "PK\005\006", 4) == 0) { + int ret = read_eocd(zip, p + i, + current_offset + i); + /* Zip64 EOCD locator precedes + * regular EOCD if present. */ + if (i >= 20 && memcmp(p + i - 20, "PK\006\007", 4) == 0) { + int ret_zip64 = read_zip64_eocd(a, zip, p + i - 20); + if (ret_zip64 > ret) + ret = ret_zip64; + } + return (ret); + } + i -= 4; + break; + case 'K': i -= 1; break; + case 005: i -= 2; break; + case 006: i -= 3; break; + default: i -= 4; break; + } + } + return 0; +} + +/* The red-black trees are only used in seeking mode to manage + * the in-memory copy of the central directory. */ + +static int +cmp_node(const struct archive_rb_node *n1, const struct archive_rb_node *n2) +{ + const struct zip_entry *e1 = (const struct zip_entry *)n1; + const struct zip_entry *e2 = (const struct zip_entry *)n2; + + if (e1->local_header_offset > e2->local_header_offset) + return -1; + if (e1->local_header_offset < e2->local_header_offset) + return 1; + return 0; +} + +static int +cmp_key(const struct archive_rb_node *n, const void *key) +{ + /* This function won't be called */ + (void)n; /* UNUSED */ + (void)key; /* UNUSED */ + return 1; +} + +static const struct archive_rb_tree_ops rb_ops = { + &cmp_node, &cmp_key +}; + +static int +rsrc_cmp_node(const struct archive_rb_node *n1, + const struct archive_rb_node *n2) +{ + const struct zip_entry *e1 = (const struct zip_entry *)n1; + const struct zip_entry *e2 = (const struct zip_entry *)n2; + + return (strcmp(e2->rsrcname.s, e1->rsrcname.s)); +} + +static int +rsrc_cmp_key(const struct archive_rb_node *n, const void *key) +{ + const struct zip_entry *e = (const struct zip_entry *)n; + return (strcmp((const char *)key, e->rsrcname.s)); +} + +static const struct archive_rb_tree_ops rb_rsrc_ops = { + &rsrc_cmp_node, &rsrc_cmp_key +}; + +static const char * +rsrc_basename(const char *name, size_t name_length) +{ + const char *s, *r; + + r = s = name; + for (;;) { + s = memchr(s, '/', name_length - (s - name)); + if (s == NULL) + break; + r = ++s; + } + return (r); +} + +static void +expose_parent_dirs(struct zip *zip, const char *name, size_t name_length) +{ + struct archive_string str; + struct zip_entry *dir; + char *s; + + archive_string_init(&str); + archive_strncpy(&str, name, name_length); + for (;;) { + s = strrchr(str.s, '/'); + if (s == NULL) + break; + *s = '\0'; + /* Transfer the parent directory from zip->tree_rsrc RB + * tree to zip->tree RB tree to expose. */ + dir = (struct zip_entry *) + __archive_rb_tree_find_node(&zip->tree_rsrc, str.s); + if (dir == NULL) + break; + __archive_rb_tree_remove_node(&zip->tree_rsrc, &dir->node); + archive_string_free(&dir->rsrcname); + __archive_rb_tree_insert_node(&zip->tree, &dir->node); + } + archive_string_free(&str); +} + +static int +slurp_central_directory(struct archive_read *a, struct archive_entry* entry, + struct zip *zip) +{ + ssize_t i; + unsigned found; + int64_t correction; + ssize_t bytes_avail; + const char *p; + + /* + * Find the start of the central directory. The end-of-CD + * record has our starting point, but there are lots of + * Zip archives which have had other data prepended to the + * file, which makes the recorded offsets all too small. + * So we search forward from the specified offset until we + * find the real start of the central directory. Then we + * know the correction we need to apply to account for leading + * padding. + */ + if (__archive_read_seek(a, zip->central_directory_offset, SEEK_SET) < 0) + return ARCHIVE_FATAL; + + found = 0; + while (!found) { + if ((p = __archive_read_ahead(a, 20, &bytes_avail)) == NULL) + return ARCHIVE_FATAL; + for (found = 0, i = 0; !found && i < bytes_avail - 4;) { + switch (p[i + 3]) { + case 'P': i += 3; break; + case 'K': i += 2; break; + case 001: i += 1; break; + case 002: + if (memcmp(p + i, "PK\001\002", 4) == 0) { + p += i; + found = 1; + } else + i += 4; + break; + case 005: i += 1; break; + case 006: + if (memcmp(p + i, "PK\005\006", 4) == 0) { + p += i; + found = 1; + } else if (memcmp(p + i, "PK\006\006", 4) == 0) { + p += i; + found = 1; + } else + i += 1; + break; + default: i += 4; break; + } + } + __archive_read_consume(a, i); + } + correction = archive_filter_bytes(&a->archive, 0) + - zip->central_directory_offset; + + __archive_rb_tree_init(&zip->tree, &rb_ops); + __archive_rb_tree_init(&zip->tree_rsrc, &rb_rsrc_ops); + + zip->central_directory_entries_total = 0; + while (1) { + struct zip_entry *zip_entry; + size_t filename_length, extra_length, comment_length; + uint32_t external_attributes; + const char *name, *r; + + if ((p = __archive_read_ahead(a, 4, NULL)) == NULL) + return ARCHIVE_FATAL; + if (memcmp(p, "PK\006\006", 4) == 0 + || memcmp(p, "PK\005\006", 4) == 0) { + break; + } else if (memcmp(p, "PK\001\002", 4) != 0) { + archive_set_error(&a->archive, + -1, "Invalid central directory signature"); + return ARCHIVE_FATAL; + } + if ((p = __archive_read_ahead(a, 46, NULL)) == NULL) + return ARCHIVE_FATAL; + + zip_entry = calloc(1, sizeof(struct zip_entry)); + if (zip_entry == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate zip entry"); + return ARCHIVE_FATAL; + } + zip_entry->next = zip->zip_entries; + zip_entry->flags |= LA_FROM_CENTRAL_DIRECTORY; + zip->zip_entries = zip_entry; + zip->central_directory_entries_total++; + + /* version = p[4]; */ + zip_entry->system = p[5]; + /* version_required = archive_le16dec(p + 6); */ + zip_entry->zip_flags = archive_le16dec(p + 8); + if (zip_entry->zip_flags + & (ZIP_ENCRYPTED | ZIP_STRONG_ENCRYPTED)){ + zip->has_encrypted_entries = 1; + } + zip_entry->compression = (char)archive_le16dec(p + 10); + zip_entry->mtime = zip_time(p + 12); + zip_entry->crc32 = archive_le32dec(p + 16); + if (zip_entry->zip_flags & ZIP_LENGTH_AT_END) + zip_entry->decdat = p[13]; + else + zip_entry->decdat = p[19]; + zip_entry->compressed_size = archive_le32dec(p + 20); + zip_entry->uncompressed_size = archive_le32dec(p + 24); + filename_length = archive_le16dec(p + 28); + extra_length = archive_le16dec(p + 30); + comment_length = archive_le16dec(p + 32); + /* disk_start = archive_le16dec(p + 34); + * Better be zero. + * internal_attributes = archive_le16dec(p + 36); + * text bit */ + external_attributes = archive_le32dec(p + 38); + zip_entry->local_header_offset = + archive_le32dec(p + 42) + correction; + + /* If we can't guess the mode, leave it zero here; + when we read the local file header we might get + more information. */ + if (zip_entry->system == 3) { + zip_entry->mode = external_attributes >> 16; + } else if (zip_entry->system == 0) { + // Interpret MSDOS directory bit + if (0x10 == (external_attributes & 0x10)) { + zip_entry->mode = AE_IFDIR | 0775; + } else { + zip_entry->mode = AE_IFREG | 0664; + } + if (0x01 == (external_attributes & 0x01)) { + // Read-only bit; strip write permissions + zip_entry->mode &= 0555; + } + } else { + zip_entry->mode = 0; + } + + /* We're done with the regular data; get the filename and + * extra data. */ + __archive_read_consume(a, 46); + p = __archive_read_ahead(a, filename_length + extra_length, + NULL); + if (p == NULL) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file header"); + return ARCHIVE_FATAL; + } + if (ARCHIVE_OK != process_extra(a, entry, p + filename_length, + extra_length, zip_entry)) { + return ARCHIVE_FATAL; + } + + /* + * Mac resource fork files are stored under the + * "__MACOSX/" directory, so we should check if + * it is. + */ + if (!zip->process_mac_extensions) { + /* Treat every entry as a regular entry. */ + __archive_rb_tree_insert_node(&zip->tree, + &zip_entry->node); + } else { + name = p; + r = rsrc_basename(name, filename_length); + if (filename_length >= 9 && + strncmp("__MACOSX/", name, 9) == 0) { + /* If this file is not a resource fork nor + * a directory. We should treat it as a non + * resource fork file to expose it. */ + if (name[filename_length-1] != '/' && + (r - name < 3 || r[0] != '.' || + r[1] != '_')) { + __archive_rb_tree_insert_node( + &zip->tree, &zip_entry->node); + /* Expose its parent directories. */ + expose_parent_dirs(zip, name, + filename_length); + } else { + /* This file is a resource fork file or + * a directory. */ + archive_strncpy(&(zip_entry->rsrcname), + name, filename_length); + __archive_rb_tree_insert_node( + &zip->tree_rsrc, &zip_entry->node); + } + } else { + /* Generate resource fork name to find its + * resource file at zip->tree_rsrc. */ + archive_strcpy(&(zip_entry->rsrcname), + "__MACOSX/"); + archive_strncat(&(zip_entry->rsrcname), + name, r - name); + archive_strcat(&(zip_entry->rsrcname), "._"); + archive_strncat(&(zip_entry->rsrcname), + name + (r - name), + filename_length - (r - name)); + /* Register an entry to RB tree to sort it by + * file offset. */ + __archive_rb_tree_insert_node(&zip->tree, + &zip_entry->node); + } + } + + /* Skip the comment too ... */ + __archive_read_consume(a, + filename_length + extra_length + comment_length); + } + + return ARCHIVE_OK; +} + +static ssize_t +zip_get_local_file_header_size(struct archive_read *a, size_t extra) +{ + const char *p; + ssize_t filename_length, extra_length; + + if ((p = __archive_read_ahead(a, extra + 30, NULL)) == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file header"); + return (ARCHIVE_WARN); + } + p += extra; + + if (memcmp(p, "PK\003\004", 4) != 0) { + archive_set_error(&a->archive, -1, "Damaged Zip archive"); + return ARCHIVE_WARN; + } + filename_length = archive_le16dec(p + 26); + extra_length = archive_le16dec(p + 28); + + return (30 + filename_length + extra_length); +} + +static int +zip_read_mac_metadata(struct archive_read *a, struct archive_entry *entry, + struct zip_entry *rsrc) +{ + struct zip *zip = (struct zip *)a->format->data; + unsigned char *metadata, *mp; + int64_t offset = archive_filter_bytes(&a->archive, 0); + size_t remaining_bytes, metadata_bytes; + ssize_t hsize; + int ret = ARCHIVE_OK, eof; + + switch(rsrc->compression) { + case 0: /* No compression. */ + if (rsrc->uncompressed_size != rsrc->compressed_size) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Malformed OS X metadata entry: " + "inconsistent size"); + return (ARCHIVE_FATAL); + } +#ifdef HAVE_ZLIB_H + case 8: /* Deflate compression. */ +#endif + break; + default: /* Unsupported compression. */ + /* Return a warning. */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Unsupported ZIP compression method (%s)", + compression_name(rsrc->compression)); + /* We can't decompress this entry, but we will + * be able to skip() it and try the next entry. */ + return (ARCHIVE_WARN); + } + + if (rsrc->uncompressed_size > (4 * 1024 * 1024)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Mac metadata is too large: %jd > 4M bytes", + (intmax_t)rsrc->uncompressed_size); + return (ARCHIVE_WARN); + } + if (rsrc->compressed_size > (4 * 1024 * 1024)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Mac metadata is too large: %jd > 4M bytes", + (intmax_t)rsrc->compressed_size); + return (ARCHIVE_WARN); + } + + metadata = malloc((size_t)rsrc->uncompressed_size); + if (metadata == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Mac metadata"); + return (ARCHIVE_FATAL); + } + + if (offset < rsrc->local_header_offset) + __archive_read_consume(a, rsrc->local_header_offset - offset); + else if (offset != rsrc->local_header_offset) { + __archive_read_seek(a, rsrc->local_header_offset, SEEK_SET); + } + + hsize = zip_get_local_file_header_size(a, 0); + __archive_read_consume(a, hsize); + + remaining_bytes = (size_t)rsrc->compressed_size; + metadata_bytes = (size_t)rsrc->uncompressed_size; + mp = metadata; + eof = 0; + while (!eof && remaining_bytes) { + const unsigned char *p; + ssize_t bytes_avail; + size_t bytes_used; + + p = __archive_read_ahead(a, 1, &bytes_avail); + if (p == NULL) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file header"); + ret = ARCHIVE_WARN; + goto exit_mac_metadata; + } + if ((size_t)bytes_avail > remaining_bytes) + bytes_avail = remaining_bytes; + switch(rsrc->compression) { + case 0: /* No compression. */ + if ((size_t)bytes_avail > metadata_bytes) + bytes_avail = metadata_bytes; + memcpy(mp, p, bytes_avail); + bytes_used = (size_t)bytes_avail; + metadata_bytes -= bytes_used; + mp += bytes_used; + if (metadata_bytes == 0) + eof = 1; + break; +#ifdef HAVE_ZLIB_H + case 8: /* Deflate compression. */ + { + int r; + + ret = zip_deflate_init(a, zip); + if (ret != ARCHIVE_OK) + goto exit_mac_metadata; + zip->stream.next_in = + (Bytef *)(uintptr_t)(const void *)p; + zip->stream.avail_in = (uInt)bytes_avail; + zip->stream.total_in = 0; + zip->stream.next_out = mp; + zip->stream.avail_out = (uInt)metadata_bytes; + zip->stream.total_out = 0; + + r = inflate(&zip->stream, 0); + switch (r) { + case Z_OK: + break; + case Z_STREAM_END: + eof = 1; + break; + case Z_MEM_ERROR: + archive_set_error(&a->archive, ENOMEM, + "Out of memory for ZIP decompression"); + ret = ARCHIVE_FATAL; + goto exit_mac_metadata; + default: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "ZIP decompression failed (%d)", r); + ret = ARCHIVE_FATAL; + goto exit_mac_metadata; + } + bytes_used = zip->stream.total_in; + metadata_bytes -= zip->stream.total_out; + mp += zip->stream.total_out; + break; + } +#endif + default: + bytes_used = 0; + break; + } + __archive_read_consume(a, bytes_used); + remaining_bytes -= bytes_used; + } + archive_entry_copy_mac_metadata(entry, metadata, + (size_t)rsrc->uncompressed_size - metadata_bytes); + +exit_mac_metadata: + __archive_read_seek(a, offset, SEEK_SET); + zip->decompress_init = 0; + free(metadata); + return (ret); +} + +static int +archive_read_format_zip_seekable_read_header(struct archive_read *a, + struct archive_entry *entry) +{ + struct zip *zip = (struct zip *)a->format->data; + struct zip_entry *rsrc; + int64_t offset; + int r, ret = ARCHIVE_OK; + + /* + * It should be sufficient to call archive_read_next_header() for + * a reader to determine if an entry is encrypted or not. If the + * encryption of an entry is only detectable when calling + * archive_read_data(), so be it. We'll do the same check there + * as well. + */ + if (zip->has_encrypted_entries == + ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) + zip->has_encrypted_entries = 0; + + a->archive.archive_format = ARCHIVE_FORMAT_ZIP; + if (a->archive.archive_format_name == NULL) + a->archive.archive_format_name = "ZIP"; + + if (zip->zip_entries == NULL) { + r = slurp_central_directory(a, entry, zip); + if (r != ARCHIVE_OK) + return r; + /* Get first entry whose local header offset is lower than + * other entries in the archive file. */ + zip->entry = + (struct zip_entry *)ARCHIVE_RB_TREE_MIN(&zip->tree); + } else if (zip->entry != NULL) { + /* Get next entry in local header offset order. */ + zip->entry = (struct zip_entry *)__archive_rb_tree_iterate( + &zip->tree, &zip->entry->node, ARCHIVE_RB_DIR_RIGHT); + } + + if (zip->entry == NULL) + return ARCHIVE_EOF; + + if (zip->entry->rsrcname.s) + rsrc = (struct zip_entry *)__archive_rb_tree_find_node( + &zip->tree_rsrc, zip->entry->rsrcname.s); + else + rsrc = NULL; + + if (zip->cctx_valid) + archive_decrypto_aes_ctr_release(&zip->cctx); + if (zip->hctx_valid) + archive_hmac_sha1_cleanup(&zip->hctx); + zip->tctx_valid = zip->cctx_valid = zip->hctx_valid = 0; + __archive_read_reset_passphrase(a); + + /* File entries are sorted by the header offset, we should mostly + * use __archive_read_consume to advance a read point to avoid + * redundant data reading. */ + offset = archive_filter_bytes(&a->archive, 0); + if (offset < zip->entry->local_header_offset) + __archive_read_consume(a, + zip->entry->local_header_offset - offset); + else if (offset != zip->entry->local_header_offset) { + __archive_read_seek(a, zip->entry->local_header_offset, + SEEK_SET); + } + zip->unconsumed = 0; + r = zip_read_local_file_header(a, entry, zip); + if (r != ARCHIVE_OK) + return r; + if (rsrc) { + int ret2 = zip_read_mac_metadata(a, entry, rsrc); + if (ret2 < ret) + ret = ret2; + } + return (ret); +} + +/* + * We're going to seek for the next header anyway, so we don't + * need to bother doing anything here. + */ +static int +archive_read_format_zip_read_data_skip_seekable(struct archive_read *a) +{ + struct zip *zip; + zip = (struct zip *)(a->format->data); + + zip->unconsumed = 0; + return (ARCHIVE_OK); +} + +int +archive_read_support_format_zip_seekable(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct zip *zip; + int r; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_format_zip_seekable"); + + zip = (struct zip *)calloc(1, sizeof(*zip)); + if (zip == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate zip data"); + return (ARCHIVE_FATAL); + } + +#ifdef HAVE_COPYFILE_H + /* Set this by default on Mac OS. */ + zip->process_mac_extensions = 1; +#endif + + /* + * Until enough data has been read, we cannot tell about + * any encrypted entries yet. + */ + zip->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW; + zip->crc32func = real_crc32; + + r = __archive_read_register_format(a, + zip, + "zip", + archive_read_format_zip_seekable_bid, + archive_read_format_zip_options, + archive_read_format_zip_seekable_read_header, + archive_read_format_zip_read_data, + archive_read_format_zip_read_data_skip_seekable, + NULL, + archive_read_format_zip_cleanup, + archive_read_support_format_zip_capabilities_seekable, + archive_read_format_zip_has_encrypted_entries); + + if (r != ARCHIVE_OK) + free(zip); + return (ARCHIVE_OK); +} + +/*# vim:set noet:*/ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_string.c b/dependencies/libarchive-3.4.2/libarchive/archive_string.c new file mode 100644 index 0000000..c77dcf5 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_string.c @@ -0,0 +1,4224 @@ +/*- + * Copyright (c) 2003-2011 Tim Kientzle + * Copyright (c) 2011-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_string.c 201095 2009-12-28 02:33:22Z kientzle $"); + +/* + * Basic resizable string support, to simplify manipulating arbitrary-sized + * strings while minimizing heap activity. + * + * In particular, the buffer used by a string object is only grown, it + * never shrinks, so you can clear and reuse the same string object + * without incurring additional memory allocations. + */ + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_ICONV_H +#include +#endif +#ifdef HAVE_LANGINFO_H +#include +#endif +#ifdef HAVE_LOCALCHARSET_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_WCHAR_H +#include +#endif +#if defined(_WIN32) && !defined(__CYGWIN__) +#include +#include +#endif + +#include "archive_endian.h" +#include "archive_private.h" +#include "archive_string.h" +#include "archive_string_composition.h" + +#if !defined(HAVE_WMEMCPY) && !defined(wmemcpy) +#define wmemcpy(a,b,i) (wchar_t *)memcpy((a), (b), (i) * sizeof(wchar_t)) +#endif + +#if !defined(HAVE_WMEMMOVE) && !defined(wmemmove) +#define wmemmove(a,b,i) (wchar_t *)memmove((a), (b), (i) * sizeof(wchar_t)) +#endif + +#undef max +#define max(a, b) ((a)>(b)?(a):(b)) + +struct archive_string_conv { + struct archive_string_conv *next; + char *from_charset; + char *to_charset; + unsigned from_cp; + unsigned to_cp; + /* Set 1 if from_charset and to_charset are the same. */ + int same; + int flag; +#define SCONV_TO_CHARSET 1 /* MBS is being converted to specified + * charset. */ +#define SCONV_FROM_CHARSET (1<<1) /* MBS is being converted from + * specified charset. */ +#define SCONV_BEST_EFFORT (1<<2) /* Copy at least ASCII code. */ +#define SCONV_WIN_CP (1<<3) /* Use Windows API for converting + * MBS. */ +#define SCONV_UTF8_LIBARCHIVE_2 (1<<4) /* Incorrect UTF-8 made by libarchive + * 2.x in the wrong assumption. */ +#define SCONV_NORMALIZATION_C (1<<6) /* Need normalization to be Form C. + * Before UTF-8 characters are actually + * processed. */ +#define SCONV_NORMALIZATION_D (1<<7) /* Need normalization to be Form D. + * Before UTF-8 characters are actually + * processed. + * Currently this only for MAC OS X. */ +#define SCONV_TO_UTF8 (1<<8) /* "to charset" side is UTF-8. */ +#define SCONV_FROM_UTF8 (1<<9) /* "from charset" side is UTF-8. */ +#define SCONV_TO_UTF16BE (1<<10) /* "to charset" side is UTF-16BE. */ +#define SCONV_FROM_UTF16BE (1<<11) /* "from charset" side is UTF-16BE. */ +#define SCONV_TO_UTF16LE (1<<12) /* "to charset" side is UTF-16LE. */ +#define SCONV_FROM_UTF16LE (1<<13) /* "from charset" side is UTF-16LE. */ +#define SCONV_TO_UTF16 (SCONV_TO_UTF16BE | SCONV_TO_UTF16LE) +#define SCONV_FROM_UTF16 (SCONV_FROM_UTF16BE | SCONV_FROM_UTF16LE) + +#if HAVE_ICONV + iconv_t cd; + iconv_t cd_w;/* Use at archive_mstring on + * Windows. */ +#endif + /* A temporary buffer for normalization. */ + struct archive_string utftmp; + int (*converter[2])(struct archive_string *, const void *, size_t, + struct archive_string_conv *); + int nconverter; +}; + +#define CP_C_LOCALE 0 /* "C" locale only for this file. */ +#define CP_UTF16LE 1200 +#define CP_UTF16BE 1201 + +#define IS_HIGH_SURROGATE_LA(uc) ((uc) >= 0xD800 && (uc) <= 0xDBFF) +#define IS_LOW_SURROGATE_LA(uc) ((uc) >= 0xDC00 && (uc) <= 0xDFFF) +#define IS_SURROGATE_PAIR_LA(uc) ((uc) >= 0xD800 && (uc) <= 0xDFFF) +#define UNICODE_MAX 0x10FFFF +#define UNICODE_R_CHAR 0xFFFD /* Replacement character. */ +/* Set U+FFFD(Replacement character) in UTF-8. */ +static const char utf8_replacement_char[] = {0xef, 0xbf, 0xbd}; + +static struct archive_string_conv *find_sconv_object(struct archive *, + const char *, const char *); +static void add_sconv_object(struct archive *, struct archive_string_conv *); +static struct archive_string_conv *create_sconv_object(const char *, + const char *, unsigned, int); +static void free_sconv_object(struct archive_string_conv *); +static struct archive_string_conv *get_sconv_object(struct archive *, + const char *, const char *, int); +static unsigned make_codepage_from_charset(const char *); +static unsigned get_current_codepage(void); +static unsigned get_current_oemcp(void); +static size_t mbsnbytes(const void *, size_t); +static size_t utf16nbytes(const void *, size_t); +#if defined(_WIN32) && !defined(__CYGWIN__) +static int archive_wstring_append_from_mbs_in_codepage( + struct archive_wstring *, const char *, size_t, + struct archive_string_conv *); +static int archive_string_append_from_wcs_in_codepage(struct archive_string *, + const wchar_t *, size_t, struct archive_string_conv *); +static int is_big_endian(void); +static int strncat_in_codepage(struct archive_string *, const void *, + size_t, struct archive_string_conv *); +static int win_strncat_from_utf16be(struct archive_string *, const void *, + size_t, struct archive_string_conv *); +static int win_strncat_from_utf16le(struct archive_string *, const void *, + size_t, struct archive_string_conv *); +static int win_strncat_to_utf16be(struct archive_string *, const void *, + size_t, struct archive_string_conv *); +static int win_strncat_to_utf16le(struct archive_string *, const void *, + size_t, struct archive_string_conv *); +#endif +static int best_effort_strncat_from_utf16be(struct archive_string *, + const void *, size_t, struct archive_string_conv *); +static int best_effort_strncat_from_utf16le(struct archive_string *, + const void *, size_t, struct archive_string_conv *); +static int best_effort_strncat_to_utf16be(struct archive_string *, + const void *, size_t, struct archive_string_conv *); +static int best_effort_strncat_to_utf16le(struct archive_string *, + const void *, size_t, struct archive_string_conv *); +#if defined(HAVE_ICONV) +static int iconv_strncat_in_locale(struct archive_string *, const void *, + size_t, struct archive_string_conv *); +#endif +static int best_effort_strncat_in_locale(struct archive_string *, + const void *, size_t, struct archive_string_conv *); +static int _utf8_to_unicode(uint32_t *, const char *, size_t); +static int utf8_to_unicode(uint32_t *, const char *, size_t); +static inline uint32_t combine_surrogate_pair(uint32_t, uint32_t); +static int cesu8_to_unicode(uint32_t *, const char *, size_t); +static size_t unicode_to_utf8(char *, size_t, uint32_t); +static int utf16_to_unicode(uint32_t *, const char *, size_t, int); +static size_t unicode_to_utf16be(char *, size_t, uint32_t); +static size_t unicode_to_utf16le(char *, size_t, uint32_t); +static int strncat_from_utf8_libarchive2(struct archive_string *, + const void *, size_t, struct archive_string_conv *); +static int strncat_from_utf8_to_utf8(struct archive_string *, const void *, + size_t, struct archive_string_conv *); +static int archive_string_normalize_C(struct archive_string *, const void *, + size_t, struct archive_string_conv *); +static int archive_string_normalize_D(struct archive_string *, const void *, + size_t, struct archive_string_conv *); +static int archive_string_append_unicode(struct archive_string *, + const void *, size_t, struct archive_string_conv *); + +static struct archive_string * +archive_string_append(struct archive_string *as, const char *p, size_t s) +{ + if (archive_string_ensure(as, as->length + s + 1) == NULL) + return (NULL); + if (s) + memmove(as->s + as->length, p, s); + as->length += s; + as->s[as->length] = 0; + return (as); +} + +static struct archive_wstring * +archive_wstring_append(struct archive_wstring *as, const wchar_t *p, size_t s) +{ + if (archive_wstring_ensure(as, as->length + s + 1) == NULL) + return (NULL); + if (s) + wmemmove(as->s + as->length, p, s); + as->length += s; + as->s[as->length] = 0; + return (as); +} + +struct archive_string * +archive_array_append(struct archive_string *as, const char *p, size_t s) +{ + return archive_string_append(as, p, s); +} + +void +archive_string_concat(struct archive_string *dest, struct archive_string *src) +{ + if (archive_string_append(dest, src->s, src->length) == NULL) + __archive_errx(1, "Out of memory"); +} + +void +archive_wstring_concat(struct archive_wstring *dest, + struct archive_wstring *src) +{ + if (archive_wstring_append(dest, src->s, src->length) == NULL) + __archive_errx(1, "Out of memory"); +} + +void +archive_string_free(struct archive_string *as) +{ + as->length = 0; + as->buffer_length = 0; + free(as->s); + as->s = NULL; +} + +void +archive_wstring_free(struct archive_wstring *as) +{ + as->length = 0; + as->buffer_length = 0; + free(as->s); + as->s = NULL; +} + +struct archive_wstring * +archive_wstring_ensure(struct archive_wstring *as, size_t s) +{ + return (struct archive_wstring *) + archive_string_ensure((struct archive_string *)as, + s * sizeof(wchar_t)); +} + +/* Returns NULL on any allocation failure. */ +struct archive_string * +archive_string_ensure(struct archive_string *as, size_t s) +{ + char *p; + size_t new_length; + + /* If buffer is already big enough, don't reallocate. */ + if (as->s && (s <= as->buffer_length)) + return (as); + + /* + * Growing the buffer at least exponentially ensures that + * append operations are always linear in the number of + * characters appended. Using a smaller growth rate for + * larger buffers reduces memory waste somewhat at the cost of + * a larger constant factor. + */ + if (as->buffer_length < 32) + /* Start with a minimum 32-character buffer. */ + new_length = 32; + else if (as->buffer_length < 8192) + /* Buffers under 8k are doubled for speed. */ + new_length = as->buffer_length + as->buffer_length; + else { + /* Buffers 8k and over grow by at least 25% each time. */ + new_length = as->buffer_length + as->buffer_length / 4; + /* Be safe: If size wraps, fail. */ + if (new_length < as->buffer_length) { + /* On failure, wipe the string and return NULL. */ + archive_string_free(as); + errno = ENOMEM;/* Make sure errno has ENOMEM. */ + return (NULL); + } + } + /* + * The computation above is a lower limit to how much we'll + * grow the buffer. In any case, we have to grow it enough to + * hold the request. + */ + if (new_length < s) + new_length = s; + /* Now we can reallocate the buffer. */ + p = (char *)realloc(as->s, new_length); + if (p == NULL) { + /* On failure, wipe the string and return NULL. */ + archive_string_free(as); + errno = ENOMEM;/* Make sure errno has ENOMEM. */ + return (NULL); + } + + as->s = p; + as->buffer_length = new_length; + return (as); +} + +/* + * TODO: See if there's a way to avoid scanning + * the source string twice. Then test to see + * if it actually helps (remember that we're almost + * always called with pretty short arguments, so + * such an optimization might not help). + */ +struct archive_string * +archive_strncat(struct archive_string *as, const void *_p, size_t n) +{ + size_t s; + const char *p, *pp; + + p = (const char *)_p; + + /* Like strlen(p), except won't examine positions beyond p[n]. */ + s = 0; + pp = p; + while (s < n && *pp) { + pp++; + s++; + } + if ((as = archive_string_append(as, p, s)) == NULL) + __archive_errx(1, "Out of memory"); + return (as); +} + +struct archive_wstring * +archive_wstrncat(struct archive_wstring *as, const wchar_t *p, size_t n) +{ + size_t s; + const wchar_t *pp; + + /* Like strlen(p), except won't examine positions beyond p[n]. */ + s = 0; + pp = p; + while (s < n && *pp) { + pp++; + s++; + } + if ((as = archive_wstring_append(as, p, s)) == NULL) + __archive_errx(1, "Out of memory"); + return (as); +} + +struct archive_string * +archive_strcat(struct archive_string *as, const void *p) +{ + /* strcat is just strncat without an effective limit. + * Assert that we'll never get called with a source + * string over 16MB. + * TODO: Review all uses of strcat in the source + * and try to replace them with strncat(). + */ + return archive_strncat(as, p, 0x1000000); +} + +struct archive_wstring * +archive_wstrcat(struct archive_wstring *as, const wchar_t *p) +{ + /* Ditto. */ + return archive_wstrncat(as, p, 0x1000000); +} + +struct archive_string * +archive_strappend_char(struct archive_string *as, char c) +{ + if ((as = archive_string_append(as, &c, 1)) == NULL) + __archive_errx(1, "Out of memory"); + return (as); +} + +struct archive_wstring * +archive_wstrappend_wchar(struct archive_wstring *as, wchar_t c) +{ + if ((as = archive_wstring_append(as, &c, 1)) == NULL) + __archive_errx(1, "Out of memory"); + return (as); +} + +/* + * Get the "current character set" name to use with iconv. + * On FreeBSD, the empty character set name "" chooses + * the correct character encoding for the current locale, + * so this isn't necessary. + * But iconv on Mac OS 10.6 doesn't seem to handle this correctly; + * on that system, we have to explicitly call nl_langinfo() + * to get the right name. Not sure about other platforms. + * + * NOTE: GNU libiconv does not recognize the character-set name + * which some platform nl_langinfo(CODESET) returns, so we should + * use locale_charset() instead of nl_langinfo(CODESET) for GNU libiconv. + */ +static const char * +default_iconv_charset(const char *charset) { + if (charset != NULL && charset[0] != '\0') + return charset; +#if HAVE_LOCALE_CHARSET && !defined(__APPLE__) + /* locale_charset() is broken on Mac OS */ + return locale_charset(); +#elif HAVE_NL_LANGINFO + return nl_langinfo(CODESET); +#else + return ""; +#endif +} + +#if defined(_WIN32) && !defined(__CYGWIN__) + +/* + * Convert MBS to WCS. + * Note: returns -1 if conversion fails. + */ +int +archive_wstring_append_from_mbs(struct archive_wstring *dest, + const char *p, size_t len) +{ + return archive_wstring_append_from_mbs_in_codepage(dest, p, len, NULL); +} + +static int +archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest, + const char *s, size_t length, struct archive_string_conv *sc) +{ + int count, ret = 0; + UINT from_cp; + + if (sc != NULL) + from_cp = sc->from_cp; + else + from_cp = get_current_codepage(); + + if (from_cp == CP_C_LOCALE) { + /* + * "C" locale special processing. + */ + wchar_t *ws; + const unsigned char *mp; + + if (NULL == archive_wstring_ensure(dest, + dest->length + length + 1)) + return (-1); + + ws = dest->s + dest->length; + mp = (const unsigned char *)s; + count = 0; + while (count < (int)length && *mp) { + *ws++ = (wchar_t)*mp++; + count++; + } + } else if (sc != NULL && + (sc->flag & (SCONV_NORMALIZATION_C | SCONV_NORMALIZATION_D))) { + /* + * Normalize UTF-8 and UTF-16BE and convert it directly + * to UTF-16 as wchar_t. + */ + struct archive_string u16; + int saved_flag = sc->flag;/* save current flag. */ + + if (is_big_endian()) + sc->flag |= SCONV_TO_UTF16BE; + else + sc->flag |= SCONV_TO_UTF16LE; + + if (sc->flag & SCONV_FROM_UTF16) { + /* + * UTF-16BE/LE NFD ===> UTF-16 NFC + * UTF-16BE/LE NFC ===> UTF-16 NFD + */ + count = (int)utf16nbytes(s, length); + } else { + /* + * UTF-8 NFD ===> UTF-16 NFC + * UTF-8 NFC ===> UTF-16 NFD + */ + count = (int)mbsnbytes(s, length); + } + u16.s = (char *)dest->s; + u16.length = dest->length << 1;; + u16.buffer_length = dest->buffer_length; + if (sc->flag & SCONV_NORMALIZATION_C) + ret = archive_string_normalize_C(&u16, s, count, sc); + else + ret = archive_string_normalize_D(&u16, s, count, sc); + dest->s = (wchar_t *)u16.s; + dest->length = u16.length >> 1; + dest->buffer_length = u16.buffer_length; + sc->flag = saved_flag;/* restore the saved flag. */ + return (ret); + } else if (sc != NULL && (sc->flag & SCONV_FROM_UTF16)) { + count = (int)utf16nbytes(s, length); + count >>= 1; /* to be WCS length */ + /* Allocate memory for WCS. */ + if (NULL == archive_wstring_ensure(dest, + dest->length + count + 1)) + return (-1); + wmemcpy(dest->s + dest->length, (const wchar_t *)s, count); + if ((sc->flag & SCONV_FROM_UTF16BE) && !is_big_endian()) { + uint16_t *u16 = (uint16_t *)(dest->s + dest->length); + int b; + for (b = 0; b < count; b++) { + uint16_t val = archive_le16dec(u16+b); + archive_be16enc(u16+b, val); + } + } else if ((sc->flag & SCONV_FROM_UTF16LE) && is_big_endian()) { + uint16_t *u16 = (uint16_t *)(dest->s + dest->length); + int b; + for (b = 0; b < count; b++) { + uint16_t val = archive_be16dec(u16+b); + archive_le16enc(u16+b, val); + } + } + } else { + DWORD mbflag; + size_t buffsize; + + if (sc == NULL) + mbflag = 0; + else if (sc->flag & SCONV_FROM_CHARSET) { + /* Do not trust the length which comes from + * an archive file. */ + length = mbsnbytes(s, length); + mbflag = 0; + } else + mbflag = MB_PRECOMPOSED; + + buffsize = dest->length + length + 1; + do { + /* Allocate memory for WCS. */ + if (NULL == archive_wstring_ensure(dest, buffsize)) + return (-1); + /* Convert MBS to WCS. */ + count = MultiByteToWideChar(from_cp, + mbflag, s, (int)length, dest->s + dest->length, + (int)(dest->buffer_length >> 1) -1); + if (count == 0 && + GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + /* Expand the WCS buffer. */ + buffsize = dest->buffer_length << 1; + continue; + } + if (count == 0 && length != 0) + ret = -1; + break; + } while (1); + } + dest->length += count; + dest->s[dest->length] = L'\0'; + return (ret); +} + +#else + +/* + * Convert MBS to WCS. + * Note: returns -1 if conversion fails. + */ +int +archive_wstring_append_from_mbs(struct archive_wstring *dest, + const char *p, size_t len) +{ + size_t r; + int ret_val = 0; + /* + * No single byte will be more than one wide character, + * so this length estimate will always be big enough. + */ + // size_t wcs_length = len; + size_t mbs_length = len; + const char *mbs = p; + wchar_t *wcs; +#if HAVE_MBRTOWC + mbstate_t shift_state; + + memset(&shift_state, 0, sizeof(shift_state)); +#endif + /* + * As we decided to have wcs_length == mbs_length == len + * we can use len here instead of wcs_length + */ + if (NULL == archive_wstring_ensure(dest, dest->length + len + 1)) + return (-1); + wcs = dest->s + dest->length; + /* + * We cannot use mbsrtowcs/mbstowcs here because those may convert + * extra MBS when strlen(p) > len and one wide character consists of + * multi bytes. + */ + while (*mbs && mbs_length > 0) { + /* + * The buffer we allocated is always big enough. + * Keep this code path in a comment if we decide to choose + * smaller wcs_length in the future + */ +/* + if (wcs_length == 0) { + dest->length = wcs - dest->s; + dest->s[dest->length] = L'\0'; + wcs_length = mbs_length; + if (NULL == archive_wstring_ensure(dest, + dest->length + wcs_length + 1)) + return (-1); + wcs = dest->s + dest->length; + } +*/ +#if HAVE_MBRTOWC + r = mbrtowc(wcs, mbs, mbs_length, &shift_state); +#else + r = mbtowc(wcs, mbs, mbs_length); +#endif + if (r == (size_t)-1 || r == (size_t)-2) { + ret_val = -1; + break; + } + if (r == 0 || r > mbs_length) + break; + wcs++; + // wcs_length--; + mbs += r; + mbs_length -= r; + } + dest->length = wcs - dest->s; + dest->s[dest->length] = L'\0'; + return (ret_val); +} + +#endif + +#if defined(_WIN32) && !defined(__CYGWIN__) + +/* + * WCS ==> MBS. + * Note: returns -1 if conversion fails. + * + * Win32 builds use WideCharToMultiByte from the Windows API. + * (Maybe Cygwin should too? WideCharToMultiByte will know a + * lot more about local character encodings than the wcrtomb() + * wrapper is going to know.) + */ +int +archive_string_append_from_wcs(struct archive_string *as, + const wchar_t *w, size_t len) +{ + return archive_string_append_from_wcs_in_codepage(as, w, len, NULL); +} + +static int +archive_string_append_from_wcs_in_codepage(struct archive_string *as, + const wchar_t *ws, size_t len, struct archive_string_conv *sc) +{ + BOOL defchar_used, *dp; + int count, ret = 0; + UINT to_cp; + int wslen = (int)len; + + if (sc != NULL) + to_cp = sc->to_cp; + else + to_cp = get_current_codepage(); + + if (to_cp == CP_C_LOCALE) { + /* + * "C" locale special processing. + */ + const wchar_t *wp = ws; + char *p; + + if (NULL == archive_string_ensure(as, + as->length + wslen +1)) + return (-1); + p = as->s + as->length; + count = 0; + defchar_used = 0; + while (count < wslen && *wp) { + if (*wp > 255) { + *p++ = '?'; + wp++; + defchar_used = 1; + } else + *p++ = (char)*wp++; + count++; + } + } else if (sc != NULL && (sc->flag & SCONV_TO_UTF16)) { + uint16_t *u16; + + if (NULL == + archive_string_ensure(as, as->length + len * 2 + 2)) + return (-1); + u16 = (uint16_t *)(as->s + as->length); + count = 0; + defchar_used = 0; + if (sc->flag & SCONV_TO_UTF16BE) { + while (count < (int)len && *ws) { + archive_be16enc(u16+count, *ws); + ws++; + count++; + } + } else { + while (count < (int)len && *ws) { + archive_le16enc(u16+count, *ws); + ws++; + count++; + } + } + count <<= 1; /* to be byte size */ + } else { + /* Make sure the MBS buffer has plenty to set. */ + if (NULL == + archive_string_ensure(as, as->length + len * 2 + 1)) + return (-1); + do { + defchar_used = 0; + if (to_cp == CP_UTF8 || sc == NULL) + dp = NULL; + else + dp = &defchar_used; + count = WideCharToMultiByte(to_cp, 0, ws, wslen, + as->s + as->length, + (int)as->buffer_length - as->length - 1, NULL, dp); + if (count == 0 && + GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + /* Expand the MBS buffer and retry. */ + if (NULL == archive_string_ensure(as, + as->buffer_length + len)) + return (-1); + continue; + } + if (count == 0) + ret = -1; + break; + } while (1); + } + as->length += count; + as->s[as->length] = '\0'; + return (defchar_used?-1:ret); +} + +#elif defined(HAVE_WCTOMB) || defined(HAVE_WCRTOMB) + +/* + * Translates a wide character string into current locale character set + * and appends to the archive_string. Note: returns -1 if conversion + * fails. + */ +int +archive_string_append_from_wcs(struct archive_string *as, + const wchar_t *w, size_t len) +{ + /* We cannot use the standard wcstombs() here because it + * cannot tell us how big the output buffer should be. So + * I've built a loop around wcrtomb() or wctomb() that + * converts a character at a time and resizes the string as + * needed. We prefer wcrtomb() when it's available because + * it's thread-safe. */ + int n, ret_val = 0; + char *p; + char *end; +#if HAVE_WCRTOMB + mbstate_t shift_state; + + memset(&shift_state, 0, sizeof(shift_state)); +#else + /* Clear the shift state before starting. */ + wctomb(NULL, L'\0'); +#endif + /* + * Allocate buffer for MBS. + * We need this allocation here since it is possible that + * as->s is still NULL. + */ + if (archive_string_ensure(as, as->length + len + 1) == NULL) + return (-1); + + p = as->s + as->length; + end = as->s + as->buffer_length - MB_CUR_MAX -1; + while (*w != L'\0' && len > 0) { + if (p >= end) { + as->length = p - as->s; + as->s[as->length] = '\0'; + /* Re-allocate buffer for MBS. */ + if (archive_string_ensure(as, + as->length + max(len * 2, + (size_t)MB_CUR_MAX) + 1) == NULL) + return (-1); + p = as->s + as->length; + end = as->s + as->buffer_length - MB_CUR_MAX -1; + } +#if HAVE_WCRTOMB + n = wcrtomb(p, *w++, &shift_state); +#else + n = wctomb(p, *w++); +#endif + if (n == -1) { + if (errno == EILSEQ) { + /* Skip an illegal wide char. */ + *p++ = '?'; + ret_val = -1; + } else { + ret_val = -1; + break; + } + } else + p += n; + len--; + } + as->length = p - as->s; + as->s[as->length] = '\0'; + return (ret_val); +} + +#else /* HAVE_WCTOMB || HAVE_WCRTOMB */ + +/* + * TODO: Test if __STDC_ISO_10646__ is defined. + * Non-Windows uses ISO C wcrtomb() or wctomb() to perform the conversion + * one character at a time. If a non-Windows platform doesn't have + * either of these, fall back to the built-in UTF8 conversion. + */ +int +archive_string_append_from_wcs(struct archive_string *as, + const wchar_t *w, size_t len) +{ + (void)as;/* UNUSED */ + (void)w;/* UNUSED */ + (void)len;/* UNUSED */ + errno = ENOSYS; + return (-1); +} + +#endif /* HAVE_WCTOMB || HAVE_WCRTOMB */ + +/* + * Find a string conversion object by a pair of 'from' charset name + * and 'to' charset name from an archive object. + * Return NULL if not found. + */ +static struct archive_string_conv * +find_sconv_object(struct archive *a, const char *fc, const char *tc) +{ + struct archive_string_conv *sc; + + if (a == NULL) + return (NULL); + + for (sc = a->sconv; sc != NULL; sc = sc->next) { + if (strcmp(sc->from_charset, fc) == 0 && + strcmp(sc->to_charset, tc) == 0) + break; + } + return (sc); +} + +/* + * Register a string object to an archive object. + */ +static void +add_sconv_object(struct archive *a, struct archive_string_conv *sc) +{ + struct archive_string_conv **psc; + + /* Add a new sconv to sconv list. */ + psc = &(a->sconv); + while (*psc != NULL) + psc = &((*psc)->next); + *psc = sc; +} + +static void +add_converter(struct archive_string_conv *sc, int (*converter) + (struct archive_string *, const void *, size_t, + struct archive_string_conv *)) +{ + if (sc == NULL || sc->nconverter >= 2) + __archive_errx(1, "Programming error"); + sc->converter[sc->nconverter++] = converter; +} + +static void +setup_converter(struct archive_string_conv *sc) +{ + + /* Reset. */ + sc->nconverter = 0; + + /* + * Perform special sequence for the incorrect UTF-8 filenames + * made by libarchive2.x. + */ + if (sc->flag & SCONV_UTF8_LIBARCHIVE_2) { + add_converter(sc, strncat_from_utf8_libarchive2); + return; + } + + /* + * Convert a string to UTF-16BE/LE. + */ + if (sc->flag & SCONV_TO_UTF16) { + /* + * If the current locale is UTF-8, we can translate + * a UTF-8 string into a UTF-16BE string. + */ + if (sc->flag & SCONV_FROM_UTF8) { + add_converter(sc, archive_string_append_unicode); + return; + } + +#if defined(_WIN32) && !defined(__CYGWIN__) + if (sc->flag & SCONV_WIN_CP) { + if (sc->flag & SCONV_TO_UTF16BE) + add_converter(sc, win_strncat_to_utf16be); + else + add_converter(sc, win_strncat_to_utf16le); + return; + } +#endif + +#if defined(HAVE_ICONV) + if (sc->cd != (iconv_t)-1) { + add_converter(sc, iconv_strncat_in_locale); + return; + } +#endif + + if (sc->flag & SCONV_BEST_EFFORT) { + if (sc->flag & SCONV_TO_UTF16BE) + add_converter(sc, + best_effort_strncat_to_utf16be); + else + add_converter(sc, + best_effort_strncat_to_utf16le); + } else + /* Make sure we have no converter. */ + sc->nconverter = 0; + return; + } + + /* + * Convert a string from UTF-16BE/LE. + */ + if (sc->flag & SCONV_FROM_UTF16) { + /* + * At least we should normalize a UTF-16BE string. + */ + if (sc->flag & SCONV_NORMALIZATION_D) + add_converter(sc,archive_string_normalize_D); + else if (sc->flag & SCONV_NORMALIZATION_C) + add_converter(sc, archive_string_normalize_C); + + if (sc->flag & SCONV_TO_UTF8) { + /* + * If the current locale is UTF-8, we can translate + * a UTF-16BE/LE string into a UTF-8 string directly. + */ + if (!(sc->flag & + (SCONV_NORMALIZATION_D |SCONV_NORMALIZATION_C))) + add_converter(sc, + archive_string_append_unicode); + return; + } + +#if defined(_WIN32) && !defined(__CYGWIN__) + if (sc->flag & SCONV_WIN_CP) { + if (sc->flag & SCONV_FROM_UTF16BE) + add_converter(sc, win_strncat_from_utf16be); + else + add_converter(sc, win_strncat_from_utf16le); + return; + } +#endif + +#if defined(HAVE_ICONV) + if (sc->cd != (iconv_t)-1) { + add_converter(sc, iconv_strncat_in_locale); + return; + } +#endif + + if ((sc->flag & (SCONV_BEST_EFFORT | SCONV_FROM_UTF16BE)) + == (SCONV_BEST_EFFORT | SCONV_FROM_UTF16BE)) + add_converter(sc, best_effort_strncat_from_utf16be); + else if ((sc->flag & (SCONV_BEST_EFFORT | SCONV_FROM_UTF16LE)) + == (SCONV_BEST_EFFORT | SCONV_FROM_UTF16LE)) + add_converter(sc, best_effort_strncat_from_utf16le); + else + /* Make sure we have no converter. */ + sc->nconverter = 0; + return; + } + + if (sc->flag & SCONV_FROM_UTF8) { + /* + * At least we should normalize a UTF-8 string. + */ + if (sc->flag & SCONV_NORMALIZATION_D) + add_converter(sc,archive_string_normalize_D); + else if (sc->flag & SCONV_NORMALIZATION_C) + add_converter(sc, archive_string_normalize_C); + + /* + * Copy UTF-8 string with a check of CESU-8. + * Apparently, iconv does not check surrogate pairs in UTF-8 + * when both from-charset and to-charset are UTF-8, and then + * we use our UTF-8 copy code. + */ + if (sc->flag & SCONV_TO_UTF8) { + /* + * If the current locale is UTF-8, we can translate + * a UTF-16BE string into a UTF-8 string directly. + */ + if (!(sc->flag & + (SCONV_NORMALIZATION_D |SCONV_NORMALIZATION_C))) + add_converter(sc, strncat_from_utf8_to_utf8); + return; + } + } + +#if defined(_WIN32) && !defined(__CYGWIN__) + /* + * On Windows we can use Windows API for a string conversion. + */ + if (sc->flag & SCONV_WIN_CP) { + add_converter(sc, strncat_in_codepage); + return; + } +#endif + +#if HAVE_ICONV + if (sc->cd != (iconv_t)-1) { + add_converter(sc, iconv_strncat_in_locale); + /* + * iconv generally does not support UTF-8-MAC and so + * we have to the output of iconv from NFC to NFD if + * need. + */ + if ((sc->flag & SCONV_FROM_CHARSET) && + (sc->flag & SCONV_TO_UTF8)) { + if (sc->flag & SCONV_NORMALIZATION_D) + add_converter(sc, archive_string_normalize_D); + } + return; + } +#endif + + /* + * Try conversion in the best effort or no conversion. + */ + if ((sc->flag & SCONV_BEST_EFFORT) || sc->same) + add_converter(sc, best_effort_strncat_in_locale); + else + /* Make sure we have no converter. */ + sc->nconverter = 0; +} + +/* + * Return canonicalized charset-name but this supports just UTF-8, UTF-16BE + * and CP932 which are referenced in create_sconv_object(). + */ +static const char * +canonical_charset_name(const char *charset) +{ + char cs[16]; + char *p; + const char *s; + + if (charset == NULL || charset[0] == '\0' + || strlen(charset) > 15) + return (charset); + + /* Copy name to uppercase. */ + p = cs; + s = charset; + while (*s) { + char c = *s++; + if (c >= 'a' && c <= 'z') + c -= 'a' - 'A'; + *p++ = c; + } + *p++ = '\0'; + + if (strcmp(cs, "UTF-8") == 0 || + strcmp(cs, "UTF8") == 0) + return ("UTF-8"); + if (strcmp(cs, "UTF-16BE") == 0 || + strcmp(cs, "UTF16BE") == 0) + return ("UTF-16BE"); + if (strcmp(cs, "UTF-16LE") == 0 || + strcmp(cs, "UTF16LE") == 0) + return ("UTF-16LE"); + if (strcmp(cs, "CP932") == 0) + return ("CP932"); + return (charset); +} + +/* + * Create a string conversion object. + */ +static struct archive_string_conv * +create_sconv_object(const char *fc, const char *tc, + unsigned current_codepage, int flag) +{ + struct archive_string_conv *sc; + + sc = calloc(1, sizeof(*sc)); + if (sc == NULL) + return (NULL); + sc->next = NULL; + sc->from_charset = strdup(fc); + if (sc->from_charset == NULL) { + free(sc); + return (NULL); + } + sc->to_charset = strdup(tc); + if (sc->to_charset == NULL) { + free(sc->from_charset); + free(sc); + return (NULL); + } + archive_string_init(&sc->utftmp); + + if (flag & SCONV_TO_CHARSET) { + /* + * Convert characters from the current locale charset to + * a specified charset. + */ + sc->from_cp = current_codepage; + sc->to_cp = make_codepage_from_charset(tc); +#if defined(_WIN32) && !defined(__CYGWIN__) + if (IsValidCodePage(sc->to_cp)) + flag |= SCONV_WIN_CP; +#endif + } else if (flag & SCONV_FROM_CHARSET) { + /* + * Convert characters from a specified charset to + * the current locale charset. + */ + sc->to_cp = current_codepage; + sc->from_cp = make_codepage_from_charset(fc); +#if defined(_WIN32) && !defined(__CYGWIN__) + if (IsValidCodePage(sc->from_cp)) + flag |= SCONV_WIN_CP; +#endif + } + + /* + * Check if "from charset" and "to charset" are the same. + */ + if (strcmp(fc, tc) == 0 || + (sc->from_cp != (unsigned)-1 && sc->from_cp == sc->to_cp)) + sc->same = 1; + else + sc->same = 0; + + /* + * Mark if "from charset" or "to charset" are UTF-8 or UTF-16BE/LE. + */ + if (strcmp(tc, "UTF-8") == 0) + flag |= SCONV_TO_UTF8; + else if (strcmp(tc, "UTF-16BE") == 0) + flag |= SCONV_TO_UTF16BE; + else if (strcmp(tc, "UTF-16LE") == 0) + flag |= SCONV_TO_UTF16LE; + if (strcmp(fc, "UTF-8") == 0) + flag |= SCONV_FROM_UTF8; + else if (strcmp(fc, "UTF-16BE") == 0) + flag |= SCONV_FROM_UTF16BE; + else if (strcmp(fc, "UTF-16LE") == 0) + flag |= SCONV_FROM_UTF16LE; +#if defined(_WIN32) && !defined(__CYGWIN__) + if (sc->to_cp == CP_UTF8) + flag |= SCONV_TO_UTF8; + else if (sc->to_cp == CP_UTF16BE) + flag |= SCONV_TO_UTF16BE | SCONV_WIN_CP; + else if (sc->to_cp == CP_UTF16LE) + flag |= SCONV_TO_UTF16LE | SCONV_WIN_CP; + if (sc->from_cp == CP_UTF8) + flag |= SCONV_FROM_UTF8; + else if (sc->from_cp == CP_UTF16BE) + flag |= SCONV_FROM_UTF16BE | SCONV_WIN_CP; + else if (sc->from_cp == CP_UTF16LE) + flag |= SCONV_FROM_UTF16LE | SCONV_WIN_CP; +#endif + + /* + * Set a flag for Unicode NFD. Usually iconv cannot correctly + * handle it. So we have to translate NFD characters to NFC ones + * ourselves before iconv handles. Another reason is to prevent + * that the same sight of two filenames, one is NFC and other + * is NFD, would be in its directory. + * On Mac OS X, although its filesystem layer automatically + * convert filenames to NFD, it would be useful for filename + * comparing to find out the same filenames that we normalize + * that to be NFD ourselves. + */ + if ((flag & SCONV_FROM_CHARSET) && + (flag & (SCONV_FROM_UTF16 | SCONV_FROM_UTF8))) { +#if defined(__APPLE__) + if (flag & SCONV_TO_UTF8) + flag |= SCONV_NORMALIZATION_D; + else +#endif + flag |= SCONV_NORMALIZATION_C; + } +#if defined(__APPLE__) + /* + * In case writing an archive file, make sure that a filename + * going to be passed to iconv is a Unicode NFC string since + * a filename in HFS Plus filesystem is a Unicode NFD one and + * iconv cannot handle it with "UTF-8" charset. It is simpler + * than a use of "UTF-8-MAC" charset. + */ + if ((flag & SCONV_TO_CHARSET) && + (flag & (SCONV_FROM_UTF16 | SCONV_FROM_UTF8)) && + !(flag & (SCONV_TO_UTF16 | SCONV_TO_UTF8))) + flag |= SCONV_NORMALIZATION_C; + /* + * In case reading an archive file. make sure that a filename + * will be passed to users is a Unicode NFD string in order to + * correctly compare the filename with other one which comes + * from HFS Plus filesystem. + */ + if ((flag & SCONV_FROM_CHARSET) && + !(flag & (SCONV_FROM_UTF16 | SCONV_FROM_UTF8)) && + (flag & SCONV_TO_UTF8)) + flag |= SCONV_NORMALIZATION_D; +#endif + +#if defined(HAVE_ICONV) + sc->cd_w = (iconv_t)-1; + /* + * Create an iconv object. + */ + if (((flag & (SCONV_TO_UTF8 | SCONV_TO_UTF16)) && + (flag & (SCONV_FROM_UTF8 | SCONV_FROM_UTF16))) || + (flag & SCONV_WIN_CP)) { + /* This case we won't use iconv. */ + sc->cd = (iconv_t)-1; + } else { + sc->cd = iconv_open(tc, fc); + if (sc->cd == (iconv_t)-1 && (sc->flag & SCONV_BEST_EFFORT)) { + /* + * Unfortunately, all of iconv implements do support + * "CP932" character-set, so we should use "SJIS" + * instead if iconv_open failed. + */ + if (strcmp(tc, "CP932") == 0) + sc->cd = iconv_open("SJIS", fc); + else if (strcmp(fc, "CP932") == 0) + sc->cd = iconv_open(tc, "SJIS"); + } +#if defined(_WIN32) && !defined(__CYGWIN__) + /* + * archive_mstring on Windows directly convert multi-bytes + * into archive_wstring in order not to depend on locale + * so that you can do a I18N programming. This will be + * used only in archive_mstring_copy_mbs_len_l so far. + */ + if (flag & SCONV_FROM_CHARSET) { + sc->cd_w = iconv_open("UTF-8", fc); + if (sc->cd_w == (iconv_t)-1 && + (sc->flag & SCONV_BEST_EFFORT)) { + if (strcmp(fc, "CP932") == 0) + sc->cd_w = iconv_open("UTF-8", "SJIS"); + } + } +#endif /* _WIN32 && !__CYGWIN__ */ + } +#endif /* HAVE_ICONV */ + + sc->flag = flag; + + /* + * Set up converters. + */ + setup_converter(sc); + + return (sc); +} + +/* + * Free a string conversion object. + */ +static void +free_sconv_object(struct archive_string_conv *sc) +{ + free(sc->from_charset); + free(sc->to_charset); + archive_string_free(&sc->utftmp); +#if HAVE_ICONV + if (sc->cd != (iconv_t)-1) + iconv_close(sc->cd); + if (sc->cd_w != (iconv_t)-1) + iconv_close(sc->cd_w); +#endif + free(sc); +} + +#if defined(_WIN32) && !defined(__CYGWIN__) +static unsigned +my_atoi(const char *p) +{ + unsigned cp; + + cp = 0; + while (*p) { + if (*p >= '0' && *p <= '9') + cp = cp * 10 + (*p - '0'); + else + return (-1); + p++; + } + return (cp); +} + +/* + * Translate Charset name (as used by iconv) into CodePage (as used by Windows) + * Return -1 if failed. + * + * Note: This translation code may be insufficient. + */ +static struct charset { + const char *name; + unsigned cp; +} charsets[] = { + /* MUST BE SORTED! */ + {"ASCII", 1252}, + {"ASMO-708", 708}, + {"BIG5", 950}, + {"CHINESE", 936}, + {"CP367", 1252}, + {"CP819", 1252}, + {"CP1025", 21025}, + {"DOS-720", 720}, + {"DOS-862", 862}, + {"EUC-CN", 51936}, + {"EUC-JP", 51932}, + {"EUC-KR", 949}, + {"EUCCN", 51936}, + {"EUCJP", 51932}, + {"EUCKR", 949}, + {"GB18030", 54936}, + {"GB2312", 936}, + {"HEBREW", 1255}, + {"HZ-GB-2312", 52936}, + {"IBM273", 20273}, + {"IBM277", 20277}, + {"IBM278", 20278}, + {"IBM280", 20280}, + {"IBM284", 20284}, + {"IBM285", 20285}, + {"IBM290", 20290}, + {"IBM297", 20297}, + {"IBM367", 1252}, + {"IBM420", 20420}, + {"IBM423", 20423}, + {"IBM424", 20424}, + {"IBM819", 1252}, + {"IBM871", 20871}, + {"IBM880", 20880}, + {"IBM905", 20905}, + {"IBM924", 20924}, + {"ISO-8859-1", 28591}, + {"ISO-8859-13", 28603}, + {"ISO-8859-15", 28605}, + {"ISO-8859-2", 28592}, + {"ISO-8859-3", 28593}, + {"ISO-8859-4", 28594}, + {"ISO-8859-5", 28595}, + {"ISO-8859-6", 28596}, + {"ISO-8859-7", 28597}, + {"ISO-8859-8", 28598}, + {"ISO-8859-9", 28599}, + {"ISO8859-1", 28591}, + {"ISO8859-13", 28603}, + {"ISO8859-15", 28605}, + {"ISO8859-2", 28592}, + {"ISO8859-3", 28593}, + {"ISO8859-4", 28594}, + {"ISO8859-5", 28595}, + {"ISO8859-6", 28596}, + {"ISO8859-7", 28597}, + {"ISO8859-8", 28598}, + {"ISO8859-9", 28599}, + {"JOHAB", 1361}, + {"KOI8-R", 20866}, + {"KOI8-U", 21866}, + {"KS_C_5601-1987", 949}, + {"LATIN1", 1252}, + {"LATIN2", 28592}, + {"MACINTOSH", 10000}, + {"SHIFT-JIS", 932}, + {"SHIFT_JIS", 932}, + {"SJIS", 932}, + {"US", 1252}, + {"US-ASCII", 1252}, + {"UTF-16", 1200}, + {"UTF-16BE", 1201}, + {"UTF-16LE", 1200}, + {"UTF-8", CP_UTF8}, + {"X-EUROPA", 29001}, + {"X-MAC-ARABIC", 10004}, + {"X-MAC-CE", 10029}, + {"X-MAC-CHINESEIMP", 10008}, + {"X-MAC-CHINESETRAD", 10002}, + {"X-MAC-CROATIAN", 10082}, + {"X-MAC-CYRILLIC", 10007}, + {"X-MAC-GREEK", 10006}, + {"X-MAC-HEBREW", 10005}, + {"X-MAC-ICELANDIC", 10079}, + {"X-MAC-JAPANESE", 10001}, + {"X-MAC-KOREAN", 10003}, + {"X-MAC-ROMANIAN", 10010}, + {"X-MAC-THAI", 10021}, + {"X-MAC-TURKISH", 10081}, + {"X-MAC-UKRAINIAN", 10017}, +}; +static unsigned +make_codepage_from_charset(const char *charset) +{ + char cs[16]; + char *p; + unsigned cp; + int a, b; + + if (charset == NULL || strlen(charset) > 15) + return -1; + + /* Copy name to uppercase. */ + p = cs; + while (*charset) { + char c = *charset++; + if (c >= 'a' && c <= 'z') + c -= 'a' - 'A'; + *p++ = c; + } + *p++ = '\0'; + cp = -1; + + /* Look it up in the table first, so that we can easily + * override CP367, which we map to 1252 instead of 367. */ + a = 0; + b = sizeof(charsets)/sizeof(charsets[0]); + while (b > a) { + int c = (b + a) / 2; + int r = strcmp(charsets[c].name, cs); + if (r < 0) + a = c + 1; + else if (r > 0) + b = c; + else + return charsets[c].cp; + } + + /* If it's not in the table, try to parse it. */ + switch (*cs) { + case 'C': + if (cs[1] == 'P' && cs[2] >= '0' && cs[2] <= '9') { + cp = my_atoi(cs + 2); + } else if (strcmp(cs, "CP_ACP") == 0) + cp = get_current_codepage(); + else if (strcmp(cs, "CP_OEMCP") == 0) + cp = get_current_oemcp(); + break; + case 'I': + if (cs[1] == 'B' && cs[2] == 'M' && + cs[3] >= '0' && cs[3] <= '9') { + cp = my_atoi(cs + 3); + } + break; + case 'W': + if (strncmp(cs, "WINDOWS-", 8) == 0) { + cp = my_atoi(cs + 8); + if (cp != 874 && (cp < 1250 || cp > 1258)) + cp = -1;/* This may invalid code. */ + } + break; + } + return (cp); +} + +/* + * Return ANSI Code Page of current locale set by setlocale(). + */ +static unsigned +get_current_codepage(void) +{ + char *locale, *p; + unsigned cp; + + locale = setlocale(LC_CTYPE, NULL); + if (locale == NULL) + return (GetACP()); + if (locale[0] == 'C' && locale[1] == '\0') + return (CP_C_LOCALE); + p = strrchr(locale, '.'); + if (p == NULL) + return (GetACP()); + if (strcmp(p+1, "utf8") == 0) + return CP_UTF8; + cp = my_atoi(p+1); + if ((int)cp <= 0) + return (GetACP()); + return (cp); +} + +/* + * Translation table between Locale Name and ACP/OEMCP. + */ +static struct { + unsigned acp; + unsigned ocp; + const char *locale; +} acp_ocp_map[] = { + { 950, 950, "Chinese_Taiwan" }, + { 936, 936, "Chinese_People's Republic of China" }, + { 950, 950, "Chinese_Taiwan" }, + { 1250, 852, "Czech_Czech Republic" }, + { 1252, 850, "Danish_Denmark" }, + { 1252, 850, "Dutch_Netherlands" }, + { 1252, 850, "Dutch_Belgium" }, + { 1252, 437, "English_United States" }, + { 1252, 850, "English_Australia" }, + { 1252, 850, "English_Canada" }, + { 1252, 850, "English_New Zealand" }, + { 1252, 850, "English_United Kingdom" }, + { 1252, 437, "English_United States" }, + { 1252, 850, "Finnish_Finland" }, + { 1252, 850, "French_France" }, + { 1252, 850, "French_Belgium" }, + { 1252, 850, "French_Canada" }, + { 1252, 850, "French_Switzerland" }, + { 1252, 850, "German_Germany" }, + { 1252, 850, "German_Austria" }, + { 1252, 850, "German_Switzerland" }, + { 1253, 737, "Greek_Greece" }, + { 1250, 852, "Hungarian_Hungary" }, + { 1252, 850, "Icelandic_Iceland" }, + { 1252, 850, "Italian_Italy" }, + { 1252, 850, "Italian_Switzerland" }, + { 932, 932, "Japanese_Japan" }, + { 949, 949, "Korean_Korea" }, + { 1252, 850, "Norwegian (BokmOl)_Norway" }, + { 1252, 850, "Norwegian (BokmOl)_Norway" }, + { 1252, 850, "Norwegian-Nynorsk_Norway" }, + { 1250, 852, "Polish_Poland" }, + { 1252, 850, "Portuguese_Portugal" }, + { 1252, 850, "Portuguese_Brazil" }, + { 1251, 866, "Russian_Russia" }, + { 1250, 852, "Slovak_Slovakia" }, + { 1252, 850, "Spanish_Spain" }, + { 1252, 850, "Spanish_Mexico" }, + { 1252, 850, "Spanish_Spain" }, + { 1252, 850, "Swedish_Sweden" }, + { 1254, 857, "Turkish_Turkey" }, + { 0, 0, NULL} +}; + +/* + * Return OEM Code Page of current locale set by setlocale(). + */ +static unsigned +get_current_oemcp(void) +{ + int i; + char *locale, *p; + size_t len; + + locale = setlocale(LC_CTYPE, NULL); + if (locale == NULL) + return (GetOEMCP()); + if (locale[0] == 'C' && locale[1] == '\0') + return (CP_C_LOCALE); + + p = strrchr(locale, '.'); + if (p == NULL) + return (GetOEMCP()); + len = p - locale; + for (i = 0; acp_ocp_map[i].acp; i++) { + if (strncmp(acp_ocp_map[i].locale, locale, len) == 0) + return (acp_ocp_map[i].ocp); + } + return (GetOEMCP()); +} +#else + +/* + * POSIX platform does not use CodePage. + */ + +static unsigned +get_current_codepage(void) +{ + return (-1);/* Unknown */ +} +static unsigned +make_codepage_from_charset(const char *charset) +{ + (void)charset; /* UNUSED */ + return (-1);/* Unknown */ +} +static unsigned +get_current_oemcp(void) +{ + return (-1);/* Unknown */ +} + +#endif /* defined(_WIN32) && !defined(__CYGWIN__) */ + +/* + * Return a string conversion object. + */ +static struct archive_string_conv * +get_sconv_object(struct archive *a, const char *fc, const char *tc, int flag) +{ + struct archive_string_conv *sc; + unsigned current_codepage; + + /* Check if we have made the sconv object. */ + sc = find_sconv_object(a, fc, tc); + if (sc != NULL) + return (sc); + + if (a == NULL) + current_codepage = get_current_codepage(); + else + current_codepage = a->current_codepage; + + sc = create_sconv_object(canonical_charset_name(fc), + canonical_charset_name(tc), current_codepage, flag); + if (sc == NULL) { + if (a != NULL) + archive_set_error(a, ENOMEM, + "Could not allocate memory for " + "a string conversion object"); + return (NULL); + } + + /* + * If there is no converter for current string conversion object, + * we cannot handle this conversion. + */ + if (sc->nconverter == 0) { + if (a != NULL) { +#if HAVE_ICONV + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "iconv_open failed : Cannot handle ``%s''", + (flag & SCONV_TO_CHARSET)?tc:fc); +#else + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "A character-set conversion not fully supported " + "on this platform"); +#endif + } + /* Failed; free a sconv object. */ + free_sconv_object(sc); + return (NULL); + } + + /* + * Success! + */ + if (a != NULL) + add_sconv_object(a, sc); + return (sc); +} + +static const char * +get_current_charset(struct archive *a) +{ + const char *cur_charset; + + if (a == NULL) + cur_charset = default_iconv_charset(""); + else { + cur_charset = default_iconv_charset(a->current_code); + if (a->current_code == NULL) { + a->current_code = strdup(cur_charset); + a->current_codepage = get_current_codepage(); + a->current_oemcp = get_current_oemcp(); + } + } + return (cur_charset); +} + +/* + * Make and Return a string conversion object. + * Return NULL if the platform does not support the specified conversion + * and best_effort is 0. + * If best_effort is set, A string conversion object must be returned + * unless memory allocation for the object fails, but the conversion + * might fail when non-ASCII code is found. + */ +struct archive_string_conv * +archive_string_conversion_to_charset(struct archive *a, const char *charset, + int best_effort) +{ + int flag = SCONV_TO_CHARSET; + + if (best_effort) + flag |= SCONV_BEST_EFFORT; + return (get_sconv_object(a, get_current_charset(a), charset, flag)); +} + +struct archive_string_conv * +archive_string_conversion_from_charset(struct archive *a, const char *charset, + int best_effort) +{ + int flag = SCONV_FROM_CHARSET; + + if (best_effort) + flag |= SCONV_BEST_EFFORT; + return (get_sconv_object(a, charset, get_current_charset(a), flag)); +} + +/* + * archive_string_default_conversion_*_archive() are provided for Windows + * platform because other archiver application use CP_OEMCP for + * MultiByteToWideChar() and WideCharToMultiByte() for the filenames + * in tar or zip files. But mbstowcs/wcstombs(CRT) usually use CP_ACP + * unless you use setlocale(LC_ALL, ".OCP")(specify CP_OEMCP). + * So we should make a string conversion between CP_ACP and CP_OEMCP + * for compatibility. + */ +#if defined(_WIN32) && !defined(__CYGWIN__) +struct archive_string_conv * +archive_string_default_conversion_for_read(struct archive *a) +{ + const char *cur_charset = get_current_charset(a); + char oemcp[16]; + + /* NOTE: a check of cur_charset is unneeded but we need + * that get_current_charset() has been surely called at + * this time whatever C compiler optimized. */ + if (cur_charset != NULL && + (a->current_codepage == CP_C_LOCALE || + a->current_codepage == a->current_oemcp)) + return (NULL);/* no conversion. */ + + _snprintf(oemcp, sizeof(oemcp)-1, "CP%d", a->current_oemcp); + /* Make sure a null termination must be set. */ + oemcp[sizeof(oemcp)-1] = '\0'; + return (get_sconv_object(a, oemcp, cur_charset, + SCONV_FROM_CHARSET)); +} + +struct archive_string_conv * +archive_string_default_conversion_for_write(struct archive *a) +{ + const char *cur_charset = get_current_charset(a); + char oemcp[16]; + + /* NOTE: a check of cur_charset is unneeded but we need + * that get_current_charset() has been surely called at + * this time whatever C compiler optimized. */ + if (cur_charset != NULL && + (a->current_codepage == CP_C_LOCALE || + a->current_codepage == a->current_oemcp)) + return (NULL);/* no conversion. */ + + _snprintf(oemcp, sizeof(oemcp)-1, "CP%d", a->current_oemcp); + /* Make sure a null termination must be set. */ + oemcp[sizeof(oemcp)-1] = '\0'; + return (get_sconv_object(a, cur_charset, oemcp, + SCONV_TO_CHARSET)); +} +#else +struct archive_string_conv * +archive_string_default_conversion_for_read(struct archive *a) +{ + (void)a; /* UNUSED */ + return (NULL); +} + +struct archive_string_conv * +archive_string_default_conversion_for_write(struct archive *a) +{ + (void)a; /* UNUSED */ + return (NULL); +} +#endif + +/* + * Dispose of all character conversion objects in the archive object. + */ +void +archive_string_conversion_free(struct archive *a) +{ + struct archive_string_conv *sc; + struct archive_string_conv *sc_next; + + for (sc = a->sconv; sc != NULL; sc = sc_next) { + sc_next = sc->next; + free_sconv_object(sc); + } + a->sconv = NULL; + free(a->current_code); + a->current_code = NULL; +} + +/* + * Return a conversion charset name. + */ +const char * +archive_string_conversion_charset_name(struct archive_string_conv *sc) +{ + if (sc->flag & SCONV_TO_CHARSET) + return (sc->to_charset); + else + return (sc->from_charset); +} + +/* + * Change the behavior of a string conversion. + */ +void +archive_string_conversion_set_opt(struct archive_string_conv *sc, int opt) +{ + switch (opt) { + /* + * A filename in UTF-8 was made with libarchive 2.x in a wrong + * assumption that wchar_t was Unicode. + * This option enables simulating the assumption in order to read + * that filename correctly. + */ + case SCONV_SET_OPT_UTF8_LIBARCHIVE2X: +#if (defined(_WIN32) && !defined(__CYGWIN__)) \ + || defined(__STDC_ISO_10646__) || defined(__APPLE__) + /* + * Nothing to do for it since wchar_t on these platforms + * is really Unicode. + */ + (void)sc; /* UNUSED */ +#else + if ((sc->flag & SCONV_UTF8_LIBARCHIVE_2) == 0) { + sc->flag |= SCONV_UTF8_LIBARCHIVE_2; + /* Set up string converters. */ + setup_converter(sc); + } +#endif + break; + case SCONV_SET_OPT_NORMALIZATION_C: + if ((sc->flag & SCONV_NORMALIZATION_C) == 0) { + sc->flag |= SCONV_NORMALIZATION_C; + sc->flag &= ~SCONV_NORMALIZATION_D; + /* Set up string converters. */ + setup_converter(sc); + } + break; + case SCONV_SET_OPT_NORMALIZATION_D: +#if defined(HAVE_ICONV) + /* + * If iconv will take the string, do not change the + * setting of the normalization. + */ + if (!(sc->flag & SCONV_WIN_CP) && + (sc->flag & (SCONV_FROM_UTF16 | SCONV_FROM_UTF8)) && + !(sc->flag & (SCONV_TO_UTF16 | SCONV_TO_UTF8))) + break; +#endif + if ((sc->flag & SCONV_NORMALIZATION_D) == 0) { + sc->flag |= SCONV_NORMALIZATION_D; + sc->flag &= ~SCONV_NORMALIZATION_C; + /* Set up string converters. */ + setup_converter(sc); + } + break; + default: + break; + } +} + +/* + * + * Copy one archive_string to another in locale conversion. + * + * archive_strncat_l(); + * archive_strncpy_l(); + * + */ + +static size_t +mbsnbytes(const void *_p, size_t n) +{ + size_t s; + const char *p, *pp; + + if (_p == NULL) + return (0); + p = (const char *)_p; + + /* Like strlen(p), except won't examine positions beyond p[n]. */ + s = 0; + pp = p; + while (s < n && *pp) { + pp++; + s++; + } + return (s); +} + +static size_t +utf16nbytes(const void *_p, size_t n) +{ + size_t s; + const char *p, *pp; + + if (_p == NULL) + return (0); + p = (const char *)_p; + + /* Like strlen(p), except won't examine positions beyond p[n]. */ + s = 0; + pp = p; + n >>= 1; + while (s < n && (pp[0] || pp[1])) { + pp += 2; + s++; + } + return (s<<1); +} + +int +archive_strncpy_l(struct archive_string *as, const void *_p, size_t n, + struct archive_string_conv *sc) +{ + as->length = 0; + return (archive_strncat_l(as, _p, n, sc)); +} + +int +archive_strncat_l(struct archive_string *as, const void *_p, size_t n, + struct archive_string_conv *sc) +{ + const void *s; + size_t length = 0; + int i, r = 0, r2; + + if (_p != NULL && n > 0) { + if (sc != NULL && (sc->flag & SCONV_FROM_UTF16)) + length = utf16nbytes(_p, n); + else + length = mbsnbytes(_p, n); + } + + /* We must allocate memory even if there is no data for conversion + * or copy. This simulates archive_string_append behavior. */ + if (length == 0) { + int tn = 1; + if (sc != NULL && (sc->flag & SCONV_TO_UTF16)) + tn = 2; + if (archive_string_ensure(as, as->length + tn) == NULL) + return (-1); + as->s[as->length] = 0; + if (tn == 2) + as->s[as->length+1] = 0; + return (0); + } + + /* + * If sc is NULL, we just make a copy. + */ + if (sc == NULL) { + if (archive_string_append(as, _p, length) == NULL) + return (-1);/* No memory */ + return (0); + } + + s = _p; + i = 0; + if (sc->nconverter > 1) { + sc->utftmp.length = 0; + r2 = sc->converter[0](&(sc->utftmp), s, length, sc); + if (r2 != 0 && errno == ENOMEM) + return (r2); + if (r > r2) + r = r2; + s = sc->utftmp.s; + length = sc->utftmp.length; + ++i; + } + r2 = sc->converter[i](as, s, length, sc); + if (r > r2) + r = r2; + return (r); +} + +#if HAVE_ICONV + +/* + * Return -1 if conversion fails. + */ +static int +iconv_strncat_in_locale(struct archive_string *as, const void *_p, + size_t length, struct archive_string_conv *sc) +{ + ICONV_CONST char *itp; + size_t remaining; + iconv_t cd; + char *outp; + size_t avail, bs; + int return_value = 0; /* success */ + int to_size, from_size; + + if (sc->flag & SCONV_TO_UTF16) + to_size = 2; + else + to_size = 1; + if (sc->flag & SCONV_FROM_UTF16) + from_size = 2; + else + from_size = 1; + + if (archive_string_ensure(as, as->length + length*2+to_size) == NULL) + return (-1); + + cd = sc->cd; + itp = (char *)(uintptr_t)_p; + remaining = length; + outp = as->s + as->length; + avail = as->buffer_length - as->length - to_size; + while (remaining >= (size_t)from_size) { + size_t result = iconv(cd, &itp, &remaining, &outp, &avail); + + if (result != (size_t)-1) + break; /* Conversion completed. */ + + if (errno == EILSEQ || errno == EINVAL) { + /* + * If an output charset is UTF-8 or UTF-16BE/LE, + * unknown character should be U+FFFD + * (replacement character). + */ + if (sc->flag & (SCONV_TO_UTF8 | SCONV_TO_UTF16)) { + size_t rbytes; + if (sc->flag & SCONV_TO_UTF8) + rbytes = sizeof(utf8_replacement_char); + else + rbytes = 2; + + if (avail < rbytes) { + as->length = outp - as->s; + bs = as->buffer_length + + (remaining * to_size) + rbytes; + if (NULL == + archive_string_ensure(as, bs)) + return (-1); + outp = as->s + as->length; + avail = as->buffer_length + - as->length - to_size; + } + if (sc->flag & SCONV_TO_UTF8) + memcpy(outp, utf8_replacement_char, sizeof(utf8_replacement_char)); + else if (sc->flag & SCONV_TO_UTF16BE) + archive_be16enc(outp, UNICODE_R_CHAR); + else + archive_le16enc(outp, UNICODE_R_CHAR); + outp += rbytes; + avail -= rbytes; + } else { + /* Skip the illegal input bytes. */ + *outp++ = '?'; + avail--; + } + itp += from_size; + remaining -= from_size; + return_value = -1; /* failure */ + } else { + /* E2BIG no output buffer, + * Increase an output buffer. */ + as->length = outp - as->s; + bs = as->buffer_length + remaining * 2; + if (NULL == archive_string_ensure(as, bs)) + return (-1); + outp = as->s + as->length; + avail = as->buffer_length - as->length - to_size; + } + } + as->length = outp - as->s; + as->s[as->length] = 0; + if (to_size == 2) + as->s[as->length+1] = 0; + return (return_value); +} + +#endif /* HAVE_ICONV */ + + +#if defined(_WIN32) && !defined(__CYGWIN__) + +/* + * Translate a string from a some CodePage to an another CodePage by + * Windows APIs, and copy the result. Return -1 if conversion fails. + */ +static int +strncat_in_codepage(struct archive_string *as, + const void *_p, size_t length, struct archive_string_conv *sc) +{ + const char *s = (const char *)_p; + struct archive_wstring aws; + size_t l; + int r, saved_flag; + + archive_string_init(&aws); + saved_flag = sc->flag; + sc->flag &= ~(SCONV_NORMALIZATION_D | SCONV_NORMALIZATION_C); + r = archive_wstring_append_from_mbs_in_codepage(&aws, s, length, sc); + sc->flag = saved_flag; + if (r != 0) { + archive_wstring_free(&aws); + if (errno != ENOMEM) + archive_string_append(as, s, length); + return (-1); + } + + l = as->length; + r = archive_string_append_from_wcs_in_codepage( + as, aws.s, aws.length, sc); + if (r != 0 && errno != ENOMEM && l == as->length) + archive_string_append(as, s, length); + archive_wstring_free(&aws); + return (r); +} + +/* + * Test whether MBS ==> WCS is okay. + */ +static int +invalid_mbs(const void *_p, size_t n, struct archive_string_conv *sc) +{ + const char *p = (const char *)_p; + unsigned codepage; + DWORD mbflag = MB_ERR_INVALID_CHARS; + + if (sc->flag & SCONV_FROM_CHARSET) + codepage = sc->to_cp; + else + codepage = sc->from_cp; + + if (codepage == CP_C_LOCALE) + return (0); + if (codepage != CP_UTF8) + mbflag |= MB_PRECOMPOSED; + + if (MultiByteToWideChar(codepage, mbflag, p, (int)n, NULL, 0) == 0) + return (-1); /* Invalid */ + return (0); /* Okay */ +} + +#else + +/* + * Test whether MBS ==> WCS is okay. + */ +static int +invalid_mbs(const void *_p, size_t n, struct archive_string_conv *sc) +{ + const char *p = (const char *)_p; + size_t r; + +#if HAVE_MBRTOWC + mbstate_t shift_state; + + memset(&shift_state, 0, sizeof(shift_state)); +#else + /* Clear the shift state before starting. */ + mbtowc(NULL, NULL, 0); +#endif + while (n) { + wchar_t wc; + +#if HAVE_MBRTOWC + r = mbrtowc(&wc, p, n, &shift_state); +#else + r = mbtowc(&wc, p, n); +#endif + if (r == (size_t)-1 || r == (size_t)-2) + return (-1);/* Invalid. */ + if (r == 0) + break; + p += r; + n -= r; + } + (void)sc; /* UNUSED */ + return (0); /* All Okey. */ +} + +#endif /* defined(_WIN32) && !defined(__CYGWIN__) */ + +/* + * Basically returns -1 because we cannot make a conversion of charset + * without iconv but in some cases this would return 0. + * Returns 0 if all copied characters are ASCII. + * Returns 0 if both from-locale and to-locale are the same and those + * can be WCS with no error. + */ +static int +best_effort_strncat_in_locale(struct archive_string *as, const void *_p, + size_t length, struct archive_string_conv *sc) +{ + size_t remaining; + const uint8_t *itp; + int return_value = 0; /* success */ + + /* + * If both from-locale and to-locale is the same, this makes a copy. + * And then this checks all copied MBS can be WCS if so returns 0. + */ + if (sc->same) { + if (archive_string_append(as, _p, length) == NULL) + return (-1);/* No memory */ + return (invalid_mbs(_p, length, sc)); + } + + /* + * If a character is ASCII, this just copies it. If not, this + * assigns '?' character instead but in UTF-8 locale this assigns + * byte sequence 0xEF 0xBD 0xBD, which are code point U+FFFD, + * a Replacement Character in Unicode. + */ + + remaining = length; + itp = (const uint8_t *)_p; + while (*itp && remaining > 0) { + if (*itp > 127) { + // Non-ASCII: Substitute with suitable replacement + if (sc->flag & SCONV_TO_UTF8) { + if (archive_string_append(as, utf8_replacement_char, sizeof(utf8_replacement_char)) == NULL) { + __archive_errx(1, "Out of memory"); + } + } else { + archive_strappend_char(as, '?'); + } + return_value = -1; + } else { + archive_strappend_char(as, *itp); + } + ++itp; + } + return (return_value); +} + + +/* + * Unicode conversion functions. + * - UTF-8 <===> UTF-8 in removing surrogate pairs. + * - UTF-8 NFD ===> UTF-8 NFC in removing surrogate pairs. + * - UTF-8 made by libarchive 2.x ===> UTF-8. + * - UTF-16BE <===> UTF-8. + * + */ + +/* + * Utility to convert a single UTF-8 sequence. + * + * Usually return used bytes, return used byte in negative value when + * a unicode character is replaced with U+FFFD. + * See also http://unicode.org/review/pr-121.html Public Review Issue #121 + * Recommended Practice for Replacement Characters. + */ +static int +_utf8_to_unicode(uint32_t *pwc, const char *s, size_t n) +{ + static const char utf8_count[256] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 00 - 0F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 10 - 1F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20 - 2F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 30 - 3F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40 - 4F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 50 - 5F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 60 - 6F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 70 - 7F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 80 - 8F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 90 - 9F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* A0 - AF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* B0 - BF */ + 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,/* C0 - CF */ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,/* D0 - DF */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,/* E0 - EF */ + 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* F0 - FF */ + }; + int ch, i; + int cnt; + uint32_t wc; + + /* Sanity check. */ + if (n == 0) + return (0); + /* + * Decode 1-4 bytes depending on the value of the first byte. + */ + ch = (unsigned char)*s; + if (ch == 0) + return (0); /* Standard: return 0 for end-of-string. */ + cnt = utf8_count[ch]; + + /* Invalid sequence or there are not plenty bytes. */ + if ((int)n < cnt) { + cnt = (int)n; + for (i = 1; i < cnt; i++) { + if ((s[i] & 0xc0) != 0x80) { + cnt = i; + break; + } + } + goto invalid_sequence; + } + + /* Make a Unicode code point from a single UTF-8 sequence. */ + switch (cnt) { + case 1: /* 1 byte sequence. */ + *pwc = ch & 0x7f; + return (cnt); + case 2: /* 2 bytes sequence. */ + if ((s[1] & 0xc0) != 0x80) { + cnt = 1; + goto invalid_sequence; + } + *pwc = ((ch & 0x1f) << 6) | (s[1] & 0x3f); + return (cnt); + case 3: /* 3 bytes sequence. */ + if ((s[1] & 0xc0) != 0x80) { + cnt = 1; + goto invalid_sequence; + } + if ((s[2] & 0xc0) != 0x80) { + cnt = 2; + goto invalid_sequence; + } + wc = ((ch & 0x0f) << 12) + | ((s[1] & 0x3f) << 6) + | (s[2] & 0x3f); + if (wc < 0x800) + goto invalid_sequence;/* Overlong sequence. */ + break; + case 4: /* 4 bytes sequence. */ + if ((s[1] & 0xc0) != 0x80) { + cnt = 1; + goto invalid_sequence; + } + if ((s[2] & 0xc0) != 0x80) { + cnt = 2; + goto invalid_sequence; + } + if ((s[3] & 0xc0) != 0x80) { + cnt = 3; + goto invalid_sequence; + } + wc = ((ch & 0x07) << 18) + | ((s[1] & 0x3f) << 12) + | ((s[2] & 0x3f) << 6) + | (s[3] & 0x3f); + if (wc < 0x10000) + goto invalid_sequence;/* Overlong sequence. */ + break; + default: /* Others are all invalid sequence. */ + if (ch == 0xc0 || ch == 0xc1) + cnt = 2; + else if (ch >= 0xf5 && ch <= 0xf7) + cnt = 4; + else if (ch >= 0xf8 && ch <= 0xfb) + cnt = 5; + else if (ch == 0xfc || ch == 0xfd) + cnt = 6; + else + cnt = 1; + if ((int)n < cnt) + cnt = (int)n; + for (i = 1; i < cnt; i++) { + if ((s[i] & 0xc0) != 0x80) { + cnt = i; + break; + } + } + goto invalid_sequence; + } + + /* The code point larger than 0x10FFFF is not legal + * Unicode values. */ + if (wc > UNICODE_MAX) + goto invalid_sequence; + /* Correctly gets a Unicode, returns used bytes. */ + *pwc = wc; + return (cnt); +invalid_sequence: + *pwc = UNICODE_R_CHAR;/* set the Replacement Character instead. */ + return (cnt * -1); +} + +static int +utf8_to_unicode(uint32_t *pwc, const char *s, size_t n) +{ + int cnt; + + cnt = _utf8_to_unicode(pwc, s, n); + /* Any of Surrogate pair is not legal Unicode values. */ + if (cnt == 3 && IS_SURROGATE_PAIR_LA(*pwc)) + return (-3); + return (cnt); +} + +static inline uint32_t +combine_surrogate_pair(uint32_t uc, uint32_t uc2) +{ + uc -= 0xD800; + uc *= 0x400; + uc += uc2 - 0xDC00; + uc += 0x10000; + return (uc); +} + +/* + * Convert a single UTF-8/CESU-8 sequence to a Unicode code point in + * removing surrogate pairs. + * + * CESU-8: The Compatibility Encoding Scheme for UTF-16. + * + * Usually return used bytes, return used byte in negative value when + * a unicode character is replaced with U+FFFD. + */ +static int +cesu8_to_unicode(uint32_t *pwc, const char *s, size_t n) +{ + uint32_t wc = 0; + int cnt; + + cnt = _utf8_to_unicode(&wc, s, n); + if (cnt == 3 && IS_HIGH_SURROGATE_LA(wc)) { + uint32_t wc2 = 0; + if (n - 3 < 3) { + /* Invalid byte sequence. */ + goto invalid_sequence; + } + cnt = _utf8_to_unicode(&wc2, s+3, n-3); + if (cnt != 3 || !IS_LOW_SURROGATE_LA(wc2)) { + /* Invalid byte sequence. */ + goto invalid_sequence; + } + wc = combine_surrogate_pair(wc, wc2); + cnt = 6; + } else if (cnt == 3 && IS_LOW_SURROGATE_LA(wc)) { + /* Invalid byte sequence. */ + goto invalid_sequence; + } + *pwc = wc; + return (cnt); +invalid_sequence: + *pwc = UNICODE_R_CHAR;/* set the Replacement Character instead. */ + if (cnt > 0) + cnt *= -1; + return (cnt); +} + +/* + * Convert a Unicode code point to a single UTF-8 sequence. + * + * NOTE:This function does not check if the Unicode is legal or not. + * Please you definitely check it before calling this. + */ +static size_t +unicode_to_utf8(char *p, size_t remaining, uint32_t uc) +{ + char *_p = p; + + /* Invalid Unicode char maps to Replacement character */ + if (uc > UNICODE_MAX) + uc = UNICODE_R_CHAR; + /* Translate code point to UTF8 */ + if (uc <= 0x7f) { + if (remaining == 0) + return (0); + *p++ = (char)uc; + } else if (uc <= 0x7ff) { + if (remaining < 2) + return (0); + *p++ = 0xc0 | ((uc >> 6) & 0x1f); + *p++ = 0x80 | (uc & 0x3f); + } else if (uc <= 0xffff) { + if (remaining < 3) + return (0); + *p++ = 0xe0 | ((uc >> 12) & 0x0f); + *p++ = 0x80 | ((uc >> 6) & 0x3f); + *p++ = 0x80 | (uc & 0x3f); + } else { + if (remaining < 4) + return (0); + *p++ = 0xf0 | ((uc >> 18) & 0x07); + *p++ = 0x80 | ((uc >> 12) & 0x3f); + *p++ = 0x80 | ((uc >> 6) & 0x3f); + *p++ = 0x80 | (uc & 0x3f); + } + return (p - _p); +} + +static int +utf16be_to_unicode(uint32_t *pwc, const char *s, size_t n) +{ + return (utf16_to_unicode(pwc, s, n, 1)); +} + +static int +utf16le_to_unicode(uint32_t *pwc, const char *s, size_t n) +{ + return (utf16_to_unicode(pwc, s, n, 0)); +} + +static int +utf16_to_unicode(uint32_t *pwc, const char *s, size_t n, int be) +{ + const char *utf16 = s; + unsigned uc; + + if (n == 0) + return (0); + if (n == 1) { + /* set the Replacement Character instead. */ + *pwc = UNICODE_R_CHAR; + return (-1); + } + + if (be) + uc = archive_be16dec(utf16); + else + uc = archive_le16dec(utf16); + utf16 += 2; + + /* If this is a surrogate pair, assemble the full code point.*/ + if (IS_HIGH_SURROGATE_LA(uc)) { + unsigned uc2; + + if (n >= 4) { + if (be) + uc2 = archive_be16dec(utf16); + else + uc2 = archive_le16dec(utf16); + } else + uc2 = 0; + if (IS_LOW_SURROGATE_LA(uc2)) { + uc = combine_surrogate_pair(uc, uc2); + utf16 += 2; + } else { + /* Undescribed code point should be U+FFFD + * (replacement character). */ + *pwc = UNICODE_R_CHAR; + return (-2); + } + } + + /* + * Surrogate pair values(0xd800 through 0xdfff) are only + * used by UTF-16, so, after above calculation, the code + * must not be surrogate values, and Unicode has no codes + * larger than 0x10ffff. Thus, those are not legal Unicode + * values. + */ + if (IS_SURROGATE_PAIR_LA(uc) || uc > UNICODE_MAX) { + /* Undescribed code point should be U+FFFD + * (replacement character). */ + *pwc = UNICODE_R_CHAR; + return (((int)(utf16 - s)) * -1); + } + *pwc = uc; + return ((int)(utf16 - s)); +} + +static size_t +unicode_to_utf16be(char *p, size_t remaining, uint32_t uc) +{ + char *utf16 = p; + + if (uc > 0xffff) { + /* We have a code point that won't fit into a + * wchar_t; convert it to a surrogate pair. */ + if (remaining < 4) + return (0); + uc -= 0x10000; + archive_be16enc(utf16, ((uc >> 10) & 0x3ff) + 0xD800); + archive_be16enc(utf16+2, (uc & 0x3ff) + 0xDC00); + return (4); + } else { + if (remaining < 2) + return (0); + archive_be16enc(utf16, uc); + return (2); + } +} + +static size_t +unicode_to_utf16le(char *p, size_t remaining, uint32_t uc) +{ + char *utf16 = p; + + if (uc > 0xffff) { + /* We have a code point that won't fit into a + * wchar_t; convert it to a surrogate pair. */ + if (remaining < 4) + return (0); + uc -= 0x10000; + archive_le16enc(utf16, ((uc >> 10) & 0x3ff) + 0xD800); + archive_le16enc(utf16+2, (uc & 0x3ff) + 0xDC00); + return (4); + } else { + if (remaining < 2) + return (0); + archive_le16enc(utf16, uc); + return (2); + } +} + +/* + * Copy UTF-8 string in checking surrogate pair. + * If any surrogate pair are found, it would be canonicalized. + */ +static int +strncat_from_utf8_to_utf8(struct archive_string *as, const void *_p, + size_t len, struct archive_string_conv *sc) +{ + const char *s; + char *p, *endp; + int n, ret = 0; + + (void)sc; /* UNUSED */ + + if (archive_string_ensure(as, as->length + len + 1) == NULL) + return (-1); + + s = (const char *)_p; + p = as->s + as->length; + endp = as->s + as->buffer_length -1; + do { + uint32_t uc; + const char *ss = s; + size_t w; + + /* + * Forward byte sequence until a conversion of that is needed. + */ + while ((n = utf8_to_unicode(&uc, s, len)) > 0) { + s += n; + len -= n; + } + if (ss < s) { + if (p + (s - ss) > endp) { + as->length = p - as->s; + if (archive_string_ensure(as, + as->buffer_length + len + 1) == NULL) + return (-1); + p = as->s + as->length; + endp = as->s + as->buffer_length -1; + } + + memcpy(p, ss, s - ss); + p += s - ss; + } + + /* + * If n is negative, current byte sequence needs a replacement. + */ + if (n < 0) { + if (n == -3 && IS_SURROGATE_PAIR_LA(uc)) { + /* Current byte sequence may be CESU-8. */ + n = cesu8_to_unicode(&uc, s, len); + } + if (n < 0) { + ret = -1; + n *= -1;/* Use a replaced unicode character. */ + } + + /* Rebuild UTF-8 byte sequence. */ + while ((w = unicode_to_utf8(p, endp - p, uc)) == 0) { + as->length = p - as->s; + if (archive_string_ensure(as, + as->buffer_length + len + 1) == NULL) + return (-1); + p = as->s + as->length; + endp = as->s + as->buffer_length -1; + } + p += w; + s += n; + len -= n; + } + } while (n > 0); + as->length = p - as->s; + as->s[as->length] = '\0'; + return (ret); +} + +static int +archive_string_append_unicode(struct archive_string *as, const void *_p, + size_t len, struct archive_string_conv *sc) +{ + const char *s; + char *p, *endp; + uint32_t uc; + size_t w; + int n, ret = 0, ts, tm; + int (*parse)(uint32_t *, const char *, size_t); + size_t (*unparse)(char *, size_t, uint32_t); + + if (sc->flag & SCONV_TO_UTF16BE) { + unparse = unicode_to_utf16be; + ts = 2; + } else if (sc->flag & SCONV_TO_UTF16LE) { + unparse = unicode_to_utf16le; + ts = 2; + } else if (sc->flag & SCONV_TO_UTF8) { + unparse = unicode_to_utf8; + ts = 1; + } else { + /* + * This case is going to be converted to another + * character-set through iconv. + */ + if (sc->flag & SCONV_FROM_UTF16BE) { + unparse = unicode_to_utf16be; + ts = 2; + } else if (sc->flag & SCONV_FROM_UTF16LE) { + unparse = unicode_to_utf16le; + ts = 2; + } else { + unparse = unicode_to_utf8; + ts = 1; + } + } + + if (sc->flag & SCONV_FROM_UTF16BE) { + parse = utf16be_to_unicode; + tm = 1; + } else if (sc->flag & SCONV_FROM_UTF16LE) { + parse = utf16le_to_unicode; + tm = 1; + } else { + parse = cesu8_to_unicode; + tm = ts; + } + + if (archive_string_ensure(as, as->length + len * tm + ts) == NULL) + return (-1); + + s = (const char *)_p; + p = as->s + as->length; + endp = as->s + as->buffer_length - ts; + while ((n = parse(&uc, s, len)) != 0) { + if (n < 0) { + /* Use a replaced unicode character. */ + n *= -1; + ret = -1; + } + s += n; + len -= n; + while ((w = unparse(p, endp - p, uc)) == 0) { + /* There is not enough output buffer so + * we have to expand it. */ + as->length = p - as->s; + if (archive_string_ensure(as, + as->buffer_length + len * tm + ts) == NULL) + return (-1); + p = as->s + as->length; + endp = as->s + as->buffer_length - ts; + } + p += w; + } + as->length = p - as->s; + as->s[as->length] = '\0'; + if (ts == 2) + as->s[as->length+1] = '\0'; + return (ret); +} + +/* + * Following Constants for Hangul compositions this information comes from + * Unicode Standard Annex #15 http://unicode.org/reports/tr15/ + */ +#define HC_SBASE 0xAC00 +#define HC_LBASE 0x1100 +#define HC_VBASE 0x1161 +#define HC_TBASE 0x11A7 +#define HC_LCOUNT 19 +#define HC_VCOUNT 21 +#define HC_TCOUNT 28 +#define HC_NCOUNT (HC_VCOUNT * HC_TCOUNT) +#define HC_SCOUNT (HC_LCOUNT * HC_NCOUNT) + +static uint32_t +get_nfc(uint32_t uc, uint32_t uc2) +{ + int t, b; + + t = 0; + b = sizeof(u_composition_table)/sizeof(u_composition_table[0]) -1; + while (b >= t) { + int m = (t + b) / 2; + if (u_composition_table[m].cp1 < uc) + t = m + 1; + else if (u_composition_table[m].cp1 > uc) + b = m - 1; + else if (u_composition_table[m].cp2 < uc2) + t = m + 1; + else if (u_composition_table[m].cp2 > uc2) + b = m - 1; + else + return (u_composition_table[m].nfc); + } + return (0); +} + +#define FDC_MAX 10 /* The maximum number of Following Decomposable + * Characters. */ + +/* + * Update first code point. + */ +#define UPDATE_UC(new_uc) do { \ + uc = new_uc; \ + ucptr = NULL; \ +} while (0) + +/* + * Replace first code point with second code point. + */ +#define REPLACE_UC_WITH_UC2() do { \ + uc = uc2; \ + ucptr = uc2ptr; \ + n = n2; \ +} while (0) + +#define EXPAND_BUFFER() do { \ + as->length = p - as->s; \ + if (archive_string_ensure(as, \ + as->buffer_length + len * tm + ts) == NULL)\ + return (-1); \ + p = as->s + as->length; \ + endp = as->s + as->buffer_length - ts; \ +} while (0) + +#define UNPARSE(p, endp, uc) do { \ + while ((w = unparse(p, (endp) - (p), uc)) == 0) {\ + EXPAND_BUFFER(); \ + } \ + p += w; \ +} while (0) + +/* + * Write first code point. + * If the code point has not be changed from its original code, + * this just copies it from its original buffer pointer. + * If not, this converts it to UTF-8 byte sequence and copies it. + */ +#define WRITE_UC() do { \ + if (ucptr) { \ + if (p + n > endp) \ + EXPAND_BUFFER(); \ + switch (n) { \ + case 4: \ + *p++ = *ucptr++; \ + /* FALL THROUGH */ \ + case 3: \ + *p++ = *ucptr++; \ + /* FALL THROUGH */ \ + case 2: \ + *p++ = *ucptr++; \ + /* FALL THROUGH */ \ + case 1: \ + *p++ = *ucptr; \ + break; \ + } \ + ucptr = NULL; \ + } else { \ + UNPARSE(p, endp, uc); \ + } \ +} while (0) + +/* + * Collect following decomposable code points. + */ +#define COLLECT_CPS(start) do { \ + int _i; \ + for (_i = start; _i < FDC_MAX ; _i++) { \ + nx = parse(&ucx[_i], s, len); \ + if (nx <= 0) \ + break; \ + cx = CCC(ucx[_i]); \ + if (cl >= cx && cl != 228 && cx != 228)\ + break; \ + s += nx; \ + len -= nx; \ + cl = cx; \ + ccx[_i] = cx; \ + } \ + if (_i >= FDC_MAX) { \ + ret = -1; \ + ucx_size = FDC_MAX; \ + } else \ + ucx_size = _i; \ +} while (0) + +/* + * Normalize UTF-8/UTF-16BE characters to Form C and copy the result. + * + * TODO: Convert composition exclusions, which are never converted + * from NFC,NFD,NFKC and NFKD, to Form C. + */ +static int +archive_string_normalize_C(struct archive_string *as, const void *_p, + size_t len, struct archive_string_conv *sc) +{ + const char *s = (const char *)_p; + char *p, *endp; + uint32_t uc, uc2; + size_t w; + int always_replace, n, n2, ret = 0, spair, ts, tm; + int (*parse)(uint32_t *, const char *, size_t); + size_t (*unparse)(char *, size_t, uint32_t); + + always_replace = 1; + ts = 1;/* text size. */ + if (sc->flag & SCONV_TO_UTF16BE) { + unparse = unicode_to_utf16be; + ts = 2; + if (sc->flag & SCONV_FROM_UTF16BE) + always_replace = 0; + } else if (sc->flag & SCONV_TO_UTF16LE) { + unparse = unicode_to_utf16le; + ts = 2; + if (sc->flag & SCONV_FROM_UTF16LE) + always_replace = 0; + } else if (sc->flag & SCONV_TO_UTF8) { + unparse = unicode_to_utf8; + if (sc->flag & SCONV_FROM_UTF8) + always_replace = 0; + } else { + /* + * This case is going to be converted to another + * character-set through iconv. + */ + always_replace = 0; + if (sc->flag & SCONV_FROM_UTF16BE) { + unparse = unicode_to_utf16be; + ts = 2; + } else if (sc->flag & SCONV_FROM_UTF16LE) { + unparse = unicode_to_utf16le; + ts = 2; + } else { + unparse = unicode_to_utf8; + } + } + + if (sc->flag & SCONV_FROM_UTF16BE) { + parse = utf16be_to_unicode; + tm = 1; + spair = 4;/* surrogate pair size in UTF-16. */ + } else if (sc->flag & SCONV_FROM_UTF16LE) { + parse = utf16le_to_unicode; + tm = 1; + spair = 4;/* surrogate pair size in UTF-16. */ + } else { + parse = cesu8_to_unicode; + tm = ts; + spair = 6;/* surrogate pair size in UTF-8. */ + } + + if (archive_string_ensure(as, as->length + len * tm + ts) == NULL) + return (-1); + + p = as->s + as->length; + endp = as->s + as->buffer_length - ts; + while ((n = parse(&uc, s, len)) != 0) { + const char *ucptr, *uc2ptr; + + if (n < 0) { + /* Use a replaced unicode character. */ + UNPARSE(p, endp, uc); + s += n*-1; + len -= n*-1; + ret = -1; + continue; + } else if (n == spair || always_replace) + /* uc is converted from a surrogate pair. + * this should be treated as a changed code. */ + ucptr = NULL; + else + ucptr = s; + s += n; + len -= n; + + /* Read second code point. */ + while ((n2 = parse(&uc2, s, len)) > 0) { + uint32_t ucx[FDC_MAX]; + int ccx[FDC_MAX]; + int cl, cx, i, nx, ucx_size; + int LIndex,SIndex; + uint32_t nfc; + + if (n2 == spair || always_replace) + /* uc2 is converted from a surrogate pair. + * this should be treated as a changed code. */ + uc2ptr = NULL; + else + uc2ptr = s; + s += n2; + len -= n2; + + /* + * If current second code point is out of decomposable + * code points, finding compositions is unneeded. + */ + if (!IS_DECOMPOSABLE_BLOCK(uc2)) { + WRITE_UC(); + REPLACE_UC_WITH_UC2(); + continue; + } + + /* + * Try to combine current code points. + */ + /* + * We have to combine Hangul characters according to + * http://uniicode.org/reports/tr15/#Hangul + */ + if (0 <= (LIndex = uc - HC_LBASE) && + LIndex < HC_LCOUNT) { + /* + * Hangul Composition. + * 1. Two current code points are L and V. + */ + int VIndex = uc2 - HC_VBASE; + if (0 <= VIndex && VIndex < HC_VCOUNT) { + /* Make syllable of form LV. */ + UPDATE_UC(HC_SBASE + + (LIndex * HC_VCOUNT + VIndex) * + HC_TCOUNT); + } else { + WRITE_UC(); + REPLACE_UC_WITH_UC2(); + } + continue; + } else if (0 <= (SIndex = uc - HC_SBASE) && + SIndex < HC_SCOUNT && (SIndex % HC_TCOUNT) == 0) { + /* + * Hangul Composition. + * 2. Two current code points are LV and T. + */ + int TIndex = uc2 - HC_TBASE; + if (0 < TIndex && TIndex < HC_TCOUNT) { + /* Make syllable of form LVT. */ + UPDATE_UC(uc + TIndex); + } else { + WRITE_UC(); + REPLACE_UC_WITH_UC2(); + } + continue; + } else if ((nfc = get_nfc(uc, uc2)) != 0) { + /* A composition to current code points + * is found. */ + UPDATE_UC(nfc); + continue; + } else if ((cl = CCC(uc2)) == 0) { + /* Clearly 'uc2' the second code point is not + * a decomposable code. */ + WRITE_UC(); + REPLACE_UC_WITH_UC2(); + continue; + } + + /* + * Collect following decomposable code points. + */ + cx = 0; + ucx[0] = uc2; + ccx[0] = cl; + COLLECT_CPS(1); + + /* + * Find a composed code in the collected code points. + */ + i = 1; + while (i < ucx_size) { + int j; + + if ((nfc = get_nfc(uc, ucx[i])) == 0) { + i++; + continue; + } + + /* + * nfc is composed of uc and ucx[i]. + */ + UPDATE_UC(nfc); + + /* + * Remove ucx[i] by shifting + * following code points. + */ + for (j = i; j+1 < ucx_size; j++) { + ucx[j] = ucx[j+1]; + ccx[j] = ccx[j+1]; + } + ucx_size --; + + /* + * Collect following code points blocked + * by ucx[i] the removed code point. + */ + if (ucx_size > 0 && i == ucx_size && + nx > 0 && cx == cl) { + cl = ccx[ucx_size-1]; + COLLECT_CPS(ucx_size); + } + /* + * Restart finding a composed code with + * the updated uc from the top of the + * collected code points. + */ + i = 0; + } + + /* + * Apparently the current code points are not + * decomposed characters or already composed. + */ + WRITE_UC(); + for (i = 0; i < ucx_size; i++) + UNPARSE(p, endp, ucx[i]); + + /* + * Flush out remaining canonical combining characters. + */ + if (nx > 0 && cx == cl && len > 0) { + while ((nx = parse(&ucx[0], s, len)) + > 0) { + cx = CCC(ucx[0]); + if (cl > cx) + break; + s += nx; + len -= nx; + cl = cx; + UNPARSE(p, endp, ucx[0]); + } + } + break; + } + if (n2 < 0) { + WRITE_UC(); + /* Use a replaced unicode character. */ + UNPARSE(p, endp, uc2); + s += n2*-1; + len -= n2*-1; + ret = -1; + continue; + } else if (n2 == 0) { + WRITE_UC(); + break; + } + } + as->length = p - as->s; + as->s[as->length] = '\0'; + if (ts == 2) + as->s[as->length+1] = '\0'; + return (ret); +} + +static int +get_nfd(uint32_t *cp1, uint32_t *cp2, uint32_t uc) +{ + int t, b; + + /* + * These are not converted to NFD on Mac OS. + */ + if ((uc >= 0x2000 && uc <= 0x2FFF) || + (uc >= 0xF900 && uc <= 0xFAFF) || + (uc >= 0x2F800 && uc <= 0x2FAFF)) + return (0); + /* + * Those code points are not converted to NFD on Mac OS. + * I do not know the reason because it is undocumented. + * NFC NFD + * 1109A ==> 11099 110BA + * 1109C ==> 1109B 110BA + * 110AB ==> 110A5 110BA + */ + if (uc == 0x1109A || uc == 0x1109C || uc == 0x110AB) + return (0); + + t = 0; + b = sizeof(u_decomposition_table)/sizeof(u_decomposition_table[0]) -1; + while (b >= t) { + int m = (t + b) / 2; + if (u_decomposition_table[m].nfc < uc) + t = m + 1; + else if (u_decomposition_table[m].nfc > uc) + b = m - 1; + else { + *cp1 = u_decomposition_table[m].cp1; + *cp2 = u_decomposition_table[m].cp2; + return (1); + } + } + return (0); +} + +#define REPLACE_UC_WITH(cp) do { \ + uc = cp; \ + ucptr = NULL; \ +} while (0) + +/* + * Normalize UTF-8 characters to Form D and copy the result. + */ +static int +archive_string_normalize_D(struct archive_string *as, const void *_p, + size_t len, struct archive_string_conv *sc) +{ + const char *s = (const char *)_p; + char *p, *endp; + uint32_t uc, uc2; + size_t w; + int always_replace, n, n2, ret = 0, spair, ts, tm; + int (*parse)(uint32_t *, const char *, size_t); + size_t (*unparse)(char *, size_t, uint32_t); + + always_replace = 1; + ts = 1;/* text size. */ + if (sc->flag & SCONV_TO_UTF16BE) { + unparse = unicode_to_utf16be; + ts = 2; + if (sc->flag & SCONV_FROM_UTF16BE) + always_replace = 0; + } else if (sc->flag & SCONV_TO_UTF16LE) { + unparse = unicode_to_utf16le; + ts = 2; + if (sc->flag & SCONV_FROM_UTF16LE) + always_replace = 0; + } else if (sc->flag & SCONV_TO_UTF8) { + unparse = unicode_to_utf8; + if (sc->flag & SCONV_FROM_UTF8) + always_replace = 0; + } else { + /* + * This case is going to be converted to another + * character-set through iconv. + */ + always_replace = 0; + if (sc->flag & SCONV_FROM_UTF16BE) { + unparse = unicode_to_utf16be; + ts = 2; + } else if (sc->flag & SCONV_FROM_UTF16LE) { + unparse = unicode_to_utf16le; + ts = 2; + } else { + unparse = unicode_to_utf8; + } + } + + if (sc->flag & SCONV_FROM_UTF16BE) { + parse = utf16be_to_unicode; + tm = 1; + spair = 4;/* surrogate pair size in UTF-16. */ + } else if (sc->flag & SCONV_FROM_UTF16LE) { + parse = utf16le_to_unicode; + tm = 1; + spair = 4;/* surrogate pair size in UTF-16. */ + } else { + parse = cesu8_to_unicode; + tm = ts; + spair = 6;/* surrogate pair size in UTF-8. */ + } + + if (archive_string_ensure(as, as->length + len * tm + ts) == NULL) + return (-1); + + p = as->s + as->length; + endp = as->s + as->buffer_length - ts; + while ((n = parse(&uc, s, len)) != 0) { + const char *ucptr; + uint32_t cp1, cp2; + int SIndex; + struct { + uint32_t uc; + int ccc; + } fdc[FDC_MAX]; + int fdi, fdj; + int ccc; + +check_first_code: + if (n < 0) { + /* Use a replaced unicode character. */ + UNPARSE(p, endp, uc); + s += n*-1; + len -= n*-1; + ret = -1; + continue; + } else if (n == spair || always_replace) + /* uc is converted from a surrogate pair. + * this should be treated as a changed code. */ + ucptr = NULL; + else + ucptr = s; + s += n; + len -= n; + + /* Hangul Decomposition. */ + if ((SIndex = uc - HC_SBASE) >= 0 && SIndex < HC_SCOUNT) { + int L = HC_LBASE + SIndex / HC_NCOUNT; + int V = HC_VBASE + (SIndex % HC_NCOUNT) / HC_TCOUNT; + int T = HC_TBASE + SIndex % HC_TCOUNT; + + REPLACE_UC_WITH(L); + WRITE_UC(); + REPLACE_UC_WITH(V); + WRITE_UC(); + if (T != HC_TBASE) { + REPLACE_UC_WITH(T); + WRITE_UC(); + } + continue; + } + if (IS_DECOMPOSABLE_BLOCK(uc) && CCC(uc) != 0) { + WRITE_UC(); + continue; + } + + fdi = 0; + while (get_nfd(&cp1, &cp2, uc) && fdi < FDC_MAX) { + int k; + + for (k = fdi; k > 0; k--) + fdc[k] = fdc[k-1]; + fdc[0].ccc = CCC(cp2); + fdc[0].uc = cp2; + fdi++; + REPLACE_UC_WITH(cp1); + } + + /* Read following code points. */ + while ((n2 = parse(&uc2, s, len)) > 0 && + (ccc = CCC(uc2)) != 0 && fdi < FDC_MAX) { + int j, k; + + s += n2; + len -= n2; + for (j = 0; j < fdi; j++) { + if (fdc[j].ccc > ccc) + break; + } + if (j < fdi) { + for (k = fdi; k > j; k--) + fdc[k] = fdc[k-1]; + fdc[j].ccc = ccc; + fdc[j].uc = uc2; + } else { + fdc[fdi].ccc = ccc; + fdc[fdi].uc = uc2; + } + fdi++; + } + + WRITE_UC(); + for (fdj = 0; fdj < fdi; fdj++) { + REPLACE_UC_WITH(fdc[fdj].uc); + WRITE_UC(); + } + + if (n2 == 0) + break; + REPLACE_UC_WITH(uc2); + n = n2; + goto check_first_code; + } + as->length = p - as->s; + as->s[as->length] = '\0'; + if (ts == 2) + as->s[as->length+1] = '\0'; + return (ret); +} + +/* + * libarchive 2.x made incorrect UTF-8 strings in the wrong assumption + * that WCS is Unicode. It is true for several platforms but some are false. + * And then people who did not use UTF-8 locale on the non Unicode WCS + * platform and made a tar file with libarchive(mostly bsdtar) 2.x. Those + * now cannot get right filename from libarchive 3.x and later since we + * fixed the wrong assumption and it is incompatible to older its versions. + * So we provide special option, "compat-2x.x", for resolving it. + * That option enable the string conversion of libarchive 2.x. + * + * Translates the wrong UTF-8 string made by libarchive 2.x into current + * locale character set and appends to the archive_string. + * Note: returns -1 if conversion fails. + */ +static int +strncat_from_utf8_libarchive2(struct archive_string *as, + const void *_p, size_t len, struct archive_string_conv *sc) +{ + const char *s; + int n; + char *p; + char *end; + uint32_t unicode; +#if HAVE_WCRTOMB + mbstate_t shift_state; + + memset(&shift_state, 0, sizeof(shift_state)); +#else + /* Clear the shift state before starting. */ + wctomb(NULL, L'\0'); +#endif + (void)sc; /* UNUSED */ + /* + * Allocate buffer for MBS. + * We need this allocation here since it is possible that + * as->s is still NULL. + */ + if (archive_string_ensure(as, as->length + len + 1) == NULL) + return (-1); + + s = (const char *)_p; + p = as->s + as->length; + end = as->s + as->buffer_length - MB_CUR_MAX -1; + while ((n = _utf8_to_unicode(&unicode, s, len)) != 0) { + wchar_t wc; + + if (p >= end) { + as->length = p - as->s; + /* Re-allocate buffer for MBS. */ + if (archive_string_ensure(as, + as->length + max(len * 2, + (size_t)MB_CUR_MAX) + 1) == NULL) + return (-1); + p = as->s + as->length; + end = as->s + as->buffer_length - MB_CUR_MAX -1; + } + + /* + * As libarchive 2.x, translates the UTF-8 characters into + * wide-characters in the assumption that WCS is Unicode. + */ + if (n < 0) { + n *= -1; + wc = L'?'; + } else + wc = (wchar_t)unicode; + + s += n; + len -= n; + /* + * Translates the wide-character into the current locale MBS. + */ +#if HAVE_WCRTOMB + n = (int)wcrtomb(p, wc, &shift_state); +#else + n = (int)wctomb(p, wc); +#endif + if (n == -1) + return (-1); + p += n; + } + as->length = p - as->s; + as->s[as->length] = '\0'; + return (0); +} + + +/* + * Conversion functions between current locale dependent MBS and UTF-16BE. + * strncat_from_utf16be() : UTF-16BE --> MBS + * strncat_to_utf16be() : MBS --> UTF16BE + */ + +#if defined(_WIN32) && !defined(__CYGWIN__) + +/* + * Convert a UTF-16BE/LE string to current locale and copy the result. + * Return -1 if conversion fails. + */ +static int +win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes, + struct archive_string_conv *sc, int be) +{ + struct archive_string tmp; + const char *u16; + int ll; + BOOL defchar; + char *mbs; + size_t mbs_size, b; + int ret = 0; + + bytes &= ~1; + if (archive_string_ensure(as, as->length + bytes +1) == NULL) + return (-1); + + mbs = as->s + as->length; + mbs_size = as->buffer_length - as->length -1; + + if (sc->to_cp == CP_C_LOCALE) { + /* + * "C" locale special process. + */ + u16 = _p; + ll = 0; + for (b = 0; b < bytes; b += 2) { + uint16_t val; + if (be) + val = archive_be16dec(u16+b); + else + val = archive_le16dec(u16+b); + if (val > 255) { + *mbs++ = '?'; + ret = -1; + } else + *mbs++ = (char)(val&0xff); + ll++; + } + as->length += ll; + as->s[as->length] = '\0'; + return (ret); + } + + archive_string_init(&tmp); + if (be) { + if (is_big_endian()) { + u16 = _p; + } else { + if (archive_string_ensure(&tmp, bytes+2) == NULL) + return (-1); + memcpy(tmp.s, _p, bytes); + for (b = 0; b < bytes; b += 2) { + uint16_t val = archive_be16dec(tmp.s+b); + archive_le16enc(tmp.s+b, val); + } + u16 = tmp.s; + } + } else { + if (!is_big_endian()) { + u16 = _p; + } else { + if (archive_string_ensure(&tmp, bytes+2) == NULL) + return (-1); + memcpy(tmp.s, _p, bytes); + for (b = 0; b < bytes; b += 2) { + uint16_t val = archive_le16dec(tmp.s+b); + archive_be16enc(tmp.s+b, val); + } + u16 = tmp.s; + } + } + + do { + defchar = 0; + ll = WideCharToMultiByte(sc->to_cp, 0, + (LPCWSTR)u16, (int)bytes>>1, mbs, (int)mbs_size, + NULL, &defchar); + /* Exit loop if we succeeded */ + if (ll != 0 || + GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + break; + } + /* Else expand buffer and loop to try again. */ + ll = WideCharToMultiByte(sc->to_cp, 0, + (LPCWSTR)u16, (int)bytes, NULL, 0, NULL, NULL); + if (archive_string_ensure(as, ll +1) == NULL) + return (-1); + mbs = as->s + as->length; + mbs_size = as->buffer_length - as->length -1; + } while (1); + archive_string_free(&tmp); + as->length += ll; + as->s[as->length] = '\0'; + if (ll == 0 || defchar) + ret = -1; + return (ret); +} + +static int +win_strncat_from_utf16be(struct archive_string *as, const void *_p, + size_t bytes, struct archive_string_conv *sc) +{ + return (win_strncat_from_utf16(as, _p, bytes, sc, 1)); +} + +static int +win_strncat_from_utf16le(struct archive_string *as, const void *_p, + size_t bytes, struct archive_string_conv *sc) +{ + return (win_strncat_from_utf16(as, _p, bytes, sc, 0)); +} + +static int +is_big_endian(void) +{ + uint16_t d = 1; + + return (archive_be16dec(&d) == 1); +} + +/* + * Convert a current locale string to UTF-16BE/LE and copy the result. + * Return -1 if conversion fails. + */ +static int +win_strncat_to_utf16(struct archive_string *as16, const void *_p, + size_t length, struct archive_string_conv *sc, int bigendian) +{ + const char *s = (const char *)_p; + char *u16; + size_t count, avail; + + if (archive_string_ensure(as16, + as16->length + (length + 1) * 2) == NULL) + return (-1); + + u16 = as16->s + as16->length; + avail = as16->buffer_length - 2; + if (sc->from_cp == CP_C_LOCALE) { + /* + * "C" locale special process. + */ + count = 0; + while (count < length && *s) { + if (bigendian) + archive_be16enc(u16, *s); + else + archive_le16enc(u16, *s); + u16 += 2; + s++; + count++; + } + as16->length += count << 1; + as16->s[as16->length] = 0; + as16->s[as16->length+1] = 0; + return (0); + } + do { + count = MultiByteToWideChar(sc->from_cp, + MB_PRECOMPOSED, s, (int)length, (LPWSTR)u16, (int)avail>>1); + /* Exit loop if we succeeded */ + if (count != 0 || + GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + break; + } + /* Expand buffer and try again */ + count = MultiByteToWideChar(sc->from_cp, + MB_PRECOMPOSED, s, (int)length, NULL, 0); + if (archive_string_ensure(as16, (count +1) * 2) + == NULL) + return (-1); + u16 = as16->s + as16->length; + avail = as16->buffer_length - 2; + } while (1); + as16->length += count * 2; + as16->s[as16->length] = 0; + as16->s[as16->length+1] = 0; + if (count == 0) + return (-1); + + if (is_big_endian()) { + if (!bigendian) { + while (count > 0) { + uint16_t v = archive_be16dec(u16); + archive_le16enc(u16, v); + u16 += 2; + count--; + } + } + } else { + if (bigendian) { + while (count > 0) { + uint16_t v = archive_le16dec(u16); + archive_be16enc(u16, v); + u16 += 2; + count--; + } + } + } + return (0); +} + +static int +win_strncat_to_utf16be(struct archive_string *as16, const void *_p, + size_t length, struct archive_string_conv *sc) +{ + return (win_strncat_to_utf16(as16, _p, length, sc, 1)); +} + +static int +win_strncat_to_utf16le(struct archive_string *as16, const void *_p, + size_t length, struct archive_string_conv *sc) +{ + return (win_strncat_to_utf16(as16, _p, length, sc, 0)); +} + +#endif /* _WIN32 && !__CYGWIN__ */ + +/* + * Do the best effort for conversions. + * We cannot handle UTF-16BE character-set without such iconv, + * but there is a chance if a string consists just ASCII code or + * a current locale is UTF-8. + */ + +/* + * Convert a UTF-16BE string to current locale and copy the result. + * Return -1 if conversion fails. + */ +static int +best_effort_strncat_from_utf16(struct archive_string *as, const void *_p, + size_t bytes, struct archive_string_conv *sc, int be) +{ + const char *utf16 = (const char *)_p; + char *mbs; + uint32_t uc; + int n, ret; + + (void)sc; /* UNUSED */ + /* + * Other case, we should do the best effort. + * If all character are ASCII(<0x7f), we can convert it. + * if not , we set a alternative character and return -1. + */ + ret = 0; + if (archive_string_ensure(as, as->length + bytes +1) == NULL) + return (-1); + mbs = as->s + as->length; + + while ((n = utf16_to_unicode(&uc, utf16, bytes, be)) != 0) { + if (n < 0) { + n *= -1; + ret = -1; + } + bytes -= n; + utf16 += n; + + if (uc > 127) { + /* We cannot handle it. */ + *mbs++ = '?'; + ret = -1; + } else + *mbs++ = (char)uc; + } + as->length = mbs - as->s; + as->s[as->length] = '\0'; + return (ret); +} + +static int +best_effort_strncat_from_utf16be(struct archive_string *as, const void *_p, + size_t bytes, struct archive_string_conv *sc) +{ + return (best_effort_strncat_from_utf16(as, _p, bytes, sc, 1)); +} + +static int +best_effort_strncat_from_utf16le(struct archive_string *as, const void *_p, + size_t bytes, struct archive_string_conv *sc) +{ + return (best_effort_strncat_from_utf16(as, _p, bytes, sc, 0)); +} + +/* + * Convert a current locale string to UTF-16BE/LE and copy the result. + * Return -1 if conversion fails. + */ +static int +best_effort_strncat_to_utf16(struct archive_string *as16, const void *_p, + size_t length, struct archive_string_conv *sc, int bigendian) +{ + const char *s = (const char *)_p; + char *utf16; + size_t remaining; + int ret; + + (void)sc; /* UNUSED */ + /* + * Other case, we should do the best effort. + * If all character are ASCII(<0x7f), we can convert it. + * if not , we set a alternative character and return -1. + */ + ret = 0; + remaining = length; + + if (archive_string_ensure(as16, + as16->length + (length + 1) * 2) == NULL) + return (-1); + + utf16 = as16->s + as16->length; + while (remaining--) { + unsigned c = *s++; + if (c > 127) { + /* We cannot handle it. */ + c = UNICODE_R_CHAR; + ret = -1; + } + if (bigendian) + archive_be16enc(utf16, c); + else + archive_le16enc(utf16, c); + utf16 += 2; + } + as16->length = utf16 - as16->s; + as16->s[as16->length] = 0; + as16->s[as16->length+1] = 0; + return (ret); +} + +static int +best_effort_strncat_to_utf16be(struct archive_string *as16, const void *_p, + size_t length, struct archive_string_conv *sc) +{ + return (best_effort_strncat_to_utf16(as16, _p, length, sc, 1)); +} + +static int +best_effort_strncat_to_utf16le(struct archive_string *as16, const void *_p, + size_t length, struct archive_string_conv *sc) +{ + return (best_effort_strncat_to_utf16(as16, _p, length, sc, 0)); +} + + +/* + * Multistring operations. + */ + +void +archive_mstring_clean(struct archive_mstring *aes) +{ + archive_wstring_free(&(aes->aes_wcs)); + archive_string_free(&(aes->aes_mbs)); + archive_string_free(&(aes->aes_utf8)); + archive_string_free(&(aes->aes_mbs_in_locale)); + aes->aes_set = 0; +} + +void +archive_mstring_copy(struct archive_mstring *dest, struct archive_mstring *src) +{ + dest->aes_set = src->aes_set; + archive_string_copy(&(dest->aes_mbs), &(src->aes_mbs)); + archive_string_copy(&(dest->aes_utf8), &(src->aes_utf8)); + archive_wstring_copy(&(dest->aes_wcs), &(src->aes_wcs)); +} + +int +archive_mstring_get_utf8(struct archive *a, struct archive_mstring *aes, + const char **p) +{ + struct archive_string_conv *sc; + int r; + + /* If we already have a UTF8 form, return that immediately. */ + if (aes->aes_set & AES_SET_UTF8) { + *p = aes->aes_utf8.s; + return (0); + } + + *p = NULL; + if (aes->aes_set & AES_SET_MBS) { + sc = archive_string_conversion_to_charset(a, "UTF-8", 1); + if (sc == NULL) + return (-1);/* Couldn't allocate memory for sc. */ + r = archive_strncpy_l(&(aes->aes_utf8), aes->aes_mbs.s, + aes->aes_mbs.length, sc); + if (a == NULL) + free_sconv_object(sc); + if (r == 0) { + aes->aes_set |= AES_SET_UTF8; + *p = aes->aes_utf8.s; + return (0);/* success. */ + } else + return (-1);/* failure. */ + } + return (0);/* success. */ +} + +int +archive_mstring_get_mbs(struct archive *a, struct archive_mstring *aes, + const char **p) +{ + int r, ret = 0; + + (void)a; /* UNUSED */ + /* If we already have an MBS form, return that immediately. */ + if (aes->aes_set & AES_SET_MBS) { + *p = aes->aes_mbs.s; + return (ret); + } + + *p = NULL; + /* If there's a WCS form, try converting with the native locale. */ + if (aes->aes_set & AES_SET_WCS) { + archive_string_empty(&(aes->aes_mbs)); + r = archive_string_append_from_wcs(&(aes->aes_mbs), + aes->aes_wcs.s, aes->aes_wcs.length); + *p = aes->aes_mbs.s; + if (r == 0) { + aes->aes_set |= AES_SET_MBS; + return (ret); + } else + ret = -1; + } + + /* + * Only a UTF-8 form cannot avail because its conversion already + * failed at archive_mstring_update_utf8(). + */ + return (ret); +} + +int +archive_mstring_get_wcs(struct archive *a, struct archive_mstring *aes, + const wchar_t **wp) +{ + int r, ret = 0; + + (void)a;/* UNUSED */ + /* Return WCS form if we already have it. */ + if (aes->aes_set & AES_SET_WCS) { + *wp = aes->aes_wcs.s; + return (ret); + } + + *wp = NULL; + /* Try converting MBS to WCS using native locale. */ + if (aes->aes_set & AES_SET_MBS) { + archive_wstring_empty(&(aes->aes_wcs)); + r = archive_wstring_append_from_mbs(&(aes->aes_wcs), + aes->aes_mbs.s, aes->aes_mbs.length); + if (r == 0) { + aes->aes_set |= AES_SET_WCS; + *wp = aes->aes_wcs.s; + } else + ret = -1;/* failure. */ + } + return (ret); +} + +int +archive_mstring_get_mbs_l(struct archive_mstring *aes, + const char **p, size_t *length, struct archive_string_conv *sc) +{ + int r, ret = 0; + +#if defined(_WIN32) && !defined(__CYGWIN__) + /* + * Internationalization programming on Windows must use Wide + * characters because Windows platform cannot make locale UTF-8. + */ + if (sc != NULL && (aes->aes_set & AES_SET_WCS) != 0) { + archive_string_empty(&(aes->aes_mbs_in_locale)); + r = archive_string_append_from_wcs_in_codepage( + &(aes->aes_mbs_in_locale), aes->aes_wcs.s, + aes->aes_wcs.length, sc); + if (r == 0) { + *p = aes->aes_mbs_in_locale.s; + if (length != NULL) + *length = aes->aes_mbs_in_locale.length; + return (0); + } else if (errno == ENOMEM) + return (-1); + else + ret = -1; + } +#endif + + /* If there is not an MBS form but is a WCS form, try converting + * with the native locale to be used for translating it to specified + * character-set. */ + if ((aes->aes_set & AES_SET_MBS) == 0 && + (aes->aes_set & AES_SET_WCS) != 0) { + archive_string_empty(&(aes->aes_mbs)); + r = archive_string_append_from_wcs(&(aes->aes_mbs), + aes->aes_wcs.s, aes->aes_wcs.length); + if (r == 0) + aes->aes_set |= AES_SET_MBS; + else if (errno == ENOMEM) + return (-1); + else + ret = -1; + } + /* If we already have an MBS form, use it to be translated to + * specified character-set. */ + if (aes->aes_set & AES_SET_MBS) { + if (sc == NULL) { + /* Conversion is unneeded. */ + *p = aes->aes_mbs.s; + if (length != NULL) + *length = aes->aes_mbs.length; + return (0); + } + ret = archive_strncpy_l(&(aes->aes_mbs_in_locale), + aes->aes_mbs.s, aes->aes_mbs.length, sc); + *p = aes->aes_mbs_in_locale.s; + if (length != NULL) + *length = aes->aes_mbs_in_locale.length; + } else { + *p = NULL; + if (length != NULL) + *length = 0; + } + return (ret); +} + +int +archive_mstring_copy_mbs(struct archive_mstring *aes, const char *mbs) +{ + if (mbs == NULL) { + aes->aes_set = 0; + return (0); + } + return (archive_mstring_copy_mbs_len(aes, mbs, strlen(mbs))); +} + +int +archive_mstring_copy_mbs_len(struct archive_mstring *aes, const char *mbs, + size_t len) +{ + if (mbs == NULL) { + aes->aes_set = 0; + return (0); + } + aes->aes_set = AES_SET_MBS; /* Only MBS form is set now. */ + archive_strncpy(&(aes->aes_mbs), mbs, len); + archive_string_empty(&(aes->aes_utf8)); + archive_wstring_empty(&(aes->aes_wcs)); + return (0); +} + +int +archive_mstring_copy_wcs(struct archive_mstring *aes, const wchar_t *wcs) +{ + return archive_mstring_copy_wcs_len(aes, wcs, + wcs == NULL ? 0 : wcslen(wcs)); +} + +int +archive_mstring_copy_utf8(struct archive_mstring *aes, const char *utf8) +{ + if (utf8 == NULL) { + aes->aes_set = 0; + return (0); + } + aes->aes_set = AES_SET_UTF8; + archive_string_empty(&(aes->aes_mbs)); + archive_string_empty(&(aes->aes_wcs)); + archive_strncpy(&(aes->aes_utf8), utf8, strlen(utf8)); + return (int)strlen(utf8); +} + +int +archive_mstring_copy_wcs_len(struct archive_mstring *aes, const wchar_t *wcs, + size_t len) +{ + if (wcs == NULL) { + aes->aes_set = 0; + return (0); + } + aes->aes_set = AES_SET_WCS; /* Only WCS form set. */ + archive_string_empty(&(aes->aes_mbs)); + archive_string_empty(&(aes->aes_utf8)); + archive_wstrncpy(&(aes->aes_wcs), wcs, len); + return (0); +} + +int +archive_mstring_copy_mbs_len_l(struct archive_mstring *aes, + const char *mbs, size_t len, struct archive_string_conv *sc) +{ + int r; + + if (mbs == NULL) { + aes->aes_set = 0; + return (0); + } + archive_string_empty(&(aes->aes_mbs)); + archive_wstring_empty(&(aes->aes_wcs)); + archive_string_empty(&(aes->aes_utf8)); +#if defined(_WIN32) && !defined(__CYGWIN__) + /* + * Internationalization programming on Windows must use Wide + * characters because Windows platform cannot make locale UTF-8. + */ + if (sc == NULL) { + if (archive_string_append(&(aes->aes_mbs), + mbs, mbsnbytes(mbs, len)) == NULL) { + aes->aes_set = 0; + r = -1; + } else { + aes->aes_set = AES_SET_MBS; + r = 0; + } +#if defined(HAVE_ICONV) + } else if (sc != NULL && sc->cd_w != (iconv_t)-1) { + /* + * This case happens only when MultiByteToWideChar() cannot + * handle sc->from_cp, and we have to iconv in order to + * translate character-set to wchar_t,UTF-16. + */ + iconv_t cd = sc->cd; + unsigned from_cp; + int flag; + + /* + * Translate multi-bytes from some character-set to UTF-8. + */ + sc->cd = sc->cd_w; + r = archive_strncpy_l(&(aes->aes_utf8), mbs, len, sc); + sc->cd = cd; + if (r != 0) { + aes->aes_set = 0; + return (r); + } + aes->aes_set = AES_SET_UTF8; + + /* + * Append the UTF-8 string into wstring. + */ + flag = sc->flag; + sc->flag &= ~(SCONV_NORMALIZATION_C + | SCONV_TO_UTF16| SCONV_FROM_UTF16); + from_cp = sc->from_cp; + sc->from_cp = CP_UTF8; + r = archive_wstring_append_from_mbs_in_codepage(&(aes->aes_wcs), + aes->aes_utf8.s, aes->aes_utf8.length, sc); + sc->flag = flag; + sc->from_cp = from_cp; + if (r == 0) + aes->aes_set |= AES_SET_WCS; +#endif + } else { + r = archive_wstring_append_from_mbs_in_codepage( + &(aes->aes_wcs), mbs, len, sc); + if (r == 0) + aes->aes_set = AES_SET_WCS; + else + aes->aes_set = 0; + } +#else + r = archive_strncpy_l(&(aes->aes_mbs), mbs, len, sc); + if (r == 0) + aes->aes_set = AES_SET_MBS; /* Only MBS form is set now. */ + else + aes->aes_set = 0; +#endif + return (r); +} + +/* + * The 'update' form tries to proactively update all forms of + * this string (WCS and MBS) and returns an error if any of + * them fail. This is used by the 'pax' handler, for instance, + * to detect and report character-conversion failures early while + * still allowing clients to get potentially useful values from + * the more tolerant lazy conversions. (get_mbs and get_wcs will + * strive to give the user something useful, so you can get hopefully + * usable values even if some of the character conversions are failing.) + */ +int +archive_mstring_update_utf8(struct archive *a, struct archive_mstring *aes, + const char *utf8) +{ + struct archive_string_conv *sc; + int r; + + if (utf8 == NULL) { + aes->aes_set = 0; + return (0); /* Succeeded in clearing everything. */ + } + + /* Save the UTF8 string. */ + archive_strcpy(&(aes->aes_utf8), utf8); + + /* Empty the mbs and wcs strings. */ + archive_string_empty(&(aes->aes_mbs)); + archive_wstring_empty(&(aes->aes_wcs)); + + aes->aes_set = AES_SET_UTF8; /* Only UTF8 is set now. */ + + /* Try converting UTF-8 to MBS, return false on failure. */ + sc = archive_string_conversion_from_charset(a, "UTF-8", 1); + if (sc == NULL) + return (-1);/* Couldn't allocate memory for sc. */ + r = archive_strcpy_l(&(aes->aes_mbs), utf8, sc); + if (a == NULL) + free_sconv_object(sc); + if (r != 0) + return (-1); + aes->aes_set = AES_SET_UTF8 | AES_SET_MBS; /* Both UTF8 and MBS set. */ + + /* Try converting MBS to WCS, return false on failure. */ + if (archive_wstring_append_from_mbs(&(aes->aes_wcs), aes->aes_mbs.s, + aes->aes_mbs.length)) + return (-1); + aes->aes_set = AES_SET_UTF8 | AES_SET_WCS | AES_SET_MBS; + + /* All conversions succeeded. */ + return (0); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_string.h b/dependencies/libarchive-3.4.2/libarchive/archive_string.h new file mode 100644 index 0000000..27e1ad6 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_string.h @@ -0,0 +1,243 @@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: head/lib/libarchive/archive_string.h 201092 2009-12-28 02:26:06Z kientzle $ + * + */ + +#ifndef ARCHIVE_STRING_H_INCLUDED +#define ARCHIVE_STRING_H_INCLUDED + +#ifndef __LIBARCHIVE_BUILD +#ifndef __LIBARCHIVE_TEST +#error This header is only to be used internally to libarchive. +#endif +#endif + +#include +#ifdef HAVE_STDLIB_H +#include /* required for wchar_t on some systems */ +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_WCHAR_H +#include +#endif + +#include "archive.h" + +/* + * Basic resizable/reusable string support similar to Java's "StringBuffer." + * + * Unlike sbuf(9), the buffers here are fully reusable and track the + * length throughout. + */ + +struct archive_string { + char *s; /* Pointer to the storage */ + size_t length; /* Length of 's' in characters */ + size_t buffer_length; /* Length of malloc-ed storage in bytes. */ +}; + +struct archive_wstring { + wchar_t *s; /* Pointer to the storage */ + size_t length; /* Length of 's' in characters */ + size_t buffer_length; /* Length of malloc-ed storage in bytes. */ +}; + +struct archive_string_conv; + +/* Initialize an archive_string object on the stack or elsewhere. */ +#define archive_string_init(a) \ + do { (a)->s = NULL; (a)->length = 0; (a)->buffer_length = 0; } while(0) + +/* Append a C char to an archive_string, resizing as necessary. */ +struct archive_string * +archive_strappend_char(struct archive_string *, char); + +/* Ditto for a wchar_t and an archive_wstring. */ +struct archive_wstring * +archive_wstrappend_wchar(struct archive_wstring *, wchar_t); + +/* Append a raw array to an archive_string, resizing as necessary */ +struct archive_string * +archive_array_append(struct archive_string *, const char *, size_t); + +/* Convert a Unicode string to current locale and append the result. */ +/* Returns -1 if conversion fails. */ +int +archive_string_append_from_wcs(struct archive_string *, const wchar_t *, size_t); + + +/* Create a string conversion object. + * Return NULL and set a error message if the conversion is not supported + * on the platform. */ +struct archive_string_conv * +archive_string_conversion_to_charset(struct archive *, const char *, int); +struct archive_string_conv * +archive_string_conversion_from_charset(struct archive *, const char *, int); +/* Create the default string conversion object for reading/writing an archive. + * Return NULL if the conversion is unneeded. + * Note: On non Windows platform this always returns NULL. + */ +struct archive_string_conv * +archive_string_default_conversion_for_read(struct archive *); +struct archive_string_conv * +archive_string_default_conversion_for_write(struct archive *); +/* Dispose of a string conversion object. */ +void +archive_string_conversion_free(struct archive *); +const char * +archive_string_conversion_charset_name(struct archive_string_conv *); +void +archive_string_conversion_set_opt(struct archive_string_conv *, int); +#define SCONV_SET_OPT_UTF8_LIBARCHIVE2X 1 +#define SCONV_SET_OPT_NORMALIZATION_C 2 +#define SCONV_SET_OPT_NORMALIZATION_D 4 + + +/* Copy one archive_string to another in locale conversion. + * Return -1 if conversion fails. */ +int +archive_strncpy_l(struct archive_string *, const void *, size_t, + struct archive_string_conv *); + +/* Copy one archive_string to another in locale conversion. + * Return -1 if conversion fails. */ +int +archive_strncat_l(struct archive_string *, const void *, size_t, + struct archive_string_conv *); + + +/* Copy one archive_string to another */ +#define archive_string_copy(dest, src) \ + ((dest)->length = 0, archive_string_concat((dest), (src))) +#define archive_wstring_copy(dest, src) \ + ((dest)->length = 0, archive_wstring_concat((dest), (src))) + +/* Concatenate one archive_string to another */ +void archive_string_concat(struct archive_string *dest, struct archive_string *src); +void archive_wstring_concat(struct archive_wstring *dest, struct archive_wstring *src); + +/* Ensure that the underlying buffer is at least as large as the request. */ +struct archive_string * +archive_string_ensure(struct archive_string *, size_t); +struct archive_wstring * +archive_wstring_ensure(struct archive_wstring *, size_t); + +/* Append C string, which may lack trailing \0. */ +/* The source is declared void * here because this gets used with + * "signed char *", "unsigned char *" and "char *" arguments. + * Declaring it "char *" as with some of the other functions just + * leads to a lot of extra casts. */ +struct archive_string * +archive_strncat(struct archive_string *, const void *, size_t); +struct archive_wstring * +archive_wstrncat(struct archive_wstring *, const wchar_t *, size_t); + +/* Append a C string to an archive_string, resizing as necessary. */ +struct archive_string * +archive_strcat(struct archive_string *, const void *); +struct archive_wstring * +archive_wstrcat(struct archive_wstring *, const wchar_t *); + +/* Copy a C string to an archive_string, resizing as necessary. */ +#define archive_strcpy(as,p) \ + archive_strncpy((as), (p), ((p) == NULL ? 0 : strlen(p))) +#define archive_wstrcpy(as,p) \ + archive_wstrncpy((as), (p), ((p) == NULL ? 0 : wcslen(p))) +#define archive_strcpy_l(as,p,lo) \ + archive_strncpy_l((as), (p), ((p) == NULL ? 0 : strlen(p)), (lo)) + +/* Copy a C string to an archive_string with limit, resizing as necessary. */ +#define archive_strncpy(as,p,l) \ + ((as)->length=0, archive_strncat((as), (p), (l))) +#define archive_wstrncpy(as,p,l) \ + ((as)->length = 0, archive_wstrncat((as), (p), (l))) + +/* Return length of string. */ +#define archive_strlen(a) ((a)->length) + +/* Set string length to zero. */ +#define archive_string_empty(a) ((a)->length = 0) +#define archive_wstring_empty(a) ((a)->length = 0) + +/* Release any allocated storage resources. */ +void archive_string_free(struct archive_string *); +void archive_wstring_free(struct archive_wstring *); + +/* Like 'vsprintf', but resizes the underlying string as necessary. */ +/* Note: This only implements a small subset of standard printf functionality. */ +void archive_string_vsprintf(struct archive_string *, const char *, + va_list) __LA_PRINTF(2, 0); +void archive_string_sprintf(struct archive_string *, const char *, ...) + __LA_PRINTF(2, 3); + +/* Translates from MBS to Unicode. */ +/* Returns non-zero if conversion failed in any way. */ +int archive_wstring_append_from_mbs(struct archive_wstring *dest, + const char *, size_t); + + +/* A "multistring" can hold Unicode, UTF8, or MBS versions of + * the string. If you set and read the same version, no translation + * is done. If you set and read different versions, the library + * will attempt to transparently convert. + */ +struct archive_mstring { + struct archive_string aes_mbs; + struct archive_string aes_utf8; + struct archive_wstring aes_wcs; + struct archive_string aes_mbs_in_locale; + /* Bitmap of which of the above are valid. Because we're lazy + * about malloc-ing and reusing the underlying storage, we + * can't rely on NULL pointers to indicate whether a string + * has been set. */ + int aes_set; +#define AES_SET_MBS 1 +#define AES_SET_UTF8 2 +#define AES_SET_WCS 4 +}; + +void archive_mstring_clean(struct archive_mstring *); +void archive_mstring_copy(struct archive_mstring *dest, struct archive_mstring *src); +int archive_mstring_get_mbs(struct archive *, struct archive_mstring *, const char **); +int archive_mstring_get_utf8(struct archive *, struct archive_mstring *, const char **); +int archive_mstring_get_wcs(struct archive *, struct archive_mstring *, const wchar_t **); +int archive_mstring_get_mbs_l(struct archive_mstring *, const char **, + size_t *, struct archive_string_conv *); +int archive_mstring_copy_mbs(struct archive_mstring *, const char *mbs); +int archive_mstring_copy_mbs_len(struct archive_mstring *, const char *mbs, + size_t); +int archive_mstring_copy_utf8(struct archive_mstring *, const char *utf8); +int archive_mstring_copy_wcs(struct archive_mstring *, const wchar_t *wcs); +int archive_mstring_copy_wcs_len(struct archive_mstring *, + const wchar_t *wcs, size_t); +int archive_mstring_copy_mbs_len_l(struct archive_mstring *, + const char *mbs, size_t, struct archive_string_conv *); +int archive_mstring_update_utf8(struct archive *, struct archive_mstring *aes, const char *utf8); + + +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_string_composition.h b/dependencies/libarchive-3.4.2/libarchive/archive_string_composition.h new file mode 100644 index 0000000..d0ac340 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_string_composition.h @@ -0,0 +1,2292 @@ +/*- + * Copyright (c) 2011-2012 libarchive Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + * + */ + +/* + * ATTENTION! + * This file is generated by build/utils/gen_archive_string_composition_h.sh + * from http://unicode.org/Public/6.0.0/ucd/UnicodeData.txt + * + * See also http://unicode.org/report/tr15/ + */ + +#ifndef ARCHIVE_STRING_COMPOSITION_H_INCLUDED +#define ARCHIVE_STRING_COMPOSITION_H_INCLUDED + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif + +struct unicode_composition_table { + uint32_t cp1; + uint32_t cp2; + uint32_t nfc; +}; + +static const struct unicode_composition_table u_composition_table[] = { + { 0x0003C , 0x00338 , 0x0226E }, + { 0x0003D , 0x00338 , 0x02260 }, + { 0x0003E , 0x00338 , 0x0226F }, + { 0x00041 , 0x00300 , 0x000C0 }, + { 0x00041 , 0x00301 , 0x000C1 }, + { 0x00041 , 0x00302 , 0x000C2 }, + { 0x00041 , 0x00303 , 0x000C3 }, + { 0x00041 , 0x00304 , 0x00100 }, + { 0x00041 , 0x00306 , 0x00102 }, + { 0x00041 , 0x00307 , 0x00226 }, + { 0x00041 , 0x00308 , 0x000C4 }, + { 0x00041 , 0x00309 , 0x01EA2 }, + { 0x00041 , 0x0030A , 0x000C5 }, + { 0x00041 , 0x0030C , 0x001CD }, + { 0x00041 , 0x0030F , 0x00200 }, + { 0x00041 , 0x00311 , 0x00202 }, + { 0x00041 , 0x00323 , 0x01EA0 }, + { 0x00041 , 0x00325 , 0x01E00 }, + { 0x00041 , 0x00328 , 0x00104 }, + { 0x00042 , 0x00307 , 0x01E02 }, + { 0x00042 , 0x00323 , 0x01E04 }, + { 0x00042 , 0x00331 , 0x01E06 }, + { 0x00043 , 0x00301 , 0x00106 }, + { 0x00043 , 0x00302 , 0x00108 }, + { 0x00043 , 0x00307 , 0x0010A }, + { 0x00043 , 0x0030C , 0x0010C }, + { 0x00043 , 0x00327 , 0x000C7 }, + { 0x00044 , 0x00307 , 0x01E0A }, + { 0x00044 , 0x0030C , 0x0010E }, + { 0x00044 , 0x00323 , 0x01E0C }, + { 0x00044 , 0x00327 , 0x01E10 }, + { 0x00044 , 0x0032D , 0x01E12 }, + { 0x00044 , 0x00331 , 0x01E0E }, + { 0x00045 , 0x00300 , 0x000C8 }, + { 0x00045 , 0x00301 , 0x000C9 }, + { 0x00045 , 0x00302 , 0x000CA }, + { 0x00045 , 0x00303 , 0x01EBC }, + { 0x00045 , 0x00304 , 0x00112 }, + { 0x00045 , 0x00306 , 0x00114 }, + { 0x00045 , 0x00307 , 0x00116 }, + { 0x00045 , 0x00308 , 0x000CB }, + { 0x00045 , 0x00309 , 0x01EBA }, + { 0x00045 , 0x0030C , 0x0011A }, + { 0x00045 , 0x0030F , 0x00204 }, + { 0x00045 , 0x00311 , 0x00206 }, + { 0x00045 , 0x00323 , 0x01EB8 }, + { 0x00045 , 0x00327 , 0x00228 }, + { 0x00045 , 0x00328 , 0x00118 }, + { 0x00045 , 0x0032D , 0x01E18 }, + { 0x00045 , 0x00330 , 0x01E1A }, + { 0x00046 , 0x00307 , 0x01E1E }, + { 0x00047 , 0x00301 , 0x001F4 }, + { 0x00047 , 0x00302 , 0x0011C }, + { 0x00047 , 0x00304 , 0x01E20 }, + { 0x00047 , 0x00306 , 0x0011E }, + { 0x00047 , 0x00307 , 0x00120 }, + { 0x00047 , 0x0030C , 0x001E6 }, + { 0x00047 , 0x00327 , 0x00122 }, + { 0x00048 , 0x00302 , 0x00124 }, + { 0x00048 , 0x00307 , 0x01E22 }, + { 0x00048 , 0x00308 , 0x01E26 }, + { 0x00048 , 0x0030C , 0x0021E }, + { 0x00048 , 0x00323 , 0x01E24 }, + { 0x00048 , 0x00327 , 0x01E28 }, + { 0x00048 , 0x0032E , 0x01E2A }, + { 0x00049 , 0x00300 , 0x000CC }, + { 0x00049 , 0x00301 , 0x000CD }, + { 0x00049 , 0x00302 , 0x000CE }, + { 0x00049 , 0x00303 , 0x00128 }, + { 0x00049 , 0x00304 , 0x0012A }, + { 0x00049 , 0x00306 , 0x0012C }, + { 0x00049 , 0x00307 , 0x00130 }, + { 0x00049 , 0x00308 , 0x000CF }, + { 0x00049 , 0x00309 , 0x01EC8 }, + { 0x00049 , 0x0030C , 0x001CF }, + { 0x00049 , 0x0030F , 0x00208 }, + { 0x00049 , 0x00311 , 0x0020A }, + { 0x00049 , 0x00323 , 0x01ECA }, + { 0x00049 , 0x00328 , 0x0012E }, + { 0x00049 , 0x00330 , 0x01E2C }, + { 0x0004A , 0x00302 , 0x00134 }, + { 0x0004B , 0x00301 , 0x01E30 }, + { 0x0004B , 0x0030C , 0x001E8 }, + { 0x0004B , 0x00323 , 0x01E32 }, + { 0x0004B , 0x00327 , 0x00136 }, + { 0x0004B , 0x00331 , 0x01E34 }, + { 0x0004C , 0x00301 , 0x00139 }, + { 0x0004C , 0x0030C , 0x0013D }, + { 0x0004C , 0x00323 , 0x01E36 }, + { 0x0004C , 0x00327 , 0x0013B }, + { 0x0004C , 0x0032D , 0x01E3C }, + { 0x0004C , 0x00331 , 0x01E3A }, + { 0x0004D , 0x00301 , 0x01E3E }, + { 0x0004D , 0x00307 , 0x01E40 }, + { 0x0004D , 0x00323 , 0x01E42 }, + { 0x0004E , 0x00300 , 0x001F8 }, + { 0x0004E , 0x00301 , 0x00143 }, + { 0x0004E , 0x00303 , 0x000D1 }, + { 0x0004E , 0x00307 , 0x01E44 }, + { 0x0004E , 0x0030C , 0x00147 }, + { 0x0004E , 0x00323 , 0x01E46 }, + { 0x0004E , 0x00327 , 0x00145 }, + { 0x0004E , 0x0032D , 0x01E4A }, + { 0x0004E , 0x00331 , 0x01E48 }, + { 0x0004F , 0x00300 , 0x000D2 }, + { 0x0004F , 0x00301 , 0x000D3 }, + { 0x0004F , 0x00302 , 0x000D4 }, + { 0x0004F , 0x00303 , 0x000D5 }, + { 0x0004F , 0x00304 , 0x0014C }, + { 0x0004F , 0x00306 , 0x0014E }, + { 0x0004F , 0x00307 , 0x0022E }, + { 0x0004F , 0x00308 , 0x000D6 }, + { 0x0004F , 0x00309 , 0x01ECE }, + { 0x0004F , 0x0030B , 0x00150 }, + { 0x0004F , 0x0030C , 0x001D1 }, + { 0x0004F , 0x0030F , 0x0020C }, + { 0x0004F , 0x00311 , 0x0020E }, + { 0x0004F , 0x0031B , 0x001A0 }, + { 0x0004F , 0x00323 , 0x01ECC }, + { 0x0004F , 0x00328 , 0x001EA }, + { 0x00050 , 0x00301 , 0x01E54 }, + { 0x00050 , 0x00307 , 0x01E56 }, + { 0x00052 , 0x00301 , 0x00154 }, + { 0x00052 , 0x00307 , 0x01E58 }, + { 0x00052 , 0x0030C , 0x00158 }, + { 0x00052 , 0x0030F , 0x00210 }, + { 0x00052 , 0x00311 , 0x00212 }, + { 0x00052 , 0x00323 , 0x01E5A }, + { 0x00052 , 0x00327 , 0x00156 }, + { 0x00052 , 0x00331 , 0x01E5E }, + { 0x00053 , 0x00301 , 0x0015A }, + { 0x00053 , 0x00302 , 0x0015C }, + { 0x00053 , 0x00307 , 0x01E60 }, + { 0x00053 , 0x0030C , 0x00160 }, + { 0x00053 , 0x00323 , 0x01E62 }, + { 0x00053 , 0x00326 , 0x00218 }, + { 0x00053 , 0x00327 , 0x0015E }, + { 0x00054 , 0x00307 , 0x01E6A }, + { 0x00054 , 0x0030C , 0x00164 }, + { 0x00054 , 0x00323 , 0x01E6C }, + { 0x00054 , 0x00326 , 0x0021A }, + { 0x00054 , 0x00327 , 0x00162 }, + { 0x00054 , 0x0032D , 0x01E70 }, + { 0x00054 , 0x00331 , 0x01E6E }, + { 0x00055 , 0x00300 , 0x000D9 }, + { 0x00055 , 0x00301 , 0x000DA }, + { 0x00055 , 0x00302 , 0x000DB }, + { 0x00055 , 0x00303 , 0x00168 }, + { 0x00055 , 0x00304 , 0x0016A }, + { 0x00055 , 0x00306 , 0x0016C }, + { 0x00055 , 0x00308 , 0x000DC }, + { 0x00055 , 0x00309 , 0x01EE6 }, + { 0x00055 , 0x0030A , 0x0016E }, + { 0x00055 , 0x0030B , 0x00170 }, + { 0x00055 , 0x0030C , 0x001D3 }, + { 0x00055 , 0x0030F , 0x00214 }, + { 0x00055 , 0x00311 , 0x00216 }, + { 0x00055 , 0x0031B , 0x001AF }, + { 0x00055 , 0x00323 , 0x01EE4 }, + { 0x00055 , 0x00324 , 0x01E72 }, + { 0x00055 , 0x00328 , 0x00172 }, + { 0x00055 , 0x0032D , 0x01E76 }, + { 0x00055 , 0x00330 , 0x01E74 }, + { 0x00056 , 0x00303 , 0x01E7C }, + { 0x00056 , 0x00323 , 0x01E7E }, + { 0x00057 , 0x00300 , 0x01E80 }, + { 0x00057 , 0x00301 , 0x01E82 }, + { 0x00057 , 0x00302 , 0x00174 }, + { 0x00057 , 0x00307 , 0x01E86 }, + { 0x00057 , 0x00308 , 0x01E84 }, + { 0x00057 , 0x00323 , 0x01E88 }, + { 0x00058 , 0x00307 , 0x01E8A }, + { 0x00058 , 0x00308 , 0x01E8C }, + { 0x00059 , 0x00300 , 0x01EF2 }, + { 0x00059 , 0x00301 , 0x000DD }, + { 0x00059 , 0x00302 , 0x00176 }, + { 0x00059 , 0x00303 , 0x01EF8 }, + { 0x00059 , 0x00304 , 0x00232 }, + { 0x00059 , 0x00307 , 0x01E8E }, + { 0x00059 , 0x00308 , 0x00178 }, + { 0x00059 , 0x00309 , 0x01EF6 }, + { 0x00059 , 0x00323 , 0x01EF4 }, + { 0x0005A , 0x00301 , 0x00179 }, + { 0x0005A , 0x00302 , 0x01E90 }, + { 0x0005A , 0x00307 , 0x0017B }, + { 0x0005A , 0x0030C , 0x0017D }, + { 0x0005A , 0x00323 , 0x01E92 }, + { 0x0005A , 0x00331 , 0x01E94 }, + { 0x00061 , 0x00300 , 0x000E0 }, + { 0x00061 , 0x00301 , 0x000E1 }, + { 0x00061 , 0x00302 , 0x000E2 }, + { 0x00061 , 0x00303 , 0x000E3 }, + { 0x00061 , 0x00304 , 0x00101 }, + { 0x00061 , 0x00306 , 0x00103 }, + { 0x00061 , 0x00307 , 0x00227 }, + { 0x00061 , 0x00308 , 0x000E4 }, + { 0x00061 , 0x00309 , 0x01EA3 }, + { 0x00061 , 0x0030A , 0x000E5 }, + { 0x00061 , 0x0030C , 0x001CE }, + { 0x00061 , 0x0030F , 0x00201 }, + { 0x00061 , 0x00311 , 0x00203 }, + { 0x00061 , 0x00323 , 0x01EA1 }, + { 0x00061 , 0x00325 , 0x01E01 }, + { 0x00061 , 0x00328 , 0x00105 }, + { 0x00062 , 0x00307 , 0x01E03 }, + { 0x00062 , 0x00323 , 0x01E05 }, + { 0x00062 , 0x00331 , 0x01E07 }, + { 0x00063 , 0x00301 , 0x00107 }, + { 0x00063 , 0x00302 , 0x00109 }, + { 0x00063 , 0x00307 , 0x0010B }, + { 0x00063 , 0x0030C , 0x0010D }, + { 0x00063 , 0x00327 , 0x000E7 }, + { 0x00064 , 0x00307 , 0x01E0B }, + { 0x00064 , 0x0030C , 0x0010F }, + { 0x00064 , 0x00323 , 0x01E0D }, + { 0x00064 , 0x00327 , 0x01E11 }, + { 0x00064 , 0x0032D , 0x01E13 }, + { 0x00064 , 0x00331 , 0x01E0F }, + { 0x00065 , 0x00300 , 0x000E8 }, + { 0x00065 , 0x00301 , 0x000E9 }, + { 0x00065 , 0x00302 , 0x000EA }, + { 0x00065 , 0x00303 , 0x01EBD }, + { 0x00065 , 0x00304 , 0x00113 }, + { 0x00065 , 0x00306 , 0x00115 }, + { 0x00065 , 0x00307 , 0x00117 }, + { 0x00065 , 0x00308 , 0x000EB }, + { 0x00065 , 0x00309 , 0x01EBB }, + { 0x00065 , 0x0030C , 0x0011B }, + { 0x00065 , 0x0030F , 0x00205 }, + { 0x00065 , 0x00311 , 0x00207 }, + { 0x00065 , 0x00323 , 0x01EB9 }, + { 0x00065 , 0x00327 , 0x00229 }, + { 0x00065 , 0x00328 , 0x00119 }, + { 0x00065 , 0x0032D , 0x01E19 }, + { 0x00065 , 0x00330 , 0x01E1B }, + { 0x00066 , 0x00307 , 0x01E1F }, + { 0x00067 , 0x00301 , 0x001F5 }, + { 0x00067 , 0x00302 , 0x0011D }, + { 0x00067 , 0x00304 , 0x01E21 }, + { 0x00067 , 0x00306 , 0x0011F }, + { 0x00067 , 0x00307 , 0x00121 }, + { 0x00067 , 0x0030C , 0x001E7 }, + { 0x00067 , 0x00327 , 0x00123 }, + { 0x00068 , 0x00302 , 0x00125 }, + { 0x00068 , 0x00307 , 0x01E23 }, + { 0x00068 , 0x00308 , 0x01E27 }, + { 0x00068 , 0x0030C , 0x0021F }, + { 0x00068 , 0x00323 , 0x01E25 }, + { 0x00068 , 0x00327 , 0x01E29 }, + { 0x00068 , 0x0032E , 0x01E2B }, + { 0x00068 , 0x00331 , 0x01E96 }, + { 0x00069 , 0x00300 , 0x000EC }, + { 0x00069 , 0x00301 , 0x000ED }, + { 0x00069 , 0x00302 , 0x000EE }, + { 0x00069 , 0x00303 , 0x00129 }, + { 0x00069 , 0x00304 , 0x0012B }, + { 0x00069 , 0x00306 , 0x0012D }, + { 0x00069 , 0x00308 , 0x000EF }, + { 0x00069 , 0x00309 , 0x01EC9 }, + { 0x00069 , 0x0030C , 0x001D0 }, + { 0x00069 , 0x0030F , 0x00209 }, + { 0x00069 , 0x00311 , 0x0020B }, + { 0x00069 , 0x00323 , 0x01ECB }, + { 0x00069 , 0x00328 , 0x0012F }, + { 0x00069 , 0x00330 , 0x01E2D }, + { 0x0006A , 0x00302 , 0x00135 }, + { 0x0006A , 0x0030C , 0x001F0 }, + { 0x0006B , 0x00301 , 0x01E31 }, + { 0x0006B , 0x0030C , 0x001E9 }, + { 0x0006B , 0x00323 , 0x01E33 }, + { 0x0006B , 0x00327 , 0x00137 }, + { 0x0006B , 0x00331 , 0x01E35 }, + { 0x0006C , 0x00301 , 0x0013A }, + { 0x0006C , 0x0030C , 0x0013E }, + { 0x0006C , 0x00323 , 0x01E37 }, + { 0x0006C , 0x00327 , 0x0013C }, + { 0x0006C , 0x0032D , 0x01E3D }, + { 0x0006C , 0x00331 , 0x01E3B }, + { 0x0006D , 0x00301 , 0x01E3F }, + { 0x0006D , 0x00307 , 0x01E41 }, + { 0x0006D , 0x00323 , 0x01E43 }, + { 0x0006E , 0x00300 , 0x001F9 }, + { 0x0006E , 0x00301 , 0x00144 }, + { 0x0006E , 0x00303 , 0x000F1 }, + { 0x0006E , 0x00307 , 0x01E45 }, + { 0x0006E , 0x0030C , 0x00148 }, + { 0x0006E , 0x00323 , 0x01E47 }, + { 0x0006E , 0x00327 , 0x00146 }, + { 0x0006E , 0x0032D , 0x01E4B }, + { 0x0006E , 0x00331 , 0x01E49 }, + { 0x0006F , 0x00300 , 0x000F2 }, + { 0x0006F , 0x00301 , 0x000F3 }, + { 0x0006F , 0x00302 , 0x000F4 }, + { 0x0006F , 0x00303 , 0x000F5 }, + { 0x0006F , 0x00304 , 0x0014D }, + { 0x0006F , 0x00306 , 0x0014F }, + { 0x0006F , 0x00307 , 0x0022F }, + { 0x0006F , 0x00308 , 0x000F6 }, + { 0x0006F , 0x00309 , 0x01ECF }, + { 0x0006F , 0x0030B , 0x00151 }, + { 0x0006F , 0x0030C , 0x001D2 }, + { 0x0006F , 0x0030F , 0x0020D }, + { 0x0006F , 0x00311 , 0x0020F }, + { 0x0006F , 0x0031B , 0x001A1 }, + { 0x0006F , 0x00323 , 0x01ECD }, + { 0x0006F , 0x00328 , 0x001EB }, + { 0x00070 , 0x00301 , 0x01E55 }, + { 0x00070 , 0x00307 , 0x01E57 }, + { 0x00072 , 0x00301 , 0x00155 }, + { 0x00072 , 0x00307 , 0x01E59 }, + { 0x00072 , 0x0030C , 0x00159 }, + { 0x00072 , 0x0030F , 0x00211 }, + { 0x00072 , 0x00311 , 0x00213 }, + { 0x00072 , 0x00323 , 0x01E5B }, + { 0x00072 , 0x00327 , 0x00157 }, + { 0x00072 , 0x00331 , 0x01E5F }, + { 0x00073 , 0x00301 , 0x0015B }, + { 0x00073 , 0x00302 , 0x0015D }, + { 0x00073 , 0x00307 , 0x01E61 }, + { 0x00073 , 0x0030C , 0x00161 }, + { 0x00073 , 0x00323 , 0x01E63 }, + { 0x00073 , 0x00326 , 0x00219 }, + { 0x00073 , 0x00327 , 0x0015F }, + { 0x00074 , 0x00307 , 0x01E6B }, + { 0x00074 , 0x00308 , 0x01E97 }, + { 0x00074 , 0x0030C , 0x00165 }, + { 0x00074 , 0x00323 , 0x01E6D }, + { 0x00074 , 0x00326 , 0x0021B }, + { 0x00074 , 0x00327 , 0x00163 }, + { 0x00074 , 0x0032D , 0x01E71 }, + { 0x00074 , 0x00331 , 0x01E6F }, + { 0x00075 , 0x00300 , 0x000F9 }, + { 0x00075 , 0x00301 , 0x000FA }, + { 0x00075 , 0x00302 , 0x000FB }, + { 0x00075 , 0x00303 , 0x00169 }, + { 0x00075 , 0x00304 , 0x0016B }, + { 0x00075 , 0x00306 , 0x0016D }, + { 0x00075 , 0x00308 , 0x000FC }, + { 0x00075 , 0x00309 , 0x01EE7 }, + { 0x00075 , 0x0030A , 0x0016F }, + { 0x00075 , 0x0030B , 0x00171 }, + { 0x00075 , 0x0030C , 0x001D4 }, + { 0x00075 , 0x0030F , 0x00215 }, + { 0x00075 , 0x00311 , 0x00217 }, + { 0x00075 , 0x0031B , 0x001B0 }, + { 0x00075 , 0x00323 , 0x01EE5 }, + { 0x00075 , 0x00324 , 0x01E73 }, + { 0x00075 , 0x00328 , 0x00173 }, + { 0x00075 , 0x0032D , 0x01E77 }, + { 0x00075 , 0x00330 , 0x01E75 }, + { 0x00076 , 0x00303 , 0x01E7D }, + { 0x00076 , 0x00323 , 0x01E7F }, + { 0x00077 , 0x00300 , 0x01E81 }, + { 0x00077 , 0x00301 , 0x01E83 }, + { 0x00077 , 0x00302 , 0x00175 }, + { 0x00077 , 0x00307 , 0x01E87 }, + { 0x00077 , 0x00308 , 0x01E85 }, + { 0x00077 , 0x0030A , 0x01E98 }, + { 0x00077 , 0x00323 , 0x01E89 }, + { 0x00078 , 0x00307 , 0x01E8B }, + { 0x00078 , 0x00308 , 0x01E8D }, + { 0x00079 , 0x00300 , 0x01EF3 }, + { 0x00079 , 0x00301 , 0x000FD }, + { 0x00079 , 0x00302 , 0x00177 }, + { 0x00079 , 0x00303 , 0x01EF9 }, + { 0x00079 , 0x00304 , 0x00233 }, + { 0x00079 , 0x00307 , 0x01E8F }, + { 0x00079 , 0x00308 , 0x000FF }, + { 0x00079 , 0x00309 , 0x01EF7 }, + { 0x00079 , 0x0030A , 0x01E99 }, + { 0x00079 , 0x00323 , 0x01EF5 }, + { 0x0007A , 0x00301 , 0x0017A }, + { 0x0007A , 0x00302 , 0x01E91 }, + { 0x0007A , 0x00307 , 0x0017C }, + { 0x0007A , 0x0030C , 0x0017E }, + { 0x0007A , 0x00323 , 0x01E93 }, + { 0x0007A , 0x00331 , 0x01E95 }, + { 0x000A8 , 0x00300 , 0x01FED }, + { 0x000A8 , 0x00301 , 0x00385 }, + { 0x000A8 , 0x00342 , 0x01FC1 }, + { 0x000C2 , 0x00300 , 0x01EA6 }, + { 0x000C2 , 0x00301 , 0x01EA4 }, + { 0x000C2 , 0x00303 , 0x01EAA }, + { 0x000C2 , 0x00309 , 0x01EA8 }, + { 0x000C4 , 0x00304 , 0x001DE }, + { 0x000C5 , 0x00301 , 0x001FA }, + { 0x000C6 , 0x00301 , 0x001FC }, + { 0x000C6 , 0x00304 , 0x001E2 }, + { 0x000C7 , 0x00301 , 0x01E08 }, + { 0x000CA , 0x00300 , 0x01EC0 }, + { 0x000CA , 0x00301 , 0x01EBE }, + { 0x000CA , 0x00303 , 0x01EC4 }, + { 0x000CA , 0x00309 , 0x01EC2 }, + { 0x000CF , 0x00301 , 0x01E2E }, + { 0x000D4 , 0x00300 , 0x01ED2 }, + { 0x000D4 , 0x00301 , 0x01ED0 }, + { 0x000D4 , 0x00303 , 0x01ED6 }, + { 0x000D4 , 0x00309 , 0x01ED4 }, + { 0x000D5 , 0x00301 , 0x01E4C }, + { 0x000D5 , 0x00304 , 0x0022C }, + { 0x000D5 , 0x00308 , 0x01E4E }, + { 0x000D6 , 0x00304 , 0x0022A }, + { 0x000D8 , 0x00301 , 0x001FE }, + { 0x000DC , 0x00300 , 0x001DB }, + { 0x000DC , 0x00301 , 0x001D7 }, + { 0x000DC , 0x00304 , 0x001D5 }, + { 0x000DC , 0x0030C , 0x001D9 }, + { 0x000E2 , 0x00300 , 0x01EA7 }, + { 0x000E2 , 0x00301 , 0x01EA5 }, + { 0x000E2 , 0x00303 , 0x01EAB }, + { 0x000E2 , 0x00309 , 0x01EA9 }, + { 0x000E4 , 0x00304 , 0x001DF }, + { 0x000E5 , 0x00301 , 0x001FB }, + { 0x000E6 , 0x00301 , 0x001FD }, + { 0x000E6 , 0x00304 , 0x001E3 }, + { 0x000E7 , 0x00301 , 0x01E09 }, + { 0x000EA , 0x00300 , 0x01EC1 }, + { 0x000EA , 0x00301 , 0x01EBF }, + { 0x000EA , 0x00303 , 0x01EC5 }, + { 0x000EA , 0x00309 , 0x01EC3 }, + { 0x000EF , 0x00301 , 0x01E2F }, + { 0x000F4 , 0x00300 , 0x01ED3 }, + { 0x000F4 , 0x00301 , 0x01ED1 }, + { 0x000F4 , 0x00303 , 0x01ED7 }, + { 0x000F4 , 0x00309 , 0x01ED5 }, + { 0x000F5 , 0x00301 , 0x01E4D }, + { 0x000F5 , 0x00304 , 0x0022D }, + { 0x000F5 , 0x00308 , 0x01E4F }, + { 0x000F6 , 0x00304 , 0x0022B }, + { 0x000F8 , 0x00301 , 0x001FF }, + { 0x000FC , 0x00300 , 0x001DC }, + { 0x000FC , 0x00301 , 0x001D8 }, + { 0x000FC , 0x00304 , 0x001D6 }, + { 0x000FC , 0x0030C , 0x001DA }, + { 0x00102 , 0x00300 , 0x01EB0 }, + { 0x00102 , 0x00301 , 0x01EAE }, + { 0x00102 , 0x00303 , 0x01EB4 }, + { 0x00102 , 0x00309 , 0x01EB2 }, + { 0x00103 , 0x00300 , 0x01EB1 }, + { 0x00103 , 0x00301 , 0x01EAF }, + { 0x00103 , 0x00303 , 0x01EB5 }, + { 0x00103 , 0x00309 , 0x01EB3 }, + { 0x00112 , 0x00300 , 0x01E14 }, + { 0x00112 , 0x00301 , 0x01E16 }, + { 0x00113 , 0x00300 , 0x01E15 }, + { 0x00113 , 0x00301 , 0x01E17 }, + { 0x0014C , 0x00300 , 0x01E50 }, + { 0x0014C , 0x00301 , 0x01E52 }, + { 0x0014D , 0x00300 , 0x01E51 }, + { 0x0014D , 0x00301 , 0x01E53 }, + { 0x0015A , 0x00307 , 0x01E64 }, + { 0x0015B , 0x00307 , 0x01E65 }, + { 0x00160 , 0x00307 , 0x01E66 }, + { 0x00161 , 0x00307 , 0x01E67 }, + { 0x00168 , 0x00301 , 0x01E78 }, + { 0x00169 , 0x00301 , 0x01E79 }, + { 0x0016A , 0x00308 , 0x01E7A }, + { 0x0016B , 0x00308 , 0x01E7B }, + { 0x0017F , 0x00307 , 0x01E9B }, + { 0x001A0 , 0x00300 , 0x01EDC }, + { 0x001A0 , 0x00301 , 0x01EDA }, + { 0x001A0 , 0x00303 , 0x01EE0 }, + { 0x001A0 , 0x00309 , 0x01EDE }, + { 0x001A0 , 0x00323 , 0x01EE2 }, + { 0x001A1 , 0x00300 , 0x01EDD }, + { 0x001A1 , 0x00301 , 0x01EDB }, + { 0x001A1 , 0x00303 , 0x01EE1 }, + { 0x001A1 , 0x00309 , 0x01EDF }, + { 0x001A1 , 0x00323 , 0x01EE3 }, + { 0x001AF , 0x00300 , 0x01EEA }, + { 0x001AF , 0x00301 , 0x01EE8 }, + { 0x001AF , 0x00303 , 0x01EEE }, + { 0x001AF , 0x00309 , 0x01EEC }, + { 0x001AF , 0x00323 , 0x01EF0 }, + { 0x001B0 , 0x00300 , 0x01EEB }, + { 0x001B0 , 0x00301 , 0x01EE9 }, + { 0x001B0 , 0x00303 , 0x01EEF }, + { 0x001B0 , 0x00309 , 0x01EED }, + { 0x001B0 , 0x00323 , 0x01EF1 }, + { 0x001B7 , 0x0030C , 0x001EE }, + { 0x001EA , 0x00304 , 0x001EC }, + { 0x001EB , 0x00304 , 0x001ED }, + { 0x00226 , 0x00304 , 0x001E0 }, + { 0x00227 , 0x00304 , 0x001E1 }, + { 0x00228 , 0x00306 , 0x01E1C }, + { 0x00229 , 0x00306 , 0x01E1D }, + { 0x0022E , 0x00304 , 0x00230 }, + { 0x0022F , 0x00304 , 0x00231 }, + { 0x00292 , 0x0030C , 0x001EF }, + { 0x00391 , 0x00300 , 0x01FBA }, + { 0x00391 , 0x00301 , 0x00386 }, + { 0x00391 , 0x00304 , 0x01FB9 }, + { 0x00391 , 0x00306 , 0x01FB8 }, + { 0x00391 , 0x00313 , 0x01F08 }, + { 0x00391 , 0x00314 , 0x01F09 }, + { 0x00391 , 0x00345 , 0x01FBC }, + { 0x00395 , 0x00300 , 0x01FC8 }, + { 0x00395 , 0x00301 , 0x00388 }, + { 0x00395 , 0x00313 , 0x01F18 }, + { 0x00395 , 0x00314 , 0x01F19 }, + { 0x00397 , 0x00300 , 0x01FCA }, + { 0x00397 , 0x00301 , 0x00389 }, + { 0x00397 , 0x00313 , 0x01F28 }, + { 0x00397 , 0x00314 , 0x01F29 }, + { 0x00397 , 0x00345 , 0x01FCC }, + { 0x00399 , 0x00300 , 0x01FDA }, + { 0x00399 , 0x00301 , 0x0038A }, + { 0x00399 , 0x00304 , 0x01FD9 }, + { 0x00399 , 0x00306 , 0x01FD8 }, + { 0x00399 , 0x00308 , 0x003AA }, + { 0x00399 , 0x00313 , 0x01F38 }, + { 0x00399 , 0x00314 , 0x01F39 }, + { 0x0039F , 0x00300 , 0x01FF8 }, + { 0x0039F , 0x00301 , 0x0038C }, + { 0x0039F , 0x00313 , 0x01F48 }, + { 0x0039F , 0x00314 , 0x01F49 }, + { 0x003A1 , 0x00314 , 0x01FEC }, + { 0x003A5 , 0x00300 , 0x01FEA }, + { 0x003A5 , 0x00301 , 0x0038E }, + { 0x003A5 , 0x00304 , 0x01FE9 }, + { 0x003A5 , 0x00306 , 0x01FE8 }, + { 0x003A5 , 0x00308 , 0x003AB }, + { 0x003A5 , 0x00314 , 0x01F59 }, + { 0x003A9 , 0x00300 , 0x01FFA }, + { 0x003A9 , 0x00301 , 0x0038F }, + { 0x003A9 , 0x00313 , 0x01F68 }, + { 0x003A9 , 0x00314 , 0x01F69 }, + { 0x003A9 , 0x00345 , 0x01FFC }, + { 0x003AC , 0x00345 , 0x01FB4 }, + { 0x003AE , 0x00345 , 0x01FC4 }, + { 0x003B1 , 0x00300 , 0x01F70 }, + { 0x003B1 , 0x00301 , 0x003AC }, + { 0x003B1 , 0x00304 , 0x01FB1 }, + { 0x003B1 , 0x00306 , 0x01FB0 }, + { 0x003B1 , 0x00313 , 0x01F00 }, + { 0x003B1 , 0x00314 , 0x01F01 }, + { 0x003B1 , 0x00342 , 0x01FB6 }, + { 0x003B1 , 0x00345 , 0x01FB3 }, + { 0x003B5 , 0x00300 , 0x01F72 }, + { 0x003B5 , 0x00301 , 0x003AD }, + { 0x003B5 , 0x00313 , 0x01F10 }, + { 0x003B5 , 0x00314 , 0x01F11 }, + { 0x003B7 , 0x00300 , 0x01F74 }, + { 0x003B7 , 0x00301 , 0x003AE }, + { 0x003B7 , 0x00313 , 0x01F20 }, + { 0x003B7 , 0x00314 , 0x01F21 }, + { 0x003B7 , 0x00342 , 0x01FC6 }, + { 0x003B7 , 0x00345 , 0x01FC3 }, + { 0x003B9 , 0x00300 , 0x01F76 }, + { 0x003B9 , 0x00301 , 0x003AF }, + { 0x003B9 , 0x00304 , 0x01FD1 }, + { 0x003B9 , 0x00306 , 0x01FD0 }, + { 0x003B9 , 0x00308 , 0x003CA }, + { 0x003B9 , 0x00313 , 0x01F30 }, + { 0x003B9 , 0x00314 , 0x01F31 }, + { 0x003B9 , 0x00342 , 0x01FD6 }, + { 0x003BF , 0x00300 , 0x01F78 }, + { 0x003BF , 0x00301 , 0x003CC }, + { 0x003BF , 0x00313 , 0x01F40 }, + { 0x003BF , 0x00314 , 0x01F41 }, + { 0x003C1 , 0x00313 , 0x01FE4 }, + { 0x003C1 , 0x00314 , 0x01FE5 }, + { 0x003C5 , 0x00300 , 0x01F7A }, + { 0x003C5 , 0x00301 , 0x003CD }, + { 0x003C5 , 0x00304 , 0x01FE1 }, + { 0x003C5 , 0x00306 , 0x01FE0 }, + { 0x003C5 , 0x00308 , 0x003CB }, + { 0x003C5 , 0x00313 , 0x01F50 }, + { 0x003C5 , 0x00314 , 0x01F51 }, + { 0x003C5 , 0x00342 , 0x01FE6 }, + { 0x003C9 , 0x00300 , 0x01F7C }, + { 0x003C9 , 0x00301 , 0x003CE }, + { 0x003C9 , 0x00313 , 0x01F60 }, + { 0x003C9 , 0x00314 , 0x01F61 }, + { 0x003C9 , 0x00342 , 0x01FF6 }, + { 0x003C9 , 0x00345 , 0x01FF3 }, + { 0x003CA , 0x00300 , 0x01FD2 }, + { 0x003CA , 0x00301 , 0x00390 }, + { 0x003CA , 0x00342 , 0x01FD7 }, + { 0x003CB , 0x00300 , 0x01FE2 }, + { 0x003CB , 0x00301 , 0x003B0 }, + { 0x003CB , 0x00342 , 0x01FE7 }, + { 0x003CE , 0x00345 , 0x01FF4 }, + { 0x003D2 , 0x00301 , 0x003D3 }, + { 0x003D2 , 0x00308 , 0x003D4 }, + { 0x00406 , 0x00308 , 0x00407 }, + { 0x00410 , 0x00306 , 0x004D0 }, + { 0x00410 , 0x00308 , 0x004D2 }, + { 0x00413 , 0x00301 , 0x00403 }, + { 0x00415 , 0x00300 , 0x00400 }, + { 0x00415 , 0x00306 , 0x004D6 }, + { 0x00415 , 0x00308 , 0x00401 }, + { 0x00416 , 0x00306 , 0x004C1 }, + { 0x00416 , 0x00308 , 0x004DC }, + { 0x00417 , 0x00308 , 0x004DE }, + { 0x00418 , 0x00300 , 0x0040D }, + { 0x00418 , 0x00304 , 0x004E2 }, + { 0x00418 , 0x00306 , 0x00419 }, + { 0x00418 , 0x00308 , 0x004E4 }, + { 0x0041A , 0x00301 , 0x0040C }, + { 0x0041E , 0x00308 , 0x004E6 }, + { 0x00423 , 0x00304 , 0x004EE }, + { 0x00423 , 0x00306 , 0x0040E }, + { 0x00423 , 0x00308 , 0x004F0 }, + { 0x00423 , 0x0030B , 0x004F2 }, + { 0x00427 , 0x00308 , 0x004F4 }, + { 0x0042B , 0x00308 , 0x004F8 }, + { 0x0042D , 0x00308 , 0x004EC }, + { 0x00430 , 0x00306 , 0x004D1 }, + { 0x00430 , 0x00308 , 0x004D3 }, + { 0x00433 , 0x00301 , 0x00453 }, + { 0x00435 , 0x00300 , 0x00450 }, + { 0x00435 , 0x00306 , 0x004D7 }, + { 0x00435 , 0x00308 , 0x00451 }, + { 0x00436 , 0x00306 , 0x004C2 }, + { 0x00436 , 0x00308 , 0x004DD }, + { 0x00437 , 0x00308 , 0x004DF }, + { 0x00438 , 0x00300 , 0x0045D }, + { 0x00438 , 0x00304 , 0x004E3 }, + { 0x00438 , 0x00306 , 0x00439 }, + { 0x00438 , 0x00308 , 0x004E5 }, + { 0x0043A , 0x00301 , 0x0045C }, + { 0x0043E , 0x00308 , 0x004E7 }, + { 0x00443 , 0x00304 , 0x004EF }, + { 0x00443 , 0x00306 , 0x0045E }, + { 0x00443 , 0x00308 , 0x004F1 }, + { 0x00443 , 0x0030B , 0x004F3 }, + { 0x00447 , 0x00308 , 0x004F5 }, + { 0x0044B , 0x00308 , 0x004F9 }, + { 0x0044D , 0x00308 , 0x004ED }, + { 0x00456 , 0x00308 , 0x00457 }, + { 0x00474 , 0x0030F , 0x00476 }, + { 0x00475 , 0x0030F , 0x00477 }, + { 0x004D8 , 0x00308 , 0x004DA }, + { 0x004D9 , 0x00308 , 0x004DB }, + { 0x004E8 , 0x00308 , 0x004EA }, + { 0x004E9 , 0x00308 , 0x004EB }, + { 0x00627 , 0x00653 , 0x00622 }, + { 0x00627 , 0x00654 , 0x00623 }, + { 0x00627 , 0x00655 , 0x00625 }, + { 0x00648 , 0x00654 , 0x00624 }, + { 0x0064A , 0x00654 , 0x00626 }, + { 0x006C1 , 0x00654 , 0x006C2 }, + { 0x006D2 , 0x00654 , 0x006D3 }, + { 0x006D5 , 0x00654 , 0x006C0 }, + { 0x00928 , 0x0093C , 0x00929 }, + { 0x00930 , 0x0093C , 0x00931 }, + { 0x00933 , 0x0093C , 0x00934 }, + { 0x009C7 , 0x009BE , 0x009CB }, + { 0x009C7 , 0x009D7 , 0x009CC }, + { 0x00B47 , 0x00B3E , 0x00B4B }, + { 0x00B47 , 0x00B56 , 0x00B48 }, + { 0x00B47 , 0x00B57 , 0x00B4C }, + { 0x00B92 , 0x00BD7 , 0x00B94 }, + { 0x00BC6 , 0x00BBE , 0x00BCA }, + { 0x00BC6 , 0x00BD7 , 0x00BCC }, + { 0x00BC7 , 0x00BBE , 0x00BCB }, + { 0x00C46 , 0x00C56 , 0x00C48 }, + { 0x00CBF , 0x00CD5 , 0x00CC0 }, + { 0x00CC6 , 0x00CC2 , 0x00CCA }, + { 0x00CC6 , 0x00CD5 , 0x00CC7 }, + { 0x00CC6 , 0x00CD6 , 0x00CC8 }, + { 0x00CCA , 0x00CD5 , 0x00CCB }, + { 0x00D46 , 0x00D3E , 0x00D4A }, + { 0x00D46 , 0x00D57 , 0x00D4C }, + { 0x00D47 , 0x00D3E , 0x00D4B }, + { 0x00DD9 , 0x00DCA , 0x00DDA }, + { 0x00DD9 , 0x00DCF , 0x00DDC }, + { 0x00DD9 , 0x00DDF , 0x00DDE }, + { 0x00DDC , 0x00DCA , 0x00DDD }, + { 0x01025 , 0x0102E , 0x01026 }, + { 0x01B05 , 0x01B35 , 0x01B06 }, + { 0x01B07 , 0x01B35 , 0x01B08 }, + { 0x01B09 , 0x01B35 , 0x01B0A }, + { 0x01B0B , 0x01B35 , 0x01B0C }, + { 0x01B0D , 0x01B35 , 0x01B0E }, + { 0x01B11 , 0x01B35 , 0x01B12 }, + { 0x01B3A , 0x01B35 , 0x01B3B }, + { 0x01B3C , 0x01B35 , 0x01B3D }, + { 0x01B3E , 0x01B35 , 0x01B40 }, + { 0x01B3F , 0x01B35 , 0x01B41 }, + { 0x01B42 , 0x01B35 , 0x01B43 }, + { 0x01E36 , 0x00304 , 0x01E38 }, + { 0x01E37 , 0x00304 , 0x01E39 }, + { 0x01E5A , 0x00304 , 0x01E5C }, + { 0x01E5B , 0x00304 , 0x01E5D }, + { 0x01E62 , 0x00307 , 0x01E68 }, + { 0x01E63 , 0x00307 , 0x01E69 }, + { 0x01EA0 , 0x00302 , 0x01EAC }, + { 0x01EA0 , 0x00306 , 0x01EB6 }, + { 0x01EA1 , 0x00302 , 0x01EAD }, + { 0x01EA1 , 0x00306 , 0x01EB7 }, + { 0x01EB8 , 0x00302 , 0x01EC6 }, + { 0x01EB9 , 0x00302 , 0x01EC7 }, + { 0x01ECC , 0x00302 , 0x01ED8 }, + { 0x01ECD , 0x00302 , 0x01ED9 }, + { 0x01F00 , 0x00300 , 0x01F02 }, + { 0x01F00 , 0x00301 , 0x01F04 }, + { 0x01F00 , 0x00342 , 0x01F06 }, + { 0x01F00 , 0x00345 , 0x01F80 }, + { 0x01F01 , 0x00300 , 0x01F03 }, + { 0x01F01 , 0x00301 , 0x01F05 }, + { 0x01F01 , 0x00342 , 0x01F07 }, + { 0x01F01 , 0x00345 , 0x01F81 }, + { 0x01F02 , 0x00345 , 0x01F82 }, + { 0x01F03 , 0x00345 , 0x01F83 }, + { 0x01F04 , 0x00345 , 0x01F84 }, + { 0x01F05 , 0x00345 , 0x01F85 }, + { 0x01F06 , 0x00345 , 0x01F86 }, + { 0x01F07 , 0x00345 , 0x01F87 }, + { 0x01F08 , 0x00300 , 0x01F0A }, + { 0x01F08 , 0x00301 , 0x01F0C }, + { 0x01F08 , 0x00342 , 0x01F0E }, + { 0x01F08 , 0x00345 , 0x01F88 }, + { 0x01F09 , 0x00300 , 0x01F0B }, + { 0x01F09 , 0x00301 , 0x01F0D }, + { 0x01F09 , 0x00342 , 0x01F0F }, + { 0x01F09 , 0x00345 , 0x01F89 }, + { 0x01F0A , 0x00345 , 0x01F8A }, + { 0x01F0B , 0x00345 , 0x01F8B }, + { 0x01F0C , 0x00345 , 0x01F8C }, + { 0x01F0D , 0x00345 , 0x01F8D }, + { 0x01F0E , 0x00345 , 0x01F8E }, + { 0x01F0F , 0x00345 , 0x01F8F }, + { 0x01F10 , 0x00300 , 0x01F12 }, + { 0x01F10 , 0x00301 , 0x01F14 }, + { 0x01F11 , 0x00300 , 0x01F13 }, + { 0x01F11 , 0x00301 , 0x01F15 }, + { 0x01F18 , 0x00300 , 0x01F1A }, + { 0x01F18 , 0x00301 , 0x01F1C }, + { 0x01F19 , 0x00300 , 0x01F1B }, + { 0x01F19 , 0x00301 , 0x01F1D }, + { 0x01F20 , 0x00300 , 0x01F22 }, + { 0x01F20 , 0x00301 , 0x01F24 }, + { 0x01F20 , 0x00342 , 0x01F26 }, + { 0x01F20 , 0x00345 , 0x01F90 }, + { 0x01F21 , 0x00300 , 0x01F23 }, + { 0x01F21 , 0x00301 , 0x01F25 }, + { 0x01F21 , 0x00342 , 0x01F27 }, + { 0x01F21 , 0x00345 , 0x01F91 }, + { 0x01F22 , 0x00345 , 0x01F92 }, + { 0x01F23 , 0x00345 , 0x01F93 }, + { 0x01F24 , 0x00345 , 0x01F94 }, + { 0x01F25 , 0x00345 , 0x01F95 }, + { 0x01F26 , 0x00345 , 0x01F96 }, + { 0x01F27 , 0x00345 , 0x01F97 }, + { 0x01F28 , 0x00300 , 0x01F2A }, + { 0x01F28 , 0x00301 , 0x01F2C }, + { 0x01F28 , 0x00342 , 0x01F2E }, + { 0x01F28 , 0x00345 , 0x01F98 }, + { 0x01F29 , 0x00300 , 0x01F2B }, + { 0x01F29 , 0x00301 , 0x01F2D }, + { 0x01F29 , 0x00342 , 0x01F2F }, + { 0x01F29 , 0x00345 , 0x01F99 }, + { 0x01F2A , 0x00345 , 0x01F9A }, + { 0x01F2B , 0x00345 , 0x01F9B }, + { 0x01F2C , 0x00345 , 0x01F9C }, + { 0x01F2D , 0x00345 , 0x01F9D }, + { 0x01F2E , 0x00345 , 0x01F9E }, + { 0x01F2F , 0x00345 , 0x01F9F }, + { 0x01F30 , 0x00300 , 0x01F32 }, + { 0x01F30 , 0x00301 , 0x01F34 }, + { 0x01F30 , 0x00342 , 0x01F36 }, + { 0x01F31 , 0x00300 , 0x01F33 }, + { 0x01F31 , 0x00301 , 0x01F35 }, + { 0x01F31 , 0x00342 , 0x01F37 }, + { 0x01F38 , 0x00300 , 0x01F3A }, + { 0x01F38 , 0x00301 , 0x01F3C }, + { 0x01F38 , 0x00342 , 0x01F3E }, + { 0x01F39 , 0x00300 , 0x01F3B }, + { 0x01F39 , 0x00301 , 0x01F3D }, + { 0x01F39 , 0x00342 , 0x01F3F }, + { 0x01F40 , 0x00300 , 0x01F42 }, + { 0x01F40 , 0x00301 , 0x01F44 }, + { 0x01F41 , 0x00300 , 0x01F43 }, + { 0x01F41 , 0x00301 , 0x01F45 }, + { 0x01F48 , 0x00300 , 0x01F4A }, + { 0x01F48 , 0x00301 , 0x01F4C }, + { 0x01F49 , 0x00300 , 0x01F4B }, + { 0x01F49 , 0x00301 , 0x01F4D }, + { 0x01F50 , 0x00300 , 0x01F52 }, + { 0x01F50 , 0x00301 , 0x01F54 }, + { 0x01F50 , 0x00342 , 0x01F56 }, + { 0x01F51 , 0x00300 , 0x01F53 }, + { 0x01F51 , 0x00301 , 0x01F55 }, + { 0x01F51 , 0x00342 , 0x01F57 }, + { 0x01F59 , 0x00300 , 0x01F5B }, + { 0x01F59 , 0x00301 , 0x01F5D }, + { 0x01F59 , 0x00342 , 0x01F5F }, + { 0x01F60 , 0x00300 , 0x01F62 }, + { 0x01F60 , 0x00301 , 0x01F64 }, + { 0x01F60 , 0x00342 , 0x01F66 }, + { 0x01F60 , 0x00345 , 0x01FA0 }, + { 0x01F61 , 0x00300 , 0x01F63 }, + { 0x01F61 , 0x00301 , 0x01F65 }, + { 0x01F61 , 0x00342 , 0x01F67 }, + { 0x01F61 , 0x00345 , 0x01FA1 }, + { 0x01F62 , 0x00345 , 0x01FA2 }, + { 0x01F63 , 0x00345 , 0x01FA3 }, + { 0x01F64 , 0x00345 , 0x01FA4 }, + { 0x01F65 , 0x00345 , 0x01FA5 }, + { 0x01F66 , 0x00345 , 0x01FA6 }, + { 0x01F67 , 0x00345 , 0x01FA7 }, + { 0x01F68 , 0x00300 , 0x01F6A }, + { 0x01F68 , 0x00301 , 0x01F6C }, + { 0x01F68 , 0x00342 , 0x01F6E }, + { 0x01F68 , 0x00345 , 0x01FA8 }, + { 0x01F69 , 0x00300 , 0x01F6B }, + { 0x01F69 , 0x00301 , 0x01F6D }, + { 0x01F69 , 0x00342 , 0x01F6F }, + { 0x01F69 , 0x00345 , 0x01FA9 }, + { 0x01F6A , 0x00345 , 0x01FAA }, + { 0x01F6B , 0x00345 , 0x01FAB }, + { 0x01F6C , 0x00345 , 0x01FAC }, + { 0x01F6D , 0x00345 , 0x01FAD }, + { 0x01F6E , 0x00345 , 0x01FAE }, + { 0x01F6F , 0x00345 , 0x01FAF }, + { 0x01F70 , 0x00345 , 0x01FB2 }, + { 0x01F74 , 0x00345 , 0x01FC2 }, + { 0x01F7C , 0x00345 , 0x01FF2 }, + { 0x01FB6 , 0x00345 , 0x01FB7 }, + { 0x01FBF , 0x00300 , 0x01FCD }, + { 0x01FBF , 0x00301 , 0x01FCE }, + { 0x01FBF , 0x00342 , 0x01FCF }, + { 0x01FC6 , 0x00345 , 0x01FC7 }, + { 0x01FF6 , 0x00345 , 0x01FF7 }, + { 0x01FFE , 0x00300 , 0x01FDD }, + { 0x01FFE , 0x00301 , 0x01FDE }, + { 0x01FFE , 0x00342 , 0x01FDF }, + { 0x02190 , 0x00338 , 0x0219A }, + { 0x02192 , 0x00338 , 0x0219B }, + { 0x02194 , 0x00338 , 0x021AE }, + { 0x021D0 , 0x00338 , 0x021CD }, + { 0x021D2 , 0x00338 , 0x021CF }, + { 0x021D4 , 0x00338 , 0x021CE }, + { 0x02203 , 0x00338 , 0x02204 }, + { 0x02208 , 0x00338 , 0x02209 }, + { 0x0220B , 0x00338 , 0x0220C }, + { 0x02223 , 0x00338 , 0x02224 }, + { 0x02225 , 0x00338 , 0x02226 }, + { 0x0223C , 0x00338 , 0x02241 }, + { 0x02243 , 0x00338 , 0x02244 }, + { 0x02245 , 0x00338 , 0x02247 }, + { 0x02248 , 0x00338 , 0x02249 }, + { 0x0224D , 0x00338 , 0x0226D }, + { 0x02261 , 0x00338 , 0x02262 }, + { 0x02264 , 0x00338 , 0x02270 }, + { 0x02265 , 0x00338 , 0x02271 }, + { 0x02272 , 0x00338 , 0x02274 }, + { 0x02273 , 0x00338 , 0x02275 }, + { 0x02276 , 0x00338 , 0x02278 }, + { 0x02277 , 0x00338 , 0x02279 }, + { 0x0227A , 0x00338 , 0x02280 }, + { 0x0227B , 0x00338 , 0x02281 }, + { 0x0227C , 0x00338 , 0x022E0 }, + { 0x0227D , 0x00338 , 0x022E1 }, + { 0x02282 , 0x00338 , 0x02284 }, + { 0x02283 , 0x00338 , 0x02285 }, + { 0x02286 , 0x00338 , 0x02288 }, + { 0x02287 , 0x00338 , 0x02289 }, + { 0x02291 , 0x00338 , 0x022E2 }, + { 0x02292 , 0x00338 , 0x022E3 }, + { 0x022A2 , 0x00338 , 0x022AC }, + { 0x022A8 , 0x00338 , 0x022AD }, + { 0x022A9 , 0x00338 , 0x022AE }, + { 0x022AB , 0x00338 , 0x022AF }, + { 0x022B2 , 0x00338 , 0x022EA }, + { 0x022B3 , 0x00338 , 0x022EB }, + { 0x022B4 , 0x00338 , 0x022EC }, + { 0x022B5 , 0x00338 , 0x022ED }, + { 0x03046 , 0x03099 , 0x03094 }, + { 0x0304B , 0x03099 , 0x0304C }, + { 0x0304D , 0x03099 , 0x0304E }, + { 0x0304F , 0x03099 , 0x03050 }, + { 0x03051 , 0x03099 , 0x03052 }, + { 0x03053 , 0x03099 , 0x03054 }, + { 0x03055 , 0x03099 , 0x03056 }, + { 0x03057 , 0x03099 , 0x03058 }, + { 0x03059 , 0x03099 , 0x0305A }, + { 0x0305B , 0x03099 , 0x0305C }, + { 0x0305D , 0x03099 , 0x0305E }, + { 0x0305F , 0x03099 , 0x03060 }, + { 0x03061 , 0x03099 , 0x03062 }, + { 0x03064 , 0x03099 , 0x03065 }, + { 0x03066 , 0x03099 , 0x03067 }, + { 0x03068 , 0x03099 , 0x03069 }, + { 0x0306F , 0x03099 , 0x03070 }, + { 0x0306F , 0x0309A , 0x03071 }, + { 0x03072 , 0x03099 , 0x03073 }, + { 0x03072 , 0x0309A , 0x03074 }, + { 0x03075 , 0x03099 , 0x03076 }, + { 0x03075 , 0x0309A , 0x03077 }, + { 0x03078 , 0x03099 , 0x03079 }, + { 0x03078 , 0x0309A , 0x0307A }, + { 0x0307B , 0x03099 , 0x0307C }, + { 0x0307B , 0x0309A , 0x0307D }, + { 0x0309D , 0x03099 , 0x0309E }, + { 0x030A6 , 0x03099 , 0x030F4 }, + { 0x030AB , 0x03099 , 0x030AC }, + { 0x030AD , 0x03099 , 0x030AE }, + { 0x030AF , 0x03099 , 0x030B0 }, + { 0x030B1 , 0x03099 , 0x030B2 }, + { 0x030B3 , 0x03099 , 0x030B4 }, + { 0x030B5 , 0x03099 , 0x030B6 }, + { 0x030B7 , 0x03099 , 0x030B8 }, + { 0x030B9 , 0x03099 , 0x030BA }, + { 0x030BB , 0x03099 , 0x030BC }, + { 0x030BD , 0x03099 , 0x030BE }, + { 0x030BF , 0x03099 , 0x030C0 }, + { 0x030C1 , 0x03099 , 0x030C2 }, + { 0x030C4 , 0x03099 , 0x030C5 }, + { 0x030C6 , 0x03099 , 0x030C7 }, + { 0x030C8 , 0x03099 , 0x030C9 }, + { 0x030CF , 0x03099 , 0x030D0 }, + { 0x030CF , 0x0309A , 0x030D1 }, + { 0x030D2 , 0x03099 , 0x030D3 }, + { 0x030D2 , 0x0309A , 0x030D4 }, + { 0x030D5 , 0x03099 , 0x030D6 }, + { 0x030D5 , 0x0309A , 0x030D7 }, + { 0x030D8 , 0x03099 , 0x030D9 }, + { 0x030D8 , 0x0309A , 0x030DA }, + { 0x030DB , 0x03099 , 0x030DC }, + { 0x030DB , 0x0309A , 0x030DD }, + { 0x030EF , 0x03099 , 0x030F7 }, + { 0x030F0 , 0x03099 , 0x030F8 }, + { 0x030F1 , 0x03099 , 0x030F9 }, + { 0x030F2 , 0x03099 , 0x030FA }, + { 0x030FD , 0x03099 , 0x030FE }, + { 0x11099 , 0x110BA , 0x1109A }, + { 0x1109B , 0x110BA , 0x1109C }, + { 0x110A5 , 0x110BA , 0x110AB }, +}; + +#define CANONICAL_CLASS_MIN 0x0300 +#define CANONICAL_CLASS_MAX 0x1D244 + +#define IS_DECOMPOSABLE_BLOCK(uc) \ + (((uc)>>8) <= 0x1D2 && u_decomposable_blocks[(uc)>>8]) +static const char u_decomposable_blocks[0x1D2+1] = { + 0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,1,1,1,1,1,1,1,0,0, + 1,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0, + 0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1, +}; + +/* Get Canonical Combining Class(CCC). */ +#define CCC(uc) \ + (((uc) > 0x1D244)?0:\ + ccc_val[ccc_val_index[ccc_index[(uc)>>8]][((uc)>>4)&0x0F]][(uc)&0x0F]) + +/* The table of the value of Canonical Combining Class */ +static const unsigned char ccc_val[][16] = { + /* idx=0: XXXX0 - XXXXF */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=1: 00300 - 0030F */ + {230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230 }, + /* idx=2: 00310 - 0031F */ + {230, 230, 230, 230, 230, 232, 220, 220, 220, 220, 232, 216, 220, 220, 220, 220 }, + /* idx=3: 00320 - 0032F */ + {220, 202, 202, 220, 220, 220, 220, 202, 202, 220, 220, 220, 220, 220, 220, 220 }, + /* idx=4: 00330 - 0033F */ + {220, 220, 220, 220, 1, 1, 1, 1, 1, 220, 220, 220, 220, 230, 230, 230 }, + /* idx=5: 00340 - 0034F */ + {230, 230, 230, 230, 230, 240, 230, 220, 220, 220, 230, 230, 230, 220, 220, 0 }, + /* idx=6: 00350 - 0035F */ + {230, 230, 230, 220, 220, 220, 220, 230, 232, 220, 220, 230, 233, 234, 234, 233 }, + /* idx=7: 00360 - 0036F */ + {234, 234, 233, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230 }, + /* idx=8: 00480 - 0048F */ + {0, 0, 0, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=9: 00590 - 0059F */ + {0, 220, 230, 230, 230, 230, 220, 230, 230, 230, 222, 220, 230, 230, 230, 230 }, + /* idx=10: 005A0 - 005AF */ + {230, 230, 220, 220, 220, 220, 220, 220, 230, 230, 220, 230, 230, 222, 228, 230 }, + /* idx=11: 005B0 - 005BF */ + {10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 0, 23 }, + /* idx=12: 005C0 - 005CF */ + {0, 24, 25, 0, 230, 220, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=13: 00610 - 0061F */ + {230, 230, 230, 230, 230, 230, 230, 230, 30, 31, 32, 0, 0, 0, 0, 0 }, + /* idx=14: 00640 - 0064F */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 28, 29, 30, 31 }, + /* idx=15: 00650 - 0065F */ + {32, 33, 34, 230, 230, 220, 220, 230, 230, 230, 230, 230, 220, 230, 230, 220 }, + /* idx=16: 00670 - 0067F */ + {35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=17: 006D0 - 006DF */ + {0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 230, 0, 0, 230 }, + /* idx=18: 006E0 - 006EF */ + {230, 230, 230, 220, 230, 0, 0, 230, 230, 0, 220, 230, 230, 220, 0, 0 }, + /* idx=19: 00710 - 0071F */ + {0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=20: 00730 - 0073F */ + {230, 220, 230, 230, 220, 230, 230, 220, 220, 220, 230, 220, 220, 230, 220, 230 }, + /* idx=21: 00740 - 0074F */ + {230, 230, 220, 230, 220, 230, 220, 230, 220, 230, 230, 0, 0, 0, 0, 0 }, + /* idx=22: 007E0 - 007EF */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230 }, + /* idx=23: 007F0 - 007FF */ + {230, 230, 220, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=24: 00810 - 0081F */ + {0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 0, 230, 230, 230, 230, 230 }, + /* idx=25: 00820 - 0082F */ + {230, 230, 230, 230, 0, 230, 230, 230, 0, 230, 230, 230, 230, 230, 0, 0 }, + /* idx=26: 00850 - 0085F */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220, 0, 0, 0, 0 }, + /* idx=27: 00930 - 0093F */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0 }, + /* idx=28: 00940 - 0094F */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0 }, + /* idx=29: 00950 - 0095F */ + {0, 230, 220, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=30: 009B0 - 009BF */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0 }, + /* idx=31: 009C0 - 009CF */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0 }, + /* idx=32: 00A30 - 00A3F */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0 }, + /* idx=33: 00A40 - 00A4F */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0 }, + /* idx=34: 00AB0 - 00ABF */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0 }, + /* idx=35: 00AC0 - 00ACF */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0 }, + /* idx=36: 00B30 - 00B3F */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0 }, + /* idx=37: 00B40 - 00B4F */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0 }, + /* idx=38: 00BC0 - 00BCF */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0 }, + /* idx=39: 00C40 - 00C4F */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0 }, + /* idx=40: 00C50 - 00C5F */ + {0, 0, 0, 0, 0, 84, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=41: 00CB0 - 00CBF */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0 }, + /* idx=42: 00CC0 - 00CCF */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0 }, + /* idx=43: 00D40 - 00D4F */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0 }, + /* idx=44: 00DC0 - 00DCF */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0 }, + /* idx=45: 00E30 - 00E3F */ + {0, 0, 0, 0, 0, 0, 0, 0, 103, 103, 9, 0, 0, 0, 0, 0 }, + /* idx=46: 00E40 - 00E4F */ + {0, 0, 0, 0, 0, 0, 0, 0, 107, 107, 107, 107, 0, 0, 0, 0 }, + /* idx=47: 00EB0 - 00EBF */ + {0, 0, 0, 0, 0, 0, 0, 0, 118, 118, 0, 0, 0, 0, 0, 0 }, + /* idx=48: 00EC0 - 00ECF */ + {0, 0, 0, 0, 0, 0, 0, 0, 122, 122, 122, 122, 0, 0, 0, 0 }, + /* idx=49: 00F10 - 00F1F */ + {0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 0, 0, 0, 0, 0, 0 }, + /* idx=50: 00F30 - 00F3F */ + {0, 0, 0, 0, 0, 220, 0, 220, 0, 216, 0, 0, 0, 0, 0, 0 }, + /* idx=51: 00F70 - 00F7F */ + {0, 129, 130, 0, 132, 0, 0, 0, 0, 0, 130, 130, 130, 130, 0, 0 }, + /* idx=52: 00F80 - 00F8F */ + {130, 0, 230, 230, 9, 0, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=53: 00FC0 - 00FCF */ + {0, 0, 0, 0, 0, 0, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=54: 01030 - 0103F */ + {0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 0, 0, 0, 0, 0 }, + /* idx=55: 01080 - 0108F */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0 }, + /* idx=56: 01350 - 0135F */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230 }, + /* idx=57: 01710 - 0171F */ + {0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=58: 01730 - 0173F */ + {0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=59: 017D0 - 017DF */ + {0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0, 0 }, + /* idx=60: 018A0 - 018AF */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 0, 0, 0, 0, 0, 0 }, + /* idx=61: 01930 - 0193F */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 230, 220, 0, 0, 0, 0 }, + /* idx=62: 01A10 - 01A1F */ + {0, 0, 0, 0, 0, 0, 0, 230, 220, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=63: 01A60 - 01A6F */ + {9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=64: 01A70 - 01A7F */ + {0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 230, 230, 0, 0, 220 }, + /* idx=65: 01B30 - 01B3F */ + {0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=66: 01B40 - 01B4F */ + {0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=67: 01B60 - 01B6F */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 220, 230, 230, 230 }, + /* idx=68: 01B70 - 01B7F */ + {230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=69: 01BA0 - 01BAF */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0 }, + /* idx=70: 01BE0 - 01BEF */ + {0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=71: 01BF0 - 01BFF */ + {0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=72: 01C30 - 01C3F */ + {0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=73: 01CD0 - 01CDF */ + {230, 230, 230, 0, 1, 220, 220, 220, 220, 220, 230, 230, 220, 220, 220, 220 }, + /* idx=74: 01CE0 - 01CEF */ + {230, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 220, 0, 0 }, + /* idx=75: 01DC0 - 01DCF */ + {230, 230, 220, 230, 230, 230, 230, 230, 230, 230, 220, 230, 230, 234, 214, 220 }, + /* idx=76: 01DD0 - 01DDF */ + {202, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230 }, + /* idx=77: 01DE0 - 01DEF */ + {230, 230, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=78: 01DF0 - 01DFF */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 220, 230, 220 }, + /* idx=79: 020D0 - 020DF */ + {230, 230, 1, 1, 230, 230, 230, 230, 1, 1, 1, 230, 230, 0, 0, 0 }, + /* idx=80: 020E0 - 020EF */ + {0, 230, 0, 0, 0, 1, 1, 230, 220, 230, 1, 1, 220, 220, 220, 220 }, + /* idx=81: 020F0 - 020FF */ + {230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=82: 02CE0 - 02CEF */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230 }, + /* idx=83: 02CF0 - 02CFF */ + {230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=84: 02D70 - 02D7F */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 }, + /* idx=85: 02DE0 - 02DEF */ + {230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230 }, + /* idx=86: 02DF0 - 02DFF */ + {230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230 }, + /* idx=87: 03020 - 0302F */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 228, 232, 222, 224, 224 }, + /* idx=88: 03090 - 0309F */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0 }, + /* idx=89: 0A660 - 0A66F */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230 }, + /* idx=90: 0A670 - 0A67F */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 0, 0 }, + /* idx=91: 0A6F0 - 0A6FF */ + {230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=92: 0A800 - 0A80F */ + {0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=93: 0A8C0 - 0A8CF */ + {0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=94: 0A8E0 - 0A8EF */ + {230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230 }, + /* idx=95: 0A8F0 - 0A8FF */ + {230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=96: 0A920 - 0A92F */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220, 0, 0 }, + /* idx=97: 0A950 - 0A95F */ + {0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=98: 0A9B0 - 0A9BF */ + {0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=99: 0A9C0 - 0A9CF */ + {9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=100: 0AAB0 - 0AABF */ + {230, 0, 230, 230, 220, 0, 0, 230, 230, 0, 0, 0, 0, 0, 230, 230 }, + /* idx=101: 0AAC0 - 0AACF */ + {0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=102: 0ABE0 - 0ABEF */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0 }, + /* idx=103: 0FB10 - 0FB1F */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0 }, + /* idx=104: 0FE20 - 0FE2F */ + {230, 230, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=105: 101F0 - 101FF */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0 }, + /* idx=106: 10A00 - 10A0F */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 230 }, + /* idx=107: 10A30 - 10A3F */ + {0, 0, 0, 0, 0, 0, 0, 0, 230, 1, 220, 0, 0, 0, 0, 9 }, + /* idx=108: 11040 - 1104F */ + {0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=109: 110B0 - 110BF */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0 }, + /* idx=110: 1D160 - 1D16F */ + {0, 0, 0, 0, 0, 216, 216, 1, 1, 1, 0, 0, 0, 226, 216, 216 }, + /* idx=111: 1D170 - 1D17F */ + {216, 216, 216, 0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220, 220, 220 }, + /* idx=112: 1D180 - 1D18F */ + {220, 220, 220, 0, 0, 230, 230, 230, 230, 230, 220, 220, 0, 0, 0, 0 }, + /* idx=113: 1D1A0 - 1D1AF */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 0, 0 }, + /* idx=114: 1D240 - 1D24F */ + {0, 0, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, +}; + +/* The index table to ccc_val[*][16] */ +static const unsigned char ccc_val_index[][16] = { + /* idx=0: XXX00 - XXXFF */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=1: 00300 - 003FF */ + { 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=2: 00400 - 004FF */ + { 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=3: 00500 - 005FF */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,10,11,12, 0, 0, 0 }, + /* idx=4: 00600 - 006FF */ + { 0,13, 0, 0,14,15, 0,16, 0, 0, 0, 0, 0,17,18, 0 }, + /* idx=5: 00700 - 007FF */ + { 0,19, 0,20,21, 0, 0, 0, 0, 0, 0, 0, 0, 0,22,23 }, + /* idx=6: 00800 - 008FF */ + { 0,24,25, 0, 0,26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=7: 00900 - 009FF */ + { 0, 0, 0,27,28,29, 0, 0, 0, 0, 0,30,31, 0, 0, 0 }, + /* idx=8: 00A00 - 00AFF */ + { 0, 0, 0,32,33, 0, 0, 0, 0, 0, 0,34,35, 0, 0, 0 }, + /* idx=9: 00B00 - 00BFF */ + { 0, 0, 0,36,37, 0, 0, 0, 0, 0, 0, 0,38, 0, 0, 0 }, + /* idx=10: 00C00 - 00CFF */ + { 0, 0, 0, 0,39,40, 0, 0, 0, 0, 0,41,42, 0, 0, 0 }, + /* idx=11: 00D00 - 00DFF */ + { 0, 0, 0, 0,43, 0, 0, 0, 0, 0, 0, 0,44, 0, 0, 0 }, + /* idx=12: 00E00 - 00EFF */ + { 0, 0, 0,45,46, 0, 0, 0, 0, 0, 0,47,48, 0, 0, 0 }, + /* idx=13: 00F00 - 00FFF */ + { 0,49, 0,50, 0, 0, 0,51,52, 0, 0, 0,53, 0, 0, 0 }, + /* idx=14: 01000 - 010FF */ + { 0, 0, 0,54, 0, 0, 0, 0,55, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=15: 01300 - 013FF */ + { 0, 0, 0, 0, 0,56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=16: 01700 - 017FF */ + { 0,57, 0,58, 0, 0, 0, 0, 0, 0, 0, 0, 0,59, 0, 0 }, + /* idx=17: 01800 - 018FF */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,60, 0, 0, 0, 0, 0 }, + /* idx=18: 01900 - 019FF */ + { 0, 0, 0,61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=19: 01A00 - 01AFF */ + { 0,62, 0, 0, 0, 0,63,64, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=20: 01B00 - 01BFF */ + { 0, 0, 0,65,66, 0,67,68, 0, 0,69, 0, 0, 0,70,71 }, + /* idx=21: 01C00 - 01CFF */ + { 0, 0, 0,72, 0, 0, 0, 0, 0, 0, 0, 0, 0,73,74, 0 }, + /* idx=22: 01D00 - 01DFF */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,75,76,77,78 }, + /* idx=23: 02000 - 020FF */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,79,80,81 }, + /* idx=24: 02C00 - 02CFF */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,82,83 }, + /* idx=25: 02D00 - 02DFF */ + { 0, 0, 0, 0, 0, 0, 0,84, 0, 0, 0, 0, 0, 0,85,86 }, + /* idx=26: 03000 - 030FF */ + { 0, 0,87, 0, 0, 0, 0, 0, 0,88, 0, 0, 0, 0, 0, 0 }, + /* idx=27: 0A600 - 0A6FF */ + { 0, 0, 0, 0, 0, 0,89,90, 0, 0, 0, 0, 0, 0, 0,91 }, + /* idx=28: 0A800 - 0A8FF */ + {92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,93, 0,94,95 }, + /* idx=29: 0A900 - 0A9FF */ + { 0, 0,96, 0, 0,97, 0, 0, 0, 0, 0,98,99, 0, 0, 0 }, + /* idx=30: 0AA00 - 0AAFF */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,100,101, 0, 0, 0 }, + /* idx=31: 0AB00 - 0ABFF */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,102, 0 }, + /* idx=32: 0FB00 - 0FBFF */ + { 0,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=33: 0FE00 - 0FEFF */ + { 0, 0,104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=34: 10100 - 101FF */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105 }, + /* idx=35: 10A00 - 10AFF */ + {106, 0, 0,107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* idx=36: 11000 - 110FF */ + { 0, 0, 0, 0,108, 0, 0, 0, 0, 0, 0,109, 0, 0, 0, 0 }, + /* idx=37: 1D100 - 1D1FF */ + { 0, 0, 0, 0, 0, 0,110,111,112, 0,113, 0, 0, 0, 0, 0 }, + /* idx=38: 1D200 - 1D2FF */ + { 0, 0, 0, 0,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, +}; + +/* The index table to ccc_val_index[*][16] */ +static const unsigned char ccc_index[] = { + 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, 0, 0,15, 0, 0, 0,16, + 17,18,19,20,21,22, 0, 0,23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,24,25, 0, 0, + 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,27, 0, + 28,29,30,31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,32, 0, 0,33, 0, 0,34, 0, 0, 0, 0, 0, 0, + 0, 0,35, 0, 0, 0, 0, 0,36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,37,38,}; + +struct unicode_decomposition_table { + uint32_t nfc; + uint32_t cp1; + uint32_t cp2; +}; + +static const struct unicode_decomposition_table u_decomposition_table[] = { + { 0x000C0 , 0x00041 , 0x00300 }, + { 0x000C1 , 0x00041 , 0x00301 }, + { 0x000C2 , 0x00041 , 0x00302 }, + { 0x000C3 , 0x00041 , 0x00303 }, + { 0x000C4 , 0x00041 , 0x00308 }, + { 0x000C5 , 0x00041 , 0x0030A }, + { 0x000C7 , 0x00043 , 0x00327 }, + { 0x000C8 , 0x00045 , 0x00300 }, + { 0x000C9 , 0x00045 , 0x00301 }, + { 0x000CA , 0x00045 , 0x00302 }, + { 0x000CB , 0x00045 , 0x00308 }, + { 0x000CC , 0x00049 , 0x00300 }, + { 0x000CD , 0x00049 , 0x00301 }, + { 0x000CE , 0x00049 , 0x00302 }, + { 0x000CF , 0x00049 , 0x00308 }, + { 0x000D1 , 0x0004E , 0x00303 }, + { 0x000D2 , 0x0004F , 0x00300 }, + { 0x000D3 , 0x0004F , 0x00301 }, + { 0x000D4 , 0x0004F , 0x00302 }, + { 0x000D5 , 0x0004F , 0x00303 }, + { 0x000D6 , 0x0004F , 0x00308 }, + { 0x000D9 , 0x00055 , 0x00300 }, + { 0x000DA , 0x00055 , 0x00301 }, + { 0x000DB , 0x00055 , 0x00302 }, + { 0x000DC , 0x00055 , 0x00308 }, + { 0x000DD , 0x00059 , 0x00301 }, + { 0x000E0 , 0x00061 , 0x00300 }, + { 0x000E1 , 0x00061 , 0x00301 }, + { 0x000E2 , 0x00061 , 0x00302 }, + { 0x000E3 , 0x00061 , 0x00303 }, + { 0x000E4 , 0x00061 , 0x00308 }, + { 0x000E5 , 0x00061 , 0x0030A }, + { 0x000E7 , 0x00063 , 0x00327 }, + { 0x000E8 , 0x00065 , 0x00300 }, + { 0x000E9 , 0x00065 , 0x00301 }, + { 0x000EA , 0x00065 , 0x00302 }, + { 0x000EB , 0x00065 , 0x00308 }, + { 0x000EC , 0x00069 , 0x00300 }, + { 0x000ED , 0x00069 , 0x00301 }, + { 0x000EE , 0x00069 , 0x00302 }, + { 0x000EF , 0x00069 , 0x00308 }, + { 0x000F1 , 0x0006E , 0x00303 }, + { 0x000F2 , 0x0006F , 0x00300 }, + { 0x000F3 , 0x0006F , 0x00301 }, + { 0x000F4 , 0x0006F , 0x00302 }, + { 0x000F5 , 0x0006F , 0x00303 }, + { 0x000F6 , 0x0006F , 0x00308 }, + { 0x000F9 , 0x00075 , 0x00300 }, + { 0x000FA , 0x00075 , 0x00301 }, + { 0x000FB , 0x00075 , 0x00302 }, + { 0x000FC , 0x00075 , 0x00308 }, + { 0x000FD , 0x00079 , 0x00301 }, + { 0x000FF , 0x00079 , 0x00308 }, + { 0x00100 , 0x00041 , 0x00304 }, + { 0x00101 , 0x00061 , 0x00304 }, + { 0x00102 , 0x00041 , 0x00306 }, + { 0x00103 , 0x00061 , 0x00306 }, + { 0x00104 , 0x00041 , 0x00328 }, + { 0x00105 , 0x00061 , 0x00328 }, + { 0x00106 , 0x00043 , 0x00301 }, + { 0x00107 , 0x00063 , 0x00301 }, + { 0x00108 , 0x00043 , 0x00302 }, + { 0x00109 , 0x00063 , 0x00302 }, + { 0x0010A , 0x00043 , 0x00307 }, + { 0x0010B , 0x00063 , 0x00307 }, + { 0x0010C , 0x00043 , 0x0030C }, + { 0x0010D , 0x00063 , 0x0030C }, + { 0x0010E , 0x00044 , 0x0030C }, + { 0x0010F , 0x00064 , 0x0030C }, + { 0x00112 , 0x00045 , 0x00304 }, + { 0x00113 , 0x00065 , 0x00304 }, + { 0x00114 , 0x00045 , 0x00306 }, + { 0x00115 , 0x00065 , 0x00306 }, + { 0x00116 , 0x00045 , 0x00307 }, + { 0x00117 , 0x00065 , 0x00307 }, + { 0x00118 , 0x00045 , 0x00328 }, + { 0x00119 , 0x00065 , 0x00328 }, + { 0x0011A , 0x00045 , 0x0030C }, + { 0x0011B , 0x00065 , 0x0030C }, + { 0x0011C , 0x00047 , 0x00302 }, + { 0x0011D , 0x00067 , 0x00302 }, + { 0x0011E , 0x00047 , 0x00306 }, + { 0x0011F , 0x00067 , 0x00306 }, + { 0x00120 , 0x00047 , 0x00307 }, + { 0x00121 , 0x00067 , 0x00307 }, + { 0x00122 , 0x00047 , 0x00327 }, + { 0x00123 , 0x00067 , 0x00327 }, + { 0x00124 , 0x00048 , 0x00302 }, + { 0x00125 , 0x00068 , 0x00302 }, + { 0x00128 , 0x00049 , 0x00303 }, + { 0x00129 , 0x00069 , 0x00303 }, + { 0x0012A , 0x00049 , 0x00304 }, + { 0x0012B , 0x00069 , 0x00304 }, + { 0x0012C , 0x00049 , 0x00306 }, + { 0x0012D , 0x00069 , 0x00306 }, + { 0x0012E , 0x00049 , 0x00328 }, + { 0x0012F , 0x00069 , 0x00328 }, + { 0x00130 , 0x00049 , 0x00307 }, + { 0x00134 , 0x0004A , 0x00302 }, + { 0x00135 , 0x0006A , 0x00302 }, + { 0x00136 , 0x0004B , 0x00327 }, + { 0x00137 , 0x0006B , 0x00327 }, + { 0x00139 , 0x0004C , 0x00301 }, + { 0x0013A , 0x0006C , 0x00301 }, + { 0x0013B , 0x0004C , 0x00327 }, + { 0x0013C , 0x0006C , 0x00327 }, + { 0x0013D , 0x0004C , 0x0030C }, + { 0x0013E , 0x0006C , 0x0030C }, + { 0x00143 , 0x0004E , 0x00301 }, + { 0x00144 , 0x0006E , 0x00301 }, + { 0x00145 , 0x0004E , 0x00327 }, + { 0x00146 , 0x0006E , 0x00327 }, + { 0x00147 , 0x0004E , 0x0030C }, + { 0x00148 , 0x0006E , 0x0030C }, + { 0x0014C , 0x0004F , 0x00304 }, + { 0x0014D , 0x0006F , 0x00304 }, + { 0x0014E , 0x0004F , 0x00306 }, + { 0x0014F , 0x0006F , 0x00306 }, + { 0x00150 , 0x0004F , 0x0030B }, + { 0x00151 , 0x0006F , 0x0030B }, + { 0x00154 , 0x00052 , 0x00301 }, + { 0x00155 , 0x00072 , 0x00301 }, + { 0x00156 , 0x00052 , 0x00327 }, + { 0x00157 , 0x00072 , 0x00327 }, + { 0x00158 , 0x00052 , 0x0030C }, + { 0x00159 , 0x00072 , 0x0030C }, + { 0x0015A , 0x00053 , 0x00301 }, + { 0x0015B , 0x00073 , 0x00301 }, + { 0x0015C , 0x00053 , 0x00302 }, + { 0x0015D , 0x00073 , 0x00302 }, + { 0x0015E , 0x00053 , 0x00327 }, + { 0x0015F , 0x00073 , 0x00327 }, + { 0x00160 , 0x00053 , 0x0030C }, + { 0x00161 , 0x00073 , 0x0030C }, + { 0x00162 , 0x00054 , 0x00327 }, + { 0x00163 , 0x00074 , 0x00327 }, + { 0x00164 , 0x00054 , 0x0030C }, + { 0x00165 , 0x00074 , 0x0030C }, + { 0x00168 , 0x00055 , 0x00303 }, + { 0x00169 , 0x00075 , 0x00303 }, + { 0x0016A , 0x00055 , 0x00304 }, + { 0x0016B , 0x00075 , 0x00304 }, + { 0x0016C , 0x00055 , 0x00306 }, + { 0x0016D , 0x00075 , 0x00306 }, + { 0x0016E , 0x00055 , 0x0030A }, + { 0x0016F , 0x00075 , 0x0030A }, + { 0x00170 , 0x00055 , 0x0030B }, + { 0x00171 , 0x00075 , 0x0030B }, + { 0x00172 , 0x00055 , 0x00328 }, + { 0x00173 , 0x00075 , 0x00328 }, + { 0x00174 , 0x00057 , 0x00302 }, + { 0x00175 , 0x00077 , 0x00302 }, + { 0x00176 , 0x00059 , 0x00302 }, + { 0x00177 , 0x00079 , 0x00302 }, + { 0x00178 , 0x00059 , 0x00308 }, + { 0x00179 , 0x0005A , 0x00301 }, + { 0x0017A , 0x0007A , 0x00301 }, + { 0x0017B , 0x0005A , 0x00307 }, + { 0x0017C , 0x0007A , 0x00307 }, + { 0x0017D , 0x0005A , 0x0030C }, + { 0x0017E , 0x0007A , 0x0030C }, + { 0x001A0 , 0x0004F , 0x0031B }, + { 0x001A1 , 0x0006F , 0x0031B }, + { 0x001AF , 0x00055 , 0x0031B }, + { 0x001B0 , 0x00075 , 0x0031B }, + { 0x001CD , 0x00041 , 0x0030C }, + { 0x001CE , 0x00061 , 0x0030C }, + { 0x001CF , 0x00049 , 0x0030C }, + { 0x001D0 , 0x00069 , 0x0030C }, + { 0x001D1 , 0x0004F , 0x0030C }, + { 0x001D2 , 0x0006F , 0x0030C }, + { 0x001D3 , 0x00055 , 0x0030C }, + { 0x001D4 , 0x00075 , 0x0030C }, + { 0x001D5 , 0x000DC , 0x00304 }, + { 0x001D6 , 0x000FC , 0x00304 }, + { 0x001D7 , 0x000DC , 0x00301 }, + { 0x001D8 , 0x000FC , 0x00301 }, + { 0x001D9 , 0x000DC , 0x0030C }, + { 0x001DA , 0x000FC , 0x0030C }, + { 0x001DB , 0x000DC , 0x00300 }, + { 0x001DC , 0x000FC , 0x00300 }, + { 0x001DE , 0x000C4 , 0x00304 }, + { 0x001DF , 0x000E4 , 0x00304 }, + { 0x001E0 , 0x00226 , 0x00304 }, + { 0x001E1 , 0x00227 , 0x00304 }, + { 0x001E2 , 0x000C6 , 0x00304 }, + { 0x001E3 , 0x000E6 , 0x00304 }, + { 0x001E6 , 0x00047 , 0x0030C }, + { 0x001E7 , 0x00067 , 0x0030C }, + { 0x001E8 , 0x0004B , 0x0030C }, + { 0x001E9 , 0x0006B , 0x0030C }, + { 0x001EA , 0x0004F , 0x00328 }, + { 0x001EB , 0x0006F , 0x00328 }, + { 0x001EC , 0x001EA , 0x00304 }, + { 0x001ED , 0x001EB , 0x00304 }, + { 0x001EE , 0x001B7 , 0x0030C }, + { 0x001EF , 0x00292 , 0x0030C }, + { 0x001F0 , 0x0006A , 0x0030C }, + { 0x001F4 , 0x00047 , 0x00301 }, + { 0x001F5 , 0x00067 , 0x00301 }, + { 0x001F8 , 0x0004E , 0x00300 }, + { 0x001F9 , 0x0006E , 0x00300 }, + { 0x001FA , 0x000C5 , 0x00301 }, + { 0x001FB , 0x000E5 , 0x00301 }, + { 0x001FC , 0x000C6 , 0x00301 }, + { 0x001FD , 0x000E6 , 0x00301 }, + { 0x001FE , 0x000D8 , 0x00301 }, + { 0x001FF , 0x000F8 , 0x00301 }, + { 0x00200 , 0x00041 , 0x0030F }, + { 0x00201 , 0x00061 , 0x0030F }, + { 0x00202 , 0x00041 , 0x00311 }, + { 0x00203 , 0x00061 , 0x00311 }, + { 0x00204 , 0x00045 , 0x0030F }, + { 0x00205 , 0x00065 , 0x0030F }, + { 0x00206 , 0x00045 , 0x00311 }, + { 0x00207 , 0x00065 , 0x00311 }, + { 0x00208 , 0x00049 , 0x0030F }, + { 0x00209 , 0x00069 , 0x0030F }, + { 0x0020A , 0x00049 , 0x00311 }, + { 0x0020B , 0x00069 , 0x00311 }, + { 0x0020C , 0x0004F , 0x0030F }, + { 0x0020D , 0x0006F , 0x0030F }, + { 0x0020E , 0x0004F , 0x00311 }, + { 0x0020F , 0x0006F , 0x00311 }, + { 0x00210 , 0x00052 , 0x0030F }, + { 0x00211 , 0x00072 , 0x0030F }, + { 0x00212 , 0x00052 , 0x00311 }, + { 0x00213 , 0x00072 , 0x00311 }, + { 0x00214 , 0x00055 , 0x0030F }, + { 0x00215 , 0x00075 , 0x0030F }, + { 0x00216 , 0x00055 , 0x00311 }, + { 0x00217 , 0x00075 , 0x00311 }, + { 0x00218 , 0x00053 , 0x00326 }, + { 0x00219 , 0x00073 , 0x00326 }, + { 0x0021A , 0x00054 , 0x00326 }, + { 0x0021B , 0x00074 , 0x00326 }, + { 0x0021E , 0x00048 , 0x0030C }, + { 0x0021F , 0x00068 , 0x0030C }, + { 0x00226 , 0x00041 , 0x00307 }, + { 0x00227 , 0x00061 , 0x00307 }, + { 0x00228 , 0x00045 , 0x00327 }, + { 0x00229 , 0x00065 , 0x00327 }, + { 0x0022A , 0x000D6 , 0x00304 }, + { 0x0022B , 0x000F6 , 0x00304 }, + { 0x0022C , 0x000D5 , 0x00304 }, + { 0x0022D , 0x000F5 , 0x00304 }, + { 0x0022E , 0x0004F , 0x00307 }, + { 0x0022F , 0x0006F , 0x00307 }, + { 0x00230 , 0x0022E , 0x00304 }, + { 0x00231 , 0x0022F , 0x00304 }, + { 0x00232 , 0x00059 , 0x00304 }, + { 0x00233 , 0x00079 , 0x00304 }, + { 0x00385 , 0x000A8 , 0x00301 }, + { 0x00386 , 0x00391 , 0x00301 }, + { 0x00388 , 0x00395 , 0x00301 }, + { 0x00389 , 0x00397 , 0x00301 }, + { 0x0038A , 0x00399 , 0x00301 }, + { 0x0038C , 0x0039F , 0x00301 }, + { 0x0038E , 0x003A5 , 0x00301 }, + { 0x0038F , 0x003A9 , 0x00301 }, + { 0x00390 , 0x003CA , 0x00301 }, + { 0x003AA , 0x00399 , 0x00308 }, + { 0x003AB , 0x003A5 , 0x00308 }, + { 0x003AC , 0x003B1 , 0x00301 }, + { 0x003AD , 0x003B5 , 0x00301 }, + { 0x003AE , 0x003B7 , 0x00301 }, + { 0x003AF , 0x003B9 , 0x00301 }, + { 0x003B0 , 0x003CB , 0x00301 }, + { 0x003CA , 0x003B9 , 0x00308 }, + { 0x003CB , 0x003C5 , 0x00308 }, + { 0x003CC , 0x003BF , 0x00301 }, + { 0x003CD , 0x003C5 , 0x00301 }, + { 0x003CE , 0x003C9 , 0x00301 }, + { 0x003D3 , 0x003D2 , 0x00301 }, + { 0x003D4 , 0x003D2 , 0x00308 }, + { 0x00400 , 0x00415 , 0x00300 }, + { 0x00401 , 0x00415 , 0x00308 }, + { 0x00403 , 0x00413 , 0x00301 }, + { 0x00407 , 0x00406 , 0x00308 }, + { 0x0040C , 0x0041A , 0x00301 }, + { 0x0040D , 0x00418 , 0x00300 }, + { 0x0040E , 0x00423 , 0x00306 }, + { 0x00419 , 0x00418 , 0x00306 }, + { 0x00439 , 0x00438 , 0x00306 }, + { 0x00450 , 0x00435 , 0x00300 }, + { 0x00451 , 0x00435 , 0x00308 }, + { 0x00453 , 0x00433 , 0x00301 }, + { 0x00457 , 0x00456 , 0x00308 }, + { 0x0045C , 0x0043A , 0x00301 }, + { 0x0045D , 0x00438 , 0x00300 }, + { 0x0045E , 0x00443 , 0x00306 }, + { 0x00476 , 0x00474 , 0x0030F }, + { 0x00477 , 0x00475 , 0x0030F }, + { 0x004C1 , 0x00416 , 0x00306 }, + { 0x004C2 , 0x00436 , 0x00306 }, + { 0x004D0 , 0x00410 , 0x00306 }, + { 0x004D1 , 0x00430 , 0x00306 }, + { 0x004D2 , 0x00410 , 0x00308 }, + { 0x004D3 , 0x00430 , 0x00308 }, + { 0x004D6 , 0x00415 , 0x00306 }, + { 0x004D7 , 0x00435 , 0x00306 }, + { 0x004DA , 0x004D8 , 0x00308 }, + { 0x004DB , 0x004D9 , 0x00308 }, + { 0x004DC , 0x00416 , 0x00308 }, + { 0x004DD , 0x00436 , 0x00308 }, + { 0x004DE , 0x00417 , 0x00308 }, + { 0x004DF , 0x00437 , 0x00308 }, + { 0x004E2 , 0x00418 , 0x00304 }, + { 0x004E3 , 0x00438 , 0x00304 }, + { 0x004E4 , 0x00418 , 0x00308 }, + { 0x004E5 , 0x00438 , 0x00308 }, + { 0x004E6 , 0x0041E , 0x00308 }, + { 0x004E7 , 0x0043E , 0x00308 }, + { 0x004EA , 0x004E8 , 0x00308 }, + { 0x004EB , 0x004E9 , 0x00308 }, + { 0x004EC , 0x0042D , 0x00308 }, + { 0x004ED , 0x0044D , 0x00308 }, + { 0x004EE , 0x00423 , 0x00304 }, + { 0x004EF , 0x00443 , 0x00304 }, + { 0x004F0 , 0x00423 , 0x00308 }, + { 0x004F1 , 0x00443 , 0x00308 }, + { 0x004F2 , 0x00423 , 0x0030B }, + { 0x004F3 , 0x00443 , 0x0030B }, + { 0x004F4 , 0x00427 , 0x00308 }, + { 0x004F5 , 0x00447 , 0x00308 }, + { 0x004F8 , 0x0042B , 0x00308 }, + { 0x004F9 , 0x0044B , 0x00308 }, + { 0x00622 , 0x00627 , 0x00653 }, + { 0x00623 , 0x00627 , 0x00654 }, + { 0x00624 , 0x00648 , 0x00654 }, + { 0x00625 , 0x00627 , 0x00655 }, + { 0x00626 , 0x0064A , 0x00654 }, + { 0x006C0 , 0x006D5 , 0x00654 }, + { 0x006C2 , 0x006C1 , 0x00654 }, + { 0x006D3 , 0x006D2 , 0x00654 }, + { 0x00929 , 0x00928 , 0x0093C }, + { 0x00931 , 0x00930 , 0x0093C }, + { 0x00934 , 0x00933 , 0x0093C }, + { 0x009CB , 0x009C7 , 0x009BE }, + { 0x009CC , 0x009C7 , 0x009D7 }, + { 0x00B48 , 0x00B47 , 0x00B56 }, + { 0x00B4B , 0x00B47 , 0x00B3E }, + { 0x00B4C , 0x00B47 , 0x00B57 }, + { 0x00B94 , 0x00B92 , 0x00BD7 }, + { 0x00BCA , 0x00BC6 , 0x00BBE }, + { 0x00BCB , 0x00BC7 , 0x00BBE }, + { 0x00BCC , 0x00BC6 , 0x00BD7 }, + { 0x00C48 , 0x00C46 , 0x00C56 }, + { 0x00CC0 , 0x00CBF , 0x00CD5 }, + { 0x00CC7 , 0x00CC6 , 0x00CD5 }, + { 0x00CC8 , 0x00CC6 , 0x00CD6 }, + { 0x00CCA , 0x00CC6 , 0x00CC2 }, + { 0x00CCB , 0x00CCA , 0x00CD5 }, + { 0x00D4A , 0x00D46 , 0x00D3E }, + { 0x00D4B , 0x00D47 , 0x00D3E }, + { 0x00D4C , 0x00D46 , 0x00D57 }, + { 0x00DDA , 0x00DD9 , 0x00DCA }, + { 0x00DDC , 0x00DD9 , 0x00DCF }, + { 0x00DDD , 0x00DDC , 0x00DCA }, + { 0x00DDE , 0x00DD9 , 0x00DDF }, + { 0x01026 , 0x01025 , 0x0102E }, + { 0x01B06 , 0x01B05 , 0x01B35 }, + { 0x01B08 , 0x01B07 , 0x01B35 }, + { 0x01B0A , 0x01B09 , 0x01B35 }, + { 0x01B0C , 0x01B0B , 0x01B35 }, + { 0x01B0E , 0x01B0D , 0x01B35 }, + { 0x01B12 , 0x01B11 , 0x01B35 }, + { 0x01B3B , 0x01B3A , 0x01B35 }, + { 0x01B3D , 0x01B3C , 0x01B35 }, + { 0x01B40 , 0x01B3E , 0x01B35 }, + { 0x01B41 , 0x01B3F , 0x01B35 }, + { 0x01B43 , 0x01B42 , 0x01B35 }, + { 0x01E00 , 0x00041 , 0x00325 }, + { 0x01E01 , 0x00061 , 0x00325 }, + { 0x01E02 , 0x00042 , 0x00307 }, + { 0x01E03 , 0x00062 , 0x00307 }, + { 0x01E04 , 0x00042 , 0x00323 }, + { 0x01E05 , 0x00062 , 0x00323 }, + { 0x01E06 , 0x00042 , 0x00331 }, + { 0x01E07 , 0x00062 , 0x00331 }, + { 0x01E08 , 0x000C7 , 0x00301 }, + { 0x01E09 , 0x000E7 , 0x00301 }, + { 0x01E0A , 0x00044 , 0x00307 }, + { 0x01E0B , 0x00064 , 0x00307 }, + { 0x01E0C , 0x00044 , 0x00323 }, + { 0x01E0D , 0x00064 , 0x00323 }, + { 0x01E0E , 0x00044 , 0x00331 }, + { 0x01E0F , 0x00064 , 0x00331 }, + { 0x01E10 , 0x00044 , 0x00327 }, + { 0x01E11 , 0x00064 , 0x00327 }, + { 0x01E12 , 0x00044 , 0x0032D }, + { 0x01E13 , 0x00064 , 0x0032D }, + { 0x01E14 , 0x00112 , 0x00300 }, + { 0x01E15 , 0x00113 , 0x00300 }, + { 0x01E16 , 0x00112 , 0x00301 }, + { 0x01E17 , 0x00113 , 0x00301 }, + { 0x01E18 , 0x00045 , 0x0032D }, + { 0x01E19 , 0x00065 , 0x0032D }, + { 0x01E1A , 0x00045 , 0x00330 }, + { 0x01E1B , 0x00065 , 0x00330 }, + { 0x01E1C , 0x00228 , 0x00306 }, + { 0x01E1D , 0x00229 , 0x00306 }, + { 0x01E1E , 0x00046 , 0x00307 }, + { 0x01E1F , 0x00066 , 0x00307 }, + { 0x01E20 , 0x00047 , 0x00304 }, + { 0x01E21 , 0x00067 , 0x00304 }, + { 0x01E22 , 0x00048 , 0x00307 }, + { 0x01E23 , 0x00068 , 0x00307 }, + { 0x01E24 , 0x00048 , 0x00323 }, + { 0x01E25 , 0x00068 , 0x00323 }, + { 0x01E26 , 0x00048 , 0x00308 }, + { 0x01E27 , 0x00068 , 0x00308 }, + { 0x01E28 , 0x00048 , 0x00327 }, + { 0x01E29 , 0x00068 , 0x00327 }, + { 0x01E2A , 0x00048 , 0x0032E }, + { 0x01E2B , 0x00068 , 0x0032E }, + { 0x01E2C , 0x00049 , 0x00330 }, + { 0x01E2D , 0x00069 , 0x00330 }, + { 0x01E2E , 0x000CF , 0x00301 }, + { 0x01E2F , 0x000EF , 0x00301 }, + { 0x01E30 , 0x0004B , 0x00301 }, + { 0x01E31 , 0x0006B , 0x00301 }, + { 0x01E32 , 0x0004B , 0x00323 }, + { 0x01E33 , 0x0006B , 0x00323 }, + { 0x01E34 , 0x0004B , 0x00331 }, + { 0x01E35 , 0x0006B , 0x00331 }, + { 0x01E36 , 0x0004C , 0x00323 }, + { 0x01E37 , 0x0006C , 0x00323 }, + { 0x01E38 , 0x01E36 , 0x00304 }, + { 0x01E39 , 0x01E37 , 0x00304 }, + { 0x01E3A , 0x0004C , 0x00331 }, + { 0x01E3B , 0x0006C , 0x00331 }, + { 0x01E3C , 0x0004C , 0x0032D }, + { 0x01E3D , 0x0006C , 0x0032D }, + { 0x01E3E , 0x0004D , 0x00301 }, + { 0x01E3F , 0x0006D , 0x00301 }, + { 0x01E40 , 0x0004D , 0x00307 }, + { 0x01E41 , 0x0006D , 0x00307 }, + { 0x01E42 , 0x0004D , 0x00323 }, + { 0x01E43 , 0x0006D , 0x00323 }, + { 0x01E44 , 0x0004E , 0x00307 }, + { 0x01E45 , 0x0006E , 0x00307 }, + { 0x01E46 , 0x0004E , 0x00323 }, + { 0x01E47 , 0x0006E , 0x00323 }, + { 0x01E48 , 0x0004E , 0x00331 }, + { 0x01E49 , 0x0006E , 0x00331 }, + { 0x01E4A , 0x0004E , 0x0032D }, + { 0x01E4B , 0x0006E , 0x0032D }, + { 0x01E4C , 0x000D5 , 0x00301 }, + { 0x01E4D , 0x000F5 , 0x00301 }, + { 0x01E4E , 0x000D5 , 0x00308 }, + { 0x01E4F , 0x000F5 , 0x00308 }, + { 0x01E50 , 0x0014C , 0x00300 }, + { 0x01E51 , 0x0014D , 0x00300 }, + { 0x01E52 , 0x0014C , 0x00301 }, + { 0x01E53 , 0x0014D , 0x00301 }, + { 0x01E54 , 0x00050 , 0x00301 }, + { 0x01E55 , 0x00070 , 0x00301 }, + { 0x01E56 , 0x00050 , 0x00307 }, + { 0x01E57 , 0x00070 , 0x00307 }, + { 0x01E58 , 0x00052 , 0x00307 }, + { 0x01E59 , 0x00072 , 0x00307 }, + { 0x01E5A , 0x00052 , 0x00323 }, + { 0x01E5B , 0x00072 , 0x00323 }, + { 0x01E5C , 0x01E5A , 0x00304 }, + { 0x01E5D , 0x01E5B , 0x00304 }, + { 0x01E5E , 0x00052 , 0x00331 }, + { 0x01E5F , 0x00072 , 0x00331 }, + { 0x01E60 , 0x00053 , 0x00307 }, + { 0x01E61 , 0x00073 , 0x00307 }, + { 0x01E62 , 0x00053 , 0x00323 }, + { 0x01E63 , 0x00073 , 0x00323 }, + { 0x01E64 , 0x0015A , 0x00307 }, + { 0x01E65 , 0x0015B , 0x00307 }, + { 0x01E66 , 0x00160 , 0x00307 }, + { 0x01E67 , 0x00161 , 0x00307 }, + { 0x01E68 , 0x01E62 , 0x00307 }, + { 0x01E69 , 0x01E63 , 0x00307 }, + { 0x01E6A , 0x00054 , 0x00307 }, + { 0x01E6B , 0x00074 , 0x00307 }, + { 0x01E6C , 0x00054 , 0x00323 }, + { 0x01E6D , 0x00074 , 0x00323 }, + { 0x01E6E , 0x00054 , 0x00331 }, + { 0x01E6F , 0x00074 , 0x00331 }, + { 0x01E70 , 0x00054 , 0x0032D }, + { 0x01E71 , 0x00074 , 0x0032D }, + { 0x01E72 , 0x00055 , 0x00324 }, + { 0x01E73 , 0x00075 , 0x00324 }, + { 0x01E74 , 0x00055 , 0x00330 }, + { 0x01E75 , 0x00075 , 0x00330 }, + { 0x01E76 , 0x00055 , 0x0032D }, + { 0x01E77 , 0x00075 , 0x0032D }, + { 0x01E78 , 0x00168 , 0x00301 }, + { 0x01E79 , 0x00169 , 0x00301 }, + { 0x01E7A , 0x0016A , 0x00308 }, + { 0x01E7B , 0x0016B , 0x00308 }, + { 0x01E7C , 0x00056 , 0x00303 }, + { 0x01E7D , 0x00076 , 0x00303 }, + { 0x01E7E , 0x00056 , 0x00323 }, + { 0x01E7F , 0x00076 , 0x00323 }, + { 0x01E80 , 0x00057 , 0x00300 }, + { 0x01E81 , 0x00077 , 0x00300 }, + { 0x01E82 , 0x00057 , 0x00301 }, + { 0x01E83 , 0x00077 , 0x00301 }, + { 0x01E84 , 0x00057 , 0x00308 }, + { 0x01E85 , 0x00077 , 0x00308 }, + { 0x01E86 , 0x00057 , 0x00307 }, + { 0x01E87 , 0x00077 , 0x00307 }, + { 0x01E88 , 0x00057 , 0x00323 }, + { 0x01E89 , 0x00077 , 0x00323 }, + { 0x01E8A , 0x00058 , 0x00307 }, + { 0x01E8B , 0x00078 , 0x00307 }, + { 0x01E8C , 0x00058 , 0x00308 }, + { 0x01E8D , 0x00078 , 0x00308 }, + { 0x01E8E , 0x00059 , 0x00307 }, + { 0x01E8F , 0x00079 , 0x00307 }, + { 0x01E90 , 0x0005A , 0x00302 }, + { 0x01E91 , 0x0007A , 0x00302 }, + { 0x01E92 , 0x0005A , 0x00323 }, + { 0x01E93 , 0x0007A , 0x00323 }, + { 0x01E94 , 0x0005A , 0x00331 }, + { 0x01E95 , 0x0007A , 0x00331 }, + { 0x01E96 , 0x00068 , 0x00331 }, + { 0x01E97 , 0x00074 , 0x00308 }, + { 0x01E98 , 0x00077 , 0x0030A }, + { 0x01E99 , 0x00079 , 0x0030A }, + { 0x01E9B , 0x0017F , 0x00307 }, + { 0x01EA0 , 0x00041 , 0x00323 }, + { 0x01EA1 , 0x00061 , 0x00323 }, + { 0x01EA2 , 0x00041 , 0x00309 }, + { 0x01EA3 , 0x00061 , 0x00309 }, + { 0x01EA4 , 0x000C2 , 0x00301 }, + { 0x01EA5 , 0x000E2 , 0x00301 }, + { 0x01EA6 , 0x000C2 , 0x00300 }, + { 0x01EA7 , 0x000E2 , 0x00300 }, + { 0x01EA8 , 0x000C2 , 0x00309 }, + { 0x01EA9 , 0x000E2 , 0x00309 }, + { 0x01EAA , 0x000C2 , 0x00303 }, + { 0x01EAB , 0x000E2 , 0x00303 }, + { 0x01EAC , 0x01EA0 , 0x00302 }, + { 0x01EAD , 0x01EA1 , 0x00302 }, + { 0x01EAE , 0x00102 , 0x00301 }, + { 0x01EAF , 0x00103 , 0x00301 }, + { 0x01EB0 , 0x00102 , 0x00300 }, + { 0x01EB1 , 0x00103 , 0x00300 }, + { 0x01EB2 , 0x00102 , 0x00309 }, + { 0x01EB3 , 0x00103 , 0x00309 }, + { 0x01EB4 , 0x00102 , 0x00303 }, + { 0x01EB5 , 0x00103 , 0x00303 }, + { 0x01EB6 , 0x01EA0 , 0x00306 }, + { 0x01EB7 , 0x01EA1 , 0x00306 }, + { 0x01EB8 , 0x00045 , 0x00323 }, + { 0x01EB9 , 0x00065 , 0x00323 }, + { 0x01EBA , 0x00045 , 0x00309 }, + { 0x01EBB , 0x00065 , 0x00309 }, + { 0x01EBC , 0x00045 , 0x00303 }, + { 0x01EBD , 0x00065 , 0x00303 }, + { 0x01EBE , 0x000CA , 0x00301 }, + { 0x01EBF , 0x000EA , 0x00301 }, + { 0x01EC0 , 0x000CA , 0x00300 }, + { 0x01EC1 , 0x000EA , 0x00300 }, + { 0x01EC2 , 0x000CA , 0x00309 }, + { 0x01EC3 , 0x000EA , 0x00309 }, + { 0x01EC4 , 0x000CA , 0x00303 }, + { 0x01EC5 , 0x000EA , 0x00303 }, + { 0x01EC6 , 0x01EB8 , 0x00302 }, + { 0x01EC7 , 0x01EB9 , 0x00302 }, + { 0x01EC8 , 0x00049 , 0x00309 }, + { 0x01EC9 , 0x00069 , 0x00309 }, + { 0x01ECA , 0x00049 , 0x00323 }, + { 0x01ECB , 0x00069 , 0x00323 }, + { 0x01ECC , 0x0004F , 0x00323 }, + { 0x01ECD , 0x0006F , 0x00323 }, + { 0x01ECE , 0x0004F , 0x00309 }, + { 0x01ECF , 0x0006F , 0x00309 }, + { 0x01ED0 , 0x000D4 , 0x00301 }, + { 0x01ED1 , 0x000F4 , 0x00301 }, + { 0x01ED2 , 0x000D4 , 0x00300 }, + { 0x01ED3 , 0x000F4 , 0x00300 }, + { 0x01ED4 , 0x000D4 , 0x00309 }, + { 0x01ED5 , 0x000F4 , 0x00309 }, + { 0x01ED6 , 0x000D4 , 0x00303 }, + { 0x01ED7 , 0x000F4 , 0x00303 }, + { 0x01ED8 , 0x01ECC , 0x00302 }, + { 0x01ED9 , 0x01ECD , 0x00302 }, + { 0x01EDA , 0x001A0 , 0x00301 }, + { 0x01EDB , 0x001A1 , 0x00301 }, + { 0x01EDC , 0x001A0 , 0x00300 }, + { 0x01EDD , 0x001A1 , 0x00300 }, + { 0x01EDE , 0x001A0 , 0x00309 }, + { 0x01EDF , 0x001A1 , 0x00309 }, + { 0x01EE0 , 0x001A0 , 0x00303 }, + { 0x01EE1 , 0x001A1 , 0x00303 }, + { 0x01EE2 , 0x001A0 , 0x00323 }, + { 0x01EE3 , 0x001A1 , 0x00323 }, + { 0x01EE4 , 0x00055 , 0x00323 }, + { 0x01EE5 , 0x00075 , 0x00323 }, + { 0x01EE6 , 0x00055 , 0x00309 }, + { 0x01EE7 , 0x00075 , 0x00309 }, + { 0x01EE8 , 0x001AF , 0x00301 }, + { 0x01EE9 , 0x001B0 , 0x00301 }, + { 0x01EEA , 0x001AF , 0x00300 }, + { 0x01EEB , 0x001B0 , 0x00300 }, + { 0x01EEC , 0x001AF , 0x00309 }, + { 0x01EED , 0x001B0 , 0x00309 }, + { 0x01EEE , 0x001AF , 0x00303 }, + { 0x01EEF , 0x001B0 , 0x00303 }, + { 0x01EF0 , 0x001AF , 0x00323 }, + { 0x01EF1 , 0x001B0 , 0x00323 }, + { 0x01EF2 , 0x00059 , 0x00300 }, + { 0x01EF3 , 0x00079 , 0x00300 }, + { 0x01EF4 , 0x00059 , 0x00323 }, + { 0x01EF5 , 0x00079 , 0x00323 }, + { 0x01EF6 , 0x00059 , 0x00309 }, + { 0x01EF7 , 0x00079 , 0x00309 }, + { 0x01EF8 , 0x00059 , 0x00303 }, + { 0x01EF9 , 0x00079 , 0x00303 }, + { 0x01F00 , 0x003B1 , 0x00313 }, + { 0x01F01 , 0x003B1 , 0x00314 }, + { 0x01F02 , 0x01F00 , 0x00300 }, + { 0x01F03 , 0x01F01 , 0x00300 }, + { 0x01F04 , 0x01F00 , 0x00301 }, + { 0x01F05 , 0x01F01 , 0x00301 }, + { 0x01F06 , 0x01F00 , 0x00342 }, + { 0x01F07 , 0x01F01 , 0x00342 }, + { 0x01F08 , 0x00391 , 0x00313 }, + { 0x01F09 , 0x00391 , 0x00314 }, + { 0x01F0A , 0x01F08 , 0x00300 }, + { 0x01F0B , 0x01F09 , 0x00300 }, + { 0x01F0C , 0x01F08 , 0x00301 }, + { 0x01F0D , 0x01F09 , 0x00301 }, + { 0x01F0E , 0x01F08 , 0x00342 }, + { 0x01F0F , 0x01F09 , 0x00342 }, + { 0x01F10 , 0x003B5 , 0x00313 }, + { 0x01F11 , 0x003B5 , 0x00314 }, + { 0x01F12 , 0x01F10 , 0x00300 }, + { 0x01F13 , 0x01F11 , 0x00300 }, + { 0x01F14 , 0x01F10 , 0x00301 }, + { 0x01F15 , 0x01F11 , 0x00301 }, + { 0x01F18 , 0x00395 , 0x00313 }, + { 0x01F19 , 0x00395 , 0x00314 }, + { 0x01F1A , 0x01F18 , 0x00300 }, + { 0x01F1B , 0x01F19 , 0x00300 }, + { 0x01F1C , 0x01F18 , 0x00301 }, + { 0x01F1D , 0x01F19 , 0x00301 }, + { 0x01F20 , 0x003B7 , 0x00313 }, + { 0x01F21 , 0x003B7 , 0x00314 }, + { 0x01F22 , 0x01F20 , 0x00300 }, + { 0x01F23 , 0x01F21 , 0x00300 }, + { 0x01F24 , 0x01F20 , 0x00301 }, + { 0x01F25 , 0x01F21 , 0x00301 }, + { 0x01F26 , 0x01F20 , 0x00342 }, + { 0x01F27 , 0x01F21 , 0x00342 }, + { 0x01F28 , 0x00397 , 0x00313 }, + { 0x01F29 , 0x00397 , 0x00314 }, + { 0x01F2A , 0x01F28 , 0x00300 }, + { 0x01F2B , 0x01F29 , 0x00300 }, + { 0x01F2C , 0x01F28 , 0x00301 }, + { 0x01F2D , 0x01F29 , 0x00301 }, + { 0x01F2E , 0x01F28 , 0x00342 }, + { 0x01F2F , 0x01F29 , 0x00342 }, + { 0x01F30 , 0x003B9 , 0x00313 }, + { 0x01F31 , 0x003B9 , 0x00314 }, + { 0x01F32 , 0x01F30 , 0x00300 }, + { 0x01F33 , 0x01F31 , 0x00300 }, + { 0x01F34 , 0x01F30 , 0x00301 }, + { 0x01F35 , 0x01F31 , 0x00301 }, + { 0x01F36 , 0x01F30 , 0x00342 }, + { 0x01F37 , 0x01F31 , 0x00342 }, + { 0x01F38 , 0x00399 , 0x00313 }, + { 0x01F39 , 0x00399 , 0x00314 }, + { 0x01F3A , 0x01F38 , 0x00300 }, + { 0x01F3B , 0x01F39 , 0x00300 }, + { 0x01F3C , 0x01F38 , 0x00301 }, + { 0x01F3D , 0x01F39 , 0x00301 }, + { 0x01F3E , 0x01F38 , 0x00342 }, + { 0x01F3F , 0x01F39 , 0x00342 }, + { 0x01F40 , 0x003BF , 0x00313 }, + { 0x01F41 , 0x003BF , 0x00314 }, + { 0x01F42 , 0x01F40 , 0x00300 }, + { 0x01F43 , 0x01F41 , 0x00300 }, + { 0x01F44 , 0x01F40 , 0x00301 }, + { 0x01F45 , 0x01F41 , 0x00301 }, + { 0x01F48 , 0x0039F , 0x00313 }, + { 0x01F49 , 0x0039F , 0x00314 }, + { 0x01F4A , 0x01F48 , 0x00300 }, + { 0x01F4B , 0x01F49 , 0x00300 }, + { 0x01F4C , 0x01F48 , 0x00301 }, + { 0x01F4D , 0x01F49 , 0x00301 }, + { 0x01F50 , 0x003C5 , 0x00313 }, + { 0x01F51 , 0x003C5 , 0x00314 }, + { 0x01F52 , 0x01F50 , 0x00300 }, + { 0x01F53 , 0x01F51 , 0x00300 }, + { 0x01F54 , 0x01F50 , 0x00301 }, + { 0x01F55 , 0x01F51 , 0x00301 }, + { 0x01F56 , 0x01F50 , 0x00342 }, + { 0x01F57 , 0x01F51 , 0x00342 }, + { 0x01F59 , 0x003A5 , 0x00314 }, + { 0x01F5B , 0x01F59 , 0x00300 }, + { 0x01F5D , 0x01F59 , 0x00301 }, + { 0x01F5F , 0x01F59 , 0x00342 }, + { 0x01F60 , 0x003C9 , 0x00313 }, + { 0x01F61 , 0x003C9 , 0x00314 }, + { 0x01F62 , 0x01F60 , 0x00300 }, + { 0x01F63 , 0x01F61 , 0x00300 }, + { 0x01F64 , 0x01F60 , 0x00301 }, + { 0x01F65 , 0x01F61 , 0x00301 }, + { 0x01F66 , 0x01F60 , 0x00342 }, + { 0x01F67 , 0x01F61 , 0x00342 }, + { 0x01F68 , 0x003A9 , 0x00313 }, + { 0x01F69 , 0x003A9 , 0x00314 }, + { 0x01F6A , 0x01F68 , 0x00300 }, + { 0x01F6B , 0x01F69 , 0x00300 }, + { 0x01F6C , 0x01F68 , 0x00301 }, + { 0x01F6D , 0x01F69 , 0x00301 }, + { 0x01F6E , 0x01F68 , 0x00342 }, + { 0x01F6F , 0x01F69 , 0x00342 }, + { 0x01F70 , 0x003B1 , 0x00300 }, + { 0x01F72 , 0x003B5 , 0x00300 }, + { 0x01F74 , 0x003B7 , 0x00300 }, + { 0x01F76 , 0x003B9 , 0x00300 }, + { 0x01F78 , 0x003BF , 0x00300 }, + { 0x01F7A , 0x003C5 , 0x00300 }, + { 0x01F7C , 0x003C9 , 0x00300 }, + { 0x01F80 , 0x01F00 , 0x00345 }, + { 0x01F81 , 0x01F01 , 0x00345 }, + { 0x01F82 , 0x01F02 , 0x00345 }, + { 0x01F83 , 0x01F03 , 0x00345 }, + { 0x01F84 , 0x01F04 , 0x00345 }, + { 0x01F85 , 0x01F05 , 0x00345 }, + { 0x01F86 , 0x01F06 , 0x00345 }, + { 0x01F87 , 0x01F07 , 0x00345 }, + { 0x01F88 , 0x01F08 , 0x00345 }, + { 0x01F89 , 0x01F09 , 0x00345 }, + { 0x01F8A , 0x01F0A , 0x00345 }, + { 0x01F8B , 0x01F0B , 0x00345 }, + { 0x01F8C , 0x01F0C , 0x00345 }, + { 0x01F8D , 0x01F0D , 0x00345 }, + { 0x01F8E , 0x01F0E , 0x00345 }, + { 0x01F8F , 0x01F0F , 0x00345 }, + { 0x01F90 , 0x01F20 , 0x00345 }, + { 0x01F91 , 0x01F21 , 0x00345 }, + { 0x01F92 , 0x01F22 , 0x00345 }, + { 0x01F93 , 0x01F23 , 0x00345 }, + { 0x01F94 , 0x01F24 , 0x00345 }, + { 0x01F95 , 0x01F25 , 0x00345 }, + { 0x01F96 , 0x01F26 , 0x00345 }, + { 0x01F97 , 0x01F27 , 0x00345 }, + { 0x01F98 , 0x01F28 , 0x00345 }, + { 0x01F99 , 0x01F29 , 0x00345 }, + { 0x01F9A , 0x01F2A , 0x00345 }, + { 0x01F9B , 0x01F2B , 0x00345 }, + { 0x01F9C , 0x01F2C , 0x00345 }, + { 0x01F9D , 0x01F2D , 0x00345 }, + { 0x01F9E , 0x01F2E , 0x00345 }, + { 0x01F9F , 0x01F2F , 0x00345 }, + { 0x01FA0 , 0x01F60 , 0x00345 }, + { 0x01FA1 , 0x01F61 , 0x00345 }, + { 0x01FA2 , 0x01F62 , 0x00345 }, + { 0x01FA3 , 0x01F63 , 0x00345 }, + { 0x01FA4 , 0x01F64 , 0x00345 }, + { 0x01FA5 , 0x01F65 , 0x00345 }, + { 0x01FA6 , 0x01F66 , 0x00345 }, + { 0x01FA7 , 0x01F67 , 0x00345 }, + { 0x01FA8 , 0x01F68 , 0x00345 }, + { 0x01FA9 , 0x01F69 , 0x00345 }, + { 0x01FAA , 0x01F6A , 0x00345 }, + { 0x01FAB , 0x01F6B , 0x00345 }, + { 0x01FAC , 0x01F6C , 0x00345 }, + { 0x01FAD , 0x01F6D , 0x00345 }, + { 0x01FAE , 0x01F6E , 0x00345 }, + { 0x01FAF , 0x01F6F , 0x00345 }, + { 0x01FB0 , 0x003B1 , 0x00306 }, + { 0x01FB1 , 0x003B1 , 0x00304 }, + { 0x01FB2 , 0x01F70 , 0x00345 }, + { 0x01FB3 , 0x003B1 , 0x00345 }, + { 0x01FB4 , 0x003AC , 0x00345 }, + { 0x01FB6 , 0x003B1 , 0x00342 }, + { 0x01FB7 , 0x01FB6 , 0x00345 }, + { 0x01FB8 , 0x00391 , 0x00306 }, + { 0x01FB9 , 0x00391 , 0x00304 }, + { 0x01FBA , 0x00391 , 0x00300 }, + { 0x01FBC , 0x00391 , 0x00345 }, + { 0x01FC1 , 0x000A8 , 0x00342 }, + { 0x01FC2 , 0x01F74 , 0x00345 }, + { 0x01FC3 , 0x003B7 , 0x00345 }, + { 0x01FC4 , 0x003AE , 0x00345 }, + { 0x01FC6 , 0x003B7 , 0x00342 }, + { 0x01FC7 , 0x01FC6 , 0x00345 }, + { 0x01FC8 , 0x00395 , 0x00300 }, + { 0x01FCA , 0x00397 , 0x00300 }, + { 0x01FCC , 0x00397 , 0x00345 }, + { 0x01FCD , 0x01FBF , 0x00300 }, + { 0x01FCE , 0x01FBF , 0x00301 }, + { 0x01FCF , 0x01FBF , 0x00342 }, + { 0x01FD0 , 0x003B9 , 0x00306 }, + { 0x01FD1 , 0x003B9 , 0x00304 }, + { 0x01FD2 , 0x003CA , 0x00300 }, + { 0x01FD6 , 0x003B9 , 0x00342 }, + { 0x01FD7 , 0x003CA , 0x00342 }, + { 0x01FD8 , 0x00399 , 0x00306 }, + { 0x01FD9 , 0x00399 , 0x00304 }, + { 0x01FDA , 0x00399 , 0x00300 }, + { 0x01FDD , 0x01FFE , 0x00300 }, + { 0x01FDE , 0x01FFE , 0x00301 }, + { 0x01FDF , 0x01FFE , 0x00342 }, + { 0x01FE0 , 0x003C5 , 0x00306 }, + { 0x01FE1 , 0x003C5 , 0x00304 }, + { 0x01FE2 , 0x003CB , 0x00300 }, + { 0x01FE4 , 0x003C1 , 0x00313 }, + { 0x01FE5 , 0x003C1 , 0x00314 }, + { 0x01FE6 , 0x003C5 , 0x00342 }, + { 0x01FE7 , 0x003CB , 0x00342 }, + { 0x01FE8 , 0x003A5 , 0x00306 }, + { 0x01FE9 , 0x003A5 , 0x00304 }, + { 0x01FEA , 0x003A5 , 0x00300 }, + { 0x01FEC , 0x003A1 , 0x00314 }, + { 0x01FED , 0x000A8 , 0x00300 }, + { 0x01FF2 , 0x01F7C , 0x00345 }, + { 0x01FF3 , 0x003C9 , 0x00345 }, + { 0x01FF4 , 0x003CE , 0x00345 }, + { 0x01FF6 , 0x003C9 , 0x00342 }, + { 0x01FF7 , 0x01FF6 , 0x00345 }, + { 0x01FF8 , 0x0039F , 0x00300 }, + { 0x01FFA , 0x003A9 , 0x00300 }, + { 0x01FFC , 0x003A9 , 0x00345 }, + { 0x0219A , 0x02190 , 0x00338 }, + { 0x0219B , 0x02192 , 0x00338 }, + { 0x021AE , 0x02194 , 0x00338 }, + { 0x021CD , 0x021D0 , 0x00338 }, + { 0x021CE , 0x021D4 , 0x00338 }, + { 0x021CF , 0x021D2 , 0x00338 }, + { 0x02204 , 0x02203 , 0x00338 }, + { 0x02209 , 0x02208 , 0x00338 }, + { 0x0220C , 0x0220B , 0x00338 }, + { 0x02224 , 0x02223 , 0x00338 }, + { 0x02226 , 0x02225 , 0x00338 }, + { 0x02241 , 0x0223C , 0x00338 }, + { 0x02244 , 0x02243 , 0x00338 }, + { 0x02247 , 0x02245 , 0x00338 }, + { 0x02249 , 0x02248 , 0x00338 }, + { 0x02260 , 0x0003D , 0x00338 }, + { 0x02262 , 0x02261 , 0x00338 }, + { 0x0226D , 0x0224D , 0x00338 }, + { 0x0226E , 0x0003C , 0x00338 }, + { 0x0226F , 0x0003E , 0x00338 }, + { 0x02270 , 0x02264 , 0x00338 }, + { 0x02271 , 0x02265 , 0x00338 }, + { 0x02274 , 0x02272 , 0x00338 }, + { 0x02275 , 0x02273 , 0x00338 }, + { 0x02278 , 0x02276 , 0x00338 }, + { 0x02279 , 0x02277 , 0x00338 }, + { 0x02280 , 0x0227A , 0x00338 }, + { 0x02281 , 0x0227B , 0x00338 }, + { 0x02284 , 0x02282 , 0x00338 }, + { 0x02285 , 0x02283 , 0x00338 }, + { 0x02288 , 0x02286 , 0x00338 }, + { 0x02289 , 0x02287 , 0x00338 }, + { 0x022AC , 0x022A2 , 0x00338 }, + { 0x022AD , 0x022A8 , 0x00338 }, + { 0x022AE , 0x022A9 , 0x00338 }, + { 0x022AF , 0x022AB , 0x00338 }, + { 0x022E0 , 0x0227C , 0x00338 }, + { 0x022E1 , 0x0227D , 0x00338 }, + { 0x022E2 , 0x02291 , 0x00338 }, + { 0x022E3 , 0x02292 , 0x00338 }, + { 0x022EA , 0x022B2 , 0x00338 }, + { 0x022EB , 0x022B3 , 0x00338 }, + { 0x022EC , 0x022B4 , 0x00338 }, + { 0x022ED , 0x022B5 , 0x00338 }, + { 0x0304C , 0x0304B , 0x03099 }, + { 0x0304E , 0x0304D , 0x03099 }, + { 0x03050 , 0x0304F , 0x03099 }, + { 0x03052 , 0x03051 , 0x03099 }, + { 0x03054 , 0x03053 , 0x03099 }, + { 0x03056 , 0x03055 , 0x03099 }, + { 0x03058 , 0x03057 , 0x03099 }, + { 0x0305A , 0x03059 , 0x03099 }, + { 0x0305C , 0x0305B , 0x03099 }, + { 0x0305E , 0x0305D , 0x03099 }, + { 0x03060 , 0x0305F , 0x03099 }, + { 0x03062 , 0x03061 , 0x03099 }, + { 0x03065 , 0x03064 , 0x03099 }, + { 0x03067 , 0x03066 , 0x03099 }, + { 0x03069 , 0x03068 , 0x03099 }, + { 0x03070 , 0x0306F , 0x03099 }, + { 0x03071 , 0x0306F , 0x0309A }, + { 0x03073 , 0x03072 , 0x03099 }, + { 0x03074 , 0x03072 , 0x0309A }, + { 0x03076 , 0x03075 , 0x03099 }, + { 0x03077 , 0x03075 , 0x0309A }, + { 0x03079 , 0x03078 , 0x03099 }, + { 0x0307A , 0x03078 , 0x0309A }, + { 0x0307C , 0x0307B , 0x03099 }, + { 0x0307D , 0x0307B , 0x0309A }, + { 0x03094 , 0x03046 , 0x03099 }, + { 0x0309E , 0x0309D , 0x03099 }, + { 0x030AC , 0x030AB , 0x03099 }, + { 0x030AE , 0x030AD , 0x03099 }, + { 0x030B0 , 0x030AF , 0x03099 }, + { 0x030B2 , 0x030B1 , 0x03099 }, + { 0x030B4 , 0x030B3 , 0x03099 }, + { 0x030B6 , 0x030B5 , 0x03099 }, + { 0x030B8 , 0x030B7 , 0x03099 }, + { 0x030BA , 0x030B9 , 0x03099 }, + { 0x030BC , 0x030BB , 0x03099 }, + { 0x030BE , 0x030BD , 0x03099 }, + { 0x030C0 , 0x030BF , 0x03099 }, + { 0x030C2 , 0x030C1 , 0x03099 }, + { 0x030C5 , 0x030C4 , 0x03099 }, + { 0x030C7 , 0x030C6 , 0x03099 }, + { 0x030C9 , 0x030C8 , 0x03099 }, + { 0x030D0 , 0x030CF , 0x03099 }, + { 0x030D1 , 0x030CF , 0x0309A }, + { 0x030D3 , 0x030D2 , 0x03099 }, + { 0x030D4 , 0x030D2 , 0x0309A }, + { 0x030D6 , 0x030D5 , 0x03099 }, + { 0x030D7 , 0x030D5 , 0x0309A }, + { 0x030D9 , 0x030D8 , 0x03099 }, + { 0x030DA , 0x030D8 , 0x0309A }, + { 0x030DC , 0x030DB , 0x03099 }, + { 0x030DD , 0x030DB , 0x0309A }, + { 0x030F4 , 0x030A6 , 0x03099 }, + { 0x030F7 , 0x030EF , 0x03099 }, + { 0x030F8 , 0x030F0 , 0x03099 }, + { 0x030F9 , 0x030F1 , 0x03099 }, + { 0x030FA , 0x030F2 , 0x03099 }, + { 0x030FE , 0x030FD , 0x03099 }, + { 0x1109A , 0x11099 , 0x110BA }, + { 0x1109C , 0x1109B , 0x110BA }, + { 0x110AB , 0x110A5 , 0x110BA }, +}; + +#endif /* ARCHIVE_STRING_COMPOSITION_H_INCLUDED */ + diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_string_sprintf.c b/dependencies/libarchive-3.4.2/libarchive/archive_string_sprintf.c new file mode 100644 index 0000000..969a560 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_string_sprintf.c @@ -0,0 +1,192 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_string_sprintf.c 189435 2009-03-06 05:14:55Z kientzle $"); + +/* + * The use of printf()-family functions can be troublesome + * for space-constrained applications. In addition, correctly + * implementing this function in terms of vsnprintf() requires + * two calls (one to determine the size, another to format the + * result), which in turn requires duplicating the argument list + * using va_copy, which isn't yet universally available. + * + * So, I've implemented a bare minimum of printf()-like capability + * here. This is only used to format error messages, so doesn't + * require any floating-point support or field-width handling. + */ +#ifdef HAVE_ERRNO_H +#include +#endif +#include + +#include "archive_string.h" +#include "archive_private.h" + +/* + * Utility functions to format signed/unsigned integers and append + * them to an archive_string. + */ +static void +append_uint(struct archive_string *as, uintmax_t d, unsigned base) +{ + static const char digits[] = "0123456789abcdef"; + if (d >= base) + append_uint(as, d/base, base); + archive_strappend_char(as, digits[d % base]); +} + +static void +append_int(struct archive_string *as, intmax_t d, unsigned base) +{ + uintmax_t ud; + + if (d < 0) { + archive_strappend_char(as, '-'); + ud = (d == INTMAX_MIN) ? (uintmax_t)(INTMAX_MAX) + 1 : (uintmax_t)(-d); + } else + ud = d; + append_uint(as, ud, base); +} + + +void +archive_string_sprintf(struct archive_string *as, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + archive_string_vsprintf(as, fmt, ap); + va_end(ap); +} + +/* + * Like 'vsprintf', but ensures the target is big enough, resizing if + * necessary. + */ +void +archive_string_vsprintf(struct archive_string *as, const char *fmt, + va_list ap) +{ + char long_flag; + intmax_t s; /* Signed integer temp. */ + uintmax_t u; /* Unsigned integer temp. */ + const char *p, *p2; + const wchar_t *pw; + + if (archive_string_ensure(as, 64) == NULL) + __archive_errx(1, "Out of memory"); + + if (fmt == NULL) { + as->s[0] = 0; + return; + } + + for (p = fmt; *p != '\0'; p++) { + const char *saved_p = p; + + if (*p != '%') { + archive_strappend_char(as, *p); + continue; + } + + p++; + + long_flag = '\0'; + switch(*p) { + case 'j': + case 'l': + case 'z': + long_flag = *p; + p++; + break; + } + + switch (*p) { + case '%': + archive_strappend_char(as, '%'); + break; + case 'c': + s = va_arg(ap, int); + archive_strappend_char(as, (char)s); + break; + case 'd': + switch(long_flag) { + case 'j': s = va_arg(ap, intmax_t); break; + case 'l': s = va_arg(ap, long); break; + case 'z': s = va_arg(ap, ssize_t); break; + default: s = va_arg(ap, int); break; + } + append_int(as, s, 10); + break; + case 's': + switch(long_flag) { + case 'l': + pw = va_arg(ap, wchar_t *); + if (pw == NULL) + pw = L"(null)"; + if (archive_string_append_from_wcs(as, pw, + wcslen(pw)) != 0 && errno == ENOMEM) + __archive_errx(1, "Out of memory"); + break; + default: + p2 = va_arg(ap, char *); + if (p2 == NULL) + p2 = "(null)"; + archive_strcat(as, p2); + break; + } + break; + case 'S': + pw = va_arg(ap, wchar_t *); + if (pw == NULL) + pw = L"(null)"; + if (archive_string_append_from_wcs(as, pw, + wcslen(pw)) != 0 && errno == ENOMEM) + __archive_errx(1, "Out of memory"); + break; + case 'o': case 'u': case 'x': case 'X': + /* Common handling for unsigned integer formats. */ + switch(long_flag) { + case 'j': u = va_arg(ap, uintmax_t); break; + case 'l': u = va_arg(ap, unsigned long); break; + case 'z': u = va_arg(ap, size_t); break; + default: u = va_arg(ap, unsigned int); break; + } + /* Format it in the correct base. */ + switch (*p) { + case 'o': append_uint(as, u, 8); break; + case 'u': append_uint(as, u, 10); break; + default: append_uint(as, u, 16); break; + } + break; + default: + /* Rewind and print the initial '%' literally. */ + p = saved_p; + archive_strappend_char(as, *p); + } + } +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_util.3 b/dependencies/libarchive-3.4.2/libarchive/archive_util.3 new file mode 100644 index 0000000..d5d4e7d --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_util.3 @@ -0,0 +1,224 @@ +.\" Copyright (c) 2003-2007 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 2, 2012 +.Dt ARCHIVE_UTIL 3 +.Os +.Sh NAME +.Nm archive_clear_error , +.Nm archive_compression , +.Nm archive_compression_name , +.Nm archive_copy_error , +.Nm archive_errno , +.Nm archive_error_string , +.Nm archive_file_count , +.Nm archive_filter_code , +.Nm archive_filter_count , +.Nm archive_filter_name , +.Nm archive_format , +.Nm archive_format_name , +.Nm archive_position , +.Nm archive_set_error +.Nd libarchive utility functions +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive.h +.Ft void +.Fn archive_clear_error "struct archive *" +.Ft int +.Fn archive_compression "struct archive *" +.Ft const char * +.Fn archive_compression_name "struct archive *" +.Ft void +.Fn archive_copy_error "struct archive *" "struct archive *" +.Ft int +.Fn archive_errno "struct archive *" +.Ft const char * +.Fn archive_error_string "struct archive *" +.Ft int +.Fn archive_file_count "struct archive *" +.Ft int +.Fn archive_filter_code "struct archive *" "int" +.Ft int +.Fn archive_filter_count "struct archive *" "int" +.Ft const char * +.Fn archive_filter_name "struct archive *" "int" +.Ft int +.Fn archive_format "struct archive *" +.Ft const char * +.Fn archive_format_name "struct archive *" +.Ft int64_t +.Fn archive_position "struct archive *" "int" +.Ft void +.Fo archive_set_error +.Fa "struct archive *" +.Fa "int error_code" +.Fa "const char *fmt" +.Fa "..." +.Fc +.Sh DESCRIPTION +These functions provide access to various information about the +.Tn struct archive +object used in the +.Xr libarchive 3 +library. +.Bl -tag -compact -width indent +.It Fn archive_clear_error +Clears any error information left over from a previous call. +Not generally used in client code. +.It Fn archive_compression +Synonym for +.Fn archive_filter_code a 0 . +.It Fn archive_compression_name +Synonym for +.Fn archive_filter_name a 0 . +.It Fn archive_copy_error +Copies error information from one archive to another. +.It Fn archive_errno +Returns a numeric error code (see +.Xr errno 2 ) +indicating the reason for the most recent error return. +Note that this can not be reliably used to detect whether an +error has occurred. +It should be used only after another libarchive function +has returned an error status. +.It Fn archive_error_string +Returns a textual error message suitable for display. +The error message here is usually more specific than that +obtained from passing the result of +.Fn archive_errno +to +.Xr strerror 3 . +.It Fn archive_file_count +Returns a count of the number of files processed by this archive object. +The count is incremented by calls to +.Xr archive_write_header 3 +or +.Xr archive_read_next_header 3 . +.It Fn archive_filter_code +Returns a numeric code identifying the indicated filter. +See +.Fn archive_filter_count +for details of the numbering. +.It Fn archive_filter_count +Returns the number of filters in the current pipeline. +For read archive handles, these filters are added automatically +by the automatic format detection. +For write archive handles, these filters are added by calls to the various +.Fn archive_write_add_filter_XXX +functions. +Filters in the resulting pipeline are numbered so that filter 0 +is the filter closest to the format handler. +As a convenience, functions that expect a filter number will +accept -1 as a synonym for the highest-numbered filter. +.Pp +For example, when reading a uuencoded gzipped tar archive, there +are three filters: +filter 0 is the gunzip filter, +filter 1 is the uudecode filter, +and filter 2 is the pseudo-filter that wraps the archive read functions. +In this case, requesting +.Fn archive_position a -1 +would be a synonym for +.Fn archive_position a 2 +which would return the number of bytes currently read from the archive, while +.Fn archive_position a 1 +would return the number of bytes after uudecoding, and +.Fn archive_position a 0 +would return the number of bytes after decompression. +.It Fn archive_filter_name +Returns a textual name identifying the indicated filter. +See +.Fn archive_filter_count +for details of the numbering. +.It Fn archive_format +Returns a numeric code indicating the format of the current +archive entry. +This value is set by a successful call to +.Fn archive_read_next_header . +Note that it is common for this value to change from +entry to entry. +For example, a tar archive might have several entries that +utilize GNU tar extensions and several entries that do not. +These entries will have different format codes. +.It Fn archive_format_name +A textual description of the format of the current entry. +.It Fn archive_position +Returns the number of bytes read from or written to the indicated filter. +In particular, +.Fn archive_position a 0 +returns the number of bytes read or written by the format handler, while +.Fn archive_position a -1 +returns the number of bytes read or written to the archive. +See +.Fn archive_filter_count +for details of the numbering here. +.It Fn archive_set_error +Sets the numeric error code and error description that will be returned +by +.Fn archive_errno +and +.Fn archive_error_string . +This function should be used within I/O callbacks to set system-specific +error codes and error descriptions. +This function accepts a printf-like format string and arguments. +However, you should be careful to use only the following printf +format specifiers: +.Dq %c , +.Dq %d , +.Dq %jd , +.Dq %jo , +.Dq %ju , +.Dq %jx , +.Dq %ld , +.Dq %lo , +.Dq %lu , +.Dq %lx , +.Dq %o , +.Dq %u , +.Dq %s , +.Dq %x , +.Dq %% . +Field-width specifiers and other printf features are +not uniformly supported and should not be used. +.El +.Sh SEE ALSO +.Xr archive_read 3 , +.Xr archive_write 3 , +.Xr libarchive 3 , +.Xr printf 3 +.Sh HISTORY +The +.Nm libarchive +library first appeared in +.Fx 5.3 . +.Sh AUTHORS +.An -nosplit +The +.Nm libarchive +library was written by +.An Tim Kientzle Aq kientzle@acm.org . diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_util.c b/dependencies/libarchive-3.4.2/libarchive/archive_util.c new file mode 100644 index 0000000..288a442 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_util.c @@ -0,0 +1,649 @@ +/*- + * Copyright (c) 2009-2012,2014 Michihiro NAKAJIMA + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_util.c 201098 2009-12-28 02:58:14Z kientzle $"); + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#if defined(HAVE_WINCRYPT_H) && !defined(__CYGWIN__) +#include +#endif +#ifdef HAVE_ZLIB_H +#include +#endif +#ifdef HAVE_LZMA_H +#include +#endif +#ifdef HAVE_BZLIB_H +#include +#endif +#ifdef HAVE_LZ4_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_random_private.h" +#include "archive_string.h" + +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + +static int archive_utility_string_sort_helper(char **, unsigned int); + +/* Generic initialization of 'struct archive' objects. */ +int +__archive_clean(struct archive *a) +{ + archive_string_conversion_free(a); + return (ARCHIVE_OK); +} + +int +archive_version_number(void) +{ + return (ARCHIVE_VERSION_NUMBER); +} + +const char * +archive_version_string(void) +{ + return (ARCHIVE_VERSION_STRING); +} + +int +archive_errno(struct archive *a) +{ + return (a->archive_error_number); +} + +const char * +archive_error_string(struct archive *a) +{ + + if (a->error != NULL && *a->error != '\0') + return (a->error); + else + return (NULL); +} + +int +archive_file_count(struct archive *a) +{ + return (a->file_count); +} + +int +archive_format(struct archive *a) +{ + return (a->archive_format); +} + +const char * +archive_format_name(struct archive *a) +{ + return (a->archive_format_name); +} + + +int +archive_compression(struct archive *a) +{ + return archive_filter_code(a, 0); +} + +const char * +archive_compression_name(struct archive *a) +{ + return archive_filter_name(a, 0); +} + + +/* + * Return a count of the number of compressed bytes processed. + */ +la_int64_t +archive_position_compressed(struct archive *a) +{ + return archive_filter_bytes(a, -1); +} + +/* + * Return a count of the number of uncompressed bytes processed. + */ +la_int64_t +archive_position_uncompressed(struct archive *a) +{ + return archive_filter_bytes(a, 0); +} + +void +archive_clear_error(struct archive *a) +{ + archive_string_empty(&a->error_string); + a->error = NULL; + a->archive_error_number = 0; +} + +void +archive_set_error(struct archive *a, int error_number, const char *fmt, ...) +{ + va_list ap; + + a->archive_error_number = error_number; + if (fmt == NULL) { + a->error = NULL; + return; + } + + archive_string_empty(&(a->error_string)); + va_start(ap, fmt); + archive_string_vsprintf(&(a->error_string), fmt, ap); + va_end(ap); + a->error = a->error_string.s; +} + +void +archive_copy_error(struct archive *dest, struct archive *src) +{ + dest->archive_error_number = src->archive_error_number; + + archive_string_copy(&dest->error_string, &src->error_string); + dest->error = dest->error_string.s; +} + +void +__archive_errx(int retvalue, const char *msg) +{ + static const char msg1[] = "Fatal Internal Error in libarchive: "; + size_t s; + + s = write(2, msg1, strlen(msg1)); + (void)s; /* UNUSED */ + s = write(2, msg, strlen(msg)); + (void)s; /* UNUSED */ + s = write(2, "\n", 1); + (void)s; /* UNUSED */ + exit(retvalue); +} + +/* + * Create a temporary file + */ +#if defined(_WIN32) && !defined(__CYGWIN__) + +/* + * Do not use Windows tmpfile() function. + * It will make a temporary file under the root directory + * and it'll cause permission error if a user who is + * non-Administrator creates temporary files. + * Also Windows version of mktemp family including _mktemp_s + * are not secure. + */ +static int +__archive_mktempx(const char *tmpdir, wchar_t *template) +{ + static const wchar_t prefix[] = L"libarchive_"; + static const wchar_t suffix[] = L"XXXXXXXXXX"; + static const wchar_t num[] = { + L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7', + L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F', + L'G', L'H', L'I', L'J', L'K', L'L', L'M', L'N', + L'O', L'P', L'Q', L'R', L'S', L'T', L'U', L'V', + L'W', L'X', L'Y', L'Z', L'a', L'b', L'c', L'd', + L'e', L'f', L'g', L'h', L'i', L'j', L'k', L'l', + L'm', L'n', L'o', L'p', L'q', L'r', L's', L't', + L'u', L'v', L'w', L'x', L'y', L'z' + }; + HCRYPTPROV hProv; + struct archive_wstring temp_name; + wchar_t *ws; + DWORD attr; + wchar_t *xp, *ep; + int fd; + + hProv = (HCRYPTPROV)NULL; + fd = -1; + ws = NULL; + + if (template == NULL) { + archive_string_init(&temp_name); + + /* Get a temporary directory. */ + if (tmpdir == NULL) { + size_t l; + wchar_t *tmp; + + l = GetTempPathW(0, NULL); + if (l == 0) { + la_dosmaperr(GetLastError()); + goto exit_tmpfile; + } + tmp = malloc(l*sizeof(wchar_t)); + if (tmp == NULL) { + errno = ENOMEM; + goto exit_tmpfile; + } + GetTempPathW((DWORD)l, tmp); + archive_wstrcpy(&temp_name, tmp); + free(tmp); + } else { + if (archive_wstring_append_from_mbs(&temp_name, tmpdir, + strlen(tmpdir)) < 0) + goto exit_tmpfile; + if (temp_name.s[temp_name.length-1] != L'/') + archive_wstrappend_wchar(&temp_name, L'/'); + } + + /* Check if temp_name is a directory. */ + attr = GetFileAttributesW(temp_name.s); + if (attr == (DWORD)-1) { + if (GetLastError() != ERROR_FILE_NOT_FOUND) { + la_dosmaperr(GetLastError()); + goto exit_tmpfile; + } + ws = __la_win_permissive_name_w(temp_name.s); + if (ws == NULL) { + errno = EINVAL; + goto exit_tmpfile; + } + attr = GetFileAttributesW(ws); + if (attr == (DWORD)-1) { + la_dosmaperr(GetLastError()); + goto exit_tmpfile; + } + } + if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) { + errno = ENOTDIR; + goto exit_tmpfile; + } + + /* + * Create a temporary file. + */ + archive_wstrcat(&temp_name, prefix); + archive_wstrcat(&temp_name, suffix); + ep = temp_name.s + archive_strlen(&temp_name); + xp = ep - wcslen(suffix); + template = temp_name.s; + } else { + xp = wcschr(template, L'X'); + if (xp == NULL) /* No X, programming error */ + abort(); + for (ep = xp; *ep == L'X'; ep++) + continue; + if (*ep) /* X followed by non X, programming error */ + abort(); + } + + if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT)) { + la_dosmaperr(GetLastError()); + goto exit_tmpfile; + } + + for (;;) { + wchar_t *p; + HANDLE h; + + /* Generate a random file name through CryptGenRandom(). */ + p = xp; + if (!CryptGenRandom(hProv, (DWORD)(ep - p)*sizeof(wchar_t), + (BYTE*)p)) { + la_dosmaperr(GetLastError()); + goto exit_tmpfile; + } + for (; p < ep; p++) + *p = num[((DWORD)*p) % (sizeof(num)/sizeof(num[0]))]; + + free(ws); + ws = __la_win_permissive_name_w(template); + if (ws == NULL) { + errno = EINVAL; + goto exit_tmpfile; + } + if (template == temp_name.s) { + attr = FILE_ATTRIBUTE_TEMPORARY | + FILE_FLAG_DELETE_ON_CLOSE; + } else { + /* mkstemp */ + attr = FILE_ATTRIBUTE_NORMAL; + } + h = CreateFileW(ws, + GENERIC_READ | GENERIC_WRITE | DELETE, + 0,/* Not share */ + NULL, + CREATE_NEW,/* Create a new file only */ + attr, + NULL); + if (h == INVALID_HANDLE_VALUE) { + /* The same file already exists. retry with + * a new filename. */ + if (GetLastError() == ERROR_FILE_EXISTS) + continue; + /* Otherwise, fail creation temporary file. */ + la_dosmaperr(GetLastError()); + goto exit_tmpfile; + } + fd = _open_osfhandle((intptr_t)h, _O_BINARY | _O_RDWR); + if (fd == -1) { + CloseHandle(h); + goto exit_tmpfile; + } else + break;/* success! */ + } +exit_tmpfile: + if (hProv != (HCRYPTPROV)NULL) + CryptReleaseContext(hProv, 0); + free(ws); + if (template == temp_name.s) + archive_wstring_free(&temp_name); + return (fd); +} + +int +__archive_mktemp(const char *tmpdir) +{ + return __archive_mktempx(tmpdir, NULL); +} + +int +__archive_mkstemp(wchar_t *template) +{ + return __archive_mktempx(NULL, template); +} + +#else + +static int +get_tempdir(struct archive_string *temppath) +{ + const char *tmp; + + tmp = getenv("TMPDIR"); + if (tmp == NULL) +#ifdef _PATH_TMP + tmp = _PATH_TMP; +#else + tmp = "/tmp"; +#endif + archive_strcpy(temppath, tmp); + if (temppath->s[temppath->length-1] != '/') + archive_strappend_char(temppath, '/'); + return (ARCHIVE_OK); +} + +#if defined(HAVE_MKSTEMP) + +/* + * We can use mkstemp(). + */ + +int +__archive_mktemp(const char *tmpdir) +{ + struct archive_string temp_name; + int fd = -1; + + archive_string_init(&temp_name); + if (tmpdir == NULL) { + if (get_tempdir(&temp_name) != ARCHIVE_OK) + goto exit_tmpfile; + } else { + archive_strcpy(&temp_name, tmpdir); + if (temp_name.s[temp_name.length-1] != '/') + archive_strappend_char(&temp_name, '/'); + } + archive_strcat(&temp_name, "libarchive_XXXXXX"); + fd = mkstemp(temp_name.s); + if (fd < 0) + goto exit_tmpfile; + __archive_ensure_cloexec_flag(fd); + unlink(temp_name.s); +exit_tmpfile: + archive_string_free(&temp_name); + return (fd); +} + +int +__archive_mkstemp(char *template) +{ + int fd = -1; + fd = mkstemp(template); + if (fd >= 0) + __archive_ensure_cloexec_flag(fd); + return (fd); +} + +#else /* !HAVE_MKSTEMP */ + +/* + * We use a private routine. + */ + +static int +__archive_mktempx(const char *tmpdir, char *template) +{ + static const char num[] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', + 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', + 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', + 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', + 'u', 'v', 'w', 'x', 'y', 'z' + }; + struct archive_string temp_name; + struct stat st; + int fd; + char *tp, *ep; + + fd = -1; + if (template == NULL) { + archive_string_init(&temp_name); + if (tmpdir == NULL) { + if (get_tempdir(&temp_name) != ARCHIVE_OK) + goto exit_tmpfile; + } else + archive_strcpy(&temp_name, tmpdir); + if (temp_name.s[temp_name.length-1] == '/') { + temp_name.s[temp_name.length-1] = '\0'; + temp_name.length --; + } + if (la_stat(temp_name.s, &st) < 0) + goto exit_tmpfile; + if (!S_ISDIR(st.st_mode)) { + errno = ENOTDIR; + goto exit_tmpfile; + } + archive_strcat(&temp_name, "/libarchive_"); + tp = temp_name.s + archive_strlen(&temp_name); + archive_strcat(&temp_name, "XXXXXXXXXX"); + ep = temp_name.s + archive_strlen(&temp_name); + template = temp_name.s; + } else { + tp = strchr(template, 'X'); + if (tp == NULL) /* No X, programming error */ + abort(); + for (ep = tp; *ep == 'X'; ep++) + continue; + if (*ep) /* X followed by non X, programming error */ + abort(); + } + + do { + char *p; + + p = tp; + archive_random(p, ep - p); + while (p < ep) { + int d = *((unsigned char *)p) % sizeof(num); + *p++ = num[d]; + } + fd = open(template, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, + 0600); + } while (fd < 0 && errno == EEXIST); + if (fd < 0) + goto exit_tmpfile; + __archive_ensure_cloexec_flag(fd); + if (template == temp_name.s) + unlink(temp_name.s); +exit_tmpfile: + if (template == temp_name.s) + archive_string_free(&temp_name); + return (fd); +} + +int +__archive_mktemp(const char *tmpdir) +{ + return __archive_mktempx(tmpdir, NULL); +} + +int +__archive_mkstemp(char *template) +{ + return __archive_mktempx(NULL, template); +} + +#endif /* !HAVE_MKSTEMP */ +#endif /* !_WIN32 || __CYGWIN__ */ + +/* + * Set FD_CLOEXEC flag to a file descriptor if it is not set. + * We have to set the flag if the platform does not provide O_CLOEXEC + * or F_DUPFD_CLOEXEC flags. + * + * Note: This function is absolutely called after creating a new file + * descriptor even if the platform seemingly provides O_CLOEXEC or + * F_DUPFD_CLOEXEC macros because it is possible that the platform + * merely declares those macros, especially Linux 2.6.18 - 2.6.24 do it. + */ +void +__archive_ensure_cloexec_flag(int fd) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + (void)fd; /* UNUSED */ +#else + int flags; + + if (fd >= 0) { + flags = fcntl(fd, F_GETFD); + if (flags != -1 && (flags & FD_CLOEXEC) == 0) + fcntl(fd, F_SETFD, flags | FD_CLOEXEC); + } +#endif +} + +/* + * Utility function to sort a group of strings using quicksort. + */ +static int +archive_utility_string_sort_helper(char **strings, unsigned int n) +{ + unsigned int i, lesser_count, greater_count; + char **lesser, **greater, **tmp, *pivot; + int retval1, retval2; + + /* A list of 0 or 1 elements is already sorted */ + if (n <= 1) + return (ARCHIVE_OK); + + lesser_count = greater_count = 0; + lesser = greater = NULL; + pivot = strings[0]; + for (i = 1; i < n; i++) + { + if (strcmp(strings[i], pivot) < 0) + { + lesser_count++; + tmp = (char **)realloc(lesser, + lesser_count * sizeof(char *)); + if (!tmp) { + free(greater); + free(lesser); + return (ARCHIVE_FATAL); + } + lesser = tmp; + lesser[lesser_count - 1] = strings[i]; + } + else + { + greater_count++; + tmp = (char **)realloc(greater, + greater_count * sizeof(char *)); + if (!tmp) { + free(greater); + free(lesser); + return (ARCHIVE_FATAL); + } + greater = tmp; + greater[greater_count - 1] = strings[i]; + } + } + + /* quicksort(lesser) */ + retval1 = archive_utility_string_sort_helper(lesser, lesser_count); + for (i = 0; i < lesser_count; i++) + strings[i] = lesser[i]; + free(lesser); + + /* pivot */ + strings[lesser_count] = pivot; + + /* quicksort(greater) */ + retval2 = archive_utility_string_sort_helper(greater, greater_count); + for (i = 0; i < greater_count; i++) + strings[lesser_count + 1 + i] = greater[i]; + free(greater); + + return (retval1 < retval2) ? retval1 : retval2; +} + +int +archive_utility_string_sort(char **strings) +{ + unsigned int size = 0; + while (strings[size] != NULL) + size++; + return archive_utility_string_sort_helper(strings, size); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_version_details.c b/dependencies/libarchive-3.4.2/libarchive/archive_version_details.c new file mode 100644 index 0000000..bfb20ea --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_version_details.c @@ -0,0 +1,151 @@ +/*- + * Copyright (c) 2009-2012,2014 Michihiro NAKAJIMA + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_util.c 201098 2009-12-28 02:58:14Z kientzle $"); + +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_ZLIB_H +#include +#endif +#ifdef HAVE_LZMA_H +#include +#endif +#ifdef HAVE_BZLIB_H +#include +#endif +#ifdef HAVE_LZ4_H +#include +#endif +#ifdef HAVE_ZSTD_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_string.h" + +const char * +archive_version_details(void) +{ + static struct archive_string str; + static int init = 0; + const char *zlib = archive_zlib_version(); + const char *liblzma = archive_liblzma_version(); + const char *bzlib = archive_bzlib_version(); + const char *liblz4 = archive_liblz4_version(); + const char *libzstd = archive_libzstd_version(); + + if (!init) { + archive_string_init(&str); + + archive_strcat(&str, ARCHIVE_VERSION_STRING); + if (zlib != NULL) { + archive_strcat(&str, " zlib/"); + archive_strcat(&str, zlib); + } + if (liblzma) { + archive_strcat(&str, " liblzma/"); + archive_strcat(&str, liblzma); + } + if (bzlib) { + const char *p = bzlib; + const char *sep = strchr(p, ','); + if (sep == NULL) + sep = p + strlen(p); + archive_strcat(&str, " bz2lib/"); + archive_strncat(&str, p, sep - p); + } + if (liblz4) { + archive_strcat(&str, " liblz4/"); + archive_strcat(&str, liblz4); + } + if (libzstd) { + archive_strcat(&str, " libzstd/"); + archive_strcat(&str, libzstd); + } + } + return str.s; +} + +const char * +archive_zlib_version(void) +{ +#ifdef HAVE_ZLIB_H + return ZLIB_VERSION; +#else + return NULL; +#endif +} + +const char * +archive_liblzma_version(void) +{ +#ifdef HAVE_LZMA_H + return LZMA_VERSION_STRING; +#else + return NULL; +#endif +} + +const char * +archive_bzlib_version(void) +{ +#ifdef HAVE_BZLIB_H + return BZ2_bzlibVersion(); +#else + return NULL; +#endif +} + +const char * +archive_liblz4_version(void) +{ +#if defined(HAVE_LZ4_H) && defined(HAVE_LIBLZ4) +#define str(s) #s +#define NUMBER(x) str(x) + return NUMBER(LZ4_VERSION_MAJOR) "." NUMBER(LZ4_VERSION_MINOR) "." NUMBER(LZ4_VERSION_RELEASE); +#undef NUMBER +#undef str +#else + return NULL; +#endif +} + +const char * +archive_libzstd_version(void) +{ +#if HAVE_ZSTD_H && HAVE_LIBZSTD + return ZSTD_VERSION_STRING; +#else + return NULL; +#endif +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_virtual.c b/dependencies/libarchive-3.4.2/libarchive/archive_virtual.c new file mode 100644 index 0000000..f509ee5 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_virtual.c @@ -0,0 +1,163 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_virtual.c 201098 2009-12-28 02:58:14Z kientzle $"); + +#include "archive.h" +#include "archive_entry.h" +#include "archive_private.h" + +int +archive_filter_code(struct archive *a, int n) +{ + return ((a->vtable->archive_filter_code)(a, n)); +} + +int +archive_filter_count(struct archive *a) +{ + return ((a->vtable->archive_filter_count)(a)); +} + +const char * +archive_filter_name(struct archive *a, int n) +{ + return ((a->vtable->archive_filter_name)(a, n)); +} + +la_int64_t +archive_filter_bytes(struct archive *a, int n) +{ + return ((a->vtable->archive_filter_bytes)(a, n)); +} + +int +archive_free(struct archive *a) +{ + if (a == NULL) + return (ARCHIVE_OK); + return ((a->vtable->archive_free)(a)); +} + +int +archive_write_close(struct archive *a) +{ + return ((a->vtable->archive_close)(a)); +} + +int +archive_read_close(struct archive *a) +{ + return ((a->vtable->archive_close)(a)); +} + +int +archive_write_fail(struct archive *a) +{ + a->state = ARCHIVE_STATE_FATAL; + return a->state; +} + +int +archive_write_free(struct archive *a) +{ + return archive_free(a); +} + +#if ARCHIVE_VERSION_NUMBER < 4000000 +/* For backwards compatibility; will be removed with libarchive 4.0. */ +int +archive_write_finish(struct archive *a) +{ + return archive_write_free(a); +} +#endif + +int +archive_read_free(struct archive *a) +{ + return archive_free(a); +} + +#if ARCHIVE_VERSION_NUMBER < 4000000 +/* For backwards compatibility; will be removed with libarchive 4.0. */ +int +archive_read_finish(struct archive *a) +{ + return archive_read_free(a); +} +#endif + +int +archive_write_header(struct archive *a, struct archive_entry *entry) +{ + ++a->file_count; + return ((a->vtable->archive_write_header)(a, entry)); +} + +int +archive_write_finish_entry(struct archive *a) +{ + return ((a->vtable->archive_write_finish_entry)(a)); +} + +la_ssize_t +archive_write_data(struct archive *a, const void *buff, size_t s) +{ + return ((a->vtable->archive_write_data)(a, buff, s)); +} + +la_ssize_t +archive_write_data_block(struct archive *a, const void *buff, size_t s, + la_int64_t o) +{ + if (a->vtable->archive_write_data_block == NULL) { + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "archive_write_data_block not supported"); + a->state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } + return ((a->vtable->archive_write_data_block)(a, buff, s, o)); +} + +int +archive_read_next_header(struct archive *a, struct archive_entry **entry) +{ + return ((a->vtable->archive_read_next_header)(a, entry)); +} + +int +archive_read_next_header2(struct archive *a, struct archive_entry *entry) +{ + return ((a->vtable->archive_read_next_header2)(a, entry)); +} + +int +archive_read_data_block(struct archive *a, + const void **buff, size_t *s, la_int64_t *o) +{ + return ((a->vtable->archive_read_data_block)(a, buff, s, o)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_windows.c b/dependencies/libarchive-3.4.2/libarchive/archive_windows.c new file mode 100644 index 0000000..624e270 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_windows.c @@ -0,0 +1,909 @@ +/*- + * Copyright (c) 2009-2011 Michihiro NAKAJIMA + * Copyright (c) 2003-2007 Kees Zeelenberg + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * A set of compatibility glue for building libarchive on Windows platforms. + * + * Originally created as "libarchive-nonposix.c" by Kees Zeelenberg + * for the GnuWin32 project, trimmed significantly by Tim Kientzle. + * + * Much of the original file was unnecessary for libarchive, because + * many of the features it emulated were not strictly necessary for + * libarchive. I hope for this to shrink further as libarchive + * internals are gradually reworked to sit more naturally on both + * POSIX and Windows. Any ideas for this are greatly appreciated. + * + * The biggest remaining issue is the dev/ino emulation; libarchive + * has a couple of public APIs that rely on dev/ino uniquely + * identifying a file. This doesn't match well with Windows. I'm + * considering alternative APIs. + */ + +#if defined(_WIN32) && !defined(__CYGWIN__) + +#include "archive_platform.h" +#include "archive_private.h" +#include "archive_entry.h" +#include +#include +#include +#ifdef HAVE_SYS_UTIME_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) + +#if defined(__LA_LSEEK_NEEDED) +static BOOL SetFilePointerEx_perso(HANDLE hFile, + LARGE_INTEGER liDistanceToMove, + PLARGE_INTEGER lpNewFilePointer, + DWORD dwMoveMethod) +{ + LARGE_INTEGER li; + li.QuadPart = liDistanceToMove.QuadPart; + li.LowPart = SetFilePointer( + hFile, li.LowPart, &li.HighPart, dwMoveMethod); + if(lpNewFilePointer) { + lpNewFilePointer->QuadPart = li.QuadPart; + } + return li.LowPart != -1 || GetLastError() == NO_ERROR; +} +#endif + +struct ustat { + int64_t st_atime; + uint32_t st_atime_nsec; + int64_t st_ctime; + uint32_t st_ctime_nsec; + int64_t st_mtime; + uint32_t st_mtime_nsec; + gid_t st_gid; + /* 64bits ino */ + int64_t st_ino; + mode_t st_mode; + uint32_t st_nlink; + uint64_t st_size; + uid_t st_uid; + dev_t st_dev; + dev_t st_rdev; +}; + +/* Transform 64-bits ino into 32-bits by hashing. + * You do not forget that really unique number size is 64-bits. + */ +#define INOSIZE (8*sizeof(ino_t)) /* 32 */ +static __inline ino_t +getino(struct ustat *ub) +{ + ULARGE_INTEGER ino64; + ino64.QuadPart = ub->st_ino; + /* I don't know this hashing is correct way */ + return ((ino_t)(ino64.LowPart ^ (ino64.LowPart >> INOSIZE))); +} + +/* + * Prepend "\\?\" to the path name and convert it to unicode to permit + * an extended-length path for a maximum total path length of 32767 + * characters. + * see also http://msdn.microsoft.com/en-us/library/aa365247.aspx + */ +wchar_t * +__la_win_permissive_name(const char *name) +{ + wchar_t *wn; + wchar_t *ws; + size_t ll; + + ll = strlen(name); + wn = malloc((ll + 1) * sizeof(wchar_t)); + if (wn == NULL) + return (NULL); + ll = mbstowcs(wn, name, ll); + if (ll == (size_t)-1) { + free(wn); + return (NULL); + } + wn[ll] = L'\0'; + ws = __la_win_permissive_name_w(wn); + free(wn); + return (ws); +} + +wchar_t * +__la_win_permissive_name_w(const wchar_t *wname) +{ + wchar_t *wn, *wnp; + wchar_t *ws, *wsp; + DWORD l, len, slen; + int unc; + + /* Get a full-pathname. */ + l = GetFullPathNameW(wname, 0, NULL, NULL); + if (l == 0) + return (NULL); + /* NOTE: GetFullPathNameW has a bug that if the length of the file + * name is just 1 then it returns incomplete buffer size. Thus, we + * have to add three to the size to allocate a sufficient buffer + * size for the full-pathname of the file name. */ + l += 3; + wnp = malloc(l * sizeof(wchar_t)); + if (wnp == NULL) + return (NULL); + len = GetFullPathNameW(wname, l, wnp, NULL); + wn = wnp; + + if (wnp[0] == L'\\' && wnp[1] == L'\\' && + wnp[2] == L'?' && wnp[3] == L'\\') + /* We have already a permissive name. */ + return (wn); + + if (wnp[0] == L'\\' && wnp[1] == L'\\' && + wnp[2] == L'.' && wnp[3] == L'\\') { + /* This is a device name */ + if (((wnp[4] >= L'a' && wnp[4] <= L'z') || + (wnp[4] >= L'A' && wnp[4] <= L'Z')) && + wnp[5] == L':' && wnp[6] == L'\\') + wnp[2] = L'?';/* Not device name. */ + return (wn); + } + + unc = 0; + if (wnp[0] == L'\\' && wnp[1] == L'\\' && wnp[2] != L'\\') { + wchar_t *p = &wnp[2]; + + /* Skip server-name letters. */ + while (*p != L'\\' && *p != L'\0') + ++p; + if (*p == L'\\') { + wchar_t *rp = ++p; + /* Skip share-name letters. */ + while (*p != L'\\' && *p != L'\0') + ++p; + if (*p == L'\\' && p != rp) { + /* Now, match patterns such as + * "\\server-name\share-name\" */ + wnp += 2; + len -= 2; + unc = 1; + } + } + } + + slen = 4 + (unc * 4) + len + 1; + ws = wsp = malloc(slen * sizeof(wchar_t)); + if (ws == NULL) { + free(wn); + return (NULL); + } + /* prepend "\\?\" */ + wcsncpy(wsp, L"\\\\?\\", 4); + wsp += 4; + slen -= 4; + if (unc) { + /* append "UNC\" ---> "\\?\UNC\" */ + wcsncpy(wsp, L"UNC\\", 4); + wsp += 4; + slen -= 4; + } + wcsncpy(wsp, wnp, slen); + wsp[slen - 1] = L'\0'; /* Ensure null termination. */ + free(wn); + return (ws); +} + +/* + * Create a file handle. + * This can exceed MAX_PATH limitation. + */ +static HANDLE +la_CreateFile(const char *path, DWORD dwDesiredAccess, DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) +{ + wchar_t *wpath; + HANDLE handle; + + handle = CreateFileA(path, dwDesiredAccess, dwShareMode, + lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, + hTemplateFile); + if (handle != INVALID_HANDLE_VALUE) + return (handle); + if (GetLastError() != ERROR_PATH_NOT_FOUND) + return (handle); + wpath = __la_win_permissive_name(path); + if (wpath == NULL) + return (handle); + handle = CreateFileW(wpath, dwDesiredAccess, dwShareMode, + lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, + hTemplateFile); + free(wpath); + return (handle); +} + +#if defined(__LA_LSEEK_NEEDED) +__int64 +__la_lseek(int fd, __int64 offset, int whence) +{ + LARGE_INTEGER distance; + LARGE_INTEGER newpointer; + HANDLE handle; + + if (fd < 0) { + errno = EBADF; + return (-1); + } + handle = (HANDLE)_get_osfhandle(fd); + if (GetFileType(handle) != FILE_TYPE_DISK) { + errno = EBADF; + return (-1); + } + distance.QuadPart = offset; + if (!SetFilePointerEx_perso(handle, distance, &newpointer, whence)) { + DWORD lasterr; + + lasterr = GetLastError(); + if (lasterr == ERROR_BROKEN_PIPE) + return (0); + if (lasterr == ERROR_ACCESS_DENIED) + errno = EBADF; + else + la_dosmaperr(lasterr); + return (-1); + } + return (newpointer.QuadPart); +} +#endif + +/* This can exceed MAX_PATH limitation. */ +int +__la_open(const char *path, int flags, ...) +{ + va_list ap; + wchar_t *ws; + int r, pmode; + DWORD attr; + + va_start(ap, flags); + pmode = va_arg(ap, int); + va_end(ap); + ws = NULL; + if ((flags & ~O_BINARY) == O_RDONLY) { + /* + * When we open a directory, _open function returns + * "Permission denied" error. + */ + attr = GetFileAttributesA(path); + if (attr == (DWORD)-1 && GetLastError() == ERROR_PATH_NOT_FOUND) { + ws = __la_win_permissive_name(path); + if (ws == NULL) { + errno = EINVAL; + return (-1); + } + attr = GetFileAttributesW(ws); + } + if (attr == (DWORD)-1) { + la_dosmaperr(GetLastError()); + free(ws); + return (-1); + } + if (attr & FILE_ATTRIBUTE_DIRECTORY) { + HANDLE handle; + + if (ws != NULL) + handle = CreateFileW(ws, 0, 0, NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | + FILE_ATTRIBUTE_READONLY, + NULL); + else + handle = CreateFileA(path, 0, 0, NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | + FILE_ATTRIBUTE_READONLY, + NULL); + free(ws); + if (handle == INVALID_HANDLE_VALUE) { + la_dosmaperr(GetLastError()); + return (-1); + } + r = _open_osfhandle((intptr_t)handle, _O_RDONLY); + return (r); + } + } + if (ws == NULL) { +#if defined(__BORLANDC__) + /* Borland has no mode argument. + TODO: Fix mode of new file. */ + r = _open(path, flags); +#else + r = _open(path, flags, pmode); +#endif + if (r < 0 && errno == EACCES && (flags & O_CREAT) != 0) { + /* Simulate other POSIX system action to pass our test suite. */ + attr = GetFileAttributesA(path); + if (attr == (DWORD)-1) + la_dosmaperr(GetLastError()); + else if (attr & FILE_ATTRIBUTE_DIRECTORY) + errno = EISDIR; + else + errno = EACCES; + return (-1); + } + if (r >= 0 || errno != ENOENT) + return (r); + ws = __la_win_permissive_name(path); + if (ws == NULL) { + errno = EINVAL; + return (-1); + } + } + r = _wopen(ws, flags, pmode); + if (r < 0 && errno == EACCES && (flags & O_CREAT) != 0) { + /* Simulate other POSIX system action to pass our test suite. */ + attr = GetFileAttributesW(ws); + if (attr == (DWORD)-1) + la_dosmaperr(GetLastError()); + else if (attr & FILE_ATTRIBUTE_DIRECTORY) + errno = EISDIR; + else + errno = EACCES; + } + free(ws); + return (r); +} + +ssize_t +__la_read(int fd, void *buf, size_t nbytes) +{ + HANDLE handle; + DWORD bytes_read, lasterr; + int r; + +#ifdef _WIN64 + if (nbytes > UINT32_MAX) + nbytes = UINT32_MAX; +#endif + if (fd < 0) { + errno = EBADF; + return (-1); + } + /* Do not pass 0 to third parameter of ReadFile(), read bytes. + * This will not return to application side. */ + if (nbytes == 0) + return (0); + handle = (HANDLE)_get_osfhandle(fd); + r = ReadFile(handle, buf, (uint32_t)nbytes, + &bytes_read, NULL); + if (r == 0) { + lasterr = GetLastError(); + if (lasterr == ERROR_NO_DATA) { + errno = EAGAIN; + return (-1); + } + if (lasterr == ERROR_BROKEN_PIPE) + return (0); + if (lasterr == ERROR_ACCESS_DENIED) + errno = EBADF; + else + la_dosmaperr(lasterr); + return (-1); + } + return ((ssize_t)bytes_read); +} + +/* Convert Windows FILETIME to UTC */ +__inline static void +fileTimeToUTC(const FILETIME *filetime, time_t *t, long *ns) +{ + ULARGE_INTEGER utc; + + utc.HighPart = filetime->dwHighDateTime; + utc.LowPart = filetime->dwLowDateTime; + if (utc.QuadPart >= EPOC_TIME) { + utc.QuadPart -= EPOC_TIME; + *t = (time_t)(utc.QuadPart / 10000000); /* milli seconds base */ + *ns = (long)(utc.QuadPart % 10000000) * 100;/* nano seconds base */ + } else { + *t = 0; + *ns = 0; + } +} + +/* Stat by handle + * Windows' stat() does not accept the path added "\\?\" especially "?" + * character. + * It means we cannot access the long name path longer than MAX_PATH. + * So I've implemented a function similar to Windows' stat() to access the + * long name path. + * And I've added some feature. + * 1. set st_ino by nFileIndexHigh and nFileIndexLow of + * BY_HANDLE_FILE_INFORMATION. + * 2. set st_nlink by nNumberOfLinks of BY_HANDLE_FILE_INFORMATION. + * 3. set st_dev by dwVolumeSerialNumber by BY_HANDLE_FILE_INFORMATION. + */ +static int +__hstat(HANDLE handle, struct ustat *st) +{ + BY_HANDLE_FILE_INFORMATION info; + ULARGE_INTEGER ino64; + DWORD ftype; + mode_t mode; + time_t t; + long ns; + + switch (ftype = GetFileType(handle)) { + case FILE_TYPE_UNKNOWN: + errno = EBADF; + return (-1); + case FILE_TYPE_CHAR: + case FILE_TYPE_PIPE: + if (ftype == FILE_TYPE_CHAR) { + st->st_mode = S_IFCHR; + st->st_size = 0; + } else { + DWORD avail; + + st->st_mode = S_IFIFO; + if (PeekNamedPipe(handle, NULL, 0, NULL, &avail, NULL)) + st->st_size = avail; + else + st->st_size = 0; + } + st->st_atime = 0; + st->st_atime_nsec = 0; + st->st_mtime = 0; + st->st_mtime_nsec = 0; + st->st_ctime = 0; + st->st_ctime_nsec = 0; + st->st_ino = 0; + st->st_nlink = 1; + st->st_uid = 0; + st->st_gid = 0; + st->st_rdev = 0; + st->st_dev = 0; + return (0); + case FILE_TYPE_DISK: + break; + default: + /* This ftype is undocumented type. */ + la_dosmaperr(GetLastError()); + return (-1); + } + + ZeroMemory(&info, sizeof(info)); + if (!GetFileInformationByHandle (handle, &info)) { + la_dosmaperr(GetLastError()); + return (-1); + } + + mode = S_IRUSR | S_IRGRP | S_IROTH; + if ((info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0) + mode |= S_IWUSR | S_IWGRP | S_IWOTH; + if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH; + else + mode |= S_IFREG; + st->st_mode = mode; + + fileTimeToUTC(&info.ftLastAccessTime, &t, &ns); + st->st_atime = t; + st->st_atime_nsec = ns; + fileTimeToUTC(&info.ftLastWriteTime, &t, &ns); + st->st_mtime = t; + st->st_mtime_nsec = ns; + fileTimeToUTC(&info.ftCreationTime, &t, &ns); + st->st_ctime = t; + st->st_ctime_nsec = ns; + st->st_size = + ((int64_t)(info.nFileSizeHigh) * ((int64_t)MAXDWORD + 1)) + + (int64_t)(info.nFileSizeLow); +#ifdef SIMULATE_WIN_STAT + st->st_ino = 0; + st->st_nlink = 1; + st->st_dev = 0; +#else + /* Getting FileIndex as i-node. We should remove a sequence which + * is high-16-bits of nFileIndexHigh. */ + ino64.HighPart = info.nFileIndexHigh & 0x0000FFFFUL; + ino64.LowPart = info.nFileIndexLow; + st->st_ino = ino64.QuadPart; + st->st_nlink = info.nNumberOfLinks; + if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + ++st->st_nlink;/* Add parent directory. */ + st->st_dev = info.dwVolumeSerialNumber; +#endif + st->st_uid = 0; + st->st_gid = 0; + st->st_rdev = 0; + return (0); +} + +static void +copy_stat(struct stat *st, struct ustat *us) +{ + st->st_atime = us->st_atime; + st->st_ctime = us->st_ctime; + st->st_mtime = us->st_mtime; + st->st_gid = us->st_gid; + st->st_ino = getino(us); + st->st_mode = us->st_mode; + st->st_nlink = us->st_nlink; + st->st_size = (off_t)us->st_size; + st->st_uid = us->st_uid; + st->st_dev = us->st_dev; + st->st_rdev = us->st_rdev; +} + +/* + * TODO: Remove a use of __la_fstat and __la_stat. + * We should use GetFileInformationByHandle in place + * where We still use the *stat functions. + */ +int +__la_fstat(int fd, struct stat *st) +{ + struct ustat u; + int ret; + + if (fd < 0) { + errno = EBADF; + return (-1); + } + ret = __hstat((HANDLE)_get_osfhandle(fd), &u); + if (ret >= 0) { + copy_stat(st, &u); + if (u.st_mode & (S_IFCHR | S_IFIFO)) { + st->st_dev = fd; + st->st_rdev = fd; + } + } + return (ret); +} + +/* This can exceed MAX_PATH limitation. */ +int +__la_stat(const char *path, struct stat *st) +{ + HANDLE handle; + struct ustat u; + int ret; + + handle = la_CreateFile(path, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + NULL); + if (handle == INVALID_HANDLE_VALUE) { + la_dosmaperr(GetLastError()); + return (-1); + } + ret = __hstat(handle, &u); + CloseHandle(handle); + if (ret >= 0) { + char *p; + + copy_stat(st, &u); + p = strrchr(path, '.'); + if (p != NULL && strlen(p) == 4) { + char exttype[4]; + + ++ p; + exttype[0] = toupper(*p++); + exttype[1] = toupper(*p++); + exttype[2] = toupper(*p++); + exttype[3] = '\0'; + if (!strcmp(exttype, "EXE") || !strcmp(exttype, "CMD") || + !strcmp(exttype, "BAT") || !strcmp(exttype, "COM")) + st->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH; + } + } + return (ret); +} + +/* + * This waitpid is limited implementation. + */ +pid_t +__la_waitpid(HANDLE child, int *status, int option) +{ + DWORD cs; + + (void)option;/* UNUSED */ + do { + if (GetExitCodeProcess(child, &cs) == 0) { + CloseHandle(child); + la_dosmaperr(GetLastError()); + *status = 0; + return (-1); + } + } while (cs == STILL_ACTIVE); + + *status = (int)(cs & 0xff); + return (0); +} + +ssize_t +__la_write(int fd, const void *buf, size_t nbytes) +{ + DWORD bytes_written; + +#ifdef _WIN64 + if (nbytes > UINT32_MAX) + nbytes = UINT32_MAX; +#endif + if (fd < 0) { + errno = EBADF; + return (-1); + } + if (!WriteFile((HANDLE)_get_osfhandle(fd), buf, (uint32_t)nbytes, + &bytes_written, NULL)) { + DWORD lasterr; + + lasterr = GetLastError(); + if (lasterr == ERROR_ACCESS_DENIED) + errno = EBADF; + else + la_dosmaperr(lasterr); + return (-1); + } + return (bytes_written); +} + +/* + * Replace the Windows path separator '\' with '/'. + */ +static int +replace_pathseparator(struct archive_wstring *ws, const wchar_t *wp) +{ + wchar_t *w; + size_t path_length; + + if (wp == NULL) + return(0); + if (wcschr(wp, L'\\') == NULL) + return(0); + path_length = wcslen(wp); + if (archive_wstring_ensure(ws, path_length) == NULL) + return(-1); + archive_wstrncpy(ws, wp, path_length); + for (w = ws->s; *w; w++) { + if (*w == L'\\') + *w = L'/'; + } + return(1); +} + +static int +fix_pathseparator(struct archive_entry *entry) +{ + struct archive_wstring ws; + const wchar_t *wp; + int ret = ARCHIVE_OK; + + archive_string_init(&ws); + wp = archive_entry_pathname_w(entry); + switch (replace_pathseparator(&ws, wp)) { + case 0: /* Not replaced. */ + break; + case 1: /* Replaced. */ + archive_entry_copy_pathname_w(entry, ws.s); + break; + default: + ret = ARCHIVE_FAILED; + } + wp = archive_entry_hardlink_w(entry); + switch (replace_pathseparator(&ws, wp)) { + case 0: /* Not replaced. */ + break; + case 1: /* Replaced. */ + archive_entry_copy_hardlink_w(entry, ws.s); + break; + default: + ret = ARCHIVE_FAILED; + } + wp = archive_entry_symlink_w(entry); + switch (replace_pathseparator(&ws, wp)) { + case 0: /* Not replaced. */ + break; + case 1: /* Replaced. */ + archive_entry_copy_symlink_w(entry, ws.s); + break; + default: + ret = ARCHIVE_FAILED; + } + archive_wstring_free(&ws); + return(ret); +} + +struct archive_entry * +__la_win_entry_in_posix_pathseparator(struct archive_entry *entry) +{ + struct archive_entry *entry_main; + const wchar_t *wp; + int has_backslash = 0; + int ret; + + wp = archive_entry_pathname_w(entry); + if (wp != NULL && wcschr(wp, L'\\') != NULL) + has_backslash = 1; + if (!has_backslash) { + wp = archive_entry_hardlink_w(entry); + if (wp != NULL && wcschr(wp, L'\\') != NULL) + has_backslash = 1; + } + if (!has_backslash) { + wp = archive_entry_symlink_w(entry); + if (wp != NULL && wcschr(wp, L'\\') != NULL) + has_backslash = 1; + } + /* + * If there is no backslash chars, return the original. + */ + if (!has_backslash) + return (entry); + + /* Copy entry so we can modify it as needed. */ + entry_main = archive_entry_clone(entry); + if (entry_main == NULL) + return (NULL); + /* Replace the Windows path-separator '\' with '/'. */ + ret = fix_pathseparator(entry_main); + if (ret < ARCHIVE_WARN) { + archive_entry_free(entry_main); + return (NULL); + } + return (entry_main); +} + + +/* + * The following function was modified from PostgreSQL sources and is + * subject to the copyright below. + */ +/*------------------------------------------------------------------------- + * + * win32error.c + * Map win32 error codes to errno values + * + * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group + * + * IDENTIFICATION + * $PostgreSQL: pgsql/src/port/win32error.c,v 1.4 2008/01/01 19:46:00 momjian Exp $ + * + *------------------------------------------------------------------------- + */ +/* +PostgreSQL Database Management System +(formerly known as Postgres, then as Postgres95) + +Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group + +Portions Copyright (c) 1994, The Regents of the University of California + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose, without fee, and without a written agreement +is hereby granted, provided that the above copyright notice and this +paragraph and the following two paragraphs appear in all copies. + +IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR +DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING +LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS +DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS +ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO +PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. +*/ + +static const struct { + DWORD winerr; + int doserr; +} doserrors[] = +{ + { ERROR_INVALID_FUNCTION, EINVAL }, + { ERROR_FILE_NOT_FOUND, ENOENT }, + { ERROR_PATH_NOT_FOUND, ENOENT }, + { ERROR_TOO_MANY_OPEN_FILES, EMFILE }, + { ERROR_ACCESS_DENIED, EACCES }, + { ERROR_INVALID_HANDLE, EBADF }, + { ERROR_ARENA_TRASHED, ENOMEM }, + { ERROR_NOT_ENOUGH_MEMORY, ENOMEM }, + { ERROR_INVALID_BLOCK, ENOMEM }, + { ERROR_BAD_ENVIRONMENT, E2BIG }, + { ERROR_BAD_FORMAT, ENOEXEC }, + { ERROR_INVALID_ACCESS, EINVAL }, + { ERROR_INVALID_DATA, EINVAL }, + { ERROR_INVALID_DRIVE, ENOENT }, + { ERROR_CURRENT_DIRECTORY, EACCES }, + { ERROR_NOT_SAME_DEVICE, EXDEV }, + { ERROR_NO_MORE_FILES, ENOENT }, + { ERROR_LOCK_VIOLATION, EACCES }, + { ERROR_SHARING_VIOLATION, EACCES }, + { ERROR_BAD_NETPATH, ENOENT }, + { ERROR_NETWORK_ACCESS_DENIED, EACCES }, + { ERROR_BAD_NET_NAME, ENOENT }, + { ERROR_FILE_EXISTS, EEXIST }, + { ERROR_CANNOT_MAKE, EACCES }, + { ERROR_FAIL_I24, EACCES }, + { ERROR_INVALID_PARAMETER, EINVAL }, + { ERROR_NO_PROC_SLOTS, EAGAIN }, + { ERROR_DRIVE_LOCKED, EACCES }, + { ERROR_BROKEN_PIPE, EPIPE }, + { ERROR_DISK_FULL, ENOSPC }, + { ERROR_INVALID_TARGET_HANDLE, EBADF }, + { ERROR_INVALID_HANDLE, EINVAL }, + { ERROR_WAIT_NO_CHILDREN, ECHILD }, + { ERROR_CHILD_NOT_COMPLETE, ECHILD }, + { ERROR_DIRECT_ACCESS_HANDLE, EBADF }, + { ERROR_NEGATIVE_SEEK, EINVAL }, + { ERROR_SEEK_ON_DEVICE, EACCES }, + { ERROR_DIR_NOT_EMPTY, ENOTEMPTY }, + { ERROR_NOT_LOCKED, EACCES }, + { ERROR_BAD_PATHNAME, ENOENT }, + { ERROR_MAX_THRDS_REACHED, EAGAIN }, + { ERROR_LOCK_FAILED, EACCES }, + { ERROR_ALREADY_EXISTS, EEXIST }, + { ERROR_FILENAME_EXCED_RANGE, ENOENT }, + { ERROR_NESTING_NOT_ALLOWED, EAGAIN }, + { ERROR_NOT_ENOUGH_QUOTA, ENOMEM } +}; + +void +__la_dosmaperr(unsigned long e) +{ + int i; + + if (e == 0) + { + errno = 0; + return; + } + + for (i = 0; i < (int)(sizeof(doserrors)/sizeof(doserrors[0])); i++) + { + if (doserrors[i].winerr == e) + { + errno = doserrors[i].doserr; + return; + } + } + + /* fprintf(stderr, "unrecognized win32 error code: %lu", e); */ + errno = EINVAL; + return; +} + +#endif /* _WIN32 && !__CYGWIN__ */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_windows.h b/dependencies/libarchive-3.4.2/libarchive/archive_windows.h new file mode 100644 index 0000000..47b7cb8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_windows.h @@ -0,0 +1,315 @@ +/*- + * Copyright (c) 2009-2011 Michihiro NAKAJIMA + * Copyright (c) 2003-2006 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * TODO: A lot of stuff in here isn't actually used by libarchive and + * can be trimmed out. Note that this file is used by libarchive and + * libarchive_test but nowhere else. (But note that it gets compiled + * with many different Windows environments, including MinGW, Visual + * Studio, and Cygwin. Significant changes should be tested in all three.) + */ + +/* + * TODO: Don't use off_t in here. Use __int64 instead. Note that + * Visual Studio and the Windows SDK define off_t as 32 bits; Win32's + * more modern file handling APIs all use __int64 instead of off_t. + */ + +#ifndef LIBARCHIVE_ARCHIVE_WINDOWS_H_INCLUDED +#define LIBARCHIVE_ARCHIVE_WINDOWS_H_INCLUDED + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif + +/* Start of configuration for native Win32 */ +#ifndef MINGW_HAS_SECURE_API +#define MINGW_HAS_SECURE_API 1 +#endif + +#include +#define set_errno(val) ((errno)=val) +#include +#include //brings in NULL +#if defined(HAVE_STDINT_H) +#include +#endif +#include +#include +#include +#include +#include +#if defined(__MINGW32__) && defined(HAVE_UNISTD_H) +/* Prevent build error from a type mismatch of ftruncate(). + * This unistd.h defines it as ftruncate(int, off_t). */ +#include +#endif +#define NOCRYPT +#include +//#define EFTYPE 7 + +#if defined(__BORLANDC__) +#pragma warn -8068 /* Constant out of range in comparison. */ +#pragma warn -8072 /* Suspicious pointer arithmetic. */ +#endif + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +/* Alias the Windows _function to the POSIX equivalent. */ +#define close _close +#define fcntl(fd, cmd, flg) /* No operation. */ +#ifndef fileno +#define fileno _fileno +#endif +#ifdef fstat +#undef fstat +#endif +#define fstat __la_fstat +#if !defined(__BORLANDC__) +#ifdef lseek +#undef lseek +#endif +#define lseek _lseeki64 +#else +#define lseek __la_lseek +#define __LA_LSEEK_NEEDED +#endif +#define lstat __la_stat +#define open __la_open +#define read __la_read +#if !defined(__BORLANDC__) && !defined(__WATCOMC__) +#define setmode _setmode +#endif +#define la_stat(path,stref) __la_stat(path,stref) +#if !defined(__WATCOMC__) +#if !defined(__BORLANDC__) +#define strdup _strdup +#endif +#define tzset _tzset +#if !defined(__BORLANDC__) +#define umask _umask +#endif +#endif +#define waitpid __la_waitpid +#define write __la_write + +#if !defined(__WATCOMC__) + +#ifndef O_RDONLY +#define O_RDONLY _O_RDONLY +#define O_WRONLY _O_WRONLY +#define O_TRUNC _O_TRUNC +#define O_CREAT _O_CREAT +#define O_EXCL _O_EXCL +#define O_BINARY _O_BINARY +#endif + +#ifndef _S_IFIFO + #define _S_IFIFO 0010000 /* pipe */ +#endif +#ifndef _S_IFCHR + #define _S_IFCHR 0020000 /* character special */ +#endif +#ifndef _S_IFDIR + #define _S_IFDIR 0040000 /* directory */ +#endif +#ifndef _S_IFBLK + #define _S_IFBLK 0060000 /* block special */ +#endif +#ifndef _S_IFLNK + #define _S_IFLNK 0120000 /* symbolic link */ +#endif +#ifndef _S_IFSOCK + #define _S_IFSOCK 0140000 /* socket */ +#endif +#ifndef _S_IFREG + #define _S_IFREG 0100000 /* regular */ +#endif +#ifndef _S_IFMT + #define _S_IFMT 0170000 /* file type mask */ +#endif + +#ifndef S_IFIFO +#define S_IFIFO _S_IFIFO +#endif +//#define S_IFCHR _S_IFCHR +//#define S_IFDIR _S_IFDIR +#ifndef S_IFBLK +#define S_IFBLK _S_IFBLK +#endif +#ifndef S_IFLNK +#define S_IFLNK _S_IFLNK +#endif +#ifndef S_IFSOCK +#define S_IFSOCK _S_IFSOCK +#endif +//#define S_IFREG _S_IFREG +//#define S_IFMT _S_IFMT + +#ifndef S_ISBLK +#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) /* block special */ +#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) /* fifo or socket */ +#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) /* char special */ +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) /* directory */ +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) /* regular file */ +#endif +#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) /* Symbolic link */ +#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) /* Socket */ + +#define _S_ISUID 0004000 /* set user id on execution */ +#define _S_ISGID 0002000 /* set group id on execution */ +#define _S_ISVTX 0001000 /* save swapped text even after use */ + +#define S_ISUID _S_ISUID +#define S_ISGID _S_ISGID +#define S_ISVTX _S_ISVTX + +#define _S_IRWXU (_S_IREAD | _S_IWRITE | _S_IEXEC) +#define _S_IXUSR _S_IEXEC /* read permission, user */ +#define _S_IWUSR _S_IWRITE /* write permission, user */ +#define _S_IRUSR _S_IREAD /* execute/search permission, user */ +#define _S_IRWXG (_S_IRWXU >> 3) +#define _S_IXGRP (_S_IXUSR >> 3) /* read permission, group */ +#define _S_IWGRP (_S_IWUSR >> 3) /* write permission, group */ +#define _S_IRGRP (_S_IRUSR >> 3) /* execute/search permission, group */ +#define _S_IRWXO (_S_IRWXG >> 3) +#define _S_IXOTH (_S_IXGRP >> 3) /* read permission, other */ +#define _S_IWOTH (_S_IWGRP >> 3) /* write permission, other */ +#define _S_IROTH (_S_IRGRP >> 3) /* execute/search permission, other */ + +#ifndef S_IRWXU +#define S_IRWXU _S_IRWXU +#define S_IXUSR _S_IXUSR +#define S_IWUSR _S_IWUSR +#define S_IRUSR _S_IRUSR +#endif +#ifndef S_IRWXG +#define S_IRWXG _S_IRWXG +#define S_IXGRP _S_IXGRP +#define S_IWGRP _S_IWGRP +#endif +#ifndef S_IRGRP +#define S_IRGRP _S_IRGRP +#endif +#ifndef S_IRWXO +#define S_IRWXO _S_IRWXO +#define S_IXOTH _S_IXOTH +#define S_IWOTH _S_IWOTH +#define S_IROTH _S_IROTH +#endif + +#endif + +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#define F_GETOWN 5 /* Get owner (receiver of SIGIO). */ +#define F_SETOWN 6 /* Set owner (receiver of SIGIO). */ +#define F_GETLK 7 /* Get record locking info. */ +#define F_SETLK 8 /* Set record locking info (non-blocking). */ +#define F_SETLKW 9 /* Set record locking info (blocking). */ + +/* XXX missing */ +#define F_GETLK64 7 /* Get record locking info. */ +#define F_SETLK64 8 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 9 /* Set record locking info (blocking). */ + +/* File descriptor flags used with F_GETFD and F_SETFD. */ +#define FD_CLOEXEC 1 /* Close on exec. */ + +//NOT SURE IF O_NONBLOCK is OK here but at least the 0x0004 flag is not used by anything else... +#define O_NONBLOCK 0x0004 /* Non-blocking I/O. */ +//#define O_NDELAY O_NONBLOCK + +/* Symbolic constants for the access() function */ +#if !defined(F_OK) + #define R_OK 4 /* Test for read permission */ + #define W_OK 2 /* Test for write permission */ + #define X_OK 1 /* Test for execute permission */ + #define F_OK 0 /* Test for existence of file */ +#endif + + +/* Replacement POSIX function */ +extern int __la_fstat(int fd, struct stat *st); +extern int __la_lstat(const char *path, struct stat *st); +#if defined(__LA_LSEEK_NEEDED) +extern __int64 __la_lseek(int fd, __int64 offset, int whence); +#endif +extern int __la_open(const char *path, int flags, ...); +extern ssize_t __la_read(int fd, void *buf, size_t nbytes); +extern int __la_stat(const char *path, struct stat *st); +extern pid_t __la_waitpid(HANDLE child, int *status, int option); +extern ssize_t __la_write(int fd, const void *buf, size_t nbytes); + +#define _stat64i32(path, st) __la_stat(path, st) +#define _stat64(path, st) __la_stat(path, st) +/* for status returned by la_waitpid */ +#define WIFEXITED(sts) ((sts & 0x100) == 0) +#define WEXITSTATUS(sts) (sts & 0x0FF) + +extern wchar_t *__la_win_permissive_name(const char *name); +extern wchar_t *__la_win_permissive_name_w(const wchar_t *wname); +extern void __la_dosmaperr(unsigned long e); +#define la_dosmaperr(e) __la_dosmaperr(e) +extern struct archive_entry *__la_win_entry_in_posix_pathseparator( + struct archive_entry *); + +#if defined(HAVE_WCRTOMB) && defined(__BORLANDC__) +typedef int mbstate_t; +size_t wcrtomb(char *, wchar_t, mbstate_t *); +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1300 +WINBASEAPI BOOL WINAPI GetVolumePathNameW( + LPCWSTR lpszFileName, + LPWSTR lpszVolumePathName, + DWORD cchBufferLength + ); +# if _WIN32_WINNT < 0x0500 /* windows.h not providing 0x500 API */ +typedef struct _FILE_ALLOCATED_RANGE_BUFFER { + LARGE_INTEGER FileOffset; + LARGE_INTEGER Length; +} FILE_ALLOCATED_RANGE_BUFFER, *PFILE_ALLOCATED_RANGE_BUFFER; +# define FSCTL_SET_SPARSE \ + CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 49, METHOD_BUFFERED, FILE_WRITE_DATA) +# define FSCTL_QUERY_ALLOCATED_RANGES \ + CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 51, METHOD_NEITHER, FILE_READ_DATA) +# endif +#endif + +#endif /* LIBARCHIVE_ARCHIVE_WINDOWS_H_INCLUDED */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write.3 b/dependencies/libarchive-3.4.2/libarchive/archive_write.3 new file mode 100644 index 0000000..e7f7f13 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write.3 @@ -0,0 +1,268 @@ +.\" Copyright (c) 2003-2011 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 2, 2012 +.Dt ARCHIVE_WRITE 3 +.Os +.Sh NAME +.Nm archive_write +.Nd functions for creating archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive.h +.Sh DESCRIPTION +These functions provide a complete API for creating streaming +archive files. +The general process is to first create the +.Tn struct archive +object, set any desired options, initialize the archive, append entries, then +close the archive and release all resources. +.\" +.Ss Create archive object +See +.Xr archive_write_new 3 . +.Pp +To write an archive, you must first obtain an initialized +.Tn struct archive +object from +.Fn archive_write_new . +.\" +.Ss Enable filters and formats, configure block size and padding +See +.Xr archive_write_filter 3 , +.Xr archive_write_format 3 +and +.Xr archive_write_blocksize 3 . +.Pp +You can then modify this object for the desired operations with the +various +.Fn archive_write_set_XXX +functions. +In particular, you will need to invoke appropriate +.Fn archive_write_add_XXX +and +.Fn archive_write_set_XXX +functions to enable the corresponding compression and format +support. +.\" +.Ss Set options +See +.Xr archive_write_set_options 3 . +.\" +.Ss Open archive +See +.Xr archive_write_open 3 . +.Pp +Once you have prepared the +.Tn struct archive +object, you call +.Fn archive_write_open +to actually open the archive and prepare it for writing. +There are several variants of this function; +the most basic expects you to provide pointers to several +functions that can provide blocks of bytes from the archive. +There are convenience forms that allow you to +specify a filename, file descriptor, +.Ft "FILE *" +object, or a block of memory from which to write the archive data. +.\" +.Ss Produce archive +See +.Xr archive_write_header 3 +and +.Xr archive_write_data 3 . +.Pp +Individual archive entries are written in a three-step +process: +You first initialize a +.Tn struct archive_entry +structure with information about the new entry. +At a minimum, you should set the pathname of the +entry and provide a +.Va struct stat +with a valid +.Va st_mode +field, which specifies the type of object and +.Va st_size +field, which specifies the size of the data portion of the object. +.\" +.Ss Release resources +See +.Xr archive_write_free 3 . +.Pp +After all entries have been written, use the +.Fn archive_write_free +function to release all resources. +.\" +.Sh EXAMPLES +The following sketch illustrates basic usage of the library. +In this example, +the callback functions are simply wrappers around the standard +.Xr open 2 , +.Xr write 2 , +and +.Xr close 2 +system calls. +.Bd -literal -offset indent +#ifdef __linux__ +#define _FILE_OFFSET_BITS 64 +#endif +#include +#include +#include +#include +#include +#include + +struct mydata { + const char *name; + int fd; +}; + +int +myopen(struct archive *a, void *client_data) +{ + struct mydata *mydata = client_data; + + mydata->fd = open(mydata->name, O_WRONLY | O_CREAT, 0644); + if (mydata->fd >= 0) + return (ARCHIVE_OK); + else + return (ARCHIVE_FATAL); +} + +la_ssize_t +mywrite(struct archive *a, void *client_data, const void *buff, size_t n) +{ + struct mydata *mydata = client_data; + + return (write(mydata->fd, buff, n)); +} + +int +myclose(struct archive *a, void *client_data) +{ + struct mydata *mydata = client_data; + + if (mydata->fd > 0) + close(mydata->fd); + return (0); +} + +void +write_archive(const char *outname, const char **filename) +{ + struct mydata *mydata = malloc(sizeof(struct mydata)); + struct archive *a; + struct archive_entry *entry; + struct stat st; + char buff[8192]; + int len; + int fd; + + a = archive_write_new(); + mydata->name = outname; + /* Set archive format and filter according to output file extension. + * If it fails, set default format. Platform depended function. + * See supported formats in archive_write_set_format_filter_by_ext.c */ + if (archive_write_set_format_filter_by_ext(a, outname) != ARCHIVE_OK) { + archive_write_add_filter_gzip(a); + archive_write_set_format_ustar(a); + } + archive_write_open(a, mydata, myopen, mywrite, myclose); + while (*filename) { + stat(*filename, &st); + entry = archive_entry_new(); + archive_entry_copy_stat(entry, &st); + archive_entry_set_pathname(entry, *filename); + archive_write_header(a, entry); + if ((fd = open(*filename, O_RDONLY)) != -1) { + len = read(fd, buff, sizeof(buff)); + while (len > 0) { + archive_write_data(a, buff, len); + len = read(fd, buff, sizeof(buff)); + } + close(fd); + } + archive_entry_free(entry); + filename++; + } + archive_write_free(a); +} + +int main(int argc, const char **argv) +{ + const char *outname; + argv++; + outname = *argv++; + write_archive(outname, argv); + return 0; +} +.Ed +.Sh SEE ALSO +.Xr tar 1 , +.Xr archive_write_set_options 3 , +.Xr libarchive 3 , +.Xr cpio 5 , +.Xr mtree 5 , +.Xr tar 5 +.Sh HISTORY +The +.Nm libarchive +library first appeared in +.Fx 5.3 . +.Sh AUTHORS +.An -nosplit +The +.Nm libarchive +library was written by +.An Tim Kientzle Aq kientzle@acm.org . +.Sh BUGS +There are many peculiar bugs in historic tar implementations that may cause +certain programs to reject archives written by this library. +For example, several historic implementations calculated header checksums +incorrectly and will thus reject valid archives; GNU tar does not fully support +pax interchange format; some old tar implementations required specific +field terminations. +.Pp +The default pax interchange format eliminates most of the historic +tar limitations and provides a generic key/value attribute facility +for vendor-defined extensions. +One oversight in POSIX is the failure to provide a standard attribute +for large device numbers. +This library uses +.Dq SCHILY.devminor +and +.Dq SCHILY.devmajor +for device numbers that exceed the range supported by the backwards-compatible +ustar header. +These keys are compatible with Joerg Schilling's +.Nm star +archiver. +Other implementations may not recognize these keys and will thus be unable +to correctly restore device nodes with large device numbers from archives +created by this library. diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write.c b/dependencies/libarchive-3.4.2/libarchive/archive_write.c new file mode 100644 index 0000000..98a55fb --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write.c @@ -0,0 +1,789 @@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_write.c 201099 2009-12-28 03:03:00Z kientzle $"); + +/* + * This file contains the "essential" portions of the write API, that + * is, stuff that will essentially always be used by any client that + * actually needs to write an archive. Optional pieces have been, as + * far as possible, separated out into separate files to reduce + * needlessly bloating statically-linked clients. + */ + +#ifdef HAVE_SYS_WAIT_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#include +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_write_private.h" + +static struct archive_vtable *archive_write_vtable(void); + +static int _archive_filter_code(struct archive *, int); +static const char *_archive_filter_name(struct archive *, int); +static int64_t _archive_filter_bytes(struct archive *, int); +static int _archive_write_filter_count(struct archive *); +static int _archive_write_close(struct archive *); +static int _archive_write_free(struct archive *); +static int _archive_write_header(struct archive *, struct archive_entry *); +static int _archive_write_finish_entry(struct archive *); +static ssize_t _archive_write_data(struct archive *, const void *, size_t); + +struct archive_none { + size_t buffer_size; + size_t avail; + char *buffer; + char *next; +}; + +static struct archive_vtable * +archive_write_vtable(void) +{ + static struct archive_vtable av; + static int inited = 0; + + if (!inited) { + av.archive_close = _archive_write_close; + av.archive_filter_bytes = _archive_filter_bytes; + av.archive_filter_code = _archive_filter_code; + av.archive_filter_name = _archive_filter_name; + av.archive_filter_count = _archive_write_filter_count; + av.archive_free = _archive_write_free; + av.archive_write_header = _archive_write_header; + av.archive_write_finish_entry = _archive_write_finish_entry; + av.archive_write_data = _archive_write_data; + inited = 1; + } + return (&av); +} + +/* + * Allocate, initialize and return an archive object. + */ +struct archive * +archive_write_new(void) +{ + struct archive_write *a; + unsigned char *nulls; + + a = (struct archive_write *)calloc(1, sizeof(*a)); + if (a == NULL) + return (NULL); + a->archive.magic = ARCHIVE_WRITE_MAGIC; + a->archive.state = ARCHIVE_STATE_NEW; + a->archive.vtable = archive_write_vtable(); + /* + * The value 10240 here matches the traditional tar default, + * but is otherwise arbitrary. + * TODO: Set the default block size from the format selected. + */ + a->bytes_per_block = 10240; + a->bytes_in_last_block = -1; /* Default */ + + /* Initialize a block of nulls for padding purposes. */ + a->null_length = 1024; + nulls = (unsigned char *)calloc(1, a->null_length); + if (nulls == NULL) { + free(a); + return (NULL); + } + a->nulls = nulls; + return (&a->archive); +} + +/* + * Set the block size. Returns 0 if successful. + */ +int +archive_write_set_bytes_per_block(struct archive *_a, int bytes_per_block) +{ + struct archive_write *a = (struct archive_write *)_a; + archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_set_bytes_per_block"); + a->bytes_per_block = bytes_per_block; + return (ARCHIVE_OK); +} + +/* + * Get the current block size. -1 if it has never been set. + */ +int +archive_write_get_bytes_per_block(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_ANY, "archive_write_get_bytes_per_block"); + return (a->bytes_per_block); +} + +/* + * Set the size for the last block. + * Returns 0 if successful. + */ +int +archive_write_set_bytes_in_last_block(struct archive *_a, int bytes) +{ + struct archive_write *a = (struct archive_write *)_a; + archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_ANY, "archive_write_set_bytes_in_last_block"); + a->bytes_in_last_block = bytes; + return (ARCHIVE_OK); +} + +/* + * Return the value set above. -1 indicates it has not been set. + */ +int +archive_write_get_bytes_in_last_block(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_ANY, "archive_write_get_bytes_in_last_block"); + return (a->bytes_in_last_block); +} + +/* + * dev/ino of a file to be rejected. Used to prevent adding + * an archive to itself recursively. + */ +int +archive_write_set_skip_file(struct archive *_a, la_int64_t d, la_int64_t i) +{ + struct archive_write *a = (struct archive_write *)_a; + archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_ANY, "archive_write_set_skip_file"); + a->skip_file_set = 1; + a->skip_file_dev = d; + a->skip_file_ino = i; + return (ARCHIVE_OK); +} + +/* + * Allocate and return the next filter structure. + */ +struct archive_write_filter * +__archive_write_allocate_filter(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct archive_write_filter *f; + + f = calloc(1, sizeof(*f)); + f->archive = _a; + f->state = ARCHIVE_WRITE_FILTER_STATE_NEW; + if (a->filter_first == NULL) + a->filter_first = f; + else + a->filter_last->next_filter = f; + a->filter_last = f; + return f; +} + +/* + * Write data to a particular filter. + */ +int +__archive_write_filter(struct archive_write_filter *f, + const void *buff, size_t length) +{ + int r; + /* Never write to non-open filters */ + if (f->state != ARCHIVE_WRITE_FILTER_STATE_OPEN) + return(ARCHIVE_FATAL); + if (length == 0) + return(ARCHIVE_OK); + if (f->write == NULL) + /* If unset, a fatal error has already occurred, so this filter + * didn't open. We cannot write anything. */ + return(ARCHIVE_FATAL); + r = (f->write)(f, buff, length); + f->bytes_written += length; + return (r); +} + +/* + * Recursive function for opening the filter chain + * Last filter is opened first + */ +static int +__archive_write_open_filter(struct archive_write_filter *f) +{ + int ret; + + ret = ARCHIVE_OK; + if (f->next_filter != NULL) + ret = __archive_write_open_filter(f->next_filter); + if (ret != ARCHIVE_OK) + return (ret); + if (f->state != ARCHIVE_WRITE_FILTER_STATE_NEW) + return (ARCHIVE_FATAL); + if (f->open == NULL) { + f->state = ARCHIVE_WRITE_FILTER_STATE_OPEN; + return (ARCHIVE_OK); + } + ret = (f->open)(f); + if (ret == ARCHIVE_OK) + f->state = ARCHIVE_WRITE_FILTER_STATE_OPEN; + else + f->state = ARCHIVE_WRITE_FILTER_STATE_FATAL; + return (ret); +} + +/* + * Open all filters + */ +static int +__archive_write_filters_open(struct archive_write *a) +{ + return (__archive_write_open_filter(a->filter_first)); +} + +/* + * Close all filtes + */ +static int +__archive_write_filters_close(struct archive_write *a) +{ + struct archive_write_filter *f; + int ret, ret1; + ret = ARCHIVE_OK; + for (f = a->filter_first; f != NULL; f = f->next_filter) { + /* Do not close filters that are not open */ + if (f->state == ARCHIVE_WRITE_FILTER_STATE_OPEN) { + if (f->close != NULL) { + ret1 = (f->close)(f); + if (ret1 < ret) + ret = ret1; + if (ret1 == ARCHIVE_OK) { + f->state = + ARCHIVE_WRITE_FILTER_STATE_CLOSED; + } else { + f->state = + ARCHIVE_WRITE_FILTER_STATE_FATAL; + } + } else + f->state = ARCHIVE_WRITE_FILTER_STATE_CLOSED; + } + } + return (ret); +} + +int +__archive_write_output(struct archive_write *a, const void *buff, size_t length) +{ + return (__archive_write_filter(a->filter_first, buff, length)); +} + +int +__archive_write_nulls(struct archive_write *a, size_t length) +{ + if (length == 0) + return (ARCHIVE_OK); + + while (length > 0) { + size_t to_write = length < a->null_length ? length : a->null_length; + int r = __archive_write_output(a, a->nulls, to_write); + if (r < ARCHIVE_OK) + return (r); + length -= to_write; + } + return (ARCHIVE_OK); +} + +static int +archive_write_client_open(struct archive_write_filter *f) +{ + struct archive_write *a = (struct archive_write *)f->archive; + struct archive_none *state; + void *buffer; + size_t buffer_size; + int ret; + + f->bytes_per_block = archive_write_get_bytes_per_block(f->archive); + f->bytes_in_last_block = + archive_write_get_bytes_in_last_block(f->archive); + buffer_size = f->bytes_per_block; + + state = (struct archive_none *)calloc(1, sizeof(*state)); + buffer = (char *)malloc(buffer_size); + if (state == NULL || buffer == NULL) { + free(state); + free(buffer); + archive_set_error(f->archive, ENOMEM, + "Can't allocate data for output buffering"); + return (ARCHIVE_FATAL); + } + + state->buffer_size = buffer_size; + state->buffer = buffer; + state->next = state->buffer; + state->avail = state->buffer_size; + f->data = state; + + if (a->client_opener == NULL) + return (ARCHIVE_OK); + ret = a->client_opener(f->archive, a->client_data); + if (ret != ARCHIVE_OK) { + free(state->buffer); + free(state); + f->data = NULL; + } + return (ret); +} + +static int +archive_write_client_write(struct archive_write_filter *f, + const void *_buff, size_t length) +{ + struct archive_write *a = (struct archive_write *)f->archive; + struct archive_none *state = (struct archive_none *)f->data; + const char *buff = (const char *)_buff; + ssize_t remaining, to_copy; + ssize_t bytes_written; + + remaining = length; + + /* + * If there is no buffer for blocking, just pass the data + * straight through to the client write callback. In + * particular, this supports "no write delay" operation for + * special applications. Just set the block size to zero. + */ + if (state->buffer_size == 0) { + while (remaining > 0) { + bytes_written = (a->client_writer)(&a->archive, + a->client_data, buff, remaining); + if (bytes_written <= 0) + return (ARCHIVE_FATAL); + remaining -= bytes_written; + buff += bytes_written; + } + return (ARCHIVE_OK); + } + + /* If the copy buffer isn't empty, try to fill it. */ + if (state->avail < state->buffer_size) { + /* If buffer is not empty... */ + /* ... copy data into buffer ... */ + to_copy = ((size_t)remaining > state->avail) ? + state->avail : (size_t)remaining; + memcpy(state->next, buff, to_copy); + state->next += to_copy; + state->avail -= to_copy; + buff += to_copy; + remaining -= to_copy; + /* ... if it's full, write it out. */ + if (state->avail == 0) { + char *p = state->buffer; + size_t to_write = state->buffer_size; + while (to_write > 0) { + bytes_written = (a->client_writer)(&a->archive, + a->client_data, p, to_write); + if (bytes_written <= 0) + return (ARCHIVE_FATAL); + if ((size_t)bytes_written > to_write) { + archive_set_error(&(a->archive), + -1, "write overrun"); + return (ARCHIVE_FATAL); + } + p += bytes_written; + to_write -= bytes_written; + } + state->next = state->buffer; + state->avail = state->buffer_size; + } + } + + while ((size_t)remaining >= state->buffer_size) { + /* Write out full blocks directly to client. */ + bytes_written = (a->client_writer)(&a->archive, + a->client_data, buff, state->buffer_size); + if (bytes_written <= 0) + return (ARCHIVE_FATAL); + buff += bytes_written; + remaining -= bytes_written; + } + + if (remaining > 0) { + /* Copy last bit into copy buffer. */ + memcpy(state->next, buff, remaining); + state->next += remaining; + state->avail -= remaining; + } + return (ARCHIVE_OK); +} + +static int +archive_write_client_close(struct archive_write_filter *f) +{ + struct archive_write *a = (struct archive_write *)f->archive; + struct archive_none *state = (struct archive_none *)f->data; + ssize_t block_length; + ssize_t target_block_length; + ssize_t bytes_written; + int ret = ARCHIVE_OK; + + /* If there's pending data, pad and write the last block */ + if (state->next != state->buffer) { + block_length = state->buffer_size - state->avail; + + /* Tricky calculation to determine size of last block */ + if (a->bytes_in_last_block <= 0) + /* Default or Zero: pad to full block */ + target_block_length = a->bytes_per_block; + else + /* Round to next multiple of bytes_in_last_block. */ + target_block_length = a->bytes_in_last_block * + ( (block_length + a->bytes_in_last_block - 1) / + a->bytes_in_last_block); + if (target_block_length > a->bytes_per_block) + target_block_length = a->bytes_per_block; + if (block_length < target_block_length) { + memset(state->next, 0, + target_block_length - block_length); + block_length = target_block_length; + } + bytes_written = (a->client_writer)(&a->archive, + a->client_data, state->buffer, block_length); + ret = bytes_written <= 0 ? ARCHIVE_FATAL : ARCHIVE_OK; + } + if (a->client_closer) + (*a->client_closer)(&a->archive, a->client_data); + free(state->buffer); + free(state); + a->client_data = NULL; + /* Clear passphrase. */ + if (a->passphrase != NULL) { + memset(a->passphrase, 0, strlen(a->passphrase)); + free(a->passphrase); + a->passphrase = NULL; + } + /* Clear the close handler myself not to be called again. */ + f->state = ARCHIVE_WRITE_FILTER_STATE_CLOSED; + return (ret); +} + +/* + * Open the archive using the current settings. + */ +int +archive_write_open(struct archive *_a, void *client_data, + archive_open_callback *opener, archive_write_callback *writer, + archive_close_callback *closer) +{ + struct archive_write *a = (struct archive_write *)_a; + struct archive_write_filter *client_filter; + int ret, r1; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_open"); + archive_clear_error(&a->archive); + + a->client_writer = writer; + a->client_opener = opener; + a->client_closer = closer; + a->client_data = client_data; + + client_filter = __archive_write_allocate_filter(_a); + client_filter->open = archive_write_client_open; + client_filter->write = archive_write_client_write; + client_filter->close = archive_write_client_close; + + ret = __archive_write_filters_open(a); + if (ret < ARCHIVE_WARN) { + r1 = __archive_write_filters_close(a); + __archive_write_filters_free(_a); + return (r1 < ret ? r1 : ret); + } + + a->archive.state = ARCHIVE_STATE_HEADER; + if (a->format_init) + ret = (a->format_init)(a); + return (ret); +} + +/* + * Close out the archive. + */ +static int +_archive_write_close(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + int r = ARCHIVE_OK, r1 = ARCHIVE_OK; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, + "archive_write_close"); + if (a->archive.state == ARCHIVE_STATE_NEW + || a->archive.state == ARCHIVE_STATE_CLOSED) + return (ARCHIVE_OK); /* Okay to close() when not open. */ + + archive_clear_error(&a->archive); + + /* Finish the last entry if a finish callback is specified */ + if (a->archive.state == ARCHIVE_STATE_DATA + && a->format_finish_entry != NULL) + r = ((a->format_finish_entry)(a)); + + /* Finish off the archive. */ + /* TODO: have format closers invoke compression close. */ + if (a->format_close != NULL) { + r1 = (a->format_close)(a); + if (r1 < r) + r = r1; + } + + /* Finish the compression and close the stream. */ + r1 = __archive_write_filters_close(a); + if (r1 < r) + r = r1; + + if (a->archive.state != ARCHIVE_STATE_FATAL) + a->archive.state = ARCHIVE_STATE_CLOSED; + return (r); +} + +static int +_archive_write_filter_count(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct archive_write_filter *p = a->filter_first; + int count = 0; + while(p) { + count++; + p = p->next_filter; + } + return count; +} + +void +__archive_write_filters_free(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + int r = ARCHIVE_OK, r1; + + while (a->filter_first != NULL) { + struct archive_write_filter *next + = a->filter_first->next_filter; + if (a->filter_first->free != NULL) { + r1 = (*a->filter_first->free)(a->filter_first); + if (r > r1) + r = r1; + } + free(a->filter_first); + a->filter_first = next; + } + a->filter_last = NULL; +} + +/* + * Destroy the archive structure. + * + * Be careful: user might just call write_new and then write_free. + * Don't assume we actually wrote anything or performed any non-trivial + * initialization. + */ +static int +_archive_write_free(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + int r = ARCHIVE_OK, r1; + + if (_a == NULL) + return (ARCHIVE_OK); + /* It is okay to call free() in state FATAL. */ + archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_write_free"); + if (a->archive.state != ARCHIVE_STATE_FATAL) + r = archive_write_close(&a->archive); + + /* Release format resources. */ + if (a->format_free != NULL) { + r1 = (a->format_free)(a); + if (r1 < r) + r = r1; + } + + __archive_write_filters_free(_a); + + /* Release various dynamic buffers. */ + free((void *)(uintptr_t)(const void *)a->nulls); + archive_string_free(&a->archive.error_string); + if (a->passphrase != NULL) { + /* A passphrase should be cleaned. */ + memset(a->passphrase, 0, strlen(a->passphrase)); + free(a->passphrase); + } + a->archive.magic = 0; + __archive_clean(&a->archive); + free(a); + return (r); +} + +/* + * Write the appropriate header. + */ +static int +_archive_write_header(struct archive *_a, struct archive_entry *entry) +{ + struct archive_write *a = (struct archive_write *)_a; + int ret, r2; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_DATA | ARCHIVE_STATE_HEADER, "archive_write_header"); + archive_clear_error(&a->archive); + + if (a->format_write_header == NULL) { + archive_set_error(&(a->archive), -1, + "Format must be set before you can write to an archive."); + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } + + /* In particular, "retry" and "fatal" get returned immediately. */ + ret = archive_write_finish_entry(&a->archive); + if (ret == ARCHIVE_FATAL) { + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } + if (ret < ARCHIVE_OK && ret != ARCHIVE_WARN) + return (ret); + + if (a->skip_file_set && + archive_entry_dev_is_set(entry) && + archive_entry_ino_is_set(entry) && + archive_entry_dev(entry) == (dev_t)a->skip_file_dev && + archive_entry_ino64(entry) == a->skip_file_ino) { + archive_set_error(&a->archive, 0, + "Can't add archive to itself"); + return (ARCHIVE_FAILED); + } + + /* Format and write header. */ + r2 = ((a->format_write_header)(a, entry)); + if (r2 == ARCHIVE_FAILED) { + return (ARCHIVE_FAILED); + } + if (r2 == ARCHIVE_FATAL) { + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } + if (r2 < ret) + ret = r2; + + a->archive.state = ARCHIVE_STATE_DATA; + return (ret); +} + +static int +_archive_write_finish_entry(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + int ret = ARCHIVE_OK; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_write_finish_entry"); + if (a->archive.state & ARCHIVE_STATE_DATA + && a->format_finish_entry != NULL) + ret = (a->format_finish_entry)(a); + a->archive.state = ARCHIVE_STATE_HEADER; + return (ret); +} + +/* + * Note that the compressor is responsible for blocking. + */ +static ssize_t +_archive_write_data(struct archive *_a, const void *buff, size_t s) +{ + struct archive_write *a = (struct archive_write *)_a; + const size_t max_write = INT_MAX; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_DATA, "archive_write_data"); + /* In particular, this catches attempts to pass negative values. */ + if (s > max_write) + s = max_write; + archive_clear_error(&a->archive); + return ((a->format_write_data)(a, buff, s)); +} + +static struct archive_write_filter * +filter_lookup(struct archive *_a, int n) +{ + struct archive_write *a = (struct archive_write *)_a; + struct archive_write_filter *f = a->filter_first; + if (n == -1) + return a->filter_last; + if (n < 0) + return NULL; + while (n > 0 && f != NULL) { + f = f->next_filter; + --n; + } + return f; +} + +static int +_archive_filter_code(struct archive *_a, int n) +{ + struct archive_write_filter *f = filter_lookup(_a, n); + return f == NULL ? -1 : f->code; +} + +static const char * +_archive_filter_name(struct archive *_a, int n) +{ + struct archive_write_filter *f = filter_lookup(_a, n); + return f != NULL ? f->name : NULL; +} + +static int64_t +_archive_filter_bytes(struct archive *_a, int n) +{ + struct archive_write_filter *f = filter_lookup(_a, n); + return f == NULL ? -1 : f->bytes_written; +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter.c new file mode 100644 index 0000000..203f414 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter.c @@ -0,0 +1,72 @@ +/*- + * Copyright (c) 2012 Ondrej Holy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_ERRNO_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" + +/* A table that maps filter codes to functions. */ +static const +struct { int code; int (*setter)(struct archive *); } codes[] = +{ + { ARCHIVE_FILTER_NONE, archive_write_add_filter_none }, + { ARCHIVE_FILTER_GZIP, archive_write_add_filter_gzip }, + { ARCHIVE_FILTER_BZIP2, archive_write_add_filter_bzip2 }, + { ARCHIVE_FILTER_COMPRESS, archive_write_add_filter_compress }, + { ARCHIVE_FILTER_GRZIP, archive_write_add_filter_grzip }, + { ARCHIVE_FILTER_LRZIP, archive_write_add_filter_lrzip }, + { ARCHIVE_FILTER_LZ4, archive_write_add_filter_lz4 }, + { ARCHIVE_FILTER_LZIP, archive_write_add_filter_lzip }, + { ARCHIVE_FILTER_LZMA, archive_write_add_filter_lzma }, + { ARCHIVE_FILTER_LZOP, archive_write_add_filter_lzip }, + { ARCHIVE_FILTER_UU, archive_write_add_filter_uuencode }, + { ARCHIVE_FILTER_XZ, archive_write_add_filter_xz }, + { ARCHIVE_FILTER_ZSTD, archive_write_add_filter_zstd }, + { -1, NULL } +}; + +int +archive_write_add_filter(struct archive *a, int code) +{ + int i; + + for (i = 0; codes[i].code != -1; i++) { + if (code == codes[i].code) + return ((codes[i].setter)(a)); + } + + archive_set_error(a, EINVAL, "No such filter"); + return (ARCHIVE_FATAL); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_b64encode.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_b64encode.c new file mode 100644 index 0000000..87fdb73 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_b64encode.c @@ -0,0 +1,304 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_string.h" +#include "archive_write_private.h" + +#define LBYTES 57 + +struct private_b64encode { + int mode; + struct archive_string name; + struct archive_string encoded_buff; + size_t bs; + size_t hold_len; + unsigned char hold[LBYTES]; +}; + +static int archive_filter_b64encode_options(struct archive_write_filter *, + const char *, const char *); +static int archive_filter_b64encode_open(struct archive_write_filter *); +static int archive_filter_b64encode_write(struct archive_write_filter *, + const void *, size_t); +static int archive_filter_b64encode_close(struct archive_write_filter *); +static int archive_filter_b64encode_free(struct archive_write_filter *); +static void la_b64_encode(struct archive_string *, const unsigned char *, size_t); +static int64_t atol8(const char *, size_t); + +static const char base64[] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '+', '/' +}; + +/* + * Add a compress filter to this write handle. + */ +int +archive_write_add_filter_b64encode(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct archive_write_filter *f = __archive_write_allocate_filter(_a); + struct private_b64encode *state; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_add_filter_uu"); + + state = (struct private_b64encode *)calloc(1, sizeof(*state)); + if (state == NULL) { + archive_set_error(f->archive, ENOMEM, + "Can't allocate data for b64encode filter"); + return (ARCHIVE_FATAL); + } + archive_strcpy(&state->name, "-"); + state->mode = 0644; + + f->data = state; + f->name = "b64encode"; + f->code = ARCHIVE_FILTER_UU; + f->open = archive_filter_b64encode_open; + f->options = archive_filter_b64encode_options; + f->write = archive_filter_b64encode_write; + f->close = archive_filter_b64encode_close; + f->free = archive_filter_b64encode_free; + + return (ARCHIVE_OK); +} + +/* + * Set write options. + */ +static int +archive_filter_b64encode_options(struct archive_write_filter *f, const char *key, + const char *value) +{ + struct private_b64encode *state = (struct private_b64encode *)f->data; + + if (strcmp(key, "mode") == 0) { + if (value == NULL) { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "mode option requires octal digits"); + return (ARCHIVE_FAILED); + } + state->mode = (int)atol8(value, strlen(value)) & 0777; + return (ARCHIVE_OK); + } else if (strcmp(key, "name") == 0) { + if (value == NULL) { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "name option requires a string"); + return (ARCHIVE_FAILED); + } + archive_strcpy(&state->name, value); + return (ARCHIVE_OK); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +/* + * Setup callback. + */ +static int +archive_filter_b64encode_open(struct archive_write_filter *f) +{ + struct private_b64encode *state = (struct private_b64encode *)f->data; + size_t bs = 65536, bpb; + + if (f->archive->magic == ARCHIVE_WRITE_MAGIC) { + /* Buffer size should be a multiple number of the of bytes + * per block for performance. */ + bpb = archive_write_get_bytes_per_block(f->archive); + if (bpb > bs) + bs = bpb; + else if (bpb != 0) + bs -= bs % bpb; + } + + state->bs = bs; + if (archive_string_ensure(&state->encoded_buff, bs + 512) == NULL) { + archive_set_error(f->archive, ENOMEM, + "Can't allocate data for b64encode buffer"); + return (ARCHIVE_FATAL); + } + + archive_string_sprintf(&state->encoded_buff, "begin-base64 %o %s\n", + state->mode, state->name.s); + + f->data = state; + return (0); +} + +static void +la_b64_encode(struct archive_string *as, const unsigned char *p, size_t len) +{ + int c; + + for (; len >= 3; p += 3, len -= 3) { + c = p[0] >> 2; + archive_strappend_char(as, base64[c]); + c = ((p[0] & 0x03) << 4) | ((p[1] & 0xf0) >> 4); + archive_strappend_char(as, base64[c]); + c = ((p[1] & 0x0f) << 2) | ((p[2] & 0xc0) >> 6); + archive_strappend_char(as, base64[c]); + c = p[2] & 0x3f; + archive_strappend_char(as, base64[c]); + } + if (len > 0) { + c = p[0] >> 2; + archive_strappend_char(as, base64[c]); + c = (p[0] & 0x03) << 4; + if (len == 1) { + archive_strappend_char(as, base64[c]); + archive_strappend_char(as, '='); + archive_strappend_char(as, '='); + } else { + c |= (p[1] & 0xf0) >> 4; + archive_strappend_char(as, base64[c]); + c = (p[1] & 0x0f) << 2; + archive_strappend_char(as, base64[c]); + archive_strappend_char(as, '='); + } + } + archive_strappend_char(as, '\n'); +} + +/* + * Write data to the encoded stream. + */ +static int +archive_filter_b64encode_write(struct archive_write_filter *f, const void *buff, + size_t length) +{ + struct private_b64encode *state = (struct private_b64encode *)f->data; + const unsigned char *p = buff; + int ret = ARCHIVE_OK; + + if (length == 0) + return (ret); + + if (state->hold_len) { + while (state->hold_len < LBYTES && length > 0) { + state->hold[state->hold_len++] = *p++; + length--; + } + if (state->hold_len < LBYTES) + return (ret); + la_b64_encode(&state->encoded_buff, state->hold, LBYTES); + state->hold_len = 0; + } + + for (; length >= LBYTES; length -= LBYTES, p += LBYTES) + la_b64_encode(&state->encoded_buff, p, LBYTES); + + /* Save remaining bytes. */ + if (length > 0) { + memcpy(state->hold, p, length); + state->hold_len = length; + } + while (archive_strlen(&state->encoded_buff) >= state->bs) { + ret = __archive_write_filter(f->next_filter, + state->encoded_buff.s, state->bs); + memmove(state->encoded_buff.s, + state->encoded_buff.s + state->bs, + state->encoded_buff.length - state->bs); + state->encoded_buff.length -= state->bs; + } + + return (ret); +} + + +/* + * Finish the compression... + */ +static int +archive_filter_b64encode_close(struct archive_write_filter *f) +{ + struct private_b64encode *state = (struct private_b64encode *)f->data; + + /* Flush remaining bytes. */ + if (state->hold_len != 0) + la_b64_encode(&state->encoded_buff, state->hold, state->hold_len); + archive_string_sprintf(&state->encoded_buff, "====\n"); + /* Write the last block */ + archive_write_set_bytes_in_last_block(f->archive, 1); + return __archive_write_filter(f->next_filter, + state->encoded_buff.s, archive_strlen(&state->encoded_buff)); +} + +static int +archive_filter_b64encode_free(struct archive_write_filter *f) +{ + struct private_b64encode *state = (struct private_b64encode *)f->data; + + archive_string_free(&state->name); + archive_string_free(&state->encoded_buff); + free(state); + return (ARCHIVE_OK); +} + +static int64_t +atol8(const char *p, size_t char_cnt) +{ + int64_t l; + int digit; + + l = 0; + while (char_cnt-- > 0) { + if (*p >= '0' && *p <= '7') + digit = *p - '0'; + else + break; + p++; + l <<= 3; + l |= digit; + } + return (l); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_by_name.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_by_name.c new file mode 100644 index 0000000..ffa633c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_by_name.c @@ -0,0 +1,77 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" + +/* A table that maps names to functions. */ +static const +struct { const char *name; int (*setter)(struct archive *); } names[] = +{ + { "b64encode", archive_write_add_filter_b64encode }, + { "bzip2", archive_write_add_filter_bzip2 }, + { "compress", archive_write_add_filter_compress }, + { "grzip", archive_write_add_filter_grzip }, + { "gzip", archive_write_add_filter_gzip }, + { "lrzip", archive_write_add_filter_lrzip }, + { "lz4", archive_write_add_filter_lz4 }, + { "lzip", archive_write_add_filter_lzip }, + { "lzma", archive_write_add_filter_lzma }, + { "lzop", archive_write_add_filter_lzop }, + { "uuencode", archive_write_add_filter_uuencode }, + { "xz", archive_write_add_filter_xz }, + { "zstd", archive_write_add_filter_zstd }, + { NULL, NULL } +}; + +int +archive_write_add_filter_by_name(struct archive *a, const char *name) +{ + int i; + + for (i = 0; names[i].name != NULL; i++) { + if (strcmp(name, names[i].name) == 0) + return ((names[i].setter)(a)); + } + + archive_set_error(a, EINVAL, "No such filter '%s'", name); + a->state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_bzip2.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_bzip2.c new file mode 100644 index 0000000..7001e9c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_bzip2.c @@ -0,0 +1,401 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_compression_bzip2.c 201091 2009-12-28 02:22:41Z kientzle $"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_BZLIB_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_write_private.h" + +#if ARCHIVE_VERSION_NUMBER < 4000000 +int +archive_write_set_compression_bzip2(struct archive *a) +{ + __archive_write_filters_free(a); + return (archive_write_add_filter_bzip2(a)); +} +#endif + +struct private_data { + int compression_level; +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) + bz_stream stream; + int64_t total_in; + char *compressed; + size_t compressed_buffer_size; +#else + struct archive_write_program_data *pdata; +#endif +}; + +static int archive_compressor_bzip2_close(struct archive_write_filter *); +static int archive_compressor_bzip2_free(struct archive_write_filter *); +static int archive_compressor_bzip2_open(struct archive_write_filter *); +static int archive_compressor_bzip2_options(struct archive_write_filter *, + const char *, const char *); +static int archive_compressor_bzip2_write(struct archive_write_filter *, + const void *, size_t); + +/* + * Add a bzip2 compression filter to this write handle. + */ +int +archive_write_add_filter_bzip2(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct archive_write_filter *f = __archive_write_allocate_filter(_a); + struct private_data *data; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_add_filter_bzip2"); + + data = calloc(1, sizeof(*data)); + if (data == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + data->compression_level = 9; /* default */ + + f->data = data; + f->options = &archive_compressor_bzip2_options; + f->close = &archive_compressor_bzip2_close; + f->free = &archive_compressor_bzip2_free; + f->open = &archive_compressor_bzip2_open; + f->code = ARCHIVE_FILTER_BZIP2; + f->name = "bzip2"; +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) + return (ARCHIVE_OK); +#else + data->pdata = __archive_write_program_allocate("bzip2"); + if (data->pdata == NULL) { + free(data); + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + data->compression_level = 0; + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Using external bzip2 program"); + return (ARCHIVE_WARN); +#endif +} + +/* + * Set write options. + */ +static int +archive_compressor_bzip2_options(struct archive_write_filter *f, + const char *key, const char *value) +{ + struct private_data *data = (struct private_data *)f->data; + + if (strcmp(key, "compression-level") == 0) { + if (value == NULL || !(value[0] >= '0' && value[0] <= '9') || + value[1] != '\0') + return (ARCHIVE_WARN); + data->compression_level = value[0] - '0'; + /* Make '0' be a synonym for '1'. */ + /* This way, bzip2 compressor supports the same 0..9 + * range of levels as gzip. */ + if (data->compression_level < 1) + data->compression_level = 1; + return (ARCHIVE_OK); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) +/* Don't compile this if we don't have bzlib. */ + +/* + * Yuck. bzlib.h is not const-correct, so I need this one bit + * of ugly hackery to convert a const * pointer to a non-const pointer. + */ +#define SET_NEXT_IN(st,src) \ + (st)->stream.next_in = (char *)(uintptr_t)(const void *)(src) +static int drive_compressor(struct archive_write_filter *, + struct private_data *, int finishing); + +/* + * Setup callback. + */ +static int +archive_compressor_bzip2_open(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + int ret; + + if (data->compressed == NULL) { + size_t bs = 65536, bpb; + if (f->archive->magic == ARCHIVE_WRITE_MAGIC) { + /* Buffer size should be a multiple number of the of bytes + * per block for performance. */ + bpb = archive_write_get_bytes_per_block(f->archive); + if (bpb > bs) + bs = bpb; + else if (bpb != 0) + bs -= bs % bpb; + } + data->compressed_buffer_size = bs; + data->compressed + = (char *)malloc(data->compressed_buffer_size); + if (data->compressed == NULL) { + archive_set_error(f->archive, ENOMEM, + "Can't allocate data for compression buffer"); + return (ARCHIVE_FATAL); + } + } + + memset(&data->stream, 0, sizeof(data->stream)); + data->stream.next_out = data->compressed; + data->stream.avail_out = data->compressed_buffer_size; + f->write = archive_compressor_bzip2_write; + + /* Initialize compression library */ + ret = BZ2_bzCompressInit(&(data->stream), + data->compression_level, 0, 30); + if (ret == BZ_OK) { + f->data = data; + return (ARCHIVE_OK); + } + + /* Library setup failed: clean up. */ + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "Internal error initializing compression library"); + + /* Override the error message if we know what really went wrong. */ + switch (ret) { + case BZ_PARAM_ERROR: + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "Internal error initializing compression library: " + "invalid setup parameter"); + break; + case BZ_MEM_ERROR: + archive_set_error(f->archive, ENOMEM, + "Internal error initializing compression library: " + "out of memory"); + break; + case BZ_CONFIG_ERROR: + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "Internal error initializing compression library: " + "mis-compiled library"); + break; + } + + return (ARCHIVE_FATAL); + +} + +/* + * Write data to the compressed stream. + * + * Returns ARCHIVE_OK if all data written, error otherwise. + */ +static int +archive_compressor_bzip2_write(struct archive_write_filter *f, + const void *buff, size_t length) +{ + struct private_data *data = (struct private_data *)f->data; + + /* Update statistics */ + data->total_in += length; + + /* Compress input data to output buffer */ + SET_NEXT_IN(data, buff); + data->stream.avail_in = length; + if (drive_compressor(f, data, 0)) + return (ARCHIVE_FATAL); + return (ARCHIVE_OK); +} + + +/* + * Finish the compression. + */ +static int +archive_compressor_bzip2_close(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + int ret; + + /* Finish compression cycle. */ + ret = drive_compressor(f, data, 1); + if (ret == ARCHIVE_OK) { + /* Write the last block */ + ret = __archive_write_filter(f->next_filter, + data->compressed, + data->compressed_buffer_size - data->stream.avail_out); + } + + switch (BZ2_bzCompressEnd(&(data->stream))) { + case BZ_OK: + break; + default: + archive_set_error(f->archive, ARCHIVE_ERRNO_PROGRAMMER, + "Failed to clean up compressor"); + ret = ARCHIVE_FATAL; + } + return ret; +} + +static int +archive_compressor_bzip2_free(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + free(data->compressed); + free(data); + f->data = NULL; + return (ARCHIVE_OK); +} + +/* + * Utility function to push input data through compressor, writing + * full output blocks as necessary. + * + * Note that this handles both the regular write case (finishing == + * false) and the end-of-archive case (finishing == true). + */ +static int +drive_compressor(struct archive_write_filter *f, + struct private_data *data, int finishing) +{ + int ret; + + for (;;) { + if (data->stream.avail_out == 0) { + ret = __archive_write_filter(f->next_filter, + data->compressed, + data->compressed_buffer_size); + if (ret != ARCHIVE_OK) { + /* TODO: Handle this write failure */ + return (ARCHIVE_FATAL); + } + data->stream.next_out = data->compressed; + data->stream.avail_out = data->compressed_buffer_size; + } + + /* If there's nothing to do, we're done. */ + if (!finishing && data->stream.avail_in == 0) + return (ARCHIVE_OK); + + ret = BZ2_bzCompress(&(data->stream), + finishing ? BZ_FINISH : BZ_RUN); + + switch (ret) { + case BZ_RUN_OK: + /* In non-finishing case, did compressor + * consume everything? */ + if (!finishing && data->stream.avail_in == 0) + return (ARCHIVE_OK); + break; + case BZ_FINISH_OK: /* Finishing: There's more work to do */ + break; + case BZ_STREAM_END: /* Finishing: all done */ + /* Only occurs in finishing case */ + return (ARCHIVE_OK); + default: + /* Any other return value indicates an error */ + archive_set_error(f->archive, + ARCHIVE_ERRNO_PROGRAMMER, + "Bzip2 compression failed;" + " BZ2_bzCompress() returned %d", + ret); + return (ARCHIVE_FATAL); + } + } +} + +#else /* HAVE_BZLIB_H && BZ_CONFIG_ERROR */ + +static int +archive_compressor_bzip2_open(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + struct archive_string as; + int r; + + archive_string_init(&as); + archive_strcpy(&as, "bzip2"); + + /* Specify compression level. */ + if (data->compression_level > 0) { + archive_strcat(&as, " -"); + archive_strappend_char(&as, '0' + data->compression_level); + } + f->write = archive_compressor_bzip2_write; + + r = __archive_write_program_open(f, data->pdata, as.s); + archive_string_free(&as); + return (r); +} + +static int +archive_compressor_bzip2_write(struct archive_write_filter *f, const void *buff, + size_t length) +{ + struct private_data *data = (struct private_data *)f->data; + + return __archive_write_program_write(f, data->pdata, buff, length); +} + +static int +archive_compressor_bzip2_close(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + + return __archive_write_program_close(f, data->pdata); +} + +static int +archive_compressor_bzip2_free(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + + __archive_write_program_free(data->pdata); + free(data); + return (ARCHIVE_OK); +} + +#endif /* HAVE_BZLIB_H && BZ_CONFIG_ERROR */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_compress.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_compress.c new file mode 100644 index 0000000..d404fae --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_compress.c @@ -0,0 +1,447 @@ +/*- + * Copyright (c) 2008 Joerg Sonnenberger + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1985, 1986, 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Diomidis Spinellis and James A. Woods, derived from original + * work by Spencer Thomas and Joseph Orost. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_compression_compress.c 201111 2009-12-28 03:33:05Z kientzle $"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_write_private.h" + +#define HSIZE 69001 /* 95% occupancy */ +#define HSHIFT 8 /* 8 - trunc(log2(HSIZE / 65536)) */ +#define CHECK_GAP 10000 /* Ratio check interval. */ + +#define MAXCODE(bits) ((1 << (bits)) - 1) + +/* + * the next two codes should not be changed lightly, as they must not + * lie within the contiguous general code space. + */ +#define FIRST 257 /* First free entry. */ +#define CLEAR 256 /* Table clear output code. */ + +struct private_data { + int64_t in_count, out_count, checkpoint; + + int code_len; /* Number of bits/code. */ + int cur_maxcode; /* Maximum code, given n_bits. */ + int max_maxcode; /* Should NEVER generate this code. */ + int hashtab [HSIZE]; + unsigned short codetab [HSIZE]; + int first_free; /* First unused entry. */ + int compress_ratio; + + int cur_code, cur_fcode; + + int bit_offset; + unsigned char bit_buf; + + unsigned char *compressed; + size_t compressed_buffer_size; + size_t compressed_offset; +}; + +static int archive_compressor_compress_open(struct archive_write_filter *); +static int archive_compressor_compress_write(struct archive_write_filter *, + const void *, size_t); +static int archive_compressor_compress_close(struct archive_write_filter *); +static int archive_compressor_compress_free(struct archive_write_filter *); + +#if ARCHIVE_VERSION_NUMBER < 4000000 +int +archive_write_set_compression_compress(struct archive *a) +{ + __archive_write_filters_free(a); + return (archive_write_add_filter_compress(a)); +} +#endif + +/* + * Add a compress filter to this write handle. + */ +int +archive_write_add_filter_compress(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct archive_write_filter *f = __archive_write_allocate_filter(_a); + + archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_add_filter_compress"); + f->open = &archive_compressor_compress_open; + f->code = ARCHIVE_FILTER_COMPRESS; + f->name = "compress"; + return (ARCHIVE_OK); +} + +/* + * Setup callback. + */ +static int +archive_compressor_compress_open(struct archive_write_filter *f) +{ + struct private_data *state; + size_t bs = 65536, bpb; + + f->code = ARCHIVE_FILTER_COMPRESS; + f->name = "compress"; + + state = (struct private_data *)calloc(1, sizeof(*state)); + if (state == NULL) { + archive_set_error(f->archive, ENOMEM, + "Can't allocate data for compression"); + return (ARCHIVE_FATAL); + } + + if (f->archive->magic == ARCHIVE_WRITE_MAGIC) { + /* Buffer size should be a multiple number of the of bytes + * per block for performance. */ + bpb = archive_write_get_bytes_per_block(f->archive); + if (bpb > bs) + bs = bpb; + else if (bpb != 0) + bs -= bs % bpb; + } + state->compressed_buffer_size = bs; + state->compressed = malloc(state->compressed_buffer_size); + + if (state->compressed == NULL) { + archive_set_error(f->archive, ENOMEM, + "Can't allocate data for compression buffer"); + free(state); + return (ARCHIVE_FATAL); + } + + f->write = archive_compressor_compress_write; + f->close = archive_compressor_compress_close; + f->free = archive_compressor_compress_free; + + state->max_maxcode = 0x10000; /* Should NEVER generate this code. */ + state->in_count = 0; /* Length of input. */ + state->bit_buf = 0; + state->bit_offset = 0; + state->out_count = 3; /* Includes 3-byte header mojo. */ + state->compress_ratio = 0; + state->checkpoint = CHECK_GAP; + state->code_len = 9; + state->cur_maxcode = MAXCODE(state->code_len); + state->first_free = FIRST; + + memset(state->hashtab, 0xff, sizeof(state->hashtab)); + + /* Prime output buffer with a gzip header. */ + state->compressed[0] = 0x1f; /* Compress */ + state->compressed[1] = 0x9d; + state->compressed[2] = 0x90; /* Block mode, 16bit max */ + state->compressed_offset = 3; + + f->data = state; + return (0); +} + +/*- + * Output the given code. + * Inputs: + * code: A n_bits-bit integer. If == -1, then EOF. This assumes + * that n_bits <= (long)wordsize - 1. + * Outputs: + * Outputs code to the file. + * Assumptions: + * Chars are 8 bits long. + * Algorithm: + * Maintain a BITS character long buffer (so that 8 codes will + * fit in it exactly). Use the VAX insv instruction to insert each + * code in turn. When the buffer fills up empty it and start over. + */ + +static const unsigned char rmask[9] = + {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; + +static int +output_byte(struct archive_write_filter *f, unsigned char c) +{ + struct private_data *state = f->data; + + state->compressed[state->compressed_offset++] = c; + ++state->out_count; + + if (state->compressed_buffer_size == state->compressed_offset) { + int ret = __archive_write_filter(f->next_filter, + state->compressed, state->compressed_buffer_size); + if (ret != ARCHIVE_OK) + return ARCHIVE_FATAL; + state->compressed_offset = 0; + } + + return ARCHIVE_OK; +} + +static int +output_code(struct archive_write_filter *f, int ocode) +{ + struct private_data *state = f->data; + int bits, ret, clear_flg, bit_offset; + + clear_flg = ocode == CLEAR; + + /* + * Since ocode is always >= 8 bits, only need to mask the first + * hunk on the left. + */ + bit_offset = state->bit_offset % 8; + state->bit_buf |= (ocode << bit_offset) & 0xff; + output_byte(f, state->bit_buf); + + bits = state->code_len - (8 - bit_offset); + ocode >>= 8 - bit_offset; + /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */ + if (bits >= 8) { + output_byte(f, ocode & 0xff); + ocode >>= 8; + bits -= 8; + } + /* Last bits. */ + state->bit_offset += state->code_len; + state->bit_buf = ocode & rmask[bits]; + if (state->bit_offset == state->code_len * 8) + state->bit_offset = 0; + + /* + * If the next entry is going to be too big for the ocode size, + * then increase it, if possible. + */ + if (clear_flg || state->first_free > state->cur_maxcode) { + /* + * Write the whole buffer, because the input side won't + * discover the size increase until after it has read it. + */ + if (state->bit_offset > 0) { + while (state->bit_offset < state->code_len * 8) { + ret = output_byte(f, state->bit_buf); + if (ret != ARCHIVE_OK) + return ret; + state->bit_offset += 8; + state->bit_buf = 0; + } + } + state->bit_buf = 0; + state->bit_offset = 0; + + if (clear_flg) { + state->code_len = 9; + state->cur_maxcode = MAXCODE(state->code_len); + } else { + state->code_len++; + if (state->code_len == 16) + state->cur_maxcode = state->max_maxcode; + else + state->cur_maxcode = MAXCODE(state->code_len); + } + } + + return (ARCHIVE_OK); +} + +static int +output_flush(struct archive_write_filter *f) +{ + struct private_data *state = f->data; + int ret; + + /* At EOF, write the rest of the buffer. */ + if (state->bit_offset % 8) { + state->code_len = (state->bit_offset % 8 + 7) / 8; + ret = output_byte(f, state->bit_buf); + if (ret != ARCHIVE_OK) + return ret; + } + + return (ARCHIVE_OK); +} + +/* + * Write data to the compressed stream. + */ +static int +archive_compressor_compress_write(struct archive_write_filter *f, + const void *buff, size_t length) +{ + struct private_data *state = (struct private_data *)f->data; + int i; + int ratio; + int c, disp, ret; + const unsigned char *bp; + + if (length == 0) + return ARCHIVE_OK; + + bp = buff; + + if (state->in_count == 0) { + state->cur_code = *bp++; + ++state->in_count; + --length; + } + + while (length--) { + c = *bp++; + state->in_count++; + state->cur_fcode = (c << 16) + state->cur_code; + i = ((c << HSHIFT) ^ state->cur_code); /* Xor hashing. */ + + if (state->hashtab[i] == state->cur_fcode) { + state->cur_code = state->codetab[i]; + continue; + } + if (state->hashtab[i] < 0) /* Empty slot. */ + goto nomatch; + /* Secondary hash (after G. Knott). */ + if (i == 0) + disp = 1; + else + disp = HSIZE - i; + probe: + if ((i -= disp) < 0) + i += HSIZE; + + if (state->hashtab[i] == state->cur_fcode) { + state->cur_code = state->codetab[i]; + continue; + } + if (state->hashtab[i] >= 0) + goto probe; + nomatch: + ret = output_code(f, state->cur_code); + if (ret != ARCHIVE_OK) + return ret; + state->cur_code = c; + if (state->first_free < state->max_maxcode) { + state->codetab[i] = state->first_free++; /* code -> hashtable */ + state->hashtab[i] = state->cur_fcode; + continue; + } + if (state->in_count < state->checkpoint) + continue; + + state->checkpoint = state->in_count + CHECK_GAP; + + if (state->in_count <= 0x007fffff && state->out_count != 0) + ratio = (int)(state->in_count * 256 / state->out_count); + else if ((ratio = (int)(state->out_count / 256)) == 0) + ratio = 0x7fffffff; + else + ratio = (int)(state->in_count / ratio); + + if (ratio > state->compress_ratio) + state->compress_ratio = ratio; + else { + state->compress_ratio = 0; + memset(state->hashtab, 0xff, sizeof(state->hashtab)); + state->first_free = FIRST; + ret = output_code(f, CLEAR); + if (ret != ARCHIVE_OK) + return ret; + } + } + + return (ARCHIVE_OK); +} + + +/* + * Finish the compression... + */ +static int +archive_compressor_compress_close(struct archive_write_filter *f) +{ + struct private_data *state = (struct private_data *)f->data; + int ret; + + ret = output_code(f, state->cur_code); + if (ret != ARCHIVE_OK) + return ret; + ret = output_flush(f); + if (ret != ARCHIVE_OK) + return ret; + + /* Write the last block */ + ret = __archive_write_filter(f->next_filter, + state->compressed, state->compressed_offset); + return (ret); +} + +static int +archive_compressor_compress_free(struct archive_write_filter *f) +{ + struct private_data *state = (struct private_data *)f->data; + + free(state->compressed); + free(state); + return (ARCHIVE_OK); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_grzip.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_grzip.c new file mode 100644 index 0000000..371102d --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_grzip.c @@ -0,0 +1,135 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif + +#include "archive.h" +#include "archive_write_private.h" + +struct write_grzip { + struct archive_write_program_data *pdata; +}; + +static int archive_write_grzip_open(struct archive_write_filter *); +static int archive_write_grzip_options(struct archive_write_filter *, + const char *, const char *); +static int archive_write_grzip_write(struct archive_write_filter *, + const void *, size_t); +static int archive_write_grzip_close(struct archive_write_filter *); +static int archive_write_grzip_free(struct archive_write_filter *); + +int +archive_write_add_filter_grzip(struct archive *_a) +{ + struct archive_write_filter *f = __archive_write_allocate_filter(_a); + struct write_grzip *data; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_add_filter_grzip"); + + data = calloc(1, sizeof(*data)); + if (data == NULL) { + archive_set_error(_a, ENOMEM, "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + data->pdata = __archive_write_program_allocate("grzip"); + if (data->pdata == NULL) { + free(data); + archive_set_error(_a, ENOMEM, "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + + f->name = "grzip"; + f->code = ARCHIVE_FILTER_GRZIP; + f->data = data; + f->open = archive_write_grzip_open; + f->options = archive_write_grzip_options; + f->write = archive_write_grzip_write; + f->close = archive_write_grzip_close; + f->free = archive_write_grzip_free; + + /* Note: This filter always uses an external program, so we + * return "warn" to inform of the fact. */ + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "Using external grzip program for grzip compression"); + return (ARCHIVE_WARN); +} + +static int +archive_write_grzip_options(struct archive_write_filter *f, const char *key, + const char *value) +{ + (void)f; /* UNUSED */ + (void)key; /* UNUSED */ + (void)value; /* UNUSED */ + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +static int +archive_write_grzip_open(struct archive_write_filter *f) +{ + struct write_grzip *data = (struct write_grzip *)f->data; + + return __archive_write_program_open(f, data->pdata, "grzip"); +} + +static int +archive_write_grzip_write(struct archive_write_filter *f, + const void *buff, size_t length) +{ + struct write_grzip *data = (struct write_grzip *)f->data; + + return __archive_write_program_write(f, data->pdata, buff, length); +} + +static int +archive_write_grzip_close(struct archive_write_filter *f) +{ + struct write_grzip *data = (struct write_grzip *)f->data; + + return __archive_write_program_close(f, data->pdata); +} + +static int +archive_write_grzip_free(struct archive_write_filter *f) +{ + struct write_grzip *data = (struct write_grzip *)f->data; + + __archive_write_program_free(data->pdata); + free(data); + return (ARCHIVE_OK); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_gzip.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_gzip.c new file mode 100644 index 0000000..8670d5c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_gzip.c @@ -0,0 +1,442 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_compression_gzip.c 201081 2009-12-28 02:04:42Z kientzle $"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#include +#ifdef HAVE_ZLIB_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_string.h" +#include "archive_write_private.h" + +#if ARCHIVE_VERSION_NUMBER < 4000000 +int +archive_write_set_compression_gzip(struct archive *a) +{ + __archive_write_filters_free(a); + return (archive_write_add_filter_gzip(a)); +} +#endif + +/* Don't compile this if we don't have zlib. */ + +struct private_data { + int compression_level; + int timestamp; +#ifdef HAVE_ZLIB_H + z_stream stream; + int64_t total_in; + unsigned char *compressed; + size_t compressed_buffer_size; + unsigned long crc; +#else + struct archive_write_program_data *pdata; +#endif +}; + +/* + * Yuck. zlib.h is not const-correct, so I need this one bit + * of ugly hackery to convert a const * pointer to a non-const pointer. + */ +#define SET_NEXT_IN(st,src) \ + (st)->stream.next_in = (Bytef *)(uintptr_t)(const void *)(src) + +static int archive_compressor_gzip_options(struct archive_write_filter *, + const char *, const char *); +static int archive_compressor_gzip_open(struct archive_write_filter *); +static int archive_compressor_gzip_write(struct archive_write_filter *, + const void *, size_t); +static int archive_compressor_gzip_close(struct archive_write_filter *); +static int archive_compressor_gzip_free(struct archive_write_filter *); +#ifdef HAVE_ZLIB_H +static int drive_compressor(struct archive_write_filter *, + struct private_data *, int finishing); +#endif + + +/* + * Add a gzip compression filter to this write handle. + */ +int +archive_write_add_filter_gzip(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct archive_write_filter *f = __archive_write_allocate_filter(_a); + struct private_data *data; + archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_add_filter_gzip"); + + data = calloc(1, sizeof(*data)); + if (data == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + f->data = data; + f->open = &archive_compressor_gzip_open; + f->options = &archive_compressor_gzip_options; + f->close = &archive_compressor_gzip_close; + f->free = &archive_compressor_gzip_free; + f->code = ARCHIVE_FILTER_GZIP; + f->name = "gzip"; +#ifdef HAVE_ZLIB_H + data->compression_level = Z_DEFAULT_COMPRESSION; + return (ARCHIVE_OK); +#else + data->pdata = __archive_write_program_allocate("gzip"); + if (data->pdata == NULL) { + free(data); + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + data->compression_level = 0; + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Using external gzip program"); + return (ARCHIVE_WARN); +#endif +} + +static int +archive_compressor_gzip_free(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + +#ifdef HAVE_ZLIB_H + free(data->compressed); +#else + __archive_write_program_free(data->pdata); +#endif + free(data); + f->data = NULL; + return (ARCHIVE_OK); +} + +/* + * Set write options. + */ +static int +archive_compressor_gzip_options(struct archive_write_filter *f, const char *key, + const char *value) +{ + struct private_data *data = (struct private_data *)f->data; + + if (strcmp(key, "compression-level") == 0) { + if (value == NULL || !(value[0] >= '0' && value[0] <= '9') || + value[1] != '\0') + return (ARCHIVE_WARN); + data->compression_level = value[0] - '0'; + return (ARCHIVE_OK); + } + if (strcmp(key, "timestamp") == 0) { + data->timestamp = (value == NULL)?-1:1; + return (ARCHIVE_OK); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +#ifdef HAVE_ZLIB_H +/* + * Setup callback. + */ +static int +archive_compressor_gzip_open(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + int ret; + + if (data->compressed == NULL) { + size_t bs = 65536, bpb; + if (f->archive->magic == ARCHIVE_WRITE_MAGIC) { + /* Buffer size should be a multiple number of + * the of bytes per block for performance. */ + bpb = archive_write_get_bytes_per_block(f->archive); + if (bpb > bs) + bs = bpb; + else if (bpb != 0) + bs -= bs % bpb; + } + data->compressed_buffer_size = bs; + data->compressed + = (unsigned char *)malloc(data->compressed_buffer_size); + if (data->compressed == NULL) { + archive_set_error(f->archive, ENOMEM, + "Can't allocate data for compression buffer"); + return (ARCHIVE_FATAL); + } + } + + data->crc = crc32(0L, NULL, 0); + data->stream.next_out = data->compressed; + data->stream.avail_out = (uInt)data->compressed_buffer_size; + + /* Prime output buffer with a gzip header. */ + data->compressed[0] = 0x1f; /* GZip signature bytes */ + data->compressed[1] = 0x8b; + data->compressed[2] = 0x08; /* "Deflate" compression */ + data->compressed[3] = 0; /* No options */ + if (data->timestamp >= 0) { + time_t t = time(NULL); + data->compressed[4] = (uint8_t)(t)&0xff; /* Timestamp */ + data->compressed[5] = (uint8_t)(t>>8)&0xff; + data->compressed[6] = (uint8_t)(t>>16)&0xff; + data->compressed[7] = (uint8_t)(t>>24)&0xff; + } else + memset(&data->compressed[4], 0, 4); + if (data->compression_level == 9) + data->compressed[8] = 2; + else if(data->compression_level == 1) + data->compressed[8] = 4; + else + data->compressed[8] = 0; + data->compressed[9] = 3; /* OS=Unix */ + data->stream.next_out += 10; + data->stream.avail_out -= 10; + + f->write = archive_compressor_gzip_write; + + /* Initialize compression library. */ + ret = deflateInit2(&(data->stream), + data->compression_level, + Z_DEFLATED, + -15 /* < 0 to suppress zlib header */, + 8, + Z_DEFAULT_STRATEGY); + + if (ret == Z_OK) { + f->data = data; + return (ARCHIVE_OK); + } + + /* Library setup failed: clean up. */ + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, "Internal error " + "initializing compression library"); + + /* Override the error message if we know what really went wrong. */ + switch (ret) { + case Z_STREAM_ERROR: + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "Internal error initializing " + "compression library: invalid setup parameter"); + break; + case Z_MEM_ERROR: + archive_set_error(f->archive, ENOMEM, + "Internal error initializing compression library"); + break; + case Z_VERSION_ERROR: + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "Internal error initializing " + "compression library: invalid library version"); + break; + } + + return (ARCHIVE_FATAL); +} + +/* + * Write data to the compressed stream. + */ +static int +archive_compressor_gzip_write(struct archive_write_filter *f, const void *buff, + size_t length) +{ + struct private_data *data = (struct private_data *)f->data; + int ret; + + /* Update statistics */ + data->crc = crc32(data->crc, (const Bytef *)buff, (uInt)length); + data->total_in += length; + + /* Compress input data to output buffer */ + SET_NEXT_IN(data, buff); + data->stream.avail_in = (uInt)length; + if ((ret = drive_compressor(f, data, 0)) != ARCHIVE_OK) + return (ret); + + return (ARCHIVE_OK); +} + +/* + * Finish the compression... + */ +static int +archive_compressor_gzip_close(struct archive_write_filter *f) +{ + unsigned char trailer[8]; + struct private_data *data = (struct private_data *)f->data; + int ret; + + /* Finish compression cycle */ + ret = drive_compressor(f, data, 1); + if (ret == ARCHIVE_OK) { + /* Write the last compressed data. */ + ret = __archive_write_filter(f->next_filter, + data->compressed, + data->compressed_buffer_size - data->stream.avail_out); + } + if (ret == ARCHIVE_OK) { + /* Build and write out 8-byte trailer. */ + trailer[0] = (uint8_t)(data->crc)&0xff; + trailer[1] = (uint8_t)(data->crc >> 8)&0xff; + trailer[2] = (uint8_t)(data->crc >> 16)&0xff; + trailer[3] = (uint8_t)(data->crc >> 24)&0xff; + trailer[4] = (uint8_t)(data->total_in)&0xff; + trailer[5] = (uint8_t)(data->total_in >> 8)&0xff; + trailer[6] = (uint8_t)(data->total_in >> 16)&0xff; + trailer[7] = (uint8_t)(data->total_in >> 24)&0xff; + ret = __archive_write_filter(f->next_filter, trailer, 8); + } + + switch (deflateEnd(&(data->stream))) { + case Z_OK: + break; + default: + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "Failed to clean up compressor"); + ret = ARCHIVE_FATAL; + } + return ret; +} + +/* + * Utility function to push input data through compressor, + * writing full output blocks as necessary. + * + * Note that this handles both the regular write case (finishing == + * false) and the end-of-archive case (finishing == true). + */ +static int +drive_compressor(struct archive_write_filter *f, + struct private_data *data, int finishing) +{ + int ret; + + for (;;) { + if (data->stream.avail_out == 0) { + ret = __archive_write_filter(f->next_filter, + data->compressed, + data->compressed_buffer_size); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + data->stream.next_out = data->compressed; + data->stream.avail_out = + (uInt)data->compressed_buffer_size; + } + + /* If there's nothing to do, we're done. */ + if (!finishing && data->stream.avail_in == 0) + return (ARCHIVE_OK); + + ret = deflate(&(data->stream), + finishing ? Z_FINISH : Z_NO_FLUSH ); + + switch (ret) { + case Z_OK: + /* In non-finishing case, check if compressor + * consumed everything */ + if (!finishing && data->stream.avail_in == 0) + return (ARCHIVE_OK); + /* In finishing case, this return always means + * there's more work */ + break; + case Z_STREAM_END: + /* This return can only occur in finishing case. */ + return (ARCHIVE_OK); + default: + /* Any other return value indicates an error. */ + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "GZip compression failed:" + " deflate() call returned status %d", + ret); + return (ARCHIVE_FATAL); + } + } +} + +#else /* HAVE_ZLIB_H */ + +static int +archive_compressor_gzip_open(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + struct archive_string as; + int r; + + archive_string_init(&as); + archive_strcpy(&as, "gzip"); + + /* Specify compression level. */ + if (data->compression_level > 0) { + archive_strcat(&as, " -"); + archive_strappend_char(&as, '0' + data->compression_level); + } + if (data->timestamp < 0) + /* Do not save timestamp. */ + archive_strcat(&as, " -n"); + else if (data->timestamp > 0) + /* Save timestamp. */ + archive_strcat(&as, " -N"); + + f->write = archive_compressor_gzip_write; + r = __archive_write_program_open(f, data->pdata, as.s); + archive_string_free(&as); + return (r); +} + +static int +archive_compressor_gzip_write(struct archive_write_filter *f, const void *buff, + size_t length) +{ + struct private_data *data = (struct private_data *)f->data; + + return __archive_write_program_write(f, data->pdata, buff, length); +} + +static int +archive_compressor_gzip_close(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + + return __archive_write_program_close(f, data->pdata); +} + +#endif /* HAVE_ZLIB_H */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_lrzip.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_lrzip.c new file mode 100644 index 0000000..e215f89 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_lrzip.c @@ -0,0 +1,197 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive.h" +#include "archive_string.h" +#include "archive_write_private.h" + +struct write_lrzip { + struct archive_write_program_data *pdata; + int compression_level; + enum { lzma = 0, bzip2, gzip, lzo, none, zpaq } compression; +}; + +static int archive_write_lrzip_open(struct archive_write_filter *); +static int archive_write_lrzip_options(struct archive_write_filter *, + const char *, const char *); +static int archive_write_lrzip_write(struct archive_write_filter *, + const void *, size_t); +static int archive_write_lrzip_close(struct archive_write_filter *); +static int archive_write_lrzip_free(struct archive_write_filter *); + +int +archive_write_add_filter_lrzip(struct archive *_a) +{ + struct archive_write_filter *f = __archive_write_allocate_filter(_a); + struct write_lrzip *data; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_add_filter_lrzip"); + + data = calloc(1, sizeof(*data)); + if (data == NULL) { + archive_set_error(_a, ENOMEM, "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + data->pdata = __archive_write_program_allocate("lrzip"); + if (data->pdata == NULL) { + free(data); + archive_set_error(_a, ENOMEM, "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + + f->name = "lrzip"; + f->code = ARCHIVE_FILTER_LRZIP; + f->data = data; + f->open = archive_write_lrzip_open; + f->options = archive_write_lrzip_options; + f->write = archive_write_lrzip_write; + f->close = archive_write_lrzip_close; + f->free = archive_write_lrzip_free; + + /* Note: This filter always uses an external program, so we + * return "warn" to inform of the fact. */ + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "Using external lrzip program for lrzip compression"); + return (ARCHIVE_WARN); +} + +static int +archive_write_lrzip_options(struct archive_write_filter *f, const char *key, + const char *value) +{ + struct write_lrzip *data = (struct write_lrzip *)f->data; + + if (strcmp(key, "compression") == 0) { + if (value == NULL) + return (ARCHIVE_WARN); + else if (strcmp(value, "bzip2") == 0) + data->compression = bzip2; + else if (strcmp(value, "gzip") == 0) + data->compression = gzip; + else if (strcmp(value, "lzo") == 0) + data->compression = lzo; + else if (strcmp(value, "none") == 0) + data->compression = none; + else if (strcmp(value, "zpaq") == 0) + data->compression = zpaq; + else + return (ARCHIVE_WARN); + return (ARCHIVE_OK); + } else if (strcmp(key, "compression-level") == 0) { + if (value == NULL || !(value[0] >= '1' && value[0] <= '9') || + value[1] != '\0') + return (ARCHIVE_WARN); + data->compression_level = value[0] - '0'; + return (ARCHIVE_OK); + } + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +static int +archive_write_lrzip_open(struct archive_write_filter *f) +{ + struct write_lrzip *data = (struct write_lrzip *)f->data; + struct archive_string as; + int r; + + archive_string_init(&as); + archive_strcpy(&as, "lrzip -q"); + + /* Specify compression type. */ + switch (data->compression) { + case lzma:/* default compression */ + break; + case bzip2: + archive_strcat(&as, " -b"); + break; + case gzip: + archive_strcat(&as, " -g"); + break; + case lzo: + archive_strcat(&as, " -l"); + break; + case none: + archive_strcat(&as, " -n"); + break; + case zpaq: + archive_strcat(&as, " -z"); + break; + } + + /* Specify compression level. */ + if (data->compression_level > 0) { + archive_strcat(&as, " -L "); + archive_strappend_char(&as, '0' + data->compression_level); + } + + r = __archive_write_program_open(f, data->pdata, as.s); + archive_string_free(&as); + return (r); +} + +static int +archive_write_lrzip_write(struct archive_write_filter *f, + const void *buff, size_t length) +{ + struct write_lrzip *data = (struct write_lrzip *)f->data; + + return __archive_write_program_write(f, data->pdata, buff, length); +} + +static int +archive_write_lrzip_close(struct archive_write_filter *f) +{ + struct write_lrzip *data = (struct write_lrzip *)f->data; + + return __archive_write_program_close(f, data->pdata); +} + +static int +archive_write_lrzip_free(struct archive_write_filter *f) +{ + struct write_lrzip *data = (struct write_lrzip *)f->data; + + __archive_write_program_free(data->pdata); + free(data); + return (ARCHIVE_OK); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_lz4.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_lz4.c new file mode 100644 index 0000000..cf19fad --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_lz4.c @@ -0,0 +1,700 @@ +/*- + * Copyright (c) 2014 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_LZ4_H +#include +#endif +#ifdef HAVE_LZ4HC_H +#include +#endif + +#include "archive.h" +#include "archive_endian.h" +#include "archive_private.h" +#include "archive_write_private.h" +#include "archive_xxhash.h" + +#define LZ4_MAGICNUMBER 0x184d2204 + +struct private_data { + int compression_level; + unsigned header_written:1; + unsigned version_number:1; + unsigned block_independence:1; + unsigned block_checksum:1; + unsigned stream_size:1; + unsigned stream_checksum:1; + unsigned preset_dictionary:1; + unsigned block_maximum_size:3; +#if defined(HAVE_LIBLZ4) && LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 2 + int64_t total_in; + char *out; + char *out_buffer; + size_t out_buffer_size; + size_t out_block_size; + char *in; + char *in_buffer_allocated; + char *in_buffer; + size_t in_buffer_size; + size_t block_size; + + void *xxh32_state; + void *lz4_stream; +#else + struct archive_write_program_data *pdata; +#endif +}; + +static int archive_filter_lz4_close(struct archive_write_filter *); +static int archive_filter_lz4_free(struct archive_write_filter *); +static int archive_filter_lz4_open(struct archive_write_filter *); +static int archive_filter_lz4_options(struct archive_write_filter *, + const char *, const char *); +static int archive_filter_lz4_write(struct archive_write_filter *, + const void *, size_t); + +/* + * Add a lz4 compression filter to this write handle. + */ +int +archive_write_add_filter_lz4(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct archive_write_filter *f = __archive_write_allocate_filter(_a); + struct private_data *data; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_add_filter_lz4"); + + data = calloc(1, sizeof(*data)); + if (data == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + + /* + * Setup default settings. + */ + data->compression_level = 1; + data->version_number = 0x01; + data->block_independence = 1; + data->block_checksum = 0; + data->stream_size = 0; + data->stream_checksum = 1; + data->preset_dictionary = 0; + data->block_maximum_size = 7; + + /* + * Setup a filter setting. + */ + f->data = data; + f->options = &archive_filter_lz4_options; + f->close = &archive_filter_lz4_close; + f->free = &archive_filter_lz4_free; + f->open = &archive_filter_lz4_open; + f->code = ARCHIVE_FILTER_LZ4; + f->name = "lz4"; +#if defined(HAVE_LIBLZ4) && LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 2 + return (ARCHIVE_OK); +#else + /* + * We don't have lz4 library, and execute external lz4 program + * instead. + */ + data->pdata = __archive_write_program_allocate("lz4"); + if (data->pdata == NULL) { + free(data); + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + data->compression_level = 0; + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Using external lz4 program"); + return (ARCHIVE_WARN); +#endif +} + +/* + * Set write options. + */ +static int +archive_filter_lz4_options(struct archive_write_filter *f, + const char *key, const char *value) +{ + struct private_data *data = (struct private_data *)f->data; + + if (strcmp(key, "compression-level") == 0) { + int val; + if (value == NULL || !((val = value[0] - '0') >= 1 && val <= 9) || + value[1] != '\0') + return (ARCHIVE_WARN); + +#ifndef HAVE_LZ4HC_H + if(val >= 3) + { + archive_set_error(f->archive, ARCHIVE_ERRNO_PROGRAMMER, + "High compression not included in this build"); + return (ARCHIVE_FATAL); + } +#endif + data->compression_level = val; + return (ARCHIVE_OK); + } + if (strcmp(key, "stream-checksum") == 0) { + data->stream_checksum = value != NULL; + return (ARCHIVE_OK); + } + if (strcmp(key, "block-checksum") == 0) { + data->block_checksum = value != NULL; + return (ARCHIVE_OK); + } + if (strcmp(key, "block-size") == 0) { + if (value == NULL || !(value[0] >= '4' && value[0] <= '7') || + value[1] != '\0') + return (ARCHIVE_WARN); + data->block_maximum_size = value[0] - '0'; + return (ARCHIVE_OK); + } + if (strcmp(key, "block-dependence") == 0) { + data->block_independence = value == NULL; + return (ARCHIVE_OK); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +#if defined(HAVE_LIBLZ4) && LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 2 +/* Don't compile this if we don't have liblz4. */ + +static int drive_compressor(struct archive_write_filter *, const char *, + size_t); +static int drive_compressor_independence(struct archive_write_filter *, + const char *, size_t); +static int drive_compressor_dependence(struct archive_write_filter *, + const char *, size_t); +static int lz4_write_stream_descriptor(struct archive_write_filter *); +static ssize_t lz4_write_one_block(struct archive_write_filter *, const char *, + size_t); + + +/* + * Setup callback. + */ +static int +archive_filter_lz4_open(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + size_t required_size; + static size_t const bkmap[] = { 64 * 1024, 256 * 1024, 1 * 1024 * 1024, + 4 * 1024 * 1024 }; + size_t pre_block_size; + + if (data->block_maximum_size < 4) + data->block_size = bkmap[0]; + else + data->block_size = bkmap[data->block_maximum_size - 4]; + + required_size = 4 + 15 + 4 + data->block_size + 4 + 4; + if (data->out_buffer_size < required_size) { + size_t bs = required_size, bpb; + free(data->out_buffer); + if (f->archive->magic == ARCHIVE_WRITE_MAGIC) { + /* Buffer size should be a multiple number of + * the of bytes per block for performance. */ + bpb = archive_write_get_bytes_per_block(f->archive); + if (bpb > bs) + bs = bpb; + else if (bpb != 0) { + bs += bpb; + bs -= bs % bpb; + } + } + data->out_block_size = bs; + bs += required_size; + data->out_buffer = malloc(bs); + data->out = data->out_buffer; + data->out_buffer_size = bs; + } + + pre_block_size = (data->block_independence)? 0: 64 * 1024; + if (data->in_buffer_size < data->block_size + pre_block_size) { + free(data->in_buffer_allocated); + data->in_buffer_size = data->block_size; + data->in_buffer_allocated = + malloc(data->in_buffer_size + pre_block_size); + data->in_buffer = data->in_buffer_allocated + pre_block_size; + if (!data->block_independence && data->compression_level >= 3) + data->in_buffer = data->in_buffer_allocated; + data->in = data->in_buffer; + data->in_buffer_size = data->block_size; + } + + if (data->out_buffer == NULL || data->in_buffer_allocated == NULL) { + archive_set_error(f->archive, ENOMEM, + "Can't allocate data for compression buffer"); + return (ARCHIVE_FATAL); + } + + f->write = archive_filter_lz4_write; + + return (ARCHIVE_OK); +} + +/* + * Write data to the out stream. + * + * Returns ARCHIVE_OK if all data written, error otherwise. + */ +static int +archive_filter_lz4_write(struct archive_write_filter *f, + const void *buff, size_t length) +{ + struct private_data *data = (struct private_data *)f->data; + int ret = ARCHIVE_OK; + const char *p; + size_t remaining; + ssize_t size; + + /* If we haven't written a stream descriptor, we have to do it first. */ + if (!data->header_written) { + ret = lz4_write_stream_descriptor(f); + if (ret != ARCHIVE_OK) + return (ret); + data->header_written = 1; + } + + /* Update statistics */ + data->total_in += length; + + p = (const char *)buff; + remaining = length; + while (remaining) { + size_t l; + /* Compress input data to output buffer */ + size = lz4_write_one_block(f, p, remaining); + if (size < ARCHIVE_OK) + return (ARCHIVE_FATAL); + l = data->out - data->out_buffer; + if (l >= data->out_block_size) { + ret = __archive_write_filter(f->next_filter, + data->out_buffer, data->out_block_size); + l -= data->out_block_size; + memcpy(data->out_buffer, + data->out_buffer + data->out_block_size, l); + data->out = data->out_buffer + l; + if (ret < ARCHIVE_WARN) + break; + } + p += size; + remaining -= size; + } + + return (ret); +} + +/* + * Finish the compression. + */ +static int +archive_filter_lz4_close(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + int ret; + + /* Finish compression cycle. */ + ret = (int)lz4_write_one_block(f, NULL, 0); + if (ret >= 0) { + /* + * Write the last block and the end of the stream data. + */ + + /* Write End Of Stream. */ + memset(data->out, 0, 4); data->out += 4; + /* Write Stream checksum if needed. */ + if (data->stream_checksum) { + unsigned int checksum; + checksum = __archive_xxhash.XXH32_digest( + data->xxh32_state); + data->xxh32_state = NULL; + archive_le32enc(data->out, checksum); + data->out += 4; + } + ret = __archive_write_filter(f->next_filter, + data->out_buffer, data->out - data->out_buffer); + } + return ret; +} + +static int +archive_filter_lz4_free(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + + if (data->lz4_stream != NULL) { +#ifdef HAVE_LZ4HC_H + if (data->compression_level >= 3) +#if LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 7 + LZ4_freeStreamHC(data->lz4_stream); +#else + LZ4_freeHC(data->lz4_stream); +#endif + else +#endif +#if LZ4_VERSION_MINOR >= 3 + LZ4_freeStream(data->lz4_stream); +#else + LZ4_free(data->lz4_stream); +#endif + } + free(data->out_buffer); + free(data->in_buffer_allocated); + free(data->xxh32_state); + free(data); + f->data = NULL; + return (ARCHIVE_OK); +} + +static int +lz4_write_stream_descriptor(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + uint8_t *sd; + + sd = (uint8_t *)data->out; + /* Write Magic Number. */ + archive_le32enc(&sd[0], LZ4_MAGICNUMBER); + /* FLG */ + sd[4] = (data->version_number << 6) + | (data->block_independence << 5) + | (data->block_checksum << 4) + | (data->stream_size << 3) + | (data->stream_checksum << 2) + | (data->preset_dictionary << 0); + /* BD */ + sd[5] = (data->block_maximum_size << 4); + sd[6] = (__archive_xxhash.XXH32(&sd[4], 2, 0) >> 8) & 0xff; + data->out += 7; + if (data->stream_checksum) + data->xxh32_state = __archive_xxhash.XXH32_init(0); + else + data->xxh32_state = NULL; + return (ARCHIVE_OK); +} + +static ssize_t +lz4_write_one_block(struct archive_write_filter *f, const char *p, + size_t length) +{ + struct private_data *data = (struct private_data *)f->data; + ssize_t r; + + if (p == NULL) { + /* Compress remaining uncompressed data. */ + if (data->in_buffer == data->in) + return 0; + else { + size_t l = data->in - data->in_buffer; + r = drive_compressor(f, data->in_buffer, l); + if (r == ARCHIVE_OK) + r = (ssize_t)l; + } + } else if ((data->block_independence || data->compression_level < 3) && + data->in_buffer == data->in && length >= data->block_size) { + r = drive_compressor(f, p, data->block_size); + if (r == ARCHIVE_OK) + r = (ssize_t)data->block_size; + } else { + size_t remaining_size = data->in_buffer_size - + (data->in - data->in_buffer); + size_t l = (remaining_size > length)? length: remaining_size; + memcpy(data->in, p, l); + data->in += l; + if (l == remaining_size) { + r = drive_compressor(f, data->in_buffer, + data->block_size); + if (r == ARCHIVE_OK) + r = (ssize_t)l; + data->in = data->in_buffer; + } else + r = (ssize_t)l; + } + + return (r); +} + + +/* + * Utility function to push input data through compressor, writing + * full output blocks as necessary. + * + * Note that this handles both the regular write case (finishing == + * false) and the end-of-archive case (finishing == true). + */ +static int +drive_compressor(struct archive_write_filter *f, const char *p, size_t length) +{ + struct private_data *data = (struct private_data *)f->data; + + if (data->stream_checksum) + __archive_xxhash.XXH32_update(data->xxh32_state, + p, (int)length); + if (data->block_independence) + return drive_compressor_independence(f, p, length); + else + return drive_compressor_dependence(f, p, length); +} + +static int +drive_compressor_independence(struct archive_write_filter *f, const char *p, + size_t length) +{ + struct private_data *data = (struct private_data *)f->data; + unsigned int outsize; + +#ifdef HAVE_LZ4HC_H + if (data->compression_level >= 3) +#if LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 7 + outsize = LZ4_compress_HC(p, data->out + 4, + (int)length, (int)data->block_size, + data->compression_level); +#else + outsize = LZ4_compressHC2_limitedOutput(p, data->out + 4, + (int)length, (int)data->block_size, + data->compression_level); +#endif + else +#endif +#if LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 7 + outsize = LZ4_compress_default(p, data->out + 4, + (int)length, (int)data->block_size); +#else + outsize = LZ4_compress_limitedOutput(p, data->out + 4, + (int)length, (int)data->block_size); +#endif + + if (outsize) { + /* The buffer is compressed. */ + archive_le32enc(data->out, outsize); + data->out += 4; + } else { + /* The buffer is not compressed. The compressed size was + * bigger than its uncompressed size. */ + archive_le32enc(data->out, length | 0x80000000); + data->out += 4; + memcpy(data->out, p, length); + outsize = length; + } + data->out += outsize; + if (data->block_checksum) { + unsigned int checksum = + __archive_xxhash.XXH32(data->out - outsize, outsize, 0); + archive_le32enc(data->out, checksum); + data->out += 4; + } + return (ARCHIVE_OK); +} + +static int +drive_compressor_dependence(struct archive_write_filter *f, const char *p, + size_t length) +{ + struct private_data *data = (struct private_data *)f->data; + int outsize; + +#define DICT_SIZE (64 * 1024) +#ifdef HAVE_LZ4HC_H + if (data->compression_level >= 3) { + if (data->lz4_stream == NULL) { +#if LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 7 + data->lz4_stream = LZ4_createStreamHC(); + LZ4_resetStreamHC(data->lz4_stream, data->compression_level); +#else + data->lz4_stream = + LZ4_createHC(data->in_buffer_allocated); +#endif + if (data->lz4_stream == NULL) { + archive_set_error(f->archive, ENOMEM, + "Can't allocate data for compression" + " buffer"); + return (ARCHIVE_FATAL); + } + } + else + LZ4_loadDictHC(data->lz4_stream, data->in_buffer_allocated, DICT_SIZE); + +#if LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 7 + outsize = LZ4_compress_HC_continue( + data->lz4_stream, p, data->out + 4, (int)length, + (int)data->block_size); +#else + outsize = LZ4_compressHC2_limitedOutput_continue( + data->lz4_stream, p, data->out + 4, (int)length, + (int)data->block_size, data->compression_level); +#endif + } else +#endif + { + if (data->lz4_stream == NULL) { + data->lz4_stream = LZ4_createStream(); + if (data->lz4_stream == NULL) { + archive_set_error(f->archive, ENOMEM, + "Can't allocate data for compression" + " buffer"); + return (ARCHIVE_FATAL); + } + } + else + LZ4_loadDict(data->lz4_stream, data->in_buffer_allocated, DICT_SIZE); + +#if LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 7 + outsize = LZ4_compress_fast_continue( + data->lz4_stream, p, data->out + 4, (int)length, + (int)data->block_size, 1); +#else + outsize = LZ4_compress_limitedOutput_continue( + data->lz4_stream, p, data->out + 4, (int)length, + (int)data->block_size); +#endif + } + + if (outsize) { + /* The buffer is compressed. */ + archive_le32enc(data->out, outsize); + data->out += 4; + } else { + /* The buffer is not compressed. The compressed size was + * bigger than its uncompressed size. */ + archive_le32enc(data->out, length | 0x80000000); + data->out += 4; + memcpy(data->out, p, length); + outsize = length; + } + data->out += outsize; + if (data->block_checksum) { + unsigned int checksum = + __archive_xxhash.XXH32(data->out - outsize, outsize, 0); + archive_le32enc(data->out, checksum); + data->out += 4; + } + + if (length == data->block_size) { +#ifdef HAVE_LZ4HC_H + if (data->compression_level >= 3) { +#if LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 7 + LZ4_saveDictHC(data->lz4_stream, data->in_buffer_allocated, DICT_SIZE); +#else + LZ4_slideInputBufferHC(data->lz4_stream); +#endif + data->in_buffer = data->in_buffer_allocated + DICT_SIZE; + } + else +#endif + LZ4_saveDict(data->lz4_stream, + data->in_buffer_allocated, DICT_SIZE); +#undef DICT_SIZE + } + return (ARCHIVE_OK); +} + +#else /* HAVE_LIBLZ4 */ + +static int +archive_filter_lz4_open(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + struct archive_string as; + int r; + + archive_string_init(&as); + archive_strcpy(&as, "lz4 -z -q -q"); + + /* Specify a compression level. */ + if (data->compression_level > 0) { + archive_strcat(&as, " -"); + archive_strappend_char(&as, '0' + data->compression_level); + } + /* Specify a block size. */ + archive_strcat(&as, " -B"); + archive_strappend_char(&as, '0' + data->block_maximum_size); + + if (data->block_checksum) + archive_strcat(&as, " -BX"); + if (data->stream_checksum == 0) + archive_strcat(&as, " --no-frame-crc"); + if (data->block_independence == 0) + archive_strcat(&as, " -BD"); + + f->write = archive_filter_lz4_write; + + r = __archive_write_program_open(f, data->pdata, as.s); + archive_string_free(&as); + return (r); +} + +static int +archive_filter_lz4_write(struct archive_write_filter *f, const void *buff, + size_t length) +{ + struct private_data *data = (struct private_data *)f->data; + + return __archive_write_program_write(f, data->pdata, buff, length); +} + +static int +archive_filter_lz4_close(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + + return __archive_write_program_close(f, data->pdata); +} + +static int +archive_filter_lz4_free(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + + __archive_write_program_free(data->pdata); + free(data); + return (ARCHIVE_OK); +} + +#endif /* HAVE_LIBLZ4 */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_lzop.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_lzop.c new file mode 100644 index 0000000..3bd9062 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_lzop.c @@ -0,0 +1,478 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); +//#undef HAVE_LZO_LZOCONF_H +//#undef HAVE_LZO_LZO1X_H + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#include +#ifdef HAVE_LZO_LZOCONF_H +#include +#endif +#ifdef HAVE_LZO_LZO1X_H +#include +#endif + +#include "archive.h" +#include "archive_string.h" +#include "archive_endian.h" +#include "archive_write_private.h" + +enum lzo_method { + METHOD_LZO1X_1 = 1, + METHOD_LZO1X_1_15 = 2, + METHOD_LZO1X_999 = 3 +}; +struct write_lzop { + int compression_level; +#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) + unsigned char *uncompressed; + size_t uncompressed_buffer_size; + size_t uncompressed_avail_bytes; + unsigned char *compressed; + size_t compressed_buffer_size; + enum lzo_method method; + unsigned char level; + lzo_voidp work_buffer; + lzo_uint32 work_buffer_size; + char header_written; +#else + struct archive_write_program_data *pdata; +#endif +}; + +static int archive_write_lzop_open(struct archive_write_filter *); +static int archive_write_lzop_options(struct archive_write_filter *, + const char *, const char *); +static int archive_write_lzop_write(struct archive_write_filter *, + const void *, size_t); +static int archive_write_lzop_close(struct archive_write_filter *); +static int archive_write_lzop_free(struct archive_write_filter *); + +#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) +/* Maximum block size. */ +#define BLOCK_SIZE (256 * 1024) +/* Block information is composed of uncompressed size(4 bytes), + * compressed size(4 bytes) and the checksum of uncompressed data(4 bytes) + * in this lzop writer. */ +#define BLOCK_INfO_SIZE 12 + +#define HEADER_VERSION 9 +#define HEADER_LIBVERSION 11 +#define HEADER_METHOD 15 +#define HEADER_LEVEL 16 +#define HEADER_MTIME_LOW 25 +#define HEADER_MTIME_HIGH 29 +#define HEADER_H_CHECKSUM 34 + +/* + * Header template. + */ +static const unsigned char header[] = { + /* LZOP Magic code 9 bytes */ + 0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a, + /* LZOP utility version(fake data) 2 bytes */ + 0x10, 0x30, + /* LZO library version 2 bytes */ + 0x09, 0x40, + /* Minimum required LZO library version 2 bytes */ + 0x09, 0x40, + /* Method */ + 1, + /* Level */ + 5, + /* Flags 4 bytes + * -OS Unix + * -Stdout + * -Stdin + * -Adler32 used for uncompressed data 4 bytes */ + 0x03, 0x00, 0x00, 0x0d, + /* Mode (AE_IFREG | 0644) 4 bytes */ + 0x00, 0x00, 0x81, 0xa4, + /* Mtime low 4 bytes */ + 0x00, 0x00, 0x00, 0x00, + /* Mtime high 4 bytes */ + 0x00, 0x00, 0x00, 0x00, + /* Filename length */ + 0x00, + /* Header checksum 4 bytes */ + 0x00, 0x00, 0x00, 0x00, +}; +#endif + +int +archive_write_add_filter_lzop(struct archive *_a) +{ + struct archive_write_filter *f = __archive_write_allocate_filter(_a); + struct write_lzop *data; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_add_filter_lzop"); + + data = calloc(1, sizeof(*data)); + if (data == NULL) { + archive_set_error(_a, ENOMEM, "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + + f->name = "lzop"; + f->code = ARCHIVE_FILTER_LZOP; + f->data = data; + f->open = archive_write_lzop_open; + f->options = archive_write_lzop_options; + f->write = archive_write_lzop_write; + f->close = archive_write_lzop_close; + f->free = archive_write_lzop_free; +#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) + if (lzo_init() != LZO_E_OK) { + free(data); + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "lzo_init(type check) failed"); + return (ARCHIVE_FATAL); + } + if (lzo_version() < 0x940) { + free(data); + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "liblzo library is too old(%s < 0.940)", + lzo_version_string()); + return (ARCHIVE_FATAL); + } + data->compression_level = 5; + return (ARCHIVE_OK); +#else + data->pdata = __archive_write_program_allocate("lzop"); + if (data->pdata == NULL) { + free(data); + archive_set_error(_a, ENOMEM, "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + data->compression_level = 0; + /* Note: We return "warn" to inform of using an external lzop + * program. */ + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "Using external lzop program for lzop compression"); + return (ARCHIVE_WARN); +#endif +} + +static int +archive_write_lzop_free(struct archive_write_filter *f) +{ + struct write_lzop *data = (struct write_lzop *)f->data; + +#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) + free(data->uncompressed); + free(data->compressed); + free(data->work_buffer); +#else + __archive_write_program_free(data->pdata); +#endif + free(data); + return (ARCHIVE_OK); +} + +static int +archive_write_lzop_options(struct archive_write_filter *f, const char *key, + const char *value) +{ + struct write_lzop *data = (struct write_lzop *)f->data; + + if (strcmp(key, "compression-level") == 0) { + if (value == NULL || !(value[0] >= '1' && value[0] <= '9') || + value[1] != '\0') + return (ARCHIVE_WARN); + data->compression_level = value[0] - '0'; + return (ARCHIVE_OK); + } + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) +static int +archive_write_lzop_open(struct archive_write_filter *f) +{ + struct write_lzop *data = (struct write_lzop *)f->data; + + switch (data->compression_level) { + case 1: + data->method = METHOD_LZO1X_1_15; data->level = 1; break; + default: + case 2: case 3: case 4: case 5: case 6: + data->method = METHOD_LZO1X_1; data->level = 5; break; + case 7: + data->method = METHOD_LZO1X_999; data->level = 7; break; + case 8: + data->method = METHOD_LZO1X_999; data->level = 8; break; + case 9: + data->method = METHOD_LZO1X_999; data->level = 9; break; + } + switch (data->method) { + case METHOD_LZO1X_1: + data->work_buffer_size = LZO1X_1_MEM_COMPRESS; break; + case METHOD_LZO1X_1_15: + data->work_buffer_size = LZO1X_1_15_MEM_COMPRESS; break; + case METHOD_LZO1X_999: + data->work_buffer_size = LZO1X_999_MEM_COMPRESS; break; + } + if (data->work_buffer == NULL) { + data->work_buffer = (lzo_voidp)malloc(data->work_buffer_size); + if (data->work_buffer == NULL) { + archive_set_error(f->archive, ENOMEM, + "Can't allocate data for compression buffer"); + return (ARCHIVE_FATAL); + } + } + if (data->compressed == NULL) { + data->compressed_buffer_size = sizeof(header) + + BLOCK_SIZE + (BLOCK_SIZE >> 4) + 64 + 3; + data->compressed = (unsigned char *) + malloc(data->compressed_buffer_size); + if (data->compressed == NULL) { + archive_set_error(f->archive, ENOMEM, + "Can't allocate data for compression buffer"); + return (ARCHIVE_FATAL); + } + } + if (data->uncompressed == NULL) { + data->uncompressed_buffer_size = BLOCK_SIZE; + data->uncompressed = (unsigned char *) + malloc(data->uncompressed_buffer_size); + if (data->uncompressed == NULL) { + archive_set_error(f->archive, ENOMEM, + "Can't allocate data for compression buffer"); + return (ARCHIVE_FATAL); + } + data->uncompressed_avail_bytes = BLOCK_SIZE; + } + return (ARCHIVE_OK); +} + +static int +make_header(struct archive_write_filter *f) +{ + struct write_lzop *data = (struct write_lzop *)f->data; + int64_t t; + uint32_t checksum; + + memcpy(data->compressed, header, sizeof(header)); + /* Overwrite library version. */ + data->compressed[HEADER_LIBVERSION] = (unsigned char ) + (lzo_version() >> 8) & 0xff; + data->compressed[HEADER_LIBVERSION + 1] = (unsigned char ) + lzo_version() & 0xff; + /* Overwrite method and level. */ + data->compressed[HEADER_METHOD] = (unsigned char)data->method; + data->compressed[HEADER_LEVEL] = data->level; + /* Overwrite mtime with current time. */ + t = (int64_t)time(NULL); + archive_be32enc(&data->compressed[HEADER_MTIME_LOW], + (uint32_t)(t & 0xffffffff)); + archive_be32enc(&data->compressed[HEADER_MTIME_HIGH], + (uint32_t)((t >> 32) & 0xffffffff)); + /* Overwrite header checksum with calculated value. */ + checksum = lzo_adler32(1, data->compressed + HEADER_VERSION, + (lzo_uint)(HEADER_H_CHECKSUM - HEADER_VERSION)); + archive_be32enc(&data->compressed[HEADER_H_CHECKSUM], checksum); + return (sizeof(header)); +} + +static int +drive_compressor(struct archive_write_filter *f) +{ + struct write_lzop *data = (struct write_lzop *)f->data; + unsigned char *p; + const int block_info_bytes = 12; + int header_bytes, r; + lzo_uint usize, csize; + uint32_t checksum; + + if (!data->header_written) { + header_bytes = make_header(f); + data->header_written = 1; + } else + header_bytes = 0; + p = data->compressed; + + usize = (lzo_uint) + (data->uncompressed_buffer_size - data->uncompressed_avail_bytes); + csize = 0; + switch (data->method) { + default: + case METHOD_LZO1X_1: + r = lzo1x_1_compress(data->uncompressed, usize, + p + header_bytes + block_info_bytes, &csize, + data->work_buffer); + break; + case METHOD_LZO1X_1_15: + r = lzo1x_1_15_compress(data->uncompressed, usize, + p + header_bytes + block_info_bytes, &csize, + data->work_buffer); + break; + case METHOD_LZO1X_999: + r = lzo1x_999_compress_level(data->uncompressed, usize, + p + header_bytes + block_info_bytes, &csize, + data->work_buffer, NULL, 0, 0, data->level); + break; + } + if (r != LZO_E_OK) { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "Lzop compression failed: returned status %d", r); + return (ARCHIVE_FATAL); + } + + /* Store uncompressed size. */ + archive_be32enc(p + header_bytes, (uint32_t)usize); + /* Store the checksum of the uncompressed data. */ + checksum = lzo_adler32(1, data->uncompressed, usize); + archive_be32enc(p + header_bytes + 8, checksum); + + if (csize < usize) { + /* Store compressed size. */ + archive_be32enc(p + header_bytes + 4, (uint32_t)csize); + r = __archive_write_filter(f->next_filter, data->compressed, + header_bytes + block_info_bytes + csize); + } else { + /* + * This case, we output uncompressed data instead. + */ + /* Store uncompressed size as compressed size. */ + archive_be32enc(p + header_bytes + 4, (uint32_t)usize); + r = __archive_write_filter(f->next_filter, data->compressed, + header_bytes + block_info_bytes); + if (r != ARCHIVE_OK) + return (ARCHIVE_FATAL); + r = __archive_write_filter(f->next_filter, data->uncompressed, + usize); + } + + if (r != ARCHIVE_OK) + return (ARCHIVE_FATAL); + return (ARCHIVE_OK); +} + +static int +archive_write_lzop_write(struct archive_write_filter *f, + const void *buff, size_t length) +{ + struct write_lzop *data = (struct write_lzop *)f->data; + const char *p = buff; + int r; + + do { + if (data->uncompressed_avail_bytes > length) { + memcpy(data->uncompressed + + data->uncompressed_buffer_size + - data->uncompressed_avail_bytes, + p, length); + data->uncompressed_avail_bytes -= length; + return (ARCHIVE_OK); + } + + memcpy(data->uncompressed + data->uncompressed_buffer_size + - data->uncompressed_avail_bytes, + p, data->uncompressed_avail_bytes); + length -= data->uncompressed_avail_bytes; + p += data->uncompressed_avail_bytes; + data->uncompressed_avail_bytes = 0; + + r = drive_compressor(f); + if (r != ARCHIVE_OK) return (r); + data->uncompressed_avail_bytes = BLOCK_SIZE; + } while (length); + + return (ARCHIVE_OK); +} + +static int +archive_write_lzop_close(struct archive_write_filter *f) +{ + struct write_lzop *data = (struct write_lzop *)f->data; + const uint32_t endmark = 0; + int r; + + if (data->uncompressed_avail_bytes < BLOCK_SIZE) { + /* Compress and output remaining data. */ + r = drive_compressor(f); + if (r != ARCHIVE_OK) + return (r); + } + /* Write a zero uncompressed size as the end mark of the series of + * compressed block. */ + return __archive_write_filter(f->next_filter, &endmark, sizeof(endmark)); +} + +#else +static int +archive_write_lzop_open(struct archive_write_filter *f) +{ + struct write_lzop *data = (struct write_lzop *)f->data; + struct archive_string as; + int r; + + archive_string_init(&as); + archive_strcpy(&as, "lzop"); + /* Specify compression level. */ + if (data->compression_level > 0) { + archive_strappend_char(&as, ' '); + archive_strappend_char(&as, '-'); + archive_strappend_char(&as, '0' + data->compression_level); + } + + r = __archive_write_program_open(f, data->pdata, as.s); + archive_string_free(&as); + return (r); +} + +static int +archive_write_lzop_write(struct archive_write_filter *f, + const void *buff, size_t length) +{ + struct write_lzop *data = (struct write_lzop *)f->data; + + return __archive_write_program_write(f, data->pdata, buff, length); +} + +static int +archive_write_lzop_close(struct archive_write_filter *f) +{ + struct write_lzop *data = (struct write_lzop *)f->data; + + return __archive_write_program_close(f, data->pdata); +} +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_none.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_none.c new file mode 100644 index 0000000..3c06c64 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_none.c @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_compression_none.c 201080 2009-12-28 02:03:54Z kientzle $"); + +#include "archive.h" + +int +archive_write_set_compression_none(struct archive *a) +{ + (void)a; /* UNUSED */ + return (ARCHIVE_OK); +} + +int +archive_write_add_filter_none(struct archive *a) +{ + (void)a; /* UNUSED */ + return (ARCHIVE_OK); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_program.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_program.c new file mode 100644 index 0000000..a4bc1d9 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_program.c @@ -0,0 +1,409 @@ +/*- + * Copyright (c) 2007 Joerg Sonnenberger + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_compression_program.c 201104 2009-12-28 03:14:30Z kientzle $"); + +#ifdef HAVE_SYS_WAIT_H +# include +#endif +#ifdef HAVE_ERRNO_H +# include +#endif +#ifdef HAVE_FCNTL_H +# include +#endif +#ifdef HAVE_STDLIB_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_string.h" +#include "archive_write_private.h" +#include "filter_fork.h" + +#if ARCHIVE_VERSION_NUMBER < 4000000 +int +archive_write_set_compression_program(struct archive *a, const char *cmd) +{ + __archive_write_filters_free(a); + return (archive_write_add_filter_program(a, cmd)); +} +#endif + +struct archive_write_program_data { +#if defined(_WIN32) && !defined(__CYGWIN__) + HANDLE child; +#else + pid_t child; +#endif + int child_stdin, child_stdout; + + char *child_buf; + size_t child_buf_len, child_buf_avail; + char *program_name; +}; + +struct private_data { + struct archive_write_program_data *pdata; + struct archive_string description; + char *cmd; +}; + +static int archive_compressor_program_open(struct archive_write_filter *); +static int archive_compressor_program_write(struct archive_write_filter *, + const void *, size_t); +static int archive_compressor_program_close(struct archive_write_filter *); +static int archive_compressor_program_free(struct archive_write_filter *); + +/* + * Add a filter to this write handle that passes all data through an + * external program. + */ +int +archive_write_add_filter_program(struct archive *_a, const char *cmd) +{ + struct archive_write_filter *f = __archive_write_allocate_filter(_a); + struct private_data *data; + static const char prefix[] = "Program: "; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_add_filter_program"); + + f->data = calloc(1, sizeof(*data)); + if (f->data == NULL) + goto memerr; + data = (struct private_data *)f->data; + + data->cmd = strdup(cmd); + if (data->cmd == NULL) + goto memerr; + + data->pdata = __archive_write_program_allocate(cmd); + if (data->pdata == NULL) + goto memerr; + + /* Make up a description string. */ + if (archive_string_ensure(&data->description, + strlen(prefix) + strlen(cmd) + 1) == NULL) + goto memerr; + archive_strcpy(&data->description, prefix); + archive_strcat(&data->description, cmd); + + f->name = data->description.s; + f->code = ARCHIVE_FILTER_PROGRAM; + f->open = archive_compressor_program_open; + f->write = archive_compressor_program_write; + f->close = archive_compressor_program_close; + f->free = archive_compressor_program_free; + return (ARCHIVE_OK); +memerr: + archive_compressor_program_free(f); + archive_set_error(_a, ENOMEM, + "Can't allocate memory for filter program"); + return (ARCHIVE_FATAL); +} + +static int +archive_compressor_program_open(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + + return __archive_write_program_open(f, data->pdata, data->cmd); +} + +static int +archive_compressor_program_write(struct archive_write_filter *f, + const void *buff, size_t length) +{ + struct private_data *data = (struct private_data *)f->data; + + return __archive_write_program_write(f, data->pdata, buff, length); +} + +static int +archive_compressor_program_close(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + + return __archive_write_program_close(f, data->pdata); +} + +static int +archive_compressor_program_free(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + + if (data) { + free(data->cmd); + archive_string_free(&data->description); + __archive_write_program_free(data->pdata); + free(data); + f->data = NULL; + } + return (ARCHIVE_OK); +} + +/* + * Allocate resources for executing an external program. + */ +struct archive_write_program_data * +__archive_write_program_allocate(const char *program) +{ + struct archive_write_program_data *data; + + data = calloc(1, sizeof(struct archive_write_program_data)); + if (data == NULL) + return (data); + data->child_stdin = -1; + data->child_stdout = -1; + data->program_name = strdup(program); + return (data); +} + +/* + * Release the resources. + */ +int +__archive_write_program_free(struct archive_write_program_data *data) +{ + + if (data) { +#if defined(_WIN32) && !defined(__CYGWIN__) + if (data->child) + CloseHandle(data->child); +#endif + free(data->program_name); + free(data->child_buf); + free(data); + } + return (ARCHIVE_OK); +} + +int +__archive_write_program_open(struct archive_write_filter *f, + struct archive_write_program_data *data, const char *cmd) +{ + pid_t child; + + if (data->child_buf == NULL) { + data->child_buf_len = 65536; + data->child_buf_avail = 0; + data->child_buf = malloc(data->child_buf_len); + + if (data->child_buf == NULL) { + archive_set_error(f->archive, ENOMEM, + "Can't allocate compression buffer"); + return (ARCHIVE_FATAL); + } + } + + child = __archive_create_child(cmd, &data->child_stdin, + &data->child_stdout); + if (child == -1) { + archive_set_error(f->archive, EINVAL, + "Can't launch external program: %s", cmd); + return (ARCHIVE_FATAL); + } +#if defined(_WIN32) && !defined(__CYGWIN__) + data->child = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, child); + if (data->child == NULL) { + close(data->child_stdin); + data->child_stdin = -1; + close(data->child_stdout); + data->child_stdout = -1; + archive_set_error(f->archive, EINVAL, + "Can't launch external program: %s", cmd); + return (ARCHIVE_FATAL); + } +#else + data->child = child; +#endif + return (ARCHIVE_OK); +} + +static ssize_t +child_write(struct archive_write_filter *f, + struct archive_write_program_data *data, const char *buf, size_t buf_len) +{ + ssize_t ret; + + if (data->child_stdin == -1) + return (-1); + + if (buf_len == 0) + return (-1); + + for (;;) { + do { + ret = write(data->child_stdin, buf, buf_len); + } while (ret == -1 && errno == EINTR); + + if (ret > 0) + return (ret); + if (ret == 0) { + close(data->child_stdin); + data->child_stdin = -1; + fcntl(data->child_stdout, F_SETFL, 0); + return (0); + } + if (ret == -1 && errno != EAGAIN) + return (-1); + + if (data->child_stdout == -1) { + fcntl(data->child_stdin, F_SETFL, 0); + __archive_check_child(data->child_stdin, + data->child_stdout); + continue; + } + + do { + ret = read(data->child_stdout, + data->child_buf + data->child_buf_avail, + data->child_buf_len - data->child_buf_avail); + } while (ret == -1 && errno == EINTR); + + if (ret == 0 || (ret == -1 && errno == EPIPE)) { + close(data->child_stdout); + data->child_stdout = -1; + fcntl(data->child_stdin, F_SETFL, 0); + continue; + } + if (ret == -1 && errno == EAGAIN) { + __archive_check_child(data->child_stdin, + data->child_stdout); + continue; + } + if (ret == -1) + return (-1); + + data->child_buf_avail += ret; + + ret = __archive_write_filter(f->next_filter, + data->child_buf, data->child_buf_avail); + if (ret != ARCHIVE_OK) + return (-1); + data->child_buf_avail = 0; + } +} + +/* + * Write data to the filter stream. + */ +int +__archive_write_program_write(struct archive_write_filter *f, + struct archive_write_program_data *data, const void *buff, size_t length) +{ + ssize_t ret; + const char *buf; + + if (data->child == 0) + return (ARCHIVE_OK); + + buf = buff; + while (length > 0) { + ret = child_write(f, data, buf, length); + if (ret == -1 || ret == 0) { + archive_set_error(f->archive, EIO, + "Can't write to program: %s", data->program_name); + return (ARCHIVE_FATAL); + } + length -= ret; + buf += ret; + } + return (ARCHIVE_OK); +} + +/* + * Finish the filtering... + */ +int +__archive_write_program_close(struct archive_write_filter *f, + struct archive_write_program_data *data) +{ + int ret, status; + ssize_t bytes_read; + + if (data->child == 0) + return ARCHIVE_OK; + + ret = 0; + close(data->child_stdin); + data->child_stdin = -1; + fcntl(data->child_stdout, F_SETFL, 0); + + for (;;) { + do { + bytes_read = read(data->child_stdout, + data->child_buf + data->child_buf_avail, + data->child_buf_len - data->child_buf_avail); + } while (bytes_read == -1 && errno == EINTR); + + if (bytes_read == 0 || (bytes_read == -1 && errno == EPIPE)) + break; + + if (bytes_read == -1) { + archive_set_error(f->archive, errno, + "Error reading from program: %s", data->program_name); + ret = ARCHIVE_FATAL; + goto cleanup; + } + data->child_buf_avail += bytes_read; + + ret = __archive_write_filter(f->next_filter, + data->child_buf, data->child_buf_avail); + if (ret != ARCHIVE_OK) { + ret = ARCHIVE_FATAL; + goto cleanup; + } + data->child_buf_avail = 0; + } + +cleanup: + /* Shut down the child. */ + if (data->child_stdin != -1) + close(data->child_stdin); + if (data->child_stdout != -1) + close(data->child_stdout); + while (waitpid(data->child, &status, 0) == -1 && errno == EINTR) + continue; +#if defined(_WIN32) && !defined(__CYGWIN__) + CloseHandle(data->child); +#endif + data->child = 0; + + if (status != 0) { + archive_set_error(f->archive, EIO, + "Error closing program: %s", data->program_name); + ret = ARCHIVE_FATAL; + } + return ret; +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_uuencode.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_uuencode.c new file mode 100644 index 0000000..1ad4589 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_uuencode.c @@ -0,0 +1,295 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_string.h" +#include "archive_write_private.h" + +#define LBYTES 45 + +struct private_uuencode { + int mode; + struct archive_string name; + struct archive_string encoded_buff; + size_t bs; + size_t hold_len; + unsigned char hold[LBYTES]; +}; + +static int archive_filter_uuencode_options(struct archive_write_filter *, + const char *, const char *); +static int archive_filter_uuencode_open(struct archive_write_filter *); +static int archive_filter_uuencode_write(struct archive_write_filter *, + const void *, size_t); +static int archive_filter_uuencode_close(struct archive_write_filter *); +static int archive_filter_uuencode_free(struct archive_write_filter *); +static void uu_encode(struct archive_string *, const unsigned char *, size_t); +static int64_t atol8(const char *, size_t); + +/* + * Add a compress filter to this write handle. + */ +int +archive_write_add_filter_uuencode(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct archive_write_filter *f = __archive_write_allocate_filter(_a); + struct private_uuencode *state; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_add_filter_uu"); + + state = (struct private_uuencode *)calloc(1, sizeof(*state)); + if (state == NULL) { + archive_set_error(f->archive, ENOMEM, + "Can't allocate data for uuencode filter"); + return (ARCHIVE_FATAL); + } + archive_strcpy(&state->name, "-"); + state->mode = 0644; + + f->data = state; + f->name = "uuencode"; + f->code = ARCHIVE_FILTER_UU; + f->open = archive_filter_uuencode_open; + f->options = archive_filter_uuencode_options; + f->write = archive_filter_uuencode_write; + f->close = archive_filter_uuencode_close; + f->free = archive_filter_uuencode_free; + + return (ARCHIVE_OK); +} + +/* + * Set write options. + */ +static int +archive_filter_uuencode_options(struct archive_write_filter *f, const char *key, + const char *value) +{ + struct private_uuencode *state = (struct private_uuencode *)f->data; + + if (strcmp(key, "mode") == 0) { + if (value == NULL) { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "mode option requires octal digits"); + return (ARCHIVE_FAILED); + } + state->mode = (int)atol8(value, strlen(value)) & 0777; + return (ARCHIVE_OK); + } else if (strcmp(key, "name") == 0) { + if (value == NULL) { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "name option requires a string"); + return (ARCHIVE_FAILED); + } + archive_strcpy(&state->name, value); + return (ARCHIVE_OK); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +/* + * Setup callback. + */ +static int +archive_filter_uuencode_open(struct archive_write_filter *f) +{ + struct private_uuencode *state = (struct private_uuencode *)f->data; + size_t bs = 65536, bpb; + + if (f->archive->magic == ARCHIVE_WRITE_MAGIC) { + /* Buffer size should be a multiple number of the of bytes + * per block for performance. */ + bpb = archive_write_get_bytes_per_block(f->archive); + if (bpb > bs) + bs = bpb; + else if (bpb != 0) + bs -= bs % bpb; + } + + state->bs = bs; + if (archive_string_ensure(&state->encoded_buff, bs + 512) == NULL) { + archive_set_error(f->archive, ENOMEM, + "Can't allocate data for uuencode buffer"); + return (ARCHIVE_FATAL); + } + + archive_string_sprintf(&state->encoded_buff, "begin %o %s\n", + state->mode, state->name.s); + + f->data = state; + return (0); +} + +static void +uu_encode(struct archive_string *as, const unsigned char *p, size_t len) +{ + int c; + + c = (int)len; + archive_strappend_char(as, c?c + 0x20:'`'); + for (; len >= 3; p += 3, len -= 3) { + c = p[0] >> 2; + archive_strappend_char(as, c?c + 0x20:'`'); + c = ((p[0] & 0x03) << 4) | ((p[1] & 0xf0) >> 4); + archive_strappend_char(as, c?c + 0x20:'`'); + c = ((p[1] & 0x0f) << 2) | ((p[2] & 0xc0) >> 6); + archive_strappend_char(as, c?c + 0x20:'`'); + c = p[2] & 0x3f; + archive_strappend_char(as, c?c + 0x20:'`'); + } + if (len > 0) { + c = p[0] >> 2; + archive_strappend_char(as, c?c + 0x20:'`'); + c = (p[0] & 0x03) << 4; + if (len == 1) { + archive_strappend_char(as, c?c + 0x20:'`'); + archive_strappend_char(as, '`'); + archive_strappend_char(as, '`'); + } else { + c |= (p[1] & 0xf0) >> 4; + archive_strappend_char(as, c?c + 0x20:'`'); + c = (p[1] & 0x0f) << 2; + archive_strappend_char(as, c?c + 0x20:'`'); + archive_strappend_char(as, '`'); + } + } + archive_strappend_char(as, '\n'); +} + +/* + * Write data to the encoded stream. + */ +static int +archive_filter_uuencode_write(struct archive_write_filter *f, const void *buff, + size_t length) +{ + struct private_uuencode *state = (struct private_uuencode *)f->data; + const unsigned char *p = buff; + int ret = ARCHIVE_OK; + + if (length == 0) + return (ret); + + if (state->hold_len) { + while (state->hold_len < LBYTES && length > 0) { + state->hold[state->hold_len++] = *p++; + length--; + } + if (state->hold_len < LBYTES) + return (ret); + uu_encode(&state->encoded_buff, state->hold, LBYTES); + state->hold_len = 0; + } + + for (; length >= LBYTES; length -= LBYTES, p += LBYTES) + uu_encode(&state->encoded_buff, p, LBYTES); + + /* Save remaining bytes. */ + if (length > 0) { + memcpy(state->hold, p, length); + state->hold_len = length; + } + while (archive_strlen(&state->encoded_buff) >= state->bs) { + ret = __archive_write_filter(f->next_filter, + state->encoded_buff.s, state->bs); + memmove(state->encoded_buff.s, + state->encoded_buff.s + state->bs, + state->encoded_buff.length - state->bs); + state->encoded_buff.length -= state->bs; + } + + return (ret); +} + + +/* + * Finish the compression... + */ +static int +archive_filter_uuencode_close(struct archive_write_filter *f) +{ + struct private_uuencode *state = (struct private_uuencode *)f->data; + + /* Flush remaining bytes. */ + if (state->hold_len != 0) + uu_encode(&state->encoded_buff, state->hold, state->hold_len); + archive_string_sprintf(&state->encoded_buff, "`\nend\n"); + /* Write the last block */ + archive_write_set_bytes_in_last_block(f->archive, 1); + return __archive_write_filter(f->next_filter, + state->encoded_buff.s, archive_strlen(&state->encoded_buff)); +} + +static int +archive_filter_uuencode_free(struct archive_write_filter *f) +{ + struct private_uuencode *state = (struct private_uuencode *)f->data; + + archive_string_free(&state->name); + archive_string_free(&state->encoded_buff); + free(state); + return (ARCHIVE_OK); +} + +static int64_t +atol8(const char *p, size_t char_cnt) +{ + int64_t l; + int digit; + + l = 0; + while (char_cnt-- > 0) { + if (*p >= '0' && *p <= '7') + digit = *p - '0'; + else + break; + p++; + l <<= 3; + l |= digit; + } + return (l); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_xz.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_xz.c new file mode 100644 index 0000000..8c1ebb8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_xz.c @@ -0,0 +1,545 @@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * Copyright (c) 2009-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_compression_xz.c 201108 2009-12-28 03:28:21Z kientzle $"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#include +#ifdef HAVE_LZMA_H +#include +#endif + +#include "archive.h" +#include "archive_endian.h" +#include "archive_private.h" +#include "archive_write_private.h" + +#if ARCHIVE_VERSION_NUMBER < 4000000 +int +archive_write_set_compression_lzip(struct archive *a) +{ + __archive_write_filters_free(a); + return (archive_write_add_filter_lzip(a)); +} + +int +archive_write_set_compression_lzma(struct archive *a) +{ + __archive_write_filters_free(a); + return (archive_write_add_filter_lzma(a)); +} + +int +archive_write_set_compression_xz(struct archive *a) +{ + __archive_write_filters_free(a); + return (archive_write_add_filter_xz(a)); +} + +#endif + +#ifndef HAVE_LZMA_H +int +archive_write_add_filter_xz(struct archive *a) +{ + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "xz compression not supported on this platform"); + return (ARCHIVE_FATAL); +} + +int +archive_write_add_filter_lzma(struct archive *a) +{ + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "lzma compression not supported on this platform"); + return (ARCHIVE_FATAL); +} + +int +archive_write_add_filter_lzip(struct archive *a) +{ + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "lzma compression not supported on this platform"); + return (ARCHIVE_FATAL); +} +#else +/* Don't compile this if we don't have liblzma. */ + +struct private_data { + int compression_level; + uint32_t threads; + lzma_stream stream; + lzma_filter lzmafilters[2]; + lzma_options_lzma lzma_opt; + int64_t total_in; + unsigned char *compressed; + size_t compressed_buffer_size; + int64_t total_out; + /* the CRC32 value of uncompressed data for lzip */ + uint32_t crc32; +}; + +static int archive_compressor_xz_options(struct archive_write_filter *, + const char *, const char *); +static int archive_compressor_xz_open(struct archive_write_filter *); +static int archive_compressor_xz_write(struct archive_write_filter *, + const void *, size_t); +static int archive_compressor_xz_close(struct archive_write_filter *); +static int archive_compressor_xz_free(struct archive_write_filter *); +static int drive_compressor(struct archive_write_filter *, + struct private_data *, int finishing); + +struct option_value { + uint32_t dict_size; + uint32_t nice_len; + lzma_match_finder mf; +}; +static const struct option_value option_values[] = { + { 1 << 16, 32, LZMA_MF_HC3}, + { 1 << 20, 32, LZMA_MF_HC3}, + { 3 << 19, 32, LZMA_MF_HC4}, + { 1 << 21, 32, LZMA_MF_BT4}, + { 3 << 20, 32, LZMA_MF_BT4}, + { 1 << 22, 32, LZMA_MF_BT4}, + { 1 << 23, 64, LZMA_MF_BT4}, + { 1 << 24, 64, LZMA_MF_BT4}, + { 3 << 23, 64, LZMA_MF_BT4}, + { 1 << 25, 64, LZMA_MF_BT4} +}; + +static int +common_setup(struct archive_write_filter *f) +{ + struct private_data *data; + struct archive_write *a = (struct archive_write *)f->archive; + data = calloc(1, sizeof(*data)); + if (data == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + f->data = data; + data->compression_level = LZMA_PRESET_DEFAULT; + data->threads = 1; + f->open = &archive_compressor_xz_open; + f->close = archive_compressor_xz_close; + f->free = archive_compressor_xz_free; + f->options = &archive_compressor_xz_options; + return (ARCHIVE_OK); +} + +/* + * Add an xz compression filter to this write handle. + */ +int +archive_write_add_filter_xz(struct archive *_a) +{ + struct archive_write_filter *f; + int r; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_add_filter_xz"); + f = __archive_write_allocate_filter(_a); + r = common_setup(f); + if (r == ARCHIVE_OK) { + f->code = ARCHIVE_FILTER_XZ; + f->name = "xz"; + } + return (r); +} + +/* LZMA is handled identically, we just need a different compression + * code set. (The liblzma setup looks at the code to determine + * the one place that XZ and LZMA require different handling.) */ +int +archive_write_add_filter_lzma(struct archive *_a) +{ + struct archive_write_filter *f; + int r; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_add_filter_lzma"); + f = __archive_write_allocate_filter(_a); + r = common_setup(f); + if (r == ARCHIVE_OK) { + f->code = ARCHIVE_FILTER_LZMA; + f->name = "lzma"; + } + return (r); +} + +int +archive_write_add_filter_lzip(struct archive *_a) +{ + struct archive_write_filter *f; + int r; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_add_filter_lzip"); + f = __archive_write_allocate_filter(_a); + r = common_setup(f); + if (r == ARCHIVE_OK) { + f->code = ARCHIVE_FILTER_LZIP; + f->name = "lzip"; + } + return (r); +} + +static int +archive_compressor_xz_init_stream(struct archive_write_filter *f, + struct private_data *data) +{ + static const lzma_stream lzma_stream_init_data = LZMA_STREAM_INIT; + int ret; +#ifdef HAVE_LZMA_STREAM_ENCODER_MT + lzma_mt mt_options; +#endif + + data->stream = lzma_stream_init_data; + data->stream.next_out = data->compressed; + data->stream.avail_out = data->compressed_buffer_size; + if (f->code == ARCHIVE_FILTER_XZ) { +#ifdef HAVE_LZMA_STREAM_ENCODER_MT + if (data->threads != 1) { + memset(&mt_options, 0, sizeof(mt_options)); + mt_options.threads = data->threads; + mt_options.timeout = 300; + mt_options.filters = data->lzmafilters; + mt_options.check = LZMA_CHECK_CRC64; + ret = lzma_stream_encoder_mt(&(data->stream), + &mt_options); + } else +#endif + ret = lzma_stream_encoder(&(data->stream), + data->lzmafilters, LZMA_CHECK_CRC64); + } else if (f->code == ARCHIVE_FILTER_LZMA) { + ret = lzma_alone_encoder(&(data->stream), &data->lzma_opt); + } else { /* ARCHIVE_FILTER_LZIP */ + int dict_size = data->lzma_opt.dict_size; + int ds, log2dic, wedges; + + /* Calculate a coded dictionary size */ + if (dict_size < (1 << 12) || dict_size > (1 << 27)) { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "Unacceptable dictionary size for lzip: %d", + dict_size); + return (ARCHIVE_FATAL); + } + for (log2dic = 27; log2dic >= 12; log2dic--) { + if (dict_size & (1 << log2dic)) + break; + } + if (dict_size > (1 << log2dic)) { + log2dic++; + wedges = + ((1 << log2dic) - dict_size) / (1 << (log2dic - 4)); + } else + wedges = 0; + ds = ((wedges << 5) & 0xe0) | (log2dic & 0x1f); + + data->crc32 = 0; + /* Make a header */ + data->compressed[0] = 0x4C; + data->compressed[1] = 0x5A; + data->compressed[2] = 0x49; + data->compressed[3] = 0x50; + data->compressed[4] = 1;/* Version */ + data->compressed[5] = (unsigned char)ds; + data->stream.next_out += 6; + data->stream.avail_out -= 6; + + ret = lzma_raw_encoder(&(data->stream), data->lzmafilters); + } + if (ret == LZMA_OK) + return (ARCHIVE_OK); + + switch (ret) { + case LZMA_MEM_ERROR: + archive_set_error(f->archive, ENOMEM, + "Internal error initializing compression library: " + "Cannot allocate memory"); + break; + default: + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "Internal error initializing compression library: " + "It's a bug in liblzma"); + break; + } + return (ARCHIVE_FATAL); +} + +/* + * Setup callback. + */ +static int +archive_compressor_xz_open(struct archive_write_filter *f) +{ + struct private_data *data = f->data; + int ret; + + if (data->compressed == NULL) { + size_t bs = 65536, bpb; + if (f->archive->magic == ARCHIVE_WRITE_MAGIC) { + /* Buffer size should be a multiple number of the of bytes + * per block for performance. */ + bpb = archive_write_get_bytes_per_block(f->archive); + if (bpb > bs) + bs = bpb; + else if (bpb != 0) + bs -= bs % bpb; + } + data->compressed_buffer_size = bs; + data->compressed + = (unsigned char *)malloc(data->compressed_buffer_size); + if (data->compressed == NULL) { + archive_set_error(f->archive, ENOMEM, + "Can't allocate data for compression buffer"); + return (ARCHIVE_FATAL); + } + } + + f->write = archive_compressor_xz_write; + + /* Initialize compression library. */ + if (f->code == ARCHIVE_FILTER_LZIP) { + const struct option_value *val = + &option_values[data->compression_level]; + + data->lzma_opt.dict_size = val->dict_size; + data->lzma_opt.preset_dict = NULL; + data->lzma_opt.preset_dict_size = 0; + data->lzma_opt.lc = LZMA_LC_DEFAULT; + data->lzma_opt.lp = LZMA_LP_DEFAULT; + data->lzma_opt.pb = LZMA_PB_DEFAULT; + data->lzma_opt.mode = + data->compression_level<= 2? LZMA_MODE_FAST:LZMA_MODE_NORMAL; + data->lzma_opt.nice_len = val->nice_len; + data->lzma_opt.mf = val->mf; + data->lzma_opt.depth = 0; + data->lzmafilters[0].id = LZMA_FILTER_LZMA1; + data->lzmafilters[0].options = &data->lzma_opt; + data->lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */ + } else { + if (lzma_lzma_preset(&data->lzma_opt, data->compression_level)) { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "Internal error initializing compression library"); + } + data->lzmafilters[0].id = LZMA_FILTER_LZMA2; + data->lzmafilters[0].options = &data->lzma_opt; + data->lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */ + } + ret = archive_compressor_xz_init_stream(f, data); + if (ret == LZMA_OK) { + f->data = data; + return (0); + } + return (ARCHIVE_FATAL); +} + +/* + * Set write options. + */ +static int +archive_compressor_xz_options(struct archive_write_filter *f, + const char *key, const char *value) +{ + struct private_data *data = (struct private_data *)f->data; + + if (strcmp(key, "compression-level") == 0) { + if (value == NULL || !(value[0] >= '0' && value[0] <= '9') || + value[1] != '\0') + return (ARCHIVE_WARN); + data->compression_level = value[0] - '0'; + if (data->compression_level > 6) + data->compression_level = 6; + return (ARCHIVE_OK); + } else if (strcmp(key, "threads") == 0) { + char *endptr; + + if (value == NULL) + return (ARCHIVE_WARN); + errno = 0; + data->threads = (int)strtoul(value, &endptr, 10); + if (errno != 0 || *endptr != '\0') { + data->threads = 1; + return (ARCHIVE_WARN); + } + if (data->threads == 0) { +#ifdef HAVE_LZMA_STREAM_ENCODER_MT + data->threads = lzma_cputhreads(); +#else + data->threads = 1; +#endif + } + return (ARCHIVE_OK); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +/* + * Write data to the compressed stream. + */ +static int +archive_compressor_xz_write(struct archive_write_filter *f, + const void *buff, size_t length) +{ + struct private_data *data = (struct private_data *)f->data; + int ret; + + /* Update statistics */ + data->total_in += length; + if (f->code == ARCHIVE_FILTER_LZIP) + data->crc32 = lzma_crc32(buff, length, data->crc32); + + /* Compress input data to output buffer */ + data->stream.next_in = buff; + data->stream.avail_in = length; + if ((ret = drive_compressor(f, data, 0)) != ARCHIVE_OK) + return (ret); + + return (ARCHIVE_OK); +} + + +/* + * Finish the compression... + */ +static int +archive_compressor_xz_close(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + int ret; + + ret = drive_compressor(f, data, 1); + if (ret == ARCHIVE_OK) { + data->total_out += + data->compressed_buffer_size - data->stream.avail_out; + ret = __archive_write_filter(f->next_filter, + data->compressed, + data->compressed_buffer_size - data->stream.avail_out); + if (f->code == ARCHIVE_FILTER_LZIP && ret == ARCHIVE_OK) { + archive_le32enc(data->compressed, data->crc32); + archive_le64enc(data->compressed+4, data->total_in); + archive_le64enc(data->compressed+12, data->total_out + 20); + ret = __archive_write_filter(f->next_filter, + data->compressed, 20); + } + } + lzma_end(&(data->stream)); + return ret; +} + +static int +archive_compressor_xz_free(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + free(data->compressed); + free(data); + f->data = NULL; + return (ARCHIVE_OK); +} + +/* + * Utility function to push input data through compressor, + * writing full output blocks as necessary. + * + * Note that this handles both the regular write case (finishing == + * false) and the end-of-archive case (finishing == true). + */ +static int +drive_compressor(struct archive_write_filter *f, + struct private_data *data, int finishing) +{ + int ret; + + for (;;) { + if (data->stream.avail_out == 0) { + data->total_out += data->compressed_buffer_size; + ret = __archive_write_filter(f->next_filter, + data->compressed, + data->compressed_buffer_size); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + data->stream.next_out = data->compressed; + data->stream.avail_out = data->compressed_buffer_size; + } + + /* If there's nothing to do, we're done. */ + if (!finishing && data->stream.avail_in == 0) + return (ARCHIVE_OK); + + ret = lzma_code(&(data->stream), + finishing ? LZMA_FINISH : LZMA_RUN ); + + switch (ret) { + case LZMA_OK: + /* In non-finishing case, check if compressor + * consumed everything */ + if (!finishing && data->stream.avail_in == 0) + return (ARCHIVE_OK); + /* In finishing case, this return always means + * there's more work */ + break; + case LZMA_STREAM_END: + /* This return can only occur in finishing case. */ + if (finishing) + return (ARCHIVE_OK); + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "lzma compression data error"); + return (ARCHIVE_FATAL); + case LZMA_MEMLIMIT_ERROR: + archive_set_error(f->archive, ENOMEM, + "lzma compression error: " + "%ju MiB would have been needed", + (uintmax_t)((lzma_memusage(&(data->stream)) + + 1024 * 1024 -1) + / (1024 * 1024))); + return (ARCHIVE_FATAL); + default: + /* Any other return value indicates an error. */ + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "lzma compression failed:" + " lzma_code() call returned status %d", + ret); + return (ARCHIVE_FATAL); + } + } +} + +#endif /* HAVE_LZMA_H */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_zstd.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_zstd.c new file mode 100644 index 0000000..4c91551 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_add_filter_zstd.c @@ -0,0 +1,325 @@ +/*- + * Copyright (c) 2017 Sean Purcell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); + + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_ZSTD_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_string.h" +#include "archive_write_private.h" + +/* Don't compile this if we don't have zstd.h */ + +struct private_data { + int compression_level; +#if HAVE_ZSTD_H && HAVE_LIBZSTD + ZSTD_CStream *cstream; + int64_t total_in; + ZSTD_outBuffer out; +#else + struct archive_write_program_data *pdata; +#endif +}; + +static int archive_compressor_zstd_options(struct archive_write_filter *, + const char *, const char *); +static int archive_compressor_zstd_open(struct archive_write_filter *); +static int archive_compressor_zstd_write(struct archive_write_filter *, + const void *, size_t); +static int archive_compressor_zstd_close(struct archive_write_filter *); +static int archive_compressor_zstd_free(struct archive_write_filter *); +#if HAVE_ZSTD_H && HAVE_LIBZSTD +static int drive_compressor(struct archive_write_filter *, + struct private_data *, int, const void *, size_t); +#endif + + +/* + * Add a zstd compression filter to this write handle. + */ +int +archive_write_add_filter_zstd(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct archive_write_filter *f = __archive_write_allocate_filter(_a); + struct private_data *data; + archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_add_filter_zstd"); + + data = calloc(1, sizeof(*data)); + if (data == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + f->data = data; + f->open = &archive_compressor_zstd_open; + f->options = &archive_compressor_zstd_options; + f->close = &archive_compressor_zstd_close; + f->free = &archive_compressor_zstd_free; + f->code = ARCHIVE_FILTER_ZSTD; + f->name = "zstd"; + data->compression_level = 3; /* Default level used by the zstd CLI */ +#if HAVE_ZSTD_H && HAVE_LIBZSTD + data->cstream = ZSTD_createCStream(); + if (data->cstream == NULL) { + free(data); + archive_set_error(&a->archive, ENOMEM, + "Failed to allocate zstd compressor object"); + return (ARCHIVE_FATAL); + } + + return (ARCHIVE_OK); +#else + data->pdata = __archive_write_program_allocate("zstd"); + if (data->pdata == NULL) { + free(data); + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Using external zstd program"); + return (ARCHIVE_WARN); +#endif +} + +static int +archive_compressor_zstd_free(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; +#if HAVE_ZSTD_H && HAVE_LIBZSTD + ZSTD_freeCStream(data->cstream); + free(data->out.dst); +#else + __archive_write_program_free(data->pdata); +#endif + free(data); + f->data = NULL; + return (ARCHIVE_OK); +} + +/* + * Set write options. + */ +static int +archive_compressor_zstd_options(struct archive_write_filter *f, const char *key, + const char *value) +{ + struct private_data *data = (struct private_data *)f->data; + + if (strcmp(key, "compression-level") == 0) { + int level = atoi(value); +#if HAVE_ZSTD_H && HAVE_LIBZSTD + if (level < 1 || level > ZSTD_maxCLevel()) { +#else + /* If we don't have the library, hard-code the max level */ + if (level < 1 || level > 22) { +#endif + return (ARCHIVE_WARN); + } + data->compression_level = level; + return (ARCHIVE_OK); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +#if HAVE_ZSTD_H && HAVE_LIBZSTD +/* + * Setup callback. + */ +static int +archive_compressor_zstd_open(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + + if (data->out.dst == NULL) { + size_t bs = ZSTD_CStreamOutSize(), bpb; + if (f->archive->magic == ARCHIVE_WRITE_MAGIC) { + /* Buffer size should be a multiple number of + * the of bytes per block for performance. */ + bpb = archive_write_get_bytes_per_block(f->archive); + if (bpb > bs) + bs = bpb; + else if (bpb != 0) + bs -= bs % bpb; + } + data->out.size = bs; + data->out.pos = 0; + data->out.dst + = (unsigned char *)malloc(data->out.size); + if (data->out.dst == NULL) { + archive_set_error(f->archive, ENOMEM, + "Can't allocate data for compression buffer"); + return (ARCHIVE_FATAL); + } + } + + f->write = archive_compressor_zstd_write; + + if (ZSTD_isError(ZSTD_initCStream(data->cstream, + data->compression_level))) { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "Internal error initializing zstd compressor object"); + return (ARCHIVE_FATAL); + } + + return (ARCHIVE_OK); +} + +/* + * Write data to the compressed stream. + */ +static int +archive_compressor_zstd_write(struct archive_write_filter *f, const void *buff, + size_t length) +{ + struct private_data *data = (struct private_data *)f->data; + int ret; + + /* Update statistics */ + data->total_in += length; + + if ((ret = drive_compressor(f, data, 0, buff, length)) != ARCHIVE_OK) + return (ret); + + return (ARCHIVE_OK); +} + +/* + * Finish the compression... + */ +static int +archive_compressor_zstd_close(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + + /* Finish zstd frame */ + return drive_compressor(f, data, 1, NULL, 0); +} + +/* + * Utility function to push input data through compressor, + * writing full output blocks as necessary. + * + * Note that this handles both the regular write case (finishing == + * false) and the end-of-archive case (finishing == true). + */ +static int +drive_compressor(struct archive_write_filter *f, + struct private_data *data, int finishing, const void *src, size_t length) +{ + ZSTD_inBuffer in = (ZSTD_inBuffer) { src, length, 0 }; + + for (;;) { + if (data->out.pos == data->out.size) { + const int ret = __archive_write_filter(f->next_filter, + data->out.dst, data->out.size); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + data->out.pos = 0; + } + + /* If there's nothing to do, we're done. */ + if (!finishing && in.pos == in.size) + return (ARCHIVE_OK); + + { + const size_t zstdret = !finishing ? + ZSTD_compressStream(data->cstream, &data->out, &in) + : ZSTD_endStream(data->cstream, &data->out); + + if (ZSTD_isError(zstdret)) { + archive_set_error(f->archive, + ARCHIVE_ERRNO_MISC, + "Zstd compression failed: %s", + ZSTD_getErrorName(zstdret)); + return (ARCHIVE_FATAL); + } + + /* If we're finishing, 0 means nothing left to flush */ + if (finishing && zstdret == 0) { + const int ret = __archive_write_filter(f->next_filter, + data->out.dst, data->out.pos); + return (ret); + } + } + } +} + +#else /* HAVE_ZSTD_H && HAVE_LIBZSTD */ + +static int +archive_compressor_zstd_open(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + struct archive_string as; + int r; + + archive_string_init(&as); + archive_string_sprintf(&as, "zstd -%d", data->compression_level); + + f->write = archive_compressor_zstd_write; + r = __archive_write_program_open(f, data->pdata, as.s); + archive_string_free(&as); + return (r); +} + +static int +archive_compressor_zstd_write(struct archive_write_filter *f, const void *buff, + size_t length) +{ + struct private_data *data = (struct private_data *)f->data; + + return __archive_write_program_write(f, data->pdata, buff, length); +} + +static int +archive_compressor_zstd_close(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + + return __archive_write_program_close(f, data->pdata); +} + +#endif /* HAVE_ZSTD_H && HAVE_LIBZSTD */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_blocksize.3 b/dependencies/libarchive-3.4.2/libarchive/archive_write_blocksize.3 new file mode 100644 index 0000000..4973f99 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_blocksize.3 @@ -0,0 +1,114 @@ +.\" Copyright (c) 2003-2011 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 2, 2012 +.Dt ARCHIVE_WRITE_BLOCKSIZE 3 +.Os +.Sh NAME +.Nm archive_write_get_bytes_per_block , +.Nm archive_write_set_bytes_per_block , +.Nm archive_write_get_bytes_in_last_block , +.Nm archive_write_set_bytes_in_last_block +.Nd functions for creating archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive.h +.Ft int +.Fn archive_write_get_bytes_per_block "struct archive *" +.Ft int +.Fn archive_write_set_bytes_per_block "struct archive *" "int bytes_per_block" +.Ft int +.Fn archive_write_get_bytes_in_last_block "struct archive *" +.Ft int +.Fn archive_write_set_bytes_in_last_block "struct archive *" "int" +.Sh DESCRIPTION +.Bl -tag -width indent +.It Fn archive_write_set_bytes_per_block +Sets the block size used for writing the archive data. +Every call to the write callback function, except possibly the last one, will +use this value for the length. +The default is to use a block size of 10240 bytes. +Note that a block size of zero will suppress internal blocking +and cause writes to be sent directly to the write callback as they occur. +.It Fn archive_write_get_bytes_per_block +Retrieve the block size to be used for writing. +A value of -1 here indicates that the library should use default values. +A value of zero indicates that internal blocking is suppressed. +.It Fn archive_write_set_bytes_in_last_block +Sets the block size used for writing the last block. +If this value is zero, the last block will be padded to the same size +as the other blocks. +Otherwise, the final block will be padded to a multiple of this size. +In particular, setting it to 1 will cause the final block to not be padded. +For compressed output, any padding generated by this option +is applied only after the compression. +The uncompressed data is always unpadded. +The default is to pad the last block to the full block size (note that +.Fn archive_write_open_filename +will set this based on the file type). +Unlike the other +.Dq set +functions, this function can be called after the archive is opened. +.It Fn archive_write_get_bytes_in_last_block +Retrieve the currently-set value for last block size. +A value of -1 here indicates that the library should use default values. +.El +.\" .Sh EXAMPLE +.Sh RETURN VALUES +.Fn archive_write_set_bytes_per_block +and +.Fn archive_write_set_bytes_in_last_block +return +.Cm ARCHIVE_OK +on success, or +.Cm ARCHIVE_FATAL . +.Pp +.Fn archive_write_get_bytes_per_block +and +.Fn archive_write_get_bytes_in_last_block +return currently configured block size +.Po +.Li -1 +indicates the default block size +.Pc , +or +.Cm ARCHIVE_FATAL . +.\" +.Sh ERRORS +Detailed error codes and textual descriptions are available from the +.Fn archive_errno +and +.Fn archive_error_string +functions. +.\" +.Sh SEE ALSO +.Xr tar 1 , +.Xr archive_write_set_options 3 , +.Xr libarchive 3 , +.Xr cpio 5 , +.Xr mtree 5 , +.Xr tar 5 diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_data.3 b/dependencies/libarchive-3.4.2/libarchive/archive_write_data.3 new file mode 100644 index 0000000..bc208b4 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_data.3 @@ -0,0 +1,90 @@ +.\" Copyright (c) 2003-2011 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 28, 2017 +.Dt ARCHIVE_WRITE_DATA 3 +.Os +.Sh NAME +.Nm archive_write_data , +.Nm archive_write_data_block +.Nd functions for creating archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive.h +.Ft la_ssize_t +.Fn archive_write_data "struct archive *" "const void *" "size_t" +.Ft la_ssize_t +.Fn archive_write_data_block "struct archive *" "const void *" "size_t size" "int64_t offset" +.Sh DESCRIPTION +.Bl -tag -width indent +.It Fn archive_write_data +Write data corresponding to the header just written. +.It Fn archive_write_data_block +Write data corresponding to the header just written. +This is like +.Fn archive_write_data +except that it performs a seek on the file being +written to the specified offset before writing the data. +This is useful when restoring sparse files from archive +formats that support sparse files. +Returns number of bytes written or -1 on error. +(Note: This is currently not supported for +.Tn archive_write +handles, only for +.Tn archive_write_disk +handles. +.El +.\" .Sh EXAMPLE +.\" +.Sh RETURN VALUES +This function returns the number of bytes actually written, or +a negative error code on error. +.\" +.Sh ERRORS +Detailed error codes and textual descriptions are available from the +.Fn archive_errno +and +.Fn archive_error_string +functions. +.\" +.Sh BUGS +In libarchive 3.x, this function sometimes returns +zero on success instead of returning the number of bytes written. +Specifically, this occurs when writing to an +.Vt archive_write_disk +handle. +Clients should treat any value less than zero as an error +and consider any non-negative value as success. +.\" +.Sh SEE ALSO +.Xr tar 1 , +.Xr archive_write_finish_entry 3 , +.Xr archive_write_set_options 3 , +.Xr libarchive 3 , +.Xr cpio 5 , +.Xr mtree 5 , +.Xr tar 5 diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_disk.3 b/dependencies/libarchive-3.4.2/libarchive/archive_write_disk.3 new file mode 100644 index 0000000..2fa016e --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_disk.3 @@ -0,0 +1,362 @@ +.\" Copyright (c) 2003-2007 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd January 19, 2020 +.Dt ARCHIVE_WRITE_DISK 3 +.Os +.Sh NAME +.Nm archive_write_disk_new , +.Nm archive_write_disk_set_options , +.Nm archive_write_disk_set_skip_file , +.Nm archive_write_disk_set_group_lookup , +.Nm archive_write_disk_set_standard_lookup , +.Nm archive_write_disk_set_user_lookup +.Nd functions for creating objects on disk +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive.h +.Ft struct archive * +.Fn archive_write_disk_new "void" +.Ft int +.Fn archive_write_disk_set_options "struct archive *" "int flags" +.Ft int +.Fn archive_write_disk_set_skip_file "struct archive *" "dev_t" "ino_t" +.Ft int +.Fo archive_write_disk_set_group_lookup +.Fa "struct archive *" +.Fa "void *" +.Fa "gid_t (*)(void *, const char *gname, gid_t gid)" +.Fa "void (*cleanup)(void *)" +.Fc +.Ft int +.Fn archive_write_disk_set_standard_lookup "struct archive *" +.Ft int +.Fo archive_write_disk_set_user_lookup +.Fa "struct archive *" +.Fa "void *" +.Fa "uid_t (*)(void *, const char *uname, uid_t uid)" +.Fa "void (*cleanup)(void *)" +.Fc +.Sh DESCRIPTION +These functions provide a complete API for creating objects on +disk from +.Tn struct archive_entry +descriptions. +They are most naturally used when extracting objects from an archive +using the +.Fn archive_read +interface. +The general process is to read +.Tn struct archive_entry +objects from an archive, then write those objects to a +.Tn struct archive +object created using the +.Fn archive_write_disk +family functions. +This interface is deliberately very similar to the +.Fn archive_write +interface used to write objects to a streaming archive. +.Bl -tag -width indent +.It Fn archive_write_disk_new +Allocates and initializes a +.Tn struct archive +object suitable for writing objects to disk. +.It Fn archive_write_disk_set_skip_file +Records the device and inode numbers of a file that should not be +overwritten. +This is typically used to ensure that an extraction process does not +overwrite the archive from which objects are being read. +This capability is technically unnecessary but can be a significant +performance optimization in practice. +.It Fn archive_write_disk_set_options +The options field consists of a bitwise OR of one or more of the +following values: +.Bl -tag -compact -width "indent" +.It Cm ARCHIVE_EXTRACT_ACL +Attempt to restore Access Control Lists. +By default, extended ACLs are ignored. +.It Cm ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS +Before removing a file system object prior to replacing it, clear +platform-specific file flags which might prevent its removal. +.It Cm ARCHIVE_EXTRACT_FFLAGS +Attempt to restore file attributes (file flags). +By default, file attributes are ignored. +See +.Xr chattr 1 +.Pq Linux +or +.Xr chflags 1 +.Pq FreeBSD, Mac OS X +for more information on file attributes. +.It Cm ARCHIVE_EXTRACT_MAC_METADATA +Mac OS X specific. +Restore metadata using +.Xr copyfile 3 . +By default, +.Xr copyfile 3 +metadata is ignored. +.It Cm ARCHIVE_EXTRACT_NO_OVERWRITE +Existing files on disk will not be overwritten. +By default, existing regular files are truncated and overwritten; +existing directories will have their permissions updated; +other pre-existing objects are unlinked and recreated from scratch. +.It Cm ARCHIVE_EXTRACT_OWNER +The user and group IDs should be set on the restored file. +By default, the user and group IDs are not restored. +.It Cm ARCHIVE_EXTRACT_PERM +Full permissions (including SGID, SUID, and sticky bits) should +be restored exactly as specified, without obeying the +current umask. +Note that SUID and SGID bits can only be restored if the +user and group ID of the object on disk are correct. +If +.Cm ARCHIVE_EXTRACT_OWNER +is not specified, then SUID and SGID bits will only be restored +if the default user and group IDs of newly-created objects on disk +happen to match those specified in the archive entry. +By default, only basic permissions are restored, and umask is obeyed. +.It Cm ARCHIVE_EXTRACT_SAFE_WRITES +Extract files atomically, by first creating a unique temporary file and then +renaming it to its required destination name. +This avoids a race where an application might see a partial file (or no +file) during extraction. +.It Cm ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS +Refuse to extract an absolute path. +The default is to not refuse such paths. +.It Cm ARCHIVE_EXTRACT_SECURE_NODOTDOT +Refuse to extract a path that contains a +.Pa .. +element anywhere within it. +The default is to not refuse such paths. +Note that paths ending in +.Pa .. +always cause an error, regardless of this flag. +.It Cm ARCHIVE_EXTRACT_SECURE_SYMLINKS +Refuse to extract any object whose final location would be altered +by a symlink on disk. +This is intended to help guard against a variety of mischief +caused by archives that (deliberately or otherwise) extract +files outside of the current directory. +The default is not to perform this check. +If +.It Cm ARCHIVE_EXTRACT_SPARSE +Scan data for blocks of NUL bytes and try to recreate them with holes. +This results in sparse files, independent of whether the archive format +supports or uses them. +.Cm ARCHIVE_EXTRACT_UNLINK +is specified together with this option, the library will +remove any intermediate symlinks it finds and return an +error only if such symlink could not be removed. +.It Cm ARCHIVE_EXTRACT_TIME +The timestamps (mtime, ctime, and atime) should be restored. +By default, they are ignored. +Note that restoring of atime is not currently supported. +.It Cm ARCHIVE_EXTRACT_UNLINK +Existing files on disk will be unlinked before any attempt to +create them. +In some cases, this can prove to be a significant performance improvement. +By default, existing files are truncated and rewritten, but +the file is not recreated. +In particular, the default behavior does not break existing hard links. +.It Cm ARCHIVE_EXTRACT_XATTR +Attempt to restore extended file attributes. +By default, they are ignored. +See +.Xr xattr 7 +.Pq Linux , +.Xr xattr 2 +.Pq Mac OS X , +or +.Xr getextattr 8 +.Pq FreeBSD +for more information on extended file attributes. +.El +.It Xo +.Fn archive_write_disk_set_group_lookup , +.Fn archive_write_disk_set_user_lookup +.Xc +The +.Tn struct archive_entry +objects contain both names and ids that can be used to identify users +and groups. +These names and ids describe the ownership of the file itself and +also appear in ACL lists. +By default, the library uses the ids and ignores the names, but +this can be overridden by registering user and group lookup functions. +To register, you must provide a lookup function which +accepts both a name and id and returns a suitable id. +You may also provide a +.Tn void * +pointer to a private data structure and a cleanup function for +that data. +The cleanup function will be invoked when the +.Tn struct archive +object is destroyed. +.It Fn archive_write_disk_set_standard_lookup +This convenience function installs a standard set of user +and group lookup functions. +These functions use +.Xr getpwnam 3 +and +.Xr getgrnam 3 +to convert names to ids, defaulting to the ids if the names cannot +be looked up. +These functions also implement a simple memory cache to reduce +the number of calls to +.Xr getpwnam 3 +and +.Xr getgrnam 3 . +.El +More information about the +.Va struct archive +object and the overall design of the library can be found in the +.Xr libarchive 3 +overview. +Many of these functions are also documented under +.Xr archive_write 3 . +.Sh RETURN VALUES +Most functions return +.Cm ARCHIVE_OK +(zero) on success, or one of several non-zero +error codes for errors. +Specific error codes include: +.Cm ARCHIVE_RETRY +for operations that might succeed if retried, +.Cm ARCHIVE_WARN +for unusual conditions that do not prevent further operations, and +.Cm ARCHIVE_FATAL +for serious errors that make remaining operations impossible. +.Pp +.Fn archive_write_disk_new +returns a pointer to a newly-allocated +.Tn struct archive +object. +.Pp +.Fn archive_write_data +returns a count of the number of bytes actually written, +or +.Li -1 +on error. +.\" +.Sh ERRORS +Detailed error codes and textual descriptions are available from the +.Fn archive_errno +and +.Fn archive_error_string +functions. +.\" +.Sh SEE ALSO +.Xr tar 1 , +.Xr archive_read 3 , +.Xr archive_write 3 , +.Xr libarchive 3 +.Sh HISTORY +The +.Nm libarchive +library first appeared in +.Fx 5.3 . +The +.Nm archive_write_disk +interface was added to +.Nm libarchive 2.0 +and first appeared in +.Fx 6.3 . +.Sh AUTHORS +.An -nosplit +The +.Nm libarchive +library was written by +.An Tim Kientzle Aq kientzle@acm.org . +.Sh BUGS +Directories are actually extracted in two distinct phases. +Directories are created during +.Fn archive_write_header , +but final permissions are not set until +.Fn archive_write_close . +This separation is necessary to correctly handle borderline +cases such as a non-writable directory containing +files, but can cause unexpected results. +In particular, directory permissions are not fully +restored until the archive is closed. +If you use +.Xr chdir 2 +to change the current directory between calls to +.Fn archive_read_extract +or before calling +.Fn archive_read_close , +you may confuse the permission-setting logic with +the result that directory permissions are restored +incorrectly. +.Pp +The library attempts to create objects with filenames longer than +.Cm PATH_MAX +by creating prefixes of the full path and changing the current directory. +Currently, this logic is limited in scope; the fixup pass does +not work correctly for such objects and the symlink security check +option disables the support for very long pathnames. +.Pp +Restoring the path +.Pa aa/../bb +does create each intermediate directory. +In particular, the directory +.Pa aa +is created as well as the final object +.Pa bb . +In theory, this can be exploited to create an entire directory hierarchy +with a single request. +Of course, this does not work if the +.Cm ARCHIVE_EXTRACT_NODOTDOT +option is specified. +.Pp +Implicit directories are always created obeying the current umask. +Explicit objects are created obeying the current umask unless +.Cm ARCHIVE_EXTRACT_PERM +is specified, in which case they current umask is ignored. +.Pp +SGID and SUID bits are restored only if the correct user and +group could be set. +If +.Cm ARCHIVE_EXTRACT_OWNER +is not specified, then no attempt is made to set the ownership. +In this case, SGID and SUID bits are restored only if the +user and group of the final object happen to match those specified +in the entry. +.Pp +The +.Dq standard +user-id and group-id lookup functions are not the defaults because +.Xr getgrnam 3 +and +.Xr getpwnam 3 +are sometimes too large for particular applications. +The current design allows the application author to use a more +compact implementation when appropriate. +.Pp +There should be a corresponding +.Nm archive_read_disk +interface that walks a directory hierarchy and returns archive +entry objects. diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_disk_posix.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_disk_posix.c new file mode 100644 index 0000000..cc53a3d --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_disk_posix.c @@ -0,0 +1,4536 @@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#if !defined(_WIN32) || defined(__CYGWIN__) + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_ACL_H +#include +#endif +#ifdef HAVE_SYS_EXTATTR_H +#include +#endif +#if HAVE_SYS_XATTR_H +#include +#elif HAVE_ATTR_XATTR_H +#include +#endif +#ifdef HAVE_SYS_EA_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYS_UTIME_H +#include +#endif +#ifdef HAVE_COPYFILE_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_GRP_H +#include +#endif +#ifdef HAVE_LANGINFO_H +#include +#endif +#ifdef HAVE_LINUX_FS_H +#include /* for Linux file flags */ +#endif +/* + * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h. + * As the include guards don't agree, the order of include is important. + */ +#ifdef HAVE_LINUX_EXT2_FS_H +#include /* for Linux file flags */ +#endif +#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__) +#include /* Linux file flags, broken on Cygwin */ +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_PWD_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_UTIME_H +#include +#endif +#ifdef F_GETTIMES /* Tru64 specific */ +#include +#endif + +/* + * Macro to cast st_mtime and time_t to an int64 so that 2 numbers can reliably be compared. + * + * It assumes that the input is an integer type of no more than 64 bits. + * If the number is less than zero, t must be a signed type, so it fits in + * int64_t. Otherwise, it's a nonnegative value so we can cast it to uint64_t + * without loss. But it could be a large unsigned value, so we have to clip it + * to INT64_MAX.* + */ +#define to_int64_time(t) \ + ((t) < 0 ? (int64_t)(t) : (uint64_t)(t) > (uint64_t)INT64_MAX ? INT64_MAX : (int64_t)(t)) + +#if __APPLE__ +#include +#if TARGET_OS_MAC && !TARGET_OS_EMBEDDED && HAVE_QUARANTINE_H +#include +#define HAVE_QUARANTINE 1 +#endif +#endif + +#ifdef HAVE_ZLIB_H +#include +#endif + +/* TODO: Support Mac OS 'quarantine' feature. This is really just a + * standard tag to mark files that have been downloaded as "tainted". + * On Mac OS, we should mark the extracted files as tainted if the + * archive being read was tainted. Windows has a similar feature; we + * should investigate ways to support this generically. */ + +#include "archive.h" +#include "archive_acl_private.h" +#include "archive_string.h" +#include "archive_endian.h" +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_write_disk_private.h" + +#ifndef O_BINARY +#define O_BINARY 0 +#endif +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + +/* Ignore non-int O_NOFOLLOW constant. */ +/* gnulib's fcntl.h does this on AIX, but it seems practical everywhere */ +#if defined O_NOFOLLOW && !(INT_MIN <= O_NOFOLLOW && O_NOFOLLOW <= INT_MAX) +#undef O_NOFOLLOW +#endif + +#ifndef O_NOFOLLOW +#define O_NOFOLLOW 0 +#endif + +#ifndef AT_FDCWD +#define AT_FDCWD -100 +#endif + +struct fixup_entry { + struct fixup_entry *next; + struct archive_acl acl; + mode_t mode; + int64_t atime; + int64_t birthtime; + int64_t mtime; + int64_t ctime; + unsigned long atime_nanos; + unsigned long birthtime_nanos; + unsigned long mtime_nanos; + unsigned long ctime_nanos; + unsigned long fflags_set; + size_t mac_metadata_size; + void *mac_metadata; + int fixup; /* bitmask of what needs fixing */ + char *name; +}; + +/* + * We use a bitmask to track which operations remain to be done for + * this file. In particular, this helps us avoid unnecessary + * operations when it's possible to take care of one step as a + * side-effect of another. For example, mkdir() can specify the mode + * for the newly-created object but symlink() cannot. This means we + * can skip chmod() if mkdir() succeeded, but we must explicitly + * chmod() if we're trying to create a directory that already exists + * (mkdir() failed) or if we're restoring a symlink. Similarly, we + * need to verify UID/GID before trying to restore SUID/SGID bits; + * that verification can occur explicitly through a stat() call or + * implicitly because of a successful chown() call. + */ +#define TODO_MODE_FORCE 0x40000000 +#define TODO_MODE_BASE 0x20000000 +#define TODO_SUID 0x10000000 +#define TODO_SUID_CHECK 0x08000000 +#define TODO_SGID 0x04000000 +#define TODO_SGID_CHECK 0x02000000 +#define TODO_APPLEDOUBLE 0x01000000 +#define TODO_MODE (TODO_MODE_BASE|TODO_SUID|TODO_SGID) +#define TODO_TIMES ARCHIVE_EXTRACT_TIME +#define TODO_OWNER ARCHIVE_EXTRACT_OWNER +#define TODO_FFLAGS ARCHIVE_EXTRACT_FFLAGS +#define TODO_ACLS ARCHIVE_EXTRACT_ACL +#define TODO_XATTR ARCHIVE_EXTRACT_XATTR +#define TODO_MAC_METADATA ARCHIVE_EXTRACT_MAC_METADATA +#define TODO_HFS_COMPRESSION ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED + +struct archive_write_disk { + struct archive archive; + + mode_t user_umask; + struct fixup_entry *fixup_list; + struct fixup_entry *current_fixup; + int64_t user_uid; + int skip_file_set; + int64_t skip_file_dev; + int64_t skip_file_ino; + time_t start_time; + + int64_t (*lookup_gid)(void *private, const char *gname, int64_t gid); + void (*cleanup_gid)(void *private); + void *lookup_gid_data; + int64_t (*lookup_uid)(void *private, const char *uname, int64_t uid); + void (*cleanup_uid)(void *private); + void *lookup_uid_data; + + /* + * Full path of last file to satisfy symlink checks. + */ + struct archive_string path_safe; + + /* + * Cached stat data from disk for the current entry. + * If this is valid, pst points to st. Otherwise, + * pst is null. + */ + struct stat st; + struct stat *pst; + + /* Information about the object being restored right now. */ + struct archive_entry *entry; /* Entry being extracted. */ + char *name; /* Name of entry, possibly edited. */ + struct archive_string _name_data; /* backing store for 'name' */ + char *tmpname; /* Temporary name * */ + struct archive_string _tmpname_data; /* backing store for 'tmpname' */ + /* Tasks remaining for this object. */ + int todo; + /* Tasks deferred until end-of-archive. */ + int deferred; + /* Options requested by the client. */ + int flags; + /* Handle for the file we're restoring. */ + int fd; + /* Current offset for writing data to the file. */ + int64_t offset; + /* Last offset actually written to disk. */ + int64_t fd_offset; + /* Total bytes actually written to files. */ + int64_t total_bytes_written; + /* Maximum size of file, -1 if unknown. */ + int64_t filesize; + /* Dir we were in before this restore; only for deep paths. */ + int restore_pwd; + /* Mode we should use for this entry; affected by _PERM and umask. */ + mode_t mode; + /* UID/GID to use in restoring this entry. */ + int64_t uid; + int64_t gid; + /* + * HFS+ Compression. + */ + /* Xattr "com.apple.decmpfs". */ + uint32_t decmpfs_attr_size; + unsigned char *decmpfs_header_p; + /* ResourceFork set options used for fsetxattr. */ + int rsrc_xattr_options; + /* Xattr "com.apple.ResourceFork". */ + unsigned char *resource_fork; + size_t resource_fork_allocated_size; + unsigned int decmpfs_block_count; + uint32_t *decmpfs_block_info; + /* Buffer for compressed data. */ + unsigned char *compressed_buffer; + size_t compressed_buffer_size; + size_t compressed_buffer_remaining; + /* The offset of the ResourceFork where compressed data will + * be placed. */ + uint32_t compressed_rsrc_position; + uint32_t compressed_rsrc_position_v; + /* Buffer for uncompressed data. */ + char *uncompressed_buffer; + size_t block_remaining_bytes; + size_t file_remaining_bytes; +#ifdef HAVE_ZLIB_H + z_stream stream; + int stream_valid; + int decmpfs_compression_level; +#endif +}; + +/* + * Default mode for dirs created automatically (will be modified by umask). + * Note that POSIX specifies 0777 for implicitly-created dirs, "modified + * by the process' file creation mask." + */ +#define DEFAULT_DIR_MODE 0777 +/* + * Dir modes are restored in two steps: During the extraction, the permissions + * in the archive are modified to match the following limits. During + * the post-extract fixup pass, the permissions from the archive are + * applied. + */ +#define MINIMUM_DIR_MODE 0700 +#define MAXIMUM_DIR_MODE 0775 + +/* + * Maximum uncompressed size of a decmpfs block. + */ +#define MAX_DECMPFS_BLOCK_SIZE (64 * 1024) +/* + * HFS+ compression type. + */ +#define CMP_XATTR 3/* Compressed data in xattr. */ +#define CMP_RESOURCE_FORK 4/* Compressed data in resource fork. */ +/* + * HFS+ compression resource fork. + */ +#define RSRC_H_SIZE 260 /* Base size of Resource fork header. */ +#define RSRC_F_SIZE 50 /* Size of Resource fork footer. */ +/* Size to write compressed data to resource fork. */ +#define COMPRESSED_W_SIZE (64 * 1024) +/* decmpfs definitions. */ +#define MAX_DECMPFS_XATTR_SIZE 3802 +#ifndef DECMPFS_XATTR_NAME +#define DECMPFS_XATTR_NAME "com.apple.decmpfs" +#endif +#define DECMPFS_MAGIC 0x636d7066 +#define DECMPFS_COMPRESSION_MAGIC 0 +#define DECMPFS_COMPRESSION_TYPE 4 +#define DECMPFS_UNCOMPRESSED_SIZE 8 +#define DECMPFS_HEADER_SIZE 16 + +#define HFS_BLOCKS(s) ((s) >> 12) + + +static int la_opendirat(int, const char *); +static int la_mktemp(struct archive_write_disk *); +static void fsobj_error(int *, struct archive_string *, int, const char *, + const char *); +static int check_symlinks_fsobj(char *, int *, struct archive_string *, + int); +static int check_symlinks(struct archive_write_disk *); +static int create_filesystem_object(struct archive_write_disk *); +static struct fixup_entry *current_fixup(struct archive_write_disk *, + const char *pathname); +#if defined(HAVE_FCHDIR) && defined(PATH_MAX) +static void edit_deep_directories(struct archive_write_disk *ad); +#endif +static int cleanup_pathname_fsobj(char *, int *, struct archive_string *, + int); +static int cleanup_pathname(struct archive_write_disk *); +static int create_dir(struct archive_write_disk *, char *); +static int create_parent_dir(struct archive_write_disk *, char *); +static ssize_t hfs_write_data_block(struct archive_write_disk *, + const char *, size_t); +static int fixup_appledouble(struct archive_write_disk *, const char *); +static int older(struct stat *, struct archive_entry *); +static int restore_entry(struct archive_write_disk *); +static int set_mac_metadata(struct archive_write_disk *, const char *, + const void *, size_t); +static int set_xattrs(struct archive_write_disk *); +static int clear_nochange_fflags(struct archive_write_disk *); +static int set_fflags(struct archive_write_disk *); +static int set_fflags_platform(struct archive_write_disk *, int fd, + const char *name, mode_t mode, + unsigned long fflags_set, unsigned long fflags_clear); +static int set_ownership(struct archive_write_disk *); +static int set_mode(struct archive_write_disk *, int mode); +static int set_time(int, int, const char *, time_t, long, time_t, long); +static int set_times(struct archive_write_disk *, int, int, const char *, + time_t, long, time_t, long, time_t, long, time_t, long); +static int set_times_from_entry(struct archive_write_disk *); +static struct fixup_entry *sort_dir_list(struct fixup_entry *p); +static ssize_t write_data_block(struct archive_write_disk *, + const char *, size_t); + +static struct archive_vtable *archive_write_disk_vtable(void); + +static int _archive_write_disk_close(struct archive *); +static int _archive_write_disk_free(struct archive *); +static int _archive_write_disk_header(struct archive *, + struct archive_entry *); +static int64_t _archive_write_disk_filter_bytes(struct archive *, int); +static int _archive_write_disk_finish_entry(struct archive *); +static ssize_t _archive_write_disk_data(struct archive *, const void *, + size_t); +static ssize_t _archive_write_disk_data_block(struct archive *, const void *, + size_t, int64_t); + +static int +la_mktemp(struct archive_write_disk *a) +{ + int oerrno, fd; + mode_t mode; + + archive_string_empty(&a->_tmpname_data); + archive_string_sprintf(&a->_tmpname_data, "%s.XXXXXX", a->name); + a->tmpname = a->_tmpname_data.s; + + fd = __archive_mkstemp(a->tmpname); + if (fd == -1) + return -1; + + mode = a->mode & 0777 & ~a->user_umask; + if (fchmod(fd, mode) == -1) { + oerrno = errno; + close(fd); + errno = oerrno; + return -1; + } + return fd; +} + +static int +la_opendirat(int fd, const char *path) { + const int flags = O_CLOEXEC +#if defined(O_BINARY) + | O_BINARY +#endif +#if defined(O_DIRECTORY) + | O_DIRECTORY +#endif +#if defined(O_PATH) + | O_PATH +#elif defined(O_SEARCH) + | O_SEARCH +#elif defined(__FreeBSD__) && defined(O_EXEC) + | O_EXEC +#else + | O_RDONLY +#endif + ; + +#if !defined(HAVE_OPENAT) + if (fd != AT_FDCWD) { + errno = ENOTSUP; + return (-1); + } else + return (open(path, flags)); +#else + return (openat(fd, path, flags)); +#endif +} + +static int +lazy_stat(struct archive_write_disk *a) +{ + if (a->pst != NULL) { + /* Already have stat() data available. */ + return (ARCHIVE_OK); + } +#ifdef HAVE_FSTAT + if (a->fd >= 0 && fstat(a->fd, &a->st) == 0) { + a->pst = &a->st; + return (ARCHIVE_OK); + } +#endif + /* + * XXX At this point, symlinks should not be hit, otherwise + * XXX a race occurred. Do we want to check explicitly for that? + */ + if (lstat(a->name, &a->st) == 0) { + a->pst = &a->st; + return (ARCHIVE_OK); + } + archive_set_error(&a->archive, errno, "Couldn't stat file"); + return (ARCHIVE_WARN); +} + +static struct archive_vtable * +archive_write_disk_vtable(void) +{ + static struct archive_vtable av; + static int inited = 0; + + if (!inited) { + av.archive_close = _archive_write_disk_close; + av.archive_filter_bytes = _archive_write_disk_filter_bytes; + av.archive_free = _archive_write_disk_free; + av.archive_write_header = _archive_write_disk_header; + av.archive_write_finish_entry + = _archive_write_disk_finish_entry; + av.archive_write_data = _archive_write_disk_data; + av.archive_write_data_block = _archive_write_disk_data_block; + inited = 1; + } + return (&av); +} + +static int64_t +_archive_write_disk_filter_bytes(struct archive *_a, int n) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + (void)n; /* UNUSED */ + if (n == -1 || n == 0) + return (a->total_bytes_written); + return (-1); +} + + +int +archive_write_disk_set_options(struct archive *_a, int flags) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + + a->flags = flags; + return (ARCHIVE_OK); +} + + +/* + * Extract this entry to disk. + * + * TODO: Validate hardlinks. According to the standards, we're + * supposed to check each extracted hardlink and squawk if it refers + * to a file that we didn't restore. I'm not entirely convinced this + * is a good idea, but more importantly: Is there any way to validate + * hardlinks without keeping a complete list of filenames from the + * entire archive?? Ugh. + * + */ +static int +_archive_write_disk_header(struct archive *_a, struct archive_entry *entry) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + struct fixup_entry *fe; + int ret, r; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_write_disk_header"); + archive_clear_error(&a->archive); + if (a->archive.state & ARCHIVE_STATE_DATA) { + r = _archive_write_disk_finish_entry(&a->archive); + if (r == ARCHIVE_FATAL) + return (r); + } + + /* Set up for this particular entry. */ + a->pst = NULL; + a->current_fixup = NULL; + a->deferred = 0; + if (a->entry) { + archive_entry_free(a->entry); + a->entry = NULL; + } + a->entry = archive_entry_clone(entry); + a->fd = -1; + a->fd_offset = 0; + a->offset = 0; + a->restore_pwd = -1; + a->uid = a->user_uid; + a->mode = archive_entry_mode(a->entry); + if (archive_entry_size_is_set(a->entry)) + a->filesize = archive_entry_size(a->entry); + else + a->filesize = -1; + archive_strcpy(&(a->_name_data), archive_entry_pathname(a->entry)); + a->name = a->_name_data.s; + archive_clear_error(&a->archive); + + /* + * Clean up the requested path. This is necessary for correct + * dir restores; the dir restore logic otherwise gets messed + * up by nonsense like "dir/.". + */ + ret = cleanup_pathname(a); + if (ret != ARCHIVE_OK) + return (ret); + + /* + * Query the umask so we get predictable mode settings. + * This gets done on every call to _write_header in case the + * user edits their umask during the extraction for some + * reason. + */ + umask(a->user_umask = umask(0)); + + /* Figure out what we need to do for this entry. */ + a->todo = TODO_MODE_BASE; + if (a->flags & ARCHIVE_EXTRACT_PERM) { + a->todo |= TODO_MODE_FORCE; /* Be pushy about permissions. */ + /* + * SGID requires an extra "check" step because we + * cannot easily predict the GID that the system will + * assign. (Different systems assign GIDs to files + * based on a variety of criteria, including process + * credentials and the gid of the enclosing + * directory.) We can only restore the SGID bit if + * the file has the right GID, and we only know the + * GID if we either set it (see set_ownership) or if + * we've actually called stat() on the file after it + * was restored. Since there are several places at + * which we might verify the GID, we need a TODO bit + * to keep track. + */ + if (a->mode & S_ISGID) + a->todo |= TODO_SGID | TODO_SGID_CHECK; + /* + * Verifying the SUID is simpler, but can still be + * done in multiple ways, hence the separate "check" bit. + */ + if (a->mode & S_ISUID) + a->todo |= TODO_SUID | TODO_SUID_CHECK; + } else { + /* + * User didn't request full permissions, so don't + * restore SUID, SGID bits and obey umask. + */ + a->mode &= ~S_ISUID; + a->mode &= ~S_ISGID; + a->mode &= ~S_ISVTX; + a->mode &= ~a->user_umask; + } + if (a->flags & ARCHIVE_EXTRACT_OWNER) + a->todo |= TODO_OWNER; + if (a->flags & ARCHIVE_EXTRACT_TIME) + a->todo |= TODO_TIMES; + if (a->flags & ARCHIVE_EXTRACT_ACL) { +#if ARCHIVE_ACL_DARWIN + /* + * On MacOS, platform ACLs get stored in mac_metadata, too. + * If we intend to extract mac_metadata and it is present + * we skip extracting libarchive NFSv4 ACLs. + */ + size_t metadata_size; + + if ((a->flags & ARCHIVE_EXTRACT_MAC_METADATA) == 0 || + archive_entry_mac_metadata(a->entry, + &metadata_size) == NULL || metadata_size == 0) +#endif +#if ARCHIVE_ACL_LIBRICHACL + /* + * RichACLs are stored in an extended attribute. + * If we intend to extract extended attributes and have this + * attribute we skip extracting libarchive NFSv4 ACLs. + */ + short extract_acls = 1; + if (a->flags & ARCHIVE_EXTRACT_XATTR && ( + archive_entry_acl_types(a->entry) & + ARCHIVE_ENTRY_ACL_TYPE_NFS4)) { + const char *attr_name; + const void *attr_value; + size_t attr_size; + int i = archive_entry_xattr_reset(a->entry); + while (i--) { + archive_entry_xattr_next(a->entry, &attr_name, + &attr_value, &attr_size); + if (attr_name != NULL && attr_value != NULL && + attr_size > 0 && strcmp(attr_name, + "trusted.richacl") == 0) { + extract_acls = 0; + break; + } + } + } + if (extract_acls) +#endif +#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL + { +#endif + if (archive_entry_filetype(a->entry) == AE_IFDIR) + a->deferred |= TODO_ACLS; + else + a->todo |= TODO_ACLS; +#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL + } +#endif + } + if (a->flags & ARCHIVE_EXTRACT_MAC_METADATA) { + if (archive_entry_filetype(a->entry) == AE_IFDIR) + a->deferred |= TODO_MAC_METADATA; + else + a->todo |= TODO_MAC_METADATA; + } +#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H) + if ((a->flags & ARCHIVE_EXTRACT_NO_HFS_COMPRESSION) == 0) { + unsigned long set, clear; + archive_entry_fflags(a->entry, &set, &clear); + if ((set & ~clear) & UF_COMPRESSED) { + a->todo |= TODO_HFS_COMPRESSION; + a->decmpfs_block_count = (unsigned)-1; + } + } + if ((a->flags & ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED) != 0 && + (a->mode & AE_IFMT) == AE_IFREG && a->filesize > 0) { + a->todo |= TODO_HFS_COMPRESSION; + a->decmpfs_block_count = (unsigned)-1; + } + { + const char *p; + + /* Check if the current file name is a type of the + * resource fork file. */ + p = strrchr(a->name, '/'); + if (p == NULL) + p = a->name; + else + p++; + if (p[0] == '.' && p[1] == '_') { + /* Do not compress "._XXX" files. */ + a->todo &= ~TODO_HFS_COMPRESSION; + if (a->filesize > 0) + a->todo |= TODO_APPLEDOUBLE; + } + } +#endif + + if (a->flags & ARCHIVE_EXTRACT_XATTR) { +#if ARCHIVE_XATTR_DARWIN + /* + * On MacOS, extended attributes get stored in mac_metadata, + * too. If we intend to extract mac_metadata and it is present + * we skip extracting extended attributes. + */ + size_t metadata_size; + + if ((a->flags & ARCHIVE_EXTRACT_MAC_METADATA) == 0 || + archive_entry_mac_metadata(a->entry, + &metadata_size) == NULL || metadata_size == 0) +#endif + a->todo |= TODO_XATTR; + } + if (a->flags & ARCHIVE_EXTRACT_FFLAGS) + a->todo |= TODO_FFLAGS; + if (a->flags & ARCHIVE_EXTRACT_SECURE_SYMLINKS) { + ret = check_symlinks(a); + if (ret != ARCHIVE_OK) + return (ret); + } +#if defined(HAVE_FCHDIR) && defined(PATH_MAX) + /* If path exceeds PATH_MAX, shorten the path. */ + edit_deep_directories(a); +#endif + + ret = restore_entry(a); + +#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H) + /* + * Check if the filesystem the file is restoring on supports + * HFS+ Compression. If not, cancel HFS+ Compression. + */ + if (a->todo | TODO_HFS_COMPRESSION) { + /* + * NOTE: UF_COMPRESSED is ignored even if the filesystem + * supports HFS+ Compression because the file should + * have at least an extended attribute "com.apple.decmpfs" + * before the flag is set to indicate that the file have + * been compressed. If the filesystem does not support + * HFS+ Compression the system call will fail. + */ + if (a->fd < 0 || fchflags(a->fd, UF_COMPRESSED) != 0) + a->todo &= ~TODO_HFS_COMPRESSION; + } +#endif + + /* + * TODO: There are rumours that some extended attributes must + * be restored before file data is written. If this is true, + * then we either need to write all extended attributes both + * before and after restoring the data, or find some rule for + * determining which must go first and which last. Due to the + * many ways people are using xattrs, this may prove to be an + * intractable problem. + */ + +#ifdef HAVE_FCHDIR + /* If we changed directory above, restore it here. */ + if (a->restore_pwd >= 0) { + r = fchdir(a->restore_pwd); + if (r != 0) { + archive_set_error(&a->archive, errno, + "chdir() failure"); + ret = ARCHIVE_FATAL; + } + close(a->restore_pwd); + a->restore_pwd = -1; + } +#endif + + /* + * Fixup uses the unedited pathname from archive_entry_pathname(), + * because it is relative to the base dir and the edited path + * might be relative to some intermediate dir as a result of the + * deep restore logic. + */ + if (a->deferred & TODO_MODE) { + fe = current_fixup(a, archive_entry_pathname(entry)); + if (fe == NULL) + return (ARCHIVE_FATAL); + fe->fixup |= TODO_MODE_BASE; + fe->mode = a->mode; + } + + if ((a->deferred & TODO_TIMES) + && (archive_entry_mtime_is_set(entry) + || archive_entry_atime_is_set(entry))) { + fe = current_fixup(a, archive_entry_pathname(entry)); + if (fe == NULL) + return (ARCHIVE_FATAL); + fe->mode = a->mode; + fe->fixup |= TODO_TIMES; + if (archive_entry_atime_is_set(entry)) { + fe->atime = archive_entry_atime(entry); + fe->atime_nanos = archive_entry_atime_nsec(entry); + } else { + /* If atime is unset, use start time. */ + fe->atime = a->start_time; + fe->atime_nanos = 0; + } + if (archive_entry_mtime_is_set(entry)) { + fe->mtime = archive_entry_mtime(entry); + fe->mtime_nanos = archive_entry_mtime_nsec(entry); + } else { + /* If mtime is unset, use start time. */ + fe->mtime = a->start_time; + fe->mtime_nanos = 0; + } + if (archive_entry_birthtime_is_set(entry)) { + fe->birthtime = archive_entry_birthtime(entry); + fe->birthtime_nanos = archive_entry_birthtime_nsec( + entry); + } else { + /* If birthtime is unset, use mtime. */ + fe->birthtime = fe->mtime; + fe->birthtime_nanos = fe->mtime_nanos; + } + } + + if (a->deferred & TODO_ACLS) { + fe = current_fixup(a, archive_entry_pathname(entry)); + if (fe == NULL) + return (ARCHIVE_FATAL); + fe->fixup |= TODO_ACLS; + archive_acl_copy(&fe->acl, archive_entry_acl(entry)); + } + + if (a->deferred & TODO_MAC_METADATA) { + const void *metadata; + size_t metadata_size; + metadata = archive_entry_mac_metadata(a->entry, &metadata_size); + if (metadata != NULL && metadata_size > 0) { + fe = current_fixup(a, archive_entry_pathname(entry)); + if (fe == NULL) + return (ARCHIVE_FATAL); + fe->mac_metadata = malloc(metadata_size); + if (fe->mac_metadata != NULL) { + memcpy(fe->mac_metadata, metadata, + metadata_size); + fe->mac_metadata_size = metadata_size; + fe->fixup |= TODO_MAC_METADATA; + } + } + } + + if (a->deferred & TODO_FFLAGS) { + fe = current_fixup(a, archive_entry_pathname(entry)); + if (fe == NULL) + return (ARCHIVE_FATAL); + fe->fixup |= TODO_FFLAGS; + /* TODO: Complete this.. defer fflags from below. */ + } + + /* We've created the object and are ready to pour data into it. */ + if (ret >= ARCHIVE_WARN) + a->archive.state = ARCHIVE_STATE_DATA; + /* + * If it's not open, tell our client not to try writing. + * In particular, dirs, links, etc, don't get written to. + */ + if (a->fd < 0) { + archive_entry_set_size(entry, 0); + a->filesize = 0; + } + + return (ret); +} + +int +archive_write_disk_set_skip_file(struct archive *_a, la_int64_t d, la_int64_t i) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_write_disk_set_skip_file"); + a->skip_file_set = 1; + a->skip_file_dev = d; + a->skip_file_ino = i; + return (ARCHIVE_OK); +} + +static ssize_t +write_data_block(struct archive_write_disk *a, const char *buff, size_t size) +{ + uint64_t start_size = size; + ssize_t bytes_written = 0; + ssize_t block_size = 0, bytes_to_write; + + if (size == 0) + return (ARCHIVE_OK); + + if (a->filesize == 0 || a->fd < 0) { + archive_set_error(&a->archive, 0, + "Attempt to write to an empty file"); + return (ARCHIVE_WARN); + } + + if (a->flags & ARCHIVE_EXTRACT_SPARSE) { +#if HAVE_STRUCT_STAT_ST_BLKSIZE + int r; + if ((r = lazy_stat(a)) != ARCHIVE_OK) + return (r); + block_size = a->pst->st_blksize; +#else + /* XXX TODO XXX Is there a more appropriate choice here ? */ + /* This needn't match the filesystem allocation size. */ + block_size = 16*1024; +#endif + } + + /* If this write would run beyond the file size, truncate it. */ + if (a->filesize >= 0 && (int64_t)(a->offset + size) > a->filesize) + start_size = size = (size_t)(a->filesize - a->offset); + + /* Write the data. */ + while (size > 0) { + if (block_size == 0) { + bytes_to_write = size; + } else { + /* We're sparsifying the file. */ + const char *p, *end; + int64_t block_end; + + /* Skip leading zero bytes. */ + for (p = buff, end = buff + size; p < end; ++p) { + if (*p != '\0') + break; + } + a->offset += p - buff; + size -= p - buff; + buff = p; + if (size == 0) + break; + + /* Calculate next block boundary after offset. */ + block_end + = (a->offset / block_size + 1) * block_size; + + /* If the adjusted write would cross block boundary, + * truncate it to the block boundary. */ + bytes_to_write = size; + if (a->offset + bytes_to_write > block_end) + bytes_to_write = block_end - a->offset; + } + /* Seek if necessary to the specified offset. */ + if (a->offset != a->fd_offset) { + if (lseek(a->fd, a->offset, SEEK_SET) < 0) { + archive_set_error(&a->archive, errno, + "Seek failed"); + return (ARCHIVE_FATAL); + } + a->fd_offset = a->offset; + } + bytes_written = write(a->fd, buff, bytes_to_write); + if (bytes_written < 0) { + archive_set_error(&a->archive, errno, "Write failed"); + return (ARCHIVE_WARN); + } + buff += bytes_written; + size -= bytes_written; + a->total_bytes_written += bytes_written; + a->offset += bytes_written; + a->fd_offset = a->offset; + } + return (start_size - size); +} + +#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_SYS_XATTR_H)\ + && defined(HAVE_ZLIB_H) + +/* + * Set UF_COMPRESSED file flag. + * This have to be called after hfs_write_decmpfs() because if the + * file does not have "com.apple.decmpfs" xattr the flag is ignored. + */ +static int +hfs_set_compressed_fflag(struct archive_write_disk *a) +{ + int r; + + if ((r = lazy_stat(a)) != ARCHIVE_OK) + return (r); + + a->st.st_flags |= UF_COMPRESSED; + if (fchflags(a->fd, a->st.st_flags) != 0) { + archive_set_error(&a->archive, errno, + "Failed to set UF_COMPRESSED file flag"); + return (ARCHIVE_WARN); + } + return (ARCHIVE_OK); +} + +/* + * HFS+ Compression decmpfs + * + * +------------------------------+ +0 + * | Magic(LE 4 bytes) | + * +------------------------------+ + * | Type(LE 4 bytes) | + * +------------------------------+ + * | Uncompressed size(LE 8 bytes)| + * +------------------------------+ +16 + * | | + * | Compressed data | + * | (Placed only if Type == 3) | + * | | + * +------------------------------+ +3802 = MAX_DECMPFS_XATTR_SIZE + * + * Type is 3: decmpfs has compressed data. + * Type is 4: Resource Fork has compressed data. + */ +/* + * Write "com.apple.decmpfs" + */ +static int +hfs_write_decmpfs(struct archive_write_disk *a) +{ + int r; + uint32_t compression_type; + + r = fsetxattr(a->fd, DECMPFS_XATTR_NAME, a->decmpfs_header_p, + a->decmpfs_attr_size, 0, 0); + if (r < 0) { + archive_set_error(&a->archive, errno, + "Cannot restore xattr:%s", DECMPFS_XATTR_NAME); + compression_type = archive_le32dec( + &a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE]); + if (compression_type == CMP_RESOURCE_FORK) + fremovexattr(a->fd, XATTR_RESOURCEFORK_NAME, + XATTR_SHOWCOMPRESSION); + return (ARCHIVE_WARN); + } + return (ARCHIVE_OK); +} + +/* + * HFS+ Compression Resource Fork + * + * +-----------------------------+ + * | Header(260 bytes) | + * +-----------------------------+ + * | Block count(LE 4 bytes) | + * +-----------------------------+ --+ + * +-- | Offset (LE 4 bytes) | | + * | | [distance from Block count] | | Block 0 + * | +-----------------------------+ | + * | | Compressed size(LE 4 bytes) | | + * | +-----------------------------+ --+ + * | | | + * | | .................. | + * | | | + * | +-----------------------------+ --+ + * | | Offset (LE 4 bytes) | | + * | +-----------------------------+ | Block (Block count -1) + * | | Compressed size(LE 4 bytes) | | + * +-> +-----------------------------+ --+ + * | Compressed data(n bytes) | Block 0 + * +-----------------------------+ + * | | + * | .................. | + * | | + * +-----------------------------+ + * | Compressed data(n bytes) | Block (Block count -1) + * +-----------------------------+ + * | Footer(50 bytes) | + * +-----------------------------+ + * + */ +/* + * Write the header of "com.apple.ResourceFork" + */ +static int +hfs_write_resource_fork(struct archive_write_disk *a, unsigned char *buff, + size_t bytes, uint32_t position) +{ + int ret; + + ret = fsetxattr(a->fd, XATTR_RESOURCEFORK_NAME, buff, bytes, + position, a->rsrc_xattr_options); + if (ret < 0) { + archive_set_error(&a->archive, errno, + "Cannot restore xattr: %s at %u pos %u bytes", + XATTR_RESOURCEFORK_NAME, + (unsigned)position, + (unsigned)bytes); + return (ARCHIVE_WARN); + } + a->rsrc_xattr_options &= ~XATTR_CREATE; + return (ARCHIVE_OK); +} + +static int +hfs_write_compressed_data(struct archive_write_disk *a, size_t bytes_compressed) +{ + int ret; + + ret = hfs_write_resource_fork(a, a->compressed_buffer, + bytes_compressed, a->compressed_rsrc_position); + if (ret == ARCHIVE_OK) + a->compressed_rsrc_position += bytes_compressed; + return (ret); +} + +static int +hfs_write_resource_fork_header(struct archive_write_disk *a) +{ + unsigned char *buff; + uint32_t rsrc_bytes; + uint32_t rsrc_header_bytes; + + /* + * Write resource fork header + block info. + */ + buff = a->resource_fork; + rsrc_bytes = a->compressed_rsrc_position - RSRC_F_SIZE; + rsrc_header_bytes = + RSRC_H_SIZE + /* Header base size. */ + 4 + /* Block count. */ + (a->decmpfs_block_count * 8);/* Block info */ + archive_be32enc(buff, 0x100); + archive_be32enc(buff + 4, rsrc_bytes); + archive_be32enc(buff + 8, rsrc_bytes - 256); + archive_be32enc(buff + 12, 0x32); + memset(buff + 16, 0, 240); + archive_be32enc(buff + 256, rsrc_bytes - 260); + return hfs_write_resource_fork(a, buff, rsrc_header_bytes, 0); +} + +static size_t +hfs_set_resource_fork_footer(unsigned char *buff, size_t buff_size) +{ + static const char rsrc_footer[RSRC_F_SIZE] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1c, 0x00, 0x32, 0x00, 0x00, 'c', 'm', + 'p', 'f', 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 + }; + if (buff_size < sizeof(rsrc_footer)) + return (0); + memcpy(buff, rsrc_footer, sizeof(rsrc_footer)); + return (sizeof(rsrc_footer)); +} + +static int +hfs_reset_compressor(struct archive_write_disk *a) +{ + int ret; + + if (a->stream_valid) + ret = deflateReset(&a->stream); + else + ret = deflateInit(&a->stream, a->decmpfs_compression_level); + + if (ret != Z_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to initialize compressor"); + return (ARCHIVE_FATAL); + } else + a->stream_valid = 1; + + return (ARCHIVE_OK); +} + +static int +hfs_decompress(struct archive_write_disk *a) +{ + uint32_t *block_info; + unsigned int block_count; + uint32_t data_pos, data_size; + ssize_t r; + ssize_t bytes_written, bytes_to_write; + unsigned char *b; + + block_info = (uint32_t *)(a->resource_fork + RSRC_H_SIZE); + block_count = archive_le32dec(block_info++); + while (block_count--) { + data_pos = RSRC_H_SIZE + archive_le32dec(block_info++); + data_size = archive_le32dec(block_info++); + r = fgetxattr(a->fd, XATTR_RESOURCEFORK_NAME, + a->compressed_buffer, data_size, data_pos, 0); + if (r != data_size) { + archive_set_error(&a->archive, + (r < 0)?errno:ARCHIVE_ERRNO_MISC, + "Failed to read resource fork"); + return (ARCHIVE_WARN); + } + if (a->compressed_buffer[0] == 0xff) { + bytes_to_write = data_size -1; + b = a->compressed_buffer + 1; + } else { + uLong dest_len = MAX_DECMPFS_BLOCK_SIZE; + int zr; + + zr = uncompress((Bytef *)a->uncompressed_buffer, + &dest_len, a->compressed_buffer, data_size); + if (zr != Z_OK) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Failed to decompress resource fork"); + return (ARCHIVE_WARN); + } + bytes_to_write = dest_len; + b = (unsigned char *)a->uncompressed_buffer; + } + do { + bytes_written = write(a->fd, b, bytes_to_write); + if (bytes_written < 0) { + archive_set_error(&a->archive, errno, + "Write failed"); + return (ARCHIVE_WARN); + } + bytes_to_write -= bytes_written; + b += bytes_written; + } while (bytes_to_write > 0); + } + r = fremovexattr(a->fd, XATTR_RESOURCEFORK_NAME, 0); + if (r == -1) { + archive_set_error(&a->archive, errno, + "Failed to remove resource fork"); + return (ARCHIVE_WARN); + } + return (ARCHIVE_OK); +} + +static int +hfs_drive_compressor(struct archive_write_disk *a, const char *buff, + size_t size) +{ + unsigned char *buffer_compressed; + size_t bytes_compressed; + size_t bytes_used; + int ret; + + ret = hfs_reset_compressor(a); + if (ret != ARCHIVE_OK) + return (ret); + + if (a->compressed_buffer == NULL) { + size_t block_size; + + block_size = COMPRESSED_W_SIZE + RSRC_F_SIZE + + + compressBound(MAX_DECMPFS_BLOCK_SIZE); + a->compressed_buffer = malloc(block_size); + if (a->compressed_buffer == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Resource Fork"); + return (ARCHIVE_FATAL); + } + a->compressed_buffer_size = block_size; + a->compressed_buffer_remaining = block_size; + } + + buffer_compressed = a->compressed_buffer + + a->compressed_buffer_size - a->compressed_buffer_remaining; + a->stream.next_in = (Bytef *)(uintptr_t)(const void *)buff; + a->stream.avail_in = size; + a->stream.next_out = buffer_compressed; + a->stream.avail_out = a->compressed_buffer_remaining; + do { + ret = deflate(&a->stream, Z_FINISH); + switch (ret) { + case Z_OK: + case Z_STREAM_END: + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to compress data"); + return (ARCHIVE_FAILED); + } + } while (ret == Z_OK); + bytes_compressed = a->compressed_buffer_remaining - a->stream.avail_out; + + /* + * If the compressed size is larger than the original size, + * throw away compressed data, use uncompressed data instead. + */ + if (bytes_compressed > size) { + buffer_compressed[0] = 0xFF;/* uncompressed marker. */ + memcpy(buffer_compressed + 1, buff, size); + bytes_compressed = size + 1; + } + a->compressed_buffer_remaining -= bytes_compressed; + + /* + * If the compressed size is smaller than MAX_DECMPFS_XATTR_SIZE + * and the block count in the file is only one, store compressed + * data to decmpfs xattr instead of the resource fork. + */ + if (a->decmpfs_block_count == 1 && + (a->decmpfs_attr_size + bytes_compressed) + <= MAX_DECMPFS_XATTR_SIZE) { + archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE], + CMP_XATTR); + memcpy(a->decmpfs_header_p + DECMPFS_HEADER_SIZE, + buffer_compressed, bytes_compressed); + a->decmpfs_attr_size += bytes_compressed; + a->compressed_buffer_remaining = a->compressed_buffer_size; + /* + * Finish HFS+ Compression. + * - Write the decmpfs xattr. + * - Set the UF_COMPRESSED file flag. + */ + ret = hfs_write_decmpfs(a); + if (ret == ARCHIVE_OK) + ret = hfs_set_compressed_fflag(a); + return (ret); + } + + /* Update block info. */ + archive_le32enc(a->decmpfs_block_info++, + a->compressed_rsrc_position_v - RSRC_H_SIZE); + archive_le32enc(a->decmpfs_block_info++, bytes_compressed); + a->compressed_rsrc_position_v += bytes_compressed; + + /* + * Write the compressed data to the resource fork. + */ + bytes_used = a->compressed_buffer_size - a->compressed_buffer_remaining; + while (bytes_used >= COMPRESSED_W_SIZE) { + ret = hfs_write_compressed_data(a, COMPRESSED_W_SIZE); + if (ret != ARCHIVE_OK) + return (ret); + bytes_used -= COMPRESSED_W_SIZE; + if (bytes_used > COMPRESSED_W_SIZE) + memmove(a->compressed_buffer, + a->compressed_buffer + COMPRESSED_W_SIZE, + bytes_used); + else + memcpy(a->compressed_buffer, + a->compressed_buffer + COMPRESSED_W_SIZE, + bytes_used); + } + a->compressed_buffer_remaining = a->compressed_buffer_size - bytes_used; + + /* + * If the current block is the last block, write the remaining + * compressed data and the resource fork footer. + */ + if (a->file_remaining_bytes == 0) { + size_t rsrc_size; + int64_t bk; + + /* Append the resource footer. */ + rsrc_size = hfs_set_resource_fork_footer( + a->compressed_buffer + bytes_used, + a->compressed_buffer_remaining); + ret = hfs_write_compressed_data(a, bytes_used + rsrc_size); + a->compressed_buffer_remaining = a->compressed_buffer_size; + + /* If the compressed size is not enough smaller than + * the uncompressed size. cancel HFS+ compression. + * TODO: study a behavior of ditto utility and improve + * the condition to fall back into no HFS+ compression. */ + bk = HFS_BLOCKS(a->compressed_rsrc_position); + bk += bk >> 7; + if (bk > HFS_BLOCKS(a->filesize)) + return hfs_decompress(a); + /* + * Write the resourcefork header. + */ + if (ret == ARCHIVE_OK) + ret = hfs_write_resource_fork_header(a); + /* + * Finish HFS+ Compression. + * - Write the decmpfs xattr. + * - Set the UF_COMPRESSED file flag. + */ + if (ret == ARCHIVE_OK) + ret = hfs_write_decmpfs(a); + if (ret == ARCHIVE_OK) + ret = hfs_set_compressed_fflag(a); + } + return (ret); +} + +static ssize_t +hfs_write_decmpfs_block(struct archive_write_disk *a, const char *buff, + size_t size) +{ + const char *buffer_to_write; + size_t bytes_to_write; + int ret; + + if (a->decmpfs_block_count == (unsigned)-1) { + void *new_block; + size_t new_size; + unsigned int block_count; + + if (a->decmpfs_header_p == NULL) { + new_block = malloc(MAX_DECMPFS_XATTR_SIZE + + sizeof(uint32_t)); + if (new_block == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for decmpfs"); + return (ARCHIVE_FATAL); + } + a->decmpfs_header_p = new_block; + } + a->decmpfs_attr_size = DECMPFS_HEADER_SIZE; + archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_MAGIC], + DECMPFS_MAGIC); + archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE], + CMP_RESOURCE_FORK); + archive_le64enc(&a->decmpfs_header_p[DECMPFS_UNCOMPRESSED_SIZE], + a->filesize); + + /* Calculate a block count of the file. */ + block_count = + (a->filesize + MAX_DECMPFS_BLOCK_SIZE -1) / + MAX_DECMPFS_BLOCK_SIZE; + /* + * Allocate buffer for resource fork. + * Set up related pointers; + */ + new_size = + RSRC_H_SIZE + /* header */ + 4 + /* Block count */ + (block_count * sizeof(uint32_t) * 2) + + RSRC_F_SIZE; /* footer */ + if (new_size > a->resource_fork_allocated_size) { + new_block = realloc(a->resource_fork, new_size); + if (new_block == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for ResourceFork"); + return (ARCHIVE_FATAL); + } + a->resource_fork_allocated_size = new_size; + a->resource_fork = new_block; + } + + /* Allocate uncompressed buffer */ + if (a->uncompressed_buffer == NULL) { + new_block = malloc(MAX_DECMPFS_BLOCK_SIZE); + if (new_block == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for decmpfs"); + return (ARCHIVE_FATAL); + } + a->uncompressed_buffer = new_block; + } + a->block_remaining_bytes = MAX_DECMPFS_BLOCK_SIZE; + a->file_remaining_bytes = a->filesize; + a->compressed_buffer_remaining = a->compressed_buffer_size; + + /* + * Set up a resource fork. + */ + a->rsrc_xattr_options = XATTR_CREATE; + /* Get the position where we are going to set a bunch + * of block info. */ + a->decmpfs_block_info = + (uint32_t *)(a->resource_fork + RSRC_H_SIZE); + /* Set the block count to the resource fork. */ + archive_le32enc(a->decmpfs_block_info++, block_count); + /* Get the position where we are going to set compressed + * data. */ + a->compressed_rsrc_position = + RSRC_H_SIZE + 4 + (block_count * 8); + a->compressed_rsrc_position_v = a->compressed_rsrc_position; + a->decmpfs_block_count = block_count; + } + + /* Ignore redundant bytes. */ + if (a->file_remaining_bytes == 0) + return ((ssize_t)size); + + /* Do not overrun a block size. */ + if (size > a->block_remaining_bytes) + bytes_to_write = a->block_remaining_bytes; + else + bytes_to_write = size; + /* Do not overrun the file size. */ + if (bytes_to_write > a->file_remaining_bytes) + bytes_to_write = a->file_remaining_bytes; + + /* For efficiency, if a copy length is full of the uncompressed + * buffer size, do not copy writing data to it. */ + if (bytes_to_write == MAX_DECMPFS_BLOCK_SIZE) + buffer_to_write = buff; + else { + memcpy(a->uncompressed_buffer + + MAX_DECMPFS_BLOCK_SIZE - a->block_remaining_bytes, + buff, bytes_to_write); + buffer_to_write = a->uncompressed_buffer; + } + a->block_remaining_bytes -= bytes_to_write; + a->file_remaining_bytes -= bytes_to_write; + + if (a->block_remaining_bytes == 0 || a->file_remaining_bytes == 0) { + ret = hfs_drive_compressor(a, buffer_to_write, + MAX_DECMPFS_BLOCK_SIZE - a->block_remaining_bytes); + if (ret < 0) + return (ret); + a->block_remaining_bytes = MAX_DECMPFS_BLOCK_SIZE; + } + /* Ignore redundant bytes. */ + if (a->file_remaining_bytes == 0) + return ((ssize_t)size); + return (bytes_to_write); +} + +static ssize_t +hfs_write_data_block(struct archive_write_disk *a, const char *buff, + size_t size) +{ + uint64_t start_size = size; + ssize_t bytes_written = 0; + ssize_t bytes_to_write; + + if (size == 0) + return (ARCHIVE_OK); + + if (a->filesize == 0 || a->fd < 0) { + archive_set_error(&a->archive, 0, + "Attempt to write to an empty file"); + return (ARCHIVE_WARN); + } + + /* If this write would run beyond the file size, truncate it. */ + if (a->filesize >= 0 && (int64_t)(a->offset + size) > a->filesize) + start_size = size = (size_t)(a->filesize - a->offset); + + /* Write the data. */ + while (size > 0) { + bytes_to_write = size; + /* Seek if necessary to the specified offset. */ + if (a->offset < a->fd_offset) { + /* Can't support backward move. */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Seek failed"); + return (ARCHIVE_FATAL); + } else if (a->offset > a->fd_offset) { + int64_t skip = a->offset - a->fd_offset; + char nullblock[1024]; + + memset(nullblock, 0, sizeof(nullblock)); + while (skip > 0) { + if (skip > (int64_t)sizeof(nullblock)) + bytes_written = hfs_write_decmpfs_block( + a, nullblock, sizeof(nullblock)); + else + bytes_written = hfs_write_decmpfs_block( + a, nullblock, skip); + if (bytes_written < 0) { + archive_set_error(&a->archive, errno, + "Write failed"); + return (ARCHIVE_WARN); + } + skip -= bytes_written; + } + + a->fd_offset = a->offset; + } + bytes_written = + hfs_write_decmpfs_block(a, buff, bytes_to_write); + if (bytes_written < 0) + return (bytes_written); + buff += bytes_written; + size -= bytes_written; + a->total_bytes_written += bytes_written; + a->offset += bytes_written; + a->fd_offset = a->offset; + } + return (start_size - size); +} +#else +static ssize_t +hfs_write_data_block(struct archive_write_disk *a, const char *buff, + size_t size) +{ + return (write_data_block(a, buff, size)); +} +#endif + +static ssize_t +_archive_write_disk_data_block(struct archive *_a, + const void *buff, size_t size, int64_t offset) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + ssize_t r; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_DATA, "archive_write_data_block"); + + a->offset = offset; + if (a->todo & TODO_HFS_COMPRESSION) + r = hfs_write_data_block(a, buff, size); + else + r = write_data_block(a, buff, size); + if (r < ARCHIVE_OK) + return (r); + if ((size_t)r < size) { + archive_set_error(&a->archive, 0, + "Too much data: Truncating file at %ju bytes", + (uintmax_t)a->filesize); + return (ARCHIVE_WARN); + } +#if ARCHIVE_VERSION_NUMBER < 3999000 + return (ARCHIVE_OK); +#else + return (size); +#endif +} + +static ssize_t +_archive_write_disk_data(struct archive *_a, const void *buff, size_t size) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_DATA, "archive_write_data"); + + if (a->todo & TODO_HFS_COMPRESSION) + return (hfs_write_data_block(a, buff, size)); + return (write_data_block(a, buff, size)); +} + +static int +_archive_write_disk_finish_entry(struct archive *_a) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + int ret = ARCHIVE_OK; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_write_finish_entry"); + if (a->archive.state & ARCHIVE_STATE_HEADER) + return (ARCHIVE_OK); + archive_clear_error(&a->archive); + + /* Pad or truncate file to the right size. */ + if (a->fd < 0) { + /* There's no file. */ + } else if (a->filesize < 0) { + /* File size is unknown, so we can't set the size. */ + } else if (a->fd_offset == a->filesize) { + /* Last write ended at exactly the filesize; we're done. */ + /* Hopefully, this is the common case. */ +#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H) + } else if (a->todo & TODO_HFS_COMPRESSION) { + char null_d[1024]; + ssize_t r; + + if (a->file_remaining_bytes) + memset(null_d, 0, sizeof(null_d)); + while (a->file_remaining_bytes) { + if (a->file_remaining_bytes > sizeof(null_d)) + r = hfs_write_data_block( + a, null_d, sizeof(null_d)); + else + r = hfs_write_data_block( + a, null_d, a->file_remaining_bytes); + if (r < 0) + return ((int)r); + } +#endif + } else { +#if HAVE_FTRUNCATE + if (ftruncate(a->fd, a->filesize) == -1 && + a->filesize == 0) { + archive_set_error(&a->archive, errno, + "File size could not be restored"); + return (ARCHIVE_FAILED); + } +#endif + /* + * Not all platforms implement the XSI option to + * extend files via ftruncate. Stat() the file again + * to see what happened. + */ + a->pst = NULL; + if ((ret = lazy_stat(a)) != ARCHIVE_OK) + return (ret); + /* We can use lseek()/write() to extend the file if + * ftruncate didn't work or isn't available. */ + if (a->st.st_size < a->filesize) { + const char nul = '\0'; + if (lseek(a->fd, a->filesize - 1, SEEK_SET) < 0) { + archive_set_error(&a->archive, errno, + "Seek failed"); + return (ARCHIVE_FATAL); + } + if (write(a->fd, &nul, 1) < 0) { + archive_set_error(&a->archive, errno, + "Write to restore size failed"); + return (ARCHIVE_FATAL); + } + a->pst = NULL; + } + } + + /* Restore metadata. */ + + /* + * This is specific to Mac OS X. + * If the current file is an AppleDouble file, it should be + * linked with the data fork file and remove it. + */ + if (a->todo & TODO_APPLEDOUBLE) { + int r2 = fixup_appledouble(a, a->name); + if (r2 == ARCHIVE_EOF) { + /* The current file has been successfully linked + * with the data fork file and removed. So there + * is nothing to do on the current file. */ + goto finish_metadata; + } + if (r2 < ret) ret = r2; + } + + /* + * Look up the "real" UID only if we're going to need it. + * TODO: the TODO_SGID condition can be dropped here, can't it? + */ + if (a->todo & (TODO_OWNER | TODO_SUID | TODO_SGID)) { + a->uid = archive_write_disk_uid(&a->archive, + archive_entry_uname(a->entry), + archive_entry_uid(a->entry)); + } + /* Look up the "real" GID only if we're going to need it. */ + /* TODO: the TODO_SUID condition can be dropped here, can't it? */ + if (a->todo & (TODO_OWNER | TODO_SGID | TODO_SUID)) { + a->gid = archive_write_disk_gid(&a->archive, + archive_entry_gname(a->entry), + archive_entry_gid(a->entry)); + } + + /* + * Restore ownership before set_mode tries to restore suid/sgid + * bits. If we set the owner, we know what it is and can skip + * a stat() call to examine the ownership of the file on disk. + */ + if (a->todo & TODO_OWNER) { + int r2 = set_ownership(a); + if (r2 < ret) ret = r2; + } + + /* + * HYPOTHESIS: + * If we're not root, we won't be setting any security + * attributes that may be wiped by the set_mode() routine + * below. We also can't set xattr on non-owner-writable files, + * which may be the state after set_mode(). Perform + * set_xattrs() first based on these constraints. + */ + if (a->user_uid != 0 && + (a->todo & TODO_XATTR)) { + int r2 = set_xattrs(a); + if (r2 < ret) ret = r2; + } + + /* + * set_mode must precede ACLs on systems such as Solaris and + * FreeBSD where setting the mode implicitly clears extended ACLs + */ + if (a->todo & TODO_MODE) { + int r2 = set_mode(a, a->mode); + if (r2 < ret) ret = r2; + } + + /* + * Security-related extended attributes (such as + * security.capability on Linux) have to be restored last, + * since they're implicitly removed by other file changes. + * We do this last only when root. + */ + if (a->user_uid == 0 && + (a->todo & TODO_XATTR)) { + int r2 = set_xattrs(a); + if (r2 < ret) ret = r2; + } + + /* + * Some flags prevent file modification; they must be restored after + * file contents are written. + */ + if (a->todo & TODO_FFLAGS) { + int r2 = set_fflags(a); + if (r2 < ret) ret = r2; + } + + /* + * Time must follow most other metadata; + * otherwise atime will get changed. + */ + if (a->todo & TODO_TIMES) { + int r2 = set_times_from_entry(a); + if (r2 < ret) ret = r2; + } + + /* + * Mac extended metadata includes ACLs. + */ + if (a->todo & TODO_MAC_METADATA) { + const void *metadata; + size_t metadata_size; + metadata = archive_entry_mac_metadata(a->entry, &metadata_size); + if (metadata != NULL && metadata_size > 0) { + int r2 = set_mac_metadata(a, archive_entry_pathname( + a->entry), metadata, metadata_size); + if (r2 < ret) ret = r2; + } + } + + /* + * ACLs must be restored after timestamps because there are + * ACLs that prevent attribute changes (including time). + */ + if (a->todo & TODO_ACLS) { + int r2; + r2 = archive_write_disk_set_acls(&a->archive, a->fd, + archive_entry_pathname(a->entry), + archive_entry_acl(a->entry), + archive_entry_mode(a->entry)); + if (r2 < ret) ret = r2; + } + +finish_metadata: + /* If there's an fd, we can close it now. */ + if (a->fd >= 0) { + close(a->fd); + a->fd = -1; + if (a->tmpname) { + if (rename(a->tmpname, a->name) == -1) { + archive_set_error(&a->archive, errno, + "rename failed"); + ret = ARCHIVE_FATAL; + } + a->tmpname = NULL; + } + } + /* If there's an entry, we can release it now. */ + archive_entry_free(a->entry); + a->entry = NULL; + a->archive.state = ARCHIVE_STATE_HEADER; + return (ret); +} + +int +archive_write_disk_set_group_lookup(struct archive *_a, + void *private_data, + la_int64_t (*lookup_gid)(void *private, const char *gname, la_int64_t gid), + void (*cleanup_gid)(void *private)) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_write_disk_set_group_lookup"); + + if (a->cleanup_gid != NULL && a->lookup_gid_data != NULL) + (a->cleanup_gid)(a->lookup_gid_data); + + a->lookup_gid = lookup_gid; + a->cleanup_gid = cleanup_gid; + a->lookup_gid_data = private_data; + return (ARCHIVE_OK); +} + +int +archive_write_disk_set_user_lookup(struct archive *_a, + void *private_data, + int64_t (*lookup_uid)(void *private, const char *uname, int64_t uid), + void (*cleanup_uid)(void *private)) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_write_disk_set_user_lookup"); + + if (a->cleanup_uid != NULL && a->lookup_uid_data != NULL) + (a->cleanup_uid)(a->lookup_uid_data); + + a->lookup_uid = lookup_uid; + a->cleanup_uid = cleanup_uid; + a->lookup_uid_data = private_data; + return (ARCHIVE_OK); +} + +int64_t +archive_write_disk_gid(struct archive *_a, const char *name, la_int64_t id) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_write_disk_gid"); + if (a->lookup_gid) + return (a->lookup_gid)(a->lookup_gid_data, name, id); + return (id); +} + +int64_t +archive_write_disk_uid(struct archive *_a, const char *name, la_int64_t id) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_write_disk_uid"); + if (a->lookup_uid) + return (a->lookup_uid)(a->lookup_uid_data, name, id); + return (id); +} + +/* + * Create a new archive_write_disk object and initialize it with global state. + */ +struct archive * +archive_write_disk_new(void) +{ + struct archive_write_disk *a; + + a = (struct archive_write_disk *)calloc(1, sizeof(*a)); + if (a == NULL) + return (NULL); + a->archive.magic = ARCHIVE_WRITE_DISK_MAGIC; + /* We're ready to write a header immediately. */ + a->archive.state = ARCHIVE_STATE_HEADER; + a->archive.vtable = archive_write_disk_vtable(); + a->start_time = time(NULL); + /* Query and restore the umask. */ + umask(a->user_umask = umask(0)); +#ifdef HAVE_GETEUID + a->user_uid = geteuid(); +#endif /* HAVE_GETEUID */ + if (archive_string_ensure(&a->path_safe, 512) == NULL) { + free(a); + return (NULL); + } +#ifdef HAVE_ZLIB_H + a->decmpfs_compression_level = 5; +#endif + return (&a->archive); +} + + +/* + * If pathname is longer than PATH_MAX, chdir to a suitable + * intermediate dir and edit the path down to a shorter suffix. Note + * that this routine never returns an error; if the chdir() attempt + * fails for any reason, we just go ahead with the long pathname. The + * object creation is likely to fail, but any error will get handled + * at that time. + */ +#if defined(HAVE_FCHDIR) && defined(PATH_MAX) +static void +edit_deep_directories(struct archive_write_disk *a) +{ + int ret; + char *tail = a->name; + + /* If path is short, avoid the open() below. */ + if (strlen(tail) < PATH_MAX) + return; + + /* Try to record our starting dir. */ + a->restore_pwd = la_opendirat(AT_FDCWD, "."); + __archive_ensure_cloexec_flag(a->restore_pwd); + if (a->restore_pwd < 0) + return; + + /* As long as the path is too long... */ + while (strlen(tail) >= PATH_MAX) { + /* Locate a dir prefix shorter than PATH_MAX. */ + tail += PATH_MAX - 8; + while (tail > a->name && *tail != '/') + tail--; + /* Exit if we find a too-long path component. */ + if (tail <= a->name) + return; + /* Create the intermediate dir and chdir to it. */ + *tail = '\0'; /* Terminate dir portion */ + ret = create_dir(a, a->name); + if (ret == ARCHIVE_OK && chdir(a->name) != 0) + ret = ARCHIVE_FAILED; + *tail = '/'; /* Restore the / we removed. */ + if (ret != ARCHIVE_OK) + return; + tail++; + /* The chdir() succeeded; we've now shortened the path. */ + a->name = tail; + } + return; +} +#endif + +/* + * The main restore function. + */ +static int +restore_entry(struct archive_write_disk *a) +{ + int ret = ARCHIVE_OK, en; + + if (a->flags & ARCHIVE_EXTRACT_UNLINK && !S_ISDIR(a->mode)) { + /* + * TODO: Fix this. Apparently, there are platforms + * that still allow root to hose the entire filesystem + * by unlinking a dir. The S_ISDIR() test above + * prevents us from using unlink() here if the new + * object is a dir, but that doesn't mean the old + * object isn't a dir. + */ + if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS) + (void)clear_nochange_fflags(a); + if (unlink(a->name) == 0) { + /* We removed it, reset cached stat. */ + a->pst = NULL; + } else if (errno == ENOENT) { + /* File didn't exist, that's just as good. */ + } else if (rmdir(a->name) == 0) { + /* It was a dir, but now it's gone. */ + a->pst = NULL; + } else { + /* We tried, but couldn't get rid of it. */ + archive_set_error(&a->archive, errno, + "Could not unlink"); + return(ARCHIVE_FAILED); + } + } + + /* Try creating it first; if this fails, we'll try to recover. */ + en = create_filesystem_object(a); + + if ((en == ENOTDIR || en == ENOENT) + && !(a->flags & ARCHIVE_EXTRACT_NO_AUTODIR)) { + /* If the parent dir doesn't exist, try creating it. */ + create_parent_dir(a, a->name); + /* Now try to create the object again. */ + en = create_filesystem_object(a); + } + + if ((en == ENOENT) && (archive_entry_hardlink(a->entry) != NULL)) { + archive_set_error(&a->archive, en, + "Hard-link target '%s' does not exist.", + archive_entry_hardlink(a->entry)); + return (ARCHIVE_FAILED); + } + + if ((en == EISDIR || en == EEXIST) + && (a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) { + /* If we're not overwriting, we're done. */ + if (S_ISDIR(a->mode)) { + /* Don't overwrite any settings on existing directories. */ + a->todo = 0; + } + archive_entry_unset_size(a->entry); + return (ARCHIVE_OK); + } + + /* + * Some platforms return EISDIR if you call + * open(O_WRONLY | O_EXCL | O_CREAT) on a directory, some + * return EEXIST. POSIX is ambiguous, requiring EISDIR + * for open(O_WRONLY) on a dir and EEXIST for open(O_EXCL | O_CREAT) + * on an existing item. + */ + if (en == EISDIR) { + /* A dir is in the way of a non-dir, rmdir it. */ + if (rmdir(a->name) != 0) { + archive_set_error(&a->archive, errno, + "Can't remove already-existing dir"); + return (ARCHIVE_FAILED); + } + a->pst = NULL; + /* Try again. */ + en = create_filesystem_object(a); + } else if (en == EEXIST) { + /* + * We know something is in the way, but we don't know what; + * we need to find out before we go any further. + */ + int r = 0; + /* + * The SECURE_SYMLINKS logic has already removed a + * symlink to a dir if the client wants that. So + * follow the symlink if we're creating a dir. + */ + if (S_ISDIR(a->mode)) + r = la_stat(a->name, &a->st); + /* + * If it's not a dir (or it's a broken symlink), + * then don't follow it. + */ + if (r != 0 || !S_ISDIR(a->mode)) + r = lstat(a->name, &a->st); + if (r != 0) { + archive_set_error(&a->archive, errno, + "Can't stat existing object"); + return (ARCHIVE_FAILED); + } + + /* + * NO_OVERWRITE_NEWER doesn't apply to directories. + */ + if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER) + && !S_ISDIR(a->st.st_mode)) { + if (!older(&(a->st), a->entry)) { + archive_entry_unset_size(a->entry); + return (ARCHIVE_OK); + } + } + + /* If it's our archive, we're done. */ + if (a->skip_file_set && + a->st.st_dev == (dev_t)a->skip_file_dev && + a->st.st_ino == (ino_t)a->skip_file_ino) { + archive_set_error(&a->archive, 0, + "Refusing to overwrite archive"); + return (ARCHIVE_FAILED); + } + + if (!S_ISDIR(a->st.st_mode)) { + if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS) + (void)clear_nochange_fflags(a); + + if ((a->flags & ARCHIVE_EXTRACT_SAFE_WRITES) && + S_ISREG(a->st.st_mode)) { + /* Use a temporary file to extract */ + if ((a->fd = la_mktemp(a)) == -1) + return ARCHIVE_FAILED; + a->pst = NULL; + en = 0; + } else { + /* A non-dir is in the way, unlink it. */ + if (unlink(a->name) != 0) { + archive_set_error(&a->archive, errno, + "Can't unlink already-existing " + "object"); + return (ARCHIVE_FAILED); + } + a->pst = NULL; + /* Try again. */ + en = create_filesystem_object(a); + } + } else if (!S_ISDIR(a->mode)) { + /* A dir is in the way of a non-dir, rmdir it. */ + if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS) + (void)clear_nochange_fflags(a); + if (rmdir(a->name) != 0) { + archive_set_error(&a->archive, errno, + "Can't replace existing directory with non-directory"); + return (ARCHIVE_FAILED); + } + /* Try again. */ + en = create_filesystem_object(a); + } else { + /* + * There's a dir in the way of a dir. Don't + * waste time with rmdir()/mkdir(), just fix + * up the permissions on the existing dir. + * Note that we don't change perms on existing + * dirs unless _EXTRACT_PERM is specified. + */ + if ((a->mode != a->st.st_mode) + && (a->todo & TODO_MODE_FORCE)) + a->deferred |= (a->todo & TODO_MODE); + /* Ownership doesn't need deferred fixup. */ + en = 0; /* Forget the EEXIST. */ + } + } + + if (en) { + /* Everything failed; give up here. */ + if ((&a->archive)->error == NULL) + archive_set_error(&a->archive, en, "Can't create '%s'", + a->name); + return (ARCHIVE_FAILED); + } + + a->pst = NULL; /* Cached stat data no longer valid. */ + return (ret); +} + +/* + * Returns 0 if creation succeeds, or else returns errno value from + * the failed system call. Note: This function should only ever perform + * a single system call. + */ +static int +create_filesystem_object(struct archive_write_disk *a) +{ + /* Create the entry. */ + const char *linkname; + mode_t final_mode, mode; + int r; + /* these for check_symlinks_fsobj */ + char *linkname_copy; /* non-const copy of linkname */ + struct stat st; + struct archive_string error_string; + int error_number; + + /* We identify hard/symlinks according to the link names. */ + /* Since link(2) and symlink(2) don't handle modes, we're done here. */ + linkname = archive_entry_hardlink(a->entry); + if (linkname != NULL) { +#if !HAVE_LINK + return (EPERM); +#else + archive_string_init(&error_string); + linkname_copy = strdup(linkname); + if (linkname_copy == NULL) { + return (EPERM); + } + /* + * TODO: consider using the cleaned-up path as the link + * target? + */ + r = cleanup_pathname_fsobj(linkname_copy, &error_number, + &error_string, a->flags); + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, error_number, "%s", + error_string.s); + free(linkname_copy); + archive_string_free(&error_string); + /* + * EPERM is more appropriate than error_number for our + * callers + */ + return (EPERM); + } + r = check_symlinks_fsobj(linkname_copy, &error_number, + &error_string, a->flags); + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, error_number, "%s", + error_string.s); + free(linkname_copy); + archive_string_free(&error_string); + /* + * EPERM is more appropriate than error_number for our + * callers + */ + return (EPERM); + } + free(linkname_copy); + archive_string_free(&error_string); + /* + * Unlinking and linking here is really not atomic, + * but doing it right, would require us to construct + * an mktemplink() function, and then use rename(2). + */ + if (a->flags & ARCHIVE_EXTRACT_SAFE_WRITES) + unlink(a->name); + r = link(linkname, a->name) ? errno : 0; + /* + * New cpio and pax formats allow hardlink entries + * to carry data, so we may have to open the file + * for hardlink entries. + * + * If the hardlink was successfully created and + * the archive doesn't have carry data for it, + * consider it to be non-authoritative for meta data. + * This is consistent with GNU tar and BSD pax. + * If the hardlink does carry data, let the last + * archive entry decide ownership. + */ + if (r == 0 && a->filesize <= 0) { + a->todo = 0; + a->deferred = 0; + } else if (r == 0 && a->filesize > 0) { +#ifdef HAVE_LSTAT + r = lstat(a->name, &st); +#else + r = la_stat(a->name, &st); +#endif + if (r != 0) + r = errno; + else if ((st.st_mode & AE_IFMT) == AE_IFREG) { + a->fd = open(a->name, O_WRONLY | O_TRUNC | + O_BINARY | O_CLOEXEC | O_NOFOLLOW); + __archive_ensure_cloexec_flag(a->fd); + if (a->fd < 0) + r = errno; + } + } + return (r); +#endif + } + linkname = archive_entry_symlink(a->entry); + if (linkname != NULL) { +#if HAVE_SYMLINK + /* + * Unlinking and linking here is really not atomic, + * but doing it right, would require us to construct + * an mktempsymlink() function, and then use rename(2). + */ + if (a->flags & ARCHIVE_EXTRACT_SAFE_WRITES) + unlink(a->name); + return symlink(linkname, a->name) ? errno : 0; +#else + return (EPERM); +#endif + } + + /* + * The remaining system calls all set permissions, so let's + * try to take advantage of that to avoid an extra chmod() + * call. (Recall that umask is set to zero right now!) + */ + + /* Mode we want for the final restored object (w/o file type bits). */ + final_mode = a->mode & 07777; + /* + * The mode that will actually be restored in this step. Note + * that SUID, SGID, etc, require additional work to ensure + * security, so we never restore them at this point. + */ + mode = final_mode & 0777 & ~a->user_umask; + + /* + * Always create writable such that [f]setxattr() works if we're not + * root. + */ + if (a->user_uid != 0 && + a->todo & (TODO_HFS_COMPRESSION | TODO_XATTR)) { + mode |= 0200; + } + + switch (a->mode & AE_IFMT) { + default: + /* POSIX requires that we fall through here. */ + /* FALLTHROUGH */ + case AE_IFREG: + a->tmpname = NULL; + a->fd = open(a->name, + O_WRONLY | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC, mode); + __archive_ensure_cloexec_flag(a->fd); + r = (a->fd < 0); + break; + case AE_IFCHR: +#ifdef HAVE_MKNOD + /* Note: we use AE_IFCHR for the case label, and + * S_IFCHR for the mknod() call. This is correct. */ + r = mknod(a->name, mode | S_IFCHR, + archive_entry_rdev(a->entry)); + break; +#else + /* TODO: Find a better way to warn about our inability + * to restore a char device node. */ + return (EINVAL); +#endif /* HAVE_MKNOD */ + case AE_IFBLK: +#ifdef HAVE_MKNOD + r = mknod(a->name, mode | S_IFBLK, + archive_entry_rdev(a->entry)); + break; +#else + /* TODO: Find a better way to warn about our inability + * to restore a block device node. */ + return (EINVAL); +#endif /* HAVE_MKNOD */ + case AE_IFDIR: + mode = (mode | MINIMUM_DIR_MODE) & MAXIMUM_DIR_MODE; + r = mkdir(a->name, mode); + if (r == 0) { + /* Defer setting dir times. */ + a->deferred |= (a->todo & TODO_TIMES); + a->todo &= ~TODO_TIMES; + /* Never use an immediate chmod(). */ + /* We can't avoid the chmod() entirely if EXTRACT_PERM + * because of SysV SGID inheritance. */ + if ((mode != final_mode) + || (a->flags & ARCHIVE_EXTRACT_PERM)) + a->deferred |= (a->todo & TODO_MODE); + a->todo &= ~TODO_MODE; + } + break; + case AE_IFIFO: +#ifdef HAVE_MKFIFO + r = mkfifo(a->name, mode); + break; +#else + /* TODO: Find a better way to warn about our inability + * to restore a fifo. */ + return (EINVAL); +#endif /* HAVE_MKFIFO */ + } + + /* All the system calls above set errno on failure. */ + if (r) + return (errno); + + /* If we managed to set the final mode, we've avoided a chmod(). */ + if (mode == final_mode) + a->todo &= ~TODO_MODE; + return (0); +} + +/* + * Cleanup function for archive_extract. Mostly, this involves processing + * the fixup list, which is used to address a number of problems: + * * Dir permissions might prevent us from restoring a file in that + * dir, so we restore the dir with minimum 0700 permissions first, + * then correct the mode at the end. + * * Similarly, the act of restoring a file touches the directory + * and changes the timestamp on the dir, so we have to touch-up dir + * timestamps at the end as well. + * * Some file flags can interfere with the restore by, for example, + * preventing the creation of hardlinks to those files. + * * Mac OS extended metadata includes ACLs, so must be deferred on dirs. + * + * Note that tar/cpio do not require that archives be in a particular + * order; there is no way to know when the last file has been restored + * within a directory, so there's no way to optimize the memory usage + * here by fixing up the directory any earlier than the + * end-of-archive. + * + * XXX TODO: Directory ACLs should be restored here, for the same + * reason we set directory perms here. XXX + */ +static int +_archive_write_disk_close(struct archive *_a) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + struct fixup_entry *next, *p; + int fd, ret; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_write_disk_close"); + ret = _archive_write_disk_finish_entry(&a->archive); + + /* Sort dir list so directories are fixed up in depth-first order. */ + p = sort_dir_list(a->fixup_list); + + while (p != NULL) { + fd = -1; + a->pst = NULL; /* Mark stat cache as out-of-date. */ + if (p->fixup & + (TODO_TIMES | TODO_MODE_BASE | TODO_ACLS | TODO_FFLAGS)) { + fd = open(p->name, + O_WRONLY | O_BINARY | O_NOFOLLOW | O_CLOEXEC); + } + if (p->fixup & TODO_TIMES) { + set_times(a, fd, p->mode, p->name, + p->atime, p->atime_nanos, + p->birthtime, p->birthtime_nanos, + p->mtime, p->mtime_nanos, + p->ctime, p->ctime_nanos); + } + if (p->fixup & TODO_MODE_BASE) { +#ifdef HAVE_FCHMOD + if (fd >= 0) + fchmod(fd, p->mode); + else +#endif + chmod(p->name, p->mode); + } + if (p->fixup & TODO_ACLS) + archive_write_disk_set_acls(&a->archive, fd, + p->name, &p->acl, p->mode); + if (p->fixup & TODO_FFLAGS) + set_fflags_platform(a, fd, p->name, + p->mode, p->fflags_set, 0); + if (p->fixup & TODO_MAC_METADATA) + set_mac_metadata(a, p->name, p->mac_metadata, + p->mac_metadata_size); + next = p->next; + archive_acl_clear(&p->acl); + free(p->mac_metadata); + free(p->name); + if (fd >= 0) + close(fd); + free(p); + p = next; + } + a->fixup_list = NULL; + return (ret); +} + +static int +_archive_write_disk_free(struct archive *_a) +{ + struct archive_write_disk *a; + int ret; + if (_a == NULL) + return (ARCHIVE_OK); + archive_check_magic(_a, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_write_disk_free"); + a = (struct archive_write_disk *)_a; + ret = _archive_write_disk_close(&a->archive); + archive_write_disk_set_group_lookup(&a->archive, NULL, NULL, NULL); + archive_write_disk_set_user_lookup(&a->archive, NULL, NULL, NULL); + archive_entry_free(a->entry); + archive_string_free(&a->_name_data); + archive_string_free(&a->_tmpname_data); + archive_string_free(&a->archive.error_string); + archive_string_free(&a->path_safe); + a->archive.magic = 0; + __archive_clean(&a->archive); + free(a->decmpfs_header_p); + free(a->resource_fork); + free(a->compressed_buffer); + free(a->uncompressed_buffer); +#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_SYS_XATTR_H)\ + && defined(HAVE_ZLIB_H) + if (a->stream_valid) { + switch (deflateEnd(&a->stream)) { + case Z_OK: + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to clean up compressor"); + ret = ARCHIVE_FATAL; + break; + } + } +#endif + free(a); + return (ret); +} + +/* + * Simple O(n log n) merge sort to order the fixup list. In + * particular, we want to restore dir timestamps depth-first. + */ +static struct fixup_entry * +sort_dir_list(struct fixup_entry *p) +{ + struct fixup_entry *a, *b, *t; + + if (p == NULL) + return (NULL); + /* A one-item list is already sorted. */ + if (p->next == NULL) + return (p); + + /* Step 1: split the list. */ + t = p; + a = p->next->next; + while (a != NULL) { + /* Step a twice, t once. */ + a = a->next; + if (a != NULL) + a = a->next; + t = t->next; + } + /* Now, t is at the mid-point, so break the list here. */ + b = t->next; + t->next = NULL; + a = p; + + /* Step 2: Recursively sort the two sub-lists. */ + a = sort_dir_list(a); + b = sort_dir_list(b); + + /* Step 3: Merge the returned lists. */ + /* Pick the first element for the merged list. */ + if (strcmp(a->name, b->name) > 0) { + t = p = a; + a = a->next; + } else { + t = p = b; + b = b->next; + } + + /* Always put the later element on the list first. */ + while (a != NULL && b != NULL) { + if (strcmp(a->name, b->name) > 0) { + t->next = a; + a = a->next; + } else { + t->next = b; + b = b->next; + } + t = t->next; + } + + /* Only one list is non-empty, so just splice it on. */ + if (a != NULL) + t->next = a; + if (b != NULL) + t->next = b; + + return (p); +} + +/* + * Returns a new, initialized fixup entry. + * + * TODO: Reduce the memory requirements for this list by using a tree + * structure rather than a simple list of names. + */ +static struct fixup_entry * +new_fixup(struct archive_write_disk *a, const char *pathname) +{ + struct fixup_entry *fe; + + fe = (struct fixup_entry *)calloc(1, sizeof(struct fixup_entry)); + if (fe == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for a fixup"); + return (NULL); + } + fe->next = a->fixup_list; + a->fixup_list = fe; + fe->fixup = 0; + fe->name = strdup(pathname); + return (fe); +} + +/* + * Returns a fixup structure for the current entry. + */ +static struct fixup_entry * +current_fixup(struct archive_write_disk *a, const char *pathname) +{ + if (a->current_fixup == NULL) + a->current_fixup = new_fixup(a, pathname); + return (a->current_fixup); +} + +/* Error helper for new *_fsobj functions */ +static void +fsobj_error(int *a_eno, struct archive_string *a_estr, + int err, const char *errstr, const char *path) +{ + if (a_eno) + *a_eno = err; + if (a_estr) + archive_string_sprintf(a_estr, "%s%s", errstr, path); +} + +/* + * TODO: Someday, integrate this with the deep dir support; they both + * scan the path and both can be optimized by comparing against other + * recent paths. + */ +/* + * Checks the given path to see if any elements along it are symlinks. Returns + * ARCHIVE_OK if there are none, otherwise puts an error in errmsg. + */ +static int +check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, + int flags) +{ +#if !defined(HAVE_LSTAT) && \ + !(defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)) + /* Platform doesn't have lstat, so we can't look for symlinks. */ + (void)path; /* UNUSED */ + (void)error_number; /* UNUSED */ + (void)error_string; /* UNUSED */ + (void)flags; /* UNUSED */ + return (ARCHIVE_OK); +#else + int res = ARCHIVE_OK; + char *tail; + char *head; + int last; + char c; + int r; + struct stat st; + int chdir_fd; +#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT) + int fd; +#endif + + /* Nothing to do here if name is empty */ + if(path[0] == '\0') + return (ARCHIVE_OK); + + /* + * Guard against symlink tricks. Reject any archive entry whose + * destination would be altered by a symlink. + * + * Walk the filename in chunks separated by '/'. For each segment: + * - if it doesn't exist, continue + * - if it's symlink, abort or remove it + * - if it's a directory and it's not the last chunk, cd into it + * As we go: + * head points to the current (relative) path + * tail points to the temporary \0 terminating the segment we're + * currently examining + * c holds what used to be in *tail + * last is 1 if this is the last tail + */ + chdir_fd = la_opendirat(AT_FDCWD, "."); + __archive_ensure_cloexec_flag(chdir_fd); + if (chdir_fd < 0) { + fsobj_error(a_eno, a_estr, errno, + "Could not open ", path); + return (ARCHIVE_FATAL); + } + head = path; + tail = path; + last = 0; + /* TODO: reintroduce a safe cache here? */ + /* Skip the root directory if the path is absolute. */ + if(tail == path && tail[0] == '/') + ++tail; + /* Keep going until we've checked the entire name. + * head, tail, path all alias the same string, which is + * temporarily zeroed at tail, so be careful restoring the + * stashed (c=tail[0]) for error messages. + * Exiting the loop with break is okay; continue is not. + */ + while (!last) { + /* + * Skip the separator we just consumed, plus any adjacent ones + */ + while (*tail == '/') + ++tail; + /* Skip the next path element. */ + while (*tail != '\0' && *tail != '/') + ++tail; + /* is this the last path component? */ + last = (tail[0] == '\0') || (tail[0] == '/' && tail[1] == '\0'); + /* temporarily truncate the string here */ + c = tail[0]; + tail[0] = '\0'; + /* Check that we haven't hit a symlink. */ +#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT) + r = fstatat(chdir_fd, head, &st, AT_SYMLINK_NOFOLLOW); +#else + r = lstat(head, &st); +#endif + if (r != 0) { + tail[0] = c; + /* We've hit a dir that doesn't exist; stop now. */ + if (errno == ENOENT) { + break; + } else { + /* + * Treat any other error as fatal - best to be + * paranoid here. + * Note: This effectively disables deep + * directory support when security checks are + * enabled. Otherwise, very long pathnames that + * trigger an error here could evade the + * sandbox. + * TODO: We could do better, but it would + * probably require merging the symlink checks + * with the deep-directory editing. + */ + fsobj_error(a_eno, a_estr, errno, + "Could not stat ", path); + res = ARCHIVE_FAILED; + break; + } + } else if (S_ISDIR(st.st_mode)) { + if (!last) { +#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT) + fd = la_opendirat(chdir_fd, head); + if (fd < 0) + r = -1; + else { + r = 0; + close(chdir_fd); + chdir_fd = fd; + } +#else + r = chdir(head); +#endif + if (r != 0) { + tail[0] = c; + fsobj_error(a_eno, a_estr, errno, + "Could not chdir ", path); + res = (ARCHIVE_FATAL); + break; + } + /* Our view is now from inside this dir: */ + head = tail + 1; + } + } else if (S_ISLNK(st.st_mode)) { + if (last) { + /* + * Last element is symlink; remove it + * so we can overwrite it with the + * item being extracted. + */ +#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT) + r = unlinkat(chdir_fd, head, 0); +#else + r = unlink(head); +#endif + if (r != 0) { + tail[0] = c; + fsobj_error(a_eno, a_estr, errno, + "Could not remove symlink ", + path); + res = ARCHIVE_FAILED; + break; + } + /* + * Even if we did remove it, a warning + * is in order. The warning is silly, + * though, if we're just replacing one + * symlink with another symlink. + */ + tail[0] = c; + /* + * FIXME: not sure how important this is to + * restore + */ + /* + if (!S_ISLNK(path)) { + fsobj_error(a_eno, a_estr, 0, + "Removing symlink ", path); + } + */ + /* Symlink gone. No more problem! */ + res = ARCHIVE_OK; + break; + } else if (flags & ARCHIVE_EXTRACT_UNLINK) { + /* User asked us to remove problems. */ +#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT) + r = unlinkat(chdir_fd, head, 0); +#else + r = unlink(head); +#endif + if (r != 0) { + tail[0] = c; + fsobj_error(a_eno, a_estr, 0, + "Cannot remove intervening " + "symlink ", path); + res = ARCHIVE_FAILED; + break; + } + tail[0] = c; + } else if ((flags & + ARCHIVE_EXTRACT_SECURE_SYMLINKS) == 0) { + /* + * We are not the last element and we want to + * follow symlinks if they are a directory. + * + * This is needed to extract hardlinks over + * symlinks. + */ +#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT) + r = fstatat(chdir_fd, head, &st, 0); +#else + r = la_stat(head, &st); +#endif + if (r != 0) { + tail[0] = c; + if (errno == ENOENT) { + break; + } else { + fsobj_error(a_eno, a_estr, + errno, + "Could not stat ", path); + res = (ARCHIVE_FAILED); + break; + } + } else if (S_ISDIR(st.st_mode)) { +#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT) + fd = la_opendirat(chdir_fd, head); + if (fd < 0) + r = -1; + else { + r = 0; + close(chdir_fd); + chdir_fd = fd; + } +#else + r = chdir(head); +#endif + if (r != 0) { + tail[0] = c; + fsobj_error(a_eno, a_estr, + errno, + "Could not chdir ", path); + res = (ARCHIVE_FATAL); + break; + } + /* + * Our view is now from inside + * this dir: + */ + head = tail + 1; + } else { + tail[0] = c; + fsobj_error(a_eno, a_estr, 0, + "Cannot extract through " + "symlink ", path); + res = ARCHIVE_FAILED; + break; + } + } else { + tail[0] = c; + fsobj_error(a_eno, a_estr, 0, + "Cannot extract through symlink ", path); + res = ARCHIVE_FAILED; + break; + } + } + /* be sure to always maintain this */ + tail[0] = c; + if (tail[0] != '\0') + tail++; /* Advance to the next segment. */ + } + /* Catches loop exits via break */ + tail[0] = c; +#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT) + /* If we operate with openat(), fstatat() and unlinkat() there was + * no chdir(), so just close the fd */ + if (chdir_fd >= 0) + close(chdir_fd); +#elif HAVE_FCHDIR + /* If we changed directory above, restore it here. */ + if (chdir_fd >= 0) { + r = fchdir(chdir_fd); + if (r != 0) { + fsobj_error(a_eno, a_estr, errno, + "chdir() failure", ""); + } + close(chdir_fd); + chdir_fd = -1; + if (r != 0) { + res = (ARCHIVE_FATAL); + } + } +#endif + /* TODO: reintroduce a safe cache here? */ + return res; +#endif +} + +/* + * Check a->name for symlinks, returning ARCHIVE_OK if its clean, otherwise + * calls archive_set_error and returns ARCHIVE_{FATAL,FAILED} + */ +static int +check_symlinks(struct archive_write_disk *a) +{ + struct archive_string error_string; + int error_number; + int rc; + archive_string_init(&error_string); + rc = check_symlinks_fsobj(a->name, &error_number, &error_string, + a->flags); + if (rc != ARCHIVE_OK) { + archive_set_error(&a->archive, error_number, "%s", + error_string.s); + } + archive_string_free(&error_string); + a->pst = NULL; /* to be safe */ + return rc; +} + + +#if defined(__CYGWIN__) +/* + * 1. Convert a path separator from '\' to '/' . + * We shouldn't check multibyte character directly because some + * character-set have been using the '\' character for a part of + * its multibyte character code. + * 2. Replace unusable characters in Windows with underscore('_'). + * See also : http://msdn.microsoft.com/en-us/library/aa365247.aspx + */ +static void +cleanup_pathname_win(char *path) +{ + wchar_t wc; + char *p; + size_t alen, l; + int mb, complete, utf8; + + alen = 0; + mb = 0; + complete = 1; + utf8 = (strcmp(nl_langinfo(CODESET), "UTF-8") == 0)? 1: 0; + for (p = path; *p != '\0'; p++) { + ++alen; + if (*p == '\\') { + /* If previous byte is smaller than 128, + * this is not second byte of multibyte characters, + * so we can replace '\' with '/'. */ + if (utf8 || !mb) + *p = '/'; + else + complete = 0;/* uncompleted. */ + } else if (*(unsigned char *)p > 127) + mb = 1; + else + mb = 0; + /* Rewrite the path name if its next character is unusable. */ + if (*p == ':' || *p == '*' || *p == '?' || *p == '"' || + *p == '<' || *p == '>' || *p == '|') + *p = '_'; + } + if (complete) + return; + + /* + * Convert path separator in wide-character. + */ + p = path; + while (*p != '\0' && alen) { + l = mbtowc(&wc, p, alen); + if (l == (size_t)-1) { + while (*p != '\0') { + if (*p == '\\') + *p = '/'; + ++p; + } + break; + } + if (l == 1 && wc == L'\\') + *p = '/'; + p += l; + alen -= l; + } +} +#endif + +/* + * Canonicalize the pathname. In particular, this strips duplicate + * '/' characters, '.' elements, and trailing '/'. It also raises an + * error for an empty path, a trailing '..', (if _SECURE_NODOTDOT is + * set) any '..' in the path or (if ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS + * is set) if the path is absolute. + */ +static int +cleanup_pathname_fsobj(char *path, int *a_eno, struct archive_string *a_estr, + int flags) +{ + char *dest, *src; + char separator = '\0'; + + dest = src = path; + if (*src == '\0') { + fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC, + "Invalid empty ", "pathname"); + return (ARCHIVE_FAILED); + } + +#if defined(__CYGWIN__) + cleanup_pathname_win(path); +#endif + /* Skip leading '/'. */ + if (*src == '/') { + if (flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) { + fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC, + "Path is ", "absolute"); + return (ARCHIVE_FAILED); + } + + separator = *src++; + } + + /* Scan the pathname one element at a time. */ + for (;;) { + /* src points to first char after '/' */ + if (src[0] == '\0') { + break; + } else if (src[0] == '/') { + /* Found '//', ignore second one. */ + src++; + continue; + } else if (src[0] == '.') { + if (src[1] == '\0') { + /* Ignore trailing '.' */ + break; + } else if (src[1] == '/') { + /* Skip './'. */ + src += 2; + continue; + } else if (src[1] == '.') { + if (src[2] == '/' || src[2] == '\0') { + /* Conditionally warn about '..' */ + if (flags + & ARCHIVE_EXTRACT_SECURE_NODOTDOT) { + fsobj_error(a_eno, a_estr, + ARCHIVE_ERRNO_MISC, + "Path contains ", "'..'"); + return (ARCHIVE_FAILED); + } + } + /* + * Note: Under no circumstances do we + * remove '..' elements. In + * particular, restoring + * '/foo/../bar/' should create the + * 'foo' dir as a side-effect. + */ + } + } + + /* Copy current element, including leading '/'. */ + if (separator) + *dest++ = '/'; + while (*src != '\0' && *src != '/') { + *dest++ = *src++; + } + + if (*src == '\0') + break; + + /* Skip '/' separator. */ + separator = *src++; + } + /* + * We've just copied zero or more path elements, not including the + * final '/'. + */ + if (dest == path) { + /* + * Nothing got copied. The path must have been something + * like '.' or '/' or './' or '/././././/./'. + */ + if (separator) + *dest++ = '/'; + else + *dest++ = '.'; + } + /* Terminate the result. */ + *dest = '\0'; + return (ARCHIVE_OK); +} + +static int +cleanup_pathname(struct archive_write_disk *a) +{ + struct archive_string error_string; + int error_number; + int rc; + archive_string_init(&error_string); + rc = cleanup_pathname_fsobj(a->name, &error_number, &error_string, + a->flags); + if (rc != ARCHIVE_OK) { + archive_set_error(&a->archive, error_number, "%s", + error_string.s); + } + archive_string_free(&error_string); + return rc; +} + +/* + * Create the parent directory of the specified path, assuming path + * is already in mutable storage. + */ +static int +create_parent_dir(struct archive_write_disk *a, char *path) +{ + char *slash; + int r; + + /* Remove tail element to obtain parent name. */ + slash = strrchr(path, '/'); + if (slash == NULL) + return (ARCHIVE_OK); + *slash = '\0'; + r = create_dir(a, path); + *slash = '/'; + return (r); +} + +/* + * Create the specified dir, recursing to create parents as necessary. + * + * Returns ARCHIVE_OK if the path exists when we're done here. + * Otherwise, returns ARCHIVE_FAILED. + * Assumes path is in mutable storage; path is unchanged on exit. + */ +static int +create_dir(struct archive_write_disk *a, char *path) +{ + struct stat st; + struct fixup_entry *le; + char *slash, *base; + mode_t mode_final, mode; + int r; + + /* Check for special names and just skip them. */ + slash = strrchr(path, '/'); + if (slash == NULL) + base = path; + else + base = slash + 1; + + if (base[0] == '\0' || + (base[0] == '.' && base[1] == '\0') || + (base[0] == '.' && base[1] == '.' && base[2] == '\0')) { + /* Don't bother trying to create null path, '.', or '..'. */ + if (slash != NULL) { + *slash = '\0'; + r = create_dir(a, path); + *slash = '/'; + return (r); + } + return (ARCHIVE_OK); + } + + /* + * Yes, this should be stat() and not lstat(). Using lstat() + * here loses the ability to extract through symlinks. Also note + * that this should not use the a->st cache. + */ + if (la_stat(path, &st) == 0) { + if (S_ISDIR(st.st_mode)) + return (ARCHIVE_OK); + if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) { + archive_set_error(&a->archive, EEXIST, + "Can't create directory '%s'", path); + return (ARCHIVE_FAILED); + } + if (unlink(path) != 0) { + archive_set_error(&a->archive, errno, + "Can't create directory '%s': " + "Conflicting file cannot be removed", + path); + return (ARCHIVE_FAILED); + } + } else if (errno != ENOENT && errno != ENOTDIR) { + /* Stat failed? */ + archive_set_error(&a->archive, errno, + "Can't test directory '%s'", path); + return (ARCHIVE_FAILED); + } else if (slash != NULL) { + *slash = '\0'; + r = create_dir(a, path); + *slash = '/'; + if (r != ARCHIVE_OK) + return (r); + } + + /* + * Mode we want for the final restored directory. Per POSIX, + * implicitly-created dirs must be created obeying the umask. + * There's no mention whether this is different for privileged + * restores (which the rest of this code handles by pretending + * umask=0). I've chosen here to always obey the user's umask for + * implicit dirs, even if _EXTRACT_PERM was specified. + */ + mode_final = DEFAULT_DIR_MODE & ~a->user_umask; + /* Mode we want on disk during the restore process. */ + mode = mode_final; + mode |= MINIMUM_DIR_MODE; + mode &= MAXIMUM_DIR_MODE; + if (mkdir(path, mode) == 0) { + if (mode != mode_final) { + le = new_fixup(a, path); + if (le == NULL) + return (ARCHIVE_FATAL); + le->fixup |=TODO_MODE_BASE; + le->mode = mode_final; + } + return (ARCHIVE_OK); + } + + /* + * Without the following check, a/b/../b/c/d fails at the + * second visit to 'b', so 'd' can't be created. Note that we + * don't add it to the fixup list here, as it's already been + * added. + */ + if (la_stat(path, &st) == 0 && S_ISDIR(st.st_mode)) + return (ARCHIVE_OK); + + archive_set_error(&a->archive, errno, "Failed to create dir '%s'", + path); + return (ARCHIVE_FAILED); +} + +/* + * Note: Although we can skip setting the user id if the desired user + * id matches the current user, we cannot skip setting the group, as + * many systems set the gid based on the containing directory. So + * we have to perform a chown syscall if we want to set the SGID + * bit. (The alternative is to stat() and then possibly chown(); it's + * more efficient to skip the stat() and just always chown().) Note + * that a successful chown() here clears the TODO_SGID_CHECK bit, which + * allows set_mode to skip the stat() check for the GID. + */ +static int +set_ownership(struct archive_write_disk *a) +{ +#if !defined(__CYGWIN__) && !defined(__linux__) +/* + * On Linux, a process may have the CAP_CHOWN capability. + * On Windows there is no 'root' user with uid 0. + * Elsewhere we can skip calling chown if we are not root and the desired + * user id does not match the current user. + */ + if (a->user_uid != 0 && a->user_uid != a->uid) { + archive_set_error(&a->archive, errno, + "Can't set UID=%jd", (intmax_t)a->uid); + return (ARCHIVE_WARN); + } +#endif + +#ifdef HAVE_FCHOWN + /* If we have an fd, we can avoid a race. */ + if (a->fd >= 0 && fchown(a->fd, a->uid, a->gid) == 0) { + /* We've set owner and know uid/gid are correct. */ + a->todo &= ~(TODO_OWNER | TODO_SGID_CHECK | TODO_SUID_CHECK); + return (ARCHIVE_OK); + } +#endif + + /* We prefer lchown() but will use chown() if that's all we have. */ + /* Of course, if we have neither, this will always fail. */ +#ifdef HAVE_LCHOWN + if (lchown(a->name, a->uid, a->gid) == 0) { + /* We've set owner and know uid/gid are correct. */ + a->todo &= ~(TODO_OWNER | TODO_SGID_CHECK | TODO_SUID_CHECK); + return (ARCHIVE_OK); + } +#elif HAVE_CHOWN + if (!S_ISLNK(a->mode) && chown(a->name, a->uid, a->gid) == 0) { + /* We've set owner and know uid/gid are correct. */ + a->todo &= ~(TODO_OWNER | TODO_SGID_CHECK | TODO_SUID_CHECK); + return (ARCHIVE_OK); + } +#endif + + archive_set_error(&a->archive, errno, + "Can't set user=%jd/group=%jd for %s", + (intmax_t)a->uid, (intmax_t)a->gid, a->name); + return (ARCHIVE_WARN); +} + +/* + * Note: Returns 0 on success, non-zero on failure. + */ +static int +set_time(int fd, int mode, const char *name, + time_t atime, long atime_nsec, + time_t mtime, long mtime_nsec) +{ + /* Select the best implementation for this platform. */ +#if defined(HAVE_UTIMENSAT) && defined(HAVE_FUTIMENS) + /* + * utimensat() and futimens() are defined in + * POSIX.1-2008. They support ns resolution and setting times + * on fds and symlinks. + */ + struct timespec ts[2]; + (void)mode; /* UNUSED */ + ts[0].tv_sec = atime; + ts[0].tv_nsec = atime_nsec; + ts[1].tv_sec = mtime; + ts[1].tv_nsec = mtime_nsec; + if (fd >= 0) + return futimens(fd, ts); + return utimensat(AT_FDCWD, name, ts, AT_SYMLINK_NOFOLLOW); + +#elif HAVE_UTIMES + /* + * The utimes()-family functions support µs-resolution and + * setting times fds and symlinks. utimes() is documented as + * LEGACY by POSIX, futimes() and lutimes() are not described + * in POSIX. + */ + struct timeval times[2]; + + times[0].tv_sec = atime; + times[0].tv_usec = atime_nsec / 1000; + times[1].tv_sec = mtime; + times[1].tv_usec = mtime_nsec / 1000; + +#ifdef HAVE_FUTIMES + if (fd >= 0) + return (futimes(fd, times)); +#else + (void)fd; /* UNUSED */ +#endif +#ifdef HAVE_LUTIMES + (void)mode; /* UNUSED */ + return (lutimes(name, times)); +#else + if (S_ISLNK(mode)) + return (0); + return (utimes(name, times)); +#endif + +#elif defined(HAVE_UTIME) + /* + * utime() is POSIX-standard but only supports 1s resolution and + * does not support fds or symlinks. + */ + struct utimbuf times; + (void)fd; /* UNUSED */ + (void)name; /* UNUSED */ + (void)atime_nsec; /* UNUSED */ + (void)mtime_nsec; /* UNUSED */ + times.actime = atime; + times.modtime = mtime; + if (S_ISLNK(mode)) + return (ARCHIVE_OK); + return (utime(name, ×)); + +#else + /* + * We don't know how to set the time on this platform. + */ + (void)fd; /* UNUSED */ + (void)mode; /* UNUSED */ + (void)name; /* UNUSED */ + (void)atime_nsec; /* UNUSED */ + (void)mtime_nsec; /* UNUSED */ + return (ARCHIVE_WARN); +#endif +} + +#ifdef F_SETTIMES +static int +set_time_tru64(int fd, int mode, const char *name, + time_t atime, long atime_nsec, + time_t mtime, long mtime_nsec, + time_t ctime, long ctime_nsec) +{ + struct attr_timbuf tstamp; + tstamp.atime.tv_sec = atime; + tstamp.mtime.tv_sec = mtime; + tstamp.ctime.tv_sec = ctime; +#if defined (__hpux) && defined (__ia64) + tstamp.atime.tv_nsec = atime_nsec; + tstamp.mtime.tv_nsec = mtime_nsec; + tstamp.ctime.tv_nsec = ctime_nsec; +#else + tstamp.atime.tv_usec = atime_nsec / 1000; + tstamp.mtime.tv_usec = mtime_nsec / 1000; + tstamp.ctime.tv_usec = ctime_nsec / 1000; +#endif + return (fcntl(fd,F_SETTIMES,&tstamp)); +} +#endif /* F_SETTIMES */ + +static int +set_times(struct archive_write_disk *a, + int fd, int mode, const char *name, + time_t atime, long atime_nanos, + time_t birthtime, long birthtime_nanos, + time_t mtime, long mtime_nanos, + time_t cctime, long ctime_nanos) +{ + /* Note: set_time doesn't use libarchive return conventions! + * It uses syscall conventions. So 0 here instead of ARCHIVE_OK. */ + int r1 = 0, r2 = 0; + +#ifdef F_SETTIMES + /* + * on Tru64 try own fcntl first which can restore even the + * ctime, fall back to default code path below if it fails + * or if we are not running as root + */ + if (a->user_uid == 0 && + set_time_tru64(fd, mode, name, + atime, atime_nanos, mtime, + mtime_nanos, cctime, ctime_nanos) == 0) { + return (ARCHIVE_OK); + } +#else /* Tru64 */ + (void)cctime; /* UNUSED */ + (void)ctime_nanos; /* UNUSED */ +#endif /* Tru64 */ + +#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME + /* + * If you have struct stat.st_birthtime, we assume BSD + * birthtime semantics, in which {f,l,}utimes() updates + * birthtime to earliest mtime. So we set the time twice, + * first using the birthtime, then using the mtime. If + * birthtime == mtime, this isn't necessary, so we skip it. + * If birthtime > mtime, then this won't work, so we skip it. + */ + if (birthtime < mtime + || (birthtime == mtime && birthtime_nanos < mtime_nanos)) + r1 = set_time(fd, mode, name, + atime, atime_nanos, + birthtime, birthtime_nanos); +#else + (void)birthtime; /* UNUSED */ + (void)birthtime_nanos; /* UNUSED */ +#endif + r2 = set_time(fd, mode, name, + atime, atime_nanos, + mtime, mtime_nanos); + if (r1 != 0 || r2 != 0) { + archive_set_error(&a->archive, errno, + "Can't restore time"); + return (ARCHIVE_WARN); + } + return (ARCHIVE_OK); +} + +static int +set_times_from_entry(struct archive_write_disk *a) +{ + time_t atime, birthtime, mtime, cctime; + long atime_nsec, birthtime_nsec, mtime_nsec, ctime_nsec; + + /* Suitable defaults. */ + atime = birthtime = mtime = cctime = a->start_time; + atime_nsec = birthtime_nsec = mtime_nsec = ctime_nsec = 0; + + /* If no time was provided, we're done. */ + if (!archive_entry_atime_is_set(a->entry) +#if HAVE_STRUCT_STAT_ST_BIRTHTIME + && !archive_entry_birthtime_is_set(a->entry) +#endif + && !archive_entry_mtime_is_set(a->entry)) + return (ARCHIVE_OK); + + if (archive_entry_atime_is_set(a->entry)) { + atime = archive_entry_atime(a->entry); + atime_nsec = archive_entry_atime_nsec(a->entry); + } + if (archive_entry_birthtime_is_set(a->entry)) { + birthtime = archive_entry_birthtime(a->entry); + birthtime_nsec = archive_entry_birthtime_nsec(a->entry); + } + if (archive_entry_mtime_is_set(a->entry)) { + mtime = archive_entry_mtime(a->entry); + mtime_nsec = archive_entry_mtime_nsec(a->entry); + } + if (archive_entry_ctime_is_set(a->entry)) { + cctime = archive_entry_ctime(a->entry); + ctime_nsec = archive_entry_ctime_nsec(a->entry); + } + + return set_times(a, a->fd, a->mode, a->name, + atime, atime_nsec, + birthtime, birthtime_nsec, + mtime, mtime_nsec, + cctime, ctime_nsec); +} + +static int +set_mode(struct archive_write_disk *a, int mode) +{ + int r = ARCHIVE_OK; + int r2; + mode &= 07777; /* Strip off file type bits. */ + + if (a->todo & TODO_SGID_CHECK) { + /* + * If we don't know the GID is right, we must stat() + * to verify it. We can't just check the GID of this + * process, since systems sometimes set GID from + * the enclosing dir or based on ACLs. + */ + if ((r = lazy_stat(a)) != ARCHIVE_OK) + return (r); + if (a->pst->st_gid != a->gid) { + mode &= ~ S_ISGID; + if (a->flags & ARCHIVE_EXTRACT_OWNER) { + /* + * This is only an error if you + * requested owner restore. If you + * didn't, we'll try to restore + * sgid/suid, but won't consider it a + * problem if we can't. + */ + archive_set_error(&a->archive, -1, + "Can't restore SGID bit"); + r = ARCHIVE_WARN; + } + } + /* While we're here, double-check the UID. */ + if (a->pst->st_uid != a->uid + && (a->todo & TODO_SUID)) { + mode &= ~ S_ISUID; + if (a->flags & ARCHIVE_EXTRACT_OWNER) { + archive_set_error(&a->archive, -1, + "Can't restore SUID bit"); + r = ARCHIVE_WARN; + } + } + a->todo &= ~TODO_SGID_CHECK; + a->todo &= ~TODO_SUID_CHECK; + } else if (a->todo & TODO_SUID_CHECK) { + /* + * If we don't know the UID is right, we can just check + * the user, since all systems set the file UID from + * the process UID. + */ + if (a->user_uid != a->uid) { + mode &= ~ S_ISUID; + if (a->flags & ARCHIVE_EXTRACT_OWNER) { + archive_set_error(&a->archive, -1, + "Can't make file SUID"); + r = ARCHIVE_WARN; + } + } + a->todo &= ~TODO_SUID_CHECK; + } + + if (S_ISLNK(a->mode)) { +#ifdef HAVE_LCHMOD + /* + * If this is a symlink, use lchmod(). If the + * platform doesn't support lchmod(), just skip it. A + * platform that doesn't provide a way to set + * permissions on symlinks probably ignores + * permissions on symlinks, so a failure here has no + * impact. + */ + if (lchmod(a->name, mode) != 0) { + switch (errno) { + case ENOTSUP: + case ENOSYS: +#if ENOTSUP != EOPNOTSUPP + case EOPNOTSUPP: +#endif + /* + * if lchmod is defined but the platform + * doesn't support it, silently ignore + * error + */ + break; + default: + archive_set_error(&a->archive, errno, + "Can't set permissions to 0%o", (int)mode); + r = ARCHIVE_WARN; + } + } +#endif + } else if (!S_ISDIR(a->mode)) { + /* + * If it's not a symlink and not a dir, then use + * fchmod() or chmod(), depending on whether we have + * an fd. Dirs get their perms set during the + * post-extract fixup, which is handled elsewhere. + */ +#ifdef HAVE_FCHMOD + if (a->fd >= 0) + r2 = fchmod(a->fd, mode); + else +#endif + /* If this platform lacks fchmod(), then + * we'll just use chmod(). */ + r2 = chmod(a->name, mode); + + if (r2 != 0) { + archive_set_error(&a->archive, errno, + "Can't set permissions to 0%o", (int)mode); + r = ARCHIVE_WARN; + } + } + return (r); +} + +static int +set_fflags(struct archive_write_disk *a) +{ + struct fixup_entry *le; + unsigned long set, clear; + int r; + mode_t mode = archive_entry_mode(a->entry); + /* + * Make 'critical_flags' hold all file flags that can't be + * immediately restored. For example, on BSD systems, + * SF_IMMUTABLE prevents hardlinks from being created, so + * should not be set until after any hardlinks are created. To + * preserve some semblance of portability, this uses #ifdef + * extensively. Ugly, but it works. + * + * Yes, Virginia, this does create a security race. It's mitigated + * somewhat by the practice of creating dirs 0700 until the extract + * is done, but it would be nice if we could do more than that. + * People restoring critical file systems should be wary of + * other programs that might try to muck with files as they're + * being restored. + */ + const int critical_flags = 0 +#ifdef SF_IMMUTABLE + | SF_IMMUTABLE +#endif +#ifdef UF_IMMUTABLE + | UF_IMMUTABLE +#endif +#ifdef SF_APPEND + | SF_APPEND +#endif +#ifdef UF_APPEND + | UF_APPEND +#endif +#if defined(FS_APPEND_FL) + | FS_APPEND_FL +#elif defined(EXT2_APPEND_FL) + | EXT2_APPEND_FL +#endif +#if defined(FS_IMMUTABLE_FL) + | FS_IMMUTABLE_FL +#elif defined(EXT2_IMMUTABLE_FL) + | EXT2_IMMUTABLE_FL +#endif +#ifdef FS_JOURNAL_DATA_FL + | FS_JOURNAL_DATA_FL +#endif + ; + + if (a->todo & TODO_FFLAGS) { + archive_entry_fflags(a->entry, &set, &clear); + + /* + * The first test encourages the compiler to eliminate + * all of this if it's not necessary. + */ + if ((critical_flags != 0) && (set & critical_flags)) { + le = current_fixup(a, a->name); + if (le == NULL) + return (ARCHIVE_FATAL); + le->fixup |= TODO_FFLAGS; + le->fflags_set = set; + /* Store the mode if it's not already there. */ + if ((le->fixup & TODO_MODE) == 0) + le->mode = mode; + } else { + r = set_fflags_platform(a, a->fd, + a->name, mode, set, clear); + if (r != ARCHIVE_OK) + return (r); + } + } + return (ARCHIVE_OK); +} + +static int +clear_nochange_fflags(struct archive_write_disk *a) +{ + mode_t mode = archive_entry_mode(a->entry); + const int nochange_flags = 0 +#ifdef SF_IMMUTABLE + | SF_IMMUTABLE +#endif +#ifdef UF_IMMUTABLE + | UF_IMMUTABLE +#endif +#ifdef SF_APPEND + | SF_APPEND +#endif +#ifdef UF_APPEND + | UF_APPEND +#endif +#ifdef EXT2_APPEND_FL + | EXT2_APPEND_FL +#endif +#ifdef EXT2_IMMUTABLE_FL + | EXT2_IMMUTABLE_FL +#endif + ; + + return (set_fflags_platform(a, a->fd, a->name, mode, 0, + nochange_flags)); +} + + +#if ( defined(HAVE_LCHFLAGS) || defined(HAVE_CHFLAGS) || defined(HAVE_FCHFLAGS) ) && defined(HAVE_STRUCT_STAT_ST_FLAGS) +/* + * BSD reads flags using stat() and sets them with one of {f,l,}chflags() + */ +static int +set_fflags_platform(struct archive_write_disk *a, int fd, const char *name, + mode_t mode, unsigned long set, unsigned long clear) +{ + int r; + const int sf_mask = 0 +#ifdef SF_APPEND + | SF_APPEND +#endif +#ifdef SF_ARCHIVED + | SF_ARCHIVED +#endif +#ifdef SF_IMMUTABLE + | SF_IMMUTABLE +#endif +#ifdef SF_NOUNLINK + | SF_NOUNLINK +#endif + ; + (void)mode; /* UNUSED */ + + if (set == 0 && clear == 0) + return (ARCHIVE_OK); + + /* + * XXX Is the stat here really necessary? Or can I just use + * the 'set' flags directly? In particular, I'm not sure + * about the correct approach if we're overwriting an existing + * file that already has flags on it. XXX + */ + if ((r = lazy_stat(a)) != ARCHIVE_OK) + return (r); + + a->st.st_flags &= ~clear; + a->st.st_flags |= set; + + /* Only super-user may change SF_* flags */ + + if (a->user_uid != 0) + a->st.st_flags &= ~sf_mask; + +#ifdef HAVE_FCHFLAGS + /* If platform has fchflags() and we were given an fd, use it. */ + if (fd >= 0 && fchflags(fd, a->st.st_flags) == 0) + return (ARCHIVE_OK); +#endif + /* + * If we can't use the fd to set the flags, we'll use the + * pathname to set flags. We prefer lchflags() but will use + * chflags() if we must. + */ +#ifdef HAVE_LCHFLAGS + if (lchflags(name, a->st.st_flags) == 0) + return (ARCHIVE_OK); +#elif defined(HAVE_CHFLAGS) + if (S_ISLNK(a->st.st_mode)) { + archive_set_error(&a->archive, errno, + "Can't set file flags on symlink."); + return (ARCHIVE_WARN); + } + if (chflags(name, a->st.st_flags) == 0) + return (ARCHIVE_OK); +#endif + archive_set_error(&a->archive, errno, + "Failed to set file flags"); + return (ARCHIVE_WARN); +} + +#elif (defined(FS_IOC_GETFLAGS) && defined(FS_IOC_SETFLAGS) && \ + defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \ + (defined(EXT2_IOC_GETFLAGS) && defined(EXT2_IOC_SETFLAGS) && \ + defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)) +/* + * Linux uses ioctl() to read and write file flags. + */ +static int +set_fflags_platform(struct archive_write_disk *a, int fd, const char *name, + mode_t mode, unsigned long set, unsigned long clear) +{ + int ret; + int myfd = fd; + int newflags, oldflags; + /* + * Linux has no define for the flags that are only settable by + * the root user. This code may seem a little complex, but + * there seem to be some Linux systems that lack these + * defines. (?) The code below degrades reasonably gracefully + * if sf_mask is incomplete. + */ + const int sf_mask = 0 +#if defined(FS_IMMUTABLE_FL) + | FS_IMMUTABLE_FL +#elif defined(EXT2_IMMUTABLE_FL) + | EXT2_IMMUTABLE_FL +#endif +#if defined(FS_APPEND_FL) + | FS_APPEND_FL +#elif defined(EXT2_APPEND_FL) + | EXT2_APPEND_FL +#endif +#if defined(FS_JOURNAL_DATA_FL) + | FS_JOURNAL_DATA_FL +#endif + ; + + if (set == 0 && clear == 0) + return (ARCHIVE_OK); + /* Only regular files and dirs can have flags. */ + if (!S_ISREG(mode) && !S_ISDIR(mode)) + return (ARCHIVE_OK); + + /* If we weren't given an fd, open it ourselves. */ + if (myfd < 0) { + myfd = open(name, O_RDONLY | O_NONBLOCK | O_BINARY | O_CLOEXEC); + __archive_ensure_cloexec_flag(myfd); + } + if (myfd < 0) + return (ARCHIVE_OK); + + /* + * XXX As above, this would be way simpler if we didn't have + * to read the current flags from disk. XXX + */ + ret = ARCHIVE_OK; + + /* Read the current file flags. */ + if (ioctl(myfd, +#ifdef FS_IOC_GETFLAGS + FS_IOC_GETFLAGS, +#else + EXT2_IOC_GETFLAGS, +#endif + &oldflags) < 0) + goto fail; + + /* Try setting the flags as given. */ + newflags = (oldflags & ~clear) | set; + if (ioctl(myfd, +#ifdef FS_IOC_SETFLAGS + FS_IOC_SETFLAGS, +#else + EXT2_IOC_SETFLAGS, +#endif + &newflags) >= 0) + goto cleanup; + if (errno != EPERM) + goto fail; + + /* If we couldn't set all the flags, try again with a subset. */ + newflags &= ~sf_mask; + oldflags &= sf_mask; + newflags |= oldflags; + if (ioctl(myfd, +#ifdef FS_IOC_SETFLAGS + FS_IOC_SETFLAGS, +#else + EXT2_IOC_SETFLAGS, +#endif + &newflags) >= 0) + goto cleanup; + + /* We couldn't set the flags, so report the failure. */ +fail: + archive_set_error(&a->archive, errno, + "Failed to set file flags"); + ret = ARCHIVE_WARN; +cleanup: + if (fd < 0) + close(myfd); + return (ret); +} + +#else + +/* + * Of course, some systems have neither BSD chflags() nor Linux' flags + * support through ioctl(). + */ +static int +set_fflags_platform(struct archive_write_disk *a, int fd, const char *name, + mode_t mode, unsigned long set, unsigned long clear) +{ + (void)a; /* UNUSED */ + (void)fd; /* UNUSED */ + (void)name; /* UNUSED */ + (void)mode; /* UNUSED */ + (void)set; /* UNUSED */ + (void)clear; /* UNUSED */ + return (ARCHIVE_OK); +} + +#endif /* __linux */ + +#ifndef HAVE_COPYFILE_H +/* Default is to simply drop Mac extended metadata. */ +static int +set_mac_metadata(struct archive_write_disk *a, const char *pathname, + const void *metadata, size_t metadata_size) +{ + (void)a; /* UNUSED */ + (void)pathname; /* UNUSED */ + (void)metadata; /* UNUSED */ + (void)metadata_size; /* UNUSED */ + return (ARCHIVE_OK); +} + +static int +fixup_appledouble(struct archive_write_disk *a, const char *pathname) +{ + (void)a; /* UNUSED */ + (void)pathname; /* UNUSED */ + return (ARCHIVE_OK); +} +#else + +/* + * On Mac OS, we use copyfile() to unpack the metadata and + * apply it to the target file. + */ + +#if defined(HAVE_SYS_XATTR_H) +static int +copy_xattrs(struct archive_write_disk *a, int tmpfd, int dffd) +{ + ssize_t xattr_size; + char *xattr_names = NULL, *xattr_val = NULL; + int ret = ARCHIVE_OK, xattr_i; + + xattr_size = flistxattr(tmpfd, NULL, 0, 0); + if (xattr_size == -1) { + archive_set_error(&a->archive, errno, + "Failed to read metadata(xattr)"); + ret = ARCHIVE_WARN; + goto exit_xattr; + } + xattr_names = malloc(xattr_size); + if (xattr_names == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for metadata(xattr)"); + ret = ARCHIVE_FATAL; + goto exit_xattr; + } + xattr_size = flistxattr(tmpfd, xattr_names, xattr_size, 0); + if (xattr_size == -1) { + archive_set_error(&a->archive, errno, + "Failed to read metadata(xattr)"); + ret = ARCHIVE_WARN; + goto exit_xattr; + } + for (xattr_i = 0; xattr_i < xattr_size; + xattr_i += strlen(xattr_names + xattr_i) + 1) { + char *xattr_val_saved; + ssize_t s; + int f; + + s = fgetxattr(tmpfd, xattr_names + xattr_i, NULL, 0, 0, 0); + if (s == -1) { + archive_set_error(&a->archive, errno, + "Failed to get metadata(xattr)"); + ret = ARCHIVE_WARN; + goto exit_xattr; + } + xattr_val_saved = xattr_val; + xattr_val = realloc(xattr_val, s); + if (xattr_val == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Failed to get metadata(xattr)"); + ret = ARCHIVE_WARN; + free(xattr_val_saved); + goto exit_xattr; + } + s = fgetxattr(tmpfd, xattr_names + xattr_i, xattr_val, s, 0, 0); + if (s == -1) { + archive_set_error(&a->archive, errno, + "Failed to get metadata(xattr)"); + ret = ARCHIVE_WARN; + goto exit_xattr; + } + f = fsetxattr(dffd, xattr_names + xattr_i, xattr_val, s, 0, 0); + if (f == -1) { + archive_set_error(&a->archive, errno, + "Failed to get metadata(xattr)"); + ret = ARCHIVE_WARN; + goto exit_xattr; + } + } +exit_xattr: + free(xattr_names); + free(xattr_val); + return (ret); +} +#endif + +static int +copy_acls(struct archive_write_disk *a, int tmpfd, int dffd) +{ +#ifndef HAVE_SYS_ACL_H + return 0; +#else + acl_t acl, dfacl = NULL; + int acl_r, ret = ARCHIVE_OK; + + acl = acl_get_fd(tmpfd); + if (acl == NULL) { + if (errno == ENOENT) + /* There are not any ACLs. */ + return (ret); + archive_set_error(&a->archive, errno, + "Failed to get metadata(acl)"); + ret = ARCHIVE_WARN; + goto exit_acl; + } + dfacl = acl_dup(acl); + acl_r = acl_set_fd(dffd, dfacl); + if (acl_r == -1) { + archive_set_error(&a->archive, errno, + "Failed to get metadata(acl)"); + ret = ARCHIVE_WARN; + goto exit_acl; + } +exit_acl: + if (acl) + acl_free(acl); + if (dfacl) + acl_free(dfacl); + return (ret); +#endif +} + +static int +create_tempdatafork(struct archive_write_disk *a, const char *pathname) +{ + struct archive_string tmpdatafork; + int tmpfd; + + archive_string_init(&tmpdatafork); + archive_strcpy(&tmpdatafork, "tar.md.XXXXXX"); + tmpfd = mkstemp(tmpdatafork.s); + if (tmpfd < 0) { + archive_set_error(&a->archive, errno, + "Failed to mkstemp"); + archive_string_free(&tmpdatafork); + return (-1); + } + if (copyfile(pathname, tmpdatafork.s, 0, + COPYFILE_UNPACK | COPYFILE_NOFOLLOW + | COPYFILE_ACL | COPYFILE_XATTR) < 0) { + archive_set_error(&a->archive, errno, + "Failed to restore metadata"); + close(tmpfd); + tmpfd = -1; + } + unlink(tmpdatafork.s); + archive_string_free(&tmpdatafork); + return (tmpfd); +} + +static int +copy_metadata(struct archive_write_disk *a, const char *metadata, + const char *datafork, int datafork_compressed) +{ + int ret = ARCHIVE_OK; + + if (datafork_compressed) { + int dffd, tmpfd; + + tmpfd = create_tempdatafork(a, metadata); + if (tmpfd == -1) + return (ARCHIVE_WARN); + + /* + * Do not open the data fork compressed by HFS+ compression + * with at least a writing mode(O_RDWR or O_WRONLY). it + * makes the data fork uncompressed. + */ + dffd = open(datafork, 0); + if (dffd == -1) { + archive_set_error(&a->archive, errno, + "Failed to open the data fork for metadata"); + close(tmpfd); + return (ARCHIVE_WARN); + } + +#if defined(HAVE_SYS_XATTR_H) + ret = copy_xattrs(a, tmpfd, dffd); + if (ret == ARCHIVE_OK) +#endif + ret = copy_acls(a, tmpfd, dffd); + close(tmpfd); + close(dffd); + } else { + if (copyfile(metadata, datafork, 0, + COPYFILE_UNPACK | COPYFILE_NOFOLLOW + | COPYFILE_ACL | COPYFILE_XATTR) < 0) { + archive_set_error(&a->archive, errno, + "Failed to restore metadata"); + ret = ARCHIVE_WARN; + } + } + return (ret); +} + +static int +set_mac_metadata(struct archive_write_disk *a, const char *pathname, + const void *metadata, size_t metadata_size) +{ + struct archive_string tmp; + ssize_t written; + int fd; + int ret = ARCHIVE_OK; + + /* This would be simpler if copyfile() could just accept the + * metadata as a block of memory; then we could sidestep this + * silly dance of writing the data to disk just so that + * copyfile() can read it back in again. */ + archive_string_init(&tmp); + archive_strcpy(&tmp, pathname); + archive_strcat(&tmp, ".XXXXXX"); + fd = mkstemp(tmp.s); + + if (fd < 0) { + archive_set_error(&a->archive, errno, + "Failed to restore metadata"); + archive_string_free(&tmp); + return (ARCHIVE_WARN); + } + written = write(fd, metadata, metadata_size); + close(fd); + if ((size_t)written != metadata_size) { + archive_set_error(&a->archive, errno, + "Failed to restore metadata"); + ret = ARCHIVE_WARN; + } else { + int compressed; + +#if defined(UF_COMPRESSED) + if ((a->todo & TODO_HFS_COMPRESSION) != 0 && + (ret = lazy_stat(a)) == ARCHIVE_OK) + compressed = a->st.st_flags & UF_COMPRESSED; + else +#endif + compressed = 0; + ret = copy_metadata(a, tmp.s, pathname, compressed); + } + unlink(tmp.s); + archive_string_free(&tmp); + return (ret); +} + +static int +fixup_appledouble(struct archive_write_disk *a, const char *pathname) +{ + char buff[8]; + struct stat st; + const char *p; + struct archive_string datafork; + int fd = -1, ret = ARCHIVE_OK; + + archive_string_init(&datafork); + /* Check if the current file name is a type of the resource + * fork file. */ + p = strrchr(pathname, '/'); + if (p == NULL) + p = pathname; + else + p++; + if (p[0] != '.' || p[1] != '_') + goto skip_appledouble; + + /* + * Check if the data fork file exists. + * + * TODO: Check if this write disk object has handled it. + */ + archive_strncpy(&datafork, pathname, p - pathname); + archive_strcat(&datafork, p + 2); + if (lstat(datafork.s, &st) == -1 || + (st.st_mode & AE_IFMT) != AE_IFREG) + goto skip_appledouble; + + /* + * Check if the file is in the AppleDouble form. + */ + fd = open(pathname, O_RDONLY | O_BINARY | O_CLOEXEC); + __archive_ensure_cloexec_flag(fd); + if (fd == -1) { + archive_set_error(&a->archive, errno, + "Failed to open a restoring file"); + ret = ARCHIVE_WARN; + goto skip_appledouble; + } + if (read(fd, buff, 8) == -1) { + archive_set_error(&a->archive, errno, + "Failed to read a restoring file"); + close(fd); + ret = ARCHIVE_WARN; + goto skip_appledouble; + } + close(fd); + /* Check AppleDouble Magic Code. */ + if (archive_be32dec(buff) != 0x00051607) + goto skip_appledouble; + /* Check AppleDouble Version. */ + if (archive_be32dec(buff+4) != 0x00020000) + goto skip_appledouble; + + ret = copy_metadata(a, pathname, datafork.s, +#if defined(UF_COMPRESSED) + st.st_flags & UF_COMPRESSED); +#else + 0); +#endif + if (ret == ARCHIVE_OK) { + unlink(pathname); + ret = ARCHIVE_EOF; + } +skip_appledouble: + archive_string_free(&datafork); + return (ret); +} +#endif + +#if ARCHIVE_XATTR_LINUX || ARCHIVE_XATTR_DARWIN || ARCHIVE_XATTR_AIX +/* + * Restore extended attributes - Linux, Darwin and AIX implementations: + * AIX' ea interface is syntaxwise identical to the Linux xattr interface. + */ +static int +set_xattrs(struct archive_write_disk *a) +{ + struct archive_entry *entry = a->entry; + struct archive_string errlist; + int ret = ARCHIVE_OK; + int i = archive_entry_xattr_reset(entry); + short fail = 0; + + archive_string_init(&errlist); + + while (i--) { + const char *name; + const void *value; + size_t size; + int e; + + archive_entry_xattr_next(entry, &name, &value, &size); + + if (name == NULL) + continue; +#if ARCHIVE_XATTR_LINUX + /* Linux: quietly skip POSIX.1e ACL extended attributes */ + if (strncmp(name, "system.", 7) == 0 && + (strcmp(name + 7, "posix_acl_access") == 0 || + strcmp(name + 7, "posix_acl_default") == 0)) + continue; + if (strncmp(name, "trusted.SGI_", 12) == 0 && + (strcmp(name + 12, "ACL_DEFAULT") == 0 || + strcmp(name + 12, "ACL_FILE") == 0)) + continue; + + /* Linux: xfsroot namespace is obsolete and unsupported */ + if (strncmp(name, "xfsroot.", 8) == 0) { + fail = 1; + archive_strcat(&errlist, name); + archive_strappend_char(&errlist, ' '); + continue; + } +#endif + + if (a->fd >= 0) { +#if ARCHIVE_XATTR_LINUX + e = fsetxattr(a->fd, name, value, size, 0); +#elif ARCHIVE_XATTR_DARWIN + e = fsetxattr(a->fd, name, value, size, 0, 0); +#elif ARCHIVE_XATTR_AIX + e = fsetea(a->fd, name, value, size, 0); +#endif + } else { +#if ARCHIVE_XATTR_LINUX + e = lsetxattr(archive_entry_pathname(entry), + name, value, size, 0); +#elif ARCHIVE_XATTR_DARWIN + e = setxattr(archive_entry_pathname(entry), + name, value, size, 0, XATTR_NOFOLLOW); +#elif ARCHIVE_XATTR_AIX + e = lsetea(archive_entry_pathname(entry), + name, value, size, 0); +#endif + } + if (e == -1) { + ret = ARCHIVE_WARN; + archive_strcat(&errlist, name); + archive_strappend_char(&errlist, ' '); + if (errno != ENOTSUP && errno != ENOSYS) + fail = 1; + } + } + + if (ret == ARCHIVE_WARN) { + if (fail && errlist.length > 0) { + errlist.length--; + errlist.s[errlist.length] = '\0'; + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Cannot restore extended attributes: %s", + errlist.s); + } else + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Cannot restore extended " + "attributes on this file system."); + } + + archive_string_free(&errlist); + return (ret); +} +#elif ARCHIVE_XATTR_FREEBSD +/* + * Restore extended attributes - FreeBSD implementation + */ +static int +set_xattrs(struct archive_write_disk *a) +{ + struct archive_entry *entry = a->entry; + struct archive_string errlist; + int ret = ARCHIVE_OK; + int i = archive_entry_xattr_reset(entry); + short fail = 0; + + archive_string_init(&errlist); + + while (i--) { + const char *name; + const void *value; + size_t size; + archive_entry_xattr_next(entry, &name, &value, &size); + if (name != NULL) { + int e; + int namespace; + + if (strncmp(name, "user.", 5) == 0) { + /* "user." attributes go to user namespace */ + name += 5; + namespace = EXTATTR_NAMESPACE_USER; + } else { + /* Other namespaces are unsupported */ + archive_strcat(&errlist, name); + archive_strappend_char(&errlist, ' '); + fail = 1; + ret = ARCHIVE_WARN; + continue; + } + + if (a->fd >= 0) { + e = extattr_set_fd(a->fd, namespace, name, + value, size); + } else { + e = extattr_set_link( + archive_entry_pathname(entry), namespace, + name, value, size); + } + if (e != (int)size) { + archive_strcat(&errlist, name); + archive_strappend_char(&errlist, ' '); + ret = ARCHIVE_WARN; + if (errno != ENOTSUP && errno != ENOSYS) + fail = 1; + } + } + } + + if (ret == ARCHIVE_WARN) { + if (fail && errlist.length > 0) { + errlist.length--; + errlist.s[errlist.length] = '\0'; + + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Cannot restore extended attributes: %s", + errlist.s); + } else + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Cannot restore extended " + "attributes on this file system."); + } + + archive_string_free(&errlist); + return (ret); +} +#else +/* + * Restore extended attributes - stub implementation for unsupported systems + */ +static int +set_xattrs(struct archive_write_disk *a) +{ + static int warning_done = 0; + + /* If there aren't any extended attributes, then it's okay not + * to extract them, otherwise, issue a single warning. */ + if (archive_entry_xattr_count(a->entry) != 0 && !warning_done) { + warning_done = 1; + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Cannot restore extended attributes on this system"); + return (ARCHIVE_WARN); + } + /* Warning was already emitted; suppress further warnings. */ + return (ARCHIVE_OK); +} +#endif + +/* + * Test if file on disk is older than entry. + */ +static int +older(struct stat *st, struct archive_entry *entry) +{ + /* First, test the seconds and return if we have a definite answer. */ + /* Definitely older. */ + if (to_int64_time(st->st_mtime) < to_int64_time(archive_entry_mtime(entry))) + return (1); + /* Definitely younger. */ + if (to_int64_time(st->st_mtime) > to_int64_time(archive_entry_mtime(entry))) + return (0); + /* If this platform supports fractional seconds, try those. */ +#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC + /* Definitely older. */ + if (st->st_mtimespec.tv_nsec < archive_entry_mtime_nsec(entry)) + return (1); +#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC + /* Definitely older. */ + if (st->st_mtim.tv_nsec < archive_entry_mtime_nsec(entry)) + return (1); +#elif HAVE_STRUCT_STAT_ST_MTIME_N + /* older. */ + if (st->st_mtime_n < archive_entry_mtime_nsec(entry)) + return (1); +#elif HAVE_STRUCT_STAT_ST_UMTIME + /* older. */ + if (st->st_umtime * 1000 < archive_entry_mtime_nsec(entry)) + return (1); +#elif HAVE_STRUCT_STAT_ST_MTIME_USEC + /* older. */ + if (st->st_mtime_usec * 1000 < archive_entry_mtime_nsec(entry)) + return (1); +#else + /* This system doesn't have high-res timestamps. */ +#endif + /* Same age or newer, so not older. */ + return (0); +} + +#ifndef ARCHIVE_ACL_SUPPORT +int +archive_write_disk_set_acls(struct archive *a, int fd, const char *name, + struct archive_acl *abstract_acl, __LA_MODE_T mode) +{ + (void)a; /* UNUSED */ + (void)fd; /* UNUSED */ + (void)name; /* UNUSED */ + (void)abstract_acl; /* UNUSED */ + (void)mode; /* UNUSED */ + return (ARCHIVE_OK); +} +#endif + +#endif /* !_WIN32 || __CYGWIN__ */ + diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_disk_private.h b/dependencies/libarchive-3.4.2/libarchive/archive_write_disk_private.h new file mode 100644 index 0000000..557d7e2 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_disk_private.h @@ -0,0 +1,45 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: head/lib/libarchive/archive_write_disk_private.h 201086 2009-12-28 02:17:53Z kientzle $ + */ + +#ifndef ARCHIVE_WRITE_DISK_PRIVATE_H_INCLUDED +#define ARCHIVE_WRITE_DISK_PRIVATE_H_INCLUDED + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif + +#include "archive_platform_acl.h" +#include "archive_acl_private.h" +#include "archive_entry.h" + +struct archive_write_disk; + +int archive_write_disk_set_acls(struct archive *, int, const char *, + struct archive_acl *, __LA_MODE_T); + +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_disk_set_standard_lookup.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_disk_set_standard_lookup.c new file mode 100644 index 0000000..5fccdb9 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_disk_set_standard_lookup.c @@ -0,0 +1,263 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk_set_standard_lookup.c 201083 2009-12-28 02:09:57Z kientzle $"); + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_GRP_H +#include +#endif +#ifdef HAVE_PWD_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_read_private.h" +#include "archive_write_disk_private.h" + +struct bucket { + char *name; + int hash; + id_t id; +}; + +static const size_t cache_size = 127; +static unsigned int hash(const char *); +static int64_t lookup_gid(void *, const char *uname, int64_t); +static int64_t lookup_uid(void *, const char *uname, int64_t); +static void cleanup(void *); + +/* + * Installs functions that use getpwnam()/getgrnam()---along with + * a simple cache to accelerate such lookups---into the archive_write_disk + * object. This is in a separate file because getpwnam()/getgrnam() + * can pull in a LOT of library code (including NIS/LDAP functions, which + * pull in DNS resolvers, etc). This can easily top 500kB, which makes + * it inappropriate for some space-constrained applications. + * + * Applications that are size-sensitive may want to just use the + * real default functions (defined in archive_write_disk.c) that just + * use the uid/gid without the lookup. Or define your own custom functions + * if you prefer. + * + * TODO: Replace these hash tables with simpler move-to-front LRU + * lists with a bounded size (128 items?). The hash is a bit faster, + * but has a bad pathology in which it thrashes a single bucket. Even + * walking a list of 128 items is a lot faster than calling + * getpwnam()! + */ +int +archive_write_disk_set_standard_lookup(struct archive *a) +{ + struct bucket *ucache = calloc(cache_size, sizeof(struct bucket)); + struct bucket *gcache = calloc(cache_size, sizeof(struct bucket)); + if (ucache == NULL || gcache == NULL) { + free(ucache); + free(gcache); + return (ARCHIVE_FATAL); + } + archive_write_disk_set_group_lookup(a, gcache, lookup_gid, cleanup); + archive_write_disk_set_user_lookup(a, ucache, lookup_uid, cleanup); + return (ARCHIVE_OK); +} + +static int64_t +lookup_gid(void *private_data, const char *gname, int64_t gid) +{ + int h; + struct bucket *b; + struct bucket *gcache = (struct bucket *)private_data; + + /* If no gname, just use the gid provided. */ + if (gname == NULL || *gname == '\0') + return (gid); + + /* Try to find gname in the cache. */ + h = hash(gname); + b = &gcache[h % cache_size ]; + if (b->name != NULL && b->hash == h && strcmp(gname, b->name) == 0) + return ((gid_t)b->id); + + /* Free the cache slot for a new entry. */ + free(b->name); + b->name = strdup(gname); + /* Note: If strdup fails, that's okay; we just won't cache. */ + b->hash = h; +#if HAVE_GRP_H +# if HAVE_GETGRNAM_R + { + char _buffer[128]; + size_t bufsize = 128; + char *buffer = _buffer; + char *allocated = NULL; + struct group grent, *result; + int r; + + for (;;) { + result = &grent; /* Old getgrnam_r ignores last arg. */ + r = getgrnam_r(gname, &grent, buffer, bufsize, &result); + if (r == 0) + break; + if (r != ERANGE) + break; + bufsize *= 2; + free(allocated); + allocated = malloc(bufsize); + if (allocated == NULL) + break; + buffer = allocated; + } + if (result != NULL) + gid = result->gr_gid; + free(allocated); + } +# else /* HAVE_GETGRNAM_R */ + { + struct group *result; + + result = getgrnam(gname); + if (result != NULL) + gid = result->gr_gid; + } +# endif /* HAVE_GETGRNAM_R */ +#elif defined(_WIN32) && !defined(__CYGWIN__) + /* TODO: do a gname->gid lookup for Windows. */ +#else + #error No way to perform gid lookups on this platform +#endif + b->id = (gid_t)gid; + + return (gid); +} + +static int64_t +lookup_uid(void *private_data, const char *uname, int64_t uid) +{ + int h; + struct bucket *b; + struct bucket *ucache = (struct bucket *)private_data; + + /* If no uname, just use the uid provided. */ + if (uname == NULL || *uname == '\0') + return (uid); + + /* Try to find uname in the cache. */ + h = hash(uname); + b = &ucache[h % cache_size ]; + if (b->name != NULL && b->hash == h && strcmp(uname, b->name) == 0) + return ((uid_t)b->id); + + /* Free the cache slot for a new entry. */ + free(b->name); + b->name = strdup(uname); + /* Note: If strdup fails, that's okay; we just won't cache. */ + b->hash = h; +#if HAVE_PWD_H +# if HAVE_GETPWNAM_R + { + char _buffer[128]; + size_t bufsize = 128; + char *buffer = _buffer; + char *allocated = NULL; + struct passwd pwent, *result; + int r; + + for (;;) { + result = &pwent; /* Old getpwnam_r ignores last arg. */ + r = getpwnam_r(uname, &pwent, buffer, bufsize, &result); + if (r == 0) + break; + if (r != ERANGE) + break; + bufsize *= 2; + free(allocated); + allocated = malloc(bufsize); + if (allocated == NULL) + break; + buffer = allocated; + } + if (result != NULL) + uid = result->pw_uid; + free(allocated); + } +# else /* HAVE_GETPWNAM_R */ + { + struct passwd *result; + + result = getpwnam(uname); + if (result != NULL) + uid = result->pw_uid; + } +#endif /* HAVE_GETPWNAM_R */ +#elif defined(_WIN32) && !defined(__CYGWIN__) + /* TODO: do a uname->uid lookup for Windows. */ +#else + #error No way to look up uids on this platform +#endif + b->id = (uid_t)uid; + + return (uid); +} + +static void +cleanup(void *private) +{ + size_t i; + struct bucket *cache = (struct bucket *)private; + + for (i = 0; i < cache_size; i++) + free(cache[i].name); + free(cache); +} + + +static unsigned int +hash(const char *p) +{ + /* A 32-bit version of Peter Weinberger's (PJW) hash algorithm, + as used by ELF for hashing function names. */ + unsigned g, h = 0; + while (*p != '\0') { + h = (h << 4) + *p++; + if ((g = h & 0xF0000000) != 0) { + h ^= g >> 24; + h &= 0x0FFFFFFF; + } + } + return h; +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_disk_windows.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_disk_windows.c new file mode 100644 index 0000000..77e36c4 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_disk_windows.c @@ -0,0 +1,2825 @@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * Copyright (c) 2011-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#if defined(_WIN32) && !defined(__CYGWIN__) + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_UTIME_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#include + +/* TODO: Support Mac OS 'quarantine' feature. This is really just a + * standard tag to mark files that have been downloaded as "tainted". + * On Mac OS, we should mark the extracted files as tainted if the + * archive being read was tainted. Windows has a similar feature; we + * should investigate ways to support this generically. */ + +#include "archive.h" +#include "archive_acl_private.h" +#include "archive_string.h" +#include "archive_entry.h" +#include "archive_private.h" + +#ifndef O_BINARY +#define O_BINARY 0 +#endif +#ifndef IO_REPARSE_TAG_SYMLINK +/* Old SDKs do not provide IO_REPARSE_TAG_SYMLINK */ +#define IO_REPARSE_TAG_SYMLINK 0xA000000CL +#endif + +static BOOL SetFilePointerEx_perso(HANDLE hFile, + LARGE_INTEGER liDistanceToMove, + PLARGE_INTEGER lpNewFilePointer, + DWORD dwMoveMethod) +{ + LARGE_INTEGER li; + li.QuadPart = liDistanceToMove.QuadPart; + li.LowPart = SetFilePointer( + hFile, li.LowPart, &li.HighPart, dwMoveMethod); + if(lpNewFilePointer) { + lpNewFilePointer->QuadPart = li.QuadPart; + } + return li.LowPart != (DWORD)-1 || GetLastError() == NO_ERROR; +} + +struct fixup_entry { + struct fixup_entry *next; + struct archive_acl acl; + mode_t mode; + int64_t atime; + int64_t birthtime; + int64_t mtime; + int64_t ctime; + unsigned long atime_nanos; + unsigned long birthtime_nanos; + unsigned long mtime_nanos; + unsigned long ctime_nanos; + unsigned long fflags_set; + int fixup; /* bitmask of what needs fixing */ + wchar_t *name; +}; + +/* + * We use a bitmask to track which operations remain to be done for + * this file. In particular, this helps us avoid unnecessary + * operations when it's possible to take care of one step as a + * side-effect of another. For example, mkdir() can specify the mode + * for the newly-created object but symlink() cannot. This means we + * can skip chmod() if mkdir() succeeded, but we must explicitly + * chmod() if we're trying to create a directory that already exists + * (mkdir() failed) or if we're restoring a symlink. Similarly, we + * need to verify UID/GID before trying to restore SUID/SGID bits; + * that verification can occur explicitly through a stat() call or + * implicitly because of a successful chown() call. + */ +#define TODO_MODE_FORCE 0x40000000 +#define TODO_MODE_BASE 0x20000000 +#define TODO_SUID 0x10000000 +#define TODO_SUID_CHECK 0x08000000 +#define TODO_SGID 0x04000000 +#define TODO_SGID_CHECK 0x02000000 +#define TODO_MODE (TODO_MODE_BASE|TODO_SUID|TODO_SGID) +#define TODO_TIMES ARCHIVE_EXTRACT_TIME +#define TODO_OWNER ARCHIVE_EXTRACT_OWNER +#define TODO_FFLAGS ARCHIVE_EXTRACT_FFLAGS +#define TODO_ACLS ARCHIVE_EXTRACT_ACL +#define TODO_XATTR ARCHIVE_EXTRACT_XATTR +#define TODO_MAC_METADATA ARCHIVE_EXTRACT_MAC_METADATA + +struct archive_write_disk { + struct archive archive; + + mode_t user_umask; + struct fixup_entry *fixup_list; + struct fixup_entry *current_fixup; + int64_t user_uid; + int skip_file_set; + int64_t skip_file_dev; + int64_t skip_file_ino; + time_t start_time; + + int64_t (*lookup_gid)(void *private, const char *gname, int64_t gid); + void (*cleanup_gid)(void *private); + void *lookup_gid_data; + int64_t (*lookup_uid)(void *private, const char *uname, int64_t uid); + void (*cleanup_uid)(void *private); + void *lookup_uid_data; + + /* + * Full path of last file to satisfy symlink checks. + */ + struct archive_wstring path_safe; + + /* + * Cached stat data from disk for the current entry. + * If this is valid, pst points to st. Otherwise, + * pst is null. + */ + BY_HANDLE_FILE_INFORMATION st; + BY_HANDLE_FILE_INFORMATION *pst; + + /* Information about the object being restored right now. */ + struct archive_entry *entry; /* Entry being extracted. */ + wchar_t *name; /* Name of entry, possibly edited. */ + struct archive_wstring _name_data; /* backing store for 'name' */ + wchar_t *tmpname; /* Temporary name */ + struct archive_wstring _tmpname_data; /* backing store for 'tmpname' */ + /* Tasks remaining for this object. */ + int todo; + /* Tasks deferred until end-of-archive. */ + int deferred; + /* Options requested by the client. */ + int flags; + /* Handle for the file we're restoring. */ + HANDLE fh; + /* Current offset for writing data to the file. */ + int64_t offset; + /* Last offset actually written to disk. */ + int64_t fd_offset; + /* Total bytes actually written to files. */ + int64_t total_bytes_written; + /* Maximum size of file, -1 if unknown. */ + int64_t filesize; + /* Dir we were in before this restore; only for deep paths. */ + int restore_pwd; + /* Mode we should use for this entry; affected by _PERM and umask. */ + mode_t mode; + /* UID/GID to use in restoring this entry. */ + int64_t uid; + int64_t gid; +}; + +/* + * Default mode for dirs created automatically (will be modified by umask). + * Note that POSIX specifies 0777 for implicitly-created dirs, "modified + * by the process' file creation mask." + */ +#define DEFAULT_DIR_MODE 0777 +/* + * Dir modes are restored in two steps: During the extraction, the permissions + * in the archive are modified to match the following limits. During + * the post-extract fixup pass, the permissions from the archive are + * applied. + */ +#define MINIMUM_DIR_MODE 0700 +#define MAXIMUM_DIR_MODE 0775 + +static int disk_unlink(const wchar_t *); +static int disk_rmdir(const wchar_t *); +static int check_symlinks(struct archive_write_disk *); +static int create_filesystem_object(struct archive_write_disk *); +static struct fixup_entry *current_fixup(struct archive_write_disk *, + const wchar_t *pathname); +static int cleanup_pathname(struct archive_write_disk *); +static int create_dir(struct archive_write_disk *, wchar_t *); +static int create_parent_dir(struct archive_write_disk *, wchar_t *); +static int la_chmod(const wchar_t *, mode_t); +static int la_mktemp(struct archive_write_disk *); +static int older(BY_HANDLE_FILE_INFORMATION *, struct archive_entry *); +static int permissive_name_w(struct archive_write_disk *); +static int restore_entry(struct archive_write_disk *); +static int set_acls(struct archive_write_disk *, HANDLE h, + const wchar_t *, struct archive_acl *); +static int set_xattrs(struct archive_write_disk *); +static int clear_nochange_fflags(struct archive_write_disk *); +static int set_fflags(struct archive_write_disk *); +static int set_fflags_platform(const wchar_t *, unsigned long, + unsigned long); +static int set_ownership(struct archive_write_disk *); +static int set_mode(struct archive_write_disk *, int mode); +static int set_times(struct archive_write_disk *, HANDLE, int, + const wchar_t *, time_t, long, time_t, long, time_t, + long, time_t, long); +static int set_times_from_entry(struct archive_write_disk *); +static struct fixup_entry *sort_dir_list(struct fixup_entry *p); +static ssize_t write_data_block(struct archive_write_disk *, + const char *, size_t); + +static struct archive_vtable *archive_write_disk_vtable(void); + +static int _archive_write_disk_close(struct archive *); +static int _archive_write_disk_free(struct archive *); +static int _archive_write_disk_header(struct archive *, + struct archive_entry *); +static int64_t _archive_write_disk_filter_bytes(struct archive *, int); +static int _archive_write_disk_finish_entry(struct archive *); +static ssize_t _archive_write_disk_data(struct archive *, const void *, + size_t); +static ssize_t _archive_write_disk_data_block(struct archive *, const void *, + size_t, int64_t); + +#define bhfi_dev(bhfi) ((bhfi)->dwVolumeSerialNumber) +/* Treat FileIndex as i-node. We should remove a sequence number + * which is high-16-bits of nFileIndexHigh. */ +#define bhfi_ino(bhfi) \ + ((((int64_t)((bhfi)->nFileIndexHigh & 0x0000FFFFUL)) << 32) \ + + (bhfi)->nFileIndexLow) +#define bhfi_size(bhfi) \ + ((((int64_t)(bhfi)->nFileSizeHigh) << 32) + (bhfi)->nFileSizeLow) + +static int +file_information(struct archive_write_disk *a, wchar_t *path, + BY_HANDLE_FILE_INFORMATION *st, mode_t *mode, int sim_lstat) +{ + HANDLE h; + int r; + DWORD flag = FILE_FLAG_BACKUP_SEMANTICS; + WIN32_FIND_DATAW findData; + + if (sim_lstat || mode != NULL) { + h = FindFirstFileW(path, &findData); + if (h == INVALID_HANDLE_VALUE && + GetLastError() == ERROR_INVALID_NAME) { + wchar_t *full; + full = __la_win_permissive_name_w(path); + h = FindFirstFileW(full, &findData); + free(full); + } + if (h == INVALID_HANDLE_VALUE) { + la_dosmaperr(GetLastError()); + return (-1); + } + FindClose(h); + } + + /* Is symlink file ? */ + if (sim_lstat && + ((findData.dwFileAttributes + & FILE_ATTRIBUTE_REPARSE_POINT) && + (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK))) + flag |= FILE_FLAG_OPEN_REPARSE_POINT; + + h = CreateFileW(a->name, 0, 0, NULL, + OPEN_EXISTING, flag, NULL); + if (h == INVALID_HANDLE_VALUE && + GetLastError() == ERROR_INVALID_NAME) { + wchar_t *full; + full = __la_win_permissive_name_w(path); + h = CreateFileW(full, 0, 0, NULL, + OPEN_EXISTING, flag, NULL); + free(full); + } + if (h == INVALID_HANDLE_VALUE) { + la_dosmaperr(GetLastError()); + return (-1); + } + r = GetFileInformationByHandle(h, st); + CloseHandle(h); + if (r == 0) { + la_dosmaperr(GetLastError()); + return (-1); + } + + if (mode == NULL) + return (0); + + *mode = S_IRUSR | S_IRGRP | S_IROTH; + if ((st->dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0) + *mode |= S_IWUSR | S_IWGRP | S_IWOTH; + if ((st->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) && + findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK) + *mode |= S_IFLNK; + else if (st->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + *mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH; + else { + const wchar_t *p; + + *mode |= S_IFREG; + p = wcsrchr(path, L'.'); + if (p != NULL && wcslen(p) == 4) { + switch (p[1]) { + case L'B': case L'b': + if ((p[2] == L'A' || p[2] == L'a' ) && + (p[3] == L'T' || p[3] == L't' )) + *mode |= S_IXUSR | S_IXGRP | S_IXOTH; + break; + case L'C': case L'c': + if (((p[2] == L'M' || p[2] == L'm' ) && + (p[3] == L'D' || p[3] == L'd' ))) + *mode |= S_IXUSR | S_IXGRP | S_IXOTH; + break; + case L'E': case L'e': + if ((p[2] == L'X' || p[2] == L'x' ) && + (p[3] == L'E' || p[3] == L'e' )) + *mode |= S_IXUSR | S_IXGRP | S_IXOTH; + break; + default: + break; + } + } + } + return (0); +} + +/* + * Note: The path, for example, "aa/a/../b../c" will be converted to "aa/c" + * by GetFullPathNameW() W32 API, which __la_win_permissive_name_w uses. + * It means we cannot handle multiple dirs in one archive_entry. + * So we have to make the full-pathname in another way, which does not + * break "../" path string. + */ +static int +permissive_name_w(struct archive_write_disk *a) +{ + wchar_t *wn, *wnp; + wchar_t *ws, *wsp; + DWORD l; + + wnp = a->name; + if (wnp[0] == L'\\' && wnp[1] == L'\\' && + wnp[2] == L'?' && wnp[3] == L'\\') + /* We have already a permissive name. */ + return (0); + + if (wnp[0] == L'\\' && wnp[1] == L'\\' && + wnp[2] == L'.' && wnp[3] == L'\\') { + /* This is a device name */ + if (((wnp[4] >= L'a' && wnp[4] <= L'z') || + (wnp[4] >= L'A' && wnp[4] <= L'Z')) && + wnp[5] == L':' && wnp[6] == L'\\') { + wnp[2] = L'?';/* Not device name. */ + return (0); + } + } + + /* + * A full-pathname starting with a drive name like "C:\abc". + */ + if (((wnp[0] >= L'a' && wnp[0] <= L'z') || + (wnp[0] >= L'A' && wnp[0] <= L'Z')) && + wnp[1] == L':' && wnp[2] == L'\\') { + wn = _wcsdup(wnp); + if (wn == NULL) + return (-1); + archive_wstring_ensure(&(a->_name_data), 4 + wcslen(wn) + 1); + a->name = a->_name_data.s; + /* Prepend "\\?\" */ + archive_wstrncpy(&(a->_name_data), L"\\\\?\\", 4); + archive_wstrcat(&(a->_name_data), wn); + free(wn); + return (0); + } + + /* + * A full-pathname pointing to a network drive + * like "\\\\file". + */ + if (wnp[0] == L'\\' && wnp[1] == L'\\' && wnp[2] != L'\\') { + const wchar_t *p = &wnp[2]; + + /* Skip server-name letters. */ + while (*p != L'\\' && *p != L'\0') + ++p; + if (*p == L'\\') { + const wchar_t *rp = ++p; + /* Skip share-name letters. */ + while (*p != L'\\' && *p != L'\0') + ++p; + if (*p == L'\\' && p != rp) { + /* Now, match patterns such as + * "\\server-name\share-name\" */ + wn = _wcsdup(wnp); + if (wn == NULL) + return (-1); + archive_wstring_ensure(&(a->_name_data), + 8 + wcslen(wn) + 1); + a->name = a->_name_data.s; + /* Prepend "\\?\UNC\" */ + archive_wstrncpy(&(a->_name_data), + L"\\\\?\\UNC\\", 8); + archive_wstrcat(&(a->_name_data), wn+2); + free(wn); + return (0); + } + } + return (0); + } + + /* + * Get current working directory. + */ + l = GetCurrentDirectoryW(0, NULL); + if (l == 0) + return (-1); + ws = malloc(l * sizeof(wchar_t)); + l = GetCurrentDirectoryW(l, ws); + if (l == 0) { + free(ws); + return (-1); + } + wsp = ws; + + /* + * A full-pathname starting without a drive name like "\abc". + */ + if (wnp[0] == L'\\') { + wn = _wcsdup(wnp); + if (wn == NULL) + return (-1); + archive_wstring_ensure(&(a->_name_data), + 4 + 2 + wcslen(wn) + 1); + a->name = a->_name_data.s; + /* Prepend "\\?\" and drive name. */ + archive_wstrncpy(&(a->_name_data), L"\\\\?\\", 4); + archive_wstrncat(&(a->_name_data), wsp, 2); + archive_wstrcat(&(a->_name_data), wn); + free(wsp); + free(wn); + return (0); + } + + wn = _wcsdup(wnp); + if (wn == NULL) + return (-1); + archive_wstring_ensure(&(a->_name_data), 4 + l + 1 + wcslen(wn) + 1); + a->name = a->_name_data.s; + /* Prepend "\\?\" and drive name if not already added. */ + if (l > 3 && wsp[0] == L'\\' && wsp[1] == L'\\' && + wsp[2] == L'?' && wsp[3] == L'\\') + { + archive_wstrncpy(&(a->_name_data), wsp, l); + } + else if (l > 2 && wsp[0] == L'\\' && wsp[1] == L'\\' && wsp[2] != L'\\') + { + archive_wstrncpy(&(a->_name_data), L"\\\\?\\UNC\\", 8); + archive_wstrncat(&(a->_name_data), wsp+2, l-2); + } + else + { + archive_wstrncpy(&(a->_name_data), L"\\\\?\\", 4); + archive_wstrncat(&(a->_name_data), wsp, l); + } + archive_wstrncat(&(a->_name_data), L"\\", 1); + archive_wstrcat(&(a->_name_data), wn); + a->name = a->_name_data.s; + free(wsp); + free(wn); + return (0); +} + +static int +la_chmod(const wchar_t *path, mode_t mode) +{ + DWORD attr; + BOOL r; + wchar_t *fullname; + int ret = 0; + + fullname = NULL; + attr = GetFileAttributesW(path); + if (attr == (DWORD)-1 && + GetLastError() == ERROR_INVALID_NAME) { + fullname = __la_win_permissive_name_w(path); + attr = GetFileAttributesW(fullname); + } + if (attr == (DWORD)-1) { + la_dosmaperr(GetLastError()); + ret = -1; + goto exit_chmode; + } + if (mode & _S_IWRITE) + attr &= ~FILE_ATTRIBUTE_READONLY; + else + attr |= FILE_ATTRIBUTE_READONLY; + if (fullname != NULL) + r = SetFileAttributesW(fullname, attr); + else + r = SetFileAttributesW(path, attr); + if (r == 0) { + la_dosmaperr(GetLastError()); + ret = -1; + } +exit_chmode: + free(fullname); + return (ret); +} + +static int +la_mktemp(struct archive_write_disk *a) +{ + int fd; + mode_t mode; + + archive_wstring_empty(&(a->_tmpname_data)); + archive_wstrcpy(&(a->_tmpname_data), a->name); + archive_wstrcat(&(a->_tmpname_data), L".XXXXXX"); + a->tmpname = a->_tmpname_data.s; + + fd = __archive_mkstemp(a->tmpname); + + mode = a->mode & 0777 & ~a->user_umask; + if (la_chmod(a->tmpname, mode) == -1) { + la_dosmaperr(GetLastError()); + _close(fd); + return -1; + } + return (fd); +} + +static void * +la_GetFunctionKernel32(const char *name) +{ + static HINSTANCE lib; + static int set; + if (!set) { + set = 1; + lib = LoadLibrary(TEXT("kernel32.dll")); + } + if (lib == NULL) { + fprintf(stderr, "Can't load kernel32.dll?!\n"); + exit(1); + } + return (void *)GetProcAddress(lib, name); +} + +static int +la_CreateHardLinkW(wchar_t *linkname, wchar_t *target) +{ + static BOOLEAN (WINAPI *f)(LPWSTR, LPWSTR, LPSECURITY_ATTRIBUTES); + static int set; + BOOL ret; + + if (!set) { + set = 1; + f = la_GetFunctionKernel32("CreateHardLinkW"); + } + if (!f) { + errno = ENOTSUP; + return (0); + } + ret = (*f)(linkname, target, NULL); + if (!ret) { + /* Under windows 2000, it is necessary to remove + * the "\\?\" prefix. */ +#define IS_UNC(name) ((name[0] == L'U' || name[0] == L'u') && \ + (name[1] == L'N' || name[1] == L'n') && \ + (name[2] == L'C' || name[2] == L'c') && \ + name[3] == L'\\') + if (!wcsncmp(linkname,L"\\\\?\\", 4)) { + linkname += 4; + if (IS_UNC(linkname)) + linkname += 4; + } + if (!wcsncmp(target,L"\\\\?\\", 4)) { + target += 4; + if (IS_UNC(target)) + target += 4; + } +#undef IS_UNC + ret = (*f)(linkname, target, NULL); + } + return (ret); +} + +/* + * Create file or directory symolic link + * + * If linktype is AE_SYMLINK_TYPE_UNDEFINED (or unknown), guess linktype from + * the link target + */ +static int +la_CreateSymbolicLinkW(const wchar_t *linkname, const wchar_t *target, + int linktype) { + static BOOLEAN (WINAPI *f)(LPCWSTR, LPCWSTR, DWORD); + static int set; + wchar_t *ttarget, *p; + int len; + DWORD attrs = 0; + DWORD flags = 0; + DWORD newflags = 0; + BOOL ret = 0; + + if (!set) { + set = 1; + f = la_GetFunctionKernel32("CreateSymbolicLinkW"); + } + if (!f) + return (0); + + len = wcslen(target); + if (len == 0) { + errno = EINVAL; + return(0); + } + /* + * When writing path targets, we need to translate slashes + * to backslashes + */ + ttarget = malloc((len + 1) * sizeof(wchar_t)); + if (ttarget == NULL) + return(0); + + p = ttarget; + + while(*target != L'\0') { + if (*target == L'/') + *p = L'\\'; + else + *p = *target; + target++; + p++; + } + *p = L'\0'; + + /* + * In case of undefined symlink type we guess it from the target. + * If the target equals ".", "..", ends with a backslash or a + * backslash followed by "." or ".." we assume it is a directory + * symlink. In all other cases we assume a file symlink. + */ + if (linktype != AE_SYMLINK_TYPE_FILE && ( + linktype == AE_SYMLINK_TYPE_DIRECTORY || + *(p - 1) == L'\\' || (*(p - 1) == L'.' && ( + len == 1 || *(p - 2) == L'\\' || ( *(p - 2) == L'.' && ( + len == 2 || *(p - 3) == L'\\')))))) { +#if defined(SYMBOLIC_LINK_FLAG_DIRECTORY) + flags |= SYMBOLIC_LINK_FLAG_DIRECTORY; +#else + flags |= 0x1; +#endif + } + +#if defined(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) + newflags = flags | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE; +#else + newflags = flags | 0x2; +#endif + + /* + * Windows won't overwrite existing links + */ + attrs = GetFileAttributesW(linkname); + if (attrs != INVALID_FILE_ATTRIBUTES) { + if (attrs & FILE_ATTRIBUTE_DIRECTORY) + disk_rmdir(linkname); + else + disk_unlink(linkname); + } + + ret = (*f)(linkname, ttarget, newflags); + /* + * Prior to Windows 10 calling CreateSymbolicLinkW() will fail + * if SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE is set + */ + if (!ret) { + ret = (*f)(linkname, ttarget, flags); + } + free(ttarget); + return (ret); +} + +static int +la_ftruncate(HANDLE handle, int64_t length) +{ + LARGE_INTEGER distance; + + if (GetFileType(handle) != FILE_TYPE_DISK) { + errno = EBADF; + return (-1); + } + distance.QuadPart = length; + if (!SetFilePointerEx_perso(handle, distance, NULL, FILE_BEGIN)) { + la_dosmaperr(GetLastError()); + return (-1); + } + if (!SetEndOfFile(handle)) { + la_dosmaperr(GetLastError()); + return (-1); + } + return (0); +} + +static int +lazy_stat(struct archive_write_disk *a) +{ + if (a->pst != NULL) { + /* Already have stat() data available. */ + return (ARCHIVE_OK); + } + if (a->fh != INVALID_HANDLE_VALUE && + GetFileInformationByHandle(a->fh, &a->st) == 0) { + a->pst = &a->st; + return (ARCHIVE_OK); + } + + /* + * XXX At this point, symlinks should not be hit, otherwise + * XXX a race occurred. Do we want to check explicitly for that? + */ + if (file_information(a, a->name, &a->st, NULL, 1) == 0) { + a->pst = &a->st; + return (ARCHIVE_OK); + } + archive_set_error(&a->archive, errno, "Couldn't stat file"); + return (ARCHIVE_WARN); +} + +static struct archive_vtable * +archive_write_disk_vtable(void) +{ + static struct archive_vtable av; + static int inited = 0; + + if (!inited) { + av.archive_close = _archive_write_disk_close; + av.archive_filter_bytes = _archive_write_disk_filter_bytes; + av.archive_free = _archive_write_disk_free; + av.archive_write_header = _archive_write_disk_header; + av.archive_write_finish_entry + = _archive_write_disk_finish_entry; + av.archive_write_data = _archive_write_disk_data; + av.archive_write_data_block = _archive_write_disk_data_block; + inited = 1; + } + return (&av); +} + +static int64_t +_archive_write_disk_filter_bytes(struct archive *_a, int n) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + (void)n; /* UNUSED */ + if (n == -1 || n == 0) + return (a->total_bytes_written); + return (-1); +} + + +int +archive_write_disk_set_options(struct archive *_a, int flags) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + + a->flags = flags; + return (ARCHIVE_OK); +} + + +/* + * Extract this entry to disk. + * + * TODO: Validate hardlinks. According to the standards, we're + * supposed to check each extracted hardlink and squawk if it refers + * to a file that we didn't restore. I'm not entirely convinced this + * is a good idea, but more importantly: Is there any way to validate + * hardlinks without keeping a complete list of filenames from the + * entire archive?? Ugh. + * + */ +static int +_archive_write_disk_header(struct archive *_a, struct archive_entry *entry) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + struct fixup_entry *fe; + int ret, r; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_write_disk_header"); + archive_clear_error(&a->archive); + if (a->archive.state & ARCHIVE_STATE_DATA) { + r = _archive_write_disk_finish_entry(&a->archive); + if (r == ARCHIVE_FATAL) + return (r); + } + + /* Set up for this particular entry. */ + a->pst = NULL; + a->current_fixup = NULL; + a->deferred = 0; + archive_entry_free(a->entry); + a->entry = NULL; + a->entry = archive_entry_clone(entry); + a->fh = INVALID_HANDLE_VALUE; + a->fd_offset = 0; + a->offset = 0; + a->restore_pwd = -1; + a->uid = a->user_uid; + a->mode = archive_entry_mode(a->entry); + if (archive_entry_size_is_set(a->entry)) + a->filesize = archive_entry_size(a->entry); + else + a->filesize = -1; + archive_wstrcpy(&(a->_name_data), archive_entry_pathname_w(a->entry)); + a->name = a->_name_data.s; + archive_clear_error(&a->archive); + + /* + * Clean up the requested path. This is necessary for correct + * dir restores; the dir restore logic otherwise gets messed + * up by nonsense like "dir/.". + */ + ret = cleanup_pathname(a); + if (ret != ARCHIVE_OK) + return (ret); + + /* + * Generate a full-pathname and use it from here. + */ + if (permissive_name_w(a) < 0) { + errno = EINVAL; + return (ARCHIVE_FAILED); + } + + /* + * Query the umask so we get predictable mode settings. + * This gets done on every call to _write_header in case the + * user edits their umask during the extraction for some + * reason. + */ + umask(a->user_umask = umask(0)); + + /* Figure out what we need to do for this entry. */ + a->todo = TODO_MODE_BASE; + if (a->flags & ARCHIVE_EXTRACT_PERM) { + a->todo |= TODO_MODE_FORCE; /* Be pushy about permissions. */ + /* + * SGID requires an extra "check" step because we + * cannot easily predict the GID that the system will + * assign. (Different systems assign GIDs to files + * based on a variety of criteria, including process + * credentials and the gid of the enclosing + * directory.) We can only restore the SGID bit if + * the file has the right GID, and we only know the + * GID if we either set it (see set_ownership) or if + * we've actually called stat() on the file after it + * was restored. Since there are several places at + * which we might verify the GID, we need a TODO bit + * to keep track. + */ + if (a->mode & S_ISGID) + a->todo |= TODO_SGID | TODO_SGID_CHECK; + /* + * Verifying the SUID is simpler, but can still be + * done in multiple ways, hence the separate "check" bit. + */ + if (a->mode & S_ISUID) + a->todo |= TODO_SUID | TODO_SUID_CHECK; + } else { + /* + * User didn't request full permissions, so don't + * restore SUID, SGID bits and obey umask. + */ + a->mode &= ~S_ISUID; + a->mode &= ~S_ISGID; + a->mode &= ~S_ISVTX; + a->mode &= ~a->user_umask; + } +#if 0 + if (a->flags & ARCHIVE_EXTRACT_OWNER) + a->todo |= TODO_OWNER; +#endif + if (a->flags & ARCHIVE_EXTRACT_TIME) + a->todo |= TODO_TIMES; + if (a->flags & ARCHIVE_EXTRACT_ACL) { + if (archive_entry_filetype(a->entry) == AE_IFDIR) + a->deferred |= TODO_ACLS; + else + a->todo |= TODO_ACLS; + } + if (a->flags & ARCHIVE_EXTRACT_XATTR) + a->todo |= TODO_XATTR; + if (a->flags & ARCHIVE_EXTRACT_FFLAGS) + a->todo |= TODO_FFLAGS; + if (a->flags & ARCHIVE_EXTRACT_SECURE_SYMLINKS) { + ret = check_symlinks(a); + if (ret != ARCHIVE_OK) + return (ret); + } + + ret = restore_entry(a); + + /* + * TODO: There are rumours that some extended attributes must + * be restored before file data is written. If this is true, + * then we either need to write all extended attributes both + * before and after restoring the data, or find some rule for + * determining which must go first and which last. Due to the + * many ways people are using xattrs, this may prove to be an + * intractable problem. + */ + + /* + * Fixup uses the unedited pathname from archive_entry_pathname(), + * because it is relative to the base dir and the edited path + * might be relative to some intermediate dir as a result of the + * deep restore logic. + */ + if (a->deferred & TODO_MODE) { + fe = current_fixup(a, archive_entry_pathname_w(entry)); + fe->fixup |= TODO_MODE_BASE; + fe->mode = a->mode; + } + + if ((a->deferred & TODO_TIMES) + && (archive_entry_mtime_is_set(entry) + || archive_entry_atime_is_set(entry))) { + fe = current_fixup(a, archive_entry_pathname_w(entry)); + fe->mode = a->mode; + fe->fixup |= TODO_TIMES; + if (archive_entry_atime_is_set(entry)) { + fe->atime = archive_entry_atime(entry); + fe->atime_nanos = archive_entry_atime_nsec(entry); + } else { + /* If atime is unset, use start time. */ + fe->atime = a->start_time; + fe->atime_nanos = 0; + } + if (archive_entry_mtime_is_set(entry)) { + fe->mtime = archive_entry_mtime(entry); + fe->mtime_nanos = archive_entry_mtime_nsec(entry); + } else { + /* If mtime is unset, use start time. */ + fe->mtime = a->start_time; + fe->mtime_nanos = 0; + } + if (archive_entry_birthtime_is_set(entry)) { + fe->birthtime = archive_entry_birthtime(entry); + fe->birthtime_nanos = archive_entry_birthtime_nsec(entry); + } else { + /* If birthtime is unset, use mtime. */ + fe->birthtime = fe->mtime; + fe->birthtime_nanos = fe->mtime_nanos; + } + } + + if (a->deferred & TODO_ACLS) { + fe = current_fixup(a, archive_entry_pathname_w(entry)); + archive_acl_copy(&fe->acl, archive_entry_acl(entry)); + } + + if (a->deferred & TODO_FFLAGS) { + unsigned long set, clear; + + fe = current_fixup(a, archive_entry_pathname_w(entry)); + archive_entry_fflags(entry, &set, &clear); + fe->fflags_set = set; + } + + /* + * On Windows, A creating sparse file requires a special mark. + */ + if (a->fh != INVALID_HANDLE_VALUE && + archive_entry_sparse_count(entry) > 0) { + int64_t base = 0, offset, length; + int i, cnt = archive_entry_sparse_reset(entry); + int sparse = 0; + + for (i = 0; i < cnt; i++) { + archive_entry_sparse_next(entry, &offset, &length); + if (offset - base >= 4096) { + sparse = 1;/* we have a hole. */ + break; + } + base = offset + length; + } + if (sparse) { + DWORD dmy; + /* Mark this file as sparse. */ + DeviceIoControl(a->fh, FSCTL_SET_SPARSE, + NULL, 0, NULL, 0, &dmy, NULL); + } + } + + /* We've created the object and are ready to pour data into it. */ + if (ret >= ARCHIVE_WARN) + a->archive.state = ARCHIVE_STATE_DATA; + /* + * If it's not open, tell our client not to try writing. + * In particular, dirs, links, etc, don't get written to. + */ + if (a->fh == INVALID_HANDLE_VALUE) { + archive_entry_set_size(entry, 0); + a->filesize = 0; + } + + return (ret); +} + +int +archive_write_disk_set_skip_file(struct archive *_a, la_int64_t d, la_int64_t i) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_write_disk_set_skip_file"); + a->skip_file_set = 1; + a->skip_file_dev = d; + a->skip_file_ino = i; + return (ARCHIVE_OK); +} + +static ssize_t +write_data_block(struct archive_write_disk *a, const char *buff, size_t size) +{ + OVERLAPPED ol; + uint64_t start_size = size; + DWORD bytes_written = 0; + ssize_t block_size = 0, bytes_to_write; + + if (size == 0) + return (ARCHIVE_OK); + + if (a->filesize == 0 || a->fh == INVALID_HANDLE_VALUE) { + archive_set_error(&a->archive, 0, + "Attempt to write to an empty file"); + return (ARCHIVE_WARN); + } + + if (a->flags & ARCHIVE_EXTRACT_SPARSE) { + /* XXX TODO XXX Is there a more appropriate choice here ? */ + /* This needn't match the filesystem allocation size. */ + block_size = 16*1024; + } + + /* If this write would run beyond the file size, truncate it. */ + if (a->filesize >= 0 && (int64_t)(a->offset + size) > a->filesize) + start_size = size = (size_t)(a->filesize - a->offset); + + /* Write the data. */ + while (size > 0) { + if (block_size == 0) { + bytes_to_write = size; + } else { + /* We're sparsifying the file. */ + const char *p, *end; + int64_t block_end; + + /* Skip leading zero bytes. */ + for (p = buff, end = buff + size; p < end; ++p) { + if (*p != '\0') + break; + } + a->offset += p - buff; + size -= p - buff; + buff = p; + if (size == 0) + break; + + /* Calculate next block boundary after offset. */ + block_end + = (a->offset / block_size + 1) * block_size; + + /* If the adjusted write would cross block boundary, + * truncate it to the block boundary. */ + bytes_to_write = size; + if (a->offset + bytes_to_write > block_end) + bytes_to_write = (DWORD)(block_end - a->offset); + } + memset(&ol, 0, sizeof(ol)); + ol.Offset = (DWORD)(a->offset & 0xFFFFFFFF); + ol.OffsetHigh = (DWORD)(a->offset >> 32); + if (!WriteFile(a->fh, buff, (uint32_t)bytes_to_write, + &bytes_written, &ol)) { + DWORD lasterr; + + lasterr = GetLastError(); + if (lasterr == ERROR_ACCESS_DENIED) + errno = EBADF; + else + la_dosmaperr(lasterr); + archive_set_error(&a->archive, errno, "Write failed"); + return (ARCHIVE_WARN); + } + buff += bytes_written; + size -= bytes_written; + a->total_bytes_written += bytes_written; + a->offset += bytes_written; + a->fd_offset = a->offset; + } + return ((ssize_t)(start_size - size)); +} + +static ssize_t +_archive_write_disk_data_block(struct archive *_a, + const void *buff, size_t size, int64_t offset) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + ssize_t r; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_DATA, "archive_write_data_block"); + + a->offset = offset; + r = write_data_block(a, buff, size); + if (r < ARCHIVE_OK) + return (r); + if ((size_t)r < size) { + archive_set_error(&a->archive, 0, + "Write request too large"); + return (ARCHIVE_WARN); + } +#if ARCHIVE_VERSION_NUMBER < 3999000 + return (ARCHIVE_OK); +#else + return (size); +#endif +} + +static ssize_t +_archive_write_disk_data(struct archive *_a, const void *buff, size_t size) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_DATA, "archive_write_data"); + + return (write_data_block(a, buff, size)); +} + +static int +_archive_write_disk_finish_entry(struct archive *_a) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + int ret = ARCHIVE_OK; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_write_finish_entry"); + if (a->archive.state & ARCHIVE_STATE_HEADER) + return (ARCHIVE_OK); + archive_clear_error(&a->archive); + + /* Pad or truncate file to the right size. */ + if (a->fh == INVALID_HANDLE_VALUE) { + /* There's no file. */ + } else if (a->filesize < 0) { + /* File size is unknown, so we can't set the size. */ + } else if (a->fd_offset == a->filesize) { + /* Last write ended at exactly the filesize; we're done. */ + /* Hopefully, this is the common case. */ + } else { + if (la_ftruncate(a->fh, a->filesize) == -1) { + archive_set_error(&a->archive, errno, + "File size could not be restored"); + return (ARCHIVE_FAILED); + } + } + + /* Restore metadata. */ + + /* + * Look up the "real" UID only if we're going to need it. + * TODO: the TODO_SGID condition can be dropped here, can't it? + */ + if (a->todo & (TODO_OWNER | TODO_SUID | TODO_SGID)) { + a->uid = archive_write_disk_uid(&a->archive, + archive_entry_uname(a->entry), + archive_entry_uid(a->entry)); + } + /* Look up the "real" GID only if we're going to need it. */ + /* TODO: the TODO_SUID condition can be dropped here, can't it? */ + if (a->todo & (TODO_OWNER | TODO_SGID | TODO_SUID)) { + a->gid = archive_write_disk_gid(&a->archive, + archive_entry_gname(a->entry), + archive_entry_gid(a->entry)); + } + + /* + * Restore ownership before set_mode tries to restore suid/sgid + * bits. If we set the owner, we know what it is and can skip + * a stat() call to examine the ownership of the file on disk. + */ + if (a->todo & TODO_OWNER) + ret = set_ownership(a); + + /* + * set_mode must precede ACLs on systems such as Solaris and + * FreeBSD where setting the mode implicitly clears extended ACLs + */ + if (a->todo & TODO_MODE) { + int r2 = set_mode(a, a->mode); + if (r2 < ret) ret = r2; + } + + /* + * Security-related extended attributes (such as + * security.capability on Linux) have to be restored last, + * since they're implicitly removed by other file changes. + */ + if (a->todo & TODO_XATTR) { + int r2 = set_xattrs(a); + if (r2 < ret) ret = r2; + } + + /* + * Some flags prevent file modification; they must be restored after + * file contents are written. + */ + if (a->todo & TODO_FFLAGS) { + int r2 = set_fflags(a); + if (r2 < ret) ret = r2; + } + + /* + * Time must follow most other metadata; + * otherwise atime will get changed. + */ + if (a->todo & TODO_TIMES) { + int r2 = set_times_from_entry(a); + if (r2 < ret) ret = r2; + } + + /* + * ACLs must be restored after timestamps because there are + * ACLs that prevent attribute changes (including time). + */ + if (a->todo & TODO_ACLS) { + int r2 = set_acls(a, a->fh, + archive_entry_pathname_w(a->entry), + archive_entry_acl(a->entry)); + if (r2 < ret) ret = r2; + } + + /* If there's an fd, we can close it now. */ + if (a->fh != INVALID_HANDLE_VALUE) { + CloseHandle(a->fh); + a->fh = INVALID_HANDLE_VALUE; + if (a->tmpname) { + /* Windows does not support atomic rename */ + disk_unlink(a->name); + if (_wrename(a->tmpname, a->name) != 0) { + archive_set_error(&a->archive, errno, + "rename failed"); + ret = ARCHIVE_FATAL; + } + a->tmpname = NULL; + } + } + /* If there's an entry, we can release it now. */ + archive_entry_free(a->entry); + a->entry = NULL; + a->archive.state = ARCHIVE_STATE_HEADER; + return (ret); +} + +int +archive_write_disk_set_group_lookup(struct archive *_a, + void *private_data, + la_int64_t (*lookup_gid)(void *private, const char *gname, la_int64_t gid), + void (*cleanup_gid)(void *private)) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_write_disk_set_group_lookup"); + + if (a->cleanup_gid != NULL && a->lookup_gid_data != NULL) + (a->cleanup_gid)(a->lookup_gid_data); + + a->lookup_gid = lookup_gid; + a->cleanup_gid = cleanup_gid; + a->lookup_gid_data = private_data; + return (ARCHIVE_OK); +} + +int +archive_write_disk_set_user_lookup(struct archive *_a, + void *private_data, + int64_t (*lookup_uid)(void *private, const char *uname, int64_t uid), + void (*cleanup_uid)(void *private)) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_write_disk_set_user_lookup"); + + if (a->cleanup_uid != NULL && a->lookup_uid_data != NULL) + (a->cleanup_uid)(a->lookup_uid_data); + + a->lookup_uid = lookup_uid; + a->cleanup_uid = cleanup_uid; + a->lookup_uid_data = private_data; + return (ARCHIVE_OK); +} + +int64_t +archive_write_disk_gid(struct archive *_a, const char *name, la_int64_t id) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_write_disk_gid"); + if (a->lookup_gid) + return (a->lookup_gid)(a->lookup_gid_data, name, id); + return (id); +} + +int64_t +archive_write_disk_uid(struct archive *_a, const char *name, la_int64_t id) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_write_disk_uid"); + if (a->lookup_uid) + return (a->lookup_uid)(a->lookup_uid_data, name, id); + return (id); +} + +/* + * Create a new archive_write_disk object and initialize it with global state. + */ +struct archive * +archive_write_disk_new(void) +{ + struct archive_write_disk *a; + + a = (struct archive_write_disk *)calloc(1, sizeof(*a)); + if (a == NULL) + return (NULL); + a->archive.magic = ARCHIVE_WRITE_DISK_MAGIC; + /* We're ready to write a header immediately. */ + a->archive.state = ARCHIVE_STATE_HEADER; + a->archive.vtable = archive_write_disk_vtable(); + a->start_time = time(NULL); + /* Query and restore the umask. */ + umask(a->user_umask = umask(0)); + if (archive_wstring_ensure(&a->path_safe, 512) == NULL) { + free(a); + return (NULL); + } + return (&a->archive); +} + +static int +disk_unlink(const wchar_t *path) +{ + wchar_t *fullname; + int r; + + r = _wunlink(path); + if (r != 0 && GetLastError() == ERROR_INVALID_NAME) { + fullname = __la_win_permissive_name_w(path); + r = _wunlink(fullname); + free(fullname); + } + return (r); +} + +static int +disk_rmdir(const wchar_t *path) +{ + wchar_t *fullname; + int r; + + r = _wrmdir(path); + if (r != 0 && GetLastError() == ERROR_INVALID_NAME) { + fullname = __la_win_permissive_name_w(path); + r = _wrmdir(fullname); + free(fullname); + } + return (r); +} + +/* + * The main restore function. + */ +static int +restore_entry(struct archive_write_disk *a) +{ + int ret = ARCHIVE_OK, en; + + if (a->flags & ARCHIVE_EXTRACT_UNLINK && !S_ISDIR(a->mode)) { + /* + * TODO: Fix this. Apparently, there are platforms + * that still allow root to hose the entire filesystem + * by unlinking a dir. The S_ISDIR() test above + * prevents us from using unlink() here if the new + * object is a dir, but that doesn't mean the old + * object isn't a dir. + */ + if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS) + (void)clear_nochange_fflags(a); + if (disk_unlink(a->name) == 0) { + /* We removed it, reset cached stat. */ + a->pst = NULL; + } else if (errno == ENOENT) { + /* File didn't exist, that's just as good. */ + } else if (disk_rmdir(a->name) == 0) { + /* It was a dir, but now it's gone. */ + a->pst = NULL; + } else { + /* We tried, but couldn't get rid of it. */ + archive_set_error(&a->archive, errno, + "Could not unlink"); + return(ARCHIVE_FAILED); + } + } + + /* Try creating it first; if this fails, we'll try to recover. */ + en = create_filesystem_object(a); + + if ((en == ENOTDIR || en == ENOENT) + && !(a->flags & ARCHIVE_EXTRACT_NO_AUTODIR)) { + wchar_t *full; + /* If the parent dir doesn't exist, try creating it. */ + create_parent_dir(a, a->name); + /* Now try to create the object again. */ + full = __la_win_permissive_name_w(a->name); + if (full == NULL) { + en = EINVAL; + } else { + /* Remove multiple directories such as "a/../b../c" */ + archive_wstrcpy(&(a->_name_data), full); + a->name = a->_name_data.s; + free(full); + en = create_filesystem_object(a); + } + } + + if ((en == ENOENT) && (archive_entry_hardlink(a->entry) != NULL)) { + archive_set_error(&a->archive, en, + "Hard-link target '%s' does not exist.", + archive_entry_hardlink(a->entry)); + return (ARCHIVE_FAILED); + } + + if ((en == EISDIR || en == EEXIST) + && (a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) { + /* If we're not overwriting, we're done. */ + if (S_ISDIR(a->mode)) { + /* Don't overwrite any settings on existing directories. */ + a->todo = 0; + } + archive_entry_unset_size(a->entry); + return (ARCHIVE_OK); + } + + /* + * Some platforms return EISDIR if you call + * open(O_WRONLY | O_EXCL | O_CREAT) on a directory, some + * return EEXIST. POSIX is ambiguous, requiring EISDIR + * for open(O_WRONLY) on a dir and EEXIST for open(O_EXCL | O_CREAT) + * on an existing item. + */ + if (en == EISDIR) { + /* A dir is in the way of a non-dir, rmdir it. */ + if (disk_rmdir(a->name) != 0) { + archive_set_error(&a->archive, errno, + "Can't remove already-existing dir"); + return (ARCHIVE_FAILED); + } + a->pst = NULL; + /* Try again. */ + en = create_filesystem_object(a); + } else if (en == EEXIST) { + mode_t st_mode; + mode_t lst_mode; + BY_HANDLE_FILE_INFORMATION lst; + /* + * We know something is in the way, but we don't know what; + * we need to find out before we go any further. + */ + int r = 0; + int dirlnk = 0; + + /* + * The SECURE_SYMLINK logic has already removed a + * symlink to a dir if the client wants that. So + * follow the symlink if we're creating a dir. + * If it's not a dir (or it's a broken symlink), + * then don't follow it. + * + * Windows distinguishes file and directory symlinks. + * A file symlink may erroneously point to a directory + * and a directory symlink to a file. Windows does not follow + * such symlinks. We always need both source and target + * information. + */ + r = file_information(a, a->name, &lst, &lst_mode, 1); + if (r != 0) { + archive_set_error(&a->archive, errno, + "Can't stat existing object"); + return (ARCHIVE_FAILED); + } else if (S_ISLNK(lst_mode)) { + if (lst.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + dirlnk = 1; + /* In case of a symlink we need target information */ + r = file_information(a, a->name, &a->st, &st_mode, 0); + if (r != 0) { + a->st = lst; + st_mode = lst_mode; + } + } else { + a->st = lst; + st_mode = lst_mode; + } + + /* + * NO_OVERWRITE_NEWER doesn't apply to directories. + */ + if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER) + && !S_ISDIR(st_mode)) { + if (!older(&(a->st), a->entry)) { + archive_entry_unset_size(a->entry); + return (ARCHIVE_OK); + } + } + + /* If it's our archive, we're done. */ + if (a->skip_file_set && + bhfi_dev(&a->st) == a->skip_file_dev && + bhfi_ino(&a->st) == a->skip_file_ino) { + archive_set_error(&a->archive, 0, + "Refusing to overwrite archive"); + return (ARCHIVE_FAILED); + } + + if (!S_ISDIR(st_mode)) { + if (a->flags & + ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS) { + (void)clear_nochange_fflags(a); + } + if ((a->flags & ARCHIVE_EXTRACT_SAFE_WRITES) && + S_ISREG(st_mode)) { + int fd = la_mktemp(a); + + if (fd == -1) + return (ARCHIVE_FAILED); + a->fh = (HANDLE)_get_osfhandle(fd); + if (a->fh == INVALID_HANDLE_VALUE) + return (ARCHIVE_FAILED); + + a->pst = NULL; + en = 0; + } else { + if (dirlnk) { + /* Edge case: dir symlink pointing + * to a file */ + if (disk_rmdir(a->name) != 0) { + archive_set_error(&a->archive, + errno, "Can't unlink " + "directory symlink"); + return (ARCHIVE_FAILED); + } + } else { + if (disk_unlink(a->name) != 0) { + /* A non-dir is in the way, + * unlink it. */ + archive_set_error(&a->archive, + errno, "Can't unlink " + "already-existing object"); + return (ARCHIVE_FAILED); + } + } + a->pst = NULL; + /* Try again. */ + en = create_filesystem_object(a); + } + } else if (!S_ISDIR(a->mode)) { + /* A dir is in the way of a non-dir, rmdir it. */ + if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS) + (void)clear_nochange_fflags(a); + if (disk_rmdir(a->name) != 0) { + archive_set_error(&a->archive, errno, + "Can't remove already-existing dir"); + return (ARCHIVE_FAILED); + } + /* Try again. */ + en = create_filesystem_object(a); + } else { + /* + * There's a dir in the way of a dir. Don't + * waste time with rmdir()/mkdir(), just fix + * up the permissions on the existing dir. + * Note that we don't change perms on existing + * dirs unless _EXTRACT_PERM is specified. + */ + if ((a->mode != st_mode) + && (a->todo & TODO_MODE_FORCE)) + a->deferred |= (a->todo & TODO_MODE); + /* Ownership doesn't need deferred fixup. */ + en = 0; /* Forget the EEXIST. */ + } + } + + if (en) { + /* Everything failed; give up here. */ + archive_set_error(&a->archive, en, "Can't create '%ls'", + a->name); + return (ARCHIVE_FAILED); + } + + a->pst = NULL; /* Cached stat data no longer valid. */ + return (ret); +} + +/* + * Returns 0 if creation succeeds, or else returns errno value from + * the failed system call. Note: This function should only ever perform + * a single system call. + */ +static int +create_filesystem_object(struct archive_write_disk *a) +{ + /* Create the entry. */ + const wchar_t *linkname; + wchar_t *fullname; + mode_t final_mode, mode; + int r; + DWORD attrs = 0; + + /* We identify hard/symlinks according to the link names. */ + /* Since link(2) and symlink(2) don't handle modes, we're done here. */ + linkname = archive_entry_hardlink_w(a->entry); + if (linkname != NULL) { + wchar_t *linkfull, *namefull; + + linkfull = __la_win_permissive_name_w(linkname); + namefull = __la_win_permissive_name_w(a->name); + if (linkfull == NULL || namefull == NULL) { + errno = EINVAL; + r = -1; + } else { + /* + * Unlinking and linking here is really not atomic, + * but doing it right, would require us to construct + * an mktemplink() function, and then use _wrename(). + */ + if (a->flags & ARCHIVE_EXTRACT_SAFE_WRITES) { + attrs = GetFileAttributesW(namefull); + if (attrs != INVALID_FILE_ATTRIBUTES) { + if (attrs & FILE_ATTRIBUTE_DIRECTORY) + disk_rmdir(namefull); + else + disk_unlink(namefull); + } + } + r = la_CreateHardLinkW(namefull, linkfull); + if (r == 0) { + la_dosmaperr(GetLastError()); + r = errno; + } else + r = 0; + } + /* + * New cpio and pax formats allow hardlink entries + * to carry data, so we may have to open the file + * for hardlink entries. + * + * If the hardlink was successfully created and + * the archive doesn't have carry data for it, + * consider it to be non-authoritative for meta data. + * This is consistent with GNU tar and BSD pax. + * If the hardlink does carry data, let the last + * archive entry decide ownership. + */ + if (r == 0 && a->filesize <= 0) { + a->todo = 0; + a->deferred = 0; + } else if (r == 0 && a->filesize > 0) { + a->fh = CreateFileW(namefull, GENERIC_WRITE, 0, NULL, + TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (a->fh == INVALID_HANDLE_VALUE) { + la_dosmaperr(GetLastError()); + r = errno; + } + } + free(linkfull); + free(namefull); + return (r); + } + linkname = archive_entry_symlink_w(a->entry); + if (linkname != NULL) { + /* + * Unlinking and linking here is really not atomic, + * but doing it right, would require us to construct + * an mktemplink() function, and then use _wrename(). + */ + attrs = GetFileAttributesW(a->name); + if (attrs != INVALID_FILE_ATTRIBUTES) { + if (attrs & FILE_ATTRIBUTE_DIRECTORY) + disk_rmdir(a->name); + else + disk_unlink(a->name); + } +#if HAVE_SYMLINK + return symlink(linkname, a->name) ? errno : 0; +#else + errno = 0; + r = la_CreateSymbolicLinkW((const wchar_t *)a->name, linkname, + archive_entry_symlink_type(a->entry)); + if (r == 0) { + if (errno == 0) + la_dosmaperr(GetLastError()); + r = errno; + } else + r = 0; + return (r); +#endif + } + + /* + * The remaining system calls all set permissions, so let's + * try to take advantage of that to avoid an extra chmod() + * call. (Recall that umask is set to zero right now!) + */ + + /* Mode we want for the final restored object (w/o file type bits). */ + final_mode = a->mode & 07777; + /* + * The mode that will actually be restored in this step. Note + * that SUID, SGID, etc, require additional work to ensure + * security, so we never restore them at this point. + */ + mode = final_mode & 0777 & ~a->user_umask; + + switch (a->mode & AE_IFMT) { + default: + /* POSIX requires that we fall through here. */ + /* FALLTHROUGH */ + case AE_IFREG: + a->tmpname = NULL; + fullname = a->name; + /* O_WRONLY | O_CREAT | O_EXCL */ + a->fh = CreateFileW(fullname, GENERIC_WRITE, 0, NULL, + CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); + if (a->fh == INVALID_HANDLE_VALUE && + GetLastError() == ERROR_INVALID_NAME && + fullname == a->name) { + fullname = __la_win_permissive_name_w(a->name); + a->fh = CreateFileW(fullname, GENERIC_WRITE, 0, NULL, + CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); + } + if (a->fh == INVALID_HANDLE_VALUE) { + if (GetLastError() == ERROR_ACCESS_DENIED) { + DWORD attr; + /* Simulate an errno of POSIX system. */ + attr = GetFileAttributesW(fullname); + if (attr == (DWORD)-1) + la_dosmaperr(GetLastError()); + else if (attr & FILE_ATTRIBUTE_DIRECTORY) + errno = EISDIR; + else + errno = EACCES; + } else + la_dosmaperr(GetLastError()); + r = 1; + } else + r = 0; + if (fullname != a->name) + free(fullname); + break; + case AE_IFCHR: + case AE_IFBLK: + /* TODO: Find a better way to warn about our inability + * to restore a block device node. */ + return (EINVAL); + case AE_IFDIR: + mode = (mode | MINIMUM_DIR_MODE) & MAXIMUM_DIR_MODE; + fullname = a->name; + r = CreateDirectoryW(fullname, NULL); + if (r == 0 && GetLastError() == ERROR_INVALID_NAME && + fullname == a->name) { + fullname = __la_win_permissive_name_w(a->name); + r = CreateDirectoryW(fullname, NULL); + } + if (r != 0) { + r = 0; + /* Defer setting dir times. */ + a->deferred |= (a->todo & TODO_TIMES); + a->todo &= ~TODO_TIMES; + /* Never use an immediate chmod(). */ + /* We can't avoid the chmod() entirely if EXTRACT_PERM + * because of SysV SGID inheritance. */ + if ((mode != final_mode) + || (a->flags & ARCHIVE_EXTRACT_PERM)) + a->deferred |= (a->todo & TODO_MODE); + a->todo &= ~TODO_MODE; + } else { + la_dosmaperr(GetLastError()); + r = -1; + } + if (fullname != a->name) + free(fullname); + break; + case AE_IFIFO: + /* TODO: Find a better way to warn about our inability + * to restore a fifo. */ + return (EINVAL); + } + + /* All the system calls above set errno on failure. */ + if (r) + return (errno); + + /* If we managed to set the final mode, we've avoided a chmod(). */ + if (mode == final_mode) + a->todo &= ~TODO_MODE; + return (0); +} + +/* + * Cleanup function for archive_extract. Mostly, this involves processing + * the fixup list, which is used to address a number of problems: + * * Dir permissions might prevent us from restoring a file in that + * dir, so we restore the dir with minimum 0700 permissions first, + * then correct the mode at the end. + * * Similarly, the act of restoring a file touches the directory + * and changes the timestamp on the dir, so we have to touch-up dir + * timestamps at the end as well. + * * Some file flags can interfere with the restore by, for example, + * preventing the creation of hardlinks to those files. + * * Mac OS extended metadata includes ACLs, so must be deferred on dirs. + * + * Note that tar/cpio do not require that archives be in a particular + * order; there is no way to know when the last file has been restored + * within a directory, so there's no way to optimize the memory usage + * here by fixing up the directory any earlier than the + * end-of-archive. + * + * XXX TODO: Directory ACLs should be restored here, for the same + * reason we set directory perms here. XXX + */ +static int +_archive_write_disk_close(struct archive *_a) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + struct fixup_entry *next, *p; + int ret; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_write_disk_close"); + ret = _archive_write_disk_finish_entry(&a->archive); + + /* Sort dir list so directories are fixed up in depth-first order. */ + p = sort_dir_list(a->fixup_list); + + while (p != NULL) { + a->pst = NULL; /* Mark stat cache as out-of-date. */ + if (p->fixup & TODO_TIMES) { + set_times(a, INVALID_HANDLE_VALUE, p->mode, p->name, + p->atime, p->atime_nanos, + p->birthtime, p->birthtime_nanos, + p->mtime, p->mtime_nanos, + p->ctime, p->ctime_nanos); + } + if (p->fixup & TODO_MODE_BASE) + la_chmod(p->name, p->mode); + if (p->fixup & TODO_ACLS) + set_acls(a, INVALID_HANDLE_VALUE, p->name, &p->acl); + if (p->fixup & TODO_FFLAGS) + set_fflags_platform(p->name, p->fflags_set, 0); + next = p->next; + archive_acl_clear(&p->acl); + free(p->name); + free(p); + p = next; + } + a->fixup_list = NULL; + return (ret); +} + +static int +_archive_write_disk_free(struct archive *_a) +{ + struct archive_write_disk *a; + int ret; + if (_a == NULL) + return (ARCHIVE_OK); + archive_check_magic(_a, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_write_disk_free"); + a = (struct archive_write_disk *)_a; + ret = _archive_write_disk_close(&a->archive); + archive_write_disk_set_group_lookup(&a->archive, NULL, NULL, NULL); + archive_write_disk_set_user_lookup(&a->archive, NULL, NULL, NULL); + archive_entry_free(a->entry); + archive_wstring_free(&a->_name_data); + archive_wstring_free(&a->_tmpname_data); + archive_string_free(&a->archive.error_string); + archive_wstring_free(&a->path_safe); + a->archive.magic = 0; + __archive_clean(&a->archive); + free(a); + return (ret); +} + +/* + * Simple O(n log n) merge sort to order the fixup list. In + * particular, we want to restore dir timestamps depth-first. + */ +static struct fixup_entry * +sort_dir_list(struct fixup_entry *p) +{ + struct fixup_entry *a, *b, *t; + + if (p == NULL) + return (NULL); + /* A one-item list is already sorted. */ + if (p->next == NULL) + return (p); + + /* Step 1: split the list. */ + t = p; + a = p->next->next; + while (a != NULL) { + /* Step a twice, t once. */ + a = a->next; + if (a != NULL) + a = a->next; + t = t->next; + } + /* Now, t is at the mid-point, so break the list here. */ + b = t->next; + t->next = NULL; + a = p; + + /* Step 2: Recursively sort the two sub-lists. */ + a = sort_dir_list(a); + b = sort_dir_list(b); + + /* Step 3: Merge the returned lists. */ + /* Pick the first element for the merged list. */ + if (wcscmp(a->name, b->name) > 0) { + t = p = a; + a = a->next; + } else { + t = p = b; + b = b->next; + } + + /* Always put the later element on the list first. */ + while (a != NULL && b != NULL) { + if (wcscmp(a->name, b->name) > 0) { + t->next = a; + a = a->next; + } else { + t->next = b; + b = b->next; + } + t = t->next; + } + + /* Only one list is non-empty, so just splice it on. */ + if (a != NULL) + t->next = a; + if (b != NULL) + t->next = b; + + return (p); +} + +/* + * Returns a new, initialized fixup entry. + * + * TODO: Reduce the memory requirements for this list by using a tree + * structure rather than a simple list of names. + */ +static struct fixup_entry * +new_fixup(struct archive_write_disk *a, const wchar_t *pathname) +{ + struct fixup_entry *fe; + + fe = (struct fixup_entry *)calloc(1, sizeof(struct fixup_entry)); + if (fe == NULL) + return (NULL); + fe->next = a->fixup_list; + a->fixup_list = fe; + fe->fixup = 0; + fe->name = _wcsdup(pathname); + fe->fflags_set = 0; + return (fe); +} + +/* + * Returns a fixup structure for the current entry. + */ +static struct fixup_entry * +current_fixup(struct archive_write_disk *a, const wchar_t *pathname) +{ + if (a->current_fixup == NULL) + a->current_fixup = new_fixup(a, pathname); + return (a->current_fixup); +} + +/* + * TODO: The deep-directory support bypasses this; disable deep directory + * support if we're doing symlink checks. + */ +/* + * TODO: Someday, integrate this with the deep dir support; they both + * scan the path and both can be optimized by comparing against other + * recent paths. + */ +static int +check_symlinks(struct archive_write_disk *a) +{ + wchar_t *pn, *p; + wchar_t c; + int r; + BY_HANDLE_FILE_INFORMATION st; + mode_t st_mode; + + /* + * Guard against symlink tricks. Reject any archive entry whose + * destination would be altered by a symlink. + */ + /* Whatever we checked last time doesn't need to be re-checked. */ + pn = a->name; + p = a->path_safe.s; + while ((*pn != '\0') && (*p == *pn)) + ++p, ++pn; + /* Skip leading backslashes */ + while (*pn == '\\') + ++pn; + c = pn[0]; + /* Keep going until we've checked the entire name. */ + while (pn[0] != '\0' && (pn[0] != '\\' || pn[1] != '\0')) { + /* Skip the next path element. */ + while (*pn != '\0' && *pn != '\\') + ++pn; + c = pn[0]; + pn[0] = '\0'; + /* Check that we haven't hit a symlink. */ + r = file_information(a, a->name, &st, &st_mode, 1); + if (r != 0) { + /* We've hit a dir that doesn't exist; stop now. */ + if (errno == ENOENT) + break; + } else if (S_ISLNK(st_mode)) { + if (c == '\0') { + /* + * Last element is a file or directory symlink. + * Remove it so we can overwrite it with the + * item being extracted. + */ + if (a->flags & + ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS) { + (void)clear_nochange_fflags(a); + } + if (st.dwFileAttributes & + FILE_ATTRIBUTE_DIRECTORY) { + r = disk_rmdir(a->name); + } else { + r = disk_unlink(a->name); + } + if (r) { + archive_set_error(&a->archive, errno, + "Could not remove symlink %ls", + a->name); + pn[0] = c; + return (ARCHIVE_FAILED); + } + a->pst = NULL; + /* + * Even if we did remove it, a warning + * is in order. The warning is silly, + * though, if we're just replacing one + * symlink with another symlink. + */ + if (!S_ISLNK(a->mode)) { + archive_set_error(&a->archive, 0, + "Removing symlink %ls", + a->name); + } + /* Symlink gone. No more problem! */ + pn[0] = c; + return (0); + } else if (a->flags & ARCHIVE_EXTRACT_UNLINK) { + /* User asked us to remove problems. */ + if (a->flags & + ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS) { + (void)clear_nochange_fflags(a); + } + if (st.dwFileAttributes & + FILE_ATTRIBUTE_DIRECTORY) { + r = disk_rmdir(a->name); + } else { + r = disk_unlink(a->name); + } + if (r != 0) { + archive_set_error(&a->archive, 0, + "Cannot remove intervening " + "symlink %ls", a->name); + pn[0] = c; + return (ARCHIVE_FAILED); + } + a->pst = NULL; + } else { + archive_set_error(&a->archive, 0, + "Cannot extract through symlink %ls", + a->name); + pn[0] = c; + return (ARCHIVE_FAILED); + } + } + pn[0] = c; + pn++; + } + pn[0] = c; + /* We've checked and/or cleaned the whole path, so remember it. */ + archive_wstrcpy(&a->path_safe, a->name); + return (ARCHIVE_OK); +} + +static int +guidword(wchar_t *p, int n) +{ + int i; + + for (i = 0; i < n; i++) { + if ((*p >= L'0' && *p <= L'9') || + (*p >= L'a' && *p <= L'f') || + (*p >= L'A' && *p <= L'F')) + p++; + else + return (-1); + } + return (0); +} + +/* + * Canonicalize the pathname. In particular, this strips duplicate + * '\' characters, '.' elements, and trailing '\'. It also raises an + * error for an empty path, a trailing '..' or (if _SECURE_NODOTDOT is + * set) any '..' in the path. + */ +static int +cleanup_pathname(struct archive_write_disk *a) +{ + wchar_t *dest, *src, *p, *top; + wchar_t separator = L'\0'; + + p = a->name; + if (*p == L'\0') { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid empty pathname"); + return (ARCHIVE_FAILED); + } + + /* Replace '/' by '\' */ + for (; *p != L'\0'; p++) { + if (*p == L'/') + *p = L'\\'; + } + p = a->name; + + /* Skip leading "\\.\" or "\\?\" or "\\?\UNC\" or + * "\\?\Volume{GUID}\" + * (absolute path prefixes used by Windows API) */ + if (p[0] == L'\\' && p[1] == L'\\' && + (p[2] == L'.' || p[2] == L'?') && p[3] == L'\\') + { + /* A path begin with "\\?\UNC\" */ + if (p[2] == L'?' && + (p[4] == L'U' || p[4] == L'u') && + (p[5] == L'N' || p[5] == L'n') && + (p[6] == L'C' || p[6] == L'c') && + p[7] == L'\\') + p += 8; + /* A path begin with "\\?\Volume{GUID}\" */ + else if (p[2] == L'?' && + (p[4] == L'V' || p[4] == L'v') && + (p[5] == L'O' || p[5] == L'o') && + (p[6] == L'L' || p[6] == L'l') && + (p[7] == L'U' || p[7] == L'u') && + (p[8] == L'M' || p[8] == L'm') && + (p[9] == L'E' || p[9] == L'e') && + p[10] == L'{') { + if (guidword(p+11, 8) == 0 && p[19] == L'-' && + guidword(p+20, 4) == 0 && p[24] == L'-' && + guidword(p+25, 4) == 0 && p[29] == L'-' && + guidword(p+30, 4) == 0 && p[34] == L'-' && + guidword(p+35, 12) == 0 && p[47] == L'}' && + p[48] == L'\\') + p += 49; + else + p += 4; + /* A path begin with "\\.\PhysicalDriveX" */ + } else if (p[2] == L'.' && + (p[4] == L'P' || p[4] == L'p') && + (p[5] == L'H' || p[5] == L'h') && + (p[6] == L'Y' || p[6] == L'y') && + (p[7] == L'S' || p[7] == L's') && + (p[8] == L'I' || p[8] == L'i') && + (p[9] == L'C' || p[9] == L'c') && + (p[9] == L'A' || p[9] == L'a') && + (p[9] == L'L' || p[9] == L'l') && + (p[9] == L'D' || p[9] == L'd') && + (p[9] == L'R' || p[9] == L'r') && + (p[9] == L'I' || p[9] == L'i') && + (p[9] == L'V' || p[9] == L'v') && + (p[9] == L'E' || p[9] == L'e') && + (p[10] >= L'0' && p[10] <= L'9') && + p[11] == L'\0') { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Path is a physical drive name"); + return (ARCHIVE_FAILED); + } else + p += 4; + } + + /* Skip leading drive letter from archives created + * on Windows. */ + if (((p[0] >= L'a' && p[0] <= L'z') || + (p[0] >= L'A' && p[0] <= L'Z')) && + p[1] == L':') { + if (p[2] == L'\0') { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Path is a drive name"); + return (ARCHIVE_FAILED); + } + if (p[2] == L'\\') + p += 2; + } + + top = dest = src = p; + /* Rewrite the path name if its character is a unusable. */ + for (; *p != L'\0'; p++) { + if (*p == L':' || *p == L'*' || *p == L'?' || *p == L'"' || + *p == L'<' || *p == L'>' || *p == L'|') + *p = L'_'; + } + /* Skip leading '\'. */ + if (*src == L'\\') + separator = *src++; + + /* Scan the pathname one element at a time. */ + for (;;) { + /* src points to first char after '\' */ + if (src[0] == L'\0') { + break; + } else if (src[0] == L'\\') { + /* Found '\\'('//'), ignore second one. */ + src++; + continue; + } else if (src[0] == L'.') { + if (src[1] == L'\0') { + /* Ignore trailing '.' */ + break; + } else if (src[1] == L'\\') { + /* Skip '.\'. */ + src += 2; + continue; + } else if (src[1] == L'.') { + if (src[2] == L'\\' || src[2] == L'\0') { + /* Conditionally warn about '..' */ + if (a->flags & + ARCHIVE_EXTRACT_SECURE_NODOTDOT) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Path contains '..'"); + return (ARCHIVE_FAILED); + } + } + /* + * Note: Under no circumstances do we + * remove '..' elements. In + * particular, restoring + * '\foo\..\bar\' should create the + * 'foo' dir as a side-effect. + */ + } + } + + /* Copy current element, including leading '\'. */ + if (separator) + *dest++ = L'\\'; + while (*src != L'\0' && *src != L'\\') { + *dest++ = *src++; + } + + if (*src == L'\0') + break; + + /* Skip '\' separator. */ + separator = *src++; + } + /* + * We've just copied zero or more path elements, not including the + * final '\'. + */ + if (dest == top) { + /* + * Nothing got copied. The path must have been something + * like '.' or '\' or './' or '/././././/./'. + */ + if (separator) + *dest++ = L'\\'; + else + *dest++ = L'.'; + } + /* Terminate the result. */ + *dest = L'\0'; + return (ARCHIVE_OK); +} + +/* + * Create the parent directory of the specified path, assuming path + * is already in mutable storage. + */ +static int +create_parent_dir(struct archive_write_disk *a, wchar_t *path) +{ + wchar_t *slash; + int r; + + /* Remove tail element to obtain parent name. */ + slash = wcsrchr(path, L'\\'); + if (slash == NULL) + return (ARCHIVE_OK); + *slash = L'\0'; + r = create_dir(a, path); + *slash = L'\\'; + return (r); +} + +/* + * Create the specified dir, recursing to create parents as necessary. + * + * Returns ARCHIVE_OK if the path exists when we're done here. + * Otherwise, returns ARCHIVE_FAILED. + * Assumes path is in mutable storage; path is unchanged on exit. + */ +static int +create_dir(struct archive_write_disk *a, wchar_t *path) +{ + BY_HANDLE_FILE_INFORMATION st; + struct fixup_entry *le; + wchar_t *slash, *base, *full; + mode_t mode_final, mode, st_mode; + int r; + + /* Check for special names and just skip them. */ + slash = wcsrchr(path, L'\\'); + if (slash == NULL) + base = path; + else + base = slash + 1; + + if (base[0] == L'\0' || + (base[0] == L'.' && base[1] == L'\0') || + (base[0] == L'.' && base[1] == L'.' && base[2] == L'\0')) { + /* Don't bother trying to create null path, '.', or '..'. */ + if (slash != NULL) { + *slash = L'\0'; + r = create_dir(a, path); + *slash = L'\\'; + return (r); + } + return (ARCHIVE_OK); + } + + /* + * Yes, this should be stat() and not lstat(). Using lstat() + * here loses the ability to extract through symlinks. Also note + * that this should not use the a->st cache. + */ + if (file_information(a, path, &st, &st_mode, 0) == 0) { + if (S_ISDIR(st_mode)) + return (ARCHIVE_OK); + if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) { + archive_set_error(&a->archive, EEXIST, + "Can't create directory '%ls'", path); + return (ARCHIVE_FAILED); + } + if (disk_unlink(path) != 0) { + archive_set_error(&a->archive, errno, + "Can't create directory '%ls': " + "Conflicting file cannot be removed", + path); + return (ARCHIVE_FAILED); + } + } else if (errno != ENOENT && errno != ENOTDIR) { + /* Stat failed? */ + archive_set_error(&a->archive, errno, + "Can't test directory '%ls'", path); + return (ARCHIVE_FAILED); + } else if (slash != NULL) { + *slash = '\0'; + r = create_dir(a, path); + *slash = '\\'; + if (r != ARCHIVE_OK) + return (r); + } + + /* + * Mode we want for the final restored directory. Per POSIX, + * implicitly-created dirs must be created obeying the umask. + * There's no mention whether this is different for privileged + * restores (which the rest of this code handles by pretending + * umask=0). I've chosen here to always obey the user's umask for + * implicit dirs, even if _EXTRACT_PERM was specified. + */ + mode_final = DEFAULT_DIR_MODE & ~a->user_umask; + /* Mode we want on disk during the restore process. */ + mode = mode_final; + mode |= MINIMUM_DIR_MODE; + mode &= MAXIMUM_DIR_MODE; + /* + * Apply __la_win_permissive_name_w to path in order to + * remove '../' path string. + */ + full = __la_win_permissive_name_w(path); + if (full == NULL) + errno = EINVAL; + else if (CreateDirectoryW(full, NULL) != 0) { + if (mode != mode_final) { + le = new_fixup(a, path); + le->fixup |=TODO_MODE_BASE; + le->mode = mode_final; + } + free(full); + return (ARCHIVE_OK); + } else { + la_dosmaperr(GetLastError()); + } + free(full); + + /* + * Without the following check, a/b/../b/c/d fails at the + * second visit to 'b', so 'd' can't be created. Note that we + * don't add it to the fixup list here, as it's already been + * added. + */ + if (file_information(a, path, &st, &st_mode, 0) == 0 && + S_ISDIR(st_mode)) + return (ARCHIVE_OK); + + archive_set_error(&a->archive, errno, "Failed to create dir '%ls'", + path); + return (ARCHIVE_FAILED); +} + +/* + * Note: Although we can skip setting the user id if the desired user + * id matches the current user, we cannot skip setting the group, as + * many systems set the gid based on the containing directory. So + * we have to perform a chown syscall if we want to set the SGID + * bit. (The alternative is to stat() and then possibly chown(); it's + * more efficient to skip the stat() and just always chown().) Note + * that a successful chown() here clears the TODO_SGID_CHECK bit, which + * allows set_mode to skip the stat() check for the GID. + */ +static int +set_ownership(struct archive_write_disk *a) +{ +/* unfortunately, on win32 there is no 'root' user with uid 0, + so we just have to try the chown and see if it works */ + + /* If we know we can't change it, don't bother trying. */ + if (a->user_uid != 0 && a->user_uid != a->uid) { + archive_set_error(&a->archive, errno, + "Can't set UID=%jd", (intmax_t)a->uid); + return (ARCHIVE_WARN); + } + + archive_set_error(&a->archive, errno, + "Can't set user=%jd/group=%jd for %ls", + (intmax_t)a->uid, (intmax_t)a->gid, a->name); + return (ARCHIVE_WARN); +} + +static int +set_times(struct archive_write_disk *a, + HANDLE h, int mode, const wchar_t *name, + time_t atime, long atime_nanos, + time_t birthtime, long birthtime_nanos, + time_t mtime, long mtime_nanos, + time_t ctime_sec, long ctime_nanos) +{ +#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) +#define WINTIME(sec, nsec) ((Int32x32To64(sec, 10000000) + EPOC_TIME)\ + + (((nsec)/1000)*10)) + + HANDLE hw = 0; + ULARGE_INTEGER wintm; + FILETIME *pfbtime; + FILETIME fatime, fbtime, fmtime; + + (void)ctime_sec; /* UNUSED */ + (void)ctime_nanos; /* UNUSED */ + + if (h != INVALID_HANDLE_VALUE) { + hw = NULL; + } else { + wchar_t *ws; + + if (S_ISLNK(mode)) + return (ARCHIVE_OK); + ws = __la_win_permissive_name_w(name); + if (ws == NULL) + goto settimes_failed; + hw = CreateFileW(ws, FILE_WRITE_ATTRIBUTES, + 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + free(ws); + if (hw == INVALID_HANDLE_VALUE) + goto settimes_failed; + h = hw; + } + + wintm.QuadPart = WINTIME(atime, atime_nanos); + fatime.dwLowDateTime = wintm.LowPart; + fatime.dwHighDateTime = wintm.HighPart; + wintm.QuadPart = WINTIME(mtime, mtime_nanos); + fmtime.dwLowDateTime = wintm.LowPart; + fmtime.dwHighDateTime = wintm.HighPart; + /* + * SetFileTime() supports birthtime. + */ + if (birthtime > 0 || birthtime_nanos > 0) { + wintm.QuadPart = WINTIME(birthtime, birthtime_nanos); + fbtime.dwLowDateTime = wintm.LowPart; + fbtime.dwHighDateTime = wintm.HighPart; + pfbtime = &fbtime; + } else + pfbtime = NULL; + if (SetFileTime(h, pfbtime, &fatime, &fmtime) == 0) + goto settimes_failed; + CloseHandle(hw); + return (ARCHIVE_OK); + +settimes_failed: + CloseHandle(hw); + archive_set_error(&a->archive, EINVAL, "Can't restore time"); + return (ARCHIVE_WARN); +} + +static int +set_times_from_entry(struct archive_write_disk *a) +{ + time_t atime, birthtime, mtime, ctime_sec; + long atime_nsec, birthtime_nsec, mtime_nsec, ctime_nsec; + + /* Suitable defaults. */ + atime = birthtime = mtime = ctime_sec = a->start_time; + atime_nsec = birthtime_nsec = mtime_nsec = ctime_nsec = 0; + + /* If no time was provided, we're done. */ + if (!archive_entry_atime_is_set(a->entry) + && !archive_entry_birthtime_is_set(a->entry) + && !archive_entry_mtime_is_set(a->entry)) + return (ARCHIVE_OK); + + if (archive_entry_atime_is_set(a->entry)) { + atime = archive_entry_atime(a->entry); + atime_nsec = archive_entry_atime_nsec(a->entry); + } + if (archive_entry_birthtime_is_set(a->entry)) { + birthtime = archive_entry_birthtime(a->entry); + birthtime_nsec = archive_entry_birthtime_nsec(a->entry); + } + if (archive_entry_mtime_is_set(a->entry)) { + mtime = archive_entry_mtime(a->entry); + mtime_nsec = archive_entry_mtime_nsec(a->entry); + } + if (archive_entry_ctime_is_set(a->entry)) { + ctime_sec = archive_entry_ctime(a->entry); + ctime_nsec = archive_entry_ctime_nsec(a->entry); + } + + return set_times(a, a->fh, a->mode, a->name, + atime, atime_nsec, + birthtime, birthtime_nsec, + mtime, mtime_nsec, + ctime_sec, ctime_nsec); +} + +static int +set_mode(struct archive_write_disk *a, int mode) +{ + int r = ARCHIVE_OK; + mode &= 07777; /* Strip off file type bits. */ + + if (a->todo & TODO_SGID_CHECK) { + /* + * If we don't know the GID is right, we must stat() + * to verify it. We can't just check the GID of this + * process, since systems sometimes set GID from + * the enclosing dir or based on ACLs. + */ + if ((r = lazy_stat(a)) != ARCHIVE_OK) + return (r); + if (0 != a->gid) { + mode &= ~ S_ISGID; + } + /* While we're here, double-check the UID. */ + if (0 != a->uid + && (a->todo & TODO_SUID)) { + mode &= ~ S_ISUID; + } + a->todo &= ~TODO_SGID_CHECK; + a->todo &= ~TODO_SUID_CHECK; + } else if (a->todo & TODO_SUID_CHECK) { + /* + * If we don't know the UID is right, we can just check + * the user, since all systems set the file UID from + * the process UID. + */ + if (a->user_uid != a->uid) { + mode &= ~ S_ISUID; + } + a->todo &= ~TODO_SUID_CHECK; + } + + if (S_ISLNK(a->mode)) { +#ifdef HAVE_LCHMOD + /* + * If this is a symlink, use lchmod(). If the + * platform doesn't support lchmod(), just skip it. A + * platform that doesn't provide a way to set + * permissions on symlinks probably ignores + * permissions on symlinks, so a failure here has no + * impact. + */ + if (lchmod(a->name, mode) != 0) { + archive_set_error(&a->archive, errno, + "Can't set permissions to 0%o", (int)mode); + r = ARCHIVE_WARN; + } +#endif + } else if (!S_ISDIR(a->mode)) { + /* + * If it's not a symlink and not a dir, then use + * fchmod() or chmod(), depending on whether we have + * an fd. Dirs get their perms set during the + * post-extract fixup, which is handled elsewhere. + */ +#ifdef HAVE_FCHMOD + if (a->fd >= 0) { + if (fchmod(a->fd, mode) != 0) { + archive_set_error(&a->archive, errno, + "Can't set permissions to 0%o", (int)mode); + r = ARCHIVE_WARN; + } + } else +#endif + /* If this platform lacks fchmod(), then + * we'll just use chmod(). */ + if (la_chmod(a->name, mode) != 0) { + archive_set_error(&a->archive, errno, + "Can't set permissions to 0%o", (int)mode); + r = ARCHIVE_WARN; + } + } + return (r); +} + +static int set_fflags_platform(const wchar_t *name, unsigned long fflags_set, + unsigned long fflags_clear) +{ + DWORD oldflags, newflags; + wchar_t *fullname; + + const DWORD settable_flags = + FILE_ATTRIBUTE_ARCHIVE | + FILE_ATTRIBUTE_HIDDEN | + FILE_ATTRIBUTE_NORMAL | + FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | + FILE_ATTRIBUTE_OFFLINE | + FILE_ATTRIBUTE_READONLY | + FILE_ATTRIBUTE_SYSTEM | + FILE_ATTRIBUTE_TEMPORARY; + + oldflags = GetFileAttributesW(name); + if (oldflags == (DWORD)-1 && + GetLastError() == ERROR_INVALID_NAME) { + fullname = __la_win_permissive_name_w(name); + oldflags = GetFileAttributesW(fullname); + } + if (oldflags == (DWORD)-1) { + la_dosmaperr(GetLastError()); + return (ARCHIVE_WARN); + } + newflags = ((oldflags & ~fflags_clear) | fflags_set) & settable_flags; + if(SetFileAttributesW(name, newflags) == 0) + return (ARCHIVE_WARN); + return (ARCHIVE_OK); +} + +static int +clear_nochange_fflags(struct archive_write_disk *a) +{ + return (set_fflags_platform(a->name, 0, FILE_ATTRIBUTE_READONLY)); +} + +static int +set_fflags(struct archive_write_disk *a) +{ + unsigned long set, clear; + + if (a->todo & TODO_FFLAGS) { + archive_entry_fflags(a->entry, &set, &clear); + if (set == 0 && clear == 0) + return (ARCHIVE_OK); + return (set_fflags_platform(a->name, set, clear)); + + } + return (ARCHIVE_OK); +} + +/* Default empty function body to satisfy mainline code. */ +static int +set_acls(struct archive_write_disk *a, HANDLE h, const wchar_t *name, + struct archive_acl *acl) +{ + (void)a; /* UNUSED */ + (void)h; /* UNUSED */ + (void)name; /* UNUSED */ + (void)acl; /* UNUSED */ + return (ARCHIVE_OK); +} + +/* + * Restore extended attributes - stub implementation for unsupported systems + */ +static int +set_xattrs(struct archive_write_disk *a) +{ + static int warning_done = 0; + + /* If there aren't any extended attributes, then it's okay not + * to extract them, otherwise, issue a single warning. */ + if (archive_entry_xattr_count(a->entry) != 0 && !warning_done) { + warning_done = 1; + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Cannot restore extended attributes on this system"); + return (ARCHIVE_WARN); + } + /* Warning was already emitted; suppress further warnings. */ + return (ARCHIVE_OK); +} + +static void +fileTimeToUtc(const FILETIME *filetime, time_t *t, long *ns) +{ + ULARGE_INTEGER utc; + + utc.HighPart = filetime->dwHighDateTime; + utc.LowPart = filetime->dwLowDateTime; + if (utc.QuadPart >= EPOC_TIME) { + utc.QuadPart -= EPOC_TIME; + /* milli seconds base */ + *t = (time_t)(utc.QuadPart / 10000000); + /* nano seconds base */ + *ns = (long)(utc.QuadPart % 10000000) * 100; + } else { + *t = 0; + *ns = 0; + } +} +/* + * Test if file on disk is older than entry. + */ +static int +older(BY_HANDLE_FILE_INFORMATION *st, struct archive_entry *entry) +{ + time_t sec; + long nsec; + + fileTimeToUtc(&st->ftLastWriteTime, &sec, &nsec); + /* First, test the seconds and return if we have a definite answer. */ + /* Definitely older. */ + if (sec < archive_entry_mtime(entry)) + return (1); + /* Definitely younger. */ + if (sec > archive_entry_mtime(entry)) + return (0); + if (nsec < archive_entry_mtime_nsec(entry)) + return (1); + /* Same age or newer, so not older. */ + return (0); +} + +#endif /* _WIN32 && !__CYGWIN__ */ + diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_filter.3 b/dependencies/libarchive-3.4.2/libarchive/archive_write_filter.3 new file mode 100644 index 0000000..c83eb77 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_filter.3 @@ -0,0 +1,134 @@ +.\" Copyright (c) 2003-2011 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd August 14, 2014 +.Dt ARCHIVE_WRITE_FILTER 3 +.Os +.Sh NAME +.Nm archive_write_add_filter_b64encode , +.Nm archive_write_add_filter_by_name , +.Nm archive_write_add_filter_bzip2 , +.Nm archive_write_add_filter_compress , +.Nm archive_write_add_filter_grzip , +.Nm archive_write_add_filter_gzip , +.Nm archive_write_add_filter_lrzip , +.Nm archive_write_add_filter_lz4 , +.Nm archive_write_add_filter_lzip , +.Nm archive_write_add_filter_lzma , +.Nm archive_write_add_filter_lzop , +.Nm archive_write_add_filter_none , +.Nm archive_write_add_filter_program , +.Nm archive_write_add_filter_uuencode , +.Nm archive_write_add_filter_xz , +.Nm archive_write_add_filter_zstd +.Nd functions enabling output filters +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive.h +.Ft int +.Fn archive_write_add_filter_b64encode "struct archive *" +.Ft int +.Fn archive_write_add_filter_bzip2 "struct archive *" +.Ft int +.Fn archive_write_add_filter_compress "struct archive *" +.Ft int +.Fn archive_write_add_filter_grzip "struct archive *" +.Ft int +.Fn archive_write_add_filter_gzip "struct archive *" +.Ft int +.Fn archive_write_add_filter_lrzip "struct archive *" +.Ft int +.Fn archive_write_add_filter_lz4 "struct archive *" +.Ft int +.Fn archive_write_add_filter_lzip "struct archive *" +.Ft int +.Fn archive_write_add_filter_lzma "struct archive *" +.Ft int +.Fn archive_write_add_filter_lzop "struct archive *" +.Ft int +.Fn archive_write_add_filter_none "struct archive *" +.Ft int +.Fn archive_write_add_filter_program "struct archive *" "const char * cmd" +.Ft int +.Fn archive_write_add_filter_uuencode "struct archive *" +.Ft int +.Fn archive_write_add_filter_xz "struct archive *" +.Ft int +.Fn archive_write_add_filter_zstd "struct archive *" +.Sh DESCRIPTION +.Bl -tag -width indent +.It Xo +.Fn archive_write_add_filter_bzip2 , +.Fn archive_write_add_filter_compress , +.Fn archive_write_add_filter_grzip , +.Fn archive_write_add_filter_gzip , +.Fn archive_write_add_filter_lrzip , +.Fn archive_write_add_filter_lz4 , +.Fn archive_write_add_filter_lzip , +.Fn archive_write_add_filter_lzma , +.Fn archive_write_add_filter_lzop , +.Fn archive_write_add_filter_xz , +.Fn archive_write_add_filter_zstd , +.Xc +The resulting archive will be compressed as specified. +Note that the compressed output is always properly blocked. +.It Xo +.Fn archive_write_add_filter_b64encode , +.Fn archive_write_add_filter_uuencode , +.Xc +The output will be encoded as specified. +The encoded output is always properly blocked. +.It Fn archive_write_add_filter_none +This is never necessary. +It is provided only for backwards compatibility. +.It Fn archive_write_add_filter_program +The archive will be fed into the specified compression program. +The output of that program is blocked and written to the client +write callbacks. +.El +.Sh RETURN VALUES +These functions return +.Cm ARCHIVE_OK +on success, or +.Cm ARCHIVE_FATAL . +.\" +.Sh ERRORS +Detailed error codes and textual descriptions are available from the +.Fn archive_errno +and +.Fn archive_error_string +functions. +.\" +.Sh SEE ALSO +.Xr tar 1 , +.Xr archive_write 3 , +.Xr archive_write_format 3 , +.Xr archive_write_set_options 3 , +.Xr libarchive 3 , +.Xr cpio 5 , +.Xr mtree 5 , +.Xr tar 5 diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_finish_entry.3 b/dependencies/libarchive-3.4.2/libarchive/archive_write_finish_entry.3 new file mode 100644 index 0000000..5797e16 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_finish_entry.3 @@ -0,0 +1,79 @@ +.\" Copyright (c) 2003-2011 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 28, 2017 +.Dt ARCHIVE_WRITE_FINISH_ENTRY 3 +.Os +.Sh NAME +.Nm archive_write_finish_entry +.Nd functions for creating archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive.h +.Ft int +.Fn archive_write_finish_entry "struct archive *" +.Sh DESCRIPTION +Close out the entry just written. +In particular, this writes out the final padding required by some formats. +Ordinarily, clients never need to call this, as it +is called automatically by +.Fn archive_write_header +and +.Fn archive_write_close +as needed. +For +.Tn archive_write_disk +handles, this flushes pending file attribute changes like modification time. +.\" .Sh EXAMPLE +.Sh RETURN VALUES +This function returns +.Cm ARCHIVE_OK +on success, or one of several non-zero +error codes for errors. +Specific error codes include: +.Cm ARCHIVE_RETRY +for operations that might succeed if retried, +.Cm ARCHIVE_WARN +for unusual conditions that do not prevent further operations, and +.Cm ARCHIVE_FATAL +for serious errors that make remaining operations impossible. +.\" +.Sh ERRORS +Detailed error codes and textual descriptions are available from the +.Fn archive_errno +and +.Fn archive_error_string +functions. +.\" +.Sh SEE ALSO +.Xr tar 1 , +.Xr archive_write_data 3 , +.Xr archive_write_set_options 3 , +.Xr libarchive 3 , +.Xr cpio 5 , +.Xr mtree 5 , +.Xr tar 5 diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_format.3 b/dependencies/libarchive-3.4.2/libarchive/archive_write_format.3 new file mode 100644 index 0000000..47a7403 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_format.3 @@ -0,0 +1,175 @@ +.\" Copyright (c) 2003-2011 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 14, 2013 +.Dt ARCHIVE_WRITE_FORMAT 3 +.Os +.Sh NAME +.Nm archive_write_set_format , +.Nm archive_write_set_format_7zip , +.Nm archive_write_set_format_ar , +.Nm archive_write_set_format_ar_bsd , +.Nm archive_write_set_format_ar_svr4 , +.Nm archive_write_set_format_by_name , +.Nm archive_write_set_format_cpio , +.Nm archive_write_set_format_cpio_newc , +.Nm archive_write_set_format_filter_by_ext , +.Nm archive_write_set_format_filter_by_ext_def , +.Nm archive_write_set_format_gnutar , +.Nm archive_write_set_format_iso9660 , +.Nm archive_write_set_format_mtree , +.Nm archive_write_set_format_mtree_classic , +.Nm archive_write_set_format_mtree_default , +.Nm archive_write_set_format_pax , +.Nm archive_write_set_format_pax_restricted , +.Nm archive_write_set_format_raw , +.Nm archive_write_set_format_shar , +.Nm archive_write_set_format_shar_dump , +.Nm archive_write_set_format_ustar , +.Nm archive_write_set_format_v7tar , +.Nm archive_write_set_format_warc , +.Nm archive_write_set_format_xar , +.Nm archive_write_set_format_zip +.Nd functions for creating archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive.h +.Ft int +.Fn archive_write_set_format "struct archive *" "int code" +.Ft int +.Fn archive_write_set_format_7zip "struct archive *" +.Ft int +.Fn archive_write_set_format_ar "struct archive *" +.Ft int +.Fn archive_write_set_format_ar_bsd "struct archive *" +.Ft int +.Fn archive_write_set_format_ar_svr4 "struct archive *" +.Ft int +.Fn archive_write_set_format_by_name "struct archive *" "const char *name" +.Ft int +.Fn archive_write_set_format_cpio "struct archive *" +.Ft int +.Fn archive_write_set_format_cpio_newc "struct archive *" +.Ft int +.Fn archive_write_set_format_filter_by_ext "struct archive *" "const char *filename" +.Ft int +.Fn archive_write_set_format_filter_by_ext_def "struct archive *" "const char *filename" "const char *def_ext" +.Ft int +.Fn archive_write_set_format_gnutar "struct archive *" +.Ft int +.Fn archive_write_set_format_iso9660 "struct archive *" +.Ft int +.Fn archive_write_set_format_mtree "struct archive *" +.Ft int +.Fn archive_write_set_format_pax "struct archive *" +.Ft int +.Fn archive_write_set_format_pax_restricted "struct archive *" +.Ft int +.Fn archive_write_set_format_raw "struct archive *" +.Ft int +.Fn archive_write_set_format_shar "struct archive *" +.Ft int +.Fn archive_write_set_format_shar_dump "struct archive *" +.Ft int +.Fn archive_write_set_format_ustar "struct archive *" +.Ft int +.Fn archive_write_set_format_v7tar "struct archive *" +.Ft int +.Fn archive_write_set_format_warc "struct archive *" +.Ft int +.Fn archive_write_set_format_xar "struct archive *" +.Ft int +.Fn archive_write_set_format_zip "struct archive *" +.Sh DESCRIPTION +These functions set the format that will be used for the archive. +.Pp +The library can write a variety of common archive formats. +.Bl -tag -width indent +.It Fn archive_write_set_format +Sets the format based on the format code (see +.Pa archive.h +for the full list of format codes). +In particular, this can be used in conjunction with +.Fn archive_format +to create a new archive with the same format as an existing archive. +.It Fn archive_write_set_format_by_name +Sets the corresponding format based on the common name. +.It Xo +.Fn archive_write_set_format_filter_by_ext , +.Fn archive_write_set_format_filter_by_ext_def +.Xc +Sets both filters and format based on the output filename. +Supported extensions: .7z, .zip, .jar, .cpio, .iso, .a, .ar, .tar, .tgz, .tar.gz, .tar.bz2, .tar.xz +.It Xo +.Fn archive_write_set_format_7zip +.Fn archive_write_set_format_ar_bsd , +.Fn archive_write_set_format_ar_svr4 , +.Fn archive_write_set_format_cpio +.Fn archive_write_set_format_cpio_newc +.Fn archive_write_set_format_gnutar +.Fn archive_write_set_format_iso9660 +.Fn archive_write_set_format_mtree +.Fn archive_write_set_format_mtree_classic +.Fn archive_write_set_format_pax +.Fn archive_write_set_format_pax_restricted +.Fn archive_write_set_format_raw +.Fn archive_write_set_format_shar +.Fn archive_write_set_format_shar_dump +.Fn archive_write_set_format_ustar +.Fn archive_write_set_format_v7tar +.Fn archive_write_set_format_warc +.Fn archive_write_set_format_xar +.Fn archive_write_set_format_zip +.Xc +Set the format as specified. +More details on the formats supported by libarchive can be found in the +.Xr libarchive-formats 5 +manual page. +.El +.\" +.Sh RETURN VALUES +These functions return +.Cm ARCHIVE_OK +on success, or +.Cm ARCHIVE_FATAL . +.\" +.Sh ERRORS +Detailed error codes and textual descriptions are available from the +.Fn archive_errno +and +.Fn archive_error_string +functions. +.\" +.Sh SEE ALSO +.Xr tar 1 , +.Xr archive_write 3 , +.Xr archive_write_set_options 3 , +.Xr libarchive 3 , +.Xr cpio 5 , +.Xr libarchive-formats 5 , +.Xr mtree 5 , +.Xr tar 5 diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_free.3 b/dependencies/libarchive-3.4.2/libarchive/archive_write_free.3 new file mode 100644 index 0000000..5210e2a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_free.3 @@ -0,0 +1,96 @@ +.\" Copyright (c) 2003-2011 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 2, 2012 +.Dt ARCHIVE_WRITE_FREE 3 +.Os +.Sh NAME +.Nm archive_write_fail , +.Nm archive_write_close , +.Nm archive_write_finish , +.Nm archive_write_free +.Nd functions for creating archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive.h +.Ft int +.Fn archive_write_fail "struct archive *" +.Ft int +.Fn archive_write_close "struct archive *" +.Ft int +.Fn archive_write_finish "struct archive *" +.Ft int +.Fn archive_write_free "struct archive *" +.Sh DESCRIPTION +.Bl -tag -width indent +.It Fn archive_write_fail +Always returns +.Cm ARCHIVE_FATAL . +This marks the archive object as being unusable; +after calling this function, the only call that can succeed is +.Fn archive_write_free +to release the resources. +This can be used to speed recovery when the archive creation +must be aborted. +Note that the created archive is likely to be malformed in this case; +.It Fn archive_write_close +Complete the archive and invoke the close callback. +.It Fn archive_write_finish +This is a deprecated synonym for +.Fn archive_write_free . +.It Fn archive_write_free +Invokes +.Fn archive_write_close +if necessary, then releases all resources. +If you need detailed information about +.Fn archive_write_close +failures, you should be careful to call it separately, as +you cannot obtain error information after +.Fn archive_write_free +returns. +.El +.\" .Sh EXAMPLE +.Sh RETURN VALUES +These functions return +.Cm ARCHIVE_OK +on success, or +.Cm ARCHIVE_FATAL . +.\" +.Sh ERRORS +Detailed error codes and textual descriptions are available from the +.Fn archive_errno +and +.Fn archive_error_string +functions. +.\" +.Sh SEE ALSO +.Xr tar 1 , +.Xr archive_write_set_options 3 , +.Xr libarchive 3 , +.Xr cpio 5 , +.Xr mtree 5 , +.Xr tar 5 diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_header.3 b/dependencies/libarchive-3.4.2/libarchive/archive_write_header.3 new file mode 100644 index 0000000..2217b18 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_header.3 @@ -0,0 +1,73 @@ +.\" Copyright (c) 2003-2011 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 2, 2012 +.Dt ARCHIVE_WRITE_HEADER 3 +.Os +.Sh NAME +.Nm archive_write_header +.Nd functions for creating archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive.h +.Ft int +.Fn archive_write_header "struct archive *" "struct archive_entry *" +.Sh DESCRIPTION +Build and write a header using the data in the provided +.Tn struct archive_entry +structure. +See +.Xr archive_entry 3 +for information on creating and populating +.Tn struct archive_entry +objects. +.\" .Sh EXAMPLE +.Sh RETURN VALUES +This function returns +.Cm ARCHIVE_OK +on success, or one of the following on error: +.Cm ARCHIVE_RETRY +for operations that might succeed if retried, +.Cm ARCHIVE_WARN +for unusual conditions that do not prevent further operations, and +.Cm ARCHIVE_FATAL +for serious errors that make remaining operations impossible. +.\" +.Sh ERRORS +Detailed error codes and textual descriptions are available from the +.Fn archive_errno +and +.Fn archive_error_string +functions. +.\" +.Sh SEE ALSO +.Xr tar 1 , +.Xr archive_write_set_options 3 , +.Xr libarchive 3 , +.Xr cpio 5 , +.Xr mtree 5 , +.Xr tar 5 diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_new.3 b/dependencies/libarchive-3.4.2/libarchive/archive_write_new.3 new file mode 100644 index 0000000..788cbb8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_new.3 @@ -0,0 +1,58 @@ +.\" Copyright (c) 2003-2011 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 2, 2012 +.Dt ARCHIVE_WRITE_NEW 3 +.Os +.Sh NAME +.Nm archive_write_new +.Nd functions for creating archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive.h +.Ft struct archive * +.Fn archive_write_new "void" +.Sh DESCRIPTION +Allocates and initializes a +.Tn struct archive +object suitable for writing a tar archive. +.Dv NULL +is returned on error. +.Pp +A complete description of the +.Tn struct archive +object can be found in the overview manual page for +.Xr libarchive 3 . +.\" .Sh ERRORS +.Sh SEE ALSO +.Xr tar 1 , +.Xr archive_write 3 , +.Xr archive_write_set_options 3 , +.Xr libarchive 3 , +.Xr cpio 5 , +.Xr mtree 5 , +.Xr tar 5 diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_open.3 b/dependencies/libarchive-3.4.2/libarchive/archive_write_open.3 new file mode 100644 index 0000000..0129d10 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_open.3 @@ -0,0 +1,246 @@ +.\" Copyright (c) 2003-2011 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 2, 2012 +.Dt ARCHIVE_WRITE_OPEN 3 +.Os +.Sh NAME +.Nm archive_write_open , +.Nm archive_write_open_fd , +.Nm archive_write_open_FILE , +.Nm archive_write_open_filename , +.Nm archive_write_open_memory +.Nd functions for creating archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive.h +.Ft int +.Fo archive_write_open +.Fa "struct archive *" +.Fa "void *client_data" +.Fa "archive_open_callback *" +.Fa "archive_write_callback *" +.Fa "archive_close_callback *" +.Fc +.Ft int +.Fn archive_write_open_fd "struct archive *" "int fd" +.Ft int +.Fn archive_write_open_FILE "struct archive *" "FILE *file" +.Ft int +.Fn archive_write_open_filename "struct archive *" "const char *filename" +.Ft int +.Fo archive_write_open_memory +.Fa "struct archive *" +.Fa "void *buffer" +.Fa "size_t bufferSize" +.Fa "size_t *outUsed" +.Fc +.Sh DESCRIPTION +.Bl -tag -width indent +.It Fn archive_write_open +Freeze the settings, open the archive, and prepare for writing entries. +This is the most generic form of this function, which accepts +pointers to three callback functions which will be invoked by +the compression layer to write the constructed archive. +This does not alter the default archive padding. +.It Fn archive_write_open_fd +A convenience form of +.Fn archive_write_open +that accepts a file descriptor. +The +.Fn archive_write_open_fd +function is safe for use with tape drives or other +block-oriented devices. +.It Fn archive_write_open_FILE +A convenience form of +.Fn archive_write_open +that accepts a +.Ft "FILE *" +pointer. +Note that +.Fn archive_write_open_FILE +is not safe for writing to tape drives or other devices +that require correct blocking. +.It Fn archive_write_open_file +A deprecated synonym for +.Fn archive_write_open_filename . +.It Fn archive_write_open_filename +A convenience form of +.Fn archive_write_open +that accepts a filename. +A NULL argument indicates that the output should be written to standard output; +an argument of +.Dq - +will open a file with that name. +If you have not invoked +.Fn archive_write_set_bytes_in_last_block , +then +.Fn archive_write_open_filename +will adjust the last-block padding depending on the file: +it will enable padding when writing to standard output or +to a character or block device node, it will disable padding otherwise. +You can override this by manually invoking +.Fn archive_write_set_bytes_in_last_block +before calling +.Fn archive_write_open . +The +.Fn archive_write_open_filename +function is safe for use with tape drives or other +block-oriented devices. +.It Fn archive_write_open_memory +A convenience form of +.Fn archive_write_open +that accepts a pointer to a block of memory that will receive +the archive. +The final +.Ft "size_t *" +argument points to a variable that will be updated +after each write to reflect how much of the buffer +is currently in use. +You should be careful to ensure that this variable +remains allocated until after the archive is +closed. +This function will disable padding unless you +have specifically set the block size. +.El +More information about the +.Va struct archive +object and the overall design of the library can be found in the +.Xr libarchive 3 +overview. +.Pp +Note that the convenience forms above vary in how +they block the output. +See +.Xr archive_write_blocksize 3 +if you need to control the block size used for writes +or the end-of-file padding behavior. +.\" +.Sh CLIENT CALLBACKS +To use this library, you will need to define and register +callback functions that will be invoked to write data to the +resulting archive. +These functions are registered by calling +.Fn archive_write_open : +.Bl -item -offset indent +.It +.Ft typedef int +.Fn archive_open_callback "struct archive *" "void *client_data" +.El +.Pp +The open callback is invoked by +.Fn archive_write_open . +It should return +.Cm ARCHIVE_OK +if the underlying file or data source is successfully +opened. +If the open fails, it should call +.Fn archive_set_error +to register an error code and message and return +.Cm ARCHIVE_FATAL . +.Bl -item -offset indent +.It +.Ft typedef la_ssize_t +.Fo archive_write_callback +.Fa "struct archive *" +.Fa "void *client_data" +.Fa "const void *buffer" +.Fa "size_t length" +.Fc +.El +.Pp +The write callback is invoked whenever the library +needs to write raw bytes to the archive. +For correct blocking, each call to the write callback function +should translate into a single +.Xr write 2 +system call. +This is especially critical when writing archives to tape drives. +On success, the write callback should return the +number of bytes actually written. +On error, the callback should invoke +.Fn archive_set_error +to register an error code and message and return -1. +.Bl -item -offset indent +.It +.Ft typedef int +.Fn archive_close_callback "struct archive *" "void *client_data" +.El +.Pp +The close callback is invoked by archive_close when +the archive processing is complete. +The callback should return +.Cm ARCHIVE_OK +on success. +On failure, the callback should invoke +.Fn archive_set_error +to register an error code and message and +return +.Cm ARCHIVE_FATAL . +.Pp +Note that if the client-provided write callback function +returns a non-zero value, that error will be propagated back to the caller +through whatever API function resulted in that call, which +may include +.Fn archive_write_header , +.Fn archive_write_data , +.Fn archive_write_close , +.Fn archive_write_finish , +or +.Fn archive_write_free . +The client callback can call +.Fn archive_set_error +to provide values that can then be retrieved by +.Fn archive_errno +and +.Fn archive_error_string . +.\" .Sh EXAMPLE +.Sh RETURN VALUES +These functions return +.Cm ARCHIVE_OK +on success, or +.Cm ARCHIVE_FATAL . +.\" +.Sh ERRORS +Detailed error codes and textual descriptions are available from the +.Fn archive_errno +and +.Fn archive_error_string +functions. +.\" +.Sh SEE ALSO +.Xr tar 1 , +.Xr archive_write 3 , +.Xr archive_write_blocksize 3 , +.Xr archive_write_filter 3 , +.Xr archive_write_format 3 , +.Xr archive_write_new 3 , +.Xr archive_write_set_options 3 , +.Xr libarchive 3 , +.Xr cpio 5 , +.Xr mtree 5 , +.Xr tar 5 diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_open_fd.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_open_fd.c new file mode 100644 index 0000000..d5c426c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_open_fd.c @@ -0,0 +1,144 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_open_fd.c 201093 2009-12-28 02:28:44Z kientzle $"); + +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_IO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "archive.h" + +struct write_fd_data { + int fd; +}; + +static int file_close(struct archive *, void *); +static int file_open(struct archive *, void *); +static ssize_t file_write(struct archive *, void *, const void *buff, size_t); + +int +archive_write_open_fd(struct archive *a, int fd) +{ + struct write_fd_data *mine; + + mine = (struct write_fd_data *)malloc(sizeof(*mine)); + if (mine == NULL) { + archive_set_error(a, ENOMEM, "No memory"); + return (ARCHIVE_FATAL); + } + mine->fd = fd; +#if defined(__CYGWIN__) || defined(_WIN32) + setmode(mine->fd, O_BINARY); +#endif + return (archive_write_open(a, mine, + file_open, file_write, file_close)); +} + +static int +file_open(struct archive *a, void *client_data) +{ + struct write_fd_data *mine; + struct stat st; + + mine = (struct write_fd_data *)client_data; + + if (fstat(mine->fd, &st) != 0) { + archive_set_error(a, errno, "Couldn't stat fd %d", mine->fd); + return (ARCHIVE_FATAL); + } + + /* + * If this is a regular file, don't add it to itself. + */ + if (S_ISREG(st.st_mode)) + archive_write_set_skip_file(a, st.st_dev, st.st_ino); + + /* + * If client hasn't explicitly set the last block handling, + * then set it here. + */ + if (archive_write_get_bytes_in_last_block(a) < 0) { + /* If the output is a block or character device, fifo, + * or stdout, pad the last block, otherwise leave it + * unpadded. */ + if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode) || + S_ISFIFO(st.st_mode) || (mine->fd == 1)) + /* Last block will be fully padded. */ + archive_write_set_bytes_in_last_block(a, 0); + else + archive_write_set_bytes_in_last_block(a, 1); + } + + return (ARCHIVE_OK); +} + +static ssize_t +file_write(struct archive *a, void *client_data, const void *buff, size_t length) +{ + struct write_fd_data *mine; + ssize_t bytesWritten; + + mine = (struct write_fd_data *)client_data; + for (;;) { + bytesWritten = write(mine->fd, buff, length); + if (bytesWritten <= 0) { + if (errno == EINTR) + continue; + archive_set_error(a, errno, "Write error"); + return (-1); + } + return (bytesWritten); + } +} + +static int +file_close(struct archive *a, void *client_data) +{ + struct write_fd_data *mine = (struct write_fd_data *)client_data; + + (void)a; /* UNUSED */ + free(mine); + return (ARCHIVE_OK); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_open_file.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_open_file.c new file mode 100644 index 0000000..f6b1412 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_open_file.c @@ -0,0 +1,109 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_open_file.c,v 1.19 2007/01/09 08:05:56 kientzle Exp $"); + +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "archive.h" + +struct write_FILE_data { + FILE *f; +}; + +static int file_close(struct archive *, void *); +static int file_open(struct archive *, void *); +static ssize_t file_write(struct archive *, void *, const void *buff, size_t); + +int +archive_write_open_FILE(struct archive *a, FILE *f) +{ + struct write_FILE_data *mine; + + mine = (struct write_FILE_data *)malloc(sizeof(*mine)); + if (mine == NULL) { + archive_set_error(a, ENOMEM, "No memory"); + return (ARCHIVE_FATAL); + } + mine->f = f; + return (archive_write_open(a, mine, + file_open, file_write, file_close)); +} + +static int +file_open(struct archive *a, void *client_data) +{ + (void)a; /* UNUSED */ + (void)client_data; /* UNUSED */ + + return (ARCHIVE_OK); +} + +static ssize_t +file_write(struct archive *a, void *client_data, const void *buff, size_t length) +{ + struct write_FILE_data *mine; + size_t bytesWritten; + + mine = client_data; + for (;;) { + bytesWritten = fwrite(buff, 1, length, mine->f); + if (bytesWritten <= 0) { + if (errno == EINTR) + continue; + archive_set_error(a, errno, "Write error"); + return (-1); + } + return (bytesWritten); + } +} + +static int +file_close(struct archive *a, void *client_data) +{ + struct write_FILE_data *mine = client_data; + + (void)a; /* UNUSED */ + free(mine); + return (ARCHIVE_OK); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_open_filename.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_open_filename.c new file mode 100644 index 0000000..66e0dfe --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_open_filename.c @@ -0,0 +1,253 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_open_filename.c 191165 2009-04-17 00:39:35Z kientzle $"); + +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_string.h" + +#ifndef O_BINARY +#define O_BINARY 0 +#endif +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + +struct write_file_data { + int fd; + struct archive_mstring filename; +}; + +static int file_close(struct archive *, void *); +static int file_open(struct archive *, void *); +static ssize_t file_write(struct archive *, void *, const void *buff, size_t); +static int open_filename(struct archive *, int, const void *); + +int +archive_write_open_file(struct archive *a, const char *filename) +{ + return (archive_write_open_filename(a, filename)); +} + +int +archive_write_open_filename(struct archive *a, const char *filename) +{ + + if (filename == NULL || filename[0] == '\0') + return (archive_write_open_fd(a, 1)); + + return (open_filename(a, 1, filename)); +} + +int +archive_write_open_filename_w(struct archive *a, const wchar_t *filename) +{ + + if (filename == NULL || filename[0] == L'\0') + return (archive_write_open_fd(a, 1)); + + return (open_filename(a, 0, filename)); +} + +static int +open_filename(struct archive *a, int mbs_fn, const void *filename) +{ + struct write_file_data *mine; + int r; + + mine = (struct write_file_data *)calloc(1, sizeof(*mine)); + if (mine == NULL) { + archive_set_error(a, ENOMEM, "No memory"); + return (ARCHIVE_FATAL); + } + if (mbs_fn) + r = archive_mstring_copy_mbs(&mine->filename, filename); + else + r = archive_mstring_copy_wcs(&mine->filename, filename); + if (r < 0) { + if (errno == ENOMEM) { + archive_set_error(a, ENOMEM, "No memory"); + return (ARCHIVE_FATAL); + } + if (mbs_fn) + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Can't convert '%s' to WCS", + (const char *)filename); + else + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Can't convert '%S' to MBS", + (const wchar_t *)filename); + return (ARCHIVE_FAILED); + } + mine->fd = -1; + return (archive_write_open(a, mine, + file_open, file_write, file_close)); +} + +static int +file_open(struct archive *a, void *client_data) +{ + int flags; + struct write_file_data *mine; + struct stat st; +#if defined(_WIN32) && !defined(__CYGWIN__) + wchar_t *fullpath; +#endif + const wchar_t *wcs; + const char *mbs; + + mine = (struct write_file_data *)client_data; + flags = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_CLOEXEC; + + /* + * Open the file. + */ + mbs = NULL; wcs = NULL; +#if defined(_WIN32) && !defined(__CYGWIN__) + if (archive_mstring_get_wcs(a, &mine->filename, &wcs) != 0) { + if (errno == ENOMEM) + archive_set_error(a, errno, "No memory"); + else { + archive_mstring_get_mbs(a, &mine->filename, &mbs); + archive_set_error(a, errno, + "Can't convert '%s' to WCS", mbs); + } + return (ARCHIVE_FATAL); + } + fullpath = __la_win_permissive_name_w(wcs); + if (fullpath != NULL) { + mine->fd = _wopen(fullpath, flags, 0666); + free(fullpath); + } else + mine->fd = _wopen(wcs, flags, 0666); +#else + if (archive_mstring_get_mbs(a, &mine->filename, &mbs) != 0) { + if (errno == ENOMEM) + archive_set_error(a, errno, "No memory"); + else { + archive_mstring_get_wcs(a, &mine->filename, &wcs); + archive_set_error(a, errno, + "Can't convert '%S' to MBS", wcs); + } + return (ARCHIVE_FATAL); + } + mine->fd = open(mbs, flags, 0666); + __archive_ensure_cloexec_flag(mine->fd); +#endif + if (mine->fd < 0) { + if (mbs != NULL) + archive_set_error(a, errno, "Failed to open '%s'", mbs); + else + archive_set_error(a, errno, "Failed to open '%S'", wcs); + return (ARCHIVE_FATAL); + } + + if (fstat(mine->fd, &st) != 0) { + if (mbs != NULL) + archive_set_error(a, errno, "Couldn't stat '%s'", mbs); + else + archive_set_error(a, errno, "Couldn't stat '%S'", wcs); + return (ARCHIVE_FATAL); + } + + /* + * Set up default last block handling. + */ + if (archive_write_get_bytes_in_last_block(a) < 0) { + if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode) || + S_ISFIFO(st.st_mode)) + /* Pad last block when writing to device or FIFO. */ + archive_write_set_bytes_in_last_block(a, 0); + else + /* Don't pad last block otherwise. */ + archive_write_set_bytes_in_last_block(a, 1); + } + + /* + * If the output file is a regular file, don't add it to + * itself. If it's a device file, it's okay to add the device + * entry to the output archive. + */ + if (S_ISREG(st.st_mode)) + archive_write_set_skip_file(a, st.st_dev, st.st_ino); + + return (ARCHIVE_OK); +} + +static ssize_t +file_write(struct archive *a, void *client_data, const void *buff, + size_t length) +{ + struct write_file_data *mine; + ssize_t bytesWritten; + + mine = (struct write_file_data *)client_data; + for (;;) { + bytesWritten = write(mine->fd, buff, length); + if (bytesWritten <= 0) { + if (errno == EINTR) + continue; + archive_set_error(a, errno, "Write error"); + return (-1); + } + return (bytesWritten); + } +} + +static int +file_close(struct archive *a, void *client_data) +{ + struct write_file_data *mine = (struct write_file_data *)client_data; + + (void)a; /* UNUSED */ + + if (mine->fd >= 0) + close(mine->fd); + + archive_mstring_clean(&mine->filename); + free(mine); + return (ARCHIVE_OK); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_open_memory.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_open_memory.c new file mode 100644 index 0000000..ea6ae0a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_open_memory.c @@ -0,0 +1,113 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_open_memory.c,v 1.3 2007/01/09 08:05:56 kientzle Exp $"); + +#include +#include +#include + +#include "archive.h" + +struct write_memory_data { + size_t used; + size_t size; + size_t * client_size; + unsigned char * buff; +}; + +static int memory_write_close(struct archive *, void *); +static int memory_write_open(struct archive *, void *); +static ssize_t memory_write(struct archive *, void *, const void *buff, size_t); + +/* + * Client provides a pointer to a block of memory to receive + * the data. The 'size' param both tells us the size of the + * client buffer and lets us tell the client the final size. + */ +int +archive_write_open_memory(struct archive *a, void *buff, size_t buffSize, size_t *used) +{ + struct write_memory_data *mine; + + mine = (struct write_memory_data *)calloc(1, sizeof(*mine)); + if (mine == NULL) { + archive_set_error(a, ENOMEM, "No memory"); + return (ARCHIVE_FATAL); + } + mine->buff = buff; + mine->size = buffSize; + mine->client_size = used; + return (archive_write_open(a, mine, + memory_write_open, memory_write, memory_write_close)); +} + +static int +memory_write_open(struct archive *a, void *client_data) +{ + struct write_memory_data *mine; + mine = client_data; + mine->used = 0; + if (mine->client_size != NULL) + *mine->client_size = mine->used; + /* Disable padding if it hasn't been set explicitly. */ + if (-1 == archive_write_get_bytes_in_last_block(a)) + archive_write_set_bytes_in_last_block(a, 1); + return (ARCHIVE_OK); +} + +/* + * Copy the data into the client buffer. + * Note that we update mine->client_size on every write. + * In particular, this means the client can follow exactly + * how much has been written into their buffer at any time. + */ +static ssize_t +memory_write(struct archive *a, void *client_data, const void *buff, size_t length) +{ + struct write_memory_data *mine; + mine = client_data; + + if (mine->used + length > mine->size) { + archive_set_error(a, ENOMEM, "Buffer exhausted"); + return (ARCHIVE_FATAL); + } + memcpy(mine->buff + mine->used, buff, length); + mine->used += length; + if (mine->client_size != NULL) + *mine->client_size = mine->used; + return (length); +} + +static int +memory_write_close(struct archive *a, void *client_data) +{ + struct write_memory_data *mine; + (void)a; /* UNUSED */ + mine = client_data; + free(mine); + return (ARCHIVE_OK); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_private.h b/dependencies/libarchive-3.4.2/libarchive/archive_write_private.h new file mode 100644 index 0000000..27cba03 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_private.h @@ -0,0 +1,164 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: head/lib/libarchive/archive_write_private.h 201155 2009-12-29 05:20:12Z kientzle $ + */ + +#ifndef ARCHIVE_WRITE_PRIVATE_H_INCLUDED +#define ARCHIVE_WRITE_PRIVATE_H_INCLUDED + +#ifndef __LIBARCHIVE_BUILD +#ifndef __LIBARCHIVE_TEST +#error This header is only to be used internally to libarchive. +#endif +#endif + +#include "archive.h" +#include "archive_string.h" +#include "archive_private.h" + +#define ARCHIVE_WRITE_FILTER_STATE_NEW 1U +#define ARCHIVE_WRITE_FILTER_STATE_OPEN 2U +#define ARCHIVE_WRITE_FILTER_STATE_CLOSED 4U +#define ARCHIVE_WRITE_FILTER_STATE_FATAL 0x8000U + +struct archive_write; + +struct archive_write_filter { + int64_t bytes_written; + struct archive *archive; /* Associated archive. */ + struct archive_write_filter *next_filter; /* Who I write to. */ + int (*options)(struct archive_write_filter *, + const char *key, const char *value); + int (*open)(struct archive_write_filter *); + int (*write)(struct archive_write_filter *, const void *, size_t); + int (*close)(struct archive_write_filter *); + int (*free)(struct archive_write_filter *); + void *data; + const char *name; + int code; + int bytes_per_block; + int bytes_in_last_block; + int state; +}; + +#if ARCHIVE_VERSION < 4000000 +void __archive_write_filters_free(struct archive *); +#endif + +struct archive_write_filter *__archive_write_allocate_filter(struct archive *); + +int __archive_write_output(struct archive_write *, const void *, size_t); +int __archive_write_nulls(struct archive_write *, size_t); +int __archive_write_filter(struct archive_write_filter *, const void *, size_t); + +struct archive_write { + struct archive archive; + + /* Dev/ino of the archive being written. */ + int skip_file_set; + int64_t skip_file_dev; + int64_t skip_file_ino; + + /* Utility: Pointer to a block of nulls. */ + const unsigned char *nulls; + size_t null_length; + + /* Callbacks to open/read/write/close archive stream. */ + archive_open_callback *client_opener; + archive_write_callback *client_writer; + archive_close_callback *client_closer; + void *client_data; + + /* + * Blocking information. Note that bytes_in_last_block is + * misleadingly named; I should find a better name. These + * control the final output from all compressors, including + * compression_none. + */ + int bytes_per_block; + int bytes_in_last_block; + + /* + * First and last write filters in the pipeline. + */ + struct archive_write_filter *filter_first; + struct archive_write_filter *filter_last; + + /* + * Pointers to format-specific functions for writing. They're + * initialized by archive_write_set_format_XXX() calls. + */ + void *format_data; + const char *format_name; + int (*format_init)(struct archive_write *); + int (*format_options)(struct archive_write *, + const char *key, const char *value); + int (*format_finish_entry)(struct archive_write *); + int (*format_write_header)(struct archive_write *, + struct archive_entry *); + ssize_t (*format_write_data)(struct archive_write *, + const void *buff, size_t); + int (*format_close)(struct archive_write *); + int (*format_free)(struct archive_write *); + + + /* + * Encryption passphrase. + */ + char *passphrase; + archive_passphrase_callback *passphrase_callback; + void *passphrase_client_data; +}; + +/* + * Utility function to format a USTAR header into a buffer. If + * "strict" is set, this tries to create the absolutely most portable + * version of a ustar header. If "strict" is set to 0, then it will + * relax certain requirements. + * + * Generally, format-specific declarations don't belong in this + * header; this is a rare example of a function that is shared by + * two very similar formats (ustar and pax). + */ +int +__archive_write_format_header_ustar(struct archive_write *, char buff[512], + struct archive_entry *, int tartype, int strict, + struct archive_string_conv *); + +struct archive_write_program_data; +struct archive_write_program_data * __archive_write_program_allocate(const char *program_name); +int __archive_write_program_free(struct archive_write_program_data *); +int __archive_write_program_open(struct archive_write_filter *, + struct archive_write_program_data *, const char *); +int __archive_write_program_close(struct archive_write_filter *, + struct archive_write_program_data *); +int __archive_write_program_write(struct archive_write_filter *, + struct archive_write_program_data *, const void *, size_t); + +/* + * Get a encryption passphrase. + */ +const char * __archive_write_get_passphrase(struct archive_write *a); +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format.c new file mode 100644 index 0000000..12de080 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format.c @@ -0,0 +1,123 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format.c 201168 2009-12-29 06:15:32Z kientzle $"); + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_ERRNO_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_write_set_format_private.h" + +/* A table that maps format codes to functions. */ +static const +struct { int code; int (*setter)(struct archive *); } codes[] = +{ + { ARCHIVE_FORMAT_7ZIP, archive_write_set_format_7zip }, + { ARCHIVE_FORMAT_CPIO, archive_write_set_format_cpio }, + { ARCHIVE_FORMAT_CPIO_POSIX, archive_write_set_format_cpio }, + { ARCHIVE_FORMAT_CPIO_SVR4_NOCRC, archive_write_set_format_cpio_newc }, + { ARCHIVE_FORMAT_ISO9660, archive_write_set_format_iso9660 }, + { ARCHIVE_FORMAT_MTREE, archive_write_set_format_mtree }, + { ARCHIVE_FORMAT_RAW, archive_write_set_format_raw }, + { ARCHIVE_FORMAT_SHAR, archive_write_set_format_shar }, + { ARCHIVE_FORMAT_SHAR_BASE, archive_write_set_format_shar }, + { ARCHIVE_FORMAT_SHAR_DUMP, archive_write_set_format_shar_dump }, + { ARCHIVE_FORMAT_TAR, archive_write_set_format_pax_restricted }, + { ARCHIVE_FORMAT_TAR_GNUTAR, archive_write_set_format_gnutar }, + { ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE, archive_write_set_format_pax }, + { ARCHIVE_FORMAT_TAR_PAX_RESTRICTED, + archive_write_set_format_pax_restricted }, + { ARCHIVE_FORMAT_TAR_USTAR, archive_write_set_format_ustar }, + { ARCHIVE_FORMAT_WARC, archive_write_set_format_warc }, + { ARCHIVE_FORMAT_XAR, archive_write_set_format_xar }, + { ARCHIVE_FORMAT_ZIP, archive_write_set_format_zip }, + { 0, NULL } +}; + +int +archive_write_set_format(struct archive *a, int code) +{ + int i; + + for (i = 0; codes[i].code != 0; i++) { + if (code == codes[i].code) + return ((codes[i].setter)(a)); + } + + archive_set_error(a, EINVAL, "No such format"); + return (ARCHIVE_FATAL); +} + +void +__archive_write_entry_filetype_unsupported(struct archive *a, + struct archive_entry *entry, const char *format) +{ + char *name = NULL; + + switch (archive_entry_filetype(entry)) { + /* + * All formats should be able to archive regular files (AE_IFREG) + */ + case AE_IFDIR: + name = "directories"; + break; + case AE_IFLNK: + name = "symbolic links"; + break; + case AE_IFCHR: + name = "character devices"; + break; + case AE_IFBLK: + name = "block devices"; + break; + case AE_IFIFO: + name = "named pipes"; + break; + case AE_IFSOCK: + name = "sockets"; + break; + default: + break; + } + + if (name != NULL) { + archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, + "%s: %s format cannot archive %s", + archive_entry_pathname(entry), format, name); + } else { + archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, + "%s: %s format cannot archive files with mode 0%lo", + archive_entry_pathname(entry), format, + (unsigned long)archive_entry_mode(entry)); + } +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_7zip.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_7zip.c new file mode 100644 index 0000000..fb7697f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_7zip.c @@ -0,0 +1,2317 @@ +/*- + * Copyright (c) 2011-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_BZLIB_H +#include +#endif +#if HAVE_LZMA_H +#include +#endif +#ifdef HAVE_ZLIB_H +#include +#endif + +#include "archive.h" +#ifndef HAVE_ZLIB_H +#include "archive_crc32.h" +#endif +#include "archive_endian.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_ppmd7_private.h" +#include "archive_private.h" +#include "archive_rb.h" +#include "archive_string.h" +#include "archive_write_private.h" +#include "archive_write_set_format_private.h" + +/* + * Codec ID + */ +#define _7Z_COPY 0 +#define _7Z_LZMA1 0x030101 +#define _7Z_LZMA2 0x21 +#define _7Z_DEFLATE 0x040108 +#define _7Z_BZIP2 0x040202 +#define _7Z_PPMD 0x030401 + +/* + * 7-Zip header property IDs. + */ +#define kEnd 0x00 +#define kHeader 0x01 +#define kArchiveProperties 0x02 +#define kAdditionalStreamsInfo 0x03 +#define kMainStreamsInfo 0x04 +#define kFilesInfo 0x05 +#define kPackInfo 0x06 +#define kUnPackInfo 0x07 +#define kSubStreamsInfo 0x08 +#define kSize 0x09 +#define kCRC 0x0A +#define kFolder 0x0B +#define kCodersUnPackSize 0x0C +#define kNumUnPackStream 0x0D +#define kEmptyStream 0x0E +#define kEmptyFile 0x0F +#define kAnti 0x10 +#define kName 0x11 +#define kCTime 0x12 +#define kATime 0x13 +#define kMTime 0x14 +#define kAttributes 0x15 +#define kEncodedHeader 0x17 + +enum la_zaction { + ARCHIVE_Z_FINISH, + ARCHIVE_Z_RUN +}; + +/* + * A stream object of universal compressor. + */ +struct la_zstream { + const uint8_t *next_in; + size_t avail_in; + uint64_t total_in; + + uint8_t *next_out; + size_t avail_out; + uint64_t total_out; + + uint32_t prop_size; + uint8_t *props; + + int valid; + void *real_stream; + int (*code) (struct archive *a, + struct la_zstream *lastrm, + enum la_zaction action); + int (*end)(struct archive *a, + struct la_zstream *lastrm); +}; + +#define PPMD7_DEFAULT_ORDER 6 +#define PPMD7_DEFAULT_MEM_SIZE (1 << 24) + +struct ppmd_stream { + int stat; + CPpmd7 ppmd7_context; + CPpmd7z_RangeEnc range_enc; + IByteOut byteout; + uint8_t *buff; + uint8_t *buff_ptr; + uint8_t *buff_end; + size_t buff_bytes; +}; + +struct coder { + unsigned codec; + size_t prop_size; + uint8_t *props; +}; + +struct file { + struct archive_rb_node rbnode; + + struct file *next; + unsigned name_len; + uint8_t *utf16name;/* UTF16-LE name. */ + uint64_t size; + unsigned flg; +#define MTIME_IS_SET (1<<0) +#define ATIME_IS_SET (1<<1) +#define CTIME_IS_SET (1<<2) +#define CRC32_IS_SET (1<<3) +#define HAS_STREAM (1<<4) + + struct { + time_t time; + long time_ns; + } times[3]; +#define MTIME 0 +#define ATIME 1 +#define CTIME 2 + + mode_t mode; + uint32_t crc32; + + signed int dir:1; +}; + +struct _7zip { + int temp_fd; + uint64_t temp_offset; + + struct file *cur_file; + size_t total_number_entry; + size_t total_number_nonempty_entry; + size_t total_number_empty_entry; + size_t total_number_dir_entry; + size_t total_bytes_entry_name; + size_t total_number_time_defined[3]; + uint64_t total_bytes_compressed; + uint64_t total_bytes_uncompressed; + uint64_t entry_bytes_remaining; + uint32_t entry_crc32; + uint32_t precode_crc32; + uint32_t encoded_crc32; + int crc32flg; +#define PRECODE_CRC32 1 +#define ENCODED_CRC32 2 + + unsigned opt_compression; + int opt_compression_level; + + struct la_zstream stream; + struct coder coder; + + struct archive_string_conv *sconv; + + /* + * Compressed data buffer. + */ + unsigned char wbuff[512 * 20 * 6]; + size_t wbuff_remaining; + + /* + * The list of the file entries which has its contents is used to + * manage struct file objects. + * We use 'next' (a member of struct file) to chain. + */ + struct { + struct file *first; + struct file **last; + } file_list, empty_list; + struct archive_rb_tree rbtree;/* for empty files */ +}; + +static int _7z_options(struct archive_write *, + const char *, const char *); +static int _7z_write_header(struct archive_write *, + struct archive_entry *); +static ssize_t _7z_write_data(struct archive_write *, + const void *, size_t); +static int _7z_finish_entry(struct archive_write *); +static int _7z_close(struct archive_write *); +static int _7z_free(struct archive_write *); +static int file_cmp_node(const struct archive_rb_node *, + const struct archive_rb_node *); +static int file_cmp_key(const struct archive_rb_node *, const void *); +static int file_new(struct archive_write *a, struct archive_entry *, + struct file **); +static void file_free(struct file *); +static void file_register(struct _7zip *, struct file *); +static void file_register_empty(struct _7zip *, struct file *); +static void file_init_register(struct _7zip *); +static void file_init_register_empty(struct _7zip *); +static void file_free_register(struct _7zip *); +static ssize_t compress_out(struct archive_write *, const void *, size_t , + enum la_zaction); +static int compression_init_encoder_copy(struct archive *, + struct la_zstream *); +static int compression_code_copy(struct archive *, + struct la_zstream *, enum la_zaction); +static int compression_end_copy(struct archive *, struct la_zstream *); +static int compression_init_encoder_deflate(struct archive *, + struct la_zstream *, int, int); +#ifdef HAVE_ZLIB_H +static int compression_code_deflate(struct archive *, + struct la_zstream *, enum la_zaction); +static int compression_end_deflate(struct archive *, struct la_zstream *); +#endif +static int compression_init_encoder_bzip2(struct archive *, + struct la_zstream *, int); +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) +static int compression_code_bzip2(struct archive *, + struct la_zstream *, enum la_zaction); +static int compression_end_bzip2(struct archive *, struct la_zstream *); +#endif +static int compression_init_encoder_lzma1(struct archive *, + struct la_zstream *, int); +static int compression_init_encoder_lzma2(struct archive *, + struct la_zstream *, int); +#if defined(HAVE_LZMA_H) +static int compression_code_lzma(struct archive *, + struct la_zstream *, enum la_zaction); +static int compression_end_lzma(struct archive *, struct la_zstream *); +#endif +static int compression_init_encoder_ppmd(struct archive *, + struct la_zstream *, unsigned, uint32_t); +static int compression_code_ppmd(struct archive *, + struct la_zstream *, enum la_zaction); +static int compression_end_ppmd(struct archive *, struct la_zstream *); +static int _7z_compression_init_encoder(struct archive_write *, unsigned, + int); +static int compression_code(struct archive *, + struct la_zstream *, enum la_zaction); +static int compression_end(struct archive *, + struct la_zstream *); +static int enc_uint64(struct archive_write *, uint64_t); +static int make_header(struct archive_write *, uint64_t, uint64_t, + uint64_t, int, struct coder *); +static int make_streamsInfo(struct archive_write *, uint64_t, uint64_t, + uint64_t, int, struct coder *, int, uint32_t); + +int +archive_write_set_format_7zip(struct archive *_a) +{ + static const struct archive_rb_tree_ops rb_ops = { + file_cmp_node, file_cmp_key + }; + struct archive_write *a = (struct archive_write *)_a; + struct _7zip *zip; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_set_format_7zip"); + + /* If another format was already registered, unregister it. */ + if (a->format_free != NULL) + (a->format_free)(a); + + zip = calloc(1, sizeof(*zip)); + if (zip == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate 7-Zip data"); + return (ARCHIVE_FATAL); + } + zip->temp_fd = -1; + __archive_rb_tree_init(&(zip->rbtree), &rb_ops); + file_init_register(zip); + file_init_register_empty(zip); + + /* Set default compression type and its level. */ +#if HAVE_LZMA_H + zip->opt_compression = _7Z_LZMA1; +#elif defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) + zip->opt_compression = _7Z_BZIP2; +#elif defined(HAVE_ZLIB_H) + zip->opt_compression = _7Z_DEFLATE; +#else + zip->opt_compression = _7Z_COPY; +#endif + zip->opt_compression_level = 6; + + a->format_data = zip; + + a->format_name = "7zip"; + a->format_options = _7z_options; + a->format_write_header = _7z_write_header; + a->format_write_data = _7z_write_data; + a->format_finish_entry = _7z_finish_entry; + a->format_close = _7z_close; + a->format_free = _7z_free; + a->archive.archive_format = ARCHIVE_FORMAT_7ZIP; + a->archive.archive_format_name = "7zip"; + + return (ARCHIVE_OK); +} + +static int +_7z_options(struct archive_write *a, const char *key, const char *value) +{ + struct _7zip *zip; + + zip = (struct _7zip *)a->format_data; + + if (strcmp(key, "compression") == 0) { + const char *name = NULL; + + if (value == NULL || strcmp(value, "copy") == 0 || + strcmp(value, "COPY") == 0 || + strcmp(value, "store") == 0 || + strcmp(value, "STORE") == 0) + zip->opt_compression = _7Z_COPY; + else if (strcmp(value, "deflate") == 0 || + strcmp(value, "DEFLATE") == 0) +#if HAVE_ZLIB_H + zip->opt_compression = _7Z_DEFLATE; +#else + name = "deflate"; +#endif + else if (strcmp(value, "bzip2") == 0 || + strcmp(value, "BZIP2") == 0) +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) + zip->opt_compression = _7Z_BZIP2; +#else + name = "bzip2"; +#endif + else if (strcmp(value, "lzma1") == 0 || + strcmp(value, "LZMA1") == 0) +#if HAVE_LZMA_H + zip->opt_compression = _7Z_LZMA1; +#else + name = "lzma1"; +#endif + else if (strcmp(value, "lzma2") == 0 || + strcmp(value, "LZMA2") == 0) +#if HAVE_LZMA_H + zip->opt_compression = _7Z_LZMA2; +#else + name = "lzma2"; +#endif + else if (strcmp(value, "ppmd") == 0 || + strcmp(value, "PPMD") == 0 || + strcmp(value, "PPMd") == 0) + zip->opt_compression = _7Z_PPMD; + else { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Unknown compression name: `%s'", + value); + return (ARCHIVE_FAILED); + } + if (name != NULL) { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "`%s' compression not supported " + "on this platform", + name); + return (ARCHIVE_FAILED); + } + return (ARCHIVE_OK); + } + if (strcmp(key, "compression-level") == 0) { + if (value == NULL || + !(value[0] >= '0' && value[0] <= '9') || + value[1] != '\0') { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Illegal value `%s'", + value); + return (ARCHIVE_FAILED); + } + zip->opt_compression_level = value[0] - '0'; + return (ARCHIVE_OK); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +static int +_7z_write_header(struct archive_write *a, struct archive_entry *entry) +{ + struct _7zip *zip; + struct file *file; + int r; + + zip = (struct _7zip *)a->format_data; + zip->cur_file = NULL; + zip->entry_bytes_remaining = 0; + + if (zip->sconv == NULL) { + zip->sconv = archive_string_conversion_to_charset( + &a->archive, "UTF-16LE", 1); + if (zip->sconv == NULL) + return (ARCHIVE_FATAL); + } + + r = file_new(a, entry, &file); + if (r < ARCHIVE_WARN) { + if (file != NULL) + file_free(file); + return (r); + } + if (file->size == 0 && file->dir) { + if (!__archive_rb_tree_insert_node(&(zip->rbtree), + (struct archive_rb_node *)file)) { + /* We have already had the same file. */ + file_free(file); + return (ARCHIVE_OK); + } + } + + if (file->flg & MTIME_IS_SET) + zip->total_number_time_defined[MTIME]++; + if (file->flg & CTIME_IS_SET) + zip->total_number_time_defined[CTIME]++; + if (file->flg & ATIME_IS_SET) + zip->total_number_time_defined[ATIME]++; + + zip->total_number_entry++; + zip->total_bytes_entry_name += file->name_len + 2; + if (file->size == 0) { + /* Count up the number of empty files. */ + zip->total_number_empty_entry++; + if (file->dir) + zip->total_number_dir_entry++; + else + file_register_empty(zip, file); + return (r); + } + + /* + * Init compression. + */ + if ((zip->total_number_entry - zip->total_number_empty_entry) == 1) { + r = _7z_compression_init_encoder(a, zip->opt_compression, + zip->opt_compression_level); + if (r < 0) { + file_free(file); + return (ARCHIVE_FATAL); + } + } + + /* Register a non-empty file. */ + file_register(zip, file); + + /* + * Set the current file to cur_file to read its contents. + */ + zip->cur_file = file; + + + /* Save a offset of current file in temporary file. */ + zip->entry_bytes_remaining = file->size; + zip->entry_crc32 = 0; + + /* + * Store a symbolic link name as file contents. + */ + if (archive_entry_filetype(entry) == AE_IFLNK) { + ssize_t bytes; + const void *p = (const void *)archive_entry_symlink(entry); + bytes = compress_out(a, p, (size_t)file->size, ARCHIVE_Z_RUN); + if (bytes < 0) + return ((int)bytes); + zip->entry_crc32 = crc32(zip->entry_crc32, p, (unsigned)bytes); + zip->entry_bytes_remaining -= bytes; + } + + return (r); +} + +/* + * Write data to a temporary file. + */ +static int +write_to_temp(struct archive_write *a, const void *buff, size_t s) +{ + struct _7zip *zip; + const unsigned char *p; + ssize_t ws; + + zip = (struct _7zip *)a->format_data; + + /* + * Open a temporary file. + */ + if (zip->temp_fd == -1) { + zip->temp_offset = 0; + zip->temp_fd = __archive_mktemp(NULL); + if (zip->temp_fd < 0) { + archive_set_error(&a->archive, errno, + "Couldn't create temporary file"); + return (ARCHIVE_FATAL); + } + } + + p = (const unsigned char *)buff; + while (s) { + ws = write(zip->temp_fd, p, s); + if (ws < 0) { + archive_set_error(&(a->archive), errno, + "fwrite function failed"); + return (ARCHIVE_FATAL); + } + s -= ws; + p += ws; + zip->temp_offset += ws; + } + return (ARCHIVE_OK); +} + +static ssize_t +compress_out(struct archive_write *a, const void *buff, size_t s, + enum la_zaction run) +{ + struct _7zip *zip = (struct _7zip *)a->format_data; + int r; + + if (run == ARCHIVE_Z_FINISH && zip->stream.total_in == 0 && s == 0) + return (0); + + if ((zip->crc32flg & PRECODE_CRC32) && s) + zip->precode_crc32 = crc32(zip->precode_crc32, buff, + (unsigned)s); + zip->stream.next_in = (const unsigned char *)buff; + zip->stream.avail_in = s; + for (;;) { + /* Compress file data. */ + r = compression_code(&(a->archive), &(zip->stream), run); + if (r != ARCHIVE_OK && r != ARCHIVE_EOF) + return (ARCHIVE_FATAL); + if (zip->stream.avail_out == 0) { + if (write_to_temp(a, zip->wbuff, sizeof(zip->wbuff)) + != ARCHIVE_OK) + return (ARCHIVE_FATAL); + zip->stream.next_out = zip->wbuff; + zip->stream.avail_out = sizeof(zip->wbuff); + if (zip->crc32flg & ENCODED_CRC32) + zip->encoded_crc32 = crc32(zip->encoded_crc32, + zip->wbuff, sizeof(zip->wbuff)); + if (run == ARCHIVE_Z_FINISH && r != ARCHIVE_EOF) + continue; + } + if (zip->stream.avail_in == 0) + break; + } + if (run == ARCHIVE_Z_FINISH) { + uint64_t bytes = sizeof(zip->wbuff) - zip->stream.avail_out; + if (write_to_temp(a, zip->wbuff, (size_t)bytes) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + if ((zip->crc32flg & ENCODED_CRC32) && bytes) + zip->encoded_crc32 = crc32(zip->encoded_crc32, + zip->wbuff, (unsigned)bytes); + } + + return (s); +} + +static ssize_t +_7z_write_data(struct archive_write *a, const void *buff, size_t s) +{ + struct _7zip *zip; + ssize_t bytes; + + zip = (struct _7zip *)a->format_data; + + if (s > zip->entry_bytes_remaining) + s = (size_t)zip->entry_bytes_remaining; + if (s == 0 || zip->cur_file == NULL) + return (0); + bytes = compress_out(a, buff, s, ARCHIVE_Z_RUN); + if (bytes < 0) + return (bytes); + zip->entry_crc32 = crc32(zip->entry_crc32, buff, (unsigned)bytes); + zip->entry_bytes_remaining -= bytes; + return (bytes); +} + +static int +_7z_finish_entry(struct archive_write *a) +{ + struct _7zip *zip; + size_t s; + ssize_t r; + + zip = (struct _7zip *)a->format_data; + if (zip->cur_file == NULL) + return (ARCHIVE_OK); + + while (zip->entry_bytes_remaining > 0) { + s = (size_t)zip->entry_bytes_remaining; + if (s > a->null_length) + s = a->null_length; + r = _7z_write_data(a, a->nulls, s); + if (r < 0) + return ((int)r); + } + zip->total_bytes_compressed += zip->stream.total_in; + zip->total_bytes_uncompressed += zip->stream.total_out; + zip->cur_file->crc32 = zip->entry_crc32; + zip->cur_file = NULL; + + return (ARCHIVE_OK); +} + +static int +flush_wbuff(struct archive_write *a) +{ + struct _7zip *zip; + int r; + size_t s; + + zip = (struct _7zip *)a->format_data; + s = sizeof(zip->wbuff) - zip->wbuff_remaining; + r = __archive_write_output(a, zip->wbuff, s); + if (r != ARCHIVE_OK) + return (r); + zip->wbuff_remaining = sizeof(zip->wbuff); + return (r); +} + +static int +copy_out(struct archive_write *a, uint64_t offset, uint64_t length) +{ + struct _7zip *zip; + int r; + + zip = (struct _7zip *)a->format_data; + if (zip->temp_offset > 0 && + lseek(zip->temp_fd, offset, SEEK_SET) < 0) { + archive_set_error(&(a->archive), errno, "lseek failed"); + return (ARCHIVE_FATAL); + } + while (length) { + size_t rsize; + ssize_t rs; + unsigned char *wb; + + if (length > zip->wbuff_remaining) + rsize = zip->wbuff_remaining; + else + rsize = (size_t)length; + wb = zip->wbuff + (sizeof(zip->wbuff) - zip->wbuff_remaining); + rs = read(zip->temp_fd, wb, rsize); + if (rs < 0) { + archive_set_error(&(a->archive), errno, + "Can't read temporary file(%jd)", + (intmax_t)rs); + return (ARCHIVE_FATAL); + } + if (rs == 0) { + archive_set_error(&(a->archive), 0, + "Truncated 7-Zip archive"); + return (ARCHIVE_FATAL); + } + zip->wbuff_remaining -= rs; + length -= rs; + if (zip->wbuff_remaining == 0) { + r = flush_wbuff(a); + if (r != ARCHIVE_OK) + return (r); + } + } + return (ARCHIVE_OK); +} + +static int +_7z_close(struct archive_write *a) +{ + struct _7zip *zip; + unsigned char *wb; + uint64_t header_offset, header_size, header_unpacksize; + uint64_t length; + uint32_t header_crc32; + int r; + + zip = (struct _7zip *)a->format_data; + + if (zip->total_number_entry > 0) { + struct archive_rb_node *n; + uint64_t data_offset, data_size, data_unpacksize; + unsigned header_compression; + + r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH); + if (r < 0) + return (r); + data_offset = 0; + data_size = zip->stream.total_out; + data_unpacksize = zip->stream.total_in; + zip->coder.codec = zip->opt_compression; + zip->coder.prop_size = zip->stream.prop_size; + zip->coder.props = zip->stream.props; + zip->stream.prop_size = 0; + zip->stream.props = NULL; + zip->total_number_nonempty_entry = + zip->total_number_entry - zip->total_number_empty_entry; + + /* Connect an empty file list. */ + if (zip->empty_list.first != NULL) { + *zip->file_list.last = zip->empty_list.first; + zip->file_list.last = zip->empty_list.last; + } + /* Connect a directory file list. */ + ARCHIVE_RB_TREE_FOREACH(n, &(zip->rbtree)) { + file_register(zip, (struct file *)n); + } + + /* + * NOTE: 7z command supports just LZMA1, LZMA2 and COPY for + * the compression type for encoding the header. + */ +#if HAVE_LZMA_H + header_compression = _7Z_LZMA1; + /* If the stored file is only one, do not encode the header. + * This is the same way 7z command does. */ + if (zip->total_number_entry == 1) + header_compression = _7Z_COPY; +#else + header_compression = _7Z_COPY; +#endif + r = _7z_compression_init_encoder(a, header_compression, 6); + if (r < 0) + return (r); + zip->crc32flg = PRECODE_CRC32; + zip->precode_crc32 = 0; + r = make_header(a, data_offset, data_size, data_unpacksize, + 1, &(zip->coder)); + if (r < 0) + return (r); + r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH); + if (r < 0) + return (r); + header_offset = data_offset + data_size; + header_size = zip->stream.total_out; + header_crc32 = zip->precode_crc32; + header_unpacksize = zip->stream.total_in; + + if (header_compression != _7Z_COPY) { + /* + * Encode the header in order to reduce the size + * of the archive. + */ + free(zip->coder.props); + zip->coder.codec = header_compression; + zip->coder.prop_size = zip->stream.prop_size; + zip->coder.props = zip->stream.props; + zip->stream.prop_size = 0; + zip->stream.props = NULL; + + r = _7z_compression_init_encoder(a, _7Z_COPY, 0); + if (r < 0) + return (r); + zip->crc32flg = ENCODED_CRC32; + zip->encoded_crc32 = 0; + + /* + * Make EncodedHeader. + */ + r = enc_uint64(a, kEncodedHeader); + if (r < 0) + return (r); + r = make_streamsInfo(a, header_offset, header_size, + header_unpacksize, 1, &(zip->coder), 0, + header_crc32); + if (r < 0) + return (r); + r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH); + if (r < 0) + return (r); + header_offset = header_offset + header_size; + header_size = zip->stream.total_out; + header_crc32 = zip->encoded_crc32; + } + zip->crc32flg = 0; + } else { + header_offset = header_size = 0; + header_crc32 = 0; + } + + length = zip->temp_offset; + + /* + * Make the zip header on wbuff(write buffer). + */ + wb = zip->wbuff; + zip->wbuff_remaining = sizeof(zip->wbuff); + memcpy(&wb[0], "7z\xBC\xAF\x27\x1C", 6); + wb[6] = 0;/* Major version. */ + wb[7] = 3;/* Minor version. */ + archive_le64enc(&wb[12], header_offset);/* Next Header Offset */ + archive_le64enc(&wb[20], header_size);/* Next Header Size */ + archive_le32enc(&wb[28], header_crc32);/* Next Header CRC */ + archive_le32enc(&wb[8], crc32(0, &wb[12], 20));/* Start Header CRC */ + zip->wbuff_remaining -= 32; + + /* + * Read all file contents and an encoded header from the temporary + * file and write out it. + */ + r = copy_out(a, 0, length); + if (r != ARCHIVE_OK) + return (r); + r = flush_wbuff(a); + return (r); +} + +/* + * Encode 64 bits value into 7-Zip's encoded UINT64 value. + */ +static int +enc_uint64(struct archive_write *a, uint64_t val) +{ + unsigned mask = 0x80; + uint8_t numdata[9]; + int i; + + numdata[0] = 0; + for (i = 1; i < (int)sizeof(numdata); i++) { + if (val < mask) { + numdata[0] |= (uint8_t)val; + break; + } + numdata[i] = (uint8_t)val; + val >>= 8; + numdata[0] |= mask; + mask >>= 1; + } + return ((int)compress_out(a, numdata, i, ARCHIVE_Z_RUN)); +} + +static int +make_substreamsInfo(struct archive_write *a, struct coder *coders) +{ + struct _7zip *zip = (struct _7zip *)a->format_data; + struct file *file; + int r; + + /* + * Make SubStreamsInfo. + */ + r = enc_uint64(a, kSubStreamsInfo); + if (r < 0) + return (r); + + if (zip->total_number_nonempty_entry > 1 && coders->codec != _7Z_COPY) { + /* + * Make NumUnPackStream. + */ + r = enc_uint64(a, kNumUnPackStream); + if (r < 0) + return (r); + + /* Write numUnpackStreams */ + r = enc_uint64(a, zip->total_number_nonempty_entry); + if (r < 0) + return (r); + + /* + * Make kSize. + */ + r = enc_uint64(a, kSize); + if (r < 0) + return (r); + file = zip->file_list.first; + for (;file != NULL; file = file->next) { + if (file->next == NULL || + file->next->size == 0) + break; + r = enc_uint64(a, file->size); + if (r < 0) + return (r); + } + } + + /* + * Make CRC. + */ + r = enc_uint64(a, kCRC); + if (r < 0) + return (r); + + + /* All are defined */ + r = enc_uint64(a, 1); + if (r < 0) + return (r); + file = zip->file_list.first; + for (;file != NULL; file = file->next) { + uint8_t crc[4]; + if (file->size == 0) + break; + archive_le32enc(crc, file->crc32); + r = (int)compress_out(a, crc, 4, ARCHIVE_Z_RUN); + if (r < 0) + return (r); + } + + /* Write End. */ + r = enc_uint64(a, kEnd); + if (r < 0) + return (r); + return (ARCHIVE_OK); +} + +static int +make_streamsInfo(struct archive_write *a, uint64_t offset, uint64_t pack_size, + uint64_t unpack_size, int num_coder, struct coder *coders, int substrm, + uint32_t header_crc) +{ + struct _7zip *zip = (struct _7zip *)a->format_data; + uint8_t codec_buff[8]; + int numFolders, fi; + int codec_size; + int i, r; + + if (coders->codec == _7Z_COPY) + numFolders = (int)zip->total_number_nonempty_entry; + else + numFolders = 1; + + /* + * Make PackInfo. + */ + r = enc_uint64(a, kPackInfo); + if (r < 0) + return (r); + + /* Write PackPos. */ + r = enc_uint64(a, offset); + if (r < 0) + return (r); + + /* Write NumPackStreams. */ + r = enc_uint64(a, numFolders); + if (r < 0) + return (r); + + /* Make Size. */ + r = enc_uint64(a, kSize); + if (r < 0) + return (r); + + if (numFolders > 1) { + struct file *file = zip->file_list.first; + for (;file != NULL; file = file->next) { + if (file->size == 0) + break; + r = enc_uint64(a, file->size); + if (r < 0) + return (r); + } + } else { + /* Write size. */ + r = enc_uint64(a, pack_size); + if (r < 0) + return (r); + } + + r = enc_uint64(a, kEnd); + if (r < 0) + return (r); + + /* + * Make UnPackInfo. + */ + r = enc_uint64(a, kUnPackInfo); + if (r < 0) + return (r); + + /* + * Make Folder. + */ + r = enc_uint64(a, kFolder); + if (r < 0) + return (r); + + /* Write NumFolders. */ + r = enc_uint64(a, numFolders); + if (r < 0) + return (r); + + /* Write External. */ + r = enc_uint64(a, 0); + if (r < 0) + return (r); + + for (fi = 0; fi < numFolders; fi++) { + /* Write NumCoders. */ + r = enc_uint64(a, num_coder); + if (r < 0) + return (r); + + for (i = 0; i < num_coder; i++) { + unsigned codec_id = coders[i].codec; + + /* Write Codec flag. */ + archive_be64enc(codec_buff, codec_id); + for (codec_size = 8; codec_size > 0; codec_size--) { + if (codec_buff[8 - codec_size]) + break; + } + if (codec_size == 0) + codec_size = 1; + if (coders[i].prop_size) + r = enc_uint64(a, codec_size | 0x20); + else + r = enc_uint64(a, codec_size); + if (r < 0) + return (r); + + /* Write Codec ID. */ + codec_size &= 0x0f; + r = (int)compress_out(a, &codec_buff[8-codec_size], + codec_size, ARCHIVE_Z_RUN); + if (r < 0) + return (r); + + if (coders[i].prop_size) { + /* Write Codec property size. */ + r = enc_uint64(a, coders[i].prop_size); + if (r < 0) + return (r); + + /* Write Codec properties. */ + r = (int)compress_out(a, coders[i].props, + coders[i].prop_size, ARCHIVE_Z_RUN); + if (r < 0) + return (r); + } + } + } + + /* + * Make CodersUnPackSize. + */ + r = enc_uint64(a, kCodersUnPackSize); + if (r < 0) + return (r); + + if (numFolders > 1) { + struct file *file = zip->file_list.first; + for (;file != NULL; file = file->next) { + if (file->size == 0) + break; + r = enc_uint64(a, file->size); + if (r < 0) + return (r); + } + + } else { + /* Write UnPackSize. */ + r = enc_uint64(a, unpack_size); + if (r < 0) + return (r); + } + + if (!substrm) { + uint8_t crc[4]; + /* + * Make CRC. + */ + r = enc_uint64(a, kCRC); + if (r < 0) + return (r); + + /* All are defined */ + r = enc_uint64(a, 1); + if (r < 0) + return (r); + archive_le32enc(crc, header_crc); + r = (int)compress_out(a, crc, 4, ARCHIVE_Z_RUN); + if (r < 0) + return (r); + } + + /* Write End. */ + r = enc_uint64(a, kEnd); + if (r < 0) + return (r); + + if (substrm) { + /* + * Make SubStreamsInfo. + */ + r = make_substreamsInfo(a, coders); + if (r < 0) + return (r); + } + + + /* Write End. */ + r = enc_uint64(a, kEnd); + if (r < 0) + return (r); + + return (ARCHIVE_OK); +} + + +#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) +static uint64_t +utcToFiletime(time_t t, long ns) +{ + uint64_t fileTime; + + fileTime = t; + fileTime *= 10000000; + fileTime += ns / 100; + fileTime += EPOC_TIME; + return (fileTime); +} + +static int +make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti) +{ + uint8_t filetime[8]; + struct _7zip *zip = (struct _7zip *)a->format_data; + struct file *file; + int r; + uint8_t b, mask; + + /* + * Make Time Bools. + */ + if (zip->total_number_time_defined[ti] == zip->total_number_entry) { + /* Write Time Type. */ + r = enc_uint64(a, type); + if (r < 0) + return (r); + /* Write EmptyStream Size. */ + r = enc_uint64(a, 2 + zip->total_number_entry * 8); + if (r < 0) + return (r); + /* All are defined. */ + r = enc_uint64(a, 1); + if (r < 0) + return (r); + } else { + if (zip->total_number_time_defined[ti] == 0) + return (ARCHIVE_OK); + + /* Write Time Type. */ + r = enc_uint64(a, type); + if (r < 0) + return (r); + /* Write EmptyStream Size. */ + r = enc_uint64(a, 2 + ((zip->total_number_entry + 7) >> 3) + + zip->total_number_time_defined[ti] * 8); + if (r < 0) + return (r); + + /* All are not defined. */ + r = enc_uint64(a, 0); + if (r < 0) + return (r); + + b = 0; + mask = 0x80; + file = zip->file_list.first; + for (;file != NULL; file = file->next) { + if (file->flg & flg) + b |= mask; + mask >>= 1; + if (mask == 0) { + r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN); + if (r < 0) + return (r); + mask = 0x80; + b = 0; + } + } + if (mask != 0x80) { + r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN); + if (r < 0) + return (r); + } + } + + /* External. */ + r = enc_uint64(a, 0); + if (r < 0) + return (r); + + + /* + * Make Times. + */ + file = zip->file_list.first; + for (;file != NULL; file = file->next) { + if ((file->flg & flg) == 0) + continue; + archive_le64enc(filetime, utcToFiletime(file->times[ti].time, + file->times[ti].time_ns)); + r = (int)compress_out(a, filetime, 8, ARCHIVE_Z_RUN); + if (r < 0) + return (r); + } + + return (ARCHIVE_OK); +} + +static int +make_header(struct archive_write *a, uint64_t offset, uint64_t pack_size, + uint64_t unpack_size, int codernum, struct coder *coders) +{ + struct _7zip *zip = (struct _7zip *)a->format_data; + struct file *file; + int r; + uint8_t b, mask; + + /* + * Make FilesInfo. + */ + r = enc_uint64(a, kHeader); + if (r < 0) + return (r); + + /* + * If there are empty files only, do not write MainStreamInfo. + */ + if (zip->total_number_nonempty_entry) { + /* + * Make MainStreamInfo. + */ + r = enc_uint64(a, kMainStreamsInfo); + if (r < 0) + return (r); + r = make_streamsInfo(a, offset, pack_size, unpack_size, + codernum, coders, 1, 0); + if (r < 0) + return (r); + } + + /* + * Make FilesInfo. + */ + r = enc_uint64(a, kFilesInfo); + if (r < 0) + return (r); + + /* Write numFiles. */ + r = enc_uint64(a, zip->total_number_entry); + if (r < 0) + return (r); + + if (zip->total_number_empty_entry > 0) { + /* Make EmptyStream. */ + r = enc_uint64(a, kEmptyStream); + if (r < 0) + return (r); + + /* Write EmptyStream Size. */ + r = enc_uint64(a, (zip->total_number_entry+7)>>3); + if (r < 0) + return (r); + + b = 0; + mask = 0x80; + file = zip->file_list.first; + for (;file != NULL; file = file->next) { + if (file->size == 0) + b |= mask; + mask >>= 1; + if (mask == 0) { + r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN); + if (r < 0) + return (r); + mask = 0x80; + b = 0; + } + } + if (mask != 0x80) { + r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN); + if (r < 0) + return (r); + } + } + + if (zip->total_number_empty_entry > zip->total_number_dir_entry) { + /* Make EmptyFile. */ + r = enc_uint64(a, kEmptyFile); + if (r < 0) + return (r); + + /* Write EmptyFile Size. */ + r = enc_uint64(a, (zip->total_number_empty_entry + 7) >> 3); + if (r < 0) + return (r); + + b = 0; + mask = 0x80; + file = zip->file_list.first; + for (;file != NULL; file = file->next) { + if (file->size) + continue; + if (!file->dir) + b |= mask; + mask >>= 1; + if (mask == 0) { + r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN); + if (r < 0) + return (r); + mask = 0x80; + b = 0; + } + } + if (mask != 0x80) { + r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN); + if (r < 0) + return (r); + } + } + + /* Make Name. */ + r = enc_uint64(a, kName); + if (r < 0) + return (r); + + /* Write Name size. */ + r = enc_uint64(a, zip->total_bytes_entry_name+1); + if (r < 0) + return (r); + + /* Write dmy byte. */ + r = enc_uint64(a, 0); + if (r < 0) + return (r); + + file = zip->file_list.first; + for (;file != NULL; file = file->next) { + r = (int)compress_out(a, file->utf16name, file->name_len+2, + ARCHIVE_Z_RUN); + if (r < 0) + return (r); + } + + /* Make MTime. */ + r = make_time(a, kMTime, MTIME_IS_SET, MTIME); + if (r < 0) + return (r); + + /* Make CTime. */ + r = make_time(a, kCTime, CTIME_IS_SET, CTIME); + if (r < 0) + return (r); + + /* Make ATime. */ + r = make_time(a, kATime, ATIME_IS_SET, ATIME); + if (r < 0) + return (r); + + /* Make Attributes. */ + r = enc_uint64(a, kAttributes); + if (r < 0) + return (r); + + /* Write Attributes size. */ + r = enc_uint64(a, 2 + zip->total_number_entry * 4); + if (r < 0) + return (r); + + /* Write "All Are Defined". */ + r = enc_uint64(a, 1); + if (r < 0) + return (r); + + /* Write dmy byte. */ + r = enc_uint64(a, 0); + if (r < 0) + return (r); + + file = zip->file_list.first; + for (;file != NULL; file = file->next) { + /* + * High 16bits is unix mode. + * Low 16bits is Windows attributes. + */ + uint32_t encattr, attr; + if (file->dir) + attr = 0x8010; + else + attr = 0x8020; + if ((file->mode & 0222) == 0) + attr |= 1;/* Read Only. */ + attr |= ((uint32_t)file->mode) << 16; + archive_le32enc(&encattr, attr); + r = (int)compress_out(a, &encattr, 4, ARCHIVE_Z_RUN); + if (r < 0) + return (r); + } + + /* Write End. */ + r = enc_uint64(a, kEnd); + if (r < 0) + return (r); + + /* Write End. */ + r = enc_uint64(a, kEnd); + if (r < 0) + return (r); + + return (ARCHIVE_OK); +} + + +static int +_7z_free(struct archive_write *a) +{ + struct _7zip *zip = (struct _7zip *)a->format_data; + + /* Close the temporary file. */ + if (zip->temp_fd >= 0) + close(zip->temp_fd); + + file_free_register(zip); + compression_end(&(a->archive), &(zip->stream)); + free(zip->coder.props); + free(zip); + + return (ARCHIVE_OK); +} + +static int +file_cmp_node(const struct archive_rb_node *n1, + const struct archive_rb_node *n2) +{ + const struct file *f1 = (const struct file *)n1; + const struct file *f2 = (const struct file *)n2; + + if (f1->name_len == f2->name_len) + return (memcmp(f1->utf16name, f2->utf16name, f1->name_len)); + return (f1->name_len > f2->name_len)?1:-1; +} + +static int +file_cmp_key(const struct archive_rb_node *n, const void *key) +{ + const struct file *f = (const struct file *)n; + + return (f->name_len - *(const char *)key); +} + +static int +file_new(struct archive_write *a, struct archive_entry *entry, + struct file **newfile) +{ + struct _7zip *zip; + struct file *file; + const char *u16; + size_t u16len; + int ret = ARCHIVE_OK; + + zip = (struct _7zip *)a->format_data; + *newfile = NULL; + + file = calloc(1, sizeof(*file)); + if (file == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + + if (0 > archive_entry_pathname_l(entry, &u16, &u16len, zip->sconv)) { + if (errno == ENOMEM) { + free(file); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for UTF-16LE"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "A filename cannot be converted to UTF-16LE;" + "You should disable making Joliet extension"); + ret = ARCHIVE_WARN; + } + file->utf16name = malloc(u16len + 2); + if (file->utf16name == NULL) { + free(file); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Name"); + return (ARCHIVE_FATAL); + } + memcpy(file->utf16name, u16, u16len); + file->utf16name[u16len+0] = 0; + file->utf16name[u16len+1] = 0; + file->name_len = (unsigned)u16len; + file->mode = archive_entry_mode(entry); + if (archive_entry_filetype(entry) == AE_IFREG) + file->size = archive_entry_size(entry); + else + archive_entry_set_size(entry, 0); + if (archive_entry_filetype(entry) == AE_IFDIR) + file->dir = 1; + else if (archive_entry_filetype(entry) == AE_IFLNK) + file->size = strlen(archive_entry_symlink(entry)); + if (archive_entry_mtime_is_set(entry)) { + file->flg |= MTIME_IS_SET; + file->times[MTIME].time = archive_entry_mtime(entry); + file->times[MTIME].time_ns = archive_entry_mtime_nsec(entry); + } + if (archive_entry_atime_is_set(entry)) { + file->flg |= ATIME_IS_SET; + file->times[ATIME].time = archive_entry_atime(entry); + file->times[ATIME].time_ns = archive_entry_atime_nsec(entry); + } + if (archive_entry_ctime_is_set(entry)) { + file->flg |= CTIME_IS_SET; + file->times[CTIME].time = archive_entry_ctime(entry); + file->times[CTIME].time_ns = archive_entry_ctime_nsec(entry); + } + + *newfile = file; + return (ret); +} + +static void +file_free(struct file *file) +{ + free(file->utf16name); + free(file); +} + +static void +file_register(struct _7zip *zip, struct file *file) +{ + file->next = NULL; + *zip->file_list.last = file; + zip->file_list.last = &(file->next); +} + +static void +file_init_register(struct _7zip *zip) +{ + zip->file_list.first = NULL; + zip->file_list.last = &(zip->file_list.first); +} + +static void +file_free_register(struct _7zip *zip) +{ + struct file *file, *file_next; + + file = zip->file_list.first; + while (file != NULL) { + file_next = file->next; + file_free(file); + file = file_next; + } +} + +static void +file_register_empty(struct _7zip *zip, struct file *file) +{ + file->next = NULL; + *zip->empty_list.last = file; + zip->empty_list.last = &(file->next); +} + +static void +file_init_register_empty(struct _7zip *zip) +{ + zip->empty_list.first = NULL; + zip->empty_list.last = &(zip->empty_list.first); +} + +#if !defined(HAVE_ZLIB_H) || !defined(HAVE_BZLIB_H) ||\ + !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H) +static int +compression_unsupported_encoder(struct archive *a, + struct la_zstream *lastrm, const char *name) +{ + + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "%s compression not supported on this platform", name); + lastrm->valid = 0; + lastrm->real_stream = NULL; + return (ARCHIVE_FAILED); +} +#endif + +/* + * _7_COPY compressor. + */ +static int +compression_init_encoder_copy(struct archive *a, struct la_zstream *lastrm) +{ + + if (lastrm->valid) + compression_end(a, lastrm); + lastrm->valid = 1; + lastrm->code = compression_code_copy; + lastrm->end = compression_end_copy; + return (ARCHIVE_OK); +} + +static int +compression_code_copy(struct archive *a, + struct la_zstream *lastrm, enum la_zaction action) +{ + size_t bytes; + + (void)a; /* UNUSED */ + if (lastrm->avail_out > lastrm->avail_in) + bytes = lastrm->avail_in; + else + bytes = lastrm->avail_out; + if (bytes) { + memcpy(lastrm->next_out, lastrm->next_in, bytes); + lastrm->next_in += bytes; + lastrm->avail_in -= bytes; + lastrm->total_in += bytes; + lastrm->next_out += bytes; + lastrm->avail_out -= bytes; + lastrm->total_out += bytes; + } + if (action == ARCHIVE_Z_FINISH && lastrm->avail_in == 0) + return (ARCHIVE_EOF); + return (ARCHIVE_OK); +} + +static int +compression_end_copy(struct archive *a, struct la_zstream *lastrm) +{ + (void)a; /* UNUSED */ + lastrm->valid = 0; + return (ARCHIVE_OK); +} + +/* + * _7_DEFLATE compressor. + */ +#ifdef HAVE_ZLIB_H +static int +compression_init_encoder_deflate(struct archive *a, + struct la_zstream *lastrm, int level, int withheader) +{ + z_stream *strm; + + if (lastrm->valid) + compression_end(a, lastrm); + strm = calloc(1, sizeof(*strm)); + if (strm == NULL) { + archive_set_error(a, ENOMEM, + "Can't allocate memory for gzip stream"); + return (ARCHIVE_FATAL); + } + /* zlib.h is not const-correct, so we need this one bit + * of ugly hackery to convert a const * pointer to + * a non-const pointer. */ + strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in; + strm->avail_in = (uInt)lastrm->avail_in; + strm->total_in = (uLong)lastrm->total_in; + strm->next_out = lastrm->next_out; + strm->avail_out = (uInt)lastrm->avail_out; + strm->total_out = (uLong)lastrm->total_out; + if (deflateInit2(strm, level, Z_DEFLATED, + (withheader)?15:-15, + 8, Z_DEFAULT_STRATEGY) != Z_OK) { + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Internal error initializing compression library"); + return (ARCHIVE_FATAL); + } + lastrm->real_stream = strm; + lastrm->valid = 1; + lastrm->code = compression_code_deflate; + lastrm->end = compression_end_deflate; + return (ARCHIVE_OK); +} + +static int +compression_code_deflate(struct archive *a, + struct la_zstream *lastrm, enum la_zaction action) +{ + z_stream *strm; + int r; + + strm = (z_stream *)lastrm->real_stream; + /* zlib.h is not const-correct, so we need this one bit + * of ugly hackery to convert a const * pointer to + * a non-const pointer. */ + strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in; + strm->avail_in = (uInt)lastrm->avail_in; + strm->total_in = (uLong)lastrm->total_in; + strm->next_out = lastrm->next_out; + strm->avail_out = (uInt)lastrm->avail_out; + strm->total_out = (uLong)lastrm->total_out; + r = deflate(strm, + (action == ARCHIVE_Z_FINISH)? Z_FINISH: Z_NO_FLUSH); + lastrm->next_in = strm->next_in; + lastrm->avail_in = strm->avail_in; + lastrm->total_in = strm->total_in; + lastrm->next_out = strm->next_out; + lastrm->avail_out = strm->avail_out; + lastrm->total_out = strm->total_out; + switch (r) { + case Z_OK: + return (ARCHIVE_OK); + case Z_STREAM_END: + return (ARCHIVE_EOF); + default: + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "GZip compression failed:" + " deflate() call returned status %d", r); + return (ARCHIVE_FATAL); + } +} + +static int +compression_end_deflate(struct archive *a, struct la_zstream *lastrm) +{ + z_stream *strm; + int r; + + strm = (z_stream *)lastrm->real_stream; + r = deflateEnd(strm); + free(strm); + lastrm->real_stream = NULL; + lastrm->valid = 0; + if (r != Z_OK) { + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Failed to clean up compressor"); + return (ARCHIVE_FATAL); + } + return (ARCHIVE_OK); +} +#else +static int +compression_init_encoder_deflate(struct archive *a, + struct la_zstream *lastrm, int level, int withheader) +{ + + (void) level; /* UNUSED */ + (void) withheader; /* UNUSED */ + if (lastrm->valid) + compression_end(a, lastrm); + return (compression_unsupported_encoder(a, lastrm, "deflate")); +} +#endif + +/* + * _7_BZIP2 compressor. + */ +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) +static int +compression_init_encoder_bzip2(struct archive *a, + struct la_zstream *lastrm, int level) +{ + bz_stream *strm; + + if (lastrm->valid) + compression_end(a, lastrm); + strm = calloc(1, sizeof(*strm)); + if (strm == NULL) { + archive_set_error(a, ENOMEM, + "Can't allocate memory for bzip2 stream"); + return (ARCHIVE_FATAL); + } + /* bzlib.h is not const-correct, so we need this one bit + * of ugly hackery to convert a const * pointer to + * a non-const pointer. */ + strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in; + strm->avail_in = lastrm->avail_in; + strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff); + strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32); + strm->next_out = (char *)lastrm->next_out; + strm->avail_out = lastrm->avail_out; + strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff); + strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32); + if (BZ2_bzCompressInit(strm, level, 0, 30) != BZ_OK) { + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Internal error initializing compression library"); + return (ARCHIVE_FATAL); + } + lastrm->real_stream = strm; + lastrm->valid = 1; + lastrm->code = compression_code_bzip2; + lastrm->end = compression_end_bzip2; + return (ARCHIVE_OK); +} + +static int +compression_code_bzip2(struct archive *a, + struct la_zstream *lastrm, enum la_zaction action) +{ + bz_stream *strm; + int r; + + strm = (bz_stream *)lastrm->real_stream; + /* bzlib.h is not const-correct, so we need this one bit + * of ugly hackery to convert a const * pointer to + * a non-const pointer. */ + strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in; + strm->avail_in = lastrm->avail_in; + strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff); + strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32); + strm->next_out = (char *)lastrm->next_out; + strm->avail_out = lastrm->avail_out; + strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff); + strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32); + r = BZ2_bzCompress(strm, + (action == ARCHIVE_Z_FINISH)? BZ_FINISH: BZ_RUN); + lastrm->next_in = (const unsigned char *)strm->next_in; + lastrm->avail_in = strm->avail_in; + lastrm->total_in = + (((uint64_t)(uint32_t)strm->total_in_hi32) << 32) + + (uint64_t)(uint32_t)strm->total_in_lo32; + lastrm->next_out = (unsigned char *)strm->next_out; + lastrm->avail_out = strm->avail_out; + lastrm->total_out = + (((uint64_t)(uint32_t)strm->total_out_hi32) << 32) + + (uint64_t)(uint32_t)strm->total_out_lo32; + switch (r) { + case BZ_RUN_OK: /* Non-finishing */ + case BZ_FINISH_OK: /* Finishing: There's more work to do */ + return (ARCHIVE_OK); + case BZ_STREAM_END: /* Finishing: all done */ + /* Only occurs in finishing case */ + return (ARCHIVE_EOF); + default: + /* Any other return value indicates an error */ + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Bzip2 compression failed:" + " BZ2_bzCompress() call returned status %d", r); + return (ARCHIVE_FATAL); + } +} + +static int +compression_end_bzip2(struct archive *a, struct la_zstream *lastrm) +{ + bz_stream *strm; + int r; + + strm = (bz_stream *)lastrm->real_stream; + r = BZ2_bzCompressEnd(strm); + free(strm); + lastrm->real_stream = NULL; + lastrm->valid = 0; + if (r != BZ_OK) { + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Failed to clean up compressor"); + return (ARCHIVE_FATAL); + } + return (ARCHIVE_OK); +} + +#else +static int +compression_init_encoder_bzip2(struct archive *a, + struct la_zstream *lastrm, int level) +{ + + (void) level; /* UNUSED */ + if (lastrm->valid) + compression_end(a, lastrm); + return (compression_unsupported_encoder(a, lastrm, "bzip2")); +} +#endif + +/* + * _7_LZMA1, _7_LZMA2 compressor. + */ +#if defined(HAVE_LZMA_H) +static int +compression_init_encoder_lzma(struct archive *a, + struct la_zstream *lastrm, int level, uint64_t filter_id) +{ + static const lzma_stream lzma_init_data = LZMA_STREAM_INIT; + lzma_stream *strm; + lzma_filter *lzmafilters; + lzma_options_lzma lzma_opt; + int r; + + if (lastrm->valid) + compression_end(a, lastrm); + strm = calloc(1, sizeof(*strm) + sizeof(*lzmafilters) * 2); + if (strm == NULL) { + archive_set_error(a, ENOMEM, + "Can't allocate memory for lzma stream"); + return (ARCHIVE_FATAL); + } + lzmafilters = (lzma_filter *)(strm+1); + if (level > 6) + level = 6; + if (lzma_lzma_preset(&lzma_opt, level)) { + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ENOMEM, + "Internal error initializing compression library"); + return (ARCHIVE_FATAL); + } + lzmafilters[0].id = filter_id; + lzmafilters[0].options = &lzma_opt; + lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */ + + r = lzma_properties_size(&(lastrm->prop_size), lzmafilters); + if (r != LZMA_OK) { + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "lzma_properties_size failed"); + return (ARCHIVE_FATAL); + } + if (lastrm->prop_size) { + lastrm->props = malloc(lastrm->prop_size); + if (lastrm->props == NULL) { + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ENOMEM, + "Cannot allocate memory"); + return (ARCHIVE_FATAL); + } + r = lzma_properties_encode(lzmafilters, lastrm->props); + if (r != LZMA_OK) { + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "lzma_properties_encode failed"); + return (ARCHIVE_FATAL); + } + } + + *strm = lzma_init_data; + r = lzma_raw_encoder(strm, lzmafilters); + switch (r) { + case LZMA_OK: + lastrm->real_stream = strm; + lastrm->valid = 1; + lastrm->code = compression_code_lzma; + lastrm->end = compression_end_lzma; + r = ARCHIVE_OK; + break; + case LZMA_MEM_ERROR: + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ENOMEM, + "Internal error initializing compression library: " + "Cannot allocate memory"); + r = ARCHIVE_FATAL; + break; + default: + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Internal error initializing compression library: " + "It's a bug in liblzma"); + r = ARCHIVE_FATAL; + break; + } + return (r); +} + +static int +compression_init_encoder_lzma1(struct archive *a, + struct la_zstream *lastrm, int level) +{ + return compression_init_encoder_lzma(a, lastrm, level, + LZMA_FILTER_LZMA1); +} + +static int +compression_init_encoder_lzma2(struct archive *a, + struct la_zstream *lastrm, int level) +{ + return compression_init_encoder_lzma(a, lastrm, level, + LZMA_FILTER_LZMA2); +} + +static int +compression_code_lzma(struct archive *a, + struct la_zstream *lastrm, enum la_zaction action) +{ + lzma_stream *strm; + int r; + + strm = (lzma_stream *)lastrm->real_stream; + strm->next_in = lastrm->next_in; + strm->avail_in = lastrm->avail_in; + strm->total_in = lastrm->total_in; + strm->next_out = lastrm->next_out; + strm->avail_out = lastrm->avail_out; + strm->total_out = lastrm->total_out; + r = lzma_code(strm, + (action == ARCHIVE_Z_FINISH)? LZMA_FINISH: LZMA_RUN); + lastrm->next_in = strm->next_in; + lastrm->avail_in = strm->avail_in; + lastrm->total_in = strm->total_in; + lastrm->next_out = strm->next_out; + lastrm->avail_out = strm->avail_out; + lastrm->total_out = strm->total_out; + switch (r) { + case LZMA_OK: + /* Non-finishing case */ + return (ARCHIVE_OK); + case LZMA_STREAM_END: + /* This return can only occur in finishing case. */ + return (ARCHIVE_EOF); + case LZMA_MEMLIMIT_ERROR: + archive_set_error(a, ENOMEM, + "lzma compression error:" + " %ju MiB would have been needed", + (uintmax_t)((lzma_memusage(strm) + 1024 * 1024 -1) + / (1024 * 1024))); + return (ARCHIVE_FATAL); + default: + /* Any other return value indicates an error */ + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "lzma compression failed:" + " lzma_code() call returned status %d", r); + return (ARCHIVE_FATAL); + } +} + +static int +compression_end_lzma(struct archive *a, struct la_zstream *lastrm) +{ + lzma_stream *strm; + + (void)a; /* UNUSED */ + strm = (lzma_stream *)lastrm->real_stream; + lzma_end(strm); + free(strm); + lastrm->valid = 0; + lastrm->real_stream = NULL; + return (ARCHIVE_OK); +} +#else +static int +compression_init_encoder_lzma1(struct archive *a, + struct la_zstream *lastrm, int level) +{ + + (void) level; /* UNUSED */ + if (lastrm->valid) + compression_end(a, lastrm); + return (compression_unsupported_encoder(a, lastrm, "lzma")); +} +static int +compression_init_encoder_lzma2(struct archive *a, + struct la_zstream *lastrm, int level) +{ + + (void) level; /* UNUSED */ + if (lastrm->valid) + compression_end(a, lastrm); + return (compression_unsupported_encoder(a, lastrm, "lzma")); +} +#endif + +/* + * _7_PPMD compressor. + */ +static void +ppmd_write(void *p, Byte b) +{ + struct archive_write *a = ((IByteOut *)p)->a; + struct _7zip *zip = (struct _7zip *)(a->format_data); + struct la_zstream *lastrm = &(zip->stream); + struct ppmd_stream *strm; + + if (lastrm->avail_out) { + *lastrm->next_out++ = b; + lastrm->avail_out--; + lastrm->total_out++; + return; + } + strm = (struct ppmd_stream *)lastrm->real_stream; + if (strm->buff_ptr < strm->buff_end) { + *strm->buff_ptr++ = b; + strm->buff_bytes++; + } +} + +static int +compression_init_encoder_ppmd(struct archive *a, + struct la_zstream *lastrm, unsigned maxOrder, uint32_t msize) +{ + struct ppmd_stream *strm; + uint8_t *props; + int r; + + if (lastrm->valid) + compression_end(a, lastrm); + strm = calloc(1, sizeof(*strm)); + if (strm == NULL) { + archive_set_error(a, ENOMEM, + "Can't allocate memory for PPMd"); + return (ARCHIVE_FATAL); + } + strm->buff = malloc(32); + if (strm->buff == NULL) { + free(strm); + archive_set_error(a, ENOMEM, + "Can't allocate memory for PPMd"); + return (ARCHIVE_FATAL); + } + strm->buff_ptr = strm->buff; + strm->buff_end = strm->buff + 32; + + props = malloc(1+4); + if (props == NULL) { + free(strm->buff); + free(strm); + archive_set_error(a, ENOMEM, + "Coludn't allocate memory for PPMd"); + return (ARCHIVE_FATAL); + } + props[0] = maxOrder; + archive_le32enc(props+1, msize); + __archive_ppmd7_functions.Ppmd7_Construct(&strm->ppmd7_context); + r = __archive_ppmd7_functions.Ppmd7_Alloc( + &strm->ppmd7_context, msize); + if (r == 0) { + free(strm->buff); + free(strm); + free(props); + archive_set_error(a, ENOMEM, + "Coludn't allocate memory for PPMd"); + return (ARCHIVE_FATAL); + } + __archive_ppmd7_functions.Ppmd7_Init(&(strm->ppmd7_context), maxOrder); + strm->byteout.a = (struct archive_write *)a; + strm->byteout.Write = ppmd_write; + strm->range_enc.Stream = &(strm->byteout); + __archive_ppmd7_functions.Ppmd7z_RangeEnc_Init(&(strm->range_enc)); + strm->stat = 0; + + lastrm->real_stream = strm; + lastrm->valid = 1; + lastrm->code = compression_code_ppmd; + lastrm->end = compression_end_ppmd; + lastrm->prop_size = 5; + lastrm->props = props; + return (ARCHIVE_OK); +} + +static int +compression_code_ppmd(struct archive *a, + struct la_zstream *lastrm, enum la_zaction action) +{ + struct ppmd_stream *strm; + + (void)a; /* UNUSED */ + + strm = (struct ppmd_stream *)lastrm->real_stream; + + /* Copy encoded data if there are remaining bytes from previous call. */ + if (strm->buff_bytes) { + uint8_t *p = strm->buff_ptr - strm->buff_bytes; + while (lastrm->avail_out && strm->buff_bytes) { + *lastrm->next_out++ = *p++; + lastrm->avail_out--; + lastrm->total_out++; + strm->buff_bytes--; + } + if (strm->buff_bytes) + return (ARCHIVE_OK); + if (strm->stat == 1) + return (ARCHIVE_EOF); + strm->buff_ptr = strm->buff; + } + while (lastrm->avail_in && lastrm->avail_out) { + __archive_ppmd7_functions.Ppmd7_EncodeSymbol( + &(strm->ppmd7_context), &(strm->range_enc), + *lastrm->next_in++); + lastrm->avail_in--; + lastrm->total_in++; + } + if (lastrm->avail_in == 0 && action == ARCHIVE_Z_FINISH) { + __archive_ppmd7_functions.Ppmd7z_RangeEnc_FlushData( + &(strm->range_enc)); + strm->stat = 1; + /* Return EOF if there are no remaining bytes. */ + if (strm->buff_bytes == 0) + return (ARCHIVE_EOF); + } + return (ARCHIVE_OK); +} + +static int +compression_end_ppmd(struct archive *a, struct la_zstream *lastrm) +{ + struct ppmd_stream *strm; + + (void)a; /* UNUSED */ + + strm = (struct ppmd_stream *)lastrm->real_stream; + __archive_ppmd7_functions.Ppmd7_Free(&strm->ppmd7_context); + free(strm->buff); + free(strm); + lastrm->real_stream = NULL; + lastrm->valid = 0; + return (ARCHIVE_OK); +} + +/* + * Universal compressor initializer. + */ +static int +_7z_compression_init_encoder(struct archive_write *a, unsigned compression, + int compression_level) +{ + struct _7zip *zip; + int r; + + zip = (struct _7zip *)a->format_data; + switch (compression) { + case _7Z_DEFLATE: + r = compression_init_encoder_deflate( + &(a->archive), &(zip->stream), + compression_level, 0); + break; + case _7Z_BZIP2: + r = compression_init_encoder_bzip2( + &(a->archive), &(zip->stream), + compression_level); + break; + case _7Z_LZMA1: + r = compression_init_encoder_lzma1( + &(a->archive), &(zip->stream), + compression_level); + break; + case _7Z_LZMA2: + r = compression_init_encoder_lzma2( + &(a->archive), &(zip->stream), + compression_level); + break; + case _7Z_PPMD: + r = compression_init_encoder_ppmd( + &(a->archive), &(zip->stream), + PPMD7_DEFAULT_ORDER, PPMD7_DEFAULT_MEM_SIZE); + break; + case _7Z_COPY: + default: + r = compression_init_encoder_copy( + &(a->archive), &(zip->stream)); + break; + } + if (r == ARCHIVE_OK) { + zip->stream.total_in = 0; + zip->stream.next_out = zip->wbuff; + zip->stream.avail_out = sizeof(zip->wbuff); + zip->stream.total_out = 0; + } + + return (r); +} + +static int +compression_code(struct archive *a, struct la_zstream *lastrm, + enum la_zaction action) +{ + if (lastrm->valid) + return (lastrm->code(a, lastrm, action)); + return (ARCHIVE_OK); +} + +static int +compression_end(struct archive *a, struct la_zstream *lastrm) +{ + if (lastrm->valid) { + lastrm->prop_size = 0; + free(lastrm->props); + lastrm->props = NULL; + return (lastrm->end(a, lastrm)); + } + return (ARCHIVE_OK); +} + + diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_ar.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_ar.c new file mode 100644 index 0000000..fc0de1e --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_ar.c @@ -0,0 +1,570 @@ +/*- + * Copyright (c) 2007 Kai Wang + * Copyright (c) 2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_ar.c 201108 2009-12-28 03:28:21Z kientzle $"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_write_private.h" +#include "archive_write_set_format_private.h" + +struct ar_w { + uint64_t entry_bytes_remaining; + uint64_t entry_padding; + int is_strtab; + int has_strtab; + char wrote_global_header; + char *strtab; +}; + +/* + * Define structure of the "ar" header. + */ +#define AR_name_offset 0 +#define AR_name_size 16 +#define AR_date_offset 16 +#define AR_date_size 12 +#define AR_uid_offset 28 +#define AR_uid_size 6 +#define AR_gid_offset 34 +#define AR_gid_size 6 +#define AR_mode_offset 40 +#define AR_mode_size 8 +#define AR_size_offset 48 +#define AR_size_size 10 +#define AR_fmag_offset 58 +#define AR_fmag_size 2 + +static int archive_write_set_format_ar(struct archive_write *); +static int archive_write_ar_header(struct archive_write *, + struct archive_entry *); +static ssize_t archive_write_ar_data(struct archive_write *, + const void *buff, size_t s); +static int archive_write_ar_free(struct archive_write *); +static int archive_write_ar_close(struct archive_write *); +static int archive_write_ar_finish_entry(struct archive_write *); +static const char *ar_basename(const char *path); +static int format_octal(int64_t v, char *p, int s); +static int format_decimal(int64_t v, char *p, int s); + +int +archive_write_set_format_ar_bsd(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + int r; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_set_format_ar_bsd"); + r = archive_write_set_format_ar(a); + if (r == ARCHIVE_OK) { + a->archive.archive_format = ARCHIVE_FORMAT_AR_BSD; + a->archive.archive_format_name = "ar (BSD)"; + } + return (r); +} + +int +archive_write_set_format_ar_svr4(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + int r; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_set_format_ar_svr4"); + r = archive_write_set_format_ar(a); + if (r == ARCHIVE_OK) { + a->archive.archive_format = ARCHIVE_FORMAT_AR_GNU; + a->archive.archive_format_name = "ar (GNU/SVR4)"; + } + return (r); +} + +/* + * Generic initialization. + */ +static int +archive_write_set_format_ar(struct archive_write *a) +{ + struct ar_w *ar; + + /* If someone else was already registered, unregister them. */ + if (a->format_free != NULL) + (a->format_free)(a); + + ar = (struct ar_w *)calloc(1, sizeof(*ar)); + if (ar == NULL) { + archive_set_error(&a->archive, ENOMEM, "Can't allocate ar data"); + return (ARCHIVE_FATAL); + } + a->format_data = ar; + + a->format_name = "ar"; + a->format_write_header = archive_write_ar_header; + a->format_write_data = archive_write_ar_data; + a->format_close = archive_write_ar_close; + a->format_free = archive_write_ar_free; + a->format_finish_entry = archive_write_ar_finish_entry; + return (ARCHIVE_OK); +} + +static int +archive_write_ar_header(struct archive_write *a, struct archive_entry *entry) +{ + int ret, append_fn; + char buff[60]; + char *ss, *se; + struct ar_w *ar; + const char *pathname; + const char *filename; + int64_t size; + + append_fn = 0; + ar = (struct ar_w *)a->format_data; + ar->is_strtab = 0; + filename = NULL; + size = archive_entry_size(entry); + + + /* + * Reject files with empty name. + */ + pathname = archive_entry_pathname(entry); + if (pathname == NULL || *pathname == '\0') { + archive_set_error(&a->archive, EINVAL, + "Invalid filename"); + return (ARCHIVE_WARN); + } + + /* + * If we are now at the beginning of the archive, + * we need first write the ar global header. + */ + if (!ar->wrote_global_header) { + __archive_write_output(a, "!\n", 8); + ar->wrote_global_header = 1; + } + + memset(buff, ' ', 60); + memcpy(&buff[AR_fmag_offset], "`\n", 2); + + if (strcmp(pathname, "/") == 0 ) { + /* Entry is archive symbol table in GNU format */ + buff[AR_name_offset] = '/'; + goto stat; + } + if (strcmp(pathname, "/SYM64/") == 0) { + /* Entry is archive symbol table in GNU 64-bit format */ + memcpy(buff + AR_name_offset, "/SYM64/", 7); + goto stat; + } + if (strcmp(pathname, "__.SYMDEF") == 0) { + /* Entry is archive symbol table in BSD format */ + memcpy(buff + AR_name_offset, "__.SYMDEF", 9); + goto stat; + } + if (strcmp(pathname, "//") == 0) { + /* + * Entry is archive filename table, inform that we should + * collect strtab in next _data call. + */ + ar->is_strtab = 1; + buff[AR_name_offset] = buff[AR_name_offset + 1] = '/'; + /* + * For archive string table, only ar_size field should + * be set. + */ + goto size; + } + + /* + * Otherwise, entry is a normal archive member. + * Strip leading paths from filenames, if any. + */ + if ((filename = ar_basename(pathname)) == NULL) { + /* Reject filenames with trailing "/" */ + archive_set_error(&a->archive, EINVAL, + "Invalid filename"); + return (ARCHIVE_WARN); + } + + if (a->archive.archive_format == ARCHIVE_FORMAT_AR_GNU) { + /* + * SVR4/GNU variant use a "/" to mark then end of the filename, + * make it possible to have embedded spaces in the filename. + * So, the longest filename here (without extension) is + * actually 15 bytes. + */ + if (strlen(filename) <= 15) { + memcpy(&buff[AR_name_offset], + filename, strlen(filename)); + buff[AR_name_offset + strlen(filename)] = '/'; + } else { + /* + * For filename longer than 15 bytes, GNU variant + * makes use of a string table and instead stores the + * offset of the real filename to in the ar_name field. + * The string table should have been written before. + */ + if (ar->has_strtab <= 0) { + archive_set_error(&a->archive, EINVAL, + "Can't find string table"); + return (ARCHIVE_WARN); + } + + se = (char *)malloc(strlen(filename) + 3); + if (se == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate filename buffer"); + return (ARCHIVE_FATAL); + } + + memcpy(se, filename, strlen(filename)); + strcpy(se + strlen(filename), "/\n"); + + ss = strstr(ar->strtab, se); + free(se); + + if (ss == NULL) { + archive_set_error(&a->archive, EINVAL, + "Invalid string table"); + return (ARCHIVE_WARN); + } + + /* + * GNU variant puts "/" followed by digits into + * ar_name field. These digits indicates the real + * filename string's offset to the string table. + */ + buff[AR_name_offset] = '/'; + if (format_decimal(ss - ar->strtab, + buff + AR_name_offset + 1, + AR_name_size - 1)) { + archive_set_error(&a->archive, ERANGE, + "string table offset too large"); + return (ARCHIVE_WARN); + } + } + } else if (a->archive.archive_format == ARCHIVE_FORMAT_AR_BSD) { + /* + * BSD variant: for any file name which is more than + * 16 chars or contains one or more embedded space(s), the + * string "#1/" followed by the ASCII length of the name is + * put into the ar_name field. The file size (stored in the + * ar_size field) is incremented by the length of the name. + * The name is then written immediately following the + * archive header. + */ + if (strlen(filename) <= 16 && strchr(filename, ' ') == NULL) { + memcpy(&buff[AR_name_offset], filename, strlen(filename)); + buff[AR_name_offset + strlen(filename)] = ' '; + } + else { + memcpy(buff + AR_name_offset, "#1/", 3); + if (format_decimal(strlen(filename), + buff + AR_name_offset + 3, + AR_name_size - 3)) { + archive_set_error(&a->archive, ERANGE, + "File name too long"); + return (ARCHIVE_WARN); + } + append_fn = 1; + size += strlen(filename); + } + } + +stat: + if (format_decimal(archive_entry_mtime(entry), buff + AR_date_offset, AR_date_size)) { + archive_set_error(&a->archive, ERANGE, + "File modification time too large"); + return (ARCHIVE_WARN); + } + if (format_decimal(archive_entry_uid(entry), buff + AR_uid_offset, AR_uid_size)) { + archive_set_error(&a->archive, ERANGE, + "Numeric user ID too large"); + return (ARCHIVE_WARN); + } + if (format_decimal(archive_entry_gid(entry), buff + AR_gid_offset, AR_gid_size)) { + archive_set_error(&a->archive, ERANGE, + "Numeric group ID too large"); + return (ARCHIVE_WARN); + } + if (format_octal(archive_entry_mode(entry), buff + AR_mode_offset, AR_mode_size)) { + archive_set_error(&a->archive, ERANGE, + "Numeric mode too large"); + return (ARCHIVE_WARN); + } + /* + * Sanity Check: A non-pseudo archive member should always be + * a regular file. + */ + if (filename != NULL && archive_entry_filetype(entry) != AE_IFREG) { + archive_set_error(&a->archive, EINVAL, + "Regular file required for non-pseudo member"); + return (ARCHIVE_WARN); + } + +size: + if (format_decimal(size, buff + AR_size_offset, AR_size_size)) { + archive_set_error(&a->archive, ERANGE, + "File size out of range"); + return (ARCHIVE_WARN); + } + + ret = __archive_write_output(a, buff, 60); + if (ret != ARCHIVE_OK) + return (ret); + + ar->entry_bytes_remaining = size; + ar->entry_padding = ar->entry_bytes_remaining % 2; + + if (append_fn > 0) { + ret = __archive_write_output(a, filename, strlen(filename)); + if (ret != ARCHIVE_OK) + return (ret); + ar->entry_bytes_remaining -= strlen(filename); + } + + return (ARCHIVE_OK); +} + +static ssize_t +archive_write_ar_data(struct archive_write *a, const void *buff, size_t s) +{ + struct ar_w *ar; + int ret; + + ar = (struct ar_w *)a->format_data; + if (s > ar->entry_bytes_remaining) + s = (size_t)ar->entry_bytes_remaining; + + if (ar->is_strtab > 0) { + if (ar->has_strtab > 0) { + archive_set_error(&a->archive, EINVAL, + "More than one string tables exist"); + return (ARCHIVE_WARN); + } + + ar->strtab = (char *)malloc(s + 1); + if (ar->strtab == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate strtab buffer"); + return (ARCHIVE_FATAL); + } + memcpy(ar->strtab, buff, s); + ar->strtab[s] = '\0'; + ar->has_strtab = 1; + } + + ret = __archive_write_output(a, buff, s); + if (ret != ARCHIVE_OK) + return (ret); + + ar->entry_bytes_remaining -= s; + return (s); +} + +static int +archive_write_ar_free(struct archive_write *a) +{ + struct ar_w *ar; + + ar = (struct ar_w *)a->format_data; + + if (ar == NULL) + return (ARCHIVE_OK); + + if (ar->has_strtab > 0) { + free(ar->strtab); + ar->strtab = NULL; + } + + free(ar); + a->format_data = NULL; + return (ARCHIVE_OK); +} + +static int +archive_write_ar_close(struct archive_write *a) +{ + struct ar_w *ar; + int ret; + + /* + * If we haven't written anything yet, we need to write + * the ar global header now to make it a valid ar archive. + */ + ar = (struct ar_w *)a->format_data; + if (!ar->wrote_global_header) { + ar->wrote_global_header = 1; + ret = __archive_write_output(a, "!\n", 8); + return (ret); + } + + return (ARCHIVE_OK); +} + +static int +archive_write_ar_finish_entry(struct archive_write *a) +{ + struct ar_w *ar; + int ret; + + ar = (struct ar_w *)a->format_data; + + if (ar->entry_bytes_remaining != 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Entry remaining bytes larger than 0"); + return (ARCHIVE_WARN); + } + + if (ar->entry_padding == 0) { + return (ARCHIVE_OK); + } + + if (ar->entry_padding != 1) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Padding wrong size: %ju should be 1 or 0", + (uintmax_t)ar->entry_padding); + return (ARCHIVE_WARN); + } + + ret = __archive_write_output(a, "\n", 1); + return (ret); +} + +/* + * Format a number into the specified field using base-8. + * NB: This version is slightly different from the one in + * _ustar.c + */ +static int +format_octal(int64_t v, char *p, int s) +{ + int len; + char *h; + + len = s; + h = p; + + /* Octal values can't be negative, so use 0. */ + if (v < 0) { + while (len-- > 0) + *p++ = '0'; + return (-1); + } + + p += s; /* Start at the end and work backwards. */ + do { + *--p = (char)('0' + (v & 7)); + v >>= 3; + } while (--s > 0 && v > 0); + + if (v == 0) { + memmove(h, p, len - s); + p = h + len - s; + while (s-- > 0) + *p++ = ' '; + return (0); + } + /* If it overflowed, fill field with max value. */ + while (len-- > 0) + *p++ = '7'; + + return (-1); +} + +/* + * Format a number into the specified field using base-10. + */ +static int +format_decimal(int64_t v, char *p, int s) +{ + int len; + char *h; + + len = s; + h = p; + + /* Negative values in ar header are meaningless, so use 0. */ + if (v < 0) { + while (len-- > 0) + *p++ = '0'; + return (-1); + } + + p += s; + do { + *--p = (char)('0' + (v % 10)); + v /= 10; + } while (--s > 0 && v > 0); + + if (v == 0) { + memmove(h, p, len - s); + p = h + len - s; + while (s-- > 0) + *p++ = ' '; + return (0); + } + /* If it overflowed, fill field with max value. */ + while (len-- > 0) + *p++ = '9'; + + return (-1); +} + +static const char * +ar_basename(const char *path) +{ + const char *endp, *startp; + + endp = path + strlen(path) - 1; + /* + * For filename with trailing slash(es), we return + * NULL indicating an error. + */ + if (*endp == '/') + return (NULL); + + /* Find the start of the base */ + startp = endp; + while (startp > path && *(startp - 1) != '/') + startp--; + + return (startp); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_by_name.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_by_name.c new file mode 100644 index 0000000..86e8621 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_by_name.c @@ -0,0 +1,92 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_by_name.c 201168 2009-12-29 06:15:32Z kientzle $"); + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" + +/* A table that maps names to functions. */ +static const +struct { const char *name; int (*setter)(struct archive *); } names[] = +{ + { "7zip", archive_write_set_format_7zip }, + { "ar", archive_write_set_format_ar_bsd }, + { "arbsd", archive_write_set_format_ar_bsd }, + { "argnu", archive_write_set_format_ar_svr4 }, + { "arsvr4", archive_write_set_format_ar_svr4 }, + { "bsdtar", archive_write_set_format_pax_restricted }, + { "cd9660", archive_write_set_format_iso9660 }, + { "cpio", archive_write_set_format_cpio }, + { "gnutar", archive_write_set_format_gnutar }, + { "iso", archive_write_set_format_iso9660 }, + { "iso9660", archive_write_set_format_iso9660 }, + { "mtree", archive_write_set_format_mtree }, + { "mtree-classic", archive_write_set_format_mtree_classic }, + { "newc", archive_write_set_format_cpio_newc }, + { "odc", archive_write_set_format_cpio }, + { "oldtar", archive_write_set_format_v7tar }, + { "pax", archive_write_set_format_pax }, + { "paxr", archive_write_set_format_pax_restricted }, + { "posix", archive_write_set_format_pax }, + { "raw", archive_write_set_format_raw }, + { "rpax", archive_write_set_format_pax_restricted }, + { "shar", archive_write_set_format_shar }, + { "shardump", archive_write_set_format_shar_dump }, + { "ustar", archive_write_set_format_ustar }, + { "v7tar", archive_write_set_format_v7tar }, + { "v7", archive_write_set_format_v7tar }, + { "warc", archive_write_set_format_warc }, + { "xar", archive_write_set_format_xar }, + { "zip", archive_write_set_format_zip }, + { NULL, NULL } +}; + +int +archive_write_set_format_by_name(struct archive *a, const char *name) +{ + int i; + + for (i = 0; names[i].name != NULL; i++) { + if (strcmp(name, names[i].name) == 0) + return ((names[i].setter)(a)); + } + + archive_set_error(a, EINVAL, "No such format '%s'", name); + a->state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_cpio.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_cpio.c new file mode 100644 index 0000000..729f9c7 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_cpio.c @@ -0,0 +1,500 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2011-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_cpio.c 201170 2009-12-29 06:34:23Z kientzle $"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_private.h" +#include "archive_write_private.h" +#include "archive_write_set_format_private.h" + +static ssize_t archive_write_cpio_data(struct archive_write *, + const void *buff, size_t s); +static int archive_write_cpio_close(struct archive_write *); +static int archive_write_cpio_free(struct archive_write *); +static int archive_write_cpio_finish_entry(struct archive_write *); +static int archive_write_cpio_header(struct archive_write *, + struct archive_entry *); +static int archive_write_cpio_options(struct archive_write *, + const char *, const char *); +static int format_octal(int64_t, void *, int); +static int64_t format_octal_recursive(int64_t, char *, int); +static int write_header(struct archive_write *, struct archive_entry *); + +struct cpio { + uint64_t entry_bytes_remaining; + + int64_t ino_next; + + struct { int64_t old; int new;} *ino_list; + size_t ino_list_size; + size_t ino_list_next; + + struct archive_string_conv *opt_sconv; + struct archive_string_conv *sconv_default; + int init_default_conversion; +}; + +#define c_magic_offset 0 +#define c_magic_size 6 +#define c_dev_offset 6 +#define c_dev_size 6 +#define c_ino_offset 12 +#define c_ino_size 6 +#define c_mode_offset 18 +#define c_mode_size 6 +#define c_uid_offset 24 +#define c_uid_size 6 +#define c_gid_offset 30 +#define c_gid_size 6 +#define c_nlink_offset 36 +#define c_nlink_size 6 +#define c_rdev_offset 42 +#define c_rdev_size 6 +#define c_mtime_offset 48 +#define c_mtime_size 11 +#define c_namesize_offset 59 +#define c_namesize_size 6 +#define c_filesize_offset 65 +#define c_filesize_size 11 + +/* + * Set output format to 'cpio' format. + */ +int +archive_write_set_format_cpio(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct cpio *cpio; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_set_format_cpio"); + + /* If someone else was already registered, unregister them. */ + if (a->format_free != NULL) + (a->format_free)(a); + + cpio = (struct cpio *)calloc(1, sizeof(*cpio)); + if (cpio == NULL) { + archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data"); + return (ARCHIVE_FATAL); + } + a->format_data = cpio; + a->format_name = "cpio"; + a->format_options = archive_write_cpio_options; + a->format_write_header = archive_write_cpio_header; + a->format_write_data = archive_write_cpio_data; + a->format_finish_entry = archive_write_cpio_finish_entry; + a->format_close = archive_write_cpio_close; + a->format_free = archive_write_cpio_free; + a->archive.archive_format = ARCHIVE_FORMAT_CPIO_POSIX; + a->archive.archive_format_name = "POSIX cpio"; + return (ARCHIVE_OK); +} + +static int +archive_write_cpio_options(struct archive_write *a, const char *key, + const char *val) +{ + struct cpio *cpio = (struct cpio *)a->format_data; + int ret = ARCHIVE_FAILED; + + if (strcmp(key, "hdrcharset") == 0) { + if (val == NULL || val[0] == 0) + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "%s: hdrcharset option needs a character-set name", + a->format_name); + else { + cpio->opt_sconv = archive_string_conversion_to_charset( + &a->archive, val, 0); + if (cpio->opt_sconv != NULL) + ret = ARCHIVE_OK; + else + ret = ARCHIVE_FATAL; + } + return (ret); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +/* + * Ino values are as long as 64 bits on some systems; cpio format + * only allows 18 bits and relies on the ino values to identify hardlinked + * files. So, we can't merely "hash" the ino numbers since collisions + * would corrupt the archive. Instead, we generate synthetic ino values + * to store in the archive and maintain a map of original ino values to + * synthetic ones so we can preserve hardlink information. + * + * TODO: Make this more efficient. It's not as bad as it looks (most + * files don't have any hardlinks and we don't do any work here for those), + * but it wouldn't be hard to do better. + * + * TODO: Work with dev/ino pairs here instead of just ino values. + */ +static int +synthesize_ino_value(struct cpio *cpio, struct archive_entry *entry) +{ + int64_t ino = archive_entry_ino64(entry); + int ino_new; + size_t i; + + /* + * If no index number was given, don't assign one. In + * particular, this handles the end-of-archive marker + * correctly by giving it a zero index value. (This is also + * why we start our synthetic index numbers with one below.) + */ + if (ino == 0) + return (0); + + /* Don't store a mapping if we don't need to. */ + if (archive_entry_nlink(entry) < 2) { + return (int)(++cpio->ino_next); + } + + /* Look up old ino; if we have it, this is a hardlink + * and we reuse the same value. */ + for (i = 0; i < cpio->ino_list_next; ++i) { + if (cpio->ino_list[i].old == ino) + return (cpio->ino_list[i].new); + } + + /* Assign a new index number. */ + ino_new = (int)(++cpio->ino_next); + + /* Ensure space for the new mapping. */ + if (cpio->ino_list_size <= cpio->ino_list_next) { + size_t newsize = cpio->ino_list_size < 512 + ? 512 : cpio->ino_list_size * 2; + void *newlist = realloc(cpio->ino_list, + sizeof(cpio->ino_list[0]) * newsize); + if (newlist == NULL) + return (-1); + + cpio->ino_list_size = newsize; + cpio->ino_list = newlist; + } + + /* Record and return the new value. */ + cpio->ino_list[cpio->ino_list_next].old = ino; + cpio->ino_list[cpio->ino_list_next].new = ino_new; + ++cpio->ino_list_next; + return (ino_new); +} + + +static struct archive_string_conv * +get_sconv(struct archive_write *a) +{ + struct cpio *cpio; + struct archive_string_conv *sconv; + + cpio = (struct cpio *)a->format_data; + sconv = cpio->opt_sconv; + if (sconv == NULL) { + if (!cpio->init_default_conversion) { + cpio->sconv_default = + archive_string_default_conversion_for_write( + &(a->archive)); + cpio->init_default_conversion = 1; + } + sconv = cpio->sconv_default; + } + return (sconv); +} + +static int +archive_write_cpio_header(struct archive_write *a, struct archive_entry *entry) +{ + const char *path; + size_t len; + + if (archive_entry_filetype(entry) == 0) { + archive_set_error(&a->archive, -1, "Filetype required"); + return (ARCHIVE_FAILED); + } + + if (archive_entry_pathname_l(entry, &path, &len, get_sconv(a)) != 0 + && errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Pathname"); + return (ARCHIVE_FATAL); + } + if (len == 0 || path == NULL || path[0] == '\0') { + archive_set_error(&a->archive, -1, "Pathname required"); + return (ARCHIVE_FAILED); + } + + if (!archive_entry_size_is_set(entry) || archive_entry_size(entry) < 0) { + archive_set_error(&a->archive, -1, "Size required"); + return (ARCHIVE_FAILED); + } + return write_header(a, entry); +} + +static int +write_header(struct archive_write *a, struct archive_entry *entry) +{ + struct cpio *cpio; + const char *p, *path; + int pathlength, ret, ret_final; + int64_t ino; + char h[76]; + struct archive_string_conv *sconv; + struct archive_entry *entry_main; + size_t len; + + cpio = (struct cpio *)a->format_data; + ret_final = ARCHIVE_OK; + sconv = get_sconv(a); + +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Make sure the path separators in pathname, hardlink and symlink + * are all slash '/', not the Windows path separator '\'. */ + entry_main = __la_win_entry_in_posix_pathseparator(entry); + if (entry_main == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate ustar data"); + return(ARCHIVE_FATAL); + } + if (entry != entry_main) + entry = entry_main; + else + entry_main = NULL; +#else + entry_main = NULL; +#endif + + ret = archive_entry_pathname_l(entry, &path, &len, sconv); + if (ret != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Pathname"); + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate pathname '%s' to %s", + archive_entry_pathname(entry), + archive_string_conversion_charset_name(sconv)); + ret_final = ARCHIVE_WARN; + } + /* Include trailing null. */ + pathlength = (int)len + 1; + + memset(h, 0, sizeof(h)); + format_octal(070707, h + c_magic_offset, c_magic_size); + format_octal(archive_entry_dev(entry), h + c_dev_offset, c_dev_size); + + ino = synthesize_ino_value(cpio, entry); + if (ino < 0) { + archive_set_error(&a->archive, ENOMEM, + "No memory for ino translation table"); + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } else if (ino > 0777777) { + archive_set_error(&a->archive, ERANGE, + "Too many files for this cpio format"); + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } + format_octal(ino & 0777777, h + c_ino_offset, c_ino_size); + + /* TODO: Set ret_final to ARCHIVE_WARN if any of these overflow. */ + format_octal(archive_entry_mode(entry), h + c_mode_offset, c_mode_size); + format_octal(archive_entry_uid(entry), h + c_uid_offset, c_uid_size); + format_octal(archive_entry_gid(entry), h + c_gid_offset, c_gid_size); + format_octal(archive_entry_nlink(entry), h + c_nlink_offset, c_nlink_size); + if (archive_entry_filetype(entry) == AE_IFBLK + || archive_entry_filetype(entry) == AE_IFCHR) + format_octal(archive_entry_dev(entry), h + c_rdev_offset, c_rdev_size); + else + format_octal(0, h + c_rdev_offset, c_rdev_size); + format_octal(archive_entry_mtime(entry), h + c_mtime_offset, c_mtime_size); + format_octal(pathlength, h + c_namesize_offset, c_namesize_size); + + /* Non-regular files don't store bodies. */ + if (archive_entry_filetype(entry) != AE_IFREG) + archive_entry_set_size(entry, 0); + + /* Symlinks get the link written as the body of the entry. */ + ret = archive_entry_symlink_l(entry, &p, &len, sconv); + if (ret != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Linkname"); + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate linkname '%s' to %s", + archive_entry_symlink(entry), + archive_string_conversion_charset_name(sconv)); + ret_final = ARCHIVE_WARN; + } + if (len > 0 && p != NULL && *p != '\0') + ret = format_octal(strlen(p), h + c_filesize_offset, + c_filesize_size); + else + ret = format_octal(archive_entry_size(entry), + h + c_filesize_offset, c_filesize_size); + if (ret) { + archive_set_error(&a->archive, ERANGE, + "File is too large for cpio format."); + ret_final = ARCHIVE_FAILED; + goto exit_write_header; + } + + ret = __archive_write_output(a, h, sizeof(h)); + if (ret != ARCHIVE_OK) { + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } + + ret = __archive_write_output(a, path, pathlength); + if (ret != ARCHIVE_OK) { + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } + + cpio->entry_bytes_remaining = archive_entry_size(entry); + + /* Write the symlink now. */ + if (p != NULL && *p != '\0') { + ret = __archive_write_output(a, p, strlen(p)); + if (ret != ARCHIVE_OK) { + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } + } +exit_write_header: + archive_entry_free(entry_main); + return (ret_final); +} + +static ssize_t +archive_write_cpio_data(struct archive_write *a, const void *buff, size_t s) +{ + struct cpio *cpio; + int ret; + + cpio = (struct cpio *)a->format_data; + if (s > cpio->entry_bytes_remaining) + s = (size_t)cpio->entry_bytes_remaining; + + ret = __archive_write_output(a, buff, s); + cpio->entry_bytes_remaining -= s; + if (ret >= 0) + return (s); + else + return (ret); +} + +/* + * Format a number into the specified field. + */ +static int +format_octal(int64_t v, void *p, int digits) +{ + int64_t max; + int ret; + + max = (((int64_t)1) << (digits * 3)) - 1; + if (v >= 0 && v <= max) { + format_octal_recursive(v, (char *)p, digits); + ret = 0; + } else { + format_octal_recursive(max, (char *)p, digits); + ret = -1; + } + return (ret); +} + +static int64_t +format_octal_recursive(int64_t v, char *p, int s) +{ + if (s == 0) + return (v); + v = format_octal_recursive(v, p+1, s-1); + *p = '0' + ((char)v & 7); + return (v >> 3); +} + +static int +archive_write_cpio_close(struct archive_write *a) +{ + int er; + struct archive_entry *trailer; + + trailer = archive_entry_new2(NULL); + /* nlink = 1 here for GNU cpio compat. */ + archive_entry_set_nlink(trailer, 1); + archive_entry_set_size(trailer, 0); + archive_entry_set_pathname(trailer, "TRAILER!!!"); + er = write_header(a, trailer); + archive_entry_free(trailer); + return (er); +} + +static int +archive_write_cpio_free(struct archive_write *a) +{ + struct cpio *cpio; + + cpio = (struct cpio *)a->format_data; + free(cpio->ino_list); + free(cpio); + a->format_data = NULL; + return (ARCHIVE_OK); +} + +static int +archive_write_cpio_finish_entry(struct archive_write *a) +{ + struct cpio *cpio; + + cpio = (struct cpio *)a->format_data; + return (__archive_write_nulls(a, + (size_t)cpio->entry_bytes_remaining)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_cpio_newc.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_cpio_newc.c new file mode 100644 index 0000000..172fda6 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_cpio_newc.c @@ -0,0 +1,457 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2006 Rudolf Marek SYSGO s.r.o. + * Copyright (c) 2011-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_cpio_newc.c 201160 2009-12-29 05:41:57Z kientzle $"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_private.h" +#include "archive_write_private.h" +#include "archive_write_set_format_private.h" + +static ssize_t archive_write_newc_data(struct archive_write *, + const void *buff, size_t s); +static int archive_write_newc_close(struct archive_write *); +static int archive_write_newc_free(struct archive_write *); +static int archive_write_newc_finish_entry(struct archive_write *); +static int archive_write_newc_header(struct archive_write *, + struct archive_entry *); +static int archive_write_newc_options(struct archive_write *, + const char *, const char *); +static int format_hex(int64_t, void *, int); +static int64_t format_hex_recursive(int64_t, char *, int); +static int write_header(struct archive_write *, struct archive_entry *); + +struct cpio { + uint64_t entry_bytes_remaining; + int padding; + + struct archive_string_conv *opt_sconv; + struct archive_string_conv *sconv_default; + int init_default_conversion; +}; + +#define c_magic_offset 0 +#define c_magic_size 6 +#define c_ino_offset 6 +#define c_ino_size 8 +#define c_mode_offset 14 +#define c_mode_size 8 +#define c_uid_offset 22 +#define c_uid_size 8 +#define c_gid_offset 30 +#define c_gid_size 8 +#define c_nlink_offset 38 +#define c_nlink_size 8 +#define c_mtime_offset 46 +#define c_mtime_size 8 +#define c_filesize_offset 54 +#define c_filesize_size 8 +#define c_devmajor_offset 62 +#define c_devmajor_size 8 +#define c_devminor_offset 70 +#define c_devminor_size 8 +#define c_rdevmajor_offset 78 +#define c_rdevmajor_size 8 +#define c_rdevminor_offset 86 +#define c_rdevminor_size 8 +#define c_namesize_offset 94 +#define c_namesize_size 8 +#define c_checksum_offset 102 +#define c_checksum_size 8 +#define c_header_size 110 + +/* Logic trick: difference between 'n' and next multiple of 4 */ +#define PAD4(n) (3 & (1 + ~(n))) + +/* + * Set output format to 'cpio' format. + */ +int +archive_write_set_format_cpio_newc(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct cpio *cpio; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_set_format_cpio_newc"); + + /* If someone else was already registered, unregister them. */ + if (a->format_free != NULL) + (a->format_free)(a); + + cpio = (struct cpio *)calloc(1, sizeof(*cpio)); + if (cpio == NULL) { + archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data"); + return (ARCHIVE_FATAL); + } + a->format_data = cpio; + a->format_name = "cpio"; + a->format_options = archive_write_newc_options; + a->format_write_header = archive_write_newc_header; + a->format_write_data = archive_write_newc_data; + a->format_finish_entry = archive_write_newc_finish_entry; + a->format_close = archive_write_newc_close; + a->format_free = archive_write_newc_free; + a->archive.archive_format = ARCHIVE_FORMAT_CPIO_SVR4_NOCRC; + a->archive.archive_format_name = "SVR4 cpio nocrc"; + return (ARCHIVE_OK); +} + +static int +archive_write_newc_options(struct archive_write *a, const char *key, + const char *val) +{ + struct cpio *cpio = (struct cpio *)a->format_data; + int ret = ARCHIVE_FAILED; + + if (strcmp(key, "hdrcharset") == 0) { + if (val == NULL || val[0] == 0) + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "%s: hdrcharset option needs a character-set name", + a->format_name); + else { + cpio->opt_sconv = archive_string_conversion_to_charset( + &a->archive, val, 0); + if (cpio->opt_sconv != NULL) + ret = ARCHIVE_OK; + else + ret = ARCHIVE_FATAL; + } + return (ret); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +static struct archive_string_conv * +get_sconv(struct archive_write *a) +{ + struct cpio *cpio; + struct archive_string_conv *sconv; + + cpio = (struct cpio *)a->format_data; + sconv = cpio->opt_sconv; + if (sconv == NULL) { + if (!cpio->init_default_conversion) { + cpio->sconv_default = + archive_string_default_conversion_for_write( + &(a->archive)); + cpio->init_default_conversion = 1; + } + sconv = cpio->sconv_default; + } + return (sconv); +} + +static int +archive_write_newc_header(struct archive_write *a, struct archive_entry *entry) +{ + const char *path; + size_t len; + + if (archive_entry_filetype(entry) == 0) { + archive_set_error(&a->archive, -1, "Filetype required"); + return (ARCHIVE_FAILED); + } + + if (archive_entry_pathname_l(entry, &path, &len, get_sconv(a)) != 0 + && errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Pathname"); + return (ARCHIVE_FATAL); + } + if (len == 0 || path == NULL || path[0] == '\0') { + archive_set_error(&a->archive, -1, "Pathname required"); + return (ARCHIVE_FAILED); + } + + if (archive_entry_hardlink(entry) == NULL + && (!archive_entry_size_is_set(entry) || archive_entry_size(entry) < 0)) { + archive_set_error(&a->archive, -1, "Size required"); + return (ARCHIVE_FAILED); + } + return write_header(a, entry); +} + +static int +write_header(struct archive_write *a, struct archive_entry *entry) +{ + int64_t ino; + struct cpio *cpio; + const char *p, *path; + int pathlength, ret, ret_final; + char h[c_header_size]; + struct archive_string_conv *sconv; + struct archive_entry *entry_main; + size_t len; + int pad; + + cpio = (struct cpio *)a->format_data; + ret_final = ARCHIVE_OK; + sconv = get_sconv(a); + +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Make sure the path separators in pathname, hardlink and symlink + * are all slash '/', not the Windows path separator '\'. */ + entry_main = __la_win_entry_in_posix_pathseparator(entry); + if (entry_main == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate ustar data"); + return(ARCHIVE_FATAL); + } + if (entry != entry_main) + entry = entry_main; + else + entry_main = NULL; +#else + entry_main = NULL; +#endif + + ret = archive_entry_pathname_l(entry, &path, &len, sconv); + if (ret != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Pathname"); + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate pathname '%s' to %s", + archive_entry_pathname(entry), + archive_string_conversion_charset_name(sconv)); + ret_final = ARCHIVE_WARN; + } + pathlength = (int)len + 1; /* Include trailing null. */ + + memset(h, 0, c_header_size); + format_hex(0x070701, h + c_magic_offset, c_magic_size); + format_hex(archive_entry_devmajor(entry), h + c_devmajor_offset, + c_devmajor_size); + format_hex(archive_entry_devminor(entry), h + c_devminor_offset, + c_devminor_size); + + ino = archive_entry_ino64(entry); + if (ino > 0xffffffff) { + archive_set_error(&a->archive, ERANGE, + "large inode number truncated"); + ret_final = ARCHIVE_WARN; + } + + /* TODO: Set ret_final to ARCHIVE_WARN if any of these overflow. */ + format_hex(ino & 0xffffffff, h + c_ino_offset, c_ino_size); + format_hex(archive_entry_mode(entry), h + c_mode_offset, c_mode_size); + format_hex(archive_entry_uid(entry), h + c_uid_offset, c_uid_size); + format_hex(archive_entry_gid(entry), h + c_gid_offset, c_gid_size); + format_hex(archive_entry_nlink(entry), h + c_nlink_offset, c_nlink_size); + if (archive_entry_filetype(entry) == AE_IFBLK + || archive_entry_filetype(entry) == AE_IFCHR) { + format_hex(archive_entry_rdevmajor(entry), h + c_rdevmajor_offset, c_rdevmajor_size); + format_hex(archive_entry_rdevminor(entry), h + c_rdevminor_offset, c_rdevminor_size); + } else { + format_hex(0, h + c_rdevmajor_offset, c_rdevmajor_size); + format_hex(0, h + c_rdevminor_offset, c_rdevminor_size); + } + format_hex(archive_entry_mtime(entry), h + c_mtime_offset, c_mtime_size); + format_hex(pathlength, h + c_namesize_offset, c_namesize_size); + format_hex(0, h + c_checksum_offset, c_checksum_size); + + /* Non-regular files don't store bodies. */ + if (archive_entry_filetype(entry) != AE_IFREG) + archive_entry_set_size(entry, 0); + + /* Symlinks get the link written as the body of the entry. */ + ret = archive_entry_symlink_l(entry, &p, &len, sconv); + if (ret != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Likname"); + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate linkname '%s' to %s", + archive_entry_symlink(entry), + archive_string_conversion_charset_name(sconv)); + ret_final = ARCHIVE_WARN; + } + if (len > 0 && p != NULL && *p != '\0') + ret = format_hex(strlen(p), h + c_filesize_offset, + c_filesize_size); + else + ret = format_hex(archive_entry_size(entry), + h + c_filesize_offset, c_filesize_size); + if (ret) { + archive_set_error(&a->archive, ERANGE, + "File is too large for this format."); + ret_final = ARCHIVE_FAILED; + goto exit_write_header; + } + + ret = __archive_write_output(a, h, c_header_size); + if (ret != ARCHIVE_OK) { + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } + + /* Pad pathname to even length. */ + ret = __archive_write_output(a, path, pathlength); + if (ret != ARCHIVE_OK) { + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } + pad = PAD4(pathlength + c_header_size); + if (pad) { + ret = __archive_write_output(a, "\0\0\0", pad); + if (ret != ARCHIVE_OK) { + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } + } + + cpio->entry_bytes_remaining = archive_entry_size(entry); + cpio->padding = (int)PAD4(cpio->entry_bytes_remaining); + + /* Write the symlink now. */ + if (p != NULL && *p != '\0') { + ret = __archive_write_output(a, p, strlen(p)); + if (ret != ARCHIVE_OK) { + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } + pad = PAD4(strlen(p)); + ret = __archive_write_output(a, "\0\0\0", pad); + if (ret != ARCHIVE_OK) { + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } + } +exit_write_header: + archive_entry_free(entry_main); + return (ret_final); +} + +static ssize_t +archive_write_newc_data(struct archive_write *a, const void *buff, size_t s) +{ + struct cpio *cpio; + int ret; + + cpio = (struct cpio *)a->format_data; + if (s > cpio->entry_bytes_remaining) + s = (size_t)cpio->entry_bytes_remaining; + + ret = __archive_write_output(a, buff, s); + cpio->entry_bytes_remaining -= s; + if (ret >= 0) + return (s); + else + return (ret); +} + +/* + * Format a number into the specified field. + */ +static int +format_hex(int64_t v, void *p, int digits) +{ + int64_t max; + int ret; + + max = (((int64_t)1) << (digits * 4)) - 1; + if (v >= 0 && v <= max) { + format_hex_recursive(v, (char *)p, digits); + ret = 0; + } else { + format_hex_recursive(max, (char *)p, digits); + ret = -1; + } + return (ret); +} + +static int64_t +format_hex_recursive(int64_t v, char *p, int s) +{ + if (s == 0) + return (v); + v = format_hex_recursive(v, p+1, s-1); + *p = "0123456789abcdef"[v & 0xf]; + return (v >> 4); +} + +static int +archive_write_newc_close(struct archive_write *a) +{ + int er; + struct archive_entry *trailer; + + trailer = archive_entry_new(); + archive_entry_set_nlink(trailer, 1); + archive_entry_set_size(trailer, 0); + archive_entry_set_pathname(trailer, "TRAILER!!!"); + /* Bypass the required data checks. */ + er = write_header(a, trailer); + archive_entry_free(trailer); + return (er); +} + +static int +archive_write_newc_free(struct archive_write *a) +{ + struct cpio *cpio; + + cpio = (struct cpio *)a->format_data; + free(cpio); + a->format_data = NULL; + return (ARCHIVE_OK); +} + +static int +archive_write_newc_finish_entry(struct archive_write *a) +{ + struct cpio *cpio; + + cpio = (struct cpio *)a->format_data; + return (__archive_write_nulls(a, + (size_t)cpio->entry_bytes_remaining + cpio->padding)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_filter_by_ext.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_filter_by_ext.c new file mode 100644 index 0000000..9fe21e4 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_filter_by_ext.c @@ -0,0 +1,142 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2015 Okhotnikov Kirill + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_by_name.c 201168 2009-12-29 06:15:32Z kientzle $"); + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" + +/* A table that maps names to functions. */ +static const +struct { const char *name; int (*format)(struct archive *); int (*filter)(struct archive *); } names[] = +{ + { ".7z", archive_write_set_format_7zip, archive_write_add_filter_none}, + { ".zip", archive_write_set_format_zip, archive_write_add_filter_none}, + { ".jar", archive_write_set_format_zip, archive_write_add_filter_none}, + { ".cpio", archive_write_set_format_cpio, archive_write_add_filter_none}, + { ".iso", archive_write_set_format_iso9660, archive_write_add_filter_none}, +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) + { ".a", archive_write_set_format_ar_bsd, archive_write_add_filter_none}, + { ".ar", archive_write_set_format_ar_bsd, archive_write_add_filter_none}, +#else + { ".a", archive_write_set_format_ar_svr4, archive_write_add_filter_none}, + { ".ar", archive_write_set_format_ar_svr4, archive_write_add_filter_none}, +#endif + { ".tar", archive_write_set_format_pax_restricted, archive_write_add_filter_none}, + { ".tgz", archive_write_set_format_pax_restricted, archive_write_add_filter_gzip}, + { ".tar.gz", archive_write_set_format_pax_restricted, archive_write_add_filter_gzip}, + { ".tar.bz2", archive_write_set_format_pax_restricted, archive_write_add_filter_bzip2}, + { ".tar.xz", archive_write_set_format_pax_restricted, archive_write_add_filter_xz}, + { NULL, NULL, NULL } +}; + +static +int cmpsuff(const char *str, const char *suffix) +{ + size_t length_str, length_suffix; + + if ((str == NULL) || (suffix == NULL)) + return -1; + + length_str = strlen(str); + length_suffix = strlen(suffix); + + if (length_str >= length_suffix) { + return strcmp(str + (length_str - length_suffix), suffix); + } else { + return -1; + } +} + +static int get_array_index(const char *name) +{ + int i; + + for (i = 0; names[i].name != NULL; i++) + { + if (cmpsuff(name, names[i].name) == 0) + return i; + } + return -1; + +} + +int +archive_write_set_format_filter_by_ext(struct archive *a, const char *filename) +{ + int names_index = get_array_index(filename); + + if (names_index >= 0) + { + int format_state = (names[names_index].format)(a); + if (format_state == ARCHIVE_OK) + return ((names[names_index].filter)(a)); + else + return format_state; + } + + archive_set_error(a, EINVAL, "No such format '%s'", filename); + a->state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); +} + +int +archive_write_set_format_filter_by_ext_def(struct archive *a, const char *filename, const char * def_ext) +{ + int names_index = get_array_index(filename); + + if (names_index < 0) + names_index = get_array_index(def_ext); + + if (names_index >= 0) + { + int format_state = (names[names_index].format)(a); + if (format_state == ARCHIVE_OK) + return ((names[names_index].filter)(a)); + else + return format_state; + } + + archive_set_error(a, EINVAL, "No such format '%s'", filename); + a->state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); +} + + + + diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_gnutar.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_gnutar.c new file mode 100644 index 0000000..ec29c5c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_gnutar.c @@ -0,0 +1,755 @@ +/*- + * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). + * Author: Jonas Gastal + * Copyright (c) 2011-2012 Michihiro NAKAJIMA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_gnu_tar.c 191579 2009-04-27 18:35:03Z gastal $"); + + +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_private.h" +#include "archive_write_private.h" +#include "archive_write_set_format_private.h" + +struct gnutar { + uint64_t entry_bytes_remaining; + uint64_t entry_padding; + const char * linkname; + size_t linkname_length; + const char * pathname; + size_t pathname_length; + const char * uname; + size_t uname_length; + const char * gname; + size_t gname_length; + struct archive_string_conv *opt_sconv; + struct archive_string_conv *sconv_default; + int init_default_conversion; +}; + +/* + * Define structure of GNU tar header. + */ +#define GNUTAR_name_offset 0 +#define GNUTAR_name_size 100 +#define GNUTAR_mode_offset 100 +#define GNUTAR_mode_size 7 +#define GNUTAR_mode_max_size 8 +#define GNUTAR_uid_offset 108 +#define GNUTAR_uid_size 7 +#define GNUTAR_uid_max_size 8 +#define GNUTAR_gid_offset 116 +#define GNUTAR_gid_size 7 +#define GNUTAR_gid_max_size 8 +#define GNUTAR_size_offset 124 +#define GNUTAR_size_size 11 +#define GNUTAR_size_max_size 12 +#define GNUTAR_mtime_offset 136 +#define GNUTAR_mtime_size 11 +#define GNUTAR_mtime_max_size 11 +#define GNUTAR_checksum_offset 148 +#define GNUTAR_checksum_size 8 +#define GNUTAR_typeflag_offset 156 +#define GNUTAR_typeflag_size 1 +#define GNUTAR_linkname_offset 157 +#define GNUTAR_linkname_size 100 +#define GNUTAR_magic_offset 257 +#define GNUTAR_magic_size 6 +#define GNUTAR_version_offset 263 +#define GNUTAR_version_size 2 +#define GNUTAR_uname_offset 265 +#define GNUTAR_uname_size 32 +#define GNUTAR_gname_offset 297 +#define GNUTAR_gname_size 32 +#define GNUTAR_rdevmajor_offset 329 +#define GNUTAR_rdevmajor_size 6 +#define GNUTAR_rdevmajor_max_size 8 +#define GNUTAR_rdevminor_offset 337 +#define GNUTAR_rdevminor_size 6 +#define GNUTAR_rdevminor_max_size 8 + +/* + * A filled-in copy of the header for initialization. + */ +static const char template_header[] = { + /* name: 100 bytes */ + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0, + /* Mode, null termination: 8 bytes */ + '0','0','0','0','0','0', '0','\0', + /* uid, null termination: 8 bytes */ + '0','0','0','0','0','0', '0','\0', + /* gid, null termination: 8 bytes */ + '0','0','0','0','0','0', '0','\0', + /* size, space termination: 12 bytes */ + '0','0','0','0','0','0','0','0','0','0','0', '\0', + /* mtime, space termination: 12 bytes */ + '0','0','0','0','0','0','0','0','0','0','0', '\0', + /* Initial checksum value: 8 spaces */ + ' ',' ',' ',' ',' ',' ',' ',' ', + /* Typeflag: 1 byte */ + '0', /* '0' = regular file */ + /* Linkname: 100 bytes */ + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0, + /* Magic: 8 bytes */ + 'u','s','t','a','r',' ', ' ','\0', + /* Uname: 32 bytes */ + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + /* Gname: 32 bytes */ + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + /* rdevmajor + null padding: 8 bytes */ + '\0','\0','\0','\0','\0','\0', '\0','\0', + /* rdevminor + null padding: 8 bytes */ + '\0','\0','\0','\0','\0','\0', '\0','\0', + /* Padding: 167 bytes */ + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0 +}; + +static int archive_write_gnutar_options(struct archive_write *, + const char *, const char *); +static int archive_format_gnutar_header(struct archive_write *, char h[512], + struct archive_entry *, int tartype); +static int archive_write_gnutar_header(struct archive_write *, + struct archive_entry *entry); +static ssize_t archive_write_gnutar_data(struct archive_write *a, const void *buff, + size_t s); +static int archive_write_gnutar_free(struct archive_write *); +static int archive_write_gnutar_close(struct archive_write *); +static int archive_write_gnutar_finish_entry(struct archive_write *); +static int format_256(int64_t, char *, int); +static int format_number(int64_t, char *, int size, int maxsize); +static int format_octal(int64_t, char *, int); + +/* + * Set output format to 'GNU tar' format. + */ +int +archive_write_set_format_gnutar(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct gnutar *gnutar; + + gnutar = (struct gnutar *)calloc(1, sizeof(*gnutar)); + if (gnutar == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate gnutar data"); + return (ARCHIVE_FATAL); + } + a->format_data = gnutar; + a->format_name = "gnutar"; + a->format_options = archive_write_gnutar_options; + a->format_write_header = archive_write_gnutar_header; + a->format_write_data = archive_write_gnutar_data; + a->format_close = archive_write_gnutar_close; + a->format_free = archive_write_gnutar_free; + a->format_finish_entry = archive_write_gnutar_finish_entry; + a->archive.archive_format = ARCHIVE_FORMAT_TAR_GNUTAR; + a->archive.archive_format_name = "GNU tar"; + return (ARCHIVE_OK); +} + +static int +archive_write_gnutar_options(struct archive_write *a, const char *key, + const char *val) +{ + struct gnutar *gnutar = (struct gnutar *)a->format_data; + int ret = ARCHIVE_FAILED; + + if (strcmp(key, "hdrcharset") == 0) { + if (val == NULL || val[0] == 0) + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "%s: hdrcharset option needs a character-set name", + a->format_name); + else { + gnutar->opt_sconv = archive_string_conversion_to_charset( + &a->archive, val, 0); + if (gnutar->opt_sconv != NULL) + ret = ARCHIVE_OK; + else + ret = ARCHIVE_FATAL; + } + return (ret); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +static int +archive_write_gnutar_close(struct archive_write *a) +{ + return (__archive_write_nulls(a, 512*2)); +} + +static int +archive_write_gnutar_free(struct archive_write *a) +{ + struct gnutar *gnutar; + + gnutar = (struct gnutar *)a->format_data; + free(gnutar); + a->format_data = NULL; + return (ARCHIVE_OK); +} + +static int +archive_write_gnutar_finish_entry(struct archive_write *a) +{ + struct gnutar *gnutar; + int ret; + + gnutar = (struct gnutar *)a->format_data; + ret = __archive_write_nulls(a, (size_t) + (gnutar->entry_bytes_remaining + gnutar->entry_padding)); + gnutar->entry_bytes_remaining = gnutar->entry_padding = 0; + return (ret); +} + +static ssize_t +archive_write_gnutar_data(struct archive_write *a, const void *buff, size_t s) +{ + struct gnutar *gnutar; + int ret; + + gnutar = (struct gnutar *)a->format_data; + if (s > gnutar->entry_bytes_remaining) + s = (size_t)gnutar->entry_bytes_remaining; + ret = __archive_write_output(a, buff, s); + gnutar->entry_bytes_remaining -= s; + if (ret != ARCHIVE_OK) + return (ret); + return (s); +} + +static int +archive_write_gnutar_header(struct archive_write *a, + struct archive_entry *entry) +{ + char buff[512]; + int r, ret, ret2 = ARCHIVE_OK; + int tartype; + struct gnutar *gnutar; + struct archive_string_conv *sconv; + struct archive_entry *entry_main; + + gnutar = (struct gnutar *)a->format_data; + + /* Setup default string conversion. */ + if (gnutar->opt_sconv == NULL) { + if (!gnutar->init_default_conversion) { + gnutar->sconv_default = + archive_string_default_conversion_for_write( + &(a->archive)); + gnutar->init_default_conversion = 1; + } + sconv = gnutar->sconv_default; + } else + sconv = gnutar->opt_sconv; + + /* Only regular files (not hardlinks) have data. */ + if (archive_entry_hardlink(entry) != NULL || + archive_entry_symlink(entry) != NULL || + !(archive_entry_filetype(entry) == AE_IFREG)) + archive_entry_set_size(entry, 0); + + if (AE_IFDIR == archive_entry_filetype(entry)) { + const char *p; + size_t path_length; + /* + * Ensure a trailing '/'. Modify the entry so + * the client sees the change. + */ +#if defined(_WIN32) && !defined(__CYGWIN__) + const wchar_t *wp; + + wp = archive_entry_pathname_w(entry); + if (wp != NULL && wp[wcslen(wp) -1] != L'/') { + struct archive_wstring ws; + + archive_string_init(&ws); + path_length = wcslen(wp); + if (archive_wstring_ensure(&ws, + path_length + 2) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate ustar data"); + archive_wstring_free(&ws); + return(ARCHIVE_FATAL); + } + /* Should we keep '\' ? */ + if (wp[path_length -1] == L'\\') + path_length--; + archive_wstrncpy(&ws, wp, path_length); + archive_wstrappend_wchar(&ws, L'/'); + archive_entry_copy_pathname_w(entry, ws.s); + archive_wstring_free(&ws); + p = NULL; + } else +#endif + p = archive_entry_pathname(entry); + /* + * On Windows, this is a backup operation just in + * case getting WCS failed. On POSIX, this is a + * normal operation. + */ + if (p != NULL && p[0] != '\0' && p[strlen(p) - 1] != '/') { + struct archive_string as; + + archive_string_init(&as); + path_length = strlen(p); + if (archive_string_ensure(&as, + path_length + 2) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate ustar data"); + archive_string_free(&as); + return(ARCHIVE_FATAL); + } +#if defined(_WIN32) && !defined(__CYGWIN__) + /* NOTE: This might break the pathname + * if the current code page is CP932 and + * the pathname includes a character '\' + * as a part of its multibyte pathname. */ + if (p[strlen(p) -1] == '\\') + path_length--; + else +#endif + archive_strncpy(&as, p, path_length); + archive_strappend_char(&as, '/'); + archive_entry_copy_pathname(entry, as.s); + archive_string_free(&as); + } + } + +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Make sure the path separators in pathname, hardlink and symlink + * are all slash '/', not the Windows path separator '\'. */ + entry_main = __la_win_entry_in_posix_pathseparator(entry); + if (entry_main == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate ustar data"); + return(ARCHIVE_FATAL); + } + if (entry != entry_main) + entry = entry_main; + else + entry_main = NULL; +#else + entry_main = NULL; +#endif + r = archive_entry_pathname_l(entry, &(gnutar->pathname), + &(gnutar->pathname_length), sconv); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Pathame"); + ret = ARCHIVE_FATAL; + goto exit_write_header; + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate pathname '%s' to %s", + archive_entry_pathname(entry), + archive_string_conversion_charset_name(sconv)); + ret2 = ARCHIVE_WARN; + } + r = archive_entry_uname_l(entry, &(gnutar->uname), + &(gnutar->uname_length), sconv); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Uname"); + ret = ARCHIVE_FATAL; + goto exit_write_header; + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate uname '%s' to %s", + archive_entry_uname(entry), + archive_string_conversion_charset_name(sconv)); + ret2 = ARCHIVE_WARN; + } + r = archive_entry_gname_l(entry, &(gnutar->gname), + &(gnutar->gname_length), sconv); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Gname"); + ret = ARCHIVE_FATAL; + goto exit_write_header; + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate gname '%s' to %s", + archive_entry_gname(entry), + archive_string_conversion_charset_name(sconv)); + ret2 = ARCHIVE_WARN; + } + + /* If linkname is longer than 100 chars we need to add a 'K' header. */ + r = archive_entry_hardlink_l(entry, &(gnutar->linkname), + &(gnutar->linkname_length), sconv); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Linkname"); + ret = ARCHIVE_FATAL; + goto exit_write_header; + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate linkname '%s' to %s", + archive_entry_hardlink(entry), + archive_string_conversion_charset_name(sconv)); + ret2 = ARCHIVE_WARN; + } + if (gnutar->linkname_length == 0) { + r = archive_entry_symlink_l(entry, &(gnutar->linkname), + &(gnutar->linkname_length), sconv); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Linkname"); + ret = ARCHIVE_FATAL; + goto exit_write_header; + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate linkname '%s' to %s", + archive_entry_hardlink(entry), + archive_string_conversion_charset_name(sconv)); + ret2 = ARCHIVE_WARN; + } + } + if (gnutar->linkname_length > GNUTAR_linkname_size) { + size_t length = gnutar->linkname_length + 1; + struct archive_entry *temp = archive_entry_new2(&a->archive); + + /* Uname/gname here don't really matter since no one reads them; + * these are the values that GNU tar happens to use on FreeBSD. */ + archive_entry_set_uname(temp, "root"); + archive_entry_set_gname(temp, "wheel"); + + archive_entry_set_pathname(temp, "././@LongLink"); + archive_entry_set_size(temp, length); + ret = archive_format_gnutar_header(a, buff, temp, 'K'); + archive_entry_free(temp); + if (ret < ARCHIVE_WARN) + goto exit_write_header; + ret = __archive_write_output(a, buff, 512); + if (ret < ARCHIVE_WARN) + goto exit_write_header; + /* Write name and trailing null byte. */ + ret = __archive_write_output(a, gnutar->linkname, length); + if (ret < ARCHIVE_WARN) + goto exit_write_header; + /* Pad to 512 bytes */ + ret = __archive_write_nulls(a, 0x1ff & (-(ssize_t)length)); + if (ret < ARCHIVE_WARN) + goto exit_write_header; + } + + /* If pathname is longer than 100 chars we need to add an 'L' header. */ + if (gnutar->pathname_length > GNUTAR_name_size) { + const char *pathname = gnutar->pathname; + size_t length = gnutar->pathname_length + 1; + struct archive_entry *temp = archive_entry_new2(&a->archive); + + /* Uname/gname here don't really matter since no one reads them; + * these are the values that GNU tar happens to use on FreeBSD. */ + archive_entry_set_uname(temp, "root"); + archive_entry_set_gname(temp, "wheel"); + + archive_entry_set_pathname(temp, "././@LongLink"); + archive_entry_set_size(temp, length); + ret = archive_format_gnutar_header(a, buff, temp, 'L'); + archive_entry_free(temp); + if (ret < ARCHIVE_WARN) + goto exit_write_header; + ret = __archive_write_output(a, buff, 512); + if(ret < ARCHIVE_WARN) + goto exit_write_header; + /* Write pathname + trailing null byte. */ + ret = __archive_write_output(a, pathname, length); + if(ret < ARCHIVE_WARN) + goto exit_write_header; + /* Pad to multiple of 512 bytes. */ + ret = __archive_write_nulls(a, 0x1ff & (-(ssize_t)length)); + if (ret < ARCHIVE_WARN) + goto exit_write_header; + } + + if (archive_entry_hardlink(entry) != NULL) { + tartype = '1'; + } else + switch (archive_entry_filetype(entry)) { + case AE_IFREG: tartype = '0' ; break; + case AE_IFLNK: tartype = '2' ; break; + case AE_IFCHR: tartype = '3' ; break; + case AE_IFBLK: tartype = '4' ; break; + case AE_IFDIR: tartype = '5' ; break; + case AE_IFIFO: tartype = '6' ; break; + default: /* AE_IFSOCK and unknown */ + __archive_write_entry_filetype_unsupported( + &a->archive, entry, "gnutar"); + ret = ARCHIVE_FAILED; + goto exit_write_header; + } + + ret = archive_format_gnutar_header(a, buff, entry, tartype); + if (ret < ARCHIVE_WARN) + goto exit_write_header; + if (ret2 < ret) + ret = ret2; + ret2 = __archive_write_output(a, buff, 512); + if (ret2 < ARCHIVE_WARN) { + ret = ret2; + goto exit_write_header; + } + if (ret2 < ret) + ret = ret2; + + gnutar->entry_bytes_remaining = archive_entry_size(entry); + gnutar->entry_padding = 0x1ff & (-(int64_t)gnutar->entry_bytes_remaining); +exit_write_header: + archive_entry_free(entry_main); + return (ret); +} + +static int +archive_format_gnutar_header(struct archive_write *a, char h[512], + struct archive_entry *entry, int tartype) +{ + unsigned int checksum; + int i, ret; + size_t copy_length; + const char *p; + struct gnutar *gnutar; + + gnutar = (struct gnutar *)a->format_data; + + ret = 0; + + /* + * The "template header" already includes the signature, + * various end-of-field markers, and other required elements. + */ + memcpy(h, &template_header, 512); + + /* + * Because the block is already null-filled, and strings + * are allowed to exactly fill their destination (without null), + * I use memcpy(dest, src, strlen()) here a lot to copy strings. + */ + + if (tartype == 'K' || tartype == 'L') { + p = archive_entry_pathname(entry); + copy_length = strlen(p); + } else { + p = gnutar->pathname; + copy_length = gnutar->pathname_length; + } + if (copy_length > GNUTAR_name_size) + copy_length = GNUTAR_name_size; + memcpy(h + GNUTAR_name_offset, p, copy_length); + + if ((copy_length = gnutar->linkname_length) > 0) { + if (copy_length > GNUTAR_linkname_size) + copy_length = GNUTAR_linkname_size; + memcpy(h + GNUTAR_linkname_offset, gnutar->linkname, + copy_length); + } + + /* TODO: How does GNU tar handle unames longer than GNUTAR_uname_size? */ + if (tartype == 'K' || tartype == 'L') { + p = archive_entry_uname(entry); + copy_length = strlen(p); + } else { + p = gnutar->uname; + copy_length = gnutar->uname_length; + } + if (copy_length > 0) { + if (copy_length > GNUTAR_uname_size) + copy_length = GNUTAR_uname_size; + memcpy(h + GNUTAR_uname_offset, p, copy_length); + } + + /* TODO: How does GNU tar handle gnames longer than GNUTAR_gname_size? */ + if (tartype == 'K' || tartype == 'L') { + p = archive_entry_gname(entry); + copy_length = strlen(p); + } else { + p = gnutar->gname; + copy_length = gnutar->gname_length; + } + if (copy_length > 0) { + if (strlen(p) > GNUTAR_gname_size) + copy_length = GNUTAR_gname_size; + memcpy(h + GNUTAR_gname_offset, p, copy_length); + } + + /* By truncating the mode here, we ensure it always fits. */ + format_octal(archive_entry_mode(entry) & 07777, + h + GNUTAR_mode_offset, GNUTAR_mode_size); + + /* GNU tar supports base-256 here, so should never overflow. */ + if (format_number(archive_entry_uid(entry), h + GNUTAR_uid_offset, + GNUTAR_uid_size, GNUTAR_uid_max_size)) { + archive_set_error(&a->archive, ERANGE, + "Numeric user ID %jd too large", + (intmax_t)archive_entry_uid(entry)); + ret = ARCHIVE_FAILED; + } + + /* GNU tar supports base-256 here, so should never overflow. */ + if (format_number(archive_entry_gid(entry), h + GNUTAR_gid_offset, + GNUTAR_gid_size, GNUTAR_gid_max_size)) { + archive_set_error(&a->archive, ERANGE, + "Numeric group ID %jd too large", + (intmax_t)archive_entry_gid(entry)); + ret = ARCHIVE_FAILED; + } + + /* GNU tar supports base-256 here, so should never overflow. */ + if (format_number(archive_entry_size(entry), h + GNUTAR_size_offset, + GNUTAR_size_size, GNUTAR_size_max_size)) { + archive_set_error(&a->archive, ERANGE, + "File size out of range"); + ret = ARCHIVE_FAILED; + } + + /* Shouldn't overflow before 2106, since mtime field is 33 bits. */ + format_octal(archive_entry_mtime(entry), + h + GNUTAR_mtime_offset, GNUTAR_mtime_size); + + if (archive_entry_filetype(entry) == AE_IFBLK + || archive_entry_filetype(entry) == AE_IFCHR) { + if (format_octal(archive_entry_rdevmajor(entry), + h + GNUTAR_rdevmajor_offset, + GNUTAR_rdevmajor_size)) { + archive_set_error(&a->archive, ERANGE, + "Major device number too large"); + ret = ARCHIVE_FAILED; + } + + if (format_octal(archive_entry_rdevminor(entry), + h + GNUTAR_rdevminor_offset, + GNUTAR_rdevminor_size)) { + archive_set_error(&a->archive, ERANGE, + "Minor device number too large"); + ret = ARCHIVE_FAILED; + } + } + + h[GNUTAR_typeflag_offset] = tartype; + + checksum = 0; + for (i = 0; i < 512; i++) + checksum += 255 & (unsigned int)h[i]; + h[GNUTAR_checksum_offset + 6] = '\0'; /* Can't be pre-set in the template. */ + /* h[GNUTAR_checksum_offset + 7] = ' '; */ /* This is pre-set in the template. */ + format_octal(checksum, h + GNUTAR_checksum_offset, 6); + return (ret); +} + +/* + * Format a number into a field, falling back to base-256 if necessary. + */ +static int +format_number(int64_t v, char *p, int s, int maxsize) +{ + int64_t limit = ((int64_t)1 << (s*3)); + + if (v < limit) + return (format_octal(v, p, s)); + return (format_256(v, p, maxsize)); +} + +/* + * Format a number into the specified field using base-256. + */ +static int +format_256(int64_t v, char *p, int s) +{ + p += s; + while (s-- > 0) { + *--p = (char)(v & 0xff); + v >>= 8; + } + *p |= 0x80; /* Set the base-256 marker bit. */ + return (0); +} + +/* + * Format a number into the specified field using octal. + */ +static int +format_octal(int64_t v, char *p, int s) +{ + int len = s; + + /* Octal values can't be negative, so use 0. */ + if (v < 0) + v = 0; + + p += s; /* Start at the end and work backwards. */ + while (s-- > 0) { + *--p = (char)('0' + (v & 7)); + v >>= 3; + } + + if (v == 0) + return (0); + + /* If it overflowed, fill field with max value. */ + while (len-- > 0) + *p++ = '7'; + + return (-1); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_iso9660.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_iso9660.c new file mode 100644 index 0000000..7cde44c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_iso9660.c @@ -0,0 +1,8162 @@ +/*- + * Copyright (c) 2009-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_UTSNAME_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#include +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_ZLIB_H +#include +#endif + +#include "archive.h" +#include "archive_endian.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_private.h" +#include "archive_rb.h" +#include "archive_write_private.h" + +#if defined(_WIN32) && !defined(__CYGWIN__) +#define getuid() 0 +#define getgid() 0 +#endif + +/*#define DEBUG 1*/ +#ifdef DEBUG +/* To compare to the ISO image file made by mkisofs. */ +#define COMPAT_MKISOFS 1 +#endif + +#define LOGICAL_BLOCK_BITS 11 +#define LOGICAL_BLOCK_SIZE 2048 +#define PATH_TABLE_BLOCK_SIZE 4096 + +#define SYSTEM_AREA_BLOCK 16 +#define PRIMARY_VOLUME_DESCRIPTOR_BLOCK 1 +#define SUPPLEMENTARY_VOLUME_DESCRIPTOR_BLOCK 1 +#define BOOT_RECORD_DESCRIPTOR_BLOCK 1 +#define VOLUME_DESCRIPTOR_SET_TERMINATOR_BLOCK 1 +#define NON_ISO_FILE_SYSTEM_INFORMATION_BLOCK 1 +#define RRIP_ER_BLOCK 1 +#define PADDING_BLOCK 150 + +#define FD_1_2M_SIZE (1024 * 1200) +#define FD_1_44M_SIZE (1024 * 1440) +#define FD_2_88M_SIZE (1024 * 2880) +#define MULTI_EXTENT_SIZE (ARCHIVE_LITERAL_LL(1) << 32) /* 4Gi bytes. */ +#define MAX_DEPTH 8 +#define RR_CE_SIZE 28 /* SUSP "CE" extension size */ + +#define FILE_FLAG_EXISTENCE 0x01 +#define FILE_FLAG_DIRECTORY 0x02 +#define FILE_FLAG_ASSOCIATED 0x04 +#define FILE_FLAG_RECORD 0x08 +#define FILE_FLAG_PROTECTION 0x10 +#define FILE_FLAG_MULTI_EXTENT 0x80 + +static const char rrip_identifier[] = + "RRIP_1991A"; +static const char rrip_descriptor[] = + "THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR " + "POSIX FILE SYSTEM SEMANTICS"; +static const char rrip_source[] = + "PLEASE CONTACT DISC PUBLISHER FOR SPECIFICATION SOURCE. " + "SEE PUBLISHER IDENTIFIER IN PRIMARY VOLUME DESCRIPTOR FOR " + "CONTACT INFORMATION."; +#define RRIP_ER_ID_SIZE (sizeof(rrip_identifier)-1) +#define RRIP_ER_DSC_SIZE (sizeof(rrip_descriptor)-1) +#define RRIP_ER_SRC_SIZE (sizeof(rrip_source)-1) +#define RRIP_ER_SIZE (8 + RRIP_ER_ID_SIZE + \ + RRIP_ER_DSC_SIZE + RRIP_ER_SRC_SIZE) + +static const unsigned char zisofs_magic[8] = { + 0x37, 0xE4, 0x53, 0x96, 0xC9, 0xDB, 0xD6, 0x07 +}; + +#define ZF_HEADER_SIZE 16 /* zisofs header size. */ +#define ZF_LOG2_BS 15 /* log2 block size; 32K bytes. */ +#define ZF_BLOCK_SIZE (1UL << ZF_LOG2_BS) + +/* + * Manage extra records. + */ +struct extr_rec { + int location; + int offset; + unsigned char buf[LOGICAL_BLOCK_SIZE]; + struct extr_rec *next; +}; + +struct ctl_extr_rec { + int use_extr; + unsigned char *bp; + struct isoent *isoent; + unsigned char *ce_ptr; + int cur_len; + int dr_len; + int limit; + int extr_off; + int extr_loc; +}; +#define DR_SAFETY RR_CE_SIZE +#define DR_LIMIT (254 - DR_SAFETY) + +/* + * The relation of struct isofile and isoent and archive_entry. + * + * Primary volume tree --> struct isoent + * | + * v + * struct isofile --> archive_entry + * ^ + * | + * Joliet volume tree --> struct isoent + * + * struct isoent has specific information for volume. + */ + +struct isofile { + /* Used for managing struct isofile list. */ + struct isofile *allnext; + struct isofile *datanext; + /* Used for managing a hardlinked struct isofile list. */ + struct isofile *hlnext; + struct isofile *hardlink_target; + + struct archive_entry *entry; + + /* + * Used for making a directory tree. + */ + struct archive_string parentdir; + struct archive_string basename; + struct archive_string basename_utf16; + struct archive_string symlink; + int dircnt; /* The number of elements of + * its parent directory */ + + /* + * Used for a Directory Record. + */ + struct content { + int64_t offset_of_temp; + int64_t size; + int blocks; + uint32_t location; + /* + * One extent equals one content. + * If this entry has multi extent, `next' variable points + * next content data. + */ + struct content *next; /* next content */ + } content, *cur_content; + int write_content; + + enum { + NO = 0, + BOOT_CATALOG, + BOOT_IMAGE + } boot; + + /* + * Used for a zisofs. + */ + struct { + unsigned char header_size; + unsigned char log2_bs; + uint32_t uncompressed_size; + } zisofs; +}; + +struct isoent { + /* Keep `rbnode' at the first member of struct isoent. */ + struct archive_rb_node rbnode; + + struct isofile *file; + + struct isoent *parent; + /* A list of children.(use chnext) */ + struct { + struct isoent *first; + struct isoent **last; + int cnt; + } children; + struct archive_rb_tree rbtree; + + /* A list of sub directories.(use drnext) */ + struct { + struct isoent *first; + struct isoent **last; + int cnt; + } subdirs; + /* A sorted list of sub directories. */ + struct isoent **children_sorted; + /* Used for managing struct isoent list. */ + struct isoent *chnext; + struct isoent *drnext; + struct isoent *ptnext; + + /* + * Used for making a Directory Record. + */ + int dir_number; + struct { + int vd; + int self; + int parent; + int normal; + } dr_len; + uint32_t dir_location; + int dir_block; + + /* + * Identifier: + * on primary, ISO9660 file/directory name. + * on joliet, UCS2 file/directory name. + * ext_off : offset of identifier extension. + * ext_len : length of identifier extension. + * id_len : byte size of identifier. + * on primary, this is ext_off + ext_len + version length. + * on joliet, this is ext_off + ext_len. + * mb_len : length of multibyte-character of identifier. + * on primary, mb_len and id_len are always the same. + * on joliet, mb_len and id_len are different. + */ + char *identifier; + int ext_off; + int ext_len; + int id_len; + int mb_len; + + /* + * Used for making a Rockridge extension. + * This is a part of Directory Records. + */ + struct isoent *rr_parent; + struct isoent *rr_child; + + /* Extra Record.(which we call in this source file) + * A maximum size of the Directory Record is 254. + * so, if generated RRIP data of a file cannot into a Directory + * Record because of its size, that surplus data relocate this + * Extra Record. + */ + struct { + struct extr_rec *first; + struct extr_rec **last; + struct extr_rec *current; + } extr_rec_list; + + signed int virtual:1; + /* If set to one, this file type is a directory. + * A convenience flag to be used as + * "archive_entry_filetype(isoent->file->entry) == AE_IFDIR". + */ + signed int dir:1; +}; + +struct hardlink { + struct archive_rb_node rbnode; + int nlink; + struct { + struct isofile *first; + struct isofile **last; + } file_list; +}; + +/* + * ISO writer options + */ +struct iso_option { + /* + * Usage : abstract-file= + * Type : string, max 37 bytes + * Default: Not specified + * COMPAT : mkisofs -abstract + * + * Specifies Abstract Filename. + * This file shall be described in the Root Directory + * and containing a abstract statement. + */ + unsigned int abstract_file:1; +#define OPT_ABSTRACT_FILE_DEFAULT 0 /* Not specified */ +#define ABSTRACT_FILE_SIZE 37 + + /* + * Usage : application-id= + * Type : string, max 128 bytes + * Default: Not specified + * COMPAT : mkisofs -A/-appid . + * + * Specifies Application Identifier. + * If the first byte is set to '_'(5F), the remaining + * bytes of this option shall specify an identifier + * for a file containing the identification of the + * application. + * This file shall be described in the Root Directory. + */ + unsigned int application_id:1; +#define OPT_APPLICATION_ID_DEFAULT 0 /* Use default identifier */ +#define APPLICATION_IDENTIFIER_SIZE 128 + + /* + * Usage : !allow-vernum + * Type : boolean + * Default: Enabled + * : Violates the ISO9660 standard if disable. + * COMPAT: mkisofs -N + * + * Allow filenames to use version numbers. + */ + unsigned int allow_vernum:1; +#define OPT_ALLOW_VERNUM_DEFAULT 1 /* Enabled */ + + /* + * Usage : biblio-file= + * Type : string, max 37 bytes + * Default: Not specified + * COMPAT : mkisofs -biblio + * + * Specifies Bibliographic Filename. + * This file shall be described in the Root Directory + * and containing bibliographic records. + */ + unsigned int biblio_file:1; +#define OPT_BIBLIO_FILE_DEFAULT 0 /* Not specified */ +#define BIBLIO_FILE_SIZE 37 + + /* + * Usage : boot= + * Type : string + * Default: Not specified + * COMPAT : mkisofs -b/-eltorito-boot + * + * Specifies "El Torito" boot image file to make + * a bootable CD. + */ + unsigned int boot:1; +#define OPT_BOOT_DEFAULT 0 /* Not specified */ + + /* + * Usage : boot-catalog= + * Type : string + * Default: "boot.catalog" + * COMPAT : mkisofs -c/-eltorito-catalog + * + * Specifies a fullpath of El Torito boot catalog. + */ + unsigned int boot_catalog:1; +#define OPT_BOOT_CATALOG_DEFAULT 0 /* Not specified */ + + /* + * Usage : boot-info-table + * Type : boolean + * Default: Disabled + * COMPAT : mkisofs -boot-info-table + * + * Modify the boot image file specified by `boot' + * option; ISO writer stores boot file information + * into the boot file in ISO image at offset 8 + * through offset 64. + */ + unsigned int boot_info_table:1; +#define OPT_BOOT_INFO_TABLE_DEFAULT 0 /* Disabled */ + + /* + * Usage : boot-load-seg= + * Type : hexadecimal + * Default: Not specified + * COMPAT : mkisofs -boot-load-seg + * + * Specifies a load segment for boot image. + * This is used with no-emulation mode. + */ + unsigned int boot_load_seg:1; +#define OPT_BOOT_LOAD_SEG_DEFAULT 0 /* Not specified */ + + /* + * Usage : boot-load-size= + * Type : decimal + * Default: Not specified + * COMPAT : mkisofs -boot-load-size + * + * Specifies a sector count for boot image. + * This is used with no-emulation mode. + */ + unsigned int boot_load_size:1; +#define OPT_BOOT_LOAD_SIZE_DEFAULT 0 /* Not specified */ + + /* + * Usage : boot-type= + * : 'no-emulation' : 'no emulation' image + * : 'fd' : floppy disk image + * : 'hard-disk' : hard disk image + * Type : string + * Default: Auto detect + * : We check a size of boot image; + * : If the size is just 1.22M/1.44M/2.88M, + * : we assume boot_type is 'fd'; + * : otherwise boot_type is 'no-emulation'. + * COMPAT : + * boot=no-emulation + * mkisofs -no-emul-boot + * boot=fd + * This is a default on the mkisofs. + * boot=hard-disk + * mkisofs -hard-disk-boot + * + * Specifies a type of "El Torito" boot image. + */ + unsigned int boot_type:2; +#define OPT_BOOT_TYPE_AUTO 0 /* auto detect */ +#define OPT_BOOT_TYPE_NO_EMU 1 /* ``no emulation'' image */ +#define OPT_BOOT_TYPE_FD 2 /* floppy disk image */ +#define OPT_BOOT_TYPE_HARD_DISK 3 /* hard disk image */ +#define OPT_BOOT_TYPE_DEFAULT OPT_BOOT_TYPE_AUTO + + /* + * Usage : compression-level= + * Type : decimal + * Default: Not specified + * COMPAT : NONE + * + * Specifies compression level for option zisofs=direct. + */ + unsigned int compression_level:1; +#define OPT_COMPRESSION_LEVEL_DEFAULT 0 /* Not specified */ + + /* + * Usage : copyright-file= + * Type : string, max 37 bytes + * Default: Not specified + * COMPAT : mkisofs -copyright + * + * Specifies Copyright Filename. + * This file shall be described in the Root Directory + * and containing a copyright statement. + */ + unsigned int copyright_file:1; +#define OPT_COPYRIGHT_FILE_DEFAULT 0 /* Not specified */ +#define COPYRIGHT_FILE_SIZE 37 + + /* + * Usage : gid= + * Type : decimal + * Default: Not specified + * COMPAT : mkisofs -gid + * + * Specifies a group id to rewrite the group id of all files. + */ + unsigned int gid:1; +#define OPT_GID_DEFAULT 0 /* Not specified */ + + /* + * Usage : iso-level=[1234] + * Type : decimal + * Default: 1 + * COMPAT : mkisofs -iso-level + * + * Specifies ISO9600 Level. + * Level 1: [DEFAULT] + * - limits each file size less than 4Gi bytes; + * - a File Name shall not contain more than eight + * d-characters or eight d1-characters; + * - a File Name Extension shall not contain more than + * three d-characters or three d1-characters; + * - a Directory Identifier shall not contain more + * than eight d-characters or eight d1-characters. + * Level 2: + * - limits each file size less than 4Giga bytes; + * - a File Name shall not contain more than thirty + * d-characters or thirty d1-characters; + * - a File Name Extension shall not contain more than + * thirty d-characters or thirty d1-characters; + * - a Directory Identifier shall not contain more + * than thirty-one d-characters or thirty-one + * d1-characters. + * Level 3: + * - no limit of file size; use multi extent. + * Level 4: + * - this level 4 simulates mkisofs option + * '-iso-level 4'; + * - crate a enhanced volume as mkisofs doing; + * - allow a File Name to have leading dot; + * - allow a File Name to have all ASCII letters; + * - allow a File Name to have multiple dots; + * - allow more then 8 depths of directory trees; + * - disable a version number to a File Name; + * - disable a forced period to the tail of a File Name; + * - the maximum length of files and directories is raised to 193. + * if rockridge option is disabled, raised to 207. + */ + unsigned int iso_level:3; +#define OPT_ISO_LEVEL_DEFAULT 1 /* ISO Level 1 */ + + /* + * Usage : joliet[=long] + * : !joliet + * : Do not generate Joliet Volume and Records. + * : joliet [DEFAULT] + * : Generates Joliet Volume and Directory Records. + * : [COMPAT: mkisofs -J/-joliet] + * : joliet=long + * : The joliet filenames are up to 103 Unicode + * : characters. + * : This option breaks the Joliet specification. + * : [COMPAT: mkisofs -J -joliet-long] + * Type : boolean/string + * Default: Enabled + * COMPAT : mkisofs -J / -joliet-long + * + * Generates Joliet Volume and Directory Records. + */ + unsigned int joliet:2; +#define OPT_JOLIET_DISABLE 0 /* Not generate Joliet Records. */ +#define OPT_JOLIET_ENABLE 1 /* Generate Joliet Records. */ +#define OPT_JOLIET_LONGNAME 2 /* Use long joliet filenames.*/ +#define OPT_JOLIET_DEFAULT OPT_JOLIET_ENABLE + + /* + * Usage : !limit-depth + * Type : boolean + * Default: Enabled + * : Violates the ISO9660 standard if disable. + * COMPAT : mkisofs -D/-disable-deep-relocation + * + * The number of levels in hierarchy cannot exceed eight. + */ + unsigned int limit_depth:1; +#define OPT_LIMIT_DEPTH_DEFAULT 1 /* Enabled */ + + /* + * Usage : !limit-dirs + * Type : boolean + * Default: Enabled + * : Violates the ISO9660 standard if disable. + * COMPAT : mkisofs -no-limit-pathtables + * + * Limits the number of directories less than 65536 due + * to the size of the Parent Directory Number of Path + * Table. + */ + unsigned int limit_dirs:1; +#define OPT_LIMIT_DIRS_DEFAULT 1 /* Enabled */ + + /* + * Usage : !pad + * Type : boolean + * Default: Enabled + * COMPAT : -pad/-no-pad + * + * Pads the end of the ISO image by null of 300Ki bytes. + */ + unsigned int pad:1; +#define OPT_PAD_DEFAULT 1 /* Enabled */ + + /* + * Usage : publisher= + * Type : string, max 128 bytes + * Default: Not specified + * COMPAT : mkisofs -publisher + * + * Specifies Publisher Identifier. + * If the first byte is set to '_'(5F), the remaining + * bytes of this option shall specify an identifier + * for a file containing the identification of the user. + * This file shall be described in the Root Directory. + */ + unsigned int publisher:1; +#define OPT_PUBLISHER_DEFAULT 0 /* Not specified */ +#define PUBLISHER_IDENTIFIER_SIZE 128 + + /* + * Usage : rockridge + * : !rockridge + * : disable to generate SUSP and RR records. + * : rockridge + * : the same as 'rockridge=useful'. + * : rockridge=strict + * : generate SUSP and RR records. + * : [COMPAT: mkisofs -R] + * : rockridge=useful [DEFAULT] + * : generate SUSP and RR records. + * : [COMPAT: mkisofs -r] + * : NOTE Our rockridge=useful option does not set a zero + * : to uid and gid, you should use application + * : option such as --gid,--gname,--uid and --uname + * : bsdtar options instead. + * Type : boolean/string + * Default: Enabled as rockridge=useful + * COMPAT : mkisofs -r / -R + * + * Generates SUSP and RR records. + */ + unsigned int rr:2; +#define OPT_RR_DISABLED 0 +#define OPT_RR_STRICT 1 +#define OPT_RR_USEFUL 2 +#define OPT_RR_DEFAULT OPT_RR_USEFUL + + /* + * Usage : volume-id= + * Type : string, max 32 bytes + * Default: Not specified + * COMPAT : mkisofs -V + * + * Specifies Volume Identifier. + */ + unsigned int volume_id:1; +#define OPT_VOLUME_ID_DEFAULT 0 /* Use default identifier */ +#define VOLUME_IDENTIFIER_SIZE 32 + + /* + * Usage : !zisofs [DEFAULT] + * : Disable to generate RRIP 'ZF' extension. + * : zisofs + * : Make files zisofs file and generate RRIP 'ZF' + * : extension. So you do not need mkzftree utility + * : for making zisofs. + * : When the file size is less than one Logical Block + * : size, that file will not zisofs'ed since it does + * : reduce an ISO-image size. + * : + * : When you specify option 'boot=', that + * : 'boot-image' file won't be converted to zisofs file. + * Type : boolean + * Default: Disabled + * + * Generates RRIP 'ZF' System Use Entry. + */ + unsigned int zisofs:1; +#define OPT_ZISOFS_DISABLED 0 +#define OPT_ZISOFS_DIRECT 1 +#define OPT_ZISOFS_DEFAULT OPT_ZISOFS_DISABLED + +}; + +struct iso9660 { + /* The creation time of ISO image. */ + time_t birth_time; + /* A file stream of a temporary file, which file contents + * save to until ISO image can be created. */ + int temp_fd; + + struct isofile *cur_file; + struct isoent *cur_dirent; + struct archive_string cur_dirstr; + uint64_t bytes_remaining; + int need_multi_extent; + + /* Temporary string buffer for Joliet extension. */ + struct archive_string utf16be; + struct archive_string mbs; + + struct archive_string_conv *sconv_to_utf16be; + struct archive_string_conv *sconv_from_utf16be; + + /* A list of all of struct isofile entries. */ + struct { + struct isofile *first; + struct isofile **last; + } all_file_list; + + /* A list of struct isofile entries which have its + * contents and are not a directory, a hardlinked file + * and a symlink file. */ + struct { + struct isofile *first; + struct isofile **last; + } data_file_list; + + /* Used for managing to find hardlinking files. */ + struct archive_rb_tree hardlink_rbtree; + + /* Used for making the Path Table Record. */ + struct vdd { + /* the root of entry tree. */ + struct isoent *rootent; + enum vdd_type { + VDD_PRIMARY, + VDD_JOLIET, + VDD_ENHANCED + } vdd_type; + + struct path_table { + struct isoent *first; + struct isoent **last; + struct isoent **sorted; + int cnt; + } *pathtbl; + int max_depth; + + int path_table_block; + int path_table_size; + int location_type_L_path_table; + int location_type_M_path_table; + int total_dir_block; + } primary, joliet; + + /* Used for making a Volume Descriptor. */ + int volume_space_size; + int volume_sequence_number; + int total_file_block; + struct archive_string volume_identifier; + struct archive_string publisher_identifier; + struct archive_string data_preparer_identifier; + struct archive_string application_identifier; + struct archive_string copyright_file_identifier; + struct archive_string abstract_file_identifier; + struct archive_string bibliographic_file_identifier; + + /* Used for making rockridge extensions. */ + int location_rrip_er; + + /* Used for making zisofs. */ + struct { + signed int detect_magic:1; + signed int making:1; + signed int allzero:1; + unsigned char magic_buffer[64]; + int magic_cnt; + +#ifdef HAVE_ZLIB_H + /* + * Copy a compressed file to iso9660.zisofs.temp_fd + * and also copy a uncompressed file(original file) to + * iso9660.temp_fd . If the number of logical block + * of the compressed file is less than the number of + * logical block of the uncompressed file, use it and + * remove the copy of the uncompressed file. + * but if not, we use uncompressed file and remove + * the copy of the compressed file. + */ + uint32_t *block_pointers; + size_t block_pointers_allocated; + int block_pointers_cnt; + int block_pointers_idx; + int64_t total_size; + int64_t block_offset; + + z_stream stream; + int stream_valid; + int64_t remaining; + int compression_level; +#endif + } zisofs; + + struct isoent *directories_too_deep; + int dircnt_max; + + /* Write buffer. */ +#define wb_buffmax() (LOGICAL_BLOCK_SIZE * 32) +#define wb_remaining(a) (((struct iso9660 *)(a)->format_data)->wbuff_remaining) +#define wb_offset(a) (((struct iso9660 *)(a)->format_data)->wbuff_offset \ + + wb_buffmax() - wb_remaining(a)) + unsigned char wbuff[LOGICAL_BLOCK_SIZE * 32]; + size_t wbuff_remaining; + enum { + WB_TO_STREAM, + WB_TO_TEMP + } wbuff_type; + int64_t wbuff_offset; + int64_t wbuff_written; + int64_t wbuff_tail; + + /* 'El Torito' boot data. */ + struct { + /* boot catalog file */ + struct archive_string catalog_filename; + struct isoent *catalog; + /* boot image file */ + struct archive_string boot_filename; + struct isoent *boot; + + unsigned char platform_id; +#define BOOT_PLATFORM_X86 0 +#define BOOT_PLATFORM_PPC 1 +#define BOOT_PLATFORM_MAC 2 + struct archive_string id; + unsigned char media_type; +#define BOOT_MEDIA_NO_EMULATION 0 +#define BOOT_MEDIA_1_2M_DISKETTE 1 +#define BOOT_MEDIA_1_44M_DISKETTE 2 +#define BOOT_MEDIA_2_88M_DISKETTE 3 +#define BOOT_MEDIA_HARD_DISK 4 + unsigned char system_type; + uint16_t boot_load_seg; + uint16_t boot_load_size; +#define BOOT_LOAD_SIZE 4 + } el_torito; + + struct iso_option opt; +}; + +/* + * Types of Volume Descriptor + */ +enum VD_type { + VDT_BOOT_RECORD=0, /* Boot Record Volume Descriptor */ + VDT_PRIMARY=1, /* Primary Volume Descriptor */ + VDT_SUPPLEMENTARY=2, /* Supplementary Volume Descriptor */ + VDT_TERMINATOR=255 /* Volume Descriptor Set Terminator */ +}; + +/* + * Types of Directory Record + */ +enum dir_rec_type { + DIR_REC_VD, /* Stored in Volume Descriptor. */ + DIR_REC_SELF, /* Stored as Current Directory. */ + DIR_REC_PARENT, /* Stored as Parent Directory. */ + DIR_REC_NORMAL /* Stored as Child. */ +}; + +/* + * Kinds of Volume Descriptor Character + */ +enum vdc { + VDC_STD, + VDC_LOWERCASE, + VDC_UCS2, + VDC_UCS2_DIRECT +}; + +/* + * IDentifier Resolver. + * Used for resolving duplicated filenames. + */ +struct idr { + struct idrent { + struct archive_rb_node rbnode; + /* Used in wait_list. */ + struct idrent *wnext; + struct idrent *avail; + + struct isoent *isoent; + int weight; + int noff; + int rename_num; + } *idrent_pool; + + struct archive_rb_tree rbtree; + + struct { + struct idrent *first; + struct idrent **last; + } wait_list; + + int pool_size; + int pool_idx; + int num_size; + int null_size; + + char char_map[0x80]; +}; + +enum char_type { + A_CHAR, + D_CHAR +}; + + +static int iso9660_options(struct archive_write *, + const char *, const char *); +static int iso9660_write_header(struct archive_write *, + struct archive_entry *); +static ssize_t iso9660_write_data(struct archive_write *, + const void *, size_t); +static int iso9660_finish_entry(struct archive_write *); +static int iso9660_close(struct archive_write *); +static int iso9660_free(struct archive_write *); + +static void get_system_identitier(char *, size_t); +static void set_str(unsigned char *, const char *, size_t, char, + const char *); +static inline int joliet_allowed_char(unsigned char, unsigned char); +static int set_str_utf16be(struct archive_write *, unsigned char *, + const char *, size_t, uint16_t, enum vdc); +static int set_str_a_characters_bp(struct archive_write *, + unsigned char *, int, int, const char *, enum vdc); +static int set_str_d_characters_bp(struct archive_write *, + unsigned char *, int, int, const char *, enum vdc); +static void set_VD_bp(unsigned char *, enum VD_type, unsigned char); +static inline void set_unused_field_bp(unsigned char *, int, int); + +static unsigned char *extra_open_record(unsigned char *, int, + struct isoent *, struct ctl_extr_rec *); +static void extra_close_record(struct ctl_extr_rec *, int); +static unsigned char * extra_next_record(struct ctl_extr_rec *, int); +static unsigned char *extra_get_record(struct isoent *, int *, int *, int *); +static void extra_tell_used_size(struct ctl_extr_rec *, int); +static int extra_setup_location(struct isoent *, int); +static int set_directory_record_rr(unsigned char *, int, + struct isoent *, struct iso9660 *, enum dir_rec_type); +static int set_directory_record(unsigned char *, size_t, + struct isoent *, struct iso9660 *, enum dir_rec_type, + enum vdd_type); +static inline int get_dir_rec_size(struct iso9660 *, struct isoent *, + enum dir_rec_type, enum vdd_type); +static inline unsigned char *wb_buffptr(struct archive_write *); +static int wb_write_out(struct archive_write *); +static int wb_consume(struct archive_write *, size_t); +#ifdef HAVE_ZLIB_H +static int wb_set_offset(struct archive_write *, int64_t); +#endif +static int write_null(struct archive_write *, size_t); +static int write_VD_terminator(struct archive_write *); +static int set_file_identifier(unsigned char *, int, int, enum vdc, + struct archive_write *, struct vdd *, + struct archive_string *, const char *, int, + enum char_type); +static int write_VD(struct archive_write *, struct vdd *); +static int write_VD_boot_record(struct archive_write *); +static int write_information_block(struct archive_write *); +static int write_path_table(struct archive_write *, int, + struct vdd *); +static int write_directory_descriptors(struct archive_write *, + struct vdd *); +static int write_file_descriptors(struct archive_write *); +static int write_rr_ER(struct archive_write *); +static void calculate_path_table_size(struct vdd *); + +static void isofile_init_entry_list(struct iso9660 *); +static void isofile_add_entry(struct iso9660 *, struct isofile *); +static void isofile_free_all_entries(struct iso9660 *); +static void isofile_init_entry_data_file_list(struct iso9660 *); +static void isofile_add_data_file(struct iso9660 *, struct isofile *); +static struct isofile * isofile_new(struct archive_write *, + struct archive_entry *); +static void isofile_free(struct isofile *); +static int isofile_gen_utility_names(struct archive_write *, + struct isofile *); +static int isofile_register_hardlink(struct archive_write *, + struct isofile *); +static void isofile_connect_hardlink_files(struct iso9660 *); +static void isofile_init_hardlinks(struct iso9660 *); +static void isofile_free_hardlinks(struct iso9660 *); + +static struct isoent *isoent_new(struct isofile *); +static int isoent_clone_tree(struct archive_write *, + struct isoent **, struct isoent *); +static void _isoent_free(struct isoent *isoent); +static void isoent_free_all(struct isoent *); +static struct isoent * isoent_create_virtual_dir(struct archive_write *, + struct iso9660 *, const char *); +static int isoent_cmp_node(const struct archive_rb_node *, + const struct archive_rb_node *); +static int isoent_cmp_key(const struct archive_rb_node *, + const void *); +static int isoent_add_child_head(struct isoent *, struct isoent *); +static int isoent_add_child_tail(struct isoent *, struct isoent *); +static void isoent_remove_child(struct isoent *, struct isoent *); +static void isoent_setup_directory_location(struct iso9660 *, + int, struct vdd *); +static void isoent_setup_file_location(struct iso9660 *, int); +static int get_path_component(char *, size_t, const char *); +static int isoent_tree(struct archive_write *, struct isoent **); +static struct isoent *isoent_find_child(struct isoent *, const char *); +static struct isoent *isoent_find_entry(struct isoent *, const char *); +static void idr_relaxed_filenames(char *); +static void idr_init(struct iso9660 *, struct vdd *, struct idr *); +static void idr_cleanup(struct idr *); +static int idr_ensure_poolsize(struct archive_write *, struct idr *, + int); +static int idr_start(struct archive_write *, struct idr *, + int, int, int, int, const struct archive_rb_tree_ops *); +static void idr_register(struct idr *, struct isoent *, int, + int); +static void idr_extend_identifier(struct idrent *, int, int); +static void idr_resolve(struct idr *, void (*)(unsigned char *, int)); +static void idr_set_num(unsigned char *, int); +static void idr_set_num_beutf16(unsigned char *, int); +static int isoent_gen_iso9660_identifier(struct archive_write *, + struct isoent *, struct idr *); +static int isoent_gen_joliet_identifier(struct archive_write *, + struct isoent *, struct idr *); +static int isoent_cmp_iso9660_identifier(const struct isoent *, + const struct isoent *); +static int isoent_cmp_node_iso9660(const struct archive_rb_node *, + const struct archive_rb_node *); +static int isoent_cmp_key_iso9660(const struct archive_rb_node *, + const void *); +static int isoent_cmp_joliet_identifier(const struct isoent *, + const struct isoent *); +static int isoent_cmp_node_joliet(const struct archive_rb_node *, + const struct archive_rb_node *); +static int isoent_cmp_key_joliet(const struct archive_rb_node *, + const void *); +static inline void path_table_add_entry(struct path_table *, struct isoent *); +static inline struct isoent * path_table_last_entry(struct path_table *); +static int isoent_make_path_table(struct archive_write *); +static int isoent_find_out_boot_file(struct archive_write *, + struct isoent *); +static int isoent_create_boot_catalog(struct archive_write *, + struct isoent *); +static size_t fd_boot_image_size(int); +static int make_boot_catalog(struct archive_write *); +static int setup_boot_information(struct archive_write *); + +static int zisofs_init(struct archive_write *, struct isofile *); +static void zisofs_detect_magic(struct archive_write *, + const void *, size_t); +static int zisofs_write_to_temp(struct archive_write *, + const void *, size_t); +static int zisofs_finish_entry(struct archive_write *); +static int zisofs_rewind_boot_file(struct archive_write *); +static int zisofs_free(struct archive_write *); + +int +archive_write_set_format_iso9660(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct iso9660 *iso9660; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_set_format_iso9660"); + + /* If another format was already registered, unregister it. */ + if (a->format_free != NULL) + (a->format_free)(a); + + iso9660 = calloc(1, sizeof(*iso9660)); + if (iso9660 == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate iso9660 data"); + return (ARCHIVE_FATAL); + } + iso9660->birth_time = 0; + iso9660->temp_fd = -1; + iso9660->cur_file = NULL; + iso9660->primary.max_depth = 0; + iso9660->primary.vdd_type = VDD_PRIMARY; + iso9660->primary.pathtbl = NULL; + iso9660->joliet.rootent = NULL; + iso9660->joliet.max_depth = 0; + iso9660->joliet.vdd_type = VDD_JOLIET; + iso9660->joliet.pathtbl = NULL; + isofile_init_entry_list(iso9660); + isofile_init_entry_data_file_list(iso9660); + isofile_init_hardlinks(iso9660); + iso9660->directories_too_deep = NULL; + iso9660->dircnt_max = 1; + iso9660->wbuff_remaining = wb_buffmax(); + iso9660->wbuff_type = WB_TO_TEMP; + iso9660->wbuff_offset = 0; + iso9660->wbuff_written = 0; + iso9660->wbuff_tail = 0; + archive_string_init(&(iso9660->utf16be)); + archive_string_init(&(iso9660->mbs)); + + /* + * Init Identifiers used for PVD and SVD. + */ + archive_string_init(&(iso9660->volume_identifier)); + archive_strcpy(&(iso9660->volume_identifier), "CDROM"); + archive_string_init(&(iso9660->publisher_identifier)); + archive_string_init(&(iso9660->data_preparer_identifier)); + archive_string_init(&(iso9660->application_identifier)); + archive_strcpy(&(iso9660->application_identifier), + archive_version_string()); + archive_string_init(&(iso9660->copyright_file_identifier)); + archive_string_init(&(iso9660->abstract_file_identifier)); + archive_string_init(&(iso9660->bibliographic_file_identifier)); + + /* + * Init El Torito bootable CD variables. + */ + archive_string_init(&(iso9660->el_torito.catalog_filename)); + iso9660->el_torito.catalog = NULL; + /* Set default file name of boot catalog */ + archive_strcpy(&(iso9660->el_torito.catalog_filename), + "boot.catalog"); + archive_string_init(&(iso9660->el_torito.boot_filename)); + iso9660->el_torito.boot = NULL; + iso9660->el_torito.platform_id = BOOT_PLATFORM_X86; + archive_string_init(&(iso9660->el_torito.id)); + iso9660->el_torito.boot_load_seg = 0; + iso9660->el_torito.boot_load_size = BOOT_LOAD_SIZE; + + /* + * Init zisofs variables. + */ +#ifdef HAVE_ZLIB_H + iso9660->zisofs.block_pointers = NULL; + iso9660->zisofs.block_pointers_allocated = 0; + iso9660->zisofs.stream_valid = 0; + iso9660->zisofs.compression_level = 9; + memset(&(iso9660->zisofs.stream), 0, + sizeof(iso9660->zisofs.stream)); +#endif + + /* + * Set default value of iso9660 options. + */ + iso9660->opt.abstract_file = OPT_ABSTRACT_FILE_DEFAULT; + iso9660->opt.application_id = OPT_APPLICATION_ID_DEFAULT; + iso9660->opt.allow_vernum = OPT_ALLOW_VERNUM_DEFAULT; + iso9660->opt.biblio_file = OPT_BIBLIO_FILE_DEFAULT; + iso9660->opt.boot = OPT_BOOT_DEFAULT; + iso9660->opt.boot_catalog = OPT_BOOT_CATALOG_DEFAULT; + iso9660->opt.boot_info_table = OPT_BOOT_INFO_TABLE_DEFAULT; + iso9660->opt.boot_load_seg = OPT_BOOT_LOAD_SEG_DEFAULT; + iso9660->opt.boot_load_size = OPT_BOOT_LOAD_SIZE_DEFAULT; + iso9660->opt.boot_type = OPT_BOOT_TYPE_DEFAULT; + iso9660->opt.compression_level = OPT_COMPRESSION_LEVEL_DEFAULT; + iso9660->opt.copyright_file = OPT_COPYRIGHT_FILE_DEFAULT; + iso9660->opt.iso_level = OPT_ISO_LEVEL_DEFAULT; + iso9660->opt.joliet = OPT_JOLIET_DEFAULT; + iso9660->opt.limit_depth = OPT_LIMIT_DEPTH_DEFAULT; + iso9660->opt.limit_dirs = OPT_LIMIT_DIRS_DEFAULT; + iso9660->opt.pad = OPT_PAD_DEFAULT; + iso9660->opt.publisher = OPT_PUBLISHER_DEFAULT; + iso9660->opt.rr = OPT_RR_DEFAULT; + iso9660->opt.volume_id = OPT_VOLUME_ID_DEFAULT; + iso9660->opt.zisofs = OPT_ZISOFS_DEFAULT; + + /* Create the root directory. */ + iso9660->primary.rootent = + isoent_create_virtual_dir(a, iso9660, ""); + if (iso9660->primary.rootent == NULL) { + free(iso9660); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + iso9660->primary.rootent->parent = iso9660->primary.rootent; + iso9660->cur_dirent = iso9660->primary.rootent; + archive_string_init(&(iso9660->cur_dirstr)); + archive_string_ensure(&(iso9660->cur_dirstr), 1); + iso9660->cur_dirstr.s[0] = 0; + iso9660->sconv_to_utf16be = NULL; + iso9660->sconv_from_utf16be = NULL; + + a->format_data = iso9660; + a->format_name = "iso9660"; + a->format_options = iso9660_options; + a->format_write_header = iso9660_write_header; + a->format_write_data = iso9660_write_data; + a->format_finish_entry = iso9660_finish_entry; + a->format_close = iso9660_close; + a->format_free = iso9660_free; + a->archive.archive_format = ARCHIVE_FORMAT_ISO9660; + a->archive.archive_format_name = "ISO9660"; + + return (ARCHIVE_OK); +} + +static int +get_str_opt(struct archive_write *a, struct archive_string *s, + size_t maxsize, const char *key, const char *value) +{ + + if (strlen(value) > maxsize) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Value is longer than %zu characters " + "for option ``%s''", maxsize, key); + return (ARCHIVE_FATAL); + } + archive_strcpy(s, value); + return (ARCHIVE_OK); +} + +static int +get_num_opt(struct archive_write *a, int *num, int high, int low, + const char *key, const char *value) +{ + const char *p = value; + int data = 0; + int neg = 0; + + if (p == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid value(empty) for option ``%s''", key); + return (ARCHIVE_FATAL); + } + if (*p == '-') { + neg = 1; + p++; + } + while (*p) { + if (*p >= '0' && *p <= '9') + data = data * 10 + *p - '0'; + else { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid value for option ``%s''", key); + return (ARCHIVE_FATAL); + } + if (data > high) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid value(over %d) for " + "option ``%s''", high, key); + return (ARCHIVE_FATAL); + } + if (data < low) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid value(under %d) for " + "option ``%s''", low, key); + return (ARCHIVE_FATAL); + } + p++; + } + if (neg) + data *= -1; + *num = data; + + return (ARCHIVE_OK); +} + +static int +iso9660_options(struct archive_write *a, const char *key, const char *value) +{ + struct iso9660 *iso9660 = a->format_data; + const char *p; + int r; + + switch (key[0]) { + case 'a': + if (strcmp(key, "abstract-file") == 0) { + r = get_str_opt(a, + &(iso9660->abstract_file_identifier), + ABSTRACT_FILE_SIZE, key, value); + iso9660->opt.abstract_file = r == ARCHIVE_OK; + return (r); + } + if (strcmp(key, "application-id") == 0) { + r = get_str_opt(a, + &(iso9660->application_identifier), + APPLICATION_IDENTIFIER_SIZE, key, value); + iso9660->opt.application_id = r == ARCHIVE_OK; + return (r); + } + if (strcmp(key, "allow-vernum") == 0) { + iso9660->opt.allow_vernum = value != NULL; + return (ARCHIVE_OK); + } + break; + case 'b': + if (strcmp(key, "biblio-file") == 0) { + r = get_str_opt(a, + &(iso9660->bibliographic_file_identifier), + BIBLIO_FILE_SIZE, key, value); + iso9660->opt.biblio_file = r == ARCHIVE_OK; + return (r); + } + if (strcmp(key, "boot") == 0) { + if (value == NULL) + iso9660->opt.boot = 0; + else { + iso9660->opt.boot = 1; + archive_strcpy( + &(iso9660->el_torito.boot_filename), + value); + } + return (ARCHIVE_OK); + } + if (strcmp(key, "boot-catalog") == 0) { + r = get_str_opt(a, + &(iso9660->el_torito.catalog_filename), + 1024, key, value); + iso9660->opt.boot_catalog = r == ARCHIVE_OK; + return (r); + } + if (strcmp(key, "boot-info-table") == 0) { + iso9660->opt.boot_info_table = value != NULL; + return (ARCHIVE_OK); + } + if (strcmp(key, "boot-load-seg") == 0) { + uint32_t seg; + + iso9660->opt.boot_load_seg = 0; + if (value == NULL) + goto invalid_value; + seg = 0; + p = value; + if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) + p += 2; + while (*p) { + if (seg) + seg <<= 4; + if (*p >= 'A' && *p <= 'F') + seg += *p - 'A' + 0x0a; + else if (*p >= 'a' && *p <= 'f') + seg += *p - 'a' + 0x0a; + else if (*p >= '0' && *p <= '9') + seg += *p - '0'; + else + goto invalid_value; + if (seg > 0xffff) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Invalid value(over 0xffff) for " + "option ``%s''", key); + return (ARCHIVE_FATAL); + } + p++; + } + iso9660->el_torito.boot_load_seg = (uint16_t)seg; + iso9660->opt.boot_load_seg = 1; + return (ARCHIVE_OK); + } + if (strcmp(key, "boot-load-size") == 0) { + int num = 0; + r = get_num_opt(a, &num, 0xffff, 1, key, value); + iso9660->opt.boot_load_size = r == ARCHIVE_OK; + if (r != ARCHIVE_OK) + return (ARCHIVE_FATAL); + iso9660->el_torito.boot_load_size = (uint16_t)num; + return (ARCHIVE_OK); + } + if (strcmp(key, "boot-type") == 0) { + if (value == NULL) + goto invalid_value; + if (strcmp(value, "no-emulation") == 0) + iso9660->opt.boot_type = OPT_BOOT_TYPE_NO_EMU; + else if (strcmp(value, "fd") == 0) + iso9660->opt.boot_type = OPT_BOOT_TYPE_FD; + else if (strcmp(value, "hard-disk") == 0) + iso9660->opt.boot_type = OPT_BOOT_TYPE_HARD_DISK; + else + goto invalid_value; + return (ARCHIVE_OK); + } + break; + case 'c': + if (strcmp(key, "compression-level") == 0) { +#ifdef HAVE_ZLIB_H + if (value == NULL || + !(value[0] >= '0' && value[0] <= '9') || + value[1] != '\0') + goto invalid_value; + iso9660->zisofs.compression_level = value[0] - '0'; + iso9660->opt.compression_level = 1; + return (ARCHIVE_OK); +#else + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Option ``%s'' " + "is not supported on this platform.", key); + return (ARCHIVE_FATAL); +#endif + } + if (strcmp(key, "copyright-file") == 0) { + r = get_str_opt(a, + &(iso9660->copyright_file_identifier), + COPYRIGHT_FILE_SIZE, key, value); + iso9660->opt.copyright_file = r == ARCHIVE_OK; + return (r); + } +#ifdef DEBUG + /* Specifies Volume creation date and time; + * year(4),month(2),day(2),hour(2),minute(2),second(2). + * e.g. "20090929033757" + */ + if (strcmp(key, "creation") == 0) { + struct tm tm; + char buf[5]; + + p = value; + if (p == NULL || strlen(p) < 14) + goto invalid_value; + memset(&tm, 0, sizeof(tm)); + memcpy(buf, p, 4); buf[4] = '\0'; p += 4; + tm.tm_year = strtol(buf, NULL, 10) - 1900; + memcpy(buf, p, 2); buf[2] = '\0'; p += 2; + tm.tm_mon = strtol(buf, NULL, 10) - 1; + memcpy(buf, p, 2); buf[2] = '\0'; p += 2; + tm.tm_mday = strtol(buf, NULL, 10); + memcpy(buf, p, 2); buf[2] = '\0'; p += 2; + tm.tm_hour = strtol(buf, NULL, 10); + memcpy(buf, p, 2); buf[2] = '\0'; p += 2; + tm.tm_min = strtol(buf, NULL, 10); + memcpy(buf, p, 2); buf[2] = '\0'; + tm.tm_sec = strtol(buf, NULL, 10); + iso9660->birth_time = mktime(&tm); + return (ARCHIVE_OK); + } +#endif + break; + case 'i': + if (strcmp(key, "iso-level") == 0) { + if (value != NULL && value[1] == '\0' && + (value[0] >= '1' && value[0] <= '4')) { + iso9660->opt.iso_level = value[0]-'0'; + return (ARCHIVE_OK); + } + goto invalid_value; + } + break; + case 'j': + if (strcmp(key, "joliet") == 0) { + if (value == NULL) + iso9660->opt.joliet = OPT_JOLIET_DISABLE; + else if (strcmp(value, "1") == 0) + iso9660->opt.joliet = OPT_JOLIET_ENABLE; + else if (strcmp(value, "long") == 0) + iso9660->opt.joliet = OPT_JOLIET_LONGNAME; + else + goto invalid_value; + return (ARCHIVE_OK); + } + break; + case 'l': + if (strcmp(key, "limit-depth") == 0) { + iso9660->opt.limit_depth = value != NULL; + return (ARCHIVE_OK); + } + if (strcmp(key, "limit-dirs") == 0) { + iso9660->opt.limit_dirs = value != NULL; + return (ARCHIVE_OK); + } + break; + case 'p': + if (strcmp(key, "pad") == 0) { + iso9660->opt.pad = value != NULL; + return (ARCHIVE_OK); + } + if (strcmp(key, "publisher") == 0) { + r = get_str_opt(a, + &(iso9660->publisher_identifier), + PUBLISHER_IDENTIFIER_SIZE, key, value); + iso9660->opt.publisher = r == ARCHIVE_OK; + return (r); + } + break; + case 'r': + if (strcmp(key, "rockridge") == 0 || + strcmp(key, "Rockridge") == 0) { + if (value == NULL) + iso9660->opt.rr = OPT_RR_DISABLED; + else if (strcmp(value, "1") == 0) + iso9660->opt.rr = OPT_RR_USEFUL; + else if (strcmp(value, "strict") == 0) + iso9660->opt.rr = OPT_RR_STRICT; + else if (strcmp(value, "useful") == 0) + iso9660->opt.rr = OPT_RR_USEFUL; + else + goto invalid_value; + return (ARCHIVE_OK); + } + break; + case 'v': + if (strcmp(key, "volume-id") == 0) { + r = get_str_opt(a, &(iso9660->volume_identifier), + VOLUME_IDENTIFIER_SIZE, key, value); + iso9660->opt.volume_id = r == ARCHIVE_OK; + return (r); + } + break; + case 'z': + if (strcmp(key, "zisofs") == 0) { + if (value == NULL) + iso9660->opt.zisofs = OPT_ZISOFS_DISABLED; + else { +#ifdef HAVE_ZLIB_H + iso9660->opt.zisofs = OPT_ZISOFS_DIRECT; +#else + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "``zisofs'' " + "is not supported on this platform."); + return (ARCHIVE_FATAL); +#endif + } + return (ARCHIVE_OK); + } + break; + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); + +invalid_value: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid value for option ``%s''", key); + return (ARCHIVE_FAILED); +} + +static int +iso9660_write_header(struct archive_write *a, struct archive_entry *entry) +{ + struct iso9660 *iso9660; + struct isofile *file; + struct isoent *isoent; + int r, ret = ARCHIVE_OK; + + iso9660 = a->format_data; + + iso9660->cur_file = NULL; + iso9660->bytes_remaining = 0; + iso9660->need_multi_extent = 0; + if (archive_entry_filetype(entry) == AE_IFLNK + && iso9660->opt.rr == OPT_RR_DISABLED) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Ignore symlink file."); + iso9660->cur_file = NULL; + return (ARCHIVE_WARN); + } + if (archive_entry_filetype(entry) == AE_IFREG && + archive_entry_size(entry) >= MULTI_EXTENT_SIZE) { + if (iso9660->opt.iso_level < 3) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Ignore over %lld bytes file. " + "This file too large.", + MULTI_EXTENT_SIZE); + iso9660->cur_file = NULL; + return (ARCHIVE_WARN); + } + iso9660->need_multi_extent = 1; + } + + file = isofile_new(a, entry); + if (file == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate data"); + return (ARCHIVE_FATAL); + } + r = isofile_gen_utility_names(a, file); + if (r < ARCHIVE_WARN) { + isofile_free(file); + return (r); + } + else if (r < ret) + ret = r; + + /* + * Ignore a path which looks like the top of directory name + * since we have already made the root directory of an ISO image. + */ + if (archive_strlen(&(file->parentdir)) == 0 && + archive_strlen(&(file->basename)) == 0) { + isofile_free(file); + return (r); + } + + isofile_add_entry(iso9660, file); + isoent = isoent_new(file); + if (isoent == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate data"); + return (ARCHIVE_FATAL); + } + if (isoent->file->dircnt > iso9660->dircnt_max) + iso9660->dircnt_max = isoent->file->dircnt; + + /* Add the current file into tree */ + r = isoent_tree(a, &isoent); + if (r != ARCHIVE_OK) + return (r); + + /* If there is the same file in tree and + * the current file is older than the file in tree. + * So we don't need the current file data anymore. */ + if (isoent->file != file) + return (ARCHIVE_OK); + + /* Non regular files contents are unneeded to be saved to + * temporary files. */ + if (archive_entry_filetype(file->entry) != AE_IFREG) + return (ret); + + /* + * Set the current file to cur_file to read its contents. + */ + iso9660->cur_file = file; + + if (archive_entry_nlink(file->entry) > 1) { + r = isofile_register_hardlink(a, file); + if (r != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + + /* + * Prepare to save the contents of the file. + */ + if (iso9660->temp_fd < 0) { + iso9660->temp_fd = __archive_mktemp(NULL); + if (iso9660->temp_fd < 0) { + archive_set_error(&a->archive, errno, + "Couldn't create temporary file"); + return (ARCHIVE_FATAL); + } + } + + /* Save an offset of current file in temporary file. */ + file->content.offset_of_temp = wb_offset(a); + file->cur_content = &(file->content); + r = zisofs_init(a, file); + if (r < ret) + ret = r; + iso9660->bytes_remaining = archive_entry_size(file->entry); + + return (ret); +} + +static int +write_to_temp(struct archive_write *a, const void *buff, size_t s) +{ + struct iso9660 *iso9660 = a->format_data; + ssize_t written; + const unsigned char *b; + + b = (const unsigned char *)buff; + while (s) { + written = write(iso9660->temp_fd, b, s); + if (written < 0) { + archive_set_error(&a->archive, errno, + "Can't write to temporary file"); + return (ARCHIVE_FATAL); + } + s -= written; + b += written; + } + return (ARCHIVE_OK); +} + +static int +wb_write_to_temp(struct archive_write *a, const void *buff, size_t s) +{ + const char *xp = buff; + size_t xs = s; + + /* + * If a written data size is big enough to use system-call + * and there is no waiting data, this calls write_to_temp() in + * order to reduce a extra memory copy. + */ + if (wb_remaining(a) == wb_buffmax() && s > (1024 * 16)) { + struct iso9660 *iso9660 = (struct iso9660 *)a->format_data; + xs = s % LOGICAL_BLOCK_SIZE; + iso9660->wbuff_offset += s - xs; + if (write_to_temp(a, buff, s - xs) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + if (xs == 0) + return (ARCHIVE_OK); + xp += s - xs; + } + + while (xs) { + size_t size = xs; + if (size > wb_remaining(a)) + size = wb_remaining(a); + memcpy(wb_buffptr(a), xp, size); + if (wb_consume(a, size) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + xs -= size; + xp += size; + } + return (ARCHIVE_OK); +} + +static int +wb_write_padding_to_temp(struct archive_write *a, int64_t csize) +{ + size_t ns; + int ret; + + ns = (size_t)(csize % LOGICAL_BLOCK_SIZE); + if (ns != 0) + ret = write_null(a, LOGICAL_BLOCK_SIZE - ns); + else + ret = ARCHIVE_OK; + return (ret); +} + +static ssize_t +write_iso9660_data(struct archive_write *a, const void *buff, size_t s) +{ + struct iso9660 *iso9660 = a->format_data; + size_t ws; + + if (iso9660->temp_fd < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Couldn't create temporary file"); + return (ARCHIVE_FATAL); + } + + ws = s; + if (iso9660->need_multi_extent && + (iso9660->cur_file->cur_content->size + ws) >= + (MULTI_EXTENT_SIZE - LOGICAL_BLOCK_SIZE)) { + struct content *con; + size_t ts; + + ts = (size_t)(MULTI_EXTENT_SIZE - LOGICAL_BLOCK_SIZE - + iso9660->cur_file->cur_content->size); + + if (iso9660->zisofs.detect_magic) + zisofs_detect_magic(a, buff, ts); + + if (iso9660->zisofs.making) { + if (zisofs_write_to_temp(a, buff, ts) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } else { + if (wb_write_to_temp(a, buff, ts) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + iso9660->cur_file->cur_content->size += ts; + } + + /* Write padding. */ + if (wb_write_padding_to_temp(a, + iso9660->cur_file->cur_content->size) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Compute the logical block number. */ + iso9660->cur_file->cur_content->blocks = (int) + ((iso9660->cur_file->cur_content->size + + LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS); + + /* + * Make next extent. + */ + ws -= ts; + buff = (const void *)(((const unsigned char *)buff) + ts); + /* Make a content for next extent. */ + con = calloc(1, sizeof(*con)); + if (con == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate content data"); + return (ARCHIVE_FATAL); + } + con->offset_of_temp = wb_offset(a); + iso9660->cur_file->cur_content->next = con; + iso9660->cur_file->cur_content = con; +#ifdef HAVE_ZLIB_H + iso9660->zisofs.block_offset = 0; +#endif + } + + if (iso9660->zisofs.detect_magic) + zisofs_detect_magic(a, buff, ws); + + if (iso9660->zisofs.making) { + if (zisofs_write_to_temp(a, buff, ws) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } else { + if (wb_write_to_temp(a, buff, ws) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + iso9660->cur_file->cur_content->size += ws; + } + + return (s); +} + +static ssize_t +iso9660_write_data(struct archive_write *a, const void *buff, size_t s) +{ + struct iso9660 *iso9660 = a->format_data; + ssize_t r; + + if (iso9660->cur_file == NULL) + return (0); + if (archive_entry_filetype(iso9660->cur_file->entry) != AE_IFREG) + return (0); + if (s > iso9660->bytes_remaining) + s = (size_t)iso9660->bytes_remaining; + if (s == 0) + return (0); + + r = write_iso9660_data(a, buff, s); + if (r > 0) + iso9660->bytes_remaining -= r; + return (r); +} + +static int +iso9660_finish_entry(struct archive_write *a) +{ + struct iso9660 *iso9660 = a->format_data; + + if (iso9660->cur_file == NULL) + return (ARCHIVE_OK); + if (archive_entry_filetype(iso9660->cur_file->entry) != AE_IFREG) + return (ARCHIVE_OK); + if (iso9660->cur_file->content.size == 0) + return (ARCHIVE_OK); + + /* If there are unwritten data, write null data instead. */ + while (iso9660->bytes_remaining > 0) { + size_t s; + + s = (iso9660->bytes_remaining > a->null_length)? + a->null_length: (size_t)iso9660->bytes_remaining; + if (write_iso9660_data(a, a->nulls, s) < 0) + return (ARCHIVE_FATAL); + iso9660->bytes_remaining -= s; + } + + if (iso9660->zisofs.making && zisofs_finish_entry(a) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Write padding. */ + if (wb_write_padding_to_temp(a, iso9660->cur_file->cur_content->size) + != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Compute the logical block number. */ + iso9660->cur_file->cur_content->blocks = (int) + ((iso9660->cur_file->cur_content->size + + LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS); + + /* Add the current file to data file list. */ + isofile_add_data_file(iso9660, iso9660->cur_file); + + return (ARCHIVE_OK); +} + +static int +iso9660_close(struct archive_write *a) +{ + struct iso9660 *iso9660; + int ret, blocks; + + iso9660 = a->format_data; + + /* + * Write remaining data out to the temporary file. + */ + if (wb_remaining(a) > 0) { + ret = wb_write_out(a); + if (ret < 0) + return (ret); + } + + /* + * Preparations... + */ +#ifdef DEBUG + if (iso9660->birth_time == 0) +#endif + time(&(iso9660->birth_time)); + + /* + * Prepare a bootable ISO image. + */ + if (iso9660->opt.boot) { + /* Find out the boot file entry. */ + ret = isoent_find_out_boot_file(a, iso9660->primary.rootent); + if (ret < 0) + return (ret); + /* Reconvert the boot file from zisofs'ed form to + * plain form. */ + ret = zisofs_rewind_boot_file(a); + if (ret < 0) + return (ret); + /* Write remaining data out to the temporary file. */ + if (wb_remaining(a) > 0) { + ret = wb_write_out(a); + if (ret < 0) + return (ret); + } + /* Create the boot catalog. */ + ret = isoent_create_boot_catalog(a, iso9660->primary.rootent); + if (ret < 0) + return (ret); + } + + /* + * Prepare joliet extensions. + */ + if (iso9660->opt.joliet) { + /* Make a new tree for joliet. */ + ret = isoent_clone_tree(a, &(iso9660->joliet.rootent), + iso9660->primary.rootent); + if (ret < 0) + return (ret); + /* Make sure we have UTF-16BE converters. + * if there is no file entry, converters are still + * uninitialized. */ + if (iso9660->sconv_to_utf16be == NULL) { + iso9660->sconv_to_utf16be = + archive_string_conversion_to_charset( + &(a->archive), "UTF-16BE", 1); + if (iso9660->sconv_to_utf16be == NULL) + /* Couldn't allocate memory */ + return (ARCHIVE_FATAL); + iso9660->sconv_from_utf16be = + archive_string_conversion_from_charset( + &(a->archive), "UTF-16BE", 1); + if (iso9660->sconv_from_utf16be == NULL) + /* Couldn't allocate memory */ + return (ARCHIVE_FATAL); + } + } + + /* + * Make Path Tables. + */ + ret = isoent_make_path_table(a); + if (ret < 0) + return (ret); + + /* + * Calculate a total volume size and setup all locations of + * contents of an iso9660 image. + */ + blocks = SYSTEM_AREA_BLOCK + + PRIMARY_VOLUME_DESCRIPTOR_BLOCK + + VOLUME_DESCRIPTOR_SET_TERMINATOR_BLOCK + + NON_ISO_FILE_SYSTEM_INFORMATION_BLOCK; + if (iso9660->opt.boot) + blocks += BOOT_RECORD_DESCRIPTOR_BLOCK; + if (iso9660->opt.joliet) + blocks += SUPPLEMENTARY_VOLUME_DESCRIPTOR_BLOCK; + if (iso9660->opt.iso_level == 4) + blocks += SUPPLEMENTARY_VOLUME_DESCRIPTOR_BLOCK; + + /* Setup the locations of Path Table. */ + iso9660->primary.location_type_L_path_table = blocks; + blocks += iso9660->primary.path_table_block; + iso9660->primary.location_type_M_path_table = blocks; + blocks += iso9660->primary.path_table_block; + if (iso9660->opt.joliet) { + iso9660->joliet.location_type_L_path_table = blocks; + blocks += iso9660->joliet.path_table_block; + iso9660->joliet.location_type_M_path_table = blocks; + blocks += iso9660->joliet.path_table_block; + } + + /* Setup the locations of directories. */ + isoent_setup_directory_location(iso9660, blocks, + &(iso9660->primary)); + blocks += iso9660->primary.total_dir_block; + if (iso9660->opt.joliet) { + isoent_setup_directory_location(iso9660, blocks, + &(iso9660->joliet)); + blocks += iso9660->joliet.total_dir_block; + } + + if (iso9660->opt.rr) { + iso9660->location_rrip_er = blocks; + blocks += RRIP_ER_BLOCK; + } + + /* Setup the locations of all file contents. */ + isoent_setup_file_location(iso9660, blocks); + blocks += iso9660->total_file_block; + if (iso9660->opt.boot && iso9660->opt.boot_info_table) { + ret = setup_boot_information(a); + if (ret < 0) + return (ret); + } + + /* Now we have a total volume size. */ + iso9660->volume_space_size = blocks; + if (iso9660->opt.pad) + iso9660->volume_space_size += PADDING_BLOCK; + iso9660->volume_sequence_number = 1; + + + /* + * Write an ISO 9660 image. + */ + + /* Switch to start using wbuff as file buffer. */ + iso9660->wbuff_remaining = wb_buffmax(); + iso9660->wbuff_type = WB_TO_STREAM; + iso9660->wbuff_offset = 0; + iso9660->wbuff_written = 0; + iso9660->wbuff_tail = 0; + + /* Write The System Area */ + ret = write_null(a, SYSTEM_AREA_BLOCK * LOGICAL_BLOCK_SIZE); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Write Primary Volume Descriptor */ + ret = write_VD(a, &(iso9660->primary)); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + if (iso9660->opt.boot) { + /* Write Boot Record Volume Descriptor */ + ret = write_VD_boot_record(a); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + + if (iso9660->opt.iso_level == 4) { + /* Write Enhanced Volume Descriptor */ + iso9660->primary.vdd_type = VDD_ENHANCED; + ret = write_VD(a, &(iso9660->primary)); + iso9660->primary.vdd_type = VDD_PRIMARY; + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + + if (iso9660->opt.joliet) { + ret = write_VD(a, &(iso9660->joliet)); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + + /* Write Volume Descriptor Set Terminator */ + ret = write_VD_terminator(a); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Write Non-ISO File System Information */ + ret = write_information_block(a); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Write Type L Path Table */ + ret = write_path_table(a, 0, &(iso9660->primary)); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Write Type M Path Table */ + ret = write_path_table(a, 1, &(iso9660->primary)); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + if (iso9660->opt.joliet) { + /* Write Type L Path Table */ + ret = write_path_table(a, 0, &(iso9660->joliet)); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Write Type M Path Table */ + ret = write_path_table(a, 1, &(iso9660->joliet)); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + + /* Write Directory Descriptors */ + ret = write_directory_descriptors(a, &(iso9660->primary)); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + if (iso9660->opt.joliet) { + ret = write_directory_descriptors(a, &(iso9660->joliet)); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + + if (iso9660->opt.rr) { + /* Write Rockridge ER(Extensions Reference) */ + ret = write_rr_ER(a); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + + /* Write File Descriptors */ + ret = write_file_descriptors(a); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Write Padding */ + if (iso9660->opt.pad) { + ret = write_null(a, PADDING_BLOCK * LOGICAL_BLOCK_SIZE); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + + if (iso9660->directories_too_deep != NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "%s: Directories too deep.", + archive_entry_pathname( + iso9660->directories_too_deep->file->entry)); + return (ARCHIVE_WARN); + } + + /* Write remaining data out. */ + ret = wb_write_out(a); + + return (ret); +} + +static int +iso9660_free(struct archive_write *a) +{ + struct iso9660 *iso9660; + int i, ret; + + iso9660 = a->format_data; + + /* Close the temporary file. */ + if (iso9660->temp_fd >= 0) + close(iso9660->temp_fd); + + /* Free some stuff for zisofs operations. */ + ret = zisofs_free(a); + + /* Remove directory entries in tree which includes file entries. */ + isoent_free_all(iso9660->primary.rootent); + for (i = 0; i < iso9660->primary.max_depth; i++) + free(iso9660->primary.pathtbl[i].sorted); + free(iso9660->primary.pathtbl); + + if (iso9660->opt.joliet) { + isoent_free_all(iso9660->joliet.rootent); + for (i = 0; i < iso9660->joliet.max_depth; i++) + free(iso9660->joliet.pathtbl[i].sorted); + free(iso9660->joliet.pathtbl); + } + + /* Remove isofile entries. */ + isofile_free_all_entries(iso9660); + isofile_free_hardlinks(iso9660); + + archive_string_free(&(iso9660->cur_dirstr)); + archive_string_free(&(iso9660->volume_identifier)); + archive_string_free(&(iso9660->publisher_identifier)); + archive_string_free(&(iso9660->data_preparer_identifier)); + archive_string_free(&(iso9660->application_identifier)); + archive_string_free(&(iso9660->copyright_file_identifier)); + archive_string_free(&(iso9660->abstract_file_identifier)); + archive_string_free(&(iso9660->bibliographic_file_identifier)); + archive_string_free(&(iso9660->el_torito.catalog_filename)); + archive_string_free(&(iso9660->el_torito.boot_filename)); + archive_string_free(&(iso9660->el_torito.id)); + archive_string_free(&(iso9660->utf16be)); + archive_string_free(&(iso9660->mbs)); + + free(iso9660); + a->format_data = NULL; + + return (ret); +} + +/* + * Get the System Identifier + */ +static void +get_system_identitier(char *system_id, size_t size) +{ +#if defined(HAVE_SYS_UTSNAME_H) + struct utsname u; + + uname(&u); + strncpy(system_id, u.sysname, size-1); + system_id[size-1] = '\0'; +#elif defined(_WIN32) && !defined(__CYGWIN__) + strncpy(system_id, "Windows", size-1); + system_id[size-1] = '\0'; +#else +#error no way to get the system identifier on your platform. +#endif +} + +static void +set_str(unsigned char *p, const char *s, size_t l, char f, const char *map) +{ + unsigned char c; + + if (s == NULL) + s = ""; + while ((c = *s++) != 0 && l > 0) { + if (c >= 0x80 || map[c] == 0) + { + /* illegal character */ + if (c >= 'a' && c <= 'z') { + /* convert c from a-z to A-Z */ + c -= 0x20; + } else + c = 0x5f; + } + *p++ = c; + l--; + } + /* If l isn't zero, fill p buffer by the character + * which indicated by f. */ + if (l > 0) + memset(p , f, l); +} + +static inline int +joliet_allowed_char(unsigned char high, unsigned char low) +{ + int utf16 = (high << 8) | low; + + if (utf16 <= 0x001F) + return (0); + + switch (utf16) { + case 0x002A: /* '*' */ + case 0x002F: /* '/' */ + case 0x003A: /* ':' */ + case 0x003B: /* ';' */ + case 0x003F: /* '?' */ + case 0x005C: /* '\' */ + return (0);/* Not allowed. */ + } + return (1); +} + +static int +set_str_utf16be(struct archive_write *a, unsigned char *p, const char *s, + size_t l, uint16_t uf, enum vdc vdc) +{ + size_t size, i; + int onepad; + + if (s == NULL) + s = ""; + if (l & 0x01) { + onepad = 1; + l &= ~1; + } else + onepad = 0; + if (vdc == VDC_UCS2) { + struct iso9660 *iso9660 = a->format_data; + if (archive_strncpy_l(&iso9660->utf16be, s, strlen(s), + iso9660->sconv_to_utf16be) != 0 && errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for UTF-16BE"); + return (ARCHIVE_FATAL); + } + size = iso9660->utf16be.length; + if (size > l) + size = l; + memcpy(p, iso9660->utf16be.s, size); + } else { + const uint16_t *u16 = (const uint16_t *)s; + + size = 0; + while (*u16++) + size += 2; + if (size > l) + size = l; + memcpy(p, s, size); + } + for (i = 0; i < size; i += 2, p += 2) { + if (!joliet_allowed_char(p[0], p[1])) + archive_be16enc(p, 0x005F);/* '_' */ + } + l -= size; + while (l > 0) { + archive_be16enc(p, uf); + p += 2; + l -= 2; + } + if (onepad) + *p = 0; + return (ARCHIVE_OK); +} + +static const char a_characters_map[0x80] = { +/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */ + 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20-2F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 30-3F */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 60-6F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 70-7F */ +}; + +static const char a1_characters_map[0x80] = { +/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */ + 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20-2F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 30-3F */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 60-6F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,/* 70-7F */ +}; + +static const char d_characters_map[0x80] = { +/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 20-2F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,/* 30-3F */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 60-6F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 70-7F */ +}; + +static const char d1_characters_map[0x80] = { +/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 20-2F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,/* 30-3F */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 60-6F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,/* 70-7F */ +}; + +static int +set_str_a_characters_bp(struct archive_write *a, unsigned char *bp, + int from, int to, const char *s, enum vdc vdc) +{ + int r; + + switch (vdc) { + case VDC_STD: + set_str(bp+from, s, to - from + 1, 0x20, + a_characters_map); + r = ARCHIVE_OK; + break; + case VDC_LOWERCASE: + set_str(bp+from, s, to - from + 1, 0x20, + a1_characters_map); + r = ARCHIVE_OK; + break; + case VDC_UCS2: + case VDC_UCS2_DIRECT: + r = set_str_utf16be(a, bp+from, s, to - from + 1, + 0x0020, vdc); + break; + default: + r = ARCHIVE_FATAL; + } + return (r); +} + +static int +set_str_d_characters_bp(struct archive_write *a, unsigned char *bp, + int from, int to, const char *s, enum vdc vdc) +{ + int r; + + switch (vdc) { + case VDC_STD: + set_str(bp+from, s, to - from + 1, 0x20, + d_characters_map); + r = ARCHIVE_OK; + break; + case VDC_LOWERCASE: + set_str(bp+from, s, to - from + 1, 0x20, + d1_characters_map); + r = ARCHIVE_OK; + break; + case VDC_UCS2: + case VDC_UCS2_DIRECT: + r = set_str_utf16be(a, bp+from, s, to - from + 1, + 0x0020, vdc); + break; + default: + r = ARCHIVE_FATAL; + } + return (r); +} + +static void +set_VD_bp(unsigned char *bp, enum VD_type type, unsigned char ver) +{ + + /* Volume Descriptor Type */ + bp[1] = (unsigned char)type; + /* Standard Identifier */ + memcpy(bp + 2, "CD001", 5); + /* Volume Descriptor Version */ + bp[7] = ver; +} + +static inline void +set_unused_field_bp(unsigned char *bp, int from, int to) +{ + memset(bp + from, 0, to - from + 1); +} + +/* + * 8-bit unsigned numerical values. + * ISO9660 Standard 7.1.1 + */ +static inline void +set_num_711(unsigned char *p, unsigned char value) +{ + *p = value; +} + +/* + * 8-bit signed numerical values. + * ISO9660 Standard 7.1.2 + */ +static inline void +set_num_712(unsigned char *p, char value) +{ + *((char *)p) = value; +} + +/* + * Least significant byte first. + * ISO9660 Standard 7.2.1 + */ +static inline void +set_num_721(unsigned char *p, uint16_t value) +{ + archive_le16enc(p, value); +} + +/* + * Most significant byte first. + * ISO9660 Standard 7.2.2 + */ +static inline void +set_num_722(unsigned char *p, uint16_t value) +{ + archive_be16enc(p, value); +} + +/* + * Both-byte orders. + * ISO9660 Standard 7.2.3 + */ +static void +set_num_723(unsigned char *p, uint16_t value) +{ + archive_le16enc(p, value); + archive_be16enc(p+2, value); +} + +/* + * Least significant byte first. + * ISO9660 Standard 7.3.1 + */ +static inline void +set_num_731(unsigned char *p, uint32_t value) +{ + archive_le32enc(p, value); +} + +/* + * Most significant byte first. + * ISO9660 Standard 7.3.2 + */ +static inline void +set_num_732(unsigned char *p, uint32_t value) +{ + archive_be32enc(p, value); +} + +/* + * Both-byte orders. + * ISO9660 Standard 7.3.3 + */ +static inline void +set_num_733(unsigned char *p, uint32_t value) +{ + archive_le32enc(p, value); + archive_be32enc(p+4, value); +} + +static void +set_digit(unsigned char *p, size_t s, int value) +{ + + while (s--) { + p[s] = '0' + (value % 10); + value /= 10; + } +} + +#if defined(HAVE_STRUCT_TM_TM_GMTOFF) +#define get_gmoffset(tm) ((tm)->tm_gmtoff) +#elif defined(HAVE_STRUCT_TM___TM_GMTOFF) +#define get_gmoffset(tm) ((tm)->__tm_gmtoff) +#else +static long +get_gmoffset(struct tm *tm) +{ + long offset; + +#if defined(HAVE__GET_TIMEZONE) + _get_timezone(&offset); +#elif defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__) + offset = _timezone; +#else + offset = timezone; +#endif + offset *= -1; + if (tm->tm_isdst) + offset += 3600; + return (offset); +} +#endif + +static void +get_tmfromtime(struct tm *tm, time_t *t) +{ +#if HAVE_LOCALTIME_R + tzset(); + localtime_r(t, tm); +#elif HAVE__LOCALTIME64_S + __time64_t tmp_t = (__time64_t) *t; //time_t may be shorter than 64 bits + _localtime64_s(tm, &tmp_t); +#else + memcpy(tm, localtime(t), sizeof(*tm)); +#endif +} + +/* + * Date and Time Format. + * ISO9660 Standard 8.4.26.1 + */ +static void +set_date_time(unsigned char *p, time_t t) +{ + struct tm tm; + + get_tmfromtime(&tm, &t); + set_digit(p, 4, tm.tm_year + 1900); + set_digit(p+4, 2, tm.tm_mon + 1); + set_digit(p+6, 2, tm.tm_mday); + set_digit(p+8, 2, tm.tm_hour); + set_digit(p+10, 2, tm.tm_min); + set_digit(p+12, 2, tm.tm_sec); + set_digit(p+14, 2, 0); + set_num_712(p+16, (char)(get_gmoffset(&tm)/(60*15))); +} + +static void +set_date_time_null(unsigned char *p) +{ + memset(p, (int)'0', 16); + p[16] = 0; +} + +static void +set_time_915(unsigned char *p, time_t t) +{ + struct tm tm; + + get_tmfromtime(&tm, &t); + set_num_711(p+0, tm.tm_year); + set_num_711(p+1, tm.tm_mon+1); + set_num_711(p+2, tm.tm_mday); + set_num_711(p+3, tm.tm_hour); + set_num_711(p+4, tm.tm_min); + set_num_711(p+5, tm.tm_sec); + set_num_712(p+6, (char)(get_gmoffset(&tm)/(60*15))); +} + + +/* + * Write SUSP "CE" System Use Entry. + */ +static int +set_SUSP_CE(unsigned char *p, int location, int offset, int size) +{ + unsigned char *bp = p -1; + /* Extend the System Use Area + * "CE" Format: + * len ver + * +----+----+----+----+-----------+-----------+ + * | 'C'| 'E'| 1C | 01 | LOCATION1 | LOCATION2 | + * +----+----+----+----+-----------+-----------+ + * 0 1 2 3 4 12 20 + * +-----------+ + * | LOCATION3 | + * +-----------+ + * 20 28 + * LOCATION1 : Location of Continuation of System Use Area. + * LOCATION2 : Offset to Start of Continuation. + * LOCATION3 : Length of the Continuation. + */ + + bp[1] = 'C'; + bp[2] = 'E'; + bp[3] = RR_CE_SIZE; /* length */ + bp[4] = 1; /* version */ + set_num_733(bp+5, location); + set_num_733(bp+13, offset); + set_num_733(bp+21, size); + return (RR_CE_SIZE); +} + +/* + * The functions, which names are beginning with extra_, are used to + * control extra records. + * The maximum size of a Directory Record is 254. When a filename is + * very long, all of RRIP data of a file won't stored to the Directory + * Record and so remaining RRIP data store to an extra record instead. + */ +static unsigned char * +extra_open_record(unsigned char *bp, int dr_len, struct isoent *isoent, + struct ctl_extr_rec *ctl) +{ + ctl->bp = bp; + if (bp != NULL) + bp += dr_len; + ctl->use_extr = 0; + ctl->isoent = isoent; + ctl->ce_ptr = NULL; + ctl->cur_len = ctl->dr_len = dr_len; + ctl->limit = DR_LIMIT; + + return (bp); +} + +static void +extra_close_record(struct ctl_extr_rec *ctl, int ce_size) +{ + int padding = 0; + + if (ce_size > 0) + extra_tell_used_size(ctl, ce_size); + /* Padding. */ + if (ctl->cur_len & 0x01) { + ctl->cur_len++; + if (ctl->bp != NULL) + ctl->bp[ctl->cur_len] = 0; + padding = 1; + } + if (ctl->use_extr) { + if (ctl->ce_ptr != NULL) + set_SUSP_CE(ctl->ce_ptr, ctl->extr_loc, + ctl->extr_off, ctl->cur_len - padding); + } else + ctl->dr_len = ctl->cur_len; +} + +#define extra_space(ctl) ((ctl)->limit - (ctl)->cur_len) + +static unsigned char * +extra_next_record(struct ctl_extr_rec *ctl, int length) +{ + int cur_len = ctl->cur_len;/* save cur_len */ + + /* Close the current extra record or Directory Record. */ + extra_close_record(ctl, RR_CE_SIZE); + + /* Get a next extra record. */ + ctl->use_extr = 1; + if (ctl->bp != NULL) { + /* Storing data into an extra record. */ + unsigned char *p; + + /* Save the pointer where a CE extension will be + * stored to. */ + ctl->ce_ptr = &ctl->bp[cur_len+1]; + p = extra_get_record(ctl->isoent, + &ctl->limit, &ctl->extr_off, &ctl->extr_loc); + ctl->bp = p - 1;/* the base of bp offset is 1. */ + } else + /* Calculating the size of an extra record. */ + (void)extra_get_record(ctl->isoent, + &ctl->limit, NULL, NULL); + ctl->cur_len = 0; + /* Check if an extra record is almost full. + * If so, get a next one. */ + if (extra_space(ctl) < length) + (void)extra_next_record(ctl, length); + + return (ctl->bp); +} + +static inline struct extr_rec * +extra_last_record(struct isoent *isoent) +{ + if (isoent->extr_rec_list.first == NULL) + return (NULL); + return ((struct extr_rec *)(void *) + ((char *)(isoent->extr_rec_list.last) + - offsetof(struct extr_rec, next))); +} + +static unsigned char * +extra_get_record(struct isoent *isoent, int *space, int *off, int *loc) +{ + struct extr_rec *rec; + + isoent = isoent->parent; + if (off != NULL) { + /* Storing data into an extra record. */ + rec = isoent->extr_rec_list.current; + if (DR_SAFETY > LOGICAL_BLOCK_SIZE - rec->offset) + rec = rec->next; + } else { + /* Calculating the size of an extra record. */ + rec = extra_last_record(isoent); + if (rec == NULL || + DR_SAFETY > LOGICAL_BLOCK_SIZE - rec->offset) { + rec = malloc(sizeof(*rec)); + if (rec == NULL) + return (NULL); + rec->location = 0; + rec->offset = 0; + /* Insert `rec` into the tail of isoent->extr_rec_list */ + rec->next = NULL; + /* + * Note: testing isoent->extr_rec_list.last == NULL + * here is really unneeded since it has been already + * initialized at isoent_new function but Clang Static + * Analyzer claims that it is dereference of null + * pointer. + */ + if (isoent->extr_rec_list.last == NULL) + isoent->extr_rec_list.last = + &(isoent->extr_rec_list.first); + *isoent->extr_rec_list.last = rec; + isoent->extr_rec_list.last = &(rec->next); + } + } + *space = LOGICAL_BLOCK_SIZE - rec->offset - DR_SAFETY; + if (*space & 0x01) + *space -= 1;/* Keep padding space. */ + if (off != NULL) + *off = rec->offset; + if (loc != NULL) + *loc = rec->location; + isoent->extr_rec_list.current = rec; + + return (&rec->buf[rec->offset]); +} + +static void +extra_tell_used_size(struct ctl_extr_rec *ctl, int size) +{ + struct isoent *isoent; + struct extr_rec *rec; + + if (ctl->use_extr) { + isoent = ctl->isoent->parent; + rec = isoent->extr_rec_list.current; + if (rec != NULL) + rec->offset += size; + } + ctl->cur_len += size; +} + +static int +extra_setup_location(struct isoent *isoent, int location) +{ + struct extr_rec *rec; + int cnt; + + cnt = 0; + rec = isoent->extr_rec_list.first; + isoent->extr_rec_list.current = rec; + while (rec) { + cnt++; + rec->location = location++; + rec->offset = 0; + rec = rec->next; + } + return (cnt); +} + +/* + * Create the RRIP entries. + */ +static int +set_directory_record_rr(unsigned char *bp, int dr_len, + struct isoent *isoent, struct iso9660 *iso9660, enum dir_rec_type t) +{ + /* Flags(BP 5) of the Rockridge "RR" System Use Field */ + unsigned char rr_flag; +#define RR_USE_PX 0x01 +#define RR_USE_PN 0x02 +#define RR_USE_SL 0x04 +#define RR_USE_NM 0x08 +#define RR_USE_CL 0x10 +#define RR_USE_PL 0x20 +#define RR_USE_RE 0x40 +#define RR_USE_TF 0x80 + int length; + struct ctl_extr_rec ctl; + struct isoent *rr_parent, *pxent; + struct isofile *file; + + bp = extra_open_record(bp, dr_len, isoent, &ctl); + + if (t == DIR_REC_PARENT) { + rr_parent = isoent->rr_parent; + pxent = isoent->parent; + if (rr_parent != NULL) + isoent = rr_parent; + else + isoent = isoent->parent; + } else { + rr_parent = NULL; + pxent = isoent; + } + file = isoent->file; + + if (t != DIR_REC_NORMAL) { + rr_flag = RR_USE_PX | RR_USE_TF; + if (rr_parent != NULL) + rr_flag |= RR_USE_PL; + } else { + rr_flag = RR_USE_PX | RR_USE_NM | RR_USE_TF; + if (archive_entry_filetype(file->entry) == AE_IFLNK) + rr_flag |= RR_USE_SL; + if (isoent->rr_parent != NULL) + rr_flag |= RR_USE_RE; + if (isoent->rr_child != NULL) + rr_flag |= RR_USE_CL; + if (archive_entry_filetype(file->entry) == AE_IFCHR || + archive_entry_filetype(file->entry) == AE_IFBLK) + rr_flag |= RR_USE_PN; +#ifdef COMPAT_MKISOFS + /* + * mkisofs 2.01.01a63 records "RE" extension to + * the entry of "rr_moved" directory. + * I don't understand this behavior. + */ + if (isoent->virtual && + isoent->parent == iso9660->primary.rootent && + strcmp(isoent->file->basename.s, "rr_moved") == 0) + rr_flag |= RR_USE_RE; +#endif + } + + /* Write "SP" System Use Entry. */ + if (t == DIR_REC_SELF && isoent == isoent->parent) { + length = 7; + if (bp != NULL) { + bp[1] = 'S'; + bp[2] = 'P'; + bp[3] = length; + bp[4] = 1; /* version */ + bp[5] = 0xBE; /* Check Byte */ + bp[6] = 0xEF; /* Check Byte */ + bp[7] = 0; + bp += length; + } + extra_tell_used_size(&ctl, length); + } + + /* Write "RR" System Use Entry. */ + length = 5; + if (extra_space(&ctl) < length) + bp = extra_next_record(&ctl, length); + if (bp != NULL) { + bp[1] = 'R'; + bp[2] = 'R'; + bp[3] = length; + bp[4] = 1; /* version */ + bp[5] = rr_flag; + bp += length; + } + extra_tell_used_size(&ctl, length); + + /* Write "NM" System Use Entry. */ + if (rr_flag & RR_USE_NM) { + /* + * "NM" Format: + * e.g. a basename is 'foo' + * len ver flg + * +----+----+----+----+----+----+----+----+ + * | 'N'| 'M'| 08 | 01 | 00 | 'f'| 'o'| 'o'| + * +----+----+----+----+----+----+----+----+ + * <----------------- len -----------------> + */ + size_t nmlen = file->basename.length; + const char *nm = file->basename.s; + size_t nmmax; + + if (extra_space(&ctl) < 6) + bp = extra_next_record(&ctl, 6); + if (bp != NULL) { + bp[1] = 'N'; + bp[2] = 'M'; + bp[4] = 1; /* version */ + } + nmmax = extra_space(&ctl); + if (nmmax > 0xff) + nmmax = 0xff; + while (nmlen + 5 > nmmax) { + length = (int)nmmax; + if (bp != NULL) { + bp[3] = length; + bp[5] = 0x01;/* Alternate Name continues + * in next "NM" field */ + memcpy(bp+6, nm, length - 5); + bp += length; + } + nmlen -= length - 5; + nm += length - 5; + extra_tell_used_size(&ctl, length); + if (extra_space(&ctl) < 6) { + bp = extra_next_record(&ctl, 6); + nmmax = extra_space(&ctl); + if (nmmax > 0xff) + nmmax = 0xff; + } + if (bp != NULL) { + bp[1] = 'N'; + bp[2] = 'M'; + bp[4] = 1; /* version */ + } + } + length = 5 + (int)nmlen; + if (bp != NULL) { + bp[3] = length; + bp[5] = 0; + memcpy(bp+6, nm, nmlen); + bp += length; + } + extra_tell_used_size(&ctl, length); + } + + /* Write "PX" System Use Entry. */ + if (rr_flag & RR_USE_PX) { + /* + * "PX" Format: + * len ver + * +----+----+----+----+-----------+-----------+ + * | 'P'| 'X'| 2C | 01 | FILE MODE | LINKS | + * +----+----+----+----+-----------+-----------+ + * 0 1 2 3 4 12 20 + * +-----------+-----------+------------------+ + * | USER ID | GROUP ID |FILE SERIAL NUMBER| + * +-----------+-----------+------------------+ + * 20 28 36 44 + */ + length = 44; + if (extra_space(&ctl) < length) + bp = extra_next_record(&ctl, length); + if (bp != NULL) { + mode_t mode; + int64_t uid; + int64_t gid; + + mode = archive_entry_mode(file->entry); + uid = archive_entry_uid(file->entry); + gid = archive_entry_gid(file->entry); + if (iso9660->opt.rr == OPT_RR_USEFUL) { + /* + * This action is similar to mkisofs -r option + * but our rockridge=useful option does not + * set a zero to uid and gid. + */ + /* set all read bit ON */ + mode |= 0444; +#if !defined(_WIN32) && !defined(__CYGWIN__) + if (mode & 0111) +#endif + /* set all exec bit ON */ + mode |= 0111; + /* clear all write bits. */ + mode &= ~0222; + /* clear setuid,setgid,sticky bits. */ + mode &= ~07000; + } + + bp[1] = 'P'; + bp[2] = 'X'; + bp[3] = length; + bp[4] = 1; /* version */ + /* file mode */ + set_num_733(bp+5, mode); + /* file links (stat.st_nlink) */ + set_num_733(bp+13, + archive_entry_nlink(file->entry)); + set_num_733(bp+21, (uint32_t)uid); + set_num_733(bp+29, (uint32_t)gid); + /* File Serial Number */ + if (pxent->dir) + set_num_733(bp+37, pxent->dir_location); + else if (file->hardlink_target != NULL) + set_num_733(bp+37, + file->hardlink_target->cur_content->location); + else + set_num_733(bp+37, + file->cur_content->location); + bp += length; + } + extra_tell_used_size(&ctl, length); + } + + /* Write "SL" System Use Entry. */ + if (rr_flag & RR_USE_SL) { + /* + * "SL" Format: + * e.g. a symbolic name is 'foo/bar' + * len ver flg + * +----+----+----+----+----+------------+ + * | 'S'| 'L'| 0F | 01 | 00 | components | + * +----+----+----+----+----+-----+------+ + * 0 1 2 3 4 5 ...|... 15 + * <----------------- len --------+------> + * components : | + * cflg clen | + * +----+----+----+----+----+ | + * | 00 | 03 | 'f'| 'o'| 'o'| <---+ + * +----+----+----+----+----+ | + * 5 6 7 8 9 10 | + * cflg clen | + * +----+----+----+----+----+ | + * | 00 | 03 | 'b'| 'a'| 'r'| <---+ + * +----+----+----+----+----+ + * 10 11 12 13 14 15 + * + * - cflg : flag of component + * - clen : length of component + */ + const char *sl; + char sl_last; + + if (extra_space(&ctl) < 7) + bp = extra_next_record(&ctl, 7); + sl = file->symlink.s; + sl_last = '\0'; + if (bp != NULL) { + bp[1] = 'S'; + bp[2] = 'L'; + bp[4] = 1; /* version */ + } + for (;;) { + unsigned char *nc, *cf, *cl, cldmy = 0; + int sllen, slmax; + + slmax = extra_space(&ctl); + if (slmax > 0xff) + slmax = 0xff; + if (bp != NULL) + nc = &bp[6]; + else + nc = NULL; + cf = cl = NULL; + sllen = 0; + while (*sl && sllen + 11 < slmax) { + if (sl_last == '\0' && sl[0] == '/') { + /* + * flg len + * +----+----+ + * | 08 | 00 | ROOT component. + * +----+----+ ("/") + * + * Root component has to appear + * at the first component only. + */ + if (nc != NULL) { + cf = nc++; + *cf = 0x08; /* ROOT */ + *nc++ = 0; + } + sllen += 2; + sl++; + sl_last = '/'; + cl = NULL; + continue; + } + if (((sl_last == '\0' || sl_last == '/') && + sl[0] == '.' && sl[1] == '.' && + (sl[2] == '/' || sl[2] == '\0')) || + (sl[0] == '/' && + sl[1] == '.' && sl[2] == '.' && + (sl[3] == '/' || sl[3] == '\0'))) { + /* + * flg len + * +----+----+ + * | 04 | 00 | PARENT component. + * +----+----+ ("..") + */ + if (nc != NULL) { + cf = nc++; + *cf = 0x04; /* PARENT */ + *nc++ = 0; + } + sllen += 2; + if (sl[0] == '/') + sl += 3;/* skip "/.." */ + else + sl += 2;/* skip ".." */ + sl_last = '.'; + cl = NULL; + continue; + } + if (((sl_last == '\0' || sl_last == '/') && + sl[0] == '.' && + (sl[1] == '/' || sl[1] == '\0')) || + (sl[0] == '/' && sl[1] == '.' && + (sl[2] == '/' || sl[2] == '\0'))) { + /* + * flg len + * +----+----+ + * | 02 | 00 | CURRENT component. + * +----+----+ (".") + */ + if (nc != NULL) { + cf = nc++; + *cf = 0x02; /* CURRENT */ + *nc++ = 0; + } + sllen += 2; + if (sl[0] == '/') + sl += 2;/* skip "/." */ + else + sl ++; /* skip "." */ + sl_last = '.'; + cl = NULL; + continue; + } + if (sl[0] == '/' || cl == NULL) { + if (nc != NULL) { + cf = nc++; + *cf = 0; + cl = nc++; + *cl = 0; + } else + cl = &cldmy; + sllen += 2; + if (sl[0] == '/') { + sl_last = *sl++; + continue; + } + } + sl_last = *sl++; + if (nc != NULL) { + *nc++ = sl_last; + (*cl) ++; + } + sllen++; + } + if (*sl) { + length = 5 + sllen; + if (bp != NULL) { + /* + * Mark flg as CONTINUE component. + */ + *cf |= 0x01; + /* + * len ver flg + * +----+----+----+----+----+- + * | 'S'| 'L'| XX | 01 | 01 | + * +----+----+----+----+----+- + * ^ + * continues in next "SL" + */ + bp[3] = length; + bp[5] = 0x01;/* This Symbolic Link + * continues in next + * "SL" field */ + bp += length; + } + extra_tell_used_size(&ctl, length); + if (extra_space(&ctl) < 11) + bp = extra_next_record(&ctl, 11); + if (bp != NULL) { + /* Next 'SL' */ + bp[1] = 'S'; + bp[2] = 'L'; + bp[4] = 1; /* version */ + } + } else { + length = 5 + sllen; + if (bp != NULL) { + bp[3] = length; + bp[5] = 0; + bp += length; + } + extra_tell_used_size(&ctl, length); + break; + } + } + } + + /* Write "TF" System Use Entry. */ + if (rr_flag & RR_USE_TF) { + /* + * "TF" Format: + * len ver + * +----+----+----+----+-----+-------------+ + * | 'T'| 'F'| XX | 01 |FLAGS| TIME STAMPS | + * +----+----+----+----+-----+-------------+ + * 0 1 2 3 4 5 XX + * TIME STAMPS : ISO 9660 Standard 9.1.5. + * If TF_LONG_FORM FLAGS is set, + * use ISO9660 Standard 8.4.26.1. + */ +#define TF_CREATION 0x01 /* Creation time recorded */ +#define TF_MODIFY 0x02 /* Modification time recorded */ +#define TF_ACCESS 0x04 /* Last Access time recorded */ +#define TF_ATTRIBUTES 0x08 /* Last Attribute Change time recorded */ +#define TF_BACKUP 0x10 /* Last Backup time recorded */ +#define TF_EXPIRATION 0x20 /* Expiration time recorded */ +#define TF_EFFECTIVE 0x40 /* Effective time recorded */ +#define TF_LONG_FORM 0x80 /* ISO 9660 17-byte time format used */ + unsigned char tf_flags; + + length = 5; + tf_flags = 0; +#ifndef COMPAT_MKISOFS + if (archive_entry_birthtime_is_set(file->entry) && + archive_entry_birthtime(file->entry) <= + archive_entry_mtime(file->entry)) { + length += 7; + tf_flags |= TF_CREATION; + } +#endif + if (archive_entry_mtime_is_set(file->entry)) { + length += 7; + tf_flags |= TF_MODIFY; + } + if (archive_entry_atime_is_set(file->entry)) { + length += 7; + tf_flags |= TF_ACCESS; + } + if (archive_entry_ctime_is_set(file->entry)) { + length += 7; + tf_flags |= TF_ATTRIBUTES; + } + if (extra_space(&ctl) < length) + bp = extra_next_record(&ctl, length); + if (bp != NULL) { + bp[1] = 'T'; + bp[2] = 'F'; + bp[3] = length; + bp[4] = 1; /* version */ + bp[5] = tf_flags; + bp += 5; + /* Creation time */ + if (tf_flags & TF_CREATION) { + set_time_915(bp+1, + archive_entry_birthtime(file->entry)); + bp += 7; + } + /* Modification time */ + if (tf_flags & TF_MODIFY) { + set_time_915(bp+1, + archive_entry_mtime(file->entry)); + bp += 7; + } + /* Last Access time */ + if (tf_flags & TF_ACCESS) { + set_time_915(bp+1, + archive_entry_atime(file->entry)); + bp += 7; + } + /* Last Attribute Change time */ + if (tf_flags & TF_ATTRIBUTES) { + set_time_915(bp+1, + archive_entry_ctime(file->entry)); + bp += 7; + } + } + extra_tell_used_size(&ctl, length); + } + + /* Write "RE" System Use Entry. */ + if (rr_flag & RR_USE_RE) { + /* + * "RE" Format: + * len ver + * +----+----+----+----+ + * | 'R'| 'E'| 04 | 01 | + * +----+----+----+----+ + * 0 1 2 3 4 + */ + length = 4; + if (extra_space(&ctl) < length) + bp = extra_next_record(&ctl, length); + if (bp != NULL) { + bp[1] = 'R'; + bp[2] = 'E'; + bp[3] = length; + bp[4] = 1; /* version */ + bp += length; + } + extra_tell_used_size(&ctl, length); + } + + /* Write "PL" System Use Entry. */ + if (rr_flag & RR_USE_PL) { + /* + * "PL" Format: + * len ver + * +----+----+----+----+------------+ + * | 'P'| 'L'| 0C | 01 | *LOCATION | + * +----+----+----+----+------------+ + * 0 1 2 3 4 12 + * *LOCATION: location of parent directory + */ + length = 12; + if (extra_space(&ctl) < length) + bp = extra_next_record(&ctl, length); + if (bp != NULL) { + bp[1] = 'P'; + bp[2] = 'L'; + bp[3] = length; + bp[4] = 1; /* version */ + set_num_733(bp + 5, + rr_parent->dir_location); + bp += length; + } + extra_tell_used_size(&ctl, length); + } + + /* Write "CL" System Use Entry. */ + if (rr_flag & RR_USE_CL) { + /* + * "CL" Format: + * len ver + * +----+----+----+----+------------+ + * | 'C'| 'L'| 0C | 01 | *LOCATION | + * +----+----+----+----+------------+ + * 0 1 2 3 4 12 + * *LOCATION: location of child directory + */ + length = 12; + if (extra_space(&ctl) < length) + bp = extra_next_record(&ctl, length); + if (bp != NULL) { + bp[1] = 'C'; + bp[2] = 'L'; + bp[3] = length; + bp[4] = 1; /* version */ + set_num_733(bp + 5, + isoent->rr_child->dir_location); + bp += length; + } + extra_tell_used_size(&ctl, length); + } + + /* Write "PN" System Use Entry. */ + if (rr_flag & RR_USE_PN) { + /* + * "PN" Format: + * len ver + * +----+----+----+----+------------+------------+ + * | 'P'| 'N'| 14 | 01 | dev_t high | dev_t low | + * +----+----+----+----+------------+------------+ + * 0 1 2 3 4 12 20 + */ + length = 20; + if (extra_space(&ctl) < length) + bp = extra_next_record(&ctl, length); + if (bp != NULL) { + uint64_t dev; + + bp[1] = 'P'; + bp[2] = 'N'; + bp[3] = length; + bp[4] = 1; /* version */ + dev = (uint64_t)archive_entry_rdev(file->entry); + set_num_733(bp + 5, (uint32_t)(dev >> 32)); + set_num_733(bp + 13, (uint32_t)(dev & 0xFFFFFFFF)); + bp += length; + } + extra_tell_used_size(&ctl, length); + } + + /* Write "ZF" System Use Entry. */ + if (file->zisofs.header_size) { + /* + * "ZF" Format: + * len ver + * +----+----+----+----+----+----+-------------+ + * | 'Z'| 'F'| 10 | 01 | 'p'| 'z'| Header Size | + * +----+----+----+----+----+----+-------------+ + * 0 1 2 3 4 5 6 7 + * +--------------------+-------------------+ + * | Log2 of block Size | Uncompressed Size | + * +--------------------+-------------------+ + * 7 8 16 + */ + length = 16; + if (extra_space(&ctl) < length) + bp = extra_next_record(&ctl, length); + if (bp != NULL) { + bp[1] = 'Z'; + bp[2] = 'F'; + bp[3] = length; + bp[4] = 1; /* version */ + bp[5] = 'p'; + bp[6] = 'z'; + bp[7] = file->zisofs.header_size; + bp[8] = file->zisofs.log2_bs; + set_num_733(bp + 9, file->zisofs.uncompressed_size); + bp += length; + } + extra_tell_used_size(&ctl, length); + } + + /* Write "CE" System Use Entry. */ + if (t == DIR_REC_SELF && isoent == isoent->parent) { + length = RR_CE_SIZE; + if (bp != NULL) + set_SUSP_CE(bp+1, iso9660->location_rrip_er, + 0, RRIP_ER_SIZE); + extra_tell_used_size(&ctl, length); + } + + extra_close_record(&ctl, 0); + + return (ctl.dr_len); +} + +/* + * Write data of a Directory Record or calculate writing bytes itself. + * If parameter `p' is NULL, calculates the size of writing data, which + * a Directory Record needs to write, then it saved and return + * the calculated size. + * Parameter `n' is a remaining size of buffer. when parameter `p' is + * not NULL, check whether that `n' is not less than the saved size. + * if that `n' is small, return zero. + * + * This format of the Directory Record is according to + * ISO9660 Standard 9.1 + */ +static int +set_directory_record(unsigned char *p, size_t n, struct isoent *isoent, + struct iso9660 *iso9660, enum dir_rec_type t, + enum vdd_type vdd_type) +{ + unsigned char *bp; + size_t dr_len; + size_t fi_len; + + if (p != NULL) { + /* + * Check whether a write buffer size is less than the + * saved size which is needed to write this Directory + * Record. + */ + switch (t) { + case DIR_REC_VD: + dr_len = isoent->dr_len.vd; break; + case DIR_REC_SELF: + dr_len = isoent->dr_len.self; break; + case DIR_REC_PARENT: + dr_len = isoent->dr_len.parent; break; + case DIR_REC_NORMAL: + default: + dr_len = isoent->dr_len.normal; break; + } + if (dr_len > n) + return (0);/* Needs more buffer size. */ + } + + if (t == DIR_REC_NORMAL && isoent->identifier != NULL) + fi_len = isoent->id_len; + else + fi_len = 1; + + if (p != NULL) { + struct isoent *xisoent; + struct isofile *file; + unsigned char flag; + + if (t == DIR_REC_PARENT) + xisoent = isoent->parent; + else + xisoent = isoent; + file = isoent->file; + if (file->hardlink_target != NULL) + file = file->hardlink_target; + /* Make a file flag. */ + if (xisoent->dir) + flag = FILE_FLAG_DIRECTORY; + else { + if (file->cur_content->next != NULL) + flag = FILE_FLAG_MULTI_EXTENT; + else + flag = 0; + } + + bp = p -1; + /* Extended Attribute Record Length */ + set_num_711(bp+2, 0); + /* Location of Extent */ + if (xisoent->dir) + set_num_733(bp+3, xisoent->dir_location); + else + set_num_733(bp+3, file->cur_content->location); + /* Data Length */ + if (xisoent->dir) + set_num_733(bp+11, + xisoent->dir_block * LOGICAL_BLOCK_SIZE); + else + set_num_733(bp+11, (uint32_t)file->cur_content->size); + /* Recording Date and Time */ + /* NOTE: + * If a file type is symbolic link, you are seeing this + * field value is different from a value mkisofs makes. + * libarchive uses lstat to get this one, but it + * seems mkisofs uses stat to get. + */ + set_time_915(bp+19, + archive_entry_mtime(xisoent->file->entry)); + /* File Flags */ + bp[26] = flag; + /* File Unit Size */ + set_num_711(bp+27, 0); + /* Interleave Gap Size */ + set_num_711(bp+28, 0); + /* Volume Sequence Number */ + set_num_723(bp+29, iso9660->volume_sequence_number); + /* Length of File Identifier */ + set_num_711(bp+33, (unsigned char)fi_len); + /* File Identifier */ + switch (t) { + case DIR_REC_VD: + case DIR_REC_SELF: + set_num_711(bp+34, 0); + break; + case DIR_REC_PARENT: + set_num_711(bp+34, 1); + break; + case DIR_REC_NORMAL: + if (isoent->identifier != NULL) + memcpy(bp+34, isoent->identifier, fi_len); + else + set_num_711(bp+34, 0); + break; + } + } else + bp = NULL; + dr_len = 33 + fi_len; + /* Padding Field */ + if (dr_len & 0x01) { + dr_len ++; + if (p != NULL) + bp[dr_len] = 0; + } + + /* Volume Descriptor does not record extension. */ + if (t == DIR_REC_VD) { + if (p != NULL) + /* Length of Directory Record */ + set_num_711(p, (unsigned char)dr_len); + else + isoent->dr_len.vd = (int)dr_len; + return ((int)dr_len); + } + + /* Rockridge */ + if (iso9660->opt.rr && vdd_type != VDD_JOLIET) + dr_len = set_directory_record_rr(bp, (int)dr_len, + isoent, iso9660, t); + + if (p != NULL) + /* Length of Directory Record */ + set_num_711(p, (unsigned char)dr_len); + else { + /* + * Save the size which is needed to write this + * Directory Record. + */ + switch (t) { + case DIR_REC_VD: + /* This case does not come, but compiler + * complains that DIR_REC_VD not handled + * in switch .... */ + break; + case DIR_REC_SELF: + isoent->dr_len.self = (int)dr_len; break; + case DIR_REC_PARENT: + isoent->dr_len.parent = (int)dr_len; break; + case DIR_REC_NORMAL: + isoent->dr_len.normal = (int)dr_len; break; + } + } + + return ((int)dr_len); +} + +/* + * Calculate the size of a directory record. + */ +static inline int +get_dir_rec_size(struct iso9660 *iso9660, struct isoent *isoent, + enum dir_rec_type t, enum vdd_type vdd_type) +{ + + return (set_directory_record(NULL, SIZE_MAX, + isoent, iso9660, t, vdd_type)); +} + +/* + * Manage to write ISO-image data with wbuff to reduce calling + * __archive_write_output() for performance. + */ + + +static inline unsigned char * +wb_buffptr(struct archive_write *a) +{ + struct iso9660 *iso9660 = (struct iso9660 *)a->format_data; + + return (&(iso9660->wbuff[sizeof(iso9660->wbuff) + - iso9660->wbuff_remaining])); +} + +static int +wb_write_out(struct archive_write *a) +{ + struct iso9660 *iso9660 = (struct iso9660 *)a->format_data; + size_t wsize, nw; + int r; + + wsize = sizeof(iso9660->wbuff) - iso9660->wbuff_remaining; + nw = wsize % LOGICAL_BLOCK_SIZE; + if (iso9660->wbuff_type == WB_TO_STREAM) + r = __archive_write_output(a, iso9660->wbuff, wsize - nw); + else + r = write_to_temp(a, iso9660->wbuff, wsize - nw); + /* Increase the offset. */ + iso9660->wbuff_offset += wsize - nw; + if (iso9660->wbuff_offset > iso9660->wbuff_written) + iso9660->wbuff_written = iso9660->wbuff_offset; + iso9660->wbuff_remaining = sizeof(iso9660->wbuff); + if (nw) { + iso9660->wbuff_remaining -= nw; + memmove(iso9660->wbuff, iso9660->wbuff + wsize - nw, nw); + } + return (r); +} + +static int +wb_consume(struct archive_write *a, size_t size) +{ + struct iso9660 *iso9660 = (struct iso9660 *)a->format_data; + + if (size > iso9660->wbuff_remaining || + iso9660->wbuff_remaining == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Internal Programming error: iso9660:wb_consume()" + " size=%jd, wbuff_remaining=%jd", + (intmax_t)size, (intmax_t)iso9660->wbuff_remaining); + return (ARCHIVE_FATAL); + } + iso9660->wbuff_remaining -= size; + if (iso9660->wbuff_remaining < LOGICAL_BLOCK_SIZE) + return (wb_write_out(a)); + return (ARCHIVE_OK); +} + +#ifdef HAVE_ZLIB_H + +static int +wb_set_offset(struct archive_write *a, int64_t off) +{ + struct iso9660 *iso9660 = (struct iso9660 *)a->format_data; + int64_t used, ext_bytes; + + if (iso9660->wbuff_type != WB_TO_TEMP) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Internal Programming error: iso9660:wb_set_offset()"); + return (ARCHIVE_FATAL); + } + + used = sizeof(iso9660->wbuff) - iso9660->wbuff_remaining; + if (iso9660->wbuff_offset + used > iso9660->wbuff_tail) + iso9660->wbuff_tail = iso9660->wbuff_offset + used; + if (iso9660->wbuff_offset < iso9660->wbuff_written) { + if (used > 0 && + write_to_temp(a, iso9660->wbuff, (size_t)used) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + iso9660->wbuff_offset = iso9660->wbuff_written; + lseek(iso9660->temp_fd, iso9660->wbuff_offset, SEEK_SET); + iso9660->wbuff_remaining = sizeof(iso9660->wbuff); + used = 0; + } + if (off < iso9660->wbuff_offset) { + /* + * Write out waiting data. + */ + if (used > 0) { + if (wb_write_out(a) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + lseek(iso9660->temp_fd, off, SEEK_SET); + iso9660->wbuff_offset = off; + iso9660->wbuff_remaining = sizeof(iso9660->wbuff); + } else if (off <= iso9660->wbuff_tail) { + iso9660->wbuff_remaining = (size_t) + (sizeof(iso9660->wbuff) - (off - iso9660->wbuff_offset)); + } else { + ext_bytes = off - iso9660->wbuff_tail; + iso9660->wbuff_remaining = (size_t)(sizeof(iso9660->wbuff) + - (iso9660->wbuff_tail - iso9660->wbuff_offset)); + while (ext_bytes >= (int64_t)iso9660->wbuff_remaining) { + if (write_null(a, (size_t)iso9660->wbuff_remaining) + != ARCHIVE_OK) + return (ARCHIVE_FATAL); + ext_bytes -= iso9660->wbuff_remaining; + } + if (ext_bytes > 0) { + if (write_null(a, (size_t)ext_bytes) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + } + return (ARCHIVE_OK); +} + +#endif /* HAVE_ZLIB_H */ + +static int +write_null(struct archive_write *a, size_t size) +{ + size_t remaining; + unsigned char *p, *old; + int r; + + remaining = wb_remaining(a); + p = wb_buffptr(a); + if (size <= remaining) { + memset(p, 0, size); + return (wb_consume(a, size)); + } + memset(p, 0, remaining); + r = wb_consume(a, remaining); + if (r != ARCHIVE_OK) + return (r); + size -= remaining; + old = p; + p = wb_buffptr(a); + memset(p, 0, old - p); + remaining = wb_remaining(a); + while (size) { + size_t wsize = size; + + if (wsize > remaining) + wsize = remaining; + r = wb_consume(a, wsize); + if (r != ARCHIVE_OK) + return (r); + size -= wsize; + } + return (ARCHIVE_OK); +} + +/* + * Write Volume Descriptor Set Terminator + */ +static int +write_VD_terminator(struct archive_write *a) +{ + unsigned char *bp; + + bp = wb_buffptr(a) -1; + set_VD_bp(bp, VDT_TERMINATOR, 1); + set_unused_field_bp(bp, 8, LOGICAL_BLOCK_SIZE); + + return (wb_consume(a, LOGICAL_BLOCK_SIZE)); +} + +static int +set_file_identifier(unsigned char *bp, int from, int to, enum vdc vdc, + struct archive_write *a, struct vdd *vdd, struct archive_string *id, + const char *label, int leading_under, enum char_type char_type) +{ + char identifier[256]; + struct isoent *isoent; + const char *ids; + size_t len; + int r; + + if (id->length > 0 && leading_under && id->s[0] != '_') { + if (char_type == A_CHAR) + r = set_str_a_characters_bp(a, bp, from, to, id->s, vdc); + else + r = set_str_d_characters_bp(a, bp, from, to, id->s, vdc); + } else if (id->length > 0) { + ids = id->s; + if (leading_under) + ids++; + isoent = isoent_find_entry(vdd->rootent, ids); + if (isoent == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Not Found %s `%s'.", + label, ids); + return (ARCHIVE_FATAL); + } + len = isoent->ext_off + isoent->ext_len; + if (vdd->vdd_type == VDD_JOLIET) { + if (len > sizeof(identifier)-2) + len = sizeof(identifier)-2; + } else { + if (len > sizeof(identifier)-1) + len = sizeof(identifier)-1; + } + memcpy(identifier, isoent->identifier, len); + identifier[len] = '\0'; + if (vdd->vdd_type == VDD_JOLIET) { + identifier[len+1] = 0; + vdc = VDC_UCS2_DIRECT; + } + if (char_type == A_CHAR) + r = set_str_a_characters_bp(a, bp, from, to, + identifier, vdc); + else + r = set_str_d_characters_bp(a, bp, from, to, + identifier, vdc); + } else { + if (char_type == A_CHAR) + r = set_str_a_characters_bp(a, bp, from, to, NULL, vdc); + else + r = set_str_d_characters_bp(a, bp, from, to, NULL, vdc); + } + return (r); +} + +/* + * Write Primary/Supplementary Volume Descriptor + */ +static int +write_VD(struct archive_write *a, struct vdd *vdd) +{ + struct iso9660 *iso9660; + unsigned char *bp; + uint16_t volume_set_size = 1; + char identifier[256]; + enum VD_type vdt; + enum vdc vdc; + unsigned char vd_ver, fst_ver; + int r; + + iso9660 = a->format_data; + switch (vdd->vdd_type) { + case VDD_JOLIET: + vdt = VDT_SUPPLEMENTARY; + vd_ver = fst_ver = 1; + vdc = VDC_UCS2; + break; + case VDD_ENHANCED: + vdt = VDT_SUPPLEMENTARY; + vd_ver = fst_ver = 2; + vdc = VDC_LOWERCASE; + break; + case VDD_PRIMARY: + default: + vdt = VDT_PRIMARY; + vd_ver = fst_ver = 1; +#ifdef COMPAT_MKISOFS + vdc = VDC_LOWERCASE; +#else + vdc = VDC_STD; +#endif + break; + } + + bp = wb_buffptr(a) -1; + /* Volume Descriptor Type */ + set_VD_bp(bp, vdt, vd_ver); + /* Unused Field */ + set_unused_field_bp(bp, 8, 8); + /* System Identifier */ + get_system_identitier(identifier, sizeof(identifier)); + r = set_str_a_characters_bp(a, bp, 9, 40, identifier, vdc); + if (r != ARCHIVE_OK) + return (r); + /* Volume Identifier */ + r = set_str_d_characters_bp(a, bp, 41, 72, + iso9660->volume_identifier.s, vdc); + if (r != ARCHIVE_OK) + return (r); + /* Unused Field */ + set_unused_field_bp(bp, 73, 80); + /* Volume Space Size */ + set_num_733(bp+81, iso9660->volume_space_size); + if (vdd->vdd_type == VDD_JOLIET) { + /* Escape Sequences */ + bp[89] = 0x25;/* UCS-2 Level 3 */ + bp[90] = 0x2F; + bp[91] = 0x45; + memset(bp + 92, 0, 120 - 92 + 1); + } else { + /* Unused Field */ + set_unused_field_bp(bp, 89, 120); + } + /* Volume Set Size */ + set_num_723(bp+121, volume_set_size); + /* Volume Sequence Number */ + set_num_723(bp+125, iso9660->volume_sequence_number); + /* Logical Block Size */ + set_num_723(bp+129, LOGICAL_BLOCK_SIZE); + /* Path Table Size */ + set_num_733(bp+133, vdd->path_table_size); + /* Location of Occurrence of Type L Path Table */ + set_num_731(bp+141, vdd->location_type_L_path_table); + /* Location of Optional Occurrence of Type L Path Table */ + set_num_731(bp+145, 0); + /* Location of Occurrence of Type M Path Table */ + set_num_732(bp+149, vdd->location_type_M_path_table); + /* Location of Optional Occurrence of Type M Path Table */ + set_num_732(bp+153, 0); + /* Directory Record for Root Directory(BP 157 to 190) */ + set_directory_record(bp+157, 190-157+1, vdd->rootent, + iso9660, DIR_REC_VD, vdd->vdd_type); + /* Volume Set Identifier */ + r = set_str_d_characters_bp(a, bp, 191, 318, "", vdc); + if (r != ARCHIVE_OK) + return (r); + /* Publisher Identifier */ + r = set_file_identifier(bp, 319, 446, vdc, a, vdd, + &(iso9660->publisher_identifier), + "Publisher File", 1, A_CHAR); + if (r != ARCHIVE_OK) + return (r); + /* Data Preparer Identifier */ + r = set_file_identifier(bp, 447, 574, vdc, a, vdd, + &(iso9660->data_preparer_identifier), + "Data Preparer File", 1, A_CHAR); + if (r != ARCHIVE_OK) + return (r); + /* Application Identifier */ + r = set_file_identifier(bp, 575, 702, vdc, a, vdd, + &(iso9660->application_identifier), + "Application File", 1, A_CHAR); + if (r != ARCHIVE_OK) + return (r); + /* Copyright File Identifier */ + r = set_file_identifier(bp, 703, 739, vdc, a, vdd, + &(iso9660->copyright_file_identifier), + "Copyright File", 0, D_CHAR); + if (r != ARCHIVE_OK) + return (r); + /* Abstract File Identifier */ + r = set_file_identifier(bp, 740, 776, vdc, a, vdd, + &(iso9660->abstract_file_identifier), + "Abstract File", 0, D_CHAR); + if (r != ARCHIVE_OK) + return (r); + /* Bibliographic File Identifier */ + r = set_file_identifier(bp, 777, 813, vdc, a, vdd, + &(iso9660->bibliographic_file_identifier), + "Bibliongraphic File", 0, D_CHAR); + if (r != ARCHIVE_OK) + return (r); + /* Volume Creation Date and Time */ + set_date_time(bp+814, iso9660->birth_time); + /* Volume Modification Date and Time */ + set_date_time(bp+831, iso9660->birth_time); + /* Volume Expiration Date and Time(obsolete) */ + set_date_time_null(bp+848); + /* Volume Effective Date and Time */ + set_date_time(bp+865, iso9660->birth_time); + /* File Structure Version */ + bp[882] = fst_ver; + /* Reserved */ + bp[883] = 0; + /* Application Use */ + memset(bp + 884, 0x20, 1395 - 884 + 1); + /* Reserved */ + set_unused_field_bp(bp, 1396, LOGICAL_BLOCK_SIZE); + + return (wb_consume(a, LOGICAL_BLOCK_SIZE)); +} + +/* + * Write Boot Record Volume Descriptor + */ +static int +write_VD_boot_record(struct archive_write *a) +{ + struct iso9660 *iso9660; + unsigned char *bp; + + iso9660 = a->format_data; + bp = wb_buffptr(a) -1; + /* Volume Descriptor Type */ + set_VD_bp(bp, VDT_BOOT_RECORD, 1); + /* Boot System Identifier */ + memcpy(bp+8, "EL TORITO SPECIFICATION", 23); + set_unused_field_bp(bp, 8+23, 39); + /* Unused */ + set_unused_field_bp(bp, 40, 71); + /* Absolute pointer to first sector of Boot Catalog */ + set_num_731(bp+72, + iso9660->el_torito.catalog->file->content.location); + /* Unused */ + set_unused_field_bp(bp, 76, LOGICAL_BLOCK_SIZE); + + return (wb_consume(a, LOGICAL_BLOCK_SIZE)); +} + +enum keytype { + KEY_FLG, + KEY_STR, + KEY_INT, + KEY_HEX +}; +static void +set_option_info(struct archive_string *info, int *opt, const char *key, + enum keytype type, ...) +{ + va_list ap; + char prefix; + const char *s; + int d; + + prefix = (*opt==0)? ' ':','; + va_start(ap, type); + switch (type) { + case KEY_FLG: + d = va_arg(ap, int); + archive_string_sprintf(info, "%c%s%s", + prefix, (d == 0)?"!":"", key); + break; + case KEY_STR: + s = va_arg(ap, const char *); + archive_string_sprintf(info, "%c%s=%s", + prefix, key, s); + break; + case KEY_INT: + d = va_arg(ap, int); + archive_string_sprintf(info, "%c%s=%d", + prefix, key, d); + break; + case KEY_HEX: + d = va_arg(ap, int); + archive_string_sprintf(info, "%c%s=%x", + prefix, key, d); + break; + } + va_end(ap); + + *opt = 1; +} + +/* + * Make Non-ISO File System Information + */ +static int +write_information_block(struct archive_write *a) +{ + struct iso9660 *iso9660; + char buf[128]; + const char *v; + int opt, r; + struct archive_string info; + size_t info_size = LOGICAL_BLOCK_SIZE * + NON_ISO_FILE_SYSTEM_INFORMATION_BLOCK; + + iso9660 = (struct iso9660 *)a->format_data; + if (info_size > wb_remaining(a)) { + r = wb_write_out(a); + if (r != ARCHIVE_OK) + return (r); + } + archive_string_init(&info); + if (archive_string_ensure(&info, info_size) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + memset(info.s, 0, info_size); + opt = 0; +#if defined(HAVE__CTIME64_S) + { + __time64_t iso9660_birth_time_tmp = (__time64_t) iso9660->birth_time; //time_t may be shorter than 64 bits + _ctime64_s(buf, sizeof(buf), &(iso9660_birth_time_tmp)); + } +#elif defined(HAVE_CTIME_R) + ctime_r(&(iso9660->birth_time), buf); +#else + strncpy(buf, ctime(&(iso9660->birth_time)), sizeof(buf)-1); + buf[sizeof(buf)-1] = '\0'; +#endif + archive_string_sprintf(&info, + "INFO %s%s", buf, archive_version_string()); + if (iso9660->opt.abstract_file != OPT_ABSTRACT_FILE_DEFAULT) + set_option_info(&info, &opt, "abstract-file", + KEY_STR, iso9660->abstract_file_identifier.s); + if (iso9660->opt.application_id != OPT_APPLICATION_ID_DEFAULT) + set_option_info(&info, &opt, "application-id", + KEY_STR, iso9660->application_identifier.s); + if (iso9660->opt.allow_vernum != OPT_ALLOW_VERNUM_DEFAULT) + set_option_info(&info, &opt, "allow-vernum", + KEY_FLG, iso9660->opt.allow_vernum); + if (iso9660->opt.biblio_file != OPT_BIBLIO_FILE_DEFAULT) + set_option_info(&info, &opt, "biblio-file", + KEY_STR, iso9660->bibliographic_file_identifier.s); + if (iso9660->opt.boot != OPT_BOOT_DEFAULT) + set_option_info(&info, &opt, "boot", + KEY_STR, iso9660->el_torito.boot_filename.s); + if (iso9660->opt.boot_catalog != OPT_BOOT_CATALOG_DEFAULT) + set_option_info(&info, &opt, "boot-catalog", + KEY_STR, iso9660->el_torito.catalog_filename.s); + if (iso9660->opt.boot_info_table != OPT_BOOT_INFO_TABLE_DEFAULT) + set_option_info(&info, &opt, "boot-info-table", + KEY_FLG, iso9660->opt.boot_info_table); + if (iso9660->opt.boot_load_seg != OPT_BOOT_LOAD_SEG_DEFAULT) + set_option_info(&info, &opt, "boot-load-seg", + KEY_HEX, iso9660->el_torito.boot_load_seg); + if (iso9660->opt.boot_load_size != OPT_BOOT_LOAD_SIZE_DEFAULT) + set_option_info(&info, &opt, "boot-load-size", + KEY_INT, iso9660->el_torito.boot_load_size); + if (iso9660->opt.boot_type != OPT_BOOT_TYPE_DEFAULT) { + v = "no-emulation"; + if (iso9660->opt.boot_type == OPT_BOOT_TYPE_FD) + v = "fd"; + if (iso9660->opt.boot_type == OPT_BOOT_TYPE_HARD_DISK) + v = "hard-disk"; + set_option_info(&info, &opt, "boot-type", + KEY_STR, v); + } +#ifdef HAVE_ZLIB_H + if (iso9660->opt.compression_level != OPT_COMPRESSION_LEVEL_DEFAULT) + set_option_info(&info, &opt, "compression-level", + KEY_INT, iso9660->zisofs.compression_level); +#endif + if (iso9660->opt.copyright_file != OPT_COPYRIGHT_FILE_DEFAULT) + set_option_info(&info, &opt, "copyright-file", + KEY_STR, iso9660->copyright_file_identifier.s); + if (iso9660->opt.iso_level != OPT_ISO_LEVEL_DEFAULT) + set_option_info(&info, &opt, "iso-level", + KEY_INT, iso9660->opt.iso_level); + if (iso9660->opt.joliet != OPT_JOLIET_DEFAULT) { + if (iso9660->opt.joliet == OPT_JOLIET_LONGNAME) + set_option_info(&info, &opt, "joliet", + KEY_STR, "long"); + else + set_option_info(&info, &opt, "joliet", + KEY_FLG, iso9660->opt.joliet); + } + if (iso9660->opt.limit_depth != OPT_LIMIT_DEPTH_DEFAULT) + set_option_info(&info, &opt, "limit-depth", + KEY_FLG, iso9660->opt.limit_depth); + if (iso9660->opt.limit_dirs != OPT_LIMIT_DIRS_DEFAULT) + set_option_info(&info, &opt, "limit-dirs", + KEY_FLG, iso9660->opt.limit_dirs); + if (iso9660->opt.pad != OPT_PAD_DEFAULT) + set_option_info(&info, &opt, "pad", + KEY_FLG, iso9660->opt.pad); + if (iso9660->opt.publisher != OPT_PUBLISHER_DEFAULT) + set_option_info(&info, &opt, "publisher", + KEY_STR, iso9660->publisher_identifier.s); + if (iso9660->opt.rr != OPT_RR_DEFAULT) { + if (iso9660->opt.rr == OPT_RR_DISABLED) + set_option_info(&info, &opt, "rockridge", + KEY_FLG, iso9660->opt.rr); + else if (iso9660->opt.rr == OPT_RR_STRICT) + set_option_info(&info, &opt, "rockridge", + KEY_STR, "strict"); + else if (iso9660->opt.rr == OPT_RR_USEFUL) + set_option_info(&info, &opt, "rockridge", + KEY_STR, "useful"); + } + if (iso9660->opt.volume_id != OPT_VOLUME_ID_DEFAULT) + set_option_info(&info, &opt, "volume-id", + KEY_STR, iso9660->volume_identifier.s); + if (iso9660->opt.zisofs != OPT_ZISOFS_DEFAULT) + set_option_info(&info, &opt, "zisofs", + KEY_FLG, iso9660->opt.zisofs); + + memcpy(wb_buffptr(a), info.s, info_size); + archive_string_free(&info); + return (wb_consume(a, info_size)); +} + +static int +write_rr_ER(struct archive_write *a) +{ + unsigned char *p; + + p = wb_buffptr(a); + + memset(p, 0, LOGICAL_BLOCK_SIZE); + p[0] = 'E'; + p[1] = 'R'; + p[3] = 0x01; + p[2] = RRIP_ER_SIZE; + p[4] = RRIP_ER_ID_SIZE; + p[5] = RRIP_ER_DSC_SIZE; + p[6] = RRIP_ER_SRC_SIZE; + p[7] = 0x01; + memcpy(&p[8], rrip_identifier, p[4]); + memcpy(&p[8+p[4]], rrip_descriptor, p[5]); + memcpy(&p[8+p[4]+p[5]], rrip_source, p[6]); + + return (wb_consume(a, LOGICAL_BLOCK_SIZE)); +} + +static void +calculate_path_table_size(struct vdd *vdd) +{ + int depth, size; + struct path_table *pt; + + pt = vdd->pathtbl; + size = 0; + for (depth = 0; depth < vdd->max_depth; depth++) { + struct isoent **ptbl; + int i, cnt; + + if ((cnt = pt[depth].cnt) == 0) + break; + + ptbl = pt[depth].sorted; + for (i = 0; i < cnt; i++) { + int len; + + if (ptbl[i]->identifier == NULL) + len = 1; /* root directory */ + else + len = ptbl[i]->id_len; + if (len & 0x01) + len++; /* Padding Field */ + size += 8 + len; + } + } + vdd->path_table_size = size; + vdd->path_table_block = + ((size + PATH_TABLE_BLOCK_SIZE -1) / + PATH_TABLE_BLOCK_SIZE) * + (PATH_TABLE_BLOCK_SIZE / LOGICAL_BLOCK_SIZE); +} + +static int +_write_path_table(struct archive_write *a, int type_m, int depth, + struct vdd *vdd) +{ + unsigned char *bp, *wb; + struct isoent **ptbl; + size_t wbremaining; + int i, r, wsize; + + if (vdd->pathtbl[depth].cnt == 0) + return (0); + + wsize = 0; + wb = wb_buffptr(a); + wbremaining = wb_remaining(a); + bp = wb - 1; + ptbl = vdd->pathtbl[depth].sorted; + for (i = 0; i < vdd->pathtbl[depth].cnt; i++) { + struct isoent *np; + size_t len; + + np = ptbl[i]; + if (np->identifier == NULL) + len = 1; /* root directory */ + else + len = np->id_len; + if (wbremaining - ((bp+1) - wb) < (len + 1 + 8)) { + r = wb_consume(a, (bp+1) - wb); + if (r < 0) + return (r); + wb = wb_buffptr(a); + wbremaining = wb_remaining(a); + bp = wb -1; + } + /* Length of Directory Identifier */ + set_num_711(bp+1, (unsigned char)len); + /* Extended Attribute Record Length */ + set_num_711(bp+2, 0); + /* Location of Extent */ + if (type_m) + set_num_732(bp+3, np->dir_location); + else + set_num_731(bp+3, np->dir_location); + /* Parent Directory Number */ + if (type_m) + set_num_722(bp+7, np->parent->dir_number); + else + set_num_721(bp+7, np->parent->dir_number); + /* Directory Identifier */ + if (np->identifier == NULL) + bp[9] = 0; + else + memcpy(&bp[9], np->identifier, len); + if (len & 0x01) { + /* Padding Field */ + bp[9+len] = 0; + len++; + } + wsize += 8 + (int)len; + bp += 8 + len; + } + if ((bp + 1) > wb) { + r = wb_consume(a, (bp+1)-wb); + if (r < 0) + return (r); + } + return (wsize); +} + +static int +write_path_table(struct archive_write *a, int type_m, struct vdd *vdd) +{ + int depth, r; + size_t path_table_size; + + r = ARCHIVE_OK; + path_table_size = 0; + for (depth = 0; depth < vdd->max_depth; depth++) { + r = _write_path_table(a, type_m, depth, vdd); + if (r < 0) + return (r); + path_table_size += r; + } + + /* Write padding data. */ + path_table_size = path_table_size % PATH_TABLE_BLOCK_SIZE; + if (path_table_size > 0) + r = write_null(a, PATH_TABLE_BLOCK_SIZE - path_table_size); + return (r); +} + +static int +calculate_directory_descriptors(struct iso9660 *iso9660, struct vdd *vdd, + struct isoent *isoent, int depth) +{ + struct isoent **enttbl; + int bs, block, i; + + block = 1; + bs = get_dir_rec_size(iso9660, isoent, DIR_REC_SELF, vdd->vdd_type); + bs += get_dir_rec_size(iso9660, isoent, DIR_REC_PARENT, vdd->vdd_type); + + if (isoent->children.cnt <= 0 || (vdd->vdd_type != VDD_JOLIET && + !iso9660->opt.rr && depth + 1 >= vdd->max_depth)) + return (block); + + enttbl = isoent->children_sorted; + for (i = 0; i < isoent->children.cnt; i++) { + struct isoent *np = enttbl[i]; + struct isofile *file; + + file = np->file; + if (file->hardlink_target != NULL) + file = file->hardlink_target; + file->cur_content = &(file->content); + do { + int dr_l; + + dr_l = get_dir_rec_size(iso9660, np, DIR_REC_NORMAL, + vdd->vdd_type); + if ((bs + dr_l) > LOGICAL_BLOCK_SIZE) { + block ++; + bs = dr_l; + } else + bs += dr_l; + file->cur_content = file->cur_content->next; + } while (file->cur_content != NULL); + } + return (block); +} + +static int +_write_directory_descriptors(struct archive_write *a, struct vdd *vdd, + struct isoent *isoent, int depth) +{ + struct iso9660 *iso9660 = a->format_data; + struct isoent **enttbl; + unsigned char *p, *wb; + int i, r; + int dr_l; + + p = wb = wb_buffptr(a); +#define WD_REMAINING (LOGICAL_BLOCK_SIZE - (p - wb)) + p += set_directory_record(p, WD_REMAINING, isoent, + iso9660, DIR_REC_SELF, vdd->vdd_type); + p += set_directory_record(p, WD_REMAINING, isoent, + iso9660, DIR_REC_PARENT, vdd->vdd_type); + + if (isoent->children.cnt <= 0 || (vdd->vdd_type != VDD_JOLIET && + !iso9660->opt.rr && depth + 1 >= vdd->max_depth)) { + memset(p, 0, WD_REMAINING); + return (wb_consume(a, LOGICAL_BLOCK_SIZE)); + } + + enttbl = isoent->children_sorted; + for (i = 0; i < isoent->children.cnt; i++) { + struct isoent *np = enttbl[i]; + struct isofile *file = np->file; + + if (file->hardlink_target != NULL) + file = file->hardlink_target; + file->cur_content = &(file->content); + do { + dr_l = set_directory_record(p, WD_REMAINING, + np, iso9660, DIR_REC_NORMAL, + vdd->vdd_type); + if (dr_l == 0) { + memset(p, 0, WD_REMAINING); + r = wb_consume(a, LOGICAL_BLOCK_SIZE); + if (r < 0) + return (r); + p = wb = wb_buffptr(a); + dr_l = set_directory_record(p, + WD_REMAINING, np, iso9660, + DIR_REC_NORMAL, vdd->vdd_type); + } + p += dr_l; + file->cur_content = file->cur_content->next; + } while (file->cur_content != NULL); + } + memset(p, 0, WD_REMAINING); + return (wb_consume(a, LOGICAL_BLOCK_SIZE)); +} + +static int +write_directory_descriptors(struct archive_write *a, struct vdd *vdd) +{ + struct isoent *np; + int depth, r; + + depth = 0; + np = vdd->rootent; + do { + struct extr_rec *extr; + + r = _write_directory_descriptors(a, vdd, np, depth); + if (r < 0) + return (r); + if (vdd->vdd_type != VDD_JOLIET) { + /* + * This extract record is used by SUSP,RRIP. + * Not for joliet. + */ + for (extr = np->extr_rec_list.first; + extr != NULL; + extr = extr->next) { + unsigned char *wb; + + wb = wb_buffptr(a); + memcpy(wb, extr->buf, extr->offset); + memset(wb + extr->offset, 0, + LOGICAL_BLOCK_SIZE - extr->offset); + r = wb_consume(a, LOGICAL_BLOCK_SIZE); + if (r < 0) + return (r); + } + } + + if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) { + /* Enter to sub directories. */ + np = np->subdirs.first; + depth++; + continue; + } + while (np != np->parent) { + if (np->drnext == NULL) { + /* Return to the parent directory. */ + np = np->parent; + depth--; + } else { + np = np->drnext; + break; + } + } + } while (np != np->parent); + + return (ARCHIVE_OK); +} + +/* + * Read file contents from the temporary file, and write it. + */ +static int +write_file_contents(struct archive_write *a, int64_t offset, int64_t size) +{ + struct iso9660 *iso9660 = a->format_data; + int r; + + lseek(iso9660->temp_fd, offset, SEEK_SET); + + while (size) { + size_t rsize; + ssize_t rs; + unsigned char *wb; + + wb = wb_buffptr(a); + rsize = wb_remaining(a); + if (rsize > (size_t)size) + rsize = (size_t)size; + rs = read(iso9660->temp_fd, wb, rsize); + if (rs <= 0) { + archive_set_error(&a->archive, errno, + "Can't read temporary file(%jd)", (intmax_t)rs); + return (ARCHIVE_FATAL); + } + size -= rs; + r = wb_consume(a, rs); + if (r < 0) + return (r); + } + return (ARCHIVE_OK); +} + +static int +write_file_descriptors(struct archive_write *a) +{ + struct iso9660 *iso9660 = a->format_data; + struct isofile *file; + int64_t blocks, offset; + int r; + + blocks = 0; + offset = 0; + + /* Make the boot catalog contents, and write it. */ + if (iso9660->el_torito.catalog != NULL) { + r = make_boot_catalog(a); + if (r < 0) + return (r); + } + + /* Write the boot file contents. */ + if (iso9660->el_torito.boot != NULL) { + file = iso9660->el_torito.boot->file; + blocks = file->content.blocks; + offset = file->content.offset_of_temp; + if (offset != 0) { + r = write_file_contents(a, offset, + blocks << LOGICAL_BLOCK_BITS); + if (r < 0) + return (r); + blocks = 0; + offset = 0; + } + } + + /* Write out all file contents. */ + for (file = iso9660->data_file_list.first; + file != NULL; file = file->datanext) { + + if (!file->write_content) + continue; + + if ((offset + (blocks << LOGICAL_BLOCK_BITS)) < + file->content.offset_of_temp) { + if (blocks > 0) { + r = write_file_contents(a, offset, + blocks << LOGICAL_BLOCK_BITS); + if (r < 0) + return (r); + } + blocks = 0; + offset = file->content.offset_of_temp; + } + + file->cur_content = &(file->content); + do { + blocks += file->cur_content->blocks; + /* Next fragment */ + file->cur_content = file->cur_content->next; + } while (file->cur_content != NULL); + } + + /* Flush out remaining blocks. */ + if (blocks > 0) { + r = write_file_contents(a, offset, + blocks << LOGICAL_BLOCK_BITS); + if (r < 0) + return (r); + } + + return (ARCHIVE_OK); +} + +static void +isofile_init_entry_list(struct iso9660 *iso9660) +{ + iso9660->all_file_list.first = NULL; + iso9660->all_file_list.last = &(iso9660->all_file_list.first); +} + +static void +isofile_add_entry(struct iso9660 *iso9660, struct isofile *file) +{ + file->allnext = NULL; + *iso9660->all_file_list.last = file; + iso9660->all_file_list.last = &(file->allnext); +} + +static void +isofile_free_all_entries(struct iso9660 *iso9660) +{ + struct isofile *file, *file_next; + + file = iso9660->all_file_list.first; + while (file != NULL) { + file_next = file->allnext; + isofile_free(file); + file = file_next; + } +} + +static void +isofile_init_entry_data_file_list(struct iso9660 *iso9660) +{ + iso9660->data_file_list.first = NULL; + iso9660->data_file_list.last = &(iso9660->data_file_list.first); +} + +static void +isofile_add_data_file(struct iso9660 *iso9660, struct isofile *file) +{ + file->datanext = NULL; + *iso9660->data_file_list.last = file; + iso9660->data_file_list.last = &(file->datanext); +} + + +static struct isofile * +isofile_new(struct archive_write *a, struct archive_entry *entry) +{ + struct isofile *file; + + file = calloc(1, sizeof(*file)); + if (file == NULL) + return (NULL); + + if (entry != NULL) + file->entry = archive_entry_clone(entry); + else + file->entry = archive_entry_new2(&a->archive); + if (file->entry == NULL) { + free(file); + return (NULL); + } + archive_string_init(&(file->parentdir)); + archive_string_init(&(file->basename)); + archive_string_init(&(file->basename_utf16)); + archive_string_init(&(file->symlink)); + file->cur_content = &(file->content); + + return (file); +} + +static void +isofile_free(struct isofile *file) +{ + struct content *con, *tmp; + + con = file->content.next; + while (con != NULL) { + tmp = con; + con = con->next; + free(tmp); + } + archive_entry_free(file->entry); + archive_string_free(&(file->parentdir)); + archive_string_free(&(file->basename)); + archive_string_free(&(file->basename_utf16)); + archive_string_free(&(file->symlink)); + free(file); +} + +#if defined(_WIN32) || defined(__CYGWIN__) +static int +cleanup_backslash_1(char *p) +{ + int mb, dos; + + mb = dos = 0; + while (*p) { + if (*(unsigned char *)p > 127) + mb = 1; + if (*p == '\\') { + /* If we have not met any multi-byte characters, + * we can replace '\' with '/'. */ + if (!mb) + *p = '/'; + dos = 1; + } + p++; + } + if (!mb || !dos) + return (0); + return (-1); +} + +static void +cleanup_backslash_2(wchar_t *p) +{ + + /* Convert a path-separator from '\' to '/' */ + while (*p != L'\0') { + if (*p == L'\\') + *p = L'/'; + p++; + } +} +#endif + +/* + * Generate a parent directory name and a base name from a pathname. + */ +static int +isofile_gen_utility_names(struct archive_write *a, struct isofile *file) +{ + struct iso9660 *iso9660; + const char *pathname; + char *p, *dirname, *slash; + size_t len; + int ret = ARCHIVE_OK; + + iso9660 = a->format_data; + + archive_string_empty(&(file->parentdir)); + archive_string_empty(&(file->basename)); + archive_string_empty(&(file->basename_utf16)); + archive_string_empty(&(file->symlink)); + + pathname = archive_entry_pathname(file->entry); + if (pathname == NULL || pathname[0] == '\0') {/* virtual root */ + file->dircnt = 0; + return (ret); + } + + /* + * Make a UTF-16BE basename if Joliet extension enabled. + */ + if (iso9660->opt.joliet) { + const char *u16, *ulast; + size_t u16len, ulen_last; + + if (iso9660->sconv_to_utf16be == NULL) { + iso9660->sconv_to_utf16be = + archive_string_conversion_to_charset( + &(a->archive), "UTF-16BE", 1); + if (iso9660->sconv_to_utf16be == NULL) + /* Couldn't allocate memory */ + return (ARCHIVE_FATAL); + iso9660->sconv_from_utf16be = + archive_string_conversion_from_charset( + &(a->archive), "UTF-16BE", 1); + if (iso9660->sconv_from_utf16be == NULL) + /* Couldn't allocate memory */ + return (ARCHIVE_FATAL); + } + + /* + * Convert a filename to UTF-16BE. + */ + if (0 > archive_entry_pathname_l(file->entry, &u16, &u16len, + iso9660->sconv_to_utf16be)) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for UTF-16BE"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "A filename cannot be converted to UTF-16BE;" + "You should disable making Joliet extension"); + ret = ARCHIVE_WARN; + } + + /* + * Make sure a path separator is not in the last; + * Remove trailing '/'. + */ + while (u16len >= 2) { +#if defined(_WIN32) || defined(__CYGWIN__) + if (u16[u16len-2] == 0 && + (u16[u16len-1] == '/' || u16[u16len-1] == '\\')) +#else + if (u16[u16len-2] == 0 && u16[u16len-1] == '/') +#endif + { + u16len -= 2; + } else + break; + } + + /* + * Find a basename in UTF-16BE. + */ + ulast = u16; + u16len >>= 1; + ulen_last = u16len; + while (u16len > 0) { +#if defined(_WIN32) || defined(__CYGWIN__) + if (u16[0] == 0 && (u16[1] == '/' || u16[1] == '\\')) +#else + if (u16[0] == 0 && u16[1] == '/') +#endif + { + ulast = u16 + 2; + ulen_last = u16len -1; + } + u16 += 2; + u16len --; + } + ulen_last <<= 1; + if (archive_string_ensure(&(file->basename_utf16), + ulen_last) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for UTF-16BE"); + return (ARCHIVE_FATAL); + } + + /* + * Set UTF-16BE basename. + */ + memcpy(file->basename_utf16.s, ulast, ulen_last); + file->basename_utf16.length = ulen_last; + } + + archive_strcpy(&(file->parentdir), pathname); +#if defined(_WIN32) || defined(__CYGWIN__) + /* + * Convert a path-separator from '\' to '/' + */ + if (cleanup_backslash_1(file->parentdir.s) != 0) { + const wchar_t *wp = archive_entry_pathname_w(file->entry); + struct archive_wstring ws; + + if (wp != NULL) { + int r; + archive_string_init(&ws); + archive_wstrcpy(&ws, wp); + cleanup_backslash_2(ws.s); + archive_string_empty(&(file->parentdir)); + r = archive_string_append_from_wcs(&(file->parentdir), + ws.s, ws.length); + archive_wstring_free(&ws); + if (r < 0 && errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + } + } +#endif + + len = file->parentdir.length; + p = dirname = file->parentdir.s; + + /* + * Remove leading '/', '../' and './' elements + */ + while (*p) { + if (p[0] == '/') { + p++; + len--; + } else if (p[0] != '.') + break; + else if (p[1] == '.' && p[2] == '/') { + p += 3; + len -= 3; + } else if (p[1] == '/' || (p[1] == '.' && p[2] == '\0')) { + p += 2; + len -= 2; + } else if (p[1] == '\0') { + p++; + len--; + } else + break; + } + if (p != dirname) { + memmove(dirname, p, len+1); + p = dirname; + } + /* + * Remove "/","/." and "/.." elements from tail. + */ + while (len > 0) { + size_t ll = len; + + if (len > 0 && p[len-1] == '/') { + p[len-1] = '\0'; + len--; + } + if (len > 1 && p[len-2] == '/' && p[len-1] == '.') { + p[len-2] = '\0'; + len -= 2; + } + if (len > 2 && p[len-3] == '/' && p[len-2] == '.' && + p[len-1] == '.') { + p[len-3] = '\0'; + len -= 3; + } + if (ll == len) + break; + } + while (*p) { + if (p[0] == '/') { + if (p[1] == '/') + /* Convert '//' --> '/' */ + memmove(p, p+1, strlen(p+1) + 1); + else if (p[1] == '.' && p[2] == '/') + /* Convert '/./' --> '/' */ + memmove(p, p+2, strlen(p+2) + 1); + else if (p[1] == '.' && p[2] == '.' && p[3] == '/') { + /* Convert 'dir/dir1/../dir2/' + * --> 'dir/dir2/' + */ + char *rp = p -1; + while (rp >= dirname) { + if (*rp == '/') + break; + --rp; + } + if (rp > dirname) { + strcpy(rp, p+3); + p = rp; + } else { + strcpy(dirname, p+4); + p = dirname; + } + } else + p++; + } else + p++; + } + p = dirname; + len = strlen(p); + + if (archive_entry_filetype(file->entry) == AE_IFLNK) { + /* Convert symlink name too. */ + pathname = archive_entry_symlink(file->entry); + archive_strcpy(&(file->symlink), pathname); +#if defined(_WIN32) || defined(__CYGWIN__) + /* + * Convert a path-separator from '\' to '/' + */ + if (archive_strlen(&(file->symlink)) > 0 && + cleanup_backslash_1(file->symlink.s) != 0) { + const wchar_t *wp = + archive_entry_symlink_w(file->entry); + struct archive_wstring ws; + + if (wp != NULL) { + int r; + archive_string_init(&ws); + archive_wstrcpy(&ws, wp); + cleanup_backslash_2(ws.s); + archive_string_empty(&(file->symlink)); + r = archive_string_append_from_wcs( + &(file->symlink), + ws.s, ws.length); + archive_wstring_free(&ws); + if (r < 0 && errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + } + } +#endif + } + /* + * - Count up directory elements. + * - Find out the position which points the last position of + * path separator('/'). + */ + slash = NULL; + file->dircnt = 0; + for (; *p != '\0'; p++) + if (*p == '/') { + slash = p; + file->dircnt++; + } + if (slash == NULL) { + /* The pathname doesn't have a parent directory. */ + file->parentdir.length = len; + archive_string_copy(&(file->basename), &(file->parentdir)); + archive_string_empty(&(file->parentdir)); + *file->parentdir.s = '\0'; + return (ret); + } + + /* Make a basename from dirname and slash */ + *slash = '\0'; + file->parentdir.length = slash - dirname; + archive_strcpy(&(file->basename), slash + 1); + if (archive_entry_filetype(file->entry) == AE_IFDIR) + file->dircnt ++; + return (ret); +} + +/* + * Register a entry to get a hardlink target. + */ +static int +isofile_register_hardlink(struct archive_write *a, struct isofile *file) +{ + struct iso9660 *iso9660 = a->format_data; + struct hardlink *hl; + const char *pathname; + + archive_entry_set_nlink(file->entry, 1); + pathname = archive_entry_hardlink(file->entry); + if (pathname == NULL) { + /* This `file` is a hardlink target. */ + hl = malloc(sizeof(*hl)); + if (hl == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + hl->nlink = 1; + /* A hardlink target must be the first position. */ + file->hlnext = NULL; + hl->file_list.first = file; + hl->file_list.last = &(file->hlnext); + __archive_rb_tree_insert_node(&(iso9660->hardlink_rbtree), + (struct archive_rb_node *)hl); + } else { + hl = (struct hardlink *)__archive_rb_tree_find_node( + &(iso9660->hardlink_rbtree), pathname); + if (hl != NULL) { + /* Insert `file` entry into the tail. */ + file->hlnext = NULL; + *hl->file_list.last = file; + hl->file_list.last = &(file->hlnext); + hl->nlink++; + } + archive_entry_unset_size(file->entry); + } + + return (ARCHIVE_OK); +} + +/* + * Hardlinked files have to have the same location of extent. + * We have to find out hardlink target entries for the entries + * which have a hardlink target name. + */ +static void +isofile_connect_hardlink_files(struct iso9660 *iso9660) +{ + struct archive_rb_node *n; + struct hardlink *hl; + struct isofile *target, *nf; + + ARCHIVE_RB_TREE_FOREACH(n, &(iso9660->hardlink_rbtree)) { + hl = (struct hardlink *)n; + + /* The first entry must be a hardlink target. */ + target = hl->file_list.first; + archive_entry_set_nlink(target->entry, hl->nlink); + /* Set a hardlink target to reference entries. */ + for (nf = target->hlnext; + nf != NULL; nf = nf->hlnext) { + nf->hardlink_target = target; + archive_entry_set_nlink(nf->entry, hl->nlink); + } + } +} + +static int +isofile_hd_cmp_node(const struct archive_rb_node *n1, + const struct archive_rb_node *n2) +{ + const struct hardlink *h1 = (const struct hardlink *)n1; + const struct hardlink *h2 = (const struct hardlink *)n2; + + return (strcmp(archive_entry_pathname(h1->file_list.first->entry), + archive_entry_pathname(h2->file_list.first->entry))); +} + +static int +isofile_hd_cmp_key(const struct archive_rb_node *n, const void *key) +{ + const struct hardlink *h = (const struct hardlink *)n; + + return (strcmp(archive_entry_pathname(h->file_list.first->entry), + (const char *)key)); +} + +static void +isofile_init_hardlinks(struct iso9660 *iso9660) +{ + static const struct archive_rb_tree_ops rb_ops = { + isofile_hd_cmp_node, isofile_hd_cmp_key, + }; + + __archive_rb_tree_init(&(iso9660->hardlink_rbtree), &rb_ops); +} + +static void +isofile_free_hardlinks(struct iso9660 *iso9660) +{ + struct archive_rb_node *n, *tmp; + + ARCHIVE_RB_TREE_FOREACH_SAFE(n, &(iso9660->hardlink_rbtree), tmp) { + __archive_rb_tree_remove_node(&(iso9660->hardlink_rbtree), n); + free(n); + } +} + +static struct isoent * +isoent_new(struct isofile *file) +{ + struct isoent *isoent; + static const struct archive_rb_tree_ops rb_ops = { + isoent_cmp_node, isoent_cmp_key, + }; + + isoent = calloc(1, sizeof(*isoent)); + if (isoent == NULL) + return (NULL); + isoent->file = file; + isoent->children.first = NULL; + isoent->children.last = &(isoent->children.first); + __archive_rb_tree_init(&(isoent->rbtree), &rb_ops); + isoent->subdirs.first = NULL; + isoent->subdirs.last = &(isoent->subdirs.first); + isoent->extr_rec_list.first = NULL; + isoent->extr_rec_list.last = &(isoent->extr_rec_list.first); + isoent->extr_rec_list.current = NULL; + if (archive_entry_filetype(file->entry) == AE_IFDIR) + isoent->dir = 1; + + return (isoent); +} + +static inline struct isoent * +isoent_clone(struct isoent *src) +{ + return (isoent_new(src->file)); +} + +static void +_isoent_free(struct isoent *isoent) +{ + struct extr_rec *er, *er_next; + + free(isoent->children_sorted); + free(isoent->identifier); + er = isoent->extr_rec_list.first; + while (er != NULL) { + er_next = er->next; + free(er); + er = er_next; + } + free(isoent); +} + +static void +isoent_free_all(struct isoent *isoent) +{ + struct isoent *np, *np_temp; + + if (isoent == NULL) + return; + np = isoent; + for (;;) { + if (np->dir) { + if (np->children.first != NULL) { + /* Enter to sub directories. */ + np = np->children.first; + continue; + } + } + for (;;) { + np_temp = np; + if (np->chnext == NULL) { + /* Return to the parent directory. */ + np = np->parent; + _isoent_free(np_temp); + if (np == np_temp) + return; + } else { + np = np->chnext; + _isoent_free(np_temp); + break; + } + } + } +} + +static struct isoent * +isoent_create_virtual_dir(struct archive_write *a, struct iso9660 *iso9660, const char *pathname) +{ + struct isofile *file; + struct isoent *isoent; + + file = isofile_new(a, NULL); + if (file == NULL) + return (NULL); + archive_entry_set_pathname(file->entry, pathname); + archive_entry_unset_mtime(file->entry); + archive_entry_unset_atime(file->entry); + archive_entry_unset_ctime(file->entry); + archive_entry_set_uid(file->entry, getuid()); + archive_entry_set_gid(file->entry, getgid()); + archive_entry_set_mode(file->entry, 0555 | AE_IFDIR); + archive_entry_set_nlink(file->entry, 2); + if (isofile_gen_utility_names(a, file) < ARCHIVE_WARN) { + isofile_free(file); + return (NULL); + } + isofile_add_entry(iso9660, file); + + isoent = isoent_new(file); + if (isoent == NULL) + return (NULL); + isoent->dir = 1; + isoent->virtual = 1; + + return (isoent); +} + +static int +isoent_cmp_node(const struct archive_rb_node *n1, + const struct archive_rb_node *n2) +{ + const struct isoent *e1 = (const struct isoent *)n1; + const struct isoent *e2 = (const struct isoent *)n2; + + return (strcmp(e1->file->basename.s, e2->file->basename.s)); +} + +static int +isoent_cmp_key(const struct archive_rb_node *n, const void *key) +{ + const struct isoent *e = (const struct isoent *)n; + + return (strcmp(e->file->basename.s, (const char *)key)); +} + +static int +isoent_add_child_head(struct isoent *parent, struct isoent *child) +{ + + if (!__archive_rb_tree_insert_node( + &(parent->rbtree), (struct archive_rb_node *)child)) + return (0); + if ((child->chnext = parent->children.first) == NULL) + parent->children.last = &(child->chnext); + parent->children.first = child; + parent->children.cnt++; + child->parent = parent; + + /* Add a child to a sub-directory chain */ + if (child->dir) { + if ((child->drnext = parent->subdirs.first) == NULL) + parent->subdirs.last = &(child->drnext); + parent->subdirs.first = child; + parent->subdirs.cnt++; + child->parent = parent; + } else + child->drnext = NULL; + return (1); +} + +static int +isoent_add_child_tail(struct isoent *parent, struct isoent *child) +{ + + if (!__archive_rb_tree_insert_node( + &(parent->rbtree), (struct archive_rb_node *)child)) + return (0); + child->chnext = NULL; + *parent->children.last = child; + parent->children.last = &(child->chnext); + parent->children.cnt++; + child->parent = parent; + + /* Add a child to a sub-directory chain */ + child->drnext = NULL; + if (child->dir) { + *parent->subdirs.last = child; + parent->subdirs.last = &(child->drnext); + parent->subdirs.cnt++; + child->parent = parent; + } + return (1); +} + +static void +isoent_remove_child(struct isoent *parent, struct isoent *child) +{ + struct isoent *ent; + + /* Remove a child entry from children chain. */ + ent = parent->children.first; + while (ent->chnext != child) + ent = ent->chnext; + if ((ent->chnext = ent->chnext->chnext) == NULL) + parent->children.last = &(ent->chnext); + parent->children.cnt--; + + if (child->dir) { + /* Remove a child entry from sub-directory chain. */ + ent = parent->subdirs.first; + while (ent->drnext != child) + ent = ent->drnext; + if ((ent->drnext = ent->drnext->drnext) == NULL) + parent->subdirs.last = &(ent->drnext); + parent->subdirs.cnt--; + } + + __archive_rb_tree_remove_node(&(parent->rbtree), + (struct archive_rb_node *)child); +} + +static int +isoent_clone_tree(struct archive_write *a, struct isoent **nroot, + struct isoent *root) +{ + struct isoent *np, *xroot, *newent; + + np = root; + xroot = NULL; + do { + newent = isoent_clone(np); + if (newent == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + if (xroot == NULL) { + *nroot = xroot = newent; + newent->parent = xroot; + } else + isoent_add_child_tail(xroot, newent); + if (np->dir && np->children.first != NULL) { + /* Enter to sub directories. */ + np = np->children.first; + xroot = newent; + continue; + } + while (np != np->parent) { + if (np->chnext == NULL) { + /* Return to the parent directory. */ + np = np->parent; + xroot = xroot->parent; + } else { + np = np->chnext; + break; + } + } + } while (np != np->parent); + + return (ARCHIVE_OK); +} + +/* + * Setup directory locations. + */ +static void +isoent_setup_directory_location(struct iso9660 *iso9660, int location, + struct vdd *vdd) +{ + struct isoent *np; + int depth; + + vdd->total_dir_block = 0; + depth = 0; + np = vdd->rootent; + do { + int block; + + np->dir_block = calculate_directory_descriptors( + iso9660, vdd, np, depth); + vdd->total_dir_block += np->dir_block; + np->dir_location = location; + location += np->dir_block; + block = extra_setup_location(np, location); + vdd->total_dir_block += block; + location += block; + + if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) { + /* Enter to sub directories. */ + np = np->subdirs.first; + depth++; + continue; + } + while (np != np->parent) { + if (np->drnext == NULL) { + /* Return to the parent directory. */ + np = np->parent; + depth--; + } else { + np = np->drnext; + break; + } + } + } while (np != np->parent); +} + +static void +_isoent_file_location(struct iso9660 *iso9660, struct isoent *isoent, + int *symlocation) +{ + struct isoent **children; + int n; + + if (isoent->children.cnt == 0) + return; + + children = isoent->children_sorted; + for (n = 0; n < isoent->children.cnt; n++) { + struct isoent *np; + struct isofile *file; + + np = children[n]; + if (np->dir) + continue; + if (np == iso9660->el_torito.boot) + continue; + file = np->file; + if (file->boot || file->hardlink_target != NULL) + continue; + if (archive_entry_filetype(file->entry) == AE_IFLNK || + file->content.size == 0) { + /* + * Do not point a valid location. + * Make sure entry is not hardlink file. + */ + file->content.location = (*symlocation)--; + continue; + } + + file->write_content = 1; + } +} + +/* + * Setup file locations. + */ +static void +isoent_setup_file_location(struct iso9660 *iso9660, int location) +{ + struct isoent *isoent; + struct isoent *np; + struct isofile *file; + size_t size; + int block; + int depth; + int joliet; + int symlocation; + int total_block; + + iso9660->total_file_block = 0; + if ((isoent = iso9660->el_torito.catalog) != NULL) { + isoent->file->content.location = location; + block = (int)((archive_entry_size(isoent->file->entry) + + LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS); + location += block; + iso9660->total_file_block += block; + } + if ((isoent = iso9660->el_torito.boot) != NULL) { + isoent->file->content.location = location; + size = fd_boot_image_size(iso9660->el_torito.media_type); + if (size == 0) + size = (size_t)archive_entry_size(isoent->file->entry); + block = ((int)size + LOGICAL_BLOCK_SIZE -1) + >> LOGICAL_BLOCK_BITS; + location += block; + iso9660->total_file_block += block; + isoent->file->content.blocks = block; + } + + depth = 0; + symlocation = -16; + if (!iso9660->opt.rr && iso9660->opt.joliet) { + joliet = 1; + np = iso9660->joliet.rootent; + } else { + joliet = 0; + np = iso9660->primary.rootent; + } + do { + _isoent_file_location(iso9660, np, &symlocation); + + if (np->subdirs.first != NULL && + (joliet || + ((iso9660->opt.rr == OPT_RR_DISABLED && + depth + 2 < iso9660->primary.max_depth) || + (iso9660->opt.rr && + depth + 1 < iso9660->primary.max_depth)))) { + /* Enter to sub directories. */ + np = np->subdirs.first; + depth++; + continue; + } + while (np != np->parent) { + if (np->drnext == NULL) { + /* Return to the parent directory. */ + np = np->parent; + depth--; + } else { + np = np->drnext; + break; + } + } + } while (np != np->parent); + + total_block = 0; + for (file = iso9660->data_file_list.first; + file != NULL; file = file->datanext) { + + if (!file->write_content) + continue; + + file->cur_content = &(file->content); + do { + file->cur_content->location = location; + location += file->cur_content->blocks; + total_block += file->cur_content->blocks; + /* Next fragment */ + file->cur_content = file->cur_content->next; + } while (file->cur_content != NULL); + } + iso9660->total_file_block += total_block; +} + +static int +get_path_component(char *name, size_t n, const char *fn) +{ + char *p; + size_t l; + + p = strchr(fn, '/'); + if (p == NULL) { + if ((l = strlen(fn)) == 0) + return (0); + } else + l = p - fn; + if (l > n -1) + return (-1); + memcpy(name, fn, l); + name[l] = '\0'; + + return ((int)l); +} + +/* + * Add a new entry into the tree. + */ +static int +isoent_tree(struct archive_write *a, struct isoent **isoentpp) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + char name[_MAX_FNAME];/* Included null terminator size. */ +#elif defined(NAME_MAX) && NAME_MAX >= 255 + char name[NAME_MAX+1]; +#else + char name[256]; +#endif + struct iso9660 *iso9660 = a->format_data; + struct isoent *dent, *isoent, *np; + struct isofile *f1, *f2; + const char *fn, *p; + int l; + + isoent = *isoentpp; + dent = iso9660->primary.rootent; + if (isoent->file->parentdir.length > 0) + fn = p = isoent->file->parentdir.s; + else + fn = p = ""; + + /* + * If the path of the parent directory of `isoent' entry is + * the same as the path of `cur_dirent', add isoent to + * `cur_dirent'. + */ + if (archive_strlen(&(iso9660->cur_dirstr)) + == archive_strlen(&(isoent->file->parentdir)) && + strcmp(iso9660->cur_dirstr.s, fn) == 0) { + if (!isoent_add_child_tail(iso9660->cur_dirent, isoent)) { + np = (struct isoent *)__archive_rb_tree_find_node( + &(iso9660->cur_dirent->rbtree), + isoent->file->basename.s); + goto same_entry; + } + return (ARCHIVE_OK); + } + + for (;;) { + l = get_path_component(name, sizeof(name), fn); + if (l == 0) { + np = NULL; + break; + } + if (l < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "A name buffer is too small"); + _isoent_free(isoent); + return (ARCHIVE_FATAL); + } + + np = isoent_find_child(dent, name); + if (np == NULL || fn[0] == '\0') + break; + + /* Find next subdirectory. */ + if (!np->dir) { + /* NOT Directory! */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "`%s' is not directory, we cannot insert `%s' ", + archive_entry_pathname(np->file->entry), + archive_entry_pathname(isoent->file->entry)); + _isoent_free(isoent); + *isoentpp = NULL; + return (ARCHIVE_FAILED); + } + fn += l; + if (fn[0] == '/') + fn++; + dent = np; + } + if (np == NULL) { + /* + * Create virtual parent directories. + */ + while (fn[0] != '\0') { + struct isoent *vp; + struct archive_string as; + + archive_string_init(&as); + archive_strncat(&as, p, fn - p + l); + if (as.s[as.length-1] == '/') { + as.s[as.length-1] = '\0'; + as.length--; + } + vp = isoent_create_virtual_dir(a, iso9660, as.s); + if (vp == NULL) { + archive_string_free(&as); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + _isoent_free(isoent); + *isoentpp = NULL; + return (ARCHIVE_FATAL); + } + archive_string_free(&as); + + if (vp->file->dircnt > iso9660->dircnt_max) + iso9660->dircnt_max = vp->file->dircnt; + isoent_add_child_tail(dent, vp); + np = vp; + + fn += l; + if (fn[0] == '/') + fn++; + l = get_path_component(name, sizeof(name), fn); + if (l < 0) { + archive_string_free(&as); + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "A name buffer is too small"); + _isoent_free(isoent); + *isoentpp = NULL; + return (ARCHIVE_FATAL); + } + dent = np; + } + + /* Found out the parent directory where isoent can be + * inserted. */ + iso9660->cur_dirent = dent; + archive_string_empty(&(iso9660->cur_dirstr)); + archive_string_ensure(&(iso9660->cur_dirstr), + archive_strlen(&(dent->file->parentdir)) + + archive_strlen(&(dent->file->basename)) + 2); + if (archive_strlen(&(dent->file->parentdir)) + + archive_strlen(&(dent->file->basename)) == 0) + iso9660->cur_dirstr.s[0] = 0; + else { + if (archive_strlen(&(dent->file->parentdir)) > 0) { + archive_string_copy(&(iso9660->cur_dirstr), + &(dent->file->parentdir)); + archive_strappend_char(&(iso9660->cur_dirstr), '/'); + } + archive_string_concat(&(iso9660->cur_dirstr), + &(dent->file->basename)); + } + + if (!isoent_add_child_tail(dent, isoent)) { + np = (struct isoent *)__archive_rb_tree_find_node( + &(dent->rbtree), isoent->file->basename.s); + goto same_entry; + } + return (ARCHIVE_OK); + } + +same_entry: + /* + * We have already has the entry the filename of which is + * the same. + */ + f1 = np->file; + f2 = isoent->file; + + /* If the file type of entries is different, + * we cannot handle it. */ + if (archive_entry_filetype(f1->entry) != + archive_entry_filetype(f2->entry)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Found duplicate entries `%s' and its file type is " + "different", + archive_entry_pathname(f1->entry)); + _isoent_free(isoent); + *isoentpp = NULL; + return (ARCHIVE_FAILED); + } + + /* Swap file entries. */ + np->file = f2; + isoent->file = f1; + np->virtual = 0; + + _isoent_free(isoent); + *isoentpp = np; + return (ARCHIVE_OK); +} + +/* + * Find a entry from `isoent' + */ +static struct isoent * +isoent_find_child(struct isoent *isoent, const char *child_name) +{ + struct isoent *np; + + np = (struct isoent *)__archive_rb_tree_find_node( + &(isoent->rbtree), child_name); + return (np); +} + +/* + * Find a entry full-path of which is specified by `fn' parameter, + * in the tree. + */ +static struct isoent * +isoent_find_entry(struct isoent *rootent, const char *fn) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + char name[_MAX_FNAME];/* Included null terminator size. */ +#elif defined(NAME_MAX) && NAME_MAX >= 255 + char name[NAME_MAX+1]; +#else + char name[256]; +#endif + struct isoent *isoent, *np; + int l; + + isoent = rootent; + np = NULL; + for (;;) { + l = get_path_component(name, sizeof(name), fn); + if (l == 0) + break; + fn += l; + if (fn[0] == '/') + fn++; + + np = isoent_find_child(isoent, name); + if (np == NULL) + break; + if (fn[0] == '\0') + break;/* We found out the entry */ + + /* Try sub directory. */ + isoent = np; + np = NULL; + if (!isoent->dir) + break;/* Not directory */ + } + + return (np); +} + +/* + * Following idr_* functions are used for resolving duplicated filenames + * and unreceivable filenames to generate ISO9660/Joliet Identifiers. + */ + +static void +idr_relaxed_filenames(char *map) +{ + int i; + + for (i = 0x21; i <= 0x2F; i++) + map[i] = 1; + for (i = 0x3A; i <= 0x41; i++) + map[i] = 1; + for (i = 0x5B; i <= 0x5E; i++) + map[i] = 1; + map[0x60] = 1; + for (i = 0x7B; i <= 0x7E; i++) + map[i] = 1; +} + +static void +idr_init(struct iso9660 *iso9660, struct vdd *vdd, struct idr *idr) +{ + + idr->idrent_pool = NULL; + idr->pool_size = 0; + if (vdd->vdd_type != VDD_JOLIET) { + if (iso9660->opt.iso_level <= 3) { + memcpy(idr->char_map, d_characters_map, + sizeof(idr->char_map)); + } else { + memcpy(idr->char_map, d1_characters_map, + sizeof(idr->char_map)); + idr_relaxed_filenames(idr->char_map); + } + } +} + +static void +idr_cleanup(struct idr *idr) +{ + free(idr->idrent_pool); +} + +static int +idr_ensure_poolsize(struct archive_write *a, struct idr *idr, + int cnt) +{ + + if (idr->pool_size < cnt) { + void *p; + const int bk = (1 << 7) - 1; + int psize; + + psize = (cnt + bk) & ~bk; + p = realloc(idr->idrent_pool, sizeof(struct idrent) * psize); + if (p == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + idr->idrent_pool = (struct idrent *)p; + idr->pool_size = psize; + } + return (ARCHIVE_OK); +} + +static int +idr_start(struct archive_write *a, struct idr *idr, int cnt, int ffmax, + int num_size, int null_size, const struct archive_rb_tree_ops *rbt_ops) +{ + int r; + + (void)ffmax; /* UNUSED */ + + r = idr_ensure_poolsize(a, idr, cnt); + if (r != ARCHIVE_OK) + return (r); + __archive_rb_tree_init(&(idr->rbtree), rbt_ops); + idr->wait_list.first = NULL; + idr->wait_list.last = &(idr->wait_list.first); + idr->pool_idx = 0; + idr->num_size = num_size; + idr->null_size = null_size; + return (ARCHIVE_OK); +} + +static void +idr_register(struct idr *idr, struct isoent *isoent, int weight, int noff) +{ + struct idrent *idrent, *n; + + idrent = &(idr->idrent_pool[idr->pool_idx++]); + idrent->wnext = idrent->avail = NULL; + idrent->isoent = isoent; + idrent->weight = weight; + idrent->noff = noff; + idrent->rename_num = 0; + + if (!__archive_rb_tree_insert_node(&(idr->rbtree), &(idrent->rbnode))) { + n = (struct idrent *)__archive_rb_tree_find_node( + &(idr->rbtree), idrent->isoent); + if (n != NULL) { + /* this `idrent' needs to rename. */ + idrent->avail = n; + *idr->wait_list.last = idrent; + idr->wait_list.last = &(idrent->wnext); + } + } +} + +static void +idr_extend_identifier(struct idrent *wnp, int numsize, int nullsize) +{ + unsigned char *p; + int wnp_ext_off; + + wnp_ext_off = wnp->isoent->ext_off; + if (wnp->noff + numsize != wnp_ext_off) { + p = (unsigned char *)wnp->isoent->identifier; + /* Extend the filename; foo.c --> foo___.c */ + memmove(p + wnp->noff + numsize, p + wnp_ext_off, + wnp->isoent->ext_len + nullsize); + wnp->isoent->ext_off = wnp_ext_off = wnp->noff + numsize; + wnp->isoent->id_len = wnp_ext_off + wnp->isoent->ext_len; + } +} + +static void +idr_resolve(struct idr *idr, void (*fsetnum)(unsigned char *p, int num)) +{ + struct idrent *n; + unsigned char *p; + + for (n = idr->wait_list.first; n != NULL; n = n->wnext) { + idr_extend_identifier(n, idr->num_size, idr->null_size); + p = (unsigned char *)n->isoent->identifier + n->noff; + do { + fsetnum(p, n->avail->rename_num++); + } while (!__archive_rb_tree_insert_node( + &(idr->rbtree), &(n->rbnode))); + } +} + +static void +idr_set_num(unsigned char *p, int num) +{ + static const char xdig[] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z' + }; + + num %= sizeof(xdig) * sizeof(xdig) * sizeof(xdig); + p[0] = xdig[(num / (sizeof(xdig) * sizeof(xdig)))]; + num %= sizeof(xdig) * sizeof(xdig); + p[1] = xdig[ (num / sizeof(xdig))]; + num %= sizeof(xdig); + p[2] = xdig[num]; +} + +static void +idr_set_num_beutf16(unsigned char *p, int num) +{ + static const uint16_t xdig[] = { + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, + 0x0036, 0x0037, 0x0038, 0x0039, + 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, + 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, + 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, + 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, + 0x0059, 0x005A + }; +#define XDIG_CNT (sizeof(xdig)/sizeof(xdig[0])) + + num %= XDIG_CNT * XDIG_CNT * XDIG_CNT; + archive_be16enc(p, xdig[(num / (XDIG_CNT * XDIG_CNT))]); + num %= XDIG_CNT * XDIG_CNT; + archive_be16enc(p+2, xdig[ (num / XDIG_CNT)]); + num %= XDIG_CNT; + archive_be16enc(p+4, xdig[num]); +} + +/* + * Generate ISO9660 Identifier. + */ +static int +isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent, + struct idr *idr) +{ + struct iso9660 *iso9660; + struct isoent *np; + char *p; + int l, r; + const char *char_map; + char allow_ldots, allow_multidot, allow_period, allow_vernum; + int fnmax, ffmax, dnmax; + static const struct archive_rb_tree_ops rb_ops = { + isoent_cmp_node_iso9660, isoent_cmp_key_iso9660 + }; + + if (isoent->children.cnt == 0) + return (0); + + iso9660 = a->format_data; + char_map = idr->char_map; + if (iso9660->opt.iso_level <= 3) { + allow_ldots = 0; + allow_multidot = 0; + allow_period = 1; + allow_vernum = iso9660->opt.allow_vernum; + if (iso9660->opt.iso_level == 1) { + fnmax = 8; + ffmax = 12;/* fnmax + '.' + 3 */ + dnmax = 8; + } else { + fnmax = 30; + ffmax = 31; + dnmax = 31; + } + } else { + allow_ldots = allow_multidot = 1; + allow_period = allow_vernum = 0; + if (iso9660->opt.rr) + /* + * MDR : The maximum size of Directory Record(254). + * DRL : A Directory Record Length(33). + * CE : A size of SUSP CE System Use Entry(28). + * MDR - DRL - CE = 254 - 33 - 28 = 193. + */ + fnmax = ffmax = dnmax = 193; + else + /* + * XA : CD-ROM XA System Use Extension + * Information(14). + * MDR - DRL - XA = 254 - 33 -14 = 207. + */ + fnmax = ffmax = dnmax = 207; + } + + r = idr_start(a, idr, isoent->children.cnt, ffmax, 3, 1, &rb_ops); + if (r < 0) + return (r); + + for (np = isoent->children.first; np != NULL; np = np->chnext) { + char *dot, *xdot; + int ext_off, noff, weight; + + l = (int)np->file->basename.length; + p = malloc(l+31+2+1); + if (p == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + memcpy(p, np->file->basename.s, l); + p[l] = '\0'; + np->identifier = p; + + dot = xdot = NULL; + if (!allow_ldots) { + /* + * If there is a '.' character at the first byte, + * it has to be replaced by '_' character. + */ + if (*p == '.') + *p++ = '_'; + } + for (;*p; p++) { + if (*p & 0x80) { + *p = '_'; + continue; + } + if (char_map[(unsigned char)*p]) { + /* if iso-level is '4', a character '.' is + * allowed by char_map. */ + if (*p == '.') { + xdot = dot; + dot = p; + } + continue; + } + if (*p >= 'a' && *p <= 'z') { + *p -= 'a' - 'A'; + continue; + } + if (*p == '.') { + xdot = dot; + dot = p; + if (allow_multidot) + continue; + } + *p = '_'; + } + p = np->identifier; + weight = -1; + if (dot == NULL) { + int nammax; + + if (np->dir) + nammax = dnmax; + else + nammax = fnmax; + + if (l > nammax) { + p[nammax] = '\0'; + weight = nammax; + ext_off = nammax; + } else + ext_off = l; + } else { + *dot = '.'; + ext_off = (int)(dot - p); + + if (iso9660->opt.iso_level == 1) { + if (dot - p <= 8) { + if (strlen(dot) > 4) { + /* A length of a file extension + * must be less than 4 */ + dot[4] = '\0'; + weight = 0; + } + } else { + p[8] = dot[0]; + p[9] = dot[1]; + p[10] = dot[2]; + p[11] = dot[3]; + p[12] = '\0'; + weight = 8; + ext_off = 8; + } + } else if (np->dir) { + if (l > dnmax) { + p[dnmax] = '\0'; + weight = dnmax; + if (ext_off > dnmax) + ext_off = dnmax; + } + } else if (l > ffmax) { + int extlen = (int)strlen(dot); + int xdoff; + + if (xdot != NULL) + xdoff = (int)(xdot - p); + else + xdoff = 0; + + if (extlen > 1 && xdoff < fnmax-1) { + int off; + + if (extlen > ffmax) + extlen = ffmax; + off = ffmax - extlen; + if (off == 0) { + /* A dot('.') character + * doesn't place to the first + * byte of identifier. */ + off ++; + extlen --; + } + memmove(p+off, dot, extlen); + p[ffmax] = '\0'; + ext_off = off; + weight = off; +#ifdef COMPAT_MKISOFS + } else if (xdoff >= fnmax-1) { + /* Simulate a bug(?) of mkisofs. */ + p[fnmax-1] = '\0'; + ext_off = fnmax-1; + weight = fnmax-1; +#endif + } else { + p[fnmax] = '\0'; + ext_off = fnmax; + weight = fnmax; + } + } + } + /* Save an offset of a file name extension to sort files. */ + np->ext_off = ext_off; + np->ext_len = (int)strlen(&p[ext_off]); + np->id_len = l = ext_off + np->ext_len; + + /* Make an offset of the number which is used to be set + * hexadecimal number to avoid duplicate identifier. */ + if (iso9660->opt.iso_level == 1) { + if (ext_off >= 5) + noff = 5; + else + noff = ext_off; + } else { + if (l == ffmax) + noff = ext_off - 3; + else if (l == ffmax-1) + noff = ext_off - 2; + else if (l == ffmax-2) + noff = ext_off - 1; + else + noff = ext_off; + } + /* Register entry to the identifier resolver. */ + idr_register(idr, np, weight, noff); + } + + /* Resolve duplicate identifier. */ + idr_resolve(idr, idr_set_num); + + /* Add a period and a version number to identifiers. */ + for (np = isoent->children.first; np != NULL; np = np->chnext) { + if (!np->dir && np->rr_child == NULL) { + p = np->identifier + np->ext_off + np->ext_len; + if (np->ext_len == 0 && allow_period) { + *p++ = '.'; + np->ext_len = 1; + } + if (np->ext_len == 1 && !allow_period) { + *--p = '\0'; + np->ext_len = 0; + } + np->id_len = np->ext_off + np->ext_len; + if (allow_vernum) { + *p++ = ';'; + *p++ = '1'; + np->id_len += 2; + } + *p = '\0'; + } else + np->id_len = np->ext_off + np->ext_len; + np->mb_len = np->id_len; + } + return (ARCHIVE_OK); +} + +/* + * Generate Joliet Identifier. + */ +static int +isoent_gen_joliet_identifier(struct archive_write *a, struct isoent *isoent, + struct idr *idr) +{ + struct iso9660 *iso9660; + struct isoent *np; + unsigned char *p; + size_t l; + int r; + size_t ffmax, parent_len; + static const struct archive_rb_tree_ops rb_ops = { + isoent_cmp_node_joliet, isoent_cmp_key_joliet + }; + + if (isoent->children.cnt == 0) + return (0); + + iso9660 = a->format_data; + if (iso9660->opt.joliet == OPT_JOLIET_LONGNAME) + ffmax = 206; + else + ffmax = 128; + + r = idr_start(a, idr, isoent->children.cnt, (int)ffmax, 6, 2, &rb_ops); + if (r < 0) + return (r); + + parent_len = 1; + for (np = isoent; np->parent != np; np = np->parent) + parent_len += np->mb_len + 1; + + for (np = isoent->children.first; np != NULL; np = np->chnext) { + unsigned char *dot; + int ext_off, noff, weight; + size_t lt; + + if ((l = np->file->basename_utf16.length) > ffmax) + l = ffmax; + + p = malloc((l+1)*2); + if (p == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + memcpy(p, np->file->basename_utf16.s, l); + p[l] = 0; + p[l+1] = 0; + + np->identifier = (char *)p; + lt = l; + dot = p + l; + weight = 0; + while (lt > 0) { + if (!joliet_allowed_char(p[0], p[1])) + archive_be16enc(p, 0x005F); /* '_' */ + else if (p[0] == 0 && p[1] == 0x2E) /* '.' */ + dot = p; + p += 2; + lt -= 2; + } + ext_off = (int)(dot - (unsigned char *)np->identifier); + np->ext_off = ext_off; + np->ext_len = (int)l - ext_off; + np->id_len = (int)l; + + /* + * Get a length of MBS of a full-pathname. + */ + if (np->file->basename_utf16.length > ffmax) { + if (archive_strncpy_l(&iso9660->mbs, + (const char *)np->identifier, l, + iso9660->sconv_from_utf16be) != 0 && + errno == ENOMEM) { + archive_set_error(&a->archive, errno, + "No memory"); + return (ARCHIVE_FATAL); + } + np->mb_len = (int)iso9660->mbs.length; + if (np->mb_len != (int)np->file->basename.length) + weight = np->mb_len; + } else + np->mb_len = (int)np->file->basename.length; + + /* If a length of full-pathname is longer than 240 bytes, + * it violates Joliet extensions regulation. */ + if (parent_len > 240 + || np->mb_len > 240 + || parent_len + np->mb_len > 240) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "The regulation of Joliet extensions;" + " A length of a full-pathname of `%s' is " + "longer than 240 bytes, (p=%d, b=%d)", + archive_entry_pathname(np->file->entry), + (int)parent_len, (int)np->mb_len); + return (ARCHIVE_FATAL); + } + + /* Make an offset of the number which is used to be set + * hexadecimal number to avoid duplicate identifier. */ + if (l == ffmax) + noff = ext_off - 6; + else if (l == ffmax-2) + noff = ext_off - 4; + else if (l == ffmax-4) + noff = ext_off - 2; + else + noff = ext_off; + /* Register entry to the identifier resolver. */ + idr_register(idr, np, weight, noff); + } + + /* Resolve duplicate identifier with Joliet Volume. */ + idr_resolve(idr, idr_set_num_beutf16); + + return (ARCHIVE_OK); +} + +/* + * This comparing rule is according to ISO9660 Standard 9.3 + */ +static int +isoent_cmp_iso9660_identifier(const struct isoent *p1, const struct isoent *p2) +{ + const char *s1, *s2; + int cmp; + int l; + + s1 = p1->identifier; + s2 = p2->identifier; + + /* Compare File Name */ + l = p1->ext_off; + if (l > p2->ext_off) + l = p2->ext_off; + cmp = memcmp(s1, s2, l); + if (cmp != 0) + return (cmp); + if (p1->ext_off < p2->ext_off) { + s2 += l; + l = p2->ext_off - p1->ext_off; + while (l--) + if (0x20 != *s2++) + return (0x20 + - *(const unsigned char *)(s2 - 1)); + } else if (p1->ext_off > p2->ext_off) { + s1 += l; + l = p1->ext_off - p2->ext_off; + while (l--) + if (0x20 != *s1++) + return (*(const unsigned char *)(s1 - 1) + - 0x20); + } + /* Compare File Name Extension */ + if (p1->ext_len == 0 && p2->ext_len == 0) + return (0); + if (p1->ext_len == 1 && p2->ext_len == 1) + return (0); + if (p1->ext_len <= 1) + return (-1); + if (p2->ext_len <= 1) + return (1); + l = p1->ext_len; + if (l > p2->ext_len) + l = p2->ext_len; + s1 = p1->identifier + p1->ext_off; + s2 = p2->identifier + p2->ext_off; + if (l > 1) { + cmp = memcmp(s1, s2, l); + if (cmp != 0) + return (cmp); + } + if (p1->ext_len < p2->ext_len) { + s2 += l; + l = p2->ext_len - p1->ext_len; + while (l--) + if (0x20 != *s2++) + return (0x20 + - *(const unsigned char *)(s2 - 1)); + } else if (p1->ext_len > p2->ext_len) { + s1 += l; + l = p1->ext_len - p2->ext_len; + while (l--) + if (0x20 != *s1++) + return (*(const unsigned char *)(s1 - 1) + - 0x20); + } + /* Compare File Version Number */ + /* No operation. The File Version Number is always one. */ + + return (cmp); +} + +static int +isoent_cmp_node_iso9660(const struct archive_rb_node *n1, + const struct archive_rb_node *n2) +{ + const struct idrent *e1 = (const struct idrent *)n1; + const struct idrent *e2 = (const struct idrent *)n2; + + return (isoent_cmp_iso9660_identifier(e2->isoent, e1->isoent)); +} + +static int +isoent_cmp_key_iso9660(const struct archive_rb_node *node, const void *key) +{ + const struct isoent *isoent = (const struct isoent *)key; + const struct idrent *idrent = (const struct idrent *)node; + + return (isoent_cmp_iso9660_identifier(isoent, idrent->isoent)); +} + +static int +isoent_cmp_joliet_identifier(const struct isoent *p1, const struct isoent *p2) +{ + const unsigned char *s1, *s2; + int cmp; + int l; + + s1 = (const unsigned char *)p1->identifier; + s2 = (const unsigned char *)p2->identifier; + + /* Compare File Name */ + l = p1->ext_off; + if (l > p2->ext_off) + l = p2->ext_off; + cmp = memcmp(s1, s2, l); + if (cmp != 0) + return (cmp); + if (p1->ext_off < p2->ext_off) { + s2 += l; + l = p2->ext_off - p1->ext_off; + while (l--) + if (0 != *s2++) + return (- *(const unsigned char *)(s2 - 1)); + } else if (p1->ext_off > p2->ext_off) { + s1 += l; + l = p1->ext_off - p2->ext_off; + while (l--) + if (0 != *s1++) + return (*(const unsigned char *)(s1 - 1)); + } + /* Compare File Name Extension */ + if (p1->ext_len == 0 && p2->ext_len == 0) + return (0); + if (p1->ext_len == 2 && p2->ext_len == 2) + return (0); + if (p1->ext_len <= 2) + return (-1); + if (p2->ext_len <= 2) + return (1); + l = p1->ext_len; + if (l > p2->ext_len) + l = p2->ext_len; + s1 = (unsigned char *)(p1->identifier + p1->ext_off); + s2 = (unsigned char *)(p2->identifier + p2->ext_off); + if (l > 1) { + cmp = memcmp(s1, s2, l); + if (cmp != 0) + return (cmp); + } + if (p1->ext_len < p2->ext_len) { + s2 += l; + l = p2->ext_len - p1->ext_len; + while (l--) + if (0 != *s2++) + return (- *(const unsigned char *)(s2 - 1)); + } else if (p1->ext_len > p2->ext_len) { + s1 += l; + l = p1->ext_len - p2->ext_len; + while (l--) + if (0 != *s1++) + return (*(const unsigned char *)(s1 - 1)); + } + /* Compare File Version Number */ + /* No operation. The File Version Number is always one. */ + + return (cmp); +} + +static int +isoent_cmp_node_joliet(const struct archive_rb_node *n1, + const struct archive_rb_node *n2) +{ + const struct idrent *e1 = (const struct idrent *)n1; + const struct idrent *e2 = (const struct idrent *)n2; + + return (isoent_cmp_joliet_identifier(e2->isoent, e1->isoent)); +} + +static int +isoent_cmp_key_joliet(const struct archive_rb_node *node, const void *key) +{ + const struct isoent *isoent = (const struct isoent *)key; + const struct idrent *idrent = (const struct idrent *)node; + + return (isoent_cmp_joliet_identifier(isoent, idrent->isoent)); +} + +static int +isoent_make_sorted_files(struct archive_write *a, struct isoent *isoent, + struct idr *idr) +{ + struct archive_rb_node *rn; + struct isoent **children; + + children = malloc(isoent->children.cnt * sizeof(struct isoent *)); + if (children == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + isoent->children_sorted = children; + + ARCHIVE_RB_TREE_FOREACH(rn, &(idr->rbtree)) { + struct idrent *idrent = (struct idrent *)rn; + *children ++ = idrent->isoent; + } + return (ARCHIVE_OK); +} + +/* + * - Generate ISO9660 and Joliet identifiers from basenames. + * - Sort files by each directory. + */ +static int +isoent_traverse_tree(struct archive_write *a, struct vdd* vdd) +{ + struct iso9660 *iso9660 = a->format_data; + struct isoent *np; + struct idr idr; + int depth; + int r; + int (*genid)(struct archive_write *, struct isoent *, struct idr *); + + idr_init(iso9660, vdd, &idr); + np = vdd->rootent; + depth = 0; + if (vdd->vdd_type == VDD_JOLIET) + genid = isoent_gen_joliet_identifier; + else + genid = isoent_gen_iso9660_identifier; + do { + if (np->virtual && + !archive_entry_mtime_is_set(np->file->entry)) { + /* Set properly times to virtual directory */ + archive_entry_set_mtime(np->file->entry, + iso9660->birth_time, 0); + archive_entry_set_atime(np->file->entry, + iso9660->birth_time, 0); + archive_entry_set_ctime(np->file->entry, + iso9660->birth_time, 0); + } + if (np->children.first != NULL) { + if (vdd->vdd_type != VDD_JOLIET && + !iso9660->opt.rr && depth + 1 >= vdd->max_depth) { + if (np->children.cnt > 0) + iso9660->directories_too_deep = np; + } else { + /* Generate Identifier */ + r = genid(a, np, &idr); + if (r < 0) + goto exit_traverse_tree; + r = isoent_make_sorted_files(a, np, &idr); + if (r < 0) + goto exit_traverse_tree; + + if (np->subdirs.first != NULL && + depth + 1 < vdd->max_depth) { + /* Enter to sub directories. */ + np = np->subdirs.first; + depth++; + continue; + } + } + } + while (np != np->parent) { + if (np->drnext == NULL) { + /* Return to the parent directory. */ + np = np->parent; + depth--; + } else { + np = np->drnext; + break; + } + } + } while (np != np->parent); + + r = ARCHIVE_OK; +exit_traverse_tree: + idr_cleanup(&idr); + + return (r); +} + +/* + * Collect directory entries into path_table by a directory depth. + */ +static int +isoent_collect_dirs(struct vdd *vdd, struct isoent *rootent, int depth) +{ + struct isoent *np; + + if (rootent == NULL) + rootent = vdd->rootent; + np = rootent; + do { + /* Register current directory to pathtable. */ + path_table_add_entry(&(vdd->pathtbl[depth]), np); + + if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) { + /* Enter to sub directories. */ + np = np->subdirs.first; + depth++; + continue; + } + while (np != rootent) { + if (np->drnext == NULL) { + /* Return to the parent directory. */ + np = np->parent; + depth--; + } else { + np = np->drnext; + break; + } + } + } while (np != rootent); + + return (ARCHIVE_OK); +} + +/* + * The entry whose number of levels in a directory hierarchy is + * large than eight relocate to rr_move directory. + */ +static int +isoent_rr_move_dir(struct archive_write *a, struct isoent **rr_moved, + struct isoent *curent, struct isoent **newent) +{ + struct iso9660 *iso9660 = a->format_data; + struct isoent *rrmoved, *mvent, *np; + + if ((rrmoved = *rr_moved) == NULL) { + struct isoent *rootent = iso9660->primary.rootent; + /* There isn't rr_move entry. + * Create rr_move entry and insert it into the root entry. + */ + rrmoved = isoent_create_virtual_dir(a, iso9660, "rr_moved"); + if (rrmoved == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + /* Add "rr_moved" entry to the root entry. */ + isoent_add_child_head(rootent, rrmoved); + archive_entry_set_nlink(rootent->file->entry, + archive_entry_nlink(rootent->file->entry) + 1); + /* Register "rr_moved" entry to second level pathtable. */ + path_table_add_entry(&(iso9660->primary.pathtbl[1]), rrmoved); + /* Save rr_moved. */ + *rr_moved = rrmoved; + } + /* + * Make a clone of curent which is going to be relocated + * to rr_moved. + */ + mvent = isoent_clone(curent); + if (mvent == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + /* linking.. and use for creating "CL", "PL" and "RE" */ + mvent->rr_parent = curent->parent; + curent->rr_child = mvent; + /* + * Move subdirectories from the curent to mvent + */ + if (curent->children.first != NULL) { + *mvent->children.last = curent->children.first; + mvent->children.last = curent->children.last; + } + for (np = mvent->children.first; np != NULL; np = np->chnext) + np->parent = mvent; + mvent->children.cnt = curent->children.cnt; + curent->children.cnt = 0; + curent->children.first = NULL; + curent->children.last = &curent->children.first; + + if (curent->subdirs.first != NULL) { + *mvent->subdirs.last = curent->subdirs.first; + mvent->subdirs.last = curent->subdirs.last; + } + mvent->subdirs.cnt = curent->subdirs.cnt; + curent->subdirs.cnt = 0; + curent->subdirs.first = NULL; + curent->subdirs.last = &curent->subdirs.first; + + /* + * The mvent becomes a child of the rr_moved entry. + */ + isoent_add_child_tail(rrmoved, mvent); + archive_entry_set_nlink(rrmoved->file->entry, + archive_entry_nlink(rrmoved->file->entry) + 1); + /* + * This entry which relocated to the rr_moved directory + * has to set the flag as a file. + * See also RRIP 4.1.5.1 Description of the "CL" System Use Entry. + */ + curent->dir = 0; + + *newent = mvent; + + return (ARCHIVE_OK); +} + +static int +isoent_rr_move(struct archive_write *a) +{ + struct iso9660 *iso9660 = a->format_data; + struct path_table *pt; + struct isoent *rootent, *rr_moved; + struct isoent *np, *last; + int r; + + pt = &(iso9660->primary.pathtbl[MAX_DEPTH-1]); + /* There aren't level 8 directories reaching a deeper level. */ + if (pt->cnt == 0) + return (ARCHIVE_OK); + + rootent = iso9660->primary.rootent; + /* If "rr_moved" directory is already existing, + * we have to use it. */ + rr_moved = isoent_find_child(rootent, "rr_moved"); + if (rr_moved != NULL && + rr_moved != rootent->children.first) { + /* + * It's necessary that rr_move is the first entry + * of the root. + */ + /* Remove "rr_moved" entry from children chain. */ + isoent_remove_child(rootent, rr_moved); + + /* Add "rr_moved" entry into the head of children chain. */ + isoent_add_child_head(rootent, rr_moved); + } + + /* + * Check level 8 path_table. + * If find out sub directory entries, that entries move to rr_move. + */ + np = pt->first; + while (np != NULL) { + last = path_table_last_entry(pt); + for (; np != NULL; np = np->ptnext) { + struct isoent *mvent; + struct isoent *newent; + + if (!np->dir) + continue; + for (mvent = np->subdirs.first; + mvent != NULL; mvent = mvent->drnext) { + r = isoent_rr_move_dir(a, &rr_moved, + mvent, &newent); + if (r < 0) + return (r); + isoent_collect_dirs(&(iso9660->primary), + newent, 2); + } + } + /* If new entries are added to level 8 path_talbe, + * its sub directory entries move to rr_move too. + */ + np = last->ptnext; + } + + return (ARCHIVE_OK); +} + +/* + * This comparing rule is according to ISO9660 Standard 6.9.1 + */ +static int +_compare_path_table(const void *v1, const void *v2) +{ + const struct isoent *p1, *p2; + const char *s1, *s2; + int cmp, l; + + p1 = *((const struct isoent **)(uintptr_t)v1); + p2 = *((const struct isoent **)(uintptr_t)v2); + + /* Compare parent directory number */ + cmp = p1->parent->dir_number - p2->parent->dir_number; + if (cmp != 0) + return (cmp); + + /* Compare identifier */ + s1 = p1->identifier; + s2 = p2->identifier; + l = p1->ext_off; + if (l > p2->ext_off) + l = p2->ext_off; + cmp = strncmp(s1, s2, l); + if (cmp != 0) + return (cmp); + if (p1->ext_off < p2->ext_off) { + s2 += l; + l = p2->ext_off - p1->ext_off; + while (l--) + if (0x20 != *s2++) + return (0x20 + - *(const unsigned char *)(s2 - 1)); + } else if (p1->ext_off > p2->ext_off) { + s1 += l; + l = p1->ext_off - p2->ext_off; + while (l--) + if (0x20 != *s1++) + return (*(const unsigned char *)(s1 - 1) + - 0x20); + } + return (0); +} + +static int +_compare_path_table_joliet(const void *v1, const void *v2) +{ + const struct isoent *p1, *p2; + const unsigned char *s1, *s2; + int cmp, l; + + p1 = *((const struct isoent **)(uintptr_t)v1); + p2 = *((const struct isoent **)(uintptr_t)v2); + + /* Compare parent directory number */ + cmp = p1->parent->dir_number - p2->parent->dir_number; + if (cmp != 0) + return (cmp); + + /* Compare identifier */ + s1 = (const unsigned char *)p1->identifier; + s2 = (const unsigned char *)p2->identifier; + l = p1->ext_off; + if (l > p2->ext_off) + l = p2->ext_off; + cmp = memcmp(s1, s2, l); + if (cmp != 0) + return (cmp); + if (p1->ext_off < p2->ext_off) { + s2 += l; + l = p2->ext_off - p1->ext_off; + while (l--) + if (0 != *s2++) + return (- *(const unsigned char *)(s2 - 1)); + } else if (p1->ext_off > p2->ext_off) { + s1 += l; + l = p1->ext_off - p2->ext_off; + while (l--) + if (0 != *s1++) + return (*(const unsigned char *)(s1 - 1)); + } + return (0); +} + +static inline void +path_table_add_entry(struct path_table *pathtbl, struct isoent *ent) +{ + ent->ptnext = NULL; + *pathtbl->last = ent; + pathtbl->last = &(ent->ptnext); + pathtbl->cnt ++; +} + +static inline struct isoent * +path_table_last_entry(struct path_table *pathtbl) +{ + if (pathtbl->first == NULL) + return (NULL); + return (((struct isoent *)(void *) + ((char *)(pathtbl->last) - offsetof(struct isoent, ptnext)))); +} + +/* + * Sort directory entries in path_table + * and assign directory number to each entries. + */ +static int +isoent_make_path_table_2(struct archive_write *a, struct vdd *vdd, + int depth, int *dir_number) +{ + struct isoent *np; + struct isoent **enttbl; + struct path_table *pt; + int i; + + pt = &vdd->pathtbl[depth]; + if (pt->cnt == 0) { + pt->sorted = NULL; + return (ARCHIVE_OK); + } + enttbl = malloc(pt->cnt * sizeof(struct isoent *)); + if (enttbl == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + pt->sorted = enttbl; + for (np = pt->first; np != NULL; np = np->ptnext) + *enttbl ++ = np; + enttbl = pt->sorted; + + switch (vdd->vdd_type) { + case VDD_PRIMARY: + case VDD_ENHANCED: +#ifdef __COMPAR_FN_T + qsort(enttbl, pt->cnt, sizeof(struct isoent *), + (__compar_fn_t)_compare_path_table); +#else + qsort(enttbl, pt->cnt, sizeof(struct isoent *), + _compare_path_table); +#endif + break; + case VDD_JOLIET: +#ifdef __COMPAR_FN_T + qsort(enttbl, pt->cnt, sizeof(struct isoent *), + (__compar_fn_t)_compare_path_table_joliet); +#else + qsort(enttbl, pt->cnt, sizeof(struct isoent *), + _compare_path_table_joliet); +#endif + break; + } + for (i = 0; i < pt->cnt; i++) + enttbl[i]->dir_number = (*dir_number)++; + + return (ARCHIVE_OK); +} + +static int +isoent_alloc_path_table(struct archive_write *a, struct vdd *vdd, + int max_depth) +{ + int i; + + vdd->max_depth = max_depth; + vdd->pathtbl = malloc(sizeof(*vdd->pathtbl) * vdd->max_depth); + if (vdd->pathtbl == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + for (i = 0; i < vdd->max_depth; i++) { + vdd->pathtbl[i].first = NULL; + vdd->pathtbl[i].last = &(vdd->pathtbl[i].first); + vdd->pathtbl[i].sorted = NULL; + vdd->pathtbl[i].cnt = 0; + } + return (ARCHIVE_OK); +} + +/* + * Make Path Tables + */ +static int +isoent_make_path_table(struct archive_write *a) +{ + struct iso9660 *iso9660 = a->format_data; + int depth, r; + int dir_number; + + /* + * Init Path Table. + */ + if (iso9660->dircnt_max >= MAX_DEPTH && + (!iso9660->opt.limit_depth || iso9660->opt.iso_level == 4)) + r = isoent_alloc_path_table(a, &(iso9660->primary), + iso9660->dircnt_max + 1); + else + /* The number of levels in the hierarchy cannot exceed + * eight. */ + r = isoent_alloc_path_table(a, &(iso9660->primary), + MAX_DEPTH); + if (r < 0) + return (r); + if (iso9660->opt.joliet) { + r = isoent_alloc_path_table(a, &(iso9660->joliet), + iso9660->dircnt_max + 1); + if (r < 0) + return (r); + } + + /* Step 0. + * - Collect directories for primary and joliet. + */ + isoent_collect_dirs(&(iso9660->primary), NULL, 0); + if (iso9660->opt.joliet) + isoent_collect_dirs(&(iso9660->joliet), NULL, 0); + /* + * Rockridge; move deeper depth directories to rr_moved. + */ + if (iso9660->opt.rr) { + r = isoent_rr_move(a); + if (r < 0) + return (r); + } + + /* Update nlink. */ + isofile_connect_hardlink_files(iso9660); + + /* Step 1. + * - Renew a value of the depth of that directories. + * - Resolve hardlinks. + * - Convert pathnames to ISO9660 name or UCS2(joliet). + * - Sort files by each directory. + */ + r = isoent_traverse_tree(a, &(iso9660->primary)); + if (r < 0) + return (r); + if (iso9660->opt.joliet) { + r = isoent_traverse_tree(a, &(iso9660->joliet)); + if (r < 0) + return (r); + } + + /* Step 2. + * - Sort directories. + * - Assign all directory number. + */ + dir_number = 1; + for (depth = 0; depth < iso9660->primary.max_depth; depth++) { + r = isoent_make_path_table_2(a, &(iso9660->primary), + depth, &dir_number); + if (r < 0) + return (r); + } + if (iso9660->opt.joliet) { + dir_number = 1; + for (depth = 0; depth < iso9660->joliet.max_depth; depth++) { + r = isoent_make_path_table_2(a, &(iso9660->joliet), + depth, &dir_number); + if (r < 0) + return (r); + } + } + if (iso9660->opt.limit_dirs && dir_number > 0xffff) { + /* + * Maximum number of directories is 65535(0xffff) + * doe to size(16bit) of Parent Directory Number of + * the Path Table. + * See also ISO9660 Standard 9.4. + */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Too many directories(%d) over 65535.", dir_number); + return (ARCHIVE_FATAL); + } + + /* Get the size of the Path Table. */ + calculate_path_table_size(&(iso9660->primary)); + if (iso9660->opt.joliet) + calculate_path_table_size(&(iso9660->joliet)); + + return (ARCHIVE_OK); +} + +static int +isoent_find_out_boot_file(struct archive_write *a, struct isoent *rootent) +{ + struct iso9660 *iso9660 = a->format_data; + + /* Find a isoent of the boot file. */ + iso9660->el_torito.boot = isoent_find_entry(rootent, + iso9660->el_torito.boot_filename.s); + if (iso9660->el_torito.boot == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't find the boot image file ``%s''", + iso9660->el_torito.boot_filename.s); + return (ARCHIVE_FATAL); + } + iso9660->el_torito.boot->file->boot = BOOT_IMAGE; + return (ARCHIVE_OK); +} + +static int +isoent_create_boot_catalog(struct archive_write *a, struct isoent *rootent) +{ + struct iso9660 *iso9660 = a->format_data; + struct isofile *file; + struct isoent *isoent; + struct archive_entry *entry; + + (void)rootent; /* UNUSED */ + /* + * Create the entry which is the "boot.catalog" file. + */ + file = isofile_new(a, NULL); + if (file == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + archive_entry_set_pathname(file->entry, + iso9660->el_torito.catalog_filename.s); + archive_entry_set_size(file->entry, LOGICAL_BLOCK_SIZE); + archive_entry_set_mtime(file->entry, iso9660->birth_time, 0); + archive_entry_set_atime(file->entry, iso9660->birth_time, 0); + archive_entry_set_ctime(file->entry, iso9660->birth_time, 0); + archive_entry_set_uid(file->entry, getuid()); + archive_entry_set_gid(file->entry, getgid()); + archive_entry_set_mode(file->entry, AE_IFREG | 0444); + archive_entry_set_nlink(file->entry, 1); + + if (isofile_gen_utility_names(a, file) < ARCHIVE_WARN) { + isofile_free(file); + return (ARCHIVE_FATAL); + } + file->boot = BOOT_CATALOG; + file->content.size = LOGICAL_BLOCK_SIZE; + isofile_add_entry(iso9660, file); + + isoent = isoent_new(file); + if (isoent == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + isoent->virtual = 1; + + /* Add the "boot.catalog" entry into tree */ + if (isoent_tree(a, &isoent) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + iso9660->el_torito.catalog = isoent; + /* + * Get a boot media type. + */ + switch (iso9660->opt.boot_type) { + default: + case OPT_BOOT_TYPE_AUTO: + /* Try detecting a media type of the boot image. */ + entry = iso9660->el_torito.boot->file->entry; + if (archive_entry_size(entry) == FD_1_2M_SIZE) + iso9660->el_torito.media_type = + BOOT_MEDIA_1_2M_DISKETTE; + else if (archive_entry_size(entry) == FD_1_44M_SIZE) + iso9660->el_torito.media_type = + BOOT_MEDIA_1_44M_DISKETTE; + else if (archive_entry_size(entry) == FD_2_88M_SIZE) + iso9660->el_torito.media_type = + BOOT_MEDIA_2_88M_DISKETTE; + else + /* We cannot decide whether the boot image is + * hard-disk. */ + iso9660->el_torito.media_type = + BOOT_MEDIA_NO_EMULATION; + break; + case OPT_BOOT_TYPE_NO_EMU: + iso9660->el_torito.media_type = BOOT_MEDIA_NO_EMULATION; + break; + case OPT_BOOT_TYPE_HARD_DISK: + iso9660->el_torito.media_type = BOOT_MEDIA_HARD_DISK; + break; + case OPT_BOOT_TYPE_FD: + entry = iso9660->el_torito.boot->file->entry; + if (archive_entry_size(entry) <= FD_1_2M_SIZE) + iso9660->el_torito.media_type = + BOOT_MEDIA_1_2M_DISKETTE; + else if (archive_entry_size(entry) <= FD_1_44M_SIZE) + iso9660->el_torito.media_type = + BOOT_MEDIA_1_44M_DISKETTE; + else if (archive_entry_size(entry) <= FD_2_88M_SIZE) + iso9660->el_torito.media_type = + BOOT_MEDIA_2_88M_DISKETTE; + else { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Boot image file(``%s'') size is too big " + "for fd type.", + iso9660->el_torito.boot_filename.s); + return (ARCHIVE_FATAL); + } + break; + } + + /* + * Get a system type. + * TODO: `El Torito' specification says "A copy of byte 5 from the + * Partition Table found in the boot image". + */ + iso9660->el_torito.system_type = 0; + + /* + * Get an ID. + */ + if (iso9660->opt.publisher) + archive_string_copy(&(iso9660->el_torito.id), + &(iso9660->publisher_identifier)); + + + return (ARCHIVE_OK); +} + +/* + * If a media type is floppy, return its image size. + * otherwise return 0. + */ +static size_t +fd_boot_image_size(int media_type) +{ + switch (media_type) { + case BOOT_MEDIA_1_2M_DISKETTE: + return (FD_1_2M_SIZE); + case BOOT_MEDIA_1_44M_DISKETTE: + return (FD_1_44M_SIZE); + case BOOT_MEDIA_2_88M_DISKETTE: + return (FD_2_88M_SIZE); + default: + return (0); + } +} + +/* + * Make a boot catalog image data. + */ +static int +make_boot_catalog(struct archive_write *a) +{ + struct iso9660 *iso9660 = a->format_data; + unsigned char *block; + unsigned char *p; + uint16_t sum, *wp; + + block = wb_buffptr(a); + memset(block, 0, LOGICAL_BLOCK_SIZE); + p = block; + /* + * Validation Entry + */ + /* Header ID */ + p[0] = 1; + /* Platform ID */ + p[1] = iso9660->el_torito.platform_id; + /* Reserved */ + p[2] = p[3] = 0; + /* ID */ + if (archive_strlen(&(iso9660->el_torito.id)) > 0) + strncpy((char *)p+4, iso9660->el_torito.id.s, 23); + p[27] = 0; + /* Checksum */ + p[28] = p[29] = 0; + /* Key */ + p[30] = 0x55; + p[31] = 0xAA; + + sum = 0; + wp = (uint16_t *)block; + while (wp < (uint16_t *)&block[32]) + sum += archive_le16dec(wp++); + set_num_721(&block[28], (~sum) + 1); + + /* + * Initial/Default Entry + */ + p = &block[32]; + /* Boot Indicator */ + p[0] = 0x88; + /* Boot media type */ + p[1] = iso9660->el_torito.media_type; + /* Load Segment */ + if (iso9660->el_torito.media_type == BOOT_MEDIA_NO_EMULATION) + set_num_721(&p[2], iso9660->el_torito.boot_load_seg); + else + set_num_721(&p[2], 0); + /* System Type */ + p[4] = iso9660->el_torito.system_type; + /* Unused */ + p[5] = 0; + /* Sector Count */ + if (iso9660->el_torito.media_type == BOOT_MEDIA_NO_EMULATION) + set_num_721(&p[6], iso9660->el_torito.boot_load_size); + else + set_num_721(&p[6], 1); + /* Load RBA */ + set_num_731(&p[8], + iso9660->el_torito.boot->file->content.location); + /* Unused */ + memset(&p[12], 0, 20); + + return (wb_consume(a, LOGICAL_BLOCK_SIZE)); +} + +static int +setup_boot_information(struct archive_write *a) +{ + struct iso9660 *iso9660 = a->format_data; + struct isoent *np; + int64_t size; + uint32_t sum; + unsigned char buff[4096]; + + np = iso9660->el_torito.boot; + lseek(iso9660->temp_fd, + np->file->content.offset_of_temp + 64, SEEK_SET); + size = archive_entry_size(np->file->entry) - 64; + if (size <= 0) { + archive_set_error(&a->archive, errno, + "Boot file(%jd) is too small", (intmax_t)size + 64); + return (ARCHIVE_FATAL); + } + sum = 0; + while (size > 0) { + size_t rsize; + ssize_t i, rs; + + if (size > (int64_t)sizeof(buff)) + rsize = sizeof(buff); + else + rsize = (size_t)size; + + rs = read(iso9660->temp_fd, buff, rsize); + if (rs <= 0) { + archive_set_error(&a->archive, errno, + "Can't read temporary file(%jd)", + (intmax_t)rs); + return (ARCHIVE_FATAL); + } + for (i = 0; i < rs; i += 4) + sum += archive_le32dec(buff + i); + size -= rs; + } + /* Set the location of Primary Volume Descriptor. */ + set_num_731(buff, SYSTEM_AREA_BLOCK); + /* Set the location of the boot file. */ + set_num_731(buff+4, np->file->content.location); + /* Set the size of the boot file. */ + size = fd_boot_image_size(iso9660->el_torito.media_type); + if (size == 0) + size = archive_entry_size(np->file->entry); + set_num_731(buff+8, (uint32_t)size); + /* Set the sum of the boot file. */ + set_num_731(buff+12, sum); + /* Clear reserved bytes. */ + memset(buff+16, 0, 40); + + /* Overwrite the boot file. */ + lseek(iso9660->temp_fd, + np->file->content.offset_of_temp + 8, SEEK_SET); + return (write_to_temp(a, buff, 56)); +} + +#ifdef HAVE_ZLIB_H + +static int +zisofs_init_zstream(struct archive_write *a) +{ + struct iso9660 *iso9660 = a->format_data; + int r; + + iso9660->zisofs.stream.next_in = NULL; + iso9660->zisofs.stream.avail_in = 0; + iso9660->zisofs.stream.total_in = 0; + iso9660->zisofs.stream.total_out = 0; + if (iso9660->zisofs.stream_valid) + r = deflateReset(&(iso9660->zisofs.stream)); + else { + r = deflateInit(&(iso9660->zisofs.stream), + iso9660->zisofs.compression_level); + iso9660->zisofs.stream_valid = 1; + } + switch (r) { + case Z_OK: + break; + default: + case Z_STREAM_ERROR: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Internal error initializing " + "compression library: invalid setup parameter"); + return (ARCHIVE_FATAL); + case Z_MEM_ERROR: + archive_set_error(&a->archive, ENOMEM, + "Internal error initializing " + "compression library"); + return (ARCHIVE_FATAL); + case Z_VERSION_ERROR: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Internal error initializing " + "compression library: invalid library version"); + return (ARCHIVE_FATAL); + } + return (ARCHIVE_OK); +} + +#endif /* HAVE_ZLIB_H */ + +static int +zisofs_init(struct archive_write *a, struct isofile *file) +{ + struct iso9660 *iso9660 = a->format_data; +#ifdef HAVE_ZLIB_H + uint64_t tsize; + size_t _ceil, bpsize; + int r; +#endif + + iso9660->zisofs.detect_magic = 0; + iso9660->zisofs.making = 0; + + if (!iso9660->opt.rr || !iso9660->opt.zisofs) + return (ARCHIVE_OK); + + if (archive_entry_size(file->entry) >= 24 && + archive_entry_size(file->entry) < MULTI_EXTENT_SIZE) { + /* Acceptable file size for zisofs. */ + iso9660->zisofs.detect_magic = 1; + iso9660->zisofs.magic_cnt = 0; + } + if (!iso9660->zisofs.detect_magic) + return (ARCHIVE_OK); + +#ifdef HAVE_ZLIB_H + /* The number of Logical Blocks which uncompressed data + * will use in iso-image file is the same as the number of + * Logical Blocks which zisofs(compressed) data will use + * in ISO-image file. It won't reduce iso-image file size. */ + if (archive_entry_size(file->entry) <= LOGICAL_BLOCK_SIZE) + return (ARCHIVE_OK); + + /* Initialize compression library */ + r = zisofs_init_zstream(a); + if (r != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Mark file->zisofs to create RRIP 'ZF' Use Entry. */ + file->zisofs.header_size = ZF_HEADER_SIZE >> 2; + file->zisofs.log2_bs = ZF_LOG2_BS; + file->zisofs.uncompressed_size = + (uint32_t)archive_entry_size(file->entry); + + /* Calculate a size of Block Pointers of zisofs. */ + _ceil = (file->zisofs.uncompressed_size + ZF_BLOCK_SIZE -1) + >> file->zisofs.log2_bs; + iso9660->zisofs.block_pointers_cnt = (int)_ceil + 1; + iso9660->zisofs.block_pointers_idx = 0; + + /* Ensure a buffer size used for Block Pointers */ + bpsize = iso9660->zisofs.block_pointers_cnt * + sizeof(iso9660->zisofs.block_pointers[0]); + if (iso9660->zisofs.block_pointers_allocated < bpsize) { + free(iso9660->zisofs.block_pointers); + iso9660->zisofs.block_pointers = malloc(bpsize); + if (iso9660->zisofs.block_pointers == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate data"); + return (ARCHIVE_FATAL); + } + iso9660->zisofs.block_pointers_allocated = bpsize; + } + + /* + * Skip zisofs header and Block Pointers, which we will write + * after all compressed data of a file written to the temporary + * file. + */ + tsize = ZF_HEADER_SIZE + bpsize; + if (write_null(a, (size_t)tsize) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* + * Initialize some variables to make zisofs. + */ + archive_le32enc(&(iso9660->zisofs.block_pointers[0]), + (uint32_t)tsize); + iso9660->zisofs.remaining = file->zisofs.uncompressed_size; + iso9660->zisofs.making = 1; + iso9660->zisofs.allzero = 1; + iso9660->zisofs.block_offset = tsize; + iso9660->zisofs.total_size = tsize; + iso9660->cur_file->cur_content->size = tsize; +#endif + + return (ARCHIVE_OK); +} + +static void +zisofs_detect_magic(struct archive_write *a, const void *buff, size_t s) +{ + struct iso9660 *iso9660 = a->format_data; + struct isofile *file = iso9660->cur_file; + const unsigned char *p, *endp; + const unsigned char *magic_buff; + uint32_t uncompressed_size; + unsigned char header_size; + unsigned char log2_bs; + size_t _ceil, doff; + uint32_t bst, bed; + int magic_max; + int64_t entry_size; + + entry_size = archive_entry_size(file->entry); + if ((int64_t)sizeof(iso9660->zisofs.magic_buffer) > entry_size) + magic_max = (int)entry_size; + else + magic_max = sizeof(iso9660->zisofs.magic_buffer); + + if (iso9660->zisofs.magic_cnt == 0 && s >= (size_t)magic_max) + /* It's unnecessary we copy buffer. */ + magic_buff = buff; + else { + if (iso9660->zisofs.magic_cnt < magic_max) { + size_t l; + + l = sizeof(iso9660->zisofs.magic_buffer) + - iso9660->zisofs.magic_cnt; + if (l > s) + l = s; + memcpy(iso9660->zisofs.magic_buffer + + iso9660->zisofs.magic_cnt, buff, l); + iso9660->zisofs.magic_cnt += (int)l; + if (iso9660->zisofs.magic_cnt < magic_max) + return; + } + magic_buff = iso9660->zisofs.magic_buffer; + } + iso9660->zisofs.detect_magic = 0; + p = magic_buff; + + /* Check the magic code of zisofs. */ + if (memcmp(p, zisofs_magic, sizeof(zisofs_magic)) != 0) + /* This is not zisofs file which made by mkzftree. */ + return; + p += sizeof(zisofs_magic); + + /* Read a zisofs header. */ + uncompressed_size = archive_le32dec(p); + header_size = p[4]; + log2_bs = p[5]; + if (uncompressed_size < 24 || header_size != 4 || + log2_bs > 30 || log2_bs < 7) + return;/* Invalid or not supported header. */ + + /* Calculate a size of Block Pointers of zisofs. */ + _ceil = (uncompressed_size + + (ARCHIVE_LITERAL_LL(1) << log2_bs) -1) >> log2_bs; + doff = (_ceil + 1) * 4 + 16; + if (entry_size < (int64_t)doff) + return;/* Invalid data. */ + + /* Check every Block Pointer has valid value. */ + p = magic_buff + 16; + endp = magic_buff + magic_max; + while (_ceil && p + 8 <= endp) { + bst = archive_le32dec(p); + if (bst != doff) + return;/* Invalid data. */ + p += 4; + bed = archive_le32dec(p); + if (bed < bst || bed > entry_size) + return;/* Invalid data. */ + doff += bed - bst; + _ceil--; + } + + file->zisofs.uncompressed_size = uncompressed_size; + file->zisofs.header_size = header_size; + file->zisofs.log2_bs = log2_bs; + + /* Disable making a zisofs image. */ + iso9660->zisofs.making = 0; +} + +#ifdef HAVE_ZLIB_H + +/* + * Compress data and write it to a temporary file. + */ +static int +zisofs_write_to_temp(struct archive_write *a, const void *buff, size_t s) +{ + struct iso9660 *iso9660 = a->format_data; + struct isofile *file = iso9660->cur_file; + const unsigned char *b; + z_stream *zstrm; + size_t avail, csize; + int flush, r; + + zstrm = &(iso9660->zisofs.stream); + zstrm->next_out = wb_buffptr(a); + zstrm->avail_out = (uInt)wb_remaining(a); + b = (const unsigned char *)buff; + do { + avail = ZF_BLOCK_SIZE - zstrm->total_in; + if (s < avail) { + avail = s; + flush = Z_NO_FLUSH; + } else + flush = Z_FINISH; + iso9660->zisofs.remaining -= avail; + if (iso9660->zisofs.remaining <= 0) + flush = Z_FINISH; + + zstrm->next_in = (Bytef *)(uintptr_t)(const void *)b; + zstrm->avail_in = (uInt)avail; + + /* + * Check if current data block are all zero. + */ + if (iso9660->zisofs.allzero) { + const unsigned char *nonzero = b; + const unsigned char *nonzeroend = b + avail; + + while (nonzero < nonzeroend) + if (*nonzero++) { + iso9660->zisofs.allzero = 0; + break; + } + } + b += avail; + s -= avail; + + /* + * If current data block are all zero, we do not use + * compressed data. + */ + if (flush == Z_FINISH && iso9660->zisofs.allzero && + avail + zstrm->total_in == ZF_BLOCK_SIZE) { + if (iso9660->zisofs.block_offset != + file->cur_content->size) { + int64_t diff; + + r = wb_set_offset(a, + file->cur_content->offset_of_temp + + iso9660->zisofs.block_offset); + if (r != ARCHIVE_OK) + return (r); + diff = file->cur_content->size - + iso9660->zisofs.block_offset; + file->cur_content->size -= diff; + iso9660->zisofs.total_size -= diff; + } + zstrm->avail_in = 0; + } + + /* + * Compress file data. + */ + while (zstrm->avail_in > 0) { + csize = zstrm->total_out; + r = deflate(zstrm, flush); + switch (r) { + case Z_OK: + case Z_STREAM_END: + csize = zstrm->total_out - csize; + if (wb_consume(a, csize) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + iso9660->zisofs.total_size += csize; + iso9660->cur_file->cur_content->size += csize; + zstrm->next_out = wb_buffptr(a); + zstrm->avail_out = (uInt)wb_remaining(a); + break; + default: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Compression failed:" + " deflate() call returned status %d", + r); + return (ARCHIVE_FATAL); + } + } + + if (flush == Z_FINISH) { + /* + * Save the information of one zisofs block. + */ + iso9660->zisofs.block_pointers_idx ++; + archive_le32enc(&(iso9660->zisofs.block_pointers[ + iso9660->zisofs.block_pointers_idx]), + (uint32_t)iso9660->zisofs.total_size); + r = zisofs_init_zstream(a); + if (r != ARCHIVE_OK) + return (ARCHIVE_FATAL); + iso9660->zisofs.allzero = 1; + iso9660->zisofs.block_offset = file->cur_content->size; + } + } while (s); + + return (ARCHIVE_OK); +} + +static int +zisofs_finish_entry(struct archive_write *a) +{ + struct iso9660 *iso9660 = a->format_data; + struct isofile *file = iso9660->cur_file; + unsigned char buff[16]; + size_t s; + int64_t tail; + + /* Direct temp file stream to zisofs temp file stream. */ + archive_entry_set_size(file->entry, iso9660->zisofs.total_size); + + /* + * Save a file pointer which points the end of current zisofs data. + */ + tail = wb_offset(a); + + /* + * Make a header. + * + * +-----------------+----------------+-----------------+ + * | Header 16 bytes | Block Pointers | Compressed data | + * +-----------------+----------------+-----------------+ + * 0 16 +X + * Block Pointers : + * 4 * (((Uncompressed file size + block_size -1) / block_size) + 1) + * + * Write zisofs header. + * Magic number + * +----+----+----+----+----+----+----+----+ + * | 37 | E4 | 53 | 96 | C9 | DB | D6 | 07 | + * +----+----+----+----+----+----+----+----+ + * 0 1 2 3 4 5 6 7 8 + * + * +------------------------+------------------+ + * | Uncompressed file size | header_size >> 2 | + * +------------------------+------------------+ + * 8 12 13 + * + * +-----------------+----------------+ + * | log2 block_size | Reserved(0000) | + * +-----------------+----------------+ + * 13 14 16 + */ + memcpy(buff, zisofs_magic, 8); + set_num_731(buff+8, file->zisofs.uncompressed_size); + buff[12] = file->zisofs.header_size; + buff[13] = file->zisofs.log2_bs; + buff[14] = buff[15] = 0;/* Reserved */ + + /* Move to the right position to write the header. */ + wb_set_offset(a, file->content.offset_of_temp); + + /* Write the header. */ + if (wb_write_to_temp(a, buff, 16) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* + * Write zisofs Block Pointers. + */ + s = iso9660->zisofs.block_pointers_cnt * + sizeof(iso9660->zisofs.block_pointers[0]); + if (wb_write_to_temp(a, iso9660->zisofs.block_pointers, s) + != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Set a file pointer back to the end of the temporary file. */ + wb_set_offset(a, tail); + + return (ARCHIVE_OK); +} + +static int +zisofs_free(struct archive_write *a) +{ + struct iso9660 *iso9660 = a->format_data; + int ret = ARCHIVE_OK; + + free(iso9660->zisofs.block_pointers); + if (iso9660->zisofs.stream_valid && + deflateEnd(&(iso9660->zisofs.stream)) != Z_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to clean up compressor"); + ret = ARCHIVE_FATAL; + } + iso9660->zisofs.block_pointers = NULL; + iso9660->zisofs.stream_valid = 0; + return (ret); +} + +struct zisofs_extract { + int pz_log2_bs; /* Log2 of block size */ + uint64_t pz_uncompressed_size; + size_t uncompressed_buffer_size; + + signed int initialized:1; + signed int header_passed:1; + + uint32_t pz_offset; + unsigned char *block_pointers; + size_t block_pointers_size; + size_t block_pointers_avail; + size_t block_off; + uint32_t block_avail; + + z_stream stream; + int stream_valid; +}; + +static ssize_t +zisofs_extract_init(struct archive_write *a, struct zisofs_extract *zisofs, + const unsigned char *p, size_t bytes) +{ + size_t avail = bytes; + size_t _ceil, xsize; + + /* Allocate block pointers buffer. */ + _ceil = (size_t)((zisofs->pz_uncompressed_size + + (((int64_t)1) << zisofs->pz_log2_bs) - 1) + >> zisofs->pz_log2_bs); + xsize = (_ceil + 1) * 4; + if (zisofs->block_pointers == NULL) { + size_t alloc = ((xsize >> 10) + 1) << 10; + zisofs->block_pointers = malloc(alloc); + if (zisofs->block_pointers == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for zisofs decompression"); + return (ARCHIVE_FATAL); + } + } + zisofs->block_pointers_size = xsize; + + /* Allocate uncompressed data buffer. */ + zisofs->uncompressed_buffer_size = (size_t)1UL << zisofs->pz_log2_bs; + + /* + * Read the file header, and check the magic code of zisofs. + */ + if (!zisofs->header_passed) { + int err = 0; + if (avail < 16) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Illegal zisofs file body"); + return (ARCHIVE_FATAL); + } + + if (memcmp(p, zisofs_magic, sizeof(zisofs_magic)) != 0) + err = 1; + else if (archive_le32dec(p + 8) != zisofs->pz_uncompressed_size) + err = 1; + else if (p[12] != 4 || p[13] != zisofs->pz_log2_bs) + err = 1; + if (err) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Illegal zisofs file body"); + return (ARCHIVE_FATAL); + } + avail -= 16; + p += 16; + zisofs->header_passed = 1; + } + + /* + * Read block pointers. + */ + if (zisofs->header_passed && + zisofs->block_pointers_avail < zisofs->block_pointers_size) { + xsize = zisofs->block_pointers_size + - zisofs->block_pointers_avail; + if (avail < xsize) + xsize = avail; + memcpy(zisofs->block_pointers + + zisofs->block_pointers_avail, p, xsize); + zisofs->block_pointers_avail += xsize; + avail -= xsize; + if (zisofs->block_pointers_avail + == zisofs->block_pointers_size) { + /* We've got all block pointers and initialize + * related variables. */ + zisofs->block_off = 0; + zisofs->block_avail = 0; + /* Complete a initialization */ + zisofs->initialized = 1; + } + } + return ((ssize_t)avail); +} + +static ssize_t +zisofs_extract(struct archive_write *a, struct zisofs_extract *zisofs, + const unsigned char *p, size_t bytes) +{ + size_t avail; + int r; + + if (!zisofs->initialized) { + ssize_t rs = zisofs_extract_init(a, zisofs, p, bytes); + if (rs < 0) + return (rs); + if (!zisofs->initialized) { + /* We need more data. */ + zisofs->pz_offset += (uint32_t)bytes; + return (bytes); + } + avail = rs; + p += bytes - avail; + } else + avail = bytes; + + /* + * Get block offsets from block pointers. + */ + if (zisofs->block_avail == 0) { + uint32_t bst, bed; + + if (zisofs->block_off + 4 >= zisofs->block_pointers_size) { + /* There isn't a pair of offsets. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Illegal zisofs block pointers"); + return (ARCHIVE_FATAL); + } + bst = archive_le32dec( + zisofs->block_pointers + zisofs->block_off); + if (bst != zisofs->pz_offset + (bytes - avail)) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Illegal zisofs block pointers(cannot seek)"); + return (ARCHIVE_FATAL); + } + bed = archive_le32dec( + zisofs->block_pointers + zisofs->block_off + 4); + if (bed < bst) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Illegal zisofs block pointers"); + return (ARCHIVE_FATAL); + } + zisofs->block_avail = bed - bst; + zisofs->block_off += 4; + + /* Initialize compression library for new block. */ + if (zisofs->stream_valid) + r = inflateReset(&zisofs->stream); + else + r = inflateInit(&zisofs->stream); + if (r != Z_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't initialize zisofs decompression."); + return (ARCHIVE_FATAL); + } + zisofs->stream_valid = 1; + zisofs->stream.total_in = 0; + zisofs->stream.total_out = 0; + } + + /* + * Make uncompressed data. + */ + if (zisofs->block_avail == 0) { + /* + * It's basically 32K bytes NUL data. + */ + unsigned char *wb; + size_t size, wsize; + + size = zisofs->uncompressed_buffer_size; + while (size) { + wb = wb_buffptr(a); + if (size > wb_remaining(a)) + wsize = wb_remaining(a); + else + wsize = size; + memset(wb, 0, wsize); + r = wb_consume(a, wsize); + if (r < 0) + return (r); + size -= wsize; + } + } else { + zisofs->stream.next_in = (Bytef *)(uintptr_t)(const void *)p; + if (avail > zisofs->block_avail) + zisofs->stream.avail_in = zisofs->block_avail; + else + zisofs->stream.avail_in = (uInt)avail; + zisofs->stream.next_out = wb_buffptr(a); + zisofs->stream.avail_out = (uInt)wb_remaining(a); + + r = inflate(&zisofs->stream, 0); + switch (r) { + case Z_OK: /* Decompressor made some progress.*/ + case Z_STREAM_END: /* Found end of stream. */ + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "zisofs decompression failed (%d)", r); + return (ARCHIVE_FATAL); + } + avail -= zisofs->stream.next_in - p; + zisofs->block_avail -= (uint32_t)(zisofs->stream.next_in - p); + r = wb_consume(a, wb_remaining(a) - zisofs->stream.avail_out); + if (r < 0) + return (r); + } + zisofs->pz_offset += (uint32_t)bytes; + return (bytes - avail); +} + +static int +zisofs_rewind_boot_file(struct archive_write *a) +{ + struct iso9660 *iso9660 = a->format_data; + struct isofile *file; + unsigned char *rbuff; + ssize_t r; + size_t remaining, rbuff_size; + struct zisofs_extract zext; + int64_t read_offset, write_offset, new_offset; + int fd, ret = ARCHIVE_OK; + + file = iso9660->el_torito.boot->file; + /* + * There is nothing to do if this boot file does not have + * zisofs header. + */ + if (file->zisofs.header_size == 0) + return (ARCHIVE_OK); + + /* + * Uncompress the zisofs'ed file contents. + */ + memset(&zext, 0, sizeof(zext)); + zext.pz_uncompressed_size = file->zisofs.uncompressed_size; + zext.pz_log2_bs = file->zisofs.log2_bs; + + fd = iso9660->temp_fd; + new_offset = wb_offset(a); + read_offset = file->content.offset_of_temp; + remaining = (size_t)file->content.size; + if (remaining > 1024 * 32) + rbuff_size = 1024 * 32; + else + rbuff_size = remaining; + + rbuff = malloc(rbuff_size); + if (rbuff == NULL) { + archive_set_error(&a->archive, ENOMEM, "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + while (remaining) { + size_t rsize; + ssize_t rs; + + /* Get the current file pointer. */ + write_offset = lseek(fd, 0, SEEK_CUR); + + /* Change the file pointer to read. */ + lseek(fd, read_offset, SEEK_SET); + + rsize = rbuff_size; + if (rsize > remaining) + rsize = remaining; + rs = read(iso9660->temp_fd, rbuff, rsize); + if (rs <= 0) { + archive_set_error(&a->archive, errno, + "Can't read temporary file(%jd)", (intmax_t)rs); + ret = ARCHIVE_FATAL; + break; + } + remaining -= rs; + read_offset += rs; + + /* Put the file pointer back to write. */ + lseek(fd, write_offset, SEEK_SET); + + r = zisofs_extract(a, &zext, rbuff, rs); + if (r < 0) { + ret = (int)r; + break; + } + } + + if (ret == ARCHIVE_OK) { + /* + * Change the boot file content from zisofs'ed data + * to plain data. + */ + file->content.offset_of_temp = new_offset; + file->content.size = file->zisofs.uncompressed_size; + archive_entry_set_size(file->entry, file->content.size); + /* Set to be no zisofs. */ + file->zisofs.header_size = 0; + file->zisofs.log2_bs = 0; + file->zisofs.uncompressed_size = 0; + r = wb_write_padding_to_temp(a, file->content.size); + if (r < 0) + ret = ARCHIVE_FATAL; + } + + /* + * Free the resource we used in this function only. + */ + free(rbuff); + free(zext.block_pointers); + if (zext.stream_valid && inflateEnd(&(zext.stream)) != Z_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to clean up compressor"); + ret = ARCHIVE_FATAL; + } + + return (ret); +} + +#else + +static int +zisofs_write_to_temp(struct archive_write *a, const void *buff, size_t s) +{ + (void)buff; /* UNUSED */ + (void)s; /* UNUSED */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Programming error"); + return (ARCHIVE_FATAL); +} + +static int +zisofs_rewind_boot_file(struct archive_write *a) +{ + struct iso9660 *iso9660 = a->format_data; + + if (iso9660->el_torito.boot->file->zisofs.header_size != 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "We cannot extract the zisofs imaged boot file;" + " this may not boot in being zisofs imaged"); + return (ARCHIVE_FAILED); + } + return (ARCHIVE_OK); +} + +static int +zisofs_finish_entry(struct archive_write *a) +{ + (void)a; /* UNUSED */ + return (ARCHIVE_OK); +} + +static int +zisofs_free(struct archive_write *a) +{ + (void)a; /* UNUSED */ + return (ARCHIVE_OK); +} + +#endif /* HAVE_ZLIB_H */ + diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_mtree.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_mtree.c new file mode 100644 index 0000000..aa41e9a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_mtree.c @@ -0,0 +1,2228 @@ +/*- + * Copyright (c) 2008 Joerg Sonnenberger + * Copyright (c) 2009-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_mtree.c 201171 2009-12-29 06:39:07Z kientzle $"); + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#include +#include +#include + +#include "archive.h" +#include "archive_digest_private.h" +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_rb.h" +#include "archive_string.h" +#include "archive_write_private.h" + +#define INDENTNAMELEN 15 +#define MAXLINELEN 80 +#define SET_KEYS \ + (F_FLAGS | F_GID | F_GNAME | F_MODE | F_TYPE | F_UID | F_UNAME) + +struct attr_counter { + struct attr_counter *prev; + struct attr_counter *next; + struct mtree_entry *m_entry; + int count; +}; + +struct att_counter_set { + struct attr_counter *uid_list; + struct attr_counter *gid_list; + struct attr_counter *mode_list; + struct attr_counter *flags_list; +}; + +struct mtree_chain { + struct mtree_entry *first; + struct mtree_entry **last; +}; + +/* + * The Data only for a directory file. + */ +struct dir_info { + struct archive_rb_tree rbtree; + struct mtree_chain children; + struct mtree_entry *chnext; + int virtual; +}; + +/* + * The Data only for a regular file. + */ +struct reg_info { + int compute_sum; + uint32_t crc; +#ifdef ARCHIVE_HAS_MD5 + unsigned char buf_md5[16]; +#endif +#ifdef ARCHIVE_HAS_RMD160 + unsigned char buf_rmd160[20]; +#endif +#ifdef ARCHIVE_HAS_SHA1 + unsigned char buf_sha1[20]; +#endif +#ifdef ARCHIVE_HAS_SHA256 + unsigned char buf_sha256[32]; +#endif +#ifdef ARCHIVE_HAS_SHA384 + unsigned char buf_sha384[48]; +#endif +#ifdef ARCHIVE_HAS_SHA512 + unsigned char buf_sha512[64]; +#endif +}; + +struct mtree_entry { + struct archive_rb_node rbnode; + struct mtree_entry *next; + struct mtree_entry *parent; + struct dir_info *dir_info; + struct reg_info *reg_info; + + struct archive_string parentdir; + struct archive_string basename; + struct archive_string pathname; + struct archive_string symlink; + struct archive_string uname; + struct archive_string gname; + struct archive_string fflags_text; + unsigned int nlink; + mode_t filetype; + mode_t mode; + int64_t size; + int64_t uid; + int64_t gid; + time_t mtime; + long mtime_nsec; + unsigned long fflags_set; + unsigned long fflags_clear; + dev_t rdevmajor; + dev_t rdevminor; + dev_t devmajor; + dev_t devminor; + int64_t ino; +}; + +struct mtree_writer { + struct mtree_entry *mtree_entry; + struct mtree_entry *root; + struct mtree_entry *cur_dirent; + struct archive_string cur_dirstr; + struct mtree_chain file_list; + + struct archive_string ebuf; + struct archive_string buf; + int first; + uint64_t entry_bytes_remaining; + + /* + * Set global value. + */ + struct { + int processing; + mode_t type; + int keys; + int64_t uid; + int64_t gid; + mode_t mode; + unsigned long fflags_set; + unsigned long fflags_clear; + } set; + struct att_counter_set acs; + int classic; + int depth; + + /* check sum */ + int compute_sum; + uint32_t crc; + uint64_t crc_len; +#ifdef ARCHIVE_HAS_MD5 + archive_md5_ctx md5ctx; +#endif +#ifdef ARCHIVE_HAS_RMD160 + archive_rmd160_ctx rmd160ctx; +#endif +#ifdef ARCHIVE_HAS_SHA1 + archive_sha1_ctx sha1ctx; +#endif +#ifdef ARCHIVE_HAS_SHA256 + archive_sha256_ctx sha256ctx; +#endif +#ifdef ARCHIVE_HAS_SHA384 + archive_sha384_ctx sha384ctx; +#endif +#ifdef ARCHIVE_HAS_SHA512 + archive_sha512_ctx sha512ctx; +#endif + /* Keyword options */ + int keys; +#define F_CKSUM 0x00000001 /* checksum */ +#define F_DEV 0x00000002 /* device type */ +#define F_DONE 0x00000004 /* directory done */ +#define F_FLAGS 0x00000008 /* file flags */ +#define F_GID 0x00000010 /* gid */ +#define F_GNAME 0x00000020 /* group name */ +#define F_IGN 0x00000040 /* ignore */ +#define F_MAGIC 0x00000080 /* name has magic chars */ +#define F_MD5 0x00000100 /* MD5 digest */ +#define F_MODE 0x00000200 /* mode */ +#define F_NLINK 0x00000400 /* number of links */ +#define F_NOCHANGE 0x00000800 /* If owner/mode "wrong", do + * not change */ +#define F_OPT 0x00001000 /* existence optional */ +#define F_RMD160 0x00002000 /* RIPEMD160 digest */ +#define F_SHA1 0x00004000 /* SHA-1 digest */ +#define F_SIZE 0x00008000 /* size */ +#define F_SLINK 0x00010000 /* symbolic link */ +#define F_TAGS 0x00020000 /* tags */ +#define F_TIME 0x00040000 /* modification time */ +#define F_TYPE 0x00080000 /* file type */ +#define F_UID 0x00100000 /* uid */ +#define F_UNAME 0x00200000 /* user name */ +#define F_VISIT 0x00400000 /* file visited */ +#define F_SHA256 0x00800000 /* SHA-256 digest */ +#define F_SHA384 0x01000000 /* SHA-384 digest */ +#define F_SHA512 0x02000000 /* SHA-512 digest */ +#define F_INO 0x04000000 /* inode number */ +#define F_RESDEV 0x08000000 /* device ID on which the + * entry resides */ + + /* Options */ + int dironly; /* If it is set, ignore all files except + * directory files, like mtree(8) -d option. */ + int indent; /* If it is set, indent output data. */ + int output_global_set; /* If it is set, use /set keyword to set + * global values. When generating mtree + * classic format, it is set by default. */ +}; + +#define DEFAULT_KEYS (F_DEV | F_FLAGS | F_GID | F_GNAME | F_SLINK | F_MODE\ + | F_NLINK | F_SIZE | F_TIME | F_TYPE | F_UID\ + | F_UNAME) +#define attr_counter_set_reset attr_counter_set_free + +static void attr_counter_free(struct attr_counter **); +static int attr_counter_inc(struct attr_counter **, struct attr_counter *, + struct attr_counter *, struct mtree_entry *); +static struct attr_counter * attr_counter_new(struct mtree_entry *, + struct attr_counter *); +static int attr_counter_set_collect(struct mtree_writer *, + struct mtree_entry *); +static void attr_counter_set_free(struct mtree_writer *); +static int get_global_set_keys(struct mtree_writer *, struct mtree_entry *); +static int mtree_entry_add_child_tail(struct mtree_entry *, + struct mtree_entry *); +static int mtree_entry_create_virtual_dir(struct archive_write *, const char *, + struct mtree_entry **); +static int mtree_entry_cmp_node(const struct archive_rb_node *, + const struct archive_rb_node *); +static int mtree_entry_cmp_key(const struct archive_rb_node *, const void *); +static int mtree_entry_exchange_same_entry(struct archive_write *, + struct mtree_entry *, struct mtree_entry *); +static void mtree_entry_free(struct mtree_entry *); +static int mtree_entry_new(struct archive_write *, struct archive_entry *, + struct mtree_entry **); +static void mtree_entry_register_free(struct mtree_writer *); +static void mtree_entry_register_init(struct mtree_writer *); +static int mtree_entry_setup_filenames(struct archive_write *, + struct mtree_entry *, struct archive_entry *); +static int mtree_entry_tree_add(struct archive_write *, struct mtree_entry **); +static void sum_init(struct mtree_writer *); +static void sum_update(struct mtree_writer *, const void *, size_t); +static void sum_final(struct mtree_writer *, struct reg_info *); +static void sum_write(struct archive_string *, struct reg_info *); +static int write_mtree_entry(struct archive_write *, struct mtree_entry *); +static int write_dot_dot_entry(struct archive_write *, struct mtree_entry *); + +#define COMPUTE_CRC(var, ch) (var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)] +static const uint32_t crctab[] = { + 0x0, + 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, + 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, + 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, + 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, + 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f, + 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, + 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, + 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, + 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe, + 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, + 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, + 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, + 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, + 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, + 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07, + 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, + 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, + 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, + 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, + 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, + 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, + 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f, + 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, + 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, + 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, + 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, + 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629, + 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, + 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, + 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, + 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8, + 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, + 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, + 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, + 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, + 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, + 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21, + 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, + 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087, + 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, + 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, + 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, + 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, + 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09, + 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, + 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, + 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 +}; + +static const unsigned char safe_char[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 0F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */ + /* !"$%&'()*+,-./ EXCLUSION:0x20( ) 0x23(#) */ + 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */ + /* 0123456789:;<>? EXCLUSION:0x3d(=) */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, /* 30 - 3F */ + /* @ABCDEFGHIJKLMNO */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */ + /* PQRSTUVWXYZ[]^_ EXCLUSION:0x5c(\) */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, /* 50 - 5F */ + /* `abcdefghijklmno */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */ + /* pqrstuvwxyz{|}~ */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* 70 - 7F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */ +}; + +static void +mtree_quote(struct archive_string *s, const char *str) +{ + const char *start; + char buf[4]; + unsigned char c; + + for (start = str; *str != '\0'; ++str) { + if (safe_char[*(const unsigned char *)str]) + continue; + if (start != str) + archive_strncat(s, start, str - start); + c = (unsigned char)*str; + buf[0] = '\\'; + buf[1] = (c / 64) + '0'; + buf[2] = (c / 8 % 8) + '0'; + buf[3] = (c % 8) + '0'; + archive_strncat(s, buf, 4); + start = str + 1; + } + + if (start != str) + archive_strncat(s, start, str - start); +} + +/* + * Indent a line as the mtree utility does so it is readable for people. + */ +static void +mtree_indent(struct mtree_writer *mtree) +{ + int i, fn, nd, pd; + const char *r, *s, *x; + + if (mtree->classic) { + if (mtree->indent) { + nd = 0; + pd = mtree->depth * 4; + } else { + nd = mtree->depth?4:0; + pd = 0; + } + } else + nd = pd = 0; + fn = 1; + s = r = mtree->ebuf.s; + x = NULL; + while (*r == ' ') + r++; + while ((r = strchr(r, ' ')) != NULL) { + if (fn) { + fn = 0; + for (i = 0; i < nd + pd; i++) + archive_strappend_char(&mtree->buf, ' '); + archive_strncat(&mtree->buf, s, r - s); + if (nd + (r -s) > INDENTNAMELEN) { + archive_strncat(&mtree->buf, " \\\n", 3); + for (i = 0; i < (INDENTNAMELEN + 1 + pd); i++) + archive_strappend_char(&mtree->buf, ' '); + } else { + for (i = (int)(r -s + nd); + i < (INDENTNAMELEN + 1); i++) + archive_strappend_char(&mtree->buf, ' '); + } + s = ++r; + x = NULL; + continue; + } + if (pd + (r - s) <= MAXLINELEN - 3 - INDENTNAMELEN) + x = r++; + else { + if (x == NULL) + x = r; + archive_strncat(&mtree->buf, s, x - s); + archive_strncat(&mtree->buf, " \\\n", 3); + for (i = 0; i < (INDENTNAMELEN + 1 + pd); i++) + archive_strappend_char(&mtree->buf, ' '); + s = r = ++x; + x = NULL; + } + } + if (fn) { + for (i = 0; i < nd + pd; i++) + archive_strappend_char(&mtree->buf, ' '); + archive_strcat(&mtree->buf, s); + s += strlen(s); + } + if (x != NULL && pd + strlen(s) > MAXLINELEN - 3 - INDENTNAMELEN) { + /* Last keyword is longer. */ + archive_strncat(&mtree->buf, s, x - s); + archive_strncat(&mtree->buf, " \\\n", 3); + for (i = 0; i < (INDENTNAMELEN + 1 + pd); i++) + archive_strappend_char(&mtree->buf, ' '); + s = ++x; + } + archive_strcat(&mtree->buf, s); + archive_string_empty(&mtree->ebuf); +} + +/* + * Write /set keyword. + * Set the most used value of uid, gid, mode and fflags, which are + * collected by the attr_counter_set_collect() function. + */ +static void +write_global(struct mtree_writer *mtree) +{ + struct archive_string setstr; + struct archive_string unsetstr; + struct att_counter_set *acs; + int keys, oldkeys, effkeys; + + archive_string_init(&setstr); + archive_string_init(&unsetstr); + keys = mtree->keys & SET_KEYS; + oldkeys = mtree->set.keys; + effkeys = keys; + acs = &mtree->acs; + if (mtree->set.processing) { + /* + * Check if the global data needs updating. + */ + effkeys &= ~F_TYPE; + if (acs->uid_list == NULL) + effkeys &= ~(F_UNAME | F_UID); + else if (oldkeys & (F_UNAME | F_UID)) { + if (acs->uid_list->count < 2 || + mtree->set.uid == acs->uid_list->m_entry->uid) + effkeys &= ~(F_UNAME | F_UID); + } + if (acs->gid_list == NULL) + effkeys &= ~(F_GNAME | F_GID); + else if (oldkeys & (F_GNAME | F_GID)) { + if (acs->gid_list->count < 2 || + mtree->set.gid == acs->gid_list->m_entry->gid) + effkeys &= ~(F_GNAME | F_GID); + } + if (acs->mode_list == NULL) + effkeys &= ~F_MODE; + else if (oldkeys & F_MODE) { + if (acs->mode_list->count < 2 || + mtree->set.mode == acs->mode_list->m_entry->mode) + effkeys &= ~F_MODE; + } + if (acs->flags_list == NULL) + effkeys &= ~F_FLAGS; + else if ((oldkeys & F_FLAGS) != 0) { + if (acs->flags_list->count < 2 || + (acs->flags_list->m_entry->fflags_set == + mtree->set.fflags_set && + acs->flags_list->m_entry->fflags_clear == + mtree->set.fflags_clear)) + effkeys &= ~F_FLAGS; + } + } else { + if (acs->uid_list == NULL) + keys &= ~(F_UNAME | F_UID); + if (acs->gid_list == NULL) + keys &= ~(F_GNAME | F_GID); + if (acs->mode_list == NULL) + keys &= ~F_MODE; + if (acs->flags_list == NULL) + keys &= ~F_FLAGS; + } + if ((keys & effkeys & F_TYPE) != 0) { + if (mtree->dironly) { + archive_strcat(&setstr, " type=dir"); + mtree->set.type = AE_IFDIR; + } else { + archive_strcat(&setstr, " type=file"); + mtree->set.type = AE_IFREG; + } + } + if ((keys & effkeys & F_UNAME) != 0) { + if (archive_strlen(&(acs->uid_list->m_entry->uname)) > 0) { + archive_strcat(&setstr, " uname="); + mtree_quote(&setstr, acs->uid_list->m_entry->uname.s); + } else { + keys &= ~F_UNAME; + if ((oldkeys & F_UNAME) != 0) + archive_strcat(&unsetstr, " uname"); + } + } + if ((keys & effkeys & F_UID) != 0) { + mtree->set.uid = acs->uid_list->m_entry->uid; + archive_string_sprintf(&setstr, " uid=%jd", + (intmax_t)mtree->set.uid); + } + if ((keys & effkeys & F_GNAME) != 0) { + if (archive_strlen(&(acs->gid_list->m_entry->gname)) > 0) { + archive_strcat(&setstr, " gname="); + mtree_quote(&setstr, acs->gid_list->m_entry->gname.s); + } else { + keys &= ~F_GNAME; + if ((oldkeys & F_GNAME) != 0) + archive_strcat(&unsetstr, " gname"); + } + } + if ((keys & effkeys & F_GID) != 0) { + mtree->set.gid = acs->gid_list->m_entry->gid; + archive_string_sprintf(&setstr, " gid=%jd", + (intmax_t)mtree->set.gid); + } + if ((keys & effkeys & F_MODE) != 0) { + mtree->set.mode = acs->mode_list->m_entry->mode; + archive_string_sprintf(&setstr, " mode=%o", + (unsigned int)mtree->set.mode); + } + if ((keys & effkeys & F_FLAGS) != 0) { + if (archive_strlen( + &(acs->flags_list->m_entry->fflags_text)) > 0) { + archive_strcat(&setstr, " flags="); + mtree_quote(&setstr, + acs->flags_list->m_entry->fflags_text.s); + mtree->set.fflags_set = + acs->flags_list->m_entry->fflags_set; + mtree->set.fflags_clear = + acs->flags_list->m_entry->fflags_clear; + } else { + keys &= ~F_FLAGS; + if ((oldkeys & F_FLAGS) != 0) + archive_strcat(&unsetstr, " flags"); + } + } + if (unsetstr.length > 0) + archive_string_sprintf(&mtree->buf, "/unset%s\n", unsetstr.s); + archive_string_free(&unsetstr); + if (setstr.length > 0) + archive_string_sprintf(&mtree->buf, "/set%s\n", setstr.s); + archive_string_free(&setstr); + mtree->set.keys = keys; + mtree->set.processing = 1; +} + +static struct attr_counter * +attr_counter_new(struct mtree_entry *me, struct attr_counter *prev) +{ + struct attr_counter *ac; + + ac = malloc(sizeof(*ac)); + if (ac != NULL) { + ac->prev = prev; + ac->next = NULL; + ac->count = 1; + ac->m_entry = me; + } + return (ac); +} + +static void +attr_counter_free(struct attr_counter **top) +{ + struct attr_counter *ac, *tac; + + if (*top == NULL) + return; + ac = *top; + while (ac != NULL) { + tac = ac->next; + free(ac); + ac = tac; + } + *top = NULL; +} + +static int +attr_counter_inc(struct attr_counter **top, struct attr_counter *ac, + struct attr_counter *last, struct mtree_entry *me) +{ + struct attr_counter *pac; + + if (ac != NULL) { + ac->count++; + if (*top == ac || ac->prev->count >= ac->count) + return (0); + for (pac = ac->prev; pac; pac = pac->prev) { + if (pac->count >= ac->count) + break; + } + ac->prev->next = ac->next; + if (ac->next != NULL) + ac->next->prev = ac->prev; + if (pac != NULL) { + ac->prev = pac; + ac->next = pac->next; + pac->next = ac; + if (ac->next != NULL) + ac->next->prev = ac; + } else { + ac->prev = NULL; + ac->next = *top; + *top = ac; + ac->next->prev = ac; + } + } else if (last != NULL) { + ac = attr_counter_new(me, last); + if (ac == NULL) + return (-1); + last->next = ac; + } + return (0); +} + +/* + * Tabulate uid, gid, mode and fflags of a entry in order to be used for /set. + */ +static int +attr_counter_set_collect(struct mtree_writer *mtree, struct mtree_entry *me) +{ + struct attr_counter *ac, *last; + struct att_counter_set *acs = &mtree->acs; + int keys = mtree->keys; + + if (keys & (F_UNAME | F_UID)) { + if (acs->uid_list == NULL) { + acs->uid_list = attr_counter_new(me, NULL); + if (acs->uid_list == NULL) + return (-1); + } else { + last = NULL; + for (ac = acs->uid_list; ac; ac = ac->next) { + if (ac->m_entry->uid == me->uid) + break; + last = ac; + } + if (attr_counter_inc(&acs->uid_list, ac, last, me) < 0) + return (-1); + } + } + if (keys & (F_GNAME | F_GID)) { + if (acs->gid_list == NULL) { + acs->gid_list = attr_counter_new(me, NULL); + if (acs->gid_list == NULL) + return (-1); + } else { + last = NULL; + for (ac = acs->gid_list; ac; ac = ac->next) { + if (ac->m_entry->gid == me->gid) + break; + last = ac; + } + if (attr_counter_inc(&acs->gid_list, ac, last, me) < 0) + return (-1); + } + } + if (keys & F_MODE) { + if (acs->mode_list == NULL) { + acs->mode_list = attr_counter_new(me, NULL); + if (acs->mode_list == NULL) + return (-1); + } else { + last = NULL; + for (ac = acs->mode_list; ac; ac = ac->next) { + if (ac->m_entry->mode == me->mode) + break; + last = ac; + } + if (attr_counter_inc(&acs->mode_list, ac, last, me) < 0) + return (-1); + } + } + if (keys & F_FLAGS) { + if (acs->flags_list == NULL) { + acs->flags_list = attr_counter_new(me, NULL); + if (acs->flags_list == NULL) + return (-1); + } else { + last = NULL; + for (ac = acs->flags_list; ac; ac = ac->next) { + if (ac->m_entry->fflags_set == me->fflags_set && + ac->m_entry->fflags_clear == + me->fflags_clear) + break; + last = ac; + } + if (attr_counter_inc(&acs->flags_list, ac, last, me) < 0) + return (-1); + } + } + + return (0); +} + +static void +attr_counter_set_free(struct mtree_writer *mtree) +{ + struct att_counter_set *acs = &mtree->acs; + + attr_counter_free(&acs->uid_list); + attr_counter_free(&acs->gid_list); + attr_counter_free(&acs->mode_list); + attr_counter_free(&acs->flags_list); +} + +static int +get_global_set_keys(struct mtree_writer *mtree, struct mtree_entry *me) +{ + int keys; + + keys = mtree->keys; + + /* + * If a keyword has been set by /set, we do not need to + * output it. + */ + if (mtree->set.keys == 0) + return (keys);/* /set is not used. */ + + if ((mtree->set.keys & (F_GNAME | F_GID)) != 0 && + mtree->set.gid == me->gid) + keys &= ~(F_GNAME | F_GID); + if ((mtree->set.keys & (F_UNAME | F_UID)) != 0 && + mtree->set.uid == me->uid) + keys &= ~(F_UNAME | F_UID); + if (mtree->set.keys & F_FLAGS) { + if (mtree->set.fflags_set == me->fflags_set && + mtree->set.fflags_clear == me->fflags_clear) + keys &= ~F_FLAGS; + } + if ((mtree->set.keys & F_MODE) != 0 && mtree->set.mode == me->mode) + keys &= ~F_MODE; + + switch (me->filetype) { + case AE_IFLNK: case AE_IFSOCK: case AE_IFCHR: + case AE_IFBLK: case AE_IFIFO: + break; + case AE_IFDIR: + if ((mtree->set.keys & F_TYPE) != 0 && + mtree->set.type == AE_IFDIR) + keys &= ~F_TYPE; + break; + case AE_IFREG: + default: /* Handle unknown file types as regular files. */ + if ((mtree->set.keys & F_TYPE) != 0 && + mtree->set.type == AE_IFREG) + keys &= ~F_TYPE; + break; + } + + return (keys); +} + +static int +mtree_entry_new(struct archive_write *a, struct archive_entry *entry, + struct mtree_entry **m_entry) +{ + struct mtree_entry *me; + const char *s; + int r; + static const struct archive_rb_tree_ops rb_ops = { + mtree_entry_cmp_node, mtree_entry_cmp_key + }; + + me = calloc(1, sizeof(*me)); + if (me == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for a mtree entry"); + *m_entry = NULL; + return (ARCHIVE_FATAL); + } + + r = mtree_entry_setup_filenames(a, me, entry); + if (r < ARCHIVE_WARN) { + mtree_entry_free(me); + *m_entry = NULL; + return (r); + } + + if ((s = archive_entry_symlink(entry)) != NULL) + archive_strcpy(&me->symlink, s); + me->nlink = archive_entry_nlink(entry); + me->filetype = archive_entry_filetype(entry); + me->mode = archive_entry_mode(entry) & 07777; + me->uid = archive_entry_uid(entry); + me->gid = archive_entry_gid(entry); + if ((s = archive_entry_uname(entry)) != NULL) + archive_strcpy(&me->uname, s); + if ((s = archive_entry_gname(entry)) != NULL) + archive_strcpy(&me->gname, s); + if ((s = archive_entry_fflags_text(entry)) != NULL) + archive_strcpy(&me->fflags_text, s); + archive_entry_fflags(entry, &me->fflags_set, &me->fflags_clear); + me->mtime = archive_entry_mtime(entry); + me->mtime_nsec = archive_entry_mtime_nsec(entry); + me->rdevmajor = archive_entry_rdevmajor(entry); + me->rdevminor = archive_entry_rdevminor(entry); + me->devmajor = archive_entry_devmajor(entry); + me->devminor = archive_entry_devminor(entry); + me->ino = archive_entry_ino(entry); + me->size = archive_entry_size(entry); + if (me->filetype == AE_IFDIR) { + me->dir_info = calloc(1, sizeof(*me->dir_info)); + if (me->dir_info == NULL) { + mtree_entry_free(me); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for a mtree entry"); + *m_entry = NULL; + return (ARCHIVE_FATAL); + } + __archive_rb_tree_init(&me->dir_info->rbtree, &rb_ops); + me->dir_info->children.first = NULL; + me->dir_info->children.last = &(me->dir_info->children.first); + me->dir_info->chnext = NULL; + } else if (me->filetype == AE_IFREG) { + me->reg_info = calloc(1, sizeof(*me->reg_info)); + if (me->reg_info == NULL) { + mtree_entry_free(me); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for a mtree entry"); + *m_entry = NULL; + return (ARCHIVE_FATAL); + } + me->reg_info->compute_sum = 0; + } + + *m_entry = me; + return (ARCHIVE_OK); +} + +static void +mtree_entry_free(struct mtree_entry *me) +{ + archive_string_free(&me->parentdir); + archive_string_free(&me->basename); + archive_string_free(&me->pathname); + archive_string_free(&me->symlink); + archive_string_free(&me->uname); + archive_string_free(&me->gname); + archive_string_free(&me->fflags_text); + free(me->dir_info); + free(me->reg_info); + free(me); +} + +static int +archive_write_mtree_header(struct archive_write *a, + struct archive_entry *entry) +{ + struct mtree_writer *mtree= a->format_data; + struct mtree_entry *mtree_entry; + int r, r2; + + if (mtree->first) { + mtree->first = 0; + archive_strcat(&mtree->buf, "#mtree\n"); + if ((mtree->keys & SET_KEYS) == 0) + mtree->output_global_set = 0;/* Disabled. */ + } + + mtree->entry_bytes_remaining = archive_entry_size(entry); + + /* While directory only mode, we do not handle non directory files. */ + if (mtree->dironly && archive_entry_filetype(entry) != AE_IFDIR) + return (ARCHIVE_OK); + + r2 = mtree_entry_new(a, entry, &mtree_entry); + if (r2 < ARCHIVE_WARN) + return (r2); + r = mtree_entry_tree_add(a, &mtree_entry); + if (r < ARCHIVE_WARN) { + mtree_entry_free(mtree_entry); + return (r); + } + mtree->mtree_entry = mtree_entry; + + /* If the current file is a regular file, we have to + * compute the sum of its content. + * Initialize a bunch of checksum context. */ + if (mtree_entry->reg_info) + sum_init(mtree); + + return (r2); +} + +static int +write_mtree_entry(struct archive_write *a, struct mtree_entry *me) +{ + struct mtree_writer *mtree = a->format_data; + struct archive_string *str; + int keys, ret; + + if (me->dir_info) { + if (mtree->classic) { + /* + * Output a comment line to describe the full + * pathname of the entry as mtree utility does + * while generating classic format. + */ + if (!mtree->dironly) + archive_strappend_char(&mtree->buf, '\n'); + if (me->parentdir.s) + archive_string_sprintf(&mtree->buf, + "# %s/%s\n", + me->parentdir.s, me->basename.s); + else + archive_string_sprintf(&mtree->buf, + "# %s\n", + me->basename.s); + } + if (mtree->output_global_set) + write_global(mtree); + } + archive_string_empty(&mtree->ebuf); + str = (mtree->indent || mtree->classic)? &mtree->ebuf : &mtree->buf; + + if (!mtree->classic && me->parentdir.s) { + /* + * If generating format is not classic one(v1), output + * a full pathname. + */ + mtree_quote(str, me->parentdir.s); + archive_strappend_char(str, '/'); + } + mtree_quote(str, me->basename.s); + + keys = get_global_set_keys(mtree, me); + if ((keys & F_NLINK) != 0 && + me->nlink != 1 && me->filetype != AE_IFDIR) + archive_string_sprintf(str, " nlink=%u", me->nlink); + + if ((keys & F_GNAME) != 0 && archive_strlen(&me->gname) > 0) { + archive_strcat(str, " gname="); + mtree_quote(str, me->gname.s); + } + if ((keys & F_UNAME) != 0 && archive_strlen(&me->uname) > 0) { + archive_strcat(str, " uname="); + mtree_quote(str, me->uname.s); + } + if ((keys & F_FLAGS) != 0) { + if (archive_strlen(&me->fflags_text) > 0) { + archive_strcat(str, " flags="); + mtree_quote(str, me->fflags_text.s); + } else if (mtree->set.processing && + (mtree->set.keys & F_FLAGS) != 0) + /* Overwrite the global parameter. */ + archive_strcat(str, " flags=none"); + } + if ((keys & F_TIME) != 0) + archive_string_sprintf(str, " time=%jd.%jd", + (intmax_t)me->mtime, (intmax_t)me->mtime_nsec); + if ((keys & F_MODE) != 0) + archive_string_sprintf(str, " mode=%o", (unsigned int)me->mode); + if ((keys & F_GID) != 0) + archive_string_sprintf(str, " gid=%jd", (intmax_t)me->gid); + if ((keys & F_UID) != 0) + archive_string_sprintf(str, " uid=%jd", (intmax_t)me->uid); + + if ((keys & F_INO) != 0) + archive_string_sprintf(str, " inode=%jd", (intmax_t)me->ino); + if ((keys & F_RESDEV) != 0) { + archive_string_sprintf(str, + " resdevice=native,%ju,%ju", + (uintmax_t)me->devmajor, + (uintmax_t)me->devminor); + } + + switch (me->filetype) { + case AE_IFLNK: + if ((keys & F_TYPE) != 0) + archive_strcat(str, " type=link"); + if ((keys & F_SLINK) != 0) { + archive_strcat(str, " link="); + mtree_quote(str, me->symlink.s); + } + break; + case AE_IFSOCK: + if ((keys & F_TYPE) != 0) + archive_strcat(str, " type=socket"); + break; + case AE_IFCHR: + if ((keys & F_TYPE) != 0) + archive_strcat(str, " type=char"); + if ((keys & F_DEV) != 0) { + archive_string_sprintf(str, + " device=native,%ju,%ju", + (uintmax_t)me->rdevmajor, + (uintmax_t)me->rdevminor); + } + break; + case AE_IFBLK: + if ((keys & F_TYPE) != 0) + archive_strcat(str, " type=block"); + if ((keys & F_DEV) != 0) { + archive_string_sprintf(str, + " device=native,%ju,%ju", + (uintmax_t)me->rdevmajor, + (uintmax_t)me->rdevminor); + } + break; + case AE_IFDIR: + if ((keys & F_TYPE) != 0) + archive_strcat(str, " type=dir"); + break; + case AE_IFIFO: + if ((keys & F_TYPE) != 0) + archive_strcat(str, " type=fifo"); + break; + case AE_IFREG: + default: /* Handle unknown file types as regular files. */ + if ((keys & F_TYPE) != 0) + archive_strcat(str, " type=file"); + if ((keys & F_SIZE) != 0) + archive_string_sprintf(str, " size=%jd", + (intmax_t)me->size); + break; + } + + /* Write a bunch of sum. */ + if (me->reg_info) + sum_write(str, me->reg_info); + + archive_strappend_char(str, '\n'); + if (mtree->indent || mtree->classic) + mtree_indent(mtree); + + if (mtree->buf.length > 32768) { + ret = __archive_write_output( + a, mtree->buf.s, mtree->buf.length); + archive_string_empty(&mtree->buf); + } else + ret = ARCHIVE_OK; + return (ret); +} + +static int +write_dot_dot_entry(struct archive_write *a, struct mtree_entry *n) +{ + struct mtree_writer *mtree = a->format_data; + int ret; + + if (n->parentdir.s) { + if (mtree->indent) { + int i, pd = mtree->depth * 4; + for (i = 0; i < pd; i++) + archive_strappend_char(&mtree->buf, ' '); + } + archive_string_sprintf(&mtree->buf, "# %s/%s\n", + n->parentdir.s, n->basename.s); + } + + if (mtree->indent) { + archive_string_empty(&mtree->ebuf); + archive_strncat(&mtree->ebuf, "..\n\n", (mtree->dironly)?3:4); + mtree_indent(mtree); + } else + archive_strncat(&mtree->buf, "..\n\n", (mtree->dironly)?3:4); + + if (mtree->buf.length > 32768) { + ret = __archive_write_output( + a, mtree->buf.s, mtree->buf.length); + archive_string_empty(&mtree->buf); + } else + ret = ARCHIVE_OK; + return (ret); +} + +/* + * Write mtree entries saved at attr_counter_set_collect() function. + */ +static int +write_mtree_entry_tree(struct archive_write *a) +{ + struct mtree_writer *mtree = a->format_data; + struct mtree_entry *np = mtree->root; + struct archive_rb_node *n; + int ret; + + do { + if (mtree->output_global_set) { + /* + * Collect attribute information to know which value + * is frequently used among the children. + */ + attr_counter_set_reset(mtree); + ARCHIVE_RB_TREE_FOREACH(n, &(np->dir_info->rbtree)) { + struct mtree_entry *e = (struct mtree_entry *)n; + if (attr_counter_set_collect(mtree, e) < 0) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + } + } + if (!np->dir_info->virtual || mtree->classic) { + ret = write_mtree_entry(a, np); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } else { + /* Whenever output_global_set is enabled + * output global value(/set keywords) + * even if the directory entry is not allowed + * to be written because the global values + * can be used for the children. */ + if (mtree->output_global_set) + write_global(mtree); + } + /* + * Output the attribute of all files except directory files. + */ + mtree->depth++; + ARCHIVE_RB_TREE_FOREACH(n, &(np->dir_info->rbtree)) { + struct mtree_entry *e = (struct mtree_entry *)n; + + if (e->dir_info) + mtree_entry_add_child_tail(np, e); + else { + ret = write_mtree_entry(a, e); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + } + mtree->depth--; + + if (np->dir_info->children.first != NULL) { + /* + * Descend the tree. + */ + np = np->dir_info->children.first; + if (mtree->indent) + mtree->depth++; + continue; + } else if (mtree->classic) { + /* + * While printing mtree classic, if there are not + * any directory files(except "." and "..") in the + * directory, output two dots ".." as returning + * the parent directory. + */ + ret = write_dot_dot_entry(a, np); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + + while (np != np->parent) { + if (np->dir_info->chnext == NULL) { + /* + * Ascend the tree; go back to the parent. + */ + if (mtree->indent) + mtree->depth--; + if (mtree->classic) { + ret = write_dot_dot_entry(a, + np->parent); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + np = np->parent; + } else { + /* + * Switch to next mtree entry in the directory. + */ + np = np->dir_info->chnext; + break; + } + } + } while (np != np->parent); + + return (ARCHIVE_OK); +} + +static int +archive_write_mtree_finish_entry(struct archive_write *a) +{ + struct mtree_writer *mtree = a->format_data; + struct mtree_entry *me; + + if ((me = mtree->mtree_entry) == NULL) + return (ARCHIVE_OK); + mtree->mtree_entry = NULL; + + if (me->reg_info) + sum_final(mtree, me->reg_info); + + return (ARCHIVE_OK); +} + +static int +archive_write_mtree_close(struct archive_write *a) +{ + struct mtree_writer *mtree= a->format_data; + int ret; + + if (mtree->root != NULL) { + ret = write_mtree_entry_tree(a); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + + archive_write_set_bytes_in_last_block(&a->archive, 1); + + return __archive_write_output(a, mtree->buf.s, mtree->buf.length); +} + +static ssize_t +archive_write_mtree_data(struct archive_write *a, const void *buff, size_t n) +{ + struct mtree_writer *mtree= a->format_data; + + if (n > mtree->entry_bytes_remaining) + n = (size_t)mtree->entry_bytes_remaining; + mtree->entry_bytes_remaining -= n; + + /* We don't need to compute a regular file sum */ + if (mtree->mtree_entry == NULL) + return (n); + + if (mtree->mtree_entry->filetype == AE_IFREG) + sum_update(mtree, buff, n); + + return (n); +} + +static int +archive_write_mtree_free(struct archive_write *a) +{ + struct mtree_writer *mtree= a->format_data; + + if (mtree == NULL) + return (ARCHIVE_OK); + + /* Make sure we do not leave any entries. */ + mtree_entry_register_free(mtree); + archive_string_free(&mtree->cur_dirstr); + archive_string_free(&mtree->ebuf); + archive_string_free(&mtree->buf); + attr_counter_set_free(mtree); + free(mtree); + a->format_data = NULL; + return (ARCHIVE_OK); +} + +static int +archive_write_mtree_options(struct archive_write *a, const char *key, + const char *value) +{ + struct mtree_writer *mtree= a->format_data; + int keybit = 0; + + switch (key[0]) { + case 'a': + if (strcmp(key, "all") == 0) + keybit = ~0; + break; + case 'c': + if (strcmp(key, "cksum") == 0) + keybit = F_CKSUM; + break; + case 'd': + if (strcmp(key, "device") == 0) + keybit = F_DEV; + else if (strcmp(key, "dironly") == 0) { + mtree->dironly = (value != NULL)? 1: 0; + return (ARCHIVE_OK); + } + break; + case 'f': + if (strcmp(key, "flags") == 0) + keybit = F_FLAGS; + break; + case 'g': + if (strcmp(key, "gid") == 0) + keybit = F_GID; + else if (strcmp(key, "gname") == 0) + keybit = F_GNAME; + break; + case 'i': + if (strcmp(key, "indent") == 0) { + mtree->indent = (value != NULL)? 1: 0; + return (ARCHIVE_OK); + } else if (strcmp(key, "inode") == 0) { + keybit = F_INO; + } + break; + case 'l': + if (strcmp(key, "link") == 0) + keybit = F_SLINK; + break; + case 'm': + if (strcmp(key, "md5") == 0 || + strcmp(key, "md5digest") == 0) + keybit = F_MD5; + if (strcmp(key, "mode") == 0) + keybit = F_MODE; + break; + case 'n': + if (strcmp(key, "nlink") == 0) + keybit = F_NLINK; + break; + case 'r': + if (strcmp(key, "resdevice") == 0) { + keybit = F_RESDEV; + } else if (strcmp(key, "ripemd160digest") == 0 || + strcmp(key, "rmd160") == 0 || + strcmp(key, "rmd160digest") == 0) + keybit = F_RMD160; + break; + case 's': + if (strcmp(key, "sha1") == 0 || + strcmp(key, "sha1digest") == 0) + keybit = F_SHA1; + if (strcmp(key, "sha256") == 0 || + strcmp(key, "sha256digest") == 0) + keybit = F_SHA256; + if (strcmp(key, "sha384") == 0 || + strcmp(key, "sha384digest") == 0) + keybit = F_SHA384; + if (strcmp(key, "sha512") == 0 || + strcmp(key, "sha512digest") == 0) + keybit = F_SHA512; + if (strcmp(key, "size") == 0) + keybit = F_SIZE; + break; + case 't': + if (strcmp(key, "time") == 0) + keybit = F_TIME; + else if (strcmp(key, "type") == 0) + keybit = F_TYPE; + break; + case 'u': + if (strcmp(key, "uid") == 0) + keybit = F_UID; + else if (strcmp(key, "uname") == 0) + keybit = F_UNAME; + else if (strcmp(key, "use-set") == 0) { + mtree->output_global_set = (value != NULL)? 1: 0; + return (ARCHIVE_OK); + } + break; + } + if (keybit != 0) { + if (value != NULL) + mtree->keys |= keybit; + else + mtree->keys &= ~keybit; + return (ARCHIVE_OK); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +static int +archive_write_set_format_mtree_default(struct archive *_a, const char *fn) +{ + struct archive_write *a = (struct archive_write *)_a; + struct mtree_writer *mtree; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, fn); + + if (a->format_free != NULL) + (a->format_free)(a); + + if ((mtree = calloc(1, sizeof(*mtree))) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate mtree data"); + return (ARCHIVE_FATAL); + } + + mtree->mtree_entry = NULL; + mtree->first = 1; + memset(&(mtree->set), 0, sizeof(mtree->set)); + mtree->keys = DEFAULT_KEYS; + mtree->dironly = 0; + mtree->indent = 0; + archive_string_init(&mtree->ebuf); + archive_string_init(&mtree->buf); + mtree_entry_register_init(mtree); + a->format_data = mtree; + a->format_free = archive_write_mtree_free; + a->format_name = "mtree"; + a->format_options = archive_write_mtree_options; + a->format_write_header = archive_write_mtree_header; + a->format_close = archive_write_mtree_close; + a->format_write_data = archive_write_mtree_data; + a->format_finish_entry = archive_write_mtree_finish_entry; + a->archive.archive_format = ARCHIVE_FORMAT_MTREE; + a->archive.archive_format_name = "mtree"; + + return (ARCHIVE_OK); +} + +int +archive_write_set_format_mtree(struct archive *_a) +{ + return archive_write_set_format_mtree_default(_a, + "archive_write_set_format_mtree"); +} + +int +archive_write_set_format_mtree_classic(struct archive *_a) +{ + int r; + + r = archive_write_set_format_mtree_default(_a, + "archive_write_set_format_mtree_classic"); + if (r == ARCHIVE_OK) { + struct archive_write *a = (struct archive_write *)_a; + struct mtree_writer *mtree; + + mtree = (struct mtree_writer *)a->format_data; + + /* Set to output a mtree archive in classic format. */ + mtree->classic = 1; + /* Basically, mtree classic format uses '/set' global + * value. */ + mtree->output_global_set = 1; + } + return (r); +} + +static void +sum_init(struct mtree_writer *mtree) +{ + + mtree->compute_sum = 0; + + if (mtree->keys & F_CKSUM) { + mtree->compute_sum |= F_CKSUM; + mtree->crc = 0; + mtree->crc_len = 0; + } +#ifdef ARCHIVE_HAS_MD5 + if (mtree->keys & F_MD5) { + if (archive_md5_init(&mtree->md5ctx) == ARCHIVE_OK) + mtree->compute_sum |= F_MD5; + else + mtree->keys &= ~F_MD5;/* Not supported. */ + } +#endif +#ifdef ARCHIVE_HAS_RMD160 + if (mtree->keys & F_RMD160) { + if (archive_rmd160_init(&mtree->rmd160ctx) == ARCHIVE_OK) + mtree->compute_sum |= F_RMD160; + else + mtree->keys &= ~F_RMD160;/* Not supported. */ + } +#endif +#ifdef ARCHIVE_HAS_SHA1 + if (mtree->keys & F_SHA1) { + if (archive_sha1_init(&mtree->sha1ctx) == ARCHIVE_OK) + mtree->compute_sum |= F_SHA1; + else + mtree->keys &= ~F_SHA1;/* Not supported. */ + } +#endif +#ifdef ARCHIVE_HAS_SHA256 + if (mtree->keys & F_SHA256) { + if (archive_sha256_init(&mtree->sha256ctx) == ARCHIVE_OK) + mtree->compute_sum |= F_SHA256; + else + mtree->keys &= ~F_SHA256;/* Not supported. */ + } +#endif +#ifdef ARCHIVE_HAS_SHA384 + if (mtree->keys & F_SHA384) { + if (archive_sha384_init(&mtree->sha384ctx) == ARCHIVE_OK) + mtree->compute_sum |= F_SHA384; + else + mtree->keys &= ~F_SHA384;/* Not supported. */ + } +#endif +#ifdef ARCHIVE_HAS_SHA512 + if (mtree->keys & F_SHA512) { + if (archive_sha512_init(&mtree->sha512ctx) == ARCHIVE_OK) + mtree->compute_sum |= F_SHA512; + else + mtree->keys &= ~F_SHA512;/* Not supported. */ + } +#endif +} + +static void +sum_update(struct mtree_writer *mtree, const void *buff, size_t n) +{ + if (mtree->compute_sum & F_CKSUM) { + /* + * Compute a POSIX 1003.2 checksum + */ + const unsigned char *p; + size_t nn; + + for (nn = n, p = buff; nn--; ++p) + COMPUTE_CRC(mtree->crc, *p); + mtree->crc_len += n; + } +#ifdef ARCHIVE_HAS_MD5 + if (mtree->compute_sum & F_MD5) + archive_md5_update(&mtree->md5ctx, buff, n); +#endif +#ifdef ARCHIVE_HAS_RMD160 + if (mtree->compute_sum & F_RMD160) + archive_rmd160_update(&mtree->rmd160ctx, buff, n); +#endif +#ifdef ARCHIVE_HAS_SHA1 + if (mtree->compute_sum & F_SHA1) + archive_sha1_update(&mtree->sha1ctx, buff, n); +#endif +#ifdef ARCHIVE_HAS_SHA256 + if (mtree->compute_sum & F_SHA256) + archive_sha256_update(&mtree->sha256ctx, buff, n); +#endif +#ifdef ARCHIVE_HAS_SHA384 + if (mtree->compute_sum & F_SHA384) + archive_sha384_update(&mtree->sha384ctx, buff, n); +#endif +#ifdef ARCHIVE_HAS_SHA512 + if (mtree->compute_sum & F_SHA512) + archive_sha512_update(&mtree->sha512ctx, buff, n); +#endif +} + +static void +sum_final(struct mtree_writer *mtree, struct reg_info *reg) +{ + + if (mtree->compute_sum & F_CKSUM) { + uint64_t len; + /* Include the length of the file. */ + for (len = mtree->crc_len; len != 0; len >>= 8) + COMPUTE_CRC(mtree->crc, len & 0xff); + reg->crc = ~mtree->crc; + } +#ifdef ARCHIVE_HAS_MD5 + if (mtree->compute_sum & F_MD5) + archive_md5_final(&mtree->md5ctx, reg->buf_md5); +#endif +#ifdef ARCHIVE_HAS_RMD160 + if (mtree->compute_sum & F_RMD160) + archive_rmd160_final(&mtree->rmd160ctx, reg->buf_rmd160); +#endif +#ifdef ARCHIVE_HAS_SHA1 + if (mtree->compute_sum & F_SHA1) + archive_sha1_final(&mtree->sha1ctx, reg->buf_sha1); +#endif +#ifdef ARCHIVE_HAS_SHA256 + if (mtree->compute_sum & F_SHA256) + archive_sha256_final(&mtree->sha256ctx, reg->buf_sha256); +#endif +#ifdef ARCHIVE_HAS_SHA384 + if (mtree->compute_sum & F_SHA384) + archive_sha384_final(&mtree->sha384ctx, reg->buf_sha384); +#endif +#ifdef ARCHIVE_HAS_SHA512 + if (mtree->compute_sum & F_SHA512) + archive_sha512_final(&mtree->sha512ctx, reg->buf_sha512); +#endif + /* Save what types of sum are computed. */ + reg->compute_sum = mtree->compute_sum; +} + +#if defined(ARCHIVE_HAS_MD5) || defined(ARCHIVE_HAS_RMD160) || \ + defined(ARCHIVE_HAS_SHA1) || defined(ARCHIVE_HAS_SHA256) || \ + defined(ARCHIVE_HAS_SHA384) || defined(ARCHIVE_HAS_SHA512) +static void +strappend_bin(struct archive_string *s, const unsigned char *bin, int n) +{ + static const char hex[] = "0123456789abcdef"; + int i; + + for (i = 0; i < n; i++) { + archive_strappend_char(s, hex[bin[i] >> 4]); + archive_strappend_char(s, hex[bin[i] & 0x0f]); + } +} +#endif + +static void +sum_write(struct archive_string *str, struct reg_info *reg) +{ + + if (reg->compute_sum & F_CKSUM) { + archive_string_sprintf(str, " cksum=%ju", + (uintmax_t)reg->crc); + } +#ifdef ARCHIVE_HAS_MD5 + if (reg->compute_sum & F_MD5) { + archive_strcat(str, " md5digest="); + strappend_bin(str, reg->buf_md5, sizeof(reg->buf_md5)); + } +#endif +#ifdef ARCHIVE_HAS_RMD160 + if (reg->compute_sum & F_RMD160) { + archive_strcat(str, " rmd160digest="); + strappend_bin(str, reg->buf_rmd160, sizeof(reg->buf_rmd160)); + } +#endif +#ifdef ARCHIVE_HAS_SHA1 + if (reg->compute_sum & F_SHA1) { + archive_strcat(str, " sha1digest="); + strappend_bin(str, reg->buf_sha1, sizeof(reg->buf_sha1)); + } +#endif +#ifdef ARCHIVE_HAS_SHA256 + if (reg->compute_sum & F_SHA256) { + archive_strcat(str, " sha256digest="); + strappend_bin(str, reg->buf_sha256, sizeof(reg->buf_sha256)); + } +#endif +#ifdef ARCHIVE_HAS_SHA384 + if (reg->compute_sum & F_SHA384) { + archive_strcat(str, " sha384digest="); + strappend_bin(str, reg->buf_sha384, sizeof(reg->buf_sha384)); + } +#endif +#ifdef ARCHIVE_HAS_SHA512 + if (reg->compute_sum & F_SHA512) { + archive_strcat(str, " sha512digest="); + strappend_bin(str, reg->buf_sha512, sizeof(reg->buf_sha512)); + } +#endif +} + +static int +mtree_entry_cmp_node(const struct archive_rb_node *n1, + const struct archive_rb_node *n2) +{ + const struct mtree_entry *e1 = (const struct mtree_entry *)n1; + const struct mtree_entry *e2 = (const struct mtree_entry *)n2; + + return (strcmp(e2->basename.s, e1->basename.s)); +} + +static int +mtree_entry_cmp_key(const struct archive_rb_node *n, const void *key) +{ + const struct mtree_entry *e = (const struct mtree_entry *)n; + + return (strcmp((const char *)key, e->basename.s)); +} + +#if defined(_WIN32) || defined(__CYGWIN__) +static int +cleanup_backslash_1(char *p) +{ + int mb, dos; + + mb = dos = 0; + while (*p) { + if (*(unsigned char *)p > 127) + mb = 1; + if (*p == '\\') { + /* If we have not met any multi-byte characters, + * we can replace '\' with '/'. */ + if (!mb) + *p = '/'; + dos = 1; + } + p++; + } + if (!mb || !dos) + return (0); + return (-1); +} + +static void +cleanup_backslash_2(wchar_t *p) +{ + + /* Convert a path-separator from '\' to '/' */ + while (*p != L'\0') { + if (*p == L'\\') + *p = L'/'; + p++; + } +} +#endif + +/* + * Generate a parent directory name and a base name from a pathname. + */ +static int +mtree_entry_setup_filenames(struct archive_write *a, struct mtree_entry *file, + struct archive_entry *entry) +{ + const char *pathname; + char *p, *dirname, *slash; + size_t len; + int ret = ARCHIVE_OK; + + archive_strcpy(&file->pathname, archive_entry_pathname(entry)); +#if defined(_WIN32) || defined(__CYGWIN__) + /* + * Convert a path-separator from '\' to '/' + */ + if (cleanup_backslash_1(file->pathname.s) != 0) { + const wchar_t *wp = archive_entry_pathname_w(entry); + struct archive_wstring ws; + + if (wp != NULL) { + int r; + archive_string_init(&ws); + archive_wstrcpy(&ws, wp); + cleanup_backslash_2(ws.s); + archive_string_empty(&(file->pathname)); + r = archive_string_append_from_wcs(&(file->pathname), + ws.s, ws.length); + archive_wstring_free(&ws); + if (r < 0 && errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + } + } +#else + (void)a; /* UNUSED */ +#endif + pathname = file->pathname.s; + if (strcmp(pathname, ".") == 0) { + archive_strcpy(&file->basename, "."); + return (ARCHIVE_OK); + } + + archive_strcpy(&(file->parentdir), pathname); + + len = file->parentdir.length; + p = dirname = file->parentdir.s; + + /* + * Remove leading '/' and '../' elements + */ + while (*p) { + if (p[0] == '/') { + p++; + len--; + } else if (p[0] != '.') + break; + else if (p[1] == '.' && p[2] == '/') { + p += 3; + len -= 3; + } else + break; + } + if (p != dirname) { + memmove(dirname, p, len+1); + p = dirname; + } + /* + * Remove "/","/." and "/.." elements from tail. + */ + while (len > 0) { + size_t ll = len; + + if (len > 0 && p[len-1] == '/') { + p[len-1] = '\0'; + len--; + } + if (len > 1 && p[len-2] == '/' && p[len-1] == '.') { + p[len-2] = '\0'; + len -= 2; + } + if (len > 2 && p[len-3] == '/' && p[len-2] == '.' && + p[len-1] == '.') { + p[len-3] = '\0'; + len -= 3; + } + if (ll == len) + break; + } + while (*p) { + if (p[0] == '/') { + if (p[1] == '/') + /* Convert '//' --> '/' */ + memmove(p, p+1, strlen(p+1) + 1); + else if (p[1] == '.' && p[2] == '/') + /* Convert '/./' --> '/' */ + memmove(p, p+2, strlen(p+2) + 1); + else if (p[1] == '.' && p[2] == '.' && p[3] == '/') { + /* Convert 'dir/dir1/../dir2/' + * --> 'dir/dir2/' + */ + char *rp = p -1; + while (rp >= dirname) { + if (*rp == '/') + break; + --rp; + } + if (rp > dirname) { + strcpy(rp, p+3); + p = rp; + } else { + strcpy(dirname, p+4); + p = dirname; + } + } else + p++; + } else + p++; + } + p = dirname; + len = strlen(p); + + /* + * Add "./" prefix. + * NOTE: If the pathname does not have a path separator, we have + * to add "./" to the head of the pathname because mtree reader + * will suppose that it is v1(a.k.a classic) mtree format and + * change the directory unexpectedly and so it will make a wrong + * path. + */ + if (strcmp(p, ".") != 0 && strncmp(p, "./", 2) != 0) { + struct archive_string as; + archive_string_init(&as); + archive_strcpy(&as, "./"); + archive_strncat(&as, p, len); + archive_string_empty(&file->parentdir); + archive_string_concat(&file->parentdir, &as); + archive_string_free(&as); + p = file->parentdir.s; + len = archive_strlen(&file->parentdir); + } + + /* + * Find out the position which points the last position of + * path separator('/'). + */ + slash = NULL; + for (; *p != '\0'; p++) { + if (*p == '/') + slash = p; + } + if (slash == NULL) { + /* The pathname doesn't have a parent directory. */ + file->parentdir.length = len; + archive_string_copy(&(file->basename), &(file->parentdir)); + archive_string_empty(&(file->parentdir)); + *file->parentdir.s = '\0'; + return (ret); + } + + /* Make a basename from file->parentdir.s and slash */ + *slash = '\0'; + file->parentdir.length = slash - file->parentdir.s; + archive_strcpy(&(file->basename), slash + 1); + return (ret); +} + +static int +mtree_entry_create_virtual_dir(struct archive_write *a, const char *pathname, + struct mtree_entry **m_entry) +{ + struct archive_entry *entry; + struct mtree_entry *file; + int r; + + entry = archive_entry_new(); + if (entry == NULL) { + *m_entry = NULL; + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + archive_entry_copy_pathname(entry, pathname); + archive_entry_set_mode(entry, AE_IFDIR | 0755); + archive_entry_set_mtime(entry, time(NULL), 0); + + r = mtree_entry_new(a, entry, &file); + archive_entry_free(entry); + if (r < ARCHIVE_WARN) { + *m_entry = NULL; + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + + file->dir_info->virtual = 1; + + *m_entry = file; + return (ARCHIVE_OK); +} + +static void +mtree_entry_register_add(struct mtree_writer *mtree, struct mtree_entry *file) +{ + file->next = NULL; + *mtree->file_list.last = file; + mtree->file_list.last = &(file->next); +} + +static void +mtree_entry_register_init(struct mtree_writer *mtree) +{ + mtree->file_list.first = NULL; + mtree->file_list.last = &(mtree->file_list.first); +} + +static void +mtree_entry_register_free(struct mtree_writer *mtree) +{ + struct mtree_entry *file, *file_next; + + file = mtree->file_list.first; + while (file != NULL) { + file_next = file->next; + mtree_entry_free(file); + file = file_next; + } +} + +static int +mtree_entry_add_child_tail(struct mtree_entry *parent, + struct mtree_entry *child) +{ + child->dir_info->chnext = NULL; + *parent->dir_info->children.last = child; + parent->dir_info->children.last = &(child->dir_info->chnext); + return (1); +} + +/* + * Find a entry from a parent entry with the name. + */ +static struct mtree_entry * +mtree_entry_find_child(struct mtree_entry *parent, const char *child_name) +{ + struct mtree_entry *np; + + if (parent == NULL) + return (NULL); + np = (struct mtree_entry *)__archive_rb_tree_find_node( + &(parent->dir_info->rbtree), child_name); + return (np); +} + +static int +get_path_component(char *name, size_t n, const char *fn) +{ + char *p; + size_t l; + + p = strchr(fn, '/'); + if (p == NULL) { + if ((l = strlen(fn)) == 0) + return (0); + } else + l = p - fn; + if (l > n -1) + return (-1); + memcpy(name, fn, l); + name[l] = '\0'; + + return ((int)l); +} + +/* + * Add a new entry into the tree. + */ +static int +mtree_entry_tree_add(struct archive_write *a, struct mtree_entry **filep) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + char name[_MAX_FNAME];/* Included null terminator size. */ +#elif defined(NAME_MAX) && NAME_MAX >= 255 + char name[NAME_MAX+1]; +#else + char name[256]; +#endif + struct mtree_writer *mtree = (struct mtree_writer *)a->format_data; + struct mtree_entry *dent, *file, *np; + const char *fn, *p; + int l, r; + + file = *filep; + if (file->parentdir.length == 0 && file->basename.length == 1 && + file->basename.s[0] == '.') { + file->parent = file; + if (mtree->root != NULL) { + np = mtree->root; + goto same_entry; + } + mtree->root = file; + mtree_entry_register_add(mtree, file); + return (ARCHIVE_OK); + } + + if (file->parentdir.length == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Internal programming error " + "in generating canonical name for %s", + file->pathname.s); + return (ARCHIVE_FAILED); + } + + fn = p = file->parentdir.s; + + /* + * If the path of the parent directory of `file' entry is + * the same as the path of `cur_dirent', add `file' entry to + * `cur_dirent'. + */ + if (archive_strlen(&(mtree->cur_dirstr)) + == archive_strlen(&(file->parentdir)) && + strcmp(mtree->cur_dirstr.s, fn) == 0) { + if (!__archive_rb_tree_insert_node( + &(mtree->cur_dirent->dir_info->rbtree), + (struct archive_rb_node *)file)) { + /* There is the same name in the tree. */ + np = (struct mtree_entry *)__archive_rb_tree_find_node( + &(mtree->cur_dirent->dir_info->rbtree), + file->basename.s); + goto same_entry; + } + file->parent = mtree->cur_dirent; + mtree_entry_register_add(mtree, file); + return (ARCHIVE_OK); + } + + dent = mtree->root; + for (;;) { + l = get_path_component(name, sizeof(name), fn); + if (l == 0) { + np = NULL; + break; + } + if (l < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "A name buffer is too small"); + return (ARCHIVE_FATAL); + } + if (l == 1 && name[0] == '.' && dent != NULL && + dent == mtree->root) { + fn += l; + if (fn[0] == '/') + fn++; + continue; + } + + np = mtree_entry_find_child(dent, name); + if (np == NULL || fn[0] == '\0') + break; + + /* Find next sub directory. */ + if (!np->dir_info) { + /* NOT Directory! */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "`%s' is not directory, we cannot insert `%s' ", + np->pathname.s, file->pathname.s); + return (ARCHIVE_FAILED); + } + fn += l; + if (fn[0] == '/') + fn++; + dent = np; + } + if (np == NULL) { + /* + * Create virtual parent directories. + */ + while (fn[0] != '\0') { + struct mtree_entry *vp; + struct archive_string as; + + archive_string_init(&as); + archive_strncat(&as, p, fn - p + l); + if (as.s[as.length-1] == '/') { + as.s[as.length-1] = '\0'; + as.length--; + } + r = mtree_entry_create_virtual_dir(a, as.s, &vp); + archive_string_free(&as); + if (r < ARCHIVE_WARN) + return (r); + + if (strcmp(vp->pathname.s, ".") == 0) { + vp->parent = vp; + mtree->root = vp; + } else { + __archive_rb_tree_insert_node( + &(dent->dir_info->rbtree), + (struct archive_rb_node *)vp); + vp->parent = dent; + } + mtree_entry_register_add(mtree, vp); + np = vp; + + fn += l; + if (fn[0] == '/') + fn++; + l = get_path_component(name, sizeof(name), fn); + if (l < 0) { + archive_string_free(&as); + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "A name buffer is too small"); + return (ARCHIVE_FATAL); + } + dent = np; + } + + /* Found out the parent directory where `file' can be + * inserted. */ + mtree->cur_dirent = dent; + archive_string_empty(&(mtree->cur_dirstr)); + archive_string_ensure(&(mtree->cur_dirstr), + archive_strlen(&(dent->parentdir)) + + archive_strlen(&(dent->basename)) + 2); + if (archive_strlen(&(dent->parentdir)) + + archive_strlen(&(dent->basename)) == 0) + mtree->cur_dirstr.s[0] = 0; + else { + if (archive_strlen(&(dent->parentdir)) > 0) { + archive_string_copy(&(mtree->cur_dirstr), + &(dent->parentdir)); + archive_strappend_char( + &(mtree->cur_dirstr), '/'); + } + archive_string_concat(&(mtree->cur_dirstr), + &(dent->basename)); + } + + if (!__archive_rb_tree_insert_node( + &(dent->dir_info->rbtree), + (struct archive_rb_node *)file)) { + np = (struct mtree_entry *)__archive_rb_tree_find_node( + &(dent->dir_info->rbtree), file->basename.s); + goto same_entry; + } + file->parent = dent; + mtree_entry_register_add(mtree, file); + return (ARCHIVE_OK); + } + +same_entry: + /* + * We have already has the entry the filename of which is + * the same. + */ + r = mtree_entry_exchange_same_entry(a, np, file); + if (r < ARCHIVE_WARN) + return (r); + if (np->dir_info) + np->dir_info->virtual = 0; + *filep = np; + mtree_entry_free(file); + return (ARCHIVE_WARN); +} + +static int +mtree_entry_exchange_same_entry(struct archive_write *a, struct mtree_entry *np, + struct mtree_entry *file) +{ + + if ((np->mode & AE_IFMT) != (file->mode & AE_IFMT)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Found duplicate entries `%s' and its file type is " + "different", + np->pathname.s); + return (ARCHIVE_FAILED); + } + + /* Update the existent mtree entry's attributes by the new one's. */ + archive_string_empty(&np->symlink); + archive_string_concat(&np->symlink, &file->symlink); + archive_string_empty(&np->uname); + archive_string_concat(&np->uname, &file->uname); + archive_string_empty(&np->gname); + archive_string_concat(&np->gname, &file->gname); + archive_string_empty(&np->fflags_text); + archive_string_concat(&np->fflags_text, &file->fflags_text); + np->nlink = file->nlink; + np->filetype = file->filetype; + np->mode = file->mode; + np->size = file->size; + np->uid = file->uid; + np->gid = file->gid; + np->fflags_set = file->fflags_set; + np->fflags_clear = file->fflags_clear; + np->mtime = file->mtime; + np->mtime_nsec = file->mtime_nsec; + np->rdevmajor = file->rdevmajor; + np->rdevminor = file->rdevminor; + np->devmajor = file->devmajor; + np->devminor = file->devminor; + np->ino = file->ino; + + return (ARCHIVE_WARN); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_pax.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_pax.c new file mode 100644 index 0000000..a2b2710 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_pax.c @@ -0,0 +1,2044 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2010-2012 Michihiro NAKAJIMA + * Copyright (c) 2016 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_pax.c 201162 2009-12-29 05:47:46Z kientzle $"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_private.h" +#include "archive_write_private.h" +#include "archive_write_set_format_private.h" + +struct sparse_block { + struct sparse_block *next; + int is_hole; + uint64_t offset; + uint64_t remaining; +}; + +struct pax { + uint64_t entry_bytes_remaining; + uint64_t entry_padding; + struct archive_string l_url_encoded_name; + struct archive_string pax_header; + struct archive_string sparse_map; + size_t sparse_map_padding; + struct sparse_block *sparse_list; + struct sparse_block *sparse_tail; + struct archive_string_conv *sconv_utf8; + int opt_binary; + + unsigned flags; +#define WRITE_SCHILY_XATTR (1 << 0) +#define WRITE_LIBARCHIVE_XATTR (1 << 1) +}; + +static void add_pax_attr(struct archive_string *, const char *key, + const char *value); +static void add_pax_attr_binary(struct archive_string *, + const char *key, + const char *value, size_t value_len); +static void add_pax_attr_int(struct archive_string *, + const char *key, int64_t value); +static void add_pax_attr_time(struct archive_string *, + const char *key, int64_t sec, + unsigned long nanos); +static int add_pax_acl(struct archive_write *, + struct archive_entry *, struct pax *, int); +static ssize_t archive_write_pax_data(struct archive_write *, + const void *, size_t); +static int archive_write_pax_close(struct archive_write *); +static int archive_write_pax_free(struct archive_write *); +static int archive_write_pax_finish_entry(struct archive_write *); +static int archive_write_pax_header(struct archive_write *, + struct archive_entry *); +static int archive_write_pax_options(struct archive_write *, + const char *, const char *); +static char *base64_encode(const char *src, size_t len); +static char *build_gnu_sparse_name(char *dest, const char *src); +static char *build_pax_attribute_name(char *dest, const char *src); +static char *build_ustar_entry_name(char *dest, const char *src, + size_t src_length, const char *insert); +static char *format_int(char *dest, int64_t); +static int has_non_ASCII(const char *); +static void sparse_list_clear(struct pax *); +static int sparse_list_add(struct pax *, int64_t, int64_t); +static char *url_encode(const char *in); + +/* + * Set output format to 'restricted pax' format. + * + * This is the same as normal 'pax', but tries to suppress + * the pax header whenever possible. This is the default for + * bsdtar, for instance. + */ +int +archive_write_set_format_pax_restricted(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + int r; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_set_format_pax_restricted"); + + r = archive_write_set_format_pax(&a->archive); + a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED; + a->archive.archive_format_name = "restricted POSIX pax interchange"; + return (r); +} + +/* + * Set output format to 'pax' format. + */ +int +archive_write_set_format_pax(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct pax *pax; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_set_format_pax"); + + if (a->format_free != NULL) + (a->format_free)(a); + + pax = (struct pax *)calloc(1, sizeof(*pax)); + if (pax == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate pax data"); + return (ARCHIVE_FATAL); + } + pax->flags = WRITE_LIBARCHIVE_XATTR | WRITE_SCHILY_XATTR; + + a->format_data = pax; + a->format_name = "pax"; + a->format_options = archive_write_pax_options; + a->format_write_header = archive_write_pax_header; + a->format_write_data = archive_write_pax_data; + a->format_close = archive_write_pax_close; + a->format_free = archive_write_pax_free; + a->format_finish_entry = archive_write_pax_finish_entry; + a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE; + a->archive.archive_format_name = "POSIX pax interchange"; + return (ARCHIVE_OK); +} + +static int +archive_write_pax_options(struct archive_write *a, const char *key, + const char *val) +{ + struct pax *pax = (struct pax *)a->format_data; + int ret = ARCHIVE_FAILED; + + if (strcmp(key, "hdrcharset") == 0) { + /* + * The character-set we can use are defined in + * IEEE Std 1003.1-2001 + */ + if (val == NULL || val[0] == 0) + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "pax: hdrcharset option needs a character-set name"); + else if (strcmp(val, "BINARY") == 0 || + strcmp(val, "binary") == 0) { + /* + * Specify binary mode. We will not convert + * filenames, uname and gname to any charsets. + */ + pax->opt_binary = 1; + ret = ARCHIVE_OK; + } else if (strcmp(val, "UTF-8") == 0) { + /* + * Specify UTF-8 character-set to be used for + * filenames. This is almost the test that + * running platform supports the string conversion. + * Especially libarchive_test needs this trick for + * its test. + */ + pax->sconv_utf8 = archive_string_conversion_to_charset( + &(a->archive), "UTF-8", 0); + if (pax->sconv_utf8 == NULL) + ret = ARCHIVE_FATAL; + else + ret = ARCHIVE_OK; + } else + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "pax: invalid charset name"); + return (ret); + } else if (strcmp(key, "xattrheader") == 0) { + if (val == NULL || val[0] == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "pax: xattrheader requires a value"); + } else if (strcmp(val, "ALL") == 0 || + strcmp(val, "all") == 0) { + pax->flags |= WRITE_LIBARCHIVE_XATTR | WRITE_SCHILY_XATTR; + ret = ARCHIVE_OK; + } else if (strcmp(val, "SCHILY") == 0 || + strcmp(val, "schily") == 0) { + pax->flags |= WRITE_SCHILY_XATTR; + pax->flags &= ~WRITE_LIBARCHIVE_XATTR; + ret = ARCHIVE_OK; + } else if (strcmp(val, "LIBARCHIVE") == 0 || + strcmp(val, "libarchive") == 0) { + pax->flags |= WRITE_LIBARCHIVE_XATTR; + pax->flags &= ~WRITE_SCHILY_XATTR; + ret = ARCHIVE_OK; + } else + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "pax: invalid xattr header name"); + return (ret); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +/* + * Note: This code assumes that 'nanos' has the same sign as 'sec', + * which implies that sec=-1, nanos=200000000 represents -1.2 seconds + * and not -0.8 seconds. This is a pretty pedantic point, as we're + * unlikely to encounter many real files created before Jan 1, 1970, + * much less ones with timestamps recorded to sub-second resolution. + */ +static void +add_pax_attr_time(struct archive_string *as, const char *key, + int64_t sec, unsigned long nanos) +{ + int digit, i; + char *t; + /* + * Note that each byte contributes fewer than 3 base-10 + * digits, so this will always be big enough. + */ + char tmp[1 + 3*sizeof(sec) + 1 + 3*sizeof(nanos)]; + + tmp[sizeof(tmp) - 1] = 0; + t = tmp + sizeof(tmp) - 1; + + /* Skip trailing zeros in the fractional part. */ + for (digit = 0, i = 10; i > 0 && digit == 0; i--) { + digit = nanos % 10; + nanos /= 10; + } + + /* Only format the fraction if it's non-zero. */ + if (i > 0) { + while (i > 0) { + *--t = "0123456789"[digit]; + digit = nanos % 10; + nanos /= 10; + i--; + } + *--t = '.'; + } + t = format_int(t, sec); + + add_pax_attr(as, key, t); +} + +static char * +format_int(char *t, int64_t i) +{ + uint64_t ui; + + if (i < 0) + ui = (i == INT64_MIN) ? (uint64_t)(INT64_MAX) + 1 : (uint64_t)(-i); + else + ui = i; + + do { + *--t = "0123456789"[ui % 10]; + } while (ui /= 10); + if (i < 0) + *--t = '-'; + return (t); +} + +static void +add_pax_attr_int(struct archive_string *as, const char *key, int64_t value) +{ + char tmp[1 + 3 * sizeof(value)]; + + tmp[sizeof(tmp) - 1] = 0; + add_pax_attr(as, key, format_int(tmp + sizeof(tmp) - 1, value)); +} + +/* + * Add a key/value attribute to the pax header. This function handles + * the length field and various other syntactic requirements. + */ +static void +add_pax_attr(struct archive_string *as, const char *key, const char *value) +{ + add_pax_attr_binary(as, key, value, strlen(value)); +} + +/* + * Add a key/value attribute to the pax header. This function handles + * binary values. + */ +static void +add_pax_attr_binary(struct archive_string *as, const char *key, + const char *value, size_t value_len) +{ + int digits, i, len, next_ten; + char tmp[1 + 3 * sizeof(int)]; /* < 3 base-10 digits per byte */ + + /*- + * PAX attributes have the following layout: + * <=> + */ + len = 1 + (int)strlen(key) + 1 + (int)value_len + 1; + + /* + * The field includes the length of the field, so + * computing the correct length is tricky. I start by + * counting the number of base-10 digits in 'len' and + * computing the next higher power of 10. + */ + next_ten = 1; + digits = 0; + i = len; + while (i > 0) { + i = i / 10; + digits++; + next_ten = next_ten * 10; + } + /* + * For example, if string without the length field is 99 + * chars, then adding the 2 digit length "99" will force the + * total length past 100, requiring an extra digit. The next + * statement adjusts for this effect. + */ + if (len + digits >= next_ten) + digits++; + + /* Now, we have the right length so we can build the line. */ + tmp[sizeof(tmp) - 1] = 0; /* Null-terminate the work area. */ + archive_strcat(as, format_int(tmp + sizeof(tmp) - 1, len + digits)); + archive_strappend_char(as, ' '); + archive_strcat(as, key); + archive_strappend_char(as, '='); + archive_array_append(as, value, value_len); + archive_strappend_char(as, '\n'); +} + +static void +archive_write_pax_header_xattr(struct pax *pax, const char *encoded_name, + const void *value, size_t value_len) +{ + struct archive_string s; + char *encoded_value; + + if (pax->flags & WRITE_LIBARCHIVE_XATTR) { + encoded_value = base64_encode((const char *)value, value_len); + + if (encoded_name != NULL && encoded_value != NULL) { + archive_string_init(&s); + archive_strcpy(&s, "LIBARCHIVE.xattr."); + archive_strcat(&s, encoded_name); + add_pax_attr(&(pax->pax_header), s.s, encoded_value); + archive_string_free(&s); + } + free(encoded_value); + } + if (pax->flags & WRITE_SCHILY_XATTR) { + archive_string_init(&s); + archive_strcpy(&s, "SCHILY.xattr."); + archive_strcat(&s, encoded_name); + add_pax_attr_binary(&(pax->pax_header), s.s, value, value_len); + archive_string_free(&s); + } +} + +static int +archive_write_pax_header_xattrs(struct archive_write *a, + struct pax *pax, struct archive_entry *entry) +{ + int i = archive_entry_xattr_reset(entry); + + while (i--) { + const char *name; + const void *value; + char *url_encoded_name = NULL, *encoded_name = NULL; + size_t size; + int r; + + archive_entry_xattr_next(entry, &name, &value, &size); + url_encoded_name = url_encode(name); + if (url_encoded_name != NULL) { + /* Convert narrow-character to UTF-8. */ + r = archive_strcpy_l(&(pax->l_url_encoded_name), + url_encoded_name, pax->sconv_utf8); + free(url_encoded_name); /* Done with this. */ + if (r == 0) + encoded_name = pax->l_url_encoded_name.s; + else if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Linkname"); + return (ARCHIVE_FATAL); + } + } + + archive_write_pax_header_xattr(pax, encoded_name, + value, size); + + } + return (ARCHIVE_OK); +} + +static int +get_entry_hardlink(struct archive_write *a, struct archive_entry *entry, + const char **name, size_t *length, struct archive_string_conv *sc) +{ + int r; + + r = archive_entry_hardlink_l(entry, name, length, sc); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Linkname"); + return (ARCHIVE_FATAL); + } + return (ARCHIVE_WARN); + } + return (ARCHIVE_OK); +} + +static int +get_entry_pathname(struct archive_write *a, struct archive_entry *entry, + const char **name, size_t *length, struct archive_string_conv *sc) +{ + int r; + + r = archive_entry_pathname_l(entry, name, length, sc); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Pathname"); + return (ARCHIVE_FATAL); + } + return (ARCHIVE_WARN); + } + return (ARCHIVE_OK); +} + +static int +get_entry_uname(struct archive_write *a, struct archive_entry *entry, + const char **name, size_t *length, struct archive_string_conv *sc) +{ + int r; + + r = archive_entry_uname_l(entry, name, length, sc); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Uname"); + return (ARCHIVE_FATAL); + } + return (ARCHIVE_WARN); + } + return (ARCHIVE_OK); +} + +static int +get_entry_gname(struct archive_write *a, struct archive_entry *entry, + const char **name, size_t *length, struct archive_string_conv *sc) +{ + int r; + + r = archive_entry_gname_l(entry, name, length, sc); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Gname"); + return (ARCHIVE_FATAL); + } + return (ARCHIVE_WARN); + } + return (ARCHIVE_OK); +} + +static int +get_entry_symlink(struct archive_write *a, struct archive_entry *entry, + const char **name, size_t *length, struct archive_string_conv *sc) +{ + int r; + + r = archive_entry_symlink_l(entry, name, length, sc); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Linkname"); + return (ARCHIVE_FATAL); + } + return (ARCHIVE_WARN); + } + return (ARCHIVE_OK); +} + +/* Add ACL to pax header */ +static int +add_pax_acl(struct archive_write *a, + struct archive_entry *entry, struct pax *pax, int flags) +{ + char *p; + const char *attr; + int acl_types; + + acl_types = archive_entry_acl_types(entry); + + if ((acl_types & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) + attr = "SCHILY.acl.ace"; + else if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) + attr = "SCHILY.acl.access"; + else if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) + attr = "SCHILY.acl.default"; + else + return (ARCHIVE_FATAL); + + p = archive_entry_acl_to_text_l(entry, NULL, flags, pax->sconv_utf8); + if (p == NULL) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, "%s %s", + "Can't allocate memory for ", attr); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "%s %s %s", + "Can't translate ", attr, " to UTF-8"); + return(ARCHIVE_WARN); + } + + if (*p != '\0') { + add_pax_attr(&(pax->pax_header), + attr, p); + } + free(p); + return(ARCHIVE_OK); +} + +/* + * TODO: Consider adding 'comment' and 'charset' fields to + * archive_entry so that clients can specify them. Also, consider + * adding generic key/value tags so clients can add arbitrary + * key/value data. + * + * TODO: Break up this 700-line function!!!! Yowza! + */ +static int +archive_write_pax_header(struct archive_write *a, + struct archive_entry *entry_original) +{ + struct archive_entry *entry_main; + const char *p; + const char *suffix; + int need_extension, r, ret; + int acl_types; + int sparse_count; + uint64_t sparse_total, real_size; + struct pax *pax; + const char *hardlink; + const char *path = NULL, *linkpath = NULL; + const char *uname = NULL, *gname = NULL; + const void *mac_metadata; + size_t mac_metadata_size; + struct archive_string_conv *sconv; + size_t hardlink_length, path_length, linkpath_length; + size_t uname_length, gname_length; + + char paxbuff[512]; + char ustarbuff[512]; + char ustar_entry_name[256]; + char pax_entry_name[256]; + char gnu_sparse_name[256]; + struct archive_string entry_name; + + ret = ARCHIVE_OK; + need_extension = 0; + pax = (struct pax *)a->format_data; + + /* Sanity check. */ + if (archive_entry_pathname(entry_original) == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't record entry in tar file without pathname"); + return (ARCHIVE_FAILED); + } + + /* + * Choose a header encoding. + */ + if (pax->opt_binary) + sconv = NULL;/* Binary mode. */ + else { + /* Header encoding is UTF-8. */ + if (pax->sconv_utf8 == NULL) { + /* Initialize the string conversion object + * we must need */ + pax->sconv_utf8 = archive_string_conversion_to_charset( + &(a->archive), "UTF-8", 1); + if (pax->sconv_utf8 == NULL) + /* Couldn't allocate memory */ + return (ARCHIVE_FAILED); + } + sconv = pax->sconv_utf8; + } + + r = get_entry_hardlink(a, entry_original, &hardlink, + &hardlink_length, sconv); + if (r == ARCHIVE_FATAL) + return (r); + else if (r != ARCHIVE_OK) { + r = get_entry_hardlink(a, entry_original, &hardlink, + &hardlink_length, NULL); + if (r == ARCHIVE_FATAL) + return (r); + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate linkname '%s' to %s", hardlink, + archive_string_conversion_charset_name(sconv)); + ret = ARCHIVE_WARN; + sconv = NULL;/* The header charset switches to binary mode. */ + } + + /* Make sure this is a type of entry that we can handle here */ + if (hardlink == NULL) { + switch (archive_entry_filetype(entry_original)) { + case AE_IFBLK: + case AE_IFCHR: + case AE_IFIFO: + case AE_IFLNK: + case AE_IFREG: + break; + case AE_IFDIR: + { + /* + * Ensure a trailing '/'. Modify the original + * entry so the client sees the change. + */ +#if defined(_WIN32) && !defined(__CYGWIN__) + const wchar_t *wp; + + wp = archive_entry_pathname_w(entry_original); + if (wp != NULL && wp[wcslen(wp) -1] != L'/') { + struct archive_wstring ws; + + archive_string_init(&ws); + path_length = wcslen(wp); + if (archive_wstring_ensure(&ws, + path_length + 2) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate pax data"); + archive_wstring_free(&ws); + return(ARCHIVE_FATAL); + } + /* Should we keep '\' ? */ + if (wp[path_length -1] == L'\\') + path_length--; + archive_wstrncpy(&ws, wp, path_length); + archive_wstrappend_wchar(&ws, L'/'); + archive_entry_copy_pathname_w( + entry_original, ws.s); + archive_wstring_free(&ws); + p = NULL; + } else +#endif + p = archive_entry_pathname(entry_original); + /* + * On Windows, this is a backup operation just in + * case getting WCS failed. On POSIX, this is a + * normal operation. + */ + if (p != NULL && p[0] != '\0' && p[strlen(p) - 1] != '/') { + struct archive_string as; + + archive_string_init(&as); + path_length = strlen(p); + if (archive_string_ensure(&as, + path_length + 2) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate pax data"); + archive_string_free(&as); + return(ARCHIVE_FATAL); + } +#if defined(_WIN32) && !defined(__CYGWIN__) + /* NOTE: This might break the pathname + * if the current code page is CP932 and + * the pathname includes a character '\' + * as a part of its multibyte pathname. */ + if (p[strlen(p) -1] == '\\') + path_length--; + else +#endif + archive_strncpy(&as, p, path_length); + archive_strappend_char(&as, '/'); + archive_entry_copy_pathname( + entry_original, as.s); + archive_string_free(&as); + } + break; + } + default: /* AE_IFSOCK and unknown */ + __archive_write_entry_filetype_unsupported( + &a->archive, entry_original, "pax"); + return (ARCHIVE_FAILED); + } + } + + /* + * If Mac OS metadata blob is here, recurse to write that + * as a separate entry. This is really a pretty poor design: + * In particular, it doubles the overhead for long filenames. + * TODO: Help Apple folks design something better and figure + * out how to transition from this legacy format. + * + * Note that this code is present on every platform; clients + * on non-Mac are unlikely to ever provide this data, but + * applications that copy entries from one archive to another + * should not lose data just because the local filesystem + * can't store it. + */ + mac_metadata = + archive_entry_mac_metadata(entry_original, &mac_metadata_size); + if (mac_metadata != NULL) { + const char *oname; + char *name, *bname; + size_t name_length; + struct archive_entry *extra = archive_entry_new2(&a->archive); + + oname = archive_entry_pathname(entry_original); + name_length = strlen(oname); + name = malloc(name_length + 3); + if (name == NULL || extra == NULL) { + /* XXX error message */ + archive_entry_free(extra); + free(name); + return (ARCHIVE_FAILED); + } + strcpy(name, oname); + /* Find last '/'; strip trailing '/' characters */ + bname = strrchr(name, '/'); + while (bname != NULL && bname[1] == '\0') { + *bname = '\0'; + bname = strrchr(name, '/'); + } + if (bname == NULL) { + memmove(name + 2, name, name_length + 1); + memmove(name, "._", 2); + } else { + bname += 1; + memmove(bname + 2, bname, strlen(bname) + 1); + memmove(bname, "._", 2); + } + archive_entry_copy_pathname(extra, name); + free(name); + + archive_entry_set_size(extra, mac_metadata_size); + archive_entry_set_filetype(extra, AE_IFREG); + archive_entry_set_perm(extra, + archive_entry_perm(entry_original)); + archive_entry_set_mtime(extra, + archive_entry_mtime(entry_original), + archive_entry_mtime_nsec(entry_original)); + archive_entry_set_gid(extra, + archive_entry_gid(entry_original)); + archive_entry_set_gname(extra, + archive_entry_gname(entry_original)); + archive_entry_set_uid(extra, + archive_entry_uid(entry_original)); + archive_entry_set_uname(extra, + archive_entry_uname(entry_original)); + + /* Recurse to write the special copyfile entry. */ + r = archive_write_pax_header(a, extra); + archive_entry_free(extra); + if (r < ARCHIVE_WARN) + return (r); + if (r < ret) + ret = r; + r = (int)archive_write_pax_data(a, mac_metadata, + mac_metadata_size); + if (r < ARCHIVE_WARN) + return (r); + if (r < ret) + ret = r; + r = archive_write_pax_finish_entry(a); + if (r < ARCHIVE_WARN) + return (r); + if (r < ret) + ret = r; + } + + /* Copy entry so we can modify it as needed. */ +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Make sure the path separators in pathname, hardlink and symlink + * are all slash '/', not the Windows path separator '\'. */ + entry_main = __la_win_entry_in_posix_pathseparator(entry_original); + if (entry_main == entry_original) + entry_main = archive_entry_clone(entry_original); +#else + entry_main = archive_entry_clone(entry_original); +#endif + if (entry_main == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate pax data"); + return(ARCHIVE_FATAL); + } + archive_string_empty(&(pax->pax_header)); /* Blank our work area. */ + archive_string_empty(&(pax->sparse_map)); + sparse_total = 0; + sparse_list_clear(pax); + + if (hardlink == NULL && + archive_entry_filetype(entry_main) == AE_IFREG) + sparse_count = archive_entry_sparse_reset(entry_main); + else + sparse_count = 0; + if (sparse_count) { + int64_t offset, length, last_offset = 0; + /* Get the last entry of sparse block. */ + while (archive_entry_sparse_next( + entry_main, &offset, &length) == ARCHIVE_OK) + last_offset = offset + length; + + /* If the last sparse block does not reach the end of file, + * We have to add a empty sparse block as the last entry to + * manage storing file data. */ + if (last_offset < archive_entry_size(entry_main)) + archive_entry_sparse_add_entry(entry_main, + archive_entry_size(entry_main), 0); + sparse_count = archive_entry_sparse_reset(entry_main); + } + + /* + * First, check the name fields and see if any of them + * require binary coding. If any of them does, then all of + * them do. + */ + r = get_entry_pathname(a, entry_main, &path, &path_length, sconv); + if (r == ARCHIVE_FATAL) { + archive_entry_free(entry_main); + return (r); + } else if (r != ARCHIVE_OK) { + r = get_entry_pathname(a, entry_main, &path, + &path_length, NULL); + if (r == ARCHIVE_FATAL) { + archive_entry_free(entry_main); + return (r); + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate pathname '%s' to %s", path, + archive_string_conversion_charset_name(sconv)); + ret = ARCHIVE_WARN; + sconv = NULL;/* The header charset switches to binary mode. */ + } + r = get_entry_uname(a, entry_main, &uname, &uname_length, sconv); + if (r == ARCHIVE_FATAL) { + archive_entry_free(entry_main); + return (r); + } else if (r != ARCHIVE_OK) { + r = get_entry_uname(a, entry_main, &uname, &uname_length, NULL); + if (r == ARCHIVE_FATAL) { + archive_entry_free(entry_main); + return (r); + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate uname '%s' to %s", uname, + archive_string_conversion_charset_name(sconv)); + ret = ARCHIVE_WARN; + sconv = NULL;/* The header charset switches to binary mode. */ + } + r = get_entry_gname(a, entry_main, &gname, &gname_length, sconv); + if (r == ARCHIVE_FATAL) { + archive_entry_free(entry_main); + return (r); + } else if (r != ARCHIVE_OK) { + r = get_entry_gname(a, entry_main, &gname, &gname_length, NULL); + if (r == ARCHIVE_FATAL) { + archive_entry_free(entry_main); + return (r); + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate gname '%s' to %s", gname, + archive_string_conversion_charset_name(sconv)); + ret = ARCHIVE_WARN; + sconv = NULL;/* The header charset switches to binary mode. */ + } + linkpath = hardlink; + linkpath_length = hardlink_length; + if (linkpath == NULL) { + r = get_entry_symlink(a, entry_main, &linkpath, + &linkpath_length, sconv); + if (r == ARCHIVE_FATAL) { + archive_entry_free(entry_main); + return (r); + } else if (r != ARCHIVE_OK) { + r = get_entry_symlink(a, entry_main, &linkpath, + &linkpath_length, NULL); + if (r == ARCHIVE_FATAL) { + archive_entry_free(entry_main); + return (r); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate linkname '%s' to %s", linkpath, + archive_string_conversion_charset_name(sconv)); + ret = ARCHIVE_WARN; + sconv = NULL; + } + } + + /* If any string conversions failed, get all attributes + * in binary-mode. */ + if (sconv == NULL && !pax->opt_binary) { + if (hardlink != NULL) { + r = get_entry_hardlink(a, entry_main, &hardlink, + &hardlink_length, NULL); + if (r == ARCHIVE_FATAL) { + archive_entry_free(entry_main); + return (r); + } + linkpath = hardlink; + linkpath_length = hardlink_length; + } + r = get_entry_pathname(a, entry_main, &path, + &path_length, NULL); + if (r == ARCHIVE_FATAL) { + archive_entry_free(entry_main); + return (r); + } + r = get_entry_uname(a, entry_main, &uname, &uname_length, NULL); + if (r == ARCHIVE_FATAL) { + archive_entry_free(entry_main); + return (r); + } + r = get_entry_gname(a, entry_main, &gname, &gname_length, NULL); + if (r == ARCHIVE_FATAL) { + archive_entry_free(entry_main); + return (r); + } + } + + /* Store the header encoding first, to be nice to readers. */ + if (sconv == NULL) + add_pax_attr(&(pax->pax_header), "hdrcharset", "BINARY"); + + + /* + * If name is too long, or has non-ASCII characters, add + * 'path' to pax extended attrs. (Note that an unconvertible + * name must have non-ASCII characters.) + */ + if (has_non_ASCII(path)) { + /* We have non-ASCII characters. */ + add_pax_attr(&(pax->pax_header), "path", path); + archive_entry_set_pathname(entry_main, + build_ustar_entry_name(ustar_entry_name, + path, path_length, NULL)); + need_extension = 1; + } else { + /* We have an all-ASCII path; we'd like to just store + * it in the ustar header if it will fit. Yes, this + * duplicates some of the logic in + * archive_write_set_format_ustar.c + */ + if (path_length <= 100) { + /* Fits in the old 100-char tar name field. */ + } else { + /* Find largest suffix that will fit. */ + /* Note: strlen() > 100, so strlen() - 100 - 1 >= 0 */ + suffix = strchr(path + path_length - 100 - 1, '/'); + /* Don't attempt an empty prefix. */ + if (suffix == path) + suffix = strchr(suffix + 1, '/'); + /* We can put it in the ustar header if it's + * all ASCII and it's either <= 100 characters + * or can be split at a '/' into a prefix <= + * 155 chars and a suffix <= 100 chars. (Note + * the strchr() above will return NULL exactly + * when the path can't be split.) + */ + if (suffix == NULL /* Suffix > 100 chars. */ + || suffix[1] == '\0' /* empty suffix */ + || suffix - path > 155) /* Prefix > 155 chars */ + { + add_pax_attr(&(pax->pax_header), "path", path); + archive_entry_set_pathname(entry_main, + build_ustar_entry_name(ustar_entry_name, + path, path_length, NULL)); + need_extension = 1; + } + } + } + + if (linkpath != NULL) { + /* If link name is too long or has non-ASCII characters, add + * 'linkpath' to pax extended attrs. */ + if (linkpath_length > 100 || has_non_ASCII(linkpath)) { + add_pax_attr(&(pax->pax_header), "linkpath", linkpath); + if (linkpath_length > 100) { + if (hardlink != NULL) + archive_entry_set_hardlink(entry_main, + "././@LongHardLink"); + else + archive_entry_set_symlink(entry_main, + "././@LongSymLink"); + } + need_extension = 1; + } + } + /* Save a pathname since it will be renamed if `entry_main` has + * sparse blocks. */ + archive_string_init(&entry_name); + archive_strcpy(&entry_name, archive_entry_pathname(entry_main)); + + /* If file size is too large, add 'size' to pax extended attrs. */ + if (archive_entry_size(entry_main) >= (((int64_t)1) << 33)) { + add_pax_attr_int(&(pax->pax_header), "size", + archive_entry_size(entry_main)); + need_extension = 1; + } + + /* If numeric GID is too large, add 'gid' to pax extended attrs. */ + if ((unsigned int)archive_entry_gid(entry_main) >= (1 << 18)) { + add_pax_attr_int(&(pax->pax_header), "gid", + archive_entry_gid(entry_main)); + need_extension = 1; + } + + /* If group name is too large or has non-ASCII characters, add + * 'gname' to pax extended attrs. */ + if (gname != NULL) { + if (gname_length > 31 || has_non_ASCII(gname)) { + add_pax_attr(&(pax->pax_header), "gname", gname); + need_extension = 1; + } + } + + /* If numeric UID is too large, add 'uid' to pax extended attrs. */ + if ((unsigned int)archive_entry_uid(entry_main) >= (1 << 18)) { + add_pax_attr_int(&(pax->pax_header), "uid", + archive_entry_uid(entry_main)); + need_extension = 1; + } + + /* Add 'uname' to pax extended attrs if necessary. */ + if (uname != NULL) { + if (uname_length > 31 || has_non_ASCII(uname)) { + add_pax_attr(&(pax->pax_header), "uname", uname); + need_extension = 1; + } + } + + /* + * POSIX/SUSv3 doesn't provide a standard key for large device + * numbers. I use the same keys here that Joerg Schilling + * used for 'star.' (Which, somewhat confusingly, are called + * "devXXX" even though they code "rdev" values.) No doubt, + * other implementations use other keys. Note that there's no + * reason we can't write the same information into a number of + * different keys. + * + * Of course, this is only needed for block or char device entries. + */ + if (archive_entry_filetype(entry_main) == AE_IFBLK + || archive_entry_filetype(entry_main) == AE_IFCHR) { + /* + * If rdevmajor is too large, add 'SCHILY.devmajor' to + * extended attributes. + */ + int rdevmajor, rdevminor; + rdevmajor = archive_entry_rdevmajor(entry_main); + rdevminor = archive_entry_rdevminor(entry_main); + if (rdevmajor >= (1 << 18)) { + add_pax_attr_int(&(pax->pax_header), "SCHILY.devmajor", + rdevmajor); + /* + * Non-strict formatting below means we don't + * have to truncate here. Not truncating improves + * the chance that some more modern tar archivers + * (such as GNU tar 1.13) can restore the full + * value even if they don't understand the pax + * extended attributes. See my rant below about + * file size fields for additional details. + */ + /* archive_entry_set_rdevmajor(entry_main, + rdevmajor & ((1 << 18) - 1)); */ + need_extension = 1; + } + + /* + * If devminor is too large, add 'SCHILY.devminor' to + * extended attributes. + */ + if (rdevminor >= (1 << 18)) { + add_pax_attr_int(&(pax->pax_header), "SCHILY.devminor", + rdevminor); + /* Truncation is not necessary here, either. */ + /* archive_entry_set_rdevminor(entry_main, + rdevminor & ((1 << 18) - 1)); */ + need_extension = 1; + } + } + + /* + * Technically, the mtime field in the ustar header can + * support 33 bits, but many platforms use signed 32-bit time + * values. The cutoff of 0x7fffffff here is a compromise. + * Yes, this check is duplicated just below; this helps to + * avoid writing an mtime attribute just to handle a + * high-resolution timestamp in "restricted pax" mode. + */ + if (!need_extension && + ((archive_entry_mtime(entry_main) < 0) + || (archive_entry_mtime(entry_main) >= 0x7fffffff))) + need_extension = 1; + + /* I use a star-compatible file flag attribute. */ + p = archive_entry_fflags_text(entry_main); + if (!need_extension && p != NULL && *p != '\0') + need_extension = 1; + + /* If there are extended attributes, we need an extension */ + if (!need_extension && archive_entry_xattr_count(entry_original) > 0) + need_extension = 1; + + /* If there are sparse info, we need an extension */ + if (!need_extension && sparse_count > 0) + need_extension = 1; + + acl_types = archive_entry_acl_types(entry_original); + + /* If there are any ACL entries, we need an extension */ + if (!need_extension && acl_types != 0) + need_extension = 1; + + /* If the symlink type is defined, we need an extension */ + if (!need_extension && archive_entry_symlink_type(entry_main) > 0) + need_extension = 1; + + /* + * Libarchive used to include these in extended headers for + * restricted pax format, but that confused people who + * expected ustar-like time semantics. So now we only include + * them in full pax format. + */ + if (a->archive.archive_format != ARCHIVE_FORMAT_TAR_PAX_RESTRICTED) { + if (archive_entry_ctime(entry_main) != 0 || + archive_entry_ctime_nsec(entry_main) != 0) + add_pax_attr_time(&(pax->pax_header), "ctime", + archive_entry_ctime(entry_main), + archive_entry_ctime_nsec(entry_main)); + + if (archive_entry_atime(entry_main) != 0 || + archive_entry_atime_nsec(entry_main) != 0) + add_pax_attr_time(&(pax->pax_header), "atime", + archive_entry_atime(entry_main), + archive_entry_atime_nsec(entry_main)); + + /* Store birth/creationtime only if it's earlier than mtime */ + if (archive_entry_birthtime_is_set(entry_main) && + archive_entry_birthtime(entry_main) + < archive_entry_mtime(entry_main)) + add_pax_attr_time(&(pax->pax_header), + "LIBARCHIVE.creationtime", + archive_entry_birthtime(entry_main), + archive_entry_birthtime_nsec(entry_main)); + } + + /* + * The following items are handled differently in "pax + * restricted" format. In particular, in "pax restricted" + * format they won't be added unless need_extension is + * already set (we're already generating an extended header, so + * may as well include these). + */ + if (a->archive.archive_format != ARCHIVE_FORMAT_TAR_PAX_RESTRICTED || + need_extension) { + if (archive_entry_mtime(entry_main) < 0 || + archive_entry_mtime(entry_main) >= 0x7fffffff || + archive_entry_mtime_nsec(entry_main) != 0) + add_pax_attr_time(&(pax->pax_header), "mtime", + archive_entry_mtime(entry_main), + archive_entry_mtime_nsec(entry_main)); + + /* I use a star-compatible file flag attribute. */ + p = archive_entry_fflags_text(entry_main); + if (p != NULL && *p != '\0') + add_pax_attr(&(pax->pax_header), "SCHILY.fflags", p); + + /* I use star-compatible ACL attributes. */ + if ((acl_types & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + ret = add_pax_acl(a, entry_original, pax, + ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID | + ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA | + ARCHIVE_ENTRY_ACL_STYLE_COMPACT); + if (ret == ARCHIVE_FATAL) { + archive_entry_free(entry_main); + archive_string_free(&entry_name); + return (ARCHIVE_FATAL); + } + } + if (acl_types & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) { + ret = add_pax_acl(a, entry_original, pax, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS | + ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID | + ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA); + if (ret == ARCHIVE_FATAL) { + archive_entry_free(entry_main); + archive_string_free(&entry_name); + return (ARCHIVE_FATAL); + } + } + if (acl_types & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) { + ret = add_pax_acl(a, entry_original, pax, + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT | + ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID | + ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA); + if (ret == ARCHIVE_FATAL) { + archive_entry_free(entry_main); + archive_string_free(&entry_name); + return (ARCHIVE_FATAL); + } + } + + /* We use GNU-tar-compatible sparse attributes. */ + if (sparse_count > 0) { + int64_t soffset, slength; + + add_pax_attr_int(&(pax->pax_header), + "GNU.sparse.major", 1); + add_pax_attr_int(&(pax->pax_header), + "GNU.sparse.minor", 0); + /* + * Make sure to store the original path, since + * truncation to ustar limit happened already. + */ + add_pax_attr(&(pax->pax_header), + "GNU.sparse.name", path); + add_pax_attr_int(&(pax->pax_header), + "GNU.sparse.realsize", + archive_entry_size(entry_main)); + + /* Rename the file name which will be used for + * ustar header to a special name, which GNU + * PAX Format 1.0 requires */ + archive_entry_set_pathname(entry_main, + build_gnu_sparse_name(gnu_sparse_name, + entry_name.s)); + + /* + * - Make a sparse map, which will precede a file data. + * - Get the total size of available data of sparse. + */ + archive_string_sprintf(&(pax->sparse_map), "%d\n", + sparse_count); + while (archive_entry_sparse_next(entry_main, + &soffset, &slength) == ARCHIVE_OK) { + archive_string_sprintf(&(pax->sparse_map), + "%jd\n%jd\n", + (intmax_t)soffset, + (intmax_t)slength); + sparse_total += slength; + if (sparse_list_add(pax, soffset, slength) + != ARCHIVE_OK) { + archive_set_error(&a->archive, + ENOMEM, + "Can't allocate memory"); + archive_entry_free(entry_main); + archive_string_free(&entry_name); + return (ARCHIVE_FATAL); + } + } + } + + /* Store extended attributes */ + if (archive_write_pax_header_xattrs(a, pax, entry_original) + == ARCHIVE_FATAL) { + archive_entry_free(entry_main); + archive_string_free(&entry_name); + return (ARCHIVE_FATAL); + } + + /* Store extended symlink information */ + if (archive_entry_symlink_type(entry_main) == + AE_SYMLINK_TYPE_FILE) { + add_pax_attr(&(pax->pax_header), + "LIBARCHIVE.symlinktype", "file"); + } else if (archive_entry_symlink_type(entry_main) == + AE_SYMLINK_TYPE_DIRECTORY) { + add_pax_attr(&(pax->pax_header), + "LIBARCHIVE.symlinktype", "dir"); + } + } + + /* Only regular files have data. */ + if (archive_entry_filetype(entry_main) != AE_IFREG) + archive_entry_set_size(entry_main, 0); + + /* + * Pax-restricted does not store data for hardlinks, in order + * to improve compatibility with ustar. + */ + if (a->archive.archive_format != ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE && + hardlink != NULL) + archive_entry_set_size(entry_main, 0); + + /* + * XXX Full pax interchange format does permit a hardlink + * entry to have data associated with it. I'm not supporting + * that here because the client expects me to tell them whether + * or not this format expects data for hardlinks. If I + * don't check here, then every pax archive will end up with + * duplicated data for hardlinks. Someday, there may be + * need to select this behavior, in which case the following + * will need to be revisited. XXX + */ + if (hardlink != NULL) + archive_entry_set_size(entry_main, 0); + + /* Save a real file size. */ + real_size = archive_entry_size(entry_main); + /* + * Overwrite a file size by the total size of sparse blocks and + * the size of sparse map info. That file size is the length of + * the data, which we will exactly store into an archive file. + */ + if (archive_strlen(&(pax->sparse_map))) { + size_t mapsize = archive_strlen(&(pax->sparse_map)); + pax->sparse_map_padding = 0x1ff & (-(ssize_t)mapsize); + archive_entry_set_size(entry_main, + mapsize + pax->sparse_map_padding + sparse_total); + } + + /* Format 'ustar' header for main entry. + * + * The trouble with file size: If the reader can't understand + * the file size, they may not be able to locate the next + * entry and the rest of the archive is toast. Pax-compliant + * readers are supposed to ignore the file size in the main + * header, so the question becomes how to maximize portability + * for readers that don't support pax attribute extensions. + * For maximum compatibility, I permit numeric extensions in + * the main header so that the file size stored will always be + * correct, even if it's in a format that only some + * implementations understand. The technique used here is: + * + * a) If possible, follow the standard exactly. This handles + * files up to 8 gigabytes minus 1. + * + * b) If that fails, try octal but omit the field terminator. + * That handles files up to 64 gigabytes minus 1. + * + * c) Otherwise, use base-256 extensions. That handles files + * up to 2^63 in this implementation, with the potential to + * go up to 2^94. That should hold us for a while. ;-) + * + * The non-strict formatter uses similar logic for other + * numeric fields, though they're less critical. + */ + if (__archive_write_format_header_ustar(a, ustarbuff, entry_main, -1, 0, + NULL) == ARCHIVE_FATAL) { + archive_entry_free(entry_main); + archive_string_free(&entry_name); + return (ARCHIVE_FATAL); + } + + /* If we built any extended attributes, write that entry first. */ + if (archive_strlen(&(pax->pax_header)) > 0) { + struct archive_entry *pax_attr_entry; + time_t s; + int64_t uid, gid; + int mode; + + pax_attr_entry = archive_entry_new2(&a->archive); + p = entry_name.s; + archive_entry_set_pathname(pax_attr_entry, + build_pax_attribute_name(pax_entry_name, p)); + archive_entry_set_size(pax_attr_entry, + archive_strlen(&(pax->pax_header))); + /* Copy uid/gid (but clip to ustar limits). */ + uid = archive_entry_uid(entry_main); + if (uid >= 1 << 18) + uid = (1 << 18) - 1; + archive_entry_set_uid(pax_attr_entry, uid); + gid = archive_entry_gid(entry_main); + if (gid >= 1 << 18) + gid = (1 << 18) - 1; + archive_entry_set_gid(pax_attr_entry, gid); + /* Copy mode over (but not setuid/setgid bits) */ + mode = archive_entry_mode(entry_main); +#ifdef S_ISUID + mode &= ~S_ISUID; +#endif +#ifdef S_ISGID + mode &= ~S_ISGID; +#endif +#ifdef S_ISVTX + mode &= ~S_ISVTX; +#endif + archive_entry_set_mode(pax_attr_entry, mode); + + /* Copy uname/gname. */ + archive_entry_set_uname(pax_attr_entry, + archive_entry_uname(entry_main)); + archive_entry_set_gname(pax_attr_entry, + archive_entry_gname(entry_main)); + + /* Copy mtime, but clip to ustar limits. */ + s = archive_entry_mtime(entry_main); + if (s < 0) { s = 0; } + if (s >= 0x7fffffff) { s = 0x7fffffff; } + archive_entry_set_mtime(pax_attr_entry, s, 0); + + /* Standard ustar doesn't support atime. */ + archive_entry_set_atime(pax_attr_entry, 0, 0); + + /* Standard ustar doesn't support ctime. */ + archive_entry_set_ctime(pax_attr_entry, 0, 0); + + r = __archive_write_format_header_ustar(a, paxbuff, + pax_attr_entry, 'x', 1, NULL); + + archive_entry_free(pax_attr_entry); + + /* Note that the 'x' header shouldn't ever fail to format */ + if (r < ARCHIVE_WARN) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "archive_write_pax_header: " + "'x' header failed?! This can't happen.\n"); + archive_entry_free(entry_main); + archive_string_free(&entry_name); + return (ARCHIVE_FATAL); + } else if (r < ret) + ret = r; + r = __archive_write_output(a, paxbuff, 512); + if (r != ARCHIVE_OK) { + sparse_list_clear(pax); + pax->entry_bytes_remaining = 0; + pax->entry_padding = 0; + archive_entry_free(entry_main); + archive_string_free(&entry_name); + return (ARCHIVE_FATAL); + } + + pax->entry_bytes_remaining = archive_strlen(&(pax->pax_header)); + pax->entry_padding = + 0x1ff & (-(int64_t)pax->entry_bytes_remaining); + + r = __archive_write_output(a, pax->pax_header.s, + archive_strlen(&(pax->pax_header))); + if (r != ARCHIVE_OK) { + /* If a write fails, we're pretty much toast. */ + archive_entry_free(entry_main); + archive_string_free(&entry_name); + return (ARCHIVE_FATAL); + } + /* Pad out the end of the entry. */ + r = __archive_write_nulls(a, (size_t)pax->entry_padding); + if (r != ARCHIVE_OK) { + /* If a write fails, we're pretty much toast. */ + archive_entry_free(entry_main); + archive_string_free(&entry_name); + return (ARCHIVE_FATAL); + } + pax->entry_bytes_remaining = pax->entry_padding = 0; + } + + /* Write the header for main entry. */ + r = __archive_write_output(a, ustarbuff, 512); + if (r != ARCHIVE_OK) { + archive_entry_free(entry_main); + archive_string_free(&entry_name); + return (r); + } + + /* + * Inform the client of the on-disk size we're using, so + * they can avoid unnecessarily writing a body for something + * that we're just going to ignore. + */ + archive_entry_set_size(entry_original, real_size); + if (pax->sparse_list == NULL && real_size > 0) { + /* This is not a sparse file but we handle its data as + * a sparse block. */ + sparse_list_add(pax, 0, real_size); + sparse_total = real_size; + } + pax->entry_padding = 0x1ff & (-(int64_t)sparse_total); + archive_entry_free(entry_main); + archive_string_free(&entry_name); + + return (ret); +} + +/* + * We need a valid name for the regular 'ustar' entry. This routine + * tries to hack something more-or-less reasonable. + * + * The approach here tries to preserve leading dir names. We do so by + * working with four sections: + * 1) "prefix" directory names, + * 2) "suffix" directory names, + * 3) inserted dir name (optional), + * 4) filename. + * + * These sections must satisfy the following requirements: + * * Parts 1 & 2 together form an initial portion of the dir name. + * * Part 3 is specified by the caller. (It should not contain a leading + * or trailing '/'.) + * * Part 4 forms an initial portion of the base filename. + * * The filename must be <= 99 chars to fit the ustar 'name' field. + * * Parts 2, 3, 4 together must be <= 99 chars to fit the ustar 'name' fld. + * * Part 1 must be <= 155 chars to fit the ustar 'prefix' field. + * * If the original name ends in a '/', the new name must also end in a '/' + * * Trailing '/.' sequences may be stripped. + * + * Note: Recall that the ustar format does not store the '/' separating + * parts 1 & 2, but does store the '/' separating parts 2 & 3. + */ +static char * +build_ustar_entry_name(char *dest, const char *src, size_t src_length, + const char *insert) +{ + const char *prefix, *prefix_end; + const char *suffix, *suffix_end; + const char *filename, *filename_end; + char *p; + int need_slash = 0; /* Was there a trailing slash? */ + size_t suffix_length = 99; + size_t insert_length; + + /* Length of additional dir element to be added. */ + if (insert == NULL) + insert_length = 0; + else + /* +2 here allows for '/' before and after the insert. */ + insert_length = strlen(insert) + 2; + + /* Step 0: Quick bailout in a common case. */ + if (src_length < 100 && insert == NULL) { + strncpy(dest, src, src_length); + dest[src_length] = '\0'; + return (dest); + } + + /* Step 1: Locate filename and enforce the length restriction. */ + filename_end = src + src_length; + /* Remove trailing '/' chars and '/.' pairs. */ + for (;;) { + if (filename_end > src && filename_end[-1] == '/') { + filename_end --; + need_slash = 1; /* Remember to restore trailing '/'. */ + continue; + } + if (filename_end > src + 1 && filename_end[-1] == '.' + && filename_end[-2] == '/') { + filename_end -= 2; + need_slash = 1; /* "foo/." will become "foo/" */ + continue; + } + break; + } + if (need_slash) + suffix_length--; + /* Find start of filename. */ + filename = filename_end - 1; + while ((filename > src) && (*filename != '/')) + filename --; + if ((*filename == '/') && (filename < filename_end - 1)) + filename ++; + /* Adjust filename_end so that filename + insert fits in 99 chars. */ + suffix_length -= insert_length; + if (filename_end > filename + suffix_length) + filename_end = filename + suffix_length; + /* Calculate max size for "suffix" section (#3 above). */ + suffix_length -= filename_end - filename; + + /* Step 2: Locate the "prefix" section of the dirname, including + * trailing '/'. */ + prefix = src; + prefix_end = prefix + 155; + if (prefix_end > filename) + prefix_end = filename; + while (prefix_end > prefix && *prefix_end != '/') + prefix_end--; + if ((prefix_end < filename) && (*prefix_end == '/')) + prefix_end++; + + /* Step 3: Locate the "suffix" section of the dirname, + * including trailing '/'. */ + suffix = prefix_end; + suffix_end = suffix + suffix_length; /* Enforce limit. */ + if (suffix_end > filename) + suffix_end = filename; + if (suffix_end < suffix) + suffix_end = suffix; + while (suffix_end > suffix && *suffix_end != '/') + suffix_end--; + if ((suffix_end < filename) && (*suffix_end == '/')) + suffix_end++; + + /* Step 4: Build the new name. */ + /* The OpenBSD strlcpy function is safer, but less portable. */ + /* Rather than maintain two versions, just use the strncpy version. */ + p = dest; + if (prefix_end > prefix) { + strncpy(p, prefix, prefix_end - prefix); + p += prefix_end - prefix; + } + if (suffix_end > suffix) { + strncpy(p, suffix, suffix_end - suffix); + p += suffix_end - suffix; + } + if (insert != NULL) { + /* Note: assume insert does not have leading or trailing '/' */ + strcpy(p, insert); + p += strlen(insert); + *p++ = '/'; + } + strncpy(p, filename, filename_end - filename); + p += filename_end - filename; + if (need_slash) + *p++ = '/'; + *p = '\0'; + + return (dest); +} + +/* + * The ustar header for the pax extended attributes must have a + * reasonable name: SUSv3 requires 'dirname'/PaxHeader.'pid'/'filename' + * where 'pid' is the PID of the archiving process. Unfortunately, + * that makes testing a pain since the output varies for each run, + * so I'm sticking with the simpler 'dirname'/PaxHeader/'filename' + * for now. (Someday, I'll make this settable. Then I can use the + * SUS recommendation as default and test harnesses can override it + * to get predictable results.) + * + * Joerg Schilling has argued that this is unnecessary because, in + * practice, if the pax extended attributes get extracted as regular + * files, no one is going to bother reading those attributes to + * manually restore them. Based on this, 'star' uses + * /tmp/PaxHeader/'basename' as the ustar header name. This is a + * tempting argument, in part because it's simpler than the SUSv3 + * recommendation, but I'm not entirely convinced. I'm also + * uncomfortable with the fact that "/tmp" is a Unix-ism. + * + * The following routine leverages build_ustar_entry_name() above and + * so is simpler than you might think. It just needs to provide the + * additional path element and handle a few pathological cases). + */ +static char * +build_pax_attribute_name(char *dest, const char *src) +{ + char buff[64]; + const char *p; + + /* Handle the null filename case. */ + if (src == NULL || *src == '\0') { + strcpy(dest, "PaxHeader/blank"); + return (dest); + } + + /* Prune final '/' and other unwanted final elements. */ + p = src + strlen(src); + for (;;) { + /* Ends in "/", remove the '/' */ + if (p > src && p[-1] == '/') { + --p; + continue; + } + /* Ends in "/.", remove the '.' */ + if (p > src + 1 && p[-1] == '.' + && p[-2] == '/') { + --p; + continue; + } + break; + } + + /* Pathological case: After above, there was nothing left. + * This includes "/." "/./." "/.//./." etc. */ + if (p == src) { + strcpy(dest, "/PaxHeader/rootdir"); + return (dest); + } + + /* Convert unadorned "." into a suitable filename. */ + if (*src == '.' && p == src + 1) { + strcpy(dest, "PaxHeader/currentdir"); + return (dest); + } + + /* + * TODO: Push this string into the 'pax' structure to avoid + * recomputing it every time. That will also open the door + * to having clients override it. + */ +#if HAVE_GETPID && 0 /* Disable this for now; see above comment. */ + sprintf(buff, "PaxHeader.%d", getpid()); +#else + /* If the platform can't fetch the pid, don't include it. */ + strcpy(buff, "PaxHeader"); +#endif + /* General case: build a ustar-compatible name adding + * "/PaxHeader/". */ + build_ustar_entry_name(dest, src, p - src, buff); + + return (dest); +} + +/* + * GNU PAX Format 1.0 requires the special name, which pattern is: + * /GNUSparseFile./ + * + * Since reproducible archives are more important, use 0 as pid. + * + * This function is used for only Sparse file, a file type of which + * is regular file. + */ +static char * +build_gnu_sparse_name(char *dest, const char *src) +{ + const char *p; + + /* Handle the null filename case. */ + if (src == NULL || *src == '\0') { + strcpy(dest, "GNUSparseFile/blank"); + return (dest); + } + + /* Prune final '/' and other unwanted final elements. */ + p = src + strlen(src); + for (;;) { + /* Ends in "/", remove the '/' */ + if (p > src && p[-1] == '/') { + --p; + continue; + } + /* Ends in "/.", remove the '.' */ + if (p > src + 1 && p[-1] == '.' + && p[-2] == '/') { + --p; + continue; + } + break; + } + + /* General case: build a ustar-compatible name adding + * "/GNUSparseFile/". */ + build_ustar_entry_name(dest, src, p - src, "GNUSparseFile.0"); + + return (dest); +} + +/* Write two null blocks for the end of archive */ +static int +archive_write_pax_close(struct archive_write *a) +{ + return (__archive_write_nulls(a, 512 * 2)); +} + +static int +archive_write_pax_free(struct archive_write *a) +{ + struct pax *pax; + + pax = (struct pax *)a->format_data; + if (pax == NULL) + return (ARCHIVE_OK); + + archive_string_free(&pax->pax_header); + archive_string_free(&pax->sparse_map); + archive_string_free(&pax->l_url_encoded_name); + sparse_list_clear(pax); + free(pax); + a->format_data = NULL; + return (ARCHIVE_OK); +} + +static int +archive_write_pax_finish_entry(struct archive_write *a) +{ + struct pax *pax; + uint64_t remaining; + int ret; + + pax = (struct pax *)a->format_data; + remaining = pax->entry_bytes_remaining; + if (remaining == 0) { + while (pax->sparse_list) { + struct sparse_block *sb; + if (!pax->sparse_list->is_hole) + remaining += pax->sparse_list->remaining; + sb = pax->sparse_list->next; + free(pax->sparse_list); + pax->sparse_list = sb; + } + } + ret = __archive_write_nulls(a, (size_t)(remaining + pax->entry_padding)); + pax->entry_bytes_remaining = pax->entry_padding = 0; + return (ret); +} + +static ssize_t +archive_write_pax_data(struct archive_write *a, const void *buff, size_t s) +{ + struct pax *pax; + size_t ws; + size_t total; + int ret; + + pax = (struct pax *)a->format_data; + + /* + * According to GNU PAX format 1.0, write a sparse map + * before the body. + */ + if (archive_strlen(&(pax->sparse_map))) { + ret = __archive_write_output(a, pax->sparse_map.s, + archive_strlen(&(pax->sparse_map))); + if (ret != ARCHIVE_OK) + return (ret); + ret = __archive_write_nulls(a, pax->sparse_map_padding); + if (ret != ARCHIVE_OK) + return (ret); + archive_string_empty(&(pax->sparse_map)); + } + + total = 0; + while (total < s) { + const unsigned char *p; + + while (pax->sparse_list != NULL && + pax->sparse_list->remaining == 0) { + struct sparse_block *sb = pax->sparse_list->next; + free(pax->sparse_list); + pax->sparse_list = sb; + } + + if (pax->sparse_list == NULL) + return (total); + + p = ((const unsigned char *)buff) + total; + ws = s - total; + if (ws > pax->sparse_list->remaining) + ws = (size_t)pax->sparse_list->remaining; + + if (pax->sparse_list->is_hole) { + /* Current block is hole thus we do not write + * the body. */ + pax->sparse_list->remaining -= ws; + total += ws; + continue; + } + + ret = __archive_write_output(a, p, ws); + pax->sparse_list->remaining -= ws; + total += ws; + if (ret != ARCHIVE_OK) + return (ret); + } + return (total); +} + +static int +has_non_ASCII(const char *_p) +{ + const unsigned char *p = (const unsigned char *)_p; + + if (p == NULL) + return (1); + while (*p != '\0' && *p < 128) + p++; + return (*p != '\0'); +} + +/* + * Used by extended attribute support; encodes the name + * so that there will be no '=' characters in the result. + */ +static char * +url_encode(const char *in) +{ + const char *s; + char *d; + int out_len = 0; + char *out; + + for (s = in; *s != '\0'; s++) { + if (*s < 33 || *s > 126 || *s == '%' || *s == '=') + out_len += 3; + else + out_len++; + } + + out = (char *)malloc(out_len + 1); + if (out == NULL) + return (NULL); + + for (s = in, d = out; *s != '\0'; s++) { + /* encode any non-printable ASCII character or '%' or '=' */ + if (*s < 33 || *s > 126 || *s == '%' || *s == '=') { + /* URL encoding is '%' followed by two hex digits */ + *d++ = '%'; + *d++ = "0123456789ABCDEF"[0x0f & (*s >> 4)]; + *d++ = "0123456789ABCDEF"[0x0f & *s]; + } else { + *d++ = *s; + } + } + *d = '\0'; + return (out); +} + +/* + * Encode a sequence of bytes into a C string using base-64 encoding. + * + * Returns a null-terminated C string allocated with malloc(); caller + * is responsible for freeing the result. + */ +static char * +base64_encode(const char *s, size_t len) +{ + static const char digits[64] = + { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O', + 'P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d', + 'e','f','g','h','i','j','k','l','m','n','o','p','q','r','s', + 't','u','v','w','x','y','z','0','1','2','3','4','5','6','7', + '8','9','+','/' }; + int v; + char *d, *out; + + /* 3 bytes becomes 4 chars, but round up and allow for trailing NUL */ + out = (char *)malloc((len * 4 + 2) / 3 + 1); + if (out == NULL) + return (NULL); + d = out; + + /* Convert each group of 3 bytes into 4 characters. */ + while (len >= 3) { + v = (((int)s[0] << 16) & 0xff0000) + | (((int)s[1] << 8) & 0xff00) + | (((int)s[2]) & 0x00ff); + s += 3; + len -= 3; + *d++ = digits[(v >> 18) & 0x3f]; + *d++ = digits[(v >> 12) & 0x3f]; + *d++ = digits[(v >> 6) & 0x3f]; + *d++ = digits[(v) & 0x3f]; + } + /* Handle final group of 1 byte (2 chars) or 2 bytes (3 chars). */ + switch (len) { + case 0: break; + case 1: + v = (((int)s[0] << 16) & 0xff0000); + *d++ = digits[(v >> 18) & 0x3f]; + *d++ = digits[(v >> 12) & 0x3f]; + break; + case 2: + v = (((int)s[0] << 16) & 0xff0000) + | (((int)s[1] << 8) & 0xff00); + *d++ = digits[(v >> 18) & 0x3f]; + *d++ = digits[(v >> 12) & 0x3f]; + *d++ = digits[(v >> 6) & 0x3f]; + break; + } + /* Add trailing NUL character so output is a valid C string. */ + *d = '\0'; + return (out); +} + +static void +sparse_list_clear(struct pax *pax) +{ + while (pax->sparse_list != NULL) { + struct sparse_block *sb = pax->sparse_list; + pax->sparse_list = sb->next; + free(sb); + } + pax->sparse_tail = NULL; +} + +static int +_sparse_list_add_block(struct pax *pax, int64_t offset, int64_t length, + int is_hole) +{ + struct sparse_block *sb; + + sb = (struct sparse_block *)malloc(sizeof(*sb)); + if (sb == NULL) + return (ARCHIVE_FATAL); + sb->next = NULL; + sb->is_hole = is_hole; + sb->offset = offset; + sb->remaining = length; + if (pax->sparse_list == NULL || pax->sparse_tail == NULL) + pax->sparse_list = pax->sparse_tail = sb; + else { + pax->sparse_tail->next = sb; + pax->sparse_tail = sb; + } + return (ARCHIVE_OK); +} + +static int +sparse_list_add(struct pax *pax, int64_t offset, int64_t length) +{ + int64_t last_offset; + int r; + + if (pax->sparse_tail == NULL) + last_offset = 0; + else { + last_offset = pax->sparse_tail->offset + + pax->sparse_tail->remaining; + } + if (last_offset < offset) { + /* Add a hole block. */ + r = _sparse_list_add_block(pax, last_offset, + offset - last_offset, 1); + if (r != ARCHIVE_OK) + return (r); + } + /* Add data block. */ + return (_sparse_list_add_block(pax, offset, length, 0)); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_private.h b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_private.h new file mode 100644 index 0000000..e200227 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_private.h @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2020 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef ARCHIVE_WRITE_SET_FORMAT_PRIVATE_H_INCLUDED +#define ARCHIVE_WRITE_SET_FORMAT_PRIVATE_H_INCLUDED + +#ifndef __LIBARCHIVE_BUILD +#ifndef __LIBARCHIVE_TEST +#error This header is only to be used internally to libarchive. +#endif +#endif + +#include "archive.h" +#include "archive_entry.h" + +void __archive_write_entry_filetype_unsupported(struct archive *a, + struct archive_entry *entry, const char *format); +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_raw.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_raw.c new file mode 100644 index 0000000..feff936 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_raw.c @@ -0,0 +1,125 @@ +/*- + * Copyright (c) 2013 Marek Kubica + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +#ifdef HAVE_ERRNO_H +#include +#endif + +#include "archive_entry.h" +#include "archive_write_private.h" + +static ssize_t archive_write_raw_data(struct archive_write *, + const void *buff, size_t s); +static int archive_write_raw_free(struct archive_write *); +static int archive_write_raw_header(struct archive_write *, + struct archive_entry *); + +struct raw { + int entries_written; +}; + +/* + * Set output format to 'raw' format. + */ +int +archive_write_set_format_raw(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct raw *raw; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_set_format_raw"); + + /* If someone else was already registered, unregister them. */ + if (a->format_free != NULL) + (a->format_free)(a); + + raw = (struct raw *)calloc(1, sizeof(*raw)); + if (raw == NULL) { + archive_set_error(&a->archive, ENOMEM, "Can't allocate raw data"); + return (ARCHIVE_FATAL); + } + raw->entries_written = 0; + a->format_data = raw; + a->format_name = "raw"; + /* no options exist for this format */ + a->format_options = NULL; + a->format_write_header = archive_write_raw_header; + a->format_write_data = archive_write_raw_data; + a->format_finish_entry = NULL; + /* nothing needs to be done on closing */ + a->format_close = NULL; + a->format_free = archive_write_raw_free; + a->archive.archive_format = ARCHIVE_FORMAT_RAW; + a->archive.archive_format_name = "RAW"; + return (ARCHIVE_OK); +} + +static int +archive_write_raw_header(struct archive_write *a, struct archive_entry *entry) +{ + struct raw *raw = (struct raw *)a->format_data; + + if (archive_entry_filetype(entry) != AE_IFREG) { + archive_set_error(&a->archive, ERANGE, + "Raw format only supports filetype AE_IFREG"); + return (ARCHIVE_FATAL); + } + + + if (raw->entries_written > 0) { + archive_set_error(&a->archive, ERANGE, + "Raw format only supports one entry per archive"); + return (ARCHIVE_FATAL); + } + raw->entries_written++; + + return (ARCHIVE_OK); +} + +static ssize_t +archive_write_raw_data(struct archive_write *a, const void *buff, size_t s) +{ + int ret; + + ret = __archive_write_output(a, buff, s); + if (ret >= 0) + return (s); + else + return (ret); +} + +static int +archive_write_raw_free(struct archive_write *a) +{ + struct raw *raw; + + raw = (struct raw *)a->format_data; + free(raw); + a->format_data = NULL; + return (ARCHIVE_OK); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_shar.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_shar.c new file mode 100644 index 0000000..9e4931c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_shar.c @@ -0,0 +1,641 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2008 Joerg Sonnenberger + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_shar.c 189438 2009-03-06 05:58:56Z kientzle $"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_write_private.h" +#include "archive_write_set_format_private.h" + +struct shar { + int dump; + int end_of_line; + struct archive_entry *entry; + int has_data; + char *last_dir; + + /* Line buffer for uuencoded dump format */ + char outbuff[45]; + size_t outpos; + + int wrote_header; + struct archive_string work; + struct archive_string quoted_name; +}; + +static int archive_write_shar_close(struct archive_write *); +static int archive_write_shar_free(struct archive_write *); +static int archive_write_shar_header(struct archive_write *, + struct archive_entry *); +static ssize_t archive_write_shar_data_sed(struct archive_write *, + const void * buff, size_t); +static ssize_t archive_write_shar_data_uuencode(struct archive_write *, + const void * buff, size_t); +static int archive_write_shar_finish_entry(struct archive_write *); + +/* + * Copy the given string to the buffer, quoting all shell meta characters + * found. + */ +static void +shar_quote(struct archive_string *buf, const char *str, int in_shell) +{ + static const char meta[] = "\n \t'`\";&<>()|*?{}[]\\$!#^~"; + size_t len; + + while (*str != '\0') { + if ((len = strcspn(str, meta)) != 0) { + archive_strncat(buf, str, len); + str += len; + } else if (*str == '\n') { + if (in_shell) + archive_strcat(buf, "\"\n\""); + else + archive_strcat(buf, "\\n"); + ++str; + } else { + archive_strappend_char(buf, '\\'); + archive_strappend_char(buf, *str); + ++str; + } + } +} + +/* + * Set output format to 'shar' format. + */ +int +archive_write_set_format_shar(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct shar *shar; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_set_format_shar"); + + /* If someone else was already registered, unregister them. */ + if (a->format_free != NULL) + (a->format_free)(a); + + shar = (struct shar *)calloc(1, sizeof(*shar)); + if (shar == NULL) { + archive_set_error(&a->archive, ENOMEM, "Can't allocate shar data"); + return (ARCHIVE_FATAL); + } + archive_string_init(&shar->work); + archive_string_init(&shar->quoted_name); + a->format_data = shar; + a->format_name = "shar"; + a->format_write_header = archive_write_shar_header; + a->format_close = archive_write_shar_close; + a->format_free = archive_write_shar_free; + a->format_write_data = archive_write_shar_data_sed; + a->format_finish_entry = archive_write_shar_finish_entry; + a->archive.archive_format = ARCHIVE_FORMAT_SHAR_BASE; + a->archive.archive_format_name = "shar"; + return (ARCHIVE_OK); +} + +/* + * An alternate 'shar' that uses uudecode instead of 'sed' to encode + * file contents and can therefore be used to archive binary files. + * In addition, this variant also attempts to restore ownership, file modes, + * and other extended file information. + */ +int +archive_write_set_format_shar_dump(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct shar *shar; + + archive_write_set_format_shar(&a->archive); + shar = (struct shar *)a->format_data; + shar->dump = 1; + a->format_write_data = archive_write_shar_data_uuencode; + a->archive.archive_format = ARCHIVE_FORMAT_SHAR_DUMP; + a->archive.archive_format_name = "shar dump"; + return (ARCHIVE_OK); +} + +static int +archive_write_shar_header(struct archive_write *a, struct archive_entry *entry) +{ + const char *linkname; + const char *name; + char *p, *pp; + struct shar *shar; + + shar = (struct shar *)a->format_data; + if (!shar->wrote_header) { + archive_strcat(&shar->work, "#!/bin/sh\n"); + archive_strcat(&shar->work, "# This is a shell archive\n"); + shar->wrote_header = 1; + } + + /* Save the entry for the closing. */ + archive_entry_free(shar->entry); + shar->entry = archive_entry_clone(entry); + name = archive_entry_pathname(entry); + + /* Handle some preparatory issues. */ + switch(archive_entry_filetype(entry)) { + case AE_IFREG: + /* Only regular files have non-zero size. */ + break; + case AE_IFDIR: + archive_entry_set_size(entry, 0); + /* Don't bother trying to recreate '.' */ + if (strcmp(name, ".") == 0 || strcmp(name, "./") == 0) + return (ARCHIVE_OK); + break; + case AE_IFIFO: + case AE_IFCHR: + case AE_IFBLK: + /* All other file types have zero size in the archive. */ + archive_entry_set_size(entry, 0); + break; + default: + archive_entry_set_size(entry, 0); + if (archive_entry_hardlink(entry) == NULL && + archive_entry_symlink(entry) == NULL) { + __archive_write_entry_filetype_unsupported( + &a->archive, entry, "shar"); + return (ARCHIVE_WARN); + } + } + + archive_string_empty(&shar->quoted_name); + shar_quote(&shar->quoted_name, name, 1); + + /* Stock preparation for all file types. */ + archive_string_sprintf(&shar->work, "echo x %s\n", shar->quoted_name.s); + + if (archive_entry_filetype(entry) != AE_IFDIR) { + /* Try to create the dir. */ + p = strdup(name); + pp = strrchr(p, '/'); + /* If there is a / character, try to create the dir. */ + if (pp != NULL) { + *pp = '\0'; + + /* Try to avoid a lot of redundant mkdir commands. */ + if (strcmp(p, ".") == 0) { + /* Don't try to "mkdir ." */ + free(p); + } else if (shar->last_dir == NULL) { + archive_strcat(&shar->work, "mkdir -p "); + shar_quote(&shar->work, p, 1); + archive_strcat(&shar->work, + " > /dev/null 2>&1\n"); + shar->last_dir = p; + } else if (strcmp(p, shar->last_dir) == 0) { + /* We've already created this exact dir. */ + free(p); + } else if (strlen(p) < strlen(shar->last_dir) && + strncmp(p, shar->last_dir, strlen(p)) == 0) { + /* We've already created a subdir. */ + free(p); + } else { + archive_strcat(&shar->work, "mkdir -p "); + shar_quote(&shar->work, p, 1); + archive_strcat(&shar->work, + " > /dev/null 2>&1\n"); + shar->last_dir = p; + } + } else { + free(p); + } + } + + /* Handle file-type specific issues. */ + shar->has_data = 0; + if ((linkname = archive_entry_hardlink(entry)) != NULL) { + archive_strcat(&shar->work, "ln -f "); + shar_quote(&shar->work, linkname, 1); + archive_string_sprintf(&shar->work, " %s\n", + shar->quoted_name.s); + } else if ((linkname = archive_entry_symlink(entry)) != NULL) { + archive_strcat(&shar->work, "ln -fs "); + shar_quote(&shar->work, linkname, 1); + archive_string_sprintf(&shar->work, " %s\n", + shar->quoted_name.s); + } else { + switch(archive_entry_filetype(entry)) { + case AE_IFREG: + if (archive_entry_size(entry) == 0) { + /* More portable than "touch." */ + archive_string_sprintf(&shar->work, + "test -e \"%s\" || :> \"%s\"\n", + shar->quoted_name.s, shar->quoted_name.s); + } else { + if (shar->dump) { + unsigned int mode = archive_entry_mode(entry) & 0777; + archive_string_sprintf(&shar->work, + "uudecode -p > %s << 'SHAR_END'\n", + shar->quoted_name.s); + archive_string_sprintf(&shar->work, + "begin %o ", mode); + shar_quote(&shar->work, name, 0); + archive_strcat(&shar->work, "\n"); + } else { + archive_string_sprintf(&shar->work, + "sed 's/^X//' > %s << 'SHAR_END'\n", + shar->quoted_name.s); + } + shar->has_data = 1; + shar->end_of_line = 1; + shar->outpos = 0; + } + break; + case AE_IFDIR: + archive_string_sprintf(&shar->work, + "mkdir -p %s > /dev/null 2>&1\n", + shar->quoted_name.s); + /* Record that we just created this directory. */ + free(shar->last_dir); + + shar->last_dir = strdup(name); + /* Trim a trailing '/'. */ + pp = strrchr(shar->last_dir, '/'); + if (pp != NULL && pp[1] == '\0') + *pp = '\0'; + /* + * TODO: Put dir name/mode on a list to be fixed + * up at end of archive. + */ + break; + case AE_IFIFO: + archive_string_sprintf(&shar->work, + "mkfifo %s\n", shar->quoted_name.s); + break; + case AE_IFCHR: + archive_string_sprintf(&shar->work, + "mknod %s c %ju %ju\n", shar->quoted_name.s, + (uintmax_t)archive_entry_rdevmajor(entry), + (uintmax_t)archive_entry_rdevminor(entry)); + break; + case AE_IFBLK: + archive_string_sprintf(&shar->work, + "mknod %s b %ju %ju\n", shar->quoted_name.s, + (uintmax_t)archive_entry_rdevmajor(entry), + (uintmax_t)archive_entry_rdevminor(entry)); + break; + default: + return (ARCHIVE_WARN); + } + } + + return (ARCHIVE_OK); +} + +static ssize_t +archive_write_shar_data_sed(struct archive_write *a, const void *buff, size_t n) +{ + static const size_t ensured = 65533; + struct shar *shar; + const char *src; + char *buf, *buf_end; + int ret; + size_t written = n; + + shar = (struct shar *)a->format_data; + if (!shar->has_data || n == 0) + return (0); + + src = (const char *)buff; + + /* + * ensure is the number of bytes in buffer before expanding the + * current character. Each operation writes the current character + * and optionally the start-of-new-line marker. This can happen + * twice before entering the loop, so make sure three additional + * bytes can be written. + */ + if (archive_string_ensure(&shar->work, ensured + 3) == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + + if (shar->work.length > ensured) { + ret = __archive_write_output(a, shar->work.s, + shar->work.length); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + archive_string_empty(&shar->work); + } + buf = shar->work.s + shar->work.length; + buf_end = shar->work.s + ensured; + + if (shar->end_of_line) { + *buf++ = 'X'; + shar->end_of_line = 0; + } + + while (n-- != 0) { + if ((*buf++ = *src++) == '\n') { + if (n == 0) + shar->end_of_line = 1; + else + *buf++ = 'X'; + } + + if (buf >= buf_end) { + shar->work.length = buf - shar->work.s; + ret = __archive_write_output(a, shar->work.s, + shar->work.length); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + archive_string_empty(&shar->work); + buf = shar->work.s; + } + } + + shar->work.length = buf - shar->work.s; + + return (written); +} + +#define UUENC(c) (((c)!=0) ? ((c) & 077) + ' ': '`') + +static void +uuencode_group(const char _in[3], char out[4]) +{ + const unsigned char *in = (const unsigned char *)_in; + int t; + + t = (in[0] << 16) | (in[1] << 8) | in[2]; + out[0] = UUENC( 0x3f & (t >> 18) ); + out[1] = UUENC( 0x3f & (t >> 12) ); + out[2] = UUENC( 0x3f & (t >> 6) ); + out[3] = UUENC( 0x3f & t ); +} + +static int +_uuencode_line(struct archive_write *a, struct shar *shar, const char *inbuf, size_t len) +{ + char *buf; + size_t alloc_len; + + /* len <= 45 -> expanded to 60 + len byte + new line */ + alloc_len = shar->work.length + 62; + if (archive_string_ensure(&shar->work, alloc_len) == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + + buf = shar->work.s + shar->work.length; + *buf++ = UUENC(len); + while (len >= 3) { + uuencode_group(inbuf, buf); + len -= 3; + inbuf += 3; + buf += 4; + } + if (len != 0) { + char tmp_buf[3]; + tmp_buf[0] = inbuf[0]; + if (len == 1) + tmp_buf[1] = '\0'; + else + tmp_buf[1] = inbuf[1]; + tmp_buf[2] = '\0'; + uuencode_group(tmp_buf, buf); + buf += 4; + } + *buf++ = '\n'; + if ((buf - shar->work.s) > (ptrdiff_t)(shar->work.length + 62)) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, "Buffer overflow"); + return (ARCHIVE_FATAL); + } + shar->work.length = buf - shar->work.s; + return (ARCHIVE_OK); +} + +#define uuencode_line(__a, __shar, __inbuf, __len) \ + do { \ + int r = _uuencode_line(__a, __shar, __inbuf, __len); \ + if (r != ARCHIVE_OK) \ + return (ARCHIVE_FATAL); \ + } while (0) + +static ssize_t +archive_write_shar_data_uuencode(struct archive_write *a, const void *buff, + size_t length) +{ + struct shar *shar; + const char *src; + size_t n; + int ret; + + shar = (struct shar *)a->format_data; + if (!shar->has_data) + return (ARCHIVE_OK); + src = (const char *)buff; + + if (shar->outpos != 0) { + n = 45 - shar->outpos; + if (n > length) + n = length; + memcpy(shar->outbuff + shar->outpos, src, n); + if (shar->outpos + n < 45) { + shar->outpos += n; + return length; + } + uuencode_line(a, shar, shar->outbuff, 45); + src += n; + n = length - n; + } else { + n = length; + } + + while (n >= 45) { + uuencode_line(a, shar, src, 45); + src += 45; + n -= 45; + + if (shar->work.length < 65536) + continue; + ret = __archive_write_output(a, shar->work.s, + shar->work.length); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + archive_string_empty(&shar->work); + } + if (n != 0) { + memcpy(shar->outbuff, src, n); + shar->outpos = n; + } + return (length); +} + +static int +archive_write_shar_finish_entry(struct archive_write *a) +{ + const char *g, *p, *u; + struct shar *shar; + int ret; + + shar = (struct shar *)a->format_data; + if (shar->entry == NULL) + return (0); + + if (shar->dump) { + /* Finish uuencoded data. */ + if (shar->has_data) { + if (shar->outpos > 0) + uuencode_line(a, shar, shar->outbuff, + shar->outpos); + archive_strcat(&shar->work, "`\nend\n"); + archive_strcat(&shar->work, "SHAR_END\n"); + } + /* Restore file mode, owner, flags. */ + /* + * TODO: Don't immediately restore mode for + * directories; defer that to end of script. + */ + archive_string_sprintf(&shar->work, "chmod %o ", + (unsigned int)(archive_entry_mode(shar->entry) & 07777)); + shar_quote(&shar->work, archive_entry_pathname(shar->entry), 1); + archive_strcat(&shar->work, "\n"); + + u = archive_entry_uname(shar->entry); + g = archive_entry_gname(shar->entry); + if (u != NULL || g != NULL) { + archive_strcat(&shar->work, "chown "); + if (u != NULL) + shar_quote(&shar->work, u, 1); + if (g != NULL) { + archive_strcat(&shar->work, ":"); + shar_quote(&shar->work, g, 1); + } + archive_strcat(&shar->work, " "); + shar_quote(&shar->work, + archive_entry_pathname(shar->entry), 1); + archive_strcat(&shar->work, "\n"); + } + + if ((p = archive_entry_fflags_text(shar->entry)) != NULL) { + archive_string_sprintf(&shar->work, "chflags %s ", p); + shar_quote(&shar->work, + archive_entry_pathname(shar->entry), 1); + archive_strcat(&shar->work, "\n"); + } + + /* TODO: restore ACLs */ + + } else { + if (shar->has_data) { + /* Finish sed-encoded data: ensure last line ends. */ + if (!shar->end_of_line) + archive_strappend_char(&shar->work, '\n'); + archive_strcat(&shar->work, "SHAR_END\n"); + } + } + + archive_entry_free(shar->entry); + shar->entry = NULL; + + if (shar->work.length < 65536) + return (ARCHIVE_OK); + + ret = __archive_write_output(a, shar->work.s, shar->work.length); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + archive_string_empty(&shar->work); + + return (ARCHIVE_OK); +} + +static int +archive_write_shar_close(struct archive_write *a) +{ + struct shar *shar; + int ret; + + /* + * TODO: Accumulate list of directory names/modes and + * fix them all up at end-of-archive. + */ + + shar = (struct shar *)a->format_data; + + /* + * Only write the end-of-archive markers if the archive was + * actually started. This avoids problems if someone sets + * shar format, then sets another format (which would invoke + * shar_finish to free the format-specific data). + */ + if (shar->wrote_header == 0) + return (ARCHIVE_OK); + + archive_strcat(&shar->work, "exit\n"); + + ret = __archive_write_output(a, shar->work.s, shar->work.length); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Shar output is never padded. */ + archive_write_set_bytes_in_last_block(&a->archive, 1); + /* + * TODO: shar should also suppress padding of + * uncompressed data within gzip/bzip2 streams. + */ + + return (ARCHIVE_OK); +} + +static int +archive_write_shar_free(struct archive_write *a) +{ + struct shar *shar; + + shar = (struct shar *)a->format_data; + if (shar == NULL) + return (ARCHIVE_OK); + + archive_entry_free(shar->entry); + free(shar->last_dir); + archive_string_free(&(shar->work)); + archive_string_free(&(shar->quoted_name)); + free(shar); + a->format_data = NULL; + return (ARCHIVE_OK); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_ustar.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_ustar.c new file mode 100644 index 0000000..d1a06bc --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_ustar.c @@ -0,0 +1,758 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2011-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_ustar.c 191579 2009-04-27 18:35:03Z kientzle $"); + + +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_private.h" +#include "archive_write_private.h" +#include "archive_write_set_format_private.h" + +struct ustar { + uint64_t entry_bytes_remaining; + uint64_t entry_padding; + + struct archive_string_conv *opt_sconv; + struct archive_string_conv *sconv_default; + int init_default_conversion; +}; + +/* + * Define structure of POSIX 'ustar' tar header. + */ +#define USTAR_name_offset 0 +#define USTAR_name_size 100 +#define USTAR_mode_offset 100 +#define USTAR_mode_size 6 +#define USTAR_mode_max_size 8 +#define USTAR_uid_offset 108 +#define USTAR_uid_size 6 +#define USTAR_uid_max_size 8 +#define USTAR_gid_offset 116 +#define USTAR_gid_size 6 +#define USTAR_gid_max_size 8 +#define USTAR_size_offset 124 +#define USTAR_size_size 11 +#define USTAR_size_max_size 12 +#define USTAR_mtime_offset 136 +#define USTAR_mtime_size 11 +#define USTAR_mtime_max_size 11 +#define USTAR_checksum_offset 148 +#define USTAR_checksum_size 8 +#define USTAR_typeflag_offset 156 +#define USTAR_typeflag_size 1 +#define USTAR_linkname_offset 157 +#define USTAR_linkname_size 100 +#define USTAR_magic_offset 257 +#define USTAR_magic_size 6 +#define USTAR_version_offset 263 +#define USTAR_version_size 2 +#define USTAR_uname_offset 265 +#define USTAR_uname_size 32 +#define USTAR_gname_offset 297 +#define USTAR_gname_size 32 +#define USTAR_rdevmajor_offset 329 +#define USTAR_rdevmajor_size 6 +#define USTAR_rdevmajor_max_size 8 +#define USTAR_rdevminor_offset 337 +#define USTAR_rdevminor_size 6 +#define USTAR_rdevminor_max_size 8 +#define USTAR_prefix_offset 345 +#define USTAR_prefix_size 155 +#define USTAR_padding_offset 500 +#define USTAR_padding_size 12 + +/* + * A filled-in copy of the header for initialization. + */ +static const char template_header[] = { + /* name: 100 bytes */ + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0, + /* Mode, space-null termination: 8 bytes */ + '0','0','0','0','0','0', ' ','\0', + /* uid, space-null termination: 8 bytes */ + '0','0','0','0','0','0', ' ','\0', + /* gid, space-null termination: 8 bytes */ + '0','0','0','0','0','0', ' ','\0', + /* size, space termination: 12 bytes */ + '0','0','0','0','0','0','0','0','0','0','0', ' ', + /* mtime, space termination: 12 bytes */ + '0','0','0','0','0','0','0','0','0','0','0', ' ', + /* Initial checksum value: 8 spaces */ + ' ',' ',' ',' ',' ',' ',' ',' ', + /* Typeflag: 1 byte */ + '0', /* '0' = regular file */ + /* Linkname: 100 bytes */ + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0, + /* Magic: 6 bytes, Version: 2 bytes */ + 'u','s','t','a','r','\0', '0','0', + /* Uname: 32 bytes */ + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + /* Gname: 32 bytes */ + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + /* rdevmajor + space/null padding: 8 bytes */ + '0','0','0','0','0','0', ' ','\0', + /* rdevminor + space/null padding: 8 bytes */ + '0','0','0','0','0','0', ' ','\0', + /* Prefix: 155 bytes */ + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0, + /* Padding: 12 bytes */ + 0,0,0,0,0,0,0,0, 0,0,0,0 +}; + +static ssize_t archive_write_ustar_data(struct archive_write *a, const void *buff, + size_t s); +static int archive_write_ustar_free(struct archive_write *); +static int archive_write_ustar_close(struct archive_write *); +static int archive_write_ustar_finish_entry(struct archive_write *); +static int archive_write_ustar_header(struct archive_write *, + struct archive_entry *entry); +static int archive_write_ustar_options(struct archive_write *, + const char *, const char *); +static int format_256(int64_t, char *, int); +static int format_number(int64_t, char *, int size, int max, int strict); +static int format_octal(int64_t, char *, int); + +/* + * Set output format to 'ustar' format. + */ +int +archive_write_set_format_ustar(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct ustar *ustar; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_set_format_ustar"); + + /* If someone else was already registered, unregister them. */ + if (a->format_free != NULL) + (a->format_free)(a); + + /* Basic internal sanity test. */ + if (sizeof(template_header) != 512) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Internal: template_header wrong size: %zu should be 512", + sizeof(template_header)); + return (ARCHIVE_FATAL); + } + + ustar = (struct ustar *)calloc(1, sizeof(*ustar)); + if (ustar == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate ustar data"); + return (ARCHIVE_FATAL); + } + a->format_data = ustar; + a->format_name = "ustar"; + a->format_options = archive_write_ustar_options; + a->format_write_header = archive_write_ustar_header; + a->format_write_data = archive_write_ustar_data; + a->format_close = archive_write_ustar_close; + a->format_free = archive_write_ustar_free; + a->format_finish_entry = archive_write_ustar_finish_entry; + a->archive.archive_format = ARCHIVE_FORMAT_TAR_USTAR; + a->archive.archive_format_name = "POSIX ustar"; + return (ARCHIVE_OK); +} + +static int +archive_write_ustar_options(struct archive_write *a, const char *key, + const char *val) +{ + struct ustar *ustar = (struct ustar *)a->format_data; + int ret = ARCHIVE_FAILED; + + if (strcmp(key, "hdrcharset") == 0) { + if (val == NULL || val[0] == 0) + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "%s: hdrcharset option needs a character-set name", + a->format_name); + else { + ustar->opt_sconv = archive_string_conversion_to_charset( + &a->archive, val, 0); + if (ustar->opt_sconv != NULL) + ret = ARCHIVE_OK; + else + ret = ARCHIVE_FATAL; + } + return (ret); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +static int +archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry) +{ + char buff[512]; + int ret, ret2; + struct ustar *ustar; + struct archive_entry *entry_main; + struct archive_string_conv *sconv; + + ustar = (struct ustar *)a->format_data; + + /* Setup default string conversion. */ + if (ustar->opt_sconv == NULL) { + if (!ustar->init_default_conversion) { + ustar->sconv_default = + archive_string_default_conversion_for_write(&(a->archive)); + ustar->init_default_conversion = 1; + } + sconv = ustar->sconv_default; + } else + sconv = ustar->opt_sconv; + + /* Sanity check. */ + if (archive_entry_pathname(entry) == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't record entry in tar file without pathname"); + return (ARCHIVE_FAILED); + } + + /* Only regular files (not hardlinks) have data. */ + if (archive_entry_hardlink(entry) != NULL || + archive_entry_symlink(entry) != NULL || + !(archive_entry_filetype(entry) == AE_IFREG)) + archive_entry_set_size(entry, 0); + + if (AE_IFDIR == archive_entry_filetype(entry)) { + const char *p; + size_t path_length; + /* + * Ensure a trailing '/'. Modify the entry so + * the client sees the change. + */ +#if defined(_WIN32) && !defined(__CYGWIN__) + const wchar_t *wp; + + wp = archive_entry_pathname_w(entry); + if (wp != NULL && wp[wcslen(wp) -1] != L'/') { + struct archive_wstring ws; + + archive_string_init(&ws); + path_length = wcslen(wp); + if (archive_wstring_ensure(&ws, + path_length + 2) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate ustar data"); + archive_wstring_free(&ws); + return(ARCHIVE_FATAL); + } + /* Should we keep '\' ? */ + if (wp[path_length -1] == L'\\') + path_length--; + archive_wstrncpy(&ws, wp, path_length); + archive_wstrappend_wchar(&ws, L'/'); + archive_entry_copy_pathname_w(entry, ws.s); + archive_wstring_free(&ws); + p = NULL; + } else +#endif + p = archive_entry_pathname(entry); + /* + * On Windows, this is a backup operation just in + * case getting WCS failed. On POSIX, this is a + * normal operation. + */ + if (p != NULL && p[0] != '\0' && p[strlen(p) - 1] != '/') { + struct archive_string as; + + archive_string_init(&as); + path_length = strlen(p); + if (archive_string_ensure(&as, + path_length + 2) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate ustar data"); + archive_string_free(&as); + return(ARCHIVE_FATAL); + } +#if defined(_WIN32) && !defined(__CYGWIN__) + /* NOTE: This might break the pathname + * if the current code page is CP932 and + * the pathname includes a character '\' + * as a part of its multibyte pathname. */ + if (p[strlen(p) -1] == '\\') + path_length--; + else +#endif + archive_strncpy(&as, p, path_length); + archive_strappend_char(&as, '/'); + archive_entry_copy_pathname(entry, as.s); + archive_string_free(&as); + } + } + +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Make sure the path separators in pathname, hardlink and symlink + * are all slash '/', not the Windows path separator '\'. */ + entry_main = __la_win_entry_in_posix_pathseparator(entry); + if (entry_main == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate ustar data"); + return(ARCHIVE_FATAL); + } + if (entry != entry_main) + entry = entry_main; + else + entry_main = NULL; +#else + entry_main = NULL; +#endif + ret = __archive_write_format_header_ustar(a, buff, entry, -1, 1, sconv); + if (ret < ARCHIVE_WARN) { + archive_entry_free(entry_main); + return (ret); + } + ret2 = __archive_write_output(a, buff, 512); + if (ret2 < ARCHIVE_WARN) { + archive_entry_free(entry_main); + return (ret2); + } + if (ret2 < ret) + ret = ret2; + + ustar->entry_bytes_remaining = archive_entry_size(entry); + ustar->entry_padding = 0x1ff & (-(int64_t)ustar->entry_bytes_remaining); + archive_entry_free(entry_main); + return (ret); +} + +/* + * Format a basic 512-byte "ustar" header. + * + * Returns -1 if format failed (due to field overflow). + * Note that this always formats as much of the header as possible. + * If "strict" is set to zero, it will extend numeric fields as + * necessary (overwriting terminators or using base-256 extensions). + * + * This is exported so that other 'tar' formats can use it. + */ +int +__archive_write_format_header_ustar(struct archive_write *a, char h[512], + struct archive_entry *entry, int tartype, int strict, + struct archive_string_conv *sconv) +{ + unsigned int checksum; + int i, r, ret; + size_t copy_length; + const char *p, *pp; + int mytartype; + + ret = 0; + mytartype = -1; + /* + * The "template header" already includes the "ustar" + * signature, various end-of-field markers and other required + * elements. + */ + memcpy(h, &template_header, 512); + + /* + * Because the block is already null-filled, and strings + * are allowed to exactly fill their destination (without null), + * I use memcpy(dest, src, strlen()) here a lot to copy strings. + */ + r = archive_entry_pathname_l(entry, &pp, ©_length, sconv); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Pathname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate pathname '%s' to %s", + pp, archive_string_conversion_charset_name(sconv)); + ret = ARCHIVE_WARN; + } + if (copy_length <= USTAR_name_size) + memcpy(h + USTAR_name_offset, pp, copy_length); + else { + /* Store in two pieces, splitting at a '/'. */ + p = strchr(pp + copy_length - USTAR_name_size - 1, '/'); + /* + * Look for the next '/' if we chose the first character + * as the separator. (ustar format doesn't permit + * an empty prefix.) + */ + if (p == pp) + p = strchr(p + 1, '/'); + /* Fail if the name won't fit. */ + if (!p) { + /* No separator. */ + archive_set_error(&a->archive, ENAMETOOLONG, + "Pathname too long"); + ret = ARCHIVE_FAILED; + } else if (p[1] == '\0') { + /* + * The only feasible separator is a final '/'; + * this would result in a non-empty prefix and + * an empty name, which POSIX doesn't + * explicitly forbid, but it just feels wrong. + */ + archive_set_error(&a->archive, ENAMETOOLONG, + "Pathname too long"); + ret = ARCHIVE_FAILED; + } else if (p > pp + USTAR_prefix_size) { + /* Prefix is too long. */ + archive_set_error(&a->archive, ENAMETOOLONG, + "Pathname too long"); + ret = ARCHIVE_FAILED; + } else { + /* Copy prefix and remainder to appropriate places */ + memcpy(h + USTAR_prefix_offset, pp, p - pp); + memcpy(h + USTAR_name_offset, p + 1, + pp + copy_length - p - 1); + } + } + + r = archive_entry_hardlink_l(entry, &p, ©_length, sconv); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Linkname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate linkname '%s' to %s", + p, archive_string_conversion_charset_name(sconv)); + ret = ARCHIVE_WARN; + } + if (copy_length > 0) + mytartype = '1'; + else { + r = archive_entry_symlink_l(entry, &p, ©_length, sconv); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Linkname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate linkname '%s' to %s", + p, archive_string_conversion_charset_name(sconv)); + ret = ARCHIVE_WARN; + } + } + if (copy_length > 0) { + if (copy_length > USTAR_linkname_size) { + archive_set_error(&a->archive, ENAMETOOLONG, + "Link contents too long"); + ret = ARCHIVE_FAILED; + copy_length = USTAR_linkname_size; + } + memcpy(h + USTAR_linkname_offset, p, copy_length); + } + + r = archive_entry_uname_l(entry, &p, ©_length, sconv); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Uname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate uname '%s' to %s", + p, archive_string_conversion_charset_name(sconv)); + ret = ARCHIVE_WARN; + } + if (copy_length > 0) { + if (copy_length > USTAR_uname_size) { + if (tartype != 'x') { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, "Username too long"); + ret = ARCHIVE_FAILED; + } + copy_length = USTAR_uname_size; + } + memcpy(h + USTAR_uname_offset, p, copy_length); + } + + r = archive_entry_gname_l(entry, &p, ©_length, sconv); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Gname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate gname '%s' to %s", + p, archive_string_conversion_charset_name(sconv)); + ret = ARCHIVE_WARN; + } + if (copy_length > 0) { + if (strlen(p) > USTAR_gname_size) { + if (tartype != 'x') { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, "Group name too long"); + ret = ARCHIVE_FAILED; + } + copy_length = USTAR_gname_size; + } + memcpy(h + USTAR_gname_offset, p, copy_length); + } + + if (format_number(archive_entry_mode(entry) & 07777, + h + USTAR_mode_offset, USTAR_mode_size, USTAR_mode_max_size, strict)) { + archive_set_error(&a->archive, ERANGE, + "Numeric mode too large"); + ret = ARCHIVE_FAILED; + } + + if (format_number(archive_entry_uid(entry), + h + USTAR_uid_offset, USTAR_uid_size, USTAR_uid_max_size, strict)) { + archive_set_error(&a->archive, ERANGE, + "Numeric user ID too large"); + ret = ARCHIVE_FAILED; + } + + if (format_number(archive_entry_gid(entry), + h + USTAR_gid_offset, USTAR_gid_size, USTAR_gid_max_size, strict)) { + archive_set_error(&a->archive, ERANGE, + "Numeric group ID too large"); + ret = ARCHIVE_FAILED; + } + + if (format_number(archive_entry_size(entry), + h + USTAR_size_offset, USTAR_size_size, USTAR_size_max_size, strict)) { + archive_set_error(&a->archive, ERANGE, + "File size out of range"); + ret = ARCHIVE_FAILED; + } + + if (format_number(archive_entry_mtime(entry), + h + USTAR_mtime_offset, USTAR_mtime_size, USTAR_mtime_max_size, strict)) { + archive_set_error(&a->archive, ERANGE, + "File modification time too large"); + ret = ARCHIVE_FAILED; + } + + if (archive_entry_filetype(entry) == AE_IFBLK + || archive_entry_filetype(entry) == AE_IFCHR) { + if (format_number(archive_entry_rdevmajor(entry), + h + USTAR_rdevmajor_offset, USTAR_rdevmajor_size, + USTAR_rdevmajor_max_size, strict)) { + archive_set_error(&a->archive, ERANGE, + "Major device number too large"); + ret = ARCHIVE_FAILED; + } + + if (format_number(archive_entry_rdevminor(entry), + h + USTAR_rdevminor_offset, USTAR_rdevminor_size, + USTAR_rdevminor_max_size, strict)) { + archive_set_error(&a->archive, ERANGE, + "Minor device number too large"); + ret = ARCHIVE_FAILED; + } + } + + if (tartype >= 0) { + h[USTAR_typeflag_offset] = tartype; + } else if (mytartype >= 0) { + h[USTAR_typeflag_offset] = mytartype; + } else { + switch (archive_entry_filetype(entry)) { + case AE_IFREG: h[USTAR_typeflag_offset] = '0' ; break; + case AE_IFLNK: h[USTAR_typeflag_offset] = '2' ; break; + case AE_IFCHR: h[USTAR_typeflag_offset] = '3' ; break; + case AE_IFBLK: h[USTAR_typeflag_offset] = '4' ; break; + case AE_IFDIR: h[USTAR_typeflag_offset] = '5' ; break; + case AE_IFIFO: h[USTAR_typeflag_offset] = '6' ; break; + default: /* AE_IFSOCK and unknown */ + __archive_write_entry_filetype_unsupported( + &a->archive, entry, "ustar"); + ret = ARCHIVE_FAILED; + } + } + + checksum = 0; + for (i = 0; i < 512; i++) + checksum += 255 & (unsigned int)h[i]; + h[USTAR_checksum_offset + 6] = '\0'; /* Can't be pre-set in the template. */ + /* h[USTAR_checksum_offset + 7] = ' '; */ /* This is pre-set in the template. */ + format_octal(checksum, h + USTAR_checksum_offset, 6); + return (ret); +} + +/* + * Format a number into a field, with some intelligence. + */ +static int +format_number(int64_t v, char *p, int s, int maxsize, int strict) +{ + int64_t limit; + + limit = ((int64_t)1 << (s*3)); + + /* "Strict" only permits octal values with proper termination. */ + if (strict) + return (format_octal(v, p, s)); + + /* + * In non-strict mode, we allow the number to overwrite one or + * more bytes of the field termination. Even old tar + * implementations should be able to handle this with no + * problem. + */ + if (v >= 0) { + while (s <= maxsize) { + if (v < limit) + return (format_octal(v, p, s)); + s++; + limit <<= 3; + } + } + + /* Base-256 can handle any number, positive or negative. */ + return (format_256(v, p, maxsize)); +} + +/* + * Format a number into the specified field using base-256. + */ +static int +format_256(int64_t v, char *p, int s) +{ + p += s; + while (s-- > 0) { + *--p = (char)(v & 0xff); + v >>= 8; + } + *p |= 0x80; /* Set the base-256 marker bit. */ + return (0); +} + +/* + * Format a number into the specified field. + */ +static int +format_octal(int64_t v, char *p, int s) +{ + int len; + + len = s; + + /* Octal values can't be negative, so use 0. */ + if (v < 0) { + while (len-- > 0) + *p++ = '0'; + return (-1); + } + + p += s; /* Start at the end and work backwards. */ + while (s-- > 0) { + *--p = (char)('0' + (v & 7)); + v >>= 3; + } + + if (v == 0) + return (0); + + /* If it overflowed, fill field with max value. */ + while (len-- > 0) + *p++ = '7'; + + return (-1); +} + +static int +archive_write_ustar_close(struct archive_write *a) +{ + return (__archive_write_nulls(a, 512*2)); +} + +static int +archive_write_ustar_free(struct archive_write *a) +{ + struct ustar *ustar; + + ustar = (struct ustar *)a->format_data; + free(ustar); + a->format_data = NULL; + return (ARCHIVE_OK); +} + +static int +archive_write_ustar_finish_entry(struct archive_write *a) +{ + struct ustar *ustar; + int ret; + + ustar = (struct ustar *)a->format_data; + ret = __archive_write_nulls(a, + (size_t)(ustar->entry_bytes_remaining + ustar->entry_padding)); + ustar->entry_bytes_remaining = ustar->entry_padding = 0; + return (ret); +} + +static ssize_t +archive_write_ustar_data(struct archive_write *a, const void *buff, size_t s) +{ + struct ustar *ustar; + int ret; + + ustar = (struct ustar *)a->format_data; + if (s > ustar->entry_bytes_remaining) + s = (size_t)ustar->entry_bytes_remaining; + ret = __archive_write_output(a, buff, s); + ustar->entry_bytes_remaining -= s; + if (ret != ARCHIVE_OK) + return (ret); + return (s); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_v7tar.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_v7tar.c new file mode 100644 index 0000000..5994071 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_v7tar.c @@ -0,0 +1,638 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2011-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + + +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_private.h" +#include "archive_write_private.h" +#include "archive_write_set_format_private.h" + +struct v7tar { + uint64_t entry_bytes_remaining; + uint64_t entry_padding; + + struct archive_string_conv *opt_sconv; + struct archive_string_conv *sconv_default; + int init_default_conversion; +}; + +/* + * Define structure of POSIX 'v7tar' tar header. + */ +#define V7TAR_name_offset 0 +#define V7TAR_name_size 100 +#define V7TAR_mode_offset 100 +#define V7TAR_mode_size 6 +#define V7TAR_mode_max_size 8 +#define V7TAR_uid_offset 108 +#define V7TAR_uid_size 6 +#define V7TAR_uid_max_size 8 +#define V7TAR_gid_offset 116 +#define V7TAR_gid_size 6 +#define V7TAR_gid_max_size 8 +#define V7TAR_size_offset 124 +#define V7TAR_size_size 11 +#define V7TAR_size_max_size 12 +#define V7TAR_mtime_offset 136 +#define V7TAR_mtime_size 11 +#define V7TAR_mtime_max_size 12 +#define V7TAR_checksum_offset 148 +#define V7TAR_checksum_size 8 +#define V7TAR_typeflag_offset 156 +#define V7TAR_typeflag_size 1 +#define V7TAR_linkname_offset 157 +#define V7TAR_linkname_size 100 +#define V7TAR_padding_offset 257 +#define V7TAR_padding_size 255 + +/* + * A filled-in copy of the header for initialization. + */ +static const char template_header[] = { + /* name: 100 bytes */ + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0, + /* Mode, space-null termination: 8 bytes */ + '0','0','0','0','0','0', ' ','\0', + /* uid, space-null termination: 8 bytes */ + '0','0','0','0','0','0', ' ','\0', + /* gid, space-null termination: 8 bytes */ + '0','0','0','0','0','0', ' ','\0', + /* size, space termination: 12 bytes */ + '0','0','0','0','0','0','0','0','0','0','0', ' ', + /* mtime, space termination: 12 bytes */ + '0','0','0','0','0','0','0','0','0','0','0', ' ', + /* Initial checksum value: 8 spaces */ + ' ',' ',' ',' ',' ',' ',' ',' ', + /* Typeflag: 1 byte */ + 0, + /* Linkname: 100 bytes */ + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0, + /* Padding: 255 bytes */ + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0 +}; + +static ssize_t archive_write_v7tar_data(struct archive_write *a, const void *buff, + size_t s); +static int archive_write_v7tar_free(struct archive_write *); +static int archive_write_v7tar_close(struct archive_write *); +static int archive_write_v7tar_finish_entry(struct archive_write *); +static int archive_write_v7tar_header(struct archive_write *, + struct archive_entry *entry); +static int archive_write_v7tar_options(struct archive_write *, + const char *, const char *); +static int format_256(int64_t, char *, int); +static int format_number(int64_t, char *, int size, int max, int strict); +static int format_octal(int64_t, char *, int); +static int format_header_v7tar(struct archive_write *, char h[512], + struct archive_entry *, int, struct archive_string_conv *); + +/* + * Set output format to 'v7tar' format. + */ +int +archive_write_set_format_v7tar(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct v7tar *v7tar; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_set_format_v7tar"); + + /* If someone else was already registered, unregister them. */ + if (a->format_free != NULL) + (a->format_free)(a); + + /* Basic internal sanity test. */ + if (sizeof(template_header) != 512) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Internal: template_header wrong size: %zu should be 512", + sizeof(template_header)); + return (ARCHIVE_FATAL); + } + + v7tar = (struct v7tar *)calloc(1, sizeof(*v7tar)); + if (v7tar == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate v7tar data"); + return (ARCHIVE_FATAL); + } + a->format_data = v7tar; + a->format_name = "tar (non-POSIX)"; + a->format_options = archive_write_v7tar_options; + a->format_write_header = archive_write_v7tar_header; + a->format_write_data = archive_write_v7tar_data; + a->format_close = archive_write_v7tar_close; + a->format_free = archive_write_v7tar_free; + a->format_finish_entry = archive_write_v7tar_finish_entry; + a->archive.archive_format = ARCHIVE_FORMAT_TAR; + a->archive.archive_format_name = "tar (non-POSIX)"; + return (ARCHIVE_OK); +} + +static int +archive_write_v7tar_options(struct archive_write *a, const char *key, + const char *val) +{ + struct v7tar *v7tar = (struct v7tar *)a->format_data; + int ret = ARCHIVE_FAILED; + + if (strcmp(key, "hdrcharset") == 0) { + if (val == NULL || val[0] == 0) + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "%s: hdrcharset option needs a character-set name", + a->format_name); + else { + v7tar->opt_sconv = archive_string_conversion_to_charset( + &a->archive, val, 0); + if (v7tar->opt_sconv != NULL) + ret = ARCHIVE_OK; + else + ret = ARCHIVE_FATAL; + } + return (ret); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +static int +archive_write_v7tar_header(struct archive_write *a, struct archive_entry *entry) +{ + char buff[512]; + int ret, ret2; + struct v7tar *v7tar; + struct archive_entry *entry_main; + struct archive_string_conv *sconv; + + v7tar = (struct v7tar *)a->format_data; + + /* Setup default string conversion. */ + if (v7tar->opt_sconv == NULL) { + if (!v7tar->init_default_conversion) { + v7tar->sconv_default = + archive_string_default_conversion_for_write( + &(a->archive)); + v7tar->init_default_conversion = 1; + } + sconv = v7tar->sconv_default; + } else + sconv = v7tar->opt_sconv; + + /* Sanity check. */ + if (archive_entry_pathname(entry) == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't record entry in tar file without pathname"); + return (ARCHIVE_FAILED); + } + + /* Only regular files (not hardlinks) have data. */ + if (archive_entry_hardlink(entry) != NULL || + archive_entry_symlink(entry) != NULL || + !(archive_entry_filetype(entry) == AE_IFREG)) + archive_entry_set_size(entry, 0); + + if (AE_IFDIR == archive_entry_filetype(entry)) { + const char *p; + size_t path_length; + /* + * Ensure a trailing '/'. Modify the entry so + * the client sees the change. + */ +#if defined(_WIN32) && !defined(__CYGWIN__) + const wchar_t *wp; + + wp = archive_entry_pathname_w(entry); + if (wp != NULL && wp[wcslen(wp) -1] != L'/') { + struct archive_wstring ws; + + archive_string_init(&ws); + path_length = wcslen(wp); + if (archive_wstring_ensure(&ws, + path_length + 2) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate v7tar data"); + archive_wstring_free(&ws); + return(ARCHIVE_FATAL); + } + /* Should we keep '\' ? */ + if (wp[path_length -1] == L'\\') + path_length--; + archive_wstrncpy(&ws, wp, path_length); + archive_wstrappend_wchar(&ws, L'/'); + archive_entry_copy_pathname_w(entry, ws.s); + archive_wstring_free(&ws); + p = NULL; + } else +#endif + p = archive_entry_pathname(entry); + /* + * On Windows, this is a backup operation just in + * case getting WCS failed. On POSIX, this is a + * normal operation. + */ + if (p != NULL && p[0] != '\0' && p[strlen(p) - 1] != '/') { + struct archive_string as; + + archive_string_init(&as); + path_length = strlen(p); + if (archive_string_ensure(&as, + path_length + 2) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate v7tar data"); + archive_string_free(&as); + return(ARCHIVE_FATAL); + } +#if defined(_WIN32) && !defined(__CYGWIN__) + /* NOTE: This might break the pathname + * if the current code page is CP932 and + * the pathname includes a character '\' + * as a part of its multibyte pathname. */ + if (p[strlen(p) -1] == '\\') + path_length--; + else +#endif + archive_strncpy(&as, p, path_length); + archive_strappend_char(&as, '/'); + archive_entry_copy_pathname(entry, as.s); + archive_string_free(&as); + } + } + +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Make sure the path separators in pathname, hardlink and symlink + * are all slash '/', not the Windows path separator '\'. */ + entry_main = __la_win_entry_in_posix_pathseparator(entry); + if (entry_main == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate v7tar data"); + return(ARCHIVE_FATAL); + } + if (entry != entry_main) + entry = entry_main; + else + entry_main = NULL; +#else + entry_main = NULL; +#endif + ret = format_header_v7tar(a, buff, entry, 1, sconv); + if (ret < ARCHIVE_WARN) { + archive_entry_free(entry_main); + return (ret); + } + ret2 = __archive_write_output(a, buff, 512); + if (ret2 < ARCHIVE_WARN) { + archive_entry_free(entry_main); + return (ret2); + } + if (ret2 < ret) + ret = ret2; + + v7tar->entry_bytes_remaining = archive_entry_size(entry); + v7tar->entry_padding = 0x1ff & (-(int64_t)v7tar->entry_bytes_remaining); + archive_entry_free(entry_main); + return (ret); +} + +/* + * Format a basic 512-byte "v7tar" header. + * + * Returns -1 if format failed (due to field overflow). + * Note that this always formats as much of the header as possible. + * If "strict" is set to zero, it will extend numeric fields as + * necessary (overwriting terminators or using base-256 extensions). + * + */ +static int +format_header_v7tar(struct archive_write *a, char h[512], + struct archive_entry *entry, int strict, + struct archive_string_conv *sconv) +{ + unsigned int checksum; + int i, r, ret; + size_t copy_length; + const char *p, *pp; + int mytartype; + + ret = 0; + mytartype = -1; + /* + * The "template header" already includes the "v7tar" + * signature, various end-of-field markers and other required + * elements. + */ + memcpy(h, &template_header, 512); + + /* + * Because the block is already null-filled, and strings + * are allowed to exactly fill their destination (without null), + * I use memcpy(dest, src, strlen()) here a lot to copy strings. + */ + r = archive_entry_pathname_l(entry, &pp, ©_length, sconv); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Pathname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate pathname '%s' to %s", + pp, archive_string_conversion_charset_name(sconv)); + ret = ARCHIVE_WARN; + } + if (strict && copy_length < V7TAR_name_size) + memcpy(h + V7TAR_name_offset, pp, copy_length); + else if (!strict && copy_length <= V7TAR_name_size) + memcpy(h + V7TAR_name_offset, pp, copy_length); + else { + /* Prefix is too long. */ + archive_set_error(&a->archive, ENAMETOOLONG, + "Pathname too long"); + ret = ARCHIVE_FAILED; + } + + r = archive_entry_hardlink_l(entry, &p, ©_length, sconv); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Linkname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate linkname '%s' to %s", + p, archive_string_conversion_charset_name(sconv)); + ret = ARCHIVE_WARN; + } + if (copy_length > 0) + mytartype = '1'; + else { + r = archive_entry_symlink_l(entry, &p, ©_length, sconv); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Linkname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate linkname '%s' to %s", + p, archive_string_conversion_charset_name(sconv)); + ret = ARCHIVE_WARN; + } + } + if (copy_length > 0) { + if (copy_length >= V7TAR_linkname_size) { + archive_set_error(&a->archive, ENAMETOOLONG, + "Link contents too long"); + ret = ARCHIVE_FAILED; + copy_length = V7TAR_linkname_size; + } + memcpy(h + V7TAR_linkname_offset, p, copy_length); + } + + if (format_number(archive_entry_mode(entry) & 07777, + h + V7TAR_mode_offset, V7TAR_mode_size, + V7TAR_mode_max_size, strict)) { + archive_set_error(&a->archive, ERANGE, + "Numeric mode too large"); + ret = ARCHIVE_FAILED; + } + + if (format_number(archive_entry_uid(entry), + h + V7TAR_uid_offset, V7TAR_uid_size, V7TAR_uid_max_size, strict)) { + archive_set_error(&a->archive, ERANGE, + "Numeric user ID too large"); + ret = ARCHIVE_FAILED; + } + + if (format_number(archive_entry_gid(entry), + h + V7TAR_gid_offset, V7TAR_gid_size, V7TAR_gid_max_size, strict)) { + archive_set_error(&a->archive, ERANGE, + "Numeric group ID too large"); + ret = ARCHIVE_FAILED; + } + + if (format_number(archive_entry_size(entry), + h + V7TAR_size_offset, V7TAR_size_size, + V7TAR_size_max_size, strict)) { + archive_set_error(&a->archive, ERANGE, + "File size out of range"); + ret = ARCHIVE_FAILED; + } + + if (format_number(archive_entry_mtime(entry), + h + V7TAR_mtime_offset, V7TAR_mtime_size, + V7TAR_mtime_max_size, strict)) { + archive_set_error(&a->archive, ERANGE, + "File modification time too large"); + ret = ARCHIVE_FAILED; + } + + if (mytartype >= 0) { + h[V7TAR_typeflag_offset] = mytartype; + } else { + switch (archive_entry_filetype(entry)) { + case AE_IFREG: case AE_IFDIR: + break; + case AE_IFLNK: + h[V7TAR_typeflag_offset] = '2'; + break; + default: + /* AE_IFBLK, AE_IFCHR, AE_IFIFO, AE_IFSOCK + * and unknown */ + __archive_write_entry_filetype_unsupported( + &a->archive, entry, "v7tar"); + ret = ARCHIVE_FAILED; + } + } + + checksum = 0; + for (i = 0; i < 512; i++) + checksum += 255 & (unsigned int)h[i]; + format_octal(checksum, h + V7TAR_checksum_offset, 6); + /* Can't be pre-set in the template. */ + h[V7TAR_checksum_offset + 6] = '\0'; + return (ret); +} + +/* + * Format a number into a field, with some intelligence. + */ +static int +format_number(int64_t v, char *p, int s, int maxsize, int strict) +{ + int64_t limit; + + limit = ((int64_t)1 << (s*3)); + + /* "Strict" only permits octal values with proper termination. */ + if (strict) + return (format_octal(v, p, s)); + + /* + * In non-strict mode, we allow the number to overwrite one or + * more bytes of the field termination. Even old tar + * implementations should be able to handle this with no + * problem. + */ + if (v >= 0) { + while (s <= maxsize) { + if (v < limit) + return (format_octal(v, p, s)); + s++; + limit <<= 3; + } + } + + /* Base-256 can handle any number, positive or negative. */ + return (format_256(v, p, maxsize)); +} + +/* + * Format a number into the specified field using base-256. + */ +static int +format_256(int64_t v, char *p, int s) +{ + p += s; + while (s-- > 0) { + *--p = (char)(v & 0xff); + v >>= 8; + } + *p |= 0x80; /* Set the base-256 marker bit. */ + return (0); +} + +/* + * Format a number into the specified field. + */ +static int +format_octal(int64_t v, char *p, int s) +{ + int len; + + len = s; + + /* Octal values can't be negative, so use 0. */ + if (v < 0) { + while (len-- > 0) + *p++ = '0'; + return (-1); + } + + p += s; /* Start at the end and work backwards. */ + while (s-- > 0) { + *--p = (char)('0' + (v & 7)); + v >>= 3; + } + + if (v == 0) + return (0); + + /* If it overflowed, fill field with max value. */ + while (len-- > 0) + *p++ = '7'; + + return (-1); +} + +static int +archive_write_v7tar_close(struct archive_write *a) +{ + return (__archive_write_nulls(a, 512*2)); +} + +static int +archive_write_v7tar_free(struct archive_write *a) +{ + struct v7tar *v7tar; + + v7tar = (struct v7tar *)a->format_data; + free(v7tar); + a->format_data = NULL; + return (ARCHIVE_OK); +} + +static int +archive_write_v7tar_finish_entry(struct archive_write *a) +{ + struct v7tar *v7tar; + int ret; + + v7tar = (struct v7tar *)a->format_data; + ret = __archive_write_nulls(a, + (size_t)(v7tar->entry_bytes_remaining + v7tar->entry_padding)); + v7tar->entry_bytes_remaining = v7tar->entry_padding = 0; + return (ret); +} + +static ssize_t +archive_write_v7tar_data(struct archive_write *a, const void *buff, size_t s) +{ + struct v7tar *v7tar; + int ret; + + v7tar = (struct v7tar *)a->format_data; + if (s > v7tar->entry_bytes_remaining) + s = (size_t)v7tar->entry_bytes_remaining; + ret = __archive_write_output(a, buff, s); + v7tar->entry_bytes_remaining -= s; + if (ret != ARCHIVE_OK) + return (ret); + return (s); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_warc.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_warc.c new file mode 100644 index 0000000..46b0573 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_warc.c @@ -0,0 +1,453 @@ +/*- + * Copyright (c) 2014 Sebastian Freundt + * Author: Sebastian Freundt + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_TIME_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_private.h" +#include "archive_random_private.h" +#include "archive_write_private.h" +#include "archive_write_set_format_private.h" + +struct warc_s { + unsigned int omit_warcinfo:1; + + time_t now; + mode_t typ; + unsigned int rng; + /* populated size */ + uint64_t populz; +}; + +static const char warcinfo[] = + "software: libarchive/" ARCHIVE_VERSION_ONLY_STRING "\r\n" + "format: WARC file version 1.0\r\n"; + +typedef enum { + WT_NONE, + /* warcinfo */ + WT_INFO, + /* metadata */ + WT_META, + /* resource */ + WT_RSRC, + /* request, unsupported */ + WT_REQ, + /* response, unsupported */ + WT_RSP, + /* revisit, unsupported */ + WT_RVIS, + /* conversion, unsupported */ + WT_CONV, + /* continuation, unsupported at the moment */ + WT_CONT, + /* invalid type */ + LAST_WT +} warc_type_t; + +typedef struct { + warc_type_t type; + const char *tgturi; + const char *recid; + time_t rtime; + time_t mtime; + const char *cnttyp; + uint64_t cntlen; +} warc_essential_hdr_t; + +typedef struct { + unsigned int u[4U]; +} warc_uuid_t; + +static int _warc_options(struct archive_write*, const char *key, const char *v); +static int _warc_header(struct archive_write *a, struct archive_entry *entry); +static ssize_t _warc_data(struct archive_write *a, const void *buf, size_t sz); +static int _warc_finish_entry(struct archive_write *a); +static int _warc_close(struct archive_write *a); +static int _warc_free(struct archive_write *a); + +/* private routines */ +static ssize_t _popul_ehdr(struct archive_string *t, size_t z, warc_essential_hdr_t); +static int _gen_uuid(warc_uuid_t *tgt); + + +/* + * Set output format to ISO 28500 (aka WARC) format. + */ +int +archive_write_set_format_warc(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct warc_s *w; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_set_format_warc"); + + /* If another format was already registered, unregister it. */ + if (a->format_free != NULL) { + (a->format_free)(a); + } + + w = malloc(sizeof(*w)); + if (w == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate warc data"); + return (ARCHIVE_FATAL); + } + /* by default we're emitting a file wide header */ + w->omit_warcinfo = 0U; + /* obtain current time for date fields */ + w->now = time(NULL); + /* reset file type info */ + w->typ = 0; + /* also initialise our rng */ + w->rng = (unsigned int)w->now; + + a->format_data = w; + a->format_name = "WARC/1.0"; + a->format_options = _warc_options; + a->format_write_header = _warc_header; + a->format_write_data = _warc_data; + a->format_close = _warc_close; + a->format_free = _warc_free; + a->format_finish_entry = _warc_finish_entry; + a->archive.archive_format = ARCHIVE_FORMAT_WARC; + a->archive.archive_format_name = "WARC/1.0"; + return (ARCHIVE_OK); +} + + +/* archive methods */ +static int +_warc_options(struct archive_write *a, const char *key, const char *val) +{ + struct warc_s *w = a->format_data; + + if (strcmp(key, "omit-warcinfo") == 0) { + if (val == NULL || strcmp(val, "true") == 0) { + /* great */ + w->omit_warcinfo = 1U; + return (ARCHIVE_OK); + } + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +static int +_warc_header(struct archive_write *a, struct archive_entry *entry) +{ + struct warc_s *w = a->format_data; + struct archive_string hdr; +#define MAX_HDR_SIZE 512 + + /* check whether warcinfo record needs outputting */ + if (!w->omit_warcinfo) { + ssize_t r; + warc_essential_hdr_t wi = { + WT_INFO, + /*uri*/NULL, + /*urn*/NULL, + /*rtm*/0, + /*mtm*/0, + /*cty*/"application/warc-fields", + /*len*/sizeof(warcinfo) - 1U, + }; + wi.rtime = w->now; + wi.mtime = w->now; + + archive_string_init(&hdr); + r = _popul_ehdr(&hdr, MAX_HDR_SIZE, wi); + if (r >= 0) { + /* jackpot! */ + /* now also use HDR buffer for the actual warcinfo */ + archive_strncat(&hdr, warcinfo, sizeof(warcinfo) -1); + + /* append end-of-record indicator */ + archive_strncat(&hdr, "\r\n\r\n", 4); + + /* write to output stream */ + __archive_write_output(a, hdr.s, archive_strlen(&hdr)); + } + /* indicate we're done with file header writing */ + w->omit_warcinfo = 1U; + archive_string_free(&hdr); + } + + if (archive_entry_pathname(entry) == NULL) { + archive_set_error(&a->archive, EINVAL, + "Invalid filename"); + return (ARCHIVE_WARN); + } + + w->typ = archive_entry_filetype(entry); + w->populz = 0U; + if (w->typ == AE_IFREG) { + warc_essential_hdr_t rh = { + WT_RSRC, + /*uri*/NULL, + /*urn*/NULL, + /*rtm*/0, + /*mtm*/0, + /*cty*/NULL, + /*len*/0, + }; + ssize_t r; + rh.tgturi = archive_entry_pathname(entry); + rh.rtime = w->now; + rh.mtime = archive_entry_mtime(entry); + rh.cntlen = (size_t)archive_entry_size(entry); + + archive_string_init(&hdr); + r = _popul_ehdr(&hdr, MAX_HDR_SIZE, rh); + if (r < 0) { + /* don't bother */ + archive_set_error( + &a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "cannot archive file"); + return (ARCHIVE_WARN); + } + /* otherwise append to output stream */ + __archive_write_output(a, hdr.s, r); + /* and let subsequent calls to _data() know about the size */ + w->populz = rh.cntlen; + archive_string_free(&hdr); + return (ARCHIVE_OK); + } + /* just resort to erroring as per Tim's advice */ + __archive_write_entry_filetype_unsupported( + &a->archive, entry, "WARC"); + return (ARCHIVE_FAILED); +} + +static ssize_t +_warc_data(struct archive_write *a, const void *buf, size_t len) +{ + struct warc_s *w = a->format_data; + + if (w->typ == AE_IFREG) { + int rc; + + /* never write more bytes than announced */ + if (len > w->populz) { + len = (size_t)w->populz; + } + + /* now then, out we put the whole shebang */ + rc = __archive_write_output(a, buf, len); + if (rc != ARCHIVE_OK) { + return rc; + } + } + return len; +} + +static int +_warc_finish_entry(struct archive_write *a) +{ + static const char _eor[] = "\r\n\r\n"; + struct warc_s *w = a->format_data; + + if (w->typ == AE_IFREG) { + int rc = __archive_write_output(a, _eor, sizeof(_eor) - 1U); + + if (rc != ARCHIVE_OK) { + return rc; + } + } + /* reset type info */ + w->typ = 0; + return (ARCHIVE_OK); +} + +static int +_warc_close(struct archive_write *a) +{ + (void)a; /* UNUSED */ + return (ARCHIVE_OK); +} + +static int +_warc_free(struct archive_write *a) +{ + struct warc_s *w = a->format_data; + + free(w); + a->format_data = NULL; + return (ARCHIVE_OK); +} + + +/* private routines */ +static void +xstrftime(struct archive_string *as, const char *fmt, time_t t) +{ +/** like strftime(3) but for time_t objects */ + struct tm *rt; +#if defined(HAVE_GMTIME_R) || defined(HAVE__GMTIME64_S) + struct tm timeHere; +#endif +#if defined(HAVE__GMTIME64_S) + errno_t terr; + __time64_t tmptime; +#endif + char strtime[100]; + size_t len; + +#ifdef HAVE_GMTIME_R + if ((rt = gmtime_r(&t, &timeHere)) == NULL) + return; +#elif defined(HAVE__GMTIME64_S) + tmptime = t; + terr = _gmtime64_s(&timeHere, &tmptime); + if (terr) + rt = NULL; + else + rt = &timeHere; +#else + if ((rt = gmtime(&t)) == NULL) + return; +#endif + /* leave the hard yacker to our role model strftime() */ + len = strftime(strtime, sizeof(strtime)-1, fmt, rt); + archive_strncat(as, strtime, len); +} + +static ssize_t +_popul_ehdr(struct archive_string *tgt, size_t tsz, warc_essential_hdr_t hdr) +{ + static const char _ver[] = "WARC/1.0\r\n"; + static const char * const _typ[LAST_WT] = { + NULL, "warcinfo", "metadata", "resource", NULL + }; + char std_uuid[48U]; + + if (hdr.type == WT_NONE || hdr.type > WT_RSRC) { + /* brilliant, how exactly did we get here? */ + return -1; + } + + archive_strcpy(tgt, _ver); + + archive_string_sprintf(tgt, "WARC-Type: %s\r\n", _typ[hdr.type]); + + if (hdr.tgturi != NULL) { + /* check if there's a xyz:// */ + static const char _uri[] = ""; + static const char _fil[] = "file://"; + const char *u; + char *chk = strchr(hdr.tgturi, ':'); + + if (chk != NULL && chk[1U] == '/' && chk[2U] == '/') { + /* yep, it's definitely a URI */ + u = _uri; + } else { + /* hm, best to prepend file:// then */ + u = _fil; + } + archive_string_sprintf(tgt, + "WARC-Target-URI: %s%s\r\n", u, hdr.tgturi); + } + + /* record time is usually when the http is sent off, + * just treat the archive writing as such for a moment */ + xstrftime(tgt, "WARC-Date: %Y-%m-%dT%H:%M:%SZ\r\n", hdr.rtime); + + /* while we're at it, record the mtime */ + xstrftime(tgt, "Last-Modified: %Y-%m-%dT%H:%M:%SZ\r\n", hdr.mtime); + + if (hdr.recid == NULL) { + /* generate one, grrrr */ + warc_uuid_t u; + + _gen_uuid(&u); + /* Unfortunately, archive_string_sprintf does not + * handle the minimum number following '%'. + * So we have to use snprintf function here instead + * of archive_string_snprintf function. */ +#if defined(_WIN32) && !defined(__CYGWIN__) && !( defined(_MSC_VER) && _MSC_VER >= 1900) +#define snprintf _snprintf +#endif + snprintf( + std_uuid, sizeof(std_uuid), + "", + u.u[0U], + u.u[1U] >> 16U, u.u[1U] & 0xffffU, + u.u[2U] >> 16U, u.u[2U] & 0xffffU, + u.u[3U]); + hdr.recid = std_uuid; + } + + /* record-id is mandatory, fingers crossed we won't fail */ + archive_string_sprintf(tgt, "WARC-Record-ID: %s\r\n", hdr.recid); + + if (hdr.cnttyp != NULL) { + archive_string_sprintf(tgt, "Content-Type: %s\r\n", hdr.cnttyp); + } + + /* next one is mandatory */ + archive_string_sprintf(tgt, "Content-Length: %ju\r\n", (uintmax_t)hdr.cntlen); + /**/ + archive_strncat(tgt, "\r\n", 2); + + return (archive_strlen(tgt) >= tsz)? -1: (ssize_t)archive_strlen(tgt); +} + +static int +_gen_uuid(warc_uuid_t *tgt) +{ + archive_random(tgt->u, sizeof(tgt->u)); + /* obey uuid version 4 rules */ + tgt->u[1U] &= 0xffff0fffU; + tgt->u[1U] |= 0x4000U; + tgt->u[2U] &= 0x3fffffffU; + tgt->u[2U] |= 0x80000000U; + return 0; +} + +/* archive_write_set_format_warc.c ends here */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_xar.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_xar.c new file mode 100644 index 0000000..d456cf8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_xar.c @@ -0,0 +1,3258 @@ +/*- + * Copyright (c) 2010-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#include +#if HAVE_LIBXML_XMLWRITER_H +#include +#endif +#ifdef HAVE_BZLIB_H +#include +#endif +#if HAVE_LZMA_H +#include +#endif +#ifdef HAVE_ZLIB_H +#include +#endif + +#include "archive.h" +#include "archive_digest_private.h" +#include "archive_endian.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_private.h" +#include "archive_rb.h" +#include "archive_string.h" +#include "archive_write_private.h" + +/* + * Differences to xar utility. + * - Subdocument is not supported yet. + * - ACL is not supported yet. + * - When writing an XML element , + * which is a file type a symbolic link is referencing is always marked + * as "broken". Xar utility uses stat(2) to get the file type, but, in + * libarchive format writer, we should not use it; if it is needed, we + * should get about it at archive_read_disk.c. + * - It is possible to appear both and elements. + * Xar utility generates on BSD platform and on Linux + * platform. + * + */ + +#if !(defined(HAVE_LIBXML_XMLWRITER_H) && defined(LIBXML_VERSION) &&\ + LIBXML_VERSION >= 20703) ||\ + !defined(HAVE_ZLIB_H) || \ + !defined(ARCHIVE_HAS_MD5) || !defined(ARCHIVE_HAS_SHA1) +/* + * xar needs several external libraries. + * o libxml2 + * o openssl or MD5/SHA1 hash function + * o zlib + * o bzlib2 (option) + * o liblzma (option) + */ +int +archive_write_set_format_xar(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Xar not supported on this platform"); + return (ARCHIVE_WARN); +} + +#else /* Support xar format */ + +/*#define DEBUG_PRINT_TOC 1 */ + +#define BAD_CAST_CONST (const xmlChar *) + +#define HEADER_MAGIC 0x78617221 +#define HEADER_SIZE 28 +#define HEADER_VERSION 1 + +enum sumalg { + CKSUM_NONE = 0, + CKSUM_SHA1 = 1, + CKSUM_MD5 = 2 +}; + +#define MD5_SIZE 16 +#define SHA1_SIZE 20 +#define MAX_SUM_SIZE 20 +#define MD5_NAME "md5" +#define SHA1_NAME "sha1" + +enum enctype { + NONE, + GZIP, + BZIP2, + LZMA, + XZ, +}; + +struct chksumwork { + enum sumalg alg; +#ifdef ARCHIVE_HAS_MD5 + archive_md5_ctx md5ctx; +#endif +#ifdef ARCHIVE_HAS_SHA1 + archive_sha1_ctx sha1ctx; +#endif +}; + +enum la_zaction { + ARCHIVE_Z_FINISH, + ARCHIVE_Z_RUN +}; + +/* + * Universal zstream. + */ +struct la_zstream { + const unsigned char *next_in; + size_t avail_in; + uint64_t total_in; + + unsigned char *next_out; + size_t avail_out; + uint64_t total_out; + + int valid; + void *real_stream; + int (*code) (struct archive *a, + struct la_zstream *lastrm, + enum la_zaction action); + int (*end)(struct archive *a, + struct la_zstream *lastrm); +}; + +struct chksumval { + enum sumalg alg; + size_t len; + unsigned char val[MAX_SUM_SIZE]; +}; + +struct heap_data { + int id; + struct heap_data *next; + uint64_t temp_offset; + uint64_t length; /* archived size. */ + uint64_t size; /* extracted size. */ + enum enctype compression; + struct chksumval a_sum; /* archived checksum. */ + struct chksumval e_sum; /* extracted checksum. */ +}; + +struct file { + struct archive_rb_node rbnode; + + int id; + struct archive_entry *entry; + + struct archive_rb_tree rbtree; + struct file *next; + struct file *chnext; + struct file *hlnext; + /* For hardlinked files. + * Use only when archive_entry_nlink() > 1 */ + struct file *hardlink_target; + struct file *parent; /* parent directory entry */ + /* + * To manage sub directory files. + * We use 'chnext' (a member of struct file) to chain. + */ + struct { + struct file *first; + struct file **last; + } children; + + /* For making a directory tree. */ + struct archive_string parentdir; + struct archive_string basename; + struct archive_string symlink; + + int ea_idx; + struct { + struct heap_data *first; + struct heap_data **last; + } xattr; + struct heap_data data; + struct archive_string script; + + signed int virtual:1; + signed int dir:1; +}; + +struct hardlink { + struct archive_rb_node rbnode; + int nlink; + struct { + struct file *first; + struct file **last; + } file_list; +}; + +struct xar { + int temp_fd; + uint64_t temp_offset; + + int file_idx; + struct file *root; + struct file *cur_dirent; + struct archive_string cur_dirstr; + struct file *cur_file; + uint64_t bytes_remaining; + struct archive_string tstr; + struct archive_string vstr; + + enum sumalg opt_toc_sumalg; + enum sumalg opt_sumalg; + enum enctype opt_compression; + int opt_compression_level; + uint32_t opt_threads; + + struct chksumwork a_sumwrk; /* archived checksum. */ + struct chksumwork e_sumwrk; /* extracted checksum. */ + struct la_zstream stream; + struct archive_string_conv *sconv; + /* + * Compressed data buffer. + */ + unsigned char wbuff[1024 * 64]; + size_t wbuff_remaining; + + struct heap_data toc; + /* + * The list of all file entries is used to manage struct file + * objects. + * We use 'next' (a member of struct file) to chain. + */ + struct { + struct file *first; + struct file **last; + } file_list; + /* + * The list of hard-linked file entries. + * We use 'hlnext' (a member of struct file) to chain. + */ + struct archive_rb_tree hardlink_rbtree; +}; + +static int xar_options(struct archive_write *, + const char *, const char *); +static int xar_write_header(struct archive_write *, + struct archive_entry *); +static ssize_t xar_write_data(struct archive_write *, + const void *, size_t); +static int xar_finish_entry(struct archive_write *); +static int xar_close(struct archive_write *); +static int xar_free(struct archive_write *); + +static struct file *file_new(struct archive_write *a, struct archive_entry *); +static void file_free(struct file *); +static struct file *file_create_virtual_dir(struct archive_write *a, struct xar *, + const char *); +static int file_add_child_tail(struct file *, struct file *); +static struct file *file_find_child(struct file *, const char *); +static int file_gen_utility_names(struct archive_write *, + struct file *); +static int get_path_component(char *, int, const char *); +static int file_tree(struct archive_write *, struct file **); +static void file_register(struct xar *, struct file *); +static void file_init_register(struct xar *); +static void file_free_register(struct xar *); +static int file_register_hardlink(struct archive_write *, + struct file *); +static void file_connect_hardlink_files(struct xar *); +static void file_init_hardlinks(struct xar *); +static void file_free_hardlinks(struct xar *); + +static void checksum_init(struct chksumwork *, enum sumalg); +static void checksum_update(struct chksumwork *, const void *, size_t); +static void checksum_final(struct chksumwork *, struct chksumval *); +static int compression_init_encoder_gzip(struct archive *, + struct la_zstream *, int, int); +static int compression_code_gzip(struct archive *, + struct la_zstream *, enum la_zaction); +static int compression_end_gzip(struct archive *, struct la_zstream *); +static int compression_init_encoder_bzip2(struct archive *, + struct la_zstream *, int); +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) +static int compression_code_bzip2(struct archive *, + struct la_zstream *, enum la_zaction); +static int compression_end_bzip2(struct archive *, struct la_zstream *); +#endif +static int compression_init_encoder_lzma(struct archive *, + struct la_zstream *, int); +static int compression_init_encoder_xz(struct archive *, + struct la_zstream *, int, int); +#if defined(HAVE_LZMA_H) +static int compression_code_lzma(struct archive *, + struct la_zstream *, enum la_zaction); +static int compression_end_lzma(struct archive *, struct la_zstream *); +#endif +static int xar_compression_init_encoder(struct archive_write *); +static int compression_code(struct archive *, + struct la_zstream *, enum la_zaction); +static int compression_end(struct archive *, + struct la_zstream *); +static int save_xattrs(struct archive_write *, struct file *); +static int getalgsize(enum sumalg); +static const char *getalgname(enum sumalg); + +int +archive_write_set_format_xar(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct xar *xar; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_set_format_xar"); + + /* If another format was already registered, unregister it. */ + if (a->format_free != NULL) + (a->format_free)(a); + + xar = calloc(1, sizeof(*xar)); + if (xar == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate xar data"); + return (ARCHIVE_FATAL); + } + xar->temp_fd = -1; + file_init_register(xar); + file_init_hardlinks(xar); + archive_string_init(&(xar->tstr)); + archive_string_init(&(xar->vstr)); + + /* + * Create the root directory. + */ + xar->root = file_create_virtual_dir(a, xar, ""); + if (xar->root == NULL) { + free(xar); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate xar data"); + return (ARCHIVE_FATAL); + } + xar->root->parent = xar->root; + file_register(xar, xar->root); + xar->cur_dirent = xar->root; + archive_string_init(&(xar->cur_dirstr)); + archive_string_ensure(&(xar->cur_dirstr), 1); + xar->cur_dirstr.s[0] = 0; + + /* + * Initialize option. + */ + /* Set default checksum type. */ + xar->opt_toc_sumalg = CKSUM_SHA1; + xar->opt_sumalg = CKSUM_SHA1; + /* Set default compression type, level, and number of threads. */ + xar->opt_compression = GZIP; + xar->opt_compression_level = 6; + xar->opt_threads = 1; + + a->format_data = xar; + + a->format_name = "xar"; + a->format_options = xar_options; + a->format_write_header = xar_write_header; + a->format_write_data = xar_write_data; + a->format_finish_entry = xar_finish_entry; + a->format_close = xar_close; + a->format_free = xar_free; + a->archive.archive_format = ARCHIVE_FORMAT_XAR; + a->archive.archive_format_name = "xar"; + + return (ARCHIVE_OK); +} + +static int +xar_options(struct archive_write *a, const char *key, const char *value) +{ + struct xar *xar; + + xar = (struct xar *)a->format_data; + + if (strcmp(key, "checksum") == 0) { + if (value == NULL) + xar->opt_sumalg = CKSUM_NONE; + else if (strcmp(value, "none") == 0) + xar->opt_sumalg = CKSUM_NONE; + else if (strcmp(value, "sha1") == 0) + xar->opt_sumalg = CKSUM_SHA1; + else if (strcmp(value, "md5") == 0) + xar->opt_sumalg = CKSUM_MD5; + else { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Unknown checksum name: `%s'", + value); + return (ARCHIVE_FAILED); + } + return (ARCHIVE_OK); + } + if (strcmp(key, "compression") == 0) { + const char *name = NULL; + + if (value == NULL) + xar->opt_compression = NONE; + else if (strcmp(value, "none") == 0) + xar->opt_compression = NONE; + else if (strcmp(value, "gzip") == 0) + xar->opt_compression = GZIP; + else if (strcmp(value, "bzip2") == 0) +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) + xar->opt_compression = BZIP2; +#else + name = "bzip2"; +#endif + else if (strcmp(value, "lzma") == 0) +#if HAVE_LZMA_H + xar->opt_compression = LZMA; +#else + name = "lzma"; +#endif + else if (strcmp(value, "xz") == 0) +#if HAVE_LZMA_H + xar->opt_compression = XZ; +#else + name = "xz"; +#endif + else { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Unknown compression name: `%s'", + value); + return (ARCHIVE_FAILED); + } + if (name != NULL) { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "`%s' compression not supported " + "on this platform", + name); + return (ARCHIVE_FAILED); + } + return (ARCHIVE_OK); + } + if (strcmp(key, "compression-level") == 0) { + if (value == NULL || + !(value[0] >= '0' && value[0] <= '9') || + value[1] != '\0') { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Illegal value `%s'", + value); + return (ARCHIVE_FAILED); + } + xar->opt_compression_level = value[0] - '0'; + return (ARCHIVE_OK); + } + if (strcmp(key, "toc-checksum") == 0) { + if (value == NULL) + xar->opt_toc_sumalg = CKSUM_NONE; + else if (strcmp(value, "none") == 0) + xar->opt_toc_sumalg = CKSUM_NONE; + else if (strcmp(value, "sha1") == 0) + xar->opt_toc_sumalg = CKSUM_SHA1; + else if (strcmp(value, "md5") == 0) + xar->opt_toc_sumalg = CKSUM_MD5; + else { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Unknown checksum name: `%s'", + value); + return (ARCHIVE_FAILED); + } + return (ARCHIVE_OK); + } + if (strcmp(key, "threads") == 0) { + char *endptr; + + if (value == NULL) + return (ARCHIVE_FAILED); + errno = 0; + xar->opt_threads = (int)strtoul(value, &endptr, 10); + if (errno != 0 || *endptr != '\0') { + xar->opt_threads = 1; + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Illegal value `%s'", + value); + return (ARCHIVE_FAILED); + } + if (xar->opt_threads == 0) { +#ifdef HAVE_LZMA_STREAM_ENCODER_MT + xar->opt_threads = lzma_cputhreads(); +#else + xar->opt_threads = 1; +#endif + } + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +static int +xar_write_header(struct archive_write *a, struct archive_entry *entry) +{ + struct xar *xar; + struct file *file; + struct archive_entry *file_entry; + int r, r2; + + xar = (struct xar *)a->format_data; + xar->cur_file = NULL; + xar->bytes_remaining = 0; + + if (xar->sconv == NULL) { + xar->sconv = archive_string_conversion_to_charset( + &a->archive, "UTF-8", 1); + if (xar->sconv == NULL) + return (ARCHIVE_FATAL); + } + + file = file_new(a, entry); + if (file == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate data"); + return (ARCHIVE_FATAL); + } + r2 = file_gen_utility_names(a, file); + if (r2 < ARCHIVE_WARN) + return (r2); + + /* + * Ignore a path which looks like the top of directory name + * since we have already made the root directory of an Xar archive. + */ + if (archive_strlen(&(file->parentdir)) == 0 && + archive_strlen(&(file->basename)) == 0) { + file_free(file); + return (r2); + } + + /* Add entry into tree */ + file_entry = file->entry; + r = file_tree(a, &file); + if (r != ARCHIVE_OK) + return (r); + /* There is the same file in tree and + * the current file is older than the file in tree. + * So we don't need the current file data anymore. */ + if (file->entry != file_entry) + return (r2); + if (file->id == 0) + file_register(xar, file); + + /* A virtual file, which is a directory, does not have + * any contents and we won't store it into a archive + * file other than its name. */ + if (file->virtual) + return (r2); + + /* + * Prepare to save the contents of the file. + */ + if (xar->temp_fd == -1) { + int algsize; + xar->temp_offset = 0; + xar->temp_fd = __archive_mktemp(NULL); + if (xar->temp_fd < 0) { + archive_set_error(&a->archive, errno, + "Couldn't create temporary file"); + return (ARCHIVE_FATAL); + } + algsize = getalgsize(xar->opt_toc_sumalg); + if (algsize > 0) { + if (lseek(xar->temp_fd, algsize, SEEK_SET) < 0) { + archive_set_error(&(a->archive), errno, + "lseek failed"); + return (ARCHIVE_FATAL); + } + xar->temp_offset = algsize; + } + } + + if (archive_entry_hardlink(file->entry) == NULL) { + r = save_xattrs(a, file); + if (r != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + + /* Non regular files contents are unneeded to be saved to + * a temporary file. */ + if (archive_entry_filetype(file->entry) != AE_IFREG) + return (r2); + + /* + * Set the current file to cur_file to read its contents. + */ + xar->cur_file = file; + + if (archive_entry_nlink(file->entry) > 1) { + r = file_register_hardlink(a, file); + if (r != ARCHIVE_OK) + return (r); + if (archive_entry_hardlink(file->entry) != NULL) { + archive_entry_unset_size(file->entry); + return (r2); + } + } + + /* Save a offset of current file in temporary file. */ + file->data.temp_offset = xar->temp_offset; + file->data.size = archive_entry_size(file->entry); + file->data.compression = xar->opt_compression; + xar->bytes_remaining = archive_entry_size(file->entry); + checksum_init(&(xar->a_sumwrk), xar->opt_sumalg); + checksum_init(&(xar->e_sumwrk), xar->opt_sumalg); + r = xar_compression_init_encoder(a); + + if (r != ARCHIVE_OK) + return (r); + else + return (r2); +} + +static int +write_to_temp(struct archive_write *a, const void *buff, size_t s) +{ + struct xar *xar; + const unsigned char *p; + ssize_t ws; + + xar = (struct xar *)a->format_data; + p = (const unsigned char *)buff; + while (s) { + ws = write(xar->temp_fd, p, s); + if (ws < 0) { + archive_set_error(&(a->archive), errno, + "fwrite function failed"); + return (ARCHIVE_FATAL); + } + s -= ws; + p += ws; + xar->temp_offset += ws; + } + return (ARCHIVE_OK); +} + +static ssize_t +xar_write_data(struct archive_write *a, const void *buff, size_t s) +{ + struct xar *xar; + enum la_zaction run; + size_t size, rsize; + int r; + + xar = (struct xar *)a->format_data; + + if (s > xar->bytes_remaining) + s = (size_t)xar->bytes_remaining; + if (s == 0 || xar->cur_file == NULL) + return (0); + if (xar->cur_file->data.compression == NONE) { + checksum_update(&(xar->e_sumwrk), buff, s); + checksum_update(&(xar->a_sumwrk), buff, s); + size = rsize = s; + } else { + xar->stream.next_in = (const unsigned char *)buff; + xar->stream.avail_in = s; + if (xar->bytes_remaining > s) + run = ARCHIVE_Z_RUN; + else + run = ARCHIVE_Z_FINISH; + /* Compress file data. */ + for (;;) { + r = compression_code(&(a->archive), &(xar->stream), + run); + if (r != ARCHIVE_OK && r != ARCHIVE_EOF) + return (ARCHIVE_FATAL); + if (xar->stream.avail_out == 0 || + run == ARCHIVE_Z_FINISH) { + size = sizeof(xar->wbuff) - + xar->stream.avail_out; + checksum_update(&(xar->a_sumwrk), xar->wbuff, + size); + xar->cur_file->data.length += size; + if (write_to_temp(a, xar->wbuff, + size) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + if (r == ARCHIVE_OK) { + /* Output buffer was full */ + xar->stream.next_out = xar->wbuff; + xar->stream.avail_out = + sizeof(xar->wbuff); + } else { + /* ARCHIVE_EOF - We are done */ + break; + } + } else { + /* Compressor wants more input */ + break; + } + } + rsize = s - xar->stream.avail_in; + checksum_update(&(xar->e_sumwrk), buff, rsize); + } +#if !defined(_WIN32) || defined(__CYGWIN__) + if (xar->bytes_remaining == + (uint64_t)archive_entry_size(xar->cur_file->entry)) { + /* + * Get the path of a shell script if so. + */ + const unsigned char *b = (const unsigned char *)buff; + + archive_string_empty(&(xar->cur_file->script)); + if (rsize > 2 && b[0] == '#' && b[1] == '!') { + size_t i, end, off; + + off = 2; + if (b[off] == ' ') + off++; +#ifdef PATH_MAX + if ((rsize - off) > PATH_MAX) + end = off + PATH_MAX; + else +#endif + end = rsize; + /* Find the end of a script path. */ + for (i = off; i < end && b[i] != '\0' && + b[i] != '\n' && b[i] != '\r' && + b[i] != ' ' && b[i] != '\t'; i++) + ; + archive_strncpy(&(xar->cur_file->script), b + off, + i - off); + } + } +#endif + + if (xar->cur_file->data.compression == NONE) { + if (write_to_temp(a, buff, size) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + xar->cur_file->data.length += size; + } + xar->bytes_remaining -= rsize; + + return (rsize); +} + +static int +xar_finish_entry(struct archive_write *a) +{ + struct xar *xar; + struct file *file; + size_t s; + ssize_t w; + + xar = (struct xar *)a->format_data; + if (xar->cur_file == NULL) + return (ARCHIVE_OK); + + while (xar->bytes_remaining > 0) { + s = (size_t)xar->bytes_remaining; + if (s > a->null_length) + s = a->null_length; + w = xar_write_data(a, a->nulls, s); + if (w > 0) + xar->bytes_remaining -= w; + else + return (w); + } + file = xar->cur_file; + checksum_final(&(xar->e_sumwrk), &(file->data.e_sum)); + checksum_final(&(xar->a_sumwrk), &(file->data.a_sum)); + xar->cur_file = NULL; + + return (ARCHIVE_OK); +} + +static int +xmlwrite_string_attr(struct archive_write *a, xmlTextWriterPtr writer, + const char *key, const char *value, + const char *attrkey, const char *attrvalue) +{ + int r; + + r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(key)); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + if (attrkey != NULL && attrvalue != NULL) { + r = xmlTextWriterWriteAttribute(writer, + BAD_CAST_CONST(attrkey), BAD_CAST_CONST(attrvalue)); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterWriteAttribute() failed: %d", r); + return (ARCHIVE_FATAL); + } + } + if (value != NULL) { + r = xmlTextWriterWriteString(writer, BAD_CAST_CONST(value)); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterWriteString() failed: %d", r); + return (ARCHIVE_FATAL); + } + } + r = xmlTextWriterEndElement(writer); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterEndElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + return (ARCHIVE_OK); +} + +static int +xmlwrite_string(struct archive_write *a, xmlTextWriterPtr writer, + const char *key, const char *value) +{ + int r; + + if (value == NULL) + return (ARCHIVE_OK); + + r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(key)); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + if (value != NULL) { + r = xmlTextWriterWriteString(writer, BAD_CAST_CONST(value)); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterWriteString() failed: %d", r); + return (ARCHIVE_FATAL); + } + } + r = xmlTextWriterEndElement(writer); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterEndElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + return (ARCHIVE_OK); +} + +static int +xmlwrite_fstring(struct archive_write *a, xmlTextWriterPtr writer, + const char *key, const char *fmt, ...) +{ + struct xar *xar; + va_list ap; + + xar = (struct xar *)a->format_data; + va_start(ap, fmt); + archive_string_empty(&xar->vstr); + archive_string_vsprintf(&xar->vstr, fmt, ap); + va_end(ap); + return (xmlwrite_string(a, writer, key, xar->vstr.s)); +} + +static int +xmlwrite_time(struct archive_write *a, xmlTextWriterPtr writer, + const char *key, time_t t, int z) +{ + char timestr[100]; + struct tm tm; +#if defined(HAVE__GMTIME64_S) + __time64_t tmptime; +#endif + +#if defined(HAVE_GMTIME_R) + gmtime_r(&t, &tm); +#elif defined(HAVE__GMTIME64_S) + tmptime = t; + _gmtime64_s(&tm, &tmptime); +#else + memcpy(&tm, gmtime(&t), sizeof(tm)); +#endif + memset(×tr, 0, sizeof(timestr)); + /* Do not use %F and %T for portability. */ + strftime(timestr, sizeof(timestr), "%Y-%m-%dT%H:%M:%S", &tm); + if (z) + strcat(timestr, "Z"); + return (xmlwrite_string(a, writer, key, timestr)); +} + +static int +xmlwrite_mode(struct archive_write *a, xmlTextWriterPtr writer, + const char *key, mode_t mode) +{ + char ms[5]; + + ms[0] = '0'; + ms[1] = '0' + ((mode >> 6) & 07); + ms[2] = '0' + ((mode >> 3) & 07); + ms[3] = '0' + (mode & 07); + ms[4] = '\0'; + + return (xmlwrite_string(a, writer, key, ms)); +} + +static int +xmlwrite_sum(struct archive_write *a, xmlTextWriterPtr writer, + const char *key, struct chksumval *sum) +{ + const char *algname; + int algsize; + char buff[MAX_SUM_SIZE*2 + 1]; + char *p; + unsigned char *s; + int i, r; + + if (sum->len > 0) { + algname = getalgname(sum->alg); + algsize = getalgsize(sum->alg); + if (algname != NULL) { + const char *hex = "0123456789abcdef"; + p = buff; + s = sum->val; + for (i = 0; i < algsize; i++) { + *p++ = hex[(*s >> 4)]; + *p++ = hex[(*s & 0x0f)]; + s++; + } + *p = '\0'; + r = xmlwrite_string_attr(a, writer, + key, buff, + "style", algname); + if (r < 0) + return (ARCHIVE_FATAL); + } + } + return (ARCHIVE_OK); +} + +static int +xmlwrite_heap(struct archive_write *a, xmlTextWriterPtr writer, + struct heap_data *heap) +{ + const char *encname; + int r; + + r = xmlwrite_fstring(a, writer, "length", "%ju", heap->length); + if (r < 0) + return (ARCHIVE_FATAL); + r = xmlwrite_fstring(a, writer, "offset", "%ju", heap->temp_offset); + if (r < 0) + return (ARCHIVE_FATAL); + r = xmlwrite_fstring(a, writer, "size", "%ju", heap->size); + if (r < 0) + return (ARCHIVE_FATAL); + switch (heap->compression) { + case GZIP: + encname = "application/x-gzip"; break; + case BZIP2: + encname = "application/x-bzip2"; break; + case LZMA: + encname = "application/x-lzma"; break; + case XZ: + encname = "application/x-xz"; break; + default: + encname = "application/octet-stream"; break; + } + r = xmlwrite_string_attr(a, writer, "encoding", NULL, + "style", encname); + if (r < 0) + return (ARCHIVE_FATAL); + r = xmlwrite_sum(a, writer, "archived-checksum", &(heap->a_sum)); + if (r < 0) + return (ARCHIVE_FATAL); + r = xmlwrite_sum(a, writer, "extracted-checksum", &(heap->e_sum)); + if (r < 0) + return (ARCHIVE_FATAL); + return (ARCHIVE_OK); +} + +/* + * xar utility records fflags as following xml elements: + * + * + * ..... + * + * or + * + * + * ..... + * + * If xar is running on BSD platform, records ..; + * if xar is running on linux platform, records ..; + * otherwise does not record. + * + * Our implements records both and if it's necessary. + */ +static int +make_fflags_entry(struct archive_write *a, xmlTextWriterPtr writer, + const char *element, const char *fflags_text) +{ + static const struct flagentry { + const char *name; + const char *xarname; + } + flagbsd[] = { + { "sappnd", "SystemAppend"}, + { "sappend", "SystemAppend"}, + { "arch", "SystemArchived"}, + { "archived", "SystemArchived"}, + { "schg", "SystemImmutable"}, + { "schange", "SystemImmutable"}, + { "simmutable", "SystemImmutable"}, + { "nosunlnk", "SystemNoUnlink"}, + { "nosunlink", "SystemNoUnlink"}, + { "snapshot", "SystemSnapshot"}, + { "uappnd", "UserAppend"}, + { "uappend", "UserAppend"}, + { "uchg", "UserImmutable"}, + { "uchange", "UserImmutable"}, + { "uimmutable", "UserImmutable"}, + { "nodump", "UserNoDump"}, + { "noopaque", "UserOpaque"}, + { "nouunlnk", "UserNoUnlink"}, + { "nouunlink", "UserNoUnlink"}, + { NULL, NULL} + }, + flagext2[] = { + { "sappnd", "AppendOnly"}, + { "sappend", "AppendOnly"}, + { "schg", "Immutable"}, + { "schange", "Immutable"}, + { "simmutable", "Immutable"}, + { "nodump", "NoDump"}, + { "nouunlnk", "Undelete"}, + { "nouunlink", "Undelete"}, + { "btree", "BTree"}, + { "comperr", "CompError"}, + { "compress", "Compress"}, + { "noatime", "NoAtime"}, + { "compdirty", "CompDirty"}, + { "comprblk", "CompBlock"}, + { "dirsync", "DirSync"}, + { "hashidx", "HashIndexed"}, + { "imagic", "iMagic"}, + { "journal", "Journaled"}, + { "securedeletion", "SecureDeletion"}, + { "sync", "Synchronous"}, + { "notail", "NoTail"}, + { "topdir", "TopDir"}, + { "reserved", "Reserved"}, + { NULL, NULL} + }; + const struct flagentry *fe, *flagentry; +#define FLAGENTRY_MAXSIZE ((sizeof(flagbsd)+sizeof(flagext2))/sizeof(flagbsd)) + const struct flagentry *avail[FLAGENTRY_MAXSIZE]; + const char *p; + int i, n, r; + + if (strcmp(element, "ext2") == 0) + flagentry = flagext2; + else + flagentry = flagbsd; + n = 0; + p = fflags_text; + do { + const char *cp; + + cp = strchr(p, ','); + if (cp == NULL) + cp = p + strlen(p); + + for (fe = flagentry; fe->name != NULL; fe++) { + if (fe->name[cp - p] != '\0' + || p[0] != fe->name[0]) + continue; + if (strncmp(p, fe->name, cp - p) == 0) { + avail[n++] = fe; + break; + } + } + if (*cp == ',') + p = cp + 1; + else + p = NULL; + } while (p != NULL); + + if (n > 0) { + r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(element)); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + for (i = 0; i < n; i++) { + r = xmlwrite_string(a, writer, + avail[i]->xarname, NULL); + if (r != ARCHIVE_OK) + return (r); + } + + r = xmlTextWriterEndElement(writer); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterEndElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + } + return (ARCHIVE_OK); +} + +static int +make_file_entry(struct archive_write *a, xmlTextWriterPtr writer, + struct file *file) +{ + struct xar *xar; + const char *filetype, *filelink, *fflags; + struct archive_string linkto; + struct heap_data *heap; + unsigned char *tmp; + const char *p; + size_t len; + int r, r2, l, ll; + + xar = (struct xar *)a->format_data; + r2 = ARCHIVE_OK; + + /* + * Make a file name entry, "". + */ + l = ll = archive_strlen(&(file->basename)); + tmp = malloc(l); + if (tmp == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + r = UTF8Toisolat1(tmp, &l, BAD_CAST(file->basename.s), &ll); + free(tmp); + if (r < 0) { + r = xmlTextWriterStartElement(writer, BAD_CAST("name")); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + r = xmlTextWriterWriteAttribute(writer, + BAD_CAST("enctype"), BAD_CAST("base64")); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterWriteAttribute() failed: %d", r); + return (ARCHIVE_FATAL); + } + r = xmlTextWriterWriteBase64(writer, file->basename.s, + 0, archive_strlen(&(file->basename))); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterWriteBase64() failed: %d", r); + return (ARCHIVE_FATAL); + } + r = xmlTextWriterEndElement(writer); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterEndElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + } else { + r = xmlwrite_string(a, writer, "name", file->basename.s); + if (r < 0) + return (ARCHIVE_FATAL); + } + + /* + * Make a file type entry, "". + */ + filelink = NULL; + archive_string_init(&linkto); + switch (archive_entry_filetype(file->entry)) { + case AE_IFDIR: + filetype = "directory"; break; + case AE_IFLNK: + filetype = "symlink"; break; + case AE_IFCHR: + filetype = "character special"; break; + case AE_IFBLK: + filetype = "block special"; break; + case AE_IFSOCK: + filetype = "socket"; break; + case AE_IFIFO: + filetype = "fifo"; break; + case AE_IFREG: + default: + if (file->hardlink_target != NULL) { + filetype = "hardlink"; + filelink = "link"; + if (file->hardlink_target == file) + archive_strcpy(&linkto, "original"); + else + archive_string_sprintf(&linkto, "%d", + file->hardlink_target->id); + } else + filetype = "file"; + break; + } + r = xmlwrite_string_attr(a, writer, "type", filetype, + filelink, linkto.s); + archive_string_free(&linkto); + if (r < 0) + return (ARCHIVE_FATAL); + + /* + * On a virtual directory, we record "name" and "type" only. + */ + if (file->virtual) + return (ARCHIVE_OK); + + switch (archive_entry_filetype(file->entry)) { + case AE_IFLNK: + /* + * xar utility has checked a file type, which + * a symbolic-link file has referenced. + * For example: + * ../ref/ + * The symlink target file is "../ref/" and its + * file type is a directory. + * + * ../f + * The symlink target file is "../f" and its + * file type is a regular file. + * + * But our implementation cannot do it, and then we + * always record that a attribute "type" is "broken", + * for example: + * foo/bar + * It means "foo/bar" is not reachable. + */ + r = xmlwrite_string_attr(a, writer, "link", + file->symlink.s, + "type", "broken"); + if (r < 0) + return (ARCHIVE_FATAL); + break; + case AE_IFCHR: + case AE_IFBLK: + r = xmlTextWriterStartElement(writer, BAD_CAST("device")); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + r = xmlwrite_fstring(a, writer, "major", + "%d", archive_entry_rdevmajor(file->entry)); + if (r < 0) + return (ARCHIVE_FATAL); + r = xmlwrite_fstring(a, writer, "minor", + "%d", archive_entry_rdevminor(file->entry)); + if (r < 0) + return (ARCHIVE_FATAL); + r = xmlTextWriterEndElement(writer); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterEndElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + break; + default: + break; + } + + /* + * Make a inode entry, "". + */ + r = xmlwrite_fstring(a, writer, "inode", + "%jd", archive_entry_ino64(file->entry)); + if (r < 0) + return (ARCHIVE_FATAL); + if (archive_entry_dev(file->entry) != 0) { + r = xmlwrite_fstring(a, writer, "deviceno", + "%d", archive_entry_dev(file->entry)); + if (r < 0) + return (ARCHIVE_FATAL); + } + + /* + * Make a file mode entry, "". + */ + r = xmlwrite_mode(a, writer, "mode", + archive_entry_mode(file->entry)); + if (r < 0) + return (ARCHIVE_FATAL); + + /* + * Make a user entry, "" and ". + */ + r = xmlwrite_fstring(a, writer, "uid", + "%d", archive_entry_uid(file->entry)); + if (r < 0) + return (ARCHIVE_FATAL); + r = archive_entry_uname_l(file->entry, &p, &len, xar->sconv); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Uname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate uname '%s' to UTF-8", + archive_entry_uname(file->entry)); + r2 = ARCHIVE_WARN; + } + if (len > 0) { + r = xmlwrite_string(a, writer, "user", p); + if (r < 0) + return (ARCHIVE_FATAL); + } + + /* + * Make a group entry, "" and ". + */ + r = xmlwrite_fstring(a, writer, "gid", + "%d", archive_entry_gid(file->entry)); + if (r < 0) + return (ARCHIVE_FATAL); + r = archive_entry_gname_l(file->entry, &p, &len, xar->sconv); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Gname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate gname '%s' to UTF-8", + archive_entry_gname(file->entry)); + r2 = ARCHIVE_WARN; + } + if (len > 0) { + r = xmlwrite_string(a, writer, "group", p); + if (r < 0) + return (ARCHIVE_FATAL); + } + + /* + * Make a ctime entry, "". + */ + if (archive_entry_ctime_is_set(file->entry)) { + r = xmlwrite_time(a, writer, "ctime", + archive_entry_ctime(file->entry), 1); + if (r < 0) + return (ARCHIVE_FATAL); + } + + /* + * Make a mtime entry, "". + */ + if (archive_entry_mtime_is_set(file->entry)) { + r = xmlwrite_time(a, writer, "mtime", + archive_entry_mtime(file->entry), 1); + if (r < 0) + return (ARCHIVE_FATAL); + } + + /* + * Make a atime entry, "". + */ + if (archive_entry_atime_is_set(file->entry)) { + r = xmlwrite_time(a, writer, "atime", + archive_entry_atime(file->entry), 1); + if (r < 0) + return (ARCHIVE_FATAL); + } + + /* + * Make fflags entries, "" and "". + */ + fflags = archive_entry_fflags_text(file->entry); + if (fflags != NULL) { + r = make_fflags_entry(a, writer, "flags", fflags); + if (r < 0) + return (r); + r = make_fflags_entry(a, writer, "ext2", fflags); + if (r < 0) + return (r); + } + + /* + * Make extended attribute entries, "". + */ + archive_entry_xattr_reset(file->entry); + for (heap = file->xattr.first; heap != NULL; heap = heap->next) { + const char *name; + const void *value; + size_t size; + + archive_entry_xattr_next(file->entry, + &name, &value, &size); + r = xmlTextWriterStartElement(writer, BAD_CAST("ea")); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + r = xmlTextWriterWriteFormatAttribute(writer, + BAD_CAST("id"), "%d", heap->id); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterWriteAttribute() failed: %d", r); + return (ARCHIVE_FATAL); + } + r = xmlwrite_heap(a, writer, heap); + if (r < 0) + return (ARCHIVE_FATAL); + r = xmlwrite_string(a, writer, "name", name); + if (r < 0) + return (ARCHIVE_FATAL); + + r = xmlTextWriterEndElement(writer); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterEndElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + } + + /* + * Make a file data entry, "". + */ + if (file->data.length > 0) { + r = xmlTextWriterStartElement(writer, BAD_CAST("data")); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + + r = xmlwrite_heap(a, writer, &(file->data)); + if (r < 0) + return (ARCHIVE_FATAL); + + r = xmlTextWriterEndElement(writer); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterEndElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + } + + if (archive_strlen(&file->script) > 0) { + r = xmlTextWriterStartElement(writer, BAD_CAST("content")); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + + r = xmlwrite_string(a, writer, + "interpreter", file->script.s); + if (r < 0) + return (ARCHIVE_FATAL); + + r = xmlwrite_string(a, writer, "type", "script"); + if (r < 0) + return (ARCHIVE_FATAL); + + r = xmlTextWriterEndElement(writer); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterEndElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + } + + return (r2); +} + +/* + * Make the TOC + */ +static int +make_toc(struct archive_write *a) +{ + struct xar *xar; + struct file *np; + xmlBufferPtr bp; + xmlTextWriterPtr writer; + int algsize; + int r, ret; + + xar = (struct xar *)a->format_data; + + ret = ARCHIVE_FATAL; + + /* + * Initialize xml writer. + */ + writer = NULL; + bp = xmlBufferCreate(); + if (bp == NULL) { + archive_set_error(&a->archive, ENOMEM, + "xmlBufferCreate() " + "couldn't create xml buffer"); + goto exit_toc; + } + writer = xmlNewTextWriterMemory(bp, 0); + if (writer == NULL) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlNewTextWriterMemory() " + "couldn't create xml writer"); + goto exit_toc; + } + r = xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartDocument() failed: %d", r); + goto exit_toc; + } + r = xmlTextWriterSetIndent(writer, 4); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterSetIndent() failed: %d", r); + goto exit_toc; + } + + /* + * Start recording TOC + */ + r = xmlTextWriterStartElement(writer, BAD_CAST("xar")); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartElement() failed: %d", r); + goto exit_toc; + } + r = xmlTextWriterStartElement(writer, BAD_CAST("toc")); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartDocument() failed: %d", r); + goto exit_toc; + } + + /* + * Record the creation time of the archive file. + */ + r = xmlwrite_time(a, writer, "creation-time", time(NULL), 0); + if (r < 0) + goto exit_toc; + + /* + * Record the checksum value of TOC + */ + algsize = getalgsize(xar->opt_toc_sumalg); + if (algsize) { + /* + * Record TOC checksum + */ + r = xmlTextWriterStartElement(writer, BAD_CAST("checksum")); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartElement() failed: %d", r); + goto exit_toc; + } + r = xmlTextWriterWriteAttribute(writer, BAD_CAST("style"), + BAD_CAST_CONST(getalgname(xar->opt_toc_sumalg))); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterWriteAttribute() failed: %d", r); + goto exit_toc; + } + + /* + * Record the offset of the value of checksum of TOC + */ + r = xmlwrite_string(a, writer, "offset", "0"); + if (r < 0) + goto exit_toc; + + /* + * Record the size of the value of checksum of TOC + */ + r = xmlwrite_fstring(a, writer, "size", "%d", algsize); + if (r < 0) + goto exit_toc; + + r = xmlTextWriterEndElement(writer); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterEndElement() failed: %d", r); + goto exit_toc; + } + } + + np = xar->root; + do { + if (np != np->parent) { + r = make_file_entry(a, writer, np); + if (r != ARCHIVE_OK) + goto exit_toc; + } + + if (np->dir && np->children.first != NULL) { + /* Enter to sub directories. */ + np = np->children.first; + r = xmlTextWriterStartElement(writer, + BAD_CAST("file")); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartElement() " + "failed: %d", r); + goto exit_toc; + } + r = xmlTextWriterWriteFormatAttribute( + writer, BAD_CAST("id"), "%d", np->id); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterWriteAttribute() " + "failed: %d", r); + goto exit_toc; + } + continue; + } + while (np != np->parent) { + r = xmlTextWriterEndElement(writer); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterEndElement() " + "failed: %d", r); + goto exit_toc; + } + if (np->chnext == NULL) { + /* Return to the parent directory. */ + np = np->parent; + } else { + np = np->chnext; + r = xmlTextWriterStartElement(writer, + BAD_CAST("file")); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartElement() " + "failed: %d", r); + goto exit_toc; + } + r = xmlTextWriterWriteFormatAttribute( + writer, BAD_CAST("id"), "%d", np->id); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterWriteAttribute() " + "failed: %d", r); + goto exit_toc; + } + break; + } + } + } while (np != np->parent); + + r = xmlTextWriterEndDocument(writer); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterEndDocument() failed: %d", r); + goto exit_toc; + } +#if DEBUG_PRINT_TOC + fprintf(stderr, "\n---TOC-- %d bytes --\n%s\n", + strlen((const char *)bp->content), bp->content); +#endif + + /* + * Compress the TOC and calculate the sum of the TOC. + */ + xar->toc.temp_offset = xar->temp_offset; + xar->toc.size = bp->use; + checksum_init(&(xar->a_sumwrk), xar->opt_toc_sumalg); + + r = compression_init_encoder_gzip(&(a->archive), + &(xar->stream), 6, 1); + if (r != ARCHIVE_OK) + goto exit_toc; + xar->stream.next_in = bp->content; + xar->stream.avail_in = bp->use; + xar->stream.total_in = 0; + xar->stream.next_out = xar->wbuff; + xar->stream.avail_out = sizeof(xar->wbuff); + xar->stream.total_out = 0; + for (;;) { + size_t size; + + r = compression_code(&(a->archive), + &(xar->stream), ARCHIVE_Z_FINISH); + if (r != ARCHIVE_OK && r != ARCHIVE_EOF) + goto exit_toc; + size = sizeof(xar->wbuff) - xar->stream.avail_out; + checksum_update(&(xar->a_sumwrk), xar->wbuff, size); + if (write_to_temp(a, xar->wbuff, size) != ARCHIVE_OK) + goto exit_toc; + if (r == ARCHIVE_EOF) + break; + xar->stream.next_out = xar->wbuff; + xar->stream.avail_out = sizeof(xar->wbuff); + } + r = compression_end(&(a->archive), &(xar->stream)); + if (r != ARCHIVE_OK) + goto exit_toc; + xar->toc.length = xar->stream.total_out; + xar->toc.compression = GZIP; + checksum_final(&(xar->a_sumwrk), &(xar->toc.a_sum)); + + ret = ARCHIVE_OK; +exit_toc: + if (writer) + xmlFreeTextWriter(writer); + if (bp) + xmlBufferFree(bp); + + return (ret); +} + +static int +flush_wbuff(struct archive_write *a) +{ + struct xar *xar; + int r; + size_t s; + + xar = (struct xar *)a->format_data; + s = sizeof(xar->wbuff) - xar->wbuff_remaining; + r = __archive_write_output(a, xar->wbuff, s); + if (r != ARCHIVE_OK) + return (r); + xar->wbuff_remaining = sizeof(xar->wbuff); + return (r); +} + +static int +copy_out(struct archive_write *a, uint64_t offset, uint64_t length) +{ + struct xar *xar; + int r; + + xar = (struct xar *)a->format_data; + if (lseek(xar->temp_fd, offset, SEEK_SET) < 0) { + archive_set_error(&(a->archive), errno, "lseek failed"); + return (ARCHIVE_FATAL); + } + while (length) { + size_t rsize; + ssize_t rs; + unsigned char *wb; + + if (length > xar->wbuff_remaining) + rsize = xar->wbuff_remaining; + else + rsize = (size_t)length; + wb = xar->wbuff + (sizeof(xar->wbuff) - xar->wbuff_remaining); + rs = read(xar->temp_fd, wb, rsize); + if (rs < 0) { + archive_set_error(&(a->archive), errno, + "Can't read temporary file(%jd)", + (intmax_t)rs); + return (ARCHIVE_FATAL); + } + if (rs == 0) { + archive_set_error(&(a->archive), 0, + "Truncated xar archive"); + return (ARCHIVE_FATAL); + } + xar->wbuff_remaining -= rs; + length -= rs; + if (xar->wbuff_remaining == 0) { + r = flush_wbuff(a); + if (r != ARCHIVE_OK) + return (r); + } + } + return (ARCHIVE_OK); +} + +static int +xar_close(struct archive_write *a) +{ + struct xar *xar; + unsigned char *wb; + uint64_t length; + int r; + + xar = (struct xar *)a->format_data; + + /* Empty! */ + if (xar->root->children.first == NULL) + return (ARCHIVE_OK); + + /* Save the length of all file extended attributes and contents. */ + length = xar->temp_offset; + + /* Connect hardlinked files */ + file_connect_hardlink_files(xar); + + /* Make the TOC */ + r = make_toc(a); + if (r != ARCHIVE_OK) + return (r); + /* + * Make the xar header on wbuff(write buffer). + */ + wb = xar->wbuff; + xar->wbuff_remaining = sizeof(xar->wbuff); + archive_be32enc(&wb[0], HEADER_MAGIC); + archive_be16enc(&wb[4], HEADER_SIZE); + archive_be16enc(&wb[6], HEADER_VERSION); + archive_be64enc(&wb[8], xar->toc.length); + archive_be64enc(&wb[16], xar->toc.size); + archive_be32enc(&wb[24], xar->toc.a_sum.alg); + xar->wbuff_remaining -= HEADER_SIZE; + + /* + * Write the TOC + */ + r = copy_out(a, xar->toc.temp_offset, xar->toc.length); + if (r != ARCHIVE_OK) + return (r); + + /* Write the checksum value of the TOC. */ + if (xar->toc.a_sum.len) { + if (xar->wbuff_remaining < xar->toc.a_sum.len) { + r = flush_wbuff(a); + if (r != ARCHIVE_OK) + return (r); + } + wb = xar->wbuff + (sizeof(xar->wbuff) - xar->wbuff_remaining); + memcpy(wb, xar->toc.a_sum.val, xar->toc.a_sum.len); + xar->wbuff_remaining -= xar->toc.a_sum.len; + } + + /* + * Write all file extended attributes and contents. + */ + r = copy_out(a, xar->toc.a_sum.len, length); + if (r != ARCHIVE_OK) + return (r); + r = flush_wbuff(a); + return (r); +} + +static int +xar_free(struct archive_write *a) +{ + struct xar *xar; + + xar = (struct xar *)a->format_data; + + /* Close the temporary file. */ + if (xar->temp_fd >= 0) + close(xar->temp_fd); + + archive_string_free(&(xar->cur_dirstr)); + archive_string_free(&(xar->tstr)); + archive_string_free(&(xar->vstr)); + file_free_hardlinks(xar); + file_free_register(xar); + compression_end(&(a->archive), &(xar->stream)); + free(xar); + + return (ARCHIVE_OK); +} + +static int +file_cmp_node(const struct archive_rb_node *n1, + const struct archive_rb_node *n2) +{ + const struct file *f1 = (const struct file *)n1; + const struct file *f2 = (const struct file *)n2; + + return (strcmp(f1->basename.s, f2->basename.s)); +} + +static int +file_cmp_key(const struct archive_rb_node *n, const void *key) +{ + const struct file *f = (const struct file *)n; + + return (strcmp(f->basename.s, (const char *)key)); +} + +static struct file * +file_new(struct archive_write *a, struct archive_entry *entry) +{ + struct file *file; + static const struct archive_rb_tree_ops rb_ops = { + file_cmp_node, file_cmp_key + }; + + file = calloc(1, sizeof(*file)); + if (file == NULL) + return (NULL); + + if (entry != NULL) + file->entry = archive_entry_clone(entry); + else + file->entry = archive_entry_new2(&a->archive); + if (file->entry == NULL) { + free(file); + return (NULL); + } + __archive_rb_tree_init(&(file->rbtree), &rb_ops); + file->children.first = NULL; + file->children.last = &(file->children.first); + file->xattr.first = NULL; + file->xattr.last = &(file->xattr.first); + archive_string_init(&(file->parentdir)); + archive_string_init(&(file->basename)); + archive_string_init(&(file->symlink)); + archive_string_init(&(file->script)); + if (entry != NULL && archive_entry_filetype(entry) == AE_IFDIR) + file->dir = 1; + + return (file); +} + +static void +file_free(struct file *file) +{ + struct heap_data *heap, *next_heap; + + heap = file->xattr.first; + while (heap != NULL) { + next_heap = heap->next; + free(heap); + heap = next_heap; + } + archive_string_free(&(file->parentdir)); + archive_string_free(&(file->basename)); + archive_string_free(&(file->symlink)); + archive_string_free(&(file->script)); + archive_entry_free(file->entry); + free(file); +} + +static struct file * +file_create_virtual_dir(struct archive_write *a, struct xar *xar, + const char *pathname) +{ + struct file *file; + + (void)xar; /* UNUSED */ + + file = file_new(a, NULL); + if (file == NULL) + return (NULL); + archive_entry_set_pathname(file->entry, pathname); + archive_entry_set_mode(file->entry, 0555 | AE_IFDIR); + + file->dir = 1; + file->virtual = 1; + + return (file); +} + +static int +file_add_child_tail(struct file *parent, struct file *child) +{ + if (!__archive_rb_tree_insert_node( + &(parent->rbtree), (struct archive_rb_node *)child)) + return (0); + child->chnext = NULL; + *parent->children.last = child; + parent->children.last = &(child->chnext); + child->parent = parent; + return (1); +} + +/* + * Find a entry from `parent' + */ +static struct file * +file_find_child(struct file *parent, const char *child_name) +{ + struct file *np; + + np = (struct file *)__archive_rb_tree_find_node( + &(parent->rbtree), child_name); + return (np); +} + +#if defined(_WIN32) || defined(__CYGWIN__) +static void +cleanup_backslash(char *utf8, size_t len) +{ + + /* Convert a path-separator from '\' to '/' */ + while (*utf8 != '\0' && len) { + if (*utf8 == '\\') + *utf8 = '/'; + ++utf8; + --len; + } +} +#else +#define cleanup_backslash(p, len) /* nop */ +#endif + +/* + * Generate a parent directory name and a base name from a pathname. + */ +static int +file_gen_utility_names(struct archive_write *a, struct file *file) +{ + struct xar *xar; + const char *pp; + char *p, *dirname, *slash; + size_t len; + int r = ARCHIVE_OK; + + xar = (struct xar *)a->format_data; + archive_string_empty(&(file->parentdir)); + archive_string_empty(&(file->basename)); + archive_string_empty(&(file->symlink)); + + if (file->parent == file)/* virtual root */ + return (ARCHIVE_OK); + + if (archive_entry_pathname_l(file->entry, &pp, &len, xar->sconv) + != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Pathname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate pathname '%s' to UTF-8", + archive_entry_pathname(file->entry)); + r = ARCHIVE_WARN; + } + archive_strncpy(&(file->parentdir), pp, len); + len = file->parentdir.length; + p = dirname = file->parentdir.s; + /* + * Convert a path-separator from '\' to '/' + */ + cleanup_backslash(p, len); + + /* + * Remove leading '/', '../' and './' elements + */ + while (*p) { + if (p[0] == '/') { + p++; + len--; + } else if (p[0] != '.') + break; + else if (p[1] == '.' && p[2] == '/') { + p += 3; + len -= 3; + } else if (p[1] == '/' || (p[1] == '.' && p[2] == '\0')) { + p += 2; + len -= 2; + } else if (p[1] == '\0') { + p++; + len--; + } else + break; + } + if (p != dirname) { + memmove(dirname, p, len+1); + p = dirname; + } + /* + * Remove "/","/." and "/.." elements from tail. + */ + while (len > 0) { + size_t ll = len; + + if (p[len-1] == '/') { + p[len-1] = '\0'; + len--; + } + if (len > 1 && p[len-2] == '/' && p[len-1] == '.') { + p[len-2] = '\0'; + len -= 2; + } + if (len > 2 && p[len-3] == '/' && p[len-2] == '.' && + p[len-1] == '.') { + p[len-3] = '\0'; + len -= 3; + } + if (ll == len) + break; + } + while (*p) { + if (p[0] == '/') { + if (p[1] == '/') + /* Convert '//' --> '/' */ + memmove(p, p+1, strlen(p+1) + 1); + else if (p[1] == '.' && p[2] == '/') + /* Convert '/./' --> '/' */ + memmove(p, p+2, strlen(p+2) + 1); + else if (p[1] == '.' && p[2] == '.' && p[3] == '/') { + /* Convert 'dir/dir1/../dir2/' + * --> 'dir/dir2/' + */ + char *rp = p -1; + while (rp >= dirname) { + if (*rp == '/') + break; + --rp; + } + if (rp > dirname) { + strcpy(rp, p+3); + p = rp; + } else { + strcpy(dirname, p+4); + p = dirname; + } + } else + p++; + } else + p++; + } + p = dirname; + len = strlen(p); + + if (archive_entry_filetype(file->entry) == AE_IFLNK) { + size_t len2; + /* Convert symlink name too. */ + if (archive_entry_symlink_l(file->entry, &pp, &len2, + xar->sconv) != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Linkname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate symlink '%s' to UTF-8", + archive_entry_symlink(file->entry)); + r = ARCHIVE_WARN; + } + archive_strncpy(&(file->symlink), pp, len2); + cleanup_backslash(file->symlink.s, file->symlink.length); + } + /* + * - Count up directory elements. + * - Find out the position which points the last position of + * path separator('/'). + */ + slash = NULL; + for (; *p != '\0'; p++) + if (*p == '/') + slash = p; + if (slash == NULL) { + /* The pathname doesn't have a parent directory. */ + file->parentdir.length = len; + archive_string_copy(&(file->basename), &(file->parentdir)); + archive_string_empty(&(file->parentdir)); + *file->parentdir.s = '\0'; + return (r); + } + + /* Make a basename from dirname and slash */ + *slash = '\0'; + file->parentdir.length = slash - dirname; + archive_strcpy(&(file->basename), slash + 1); + return (r); +} + +static int +get_path_component(char *name, int n, const char *fn) +{ + char *p; + int l; + + p = strchr(fn, '/'); + if (p == NULL) { + if ((l = strlen(fn)) == 0) + return (0); + } else + l = p - fn; + if (l > n -1) + return (-1); + memcpy(name, fn, l); + name[l] = '\0'; + + return (l); +} + +/* + * Add a new entry into the tree. + */ +static int +file_tree(struct archive_write *a, struct file **filepp) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + char name[_MAX_FNAME];/* Included null terminator size. */ +#elif defined(NAME_MAX) && NAME_MAX >= 255 + char name[NAME_MAX+1]; +#else + char name[256]; +#endif + struct xar *xar = (struct xar *)a->format_data; + struct file *dent, *file, *np; + struct archive_entry *ent; + const char *fn, *p; + int l; + + file = *filepp; + dent = xar->root; + if (file->parentdir.length > 0) + fn = p = file->parentdir.s; + else + fn = p = ""; + + /* + * If the path of the parent directory of `file' entry is + * the same as the path of `cur_dirent', add isoent to + * `cur_dirent'. + */ + if (archive_strlen(&(xar->cur_dirstr)) + == archive_strlen(&(file->parentdir)) && + strcmp(xar->cur_dirstr.s, fn) == 0) { + if (!file_add_child_tail(xar->cur_dirent, file)) { + np = (struct file *)__archive_rb_tree_find_node( + &(xar->cur_dirent->rbtree), + file->basename.s); + goto same_entry; + } + return (ARCHIVE_OK); + } + + for (;;) { + l = get_path_component(name, sizeof(name), fn); + if (l == 0) { + np = NULL; + break; + } + if (l < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "A name buffer is too small"); + file_free(file); + *filepp = NULL; + return (ARCHIVE_FATAL); + } + + np = file_find_child(dent, name); + if (np == NULL || fn[0] == '\0') + break; + + /* Find next subdirectory. */ + if (!np->dir) { + /* NOT Directory! */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "`%s' is not directory, we cannot insert `%s' ", + archive_entry_pathname(np->entry), + archive_entry_pathname(file->entry)); + file_free(file); + *filepp = NULL; + return (ARCHIVE_FAILED); + } + fn += l; + if (fn[0] == '/') + fn++; + dent = np; + } + if (np == NULL) { + /* + * Create virtual parent directories. + */ + while (fn[0] != '\0') { + struct file *vp; + struct archive_string as; + + archive_string_init(&as); + archive_strncat(&as, p, fn - p + l); + if (as.s[as.length-1] == '/') { + as.s[as.length-1] = '\0'; + as.length--; + } + vp = file_create_virtual_dir(a, xar, as.s); + if (vp == NULL) { + archive_string_free(&as); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + file_free(file); + *filepp = NULL; + return (ARCHIVE_FATAL); + } + archive_string_free(&as); + if (file_gen_utility_names(a, vp) <= ARCHIVE_FAILED) + return (ARCHIVE_FATAL); + file_add_child_tail(dent, vp); + file_register(xar, vp); + np = vp; + + fn += l; + if (fn[0] == '/') + fn++; + l = get_path_component(name, sizeof(name), fn); + if (l < 0) { + archive_string_free(&as); + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "A name buffer is too small"); + file_free(file); + *filepp = NULL; + return (ARCHIVE_FATAL); + } + dent = np; + } + + /* Found out the parent directory where isoent can be + * inserted. */ + xar->cur_dirent = dent; + archive_string_empty(&(xar->cur_dirstr)); + archive_string_ensure(&(xar->cur_dirstr), + archive_strlen(&(dent->parentdir)) + + archive_strlen(&(dent->basename)) + 2); + if (archive_strlen(&(dent->parentdir)) + + archive_strlen(&(dent->basename)) == 0) + xar->cur_dirstr.s[0] = 0; + else { + if (archive_strlen(&(dent->parentdir)) > 0) { + archive_string_copy(&(xar->cur_dirstr), + &(dent->parentdir)); + archive_strappend_char(&(xar->cur_dirstr), '/'); + } + archive_string_concat(&(xar->cur_dirstr), + &(dent->basename)); + } + + if (!file_add_child_tail(dent, file)) { + np = (struct file *)__archive_rb_tree_find_node( + &(dent->rbtree), file->basename.s); + goto same_entry; + } + return (ARCHIVE_OK); + } + +same_entry: + /* + * We have already has the entry the filename of which is + * the same. + */ + if (archive_entry_filetype(np->entry) != + archive_entry_filetype(file->entry)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Found duplicate entries `%s' and its file type is " + "different", + archive_entry_pathname(np->entry)); + file_free(file); + *filepp = NULL; + return (ARCHIVE_FAILED); + } + + /* Swap files. */ + ent = np->entry; + np->entry = file->entry; + file->entry = ent; + np->virtual = 0; + + file_free(file); + *filepp = np; + return (ARCHIVE_OK); +} + +static void +file_register(struct xar *xar, struct file *file) +{ + file->id = xar->file_idx++; + file->next = NULL; + *xar->file_list.last = file; + xar->file_list.last = &(file->next); +} + +static void +file_init_register(struct xar *xar) +{ + xar->file_list.first = NULL; + xar->file_list.last = &(xar->file_list.first); +} + +static void +file_free_register(struct xar *xar) +{ + struct file *file, *file_next; + + file = xar->file_list.first; + while (file != NULL) { + file_next = file->next; + file_free(file); + file = file_next; + } +} + +/* + * Register entry to get a hardlink target. + */ +static int +file_register_hardlink(struct archive_write *a, struct file *file) +{ + struct xar *xar = (struct xar *)a->format_data; + struct hardlink *hl; + const char *pathname; + + archive_entry_set_nlink(file->entry, 1); + pathname = archive_entry_hardlink(file->entry); + if (pathname == NULL) { + /* This `file` is a hardlink target. */ + hl = malloc(sizeof(*hl)); + if (hl == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + hl->nlink = 1; + /* A hardlink target must be the first position. */ + file->hlnext = NULL; + hl->file_list.first = file; + hl->file_list.last = &(file->hlnext); + __archive_rb_tree_insert_node(&(xar->hardlink_rbtree), + (struct archive_rb_node *)hl); + } else { + hl = (struct hardlink *)__archive_rb_tree_find_node( + &(xar->hardlink_rbtree), pathname); + if (hl != NULL) { + /* Insert `file` entry into the tail. */ + file->hlnext = NULL; + *hl->file_list.last = file; + hl->file_list.last = &(file->hlnext); + hl->nlink++; + } + archive_entry_unset_size(file->entry); + } + + return (ARCHIVE_OK); +} + +/* + * Hardlinked files have to have the same location of extent. + * We have to find out hardlink target entries for entries which + * have a hardlink target name. + */ +static void +file_connect_hardlink_files(struct xar *xar) +{ + struct archive_rb_node *n; + struct hardlink *hl; + struct file *target, *nf; + + ARCHIVE_RB_TREE_FOREACH(n, &(xar->hardlink_rbtree)) { + hl = (struct hardlink *)n; + + /* The first entry must be a hardlink target. */ + target = hl->file_list.first; + archive_entry_set_nlink(target->entry, hl->nlink); + if (hl->nlink > 1) + /* It means this file is a hardlink + * target itself. */ + target->hardlink_target = target; + for (nf = target->hlnext; + nf != NULL; nf = nf->hlnext) { + nf->hardlink_target = target; + archive_entry_set_nlink(nf->entry, hl->nlink); + } + } +} + +static int +file_hd_cmp_node(const struct archive_rb_node *n1, + const struct archive_rb_node *n2) +{ + const struct hardlink *h1 = (const struct hardlink *)n1; + const struct hardlink *h2 = (const struct hardlink *)n2; + + return (strcmp(archive_entry_pathname(h1->file_list.first->entry), + archive_entry_pathname(h2->file_list.first->entry))); +} + +static int +file_hd_cmp_key(const struct archive_rb_node *n, const void *key) +{ + const struct hardlink *h = (const struct hardlink *)n; + + return (strcmp(archive_entry_pathname(h->file_list.first->entry), + (const char *)key)); +} + + +static void +file_init_hardlinks(struct xar *xar) +{ + static const struct archive_rb_tree_ops rb_ops = { + file_hd_cmp_node, file_hd_cmp_key, + }; + + __archive_rb_tree_init(&(xar->hardlink_rbtree), &rb_ops); +} + +static void +file_free_hardlinks(struct xar *xar) +{ + struct archive_rb_node *n, *tmp; + + ARCHIVE_RB_TREE_FOREACH_SAFE(n, &(xar->hardlink_rbtree), tmp) { + __archive_rb_tree_remove_node(&(xar->hardlink_rbtree), n); + free(n); + } +} + +static void +checksum_init(struct chksumwork *sumwrk, enum sumalg sum_alg) +{ + sumwrk->alg = sum_alg; + switch (sum_alg) { + case CKSUM_NONE: + break; + case CKSUM_SHA1: + archive_sha1_init(&(sumwrk->sha1ctx)); + break; + case CKSUM_MD5: + archive_md5_init(&(sumwrk->md5ctx)); + break; + } +} + +static void +checksum_update(struct chksumwork *sumwrk, const void *buff, size_t size) +{ + + switch (sumwrk->alg) { + case CKSUM_NONE: + break; + case CKSUM_SHA1: + archive_sha1_update(&(sumwrk->sha1ctx), buff, size); + break; + case CKSUM_MD5: + archive_md5_update(&(sumwrk->md5ctx), buff, size); + break; + } +} + +static void +checksum_final(struct chksumwork *sumwrk, struct chksumval *sumval) +{ + + switch (sumwrk->alg) { + case CKSUM_NONE: + sumval->len = 0; + break; + case CKSUM_SHA1: + archive_sha1_final(&(sumwrk->sha1ctx), sumval->val); + sumval->len = SHA1_SIZE; + break; + case CKSUM_MD5: + archive_md5_final(&(sumwrk->md5ctx), sumval->val); + sumval->len = MD5_SIZE; + break; + } + sumval->alg = sumwrk->alg; +} + +#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H) +static int +compression_unsupported_encoder(struct archive *a, + struct la_zstream *lastrm, const char *name) +{ + + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "%s compression not supported on this platform", name); + lastrm->valid = 0; + lastrm->real_stream = NULL; + return (ARCHIVE_FAILED); +} +#endif + +static int +compression_init_encoder_gzip(struct archive *a, + struct la_zstream *lastrm, int level, int withheader) +{ + z_stream *strm; + + if (lastrm->valid) + compression_end(a, lastrm); + strm = calloc(1, sizeof(*strm)); + if (strm == NULL) { + archive_set_error(a, ENOMEM, + "Can't allocate memory for gzip stream"); + return (ARCHIVE_FATAL); + } + /* zlib.h is not const-correct, so we need this one bit + * of ugly hackery to convert a const * pointer to + * a non-const pointer. */ + strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in; + strm->avail_in = lastrm->avail_in; + strm->total_in = (uLong)lastrm->total_in; + strm->next_out = lastrm->next_out; + strm->avail_out = lastrm->avail_out; + strm->total_out = (uLong)lastrm->total_out; + if (deflateInit2(strm, level, Z_DEFLATED, + (withheader)?15:-15, + 8, Z_DEFAULT_STRATEGY) != Z_OK) { + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Internal error initializing compression library"); + return (ARCHIVE_FATAL); + } + lastrm->real_stream = strm; + lastrm->valid = 1; + lastrm->code = compression_code_gzip; + lastrm->end = compression_end_gzip; + return (ARCHIVE_OK); +} + +static int +compression_code_gzip(struct archive *a, + struct la_zstream *lastrm, enum la_zaction action) +{ + z_stream *strm; + int r; + + strm = (z_stream *)lastrm->real_stream; + /* zlib.h is not const-correct, so we need this one bit + * of ugly hackery to convert a const * pointer to + * a non-const pointer. */ + strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in; + strm->avail_in = lastrm->avail_in; + strm->total_in = (uLong)lastrm->total_in; + strm->next_out = lastrm->next_out; + strm->avail_out = lastrm->avail_out; + strm->total_out = (uLong)lastrm->total_out; + r = deflate(strm, + (action == ARCHIVE_Z_FINISH)? Z_FINISH: Z_NO_FLUSH); + lastrm->next_in = strm->next_in; + lastrm->avail_in = strm->avail_in; + lastrm->total_in = strm->total_in; + lastrm->next_out = strm->next_out; + lastrm->avail_out = strm->avail_out; + lastrm->total_out = strm->total_out; + switch (r) { + case Z_OK: + return (ARCHIVE_OK); + case Z_STREAM_END: + return (ARCHIVE_EOF); + default: + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "GZip compression failed:" + " deflate() call returned status %d", r); + return (ARCHIVE_FATAL); + } +} + +static int +compression_end_gzip(struct archive *a, struct la_zstream *lastrm) +{ + z_stream *strm; + int r; + + strm = (z_stream *)lastrm->real_stream; + r = deflateEnd(strm); + free(strm); + lastrm->real_stream = NULL; + lastrm->valid = 0; + if (r != Z_OK) { + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Failed to clean up compressor"); + return (ARCHIVE_FATAL); + } + return (ARCHIVE_OK); +} + +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) +static int +compression_init_encoder_bzip2(struct archive *a, + struct la_zstream *lastrm, int level) +{ + bz_stream *strm; + + if (lastrm->valid) + compression_end(a, lastrm); + strm = calloc(1, sizeof(*strm)); + if (strm == NULL) { + archive_set_error(a, ENOMEM, + "Can't allocate memory for bzip2 stream"); + return (ARCHIVE_FATAL); + } + /* bzlib.h is not const-correct, so we need this one bit + * of ugly hackery to convert a const * pointer to + * a non-const pointer. */ + strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in; + strm->avail_in = lastrm->avail_in; + strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff); + strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32); + strm->next_out = (char *)lastrm->next_out; + strm->avail_out = lastrm->avail_out; + strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff); + strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32); + if (BZ2_bzCompressInit(strm, level, 0, 30) != BZ_OK) { + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Internal error initializing compression library"); + return (ARCHIVE_FATAL); + } + lastrm->real_stream = strm; + lastrm->valid = 1; + lastrm->code = compression_code_bzip2; + lastrm->end = compression_end_bzip2; + return (ARCHIVE_OK); +} + +static int +compression_code_bzip2(struct archive *a, + struct la_zstream *lastrm, enum la_zaction action) +{ + bz_stream *strm; + int r; + + strm = (bz_stream *)lastrm->real_stream; + /* bzlib.h is not const-correct, so we need this one bit + * of ugly hackery to convert a const * pointer to + * a non-const pointer. */ + strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in; + strm->avail_in = lastrm->avail_in; + strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff); + strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32); + strm->next_out = (char *)lastrm->next_out; + strm->avail_out = lastrm->avail_out; + strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff); + strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32); + r = BZ2_bzCompress(strm, + (action == ARCHIVE_Z_FINISH)? BZ_FINISH: BZ_RUN); + lastrm->next_in = (const unsigned char *)strm->next_in; + lastrm->avail_in = strm->avail_in; + lastrm->total_in = + (((uint64_t)(uint32_t)strm->total_in_hi32) << 32) + + (uint64_t)(uint32_t)strm->total_in_lo32; + lastrm->next_out = (unsigned char *)strm->next_out; + lastrm->avail_out = strm->avail_out; + lastrm->total_out = + (((uint64_t)(uint32_t)strm->total_out_hi32) << 32) + + (uint64_t)(uint32_t)strm->total_out_lo32; + switch (r) { + case BZ_RUN_OK: /* Non-finishing */ + case BZ_FINISH_OK: /* Finishing: There's more work to do */ + return (ARCHIVE_OK); + case BZ_STREAM_END: /* Finishing: all done */ + /* Only occurs in finishing case */ + return (ARCHIVE_EOF); + default: + /* Any other return value indicates an error */ + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Bzip2 compression failed:" + " BZ2_bzCompress() call returned status %d", r); + return (ARCHIVE_FATAL); + } +} + +static int +compression_end_bzip2(struct archive *a, struct la_zstream *lastrm) +{ + bz_stream *strm; + int r; + + strm = (bz_stream *)lastrm->real_stream; + r = BZ2_bzCompressEnd(strm); + free(strm); + lastrm->real_stream = NULL; + lastrm->valid = 0; + if (r != BZ_OK) { + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Failed to clean up compressor"); + return (ARCHIVE_FATAL); + } + return (ARCHIVE_OK); +} + +#else +static int +compression_init_encoder_bzip2(struct archive *a, + struct la_zstream *lastrm, int level) +{ + + (void) level; /* UNUSED */ + if (lastrm->valid) + compression_end(a, lastrm); + return (compression_unsupported_encoder(a, lastrm, "bzip2")); +} +#endif + +#if defined(HAVE_LZMA_H) +static int +compression_init_encoder_lzma(struct archive *a, + struct la_zstream *lastrm, int level) +{ + static const lzma_stream lzma_init_data = LZMA_STREAM_INIT; + lzma_stream *strm; + lzma_options_lzma lzma_opt; + int r; + + if (lastrm->valid) + compression_end(a, lastrm); + if (lzma_lzma_preset(&lzma_opt, level)) { + lastrm->real_stream = NULL; + archive_set_error(a, ENOMEM, + "Internal error initializing compression library"); + return (ARCHIVE_FATAL); + } + strm = calloc(1, sizeof(*strm)); + if (strm == NULL) { + archive_set_error(a, ENOMEM, + "Can't allocate memory for lzma stream"); + return (ARCHIVE_FATAL); + } + *strm = lzma_init_data; + r = lzma_alone_encoder(strm, &lzma_opt); + switch (r) { + case LZMA_OK: + lastrm->real_stream = strm; + lastrm->valid = 1; + lastrm->code = compression_code_lzma; + lastrm->end = compression_end_lzma; + r = ARCHIVE_OK; + break; + case LZMA_MEM_ERROR: + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ENOMEM, + "Internal error initializing compression library: " + "Cannot allocate memory"); + r = ARCHIVE_FATAL; + break; + default: + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Internal error initializing compression library: " + "It's a bug in liblzma"); + r = ARCHIVE_FATAL; + break; + } + return (r); +} + +static int +compression_init_encoder_xz(struct archive *a, + struct la_zstream *lastrm, int level, int threads) +{ + static const lzma_stream lzma_init_data = LZMA_STREAM_INIT; + lzma_stream *strm; + lzma_filter *lzmafilters; + lzma_options_lzma lzma_opt; + int r; +#ifdef HAVE_LZMA_STREAM_ENCODER_MT + lzma_mt mt_options; +#endif + + (void)threads; /* UNUSED (if multi-threaded LZMA library not avail) */ + + if (lastrm->valid) + compression_end(a, lastrm); + strm = calloc(1, sizeof(*strm) + sizeof(*lzmafilters) * 2); + if (strm == NULL) { + archive_set_error(a, ENOMEM, + "Can't allocate memory for xz stream"); + return (ARCHIVE_FATAL); + } + lzmafilters = (lzma_filter *)(strm+1); + if (level > 6) + level = 6; + if (lzma_lzma_preset(&lzma_opt, level)) { + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ENOMEM, + "Internal error initializing compression library"); + return (ARCHIVE_FATAL); + } + lzmafilters[0].id = LZMA_FILTER_LZMA2; + lzmafilters[0].options = &lzma_opt; + lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */ + + *strm = lzma_init_data; +#ifdef HAVE_LZMA_STREAM_ENCODER_MT + if (threads > 1) { + memset(&mt_options, 0, sizeof(mt_options)); + mt_options.threads = threads; + mt_options.timeout = 300; + mt_options.filters = lzmafilters; + mt_options.check = LZMA_CHECK_CRC64; + r = lzma_stream_encoder_mt(strm, &mt_options); + } else +#endif + r = lzma_stream_encoder(strm, lzmafilters, LZMA_CHECK_CRC64); + switch (r) { + case LZMA_OK: + lastrm->real_stream = strm; + lastrm->valid = 1; + lastrm->code = compression_code_lzma; + lastrm->end = compression_end_lzma; + r = ARCHIVE_OK; + break; + case LZMA_MEM_ERROR: + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ENOMEM, + "Internal error initializing compression library: " + "Cannot allocate memory"); + r = ARCHIVE_FATAL; + break; + default: + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Internal error initializing compression library: " + "It's a bug in liblzma"); + r = ARCHIVE_FATAL; + break; + } + return (r); +} + +static int +compression_code_lzma(struct archive *a, + struct la_zstream *lastrm, enum la_zaction action) +{ + lzma_stream *strm; + int r; + + strm = (lzma_stream *)lastrm->real_stream; + strm->next_in = lastrm->next_in; + strm->avail_in = lastrm->avail_in; + strm->total_in = lastrm->total_in; + strm->next_out = lastrm->next_out; + strm->avail_out = lastrm->avail_out; + strm->total_out = lastrm->total_out; + r = lzma_code(strm, + (action == ARCHIVE_Z_FINISH)? LZMA_FINISH: LZMA_RUN); + lastrm->next_in = strm->next_in; + lastrm->avail_in = strm->avail_in; + lastrm->total_in = strm->total_in; + lastrm->next_out = strm->next_out; + lastrm->avail_out = strm->avail_out; + lastrm->total_out = strm->total_out; + switch (r) { + case LZMA_OK: + /* Non-finishing case */ + return (ARCHIVE_OK); + case LZMA_STREAM_END: + /* This return can only occur in finishing case. */ + return (ARCHIVE_EOF); + case LZMA_MEMLIMIT_ERROR: + archive_set_error(a, ENOMEM, + "lzma compression error:" + " %ju MiB would have been needed", + (uintmax_t)((lzma_memusage(strm) + 1024 * 1024 -1) + / (1024 * 1024))); + return (ARCHIVE_FATAL); + default: + /* Any other return value indicates an error */ + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "lzma compression failed:" + " lzma_code() call returned status %d", r); + return (ARCHIVE_FATAL); + } +} + +static int +compression_end_lzma(struct archive *a, struct la_zstream *lastrm) +{ + lzma_stream *strm; + + (void)a; /* UNUSED */ + strm = (lzma_stream *)lastrm->real_stream; + lzma_end(strm); + free(strm); + lastrm->valid = 0; + lastrm->real_stream = NULL; + return (ARCHIVE_OK); +} +#else +static int +compression_init_encoder_lzma(struct archive *a, + struct la_zstream *lastrm, int level) +{ + + (void) level; /* UNUSED */ + if (lastrm->valid) + compression_end(a, lastrm); + return (compression_unsupported_encoder(a, lastrm, "lzma")); +} +static int +compression_init_encoder_xz(struct archive *a, + struct la_zstream *lastrm, int level, int threads) +{ + + (void) level; /* UNUSED */ + (void) threads; /* UNUSED */ + if (lastrm->valid) + compression_end(a, lastrm); + return (compression_unsupported_encoder(a, lastrm, "xz")); +} +#endif + +static int +xar_compression_init_encoder(struct archive_write *a) +{ + struct xar *xar; + int r; + + xar = (struct xar *)a->format_data; + switch (xar->opt_compression) { + case GZIP: + r = compression_init_encoder_gzip( + &(a->archive), &(xar->stream), + xar->opt_compression_level, 1); + break; + case BZIP2: + r = compression_init_encoder_bzip2( + &(a->archive), &(xar->stream), + xar->opt_compression_level); + break; + case LZMA: + r = compression_init_encoder_lzma( + &(a->archive), &(xar->stream), + xar->opt_compression_level); + break; + case XZ: + r = compression_init_encoder_xz( + &(a->archive), &(xar->stream), + xar->opt_compression_level, xar->opt_threads); + break; + default: + r = ARCHIVE_OK; + break; + } + if (r == ARCHIVE_OK) { + xar->stream.total_in = 0; + xar->stream.next_out = xar->wbuff; + xar->stream.avail_out = sizeof(xar->wbuff); + xar->stream.total_out = 0; + } + + return (r); +} + +static int +compression_code(struct archive *a, struct la_zstream *lastrm, + enum la_zaction action) +{ + if (lastrm->valid) + return (lastrm->code(a, lastrm, action)); + return (ARCHIVE_OK); +} + +static int +compression_end(struct archive *a, struct la_zstream *lastrm) +{ + if (lastrm->valid) + return (lastrm->end(a, lastrm)); + return (ARCHIVE_OK); +} + + +static int +save_xattrs(struct archive_write *a, struct file *file) +{ + struct xar *xar; + const char *name; + const void *value; + struct heap_data *heap; + size_t size; + int count, r; + + xar = (struct xar *)a->format_data; + count = archive_entry_xattr_reset(file->entry); + if (count == 0) + return (ARCHIVE_OK); + while (count--) { + archive_entry_xattr_next(file->entry, + &name, &value, &size); + checksum_init(&(xar->a_sumwrk), xar->opt_sumalg); + checksum_init(&(xar->e_sumwrk), xar->opt_sumalg); + + heap = calloc(1, sizeof(*heap)); + if (heap == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for xattr"); + return (ARCHIVE_FATAL); + } + heap->id = file->ea_idx++; + heap->temp_offset = xar->temp_offset; + heap->size = size;/* save a extracted size */ + heap->compression = xar->opt_compression; + /* Get a extracted sumcheck value. */ + checksum_update(&(xar->e_sumwrk), value, size); + checksum_final(&(xar->e_sumwrk), &(heap->e_sum)); + + /* + * Not compression to xattr is simple way. + */ + if (heap->compression == NONE) { + checksum_update(&(xar->a_sumwrk), value, size); + checksum_final(&(xar->a_sumwrk), &(heap->a_sum)); + if (write_to_temp(a, value, size) + != ARCHIVE_OK) { + free(heap); + return (ARCHIVE_FATAL); + } + heap->length = size; + /* Add heap to the tail of file->xattr. */ + heap->next = NULL; + *file->xattr.last = heap; + file->xattr.last = &(heap->next); + /* Next xattr */ + continue; + } + + /* + * Init compression library. + */ + r = xar_compression_init_encoder(a); + if (r != ARCHIVE_OK) { + free(heap); + return (ARCHIVE_FATAL); + } + + xar->stream.next_in = (const unsigned char *)value; + xar->stream.avail_in = size; + for (;;) { + r = compression_code(&(a->archive), + &(xar->stream), ARCHIVE_Z_FINISH); + if (r != ARCHIVE_OK && r != ARCHIVE_EOF) { + free(heap); + return (ARCHIVE_FATAL); + } + size = sizeof(xar->wbuff) - xar->stream.avail_out; + checksum_update(&(xar->a_sumwrk), + xar->wbuff, size); + if (write_to_temp(a, xar->wbuff, size) + != ARCHIVE_OK) { + free(heap); + return (ARCHIVE_FATAL); + } + if (r == ARCHIVE_OK) { + xar->stream.next_out = xar->wbuff; + xar->stream.avail_out = sizeof(xar->wbuff); + } else { + checksum_final(&(xar->a_sumwrk), + &(heap->a_sum)); + heap->length = xar->stream.total_out; + /* Add heap to the tail of file->xattr. */ + heap->next = NULL; + *file->xattr.last = heap; + file->xattr.last = &(heap->next); + break; + } + } + /* Clean up compression library. */ + r = compression_end(&(a->archive), &(xar->stream)); + if (r != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + return (ARCHIVE_OK); +} + +static int +getalgsize(enum sumalg sumalg) +{ + switch (sumalg) { + default: + case CKSUM_NONE: + return (0); + case CKSUM_SHA1: + return (SHA1_SIZE); + case CKSUM_MD5: + return (MD5_SIZE); + } +} + +static const char * +getalgname(enum sumalg sumalg) +{ + switch (sumalg) { + default: + case CKSUM_NONE: + return (NULL); + case CKSUM_SHA1: + return (SHA1_NAME); + case CKSUM_MD5: + return (MD5_NAME); + } +} + +#endif /* Support xar format */ diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_zip.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_zip.c new file mode 100644 index 0000000..6d48529 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_format_zip.c @@ -0,0 +1,1695 @@ +/*- + * Copyright (c) 2008 Anselm Strauss + * Copyright (c) 2009 Joerg Sonnenberger + * Copyright (c) 2011-2012,2014 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Development supported by Google Summer of Code 2008. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_zip.c 201168 2009-12-29 06:15:32Z kientzle $"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_LANGINFO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_ZLIB_H +#include +#endif + +#include "archive.h" +#include "archive_cryptor_private.h" +#include "archive_endian.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_hmac_private.h" +#include "archive_private.h" +#include "archive_random_private.h" +#include "archive_write_private.h" +#include "archive_write_set_format_private.h" + +#ifndef HAVE_ZLIB_H +#include "archive_crc32.h" +#endif + +#define ZIP_ENTRY_FLAG_ENCRYPTED (1<<0) +#define ZIP_ENTRY_FLAG_LENGTH_AT_END (1<<3) +#define ZIP_ENTRY_FLAG_UTF8_NAME (1 << 11) + +#define ZIP_4GB_MAX ARCHIVE_LITERAL_LL(0xffffffff) +#define ZIP_4GB_MAX_UNCOMPRESSED ARCHIVE_LITERAL_LL(0xff000000) + +enum compression { + COMPRESSION_UNSPECIFIED = -1, + COMPRESSION_STORE = 0, + COMPRESSION_DEFLATE = 8 +}; + +#ifdef HAVE_ZLIB_H +#define COMPRESSION_DEFAULT COMPRESSION_DEFLATE +#else +#define COMPRESSION_DEFAULT COMPRESSION_STORE +#endif + +enum encryption { + ENCRYPTION_NONE = 0, + ENCRYPTION_TRADITIONAL, /* Traditional PKWARE encryption. */ + ENCRYPTION_WINZIP_AES128, /* WinZIP AES-128 encryption. */ + ENCRYPTION_WINZIP_AES256, /* WinZIP AES-256 encryption. */ +}; + +#define TRAD_HEADER_SIZE 12 +/* + * See "WinZip - AES Encryption Information" + * http://www.winzip.com/aes_info.htm + */ +/* Value used in compression method. */ +#define WINZIP_AES_ENCRYPTION 99 +/* A WinZip AES header size which is stored at the beginning of + * file contents. */ +#define WINZIP_AES128_HEADER_SIZE (8 + 2) +#define WINZIP_AES256_HEADER_SIZE (16 + 2) +/* AES vendor version. */ +#define AES_VENDOR_AE_1 0x0001 +#define AES_VENDOR_AE_2 0x0002 +/* Authentication code size. */ +#define AUTH_CODE_SIZE 10 +/**/ +#define MAX_DERIVED_KEY_BUF_SIZE (AES_MAX_KEY_SIZE * 2 + 2) + +struct cd_segment { + struct cd_segment *next; + size_t buff_size; + unsigned char *buff; + unsigned char *p; +}; + +struct trad_enc_ctx { + uint32_t keys[3]; +}; + +struct zip { + + int64_t entry_offset; + int64_t entry_compressed_size; + int64_t entry_uncompressed_size; + int64_t entry_compressed_written; + int64_t entry_uncompressed_written; + int64_t entry_uncompressed_limit; + struct archive_entry *entry; + uint32_t entry_crc32; + enum compression entry_compression; + enum encryption entry_encryption; + int entry_flags; + int entry_uses_zip64; + int experiments; + struct trad_enc_ctx tctx; + char tctx_valid; + unsigned char trad_chkdat; + unsigned aes_vendor; + archive_crypto_ctx cctx; + char cctx_valid; + archive_hmac_sha1_ctx hctx; + char hctx_valid; + + unsigned char *file_header; + size_t file_header_extra_offset; + unsigned long (*crc32func)(unsigned long crc, const void *buff, size_t len); + + struct cd_segment *central_directory; + struct cd_segment *central_directory_last; + size_t central_directory_bytes; + size_t central_directory_entries; + + int64_t written_bytes; /* Overall position in file. */ + + struct archive_string_conv *opt_sconv; + struct archive_string_conv *sconv_default; + enum compression requested_compression; + int deflate_compression_level; + int init_default_conversion; + enum encryption encryption_type; + +#define ZIP_FLAG_AVOID_ZIP64 1 +#define ZIP_FLAG_FORCE_ZIP64 2 +#define ZIP_FLAG_EXPERIMENT_xl 4 + int flags; + +#ifdef HAVE_ZLIB_H + z_stream stream; +#endif + size_t len_buf; + unsigned char *buf; +}; + +/* Don't call this min or MIN, since those are already defined + on lots of platforms (but not all). */ +#define zipmin(a, b) ((a) > (b) ? (b) : (a)) + +static ssize_t archive_write_zip_data(struct archive_write *, + const void *buff, size_t s); +static int archive_write_zip_close(struct archive_write *); +static int archive_write_zip_free(struct archive_write *); +static int archive_write_zip_finish_entry(struct archive_write *); +static int archive_write_zip_header(struct archive_write *, + struct archive_entry *); +static int archive_write_zip_options(struct archive_write *, + const char *, const char *); +static unsigned int dos_time(const time_t); +static size_t path_length(struct archive_entry *); +static int write_path(struct archive_entry *, struct archive_write *); +static void copy_path(struct archive_entry *, unsigned char *); +static struct archive_string_conv *get_sconv(struct archive_write *, struct zip *); +static int trad_enc_init(struct trad_enc_ctx *, const char *, size_t); +static unsigned trad_enc_encrypt_update(struct trad_enc_ctx *, const uint8_t *, + size_t, uint8_t *, size_t); +static int init_traditional_pkware_encryption(struct archive_write *); +static int is_traditional_pkware_encryption_supported(void); +static int init_winzip_aes_encryption(struct archive_write *); +static int is_winzip_aes_encryption_supported(int encryption); + +static unsigned char * +cd_alloc(struct zip *zip, size_t length) +{ + unsigned char *p; + + if (zip->central_directory == NULL + || (zip->central_directory_last->p + length + > zip->central_directory_last->buff + zip->central_directory_last->buff_size)) { + struct cd_segment *segment = calloc(1, sizeof(*segment)); + if (segment == NULL) + return NULL; + segment->buff_size = 64 * 1024; + segment->buff = malloc(segment->buff_size); + if (segment->buff == NULL) { + free(segment); + return NULL; + } + segment->p = segment->buff; + + if (zip->central_directory == NULL) { + zip->central_directory + = zip->central_directory_last + = segment; + } else { + zip->central_directory_last->next = segment; + zip->central_directory_last = segment; + } + } + + p = zip->central_directory_last->p; + zip->central_directory_last->p += length; + zip->central_directory_bytes += length; + return (p); +} + +static unsigned long +real_crc32(unsigned long crc, const void *buff, size_t len) +{ + return crc32(crc, buff, (unsigned int)len); +} + +static unsigned long +fake_crc32(unsigned long crc, const void *buff, size_t len) +{ + (void)crc; /* UNUSED */ + (void)buff; /* UNUSED */ + (void)len; /* UNUSED */ + return 0; +} + +static int +archive_write_zip_options(struct archive_write *a, const char *key, + const char *val) +{ + struct zip *zip = a->format_data; + int ret = ARCHIVE_FAILED; + + if (strcmp(key, "compression") == 0) { + /* + * Set compression to use on all future entries. + * This only affects regular files. + */ + if (val == NULL || val[0] == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "%s: compression option needs a compression name", + a->format_name); + } else if (strcmp(val, "deflate") == 0) { +#ifdef HAVE_ZLIB_H + zip->requested_compression = COMPRESSION_DEFLATE; + ret = ARCHIVE_OK; +#else + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "deflate compression not supported"); +#endif + } else if (strcmp(val, "store") == 0) { + zip->requested_compression = COMPRESSION_STORE; + ret = ARCHIVE_OK; + } + return (ret); + } else if (strcmp(key, "compression-level") == 0) { + if (val == NULL || !(val[0] >= '0' && val[0] <= '9') || val[1] != '\0') { + return ARCHIVE_WARN; + } + + if (val[0] == '0') { + zip->requested_compression = COMPRESSION_STORE; + return ARCHIVE_OK; + } else { +#ifdef HAVE_ZLIB_H + zip->requested_compression = COMPRESSION_DEFLATE; + zip->deflate_compression_level = val[0] - '0'; + return ARCHIVE_OK; +#else + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "deflate compression not supported"); +#endif + } + } else if (strcmp(key, "encryption") == 0) { + if (val == NULL) { + zip->encryption_type = ENCRYPTION_NONE; + ret = ARCHIVE_OK; + } else if (val[0] == '1' || strcmp(val, "traditional") == 0 + || strcmp(val, "zipcrypt") == 0 + || strcmp(val, "ZipCrypt") == 0) { + if (is_traditional_pkware_encryption_supported()) { + zip->encryption_type = ENCRYPTION_TRADITIONAL; + ret = ARCHIVE_OK; + } else { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "encryption not supported"); + } + } else if (strcmp(val, "aes128") == 0) { + if (is_winzip_aes_encryption_supported( + ENCRYPTION_WINZIP_AES128)) { + zip->encryption_type = ENCRYPTION_WINZIP_AES128; + ret = ARCHIVE_OK; + } else { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "encryption not supported"); + } + } else if (strcmp(val, "aes256") == 0) { + if (is_winzip_aes_encryption_supported( + ENCRYPTION_WINZIP_AES256)) { + zip->encryption_type = ENCRYPTION_WINZIP_AES256; + ret = ARCHIVE_OK; + } else { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "encryption not supported"); + } + } else { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "%s: unknown encryption '%s'", + a->format_name, val); + } + return (ret); + } else if (strcmp(key, "experimental") == 0) { + if (val == NULL || val[0] == 0) { + zip->flags &= ~ ZIP_FLAG_EXPERIMENT_xl; + } else { + zip->flags |= ZIP_FLAG_EXPERIMENT_xl; + } + return (ARCHIVE_OK); + } else if (strcmp(key, "fakecrc32") == 0) { + /* + * FOR TESTING ONLY: disable CRC calculation to speed up + * certain complex tests. + */ + if (val == NULL || val[0] == 0) { + zip->crc32func = real_crc32; + } else { + zip->crc32func = fake_crc32; + } + return (ARCHIVE_OK); + } else if (strcmp(key, "hdrcharset") == 0) { + /* + * Set the character set used in translating filenames. + */ + if (val == NULL || val[0] == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "%s: hdrcharset option needs a character-set name", + a->format_name); + } else { + zip->opt_sconv = archive_string_conversion_to_charset( + &a->archive, val, 0); + if (zip->opt_sconv != NULL) + ret = ARCHIVE_OK; + else + ret = ARCHIVE_FATAL; + } + return (ret); + } else if (strcmp(key, "zip64") == 0) { + /* + * Bias decisions about Zip64: force them to be + * generated in certain cases where they are not + * forbidden or avoid them in certain cases where they + * are not strictly required. + */ + if (val != NULL && *val != '\0') { + zip->flags |= ZIP_FLAG_FORCE_ZIP64; + zip->flags &= ~ZIP_FLAG_AVOID_ZIP64; + } else { + zip->flags &= ~ZIP_FLAG_FORCE_ZIP64; + zip->flags |= ZIP_FLAG_AVOID_ZIP64; + } + return (ARCHIVE_OK); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +int +archive_write_zip_set_compression_deflate(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + int ret = ARCHIVE_FAILED; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW | ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_write_zip_set_compression_deflate"); + if (a->archive.archive_format != ARCHIVE_FORMAT_ZIP) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can only use archive_write_zip_set_compression_deflate" + " with zip format"); + ret = ARCHIVE_FATAL; + } else { +#ifdef HAVE_ZLIB_H + struct zip *zip = a->format_data; + zip->requested_compression = COMPRESSION_DEFLATE; + ret = ARCHIVE_OK; +#else + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "deflate compression not supported"); + ret = ARCHIVE_FAILED; +#endif + } + return (ret); +} + +int +archive_write_zip_set_compression_store(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct zip *zip = a->format_data; + int ret = ARCHIVE_FAILED; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW | ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_write_zip_set_compression_deflate"); + if (a->archive.archive_format != ARCHIVE_FORMAT_ZIP) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can only use archive_write_zip_set_compression_store" + " with zip format"); + ret = ARCHIVE_FATAL; + } else { + zip->requested_compression = COMPRESSION_STORE; + ret = ARCHIVE_OK; + } + return (ret); +} + +int +archive_write_set_format_zip(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct zip *zip; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_set_format_zip"); + + /* If another format was already registered, unregister it. */ + if (a->format_free != NULL) + (a->format_free)(a); + + zip = (struct zip *) calloc(1, sizeof(*zip)); + if (zip == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate zip data"); + return (ARCHIVE_FATAL); + } + + /* "Unspecified" lets us choose the appropriate compression. */ + zip->requested_compression = COMPRESSION_UNSPECIFIED; +#ifdef HAVE_ZLIB_H + zip->deflate_compression_level = Z_DEFAULT_COMPRESSION; +#endif + zip->crc32func = real_crc32; + + /* A buffer used for both compression and encryption. */ + zip->len_buf = 65536; + zip->buf = malloc(zip->len_buf); + if (zip->buf == NULL) { + free(zip); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate compression buffer"); + return (ARCHIVE_FATAL); + } + + a->format_data = zip; + a->format_name = "zip"; + a->format_options = archive_write_zip_options; + a->format_write_header = archive_write_zip_header; + a->format_write_data = archive_write_zip_data; + a->format_finish_entry = archive_write_zip_finish_entry; + a->format_close = archive_write_zip_close; + a->format_free = archive_write_zip_free; + a->archive.archive_format = ARCHIVE_FORMAT_ZIP; + a->archive.archive_format_name = "ZIP"; + + return (ARCHIVE_OK); +} + +static int +is_all_ascii(const char *p) +{ + const unsigned char *pp = (const unsigned char *)p; + + while (*pp) { + if (*pp++ > 127) + return (0); + } + return (1); +} + +static int +archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) +{ + unsigned char local_header[32]; + unsigned char local_extra[144]; + struct zip *zip = a->format_data; + unsigned char *e; + unsigned char *cd_extra; + size_t filename_length; + const char *slink = NULL; + size_t slink_size = 0; + struct archive_string_conv *sconv = get_sconv(a, zip); + int ret, ret2 = ARCHIVE_OK; + mode_t type; + int version_needed = 10; + + /* Ignore types of entries that we don't support. */ + type = archive_entry_filetype(entry); + if (type != AE_IFREG && type != AE_IFDIR && type != AE_IFLNK) { + __archive_write_entry_filetype_unsupported( + &a->archive, entry, "zip"); + return ARCHIVE_FAILED; + }; + + /* If we're not using Zip64, reject large files. */ + if (zip->flags & ZIP_FLAG_AVOID_ZIP64) { + /* Reject entries over 4GB. */ + if (archive_entry_size_is_set(entry) + && (archive_entry_size(entry) > ZIP_4GB_MAX)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Files > 4GB require Zip64 extensions"); + return ARCHIVE_FAILED; + } + /* Reject entries if archive is > 4GB. */ + if (zip->written_bytes > ZIP_4GB_MAX) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Archives > 4GB require Zip64 extensions"); + return ARCHIVE_FAILED; + } + } + + /* Only regular files can have size > 0. */ + if (type != AE_IFREG) + archive_entry_set_size(entry, 0); + + + /* Reset information from last entry. */ + zip->entry_offset = zip->written_bytes; + zip->entry_uncompressed_limit = INT64_MAX; + zip->entry_compressed_size = 0; + zip->entry_uncompressed_size = 0; + zip->entry_compressed_written = 0; + zip->entry_uncompressed_written = 0; + zip->entry_flags = 0; + zip->entry_uses_zip64 = 0; + zip->entry_crc32 = zip->crc32func(0, NULL, 0); + zip->entry_encryption = 0; + archive_entry_free(zip->entry); + zip->entry = NULL; + + if (zip->cctx_valid) + archive_encrypto_aes_ctr_release(&zip->cctx); + if (zip->hctx_valid) + archive_hmac_sha1_cleanup(&zip->hctx); + zip->tctx_valid = zip->cctx_valid = zip->hctx_valid = 0; + + if (type == AE_IFREG + &&(!archive_entry_size_is_set(entry) + || archive_entry_size(entry) > 0)) { + switch (zip->encryption_type) { + case ENCRYPTION_TRADITIONAL: + case ENCRYPTION_WINZIP_AES128: + case ENCRYPTION_WINZIP_AES256: + zip->entry_flags |= ZIP_ENTRY_FLAG_ENCRYPTED; + zip->entry_encryption = zip->encryption_type; + break; + default: + break; + } + } + + +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Make sure the path separators in pathname, hardlink and symlink + * are all slash '/', not the Windows path separator '\'. */ + zip->entry = __la_win_entry_in_posix_pathseparator(entry); + if (zip->entry == entry) + zip->entry = archive_entry_clone(entry); +#else + zip->entry = archive_entry_clone(entry); +#endif + if (zip->entry == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate zip header data"); + return (ARCHIVE_FATAL); + } + + if (sconv != NULL) { + const char *p; + size_t len; + + if (archive_entry_pathname_l(entry, &p, &len, sconv) != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Pathname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate Pathname '%s' to %s", + archive_entry_pathname(entry), + archive_string_conversion_charset_name(sconv)); + ret2 = ARCHIVE_WARN; + } + if (len > 0) + archive_entry_set_pathname(zip->entry, p); + + /* + * There is no standard for symlink handling; we convert + * it using the same character-set translation that we use + * for filename. + */ + if (type == AE_IFLNK) { + if (archive_entry_symlink_l(entry, &p, &len, sconv)) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory " + " for Symlink"); + return (ARCHIVE_FATAL); + } + /* No error if we can't convert. */ + } else if (len > 0) + archive_entry_set_symlink(zip->entry, p); + } + } + + /* If filename isn't ASCII and we can use UTF-8, set the UTF-8 flag. */ + if (!is_all_ascii(archive_entry_pathname(zip->entry))) { + if (zip->opt_sconv != NULL) { + if (strcmp(archive_string_conversion_charset_name( + zip->opt_sconv), "UTF-8") == 0) + zip->entry_flags |= ZIP_ENTRY_FLAG_UTF8_NAME; +#if HAVE_NL_LANGINFO + } else if (strcmp(nl_langinfo(CODESET), "UTF-8") == 0) { + zip->entry_flags |= ZIP_ENTRY_FLAG_UTF8_NAME; +#endif + } + } + filename_length = path_length(zip->entry); + + /* Determine appropriate compression and size for this entry. */ + if (type == AE_IFLNK) { + slink = archive_entry_symlink(zip->entry); + if (slink != NULL) + slink_size = strlen(slink); + else + slink_size = 0; + zip->entry_uncompressed_limit = slink_size; + zip->entry_compressed_size = slink_size; + zip->entry_uncompressed_size = slink_size; + zip->entry_crc32 = zip->crc32func(zip->entry_crc32, + (const unsigned char *)slink, slink_size); + zip->entry_compression = COMPRESSION_STORE; + version_needed = 20; + } else if (type != AE_IFREG) { + zip->entry_compression = COMPRESSION_STORE; + zip->entry_uncompressed_limit = 0; + version_needed = 20; + } else if (archive_entry_size_is_set(zip->entry)) { + int64_t size = archive_entry_size(zip->entry); + int64_t additional_size = 0; + + zip->entry_uncompressed_limit = size; + zip->entry_compression = zip->requested_compression; + if (zip->entry_compression == COMPRESSION_UNSPECIFIED) { + zip->entry_compression = COMPRESSION_DEFAULT; + } + if (zip->entry_compression == COMPRESSION_STORE) { + zip->entry_compressed_size = size; + zip->entry_uncompressed_size = size; + version_needed = 10; + } else { + zip->entry_uncompressed_size = size; + version_needed = 20; + } + + if (zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) { + switch (zip->entry_encryption) { + case ENCRYPTION_TRADITIONAL: + additional_size = TRAD_HEADER_SIZE; + version_needed = 20; + break; + case ENCRYPTION_WINZIP_AES128: + additional_size = WINZIP_AES128_HEADER_SIZE + + AUTH_CODE_SIZE; + version_needed = 20; + break; + case ENCRYPTION_WINZIP_AES256: + additional_size = WINZIP_AES256_HEADER_SIZE + + AUTH_CODE_SIZE; + version_needed = 20; + break; + default: + break; + } + if (zip->entry_compression == COMPRESSION_STORE) + zip->entry_compressed_size += additional_size; + } + + /* + * Set Zip64 extension in any of the following cases + * (this was suggested by discussion on info-zip-dev + * mailing list): + * = Zip64 is being forced by user + * = File is over 4GiB uncompressed + * (including encryption header, if any) + * = File is close to 4GiB and is being compressed + * (compression might make file larger) + */ + if ((zip->flags & ZIP_FLAG_FORCE_ZIP64) + || (zip->entry_uncompressed_size + additional_size > ZIP_4GB_MAX) + || (zip->entry_uncompressed_size > ZIP_4GB_MAX_UNCOMPRESSED + && zip->entry_compression != COMPRESSION_STORE)) { + zip->entry_uses_zip64 = 1; + version_needed = 45; + } + + /* We may know the size, but never the CRC. */ + zip->entry_flags |= ZIP_ENTRY_FLAG_LENGTH_AT_END; + } else { + /* We don't know the size. In this case, we prefer + * deflate (it has a clear end-of-data marker which + * makes length-at-end more reliable) and will + * enable Zip64 extensions unless we're told not to. + */ + zip->entry_compression = COMPRESSION_DEFAULT; + zip->entry_flags |= ZIP_ENTRY_FLAG_LENGTH_AT_END; + if ((zip->flags & ZIP_FLAG_AVOID_ZIP64) == 0) { + zip->entry_uses_zip64 = 1; + version_needed = 45; + } else if (zip->entry_compression == COMPRESSION_STORE) { + version_needed = 10; + } else { + version_needed = 20; + } + + if (zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) { + switch (zip->entry_encryption) { + case ENCRYPTION_TRADITIONAL: + case ENCRYPTION_WINZIP_AES128: + case ENCRYPTION_WINZIP_AES256: + if (version_needed < 20) + version_needed = 20; + break; + default: + break; + } + } + } + + /* Format the local header. */ + memset(local_header, 0, sizeof(local_header)); + memcpy(local_header, "PK\003\004", 4); + archive_le16enc(local_header + 4, version_needed); + archive_le16enc(local_header + 6, zip->entry_flags); + if (zip->entry_encryption == ENCRYPTION_WINZIP_AES128 + || zip->entry_encryption == ENCRYPTION_WINZIP_AES256) + archive_le16enc(local_header + 8, WINZIP_AES_ENCRYPTION); + else + archive_le16enc(local_header + 8, zip->entry_compression); + archive_le32enc(local_header + 10, + dos_time(archive_entry_mtime(zip->entry))); + archive_le32enc(local_header + 14, zip->entry_crc32); + if (zip->entry_uses_zip64) { + /* Zip64 data in the local header "must" include both + * compressed and uncompressed sizes AND those fields + * are included only if these are 0xffffffff; + * THEREFORE these must be set this way, even if we + * know one of them is smaller. */ + archive_le32enc(local_header + 18, ZIP_4GB_MAX); + archive_le32enc(local_header + 22, ZIP_4GB_MAX); + } else { + archive_le32enc(local_header + 18, (uint32_t)zip->entry_compressed_size); + archive_le32enc(local_header + 22, (uint32_t)zip->entry_uncompressed_size); + } + archive_le16enc(local_header + 26, (uint16_t)filename_length); + + if (zip->entry_encryption == ENCRYPTION_TRADITIONAL) { + if (zip->entry_flags & ZIP_ENTRY_FLAG_LENGTH_AT_END) + zip->trad_chkdat = local_header[11]; + else + zip->trad_chkdat = local_header[17]; + } + + /* Format as much of central directory file header as we can: */ + zip->file_header = cd_alloc(zip, 46); + /* If (zip->file_header == NULL) XXXX */ + ++zip->central_directory_entries; + memset(zip->file_header, 0, 46); + memcpy(zip->file_header, "PK\001\002", 4); + /* "Made by PKZip 2.0 on Unix." */ + archive_le16enc(zip->file_header + 4, 3 * 256 + version_needed); + archive_le16enc(zip->file_header + 6, version_needed); + archive_le16enc(zip->file_header + 8, zip->entry_flags); + if (zip->entry_encryption == ENCRYPTION_WINZIP_AES128 + || zip->entry_encryption == ENCRYPTION_WINZIP_AES256) + archive_le16enc(zip->file_header + 10, WINZIP_AES_ENCRYPTION); + else + archive_le16enc(zip->file_header + 10, zip->entry_compression); + archive_le32enc(zip->file_header + 12, + dos_time(archive_entry_mtime(zip->entry))); + archive_le16enc(zip->file_header + 28, (uint16_t)filename_length); + /* Following Info-Zip, store mode in the "external attributes" field. */ + archive_le32enc(zip->file_header + 38, + ((uint32_t)archive_entry_mode(zip->entry)) << 16); + e = cd_alloc(zip, filename_length); + /* If (e == NULL) XXXX */ + copy_path(zip->entry, e); + + /* Format extra data. */ + memset(local_extra, 0, sizeof(local_extra)); + e = local_extra; + + /* First, extra blocks that are the same between + * the local file header and the central directory. + * We format them once and then duplicate them. */ + + /* UT timestamp, length depends on what timestamps are set. */ + memcpy(e, "UT", 2); + archive_le16enc(e + 2, + 1 + + (archive_entry_mtime_is_set(entry) ? 4 : 0) + + (archive_entry_atime_is_set(entry) ? 4 : 0) + + (archive_entry_ctime_is_set(entry) ? 4 : 0)); + e += 4; + *e++ = + (archive_entry_mtime_is_set(entry) ? 1 : 0) + | (archive_entry_atime_is_set(entry) ? 2 : 0) + | (archive_entry_ctime_is_set(entry) ? 4 : 0); + if (archive_entry_mtime_is_set(entry)) { + archive_le32enc(e, (uint32_t)archive_entry_mtime(entry)); + e += 4; + } + if (archive_entry_atime_is_set(entry)) { + archive_le32enc(e, (uint32_t)archive_entry_atime(entry)); + e += 4; + } + if (archive_entry_ctime_is_set(entry)) { + archive_le32enc(e, (uint32_t)archive_entry_ctime(entry)); + e += 4; + } + + /* ux Unix extra data, length 11, version 1 */ + /* TODO: If uid < 64k, use 2 bytes, ditto for gid. */ + memcpy(e, "ux\013\000\001", 5); + e += 5; + *e++ = 4; /* Length of following UID */ + archive_le32enc(e, (uint32_t)archive_entry_uid(entry)); + e += 4; + *e++ = 4; /* Length of following GID */ + archive_le32enc(e, (uint32_t)archive_entry_gid(entry)); + e += 4; + + /* AES extra data field: WinZIP AES information, ID=0x9901 */ + if ((zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) + && (zip->entry_encryption == ENCRYPTION_WINZIP_AES128 + || zip->entry_encryption == ENCRYPTION_WINZIP_AES256)) { + + memcpy(e, "\001\231\007\000\001\000AE", 8); + /* AES vendor version AE-2 does not store a CRC. + * WinZip 11 uses AE-1, which does store the CRC, + * but it does not store the CRC when the file size + * is less than 20 bytes. So we simulate what + * WinZip 11 does. + * NOTE: WinZip 9.0 and 10.0 uses AE-2 by default. */ + if (archive_entry_size_is_set(zip->entry) + && archive_entry_size(zip->entry) < 20) { + archive_le16enc(e+4, AES_VENDOR_AE_2); + zip->aes_vendor = AES_VENDOR_AE_2;/* no CRC. */ + } else + zip->aes_vendor = AES_VENDOR_AE_1; + e += 8; + /* AES encryption strength. */ + *e++ = (zip->entry_encryption == ENCRYPTION_WINZIP_AES128)?1:3; + /* Actual compression method. */ + archive_le16enc(e, zip->entry_compression); + e += 2; + } + + /* Copy UT ,ux, and AES-extra into central directory as well. */ + zip->file_header_extra_offset = zip->central_directory_bytes; + cd_extra = cd_alloc(zip, e - local_extra); + memcpy(cd_extra, local_extra, e - local_extra); + + /* + * Following extra blocks vary between local header and + * central directory. These are the local header versions. + * Central directory versions get formatted in + * archive_write_zip_finish_entry() below. + */ + + /* "[Zip64 entry] in the local header MUST include BOTH + * original [uncompressed] and compressed size fields." */ + if (zip->entry_uses_zip64) { + unsigned char *zip64_start = e; + memcpy(e, "\001\000\020\000", 4); + e += 4; + archive_le64enc(e, zip->entry_uncompressed_size); + e += 8; + archive_le64enc(e, zip->entry_compressed_size); + e += 8; + archive_le16enc(zip64_start + 2, (uint16_t)(e - (zip64_start + 4))); + } + + if (zip->flags & ZIP_FLAG_EXPERIMENT_xl) { + /* Experimental 'xl' extension to improve streaming. */ + unsigned char *external_info = e; + int included = 7; + memcpy(e, "xl\000\000", 4); // 0x6c65 + 2-byte length + e += 4; + e[0] = included; /* bitmap of included fields */ + e += 1; + if (included & 1) { + archive_le16enc(e, /* "Version created by" */ + 3 * 256 + version_needed); + e += 2; + } + if (included & 2) { + archive_le16enc(e, 0); /* internal file attributes */ + e += 2; + } + if (included & 4) { + archive_le32enc(e, /* external file attributes */ + ((uint32_t)archive_entry_mode(zip->entry)) << 16); + e += 4; + } + if (included & 8) { + // Libarchive does not currently support file comments. + } + archive_le16enc(external_info + 2, (uint16_t)(e - (external_info + 4))); + } + + /* Update local header with size of extra data and write it all out: */ + archive_le16enc(local_header + 28, (uint16_t)(e - local_extra)); + + ret = __archive_write_output(a, local_header, 30); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + zip->written_bytes += 30; + + ret = write_path(zip->entry, a); + if (ret <= ARCHIVE_OK) + return (ARCHIVE_FATAL); + zip->written_bytes += ret; + + ret = __archive_write_output(a, local_extra, e - local_extra); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + zip->written_bytes += e - local_extra; + + /* For symlinks, write the body now. */ + if (slink != NULL) { + ret = __archive_write_output(a, slink, slink_size); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + zip->entry_compressed_written += slink_size; + zip->entry_uncompressed_written += slink_size; + zip->written_bytes += slink_size; + } + +#ifdef HAVE_ZLIB_H + if (zip->entry_compression == COMPRESSION_DEFLATE) { + zip->stream.zalloc = Z_NULL; + zip->stream.zfree = Z_NULL; + zip->stream.opaque = Z_NULL; + zip->stream.next_out = zip->buf; + zip->stream.avail_out = (uInt)zip->len_buf; + if (deflateInit2(&zip->stream, zip->deflate_compression_level, + Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY) != Z_OK) { + archive_set_error(&a->archive, ENOMEM, + "Can't init deflate compressor"); + return (ARCHIVE_FATAL); + } + } +#endif + + return (ret2); +} + +static ssize_t +archive_write_zip_data(struct archive_write *a, const void *buff, size_t s) +{ + int ret; + struct zip *zip = a->format_data; + + if ((int64_t)s > zip->entry_uncompressed_limit) + s = (size_t)zip->entry_uncompressed_limit; + zip->entry_uncompressed_written += s; + + if (s == 0) return 0; + + if (zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) { + switch (zip->entry_encryption) { + case ENCRYPTION_TRADITIONAL: + /* Initialize traditional PKWARE encryption context. */ + if (!zip->tctx_valid) { + ret = init_traditional_pkware_encryption(a); + if (ret != ARCHIVE_OK) + return (ret); + zip->tctx_valid = 1; + } + break; + case ENCRYPTION_WINZIP_AES128: + case ENCRYPTION_WINZIP_AES256: + if (!zip->cctx_valid) { + ret = init_winzip_aes_encryption(a); + if (ret != ARCHIVE_OK) + return (ret); + zip->cctx_valid = zip->hctx_valid = 1; + } + break; + default: + break; + } + } + + switch (zip->entry_compression) { + case COMPRESSION_STORE: + if (zip->tctx_valid || zip->cctx_valid) { + const uint8_t *rb = (const uint8_t *)buff; + const uint8_t * const re = rb + s; + + while (rb < re) { + size_t l; + + if (zip->tctx_valid) { + l = trad_enc_encrypt_update(&zip->tctx, + rb, re - rb, + zip->buf, zip->len_buf); + } else { + l = zip->len_buf; + ret = archive_encrypto_aes_ctr_update( + &zip->cctx, + rb, re - rb, zip->buf, &l); + if (ret < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Failed to encrypt file"); + return (ARCHIVE_FAILED); + } + archive_hmac_sha1_update(&zip->hctx, + zip->buf, l); + } + ret = __archive_write_output(a, zip->buf, l); + if (ret != ARCHIVE_OK) + return (ret); + zip->entry_compressed_written += l; + zip->written_bytes += l; + rb += l; + } + } else { + ret = __archive_write_output(a, buff, s); + if (ret != ARCHIVE_OK) + return (ret); + zip->written_bytes += s; + zip->entry_compressed_written += s; + } + break; +#if HAVE_ZLIB_H + case COMPRESSION_DEFLATE: + zip->stream.next_in = (unsigned char*)(uintptr_t)buff; + zip->stream.avail_in = (uInt)s; + do { + ret = deflate(&zip->stream, Z_NO_FLUSH); + if (ret == Z_STREAM_ERROR) + return (ARCHIVE_FATAL); + if (zip->stream.avail_out == 0) { + if (zip->tctx_valid) { + trad_enc_encrypt_update(&zip->tctx, + zip->buf, zip->len_buf, + zip->buf, zip->len_buf); + } else if (zip->cctx_valid) { + size_t outl = zip->len_buf; + ret = archive_encrypto_aes_ctr_update( + &zip->cctx, + zip->buf, zip->len_buf, + zip->buf, &outl); + if (ret < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Failed to encrypt file"); + return (ARCHIVE_FAILED); + } + archive_hmac_sha1_update(&zip->hctx, + zip->buf, zip->len_buf); + } + ret = __archive_write_output(a, zip->buf, + zip->len_buf); + if (ret != ARCHIVE_OK) + return (ret); + zip->entry_compressed_written += zip->len_buf; + zip->written_bytes += zip->len_buf; + zip->stream.next_out = zip->buf; + zip->stream.avail_out = (uInt)zip->len_buf; + } + } while (zip->stream.avail_in != 0); + break; +#endif + + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid ZIP compression type"); + return ARCHIVE_FATAL; + } + + zip->entry_uncompressed_limit -= s; + if (!zip->cctx_valid || zip->aes_vendor != AES_VENDOR_AE_2) + zip->entry_crc32 = + zip->crc32func(zip->entry_crc32, buff, (unsigned)s); + return (s); + +} + +static int +archive_write_zip_finish_entry(struct archive_write *a) +{ + struct zip *zip = a->format_data; + int ret; + +#if HAVE_ZLIB_H + if (zip->entry_compression == COMPRESSION_DEFLATE) { + for (;;) { + size_t remainder; + + ret = deflate(&zip->stream, Z_FINISH); + if (ret == Z_STREAM_ERROR) + return (ARCHIVE_FATAL); + remainder = zip->len_buf - zip->stream.avail_out; + if (zip->tctx_valid) { + trad_enc_encrypt_update(&zip->tctx, + zip->buf, remainder, zip->buf, remainder); + } else if (zip->cctx_valid) { + size_t outl = remainder; + ret = archive_encrypto_aes_ctr_update( + &zip->cctx, zip->buf, remainder, + zip->buf, &outl); + if (ret < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Failed to encrypt file"); + return (ARCHIVE_FAILED); + } + archive_hmac_sha1_update(&zip->hctx, + zip->buf, remainder); + } + ret = __archive_write_output(a, zip->buf, remainder); + if (ret != ARCHIVE_OK) + return (ret); + zip->entry_compressed_written += remainder; + zip->written_bytes += remainder; + zip->stream.next_out = zip->buf; + if (zip->stream.avail_out != 0) + break; + zip->stream.avail_out = (uInt)zip->len_buf; + } + deflateEnd(&zip->stream); + } +#endif + if (zip->hctx_valid) { + uint8_t hmac[20]; + size_t hmac_len = 20; + + archive_hmac_sha1_final(&zip->hctx, hmac, &hmac_len); + ret = __archive_write_output(a, hmac, AUTH_CODE_SIZE); + if (ret != ARCHIVE_OK) + return (ret); + zip->entry_compressed_written += AUTH_CODE_SIZE; + zip->written_bytes += AUTH_CODE_SIZE; + } + + /* Write trailing data descriptor. */ + if ((zip->entry_flags & ZIP_ENTRY_FLAG_LENGTH_AT_END) != 0) { + char d[24]; + memcpy(d, "PK\007\010", 4); + if (zip->cctx_valid && zip->aes_vendor == AES_VENDOR_AE_2) + archive_le32enc(d + 4, 0);/* no CRC.*/ + else + archive_le32enc(d + 4, zip->entry_crc32); + if (zip->entry_uses_zip64) { + archive_le64enc(d + 8, + (uint64_t)zip->entry_compressed_written); + archive_le64enc(d + 16, + (uint64_t)zip->entry_uncompressed_written); + ret = __archive_write_output(a, d, 24); + zip->written_bytes += 24; + } else { + archive_le32enc(d + 8, + (uint32_t)zip->entry_compressed_written); + archive_le32enc(d + 12, + (uint32_t)zip->entry_uncompressed_written); + ret = __archive_write_output(a, d, 16); + zip->written_bytes += 16; + } + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + + /* Append Zip64 extra data to central directory information. */ + if (zip->entry_compressed_written > ZIP_4GB_MAX + || zip->entry_uncompressed_written > ZIP_4GB_MAX + || zip->entry_offset > ZIP_4GB_MAX) { + unsigned char zip64[32]; + unsigned char *z = zip64, *zd; + memcpy(z, "\001\000\000\000", 4); + z += 4; + if (zip->entry_uncompressed_written >= ZIP_4GB_MAX) { + archive_le64enc(z, zip->entry_uncompressed_written); + z += 8; + } + if (zip->entry_compressed_written >= ZIP_4GB_MAX) { + archive_le64enc(z, zip->entry_compressed_written); + z += 8; + } + if (zip->entry_offset >= ZIP_4GB_MAX) { + archive_le64enc(z, zip->entry_offset); + z += 8; + } + archive_le16enc(zip64 + 2, (uint16_t)(z - (zip64 + 4))); + zd = cd_alloc(zip, z - zip64); + if (zd == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate zip data"); + return (ARCHIVE_FATAL); + } + memcpy(zd, zip64, z - zip64); + /* Zip64 means version needs to be set to at least 4.5 */ + if (archive_le16dec(zip->file_header + 6) < 45) + archive_le16enc(zip->file_header + 6, 45); + } + + /* Fix up central directory file header. */ + if (zip->cctx_valid && zip->aes_vendor == AES_VENDOR_AE_2) + archive_le32enc(zip->file_header + 16, 0);/* no CRC.*/ + else + archive_le32enc(zip->file_header + 16, zip->entry_crc32); + archive_le32enc(zip->file_header + 20, + (uint32_t)zipmin(zip->entry_compressed_written, + ZIP_4GB_MAX)); + archive_le32enc(zip->file_header + 24, + (uint32_t)zipmin(zip->entry_uncompressed_written, + ZIP_4GB_MAX)); + archive_le16enc(zip->file_header + 30, + (uint16_t)(zip->central_directory_bytes - zip->file_header_extra_offset)); + archive_le32enc(zip->file_header + 42, + (uint32_t)zipmin(zip->entry_offset, + ZIP_4GB_MAX)); + + return (ARCHIVE_OK); +} + +static int +archive_write_zip_close(struct archive_write *a) +{ + uint8_t buff[64]; + int64_t offset_start, offset_end; + struct zip *zip = a->format_data; + struct cd_segment *segment; + int ret; + + offset_start = zip->written_bytes; + segment = zip->central_directory; + while (segment != NULL) { + ret = __archive_write_output(a, + segment->buff, segment->p - segment->buff); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + zip->written_bytes += segment->p - segment->buff; + segment = segment->next; + } + offset_end = zip->written_bytes; + + /* If central dir info is too large, write Zip64 end-of-cd */ + if (offset_end - offset_start > ZIP_4GB_MAX + || offset_start > ZIP_4GB_MAX + || zip->central_directory_entries > 0xffffUL + || (zip->flags & ZIP_FLAG_FORCE_ZIP64)) { + /* Zip64 end-of-cd record */ + memset(buff, 0, 56); + memcpy(buff, "PK\006\006", 4); + archive_le64enc(buff + 4, 44); + archive_le16enc(buff + 12, 45); + archive_le16enc(buff + 14, 45); + /* This is disk 0 of 0. */ + archive_le64enc(buff + 24, zip->central_directory_entries); + archive_le64enc(buff + 32, zip->central_directory_entries); + archive_le64enc(buff + 40, offset_end - offset_start); + archive_le64enc(buff + 48, offset_start); + ret = __archive_write_output(a, buff, 56); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + zip->written_bytes += 56; + + /* Zip64 end-of-cd locator record. */ + memset(buff, 0, 20); + memcpy(buff, "PK\006\007", 4); + archive_le32enc(buff + 4, 0); + archive_le64enc(buff + 8, offset_end); + archive_le32enc(buff + 16, 1); + ret = __archive_write_output(a, buff, 20); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + zip->written_bytes += 20; + + } + + /* Format and write end of central directory. */ + memset(buff, 0, sizeof(buff)); + memcpy(buff, "PK\005\006", 4); + archive_le16enc(buff + 8, (uint16_t)zipmin(0xffffU, + zip->central_directory_entries)); + archive_le16enc(buff + 10, (uint16_t)zipmin(0xffffU, + zip->central_directory_entries)); + archive_le32enc(buff + 12, + (uint32_t)zipmin(ZIP_4GB_MAX, (offset_end - offset_start))); + archive_le32enc(buff + 16, + (uint32_t)zipmin(ZIP_4GB_MAX, offset_start)); + ret = __archive_write_output(a, buff, 22); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + zip->written_bytes += 22; + return (ARCHIVE_OK); +} + +static int +archive_write_zip_free(struct archive_write *a) +{ + struct zip *zip; + struct cd_segment *segment; + + zip = a->format_data; + while (zip->central_directory != NULL) { + segment = zip->central_directory; + zip->central_directory = segment->next; + free(segment->buff); + free(segment); + } + free(zip->buf); + archive_entry_free(zip->entry); + if (zip->cctx_valid) + archive_encrypto_aes_ctr_release(&zip->cctx); + if (zip->hctx_valid) + archive_hmac_sha1_cleanup(&zip->hctx); + /* TODO: Free opt_sconv, sconv_default */ + + free(zip); + a->format_data = NULL; + return (ARCHIVE_OK); +} + +/* Convert into MSDOS-style date/time. */ +static unsigned int +dos_time(const time_t unix_time) +{ + struct tm *t; + unsigned int dt; +#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S) + struct tm tmbuf; +#endif +#if defined(HAVE__LOCALTIME64_S) + errno_t terr; + __time64_t tmptime; +#endif + + /* This will not preserve time when creating/extracting the archive + * on two systems with different time zones. */ +#if defined(HAVE_LOCALTIME_R) + t = localtime_r(&unix_time, &tmbuf); +#elif defined(HAVE__LOCALTIME64_S) + tmptime = unix_time; + terr = _localtime64_s(&tmbuf, &tmptime); + if (terr) + t = NULL; + else + t = &tmbuf; +#else + t = localtime(&unix_time); +#endif + + /* MSDOS-style date/time is only between 1980-01-01 and 2107-12-31 */ + if (t->tm_year < 1980 - 1900) + /* Set minimum date/time '1980-01-01 00:00:00'. */ + dt = 0x00210000U; + else if (t->tm_year > 2107 - 1900) + /* Set maximum date/time '2107-12-31 23:59:58'. */ + dt = 0xff9fbf7dU; + else { + dt = 0; + dt += ((t->tm_year - 80) & 0x7f) << 9; + dt += ((t->tm_mon + 1) & 0x0f) << 5; + dt += (t->tm_mday & 0x1f); + dt <<= 16; + dt += (t->tm_hour & 0x1f) << 11; + dt += (t->tm_min & 0x3f) << 5; + dt += (t->tm_sec & 0x3e) >> 1; /* Only counting every 2 seconds. */ + } + return dt; +} + +static size_t +path_length(struct archive_entry *entry) +{ + mode_t type; + const char *path; + size_t len; + + type = archive_entry_filetype(entry); + path = archive_entry_pathname(entry); + + if (path == NULL) + return (0); + len = strlen(path); + if (type == AE_IFDIR && (path[0] == '\0' || path[len - 1] != '/')) + ++len; /* Space for the trailing / */ + return len; +} + +static int +write_path(struct archive_entry *entry, struct archive_write *archive) +{ + int ret; + const char *path; + mode_t type; + size_t written_bytes; + + path = archive_entry_pathname(entry); + type = archive_entry_filetype(entry); + written_bytes = 0; + + if (path == NULL) + return (ARCHIVE_FATAL); + + ret = __archive_write_output(archive, path, strlen(path)); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + written_bytes += strlen(path); + + /* Folders are recognized by a trailing slash. */ + if ((type == AE_IFDIR) & (path[strlen(path) - 1] != '/')) { + ret = __archive_write_output(archive, "/", 1); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + written_bytes += 1; + } + + return ((int)written_bytes); +} + +static void +copy_path(struct archive_entry *entry, unsigned char *p) +{ + const char *path; + size_t pathlen; + mode_t type; + + path = archive_entry_pathname(entry); + pathlen = strlen(path); + type = archive_entry_filetype(entry); + + memcpy(p, path, pathlen); + + /* Folders are recognized by a trailing slash. */ + if ((type == AE_IFDIR) && (path[pathlen - 1] != '/')) + p[pathlen] = '/'; +} + + +static struct archive_string_conv * +get_sconv(struct archive_write *a, struct zip *zip) +{ + if (zip->opt_sconv != NULL) + return (zip->opt_sconv); + + if (!zip->init_default_conversion) { + zip->sconv_default = + archive_string_default_conversion_for_write(&(a->archive)); + zip->init_default_conversion = 1; + } + return (zip->sconv_default); +} + +/* + Traditional PKWARE Decryption functions. + */ + +static void +trad_enc_update_keys(struct trad_enc_ctx *ctx, uint8_t c) +{ + uint8_t t; +#define CRC32(c, b) (crc32(c ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL) + + ctx->keys[0] = CRC32(ctx->keys[0], c); + ctx->keys[1] = (ctx->keys[1] + (ctx->keys[0] & 0xff)) * 134775813L + 1; + t = (ctx->keys[1] >> 24) & 0xff; + ctx->keys[2] = CRC32(ctx->keys[2], t); +#undef CRC32 +} + +static uint8_t +trad_enc_decrypt_byte(struct trad_enc_ctx *ctx) +{ + unsigned temp = ctx->keys[2] | 2; + return (uint8_t)((temp * (temp ^ 1)) >> 8) & 0xff; +} + +static unsigned +trad_enc_encrypt_update(struct trad_enc_ctx *ctx, const uint8_t *in, + size_t in_len, uint8_t *out, size_t out_len) +{ + unsigned i, max; + + max = (unsigned)((in_len < out_len)? in_len: out_len); + + for (i = 0; i < max; i++) { + uint8_t t = in[i]; + out[i] = t ^ trad_enc_decrypt_byte(ctx); + trad_enc_update_keys(ctx, t); + } + return i; +} + +static int +trad_enc_init(struct trad_enc_ctx *ctx, const char *pw, size_t pw_len) +{ + + ctx->keys[0] = 305419896L; + ctx->keys[1] = 591751049L; + ctx->keys[2] = 878082192L; + + for (;pw_len; --pw_len) + trad_enc_update_keys(ctx, *pw++); + return 0; +} + +static int +is_traditional_pkware_encryption_supported(void) +{ + uint8_t key[TRAD_HEADER_SIZE]; + + if (archive_random(key, sizeof(key)-1) != ARCHIVE_OK) + return (0); + return (1); +} + +static int +init_traditional_pkware_encryption(struct archive_write *a) +{ + struct zip *zip = a->format_data; + const char *passphrase; + uint8_t key[TRAD_HEADER_SIZE]; + uint8_t key_encrypted[TRAD_HEADER_SIZE]; + int ret; + + passphrase = __archive_write_get_passphrase(a); + if (passphrase == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Encryption needs passphrase"); + return ARCHIVE_FAILED; + } + if (archive_random(key, sizeof(key)-1) != ARCHIVE_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't generate random number for encryption"); + return ARCHIVE_FATAL; + } + trad_enc_init(&zip->tctx, passphrase, strlen(passphrase)); + /* Set the last key code which will be used as a check code + * for verifying passphrase in decryption. */ + key[TRAD_HEADER_SIZE-1] = zip->trad_chkdat; + trad_enc_encrypt_update(&zip->tctx, key, TRAD_HEADER_SIZE, + key_encrypted, TRAD_HEADER_SIZE); + /* Write encrypted keys in the top of the file content. */ + ret = __archive_write_output(a, key_encrypted, TRAD_HEADER_SIZE); + if (ret != ARCHIVE_OK) + return (ret); + zip->written_bytes += TRAD_HEADER_SIZE; + zip->entry_compressed_written += TRAD_HEADER_SIZE; + return (ret); +} + +static int +init_winzip_aes_encryption(struct archive_write *a) +{ + struct zip *zip = a->format_data; + const char *passphrase; + size_t key_len, salt_len; + uint8_t salt[16 + 2]; + uint8_t derived_key[MAX_DERIVED_KEY_BUF_SIZE]; + int ret; + + passphrase = __archive_write_get_passphrase(a); + if (passphrase == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Encryption needs passphrase"); + return (ARCHIVE_FAILED); + } + if (zip->entry_encryption == ENCRYPTION_WINZIP_AES128) { + salt_len = 8; + key_len = 16; + } else { + /* AES 256 */ + salt_len = 16; + key_len = 32; + } + if (archive_random(salt, salt_len) != ARCHIVE_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't generate random number for encryption"); + return (ARCHIVE_FATAL); + } + archive_pbkdf2_sha1(passphrase, strlen(passphrase), + salt, salt_len, 1000, derived_key, key_len * 2 + 2); + + ret = archive_encrypto_aes_ctr_init(&zip->cctx, derived_key, key_len); + if (ret != 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Decryption is unsupported due to lack of crypto library"); + return (ARCHIVE_FAILED); + } + ret = archive_hmac_sha1_init(&zip->hctx, derived_key + key_len, + key_len); + if (ret != 0) { + archive_encrypto_aes_ctr_release(&zip->cctx); + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to initialize HMAC-SHA1"); + return (ARCHIVE_FAILED); + } + + /* Set a password verification value after the 'salt'. */ + salt[salt_len] = derived_key[key_len * 2]; + salt[salt_len + 1] = derived_key[key_len * 2 + 1]; + + /* Write encrypted keys in the top of the file content. */ + ret = __archive_write_output(a, salt, salt_len + 2); + if (ret != ARCHIVE_OK) + return (ret); + zip->written_bytes += salt_len + 2; + zip->entry_compressed_written += salt_len + 2; + + return (ARCHIVE_OK); +} + +static int +is_winzip_aes_encryption_supported(int encryption) +{ + size_t key_len, salt_len; + uint8_t salt[16 + 2]; + uint8_t derived_key[MAX_DERIVED_KEY_BUF_SIZE]; + archive_crypto_ctx cctx; + archive_hmac_sha1_ctx hctx; + int ret; + + if (encryption == ENCRYPTION_WINZIP_AES128) { + salt_len = 8; + key_len = 16; + } else { + /* AES 256 */ + salt_len = 16; + key_len = 32; + } + if (archive_random(salt, salt_len) != ARCHIVE_OK) + return (0); + ret = archive_pbkdf2_sha1("p", 1, salt, salt_len, 1000, + derived_key, key_len * 2 + 2); + if (ret != 0) + return (0); + + ret = archive_encrypto_aes_ctr_init(&cctx, derived_key, key_len); + if (ret != 0) + return (0); + ret = archive_hmac_sha1_init(&hctx, derived_key + key_len, + key_len); + archive_encrypto_aes_ctr_release(&cctx); + if (ret != 0) + return (0); + archive_hmac_sha1_cleanup(&hctx); + return (1); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_set_options.3 b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_options.3 new file mode 100644 index 0000000..cffe571 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_options.3 @@ -0,0 +1,707 @@ +.\" Copyright (c) 2003-2010 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd January 31, 2020 +.Dt ARCHIVE_WRITE_OPTIONS 3 +.Os +.Sh NAME +.Nm archive_write_set_filter_option , +.Nm archive_write_set_format_option , +.Nm archive_write_set_option , +.Nm archive_write_set_options +.Nd functions controlling options for writing archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.Ft int +.Fo archive_write_set_filter_option +.Fa "struct archive *" +.Fa "const char *module" +.Fa "const char *option" +.Fa "const char *value" +.Fc +.Ft int +.Fo archive_write_set_format_option +.Fa "struct archive *" +.Fa "const char *module" +.Fa "const char *option" +.Fa "const char *value" +.Fc +.Ft int +.Fo archive_write_set_option +.Fa "struct archive *" +.Fa "const char *module" +.Fa "const char *option" +.Fa "const char *value" +.Fc +.Ft int +.Fo archive_write_set_options +.Fa "struct archive *" +.Fa "const char *options" +.Fc +.Sh DESCRIPTION +These functions provide a way for libarchive clients to configure +specific write modules. +.Bl -tag -width indent +.It Xo +.Fn archive_write_set_filter_option , +.Fn archive_write_set_format_option +.Xc +Specifies an option that will be passed to the currently-registered +filters (including decompression filters) or format readers. +.Pp +If +.Ar option +and +.Ar value +are both +.Dv NULL , +these functions will do nothing and +.Cm ARCHIVE_OK +will be returned. +If +.Ar option +is +.Dv NULL +but +.Ar value +is not, these functions will do nothing and +.Cm ARCHIVE_FAILED +will be returned. +.Pp +If +.Ar module +is not +.Dv NULL , +.Ar option +and +.Ar value +will be provided to the filter or reader named +.Ar module . +The return value will be either +.Cm ARCHIVE_OK +if the option was successfully handled or +.Cm ARCHIVE_WARN +if the option was unrecognized by the module or could otherwise +not be handled. +If there is no such module, +.Cm ARCHIVE_FAILED +will be returned. +.Pp +If +.Ar module +is +.Dv NULL , +.Ar option +and +.Ar value +will be provided to every registered module. +If any module returns +.Cm ARCHIVE_FATAL , +this value will be returned immediately. +Otherwise, +.Cm ARCHIVE_OK +will be returned if any module accepts the option, and +.Cm ARCHIVE_FAILED +in all other cases. +.\" +.It Fn archive_write_set_option +Calls +.Fn archive_write_set_format_option , +then +.Fn archive_write_set_filter_option . +If either function returns +.Cm ARCHIVE_FATAL , +.Cm ARCHIVE_FATAL +will be returned +immediately. +Otherwise, the greater of the two values will be returned. +.\" +.It Fn archive_write_set_options +.Ar options +is a comma-separated list of options. +If +.Ar options +is +.Dv NULL +or empty, +.Cm ARCHIVE_OK +will be returned immediately. +.Pp +Individual options have one of the following forms: +.Bl -tag -compact -width indent +.It Ar option=value +The option/value pair will be provided to every module. +Modules that do not accept an option with this name will ignore it. +.It Ar option +The option will be provided to every module with a value of +.Dq 1 . +.It Ar !option +The option will be provided to every module with a NULL value. +.It Ar module:option=value , Ar module:option , Ar module:!option +As above, but the corresponding option and value will be provided +only to modules whose name matches +.Ar module . +.El +.El +.\" +.Sh OPTIONS +.Bl -tag -compact -width indent +.It Filter b64encode +.Bl -tag -compact -width indent +.It Cm mode +The value is interpreted as octal digits specifying the file mode. +.It Cm name +The value specifies the file name. +.El +.It Filter bzip2 +.Bl -tag -compact -width indent +.It Cm compression-level +The value is interpreted as a decimal integer specifying the +bzip2 compression level. Supported values are from 1 to 9. +.El +.It Filter gzip +.Bl -tag -compact -width indent +.It Cm compression-level +The value is interpreted as a decimal integer specifying the +gzip compression level. Supported values are from 0 to 9. +.It Cm timestamp +Store timestamp. This is enabled by default. +.El +.It Filter lrzip +.Bl -tag -compact -width indent +.It Cm compression Ns = Ns Ar type +Use +.Ar type +as compression method. +Supported values are +.Dq bzip2 , +.Dq gzipi , +.Dq lzo +.Pq ultra fast , +and +.Dq zpaq +.Pq best, extremely slow . +.It Cm compression-level +The value is interpreted as a decimal integer specifying the +lrzip compression level. Supported values are from 1 to 9. +.El +.It Filter lz4 +.Bl -tag -compact -width indent +.It Cm compression-level +The value is interpreted as a decimal integer specifying the +lz4 compression level. Supported values are from 0 to 9. +.It Cm stream-checksum +Enable stream checksum. This is enabled by default. +.It Cm block-checksum +Enable block checksum. This is disabled by default. +.It Cm block-size +The value is interpreted as a decimal integer specifying the +lz4 compression block size. Supported values are from 4 to 7 +.Pq default . +.It Cm block-dependence +Use the previous block of the block being compressed for +a compression dictionary to improve compression ratio. +This is disabled by default. +.El +.It Filter lzop +.Bl -tag -compact -width indent +.It Cm compression-level +The value is interpreted as a decimal integer specifying the +lzop compression level. Supported values are from 1 to 9. +.El +.It Filter uuencode +.Bl -tag -compact -width indent +.It Cm mode +The value is interpreted as octal digits specifying the file mode. +.It Cm name +The value specifies the file name. +.El +.It Filter xz +.Bl -tag -compact -width indent +.It Cm compression-level +The value is interpreted as a decimal integer specifying the +compression level. Supported values are from 0 to 9. +.It Cm threads +The value is interpreted as a decimal integer specifying the +number of threads for multi-threaded lzma compression. +If supported, the default value is read from +.Fn lzma_cputhreads . +.El +.It Filter zstd +.Bl -tag -compact -width indent +.It Cm compression-level +The value is interpreted as a decimal integer specifying the +compression level. Supported values are from 1 to 22. +.El +.It Format 7zip +.Bl -tag -compact -width indent +.It Cm compression +The value is one of +.Dq store , +.Dq deflate , +.Dq bzip2 , +.Dq lzma1 , +.Dq lzma2 +or +.Dq ppmd +to indicate how the following entries should be compressed. +Note that this setting is ignored for directories, symbolic links, +and other special entries. +.It Cm compression-level +The value is interpreted as a decimal integer specifying the +compression level. +Values between 0 and 9 are supported. +The interpretation of the compression level depends on the chosen +compression method. +.El +.It Format cpio +.Bl -tag -compact -width indent +.It Cm hdrcharset +The value is used as a character set name that will be +used when translating file names. +.El +.It Format gnutar +.Bl -tag -compact -width indent +.It Cm hdrcharset +The value is used as a character set name that will be +used when translating file, group and user names. +.El +.It Format iso9660 - volume metadata +These options are used to set standard ISO9660 metadata. +.Bl -tag -compact -width indent +.It Cm abstract-file Ns = Ns Ar filename +The file with the specified name will be identified in the ISO9660 metadata +as holding the abstract for this volume. +Default: none. +.It Cm application-id Ns = Ns Ar filename +The file with the specified name will be identified in the ISO9660 metadata +as holding the application identifier for this volume. +Default: none. +.It Cm biblio-file Ns = Ns Ar filename +The file with the specified name will be identified in the ISO9660 metadata +as holding the bibliography for this volume. +Default: none. +.It Cm copyright-file Ns = Ns Ar filename +The file with the specified name will be identified in the ISO9660 metadata +as holding the copyright for this volume. +Default: none. +.It Cm publisher Ns = Ns Ar filename +The file with the specified name will be identified in the ISO9660 metadata +as holding the publisher information for this volume. +Default: none. +.It Cm volume-id Ns = Ns Ar string +The specified string will be used as the Volume Identifier in the ISO9660 metadata. +It is limited to 32 bytes. +Default: none. +.El +.It Format iso9660 - boot support +These options are used to make an ISO9660 image that can be directly +booted on various systems. +.Bl -tag -compact -width indent +.It Cm boot Ns = Ns Ar filename +The file matching this name will be used as the El Torito boot image file. +.It Cm boot-catalog Ns = Ns Ar name +The name that will be used for the El Torito boot catalog. +Default: +.Ar boot.catalog +.It Cm boot-info-table +The boot image file provided by the +.Cm boot Ns = Ns Ar filename +option will be edited with appropriate boot information in bytes 8 through 64. +Default: disabled +.It Cm boot-load-seg Ns = Ns Ar hexadecimal-number +The load segment for a no-emulation boot image. +.It Cm boot-load-size Ns = Ns Ar decimal-number +The number of "virtual" 512-byte sectors to be loaded from a no-emulation boot image. +Some very old BIOSes can only load very small images, setting this +value to 4 will often allow such BIOSes to load the first part of +the boot image (which will then need to be intelligent enough to +load the rest of itself). +This should not be needed unless you are trying to support systems with very old BIOSes. +This defaults to the full size of the image. +.It Cm boot-type Ns = Ns Ar value +Specifies the boot semantics used by the El Torito boot image: +If the +.Ar value +is +.Cm fd , +then the boot image is assumed to be a bootable floppy image. +If the +.Ar value +is +.Cm hd , +then the boot image is assumed to be a bootable hard disk image. +If the +.Ar value +is +.Cm no-emulation , +the boot image is used without floppy or hard disk emulation. +If the boot image is exactly 1.2MB, 1.44MB, or 2.88MB, then +the default is +.Cm fd , +otherwise the default is +.Cm no-emulation . +.El +.It Format iso9660 - filename and size extensions +Various extensions to the base ISO9660 format. +.Bl -tag -compact -width indent +.It Cm allow-ldots +If enabled, allows filenames to begin with a leading period. +If disabled, filenames that begin with a leading period will have +that period replaced by an underscore character in the standard ISO9660 +namespace. +This does not impact names stored in the Rockridge or Joliet extension area. +Default: disabled. +.It Cm allow-lowercase +If enabled, allows filenames to contain lowercase characters. +If disabled, filenames will be forced to uppercase. +This does not impact names stored in the Rockridge or Joliet extension area. +Default: disabled. +.It Cm allow-multidot +If enabled, allows filenames to contain multiple period characters, in violation of the ISO9660 specification. +If disabled, additional periods will be converted to underscore characters. +This does not impact names stored in the Rockridge or Joliet extension area. +Default: disabled. +.It Cm allow-period +If enabled, allows filenames to contain trailing period characters, in violation of the ISO9660 specification. +If disabled, trailing periods will be converted to underscore characters. +This does not impact names stored in the Rockridge or Joliet extension area. +Default: disabled. +.It Cm allow-pvd-lowercase +If enabled, the Primary Volume Descriptor may contain lowercase ASCII characters, in violation of the ISO9660 specification. +If disabled, characters will be converted to uppercase ASCII. +Default: disabled. +.It Cm allow-sharp-tilde +If enabled, sharp and tilde characters will be permitted in filenames, in violation if the ISO9660 specification. +If disabled, such characters will be converted to underscore characters. +Default: disabled. +.It Cm allow-vernum +If enabled, version numbers will be included with files. +If disabled, version numbers will be suppressed, in violation of the ISO9660 standard. +This does not impact names stored in the Rockridge or Joliet extension area. +Default: enabled. +.It Cm iso-level +This enables support for file size and file name extensions in the +core ISO9660 area. +The name extensions specified here do not affect the names stored in the Rockridge or Joliet extension areas. +.Bl -tag -compact -width indent +.It Cm iso-level=1 +The most compliant form of ISO9660 image. +Filenames are limited to 8.3 uppercase format, +directory names are limited to 8 uppercase characters, +files are limited to 4 GiB, +the complete ISO9660 image cannot exceed 4 GiB. +.It Cm iso-level=2 +Filenames are limited to 30 uppercase characters with a 30-character extension, +directory names are limited to 30 characters, +files are limited to 4 GiB. +.It Cm iso-level=3 +As with +.Cm iso-level=2 , +except that files may exceed 4 GiB. +.It Cm iso-level=4 +As with +.Cm iso-level=3 , +except that filenames may be up to 193 characters +and may include arbitrary 8-bit characters. +.El +.It Cm joliet +Microsoft's Joliet extensions store a completely separate set of directory information about each file. +In particular, this information includes Unicode filenames of up to 255 characters. +Default: enabled. +.It Cm limit-depth +If enabled, libarchive will use directory relocation records to ensure that +no pathname exceeds the ISO9660 limit of 8 directory levels. +If disabled, no relocation will occur. +Default: enabled. +.It Cm limit-dirs +If enabled, libarchive will cause an error if there are more than +65536 directories. +If disabled, there is no limit on the number of directories. +Default: enabled +.It Cm pad +If enabled, 300 kiB of zero bytes will be appended to the end of the archive. +Default: enabled +.It Cm relaxed-filenames +If enabled, all 7-bit ASCII characters are permitted in filenames +(except lowercase characters unless +.Cm allow-lowercase +is also specified). +This violates ISO9660 standards. +This does not impact names stored in the Rockridge or Joliet extension area. +Default: disabled. +.It Cm rockridge +The Rockridge extensions store an additional set of POSIX-style file +information with each file, including mtime, atime, ctime, permissions, +and long filenames with arbitrary 8-bit characters. +These extensions also support symbolic links and other POSIX file types. +Default: enabled. +.El +.It Format iso9660 - zisofs support +The zisofs extensions permit each file to be independently compressed +using a gzip-compatible compression. +This can provide significant size savings, but requires the reading +system to have support for these extensions. +These extensions are disabled by default. +.Bl -tag -compact -width indent +.It Cm compression-level Ns = Ns number +The compression level used by the deflate compressor. +Ranges from 0 (least effort) to 9 (most effort). +Default: 6 +.It Cm zisofs +Synonym for +.Cm zisofs=direct . +.It Cm zisofs=direct +Compress each file in the archive. +Unlike +.Cm zisofs=indirect , +this is handled entirely within libarchive and does not require a +separate utility. +For best results, libarchive tests each file and will store +the file uncompressed if the compression does not actually save any space. +In particular, files under 2k will never be compressed. +Note that boot image files are never compressed. +.It Cm zisofs=indirect +Recognizes files that have already been compressed with the +.Cm mkzftree +utility and sets up the necessary file metadata so that +readers will correctly identify these as zisofs-compressed files. +.It Cm zisofs-exclude Ns = Ns Ar filename +Specifies a filename that should not be compressed when using +.Cm zisofs=direct . +This option can be provided multiple times to suppress compression +on many files. +.El +.It Format mtree +.Bl -tag -compact -width indent +.It Cm cksum , Cm device , Cm flags , Cm gid , Cm gname , Cm indent , Cm link , Cm md5 , Cm mode , Cm nlink , Cm rmd160 , Cm sha1 , Cm sha256 , Cm sha384 , Cm sha512 , Cm size , Cm time , Cm uid , Cm uname +Enable a particular keyword in the mtree output. +Prefix with an exclamation mark to disable the corresponding keyword. +The default is equivalent to +.Dq device, flags, gid, gname, link, mode, nlink, size, time, type, uid, uname . +.It Cm all +Enables all of the above keywords. +.It Cm use-set +Enables generation of +.Cm /set +lines that specify default values for the following files and/or directories. +.It Cm indent +XXX needs explanation XXX +.El +.It Format newc +.Bl -tag -compact -width indent +.It Cm hdrcharset +The value is used as a character set name that will be +used when translating file names. +.El +.It Format pax +.Bl -tag -compact -width indent +.It Cm hdrcharset +The value is used as a character set name that will be +used when translating file, group and user names. +The value is one of +.Dq BINARY +or +.Dq UTF-8 . +With +.Dq BINARY +there is no character conversion, with +.Dq UTF-8 +names are converted to UTF-8. +.It Cm xattrheader +When storing extended attributes, this option configures which +headers should be written. The value is one of +.Dq all , +.Dq LIBARCHIVE , +or +.Dq SCHILY . +By default, both +.Dq LIBARCHIVE.xattr +and +.Dq SCHILY.xattr +headers are written. +.El +.It Format ustar +.Bl -tag -compact -width indent +.It Cm hdrcharset +The value is used as a character set name that will be +used when translating file, group and user names. +.El +.It Format v7tar +.Bl -tag -compact -width indent +.It Cm hdrcharset +The value is used as a character set name that will be +used when translating file, group and user names. +.El +.It Format warc +.Bl -tag -compact -width indent +.It Cm omit-warcinfo +Set to +.Dq true +to disable output of the warcinfo record. +.El +.It Format xar +.Bl -tag -compact -width indent +.It Cm checksum Ns = Ns Ar type +Use +.Ar type +as file checksum method. +Supported values are +.Dq none , +.Dq md5 , +and +.Dq sha1 +.Pq default . +.It Cm compression Ns = Ns Ar type +Use +.Ar type +as compression method. +Supported values are +.Dq none , +.Dq bzip2 , +.Dq gzip +.Pq default , +.Dq lzma +and +.Dq xz . +.It Cm compression_level +The value is a decimal integer from 1 to 9 specifying the compression level. +.It Cm toc-checksum Ns = Ns Ar type +Use +.Ar type +as table of contents checksum method. +Supported values are +.Dq none , +.Dq md5 +and +.Dq sha1 +.Pq default . +.El +.It Format zip +.Bl -tag -compact -width indent +.It Cm compression +The value is either +.Dq store +or +.Dq deflate +to indicate how the following entries should be compressed. +Note that this setting is ignored for directories, symbolic links, +and other special entries. +.It Cm compression-level +The value is interpreted as a decimal integer specifying the +compression level. +Values between 0 and 9 are supported. +A compression level of 0 switches the compression method to +.Dq store , +other values will enable +.Dq deflate +compression with the given level. +.It Cm encryption +Enable encryption using traditional zip encryption. +.It Cm encryption Ns = Ns Ar type +Use +.Ar type +as encryption type. +Supported values are +.Dq zipcrypt +.Pq traditional zip encryption , +.Dq aes128 +.Pq WinZip AES-128 encryption +and +.Dq aes256 +.Pq WinZip AES-256 encryption . +.It Cm experimental +This boolean option enables or disables experimental Zip features +that may not be compatible with other Zip implementations. +.It Cm fakecrc32 +This boolean option disables CRC calculations. +All CRC fields are set to zero. +It should not be used except for testing purposes. +.It Cm hdrcharset +The value is used as a character set name that will be +used when translating file names. +.It Cm zip64 +Zip64 extensions provide additional file size information +for entries larger than 4 GiB. +They also provide extended file offset and archive size information +when archives exceed 4 GiB. +By default, the Zip writer selectively enables these extensions only as needed. +In particular, if the file size is unknown, the Zip writer will +include Zip64 extensions to guard against the possibility that the +file might be larger than 4 GiB. +.Pp +Setting this boolean option will force the writer to use Zip64 extensions +even for small files that would not otherwise require them. +This is primarily useful for testing. +.Pp +Disabling this option with +.Cm !zip64 +will force the Zip writer to avoid Zip64 extensions: +It will reject files with size greater than 4 GiB, +it will reject any new entries once the total archive size reaches 4 GiB, +and it will not use Zip64 extensions for files with unknown size. +In particular, this can improve compatibility when generating archives +where the entry sizes are not known in advance. +.El +.El +.Sh EXAMPLES +The following example creates an archive write handle to +create a gzip-compressed ISO9660 format image. +The two options here specify that the ISO9660 archive will use +.Ar kernel.img +as the boot image for El Torito booting, and that the gzip +compressor should use the maximum compression level. +.Bd -literal -offset indent +a = archive_write_new(); +archive_write_add_filter_gzip(a); +archive_write_set_format_iso9660(a); +archive_write_set_options(a, "boot=kernel.img,compression=9"); +archive_write_open_filename(a, filename, blocksize); +.Ed +.\" +.Sh ERRORS +More detailed error codes and textual descriptions are available from the +.Fn archive_errno +and +.Fn archive_error_string +functions. +.\" +.Sh SEE ALSO +.Xr tar 1 , +.Xr archive_read_set_options 3 , +.Xr archive_write 3 , +.Xr libarchive 3 +.Sh HISTORY +The +.Nm libarchive +library first appeared in +.Fx 5.3 . +.Sh AUTHORS +.An -nosplit +The options support for libarchive was originally implemented by +.An Michihiro NAKAJIMA . +.Sh BUGS diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_set_options.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_options.c new file mode 100644 index 0000000..962309a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_options.c @@ -0,0 +1,130 @@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#include "archive_write_private.h" +#include "archive_options_private.h" + +static int archive_set_format_option(struct archive *a, + const char *m, const char *o, const char *v); +static int archive_set_filter_option(struct archive *a, + const char *m, const char *o, const char *v); +static int archive_set_option(struct archive *a, + const char *m, const char *o, const char *v); + +int +archive_write_set_format_option(struct archive *a, const char *m, const char *o, + const char *v) +{ + return _archive_set_option(a, m, o, v, + ARCHIVE_WRITE_MAGIC, "archive_write_set_format_option", + archive_set_format_option); +} + +int +archive_write_set_filter_option(struct archive *a, const char *m, const char *o, + const char *v) +{ + return _archive_set_option(a, m, o, v, + ARCHIVE_WRITE_MAGIC, "archive_write_set_filter_option", + archive_set_filter_option); +} + +int +archive_write_set_option(struct archive *a, const char *m, const char *o, + const char *v) +{ + return _archive_set_option(a, m, o, v, + ARCHIVE_WRITE_MAGIC, "archive_write_set_option", + archive_set_option); +} + +int +archive_write_set_options(struct archive *a, const char *options) +{ + return _archive_set_options(a, options, + ARCHIVE_WRITE_MAGIC, "archive_write_set_options", + archive_set_option); +} + +static int +archive_set_format_option(struct archive *_a, const char *m, const char *o, + const char *v) +{ + struct archive_write *a = (struct archive_write *)_a; + + if (a->format_name == NULL) + return (m == NULL)?ARCHIVE_FAILED:ARCHIVE_WARN - 1; + /* If the format name didn't match, return a special code for + * _archive_set_option[s]. */ + if (m != NULL && strcmp(m, a->format_name) != 0) + return (ARCHIVE_WARN - 1); + if (a->format_options == NULL) + return (ARCHIVE_WARN); + return a->format_options(a, o, v); +} + +static int +archive_set_filter_option(struct archive *_a, const char *m, const char *o, + const char *v) +{ + struct archive_write *a = (struct archive_write *)_a; + struct archive_write_filter *filter; + int r, rv = ARCHIVE_WARN; + + for (filter = a->filter_first; filter != NULL; filter = filter->next_filter) { + if (filter->options == NULL) + continue; + if (m != NULL && strcmp(filter->name, m) != 0) + continue; + + r = filter->options(filter, o, v); + + if (r == ARCHIVE_FATAL) + return (ARCHIVE_FATAL); + + if (m != NULL) + return (r); + + if (r == ARCHIVE_OK) + rv = ARCHIVE_OK; + } + /* If the filter name didn't match, return a special code for + * _archive_set_option[s]. */ + if (rv == ARCHIVE_WARN && m != NULL) + rv = ARCHIVE_WARN - 1; + return (rv); +} + +static int +archive_set_option(struct archive *a, const char *m, const char *o, + const char *v) +{ + return _archive_set_either_option(a, m, o, v, + archive_set_format_option, + archive_set_filter_option); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_set_passphrase.3 b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_passphrase.3 new file mode 100644 index 0000000..2db7703 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_passphrase.3 @@ -0,0 +1,74 @@ +.\" Copyright (c) 2014 Michihiro NAKAJIMA +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd September 21, 2014 +.Dt ARCHIVE_WRITE_SET_PASSPHRASE 3 +.Os +.Sh NAME +.Nm archive_write_set_passphrase , +.Nm archive_write_set_passphrase_callback +.Nd functions for writing encrypted archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) +.Sh SYNOPSIS +.In archive.h +.Ft int +.Fo archive_write_set_passphrase +.Fa "struct archive *" +.Fa "const char *passphrase" +.Fc +.Ft int +.Fo archive_write_set_passphrase_callback +.Fa "struct archive *" +.Fa "void *client_data" +.Fa "archive_passphrase_callback *" +.Fc +.Sh DESCRIPTION +.Bl -tag -width indent +.It Fn archive_write_set_passphrase +Set a passphrase for writing an encrypted archive. +If +.Ar passphrase +is +.Dv NULL +or empty, this function will do nothing and +.Cm ARCHIVE_FAILED +will be returned. +Otherwise, +.Cm ARCHIVE_OK +will be returned. +.It Fn archive_write_set_passphrase_callback +Register a callback function that will be invoked to get a passphrase +for encryption if the passphrase was not set by the +.Fn archive_write_set_passphrase +function. +.El +.\" .Sh ERRORS +.Sh SEE ALSO +.Xr tar 1 , +.Xr archive_write 3 , +.Xr archive_write_set_options 3 , +.Xr libarchive 3 diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_write_set_passphrase.c b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_passphrase.c new file mode 100644 index 0000000..710ecba --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_write_set_passphrase.c @@ -0,0 +1,95 @@ +/*- + * Copyright (c) 2014 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#include "archive_write_private.h" + +int +archive_write_set_passphrase(struct archive *_a, const char *p) +{ + struct archive_write *a = (struct archive_write *)_a; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, + "archive_write_set_passphrase"); + + if (p == NULL || p[0] == '\0') { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Empty passphrase is unacceptable"); + return (ARCHIVE_FAILED); + } + free(a->passphrase); + a->passphrase = strdup(p); + if (a->passphrase == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate data for passphrase"); + return (ARCHIVE_FATAL); + } + return (ARCHIVE_OK); +} + + +int +archive_write_set_passphrase_callback(struct archive *_a, void *client_data, + archive_passphrase_callback *cb) +{ + struct archive_write *a = (struct archive_write *)_a; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, + "archive_write_set_passphrase_callback"); + + a->passphrase_callback = cb; + a->passphrase_client_data = client_data; + return (ARCHIVE_OK); +} + + +const char * +__archive_write_get_passphrase(struct archive_write *a) +{ + + if (a->passphrase != NULL) + return (a->passphrase); + + if (a->passphrase_callback != NULL) { + const char *p; + p = a->passphrase_callback(&a->archive, + a->passphrase_client_data); + if (p != NULL) { + a->passphrase = strdup(p); + if (a->passphrase == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate data for passphrase"); + return (NULL); + } + return (a->passphrase); + } + } + return (NULL); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/archive_xxhash.h b/dependencies/libarchive-3.4.2/libarchive/archive_xxhash.h new file mode 100644 index 0000000..1c7131c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/archive_xxhash.h @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2014 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef ARCHIVE_XXHASH_H_INCLUDED +#define ARCHIVE_XXHASH_H_INCLUDED + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif + + +typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode; + +struct archive_xxhash { + unsigned int (*XXH32)(const void* input, unsigned int len, + unsigned int seed); + void* (*XXH32_init)(unsigned int seed); + XXH_errorcode (*XXH32_update)(void* state, const void* input, + unsigned int len); + unsigned int (*XXH32_digest)(void* state); +}; + +extern const struct archive_xxhash __archive_xxhash; + +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/config_freebsd.h b/dependencies/libarchive-3.4.2/libarchive/config_freebsd.h new file mode 100644 index 0000000..f16fd34 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/config_freebsd.h @@ -0,0 +1,260 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include + +/* FreeBSD 5.0 and later has ACL and extattr support. */ +#if __FreeBSD__ > 4 +#define ARCHIVE_ACL_FREEBSD 1 +#define HAVE_ACL_GET_PERM_NP 1 +#define HAVE_ARC4RANDOM_BUF 1 +#define HAVE_EXTATTR_GET_FILE 1 +#define HAVE_EXTATTR_LIST_FILE 1 +#define HAVE_EXTATTR_SET_FD 1 +#define HAVE_EXTATTR_SET_FILE 1 +#define HAVE_STRUCT_XVFSCONF 1 +#define HAVE_SYS_ACL_H 1 +#define HAVE_SYS_EXTATTR_H 1 +#if __FreeBSD__ > 7 +/* FreeBSD 8.0 and later has NFSv4 ACL support */ +#define ARCHIVE_ACL_FREEBSD_NFS4 1 +#define HAVE_ACL_GET_LINK_NP 1 +#define HAVE_ACL_IS_TRIVIAL_NP 1 +#define HAVE_ACL_SET_LINK_NP 1 +#endif /* __FreeBSD__ > 7 */ +#endif /* __FreeBSD__ > 4 */ + +#ifdef WITH_OPENSSL +#define HAVE_LIBCRYPTO 1 +#define HAVE_OPENSSL_EVP_H 1 +#define HAVE_OPENSSL_MD5_H 1 +#define HAVE_OPENSSL_RIPEMD_H 1 +#define HAVE_OPENSSL_SHA_H 1 +#define HAVE_OPENSSL_SHA256_INIT 1 +#define HAVE_OPENSSL_SHA384_INIT 1 +#define HAVE_OPENSSL_SHA512_INIT 1 +#define HAVE_PKCS5_PBKDF2_HMAC_SHA1 1 +#define HAVE_SHA256 1 +#define HAVE_SHA384 1 +#define HAVE_SHA512 1 +#else +#define HAVE_LIBMD 1 +#define HAVE_MD5_H 1 +#define HAVE_MD5INIT 1 +#define HAVE_RIPEMD_H 1 +#define HAVE_SHA_H 1 +#define HAVE_SHA1 1 +#define HAVE_SHA1_INIT 1 +#define HAVE_SHA256 1 +#define HAVE_SHA256_H 1 +#define HAVE_SHA256_INIT 1 +#define HAVE_SHA512 1 +#define HAVE_SHA512_H 1 +#define HAVE_SHA512_INIT 1 +#endif + +#define HAVE_BSDXML_H 1 +#define HAVE_BZLIB_H 1 +#define HAVE_CHFLAGS 1 +#define HAVE_CHOWN 1 +#define HAVE_CHROOT 1 +#define HAVE_CTIME_R 1 +#define HAVE_CTYPE_H 1 +#define HAVE_DECL_EXTATTR_NAMESPACE_USER 1 +#define HAVE_DECL_INT32_MAX 1 +#define HAVE_DECL_INT32_MIN 1 +#define HAVE_DECL_INT64_MAX 1 +#define HAVE_DECL_INT64_MIN 1 +#define HAVE_DECL_INTMAX_MAX 1 +#define HAVE_DECL_INTMAX_MIN 1 +#define HAVE_DECL_SIZE_MAX 1 +#define HAVE_DECL_SSIZE_MAX 1 +#define HAVE_DECL_STRERROR_R 1 +#define HAVE_DECL_UINT32_MAX 1 +#define HAVE_DECL_UINT64_MAX 1 +#define HAVE_DECL_UINTMAX_MAX 1 +#define HAVE_DIRENT_H 1 +#define HAVE_DLFCN_H 1 +#define HAVE_D_MD_ORDER 1 +#define HAVE_EFTYPE 1 +#define HAVE_EILSEQ 1 +#define HAVE_ERRNO_H 1 +#define HAVE_FCHDIR 1 +#define HAVE_FCHFLAGS 1 +#define HAVE_FCHMOD 1 +#define HAVE_FCHOWN 1 +#define HAVE_FCNTL 1 +#define HAVE_FCNTL_H 1 +#define HAVE_FDOPENDIR 1 +#define HAVE_FORK 1 +#define HAVE_FSEEKO 1 +#define HAVE_FSTAT 1 +#define HAVE_FSTATAT 1 +#define HAVE_FSTATFS 1 +#define HAVE_FSTATVFS 1 +#define HAVE_FTRUNCATE 1 +#define HAVE_FUTIMES 1 +#define HAVE_FUTIMESAT 1 +#define HAVE_GETEUID 1 +#define HAVE_GETGRGID_R 1 +#define HAVE_GETGRNAM_R 1 +#define HAVE_GETPID 1 +#define HAVE_GETPWNAM_R 1 +#define HAVE_GETPWUID_R 1 +#define HAVE_GETVFSBYNAME 1 +#define HAVE_GMTIME_R 1 +#define HAVE_GRP_H 1 +#define HAVE_INTMAX_T 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_LANGINFO_H 1 +#define HAVE_LCHFLAGS 1 +#define HAVE_LCHMOD 1 +#define HAVE_LCHOWN 1 +#define HAVE_LIBZ 1 +#define HAVE_LIMITS_H 1 +#define HAVE_LINK 1 +#define HAVE_LOCALE_H 1 +#define HAVE_LOCALTIME_R 1 +#define HAVE_LONG_LONG_INT 1 +#define HAVE_LSTAT 1 +#define HAVE_LUTIMES 1 +#define HAVE_MBRTOWC 1 +#define HAVE_MEMMOVE 1 +#define HAVE_MEMORY_H 1 +#define HAVE_MEMSET 1 +#define HAVE_MKDIR 1 +#define HAVE_MKFIFO 1 +#define HAVE_MKNOD 1 +#define HAVE_MKSTEMP 1 +#define HAVE_NL_LANGINFO 1 +#define HAVE_OPENAT 1 +#define HAVE_PATHS_H 1 +#define HAVE_PIPE 1 +#define HAVE_POLL 1 +#define HAVE_POLL_H 1 +#define HAVE_POSIX_SPAWNP 1 +#define HAVE_PTHREAD_H 1 +#define HAVE_PWD_H 1 +#define HAVE_READDIR_R 1 +#define HAVE_READLINK 1 +#define HAVE_READLINKAT 1 +#define HAVE_READPASSPHRASE 1 +#define HAVE_READPASSPHRASE_H 1 +#define HAVE_REGEX_H 1 +#define HAVE_SELECT 1 +#define HAVE_SETENV 1 +#define HAVE_SETLOCALE 1 +#define HAVE_SIGACTION 1 +#define HAVE_SIGNAL_H 1 +#define HAVE_SPAWN_H 1 +#define HAVE_STATFS 1 +#define HAVE_STATVFS 1 +#define HAVE_STDARG_H 1 +#define HAVE_STDINT_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_STRCHR 1 +#define HAVE_STRDUP 1 +#define HAVE_STRERROR 1 +#define HAVE_STRERROR_R 1 +#define HAVE_STRFTIME 1 +#define HAVE_STRINGS_H 1 +#define HAVE_STRING_H 1 +#define HAVE_STRRCHR 1 +#define HAVE_STRUCT_STATFS_F_NAMEMAX 1 +#define HAVE_STRUCT_STAT_ST_BIRTHTIME 1 +#define HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC 1 +#define HAVE_STRUCT_STAT_ST_BLKSIZE 1 +#define HAVE_STRUCT_STAT_ST_FLAGS 1 +#define HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1 +#define HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1 +#define HAVE_STRUCT_TM_TM_GMTOFF 1 +#define HAVE_SYMLINK 1 +#define HAVE_SYS_CDEFS_H 1 +#define HAVE_SYS_IOCTL_H 1 +#define HAVE_SYS_MOUNT_H 1 +#define HAVE_SYS_PARAM_H 1 +#define HAVE_SYS_POLL_H 1 +#define HAVE_SYS_SELECT_H 1 +#define HAVE_SYS_STATVFS_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_SYS_TIME_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_SYS_UTSNAME_H 1 +#define HAVE_SYS_WAIT_H 1 +#define HAVE_TIMEGM 1 +#define HAVE_TIME_H 1 +#define HAVE_TZSET 1 +#define HAVE_UINTMAX_T 1 +#define HAVE_UNISTD_H 1 +#define HAVE_UNLINKAT 1 +#define HAVE_UNSETENV 1 +#define HAVE_UNSIGNED_LONG_LONG 1 +#define HAVE_UNSIGNED_LONG_LONG_INT 1 +#define HAVE_UTIME 1 +#define HAVE_UTIMES 1 +#define HAVE_UTIME_H 1 +#define HAVE_VFORK 1 +#define HAVE_VPRINTF 1 +#define HAVE_WCHAR_H 1 +#define HAVE_WCHAR_T 1 +#define HAVE_WCRTOMB 1 +#define HAVE_WCSCMP 1 +#define HAVE_WCSCPY 1 +#define HAVE_WCSLEN 1 +#define HAVE_WCTOMB 1 +#define HAVE_WCTYPE_H 1 +#define HAVE_WMEMCMP 1 +#define HAVE_WMEMCPY 1 +#define HAVE_WMEMMOVE 1 +#define HAVE_ZLIB_H 1 +#define TIME_WITH_SYS_TIME 1 + +#if __FreeBSD_version >= 1100056 +#define HAVE_FUTIMENS 1 +#define HAVE_UTIMENSAT 1 +#endif + +/* FreeBSD 4 and earlier lack intmax_t/uintmax_t */ +#if __FreeBSD__ < 5 +#define intmax_t int64_t +#define uintmax_t uint64_t +#endif + +/* FreeBSD defines for archive_hash.h */ +#ifdef WITH_OPENSSL +#define ARCHIVE_CRYPTO_MD5_OPENSSL 1 +#define ARCHIVE_CRYPTO_RMD160_OPENSSL 1 +#define ARCHIVE_CRYPTO_SHA1_OPENSSL +#define ARCHIVE_CRYPTO_SHA256_OPENSSL 1 +#define ARCHIVE_CRYPTO_SHA384_OPENSSL 1 +#define ARCHIVE_CRYPTO_SHA512_OPENSSL 1 +#else +#define ARCHIVE_CRYPTO_MD5_LIBMD 1 +#define ARCHIVE_CRYPTO_SHA1_LIBMD 1 +#define ARCHIVE_CRYPTO_SHA256_LIBMD 1 +#define ARCHIVE_CRYPTO_SHA512_LIBMD 1 +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/cpio.5 b/dependencies/libarchive-3.4.2/libarchive/cpio.5 new file mode 100644 index 0000000..1a2886f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/cpio.5 @@ -0,0 +1,325 @@ +.\" Copyright (c) 2007 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd December 23, 2011 +.Dt CPIO 5 +.Os +.Sh NAME +.Nm cpio +.Nd format of cpio archive files +.Sh DESCRIPTION +The +.Nm +archive format collects any number of files, directories, and other +file system objects (symbolic links, device nodes, etc.) into a single +stream of bytes. +.Ss General Format +Each file system object in a +.Nm +archive comprises a header record with basic numeric metadata +followed by the full pathname of the entry and the file data. +The header record stores a series of integer values that generally +follow the fields in +.Va struct stat . +(See +.Xr stat 2 +for details.) +The variants differ primarily in how they store those integers +(binary, octal, or hexadecimal). +The header is followed by the pathname of the +entry (the length of the pathname is stored in the header) +and any file data. +The end of the archive is indicated by a special record with +the pathname +.Dq TRAILER!!! . +.Ss PWB format +XXX Any documentation of the original PWB/UNIX 1.0 format? XXX +.Ss Old Binary Format +The old binary +.Nm +format stores numbers as 2-byte and 4-byte binary values. +Each entry begins with a header in the following format: +.Bd -literal -offset indent +struct header_old_cpio { + unsigned short c_magic; + unsigned short c_dev; + unsigned short c_ino; + unsigned short c_mode; + unsigned short c_uid; + unsigned short c_gid; + unsigned short c_nlink; + unsigned short c_rdev; + unsigned short c_mtime[2]; + unsigned short c_namesize; + unsigned short c_filesize[2]; +}; +.Ed +.Pp +The +.Va unsigned short +fields here are 16-bit integer values; the +.Va unsigned int +fields are 32-bit integer values. +The fields are as follows +.Bl -tag -width indent +.It Va magic +The integer value octal 070707. +This value can be used to determine whether this archive is +written with little-endian or big-endian integers. +.It Va dev , Va ino +The device and inode numbers from the disk. +These are used by programs that read +.Nm +archives to determine when two entries refer to the same file. +Programs that synthesize +.Nm +archives should be careful to set these to distinct values for each entry. +.It Va mode +The mode specifies both the regular permissions and the file type. +It consists of several bit fields as follows: +.Bl -tag -width "MMMMMMM" -compact +.It 0170000 +This masks the file type bits. +.It 0140000 +File type value for sockets. +.It 0120000 +File type value for symbolic links. +For symbolic links, the link body is stored as file data. +.It 0100000 +File type value for regular files. +.It 0060000 +File type value for block special devices. +.It 0040000 +File type value for directories. +.It 0020000 +File type value for character special devices. +.It 0010000 +File type value for named pipes or FIFOs. +.It 0004000 +SUID bit. +.It 0002000 +SGID bit. +.It 0001000 +Sticky bit. +On some systems, this modifies the behavior of executables and/or directories. +.It 0000777 +The lower 9 bits specify read/write/execute permissions +for world, group, and user following standard POSIX conventions. +.El +.It Va uid , Va gid +The numeric user id and group id of the owner. +.It Va nlink +The number of links to this file. +Directories always have a value of at least two here. +Note that hardlinked files include file data with every copy in the archive. +.It Va rdev +For block special and character special entries, +this field contains the associated device number. +For all other entry types, it should be set to zero by writers +and ignored by readers. +.It Va mtime +Modification time of the file, indicated as the number +of seconds since the start of the epoch, +00:00:00 UTC January 1, 1970. +The four-byte integer is stored with the most-significant 16 bits first +followed by the least-significant 16 bits. +Each of the two 16 bit values are stored in machine-native byte order. +.It Va namesize +The number of bytes in the pathname that follows the header. +This count includes the trailing NUL byte. +.It Va filesize +The size of the file. +Note that this archive format is limited to +four gigabyte file sizes. +See +.Va mtime +above for a description of the storage of four-byte integers. +.El +.Pp +The pathname immediately follows the fixed header. +If the +.Cm namesize +is odd, an additional NUL byte is added after the pathname. +The file data is then appended, padded with NUL +bytes to an even length. +.Pp +Hardlinked files are not given special treatment; +the full file contents are included with each copy of the +file. +.Ss Portable ASCII Format +.St -susv2 +standardized an ASCII variant that is portable across all +platforms. +It is commonly known as the +.Dq old character +format or as the +.Dq odc +format. +It stores the same numeric fields as the old binary format, but +represents them as 6-character or 11-character octal values. +.Bd -literal -offset indent +struct cpio_odc_header { + char c_magic[6]; + char c_dev[6]; + char c_ino[6]; + char c_mode[6]; + char c_uid[6]; + char c_gid[6]; + char c_nlink[6]; + char c_rdev[6]; + char c_mtime[11]; + char c_namesize[6]; + char c_filesize[11]; +}; +.Ed +.Pp +The fields are identical to those in the old binary format. +The name and file body follow the fixed header. +Unlike the old binary format, there is no additional padding +after the pathname or file contents. +If the files being archived are themselves entirely ASCII, then +the resulting archive will be entirely ASCII, except for the +NUL byte that terminates the name field. +.Ss New ASCII Format +The "new" ASCII format uses 8-byte hexadecimal fields for +all numbers and separates device numbers into separate fields +for major and minor numbers. +.Bd -literal -offset indent +struct cpio_newc_header { + char c_magic[6]; + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; +}; +.Ed +.Pp +Except as specified below, the fields here match those specified +for the old binary format above. +.Bl -tag -width indent +.It Va magic +The string +.Dq 070701 . +.It Va check +This field is always set to zero by writers and ignored by readers. +See the next section for more details. +.El +.Pp +The pathname is followed by NUL bytes so that the total size +of the fixed header plus pathname is a multiple of four. +Likewise, the file data is padded to a multiple of four bytes. +Note that this format supports only 4 gigabyte files (unlike the +older ASCII format, which supports 8 gigabyte files). +.Pp +In this format, hardlinked files are handled by setting the +filesize to zero for each entry except the last one that +appears in the archive. +.Ss New CRC Format +The CRC format is identical to the new ASCII format described +in the previous section except that the magic field is set +to +.Dq 070702 +and the +.Va check +field is set to the sum of all bytes in the file data. +This sum is computed treating all bytes as unsigned values +and using unsigned arithmetic. +Only the least-significant 32 bits of the sum are stored. +.Ss HP variants +The +.Nm cpio +implementation distributed with HPUX used XXXX but stored +device numbers differently XXX. +.Ss Other Extensions and Variants +Sun Solaris uses additional file types to store extended file +data, including ACLs and extended attributes, as special +entries in cpio archives. +.Pp +XXX Others? XXX +.Sh SEE ALSO +.Xr cpio 1 , +.Xr tar 5 +.Sh STANDARDS +The +.Nm cpio +utility is no longer a part of POSIX or the Single Unix Standard. +It last appeared in +.St -susv2 . +It has been supplanted in subsequent standards by +.Xr pax 1 . +The portable ASCII format is currently part of the specification for the +.Xr pax 1 +utility. +.Sh HISTORY +The original cpio utility was written by Dick Haight +while working in AT&T's Unix Support Group. +It appeared in 1977 as part of PWB/UNIX 1.0, the +.Dq Programmer's Work Bench +derived from +.At v6 +that was used internally at AT&T. +Both the old binary and old character formats were in use +by 1980, according to the System III source released +by SCO under their +.Dq Ancient Unix +license. +The character format was adopted as part of +.St -p1003.1-88 . +XXX when did "newc" appear? Who invented it? When did HP come out with their variant? When did Sun introduce ACLs and extended attributes? XXX +.Sh BUGS +The +.Dq CRC +format is mis-named, as it uses a simple checksum and +not a cyclic redundancy check. +.Pp +The old binary format is limited to 16 bits for user id, +group id, device, and inode numbers. +It is limited to 4 gigabyte file sizes. +.Pp +The old ASCII format is limited to 18 bits for +the user id, group id, device, and inode numbers. +It is limited to 8 gigabyte file sizes. +.Pp +The new ASCII format is limited to 4 gigabyte file sizes. +.Pp +None of the cpio formats store user or group names, +which are essential when moving files between systems with +dissimilar user or group numbering. +.Pp +Especially when writing older cpio variants, it may be necessary +to map actual device/inode values to synthesized values that +fit the available fields. +With very large filesystems, this may be necessary even for +the newer formats. diff --git a/dependencies/libarchive-3.4.2/libarchive/filter_fork.h b/dependencies/libarchive-3.4.2/libarchive/filter_fork.h new file mode 100644 index 0000000..908e7cd --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/filter_fork.h @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 2007 Joerg Sonnenberger + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: head/lib/libarchive/filter_fork.h 201087 2009-12-28 02:18:26Z kientzle $ + */ + +#ifndef FILTER_FORK_H +#define FILTER_FORK_H + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif + +pid_t +__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout); + +void +__archive_check_child(int in, int out); + +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive/filter_fork_posix.c b/dependencies/libarchive-3.4.2/libarchive/filter_fork_posix.c new file mode 100644 index 0000000..02dbd4b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/filter_fork_posix.c @@ -0,0 +1,238 @@ +/*- + * Copyright (c) 2007 Joerg Sonnenberger + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +/* This capability is only available on POSIX systems. */ +#if defined(HAVE_PIPE) && defined(HAVE_FCNTL) && \ + (defined(HAVE_FORK) || defined(HAVE_VFORK) || defined(HAVE_POSIX_SPAWNP)) + +__FBSDID("$FreeBSD: head/lib/libarchive/filter_fork.c 182958 2008-09-12 05:33:00Z kientzle $"); + +#if defined(HAVE_SYS_TYPES_H) +# include +#endif +#ifdef HAVE_ERRNO_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif +#if defined(HAVE_POLL) && (defined(HAVE_POLL_H) || defined(HAVE_SYS_POLL_H)) +# if defined(HAVE_POLL_H) +# include +# elif defined(HAVE_SYS_POLL_H) +# include +# endif +#elif defined(HAVE_SELECT) +# if defined(HAVE_SYS_SELECT_H) +# include +# elif defined(HAVE_UNISTD_H) +# include +# endif +#endif +#ifdef HAVE_FCNTL_H +# include +#endif +#ifdef HAVE_SPAWN_H +# include +#endif +#ifdef HAVE_STDLIB_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif + +#include "archive.h" +#include "archive_cmdline_private.h" + +#include "filter_fork.h" + +pid_t +__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout) +{ + pid_t child; + int stdin_pipe[2], stdout_pipe[2], tmp; +#if HAVE_POSIX_SPAWNP + posix_spawn_file_actions_t actions; + int r; +#endif + struct archive_cmdline *cmdline; + + cmdline = __archive_cmdline_allocate(); + if (cmdline == NULL) + goto state_allocated; + if (__archive_cmdline_parse(cmdline, cmd) != ARCHIVE_OK) + goto state_allocated; + + if (pipe(stdin_pipe) == -1) + goto state_allocated; + if (stdin_pipe[0] == 1 /* stdout */) { + if ((tmp = dup(stdin_pipe[0])) == -1) + goto stdin_opened; + close(stdin_pipe[0]); + stdin_pipe[0] = tmp; + } + if (pipe(stdout_pipe) == -1) + goto stdin_opened; + if (stdout_pipe[1] == 0 /* stdin */) { + if ((tmp = dup(stdout_pipe[1])) == -1) + goto stdout_opened; + close(stdout_pipe[1]); + stdout_pipe[1] = tmp; + } + +#if HAVE_POSIX_SPAWNP + + r = posix_spawn_file_actions_init(&actions); + if (r != 0) { + errno = r; + goto stdout_opened; + } + r = posix_spawn_file_actions_addclose(&actions, stdin_pipe[1]); + if (r != 0) + goto actions_inited; + r = posix_spawn_file_actions_addclose(&actions, stdout_pipe[0]); + if (r != 0) + goto actions_inited; + /* Setup for stdin. */ + r = posix_spawn_file_actions_adddup2(&actions, stdin_pipe[0], 0); + if (r != 0) + goto actions_inited; + if (stdin_pipe[0] != 0 /* stdin */) { + r = posix_spawn_file_actions_addclose(&actions, stdin_pipe[0]); + if (r != 0) + goto actions_inited; + } + /* Setup for stdout. */ + r = posix_spawn_file_actions_adddup2(&actions, stdout_pipe[1], 1); + if (r != 0) + goto actions_inited; + if (stdout_pipe[1] != 1 /* stdout */) { + r = posix_spawn_file_actions_addclose(&actions, stdout_pipe[1]); + if (r != 0) + goto actions_inited; + } + r = posix_spawnp(&child, cmdline->path, &actions, NULL, + cmdline->argv, NULL); + if (r != 0) + goto actions_inited; + posix_spawn_file_actions_destroy(&actions); + +#else /* HAVE_POSIX_SPAWNP */ + +#if HAVE_VFORK + child = vfork(); +#else + child = fork(); +#endif + if (child == -1) + goto stdout_opened; + if (child == 0) { + close(stdin_pipe[1]); + close(stdout_pipe[0]); + if (dup2(stdin_pipe[0], 0 /* stdin */) == -1) + _exit(254); + if (stdin_pipe[0] != 0 /* stdin */) + close(stdin_pipe[0]); + if (dup2(stdout_pipe[1], 1 /* stdout */) == -1) + _exit(254); + if (stdout_pipe[1] != 1 /* stdout */) + close(stdout_pipe[1]); + execvp(cmdline->path, cmdline->argv); + _exit(254); + } +#endif /* HAVE_POSIX_SPAWNP */ + + close(stdin_pipe[0]); + close(stdout_pipe[1]); + + *child_stdin = stdin_pipe[1]; + fcntl(*child_stdin, F_SETFL, O_NONBLOCK); + *child_stdout = stdout_pipe[0]; + fcntl(*child_stdout, F_SETFL, O_NONBLOCK); + __archive_cmdline_free(cmdline); + + return child; + +#if HAVE_POSIX_SPAWNP +actions_inited: + errno = r; + posix_spawn_file_actions_destroy(&actions); +#endif +stdout_opened: + close(stdout_pipe[0]); + close(stdout_pipe[1]); +stdin_opened: + close(stdin_pipe[0]); + close(stdin_pipe[1]); +state_allocated: + __archive_cmdline_free(cmdline); + return -1; +} + +void +__archive_check_child(int in, int out) +{ +#if defined(HAVE_POLL) && (defined(HAVE_POLL_H) || defined(HAVE_SYS_POLL_H)) + struct pollfd fds[2]; + int idx; + + idx = 0; + if (in != -1) { + fds[idx].fd = in; + fds[idx].events = POLLOUT; + ++idx; + } + if (out != -1) { + fds[idx].fd = out; + fds[idx].events = POLLIN; + ++idx; + } + + poll(fds, idx, -1); /* -1 == INFTIM, wait forever */ +#elif defined(HAVE_SELECT) + fd_set fds_in, fds_out, fds_error; + + FD_ZERO(&fds_in); + FD_ZERO(&fds_out); + FD_ZERO(&fds_error); + if (out != -1) { + FD_SET(out, &fds_in); + FD_SET(out, &fds_error); + } + if (in != -1) { + FD_SET(in, &fds_out); + FD_SET(in, &fds_error); + } + select(in < out ? out + 1 : in + 1, &fds_in, &fds_out, &fds_error, NULL); +#else + sleep(1); +#endif +} + +#endif /* defined(HAVE_PIPE) && defined(HAVE_VFORK) && defined(HAVE_FCNTL) */ diff --git a/dependencies/libarchive-3.4.2/libarchive/filter_fork_windows.c b/dependencies/libarchive-3.4.2/libarchive/filter_fork_windows.c new file mode 100644 index 0000000..ad271fe --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/filter_fork_windows.c @@ -0,0 +1,190 @@ +/*- + * Copyright (c) 2009-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +#if defined(_WIN32) && !defined(__CYGWIN__) +#include "archive_cmdline_private.h" +#include "archive_string.h" + +#include "filter_fork.h" + +pid_t +__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout) +{ + HANDLE childStdout[2], childStdin[2],childStderr; + SECURITY_ATTRIBUTES secAtts; + STARTUPINFOA staInfo; + PROCESS_INFORMATION childInfo; + struct archive_string cmdline; + struct archive_string fullpath; + struct archive_cmdline *acmd; + char *arg0, *ext; + int i, l; + DWORD fl, fl_old; + + childStdout[0] = childStdout[1] = INVALID_HANDLE_VALUE; + childStdin[0] = childStdin[1] = INVALID_HANDLE_VALUE; + childStderr = INVALID_HANDLE_VALUE; + archive_string_init(&cmdline); + archive_string_init(&fullpath); + + acmd = __archive_cmdline_allocate(); + if (acmd == NULL) + goto fail; + if (__archive_cmdline_parse(acmd, cmd) != ARCHIVE_OK) + goto fail; + + /* + * Search the full path of 'path'. + * NOTE: This does not need if we give CreateProcessA 'path' as + * a part of the cmdline and give CreateProcessA NULL as first + * parameter, but I do not like that way. + */ + ext = strrchr(acmd->path, '.'); + if (ext == NULL || strlen(ext) > 4) + /* 'path' does not have a proper extension, so we have to + * give SearchPath() ".exe" as the extension. */ + ext = ".exe"; + else + ext = NULL;/* 'path' has an extension. */ + + fl = MAX_PATH; + do { + if (archive_string_ensure(&fullpath, fl) == NULL) + goto fail; + fl_old = fl; + fl = SearchPathA(NULL, acmd->path, ext, fl, fullpath.s, + &arg0); + } while (fl != 0 && fl > fl_old); + if (fl == 0) + goto fail; + + /* + * Make a command line. + */ + for (l = 0, i = 0; acmd->argv[i] != NULL; i++) { + if (i == 0) + continue; + l += (int)strlen(acmd->argv[i]) + 1; + } + if (archive_string_ensure(&cmdline, l + 1) == NULL) + goto fail; + for (i = 0; acmd->argv[i] != NULL; i++) { + if (i == 0) { + const char *p, *sp; + + if ((p = strchr(acmd->argv[i], '/')) != NULL || + (p = strchr(acmd->argv[i], '\\')) != NULL) + p++; + else + p = acmd->argv[i]; + if ((sp = strchr(p, ' ')) != NULL) + archive_strappend_char(&cmdline, '"'); + archive_strcat(&cmdline, p); + if (sp != NULL) + archive_strappend_char(&cmdline, '"'); + } else { + archive_strappend_char(&cmdline, ' '); + archive_strcat(&cmdline, acmd->argv[i]); + } + } + if (i <= 1) { + const char *sp; + + if ((sp = strchr(arg0, ' ')) != NULL) + archive_strappend_char(&cmdline, '"'); + archive_strcat(&cmdline, arg0); + if (sp != NULL) + archive_strappend_char(&cmdline, '"'); + } + + secAtts.nLength = sizeof(SECURITY_ATTRIBUTES); + secAtts.bInheritHandle = TRUE; + secAtts.lpSecurityDescriptor = NULL; + if (CreatePipe(&childStdout[0], &childStdout[1], &secAtts, 0) == 0) + goto fail; + if (!SetHandleInformation(childStdout[0], HANDLE_FLAG_INHERIT, 0)) + goto fail; + if (CreatePipe(&childStdin[0], &childStdin[1], &secAtts, 0) == 0) + goto fail; + if (!SetHandleInformation(childStdin[1], HANDLE_FLAG_INHERIT, 0)) + goto fail; + if (DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_ERROR_HANDLE), + GetCurrentProcess(), &childStderr, 0, TRUE, + DUPLICATE_SAME_ACCESS) == 0) + goto fail; + + memset(&staInfo, 0, sizeof(staInfo)); + staInfo.cb = sizeof(staInfo); + staInfo.hStdError = childStderr; + staInfo.hStdOutput = childStdout[1]; + staInfo.hStdInput = childStdin[0]; + staInfo.wShowWindow = SW_HIDE; + staInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; + if (CreateProcessA(fullpath.s, cmdline.s, NULL, NULL, TRUE, 0, + NULL, NULL, &staInfo, &childInfo) == 0) + goto fail; + WaitForInputIdle(childInfo.hProcess, INFINITE); + CloseHandle(childInfo.hProcess); + CloseHandle(childInfo.hThread); + + *child_stdout = _open_osfhandle((intptr_t)childStdout[0], _O_RDONLY); + *child_stdin = _open_osfhandle((intptr_t)childStdin[1], _O_WRONLY); + + CloseHandle(childStdout[1]); + CloseHandle(childStdin[0]); + + archive_string_free(&cmdline); + archive_string_free(&fullpath); + __archive_cmdline_free(acmd); + return (childInfo.dwProcessId); + +fail: + if (childStdout[0] != INVALID_HANDLE_VALUE) + CloseHandle(childStdout[0]); + if (childStdout[1] != INVALID_HANDLE_VALUE) + CloseHandle(childStdout[1]); + if (childStdin[0] != INVALID_HANDLE_VALUE) + CloseHandle(childStdin[0]); + if (childStdin[1] != INVALID_HANDLE_VALUE) + CloseHandle(childStdin[1]); + if (childStderr != INVALID_HANDLE_VALUE) + CloseHandle(childStderr); + archive_string_free(&cmdline); + archive_string_free(&fullpath); + __archive_cmdline_free(acmd); + return (-1); +} + +void +__archive_check_child(int in, int out) +{ + (void)in; /* UNUSED */ + (void)out; /* UNUSED */ + Sleep(100); +} + +#endif /* _WIN32 && !__CYGWIN__ */ diff --git a/dependencies/libarchive-3.4.2/libarchive/libarchive-formats.5 b/dependencies/libarchive-3.4.2/libarchive/libarchive-formats.5 new file mode 100644 index 0000000..62359dd --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/libarchive-formats.5 @@ -0,0 +1,465 @@ +.\" Copyright (c) 2003-2009 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd December 27, 2016 +.Dt LIBARCHIVE-FORMATS 5 +.Os +.Sh NAME +.Nm libarchive-formats +.Nd archive formats supported by the libarchive library +.Sh DESCRIPTION +The +.Xr libarchive 3 +library reads and writes a variety of streaming archive formats. +Generally speaking, all of these archive formats consist of a series of +.Dq entries . +Each entry stores a single file system object, such as a file, directory, +or symbolic link. +.Pp +The following provides a brief description of each format supported +by libarchive, with some information about recognized extensions or +limitations of the current library support. +Note that just because a format is supported by libarchive does not +imply that a program that uses libarchive will support that format. +Applications that use libarchive specify which formats they wish +to support, though many programs do use libarchive convenience +functions to enable all supported formats. +.Ss Tar Formats +The +.Xr libarchive 3 +library can read most tar archives. +It can write POSIX-standard +.Dq ustar +and +.Dq pax interchange +formats as well as v7 tar format and a subset of the legacy GNU tar format. +.Pp +All tar formats store each entry in one or more 512-byte records. +The first record is used for file metadata, including filename, +timestamp, and mode information, and the file data is stored in +subsequent records. +Later variants have extended this by either appropriating undefined +areas of the header record, extending the header to multiple records, +or by storing special entries that modify the interpretation of +subsequent entries. +.Bl -tag -width indent +.It Cm gnutar +The +.Xr libarchive 3 +library can read most GNU-format tar archives. +It currently supports the most popular GNU extensions, including +modern long filename and linkname support, as well as atime and ctime data. +The libarchive library does not support multi-volume +archives, nor the old GNU long filename format. +It can read GNU sparse file entries, including the new POSIX-based +formats. +.Pp +The +.Xr libarchive 3 +library can write GNU tar format, including long filename +and linkname support, as well as atime and ctime data. +.It Cm pax +The +.Xr libarchive 3 +library can read and write POSIX-compliant pax interchange format +archives. +Pax interchange format archives are an extension of the older ustar +format that adds a separate entry with additional attributes stored +as key/value pairs immediately before each regular entry. +The presence of these additional entries is the only difference between +pax interchange format and the older ustar format. +The extended attributes are of unlimited length and are stored +as UTF-8 Unicode strings. +Keywords defined in the standard are in all lowercase; vendors are allowed +to define custom keys by preceding them with the vendor name in all uppercase. +When writing pax archives, libarchive uses many of the SCHILY keys +defined by Joerg Schilling's +.Dq star +archiver and a few LIBARCHIVE keys. +The libarchive library can read most of the SCHILY keys +and most of the GNU keys introduced by GNU tar. +It silently ignores any keywords that it does not understand. +.Pp +The pax interchange format converts filenames to Unicode +and stores them using the UTF-8 encoding. +Prior to libarchive 3.0, libarchive erroneously assumed +that the system wide-character routines natively supported +Unicode. +This caused it to mis-handle non-ASCII filenames on systems +that did not satisfy this assumption. +.It Cm restricted pax +The libarchive library can also write pax archives in which it +attempts to suppress the extended attributes entry whenever +possible. +The result will be identical to a ustar archive unless the +extended attributes entry is required to store a long file +name, long linkname, extended ACL, file flags, or if any of the standard +ustar data (user name, group name, UID, GID, etc) cannot be fully +represented in the ustar header. +In all cases, the result can be dearchived by any program that +can read POSIX-compliant pax interchange format archives. +Programs that correctly read ustar format (see below) will also be +able to read this format; any extended attributes will be extracted as +separate files stored in +.Pa PaxHeader +directories. +.It Cm ustar +The libarchive library can both read and write this format. +This format has the following limitations: +.Bl -bullet -compact +.It +Device major and minor numbers are limited to 21 bits. +Nodes with larger numbers will not be added to the archive. +.It +Path names in the archive are limited to 255 bytes. +(Shorter if there is no / character in exactly the right place.) +.It +Symbolic links and hard links are stored in the archive with +the name of the referenced file. +This name is limited to 100 bytes. +.It +Extended attributes, file flags, and other extended +security information cannot be stored. +.It +Archive entries are limited to 8 gigabytes in size. +.El +Note that the pax interchange format has none of these restrictions. +The ustar format is old and widely supported. +It is recommended when compatibility is the primary concern. +.It Cm v7 +The libarchive library can read and write the legacy v7 tar format. +This format has the following limitations: +.Bl -bullet -compact +.It +Only regular files, directories, and symbolic links can be archived. +Block and character device nodes, FIFOs, and sockets cannot be archived. +.It +Path names in the archive are limited to 100 bytes. +.It +Symbolic links and hard links are stored in the archive with +the name of the referenced file. +This name is limited to 100 bytes. +.It +User and group information are stored as numeric IDs; there +is no provision for storing user or group names. +.It +Extended attributes, file flags, and other extended +security information cannot be stored. +.It +Archive entries are limited to 8 gigabytes in size. +.El +Generally, users should prefer the ustar format for portability +as the v7 tar format is both less useful and less portable. +.El +.Pp +The libarchive library also reads a variety of commonly-used extensions to +the basic tar format. +These extensions are recognized automatically whenever they appear. +.Bl -tag -width indent +.It Numeric extensions. +The POSIX standards require fixed-length numeric fields to be written with +some character position reserved for terminators. +Libarchive allows these fields to be written without terminator characters. +This extends the allowable range; in particular, ustar archives with this +extension can support entries up to 64 gigabytes in size. +Libarchive also recognizes base-256 values in most numeric fields. +This essentially removes all limitations on file size, modification time, +and device numbers. +.It Solaris extensions +Libarchive recognizes ACL and extended attribute records written +by Solaris tar. +.El +.Pp +The first tar program appeared in Seventh Edition Unix in 1979. +The first official standard for the tar file format was the +.Dq ustar +(Unix Standard Tar) format defined by POSIX in 1988. +POSIX.1-2001 extended the ustar format to create the +.Dq pax interchange +format. +.Ss Cpio Formats +The libarchive library can read a number of common cpio variants and can write +.Dq odc +and +.Dq newc +format archives. +A cpio archive stores each entry as a fixed-size header followed +by a variable-length filename and variable-length data. +Unlike the tar format, the cpio format does only minimal padding +of the header or file data. +There are several cpio variants, which differ primarily in +how they store the initial header: some store the values as +octal or hexadecimal numbers in ASCII, others as binary values of +varying byte order and length. +.Bl -tag -width indent +.It Cm binary +The libarchive library transparently reads both big-endian and little-endian +variants of the original binary cpio format. +This format used 32-bit binary values for file size and mtime, +and 16-bit binary values for the other fields. +.It Cm odc +The libarchive library can both read and write this +POSIX-standard format, which is officially known as the +.Dq cpio interchange format +or the +.Dq octet-oriented cpio archive format +and sometimes unofficially referred to as the +.Dq old character format . +This format stores the header contents as octal values in ASCII. +It is standard, portable, and immune from byte-order confusion. +File sizes and mtime are limited to 33 bits (8GB file size), +other fields are limited to 18 bits. +.It Cm SVR4/newc +The libarchive library can read both CRC and non-CRC variants of +this format. +The SVR4 format uses eight-digit hexadecimal values for +all header fields. +This limits file size to 4GB, and also limits the mtime and +other fields to 32 bits. +The SVR4 format can optionally include a CRC of the file +contents, although libarchive does not currently verify this CRC. +.El +.Pp +Cpio first appeared in PWB/UNIX 1.0, which was released within +AT&T in 1977. +PWB/UNIX 1.0 formed the basis of System III Unix, released outside +of AT&T in 1981. +This makes cpio older than tar, although cpio was not included +in Version 7 AT&T Unix. +As a result, the tar command became much better known in universities +and research groups that used Version 7. +The combination of the +.Nm find +and +.Nm cpio +utilities provided very precise control over file selection. +Unfortunately, the format has many limitations that make it unsuitable +for widespread use. +Only the POSIX format permits files over 4GB, and its 18-bit +limit for most other fields makes it unsuitable for modern systems. +In addition, cpio formats only store numeric UID/GID values (not +usernames and group names), which can make it very difficult to correctly +transfer archives across systems with dissimilar user numbering. +.Ss Shar Formats +A +.Dq shell archive +is a shell script that, when executed on a POSIX-compliant +system, will recreate a collection of file system objects. +The libarchive library can write two different kinds of shar archives: +.Bl -tag -width indent +.It Cm shar +The traditional shar format uses a limited set of POSIX +commands, including +.Xr echo 1 , +.Xr mkdir 1 , +and +.Xr sed 1 . +It is suitable for portably archiving small collections of plain text files. +However, it is not generally well-suited for large archives +(many implementations of +.Xr sh 1 +have limits on the size of a script) nor should it be used with non-text files. +.It Cm shardump +This format is similar to shar but encodes files using +.Xr uuencode 1 +so that the result will be a plain text file regardless of the file contents. +It also includes additional shell commands that attempt to reproduce as +many file attributes as possible, including owner, mode, and flags. +The additional commands used to restore file attributes make +shardump archives less portable than plain shar archives. +.El +.Ss ISO9660 format +Libarchive can read and extract from files containing ISO9660-compliant +CDROM images. +In many cases, this can remove the need to burn a physical CDROM +just in order to read the files contained in an ISO9660 image. +It also avoids security and complexity issues that come with +virtual mounts and loopback devices. +Libarchive supports the most common Rockridge extensions and has partial +support for Joliet extensions. +If both extensions are present, the Joliet extensions will be +used and the Rockridge extensions will be ignored. +In particular, this can create problems with hardlinks and symlinks, +which are supported by Rockridge but not by Joliet. +.Pp +Libarchive reads ISO9660 images using a streaming strategy. +This allows it to read compressed images directly +(decompressing on the fly) and allows it to read images +directly from network sockets, pipes, and other non-seekable +data sources. +This strategy works well for optimized ISO9660 images created +by many popular programs. +Such programs collect all directory information at the beginning +of the ISO9660 image so it can be read from a physical disk +with a minimum of seeking. +However, not all ISO9660 images can be read in this fashion. +.Pp +Libarchive can also write ISO9660 images. +Such images are fully optimized with the directory information +preceding all file data. +This is done by storing all file data to a temporary file +while collecting directory information in memory. +When the image is finished, libarchive writes out the +directory structure followed by the file data. +The location used for the temporary file can be changed +by the usual environment variables. +.Ss Zip format +Libarchive can read and write zip format archives that have +uncompressed entries and entries compressed with the +.Dq deflate +algorithm. +Other zip compression algorithms are not supported. +It can extract jar archives, archives that use Zip64 extensions and +self-extracting zip archives. +Libarchive can use either of two different strategies for +reading Zip archives: +a streaming strategy which is fast and can handle extremely +large archives, and a seeking strategy which can correctly +process self-extracting Zip archives and archives with +deleted members or other in-place modifications. +.Pp +The streaming reader processes Zip archives as they are read. +It can read archives of arbitrary size from tape or +network sockets, and can decode Zip archives that have +been separately compressed or encoded. +However, self-extracting Zip archives and archives with +certain types of modifications cannot be correctly +handled. +Such archives require that the reader first process the +Central Directory, which is ordinarily located +at the end of a Zip archive and is thus inaccessible +to the streaming reader. +If the program using libarchive has enabled seek support, then +libarchive will use this to processes the central directory first. +.Pp +In particular, the seeking reader must be used to +correctly handle self-extracting archives. +Such archives consist of a program followed by a regular +Zip archive. +The streaming reader cannot parse the initial program +portion, but the seeking reader starts by reading the +Central Directory from the end of the archive. +Similarly, Zip archives that have been modified in-place +can have deleted entries or other garbage data that +can only be accurately detected by first reading the +Central Directory. +.Ss Archive (library) file format +The Unix archive format (commonly created by the +.Xr ar 1 +archiver) is a general-purpose format which is +used almost exclusively for object files to be +read by the link editor +.Xr ld 1 . +The ar format has never been standardised. +There are two common variants: +the GNU format derived from SVR4, +and the BSD format, which first appeared in 4.4BSD. +The two differ primarily in their handling of filenames +longer than 15 characters: +the GNU/SVR4 variant writes a filename table at the beginning of the archive; +the BSD format stores each long filename in an extension +area adjacent to the entry. +Libarchive can read both extensions, +including archives that may include both types of long filenames. +Programs using libarchive can write GNU/SVR4 format +if they provide an entry called +.Pa // +containing a filename table to be written into the archive +before any of the entries. +Any entries whose names are not in the filename table +will be written using BSD-style long filenames. +This can cause problems for programs such as +GNU ld that do not support the BSD-style long filenames. +.Ss mtree +Libarchive can read and write files in +.Xr mtree 5 +format. +This format is not a true archive format, but rather a textual description +of a file hierarchy in which each line specifies the name of a file and +provides specific metadata about that file. +Libarchive can read all of the keywords supported by both +the NetBSD and FreeBSD versions of +.Xr mtree 8 , +although many of the keywords cannot currently be stored in an +.Tn archive_entry +object. +When writing, libarchive supports use of the +.Xr archive_write_set_options 3 +interface to specify which keywords should be included in the +output. +If libarchive was compiled with access to suitable +cryptographic libraries (such as the OpenSSL libraries), +it can compute hash entries such as +.Cm sha512 +or +.Cm md5 +from file data being written to the mtree writer. +.Pp +When reading an mtree file, libarchive will locate the corresponding +files on disk using the +.Cm contents +keyword if present or the regular filename. +If it can locate and open the file on disk, it will use that +to fill in any metadata that is missing from the mtree file +and will read the file contents and return those to the program +using libarchive. +If it cannot locate and open the file on disk, libarchive +will return an error for any attempt to read the entry +body. +.Ss 7-Zip +Libarchive can read and write 7-Zip format archives. +TODO: Need more information +.Ss CAB +Libarchive can read Microsoft Cabinet ( +.Dq CAB ) +format archives. +TODO: Need more information. +.Ss LHA +TODO: Information about libarchive's LHA support +.Ss RAR +Libarchive has limited support for reading RAR format archives. +Currently, libarchive can read RARv3 format archives +which have been either created uncompressed, or compressed using +any of the compression methods supported by the RARv3 format. +Libarchive can also read self-extracting RAR archives. +.Ss Warc +Libarchive can read and write +.Dq web archives . +TODO: Need more information +.Ss XAR +Libarchive can read and write the XAR format used by many Apple tools. +TODO: Need more information +.Sh SEE ALSO +.Xr ar 1 , +.Xr cpio 1 , +.Xr mkisofs 1 , +.Xr shar 1 , +.Xr tar 1 , +.Xr zip 1 , +.Xr zlib 3 , +.Xr cpio 5 , +.Xr mtree 5 , +.Xr tar 5 diff --git a/dependencies/libarchive-3.4.2/libarchive/libarchive.3 b/dependencies/libarchive-3.4.2/libarchive/libarchive.3 new file mode 100644 index 0000000..c6894d2 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/libarchive.3 @@ -0,0 +1,289 @@ +.\" Copyright (c) 2003-2007 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd March 18, 2012 +.Dt LIBARCHIVE 3 +.Os +.Sh NAME +.Nm libarchive +.Nd functions for reading and writing streaming archives +.Sh OVERVIEW +The +.Nm +library provides a flexible interface for reading and writing +archives in various formats such as tar and cpio. +.Nm +also supports reading and writing archives compressed using +various compression filters such as gzip and bzip2. +The library is inherently stream-oriented; readers serially iterate through +the archive, writers serially add things to the archive. +In particular, note that there is currently no built-in support for +random access nor for in-place modification. +.Pp +When reading an archive, the library automatically detects the +format and the compression. +The library currently has read support for: +.Bl -bullet -compact +.It +old-style tar archives, +.It +most variants of the POSIX +.Dq ustar +format, +.It +the POSIX +.Dq pax interchange +format, +.It +GNU-format tar archives, +.It +most common cpio archive formats, +.It +ISO9660 CD images (including RockRidge and Joliet extensions), +.It +Zip archives, +.It +ar archives (including GNU/SysV and BSD extensions), +.It +Microsoft CAB archives, +.It +LHA archives, +.It +mtree file tree descriptions, +.It +RAR archives, +.It +XAR archives. +.El +The library automatically detects archives compressed with +.Xr gzip 1 , +.Xr bzip2 1 , +.Xr xz 1 , +.Xr lzip 1 , +or +.Xr compress 1 +and decompresses them transparently. +It can similarly detect and decode archives processed with +.Xr uuencode 1 +or which have an +.Xr rpm 1 +header. +.Pp +When writing an archive, you can specify the compression +to be used and the format to use. +The library can write +.Bl -bullet -compact +.It +POSIX-standard +.Dq ustar +archives, +.It +POSIX +.Dq pax interchange format +archives, +.It +POSIX octet-oriented cpio archives, +.It +Zip archive, +.It +two different variants of shar archives, +.It +ISO9660 CD images, +.It +7-Zip archives, +.It +ar archives, +.It +mtree file tree descriptions, +.It +XAR archives. +.El +Pax interchange format is an extension of the tar archive format that +eliminates essentially all of the limitations of historic tar formats +in a standard fashion that is supported +by POSIX-compliant +.Xr pax 1 +implementations on many systems as well as several newer implementations of +.Xr tar 1 . +Note that the default write format will suppress the pax extended +attributes for most entries; explicitly requesting pax format will +enable those attributes for all entries. +.Pp +The read and write APIs are accessed through the +.Fn archive_read_XXX +functions and the +.Fn archive_write_XXX +functions, respectively, and either can be used independently +of the other. +.Pp +The rest of this manual page provides an overview of the library +operation. +More detailed information can be found in the individual manual +pages for each API or utility function. +.\" +.Sh READING AN ARCHIVE +See +.Xr archive_read 3 . +.\" +.Sh WRITING AN ARCHIVE +See +.Xr archive_write 3 . +.\" +.Sh WRITING ENTRIES TO DISK +The +.Xr archive_write_disk 3 +API allows you to write +.Xr archive_entry 3 +objects to disk using the same API used by +.Xr archive_write 3 . +The +.Xr archive_write_disk 3 +API is used internally by +.Fn archive_read_extract ; +using it directly can provide greater control over how entries +get written to disk. +This API also makes it possible to share code between +archive-to-archive copy and archive-to-disk extraction +operations. +.Sh READING ENTRIES FROM DISK +The +.Xr archive_read_disk 3 +supports for populating +.Xr archive_entry 3 +objects from information in the filesystem. +This includes the information accessible from the +.Xr stat 2 +system call as well as ACLs, extended attributes, +and other metadata. +The +.Xr archive_read_disk 3 +API also supports iterating over directory trees, +which allows directories of files to be read using +an API compatible with +the +.Xr archive_read 3 +API. +.Sh DESCRIPTION +Detailed descriptions of each function are provided by the +corresponding manual pages. +.Pp +All of the functions utilize an opaque +.Tn struct archive +datatype that provides access to the archive contents. +.Pp +The +.Tn struct archive_entry +structure contains a complete description of a single archive +entry. +It uses an opaque interface that is fully documented in +.Xr archive_entry 3 . +.Pp +Users familiar with historic formats should be aware that the newer +variants have eliminated most restrictions on the length of textual fields. +Clients should not assume that filenames, link names, user names, or +group names are limited in length. +In particular, pax interchange format can easily accommodate pathnames +in arbitrary character sets that exceed +.Va PATH_MAX . +.Sh RETURN VALUES +Most functions return +.Cm ARCHIVE_OK +(zero) on success, non-zero on error. +The return value indicates the general severity of the error, ranging +from +.Cm ARCHIVE_WARN , +which indicates a minor problem that should probably be reported +to the user, to +.Cm ARCHIVE_FATAL , +which indicates a serious problem that will prevent any further +operations on this archive. +On error, the +.Fn archive_errno +function can be used to retrieve a numeric error code (see +.Xr errno 2 ) . +The +.Fn archive_error_string +returns a textual error message suitable for display. +.Pp +.Fn archive_read_new +and +.Fn archive_write_new +return pointers to an allocated and initialized +.Tn struct archive +object. +.Pp +.Fn archive_read_data +and +.Fn archive_write_data +return a count of the number of bytes actually read or written. +A value of zero indicates the end of the data for this entry. +A negative value indicates an error, in which case the +.Fn archive_errno +and +.Fn archive_error_string +functions can be used to obtain more information. +.Sh ENVIRONMENT +There are character set conversions within the +.Xr archive_entry 3 +functions that are impacted by the currently-selected locale. +.Sh SEE ALSO +.Xr tar 1 , +.Xr archive_entry 3 , +.Xr archive_read 3 , +.Xr archive_util 3 , +.Xr archive_write 3 , +.Xr tar 5 +.Sh HISTORY +The +.Nm libarchive +library first appeared in +.Fx 5.3 . +.Sh AUTHORS +.An -nosplit +The +.Nm libarchive +library was originally written by +.An Tim Kientzle Aq kientzle@acm.org . +.Sh BUGS +Some archive formats support information that is not supported by +.Tn struct archive_entry . +Such information cannot be fully archived or restored using this library. +This includes, for example, comments, character sets, +or the arbitrary key/value pairs that can appear in +pax interchange format archives. +.Pp +Conversely, of course, not all of the information that can be +stored in an +.Tn struct archive_entry +is supported by all formats. +For example, cpio formats do not support nanosecond timestamps; +old tar formats do not support large device numbers. +.Pp +The ISO9660 reader cannot yet read all ISO9660 images; +it should learn how to seek. +.Pp +The AR writer requires the client program to use +two passes, unlike all other libarchive writers. diff --git a/dependencies/libarchive-3.4.2/libarchive/libarchive_changes.3 b/dependencies/libarchive-3.4.2/libarchive/libarchive_changes.3 new file mode 100644 index 0000000..6bf8db0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/libarchive_changes.3 @@ -0,0 +1,341 @@ +.\" Copyright (c) 2011 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd December 23, 2011 +.Dt LIBARCHIVE_CHANGES 3 +.Os +.Sh NAME +.Nm libarchive_changes +.Nd changes in libarchive interface +.\" +.Sh CHANGES IN LIBARCHIVE 3 +This page describes user-visible changes in libarchive3, and lists +public functions and other symbols changed, deprecated or removed +in libarchive3, along with their replacements if any. +.\" +.Ss Multiple Filters +.\" +Libarchive2 permitted a single (input or output) filter active +on an archive. +Libarchive3 extends this into a variable-length stack. +Where +.Fn archive_write_set_compression_XXX +would replace any existing filter, +.Fn archive_write_add_filter_XXX +extends the write pipeline with another filter. +.\" +.Ss Character Set Handling +.\" +Libarchive2 assumed that the local platform uses +.Tn Unicode +as the native +.Tn wchar_t +encoding, which is true on +.Tn Windows , +modern +.Tn Linux , +and a few other systems, but is certainly not universal. +As a result, pax format archives were written incorrectly on some +systems, since pax format requires +.Tn UTF-8 +and libarchive 2 incorrectly +assumed that +.Tn wchar_t +strings can be easily converted to +.Tn UTF-8 . +.Pp +Libarchive3 uses the standard iconv library to convert between character +sets and is introducing the notion of a +.Dq default character set for the archive . +To support this, +.Tn archive_entry +objects can now be bound to a particular archive when they are created. +The automatic character set conversions performed by +.Tn archive_entry +objects when reading and writing filenames, usernames, and other strings +will now use an appropriate default character set: +.Pp +If the +.Tn archive_entry +object is bound to an archive, it will use the +default character set for that archive. +.Pp +The platform default character encoding (as returned by +.Fn nl_langinfo CHARSET ) +will be used if nothing else is specified. +.Pp +Libarchive3 also introduces charset options to many of the archive +readers and writers to control the character set that will be used for +filenames written in those archives. +When possible, this will be set automatically based on information in +the archive itself. +Combining this with the notion of a default character set for the +archive should allow you to configure libarchive to read archives from +other platforms and have the filenames and other information +transparently converted to the character encoding suitable for your +application. +.\" +.Ss Prototype Changes +.\" +These changes break binary compatibility; libarchive3 has a new shared +library version to reflect these changes. +The library now uses portable wide types such as +.Tn int64_t +instead of less-portable types such as +.Tn off_t , +.Tn gid_t , +.Tn uid_t , +and +.Tn ino_t . +.Pp +There are a few cases where these changes will affect your source code: +.Bl -bullet -width ind +.It +In some cases, libarchive's wider types will introduce the possibility +of truncation: for example, on a system with a 16-bit +.Tn uid_t , you risk having uid +.Li 65536 +be truncated to uid +.Li 0 , +which can cause serious security problems. +.It +Typedef function pointer types will be incompatible. +For example, if you define custom skip callbacks, you may have to use +code similar to the following if you want to support building against +libarchive2 and libarchive3: +.Bd -literal +#if ARCHIVE_VERSION_NUMBER < 3000000 +typedef off_t myoff_t; +#else +typedef int64_t myoff_t; +#endif + +myoff_t +my_skip_function(struct archive *a, void *v, myoff_t o) +{ + ... implementation ... +} +.Ed +.El +.Pp +Affected functions: +.Pp +.Bl -bullet -compact +.It +.Xo +.Fn archive_entry_gid , +.Fn archive_entry_set_gid +.Xc +.It +.Xo +.Fn archive_entry_uid , +.Fn archive_entry_set_uid +.Xc +.It +.Xo +.Fn archive_entry_ino , +.Fn archive_entry_set_ino +.Xc +.It +.Xo +.Fn archive_read_data_block , +.Fn archive_write_data_block +.Xc +.It +.Xo +.Fn archive_read_disk_gname , +.Fn archive_read_disk_uname +.Xc +.It +.Xo +.Fn archive_read_disk_set_gname_lookup , +.Fn archive_read_disk_set_group_lookup , +.Fn archive_read_disk_set_uname_lookup , +.Fn archive_read_disk_set_user_lookup +.Xc +.It +.Fn archive_skip_callback +.It +.Xo +.Fn archive_read_extract_set_skip_file , +.Fn archive_write_disk_set_skip_file , +.Fn archive_write_set_skip_file +.Xc +.It +.Xo +.Fn archive_write_disk_set_group_lookup , +.Fn archive_write_disk_set_user_lookup +.Xc +.El +.Pp +Where these functions or their arguments took or returned +.Tn gid_t , +.Tn ino_t , +.Tn off_t , +or +.Tn uid_t +they now take or return +.Tn int64_t +or equivalent. +.\" +.Ss Deprecated Symbols +.\" +Symbols deprecated in libarchive3 will be removed in libarchive4. +These symbols, along with their replacements if any, are listed below: +.\" +.Bl -tag -width ind +.It Fn archive_position_compressed , Fn archive_position_uncompressed +.Fn archive_filter_bytes +.It Fn archive_compression +.Fn archive_filter_code +.It Fn archive_compression_name +.Fn archive_filter_name +.It Fn archive_read_finish , Fn archive_write_finish +.Fn archive_read_free , +.Fn archive_write_free +.It Fn archive_read_open_file , Fn archive_write_open_file +.Fn archive_read_open_filename , +.Fn archive_write_open_filename +.It Fn archive_read_support_compression_all +.\" archive_read_support_compression_* -> archive_read_support_filter_* +.Fn archive_read_support_filter_all +.It Fn archive_read_support_compression_bzip2 +.Fn archive_read_support_filter_bzip2 +.It Fn archive_read_support_compression_compress +.Fn archive_read_support_filter_compress +.It Fn archive_read_support_compression_gzip +.Fn archive_read_support_filter_gzip +.It Fn archive_read_support_compression_lzip +.Fn archive_read_support_filter_lzip +.It Fn archive_read_support_compression_lzma +.Fn archive_read_support_filter_lzma +.It Fn archive_read_support_compression_none +.Fn archive_read_support_filter_none +.It Fn archive_read_support_compression_program +.Fn archive_read_support_filter_program +.It Fn archive_read_support_compression_program_signature +.Fn archive_read_support_filter_program_signature +.It Fn archive_read_support_compression_rpm +.Fn archive_read_support_filter_rpm +.It Fn archive_read_support_compression_uu +.Fn archive_read_support_filter_uu +.It Fn archive_read_support_compression_xz +.Fn archive_read_support_filter_xz +.\" archive_write_set_compression_* -> archive_write_add_filter_* +.It Fn archive_write_set_compression_bzip2 +.Fn archive_write_add_filter_bzip2 +.It Fn archive_write_set_compression_compress +.Fn archive_write_add_filter_compress +.It Fn archive_write_set_compression_gzip +.Fn archive_write_add_filter_gzip +.It Fn archive_write_set_compression_lzip +.Fn archive_write_add_filter_lzip +.It Fn archive_write_set_compression_lzma +.Fn archive_write_add_filter_lzma +.It Fn archive_write_set_compression_none +.Fn archive_write_add_filter_none +.It Fn archive_write_set_compression_program +.Fn archive_write_add_filter_program +.It Fn archive_write_set_compression_filter +.Fn archive_write_add_filter_filter +.El +.\" +.Ss Removed Symbols +.\" +These symbols, listed below along with their replacements if any, +were deprecated in libarchive2, and are not part of libarchive3. +.\" +.Bl -tag -width ind +.It Fn archive_api_feature +.Fn archive_version_number +.It Fn archive_api_version +.Fn archive_version_number +.It Fn archive_version +.Fn archive_version_string +.It Fn archive_version_stamp +.Fn archive_version_number +.It Fn archive_read_set_filter_options +.Fn archive_read_set_options +or +.Fn archive_read_set_filter_option +.It Fn archive_read_set_format_options +.Fn archive_read_set_options +or +.Fn archive_read_set_format_option +.It Fn archive_write_set_filter_options +.Fn archive_write_set_options +or +.Fn archive_write_set_filter_option +.It Fn archive_write_set_format_options +.Fn archive_write_set_options +or +.Fn archive_write_set_format_option +.It Dv ARCHIVE_API_FEATURE +.Dv ARCHIVE_VERSION_NUMBER +.It Dv ARCHIVE_API_VERSION +.Dv ARCHIVE_VERSION_NUMBER +.It Dv ARCHIVE_VERSION_STAMP +.Dv ARCHIVE_VERSION_NUMBER +.It Dv ARCHIVE_LIBRARY_VERSION +.Dv ARCHIVE_VERSION_STRING +.\" +.It Dv ARCHIVE_COMPRESSION_NONE +.Dv ARCHIVE_FILTER_NONE +.It Dv ARCHIVE_COMPRESSION_GZIP +.Dv ARCHIVE_FILTER_GZIP +.It Dv ARCHIVE_COMPRESSION_BZIP2 +.Dv ARCHIVE_FILTER_BZIP2 +.It Dv ARCHIVE_COMPRESSION_COMPRESS +.Dv ARCHIVE_FILTER_COMPRESS +.It Dv ARCHIVE_COMPRESSION_PROGRAM +.Dv ARCHIVE_FILTER_PROGRAM +.It Dv ARCHIVE_COMPRESSION_LZMA +.Dv ARCHIVE_FILTER_LZMA +.It Dv ARCHIVE_COMPRESSION_XZ +.Dv ARCHIVE_FILTER_XZ +.It Dv ARCHIVE_COMPRESSION_UU +.Dv ARCHIVE_FILTER_UU +.It Dv ARCHIVE_COMPRESSION_RPM +.Dv ARCHIVE_FILTER_RPM +.It Dv ARCHIVE_COMPRESSION_LZIP +.Dv ARCHIVE_FILTER_LZIP +.\" +.It Dv ARCHIVE_BYTES_PER_RECORD +.Li 512 +.It Dv ARCHIVE_DEFAULT_BYTES_PER_BLOCK +.Li 10240 +.El +.Sh SEE ALSO +.Xr archive_read 3 , +.Xr archive_read_filter 3 , +.Xr archive_read_format 3 , +.Xr archive_read_set_options 3 , +.Xr archive_util 3 , +.Xr archive_write 3 , +.Xr archive_write_filter 3 , +.Xr archive_write_format 3 , +.Xr archive_write_set_options 3 , +.Xr libarchive 3 diff --git a/dependencies/libarchive-3.4.2/libarchive/libarchive_internals.3 b/dependencies/libarchive-3.4.2/libarchive/libarchive_internals.3 new file mode 100644 index 0000000..d672f3e --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/libarchive_internals.3 @@ -0,0 +1,365 @@ +.\" Copyright (c) 2003-2007 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd January 26, 2011 +.Dt LIBARCHIVE_INTERNALS 3 +.Os +.Sh NAME +.Nm libarchive_internals +.Nd description of libarchive internal interfaces +.Sh OVERVIEW +The +.Nm libarchive +library provides a flexible interface for reading and writing +streaming archive files such as tar and cpio. +Internally, it follows a modular layered design that should +make it easy to add new archive and compression formats. +.Sh GENERAL ARCHITECTURE +Externally, libarchive exposes most operations through an +opaque, object-style interface. +The +.Xr archive_entry 3 +objects store information about a single filesystem object. +The rest of the library provides facilities to write +.Xr archive_entry 3 +objects to archive files, +read them from archive files, +and write them to disk. +(There are plans to add a facility to read +.Xr archive_entry 3 +objects from disk as well.) +.Pp +The read and write APIs each have four layers: a public API +layer, a format layer that understands the archive file format, +a compression layer, and an I/O layer. +The I/O layer is completely exposed to clients who can replace +it entirely with their own functions. +.Pp +In order to provide as much consistency as possible for clients, +some public functions are virtualized. +Eventually, it should be possible for clients to open +an archive or disk writer, and then use a single set of +code to select and write entries, regardless of the target. +.Sh READ ARCHITECTURE +From the outside, clients use the +.Xr archive_read 3 +API to manipulate an +.Nm archive +object to read entries and bodies from an archive stream. +Internally, the +.Nm archive +object is cast to an +.Nm archive_read +object, which holds all read-specific data. +The API has four layers: +The lowest layer is the I/O layer. +This layer can be overridden by clients, but most clients use +the packaged I/O callbacks provided, for example, by +.Xr archive_read_open_memory 3 , +and +.Xr archive_read_open_fd 3 . +The compression layer calls the I/O layer to +read bytes and decompresses them for the format layer. +The format layer unpacks a stream of uncompressed bytes and +creates +.Nm archive_entry +objects from the incoming data. +The API layer tracks overall state +(for example, it prevents clients from reading data before reading a header) +and invokes the format and compression layer operations +through registered function pointers. +In particular, the API layer drives the format-detection process: +When opening the archive, it reads an initial block of data +and offers it to each registered compression handler. +The one with the highest bid is initialized with the first block. +Similarly, the format handlers are polled to see which handler +is the best for each archive. +(Prior to 2.4.0, the format bidders were invoked for each +entry, but this design hindered error recovery.) +.Ss I/O Layer and Client Callbacks +The read API goes to some lengths to be nice to clients. +As a result, there are few restrictions on the behavior of +the client callbacks. +.Pp +The client read callback is expected to provide a block +of data on each call. +A zero-length return does indicate end of file, but otherwise +blocks may be as small as one byte or as large as the entire file. +In particular, blocks may be of different sizes. +.Pp +The client skip callback returns the number of bytes actually +skipped, which may be much smaller than the skip requested. +The only requirement is that the skip not be larger. +In particular, clients are allowed to return zero for any +skip that they don't want to handle. +The skip callback must never be invoked with a negative value. +.Pp +Keep in mind that not all clients are reading from disk: +clients reading from networks may provide different-sized +blocks on every request and cannot skip at all; +advanced clients may use +.Xr mmap 2 +to read the entire file into memory at once and return the +entire file to libarchive as a single block; +other clients may begin asynchronous I/O operations for the +next block on each request. +.Ss Decompresssion Layer +The decompression layer not only handles decompression, +it also buffers data so that the format handlers see a +much nicer I/O model. +The decompression API is a two stage peek/consume model. +A read_ahead request specifies a minimum read amount; +the decompression layer must provide a pointer to at least +that much data. +If more data is immediately available, it should return more: +the format layer handles bulk data reads by asking for a minimum +of one byte and then copying as much data as is available. +.Pp +A subsequent call to the +.Fn consume +function advances the read pointer. +Note that data returned from a +.Fn read_ahead +call is guaranteed to remain in place until +the next call to +.Fn read_ahead . +Intervening calls to +.Fn consume +should not cause the data to move. +.Pp +Skip requests must always be handled exactly. +Decompression handlers that cannot seek forward should +not register a skip handler; +the API layer fills in a generic skip handler that reads and discards data. +.Pp +A decompression handler has a specific lifecycle: +.Bl -tag -compact -width indent +.It Registration/Configuration +When the client invokes the public support function, +the decompression handler invokes the internal +.Fn __archive_read_register_compression +function to provide bid and initialization functions. +This function returns +.Cm NULL +on error or else a pointer to a +.Cm struct decompressor_t . +This structure contains a +.Va void * config +slot that can be used for storing any customization information. +.It Bid +The bid function is invoked with a pointer and size of a block of data. +The decompressor can access its config data +through the +.Va decompressor +element of the +.Cm archive_read +object. +The bid function is otherwise stateless. +In particular, it must not perform any I/O operations. +.Pp +The value returned by the bid function indicates its suitability +for handling this data stream. +A bid of zero will ensure that this decompressor is never invoked. +Return zero if magic number checks fail. +Otherwise, your initial implementation should return the number of bits +actually checked. +For example, if you verify two full bytes and three bits of another +byte, bid 19. +Note that the initial block may be very short; +be careful to only inspect the data you are given. +(The current decompressors require two bytes for correct bidding.) +.It Initialize +The winning bidder will have its init function called. +This function should initialize the remaining slots of the +.Va struct decompressor_t +object pointed to by the +.Va decompressor +element of the +.Va archive_read +object. +In particular, it should allocate any working data it needs +in the +.Va data +slot of that structure. +The init function is called with the block of data that +was used for tasting. +At this point, the decompressor is responsible for all I/O +requests to the client callbacks. +The decompressor is free to read more data as and when +necessary. +.It Satisfy I/O requests +The format handler will invoke the +.Va read_ahead , +.Va consume , +and +.Va skip +functions as needed. +.It Finish +The finish method is called only once when the archive is closed. +It should release anything stored in the +.Va data +and +.Va config +slots of the +.Va decompressor +object. +It should not invoke the client close callback. +.El +.Ss Format Layer +The read formats have a similar lifecycle to the decompression handlers: +.Bl -tag -compact -width indent +.It Registration +Allocate your private data and initialize your pointers. +.It Bid +Formats bid by invoking the +.Fn read_ahead +decompression method but not calling the +.Fn consume +method. +This allows each bidder to look ahead in the input stream. +Bidders should not look further ahead than necessary, as long +look aheads put pressure on the decompression layer to buffer +lots of data. +Most formats only require a few hundred bytes of look ahead; +look aheads of a few kilobytes are reasonable. +(The ISO9660 reader sometimes looks ahead by 48k, which +should be considered an upper limit.) +.It Read header +The header read is usually the most complex part of any format. +There are a few strategies worth mentioning: +For formats such as tar or cpio, reading and parsing the header is +straightforward since headers alternate with data. +For formats that store all header data at the beginning of the file, +the first header read request may have to read all headers into +memory and store that data, sorted by the location of the file +data. +Subsequent header read requests will skip forward to the +beginning of the file data and return the corresponding header. +.It Read Data +The read data interface supports sparse files; this requires that +each call return a block of data specifying the file offset and +size. +This may require you to carefully track the location so that you +can return accurate file offsets for each read. +Remember that the decompressor will return as much data as it has. +Generally, you will want to request one byte, +examine the return value to see how much data is available, and +possibly trim that to the amount you can use. +You should invoke consume for each block just before you return it. +.It Skip All Data +The skip data call should skip over all file data and trailing padding. +This is called automatically by the API layer just before each +header read. +It is also called in response to the client calling the public +.Fn data_skip +function. +.It Cleanup +On cleanup, the format should release all of its allocated memory. +.El +.Ss API Layer +XXX to do XXX +.Sh WRITE ARCHITECTURE +The write API has a similar set of four layers: +an API layer, a format layer, a compression layer, and an I/O layer. +The registration here is much simpler because only +one format and one compression can be registered at a time. +.Ss I/O Layer and Client Callbacks +XXX To be written XXX +.Ss Compression Layer +XXX To be written XXX +.Ss Format Layer +XXX To be written XXX +.Ss API Layer +XXX To be written XXX +.Sh WRITE_DISK ARCHITECTURE +The write_disk API is intended to look just like the write API +to clients. +Since it does not handle multiple formats or compression, it +is not layered internally. +.Sh GENERAL SERVICES +The +.Nm archive_read , +.Nm archive_write , +and +.Nm archive_write_disk +objects all contain an initial +.Nm archive +object which provides common support for a set of standard services. +(Recall that ANSI/ISO C90 guarantees that you can cast freely between +a pointer to a structure and a pointer to the first element of that +structure.) +The +.Nm archive +object has a magic value that indicates which API this object +is associated with, +slots for storing error information, +and function pointers for virtualized API functions. +.Sh MISCELLANEOUS NOTES +Connecting existing archiving libraries into libarchive is generally +quite difficult. +In particular, many existing libraries strongly assume that you +are reading from a file; they seek forwards and backwards as necessary +to locate various pieces of information. +In contrast, libarchive never seeks backwards in its input, which +sometimes requires very different approaches. +.Pp +For example, libarchive's ISO9660 support operates very differently +from most ISO9660 readers. +The libarchive support utilizes a work-queue design that +keeps a list of known entries sorted by their location in the input. +Whenever libarchive's ISO9660 implementation is asked for the next +header, checks this list to find the next item on the disk. +Directories are parsed when they are encountered and new +items are added to the list. +This design relies heavily on the ISO9660 image being optimized so that +directories always occur earlier on the disk than the files they +describe. +.Pp +Depending on the specific format, such approaches may not be possible. +The ZIP format specification, for example, allows archivers to store +key information only at the end of the file. +In theory, it is possible to create ZIP archives that cannot +be read without seeking. +Fortunately, such archives are very rare, and libarchive can read +most ZIP archives, though it cannot always extract as much information +as a dedicated ZIP program. +.Sh SEE ALSO +.Xr archive_entry 3 , +.Xr archive_read 3 , +.Xr archive_write 3 , +.Xr archive_write_disk 3 , +.Xr libarchive 3 +.Sh HISTORY +The +.Nm libarchive +library first appeared in +.Fx 5.3 . +.Sh AUTHORS +.An -nosplit +The +.Nm libarchive +library was written by +.An Tim Kientzle Aq kientzle@acm.org . diff --git a/dependencies/libarchive-3.4.2/libarchive/mtree.5 b/dependencies/libarchive-3.4.2/libarchive/mtree.5 new file mode 100644 index 0000000..8147796 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/mtree.5 @@ -0,0 +1,324 @@ +.\" Copyright (c) 1989, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" From: @(#)mtree.8 8.2 (Berkeley) 12/11/93 +.\" $FreeBSD$ +.\" +.Dd September 4, 2013 +.Dt MTREE 5 +.Os +.Sh NAME +.Nm mtree +.Nd format of mtree dir hierarchy files +.Sh DESCRIPTION +The +.Nm +format is a textual format that describes a collection of filesystem objects. +Such files are typically used to create or verify directory hierarchies. +.Ss General Format +An +.Nm +file consists of a series of lines, each providing information +about a single filesystem object. +Leading whitespace is always ignored. +.Pp +When encoding file or pathnames, any backslash character or +character outside of the 95 printable ASCII characters must be +encoded as a backslash followed by three +octal digits. +When reading mtree files, any appearance of a backslash +followed by three octal digits should be converted into the +corresponding character. +.Pp +Each line is interpreted independently as one of the following types: +.Bl -tag -width Cm +.It Blank +Blank lines are ignored. +.It Comment +Lines beginning with +.Cm # +are ignored. +.It Special +Lines beginning with +.Cm / +are special commands that influence +the interpretation of later lines. +.It Relative +If the first whitespace-delimited word has no +.Cm / +characters, +it is the name of a file in the current directory. +Any relative entry that describes a directory changes the +current directory. +.It dot-dot +As a special case, a relative entry with the filename +.Pa .. +changes the current directory to the parent directory. +Options on dot-dot entries are always ignored. +.It Full +If the first whitespace-delimited word has a +.Cm / +character after +the first character, it is the pathname of a file relative to the +starting directory. +There can be multiple full entries describing the same file. +.El +.Pp +Some tools that process +.Nm +files may require that multiple lines describing the same file +occur consecutively. +It is not permitted for the same file to be mentioned using +both a relative and a full file specification. +.Ss Special commands +Two special commands are currently defined: +.Bl -tag -width Cm +.It Cm /set +This command defines default values for one or more keywords. +It is followed on the same line by one or more whitespace-separated +keyword definitions. +These definitions apply to all following files that do not specify +a value for that keyword. +.It Cm /unset +This command removes any default value set by a previous +.Cm /set +command. +It is followed on the same line by one or more keywords +separated by whitespace. +.El +.Ss Keywords +After the filename, a full or relative entry consists of zero +or more whitespace-separated keyword definitions. +Each such definition consists of a key from the following +list immediately followed by an '=' sign +and a value. +Software programs reading mtree files should warn about +unrecognized keywords. +.Pp +Currently supported keywords are as follows: +.Bl -tag -width Cm +.It Cm cksum +The checksum of the file using the default algorithm specified by +the +.Xr cksum 1 +utility. +.It Cm device +The device number for +.Sy block +or +.Sy char +file types. +The value must be one of the following forms: +.Bl -tag -width 4n +.It Ar format , Ns Ar major , Ns Ar minor Ns Bo , Ns Ar subunit Bc +A device with +.Ar major , minor +and optional +.Ar subunit +fields. +Their meaning is specified by the operating's system +.Ar format . +See below for valid formats. +.It Ar number +Opaque number (as stored on the file system). +.El +.Pp +The following values for +.Ar format +are recognized: +.Sy native , +.Sy 386bsd , +.Sy 4bsd , +.Sy bsdos , +.Sy freebsd , +.Sy hpux , +.Sy isc , +.Sy linux , +.Sy netbsd , +.Sy osf1 , +.Sy sco , +.Sy solaris , +.Sy sunos , +.Sy svr3 , +.Sy svr4 , +and +.Sy ultrix . +.Pp +See +.Xr mknod 8 +for more details. +.It Cm contents +The full pathname of a file that holds the contents of this file. +.It Cm flags +The file flags as a symbolic name. +See +.Xr chflags 1 +for information on these names. +If no flags are to be set the string +.Dq none +may be used to override the current default. +.It Cm gid +The file group as a numeric value. +.It Cm gname +The file group as a symbolic name. +.It Cm ignore +Ignore any file hierarchy below this file. +.It Cm inode +The inode number. +.It Cm link +The target of the symbolic link when type=link. +.It Cm md5 +The MD5 message digest of the file. +.It Cm md5digest +A synonym for +.Cm md5 . +.It Cm mode +The current file's permissions as a numeric (octal) or symbolic +value. +.It Cm nlink +The number of hard links the file is expected to have. +.It Cm nochange +Make sure this file or directory exists but otherwise ignore all attributes. +.It Cm optional +The file is optional; do not complain about the file if it is not in +the file hierarchy. +.It Cm resdevice +The +.Dq resident +device number of the file, e.g. the ID of the device that +contains the file. +Its format is the same as the one for +.Cm device . +.It Cm ripemd160digest +The +.Tn RIPEMD160 +message digest of the file. +.It Cm rmd160 +A synonym for +.Cm ripemd160digest . +.It Cm rmd160digest +A synonym for +.Cm ripemd160digest . +.It Cm sha1 +The +.Tn FIPS +160-1 +.Pq Dq Tn SHA-1 +message digest of the file. +.It Cm sha1digest +A synonym for +.Cm sha1 . +.It Cm sha256 +The +.Tn FIPS +180-2 +.Pq Dq Tn SHA-256 +message digest of the file. +.It Cm sha256digest +A synonym for +.Cm sha256 . +.It Cm sha384 +The +.Tn FIPS +180-2 +.Pq Dq Tn SHA-384 +message digest of the file. +.It Cm sha384digest +A synonym for +.Cm sha384 . +.It Cm sha512 +The +.Tn FIPS +180-2 +.Pq Dq Tn SHA-512 +message digest of the file. +.It Cm sha512digest +A synonym for +.Cm sha512 . +.It Cm size +The size, in bytes, of the file. +.It Cm time +The last modification time of the file. +.It Cm type +The type of the file; may be set to any one of the following: +.Pp +.Bl -tag -width Cm -compact +.It Cm block +block special device +.It Cm char +character special device +.It Cm dir +directory +.It Cm fifo +fifo +.It Cm file +regular file +.It Cm link +symbolic link +.It Cm socket +socket +.El +.It Cm uid +The file owner as a numeric value. +.It Cm uname +The file owner as a symbolic name. +.El +.Sh SEE ALSO +.Xr cksum 1 , +.Xr find 1 , +.Xr mtree 8 +.Sh HISTORY +The +.Nm +utility appeared in +.Bx 4.3 Reno . +The +.Tn MD5 +digest capability was added in +.Fx 2.1 , +in response to the widespread use of programs which can spoof +.Xr cksum 1 . +The +.Tn SHA-1 +and +.Tn RIPEMD160 +digests were added in +.Fx 4.0 , +as new attacks have demonstrated weaknesses in +.Tn MD5 . +The +.Tn SHA-256 +digest was added in +.Fx 6.0 . +Support for file flags was added in +.Fx 4.0 , +and mostly comes from +.Nx . +The +.Dq full +entry format was added by +.Nx . diff --git a/dependencies/libarchive-3.4.2/libarchive/tar.5 b/dependencies/libarchive-3.4.2/libarchive/tar.5 new file mode 100644 index 0000000..34ad4f7 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/tar.5 @@ -0,0 +1,949 @@ +.\" Copyright (c) 2003-2009 Tim Kientzle +.\" Copyright (c) 2016 Martin Matuska +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd December 27, 2016 +.Dt TAR 5 +.Os +.Sh NAME +.Nm tar +.Nd format of tape archive files +.Sh DESCRIPTION +The +.Nm +archive format collects any number of files, directories, and other +file system objects (symbolic links, device nodes, etc.) into a single +stream of bytes. +The format was originally designed to be used with +tape drives that operate with fixed-size blocks, but is widely used as +a general packaging mechanism. +.Ss General Format +A +.Nm +archive consists of a series of 512-byte records. +Each file system object requires a header record which stores basic metadata +(pathname, owner, permissions, etc.) and zero or more records containing any +file data. +The end of the archive is indicated by two records consisting +entirely of zero bytes. +.Pp +For compatibility with tape drives that use fixed block sizes, +programs that read or write tar files always read or write a fixed +number of records with each I/O operation. +These +.Dq blocks +are always a multiple of the record size. +The maximum block size supported by early +implementations was 10240 bytes or 20 records. +This is still the default for most implementations +although block sizes of 1MiB (2048 records) or larger are +commonly used with modern high-speed tape drives. +(Note: the terms +.Dq block +and +.Dq record +here are not entirely standard; this document follows the +convention established by John Gilmore in documenting +.Nm pdtar . ) +.Ss Old-Style Archive Format +The original tar archive format has been extended many times to +include additional information that various implementors found +necessary. +This section describes the variant implemented by the tar command +included in +.At v7 , +which seems to be the earliest widely-used version of the tar program. +.Pp +The header record for an old-style +.Nm +archive consists of the following: +.Bd -literal -offset indent +struct header_old_tar { + char name[100]; + char mode[8]; + char uid[8]; + char gid[8]; + char size[12]; + char mtime[12]; + char checksum[8]; + char linkflag[1]; + char linkname[100]; + char pad[255]; +}; +.Ed +All unused bytes in the header record are filled with nulls. +.Bl -tag -width indent +.It Va name +Pathname, stored as a null-terminated string. +Early tar implementations only stored regular files (including +hardlinks to those files). +One common early convention used a trailing "/" character to indicate +a directory name, allowing directory permissions and owner information +to be archived and restored. +.It Va mode +File mode, stored as an octal number in ASCII. +.It Va uid , Va gid +User id and group id of owner, as octal numbers in ASCII. +.It Va size +Size of file, as octal number in ASCII. +For regular files only, this indicates the amount of data +that follows the header. +In particular, this field was ignored by early tar implementations +when extracting hardlinks. +Modern writers should always store a zero length for hardlink entries. +.It Va mtime +Modification time of file, as an octal number in ASCII. +This indicates the number of seconds since the start of the epoch, +00:00:00 UTC January 1, 1970. +Note that negative values should be avoided +here, as they are handled inconsistently. +.It Va checksum +Header checksum, stored as an octal number in ASCII. +To compute the checksum, set the checksum field to all spaces, +then sum all bytes in the header using unsigned arithmetic. +This field should be stored as six octal digits followed by a null and a space +character. +Note that many early implementations of tar used signed arithmetic +for the checksum field, which can cause interoperability problems +when transferring archives between systems. +Modern robust readers compute the checksum both ways and accept the +header if either computation matches. +.It Va linkflag , Va linkname +In order to preserve hardlinks and conserve tape, a file +with multiple links is only written to the archive the first +time it is encountered. +The next time it is encountered, the +.Va linkflag +is set to an ASCII +.Sq 1 +and the +.Va linkname +field holds the first name under which this file appears. +(Note that regular files have a null value in the +.Va linkflag +field.) +.El +.Pp +Early tar implementations varied in how they terminated these fields. +The tar command in +.At v7 +used the following conventions (this is also documented in early BSD manpages): +the pathname must be null-terminated; +the mode, uid, and gid fields must end in a space and a null byte; +the size and mtime fields must end in a space; +the checksum is terminated by a null and a space. +Early implementations filled the numeric fields with leading spaces. +This seems to have been common practice until the +.St -p1003.1-88 +standard was released. +For best portability, modern implementations should fill the numeric +fields with leading zeros. +.Ss Pre-POSIX Archives +An early draft of +.St -p1003.1-88 +served as the basis for John Gilmore's +.Nm pdtar +program and many system implementations from the late 1980s +and early 1990s. +These archives generally follow the POSIX ustar +format described below with the following variations: +.Bl -bullet -compact -width indent +.It +The magic value consists of the five characters +.Dq ustar +followed by a space. +The version field contains a space character followed by a null. +.It +The numeric fields are generally filled with leading spaces +(not leading zeros as recommended in the final standard). +.It +The prefix field is often not used, limiting pathnames to +the 100 characters of old-style archives. +.El +.Ss POSIX ustar Archives +.St -p1003.1-88 +defined a standard tar file format to be read and written +by compliant implementations of +.Xr tar 1 . +This format is often called the +.Dq ustar +format, after the magic value used +in the header. +(The name is an acronym for +.Dq Unix Standard TAR . ) +It extends the historic format with new fields: +.Bd -literal -offset indent +struct header_posix_ustar { + char name[100]; + char mode[8]; + char uid[8]; + char gid[8]; + char size[12]; + char mtime[12]; + char checksum[8]; + char typeflag[1]; + char linkname[100]; + char magic[6]; + char version[2]; + char uname[32]; + char gname[32]; + char devmajor[8]; + char devminor[8]; + char prefix[155]; + char pad[12]; +}; +.Ed +.Bl -tag -width indent +.It Va typeflag +Type of entry. +POSIX extended the earlier +.Va linkflag +field with several new type values: +.Bl -tag -width indent -compact +.It Dq 0 +Regular file. +NUL should be treated as a synonym, for compatibility purposes. +.It Dq 1 +Hard link. +.It Dq 2 +Symbolic link. +.It Dq 3 +Character device node. +.It Dq 4 +Block device node. +.It Dq 5 +Directory. +.It Dq 6 +FIFO node. +.It Dq 7 +Reserved. +.It Other +A POSIX-compliant implementation must treat any unrecognized typeflag value +as a regular file. +In particular, writers should ensure that all entries +have a valid filename so that they can be restored by readers that do not +support the corresponding extension. +Uppercase letters "A" through "Z" are reserved for custom extensions. +Note that sockets and whiteout entries are not archivable. +.El +It is worth noting that the +.Va size +field, in particular, has different meanings depending on the type. +For regular files, of course, it indicates the amount of data +following the header. +For directories, it may be used to indicate the total size of all +files in the directory, for use by operating systems that pre-allocate +directory space. +For all other types, it should be set to zero by writers and ignored +by readers. +.It Va magic +Contains the magic value +.Dq ustar +followed by a NUL byte to indicate that this is a POSIX standard archive. +Full compliance requires the uname and gname fields be properly set. +.It Va version +Version. +This should be +.Dq 00 +(two copies of the ASCII digit zero) for POSIX standard archives. +.It Va uname , Va gname +User and group names, as null-terminated ASCII strings. +These should be used in preference to the uid/gid values +when they are set and the corresponding names exist on +the system. +.It Va devmajor , Va devminor +Major and minor numbers for character device or block device entry. +.It Va name , Va prefix +If the pathname is too long to fit in the 100 bytes provided by the standard +format, it can be split at any +.Pa / +character with the first portion going into the prefix field. +If the prefix field is not empty, the reader will prepend +the prefix value and a +.Pa / +character to the regular name field to obtain the full pathname. +The standard does not require a trailing +.Pa / +character on directory names, though most implementations still +include this for compatibility reasons. +.El +.Pp +Note that all unused bytes must be set to +.Dv NUL . +.Pp +Field termination is specified slightly differently by POSIX +than by previous implementations. +The +.Va magic , +.Va uname , +and +.Va gname +fields must have a trailing +.Dv NUL . +The +.Va pathname , +.Va linkname , +and +.Va prefix +fields must have a trailing +.Dv NUL +unless they fill the entire field. +(In particular, it is possible to store a 256-character pathname if it +happens to have a +.Pa / +as the 156th character.) +POSIX requires numeric fields to be zero-padded in the front, and requires +them to be terminated with either space or +.Dv NUL +characters. +.Pp +Currently, most tar implementations comply with the ustar +format, occasionally extending it by adding new fields to the +blank area at the end of the header record. +.Ss Numeric Extensions +There have been several attempts to extend the range of sizes +or times supported by modifying how numbers are stored in the +header. +.Pp +One obvious extension to increase the size of files is to +eliminate the terminating characters from the various +numeric fields. +For example, the standard only allows the size field to contain +11 octal digits, reserving the twelfth byte for a trailing +NUL character. +Allowing 12 octal digits allows file sizes up to 64 GB. +.Pp +Another extension, utilized by GNU tar, star, and other newer +.Nm +implementations, permits binary numbers in the standard numeric fields. +This is flagged by setting the high bit of the first byte. +The remainder of the field is treated as a signed twos-complement +value. +This permits 95-bit values for the length and time fields +and 63-bit values for the uid, gid, and device numbers. +In particular, this provides a consistent way to handle +negative time values. +GNU tar supports this extension for the +length, mtime, ctime, and atime fields. +Joerg Schilling's star program and the libarchive library support +this extension for all numeric fields. +Note that this extension is largely obsoleted by the extended +attribute record provided by the pax interchange format. +.Pp +Another early GNU extension allowed base-64 values rather than octal. +This extension was short-lived and is no longer supported by any +implementation. +.Ss Pax Interchange Format +There are many attributes that cannot be portably stored in a +POSIX ustar archive. +.St -p1003.1-2001 +defined a +.Dq pax interchange format +that uses two new types of entries to hold text-formatted +metadata that applies to following entries. +Note that a pax interchange format archive is a ustar archive in every +respect. +The new data is stored in ustar-compatible archive entries that use the +.Dq x +or +.Dq g +typeflag. +In particular, older implementations that do not fully support these +extensions will extract the metadata into regular files, where the +metadata can be examined as necessary. +.Pp +An entry in a pax interchange format archive consists of one or +two standard ustar entries, each with its own header and data. +The first optional entry stores the extended attributes +for the following entry. +This optional first entry has an "x" typeflag and a size field that +indicates the total size of the extended attributes. +The extended attributes themselves are stored as a series of text-format +lines encoded in the portable UTF-8 encoding. +Each line consists of a decimal number, a space, a key string, an equals +sign, a value string, and a new line. +The decimal number indicates the length of the entire line, including the +initial length field and the trailing newline. +An example of such a field is: +.Dl 25 ctime=1084839148.1212\en +Keys in all lowercase are standard keys. +Vendors can add their own keys by prefixing them with an all uppercase +vendor name and a period. +Note that, unlike the historic header, numeric values are stored using +decimal, not octal. +A description of some common keys follows: +.Bl -tag -width indent +.It Cm atime , Cm ctime , Cm mtime +File access, inode change, and modification times. +These fields can be negative or include a decimal point and a fractional value. +.It Cm hdrcharset +The character set used by the pax extension values. +By default, all textual values in the pax extended attributes +are assumed to be in UTF-8, including pathnames, user names, +and group names. +In some cases, it is not possible to translate local +conventions into UTF-8. +If this key is present and the value is the six-character ASCII string +.Dq BINARY , +then all textual values are assumed to be in a platform-dependent +multi-byte encoding. +Note that there are only two valid values for this key: +.Dq BINARY +or +.Dq ISO-IR\ 10646\ 2000\ UTF-8 . +No other values are permitted by the standard, and +the latter value should generally not be used as it is the +default when this key is not specified. +In particular, this flag should not be used as a general +mechanism to allow filenames to be stored in arbitrary +encodings. +.It Cm uname , Cm uid , Cm gname , Cm gid +User name, group name, and numeric UID and GID values. +The user name and group name stored here are encoded in UTF8 +and can thus include non-ASCII characters. +The UID and GID fields can be of arbitrary length. +.It Cm linkpath +The full path of the linked-to file. +Note that this is encoded in UTF8 and can thus include non-ASCII characters. +.It Cm path +The full pathname of the entry. +Note that this is encoded in UTF8 and can thus include non-ASCII characters. +.It Cm realtime.* , Cm security.* +These keys are reserved and may be used for future standardization. +.It Cm size +The size of the file. +Note that there is no length limit on this field, allowing conforming +archives to store files much larger than the historic 8GB limit. +.It Cm SCHILY.* +Vendor-specific attributes used by Joerg Schilling's +.Nm star +implementation. +.It Cm SCHILY.acl.access , Cm SCHILY.acl.default , Cm SCHILY.acl.ace +Stores the access, default and NFSv4 ACLs as textual strings in a format +that is an extension of the format specified by POSIX.1e draft 17. +In particular, each user or group access specification can include +an additional colon-separated field with the numeric UID or GID. +This allows ACLs to be restored on systems that may not have complete +user or group information available (such as when NIS/YP or LDAP services +are temporarily unavailable). +.It Cm SCHILY.devminor , Cm SCHILY.devmajor +The full minor and major numbers for device nodes. +.It Cm SCHILY.fflags +The file flags. +.It Cm SCHILY.realsize +The full size of the file on disk. +XXX explain? XXX +.It Cm SCHILY.dev , Cm SCHILY.ino , Cm SCHILY.nlinks +The device number, inode number, and link count for the entry. +In particular, note that a pax interchange format archive using Joerg +Schilling's +.Cm SCHILY.* +extensions can store all of the data from +.Va struct stat . +.It Cm LIBARCHIVE.* +Vendor-specific attributes used by the +.Nm libarchive +library and programs that use it. +.It Cm LIBARCHIVE.creationtime +The time when the file was created. +(This should not be confused with the POSIX +.Dq ctime +attribute, which refers to the time when the file +metadata was last changed.) +.It Cm LIBARCHIVE.xattr . Ns Ar namespace . Ns Ar key +Libarchive stores POSIX.1e-style extended attributes using +keys of this form. +The +.Ar key +value is URL-encoded: +All non-ASCII characters and the two special characters +.Dq = +and +.Dq % +are encoded as +.Dq % +followed by two uppercase hexadecimal digits. +The value of this key is the extended attribute value +encoded in base 64. +XXX Detail the base-64 format here XXX +.It Cm VENDOR.* +XXX document other vendor-specific extensions XXX +.El +.Pp +Any values stored in an extended attribute override the corresponding +values in the regular tar header. +Note that compliant readers should ignore the regular fields when they +are overridden. +This is important, as existing archivers are known to store non-compliant +values in the standard header fields in this situation. +There are no limits on length for any of these fields. +In particular, numeric fields can be arbitrarily large. +All text fields are encoded in UTF8. +Compliant writers should store only portable 7-bit ASCII characters in +the standard ustar header and use extended +attributes whenever a text value contains non-ASCII characters. +.Pp +In addition to the +.Cm x +entry described above, the pax interchange format +also supports a +.Cm g +entry. +The +.Cm g +entry is identical in format, but specifies attributes that serve as +defaults for all subsequent archive entries. +The +.Cm g +entry is not widely used. +.Pp +Besides the new +.Cm x +and +.Cm g +entries, the pax interchange format has a few other minor variations +from the earlier ustar format. +The most troubling one is that hardlinks are permitted to have +data following them. +This allows readers to restore any hardlink to a file without +having to rewind the archive to find an earlier entry. +However, it creates complications for robust readers, as it is no longer +clear whether or not they should ignore the size field for hardlink entries. +.Ss GNU Tar Archives +The GNU tar program started with a pre-POSIX format similar to that +described earlier and has extended it using several different mechanisms: +It added new fields to the empty space in the header (some of which was later +used by POSIX for conflicting purposes); +it allowed the header to be continued over multiple records; +and it defined new entries that modify following entries +(similar in principle to the +.Cm x +entry described above, but each GNU special entry is single-purpose, +unlike the general-purpose +.Cm x +entry). +As a result, GNU tar archives are not POSIX compatible, although +more lenient POSIX-compliant readers can successfully extract most +GNU tar archives. +.Bd -literal -offset indent +struct header_gnu_tar { + char name[100]; + char mode[8]; + char uid[8]; + char gid[8]; + char size[12]; + char mtime[12]; + char checksum[8]; + char typeflag[1]; + char linkname[100]; + char magic[6]; + char version[2]; + char uname[32]; + char gname[32]; + char devmajor[8]; + char devminor[8]; + char atime[12]; + char ctime[12]; + char offset[12]; + char longnames[4]; + char unused[1]; + struct { + char offset[12]; + char numbytes[12]; + } sparse[4]; + char isextended[1]; + char realsize[12]; + char pad[17]; +}; +.Ed +.Bl -tag -width indent +.It Va typeflag +GNU tar uses the following special entry types, in addition to +those defined by POSIX: +.Bl -tag -width indent +.It "7" +GNU tar treats type "7" records identically to type "0" records, +except on one obscure RTOS where they are used to indicate the +pre-allocation of a contiguous file on disk. +.It "D" +This indicates a directory entry. +Unlike the POSIX-standard "5" +typeflag, the header is followed by data records listing the names +of files in this directory. +Each name is preceded by an ASCII "Y" +if the file is stored in this archive or "N" if the file is not +stored in this archive. +Each name is terminated with a null, and +an extra null marks the end of the name list. +The purpose of this +entry is to support incremental backups; a program restoring from +such an archive may wish to delete files on disk that did not exist +in the directory when the archive was made. +.Pp +Note that the "D" typeflag specifically violates POSIX, which requires +that unrecognized typeflags be restored as normal files. +In this case, restoring the "D" entry as a file could interfere +with subsequent creation of the like-named directory. +.It "K" +The data for this entry is a long linkname for the following regular entry. +.It "L" +The data for this entry is a long pathname for the following regular entry. +.It "M" +This is a continuation of the last file on the previous volume. +GNU multi-volume archives guarantee that each volume begins with a valid +entry header. +To ensure this, a file may be split, with part stored at the end of one volume, +and part stored at the beginning of the next volume. +The "M" typeflag indicates that this entry continues an existing file. +Such entries can only occur as the first or second entry +in an archive (the latter only if the first entry is a volume label). +The +.Va size +field specifies the size of this entry. +The +.Va offset +field at bytes 369-380 specifies the offset where this file fragment +begins. +The +.Va realsize +field specifies the total size of the file (which must equal +.Va size +plus +.Va offset ) . +When extracting, GNU tar checks that the header file name is the one it is +expecting, that the header offset is in the correct sequence, and that +the sum of offset and size is equal to realsize. +.It "N" +Type "N" records are no longer generated by GNU tar. +They contained a +list of files to be renamed or symlinked after extraction; this was +originally used to support long names. +The contents of this record +are a text description of the operations to be done, in the form +.Dq Rename %s to %s\en +or +.Dq Symlink %s to %s\en ; +in either case, both +filenames are escaped using K&R C syntax. +Due to security concerns, "N" records are now generally ignored +when reading archives. +.It "S" +This is a +.Dq sparse +regular file. +Sparse files are stored as a series of fragments. +The header contains a list of fragment offset/length pairs. +If more than four such entries are required, the header is +extended as necessary with +.Dq extra +header extensions (an older format that is no longer used), or +.Dq sparse +extensions. +.It "V" +The +.Va name +field should be interpreted as a tape/volume header name. +This entry should generally be ignored on extraction. +.El +.It Va magic +The magic field holds the five characters +.Dq ustar +followed by a space. +Note that POSIX ustar archives have a trailing null. +.It Va version +The version field holds a space character followed by a null. +Note that POSIX ustar archives use two copies of the ASCII digit +.Dq 0 . +.It Va atime , Va ctime +The time the file was last accessed and the time of +last change of file information, stored in octal as with +.Va mtime . +.It Va longnames +This field is apparently no longer used. +.It Sparse Va offset / Va numbytes +Each such structure specifies a single fragment of a sparse +file. +The two fields store values as octal numbers. +The fragments are each padded to a multiple of 512 bytes +in the archive. +On extraction, the list of fragments is collected from the +header (including any extension headers), and the data +is then read and written to the file at appropriate offsets. +.It Va isextended +If this is set to non-zero, the header will be followed by additional +.Dq sparse header +records. +Each such record contains information about as many as 21 additional +sparse blocks as shown here: +.Bd -literal -offset indent +struct gnu_sparse_header { + struct { + char offset[12]; + char numbytes[12]; + } sparse[21]; + char isextended[1]; + char padding[7]; +}; +.Ed +.It Va realsize +A binary representation of the file's complete size, with a much larger range +than the POSIX file size. +In particular, with +.Cm M +type files, the current entry is only a portion of the file. +In that case, the POSIX size field will indicate the size of this +entry; the +.Va realsize +field will indicate the total size of the file. +.El +.Ss GNU tar pax archives +GNU tar 1.14 (XXX check this XXX) and later will write +pax interchange format archives when you specify the +.Fl -posix +flag. +This format follows the pax interchange format closely, +using some +.Cm SCHILY +tags and introducing new keywords to store sparse file information. +There have been three iterations of the sparse file support, referred to +as +.Dq 0.0 , +.Dq 0.1 , +and +.Dq 1.0 . +.Bl -tag -width indent +.It Cm GNU.sparse.numblocks , Cm GNU.sparse.offset , Cm GNU.sparse.numbytes , Cm GNU.sparse.size +The +.Dq 0.0 +format used an initial +.Cm GNU.sparse.numblocks +attribute to indicate the number of blocks in the file, a pair of +.Cm GNU.sparse.offset +and +.Cm GNU.sparse.numbytes +to indicate the offset and size of each block, +and a single +.Cm GNU.sparse.size +to indicate the full size of the file. +This is not the same as the size in the tar header because the +latter value does not include the size of any holes. +This format required that the order of attributes be preserved and +relied on readers accepting multiple appearances of the same attribute +names, which is not officially permitted by the standards. +.It Cm GNU.sparse.map +The +.Dq 0.1 +format used a single attribute that stored a comma-separated +list of decimal numbers. +Each pair of numbers indicated the offset and size, respectively, +of a block of data. +This does not work well if the archive is extracted by an archiver +that does not recognize this extension, since many pax implementations +simply discard unrecognized attributes. +.It Cm GNU.sparse.major , Cm GNU.sparse.minor , Cm GNU.sparse.name , Cm GNU.sparse.realsize +The +.Dq 1.0 +format stores the sparse block map in one or more 512-byte blocks +prepended to the file data in the entry body. +The pax attributes indicate the existence of this map +(via the +.Cm GNU.sparse.major +and +.Cm GNU.sparse.minor +fields) +and the full size of the file. +The +.Cm GNU.sparse.name +holds the true name of the file. +To avoid confusion, the name stored in the regular tar header +is a modified name so that extraction errors will be apparent +to users. +.El +.Ss Solaris Tar +XXX More Details Needed XXX +.Pp +Solaris tar (beginning with SunOS XXX 5.7 ?? XXX) supports an +.Dq extended +format that is fundamentally similar to pax interchange format, +with the following differences: +.Bl -bullet -compact -width indent +.It +Extended attributes are stored in an entry whose type is +.Cm X , +not +.Cm x , +as used by pax interchange format. +The detailed format of this entry appears to be the same +as detailed above for the +.Cm x +entry. +.It +An additional +.Cm A +header is used to store an ACL for the following regular entry. +The body of this entry contains a seven-digit octal number +followed by a zero byte, followed by the +textual ACL description. +The octal value is the number of ACL entries +plus a constant that indicates the ACL type: 01000000 +for POSIX.1e ACLs and 03000000 for NFSv4 ACLs. +.El +.Ss AIX Tar +XXX More details needed XXX +.Pp +AIX Tar uses a ustar-formatted header with the type +.Cm A +for storing coded ACL information. +Unlike the Solaris format, AIX tar writes this header after the +regular file body to which it applies. +The pathname in this header is either +.Cm NFS4 +or +.Cm AIXC +to indicate the type of ACL stored. +The actual ACL is stored in platform-specific binary format. +.Ss Mac OS X Tar +The tar distributed with Apple's Mac OS X stores most regular files +as two separate files in the tar archive. +The two files have the same name except that the first +one has +.Dq ._ +prepended to the last path element. +This special file stores an AppleDouble-encoded +binary blob with additional metadata about the second file, +including ACL, extended attributes, and resources. +To recreate the original file on disk, each +separate file can be extracted and the Mac OS X +.Fn copyfile +function can be used to unpack the separate +metadata file and apply it to th regular file. +Conversely, the same function provides a +.Dq pack +option to encode the extended metadata from +a file into a separate file whose contents +can then be put into a tar archive. +.Pp +Note that the Apple extended attributes interact +badly with long filenames. +Since each file is stored with the full name, +a separate set of extensions needs to be included +in the archive for each one, doubling the overhead +required for files with long names. +.Ss Summary of tar type codes +The following list is a condensed summary of the type codes +used in tar header records generated by different tar implementations. +More details about specific implementations can be found above: +.Bl -tag -compact -width XXX +.It NUL +Early tar programs stored a zero byte for regular files. +.It Cm 0 +POSIX standard type code for a regular file. +.It Cm 1 +POSIX standard type code for a hard link description. +.It Cm 2 +POSIX standard type code for a symbolic link description. +.It Cm 3 +POSIX standard type code for a character device node. +.It Cm 4 +POSIX standard type code for a block device node. +.It Cm 5 +POSIX standard type code for a directory. +.It Cm 6 +POSIX standard type code for a FIFO. +.It Cm 7 +POSIX reserved. +.It Cm 7 +GNU tar used for pre-allocated files on some systems. +.It Cm A +Solaris tar ACL description stored prior to a regular file header. +.It Cm A +AIX tar ACL description stored after the file body. +.It Cm D +GNU tar directory dump. +.It Cm K +GNU tar long linkname for the following header. +.It Cm L +GNU tar long pathname for the following header. +.It Cm M +GNU tar multivolume marker, indicating the file is a continuation of a file from the previous volume. +.It Cm N +GNU tar long filename support. +Deprecated. +.It Cm S +GNU tar sparse regular file. +.It Cm V +GNU tar tape/volume header name. +.It Cm X +Solaris tar general-purpose extension header. +.It Cm g +POSIX pax interchange format global extensions. +.It Cm x +POSIX pax interchange format per-file extensions. +.El +.Sh SEE ALSO +.Xr ar 1 , +.Xr pax 1 , +.Xr tar 1 +.Sh STANDARDS +The +.Nm tar +utility is no longer a part of POSIX or the Single Unix Standard. +It last appeared in +.St -susv2 . +It has been supplanted in subsequent standards by +.Xr pax 1 . +The ustar format is currently part of the specification for the +.Xr pax 1 +utility. +The pax interchange file format is new with +.St -p1003.1-2001 . +.Sh HISTORY +A +.Nm tar +command appeared in Seventh Edition Unix, which was released in January, 1979. +It replaced the +.Nm tp +program from Fourth Edition Unix which in turn replaced the +.Nm tap +program from First Edition Unix. +John Gilmore's +.Nm pdtar +public-domain implementation (circa 1987) was highly influential +and formed the basis of +.Nm GNU tar +(circa 1988). +Joerg Shilling's +.Nm star +archiver is another open-source (CDDL) archiver (originally developed +circa 1985) which features complete support for pax interchange +format. +.Pp +This documentation was written as part of the +.Nm libarchive +and +.Nm bsdtar +project by +.An Tim Kientzle Aq kientzle@FreeBSD.org . diff --git a/dependencies/libarchive-3.4.2/libarchive/test/CMakeLists.txt b/dependencies/libarchive-3.4.2/libarchive/test/CMakeLists.txt new file mode 100644 index 0000000..df34d3e --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/CMakeLists.txt @@ -0,0 +1,323 @@ +############################################ +# +# How to build libarchive_test +# +############################################ +IF(ENABLE_TEST) + SET(libarchive_test_SOURCES + ../../test_utils/test_utils.c + ../../test_utils/test_main.c + read_open_memory.c + test.h + test_acl_nfs4.c + test_acl_pax.c + test_acl_platform_nfs4.c + test_acl_platform_posix1e.c + test_acl_posix1e.c + test_acl_text.c + test_archive_api_feature.c + test_archive_clear_error.c + test_archive_cmdline.c + test_archive_digest.c + test_archive_getdate.c + test_archive_match_owner.c + test_archive_match_path.c + test_archive_match_time.c + test_archive_pathmatch.c + test_archive_read_add_passphrase.c + test_archive_read_close_twice.c + test_archive_read_close_twice_open_fd.c + test_archive_read_close_twice_open_filename.c + test_archive_read_multiple_data_objects.c + test_archive_read_next_header_empty.c + test_archive_read_next_header_raw.c + test_archive_read_open2.c + test_archive_read_set_filter_option.c + test_archive_read_set_format_option.c + test_archive_read_set_option.c + test_archive_read_set_options.c + test_archive_read_support.c + test_archive_set_error.c + test_archive_string.c + test_archive_string_conversion.c + test_archive_write_add_filter_by_name.c + test_archive_write_set_filter_option.c + test_archive_write_set_format_by_name.c + test_archive_write_set_format_filter_by_ext.c + test_archive_write_set_format_option.c + test_archive_write_set_option.c + test_archive_write_set_options.c + test_archive_write_set_passphrase.c + test_bad_fd.c + test_compat_bzip2.c + test_compat_cpio.c + test_compat_gtar.c + test_compat_gzip.c + test_compat_lz4.c + test_compat_lzip.c + test_compat_lzma.c + test_compat_lzop.c + test_compat_mac.c + test_compat_perl_archive_tar.c + test_compat_plexus_archiver_tar.c + test_compat_solaris_pax_sparse.c + test_compat_solaris_tar_acl.c + test_compat_star_acl.c + test_compat_tar_hardlink.c + test_compat_uudecode.c + test_compat_uudecode_large.c + test_compat_xz.c + test_compat_zip.c + test_compat_zstd.c + test_empty_write.c + test_entry.c + test_entry_strmode.c + test_extattr_freebsd.c + test_filter_count.c + test_fuzz.c + test_gnutar_filename_encoding.c + test_link_resolver.c + test_open_failure.c + test_open_fd.c + test_open_file.c + test_open_filename.c + test_pax_filename_encoding.c + test_pax_xattr_header.c + test_read_data_large.c + test_read_disk.c + test_read_disk_directory_traversals.c + test_read_disk_entry_from_file.c + test_read_extract.c + test_read_file_nonexistent.c + test_read_filter_compress.c + test_read_filter_grzip.c + test_read_filter_lrzip.c + test_read_filter_lzop.c + test_read_filter_lzop_multiple_parts.c + test_read_filter_program.c + test_read_filter_program_signature.c + test_read_filter_uudecode.c + test_read_format_7zip.c + test_read_format_7zip_encryption_data.c + test_read_format_7zip_encryption_header.c + test_read_format_7zip_encryption_partially.c + test_read_format_7zip_malformed.c + test_read_format_7zip_packinfo_digests.c + test_read_format_ar.c + test_read_format_cab.c + test_read_format_cab_filename.c + test_read_format_cpio_afio.c + test_read_format_cpio_bin.c + test_read_format_cpio_bin_Z.c + test_read_format_cpio_bin_be.c + test_read_format_cpio_bin_bz2.c + test_read_format_cpio_bin_gz.c + test_read_format_cpio_bin_le.c + test_read_format_cpio_bin_lzip.c + test_read_format_cpio_bin_lzma.c + test_read_format_cpio_bin_xz.c + test_read_format_cpio_filename.c + test_read_format_cpio_odc.c + test_read_format_cpio_svr4_bzip2_rpm.c + test_read_format_cpio_svr4_gzip.c + test_read_format_cpio_svr4_gzip_rpm.c + test_read_format_cpio_svr4c_Z.c + test_read_format_empty.c + test_read_format_gtar_filename.c + test_read_format_gtar_gz.c + test_read_format_gtar_lzma.c + test_read_format_gtar_sparse.c + test_read_format_gtar_sparse_skip_entry.c + test_read_format_iso_Z.c + test_read_format_iso_multi_extent.c + test_read_format_iso_xorriso.c + test_read_format_isojoliet_bz2.c + test_read_format_isojoliet_long.c + test_read_format_isojoliet_rr.c + test_read_format_isojoliet_versioned.c + test_read_format_isorr_bz2.c + test_read_format_isorr_ce.c + test_read_format_isorr_new_bz2.c + test_read_format_isorr_rr_moved.c + test_read_format_isozisofs_bz2.c + test_read_format_lha.c + test_read_format_lha_bugfix_0.c + test_read_format_lha_filename.c + test_read_format_lha_filename_utf16.c + test_read_format_mtree.c + test_read_format_mtree_crash747.c + test_read_format_pax_bz2.c + test_read_format_rar.c + test_read_format_rar_encryption_data.c + test_read_format_rar_encryption_header.c + test_read_format_rar_encryption_partially.c + test_read_format_rar_invalid1.c + test_read_format_rar5.c + test_read_format_raw.c + test_read_format_tar.c + test_read_format_tar_concatenated.c + test_read_format_tar_empty_filename.c + test_read_format_tar_empty_with_gnulabel.c + test_read_format_tar_empty_pax.c + test_read_format_tar_filename.c + test_read_format_tbz.c + test_read_format_tgz.c + test_read_format_tlz.c + test_read_format_txz.c + test_read_format_tz.c + test_read_format_ustar_filename.c + test_read_format_warc.c + test_read_format_xar.c + test_read_format_zip.c + test_read_format_zip_7075_utf8_paths.c + test_read_format_zip_comment_stored.c + test_read_format_zip_encryption_data.c + test_read_format_zip_encryption_header.c + test_read_format_zip_encryption_partially.c + test_read_format_zip_extra_padding.c + test_read_format_zip_filename.c + test_read_format_zip_high_compression.c + test_read_format_zip_jar.c + test_read_format_zip_mac_metadata.c + test_read_format_zip_malformed.c + test_read_format_zip_msdos.c + test_read_format_zip_nested.c + test_read_format_zip_nofiletype.c + test_read_format_zip_padded.c + test_read_format_zip_sfx.c + test_read_format_zip_traditional_encryption_data.c + test_read_format_zip_winzip_aes.c + test_read_format_zip_winzip_aes_large.c + test_read_format_zip_zip64.c + test_read_format_zip_with_invalid_traditional_eocd.c + test_read_large.c + test_read_pax_schily_xattr.c + test_read_pax_truncated.c + test_read_position.c + test_read_set_format.c + test_read_too_many_filters.c + test_read_truncated.c + test_read_truncated_filter.c + test_sparse_basic.c + test_tar_filenames.c + test_tar_large.c + test_ustar_filename_encoding.c + test_ustar_filenames.c + test_warn_missing_hardlink_target.c + test_write_disk.c + test_write_disk_appledouble.c + test_write_disk_failures.c + test_write_disk_hardlink.c + test_write_disk_hfs_compression.c + test_write_disk_lookup.c + test_write_disk_mac_metadata.c + test_write_disk_no_hfs_compression.c + test_write_disk_perms.c + test_write_disk_secure.c + test_write_disk_secure744.c + test_write_disk_secure745.c + test_write_disk_secure746.c + test_write_disk_sparse.c + test_write_disk_symlink.c + test_write_disk_times.c + test_write_filter_b64encode.c + test_write_filter_bzip2.c + test_write_filter_compress.c + test_write_filter_gzip.c + test_write_filter_gzip_timestamp.c + test_write_filter_lrzip.c + test_write_filter_lz4.c + test_write_filter_lzip.c + test_write_filter_lzma.c + test_write_filter_lzop.c + test_write_filter_program.c + test_write_filter_uuencode.c + test_write_filter_xz.c + test_write_filter_zstd.c + test_write_format_7zip.c + test_write_format_7zip_empty.c + test_write_format_7zip_large.c + test_write_format_ar.c + test_write_format_cpio.c + test_write_format_cpio_empty.c + test_write_format_cpio_newc.c + test_write_format_cpio_odc.c + test_write_format_gnutar.c + test_write_format_gnutar_filenames.c + test_write_format_iso9660.c + test_write_format_iso9660_boot.c + test_write_format_iso9660_empty.c + test_write_format_iso9660_filename.c + test_write_format_iso9660_zisofs.c + test_write_format_mtree.c + test_write_format_mtree_absolute_path.c + test_write_format_mtree_classic.c + test_write_format_mtree_classic_indent.c + test_write_format_mtree_fflags.c + test_write_format_mtree_no_separator.c + test_write_format_mtree_quoted_filename.c + test_write_format_pax.c + test_write_format_raw.c + test_write_format_raw_b64.c + test_write_format_shar_empty.c + test_write_format_tar.c + test_write_format_tar_empty.c + test_write_format_tar_sparse.c + test_write_format_tar_ustar.c + test_write_format_tar_v7tar.c + test_write_format_warc.c + test_write_format_warc_empty.c + test_write_format_xar.c + test_write_format_xar_empty.c + test_write_format_zip.c + test_write_format_zip_compression_store.c + test_write_format_zip_empty.c + test_write_format_zip_empty_zip64.c + test_write_format_zip_file.c + test_write_format_zip_file_zip64.c + test_write_format_zip_large.c + test_write_format_zip_zip64.c + test_write_open_memory.c + test_write_read_format_zip.c + test_xattr_platform.c + test_zip_filename_encoding.c + ) + + # + # Register target + # + ADD_EXECUTABLE(libarchive_test ${libarchive_test_SOURCES}) + TARGET_LINK_LIBRARIES(libarchive_test archive_static ${ADDITIONAL_LIBS}) + SET_PROPERTY(TARGET libarchive_test PROPERTY COMPILE_DEFINITIONS + LIBARCHIVE_STATIC LIST_H) + + # + # Generate list.h by grepping DEFINE_TEST() lines out of the C sources. + # + GENERATE_LIST_H(${CMAKE_CURRENT_BINARY_DIR}/list.h + ${CMAKE_CURRENT_LIST_FILE} ${libarchive_test_SOURCES}) + SET_PROPERTY(DIRECTORY APPEND PROPERTY INCLUDE_DIRECTORIES + ${CMAKE_CURRENT_BINARY_DIR}) + + # list.h has a line DEFINE_TEST(testname) for every + # test. We can use that to define the tests for cmake by + # defining a DEFINE_TEST macro and reading list.h in. + MACRO (DEFINE_TEST _testname) + ADD_TEST( + NAME libarchive_${_testname} + COMMAND libarchive_test -vv + -r ${CMAKE_CURRENT_SOURCE_DIR} + ${_testname}) + ENDMACRO (DEFINE_TEST _testname) + + INCLUDE(${CMAKE_CURRENT_BINARY_DIR}/list.h) + INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) + INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/test_utils) + INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/libarchive/test) + + # Experimental new test handling + ADD_CUSTOM_TARGET(run_libarchive_test + COMMAND libarchive_test -r ${CMAKE_CURRENT_SOURCE_DIR} -vv) + ADD_DEPENDENCIES(run_all_tests run_libarchive_test) +ENDIF(ENABLE_TEST) + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/README b/dependencies/libarchive-3.4.2/libarchive/test/README new file mode 100644 index 0000000..1b70c7a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/README @@ -0,0 +1,63 @@ +$FreeBSD: src/lib/libarchive/test/README,v 1.3 2008/01/01 22:28:04 kientzle Exp $ + +This is the test harness for libarchive. + +It compiles into a single program "libarchive_test" that is intended +to exercise as much of the library as possible. It is, of course, +very much a work in progress. + +Each test is a function named test_foo in a file named test_foo.c. +Note that the file name is the same as the function name. +Each file must start with this line: + + #include "test.h" + +The test function must be declared with a line of this form + + DEFINE_TEST(test_foo) + +Nothing else should appear on that line. + +When you add a test, please update the top-level Makefile.am and the +CMakeLists.txt in this directory to add your file to the list of +tests. The Makefile and main.c use various macro trickery to +automatically collect a list of test functions to be invoked. + +Each test function can rely on the following: + + * The current directory will be a freshly-created empty directory + suitable for that test. (The top-level main() creates a + directory for each separate test and chdir()s to that directory + before running the test.) + + * The test function should use assert(), assertA() and similar macros + defined in test.h. If you need to add new macros of this form, feel + free to do so. The current macro set includes assertEqualInt() and + assertEqualString() that print out additional detail about their + arguments if the assertion does fail. 'A' versions also accept + a struct archive * and display any error message from there on + failure. + + * You are encouraged to document each assertion with a failure() call + just before the assert. The failure() function is a printf-like + function whose text is displayed only if the assertion fails. It + can be used to display additional information relevant to the failure: + + failure("The data read from file %s did not match the data written to that file.", filename); + assert(strcmp(buff1, buff2) == 0); + + * Tests are encouraged to be economical with their memory and disk usage, + though this is not essential. The test is occasionally run under + a memory debugger to try to locate memory leaks in the library; + as a result, tests should be careful to release any memory they + allocate. + + * Disable tests on specific platforms as necessary. Please avoid + using config.h to adjust feature requirements, as I want the tests + to also serve as a check on the configure process. The following + form is usually more appropriate: + +#if !defined(__PLATFORM) && !defined(__Platform2__) + assert(xxxx) +#endif + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/list.h b/dependencies/libarchive-3.4.2/libarchive/test/list.h new file mode 100644 index 0000000..59a22fe --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/list.h @@ -0,0 +1,569 @@ +DEFINE_TEST(test_acl_nfs4) +DEFINE_TEST(test_acl_pax_posix1e) +DEFINE_TEST(test_acl_pax_nfs4) +DEFINE_TEST(test_acl_platform_nfs4) +DEFINE_TEST(test_acl_platform_posix1e_restore) +DEFINE_TEST(test_acl_platform_posix1e_read) +DEFINE_TEST(test_acl_posix1e) +DEFINE_TEST(test_acl_from_text) +DEFINE_TEST(test_acl_to_text) +DEFINE_TEST(test_archive_api_feature) +DEFINE_TEST(test_archive_clear_error) +DEFINE_TEST(test_archive_cmdline) +DEFINE_TEST(test_archive_md5) +DEFINE_TEST(test_archive_rmd160) +DEFINE_TEST(test_archive_sha1) +DEFINE_TEST(test_archive_sha256) +DEFINE_TEST(test_archive_sha384) +DEFINE_TEST(test_archive_sha512) +DEFINE_TEST(test_archive_getdate) +DEFINE_TEST(test_archive_match_owner) +DEFINE_TEST(test_archive_match_path) +DEFINE_TEST(test_archive_match_time) +DEFINE_TEST(test_archive_pathmatch) +DEFINE_TEST(test_archive_read_add_passphrase) +DEFINE_TEST(test_archive_read_add_passphrase_incorrect_sequance) +DEFINE_TEST(test_archive_read_add_passphrase_single) +DEFINE_TEST(test_archive_read_add_passphrase_multiple) +DEFINE_TEST(test_archive_read_add_passphrase_set_callback1) +DEFINE_TEST(test_archive_read_add_passphrase_set_callback2) +DEFINE_TEST(test_archive_read_add_passphrase_set_callback3) +DEFINE_TEST(test_archive_read_add_passphrase_multiple_with_callback) +DEFINE_TEST(test_archive_read_add_passphrase_multiple_with_callback2) +DEFINE_TEST(test_archive_read_close_twice) +DEFINE_TEST(test_archive_read_close_twice_open_fd) +DEFINE_TEST(test_archive_read_close_twice_open_filename) +DEFINE_TEST(test_archive_read_multiple_data_objects) +DEFINE_TEST(test_archive_read_next_header_empty) +DEFINE_TEST(test_archive_read_next_header_raw) +DEFINE_TEST(test_archive_read_open2) +DEFINE_TEST(test_archive_read_set_filter_option) +DEFINE_TEST(test_archive_read_set_format_option) +DEFINE_TEST(test_archive_read_set_option) +DEFINE_TEST(test_archive_read_set_options) +DEFINE_TEST(test_archive_read_support) +DEFINE_TEST(test_archive_set_error) +DEFINE_TEST(test_archive_string) +DEFINE_TEST(test_archive_string_sort) +DEFINE_TEST(test_archive_string_conversion) +DEFINE_TEST(test_archive_write_add_filter_by_name_b64encode) +DEFINE_TEST(test_archive_write_add_filter_by_name_bzip2) +DEFINE_TEST(test_archive_write_add_filter_by_name_compress) +DEFINE_TEST(test_archive_write_add_filter_by_name_grzip) +DEFINE_TEST(test_archive_write_add_filter_by_name_gzip) +DEFINE_TEST(test_archive_write_add_filter_by_name_lrzip) +DEFINE_TEST(test_archive_write_add_filter_by_name_lz4) +DEFINE_TEST(test_archive_write_add_filter_by_name_lzip) +DEFINE_TEST(test_archive_write_add_filter_by_name_lzma) +DEFINE_TEST(test_archive_write_add_filter_by_name_lzop) +DEFINE_TEST(test_archive_write_add_filter_by_name_uuencode) +DEFINE_TEST(test_archive_write_add_filter_by_name_xz) +DEFINE_TEST(test_archive_write_add_filter_by_name_zstd) +DEFINE_TEST(test_archive_write_set_filter_option) +DEFINE_TEST(test_archive_write_set_format_by_name_7zip) +DEFINE_TEST(test_archive_write_set_format_by_name_ar) +DEFINE_TEST(test_archive_write_set_format_by_name_arbsd) +DEFINE_TEST(test_archive_write_set_format_by_name_argnu) +DEFINE_TEST(test_archive_write_set_format_by_name_arsvr4) +DEFINE_TEST(test_archive_write_set_format_by_name_bsdtar) +DEFINE_TEST(test_archive_write_set_format_by_name_cd9660) +DEFINE_TEST(test_archive_write_set_format_by_name_cpio) +DEFINE_TEST(test_archive_write_set_format_by_name_gnutar) +DEFINE_TEST(test_archive_write_set_format_by_name_iso) +DEFINE_TEST(test_archive_write_set_format_by_name_iso9660) +DEFINE_TEST(test_archive_write_set_format_by_name_mtree) +DEFINE_TEST(test_archive_write_set_format_by_name_mtree_classic) +DEFINE_TEST(test_archive_write_set_format_by_name_newc) +DEFINE_TEST(test_archive_write_set_format_by_name_odc) +DEFINE_TEST(test_archive_write_set_format_by_name_oldtar) +DEFINE_TEST(test_archive_write_set_format_by_name_pax) +DEFINE_TEST(test_archive_write_set_format_by_name_paxr) +DEFINE_TEST(test_archive_write_set_format_by_name_posix) +DEFINE_TEST(test_archive_write_set_format_by_name_rpax) +DEFINE_TEST(test_archive_write_set_format_by_name_shar) +DEFINE_TEST(test_archive_write_set_format_by_name_shardump) +DEFINE_TEST(test_archive_write_set_format_by_name_ustar) +DEFINE_TEST(test_archive_write_set_format_by_name_v7tar) +DEFINE_TEST(test_archive_write_set_format_by_name_v7) +DEFINE_TEST(test_archive_write_set_format_by_name_warc) +DEFINE_TEST(test_archive_write_set_format_by_name_xar) +DEFINE_TEST(test_archive_write_set_format_by_name_zip) +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_7zip) +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_zip) +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_jar) +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_a) +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_ar) +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_cpio) +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_iso) +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_tar) +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_tar_gz) +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_tar_bz2) +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_tar_xz) +DEFINE_TEST(test_archive_write_set_format_filter_by_no_ext_def_zip) +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_tar_bz2_def_zip) +DEFINE_TEST(test_archive_write_set_format_option) +DEFINE_TEST(test_archive_write_set_option) +DEFINE_TEST(test_archive_write_set_options) +DEFINE_TEST(test_archive_write_set_passphrase) +DEFINE_TEST(test_archive_write_set_passphrase_callback) +DEFINE_TEST(test_bad_fd) +DEFINE_TEST(test_compat_bzip2) +DEFINE_TEST(test_compat_cpio) +DEFINE_TEST(test_compat_gtar) +DEFINE_TEST(test_compat_gzip) +DEFINE_TEST(test_compat_lz4) +DEFINE_TEST(test_compat_lzip) +DEFINE_TEST(test_compat_lzma) +DEFINE_TEST(test_compat_lzop) +DEFINE_TEST(test_compat_mac) +DEFINE_TEST(test_compat_perl_archive_tar) +DEFINE_TEST(test_compat_plexus_archiver_tar) +DEFINE_TEST(test_compat_solaris_pax_sparse) +DEFINE_TEST(test_compat_solaris_tar_acl) +DEFINE_TEST(test_compat_star_acl_posix1e) +DEFINE_TEST(test_compat_star_acl_nfs4) +DEFINE_TEST(test_compat_tar_hardlink) +DEFINE_TEST(test_compat_uudecode) +DEFINE_TEST(test_compat_uudecode_large) +DEFINE_TEST(test_compat_xz) +DEFINE_TEST(test_compat_zip_1) +DEFINE_TEST(test_compat_zip_2) +DEFINE_TEST(test_compat_zip_3) +DEFINE_TEST(test_compat_zip_4) +DEFINE_TEST(test_compat_zip_5) +DEFINE_TEST(test_compat_zip_6) +DEFINE_TEST(test_compat_zip_7) +DEFINE_TEST(test_compat_zip_8) +DEFINE_TEST(test_compat_zstd) +DEFINE_TEST(test_empty_write) +DEFINE_TEST(test_entry) +DEFINE_TEST(test_entry_strmode) +DEFINE_TEST(test_extattr_freebsd) +DEFINE_TEST(test_filter_count) +DEFINE_TEST(test_fuzz_ar) +DEFINE_TEST(test_fuzz_cab) +DEFINE_TEST(test_fuzz_cpio) +DEFINE_TEST(test_fuzz_iso9660) +DEFINE_TEST(test_fuzz_lzh) +DEFINE_TEST(test_fuzz_mtree) +DEFINE_TEST(test_fuzz_rar) +DEFINE_TEST(test_fuzz_tar) +DEFINE_TEST(test_fuzz_zip) +DEFINE_TEST(test_gnutar_filename_encoding_UTF8_CP866) +DEFINE_TEST(test_gnutar_filename_encoding_KOI8R_UTF8) +DEFINE_TEST(test_gnutar_filename_encoding_KOI8R_CP866) +DEFINE_TEST(test_gnutar_filename_encoding_CP1251_UTF8) +DEFINE_TEST(test_gnutar_filename_encoding_ru_RU_CP1251) +DEFINE_TEST(test_gnutar_filename_encoding_Russian_Russia) +DEFINE_TEST(test_gnutar_filename_encoding_EUCJP_UTF8) +DEFINE_TEST(test_gnutar_filename_encoding_EUCJP_CP932) +DEFINE_TEST(test_gnutar_filename_encoding_CP932_UTF8) +DEFINE_TEST(test_link_resolver) +DEFINE_TEST(test_open_failure) +DEFINE_TEST(test_open_fd) +DEFINE_TEST(test_open_file) +DEFINE_TEST(test_open_filename) +DEFINE_TEST(test_pax_filename_encoding_KOI8R) +DEFINE_TEST(test_pax_filename_encoding_CP1251) +DEFINE_TEST(test_pax_filename_encoding_EUCJP) +DEFINE_TEST(test_pax_filename_encoding_CP932) +DEFINE_TEST(test_pax_filename_encoding_KOI8R_BINARY) +DEFINE_TEST(test_pax_filename_encoding_KOI8R_CP1251) +DEFINE_TEST(test_pax_filename_encoding) +DEFINE_TEST(test_pax_xattr_header) +DEFINE_TEST(test_read_data_large) +DEFINE_TEST(test_read_disk) +DEFINE_TEST(test_read_disk_directory_traversals) +DEFINE_TEST(test_read_disk_entry_from_file) +DEFINE_TEST(test_read_extract) +DEFINE_TEST(test_read_file_nonexistent) +DEFINE_TEST(test_read_filter_compress_truncated) +DEFINE_TEST(test_read_filter_compress_empty2) +DEFINE_TEST(test_read_filter_compress_invalid) +DEFINE_TEST(test_read_filter_grzip) +DEFINE_TEST(test_read_filter_lrzip) +DEFINE_TEST(test_read_filter_lzop) +DEFINE_TEST(test_read_filter_lzop_multiple_parts) +DEFINE_TEST(test_read_filter_program) +DEFINE_TEST(test_read_filter_program_signature) +DEFINE_TEST(test_read_filter_uudecode) +DEFINE_TEST(test_read_filter_uudecode_base64) +DEFINE_TEST(test_read_format_7zip) +DEFINE_TEST(test_read_format_7zip_bzip2) +DEFINE_TEST(test_read_format_7zip_from_fd) +DEFINE_TEST(test_read_format_7zip_copy) +DEFINE_TEST(test_read_format_7zip_deflate) +DEFINE_TEST(test_read_format_7zip_empty) +DEFINE_TEST(test_read_format_7zip_lzma1) +DEFINE_TEST(test_read_format_7zip_lzma2) +DEFINE_TEST(test_read_format_7zip_ppmd) +DEFINE_TEST(test_read_format_7zip_encryption_data) +DEFINE_TEST(test_read_format_7zip_encryption_header) +DEFINE_TEST(test_read_format_7zip_encryption_partially) +DEFINE_TEST(test_read_format_7zip_malformed) +DEFINE_TEST(test_read_format_7zip_packinfo_digests) +DEFINE_TEST(test_read_format_ar) +DEFINE_TEST(test_read_format_cab) +DEFINE_TEST(test_read_format_cab_filename) +DEFINE_TEST(test_read_format_cpio_afio) +DEFINE_TEST(test_read_format_cpio_bin) +DEFINE_TEST(test_read_format_cpio_bin_Z) +DEFINE_TEST(test_read_format_cpio_bin_be) +DEFINE_TEST(test_read_format_cpio_bin_bz2) +DEFINE_TEST(test_read_format_cpio_bin_gz) +DEFINE_TEST(test_read_format_cpio_bin_le) +DEFINE_TEST(test_read_format_cpio_bin_lzip) +DEFINE_TEST(test_read_format_cpio_bin_lzma) +DEFINE_TEST(test_read_format_cpio_bin_xz) +DEFINE_TEST(test_read_format_cpio_filename_eucJP_UTF8) +DEFINE_TEST(test_read_format_cpio_filename_UTF8_eucJP) +DEFINE_TEST(test_read_format_cpio_filename_UTF8_UTF8_jp) +DEFINE_TEST(test_read_format_cpio_filename_CP866_KOI8R) +DEFINE_TEST(test_read_format_cpio_filename_CP866_UTF8) +DEFINE_TEST(test_read_format_cpio_filename_KOI8R_CP866) +DEFINE_TEST(test_read_format_cpio_filename_KOI8R_UTF8) +DEFINE_TEST(test_read_format_cpio_filename_UTF8_KOI8R) +DEFINE_TEST(test_read_format_cpio_filename_UTF8_CP866) +DEFINE_TEST(test_read_format_cpio_filename_UTF8_UTF8_ru) +DEFINE_TEST(test_read_format_cpio_filename_eucJP_CP932) +DEFINE_TEST(test_read_format_cpio_filename_UTF8_CP932) +DEFINE_TEST(test_read_format_cpio_filename_CP866_CP1251) +DEFINE_TEST(test_read_format_cpio_filename_CP866_CP1251_win) +DEFINE_TEST(test_read_format_cpio_filename_KOI8R_CP1251) +DEFINE_TEST(test_read_format_cpio_filename_UTF8_CP1251) +DEFINE_TEST(test_read_format_cpio_odc) +DEFINE_TEST(test_read_format_cpio_svr4_bzip2_rpm) +DEFINE_TEST(test_read_format_cpio_svr4_gzip) +DEFINE_TEST(test_read_format_cpio_svr4_gzip_rpm) +DEFINE_TEST(test_read_format_cpio_svr4c_Z) +DEFINE_TEST(test_read_format_empty) +DEFINE_TEST(test_read_format_gtar_filename_eucJP_UTF8) +DEFINE_TEST(test_read_format_gtar_filename_CP866_KOI8R) +DEFINE_TEST(test_read_format_gtar_filename_CP866_UTF8) +DEFINE_TEST(test_read_format_gtar_filename_KOI8R_CP866) +DEFINE_TEST(test_read_format_gtar_filename_KOI8R_UTF8) +DEFINE_TEST(test_read_format_gtar_filename_eucJP_CP932) +DEFINE_TEST(test_read_format_gtar_filename_CP866_CP1251) +DEFINE_TEST(test_read_format_gtar_filename_CP866_CP1251_win) +DEFINE_TEST(test_read_format_gtar_filename_KOI8R_CP1251) +DEFINE_TEST(test_read_format_gtar_gz) +DEFINE_TEST(test_read_format_gtar_lzma) +DEFINE_TEST(test_read_format_gtar_sparse) +DEFINE_TEST(test_read_format_gtar_sparse_skip_entry) +DEFINE_TEST(test_read_format_iso_Z) +DEFINE_TEST(test_read_format_iso_multi_extent) +DEFINE_TEST(test_read_format_iso_xorriso) +DEFINE_TEST(test_read_format_isojoliet_bz2) +DEFINE_TEST(test_read_format_isojoliet_long) +DEFINE_TEST(test_read_format_isojoliet_rr) +DEFINE_TEST(test_read_format_isojoliet_versioned) +DEFINE_TEST(test_read_format_isorr_bz2) +DEFINE_TEST(test_read_format_isorr_ce) +DEFINE_TEST(test_read_format_isorr_new_bz2) +DEFINE_TEST(test_read_format_isorr_rr_moved) +DEFINE_TEST(test_read_format_isozisofs_bz2) +DEFINE_TEST(test_read_format_lha) +DEFINE_TEST(test_read_format_lha_bugfix_0) +DEFINE_TEST(test_read_format_lha_filename) +DEFINE_TEST(test_read_format_lha_filename_UTF16) +DEFINE_TEST(test_read_format_mtree) +DEFINE_TEST(test_read_format_mtree_filenames_only) +DEFINE_TEST(test_read_format_mtree_nochange) +DEFINE_TEST(test_read_format_mtree_nomagic_v1_form) +DEFINE_TEST(test_read_format_mtree_nomagic_v2_form) +DEFINE_TEST(test_read_format_mtree_nomagic_v2_netbsd_form) +DEFINE_TEST(test_read_format_mtree_nonexistent_contents_file) +DEFINE_TEST(test_read_format_mtree_noprint) +DEFINE_TEST(test_read_format_mtree_crash747) +DEFINE_TEST(test_read_format_pax_bz2) +DEFINE_TEST(test_read_format_rar_set_format) +DEFINE_TEST(test_read_format_rar_basic) +DEFINE_TEST(test_read_format_rar_subblock) +DEFINE_TEST(test_read_format_rar_noeof) +DEFINE_TEST(test_read_format_rar_unicode_UTF8) +DEFINE_TEST(test_read_format_rar_unicode_CP932) +DEFINE_TEST(test_read_format_rar_compress_normal) +DEFINE_TEST(test_read_format_rar_multi_lzss_blocks) +DEFINE_TEST(test_read_format_rar_compress_best) +DEFINE_TEST(test_read_format_rar_ppmd_lzss_conversion) +DEFINE_TEST(test_read_format_rar_binary) +DEFINE_TEST(test_read_format_rar_windows) +DEFINE_TEST(test_read_format_rar_multivolume) +DEFINE_TEST(test_read_format_rar_multivolume_skip) +DEFINE_TEST(test_read_format_rar_sfx) +DEFINE_TEST(test_read_format_rar_multivolume_stored_file) +DEFINE_TEST(test_read_format_rar_multivolume_stored_file_skip) +DEFINE_TEST(test_read_format_rar_multivolume_seek_data) +DEFINE_TEST(test_read_format_rar_multivolume_seek_multiple_files) +DEFINE_TEST(test_read_format_rar_multivolume_uncompressed_files) +DEFINE_TEST(test_read_format_rar_ppmd_use_after_free) +DEFINE_TEST(test_read_format_rar_ppmd_use_after_free2) +DEFINE_TEST(test_read_format_rar5_set_format) +DEFINE_TEST(test_read_format_rar5_stored) +DEFINE_TEST(test_read_format_rar5_compressed) +DEFINE_TEST(test_read_format_rar5_multiple_files) +DEFINE_TEST(test_read_format_rar5_multiple_files_solid) +DEFINE_TEST(test_read_format_rar5_multiarchive_skip_all) +DEFINE_TEST(test_read_format_rar5_multiarchive_skip_all_but_first) +DEFINE_TEST(test_read_format_rar5_multiarchive_skip_all_but_second) +DEFINE_TEST(test_read_format_rar5_blake2) +DEFINE_TEST(test_read_format_rar5_arm_filter) +DEFINE_TEST(test_read_format_rar5_stored_skip_all) +DEFINE_TEST(test_read_format_rar5_stored_skip_in_part) +DEFINE_TEST(test_read_format_rar5_stored_skip_all_but_first) +DEFINE_TEST(test_read_format_rar5_stored_skip_all_in_part) +DEFINE_TEST(test_read_format_rar5_multiarchive_solid_extr_all) +DEFINE_TEST(test_read_format_rar5_multiarchive_solid_skip_all) +DEFINE_TEST(test_read_format_rar5_multiarchive_solid_skip_all_but_first) +DEFINE_TEST(test_read_format_rar5_multiarchive_solid_skip_all_but_scnd) +DEFINE_TEST(test_read_format_rar5_multiarchive_solid_skip_all_but_third) +DEFINE_TEST(test_read_format_rar5_multiarchive_solid_skip_all_but_last) +DEFINE_TEST(test_read_format_rar5_solid_skip_all) +DEFINE_TEST(test_read_format_rar5_solid_skip_all_but_first) +DEFINE_TEST(test_read_format_rar5_solid_skip_all_but_second) +DEFINE_TEST(test_read_format_rar5_solid_skip_all_but_last) +DEFINE_TEST(test_read_format_rar5_extract_win32) +DEFINE_TEST(test_read_format_rar5_block_by_block) +DEFINE_TEST(test_read_format_rar5_owner) +DEFINE_TEST(test_read_format_rar5_symlink) +DEFINE_TEST(test_read_format_rar5_hardlink) +DEFINE_TEST(test_read_format_rar5_extra_field_version) +DEFINE_TEST(test_read_format_rar5_readtables_overflow) +DEFINE_TEST(test_read_format_rar5_leftshift1) +DEFINE_TEST(test_read_format_rar5_leftshift2) +DEFINE_TEST(test_read_format_rar5_truncated_huff) +DEFINE_TEST(test_read_format_rar5_invalid_dict_reference) +DEFINE_TEST(test_read_format_rar5_distance_overflow) +DEFINE_TEST(test_read_format_rar5_nonempty_dir_stream) +DEFINE_TEST(test_read_format_rar5_fileattr) +DEFINE_TEST(test_read_format_rar5_different_window_size) +DEFINE_TEST(test_read_format_rar5_arm_filter_on_window_boundary) +DEFINE_TEST(test_read_format_rar5_different_solid_window_size) +DEFINE_TEST(test_read_format_rar5_different_winsize_on_merge) +DEFINE_TEST(test_read_format_rar5_block_size_is_too_small) +DEFINE_TEST(test_read_format_rar_encryption_data) +DEFINE_TEST(test_read_format_rar_encryption_header) +DEFINE_TEST(test_read_format_rar_encryption_partially) +DEFINE_TEST(test_read_format_rar_invalid1) +DEFINE_TEST(test_read_format_raw) +DEFINE_TEST(test_read_format_tar) +DEFINE_TEST(test_read_format_tar_concatenated) +DEFINE_TEST(test_read_format_tar_empty_filename) +DEFINE_TEST(test_read_format_tar_empty_pax) +DEFINE_TEST(test_read_format_tar_empty_with_gnulabel) +DEFINE_TEST(test_read_format_tar_filename) +DEFINE_TEST(test_read_format_tbz) +DEFINE_TEST(test_read_format_tgz) +DEFINE_TEST(test_read_format_tlz) +DEFINE_TEST(test_read_format_txz) +DEFINE_TEST(test_read_format_tz) +DEFINE_TEST(test_read_format_ustar_filename) +DEFINE_TEST(test_read_format_warc) +DEFINE_TEST(test_read_format_xar) +DEFINE_TEST(test_read_format_zip) +DEFINE_TEST(test_read_format_zip_ppmd_one_file) +DEFINE_TEST(test_read_format_zip_ppmd_one_file_blockread) +DEFINE_TEST(test_read_format_zip_ppmd_multi) +DEFINE_TEST(test_read_format_zip_ppmd_multi_blockread) +DEFINE_TEST(test_read_format_zip_lzma_one_file) +DEFINE_TEST(test_read_format_zip_lzma_one_file_blockread) +DEFINE_TEST(test_read_format_zip_lzma_multi) +DEFINE_TEST(test_read_format_zip_lzma_multi_blockread) +DEFINE_TEST(test_read_format_zip_bzip2_one_file) +DEFINE_TEST(test_read_format_zip_bzip2_one_file_blockread) +DEFINE_TEST(test_read_format_zip_bzip2_multi) +DEFINE_TEST(test_read_format_zip_bzip2_multi_blockread) +DEFINE_TEST(test_read_format_zip_xz_multi) +DEFINE_TEST(test_read_format_zip_xz_multi_blockread) +DEFINE_TEST(test_read_format_zip_ppmd8_crash_1) +DEFINE_TEST(test_read_format_zip_bz2_hang_on_invalid) +DEFINE_TEST(test_read_format_zip_ppmd8_crash_2) +DEFINE_TEST(test_read_format_zip_lzma_alone_leak) +DEFINE_TEST(test_read_format_zip_utf8_paths) +DEFINE_TEST(test_read_format_zip_comment_stored) +DEFINE_TEST(test_read_format_zip_encryption_data) +DEFINE_TEST(test_read_format_zip_encryption_header) +DEFINE_TEST(test_read_format_zip_encryption_partially) +DEFINE_TEST(test_read_format_zip_extra_padding) +DEFINE_TEST(test_read_format_zip_filename_CP932_eucJP) +DEFINE_TEST(test_read_format_zip_filename_CP932_UTF8) +DEFINE_TEST(test_read_format_zip_filename_UTF8_eucJP) +DEFINE_TEST(test_read_format_zip_filename_UTF8_UTF8) +DEFINE_TEST(test_read_format_zip_filename_CP866_KOI8R) +DEFINE_TEST(test_read_format_zip_filename_CP866_UTF8) +DEFINE_TEST(test_read_format_zip_filename_KOI8R_CP866) +DEFINE_TEST(test_read_format_zip_filename_KOI8R_UTF8) +DEFINE_TEST(test_read_format_zip_filename_UTF8_KOI8R) +DEFINE_TEST(test_read_format_zip_filename_UTF8_CP866) +DEFINE_TEST(test_read_format_zip_filename_UTF8_UTF8_ru) +DEFINE_TEST(test_read_format_zip_filename_CP932_CP932) +DEFINE_TEST(test_read_format_zip_filename_UTF8_CP932) +DEFINE_TEST(test_read_format_zip_filename_CP866_CP1251) +DEFINE_TEST(test_read_format_zip_filename_CP866_CP1251_win) +DEFINE_TEST(test_read_format_zip_filename_KOI8R_CP1251) +DEFINE_TEST(test_read_format_zip_filename_UTF8_CP1251) +DEFINE_TEST(test_read_format_zip_filename_KOI8R_UTF8_2) +DEFINE_TEST(test_read_format_zip_high_compression) +DEFINE_TEST(test_read_format_zip_high_compression2) +DEFINE_TEST(test_read_format_zip_jar) +DEFINE_TEST(test_read_format_zip_mac_metadata) +DEFINE_TEST(test_read_format_zip_malformed) +DEFINE_TEST(test_read_format_zip_msdos) +DEFINE_TEST(test_read_format_zip_nested) +DEFINE_TEST(test_read_format_zip_nofiletype) +DEFINE_TEST(test_read_format_zip_padded1) +DEFINE_TEST(test_read_format_zip_padded2) +DEFINE_TEST(test_read_format_zip_padded3) +DEFINE_TEST(test_read_format_zip_sfx) +DEFINE_TEST(test_read_format_zip_traditional_encryption_data) +DEFINE_TEST(test_read_format_zip_winzip_aes128) +DEFINE_TEST(test_read_format_zip_winzip_aes256) +DEFINE_TEST(test_read_format_zip_winzip_aes256_stored) +DEFINE_TEST(test_read_format_zip_winzip_aes256_large) +DEFINE_TEST(test_read_format_zip_with_invalid_traditional_eocd) +DEFINE_TEST(test_read_format_zip_zip64a) +DEFINE_TEST(test_read_format_zip_zip64b) +DEFINE_TEST(test_read_large) +DEFINE_TEST(test_schily_xattr_pax) +DEFINE_TEST(test_read_pax_truncated) +DEFINE_TEST(test_read_position) +DEFINE_TEST(test_read_set_format) +DEFINE_TEST(test_read_set_wrong_format) +DEFINE_TEST(test_read_append_filter) +DEFINE_TEST(test_read_append_wrong_filter) +DEFINE_TEST(test_read_append_filter_program) +DEFINE_TEST(test_read_append_filter_wrong_program) +DEFINE_TEST(test_read_too_many_filters) +DEFINE_TEST(test_read_truncated) +DEFINE_TEST(test_read_truncated_filter_bzip2) +DEFINE_TEST(test_read_truncated_filter_compress) +DEFINE_TEST(test_read_truncated_filter_gzip) +DEFINE_TEST(test_read_truncated_filter_lzip) +DEFINE_TEST(test_read_truncated_filter_lzma) +DEFINE_TEST(test_read_truncated_filter_lzop) +DEFINE_TEST(test_read_truncated_filter_xz) +DEFINE_TEST(test_sparse_basic) +DEFINE_TEST(test_fully_sparse_files) +DEFINE_TEST(test_tar_filenames) +DEFINE_TEST(test_tar_large) +DEFINE_TEST(test_ustar_filename_encoding_UTF8_CP866) +DEFINE_TEST(test_ustar_filename_encoding_KOI8R_UTF8) +DEFINE_TEST(test_ustar_filename_encoding_KOI8R_CP866) +DEFINE_TEST(test_ustar_filename_encoding_CP1251_UTF8) +DEFINE_TEST(test_ustar_filename_encoding_ru_RU_CP1251) +DEFINE_TEST(test_ustar_filename_encoding_Russian_Russia) +DEFINE_TEST(test_ustar_filename_encoding_EUCJP_UTF8) +DEFINE_TEST(test_ustar_filename_encoding_EUCJP_CP932) +DEFINE_TEST(test_ustar_filename_encoding_CP932_UTF8) +DEFINE_TEST(test_ustar_filenames) +DEFINE_TEST(test_warn_missing_hardlink_target) +DEFINE_TEST(test_write_disk) +DEFINE_TEST(test_write_disk_appledouble) +DEFINE_TEST(test_write_disk_failures) +DEFINE_TEST(test_write_disk_hardlink) +DEFINE_TEST(test_write_disk_hfs_compression) +DEFINE_TEST(test_write_disk_lookup) +DEFINE_TEST(test_write_disk_mac_metadata) +DEFINE_TEST(test_write_disk_no_hfs_compression) +DEFINE_TEST(test_write_disk_perms) +DEFINE_TEST(test_write_disk_secure) +DEFINE_TEST(test_write_disk_secure744) +DEFINE_TEST(test_write_disk_secure745) +DEFINE_TEST(test_write_disk_secure746a) +DEFINE_TEST(test_write_disk_secure746b) +DEFINE_TEST(test_write_disk_sparse) +DEFINE_TEST(test_write_disk_symlink) +DEFINE_TEST(test_write_disk_times) +DEFINE_TEST(test_write_filter_b64encode) +DEFINE_TEST(test_write_filter_bzip2) +DEFINE_TEST(test_write_filter_compress) +DEFINE_TEST(test_write_filter_gzip) +DEFINE_TEST(test_write_filter_gzip_timestamp) +DEFINE_TEST(test_write_filter_lrzip) +DEFINE_TEST(test_write_filter_lz4) +DEFINE_TEST(test_write_filter_lz4_disable_stream_checksum) +DEFINE_TEST(test_write_filter_lz4_enable_block_checksum) +DEFINE_TEST(test_write_filter_lz4_block_size_4) +DEFINE_TEST(test_write_filter_lz4_block_size_5) +DEFINE_TEST(test_write_filter_lz4_block_size_6) +DEFINE_TEST(test_write_filter_lz4_block_dependence) +DEFINE_TEST(test_write_filter_lzip) +DEFINE_TEST(test_write_filter_lzma) +DEFINE_TEST(test_write_filter_lzop) +DEFINE_TEST(test_write_filter_program) +DEFINE_TEST(test_write_filter_uuencode) +DEFINE_TEST(test_write_filter_xz) +DEFINE_TEST(test_write_filter_zstd) +DEFINE_TEST(test_write_format_7zip) +DEFINE_TEST(test_write_format_7zip_basic_bzip2) +DEFINE_TEST(test_write_format_7zip_basic_copy) +DEFINE_TEST(test_write_format_7zip_basic_deflate) +DEFINE_TEST(test_write_format_7zip_basic_lzma1) +DEFINE_TEST(test_write_format_7zip_basic_lzma2) +DEFINE_TEST(test_write_format_7zip_basic_ppmd) +DEFINE_TEST(test_write_format_7zip_empty_archive) +DEFINE_TEST(test_write_format_7zip_empty_files) +DEFINE_TEST(test_write_format_7zip_large_bzip2) +DEFINE_TEST(test_write_format_7zip_large_copy) +DEFINE_TEST(test_write_format_7zip_large_deflate) +DEFINE_TEST(test_write_format_7zip_large_lzma1) +DEFINE_TEST(test_write_format_7zip_large_lzma2) +DEFINE_TEST(test_write_format_7zip_large_ppmd) +DEFINE_TEST(test_write_format_ar) +DEFINE_TEST(test_write_format_cpio) +DEFINE_TEST(test_write_format_cpio_empty) +DEFINE_TEST(test_write_format_cpio_newc) +DEFINE_TEST(test_write_format_cpio_odc) +DEFINE_TEST(test_write_format_gnutar) +DEFINE_TEST(test_write_format_gnutar_filenames) +DEFINE_TEST(test_write_format_gnutar_linknames) +DEFINE_TEST(test_write_format_iso9660) +DEFINE_TEST(test_write_format_iso9660_boot) +DEFINE_TEST(test_write_format_iso9660_empty) +DEFINE_TEST(test_write_format_iso9660_filename) +DEFINE_TEST(test_write_format_iso9660_zisofs) +DEFINE_TEST(test_write_format_mtree) +DEFINE_TEST(test_write_format_mtree_no_leading_dotslash) +DEFINE_TEST(test_write_format_mtree_absolute_path) +DEFINE_TEST(test_write_format_mtree_classic) +DEFINE_TEST(test_write_format_mtree_classic_indent) +DEFINE_TEST(test_write_format_mtree_fflags) +DEFINE_TEST(test_write_format_mtree_no_separator) +DEFINE_TEST(test_write_format_mtree_quoted_filename) +DEFINE_TEST(test_write_format_pax) +DEFINE_TEST(test_write_format_raw) +DEFINE_TEST(test_write_format_raw_b64) +DEFINE_TEST(test_write_format_shar_empty) +DEFINE_TEST(test_write_format_tar) +DEFINE_TEST(test_write_format_tar_empty) +DEFINE_TEST(test_write_format_tar_sparse) +DEFINE_TEST(test_write_format_tar_ustar) +DEFINE_TEST(test_write_format_tar_v7tar) +DEFINE_TEST(test_write_format_warc) +DEFINE_TEST(test_write_format_warc_empty) +DEFINE_TEST(test_write_format_xar) +DEFINE_TEST(test_write_format_xar_empty) +DEFINE_TEST(test_write_format_zip) +DEFINE_TEST(test_write_format_zip64) +DEFINE_TEST(test_write_format_zip_traditional_pkware_encryption) +DEFINE_TEST(test_write_format_zip_winzip_aes128_encryption) +DEFINE_TEST(test_write_format_zip_winzip_aes256_encryption) +DEFINE_TEST(test_write_format_zip_compression_store) +DEFINE_TEST(test_write_format_zip_empty) +DEFINE_TEST(test_write_format_zip_empty_zip64) +DEFINE_TEST(test_write_format_zip_file) +DEFINE_TEST(test_write_format_zip_file_zip64) +DEFINE_TEST(test_write_format_zip_large) +DEFINE_TEST(test_write_format_zip_zip64_oversize) +DEFINE_TEST(test_write_open_memory) +DEFINE_TEST(test_write_read_format_zip) +DEFINE_TEST(test_write_read_format_zip_improved_streaming) +DEFINE_TEST(test_write_read_format_zip64) +DEFINE_TEST(test_write_read_format_zip64_improved_streaming) +DEFINE_TEST(test_xattr_platform) +DEFINE_TEST(test_zip_filename_encoding_UTF8) +DEFINE_TEST(test_zip_filename_encoding_KOI8R) +DEFINE_TEST(test_zip_filename_encoding_ru_RU_CP1251) +DEFINE_TEST(test_zip_filename_encoding_Russian_Russia) +DEFINE_TEST(test_zip_filename_encoding_EUCJP) +DEFINE_TEST(test_zip_filename_encoding_CP932) diff --git a/dependencies/libarchive-3.4.2/libarchive/test/read_open_memory.c b/dependencies/libarchive-3.4.2/libarchive/test/read_open_memory.c new file mode 100644 index 0000000..daa3c3a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/read_open_memory.c @@ -0,0 +1,222 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/read_open_memory.c 191183 2009-04-17 01:06:31Z kientzle $"); + +#include +#include +#include + +/* + * Read an archive from a block of memory. + * + * This is identical to archive_read_open_memory(), except + * that it goes out of its way to be a little bit unpleasant, + * in order to better test the libarchive internals. + */ + +struct read_memory_data { + const unsigned char *start; + const unsigned char *p; + const unsigned char *end; + size_t read_size; + size_t copy_buff_size; + size_t copy_buff_offset; + char *copy_buff; +}; + +static int memory_read_close(struct archive *, void *); +static int memory_read_open(struct archive *, void *); +static int64_t memory_read_seek(struct archive *, void *, int64_t request, int whence); +static int64_t memory_read_skip(struct archive *, void *, int64_t request); +static ssize_t memory_read(struct archive *, void *, const void **buff); +static int read_open_memory_internal(struct archive *a, const void *buff, + size_t size, size_t read_size, int fullapi); + + +int +read_open_memory(struct archive *a, const void *buff, size_t size, size_t read_size) +{ + return read_open_memory_internal(a, buff, size, read_size, 2); +} + +/* + * As above, but don't register any optional part of the API, to verify + * that internals work correctly with just the minimal entry points. + */ +int +read_open_memory_minimal(struct archive *a, const void *buff, size_t size, size_t read_size) +{ + return read_open_memory_internal(a, buff, size, read_size, 1); +} + +/* + * Include a seek callback as well. + */ +int +read_open_memory_seek(struct archive *a, const void *buff, size_t size, size_t read_size) +{ + return read_open_memory_internal(a, buff, size, read_size, 3); +} + +static int +read_open_memory_internal(struct archive *a, const void *buff, + size_t size, size_t read_size, int level) +{ + struct read_memory_data *mine = NULL; + + switch (level) { + case 3: + archive_read_set_seek_callback(a, memory_read_seek); + __LA_FALLTHROUGH; + case 2: + archive_read_set_open_callback(a, memory_read_open); + archive_read_set_skip_callback(a, memory_read_skip); + __LA_FALLTHROUGH; + case 1: + mine = malloc(sizeof(*mine)); + if (mine == NULL) { + archive_set_error(a, ENOMEM, "No memory"); + return (ARCHIVE_FATAL); + } + memset(mine, 0, sizeof(*mine)); + mine->start = mine->p = (const unsigned char *)buff; + mine->end = mine->start + size; + mine->read_size = read_size; + mine->copy_buff_offset = 32; + mine->copy_buff_size = read_size + mine->copy_buff_offset * 2; + mine->copy_buff = malloc(mine->copy_buff_size); + memset(mine->copy_buff, 0xA5, mine->copy_buff_size); + + archive_read_set_read_callback(a, memory_read); + archive_read_set_close_callback(a, memory_read_close); + archive_read_set_callback_data(a, mine); + } + return archive_read_open1(a); +} + +/* + * There's nothing to open. + */ +static int +memory_read_open(struct archive *a, void *client_data) +{ + (void)a; /* UNUSED */ + (void)client_data; /* UNUSED */ + return (ARCHIVE_OK); +} + +/* + * In order to exercise libarchive's internal read-combining logic, + * we deliberately copy data for each read to a separate buffer. + * That way, code that runs off the end of the provided data + * will screw up. + */ +static ssize_t +memory_read(struct archive *a, void *client_data, const void **buff) +{ + struct read_memory_data *mine = (struct read_memory_data *)client_data; + ssize_t size; + + (void)a; /* UNUSED */ + size = mine->end - mine->p; + if (size < 0) { + buff = NULL; + return 0; + } + if ((size_t)size > mine->read_size) + size = mine->read_size; + else + memset(mine->copy_buff, 0xA5, mine->copy_buff_size); + memcpy(mine->copy_buff + mine->copy_buff_offset, mine->p, size); + *buff = mine->copy_buff + mine->copy_buff_offset; + + mine->p += size; + return ((ssize_t)size); +} + +/* + * How mean can a skip() routine be? Let's try to find out. + */ +static int64_t +memory_read_skip(struct archive *a, void *client_data, int64_t skip) +{ + struct read_memory_data *mine = (struct read_memory_data *)client_data; + + (void)a; /* UNUSED */ + /* We can't skip by more than is available. */ + if ((off_t)skip > (off_t)(mine->end - mine->p)) + skip = mine->end - mine->p; + /* Always do small skips by prime amounts. */ + if (skip > 71) + skip = 71; + mine->p += skip; + return (skip); +} + +/* + */ +static int64_t +memory_read_seek(struct archive *a, void *client_data, int64_t offset, int whence) +{ + struct read_memory_data *mine = (struct read_memory_data *)client_data; + + (void)a; /* UNUSED */ + switch (whence) { + case SEEK_SET: + mine->p = mine->start + offset; + break; + case SEEK_END: + mine->p = mine->end + offset; + break; + case SEEK_CUR: + mine->p += offset; + break; + } + if (mine->p < mine->start) { + mine->p = mine->start; + return ARCHIVE_FAILED; + } + if (mine->p > mine->end) { + mine->p = mine->end; + return ARCHIVE_FAILED; + } + return (mine->p - mine->start); +} + +/* + * Close is just cleaning up our one small bit of data. + */ +static int +memory_read_close(struct archive *a, void *client_data) +{ + struct read_memory_data *mine = (struct read_memory_data *)client_data; + (void)a; /* UNUSED */ + if (mine != NULL) + free(mine->copy_buff); + free(mine); + return (ARCHIVE_OK); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test.h b/dependencies/libarchive-3.4.2/libarchive/test/test.h new file mode 100644 index 0000000..c0a0c0d --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2003-2017 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Every test program should #include "test.h" as the first thing. */ + +#define KNOWNREF "test_compat_gtar_1.tar.uu" +#define ENVBASE "LIBARCHIVE" /* Prefix for environment variables. */ +#undef PROGRAM /* Testing a library, not a program. */ +#define LIBRARY "libarchive" +#define EXTRA_DUMP(x) archive_error_string((struct archive *)(x)) +#define EXTRA_ERRNO(x) archive_errno((struct archive *)(x)) +#define EXTRA_VERSION archive_version_details() + +#if defined(__GNUC__) && (__GNUC__ >= 7) +#define __LA_FALLTHROUGH __attribute__((fallthrough)) +#else +#define __LA_FALLTHROUGH +#endif + +#include "test_common.h" diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_acl_nfs4.c b/dependencies/libarchive-3.4.2/libarchive/test/test_acl_nfs4.c new file mode 100644 index 0000000..fdc0191 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_acl_nfs4.c @@ -0,0 +1,208 @@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * Exercise the system-independent portion of the ACL support. + * Check that archive_entry objects can save and restore NFS4 ACL data. + * + * This should work on all systems, regardless of whether local + * filesystems support ACLs or not. + */ + +static struct archive_test_acl_t acls1[] = { + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_READ_DATA, + ARCHIVE_ENTRY_ACL_USER, 77, "user77" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_DATA, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_WRITE_DATA, + ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }, +}; + +static struct archive_test_acl_t acls2[] = { + /* An entry for each type. */ + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, 0, + ARCHIVE_ENTRY_ACL_USER, 108, "user108" }, + { ARCHIVE_ENTRY_ACL_TYPE_DENY, 0, + ARCHIVE_ENTRY_ACL_USER, 109, "user109" }, + { ARCHIVE_ENTRY_ACL_TYPE_AUDIT, 0, + ARCHIVE_ENTRY_ACL_USER, 110, "user110" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALARM, 0, + ARCHIVE_ENTRY_ACL_USER, 111, "user111" }, + + /* An entry for each permission. */ + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_USER, 112, "user112" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_DATA, + ARCHIVE_ENTRY_ACL_USER, 113, "user113" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, + ARCHIVE_ENTRY_ACL_USER, 114, "user114" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_DATA, + ARCHIVE_ENTRY_ACL_USER, 115, "user115" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_ADD_FILE, + ARCHIVE_ENTRY_ACL_USER, 116, "user116" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_APPEND_DATA, + ARCHIVE_ENTRY_ACL_USER, 117, "user117" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, + ARCHIVE_ENTRY_ACL_USER, 118, "user118" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, + ARCHIVE_ENTRY_ACL_USER, 119, "user119" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, + ARCHIVE_ENTRY_ACL_USER, 120, "user120" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_DELETE_CHILD, + ARCHIVE_ENTRY_ACL_USER, 121, "user121" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, + ARCHIVE_ENTRY_ACL_USER, 122, "user122" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, + ARCHIVE_ENTRY_ACL_USER, 123, "user123" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_DELETE, + ARCHIVE_ENTRY_ACL_USER, 124, "user124" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ACL, + ARCHIVE_ENTRY_ACL_USER, 125, "user125" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ACL, + ARCHIVE_ENTRY_ACL_USER, 126, "user126" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_OWNER, + ARCHIVE_ENTRY_ACL_USER, 127, "user127" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_USER, 128, "user128" }, + + /* One entry with each inheritance value. */ + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, + ARCHIVE_ENTRY_ACL_USER, 129, "user129" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, + ARCHIVE_ENTRY_ACL_USER, 130, "user130" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, + ARCHIVE_ENTRY_ACL_USER, 131, "user131" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, + ARCHIVE_ENTRY_ACL_USER, 132, "user132" }, + { ARCHIVE_ENTRY_ACL_TYPE_AUDIT, + ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, + ARCHIVE_ENTRY_ACL_USER, 133, "user133" }, + { ARCHIVE_ENTRY_ACL_TYPE_AUDIT, + ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, + ARCHIVE_ENTRY_ACL_USER, 134, "user134" }, + + /* One entry for each qualifier. */ + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_USER, 135, "user135" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_GROUP, 136, "group136" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }, +}; + +/* + * Entries that should be rejected when we attempt to set them + * on an ACL that already has NFS4 entries. + */ +static struct archive_test_acl_t acls_bad[] = { + /* POSIX.1e ACL types */ + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_USER, 78, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_USER, 78, "" }, + + /* POSIX.1e tags */ + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_OTHER, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_MASK, -1, "" }, + + /* POSIX.1e permissions */ + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE, + ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }, +}; + +DEFINE_TEST(test_acl_nfs4) +{ + struct archive_entry *ae; + int i; + + /* Create a simple archive_entry. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_pathname(ae, "file"); + archive_entry_set_mode(ae, S_IFREG | 0777); + + /* Store and read back some basic ACL entries. */ + assertEntrySetAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0])); + + /* Check that entry contains only NFSv4 types */ + assert((archive_entry_acl_types(ae) & + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) == 0); + assert((archive_entry_acl_types(ae) & + ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0); + + assertEqualInt(4, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEntryCompareAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]), + ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0); + + /* A more extensive set of ACLs. */ + assertEntrySetAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0])); + assertEqualInt(32, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEntryCompareAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]), + ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0); + + /* + * Check that clearing ACLs gets rid of them all by repeating + * the first test. + */ + assertEntrySetAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0])); + failure("Basic ACLs shouldn't be stored as extended ACLs"); + assertEqualInt(4, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + + /* + * Different types of malformed ACL entries that should + * fail when added to existing NFS4 ACLs. + */ + assertEntrySetAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0])); + for (i = 0; i < (int)(sizeof(acls_bad)/sizeof(acls_bad[0])); ++i) { + struct archive_test_acl_t *p = &acls_bad[i]; + failure("Malformed ACL test #%d", i); + assertEqualInt(ARCHIVE_FAILED, + archive_entry_acl_add_entry(ae, + p->type, p->permset, p->tag, p->qual, p->name)); + failure("Malformed ACL test #%d", i); + assertEqualInt(32, + archive_entry_acl_reset(ae, + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + } + archive_entry_free(ae); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_acl_pax.c b/dependencies/libarchive-3.4.2/libarchive/test/test_acl_pax.c new file mode 100644 index 0000000..8566f55 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_acl_pax.c @@ -0,0 +1,415 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2016 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * Exercise the system-independent portion of the ACL support. + * Check that pax archive can save and restore POSIX.1e ACL data. + * + * This should work on all systems, regardless of whether local + * filesystems support ACLs or not. + */ + +static unsigned char buff[16384]; + +static struct archive_test_acl_t acls0[] = { + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_USER_OBJ, 0, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_WRITE, + ARCHIVE_ENTRY_ACL_OTHER, 0, "" }, +}; + +static struct archive_test_acl_t acls1[] = { + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_USER, 77, "user77" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_WRITE, + ARCHIVE_ENTRY_ACL_OTHER, -1, "" }, +}; + +static struct archive_test_acl_t acls2[] = { + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE | ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_USER, 77, "user77" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0, + ARCHIVE_ENTRY_ACL_USER, 78, "user78" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0007, + ARCHIVE_ENTRY_ACL_GROUP, 78, "group78" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_OTHER, -1, "" }, +}; + +static struct archive_test_acl_t acls3[] = { + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_APPEND_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_WRITE_ACL | + ARCHIVE_ENTRY_ACL_WRITE_OWNER | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_USER_OBJ, 0, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_APPEND_DATA | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_EVERYONE, 0, "" }, +}; + +static struct archive_test_acl_t acls4[] = { + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_APPEND_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_WRITE_ACL | + ARCHIVE_ENTRY_ACL_WRITE_OWNER | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_USER_OBJ, 0, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE | + ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, + ARCHIVE_ENTRY_ACL_USER, 77, "user77" }, + { ARCHIVE_ENTRY_ACL_TYPE_DENY, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_USER, 78, "user78" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_APPEND_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_DENY, + ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_APPEND_DATA | + ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_WRITE_ACL | + ARCHIVE_ENTRY_ACL_WRITE_OWNER, + ARCHIVE_ENTRY_ACL_GROUP, 78, "group78" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_EVERYONE, 0, "" }, +}; + +static struct archive_test_acl_t acls5[] = { + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_APPEND_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_WRITE_ACL | + ARCHIVE_ENTRY_ACL_WRITE_OWNER | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_USER_OBJ, 0, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_APPEND_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_WRITE_OWNER | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_USER, 77, "user77" }, + { ARCHIVE_ENTRY_ACL_TYPE_AUDIT, + ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_APPEND_DATA | + ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, + ARCHIVE_ENTRY_ACL_USER, 77, "user77" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_APPEND_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALARM, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, + ARCHIVE_ENTRY_ACL_GROUP, 78, "group78" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_EVERYONE, 0, "" }, +}; + +DEFINE_TEST(test_acl_pax_posix1e) +{ + struct archive *a; + struct archive_entry *ae; + size_t used; + FILE *f; + void *reference; + size_t reference_size; + + /* Write an archive to memory. */ + assert(NULL != (a = archive_write_new())); + assertA(0 == archive_write_set_format_pax(a)); + assertA(0 == archive_write_add_filter_none(a)); + assertA(0 == archive_write_set_bytes_per_block(a, 1)); + assertA(0 == archive_write_set_bytes_in_last_block(a, 1)); + assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used)); + + /* Write a series of files to the archive with different ACL info. */ + + /* Create a simple archive_entry. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_pathname(ae, "file"); + archive_entry_set_mode(ae, S_IFREG | 0777); + + /* Basic owner/owning group should just update mode bits. */ + assertEntrySetAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0])); + assertA(0 == archive_write_header(a, ae)); + + /* With any extended ACL entry, we should read back a full set. */ + assertEntrySetAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0])); + assertA(0 == archive_write_header(a, ae)); + + /* A more extensive set of ACLs. */ + assertEntrySetAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0])); + assertA(0 == archive_write_header(a, ae)); + + /* + * Check that clearing ACLs gets rid of them all by repeating + * the first test. + */ + assertEntrySetAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0])); + assertA(0 == archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Write out the data we generated to a file for manual inspection. */ + assert(NULL != (f = fopen("testout", "wb"))); + assertEqualInt(used, (size_t)fwrite(buff, 1, (unsigned int)used, f)); + fclose(f); + + /* Write out the reference data to a file for manual inspection. */ + extract_reference_file("test_acl_pax_posix1e.tar"); + reference = slurpfile(&reference_size, "test_acl_pax_posix1e.tar"); + + /* Assert that the generated data matches the built-in reference data.*/ + failure("Generated pax archive does not match reference; compare 'testout' to 'test_acl_pax_posix1e.tar' reference file."); + assertEqualMem(buff, reference, reference_size); + failure("Generated pax archive does not match reference; compare 'testout' to 'test_acl_pax_posix1e.tar' reference file."); + assertEqualInt((int)used, reference_size); + free(reference); + + /* Read back each entry and check that the ACL data is right. */ + assert(NULL != (a = archive_read_new())); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_open_memory(a, buff, used)); + + /* First item has no ACLs */ + assertA(0 == archive_read_next_header(a, &ae)); + failure("Basic ACLs shouldn't be stored as extended ACLs"); + assert(0 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + failure("Basic ACLs should set mode to 0142, not %04o", + archive_entry_mode(ae)&0777); + assert((archive_entry_mode(ae) & 0777) == 0142); + + /* Second item has a few ACLs */ + assertA(0 == archive_read_next_header(a, &ae)); + failure("One extended ACL should flag all ACLs to be returned."); + assert(4 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEntryCompareAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]), + ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0142); + failure("Basic ACLs should set mode to 0142, not %04o", + archive_entry_mode(ae)&0777); + assert((archive_entry_mode(ae) & 0777) == 0142); + + /* Third item has pretty extensive ACLs */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualInt(6, archive_entry_acl_reset(ae, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEntryCompareAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]), + ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0543); + failure("Basic ACLs should set mode to 0543, not %04o", + archive_entry_mode(ae)&0777); + assert((archive_entry_mode(ae) & 0777) == 0543); + + /* Fourth item has no ACLs */ + assertA(0 == archive_read_next_header(a, &ae)); + failure("Basic ACLs shouldn't be stored as extended ACLs"); + assert(0 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + failure("Basic ACLs should set mode to 0142, not %04o", + archive_entry_mode(ae)&0777); + assert((archive_entry_mode(ae) & 0777) == 0142); + + /* Close the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_acl_pax_nfs4) +{ + struct archive *a; + struct archive_entry *ae; + size_t used; + FILE *f; + void *reference; + size_t reference_size; + + /* Write an archive to memory. */ + assert(NULL != (a = archive_write_new())); + assertA(0 == archive_write_set_format_pax(a)); + assertA(0 == archive_write_add_filter_none(a)); + assertA(0 == archive_write_set_bytes_per_block(a, 1)); + assertA(0 == archive_write_set_bytes_in_last_block(a, 1)); + assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used)); + + /* Write a series of files to the archive with different ACL info. */ + + /* Create a simple archive_entry. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_pathname(ae, "file"); + archive_entry_set_mode(ae, S_IFREG | 0777); + + /* NFS4 ACLs mirroring 0754 file mode */ + assertEntrySetAcls(ae, acls3, sizeof(acls3)/sizeof(acls3[0])); + assertA(0 == archive_write_header(a, ae)); + + /* A more extensive set of NFS4 ACLs. */ + assertEntrySetAcls(ae, acls4, sizeof(acls4)/sizeof(acls4[0])); + assertA(0 == archive_write_header(a, ae)); + + /* Set with special (audit, alarm) NFS4 ACLs. */ + assertEntrySetAcls(ae, acls5, sizeof(acls5)/sizeof(acls5[0])); + assertA(0 == archive_write_header(a, ae)); + + archive_entry_free(ae); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Write out the data we generated to a file for manual inspection. */ + assert(NULL != (f = fopen("testout", "wb"))); + assertEqualInt(used, (size_t)fwrite(buff, 1, (unsigned int)used, f)); + fclose(f); + + /* Write out the reference data to a file for manual inspection. */ + extract_reference_file("test_acl_pax_nfs4.tar"); + reference = slurpfile(&reference_size, "test_acl_pax_nfs4.tar"); + + /* Assert that the generated data matches the built-in reference data.*/ + failure("Generated pax archive does not match reference; compare 'testout' to 'test_acl_pax_nfs4.tar' reference file."); + assertEqualMem(buff, reference, reference_size); + failure("Generated pax archive does not match reference; compare 'testout' to 'test_acl_pax_nfs4.tar' reference file."); + assertEqualInt((int)used, reference_size); + free(reference); + + /* Read back each entry and check that the ACL data is right. */ + assert(NULL != (a = archive_read_new())); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_open_memory(a, buff, used)); + + /* First item has NFS4 ACLs mirroring file mode */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualInt(3, archive_entry_acl_reset(ae, + ARCHIVE_ENTRY_ACL_TYPE_ALLOW)); + assertEntryCompareAcls(ae, acls3, sizeof(acls3)/sizeof(acls3[0]), + ARCHIVE_ENTRY_ACL_TYPE_ALLOW, 0); + + /* Second item has has more fine-grained NFS4 ACLs */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualInt(6, archive_entry_acl_reset(ae, + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEntryCompareAcls(ae, acls4, sizeof(acls4)/sizeof(acls4[0]), + ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0); + + /* Third item has has audit and alarm NFS4 ACLs */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualInt(6, archive_entry_acl_reset(ae, + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEntryCompareAcls(ae, acls5, sizeof(acls5)/sizeof(acls5[0]), + ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0); + + /* Close the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_acl_pax_nfs4.tar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_acl_pax_nfs4.tar.uu new file mode 100644 index 0000000..ffc5cc2 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_acl_pax_nfs4.tar.uu @@ -0,0 +1,129 @@ +begin 644 test_acl_pax_nfs4.tar +M4&%X2&5A9&5R+V9I;&4````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````#`P,#``````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````!U``````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````!U#HZ9&5N>3HW."QG``````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````````````!U +M'!A05)78T-O"QG +#endif +#if HAVE_SYS_RICHACL_H +#include +#endif +#if HAVE_MEMBERSHIP_H +#include +#endif + +struct myacl_t { + int type; + int permset; + int tag; + int qual; /* GID or UID of user/group, depending on tag. */ + const char *name; /* Name of user/group, depending on tag. */ +}; + +static struct myacl_t acls_reg[] = { +#if !ARCHIVE_ACL_DARWIN + /* For this test, we need the file owner to be able to read and write the ACL. */ + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_READ_ACL | ARCHIVE_ENTRY_ACL_WRITE_ACL | ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, + ARCHIVE_ENTRY_ACL_USER_OBJ, -1, ""}, +#endif + /* An entry for each type. */ + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_USER, 108, "user108" }, + { ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_USER, 109, "user109" }, + + /* An entry for each permission. */ + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_USER, 112, "user112" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_DATA, + ARCHIVE_ENTRY_ACL_USER, 113, "user113" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_DATA, + ARCHIVE_ENTRY_ACL_USER, 115, "user115" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_APPEND_DATA, + ARCHIVE_ENTRY_ACL_USER, 117, "user117" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, + ARCHIVE_ENTRY_ACL_USER, 119, "user119" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, + ARCHIVE_ENTRY_ACL_USER, 120, "user120" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, + ARCHIVE_ENTRY_ACL_USER, 122, "user122" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, + ARCHIVE_ENTRY_ACL_USER, 123, "user123" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_DELETE, + ARCHIVE_ENTRY_ACL_USER, 124, "user124" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ACL, + ARCHIVE_ENTRY_ACL_USER, 125, "user125" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ACL, + ARCHIVE_ENTRY_ACL_USER, 126, "user126" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_OWNER, + ARCHIVE_ENTRY_ACL_USER, 127, "user127" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_USER, 128, "user128" }, + + /* One entry for each qualifier. */ + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_USER, 135, "user135" }, +// { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE, +// ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_GROUP, 136, "group136" }, +#if !ARCHIVE_ACL_DARWIN + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" } +#else /* MacOS - mode 0654 */ + { ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_APPEND_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_WRITE_ACL | + ARCHIVE_ENTRY_ACL_WRITE_OWNER | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" } +#endif +}; + +static const int acls_reg_cnt = (int)(sizeof(acls_reg)/sizeof(acls_reg[0])); + +static struct myacl_t acls_dir[] = { + /* For this test, we need to be able to read and write the ACL. */ +#if !ARCHIVE_ACL_DARWIN + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_READ_ACL, + ARCHIVE_ENTRY_ACL_USER_OBJ, -1, ""}, +#endif + + /* An entry for each type. */ + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, + ARCHIVE_ENTRY_ACL_USER, 101, "user101" }, + { ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, + ARCHIVE_ENTRY_ACL_USER, 102, "user102" }, + + /* An entry for each permission. */ + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, + ARCHIVE_ENTRY_ACL_USER, 201, "user201" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_ADD_FILE, + ARCHIVE_ENTRY_ACL_USER, 202, "user202" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, + ARCHIVE_ENTRY_ACL_USER, 203, "user203" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, + ARCHIVE_ENTRY_ACL_USER, 204, "user204" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, + ARCHIVE_ENTRY_ACL_USER, 205, "user205" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_DELETE_CHILD, + ARCHIVE_ENTRY_ACL_USER, 206, "user206" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, + ARCHIVE_ENTRY_ACL_USER, 207, "user207" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, + ARCHIVE_ENTRY_ACL_USER, 208, "user208" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_DELETE, + ARCHIVE_ENTRY_ACL_USER, 209, "user209" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ACL, + ARCHIVE_ENTRY_ACL_USER, 210, "user210" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ACL, + ARCHIVE_ENTRY_ACL_USER, 211, "user211" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_OWNER, + ARCHIVE_ENTRY_ACL_USER, 212, "user212" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_USER, 213, "user213" }, + + /* One entry with each inheritance value. */ + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, + ARCHIVE_ENTRY_ACL_USER, 301, "user301" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, + ARCHIVE_ENTRY_ACL_USER, 302, "user302" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT | + ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, + ARCHIVE_ENTRY_ACL_USER, 303, "user303" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT | + ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, + ARCHIVE_ENTRY_ACL_USER, 304, "user304" }, +#if !defined(ARCHIVE_ACL_SUNOS_NFS4) || defined(ACE_INHERITED_ACE) + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, + ARCHIVE_ENTRY_ACL_USER, 305, "user305" }, +#endif + +#if 0 + /* FreeBSD does not support audit entries. */ + { ARCHIVE_ENTRY_ACL_TYPE_AUDIT, + ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, + ARCHIVE_ENTRY_ACL_USER, 401, "user401" }, + { ARCHIVE_ENTRY_ACL_TYPE_AUDIT, + ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, + ARCHIVE_ENTRY_ACL_USER, 402, "user402" }, +#endif + + /* One entry for each qualifier. */ + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, + ARCHIVE_ENTRY_ACL_USER, 501, "user501" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, + ARCHIVE_ENTRY_ACL_GROUP, 502, "group502" }, +#if !ARCHIVE_ACL_DARWIN + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, + ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" } +#else /* MacOS - mode 0654 */ + { ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_APPEND_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_WRITE_ACL | + ARCHIVE_ENTRY_ACL_WRITE_OWNER | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" } +#endif +}; + +static const int acls_dir_cnt = (int)(sizeof(acls_dir)/sizeof(acls_dir[0])); + +static void +set_acls(struct archive_entry *ae, struct myacl_t *acls, int start, int end) +{ + int i; + + archive_entry_acl_clear(ae); +#if !ARCHIVE_ACL_DARWIN + if (start > 0) { + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_add_entry(ae, + acls[0].type, acls[0].permset, acls[0].tag, + acls[0].qual, acls[0].name)); + } +#endif + for (i = start; i < end; i++) { + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_add_entry(ae, + acls[i].type, acls[i].permset, acls[i].tag, + acls[i].qual, acls[i].name)); + } +} + +static int +#if ARCHIVE_ACL_SUNOS_NFS4 +acl_permset_to_bitmap(uint32_t mask) +#elif ARCHIVE_ACL_LIBRICHACL +acl_permset_to_bitmap(unsigned int mask) +#else +acl_permset_to_bitmap(acl_permset_t opaque_ps) +#endif +{ + static struct { int portable; int machine; } perms[] = { +#ifdef ARCHIVE_ACL_SUNOS_NFS4 /* Solaris NFSv4 ACL permissions */ + {ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE}, + {ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA}, + {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY}, + {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE}, + {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY}, + {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD}, + {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE}, + {ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER}, + {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE} +#elif ARCHIVE_ACL_DARWIN /* MacOS NFSv4 ACL permissions */ + {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA}, + {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY}, + {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE}, + {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, + {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE}, + {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY}, + {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD}, + {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY}, + {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY}, + {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER}, +#if HAVE_DECL_ACL_SYNCHRONIZE + {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE} +#endif +#elif ARCHIVE_ACL_LIBRICHACL + {ARCHIVE_ENTRY_ACL_EXECUTE, RICHACE_EXECUTE}, + {ARCHIVE_ENTRY_ACL_READ_DATA, RICHACE_READ_DATA}, + {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, RICHACE_LIST_DIRECTORY}, + {ARCHIVE_ENTRY_ACL_WRITE_DATA, RICHACE_WRITE_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_FILE, RICHACE_ADD_FILE}, + {ARCHIVE_ENTRY_ACL_APPEND_DATA, RICHACE_APPEND_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, RICHACE_ADD_SUBDIRECTORY}, + {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, RICHACE_READ_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, RICHACE_WRITE_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_DELETE_CHILD, RICHACE_DELETE_CHILD}, + {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, RICHACE_READ_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, RICHACE_WRITE_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_DELETE, RICHACE_DELETE}, + {ARCHIVE_ENTRY_ACL_READ_ACL, RICHACE_READ_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_ACL, RICHACE_WRITE_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_OWNER, RICHACE_WRITE_OWNER}, + {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, RICHACE_SYNCHRONIZE} +#else /* FreeBSD NFSv4 ACL permissions */ + {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, + {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA}, + {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY}, + {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE}, + {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY}, + {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD}, + {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE}, + {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER}, + {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE} +#endif + }; + int i, permset = 0; + + for (i = 0; i < (int)(sizeof(perms)/sizeof(perms[0])); ++i) +#if ARCHIVE_ACL_SUNOS_NFS4 || ARCHIVE_ACL_LIBRICHACL + if (mask & perms[i].machine) +#else + if (acl_get_perm_np(opaque_ps, perms[i].machine)) +#endif + permset |= perms[i].portable; + return permset; +} + +static int +#if ARCHIVE_ACL_SUNOS_NFS4 +acl_flagset_to_bitmap(uint16_t flags) +#elif ARCHIVE_ACL_LIBRICHACL +acl_flagset_to_bitmap(int flags) +#else +acl_flagset_to_bitmap(acl_flagset_t opaque_fs) +#endif +{ + static struct { int portable; int machine; } perms[] = { +#if ARCHIVE_ACL_SUNOS_NFS4 /* Solaris NFSv4 ACL inheritance flags */ + {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG}, + {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG}, +#ifdef ACE_INHERITED_ACE + {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE} +#endif +#elif ARCHIVE_ACL_DARWIN /* MacOS NFSv4 ACL inheritance flags */ + {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}, + {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT} +#elif ARCHIVE_ACL_LIBRICHACL + {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, RICHACE_FILE_INHERIT_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, RICHACE_DIRECTORY_INHERIT_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, RICHACE_NO_PROPAGATE_INHERIT_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, RICHACE_INHERIT_ONLY_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, RICHACE_INHERITED_ACE} +#else /* FreeBSD NFSv4 ACL inheritance flags */ +#ifdef ACL_ENTRY_INHERITED + {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}, +#endif + {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS}, + {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS}, + {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY} +#endif + }; + int i, flagset = 0; + + for (i = 0; i < (int)(sizeof(perms)/sizeof(perms[0])); ++i) +#if ARCHIVE_ACL_SUNOS_NFS4 || ARCHIVE_ACL_LIBRICHACL + if (flags & perms[i].machine) +#else + if (acl_get_flag_np(opaque_fs, perms[i].machine)) +#endif + flagset |= perms[i].portable; + return flagset; +} + +#if ARCHIVE_ACL_SUNOS_NFS4 +static int +acl_match(ace_t *ace, struct myacl_t *myacl) +{ + int perms; + + perms = acl_permset_to_bitmap(ace->a_access_mask) | acl_flagset_to_bitmap(ace->a_flags); + + if (perms != myacl->permset) + return (0); + + switch (ace->a_type) { + case ACE_ACCESS_ALLOWED_ACE_TYPE: + if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW) + return (0); + break; + case ACE_ACCESS_DENIED_ACE_TYPE: + if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_DENY) + return (0); + break; + case ACE_SYSTEM_AUDIT_ACE_TYPE: + if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_AUDIT) + return (0); + break; + case ACE_SYSTEM_ALARM_ACE_TYPE: + if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALARM) + return (0); + break; + default: + return (0); + } + + if (ace->a_flags & ACE_OWNER) { + if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) + return (0); + } else if (ace->a_flags & ACE_GROUP) { + if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) + return (0); + } else if (ace->a_flags & ACE_EVERYONE) { + if (myacl->tag != ARCHIVE_ENTRY_ACL_EVERYONE) + return (0); + } else if (ace->a_flags & ACE_IDENTIFIER_GROUP) { + if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP) + return (0); + if ((gid_t)myacl->qual != ace->a_who) + return (0); + } else { + if (myacl->tag != ARCHIVE_ENTRY_ACL_USER) + return (0); + if ((uid_t)myacl->qual != ace->a_who) + return (0); + } + return (1); +} +#elif ARCHIVE_ACL_LIBRICHACL +static int +acl_match(struct richace *richace, struct myacl_t *myacl) +{ + int perms; + + perms = acl_permset_to_bitmap(richace->e_mask) | + acl_flagset_to_bitmap(richace->e_flags); + + if (perms != myacl->permset) + return (0); + + switch (richace->e_type) { + case RICHACE_ACCESS_ALLOWED_ACE_TYPE: + if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW) + return (0); + break; + case RICHACE_ACCESS_DENIED_ACE_TYPE: + if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_DENY) + return (0); + break; + default: + return (0); + } + + if (richace->e_flags & RICHACE_SPECIAL_WHO) { + switch (richace->e_id) { + case RICHACE_OWNER_SPECIAL_ID: + if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) + return (0); + break; + case RICHACE_GROUP_SPECIAL_ID: + if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) + return (0); + break; + case RICHACE_EVERYONE_SPECIAL_ID: + if (myacl->tag != ARCHIVE_ENTRY_ACL_EVERYONE) + return (0); + break; + default: + /* Invalid e_id */ + return (0); + } + } else if (richace->e_flags & RICHACE_IDENTIFIER_GROUP) { + if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP) + return (0); + if ((gid_t)myacl->qual != richace->e_id) + return (0); + } else { + if (myacl->tag != ARCHIVE_ENTRY_ACL_USER) + return (0); + if ((uid_t)myacl->qual != richace->e_id) + return (0); + } + return (1); +} +#elif ARCHIVE_ACL_DARWIN +static int +acl_match(acl_entry_t aclent, struct myacl_t *myacl) +{ + void *q; + uid_t ugid; + int r, idtype; + acl_tag_t tag_type; + acl_permset_t opaque_ps; + acl_flagset_t opaque_fs; + int perms; + + acl_get_tag_type(aclent, &tag_type); + + /* translate the silly opaque permset to a bitmap */ + acl_get_permset(aclent, &opaque_ps); + acl_get_flagset_np(aclent, &opaque_fs); + perms = acl_permset_to_bitmap(opaque_ps) | acl_flagset_to_bitmap(opaque_fs); + if (perms != myacl->permset) + return (0); + + r = 0; + switch (tag_type) { + case ACL_EXTENDED_ALLOW: + if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW) + return (0); + break; + case ACL_EXTENDED_DENY: + if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_DENY) + return (0); + break; + default: + return (0); + } + q = acl_get_qualifier(aclent); + if (q == NULL) + return (0); + r = mbr_uuid_to_id((const unsigned char *)q, &ugid, &idtype); + acl_free(q); + if (r != 0) + return (0); + switch (idtype) { + case ID_TYPE_UID: + if (myacl->tag != ARCHIVE_ENTRY_ACL_USER) + return (0); + if ((uid_t)myacl->qual != ugid) + return (0); + break; + case ID_TYPE_GID: + if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP) + return (0); + if ((gid_t)myacl->qual != ugid) + return (0); + break; + default: + return (0); + } + return (1); +} +#else /* ARCHIVE_ACL_FREEBSD_NFS4 */ +static int +acl_match(acl_entry_t aclent, struct myacl_t *myacl) +{ + gid_t g, *gp; + uid_t u, *up; + acl_entry_type_t entry_type; + acl_tag_t tag_type; + acl_permset_t opaque_ps; + acl_flagset_t opaque_fs; + int perms; + + acl_get_tag_type(aclent, &tag_type); + acl_get_entry_type_np(aclent, &entry_type); + + /* translate the silly opaque permset to a bitmap */ + acl_get_permset(aclent, &opaque_ps); + acl_get_flagset_np(aclent, &opaque_fs); + perms = acl_permset_to_bitmap(opaque_ps) | acl_flagset_to_bitmap(opaque_fs); + if (perms != myacl->permset) + return (0); + + switch (entry_type) { + case ACL_ENTRY_TYPE_ALLOW: + if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW) + return (0); + break; + case ACL_ENTRY_TYPE_DENY: + if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_DENY) + return (0); + break; + case ACL_ENTRY_TYPE_AUDIT: + if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_AUDIT) + return (0); + case ACL_ENTRY_TYPE_ALARM: + if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALARM) + return (0); + default: + return (0); + } + + switch (tag_type) { + case ACL_USER_OBJ: + if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0); + break; + case ACL_USER: + if (myacl->tag != ARCHIVE_ENTRY_ACL_USER) + return (0); + up = acl_get_qualifier(aclent); + u = *up; + acl_free(up); + if ((uid_t)myacl->qual != u) + return (0); + break; + case ACL_GROUP_OBJ: + if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (0); + break; + case ACL_GROUP: + if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP) + return (0); + gp = acl_get_qualifier(aclent); + g = *gp; + acl_free(gp); + if ((gid_t)myacl->qual != g) + return (0); + break; + case ACL_MASK: + if (myacl->tag != ARCHIVE_ENTRY_ACL_MASK) return (0); + break; + case ACL_EVERYONE: + if (myacl->tag != ARCHIVE_ENTRY_ACL_EVERYONE) return (0); + break; + } + return (1); +} +#endif /* various ARCHIVE_ACL_NFS4 implementations */ + +static void +compare_acls( +#if ARCHIVE_ACL_SUNOS_NFS4 + void *aclp, + int aclcnt, +#elif ARCHIVE_ACL_LIBRICHACL + struct richacl *richacl, +#else + acl_t acl, +#endif + struct myacl_t *myacls, const char *filename, int start, int end) +{ + int *marker; + int matched; + int i, n; +#if ARCHIVE_ACL_SUNOS_NFS4 + int e; + ace_t *acl_entry; +#elif ARCHIVE_ACL_LIBRICHACL + int e; + struct richace *acl_entry; + int aclcnt; +#else + int entry_id = ACL_FIRST_ENTRY; + acl_entry_t acl_entry; +#if ARCHIVE_ACL_DARWIN + const int acl_get_entry_ret = 0; +#else + const int acl_get_entry_ret = 1; +#endif +#endif + +#if ARCHIVE_ACL_SUNOS_NFS4 + if (aclp == NULL) + return; +#elif ARCHIVE_ACL_LIBRICHACL + if (richacl == NULL) + return; + aclcnt = richacl->a_count; +#else + if (acl == NULL) + return; +#endif + + n = end - start; + marker = malloc(sizeof(marker[0]) * (n + 1)); + for (i = 0; i < n; i++) + marker[i] = i + start; +#if !ARCHIVE_ACL_DARWIN + /* Always include the first ACE. */ + if (start > 0) { + marker[n] = 0; + ++n; + } +#endif + + /* + * Iterate over acls in system acl object, try to match each + * one with an item in the myacls array. + */ +#if ARCHIVE_ACL_SUNOS_NFS4 || ARCHIVE_ACL_LIBRICHACL + for (e = 0; e < aclcnt; e++) +#else + while (acl_get_entry_ret == acl_get_entry(acl, entry_id, &acl_entry)) +#endif + { +#if ARCHIVE_ACL_SUNOS_NFS4 + acl_entry = &((ace_t *)aclp)[e]; +#elif ARCHIVE_ACL_LIBRICHACL + acl_entry = &(richacl->a_entries[e]); +#else + /* After the first time... */ + entry_id = ACL_NEXT_ENTRY; +#endif + /* Search for a matching entry (tag and qualifier) */ + for (i = 0, matched = 0; i < n && !matched; i++) { + if (acl_match(acl_entry, &myacls[marker[i]])) { + /* We found a match; remove it. */ + marker[i] = marker[n - 1]; + n--; + matched = 1; + } + } + + failure("ACL entry on file %s that shouldn't be there", + filename); + assert(matched == 1); + } + + /* Dump entries in the myacls array that weren't in the system acl. */ + for (i = 0; i < n; ++i) { + failure(" ACL entry %d missing from %s: " + "type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s''\n", + marker[i], filename, + myacls[marker[i]].type, myacls[marker[i]].permset, + myacls[marker[i]].tag, myacls[marker[i]].qual, + myacls[marker[i]].name); + assert(0); /* Record this as a failure. */ + } + free(marker); +} + +static void +compare_entry_acls(struct archive_entry *ae, struct myacl_t *myacls, const char *filename, int start, int end) +{ + int *marker; + int matched; + int i, n; + int type, permset, tag, qual; + const char *name; + + /* Count ACL entries in myacls array and allocate an indirect array. */ + n = end - start; + marker = malloc(sizeof(marker[0]) * (n + 1)); + for (i = 0; i < n; i++) + marker[i] = i + start; + /* Always include the first ACE. */ + if (start > 0) { + marker[n] = 0; + ++n; + } + + /* + * Iterate over acls in entry, try to match each + * one with an item in the myacls array. + */ + assertEqualInt(n, archive_entry_acl_reset(ae, + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + while (ARCHIVE_OK == archive_entry_acl_next(ae, + ARCHIVE_ENTRY_ACL_TYPE_NFS4, &type, &permset, &tag, &qual, &name)) { + + /* Search for a matching entry (tag and qualifier) */ + for (i = 0, matched = 0; i < n && !matched; i++) { + if (tag == myacls[marker[i]].tag + && qual == myacls[marker[i]].qual + && permset == myacls[marker[i]].permset + && type == myacls[marker[i]].type) { + /* We found a match; remove it. */ + marker[i] = marker[n - 1]; + n--; + matched = 1; + } + } + + failure("ACL entry on file that shouldn't be there: " + "type=%#010x,permset=%#010x,tag=%d,qual=%d", + type,permset,tag,qual); + assert(matched == 1); + } + + /* Dump entries in the myacls array that weren't in the system acl. */ + for (i = 0; i < n; ++i) { + failure(" ACL entry %d missing from %s: " + "type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s''\n", + marker[i], filename, + myacls[marker[i]].type, myacls[marker[i]].permset, + myacls[marker[i]].tag, myacls[marker[i]].qual, + myacls[marker[i]].name); + assert(0); /* Record this as a failure. */ + } + free(marker); +} +#endif /* ARCHIVE_ACL_NFS4 */ + +/* + * Verify ACL restore-to-disk. This test is Platform-specific. + */ + +DEFINE_TEST(test_acl_platform_nfs4) +{ +#if !ARCHIVE_ACL_NFS4 + skipping("NFS4 ACLs are not supported on this platform"); +#else /* ARCHIVE_ACL_NFS4 */ + char buff[64]; + int i; + struct stat st; + struct archive *a; + struct archive_entry *ae; +#if ARCHIVE_ACL_DARWIN /* On MacOS we skip trivial ACLs in some tests */ + const int regcnt = acls_reg_cnt - 4; + const int dircnt = acls_dir_cnt - 4; +#else + const int regcnt = acls_reg_cnt; + const int dircnt = acls_dir_cnt; +#endif +#if ARCHIVE_ACL_SUNOS_NFS4 + void *aclp; + int aclcnt; +#elif ARCHIVE_ACL_LIBRICHACL + struct richacl *richacl; +#else /* !ARCHIVE_ACL_SUNOS_NFS4 */ + acl_t acl; +#endif + + assertMakeFile("pretest", 0644, "a"); + + if (setTestAcl("pretest") != ARCHIVE_TEST_ACL_TYPE_NFS4) { + skipping("NFS4 ACLs are not writable on this filesystem"); + return; + } + + /* Create a write-to-disk object. */ + assert(NULL != (a = archive_write_disk_new())); + archive_write_disk_set_options(a, + ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL); + + /* Populate an archive entry with some metadata, including ACL info */ + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_pathname(ae, "testall"); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_perm(ae, 0654); + archive_entry_set_mtime(ae, 123456, 7890); + archive_entry_set_size(ae, 0); + set_acls(ae, acls_reg, 0, acls_reg_cnt); + + /* Write the entry to disk, including ACLs. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + + /* Likewise for a dir. */ + archive_entry_set_pathname(ae, "dirall"); + archive_entry_set_filetype(ae, AE_IFDIR); + archive_entry_set_perm(ae, 0654); + archive_entry_set_mtime(ae, 123456, 7890); + set_acls(ae, acls_dir, 0, acls_dir_cnt); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + + for (i = 0; i < acls_dir_cnt; ++i) { + sprintf(buff, "dir%d", i); + archive_entry_set_pathname(ae, buff); + archive_entry_set_filetype(ae, AE_IFDIR); + archive_entry_set_perm(ae, 0654); + archive_entry_set_mtime(ae, 123456 + i, 7891 + i); + set_acls(ae, acls_dir, i, i + 1); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + } + + archive_entry_free(ae); + + /* Close the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Verify the data on disk. */ + assertEqualInt(0, stat("testall", &st)); + assertEqualInt(st.st_mtime, 123456); +#if ARCHIVE_ACL_SUNOS_NFS4 + aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, "testall"); + failure("acl(\"%s\"): errno = %d (%s)", "testall", errno, + strerror(errno)); + assert(aclp != NULL); +#elif ARCHIVE_ACL_LIBRICHACL + richacl = richacl_get_file("testall"); + failure("richacl_get_file(\"%s\"): errno = %d (%s)", "testall", errno, + strerror(errno)); + assert(richacl != NULL); +#else +#if ARCHIVE_ACL_DARWIN + acl = acl_get_file("testall", ACL_TYPE_EXTENDED); +#else + acl = acl_get_file("testall", ACL_TYPE_NFS4); +#endif + failure("acl_get_file(\"%s\"): errno = %d (%s)", "testall", errno, + strerror(errno)); + assert(acl != (acl_t)NULL); +#endif +#if ARCHIVE_ACL_SUNOS_NFS4 + compare_acls(aclp, aclcnt, acls_reg, "testall", 0, regcnt); + free(aclp); + aclp = NULL; +#elif ARCHIVE_ACL_LIBRICHACL + compare_acls(richacl, acls_reg, "testall", 0, regcnt); + richacl_free(richacl); +#else + compare_acls(acl, acls_reg, "testall", 0, regcnt); + acl_free(acl); +#endif + + + /* Verify single-permission dirs on disk. */ + for (i = 0; i < dircnt; ++i) { + sprintf(buff, "dir%d", i); + assertEqualInt(0, stat(buff, &st)); + assertEqualInt(st.st_mtime, 123456 + i); +#if ARCHIVE_ACL_SUNOS_NFS4 + aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, buff); + failure("acl(\"%s\"): errno = %d (%s)", buff, errno, + strerror(errno)); + assert(aclp != NULL); +#elif ARCHIVE_ACL_LIBRICHACL + richacl = richacl_get_file(buff); + /* First and last two dir do not return a richacl */ + if ((i == 0 || i >= dircnt - 2) && richacl == NULL && + errno == ENODATA) + continue; + failure("richacl_get_file(\"%s\"): errno = %d (%s)", buff, + errno, strerror(errno)); + assert(richacl != NULL); +#else +#if ARCHIVE_ACL_DARWIN + acl = acl_get_file(buff, ACL_TYPE_EXTENDED); +#else + acl = acl_get_file(buff, ACL_TYPE_NFS4); +#endif + failure("acl_get_file(\"%s\"): errno = %d (%s)", buff, errno, + strerror(errno)); + assert(acl != (acl_t)NULL); +#endif +#if ARCHIVE_ACL_SUNOS_NFS4 + compare_acls(aclp, aclcnt, acls_dir, buff, i, i + 1); + free(aclp); + aclp = NULL; +#elif ARCHIVE_ACL_LIBRICHACL + compare_acls(richacl, acls_dir, buff, i, i + 1); + richacl_free(richacl); +#else + compare_acls(acl, acls_dir, buff, i, i + 1); + acl_free(acl); +#endif + } + + /* Verify "dirall" on disk. */ + assertEqualInt(0, stat("dirall", &st)); + assertEqualInt(st.st_mtime, 123456); +#if ARCHIVE_ACL_SUNOS_NFS4 + aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, "dirall"); + failure("acl(\"%s\"): errno = %d (%s)", "dirall", errno, + strerror(errno)); + assert(aclp != NULL); +#elif ARCHIVE_ACL_LIBRICHACL + richacl = richacl_get_file("dirall"); + failure("richacl_get_file(\"%s\"): errno = %d (%s)", "dirall", + errno, strerror(errno)); + assert(richacl != NULL); +#else +#if ARCHIVE_ACL_DARWIN + acl = acl_get_file("dirall", ACL_TYPE_EXTENDED); +#else + acl = acl_get_file("dirall", ACL_TYPE_NFS4); +#endif + failure("acl_get_file(\"%s\"): errno = %d (%s)", "dirall", errno, + strerror(errno)); + assert(acl != (acl_t)NULL); +#endif +#if ARCHIVE_ACL_SUNOS_NFS4 + compare_acls(aclp, aclcnt, acls_dir, "dirall", 0, dircnt); + free(aclp); + aclp = NULL; +#elif ARCHIVE_ACL_LIBRICHACL + compare_acls(richacl, acls_dir, "dirall", 0, dircnt); + richacl_free(richacl); +#else + compare_acls(acl, acls_dir, "dirall", 0, dircnt); + acl_free(acl); +#endif + + /* Read and compare ACL via archive_read_disk */ + a = archive_read_disk_new(); + assert(a != NULL); + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_pathname(ae, "testall"); + assertEqualInt(ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + compare_entry_acls(ae, acls_reg, "testall", 0, acls_reg_cnt); + archive_entry_free(ae); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* Read and compare ACL via archive_read_disk */ + a = archive_read_disk_new(); + assert(a != NULL); + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_pathname(ae, "dirall"); + assertEqualInt(ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + compare_entry_acls(ae, acls_dir, "dirall", 0, acls_dir_cnt); + archive_entry_free(ae); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +#endif /* ARCHIVE_ACL_NFS4 */ +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_acl_platform_posix1e.c b/dependencies/libarchive-3.4.2/libarchive/test/test_acl_platform_posix1e.c new file mode 100644 index 0000000..801a7ac --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_acl_platform_posix1e.c @@ -0,0 +1,606 @@ +/*- + * Copyright (c) 2003-2008 Tim Kientzle + * Copyright (c) 2017 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_acl_freebsd.c 189427 2009-03-06 04:21:23Z kientzle $"); + +#if ARCHIVE_ACL_POSIX1E +#include +#if HAVE_ACL_GET_PERM +#include +#define ACL_GET_PERM acl_get_perm +#elif HAVE_ACL_GET_PERM_NP +#define ACL_GET_PERM acl_get_perm_np +#endif + +static struct archive_test_acl_t acls2[] = { + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE | ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_USER, 77, "user77" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0, + ARCHIVE_ENTRY_ACL_USER, 78, "user78" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0007, + ARCHIVE_ENTRY_ACL_GROUP, 78, "group78" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_OTHER, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_READ | ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_MASK, -1, "" }, +}; + +static int +#if ARCHIVE_ACL_SUNOS +acl_entry_get_perm(aclent_t *aclent) +#else +acl_entry_get_perm(acl_entry_t aclent) +#endif +{ + int permset = 0; +#if ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL + acl_permset_t opaque_ps; +#endif + +#if ARCHIVE_ACL_SUNOS + if (aclent->a_perm & 1) + permset |= ARCHIVE_ENTRY_ACL_EXECUTE; + if (aclent->a_perm & 2) + permset |= ARCHIVE_ENTRY_ACL_WRITE; + if (aclent->a_perm & 4) + permset |= ARCHIVE_ENTRY_ACL_READ; +#else + /* translate the silly opaque permset to a bitmap */ + acl_get_permset(aclent, &opaque_ps); + if (ACL_GET_PERM(opaque_ps, ACL_EXECUTE)) + permset |= ARCHIVE_ENTRY_ACL_EXECUTE; + if (ACL_GET_PERM(opaque_ps, ACL_WRITE)) + permset |= ARCHIVE_ENTRY_ACL_WRITE; + if (ACL_GET_PERM(opaque_ps, ACL_READ)) + permset |= ARCHIVE_ENTRY_ACL_READ; +#endif + return permset; +} + +#if 0 +static int +acl_get_specific_entry(acl_t acl, acl_tag_t requested_tag_type, int requested_tag) { + int entry_id = ACL_FIRST_ENTRY; + acl_entry_t acl_entry; + acl_tag_t acl_tag_type; + + while (1 == acl_get_entry(acl, entry_id, &acl_entry)) { + /* After the first time... */ + entry_id = ACL_NEXT_ENTRY; + + /* If this matches, return perm mask */ + acl_get_tag_type(acl_entry, &acl_tag_type); + if (acl_tag_type == requested_tag_type) { + switch (acl_tag_type) { + case ACL_USER_OBJ: + if ((uid_t)requested_tag == *(uid_t *)(acl_get_qualifier(acl_entry))) { + return acl_entry_get_perm(acl_entry); + } + break; + case ACL_GROUP_OBJ: + if ((gid_t)requested_tag == *(gid_t *)(acl_get_qualifier(acl_entry))) { + return acl_entry_get_perm(acl_entry); + } + break; + case ACL_USER: + case ACL_GROUP: + case ACL_OTHER: + return acl_entry_get_perm(acl_entry); + default: + failure("Unexpected ACL tag type"); + assert(0); + } + } + + + } + return -1; +} +#endif + +#if ARCHIVE_ACL_SUNOS +static int +acl_match(aclent_t *aclent, struct archive_test_acl_t *myacl) +{ + + if (myacl->permset != acl_entry_get_perm(aclent)) + return (0); + + switch (aclent->a_type) { + case DEF_USER_OBJ: + case USER_OBJ: + if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0); + break; + if (myacl->tag != ARCHIVE_ENTRY_ACL_USER) + return (0); + if ((uid_t)myacl->qual != aclent->a_id) + return (0); + break; + case DEF_GROUP_OBJ: + case GROUP_OBJ: + if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (0); + break; + case DEF_GROUP: + case GROUP: + if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP) + return (0); + if ((gid_t)myacl->qual != aclent->a_id) + return (0); + break; + case DEF_CLASS_OBJ: + case CLASS_OBJ: + if (myacl->tag != ARCHIVE_ENTRY_ACL_MASK) return (0); + break; + case DEF_OTHER_OBJ: + case OTHER_OBJ: + if (myacl->tag != ARCHIVE_ENTRY_ACL_OTHER) return (0); + break; + } + return (1); +} + +#else /* ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL */ +static int +acl_match(acl_entry_t aclent, struct archive_test_acl_t *myacl) +{ + gid_t g, *gp; + uid_t u, *up; + acl_tag_t tag_type; + + if (myacl->permset != acl_entry_get_perm(aclent)) + return (0); + + acl_get_tag_type(aclent, &tag_type); + switch (tag_type) { + case ACL_USER_OBJ: + if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0); + break; + case ACL_USER: + if (myacl->tag != ARCHIVE_ENTRY_ACL_USER) + return (0); + up = acl_get_qualifier(aclent); + u = *up; + acl_free(up); + if ((uid_t)myacl->qual != u) + return (0); + break; + case ACL_GROUP_OBJ: + if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (0); + break; + case ACL_GROUP: + if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP) + return (0); + gp = acl_get_qualifier(aclent); + g = *gp; + acl_free(gp); + if ((gid_t)myacl->qual != g) + return (0); + break; + case ACL_MASK: + if (myacl->tag != ARCHIVE_ENTRY_ACL_MASK) return (0); + break; + case ACL_OTHER: + if (myacl->tag != ARCHIVE_ENTRY_ACL_OTHER) return (0); + break; + } + return (1); +} +#endif + +static void +compare_acls( +#if ARCHIVE_ACL_SUNOS + void *aclp, int aclcnt, +#else + acl_t acl, +#endif + struct archive_test_acl_t *myacls, int n) +{ + int *marker; + int matched; + int i; +#if ARCHIVE_ACL_SUNOS + int e; + aclent_t *acl_entry; +#else + int entry_id = ACL_FIRST_ENTRY; + acl_entry_t acl_entry; +#endif + + /* Count ACL entries in myacls array and allocate an indirect array. */ + marker = malloc(sizeof(marker[0]) * n); + if (marker == NULL) + return; + for (i = 0; i < n; i++) + marker[i] = i; + + /* + * Iterate over acls in system acl object, try to match each + * one with an item in the myacls array. + */ +#if ARCHIVE_ACL_SUNOS + for(e = 0; e < aclcnt; e++) { + acl_entry = &((aclent_t *)aclp)[e]; +#else + while (1 == acl_get_entry(acl, entry_id, &acl_entry)) { + /* After the first time... */ + entry_id = ACL_NEXT_ENTRY; +#endif + + /* Search for a matching entry (tag and qualifier) */ + for (i = 0, matched = 0; i < n && !matched; i++) { + if (acl_match(acl_entry, &myacls[marker[i]])) { + /* We found a match; remove it. */ + marker[i] = marker[n - 1]; + n--; + matched = 1; + } + } + + /* TODO: Print out more details in this case. */ + failure("ACL entry on file that shouldn't be there"); + assert(matched == 1); + } + + /* Dump entries in the myacls array that weren't in the system acl. */ + for (i = 0; i < n; ++i) { + failure(" ACL entry missing from file: " + "type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s''\n", + myacls[marker[i]].type, myacls[marker[i]].permset, + myacls[marker[i]].tag, myacls[marker[i]].qual, + myacls[marker[i]].name); + assert(0); /* Record this as a failure. */ + } + free(marker); +} +#endif + +/* + * Verify ACL restore-to-disk. This test is Platform-specific. + */ + +DEFINE_TEST(test_acl_platform_posix1e_restore) +{ +#if !ARCHIVE_ACL_POSIX1E + skipping("POSIX.1e ACLs are not supported on this platform"); +#else /* ARCHIVE_ACL_POSIX1E */ + struct stat st; + struct archive *a; + struct archive_entry *ae; +#if ARCHIVE_ACL_SUNOS + void *aclp; + int aclcnt; +#else + acl_t acl; +#endif + + assertMakeFile("pretest", 0644, "a"); + + if (setTestAcl("pretest") != ARCHIVE_TEST_ACL_TYPE_POSIX1E) { + skipping("POSIX.1e ACLs are not writable on this filesystem"); + return; + } + + /* Create a write-to-disk object. */ + assert(NULL != (a = archive_write_disk_new())); + archive_write_disk_set_options(a, + ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL); + + /* Populate an archive entry with some metadata, including ACL info */ + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_pathname(ae, "test0"); + archive_entry_set_mtime(ae, 123456, 7890); + archive_entry_set_size(ae, 0); + assertEntrySetAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0])); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Close the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Verify the data on disk. */ + assertEqualInt(0, stat("test0", &st)); + assertEqualInt(st.st_mtime, 123456); +#if ARCHIVE_ACL_SUNOS + aclp = sunacl_get(GETACL, &aclcnt, 0, "test0"); + failure("acl(): errno = %d (%s)", errno, strerror(errno)); + assert(aclp != NULL); +#else + acl = acl_get_file("test0", ACL_TYPE_ACCESS); + failure("acl_get_file(): errno = %d (%s)", errno, strerror(errno)); + assert(acl != (acl_t)NULL); +#endif +#if ARCHIVE_ACL_SUNOS + compare_acls(aclp, aclcnt, acls2, sizeof(acls2)/sizeof(acls2[0])); + free(aclp); + aclp = NULL; +#else + compare_acls(acl, acls2, sizeof(acls2)/sizeof(acls2[0])); + acl_free(acl); +#endif + +#endif /* ARCHIVE_ACL_POSIX1E */ +} + +/* + * Verify ACL read-from-disk. This test is Platform-specific. + */ +DEFINE_TEST(test_acl_platform_posix1e_read) +{ +#if !ARCHIVE_ACL_POSIX1E + skipping("POSIX.1e ACLs are not supported on this platform"); +#else /* ARCHIVE_ACL_POSIX1E */ + struct archive *a; + struct archive_entry *ae; + int n, fd, flags, dflags; + char *func, *acl_text; + const char *acl1_text, *acl2_text, *acl3_text; +#if ARCHIVE_ACL_SUNOS + void *aclp; + int aclcnt; +#else + acl_t acl1, acl2, acl3; +#endif + + /* + * Manually construct a directory and two files with + * different ACLs. This also serves to verify that ACLs + * are supported on the local filesystem. + */ + + /* Create a test file f1 with acl1 */ +#if ARCHIVE_ACL_SUNOS + acl1_text = "user::rwx," + "group::rwx," + "other:rwx," + "user:1:rw-," + "group:15:r-x," + "mask:rwx"; + aclent_t aclp1[] = { + { USER_OBJ, -1, 4 | 2 | 1 }, + { USER, 1, 4 | 2 }, + { GROUP_OBJ, -1, 4 | 2 | 1 }, + { GROUP, 15, 4 | 1 }, + { CLASS_OBJ, -1, 4 | 2 | 1 }, + { OTHER_OBJ, -1, 4 | 2 | 1 } + }; +#else + acl1_text = "user::rwx\n" + "group::rwx\n" + "other::rwx\n" + "user:1:rw-\n" + "group:15:r-x\n" + "mask::rwx"; + acl1 = acl_from_text(acl1_text); + failure("acl_from_text(): errno = %d (%s)", errno, strerror(errno)); + assert((void *)acl1 != NULL); +#endif + fd = open("f1", O_WRONLY | O_CREAT | O_EXCL, 0777); + failure("Could not create test file?!"); + if (!assert(fd >= 0)) { +#if !ARCHIVE_ACL_SUNOS + acl_free(acl1); +#endif + return; + } +#if ARCHIVE_ACL_SUNOS + /* Check if Solaris filesystem supports POSIX.1e ACLs */ + aclp = sunacl_get(GETACL, &aclcnt, fd, NULL); + if (aclp == 0) + close(fd); + if (errno == ENOSYS || errno == ENOTSUP) { + skipping("POSIX.1e ACLs are not supported on this filesystem"); + return; + } + failure("facl(): errno = %d (%s)", errno, strerror(errno)); + assert(aclp != NULL); + + func = "facl()"; + n = facl(fd, SETACL, (int)(sizeof(aclp1)/sizeof(aclp1[0])), aclp1); +#else + func = "acl_set_fd()"; + n = acl_set_fd(fd, acl1); +#endif +#if !ARCHIVE_ACL_SUNOS + acl_free(acl1); +#endif + + if (n != 0) { +#if ARCHIVE_ACL_SUNOS + if (errno == ENOSYS || errno == ENOTSUP) +#else + if (errno == EOPNOTSUPP || errno == EINVAL) +#endif + { + close(fd); + skipping("POSIX.1e ACLs are not supported on this filesystem"); + return; + } + } + failure("%s: errno = %d (%s)", func, errno, strerror(errno)); + assertEqualInt(0, n); + + close(fd); + + assertMakeDir("d", 0700); + + /* + * Create file d/f1 with acl2 + * + * This differs from acl1 in the u:1: and g:15: permissions. + * + * This file deliberately has the same name but a different ACL. + * Github Issue #777 explains how libarchive's directory traversal + * did not always correctly enter directories before attempting + * to read ACLs, resulting in reading the ACL from a like-named + * file in the wrong directory. + */ +#if ARCHIVE_ACL_SUNOS + acl2_text = "user::rwx," + "group::rwx," + "other:---," + "user:1:r--," + "group:15:r--," + "mask:rwx"; + aclent_t aclp2[] = { + { USER_OBJ, -1, 4 | 2 | 1 }, + { USER, 1, 4 }, + { GROUP_OBJ, -1, 4 | 2 | 1}, + { GROUP, 15, 4 }, + { CLASS_OBJ, -1, 4 | 2 | 1}, + { OTHER_OBJ, -1, 0 } + }; +#else + acl2_text = "user::rwx\n" + "group::rwx\n" + "other::---\n" + "user:1:r--\n" + "group:15:r--\n" + "mask::rwx"; + acl2 = acl_from_text(acl2_text); + failure("acl_from_text(): errno = %d (%s)", errno, strerror(errno)); + assert((void *)acl2 != NULL); +#endif + fd = open("d/f1", O_WRONLY | O_CREAT | O_EXCL, 0777); + failure("Could not create test file?!"); + if (!assert(fd >= 0)) { +#if !ARCHIVE_ACL_SUNOS + acl_free(acl2); +#endif + return; + } +#if ARCHIVE_ACL_SUNOS + func = "facl()"; + n = facl(fd, SETACL, (int)(sizeof(aclp2) / sizeof(aclp2[0])), aclp2); +#else + func = "acl_set_fd()"; + n = acl_set_fd(fd, acl2); + acl_free(acl2); +#endif + if (n != 0) + close(fd); + failure("%s: errno = %d (%s)", func, errno, strerror(errno)); + assertEqualInt(0, n); + close(fd); + + /* Create nested directory d2 with default ACLs */ + assertMakeDir("d/d2", 0755); + +#if ARCHIVE_ACL_SUNOS + acl3_text = "user::rwx," + "group::r-x," + "other:r-x," + "user:2:r--," + "group:16:-w-," + "mask:rwx," + "default:user::rwx," + "default:user:1:r--," + "default:group::r-x," + "default:group:15:r--," + "default:mask:rwx," + "default:other:r-x"; + aclent_t aclp3[] = { + { USER_OBJ, -1, 4 | 2 | 1 }, + { USER, 2, 4 }, + { GROUP_OBJ, -1, 4 | 1 }, + { GROUP, 16, 2 }, + { CLASS_OBJ, -1, 4 | 2 | 1 }, + { OTHER_OBJ, -1, 4 | 1 }, + { USER_OBJ | ACL_DEFAULT, -1, 4 | 2 | 1 }, + { USER | ACL_DEFAULT, 1, 4 }, + { GROUP_OBJ | ACL_DEFAULT, -1, 4 | 1 }, + { GROUP | ACL_DEFAULT, 15, 4 }, + { CLASS_OBJ | ACL_DEFAULT, -1, 4 | 2 | 1}, + { OTHER_OBJ | ACL_DEFAULT, -1, 4 | 1 } + }; +#else + acl3_text = "user::rwx\n" + "user:1:r--\n" + "group::r-x\n" + "group:15:r--\n" + "mask::rwx\n" + "other::r-x"; + acl3 = acl_from_text(acl3_text); + failure("acl_from_text(): errno = %d (%s)", errno, strerror(errno)); + assert((void *)acl3 != NULL); +#endif + +#if ARCHIVE_ACL_SUNOS + func = "acl()"; + n = acl("d/d2", SETACL, (int)(sizeof(aclp3) / sizeof(aclp3[0])), aclp3); +#else + func = "acl_set_file()"; + n = acl_set_file("d/d2", ACL_TYPE_DEFAULT, acl3); + acl_free(acl3); +#endif + failure("%s: errno = %d (%s)", func, errno, strerror(errno)); + assertEqualInt(0, n); + + /* Create a read-from-disk object. */ + assert(NULL != (a = archive_read_disk_new())); + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, ".")); + assert(NULL != (ae = archive_entry_new())); + +#if ARCHIVE_ACL_SUNOS + flags = ARCHIVE_ENTRY_ACL_TYPE_POSIX1E + | ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA + | ARCHIVE_ENTRY_ACL_STYLE_SOLARIS; + dflags = flags; +#else + flags = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; + dflags = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT; +#endif + + /* Walk the dir until we see both of the files */ + while (ARCHIVE_OK == archive_read_next_header2(a, ae)) { + archive_read_disk_descend(a); + if (strcmp(archive_entry_pathname(ae), "./f1") == 0) { + acl_text = archive_entry_acl_to_text(ae, NULL, flags); + assertEqualString(acl_text, acl1_text); + free(acl_text); + } else if (strcmp(archive_entry_pathname(ae), "./d/f1") == 0) { + acl_text = archive_entry_acl_to_text(ae, NULL, flags); + assertEqualString(acl_text, acl2_text); + free(acl_text); + } else if (strcmp(archive_entry_pathname(ae), "./d/d2") == 0) { + acl_text = archive_entry_acl_to_text(ae, NULL, dflags); + assertEqualString(acl_text, acl3_text); + free(acl_text); + } + } + + archive_entry_free(ae); + assertEqualInt(ARCHIVE_OK, archive_free(a)); +#endif /* ARCHIVE_ACL_POSIX1E */ +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_acl_posix1e.c b/dependencies/libarchive-3.4.2/libarchive/test/test_acl_posix1e.c new file mode 100644 index 0000000..fa2628d --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_acl_posix1e.c @@ -0,0 +1,180 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/lib/libarchive/test/test_acl_basic.c,v 1.6 2008/10/19 00:13:57 kientzle Exp $"); + +/* + * Exercise the system-independent portion of the ACL support. + * Check that archive_entry objects can save and restore POSIX.1e-style + * ACL data. + * + * This should work on all systems, regardless of whether local + * filesystems support ACLs or not. + */ + +static struct archive_test_acl_t acls0[] = { + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_USER_OBJ, 0, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_WRITE, + ARCHIVE_ENTRY_ACL_OTHER, 0, "" }, +}; + +static struct archive_test_acl_t acls1[] = { + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_USER, 77, "user77" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_WRITE, + ARCHIVE_ENTRY_ACL_OTHER, -1, "" }, +}; + +static struct archive_test_acl_t acls2[] = { + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE | ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_USER, 77, "user77" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0, + ARCHIVE_ENTRY_ACL_USER, 78, "user78" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0007, + ARCHIVE_ENTRY_ACL_GROUP, 78, "group78" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_OTHER, -1, "" }, +}; + +/* + * NFS4 entry types; attempts to set these on top of POSIX.1e + * attributes should fail. + */ +static struct archive_test_acl_t acls_nfs4[] = { + /* NFS4 types */ + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_USER, 78, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_USER, 78, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_AUDIT, ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_USER, 78, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALARM, ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_USER, 78, "" }, + + /* NFS4 tags */ + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }, + + /* NFS4 inheritance markers */ + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_READ | ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, + ARCHIVE_ENTRY_ACL_USER, 79, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_READ | ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, + ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" }, +}; + +DEFINE_TEST(test_acl_posix1e) +{ + struct archive_entry *ae; + int i; + + /* Create a simple archive_entry. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_pathname(ae, "file"); + archive_entry_set_mode(ae, S_IFREG | 0777); + + /* Basic owner/owning group should just update mode bits. */ + + /* + * Note: This features of libarchive's ACL implementation + * shouldn't be relied on and should probably be removed. It + * was done to identify trivial ACLs so we could avoid + * triggering unnecessary extensions. It's better to identify + * trivial ACLs at the point they are being read from disk. + */ + assertEntrySetAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0])); + failure("Basic ACLs shouldn't be stored as extended ACLs"); + assert(0 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + failure("Basic ACLs should set mode to 0142, not %04o", + archive_entry_mode(ae)&0777); + assert((archive_entry_mode(ae) & 0777) == 0142); + + /* With any extended ACL entry, we should read back a full set. */ + assertEntrySetAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0])); + failure("One extended ACL should flag all ACLs to be returned."); + + /* Check that entry contains only POSIX.1e types */ + assert((archive_entry_acl_types(ae) & + ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0); + assert((archive_entry_acl_types(ae) & + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0); + + assert(4 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEntryCompareAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]), + ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0142); + failure("Basic ACLs should set mode to 0142, not %04o", + archive_entry_mode(ae)&0777); + assert((archive_entry_mode(ae) & 0777) == 0142); + + + /* A more extensive set of ACLs. */ + assertEntrySetAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0])); + assertEqualInt(6, archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEntryCompareAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]), + ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0543); + failure("Basic ACLs should set mode to 0543, not %04o", + archive_entry_mode(ae)&0777); + assert((archive_entry_mode(ae) & 0777) == 0543); + + /* + * Check that clearing ACLs gets rid of them all by repeating + * the first test. + */ + assertEntrySetAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0])); + failure("Basic ACLs shouldn't be stored as extended ACLs"); + assert(0 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + failure("Basic ACLs should set mode to 0142, not %04o", + archive_entry_mode(ae)&0777); + assert((archive_entry_mode(ae) & 0777) == 0142); + + /* + * Different types of malformed ACL entries that should + * fail when added to existing POSIX.1e ACLs. + */ + assertEntrySetAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0])); + for (i = 0; i < (int)(sizeof(acls_nfs4)/sizeof(acls_nfs4[0])); ++i) { + struct archive_test_acl_t *p = &acls_nfs4[i]; + failure("Malformed ACL test #%d", i); + assertEqualInt(ARCHIVE_FAILED, + archive_entry_acl_add_entry(ae, + p->type, p->permset, p->tag, p->qual, p->name)); + assertEqualInt(6, + archive_entry_acl_reset(ae, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + } + archive_entry_free(ae); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_acl_text.c b/dependencies/libarchive-3.4.2/libarchive/test/test_acl_text.c new file mode 100644 index 0000000..8072893 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_acl_text.c @@ -0,0 +1,473 @@ +/*- + * Copyright (c) 2016 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * Test converting ACLs to text, both wide and non-wide + * + * This should work on all systems, regardless of whether local + * filesystems support ACLs or not. + */ + +static struct archive_test_acl_t acls0[] = { + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_READ | + ARCHIVE_ENTRY_ACL_WRITE, + ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_USER, 100, "user100" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0, + ARCHIVE_ENTRY_ACL_USER, 1000, "user1000" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_READ | + ARCHIVE_ENTRY_ACL_WRITE, + ARCHIVE_ENTRY_ACL_GROUP, 78, "group78" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_READ | + ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_OTHER, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, + ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, + ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, 0, + ARCHIVE_ENTRY_ACL_OTHER, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, + ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_USER, 101, "user101"}, + { ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, + ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_GROUP, 79, "group79" }, +}; + +static struct archive_test_acl_t acls1[] = { + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_APPEND_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_WRITE_OWNER, + ARCHIVE_ENTRY_ACL_USER, 77, "user77" }, + { ARCHIVE_ENTRY_ACL_TYPE_DENY, + ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_APPEND_DATA | + ARCHIVE_ENTRY_ACL_DELETE_CHILD | + ARCHIVE_ENTRY_ACL_DELETE | + ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT | + ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT | + ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY | + ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, + ARCHIVE_ENTRY_ACL_USER, 101, "user101" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, + ARCHIVE_ENTRY_ACL_GROUP, 78, "group78" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_APPEND_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_WRITE_ACL | + ARCHIVE_ENTRY_ACL_WRITE_OWNER, + ARCHIVE_ENTRY_ACL_USER_OBJ, 0, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_APPEND_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_EVERYONE, 0, "" }, +}; + +const char* acltext[] = { + "user::rwx\n" + "group::r-x\n" + "other::r-x\n" + "user:user100:r-x\n" + "user:user1000:---\n" + "group:group78:rwx\n" + "default:user::r-x\n" + "default:group::r-x\n" + "default:other::---\n" + "default:user:user101:r-x\n" + "default:group:group79:--x", + + "user::rwx\n" + "group::r-x\n" + "other::r-x\n" + "user:user100:r-x:100\n" + "user:user1000:---:1000\n" + "group:group78:rwx:78\n" + "default:user::r-x\n" + "default:group::r-x\n" + "default:other::---\n" + "default:user:user101:r-x:101\n" + "default:group:group79:--x:79", + + "u::rwx\n" + "g::r-x\n" + "o::r-x\n" + "u:user100:r-x:100\n" + "u:user1000:---:1000\n" + "g:group78:rwx:78\n" + "d:user::r-x\n" + "d:group::r-x\n" + "d:other::---\n" + "d:user:user101:r-x:101\n" + "d:group:group79:--x:79", + + "user::rwx\n" + "group::r-x\n" + "other::r-x\n" + "user:user100:r-x\n" + "user:user1000:---\n" + "group:group78:rwx", + + "user::rwx," + "group::r-x," + "other::r-x," + "user:user100:r-x," + "user:user1000:---," + "group:group78:rwx", + + "user::rwx\n" + "group::r-x\n" + "other::r-x\n" + "user:user100:r-x:100\n" + "user:user1000:---:1000\n" + "group:group78:rwx:78", + + "user::r-x\n" + "group::r-x\n" + "other::---\n" + "user:user101:r-x\n" + "group:group79:--x", + + "user::r-x\n" + "group::r-x\n" + "other::---\n" + "user:user101:r-x:101\n" + "group:group79:--x:79", + + "default:user::r-x\n" + "default:group::r-x\n" + "default:other::---\n" + "default:user:user101:r-x\n" + "default:group:group79:--x", + + "user:user77:rw-p--a-R-c-o-:-------:allow\n" + "user:user101:-w-pdD--------:fdin---:deny\n" + "group:group78:r-----a-R-c---:------I:allow\n" + "owner@:rwxp--aARWcCo-:-------:allow\n" + "group@:rw-p--a-R-c---:-------:allow\n" + "everyone@:r-----a-R-c--s:-------:allow", + + "user:user77:rw-p--a-R-c-o-:-------:allow:77\n" + "user:user101:-w-pdD--------:fdin---:deny:101\n" + "group:group78:r-----a-R-c---:------I:allow:78\n" + "owner@:rwxp--aARWcCo-:-------:allow\n" + "group@:rw-p--a-R-c---:-------:allow\n" + "everyone@:r-----a-R-c--s:-------:allow", + + "user:user77:rwpaRco::allow:77\n" + "user:user101:wpdD:fdin:deny:101\n" + "group:group78:raRc:I:allow:78\n" + "owner@:rwxpaARWcCo::allow\n" + "group@:rwpaRc::allow\n" + "everyone@:raRcs::allow" +}; + +static wchar_t * +convert_s_to_ws(const char *s) +{ + size_t len; + wchar_t *ws = NULL; + + if (s != NULL) { + len = strlen(s) + 1; + ws = malloc(len * sizeof(wchar_t)); + assert(mbstowcs(ws, s, len) != (size_t)-1); + } + + return (ws); +} + +static void +compare_acl_text(struct archive_entry *ae, int flags, const char *s) +{ + char *text; + wchar_t *wtext; + wchar_t *ws; + ssize_t slen; + + ws = convert_s_to_ws(s); + + text = archive_entry_acl_to_text(ae, &slen, flags); + assertEqualString(text, s); + if (text != NULL) + assertEqualInt(strlen(text), slen); + wtext = archive_entry_acl_to_text_w(ae, &slen, flags); + assertEqualWString(wtext, ws); + if (wtext != NULL) { + assertEqualInt(wcslen(wtext), slen); + } + free(text); + free(wtext); + free(ws); +} + +DEFINE_TEST(test_acl_from_text) +{ + struct archive_entry *ae; + wchar_t *ws = NULL; + + /* Create an empty archive_entry. */ + assert((ae = archive_entry_new()) != NULL); + + /* 1a. Read POSIX.1e access ACLs from text */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, acltext[5], + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]), + ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0755); + assertEqualInt(6, archive_entry_acl_reset(ae, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + + /* 1b. Now read POSIX.1e default ACLs and append them */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, acltext[7], + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)); + assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]), + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, 0755); + assertEqualInt(11, archive_entry_acl_reset(ae, + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)); + archive_entry_acl_clear(ae); + + /* 1a and 1b with wide strings */ + ws = convert_s_to_ws(acltext[5]); + + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text_w(ae, ws, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]), + ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0755); + assertEqualInt(6, archive_entry_acl_reset(ae, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + + free(ws); + ws = convert_s_to_ws(acltext[7]); + + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text_w(ae, ws, + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)); + assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]), + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, 0755); + assertEqualInt(11, archive_entry_acl_reset(ae, + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)); + archive_entry_acl_clear(ae); + + /* 2. Read POSIX.1e default ACLs from text */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, acltext[7], + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)); + assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]), + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, 0); + assertEqualInt(5, archive_entry_acl_reset(ae, + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)); + archive_entry_acl_clear(ae); + + /* ws is still acltext[7] */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text_w(ae, ws, + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)); + assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]), + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, 0); + assertEqualInt(5, archive_entry_acl_reset(ae, + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)); + archive_entry_acl_clear(ae); + + /* 3. Read POSIX.1e access and default ACLs from text */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, acltext[1], + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)); + assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]), + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, 0755); + assertEqualInt(11, archive_entry_acl_reset(ae, + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)); + archive_entry_acl_clear(ae); + + free(ws); + ws = convert_s_to_ws(acltext[1]); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text_w(ae, ws, + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)); + assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]), + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, 0755); + assertEqualInt(11, archive_entry_acl_reset(ae, + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)); + archive_entry_acl_clear(ae); + + /* 4. Read POSIX.1e access and default ACLs from text (short form) */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, acltext[2], + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)); + assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]), + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, 0755); + assertEqualInt(11, archive_entry_acl_reset(ae, + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)); + archive_entry_acl_clear(ae); + + free(ws); + ws = convert_s_to_ws(acltext[2]); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text_w(ae, ws, + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)); + assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]), + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, 0755); + assertEqualInt(11, archive_entry_acl_reset(ae, + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)); + archive_entry_acl_clear(ae); + + /* 5. Read NFSv4 ACLs from text */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, acltext[10], + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEntryCompareAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]), + ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0); + assertEqualInt(6, archive_entry_acl_reset(ae, + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + archive_entry_acl_clear(ae); + + free(ws); + ws = convert_s_to_ws(acltext[10]); + + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text_w(ae, ws, + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEntryCompareAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]), + ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0); + assertEqualInt(6, archive_entry_acl_reset(ae, + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + archive_entry_acl_clear(ae); + + free(ws); + archive_entry_free(ae); +} + +DEFINE_TEST(test_acl_to_text) +{ + struct archive_entry *ae; + + /* Create an empty archive_entry. */ + assert((ae = archive_entry_new()) != NULL); + + /* Write POSIX.1e ACLs */ + assertEntrySetAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0])); + + /* No flags should give output like getfacl(1) on linux */ + compare_acl_text(ae, 0, acltext[0]); + + /* This should give the same output as previous test */ + compare_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS | + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, acltext[0]); + + /* This should give the same output as previous two tests */ + compare_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS | + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT | + ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT, acltext[0]); + + /* POSIX.1e access and default ACLs with appended ID */ + compare_acl_text(ae, ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID, acltext[1]); + + /* POSIX.1e access acls only, like getfacl(1) on FreeBSD */ + compare_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, acltext[3]); + + /* POSIX.1e access acls separated with comma */ + compare_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS | + ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA, + acltext[4]); + + /* POSIX.1e access acls with appended user or group ID */ + compare_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS | + ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID, acltext[5]); + + /* POSIX.1e default acls */ + compare_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, acltext[6]); + + /* POSIX.1e default acls with appended user or group ID */ + compare_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT | + ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID, acltext[7]); + + /* POSIX.1e default acls prefixed with default: */ + compare_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT | + ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT, acltext[8]); + + /* Write NFSv4 ACLs */ + assertEntrySetAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0])); + + /* NFSv4 ACLs like getfacl(1) on FreeBSD */ + compare_acl_text(ae, 0, acltext[9]); + + /* NFSv4 ACLs like "getfacl -i" on FreeBSD */ + compare_acl_text(ae, ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID, acltext[10]); + + /* NFSv4 ACLs like "getfacl -i" on FreeBSD with stripped minus chars */ + compare_acl_text(ae, ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID | + ARCHIVE_ENTRY_ACL_STYLE_COMPACT, acltext[11]); + + archive_entry_free(ae); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_api_feature.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_api_feature.c new file mode 100644 index 0000000..60773ad --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_api_feature.c @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/lib/libarchive/test/test_archive_api_feature.c,v 1.5 2008/05/26 17:00:24 kientzle Exp $"); + +DEFINE_TEST(test_archive_api_feature) +{ + char buff[128]; + const char *p; + + /* This is the (hopefully) final versioning API. */ + assertEqualInt(ARCHIVE_VERSION_NUMBER, archive_version_number()); + sprintf(buff, "libarchive %d.%d.%d", + archive_version_number() / 1000000, + (archive_version_number() / 1000) % 1000, + archive_version_number() % 1000); + failure("Version string is: %s, computed is: %s", + archive_version_string(), buff); + assertEqualMem(buff, archive_version_string(), strlen(buff)); + if (strlen(buff) < strlen(archive_version_string())) { + p = archive_version_string() + strlen(buff); + failure("Version string is: %s", archive_version_string()); + if (p[0] == 'd'&& p[1] == 'e' && p[2] == 'v') + p += 3; + else { + assert(*p == 'a' || *p == 'b' || *p == 'c' || *p == 'd'); + ++p; + } + failure("Version string is: %s", archive_version_string()); + assert(*p == '\0'); + } +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_clear_error.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_clear_error.c new file mode 100644 index 0000000..66dbe93 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_clear_error.c @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_archive_clear_error) +{ + struct archive* a = archive_read_new(); + + archive_set_error(a, 12, "abcdefgh"); + assertEqualInt(12, archive_errno(a)); + assertEqualString("abcdefgh", archive_error_string(a)); + + archive_clear_error(a); + assertEqualInt(0, archive_errno(a)); + assertEqualString(NULL, archive_error_string(a)); + + archive_read_free(a); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_cmdline.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_cmdline.c new file mode 100644 index 0000000..a823610 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_cmdline.c @@ -0,0 +1,141 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +#define __LIBARCHIVE_TEST +#include "archive_cmdline_private.h" + +DEFINE_TEST(test_archive_cmdline) +{ + struct archive_cmdline *cl; + + /* Command name only. */ + assert((cl = __archive_cmdline_allocate()) != NULL); + if (cl == NULL) + return; + assertEqualInt(ARCHIVE_OK, __archive_cmdline_parse(cl, "gzip")); + assertEqualInt(1, cl->argc); + assertEqualString("gzip", cl->path); + assertEqualString("gzip", cl->argv[0]); + assertEqualInt(ARCHIVE_OK, __archive_cmdline_free(cl)); + + assert((cl = __archive_cmdline_allocate()) != NULL); + if (cl == NULL) + return; + assertEqualInt(ARCHIVE_OK, __archive_cmdline_parse(cl, "gzip ")); + assertEqualInt(1, cl->argc); + failure("path should not include a space character"); + assertEqualString("gzip", cl->path); + failure("arg0 should not include a space character"); + assertEqualString("gzip", cl->argv[0]); + assertEqualInt(ARCHIVE_OK, __archive_cmdline_free(cl)); + + assert((cl = __archive_cmdline_allocate()) != NULL); + if (cl == NULL) + return; + assertEqualInt(ARCHIVE_OK, __archive_cmdline_parse(cl, + "/usr/bin/gzip ")); + assertEqualInt(1, cl->argc); + failure("path should be a full path"); + assertEqualString("/usr/bin/gzip", cl->path); + failure("arg0 should not be a full path"); + assertEqualString("gzip", cl->argv[0]); + assertEqualInt(ARCHIVE_OK, __archive_cmdline_free(cl)); + + /* A command line includes space character. */ + assert((cl = __archive_cmdline_allocate()) != NULL); + if (cl == NULL) + return; + assertEqualInt(ARCHIVE_OK, __archive_cmdline_parse(cl, "\"gzip \"")); + assertEqualInt(1, cl->argc); + failure("path should include a space character"); + assertEqualString("gzip ", cl->path); + failure("arg0 should include a space character"); + assertEqualString("gzip ", cl->argv[0]); + assertEqualInt(ARCHIVE_OK, __archive_cmdline_free(cl)); + + /* A command line includes space character: pattern 2.*/ + assert((cl = __archive_cmdline_allocate()) != NULL); + if (cl == NULL) + return; + assertEqualInt(ARCHIVE_OK, __archive_cmdline_parse(cl, "\"gzip \"x")); + assertEqualInt(1, cl->argc); + failure("path should include a space character"); + assertEqualString("gzip x", cl->path); + failure("arg0 should include a space character"); + assertEqualString("gzip x", cl->argv[0]); + assertEqualInt(ARCHIVE_OK, __archive_cmdline_free(cl)); + + /* A command line includes space character: pattern 3.*/ + assert((cl = __archive_cmdline_allocate()) != NULL); + if (cl == NULL) + return; + assertEqualInt(ARCHIVE_OK, __archive_cmdline_parse(cl, + "\"gzip \"x\" s \"")); + assertEqualInt(1, cl->argc); + failure("path should include a space character"); + assertEqualString("gzip x s ", cl->path); + failure("arg0 should include a space character"); + assertEqualString("gzip x s ", cl->argv[0]); + assertEqualInt(ARCHIVE_OK, __archive_cmdline_free(cl)); + + /* A command line includes space character: pattern 4.*/ + assert((cl = __archive_cmdline_allocate()) != NULL); + if (cl == NULL) + return; + assertEqualInt(ARCHIVE_OK, __archive_cmdline_parse(cl, + "\"gzip\\\" \"")); + assertEqualInt(1, cl->argc); + failure("path should include a space character"); + assertEqualString("gzip\" ", cl->path); + failure("arg0 should include a space character"); + assertEqualString("gzip\" ", cl->argv[0]); + assertEqualInt(ARCHIVE_OK, __archive_cmdline_free(cl)); + + /* A command name with a argument. */ + assert((cl = __archive_cmdline_allocate()) != NULL); + if (cl == NULL) + return; + assertEqualInt(ARCHIVE_OK, __archive_cmdline_parse(cl, "gzip -d")); + assertEqualInt(2, cl->argc); + assertEqualString("gzip", cl->path); + assertEqualString("gzip", cl->argv[0]); + assertEqualString("-d", cl->argv[1]); + assertEqualInt(ARCHIVE_OK, __archive_cmdline_free(cl)); + + /* A command name with two arguments. */ + assert((cl = __archive_cmdline_allocate()) != NULL); + if (cl == NULL) + return; + assertEqualInt(ARCHIVE_OK, __archive_cmdline_parse(cl, "gzip -d -q")); + assertEqualInt(3, cl->argc); + assertEqualString("gzip", cl->path); + assertEqualString("gzip", cl->argv[0]); + assertEqualString("-d", cl->argv[1]); + assertEqualString("-q", cl->argv[2]); + assertEqualInt(ARCHIVE_OK, __archive_cmdline_free(cl)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_digest.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_digest.c new file mode 100644 index 0000000..a8654ae --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_digest.c @@ -0,0 +1,145 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2011 Andres Mejia + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +/* Sanity test of internal digest functionality */ + +#define __LIBARCHIVE_BUILD 1 +#include "archive_digest_private.h" + +DEFINE_TEST(test_archive_md5) +{ + archive_md5_ctx ctx; + unsigned char buf[] = ""; + unsigned char md[16]; + unsigned char actualmd[] = "\x93\xb8\x85\xad\xfe\x0d\xa0\x89" + "\xcd\xf6\x34\x90\x4f\xd5\x9f\x71"; + + if (ARCHIVE_OK != archive_md5_init(&ctx)) { + skipping("This platform does not support MD5"); + return; + } + assertEqualInt(ARCHIVE_OK, archive_md5_update(&ctx, buf, sizeof(buf))); + assertEqualInt(ARCHIVE_OK, archive_md5_final(&ctx, md)); + assertEqualMem(md, actualmd, sizeof(md)); +} + +DEFINE_TEST(test_archive_rmd160) +{ + archive_rmd160_ctx ctx; + unsigned char buf[] = ""; + unsigned char md[20]; + unsigned char actualmd[] = "\xc8\x1b\x94\x93\x34\x20\x22\x1a\x7a\xc0" + "\x04\xa9\x02\x42\xd8\xb1\xd3\xe5\x07\x0d"; + + if (ARCHIVE_OK != archive_rmd160_init(&ctx)) { + skipping("This platform does not support RMD160"); + return; + } + assertEqualInt(ARCHIVE_OK, archive_rmd160_update(&ctx, buf, sizeof(buf))); + assertEqualInt(ARCHIVE_OK, archive_rmd160_final(&ctx, md)); + assertEqualMem(md, actualmd, sizeof(md)); +} + +DEFINE_TEST(test_archive_sha1) +{ + archive_sha1_ctx ctx; + unsigned char buf[] = ""; + unsigned char md[20]; + unsigned char actualmd[] = "\x5b\xa9\x3c\x9d\xb0\xcf\xf9\x3f\x52\xb5" + "\x21\xd7\x42\x0e\x43\xf6\xed\xa2\x78\x4f"; + + if (ARCHIVE_OK != archive_sha1_init(&ctx)) { + skipping("This platform does not support SHA1"); + return; + } + assertEqualInt(ARCHIVE_OK, archive_sha1_update(&ctx, buf, sizeof(buf))); + assertEqualInt(ARCHIVE_OK, archive_sha1_final(&ctx, md)); + assertEqualMem(md, actualmd, sizeof(md)); +} + +DEFINE_TEST(test_archive_sha256) +{ + archive_sha256_ctx ctx; + unsigned char buf[] = ""; + unsigned char md[32]; + unsigned char actualmd[] = "\x6e\x34\x0b\x9c\xff\xb3\x7a\x98" + "\x9c\xa5\x44\xe6\xbb\x78\x0a\x2c" + "\x78\x90\x1d\x3f\xb3\x37\x38\x76" + "\x85\x11\xa3\x06\x17\xaf\xa0\x1d"; + + if (ARCHIVE_OK != archive_sha256_init(&ctx)) { + skipping("This platform does not support SHA256"); + return; + } + assertEqualInt(ARCHIVE_OK, archive_sha256_update(&ctx, buf, sizeof(buf))); + assertEqualInt(ARCHIVE_OK, archive_sha256_final(&ctx, md)); + assertEqualMem(md, actualmd, sizeof(md)); +} + +DEFINE_TEST(test_archive_sha384) +{ + archive_sha384_ctx ctx; + unsigned char buf[] = ""; + unsigned char md[48]; + unsigned char actualmd[] = "\xbe\xc0\x21\xb4\xf3\x68\xe3\x06" + "\x91\x34\xe0\x12\xc2\xb4\x30\x70" + "\x83\xd3\xa9\xbd\xd2\x06\xe2\x4e" + "\x5f\x0d\x86\xe1\x3d\x66\x36\x65" + "\x59\x33\xec\x2b\x41\x34\x65\x96" + "\x68\x17\xa9\xc2\x08\xa1\x17\x17"; + + if (ARCHIVE_OK != archive_sha384_init(&ctx)) { + skipping("This platform does not support SHA384"); + return; + } + assertEqualInt(ARCHIVE_OK, archive_sha384_update(&ctx, buf, sizeof(buf))); + assertEqualInt(ARCHIVE_OK, archive_sha384_final(&ctx, md)); + assertEqualMem(md, actualmd, sizeof(md)); +} + +DEFINE_TEST(test_archive_sha512) +{ + archive_sha512_ctx ctx; + unsigned char buf[] = ""; + unsigned char md[64]; + unsigned char actualmd[] = "\xb8\x24\x4d\x02\x89\x81\xd6\x93" + "\xaf\x7b\x45\x6a\xf8\xef\xa4\xca" + "\xd6\x3d\x28\x2e\x19\xff\x14\x94" + "\x2c\x24\x6e\x50\xd9\x35\x1d\x22" + "\x70\x4a\x80\x2a\x71\xc3\x58\x0b" + "\x63\x70\xde\x4c\xeb\x29\x3c\x32" + "\x4a\x84\x23\x34\x25\x57\xd4\xe5" + "\xc3\x84\x38\xf0\xe3\x69\x10\xee"; + + if (ARCHIVE_OK != archive_sha512_init(&ctx)) { + skipping("This platform does not support SHA512"); + return; + } + assertEqualInt(ARCHIVE_OK, archive_sha512_update(&ctx, buf, sizeof(buf))); + assertEqualInt(ARCHIVE_OK, archive_sha512_final(&ctx, md)); + assertEqualMem(md, actualmd, sizeof(md)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_getdate.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_getdate.c new file mode 100644 index 0000000..9e91b83 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_getdate.c @@ -0,0 +1,89 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +#include + +#define __LIBARCHIVE_BUILD 1 +#include "archive_getdate.h" + +/* + * Verify that the getdate() function works. + */ + +#define get_date __archive_get_date + +DEFINE_TEST(test_archive_getdate) +{ + time_t now = time(NULL); + + assertEqualInt(get_date(now, "Jan 1, 1970 UTC"), 0); + assertEqualInt(get_date(now, "7:12:18-0530 4 May 1983"), 420900138); + assertEqualInt(get_date(now, "2004/01/29 513 mest"), 1075345980); + assertEqualInt(get_date(now, "99/02/17 7pm utc"), 919278000); + assertEqualInt(get_date(now, "02/17/99 7:11am est"), 919253460); + assertEqualInt(get_date(now, "now - 2 hours"), + get_date(now, "2 hours ago")); + assertEqualInt(get_date(now, "2 hours ago"), + get_date(now, "+2 hours ago")); + assertEqualInt(get_date(now, "now - 2 hours"), + get_date(now, "-2 hours")); + /* It's important that we handle ctime() format. */ + assertEqualInt(get_date(now, "Sun Feb 22 17:38:26 PST 2009"), + 1235353106); + /* Basic relative offsets. */ + /* If we use the actual current time as the reference, then + * these tests break around DST changes, so it's actually + * important to use a specific reference time here. */ + assertEqualInt(get_date(0, "tomorrow"), 24 * 60 * 60); + assertEqualInt(get_date(0, "yesterday"), - 24 * 60 * 60); + assertEqualInt(get_date(0, "now + 1 hour"), 60 * 60); + assertEqualInt(get_date(0, "now + 1 hour + 1 minute"), 60 * 60 + 60); + /* Repeat the above for a different start time. */ + now = 1231113600; /* Jan 5, 2009 00:00 UTC */ + assertEqualInt(get_date(0, "Jan 5, 2009 00:00 UTC"), now); + assertEqualInt(get_date(now, "tomorrow"), now + 24 * 60 * 60); + assertEqualInt(get_date(now, "yesterday"), now - 24 * 60 * 60); + assertEqualInt(get_date(now, "now + 1 hour"), now + 60 * 60); + assertEqualInt(get_date(now, "now + 1 hour + 1 minute"), + now + 60 * 60 + 60); + assertEqualInt(get_date(now, "tomorrow 5:16am UTC"), + now + 24 * 60 * 60 + 5 * 60 * 60 + 16 * 60); + assertEqualInt(get_date(now, "UTC 5:16am tomorrow"), + now + 24 * 60 * 60 + 5 * 60 * 60 + 16 * 60); + + /* Jan 5, 2009 was a Monday. */ + assertEqualInt(get_date(now, "monday UTC"), now); + assertEqualInt(get_date(now, "sunday UTC"), now + 6 * 24 * 60 * 60); + assertEqualInt(get_date(now, "tuesday UTC"), now + 24 * 60 * 60); + /* "next tuesday" is one week after "tuesday" */ + assertEqualInt(get_date(now, "UTC next tuesday"), + now + 8 * 24 * 60 * 60); + /* "last tuesday" is one week before "tuesday" */ + assertEqualInt(get_date(now, "last tuesday UTC"), + now - 6 * 24 * 60 * 60); + /* TODO: Lots more tests here. */ +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_match_owner.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_match_owner.c new file mode 100644 index 0000000..6bf9c6f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_match_owner.c @@ -0,0 +1,289 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +static void +test_uid(void) +{ + struct archive_entry *ae; + struct archive *m; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + + assertEqualIntA(m, 0, archive_match_include_uid(m, 1000)); + assertEqualIntA(m, 0, archive_match_include_uid(m, 1002)); + + archive_entry_set_uid(ae, 0); + failure("uid 0 should be excluded"); + assertEqualInt(1, archive_match_owner_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + archive_entry_set_uid(ae, 1000); + failure("uid 1000 should not be excluded"); + assertEqualInt(0, archive_match_owner_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + archive_entry_set_uid(ae, 1001); + failure("uid 1001 should be excluded"); + assertEqualInt(1, archive_match_owner_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + archive_entry_set_uid(ae, 1002); + failure("uid 1002 should not be excluded"); + assertEqualInt(0, archive_match_owner_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + archive_entry_set_uid(ae, 1003); + failure("uid 1003 should be excluded"); + assertEqualInt(1, archive_match_owner_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_entry_free(ae); + archive_match_free(m); +} + +static void +test_gid(void) +{ + struct archive_entry *ae; + struct archive *m; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + + assertEqualIntA(m, 0, archive_match_include_gid(m, 1000)); + assertEqualIntA(m, 0, archive_match_include_gid(m, 1002)); + + archive_entry_set_gid(ae, 0); + failure("uid 0 should be excluded"); + assertEqualInt(1, archive_match_owner_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + archive_entry_set_gid(ae, 1000); + failure("uid 1000 should not be excluded"); + assertEqualInt(0, archive_match_owner_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + archive_entry_set_gid(ae, 1001); + failure("uid 1001 should be excluded"); + assertEqualInt(1, archive_match_owner_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + archive_entry_set_gid(ae, 1002); + failure("uid 1002 should not be excluded"); + assertEqualInt(0, archive_match_owner_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + archive_entry_set_gid(ae, 1003); + failure("uid 1003 should be excluded"); + assertEqualInt(1, archive_match_owner_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_entry_free(ae); + archive_match_free(m); +} + +static void +test_uname_mbs(void) +{ + struct archive_entry *ae; + struct archive *m; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + + assertEqualIntA(m, 0, archive_match_include_uname(m, "foo")); + assertEqualIntA(m, 0, archive_match_include_uname(m, "bar")); + + archive_entry_copy_uname(ae, "unknown"); + failure("User 'unknown' should be excluded"); + assertEqualInt(1, archive_match_owner_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + archive_entry_copy_uname(ae, "foo"); + failure("User 'foo' should not be excluded"); + assertEqualInt(0, archive_match_owner_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + archive_entry_copy_uname(ae, "foo1"); + failure("User 'foo1' should be excluded"); + assertEqualInt(1, archive_match_owner_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + archive_entry_copy_uname(ae, "bar"); + failure("User 'bar' should not be excluded"); + assertEqualInt(0, archive_match_owner_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + archive_entry_copy_uname(ae, "bar1"); + failure("User 'bar1' should be excluded"); + assertEqualInt(1, archive_match_owner_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_entry_free(ae); + archive_match_free(m); +} + +static void +test_uname_wcs(void) +{ + struct archive_entry *ae; + struct archive *m; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + + assertEqualIntA(m, 0, archive_match_include_uname_w(m, L"foo")); + assertEqualIntA(m, 0, archive_match_include_uname_w(m, L"bar")); + + archive_entry_copy_uname_w(ae, L"unknown"); + failure("User 'unknown' should be excluded"); + assertEqualInt(1, archive_match_owner_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + archive_entry_copy_uname_w(ae, L"foo"); + failure("User 'foo' should not be excluded"); + assertEqualInt(0, archive_match_owner_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + archive_entry_copy_uname_w(ae, L"foo1"); + failure("User 'foo1' should be excluded"); + assertEqualInt(1, archive_match_owner_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + archive_entry_copy_uname_w(ae, L"bar"); + failure("User 'bar' should not be excluded"); + assertEqualInt(0, archive_match_owner_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + archive_entry_copy_uname_w(ae, L"bar1"); + failure("User 'bar1' should be excluded"); + assertEqualInt(1, archive_match_owner_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_entry_free(ae); + archive_match_free(m); +} + +static void +test_gname_mbs(void) +{ + struct archive_entry *ae; + struct archive *m; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + + assertEqualIntA(m, 0, archive_match_include_gname(m, "foo")); + assertEqualIntA(m, 0, archive_match_include_gname(m, "bar")); + + archive_entry_copy_gname(ae, "unknown"); + failure("Group 'unknown' should be excluded"); + assertEqualInt(1, archive_match_owner_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + archive_entry_copy_gname(ae, "foo"); + failure("Group 'foo' should not be excluded"); + assertEqualInt(0, archive_match_owner_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + archive_entry_copy_gname(ae, "foo1"); + failure("Group 'foo1' should be excluded"); + assertEqualInt(1, archive_match_owner_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + archive_entry_copy_gname(ae, "bar"); + failure("Group 'bar' should not be excluded"); + assertEqualInt(0, archive_match_owner_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + archive_entry_copy_gname(ae, "bar1"); + failure("Group 'bar1' should be excluded"); + assertEqualInt(1, archive_match_owner_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_entry_free(ae); + archive_match_free(m); +} + +static void +test_gname_wcs(void) +{ + struct archive_entry *ae; + struct archive *m; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + + assertEqualIntA(m, 0, archive_match_include_gname_w(m, L"foo")); + assertEqualIntA(m, 0, archive_match_include_gname_w(m, L"bar")); + + archive_entry_copy_gname_w(ae, L"unknown"); + failure("Group 'unknown' should be excluded"); + assertEqualInt(1, archive_match_owner_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + archive_entry_copy_gname_w(ae, L"foo"); + failure("Group 'foo' should not be excluded"); + assertEqualInt(0, archive_match_owner_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + archive_entry_copy_gname_w(ae, L"foo1"); + failure("Group 'foo1' should be excluded"); + assertEqualInt(1, archive_match_owner_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + archive_entry_copy_gname_w(ae, L"bar"); + failure("Group 'bar' should not be excluded"); + assertEqualInt(0, archive_match_owner_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + archive_entry_copy_gname_w(ae, L"bar1"); + failure("Group 'bar1' should be excluded"); + assertEqualInt(1, archive_match_owner_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_entry_free(ae); + archive_match_free(m); +} + +DEFINE_TEST(test_archive_match_owner) +{ + test_uid(); + test_gid(); + test_uname_mbs(); + test_uname_wcs(); + test_gname_mbs(); + test_gname_wcs(); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_match_path.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_match_path.c new file mode 100644 index 0000000..5e9b9a8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_match_path.c @@ -0,0 +1,450 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +static void +test_exclusion_mbs(void) +{ + struct archive_entry *ae; + struct archive *m; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + + /* Test for pattern "^aa*" */ + assertEqualIntA(m, 0, archive_match_exclude_pattern(m, "^aa*")); + + /* Test with 'aa1234', which should be excluded. */ + archive_entry_copy_pathname(ae, "aa1234"); + failure("'aa1234' should be excluded"); + assertEqualInt(1, archive_match_path_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + archive_entry_clear(ae); + archive_entry_copy_pathname_w(ae, L"aa1234"); + failure("'aa1234' should be excluded"); + assertEqualInt(1, archive_match_path_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Test with 'a1234', which should not be excluded. */ + archive_entry_copy_pathname(ae, "a1234"); + failure("'a1234' should not be excluded"); + assertEqualInt(0, archive_match_path_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + archive_entry_clear(ae); + archive_entry_copy_pathname_w(ae, L"a1234"); + failure("'a1234' should not be excluded"); + assertEqualInt(0, archive_match_path_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_entry_free(ae); + archive_match_free(m); +} + +static void +test_exclusion_wcs(void) +{ + struct archive_entry *ae; + struct archive *m; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + + /* Test for pattern "^aa*" */ + assertEqualIntA(m, 0, archive_match_exclude_pattern_w(m, L"^aa*")); + + /* Test with 'aa1234', which should be excluded. */ + archive_entry_copy_pathname(ae, "aa1234"); + failure("'aa1234' should be excluded"); + assertEqualInt(1, archive_match_path_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + archive_entry_clear(ae); + archive_entry_copy_pathname_w(ae, L"aa1234"); + failure("'aa1234' should be excluded"); + assertEqualInt(1, archive_match_path_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Test with 'a1234', which should not be excluded. */ + archive_entry_copy_pathname(ae, "a1234"); + failure("'a1234' should not be excluded"); + assertEqualInt(0, archive_match_path_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + archive_entry_clear(ae); + archive_entry_copy_pathname_w(ae, L"a1234"); + failure("'a1234' should not be excluded"); + assertEqualInt(0, archive_match_path_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_entry_free(ae); + archive_match_free(m); +} + +static void +exclusion_from_file(struct archive *m) +{ + struct archive_entry *ae; + + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + + /* Test with 'first', which should not be excluded. */ + archive_entry_copy_pathname(ae, "first"); + failure("'first' should not be excluded"); + assertEqualInt(0, archive_match_path_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + archive_entry_clear(ae); + archive_entry_copy_pathname_w(ae, L"first"); + failure("'first' should not be excluded"); + assertEqualInt(0, archive_match_path_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + /* Test with 'second', which should be excluded. */ + archive_entry_copy_pathname(ae, "second"); + failure("'second' should be excluded"); + assertEqualInt(1, archive_match_path_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + archive_entry_clear(ae); + archive_entry_copy_pathname_w(ae, L"second"); + failure("'second' should be excluded"); + assertEqualInt(1, archive_match_path_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Test with 'third', which should not be excluded. */ + archive_entry_copy_pathname(ae, "third"); + failure("'third' should not be excluded"); + assertEqualInt(0, archive_match_path_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + archive_entry_clear(ae); + archive_entry_copy_pathname_w(ae, L"third"); + failure("'third' should not be excluded"); + assertEqualInt(0, archive_match_path_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + /* Test with 'four', which should be excluded. */ + archive_entry_copy_pathname(ae, "four"); + failure("'four' should be excluded"); + assertEqualInt(1, archive_match_path_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + archive_entry_clear(ae); + archive_entry_copy_pathname_w(ae, L"four"); + failure("'four' should be excluded"); + assertEqualInt(1, archive_match_path_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_entry_free(ae); +} + +static void +test_exclusion_from_file_mbs(void) +{ + struct archive *m; + + /* Test1: read exclusion patterns from file */ + if (!assert((m = archive_match_new()) != NULL)) + return; + assertEqualIntA(m, 0, + archive_match_exclude_pattern_from_file(m, "exclusion", 0)); + exclusion_from_file(m); + /* Clean up. */ + archive_match_free(m); + + /* Test2: read exclusion patterns in a null separator from file */ + if (!assert((m = archive_match_new()) != NULL)) + return; + /* Test for pattern reading from file */ + assertEqualIntA(m, 0, + archive_match_exclude_pattern_from_file(m, "exclusion_null", 1)); + exclusion_from_file(m); + /* Clean up. */ + archive_match_free(m); +} + +static void +test_exclusion_from_file_wcs(void) +{ + struct archive *m; + + /* Test1: read exclusion patterns from file */ + if (!assert((m = archive_match_new()) != NULL)) + return; + assertEqualIntA(m, 0, + archive_match_exclude_pattern_from_file_w(m, L"exclusion", 0)); + exclusion_from_file(m); + /* Clean up. */ + archive_match_free(m); + + /* Test2: read exclusion patterns in a null separator from file */ + if (!assert((m = archive_match_new()) != NULL)) + return; + /* Test for pattern reading from file */ + assertEqualIntA(m, 0, + archive_match_exclude_pattern_from_file_w(m, L"exclusion_null", 1)); + exclusion_from_file(m); + /* Clean up. */ + archive_match_free(m); +} + +static void +test_inclusion_mbs(void) +{ + struct archive_entry *ae; + struct archive *m; + const char *mp; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + + /* Test for pattern "^aa*" */ + assertEqualIntA(m, 0, archive_match_include_pattern(m, "^aa*")); + + /* Test with 'aa1234', which should not be excluded. */ + archive_entry_copy_pathname(ae, "aa1234"); + failure("'aa1234' should not be excluded"); + assertEqualInt(0, archive_match_path_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + archive_entry_clear(ae); + archive_entry_copy_pathname_w(ae, L"aa1234"); + failure("'aa1234' should not be excluded"); + assertEqualInt(0, archive_match_path_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + /* Test with 'a1234', which should be excluded. */ + archive_entry_copy_pathname(ae, "a1234"); + failure("'a1234' should be excluded"); + assertEqualInt(1, archive_match_path_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + archive_entry_clear(ae); + archive_entry_copy_pathname_w(ae, L"a1234"); + failure("'a1234' should be excluded"); + assertEqualInt(1, archive_match_path_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Verify unmatched_inclusions. */ + assertEqualInt(0, archive_match_path_unmatched_inclusions(m)); + assertEqualIntA(m, ARCHIVE_EOF, + archive_match_path_unmatched_inclusions_next(m, &mp)); + + /* Clean up. */ + archive_entry_free(ae); + archive_match_free(m); +} + +static void +test_inclusion_wcs(void) +{ + struct archive_entry *ae; + struct archive *m; + const char *mp; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + + /* Test for pattern "^aa*" */ + assertEqualIntA(m, 0, archive_match_include_pattern_w(m, L"^aa*")); + + /* Test with 'aa1234', which should not be excluded. */ + archive_entry_copy_pathname(ae, "aa1234"); + failure("'aa1234' should not be excluded"); + assertEqualInt(0, archive_match_path_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + archive_entry_clear(ae); + archive_entry_copy_pathname_w(ae, L"aa1234"); + failure("'aa1234' should not be excluded"); + assertEqualInt(0, archive_match_path_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + /* Test with 'a1234', which should be excluded. */ + archive_entry_copy_pathname(ae, "a1234"); + failure("'a1234' should be excluded"); + assertEqualInt(1, archive_match_path_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + archive_entry_clear(ae); + archive_entry_copy_pathname_w(ae, L"a1234"); + failure("'a1234' should be excluded"); + assertEqualInt(1, archive_match_path_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Verify unmatched_inclusions. */ + assertEqualInt(0, archive_match_path_unmatched_inclusions(m)); + assertEqualIntA(m, ARCHIVE_EOF, + archive_match_path_unmatched_inclusions_next(m, &mp)); + + /* Clean up. */ + archive_entry_free(ae); + archive_match_free(m); +} + +static void +test_inclusion_from_file_mbs(void) +{ + struct archive *m; + + /* Test1: read inclusion patterns from file */ + if (!assert((m = archive_match_new()) != NULL)) + return; + assertEqualIntA(m, 0, + archive_match_include_pattern_from_file(m, "inclusion", 0)); + exclusion_from_file(m); + /* Clean up. */ + archive_match_free(m); + + /* Test2: read inclusion patterns in a null separator from file */ + if (!assert((m = archive_match_new()) != NULL)) + return; + assertEqualIntA(m, 0, + archive_match_include_pattern_from_file(m, "inclusion_null", 1)); + exclusion_from_file(m); + /* Clean up. */ + archive_match_free(m); +} + +static void +test_inclusion_from_file_wcs(void) +{ + struct archive *m; + + /* Test1: read inclusion patterns from file */ + if (!assert((m = archive_match_new()) != NULL)) + return; + /* Test for pattern reading from file */ + assertEqualIntA(m, 0, + archive_match_include_pattern_from_file_w(m, L"inclusion", 0)); + exclusion_from_file(m); + /* Clean up. */ + archive_match_free(m); + + /* Test2: read inclusion patterns in a null separator from file */ + if (!assert((m = archive_match_new()) != NULL)) + return; + /* Test for pattern reading from file */ + assertEqualIntA(m, 0, + archive_match_include_pattern_from_file_w(m, L"inclusion_null", 1)); + exclusion_from_file(m); + /* Clean up. */ + archive_match_free(m); +} + +static void +test_exclusion_and_inclusion(void) +{ + struct archive_entry *ae; + struct archive *m; + const char *mp; + const wchar_t *wp; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + + assertEqualIntA(m, 0, archive_match_exclude_pattern(m, "^aaa*")); + assertEqualIntA(m, 0, archive_match_include_pattern_w(m, L"^aa*")); + assertEqualIntA(m, 0, archive_match_include_pattern(m, "^a1*")); + + /* Test with 'aa1234', which should not be excluded. */ + archive_entry_copy_pathname(ae, "aa1234"); + failure("'aa1234' should not be excluded"); + assertEqualInt(0, archive_match_path_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + archive_entry_clear(ae); + archive_entry_copy_pathname_w(ae, L"aa1234"); + failure("'aa1234' should not be excluded"); + assertEqualInt(0, archive_match_path_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + /* Test with 'aaa1234', which should be excluded. */ + archive_entry_copy_pathname(ae, "aaa1234"); + failure("'aaa1234' should be excluded"); + assertEqualInt(1, archive_match_path_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + archive_entry_clear(ae); + archive_entry_copy_pathname_w(ae, L"aaa1234"); + failure("'aaa1234' should be excluded"); + assertEqualInt(1, archive_match_path_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Verify unmatched_inclusions. */ + assertEqualInt(1, archive_match_path_unmatched_inclusions(m)); + /* Verify unmatched inclusion patterns. */ + assertEqualIntA(m, ARCHIVE_OK, + archive_match_path_unmatched_inclusions_next(m, &mp)); + assertEqualString("^a1*", mp); + assertEqualIntA(m, ARCHIVE_EOF, + archive_match_path_unmatched_inclusions_next(m, &mp)); + /* Verify unmatched inclusion patterns again in Wide-Char. */ + assertEqualIntA(m, ARCHIVE_OK, + archive_match_path_unmatched_inclusions_next_w(m, &wp)); + assertEqualWString(L"^a1*", wp); + assertEqualIntA(m, ARCHIVE_EOF, + archive_match_path_unmatched_inclusions_next_w(m, &wp)); + + /* Clean up. */ + archive_entry_free(ae); + archive_match_free(m); +} + +DEFINE_TEST(test_archive_match_path) +{ + /* Make exclusion sample files which contain exclusion patterns. */ + assertMakeFile("exclusion", 0666, "second\nfour\n"); + assertMakeBinFile("exclusion_null", 0666, 12, "second\0four\0"); + /* Make inclusion sample files which contain inclusion patterns. */ + assertMakeFile("inclusion", 0666, "first\nthird\n"); + assertMakeBinFile("inclusion_null", 0666, 12, "first\0third\0"); + + test_exclusion_mbs(); + test_exclusion_wcs(); + test_exclusion_from_file_mbs(); + test_exclusion_from_file_wcs(); + test_inclusion_mbs(); + test_inclusion_wcs(); + test_inclusion_from_file_mbs(); + test_inclusion_from_file_wcs(); + test_exclusion_and_inclusion(); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_match_time.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_match_time.c new file mode 100644 index 0000000..c6864b3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_match_time.c @@ -0,0 +1,1359 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +#define __LIBARCHIVE_BUILD 1 +#include "archive_getdate.h" + +static void +test_newer_time(void) +{ + struct archive_entry *ae; + struct archive *m; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + + assertEqualIntA(m, 0, archive_match_include_time(m, + ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME | + ARCHIVE_MATCH_NEWER, 7880, 0)); + + archive_entry_copy_pathname(ae, "file1"); + archive_entry_set_mtime(ae, 7880, 0); + archive_entry_set_ctime(ae, 7880, 0); + failure("Both Its mtime and ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + archive_entry_set_mtime(ae, 7879, 999); + archive_entry_set_ctime(ae, 7879, 999); + failure("Both Its mtime and ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + archive_entry_set_mtime(ae, 7881, 0); + archive_entry_set_ctime(ae, 7881, 0); + failure("Both Its mtime and ctime should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + archive_entry_set_mtime(ae, 7880, 1); + archive_entry_set_ctime(ae, 7880, 0); + failure("Its mtime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + archive_entry_set_mtime(ae, 7880, 0); + archive_entry_set_ctime(ae, 7880, 1); + failure("Its ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_entry_free(ae); + archive_match_free(m); +} + +static void +test_newer_time_str(void) +{ + struct archive_entry *ae; + struct archive *m; + time_t now, t; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + + time(&now); + + assertEqualIntA(m, 0, archive_match_include_date(m, + ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME | + ARCHIVE_MATCH_NEWER, "1980/2/1 0:0:0 UTC")); + + /* Test1: Allow newer time. */ + archive_entry_copy_pathname(ae, "file1"); + t = __archive_get_date(now, "1980/2/1 0:0:0 UTC"); + archive_entry_set_mtime(ae, t, 0); + archive_entry_set_ctime(ae, t, 0); + failure("Both Its mtime and ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + t = __archive_get_date(now, "1980/1/1 0:0:0 UTC"); + archive_entry_set_mtime(ae, t, 0); + archive_entry_set_ctime(ae, t, 0); + failure("Both Its mtime and ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + t = __archive_get_date(now, "1980/2/1 0:0:1 UTC"); + archive_entry_set_mtime(ae, t, 0); + archive_entry_set_ctime(ae, t, 0); + failure("Both Its mtime and ctime should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + t = __archive_get_date(now, "1980/2/1 0:0:0 UTC"); + archive_entry_set_mtime(ae, t, 1); + archive_entry_set_ctime(ae, t, 0); + failure("Its mtime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + archive_entry_set_mtime(ae, t, 0); + archive_entry_set_ctime(ae, t, 1); + failure("Its ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + + /* Test2: Allow equal or newer time. */ + assertEqualIntA(m, 0, archive_match_include_date(m, + ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME | + ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_EQUAL, + "1980/2/1 0:0:0 UTC")); + + archive_entry_copy_pathname(ae, "file1"); + t = __archive_get_date(now, "1980/2/1 0:0:0 UTC"); + archive_entry_set_mtime(ae, t, 0); + archive_entry_set_ctime(ae, t, 0); + failure("Both Its mtime and ctime should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + t = __archive_get_date(now, "1980/1/1 0:0:0 UTC"); + archive_entry_set_mtime(ae, t, 0); + archive_entry_set_ctime(ae, t, 0); + failure("Both Its mtime and ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + t = __archive_get_date(now, "1980/2/1 0:0:1 UTC"); + archive_entry_set_mtime(ae, t, 0); + archive_entry_set_ctime(ae, t, 0); + failure("Both Its mtime and ctime should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_entry_free(ae); + archive_match_free(m); +} + +static void +test_newer_time_str_w(void) +{ + struct archive_entry *ae; + struct archive *m; + time_t now, t; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + + time(&now); + + assertEqualIntA(m, 0, archive_match_include_date_w(m, + ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME | + ARCHIVE_MATCH_NEWER, L"1980/2/1 0:0:0 UTC")); + + /* Test1: Allow newer time. */ + archive_entry_copy_pathname(ae, "file1"); + t = __archive_get_date(now, "1980/2/1 0:0:0 UTC"); + archive_entry_set_mtime(ae, t, 0); + archive_entry_set_ctime(ae, t, 0); + failure("Both Its mtime and ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + t = __archive_get_date(now, "1980/1/1 0:0:0 UTC"); + archive_entry_set_mtime(ae, t, 0); + archive_entry_set_ctime(ae, t, 0); + failure("Both Its mtime and ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + t = __archive_get_date(now, "1980/2/1 0:0:1 UTC"); + archive_entry_set_mtime(ae, t, 0); + archive_entry_set_ctime(ae, t, 0); + failure("Both Its mtime and ctime should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + t = __archive_get_date(now, "1980/2/1 0:0:0 UTC"); + archive_entry_set_mtime(ae, t, 1); + archive_entry_set_ctime(ae, t, 0); + failure("Its mtime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + archive_entry_set_mtime(ae, t, 0); + archive_entry_set_ctime(ae, t, 1); + failure("Its ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + + /* Test2: Allow equal or newer time. */ + assertEqualIntA(m, 0, archive_match_include_date_w(m, + ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME | + ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_EQUAL, + L"1980/2/1 0:0:0 UTC")); + + archive_entry_copy_pathname(ae, "file1"); + t = __archive_get_date(now, "1980/2/1 0:0:0 UTC"); + archive_entry_set_mtime(ae, t, 0); + archive_entry_set_ctime(ae, t, 0); + failure("Both Its mtime and ctime should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + t = __archive_get_date(now, "1980/1/1 0:0:0 UTC"); + archive_entry_set_mtime(ae, t, 0); + archive_entry_set_ctime(ae, t, 0); + failure("Both Its mtime and ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + t = __archive_get_date(now, "1980/2/1 0:0:1 UTC"); + archive_entry_set_mtime(ae, t, 0); + archive_entry_set_ctime(ae, t, 0); + failure("Both Its mtime and ctime should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_entry_free(ae); + archive_match_free(m); +} + +static void +test_newer_mtime_than_file_mbs(void) +{ + struct archive *a; + struct archive_entry *ae; + struct archive *m; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + if (!assert((a = archive_read_disk_new()) != NULL)) { + archive_match_free(m); + archive_entry_free(ae); + return; + } + + /* + * Test: newer mtime than a file specified in MBS file name. + */ + assertEqualIntA(m, 0, archive_match_include_file_time(m, + ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_NEWER, "mid_mtime")); + + /* Verify 'old_mtime' file. */ + archive_entry_copy_pathname(ae, "old_mtime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("old_mtime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Verify 'mid_mtime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "mid_mtime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("mid_mtime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Verify 'new_mtime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "new_mtime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("new_mtime should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_read_free(a); + archive_entry_free(ae); + archive_match_free(m); +} + +static void +test_newer_ctime_than_file_mbs(void) +{ + struct archive *a; + struct archive_entry *ae; + struct archive *m; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + if (!assert((a = archive_read_disk_new()) != NULL)) { + archive_match_free(m); + archive_entry_free(ae); + return; + } + + /* + * Test: newer ctime than a file specified in MBS file name. + */ + assertEqualIntA(m, 0, archive_match_include_file_time(m, + ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_NEWER, "mid_ctime")); + + /* Verify 'old_ctime' file. */ + archive_entry_copy_pathname(ae, "old_ctime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("old_ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Verify 'mid_ctime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "mid_ctime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("mid_ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Verify 'new_ctime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "new_ctime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("new_ctime should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_read_free(a); + archive_entry_free(ae); + archive_match_free(m); +} + +static void +test_newer_mtime_than_file_wcs(void) +{ + struct archive *a; + struct archive_entry *ae; + struct archive *m; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + if (!assert((a = archive_read_disk_new()) != NULL)) { + archive_match_free(m); + archive_entry_free(ae); + return; + } + + /* + * Test: newer mtime than a file specified in WCS file name. + */ + assertEqualIntA(m, 0, archive_match_include_file_time_w(m, + ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_NEWER, L"mid_mtime")); + + /* Verify 'old_mtime' file. */ + archive_entry_copy_pathname(ae, "old_mtime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("old_mtime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Verify 'mid_mtime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "mid_mtime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("mid_mtime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Verify 'new_mtime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "new_mtime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("new_mtime should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_read_free(a); + archive_entry_free(ae); + archive_match_free(m); +} + +static void +test_newer_ctime_than_file_wcs(void) +{ + struct archive *a; + struct archive_entry *ae; + struct archive *m; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + if (!assert((a = archive_read_disk_new()) != NULL)) { + archive_match_free(m); + archive_entry_free(ae); + return; + } + + /* + * Test: newer ctime than a file specified in WCS file name. + */ + assertEqualIntA(m, 0, archive_match_include_file_time_w(m, + ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_NEWER, L"mid_ctime")); + + /* Verify 'old_ctime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "old_ctime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("old_ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Verify 'mid_ctime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "mid_ctime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("mid_ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Verify 'new_ctime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "new_ctime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("new_ctime should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_read_free(a); + archive_entry_free(ae); + archive_match_free(m); +} + +static void +test_older_time(void) +{ + struct archive_entry *ae; + struct archive *m; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + + assertEqualIntA(m, 0, archive_match_include_time(m, + ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME | + ARCHIVE_MATCH_OLDER, 7880, 0)); + + archive_entry_copy_pathname(ae, "file1"); + archive_entry_set_mtime(ae, 7880, 0); + archive_entry_set_ctime(ae, 7880, 0); + failure("Both Its mtime and ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + archive_entry_set_mtime(ae, 7879, 999); + archive_entry_set_ctime(ae, 7879, 999); + failure("Both Its mtime and ctime should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + archive_entry_set_mtime(ae, 7881, 0); + archive_entry_set_ctime(ae, 7881, 0); + failure("Both Its mtime and ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + archive_entry_set_mtime(ae, 7880, 1); + archive_entry_set_ctime(ae, 7879, 0); + failure("Its mtime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + archive_entry_set_mtime(ae, 7879, 0); + archive_entry_set_ctime(ae, 7880, 1); + failure("Its ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_entry_free(ae); + archive_match_free(m); +} + +static void +test_older_time_str(void) +{ + struct archive_entry *ae; + struct archive *m; + time_t now, t; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + + time(&now); + + /* Test1: Allow newer time. */ + assertEqualIntA(m, 0, archive_match_include_date(m, + ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME | + ARCHIVE_MATCH_OLDER, "1980/2/1 0:0:0 UTC")); + + archive_entry_copy_pathname(ae, "file1"); + t = __archive_get_date(now, "1980/2/1 0:0:0 UTC"); + archive_entry_set_mtime(ae, t, 0); + archive_entry_set_ctime(ae, t, 0); + failure("Both Its mtime and ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + t = __archive_get_date(now, "1980/1/1 0:0:0 UTC"); + archive_entry_set_mtime(ae, t, 0); + archive_entry_set_ctime(ae, t, 0); + failure("Both Its mtime and ctime should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + t = __archive_get_date(now, "1980/3/1 0:0:0 UTC"); + archive_entry_set_mtime(ae, t, 0); + archive_entry_set_ctime(ae, t, 0); + failure("Both Its mtime and ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + t = __archive_get_date(now, "1980/3/1 0:0:0 UTC"); + archive_entry_set_mtime(ae, t, 0); + t = __archive_get_date(now, "1980/1/1 0:0:0 UTC"); + archive_entry_set_ctime(ae, t, 0); + failure("Its mtime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + t = __archive_get_date(now, "1980/1/1 0:0:0 UTC"); + archive_entry_set_mtime(ae, t, 0); + t = __archive_get_date(now, "1980/3/1 0:0:0 UTC"); + archive_entry_set_ctime(ae, t, 0); + failure("Its ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Test2: Allow equal or newer time. */ + assertEqualIntA(m, 0, archive_match_include_date(m, + ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME | + ARCHIVE_MATCH_OLDER | ARCHIVE_MATCH_EQUAL, + "1980/2/1 0:0:0 UTC")); + + archive_entry_copy_pathname(ae, "file1"); + t = __archive_get_date(now, "1980/2/1 0:0:0 UTC"); + archive_entry_set_mtime(ae, t, 0); + archive_entry_set_ctime(ae, t, 0); + failure("Both Its mtime and ctime should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + t = __archive_get_date(now, "1980/1/1 0:0:0 UTC"); + archive_entry_set_mtime(ae, t, 0); + archive_entry_set_ctime(ae, t, 0); + failure("Both Its mtime and ctime should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + t = __archive_get_date(now, "1980/3/1 0:0:0 UTC"); + archive_entry_set_mtime(ae, t, 0); + archive_entry_set_ctime(ae, t, 0); + failure("Both Its mtime and ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_entry_free(ae); + archive_match_free(m); +} + +static void +test_older_time_str_w(void) +{ + struct archive_entry *ae; + struct archive *m; + time_t now, t; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + + time(&now); + + /* Test1: Allow newer time. */ + assertEqualIntA(m, 0, archive_match_include_date_w(m, + ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME | + ARCHIVE_MATCH_OLDER, L"1980/2/1 0:0:0 UTC")); + + archive_entry_copy_pathname(ae, "file1"); + t = __archive_get_date(now, "1980/2/1 0:0:0 UTC"); + archive_entry_set_mtime(ae, t, 0); + archive_entry_set_ctime(ae, t, 0); + failure("Both Its mtime and ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + t = __archive_get_date(now, "1980/1/1 0:0:0 UTC"); + archive_entry_set_mtime(ae, t, 0); + archive_entry_set_ctime(ae, t, 0); + failure("Both Its mtime and ctime should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + t = __archive_get_date(now, "1980/3/1 0:0:0 UTC"); + archive_entry_set_mtime(ae, t, 0); + archive_entry_set_ctime(ae, t, 0); + failure("Both Its mtime and ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + t = __archive_get_date(now, "1980/3/1 0:0:0 UTC"); + archive_entry_set_mtime(ae, t, 0); + t = __archive_get_date(now, "1980/1/1 0:0:0 UTC"); + archive_entry_set_ctime(ae, t, 0); + failure("Its mtime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + t = __archive_get_date(now, "1980/1/1 0:0:0 UTC"); + archive_entry_set_mtime(ae, t, 0); + t = __archive_get_date(now, "1980/3/1 0:0:0 UTC"); + archive_entry_set_ctime(ae, t, 0); + failure("Its ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Test2: Allow equal or newer time. */ + assertEqualIntA(m, 0, archive_match_include_date_w(m, + ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME | + ARCHIVE_MATCH_OLDER | ARCHIVE_MATCH_EQUAL, + L"1980/2/1 0:0:0 UTC")); + + archive_entry_copy_pathname(ae, "file1"); + t = __archive_get_date(now, "1980/2/1 0:0:0 UTC"); + archive_entry_set_mtime(ae, t, 0); + archive_entry_set_ctime(ae, t, 0); + failure("Both Its mtime and ctime should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + t = __archive_get_date(now, "1980/1/1 0:0:0 UTC"); + archive_entry_set_mtime(ae, t, 0); + archive_entry_set_ctime(ae, t, 0); + failure("Both Its mtime and ctime should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + t = __archive_get_date(now, "1980/3/1 0:0:0 UTC"); + archive_entry_set_mtime(ae, t, 0); + archive_entry_set_ctime(ae, t, 0); + failure("Both Its mtime and ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_entry_free(ae); + archive_match_free(m); +} + +static void +test_older_mtime_than_file_mbs(void) +{ + struct archive *a; + struct archive_entry *ae; + struct archive *m; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + if (!assert((a = archive_read_disk_new()) != NULL)) { + archive_match_free(m); + archive_entry_free(ae); + return; + } + + /* + * Test: older mtime than a file specified in MBS file name. + */ + assertEqualIntA(m, 0, archive_match_include_file_time(m, + ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER, "mid_mtime")); + + /* Verify 'old_mtime' file. */ + archive_entry_copy_pathname(ae, "old_mtime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("old_mtime should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + /* Verify 'mid_mtime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "mid_mtime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("mid_mtime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Verify 'new_mtime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "new_mtime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("new_mtime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_read_free(a); + archive_entry_free(ae); + archive_match_free(m); +} + +static void +test_older_ctime_than_file_mbs(void) +{ + struct archive *a; + struct archive_entry *ae; + struct archive *m; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + if (!assert((a = archive_read_disk_new()) != NULL)) { + archive_match_free(m); + archive_entry_free(ae); + return; + } + + /* + * Test: older ctime than a file specified in MBS file name. + */ + assertEqualIntA(m, 0, archive_match_include_file_time(m, + ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_OLDER, "mid_ctime")); + + /* Verify 'old_ctime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "old_ctime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("old_ctime should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + /* Verify 'mid_ctime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "mid_ctime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("mid_ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Verify 'new_ctime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "new_ctime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("new_ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_read_free(a); + archive_entry_free(ae); + archive_match_free(m); +} + +static void +test_older_mtime_than_file_wcs(void) +{ + struct archive *a; + struct archive_entry *ae; + struct archive *m; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + if (!assert((a = archive_read_disk_new()) != NULL)) { + archive_match_free(m); + archive_entry_free(ae); + return; + } + + /* + * Test: older mtime than a file specified in WCS file name. + */ + assertEqualIntA(m, 0, archive_match_include_file_time_w(m, + ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER, L"mid_mtime")); + + /* Verify 'old_mtime' file. */ + archive_entry_copy_pathname(ae, "old_mtime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("old_mtime should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + /* Verify 'mid_mtime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "mid_mtime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("mid_mtime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Verify 'new_mtime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "new_mtime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("new_mtime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_read_free(a); + archive_entry_free(ae); + archive_match_free(m); +} + +static void +test_older_ctime_than_file_wcs(void) +{ + struct archive *a; + struct archive_entry *ae; + struct archive *m; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + if (!assert((a = archive_read_disk_new()) != NULL)) { + archive_match_free(m); + archive_entry_free(ae); + return; + } + + /* + * Test: older ctime than a file specified in WCS file name. + */ + assertEqualIntA(m, 0, archive_match_include_file_time_w(m, + ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_OLDER, L"mid_ctime")); + + /* Verify 'old_ctime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "old_ctime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("old_ctime should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + /* Verify 'mid_ctime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "mid_ctime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("mid_ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Verify 'new_ctime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "new_ctime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("new_ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_read_free(a); + archive_entry_free(ae); + archive_match_free(m); +} + +static void +test_mtime_between_files_mbs(void) +{ + struct archive *a; + struct archive_entry *ae; + struct archive *m; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + if (!assert((a = archive_read_disk_new()) != NULL)) { + archive_match_free(m); + archive_entry_free(ae); + return; + } + + /* + * Test: mtime between file specified in MBS file name. + */ + assertEqualIntA(m, 0, archive_match_include_file_time(m, + ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_NEWER, "old_mtime")); + assertEqualIntA(m, 0, archive_match_include_file_time(m, + ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER, "new_mtime")); + + /* Verify 'old_mtime' file. */ + archive_entry_copy_pathname(ae, "old_mtime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("old_mtime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Verify 'mid_mtime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "mid_mtime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("mid_mtime should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + /* Verify 'new_mtime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "new_mtime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("new_mtime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_read_free(a); + archive_entry_free(ae); + archive_match_free(m); +} + +static void +test_mtime_between_files_wcs(void) +{ + struct archive *a; + struct archive_entry *ae; + struct archive *m; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + if (!assert((a = archive_read_disk_new()) != NULL)) { + archive_match_free(m); + archive_entry_free(ae); + return; + } + + /* + * Test: mtime between file specified in WCS file name. + */ + assertEqualIntA(m, 0, archive_match_include_file_time_w(m, + ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_NEWER, L"old_mtime")); + assertEqualIntA(m, 0, archive_match_include_file_time_w(m, + ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER, L"new_mtime")); + + /* Verify 'old_mtime' file. */ + archive_entry_copy_pathname(ae, "old_mtime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("old_mtime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Verify 'mid_mtime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "mid_mtime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("mid_mtime should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + /* Verify 'new_mtime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "new_mtime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("new_mtime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_read_free(a); + archive_entry_free(ae); + archive_match_free(m); +} + +static void +test_ctime_between_files_mbs(void) +{ + struct archive *a; + struct archive_entry *ae; + struct archive *m; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + if (!assert((a = archive_read_disk_new()) != NULL)) { + archive_match_free(m); + archive_entry_free(ae); + return; + } + + /* + * Test: ctime between files specified in MBS file name. + */ + assertEqualIntA(m, 0, archive_match_include_file_time(m, + ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_NEWER, "old_ctime")); + assertEqualIntA(m, 0, archive_match_include_file_time(m, + ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_OLDER, "new_ctime")); + + /* Verify 'old_ctime' file. */ + archive_entry_copy_pathname(ae, "old_ctime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("old_ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Verify 'mid_ctime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "mid_ctime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("mid_ctime should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + /* Verify 'new_ctime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "new_ctime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("new_ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_read_free(a); + archive_entry_free(ae); + archive_match_free(m); +} + +static void +test_ctime_between_files_wcs(void) +{ + struct archive *a; + struct archive_entry *ae; + struct archive *m; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + if (!assert((a = archive_read_disk_new()) != NULL)) { + archive_match_free(m); + archive_entry_free(ae); + return; + } + + /* + * Test: ctime between files specified in WCS file name. + */ + assertEqualIntA(m, 0, archive_match_include_file_time_w(m, + ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_NEWER, L"old_ctime")); + assertEqualIntA(m, 0, archive_match_include_file_time_w(m, + ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_OLDER, L"new_ctime")); + + /* Verify 'old_ctime' file. */ + archive_entry_copy_pathname(ae, "old_ctime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("old_ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Verify 'mid_ctime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "mid_ctime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("mid_ctime should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + /* Verify 'new_ctime' file. */ + archive_entry_clear(ae); + archive_entry_copy_pathname(ae, "new_ctime"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + failure("new_ctime should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* Clean up. */ + archive_read_free(a); + archive_entry_free(ae); + archive_match_free(m); +} + +static void +excluded(struct archive *m) +{ + struct archive_entry *ae; + + if (!assert((ae = archive_entry_new()) != NULL)) + return; + + archive_entry_copy_pathname(ae, "file1"); + archive_entry_set_mtime(ae, 7879, 999); + failure("It should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + archive_entry_set_mtime(ae, 7880, 0); + failure("It should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + archive_entry_set_mtime(ae, 7880, 1); + failure("It should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + archive_entry_copy_pathname(ae, "file2"); + archive_entry_set_mtime(ae, 7879, 999); + failure("It should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + archive_entry_set_mtime(ae, 7880, 0); + failure("It should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + archive_entry_set_mtime(ae, 7880, 1); + failure("It should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + archive_entry_copy_pathname(ae, "file3"); + archive_entry_set_mtime(ae, 7879, 999); + failure("It should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + archive_entry_set_mtime(ae, 7880, 0); + failure("It should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + archive_entry_set_mtime(ae, 7880, 1); + failure("It should be excluded"); + assertEqualInt(1, archive_match_time_excluded(m, ae)); + assertEqualInt(1, archive_match_excluded(m, ae)); + + /* + * "file4" is not registered, that sort of a file should not be + * excluded with any mtime. + */ + archive_entry_copy_pathname(ae, "file4"); + archive_entry_set_mtime(ae, 7879, 999); + failure("It should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + archive_entry_set_mtime(ae, 7880, 0); + failure("It should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + archive_entry_set_mtime(ae, 7880, 1); + failure("It should not be excluded"); + assertEqualInt(0, archive_match_time_excluded(m, ae)); + assertEqualInt(0, archive_match_excluded(m, ae)); + + + /* Clean up. */ + archive_entry_free(ae); +} + +static void +test_pathname_newer_mtime(void) +{ + struct archive_entry *ae; + struct archive *m; + + if (!assert((m = archive_match_new()) != NULL)) + return; + if (!assert((ae = archive_entry_new()) != NULL)) { + archive_match_free(m); + return; + } + + archive_entry_copy_pathname(ae, "file1"); + archive_entry_set_mtime(ae, 7880, 0); + assertEqualIntA(m, 0, archive_match_exclude_entry(m, + ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER | + ARCHIVE_MATCH_EQUAL, ae)); + archive_entry_copy_pathname(ae, "file2"); + archive_entry_set_mtime(ae, 1, 0); + assertEqualIntA(m, 0, archive_match_exclude_entry(m, + ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER | + ARCHIVE_MATCH_EQUAL, ae)); + archive_entry_copy_pathname(ae, "file3"); + archive_entry_set_mtime(ae, 99999, 0); + assertEqualIntA(m, 0, archive_match_exclude_entry(m, + ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER | + ARCHIVE_MATCH_EQUAL, ae)); + + excluded(m); + + /* Clean up. */ + archive_entry_free(ae); + archive_match_free(m); +} + +DEFINE_TEST(test_archive_match_time) +{ + struct stat st; + + /* Test: matching newer times. */ + test_newer_time(); + test_newer_time_str(); + test_newer_time_str_w(); + /* Test: matching older times. */ + test_older_time(); + test_older_time_str(); + test_older_time_str_w(); + + /* + * Create sample files for tests matching mtime. + * ctimes of those files may be all the same or the ctime of + * new_mtime may be older than old_mtime. + */ + assertMakeFile("new_mtime", 0666, "new"); + assertUtimes("new_mtime", 10002, 0, 10002, 0); + assertMakeFile("mid_mtime", 0666, "mid"); + assertUtimes("mid_mtime", 10001, 0, 10001, 0); + assertMakeFile("old_mtime", 0666, "old"); + assertUtimes("old_mtime", 10000, 0, 10000, 0); + + /* + * Create sample files for tests matching ctime. + * the mtime of mid_ctime is older than old_ctime and also the mtime + * of new_ctime is older than both mid_ctime and old_ctime. + */ + assertMakeFile("old_ctime", 0666, "old"); + assertUtimes("old_ctime", 10002, 0, 10002, 0); + assertEqualInt(0, stat("old_ctime", &st)); + sleepUntilAfter(st.st_ctime); + assertMakeFile("mid_ctime", 0666, "mid"); + assertUtimes("mid_ctime", 10001, 0, 10001, 0); + assertEqualInt(0, stat("mid_ctime", &st)); + sleepUntilAfter(st.st_ctime); + assertMakeFile("new_ctime", 0666, "new"); + assertUtimes("new_ctime", 10000, 0, 10000, 0); + + /* + * Test: matching mtime which indicated by files on the disk. + */ + test_newer_mtime_than_file_mbs(); + test_newer_mtime_than_file_wcs(); + test_older_mtime_than_file_mbs(); + test_older_mtime_than_file_wcs(); + test_mtime_between_files_mbs(); + test_mtime_between_files_wcs(); + + /* + * Test: matching ctime which indicated by files on the disk. + */ + test_newer_ctime_than_file_mbs(); + test_newer_ctime_than_file_wcs(); + test_older_ctime_than_file_mbs(); + test_older_ctime_than_file_wcs(); + test_ctime_between_files_mbs(); + test_ctime_between_files_wcs(); + + /* Test: matching both pathname and mtime. */ + test_pathname_newer_mtime(); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_pathmatch.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_pathmatch.c new file mode 100644 index 0000000..21cbdd7 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_pathmatch.c @@ -0,0 +1,285 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +#define __LIBARCHIVE_TEST +#include "archive_pathmatch.h" + +/* + * Verify that the pattern matcher implements the wildcard logic specified + * in SUSv2 for the cpio command. This is essentially the + * shell glob syntax: + * * - matches any sequence of chars, including '/' + * ? - matches any single char, including '/' + * [...] - matches any of a set of chars, '-' specifies a range, + * initial '!' is undefined + * + * The specification in SUSv2 is a bit incomplete, I assume the following: + * Trailing '-' in [...] is not special. + * + * TODO: Figure out if there's a good way to extend this to handle + * Windows paths that use '\' as a path separator. + */ + +DEFINE_TEST(test_archive_pathmatch) +{ + assertEqualInt(1, archive_pathmatch("a/b/c", "a/b/c", 0)); + assertEqualInt(0, archive_pathmatch("a/b/", "a/b/c", 0)); + assertEqualInt(0, archive_pathmatch("a/b", "a/b/c", 0)); + assertEqualInt(0, archive_pathmatch("a/b/c", "a/b/", 0)); + assertEqualInt(0, archive_pathmatch("a/b/c", "a/b", 0)); + + /* Empty pattern only matches empty string. */ + assertEqualInt(1, archive_pathmatch("","", 0)); + assertEqualInt(0, archive_pathmatch("","a", 0)); + assertEqualInt(1, archive_pathmatch("*","", 0)); + assertEqualInt(1, archive_pathmatch("*","a", 0)); + assertEqualInt(1, archive_pathmatch("*","abcd", 0)); + /* SUSv2: * matches / */ + assertEqualInt(1, archive_pathmatch("*","abcd/efgh/ijkl", 0)); + assertEqualInt(1, archive_pathmatch("abcd*efgh/ijkl","abcd/efgh/ijkl", 0)); + assertEqualInt(1, archive_pathmatch("abcd***efgh/ijkl","abcd/efgh/ijkl", 0)); + assertEqualInt(1, archive_pathmatch("abcd***/efgh/ijkl","abcd/efgh/ijkl", 0)); + assertEqualInt(0, archive_pathmatch("?", "", 0)); + assertEqualInt(0, archive_pathmatch("?", "\0", 0)); + assertEqualInt(1, archive_pathmatch("?", "a", 0)); + assertEqualInt(0, archive_pathmatch("?", "ab", 0)); + assertEqualInt(1, archive_pathmatch("?", ".", 0)); + assertEqualInt(1, archive_pathmatch("?", "?", 0)); + assertEqualInt(1, archive_pathmatch("a", "a", 0)); + assertEqualInt(0, archive_pathmatch("a", "ab", 0)); + assertEqualInt(0, archive_pathmatch("a", "ab", 0)); + assertEqualInt(1, archive_pathmatch("a?c", "abc", 0)); + /* SUSv2: ? matches / */ + assertEqualInt(1, archive_pathmatch("a?c", "a/c", 0)); + assertEqualInt(1, archive_pathmatch("a?*c*", "a/c", 0)); + assertEqualInt(1, archive_pathmatch("*a*", "a/c", 0)); + assertEqualInt(1, archive_pathmatch("*a*", "/a/c", 0)); + assertEqualInt(1, archive_pathmatch("*a*", "defaaaaaaa", 0)); + assertEqualInt(0, archive_pathmatch("a*", "defghi", 0)); + assertEqualInt(0, archive_pathmatch("*a*", "defghi", 0)); + + /* Character classes */ + assertEqualInt(1, archive_pathmatch("abc[def", "abc[def", 0)); + assertEqualInt(0, archive_pathmatch("abc[def]", "abc[def", 0)); + assertEqualInt(0, archive_pathmatch("abc[def", "abcd", 0)); + assertEqualInt(1, archive_pathmatch("abc[def]", "abcd", 0)); + assertEqualInt(1, archive_pathmatch("abc[def]", "abce", 0)); + assertEqualInt(1, archive_pathmatch("abc[def]", "abcf", 0)); + assertEqualInt(0, archive_pathmatch("abc[def]", "abcg", 0)); + assertEqualInt(1, archive_pathmatch("abc[d*f]", "abcd", 0)); + assertEqualInt(1, archive_pathmatch("abc[d*f]", "abc*", 0)); + assertEqualInt(0, archive_pathmatch("abc[d*f]", "abcdefghi", 0)); + assertEqualInt(0, archive_pathmatch("abc[d*", "abcdefghi", 0)); + assertEqualInt(1, archive_pathmatch("abc[d*", "abc[defghi", 0)); + assertEqualInt(1, archive_pathmatch("abc[d-f]", "abcd", 0)); + assertEqualInt(1, archive_pathmatch("abc[d-f]", "abce", 0)); + assertEqualInt(1, archive_pathmatch("abc[d-f]", "abcf", 0)); + assertEqualInt(0, archive_pathmatch("abc[d-f]", "abcg", 0)); + assertEqualInt(0, archive_pathmatch("abc[d-fh-k]", "abca", 0)); + assertEqualInt(1, archive_pathmatch("abc[d-fh-k]", "abcd", 0)); + assertEqualInt(1, archive_pathmatch("abc[d-fh-k]", "abce", 0)); + assertEqualInt(1, archive_pathmatch("abc[d-fh-k]", "abcf", 0)); + assertEqualInt(0, archive_pathmatch("abc[d-fh-k]", "abcg", 0)); + assertEqualInt(1, archive_pathmatch("abc[d-fh-k]", "abch", 0)); + assertEqualInt(1, archive_pathmatch("abc[d-fh-k]", "abci", 0)); + assertEqualInt(1, archive_pathmatch("abc[d-fh-k]", "abcj", 0)); + assertEqualInt(1, archive_pathmatch("abc[d-fh-k]", "abck", 0)); + assertEqualInt(0, archive_pathmatch("abc[d-fh-k]", "abcl", 0)); + assertEqualInt(0, archive_pathmatch("abc[d-fh-k]", "abc-", 0)); + + /* [] matches nothing, [!] is the same as ? */ + assertEqualInt(0, archive_pathmatch("abc[]efg", "abcdefg", 0)); + assertEqualInt(0, archive_pathmatch("abc[]efg", "abcqefg", 0)); + assertEqualInt(0, archive_pathmatch("abc[]efg", "abcefg", 0)); + assertEqualInt(1, archive_pathmatch("abc[!]efg", "abcdefg", 0)); + assertEqualInt(1, archive_pathmatch("abc[!]efg", "abcqefg", 0)); + assertEqualInt(0, archive_pathmatch("abc[!]efg", "abcefg", 0)); + + /* I assume: Trailing '-' is non-special. */ + assertEqualInt(0, archive_pathmatch("abc[d-fh-]", "abcl", 0)); + assertEqualInt(1, archive_pathmatch("abc[d-fh-]", "abch", 0)); + assertEqualInt(1, archive_pathmatch("abc[d-fh-]", "abc-", 0)); + assertEqualInt(1, archive_pathmatch("abc[d-fh-]", "abc-", 0)); + + /* ']' can be backslash-quoted within a character class. */ + assertEqualInt(1, archive_pathmatch("abc[\\]]", "abc]", 0)); + assertEqualInt(1, archive_pathmatch("abc[\\]d]", "abc]", 0)); + assertEqualInt(1, archive_pathmatch("abc[\\]d]", "abcd", 0)); + assertEqualInt(1, archive_pathmatch("abc[d\\]]", "abc]", 0)); + assertEqualInt(1, archive_pathmatch("abc[d\\]]", "abcd", 0)); + assertEqualInt(1, archive_pathmatch("abc[d]e]", "abcde]", 0)); + assertEqualInt(1, archive_pathmatch("abc[d\\]e]", "abc]", 0)); + assertEqualInt(0, archive_pathmatch("abc[d\\]e]", "abcd]e", 0)); + assertEqualInt(0, archive_pathmatch("abc[d]e]", "abc]", 0)); + + /* backslash-quoted chars can appear as either end of a range. */ + assertEqualInt(1, archive_pathmatch("abc[\\d-f]gh", "abcegh", 0)); + assertEqualInt(0, archive_pathmatch("abc[\\d-f]gh", "abcggh", 0)); + assertEqualInt(0, archive_pathmatch("abc[\\d-f]gh", "abc\\gh", 0)); + assertEqualInt(1, archive_pathmatch("abc[d-\\f]gh", "abcegh", 0)); + assertEqualInt(1, archive_pathmatch("abc[\\d-\\f]gh", "abcegh", 0)); + assertEqualInt(1, archive_pathmatch("abc[\\d-\\f]gh", "abcegh", 0)); + /* backslash-quoted '-' isn't special. */ + assertEqualInt(0, archive_pathmatch("abc[d\\-f]gh", "abcegh", 0)); + assertEqualInt(1, archive_pathmatch("abc[d\\-f]gh", "abc-gh", 0)); + + /* Leading '!' negates a character class. */ + assertEqualInt(0, archive_pathmatch("abc[!d]", "abcd", 0)); + assertEqualInt(1, archive_pathmatch("abc[!d]", "abce", 0)); + assertEqualInt(1, archive_pathmatch("abc[!d]", "abcc", 0)); + assertEqualInt(0, archive_pathmatch("abc[!d-z]", "abcq", 0)); + assertEqualInt(1, archive_pathmatch("abc[!d-gi-z]", "abch", 0)); + assertEqualInt(1, archive_pathmatch("abc[!fgijkl]", "abch", 0)); + assertEqualInt(0, archive_pathmatch("abc[!fghijkl]", "abch", 0)); + + /* Backslash quotes next character. */ + assertEqualInt(0, archive_pathmatch("abc\\[def]", "abc\\d", 0)); + assertEqualInt(1, archive_pathmatch("abc\\[def]", "abc[def]", 0)); + assertEqualInt(0, archive_pathmatch("abc\\\\[def]", "abc[def]", 0)); + assertEqualInt(0, archive_pathmatch("abc\\\\[def]", "abc\\[def]", 0)); + assertEqualInt(1, archive_pathmatch("abc\\\\[def]", "abc\\d", 0)); + assertEqualInt(1, archive_pathmatch("abcd\\", "abcd\\", 0)); + assertEqualInt(0, archive_pathmatch("abcd\\", "abcd\\[", 0)); + assertEqualInt(0, archive_pathmatch("abcd\\", "abcde", 0)); + assertEqualInt(0, archive_pathmatch("abcd\\[", "abcd\\", 0)); + + /* + * Because '.' and '/' have special meanings, we can + * identify many equivalent paths even if they're expressed + * differently. (But quoting a character with '\\' suppresses + * special meanings!) + */ + assertEqualInt(0, archive_pathmatch("a/b/", "a/bc", 0)); + assertEqualInt(1, archive_pathmatch("a/./b", "a/b", 0)); + assertEqualInt(0, archive_pathmatch("a\\/./b", "a/b", 0)); + assertEqualInt(0, archive_pathmatch("a/\\./b", "a/b", 0)); + assertEqualInt(0, archive_pathmatch("a/.\\/b", "a/b", 0)); + assertEqualInt(0, archive_pathmatch("a\\/\\.\\/b", "a/b", 0)); + assertEqualInt(1, archive_pathmatch("./abc/./def/", "abc/def/", 0)); + assertEqualInt(1, archive_pathmatch("abc/def", "./././abc/./def", 0)); + assertEqualInt(1, archive_pathmatch("abc/def/././//", "./././abc/./def/", 0)); + assertEqualInt(1, archive_pathmatch(".////abc/.//def", "./././abc/./def", 0)); + assertEqualInt(1, archive_pathmatch("./abc?def/", "abc/def/", 0)); + failure("\"?./\" is not the same as \"/./\""); + assertEqualInt(0, archive_pathmatch("./abc?./def/", "abc/def/", 0)); + failure("Trailing '/' should match no trailing '/'"); + assertEqualInt(1, archive_pathmatch("./abc/./def/", "abc/def", 0)); + failure("Trailing '/./' is still the same directory."); + assertEqualInt(1, archive_pathmatch("./abc/./def/./", "abc/def", 0)); + failure("Trailing '/.' is still the same directory."); + assertEqualInt(1, archive_pathmatch("./abc/./def/.", "abc/def", 0)); + assertEqualInt(1, archive_pathmatch("./abc/./def", "abc/def/", 0)); + failure("Trailing '/./' is still the same directory."); + assertEqualInt(1, archive_pathmatch("./abc/./def", "abc/def/./", 0)); + failure("Trailing '/.' is still the same directory."); + assertEqualInt(1, archive_pathmatch("./abc*/./def", "abc/def/.", 0)); + + /* Matches not anchored at beginning. */ + assertEqualInt(0, + archive_pathmatch("bcd", "abcd", PATHMATCH_NO_ANCHOR_START)); + assertEqualInt(1, + archive_pathmatch("abcd", "abcd", PATHMATCH_NO_ANCHOR_START)); + assertEqualInt(0, + archive_pathmatch("^bcd", "abcd", PATHMATCH_NO_ANCHOR_START)); + assertEqualInt(1, + archive_pathmatch("b/c/d", "a/b/c/d", PATHMATCH_NO_ANCHOR_START)); + assertEqualInt(0, + archive_pathmatch("^b/c/d", "a/b/c/d", PATHMATCH_NO_ANCHOR_START)); + assertEqualInt(0, + archive_pathmatch("/b/c/d", "a/b/c/d", PATHMATCH_NO_ANCHOR_START)); + assertEqualInt(0, + archive_pathmatch("a/b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_START)); + assertEqualInt(1, + archive_pathmatch("a/b/c/d", "a/b/c/d", PATHMATCH_NO_ANCHOR_START)); + assertEqualInt(0, + archive_pathmatch("b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_START)); + assertEqualInt(0, + archive_pathmatch("^b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_START)); + + + assertEqualInt(1, + archive_pathmatch("b/c/d", "a/b/c/d", PATHMATCH_NO_ANCHOR_START)); + assertEqualInt(1, + archive_pathmatch("b/c/d", "/a/b/c/d", PATHMATCH_NO_ANCHOR_START)); + + + /* Matches not anchored at end. */ + assertEqualInt(0, + archive_pathmatch("bcd", "abcd", PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(1, + archive_pathmatch("abcd", "abcd", PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(1, + archive_pathmatch("abcd", "abcd/", PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(1, + archive_pathmatch("abcd", "abcd/.", PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(0, + archive_pathmatch("abc", "abcd", PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(1, + archive_pathmatch("a/b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(0, + archive_pathmatch("a/b/c$", "a/b/c/d", PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(1, + archive_pathmatch("a/b/c$", "a/b/c", PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(1, + archive_pathmatch("a/b/c$", "a/b/c/", PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(1, + archive_pathmatch("a/b/c/", "a/b/c/d", PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(0, + archive_pathmatch("a/b/c/$", "a/b/c/d", PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(1, + archive_pathmatch("a/b/c/$", "a/b/c/", PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(1, + archive_pathmatch("a/b/c/$", "a/b/c", PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(0, + archive_pathmatch("b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_END)); + + /* Matches not anchored at either end. */ + assertEqualInt(1, + archive_pathmatch("b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(0, + archive_pathmatch("/b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(0, + archive_pathmatch("/a/b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(1, + archive_pathmatch("/a/b/c", "/a/b/c/d", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(0, + archive_pathmatch("/a/b/c$", "a/b/c/d", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(0, + archive_pathmatch("/a/b/c/d$", "a/b/c/d", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(0, + archive_pathmatch("/a/b/c/d$", "/a/b/c/d/e", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(1, + archive_pathmatch("/a/b/c/d$", "/a/b/c/d", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(1, + archive_pathmatch("^a/b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(0, + archive_pathmatch("^a/b/c$", "a/b/c/d", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(0, + archive_pathmatch("a/b/c$", "a/b/c/d", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(1, + archive_pathmatch("b/c/d$", "a/b/c/d", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_add_passphrase.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_add_passphrase.c new file mode 100644 index 0000000..0ce5a76 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_add_passphrase.c @@ -0,0 +1,260 @@ +/*- + * Copyright (c) 2011 Tim Kientzle + * Copyright (c) 2014 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +struct archive_read; +extern void __archive_read_reset_passphrase(struct archive_read *); +extern const char * __archive_read_next_passphrase(struct archive_read *); + +static void +test(int pristine) +{ + struct archive* a = archive_read_new(); + + if (!pristine) { + archive_read_support_filter_all(a); + archive_read_support_format_all(a); + } + + assertEqualInt(ARCHIVE_OK, archive_read_add_passphrase(a, "pass1")); + /* An empty passphrase cannot be accepted. */ + assertEqualInt(ARCHIVE_FAILED, archive_read_add_passphrase(a, "")); + /* NULL passphrases cannot be accepted. */ + assertEqualInt(ARCHIVE_FAILED, archive_read_add_passphrase(a, NULL)); + + archive_read_free(a); +} + +DEFINE_TEST(test_archive_read_add_passphrase) +{ + test(1); + test(0); +} + +DEFINE_TEST(test_archive_read_add_passphrase_incorrect_sequance) +{ + struct archive* a = archive_read_new(); + struct archive_read *ar = (struct archive_read *)a; + + assertEqualInt(ARCHIVE_OK, archive_read_add_passphrase(a, "pass1")); + + /* No call of __archive_read_reset_passphrase() leads to + * get NULL even if a user has passed a passphrases. */ + assertEqualString(NULL, __archive_read_next_passphrase(ar)); + + archive_read_free(a); +} + +DEFINE_TEST(test_archive_read_add_passphrase_single) +{ + struct archive* a = archive_read_new(); + struct archive_read *ar = (struct archive_read *)a; + + assertEqualInt(ARCHIVE_OK, archive_read_add_passphrase(a, "pass1")); + + __archive_read_reset_passphrase(ar); + /* Fist call, we should get "pass1" as a passphrase. */ + assertEqualString("pass1", __archive_read_next_passphrase(ar)); + /* Second call, we should get NULL which means all the passphrases + * are passed already. */ + assertEqualString(NULL, __archive_read_next_passphrase(ar)); + + archive_read_free(a); +} + +DEFINE_TEST(test_archive_read_add_passphrase_multiple) +{ + struct archive* a = archive_read_new(); + struct archive_read *ar = (struct archive_read *)a; + + assertEqualInt(ARCHIVE_OK, archive_read_add_passphrase(a, "pass1")); + assertEqualInt(ARCHIVE_OK, archive_read_add_passphrase(a, "pass2")); + + __archive_read_reset_passphrase(ar); + /* Fist call, we should get "pass1" as a passphrase. */ + assertEqualString("pass1", __archive_read_next_passphrase(ar)); + /* Second call, we should get "pass2" as a passphrase. */ + assertEqualString("pass2", __archive_read_next_passphrase(ar)); + /* Third call, we should get NULL which means all the passphrases + * are passed already. */ + assertEqualString(NULL, __archive_read_next_passphrase(ar)); + + archive_read_free(a); +} + +static const char * +callback1(struct archive *a, void *_client_data) +{ + (void)a; /* UNUSED */ + (void)_client_data; /* UNUSED */ + return ("passCallBack"); +} + +DEFINE_TEST(test_archive_read_add_passphrase_set_callback1) +{ + struct archive* a = archive_read_new(); + struct archive_read *ar = (struct archive_read *)a; + + assertEqualInt(ARCHIVE_OK, + archive_read_set_passphrase_callback(a, NULL, callback1)); + + __archive_read_reset_passphrase(ar); + /* Fist call, we should get "passCallBack" as a passphrase. */ + assertEqualString("passCallBack", __archive_read_next_passphrase(ar)); + /* Second call, we still get "passCallBack" as a passphrase. */ + assertEqualString("passCallBack", __archive_read_next_passphrase(ar)); + + archive_read_free(a); + + /* Without __archive_read_reset_passphrase call, the callback + * should work fine. */ + a = archive_read_new(); + ar = (struct archive_read *)a; + assertEqualInt(ARCHIVE_OK, + archive_read_set_passphrase_callback(a, NULL, callback1)); + /* Fist call, we should get "passCallBack" as a passphrase. */ + assertEqualString("passCallBack", __archive_read_next_passphrase(ar)); + /* Second call, we still get "passCallBack" as a passphrase. */ + assertEqualString("passCallBack", __archive_read_next_passphrase(ar)); + + archive_read_free(a); +} + +static const char * +callback2(struct archive *a, void *_client_data) +{ + int *cd = (int *)_client_data; + + (void)a; /* UNUSED */ + + if (*cd == 0) { + *cd = 1; + return ("passCallBack"); + } + return (NULL); +} + +DEFINE_TEST(test_archive_read_add_passphrase_set_callback2) +{ + struct archive* a = archive_read_new(); + struct archive_read *ar = (struct archive_read *)a; + int client_data = 0; + + assertEqualInt(ARCHIVE_OK, + archive_read_set_passphrase_callback(a, &client_data, callback2)); + + __archive_read_reset_passphrase(ar); + /* Fist call, we should get "passCallBack" as a passphrase. */ + assertEqualString("passCallBack", __archive_read_next_passphrase(ar)); + /* Second call, we should get NULL which means all the passphrases + * are passed already. */ + assertEqualString(NULL, __archive_read_next_passphrase(ar)); + + archive_read_free(a); +} + +DEFINE_TEST(test_archive_read_add_passphrase_set_callback3) +{ + struct archive* a = archive_read_new(); + struct archive_read *ar = (struct archive_read *)a; + int client_data = 0; + + assertEqualInt(ARCHIVE_OK, + archive_read_set_passphrase_callback(a, &client_data, callback2)); + + __archive_read_reset_passphrase(ar); + /* Fist call, we should get "passCallBack" as a passphrase. */ + assertEqualString("passCallBack", __archive_read_next_passphrase(ar)); + __archive_read_reset_passphrase(ar); + /* After reset passphrase, we should get "passCallBack" passphrase. */ + assertEqualString("passCallBack", __archive_read_next_passphrase(ar)); + /* Second call, we should get NULL which means all the passphrases + * are passed already. */ + assertEqualString(NULL, __archive_read_next_passphrase(ar)); + + archive_read_free(a); +} + +DEFINE_TEST(test_archive_read_add_passphrase_multiple_with_callback) +{ + struct archive* a = archive_read_new(); + struct archive_read *ar = (struct archive_read *)a; + int client_data = 0; + + assertEqualInt(ARCHIVE_OK, archive_read_add_passphrase(a, "pass1")); + assertEqualInt(ARCHIVE_OK, archive_read_add_passphrase(a, "pass2")); + assertEqualInt(ARCHIVE_OK, + archive_read_set_passphrase_callback(a, &client_data, callback2)); + + __archive_read_reset_passphrase(ar); + /* Fist call, we should get "pass1" as a passphrase. */ + assertEqualString("pass1", __archive_read_next_passphrase(ar)); + /* Second call, we should get "pass2" as a passphrase. */ + assertEqualString("pass2", __archive_read_next_passphrase(ar)); + /* Third call, we should get "passCallBack" as a passphrase. */ + assertEqualString("passCallBack", __archive_read_next_passphrase(ar)); + /* Fourth call, we should get NULL which means all the passphrases + * are passed already. */ + assertEqualString(NULL, __archive_read_next_passphrase(ar)); + + archive_read_free(a); +} + +DEFINE_TEST(test_archive_read_add_passphrase_multiple_with_callback2) +{ + struct archive* a = archive_read_new(); + struct archive_read *ar = (struct archive_read *)a; + int client_data = 0; + + assertEqualInt(ARCHIVE_OK, archive_read_add_passphrase(a, "pass1")); + assertEqualInt(ARCHIVE_OK, archive_read_add_passphrase(a, "pass2")); + assertEqualInt(ARCHIVE_OK, + archive_read_set_passphrase_callback(a, &client_data, callback2)); + + __archive_read_reset_passphrase(ar); + /* Fist call, we should get "pass1" as a passphrase. */ + assertEqualString("pass1", __archive_read_next_passphrase(ar)); + /* Second call, we should get "pass2" as a passphrase. */ + assertEqualString("pass2", __archive_read_next_passphrase(ar)); + /* Third call, we should get "passCallBack" as a passphrase. */ + assertEqualString("passCallBack", __archive_read_next_passphrase(ar)); + + __archive_read_reset_passphrase(ar); + /* After reset passphrase, we should get "passCallBack" passphrase. */ + assertEqualString("passCallBack", __archive_read_next_passphrase(ar)); + /* Second call, we should get "pass1" as a passphrase. */ + assertEqualString("pass1", __archive_read_next_passphrase(ar)); + /* Third call, we should get "passCallBack" as a passphrase. */ + assertEqualString("pass2", __archive_read_next_passphrase(ar)); + /* Fourth call, we should get NULL which means all the passphrases + * are passed already. */ + assertEqualString(NULL, __archive_read_next_passphrase(ar)); + + archive_read_free(a); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_close_twice.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_close_twice.c new file mode 100644 index 0000000..16cc805 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_close_twice.c @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + + +DEFINE_TEST(test_archive_read_close_twice) +{ + struct archive* a = archive_read_new(); + + assertEqualInt(0, archive_read_close(a)); + assertEqualInt(0, archive_errno(a)); + assertEqualString(NULL, archive_error_string(a)); + + assertEqualInt(0, archive_read_close(a)); + assertEqualInt(0, archive_errno(a)); + assertEqualString(NULL, archive_error_string(a)); + + archive_read_free(a); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_close_twice_open_fd.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_close_twice_open_fd.c new file mode 100644 index 0000000..3aba317 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_close_twice_open_fd.c @@ -0,0 +1,47 @@ +/*- + * Copyright (c) 2011 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_archive_read_close_twice_open_fd) +{ + struct archive* a = archive_read_new(); + + assertEqualInt(ARCHIVE_OK, archive_read_support_format_empty(a)); + assertEqualInt(ARCHIVE_OK, archive_read_open_fd(a, 0, 0)); + assertEqualInt(0, archive_errno(a)); + assertEqualString(NULL, archive_error_string(a)); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(0, archive_errno(a)); + assertEqualString(NULL, archive_error_string(a)); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(0, archive_errno(a)); + assertEqualString(NULL, archive_error_string(a)); + + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_close_twice_open_filename.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_close_twice_open_filename.c new file mode 100644 index 0000000..9a194fd --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_close_twice_open_filename.c @@ -0,0 +1,49 @@ +/*- + * Copyright (c) 2011 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_archive_read_close_twice_open_filename) +{ + const char *filename = "empty.file"; + struct archive* a = archive_read_new(); + + assertMakeFile(filename, 0644, ""); + assertEqualInt(ARCHIVE_OK, archive_read_support_format_empty(a)); + assertEqualInt(ARCHIVE_OK, archive_read_open_filename(a, filename, 0)); + assertEqualInt(0, archive_errno(a)); + assertEqualString(NULL, archive_error_string(a)); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(0, archive_errno(a)); + assertEqualString(NULL, archive_error_string(a)); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(0, archive_errno(a)); + assertEqualString(NULL, archive_error_string(a)); + + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_multiple_data_objects.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_multiple_data_objects.c new file mode 100644 index 0000000..9962cf7 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_multiple_data_objects.c @@ -0,0 +1,372 @@ +/*- + * Copyright (c) 2011 Tim Kientzle + * Copyright (c) 2011-2012 Andres Mejia + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +#if defined(_WIN32) && !defined(__CYGWIN__) +#define open _open +#define close _close +#define read _read +#if !defined(__BORLANDC__) +#ifdef lseek +#undef lseek +#endif +#define lseek(f, o, w) _lseek(f, (long)(o), (int)(w)) +#endif +#endif + +static void +test_splitted_file(void) +{ + char buff[64]; + static const char *reffiles[] = + { + "test_read_splitted_rar_aa", + "test_read_splitted_rar_ab", + "test_read_splitted_rar_ac", + "test_read_splitted_rar_ad", + NULL + }; + const char test_txt[] = "test text document\r\n"; + int size = sizeof(test_txt)-1; + struct archive_entry *ae; + struct archive *a; + + extract_reference_files(reffiles); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_filenames(a, reffiles, 10240)); + + /* First header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.txt", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(20, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertA(size == archive_read_data(a, buff, size)); + assertEqualMem(buff, test_txt, size); + + /* Second header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testlink", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(41471, archive_entry_mode(ae)); + assertEqualString("test.txt", archive_entry_symlink(ae)); + assertEqualIntA(a, 0, archive_read_data(a, buff, sizeof(buff))); + + /* Third header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testdir/test.txt", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(20, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertA(size == archive_read_data(a, buff, size)); + assertEqualMem(buff, test_txt, size); + + /* Fourth header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testdir", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(16877, archive_entry_mode(ae)); + + /* Fifth header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testemptydir", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(16877, archive_entry_mode(ae)); + + /* Test EOF */ + assertA(1 == archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_file_count(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +static void +test_large_splitted_file(void) +{ + static const char *reffiles[] = + { + "test_read_large_splitted_rar_aa", + "test_read_large_splitted_rar_ab", + "test_read_large_splitted_rar_ac", + "test_read_large_splitted_rar_ad", + "test_read_large_splitted_rar_ae", + NULL + }; + const char test_txt[] = "gin-bottom: 0in\">
    \n

    \n\n"; + int size = 241647978, offset = 0; + char buff[64]; + struct archive_entry *ae; + struct archive *a; + + extract_reference_files(reffiles); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_filenames(a, reffiles, 10240)); + + /* First header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("ppmd_lzss_conversion_test.txt", + archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(size, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + while (offset + (int)sizeof(buff) < size) + { + assertA(sizeof(buff) == archive_read_data(a, buff, sizeof(buff))); + offset += sizeof(buff); + } + assertA(size - offset == archive_read_data(a, buff, size - offset)); + assertEqualMem(buff, test_txt, size - offset); + + /* Test EOF */ + assertA(1 == archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_file_count(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +#define BLOCK_SIZE 10240 +struct mydata { + char *filename; + void *buffer; + int fd; +}; + +static int +file_open(struct archive *a, void *data) +{ + struct mydata *mydata = (struct mydata *)data; + (void)a; + if (mydata->fd < 0) + { + mydata->fd = open(mydata->filename, O_RDONLY | O_BINARY); + if (mydata->fd >= 0) + { + if ((mydata->buffer = (void*)calloc(1, BLOCK_SIZE)) == NULL) + return (ARCHIVE_FAILED); + } + } + return (ARCHIVE_OK); +} +static ssize_t +file_read(struct archive *a, void *data, const void **buff) +{ + struct mydata *mydata = (struct mydata *)data; + (void)a; + *buff = mydata->buffer; + return read(mydata->fd, mydata->buffer, BLOCK_SIZE); +} +static int64_t +file_skip(struct archive *a, void *data, int64_t request) +{ + struct mydata *mydata = (struct mydata *)data; + int64_t result = lseek(mydata->fd, SEEK_CUR, request); + if (result >= 0) + return result; + archive_set_error(a, errno, "Error seeking in '%s'", mydata->filename); + return -1; +} +static int +file_switch(struct archive *a, void *data1, void *data2) +{ + struct mydata *mydata1 = (struct mydata *)data1; + struct mydata *mydata2 = (struct mydata *)data2; + int r = (ARCHIVE_OK); + + (void)a; + if (mydata1 && mydata1->fd >= 0) + { + close(mydata1->fd); + free(mydata1->buffer); + mydata1->buffer = NULL; + mydata1->fd = -1; + } + if (mydata2) + { + r = file_open(a, mydata2); + } + return (r); +} +static int +file_close(struct archive *a, void *data) +{ + struct mydata *mydata = (struct mydata *)data; + if (mydata == NULL) + return (ARCHIVE_FATAL); + file_switch(a, mydata, NULL); + free(mydata->filename); + free(mydata); + return (ARCHIVE_OK); +} +static int64_t +file_seek(struct archive *a, void *data, int64_t request, int whence) +{ + struct mydata *mine = (struct mydata *)data; + int64_t r; + + (void)a; + r = lseek(mine->fd, request, whence); + if (r >= 0) + return r; + return (ARCHIVE_FATAL); +} + +static void +test_customized_multiple_data_objects(void) +{ + char buff[64]; + static const char *reffiles[] = + { + "test_read_splitted_rar_aa", + "test_read_splitted_rar_ab", + "test_read_splitted_rar_ac", + "test_read_splitted_rar_ad", + NULL + }; + const char test_txt[] = "test text document\r\n"; + int size = sizeof(test_txt)-1; + struct archive_entry *ae; + struct archive *a; + struct mydata *mydata; + const char *filename = *reffiles; + int i; + + extract_reference_files(reffiles); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + + for (i = 0; filename != NULL;) + { + assert((mydata = (struct mydata *)calloc(1, sizeof(*mydata))) != NULL); + if (mydata == NULL) { + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + assert((mydata->filename = + (char *)calloc(1, strlen(filename) + 1)) != NULL); + if (mydata->filename == NULL) { + free(mydata); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + strcpy(mydata->filename, filename); + mydata->fd = -1; + filename = reffiles[++i]; + assertA(0 == archive_read_append_callback_data(a, mydata)); + } + assertA(0 == archive_read_set_open_callback(a, file_open)); + assertA(0 == archive_read_set_read_callback(a, file_read)); + assertA(0 == archive_read_set_skip_callback(a, file_skip)); + assertA(0 == archive_read_set_close_callback(a, file_close)); + assertA(0 == archive_read_set_switch_callback(a, file_switch)); + assertA(0 == archive_read_set_seek_callback(a, file_seek)); + assertA(0 == archive_read_open1(a)); + + /* First header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.txt", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(20, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertA(size == archive_read_data(a, buff, size)); + assertEqualMem(buff, test_txt, size); + + /* Second header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testlink", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(41471, archive_entry_mode(ae)); + assertEqualString("test.txt", archive_entry_symlink(ae)); + assertEqualIntA(a, 0, archive_read_data(a, buff, sizeof(buff))); + + /* Third header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testdir/test.txt", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(20, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertA(size == archive_read_data(a, buff, size)); + assertEqualMem(buff, test_txt, size); + + /* Fourth header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testdir", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(16877, archive_entry_mode(ae)); + + /* Fifth header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testemptydir", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(16877, archive_entry_mode(ae)); + + /* Test EOF */ + assertA(1 == archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_file_count(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_archive_read_multiple_data_objects) +{ + test_splitted_file(); + test_large_splitted_file(); + test_customized_multiple_data_objects(); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_next_header_empty.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_next_header_empty.c new file mode 100644 index 0000000..f650bcc --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_next_header_empty.c @@ -0,0 +1,111 @@ +/*- + * Copyright (c) 2003-2011 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +static void +test_empty_file1(void) +{ + struct archive* a = archive_read_new(); + + /* Try opening an empty file with the raw handler. */ + assertEqualInt(ARCHIVE_OK, archive_read_support_format_raw(a)); + assertEqualInt(0, archive_errno(a)); + assertEqualString(NULL, archive_error_string(a)); + + /* Raw handler doesn't support empty files. */ + assertEqualInt(ARCHIVE_FATAL, archive_read_open_filename(a, "emptyfile", 0)); + assert(NULL != archive_error_string(a)); + + archive_read_free(a); +} + +static void +test_empty_file2(void) +{ + struct archive* a = archive_read_new(); + struct archive_entry* e; + + /* Try opening an empty file with raw and empty handlers. */ + assertEqualInt(ARCHIVE_OK, archive_read_support_format_raw(a)); + assertEqualInt(ARCHIVE_OK, archive_read_support_format_empty(a)); + assertEqualInt(0, archive_errno(a)); + assertEqualString(NULL, archive_error_string(a)); + + assertEqualInt(ARCHIVE_OK, archive_read_open_filename(a, "emptyfile", 0)); + assertEqualInt(0, archive_errno(a)); + assertEqualString(NULL, archive_error_string(a)); + + assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &e)); + assertEqualInt(0, archive_errno(a)); + assertEqualString(NULL, archive_error_string(a)); + + archive_read_free(a); +} + +static void +test_empty_tarfile(void) +{ + struct archive* a = archive_read_new(); + struct archive_entry* e; + + /* Try opening an empty file with raw and empty handlers. */ + assertEqualInt(ARCHIVE_OK, archive_read_support_format_tar(a)); + assertEqualInt(0, archive_errno(a)); + assertEqualString(NULL, archive_error_string(a)); + + assertEqualInt(ARCHIVE_OK, archive_read_open_filename(a, "empty.tar", 0)); + assertEqualInt(0, archive_errno(a)); + assertEqualString(NULL, archive_error_string(a)); + + assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &e)); + assertEqualInt(0, archive_errno(a)); + assertEqualString(NULL, archive_error_string(a)); + + archive_read_free(a); +} + +/* 512 zero bytes. */ +static char nulls[512]; + +DEFINE_TEST(test_archive_read_next_header_empty) +{ + FILE *f; + + /* Create an empty file. */ + f = fopen("emptyfile", "wb"); + fclose(f); + + /* Create a file with 512 zero bytes. */ + f = fopen("empty.tar", "wb"); + assertEqualInt(512, fwrite(nulls, 1, 512, f)); + fclose(f); + + test_empty_file1(); + test_empty_file2(); + test_empty_tarfile(); + +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_next_header_raw.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_next_header_raw.c new file mode 100644 index 0000000..1c8af20 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_next_header_raw.c @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 2011 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +#define DATA "random garbage for testing purposes" + +static const char data[sizeof(DATA)] = DATA; + +static void +test(int skip_explicitely) +{ + struct archive* a = archive_read_new(); + struct archive_entry* e; + + assertEqualInt(ARCHIVE_OK, archive_read_support_format_raw(a)); + assertEqualInt(0, archive_errno(a)); + assertEqualString(NULL, archive_error_string(a)); + + assertEqualInt(ARCHIVE_OK, archive_read_open_memory(a, + (void *)(uintptr_t) data, sizeof(data))); + assertEqualString(NULL, archive_error_string(a)); + + assertEqualInt(ARCHIVE_OK, archive_read_next_header(a, &e)); + assertEqualInt(0, archive_errno(a)); + assertEqualString(NULL, archive_error_string(a)); + + if (skip_explicitely) + assertEqualInt(ARCHIVE_OK, archive_read_data_skip(a)); + + assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &e)); + assertEqualInt(0, archive_errno(a)); + assertEqualString(NULL, archive_error_string(a)); + + archive_read_free(a); +} + +DEFINE_TEST(test_archive_read_next_header_raw) +{ + test(1); + test(0); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_open2.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_open2.c new file mode 100644 index 0000000..0a801ac --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_open2.c @@ -0,0 +1,109 @@ +/*- + * Copyright (c) 2011 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +static int +open_cb(struct archive *a, void *client) +{ + (void)a; /* UNUSED */ + (void)client; /* UNUSED */ + return 0; +} +static ssize_t +read_cb(struct archive *a, void *client, const void **buff) +{ + (void)a; /* UNUSED */ + (void)client; /* UNUSED */ + (void)buff; /* UNUSED */ + return (ssize_t)0; +} +static int64_t +skip_cb(struct archive *a, void *client, int64_t request) +{ + (void)a; /* UNUSED */ + (void)client; /* UNUSED */ + (void)request; /* UNUSED */ + return (int64_t)0; +} +static int +close_cb(struct archive *a, void *client) +{ + (void)a; /* UNUSED */ + (void)client; /* UNUSED */ + return 0; +} + +static void +test(int formatted, archive_open_callback *o, archive_read_callback *r, + archive_skip_callback *s, archive_close_callback *c, + int rv, const char *msg) +{ + struct archive* a = archive_read_new(); + if (formatted) + assertEqualInt(ARCHIVE_OK, + archive_read_support_format_empty(a)); + assertEqualInt(rv, + archive_read_open2(a, NULL, o, r, s, c)); + assertEqualString(msg, archive_error_string(a)); + archive_read_free(a); +} + +DEFINE_TEST(test_archive_read_open2) +{ + const char *no_reader = + "No reader function provided to archive_read_open"; + const char *no_formats = "No formats registered"; + + test(1, NULL, NULL, NULL, NULL, + ARCHIVE_FATAL, no_reader); + test(1, open_cb, NULL, NULL, NULL, + ARCHIVE_FATAL, no_reader); + test(1, open_cb, read_cb, NULL, NULL, + ARCHIVE_OK, NULL); + test(1, open_cb, read_cb, skip_cb, NULL, + ARCHIVE_OK, NULL); + test(1, open_cb, read_cb, skip_cb, close_cb, + ARCHIVE_OK, NULL); + test(1, NULL, read_cb, skip_cb, close_cb, + ARCHIVE_OK, NULL); + test(1, open_cb, read_cb, skip_cb, NULL, + ARCHIVE_OK, NULL); + test(1, NULL, read_cb, skip_cb, NULL, + ARCHIVE_OK, NULL); + test(1, NULL, read_cb, NULL, NULL, + ARCHIVE_OK, NULL); + + test(0, NULL, NULL, NULL, NULL, + ARCHIVE_FATAL, no_reader); + test(0, open_cb, NULL, NULL, NULL, + ARCHIVE_FATAL, no_reader); + test(0, open_cb, read_cb, NULL, NULL, + ARCHIVE_FATAL, no_formats); + test(0, open_cb, read_cb, skip_cb, NULL, + ARCHIVE_FATAL, no_formats); + test(0, open_cb, read_cb, skip_cb, close_cb, + ARCHIVE_FATAL, no_formats); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_set_filter_option.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_set_filter_option.c new file mode 100644 index 0000000..31d575f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_set_filter_option.c @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 2011 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +#define should(__a, __code, __m, __o, __v) \ +assertEqualInt(__code, archive_read_set_filter_option(__a, __m, __o, __v)) + +static void +test(int pristine) +{ + struct archive* a = archive_read_new(); + + if (!pristine) + archive_read_support_filter_all(a); + + should(a, ARCHIVE_OK, NULL, NULL, NULL); + should(a, ARCHIVE_OK, "", "", ""); + + should(a, ARCHIVE_FAILED, NULL, "fubar", NULL); + should(a, ARCHIVE_FAILED, NULL, "fubar", "snafu"); + should(a, ARCHIVE_FAILED, "fubar", "snafu", NULL); + should(a, ARCHIVE_FAILED, "fubar", "snafu", "betcha"); + + archive_read_free(a); +} + +DEFINE_TEST(test_archive_read_set_filter_option) +{ + test(1); + test(0); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_set_format_option.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_set_format_option.c new file mode 100644 index 0000000..2d7acf3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_set_format_option.c @@ -0,0 +1,67 @@ +/*- + * Copyright (c) 2011 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +#define should(__a, __code, __m, __o, __v) \ +assertEqualInt(__code, archive_read_set_format_option(__a, __m, __o, __v)) + +static void +test(int pristine) +{ + struct archive* a = archive_read_new(); + int known_option_rv = pristine ? ARCHIVE_FAILED : ARCHIVE_OK; + + if (!pristine) + archive_read_support_format_all(a); + + /* NULL and "" denote `no option', so they're ok no matter + * what, if any, formats are registered */ + should(a, ARCHIVE_OK, NULL, NULL, NULL); + should(a, ARCHIVE_OK, "", "", ""); + + /* unknown modules and options */ + should(a, ARCHIVE_FAILED, "fubar", "snafu", NULL); + should(a, ARCHIVE_FAILED, "fubar", "snafu", "betcha"); + + /* unknown modules and options */ + should(a, ARCHIVE_FAILED, NULL, "snafu", NULL); + should(a, ARCHIVE_FAILED, NULL, "snafu", "betcha"); + + /* ARCHIVE_OK with iso9660 loaded, ARCHIVE_WARN otherwise */ + should(a, known_option_rv, "iso9660", "joliet", NULL); + should(a, known_option_rv, "iso9660", "joliet", NULL); + should(a, known_option_rv, NULL, "joliet", NULL); + should(a, known_option_rv, NULL, "joliet", NULL); + + archive_read_free(a); +} + +DEFINE_TEST(test_archive_read_set_format_option) +{ + test(1); + test(0); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_set_option.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_set_option.c new file mode 100644 index 0000000..0b816b7 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_set_option.c @@ -0,0 +1,69 @@ +/*- + * Copyright (c) 2011 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +#define should(__a, __code, __m, __o, __v) \ +assertEqualInt(__code, archive_read_set_option(__a, __m, __o, __v)) + +static void +test(int pristine) +{ + struct archive* a = archive_read_new(); + int known_option_rv = pristine ? ARCHIVE_FAILED : ARCHIVE_OK; + + if (!pristine) { + archive_read_support_filter_all(a); + archive_read_support_format_all(a); + } + + /* NULL and "" denote `no option', so they're ok no matter + * what, if any, formats are registered */ + should(a, ARCHIVE_OK, NULL, NULL, NULL); + should(a, ARCHIVE_OK, "", "", ""); + + /* unknown modules and options */ + should(a, ARCHIVE_FAILED, "fubar", "snafu", NULL); + should(a, ARCHIVE_FAILED, "fubar", "snafu", "betcha"); + + /* unknown modules and options */ + should(a, ARCHIVE_FAILED, NULL, "snafu", NULL); + should(a, ARCHIVE_FAILED, NULL, "snafu", "betcha"); + + /* ARCHIVE_OK with iso9660 loaded, ARCHIVE_WARN otherwise */ + should(a, known_option_rv, "iso9660", "joliet", NULL); + should(a, known_option_rv, "iso9660", "joliet", NULL); + should(a, known_option_rv, NULL, "joliet", NULL); + should(a, known_option_rv, NULL, "joliet", NULL); + + archive_read_free(a); +} + +DEFINE_TEST(test_archive_read_set_option) +{ + test(1); + test(0); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_set_options.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_set_options.c new file mode 100644 index 0000000..a8c68d7 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_set_options.c @@ -0,0 +1,126 @@ +/*- + * Copyright (c) 2011 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +#define should(__a, __code, __opts) \ +assertEqualInt(__code, archive_read_set_options(__a, __opts)) + +static void +test(int pristine) +{ + struct archive* a = archive_read_new(); + int halfempty_options_rv = pristine ? ARCHIVE_FAILED : ARCHIVE_OK; + int known_option_rv = pristine ? ARCHIVE_FAILED : ARCHIVE_OK; + + if (!pristine) { + archive_read_support_filter_all(a); + archive_read_support_format_all(a); + } + + /* NULL and "" denote `no option', so they're ok no matter + * what, if any, formats are registered */ + should(a, ARCHIVE_OK, NULL); + should(a, ARCHIVE_OK, ""); + + /* unknown modules and options */ + should(a, ARCHIVE_FAILED, "fubar:snafu"); + assertEqualString("Unknown module name: `fubar'", + archive_error_string(a)); + should(a, ARCHIVE_FAILED, "fubar:snafu=betcha"); + assertEqualString("Unknown module name: `fubar'", + archive_error_string(a)); + + /* unknown modules and options */ + should(a, ARCHIVE_FAILED, "snafu"); + assertEqualString("Undefined option: `snafu'", + archive_error_string(a)); + should(a, ARCHIVE_FAILED, "snafu=betcha"); + assertEqualString("Undefined option: `snafu'", + archive_error_string(a)); + + /* ARCHIVE_OK with iso9660 loaded, ARCHIVE_FAILED otherwise */ + should(a, known_option_rv, "iso9660:joliet"); + if (pristine) { + assertEqualString("Unknown module name: `iso9660'", + archive_error_string(a)); + } + should(a, known_option_rv, "iso9660:joliet"); + if (pristine) { + assertEqualString("Unknown module name: `iso9660'", + archive_error_string(a)); + } + should(a, known_option_rv, "joliet"); + if (pristine) { + assertEqualString("Undefined option: `joliet'", + archive_error_string(a)); + } + should(a, known_option_rv, "!joliet"); + if (pristine) { + assertEqualString("Undefined option: `joliet'", + archive_error_string(a)); + } + + should(a, ARCHIVE_OK, ","); + should(a, ARCHIVE_OK, ",,"); + + should(a, halfempty_options_rv, ",joliet"); + if (pristine) { + assertEqualString("Undefined option: `joliet'", + archive_error_string(a)); + } + should(a, halfempty_options_rv, "joliet,"); + if (pristine) { + assertEqualString("Undefined option: `joliet'", + archive_error_string(a)); + } + + should(a, ARCHIVE_FAILED, "joliet,snafu"); + if (pristine) { + assertEqualString("Undefined option: `joliet'", + archive_error_string(a)); + } else { + assertEqualString("Undefined option: `snafu'", + archive_error_string(a)); + } + + should(a, ARCHIVE_FAILED, "iso9660:snafu"); + if (pristine) { + assertEqualString("Unknown module name: `iso9660'", + archive_error_string(a)); + } else { + assertEqualString("Undefined option: `iso9660:snafu'", + archive_error_string(a)); + } + + archive_read_free(a); +} + +DEFINE_TEST(test_archive_read_set_options) +{ + test(1); + test(0); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_support.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_support.c new file mode 100644 index 0000000..1619b07 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_read_support.c @@ -0,0 +1,98 @@ +/*- + * Copyright (c) 2011 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * Verify that the various archive_read_support_* functions + * return appropriate errors when invoked on the wrong kind of + * archive handle. + */ + +typedef struct archive *constructor(void); +typedef int enabler(struct archive *); +typedef int destructor(struct archive *); + +static void +test_success(constructor new_, enabler enable_, destructor free_) +{ + struct archive *a = new_(); + int result = enable_(a); + if (result == ARCHIVE_WARN) { + assert(NULL != archive_error_string(a)); + assertEqualIntA(a, -1, archive_errno(a)); + } else { + assertEqualIntA(a, ARCHIVE_OK, result); + assert(NULL == archive_error_string(a)); + assertEqualIntA(a, 0, archive_errno(a)); + } + free_(a); +} + +static void +test_failure(constructor new_, enabler enable_, destructor free_) +{ + struct archive *a = new_(); + assertEqualIntA(a, ARCHIVE_FATAL, enable_(a)); + assert(NULL != archive_error_string(a)); + assertEqualIntA(a, -1, archive_errno(a)); + free_(a); +} + +static void +test_filter_or_format(enabler enable) +{ + test_success(archive_read_new, enable, archive_read_free); + test_failure(archive_write_new, enable, archive_write_free); + test_failure(archive_read_disk_new, enable, archive_read_free); + test_failure(archive_write_disk_new, enable, archive_write_free); +} + +DEFINE_TEST(test_archive_read_support) +{ + test_filter_or_format(archive_read_support_format_7zip); + test_filter_or_format(archive_read_support_format_all); + test_filter_or_format(archive_read_support_format_ar); + test_filter_or_format(archive_read_support_format_cab); + test_filter_or_format(archive_read_support_format_cpio); + test_filter_or_format(archive_read_support_format_empty); + test_filter_or_format(archive_read_support_format_iso9660); + test_filter_or_format(archive_read_support_format_lha); + test_filter_or_format(archive_read_support_format_mtree); + test_filter_or_format(archive_read_support_format_tar); + test_filter_or_format(archive_read_support_format_xar); + test_filter_or_format(archive_read_support_format_zip); + + test_filter_or_format(archive_read_support_filter_all); + test_filter_or_format(archive_read_support_filter_bzip2); + test_filter_or_format(archive_read_support_filter_compress); + test_filter_or_format(archive_read_support_filter_gzip); + test_filter_or_format(archive_read_support_filter_lzip); + test_filter_or_format(archive_read_support_filter_lzma); + test_filter_or_format(archive_read_support_filter_none); + test_filter_or_format(archive_read_support_filter_rpm); + test_filter_or_format(archive_read_support_filter_uu); + test_filter_or_format(archive_read_support_filter_xz); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_set_error.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_set_error.c new file mode 100644 index 0000000..b83c08c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_set_error.c @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2011 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +static void +test(struct archive *a, int code, const char *msg) +{ + archive_set_error(a, code, "%s", msg); + + assertEqualInt(code, archive_errno(a)); + assertEqualString(msg, archive_error_string(a)); +} + +DEFINE_TEST(test_archive_set_error) +{ + struct archive* a = archive_read_new(); + + /* unlike printf("%s", NULL), + * archive_set_error(a, code, "%s", NULL) + * segfaults, so it's not tested here */ + test(a, 12, "abcdefgh"); + test(a, 0, "123456"); + test(a, -1, "tuvw"); + test(a, 34, "XYZ"); + + archive_read_free(a); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_string.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_string.c new file mode 100644 index 0000000..7fa743b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_string.c @@ -0,0 +1,431 @@ +/*- + * Copyright (c) 2011 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +#define __LIBARCHIVE_TEST +#include "archive_string.h" + +#define EXTENT 32 + +#define assertStringSizes(strlen, buflen, as) \ + assertEqualInt(strlen, (as).length); \ + assertEqualInt(buflen, (as).buffer_length); + +#define assertExactString(strlen, buflen, data, as) \ + do { \ + assertStringSizes(strlen, buflen, as); \ + assertEqualString(data, (as).s); \ + } while (0) + +#define assertNonNULLString(strlen, buflen, as) \ + do { \ + assertStringSizes(strlen, buflen, as); \ + assert(NULL != (as).s); \ + } while (0) + +static void +test_archive_string_ensure(void) +{ + struct archive_string s; + + archive_string_init(&s); + assertExactString(0, 0, NULL, s); + + /* single-extent allocation */ + assert(&s == archive_string_ensure(&s, 5)); + assertNonNULLString(0, EXTENT, s); + + /* what happens around extent boundaries? */ + assert(&s == archive_string_ensure(&s, EXTENT - 1)); + assertNonNULLString(0, EXTENT, s); + + assert(&s == archive_string_ensure(&s, EXTENT)); + assertNonNULLString(0, EXTENT, s); + + assert(&s == archive_string_ensure(&s, EXTENT + 1)); + assertNonNULLString(0, 2 * EXTENT, s); + + archive_string_free(&s); +} + +static void +test_archive_strcat(void) +{ + struct archive_string s; + + archive_string_init(&s); + assertExactString(0, 0, NULL, s); + + /* null target, empty source */ + assert(&s == archive_strcat(&s, "")); + assertExactString(0, EXTENT, "", s); + + /* empty target, empty source */ + assert(&s == archive_strcat(&s, "")); + assertExactString(0, EXTENT, "", s); + + /* empty target, non-empty source */ + assert(&s == archive_strcat(&s, "fubar")); + assertExactString(5, EXTENT, "fubar", s); + + /* non-empty target, non-empty source */ + assert(&s == archive_strcat(&s, "baz")); + assertExactString(8, EXTENT, "fubarbaz", s); + + archive_string_free(&s); +} + +static void +test_archive_strappend_char(void) +{ + struct archive_string s; + + archive_string_init(&s); + assertExactString(0, 0, NULL, s); + + /* null target */ + archive_strappend_char(&s, 'X'); + assertExactString(1, EXTENT, "X", s); + + /* non-empty target */ + archive_strappend_char(&s, 'Y'); + assertExactString(2, EXTENT, "XY", s); + + archive_string_free(&s); +} + +/* archive_strnXXX() tests focus on length handling. + * other behaviors are tested by proxy through archive_strXXX() + */ + +static void +test_archive_strncat(void) +{ + struct archive_string s; + + archive_string_init(&s); + assertExactString(0, 0, NULL, s); + + /* perfect length */ + assert(&s == archive_strncat(&s, "snafu", 5)); + assertExactString(5, EXTENT, "snafu", s); + + /* short read */ + assert(&s == archive_strncat(&s, "barbazqux", 3)); + assertExactString(8, EXTENT, "snafubar", s); + + /* long read is ok too! */ + assert(&s == archive_strncat(&s, "snafu", 8)); + assertExactString(13, EXTENT, "snafubarsnafu", s); + + archive_string_free(&s); +} + +static void +test_archive_strncpy(void) +{ + struct archive_string s; + + archive_string_init(&s); + assertExactString(0, 0, NULL, s); + + /* perfect length */ + assert(&s == archive_strncpy(&s, "fubar", 5)); + assertExactString(5, EXTENT, "fubar", s); + + /* short read */ + assert(&s == archive_strncpy(&s, "snafubar", 5)); + assertExactString(5, EXTENT, "snafu", s); + + /* long read is ok too! */ + assert(&s == archive_strncpy(&s, "snafu", 8)); + assertExactString(5, EXTENT, "snafu", s); + + archive_string_free(&s); +} + +static void +test_archive_strcpy(void) +{ + struct archive_string s; + + archive_string_init(&s); + assertExactString(0, 0, NULL, s); + + /* null target */ + assert(&s == archive_strcpy(&s, "snafu")); + assertExactString(5, EXTENT, "snafu", s); + + /* dirty target */ + assert(&s == archive_strcpy(&s, "foo")); + assertExactString(3, EXTENT, "foo", s); + + /* dirty target, empty source */ + assert(&s == archive_strcpy(&s, "")); + assertExactString(0, EXTENT, "", s); + + archive_string_free(&s); +} + +static void +test_archive_string_concat(void) +{ + struct archive_string s, t, u, v; + + archive_string_init(&s); + assertExactString(0, 0, NULL, s); + archive_string_init(&t); + assertExactString(0, 0, NULL, t); + archive_string_init(&u); + assertExactString(0, 0, NULL, u); + archive_string_init(&v); + assertExactString(0, 0, NULL, v); + + /* null target, null source */ + archive_string_concat(&t, &s); + assertExactString(0, 0, NULL, s); + assertExactString(0, EXTENT, "", t); + + /* null target, empty source */ + assert(&s == archive_strcpy(&s, "")); + archive_string_concat(&u, &s); + assertExactString(0, EXTENT, "", s); + assertExactString(0, EXTENT, "", u); + + /* null target, non-empty source */ + assert(&s == archive_strcpy(&s, "foo")); + archive_string_concat(&v, &s); + assertExactString(3, EXTENT, "foo", s); + assertExactString(3, EXTENT, "foo", v); + + /* empty target, empty source */ + assert(&s == archive_strcpy(&s, "")); + assert(&t == archive_strcpy(&t, "")); + archive_string_concat(&t, &s); + assertExactString(0, EXTENT, "", s); + assertExactString(0, EXTENT, "", t); + + /* empty target, non-empty source */ + assert(&s == archive_strcpy(&s, "snafu")); + assert(&t == archive_strcpy(&t, "")); + archive_string_concat(&t, &s); + assertExactString(5, EXTENT, "snafu", s); + assertExactString(5, EXTENT, "snafu", t); + + archive_string_free(&v); + archive_string_free(&u); + archive_string_free(&t); + archive_string_free(&s); +} + +static void +test_archive_string_copy(void) +{ + struct archive_string s, t, u, v; + + archive_string_init(&s); + assertExactString(0, 0, NULL, s); + archive_string_init(&t); + assertExactString(0, 0, NULL, t); + archive_string_init(&u); + assertExactString(0, 0, NULL, u); + archive_string_init(&v); + assertExactString(0, 0, NULL, v); + + /* null target, null source */ + archive_string_copy(&t, &s); + assertExactString(0, 0, NULL, s); + assertExactString(0, EXTENT, "", t); + + /* null target, empty source */ + archive_string_copy(&u, &t); + assertExactString(0, EXTENT, "", t); + assertExactString(0, EXTENT, "", u); + + /* empty target, empty source */ + archive_string_copy(&u, &t); + assertExactString(0, EXTENT, "", t); + assertExactString(0, EXTENT, "", u); + + /* null target, non-empty source */ + assert(NULL != archive_strcpy(&s, "snafubar")); + assertExactString(8, EXTENT, "snafubar", s); + + archive_string_copy(&v, &s); + assertExactString(8, EXTENT, "snafubar", s); + assertExactString(8, EXTENT, "snafubar", v); + + /* empty target, non-empty source */ + assertExactString(0, EXTENT, "", t); + archive_string_copy(&t, &s); + assertExactString(8, EXTENT, "snafubar", s); + assertExactString(8, EXTENT, "snafubar", t); + + /* non-empty target, non-empty source */ + assert(NULL != archive_strcpy(&s, "fubar")); + assertExactString(5, EXTENT, "fubar", s); + + archive_string_copy(&t, &s); + assertExactString(5, EXTENT, "fubar", s); + assertExactString(5, EXTENT, "fubar", t); + + archive_string_free(&v); + archive_string_free(&u); + archive_string_free(&t); + archive_string_free(&s); +} + +static void +test_archive_string_sprintf(void) +{ + struct archive_string s; +#define S16 "0123456789abcdef" +#define S32 S16 S16 +#define S64 S32 S32 +#define S128 S64 S64 + const char *s32 = S32; + const char *s33 = S32 "0"; + const char *s64 = S64; + const char *s65 = S64 "0"; + const char *s128 = S128; + const char *s129 = S128 "0"; +#undef S16 +#undef S32 +#undef S64 +#undef S128 + + archive_string_init(&s); + assertExactString(0, 0, NULL, s); + + archive_string_sprintf(&s, "%s", ""); + assertExactString(0, 2 * EXTENT, "", s); + + archive_string_empty(&s); + archive_string_sprintf(&s, "%s", s32); + assertExactString(32, 2 * EXTENT, s32, s); + + archive_string_empty(&s); + archive_string_sprintf(&s, "%s", s33); + assertExactString(33, 2 * EXTENT, s33, s); + + archive_string_empty(&s); + archive_string_sprintf(&s, "%s", s64); + assertExactString(64, 4 * EXTENT, s64, s); + + archive_string_empty(&s); + archive_string_sprintf(&s, "%s", s65); + assertExactString(65, 4 * EXTENT, s65, s); + + archive_string_empty(&s); + archive_string_sprintf(&s, "%s", s128); + assertExactString(128, 8 * EXTENT, s128, s); + + archive_string_empty(&s); + archive_string_sprintf(&s, "%s", s129); + assertExactString(129, 8 * EXTENT, s129, s); + + archive_string_empty(&s); + archive_string_sprintf(&s, "%d", 1234567890); + assertExactString(10, 8 * EXTENT, "1234567890", s); + + archive_string_free(&s); +} + +DEFINE_TEST(test_archive_string) +{ + test_archive_string_ensure(); + test_archive_strcat(); + test_archive_strappend_char(); + test_archive_strncat(); + test_archive_strncpy(); + test_archive_strcpy(); + test_archive_string_concat(); + test_archive_string_copy(); + test_archive_string_sprintf(); +} + +static const char *strings[] = +{ + "dir/path", + "dir/path2", + "dir/path3", + "dir/path4", + "dir/path5", + "dir/path6", + "dir/path7", + "dir/path8", + "dir/path9", + "dir/subdir/path", + "dir/subdir/path2", + "dir/subdir/path3", + "dir/subdir/path4", + "dir/subdir/path5", + "dir/subdir/path6", + "dir/subdir/path7", + "dir/subdir/path8", + "dir/subdir/path9", + "dir2/path", + "dir2/path2", + "dir2/path3", + "dir2/path4", + "dir2/path5", + "dir2/path6", + "dir2/path7", + "dir2/path8", + "dir2/path9", + NULL +}; + +DEFINE_TEST(test_archive_string_sort) +{ + unsigned int i, j, size; + char **test_strings, *tmp; + + srand((unsigned int)time(NULL)); + size = sizeof(strings) / sizeof(char *); + assert((test_strings = (char **)calloc(1, sizeof(strings))) != NULL); + for (i = 0; i < (size - 1); i++) + assert((test_strings[i] = strdup(strings[i])) != NULL); + + /* Shuffle the test strings */ + for (i = 0; i < (size - 1); i++) + { + j = rand() % ((size - 1) - i); + j += i; + tmp = test_strings[i]; + test_strings[i] = test_strings[j]; + test_strings[j] = tmp; + } + + /* Sort and test */ + assertEqualInt(ARCHIVE_OK, archive_utility_string_sort(test_strings)); + for (i = 0; i < (size - 1); i++) + assertEqualString(test_strings[i], strings[i]); + + for (i = 0; i < (size - 1); i++) + free(test_strings[i]); + free(test_strings); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_string_conversion.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_string_conversion.c new file mode 100644 index 0000000..e86f97c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_string_conversion.c @@ -0,0 +1,810 @@ +/*- + * Copyright (c) 2011-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +#include + +#define __LIBARCHIVE_TEST +#include "archive_string.h" + +/* +Execute the following to rebuild the data for this program: + tail -n +36 test_archive_string_conversion.c | /bin/sh +# +# This requires http://unicode.org/Public/6.0.0/ucd/NormalizationTest.txt +# +if="NormalizationTest.txt" +if [ ! -f ${if} ]; then + echo "Not found: \"${if}\"" + exit 0 +fi +of=test_archive_string_conversion.txt.Z +echo "\$FreeBSD\$" > ${of}.uu +awk -F ';' '$0 ~/^[0-9A-F]+/ {printf "%s;%s\n", $2, $3}' ${if} | compress | uuencode ${of} >> ${of}.uu +exit 1 +*/ + +static int +unicode_to_utf8(char *p, uint32_t uc) +{ + char *_p = p; + + /* Translate code point to UTF8 */ + if (uc <= 0x7f) { + *p++ = (char)uc; + } else if (uc <= 0x7ff) { + *p++ = 0xc0 | ((uc >> 6) & 0x1f); + *p++ = 0x80 | (uc & 0x3f); + } else if (uc <= 0xffff) { + *p++ = 0xe0 | ((uc >> 12) & 0x0f); + *p++ = 0x80 | ((uc >> 6) & 0x3f); + *p++ = 0x80 | (uc & 0x3f); + } else { + *p++ = 0xf0 | ((uc >> 18) & 0x07); + *p++ = 0x80 | ((uc >> 12) & 0x3f); + *p++ = 0x80 | ((uc >> 6) & 0x3f); + *p++ = 0x80 | (uc & 0x3f); + } + return ((int)(p - _p)); +} + +static void +archive_be16enc(void *pp, uint16_t u) +{ + unsigned char *p = (unsigned char *)pp; + + p[0] = (u >> 8) & 0xff; + p[1] = u & 0xff; +} + +static int +unicode_to_utf16be(char *p, uint32_t uc) +{ + char *utf16 = p; + + if (uc > 0xffff) { + /* We have a code point that won't fit into a + * wchar_t; convert it to a surrogate pair. */ + uc -= 0x10000; + archive_be16enc(utf16, ((uc >> 10) & 0x3ff) + 0xD800); + archive_be16enc(utf16+2, (uc & 0x3ff) + 0xDC00); + return (4); + } else { + archive_be16enc(utf16, uc); + return (2); + } +} + +static void +archive_le16enc(void *pp, uint16_t u) +{ + unsigned char *p = (unsigned char *)pp; + + p[0] = u & 0xff; + p[1] = (u >> 8) & 0xff; +} + +static size_t +unicode_to_utf16le(char *p, uint32_t uc) +{ + char *utf16 = p; + + if (uc > 0xffff) { + /* We have a code point that won't fit into a + * wchar_t; convert it to a surrogate pair. */ + uc -= 0x10000; + archive_le16enc(utf16, ((uc >> 10) & 0x3ff) + 0xD800); + archive_le16enc(utf16+2, (uc & 0x3ff) + 0xDC00); + return (4); + } else { + archive_le16enc(utf16, uc); + return (2); + } +} + +static int +wc_size(void) +{ + return (sizeof(wchar_t)); +} + +static int +unicode_to_wc(wchar_t *wp, uint32_t uc) +{ + if (wc_size() == 4) { + *wp = (wchar_t)uc; + return (1); + } + if (uc > 0xffff) { + /* We have a code point that won't fit into a + * wchar_t; convert it to a surrogate pair. */ + uc -= 0x10000; + *wp++ = (wchar_t)(((uc >> 10) & 0x3ff) + 0xD800); + *wp = (wchar_t)((uc & 0x3ff) + 0xDC00); + return (2); + } else { + *wp = (wchar_t)uc; + return (1); + } +} + +/* + * Note: U+2000 - U+2FFF, U+F900 - U+FAFF and U+2F800 - U+2FAFF are not + * converted to NFD on Mac OS. + * see also http://developer.apple.com/library/mac/#qa/qa2001/qa1173.html + */ +static int +scan_unicode_pattern(char *out, wchar_t *wout, char *u16be, char *u16le, + const char *pattern, int mac_nfd) +{ + unsigned uc = 0; + const char *p = pattern; + char *op = out; + wchar_t *owp = wout; + char *op16be = u16be; + char *op16le = u16le; + int ret = 0; + + for (;;) { + if (*p >= '0' && *p <= '9') + uc = (uc << 4) + (*p - '0'); + else if (*p >= 'A' && *p <= 'F') + uc = (uc << 4) + (*p - 'A' + 0x0a); + else { + if (mac_nfd && op == out) { + /* + * These are not converted to NFD on Mac OS. + * U+2000 - U+2FFF + * U+F900 - U+FAFF + * U+2F800 - U+2FAFF + */ + switch (uc) { + case 0x2194: case 0x219A: case 0x219B: + case 0x21AE: case 0x21CD: case 0x21CE: + case 0x21CF: case 0x2204: case 0x2209: + case 0x220C: case 0x2224: case 0x2226: + case 0x2241: case 0x2244: case 0x2247: + case 0x2249: case 0x2260: case 0x2262: + case 0x226D: case 0x226E: case 0x226F: + case 0x2270: case 0x2271: case 0x2274: + case 0x2275: case 0x2276: case 0x2278: + case 0x2279: case 0x227A: case 0x227B: + case 0x2280: case 0x2281: case 0x2284: + case 0x2285: case 0x2288: case 0x2289: + case 0x22AC: case 0x22AD: case 0x22AE: + case 0x22AF: case 0x22E0: case 0x22E1: + case 0x22E2: case 0x22E3: case 0x22EA: + case 0x22EB: case 0x22EC: case 0x22ED: + + /* + * Those code points are not converted to + * NFD on Mac OS. I do not know the reason + * because it is undocumented. + * NFC NFD + * 1109A ==> 11099 110BA + * 1109C ==> 1109B 110BA + * 110AB ==> 110A5 110BA + */ + case 0x1109A: case 0x1109C: case 0x110AB: + ret = 1; + break; + } + } + op16be += unicode_to_utf16be(op16be, uc); + op16le += unicode_to_utf16le(op16le, uc); + owp += unicode_to_wc(owp, uc); + op += unicode_to_utf8(op, uc); + if (!*p) { + *op16be++ = 0; + *op16be = 0; + *op16le++ = 0; + *op16le = 0; + *owp = L'\0'; + *op = '\0'; + break; + } + uc = 0; + } + p++; + } + return (ret); +} + +static int +is_wc_unicode(void) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + return (1); +#else + return (0); +#endif +} + +/* + * A conversion test that we correctly normalize UTF-8 and UTF-16BE characters. + * On Mac OS, the characters to be Form D. + * On other platforms, the characters to be Form C. + */ +static void +test_archive_string_normalization_nfc(const char *testdata) +{ + struct archive *a, *a2; + struct archive_string utf8; + struct archive_mstring mstr; + struct archive_string_conv *f_sconv8, *t_sconv8; + struct archive_string_conv *f_sconv16be, *f_sconv16le; + FILE *fp; + char buff[512]; + int line = 0; + int locale_is_utf8, wc_is_unicode; + int sconv_opt = SCONV_SET_OPT_NORMALIZATION_C; + + locale_is_utf8 = (NULL != setlocale(LC_ALL, "en_US.UTF-8")); + wc_is_unicode = is_wc_unicode(); + /* If it doesn't exist, just warn and return. */ + if (!locale_is_utf8 && !wc_is_unicode) { + skipping("A test of string normalization for NFC requires " + "a suitable locale; en_US.UTF-8 not available on this " + "system"); + return; + } + + archive_string_init(&utf8); + memset(&mstr, 0, sizeof(mstr)); + + /* + * Create string conversion objects. + */ + assert((a = archive_read_new()) != NULL); + assertA(NULL != (f_sconv8 = + archive_string_conversion_from_charset(a, "UTF-8", 0))); + assertA(NULL != (f_sconv16be = + archive_string_conversion_from_charset(a, "UTF-16BE", 0))); + assertA(NULL != (f_sconv16le = + archive_string_conversion_from_charset(a, "UTF-16LE", 0))); + assert((a2 = archive_write_new()) != NULL); + assertA(NULL != (t_sconv8 = + archive_string_conversion_to_charset(a2, "UTF-8", 0))); + if (f_sconv8 == NULL || f_sconv16be == NULL || f_sconv16le == NULL || + t_sconv8 == NULL) { + /* We cannot continue this test. */ + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + archive_string_conversion_set_opt(f_sconv8, sconv_opt); + archive_string_conversion_set_opt(f_sconv16be, sconv_opt); + archive_string_conversion_set_opt(f_sconv16le, sconv_opt); + archive_string_conversion_set_opt(t_sconv8, sconv_opt); + + /* Open a test pattern file. */ + assert((fp = fopen(testdata, "r")) != NULL); + + /* + * Read test data. + * Test data format: + * ';' '\n' + * Unicode pattern format: + * [0-9A-F]{4,5}([ ][0-9A-F]{4,5}){0,} + */ + while (fgets(buff, sizeof(buff), fp) != NULL) { + char nfc[80], nfd[80]; + char utf8_nfc[80], utf8_nfd[80]; + char utf16be_nfc[80], utf16be_nfd[80]; + char utf16le_nfc[80], utf16le_nfd[80]; + wchar_t wc_nfc[40], wc_nfd[40]; + char *e, *p; + const wchar_t *wp; + const char *mp; + size_t mplen; + + line++; + if (buff[0] == '#') + continue; + p = strchr(buff, ';'); + if (p == NULL) + continue; + *p++ = '\0'; + /* Copy an NFC pattern */ + strncpy(nfc, buff, sizeof(nfc)-1); + nfc[sizeof(nfc)-1] = '\0'; + e = p; + p = strchr(p, '\n'); + if (p == NULL) + continue; + *p = '\0'; + /* Copy an NFD pattern */ + strncpy(nfd, e, sizeof(nfd)-1); + nfd[sizeof(nfd)-1] = '\0'; + + /* + * Get an NFC patterns. + */ + scan_unicode_pattern(utf8_nfc, wc_nfc, utf16be_nfc, utf16le_nfc, + nfc, 0); + + /* + * Get an NFD patterns. + */ + scan_unicode_pattern(utf8_nfd, wc_nfd, utf16be_nfd, utf16le_nfd, + nfd, 0); + + if (locale_is_utf8) { + /* + * Normalize an NFD string for import. + */ + assertEqualInt(0, archive_strcpy_l( + &utf8, utf8_nfd, f_sconv8)); + failure("NFD(%s) should be converted to NFC(%s):%d", + nfd, nfc, line); + assertEqualUTF8String(utf8_nfc, utf8.s); + + /* + * Normalize an NFC string for import. + */ + assertEqualInt(0, archive_strcpy_l( + &utf8, utf8_nfc, f_sconv8)); + failure("NFC(%s) should not be any changed:%d", + nfc, line); + assertEqualUTF8String(utf8_nfc, utf8.s); + + /* + * Copy an NFC string for export. + */ + assertEqualInt(0, archive_strcpy_l( + &utf8, utf8_nfc, t_sconv8)); + failure("NFC(%s) should not be any changed:%d", + nfc, line); + assertEqualUTF8String(utf8_nfc, utf8.s); + + /* + * Normalize an NFD string in UTF-16BE for import. + */ + assertEqualInt(0, archive_strncpy_l( + &utf8, utf16be_nfd, 100000, f_sconv16be)); + failure("NFD(%s) should be converted to NFC(%s):%d", + nfd, nfc, line); + assertEqualUTF8String(utf8_nfc, utf8.s); + + /* + * Normalize an NFD string in UTF-16LE for import. + */ + assertEqualInt(0, archive_strncpy_l( + &utf8, utf16le_nfd, 100000, f_sconv16le)); + failure("NFD(%s) should be converted to NFC(%s):%d", + nfd, nfc, line); + assertEqualUTF8String(utf8_nfc, utf8.s); + } + + /* + * Test for archive_mstring interface. + * In specific, Windows platform UTF-16BE is directly + * converted to/from wide-character to avoid the effect of + * current locale since windows platform cannot make + * locale UTF-8. + */ + if (locale_is_utf8 || wc_is_unicode) { + /* + * Normalize an NFD string in UTF-8 for import. + */ + assertEqualInt(0, archive_mstring_copy_mbs_len_l( + &mstr, utf8_nfd, 100000, f_sconv8)); + assertEqualInt(0, + archive_mstring_get_wcs(a, &mstr, &wp)); + failure("UTF-8 NFD(%s) should be converted " + "to WCS NFC(%s):%d", nfd, nfc, line); + assertEqualWString(wc_nfc, wp); + + /* + * Normalize an NFD string in UTF-16BE for import. + */ + assertEqualInt(0, archive_mstring_copy_mbs_len_l( + &mstr, utf16be_nfd, 100000, f_sconv16be)); + assertEqualInt(0, + archive_mstring_get_wcs(a, &mstr, &wp)); + failure("UTF-8 NFD(%s) should be converted " + "to WCS NFC(%s):%d", nfd, nfc, line); + assertEqualWString(wc_nfc, wp); + + /* + * Normalize an NFD string in UTF-16LE for import. + */ + assertEqualInt(0, archive_mstring_copy_mbs_len_l( + &mstr, utf16le_nfd, 100000, f_sconv16le)); + assertEqualInt(0, + archive_mstring_get_wcs(a, &mstr, &wp)); + failure("UTF-8 NFD(%s) should be converted " + "to WCS NFC(%s):%d", nfd, nfc, line); + assertEqualWString(wc_nfc, wp); + + /* + * Copy an NFC wide-string for export. + */ + assertEqualInt(0, + archive_mstring_copy_wcs(&mstr, wc_nfc)); + assertEqualInt(0, archive_mstring_get_mbs_l( + &mstr, &mp, &mplen, t_sconv8)); + failure("WCS NFC(%s) should be UTF-8 NFC:%d" + ,nfc, line); + assertEqualUTF8String(utf8_nfc, mp); + } + } + + archive_string_free(&utf8); + archive_mstring_clean(&mstr); + fclose(fp); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a2)); +} + +static void +test_archive_string_normalization_mac_nfd(const char *testdata) +{ + struct archive *a, *a2; + struct archive_string utf8; + struct archive_mstring mstr; + struct archive_string_conv *f_sconv8, *t_sconv8; + struct archive_string_conv *f_sconv16be, *f_sconv16le; + FILE *fp; + char buff[512]; + int line = 0; + int locale_is_utf8, wc_is_unicode; + int sconv_opt = SCONV_SET_OPT_NORMALIZATION_D; + + locale_is_utf8 = (NULL != setlocale(LC_ALL, "en_US.UTF-8")); + wc_is_unicode = is_wc_unicode(); + /* If it doesn't exist, just warn and return. */ + if (!locale_is_utf8 && !wc_is_unicode) { + skipping("A test of string normalization for NFD requires " + "a suitable locale; en_US.UTF-8 not available on this " + "system"); + return; + } + + archive_string_init(&utf8); + memset(&mstr, 0, sizeof(mstr)); + + /* + * Create string conversion objects. + */ + assert((a = archive_read_new()) != NULL); + assertA(NULL != (f_sconv8 = + archive_string_conversion_from_charset(a, "UTF-8", 0))); + assertA(NULL != (f_sconv16be = + archive_string_conversion_from_charset(a, "UTF-16BE", 0))); + assertA(NULL != (f_sconv16le = + archive_string_conversion_from_charset(a, "UTF-16LE", 0))); + assert((a2 = archive_write_new()) != NULL); + assertA(NULL != (t_sconv8 = + archive_string_conversion_to_charset(a2, "UTF-8", 0))); + if (f_sconv8 == NULL || f_sconv16be == NULL || f_sconv16le == NULL || + t_sconv8 == NULL) { + /* We cannot continue this test. */ + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + archive_string_conversion_set_opt(f_sconv8, sconv_opt); + archive_string_conversion_set_opt(f_sconv16be, sconv_opt); + archive_string_conversion_set_opt(f_sconv16le, sconv_opt); + archive_string_conversion_set_opt(t_sconv8, sconv_opt); + + /* Open a test pattern file. */ + assert((fp = fopen(testdata, "r")) != NULL); + + /* + * Read test data. + * Test data format: + * ';' '\n' + * Unicode pattern format: + * [0-9A-F]{4,5}([ ][0-9A-F]{4,5}){0,} + */ + while (fgets(buff, sizeof(buff), fp) != NULL) { + char nfc[80], nfd[80]; + char utf8_nfc[80], utf8_nfd[80]; + char utf16be_nfc[80], utf16be_nfd[80]; + char utf16le_nfc[80], utf16le_nfd[80]; + wchar_t wc_nfc[40], wc_nfd[40]; + char *e, *p; + const wchar_t *wp; + const char *mp; + size_t mplen; + int should_be_nfc; + + line++; + if (buff[0] == '#') + continue; + p = strchr(buff, ';'); + if (p == NULL) + continue; + *p++ = '\0'; + /* Copy an NFC pattern */ + strncpy(nfc, buff, sizeof(nfc)-1); + nfc[sizeof(nfc)-1] = '\0'; + e = p; + p = strchr(p, '\n'); + if (p == NULL) + continue; + *p = '\0'; + /* Copy an NFD pattern */ + strncpy(nfd, e, sizeof(nfd)-1); + nfd[sizeof(nfd)-1] = '\0'; + + /* + * Get an NFC patterns. + */ + should_be_nfc = scan_unicode_pattern(utf8_nfc, wc_nfc, + utf16be_nfc, utf16le_nfc, nfc, 1); + + /* + * Get an NFD patterns. + */ + scan_unicode_pattern(utf8_nfd, wc_nfd, utf16be_nfd, utf16le_nfd, + nfd, 0); + + if (locale_is_utf8) { + /* + * Normalize an NFC string for import. + */ + assertEqualInt(0, archive_strcpy_l( + &utf8, utf8_nfc, f_sconv8)); + if (should_be_nfc) { + failure("NFC(%s) should not be converted to" + " NFD(%s):%d", nfc, nfd, line); + assertEqualUTF8String(utf8_nfc, utf8.s); + } else { + failure("NFC(%s) should be converted to" + " NFD(%s):%d", nfc, nfd, line); + assertEqualUTF8String(utf8_nfd, utf8.s); + } + + /* + * Normalize an NFD string for import. + */ + assertEqualInt(0, archive_strcpy_l( + &utf8, utf8_nfd, f_sconv8)); + failure("NFD(%s) should not be any changed:%d", + nfd, line); + assertEqualUTF8String(utf8_nfd, utf8.s); + + /* + * Copy an NFD string for export. + */ + assertEqualInt(0, archive_strcpy_l( + &utf8, utf8_nfd, t_sconv8)); + failure("NFD(%s) should not be any changed:%d", + nfd, line); + assertEqualUTF8String(utf8_nfd, utf8.s); + + /* + * Normalize an NFC string in UTF-16BE for import. + */ + assertEqualInt(0, archive_strncpy_l( + &utf8, utf16be_nfc, 100000, f_sconv16be)); + if (should_be_nfc) { + failure("NFC(%s) should not be converted to" + " NFD(%s):%d", nfc, nfd, line); + assertEqualUTF8String(utf8_nfc, utf8.s); + } else { + failure("NFC(%s) should be converted to" + " NFD(%s):%d", nfc, nfd, line); + assertEqualUTF8String(utf8_nfd, utf8.s); + } + + /* + * Normalize an NFC string in UTF-16LE for import. + */ + assertEqualInt(0, archive_strncpy_l( + &utf8, utf16le_nfc, 100000, f_sconv16le)); + if (should_be_nfc) { + failure("NFC(%s) should not be converted to" + " NFD(%s):%d", nfc, nfd, line); + assertEqualUTF8String(utf8_nfc, utf8.s); + } else { + failure("NFC(%s) should be converted to" + " NFD(%s):%d", nfc, nfd, line); + assertEqualUTF8String(utf8_nfd, utf8.s); + } + } + + /* + * Test for archive_mstring interface. + * In specific, Windows platform UTF-16BE is directly + * converted to/from wide-character to avoid the effect of + * current locale since windows platform cannot make + * locale UTF-8. + */ + if (locale_is_utf8 || wc_is_unicode) { + /* + * Normalize an NFD string in UTF-8 for import. + */ + assertEqualInt(0, archive_mstring_copy_mbs_len_l( + &mstr, utf8_nfc, 100000, f_sconv8)); + assertEqualInt(0, + archive_mstring_get_wcs(a, &mstr, &wp)); + if (should_be_nfc) { + failure("UTF-8 NFC(%s) should not be converted " + "to WCS NFD(%s):%d", nfc, nfd, line); + assertEqualWString(wc_nfc, wp); + } else { + failure("UTF-8 NFC(%s) should be converted " + "to WCS NFD(%s):%d", nfc, nfd, line); + assertEqualWString(wc_nfd, wp); + } + + /* + * Normalize an NFD string in UTF-16BE for import. + */ + assertEqualInt(0, archive_mstring_copy_mbs_len_l( + &mstr, utf16be_nfc, 100000, f_sconv16be)); + assertEqualInt(0, + archive_mstring_get_wcs(a, &mstr, &wp)); + if (should_be_nfc) { + failure("UTF-16BE NFC(%s) should not be " + "converted to WCS NFD(%s):%d", + nfc, nfd, line); + assertEqualWString(wc_nfc, wp); + } else { + failure("UTF-16BE NFC(%s) should be converted " + "to WCS NFD(%s):%d", nfc, nfd, line); + assertEqualWString(wc_nfd, wp); + } + + /* + * Normalize an NFD string in UTF-16LE for import. + */ + assertEqualInt(0, archive_mstring_copy_mbs_len_l( + &mstr, utf16le_nfc, 100000, f_sconv16le)); + assertEqualInt(0, + archive_mstring_get_wcs(a, &mstr, &wp)); + if (should_be_nfc) { + failure("UTF-16LE NFC(%s) should not be " + "converted to WCS NFD(%s):%d", + nfc, nfd, line); + assertEqualWString(wc_nfc, wp); + } else { + failure("UTF-16LE NFC(%s) should be converted " + "to WCS NFD(%s):%d", nfc, nfd, line); + assertEqualWString(wc_nfd, wp); + } + + /* + * Copy an NFD wide-string for export. + */ + assertEqualInt(0, archive_mstring_copy_wcs( + &mstr, wc_nfd)); + assertEqualInt(0, archive_mstring_get_mbs_l( + &mstr, &mp, &mplen, t_sconv8)); + failure("WCS NFD(%s) should be UTF-8 NFD:%d" + ,nfd, line); + assertEqualUTF8String(utf8_nfd, mp); + } + } + + archive_string_free(&utf8); + archive_mstring_clean(&mstr); + fclose(fp); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a2)); +} + +static void +test_archive_string_canonicalization(void) +{ + struct archive *a; + struct archive_string_conv *sconv; + + setlocale(LC_ALL, "en_US.UTF-8"); + + assert((a = archive_read_new()) != NULL); + + assertA(NULL != (sconv = + archive_string_conversion_to_charset(a, "UTF-8", 1))); + failure("Charset name should be UTF-8"); + assertEqualString("UTF-8", + archive_string_conversion_charset_name(sconv)); + + assertA(NULL != (sconv = + archive_string_conversion_to_charset(a, "UTF8", 1))); + failure("Charset name should be UTF-8"); + assertEqualString("UTF-8", + archive_string_conversion_charset_name(sconv)); + + assertA(NULL != (sconv = + archive_string_conversion_to_charset(a, "utf8", 1))); + failure("Charset name should be UTF-8"); + assertEqualString("UTF-8", + archive_string_conversion_charset_name(sconv)); + + assertA(NULL != (sconv = + archive_string_conversion_to_charset(a, "UTF-16BE", 1))); + failure("Charset name should be UTF-16BE"); + assertEqualString("UTF-16BE", + archive_string_conversion_charset_name(sconv)); + + assertA(NULL != (sconv = + archive_string_conversion_to_charset(a, "UTF16BE", 1))); + failure("Charset name should be UTF-16BE"); + assertEqualString("UTF-16BE", + archive_string_conversion_charset_name(sconv)); + + assertA(NULL != (sconv = + archive_string_conversion_to_charset(a, "utf16be", 1))); + failure("Charset name should be UTF-16BE"); + assertEqualString("UTF-16BE", + archive_string_conversion_charset_name(sconv)); + + assertA(NULL != (sconv = + archive_string_conversion_to_charset(a, "UTF-16LE", 1))); + failure("Charset name should be UTF-16LE"); + assertEqualString("UTF-16LE", + archive_string_conversion_charset_name(sconv)); + + assertA(NULL != (sconv = + archive_string_conversion_to_charset(a, "UTF16LE", 1))); + failure("Charset name should be UTF-16LE"); + assertEqualString("UTF-16LE", + archive_string_conversion_charset_name(sconv)); + + assertA(NULL != (sconv = + archive_string_conversion_to_charset(a, "utf16le", 1))); + failure("Charset name should be UTF-16LE"); + assertEqualString("UTF-16LE", + archive_string_conversion_charset_name(sconv)); + + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + +} + +DEFINE_TEST(test_archive_string_conversion) +{ + static const char reffile[] = "test_archive_string_conversion.txt.Z"; + static const char testdata[] = "testdata.txt"; + struct archive *a; + struct archive_entry *ae; + char buff[512]; + ssize_t size; + FILE *fp; + + /* + * Extract a test pattern file. + */ + extract_reference_file(reffile); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_raw(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, reffile, 512)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assert((fp = fopen(testdata, "w")) != NULL); + while ((size = archive_read_data(a, buff, 512)) > 0) + assertEqualInt(size, fwrite(buff, 1, size, fp)); + assertEqualInt(0, fclose(fp)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + test_archive_string_normalization_nfc(testdata); + test_archive_string_normalization_mac_nfd(testdata); + test_archive_string_canonicalization(); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_string_conversion.txt.Z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_string_conversion.txt.Z.uu new file mode 100644 index 0000000..33c2e03 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_string_conversion.txt.Z.uu @@ -0,0 +1,2605 @@ +$FreeBSD$ +begin 644 test_archive_string_conversion.txt.Z +M'YV0,8K`"+(#!@P:-$#`F`'CAH*`,(84/)APH8P9#P4.4FG&ET +MIG185$70IUY5&-775RS^?NK2S9 +M\6"_>R7#V`RCAI`8"DWC2"TD1^H6"%F,,5P8H9/CG1C +M1$H=!"4,00[1X4'"1>D6B"F5*:-;)*:IY8GZD3E2D$2\F%(1._9%!(TT&$&9 +M043D>)"?5>KI(Z$,;4G$D(/F":@-'R$*IIY3EO;E9T1D6,.75@+:Y:9O`CHF +MJ##1B>9P(W4*@T`3V1#C9T78"8.KJ?95!(VTPK1E$8+FRA"/JR+HZZ0&%<'H +ML$86@:0-2C*YJGPV7&IKI='66FR&U>IJ:Y?9,A1D$6/:H":LIXIK[:IMSJKF +MKG&:6VI?1LAJ`YXP`6L$KI)^9D2ODJIJA+"2;FG$L9+:"ZE!-D@:I!&5WB"M +M049DZ/"Y1G0YL;80CWFQM_">>H.:_L;Y\9QUQ6`0C*29+&^,ZIG,9XPVE+Q0 +MJS#+[..*,DQH\K$XZSSK1U:M:?*R07=JLI-!WV@RM4G+C&703)K,+=0RCTE# +MT$/(7"[6,J>K$D-9VP5#NXZ%?1>?7[8<0Z]IEQP9E0S%3-BQ7\I]U\%>MD38 +MLE]&'8.34.;L-K6!ZQP#EE^:+52KB;MM-7B)NETNY#`H'=!'E-L=0[N9ERQ# +MB@=1'K4,\HKN.9^0+^EYKZF/[N-J&.-U+.R1VY7S1VKRB!>UN7N.I9HMR\`M +M\)Y;K:;=,I1[O.=>ERFX[>TZKS-#N.N]]G_7ESQ#CFOK/H./0,4^P['AU[XV +MWC1H95'4,RRK/DWL5TI#3D+/@"W]1L_0Y?PAL1]N3JJSRPQ.Q3^8F&T&Z;(! +M_0ZHG[7Q1S$I@F#)KO81>C'$:`AIE06%]J0*]F^">)O7!^U"`R318(-FHP&T +M4#C!*2GF0B2TFJ1:1H-RS7""7I.4W?K4*AV6K`:@Z]-(A/!#>4F*B':I`8)J +M4)X+_I!1-VBBT&J`-R:.,`8U0%(4KU@#^5C1@#]LF!3-EIR)U*!H/[08&I,X +MJJ8ET6-NQ&*ZSLA%D36K9#8`'1W!:!=73>0&7.LCC91X16;]<28!C($-EE@V +M/$*QD7WTXI=T)ZX_3A*/FFI;'RVF246.JFYX]!@H^SC'+VU(D2(S9#[#*$@_G3;D-`B3^C]I:"^%-G +M0W!A1/=I'W^><@A*\>10,>V3@#$RVQ`2&-)]QHD&:C(;$4#G+K"5K$[K +MY&,,]M3#8$H9$?`V2]H=Y*5(`JI1C48$^1356C.M +ME%)M.E.)?#6874&KIC2Q*@M*X(- +M0P)9M+9)*'VU2Q'T(P/R4-4(+(6FV>+ET'B5[%ZE5=J^2JN[?V$.J@/C*VR= +MM,'!;(Y:M3TMEF)$S=-RB[>P'9-<"V47(YRJKK!-5U-A&R6?> +M]?XN*.\='G[#*\/Z?FZR\@UO#O>[WG8A2KVDTZ,4J7N7/RX8NH4QR!>GPMVU +M.9C`I%OBEQ@,Q0U#N(KNA;`60URYOYE127(C7<-0#&%-(3+%BS/(#5X,8:]A +M%<+MNG'E9("^&#%)!DMRJT]V#+@1`IEP1I:!8>=$&B`KELEGW7%_Z]7DY-64 +MRE$&\H"'#&0#Z^TB0904Y=1SD7?:I,DT,2/Q*K>]/ZY9>"F",W1/4Q#A<=<_ +M=?;/G',D/!X)[S)_GO.0A#=0X1W,T'-&B?!^+*$\3RAY?X$T=(DPI>3!,'GV +MP?2DE9(\)":O0Y^>-)J2)Z+*I54&`H%N6TW-W5O5^5:JYC.O5`WH(JB'104Q +MTP5SO::IY,C7=?%6JGC]W,JU)L\P;)]]E-T7_4U$?\'&P65F(.UH,RH^UJ+V +MP69`'.(F"$G?B?9?N,VI:$^)VY3K%+67G0.01;M#W.Y7M-MDOW(O!`?ZL9^[ +M%Y*#%.F/F=D.`KN9&>P@**7>)%L(;G)]FH"C27_VMA^]OQ/P?+"6JK[W+54OW5LJ3Y0 +MJ9^;876APHEOU]M\:$[6`D=PY\2OGV6K7>1XQ6)^OG]YVIQCUO8:5XCV^C^ +M(#B_FN\##_S;FXSR.$W2\"=40]5CL?9$>/OD87+X3#E^N7(G@E)J2'#@TYWV +MV1=][HE50[_#$OGZN1KEF._J&E7V(+QR_.@;$W9;S]ZH[!_2U?!??^=OD/W2 +M]W_U9Q\GQ'_PMWU%T'TG1'?)0WF2Y7@UY(!^!WCJ<4+I=WI1UB!F+!#M)V(,R,"1'."N;`H4'LTCA\X2S +M`DQ;.%`V<`-7"(8]>`,H\85,\H5_@88]B")`N"A(J$1K^!\*%!M::`/)9X?E +MH87D,27D`3LY<')U\8=V\H>V\8=A\X>7\8<]88B!^'PP8(@%`1N!P8B/"'Z0 +M6(EQ1XFP`1Z7N(D*H8G^](DG%XFA^(B`^(BD(XH=0AZQH8E`IHJ1^(JF>(@U +M.(NQJ#ZN2"B=*`.Z>(HY@%&1F%"?*`0F\H@H]XN<&'V!Z$[#N(K,^(A"<(A! +M4!XY$(V1.(W-N(RZ:(V/*$_9.!`TH1!!,(K@6![C&#;C"#OG6!#I*(ZGZ$YQ +MMXX#`7[G6!?N!![R>(_NB(ZEF(_]^(ZUF(\!>8H*\A<*`AY"0$5UH2!*<9`* +M,2#%J"`=XI`,PB3^$1L#,I&IF"`$*8L961#^41X9N9`Y4UI8?EY9$L)9SB7=#P!]PB29P*1QW22AWN2%PV29_ +MV99$P!^\DB.+61>)Q9@&LBIW61"2%3:2A2:761>@U2&;J9E_IQ`5@Q+_4AZA +MZ9DO$9H%\2^G&6YC$WF@^1VIZ9ICPYH#$W>HV9JV29NF\9JBN9NSR23_8AL5 +M,R3!^9H#902Q!)I1E)K).391I)G-B9R7@9RQ(9V:Z1^@B0,I4C&DJ9W0*9ID +M>)T]X5S;.2#9.1C(.27I"9W5J9W,V9[HZ5F_F9KR69IC\XN\29^K"9S/>)L1 +M4YVT&02Y*9H"RIN::7#Y.38(^IN:V6_&29_"F9`/43F0XC)RX3(F8C)&(!$: +MFC5"\3,?>J$#\B`?"AD\<>D]:`:,KNBH[\*': +M8:-"41@]BAH\.B!#D:)`$:0#E*,9"0)!*G9(BD!*.J(K^B--ZB=+2B!"\9D\ +MNB<A.!8J*%NJ85DJ87DJ8M&BCXD:9;"HAI^J6! +M(B)I2B*7NJ:\D:;,,5-,ZJETX:DO(JI=^G=D^G>E2J=74ZIXVI6(T95["JNE +M^J*JAF6:J&JD*EFJA=N:A=V:A>6:I#2I:ENJ7S4ZJ46D.ENJE=V:F+ +M@J;1VJ611Z:11ZUPNBARNBAT>D;4VJIP.%.;8JU]2D76:JMN::V$VD762A_B +MZJNZ0:V-FAS46JRF0:U;VGG42JDU8*F+@JG_2JW.6@/0FD=DFD==ZD+"$:@.&"K()ZZOBDK"-:@./&GV& +MJDQ=6HUD6HTMNZ6_V+*4F@/^F@,`B[,MZZR[T:7J5%6AFBFC*K0^FZW3Z+-T +M.HX^VZI!\*K30:;3X;-_*J`^BZM!0*CQ`;7NFBF^&@3`*G!0F[(&![5$5%5; +MBAL^2ZG9X;,`&P1F*D]0"ZT9-U/WU*5T1K=60K?9JF=T2Z<&0K>MJB!V&ZL2 +M2K=_*@3H"IMT2ZB-1K=;>VQT"ZQ"T*B3:[?%ZI)VNZ71:+>4*@3^2HQD^I)T +MZZPJ5Q+2%1(D*A#691&IFUTI(44W(1"]`KLEX2--=!$E<2RW:Z<"@3Y-Y*80 +ML2R_F[<"@33]4RL0P33'6R@0@26.$;L)TBK/ZQ)2@;L042Z(Q+LX.A;;0[QC +M([T<`;RQ$D2(%+L-AC#E"QE\@DB6&BN]PKZ<`3>3`5:)45Z'01F)@5Z9P;RQ +MPC?[ZT2)4606T;Z#QS@A0<"($[ZA&BO<`B5JFAA6$SB=DQCE(L&+EQA>,W[F +MVRX:G!&?\UIG%1"D(ULA?"M\8E2Q>Q&M@L(>_#H\X<&S\\(BC#[\)\++4L.W +MXB2THSHB3"T[G,)8LL,9>BO<(L0>;#P*[,'*D\0BW#Q0!L"W$CU/+",!03TI +M`5C$RZ8(@\49D697+,.+V2KO8[V\XB/O([[C(\;AF\7H`T"\VSZMXL9=["1N +MO!E53"UU7,+V\Q$Y@<;@QY0+'6MHLA4;&M!Y,BQ +M*Z4((\D98:HIHM!#BBU(: +MM,:7C"6GW+[I$\L#?,E3]BO(:VL`QLO\>T*.M1`D$Q`\A#`%4\S&$F;_^Q@! +M4:W(W,P+S$3#[!C$>T97UAB]K$1F-'S7#$7>G!'F*F'#%[N9)V/E+,Y>1+O/ +M+$9?4482MKOB;#'R_,RCLKMV;"P>@\\E7`-S-+SB+#(`'1`&*V%40]"R=-!U +M-4A*PKN&)&,-G1&+=&*I\A71\D=%8]%5A#46K44<[1,$[44-;=$K5A8@75\]($/4P,>@]95/4>Y1\;H]$=OS;ON*6&4L\`X($MWG1$X,$CIQM>Y]- +M\]ESI":QBV]N]A7]]DQO$A"P\4?0)*<).$CE0\9_Z-I@7)*J[.]Y2 +MA-^[Y=Z_PMV_Y=\+P=U6@S--$Q#9H=V`!]MNZ]VS@MYE97B]G''U/7X+3&?J +M+>'OC6<5?M\9,2#C/7[@K2`.SM8!D9`AGB07T?'M\FK7LG+L#;?>)( +MYA0GGL`P,>(-[.$G'L$JGE@5'.2@*[]21+PJ9\"ZTLML:.3X"R[R\B52M,!9 +M*1G[G1&SH>2)XN/@XB-2'N0;I^7V72]8KK\M'CD!D5!:ON!8[B1J`MX1U2IO +MCN7WA>/@HE]VCG*-DN>_3,8C-"212VGOMJ2M61H +M`<7:E\U4\AAXN`1>E;5D]BSSKNK)NFO3NI%T'[$ +M/L;&SB]A0<;V)V&!8^Q-;>=U]=7@O5=;+>R2=.O$FX"6!.X9$=Y7/>L+G%CC +MGNSI_DFWONVB].[E7DJW;NRI5.\9T734'NV\^X$-D5[.GN^#-"[YGDL$'Q!8 +MARIVOG4-X3S]3DQ@(OTQ!SC`3#^J@Y6\-5Q1V"EI1U_%3@1B@Q7,B +MOS;X"UJ_=O*>\1"@-6TGCT:;4QH,]UW6[/(_DW+?916H.O,HH3\VSQ$]#UKC +MUFW`-O/G9O2*@?/LMO,I'[W\%O3TNYFYIO0R#UH/I_0W/_/T9O5"+Z>@E6]: +M__4N;S(,EUX??[X0%Q0D'V%K[_$I;V$IEUXMOSEO\_:^AKSQ9_^Y/!^D<0J@$GQH==`*BKZ) +ME@$6O(,_3^:@P:$'LL2@'30"E43AZ,$[N&R\EB/\ +M@V;P`?Y!>.,)81_RLT.6T`KF+4Q(;THA":2$^<85.L&AM]-TWI^P'_!&Y%W! +MY33W;F&"ZX61+ZG1/EW3X(;A+G1_OM#BN)O-8=4FX"U$.2-P%RX;)/@86$X6 +MU'O:I!&2'IBC#9%?70-ZCO!)N+R\5O.^((ER+B;/Z0D&H7<.<<#*DWHL@AV. +M0YBG#B^(/-P<.(#OP4.[<`^=B^NKAY\I]K7#G\?ROEX_Q`%%#R"VPZ0'#\4A +M/FQZG]#W.$3GHOCVH41LA\6O'O)#@3@.L]X^7!$3$0=T/8#81$*BV&N()?$< +MIK9AB/(XXFT)>=)/)7Z^B-@/:QM+]`PU$?5]0I"H$E>?*JR)KN_YI4279_P8 +MCO0;BK<%]X5#E;C[S"%1]'TTT24R#,6W_`Q"32Q^QV\C?@^5J/Q^HE3$6<(O +M'")%AA']ON!8M&Z!T!1.Q.R6"-N@5.QN;;$EQL.WR`1%X45T>4VK&\I%K;@6 +MCXXD=(OV\"UNF[\H%P/B5L2+D?`!&L:U.&YD(<\[A_E-$SK%S0&V)*,IM(IO +M,10*PGZX<"QC$N2)>'$-BD+02!E;(0,\B[%0,8Y%"@<.7=SFP'"MD?Z\QG2H +M&:0BB+.%MI$>5C3;^`_K'VS"C1"P'S::J'?!*@9#M&,5`R)NP\56]6+$*N1& +MW(8T5HPO-1V#S;$)?RXOR;W&3K6AT%1W='FR9SW0CJ%7Y8SA7=P<66X83D1^ +M8A1WXV%$CT&Q_JDY]3@6F1*YN84(\?'I/:B$;O!C4XQ\T-#X]<.AE*,J1KX` +MCYC*0.['3:4@Y:#+XSW=+_!L#IP3(4E>HXN0>R?8K$0,J?>&BOFK?]'G0Y8* +M$'G_BB.E68#(,2YQ&X)W;P9.AZ2.1B"W3,@$&2,[)(.LD0YR'=R+,Z@%[@<BQBI<#FFQD-)"LN$..P/"$)P +M;8X862!CI`*(+GD!4UY*@T`@H@M&P)0[0%-ZRE#)*3>E>(DN?"&Z-`A5:2HA +M172)&='%(\1*4PD7H@M]B"X5`E>:2H(07?!#=7D1OW)3PA)2"4LVI0Q8#)_C +M6!K+55DY'D2R=)44RECRAF3)'+I+IW1EF[+\=9=4N1"@9?O+EK)R(3B$[B(1 +MR&6V)!'=Q41\CA)"*DO(IF1EZ_)6DHEV>2$^1^:QE^.R-$Q+?;DI=]KG8"7] +M$E@V!"OQ+Y%E0^"6P.1?.LN&`"W%T+\,E^'I7];*AB`OG"68*S+SF,C,EF`@0 +M,/-:ND.7:3"K#8RPR4.R)?Y$6;*2QR0*\$$QL0!&A-JNLR. +M"28^)I@(F3A@9(*)DKDU72;*%(F;,K5]CGX3-@4F;`B;-I,\A,UK^8?"IL$L +M26&36?*VL`DM@5O8#)?&+VQ.S.,6-IMFNPF;&O.YA4VJ";/&9LB<69\C:R7. +M6VDRVD."H0L)!EBJC$OI,D*ERZ"<,R/!?,J=83E+`^9TE28#5@Z-SCDNET;G +MK)F3LS9,:4&YBR7)F-DFHR2.3LQ)[HT&>I20W7.:GD7'&?OI)P-AG2` +M%^&9*<\&\.R4=V%S8A'+B46`)^A4),`S5]X%U'DXF*>OO`NM4Y\(3]CI3X`G +M[9PIE/.#D8[/$3XE)^D(G\43R(1/9(D7;DUDU#?ALU;BA2!QRZ[8B6`4/V(D +M7$\9`#OY9_BDG6%J?$Y+O,`[J0?I4%,'5'*ZJ0.*/+<'Y=26:R-5KHU5.4$? +M*.C\E@=45JZ-TDEM+">U>:#2D]L\T-8);0XH[`1$!Y1V#I`'>CL1R`,=H%*' +MZHBR3SAT1"EH%3JBH%,A'5$-FD6*J/SL(D54>L:K(ZHZZ=41;9WW +MZHC"3GUU1&EGORJBM].?%=$!2K`HI\$B'0@+CTI.AH5'B^?#PJ/(4V+A4?99 +ML?`H!<58>!1T;BP[JD&_D!V5GR(+CTK/DH5'52?*LJ.MTP9\3$]B.16(':6= +M=LB.WLYY84<':,*@G/X2EM306&(Y8PDJ+9[/B70`DE:Z.9.:+)6@"1.6.$M8 +M`CH=)BS1H!$3ELA/EB5+I>?'0*6J4YJ@TM9I35`I[-0FJ)1VJC54>CO%"2H= +MH"V3=#!-R\DT*>=SLYP.RI4Q3I>E8GX7XVQP*J:F,4X"23I62OA:I[>S*[U3 +MRKF7+"?1V1ZW(Q" +M=6`(M:#ZSX9:,H&,B&BHT[++#%0#"F8&JI0",B>GGQY+9'DLK0)#/9:R\EA" +M5(^:*X^E<,NG!2WGB%0^"&1\Q4E%A4`F`HG3@3HOGDT?@ZEQPDGM5"#C+WF, +M.AVHK+2FKE2B2E*WR%!=$JMR29C4?&K5B&KN.:D6$;\NGY)"H +M'M2!2MB`3%\3J?EPG[I#M%HK<\95!:LM]6B*U(4#9+#14TUP=?6E#E1TJF3* +MQ$F%6W5UK&H9Q[DD?NI`;2M$59&=5%=S9%;$8NV4G<6<'E9>*3PDJY;IF'U& +MI#86)W-4M4Q%[7L[E47`!=&J`%A$A3"ME[)6.4[5FEK]R+'DH[4J4\;6UMHI +M:]6GK%7($K>VUE59JYQEK7*5O[6URLI:-2YK5:TTKJTU5]:J>EFK>&5S;:T= +MLU9]S%I5+JEK:RV9M>JBUBITN5U;Z[2L5=6RA*Q6@(E2@64)(9@E1+;&TA)2 +M6P%):K6EJ^>]\E:'\5Z!J\-T/:'2];S7XTI,2XAR/:8HU;DJ4Y0:79LI2JVN +MT!2E8M=IBE*YJS5%J=\UFZJ0U1HS58AYI9DN5;;VM=3J#O/KSG2IN=5GJA#> +M&C1=*G`EFBYUN!Y-#GM<$2*'5:[=U*4Z5ZGI4J,K#IBN6=/#CDP5@EU!&X?E +MKF#3I7Y7?)-:Q29*@9PHQ;R>S6-)'O*KVF2RM;5M,MG<"C>9+&^=FTP6N-I- +M)CM<\R:3/:Y\D\DJU[_)9)VKX&2RT;5PHI3JBCA1"G:U6466N^HL)OM=>]:Q +M5"=W%LEFMSN+7KO;G<697JFV*JT[FUN;5FI]6G?6MPJH_$JU[NQPO5J']KC& +MAT.K7+W6H76N`N?01E>#I->,J':[A9M4>5PF1:I5K:TBUSK5R +MK=KHBKE6;77=7*L6NWJN5,M=7]*J_:ZEZUBR(6V+9&6/MD6O54[;`MHLIVUO +M*WO4MJER?O#6C9-:"TI^+2CM=K@FE'9[7-]"NU6N$T7;.M>ZI&VC*T9IM]75 +MHVA;[#J4VBUW'2GM]KONI=1*ZE3$#3$O#^W=6":O;%I=QXH7+C'5Z[ +MD'AE!"_*+H\79ZJ\QOLI7U[C396@955FWL7K*D$+K`0MLA+T+MY:2?06;ZX$ +M+?42M/!*U;MX.R9H^9A4[_&.3*S7>"\J:$&7MW?Q3LNP=WC-'B\R&;T76,8+ +M@ADO,F7Q[;V=,EY4WLCP>S'O\OR]SC)>=%[H^7M#;['\O:3W;_3>TSMX>N_J +M/1R]U_5JSWA1+LEO[RV9DJ_WXMZ`T'MW[^8XO.+S7D#.>R%\SR1/J_<6\42CQ1B'XVWEY#/P-O:KC_I)>P7%_3V]G@;^K5\G`7]J^.+TB]`2O7OLA@EUO"=T7Y1>%[@OTNT)/ +M,.YUH2=X]\907C1#@]/A_:C_@OB:*BHL>2D(%:Z\&80*8]X.0H6C;ZU*O#N4 +M"H=>'_HO2&\0_1>GEXA2X=4[K*BPZTT?5[C\)BLJC'Z9%17&O2?D"N_>/G%X +MC>C`F+_5BALUH&4R\:71@E%\VJ@91L>WU9ZC8`[]!15PM,:'CM,6'U[5B0N)+ +M4S&AY#4DO$B08D(87$@QH>9%I)BP\R[28!QZ'6DP)KV1%!.>7DJ*"5?O)0W& +MKE>3YN+RZTF#,?H-I<$8]Y+28+Q[3RDO\I?(:?XF5>IT>)?3.9:\L_0<5UY; +M:IW.L>:EK^>X\SI,Y!1Z(R9R(KW$-#TE7@"+G%;O@$5.KM?`(J?RFV"1$_IE +ML,@)]SY8Y+1[LREY2KPQT[D(7PR+#C&RY.VPO.C#.A<8[#.=B^8ML?X0(W_> +MHXF1.W'2="ZWTKFC1CS=\_^I\/K9R.& +MY!5OO&C01@P8;&@#L^:-6H&Y\S;:B!%Z(6U@)KV3-C"?7DL;F%=OI@W,KI?3 +M!N;R^VDC!OH5M1$#]Y;:P+Q[42TO4K458_[2F=-,?/',:9:\(.XT5UX2=YHQ +M+XH[S=$7<25>7WN:0V^PK1BDE]B>YM-[;$_SZE6V%V<>E>2=O:5&\KU_EOM7'X%[H9"OP57.^->A*N==^_"Y44- +MU[C,7YB"H(DO34'0DA>G(.C*6^D0-.;-=`CZ0;"(]K"A2VNWW`&_(F;\BM%Z +M;SPTMP'1_,9$$X1?@1\:@T1H#%KANUV(QD`B&H-VD-$>NO$T!C^!HQD"-?/1 +MJ*%'EX;%X*-9@I`V5SY:+AQI$IU%0,"17M&HXDB_:._@I!_1C"X--;HTW&@K +M[:$-EH_FT5PZ;N2%N!&DPS050M&+I$K_S;CA$>*&71'2E21NK`8AO=/B!IA> +MTP,33=_I%MT0"$1'L`YTFD@W!$#=C3ST4^L(2MI,DR$4/3&^&Y]V)AUA3BMJ +M**U,U/2CGM+61$U?:;7&J&-TH?YN@KI6:6H/[;*^&Q'Y;E-Z9GVW+&VS1O5W +MXPVOVD,O'(:`H(1T@Z/56QI/9QQ:?:>O-)Y)065:5PMJ\R2D=7,*2M2ZFD13 +MG&(-I2].L9[2+LE5)X@L[;FD-1M*0;W:0U-K*]TB.37\=I= +MGU:\DZ[]-91>+OG:74]I[2.MX1**9M@)>VP(Z@(EI"4>0]@LTGH&,030DK$' +M=KS(V%#Z7F3L+&U<,C:L'AO,P=>\")5=6J\'B,X>OL9/=X^67?Y\#5_P-0T" +M9]/L?7T^:':;WJ`T>[2N#?K@:T[KVIC1:V-%)VV:/11\S:E>&R\::M-L$.%K +M1(2OJ=%KPT3X&ECM0%HVDQIY=&'DK6S%8"5&WIA6#`%BY,GL537RB+1BN-DV +M]&6+PY''LW?HR/O9[G+D"6U>-?*,-A$=>4I[6(V\IJT8GO;\D-M98^11;<5@ +MM14#U@[$(X]K$^*IH*.Q2-C&(F/[6E'NL^U$*;?,]E:4VVW#(Z?W44IM]`&HY3;:,G@I=6))?;CQCOLJU(SO;#,MXR6V(9;[==L8QWZ<98QIMG+U+C_;,=J?$6 +MVB++>!OMDF6\E?8E-=Z$6QL;[ZCM28WWX@ZEQAMKDU+CS;5/Z52HTZJT9;/2 +M^\V\E]/]3MNP1&:[U_OMMF>,_B[=]/5^\VPQ=+]_=GBZWT*;9=UOHWU,[[?2 +M5J;WFW`WT_L=M:'I_5[K^Y=LN<"NX)A5]N]D;%H7+ +M[)V)PMUVM4'AI3MHHG">3311^,]>L2A<:+M8%&ZTNRD*5]I2$X43[AO;LG,L +M"D_V*XX1KKC;AIM7O'3/S2O.L^WF%?_9>?.* +M"VV^><6-]IH>/$I;<%YQP@VSKGC45M6#9W'#V2N.M776%>?:/8LFG`Q!'K:K +M"XBN+J4U61[RRI'(9X8@[^+Z5)#?;'NYR#7TY]C7E[R1M^E_V6G +M7)_@/7%Y*P>?N!R6LU^:\,'(>2$?8>2\;#?40ZX^R7DPQUWDG)@K2W)^ +MS``@YZ'\`9-S4BZ!R?DIK\#D7)7[3W+>RL,4.8?E +MJ":1\R)VGK+!S"%74U5AE[NIJN#+5W!5".8.M"H0\^^1R--85;#D-K@JB.B+ +ML,EW<%7PY!^T*H1R$5H52#D1K@JG'-I4!54.B*I"*U^A50&6N]"J0,MC*$WX +MVL>RD$NIHZ[.3=513]LE]9"S[9$JU2=Y!SGJEOP,'_65SBZ/ND.@"3HZ"A7R +M:@76U?F/CD)0'9N!=4C.S<#Z)!]78-V2(^DHM-(S#UC_ZE'(D\/N*!3*9W<4 +M(N6V.PJ=\MP=A50Y[XY"K?QW1R%8+KRC$"TOWCR&0T?V1*Z\>8PZYX,TX7GS +MF&`NO8WJ(:_>/.:88V\>@\FW-X_9Y-Z;QWCR\,UC0CGYYC&D_'SSF%.NOGF, +M*F_?/*:5PV\>`\OG-X^AY?9[24AV@`D_=KDKA1^^_#G!CV`^P)<$,3?@\..8 +M)_`E@,Z0[-[IL>QRFOE8?'D,SQG!G(;G#&)^PW/&,=?A;O60]_",[PY$,\ +M9X1R(YXS2'D2SQFGG(D_%E6>-1.Y3WXL5CMGP'(KGC-H.9&E":D-Q!?RU@;B +MU3D6CZR)?(MW%DB.VT#\).=MAWR,=Q9,;L8[RR9/XYW%D[/QSA+*UW1G(>5R +MO+.<\CK>652YJNXLK7R/=Q98[L<["RT/Y$I&LK\'FI#=J+PZ[VY4'JJ+-RH/ +MR?,BE9_D3XO*6_)%2^57^M4ZY)"6RGOR24OE0[FEI?*D/--2^5/.::F\*D=; +M5+Z5KRTJ#\M++96GY:B6)NQJ.2/H=_FK%?2^7,\(^F!N(`0],1=<@OZ82RA! +MC\E]K:#?Y.%&T'MR8BOH0_FQ%?2DO'()^E..N02]*M]<@KZ53UM!#\M?DJ"G +MY:6+)EQK_EG(98^L5^?;FG]"]2PGZR$Y>Y3UD_Q;\T]+[FYE_4H?U_P3KS<4 +M64^T^6Z@^KY,')*]TXWZ29[IQ;\D]Y+A?Z?\Z>>#UIG+(3^ZX#^4J=]R3 +M\I8[[D\YS!WWJGSFCOM6;G/'/2S/N8D5\6KY9$GG3H0E/!^GOB'IMKNV_#7Z8EM^6+VQ#?\MGPIA +MF\(@?O#2O?8^7C#]?C_S=:_`O_2Z%^%OGMUK7QMOT[_XG3D*7_U$^XJO_AD] +M%2C_-:\GJS_S.[[NE;BG@N<'YU,A](_SJ4#ZW^_V*.>"W/"C'_7P?[/!>OC7T)D]_(MH^!'^O_IC"?_!O[.$?^*O9,)_BQ;TX3_S\\_P +MW_RMS/6WVA9?^*>U(7WA7\I&]R%^&%WW@@"6;=Y +M?0^DW^0V/G!H9Z#A1]:-#PS@CS8^/(!JW?C0Q8T/@=_H-CX0?E7(]H"DC0_K +MGUTW/KA_[(H>&/R%07H@\5=&Z('WGVF`^.5NX\,6R+N-#Y[?[S8^A'["V_A` +M^A5O[0\:B+!L#\I;^\,`8G;MSP-H2'""<^!$PPF6?Q<-)XC^,4*_M3^AW_S6_I!^]EO[ +M@`82=^T#WG?M0$`!F7XU`!HVN!3!F"(QVVD?B1>=&3X87'< +MQ@.XQ7$;]C#&<1NZGQF';B!^:1RWX?BQ<2L24$C\?5,ZX?U7 +MJG$;F=\O`A0V?S8+4`@`@D4ZX0"X&P"%!J`ZL3U,>?8#WN=.&'Y8GOWP`&YY +M]L,?H&XO?FV0^4GYQG/V"!=1XN +M9!OJ# +MY[?JZ0^AGZMW`:6&!N"U=G*D?K;>R<$`;FLGQP/(ZYT<<^"O=W*4?]\:$63X +M%7LGQ_HWKIT<[M^R=W($?^=:';0<4G[3WLF!!5I[)\<6F.V=')X?M\<-;0_? +MWLE!^HE[`P0::'-L#^_:`,$`JGL]A^$WK_T<\F'@MW&QAX0?4<(>ZGY+!WNX +M^"DC[*'CY^\-$)%?P#=`4'X$WP"!!1Y\`\06J/`-$)Y?PS=`A'X0'WM(^O5< +MVT/%AT"D?FU%AL@`NAH9X@,8?V2(/1) +M':D?:;$],'U2Q][W]#V)?I_4)W4$?E7?DTCX87U/HNZW]3V)BY_7]R0Z?F'? +MDQCYD7U2!^5W]CV)6*#:]R1N@6W?D^CYP7U/8N@W]TD=I%^=I`!<+3L-GT@7 +MX`8G0^\T&MP-5@*@.*HT3DJ*(@&D'`[T`:`(IR"*A&*B:&D!BE8*I*@H2HKX +M`:"(IUB*M,)=P&D!BGL*I[@HHBV`8H4B*DJ*(@*@**B#5BCIYBIC@;<(V3HZ3H-AXI&B/E>#C(C0I0Z1@SXHT?(^=X..R+GPJG:#KN +MC/P$W!@Z8D]`HZFB.A*-UB(%L3L*!0YC!O$[&@BX00##IXCNW)`?HH;Q_6H2"0$GJ+<6$8LD/:B(KA`LH^@X]T` +M0.3JF%`\CW2D +MS8@;6#5K)`CH%DCY)&;HZ-I)XQ2&:0B@09$\Z3<^+>&D_+AHI92[XIF74CJ,68O&6$KF-S(E +M&HD;@"TU)1MY4R:4B@2*HDU^')3D%U)'WI3.Y+3H4^J1#4Y.>3B$E->D4"E( +M8A1K8[EX5/J-=PNGZ%.*D'B&4OEJX08@CE;I,)(X6B7DB.)HE15Z3E:(UJEV^BYY)7PHMP( +MNFB5]J)V)%>^)+@!&Z)5^HVRAU(I/U8YCN6NF.4XE@XC>Z0Q1JH%,:)9UER)A8]I.*A&=I,EJ+<8YF&4&BE@5E:>E'`B.JY>N(6@:5IB7M +M2"#%EB+DGX-;2I9-I6DI20XE427-Z%M"CC`%;HD\TA2X9=6(4^"66F.E@UN6 +MDID.;LDM>DBX9<<8(N&6GB._AUNZC2<2;BDW6A^XI;T8Z^"6^^)D@EOZC0Y; +M;"D_YERAI3%I+0([ZJ7#R"IHC!UC6T%?;I:NQGWY6<8?^N5/:7_TEPQDDP1@ +MRHW9#H!I+^X5`.:^*","F'ZCN--?BI#FSH.Y*ZH[#Z9\&52^*/_D2%%4W@T8 +MYD`)]#V852.2^&!JC4W'@UE*DA8/)K>(6CR8'>-J\6!ZCJ[%@^DVQA8/IMS8 +M)SV8]J+$\V#NBS/(@^DW8CS]I?R(*`69NV+%4$]BF(PC;K"AU),PYH:I2!0I +MC**U2"EIC%#FI+B7-)559J:X4@27TV*5>3*N%*68*DBM%.[EF&I(KQ1WY9MZ**P4?.6<6BBM%/CEG_HHK!6DI9F)/P^)*@4A" +MF9KD2M%:_IE"P;*X4O"4B&;TN%($E80F#[E2.)F-9J.X4G"2=P.A*2ZN%%@F +MO*AE1HN<(J'Y93885&9@26;Z**$FO)@JU@EJ9J/I*M8);F:C.2O6"7(FHCDX +MU@EVIJV)9PY+I>;AR&>:&!KCJ(E(UBA19G90,'**Q.:D6"T*LN6X&F@'8N8D]'8M[0JZY;BJ:1N.XF36&FW[FNBEIRG_RYEP9;AZ: +MZ^:F&?P$G.>BEK)MMHWAIK1I:I:;UJ8FI6J&FTWENOEJ4@\(YZS)I@2>FR2Y5G5HF*U-U +M?IFP3-5);6Z/7.>JZ3URG:]F^,AUSIKD(]9Y:YZ/>B>>J3[JG7QF^\@IKIKP +MX^!I4VHK]>2.XG*2F?BCX=DY,IZQIN+Y*2X*M:;D26T*D([G4LEXZIEVB*3X +M:BJ0F>?.N"@@DHHGG3E!9IY;Y:+`:):>@6=067H&FAZDQEAZTINPF.P)+RJ: +M;Y#M&4J2F2PDZBEI*BRHIZ5)0Z*>F^8-B7IJF3HDZOEE^I"H)[491**>JR81 +MB7J^FD"84J7LVC+QG4$E]4IIX@LK917**Y>?BF1V` +MD>BG:!E]<)EW0_HY>9J1[>=JF1VHD?6GYGE_MIKRYZN9U&B,\N>L"4P`H$?G +M_9EKII^IYZ)&@.Z3]Z>?B8`&FL[$`@HUWI^')@*J:%H3]20"^BQ&'^(GO"AI +M8I+YI]@8?42<".BF&==(H`GG*!F"?IGD$`I*;:Z2(>BJZ4J&H*]F+!F"SIJT +M9/YY:]Z2.BB>J4OJH'QF+\DIXJ"())52;#85AZ81JFPBDT.H^[E,-J'>))GI +MDVF,2N@+&G$JH3)H4ZF$OIK<)!0*9X*37BB=24Z&H7AF;4.%PHM\)FYSA@*: +M9&8\&8;2F_3D&IIU9@=%D1SJ:!XW]:01ZC52&D5H*MF&)J'PXJ;ILMBA6B9# +M&89^F0]E&$IM2I1AZ*I948:AKR9&62[JH;,F1^F%WIH?Y26*9XJ4ERB?65): +MB@!3=H!2@J(OXZ0EBMJ9K$0UF2GHF:GHXRF*DI:MZ&DIBCJ0L2BIF"FTEK7H +MJCFV+(RU:"1*2=:BE:B3&8O2F4DE*8IN9@K7Y##*9\XMQB@;FAU4E=_B,$IO +M9I7-Z!RJ?:B9P^@&"E96HWOH6,F-6IIF)3>Z:::5T>C+F'"VE>4HP_F,TJ+F +M*+595W*CJR9>R8N:HZ\F7\F-SII_Y3PJ./Z)VH>U&8LBCL]H,OHRCIR*)2B* +M9S:6!NGA"5DFI#KE78*-CHI:IF7)D,JB=XF.9XF97RF>8E*`J6"J,ZHU#JC^J,16DRJC-JF?.E +M6'ISVI=N*4::7\:E^F?.A8WJC*_F?TF7BIX")EU*9Q:8?BF>B6#ZI7SF@NF7 +M!IH.IE]*;T:8?JFB26'ZI1MH8\&+VHV2Y@,RF?JAV<&'Z9=NFB*F7ZIEEIA^ +MZ9>)8OJEU.:*Z9>NFBZF7_IJQIA^Z:Q)8]*EM^:-"9OBF3HF;,IG]IB@:*`) +M9.:FA^>0R9LVI$8F+SH[?J:_Z.PHF@JCLV-IZH_.CJAI,CH[NHH"`?P9P(VD +MJ@LQ"4@4H`*!F7F=+IVRBW7*//Z*`H&;N9W^DP*!1^Z)`@$K +MRCP^B\6+>OI6LJ?_E'"*F0H$N"CS*"X*!"PI\Y@I:@3RJ5!P,@H$R.G#*1`L +MIQ.GV_*]V*?8$W0*:D:CS..L&"NF(T#JO@2H26:L()ZBI\L3 +M+[I!FJ*Q`BHZHNZGO"8H.J+^I\"FBCI4Q@JTZ(C*,L8*N.B(FBHR,-;IB.J@ +M_J(CJH0Z,8JHV&G&Z*)RI]HFD,J`W@K2Z8P!+PZ+MP*%&D*BI^;FD#J'W@K8 +M:`@)GR941FKU>"M8I"%DHW@KF*B!*'N:;T:C(>1_JC1*J>SBK1"C&JCU7Y9Z +M-Q(Q.>H4*:;RJ/"BA&IE9*D6ZIB"IQ:*44RZ,O`(M +M:DG^B;P"+FI)\JD_)Z4J2?(*OZ@ER:06G9NJ#`FH^J.6Y*#*R#"J:R5["G6^ +MC!/#?.JV4)VJJI=Z=<:JX:*NBHU:DO^IUTFL"JBZJD5J2J>J.>G:HJ +M=*IVJJH2:MM)J5JH<.>RJJ'.G=XJ>&IW\D.$HJX*-BZ*U"*)RG>2JPSCI&AK +M?(SH*D3*G@J>[&JZ.J`6GO7JJ#BC4C.]4[RZ.AH+Y**_*D@:"^FBP&I(&@ON +MHL%Z*QH+\Z+"RJ<:D"K#M+@N@J>@9[ZZI,ZK`:/"BIZ>GA8KU3BO7HT**WS: +M>2B/"BL/J<^0K!+K?5I[1JP'X['EMN2>+"O#>"[6%5&EPCJ@`I\=JU`PHPZ? +M.>N;:GSVK-!I\MFS2JC,9\YJH3Z?1BN?*GT:K>!I]5FO-JT9J^%8;*(T*.O= +M@):RI]YGS%HS:I-U!<2(KNJ,-^NY*K62BG4%V?BU_JOLY]/J>;*G8Z36JC-* +MJ/2GVDIN!C55*\S(GJV#*!]Z[S)MC:L>NN@JH`&KOOF +MW]HOGJV^JK(0M5JM]ZE7D[="KL7JWPJRZJW_:38TN=JMS.K?*K92KCHKVVJV +MZJTWZ@F*N"*6BDW-JK=*J"THXFJAPJ!R*\+(GLZ@L6N':H/6JTQJ#HJ[VI2* +M#>%:/^J4B@V^B*X.I[/KXDH]?HJ*S>.J2"2GLZO4.+S^JTSH[CJP/J'2Z\$Z +MA6JMS".I.DUBK^BF8@.O4H^K:A=:O1*/"0BV^+P*KF[+&#J^#JIF*/>Z>Z:O +M!2OX:K*ZH>.KEQJ'NJ]"P7Y:A^*O,RL>NKDR"^KH6:+TZHGJIF:@'JZAR +MHB*L*QK>Q*]7I"P:WB2L4J3]&=[XK@_DO^I2:JTZ*GL:4]*PU"E-B[6_WJJLJ<=Z2;KDCJR +M;6P@2[Z6I)#L!`HN.*^=)"A[N2:RT2.XX+5&DB;K;2G*BHW@`B";2.:OH"PA +MN\O.K#WI+3N@`J6I;+PH67B+Z*HE>:,:I<4L=)J4%K,2*E.:REJH3^DTRZ=* +MI=,L>%J5UJOP*5;*S?*N6^DW"[QZI>(LUQJ6EK/(:WJIM:J3,RI[^;^JD\NL +M+ZM.0J=M*3HKH<*EY>S".I?FLWPJ?[G.HJ'LJ5Z:SS*I?6D^BYX"IOGLH#J8 +MYK/PJ6&:SYJLB6D^ZZ4RIOGL?OJ8YK/_J63ZSV)/`ZIENM&&KFZ+9IK/WJB= +M:3X+G8*F^:R$.IJ6LQ:J:*F/BWRNIL&M3.J;QK4WJC!J=9Z5)ZTL^S=,%6RI\;%`'M5DJI3IE+;O=9) +M4BU`*T\$BE:M,PKR9+7H:\D#ULZAD]?_>E4^BY:76>N![HF9UU@K-GI>;JVX +M"'JYM9DBT>/6GHRHEUO+,JI>;FVJ^'JYM:XBU:/68I%L+=XQU@Z.M]=A6RB& +M/8?MKQ@O(+*E)5M+:FJMM66C6'P-L+6E7&MA_*^U95T;&7"V0^7>@]DVLM+7 +M:!O)2K;"Z[186P:V+6J]6EO.BO&"\@JR%*#Q`BM[-_B6BZW"2-EJM>27:?M/ +M2CZ^K289+^BRON6R&"_XLKXE6NMMNK9KK3PA;C*WVR);&Z5"M[RL +MIG1[RM@_GO0##Z92M__BO2#;FI:(;9NZ +MV[J7SNTKZUK^J-MA+K::*KK:83JVGNJ& +M^]N>:/]KAWDL[@NV[7Z[GLH3J:J)&STB81=N<[N$U;C1+8PKX(:I,&Z!F]W* +M$U"GB*N.9F$X+D@[FA2Y=^._,.&ZN&LLD+O==IBP;=AIXB*VT>J4N]A2JU.N +M8WNMUJMUK;;*Y=J4_T*+BVA.BO^"?3OF=KGZ[9B+U^:=7Z[]^2_HLE6F7_MW +MMKFRI3Q!KZ*K529LBZ_BN;0MOZJU$IJ+;>-)YTJ2DM@`2V@.BY68H:O$8D'_ +M*Z%IW$*L@RY:6['RN;[JP"#;$IJ6+<=*Z5:WIUBC^^.J8HIN=VOG?JYSYEZ[ +ML@ZZ?BW,.N@&MKWGH`O;XJR;+F++L\:ZB^W/&NLZMD(KNHK7%JVZ+IB+M/:Z +M.B4FE-K># +MFY@I%IQL[>$*[YZ+_UBY*^H*9/_KNKG72J[L;H**D/F[^F*^2^W6J?GN +MM4ML(K;B!,(+D%)D$J]CJX+6JWMMZXKQ@KFP*[HJ<\JUM*O'*UJ.9`.LS(G7 +MZJXBKYO+@VZ\IZT\\8.RO'4N3%;RCJ0RV2[\ZO7OM_4KT^K7[*]$;V/JO7"_#R_3*MBTG8GO`IKWT+5JF].*W +M:]D`2_9>NY(GU:O+2IY7KR\K>=:U&NRT*'GBM1TLNFIYLK4AK.$;X9*PBJ\@ +M.9C9O33O*%JOEIY_8L0PWI:>B^T,._GRMC?LYNO5ZK">[P0:,8BYI:=Q&\2& +MOC,N$:NUEIX\I&<&^>:XH=GKR^G"+?]KZ5G73K&-;^=:,42]=T/IN==FL;EO +MDMM5KKYRJCP!Q@:_L.T8F_LBMF;L\KO8IK&"K^#HV**CZ&I@"\=6OV#N'(O] +M!KMV;+TJ?]Z^::[\B=?RL=XO:3M8:JWRIU]K6):_CF]!ROX:DMS9`(N`5KZ/ +M[/;[PXIG\B]O*Y&^O\3CAC+OBA!A;2>+_KZX&\JPJTAHH&QM2#H`5[JHK/W[ +MUJ*D"S"G"UM&P/PN3$H!X[6V+/^[U]ZD_*]?JY-2P(%M,,O_PK;$K/V+V`ZE +M[^_$R\R:P([M,XNNDL#_KQ)JV5:S+W`U:5P8P`G#R+O-UL"1JG$AVU:A;&TX +MRP/KG\:%F;N%!L%IKA)*`E^[>FCEZ\YJK7KH8@M?0L&\;3T[!/>_^.P5O.+N +MLU>P<>O/UJMZ*%HKT%[!K6]!>P5;M@CM%2S7+K17<%WKT%[!>&U$>P7OM13M +M%>S77K17<&"KT8+!:F^,Q`3OHVRM2#L$3[PE[2#LV**TBV(H6B?QOJH4F.O2 +M)L*EJ%P;TT+"(R]-2PGWP#?M)5RIUDDP;"[*UO:TFO`Z62>5LL#H)ZR\#J.5 +MKU&K"6^5=9)]JXQ^POKM,(KH1K6;JS3Z"0.RPZAQB]76PN9HS'!/<+7LZC#J +M$/S"C/`P2A_\PLALHCB,7@B_\)([C.('O_`E.XP2$;_PO#N,9@V_<"=LCHH( +MO[`!/(R:"+\P*6R.,@>_\"D\D-(%OW"+^X]:";^P*SR0!@B_<"S,#@,*=6M+ +M.FG]PKCPJ,@,0PSUL+QZ3SRHB?"H2`T3!OWPF/D/)\-W@3W,#0L0!;'-^`]+ +MPZ,B.9Q$-,0?B@+P#W?"Z^(\G*(&PQ.K16P7D,+K(D;P#Y_"-:E'?&QRQ.OI +M/^P*KXN^,$%!$8<;_S"IVY(26_]P/ARF_L.$[$P,#:\7+_%`_-P&Q*;F/3'= +M`L7UHD>LPM3"ZR(X7#E`Q`RO4&P-+XH#HU",$=N/1K$W#!7#PY4#*8P5`YPQ +MZQ91.0K%ZO#5*A2[PFNI41P+@ZU&L4RL,V+#ID8]K#,NQ&=C5XR7>L0(;B+\ +MMM+%Q;#=B`Y;!&[Q/7E/A)S!L-V(%3^J@?'%^A=;PW8C7_`7=\)VXX/P%WO# +M=F-+7.+:Q6OM7WP*VXW'L,+1%Q>K?S%9G-W^Q6_&P2AF[EZVQ,UPR,HZML30L$GL)]?#LF!E7 +MN8GP[+@/8[G%<RZKE,4(\G7JLY;$S_)YZQ/MC5\P\ +M#L.60G#LAY;'G;!^2A][P_XI?QI'P/"Y?%W3!67QSEQAHH5M[J)L&(\*Q3#'ZQ'/.LJPR>JB.P,KZ@BLC0\ +MH@[$O"Z);!#/"IVPC2HB>\,U[#UQ[+K(GJ)$C'T&PR'D7KQ]\LA^\:S@"JN0 +M(G(L;,2*R#+QDRHBX\(AI&.LZ-3#5JI''.YVR)5QGE8+=ZE2LGNLI'+&?1J4 +M_!D?3%YR=WM/`*Y`\H$\)L?("G)#0",WR(1D5QQ"2L01J)M,(6=,8;+L.B8/ +MR=*OE!P+.\D@:##LQX[)N'`>N0^;KGZR<@PF0+:]ZFEY3VB\B7`>R19WO,HP +MINH1A[R1\MJZ*$O#>:1$C/)6RHKDHMP)?[*+LC=L26+%0FBAS(8NRJ>P)>DA +MX[Q=<:TZ*;O"EF1+3+TVRE7RT$LK1[>+,W?*HF!F_O?;-P6AI#VR.#DLDXWQ\MHR+'^, +M];)2+(G6RQ)Q!QLOURTLBK?X+\_#).R_C!5_HN6RS/H;2[[_LH>\4KH,*2M\ +M/!#@B_]R2]SY_LOX,>C[+V?&/6S";"[NPZ?OO[P3J[X>\[HX$".Q$'/+RA87 +MHR5SFDS[ILPRJU(\Q?[+$C$T&B]3RUGLS3P/#[\M\Y]*HZ2+W3)6/,8&S6@D +MC3(O$LUL)(U",8^M.S$ZBC0KR@D"N#RVLL5S[--L+R<(Z?+8*C-#C%9SS0PO +MZZU[\?GK,=N-.S.^K+=BQ>[OTVP@R"C8HMKL(3^R:K.3/,F.S;FJC`(TZZWX +ML29+-^/*$<'1K+?NPZ'LWBP4[,0*L.",N<@H4C/HNKG(*%*CVKP03\"&LU)L +M`1O.$G$&_#13RQSPY3P/?\"",V^,=T25W?)O3,R&SD4SWB$P'Z_[,#-+.C^> +M]\0SNSI#S=+LZXRVM,Y^\^^J>;;.2[/M7&JUSMSR\2H1>[.O,\",=S3.X.L\ +M3,X&SUCQ.1L\B\Y?L^TLN+3.]#+XZB1/P1[S?'Q/U+/!,WZ,SP;/F?$^&SSO +MPU]P\+P3"[3!\T!1]\1*NT!'QV/#Z4Q` +M+\0Q[0,M6S;0=S,!+1'?M!:T\*S3=M#S<$_;06/%0&T'_1L/M1VTAVS4=M!. +M_",'.:ACU!PXV3\MA!4\,J@Q`] +M0R_.E5/OU$%SPR8#N=A!@\,F0P9]0T/(%C'GI$3/T%%QZ&1$I["(XVD0$US1 +M7#0\?#1LT95D%5V?]M!_M`W-1F/#N-,; +M'3-ZT0=T(0M%/ZC=XJB-#.,/8G20+3C`T:;LD3T +MCPI)F\EWP0!MRC+11>HKG?">!LLM)4W8XM)M$'MC$UFCKBT)FU/LL[STQJM3A+17+''S,Y6T?*M-KU'XP59 +MLS^Y.^,%0R?#P4U+TM/2],")1!=XMK3 +MHO'1UE`CT7N,/RU0,M$Q+D6]QM+3Y;0\30ZO#>DTA9RU-=1=M`.!4HO14&>W +M#$K+QBXU,SVLQM1)LV)`3#NURO';MD8?E42TE$M3R\N*@3/M5-[.BH$TO=16 +MT5ON3XUJG09>[D\-,"L&Q#-.S3LRU>%T3PG0,M4A]56)3[.Y3C4_O:XZU0#U +MG.M4<]+TJE,-2N.K3O5"[>=ZS%>E*2WH.M5`='W,5E?4_F,/?57BT9CG7%T4 +MGP:0KE,-15>L3O5('0;YTSYE%LVQ_M0IM05I5VO+6$1(K5;;T95M%7WJ=LN9 +MK60=3W>V572K2UDST(KB&EU;XM$\ZV9]VIX&/ZMH?4$_D)XUN$E:(]3@;:>, +M3:;64W5/"5N3QZ7E;+TV[[>V-3_](YO6$@II7563M[X6:>U85\:*!&2]'Q_` +MMK4IG;;RUD!TN,M;$]%Q*V^-1Y^[O#43O>YZS.EM%?WN\M8C-9EL6F?13XT_ +M#=\JTOKN=RU&M\D>LRD=)Z?7S#3!RU[7U!BH/VW@:M,X5;1&J^`?72>!K"K@1U;TZX*-FU]NS;8M[7N"F'STRLO +MA`U0O[P0-B==*D/8H#0PV4-WF`LUJ_Q>.]1_PV_=80+1U"N$340/O1`V'FWT +M0MA,=-+[8;/&@P?H/"U"N54TL=Q@9]'JZXZM2&.].[88[2QWRT`T_4ID,]-B +M[Y%=4Y>]2G8<>1J@O1ZSEYEC)\YOYNP,QZW1<6Z._5M7F5`TN]QEJM9Y')9] +M8`\>[32@FV/'TX2F&+TO?]FG\N&@3\^9_'0(VV3WUH?#33UG1H\S%'V37PX2-.$)A!],??9A[/+*6;#TAWSG,U$A\R(-A1-,L_9(S7* +M'&C3QE4TR]QDI]0O\Z4-?IX&,_.T2$3;S*(V,YTSE]HU-<_<+1>[H+84C>TJ +MRHGF&LWL@MI"];,+:DO3TBZH[4G3N^!FGSL`T3(XS2]B@--UO;IO3<_&P/SE7T_OMM +M)]IZ\[B-1PO`'O.ZR40'SN,V%%TXC]LC-2K[;6?1$'"Z?2%K%-(V;^Q/A-3G +MMATM;#3QKW,]S57%Q0]O',\K-22O/ +M*#\\H-Q,=/J/<4#3Y +MC'*/U.>SQIU%J\].MR+=/CO=8C3\+/A6T?-S]/L5(SAK--^+=?_6?R_6'5(/ +MOEBW'7WX]MSMM.1I=,?3DB<4K4!KW1SD:>!`P]U/M4O;+6.^570%37>+T33M +MW1U)<]!T-S_]0=/=`+4(37=STB4TW0U*H]!T]T*]0M/=IK0+[7?_T'GWV%U1 +MT\(]M.^;=Z?="O*DU'6SQM'%Y[U+&W+^M.(9%2MRI?>%W%V(WI^V/N5/@\.4 +MW.M=-%]R:[3\R0S_2[6W<@PSY=[N\MC$>\O+B=/O;2\;5,(W[!T1"-_D\'_Q +M>P/,L=SRS0[/-3R?7MOQ-TR`@H-:U/+-S6L8BS?V##I$%4?P`HRZ?!;(Z"PMRK=0R.@R;WD/I_J]ZU]`#N,_M3:W3R_=QVRS*P1;S.^=-*Z.U]%/?02NCZ?4Q[ +MS$JH^ZU,8^`&<4V5@._11-4'[A";52)XW'UDE.#,=S?-@/O%3@8*+GWO?Q"X +M86Q1H>#8MYY*@:?$708*[GW7T].B'AI^,[@<.*Y\$2#2.3!G?!%,W'KH^DT8 +MK^!B\D7`6J,20?%%(%3KH=PP2X>"P]X3=0_>%%\$O[81>GIGU# +MN/0M=,+,`)-_`*N6C+4H^9UT)LRUZ.VM&L/AI>CZW5(KPZ6H^PU3X^$=^$S- +MAX_64=TJW8LZX,HJ&UZ*)M\^]1^^<;]69/0P^GQCN8;X5>U2->+F:/7=5"OB +MS_.=18GCX.!J)+Y[^@?CJB=.0SMW6(V)K]]E-2;N?J/5F'C\ +MO5:+XM.6?_!68^*PMUQ-BR??=34=3B'3=:6XG1R%:-+_J/0-6"O#S_=@C8:+ +MRP[X88V,0]."72/N#Q=VTC@#C=A5X]'Q8H>-W\Z.W3:^.T=VWGCRC;.RX>LB +M.LQC(-(S\?-=6C_CC;1G)XB'Q`YXT4J.L\>DW3;>6Y]V]KCW[;3.XP9U:V>/ +MD]^[-3ON4,]V]OCZ746^XZ)Q;F>/Q]_:+C]>WL;C??1,#'L[UP(YM+PDO-DM +MZ>E-70OD7;14M8WSQLY=(RY]>]>O\>P=7J/A8O%U)XB7Q?X!>LV&H\4M.97M +M%0/?[O5+#H+'URBYI6S>K>2J=7HGDA_8[-U//E4O"1&Y8.R`!]@E^:F<,V#D +MB?%1CHXWQD>YG3V3!]?[G5`^BDO82;F?'>#QY$8XAIV55R[^P8;]E;O?'C8< +M;C?&WR*V3;Y70WA6^4L2EI?34WGRS6)GY:?WBTV7/]\RMEFN+7<6-G9"7'WK +MV.OQ5QQ9->+&L0,.9`?F3G9G(46/IW1T9_&$,^;Q=Y*-F`_?3/9D#GM#V6RX +M=FR8R^3=L7]`+F?F+/@""X=_IX8Y7(X>&^8V]'B:B5.PH#E\[.01YG5SE`>; +M]^/^,F).$RL9Z+A_[!\4S+;Y^IUGV^;N-Y_MET?A@'9K_I#OYL0X\PA[']K# +M^>BM,2/FIW>C#9T_WY!V<]YZ3]HDL@-N:;/A`;22(4MOR8OG;AZ1H\C^0:B= +M$*_(#CBI?9YWX*?V>@Z(J]HX\@7]9S3B/6IZ_ICWR.FY,PV>OUKE.3%.))?G +MN_9^7GW#L=PY/2YLN^>8M/!05>_GWG<>6Z#WX\MV?'Z;.]L2^NV]_C[H/#>M +M1Y\GY(LLAKXXZWH;^EKN;4OHL+>X+:$GW^5V?'YZH]L8>D?.;JOHTO>['2D[ +MX/)VL'P/\T_S=Z)\+O-/"SH<[1],SFQX'NE^6\XV>OP=<"?$DO*/'I%SJ@XX +MPFVC)]\,-Y(.E*/`03H+KCH'R_-T\K"8NZI-^F.N*C?I^KFK[!]@LU7Z)PYI +M-.*69/A]O(==,OIIS?13:@_WT,:KB+C3HS[A\@M)$Z-+[05NJL,ZK1 +M+V+JBC*J$3!RZK,SJB$U@NI5^$4+JL/>>S"H+JB#C9PZ\RW2MNJ(^L?8JDO? +M*&VK7GVOM*TZ]NW2MNK;=TS;JGO?-&VK'G[?M*TZ^:W3MNJW=T_;JJ_?0&VK +M[GX/M:UZ_&W4MNI5N`O=JL/>2V;OU*HGWY@W,7,PGMXY-*?>D?/0WCK#R!OC +M&MIZW6@1[QKI.NAZ#R<*RF.C+A;_"O$ZT[RNBQ?M.N=*1_MH];J[C@T??OGZ +MUFHOZP0!^UP\(,`7!;MJ_=WTZYPKP$RK,>Q;*W^>@D#L1OG!#C'*ZX:QNT:Q +ML\<7V\8.'V]L'ONTC?J%[#"QZI>PX\I3@;>(L7/&O@;)#@V//"0[-4RYD>S_ +MNB)!LG/#]QO)#@[_?B<[%3T@%#`]>U1<_(7L733R%[3#PU/!Q3XYKNO^=Z,N +M'#/M9*/3#DU3?Q`[\3H@++=2N[N,RU7M!C$YQ[6/UN!?P'X=7^WI8M8>=YM_ +M8ON!G?ZE[5,U^\>VD\?OW]N^-H-X7SO4>+6/ZM+SNGYP-M'@JR\LZ]7M)7M_ +M6ZX3L'YV`"BW,\,$H-S^LB.X9OOAK`#*[?_Z@]NXX^R`<>.^LQ/&C3LYK`?6 +M[4*[#?:V%^V:JME^KI>XC;IBK!-"[`'T5HBZ3^TQ;NFN').'J[O6#JNZ[M%Q +MAAB[W\Y/XNV^.^.`NKOF+AO3[ALW!'2[2^Q;Y^#^GPN!P[M(O!4-[Z9[E0N\ +M]]9+X/#NMV^YS_LP'`4.[\#_WFM#@A)\\'[J,O`2NZJ+P2/M +MK2X&K[SCK!B\Z];ZP'_4OF`%#RT'@Q6\T*[M,O!%>]J*Q"/MX6ZC[K?' +MK4Y\T0P-0NSJ).)^74?QK+,U2,4ST-G@%E^[G^2#.SR[KNN[6/P%+0YZ\6?[ +M>EW&.^SN]1I/O^/D8?Q5[0ZB\7-[G[S&F^X1;\`N4.KOA/(:[[=?O&N\]:[Q +MKO'9.^RZQB/NM.L:_[+?KFN\S*Z[KO'_^LJ[QN/L+^\:O[.7RFN\YEZ6E_%" +MNXC-R=/OT2LGC[13KXVZ(,^J&Y52O-%;RD_M>?DJG\6+KZZ\HAP=0>Q'Y;^N +MOL;R`SO6B\OO[,XR+J^YTZ^QO,,N]@;S]'O9&\PC[5!V,*^\MQNT/,=.+@?S +M^KMH'LS[[0YL,&^]1[#!?/9.P0;SB/L%&\R_[))H,"^S=[#!_+\>P@;S.#L) +M&\SO[`AS,*^Y2[ZQO-`.:,?S]+OF&\\C[9UOHYZ]@[[ZO!3?,??S2?->"+%C +MU@,"R0S0R_*6]D$_.TL<`_T>;3_(ZMBM0YP8-O03/#1ZT#OL6>Q%3[_SS!<] +MT@[&7O3*^QA[T9ON9NQ%K[^3HQ>]WXZ.7O36.QQ[T6?O<^Q%C[AWOQ?]RY[' +M7O0R._E[T?_K8O-%C[.OOQ?]SN[^7O2:^R)[T`OMC^Q13[_/S4<]TK[_-NJ( +MN]X,U4OQZ/94']`'SE:]DST=0NSV=4;RJ=_877N]G=4/[)#S6"_4*^T4[@2? +M`6?U#CL'S-8O]1!]6@^WB\!LO?).S++UICL*S-;K[\PL6^^W/[-LO?4NS;+U +MV7LUR]8C[M@L6_^R;[-LO8^ +MSMG3[]0S9X^TU[.-^LN.SY;V4OP^B]H']%_P:J_5,^I]]KY>T+KV"SVE'MOC +M[)=Z;+^S.[2TO>8>T;KV#CM%"]S3[Z8ZHCW:H_5SIO+^/P/WIONKCFCK[R4M +M<.^WU^J(MO6.JR/:V?NNCF@C[KXZHOVR!^N(MLQ.K"/:__JQCFCC[,IZI+VN +M-^N(MN8.K??90ONT#M_3[]8Z?(^T9^M\.[&[WI_RQ*X4'ZX/V^`;Q&*'R@[@<\-B![EXX%O*8D?9#N"3PV('I&YMH\-PQX(_ +M5;L='CYY+'9LZM:V2"QV?/7]O>"J(`P$(7YO+79(SPV)'7(_C@^4_@H%O;5/#/P*V&.,;RS^"@Y_B'^<_@H1O;8/#/X*% +MO^1#RVA'B!\5_PCSXI'?1?\(^**6#P_K'1`[-OPCH/B>1-%<=X3YT/2/`.-K +MW)F6@J!_#^X*MYM_XU/?V#_'4I^ +MF?_A3^!P_E7]=TCYAC[3J"!LX(*^BO]W9/DHMV/<@J#Y,OYZ&^G3T'\'F4_G +MY_C=]*9_;#WZ:_[=X'1"PW\'J^M3^KUOFA^ZP]UM_OX! +ML9/=Q[ZG?W9?#7A[LS]:7PVE?G%-X9_A@[ODB>'/[G0WA_^&)_M^\=50Z[.> +M"3[4B>Z?R@B!D1]XM_N%?N<)'R,$P;ZW+^,KJ^\^IR_E]OLT,4+`[.O[#C5" +MT.73W:@^]4YW$_E>+L`OYG>K`#^$W[W3W5`^^$YW8_CC.]Q]Y9OO&C\[C!"L +M^\,^^SXM0OGO^\AOYLOO)G_27'E`[-]O@H^_I_R*\I.@X<>?#'Y>W:BGOR[_ +MP4_S.\1/`HF_\\?=3X*G/_^Z_-D^_?WA._`WOZ(_L@;L#ZC+/^)\X6A +M%$A_PC#Z'YG/&$;_X_Z9HWA\TKQ5'/U/_&>.(O)A\V)Q]#_TWS:,_K?^HT1`#U^ZCP2X)>OG8>,^P#._&`)DCJOQ,#/'L;CL^<) +MY*)]^;P;()&/GW<#%//]\VZ`$+[3E_SO(_4!%/]%Q#Z`Y;]RW`<0_9<1^P"N +M_SIB#`DA7T(,'L>0Z/K!`-ECZ8-"WTS,TL?1J\@9`#]Z%;D:GTBO(O?U*^E5 +MY'A\*+V*'*IOI5>1(_*Y]"IR8KZ87D4.PD?3J\A!^6YZ%3D,GTZ/(\?AZ^EQ +MY#Q^0#V.W)=OJ/<:2_`9];)RVK^D'B*0Q\?40P2B^IYZB$`BGU0/$2CFJ^HA +M`B%\6#U$()2O<";_NXM))!:`>C%#(/>/;&8(_/Y5[.8'XC^[D8EOK?>5B_JY +M];YREC[.62>P;E9#D`+"$BA3";Z[WE?NZZ?7^\KQ^/IZ7SE4'V!O+)<+?`%. +MY<1\AKVO'(0OL?>5@_(Q]KYR&+[''EV.PR?9N\OE`DV!PS[,WGDL%UC^>]HI +M"#Q[D[E?X/K/:G="L`4RYHA\I[W)G)A/M3>9@_"U]BQS"3[8GG5NJ79",`9V +MYDX(,T#P6#Q0Y_<>$_'Q]FQS)K[?GFTNZB?;2_!1]Q*"1+[K7D)0S*?=2PA"^+I["4$H'W@O(8CA&^]9 +MYZY\YKV3H,>HZ/U +M"`3;*MX!D8%,L\F`%!,]% +MQ2(/4<$+6>2A*KA!XHU%'K*"CK'(@S'P3Q9YF`$*RK:"&S'YGX\N\H``%-)A +M!A>`";R$Q$E,,[A'BSQ\_YATHD'QGR!--%C^,Z2)!M%_H++(P_IO5+85]//5 +MZ41B3(3"X)]'+Q +M!P^#W:HCX5007'4DO`J.J]B#3D*P$92P:*9$`!&.K9B#*31@9=."Q"4N$2S\'H>),+2@AFPPHSEB$IRXV(7-0U<4FI!&V +MNMB$=T&<%9MP1\BS8A-F!W]6;$($H="*30@>+%IU"0^#2*M/X51P:?4IO`HZ +MK=B#N,$=&:J02O@C6Q4FS:@(%L+CE:,P0WB\BA1*"8]7E$(KH>[L4O@Q +MT+(()T+?V58P;N4K;!.>NXJ%4\'K6K'P*OCN*A;B!LEDQ4(/(1BO6!@9U'<5 +M"TN$Z+5BH5IPO58L9!&ZUXJ%S$$X7K&01JBY$A0NKZ:#?;)BX8XPCV!6]7[$$/H>XJ8$@E7'D1 +M#%^%+Z^#H9.MBZ`@G*'1T;H(`2.%88!0Q"8QS`Y&KR2&\T):H09M*SCT4ABV +M"8U>'D-^8;RPB745%%]Y#'&#Q#*/H8=0?>4QC`QBO3R&)4)GF<=0+4B_\ABR +M",5>'D/F8-G+8T@CA+)Y#.^"S+S>B<=P1T@N\QAF!T5S'D,$H0/+8P@>C&`I +M#`^#%*RGX53P@O4TO`I*HMB#D<$.%M:02AC"VAJ^"DE87L.%(<(L;/@PE'R1 +M#7>$@#:R8790\T4V1!!VOLB&X$'05]BP3=@QFQM.!4]?:&:D%HU-R019C%FALR!WEF$9JRY87:0'#4W1!"BH^:&X$$X5MCP,#C'&AU.!;M?H\.K8!Z+/5@B)'^Q +M#JF$8K/7X:MP_24[7!BZOVJ'#\-%%NYP1_C(PAUF!^=FN$,$X?X+=P@>U)O5 +M#MN$Z+;CX50P<'8\O`H6SHZ'N$%4UO'00UAO.QY&!B%GQ\,2X>3L>*@6S(`= +M#UF$'+#C(7.0`@>E&;5 +M#@^#U:S[X500FW4_O`INL]B#:D%O%@"12AC.&B"^"LE9!L2%X3DK@?@PG+DQ +M$-F'ND*KVFBM7T$X'*KMSOP9P4*I6MS-G_$>1.5UROP9+D(-(H7P"Y9`G*?Y +M,VR$(D3<8$&KA.@A1&B5$".#"ZT28HG0H55"5`M&M$J(+$**5@F1.7C1*B'2 +M"/=@)<2[X/^LA+@C%&F5$+.#):T2(H(0I55"!`^NM!*(AT&7%A1Q*AC3@B)> +M!6E:[$$6X4TKBT@EU&EQ$5^%/:TOXL(0J"5&?!@.M&Y*VE&L'B5MA:@Q#FT,2(%$)R'1X1'I9'R"#>MQQ]>80.8AWQ>99'""'^ +M$7MK>009X2#1%Y9'0"$>$H=A>83_8$3/SY9'>!,>$IEA>01\$1X1&I9':!@. +M$JEA>82(X21Q<99'D!".$KEA>818X2`1')9'@"/ZELAA>00ZXA\Q*I9'B""2 +MM[IH>80*(GR+C_B@8@]B$@EIOL2BF:O`D&@N2)JY"A2)3"XGFZO`D5A,5)2Y +M"B2)Y"C2)8#V'F*O`DYA,7*JY"D2)Y +M"E2)R<1YFJL`CMAA$HFY"F2)S41"H@`NF`@?"Y980RB.#(BAQ`V=0Q(;Y(*B)'294XIC*H,A*7&\9 +M%&&)V;1](BVQFZ91-"?N[0R%R43>F`\"CLA)%-RQ!ZM,`,58WTD1FN:#J"!F +MF2QBS`(_HIH+I@B$6RE&QY@%Q,0L&^(",&93O*`Q"YB)>2Z:(C1QSH0.8Q90 +M$\UL.T5L8J;IJL8LX"8VFMR)#4*08J-),<8L("?.F1QCS`)T8J.)D0CNZRG" +MQ)@%\$1,%TW1EJAIHBFZ%#]CBP29HJ@)IJ@B).^Q%7.*"K)%`C+1U<16!"HV +MQ18)0T5;4U&QRM53Q"4"">U[;$6G(BC12`C@`R@F"0%\F$0F(8"/D_@D!/`- +M%N&)L[9%@BW1UK9(J"#FVJ(%,L5J%TSQ2[CAVRP2$[E=F\6YXK=KL\A,?#=M +M%O.*ZR:J8EZ-/7AOVBPJ%7]\C,0ZH;4-DH@GM+8!%/>$W+;-HE9QW<1)#!1* +M%==-H,1"(6LQ*!8MF"S&%1F%3SZ8XJ/0V@9+E!0.VVB)E<+GHCD14_ARL6\XK]-N4A-_'@I%U^+G[XVW\;"J1CGVUB`$QM]TL16(9Y/N:A5Y/,I +M%^&(,J?F(CS1Z514U':Q!W5>RL4*HL@-IACNNB\:QKX0_L15'U7Q6%CIXR_. +M%9U.C,1F8AT*RJR"Z6*;2]S(J',O^@S`UG(%%&)]T)H'T!17PCMPR3V +M"Z%]G$2`(;0/E#@PA/8Y%`V&T#X8(WBQ[093+)6Q!\5]1<8,(^6KR&A5M/>] +MTT`66D5V'^*">G5D_"]V#.=]4T9;8NFKR%A!+#TQ$DV&BC>88LJP\29F)":6 +MGC")+T.$GYB1F5AZ`B76#.EN#D6<(=T-E;@SI/B)&9V*I2=88M"P76AZ*RH6 +M#3M^8L8HH[9,7`!'9"4Z#6%^]S!Q@2W1]B9FK""V_!`75T-$(RA1:XAH="AV +M#1&-J$2P(:*1E3@V1#3"$LV&5[^B8MKPZF=.9!M>_?B(;\.KGSM1;GCUHRK6 +M#:]^6$6\X=6/D4@R8P\BH"")?L.K'T`Q<'CUPR1VVFR-:,7#X=4/E*@X5/O! +M%!N';;]CXUP1_W9L9";RWXZ->44`7%$Q4/EJ@[#/T5 +M%7N'H3]S(O`P],=''!Z&_MR)QD/4'TPQ>;CZ&SB"%\-@`T>GHNP/<2$]#/T! +M%*N'H3],(O9P]S=P-#>*QA0(Z4;B8OB0^#=PK"#JH5B)YT/E'TQ1?=C\*RJV +M#Z%_(\>Y8AENY.A(3,/9(8:*;;B1HR6Q^X>XX!]F_SB)_\/L'RA1@)C] +M%Z]A5$>KXC`*E=A#Q,51'8N.XS"J(]+Q'$9U7#H.I,R)2405($R1B=@"1%P\ +M$6^``$4IX@T0DUA%O`%R$K&(.L#!(\Q17S5XG#ENI`:/:4Y8Q/0\(A.G(GQ$7>"4DQ*<9*^#Q2R%@)HL<+&2NA]'@50SX6'>%AK`2D8UD*^;AT%(NQ +M$IR.++E8@NT1)A=+T#VNQ6B/J":0XDS.7A9+Z#H:[&()+4=/8"P!YA@*_`[8 +M[)2/"3%2H/\Q[5BQBR6P'56!\,>W8U/._RAWA,KY'TN/D3'XX_>Q,A9+$#_N +MQV()Y<>;6"P!_?@9BR*L'T5C403W8U`LBN![1(W1'@N*S<`39/Z1^LA0G`:> +M(&>.NS%V6!2!`*DMBR*P'45B482WHSK712AZ-@<^T$B +M'9E7/\BE(W7L!^ET'-L!$FR/FKGO0$W1-H<.`R3X'O6!4LBN(VE."MER/,U) +M(6&.YRG:H^?.7*B:(,%P\D?='""A]!@@DT(2 +M(4&0'$+;'#8,D*"$=#Z."&USX+`9`Q22^MA6/`E6(8=5;DC0A\6<(#=LQE!ZK)'- +M&(J.2L$9`](1/]>)7#I*!6F/64()'?B12RBAPT%R%A%TSS.'@>\Q+/@=*!-* +MZ'QA#H.68UJ0]K@FE-#Q'E>+%3IB)":R`RE;Q$52PQP&;\<0TAX2MXB+'$7Z +M"4ETQ$A4)/51N*BBJT(F"E5T,DCD(H*.-P:&L#V:(9V+DI+-+1'D.%-KI1)*G01A>(/!4^Z>Z1;T?7(!A"[@@J`T.4 +M'FF#[LBB(Y?.'8ETW`V"(9:.8CHPA--1./@=Z"]BZ7"/Q$(L'>^1P%BG`SXJ +M"[%TQ$<%8YWN&0DMQ-+M(:>%V$':H[402Q>(M#`&ZE22`2/$C6 +M(,N%I0&)E4H2;`1'2E=M),E&/4E]F$KR8Q245(XI$Z)*14EWF3(!6Y24E);FM)/%1?+65?$82 +MR[:2>TCUU59R%(GUVDH&(IUE6TFL)/VJ*1D5^QAX)1^$7;2/`;Z(,0E^A++U +M)"N3`:/+9-'L8R`UTDPFS3X&5R//I)/M8P`Q$DW2T3X&/,FI&>V1@F6:)$P2 +M);5FM$=)E&D2*]G!$DUR)4-8MDD9)`G+-@E^1)C9)G&0DB_;)"02T&:;-$-J +MOFR3P,C.EVT2]PCZLDWR'CMFMDG@X^G+-DE\))G9)I^1EC;;Y!Z296:;'$5V +MVFR3@<@IEFT2*PF-$DTV)K-8YDD9),_,/`E^!&/U)'&08ZSWY&;2C"6?_$R2 +MH^J3HTET%'[R-`G'VD_N(>=8^\E19/=K/QF>+$T*"[\#Y"_\)%=2;*:@5$^^ +M)IUGX$?WEX(2![G(4E!"(A]9"DHSY-Q,00F,W'\I*'&/>C,%)>\1W::@!#X& +MSA24Q,?"F8+R&8G*4E#N(>MM"LI1).1,01F(G)PI*+&2&3#\9&.2`Z:CE$%R +MSG24X$<16$\2$DG,&E)N)E%@1LK/)#,K23F:?&8Q*4^3TJPGY1ZRFO6D'$5B +MLYZ4@6E'$4N +MM+R4@4B'EI<2*QG18E(V)BE:CDH9Y$7+40E^W(/U),V0_[-+Y692I*6I_$R6 +MM#J5HTF4%JCR-+G2&E7N(5U:H\I19$QK5!F(I&F-*K&2-RU0)5=2IR6KE$'V +MM&25X$>@EJP2!SG4DE5"(HU:LDHSI`M-5@F,W`G**G&/W3I9)>\QAR:K!#Z2 +MZV25T##M!%(RDD0-TTXP)2-)V##M!%0RDL0-TTZ0BV25X##M1+I(5DD.TTYH +M)7UIZ##MQ&,RD=5%TTY,)HMI%C'M1+^H)^D+TTYD)A-J13/M1&<27YDTTTZ$ +M)OF53C;MA)G2G*8HTTZD)L5IV4H<1>^$7KE'TTX\*`F6N[.\QK12G%:N)*0Q +M+#ME>8UMI4&)'9;7^%8"+.=I>8UQY<=2));7.%?NT^*5_\>=P%R_H:+DL)8L!RO16V9*#U-6J6:LO965\C9QFW[%9^ +M%-N6#K&^QL#2@ABU)%H.U0!F?0VDI=J2/]?7>%C^+;>6""Z\I://'7*M%"$J +MQMPA5LN_)4R6EGBJEQ6 +M*Z.*E +M+&5COLM\Y;`J>-FO+-X1+P.6RJKC)1U-VF"R_"/*+:M1FNW'(I +M+\N57J[C)>"R6Z6]Y%B"J[27O,N]Y7`I7LGFTEX^+M=5VDN6Y9Q+>UFOI%=I +M+V>6^"KMYQFNK%AI +M+\N5![SC)=628Z7`Y%@Z\!286TO?8D_2?NFW_&_-+P67U43[I>%ROB8A:'5- +M,-V6.*L/9G1LL1&YY*_%*W]6(LP+VF(#V3"?.++5(1 +MSHXFADLN6[SRXN7'7*HA1!J71,5!9N02J8@0\5@N%1MI"!$6YJ%KD-F\G"H. +M,M>55\5!9MIRJSC(C%D^,FEH")$VIEA10J"6W.X-,NF8C:9H)5PRO#?(]%L2 +MFK*5=LGSWB`SD,D:8YH\+65-\&-.$A5FM7$P6 +M%G.9F,Q7V]FR[-639+4Q33R9.+[EY9[QC/W%NN +MF\J5V6TOQ)'910E">9//=+-&3;+Z=Y7J2S1>M=$^R +M^:J5\4DV7[:2/KE>Y&AN,MV+'$UH9GBQ7-F?1+FE*P&4*#>.Y8`2Y9;1W%L& +MO3B:?DNGT^.205E@Y&@:+A&,\4H)Y8)10E"A1+G=+#&4*+>=Y8:2PIC49&%V +MO9*:EETZE:>*)%N24V9IM.I7-FB+#$F-1&:*<:D)BJS[;6UM%%> +MW9B:?DME'U,3@^EU8VH:+L-N$@(AY8XQ7EFD]#'R-2.7:C>^)C#3R1BQ=%)" +M^\J54 +M_%B;E62C`(I]^R"0;AQ&!&P2"I![J&`8;\'#>Q#8144Z*XY*3Q"D:@PV< +M.(-BL`$5IX(,-M#B9(W!!F"<33'8P(R30@8;L'%>R&`#.4YM&7G@:9F&8T5D +M.1-BI2@JYW0+CD1S)`\`,\%_",X+')\S#Q?H;%Z:_P*=F,ST'WD@;H%LR'4\2=,RG(WE@8#EU/$D0+6UA)PG!92XLT/FP]#JV +M!A*7F+AAF"!BTFF.HG(^N`:=5T[*I03PU(FY;#N>.@V=[2@$I^<2UKE7^T,P +M.CV`ITYHYC`JPXFZ)`&BP_X0ELZ_HZXST_D.TW5R.MEA?XA/IZ3N#R'J%$J> +M.DN=_K"2!)U3((;@!%[V`+N=5DN%6+?SSZEY+$G4.CN/)0E#)^BQ))'H'#V6 +M)!B=4,"2A+"3"EB2@%O.Q(:SE[;`V,J_B +M.=>7:D`$I_NR#:CP1&3.Q+!AO(UPY[J(&\;;('>:.?67>4"%I[J3S0G`_`,J +M/.&=;\XM)EUNQ^G%W`:F/0V=WD#C1Z+3!VG\8'1: +M[8P?PLXBI/'#WHF$-'Y8.I>0QH],Y]C.^,'IC$(:/SZ=G3GCAZ@3"VG\*'5N +M(8\;=$XOY''#X1F&;`W`KOBAS/W; +M.<.2%4'/9^"SRWF6U$.F/@^?8\ZV)"`R]=GX3'/.):%SQ\Y8IDHP]6GYE'/R +M);-SK0%=9DZ0RMG+S`EJ/0N3\;DV7[NAULF);#<8.H."R<]$)U&PW<#HK)&U +M&X2=2L%V@[V3%=ENL'2^(I.?F<[_7+N!TWDD2WY^.KV"[091)R^RW5#JC)*U +M!M29N$A59SL3%TGEA&?B(K6>\TQ<)#3LN4']['(&)R5T$$]^9C42P?G/Q$6" +MPYX;X,\T9W.R&\D`-7^^.1>:X\@=IW5R1G?__'3^R9X;HLYVY'.CU.FCJT;0 +M.3V#K8&.9CH2X@G23$=2/$>:Z<@'J$DS'9GA3&G6Z8Z=+,TZ';3S/HFEVW'J +M)[%T/\Z:9IUNR(G3K-,=.7>:=;K29QZ+SYFF0W`F*#623M`0Z)5S_<4$[7HJ +M-4>2",ZF9IT.X@G5K--1/*>:=;H'J(<22Y?A#%$&RZ)BOXA$Y[0,VOG55-1E +M0?M%V21OV2\B8!0'G7;6V^J@T+1?Q-4(#\HZ^T5`C/B@BK)?!-@($#H[^T60 +MC0BA7]"/$2'T`2H"(X1F.(E9@%"`F>KI(*,63>A8)?8#6LR*A&4Y\%B`4#;K/&H9".[]@P]`=IT`K#JH,=1<+JUVZ)$SIM4.+7W2 +MM-JAJLZ;5CN4RJG3:H=J/7M:[=`!*%"K'4H+'6JU0R&>1JUV*,73A=8.?8#N +M!-NA&Q +M!^B@X"MT&'M`:E03Y<^Q!_:@X"N1Z/&M=](4-8D:MJBBX"O%&'O@$)JWFUPL +MJ'BBSC-?F#N!)"J_<8,H3W8@U186BK:VFJ%$4:`<6/1=BVB87)[&::!?-G0`5M9WQ +MQMP)YE`-DEDT'3I%NX>Y$[BB!+2V:`$N#DJ>FT:010EH=='G%F?4(#:-6(M6 +M1GVBB+[1J$-L&C$7W1A.+C9PJM&-VS1"&GI$8X=-(X"B)$.7Z'HK-KHVFT8@ +M19M86M%N&F_4,3:-:(Q.T8)KTXC(Z'%T&#:-H(SZT/QLTPC,Z'&T+7H>Y(W& +M11%J%"4,,8;-8IJN&*C4;%Q!&V4BV8;U52A +M1T6B):XX*'$TJB@?58G"(>NC2;-QA'&4C78=58ZRT;2CSM'0X#A".LI&`X_" +M0^=H0E&H$WXT[M:T0(E&DI2BPZH%J5.T>"*@8M%>'))4)9I76Y+F +M1R%=3E(GVW2`*`JQK(L>\**DL[/I`%,48&DOFP[L1^=9+E'?(I:T1^H<5:>% +M20FD`J4AZ8&T:"D2;75%27NC.*LWJ5:49_4F)8[^K-ZD8E&AU9N4.5JT>I.F +M19%6;]*VZ-+J31H7=5J]2>NB.[(W:5[T1_8F]8GZ\-ZD0E$BYH/#H&04#7M& +M2=.CVJY+J6TT;74I%8F&N^*@S-&X%:A4)7KN&I7F1Z]KIE(IZ;LK54I'0[OL +M13V(\K*VRZO4;.D3U7>Q2H6BZ#56J5%TO98J!9A=+;:D(D3;*!RO5^HI]8]J +MU5RB?;)>J5;TQ-@K)8X2RGJE8M&+5Z^4.:KQZI6F16%7O=*V*.VJ5QH7O5WU +M2NNBNJM>:5YTY=4K]8F^O'JE0M%26:_4*%J62Y6F1T5L[E+;:/3*72H2I5[% +M0:^ESM'(VN3"Z'4OA:;%!]:D<<2XJ/BJ7^HN\UHX2.N(65+U%<'T=N:U>(LB +M3(6BSK*%Z5+-:W$7/20J1<5>"U.G:-DK8RH2A;)E3$VBT\R,J5:47)8Q)8Z* +MYC*F8E$'5L:4.1K!RIBF12E8&=.VZ`4K8QH7E41E3.NB':R,:5XTA)4Q]8F2 +ML#*F0E&$6<;4*"KY6IBF1P%M1E/;J.;+:"H2[7S%0=NBH*^GJ4JT8R8US8^> +MOJJF4E*2&=:T56IIVYKN3`FD)LS)1:=M:RH4G6)M38VBT"BLJ:\TBZ4VM8WR +MS-2F(E$PEMK4)#K&4IMJ1I39FC<"RU:5ITCJ4V;8MV +MO]2F<=$\EMJT+DK^4IOF1<5F:E.?Z/I+;2H4=7^I38VBBRRL:7KTD:4YM8W. +MS32G(M']5QPT+JHW&YVJ1-%MIM/\:.`L=2HE+9RQ3ENEJ*S7:5[T#GK;82;80BVDRBD%!$FU84!>8[)8Y> +M0A%M8E%-:'6O>%HQK3053]>C.HFURBPM!CYN2B&(I8Q)\Z +M3*.9<=%EJ&,1?UH]G;6Y+;"GRDR?Z$(K#IIKAUC:1Z!Z,@6H8Y1.>A]\S)A3W4MGA"-8T" +MV]JB_%"`Y@FU-?KCJXL*1*UM>=&"J+7-)XH096BZO.RGP#:CJ$-4HGE"!9;B +M^!:C%-'JX@G5/YI#=8YN%U6H!%+OH@H58&IPLXC]PH"H<;Y_&!;5("84VZ*. +MUOYB7M0+6FLLC+I4*X^%40%F-K(S*CML3'9&A8 +M4C]C/SI@:B)5<'=--9--ZH"IC]3JJ)W1)8$=O6V24P^F!#],JG<4T$A._9\Z +M&7EC`P(:*BF%G%H]+6Y:43V7<5!&(SD5-VKT<[(-"+RGXJ][*C0UNGE/-:)V +M-^UE0@H@ZG63G.H?#4#=4YVC0S]R*H$TO'E/!9@BH-RH"E)5HQ55-I9/98\] +M^A2J*;%C'TCU$Z<@D*?>&C>J]=3]V.!OI.I0.TBP5,%R!8F7:B+51!K@5!`8 +M5`F<&]7]*+/1)?$BG?MM5"&J%#(%P43U0G839*G"4W>DVT:7A(^T\@=(#9)6 +M_@:I1-+*GR'U2%KY2Z0J22M_C-0F:;O1B@HEA3=R5;VG,4ZE*C25QJE4-:C> +M.)6J^U$=)U?5/^KCY*HZ1X6<7%4"J9&3JPHP57(B+CZCN#^8&.("G>KDE*;2 +M22..5M0[J983<2%/U4,E4ONDP;_`*@*5"A=8Y:?V526IAE*1HTLB45IR#*R: +M58FJC]+I7V!5.9J&JSG:3V..DU7I*,W1\/A9K<-943^E.L?3*CKUT.F2*)4" +M'4^K_U/V7R>RM*I:ZT725CME[LC;ZCNM(JE;#:;F2OE_IU4)*JCS.V!$'76V +M5HVCIL[O`&=:.J2PN/YLS/JJ3.GRE?-:7. +M2QV/V57.*K?3NNI/%U;]JFBL-=!?#8JU!@"L"K+6P("5->859;!64G.F?$`K*L_4X^F2^)D* +M`G6LXU4W:M'4Y*ECQ9[.'P>I2U-'H(Z52CI_3*1&32F!.M;B:LVSQXI<-=CQ +M3C^KGL#Q*9;UP+8_W;).U52H7E;RF$L"KSJ5BZ.F396>+@FV:=,SS1I;A7KR +M5,.L>M6ZZ2[0BHHW]07263>L=B-#JM^4&)AF%:Z>Y>BL4M88Z^$4[>F2X*S" +MQNBLSM7=&'H5-&*\6 +M(:,1YE4D9#3"R+J$C$9L6,=VT0@F:Q0R&B%<[F22)XF!`&IS%/;W"#U>9H0-*1* +M3S&"5M1.J.VSV$IJC;%N3T."T595:U/,<]%J#:J23X>?Q=99J[;,<\%9I:/. +MW"JL`33/A6C5)NBYH*Z2YX@19%9.)#%BM8K])$9T5XF"Q(C8:HV,&#%>50H2 +M(\RKK$ABA)'U_$F,V+#^YX@13-;V)S%"N.H5)$845WF1Q`CDJOV3&%%NK8P1 +M(YRK6#*7!#LT&:EQ=;=B4U&HSD@KZ@H5%\E(S8=*Z!ZI,50'J,BUW[IMO:&. +M(]&K.M1QY!JUAYH!%;DR6>^H0]1T)"`U(FJC&Z0F4>&1(E?.*@I4Y>!<#0VJ +M'$2K23J5`W45-8@B(+.N!E$$JU77((J@NPHJ0Q'$5A&2*(+QZD(216!>W0VB +M"(RL8CH4P8:5(HDBN+E6QE`$PE5+TC$,15!<70Y:Q'A%GU5?631B*EH8?0Y2 +MPU`$1=>@&(H`Z:H@0Q$L75EC+@*G:U/L6A1WI9!UBPJON#$7P=556^8B2!?Y +ME+QE+@)WT>-54N65=<8OTKP^".EH+H*`T>957N8BD!J- +M7NUE+H*KT>D5'/8P\KR:R\AA+@*PT>@58.8B(!O-7MEA'B/7J\P*'I:5B"K- +M7D5B60ELT>Q5,9:5\!;-7AUC60ERT>S5%Y:5<+R^"(=A60G)ZXMP[4JV;`B\ +M")EA60E\T>P5&I:5Z!?-7N^NV;39*S8L*V%Z]1&^73^*LU?6:W?0^MJR@KT* +M[D:O4;&LA.T5,HE[/0_"7WFO"*['*_Y5^#JV6KL^N/2OF%?`&`"6\TH8&\`J +MROY&NE>!W?C5!1;[.X2RPS%>HDP46^BH;L\"N78=5%ECL:_'.`LM]5599 +M8.^N4BX+[/BURF6!Y8;Q$[2O>BO6ZY;+`@M[]7(98..OW:HC+.X57'6$Y;V. +MJQZOP%57J6%/<#BJ[JPL[/Y40)V";EQ4+X& +M1=^N%I;WFU=JPN%=(5QN6]UJQ:L,"7P]X;5CB*\>J#8M\=>"U +M89FOOL4V+/2U4-B&7;N>NMJPV%=55QN6^]KJ:L/>77%6;=CQ*\^J#>N#_5FU +M85FO0JLV+.RU:-6%C;\BK3JQN->E52>6]^JT>KP27W=DIE@J[(\L%9LT*RBH +M7AV&C%@/K,/P$2M[=1A*8JVPI]&W:]J*%7M!2RCX7AV&L->X%2^6]GKN&L;B +M7J]KPUC>Z[MK&`M\)9,-8XFO8+QA+/)5WS6,9;ZBUX:QT-?UVC!V[>I>&\9B +M7^%XPUCN*TYR&'MW[9,-8\>O)\9AK`^64#:,9;U>O(:QL%>-%R\V_@J[FL?B +M7FE7\UC>Z^WJ\8I\U5WQ8ZFP*Z]_;"OVY260=;*]!;ROC230:UFN(!N&%;$Q +M9'VPT2N&K#M6%CM'B\?68F%9Z+"W`"[VEW6/S<)&DGBOXJN"[-HLHL!_A641 +M7]57(EGD*]9+),M\=9:)9*&O]"N1[-I5["62Q;Z6O42RW%L)2RO%=)U..5^=K!FLI2 +M84-85ME6+`DK*VN019AQ94&ODJ^O[/@5T/:5]<%JOKZRK-?.UU<6]@KZXLK2 +M7CMF;EG:61;YVVMRRS-^N8RRW[/C5C.66]<&2H]RRK%=TE%L6]@K'XLK& +M7^=8GEG<:_?+,\M[S6,]7@FS%]FXY6%V(WM44LQZ9,V6W%?WUVF6@28F*,G& +M+<>OCZS9[&A-3&"&-5NR7O=?NMFXFYA`^BI"S,BBVX*S_#G04N\$.NWJS_+!4VG"6@;<62LPJT!MES%H(6]#IS6]"N9S>RM27W[&O6>UUGZ6AQ;U^P32TO%>!EH86^%K0TM`27Q%:&EKDZT)+0\M\=6AI +M:*&O$2T-[=J5HJ6AQ;Y>M#2TW-<]F(;V[OH_T]".7T5:&EH?;$E+0\MZ16EI +M:&&O*RT$;?S5I:6DQ;W&M)2TO%>:UN,5^WK3FM)2875:5MI6;$\K2VN0!6IQ +M:4&O0ZTO[?C5J/6E]<&ZT+ZT15J[;`OS[=JMX]+27G-H;EHG[80VG@@/VS(E +M8-N)%C$PTYV6/59FVM/"Q]),?MII6YLI4`L3BS,1:H]A=29"+3,LST2HA8;U +MF0BUU#!!$Z$6&V9H(M1RPQ9-A%IPV*.)4$L.FS0%:J-BEZ9/+3N,T_2IK=,^ +MJ!ZOCEI"&JJV:%8G,+[&]A:UFZVA06PO5>M\_632T6A-"=@J$Z4V9M#:[M"7ZQS=IAV)[`-FL]]5Q,M[JUBUI$7[?647N!Z]9& +M:C=PW5I*;?6U6WNI'5-U:S6UZZUN;:[PFF]*U/;:\M4$"GE<"N,RVVHE=WYLF66?OC=H6+`XU:;NQ_?%= +M:F>P#$U7AKF-J":GFP%4W/!98+8^LSZTH0:ST)2=N8K;#O*Q:L2,!* +M4LNZTHH;'5.2=N-;,1-:SNGA6E&*]BV<;=%`;F6OIBG7:L] +M7O&+G@M!U]\V6IN&1;F)Q"A/>-OGV:+`\EK43%<<;,>V@MHZ[%)S])2X1=3N +M8:.:?5N<[:K/41N(O3`&;M^V0;%_1>+V4JN(!6MZ+AJQN;[3[=Z60C94:-I^ +M^@*VEMA.ZNFV5EM +M;FFVA,U+K0_O\4ID/-VJ:7&I0P6%[9+Q=+N1;6SR71*P4L;W$_;6,!9](-=: +M-CT7Q5C"6YX6&7MX&]_2;J.IXEIG+)D1?*N[)?B-^J(/OMMHJJ/V&KOP&]^* +M;=VWE-IN[)QQ?*NYI6V.;Y^W3;'H@_26=9N.9:=&'^:TIKGE<:@FRF\8&KO#6H9K!O=]V +M-P%F2*@$+$4U@ZNYO:@V<-6TY\VF@L(6ZM?`W">#V +M9.U^REJ@[(23TM#"U991&M2TG=JD+%-UB;N1_7!2&N:T(LY,`0^WQ"FT2,"J +M&S,%KML59Z;`B.OBS!2<;\.JF8*2;5]564N6S3?F:<^R_,8_KO"VK>JY:,L* +M'`NYR-NY:B%7JO<+:#SDVN7'?]Q8".^$2R=R\H^;ZP^`2L=S]ZE]BF.M?A4O< +M<@.L<`E=KN81+M'+[3SV)2BZ![;"!$AWJ@:7,.9"`7,NR5PJ8,Z%F=MZS+D\ +M=H/;;\SYU+0#7C&=!&Z^[&`,5V-+BE71YOQ5+<"(::4>>B0EF[OBQW?K,%8LE +M)@2Z++G$1$$7)I>8P.;*/!,3"]TI:V+"FVNP2TS$>U:G'[2UP/Y:=.NS> +MQ+I3BMVI'#0L/.78%9.5IRJ[QK+T5&37!`EO9>NRQN)3F]VFF$!`KDLAPT]A +M=KMH_*G3+CP,0!79%8D1J(:YWL`#%6P7FB80,.9:[<87LUUWV80JMRLONU#Q +M=NUE&ZK6KJ7,0_7;)8?%"K"YG;D2%6^7/]>_6.ZN=EM;/B75G&OW6!O=[7S2 +MJ):[CC$5=J^ +M7)N\(MX+F:U!H-L87.W:8#F@M@9L[I_,UK#0;4?:&KRY/CI;0RP7!6IKH.6& +M!FT-M]PDG:U!EXL:M#7T#OHQAKFO0UC#/!96]J^2\5[5E!I[W5&8L8.;N +M!HT%SUPQ'F%B"*M#[S&,877H9889"\"\Z5W)+1;TWVKF#8H9 +M"]*\1EX_+$MRO-NY?4G^6X&YTS(0[R'V#/K?+=VZ006N4273DK>LKH`M4O5* +MZA8:RB-7+VWW9R7K99W5%=)%M5Y%65W!793KG9W5%>9%O5[Y[M*JUUO?=5KU +M>HV[.[)<+\",:M4[4?;^=WUXRM[5KJ14V>O:#7LJ>PN\VBYE;W8W;:7L]84I +M"U*]S]?Q;MQ*V;OH/7QV]US5E[V3WW:7L9>^2R92][UTPGK)7OJOO4O;6 +M=]%KRE[C[GHMUQL54Q9(C?B]_UTX'K]WM8N35/42?,%&!M^BF;*`;)3P39HI +M"SY\G6^HJUKL-'>]JO"*^OE[8%<97ODN[POC6=V]7&%_CKNXJXKOL77F1 +M?/^[+R^2[VJW5$;R=>V6Y4B^!5X1&\DWNQN](OEZ>ZE7)-]AF&(#X:NW6O0: +MO4B^CMZ\',EWLBN^(OFR=XEE)-_WKOJ*Y"O?Q7J1?.N[SC*2KW&7?A7Q[?>* +MO:J^_]VR5]5WM0ME4_6Z=J>97E^%+[DL[.OP%^2L/2^JUV$F=[7M2OYTOL6 +M>`%M>M_LKN9+[^OM[7SI?76^H"^][Z*W8Z;W=?2>OO2^DUV2F=Z7O6MIT_N^ +M=UEF>E_Y;J=-[UO?G6+I?8V[T*BS;[\WBZ7Z_>_RS%2_JUTPEJJWP#O&FOTJ +M?,U8ME^'+SDJ]ROQ14?Q?M>^<*S?[WMWCO7[E>]VOWZ_I5^(T>\7]=OV/8Z" +M>,5FO%_F[OHK^KO:=7]%?UV[BZSH;X'WD17]S>[.S:*_WM[]5_17YZLWB_XN +M>M%MT5]';^`L^CO9+9Q%?]F[J*SH[WNWWA;]E>]"SJ*_]=W)6?37N)L!X_WV +M>SE@_M__+N?,_[O:%8&I>K.[Q*P#L,(7!:8`=O@RLQK`$M]G%@1X[2O-F@"_ +M=ZM9$V#Y+C9K`ES?W69-@(V[WBP(\+(WG"4"_N^2LT3`!6#E;R3)M3MS$P$7 +M>/5T(F`$,,0WDN3MK6>)@'6^^"P1\*)WGR4"=O1^P43`DUV!E@B8O5O0$@&_ +M=Q%:(F#Y[D)+!%S?=6B)@(V[$2T(<+^7HB4%_N]>M*3`J]T]F*JW!MS\=:?= +MPY8=<%]QF@]X!BQ.F^RBM+;`#+3-0JN72_K>=6FA@4=KFP5RT1OX@K99P/5R +M28V[-ZTY\+)7IZ4'_N_VM/3`JUV@EA[8M3O4T@,7>(U:>N#LK@M-#^SMW0GJ +M@76^W3H]\*(WAZ8'=O22Z_3`T##$2[/W8TD-^VIM@@U*V#"QUB>X:,D-*VL= +M#3Z6X+"TUBF84FH1:VN-@MUI43&XUBLXF]1%FVO-@K5E=JU7\#`LKZ4++IKQ +MM7K!2;._%C#8R2;86@7'+3O!5U%CL`4Q%*RP5`8?E4K!7]&@@F^V%?R@4O4^ +MM50.A#1K\('MLC4,YL\I7RB^(D1X6+S`#IQ"I`;S>F&ES[/25C?8,18OP!=I +M@S]Q\8)^T3N8AA;;`@`"W#\X%;S<^@>3P^@O^N#"&CKL7N`MF@?7@A%]%F%Q\`5.U8L/WL!Q +MA'W!U=>/<#!X3"42)@:OMTK"=#3WEC[XL]8*[J:AA$O!'T64,$-8!8PP?0@+ +M[DK"`+,`UTK8+_:!V0DWTD@P/F%'W[Y@#3Q(5(RE8(+"O34)%U+8%V;A>@7[ +MEG;!&BZ<,#[8`2%TZX$QQ5Q`F'@N&0..%2<(P+)YP*!O?A +MA!_"L*J2<"SX#:<69H?M"\C`LT1Q,-1)U*<7)@8K +MJ_K"*6$I%V`X%%SE`@R7@K%<@.%4\)8+,/P0]G+UA7/"W:K'L%L87/48E@O3 +MA-.)(K%_01=8Q=4*7E<]AMG!@QG +M@N5JC^%.<"_N,1P*SJL]ADO!D*['<"JX8O48?@@?\/K"L6".%7#8+>S``PZ+ +M@WV+JM[7@Z[RW8Q^F!=+76X(EP[53G0 +M>G5[U&%R<)7M(5RTL@YOW)(QV6&>\+#7N$<=E@Z&GU.'+<*-I%VSMQ>Y1A\/`V5/JL'2XT-8*#G?)ASO!XU[Q*7*".]RL+06G +M>]5[*@=V[_HT0GP.)MA.A.6]\5-^3'K89];O>@4CB./#^M."C#[X85L@]@:$8,*<:./)F;YHA3S@Q>_5$V5@^/7:GF)%,84L]A4IQHU%#*3#;,U6L.GWK;G[T@?+-;D3QF+H\.L7QR@L%@\/ +M;X7%HF+"9B@8]QMD%!;?B7^WJ6#?[V%36.PJ=M].A(F_=#>W\/%W[R8LU@]/ +M-E4.Y"]5[_>V8M`ESFP:2)+%\&#KKS,U_O4*+CWA@[F_D+=6\/=7S:AR$/_6 +M;_O%T6+-6[^83KR[K<45P.#%M[0-Q9+8??L0CO]J_";"]%]V:GX&8=PFUO\R +M +M75_&3;$8B]A,9*@,>[O7!8C,1'? +M#42<,1+]<(G3#Z8/5C?&2+K$*\X8B738Q5DGH1K/C1_"*RU5+UFU3J(U[JNZ +MA6-:BF-),4TK:<5^5'?P'#OTQA07!H;]=<"'8X=@*1@0# +M5I6N=N.\:B;8$;S)5;IV@?50H6!*<"BW3C(XEE,U70W'?57F0-.U9.R%HPLT +M71O'K%P%0--U98S[8QPU7<7#`).FJZ@XYMATK1EW_YJNUV)`9]-U8>S+;;IV +MBP^=35>YL2>LZ9HZ'L0U72_#I;"F:_-W_M=T!1`S'9NN<.%7&-35<#QUA+J: +MB6UA4%>M\:@3ZDH\]CI"79''S%6HZ_*XG`MU=1Y+5Z&NT>-UKO#X(V8/;CM" +M7:_'N4ZHJ_9X`PAU[1Y[`*&NX..\(]1U?,QWA+J:CY6=4-?T<;-SZLH^MA), +M7=_'S+BIJ_Q8*#EUK1_+JZ:NR&-NY]1U>4QYG+HZCR^/4]?H,1%PZDH]/@). +M7:_'2L"IJ_:X"3AU[1YWQ*:NX&-XW-1U?%P2F[J:CV&Z4]?T,4ML@(S@,BW= +M'IG((&0_E-5UA!RFLKJ:D+-;5M<4,L/)ZLI"-C5975_($R>KJPS9=GQO*""O +MBW3'_`8S,B#,ZKI#IHI977W(>3*K*_@X0&!U'1^/'ZVNYN.KE=4U?5P6R[JR +MC]%B6=?W\?LQZRH_KGEF7>O'<[&L*_+X+I9U71Z'`K.NSF-28-8U>FR4R[I2 +MCQ&06=?K<5,NZZH]ALIE7;O'$$/!>2LYP`Y-!P,'""3 +MAHF!7%=!LA>Y-%!(#B.7!A#)9&38\-J3Z^I(7B.7!B+);N32`"4YCEP:H!YC +M!+BNU^.G'==5>UR8X[IVCXE77%?P<7.,ZSH^9EYQ75F5Q%%I+ED['(LP)I\A9Y5E!-GB5G>VUS(H*OZS:9C&P@MLVA +MD1/$AL@!LKEW.B=1/B<3DR7$,$&QZ_(X1"9V=1Z7R,2NT6,4F=B5>HR>$[M> +MCX."8E?ML8Q,[-H]KF&)7<'']3FQZ_@8/R=V-1^_(L6NZ6,B6=F5?7PD*[N^ +MCY5D95?Y<5BP[%H_CI*579''P\BRZT;YE%PD_G\.D%.^$CK\0-F5I#Q0=A*3 +M7)_**F5;7,$=OU8Q173$J\(6Y1<1EOP +MBKQ%S>6$,D=">=1<-A'PBM)%S64T\A@KN5RWX!7-B[C+'N1O`W7Y14A'3A#T +MB[C+Q^2HV7BY9<47X!5)C;C+#P)>T=6(NQPSX!5!C+C+#@%>$6]Y^CI`%IMQ +MER\$O"+B\HQP@.S^XBX3$5`$BRSN9_DI@QA=AF,O+A;/<,H@Y8"1B1B,AF-_+5T("\WS97H=@OB]7 +M?!',^V5_'8$9N#RVDBYSSDK,-B.\*W+Y'#I`)F;AF"MB>-<&,YRPQPQACH?B +M72G,BK/TLC3KQRRXP+MNF!5G\66\@X=9;U5?)MBLEQMV^66\`XFYY]MC1C$K +MS@#,>(<5L^),JJR7N#)'[`[,<@DS\Y\5[TIC5IQ)EZEG3&8)U9$7V`5N#5TWP#4W +MLP%YC=#G4K/Y[3&:]59GN8[1MN8F=.D^.;B'>[9)=5X13G? +MTX+/+.>/I;BYRC5\EE`T7M'.\K3/\Y:K^'/X9Z9Q7VS^SD2*OT.>CTM.Y8N5_5BYC$03.RV!\,\>J`+VVB+Q" +MFX]JD=?5\U,K\LIWGFHIH&//5Z7Y,^WYJN1M;G45H`T$E=?=\U5)W,RS^D!7 +MG']6'^C/L]#J`\UQ+EI]H,W-2*L/M+IY:?6!?CH[K3[04^<=V0>:WOPC^T#+ +MG'UX'VA^LZ3T`YUS#GL6H'G.VJXC],\Y;76$]C:'NW++YN:X%10:Z7SNFD+_ +MGP,X9F;,VKT(Y5Q;FCJ3R:S0XJ1[$;`Y0HMOUG>!H3G-PI0L-+CI7H2`]BWU +MGMUK8.A7R[T(VNQ;7]R*^LV])W'QBC$-7G`EE<>C/\\4K#LUQUGC% +MH<6A^O6)]C93KW++BVB^LP43WVST0D6;GO-RKFCCNV@Y].`!^CSBRD7? +MG,.)#N=I9C):W$PN2T97G$5SR>C/LP,K&EU]2QE*[WRG;7#I=?8+)?UTSF.QI*?.Y"^6-+W9ORS+3+U6 +MI&W'_@2,-*$IYYQ@[M<^C&3-[M.?\]S,)&T\]B>@G*?.%^9CYL,(V$PB?AA! +MGXM=#R.9M#(3*XV`9G8]C`K2SZZ'$;19VO4P6CUK%A]&?&=Q)KZ9`Y9;!BT^ +MC&C/H\78*T;:M!A[W3V#4&.OLN;68NQ5)&U"C;U>I4G)X@HS\\\V]LJ5'CEC +ML^K26.29@E@:N(AO]F9!IEW.*C=_L[JM,KV61DJ?LR[35+38:UQZC3Q3B#T_ +MO'[.<&8E:NT5(TUOMC/+B6NOLF;O8NU5)%U%K;VBG!5NM==B-'JQ-0ULCKC5 +M7J'/[L7:JU@:45Q[14#S;6NO!6G\8NT5VKQ?K+VNGH->M5>^LU`3WRS2RBT[ +MG2K.)2WK-$QZYF%F=CIQG%=:VNGHELP6^\5(TUVZ[WNG@]?O5=9JVXZFNH[IKWY +MF_%NO5?H,[NO]RJ6GFSV7A'0ELW>:T%ZR]A[A39S-GNOJ^?/9N^5[VPO%AXW +MWS[4563H&XZ:\A9\95!OD:UO.^K05?!50AU&YKX%J5\2P5<,]5=9_!:DSC"7 +MWYK4'F192H`ZCLQ^\S=;E]]O5FH3L_S-S,QH#+Y"FUM^P=?5A7_%5UDQ1+;Z*I%VXQ5>4<].O^+JAIN$6 +M7X'-[#YP)E\=5,OJ1'/6%P;]>*YVIA\O5-3J2//V\;DZX:Z`9=\!3:' +M&Y.OT&=R8_)5+'UN3+XBH(%@R=>"M.0O^0IM/H(E7U?/,<[D*]^9QIE\C3W? +M.).OM&>U:O,5(]U6;;[NGN&JS5=9\URU^2J21C@V7U'.LK_FZZI:BLR(\S?K +MH0#,*!4SQ^=JKMAUK6\352VKQAR%R#57CZ,0NFGL,3!.W[P]'L8! +MK$M15VH"]/O/1GW`PS"1C_\Z#VM3MB5=!H8"U`#AH9K"N`-FH7-`8P:(1H]JX& +MC=#.W["U7BUE7_7,XL[LZ\!ZAAR28UC;D*$J76L@,W4G;2V'5LG) +MFZ^`^Z3LZ]!:B-S=85NWE\$[9NOU5/:5:;U$SKX^K4G)/KF\M7@Z*">XYF5E +M7YO..C$;]2":X=E][5<7=1778.N)I^)Z;.VN?D1G/+NO"6NHKN*Z9PT5BU)C +MHG^LW=>A-1U9P0.POB,W>$K7PF6V',.ZCYPS^%@#DG,&H>;YXX)9PX.ZQC1W +M>&K7LJ6LA/C*8LU([BSTJQ_)@[G5M<8:Z\6[5C@KYG#7(&C''/+Z;HV,;GKJ +MKH'6H>0<#_(ZO\SC05ZWE7\\R&MP-3:ZE:R[=EW_J+W17[G9=3A:&6BC)D>G +M(,FO4>>XG(U:'>V")+^"K6.0Z^N!-:1U?6VP/B8K&1+6RF0E0\^ZF:QD`%I# +MDY4,0^MIP1GU:C?#7W.J5M++51DV.LF!' +MJM%1+NSNEM7(:,T\FEWCI!'*+&P%MKO:)^U09F%#L-?(PH.2M7^7A8VX%O!N +MC=+7=^NF]/+31OW(LEA_E/DG`VN1,O_$8%U2'O8`K%'*_).>]4HYV7/%[CKS +M3X;6,65G3Q=[[(RC&V,[DK9&3&N=,O_D8]U3YI_$KH'*_).2]5"9?X*X-BJ7 +M>\S8>F=T#Q[[>HT"M98.CWU@3AXDK*61-NIJ5B#[(9>5>$QS +ME<]T#.LW62+;:-T8[%"'LQ;9?.9.@QG;>/QI`%C'E^]T#&L_5B.[9`U73AX@ +MKN?*J(;TM5T9U="OSBNC&L#6?&54P\#ZKXQJ,%@+EA]UGNRCD_RU9XU81C4` +MK1?+FKIO.LOR5E)VCSDZ# +M)&W4JV8L72$;/&V2Q&;#LHO4YNDP*#;;EKVDYC6?03O4.BV+]1H4F_W+IE(# +MM:!,NN6EC/((GAU"#LS,LS^OX&H7&CU;(:V=N6>;R[;98*-]MM>:%T$V$FCS +MHGD1'R.#-J<979V6E>\87M<[,6C+H>EU%6WRLO"X,>#/5IAM +MM)./$6V957L98!?2-A?%EPEV)>V^M;>@HVTNRB\O[#+:+:NV\L,.IBVS`C!/ +M[&C:YB*ILN8'IWU\5!L%M&^A'^V"MH,99,?3MAV/[(K:A*VW$;;(H)UA3MFQ +MM#O7&^U8[4``,DE'AMGAM*O:(:J2]AW9>,/2UB/G[*[:"FF>G58[TBS\`6M[ +MK8=V9FU>M-%NK)UC3MIUM=?0SI^W]M@Y^B/7/F-3[=+:>H:Y450)GHU)WMKA +MM4?:TRV^MMXZ;,?6WC?-C=)%@NWYU-S(7938%CC-C>9%C>UCR]P(7Q39UFFO +MMR+;!V:Z'5Y[P4SEJ6M/6^9&5Z/(MG7Y;X?7?F@+[AK;3>U8'VK;@YRX*VP; +MCP]`..UC\N.NI*U,;@#%MH7+$""6-C1Y`J3;)FMKN.#9UF1.4&\;T[P]H&R? +M86<#)2[@-EP[JJC/M-EG(:[N^R_PVG? +ME/]`%NZX]?B@7S3BEFT?\$;<(VV.U8C[I.W`&W'7ER-X)FY2,@4OQRV>G@2E +MN`W7EJ`?=^5B-M#J&G%GMG%6(V[.-L]JQ%W?_EF-N$?;0JL1]T.[:*7A;FHC +MK:K?M'=D7FX%]X\LS/U_W@6QM.?*03R1N3E(LX&XU9V;Q'WNVG.SMJ]K>^ZJ]KMKSRW;)I/M +MN4?:8+P]]TE;W[7GOG&CU_;<+NWUVIY;INU>VW/;M.%X>VZ=-DYRSYW9[I/M +MN3G;)\8]=WV;4+;G'FU?O/;<#VV-UYV[J0V[6G6SMFE7J^ZJ]NT*GGWCUEW1 +MNA7<*Z];=YG[Y:7KCB/-!DIEO6Y.RZ\[8!3LYFR+V(+=]>WH5;#;U`TQ"G:G +MNG_:!J6)MM&KUWW1SLM1NZO:XBMJMVR;6$;M'FFKKZC=)VVL%[7[QNTLHW:[ +MM.E7U&Z9MMB+VFW3+GM1NW7:4#9J=V9[FDGMYFR3RZC=]6W1'+5[M.W`HG8_ +MM"-8O>ZF-@4KX,W:OF`%O*O:DBAXMDN[@Z7P5G"'L!K>96X2%L3;UXT68FGS +MU#;:DJ^)MW/9?@#9AI4VH.T'QNUI\&R@\Z7Q?FB#OB;>).Z.&,NTL%LK;ILTS0WGK +MM,%8*._,]A@+Y3>TY%M:;M=W]PGI7 +MM?-8\.R@-[3;>1GT9G`[+XG>9^U'%MQ;K3TWFWLO +MM/=?=N^'MMYL[DWB1K?QO5G;@3.^=U6[<,;WEFVCLOC>(^UZ&]_[I`TYXWO? +MN"=G?&^7=@:,[RW3YH#QO6W:G#.^MTY;!,;WSFP3L_C>G&T4&-^[OLW,XGN/ +MMI]9?.^'MC1K[MW4KF:QOEG;V"S6=U5[FP7/MFE[LVK?"NYP%NZ[S$W.VGU3 +MO,]9OF]A-X2(I8V+G@WHZ8+?I.^T]R]ZHUW/"GX_M/%9OF\2]SXK^LW:_H)% +MOZO:`JWHMVR[H!7]'FDCM*+?)^V%5O3[QNW0BGZ[M"-:T6^9-D4K^FW3OFA% +MOW7:>[#H=V;[?Q;]YFR+M*+?]>V25O1[M(W2BGX_M%=:ON^FMDLK`,[:CFD% +MP*O:-"UXMD[[IJ4`5W#KM!K@9>Z>%@2# +MAV<#.\$,^/][[)VLW6CGT";@%VUR'0J47WP_@H$KOVU-+/`'%3S[P%SD8VDG +MF]K*23XSN'"YR:<&-RY'^=K@RN4J'T[;+(WE@X,WH+E\=G`J>&MK#+Z&'O/! +MP;O+9[XYN*E9S?<'#X/#O*=\Q^0?`0G\+VWG^X/'EW\$7_#"]-]AKWW/Y"<\ +MM_C@XFE"WQ^<"([HPX2;G!=]?W`R^`;.$[ZYL(0+P9VVPN-+GR!\C64)3X)/ +M^73'G3XXN!:\F^8)YS/_'4+;JNE4'TM[P=SJVX6;F/\.9N_P(B?\"UZ;%C[X +MPJ-0_`0@'#P;;IL,SW"O%Y/AY*)E>->9V'<,QW,_'JKA@'#/I32<=Y0,#WF/ +MBEG@R6W#;2J,TM&1X,Q[F- +MPXGA6&2$`"7\54P&)V\+W5+AY^T.(S]!O0W6'(@CMG-]`W'&MEES('X*?]UZ +MD`U^U7#C,4+`%5Z['8@SP7>WDY:!^!.\Q@@05X?_;J7*"`%W^+-X($X"AU`C +M!(+A$^J/'TO;0OTDV(?_;F'A^"IX]I*1G[!6DXD/PCG,?[$[<9@P/-W3K +M&B_C#7%']0^V+IX/?W0K<7^P%W&;,2^\TIUL_,%ZQ$^X5/!-MT_U!TL"?W#^ +M8(/A`+B'.*G;[L<"/W6GJBTL+&U6M0JA,CXW)H+#NJ6JJ?!9=U4U.?X6GQOS +MPG/=6]6+.:Q](=CSBK +M$(+ATVH5PA?<6GUD*8_WP+G=I&-^PK<;L"H?3XO?C?/AY6YS-4JA.=Y7Y86O +MN]?5*(7IN.WX`.@>MT^C%%+C3DXM^+T;Y2@??XVO'.7C[O#DL9NEH\T\1BF8 +MO9_'*`7EM_38*^$2KQY[)23C>$Z^^,/[M3TP2E<:2TE]X8WK=,'-_*'^-5;:BTE[Y$S=*7D0?(3DQ%8[WEK`R +MREOD1>3YP9@<':7)2\OQ`1RYB992[R7FZC/(X>3X<\LVXGA_< +MR;'BEF^D+C\A\VT'3(5SOB_7-81!>4;.=UQ#((YGY![BI6_0=0VA2\X"7WT3 +M6?D)KN^4)[#<3-Y'KB'0:0H203`J]<4\[]GK-6 +M8D3@K5\C7Q"N)## +MKZNP&O+Y-3^A_[T-7)C+RI7)?0);>3.Y3Z`HAR:O("CDT^0^08ON>&:*B@T'W)C!8OF!V:N8-%\P0Q$\)B' +MD8$((7/;\5FP:*X[7@L*S3/,;L&KN04)Y,?@VMRX_!M_F5?.LM@R\+#AVK@RR +MS>70D00.:B:`A_RN?$3KD@F7WX/&\NRP?G)YOS0%CQ'.%LWYP>FXX_VUC +MZ<+FVG`L7>Y<4Y4]QS@G"*?G^>4S@HYH?((@GXVQW)1T-7F6ZX+>MOM*<3!9(9YJ#\0+I"Z17S==K;72LN7LMEKXUA^/% +MTKWF.$D&NN&\3Z9+YYV?&'OI:G1"&3#=C7[Q&J;+T35>QG2F.>S*F#XWIUT9 +MT^WFMRMC>M5<=S5,IYZOO*KI6_.75S7=:UXJJZ8;SLMRU?2PN8BMFIX[CUY5 +MTQ_GU*MJ>OI\Z%5-%Z(;O:KIFO.\7#6]M69#G7>.;DLHJY&%\U1 +MU-WH#JR+NAP]@J51UZ>3C33J_?2/D4;=;BZ)TJA7S3M8%W7J>0@KI;XU)V&E +MU+WF"+.4NN%<\I52#YL#VE+JN7/-5TK]<=[Y2JFGST%?*74A>LM+18KJ[XUYYEE +MU;WF8"P&>NY\C"56YYV;L%8;G6F^1S+K3XW[WZY +MU:GJB?2$[%4=A?X@#9V+S=;J@//U%V#=:^[^`JP;SA=9@/6P^2,+L)X[GYL! +MUA_G^R_`>OI<;P98%Z*CVP#KFO/`&6"];T-L#XWAYP! +MUNWFDS/`>M4\`[96QYISP%KK6W/.66O=:RX"8Z`_SHE9MG7>.0HLMZY&9V;Q +MUMWHSZS?NAQ=FB5<9YI7LX3K3@KNKXU)V=% +MUVGK>76#DN%\YA9=#YOKZ:+KN7/J673]<5[/BJZGS_%9T74A^CXKNJXY_X)% +MUSOG`JWH>M*\H!5=9YHCM*+K<_.%5G3=;N[0BJY7S2-:OW6L.44KP+XUOV@% +MV+WF>S`&^GF=KVZV5*]_U#W>[761NL>[508I0]LN9EEQJAV87+J<0UNT*ZE2AG1X;'$NOL8>A:(IZ]`9U+W+-? +MV1]4;_;W[YFXAH3[.?Q`+MANMS(J+]R/[F`[6KG-^)B/8GNP#.U#YE+\"9 +MVJ_LRRU3N^ZXGXAGSS`'%&OM'N0B1*V=T7Z!8Z`#F'T0)_9N8IJ]^NIKA[./ +MJ8KMQF4?Q)D]FZA<]D$$C)#M>?9N&K2=S_Y1G+;#VK/KW<19N^`.VMY=]D$\ +MV,N)PN.68I2]&5U00'!QVQ_M0#ANNZ3]P<5MK[0#QKCMF';"&+=]TZ[AXK:G +MV3V7W/9?NZ:*VWYD+W%QVY?L445N^Y,=#LEMG[+'N+CM5W9P'[=]U@ZK@K;; +MVM]P#O=<^QS.X`MTKC_G^6*4?:78D%A@6X!#[=+ +MN3SN>?8J%\J=SVY!_X`W(4+N:^A%PK,=T69H_Z`CVG+M(G3V\,@=V_Y4-+DS +MV.%L)O=O>R9SY"YA;]9BVF/HT]."`@W=/ZQT[[B;,I7N(/9F[9&]AZX$CQ8$ +MVQM-3_:\&LK]LQTMP!=MW:_L2O3UJ=)]YFXA#K=#T7V92O>K$!PMX+DO +MV;/H6NGB8I2]*QTM*+H#4,/M8O0!:D$!9\5`-TMO+)SN'-LI^\^J[]YUWEC` +MT2]\>/>KNUQZ[WY'3]GNW;WN/N*]^[(=$8YW)[O_^"3M@W0C\=Y=[9XDWKN[ +MW4G)&XN?.[`MS?Y(SRWNW>WNP+8C>R5]H%E0P*0O;5OO@'=4>.L]ZO[CN[*' +MTLG$K7?%^QKYP3AW=R-+&'LGA/<_5>M]\@ZV;;U;WL.+:?99>IVX]GTY6]GHX0%Q<0VAM]MO9]^J^OH.!/[Z12 +MX-'O%7%QP=5=V4>!=[__;G_M"G5F,06>^#X2%Q< +MV9/JM\TB_`Q^]_Y4/XNC+'+P<61-"@^^+:Y)`<+;4UVQXOUM=N^F*/;[+J;^-4?8ZM2:E"X^GUJ3P +MW/?4FA31NY]:DV)]#U1K4E#OA&H%PAJ>ZK=I1ZQ_Q@L*BW7\)BB>#K_?!,4G +MX?V;X7;*NK$1%-^'#R,K$`#Q-N,K>V=]-JY`,,3OWD?KI&H%`B,^#9]:3U5C +M'*/LK&H%@O7]5:U`0+W+JNT0F_BY\9(=MXY5#;?OUJ/C=@@ZO*_:#I&$#U:_ +M'('QNFP[Q!/^6&V'@,7W51GMS?5_HS/^^`ZMMD.HX/.JE7;KNN?8&<]SSU;; +M(43OD]R"PG>=/FZ',,9CD><%R?B^ZI(=O9Y8+2BLU]?57$=L/"M\7E"-U[+3 +MU^?5\X)MO.]=OZY9]<<3WY/'\P++._-X7G".?Q[/"_KOTN-Y`;:]>CPO^+EC +MC^<%0O?M\;S`[NX]3A@DX\/'"8,'//DX81![/Q\G#&COZN.$`0:^?9PP"+;# +MCQ,&'OCY<<(`%F\_3A@\Y//'"0.)//\X85"1_Q\G###R->N$P48^2KYZ;++# +M'0L*0G9,W)2]R&YW],6>Y"7(N4>G?`6Y]ZB5=R,''[ORPO?BHU/>@\Q*L,F' +MD%D).7D2\O-Q+*^0ECZRY9'AU<>W?!@:^RB7;T!O'^ORUF56PD;>AAQ^E,MW +MEUD)(7D>\OG1+T]'5C_ZY8_)[4>_?'LYEM"21R+7'_WR]67\HU\^O[Q_],NW +ME6,):?DJ!Q+V,M_ +ME2N0D#R#_,WGF&V0SGD\=PXR.O^7E[9_YX&X-3"@>`_J-/&*^X3Z9N\Q# +MW,.!`WJ2/#19$.F4GR;/&%3RUN090TL^F[R(K-!WG6<,,_EO"K'F;>T(PODR*5-%'YDOH#,$8O4=>GSQC",G[ +MQQ(*+O2*8$(!Z0YM'=)CZ._S-W0<]I`>)J^<8\U3W4F"3GJ;?(;*=^PPR,D/ +ML8?T/'DCML/@(;^8;Z)'/R_S9W?GIY,>(R]2=AALY$O*#@.//$K981"27RD[ +M#$CR+N5RI%,^I@R&4,G3E->1>E`R&D,A7S@>2>7J9M4$R4F]R!D.GSC/0A[QZI3:^?EZ1S +ME%:F5"KC\_3 +MWTO+RH1=_7U^G*Y:5B8$ZVW'R@1B_6N>G7[.WM8KZ[WR\O0S:&%>?-5RTBU_ +M#+!%_?JSO/HJ8`^N?PQ[X8Q`P6MC_Y@N6QI]%? +ML#SVD7E)E,>>,M_!\MA?YD-8'GOW/`G+8R]5EB8H[&^$K'G)E\=^P2Q-F!=Y +M["GVFB^/?5Z^\^6QW]B#OA;VLOF.&=2>+'_Z@MH7YDEF_?JK/=@H:V]BEB:0 +MC;CV_V=IPL<(;._KMB9$EC(6VW]B/ +ML+$^.PML7YM%1>'O$/!P+;[^8GV/A[6GTW2^\?60^CX6WI\R3 +MO_#VEWFQ&=[>/;_^PMOW[-U?>'O1_"(+;T^T?V3A[2GV+!\X0]T7Y@MG_7K$/"HK=M^UK[?1[L/VD+/;?=E^>4:E1X'I[N70:@URT?.^,/_,>MXC +MYJ59S_O%?#7K>4^CQV8][R/SVZSG/67>F_6\O\R'LY[W[GERUO.^9W_.>MZ+ +MYF=NSWNBO9[N>4^QIYX][_/R]:SG_<8>GZ6[E\WOL_KW9/DO6/^^,"_0ZM[VF%\'OV0*T0OFA^J!7")]H;M4+X%'L76@@_+[\3#.%O +M[+MU#WS9?`XMBD^6)]=%\>G(TDJ+/1Y)>&RMU.(7LMK*VDHO/AL-P.RM%.// +ME<659OQ(L[DRC>^U5E>R\7G1[LHW/J=97BG'UQW;*]_XW65])1[?@^ROQ.-C +M\>FN)@%8UC'98(G';R]K)X3WL*SXLL,2CU]?EECB\?/+>8WEO2D+C!]_[->[ +M74U)TOM(DE0Y9(G'/S"7+/'X"^:\AM&>6\G%WXA9\FW'>8U^T2D_J4VS?.-G +MF'&6KGP^OFXKD!_(,A[G-3KXZ:12_M:>2TK)1^1#+,GX!;A^?>J9B[_<$N:K +M\9];QOPV_G0KF0_'1_0Q\^?X%[AGOAU_`\?,S^-77ZOY?/PQ534?B[_>JN8/ +M\K-IU7Q#?C>MFJ_(_RA6\QOYZ]=J/B1?<%?-!^/'^JKY9/SS8#5_DX_@JN9[ +M\H%PU?Q0_H.KFI]0=H=D\@U*UN7+I1A?H&3'UW`Q\U_YGLN#/A]?4W70Q^*7 +MN/KUD/RH(D3?Q.P.D1I-]/_/[I"KT47?U^T.P>4?@[GXL*J-OG/9'>++MR#V +M\^=P(OV`/M1)I&_'EXUM]//XPZJ7/A^_>/?2Q^(KJU[Z@WPIUTO?D%_E>NDK +M\K%<+_U&_I;KI0_)]W*]],'XW:J7/AD?7/72W^2/JU[ZGGPVUTL_E+^N>NGW +M\^=<+_V`/KWJI6_'QU=M]%_Y:[6O/A]?T/75Q^++U?KU8/Q>'%J?HI]76^MC +M]"%=;GV.?L4JKB_LSH=T[">)(WV.%5V_G^_`H^MK]3WZ<<2N_BZ_T,[%/W7% +M]>70^1`3_B$1B]_J.NP/\G%6AWU#/L_JL*_(_UD=]AOY0JO#/B2_:'78!^,C +MK0[[9/REU6%_D^^T.NQ[\G=DA_U0_H_LL-_/]^$=]@/ZDM+#OAT_[!G7?^5K +MNVK[?/RT56T?BQ_NZM>3\>-6OGV*_KDKN(_1OZX1]SGZ[Z[C?EV?3*;<#^6# +M\93[_7Q]EW(_H(]>4^[;\==KQ_T\OGLMN\_'A^-E]WG[@'T\[5N@3Y;=-^2? +M&+/[BGQ"67:_D7_QRNY#\C5>V7TP/NPJNT_&IUUE]S?YMZOLOB=?=Y7=#^6O +MO++[_?R75W8_H%\JR^[;\*PI[ES +M\<5>*GYN.-,$7Q3C)SX_,\7X+W"FR5U_!O[BM^@_]U[\&GW\,(O%3 +M^*VG'/X+?Q69::+A/X)#39#WS5I/?LV^"0XU<=L7I:$F)GZZXEL`85;CMT]# +M35K\9?+W[3OO-Y8T/Y/8TL_F'[U;^GW\4SXR?N)>A@KI!^Q3 +MIB']>'XO\HUESQ]&OK'X^5'YF'O<>]8$Q/_P\AUG31#]1U0^?NA>-9TU^Y[L!^P3 +MI[,F1_[C=-:DI*^)/+N;U"+ +M1(+]TF(N_@*_6JR1Q?=CBT7^FOZ7N,B_TS\3%XE`^Z.I?'P-?DY<)`+8-U&+ +M1([\*6J12$F?12T2T?"_J/$-XGX9-;X!Q%^C?@N\\//%1O\LO^V+BU_#K]\: +M_4'^FC>C/Z4_FMK/]^';&8W^*?^P.-.?Y:_P/^*?Q?$-`_]W*A:_B=\6QS<< +M^=_P^(:2?I<:WZ#A!U,G.,7X8^I^`XC?3-UON/BGJ?L-67XV=;_AW?^FUG#" +M_779'\WV#R/^'2D?L-6?\]=;^AT^^G3G$*_D'8_8:P/Z&ZWP#8/U3W +M&\[^4N1^@]J_BMQO:/MCD7F)7S\<]GQG+"_GGCPF/80-9?=^SE%..SJL.>/8Y`([G_A8]%.(H!C9]1.*X!G;'\(BGWJ8]I.+H`@:"4)DGSP8R4)N'[S +M8R4))G[V8^9.-(#Y9>E.-(#P?SU]9T<1!4!]$D!'@!R`47+U3C2`I7])?5)Y +MN7],?55Y)0D>?41K)0D4?D=K1X"^?&1R)0DQ@!MDO`V!?JX4$05>?6QR$4\0 +M@"1D%4]H@`IIO`V^?O8P!V:\#1.`+62\#1:`,&2\#29_]C"K?W-]-T"\?P<\ +M+2\#5R`2&2\#3&`?6LY +M3XV`+&L\3Y:`0'`_3YF`\W^6?0E/$069?8QKP`UR@%YDP`UU@&%DP`UX@*MY +MH(`<@&=DN7^H?3E6H("#@%!MH(`E@-U'H(!6@(=_M'V_%KN7_S?>1K$07V?>=KID_B@+Q__'WM:ZU/WX"U?P)^ +M"'KZ@!R`QV3'#1^`RF3'#8.`S63'#26`T&3'#5:`TV3'#5F`UF3'#5R`V63' +M#3&`W&3M!F*`WV3M!C>`XF3M!CJ`Y63M!CV`Z&333Q"`ZV363RR!(VOM!A:` +M\63<3R^!&&??3S6!EX#33'^`^F3E3SB!DFWM!A&!GW\.+#N!6V3M!A>!I8`L +M>TIZ]$\^@:M_,GL];`0E(X%K9,\-)H$+@#M[T#F'?UQ^V3D$)1.`'&7/#1:` +M'V7/#7B`(F404!"`)67/#1^`*&7/#8.`*V7/#26`+F7/#5:`,67/#5F`-&4@ +M4&6!IF8C4'>!<6LF4'J!K6;5"#>`0&75"#J`0V75"#V`1F75"&Z`2675"%R! +MF7]Z>\E(""5B@9]_@'L2.G"`@WN:>M4(:X&H@*-^*E<()7&!KG^/>Q10""5< +M@*AZ""4Q@%5>N7^Q?FEE$06;>[!ZJX$Z@'!EOP@]@'-EOPAN@'9EOP@3@'EE +M:5`0@'QER`B[@5UGOP@<@()EE#$@<1G?E#*@36`OWO? +M(#,,N:!P8&N?^1[]7KC@8.`ZVSC@26`Z4'F@1`CBB>Z +M9;50RB/\@2%D-@MD(P""PG_4,P2"Q7_U+`>"R'_X+`J"RW_[+`V"J']?,`V" +MJW\"+0V"O'\%+0J"W6714/^!+T+(@0LM&8*'?PXM&8()@1$M&8+M93@+4B,9 +M@O%E.`M7(QF"Z'][,!F"08#_,QF"\'\B+1F"\W\E+1F"4F6[`5$E&8)P@"LM +M&8*E?RXM&8*H?S$M&8*K?S0M&8*\?S"18(?(V>" +MUF4C41R"[CJZ8R=1<((-.[YC*U%T@A$['F0O47B"E60S47R"%RL?!R!M>`=Z +M*^UE[`%0@H4KPF,_47^"&&=#48N"+&M'48Z"0'!+49&"`&9/49&"4F5A%Y&" +M!V;L`6`C9(*E<%M1D8()9>P!;()!6(F"#RJ>@G*"A#1D@AEF:E&.@GQF;E&N +M@G1DE&]$_R!S63W"+>"QF7N!/TBNX*19NX$68(Y41\' +M)S'"@IAFC%&^@KEKD%',@@!G[@2=@DE1IH(#@L4SIH*D@JEF'P?++."E8)C*N"" +MF(+K+>""FX+9-."""V;3"%V"SC.B@A]%X()N@NM7X()R@H([W(*L@K$^!X-Z +M@N=!!X.R@@@N_(&%@D`X$(.X@@\N$X/_9^,(YH*P6(F"A#$6@\IEXPCM@K98 +M&X.'@O=F'P>:*AV#G&;I"'B",67C",6"32QV@G!('8-R:/I1*H,*9^L(NH)' +M-+6"L"HQ@Q&#U8)-+/%EXPC8@L=1Z()0)S&#ZX*R,3&#[X+#*C&#E8+%.S&# +MF(+**C&#FX)2+C&#^X)5+C&#HH)8+C&#;H);+C&#+AV#K(+=*F"#>H+@ +M*F"#LH+C*OR!/X-L+FF#N(+K*FR#%X-S+F^#OF[3`3V""5F;@O@J#>H)+*[>#LH). +M*_R!Z(([,L"#N((_,L.#%X,^/,:#)@N$NS(-R@G$KR8.'@^((F3$`E&8/11&Z"^R_,A+EGN`$@@\9HB8+H-M:$9VR#),^$-8.%,]V$ +M(&C;)."$$6:$(&Q<)>F$MV:))>R$ZX(9,..$[X(<,..$E8*<,^.$F((B +M,..$FX+$+..$^X(H,..$HH+,+..$;H+/+..$H+8+`J% +MLH+;+/R!^80M@Q5^B8+A+!.%PF7/*'B"(G%29A=9E>U29 +MA;IC?E26A1EF@52QA1YDA%2QA71DAU2)A::%JH*O:8U4NH7"99!4OX7&99-4 +MPH7*9994Q87.99E4R(6IA1LQ_('!:0@V>(+$::%4Q87=9:14U(6UA;-\SH6' +MA6\^VH4:;*U4U(7M9;!4U(7Q97(WT84P:?X!R(3O<,)C%PGFA>)I(0GMA89K +MOU34A:"%%SC=A-]4B84':OX!U8,*:@<[>((-:C\[&887;E<[ +M'(:89@,",X6$3:R%'(,Q>",*'X9`9@,"/(4@:@,"^"+\@2-J_U0HAB!H`P)R +MA2EJ!3TRAN2%,2XOAN>%X#X[AHIM`P(0AE)D$`DRAIV%")5$X:V8R55,H:OA5.#9'%.ABN&;F0N55*&PG#LW%[57&&LH6M@Z1J.T6KAKB%LX.I:H@+AH9O8VUEB`L\A:]JB`LN +MALAQIX:/ANM_QH7"@\UXIX;]@G-CJ87(@]!_#$=X@L%JGE6)A<1J4$?+AJ9F +MI%7.AH>%V(/B>!@%VX,"1]B&?(,%1]B&(H;6:K-5U(8_AN>#\7&Y5>*&\87M +M@Q1'V(:_AGE5HX7S@_UXQ%71ALYF"$KRAC5GRE7UAO9IWP&_A+UCZX4"A`QR +MWP'5@P]R$@+IA'$&L0A^R&X6/Q51J'NFST52"'W'`<372"ZF-,32:'E3@0AR^$ +M\&,2`L*$\V/H32F'YX4XA*E.ZX4[A&1'-H?9Y/1H>OA5.$_5P8!5:$`%U/AYF&/G+&8ZT!385C@"Q6 +M)H'A'+)A6Z$0$#KA7&$-T"LA72$?(!J +MAQ2'.623"XF#A(!AA[R&4T"'A8"$CG)AAQ6%%E9AA\6&6T!JAU.''%9JAU>' +M-EUAARR'G7)AAR^'H')AAT&#B6L8!9B$C&LN"66'#T_KA9Z$JG+D5%V'K'!O +M5A>'KH"1AW&':V2359N'_&FM5:2'58>PA(5`D8=]AW=D/58FAWID:5:OAPII +MA5:RA\APQ5:UAV%H&E>XAPUH+@F/AXED[AZ^%RX1?.;YCEU:XAW)HFE;' +MA[B%U81?.8N%>C.*)U,YX87'H(63,^"'08?QA/:`WH^AU.&^H2[9-5:N(>RA0"%!7H6 +M6_.'N(4&A0US@5LFA\IDIUO]A\"%#X63.:"%$H63.:.%WBS0A]9DA5P`B""& +MY"P)B'6&YRP/B+EG^UP,B"F&>CH2B&=L[585B'EM\%8;B(N%+84)0>&%,(4S +M>NN%$H*D3R6(@X8)09&&.87'5B6(=(<_>@57&XB@A2*"P#DEB'V'-6PEB("' +M"2PEB(.'37H8!3""3X$75Q6(LH4V@A1E/XB/AT9L*@<$A^&%0()?>NN%0X+1 +M3YV%884Y0:"%28+13Z.%9H6?2$^(=('/65$5VB(369'5W"(Y(6%A;](PF--5W"(^6505W"(;653 +M5W"(`&965W"(4F595W"(!V9<5W"("V9?5W"("65B5W"(UF5E5W"(NF-H5VB( +M&69L5Y2('F1P5Q>'IX$_"5>'\65X5R:'HFQ[5Z"(PF5^5Z.(QF6!5Z:(RF6$ +M5Q>'>66'5ZR(<6Z*5ZF(G&:-5[*(DHAZ<]"'A6655ZF(F>Q5[N(?8@".+B(562Y5\V(@XC; +M@N6!4PF5A\\J=XC3+=.(SF;)5[N(CXCUA610W8@4AZ%>W8ATA_:!V5>IB,9C +MW5?*(^DGNF6Z:_"(GU=]B-TT\8@D9%8C](CF,M>($"/XB)%FC6S[B.TJB8BQ +M/O^(F&99"1\C!HFY:VHC`HGI*I*(0#@*B=UEB)HJ$8G+B"4N$8EZB%%%$8E]B'!($8F`B#$N$8F# +MB.`^$8F&B+`J$8F)B&\X$8F,B',X$8F/B%`G$8F2B+(Q"HF5B,,J0XF8B,4[ +M0XET9`-Q#8E*B5(N\8AW9,DC'HE>@C]83(D*:3D)58G((@BYSB35SB8"(D"YSB8.(%2MSB8:(!SQS +MB8F('"MSB8R(#CQSB8^(OD5SB9*(A4)PB96(IRZ8B9B(JBZ8B4J)K2[QB!R) +M."NAB29F!07>(J2)_V?E=@V)T&0C=ZN)`(E%*ZB)7(E(*[&)7XE+*[2)CXA. +M*[2)DH@[,K&)$HD_,KV)F(@^/+V)GXECBHAQ*[V)?8CG+KV)@(C7-;V)@XCO+KV)AHAD,KV)B8A@/+V)C(CZ +M+KV)CXCH-;V)DHCK-;&)E8CN->V)F(AP/.V)2HDX2?&(Q8A],O:)I8DG1OF) +MJ8F$,OR)OFYO`5$E_XG";J8D#8DH96\!IXD.0XR(M"L#BH^(MRL#BI*(NBO_ +MB1*)*R\3BIB(+R\3BDJ)I3(3BAR)93D3BL6((C83BIZ(T2L3BLN(U"L3BGJ( +M0R\3BGV(1B\3BH"(>3D3BH.(XBL3BH:(Q#(3BHF(ZBL3BHR(6"\3BH^(SC(3 +MBI*(]"O_B96(8B]#BIB(92]#BDJ)4#;QB)Z(TTQ,BJ6)Y#)/BJF)HCE2B@"* +M#BQ5B@2*$2Q8BCB*9"-8BCN*"8ET;G>(DBA8BI*('2Q5BA*)(2QGBIB()"QG +MBDJ)"#-GBAR)DB]GBL6(@#9GBIZ(FB]GBLN(G2]GBGJ(H"]GBGV('3-GBH"( +MIR]GBH.()#-GBH:(EC9GBHF(+#-GBHR(G39GBH^(4RQGBI*(T"A5BI6(62R7 +MBIB(/#.7BDJ)8"SQB,N(8RR@BJ6)9BRCBJF)Y"BFB@"*Z"BIB@2*<"RLBHF( +MHC$+/6*I8DH,/B*J8G,+/N*`(K/+/Z*!(K2+`&+B8C5+`&+C(C8+`&+ +MCXC;+`&+DHC>+/Z*$HGA+!"+F(CD+!"+\XJWBG]+'(DS-Q"+Q8AZ.A"+GHC4 +M,Q"+RXCU+!"+>HCX+!"+?8C[+!"+@(A?,!"+@X@"+1"+AH@%+1"+B8@(+1"+ +MC(@++1"+CX@.+1"+DH@1+?Z*E8@4+4"+F(@7+4"+2HE[,/&(*8NZB@A3*8M= +MBGA]+(O!BLY+@X@H+4F+`(DK+56+7FM["0F*"%.,B#$M6(L+B30M7XL`9WL) +M[B)?BQ*).BUFBYB(/2UFBTJ)0"UFBQR)0RUFB\6(1BUFBYZ(+C1FB\N(.T%F +MBWJ(W3IFBWV(.31FBX"(Y#IFBU)E=EIVB8=$!V9Z6H>+P#4+9GU:BXN^)0EE +M@%J/B[9C@UJ3BTEMAEJ6BTEIPF.)6IF+?&:,6IV+=&2/6HN+`&:26J.+)F:5 +M6J:+_V>86JF+OFZ;6JR+PFZ>6J^+C8O-8*L"S'8-:*1:KXO6974"`HJVB[IC +M=0+8(O&('2:^8ZU:#8D?+IN+4FW!BPIGL";%BX""N%JLBTUFN";,B]=Z=0+X +M(LF+&&?#6M*++&MU`@$CUHN.;P);BR%%'F1[`N0B]HNABQ()'X"6PV)%FD&6[@3 +ML3WTB^F+)7!#"06),84=C%&+(VF;BP@N"HP@:($"P(LZA1I;%8QZ:QY;BXN$ +M)O5E(5LNC*1D)%LKC.)I*R%."<^C*5PC@I!C)&+ +M,(E6A8$"&(M+:2.,&XSN4\.+.8EH=X$"(8SN4Z&+/XEJ?ET)*(P<6VUE70GY +MB\I,I(M(B2=B0PG**O&("#YAC&6+`#Z-BU4N8XQQ;F8)#8EL:5Y;;8QK:+\* +M<(QC9V5;BXMV:6A;=HS*B^,J:HP:;&Y;EN&C%J,:S5\C(9KW`J&C(6+?(FL=XA;B8Q":HM;AHR1BX6)R45;"?TB +MCXSV:91;EXSWBXZ)%4U;"5)KVFB6XN+LFF+`B&,M6E# +M!;R+>&*)BZ.)*DV;BSPK\8B^:4,%_8O4?D,)0BN^C'&,L(G@=\.,\R+%C-QP +MO5L-B=IVENQC%MDW5O1C"YGT0=8IN+L"L8C:9F307!C`5CH8L/BG0W +MQV1-!?B,[EOM94T%RHQ$>$T%.XP%8S",&XIA1A:-W(M->"E'A\*`V)9FJ4!@:-+&.1 +MBU2*(5Q#"5>*A'B4!AN,)D"+8U4/Z2+>(I7/X6+>XJG<5P+A8U"C(&*K7&9 +M`CR-L'&;BX>*LW&17(6-]XN-BJ1JEUR+BQ9.0PF3BJEJV@=-C:QJV@=*C<:&FXNHBM!_V@>?C--_I8TVC<"&W66V +M7+*-S(RTBN!QV@<8B\UJV@<;C-!JPER+B]-JQ5S%C89MR%S3C7IGRUS6C5J, +MCRSQB-]JFXMS,]R-6&1W"?6,PHV)B].*_7C:7-"-863=7-:-NHO* +M/4>;B_J*)')P"5.-WF-P">.-/G(`9W`)*8WD8PI=!8[,C`F+^3\)CKZ-.X*"4!#"1N+.(.)F31=-(Z^BS.+3HDG86M47?R-,V2)";>, +M9H>^BU>+%3G#BRXM6XX\9%]=7H[*BV&+>X=E76N.$6=H77".V(QKB[-'0PEN +MBQ]6=XY+CHJ'=%USCN&+=XN?@'I=?HZ)BWV+RT=WCO^-J'F#77Z.UF6&78>+ +M,S&Z8XE=&(QXAUUVC5V.CK2`D%V2CH1RQF.478Z.=&2779V.)F::79F.1U;" +M8^TI_(U]9*!=HXZ`9*-=IXX7;J9=H(Z89JE=L(ZY:ZQ=JHYK:*]=LX[=9;)= +MN8X>9+5=K8YQ:[A=N8['9+M=N8[M9;Y=N8[Q9<%=MHX89\1=N8[Y9<==OXZ. +M;CI". +M_C=;C@)Z(P7LBP5ZYUW1CIN.\HL-<^U=CH[*9/!=]8["9?-=^([&9?9=_(W3 +M9%LJ_HZNC@:,[4"EC@F,\$`C!0R,DSF0C@^,5$@%CR*.JCF]CA]%6X[H9`]> +M`8\:;!)>%H]P9Q5>&8_.9QA>HX[T9+P"88ZJ.<^.$(D/0:6.#RX3CU5D)%ZU +MB\U6)X\0CJHY!V:\`A2..(@C!2&)2GHQ7AR/C(XGB4^!-U[[CIJ+-8\/CU=Z +M/%X9CYN.,XE:@;P"5XX<9;P"_XT?94=>_(TB99`,3X^19K8&&XT]00MFM@;Y +MBSU!XHY?C#E!C(YBC!Q>I8Y.B1]>88^XC?LYO8Y8+EN..F5B7E*/%X]>+FF/ +M(VMH7FR/(&QK7G*/MV9N7G6/SXYFB<9(88],CRJ/;(E19:6.;XF4@8&/58^( +M;",%CHRF/#8Y)7H&/+X^LCHZO/98^D@8]>_7L"/.W(BSCZN/861U!:Z/[H$C +M!=&)Y8C@CU6/Z(C@CUF/]H%%#<./FX[O+D8HNF5,#CA/(C8,D.*.T2L,D(R.U"L, +MD)".0R_[CQEFB@UD(SV0O8YY.3V0GH[B*^V/19#8(D>0H8[J*TJ0_V<)".0B +M39"^;@D((9`O9@D([B)1D,YE"0CTCS5FI8YE+UB0C(Y0-EB0D([33%&0NH[D +M,F60O8ZB.66019`0(V60PXX1+&60QHX4+&60R8X7+&60'Y"2*&60SXX=+&60 +MS8\A+&60U8XD+&60V(X(,V60,8^2+V605X^`-F60XHZ:+V60C(Z=+V60D(Z@ +M+U&0/I`=,Y60O8ZG+Y60GHXD,^V/PXZ6-IZ0H8XL,Z&03I"=-J204I!3+*>0 +MPFZ)!4F0QH*)!=XBJI#BCCPSJI",CF`LJI"0CF,LIY"ZCF8LNI"]CN0HNI"> +MCN@HNI##CG`LNI#&CG,LNI#)CMTONI`?D'DLNI#/CN0ONI#-CV(SNI#5CNLO +MNI#8CNXONI`QCXLLNI!7CX\LNI#BCG,SNI",COLONI"0CGHSIY`^D.@VZI"] +MCH$SZI">CH4S[8_&CJ@L\Y"ACO4V]I!.D)`S^9!2D),S_)"KD!DP_Y#?D$"0 +M"HJECIPS_Y",CB(P_Y"0CL0L_)"ZCB@P#I&]CLPL#I&>CL\L#I'#CM(L#I'& +MCM4L#I')CM@L#I$?D-LL#I'/CMXL#I'-C^$L#I'5CN0L#I'8CNC@(M[8_) +MC@4M1Y&AC@@M2I%.D`LM39%2D`XM4)&KD!$M4Y%7CQ0M4Y'BCAG6ECO\S4)&ZCB(M8I%"D1\C8I&>CB@M8I'#CBLM8I'&CBXM8I')CC$M8I$? +MD#0M8I'/CC(T;66B +M8)^1OWR=D3,#O1/MC\-\>PGX.J.1K&>ED5>0;&"ED5N0XC0)9;9@K)%@4JJ1 +M_2*HD6MHO&"VD;ILOV"]D=QPPF#`D<1GQ6!C`R-+I9%@([J1$6>)+:>1*TNE +MD6>1'TOU98\M_H\&)?EEPQ?4D45+H9'Q1\J1AFO?8,V1/DN=D4Q.W)$J9Z(M +MWY%%2PMFZF##D9]M[6#8D?(TUF7Q8.V1!'WAD0$CW)$99OE@YI&P8!YD_6#Q +MD7%D`6&LD=:1_C?MCV)+X9$$D69+`&;'+>V1`FB=D;[21B#X-DCEFIP\)DKN1&S@7DD!FXBT:DL&18RH=DGEM]P*YD3%O"Y+T +MD>A@[67W`E(C(Y+Q9?<"!9#H8-*1ZU2YT$CDE)E +M0&$0DEMD0V$@DD)J1V%!DLYF2F%'DC5G36'_D5]E^P*OD1I$]I&>2QV2?&8Y +M&$22QF/V#^V1H9%11>V/;'8L+EJ2PF7[`C&2:F^=D>`^79(.DK`J9Y)>:_L" +M!9+.2[21Y(ODE@N>Y+2D5LN>Y+6D5XN>Y*AD=TJ>Y('DN`J>Y(_DN,J +M>Y('9IIA?I*E<&\NG9*TD7,N>Y+OD?0J>Y*Z8P,#K9!U1/:1:S5QDE62@BZM +MDIF12O3BSDB9FC"ZLD0,NG9&0+K:2QF6>&.V1M6B6+L"2%VZD&,.2 +MF&:=+KF276>@+OB1`S9DB\F1S';=90,#;9+Q1/J1JBZ]DL21K2[7DB!HV&', +MDB-KOAC&DB!LF!!0D-"2TI%"*]J2UI%%*]J2H9%(*]J2!Y)+*]J2/Y).*]J2 +MFY([,MJ2Z)$_,MJ2M)$^/-J2[Y&24MJ2IY)A3]>2]I':+@*3^I%I*P*3F9'A +M+NV//Y)Q*PN3MY+G+@Z3_V?(">.2MEH,DU20MEJ;DF0R$9-A:/8N[9$3:1IB +M^)$6:1UBK)%!17L)ZS4;D]&2`9`?C`=D120272,)!.:349,)-=<%-B))/]D3F0:G[.!<^268PZD].276G. +M!3B3=W=["4:0>G=0+^V19FE-&6N3<6YK8OB1;&EN8G&3NY'T*^V/BW=9&6Z3 +MP9%>D)%W>F)TDQIL?6)_DW!G@&*"D\YG@V+&D5,^TI$.+'>3I&1N&7J3/Y-S +MD*9WD&*LD;Q%G9%YD*QWEF*%D^B1?Y`[5):31)/`-N^1A9"X=Z%BCY/VD8N0 +MIHR,&:63F9&1D-A%>PF4D*]IL6+XD;)I$0-CDNA%/Y*=D,M^KI-?D[MIEI/3 +MDKYIOV+MD<%IJ1G!D[N1T"CMC\=IR&*RDZ9F%0.?D\UI%0,7DZ-B@I*YD-2, +M%0.RD:-B+Y*_D/)WP!G$DXIMQA'23IY+=D`MQWQG?DU62XY`6>.49[9&TD>F0!&H;"M:3 +M&'^=D>^0(G@*8_R3#I+UD'Y->PGXD"1_$V/XD19J&PI>D1AQ\Y.[DQQJ`Y33 +MDB!J'F,'E'%K(6,/E#&3#9$_<<8%$Y(%8R^2$Y%'>"YC&Y0L:S%C*91`<#1C +M+)0'DA^14G'&!2:2!6.;DB6138;&!2V26WA%,"R4[Y$ND6%XQ@45E+I->PDT +MD6=Q4&,IE%B2.I%M<3X2[9%O>%EC391ADD.1RTV=D4:1>'AB8U"4:Y),D=1- +M>PE/D6R-6!)8E'AN;6-@E-&26)&D1E24M9.&?U24$I0V8X*289&3<7]C8Y0O +MDB4M[8^$:H5C8Y36D6V1GWB,8V.4!Y)SD8Z-G9%VD:=QEF-CE.B1?)&M<742 +M^")TE+9CHS!CE*>2A9&A:E0&DF#I5:EMZ5")6%.74F"Y7$*WDF0%&5])A66H95@`O64Q91.$W:5(3)])OR4 +M)3)])O^4*#)])@*5Z#E])@6504%])@B5,C)])@N5-2R")G*5]3F")A*5^#F" +M)A65KTB")AB51#*")AN51S*")AZ52C*")B&584&")E:543*")D26U)5DD'N/ +M@B9*EH:5:I"`CX(F4)8OEH\(4Y8REI&3"U"")EF6E967D[A(0I7S"$>6[I6< +MDS)7M)2"D*MZAB8;E0\"AB8>E7XLAB8AE9=!AB96E7`TAB;UE)Y!AB8KE0D\ +MAB;\E)(RAB;_E$PZAB8"E8(TAB8%E88TAB8(E9\LAB8+E;1!BR9RE5PZBR82 +ME5\ZBR85E:XRBR88E<)!BR:4EM25TY/,C[24O)!8.A<"BR:=EMDMBR:@EG^6 +MQ9#=;(LFII;FE6JR6/)J8B +M^Y::)X\FJR+_EJ46CR:P(@.7BI8E*?^6=0N/)KDB"I=.E5P"%",*EZ252PD1 +MES0C\#B/)L4B"I=%EC5EA$!S2(*ER:5GS,5E^%>DR;HEA:7@Y5#*0J7 +M\)9&*0J76)5)*0J71`23)OJ6*)<',I,F_I8UEP\YDR8"ESF7+PF3)@:7/9>* +MEE@I_Y8#(Y,F#9Z639<9ET\CDQ:3)LDB3Y>9(Y,F +M()=2EUB5;2E6EU$HER8GEZI)ER;MEE*7(@*7)O*64I#*6^7>@:7)D"7>BMTE8DI=I=%EHPI=I<>EX\I=I*,XJ6KREOET67OV:AEWMF#Y>U*:67$Y>X*>Z6=)6[*:^7 +M:"2<)D>7+5&<)DN7KB.9%IPFP2*REUZ78P.)EY1FG":,EW%?G"99EV=8NXMK +M([V7'"2[BY:7HF;LE.=FRI>O%KN+9Y=14:J4[F8=9]`CP93Q9M&7Q93U9KT3 +M>3N[BSR7?3O6EP@[WY?.,X>7IA/8E^`K^I1J-.J7;%'DE[B7<%'DE[R7T",R +MEP]G[I>B9IB7>33XE^Y"99<69^:7HF9IE[T3J)?N0D*5'6<$F%-ZUI>H)LJ7 +M299>@40J8M2+N +MEE26/660&SM'F`DOK5HLF&XL19@OF,]1 +M19?L-#F8[B6M6L:78336EX$J[I:5EODT!)B8EOTT#YB;E@$U_)>>E@0U>9CX +MEA,4P +M+,N6-C66F.`VL"83F+`L]I=A)XF869C1*K28.I=%-:V8/I>*`1^8IBP&F-HJ +MMYAGF'`GP9@TF',GP9B4F'8G[I8FE8P;!)BB9]:7?"?*F%>7B@&?F%Y@4IB" +M)]&87I>8&\V8@)A8!*F8$$O^EXTGV)BR);0FL)BXBM:7=37BF`N7J!O;F+PC +MM":%F`(EE)B@)^F8VI?*..F8W9>G)^F8<9B*->F8RYB!0NF8Z)<2,NF8[)YDGF3PH?IEL),-:A9B8-<-:O9AQ1/:7'C:! +MF>(DPUJ/F'%$_I=,*(N9!)=_`S"9@7W6E]%K+6F68 +MG&'+6C:9\41QF"\SXIF^%LLF/)GA1.B7524"FNR7U"@"FJN8PR\"FE*8VR@" +MFO:7WB@"FOJ7X2@"FOZ7:24"F@*8;24"F@:8<27BF6>8[R@AFC28=BPAFI28 +M]BCNEA":99C,8D76ET\I1)H-F%(I?9J4F%4I +M[I9JFE.:;7Y[FHZ9)&+HB_69RDQGFI69"#[HBV68S"[HB_Z9SR[HB]28TB[5 +M)C::?876EW`I@YI(FG,IGII+FOXLH9I.FL8,!)BF1=4F>9H@5-4F@IBM1=4F +MA9@F5-4FAYD\6]4FA9J>?M4FB)IDFH*7-".5D]4FCIHOEI@.IYKCE0$!E)J2 +ME0@/PIIK+'4"DI>\FIB5=@_(FIJ+RIK>F*\V#9B=E\R:?RK*FMZ9^I>DES0C +MVT7*FH*8WD7*FH68553*FH>9"C?*FK::<%O*FHZ9$3?*FHN:[D7*FI69B&+* +MFF68?%O*FOZ9^$7*FM28^T7?6IJ:02_?6CR8TVG?6M*:UVFJE*LW_)=(3=]: +MV9J`E;$W#Y@U-]]:WYK5E+@W!YO.EKLW$YO=+=]:Z)KCE<$W%ILZE\0W')L^ +MEP05!)BX8M]:])J;E3=J#9OOE#IJ*)O7FM,W_)=EET!J#YC*/N-:TII>-^-: +M0)IA-^-:WIED-^-:>9J'+^-:@IB!3>-:A9A$1N-:AYE(1N-:MII+1N-:CIEX +M-^-:BYKL/N-:E9F33>-:99B63>-:_IE;1N-:U)B<3?B+FIJ?3?B+/)@U:OB+ +M-)L1FQ,X[I9+?_B+.ILOED`&/9L:FV1+9YN2E2$X+IOEE"0X9I#/_R+@I@45?R+A9@N7/R+AYE- +M/_R+MIHT7/R+CIGM3?R+BYH(,/R+@IL+FT4G[I:*:OR+B)L1FZHQM9L4F[$C +MNYL7F\<2D9L:FUF6U5\YMYFG!5\YN" +MF'-5\YN%F,R4>1WXF]4B\YNVFI-<\YOP(_F2N.4^4=1G$:<196$:W2<*9MKF5.<+)MNF;PJ3I5+.2Z<494Y`U:<5)7X +M'8.<-)I5.32B9PV(XZ<:)QGE:1KC)RWE*=K +MG)SMF*IKDYP`+8Z<,)ESE06;F)F0G((KCIPVF8&'CIQ,G'V5?#F6G`BP*GF:F<5Y>O.32":7#VS]G/J4$FP` +MG;J<2@9,G'E6!9O,*/&<:YL(FNF:)IV!G!J:)IW5G!V:O"K!E,(#.IQ/.P);CYB,.V<$Y90;$*= +M^9M3;%*=3"-:"E^<')99;%6=$@I:"F6<(I9?;%N="IT)ER^=TI1E;$B=$9M9 +MFF2=E#=:"CR=:YNV+$^=&IL==YMZ;'F=T)K)`U:< +M0VQ>"KR<`EY>"ERV<5Y::;#2<6I:=;)J=[YOJ+)>=G9Q/,*"=H)Q3,*.=^YQV6=0YVKE[PJJI8A +M&>B=RY?R;#2=EY@(&OJ=AIU5+>N=G9@(;?J= +M)I4,;0.>")P0;0F>MIP4;6Z<;E=G"KRRY9$;2Z>_(@7GJ`F=P&?5S*7)CLYG@.).Y[MEC*>'9ZQ6CV>YC(@ +MGH\T2)[M*D*5,SLUGB]"[)1<;5">+2M.E5]M09[F(J258FU,GN8BP91E;5B> +M)3$GC`V7"BN5EFMM7)Y]E6YM5)XR*X>7<6UJGN8B^I1T;6Z>H'(GC""7"BO9 +ME((<$9>XB9GGN.57CMRGI*5A&U]GLF:XQ^`GG>;:#M@GB:>;YL&*TF7 +M;CN)GM>:<3M8GEJ>7#%5G6UNGJJ5^!^8GC2:I&V2GOB6XQYYGF&7ACN> +MGNJ>J2K'GI4+=0J\ +ME\&>/YZTF\&>F)?;;;">'9ZZF\&>()Z]F\&>3I[`*L>>19?".[:>C9[&F[V> +M\Y3(.VZ>7IZSF.MI?V;5B>_I5.(*&>NC,_GL"8[9YH"R0GRIZ[ +M0A>>QICZGMR>T9["0B0G,9[3@B0G59?MGK&>?R=U90H;B"?SYXK;A:?[D(_ +MGO68"I_6GOB8"I\=GON8"I\@GOZ8"I].G@&9[9[BG@29.9]6G@>9.9]:G@J9 +M&RP7G@V9:BSNGJ$@*9]+ENT/\I9%G[J7[0_VEDR?/YX9F4R?UIXQU%6GBR97Y]`GP.?9TI#GP:?P%%#GPF? +M;4I#GW6>1S0'GFTK7)[#2#J,Z)9?GW">^"=UGR2?ZRY\GVN=6CQNGE6873R" +MGWZ>4)E?GQV>4YE?GR">5IE?GTZ>69E%G^*>7)F1GU:>7YF1GUJ>8IG)+!>> +M99G)++.7]"`IGYN6]R"@GYR>;IF=GUZ7_2"CG_R6`"&IGP"7`R&LGP27!B&O +MGTZ>?9FFGW"7#"%NGK.6#R&LGW>7$B&[GUZ>BIFUG[J>&"&XGT&8U`9+E\&? +M!YY/*%R>I)@B(;N?<)Z;F<&?-YXR-LN?SI8K(;N?/YZDF<&?UIZGF<&?'9ZJ +MF<&?()ZMF<&?3IZPF;6?XIZSF>:?5IZVF>:?6IZYF>@J!YZ\F>^?GI^_F?*? +M@IE,(2F?PWPX)VB?55(7GLB9]9^,F=P&;I^SD?V?<9_B-"">T9G_GQ"572'X +MG[>48B$,H.V892$/H$Z:%6]NGL=GC@KZEO^?PI\/,UR>>SP7GC,L'*!:G'(A +M$J!>FG4A%:#2E'@A(Z`WGD$L(*"`GZHO+*#,*HX*:Y_GD1Z@`J"D8!Z@!:!% +M2R">%9T9H$Z>")K_G^*>"YH_H%:>#IH_H%J>$9KH*FR>%)I(H)Z?%YI+H/:? +M&II.H'$D-UL&EU&@G!8W6R*85:#6GB.:5:`=GB::5:`ZH/N??$L7GGPL7)X6 +M:#=;-:!_2T.@.*"'2Q>>Y)91H$N9OB$IGR-H;:!$GNA@99Z3+&6@(:!#FF^@ +M;)Z:+'F@N9W-(7*@))^A+'^@KIA;/6Z>5R4_G@F7;Z#6GA`PA:`=G=HA@J"$ +MGA8PCZ!.GF^=4:#BGAR7F*!6GG6=F*!:GFB:Z"T7GFN:Z"V>GRJ7I*#VGRV7 +MIZ!2H`,$3Y]X?3^>3"E*;&@HYP-(BF?XTN5"C*@P#7%E!,BQZ#%GZ6=OJ`'GER7OJ!LGIV: +MOJ!PGJ":OJ`WGJ.:OJ!WGGHIQ*`7FP@$&*"C1-:>@"G@H#J7"`2WH*M$%YZ& +M*>>@(YY\EZJ@XIY_E_&@5IZ"E_&@6IZ%ER(N[*#*H*MH8@EHH+J28@EKH-R9 +M3"(IG_8U48QXG[:+UIZF*5R>YIE2!TN?MHL@GN2=0BY$G%('XZ#:A%&,M*#I +M1%:>JY<3H1.@KI<=H7"@L9<@H'28REPH^.:'CE35P/:%%,49;#Z'A1&F7.W!` +MH50T1EL6H2%%[)0=/D>A29=%<%B>2":DE2,^*9_9E"<^5:&SEV('8I\&::J4 +M4G!NGB]%1EMAH%(V1EO*H-IA1EMHH#Z:/3Y8H9><03YKH4:7!Q +MH>V8;'!TH4Z:;W!WH4N9:T57C&6A/J%"*I.ADI60<&ZA/I>3<)RA0I5_ +M!PBA97=;C'6@9'Y=H6:;MRZGH:V@^CU;C$JA"UNGH1FA78RGH>J@=W=;C%2@ +M`U1;C%B@9XRGH5NAE9JW<"F?F)JZ<&Z>FD5;C,J@^4ZC[XH5.AW9[81:X*HJ'"?EVAPYL]+Y86K@K9H>%%5J')FP>B.Z'LGKN, +MK@JQH>R:$'%NGN^:$W$IG_*:"`&ZH:]B3*'#F$XO3I4(`<>?YG>N"F&@_IH( +M`B88"\ZHA.BFJ$0*UR>"G@ZHK>AKV*@H2R?9DVP"ENA:4VP"B.B^8Q3 +MH36?5S>P"LJ@,IM9<6Z>-9M<<2F?.)M9/URB^)9Z%>G_,^8`E;H5F;@'%Z +MHH6A1$Q%HHZA[">+HN>A=)_!+SNA/YG!+YB7Z15WHF67 +M[!5WHD6A29G(+UVA@"N.HM":)02QH:8W(:**GVIQGJ)*H@ID.,,&4(Q;'HJV=*@2QH:V;*@2TH2=)U5> +M6ZRB)UR+H:PRVJ*.H9&9#C!6H6[ZBY93M<<2B +MF)5)%M"B^:'"=:AFV-=H>R<5S"%H?"<9#`GHZZA"YPO<@BCCJ$?H&TP)Z.I +MHOIX)Z/=HOQ_P0I;H1J<0'(BHT6A+J!7,*"A*#-(I5\S'+#HYV8SW+)H_LF;EO[GT]D;ELRH+M' +MJ:.DHW.>.Q?,HS>ATZ`,3X&,K:,^H=F@2%V!C+.CJWF!C+:CKH"!C(JCFFN! +MC(VC4&V!C,"CH94%"%:C4Z'PH$16@8QJHZJ5)P1MHZV5_W)3H["5`G/QHV:B +MFBEVH[:5%@C_HVRADI>W,6^AHRD"I'*A"Z$(I-*7%',%I'BA$J'-AUVAI)<. +MI'^AZIT.I(*A'*%?.86A'Z%?.8BA(J%S5L\*]J..H2BA#J16H?@]"Z07FS]! +M$:3%G35S+J28HC6A#J1IESMS_*.8E3YS$:1%ET%S-Z1JF$1S/:2`FT=S4Z/! +ME$IS0Z2SETUS5J/[E5!S2:0TFE-S1J1>EU9S3Z2,F5ES4J1K"]$*;:,*EE]S +M3*1$G&)S4J0+EV5S7J1.E6AS7J2DE6MS7J1$I),M=J,FM)SOJ3Z +ME-5SOJ1ZI"$GQ*1KG=MSOJ2`I-^AHZ07G`)"QZ2&I.6AUJ0^E^=SOJ1"E>IS +MM:0[I&`XT*2R*]P*;:/7G6<$SZ-NI-2>L'K<"J2CFY9G!*>CGI;_854)6HQ">2@3SI,Z6FP+) +ME[E[Y2;`@JE +MH96;`@:7X3*JE)L"(ICU,LND^)CU,GJD^YCU,MF4FP*\E_4R@*0!F?4R@Z0$ +MF?4RAJ0'F?DR0*4*F?PR5Z7HEO\R[)14!.V6`S-7I?*6!C-7I?:6_S)$I!F9 +M#3-7I?Z6_S)NI!^9%3-7I3ZE)9=4!$*E_&6+6PV7_S)ZI"R9(C-7I4RE0'N+ +M6QF7_S*#I(JB_S*&I(VB_S(UI'2?-#-`I3^9-S-=I7N?.C.+I6*E5&V+I66E +MZCIN"?J65C/+I%"95C-ZI%.95C-*I5:95C.`I%F95C.#I%R95C.&I%^95C.( +MI7VE<8*+I8"E8#.+I567:C-BI&N9:C-EI&Z9:C-$I'&9;C-`I729<3.^I9*E +MBC-QI'J9:C-TI'V9:C/+I("9:C-ZI#\H>`&8*[ZE<:6*,X"DBIEJ,X.DX**. +M,[ZE2Y=J,S6DRI]J,^"DF)F7,UVEFYF:,[ZE()>7,V6DH9FA,T"EI)FR,\ND +MIYFR,WJDJIFR,TJEK9FR,X"DL)FR,X.DLYFR,X:DMIFR,S6DN9FR,^"DO)G! +M,UVEOYG!,V*DPIG(,^REK:6B9D2DR)G!,YBDRYG!,VZDSIG!,W&DT9G9,T"E +MU)G<,QRF7Z7@*WJD[)SB,QRFE:7.,X"DX9GH,QRF:Z7@*X:D'Z#N,QRFTJ6B +M9N"D.BS/I8Y17:4]+#:FB6:2I"N@^C,J3#H+*F +M2J5.E[*F@*2?G;*F@Z2BG;*FAJ2EG;*F-:1J2KEPNG2J6NEPNG +M@*2QEPNG@Z0EH0NGAJ0HH0NG-:0JI`NGX*0OH>ZF.Z0"GCFG8J0UH3FGI)5( +M=AUG+C6JE$QV0J<>;_J44'9&IP:21*>FD6<#$W9,IR:F,9E;=DJGMUE,I_&F +M-YFVC/2F(79,IV6F3RVVC/NF?TOLE*5$$9=.-4Z5<794IVR@MHQ`IL=2MHP' +MIW]+Q91Z=FBG5R65EGUV7@W9DI^A@2*<+F$XURY:*=G:G +M:YV-=H2G,*"0=H>GQ9V3=HJG99>6=HJG:9>9=HJG0I6<=H>G19?C1'VG49)F +MI[HMD*:%-4"GDJ&4-42GKC20II$U0P68H:8U"*+V1)FG4HM$I]XFI*?XEK1V +M:*>RH+=VLJ<^G+IVM:>7G`A%N*?+E\!VJZ?`-6*G;YN\-6:G^2:OI_F;RG:^ +MI\B@SG;(IU2F+PU)I4C1ZG.)V +MNZ?/GC%%U:>(I]*ATC5$IX@JW*<=G(F`(VYJ=@I_V@546^IP"A644!J#2:S`)`I@:A8$4$J/R6 +MS`*HIM5$CJ>ZFPTV!)=I10JHO*?@GA`V8J?#FQ`V9J?&FQ`V0*?)FQ`VP91X +M112HNIZ+!%>G_YE$I]*;&38HJ&6F+:$HJ/ZGTI18"".H@J?&F!`VV92+!`>H +M+Y:+!&ZG'2:8EY)%(ZB.IPR?$#:1I]>8$#:4IX4GD*9()F*G])L^-D2GX9A! +M-DVH4:>7%$,%Z)A--E.7T0(FJ#":4ZCXIW5,3:AEIF.AT0)@IV:AT0+.I[Y: +M3:B@IB=^3:A`ID%%4ZANIX0F2J@-J&8V4Z@.IS2%0P58I>]A=:A;I2EI=:@@ +MILU:=*<3F7,VTZ<6F7HV1*=HI?YA=:A8J-64&PM;J*E,A*A>J#FH)9ES-CVH +MVR>0IG":A*AGJ'1%=:AJJ)B5H7>^ITV,A*APJ.^4&PMSJ&!P1*>)I0A;O5MY +MJ&"3O5M\J-%,@J=^G]\VNI=?"%&HCYI?")BENZ&]6R:HE9J_=TZG'%N1IZ&E +MB'>]6V"GQZ%?"&2H@X6EJ)>HS:$A1KZGJ)K2=\NHS*=HF>,V=*>VI4EBP5MY +MIYM^P5NIJ#\^2*>_I;E%P5OKI[V:(`NSJ#FHR*5+6\%;N:B2E2`+BZAA8L%; +M9:8/342GU:5$5,%;Q:BG:>^HR*BAE2`+0*8]J.&EH")N$1B"IUJ<1IO-^$*G^J(FH%Z8\ +MHCMX**F(IQVF_W!#!=>9.S?IIR.F8$TVJ5&H(YLH"Q2I$'ABIQN@.S?VIR^F +MG50VJ66FCJH.)LH"T"F.YLH"VZG/ILH"PVH09MG +M>+ZG1)MJ>%ZIBIAM>&&I]9R:%`NI39MS>&2I3IJ:%%&H4YN:%$"I07A$IU^F +MXEO9C(NH7)N:%$FI@)6:%&"G8IN(>&BG.HW9C%*ISI:.>&JIF`O9C%BIXY64 +M>(6ICJ=ZIG9&W(P$J5I_W(S9J$Z-1*>#IH!&W(SKIPE,FPH$9::/F[5XI*F`F`H$Q:B5F[IXJJFYIY2@Z3=BJ:6FH4:5 +MJ0VHH9O%>+"I:ZFNIAI5T5N3J:J;>`B[J5R=T7C#J=.GNJ:0AD2GO::?<=%; +MH:F)J,.F?Y316Z>I.:C)IL9&T5NMJ>BHSZ8'3M%;0*;/1M%;;J?.FW8(N*FA +MJ-NFN'_BC)"IE*?AI@"C\P(+J=V;`7EHIZ*4!'F^IZ:4\P)PJ4`PXHPFJ.F; +M\P*+J+"4\P)EIC%.XHQ@I_*;%'GSJ429%WD%JL:GA9=,.%:='7D(JJV=('D. +MJL2ICY<+J@.:)GD1JGNG%*>D8WP7[:F)J!JG%$=\%U&H^7]\%_:IB:DCI^*4 +M.WD1JI&G*:52G+YP)`ZBF_90) +M`W.H`)6U1ZNG`Y59>3FJI2B8EUQY1:H^G%]Y2:J7G&)Y3*K+EV5Y0JKF*.R4 +M:'E2JD29:WE/JG>7;GE9JL&4<7E9JL64='E9JI66=WE9JB:5>GE6JDB8?7E9 +MJOJ4@'EHJKJ<@WE9JMF4AGE9JC*7B7E9JD>J@*=1@-U;AJ9!:]U;4:?D5=U; +M0*E':]U;5Z=*:]U;6Z@#7=U;,J:N%-U;^Z9,CJJ4L01DJ*6CL01GJ*BCW5LV +MJHVCD*I\G@XY"Y>^>9ZJ[9C!>4*J +M<)7$>:ZJ.IC'>;&JJIS*>;2JOI[->:NJS:/0>;JJ7IK3>;VJ;*I[FZBJRY91 +M!)6JB95#2+>JAJG>>;VJ0I6`!-FHLW*0JN>G +M#CE)E^]YMZKSE/)Y0JJDE?5YXJJSE_AYY:J"F?MY.:JME6I(Z*JG)=$'QIYJ +M.8R9@`22JK:5NNJ +MLJH6J$I/](RLJ%,Y8ZH5)GH(JV.<*7H9JZZ8+'H< +MJ\JJP)CRJL6=,P;UJI*5-7H?J].JR9@BJ]:J>2<"JYN5/7KNJMVJ0:CSE0X# +MI*I=JD>HQCE3E[I(0JK[E0X#?*K^E<%(/*OXE@X#@JH$EE5Z0JOJG`X#B*H* +MEEMZ2*M0JO68QCFIJD6EMCE.E0X#E:H6EF9Z3JM+F6EZ6JM@JE*E!D&0JE6E +M)XC1!W:H*HB0J@V94:MLJA"94:O$JG^H+)9^>EJK=:J%J!M!9ZN%JC66AWI: +MJ].J(IE1J]:JD*C[762KDJJ`G9-Z.:J#G99Z0JI@JDA,H:I(E@])AZM7EQ)) +MC:LNF:!ZD*OOJJ-ZDZO[GJ9ZEJO0JJ^HT4_3JDF9&#H0E60(@JI@EF0(A:IC +MEK1ZDZM:JK^HN$A=JJ2E$CI@JJ>E$CICJJJE=HCP6S:J=I_&>JBK;*K0J,E( +M\%L_JEXL*@NDJE68TGHYJHAL*@L-J\B=*@M\JHR/*@M_JLZ=64F3JT67X7K$ +MJ^^4Y'K0J^.JV:)!.I"J\*@Z5]JKDJJ;ENYZ0JJ>EO%ZX:M#J_NHJ8\J"SRJ +MIY;*!#^JJI8?`Z2JK9;_>N2K]9P?`PVKLY8?`WRJMI8)>_*K5IT->_NKNIX1 +M>SFJOY85>P&L6IP?`XNJI)@<>_ZK;*HBJ:!ET0<+IM=L#JPVJA:>#JS^JMR( +M#JSIJR:K+ZGB;`6-[ZN8E=($V*KHB`6-]:O4JSJI;E"]?G`!)ZP*`**HBP$K +MK`H`-'\$`2^L+JQB`BBL,ZPJK)(%+P(=>58"YW)Y`3NL"@`?0@T"/ZP*`+L! +M3B%#K%D#1:P[`$6L/JR\#2\"N@'7"FI.+P)/K#ZL.@@[`#VE#@&Z`:P,5ZST +M`?9$D`);K`H`A'H5`E^L7JQ"8N@$01.+#8P,9JS,`7-,,*S6!/@!"!$S"&ZL +M]`&(?[P!".W@!`G8(BP-YK$0$X4=@K%IF7JS-H/VJ)@+2!D<*A*PB +M`E5.!`&(K$*LNP%0K(RL"@`%"#RLB@T!`F<$P`24K`\":G@LK*TQ7JSV-SL` +M(4A$!"1,(`*@K$*LY%U(K.1=/JQW6_T*2!0[JD,!JZPNK)T'H:ROK"ZL14\[ +M`$P3%0LC114"MZPNK))IM*R2:2ZL>0V\`8=,S`'^#"L)PZSX`0!&'@''K"JL +M-JD[`-IX^`'D>1(!SZQ"K!$!)`*4?R8"(W.0`M>L/JPN::9!5JS)`R0"X4$F +M`C>H+*SS`WP!5ZD$`N:LFZQF#R%(=`$/21X![:PNK`8!+P+22E8"BPT_`_6L +M,0.+#2,K^:Q9`Z--P*Q474*L['G,@`$"U0@W#02MS`$V"X@2"*W.K`@1T*P, +MK5ZLE4^=K)5/7JQZC6H-[P$=?14"%ZU"K!QMA`A\`=50TK.LG +M/JRF352LIDT^K)87!`M'!=H$!@LMK70![DHD`C&MFZQ\$,IY`0+Q>@0!.*TR +MK%4.61.,(\"`'@$_K26M_!Y=!"<7G0=\$$:M>*RP@C]X&`'O>`0!3:TJK(PM +M)GG,`6H-$QU4K5.M.(_B!#L814]#`5NM/JQ^G52L?IWPK!LA\DI$!)-S$@%F +MK=JL'`60TK`.' +M*JQT;,RL=&QUK-D%=ZPAK902?7[6K#=>YW(7`J8!>P6-K0X!@41Y`9&M@*PL +M&6I(#@%*J^T!F*T^K#D[[D&7K6!_G:Q@?X^L[V)]`J4+!`OY#::M%P+E0"`" +MJJTJK&("$@$*!!X%77=P`;*M$ZT_"%2MDZS$(52LQ"$EK;`8701R%*!Z+P+` +MK2ZL&Z*TK!NB(:U@"U`3F1:+>$ZM/58NK,.38']T`::ILZT'67^ME!(M18.L +MN&R!2Y>L]@/M`55%[*QS=)VLP7SK0X!?0TW#?>M::SE)B.M%1=G3G.L!#=>K;$%S',/`C5" +M>0$%KDJLLQ2Z`>X5_@R-!0RN60-M=PT"$*Y0K=:MG90/K?4?]*OX`8*`(`(: +MKD*L`@J)K!ZNHZQ%$3@+>1,X"W\.):[GK4(>8*TP"QL+[A8LKC$#?WC(K!5) +MSJU\$/@&#PO^#$D--Z[EK+-HWT31K:$W/@B/`3)W3JTH!<:LHP_,K*,/7JPO +M!)VL+P1>K"H$8*Q-K@^M*PFD20"M +MK`S/@'&LJ7Q(K*E\HJT;(2-S?*QV@9Q))@)D3K.N4"-;3W`!RJXJK*L".*S. +MKN.MS!$%"#$#>$$$`=6NF:Y`'XVMYZT@<%2L('`JK+H!N*S@KH.MDJTK44BN +M?PZM>8JN''>=K!QWPZU+)M(&;1^$?Q(!\:Y"K%Z32*Q>DRJL[ZW,K.^M0JS> +M=K>N$1W10>FM"AXJK,!ZS*S`>@.OJP5?"(87U'@XK%>,-JQ.(1%Y;*U7H8)( +MJ:Y!I>&M\0I=24,!&*\3K>JLNXM"K/D0U*P?K]JLJ!"502("`44D`B:O_*Y6 +M#:F`]`%004,!+:^GK`4,_0K=%^*I3JTY%VVL+)*TK"R2*:T;(00+3!S+1"RL +M;QLJK"U+S*PM2Y2M[JP/(?RNS!'`#403G*0!KP\8)D*\`5"O/JQ*=]VN&`L; +M"Q8&5Z],K3"KLJCAK%`3LZU>KZVM31+">`\"@DB0`F6O7JP@1.&ML`;H!,X$ +M;*\7`@RMP*S>?KZL;04($4079T[RKOLV_*ZN!KV`N*V,#/9!S`$7>4ZMB05G +MKHIP5*R*<$BN-`<52.RL!'(S!GP3B7TPK*:M_*[B#<`-2@NW@4"M&P<.`2.N +M'ZT]"U\(11&=KY"M]HUV"/\61TLHK(,-7JSKA-($_Q9M>YFMZ(5>K-%_G:S1 +M?YNL;`A#2.RL5AITKG\3-Q;L"KFO]`$+".T!O:\NK,)M_GS4KAG&`':!!X2TJ_4KA("0*S6K\JLEP-YK.&L;*GZ +MKH(+^`;.!N"OGZS2!A(!D4Q&K#JHMZ[,"L],0P'KKSZLD@4$`OX,&!>/0>T! +M\Z]2K&P(2Z5T`;ZMUJ[Y$,:LLJCZK@87JRLJ>NN=0GW +MJ]"LC`@->R0"#K`/K1<-CDEDKQR!$:U$%M*`D`(8L*ZO<:T_B&*L?R7H!-,6 +MBPV%`2*P`0)]?BBL+B_2K!T4>']QK+^72*R_EQZO2"(9@0>M^`;RKC2PBZRW +M`R6!<:RQC38+@@LT0>6MH1D^K*L"::Y"L-JL7B"/02("NJ0!KQ,%Y$&+`4RP +MFZW5"OY!5@)!I7"NN@%(L)5$EZZ!!U0$E1!:L"ROT@;TKUZP):U9"UT$DQ9& +MK4VP(W=3KST51JWAK(\(+*QLL"JLM3731%JL?P,GKW.P;["H!?9$>*PAIIYD56`N^M$:X($9>L_8S=>)"MUUWS`N`7+'F2K11A2*X] +M%9AYBJXM."1(?*R:S$##7L@`J^P#ZT^&0:L(@(&K`^P&8&GKTP*/GOLK/$!P:V] +ML%ZLP(?6!`,C:@VN!<2P?`'B!/\4R+"IKE2/G:Q4CV*LRPELKR6PM9322@\" +M1TNAK)@.+JQU:VA+;Z_:L-T=PZV9!\Q+]JV@?YNP,*TQ@;2L,8%[K8P7@'[T +MK#2&?:TB%-A^!`+PL"ZLCUKA?O0!8'^0`O>P*;#+KB4:O8!BKEQ'`*U8+95/ +M,[#.!L<-T`:91!&N_PZI%:@&W!4+L=FP)@9]#=H7Y'+8K%\JVJPH#J9!!*ZU +M-95!O*\7&2-S^:]Q&X]!&+'N"9Q!^:]<;+JDW:R($LQS9ZY5L%2L5;!2K.,* +MFP)5"$&EZ:WBKIL"K@8UL9.L_*\GK?0*700@#CRQ;JX_@%>L?`%-K$VP;8`^ +MK`(*!JY'L9FNMP.F`8(#\:\&KL +ML41RL,(,RT3AK&,T>*=RL$$9VT1AL08+TT31K9L#DJUKL7^MY0]%".6LQR&% +MKO\$BP2.#W6Q#ZY/`I*M>;'?KN8*5GH>NS@1_>.ZMKH?+K40$&GFLK'<.4*T_"(ZPP81]0$\`(";*?K%I4Z["&K3*M +M\@2#K!Y4(ZV2!7NM)QHW%N^P]%69?FVL]+!])LZM'13@KRRPRPF$?P.M@P<5 +M`EY.%P*+3AFPU!TIK_*N(49ZK_ZPLP88L$BLB[&/3URM`;LO3`+]"L(!I@'<`7D)GK+-`2(;W@$["*.RI@$.`=P)=+*MK]P)+P*L +MLG:R/PC<"0$"W`D$`K.RK[*"LJ`XK[*3L@,8W`F6L@88W`F9LBTYK[)P`=P) +M]`'<"14"QK+-`0D(Q0%V`OX,G;*((U@:SK+_`6R%0'] +MLEH:![,`LVX(X0'HLM0!"[-Q!PBS_0H1LPNSL`,2L]@'W[+ELIVR`[.@L@NS +MX0,7LQ^S"[/J`Q>S([,+L[D!'+,GL_6R.1?WLOT*]`(9LU@:]++9LO2RR;+Y +MLAT"'$0%LU@:`K,VL[P".+,G1"RSM@8]L\@%#;-8&A2S];+*`C^SX`$OL_>F +M/[,6LP"SVK(2LT^S3K,ALSNS4[/EL@^S4P*IK,$!Y;+YLOH!]K+>`?P!GJZL +M`5VS#!M?L\FR"K-=LT"S9;//D[P!:[-VLHT'PPET`<,)K;*B06ZS>[*\06ZS +MM+)_AFZSM[)P",,)D[)5",,)EK(*"<,)P+)=%,,)P[*.AFZSQ[*2AFZS!`'# +M"?@!PPE#`9&S;K,2`<,)60/#"2`"F+-NLR0"PPDF`L,);+.DAG:R!@O5DW&S +MJH;5DWFRB`MVLP\+U9-YLQ(+U9.WLA4+U9.3LA@+U9.6LHL4U9/`LHX4U9.( +MLR(+U9.+LR4+U9..LY!&HK.2L^M&HK.5LPQ'HK.9LS5'HK.P!G+LSX6 +MP!G.LV`3P!F@LT06QA&JLF03QA%SLV<3QA%VLVH3QA%YLVT3QA&WLG`3QA&3 +MLG,3QA&6LG83QA'`LGD3QA&(LWP3QA&+LW\3QA'"LX(3QA'%LS`+QA'(LS,+ +MQA'+LW`6QA'.LSH+QA&@LST+R1&JLN\!R1%SLU\AR1%VLT<+R1%YLTH+R1&W +MLH86R1&3LE$+R1&6LE0+R1'`LI`6R1&(LY,6R1&+LY86R1'"LYD6R1'%LYP6 +MR1'(LV@+R1'+LVL+R1'.LZ46R1&@LZ@6R1FJLG4+R1ESLZ\6TQ%YLQ@7TQ&W +MLAL7TQ&3LD0)TQ&6LDL'TQ'`LLH(TQ&(LR<7TQ&+LRH7TQ'"LRT7TQ'%LS`7 +MTQ'(LS,7TQ'+LS87TQ'.LQ`?TQ&@LST7[&*JLJD&[&)SLT07[&)VL[`&[&)Y +ML[,&[&*WLDT7[&*3LE`7[&*6LE,7[&+`LE87[&*(LUD7[&*+LUP7[&+"LU\7 +M[&+%LS@?[&+(LT`B[&++LQ6R[&+.LT(?[&*@LT4?!A*JLD\'!A)SLZ8%!A)V +MLT\?!A)YLX87!A*WLE4?!A*3LE@?!A*6LEL?!A+`LEX?!A*(LV$?!A*+LV`' +M!A+"LV;)^B-T1LK*!B-T1@+*$B-T1D;*'B-T1A[**B-T1,0/=$9FR8E5M>17B+5$M148WQE'M?X3WQE* +MM6$*WQE-M1$=WQE0M2$8XADAM6H*XAF&M6X*XAE[LG,C([5M!N(9++7E#^(9 +M+[5I#.(9,K4V&.(9E[5P#.(9FK4=%.(9/+4G&N(9H+5[#.(9D+.S`42UT`;B +M&4>U@`CB&4JU*Q3B&4VU+A3B&5"U,13E&2&U8@P2Y1F:M:P,Y1D\M;`,Y1F@M3(0Y1G4 +MM;<,Y1E$!.491[7)"N492K7,"N493;6!&.494+6$&/XO(;5(%/XOAK77"OXO +MNK5.%/XOC+7>"OXO7[5]LQL'8K6`LST)HK6#LYBO*+::M>P*_B\\M6$0_B^@ +MM64$_B_4M8H@_B\(MAL'1[7Z"OXO2K5O%/XO3;5R%/XO4+5U%`"4(;4("P"4 +MAK4,"P"4NK6KLZJ)`)0LM1,-`)0OM1<-`)0RM8P0`)27M1T+`)2:M940`)0\ +MM94$`)2@M;@@`)34M5`D`)0XME4D`)27L_)XHK6A%`"43;6D%`"44+72L[Y8 +MHK75LYYY=K8FMMAI9 +MHK4OM$9_T+:DMA$%(;4UM"19HK4XM*^O&PH[M`:`V;8LM;@-W+8OM3`>W+8R +MM?0DW+:7M441W+::M7@HW+8\MLU^"V;;4MNH$&PIEM,>"HK5HM-J"";(-!K7M6<>!K>:M5D+!K<\M?D-!K>@M6`+!K?4M6,+!KP1$90OM6$.$90RM>X6$927M6H.$92:M0T%$90\M7$.$92@M2L) +M$934M<`($90XMAP%$91KM@02$93.MG\.$90!M_44$934MC0'_QE5M3`%_QDF +MM30%_QDIM3@%_QDLM94._QDOM9D._QDRM1X2_QF7M2$2_QF:M?P>_QD\M2<2 +M_QF@M=8'_QG4M;$._QDXMI,)_QEKM@X;_QG.MNPE_QD!M\`._QG4MJP"&PK" +MM.R.HK7%M`B/R;7M7L%QK>:M3(B +MQK<\M>(.QK>@M>8.QK?4M>H.QK +MMJ%:"AJ>LZ1:"AHDN%.U':_&!0T&5[@JN%FUK5IRLJPFE;6L)EVXD0%7N#.X +MRQ-7N#:X-CM7N#FXPQ)7N#RX)@97N#^X!0Q7N$*XU1-7N$6XBP-7N$BXC@]7 +MN$NX$R-7N$ZXEP-7N%&XVB97N"2X'PPBE">X(PPBE"JXL++XBUVX*@PBE#"X +M"14BE#.X`1@BE#:X#A4BE#FX008BE#RXMP,BE#^XGK6WG(ZXCK/KG(ZXDK," +M6XZXE;-<"B*4F;->"HZXG+-E"HZX;+/8G5VXU`/&!;6U)XQ?N+BU*HRWN"VX +MO;5U"K6X@K(D)[6XA;(D6[6XB;*`"K>XF;(ZC+6XP[*'"K>XQ[(X)[6XI+A$ +M&+>XI[C7M4B,NKA+N$<*M[A.N&^STPHQ8ZVR>EM=N-0,,6,MN-@,,6,PN-P, +M,6,SN.,*,6,VN.8*,6,YN)D',6,\N"VVBP(_N#"VHR?DN*2X]`HQ8Z>X]PHQ +M8ZJX.[:+`JVX/K:B6S%C4;AO$#%C)+BCL[:,7;A^!#1C*KA\$#1C+;B&!#1C +M,+A1MD,%,[A4ME.H$+G(N+>SS8PT8SRX7;;!6Q"YT;C`L\NL-&-%N&:VV8P0 +MN:JXGA0T8ZVX;K;BC%^X<;;76S1C)+@[#3X]K,< +M*$JY2[BXY!`SE"JXJ[9-!2VXKK8AC5VX +ML;9-!3.XM+8HC7*YR+@7M"^-7[@:M$T%SK@=M$T%T;@@M"E<,Y1%N,:V305( +MN,FV305+N,RV,EQRN;"X+[1&C7RY)+A-%CXP+;BU#3XP,+CAMI0&,[CDMEB- +M7;CGMDYY)+@%MVI<7;C9#3F4*KC=#3F4+;@.MW-5Q?N'2T +MB8W+N3FX&K>K*+ZYSKA]M)*-.91"N".WMRB^N:>XAK2.7,NY2[@LMY%X.+>HC5VX.[>KC>VYM++7*.VYPKB""T4PQ;@2"D4P +MR+B^%D4PR[CA!D4PSKC$%D4PT;C'%D4PI+B5"T4PI[B8"T4PJKB;"T4PK;C3 +M%D4PL+@O"44PL[BE"\8%9;?(7%VX:+?+7!JZ>[+.7!JZ\;FS`1JZPKC_!!>Z +MQ;CL%A>ZR+CP%A>ZR[CS%E!C=+)@CEVX^+=973*Z'KKXM&J.4&,PN`&X5JY0 +M8\6X`;5RCE!C.;@*N&M=,KK.N`JU<5U?N`VU?8Y08T6X%KAW73*ZJK@6M;A= +M/A)QL[M=/A)YLKY=/A*RLALJ/A*`LL1=/A*1LM"./A*'LLI=/A(UM;JTLHT)>;J"LF4, +M;KK#M3*/@;J)LBY>@;J9LC%>@;K#LC1>@;K'LJ$J@;J.LZ4J@;J2LSQ>@;J5 +MLZPJ@;J9LTB/@;J;KI,"C$2YK6DNJVRSK"DNGNR6(^BNGRZ +MJPJDNG^Z1""DNHBZ[A*DNHNZO`JDNHZZ1!2DNI&ZPPJDNI2Z>!BDNI>Z"[9Q +M7J2ZGK9T7FRZ$;9W7J2ZI+9Z7F)C5;K5"F)C6+KEN(!>;KKKN`0KU;J%L@@K +MU;J%NH.SEH]B8VJZ+;;&`L6RQ@*.NO$*8F.1NOZXH8]LN@&YQ@*7NCNV)RMB +M8\:ZL!AB8YZSK8_KNLRZH[,T*VZZ$;FL7ONZJKJKLW4%?+JNL[R/,1*QL[^/ +M!;MDNE>VOU[[NHNZO;-U!8ZZP+-4*P6[D+/1CVRZVAAG8W2RWUYNNCZYR@)8 +MNGNV00T;NW^ZX;/SCVRZY[/*`HBZZK/*`HNZ[;/]CV=C<;J3MOY>&[N4NO:S +M9@TENY>SR@*:NORS"U\EN_6Z<0UG8\RZ9[FI*VZZ:KF*#5BZJ[:2K$.[?+H. +MM""0;+H1M(H-V;H4M+TK3;MGNKJVP2M#NXNZ';3)*TV[<;K#MHH-%+O&MHH- +M"+:=#4V[-[O,MCM?0[N=NB^TWBM-N\RZJ0UM8U6ZK0UM8UBZE;FQ#6ZZF+E/ +MD':[?[I!M%:0;+I$M%J0?;MGNNJV"0AJNNVV"0CCNO"VRPUVNY&Z4[0)")2Z +M5K0)")>Z6;1L7WV[QKK_M@D(];I7(6UCS+H%M^$-5;J_N>$-6+K"N>$-6[H. +MM^$-7KH1MRT\`ULNGJTX0V+NGVTX0V.NH"TX0V1NH.T +MX0V4NH:TX0V7NHFTX0V:NHRTY*VQN_6Z,K=/+&ZZ-;>)!56Z.+>LD,J[JKIZ +M!G5C?+H&`G5C?[KUN8D%V;KXN8D%A;K[N8D%B+K^N8D%B[H!NHD%CKH$NH.O +M;+H'NHD%E+H*NHD%E[H-ND(.Z;O&NE^WB07UNF*W@RQNNF6WARSYNZ>ZB"-Y +M8ZJZC"-Y8WRZ(KIY8W^Z);K@`MFZ*+K@`H6Z*[K@`HBZ+KK@`HNZ]A9Y8XZZ +M$P5Y8Y&Z=0EY8Y2Z_Q9Y8Y>Z'@5Y8YJZ!1=Y8YVZ"!=Y8Z"Z"Q=^,!F[-@=^ +M,*>Z.@=^,*JZ%1=^,'RZF[22!7^ZGK22!=FZH;22!86ZI+22!8BZI[22!8NZ +MJK2I#FRZK;2M#D6\%+NVMY(%8KNYMY4);KJ\MYD)?C"=NKRTD@6@NK^TRPX9 +MN\*TRPZGNL6TRPZJNLBTRPY\NLNTRPY_NLZTRP[9NM&TRPZ%NM2TRPZ(NM>T +MRPZ+NMJTRPZ.NMVTRPZ1NN"TRPZ4NN.TRPZ7NN:TRPZ:NNFT8&!LNNRTRPZ@ +MNN^TFP49N_*T:F!LNO6TFP6JNOBT<6",O%ZZ`;AU8&ZZ!+B;!62Z![B;!6>Z +M"KB;!6JZ#;B;!>.Z$+B;!7&Z$[B;!12[%KB;!6*[&;B;!9>S7RV%8WFR8BV% +M8[*RDQ>%8X"REA>%8Y&R;2V%8X>R<"V%8S6U2V%8S^U +M?"V%8Y"S?RV%8PBV5`^%8ZZ\ABV%8YZVB2V%8YZSC"V%8Z2VTY&+,'&SUY&+ +M,+&\6;7'%XLPM++*%W*RXV"5M>-@Y[QEN'L/Z[R)LM(7Z[R9LNU@Z[S#LO%@ +MZ[S'LK$MZ[R.L[4MZ[R2L_U@Z[R5L^87BS"9L^D7BS"\;`IU$KBU1V%`O;2\O;42+CZ]&;TD'4"]'+TJ"D"][[S?$D"] +M\KP[&$"]];P?%$"]^+PB%$"]^[S5N&*2Z;S7M30N0+VNO-RX2Q@^O0>]X+5O +M85V]V[RCNE88=1+HM5D8Y[SKM:,);[WEO*ZZ_P(9O;&Z@Y+IO.(0;+WOO#L4 +M;+WRO+2Z;1AYO<:\`+9P&&^]^[R]NF4N>;W/O(<;;+VNO%X@;+W5O,(,;+W8 +MO#P$;+W;O&^SAQCGO-"ZJ)*:O1.]';9+$.F\(+:%+I9CNKSNN)48FKWOO(.S +MG!BAO<.\+;:>&)J]^+SFNL62EF/,O#:V91":O0&].[:M&)9CU;SSNM*2FKT* +MO42VMACIO$>VV&&<,+&\%+F^&.>\%[GBDLN]&;VQL\88Q+V]O%>VR1C+O?*\ +MNK.8$/6\O;/*+IPPR;QCMM48R[W^O!>[F!`!O3&YF!`$O6ZVK!#$O=B\-PV< +M,-N\.[GI&.>\/KGL&(B4$[W;LQ.3Z;S>L]()^;VZO(2V\B[RO>^\Y[,:8HB4 +MP[R-MO\8\KWXO/"S(F*(E,R\EK8(&?*]`;WYLRMBB)35O!$OB)38O#Z[%!GG +MO&>YY`D;OA"]"+0=&:,PM+RNMD.3&[X9O1&T0F*C,+V\M[;^$!N^\KP:M#(O +MHS#&O,"V,AD;OON\([0X&:,PS[S)MC\O&[X$O2RT;[+IO"^T9)-"OMN\;KM( +M&>>\<;M0+TF^$[T[M&MB=1(^M&YB4+ZZO.2V5AE)ON^\1[1<&>F\2K1Z8E"^ +MQKSPMF(92;[[O%.T:!E0OL^\^;9K&4F^!+U!GG +MO+^Y>QEU$L*Y?AEUON6\;K2/+WB^NKP4MZ%B=;[OO'>TJ9-XOL.\';<1`\:\ +M(+>M8G6^^[R#M+23Z;R&M+9BDKZNO"RW6K%XO@>]C[3`DWB^V[PUMZD9Y[PX +MM[LOH;X3O=*[S)/IO-6[SY.HOKJ\1+?#":&^[[S[N:@)K3##O$VWP!FAOOB\ +M!+K)$:B^S+Q6M\D9H;X!O0VZSQFM,-6\7[?L8N>\:[??&<>^Y;P$O/N3=1(E +MNOXOZ;PHN@"4T;[`O'JW!3#'OON\&;P38\Z^S[R)MQ&4Q[X$O2*\QK?1OMB\ +MDK<>8^>\F[M"N4[[Z]O*>W-&/HOO*\I[0YE.F\L+0\ +ME.^^S[RYMQ>ZY[S%MU-C`;\0O<6T3Y2=E+2\SK=YN@&_&;W.M%>4G92]O->W +M!;L!O_6\VK1BE)V4R;SCMW%C`;_^O..T>6/IO.:T?&.=E-6\[[=_8P\!2P/O +M91@F&@(GO\8(U&7$)BN_%6VA;7`D,+_NF$H*N":Q"E@$*`HWOUT*6`2>)3>_ +M9`H]OS:_930S!4&_1+^))#690+]=!$*_1[^JHD2_2K]&OQ<*N";."D6_-[]+ +MO]`*5+_%)#N92;\^OUF_^1M.OUR_3+]F)+0F8+]1OS!`/+]/OU6_1+]J)&._ +M2[]EO\\)1+\7!U"_0+]QOSN_<+]%"C^_=K]MOSR_=+]=OUTDRR8O"FF_-9E[ +MOW>_?;\`"X,S;;]+OV8*^2N(OT:_4[]\OTR_IQ1YOU"_5K]SOX2_D+_0"CBA +M1EM!"SRA1EMY"T9;V0H-/J4*II%"H:*_K0H5/J*_L0H9/J*_M`H2$D9;N`IN +M!Z*_NPJ3`J`*O@HG/J*_P@H#`:*_Q0HO/J*_R`J!!:`*RPIX!Z*_``M]!Z*_ +MS@H]/J4*T2)7C)N_I"97C)Z__(1B>"A@GSJ&;OQLGSJ'/OQXGSJ'2OWDCV*&I +M"J:_)!TKP*F_*@HKP+0*WQ(KP*^_.Q@KP+L*'Q0KP+6_(A0KP,(*1!@KP+N_ +MT`8KP,@*D@K.H_,12>"I\*K@J;OU0G`J*L"J"_/0\) +MHJ<*JPI;P*:_1"!;P*F_#A$2HF7`Z`H5HJX*A`H8HEO`6PO$K5O`P`H(`<(* +MPPI;P+N_>!A;P,@*R0I;P,L*S`I;P,2_@1A;P,>_A!B>"NTCL`J;O_`CL`K/ +MO_PJL`K2O_@CL`H&P/LC/:*E"@(DL`IOP`8DL`IRP`HDL`IUP(,UL`IXP!,D +M3Z*:P+N_]PJ+P,@*^@J+P,L*;Q2+P,2__=12>"BPD8`F;OPH+8`G/ +MOS0D8`G2OS_D;]F"=(*XA6E +M"F*_M;&W"J"_;[]F":H*[A6W"J:_!ARW"JF_]!6W"K0*8@BW"J^_X0FW"KL* +M+`NW"K6_QQ2W"L(*RA2W"KN_S12W"L@*T!2W"LL*TQ2W"L2_UA2W"L>_+1.> +M"J,D7EN;ORTH7EO/OZLD7EO2OZXD7EL&P+$D7EL)P+0D7EO*P+_1!:>"MPDOPJ;O^`DOPK/O^0DOPK2OV8H^:*]"J:_1-(P;L*?!-(P;6_?Q-(P<(*@A-(P;N_,`M(P<@*,PM(P<2_.@M( +MP<>_/0N>"A\EP0K2OR@EP0K*P"LEP0IOP#0EP0IXP#@E.Z.E"KLHP0IE"\$* +MR`IH"W7!Q+^E%G7!Q[^H%IX*!;O!RPH%%[O! +MQ+\(%[O!Q[\+%YX*/2EN6YN_Q26LH\H*H+\5%^C!J@H8%^C!IK\;%^C!J;]$ +M">C!M`I+!^C!K[_*".C!NPHG%^C!M;\J%^C!P@HM%^C!N[\P%^C!R`HS%^C! +MRPHV%^C!Q+\0'^C!Q[\]%YX*\R6!C)N_]B7Z3B"N&_>EN&"IQ!I<+P"N>_>EOS"NJ_>EOV"NV_>EOY"O"_ +M>EL`"Y$'G,)%*GI;G\+[OYYSV`I#"[E!V`K9"IRDV`K="M8+V@K@"LH2X@KQ +M)MH*Y0K)0=H*L<)&(]H*ZPI*(]H*D,(`)]H*D\)M*MH*EL(')]H*A\&ZI-8* +M(<#:"OP*),#:"L7")\#:"@,+*L#<"M(*SW/4"B_`[D'^PM'"*QCB"C7`]D'^ +MPN`*.<#<"K$*_D'^PG\*`D+^PK@*E*S^PK;"1<#<"O`*2,#GI-8*3L#<"OD* +M4I=0*PL!K='W#X`H5"W?#"\,8"W?##L.+%'?#$<..%'?#ML(B +M"W?#\`HE"W?#\PJ7%'?#]@K;P(M;^0K>P'^EYPJ9PGZ_5`2"FX)_`H1P6X)Q<(4P6X) +M`PL7P?BX_,+>">(*',%=!'["'\%=!('"(L%=!(3")<%=!(?"*,&^K=0**\%= +M!+'"+L$\"-?#ML(N%M?#\`K=%-?#\PHXP?BX]@H[P?BX^0H^P?BX_`I!P?BX +MQ<)$P?BX`PM'P:,G_,)D$^\*SL)G$^\*T<)J$^\*W0IM$^\*X`I6P:,G"\-9 +MP:,G#L-(*'"5"IG["=L')`8'"(B5"IH3")25" +MIH?"><')`>4*?,')`;'"+B5"INL*,25"II#"?\')`9/"@L')`9;"A<')`>[" +M1"Q"ILK#R0'\"FL+-\3%PHW!0J8#"Y#!3*;6"G4+X@J5P;X!]0K1PIG!I@'= +M"IS!GK)FQ(?"8R6J)^4*9B6J)['"B@NJ)^L*C0NJ)Y#"D`NJ)Y/"=26J)Y;" +M\BAMIO4*^0J;"VC$_`JTP7:F9L2?PKS!G0=[PK_!G0=^PL+!G0>! +MPL7!G0>$PI8EJXR'PLC!G0?E"ITLJXRQPATIJXSK"B$IJXR0PJDEJXR3PB@I +MJXR6PK`EJXSNPC`IJXQ;Q+OTFGMHS;"E1V"PND#K:,%`M>$K:,%PN>$U[% +M&@NMOV-V7L4?"X["G416Q20+Y`U>Q2<+N;]>Q<4*J416Q5L*K416Q90*L416 +MQ0`+M416Q*>#Q4,+@W:#Q0X+KQ\+"ZG"QT2#Q10+V+^FIQ<+ +MV[^FIQH+WK^FI[@*UT2#Q2$+Y+^FIR0+NL*8IXS%*0NB=HS%A\'K1`<+P\*H +M=HS%_@JN`G[%]K^FIX'%^;^M6U3%Y!,+"_Z__40-"PX+ZA.VQ1$+U<*ZIZU; +MKPJ]I[;%?0H/10<+#\"M6YG%$L#'I[;%6PO*I[;%P`K-I\;%H\7LPCX(IL4P +M.*U;RL/7I\;%K,5Z*JU;9@K>IZU;!0LLP#%%$`N'Q<`+P(P."P/#P(P1"PX4 +M"PM\(\",P<4G)\",Q,6>.\",'`N*(\",'PLU)\",S<4H+L",T,49-<",H\4_ +M)\",IL5")\",V<6D(\",K,6I(\",W\6W*L",!0MH=<8<"\[`BJ@9"R$+CL-U +MJ"0+D<-UJ"<+E,-UJ'7%E\,LKG7&V<5:)'6HK,5^OQL+W\6APZ*H"0NDPU\( +M00L`1AX+6<5KOU\(7,6MPU\('L:PP[*HG\87"_G`N*@>"QP+N<-F")_&(0L" +MP<&H'@O0Q<+#Q*B?QG7%"\&]6WC%#L&]6WO%S&HS\87"T$3"PLKP2`+'`LNP>FHS\8A +M"^[#P5LD"_'#\J@'"_3#4$;KQJ;%RR3!6]G%4RC!6ZS%TR3]J,_&@<4#Q`.I +M!PL&Q!"IA\4)Q!"I#@L,Q!"I$0L/Q!"I%`L2Q!IX_,;$Q7$H$*D<"W4H$*D? +M"_XK$*G-Q4%#$*G0Q0`D+ +ME<%M>%7'#@N9P6FI"PN'Q8@C"PO"P0H$7,7%P0H$'L:@Q`H$P<7(P0H$Q,6FQ`H$'`NIQ*]X@,'!W(Q^Q>3!W(R!Q>?! +MT5M4Q38'"POLP7FL"0O*Q'@(ML<1"_/!T5L4"_;!T5L7"_G!S:D'"_S!T5N9 +MQ?_!TJG#Q\W%W\1V"-#%XL3F>+;'=<4+PMRIP\?9Q>O$[WBVQW[%%,+16X'% +M%\+GJ0<+J08+"QS"C+`)"Q_"[*GDQQ$+LP;AQQ0+)L+BC!<+*<+XJ=_''`L) +MQ?NIY,>3'=<4[PN*,>,4^PN*,>\5!PN*,?L5$PN*, +M@<5'PGP75,5/!PL+3,(I>0D+3\(L>1+($0N&%P_(%`LQQ2.J!PLTQ7P7&@LW +MQ7P7F<4ZQ7P7(0L]Q2VJ',C0Q6?"1'D2R'7%1L5*>1S(V<6T,'P7K,53)GP7 +MW\6[,'P7T`I!JB`WS@SO)T,+N4=="DBJ[R?;"DNJ[R?5OTZJ[R>O"E&J/,A] +M"E6J/,CH"EBJ[R>$"ENJ[R=;"UZJ[R?`"F&J[R'P6>J/,C*PVJJ +M[R?^"FVJ/,AF"G"J[R60*HWENR(T*D:INR,4*B+$@-ZHT +MEZINR)0*%4ANR``+&$ANR,X*&TA!R/N_'DB;R#_(YQ,@-P'`)$B;R'7(U<*P +MJJ'(2LC:PL=YF\A^R,?%N:KNC%/(X\(V2)O(O@HY2)O(BL@;P.Z,C<@>P.Z, +M6PI#2)O(D\CTPN%YA\CWPM&JH<@ZR"S`3TA!R"_`UZK+R'+(ZL7>JB`W[<7P +MJGC("OC(3<@SPY1(^\B!R"K&](PK"RW&](RUR##&](R*R#?#)ZOTC%_( +MX2/TC&+(.L:J2/O(ELA#PS,&F,/\A'QO>,\A3QO>,?LA6QO>,@,8LBQ)_>,9,:,AOQF]Z0E')*PN*QHUZ8D'( +MQ<,&KW_)OLC#QKBK?\EER'D\\%MHR,K&S'I!R!G!1TFLR3_(-!,@-Q_!3TFL +MR77(.Q.RR7C(U0:RR7O(W<8J"W[(1!.RR8'(*Q:RR2L+YL;I>H?(Z<;*!(K( +M],/@J[+)7\CPQO%ZK,F3R/W#R@26R`#$ZZO(R3K(2<'NJT'(3,'_>MW)KA\@&Q_JK(#<2Q/VKY\E-R`W'CDG=R8'(&\0&K.3)5L@6QQQ[WT'(><'2!$W(?,%%>Q;*@,B^Q^*QDLI-R-;$:@U0R-G$:@U3R-S$:@U6R-_$ +M:@U9R.+$%:U!R.7$.+(@-^C$:@UBR.O$:@UER.[$:@UHR/'$Q+!!R!G"R+#` +MRC_(1!<@-Q_"X@1$R"+"6:W`RGC([,?B!'O([\?B!'[(+,(C*('(+\(C*"L+ +M]\?B!+7(-<(C*(K(.,(C*(W(_\?B!+[(`LAGLH?(!`HMRR/+>PJ/+><0 +M]6:/+;8*CRV""C?+(\LF"H\M[@J/+8D*/LLCRRT*CRV/"L,7(2/*%VD/?"/*%VT/)R?*%S/+ +MGCO*%UK+BB/*%Y++-2?*%Y7+*"[*%V3+21M^RTO`RA>=RT[`RA>@RY(*RA=P +MRU3`RA=TRU?`RA=WRUK`XV`AR^:U=@]4)^-@)LNZ(^-@*B#T!J]!>K$-DW:[&+Q?075@H@S)H/4LO%'![,,S%W+56KT%SW+6&KT%V3+6VH>S$3+G*P>S&O+I`-MRSS,(\S4$>T4 +M(\P)$J0#&0KT%PP2I`/<$0@X:[&UQ11AK,M`!AS,YB8481;,A,L@%9X/+LLY +M%9X/)\P,P!1A*LPU%9X/.,M$%9X/.\MF%9X//\M'!IX/0LMU%9X/:NMJ]K08RM0K!4K$2P7W-1 +MKQ^7I146P5*R,&]JLW`R204*QJ#650>_,BQJ!<_D2 +MD'.D$I!SX.M'`4+"%D#BG-GK>(D%['JS+L6:D[3$A?-VJP"KD(0QZ_PK]T%X7JUQ#DFP7JWV +M!TZP*;%@K6MGQ:.&^P3ZG(EK:@%701/'^#-::[X!E:L@7^Z`5FPP'^Z`>`7U0$& +MKN0!DZR;@+H!?Q1/)I`4D1D',)847Q>Z`0VN):Y&L8L#R0'Z!#S$::ZW44JL +M0ZTV"RRO`@I"S0?.I140JL0@6ALOR,<@$,UO5+4!+*]#AF[$YZT4SA`)WA3P +M&8,']A;?LO"OFE:9KD.M&5S8KFFN!5>9KJL%I@&&%_8W)@8JSA/.6"THSL*L +MBHB5Q-2NH+TF=FZNQ5?=KNT6L1P+0SO,6RT2SK;R8;["'&\M$#ZZ.&\RLCAOJSV-W^M'B3`=B6O=@:!K:\6UZ*Q$$'.QVZWY#55%,QK142`:T5$JSY4$):CNK;JBBP36%#)W +M(`(^SRK/BQH\SU\=`@HO&D7/WZX\!$D(@*]4!*^M3,^FSNL!4K+K`7VPYZS^ +MQ/BN,PBBJ%JL,G?ZKG\;H51`#^ZM@;`.>%2R\`6)(40;ORHUSTO.@P<&KFG/ +M!LU`K,1H`Z\G`Z'&T:TGJ>9%_*P#`:&L=L^/K`0BR\P$(@.OPQ+)K(:QA+&8 +ML2%(!:_G$[6H)Z]L>HFQYZPNR4@$QJS/JV@( +MEZSY$)*MFL]"KVD5A+"FSH9QLJZA%.^M)Z]UKT*OVB;1QH"OK'_,K*Q_5+)1 +M(5:R*JPY@*S/J`HI>.>LSPU,K2B"K,]?%TZILZT"![<289^=$L#/=:R6L<\H +MI16=5[XA6JSLA6:I!!/K!K(2S<^'KMP,;ZDW&VF)QR'AK#](S*P_2(>N5R%[ +MJ8"OD+'-K8MXK*QI5J;.\0$E$W(A%Q4S!=$+[12T!,2OB!+LS\:L:8F.Q^H2 +MVB'E$O//K:U)#KIX@*]B`C_/^L^MK1T+E,>@KS8[>:POKF()S*QH"8FP!=#A +M"0NO!=`IP]IXN*P0J%JL*(T%T"46[B'H$A?0RJQOL<.X[*GTSE$, +M-JP]%0EY6AL>6S\'3*UW#LRLF[$:>L4K(WK,JL&`_U>.ZMZKTX +M>?+/TI)2LK^]%P%!OCO0[,[3ODIYKK!I9,%'J:Z:!72N[!>Y1QFO=@&G&DY< +M(!JBN<5'.:T'`4@6G43Y%6W% +M-DB9K>\=FZPP'CE(OA7DJB@5*@HN%NZL!C],KB,KD4@1KZP4L[%,KFD5 +MFDADK_,#.:VIT*45^Y%WS7RLJG/AK05*@89%8,'P['JK(7%]VI[%C1!Z!7;D_=JPAE80<@2S-"LT$LF>")9`P4^ +M6;(&`9O0,GGKKE4?8AV$%WY!GQ)^09D2WM!BLJ$T\)O=%_";;0;ET-&OLWFC +M>HJN&TB=K)K(HWJ\`>_0S;$YK22K6[(G&EVRI;$;(;=Z1`05/MBLL*XG/OW0 +M6Q;XI"43`M'4L<(,R@2!&,H$.18)T6RMU;'Q>M+0JP($`GT'W=#%Q70=!ABM +ML!&M6A1SI;P2&M%BLI''H1),SQ2PI@T&K%.M+((1K3@?23Z\`2C1N;"9K4T+ +MO+#.L4T+SJQ-"_#0,M%BLHQ/']&,3V*R`@>R$E3$XQ(\T1_1.M&GKT`?7GO6 +MK(HN-MLJ7K8U=R+`WK5E>S;#B$)<'DZX3()<2`46U$H+1@='A:NM!@=`K,?1@=&F +ML:$2Q*CC$E\(MQG/T<`26-)FLJ8SH1+A1\;,L$++S+!"+JR81;2L1,;[K&72 +M^@J+#1T+:M+VK>9%9=(E"XL-^0UQTF^O^:Z+#2X61Q,X"GC2@ZSLJ672L`9' +M$\X$?])OK]!Y1Q."`T<34"2&TI^LX7I'$T03H0<>`8W2+JSB!/*LD=*^K.JP +MUDI0TA@/7'%OK_6LM*SUK+ZL#-)FK&:RBJA=TH?&"!$A$J72]JT+?Z72UJP1 +MS\O,$<^^K(@2;JPM&FRCX\S-%LK)Z!*VTF:RIH!=TJ:`CZR*J=(5J])J#M05 +M]JT"!ZC1Q-(AK0\(>GX*TAJR_DPRK.,*P'[.$H7*M1+1TC*L8PO/?I^LQXH] +MK?2LSUJ@#?H$]WX>`=[29K(]840Y(1@P$Z<2AS)\`:`-"K(K*?.PU@@"?_RL +M8(ZTK#&Z,!/L)?/2@ZPUO+2L-;P?LBBL]@^7$OD0#QK^TC@3'Z\E$P+3TJRX +M#8M_':V5ERZPI@5`3E"L'6?]TL/(!!X1'4!.7*W8$[&N*K`7`7&LC9WD`TJ$2X-(69<2 +MK'^K$DK32=-;:I$5X!P)[)["(NL9Q[E3YFOOPAVTX/3BZR4$O1/UJR[5GK3!!J% +M@8X3C=-#LH4!1;)"K#!P2*PP<)/342W4@5>R8@+EK9O3CZP:)LO,&B9"K,V, +M-@O.&&$7Z!*FTY[3,PCS`V$?2@:<$ZW3G]&>4:?3L1Q@%[2T^#3?!`9 +M#KTUH1Y=.[`MS3Z=.4&_+3 +MYM,?,JD!W=/PT^K3_-,(`[L"[].'#@34\]/GT_73`]2;#OC3W`U)LP'4"=3^ +MT[D"#-0(U)@1$]0&U`#4&P16`?C3]-,2U!C4Q`SKT_W3NP*T`2#4O@<>U`O4 +M(-2A#_'3!=3BTQO4_PLIU/_3Z-/VTTP![--*`QL1%M08U#+4%=0@U#@1(]0N +MU.[3,-0P`>D%-]0?U/O3.4E`U.'3*M0;!)<"+=0*U#/4.M1.U$K4[=/5TT/4 +M<0-/U!34^M/VT[D'#]0G#EO45-3;TU?4#PX#U`_40M0TU&<&8=1'U/;3F`\W +MU-`%2P)CU"C41M1,U&\%9=1NU&?4.M2T`SS48-1S$@$59M3!`G'46=1BU&C4 +M1!+?TW?45M2$U(\(@M1KU`W4X@]NU`@.)M3[TWO48]3C`H+4+]2)U.4#D]2) +MU,,'F=2'U,8"@=1JU'3410+DTY[4!]1@=J'44=0GU$,$EM2BU"D(I-0DU(S4 +MKM1VU"34E]0ZU#D!FM0ZU,,'M]1WU&*:H-09U+'49P&&U+34>-0@U(H,N-2J +MU#`!QM2'U#W4&P2.#'+4L-2MU(."L]1!U(C4.M06!,?42-37U,O4?-2UB]/4 +M4-3,U",!DM2EU&/4!P9SU*G42-3EU,/4U06^U-C4UP6OU-34`@%7U,<'J-3@ +MU&74S]34U/74J!_OU-_4?-3SU,+4\-0'U#V>]-3$##M6T`HD"F=17U<,!6=49U5S53]5CU5_5 +M)-5;U94#7=5!`4FS4M5'U1D.8M56U6K56-5FU535F=28#U'58-5BU&_5]QMD +MU;H!>-5]`6?55=7&&T$!%K-LU?S43=5IU44!A-5^U6[5:-6#U7S5A=5AU8W5 +MB=6/U8O5_]-ZU>`'5QQRU6W5EM62U8+510&=LI#56P*`U9G4X@]WU5/5A]5! +M`:75FM4.U4/5.]6'`QP!2]6&U=/4Q1^PU2\!K-4HU)W4M=6GU674N=4+`;'5 +M5=2=(OZ-80%&`6_5AM5=!=?4[P/$U9+56M5`"L+5KP[*U575QM7.U;X.9`'% +MU<#5=-5DU4D[J]61U8'5F-6E"'W5<]6HU44!M]2FU9O5H]5!`>35V]6BU=C5 +M<-5%`>@!X-7FU>S5GM7.'^K5?]7RU3,%E-6GU9?5QM3EU=9VUBS6\]51"'+6>]9TUN,!?M40`6G6@M9_ +MUH'6"]8'UG/6[=69'8G6B-86`6[6CM:0UHS6>-4PUK,-7M5CU@C60=9,UNL# +M5-9%UC;6QPM:UA'6GM;P`U[6/]9;UN4+J=95UJ;65]8]`Z'6\=7*":/6%@$^ +MOZK6[=,J2Z?6J0BEUH/45]8[##C6KM;KU1+6(0&@U9C6E=:8U9T%?M;RUU9S6R-9O#1^S)M;4UB$!UM8KULS6B-5CUIG6V=8SUF#6*-8A +M`2.SU]:#UH_6M0C3UN?6@A[AUF36LPW)U936Z];)UKD!YM9_UO/6R];_U?P3 +M[=;?UA8!Z=5EU2+6X]8##)'6Q-8"U__6_M5ZU0T(SM:SU@C7_-7XUG#6J`8# +MUP_7!M;;UOG6#]81U]#6%M<&U^+69=8A`136]=:2UD@?#M?0UAS6%]M53`?O6E=9!UPK7!]$(+]=#UQ35>M9_UDO7,]<_UT?7 +MVP-)UX_65==,U^O66-=2U\_6@=5;US?7C=8SU!,@X0L5`88(N]5CUZX,9=S"&?7 +MTP=NUWC7IM9ZUYD(A->#U(;7<]=LU^T/?]=\UQG5K@Q7%6K7MM6%U]\#X0N< +M"(C7V@V6UZX,F->4U\/6G->.UYG7Y]/%;:'7GM>=UGK7?@BBUV+7F]?X%(O7 +M?=?S!YO7C]>)U[#7D]?AU2K7QM9=URW7N-<`UU[7JM4HU_S6.B'MUC#7'->N +M#-K6N==*U\;7O->^#=W6/-U_#6T]?5UT77 +M&]VUS'7_M;>UD/7Y==AUT/5%M0#!`K5-M48U.S7*M6M +MU/#7&-6#U.O7SM0K7$M1"%375(=6^!_O7%=5\U/O7.-6[U>O7XM1"U0?4 +M4@?MU_W7X0OIU$#6Z]?Y`@K8`=@0V/'7'=7[U)#7N=06V!K4"=42U1O8]-S(-0JV!S8>=3N$338?=?]"NP05MAPUY`@5]A;$7376=@"$5?8>==5V%[8 +M8M@YV(34HAI0V"/89M@EV*W4:=A3V!?8$M1LV$38*=='US$(O]?8UK$/:]70 +MU^4#=-A=C9U2H$T]>8U8/86==_UH;8?-@-UG[8>M3QUCG7 +M0@^[UXO8T=MB^U^;7Z]:4V-O7&M@VV+W5LM48V+$/GMBFUIW80=AK +MV-`$<=@?V$(/R=4@U2?8L0^KV'37-MB[#BC89=BRV!381MA"#[O4(MC[TP4$ +M:M@VU;S8;=CUUV_8]`.HV';8WP/OUU&[8 +M%@3GV![8Q-3JV"'8/-C[T[()O=CFV$_8_-=\U/+8P-BIV+[5%-6LV+[4$P8_ +MV(34$P;`V+'4`MG$V.#7L-6T`S8==_UA79$-G`UQS9@-CCU]'7I`*8V!?9=R"5V+#5Z05/U_+5]`0@ +MVM4PV1W9E=8VV2W99-@6U$T:9]CQV&W4L-@2U#W9 +M]-<$V7<-*]@MU"MNNM58V#382=F^U:;79]1-V4#5GM=(U;#5>M10`K_5==*U3D!2]5_V877@=E^ +MV6'8@-E7V8+9@MGH`538C-FPU8H,60)8V(/98=A=V%O8;->4V8H,E=F2V6#8 +MC]F^U9'9,=A.V9#9L-46!)S9D-=&U9;9_@Q?V(77E-GJV*#99]>MV:/98]B% +MV8K9L-6(`HC9I]F&V;[5M]F-V;39MMF'V;W9B==*U;?9GMF.V;+9F2"KV8G7 +MF=D<`7D$R=FGUX/9S=F?V/8K]F8V9[9GB#3V:/7R]G=$CP17-C0 +MV2L"F]G]V*+9WMG'V:;9G]=]V=T2302XV<+9M=GKV;+9?==%U1LCY=F$V>[9 +MS-GLV<791=@'U``L/MG>T_W9\]A\U`#:`]FMU`/:!MG?V$Z?L]B@V`G:%-CY +MU&D:Z-C!V!8$#]KLV!78W1)%U+K8_]D7VG;9$MI3U'G9%M3=`OG8[=C,V5W4 +MY-D+VO8D#=H"VA8."MH2U"?:%-H(VD(E_MD#U##:`=I7U#/:!-HVU3;:!]K\ +MV5;9&-HRVCS:&]K,V7L'*]H2VD+:MMC\V8[4/=IS$BT%`-D?VI74,=JV(!G8 +M^MAAGT/:_]FBV)_7']JGV%3:W1)9VD;:-=IUV9_8(]@2)RC:7MJEV#C:>]DY +MU1_:N=CPV/_9:MHTUFG:9=H.VL/81]F$U)TG3]H8U'7:--ITVO?73]IXVB': +M%=K$(%K:2MK:U$'9$MH&V&O:W1*&VCO9+-H-V&#:^],Y,&/:=-H3V![:B]I1 +MVB+:!P%K%7;:M@$J!#O8;MH!U)O:<-I@U)_:$-KZV"H$,=6-VK41I=KEV*': +MT@:@VD/4J=JCVI;:(Q:!VI@1LMJ0V@S4M=I$V:+4N-I^VM_8TJ*SVIK:BPVJ +MVJ[:P=H0VHS4OMJPVA7:U:*_V@H!RMJVVI[:+5UMJ;V/K8U0'+VL,!_-B$VJ\!&]4QVN+:R-K?V+H!G-KI +MV+41[=K"VFC4\=K1VB_5]-HNVN_35ZSCVOK:SMH&UC35+MC\VOC:0]1-K/O: +MBP_]VJ\!'=H`VP;;U-J2UO'-U]K#`8[8[-4.VVW9CM83VQ#9X=H"$IG:KP%` +MV4#:PP%&V>G:&=L"V_/:QPT%VS_:G=H&UD7:D]HHVY7:%=K@K@7;2-H=VR[; +M]=KUU#+;#-LAUN#5B0+"UMH-+=DXVZ8&7-@\VU+5.=MGUT#;0`%"VR[9C-;E +MUM_7U=K5"%_9N@'8UVC9;]5.VQ/9+=OX"1K;PP%MVJ/8`=2Z`7+:(-M\V_#;OMN2U53$0M>WVV_9`-4#VPL*Z]MS +M$5?$Z-OCVV?:/=K^V^O:^=K*`6+;!MQYVHO;7MN3VPO`>RR[+)"W*;61-S=`4O<'0]#W#H53-Q'W+#8]P2L`?FR^;+E +M`9_84]Q!W%3 +M`8#<7MR"W''`9/`7$'6-P*LP^S#[.FW%[W-7`>+W/+<[]QWW/?O;R]VQW<3=3A"IW;8! +MRT3,W=;=P]T,U-C=QMVGW1K:I]KJT\]$U]U%U3?:]=3AW='=VMW>U;:'S(JVJ_=F-6[W;+=YP=6V]=$XMT?V\_=]-TVV[,".A7;1*?=3@B#![O5 +M.JC_W03>'S*`-ZI]T'WN?3$-[?1!+>I]VQ +MVQ'>!MX7WA\R%-<:WA;>&]X=W@+>?P,XT1TUR;>K]4BWE0(2-R#U"G> +M60@JWK?-*-X!WBO>)]XLWB/>P@$VWCK>L@G^U7;=-,9("#@(_-T9W?_3/MY! +MWC_>0M[AU47>Z@-'WC>HI]5*WD#>2]X%!#363-X%!$W>_-TLW3/45-XO`5;> +M"=Y3WD;>5=Y@WEC>N0):WD#>6]XZ%5[>9M[H`0_>)-YPUUS>_=W]W6S>:-Y` +MWFK><-ZP`[+5;MYTWFK><=ZFUFO>3@C6V"#>=]YUWD#>Q]T3WEG>;]['W0S> +M`MZ'W@7>@-Y\WFS>)MY"!"O>=]Z/WC3>E448WC/>?MZ$`B_>(]Z9WB7>*MY3 +MWI7>,=[GV#+>;=ZAWED(H]X\WH[>.=ZCWJ+>+=X.WI7>K-ZGWBW>"-ZMWF\( +M=`A?!)/>LMZVWF\(8]RTWKK>-]Y4"%C=%-ZUWL#>2L8HWK()QM[!WD@(J2AM +MWLC>7P3)WJ'&Q]ZWWGD(S][,WG?>SM[4WGD(UMXQW,3=#]G4W6\([MI7V@'4 +M0PBMVMW>SMU_U-_820BTW1_9F-SCWAS9Y-U@U.K>/-R2UE9W#]OUWO/;5=7W +MWI[;+-;ZWL';6=F(U5>H]MXSV8W=;]4!W[;;_-XYV?'6Z=Y#V=_>5`@ +MV=G=[M[MV^+;;PA6VN+8+-\FWUS:S]UGV=S=5`A?VN_:&=\VW^+>P=URV?#> +MLMT\WP;9%]EM=P+?XM='VT+?!]_LU4;?Q-L+W\K42=JJW979P-UO"'O:,M]2 +MW^C>O-VJV?7=5]\)W.[>B=HWW\5%+-M!WP0+`M\>U\O8=7?VVPC?)]<-V +M6PC5W[4<"WM7>;-^V`6[?0-;0WLS>T=X#$Z[>%-YPW\O>';/=IV")K?^=O$W7D)E=^#WR+?W=L$92K?F]^@WR#?VMV9`HS?5MHW +MW)/?,=\3WZO?DM^(WSG?+M\$93G?KM^TW^7>JM\!W)[?JM]8VQC?)-]W"87? +M#=RGW\7?OM^3WS/(7?.=R'VLS?L]]("*W5#=_X>-?=K=4]W\3=U]\Z +MVK+=L0*TW=W?MMW?WQW?\=[AWZG?X]ZW`M[?Y=H=V^RIN]_FW^C:--IAUEQ' +M]MX\L_C>60CSW_O>2-_VW_[>^M@$>=[?IMJDW_S?A]_2WX;=R-_!W4>S]=T& +MX%K?!>"/WYO?".#EWP7@%]_+WXH-UM^=W]_=_JE?W_3>X0WRW\G71M?YWAG@ +M1]_BU11Y4]OIWHD%WM^XWZ+4%WGLWP7@O=]_WQIYWM_`W[G?TM_'WQ7@X`(7 +MX`37'7GRWQ[<1=^2!6;?^-_0V(W=:]\*`7/?<]\DM@+>;=\"U4/@I`)3WD;@ +ML0%(X.39=]]"X`+51.`$X$'@-M?JW7,13TC,W5C@`>!]&J[=[]\!U]>J#]M@ +MX/3?5.#";US39DM5^X!_@;]6#X&C@<.""UPW?]7EWX`G;ZMV+ +MX-'??1J!WX?:5^"-UVW@E>!OX&C4^'DUX&'69TA_X-#;1]N=X(3@@N#M`\[; +M?>"C!XK=G."GX`3?H^"-V&;@\P?ZWW;8`'I_X%O9_]Y4X&39T=NRX-C;%=KT +MJFO@GP>6X+#?CN"^X#;;J>!)V]';GM5S2%_9R."BX%75RN#$VQ?9^JI_X$3? +M'.#A`]#@R^#4X&O7A^"9X//7BN#;X.W>]`+]JBG@5.!4WS'8J>`3U\;@X`=\ +M2,G@_]>0W`TWX)(:^!B!UG@^^#VX/W@ +M^.#Y$U;;%WK\X)+;CN`!X'\LJO@S.`MV.S@U.`0X>_@:>`H +M"(K@%N'>X$'@*`AYX`'4BTB;X`GAL-OGX'$'('K)X%\#_M[\UB3ANN#PX)+9 +MH=\:X=[=I-^12.'@!Q.-X(?=Q^!FV`OAQ->42"7AR]NQVX7@:=BPX+O@?]A6 +MX)@1ETC\X`O@A]I%X7S@G."&V#CAB-6:2"7AK>!0VX+@B=A`X2OAH]_!WT3A +MFM@)X!KAIM](X5KA$OX/3@=^&8X'K@>^%@X6>R:^`[X&W@@N%\X7;A +MX^!PV9G@RPZ!X6[;$-\I$US?&-_JRFKA<.`8&VWA\^`OU>W*,N&8X9#@\,IK +MX!P;;>">X87AW^"@X7_A'QL"X:7A;^'H!`7A:.&GX97;DM;H!`WA/>%?X*:R +M#N'4X*.R]]_BU:_A(N!IX/L"G>'AWC#@*Q/GWH[@O.&0X*)\X]K%X8/;Q^&A +MX0H!R>%@X2U+QN'ZW9C?SN%;X-+A--^I?,_A%]^_X=;AT^%LWM7A--XMX';X73A^MBW?,_A>>'LX:4(RN'' +MSC+@W-X,U$-+S^%,WQW;^^';X8?A4^#'SHSA-]]S$4=+S-T'XMOAC^'PX2#6 +M5MN_K`CB#>+VX0_BQ.$RU@[B%>)OX4Y+,N$9XA3B[]@CWY@1$+$(XAL)$N(B +MXLWA6-8-WU5+(>+NWR[8*.(4XG3@8^'+X6P!T>&`!X;;[.$SXHK;`=1]#2_A +M6.&V`3GB(>(TX8?:/>(4XI+@'N(\XCP&(>+OW>O;]ZWGX?KA<-06X@_?I-]H +M2QKB3>+5X='6)^)5XAGA-Q-=X=_=;TM+XCCBW=5#X47BK=^BU'-+4N)GX0+B +M]='&X;4(&.)JXN3A,.+OX9;:>DMIXO/A]=1QXM/A^M84XOWA1.(PXGGB4.() +MUR/B`>+3X&35=GT/VX/B8^!@`B??M^%OU87BSN"2UOROA.)GV8'@5=6.XM;@ +MR^$SWT#A%]GY$,7@?=C$UYGB7]F=XI3BA^)/VVG?@]G +MXHS7J>*FXE8:J.*+UZ[B[0;CU[/B;+#H`4K<6=R+V+7B1-RXXK8!1M>[XCH5 +MO>+/UL#BM^)/W+GB^>$!U$NLX]K*XH/;S.+VX<[BK>$$UQ%/#]O3XH;BU>*) +MXI+5U^)5X>_3%4_+XM[>6.+=XEO@X>(TWVV`WN+^WSK?GPCOWC3B]=3EXGS@ +M===OU]4(&P&KXGG7L==KU_'BFAIH]?ZXJ7B(17SXN+6Q.*? +M"$,)0-RZXL(!O.(&XT7IXN<(^.)8V/7B +M+P$8XP+CZ=F;UQCCJN*OXAKC%0$AX_SB#>.?"#H530LSW17C'M8$XP,!%.,H +MXS#CQ>(LX\/BP@$KXRGC->.LXHO7!@?RXB/C].(7X^.R'N.GUR#C^^(!XS_C +MI]E%XP#C/N.UXK_B">,JXPOCW0$(XSGCX@A1X\?B,3 +MXSKCK]>IXDD*'N.:UV+C1^--XQ;C#PGVXF?C_>*KUQ4!20HBXVCC6.-/X^@! +MWT!UXG;CMN)WXR?6?>/!XGOC3N-4XRH)8.-=XWGCA^-W +MXS#7?>-?XX#CC-6.XUOC#.-\XXKCP'*0XYS5+^.7XY3CA>,39I/C4N.)XU() +M@^.(XY_73>!2":0"/0F[U:;C0@*!`:GC0-:KXU+@KN.RU;#CJ.,PV336L>,P +MV:[C-%Z[U;CC/`DPV;OC0-:]XZ?C<0?`X[+5PN-"`L3CHP=AXXO7WH<9XT#C +MS.-"XTCC'^,5`-MXS85U.-&XTSCA=YGU9KC5N,MXX'CEN/?XS+C^L^& +MXZ#C>.-8"9_C5^.-XXKC;EN8X]WC[>.$XP/C@`FCX^_CW1IM"?7CG./SXX;C +M@PGVXQGC1-S]X_KC<^-T">$#$.-3XWH)!>3RXY_7NN.C!\#C8EZ\X[_C#>0- +MY(;8M^,1Y+`##N04Y)#7#.07Y!/D=MZFUAOD"@&A*B'D&>2#U"#D$-'"`0_D +MP>,1Y"CD'>00Y,GC+.07Y"3D[..&XZ4J_N.KXD3<->0"Y#/D$-$)Y*3CX>,A +MY+[@!N2FUACD,>07Y`+=LM5$Y"/D1N0>Y)_72>3!`DODN]5.Y"GDXKMTUU+D +MFMA4Y'#75N0HY$?D0^03Y"CDAMA8Y$CD7N1*Y"'D7.1-Y"WDP0+A`V'DD-=6 +MY&KD9N2=UACD:N1@Y&;D0@9QY&3DJP)OY.?35N3J`VOD@]1[Y&7D3.1PY!/D +M?.1SY$SD=>2#Y'?D?>1PY(7D@.0AY&\!4>2,Y'CD%^2/Y$#64^0"W5CD$;R0 +MY%#DDN2.Y('D>N21Y.6[G>2:Y(WD>.0HY)3D--:6Y%ODD^2&Y)_D1N2JY*+D +ME>27Y)3DF>3."7G?,]28Y+/DE.34"57DLN2KY,H)MN2Y`KCDON2UY+SDP^1] +MKK_D4>2]Y([DP@&[Y+'DD^2FY+`#S>1(Y++DT.3(Y,[DL.2K+-;DT^3&Y!\' +MVN1#Y++D:N2ZY,T)V^2.Y.'DT>3CY-_DW.3J`]+D;.3*Y*L"&`7>Y$WDLN1\ +MY.+DP.2Q`;CD].3GY+/>=MCQ8`_;_>2&XO_DV.)5U0'EE^*2UK$M_N0TWI'B +MX0,'Y:#B#.6,X@373Y+^Y-,'"N6@"8G@$>$5Y2G9:]G@!SD8$N6?X('B8P.D +MX`WE(>4/Y4G6U-4_&.+5TM4_UB;EW`8HY1'62=8GY=75R]49U2_E+.4QY='5 +M0^3UY-;D"V)1Y#GEQ.3.";W>>N0]Y5&UE_E<-=EY14!9^5)Y4_E2^4+Y4;63N7*"6[EM-95_Y7SE;.6$Y3_EA>6"Y4?E@.5XY:_6?N7.":<) +M@>6^UH_E"QF)Y9_75.61Y8WED^5/Y9GEEN53Y93E:@V6Y5CEH.7H`4WECN5/ +MY:7E4>5%UJCEY>?3@^5C`]H)HN6OY93ELN6>UH;EL>7"":KE:.71";;E +M:>6(X0S4Z!#CVL+E@]O$Y?;AQN5@X4.3P^68VF_ARN5;X,[E".$OXR,9-N0C +MXT3OE,N'QY4KA`=<`E/[DPP44Y3$T/.'1V_;ENN#8XW/73330 +M`63C_N*UUP'FSN-IXP;FUN.PX@GF)^.5XU3C330;L^#CV>4/YOP&C.,3YA#F +MYN-7XS_D&.;?C.^0^W$TT(;,2YIGC>>,AYA;F).9*"@H'&>8CYO#C*>9! +MY.'EV-9'`SG@DMAIU3+F)]DVYI3B..;9X/73$Q1\XNWE/>:LW4#F`>!"YMS= +M$Q0$XC_FDR!!YDGF0^9+YD7FEB#+VA,4EN'@U%'FX>!4YO3E!.,P0`JS+.;W +MXW_C6>8GYBWF7N8=YAKF%^;X1ROF,N,@YH/@Y^/>Y6CF@.#KXV3FL=<*Y!OF +M@^!"Y`/D7>94K=3E6.9WYMCE*.:P!$0'=.9RYG[F,.85V'WF/N8NWX3F0>:Y +MRE7FB>:QW2K8;V/+9 +MIM6#!RSE&]RYV:#F'H`?W)_F2@JFYAK:XUZ/F=>'E)\A.4.:T +MY@?;H>9FXJ?:N.8?X1S7H>::XC3F8]6^YC?F)(`\X*C5PN8JX>/3;C;LY8;F +M^@BWYLWFRN'*YKSF->;`@M?:;C:*U:?;UN;%YF+5V>;^Y5SF(.8""D;<-N,/ +MYN#F7^;WX^29A0AQYA?FY.9BYBWCJ=B#-CKBS.;Y!!GA[^95YF@77>+E)VT7 +M4.;YYL[F8`CUYOWFT=^#-LOF+^(!YT'F?"+^YD?AIMV#-A#@`^=7"]CA=-0* +MY_[F%.#(XOCF(P,:VX,VX>$/YU<+6N+OVA?G]^9*"K]2^N;D!/SFN>89&OSF=.%KU(,V;^*#YE<+P-_QYG/B6]2#-OCA--PWY]+FP>97 +M"V/?(N$?Y]0-8^"#-FC?8ME#YZ7@[^(A%2D*X1K2XV7C`.;Q5`?FT^-/"AOC +M4.=-YTKG<]=#XQ/F7>8E57CF)>9;YWOF8.9>YW_F%^9AYX+FM]A9(RGG[M># +M(NM&0>9KYT/F;><(X;WF#$?5YG+G0N=TYP+E10IVY]OB,-19(X7F`^/VEOACN=5YH9''N>8 +M!8+G@=27YVSGS-Z+YYSGC>?^1X?GS0F2YZ#G;N>BYY_G3A4MX9@%Z=\0WZKG +ME.>HYZ?G+N)IYT\*URF)Y[3GG>?!X6?F$0B#,R+FXN9:Y_+;'N9CY_+;8N=\ +MYF)39N8[XX#7^B+E&G+C3>?(YP)74.=$XQ`DSN<*YB3C3PI"LPWFG>,@YBH' +M_[);YO_CNN?:Y^7F^.(0,M0(Z>;$YZ.R=.8?YM[GP^%JYEGGV>?JYV[FY>>+ +M".3G8.?#X>?G!.8`YGEN5.?VY\CG^.=8YV[C2@KXY]/GS^/^!"'EU^<3Y__G +MYK*IY\`E0>8*Z$/F#.A%YD,)'>(%XMDB$.@+Z'4"5>84Z`#G'8Q0YAKHM^8< +MZ-#F'NC1XG'7_@3R%(#7U.Y5S9@M5' +MZ$#HU=M2X4[52^A%Z./6(^C7YIOB->86C4#H4>%-X0?H6>BTX<'F;8W5YE_H +M0N=AZ'?G!^BWX%/@(^ABX;+G:.@5Z"3G.>=#"6WH[N:EC1OH9+.2YW+H#>AT +MZ-'B1NA#"=+@2>BNYGOH0.CHU['A3^A_Z%'HO>8JCF#H<`E`Z#[@@NA%"H?H +MA>A6Z"NS3NB0Z.;@+MDCZ-W81>='CJ7@>NB)"8CH/N>5Z'>.-^B#Z)SHR.9[ +MYR,%F.<)U6*:0-\VYZ;H%^C:W_+:8]=BFM0(JM?_Y;'HKMBYZ,;5(P4U#<[HT.?0Z'?70]ZTZ(>/P.C%Z-_HR^C6Z)_4X^@(YK./ +MP.A5Y^CH)>@IZ.OHI.(LZ.[H4^?,Z."/Z>CVYV*:G=?AU??HU>C)Z`C@\NC+ +MXV*:J=?=Z(X5PN@!Z?GH8M'[Z&+4`.D(Z?BC3?IY^(PX%T% +M`^"ZYC[I(NE-$&#B/M8ZXD'I%2D@Z=00V]\TU%T%Y>4_YADI'NG#!3OI2.)5 +MWS7IEMVIY]U<5>D(YQSG7>E&Z0OG:NC@7%7I$N8!Y`_I2NATZ5WH707XV\#F>>FZX5KI:.<+V%T%Z^%3YBLI3>DP +MYV;G=PDSYP/GB.E5Z3CG+N>+Z>[BJ-E5V%T%U]F=V:/9D^G.V=S9*2?9 +MY-D\U9?ITMFSV>G9O-;"U27E30%YUZ/I.=:EZ?SHZ>4GT]6FZ:?9K>FR +MUM35'^5VZ7L)+>FWZ2_IN>DQZ8$)1^=?Y3,%[A2]UJ/EH];`Z8,B7]:7Y5LR +M^%RMUJ+6-K\(Z++I9^AP"1'H4^D6Z";IU.DHZ=;I/>GW%-_>P.FKY]W;W.D@ +MZ?<4V>FQYX#I#(X>Z8$"X.FXY]#I).AOI4-_`Z4/I8.GKZ=GI\.:*Z0RS +MDN<3CN#I/^()YPI=).E!Z//F_.E#Y@#J1>9P"0+G9.F-W]7I7^EHZ0?J`^J7 +MWTCIP.D.YR75#^K@Z6?I[N:'"1;G%NKWZ:C?&^D9Z1CJV>EIZ.3ILM\9ZFWH +MCNDAZMGI?^DGV,#I@NDVYQE=X.F&ZG#WP'J-.H,ZGWG!NH^ +MYDOIB>@UZH#B!NC`Z4?F;.F1Z!GJC^$DZ@OB(MK`Z8_G!NI2YBOJH^C7Z<[? +M^^G3WP[J*%T>Z:[H_MFE:5W@6>E0Z2M=).GAW^[I7.H!ZN3?3^D\YBY=7>K= +MZ>CBI6DJXLG=:>J6YW8I7>J^X0_G;NIAZNGI4>KGXFSI:;/WZ7CJ;>*E:?#I +MLN8VO^7H7.F`ZE_J@.I[ZCD7^ND_ZCI=7>I2Z4OI0K,HZ8WJ(>A]V3,%&PKQ +MV;G9M=F2ZOK9Z=G/!Y?JP-E#VU&_D^KUV>W9#.G!YGU=+>DE&R_IINJ\Z:CJ +M>N=;ZC@27.FMZE_JK>J%ZK'JJN@[Z(-=I>J>Z('BDNI$YXSH-K]U$GWI--3_ +M!1OJU]/!ZJS=Q.H!X,;JW-W_!=+I+M_*ZL7J>`>JX6O:S>J0Z9;7_P6RZ`+I +MJIV/\%].FRY_OJ].J'ZC3<_NK1W_\% +M4NG,ZG@'B^ITU`3KX>`*ZP/K4F;+VO\%[^4)ZP[KQ^H3Z_O=8]?_!07IU.<8 +MZ^CJM`(;Z^OJV^H$&POI]N?_!0GCY.K8ZEIF'.NH`23K".GLZBCKW>K:Z/\% +M!>0FZW'7,>LIZ_?J(>K^Z!G5->LOZR+:_P4GZH'4/NOTZBWG$NMXZ&/JW=/_ +M!8GI_>IZ"?3JC>E$ZSCG^NK.K@_K4>L'V[$`TZZL"W.BPXK$< +M7.M,U5[K+.L@ZX#J.>M1Y[$(UPC69^MBZ^GJAV8BZQ78L1P% +MZ@O8=.O.Z@W@]NIWZ_3E'->Q'%3HP.9PU7[K)]F"ZY3BA.L[YD?KJP)KZ?+J +MB>MXZV_I:]2Q'&_I,.NK`C+K:>L7ZY/K-NNQ'+X-SN@MZQ[@[NIIX[$OOY(/KL>N%Z[/K#^4CUK$< +M,^9]Z'8%N.NRZQ/I%^6\ZX_H8]6Q')3H@.N"UN7Z+SJQ^O!Z[#KE.%U +MZ;0'L1RXZMS7]^J4X63HT>N_ZO73LQSVZNL0VNO.ZJ/A>NMC`UGJ*]]Q;$KJ +M=NLC!4SJ,-3DZPOKY^L>YW1LV^OQ$.[KQ>JJD>OKW^LWXG@"=&S+ZO+J>PG2 +MZ3#@^.OTZU;K^^-_X_H>1-WS*X1/L[>M@ZBWAWJS\ZPGK&NQMXASL&>SGWQ+L9>I4ZR7L%^PG +M['+@WJSCZ2?8*^S%ZG+J*.SVWRKL-%T/ZS3L)NQZZGKK-NS)ZH;J->R"ZAGA +MWJP`ZX_K/.P#ZXGJ).R-ZE#?WJQ8ZPB['7K+>PY%Q'K)=7>K`GJ0NQY +MZ_;KYNHY%V/I=NM9["_L$N#'ZESL1.S:LAOL0UU=[([K'NQB[#/LG>O?WMZL +M8N)2[#:O"^MO[&'L/^L)U=ZL*NKIZSD70^MN[&[A:>Q)ZUOL>^%([%..<.Q^ +MX4;K]^M6CCWL.NIG[#[J`>N&[&'L0>KRZCD71^;]ZY#L@NQ'ZA#LU>MK[%1= +M7>Q0ZN_:WJR;['[JIFSOZU81H.PO[/7K_MFC[$3LI^&8[*GL/^Q977#LK.&$ +M[%CLMN&J[&?JDNRVX2#LB0EJZACIA>S#X6/LO.R`[+SLM^S`[+#LIFSQZOWJ +M8EVD['WJ0NS_`AGL`P,U[,WL)NS/["CLT>PS[)@0SNP(ZV[LU>Q?[-GL.^S( +M"<[L4>S@U*9L5.P>[-WLJ.Q:[$_LS@6D[&?IRNP4ZCWK<5W.[!CGV.QF[/'L +MS.P?ZN?L;>S@['1=KNQPZ.WL%0/.[';L%>S][-KL+NIW[)_JO>PRZ@#M3>O8 +M[$_K_.PXZEOLJNJL[*CJP>R*[/KJ@%W.[)'LX^Q%ZACMS.SEZ^?LZ.L`[9[L +MRNR>[*?7T-5%VP'7@-F>&D[58=;RV2CM)>W$UR?MJ-4J[3';=TXD"`-W3 +MZ)?F--0U[;41EN;>/CKM:-2;YEL:Z=;(U&38_-.)`HO99]<#V$;M2MDYV$KM +M.M58V5393>WJV:CFJ^8-"+'F.]NFU8D"0>W"UB/MY1H)USW;$->MYEWM'MRQ +MYC?<0=L^VT+;*MR?V&;M$-=H[3CM;MIK[7@";>TNW&KM+>UQ[3[;:>VCV'#M +M3=54"F[M%]AZ[8D"?.US[7GM+>U@&A#7>.WUUVOMA>VNZ8+MG]?!V9W6CNW5Y6?>D->6[2_C--::[3WDN]6=[8;CG.UGXR7MF^V9[:/M +MD^VZ["``!\X<[8'4J^VLW:[M`>"P[=S=`@K:!,O:M.T'[?73M^WAX+KMT=^T +M[0WM)]B^[:_MTG>[[TF>;;MQ^T'VP(*I>R-V\OMXNNI[NRY]'M +MPNVO[%3:U.U7YGGC\0%DU.OG*.9_X]OM%+/MYA/FX.W&YU/CY.T,[`[FW^V] +M?ESG5./Q`8#=P.VQ[?_M +ML^TB$=+M"]CY[1WL)=4&[KOM`^X>Y_GM9^HNWPWN_NTC[,KA$.Z][;)-MNT6 +M[LKM&.X3[AKNXQTU![N#.X??Q?N/NSFVOGM0>PD[B?N +M%>Y'[$CI^>W7[.#4,NX*[H_JL.SY[4[LK>V^31'NXNP([CSN+^[F[#ON7NQ; +MX?GMZNPM[D3N'>XB$8KKT^U+[A'N\NPT[D[N+^[U[$/N]^Q;U/GM(^I([OOL +M%=CY[7/L&-A=[A'N>>Q1[GOL..XT?RCNN.W=T_GM">UC[@OM7.XW?RCNB.P_ +M[H3A;>+Y[1/M(MKY[8[L3>Z*X1GN>^X;[GWN2NZ7[#'N/7\1[B#M2.XB[7?N +M0'\7[J#A4-__4L_M:]J-[B;NJ^S[[?]2!^Y1[M;M_MF4[COG<-5>"^G6S-N" +MU9SNO^;3ZZ#NH>A``:/NS.N?[IM.U]J<[J[KHNJK[J3NJNVI[J?NM`><[KGK +MK^NH[E[M7>BT[J_NNNY1Z`3C%%,"LP7LE^W:`;_N">ROXL3N]^VAX\?N#^S_ +MY8#77@O$&DSG^N=FU\[N1AK2X]KHT^Y7Y]#N_N?7[@'H`>P^W%X+*`+L[=_M +MOPCAY@[FW^[HYO3M\>WC[N7M!N@"!UG<+>'M[A3LN>T&!X[NI]KP[@SN8M.V +M[?CNRNWZ[A/N_.X=[@8'+.RM[0#OK^T#[['M!>]PYVG5[>XAX57H8]4*[R?9 +M#N^4XA#OA^MX`NWN.NX)U17O!.^O#_WN&N__[@+=[^X&!Q#J-.X@[[OM(^^] +M[08'>>X%[B?O&>\9[0CN*N\F[T7=&MOM[A[M\NXP[QOOA^Y<[M`B^>Y\&[SOO*NF^[A=7X>[>[D+O7^?WXR?OZN/![K/B2._K[E?:==T]-VK=4._\ +MW3;M4=1/[P'63]X.V%;O>`)8[Y_86N]1[PK61]ZFW5ECH>RC`6/OK-UF[P'@ +M:._.]T[U0JR]I9 +M8W#J)=6`[W+O?N]][W76&MM98T#I=-2)[X3OA^]K[ULJ?^^0[P?;66,L[H+O +MDN^/[T;BB.]?*GGO2NP8VEECG>]'VTKHQ06U[L#7KN:C[S?FI^\YYJGOMNM2 +MZ`,!TM3/Z]`DKN^U[J+JJ1/2U#'ILN_8ZQGIKN^L[:CHN^]!YK[O0^;`[T7F +MX`A"[KWO[0BWYL3O5>;)[]/J$"3@""7KE>N6UZD3->6EZYTBSN]OZ]7O+(-R +MZX_8TN\;X+KK*>;C"-WOM>#<[Z_NX^^][B7FX`@$[+WG(.;H[\7NL^+2[[H( +M\N?FYNSOR.YUYB#F433A[>KONN?W[^WO*K]FV,/G8.;[[_3OZ.>*)U$S0^_Z +M[P7P1N_AYU(#BN/=[0#P"/#+[N7JR.=2`Z3MD.8KZ,!W%/"]Z(DB&@+8[LOG +M]N@3\!SPW./!UE`!D[_6U0GIK^DU"E6_)?#%Z*3I5;\VY;';1-:3OR[P^>@G +M\$N_7>TO\#3P1K\V\#/PJ>FX)EW4+.TLZ"SPSS0R\,SHN";XZ";H1?`VZT:_ +M6Q6;ZS?M5C4\Z_[G1K\9ZP+HN"92\"[E5/#7[Y'FLRU/\+3HN";/[POF7?!) +M\&#P'^LEW&+PGNM9V8OM]CXX[0S4DMAH\#L*:O`LW!O7;?!+OR+<;-U4U7+P +M,^U;[3?M*N5&`4:_=NTWY2;P>_`H\/0W*O!Z\&CPR-4MY8#PAO!0`83P9/"! +M\%:_B/!N!:KIC_",\,'5//!0.$/P*>5H\`<&/_!,U9+P:K^C`27PD?`X\#N9 +MB/`K\);PG.BC\%=`H?"%\"/PU(OLU:[PI_#?!:WP,^5! +M\*+GJ?"=\*_P6P2Q\(WPA_!JOX0:?_"F\(OMJ.>]\)GP0K_)\+GPM>`^Z-2+ +MH>ZV[J[FT?`WYM7P.>;7\*SO<^FP!*[KI>_0)-2+K.Y#Z.#PY._C\++NW_!] +MYBWIZ/`OZ>KPO.GL\`7EM>JP!,3KWN]JO_+PXN_4B\GKQ]?T\)KH*^FP!-+K +MT_#G\$'G%.5JO[OJ^?#4BP3QH>_4\'\#*M8SZ,-:"_&5Z`WQY/`*\?OPV_!Y +M#>GP%?'K\!?Q[?`9\>_P1NC#6K#A#/%_`Q_Q#_$A\1'Q9Q6DZ%OJ?P/\ZN3I +M*?$>Z2SQ`>HN\0/J?P,%ZXKI,O$M\>GEA>HU\2+I?P,6[QSI@YDV\3[N@^D[ +M\6WJ?P/%[SWQ1/$V\4?N$>J&F4/Q3!,DZ7\#\.Q!\4WQ+_%2\0COH^I_`^'O +MWO!"OU`3UO!7\27Q>NG3Z]#P)386\=+PM._#6J+B1>=F\;GOB^WRVUSI""0M +M\6SQ./%P\;#L1+_[V]OI])EO\6+N*^HF(T/Q"-QV\:FBS"3IC?$FZ8_Q*.F1\8SQ&.'[[6`*E?%`VI?Q=.I@ +MZ245;>HC%8[Q)N'_Z9_Q`>JC\>S8R`B.UT4.I_'OXC0)JO%NUR$2Q@A+\)\( +M*0D4"6C70X8)`GO8F]<8SK?QL?$,`@<#M/&Y\0H)N_%_UPD)*`&_\6_C7111 +M,[\+;^.O\2<)P_&S\5;IN?%%#J-6P_$T"=/Q==?@6RP)DM?QC"-1">?QF0[P\6C7Z/'S +M\9O7PXSE\>KQ4@E+!TL)FNO[\4,"[?%3">/Q2@EL"777!-#XZMKQ>`"O)V"GP[A/)"/I'R +M++_8Z*HM$T9Z\NX*#D*$\I)$F_(LOPX,1T993GKRE@H\47KR.%&E\BR_VO$! +M2*]2A/)R"K):>O+E5Z_R++_"#5!"%%]Z\JWR`171[Z@$M?*PZ*@$++\9\D8E +MXV5Z\C.\B27CO(GO_[4N?)TGW'R7K\NGICRH9Z8\OCR@?*Z +M%`#SO/+YP$ZGHO)]IZ+R-PJ?\E+G>PKE,6[R4`HG"A'S)R=C,A3S,0J*U"+H +M)X8N"A?S-PK1\AOS-`H=\SH*%_-("N+RT><\P(XT)/,_"B+S!3TJ\RWS&O,H +M\]C@T>\@\S+S)_,Q"OO7,_,5\SCS-O,K"@G8,/,/\S[SL.@2\X\^+O.&$3GS +M52,`)73R!R4%[;GR>2QSFE/SU";@[DWS_B@# +M\^LD'BIW\F,LJ9U3\X,J6O"\\GDL9RM9\](M?0PZ*C4N7/-"+_SRRB\"-V3S +M03"5\@4L`RSP\HALVS)W\IHV*2MO\]?\\]S8?-Y10/SO37BPX?S$T8Q +M)&KSA%61\Z\CM_/T+G_SA$:Q\[WS(@24\\GM9_-%1[/S_TF$\Q1-]2-_\_)* +MP?,23NXDE//Y$*GS2U!@/;GS0O#&\[9;RO/56]OSL%S[\]%=B[TG'HQ]*FO^_-<>U[TTDH; +M]*=\+/3V[;SR+#/F?DWTNG]H]%HX7O1>3VST)3DL].,(2_0T@S'T\0%/]-WR +M.#5>]-D!2?0?A2ST5H<@]-"'7O.LA:#AI/-BB%[T`W$;]&>)+/1])B#TR8LQ +M]*N,^_/%C%[TZ;F3]';T'O3*`CWT^)&,]`:10?3JE*'SX9'4\YB4L?$N9U-C +M(/2*E&_S3)7[\]R5L_,>EP@1&_3\V*SS_)>I\N.8AP,E].^9L?/6 +ME\OL*O03FVKS`EMD]$*=LO1@`^SS?9YT\WX* 0) { + assertEqualMem(buff, image, image_size); + } + if (format_id > 0) { + /* + * Now, read the data back. + */ + /* With the test memory reader -- seeking mode. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + read_open_memory_seek(a, buff, used, 7)); + + if (dot_stored & 1) { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae)); + assertEqualString(".", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + } + /* + * Read and verify the file. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + if (dot_stored & 2) { + assertEqualString("./file", archive_entry_pathname(ae)); + } else { + assertEqualString("file", archive_entry_pathname(ae)); + } + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(8, archive_entry_size(ae)); + + /* Verify the end of the archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, + archive_filter_code(a, 0)); + assertEqualIntA(a, format_id, archive_format(a)); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + } + free(buff); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_7zip) +{ + test_format_by_name("7zip", "copy", ARCHIVE_FORMAT_7ZIP, 0, + "\x37\x7a\xbc\xaf\x27\x1c\x00\x03", 8); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_ar) +{ + test_format_by_name("ar", NULL, ARCHIVE_FORMAT_AR, 0, NULL, 0); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_arbsd) +{ + test_format_by_name("arbsd", NULL, ARCHIVE_FORMAT_AR, 0, NULL, 0); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_argnu) +{ + test_format_by_name("argnu", NULL, ARCHIVE_FORMAT_AR_GNU, 0, NULL, 0); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_arsvr4) +{ + test_format_by_name("arsvr4", NULL, ARCHIVE_FORMAT_AR_GNU, 0, NULL, 0); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_bsdtar) +{ + test_format_by_name("bsdtar", NULL, ARCHIVE_FORMAT_TAR_USTAR, 0, NULL, 0); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_cd9660) +{ + test_format_by_name("cd9660", NULL, ARCHIVE_FORMAT_ISO9660_ROCKRIDGE, 1, + NULL, 0); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_cpio) +{ + test_format_by_name("cpio", NULL, ARCHIVE_FORMAT_CPIO_POSIX, 0, NULL, 0); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_gnutar) +{ + test_format_by_name("gnutar", NULL, ARCHIVE_FORMAT_TAR_GNUTAR, 0, + NULL, 0); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_iso) +{ + test_format_by_name("iso", NULL, ARCHIVE_FORMAT_ISO9660_ROCKRIDGE, 1, + NULL, 0); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_iso9660) +{ + test_format_by_name("iso9660", NULL, ARCHIVE_FORMAT_ISO9660_ROCKRIDGE, 1, + NULL, 0); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_mtree) +{ + test_format_by_name("mtree", NULL, ARCHIVE_FORMAT_MTREE, 2, NULL, 0); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_mtree_classic) +{ + test_format_by_name("mtree-classic", NULL, ARCHIVE_FORMAT_MTREE, 1, + NULL, 0); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_newc) +{ + test_format_by_name("newc", NULL, ARCHIVE_FORMAT_CPIO_SVR4_NOCRC, 0, + NULL, 0); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_odc) +{ + test_format_by_name("odc", NULL, ARCHIVE_FORMAT_CPIO_POSIX, 0, NULL, 0); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_oldtar) +{ + test_format_by_name("oldtar", NULL, ARCHIVE_FORMAT_TAR, 0, NULL, 0); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_pax) +{ + test_format_by_name("pax", NULL, ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE, 0, + NULL, 0); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_paxr) +{ + test_format_by_name("paxr", NULL, ARCHIVE_FORMAT_TAR_USTAR, 0, NULL, 0); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_posix) +{ + test_format_by_name("posix", NULL, ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE, 0, + NULL, 0); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_rpax) +{ + test_format_by_name("rpax", NULL, ARCHIVE_FORMAT_TAR_USTAR, 0, NULL, 0); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_shar) +{ + test_format_by_name("shar", NULL, -1, 0, + "#!/bin/sh\n# This is a shell archive\n", 36); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_shardump) +{ + test_format_by_name("shardump", NULL, -1, 0, + "#!/bin/sh\n# This is a shell archive\n", 36); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_ustar) +{ + test_format_by_name("ustar", NULL, ARCHIVE_FORMAT_TAR_USTAR, 0, NULL, 0); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_v7tar) +{ + test_format_by_name("v7tar", NULL, ARCHIVE_FORMAT_TAR, 0, NULL, 0); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_v7) +{ + test_format_by_name("v7", NULL, ARCHIVE_FORMAT_TAR, 0, NULL, 0); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_warc) +{ + test_format_by_name("warc", NULL, ARCHIVE_FORMAT_WARC, 0, NULL, 0); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_xar) +{ + test_format_by_name("xar", "gzip", ARCHIVE_FORMAT_XAR, 0, NULL, 0); +} + +DEFINE_TEST(test_archive_write_set_format_by_name_zip) +{ + test_format_by_name("zip", "store", ARCHIVE_FORMAT_ZIP, 0, NULL, 0); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_write_set_format_filter_by_ext.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_write_set_format_filter_by_ext.c new file mode 100644 index 0000000..2234503 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_write_set_format_filter_by_ext.c @@ -0,0 +1,211 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * Copyright (c) 2015 Okhotnikov Kirill + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "test.h" +__FBSDID("$FreeBSD$"); + +static void +test_format_filter_by_ext(const char *output_file, + int format_id, int filter_id, int dot_stored, const char * def_ext) +{ + struct archive_entry *ae; + struct archive *a; + size_t used; + size_t buffsize = 1024 * 1024; + char *buff; + int r; + + assert((buff = malloc(buffsize)) != NULL); + if (buff == NULL) + return; + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + if( def_ext == NULL) + r = archive_write_set_format_filter_by_ext(a, output_file); + else + r = archive_write_set_format_filter_by_ext_def(a, output_file, def_ext); + if (r == ARCHIVE_WARN) { + skipping("%s format not fully supported on this platform", + archive_format_name(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); + return; + } else if (r == ARCHIVE_FATAL && + (strcmp(archive_error_string(a), + "lzma compression not supported on this platform") == 0 || + strcmp(archive_error_string(a), + "xz compression not supported on this platform") == 0)) { + const char *filter_name = archive_filter_name(a, 0); + skipping("%s filter not supported on this platform", filter_name); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); + return; + } else { + if (!assertEqualIntA(a, ARCHIVE_OK, r)) { + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); + return; + } + } + + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 0); + assertEqualInt(1, archive_entry_mtime(ae)); + archive_entry_set_ctime(ae, 1, 0); + assertEqualInt(1, archive_entry_ctime(ae)); + archive_entry_set_atime(ae, 1, 0); + assertEqualInt(1, archive_entry_atime(ae)); + archive_entry_copy_pathname(ae, "file"); + assertEqualString("file", archive_entry_pathname(ae)); + archive_entry_set_mode(ae, AE_IFREG | 0755); + assertEqualInt((AE_IFREG | 0755), archive_entry_mode(ae)); + archive_entry_set_size(ae, 8); + assertEqualInt(0, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(8, archive_write_data(a, "12345678", 8)); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + if (format_id > 0) { + /* + * Now, read the data back. + */ + /* With the test memory reader -- seeking mode. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + read_open_memory_seek(a, buff, used, 7)); + + if (dot_stored & 1) { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae)); + assertEqualString(".", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + } + /* + * Read and verify the file. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + if (dot_stored & 2) { + assertEqualString("./file", archive_entry_pathname(ae)); + } else { + assertEqualString("file", archive_entry_pathname(ae)); + } + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(8, archive_entry_size(ae)); + + /* Verify the end of the archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, filter_id, + archive_filter_code(a, 0)); + assertEqualIntA(a, format_id, archive_format(a) & ARCHIVE_FORMAT_BASE_MASK ); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + } + free(buff); +} + +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_7zip) +{ + test_format_filter_by_ext("./data/test.7z", ARCHIVE_FORMAT_7ZIP, ARCHIVE_FILTER_NONE, 0, NULL); +} + +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_zip) +{ + test_format_filter_by_ext("./data/test.zip", ARCHIVE_FORMAT_ZIP, ARCHIVE_FILTER_NONE, 0, NULL); +} + +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_jar) +{ + test_format_filter_by_ext("./data/test.jar", ARCHIVE_FORMAT_ZIP, ARCHIVE_FILTER_NONE, 0, NULL); +} + +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_a) +{ + test_format_filter_by_ext("./data/test.a", ARCHIVE_FORMAT_AR, ARCHIVE_FILTER_NONE, 0, NULL); +} + +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_ar) +{ + test_format_filter_by_ext("./data/test.ar", ARCHIVE_FORMAT_AR, ARCHIVE_FILTER_NONE, 0, NULL); +} + +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_cpio) +{ + test_format_filter_by_ext("./data/test.cpio", ARCHIVE_FORMAT_CPIO, ARCHIVE_FILTER_NONE, 0, NULL); +} + +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_iso) +{ + test_format_filter_by_ext("./data/test.iso", ARCHIVE_FORMAT_ISO9660, ARCHIVE_FILTER_NONE, 1, NULL); +} + +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_tar) +{ + test_format_filter_by_ext("./data/test.tar", ARCHIVE_FORMAT_TAR, ARCHIVE_FILTER_NONE, 0, NULL); +} + +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_tar_gz) +{ + test_format_filter_by_ext("./data/test.tar.gz", ARCHIVE_FORMAT_TAR, ARCHIVE_FILTER_GZIP, 20, NULL); +} + +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_tar_bz2) +{ + test_format_filter_by_ext("./data/test.tar.bz2", ARCHIVE_FORMAT_TAR, ARCHIVE_FILTER_BZIP2, 0, NULL); +} + +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_tar_xz) +{ + test_format_filter_by_ext("./data/test.tar.xz", ARCHIVE_FORMAT_TAR, ARCHIVE_FILTER_XZ, 0, NULL); +} + +DEFINE_TEST(test_archive_write_set_format_filter_by_no_ext_def_zip) +{ + test_format_filter_by_ext("./data/test", ARCHIVE_FORMAT_ZIP, ARCHIVE_FILTER_NONE, 0, ".zip"); +} + +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_tar_bz2_def_zip) +{ + test_format_filter_by_ext("./data/test.tar.bz2", ARCHIVE_FORMAT_TAR, ARCHIVE_FILTER_BZIP2, 0, ".zip"); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_write_set_format_option.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_write_set_format_option.c new file mode 100644 index 0000000..d964df4 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_write_set_format_option.c @@ -0,0 +1,67 @@ +/*- + * Copyright (c) 2011 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +#define should(__a, __code, __m, __o, __v) \ +assertEqualInt(__code, archive_write_set_format_option(__a, __m, __o, __v)) + +static void +test(int pristine) +{ + struct archive* a = archive_write_new(); + int known_option_rv = pristine ? ARCHIVE_FAILED : ARCHIVE_OK; + + if (!pristine) + archive_write_set_format_iso9660(a); + + /* NULL and "" denote `no option', so they're ok no matter + * what, if any, formats are registered */ + should(a, ARCHIVE_OK, NULL, NULL, NULL); + should(a, ARCHIVE_OK, "", "", ""); + + /* unknown modules and options */ + should(a, ARCHIVE_FAILED, "fubar", "snafu", NULL); + should(a, ARCHIVE_FAILED, "fubar", "snafu", "betcha"); + + /* unknown modules and options */ + should(a, ARCHIVE_FAILED, NULL, "snafu", NULL); + should(a, ARCHIVE_FAILED, NULL, "snafu", "betcha"); + + /* ARCHIVE_OK with iso9660 loaded, ARCHIVE_WARN otherwise */ + should(a, known_option_rv, "iso9660", "joliet", NULL); + should(a, known_option_rv, "iso9660", "joliet", NULL); + should(a, known_option_rv, NULL, "joliet", NULL); + should(a, known_option_rv, NULL, "joliet", NULL); + + archive_write_free(a); +} + +DEFINE_TEST(test_archive_write_set_format_option) +{ + test(1); + test(0); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_write_set_option.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_write_set_option.c new file mode 100644 index 0000000..2778234 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_write_set_option.c @@ -0,0 +1,69 @@ +/*- + * Copyright (c) 2011 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +#define should(__a, __code, __m, __o, __v) \ +assertEqualInt(__code, archive_write_set_option(__a, __m, __o, __v)) + +static void +test(int pristine) +{ + struct archive* a = archive_write_new(); + int known_option_rv = pristine ? ARCHIVE_FAILED : ARCHIVE_OK; + + if (!pristine) { + archive_write_add_filter_gzip(a); + archive_write_set_format_iso9660(a); + } + + /* NULL and "" denote `no option', so they're ok no matter + * what, if any, formats are registered */ + should(a, ARCHIVE_OK, NULL, NULL, NULL); + should(a, ARCHIVE_OK, "", "", ""); + + /* unknown modules and options */ + should(a, ARCHIVE_FAILED, "fubar", "snafu", NULL); + should(a, ARCHIVE_FAILED, "fubar", "snafu", "betcha"); + + /* unknown modules and options */ + should(a, ARCHIVE_FAILED, NULL, "snafu", NULL); + should(a, ARCHIVE_FAILED, NULL, "snafu", "betcha"); + + /* ARCHIVE_OK with iso9660 loaded, ARCHIVE_WARN otherwise */ + should(a, known_option_rv, "iso9660", "joliet", NULL); + should(a, known_option_rv, "iso9660", "joliet", NULL); + should(a, known_option_rv, NULL, "joliet", NULL); + should(a, known_option_rv, NULL, "joliet", NULL); + + archive_write_free(a); +} + +DEFINE_TEST(test_archive_write_set_option) +{ + test(1); + test(0); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_write_set_options.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_write_set_options.c new file mode 100644 index 0000000..db7e50e --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_write_set_options.c @@ -0,0 +1,126 @@ +/*- + * Copyright (c) 2011 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +#define should(__a, __code, __opts) \ +assertEqualInt(__code, archive_write_set_options(__a, __opts)) + +static void +test(int pristine) +{ + struct archive* a = archive_write_new(); + int halfempty_options_rv = pristine ? ARCHIVE_FAILED : ARCHIVE_OK; + int known_option_rv = pristine ? ARCHIVE_FAILED : ARCHIVE_OK; + + if (!pristine) { + archive_write_add_filter_gzip(a); + archive_write_set_format_iso9660(a); + } + + /* NULL and "" denote `no option', so they're ok no matter + * what, if any, formats are registered */ + should(a, ARCHIVE_OK, NULL); + should(a, ARCHIVE_OK, ""); + + /* unknown modules and options */ + should(a, ARCHIVE_FAILED, "fubar:snafu"); + assertEqualString("Unknown module name: `fubar'", + archive_error_string(a)); + should(a, ARCHIVE_FAILED, "fubar:snafu=betcha"); + assertEqualString("Unknown module name: `fubar'", + archive_error_string(a)); + + /* unknown modules and options */ + should(a, ARCHIVE_FAILED, "snafu"); + assertEqualString("Undefined option: `snafu'", + archive_error_string(a)); + should(a, ARCHIVE_FAILED, "snafu=betcha"); + assertEqualString("Undefined option: `snafu'", + archive_error_string(a)); + + /* ARCHIVE_OK with iso9660 loaded, ARCHIVE_FAILED otherwise */ + should(a, known_option_rv, "iso9660:joliet"); + if (pristine) { + assertEqualString("Unknown module name: `iso9660'", + archive_error_string(a)); + } + should(a, known_option_rv, "iso9660:joliet"); + if (pristine) { + assertEqualString("Unknown module name: `iso9660'", + archive_error_string(a)); + } + should(a, known_option_rv, "joliet"); + if (pristine) { + assertEqualString("Undefined option: `joliet'", + archive_error_string(a)); + } + should(a, known_option_rv, "!joliet"); + if (pristine) { + assertEqualString("Undefined option: `joliet'", + archive_error_string(a)); + } + + should(a, ARCHIVE_OK, ","); + should(a, ARCHIVE_OK, ",,"); + + should(a, halfempty_options_rv, ",joliet"); + if (pristine) { + assertEqualString("Undefined option: `joliet'", + archive_error_string(a)); + } + should(a, halfempty_options_rv, "joliet,"); + if (pristine) { + assertEqualString("Undefined option: `joliet'", + archive_error_string(a)); + } + + should(a, ARCHIVE_FAILED, "joliet,snafu"); + if (pristine) { + assertEqualString("Undefined option: `joliet'", + archive_error_string(a)); + } else { + assertEqualString("Undefined option: `snafu'", + archive_error_string(a)); + } + + should(a, ARCHIVE_FAILED, "iso9660:snafu"); + if (pristine) { + assertEqualString("Unknown module name: `iso9660'", + archive_error_string(a)); + } else { + assertEqualString("Undefined option: `iso9660:snafu'", + archive_error_string(a)); + } + + archive_write_free(a); +} + +DEFINE_TEST(test_archive_write_set_options) +{ + test(1); + test(0); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_archive_write_set_passphrase.c b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_write_set_passphrase.c new file mode 100644 index 0000000..4bfcbb2 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_archive_write_set_passphrase.c @@ -0,0 +1,95 @@ +/*- + * Copyright (c) 2011 Tim Kientzle + * Copyright (c) 2014 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +struct archive_write; +extern const char * __archive_write_get_passphrase(struct archive_write *); + +static void +test(int pristine) +{ + struct archive* a = archive_write_new(); + struct archive_write* aw = (struct archive_write *)a; + + if (!pristine) { + archive_write_add_filter_gzip(a); + archive_write_set_format_iso9660(a); + } + + assertEqualInt(ARCHIVE_OK, archive_write_set_passphrase(a, "pass1")); + /* An empty passphrase cannot be accepted. */ + assertEqualInt(ARCHIVE_FAILED, archive_write_set_passphrase(a, "")); + /* NULL passphrases cannot be accepted. */ + assertEqualInt(ARCHIVE_FAILED, archive_write_set_passphrase(a, NULL)); + /* Check a passphrase. */ + assertEqualString("pass1", __archive_write_get_passphrase(aw)); + /* Change the passphrase. */ + assertEqualInt(ARCHIVE_OK, archive_write_set_passphrase(a, "pass2")); + assertEqualString("pass2", __archive_write_get_passphrase(aw)); + + archive_write_free(a); +} + +DEFINE_TEST(test_archive_write_set_passphrase) +{ + test(1); + test(0); +} + + +static const char * +callback1(struct archive *a, void *_client_data) +{ + int *cnt; + + (void)a; /* UNUSED */ + + cnt = (int *)_client_data; + *cnt += 1; + return ("passCallBack"); +} + +DEFINE_TEST(test_archive_write_set_passphrase_callback) +{ + struct archive* a = archive_write_new(); + struct archive_write* aw = (struct archive_write *)a; + int cnt = 0; + + archive_write_set_format_zip(a); + + assertEqualInt(ARCHIVE_OK, + archive_write_set_passphrase_callback(a, &cnt, callback1)); + /* Check a passphrase. */ + assertEqualString("passCallBack", __archive_write_get_passphrase(aw)); + assertEqualInt(1, cnt); + /* Callback function should be called just once. */ + assertEqualString("passCallBack", __archive_write_get_passphrase(aw)); + assertEqualInt(1, cnt); + + archive_write_free(a); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_bad_fd.c b/dependencies/libarchive-3.4.2/libarchive/test/test_bad_fd.c new file mode 100644 index 0000000..f8144a3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_bad_fd.c @@ -0,0 +1,37 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/lib/libarchive/test/test_bad_fd.c,v 1.2 2008/09/01 05:38:33 kientzle Exp $"); + +/* Verify that attempting to open an invalid fd returns correct error. */ +DEFINE_TEST(test_bad_fd) +{ + struct archive *a; + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(ARCHIVE_FATAL == archive_read_open_fd(a, -1, 1024)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_bzip2.c b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_bzip2.c new file mode 100644 index 0000000..7df086f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_bzip2.c @@ -0,0 +1,89 @@ +/*- + * Copyright (c) 2003-2008 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_compat_bzip2.c 201247 2009-12-30 05:59:21Z kientzle $"); + +/* + * Verify our ability to read sample files compatibly with bunzip2. + * + * In particular: + * * bunzip2 will read multiple bzip2 streams, concatenating the output + * * bunzip2 will stop at the end of a stream if the following data + * doesn't start with a bzip2 signature. + */ + +/* + * All of the sample files have the same contents; they're just + * compressed in different ways. + */ +static void +compat_bzip2(const char *name) +{ + const char *n[7] = { "f1", "f2", "f3", "d1/f1", "d1/f2", "d1/f3", NULL }; + struct archive_entry *ae; + struct archive *a; + int i; + + assert((a = archive_read_new()) != NULL); + if (ARCHIVE_OK != archive_read_support_filter_bzip2(a)) { + skipping("Unsupported bzip2"); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + extract_reference_file(name); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 2)); + + /* Read entries, match up names with list above. */ + for (i = 0; i < 6; ++i) { + failure("Could not read file %d (%s) from %s", i, n[i], name); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae)); + assertEqualString(n[i], archive_entry_pathname(ae)); + } + + /* Verify the end-of-archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify that the format detection worked. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_BZIP2); + assertEqualString(archive_filter_name(a, 0), "bzip2"); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_BZIP2); + assertEqualString(archive_filter_name(a, 0), "bzip2"); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); + + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + +DEFINE_TEST(test_compat_bzip2) +{ + compat_bzip2("test_compat_bzip2_1.tbz"); + compat_bzip2("test_compat_bzip2_2.tbz"); +} + + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_bzip2_1.tbz.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_bzip2_1.tbz.uu new file mode 100644 index 0000000..989af82 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_bzip2_1.tbz.uu @@ -0,0 +1,24 @@ +$FreeBSD: head/lib/libarchive/test/test_compat_bzip2_1.tbz.uu 185683 2008-12-06 07:08:08Z kientzle $ + +begin 644 test_compat_bzip2_1.tbz +M0EIH.3%!62936;12^)(``#-;D=$00`!_@``!8RT>$`0`$```""``5#5/*'J> +MD#(&30_5!H4_5-ZH`T``327U4@&L('"(9-%8<7&$I,`:7FXH+*\GV#JF<`PK29-8'OPDG36S\7HR&C(T:/U0:$U'I +MJ!ZC0`#VECO\[$10H'-Z@F*:6A1$H$V("2G0Q(U0(8=(7AK$S04#!)RXOAP% +MP:D%#Q;NO)\4UL23'2[\7````6YC1 +M$$`$?X```6,M'A`$`!````@@`'4-4S*,U!HT!HT?J@T)E-I--!H`![60EIH.3%!629364RNM^,```#?L-$00`#_@`0```AG +M+1X0`!`$```((`!U#5-,:1IH`TT,1^J#)&H]3U`T``!CX[_.[`F40.64EC"D +M()+?KX6,VP?6Y;F%5$XR[Y/D#*9),K3^+N2*<*$@9@ +MX6(`0EIH.3%!62936>ZM4*4```);D-$00`#O@``(9ST>$`0```@@`'0:IFC2 +M&F@!B:/U0:$R&H:&@`"KS^U=Y`BC`#FY2*9-8%%&13E$@%8ZF(&J!##]!#E` +MKVL'2LUW2.*C08`$)::#DQ05DF +?4UDI/)=P````0!!```0`(``A`(*#%W)%.%"0*3R7<``` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_bzip2_2.tbz.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_bzip2_2.tbz.uu new file mode 100644 index 0000000..9ba63e8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_bzip2_2.tbz.uu @@ -0,0 +1,11 @@ +$FreeBSD: head/lib/libarchive/test/test_compat_bzip2_2.tbz.uu 185683 2008-12-06 07:08:08Z kientzle $ + +begin 644 test_compat_bzip2_2.tbz +M0EIH.3%!629361HI1P<``4#;D-$00`#_@``)9RT>$`0``!@P`/@#&$Q,F`F` +M`,83$R8"8``1133"1/2-J-#$/U3@;XVF9V'`Y3882XA$*KO6\WTL`]QU&J"8 +M$-=*Q$\@=`=QJ,TQ;3UH,NPT$-(!"HV&!ZO5D&@P-1D&1@'L<8&209QV9'G` +MW&PRZ0Q(-BT%&DG*DE.!U*#J.P]*#%-P9G`W9+34:#S&M`;@^1R^![C]:Y)U +MDF9/(\AR/@?P@^@I_B[DBG"A(#12C@X!3;VUE(&UOV=QL!06ER26`1T2G9F:EY)54XJ +MN>9`/*(`IX<(2#/D&F@GC`(Z``#S57',@'E&`TT,$I!EQ +M#;031@$5`0`Q!<\4Z`,``!^+"`B8OB))``-T97-T+7-P;&ET+G1A$0!3@\1D&;,-=!.&`5D``#7L]HO +MZ`,``!^+"`B8OB))``-T97-T+7-P;&ET+G1A57',@'E&`TT,$I!ER#;031@$>``"Y*#OBZ`,``!^+"`B8 +MOB))``-T97-T+7-P;&ET+G1A@ALXPP`]CXF=Q&A<:-UX>EN)C5M,AL;P +MO@V[0A=_.E39F2.B'*.?5QX2?Z\?XGE&27)F]L0)V>E_'7YY07\>OZ)Y1W6Q\!-J3!?H^Z_J7TG]%_"QK0?\]4[/>HZS^_^T\! +M_;>@@OY[=N2]6E\!JOH/P])_2OC^-X'YOV]+_]97@*K^A4K_C/Y;P/S?MZ5_ +MZRM`7?]<^L?_OR8P_P,`].D%,XR2*0`<``!4:&ES(&ES('5NFQE%0`/ +M`@`@`LL``-T```(`'R!"`"`/`@!B/V8Q"G@`8@\"`/]V+V8RB@%/#P`$&Q(S +M``0?-@`$_U4?,@`$_^T?,P`$?1$V``0O-3(`!/]5'S,`!/_G4``````````` +M`";]7\`$(DT89'"YL@```&]D,2]F,0`!`$OH,#`P-C0T(``P,#$W-3$(``0" +M`/\(,R`Q,3$Q,#4S-C8R-R`P,3$U-38`(#"7`$L"`@#R`75S=&%R`#`P:VEE +M;G1Z;&46``\"`!\"RP``W0```@`?($$`'P\"`&,_9C$*>0!C#P(`_W4```0? +M,HP!3`\`!!HB,S``!!\Q``3_51\R``3_\!\S``1Z$C$`!!\S``3_51\S``3_ +6[`\"`/___^M0````````````;,,BR0`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lz4_2.tar.lz4.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lz4_2.tar.lz4.uu new file mode 100644 index 0000000..5efdd74 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lz4_2.tar.lz4.uu @@ -0,0 +1,13 @@ +begin 644 test_compat_lz4_2.tar.lz4 +M!")-&&1PN:8````_9C$``0!.Z#`P,#8T-"``,#`Q-S4Q"``$`@#_"#,@,3$Q +M,3`U,S8V,3$@,#$Q,C0S`"`PF@!.\00```!UFQE%0`/ +M`@`@`LL``-T```(`'R!"`"`/`@!B/V8Q"G@`8@\"`/]V+V8RB@%/#P`$&Q(S +M``0?-@`$_U4?,@`$_^T?,P`$?1$V``0O-3(`!/]5'S,`!/_G4``````````` +M`";]7\`$(DT89'"YL@```&]D,2]F,0`!`$OH,#`P-C0T(``P,#$W-3$(``0" +M`/\(,R`Q,3$Q,#4S-C8R-R`P,3$U-38`(#"7`$L"`@#R`75S=&%R`#`P:VEE +M;G1Z;&46``\"`!\"RP``W0```@`?($$`'P\"`&,_9C$*>0!C#P(`_W4```0? +M,HP!3`\`!!HB,S``!!\Q``3_51\R``3_\!\S``1Z$C$`!!\S``3_51\S``3_ +M[`\"`/___^M0````````````;,,BR51H:7,@:7,@=6YR96QA=&5D(&IU;FL@ +<9&%T82!A="!T:&4@96YD(&]F('1H92!F:6QE"@`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lz4_3.tar.lz4.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lz4_3.tar.lz4.uu new file mode 100644 index 0000000..97e79fb --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lz4_3.tar.lz4.uu @@ -0,0 +1,9 @@ +begin 644 test_compat_lz4_3.tar.lz4 +M`B%,&/X````_9C$``0!.Z#`P,#8T-"``,#`Q-S4Q"``$`@#_"#,@,3$Q,3`U +M,S8V,3$@,#$Q,C0S`"`PF@!.\00```!UFQE%0`/`@`@ +M`LL``-T```(`'R!"`"`/`@!B/V8Q"G@`8@\"`/]V+V8RB@%/#P`$&Q(S``0? +M-@`$_U4?,@`$_^T?,P`$?1$V``0O-3(`!/]5'S,`!/_L/V0Q+P,,3@\`"!H@ +M,C<`!"\U-0`(_U8/``S_[0``!`\##$T/``0:(C,P``0?,0`(_U4/``S_[0`` +E!`\##$T/``0;`0`4+S4U`!3_5@\`#/_M#P(`____ZU`````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lz4_B4.tar.lz4.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lz4_B4.tar.lz4.uu new file mode 100644 index 0000000..329a853 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lz4_B4.tar.lz4.uu @@ -0,0 +1,6739 @@ +begin 644 test_compat_lz4_B4.tar.lz4 +M!")-&&1`IY41``!O>&9I;&4``0!+X3`P,#8T-"``,#`P-S8U"``B,#(0`"(R +M,`$`_P<@,3(S-3,U-3,U,3(@,#$R,#(S`"`PEP!+`@(`KW5S=&%R`#`P8W4' +M`0M22T`5RH@8V%T:0`K871H`&!S:6UP;&5H`@6U`$!T;V]L +M,P$`0``#`@!R>F-A="P@8@<`$G@'``!)`4!S=6-H)P!0*B!E>&%)`$!S.B!3 +M,@-46]U(&UA>2!F:6YDT`(Q9G5L+P(&10!1 +M+VUI;FF%`1%AXP%186-T('-@`*$@9&5M;VYS=')AP0$`#@,G;V9>`0-)`#!C +M;VY#`O`".B`@5F%R:6]UP``"@+Q`F%U=&AO7-T96TZ"B`J(+@$=2XQ(&5X<&R# +M`@,O`P!"`0(A``2:`P,S``"(!`\T``L`(@`,-0`O870T``PH870S``8!!H`N +M,R!G:79E<]\&@&]V97)V:65W\P(`H``$NP4087$%,'=H;Y$"(RH@V0>%7W)E +M860N,RP0``#1!1UE$0!17V1I]!;!I;@IA(&YU;6)E`D09BP``;<&42H@1TY5=0$" +M-0(F("@$"P`:`$%L;VYG4`9B;F%M97,L$```!0L3(!$``&,`4G-P87)S?`(A +M`@@;W#+`\!A;"!2;V-KB,``!DT%``)"`$```I58W)E873/ +M``%U!`\&`0("J@,#OP,"O`(/'P,8,")R9:`-46-T960B1P,"3P#$+"!W:&EC +M:"!W:6QLB@`!5@`%R@%A(&5X8V5P0`4`N04$:0)1('1H871##C%I\+`OH#`*D"!B($`88!`MH` +M#Y8#!0'(`V$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0%!`);`0&)``]9`P`* +M%@,S5VAE`P((T0X"Y@5A`3AN97>U`P#P!`![``-S!`![``&'"0&C``)*#`!-$2)I +M7-S""IE9(H(`D<`<$DG=F4@870M#0",!S!T;R`A$+)M +M:7IE('-T871I8U((07!O;&PV$E$N("!)9O4(061O;B<<$Y!E>'!L:6-I=&S9 +M"4!V;VMEO!(!ZP`!?PH#SA$@("C2$"4@8?L*`*D`("!AL@$!)Q`"+0`(S0`4 +M;Y4(<"DL(&ET('=P`$$@9V5T&1,!70H`I`0W($EN;@`W+"!IG@`!40$#FP`B +M96[)`07L#$7`U`-%A=&5V97(@8FQO8VMS\```[@2X'<70@ +M82!T:6U7`W%O@``S0)P82!S;V-K9687`CX#27=I4X.``P1$2(A`0!:""`L(E`(H"P@8V%P86)I;&D2%`8# +M`07Q``+S#P&W!`CV!0&7`8`@:6YD:79I9&P.`]L(`(4``#H2`D(``*P+`-$` +M`#8!(71OK`TP9&%TUP``!0X6.BX!`L@)`#T`$F'L`@#)"@$K`#-I;B`G`0"/ +M`C!A9&1T!`!,``CW#`&I"@,>#U%F:7)S=)("`*8!$6%P$A%O\0T`]@`6+G0` +M`]D#`J0#`',*`.$G;71R964G(&9O +M$E33SDV-C`3`%HW+5II<#D`-EA!4A$`Y0I7:&5N(&-R96%T:6YG +M&`#Q&2P@=&AE(')EFEPX0`Q:6]N%0!=8GII<#(6 +M``0'`4TO3%I7'0"Q;'IM82P@;'II<"P4`2EX>B,`P0I.;W1E7-T96TN("!4:&5R92P`@&YO(&1I'!L86EN:6YGR0`P:&]W^``"]0`'+``"*@$A3VZJ`!PL`P$`48!`-T!\@%E9"!A=71O;6%T:6-A;&QY1P"P22=V92!A='1E +M;7#7`>!T;R!M:6YI;6EZ92!S="L`L"!L:6YK('!O;&QUN`'A+B`@268@>6]U +M(&1O;B?L`0"V`/$":6-I=&QY(&EN=F]K92!A('#K`(!U;&%R(&9E85D"0"`H +MD`!RT`!.<#`R("`ID!<"DL(&ET('=P`/``(&=E="!P=6QL +M960@:6XN/@`G26YN`#``%1`0.;`")E;LD!!RT``#X`"W$`*&1E$0`# +MQ@(1+/```H``(FYEC@(`%@$`0`!B86=A:6YS1P*@8V]R7L#$7`U`-%A=&5V97(@8FQO8VMS\``0:%<%(6ETH0!!66]U +M717`F$@82!T:6U7 +M`W%O`+$@(&)S9'1AX`0!V``*4`0"A`P&3``)/!R)L>8<``J,!!H`%,7=A;H@`$'0V!`5%`0!@ +M`!!IA0(`C@%EB!$!GF-A="P@8@<`$G@'``!)`0"2 +M"0`G`%`J(&5X84D`0',Z(%,R`U1S;6%L;!4`!#X!`%(#(6%T'`@@;6'F!"!N +M9-`",69U;"\"!D4`$"]#"@&%`1%AG@I186-T('-@`)(@9&5M;VYS=')*#0`I +M!B=O9EX!`TD`,&-O;D,"\`(Z("!687)I;W5S(&ET96US(#,!`'T#0&UE(&(W +M`3)I0&";8"(FENU@0`I`H`ZP4$O0+P`DY% +M5U,@+2!H:6=H;&EG:'1S7`8PH($',+!0$^`0!U```7`@#Y!`%Q +M``%Q"@B7```\"3-Y+C--``#O!#)E(")K`P6K``$D`!0B"PM9(&-L87-$``$? +M"49N86QSG0`2!Q(M@@0U]!9!I;@IA +M(&YU;6+R#!=FD0<$.P''"@I9;W4@ +M`*%35E(T($%30TE)=`(!%``/,@`+$$)M$1%Y+@"Q("AB:6%T`/ +M"Q<`T$UI8W)O"T4``("`+D%!(D1`@L7`UH7`5$`!>D2,',@*%,*`30$`(0!`S,$`/0#8"P@ +M971C*>\+`OH#`&P$`&T``HT``9L!`MH`#\@#"F$B;F5W8R*;`P$S`"=S:+`` +M`1(`#T8#8P0%!`?.``]9`P`*%@,/9!K_____________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________XE!E=&%I;%H1``#U'G,@=&AE +M(")S=')U8W0@87)C:&EV95]E;G1R>2(@=71I;&ET>2!C;&%SP#S"2P@:6YC;'5D:6YG +M(&AA``"/`/0:("=D;V,G +M(&1I2!I;@IA(&YU;6)E6]U(#\!8"X*"D-U\!`DD` +M-%I)4%8#!$``P'5N8V]M<')EB,``!DT%``) +M"`&58V%N(&-R96%TSP`!=00/!@$"`J\!`[\#`KP"#Q\#&,$B!S>7-T96TN("!4 +M:&5R92P`(VYOX@<`@@(#WP@`DP3R`B!I;BUP;&%C92!M;V1I9FECK0CS`F]R +M(')A;F1O;2!A8V-E0`&@`3R`FES(&1EP`#P`!APD!HP!4(&]N;'D*`P`X"`"R``$>`P"F +M!`(,`B$@8C<)<7)E861A8FP`!D%W48!`-T!*F5DB@@"1P"P22=V92!A='1E;7",!^!T;R!M:6YI +M;6EZ92!S=+4(`E((4'!O;&QU(@=1+B`@26;U"$!D;VXGU@7L#$7`U`-%A=&5V97(@8FQO8VMS\``` +M[@2X'<70@82!T:6U7`P!K"S%M87#X`C!E;G21!@/0`@%1`T!G:79EY@$A=&\B +M``6A`&%T(&]N8V6%`"%/;I`#&V7#``+D`C)P@``P0&%82!S;V-K970^`TEW:7-HN@0!)@\# +M60\`0#`',*T2!S87ES+@I214%$3442!@9)$>$@8G5N9&QE+@H*475E<_H" +MH#\@($ES8$(&YDT`(Q9G5L +M+P(&10`0+T,*`84!$6&>"C1A8W1[$W!D96UO;G-T.14@;F<^``"`!094`@-) +M`#!C;VY#`F$Z("!687+N$V!I=&5M$0(8 +M`&!C;VYF:6=^"Q4M#``"1`"UM`Q$SM@L`$!20(&]V97)V:65W\P(`JP`%P`L`<04P=VAOD0(4*J0* +MA5]R96%D+C,L$``!^`@-$0!17V1I2#R`I!I;VYS+@H*5&B=`?("<"UL979E;"!D:7)E8W1O'2(`#!P=71>`H$@(F-M86ME(B0#:60@ +M=&]O;$T``E8!!NL#`2D!,2!I;DP!#VT!`3!A2!N965D?``Q;6%I]@$C97)<`05P`"1I;F0`\@,N:"YI +M;@H)+2!T96UP;&%T97-G`!%B-`(!9@$39;4`8`H*1W5I9/,`4"!$;V-UF04" +M@0$`Q0$R86QL=0`!MP&R'!L@P(#+P,`0@$" +M(0`$F@,#,P``B`0/-``+`"(`##4`+V%T-``,*&%T,P`&`0:`+C,@9VEV97/? +M!H!O=F5R=FEE=_,"`*``!+L%$&%Q!3!W:&^1`B,J("X'A5]R96%D+C,L$``` +MT04=91$`45]D:7-K%@`@;F30`0@^``,<``"9`!!V7P$"MP)A960@8V%LB0<0 +M<]0&06YC97.M`@"3``!U``%'``-"!FAE($%027.7`'-E;G1R>2XS30`"]P,2 +M(FL#!:L``20`4"(@=71II`59(&-L87-$``'O!49N86QSG0`P] +M!;!I;@IA(&YU;6)E`D09BP``;<&42H@1TY5=0$"-0(B +M("BK"0"Y`0`:`$%L;VYG4`9B;F%M97,L$`!3;&EN:R`1``!C`%)S<&%R'1E;J+``-J +M`0`9`]$J(%!/4TE8('5S=&%R6P`"$``R<&%X-`,"60<#>`('(0#`;V-T970M +M;W)I96YT%P0@<&E^"<8J(%-64C0@05-#24D4``)3``\R``5A0FEN87)Y+@#` +M("AB:6B,``!DT%``)"`$```I58W)E873/ +M``%U!`\&`0("J@,#OP,"O`(/'P,8,")R9:`-46-T960B1P,"3P#$+"!W:&EC +M:"!W:6QLB@`!5@`%R@%A(&5X8V5P0`4`N04$:0)1('1H871##C%I\+`OH#`*D"!B($`88!`MH` +M#Y8#!0'(`V$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0%!`);`0&)``]9`P`* +M%@,S5VAE`P(`?`4#U`(2<^8%87)E`3AN97>U`P#P!`![``.?`0![``&'"0&C``)*#`!- +M$2)IF4@ +M``%1`0.;`")E;LD!!RT``'P`"W$`*&1E$0`#Q@(1+/```H```(T.`)8!`!8! +M`$``,&%G82X.`?$)D6-OP,1<#4`T6%T979E$P$/`P*A%0"V`A!GJA40:2(3 +M`2(`!4H``.,3(6-EA0`A3VZ0`QMEPP`"Y`(R<')O.@$!A0%18W1L>2W,`))E +M9"!O=71P=73O`@!@!/$#;V)J96-T+7-T>6QE(&%P<')OR`,`^10"^@!0=&\@ +M:&$Y%D!U;'1IPQ,$J0`"`00`N0A5(&]P96Z>`!,@%1``:A``"@$`/06#;B!I +M=',@(D`\`!(BO0012!F4X.``P1$2(A`0!:""`L(E`(H"P@8V%P86)I +M;&D2%`8#`07Q``+S#P$_#@CV!0&7`8`@:6YD:79I9&P.`]L(`(4``#H2`D(` +M`*P+`-$``#8!(71OK`TP9&%TUP``!0X6.BX!`L@)`#T`$F'L`@#)"@$K`#-I +M;B`G`0"/`C!A9&1T!`!,``CW#`&I"@,>#U%F:7)S=)("`*8!$6%P$A%O\0T` +M]@`6+G0``]D#`J#B)A;N@"`*4'!C0*$"QC`$!D97-PH@``;`0!Y`,`7,N"B05 +M$6:X#06Y&0*A&$0N"@I1$19`/R`@2:T9(',_4@`4*I491G=W=RXX`$`N;W)G +MDP``2`$0:+@"`%<`0V]N9V]8!Q<@3`<@(&18%B!O<#P%"!D1!+H1`:P(`3<, +M`'$``#H`'VYD&O______________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________:E!I=F4@92@1``#Q$6YT7,@9&5T96-T960@ +M875T;VUA=&EC86QL>4<`L$DG=F4@871T96UP(@#@=&\@;6EN:6UI>F4@6]U(&1O;B=TJ```M@#Q`FEC:71L +M>2!I;G9O:V4@82!PZP#P#G5L87(@9F5A='5R92`H``%1`0.;`%IE;F%B;)L``#X`"W$`*&1E$0`#J@`1 +M+/```H``(FYE)@$`%@$`0`!Q86=A:6YS=,\!V6-O8`0U: +M`)%L:6)R87)I97/#`/$"5&AI3X`!8P``+$!\09P"!I;G1E7,N"E)%041-12X`!^@& +MX2!B=6YD;&4N"@I1=65S^@*@/R`@27-S=65S/U(`UBH@:'1T<#HO+W=W=RY, +M!T`N;W)GDP``2`$0:+@"@V9O0(1.FH` +M$B>7!9`G('!R;V=R86T6`G-A(&9U;&PME@AP9"`G=&%R)WX``P(`4W)E<&QA +M0@%`8G5I;($&`(H``V,``"H`9BH@8W!I;V,```X`"V0`(&1I:P4R96YT,`-# +M9F%C96H#`P(`,&5S`<``$D!`)()`"<` +M4"H@97AA20!`8$(&YDT`(Q +M9G5L+P(&10`0+T,*`84!$6$&"5%A8W0@`0-)`#!C;VY#`O`".B`@5F%R:6]UP``7P%Q875T:&]R<\`%`1\&`?("`DT' +M$`J(!E!T;W`M;`P$`W8%`#`'`4$`$&GD!@FV`B)I;M8$`'$+`.L%!+T"\`). +M15=3("T@:&EG:&QI9VAT=&%R+C54`0CQ!$%A8F]U4P41]!9!I;@IA(&YU;6+R#!=FD0<$.P''"@I9;W4@`D09@82`;<&42H@1TY5=0$"-0(F("@$"P`:`"-L;[P%`*T+(G,L +M$```!0L3(!$``&,`4G-P87)S?`(A`*%35E(T($%30TE)=`(!%``/,@`+$$)M$1%Y +M+@"Q("AB:6`@@;W#+`\!A;"!2;V-K[`@0]`5HW+5II<"8`V$UI8W)OFEP/@$@:6]/$WTJ(&)Z:7`R +M%@`$?`%-+TQ:5QT`HFQZ;6$L(&QZ:7`3`R]X>B,``!DT%``)"`$```H"G!`% +M.@$`=00/!@$"`J\!`[\#`KP"#Q\#&#`B0`&@`0I:7-N%")B98@%`$`$`5X!.&YE +M=[4#`/`$`/T"`Y\!`'L``8<)`,,7$F5*#`!-$2)I2!D971E8W1S(&%N9"!R96%D +MFEP/@$Q:6]N!0%=8GII<#(6``1D`4TO3%I7'0"B +M;'IM82P@;'II0`&EP"0:7,@9&5S:6=NH@9";R!B98@%`$`$`3`$.&YE=[4#`/`$ +M`'L``4,` +M4&EN9&5PJ@`B;G1_`!!R.P0`!``P=&EC0@4D;VZ!`02N`/``5VEK:2!E>'!L +M86EN:6YGB0`P:&]W^``!LP,09)8%`RP``BH!(4]N/P@<+`,!``0$,FUA='`` +M0&QW87E&`0#=`2IE9(H(`D<`L$DG=F4@871T96UPC`?@=&\@;6EN:6UI>F4@ +M2!I +M;G9O:V4@82!PZP`@=6R]"*!E871U``%1 +M`0.;`")E;LD!!RT``'P`"W$`*&1E$0`#J@`1+/```H``(FYEC@(`%@$`0`!Q +M86=A:6YS=,\!D6-OP,1<#4`T6%T979E`%`@(&)S9",' +M(75SO`$`/06#;B!I=',@(D#E`!(BO01&"2`L(E`(<"P@8V%P86)!``'V`@)F!A%E50(!\0!A92!!4$ES +MMP0(]@4!EP&Q(&EN9&EV:61U86QH!1%I0@@`>P`28D(``$X&`-$``#8!(71O +MFPDP9&%TUP!6=7)C93HN`0+("0#"`!)A[`(`R0H!*P`S:6X@)P$`E0LS861D +MC@(88?<,`=<'(6]U]P119FER0"0:7,@97-P96-I;@0!T`$"J@$`.@@P.B`BDPH.V@T3(KD"`-X. +M(F%NZ`(`I0<`$0,"P040+&,`0&1E%E +MF-%#A)B!P`2>`<``$D!`)()`"<`4"H@97AA20!`8$(&YDT`(Q9G5L+P(&10`0+T,* +M`84!$6&>"E%A8W0@'2(`")P==8-(")C-`81(B0#`#@,*6]L30`"5@$&ZP,!*0$` +M%@D`C@$/;0$!`+`,$'4]$P':`31E"B>P`"-E)ZT``#H/,"`J(),``$X`\``N +M86TL(&%C;&]C86PN;30)#0/M`#`N86/_```"`!`MH@(`GP`$J```V0X(H@02 +M+!H.`-<+`%D+$'G*!0'V`2-EH($',+!0$^`0!U```7`@#Y!`%Q``%Q"@B7```\ +M"3!Y+C/T%#!A:6SO!#)E(")K`P6K``$D`!0B"PM9(&-L87-$``$?"49N86QS +MG0`2!Q(M@@0U=H+`#L'`2,)#V0:________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________________________________]I4'(*("`@/A$``!(@`0!R>F-A +M="P@8@<`$G@'`/0386YD('-U8V@*("`@*B!E>&%M<&QE'2( +M`#%P=70I`/D#(F-M86ME(B!B=6EL9"!T;V]L30`"5@$&-0$!*0$Q(&EN3`$/ +M;0$!,&%R91`"$F3:`35E"B>\`!,GK0`2.M0``),``$X`]0$N86TL(&%C;&]C +M86PN;30LX0!`92YA8RL```(`$BU4`"1T;Z@``"`!,&1IM`_`$,R!G:79E2XS!`,!JP(2(FL#!:L``20`Z2(@=71I;&ET>2!C;&%S1`"6:6YT97)N86QS +MG0`P`?$#+@H*66]U('-H;W5L9"!A;'-O(@(!3``Q8V]P=@8R8V]M6P%# +M:6X@(KT",BYH(JD`@&AE"G-O=7)C+P`19'4!`!0`!.D&!30'`"P%-&UO<$",&5C=)D#$635 +M``,<`@7"!A!F+``!MP91*B!'3E5U`0*Z`28@*+D!`!H`06QO;F=5`F)N86UE +M'1E +M;J+``-J`0`9`]$J(%!/4TE8('5S=&%R6P`" +M$``P<&%X20,B97)9!P-X`@FEP,A8`!'P!32],6E<=`*)L>FUA+"!L +M>FEP$P,O>'HC```9-!0`"0@!```*56-R96%TSP`!=00/!@$"`JH#`[\#`KP" +M#Q\#&#`B&-E<$`%`+D%!&D"`A4,<7)E<75IP`#GP$`>P`!APD!HP`"2@P#"@,`.`@`L@`Q=&AA+PD#*P`A +M(&(W"0!J"#%A8FP`!@","@$,``$L"P($`0!H``([`$)E86-H/0$A=F5S`Q-Y +M0P!0:6YD97"J`"5N="(!`!@)``\/$&-"!1)O;`T&-0I4(%=I:VE2##!I;F?) +M`#!H;W=1#P&S`Q=DE@H"*@$A3VX_"`#W#`)@!@,#`03-``%P`$!L=V%Y1@$` +MW0$J962*"`)'`'!))W9E(&%T+0T`C`<`P0^0:6YI;6EZ92!S#@T28U((07!O +M;&R4#5$N("!)9O4(4&1O;B=TJ`"097AP;&EC:71LV0EB=F]K92!A^@\18W\* +M,69E830+$"C2$`!U#`@<`A!A00`!)Q`"+0`(S0`4;_D(<"DL(&ET('=P`'$@ +M9V5T('!UG`T0:7H+1R`@26YN`#``%1`0.;`")E;LD!!RT``#X`"W$` +M*&1E$0`#J@`1+/```H```(T.`)8!`!8!`$``(&%G`PX"4`.18V]R0`P&@`A!MV`$32X'<70@82!T:6U7 +M`W%O8!(71O(@`%2@!2="!O;F-\ +M$B)/;AP."\,``N0",G!R;SH!`84!46-T;'DMS`"2960@;W5T<'5T[P(`8`3Q +M`V]B:F5C="US='EL92!A<'!R;\@#`$,2`OH`X'1O(&AA=F4@;75L=&EP)0`` +M(040=A(#0')E86VY"%4@;W!E;IX`$R`5$`!J$``*`0`]!8-N(&ETP"`,D*`2L`,VEN +M("#U%F:7)S=)("`*8!$6%P$A%O61$`]@`6 +M+G0``]D#`J60!`,P` +M`*,!!H`%,7=A;G\%$G0=#P-%`0!@```:!!!TC@0#`',*%E7,@<')O9'5C97,@8V]R6QE(&%P<')O86-H(&%L;&]W^@#@=&\@:&%V92!M=6QT:7`E +M``.I`'%S=')E86USSP`U<&5NG@#S#2`@8G-D=&%R('5S97,@=&AI2!D8737`%9UP",B!O9BL`,VEN(""!I;G1E7,N"E)%041-12X``$0$!&T!T6)U;F1L92X*"E%U97/Z`J`_("!)!D!G`<``$D!0'-U8V@G`%`J(&5X84D`0',Z(%,R`U1S +M;6%L;!4`!#X!`%(#(6%T(`8@;6'F!"!N9-`",69U;"\"!D4`42]M:6YIA0$1 +M8>,!46%C="!S8`"P(&1E;6]N0&";8"(FEN^`0B:6_A!@2]`O`"3D574R`M(&AI9VAL:6=H +M='-M``,D!`"3``!.`/4! +M+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_```"`!`MH@(`GP`$J``,H@2R+"!O +M;FQY(&YE961\`#%M86GV`2-E7-T96TZ +MIPH"N`1U+C$@97AP;(,"`R\#`$(!`B$`!)H#`S,``(@$#S0`"P`B``PU`"]A +M=#0`#"AA=#,`!@$&(2XSM@L0<]\&@&]V97)V:65W\P(`H``%G@L`<04P=VAO +MD0(4*J0*A5]R96%D+C,L$``!^`@-$0!17V1I``'<`%0P#'`(%>`D09BP``;<&42H@1TY5=0$"-0(F("@$"P`:`$%L;VYG +M50(`K0LB+``-J`0`9`]$J(%!/4TE8('5S=&%R6P`"$``/ +MB@P#!R$`P&]C=&5T+6]R:65N=!<$,7!I;QX`IE-64C0@05-#24D4``)3``\R +M``5A0FEN87)Y+@#`("AB:6FEP/@$Q:6]N +M&`%=8GII<#(6``1\`4TO3%I7'0"B;'IM82P@;'IID2,',@*'T'`30$`(0!`S,$`/0#8"P@971C*>\+`OH#`*D"`&@1 +M`HT``88!`MH`#Y8#!0'(`V$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0%!`?. +M``]9`P`*%@,S5VAE`P(`-0<#U`(2<^8%87)E'!L:6-I=&S9"6)V;VME(&'Z#Q%C?PH#SA$@ +M("C2$`!U#`@<`A!AL@$!)Q`"+0`(S0`4;W,$<"DL(&ET('=P`%`@9V5T(-(2 +M`5T*`*0$-R!);FX`!287`9X``5$!`YL`(F5NR0$'+0``?``+<0`H9&41``.J +M`!$L6!$"@```C0X`E@$`%@$`0``P86=A\P\!7PJ18V]R2!O9B!T:&4@9F]L;&]W:6YG(&)E9F]R92!E=F%L +M=6%T$@``(`#Q#6%R8VAI=F4Z"B`@*B!U=65N8V]D960@9FEL97,4``$*`/$" +M('=I=&@@4E!-('=R87!P97(;`/$!9WII<"!C;VUP'HC```9-!0`"0@!E6-A;B!C +M'1E;DT!L7,@*&9O$E33SDV-C`3`%HW+5II<#D`-EA!4A$`0PI7:&4#`@#8`@1U +M`1$L`@-AT!X'-Y0`&EP#R`FES(&1EP`!S@`4=E@#$G.C`%0@;VYL>0H#0&UE;G2R``$>`P"F!`)G`S`@ +M8F5``(!R96%D86)L9:(`07=R:70,`!!A#`$"!`$!1`0!.P!"96%C:#T!(79E +ME@(3>4,`4&EN9&5PJ@`B;G1_`!!R.P0`!``P=&EC0@4D;VZ!`02N`/``5VEK +M:2!E>'!L86EN:6YGB0`P:&]W^``"]0``E@4#+``"*@$A3VZJ`!PL`P$#V0(" +M<`!`;'=A>48!`-T!\@%E9"!A=71O;6%T:6-A;&QY1P"P22=V92!A='1E;7#$ +M`^!T;R!M:6YI;6EZ92!S="L`L"!L:6YK('!O;&QUN`'A+B`@268@>6]U(&1O +M;B?L`0"V`/$":6-I=&QY(&EN=F]K92!A('#K`"!U;#<$H&5A='5R92`HD`!RT`!^\%`(`!`ID!<"DL(&ET('=P`.`@9V5T('!U;&QE9"!I +M;J0$-R!);FX`-RP@:9X``5$!`YL`(F5NR0$'+0``?``+<0`H9&41``/&`A$L +M\``"@``B;F6.`@`6`0!``&)A9V%I;G-'`J!C;W)R97-P;VYD)P0(20`-6@`" +M>P,Q:65SPP`!;P,!;P=1P,1<#4`T6%T979E`%`@(&)S9",'(75SO`$`/06#;B!I=',@(D#E`!(BO01&"2`L(E`(<"P@8V%P86)!``'V +M`@)F!A%E50(!\0!A92!!4$ESMP0(]@4!EP&Q(&EN9&EV:61U86QH!1%IWP<` +M>P`28D(``"P$`-$``#8!(71OFPDP9&%TUP!6=7)C93HN`0+("0#"`!)A[`(` +MR0H!*P`S:6X@)P$`3P@S861DC@(18?P(!*H!`'D&(6]U]P119FER0#`',*T"!S87ES+@I214%$346[!@?H!N$@8G5N9&QE+@H*475E<_H" +MH#\@($ES8N9V]O9VQE+F-O +M;2]P+VH`$2\Z`"!S+VD``),``6<`47-U8FUI9P!P96YH86YC9;L``*8`!C@` +M@RP@<&QE87-E+```.P``!`,`2P7!1`GH@1`9W)A;18"F-%#A)B +M!P`2>`<``$D!`)()`"<`4"H@97AA20!`8$(&YDT`(Q9G5L+P(&10`0+T,*`84!$6&>"E%A8W0@'2(`")P==8- +M(")C-`81(B0#`#@,*6]L30`"5@$&ZP,!*0$`%@D`C@$/;0$!`+`,('5SW0H` +MV@$T90HGL``C92>M``-G`0"3``!.`/``+F%M+"!A8VQO8V%L+FTT"0T#[0`P +M+F%C%P$``@`0+:("`)\`!*@``-D."*($$BP:#@#7"P)\`#%M86GV`2-EPH"MP(`A1(A86R)!T!S97%UZ@@0!Q(M@@0U``&I`5"`"X!!,B!0XR+F@BJ0`R:&4*7PP0(+`) +M`/H``!0`!.D&`W((`G\"$&T:%P/[`$(N("!0B@FR;&5T('5S"FMN;W<0`0&X +M#&!E2X`H"`H8FEG+65N9&GS!(-R(&QI='1L91$``L<`!%\6D4-$+5)/ +M32!I;;<"$"@X#C`@;W#+`\!A;"!2;V-K%V,/"Q<`T$UI8W)O2!A0A$``/4R2!T:&4*)V-O;F9I9W5R92<@`""(&EN'!L86EN@`/`#;&EB2!A2XS30`"=`%U(G-T2!C;&%S1`"6:6YT97)N +M86QSG0!@2QN``5H`W!U=&]M871I_P(0>68!,&5C=)D#$635``,<`E!O +M;&QO=Y,!$&8L`!!S4`51*B!'3E5U`0(U`B8@*+D!`!H`06QO;F=5`F)N86UE +M`*%3 +M5E(T($%30TE)=`(!%``"4P`/,@`%84)I;F%R>2X`H"`H8FEG+65N9&GS!(-R +M(&QI='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I;;<"@"AW:71H(&]P^@7` +M86P@4F]C:W)I9&=E10!B2F]L:65T*0$![P$"20`T6DE05@,$0`"0=6YC;VUP +M[`@0]`5HW+5II<"8`V$UI8W)O`,(KP)@:&%N9&QENP(0>;<#`+8$ +M!K@",&)E9DH#<&5V86QU873*`@`@``.9`P+/`A!U]@40;W$"`+8"`D,"`0H` +M$2"#`:)24$T@=W)A<'!E3@)%9WII<#X!,6EO;A@!76)Z:7`R%@`$?`%-+TQ: +M5QT`HFQZ;6$L(&QZ:7`3`R]X>B,``!DT%``)"`&58V%N(&-R96%TSP`!=00/ +M!@$"`J\!`[\#`KP"#Q\#&#`B&-E<$`%`+D%!&D"L"!T:&%T(')E<75IE@4G87C*`B`@ +M*'T'`30$`(0!`S,$`/0#<2P@971C*2YO`0#Z`P"I`@8B!`$7``+:``^6`P4! +MR`-A(FYE=V,BFP,!,P`G?P(-F5A;;4%`A$+@"X@(%1H97)E+``C;F_B!P""`@/?"`"3!/("(&EN+7!L +M86-E(&UO9&EF:6.M"/,";W(@U`P#P!`![``.?`0![``&'"0&C``)*#`,*`P`X +M"`"R``$>`P"F!`(,`B$@8C<)<7)E861A8FP`!@","@$,``$L"P($`0!H``([ +M`$)E86-H/0$A=F5S`Q-Y0P!0:6YD97"J`"5N="(!`!@)4&%R=&EC0@4D;VZ! +M`02N`$17:6MI4@PP:6YGR0`P:&]WFPP"I@<'E@H"*@$A3VX_"`#W#`)X!@$" +M"B-N9/@``8@)8V%L=V%YD`!RT`!"T' +M`,T`%&_Y"'`I+"!I="!W<`!Q(&=E="!P=9P-(&ENI`0W($EN;@`W+"!IG@`( +MFP`B96[)`02UV```S#`#W"!%IAP8`A`!P96YV:7)O;M<",7,@ +M=Y`#`:`"$&W8`1-R6@,%,`(`6P`"?P`1>7L#$7`U`-%A=&5V97(@8FQO8VMS +M\```[@@``S0*%82!S;V-K970^`TEW:7-HN@0!)@\# +M60\`4X.475S92`B(0$`6@@@+")0"+$L(&-A<&%B +M:6QI=/8"!`,!!?$``O,/`;<$"/8%`9P"`,D*`2L` +M,VEN("#U%F:7)S=)("`*8!$6%P$A%O61$` +M]@`6+G0``]D#`J60! +M`,P``*,!!H`%,7=A;G\%$G0=#P$V`@%;`P$:!!!TC@0#`',* +MT2!S87ES+@I214%$3442!@9)$>$@8G5N9&QE+@H*475E<_H"H#\@($ESF-%#A)B!P`2>`<``$D!`)()`"<`02H@97@;$T!S.B!3,@-4X/\`4@*B!.15=3("T@:&EG:&QI9VAT<]P`,')E8]D4`C$%`Z`" +MDD-/4%E)3D<@+0P%`$(4`,H'(F1OGP``AP4`S@"T*B!)3E-404Q,("V2&`&/ +M!`$-``#Y%@"_``(I``-`!1(M1!D`E0`"&``%=QDE("T,``)$``*W&54L('-E +M96<``"@%`JT7`F,(@2H@0TUA:V5,U`0Q='ATB``A<'5G$#`@(F,T!A0BO!DY +M;V]L30`"5@$&-0$`E```L`H!C@$/;0$!`*(&#V0:____________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________________________________________]G4'1O(&%L+1$` +M`/`@;&]W(&EN9&EV:61U86P@96YT2!A;F0@861D(&ET3`#P!2!T87(@87)C +M:&EV92!W:71H;W5T00!19FER2!F:6QE+G0` +M0F%L8<`\01S;V-K970N("!)9B!Y;W4@=V%NB``2=%T`$B\]``,?`0`S`%!D +M:7-K+$X`\!!R92!A0#P*FES(&5S<&5C:6%L;'D@96%S>2X*"B`J($YO=&4Z(")P87@@:6YT97)C +M:&%N9V4@9F]R;6%T(B!I<^```#,``.(`<7AT96YD960X`0(B`!`L8P!`9&5S +M<-\`0'=H8726`/`#(&YA;64@F-A="P@8@<`$G@'``!)`4!S=6-H)P!0*B!E>&%)`$!S.B!3,@-4`0-)`#!C;VY#`O`".B`@5F%R +M:6]UP``7P%Q875T:&]R<\`%`1\&`?("``$%4"X*"E1HG0$P<"UL#`0#=@4` +M"08!00`0:20%";8"(FENU@0Q:6]NZP4$O0+P`DY%5U,@+2!H:6=H;&EG:'1S +M7`8PM``,D!`"3``!. +M`/4!+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_```"`!`MH@(`GP`$J``,H@2R +M+"!O;FQY(&YE961\`#%M86GV`2-E7-T +M96TZ<`<"N`1U+C$@97AP;(,"`R\#`$(!`B$`!)H#`S,``(@$#S0`"P`B``PU +M`"]A=#0`#"AA=#,`!@$&@"XS(&=I=F5SWP:`;W9EP$2+8($-7,N-:H(`)X%$67[`P#R`(!M871S +M('-U<'\(!&,"!98!`$P```H"D"XU+"!M=')E90D``&\`7G1A`D09BP``;<&42H@1TY5 +M=0$"-0(F("@$"P`:`$%L;VYG50(`K0LB+``-J`0`9`]$J +M(%!/4TE8('5S=&%R6P`"$``/B@P#!R$`P&]C=&5T+6]R:65N=!<$('!IZ`S& +M*B!35E(T($%30TE)%``"4P`/,@`%84)I;F%R>2X`P"`H8FEG+65N9&EA;J(! +M8VQI='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I;;<"$"@X#C`@;W#+`\!A +M;"!2;V-K[`@0]`5HW+5II<"8`V$UI8W)OFEP/@$Q:6]N&`%=8GII<#(6``1\`4TO3%I7'0"B;'IM +M82P@;'II\+`OH#`*D"`&@1`HT``88!`MH`#Y8#!0'(`V$B;F5W +M8R*;`P$S`"=S:+```1(`#T8#8P0%!`?.``]9`P`*%@,S5VAE`P(`&@T#U`(2 +M<^8%87)E4,`4&EN9&5PJ@`E;G0B`0!$#0`/#Q!C0@42;VP-!C4*5"!7:6MI4@P# +M#!,P:&]W^``"]0``K0$#V@`"*@$A3VX_"`#W#`)@!@#S#@!0!@/-``%P`%-L +M=V%Y'!L:6-I#16":6YV;VME(&'Z#Q%C?PH# +MSA$@("C2$"4@8?L*`*$!("!AL@$!)Q`"+0`(S0`4;W,$<"DL(&ET('=P`%`@ +M9V5T(-(2`5T*`*0$-R!);FX`,BP@:8(5`9X``5$!`YL`(F5NR0$'+0``?``+ +M<0`H9&41``/&`A$LY0D"@```C0X`E@$`%@$`0``P86=A\P\!7PJ18V]R"(&5N=FER;VX/"Q%WD`,!H`(0;=@!$W): +M`P4P`@!;``)_`!%Y>P,1<#4`8F%T979E2!O9B<`H69O;&QO +M=VEN9SJ&`(%U=65N8V]D90T`\0%G>FEP(&-O;7!R97-S:6]N%0!=8GII<#(6 +M``0F`$TO3%I7'0"Q;'IM82P@;'II<"P4`2EX>B,`P0I.;W1E7-T96TN("!4:&5R92P`@&YO(&1IF4@2!I;G9O:V4@82!PZP"`=6QA2!FP`28D(``"P$`-$``#8!(71O>`0#\`)N86UE('-A +M>7,N"E)%041-15``!^@&X2!B=6YD;&4N"@I1=65S^@*@/R`@27-S=65S/U(` +MURH@:'1T<#HO+W=W=RX@!S!O3``!(`1!HN`*#9F]R(&]N9V]8!Q@@9`!P +M9&5V96QO<#P%<2P@:6YC;'6]!4!D;V-U%``!K`@!3@D`<0``.@`A;FM=`0!= +M``9S`%`@;6%I;`<"0FQIF-A="P@8@<`$G@' +M``!)`0"2"0`G`%`J(&5X84D`0',Z(%,R`U1S;6%L;!4`!#X!`%(#(6%T'`@@ +M;6'F!"!N9-`",69U;"\"!D4`$"]#"@&%`1%AG@I186-T('-@`)(@9&5M;VYS +M=')*#0`I!B=O9EX!`TD`,&-O;D,"\`(Z("!687)I;W5S(&ET96US(#,!`'T# +M0&UE(&(W`3)I0&";8"(FENU@0`Q@P`ZP4$ +MO0+P`DY%5U,@+2!H:6=H;&EG:'1S7`8PP +M`"-E)ZT``R0$`),``$X`\``N86TL(&%C;&]C86PN;30)#0/M`#`N86,7`0`" +M`!`MH@(`GP`$J```V0X(H@02+!H.`-<+`GP`,6UA:?8!(V5RK@$%<``D:6YD +M`($N:"YI;@H)+?0'(&QA5@\$NP`%A0`#M0!@"@I'=6ED\P`H($14!@32`0)U +M``&W`0)3#Q`Z&@D"N`0A+C'!#`!A#`$W`0,O`P`+``(A``2:`P,S``"(!`\T +M``L`(@`,-0`O870T``PH870S``8!!B$N,[8+$'-E"H!O=F5R=FEE=_,"`*`` +M!<`+`'$%4'=H;VQEI``#1`6$7W)E860N,RRT"A%?^`@-$0!17V1IH($',+!0$^`0!U```7`@#Y +M!`%Q``%Q"@B7```\"3-Y+C--``#O!#)E(")K`P6K``$D`!0B"PM9(&-L87-$ +M``$?"49N86QSG0`2!Q(M@@0U]!9!I +M;@IA(&YU;6+R#!=FD0<$.P''"@I9;W4@2X`L2`H8FEG+65N9&EA +MU!%C;&ET=&QE$0`"^@`$7Q:10T0M4D]-(&EMMP(0*#@.,"!O<,L#P&%L(%)O +M8VMR:61G9>\!`DD`-%I)4'4$!$``('5N,0L`)18`UA!@ +MC2H`0#E%PD( +M`0``"@*<$`5+`0!U!`\&`0("@P$#OP,"O`(/'P,8,")R9:`-`!`6$2)'`P)/ +M`,(L('=H:6-H('=I;&SK&`!P"``9!`-?`4!S(&5X+10``@(`N04$B1$""Q<# +M6A`'!L:6)R87)Y3`#08W!I;RXU+"!M=')E90D``&\`5'1AP#S +M"2P@:6YC;'5D:6YG(&AA +M``"/`/0:("=D;V,G(&1I2!I;@IA(&YU;6)E6]U(#\!8"X*"D-UFEP,A8`!'P!32],6E<=`*)L>FUA+"!L>FEP +M$P,O>'HC```9-!0`"0@!E6-A;B!C,H"4B`H9F]R-`0`A`$#,P0` +M]`-Q+"!E=&,I+F\!`/H#`*D"!B($`1<``MH`#Y8#!0'(`V$B;F5W8R*;`P$S +M`"=S:+```1(`#T8#8P0%!`);`0&)``]9`P`*%@,S5VAE`P(`V`(#U`(2<^8% +M87)E'!L86EN:6YGR0`P:&]W^``"I@<`K0$#+``" +M*@$A3VX4"1PL`P$#^``!B`E086QW87E&`0#=`2IE9(H(`D<`L$DG=F4@871T +M96UPC`?@=&\@;6EN:6UI>F4@D`!RT`!"T'`,\*%&_Y"'`I+"!I="!W<`""(&=E="!P=6S["@"D!#<@ +M26YN`#``B;`")E;LD!!RT``'P`"W$`*&1E$0`#Q@(1+/```H``(FYE +MC@(`%@$`0`!B86=A:6YS1P*18V]R0`P&@`A!MV`$38!(71O(@`%H0!A="!O;F-EA0`A3VZ0`QMEPP`"Y`(R<')O.@$! +MA0%18W1L>2W,``"."5)U='!U=.\"`&`$\0-O8FIE8W0M60!`,P``*,!!H`%,7=A;G\%$G0=#P$V`@%;`P!C +M#``S`$%D:7-K+`,`L1`0#B)A;N@"`*4'`!$# +M`EH'$"QC`$!D97-PH@``;`0!Y`,`7,N"E)%041-11(&!DD1X2!B +M=6YD;&4N"@I1=65S^@*@/R`@27-S=65S/U(`UBH@:'1T<#HO+W=W=RXX`$`N +M;W)GDP``2`$0:+@"$&:Q#S-N9V]8!Q<@3`>`(&1E=F5L;W`\!0@9$02Z$0&L +M"`$W#`!Q```Z`"%N:UT!`%T`!G,`4"!M86EL!P(P;&ESOQ`!G0`05)D!`.41 +M`.%E8$(&YDT`(Q9G5L+P(&10`0+T,*`84!$6&>"C1A8W1[$W!D96UO;G-T +M.14@;F<^``"`!094`@-)`#!C;VY#`F$Z("!687+N$V!I=&5M$0(8`&!C;VYF:6>R%A4M#``"1`"UM`Q$SM@L`$!20(&]V97)V:65W\P(`JP`% +MP`L`<04P=VAOD0(4*J0*A5]R96%D+C,L$``!^`@-$0!17V1I2#R`I!I;VYS+@H*5&B=`?("<"UL979E +M;"!D:7)E8W1O'2(`#!P=71>`H$@ +M(F-M86ME(B0#:60@=&]O;$T``E8!!NL#`2D!,2!I;DP!#VT!`3!A2!N965D?``Q;6%I]@$C97)<`05P +M`"1I;F0`\@,N:"YI;@H)+2!T96UP;&%T97-G`!%B-`(!9@$39;4`8`H*1W5I +M9/,`4"!$;V-UF04"@0$`Q0$R86QL=0`!MP&R'!L@P(#+P,`0@$"(0`$F@,#,P``B`0/-``+`"(`##4`+V%T-``,*&%T,P`& +M`0:`+C,@9VEV97/?!H!O=F5R=FEE=_,"`*``!+L%$&%Q!3!W:&^1`B,J(,0& +MA5]R96%D+C,L$```T04=91$`45]D:7-K%@`@;F30`0@^``,<``"9`!!V7P$" +MMP)P960@8V%L;!(&$'/4!D%N8V5SK0(`DP``=0`!1P`#0@9H92!!4$ESEP!S +M96YTP$2+8($4W,N-2!D5@("KP``&0,`\@"`;6%T#0#`ED' +M`W@"!R$`P&]C=&5T+6]R:65N=!<$('!I?@G&*B!35E(T($%30TE)%``"4P`/ +M,@`%84)I;F%R>2X`P"`H8FEG+65N9&EA;J(!8VQI='1L91$``OH`\0))4T\Y +M-C8P($-$+5)/32!I;;<"$2AX""!O<,L#P&%L(%)O8VMR:61G944`8DIO;&EE +M="D!`>\!`DD`-%I)4%8#!$``('5N,0LPFEP,A8`!'P!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9-!0` +M"0@!```*56-R96%TSP`!=00/!@$"`JH#`[\#`KP"#Q\#&#`B&-E<$`%`+D%!&D"42!T +M:&%T0PXQ:7)E40`!\P,!R@(@("@6!0$T!`"$`0,S!`#T`V`L(&5T8RGO"P+Z +M`P"I`@8B!`&&`0+:``^6`P4!R`-A(FYE=V,BFP,!,P`GD#`*4#(71EVP@P +M.@H*'Q$R:&ESD0]P:&5A=FEL>?P(-F5A;;4%`A$+<"X@(%1H97(T$3,@;F_B +M!P""`@/?"`"3!$$@:6XMMP^"(&UO9&EF:6-D"_``;W(@0`&EP``L!!397-I9VXE#!)EB`4`0`0!7@$X;F5WM0,`\`0`>P`#GP$` +M>P`!APD!HP`"2@P`31$B:7*"$1!I>0<280D!`@P"(2!B-PD`:@@Q86)L``8` +M_0H!#``!+`L"U!``:``".P!"96%C:#T!(79E4,`4&EN9&5PJ@`E;G0B +M`0`8"0`/#Q!C0@42;VP-!C4*5"!7:6MI4@PP:6YGR0`P:&]W40\!LP,09$X( +M`]H``BH!(4]N/P@`]PP"8`8`TQ$`4`8#S0`!<`!3;'=A>7-S""IE9(H(`D<` +M<$DG=F4@870M#0",!S!T;R`A$+)M:7IE('-T871I8U((07!O;&PV$E$N("!) +M9O4(061O;B<<$Y!E>'!L:6-I=&S9"4!V;VMEO!(!ZP`!?PH#SA$@("C2$"4@ +M8?L*`*$!("!AZ0`!)Q`"+0`(S0`4;_D(<"DL(&ET('=P`$$@9V5T&1,!70H` +MI`0W($EN;@`W+"!IG@`!40$#FP`B96[)`07L#$7`U +M`-%A=&5V97(@8FQO8VMS\```[@2X'<70@82!T:6U7`W%O8!(71O(@`%2@``XQ,A8V6%`"%/;I`#&V7#``+D`C)P`!,@ +M%1``:A``"@$`/06#;B!I=',@(D`\`!(BO0012!F4X.``P1$2(A`0!: +M""`L(E`(H"P@8V%P86)I;&D2%`8#`07Q``+S#P$_#@CV!0&7`8`@:6YD:79I +M9&P.`]L(`(4``#H2`D(``*P+`-$``#8!(71OK`TP9&%TUP``!0X6.BX!`L@) +M`#T`$F'L`@#)"@$K`#-I;B`G`0!%!3-A9&2.`AAA]PP!J0H#'@]19FER0#`',*'!L86EN:6YG"B`@(&AO=R!T;R!E>'1E;F0L +M`/(6+@H*("H@3VX@0*A2!A8V-E<#4`T6%T +M979E717`G`@82!T:6UEI0!Q;W(@;6UA<-H`065N +M=&D/`P+\`@!I`!!G!0,@:71/``FA`&%T(&]N8V6%`(M/;B!W`+$@(&)S9'1A2!B=69F97(@ +M;W+!``!E``1R`85A('-O8VME=#X#4'=I2UT;RUU"!I;G1E +M7,N"E)%041-12X`!^@&X2!B=6YD;&4N"@I1=65S^@*@ +M/R`@27-S=65S/U(`UBH@:'1T<#HO+W=W=RY,!T`N;W)GDP``2`$0:+@"@V9O +M0(1.FH`$B>7!9`G('!R;V=R86T6`G-A +M(&9U;&PME@AP9"`G=&%R)WX``P(`4W)E<&QA0@%`8G5I;($&`(H``V,``"H` +M9BH@8W!I;V,```X`"V0`(&1I:P4R96YT,`-#9F%C96H#`P(`,&5S`<``$D!`)()`"<`4"H@97AA20!`8$(&YDT`(Q9G5L+P(&10`0+T,*`84!$6$& +M"5%A8W0@`0-)`#!C;VY#`O`".B`@ +M5F%R:6]UP``7P%Q875T:&]R<\`%`1\&`?("`DT'$`J(!E!T;W`M;`P$`W8%`#`' +M`4$`$&GD!@FV`B)I;M8$`'$+`.L%!+T"\`).15=3("T@:&EG:&QI9VAT=&%R+C54`0CQ!$%A8F]U4P41]!9!I;@IA(&YU;6+R#!=F +MD0<$.P''"@I9;W4@`D09@82`;<&42H@ +M1TY5=0$"-0(F("@$"P`:`"-L;[P%`*T+(G,L$```!0L3(!$``&,`4G-P87)S +M?`(A +M`*%35E(T($%30TE)=`(!%``/,@`+$$)M$1%Y+@"Q("AB:6`@@;W#+`\!A;"!2 +M;V-K[`@0]`5HW+5II<"8`V$UI8W)OFEP/@$@:6]/$WTJ(&)Z:7`R%@`$?`%-+TQ:5QT`HFQZ;6$L +M(&QZ:7`3`R]X>B,``!DT%``)"`$```H"G!`%.@$`=00/!@$"`J\!`[\#`KP" +M#Q\#&#`B\+`OH#`*D"`&@1`HT``9L!`MH`#\@#"F$B;F5W8R*;`P$S`"=S +M:+```1(`#T8#8P0%!`?.``]9`P`*%@,S5VAE`P(`OP@#U`(2<^8%87)E`3AN97>U`P#P!`#]`@.?`0![``&'"0$K +M%0)*#`,*`P`X"`!O$!1T[A("#`(A(&(W"0","@&/&`.X%`$,`!!A#`$"U!`` +M:``".P`199P6`#T!(79E4,`4&EN9&5PJ@`E;G0B`0!$#0]D&O______ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M8U!A;F0@'1E;F1E +M9&0`!#-!0TPS`&%/;&0@5C2!O9K@"X&)E9F]R92!E=F%L=6%TI`(`V`(# +M+P("SP)@=75E;F-O<0(`M@("0P(!"@`1((,!HE)032!WFEP +M/@$Q:6]N!0%=8GII<#(6``1D`4TO3%I7'0"B;'IM82P@;'II0`&EP"0:7,@9&5S +M:6=NH@9";R!B98@%`$`$`3`$.&YE=[4#`*,$`'L``4,`4&EN9&5PJ@`B;G1_`!!R.P0` +M!``P=&EC0@4D;VZ!`02N`/``5VEK:2!E>'!L86EN:6YGB0`P:&]W^``!LP,0 +M9)8%`RP``BH!(4]NJ@`<+`,!``0$,FUA='``0&QW87E&`0#=`6!E9"!A=71> +M"&)I8V%L;'E'`+!))W9E(&%T=&5M<(P'X'1O(&UI;FEM:7IE('-T*P`"4@A0 +M<&]L;'6X`>$N("!)9B!Y;W4@9&]N)^P!`+8`\0)I8VET;'D@:6YV;VME(&$@ +M<.L`('5LO0B@96%T=7)E("AS=2\!&7,<`A!AZ0`'+0`$10<#(@("F0%P*2P@ +M:70@=W``X"!G970@<'5L;&5D(&ENI`0W($EN;@`W+"!IG@`!40$#FP`B96[) +M`07L#$7`U`-%A=&5V97(@8FQO8VMS\``` +M[@2X'<70@82!T:6U7`W%O8!(71O +M(@`%H0!A="!O;F-EA0`A3VZ0`QMEPP`"Y`(R<')O.@$!A0%18W1L>2W,``". +M"5)U='!U=.\"`&`$\0-O8FIE8W0M2!B=69F97(@)`@`90`$<@&%82!S;V-K970^`TEW:7-HN@3` +MP"`,D*`2L`,VEN(">D``,P``*,!!H`%,7=A;H@`$'0V +M!`5%`0!@```:!!!TC@7,N"E)%041-1;L&!^@& +MX2!B=6YD;&4N"@I1=65S^@*@/R`@27-S=65S/U(`URH@:'1T<#HO+W=W=RX@ +M!S!O3``!(`1!HN`*#9F]R(&]N9V]8!Q@@9`!P9&5V96QO<#P%)BP@8`]` +M9&]C=10``:P(`3<,`'$``#H`(6YK70$`70`&8N9V]O9VQE+F-O;2]P+VH`$2\Z`"!S+VD``),``6<`47-U8FUI9P!P96YH +M86YC9;L``#8"!C@`@RP@<&QE87-E+```.P``!`,`2PB!$!G0&";8"(FENU@0`I`H`ZP4![@_P!2`J($Y%5U,@+2!H:6=H;&EG:'1S7`8P +MM```Z#S`@*B"3``!.`/``+F%M+"!A +M8VQO8V%L+FTT"0T#[0`P+F%C_P```@`0+:("`)\`!*@``-D."*($$BP:#@#7 +M"P!9"Q!YR@4!]@$C97*N`05P`"1I;F0`@2YH+FEN"@DM]`<`YA,22XS +M]!0P86EL[P0R92`B:P,%JP`!)``4(@L+62!C;&%S1``!'PE&;F%L``'?`5&%M<&QE'2(`#%P=70I +M`/D#(F-M86ME(B!B=6EL9"!T;V]L30`"5@$&-0$!*0$Q(&EN3`$/;0$!,&%R +M91`"$F3:`35E"B>\`!,GK0`2.M0``),``$X`]0$N86TL(&%C;&]C86PN;30L +MX0!`92YA8RL```(`$BU4`"1T;Z@``"`!,&1IM`_`$,R!G:79E2XS!`,! +MJP(2(FL#!:L``20`Z2(@=71I;&ET>2!C;&%S1`"6:6YT97)N86QSG0`PP$2+8($4W,N-2!D5@(#I@0@:6QV`]1R;6%T-50!"/$$4&%B;W5T&@$@P"`+"!I;F-L=62*`8%H87)D+71O+3`&`J@!$G-'``!! +M`&%M;V1E$D#(F5R60<#>`('(0"P;V-T970M;W)I96X!`P!@`@$>`*%35E(T($%30TE) +M=`(!%``"4P`/,@`%,$)I;LH$`$(`H"`H8FEG+65N9&GS!(-R(&QI='1L91$` +M`OH`\0))4T\Y-C8P($-$+5)/32!I;;<"$2AX""!O<,L#P&%L(%)O8VMR:61G +M944`8DIO;&EE="D!`>\!`DD`-%I)4%8#!$``('5N3@DPFEP/@$Q:6]N&`%=8GII<#(6``1\`4TO3%I7'0"B;'IM82P@;'II?P(-F5A;;4%`A$+@"X@(%1H97)E +M+``C;F_B!P""`@/?"`"3!/("(&EN+7!L86-E(&UO9&EF:6-D"_``;W(@0`&@`23:7,@9&5S:6=N)0P298@%`$`$`;,%.&YE=[4# +M`/`$`'L``Y\!`'L``8<)`:,``DH,`PH#`#@(`+(`,71H82\)`RL`(2!B-PD` +M:@@Q86)L``8`C`H!#``!+`L"!`$`:``".P!"96%C:#T!(79E4,`4&EN +M9&5PJ@`E;G0B`0`8"0`/#Q!C0@42;VP-!C4*5"!7:6MI4@PP:6YGR0`P:&]W +M40\!LP,79)8*`BH!(4]N/P@`]PP"8`8#`P$$S0`!<`!`;'=A>48!`-T!*F5D +MB@@"1P!P22=V92!A="T-`(P'`,$/D&EN:6UI>F4@P,1<#4`T6%T979EP"`,D*`2L`,VEN("#U%F:7)S=)("`*8!$6%P$A%O61$`]@`6+G0``]D# +M`J60!`,P``*,!!H`% +M,7=A;G\%$G0=#P-%`0!@```:!!!TC@0#`',*%EF-%#A)B!P`2>`<``$D!`)()`"<`#V0: +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______]?4'(@8FQO)!$``/%/8VMS('EO=2!H86YD(&ET+@H@("!9;W5R(')E +M860@8V%L;&)A8VL@:7,@9G)E92!T;R!P87-S('1H92!L:6)R87)Y(&$@8GET +M92!A="!A('1I;64*("`@;W(@;6UA<"@`\`!E;G1I7,@<')O +M9'5C97,@8V]R`,`@(&)S9'1A&%)`$!S.B!3,@-4`0-)`#!C;VY#`O`".B`@ +M5F%R:6]UP``7P%Q875T:&]R<\`%`1\&`?("`DT'$`H5"%!T;W`M;`P$`W8% +M`#`'`4$`$&GD!@FV`B)I;O@$(FEOX08$O0+P`DY%5U,@+2!H:6=H;&EG:'1S +M7`8P'2(`#!P=71>`C`@(F,T!A$B)`,`J@2!N965D?``Q;6%I]@$C97*N`05P`"1I;F0`@2YH+FEN"@DM]`=2;&%T97-G +M`!%B-`(#<@$"M0!@"@I'=6ED\P`H($14!@32`0)U``&W`7!S>7-T96TZIPH" +MN`1U+C$@97AP;(,"`R\#`$(!`B$`!)H#`S,``(@$#S0`"P`B``PU`"]A=#0` +M#"AA=#,`!@$&(2XSM@L0<]\&@&]V97)V:65W\P(`H``%G@L`<04P=VAOD0(4 +M*J0*A5]R96%D+C,L$``!^`@-$0!17V1I``'<`%0P#'`(%>`D09BP``;<&42H@1TY5=0$"-0(F("@$"P`:`$%L;VYG4`8` +MK0LB+``-J`0`9`]$J(%!/4TE8('5S=&%R6P`"$``/B@P# +M!R$`P&]C=&5T+6]R:65N=!<$,7!I;QX`IE-64C0@05-#24D4``)3``\R``5A +M0FEN87)Y+@#`("AB:6FEP/@$Q:6]N&`%= +M8GII<#(6``1\`4TO3%I7'0"B;'IM82P@;'IID2,',@*'T'`30$`(0!`S,$`/0#8"P@971C*>\+`OH#`*D"`&@1`HT` +M`88!`MH`#Y8#!0'(`V$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0%!`?.``]9 +M`P`*%@,S5VAE`P(`-0<#U`(2<^8%87)E`3AN97>U`P#P!`#]`@.?`0![``&'"0$K%0)*#`!-$2)IE(7`+4(`E(( +M07!O;&PV$@;D%$%D;VXG[`&097AP;&EC:71LV0EB=F]K92!A^@\18W\*`\X1 +M("`HTA``=0P('`(08;(!`2<0`BT`",T`%&]S!'`I+"!I="!W<`!0(&=E="#2 +M$@%="@"D!#<@26YN``4F%P&>``%1`0.;`")E;LD!!RT``'P`"W$`*&1E$0`# +MJ@`1+%@1`H```(T.`)8!`!8!`$``,&%G8?,/`5\*D6-O!<1<_```.X'#V0:________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________________________________________]>4'1S(&%N3Q$``/`> +M9"!H86YD;&5S(&%N>2!O9B!T:&4@9F]L;&]W:6YG(&)E9F]R92!E=F%L=6%T +M$@``(`#Q#6%R8VAI=F4Z"B`@*B!U=65N8V]D960@9FEL97,4``$*`/$"('=I +M=&@@4E!-('=R87!P97(;`/$!9WII<"!C;VUPFUA+"!L>FEP+"!A;F0@>'HC```9-!0`]0<*5&AE(&QI +M8G)A"!I;G1E&-E<'0@9F]J`/$'("!E;G1R +M:65S('1H870@.`?$#;F%M +M97,L($%#3',L(&5T8RDND@"P3VQD($=.52!T87)=``2I``+*`/$$;V-T970M +M;W)I96YT960@8W!I;S4`ME-64C0@(FYE=V,B%0`G`'@G;71R964GNP!X25-/.38V,!,`6CT!X'-Y0`&EP#R`FES(&1EP`!S@`4=E@#$G.C`%0@;VYL>0H#0&UE;G2R +M``$>`P"F!`)G`S`@8F5``(!R96%D86)L9:(`07=R:70,`!!A#`$"!`$!1`0! +M.P!$96%C:"8"`98"$WE#`%!I;F1E<*H`(FYT?P`04<`L$DG +M=F4@871T96UPQ`/@=&\@;6EN:6UI>F4@2!I;G9O:V4@82!PZP`@=6PW!"!E +M85D"0"`HD`!RT`!^\%`(`!`ID!<"DL(&ET('=P`.`@9V5T +M('!U;&QE9"!I;J0$-R!);FX`-RP@:9X``5$!`YL`(F5NR0$'+0``?``+<0`H +M9&41``/&`A$L\``"@``B;F6.`@`6`0!``&)A9V%I;G-'`J!C;W)R97-P;VYD +M)P0(20`-6@`">P,Q:65SPP`!;P.A86QS;R!R961U8[D%,&4@`(&5N=FER;V[7`C%S('=N`@&@`A!MV`$3 +M6QE(&%P<')OR`,`R0@"^@#@=&\@:&%V92!M=6QT +M:7`E```A!1!V$@,`!04`N0A5(&]P96Z>`%`@(&)S9",'(75SO`$`/06#;B!I +M=',@(D#E`!(BO01&P`28D(``"P$`-$``#8!(71OFPDP9&%TUP!6=7)C +M93HN`0+("0#"`!)A[`(`R0H!*P`S:6X@)P$`3P@S861DC@(18?P(!*H!`'D& +M(6]U]P119FER0#`',*T"!S87ES+@I214%$346[!@?H!N$@ +M8G5N9&QE+@H*475E<_H"H#\@($ES8N9V]O9VQE+F-O;2]P+VH`$2\Z`"!S+VD``),``6<`47-U8FUI9P!P +M96YH86YC9;L``*8`!C@`@RP@<&QE87-E+```.P``!`,`2P7!1`GH@1` +M9W)A;18"F-%#A)B!P`2>`<``$D!`)()`"<`4"H@97AA20!`8$(&YDT`(Q9G5L+P(&10`0+T,*`84! +M$6&>"E%A8W0@H($',+!0$^`0!U```7`@#Y!`%Q``%Q"@B7```\"3-Y+C-- +M``#O!#)E(")K`P6K``$D`!0B"PM9(&-L87-$``$?"49N86QSG0`2!Q(M@@0U +M"`"X!!,B!0XR+F@BJ0`R +M:&4*7PP0(+`)`/H``!0`!.D&`W((`G\"$&T:%P/[`$(N("!0B@FS;&5T('5S +M"FMN;W>5$P`P%&!E\6`2T5`A``#XH,`P`""(&EN'!L86EN3`1!F+``0'1E;J`*%35E(T($%30TE)=`(!%``"4P`/,@`%84)I +M;F%R>2X`H"`H8FEG+65N9&GS!(-R(&QI='1L91$``OH`\0))4T\Y-C8P($-$ +M+5)/32!I;;<"@"AW:71H(&]P^@7`86P@4F]C:W)I9&=E10!B2F]L:65T*0$! +M[P$"20`T6DE05@,$0`"0=6YC;VUPB,``!DT +M%``)"`&58V%N(&-R96%TSP`!=00/!@$"`NP"`[\#`KP"#Q\#&#`B&-E<$`%`+D%!&D" +ML"!T:&%T(')E<75IE@4G87C*`B`@*'T'`30$`(0!`S,$`/0#<2P@971C*2YO +M`0#Z`P"I`@8B!`$7``+:``^6`P4!R`-A(FYE=V,BFP,!,P`G?P(-F5A;;4%`A$+@"X@(%1H97)E+``C +M;F_B!P""`@/?"`"3!/("(&EN+7!L86-E(&UO9&EF:6.M"/,";W(@U`P#P!`![ +M``.?`0![``&'"0&C``)*#`,*`P`X"`"R``$>`P"F!`(,`B$@8C<)<7)E861A +M8FP`!@","@$,``$L"P($`0!H``([`$)E86-H/0$A=F5S`Q-Y0P!0:6YD97"J +M`"5N="(!`!@)4&%R=&EC0@4D;VZ!`02N`$17:6MI4@PP:6YGR0`P:&]WFPP" +MI@<'E@H"*@$A3VX_"`#W#`)X!@$""B-N9/@``8@)8V%L=V%YD`!RT`!"T'`,T`%&^5"'`I+"!I="!W<`!Q(&=E="!P +M=9P-(&ENI`0W($EN;@`W+"!IG@`(FP`B96[)`02UV```S#`#W +M"!%IAP8`A`!P96YV:7)O;M<",7,@=Y`#`:`"$&W8`1-R6@,%,`(`6P`"?P`1 +M>7L#$7`U`-%A=&5V97(@8FQO8VMS\```[@`A$)P`$`B0`P;6%K>0"0:7,@ +M97-P96-I;@0!T`$"J@$`.@@P.B`BDPH!#A$)V@T3(KD"`-X.(F%NZ`(`I0<& +M-`H0+&,`0&1EF-%#A)B!P`2>`<``$D!`)() +M`"<`02H@97@;$T!S.B!3,@-4'2(`"%P=6<0,"`B8S0&%"*\&3EO;VQ-``)6`08U`0"4``"P"@&.`0]M +M`0$`(`T!$!H!V@$T90HGL``C92>O&0,D!`"3``!.``]D&O______________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________5E`@("!T +M;SL1``#R-B!B92!R96%D(&]R('=R:71T96X@=&\@86YY(&1A=&$@7,N"E)%041-15``1"!L:6)M`=%B=6YD;&4N"@I1=65SK@"@/R`@27-S=65S +M/U(`UBH@:'1T<#HO+W=W=RXX`$`N;W)GDP``2`$Q:&]MIP"`(&]N9V]I;F8$(&YD +MT`(Q9G5L+P(&10!1+VUI;FF%`1%AXP%186-T('-@`+`@9&5M;VYS=')A=+\`!,GK0`#)`0`DP``3@#U`2YA;2P@86-L;V-A;"YM-"SA +M`$!E+F%C_P```@`0+:("`)\`!*@`#*($LBP@;VYL>2!N965D?``Q;6%I]@$C +M97*N`05P`"1I;F0`@2YH+FEN"@DM]`=2;&%T97-G`!%B-`(!9@$39;4`8`H* +M1W5I9/,`*"!$5`8$T@$"=0`!MP%P!1%E^P,`\@"`;6%T``&I`5"`"X!!,B?P(R+F@BJ0`R:&4*7PP0(+`)`'4!`!0`!.D&`W((`G\"-&UO +M2X`P"`H8FEG+65N9&EA;J(!8VQI='1L91$``OH`\0))4T\Y-C8P +M($-$+5)/32!I;;<"$"@X#C`@;W#+`\!A;"!2;V-K[`@0]`5HW+5II<"8` +MV$UI8W)OFEP/@$Q:6]N +M&`%=8GII<#(6``1\`4TO3%I7'0"B;'IM82P@;'II\+`OH#`*D" +M`&@1`HT``88!`MH`#Y8#!0'(`V$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0% +M!`?.``]9`P`*%@,S5VAE`P(`&@T#U`(2<^8%87)E`3AN97>U`P#P!`#]`@.?`0![ +M``&'"0&C``)*#`!-$2)I7-S""IE9(H(`D<`L$DG=F4@ +M871T96UPC```%1`0.;`")E;LD!!RT``'P`"W$`*&1E$0`#Q@(1+.4)`H```(T. +M`)8!`!8!`$``,&%G8?,/`5\*D6-O7L#$7`U`&)A +M=&5V97)X%Q%S\```[@2X'$'1[%R%I;5<#<6]R(&UM87`I`0!>$P'Y%@*Y%P"V`A!G +MPA<0:2(3`2(`!4H``.,3(6-EA0`A3VZ0`QMEPP`"Y`(R<')O.@$!A0$`FA<1 +M+408DF5D(&]U='!U=.\"`&`$\0-O8FIE8W0M$E33SDV-C`3 +M`+0W+5II<"!AFUA+"!L>FEP+"!A;F0@>'HC`,$*3F]T97,@86)O=724 +M`')L:6)R87)YT0#P+G1E8W1U2!S +M=')E86TM;W)I96YT960@4,`4&EN9&5PJ@`B;G1_`$%R92!A!`"4=&EC;&5S(&]N@0$#=@+P +M`2!7:6MI(&5X<&QA:6YI;F?)`#!H;W?X``+U``$N("!)9B!Y +M;W4@9&]N)^P!`+8`\0)I8VET;'D@:6YV;VME(&$@<.L`@'5L87(@9F5A60)` +M("AS=2\!&7,<`A!AZ0`'+0`'!@,`@`$"F0%P*2P@:70@=W``\``@9V5T('!U +M;&QE9"!I;BX^`"=);FX`-RP@:9X``5$!`YL`(F5NR0$'+0``/@`+<0`H9&41 +M``/&`A$L\``"@``B;F6.`@`6`0!``&)A9V%I;G-'`J!C;W)R97-P;VYD)P0( +M20`-6@`">P,Q:65SPP`!;P.P86QS;R!R961U8V6;`C!E('.%`2-O9H@!`+,! +M$"UV`&%E9"!B:6X]`"`@:2P$@"!E;G9IP,1<#4`T6%T979E8!(71O(@`%2@!A="!O +M;F-EA0`A3VZ0`QMEPP`"Y`(R<')O.@$!A0%18W1L>2W,`))E9"!O=71P=73O +M`@!@!/$#;V)J96-T+7-T>6QE(&%P<')OR`,`H`4"^@#@=&\@:&%V92!M=6QT +M:7`E``.E`P(!!`!;!E4@;W!E;IX`L2`@8G-D=&%R('5SO`$`/06#;B!I=',@ +M(D#E`!(BR`-&P"`*`'`2L`,VEN("8<``J,!!H`%,7=A;H@`$'0V +M!`5%`0!@`!!IA0(`C@%EB!$!G&%)`$!S.B!3,@-4`0-)`#!C;VY#`O`".B`@5F%R:6]UP``7P%V875T:&]R,&`4D!A69I9W5R92`M#``"1`"U'2(`")P==8-(")C-`81 +M(B0#`#@,*6]L30`"5@$&ZP,!*0$`%@D`C@$/;0$!`*(&('5SW0H`V@$T90HG +ML``C92>M``,D!`"3``!.`/``+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C%P$` +M`@`0+:("`)\`!*@``-D."*($$BP:#@#7"P)\`#%M86GV`2-EPH"MP(29:`,`!(&0'-E<77J"!!S"P4!/@$`=0``%P(` +M^00!<0`!<0H(EP``/`DS>2XS30``[P0R92`B:P,%JP`!)``4(@L+62!C;&%S +M1``!'PE&;F%L"`"X!!,B!0XR+F@BJ0`R:&4*7PP0(+`)`/H``!0`!.D&`W((`G\"-&UO +M5$P`P%&!E+``-J`0`9`[$J(%!/4TE8('5S=+`1!!``#XH,`P%\``(Q`%9O +M8W1E=*\4`&`"`1X`H5-64C0@05-#24ET`@$4``\R``L00FT1$7DN`+$@*&)I +M9RUE;F1I8=018VQI='1L91$``OH`!%\6D4-$+5)/32!I;;<"$"@X#C`@;W#+ +M`\!A;"!2;V-KC2H`0#E%PD(`0``"@*<$`5+`0!U!`\&`0("@P$#OP," +MO`(/'P,8,")R9:`-`!`6$2)'`P)/`,(L('=H:6-H('=I;&SK&`!P"`###P-? +M`4!S(&5X+10``@(`N04$B1$""Q<#6A4P`T&-P:6\N-2P@;71R964)``!O`%1T87(N-;<`PB!D +M971A:6QE9"!I;E(`D&EO;B!A8F]U=$T`('-EN`"#<&]P=6QA#0#46-H86YG?@$W +M;6%T(0"P;V-T970M;W)I96X!`P!@`@$>`*%35E(T($%30TE)=`(!%``"4P`/ +M,@`%84)I;F%R>2X`P"`H8FEG+65N9&EA;J(!8VQI='1L91$``OH`\0))4T\Y +M-C8P($-$+5)/32!I;;<"@"AW:71H(&]PRP/`86P@4F]C:W)I9&=E10!B2F]L +M:65T*0$![P$"20`T6DE05@,$0`#`=6YC;VUPB,``!DT%``)"`&58V%N(&-R96%TSP`!=00/!@$"`J\!`[\#`KP"#Q\# +M&,$B!S>7-T96TN("!4:&5R92P`(VYOX@<`@@(#WP@`DP3R`B!I;BUP;&%C92!M +M;V1I9FECK0CS`F]R(')A;F1O;2!A8V-E0`&@`3R`FES(&1EP`#P`!APD!HP!4(&]N;'D* +M`P`X"`"R``$>`P"F!`(,`B$@8C<)<7)E861A8FP`!D%W48!`-T!*F5DB@@"1P"P22=V92!A='1E +M;7",!^!T;R!M:6YI;6EZ92!S=+4(`E((4'!O;&QU(@=1+B`@26;U"$!D;VXG +MU@7L#$7`U`-%A=&5V +M97(@8FQO8VMS\```[@2X'<70@82!T:6U7`P!K"S%M87#X`C!E;G21!@/0`@%1 +M`T!G:79EY@$A=&\B``6A`&%T(&]N8V6%`"%/;I`#&V7#``+D`C)P@``P0&%82!S;V-K970^ +M`TEW:7-HN@0!)@]P=71I;&ET>7,"!8P``#\``TP/4"!E87-Y3@Y1=7-E("(A +M`0!:""`L(E`(<"P@8V%P86)!``'V`@0#`07Q`&%E($%027.W!`CV!0&7`8`@ +M:6YD:79I9&P.`]L(`(4``A4&`$(``'(+`-$``#8!(71OK`TP9&%TUP``!0X6 +M.BX!`L@)`#T`$F'L`@#)"@$K`#-I;B`G`0"5"S-A9&2.`AAA]PP!UP<#'@]1 +M9FER0"0:7,@ +M97-P96-I;@0!T`$"J@$`.@@P.B`BDPH!#A$)V@T3(KD"`-X.(F%NZ`(`I0<` +M$0,"6@<0+&,`0&1E8N9V]O +M9VQE+F-O;2]P+VH`$2\Z`"!S+VD``),``6<`47-U8FUI9P!P96YH86YC9<\` +M`*8`!C@`,BP@<-H0`BP``#L```0#`$L'`1<)X65S="!V:6$@1VET2'5BP@`" +MD`"A7!1`GD1(`\A$`%@)S82!F=6QL +M+98(F-%#A)B!P`2>`<` +M`$D!`)()`"<`02H@97@;$T!S.B!3,@-4P``7P%C875T:&]R:1``EPT!\@(`P1,2 +M+NT/4'1O<"UL#`0#Q0P`,`0&";8""',5`.L%`>X/\`4@*B!.15=3 +M("T@:&EG:&QI9VAT<]P`,')E8]D4`C$%`Z`"DD-/4%E)3D<@+0P%`$(4`,H' +M(61O7P8!AP4`S@#`*B!)3E-404Q,("T@9`HQ86QLCP0!#0``BA8`OP`"*0`# +M0`41+3P``5X1`A@`8&-O;F9I9[(6%2T,``)$`+5S8W)I<'0L('-E96<``"@% +M`ED6`F,(@2H@0TUA:V5,U`0Q='ATB``A<'5G$#`@(F,T!A$B)`,`.`PI;VQ- +M``)6`0;K`P$I`0`6"0".`0]M`0$`(`T0=3T3`A`7)`HGL``C92>M``,D!`"3 +M``!.`/``+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C_P```@`0+60"`)\`!*@` +M`-D."*($$BP:#@#7"P!9"Q!YR@4!]@$C97*N`05P`"1I;F0`@2YH+FEN"@DM +M]`<`YA,2\%#V0:____________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________]G4&%N(&ES-1$``/`02#R`I!I;VYS+@H*5&B=`?("<"UL979E;"!D:7)E8W1O'2(`#!P=71>`H$@(F-M86ME(B0#:60@ +M=&]O;$T``E8!!NL#`2D!,2!I;DP!#VT!`3!A2!N965D?``Q;6%I]@$C97)<`05P`"1I;F0`\@,N:"YI +M;@H)+2!T96UP;&%T97-G`!%B-`(!9@$39;4`8`H*1W5I9/,`4"!$;V-UF04" +M@0$`Q0$R86QL=0`!MP&R'!L@P(#+P,`0@$" +M(0`$F@,#,P``B`0/-``+`"(`##4`+V%T-``,*&%T,P`&`0:`+C,@9VEV97-X +M!H!O=F5R=FEE=_,"`*``!+L%$&%Q!3!W:&^1`B,J(,0&A5]R96%D+C,L$``` +MT04=91$`45]D:7-K%@`@;F30`0@^``,<``"9`!!V7P$"MP)P960@8V%L;!(& +M$'/4!D%N8V5SK0(`DP``=0`!1P`#0@9H92!!4$ESEP!S96YTP$2+8($ +M4W,N-2!D5@("KP``&0,`\@#$;6%T=&%R+C54`0CQ!$%A8F]U4P4@P`3+/('`(H!@6AA``%4!%#0#`ED'`W@"!R$`L&]C=&5T +M+6]R:65N`0,`8`(!'@"A4U92-"!!4T-)270"`10``E,`#S(`!6%":6YA`@@;W#+`\!A;"!2;V-KFEP/@$Q:6]N&`%=8GII<#(6 +M``1\`4TO3%I7'0"B;'IM82P@;'II`3AN97>U`P#P!`![``.?`0![``&'"0&C``)* +M#`!-$2)IF4@``%1`0.;`")E;LD!!RT``'P`"W$`*&1E$0`#Q@(1+/```H```(T.`)8! +M`!8!`$``,&%G82X.`?$)D6-OP,1<#4`T6%T979E$P$/`P$W%0%1`T!G:79E +MY@$A=&\B``5*``#C$R%C984`(4]ND`,;9<,``N0",G!R;SH!`84!46-T;'DM +MS`"2960@;W5T<'5T[P(`8`3Q`V]B:F5C="US='EL92!A<'!R;\@#`/D4`OH` +MT'1O(&AA=F4@;75L=&G#$P2I``(!!`"Y"%4@;W!E;IX`$R`5$`!J$``*`1%I +M(0AC:71S(")`/``2(KT$$7,P#@)C!098`&!I='-E;&93`5!R96%D+^8`8'1E +M;B!U@``S0*%82!S;V-K970^`TEW:7-HN@0! +M)@\#60\`7,N"B05 +M$6:X#01/&0.A&$0N"@I1$19`/R`@29X9(',_4@`1*@49=CHO+W=W=RXX`$`N +M;W)GDP``2`$0:+@"`%<`0V]N9V]8!Q<@3`<@(&18%B!O<#P%"!D1!+H1`:P( +M`3<,`'$``#H`(&YK-`$!P0`&7,@9&5T96-T960@875T;VUA +M=&EC86QL>4<`L$DG=F4@871T96UP(@#P(71O(&UI;FEM:7IE('-T871I8R!L +M:6YK('!O;&QU=&EO;BX@($EF('EO=2!D;VXG=*@``+8`\"1I8VET;'D@:6YV +M;VME(&$@<&%R=&EC=6QA!E('-O;64@=71I;&ET>3X`!8P``+$!\09P2!D8737`%9UP",B!O9BL`,VEN("X +M`0!V``*4`0```P&^``7+`0#3``.C`0:`!3%W86Z(`!!T-@0#-@(!6P,`'P$` +MN@!!9&ES:RP#`\0!N6-O;G9E;FEE;F-EP`$`B0`P;6%K>0"0:7,@97-P96-I +M;@0!T`$"J@'S!TYO=&4Z(")P87@@:6YT97)C:&%N9V6?!1,BN0(@;&P\`0+H +M`A!DO@$`_04!C080+&,`0&1E0(1.FH`$B>7!9`G('!R;V=R86T6`G-A(&9U;&PME@AP9"`G=&%R)WX``P(` +M4W)E<&QA0@%`8G5I;($&`(H``V,``"H`9BH@8W!I;V,```X`"V0`(&1I:P4R +M96YT,`-#9F%C96H#`P(`,&5S`<``$D! +M`)()`"<`4"H@97AA20!`8$ +M(&YDT`(Q9G5L+P(&10`0+T,*`84!$6$&"5%A8W0@`0-)`#!C;VY#`O`".B`@5F%R:6]UP``7P%Q875T:&]R<\`%`1\& +M`?("`DT'$`J(!E!T;W`M;`P$`W8%`#`'`4$`$&GD!@FV`B)I;M8$`'$+`.L% +M!+T"\`).15=3("T@:&EG:&QI9VAT=&%R+C54`0CQ!$%A8F]U4P41 +M]!9!I;@IA(&YU;6+R#!=FD0<$.P''"@I9;W4@`D09@82`;<&42H@1TY5=0$"-0(F("@$"P`:`"-L;[P% +M`*T+(G,L$```!0L3(!$``&,`4G-P87)S?`(A`*%35E(T($%30TE)=`(!%``/,@`+ +M$$)M$1%Y+@"Q("AB:6`@@;W#+`\!A;"!2;V-K[`@0]`5HW+5II<"8`V$UI +M8W)OFEP/@$@:6]/$WTJ +M(&)Z:7`R%@`$?`%-+TQ:5QT`HFQZ;6$L(&QZ:7`3`R]X>B,``!DT%``)"`$` +M``H"G!`%.@$`=00/!@$"`J\!`[\#`KP"#Q\#&#`B\+`OH#`*D"`&@1`HT` +M`9L!`MH`#\@#"F$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0%!`?.``]9`P`* +M%@,S5VAE`P(`OP@#U`(2<^8%87)E +M`3AN97>U`P#P!`#]`@.?`0![``&'"0$K%0)*#`,*`P`X"`!O$!1T[A("#`(A +M(&(W"0","@&/&`.X%`$,`!!A#`$"U!``:``".P`199P6`#T!(79E4,` +M4&EN9&5PJ@`E;G0B`0!$#0%Y&0!"!1)O;`T&L`L/9!K_________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_________________________________________________V50=',Z"B`P +M$0``\0T@*B!'3E4@=&%R(&9O`*935E(T($%30TE)%``"8P`/,@`%84)I;F%R>2X`\P<@*&)I +M9RUE;F1I86X@;W(@;&ET=&QE$0`"^@#P'TE33SDV-C`@0T0M4D]-(&EM86=E +MFEP/@$Q:6]N1`!=8GII<#(6``1D`4TO3%I7'0"B +M;'IM82P@;'IID#`*4#`.<#]A)U2!S=')E86VU!>!S>7-T96TN("!4:&5R92P`D&YO(&1I +M-R86YD +M;VT@86-C97-S+GD`!I<`D&ES(&1EU +M`P"C!`![``'.`!!VFP0`-0<2$N("!)9B!Y;W4@ +M9&]N)^P!`+8`\0)I8VET;'D@:6YV;VME(&$@<.L`('5LO0B@96%T=7)E("AS +M=2\!&7,<`A!AZ0`'+0`$10<#(@("F0%P*2P@:70@=W``X"!G970@<'5L;&5D +M(&ENI`0W($EN;@`W+"!IG@`!40$#FP`B96[)`07L#$7`U`-%A=&5V97(@8FQO8VMS\```[@2X'<70@82!T:6U7`W%O8!(71O(@`%H0!A="!O;F-EA0`A3VZ0 +M`QMEPP`"Y`(R<')O.@$!A0%18W1L>2W,``"."5)U='!U=.\"`&`$\0-O8FIE +M8W0M2!B=69F97(@ +M)`@`90`$<@&%82!S;V-K970^`TEW:7-HN@3`P" +M`,D*`2L`,VEN(">D``,P``*,!!H`%,7=A;H@`$'0V!`5%`0!@```:!!!TC@7,N"E)%041-1;L&!^@&X2!B=6YD;&4N"@I1=65S^@*@ +M/R`@27-S=65S/U(`URH@:'1T<#HO+W=W=RX@!S!O3``!(`1!HN`*#9F]R +M(&]N9V]8!Q@@9`!P9&5V96QO<#P%)BP@8`]`9&]C=10``:P(`3<,`'$``#H` +M(6YK70$`70`&8N9V]O9VQE+F-O;2]P+VH` +M$2\Z`"!S+VD``),``6<`47-U8FUI9P!P96YH86YC9;L``#8"!C@`@RP@<&QE +M87-E+```.P``!`,`2PB!$!G0&";8"(FENU@0`I`H`ZP4$ +MO0+P`DY%5U,@+2!H:6=H;&EG:'1S7`8PM```Z#S`@*B"3``!.`/``+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C_P`` +M`@`0+:("`)\`!*@``-D."*($$BP:#@#7"P!9"Q!YR@4!]@$C97*N`05P`"1I +M;F0`@2YH+FEN"@DM]`<`YA,22XS]!0P86EL[P0R92`B:P,%JP`!)``4 +M(@L+62!C;&%S1``!'PE&;F%L``'? +M`5&%M<&QE('!R;V=R86US('1H870@>6]U(&UA>2!F:6YD('5S969U +M;"X*("`@*C``\@=S+VUI;FET87(Z(&$@8V]M<&%C="!S2P#09&5M;VYS=')A +M=&EN9SX`XR!O9B!L:6)AM`_`$ +M,R!G:79E2XS!`,!JP(2(FL#!:L``20`Z2(@=71I;&ET>2!C;&%S +M1`"6:6YT97)N86QSG0!@P$2+8($4W,N-2!D5@(#I@0@:6QV`]1R +M;6%T-50! +M"/$$4&%B;W5T&@$@P"`+"!I;F-L=62*`8%H +M87)D+71O+3`&`J@!$G-'``!!`&%M;V1E$D#(F5R60<#>`('(0"P;V-T970M;W)I96X! +M`P!@`@$>`*%35E(T($%30TE)=`(!%``"4P`/,@`%,$)I;LH$`$(`H"`H8FEG +M+65N9&GS!(-R(&QI='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I;;<"$2AX +M""!O<,L#P&%L(%)O8VMR:61G944`8DIO;&EE="D!`>\!`DD`-%I)4%8#!$`` +M('5N3@DPFEP/@$Q:6]N&`%=8GII<#(6``1\`4TO +M3%I7'0"B;'IM82P@;'II?P( +M-F5A;;4%`A$+@"X@(%1H97)E+``C;F_B!P""`@/?"`"3!/("(&EN+7!L86-E +M(&UO9&EF:6-D"_``;W(@0`&@`23:7,@9&5S:6=N +M)0P298@%`$`$`;,%.&YE=[4#`/`$`'L``Y\!`'L``8<)`:,``DH,`PH#`#@( +M`+(`,71H82\)`RL`(2!B-PD`:@@Q86)L``8`C`H!#``!+`L"!`$`:``".P!" +M96%C:#T!(79E4,`4&EN9&5PJ@`E;G0B`0`8"0`/#Q!C0@42;VP-!C4* +M5"!7:6MI4@PP:6YGR0`P:&]W40\!LP,79)8*`BH!(4]N/P@`]PP"8`8#`P$$ +MS0`!<`!`;'=A>48!`-T!*F5DB@@"1P!P22=V92!A="T-`(P'`,$/D&EN:6UI +M>F4@P,1<#4`T6%T979EP" +M`,D*`2L`,VEN("#U%F:7)S=)("`*8!$6%P +M$A%O61$`]@`6+G0``]D#`J60!`,P``*,!!H`%,7=A;G\%$G0=#P-%`0!@```:!!!TC@0# +M`',*%EF-%#A)B!P`2 +M>`<``$D!`)()`"<`!A\:,#H@4S(##V0:____________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________________________________]J4'(@71E(&%T +M(&$@=&EM90H@("!O2UB;&]C:V5D(&]U='!U="X*"B`J(%1H92!O8FIE8W0M +M'1E;G-I;VZ*``,<```J`#!E;&93`5!R96%D+^8`EG1E;B!U2!B=69F97(@;W+!``!E``1R`3!A(',K`5%T+"!I9@(!8'=I +M2UT;RUU`@#1```V`:!T;R!A;GD@9&%TUP!6=7)C93HN`5%C`@&^``7+`0#3``.C`4,N("!)I`$A86Z(`!)T70`#10$`8``0 +M:84"86\@9&ES:RP#`\0!N6-O;G9E;FEE;F-EP`$`B0`P;6%K>0#1:7,@97-P +M96-I86QL>=`!`JH!\P].;W1E.B`B<&%X(&EN=&5R8VAA;F=E(&9O7,N"E)%041-12X``$0$!&T!T6)U;F1L92X*"E%U97/Z`J`_("!)0(1.FH`$B>7!1`G'@9`9W)A;18"\`9A(&9U +M;&PM9F5A='5R960@)W1A`<``$D!0'-U8V@G`%`J(&5X84D`0',Z(%,R +M`U1S;6%L;!4`!#X!`%(#(6%T(`8@;6'F!"!N9-`",69U;"\"!D4`42]M:6YI +MA0$18>,!46%C="!S8`"P(&1E;6]N0&";8"(FEN^`0B:6_A!@2]`O`"3D574R`M(&AI9VAL +M:6=H='-M``,D!`"3``!. +M`/4!+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_```"`!`MH@(`GP`$J``,H@2R +M+"!O;FQY(&YE961\`#%M86GV`2-E'!L@P(#+P,`0@$"(0`$F@,#,P``B`0/-``+`"(`##4` +M+V%T-``,*&%T,P`&`08A+C.V"Q!SWP:`;W9E"P!Q!3!W +M:&^1`A0JI`J%7W)E860N,RP0``'X"`T1`%%?9&ES:Q8``GX'`X(%`3X``QP` +M`)D``7L*`K<"$F6@#`!;!!!SU`80;A$,`-8"`),``'4``!<"`/D$`7$``7$* +M")<``#P),WDN,TT``.\$,F4@(FL#!:L``20`%"(+"UD@8VQA``'<`%`D09BP``;<&42H@1TY5=0$"-0(F("@$"P`:`$%L +M;VYG4`8`K0LB+``-J`0`9`]$J(%!/4TE8('5S=&%R6P`" +M$``/B@P#!R$`P&]C=&5T+6]R:65N=!<$,7!I;QX`IE-64C0@05-#24D4``)3 +M``\R``5A0FEN87)Y+@#`("AB:6B,``!DT +M%``)"`$```H"G!`%.@$`=00/!@$"`J\!`[\#`KP"#Q\#&,$B&-E<$`%`+D%!(D142!T +M:&%T0PX`TQ,`40`%Z1(P?P(-F5A;;4%`A$+!8@40&ES(&[6$C%R96,P$0/?"`"3 +M!$$@:6XM`@^"(&UO9&EF:6/E#/<`;W(@`3AN97>U`P#P!`#]`@.?`0![``&'"0$K%0)*#`!-$2)I +ME(7`+4(`E((07!O;&PV$@;D%$%D;VXG[`&097AP;&EC:71LV0EB=F]K92!A +M^@\18W\*`\X1("`HTA``=0P('`(08;(!`2<0`BT`",T`%&]S!'`I+"!I="!W +M<`!0(&=E="#2$@%="@"D!#<@26YN``4F%P&>``%1`0.;`")E;LD!!RT``'P` +M"W$`*&1E$0`#J@`1+%@1`H```(T.`)8!`!8!`$``,&%G8?,/`5\*D6-O"(&5N=FER;VX/"T!W:&5R+Q9`870@;=@!$W): +M`P4P`@!;``)_`!%Y>P,1<#4`8F%T979EFEP(&-O;7!R97-S:6]N%0!=8GII<#(6``0F +M`$TO3%I7'0#_`VQZ;6$L(&QZ:7`L(&%N9"!X>B,``!DT%`#U!PI4:&4@;&EB +M2!C86X@8W)E873/`+%S(&EN(&%N>2!O9N8`8&9O;&QO=_0``21E9-T` +M$2E%``"=``#5`85"4T0@)V%R)U(``1X`>"=M=')E92>[`'A)4T\Y-C8P$P!: +M-RU::7`Y`#9805(1`$,*5VAE`P(`Y`$#U`(AT!X'-Y +M0`&EP#R`FES(&1E +MP`!S@`4=E@#$G.C +M`%0@;VYL>0H#0&UE;G2R``$>`P"F!`)G`S`@8F5``(!R96%D86)L9:(`07=R +M:70,`!!A#`$"!`$!1`0!.P!$96%C:"8"`98"$WE#`%!I;F1E<*H`(FYT?P`0 +M)`#!H;W?X +M``+U``".!`,L``(J`2%/;JH`'"P#`0/9`@)P`$!L=V%Y1@$`W0'R`65D(&%U +M=&]M871I8V%L;'E'`+!))W9E(&%T=&5M<,0#X'1O(&UI;FEM:7IE('-T*P"P +M(&QI;FL@<&]L;'6X`>$N("!)9B!Y;W4@9&]N)^P!`+8`\0)I8VET;'D@:6YV +M;VME(&$@<.L`('5L-P0@96%9`D`@*'-U+P$9``%1`0.; +M`")E;LD!!RT``'P`"W$`*&1E$0`#Q@(1+/```H``(FYEC@(`%@$`0`!B86=A +M:6YS1P*@8V]RP,1<#4`T6%T979E2!B=69F97(@)`@`90`$<@&%82!S;V-K +M970^`TEW:7-HN@3`P"`,,)`2L`,VEN("0#`',*T"!S87ES +M+@I214%$346[!@?H!N$@8G5N9&QE+@H*475E<_H"H#\@($ES8N9V]O9VQE+F-O;2]P+VH`$2\Z`"!S+VD` +M`),``6<`47-U8FUI9P!P96YH86YC9;L``*8`!C@`@RP@<&QE87-E+```.P`` +M!`,`2P7!1`GH@1`9W)A;18"F-%#A)B!P`2>`<``$D!`)()`"<` +M4"H@97AA20!`8$(&YDT`(Q +M9G5L+P(&10`0+T,*`84!$6&>"E%A8W0@H($',+!0$^`0!U```7`@#Y!`%Q +M``%Q"@B7```\"3-Y+C--``#O!#)E(")K`P6K``$D`!0B"PM9(&-L87-$``$? +M"49N86QSG0`2!Q(M@@0U +M"`"X!!,B!0XR+F@BJ0`R:&4*7PP0(+`)`/H``!0`!.D&`W((`G\"$&T:%P/[ +M`$(N("!0B@FS;&5T('5S"FMN;W>5$P`P%&!E2X`L2`H8FEG+65N +M9&EAU!%C;&ET=&QE$0`"QP`$7Q:10T0M4D]-(&EMMP(0*#@.,"!O<,L#P&%L +M(%)O8VMR:61G9>\!`DD`#QX78P\+%P#036EC84`X"!S8W)I<'0* +M"D=U:61E@@"01&]C=6UE;G1A>`""(&EN'!L86EN3`1!F+``P'1E;J`*%35E(T($%30TE)=`(!%``"4P`/,@`%84)I;F%R>2X` +MH"`H8FEG+65N9&GS!(-R(&QI='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I +M;;<"@"AW:71H(&]P^@7`86P@4F]C:W)I9&=E10!B2F]L:65T*0$![P$"20`T +M6DE05@,$0`"0=6YC;VUPB,``!DT%``)"`&5 +M8V%N(&-R96%TSP`!=00/!@$"`NP"`[\#`KP"#Q\#&#`B&-E<$`%`+D%!&D"L"!T:&%T +M(')E<75IE@4G87C*`B`@*'T'`30$`(0!`S,$`/0#<2P@971C*2YO`0#Z`P"I +M`@8B!`$7``+:``^6`P4!R`-A(FYE=V,BFP,!,P`G?P(-F5A;;4%`A$+@"X@(%1H97)E+``C;F_B!P"" +M`@/?"`"3!/("(&EN+7!L86-E(&UO9&EF:6.M"/,";W(@U`P#P!`![``.?`0![ +M``&'"0&C``)*#`,*`P`X"`"R``$>`P"F!`(,`B$@8C<)<7)E861A8FP`!@", +M"@$,``$L"P($`0!H``([`$)E86-H/0$A=F5S`Q-Y0P!0:6YD97"J`"5N="(! +M`!@)4&%R=&EC0@4D;VZ!`02N`$17:6MI4@PP:6YGR0`P:&]WFPP"I@<'E@H" +M*@$A3VX_"`#W#`)X!@$""B-N9/@``8@)8V%L=V%YD`!RT`!"T'`,T`%&^5"'`I+"!I="!W<`!Q(&=E="!P=9P-(&EN +MI`0W($EN;@`W+"!IG@`(FP`B96[)`02UV```S#`#W"!%IAP8` +MA`!P96YV:7)O;M<",7,@=Y`#`:`"$&W8`1-R6@,%,`(`6P`"?P`1>7L#$7`U +M`-%A=&5V97(@8FQO8VMS\```[@`A$)P`$`B0`P;6%K>0"0:7,@97-P96-I +M;@0!T`$"J@$`.@@P.B`BDPH!#A$)V@T3(KD"`-X.(F%NZ`(`I0<&-`H0+&,` +M0&1EF-%#A)B!P`2>`<``$D!`)()`"<`02H@ +M97@;$T!S.B!3,@-4'2( +M`"%P=6<0,"`B8S0&%"*\&3EO;VQ-``)6`08U`0"4``"P"@&.`0]M`0$`(`T! +M$!H!V@$T90HGL``C92>O&0,D!`"3``!.`(\N86TL(&%C;&0:____________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________________________________________________]J4&%N +M>2!D,!$``/`<871A('-O=7)C93H@(%EO=2!C86X@8W)E871E"B`@(&$@8FQO +M8VL@;V8@9"L`\!YI;B!M96UO2!E87-Y+@H*("H@3F]T93H@(G!A +M>"!I;G1E'1E;F1E9#@!`B(` +M$"QC`$!D97-PWP!`=VAA=)8`\`,@;F%M92!S87ES+@I214%$3450`$0@;&EB +M;0'18G5N9&QE+@H*475E`<``$D!0'-U8V@G`%`J(&5X84D`0',Z(%,R`U1S +M;6%L;!4`!#X!`%(#(6%T?`0@;6'F!"!N9-`",69U;"\"!D4`42]M:6YIA0$1 +M8>,!46%C="!S8`"A(&1E;6]NM``,D +M!`"3``!.`/4!+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_```"`!`MH@(`GP`$ +MJ``,H@2R+"!O;FQY(&YE961\`#%M86GV`2-E7-T96TZ<`<"N`1U+C$@97AP;(,"`R\#`$(!`B$`!)H#`S,``(@$#S0` +M"P`B``PU`"]A=#0`#"AA=#,`!@$&@"XS(&=I=F5SWP:`;W9EP$2+8($-7,N-:H(`)X%$67[`P#R +M`(!M871S('-U<'\(!&,"!98!`$P```H"D"XU+"!M=')E90D``&\`7G1A`D09BP``;<& +M42H@1TY5=0$"-0(F("@$"P`:`$%L;VYG50(`K0LB+``-J +M`0`9`]$J(%!/4TE8('5S=&%R6P`"$``/B@P#!R$`P&]C=&5T+6]R:65N=!<$ +M,7!I;QX`IE-64C0@05-#24D4``)3``\R``5A0FEN87)Y+@#`("AB:6FEP,A8`!'P!32],6E<= +M`*)L>FUA+"!L>FEP$P,O>'HC```9-!0`"0@!```*`IP0!3H!`'4$#P8!`@*O +M`0._`P*\`@\?`Q@P(G)EH`U18W1E9")'`P)/`,,L('=H:6-H('=I;&PF$0)U +M`P:0`%%E>&-E<$`%`+D%`?P(-F5A;;4%`A$+ +M<"X@(%1H97(T$2`@;M82,7)E8S`1`]\(`),$02!I;BVW#X(@;6]D:69I8^4, +M\@%OP`!APD!HP`"2@P`31$B:7*"$1!I>0<# +M[A("#`(A(&(W"0","C%A8FP`!@","@$,``$L"P+4$`!H``([`$)E86-H/0$A +M=F5S`Q-Y0P!0:6YD97"J`"5N="(!`$0-``\/$&-"!1)O;`T&-0I4(%=I:VE2 +M#`,,$S!H;W?X``&S`Q!DK0$#V@`"*@$A3VX_"`#W#`)@!@#S#@!0!@/-``%P +M`%-L=V%Y'!L:6-I#16":6YV;VME(&'Z#Q%C +M?PH#SA$@("C2$"4@8?L*`*$!("!AL@$!)Q`"+0`(S0`4;W,$<"DL(&ET('=P +M`%`@9V5T(-(2`5T*`*0$-R!);FX`,BP@:8(5`9X``5$!`YL`(F5NR0$'+0`` +M?``+<0`H9&41``/&`A$LY0D"@```C0X`E@$`%@$`0``P86=A\P\!7PJ18V]R +M"(&5N=FER;VX/"Q%WD`,!H`(0;=@! +M$W):`P4P`@!;``)_`!%Y>P,1<#4`8F%T979E:89`@4.#V0:____________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________________________________________]@4"`@*B!)1!$` +M`/$14T\Y-C8P(&9OFEP,A8`!"8`32],6E<=`/D#;'IM82P@;'II<"P@ +M86YD('AZ(P#!"DYO=&5S(&%B;W5TE`!R;&EB=$`\"YT96-T=7)E.@H* +M("H@5&AI0`&EP#@:7,@9&5S:6=N960@ +M=&]>`61E>'1E;F1>`3AN97?@``#S`#(*("#.`!!V<@$`X0$22!R97%U:7)E;65N=+(`,G1H80D!`BL`("!BCP&0(')E861A8FQEH@!!=W)I +M=`P`$&$,`0($`0!H``([`$5E86-H;P!396YT'!L86EN:6YGR0`P:&]W +M^``"]0`'+``"*@$A3VZJ`!PL`P$`48!`-T!\@%E9"!A +M=71O;6%T:6-A;&QY1P"P22=V92!A='1E;7#7`>!T;R!M:6YI;6EZ92!S="L` +ML"!L:6YK('!O;&QUN`'A+B`@268@>6]U(&1O;B?L`0"V`/$":6-I=&QY(&EN +M=F]K92!A('#K`(!U;&%R(&9E85D"0"`HD`!RT`!P8#`(`! +M`ID!<"DL(&ET('=P`/``(&=E="!P=6QL960@:6XN/@`G26YN`#``%1 +M`0.;`")E;LD!!RT``#X`"W$`*&1E$0`#Q@(1+/```H``(FYEC@(`%@$`0`!B +M86=A:6YS1P*@8V]R7L#$7`U`-%A=&5V +M97(@8FQO8VMS\``0:$,$(6ETH0!!66]U717`F$@82!T:6U7`W%O`+$@ +M(&)S9'1A3X`!8P``0`"\05R;W9I9&4@ +M96%S>2UT;RUUX`0!V``##``"\`Q)EDP`" +M3P0"0:7,@97-P96-I;@0!T`$"J@$`.@CS +M`SH@(G!A>"!I;G1E`<``$D!`)()`"<`4"H@97AA20!`8$(&YDT`(Q9G5L+P(&10`0+T,* +M`84!$6&>"E%A8W0@"`"X!!,B!0XR+F@BJ0`R:&4* +M7PP0(+`)`/H``!0`!.D&`W((`G\"-&UO5$P`P%&!E+``-J`0`9`[$J(%!/ +M4TE8('5S=+`1!!``#XH,`P%\``(Q`%9O8W1E=*\4`&`"`1X`H5-64C0@05-# +M24ET`@$4``\R``L00FT1$7DN`+$@*&)I9RUE;F1I8=018VQI='1L91$``OH` +M$TE?%I%#1"U23TT@:6VW`A`H.`XP(&]PRP/`86P@4F]C:W)I9&=EYP%B2F]L +M:65T*0$![P$"20`T6DE0=00$0``@=6XQ"P`E%@#6$&!R(")D969^!A$B9@D# +M&```H00C:655`0##`0"B`85"4T0@)V%R)U(``?@`$2?]`Q`GNP(/"Q<(V$UI +M8W)OQ=4`)H`-6QZ-*@!`.47"0@! +M```*`IP0!4L!`'4$#P8!`@*O`0._`P*\`@\?`Q@P(G)EH`T`$!81(D<#`D\` +MPBP@=VAI8V@@=VEL;.L8`'`(`,,/`U\!0',@97@M%``"`@"Y!02)$0(+%P-: +M%P%1``7I$C!S("A3"@$T!`"$`0,S!`#T`V`L(&5T8RGO"P+Z`P"I`@!M``*- +M``&;`0+:``_(`PIA(FYE=V,BFP,!,P`G`'!L:6)R +M87)Y3`#08W!I;RXU+"!M=')E90D``&\`\@IT87(N-2!P2!E2QN``/2`>`@875T;VUA +M=&EC86QL>68!065C='.H``#5``,<`E!O;&QO=Y,!$&8L`*%S.@H@("H@1TY5 +M=0$"4@(F("BY`0`:`$%L;VYG50)B;F%M97,L$`!3;&EN:R`1```W`E)S<&%R +M'1E;J+ +M``-J`0`9`]$J(%!/4TE8('5S=&%R6P`"$``R<&%X-`-18VAA;F=^`3=M870A +M`+!O8W1E="UOFEP/@$Q:6]N&`%=8GII<#(6``1\`4TO3%I7'0"B;'IM82P@;'II&-E<$`% +M`+D%!&D"L"!T:&%T(')E<75IE@4G87C*`E(@*&9O?P(-F5A;;4%X'-Y +MU`P#P!`![``-S!`![``&'"0&C`%0@;VYL>0H#`#@( +M`+(``1X#`*8$`@P"(2!B-PEQ4,`4&EN9&5PJ@`E;G0B`0`8"5!AP,1<#4`T6%T979E6QE(&%P<')OR`,`R0@" +M^@#0=&\@:&%V92!M=6QT:3$,!*D``@$$`+D(`/X-%6Z>`%`@(&)S9",'(75S +MO`$`/06#;B!I=',@(D`\`!(BO0012!F +M0"0:7,@97-P +M96-I;@0!T`$"J@$`.@@P.B`BDPH!#A$)V@T3(KD"`-X.(F%NZ`(`I0<`$0," +M6@<0+&,`0&1E8N9V]O9VQE +M+F-O;2]P+VH`$2\Z`"!S+VD``),``6<`47-U8FUI9P!P96YH86YC9<\``*8` +M!C@`,BP@<-H0`BP``#L```0#`$L'`1<)X65S="!V:6$@1VET2'5BP@`"D`"A +M7!1`GD1(`\A$`%@)S82!F=6QL+98( +MF-%#A)B!P`2>`<``$D! +M`)()`"<`02H@97@;$T!S.B!3,@-4P``7P%C875T:&]R:1``EPT!\@(`P1,2+NT/ +M4'1O<"UL#`0#Q0P`,`0&";8""',5`.L%`>X/\`4@*B!.15=3("T@ +M:&EG:&QI9VAT<]P`,')E8]D4`C$%`Z`"DD-/4%E)3D<@+0P%`$(4`,H'(61O +M7P8!AP4`S@#`*B!)3E-404Q,("T@9`HQ86QLCP0!#0``BA8`OP`"*0`#0`41 +M+3P``5X1`A@`8&-O;F9I9[(6%2T,``)$`+5S8W)I<'0L('-E96<``"@%`ED6 +M`F,(@2H@0TUA:V5,U`0Q='ATB``A<'5G$#`@(F,T!A$B)`,`.`PI;VQ-``)6 +M`0;K`P$I`0`6"0".`0]M`0$`(`T0=3T3`A`7)`HGL``C92>M``,D!`"3``!. +M`/``+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C_P```@`0+60"`)\`!*@``-D. +M"*($$BP:#@#7"P!9"Q!YR@4!]@$C97*N`05P`"1I;F0`@2YH+FEN"@DM]`<` +MYA,2\% +M1FYA;'.=`!)S/@M/:6YS:60:____________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________________________]J4&ME2!F;W(@:L`D'-A +M;64@9G5N8S`<``$D!0'-U8V@G`%`J(&5X84D`U',Z(%-O +M;64@6]U(&UA>2!F:6YD('5S969U;"\"!D4` +M42]M:6YIA0$18>,!46%C="!S8`"A(&1E;6]N2#R`I!I +M;VYS+@H*5&B=`?("<"UL979E;"!D:7)E8W1O%#36%K +M94QI\`!,GK0`#)`0`DP``3@#U`2YA +M;2P@86-L;V-A;"YM-"SA`$!E+F%C_P```@`2+50`)'1OJ``,H@2R+"!O;FQY +M(&YE961\`#%M86GV`2-E7-T96TZ"B`J(+@$=2XQ(&5X<&R#`@,O`P!"`0(A``2:`P,S``"(!`\T +M``L`(@`,-0`O870T``PH870S``8!!H`N,R!G:79E2XS30`"]P,2(FL#!:L``20`4"(@ +M=71II`59(&-L87-$``'O!49N86QSG0`P`D09BP``;<&42H@1TY5=0$"-0(B("BK"0"Y`0`:`$%L +M;VYG4`9B;F%M97,L$`!3;&EN:R`1``!C`%)S<&%R'1E;J+``-J`0`9`]$J(%!/4TE8 +M('5S=&%R6P`"$``R<&%X-`,"60<#>`('(0"P;V-T970M;W)I96X!`P!@`@$> +M`*%35E(T($%30TE)=`(!%``"4P`/,@`%84)I;F%R>2X`P"`H8FEG+65N9&EA +M;J(!8VQI='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I;;<"$2AX""!O<,L# +MP&%L(%)O8VMR:61G944`8DIO;&EE="D!`>\!`DD`-%I)4%8#!$``('5N,0LP +MFEP,A8`!'P!32],6E<=`*)L +M>FUA+"!L>FEP$P,O>'HC```9-!0`"0@!```*56-R96%TSP`!=00/!@$"`JH# +M`[\#`KP"#Q\#&#`B&-E<$`%`+D%!&D"42!T:&%T0PXQ:7)E40`!\P,!R@(@("@6!0$T +M!`"$`0,S!`#T`V`L(&5T8REF"@+Z`P"I`@8B!`&&`0+:``^6`P4!R`-A(FYE +M=V,BFP,!,P`GD#`*4#(71EVPAA.@H*("H@+1`0:2`*<&AE879I;'G\"#9E +M86VU!0(1"X`N("!4:&5R9;T/(VYOX@<`@@(#WP@`DP1!(&EN+;D``2<0`BT`",T`%&_Y +M"'`I+"!I="!W<`!!(&=E=!D3`5T*`*0$-R!);FX`-RP@:9X``5$!`YL`(F5N +MR0$'+0``?``+<0`H9&41``/&`A$L\``"@```C0X`E@$`%@$`0``@86<##A%T +M\0F18V]RP,B:67-#P%O`P/G"B!D=1D-`)\#$'.% +M`2-O9H@!`(X2$"UV```S#`#W"!%IM`\`A`!R96YV:7)O;@\+$7>0`P&@`A!M +MV`$3<3`<0-0&)A8VOR`S%F2W,`))E9"!O=71P=73O +M`@!@!/$#;V)J96-T+7-T>6QE(&%P<')OR`,`^10"^@#0=&\@:&%V92!M=6QT +M:<,3!*D``@$$`+D(52!O<&5NG@`3(!40`&H0``H!$6DA"&-I=',@(D`\`!(B +MO0012!F4X.``P1$2(A`0!:""`L(E`(H"P@8V%P86)I;&D2%`8#`07Q +M``+S#P$_#@CV!0&7`8`@:6YD:79I9&P.`]L(`(4``#H2`D(``*P+`-$``#8! +M(71OK`TP9&%TUP``!0X6.BX!`L@)`#T`$F'L`@#)"@$K`#-I;B`G`0!%!3-A +M9&2.`AAA]PP!J0H#'@]19FER41`.'1E;F0@ +M;&EB87)C:&EV92X*"B`J($]N(')E860L(&-O;7!R97-S:6]N(&%N9"!F;W)M +M870@87)E(&%L=V%Y2!A +M8V-E<#4`T6%T979E2W,`))E9"!O=71P=70&`>!4:&4@ +M;V)J96-T+7-T>1`"4'!P!E +M('-O;64@=71I;&ET>3X`!8P``0`"\05R;W9I9&4@96%S>2UT;RUU"!I;G1E0#\`)N86UE('-A>7,N"E)%041-12X`!^@&X2!B=6YD;&4N +M"@I1=65S^@*@/R`@27-S=65S/U(`URH@:'1T<#HO+W=W=RX@!S!O3``!( +M`1!HN`*P9F]R(&]N9V]I;FH&0&%N(&FW`!`L(00!_``!#P"A('1R86-K97(@8B!$!G +MF-A="P@8@<`$G@'``!)`0"2"0`G`%`J(&5X84D`0',Z +M(%,R`U1S;6%L;!4`!#X!`%(#(6%T'`@@;6'F!"!N9-`",69U;"\"!D4`$"]# +M"@&%`1%A!@E186-T('-@`+`@9&5M;VYS=')A=+'2(`")P=;H+(")C-`81(B0#`#@,*6]L30`"5@$&ZP,` +ME``!%@D`C@$/;0$!`&8(('5SW0H`V@$T90HGL``C92>M``-G`0"3``!.`/`` +M+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C_P```@`0+:("`)\`!*@``&H+"*($ +M82P@;VYL>=<+`GP`,6UA:?8!(V5RK@$%<``D:6YD`($N:"YI;@H)+?0'4FQA +M=&5S9P`18C0"`W(!`K4`8`H*1W5I9/,`*"!$5`8$T@$"=0`!MP%PP`( +M2PE`:&%R9!8,`3`&!%L!`4<``(X!86UO9&5R;H\``.@!`+P'<"!V87)I86Y( +M"0":!3!M86[X"T%P86=E.```,0XD``$=`U=H+`#L'`2,)"=H1`,$",&5C=)D#$62V#P,<`@5X"1!F +M!A(!MP91*B!'3E5U`0(U`B8@*`0+`!H`(VQOO`4`K0LB+ +M``-J`0`9`[$J(%!/4TE8('5S=+`1!!``#XH,`P%\``(Q`+!O8W1E="UO\!`DD`-%I)4'4$!$``('5N +M,0L`[!,`UA!@"T4``("`+D%!(D1`FL4`$,.`-,3`%$``;$6`0`&@`0I:7-N%")B98@%`$`$`5X!.&YE=[4#`/`$`/T"`Y\! +M`'L``8<)`2L5`DH,`PH#`#@(`&\0%'3N$@(,`B$@8C<)`(P*`8\8`[@4`0P` +M$&$,`0+4$`!H``([`!%EG!8`/0$A=F5S`Q-Y0P!0:6YD97"J`"5N="(!`$0- +M`7D9`$(%$F]L#0:P"U0@5VEK:5(,`PP3,&AO=U$/`;,#$&2M`0/:``+W$P4T +M&`3\!`#S#@!0!@/-``%P``*`%P+$!0]D&O__________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M________________________________________'E!U9&EN9RX1``#R!2!' +M3E4@;&]N9R!F:6QE;F%M97,L$`!3;&EN:R`1`*%A;F0@`*935E(T +M($%30TE)%``"8P`/,@`%84)I;F%R>2X`\P<@*&)I9RUE;F1I86X@;W(@;&ET +M=&QE$0`"^@#P'TE33SDV-C`@0T0M4D]-(&EM86=EFEP/@$Q:6]N1`!=8GII<#(6``1D`4TO3%I7'0"B;'IM82P@;'IID#`*4#`.<#]A)U2!S +M=')E86VU!>!S>7-T96TN("!4:&5R92P`D&YO(&1I-R86YD;VT@86-C97-S+GD`!I<` +MD&ES(&1EU`P"C!`![``'.`!!VFP0` +MT082$N("!)9B!Y;W4@9&]N)^P!`+8`\0)I8VET +M;'D@:6YV;VME(&$@<.L`('5L60B@96%T=7)E("AS=2\!&7,<`A!AZ0`'+0`$ +M10<#(@("F0%P*2P@:70@=W``X"!G970@<'5L;&5D(&ENI`0W($EN;@`W+"!I +MG@`!40$#FP`B96[)`07L#$7`U`-%A=&5V +M97(@8FQO8VMS\```[@2X'<70@82!T:6U7`W%O8!(71O(@`%H0!A="!O;F-EA0`A3VZ0`QMEPP`"Y`(R<')O.@$! +MA0%18W1L>2W,``"."5)U='!U=.\"`&`$\0-O8FIE8W0M2!B=69F97(@)`@`90`$<@&%82!S;V-K +M970^`TEW:7-HN@3`P"`,D*`2L`,VEN(">D``,P``*,! +M!H`%,7=A;H@`$'0V!`5%`0!@```:!!!TC@7,N +M"E)%041-1;L&!^@&X2!B=6YD;&4N"@I1=65S^@*@/R`@27-S=65S/U(`URH@ +M:'1T<#HO+W=W=RX@!S!O3``!(`1!HN`*#9F]R(&]N9V]8!Q@@9`!P9&5V +M96QO<#P%)BP@_`Y`9&]C=10``:P(`3<,`'$``#H`(6YK70$`70`&8N9V]O9VQE+F-O;2]P+VH`$2\Z`"!S+VD``),``6<` +M47-U8FUI9P!P96YH86YC9;L``#8"!C@`@RP@<&QE87-E+```.P``!`,`2PB!$!G0&";8"(FENU@0`I`H`ZP4$O0+P`DY%5U,@+2!H:6=H +M;&EG:'1S7`8PM```Z#S`@*B"3``!. +M`/``+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C_P```@`0+:("`)\`!*@``-D. +M"*($$BP:#@#7"P!9"Q!YR@4!]@$C97*N`05P`"1I;F0`@2YH+FEN"@DM]`<` +MYA,22XS]!0P86EL[P0R92`B:P,%JP`!)``4(@L+62!C;&%S1``!'PE& +M;F%L``'?`5P#R*71H92!A=71H;W)S('=I=&@@86YY('%U97-T +M:6]N'2(`#%P=70I`/D#(F-M86ME +M(B!B=6EL9"!T;V]L30`"5@$&-0$!*0$Q(&EN3`$/;0$!,&%R91`"$F3:`35E +M"B>\`!,GK0`#9P$`DP``3@#U`2YA;2P@86-L;V-A;"YM-"SA`$!E+F%C_P`` +M`@`2+50`)'1OJ```(`$P9&ES7P(0=4$!LBP@;VYL>2!N965D?``Q;6%I]@$C +M97)<`05P`"1I;F0`\@,N:"YI;@H)+2!T96UP;&%T97-G`!%B-`(!9@$39;4` +M8`H*1W5I9/,`DB!$;V-U;65N=($!`,4!,F%L;'4``/,!]0H@'!L@P(#+P,`0@$"(0"#('!R;V=R86TS`$]C<&EO-``+ +M`"(`##4`+V%T-``,*&%T,P`'K0/P!#,@9VEV97,@86X@;W9E2!A``"/`&<@)V1O8R>]!;!I;@IA(&YU;6)E2QN``5H`S!U=&^3!@#_`A!YP0(P96-TF0,19-4``QP"!<(&$&8L +M``&W!E$J($=.574!`KH!)B`HN0$`&@!!;&]N9U4"8FYA;65S+!``4VQI;FL@ +M$0``8P!A`@@;W#+`\!A;"!2;V-KB,` +M`!DT%``)"`$```I58W)E873/``%U!`\&`0("J@,#OP,"O`(/'P,8,")R9?X( +M46-T960B1P,"3P#$+"!W:&EC:"!W:6QLB@`!5@`%R@%A(&5X8V5P0`4`N04$ +M:0+1('1H870@U`P#P +M!`![``.?`0![``&'"0&C``)*#`,*`P`X"`"R``$>`P"F!`(,`B$@8C<)`&H( +M,6%B;``&`(P*`0P``2P+`@0!`&@``CL`0F5A8V@]`2%V97,#$WE#`%!I;F1E +M<*H`)6YT(@$`&`D`#P\08T(%$F]L#08U"E0@5VEK:5(,,&EN9\D`,&AO=U$/ +M`;,#%V26"@(J`2%/;C\(`/<,`F`&`P,!`_@``8@)4&%L=V%Y1@$`W0$J962* +M"`)'`'!))W9E(&%T+0T`C`<`P0^0:6YI;6EZ92!S#@T28U((07!O;&R4#5$N +M("!)9O4(4&1O;B=TJ`"097AP;&EC:71LV0EB=F]K92!A^@\18W\*,69E830+ +M,"AS=2\!!?L*`*D`("!A00`!)Q`"+0`(S0`4;_D(<"DL(&ET('=P`'$@9V5T +M('!UG`T0:7H+1R`@26YN`#``%1`0.;`")E;LD!!RT``#X`"W$`*&1E +M$0`#Q@(1+/```H```(T.`)8!`!8!`$``(&%G`PX"4`.18V]R0`P&@`A!MV`$32X'<70@82!T:6U7`W%O +M8!(71O(@`%2@!2="!O;F-\$B)/ +M;AP."\,``N0",G!R;SH!`84!46-T;'DMS`"2960@;W5T<'5T[P(`8`3Q`V]B +M:F5C="US='EL92!A<'!R;\@#`$,2`OH`X'1O(&AA=F4@;75L=&EP)0``(040 +M=A(#0')E86VY"`#^#15NG@`3(!40`&H0``H!`#T%@VX@:71S(")`Y0`2(KT$ +M$7,P#@)C!08!`6!I='-E;&93`0!]!!`O=@1@=&5N('5S;P8`-PP!<@$R9G5N +M6!($DP$!=08`,@`U(&%NI``"(Q-0;'D@9G)@``S0*%82!S;V-K970^`TEW:7-HN@0!)@\#60\`#B)A;N@"`*4'!C0*$"QC`$!D97-PWP``;`0!Y`,`7,N"B05 +M$6:X#01Q%K0@8G5N9&QE+@H*41$6H#\@($ES7,@<')O9'5C97,@8V]R6]U('1O(&AA=F4@;75L=&EP)0`#J0!P`/,-("!B +M!E +M('-O;64@=71I;&ET>3X`!8P`,"!T;WP!\0-V:61E(&5A2!D8737`%9UX`0!V``##`!%EW@(!O@`%RP$` +MTP`#HP%#+B`@2:0!(6%NB``2=%T``38"`5L#`!\!`#L!061I"!I;G1E&%)`$!S.B!3,@-4`0-)`#!C;VY#`O`".B`@5F%R:6]UP`` +M7P%Q875T:&]R<\`%`1\&`?("`DT'$`H5"%!T;W`M;`P$`W8%`#`'`4$`$&DD +M!0FV`B)I;O@$(FEOX08$O0+P`DY%5U,@+2!H:6=H;&EG:'1S7`8P'2(`#!P=71>`C`@(F,T!A$B)`,`J@2!N965D?``Q +M;6%I]@$C97*N`05P`"1I;F0`@2YH+FEN"@DM]`=2;&%T97-G`!%B-`(#<@$" +MM0!@"@I'=6ED\P`H($14!@32`0)U``#S`8`@PH"MP(A960N +M"P!;!!!SU`80;A$,`-8"`),``'4``!<"`/D$`7$``7$*")<``9P)(RXS30`` +M[P0R92`B:P,%JP`!)``4(@L+62!C;&%S1``!'PE&;F%L=H+`#L'`2,)@&%U=&]M871I_P(0><$",&5C=)D#$60Y"0,< +M`@5X"1!F+``!MP91*B!'3E5U`0(U`B8@*`0+`!H`06QO;F=5`@"M"R)S+!`` +M``4+$R`1``!C`%)S<&%RB,``!DT%``)"`$```H"G!`% +M.@$`=00/!@$"`J\!`[\#`KP"#Q\#&#`BP`!APD!*Q4"2@P`31$B:7*"$1!I>0<#[A("#`(A +M(&(W"0","C%A8FP`!@","@$,`!!A#`$"U!``:``".P!"96%C:#T!(79E4,`4&EN9&5PJ@`E;G0B`0!$#0`/#Q!C0@42;VP-!K`+5"!7:6MI4@P##!,P +M:&]W40\!LP,09*T!`]H``O<3(4]N/P@`]PP"8`8`\PX`4`8#S0`!<``"@!<" +MQ`4J962*"`)'`#!))W8-&``A%0",!S!T;R`A$#!M:7I2%P"U"`)2"$%P;VQL +M-A(&Y!1!9&]N)^P!D&5X<&QI8VET;-D)8G9O:V4@8?H/$6-_"@/.$2`@*-(0 +M`'4,"!P"$&&R`0$G$`(M``C-`!1OP,1 +M<#4`8F%T979EFUA+"!L>FEP+"!A +M;F0@>'HC```9-!0`\`P*5&AE(&QI8G)A"!I;G1E'1E;DT!L7,@*&9O$E33SDV-C`3`%HW+5II<#D`-EA!4A$`0PI7 +M:&4#`@#D`00%`A$L_`%A2!S=')E86WM`>!S>7-T96TN("!4:&5R92P`D&YO +M(&1I4,`4&EN9&5PJ@`B;G1_`!!R.P0`!`"4=&EC;&5S(&]N@0$$ +MK@#P`%=I:VD@97AP;&%I;FEN9XD`,&AO=_@``O4``(X$`RP``BH!(4]NJ@`< +M+`,!`]D"`G``0&QW87E&`0#=`?(!960@875T;VUA=&EC86QL>4<`L$DG=F4@ +M871T96UPQ`/@=&\@;6EN:6UI>F4@2!I;G9O:V4@82!PZP`@=6PW!"!E85D" +M0"`HD`!RT`!^\%`(`!`ID!<"DL(&ET('=P`.`@9V5T('!U +M;&QE9"!I;J0$-R!);FX`-RP@:9X``5$!`YL`(F5NR0$'+0``?``+<0`H9&41 +M``.J`!$L\``"@``B;F6.`@`6`0!``&)A9V%I;G-'`J!C;W)R97-P;VYD)P0( +M20`-6@`">P,Q:65SPP`!;P.A86QS;R!R961U8[D%,&4@`(&5N=FER;V[7`C%S('=N`@&@`A!MV`$36QE(&%P<')OR`,`PP<"^@#@=&\@:&%V92!M=6QT:7`E +M```A!1!V$@,`!04`N0A5(&]P96Z>`%`@(&)S9",'(75SO`$`/06#;B!I=',@ +M(D#E`!(BO01&P`28D(``"P$`-$``#8!(71OFPDP9&%TUP!6=7)C93HN +M`0+("0#"`!)A[`(`PPD!*P`S:6X@)P$`^`(@863\`@!B`!%A_`@$J@$`>08A +M;W7W!%%F:7)S=)("`*8!(&$@0P41;S$*`/8`%BYT``/9`P*G`0":"0*<`0&% +M``:X`0!V``##``"\`Q)EDP`"3P7,N"E)%041-1;L&!^@&X2!B=6YD +M;&4N"@I1=65S^@*@/R`@27-S=65S/U(`URH@:'1T<#HO+W=W=RX@!S!O3 +M``!(`1!HN`*#9F]R(&]N9V]8!Q@@9`!P9&5V96QO<#P%<2P@:6YC;'6]!4!D +M;V-U%``!K`@!-PP`<0``.@`A;FM=`0!=``9S`%`@;6%I;`<"0FQI%EB!$!G&%)`$!S.B!3,@-4`0-)`#!C;VY#`O`".B`@5F%R +M:6]UP``7P%V875T:&]RT/4'1O<"UL#`0#Q0P`,`0& +M";8"(FENU@0`=`P`ZP40<],-\`4@*B!.15=3("T@:&EG:&QI9VAT'2(`")P==8-(")C-`81(B0#`#@,*6]L30`"5@$&ZP,!*0$`%@D`C@$/ +M;0$!`+`,('5SW0H`V@$T90HGL``C92>M``-G`0"3``!.`/``+F%M+"!A8VQO +M8V%L+FTT"0T#[0`P+F%C%P$``@`0+:("`)\`!*@``-D."*($$BP:#@#7"P)\ +M`#%M86GV`2-EPH"MP(`A1(A86R) +M!T!S97%UZ@@0=&%R +M+C54`0CQ!`4^$A%S8P0Q<&]PY0\#G`$$>P`(2PE`:&%R9!8,`3`&!%L!`4<` +M`(X!86UO9&5R;H\``.@!`+P'<"!V87)I86Y("0`B##!M86[X"T%P86=E.``` +M,0X`SA0"^@$`G@`!WP%7)V1O8R>]!9!I;@IA(&YU;6+R#!=FD0<$.P''"@I9 +M;W4@`""(&EN'!L86EN3`1!F+``P'1E;J+``-J`0`9`]$J(%!/ +M4TE8('5S=&%R6P`"$``P<&%X20-Q97)C:&%N9WX!-VUA="$`L&]C=&5T+6]R +M:65N`0,`8`(!'@"A4U92-"!!4T-)270"`10``E,`#S(`!6%":6YA\!`DD`-%I) +M4%8#!$``D'5N8V]M<')E<],&<&]R(")D969^!A`BJ0($&```H00C:655`0## +M`0"B`85"4T0@)V%R)U(``?@`$2?]`Q`GNP($/0%:-RU::7`F`-A-:6-R;W-O +M9G0@0T%"+``Q3$A!"@,Z3%I(,@`Z4D%2$0`86!$``=4#!;@"`'@#"*\"8&AA +M;F1L9;L"$'FW`P"V!`:X`C!B969*`W!E=F%L=6%TR@(`(``#F0,"SP(0=?8% +M$&]Q`@"V`@)#`@$*`!$@@P&B4E!-('=R87!P94X"16=Z:7`^`3%I;VX8`5UB +M>FEP,A8`!'P!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9-!0`"0@!E6-A +M;B!C0`&@`0`#@Q397-I9VXE#!)EO@(`0`0!,`0X;F5WM0,`\`0`>P`#GP$`>P`! +MAPD!HP`"2@P#"@,`.`@`L@`!'@,`I@0"#`(A(&(W"7%R96%D86)L``8`C`H! +M#``!+`L"!`$`:``".P!"96%C:#T!(79E4,`4&EN9&5PJ@`E;G0B`0`8 +M"5!AD` +M!RT`!"T'`,\*%&_Y"'`I+"!I="!W<`!Q(&=E="!P=9P-(&ENI`0W($EN;@`W +M+"!IG@`(FP`B96[)`02UV```S#`#W"!%IAP8`A`!P96YV:7)O +M;M<",7,@=Y`#`:`"$&W8`1-R6@,%,`(`6P`"?P`1>7L#$7`U`-%A=&5V97(@ +M8FQO8VMS\```[@@``S0*%82!S;V-K970^`TEW:7-H +MN@0!)@\#60\`4X.475S92`B(0$`6@@@+")0"+$L +M(&-A<&%B:6QI=/8"!`,!!?$``O,/`;<$"/8%`9P" +M`,D*`2L`,VEN("#U%F:7)S=)("`*8!(&$@ +M0P41;UD1`/8`%BYT``/9`P*G`0"_``*<`0&%``:X`0!V``##``"\`Q)EDP`" +M,0\@;'ED`0#,``"C`0:`!3%W86Y_!1)T'0\!-@(!6P,!&@00=(X'(7-K+`,0 +MA$)P`$`B0`P;6%K>0"0:7,@97-P96-I;@0!T`$"J@$` +M.@@P.B`BDPH!#A$)V@T3(KD"`-X.(F%NZ`(`I0<&-`H0+&,`0&1EF-%#A)B!P`2>`<``$D!`)()`"<`02H@97@;$T!S.B!3 +M,@-42!A;F0@861D(&ET('1O(&$@=&%R(&%R8VAI=F4@=VET:&]U=`H@ +M("!F:7)S="!W2!F8<`\`5S;V-K970N("!)9B!Y;W4@=V%N=$0`$G1=`!(O/0``8``P +M:65S,P!09&ES:RQ.`/`,0#Q+6ES(&5S<&5C:6%L;'D@96%S>2X*"B`J($YO=&4Z(")P87@@ +M:6YT97)C:&%N9V4@9F]R;6%T(B!I7,N"E)%041-15``1"!L:6)M +M`=%B=6YD;&4N"@I1=65SK@"@/R`@27-S=65S/U(`UBH@:'1T<#HO+W=W=RXX +M`$`N;W)GDP``2`$Q:&]MIP"`(&]N9V]I;F8$(&YDT`(Q9G5L+P(&10!1+VUI;FF%`1%A +MXP%186-T('-@`+`@9&5M;VYS=')A=+M``,D +M!`"3``!.`/4!+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_```"`!`MH@(`GP`$ +MJ``,H@2R+"!O;FQY(&YE961\`#%M86GV`2-E7-T96TZ<`<"N`1U+C$@97AP;(,"`R\#`$(!`B$`!)H#`S,``(@$#S0` +M"P`B``PU`"]A=#0`#"AA=#,`!@$&@"XS(&=I=F5SWP:`;W9EP$2+8($-7,N-:H(`)X%$67[`P#R +M`(!M871S('-U<'\(!&,"!98!`$P```H"D"XU+"!M=')E90D``&\`7G1A``&I`5"`"X!!,B?P(R+F@BJ0"` +M:&4*`D09BP` +M`;<&42H@1TY5=0$"-0(F("@$"P`:`$%L;VYG50(`K0LB+ +M``-J`0`9`]$J(%!/4TE8('5S=&%R6P`"$``/B@P#!R$`P&]C=&5T+6]R:65N +M=!<$,7!I;QX`IE-64C0@05-#24D4``)3``\R``5A0FEN87)Y+@#`("AB:6FEP,A8`!'P! +M32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9-!0`"0@!```*56-R96%TSP`! +M=00/!@$"`JH#`[\#`KP"#Q\#&#`B&-E<$`%`+D%!&D"42!T:&%T0PXQ:7)E40`!`1`! +MR@(@("A3"@$T!`"$`0-$!`#T`V`L(&5T8RGO"P+Z`P"I`@!H$0*-``&&`0+: +M``^6`P4!R`-A(FYE=V,BFP,!,P`G?P(-F5A;;4%`A$+<"X@(%1H97(T$2`@;M82,7)E8S`1`]\(`),$02!I;BVW +M#X(@;6]D:69I8^4,\@%OP`!APD!HP`"2@P` +M31$B:7*"$1!I>0<#[A("#`(A(&(W"0","C%A8FP`!@","@$,``$L"P+4$`!H +M``([`$)E86-H/0$A=F5S`Q-Y0P!0:6YD97"J`"5N="(!`$0-``\/$&-"!1)O +M;`T&-0I4(%=I:VE2#`,,$S!H;W?X``&S`Q!DK0$#V@`"*@$A3VX_"`#W#`)@ +M!@#S#@!0!@/-``%P`%-L=V%YF4@0`P&@`A!MV`$3!<1<_`` +M`.X',2!I=&0!,EEO=><3`<0-0&)A8VNO$S%F6QE(&%P<')OR`,`@0L"^@!0=&\@:&$Y%D!U +M;'1IPQ,$J0`"`00`N0A5(&]P96Z>`!0@]`\A=7-U!Q!IF@%S(&ETFEP,A8`!"8`32],6E<=`/D#;'IM82P@;'II +M<"P@86YD('AZ(P#!"DYO=&5S(&%B;W5TE`!R;&EB=$`\"YT96-T=7)E +M.@H*("H@5&AI48!`-T!\@%E +M9"!A=71O;6%T:6-A;&QY1P"P22=V92!A='1E;7#7`>!T;R!M:6YI;6EZ92!S +M="L`L"!L:6YK('!O;&QUN`'A+B`@268@>6]U(&1O;B?L`0"V`/$":6-I=&QY +M(&EN=F]K92!A('#K`(!U;&%R(&9E85D"0"`HD`!RT`!P8# +M`(`!`ID!<"DL(&ET('=P`/``(&=E="!P=6QL960@:6XN/@`G26YN`# +M``%1`0.;`")E;LD!!RT``#X`"W$`*&1E$0`#Q@(1+/```H``(FYEC@(`%@$` +M0`!B86=A:6YS1P*@8V]R7L#$7`U`-%A +M=&5V97(@8FQO8VMS\``0:$,$(6ETH0!!66]U717`F$@82!T:6U7`W%O +M`+$@(&)S9'1A3X`!8P``0`"\05R;W9I +M9&4@96%S>2UT;RUUX`0!V``##``"\`Q)E +MDP`"3P0"0:7,@97-P96-I;@0!T`$"J@$` +M.@CS`SH@(G!A>"!I;G1E`<``$D!`)()`"<`4"H@97AA20!` +M8$(&YDT`(Q9G5L+P(&10`0 +M+T,*`84!$6&>"E%A8W0@"`"X!!,B!0XR+F@BJ0`R +M:&4*7PP0(+`)`/H``!0`!.D&`W((`G\"-&UO5$P`P%&!E+``-J`0`9`[$J +M(%!/4TE8('5S=+`1!!``#XH,`P%\``(Q`%9O8W1E=*\4`&`"`1X`H5-64C0@ +M05-#24ET`@$4``\R``L00FT1$7DN`+$@*&)I9RUE;F1I8=018VQI='1L91$` +M`OH`\0))4T\Y-C8P($-$+5)/32!I;;<"$"@X#C`@;W#+`\!A;"!2;V-K[ +M`@0]`5HW+5II<"8`V$UI8W)OQ=4 +M`)H`-6QZ-*@!`.47"0@!```*`IP0!4L!`'4$#P8!`@*O`0._`P*\`@\?`Q@P +M(G)EH`T`$!81(D<#`D\`PBP@=VAI8V@@=VEL;.L8`'`(`,,/`U\!0',@97@M +M%``"`@"Y!02)$0(+%P-:%P%1``7I$C!S("A3"@$T!`"$`0,S!`#T`V`L(&5T +M8RGO"P+Z`P"I`@!M``*-``&;`0+:``_(`PIA(FYE=V,BFP,!,P`G4P`T&-P:6\N-2P@;71R964)``!O`/(*=&%R+C4@<')O=FED92!D971A +M:6QE9"!I;E(`D&EO;B!A8F]U=$T`XW-E"B`@('!O<'5L87(@F``2("D`\PIS +M+"!I;F-L=61I;F<@:&%R9"UT;RUF:6YD5``2FEP/@$Q:6]N,`!=8GII<#(6``1\`4TO3%I7'0"B;'IM82P@;'II +M&-E<$`%`+D%!&D"L"!T:&%T(')E<75IE@4G87C*`E(@*&9O?P(-F5A +M;;4%X'-Y`3AN97>U`P#P!`![``-S!`![``&'"0&C`%0@;VYL +M>0H#`#@(`+(``1X#`*8$`@P"(2!B-PEQ4,`4&EN9&5PJ@`E;G0B`0`8"5!A48!`-T!*F5DB@@"1P"P22=V92!A +M='1E;7",!^!T;R!M:6YI;6EZ92!S=+4(`E((4'!O;&QU(@=1+B`@26;U"%!D +M;VXG=*@``+8`4&EC:71LV0F!=F]K92!A('#K``%_"C%F96$T"S`H``%1`0.;`")E;LD!!RT``'P`"W$`*&1E$0`#Q@(1+/`` +M`H``(FYEC@(`%@$`0`!B86=A:6YS1P*18V]R0`P&@`A!MV`$38!(71O(@`%H0!A="!O;F-EA0`A3VZ0`QMEPP`"Y`(R +M<')O.@$!A0%18W1L>2W,``"."5)U='!U=.\"`&`$\0-O8FIE8W0M7,"!8P``#\`!)4.0&5AP"`,D*`2L`,VEN("#U%F:7)S=)("`*8!(&$@0P41;U`'`/8`%BYT``/9`P*G`0"_``*< +M`0&%``:X`0!V``##``"\`Q)EDP`",0\@;'ED`0#,``"C`0:`!3%W86Y_!1)T +M'0\!-@(!6P,`8PP`,P!!9&ES:RP#`+$0$'*?!)EN=F5N:65N8V7``0")`#!M +M86MY`)!I0#`',*T2!S87ES+@I214%$3442 +M!@<4!]%B=6YD;&4N"@I1=65S^@*@/R`@27-S=65S/U(`UBH@:'1T<#HO+W=W +M=RXX`$`N;W)GDP``2`$0:+@"$&:Q#S-N9V]8!Q<@3`>`(&1E=F5L;W`\!0@9 +M$02Z$0&L"`$W#`!Q```Z`"%N:UT!`%T`!G,`4"!M86EL!P(P;&ESOQ`!G0`0 +M5)D!`.41`.%E8$(&YDT`(Q9G5L+P(&10`0+T,*`84!$6&>"C1A8W1[$W!D96UO;G-T +M.14@;F<^``"`!094`@-)`#!C;VY#`F$Z("!687+N$V!I=&5M$0(8`&!C;VYF:6>R%A4M#``"1`"UM`Q$SM@L`$!20(&]V97)V:65W\P(`JP`% +MP`L`<04P=VAOD0(4*J0*A5]R96%D+C,L$``!^`@-$0!17V1I4$`(&EN^``(M@)P +M:6YF;W)M8:D!,"!F:34!`'P`\`0J($Y%5U,@+2!H:6=H;&EG:'1SW``P@`K1#3U!924Y'("T@=U$!8F-A;B!D;Y\`,W1H:2D`\@))3E-4 +M04Q,("T@:6YS=&%L;'4```T`(7)U*@(#*0"!4D5!1$U%("T\``&5``*3`+!C +M;VYF:6=UM``,D!`"3``!. +M`/4!+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_```"`!(M5``D=&^H``RB!+(L +M(&]N;'D@;F5E9'P`,6UA:?8!(V5R7`$%<``D:6YD`/(#+F@N:6X*"2T@=&5M +M<&QA=&5S9P`18C0"`68!$V6U`&`*"D=U:63S`%`@1&]C=9D%`H$!`,4!,F%L +M;'4``;`:`;W9E]!;!I;@IA +M(&YU;6)E"`"X!!,BO0(R+F@BJ0"`:&4*2R"```[!P$C"4!A=71ODP8`_P(0 +M><$",&5C=)D#$635``,<`@5X"1!F+``!MP91*B!'3E5U`0(U`B(@**L)`+D! +M`!H`06QO;F=0!F)N86UEB,``!DT%``)"`$```I58W)E873/``%U!`\& +M`0("J@,#OP,"O`(/'P,8,")R9:`-46-T960B1P,"3P#$+"!W:&EC:"!W:6QL +MB@`!5@`%R@%A(&5X8V5P0`4`N04$:0)1('1H871##C%I`3AN97>U`P#P!`![``.?`0![``&'"0&C``)*#`!-$2)IF4@``%1`0.; +M`")E;LD!!RT``'P`"W$`*&1E$0`#Q@(1+/```H```(T.`)8!`!8!`$``(&%G +M`PX1=/$)D6-OP,1<#4`T6%T979EP"`,D*`2L`,VEN("#U%F:7)S=)("`*8!$6%P$A%O\0T`]@`6+G0` +M`]D#`J +M#@#G&`Y6#A`L8P!`9&5S<*(``&P$`>0#`',*2!I;G9O:V4@82!P87)T:6-U;&%R(&9E +M871U!E('-O;64@=71I;&ET>3X`!8P``+$!\09P2!D8737`%9UP"`&$# +M`2L`,VEN("7,N"E)%041-15``1"!L:6)M +M`=%B=6YD;&4N"@I1=65S^@*@/R`@27-S=65S/U(`UBH@:'1T<#HO+W=W=RXX +M`$`N;W)GDP``2`$0:+@"L&9OF-A="P@8@<`$G@'``!)`4!S=6-H +M)P!0*B!E>&%)`$!S.B!3,@-40&";8"(FEN8PL`<0L`ZP4$O0+P +M`DY%5U,@+2!H:6=H;&EG:'1S7`8P'2(`#!P=71>`C`@(F,T!A$B)`-I +M9"!T;V]L30`"5@$&ZP,`E``!%@D`C@$/;0$!`&8(('5SW0H`V@$T90HGL``C +M92>M``-G`0"3``!.`/``+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C_P```@`0 +M+:("`)\`!*@``&H+"*($82P@;VYL>=<+`GP`,6UA:?8!(V5RK@$%<``D:6YD +M`($N:"YI;@H)+?0'4FQA=&5S9P`18C0"`W(!`K4`8`H*1W5I9/,`*"!$5`8$ +MT@$"=0`!MP%P=H+`#L'`2,)"=H1`,$",&5C +M=)D#$62V#P,<`@5X"1!F!A(!MP91*B!'3E5U`0(U`B8@*`0+`!H`(VQOO`4` +MK0LB+``-J`0`9`[$J(%!/4TE8('5S=+`1!!``#XH,`P%\ +M``(Q`+!O8W1E="UO`@@;W#+`\!A;"!2;V-K[`@0]`5HW+5II<"8`V$UI +M8W)OFEP/@$@:6]/$WTJ +M(&)Z:7`R%@`$?`%-+TQ:5QT`HFQZ;6$L(&QZ:7`3`R]X>B,``!DT%``)"`$` +M``H"G!`%.@$`=00/!@$"`J\!`[\#`KP"#Q\#&#`BD6$W,*%P!5"`2`!"EIP`!APD!*Q4"2@P#"@,`.`@`W@`4=.X2`@P"(2!B +M-PD`C`H!CQ@#N!0!#``080P!`M00`&@``CL`$66<%@`]`2%V97,#$WE#`%!I +M;F1E<*H`)6YT(@$`1`U087)T:6-"!1)O;`T&L`M4(%=I:VE2#`,,$S!H;W=1 +M#P&S`Q!DK0$#V@`"]Q,%-!@$_`0`\PX`4`8#S0`!<``"@!<"Q`4/9!K_____ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_SI0;F<@;&DN$0``\SUN:R!N86UE'1E;F1E9"!T87(@9F]R;6%T("AI;F-L=61I;F<@04-, +M,P!A3VQD(%8W)P"!87)C:&EV97-+`+=03U-)6"!U"=M=')E92<]`5HW+5II<"8`V$UI8W)O2!A;'-O(&1E=&5C='--`&!H86YD +M;&4,`'!Y(&]F('1HW`'P!VQL;W=I;F<@8F5F;W)E(&5V86QU8702```@``,O +M`A$ZU`!@=75E;F-O<0(!CP(!%``!"@`1((,!HE)032!WFEP +M/@$Q:6]N,`!=8GII<#(6``1D`4TO3%I7'0"B;'IM82P@;'IIP`!S@`0 +M=IL$`-$&$G.C`%0@;VYL>0H#0&UE;G2R``$>`P"F!`(K`#`@8F5``'%R96%D +M86)L``9!=W)I=`P`$&$,`0($`0!H``([`$)E86-H/0$A=F5S`Q-Y0P!0:6YD +M97"J`")N='\`$'([!``$`#!T:6-"!21O;H$!!*X`\`!7:6MI(&5X<&QA:6YI +M;F>)`#!H;W?X``&S`Q!DE@4#+``"*@$A3VZJ`!PL`P$`!`0R;6%T<`!`;'=A +M>48!`-T!\@%E9"!A=71O;6%T:6-A;&QY1P"P22=V92!A='1E;7",!^!T;R!M +M:6YI;6EZ92!S="L`L"!L:6YK('!O;&QUN`'A+B`@268@>6]U(&1O;B?L`0"V +M`/$":6-I=&QY(&EN=F]K92!A('#K`"!U;%D(H&5A='5R92`HD`!RT`!$4'`R("`ID!<"DL(&ET('=P`.`@9V5T('!U;&QE9"!I;J0$-R!) +M;FX`-RP@:9X``5$!`YL`(F5NR0$'+0``?``+<0`H9&41``.J`!$L\``"@``B +M;F6.`@`6`0!``'%A9V%I;G-TSP&18V]RP,Q:65S +MPP`!;P,!;P=16QE +M(&%P<')OR`,`R0@"^@#@=&\@:&%V92!M=6QT:7`E``-3!`(!!`#\"E4@;W!E +M;IX`4"`@8G-D(P2!F)M96UO7,"!8P``0`"\05R;W9I +M9&4@96%S>2UT;RUU0#`',* +MT"!S87ES+@I214%$346[!@?H!N$@8G5N9&QE+@H*475E<_H"H#\@($ES7!1`GH@1`9W)A;18"&%)`$!S.B!3,@-4 +M`0-)`#!C;VY#`O`".B`@5F%R:6]UP``7P%Q875T:&]R<\`%`1\&`?("`-(1$B[M +M#U!T;W`M;`P$`\4,`#`'`4$`$&GD!@FV`B)I;M8$`*0*`.L%!+T"\`).15=3 +M("T@:&EG:&QI9VATPH"MP(`318A86R)!T!S97%UZ@@0=&%R+C54`0CQ!`4^$A%SU@TQ<&]PY0\# +MG`$$>P`(2PE`:&%R9!8,`3`&`J@!`X42`(X!86UO9&5R;H\``.@!`+P'<"!V +M87)I86Y("0`B##!M86[X"Q%PK1] +M!;!I;@IA(&YU;6)E"`"X!!,BXP`R+F@BJ0`R:&4*7PP0(+`)`/H``!0`!.D&`W((`G\" +M$&T:%P/[`$(N("!0B@FR;&5T('5S"FMN;W<0`0&9!F!E`D09@82`;<&`H<8!JH+"``:`/@5#"`6`1````4+#V0:________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________________________________________________]H4"`J(&5X +M1!$``/$,86UP;&5S+VUI;FET87(Z(&$@8V]M<&%C="!S&P#T3R!D96UO;G-T +MV`'!I;F9O +M6]U(&-A;B!D;Y\`,W1H:2D`\@)) +M3E-404Q,("T@:6YS=&%L;'4```T`,')U8X$``RD`@%)%041-12`M%`$1`?$#+@H*66]U('-H +M;W5L9"!A;'-O(@(!3``Q8V]P=@8R8V]M6P%#:6X@(KT",BYH(JD`@&AE"G-O +M=7)C+P`19'4!`!0`!.D&`YH#`G\"-&UO68!,&5C=)D#$635``,<`@7"!A!F+``!MP91*B!' +M3E5U`0*Z`28@*+D!`!H`06QO;F=5`F)N86UE'1E;J+``-J`0`9`]$J(%!/4TE8('5S=&%R6P`"$``P<&%X20,B97)9!P-X`@FEP,A8`!'P!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9-!0`"0@! +M```*56-R96%TSP`!=00/!@$"`JH#`[\#`KP"#Q\#&#`B&-E<$`%`+D%!&D"T2!T:&%T +M(')E<75IP`# +MGP$`>P`!APD!HP`"2@P#"@,`.`@`L@`!'@,`"0$"#`(A(&(W"0!J"#%A8FP` +M!@","@$,``$L"P($`0!H``([`$)E86-H/0$A=F5S`Q-Y0P!0:6YD97"J`"5N +M="(!`!@)``\/$&-"!1)O;`T&-0I4(%=I:VE2##!I;F?)`&-H;W<@=&_U``>6 +M"@(J`2%/;C\(`/<,`F`&`P,!`_@``8@)4&%L=V%Y1@$`W0$J962*"`)'`'!) +M)W9E(&%T+0T`C`<`P0^0:6YI;6EZ92!S#@T28U((07!O;&R4#5$N("!)9O4( +M4&1O;B=TJ`"097AP;&EC:71LV0EB=F]K92!A^@\18W\*,69E830+,"AS=2\! +M!?L*`*D`("!A00`1P,1<#4`T6%T979EP"`,D*`2L`,VEN("#U%F:7)S=)("`*8!$6%P$A%O61$`]@`6+G0``]D#`J60!`,P``*,!!H`%,7=A +M;G\%$G0=#P-%`0!@```:!!!TC@0#`',*F-%#A)B!P`2>`<``$D!`)()`"<`02H@97@$ +M&D!S.B!3,@-48$(&YDT`(Q9G5L+P(&10`/ +M9!K_________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_________V10=&EM90HH$0``\!0@("!O2UB;&]C:V5D(&]U +M='!U="X*"B`J(%1H92!O8FIE8W0M`@#1```V`:!T +M;R!A;GD@9&%TUP!6=7)C93HN`6!C`@&^``7+ +M`0#3``.C`4,N("!)I`$A86Z(`!)T70`!-@(!6P,`'P$`.P%!9&ES:RP#`\0! +MMF-O;G9E;FEE;F-E3`(P('1OB0`P;6%K>0#1:7,@97-P96-I86QL>=`!`JH! +M\P].;W1E.B`B<&%X(&EN=&5R8VAA;F=E(&9O7,N"E)%041-12X` +M1"!L:6)M`=%B=6YD;&4N"@I1=65S^@*@/R`@27-S=65S/U(`UBH@:'1T<#HO +M+W=W=RXX`$`N;W)GDP``:@00:+@"L&9O&%)`$!S.B!3,@-4`0-)`#!C;VY#`O`".B`@5F%R:6]U +MP``7P%Q875T:&]R<\`%`1\&`?("`DT'$`H5"%!T;W`M;`P$`W8%`#`'`4$` +M$&DD!0FV`B)I;O@$(FEOX08$O0+P`DY%5U,@+2!H:6=H;&EG:'1S7`8P'2(`#!P=71>`C`@(F,T!A$B)`,`J@2!N965D +M?``Q;6%I]@$C97*N`05P`"1I;F0`@2YH+FEN"@DM]`=2;&%T97-G`!%B-`(# +M<@$"M0!@"@I'=6ED\P`H($14!@32`0)U``#S`8`@PH"MP(A +M960N"P!;!!!SU`80;A$,`-8"`),``'4``!<"`/D$`7$``7$*")<``9P)(RXS +M30``[P0R92`B:P,%JP`!)``4(@L+62!C;&%S1``!'PE&;F%L=H+`#L'`2,)@&%U=&]M871I_P(0><$",&5C=)D#$60Y +M"0,<`@5X"1!F+``!MP91*B!'3E5U`0(U`B8@*`0+`!H`06QO;F=5`@"M"R)S +M+!````4+$R`1``!C`%)S<&%RB,``!DT%``)"`$```H" +MG!`%.@$`=00/!@$"`J\!`[\#`KP"#Q\#&#`BP`!APD!*Q4"2@P`31$B:7*"$1!I>0<#[A(" +M#`(A(&(W"0","C%A8FP`!@","@$,`!!A#`$"U!``:``".P!"96%C:#T!(79E +M4,`4&EN9&5PJ@`E;G0B`0!$#0`/#Q!C0@42;VP-!K`+5"!7:6MI4@P# +M#!,P:&]W40\!LP,09*T!`]H``O<3(4]N/P@`]PP"8`8`\PX`4`8#S0`!<``" +M@!<"Q`4J962*"`)'`'!))W9E(&%T(14`C`'!L:6-I=&S9"6)V;VME(&'Z#Q%C?PH#SA$@ +M("C2$`!U#`@<`A!AL@$!)Q`"+0`(S0`4;W,$<"DL(&ET('=P`%`@9V5T(-(2 +M`5T*`*0$-R!);FX`!287`9X``5$!`YL`(F5NR0$'+0``?``+<0`H9&41``.J +M`!$L6!$"@```C0X`E@$`%@$`0``P86=A\P\!7PJ18V]R7L#$7`U`&)A=&5V97)X%Q%S\```[@*B!F:6QEFEP(&-O;7!R +M97-S:6]N%0!=8GII<#(6``0F`$TO3%I7'0#_`VQZ;6$L(&QZ:7`L(&%N9"!X +M>B,``!DT%`#Q,@I4:&4@;&EB2!C86X@8W)E871E(&%R8VAI=F5S(&EN +M(&%N>2!O9B!T:&4@9F]L;&]W:6YG(&9O"!I;G1E'1E;DT!L7,@*&9O$E33SDV-C`3`%HW+5II<#D`-EA!4A$`0PI7:&4# +M`@#D`00%`A$L_`%AT!X'-Y +M`>-R86YD;VT@86-C97-S+GD`!I<`\@)I +M`35N97<7`@!2`#!A;F1[``'.`!1V6`,24,`4&EN9&5PJ@`B;G1_`!!R.P0`!``P=&EC\`0D;VZ!`02N +M`/``5VEK:2!E>'!L86EN:6YGR0`P:&]W^``"]0``C@0#+``"*@$A3VZJ`!PL +M`P$#V0("<`!`;'=A>48!`-T!\@%E9"!A=71O;6%T:6-A;&QY1P"P22=V92!A +M='1E;7#$`^!T;R!M:6YI;6EZ92!S="L`L"!L:6YK('!O;&QUN`'A+B`@268@ +M>6]U(&1O;B?L`0"V`/$":6-I=&QY(&EN=F]K92!A('#K`"!U;#<$(&5A60)` +M("AS=2\!&7,<`A!AZ0`'+0`'[P4`@`$"F0%P*2P@:70@=W``X"!G970@<'5L +M;&5D(&ENI`0W($EN;@`W+"!IG@`!40$#FP`B96[)`07L#$7`U`-%A=&5V97(@8FQO8VMS\``0:%<%(6ETH0!!66]U +M2X'<70@82!T:6U7 +M`W%O8!(71O(@`%H0!A="!O;F-E +MA0`A3VZ0`QMEPP`"Y`(R<')O.@$!A0%18W1L>2W,``!(!E)U='!U=.\"`&`$ +M\0-O8FIE8W0M2!F)M96UO +M?\`!8P``0`"\05R;W9I9&4@96%S>2UT;RUU8<``J,!!H`%,7=A;H@`$'0V!`5%`0!@ +M``'Z"0".!R%S:RP#`WX&N6-O;G9E;FEE;F-EP`$`B0`P;6%K>0"0:7,@97-P +M96-I;@0!T`$"J@$`.@@P.B`BDPH.NPH3(KD"(&QL/`$"Z`(`I0<`$0,"P040 +M+&,`0&1EH($',+!0$^`0!U```7`@#Y!`%Q``%Q"@B7```\"3-Y+C--``#O +M!#)E(")K`P6K``$D`!0B"PM9(&-L87-$``$?"49N86QSG0`2!Q(M@@0U"`"X!!,B!0XR+F@BJ0`R:&4* +M7PP0(+`)`/H``!0`!.D&`W((`G\"-&UO5$P"9!F!E2X`L2`H8FEG+65N9&EAU!%C;&ET=&QE$0`"QP`$ +M7Q:10T0M4D]-(&EMMP(0*#@.,"!O<,L#P&%L(%)O8VMR:61G9>\!`DD`#QX78P\+%P#036EC@`/`#;&EB +M2!A2XS30`"=`%U +M(G-T2!C;&%S1`"6:6YT97)N86QSG0!@2!E2QN``5H`W!U=&]M871I_P(0>68!,&5C=)D#$635``,<`E!O;&QO=Y,!$&8L +M`#!S.@K?!#%'3E5U`0(U`B8@*+D!`!H`06QO;F=5`F)N86UE`*%35E(T($%30TE) +M=`(!%``"4P`/,@`%84)I;F%R>2X`H"`H8FEG+65N9&GS!(-R(&QI='1L91$` +M`OH`\0))4T\Y-C8P($-$+5)/32!I;;<"@"AW:71H(&]P^@7`86P@4F]C:W)I +M9&=E10!B2F]L:65T*0$![P$"20`T6DE05@,$0`#`=6YC;VUP[`@0]`5HW+5II<"8`V$UI8W)O`,(KP)@:&%N9&QENP(0>;<#`+8$!K@",&)E9DH# +M<&5V86QU873*`@`@``.9`P+/`A!U]@40;W$"`+8"`D,"`0H`$2"#`:)24$T@ +M=W)A<'!E3@)%9WII<#X!,6EO;A@!76)Z:7`R%@`$?`%-+TQ:5QT`HFQZ;6$L +M(&QZ:7`3`R]X>B,``!DT%``)"`&58V%N(&-R96%TSP`!=00/!@$"`J\!`[\# +M`KP"#Q\#&,$B0`&@`2P:7,@9&5S:6=N962C"R)B +M9;X"`$`$`3`$.&YE=[4#`/`$`'L``Y\!`'L``8<)`:,``DH,`PH#`#@(`+(` +M`1X#`*8$`@P"(2!B-PEQ6"@(J`2%/;C\(`/<,`G@&`0(*(VYD +M^``!B`E086QW87E&`0#=`2IE9(H(`D<`<$DG=F4@870M#0",!]!T;R!M:6YI +M;6EZ92!S#@T28U((07!O;&R4#5$N("!)9O4(0&1O;B?6!P&V`%!I8VET;-D) +M@79O:V4@82!PZP`!?PHQ9F5A-`LP*'-U+P$%^PH`J0`@(&'I``0 +M`P&@`A!MV`$32X'<70@82!T:6U7`W%O8!(71O +M(@`%2@!A="!O;F-EA0`B3VX<#@O#``+D`C)P@``S0*%82!S;V-K970^`TEW:7-HN@0!)@\#60\` +M4X.``P1$2(A`0!:""`L(E`(L2P@8V%P86)I;&ET +M]@($`P$%\0`"\P\!MP0(]@4!EP&`(&EN9&EV:61L#@/;"`"%``(5!@!"``!R +M"P#1```V`2%T;W@',&1A=-<```4.%CHN`0+("0`]`!)A[`(`R0H!*P`S:6X@ +M)P$`CP(S861DC@(88?<,`=<'`QX/469I60!`,P` +M`*,!!H`%,7=A;G\%$G0=#P$V`@%;`P$:!!!TC@0#`',*T2!S +M87ES+@I214%$3442!@9)$>$@8G5N9&QE+@H*475E<_H"H#\@($ES+%1`G +MD1(`\A$`%@)S82!F=6QL+98(F-%#A)B!P`2>`<``$D!`)()`"<`02H@97@;$T!S.B!3,@-4 +MO&0,D!`"3``!.`/``+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C_P`` +M`@`0+60"`)\`!*@``-D."*($$BP:#@#7"P!9"P]D&O__________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M________________________________________________55!E;6]R>341 +M``#P)B!A;F0@861D(&ET('1O(&$@=&%R(&%R8VAI=F4@=VET:&]U=`H@("!F +M:7)S="!W``-:``!V``!-`/($92!T:&4@9&%T82!D +M:7)E8W1L>8<`\01S;V-K970N("!)9B!Y;W4@=V%NB``2=%T`$B\]``!@`#!I +M97,S`%!D:7-K+$X`\`QR92!A2!E87-Y+@H*("H@3F]T93H@(G!A>"!I +M;G1E'1E;F1E9#@!`B(`$"QC +M`$!D97-PWP!`=VAA=)8`\`,@;F%M92!S87ES+@I214%$3450`$0@;&EB;0'1 +M8G5N9&QE+@H*475E6H`)V%T:0`K871H`&ES:6UP;&6U`$!T;V]L,P$`0``# +M`@!R>F-A="P@8@<`$G@'``!)`4!S=6-H)P!0*B!E>&%)`$!S.B!3,@-4P``7P%Q875T:&]R<\`%42!A;GD@\@(``050+@H*5&B=`3!P+6P, +M!`-V!3!O'2(`#!P=71>`C`@(F,T!A$B)`-I9"!T +M;V]L30`"5@$&ZP,`%`=!'!L@P(#+P,`0@$"(0`$F@,#,P``B`0/ +M-``+`"(`##4`+V%T-``,*&%T,P`&`0:`+C,@9VEV97/?!H!O=F5R=FEE=_," +M`*``!+L%$&%Q!3!W:&^1`A0J[`B%7W)E860N,RP0``&["`T1`%%?9&ES:Q8` +M`GX'`RH)`3X``QP``)D`$'9?`0*W`F%E9"!C86R)!Q!SU`9!;F-E2XS!`,!JP(2(FL#!:L``20`4"(@ +M=71II`59(&-L87-$``$?"49N86QSG0`P=H+`#L'`2,)@&%U=&]M871I_P(0><$",&5C=)D#$60Y"0,<`@5X"1!F +M+``!MP91*B!'3E5U`0(U`B8@*`0+`!H`06QO;F=5`@"M"R)S+!````4+`;X+ +M$G,W`E)S<&%RB,``!DT%``)"`$```I58W)E873/``$M +M"0\&`0("J@,#OP,"O`(/'P,8,")R9:`-46-T960B1P,"3P#$+"!W:&EC:"!W +M:6QLB@`!5@`%R@%A(&5X8V5P0`4`N04!RA`!:A`Q:&%T0PXQ:7)E40`!`1`! +MR@(@("A3"@$T!`"$`0-$!`#T`V`L(&5T8RGO"P+Z`P"I`@!H$0*-``&&`0+: +M``^6`P4!R`-A(FYE=V,BFP,!,P`G`3AN97>U`P#P!`#]`@-S!`![``&'"0&C``)*#`!-$2)I +MF4@``%1`0.;`")E +M;LD!!RT``'P`"W$`*&1E$0`#Q@(1+.4)`H```(T.`)8!`!8!`$``,&%G8?,/ +M`5\*D6-O7L#$7`U`-%A=&5V97(@8FQO8VMS\``` +M[@2X' +M$'1[%R%I;5<#<6]R(&UM87`I`0!>$P'Y%@*Y%P"V`A!GPA<0:2(3`2(`!4H` +M`.,3(6-EA0`A3VZ0`QMEPP`"Y`(R<')O.@$!A0$`FA<1+P"`8`.`-$9,VEN("FEP,A8`!"8`32],6E<=`/D#;'IM82P@ +M;'II<"P@86YD('AZ(P#!"DYO=&5S(&%B;W5TE`!R;&EB=$`\"YT96-T +M=7)E.@H*("H@5&AI48!`-T! +M\@%E9"!A=71O;6%T:6-A;&QY1P"P22=V92!A='1E;7#7`>!T;R!M:6YI;6EZ +M92!S="L`L"!L:6YK('!O;&QUN`'A+B`@268@>6]U(&1O;B?L`0"V`/$":6-I +M=&QY(&EN=F]K92!A('#K`(!U;&%R(&9E85D"0"`HD`!RT` +M!P8#`(`!`ID!<"DL(&ET('=P`/``(&=E="!P=6QL960@:6XN/@`G26YN`#``%1`0.;`")E;LD!!RT``#X`"W$`*&1E$0`#Q@(1+/```H``(FYEC@(` +M%@$`0`!B86=A:6YS1P*@8V]R7L#$7`U +M`-%A=&5V97(@8FQO8VMS\``0:$,$(6ETH0!!66]U717`F$@82!T:6U7`W%O`+$@(&)S9'1A3X`!8P``0`"\05R +M;W9I9&4@96%S>2UT;RUUX`0!V``*4`0"A`P&3 +M``)/!R)L>8<``J,!!H`%,7=A;H@`$'0V!`5%`0!@`!!IA0(`C@%EB!$!G +M&%)`$!S +M.B!3,@-4`0-)`#!C;VY# +M`O`".B`@5F%R:6]UP``7P%V875T:&]R,& +M`4D!A69I9W5R92`M#``"1`"U'2(`")P==8-(")C-`81(B0#`#@,*6]L30`"5@$&ZP,!*0$` +M%@D`C@$/;0$!`*(&('5SW0H`V@$T90HGL``C92>M``,D!`"3``!.`/``+F%M +M+"!A8VQO8V%L+FTT"0T#[0`P+F%C%P$``@`0+:("`)\`!*@``-D."*($$BP: +M#@#7"P)\`#%M86GV`2-EPH"MP(29:`, +M`!(&0'-E<77J"!!S"P4!/@$`=0``%P(`^00!<0`!<0H(EP``/`DS>2XS30`` +M[P0R92`B:P,%JP`!)``4(@L+62!C;&%S1``!'PE&;F%L]!9!I;@IA(&YU;6+R#!=FD0<$.P'' +M"@I9;W4@2X`L2`H8FEG+65N9&EAU!%C;&ET=&QE$0`" +M^@#Q`DE33SDV-C`@0T0M4D]-(&EMMP(0*#@.,"!O<,L#P&%L(%)O8VMR:61G +M9>\!`DD`-%I)4'4$!$``('5N,0L`)18`UA!@C2H`0#E%PD(`0``"@*<$`4Z`0!U!`\&`0("KP$#OP,"O`(/'P,8,")R +M9:`-`!`6$2)'`P)/`,0L('=H:6-H('=I;&R*``%6``:0`"!E>"T4``("`+D% +M!(D1`@L7`UH7`5$`!>D2,',@*%,*`30$`(0!`S,$`/0#8"P@971C*>\+`OH# +M`*D"!C`0`9L!`MH`#\@#"F$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0%!`); +M`0&)``]9`P`*%@,S5VAE`P(`OP@#U`(2<^8%#V0:____________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________________________________________]34')A=&EO2A$` +M`/,?;BX*("H@;&EB87)C:&EV92UF;W)M871S+C4@9&]C=6UE;G1S('1H92!F +M:6QE(!T`T2!S=7!P;W)T960@8GD>`'!L:6)R87)Y3`#08W!I;RXU+"!M=')E +M90D`\@YA;F0@=&%R+C4@<')O=FED92!D971A:6QE9"!I;E(`D&EO;B!A8F]U +M=$T`XW-E"B`@('!O<'5L87(@F``$>P#S"2P@:6YC;'5D:6YG(&AA``"/`/0:("=D;V,G(&1I2!I +M;@IA(&YU;6)E6]U(#\! +M8"X*"D-U"!I;G1E`*%35E(T($%30TE)=`(!%``"8P`/,@`%84)I;F%R>2X`P"`H8FEG+65N +M9&EA;J(!8VQI='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I;;<"\`DH=VET +M:"!O<'1I;VYA;"!2;V-KFEP/@$Q:6]N!0%=8GII +M<#(6``1\`4TO3%I7'0"B;'IM82P@;'II&-E<$`%`+D%!&D"L"!T:&%T(')E +M<75IE@4G87C*`E(@*&9OU`P#P!`![``-S!`![``&'"0&C`%0@;VYL>0H#`#@(`+(``1X#`*8$`@P" +M(2!B-PEQ4,`4&EN9&5PJ@`E;G0B`0`8"5!A``B; +M`")E;LD!!RT``'P`"W$`*&1E$0`#Q@(1+/```H``(FYEC@(`%@$`0`!B86=A +M:6YS1P*18V]R0 +M`P&@`A!MV`$38!(71O +M(@`%H0!A="!O;F-EA0`A3VZ0`QMEPP`"Y`(R<')O.@$!A0%18W1L>2W,``". +M"5)U='!U=.\"`&`$\0-O8FIE8W0M`%`@(&)S9",'(75SO`$`/06# +M;B!I=',@(D`\`!(BO01&2!F60!`,P``*,!!H`%,7=A;G\%$G0=#P-%`0!@```:!!!TC@0"0:7,@97-P96-I;@0! +MT`$"J@$`.@@P.B`BDPH.V@T3(KD"`-X.(F%NZ`(`I0<`$0,"6@<0+&,`0&1E +M8$(&YDT`(Q9G5L+P(& +M10`0+T,*`84!$6&>"C1A8W1[$X)D96UO;G-T$0(8`+5C;VYF +M:6=U'2(`"%P=6<0,"`B8S0&$2(D`P`X#"EO;$T``E8!!NL#`2D!`!8)`(X! +M#VT!`0"B!A!U/1,"$!P`"-E)ZT``R0$`),``$X`\``N86TL(&%C;&]C +M86PN;30)#0/M`#`N86/_```"`!`MH@(`GP`$J```V0X(H@02+!H.`-<+`%D+ +M$'G*!0'V`2-E!Q(M +M6`D/9!K_____________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_____________U-0:7-T"B`O$0``\R,@("H@5&\@2!F;W(@ +M:L`D'-A;64@9G5N8S`<``$D!0'-U8V@G`%`J(&5X84D`U',Z(%-O;64@6]U(&UA>2!F:6YD('5S969U;"\"!D4`42]M:6YIA0$1 +M8>,!46%C="!S8`"A(&1E;6]N2#R`I!I;VYS+@H*5&B= +M`?("<"UL979E;"!D:7)E8W1O%#36%K94QI\`!,GK0`#)`0`DP``3@#U`2YA;2P@86-L;V-A +M;"YM-"SA`$!E+F%C_P```@`2+50`)'1OJ``,H@2R+"!O;FQY(&YE961\`#%M +M86GV`2-E7-T96TZ +M"B`J(+@$=2XQ(&5X<&R#`@,O`P!"`0(A``2:`P,S``"(!`\T``L`(@`,-0`O +M870T``PH870S``8!!H`N,R!G:79E2XS30`"]P,2(FL#!:L``20`4"(@=71II`59(&-L +M87-$``'O!49N86QSG0`P`D09BP``;<&42H@1TY5=0$"-0(B("BK"0"Y`0`:`$%L;VYG4`9B;F%M +M97,L$`!3;&EN:R`1``!C`%)S<&%R'1E +M;J+``-J`0`9`]$J(%!/4TE8('5S=&%R6P`" +M$``R<&%X-`,"60<#>`('(0"P;V-T970M;W)I96X!`P!@`@$>`*%35E(T($%3 +M0TE)=`(!%``"4P`/,@`%84)I;F%R>2X`P"`H8FEG+65N9&EA;J(!8VQI='1L +M91$``OH`\0))4T\Y-C8P($-$+5)/32!I;;<"$2AX""!O<,L#P&%L(%)O8VMR +M:61G944`8DIO;&EE="D!`>\!`DD`-%I)4%8#!$``('5N,0LPFEP,A8`!'P!32],6E<=`*)L>FUA+"!L>FEP +M$P,O>'HC```9-!0`"0@!```*56-R96%TSP`!=00/!@$"`JH#`[\#`KP"#Q\# +M&#`B&-E +M<$`%`+D%!&D"42!T:&%T0PXQ:7)E40`!\P,!R@(@("@6!0$T!`"$`0,S!`#T +M`V`L(&5T8REF"@+Z`P"I`@8B!`&&`0+:``^6`P4!R`-A(FYE=V,BFP,!,P`G +MD#`*4#(71EVP@P.@H*N!`R:&ESD0]P:&5A=FEL>?P(-F5A;;4%`A$+@"X@ +M(%1H97)E+``C;F_B!P""`@/?"`"3!$$@:6XMMP^"(&UO9&EF:6-D"_``;W(@ +M0`&EP``L!!397-I9VXE#!)EB`4`0`0!7@$X;F5W +MM0,`\`0`>P`#GP$`>P`!APD!HP`"2@P`31$B:7*"$1!I>0<280D!`@P"(2!B +M-PD`C`HQ86)L``8`_0H!#``!+`L"U!``:``".P!"96%C:#T!(79E4,` +M4&EN9&5PJ@`E;G0B`0`8"0`/#Q!C0@42;VP-!C4*5"!7:6MI4@PP:6YGR0`P +M:&]W40\!LP,09$X(`]H``BH!(4]N/P@`]PP"8`8`TQ$`4`8#S0`!<`!3;'=A +M>7-S""IE9(H(`D<`<$DG=F4@870M#0",!S!T;R`A$+)M:7IE('-T871I8U(( +M07!O;&PV$E$N("!)9O4(4&1O;B=TJ`"097AP;&EC:71LV0EB=F]K92!A^@\1 +M8W\*`\X1("`HTA`E(&'["@"A`2`@84$``2<0`BT`",T`%&_Y"'`I+"!I="!W +M<`!!(&=E=!D3`5T*`*0$-R!);FX`-RP@:9X``5$!`YL`(F5NR0$'+0``?``+ +M<0`H9&41``/&`A$L\``"@```C0X`E@$`%@$`0``@86<##A%T\0F18V]RP,B:67-#P&<$P/G"B!D=1D-`)\#$'.%`2-O9H@!`(X2 +M$"UV```S#`#W"!%IM`\`A`!R96YV:7)O;@\+$7>0`P&@`A!MV`$3<3 +M`<0-0&)A8VOR`S%F2W,`))E9"!O=71P=73O`@!@!/$#;V)J +M96-T+7-T>6QE(&%P<')OR`,`^10"^@#0=&\@:&%V92!M=6QT:<,3!*D``@$$ +M`+D(52!O<&5NG@`3(!40`&H0``H!`#T%@VX@:71S(")`/``2(KT$$7,P#@)C +M!098`&!I='-E;&93`5!R96%D+^8`8'1E;B!U@``S0*%82!S;V-K970^`TEW:7-HN@0!)@\#60\`7,N"B05$6:X#007&0.A&$0N"@I1$1:@/R`@ +M27-S=65S/U(`$2H%&78Z+R]W=W7,@9&5T96-T960@875T;VUA +M=&EC86QL>2X*"B`J($DG=F4@871T96UP(@#@=&\@;6EN:6UI>F4@6]U(&1O;B=T"B`@(&5X<&QI8VET;'D@ +M:6YV;VME(&$@<&%R=&EC=6QA2!A8V-E<#4` +MT6%T979E717`G`@82!T:6UEI0!Q;W(@;6UA<'\` +M0&5N=&F?`D!R8VAI?P)`;F0@9PD`(&ET3P``2P$%2@!A="!O;F-EA0"+3VX@ +M=W)I=&7#``+D`C)P2!B=69F97(@;W+!``!E``1R`85A('-O8VME=#X#4'=I2UT;RUU0"0:7,@97-P96-I;@0!T`$"J@'S!TYO +M=&4Z(")P87@@:6YT97)C:&%N9V6?!1,BN0(@;&P\`0+H`A!DO@$`_04!P040 +M+&,`0&1EF-A="P@8@<`$G@'``!)`0"2"0`G`%`J +M(&5X84D`0',Z(%,R`U1S;6%L;!4`!#X!`%(#(6%T'`@@;6'F!"!N9-`",69U +M;"\"!D4`$"]#"@&%`1%A!@E186-T('-@`+`@9&5M;VYS=')A=+'2(`")P=;H+(")C-`81(B0#`!(+*6]L +M30`"5@$&ZP,`E``!%@D`C@$/;0$!`&8(('5SW0H`V@$T90HGL``C92>M``-G +M`0"3``!.`/4!+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_```"`!`MH@(`GP`$ +MJ```:@L(H@1A+"!O;FQYUPL"?``Q;6%I]@$C97*N`05P`"1I;F0`@2YH+FEN +M"@DM]`=2;&%T97-G`!%B-`(#<@$"M0!@"@I'=6ED\P`H($14!@32`0)U``&W +M`7!S>7-T96TZ&@D"N`0A+C'!#`!A#`$W`0,O`P`+``(A``2:`P,S``"(!`\T +M``L`(@`,-0`O870T``PH870S``8!!B$N,[8+$'-E"H!O=F5R=FEE=_,"`*`` +M!<`+`'$%,'=H;Y$"%"JD"H5?PH"MP(29:`,`%L$$'/4!A!N2PT`U@(`DP``=0``%P(` +M^00!<0`!<0H(EP`!G`DC+C--``#O!#)E(")K`P6K``$D`!0B"PM9(&-L87-$ +M``$?"49N86QSG0`2P$2+8($-7,N-:H(`J\``!D#`/T%-6UA=&D/!&,"!98!`+`` +M``H"D"XU+"!M=')E90D``&\`7G1A"`#.#1,BR0TR+F@BJ0`R:&4*7PP0(+`)`/H``!0`!.D&`W((`G\" +M-&UO2X` +ML2`H8FEG+65N9&EAU!%C;&ET=&QE$0`"^@#Q`DE33SDV-C`@0T0M4D]-(&EM +MMP(1*'@((&]PRP/`86P@4F]C:W)I9&=EYP%B2F]L:65T*0$![P$"20`T6DE0 +M=00$0``@=6XQ"P`?$P#6$&!R(")D969^!A$B9@D#&```H00C:655`0##`0"B +M`85"4T0@)V%R)U(``?@`$2?]`Q`GNP($/0%:-RU::7`F`-A-:6-R;W-O9G0@ +M0T%"+``Q3$A!"@,Z3%I(,@`Z4D%2$0`86!$``1D(!2`&`/42"*\"`'82`"H( +M`,,/`TP&!D4(,&)E9DH#4F5V86QU0@H`K@,#+P(`'P@P*B!U]@40;Q@$``L% +M`D,"`0H``EP)L5)032!WFEP,A8` +M!'P!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9-!0`"0@!```*`IP0!3H! +M`'4$#P8!`@*O`0._`P*\`@\?`Q@P(G)EH`T`$!81(D<#`D\`Q"P@=VAI8V@@ +M=VEL;(H``58`!I``(&5X+10``@(`N04$B1$":Q0`0PX`TQ,`40`%Z1(PA@!+1`0:2`*<&AE879I;'G\"#9E86VU +M!0(1"P6(%$!I0`&@`0I:7-N%")B98@%`$`$`5X!.&YE=[4#`/`$ +M`/T"`Y\!`'L``8<)`2L5`DH,`PH#`#@(`&\0%'3N$@(,`B$@8C<)`(P*`8\8 +M`[@4`0P`$&$,`0+4$`!H``([`!%EG!8`/0$A=F5S`Q-Y0P!0:6YD97"J`"5N +M="(!`$0-`7D9`$(%$F]L#0:P"U0@5VEK:5(,`PP3,&AO=U$/`;,#$&2M`0/: +M``+W$P4T&`3\!`#S#@!0!@/-``%P``*`%P+$!0]D&O__________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M________________________________________________5E!L97,I"BP1 +M``#P)"`@*B!3;VQA +M`*935E(T($%30TE)%``"8P`/,@`%84)I;F%R>2X`\P<@*&)I9RUE;F1I86X@ +M;W(@;&ET=&QE$0`"QP#P'TE33SDV-C`@0T0M4D]-(&EM86=EFEP/@$Q:6]N1`!=8GII<#(6``1D`4TO3%I7'0"Q;'IM82P@ +M;'II<"S'`"]X>B,``!DT%``)"`&58V%N(&-R96%TSP!/&-E<'0"`D0*("`@:0+1('1H870@0`&EP"0:7,@9&5S:6=NH@9";R!B98@%`$`$`3`$ +M.&YE=[4#`-P#`'L``4,`4&EN9&5PJ@`B;G1_`!!R.P0`!``P=&EC0@4D;VZ!`02N +M`/``5VEK:2!E>'!L86EN:6YGB0`P:&]W^``!LP,09)8%`RP``BH!(4]NJ@`< +M+`,!``0$,FUA='``0&QW87E&`0#=`?(!960@875T;VUA=&EC86QL>4<`L$DG +M=F4@871T96UPC`?@=&\@;6EN:6UI>F4@2!I;G9O:V4@82!PZP`@=6Q9"*!E +M871UP,1<#4`T6%T979E`%`@(&)S9",'(75SO`$`/06#;B!I=',@(D#E +M`!(BO01&P`28D(``$X&`-$``#8!(71OFPDP9&%TUP!6=7)C93HN`0+( +M"0#"`!)A[`(`R0H!*P`S:6X@)P$`E0LS861DC@(88?<,`=<'(6]U]P119FER +M0"0:7,@97-P96-I +M;@0!T`$"J@$`.@@P.B`BDPH.V@T3(KD"(&QL/`$"Z`(`I0<`$0,"P040+&,` +M0&1E%EF-%#A)B +M!P`2>`<``$D!`)()`"<`4"H@97AA20!`8$(&YDT`(Q9G5L+P(&10`0+T,*`84!$6&>"E%A8W0@'2(`")P==8- +M(")C-`81(B0#`#@,*6]L30`"5@$&ZP,!*0$`%@D`C@$/;0$!`+`,$'4]$P': +M`31E"B>P`"-E)ZT``#H/,"`J(),``$X`\``N86TL(&%C;&]C86PN;30)#0/M +M`#`N86,7`0`"`!`MH@(`GP`$J```V0X(H@02+!H.`-<+`%D+$'G*!0'V`2-E +MPH"MP(`318A86R)!T!S97%UZ@@0 +M=&%R+C54`0CQ +M!`4^$A%S8P0Q<&]PY0\#G`$$>P`(2PE`:&%R9!8,`3`&`J@!`X42`(X!86UO +M9&5R;H\``.@!`+P'<"!V87)I86Y("0`B##!M86[X"Q%PK1]!;!I;@IA(&YU;6)E"`"X!!,BXP`R+F@BJ0`R:&4*7PP0(+`) +M`/H``!0`!.D&`W((`G\"$&T:%P/[`$(N("!0B@FR;&5T('5S"FMN;W<0`0&9 +M!F!E`D09@82`;<&`H<8!JH+"``:`/@5#"`6`1````4+ +M`;X+$G,W`E)S<&%R%#36%K94QIM``-G`0"3``!.`/4!+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_```" +M`!(M5``D=&^H```@`3!D:7-?`A!U00&R+"!O;FQY(&YE961\`#%M86GV`2-E +M7-T96TZ"B`J +M(&)S9'1AM`_`$,R!G:79E2XS!`,!JP(2(FL# +M!:L``20`Z2(@=71I;&ET>2!C;&%S1`"6:6YT97)N86QSG0!@P$2 +M+8($4W,N-2!D5@(#I@0@:6QV`]1R;6%T-50!"/$$4&%B;W5T&@$@P"`+"!I;F-L=62*`<5H87)D+71O+69I;F1;`0%'``!!`&%M;V1E +M$D# +M(F5R60<#>`('(0"P;V-T970M;W)I96X!`P!@`@$>`*%35E(T($%30TE)=`(! +M%``"4P`/,@`%,$)I;LH$`$(`H"`H8FEG+65N9&GS!(-R(&QI='1L91$``OH` +M\0))4T\Y-C8P($-$+5)/32!I;;<"$2AX""!O<,L#P&%L(%)O8VMR:61G944` +M8DIO;&EE="D!`>\!`DD`-%I)4%8#!$``D'5N8V]M<')EFEP,A8`!&0!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC +M```9-!0`"0@!```*56-R96%TSP`!=00/!@$"`JH#`[\#`KP"#Q\#&#`B&-E<$`%`+D% +M!&D"T2!T:&%T(')E<75IP`#GP$`>P`!APD!HP`"2@P#"@,`.`@`L@`!'@,`"0$"#`(A(&(W +M"0!J"#%A8FP`!@","@$,``$L"P($`0!H``([`$)E86-H/0$A=F5S`Q-Y0P!0 +M:6YD97"J`"5N="(!`!@)``\/$&-"!1)O;`T&-0I4(%=I:VE2##!I;F?)`&-H +M;W<@=&_U``>6"@(J`2%/;C\(`/<,`G@&`P,!`_@``8@)4&%L=V%Y1@$`W0$J +M962*"`)'`'!))W9E(&%T+0T`C`<`P0^0:6YI;6EZ92!S#@T28U((07!O;&R4 +M#5$N("!)9O4(4&1O;B=TJ`"097AP;&EC:71LV0EB=F]K92!A^@\18W\*,69E +M830+,"AS=2\!!?L*`*D`("!A00`1P,1<#4`T6%T979EP"`,D*`2L`,VEN("#U%F:7)S=)("`*8!$6%P$A%O61$`]@`6+G0` +M`]D#`J60!`,P``*,! +M!H`%,7=A;G\%$G0=#P-%`0!@```:!!!TC@0#`',*+%1`G-Q,`C!4`%@)S82!F=6QL+98(7,@<')O9'5C97,@8V]R6]U('1O(&AA=F4@;75L=&EP)0`P`/,- +M("!B2!D8737`%9UX`0!V``*4`0`` +M`P&^``7+`0#3``.C`4,N("!)I`$A86Z(`!)T70`!-@(491\!`#L!061I"!I;G1E&%)`$!S.B!3,@-4`0-)`#!C;VY#`O`".B`@5F%R +M:6]UP``7P%Q875T:&]R<\`%`1\&`?("`DT'$`H5"%!T;W`M;`P$`W8%`#`' +M`4$`$&DD!0FV`B)I;O@$(FEOX08$O0+P`DY%5U,@+2!H:6=H;&EG:'1S7`8P +M'2(`#!P=71>`C`@(F,T!A$B)`,`J@2!N +M965D?``Q;6%I]@$C97*N`05P`"1I;F0`@2YH+FEN"@DM]`=2;&%T97-G`!%B +M-`(#<@$"M0!@"@I'=6ED\P`H($14!@32`0)U``#S`8`@PH" +MMP(A960N"P!;!!!SU`80;A$,`-8"`),``'4``!<"`/D$`7$``7$*")<``9P) +M(RXS30``[P0R92`B:P,%JP`!)``4(@L+62!C;&%S1``!'PE&;F%L]!9!I;@IA +M(&YU;6+R#!=FD0<#HP#7+@H*66]U('-H;W5L9*0+`$P`,6-O<'8&0&-O;6V> +M"`#.#1,BR0TR+F@BJ0`R:&4*7PP0(+`)`'4!`!0`!.D&`W((`G\"-&UO@,QBH@4U92-"!!4T-)210``E,`#S(`!6%" +M:6YA`@@;W#+`\!A;"!2;V-K[`@0]`5HW+5II<"8`V$UI +M8W)OFEP/@$Q:6]N&`%= +M8GII<#(6``1\`4TO3%I7'0"B;'IM82P@;'IIP`!APD!*Q4"2@P`31$B:7*"$1!I>0<#[A(" +M#`(A(&(W"0","C%A8FP`!@","@$,`!!A#`$"U!``:``".P!"96%C:#T!(79E +M4,`4&EN9&5PJ@`E;G0B`0!$#0`/#Q!C0@42;VP-!K`+5"!7:6MI4@P# +M#!,P:&]W40\!LP,09*T!`]H``O<3(4]N/P@`]PP"8`8`\PX`4`8#S0`!<``" +M@!<"Q`4J962*"`)'`'!))W9E(&%T(14`C`'!L:6-I=&S9"6)V;VME(&'Z#Q%C?PH#SA$@ +M("C2$`!U#`@<`A!AL@$!)Q`"+0`(S0`4;W,$<"DL(&ET('=P`%`@9V5T(-(2 +M`5T*`*0$-R!);FX`!287`9X``5$!`YL`(F5NR0$'+0``?``+<0`H9&41``.J +M`!$L6!$"@```C0X`E@$`%@$`0``P86=A\P\!7PJ18V]R7L#$7`U`&)A=&5V97)X%Q%S\```[@$P'Y +M%@*[&0"V`A!GQ!D0:2(3`2(`!4H``.,3#V0:________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________________________________________](4'(*("`J-Q$``/T, +M(&=Z:7`@8V]M<')EFUA +M+"!L>FEP+"!A;F0@>'HC```9-!0`\3(*5&AE(&QI8G)A&-E<'1_`/$* +M"B`@("!E;G1R:65S('1H870@$E33SDV-C`3`%HW +M+5II<#D`-EA!4A$`0PI7:&4#`@#D`00%`A$L_`%A2!S=')E86WM +M`>!S>7-T96TN("!4:&5R92P`D&YO(&1IP`!S@`4=E@#$G.C +M`%0@;VYL>0H#0&UE;G2R``$>`P+``P"#`R`@8H\!D"!R96%D86)L9:(`07=R +M:70,`!!A#`$"!`$!1`0!.P!$96%C:"8"`98"$WE#`%!I;F1E<*H`(FYT?P`0 +M$N("!)9B!Y;W4@9&]N)^P!`+8`\0)I8VET;'D@:6YV +M;VME(&$@<.L`('5L-P0@96%9`D`@*'-U+P$9``%1`0.; +M`")E;LD!!RT``'P`"W$`*&1E$0`#J@`1+/```H``(FYEC@(`%@$`0`!B86=A +M:6YS1P*@8V]RP,1<#4`T6%T979E2!B=69F97(@)`@`90`$<@&%82!S;V-K +M970^`TEW:7-HN@3`P"`,,)`2L`,VEN("0#`',*T"!S87ES +M+@I214%$346[!@?H!N$@8G5N9&QE+@H*475E<_H"H#\@($ES7!1`GH@1`9W)A;18"F-%#A)B!P`2>`<``$D!`)()`"<` +M4"H@97AA20!`8$(&YDT`(Q +M9G5L+P(&10`0+T,*`84!$6&>"E%A8W0@H($',+!0$^`0!U```7`@#Y!`%Q +M``%Q"@B7```\"3-Y+C--``#O!#)E(")K`P6K``$D`!0B"PM9(&-L87-$``$? +M"49N86QSG0`2!Q(M@@0U +M"`"X!!,B!0XR+F@BJ0`R:&4*7PP0(+`)`/H``!0`!.D&`W((`G\"-&UO5$P`P%&!E2X`L2`H8FEG+65N +M9&EAU!%C;&ET=&QE$0`"QP`$7Q:10T0M4D]-(&EMMP(0*#@.,"!O<,L#P&%L +M(%)O8VMR:61G9>\!`DD`#QX78P\+%P#036EC2$`\AMU7-T96TZ"B`J(&)S9'1A@ +M`/`#;&EB2!A2XS +M30`"=`%U(G-T2!C;&%S1`"6:6YT97)N86QS +MG0!@P"`+"!I;F-L=62*`<5H87)D+71O+69I +M;F1;`0%'``!!`&%M;V1E``"/`/`-("=D;V,G(&1I2!I +M;@IA(&YU;6)E2!E2QN``5H`W!U=&]M871I_P(0>68!,&5C=)D#$635``,<`E!O;&QO +M=Y,!$&8L`#!S.@K?!#%'3E5U`0(U`B8@*+D!`!H`06QO;F=5`F)N86UE`*%35E(T +M($%30TE)=`(!%``"4P`/,@`%84)I;F%R>2X`H"`H8FEG+65N9&GS!(-R(&QI +M='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I;;<"@"AW:71H(&]P^@7`86P@ +M4F]C:W)I9&=E10!B2F]L:65T*0$![P$"20`T6DE05@,$0`"0=6YC;VUP[`@0]`5HW+5II<"8`V$UI8W)O`,(KP)@:&%N9&QENP(0>;<#`+8$!K@" +M,&)E9DH#<&5V86QU873*`@`@``.9`P+/`A!U]@40;W$"`+8"`D,"`0H`$2"# +M`:)24$T@=W)A<'!E3@)%9WII<#X!,6EO;A@!76)Z:7`R%@`$?`%-+TQ:5QT` +MHFQZ;6$L(&QZ:7`3`R]X>B,``!DT%``)"`&58V%N(&-R96%TSP`!=00/!@$" +M`J\!`[\#`KP"#Q\#&,$B0`&EP"P:7,@9&5S +M:6=N962C"R)B9;X"`$`$`3`$.&YE=[4#`/`$`'L``Y\!`'L``8<)`:,`5"!O +M;FQY"@,`.`@`L@`!'@,`"0$"#`(A(&(W"7%R96%D86)L``8`C`H!#``!+`L" +M!`$`:``".P!"96%C:#T!(79E4,`4&EN9&5PJ@`E;G0B`0`8"5!A`8!`@HC;F3X``&("5!A;'=A>48!`-T!*F5DB@@"1P!P22=V92!A="T- +M`(P'T'1O(&UI;FEM:7IE(',.#1)C4@A0<&]L;'4B!U$N("!)9O4(0&1O;B?6 +M!P&V`%!I8VET;-D)@79O:V4@82!PZP`!?PHQ9F5A-`LP*'-U+P$%^PH`J0`@ +M(&'I``2UV```S#`#W"!%IAP8`A`!P96YV +M:7)O;M<",7,@=Y`#`:`"$&W8`1-R6@,%,`(`6P`"?P`1>7L#$7`U`-%A=&5V +M97(@8FQO8VMS\```[@@``8P2%82!S;V-K970^`TEW +M:7-HN@0!)@\#60\`4X.475S92`B(0$`6@@@+")0 +M"+$L(&-A<&%B:6QI=/8"!`,!!?$``O,/`;<$"/8%`9P"`,D*`2L`,VEN("#U%F:7)S=)("`*8! +M$6%P$A%O61$`]@`6+G0``]D#`J60!`,P``*,!!H`%,7=A;G\%$G0=#P$V`@%;`P$:!!!TC@0#`',*T2!S87ES+@I214%$3442!@9)$>$@8G5N9&QE+@H*475E<_H" +MH#\@($ES+%1`GD1(`\A$`%@)S82!F=6QL+98(F-%#A)B!P`2>`<``$D!`)()`"<`02H@ +M97@;$T!S.B!3,@-4O&0,D!`"3``!.`/``+F%M+"!A8VQO8V%L+FTT +M"0T#[0`P+F%C_P```@`0+60"`)\`!*@``-D."*($$BP:#@#7"P!9"Q!YR@4! +M]@$/9!K_____________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_____________V=08VAI=F4G$0``\#T@=VET:&]U=`H@("!F:7)S="!W2!F6]U('=A;H@`$G1=`!`OB@`196``,&EE +M7,N"E)%041-12X`1"!L:6(3 +M`=%B=6YD;&4N"@I1=65SK@"@/R`@27-S=65S/U(`UBH@:'1T<#HO+W=W=RXX +M`$`N;W)GDP``2`$Q:&]MIP"`(&]N9V]I;F`<``$D!0'-U8V@G`%`J(&5X84D`0',Z(%,R`U1S +M;6%L;!4`!#X!`%(#(6%T?`2`;6%Y(&9I;F30`C%F=6PO`@9%`%$O;6EN:84! +M$6'C`5%A8W0@2#R`@`!!5`N"@I4:)T!,'`M +M;`P$`W8%,&]R>3$%,'1A:20%";8"(FEN^`0Q:6]NZP4$O0+P"4Y%5U,@+2!H +M:6=H;&EG:'1S(&]F(')E8P8"`C$%`Z`"DD-/4%E)3D<@+0P%`,T%`"@&(F1O +MGP``AP4`S@#R!"H@24Y35$%,3"`M(&EN\`!,G +MK0`#)`0`DP``3@#U`2YA;2P@86-L;V-A;"YM-"SA`$!E+F%C_P```@`0+:(" +M`)\`!*@`#*($LBP@;VYL>2!N965D?``Q;6%I]@$C97*N`05P`"1I;F0`@2YH +M+FEN"@DM]`=2;&%T97-G`!%B-`(!9@$39;4`8`H*1W5I9/,`*"!$5`8$T@$" +M=0`!MP%P!1%E +M^P,`\@"`;6%T]!;!I;@IA(&YU;6)E"`"X!!,B?P(R +M+F@BJ0"`:&4*`D09BP``;<&42H@1TY5=0$"-0(F("@$"P`:`$%L;VYG50(`K0LB+``-J`0`9`]$J(%!/4TE8('5S=&%R6P`"$``/B@P#!R$`P&]C=&5T +M+6]R:65N=!<$,7!I;QX`IE-64C0@05-#24D4``)3``\R``5A0FEN87)Y+@#` +M("AB:6FEP,A8` +M!'P!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9-!0`"0@!```*56-R96%T +MSP`!+0D/!@$"`JH#`[\#`KP"#Q\#&#`B&-E<$`%`+D%!FH0,6AA=$,.$&F6!2=A>,H" +M("`H%@4!-`0`A`$#1`0`]`-@+"!E=&,I[PL"^@,`J0(&,!`!A@$"V@`/E@,% +M`<@#82)N97=C(IL#`3,`)W-HL``!$@`/1@-C!`4$`EL!`8D`#UD#``H6`S-7 +M:&4#`@C1#@+F!6%R97-U;'1-$A%B:`4@=&6[#@%5!`\C`@$*"P,!@``/Z0)4 +M$`HJ$@&G!P(F"`:A!@`^!R%T9=L($3I4$@$M$!!I(`IP:&5A=FEL>?P(-F5A +M;;4%`A$+<"X@(%1H97(T$2`@;M82,7)E8S`1`]\(`),$02!I;BVW#X(@;6]D +M:69I8^4,\`!O`3AN97>U`P#P!`#]`@-S!`![``&'"0&C``)*#`!-$2)I7-S""IE9(H(`D<`<$DG=F4@870A%0",!S!T;R`A$'!M:7IE +M('-TM0@"4@A!<&]L;#82!N04061O;B?L`7!E>'!L:6-I#15@:6YV;VMEO!(! +MZP`!?PH#SA$@("C2$"4@8?L*`*$!("!AL@$!)Q`"+0`(S0`4;_D(<"DL(&ET +M('=P`$$@9V5T&1,!70H`I`0W($EN;@`R+"!I@A4!G@`!40$#FP`B96[)`0"(&5N=FER;VX/"Q%WD`,!H`(0 +M;=@!$W):`P4P`@!;``)_`!%Y>P,1<#4`T6%T979E:89`@4.%CHN`0+("0`]`!)A +M[`(!@`X`T1DS:6X@)P$`104U861D'`$`_`@$J@$`>08/9!K_____________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_____________________________________________________V502!O9B!T:&4@9F]L +M;&]W:6YG.@H@("H@=75E;F-O9&4-`/$!9WII<"!C;VUPFUA+"!L>FEP+"!A;F0@>'HC`,$*3F]T97,@ +M86)O=724`/`[;&EB2!A2!S=')E86TM;W)I96YT960@P`!S@`0=G(!4G)M871SHP#P`B!O;FQY(')E<75I4,`4&EN9&5PJ@`B;G1_`$%R92!A!`"4 +M=&EC;&5S(&]N@0$$K@#P`%=I:VD@97AP;&%I;FEN9\D`,&AO=_@``O4`!RP` +M`BH!(4]NJ@`<+`,!`',!,FUA='``0&QW87E&`0#=`?(!960@875T;VUA=&EC +M86QL>4<`L$DG=F4@871T96UPUP'@=&\@;6EN:6UI>F4@2!I;G9O:V4@82!P +MZP"`=6QA8`0U:``)[`S%I97/#``%O`[!A;'-O(')E9'5C99L" +M,&4@0"0:7,@97-P96-I;@0!T`$"J@$`.@CS`SH@(G!A +M>"!I;G1E7!1`GH@1`9W)A;18"`<``$D!`)()`"<`4"H@97AA20!`8$(&YDT`(Q9G5L+P(&10`0+T,*`84!$6$& +M"5%A8W0@`0-)`#!C;VY#`O`".B`@ +M5F%R:6]UP``7P%V875T:&]R,&`4D!A69I +M9W5R92`M#``"1`"U'2(`")P==8-(")C-`81(B0#`#@,*6]L30`"5@$&ZP,!*0$`%@D`C@$/ +M;0$!`*(&('5SW0H`V@$T90HGL``C92>M``,D!`"3``!.`/``+F%M+"!A8VQO +M8V%L+FTT"0T#[0`P+F%C%P$``@`0+:("`)\`!*@``-D."*($$BP:#@#7"P)\ +M`#%M86GV`2-EPH"MP(29:`,`%L$0'-E +M<77J"!!S"P4!/@$`=0``%P(`^00!<0`!<0H(EP``/`DS>2XS30``[P0R92`B +M:P,%JP`!)``4(@L+62!C;&%S1``!'PE&;F%L]!9!I;@IA(&YU;6+R#!=FD0<$.P''"@I9;W4@ +M2X`L2`H8FEG+65N9&EAU!%C;&ET=&QE$0`"^@#Q`DE3 +M3SDV-C`@0T0M4D]-(&EMMP(0*#@.,"!O<,L#P&%L(%)O8VMR:61G9>\!`DD`-%I)4'4$!$``('5N,0L`)18`UA!@C2H +M`0#E%PD(`0``"@*<$`4Z`0!U!`\&`0("KP$#OP,"O`(/'P,8,")R9:`-`!`6 +M$2)'`P)/`,0L('=H:6-H('=I;&R*``%6``:0`"!E>"T4``("`+D%!(D1`@L7 +M`UH7`5$`!>D2,',@*%,*`30$`(0!`S,$`/0#8"P@971C*>\+`OH#`*D"!C`0 +M`9L!`MH`#\@#"F$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0%!`);`0&)``]9 +M`P`*%@,S5VAE`P(`OP@#U`(2<^8%7W)E1X`\`EL +M:6)R87)Y"B`J(&-P:6\N-2P@;71R964)`/(.86YD('1A3`1!F+`"@FEP,A8`!'P!32],6E<=`*)L>FUA +M+"!L>FEP$P,O>'HC```9-!0`"0@!E6-A;B!C,H"4B`H9F]R-`0` +MA`$#,P0`]`-Q+"!E=&,I+F\!`/H#`*D"!B($`1<``MH`#Y8#!0'(`V$B;F5W +M8R*;`P$S`"=S:+```1(`#T8#8P0%!`);`0&)``]9`P`*%@,S5VAE`P(`V`(# +MU`(2<^8%87)E``B;`")E;LD!!RT``'P`"W$`*&1E$0`# +MQ@(1+/```H``(FYEC@(`%@$`0`!B86=A:6YS1P*18V]RP,Q:65SPP`!;P,#YPHQ9'5CN04P92!SA0$C;V:(`0`]"A`M=@``,PP` +M]P@1:8<&`(0`<&5N=FER;V[7`C%S('=N`@&@`A!MV`$32W,``"."5)U='!U=.\"`&`$\0-O8FIE8W0M`%`@(&)S9",'(75SO`$`/06#;B!I=',@(D`\`!(BO01&2!F#U%F:7)S=)("`*8!(&$@0P40;\,/`=X*%BYT``/9`P*G +M`0"_``*<`0&%``:X`0!V``##``"\`Q)EDP`",0\@;'ED`0#,``"C`0:`!3%W +M86Y_!1)T'0\!-@(!6P,`8PP`,P!!9&ES:RP#`WX&N6-O;G9E;FEE;F-EP`$` +MB0`P;6%K>0"0:7,@97-P96-I;@0!T`$"J@$`.@@P.B`BDPH.V@T3(KD"`-X. +M(F%NZ`(`I0<`$0,"6@<0+&,`0&1E`0-)`#!C;VY#`F$Z("!687+N$V!I=&5MH(`N47`),``'4` +M`!<"`/D$`7$``7$*")<``9P)("XSHQ:L`D'-A;64@9G5N8S`<``$D!0'-U8V@G`%`J(&5X +M84D`U',Z(%-O;64@6]U(&UA>2!F:6YD('5S +M969U;"\"!D4`42]M:6YIA0$18>,!46%C="!S8`"A(&1E;6]N2#R`I!I;VYS+@H*5&B=`?("<"UL979E;"!D:7)E8W1O%#36%K94QI\`!,GK0`#)`0` +MDP``3@#U`2YA;2P@86-L;V-A;"YM-"SA`$!E+F%C_P```@`2+50`)'1OJ``, +MH@2R+"!O;FQY(&YE961\`#%M86GV`2-E7-T96TZ"B`J(+@$=2XQ(&5X<&R#`@,O`P!"`0(A``2: +M`P,S``"(!`\T``L`(@`,-0`O870T``PH870S``8!!O`%+C,@9VEV97,@86X@ +M;W9E] +M!;!I;@IA(&YU;6)E"`"X!!,BO0(R+F@BJ0"`:&4*2R"```[!P$C"4!A=71O +MDP8`_P(0><$",&5C=)D#$635``,<`@5X"1!F+``!MP91*B!'3E5U`0(U`B(@ +M**L)`+D!`!H`06QO;F=0!F)N86UEB,``!DT%``)"`$```I58W)E873/ +M``%U!`\&`0("J@,#OP,"O`(/'P,8,")R9:`-46-T960B1P,"3P#$+"!W:&EC +M:"!W:6QLB@`!5@`%R@%A(&5X8V5P0`4`N04$:0)1('1H871##C%I?P(-F5A;;4%`A$+@"X@(%1H97)EO0\C;F_B!P""`@/?"`"3!$$@ +M:6XMMP^"(&UO9&EF:6-D"_``;W(@0`&EP``L!!3 +M97-I9VXE#!)EB`4`0`0!7@$X;F5WM0,`\`0`>P`#GP$`>P`!APD!HP`"2@P` +M31$B:7)`$!!I>0<280D!`@P"(2!B-PD`C`HQ86)L``8`_0H!#``!+`L"U!`` +M:``".P!"96%C:#T!(79E4,`4&EN9&5PJ@`E;G0B`0`8"0`/#Q!C0@42 +M;VP-!C4*5"!7:6MI4@PP:6YGR0`P:&]W40\!LP,09$X(`]H``BH!(4]N/P@` +M]PP"8`8`TQ$`4`8#S0`!<`!3;'=A>7-S""IE9(H(`D<`<$DG=F4@870M#0", +M!S!T;R`A$+)M:7IE('-T871I8U((07!O;&PV$E$N("!)9O4(061O;B>L$I!E +M>'!L:6-I=&S9"6)V;VME(&'Z#Q%C?PH#SA$@("C2$"4@8?L*`*$!("!AZ0`! +M)Q`"+0`(S0`4;_D(<"DL(&ET('=P`$$@9V5T&1,!70H`I`0W($EN;@`W+"!I +MG@`!40$#FP`B96[)`07L#$7`U`-%A=&5V97(@8FQO +M8VMS\```[@2X'<70@82!T:6U7`W%O8! +M(71O(@`%2@``XQ,A8V6%`"%/;I`#&V7#``+D`C)P`!,@%1``:A``"@$1:2$( +M8VETP"`,D*`2L` +M,VEN("#U%F:7)S=)("`*8!$6%P$A%O\0T` +M]@`6+G0``]D#`J#B)A;N@"`*4'!C0*$"QC`$!D97-PH@``;`0!Y`,`7,N +M"B05$6:X#007&0.A&$0N"@I1$1:@/R`@27-S=65S/U(`$2H%&78Z+R]W=WF4@6]U(&1O;B=T"B`@ +M(&5X<&QI8VET;'D@:6YV;VME(&$@<&%R=&EC=6QA2T`5RH@8V%T:0`K871H`&ES:6UP;&6U`$!T;V]L +M,P$`0``#`@!R>F-A="P@8@<`$G@'``!)`0#^!@`G`%`J(&5X84D`0',Z(%,R +M`U1S;6%L;!4`!#X!`%(#(6%T>`:`;6%Y(&9I;F30`C%F=6PO`@9%`!`OKP2#R`C!I;VZ*!B!4 +M:)T!,'`M;`P$HB!D:7)E8W1O\`!,GK0`#)`0`DP``3@#U`2YA;2P@86-L;V-A;"YM-"SA`$!E +M+F%C_P```@`2+50`)'1OJ```(`$(H@2P+"!O;FQY(&YE963%"!!YR@4!]@$C +M97)<`05P`"1I;F0`D"YH+FEN"@DM(*,*4FQA=&5S9P`18C0"`68!$V6U`&`* +M"D=U:63S`"@@1%0&!-(!`G4``/,!@"!S>7-T96TZ`@L"N`0A+C$M"@#-"0$W +M`0,O`P!"`0(A``2:`P,S``"(!`\T``L`(@`,-0`O870T``PH870S``8!!O`% +M+C,@9VEV97,@86X@;W9E2XS30`"]P,2(FL#!:L``20`4"(@=71II`59(&-L87-$``'O!49N86QS +MG0`PP$2+8($-7,N-:H(`J\``!D#`/T%-6UA=-4,!&,"!98!`$P```H"D"XU +M+"!M=')E90D``&\`7G1AP`(2PF!:&%R9"UT;RTP!@1;`0%'``!!`&%M;V1E``$=`U'1E;J`('(0"P;V-T970M;W)I96Y$$`!@`@$> +M`*%35E(T($%30TE)=`(!%``"4P`/,@`%$$+9#A%Y+@"@("AB:6\+`OH#`*D"!B($`9L!`MH`#Y8#!0'(`V$B;F5W8R*;`P$S +M`"=S:+```1(`#T8#8P0%!`);`0&)``]9`P`*%@,S5VAE`P(`OP@#U`(2<^8% +M87)E0`&EP"2:7,@9&5S:6=N0A4B8F6^`@!`!`%>`3AN +M97>U`P#P!`![``.?`0![``&'"0&C``)*#`,*`P`X"`!O$#)T:&$)`0(,`B$@ +M8C<)`&H(`?L5(6]RSA`!#``080P!`M00`&@``CL`0F5A8V@]`2%V97,#$WE# +M`%!I;F1E<*H`)6YT(@$`1`T!Y18`0@42;VP-!K`+5"!7:6MI4@P##!,P:&]W +M40\"I@<`3@@#V@`+H!4$_`0`\PX`4`8#S0`!<`!`;'=A>48!`-T!*F5DB@@" +M1P`/T!?_X`GZ`Q!C-P8`!1C"871E=F5R(&)L;V-KU0H`[@<3`<0-0&)A8VM``S%F2!FP"`8`.`"L`,VEN("#U%F:7)S=)("`*8!$6%P$A%O_P(`]@`6+G0`!L`.`048`"<&`)P!`84` +M!K@!`'8``,,``H08`;X``NX4`(46`(<``J,!!E`=,7=A;IL8$'3+&`,V`@%; +M`P`G'``S``"C$0$L`P%K`P`+#YEN=F5N:65N8V7``0")```P%`*!$U)E#@#B``Y6#A`L8P!`9&5S +M<*(``&P$`>0#`',*CR!S87ES+@H``0#_B0`[%P^?`4T/`!X+434@("!# +M\2`!F0(#8P``4AT9R965" +M4T0P`#%3>6TW%P3``0.F`P#E`29E`I@`!58!$TDV +M``+=#`!&!`!/``+$`!4GJ1H!U0().`,`R@HR:65S3@`"F@1A,3H@3F5WF@,* +M2``$&P-9$@3("0%!``.) +M!1`P"`(!LB<`>`!V($UA8R!/4ZD"`#P`!ZX$`3H``T(")#`Z4``'ZP``J@D# +M_0(05`T%$CL^ +M+T`@97AI$14"IP0#U`<`&@$`E!T#C0H"8P`&FP`#700!WR$&$`4$!P($&P-@ +M8R!C;4',6UA=`P$`]P%03`Z($0V,$%D97)E)"HS8V4@ +MPP,"``>`!`OX8`0$2%3-4``01`0#?(S,@+5;B +M#@93!`9K"S@R+CBK$3=*86[(`P!V"P',"`8*`P"3`.`G96-H;R!N;VYE>&ES +M=,`0!(`!)S,P`% +M7`$`9``',P`"9P0"H1(`_S-!C```D$#!#```)$Q`I@!02`Q+C=E!Q$Q]0`((0!P;'IM82]X>EL#`^$" +M`&<`!!8@"0((`D`$`)\%$WGR#@!)`!%(R"0@(&?^$@)%``#8"01!`$!/<&5N +ME"5P(F=ZP`%B0)` +M061D:,F +M!#40%&F3#P!/`0#$`B)S=1TB(@H)(P``GC<";2(A +M`X,($CMJ$]-"``!904`*`)`4$1&(!$+`.0Q`-@(,FUA +M;BX(`)D0`,,(`NTU$&60#P&;#P@6,`%-```P#`!*`#!-86JG(P/[#@06"@-# +M!`$!`P!"$4!#:&%R_PM`5VEL@$+60`03I8P`_H.7V9R86UE9``+8$AI +M9V@M`,<'071A;7"6"S!46L6&B^O`P** +M%@"[`0_Y`P(-20`*NPD(NQD"]QP!2@`$6P("^0P08[H!(&5R?B4I=&]V&0!- +M!@!\-`(',0&7!!!I=B@!'P$`!0L`BP50"@EP96^T"P&))0"D`2!I<-H##XH` +M!@VV``M5!P>."`$*$@'Y#0TH`%8U+CDP-3P*`0D!`M(4#RL``ALT*P`#3PH/ +M5@`!%S,K``#^&`/C"`\K``$(#@D!*P`%TP$)U```K``(B@@**P`04S`+`(8& +M1'!R92W<"P"4"``["0!F`0E,`!(VC!@#\P,:.$<#!#0#0#H@5&C^`0`!%P"< +M"@";*4%R;W5T)@/":G5S=`H)8V]NH6`7<``H(1 +M`($"`BT%$SI=!@3G!@8.!P&I)W!G971O<'1?(0=2*"DL"@DR-P":`0-3#@+) +M$@$^```-`A!OS"46;$,5$2XA&@:\`*!*86%K:V\@2&5I@0$0;K$`)6%RCS8# +M%@4(]!@"0``"%`L0.`D1\`9D!P'%"`(<0`#80@)K +M*P"1*5)D(&)U9\4"('-IP@$`5@$A-&*<(A=YKP$+>`$7-$\!`2D`!24##]@! +M`3!F:7CK!0!L`@3\'@JP$P`.-`#-``!&!`$S&`8C!@&^'`%F$0!+(0;V'P)I +M`P`_#@`)"1-AW4-S(E-C;W1T(MP6$"!4```+"@6>`Q-M@SX0<]0&!#4`DDME +M97,@6F5E;-0"`#4`!4$``3T*`;T?`-,4`),.!!L!!?(`2$9I>""Q.I)N;VXM +M97AP;&\!$`!M%A!E9`T";0$"92V5=F5R9FQO=W,L:0`&CP#`1&%V:60@4F5M +M86AL]R("=14!)!TR;VENP!P`QCL`1`L-C0#P"$-O;&EN(%!E`0`O/`*``0..$@(?`P!H +M0Q%SB1%0(&AAFRJ1A(MN`01;"\R`0(`($1IRS$!8`4D.B".`.%R979I9775R;/E&8C0V;61G#H@16YS0T`"P3DP9&ER"AU`CH)$'#L.P#<%P*W +M!`"Z`$`M;F\MN@HC9FF..#1L:6+-1P-O%``G``NH`&(Z(%-K:7"3&`&S`0%C +M!0%*!0/_!`(Q"%`S,BUB:18%,&9?=$<`,&ES;ZD^!"P!$F*[(3!T`*L`""@`!-XC`<8!("URD@8@+74E``87`073``$>'P,\!"PN:+L# +M$%.X$3!I9FD##P`J`#5I;F=0"R`N:,D)!I\&`+`-`7-'(&5DE000:0,($7DX +M2S!I``&8!P#5$P/J"`%\"0()!`8]"P#B +M`@]+``\`)@$`JP``^`@895L"`UH5,"!U=1L1,&1E.PP!$7F0#@*X#0'4#Q`M +M@2XQ96-O@052;&]G:6.Q%0(T`!!S-```3A4"3R(!]A0`=@$!&``"6TD"FQ<# +M?0(&U`@)4P)$-"XQ-'H>0&0[(&E`!@S!$`B"6%*"@!3`0'P +M"!!G2P41+W8C8"!M:7AU<-\I!L@6`K$``,()%&G$+R)D"NT6`&<$`H0I`1X' +M$B[('P;F#@RF`!4SI@`"DQ@%^0(#=AT`G081+$P"`),`$BR:`!`L+`0"G@`! +M.P$@8V%E$!%BF`LQ=F5RVP,$TB).$F7^ +M`4!355,MW0D!K!@'C@``TPL`@0!@(&-L87-HF@H"9RL"*``5,4D4`"@``!<% +M`$8#`ID&":Q#$"R"))$@2V%I(%=A;F?R``8\`!);FP(075\)0&UI="!-*@+L +M4P7@(E!D979I8U8!``@HI``"H`2!B87-.$62(`P$7"0,5 +M`0;#)0-,!0(J(@9U``I+`&1697)I9GE-!`%6"`!)&C%G972:#0*E/`%B"P3- +M50!Q&@&.!44R+CDN@@$".@``2`$2;%0Q$&(3&0';"P?A#R(H+:4/0"UZ*2RK +M`P`A#S$);V:J#3!R;6%>$@">'S)E=L"`9P!!U,'5&ET:`H)@P(4&"%`P+CDN,,8'`($'`LY3('=IH14S +M=7-E)QL%-``@0V^/&P`:"U!I;FET:7P&``\E!#$0`,H!`PD"!)@``L<##I@` +M%3G*!@+```4H``;4!0!C`0*--`!Z!0*)%PED`/`#.B`@+6$L("UQ+"`M3"P@ +M+68LFQ@0=#X8-"!S9?LO`)4`(2UI'0@S+6ETF``#\0\.F``:.)@`!B@``2LD +M`$4`#7](`"`4`OL(<64@>F5R;RWZ0`!Y!`&<)`.,0!`LF@H$C1*A1&%M:65N +M($=O;*H$`*,`$&)Z#0#I``&/`P").!!YR08`*$$`L"`!)@$"I"H/Y@$`%C>V +M``(I``(:$`[?`!8V*0``>`(#61L1-Z@K$"\%"0$%`!!?N!0@+F.A(0"""S!S +M("*B!4`M8R!\*``P("UXTTHE<'GX'0%T``,0&Q(WB05082!C;W64'"-O9I8$ +M!ZTF`.4%`7\``JD/#J<`!_(5"B@``%L``*D#`:<``04`$5]I`1!?WP0A8GG9 +M,0)%`7)E('5M87-KI#\#0`$#^AX.<``&6`D"RP`%'@(`A@<&-%($A`)0+2UD +M:7.G$%(M>&%T='D*!A0`=6%C;"P*"73M`?\`4V%M=6QI(%-U;VUI;F5NC``- +M!SX)`?P`!8P`!C\"P$QA<&\@3'5C:&EN:=4%`'I5`4D"`$X<`55)``4.`=() +M`9HD`TH%`),!(&QD5PD!52X`^AL$;P0P8G5GQ@4!&```0`&P;V8*"2)L96YG +M=&B>%)!E;F0B(&9L86<>"@5A`!)S'P0&5@$"3@`#`@01()L&`5(&`3X"`*D& +M`2\$!#<`!?,#$$:C`4`@8W5T:P!`)!0HH``)X```E"`#Q +M!0`R%`8\`@.Z#%!C:&EL;`<7"SL`$$^0!@#9$`#P`@+W!R(@87M6("!OZ1`J<;`JQ8`LT"`X\;`"T9`$\%`DHT +M`"U7``\($GF&``9S!A!4!`8#,P``%0$`.`03>?,0`%@2`$($`,8E`+LB`^8) +M&#J8`@)M"``U""!E>-06`$)%!#@``>8>,S)'0G\F,S%40F@!`E8Y#0P%&#,N +M&@`M`08H`!)##P@"/P`\T%`*`&4'-K:7!P&`$# +M.@(%L1,!K@T`,12E97AA8W1L>0H)82L@`.87(#1'M`@#X!(':!$!G0$"&PX' +M9P``6P$`9@`'0P)0*#XX1RGC``4^`@#4``#<$D-A($`;D"$V3R +M-`%Z$``!!!$@?AA@"@EI;G-TA`80P"!$`>`$D-`AL$`;H*!.@K,4-64UD? +M`-A()W5LG0$+M``'^0X"*0`/Q@P#&#(;"`%1``4H``93"@HF(A(G3R8`A`H$ +M1"$!E`(19"@%`*`"!.,3,F-R:5@84G-E8W5RN"@@9W.`+0)]8B`@8?\5`/\. +M`!IG$PF5'P0M``DC(%!A9'9I<^9;(W,O"@&F+5-!+3`W.C`U+OH`0BYA``'O``>L!P&*)`'R/0#]"P!Y"`A:$`#@```!#P",`P!E*`#V'`:? +M)A`L#1P!`0PD"@F&%0))$P11.24@=!86`I<$("YH+!XC863%"6-L96%N=7!^ +M*PIB`1(L'14`#`<1P=V]R:V5D(&]K +M87F+'`'.!Y!I="!H96QD(&_#0P"H!0*:``!A&P&J``"]-0"%*@(7(@#Y'2!U +M;4$P`'P5`EP.!/X&`9Q#`/$08"!B`/HP`?@"!)\` +M`6``$%\9`19E^30`E@X`J``"[BP0:'(,`2X=@'-O;F%B;'D@N0$`$A4"EPT` +MR34`IAP7>8(3@5-K96QE=&%L?`L&C`@!70<#[`$&`@4+[`$:,>P!!B@`4$9L +M97-HR1<`U01>>H#0F%C:&73`0*M!0`"$Q!N)`$0;R$@$'*D!@#,`0"_#0!3$3!R +M:7.V4B!E;KH'$&E48P&F&`-R`@!'(#`*"61E`S!M:6QG#@%3!`#Y"@"1.`^! +M#`09,9P7`2D`!58(!!,2!G($`TP``@I+`/D$"2H"`&L!`JT!`TL`!B@``*0! +M`740,7)E8W\.%RVH`042`@$:"@7$.#$*"2A*(``#8P#?+0!1*03B%@#%'`"I +M)`%."0%W-P`:,$%C:"!B="-1+BD*"48%!$,@:7-O*`$0;:,W("@I>6H""`!A +M86ME9&5V1R`%MP,!R@$D+F/I``4$`@OI``<`"@`T`08H``(T`0+/`1%F[R(! +M@@<`H!\!'!4@;V[20T-/4R!82P$%,P<+8@`([`D%!4X`$1"_X`!S8))@E,.Q8`@0``[`0"NB`0 +M;F8=`2HA``D!`'4$``0#`/Y/1&5R:7AC``6E!PMC``CE"`#$`0,:(PQV"R681(N@!#AT` +M`1`"$B`<*P:[``(?#@!U-P&C``0V`#)I;VZY,0(Y,0#7!`%A!B)E9.H=,&QI +M:U@1`-\I!SD"`O4]`&("\`%&965D8F%C:PH)87!PA +M*P8P)@',``5W``)N3@`N"J!N9FEG+F=U97-S"#`!#@`P`1`T!%PH`FD``.0``C\"`,15`HLG +M!2@!`>H#!``7`-@%"3H)(G1O"#T$B`$%-P`,B`$'N04*B`$12`T'!$<-(',[ +MD`T09=`$8&YU>"]F2!O8G:N<@!F!0%K&P/>*P(]$U%T +M:&ES+/,((6UEO"@`C0H(Y0`35Q`$-705). +M&`(&"B`'MP`!:@0'8@8`7`$&*0``*Q0![0$`G@(`>`(QD``/X&`_L7`"8``#X`"?P9,F]W*<2!G;V]D_0$&]0D2,ADD$6_J0P'7&@"_)B!O9NP+%&$' +M*@^]&@-&,&(Q-Y,,`&`H!HD=`7('`*\!-$=)1"<%`@P#$G,`!0-%`R)B>18` +M,6EN9Q@!(7=H="X!MPX#3AL!W5$!YCQ0=&]O(&9,0@##!P#.%J%N>2!P65S(B!0)@TQ;L.R4`(A=&76 +M'P",'063:0'J``/]!@`)`P"'#@#]"#!'96[8``&\`Q,H<2TP(2D@4#L!RQT" +M%@$`1!$!0@`!Z!^R:7,@;&]N9RUS=&%U*C]B=6<*`0X'1`<*"@$`E@<28``?%!@&>``5/`Q%""5P$\10" +MI`(#ODCQ"SH@7T585%)!0U1?4T5#55)%7TY/1$]41$]4E@$`[AL,(0!Q4UE- +M3$E.2XHA-&5S94\``>D-`*M%`;XI`G0&$2Q%``!5%P$Y+B!B9=X!4"!D;W=N +M$PX'7@$@=V@R`0$E``,1"`%/`"%B>4$```A9AAQ``(P$$VQ4-MQ\!&@$`)1H` +MC`(#Y14`\C(!B6<#C&D!0!`"M!4#Q@,`HS0!HA@$9P$!1P`A87+;$2`H:J`2 +M(&9E#1$%'@L##1$$40`@9&6>"1!BH04!%#6]U0P`$2AH""6@2*5=``)L` +M86]V97)R:4(1`'8*06%M92^;,#`M=&^T5!`O.QMB;&]O:W5P'`$3*$E]"M4! +M$6$63@&92T)86%@H@@M29V5T9W(/`%!B;&]A=!P%`*(!+S`YDP(#%V$;!0`H +M``4G``3)`0-^!@3"`0>"$Q`[$@$!VAL`H!X#408!"!T`?$,0;]T^`(0"`"T% +M`C(N`215!HMW`FH)`2M:`]`&$%,B-5!F96%T==\(`O87$&Y[`07*.P"I!@'# +M'@>7`P)'%0%R`0)R`%%I;G9O;-0!!/,!`&$+```"(&]FSQ'B(&]V97)H875L('=I;&S")@&X+P,Q-@*D +M"P%^``**+@9'`0=\>`+9$`#/`@+N&PK=#@C4``+-``)')@&<.P-W!P`<)1`H +M]C@$OTH`L00!@P$`?0(C;V8,)Q!F/1,+B0``RQ\071H +M-`L!8@,`K`,!K`(">``"NQX&F@``V`D+ZP`'EQ<`V@4"@0$`&QLP`WE3@'.'@(:#P.8)1$V[@@0(.MK`7TG$#L&`!%L32D` +M_P4@;VQ/$!)H(R@"V0`!1PH`7P`!B`$`]@<0)Z<6$7)5#S!K967I<0&O)U!L +M92!U<$4'`&,T`CP``'8((&]NRRM"3$1%4G8`HE-534U!4DE%4PK]$`*M!0]D +M`P`:,2$!`R$C$#99#@B9)0!6%R!N9&\!$G390P6(#PF6(S(@ +M``7\`1!)N"8Q<&]RK00+9DH`HV50=&EL;"TP!PQ?-0!B``#E!0X.`1AS(VD! +MV!-\+6]N;'DN*7P`8%)E;W)G81YA$&1M6P)-`0#;!5!P86-K89=+!P)X`-@! +M$&6X"D`N9WH*S&H`:A,!AP0!BAL2<_@4!_8$`.L%`M\,`H@X`W,S`,\!!(X% +M`GL6%#I[!P%2*@"2(0$!40$_.03W!A(LOB``>0`W4&%X^@$!7AP"%G\1+OY- +M`@`;&S7:&0&^`0/V`02U$0E'3P`^#@1=&0`?"P9?&0"[!0!&$P*V!`(?$@!S +M#024!`KI2@)D``+D2@"N```\%%!A@8"\PH5-947`)5*0&5T96-\""1A=*4= +M`:E*`5<5`=@$`JLG`"P3`W(9!<`!"WXZ`0T2`/0``HD``_`%`1`.`F8"`*\` +M$E>/6P")>Q,@P"229VYU=VEN,S(N-H*A9F]R9V4N;F5T+P4>`_H.`2\"`U8$ +ME%II<"]::7`V-.X#"5$!86X@3F5L<\<;02U,+RWI`P#V%P$K$@O``P-P`P*M +M#2HU.C$"`U\&`55%`%X#`2D/$&5>"1%YW1$`/0($[D,Q@.\.@:Y +M`P!Y``,\`?,.>'-N:6PN86YT8F5A:,2$#32`2%N +M>2LJ$"UW"`#%/2%L92\"`=01`$@Y`58#`1M2`U8`(&%L)0X`'0$!U1\#[!8! +M`!H%,3L$&9I;&4``0!+X3`P,#8T-"``,#`P-S8U"``B,#(0`"(R +M,`$`_P<@,3(S-3,U-3,U,3(@,#$R,#(S`"`PEP!+`@(`KW5S=&%R`#`P8W4' +M`0M22T`5RH@8V%T:0`K871H`&!S:6UP;&5H`@6U`$!T;V]L +M,P$`0``#`@!R>F-A="P@8@<`$G@'``!)`4!S=6-H)P!0*B!E>&%)`$!S.B!3 +M,@-46]U(&UA>2!F:6YDT`(Q9G5L+P(&10!1 +M+VUI;FF%`1%AXP%186-T('-@`*$@9&5M;VYS=')AP0$`#@,G;V9>`0-)`#!C +M;VY#`O`".B`@5F%R:6]UP``"@+Q`F%U=&AO7-T96TZ"B`J(+@$=2XQ(&5X<&R# +M`@,O`P!"`0(A``2:`P,S``"(!`\T``L`(@`,-0`O870T``PH870S``8!!H`N +M,R!G:79E<]\&@&]V97)V:65W\P(`H``$NP4087$%,'=H;Y$"(RH@V0>%7W)E +M860N,RP0``#1!1UE$0!17V1I]!;!I;@IA(&YU;6)E`D09BP``;<&42H@1TY5=0$" +M-0(F("@$"P`:`$%L;VYG4`9B;F%M97,L$```!0L3(!$``&,`4G-P87)S?`(A +M`@@;W#+`\!A;"!2;V-KB,``!DT%``)"`$```I58W)E873/ +M``%U!`\&`0("J@,#OP,"O`(/'P,8,")R9:`-46-T960B1P,"3P#$+"!W:&EC +M:"!W:6QLB@`!5@`%R@%A(&5X8V5P0`4`N04$:0)1('1H871##C%I\+`OH#`*D"!B($`88!`MH` +M#Y8#!0'(`V$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0%!`);`0&)``]9`P`* +M%@,S5VAE`P((T0X"Y@5A`3AN97>U`P#P!`![``-S!`![``&'"0&C``)*#`!-$2)I +M7-S""IE9(H(`D<`<$DG=F4@870M#0",!S!T;R`A$+)M +M:7IE('-T871I8U((07!O;&PV$E$N("!)9O4(061O;B<<$Y!E>'!L:6-I=&S9 +M"4!V;VMEO!(!ZP`!?PH#SA$@("C2$"4@8?L*`*D`("!AL@$!)Q`"+0`(S0`4 +M;Y4(<"DL(&ET('=P`$$@9V5T&1,!70H`I`0W($EN;@`W+"!IG@`!40$#FP`B +M96[)`07L#$7`U`-%A=&5V97(@8FQO8VMS\```[@2X'<70@ +M82!T:6U7`W%O@``S0)P82!S;V-K9687`CX#27=I4X.``P1$2(A`0!:""`L(E`(H"P@8V%P86)I;&D2%`8# +M`07Q``+S#P&W!`CV!0&7`8`@:6YD:79I9&P.`]L(`(4``#H2`D(``*P+`-$` +M`#8!(71OK`TP9&%TUP``!0X6.BX!`L@)`#T`$F'L`@#)"@$K`#-I;B`G`0"/ +M`C!A9&1T!`!,``CW#`&I"@,>#U%F:7)S=)("`*8!$6%P$A%O\0T`]@`6+G0` +M`]D#`J0#`',*`.$G;71R964G(&9O +M$E33SDV-C`3`%HW+5II<#D`-EA!4A$`Y0I7:&5N(&-R96%T:6YG +M&`#Q&2P@=&AE(')EFEPX0`Q:6]N%0!=8GII<#(6 +M``0'`4TO3%I7'0"Q;'IM82P@;'II<"P4`2EX>B,`P0I.;W1E7-T96TN("!4:&5R92P`@&YO(&1I'!L86EN:6YGR0`P:&]W^``"]0`'+``"*@$A3VZJ`!PL`P$`48!`-T!\@%E9"!A=71O;6%T:6-A;&QY1P"P22=V92!A='1E +M;7#7`>!T;R!M:6YI;6EZ92!S="L`L"!L:6YK('!O;&QUN`'A+B`@268@>6]U +M(&1O;B?L`0"V`/$":6-I=&QY(&EN=F]K92!A('#K`(!U;&%R(&9E85D"0"`H +MD`!RT`!.<#`R("`ID!<"DL(&ET('=P`/``(&=E="!P=6QL +M960@:6XN/@`G26YN`#``%1`0.;`")E;LD!!RT``#X`"W$`*&1E$0`# +MQ@(1+/```H``(FYEC@(`%@$`0`!B86=A:6YS1P*@8V]R7L#$7`U`-%A=&5V97(@8FQO8VMS\``0:%<%(6ETH0!!66]U +M717`F$@82!T:6U7 +M`W%O`+$@(&)S9'1AX`0!V``*4`0"A`P&3``)/!R)L>8<``J,!!H`%,7=A;H@`$'0V!`5%`0!@ +M`!!IA0(`C@%EB!$!GF-A="P@8@<`$G@'``!)`0"2 +M"0`G`%`J(&5X84D`0',Z(%,R`U1S;6%L;!4`!#X!`%(#(6%T'`@@;6'F!"!N +M9-`",69U;"\"!D4`$"]#"@&%`1%AG@I186-T('-@`)(@9&5M;VYS=')*#0`I +M!B=O9EX!`TD`,&-O;D,"\`(Z("!687)I;W5S(&ET96US(#,!`'T#0&UE(&(W +M`3)I0&";8"(FENU@0`I`H`ZP4$O0+P`DY% +M5U,@+2!H:6=H;&EG:'1S7`8PH($',+!0$^`0!U```7`@#Y!`%Q +M``%Q"@B7```\"3-Y+C--``#O!#)E(")K`P6K``$D`!0B"PM9(&-L87-$``$? +M"49N86QSG0`2!Q(M@@0U]!9!I;@IA +M(&YU;6+R#!=FD0<$.P''"@I9;W4@ +M`*%35E(T($%30TE)=`(!%``/,@`+$$)M$1%Y+@"Q("AB:6%T`/ +M"Q<`T$UI8W)O"T4``("`+D%!(D1`@L7`UH7`5$`!>D2,',@*%,*`30$`(0!`S,$`/0#8"P@ +M971C*>\+`OH#`&P$`&T``HT``9L!`MH`#\@#"F$B;F5W8R*;`P$S`"=S:+`` +M`1(`#T8#8P0%!`?.``]9`P`*%@,/9!K_____________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________XE!E=&%I;%H1``#U'G,@=&AE +M(")S=')U8W0@87)C:&EV95]E;G1R>2(@=71I;&ET>2!C;&%SP#S"2P@:6YC;'5D:6YG +M(&AA``"/`/0:("=D;V,G +M(&1I2!I;@IA(&YU;6)E6]U(#\!8"X*"D-U\!`DD` +M-%I)4%8#!$``P'5N8V]M<')EB,``!DT%``) +M"`&58V%N(&-R96%TSP`!=00/!@$"`J\!`[\#`KP"#Q\#&,$B!S>7-T96TN("!4 +M:&5R92P`(VYOX@<`@@(#WP@`DP3R`B!I;BUP;&%C92!M;V1I9FECK0CS`F]R +M(')A;F1O;2!A8V-E0`&@`3R`FES(&1EP`#P`!APD!HP!4(&]N;'D*`P`X"`"R``$>`P"F +M!`(,`B$@8C<)<7)E861A8FP`!D%W48!`-T!*F5DB@@"1P"P22=V92!A='1E;7",!^!T;R!M:6YI +M;6EZ92!S=+4(`E((4'!O;&QU(@=1+B`@26;U"$!D;VXGU@7L#$7`U`-%A=&5V97(@8FQO8VMS\``` +M[@2X'<70@82!T:6U7`P!K"S%M87#X`C!E;G21!@/0`@%1`T!G:79EY@$A=&\B +M``6A`&%T(&]N8V6%`"%/;I`#&V7#``+D`C)P@``P0&%82!S;V-K970^`TEW:7-HN@0!)@\# +M60\`0#`',*T2!S87ES+@I214%$3442!@9)$>$@8G5N9&QE+@H*475E<_H" +MH#\@($ES8$(&YDT`(Q9G5L +M+P(&10`0+T,*`84!$6&>"C1A8W1[$W!D96UO;G-T.14@;F<^``"`!094`@-) +M`#!C;VY#`F$Z("!687+N$V!I=&5M$0(8 +M`&!C;VYF:6=^"Q4M#``"1`"UM`Q$SM@L`$!20(&]V97)V:65W\P(`JP`%P`L`<04P=VAOD0(4*J0* +MA5]R96%D+C,L$``!^`@-$0!17V1I2#R`I!I;VYS+@H*5&B=`?("<"UL979E;"!D:7)E8W1O'2(`#!P=71>`H$@(F-M86ME(B0#:60@ +M=&]O;$T``E8!!NL#`2D!,2!I;DP!#VT!`3!A2!N965D?``Q;6%I]@$C97)<`05P`"1I;F0`\@,N:"YI +M;@H)+2!T96UP;&%T97-G`!%B-`(!9@$39;4`8`H*1W5I9/,`4"!$;V-UF04" +M@0$`Q0$R86QL=0`!MP&R'!L@P(#+P,`0@$" +M(0`$F@,#,P``B`0/-``+`"(`##4`+V%T-``,*&%T,P`&`0:`+C,@9VEV97/? +M!H!O=F5R=FEE=_,"`*``!+L%$&%Q!3!W:&^1`B,J("X'A5]R96%D+C,L$``` +MT04=91$`45]D:7-K%@`@;F30`0@^``,<``"9`!!V7P$"MP)A960@8V%LB0<0 +M<]0&06YC97.M`@"3``!U``%'``-"!FAE($%027.7`'-E;G1R>2XS30`"]P,2 +M(FL#!:L``20`4"(@=71II`59(&-L87-$``'O!49N86QSG0`P] +M!;!I;@IA(&YU;6)E`D09BP``;<&42H@1TY5=0$"-0(B +M("BK"0"Y`0`:`$%L;VYG4`9B;F%M97,L$`!3;&EN:R`1``!C`%)S<&%R'1E;J+``-J +M`0`9`]$J(%!/4TE8('5S=&%R6P`"$``R<&%X-`,"60<#>`('(0#`;V-T970M +M;W)I96YT%P0@<&E^"<8J(%-64C0@05-#24D4``)3``\R``5A0FEN87)Y+@#` +M("AB:6B,``!DT%``)"`$```I58W)E873/ +M``%U!`\&`0("J@,#OP,"O`(/'P,8,")R9:`-46-T960B1P,"3P#$+"!W:&EC +M:"!W:6QLB@`!5@`%R@%A(&5X8V5P0`4`N04$:0)1('1H871##C%I\+`OH#`*D"!B($`88!`MH` +M#Y8#!0'(`V$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0%!`);`0&)``]9`P`* +M%@,S5VAE`P(`?`4#U`(2<^8%87)E`3AN97>U`P#P!`![``.?`0![``&'"0&C``)*#`!- +M$2)IF4@ +M``%1`0.;`")E;LD!!RT``'P`"W$`*&1E$0`#Q@(1+/```H```(T.`)8!`!8! +M`$``,&%G82X.`?$)D6-OP,1<#4`T6%T979E$P$/`P*A%0"V`A!GJA40:2(3 +M`2(`!4H``.,3(6-EA0`A3VZ0`QMEPP`"Y`(R<')O.@$!A0%18W1L>2W,`))E +M9"!O=71P=73O`@!@!/$#;V)J96-T+7-T>6QE(&%P<')OR`,`^10"^@!0=&\@ +M:&$Y%D!U;'1IPQ,$J0`"`00`N0A5(&]P96Z>`!,@%1``:A``"@$`/06#;B!I +M=',@(D`\`!(BO0012!F4X.``P1$2(A`0!:""`L(E`(H"P@8V%P86)I +M;&D2%`8#`07Q``+S#P$_#@CV!0&7`8`@:6YD:79I9&P.`]L(`(4``#H2`D(` +M`*P+`-$``#8!(71OK`TP9&%TUP``!0X6.BX!`L@)`#T`$F'L`@#)"@$K`#-I +M;B`G`0"/`C!A9&1T!`!,``CW#`&I"@,>#U%F:7)S=)("`*8!$6%P$A%O\0T` +M]@`6+G0``]D#`J#B)A;N@"`*4'!C0*$"QC`$!D97-PH@``;`0!Y`,`7,N"B05 +M$6:X#06Y&0*A&$0N"@I1$19`/R`@2:T9(',_4@`4*I491G=W=RXX`$`N;W)G +MDP``2`$0:+@"`%<`0V]N9V]8!Q<@3`<@(&18%B!O<#P%"!D1!+H1`:P(`3<, +M`'$``#H`'VYD&O______________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________:E!I=F4@92@1``#Q$6YT7,@9&5T96-T960@ +M875T;VUA=&EC86QL>4<`L$DG=F4@871T96UP(@#@=&\@;6EN:6UI>F4@6]U(&1O;B=TJ```M@#Q`FEC:71L +M>2!I;G9O:V4@82!PZP#P#G5L87(@9F5A='5R92`H``%1`0.;`%IE;F%B;)L``#X`"W$`*&1E$0`#J@`1 +M+/```H``(FYE)@$`%@$`0`!Q86=A:6YS=,\!V6-O8`0U: +M`)%L:6)R87)I97/#`/$"5&AI3X`!8P``+$!\09P"!I;G1E7,N"E)%041-12X`!^@& +MX2!B=6YD;&4N"@I1=65S^@*@/R`@27-S=65S/U(`UBH@:'1T<#HO+W=W=RY, +M!T`N;W)GDP``2`$0:+@"@V9O0(1.FH` +M$B>7!9`G('!R;V=R86T6`G-A(&9U;&PME@AP9"`G=&%R)WX``P(`4W)E<&QA +M0@%`8G5I;($&`(H``V,``"H`9BH@8W!I;V,```X`"V0`(&1I:P4R96YT,`-# +M9F%C96H#`P(`,&5S`<``$D!`)()`"<` +M4"H@97AA20!`8$(&YDT`(Q +M9G5L+P(&10`0+T,*`84!$6$&"5%A8W0@`0-)`#!C;VY#`O`".B`@5F%R:6]UP``7P%Q875T:&]R<\`%`1\&`?("`DT' +M$`J(!E!T;W`M;`P$`W8%`#`'`4$`$&GD!@FV`B)I;M8$`'$+`.L%!+T"\`). +M15=3("T@:&EG:&QI9VAT=&%R+C54`0CQ!$%A8F]U4P41]!9!I;@IA(&YU;6+R#!=FD0<$.P''"@I9;W4@`D09@82`;<&42H@1TY5=0$"-0(F("@$"P`:`"-L;[P%`*T+(G,L +M$```!0L3(!$``&,`4G-P87)S?`(A`*%35E(T($%30TE)=`(!%``/,@`+$$)M$1%Y +M+@"Q("AB:6`@@;W#+`\!A;"!2;V-K[`@0]`5HW+5II<"8`V$UI8W)OFEP/@$@:6]/$WTJ(&)Z:7`R +M%@`$?`%-+TQ:5QT`HFQZ;6$L(&QZ:7`3`R]X>B,``!DT%``)"`$```H"G!`% +M.@$`=00/!@$"`J\!`[\#`KP"#Q\#&#`B0`&@`0I:7-N%")B98@%`$`$`5X!.&YE +M=[4#`/`$`/T"`Y\!`'L``8<)`,,7$F5*#`!-$2)I2!D971E8W1S(&%N9"!R96%D +MFEP/@$Q:6]N!0%=8GII<#(6``1D`4TO3%I7'0"B +M;'IM82P@;'II0`&EP"0:7,@9&5S:6=NH@9";R!B98@%`$`$`3`$.&YE=[4#`/`$ +M`'L``4,` +M4&EN9&5PJ@`B;G1_`!!R.P0`!``P=&EC0@4D;VZ!`02N`/``5VEK:2!E>'!L +M86EN:6YGB0`P:&]W^``!LP,09)8%`RP``BH!(4]N/P@<+`,!``0$,FUA='`` +M0&QW87E&`0#=`2IE9(H(`D<`L$DG=F4@871T96UPC`?@=&\@;6EN:6UI>F4@ +M2!I +M;G9O:V4@82!PZP`@=6R]"*!E871U``%1 +M`0.;`")E;LD!!RT``'P`"W$`*&1E$0`#J@`1+/```H``(FYEC@(`%@$`0`!Q +M86=A:6YS=,\!D6-OP,1<#4`T6%T979E`%`@(&)S9",' +M(75SO`$`/06#;B!I=',@(D#E`!(BO01&"2`L(E`(<"P@8V%P86)!``'V`@)F!A%E50(!\0!A92!!4$ES +MMP0(]@4!EP&Q(&EN9&EV:61U86QH!1%I0@@`>P`28D(``$X&`-$``#8!(71O +MFPDP9&%TUP!6=7)C93HN`0+("0#"`!)A[`(`R0H!*P`S:6X@)P$`E0LS861D +MC@(88?<,`=<'(6]U]P119FER0"0:7,@97-P96-I;@0!T`$"J@$`.@@P.B`BDPH.V@T3(KD"`-X. +M(F%NZ`(`I0<`$0,"P040+&,`0&1E%E +MF-%#A)B!P`2>`<``$D!`)()`"<`4"H@97AA20!`8$(&YDT`(Q9G5L+P(&10`0+T,* +M`84!$6&>"E%A8W0@'2(`")P==8-(")C-`81(B0#`#@,*6]L30`"5@$&ZP,!*0$` +M%@D`C@$/;0$!`+`,$'4]$P':`31E"B>P`"-E)ZT``#H/,"`J(),``$X`\``N +M86TL(&%C;&]C86PN;30)#0/M`#`N86/_```"`!`MH@(`GP`$J```V0X(H@02 +M+!H.`-<+`%D+$'G*!0'V`2-EH($',+!0$^`0!U```7`@#Y!`%Q``%Q"@B7```\ +M"3!Y+C/T%#!A:6SO!#)E(")K`P6K``$D`!0B"PM9(&-L87-$``$?"49N86QS +MG0`2!Q(M@@0U=H+`#L'`2,)#V0:________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________________________________]I4'(*("`@/A$``!(@`0!R>F-A +M="P@8@<`$G@'`/0386YD('-U8V@*("`@*B!E>&%M<&QE'2( +M`#%P=70I`/D#(F-M86ME(B!B=6EL9"!T;V]L30`"5@$&-0$!*0$Q(&EN3`$/ +M;0$!,&%R91`"$F3:`35E"B>\`!,GK0`2.M0``),``$X`]0$N86TL(&%C;&]C +M86PN;30LX0!`92YA8RL```(`$BU4`"1T;Z@``"`!,&1IM`_`$,R!G:79E2XS!`,!JP(2(FL#!:L``20`Z2(@=71I;&ET>2!C;&%S1`"6:6YT97)N86QS +MG0`P`?$#+@H*66]U('-H;W5L9"!A;'-O(@(!3``Q8V]P=@8R8V]M6P%# +M:6X@(KT",BYH(JD`@&AE"G-O=7)C+P`19'4!`!0`!.D&!30'`"P%-&UO<$",&5C=)D#$635 +M``,<`@7"!A!F+``!MP91*B!'3E5U`0*Z`28@*+D!`!H`06QO;F=5`F)N86UE +M'1E +M;J+``-J`0`9`]$J(%!/4TE8('5S=&%R6P`" +M$``P<&%X20,B97)9!P-X`@FEP,A8`!'P!32],6E<=`*)L>FUA+"!L +M>FEP$P,O>'HC```9-!0`"0@!```*56-R96%TSP`!=00/!@$"`JH#`[\#`KP" +M#Q\#&#`B&-E<$`%`+D%!&D"`A4,<7)E<75IP`#GP$`>P`!APD!HP`"2@P#"@,`.`@`L@`Q=&AA+PD#*P`A +M(&(W"0!J"#%A8FP`!@","@$,``$L"P($`0!H``([`$)E86-H/0$A=F5S`Q-Y +M0P!0:6YD97"J`"5N="(!`!@)``\/$&-"!1)O;`T&-0I4(%=I:VE2##!I;F?) +M`#!H;W=1#P&S`Q=DE@H"*@$A3VX_"`#W#`)@!@,#`03-``%P`$!L=V%Y1@$` +MW0$J962*"`)'`'!))W9E(&%T+0T`C`<`P0^0:6YI;6EZ92!S#@T28U((07!O +M;&R4#5$N("!)9O4(4&1O;B=TJ`"097AP;&EC:71LV0EB=F]K92!A^@\18W\* +M,69E830+$"C2$`!U#`@<`A!A00`!)Q`"+0`(S0`4;_D(<"DL(&ET('=P`'$@ +M9V5T('!UG`T0:7H+1R`@26YN`#``%1`0.;`")E;LD!!RT``#X`"W$` +M*&1E$0`#J@`1+/```H```(T.`)8!`!8!`$``(&%G`PX"4`.18V]R0`P&@`A!MV`$32X'<70@82!T:6U7 +M`W%O8!(71O(@`%2@!2="!O;F-\ +M$B)/;AP."\,``N0",G!R;SH!`84!46-T;'DMS`"2960@;W5T<'5T[P(`8`3Q +M`V]B:F5C="US='EL92!A<'!R;\@#`$,2`OH`X'1O(&AA=F4@;75L=&EP)0`` +M(040=A(#0')E86VY"%4@;W!E;IX`$R`5$`!J$``*`0`]!8-N(&ETP"`,D*`2L`,VEN +M("#U%F:7)S=)("`*8!$6%P$A%O61$`]@`6 +M+G0``]D#`J60!`,P` +M`*,!!H`%,7=A;G\%$G0=#P-%`0!@```:!!!TC@0#`',*%E7,@<')O9'5C97,@8V]R6QE(&%P<')O86-H(&%L;&]W^@#@=&\@:&%V92!M=6QT:7`E +M``.I`'%S=')E86USSP`U<&5NG@#S#2`@8G-D=&%R('5S97,@=&AI2!D8737`%9UP",B!O9BL`,VEN(""!I;G1E7,N"E)%041-12X``$0$!&T!T6)U;F1L92X*"E%U97/Z`J`_("!)!D!G`<``$D!0'-U8V@G`%`J(&5X84D`0',Z(%,R`U1S +M;6%L;!4`!#X!`%(#(6%T(`8@;6'F!"!N9-`",69U;"\"!D4`42]M:6YIA0$1 +M8>,!46%C="!S8`"P(&1E;6]N0&";8"(FEN^`0B:6_A!@2]`O`"3D574R`M(&AI9VAL:6=H +M='-M``,D!`"3``!.`/4! +M+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_```"`!`MH@(`GP`$J``,H@2R+"!O +M;FQY(&YE961\`#%M86GV`2-E7-T96TZ +MIPH"N`1U+C$@97AP;(,"`R\#`$(!`B$`!)H#`S,``(@$#S0`"P`B``PU`"]A +M=#0`#"AA=#,`!@$&(2XSM@L0<]\&@&]V97)V:65W\P(`H``%G@L`<04P=VAO +MD0(4*J0*A5]R96%D+C,L$``!^`@-$0!17V1I``'<`%0P#'`(%>`D09BP``;<&42H@1TY5=0$"-0(F("@$"P`:`$%L;VYG +M50(`K0LB+``-J`0`9`]$J(%!/4TE8('5S=&%R6P`"$``/ +MB@P#!R$`P&]C=&5T+6]R:65N=!<$,7!I;QX`IE-64C0@05-#24D4``)3``\R +M``5A0FEN87)Y+@#`("AB:6FEP/@$Q:6]N +M&`%=8GII<#(6``1\`4TO3%I7'0"B;'IM82P@;'IID2,',@*'T'`30$`(0!`S,$`/0#8"P@971C*>\+`OH#`*D"`&@1 +M`HT``88!`MH`#Y8#!0'(`V$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0%!`?. +M``]9`P`*%@,S5VAE`P(`-0<#U`(2<^8%87)E'!L:6-I=&S9"6)V;VME(&'Z#Q%C?PH#SA$@ +M("C2$`!U#`@<`A!AL@$!)Q`"+0`(S0`4;W,$<"DL(&ET('=P`%`@9V5T(-(2 +M`5T*`*0$-R!);FX`!287`9X``5$!`YL`(F5NR0$'+0``?``+<0`H9&41``.J +M`!$L6!$"@```C0X`E@$`%@$`0``P86=A\P\!7PJ18V]R2!O9B!T:&4@9F]L;&]W:6YG(&)E9F]R92!E=F%L +M=6%T$@``(`#Q#6%R8VAI=F4Z"B`@*B!U=65N8V]D960@9FEL97,4``$*`/$" +M('=I=&@@4E!-('=R87!P97(;`/$!9WII<"!C;VUP'HC```9-!0`"0@!E6-A;B!C +M'1E;DT!L7,@*&9O$E33SDV-C`3`%HW+5II<#D`-EA!4A$`0PI7:&4#`@#8`@1U +M`1$L`@-AT!X'-Y0`&EP#R`FES(&1EP`!S@`4=E@#$G.C`%0@;VYL>0H#0&UE;G2R``$>`P"F!`)G`S`@ +M8F5``(!R96%D86)L9:(`07=R:70,`!!A#`$"!`$!1`0!.P!"96%C:#T!(79E +ME@(3>4,`4&EN9&5PJ@`B;G1_`!!R.P0`!``P=&EC0@4D;VZ!`02N`/``5VEK +M:2!E>'!L86EN:6YGB0`P:&]W^``"]0``E@4#+``"*@$A3VZJ`!PL`P$#V0(" +M<`!`;'=A>48!`-T!\@%E9"!A=71O;6%T:6-A;&QY1P"P22=V92!A='1E;7#$ +M`^!T;R!M:6YI;6EZ92!S="L`L"!L:6YK('!O;&QUN`'A+B`@268@>6]U(&1O +M;B?L`0"V`/$":6-I=&QY(&EN=F]K92!A('#K`"!U;#<$H&5A='5R92`HD`!RT`!^\%`(`!`ID!<"DL(&ET('=P`.`@9V5T('!U;&QE9"!I +M;J0$-R!);FX`-RP@:9X``5$!`YL`(F5NR0$'+0``?``+<0`H9&41``/&`A$L +M\``"@``B;F6.`@`6`0!``&)A9V%I;G-'`J!C;W)R97-P;VYD)P0(20`-6@`" +M>P,Q:65SPP`!;P,!;P=1P,1<#4`T6%T979E`%`@(&)S9",'(75SO`$`/06#;B!I=',@(D#E`!(BO01&"2`L(E`(<"P@8V%P86)!``'V +M`@)F!A%E50(!\0!A92!!4$ESMP0(]@4!EP&Q(&EN9&EV:61U86QH!1%IWP<` +M>P`28D(``"P$`-$``#8!(71OFPDP9&%TUP!6=7)C93HN`0+("0#"`!)A[`(` +MR0H!*P`S:6X@)P$`3P@S861DC@(18?P(!*H!`'D&(6]U]P119FER0#`',*T"!S87ES+@I214%$346[!@?H!N$@8G5N9&QE+@H*475E<_H" +MH#\@($ES8N9V]O9VQE+F-O +M;2]P+VH`$2\Z`"!S+VD``),``6<`47-U8FUI9P!P96YH86YC9;L``*8`!C@` +M@RP@<&QE87-E+```.P``!`,`2P7!1`GH@1`9W)A;18"F-%#A)B +M!P`2>`<``$D!`)()`"<`4"H@97AA20!`8$(&YDT`(Q9G5L+P(&10`0+T,*`84!$6&>"E%A8W0@'2(`")P==8- +M(")C-`81(B0#`#@,*6]L30`"5@$&ZP,!*0$`%@D`C@$/;0$!`+`,('5SW0H` +MV@$T90HGL``C92>M``-G`0"3``!.`/``+F%M+"!A8VQO8V%L+FTT"0T#[0`P +M+F%C%P$``@`0+:("`)\`!*@``-D."*($$BP:#@#7"P)\`#%M86GV`2-EPH"MP(`A1(A86R)!T!S97%UZ@@0!Q(M@@0U``&I`5"`"X!!,B!0XR+F@BJ0`R:&4*7PP0(+`) +M`/H``!0`!.D&`W((`G\"$&T:%P/[`$(N("!0B@FR;&5T('5S"FMN;W<0`0&X +M#&!E2X`H"`H8FEG+65N9&GS!(-R(&QI='1L91$``L<`!%\6D4-$+5)/ +M32!I;;<"$"@X#C`@;W#+`\!A;"!2;V-K%V,/"Q<`T$UI8W)O2!A0A$``/4R2!T:&4*)V-O;F9I9W5R92<@`""(&EN'!L86EN@`/`#;&EB2!A2XS30`"=`%U(G-T2!C;&%S1`"6:6YT97)N +M86QSG0!@2QN``5H`W!U=&]M871I_P(0>68!,&5C=)D#$635``,<`E!O +M;&QO=Y,!$&8L`!!S4`51*B!'3E5U`0(U`B8@*+D!`!H`06QO;F=5`F)N86UE +M`*%3 +M5E(T($%30TE)=`(!%``"4P`/,@`%84)I;F%R>2X`H"`H8FEG+65N9&GS!(-R +M(&QI='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I;;<"@"AW:71H(&]P^@7` +M86P@4F]C:W)I9&=E10!B2F]L:65T*0$![P$"20`T6DE05@,$0`"0=6YC;VUP +M[`@0]`5HW+5II<"8`V$UI8W)O`,(KP)@:&%N9&QENP(0>;<#`+8$ +M!K@",&)E9DH#<&5V86QU873*`@`@``.9`P+/`A!U]@40;W$"`+8"`D,"`0H` +M$2"#`:)24$T@=W)A<'!E3@)%9WII<#X!,6EO;A@!76)Z:7`R%@`$?`%-+TQ: +M5QT`HFQZ;6$L(&QZ:7`3`R]X>B,``!DT%``)"`&58V%N(&-R96%TSP`!=00/ +M!@$"`J\!`[\#`KP"#Q\#&#`B&-E<$`%`+D%!&D"L"!T:&%T(')E<75IE@4G87C*`B`@ +M*'T'`30$`(0!`S,$`/0#<2P@971C*2YO`0#Z`P"I`@8B!`$7``+:``^6`P4! +MR`-A(FYE=V,BFP,!,P`G?P(-F5A;;4%`A$+@"X@(%1H97)E+``C;F_B!P""`@/?"`"3!/("(&EN+7!L +M86-E(&UO9&EF:6.M"/,";W(@U`P#P!`![``.?`0![``&'"0&C``)*#`,*`P`X +M"`"R``$>`P"F!`(,`B$@8C<)<7)E861A8FP`!@","@$,``$L"P($`0!H``([ +M`$)E86-H/0$A=F5S`Q-Y0P!0:6YD97"J`"5N="(!`!@)4&%R=&EC0@4D;VZ! +M`02N`$17:6MI4@PP:6YGR0`P:&]WFPP"I@<'E@H"*@$A3VX_"`#W#`)X!@$" +M"B-N9/@``8@)8V%L=V%YD`!RT`!"T' +M`,T`%&_Y"'`I+"!I="!W<`!Q(&=E="!P=9P-(&ENI`0W($EN;@`W+"!IG@`( +MFP`B96[)`02UV```S#`#W"!%IAP8`A`!P96YV:7)O;M<",7,@ +M=Y`#`:`"$&W8`1-R6@,%,`(`6P`"?P`1>7L#$7`U`-%A=&5V97(@8FQO8VMS +M\```[@@``S0*%82!S;V-K970^`TEW:7-HN@0!)@\# +M60\`4X.475S92`B(0$`6@@@+")0"+$L(&-A<&%B +M:6QI=/8"!`,!!?$``O,/`;<$"/8%`9P"`,D*`2L` +M,VEN("#U%F:7)S=)("`*8!$6%P$A%O61$` +M]@`6+G0``]D#`J60! +M`,P``*,!!H`%,7=A;G\%$G0=#P$V`@%;`P$:!!!TC@0#`',* +MT2!S87ES+@I214%$3442!@9)$>$@8G5N9&QE+@H*475E<_H"H#\@($ESF-%#A)B!P`2>`<``$D!`)()`"<`02H@97@;$T!S.B!3,@-4X/\`4@*B!.15=3("T@:&EG:&QI9VAT<]P`,')E8]D4`C$%`Z`" +MDD-/4%E)3D<@+0P%`$(4`,H'(F1OGP``AP4`S@"T*B!)3E-404Q,("V2&`&/ +M!`$-``#Y%@"_``(I``-`!1(M1!D`E0`"&``%=QDE("T,``)$``*W&54L('-E +M96<``"@%`JT7`F,(@2H@0TUA:V5,U`0Q='ATB``A<'5G$#`@(F,T!A0BO!DY +M;V]L30`"5@$&-0$`E```L`H!C@$/;0$!`*(&#V0:____________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________________________________________]G4'1O(&%L+1$` +M`/`@;&]W(&EN9&EV:61U86P@96YT2!A;F0@861D(&ET3`#P!2!T87(@87)C +M:&EV92!W:71H;W5T00!19FER2!F:6QE+G0` +M0F%L8<`\01S;V-K970N("!)9B!Y;W4@=V%NB``2=%T`$B\]``,?`0`S`%!D +M:7-K+$X`\!!R92!A0#P*FES(&5S<&5C:6%L;'D@96%S>2X*"B`J($YO=&4Z(")P87@@:6YT97)C +M:&%N9V4@9F]R;6%T(B!I<^```#,``.(`<7AT96YD960X`0(B`!`L8P!`9&5S +M<-\`0'=H8726`/`#(&YA;64@F-A="P@8@<`$G@'``!)`4!S=6-H)P!0*B!E>&%)`$!S.B!3,@-4`0-)`#!C;VY#`O`".B`@5F%R +M:6]UP``7P%Q875T:&]R<\`%`1\&`?("``$%4"X*"E1HG0$P<"UL#`0#=@4` +M"08!00`0:20%";8"(FENU@0Q:6]NZP4$O0+P`DY%5U,@+2!H:6=H;&EG:'1S +M7`8PM``,D!`"3``!. +M`/4!+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_```"`!`MH@(`GP`$J``,H@2R +M+"!O;FQY(&YE961\`#%M86GV`2-E7-T +M96TZ<`<"N`1U+C$@97AP;(,"`R\#`$(!`B$`!)H#`S,``(@$#S0`"P`B``PU +M`"]A=#0`#"AA=#,`!@$&@"XS(&=I=F5SWP:`;W9EP$2+8($-7,N-:H(`)X%$67[`P#R`(!M871S +M('-U<'\(!&,"!98!`$P```H"D"XU+"!M=')E90D``&\`7G1A`D09BP``;<&42H@1TY5 +M=0$"-0(F("@$"P`:`$%L;VYG50(`K0LB+``-J`0`9`]$J +M(%!/4TE8('5S=&%R6P`"$``/B@P#!R$`P&]C=&5T+6]R:65N=!<$('!IZ`S& +M*B!35E(T($%30TE)%``"4P`/,@`%84)I;F%R>2X`P"`H8FEG+65N9&EA;J(! +M8VQI='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I;;<"$"@X#C`@;W#+`\!A +M;"!2;V-K[`@0]`5HW+5II<"8`V$UI8W)OFEP/@$Q:6]N&`%=8GII<#(6``1\`4TO3%I7'0"B;'IM +M82P@;'II\+`OH#`*D"`&@1`HT``88!`MH`#Y8#!0'(`V$B;F5W +M8R*;`P$S`"=S:+```1(`#T8#8P0%!`?.``]9`P`*%@,S5VAE`P(`&@T#U`(2 +M<^8%87)E4,`4&EN9&5PJ@`E;G0B`0!$#0`/#Q!C0@42;VP-!C4*5"!7:6MI4@P# +M#!,P:&]W^``"]0``K0$#V@`"*@$A3VX_"`#W#`)@!@#S#@!0!@/-``%P`%-L +M=V%Y'!L:6-I#16":6YV;VME(&'Z#Q%C?PH# +MSA$@("C2$"4@8?L*`*$!("!AL@$!)Q`"+0`(S0`4;W,$<"DL(&ET('=P`%`@ +M9V5T(-(2`5T*`*0$-R!);FX`,BP@:8(5`9X``5$!`YL`(F5NR0$'+0``?``+ +M<0`H9&41``/&`A$LY0D"@```C0X`E@$`%@$`0``P86=A\P\!7PJ18V]R"(&5N=FER;VX/"Q%WD`,!H`(0;=@!$W): +M`P4P`@!;``)_`!%Y>P,1<#4`8F%T979E2!O9B<`H69O;&QO +M=VEN9SJ&`(%U=65N8V]D90T`\0%G>FEP(&-O;7!R97-S:6]N%0!=8GII<#(6 +M``0F`$TO3%I7'0"Q;'IM82P@;'II<"P4`2EX>B,`P0I.;W1E7-T96TN("!4:&5R92P`@&YO(&1IF4@2!I;G9O:V4@82!PZP"`=6QA2!FP`28D(``"P$`-$``#8!(71O>`0#\`)N86UE('-A +M>7,N"E)%041-15``!^@&X2!B=6YD;&4N"@I1=65S^@*@/R`@27-S=65S/U(` +MURH@:'1T<#HO+W=W=RX@!S!O3``!(`1!HN`*#9F]R(&]N9V]8!Q@@9`!P +M9&5V96QO<#P%<2P@:6YC;'6]!4!D;V-U%``!K`@!3@D`<0``.@`A;FM=`0!= +M``9S`%`@;6%I;`<"0FQIF-A="P@8@<`$G@' +M``!)`0"2"0`G`%`J(&5X84D`0',Z(%,R`U1S;6%L;!4`!#X!`%(#(6%T'`@@ +M;6'F!"!N9-`",69U;"\"!D4`$"]#"@&%`1%AG@I186-T('-@`)(@9&5M;VYS +M=')*#0`I!B=O9EX!`TD`,&-O;D,"\`(Z("!687)I;W5S(&ET96US(#,!`'T# +M0&UE(&(W`3)I0&";8"(FENU@0`Q@P`ZP4$ +MO0+P`DY%5U,@+2!H:6=H;&EG:'1S7`8PP +M`"-E)ZT``R0$`),``$X`\``N86TL(&%C;&]C86PN;30)#0/M`#`N86,7`0`" +M`!`MH@(`GP`$J```V0X(H@02+!H.`-<+`GP`,6UA:?8!(V5RK@$%<``D:6YD +M`($N:"YI;@H)+?0'(&QA5@\$NP`%A0`#M0!@"@I'=6ED\P`H($14!@32`0)U +M``&W`0)3#Q`Z&@D"N`0A+C'!#`!A#`$W`0,O`P`+``(A``2:`P,S``"(!`\T +M``L`(@`,-0`O870T``PH870S``8!!B$N,[8+$'-E"H!O=F5R=FEE=_,"`*`` +M!<`+`'$%4'=H;VQEI``#1`6$7W)E860N,RRT"A%?^`@-$0!17V1IH($',+!0$^`0!U```7`@#Y +M!`%Q``%Q"@B7```\"3-Y+C--``#O!#)E(")K`P6K``$D`!0B"PM9(&-L87-$ +M``$?"49N86QSG0`2!Q(M@@0U]!9!I +M;@IA(&YU;6+R#!=FD0<$.P''"@I9;W4@2X`L2`H8FEG+65N9&EA +MU!%C;&ET=&QE$0`"^@`$7Q:10T0M4D]-(&EMMP(0*#@.,"!O<,L#P&%L(%)O +M8VMR:61G9>\!`DD`-%I)4'4$!$``('5N,0L`)18`UA!@ +MC2H`0#E%PD( +M`0``"@*<$`5+`0!U!`\&`0("@P$#OP,"O`(/'P,8,")R9:`-`!`6$2)'`P)/ +M`,(L('=H:6-H('=I;&SK&`!P"``9!`-?`4!S(&5X+10``@(`N04$B1$""Q<# +M6A`'!L:6)R87)Y3`#08W!I;RXU+"!M=')E90D``&\`5'1AP#S +M"2P@:6YC;'5D:6YG(&AA +M``"/`/0:("=D;V,G(&1I2!I;@IA(&YU;6)E6]U(#\!8"X*"D-UFEP,A8`!'P!32],6E<=`*)L>FUA+"!L>FEP +M$P,O>'HC```9-!0`"0@!E6-A;B!C,H"4B`H9F]R-`0`A`$#,P0` +M]`-Q+"!E=&,I+F\!`/H#`*D"!B($`1<``MH`#Y8#!0'(`V$B;F5W8R*;`P$S +M`"=S:+```1(`#T8#8P0%!`);`0&)``]9`P`*%@,S5VAE`P(`V`(#U`(2<^8% +M87)E'!L86EN:6YGR0`P:&]W^``"I@<`K0$#+``" +M*@$A3VX4"1PL`P$#^``!B`E086QW87E&`0#=`2IE9(H(`D<`L$DG=F4@871T +M96UPC`?@=&\@;6EN:6UI>F4@D`!RT`!"T'`,\*%&_Y"'`I+"!I="!W<`""(&=E="!P=6S["@"D!#<@ +M26YN`#``B;`")E;LD!!RT``'P`"W$`*&1E$0`#Q@(1+/```H``(FYE +MC@(`%@$`0`!B86=A:6YS1P*18V]R0`P&@`A!MV`$38!(71O(@`%H0!A="!O;F-EA0`A3VZ0`QMEPP`"Y`(R<')O.@$! +MA0%18W1L>2W,``"."5)U='!U=.\"`&`$\0-O8FIE8W0M60!`,P``*,!!H`%,7=A;G\%$G0=#P$V`@%;`P!C +M#``S`$%D:7-K+`,`L1`0#B)A;N@"`*4'`!$# +M`EH'$"QC`$!D97-PH@``;`0!Y`,`7,N"E)%041-11(&!DD1X2!B +M=6YD;&4N"@I1=65S^@*@/R`@27-S=65S/U(`UBH@:'1T<#HO+W=W=RXX`$`N +M;W)GDP``2`$0:+@"$&:Q#S-N9V]8!Q<@3`>`(&1E=F5L;W`\!0@9$02Z$0&L +M"`$W#`!Q```Z`"%N:UT!`%T`!G,`4"!M86EL!P(P;&ESOQ`!G0`05)D!`.41 +M`.%E8$(&YDT`(Q9G5L+P(&10`0+T,*`84!$6&>"C1A8W1[$W!D96UO;G-T +M.14@;F<^``"`!094`@-)`#!C;VY#`F$Z("!687+N$V!I=&5M$0(8`&!C;VYF:6>R%A4M#``"1`"UM`Q$SM@L`$!20(&]V97)V:65W\P(`JP`% +MP`L`<04P=VAOD0(4*J0*A5]R96%D+C,L$``!^`@-$0!17V1I2#R`I!I;VYS+@H*5&B=`?("<"UL979E +M;"!D:7)E8W1O'2(`#!P=71>`H$@ +M(F-M86ME(B0#:60@=&]O;$T``E8!!NL#`2D!,2!I;DP!#VT!`3!A2!N965D?``Q;6%I]@$C97)<`05P +M`"1I;F0`\@,N:"YI;@H)+2!T96UP;&%T97-G`!%B-`(!9@$39;4`8`H*1W5I +M9/,`4"!$;V-UF04"@0$`Q0$R86QL=0`!MP&R'!L@P(#+P,`0@$"(0`$F@,#,P``B`0/-``+`"(`##4`+V%T-``,*&%T,P`& +M`0:`+C,@9VEV97/?!H!O=F5R=FEE=_,"`*``!+L%$&%Q!3!W:&^1`B,J(,0& +MA5]R96%D+C,L$```T04=91$`45]D:7-K%@`@;F30`0@^``,<``"9`!!V7P$" +MMP)P960@8V%L;!(&$'/4!D%N8V5SK0(`DP``=0`!1P`#0@9H92!!4$ESEP!S +M96YTP$2+8($4W,N-2!D5@("KP``&0,`\@"`;6%T#0#`ED' +M`W@"!R$`P&]C=&5T+6]R:65N=!<$('!I?@G&*B!35E(T($%30TE)%``"4P`/ +M,@`%84)I;F%R>2X`P"`H8FEG+65N9&EA;J(!8VQI='1L91$``OH`\0))4T\Y +M-C8P($-$+5)/32!I;;<"$2AX""!O<,L#P&%L(%)O8VMR:61G944`8DIO;&EE +M="D!`>\!`DD`-%I)4%8#!$``('5N,0LPFEP,A8`!'P!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9-!0` +M"0@!```*56-R96%TSP`!=00/!@$"`JH#`[\#`KP"#Q\#&#`B&-E<$`%`+D%!&D"42!T +M:&%T0PXQ:7)E40`!\P,!R@(@("@6!0$T!`"$`0,S!`#T`V`L(&5T8RGO"P+Z +M`P"I`@8B!`&&`0+:``^6`P4!R`-A(FYE=V,BFP,!,P`GD#`*4#(71EVP@P +M.@H*'Q$R:&ESD0]P:&5A=FEL>?P(-F5A;;4%`A$+<"X@(%1H97(T$3,@;F_B +M!P""`@/?"`"3!$$@:6XMMP^"(&UO9&EF:6-D"_``;W(@0`&EP``L!!397-I9VXE#!)EB`4`0`0!7@$X;F5WM0,`\`0`>P`#GP$` +M>P`!APD!HP`"2@P`31$B:7*"$1!I>0<280D!`@P"(2!B-PD`:@@Q86)L``8` +M_0H!#``!+`L"U!``:``".P!"96%C:#T!(79E4,`4&EN9&5PJ@`E;G0B +M`0`8"0`/#Q!C0@42;VP-!C4*5"!7:6MI4@PP:6YGR0`P:&]W40\!LP,09$X( +M`]H``BH!(4]N/P@`]PP"8`8`TQ$`4`8#S0`!<`!3;'=A>7-S""IE9(H(`D<` +M<$DG=F4@870M#0",!S!T;R`A$+)M:7IE('-T871I8U((07!O;&PV$E$N("!) +M9O4(061O;B<<$Y!E>'!L:6-I=&S9"4!V;VMEO!(!ZP`!?PH#SA$@("C2$"4@ +M8?L*`*$!("!AZ0`!)Q`"+0`(S0`4;_D(<"DL(&ET('=P`$$@9V5T&1,!70H` +MI`0W($EN;@`W+"!IG@`!40$#FP`B96[)`07L#$7`U +M`-%A=&5V97(@8FQO8VMS\```[@2X'<70@82!T:6U7`W%O8!(71O(@`%2@``XQ,A8V6%`"%/;I`#&V7#``+D`C)P`!,@ +M%1``:A``"@$`/06#;B!I=',@(D`\`!(BO0012!F4X.``P1$2(A`0!: +M""`L(E`(H"P@8V%P86)I;&D2%`8#`07Q``+S#P$_#@CV!0&7`8`@:6YD:79I +M9&P.`]L(`(4``#H2`D(``*P+`-$``#8!(71OK`TP9&%TUP``!0X6.BX!`L@) +M`#T`$F'L`@#)"@$K`#-I;B`G`0!%!3-A9&2.`AAA]PP!J0H#'@]19FER0#`',*'!L86EN:6YG"B`@(&AO=R!T;R!E>'1E;F0L +M`/(6+@H*("H@3VX@0*A2!A8V-E<#4`T6%T +M979E717`G`@82!T:6UEI0!Q;W(@;6UA<-H`065N +M=&D/`P+\`@!I`!!G!0,@:71/``FA`&%T(&]N8V6%`(M/;B!W`+$@(&)S9'1A2!B=69F97(@ +M;W+!``!E``1R`85A('-O8VME=#X#4'=I2UT;RUU"!I;G1E +M7,N"E)%041-12X`!^@&X2!B=6YD;&4N"@I1=65S^@*@ +M/R`@27-S=65S/U(`UBH@:'1T<#HO+W=W=RY,!T`N;W)GDP``2`$0:+@"@V9O +M0(1.FH`$B>7!9`G('!R;V=R86T6`G-A +M(&9U;&PME@AP9"`G=&%R)WX``P(`4W)E<&QA0@%`8G5I;($&`(H``V,``"H` +M9BH@8W!I;V,```X`"V0`(&1I:P4R96YT,`-#9F%C96H#`P(`,&5S`<``$D!`)()`"<`4"H@97AA20!`8$(&YDT`(Q9G5L+P(&10`0+T,*`84!$6$& +M"5%A8W0@`0-)`#!C;VY#`O`".B`@ +M5F%R:6]UP``7P%Q875T:&]R<\`%`1\&`?("`DT'$`J(!E!T;W`M;`P$`W8%`#`' +M`4$`$&GD!@FV`B)I;M8$`'$+`.L%!+T"\`).15=3("T@:&EG:&QI9VAT=&%R+C54`0CQ!$%A8F]U4P41]!9!I;@IA(&YU;6+R#!=F +MD0<$.P''"@I9;W4@`D09@82`;<&42H@ +M1TY5=0$"-0(F("@$"P`:`"-L;[P%`*T+(G,L$```!0L3(!$``&,`4G-P87)S +M?`(A +M`*%35E(T($%30TE)=`(!%``/,@`+$$)M$1%Y+@"Q("AB:6`@@;W#+`\!A;"!2 +M;V-K[`@0]`5HW+5II<"8`V$UI8W)OFEP/@$@:6]/$WTJ(&)Z:7`R%@`$?`%-+TQ:5QT`HFQZ;6$L +M(&QZ:7`3`R]X>B,``!DT%``)"`$```H"G!`%.@$`=00/!@$"`J\!`[\#`KP" +M#Q\#&#`B\+`OH#`*D"`&@1`HT``9L!`MH`#\@#"F$B;F5W8R*;`P$S`"=S +M:+```1(`#T8#8P0%!`?.``]9`P`*%@,S5VAE`P(`OP@#U`(2<^8%87)E`3AN97>U`P#P!`#]`@.?`0![``&'"0$K +M%0)*#`,*`P`X"`!O$!1T[A("#`(A(&(W"0","@&/&`.X%`$,`!!A#`$"U!`` +M:``".P`199P6`#T!(79E4,`4&EN9&5PJ@`E;G0B`0!$#0]D&O______ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M8U!A;F0@'1E;F1E +M9&0`!#-!0TPS`&%/;&0@5C2!O9K@"X&)E9F]R92!E=F%L=6%TI`(`V`(# +M+P("SP)@=75E;F-O<0(`M@("0P(!"@`1((,!HE)032!WFEP +M/@$Q:6]N!0%=8GII<#(6``1D`4TO3%I7'0"B;'IM82P@;'II0`&EP"0:7,@9&5S +M:6=NH@9";R!B98@%`$`$`3`$.&YE=[4#`*,$`'L``4,`4&EN9&5PJ@`B;G1_`!!R.P0` +M!``P=&EC0@4D;VZ!`02N`/``5VEK:2!E>'!L86EN:6YGB0`P:&]W^``!LP,0 +M9)8%`RP``BH!(4]NJ@`<+`,!``0$,FUA='``0&QW87E&`0#=`6!E9"!A=71> +M"&)I8V%L;'E'`+!))W9E(&%T=&5M<(P'X'1O(&UI;FEM:7IE('-T*P`"4@A0 +M<&]L;'6X`>$N("!)9B!Y;W4@9&]N)^P!`+8`\0)I8VET;'D@:6YV;VME(&$@ +M<.L`('5LO0B@96%T=7)E("AS=2\!&7,<`A!AZ0`'+0`$10<#(@("F0%P*2P@ +M:70@=W``X"!G970@<'5L;&5D(&ENI`0W($EN;@`W+"!IG@`!40$#FP`B96[) +M`07L#$7`U`-%A=&5V97(@8FQO8VMS\``` +M[@2X'<70@82!T:6U7`W%O8!(71O +M(@`%H0!A="!O;F-EA0`A3VZ0`QMEPP`"Y`(R<')O.@$!A0%18W1L>2W,``". +M"5)U='!U=.\"`&`$\0-O8FIE8W0M2!B=69F97(@)`@`90`$<@&%82!S;V-K970^`TEW:7-HN@3` +MP"`,D*`2L`,VEN(">D``,P``*,!!H`%,7=A;H@`$'0V +M!`5%`0!@```:!!!TC@7,N"E)%041-1;L&!^@& +MX2!B=6YD;&4N"@I1=65S^@*@/R`@27-S=65S/U(`URH@:'1T<#HO+W=W=RX@ +M!S!O3``!(`1!HN`*#9F]R(&]N9V]8!Q@@9`!P9&5V96QO<#P%)BP@8`]` +M9&]C=10``:P(`3<,`'$``#H`(6YK70$`70`&8N9V]O9VQE+F-O;2]P+VH`$2\Z`"!S+VD``),``6<`47-U8FUI9P!P96YH +M86YC9;L``#8"!C@`@RP@<&QE87-E+```.P``!`,`2PB!$!G0&";8"(FENU@0`I`H`ZP4![@_P!2`J($Y%5U,@+2!H:6=H;&EG:'1S7`8P +MM```Z#S`@*B"3``!.`/``+F%M+"!A +M8VQO8V%L+FTT"0T#[0`P+F%C_P```@`0+:("`)\`!*@``-D."*($$BP:#@#7 +M"P!9"Q!YR@4!]@$C97*N`05P`"1I;F0`@2YH+FEN"@DM]`<`YA,22XS +M]!0P86EL[P0R92`B:P,%JP`!)``4(@L+62!C;&%S1``!'PE&;F%L``'?`5&%M<&QE'2(`#%P=70I +M`/D#(F-M86ME(B!B=6EL9"!T;V]L30`"5@$&-0$!*0$Q(&EN3`$/;0$!,&%R +M91`"$F3:`35E"B>\`!,GK0`2.M0``),``$X`]0$N86TL(&%C;&]C86PN;30L +MX0!`92YA8RL```(`$BU4`"1T;Z@``"`!,&1IM`_`$,R!G:79E2XS!`,! +MJP(2(FL#!:L``20`Z2(@=71I;&ET>2!C;&%S1`"6:6YT97)N86QSG0`PP$2+8($4W,N-2!D5@(#I@0@:6QV`]1R;6%T-50!"/$$4&%B;W5T&@$@P"`+"!I;F-L=62*`8%H87)D+71O+3`&`J@!$G-'``!! +M`&%M;V1E$D#(F5R60<#>`('(0"P;V-T970M;W)I96X!`P!@`@$>`*%35E(T($%30TE) +M=`(!%``"4P`/,@`%,$)I;LH$`$(`H"`H8FEG+65N9&GS!(-R(&QI='1L91$` +M`OH`\0))4T\Y-C8P($-$+5)/32!I;;<"$2AX""!O<,L#P&%L(%)O8VMR:61G +M944`8DIO;&EE="D!`>\!`DD`-%I)4%8#!$``('5N3@DPFEP/@$Q:6]N&`%=8GII<#(6``1\`4TO3%I7'0"B;'IM82P@;'II?P(-F5A;;4%`A$+@"X@(%1H97)E +M+``C;F_B!P""`@/?"`"3!/("(&EN+7!L86-E(&UO9&EF:6-D"_``;W(@0`&@`23:7,@9&5S:6=N)0P298@%`$`$`;,%.&YE=[4# +M`/`$`'L``Y\!`'L``8<)`:,``DH,`PH#`#@(`+(`,71H82\)`RL`(2!B-PD` +M:@@Q86)L``8`C`H!#``!+`L"!`$`:``".P!"96%C:#T!(79E4,`4&EN +M9&5PJ@`E;G0B`0`8"0`/#Q!C0@42;VP-!C4*5"!7:6MI4@PP:6YGR0`P:&]W +M40\!LP,79)8*`BH!(4]N/P@`]PP"8`8#`P$$S0`!<`!`;'=A>48!`-T!*F5D +MB@@"1P!P22=V92!A="T-`(P'`,$/D&EN:6UI>F4@P,1<#4`T6%T979EP"`,D*`2L`,VEN("#U%F:7)S=)("`*8!$6%P$A%O61$`]@`6+G0``]D# +M`J60!`,P``*,!!H`% +M,7=A;G\%$G0=#P-%`0!@```:!!!TC@0#`',*%EF-%#A)B!P`2>`<``$D!`)()`"<`#V0: +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______]?4'(@8FQO)!$``/%/8VMS('EO=2!H86YD(&ET+@H@("!9;W5R(')E +M860@8V%L;&)A8VL@:7,@9G)E92!T;R!P87-S('1H92!L:6)R87)Y(&$@8GET +M92!A="!A('1I;64*("`@;W(@;6UA<"@`\`!E;G1I7,@<')O +M9'5C97,@8V]R`,`@(&)S9'1A&%)`$!S.B!3,@-4`0-)`#!C;VY#`O`".B`@ +M5F%R:6]UP``7P%Q875T:&]R<\`%`1\&`?("`DT'$`H5"%!T;W`M;`P$`W8% +M`#`'`4$`$&GD!@FV`B)I;O@$(FEOX08$O0+P`DY%5U,@+2!H:6=H;&EG:'1S +M7`8P'2(`#!P=71>`C`@(F,T!A$B)`,`J@2!N965D?``Q;6%I]@$C97*N`05P`"1I;F0`@2YH+FEN"@DM]`=2;&%T97-G +M`!%B-`(#<@$"M0!@"@I'=6ED\P`H($14!@32`0)U``&W`7!S>7-T96TZIPH" +MN`1U+C$@97AP;(,"`R\#`$(!`B$`!)H#`S,``(@$#S0`"P`B``PU`"]A=#0` +M#"AA=#,`!@$&(2XSM@L0<]\&@&]V97)V:65W\P(`H``%G@L`<04P=VAOD0(4 +M*J0*A5]R96%D+C,L$``!^`@-$0!17V1I``'<`%0P#'`(%>`D09BP``;<&42H@1TY5=0$"-0(F("@$"P`:`$%L;VYG4`8` +MK0LB+``-J`0`9`]$J(%!/4TE8('5S=&%R6P`"$``/B@P# +M!R$`P&]C=&5T+6]R:65N=!<$,7!I;QX`IE-64C0@05-#24D4``)3``\R``5A +M0FEN87)Y+@#`("AB:6FEP/@$Q:6]N&`%= +M8GII<#(6``1\`4TO3%I7'0"B;'IM82P@;'IID2,',@*'T'`30$`(0!`S,$`/0#8"P@971C*>\+`OH#`*D"`&@1`HT` +M`88!`MH`#Y8#!0'(`V$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0%!`?.``]9 +M`P`*%@,S5VAE`P(`-0<#U`(2<^8%87)E`3AN97>U`P#P!`#]`@.?`0![``&'"0$K%0)*#`!-$2)IE(7`+4(`E(( +M07!O;&PV$@;D%$%D;VXG[`&097AP;&EC:71LV0EB=F]K92!A^@\18W\*`\X1 +M("`HTA``=0P('`(08;(!`2<0`BT`",T`%&]S!'`I+"!I="!W<`!0(&=E="#2 +M$@%="@"D!#<@26YN``4F%P&>``%1`0.;`")E;LD!!RT``'P`"W$`*&1E$0`# +MJ@`1+%@1`H```(T.`)8!`!8!`$``,&%G8?,/`5\*D6-O!<1<_```.X'#V0:________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________________________________________]>4'1S(&%N3Q$``/`> +M9"!H86YD;&5S(&%N>2!O9B!T:&4@9F]L;&]W:6YG(&)E9F]R92!E=F%L=6%T +M$@``(`#Q#6%R8VAI=F4Z"B`@*B!U=65N8V]D960@9FEL97,4``$*`/$"('=I +M=&@@4E!-('=R87!P97(;`/$!9WII<"!C;VUPFUA+"!L>FEP+"!A;F0@>'HC```9-!0`]0<*5&AE(&QI +M8G)A"!I;G1E&-E<'0@9F]J`/$'("!E;G1R +M:65S('1H870@.`?$#;F%M +M97,L($%#3',L(&5T8RDND@"P3VQD($=.52!T87)=``2I``+*`/$$;V-T970M +M;W)I96YT960@8W!I;S4`ME-64C0@(FYE=V,B%0`G`'@G;71R964GNP!X25-/.38V,!,`6CT!X'-Y0`&EP#R`FES(&1EP`!S@`4=E@#$G.C`%0@;VYL>0H#0&UE;G2R +M``$>`P"F!`)G`S`@8F5``(!R96%D86)L9:(`07=R:70,`!!A#`$"!`$!1`0! +M.P!$96%C:"8"`98"$WE#`%!I;F1E<*H`(FYT?P`04<`L$DG +M=F4@871T96UPQ`/@=&\@;6EN:6UI>F4@2!I;G9O:V4@82!PZP`@=6PW!"!E +M85D"0"`HD`!RT`!^\%`(`!`ID!<"DL(&ET('=P`.`@9V5T +M('!U;&QE9"!I;J0$-R!);FX`-RP@:9X``5$!`YL`(F5NR0$'+0``?``+<0`H +M9&41``/&`A$L\``"@``B;F6.`@`6`0!``&)A9V%I;G-'`J!C;W)R97-P;VYD +M)P0(20`-6@`">P,Q:65SPP`!;P.A86QS;R!R961U8[D%,&4@`(&5N=FER;V[7`C%S('=N`@&@`A!MV`$3 +M6QE(&%P<')OR`,`R0@"^@#@=&\@:&%V92!M=6QT +M:7`E```A!1!V$@,`!04`N0A5(&]P96Z>`%`@(&)S9",'(75SO`$`/06#;B!I +M=',@(D#E`!(BO01&P`28D(``"P$`-$``#8!(71OFPDP9&%TUP!6=7)C +M93HN`0+("0#"`!)A[`(`R0H!*P`S:6X@)P$`3P@S861DC@(18?P(!*H!`'D& +M(6]U]P119FER0#`',*T"!S87ES+@I214%$346[!@?H!N$@ +M8G5N9&QE+@H*475E<_H"H#\@($ES8N9V]O9VQE+F-O;2]P+VH`$2\Z`"!S+VD``),``6<`47-U8FUI9P!P +M96YH86YC9;L``*8`!C@`@RP@<&QE87-E+```.P``!`,`2P7!1`GH@1` +M9W)A;18"F-%#A)B!P`2>`<``$D!`)()`"<`4"H@97AA20!`8$(&YDT`(Q9G5L+P(&10`0+T,*`84! +M$6&>"E%A8W0@H($',+!0$^`0!U```7`@#Y!`%Q``%Q"@B7```\"3-Y+C-- +M``#O!#)E(")K`P6K``$D`!0B"PM9(&-L87-$``$?"49N86QSG0`2!Q(M@@0U +M"`"X!!,B!0XR+F@BJ0`R +M:&4*7PP0(+`)`/H``!0`!.D&`W((`G\"$&T:%P/[`$(N("!0B@FS;&5T('5S +M"FMN;W>5$P`P%&!E\6`2T5`A``#XH,`P`""(&EN'!L86EN3`1!F+``0'1E;J`*%35E(T($%30TE)=`(!%``"4P`/,@`%84)I +M;F%R>2X`H"`H8FEG+65N9&GS!(-R(&QI='1L91$``OH`\0))4T\Y-C8P($-$ +M+5)/32!I;;<"@"AW:71H(&]P^@7`86P@4F]C:W)I9&=E10!B2F]L:65T*0$! +M[P$"20`T6DE05@,$0`"0=6YC;VUPB,``!DT +M%``)"`&58V%N(&-R96%TSP`!=00/!@$"`NP"`[\#`KP"#Q\#&#`B&-E<$`%`+D%!&D" +ML"!T:&%T(')E<75IE@4G87C*`B`@*'T'`30$`(0!`S,$`/0#<2P@971C*2YO +M`0#Z`P"I`@8B!`$7``+:``^6`P4!R`-A(FYE=V,BFP,!,P`G?P(-F5A;;4%`A$+@"X@(%1H97)E+``C +M;F_B!P""`@/?"`"3!/("(&EN+7!L86-E(&UO9&EF:6.M"/,";W(@U`P#P!`![ +M``.?`0![``&'"0&C``)*#`,*`P`X"`"R``$>`P"F!`(,`B$@8C<)<7)E861A +M8FP`!@","@$,``$L"P($`0!H``([`$)E86-H/0$A=F5S`Q-Y0P!0:6YD97"J +M`"5N="(!`!@)4&%R=&EC0@4D;VZ!`02N`$17:6MI4@PP:6YGR0`P:&]WFPP" +MI@<'E@H"*@$A3VX_"`#W#`)X!@$""B-N9/@``8@)8V%L=V%YD`!RT`!"T'`,T`%&^5"'`I+"!I="!W<`!Q(&=E="!P +M=9P-(&ENI`0W($EN;@`W+"!IG@`(FP`B96[)`02UV```S#`#W +M"!%IAP8`A`!P96YV:7)O;M<",7,@=Y`#`:`"$&W8`1-R6@,%,`(`6P`"?P`1 +M>7L#$7`U`-%A=&5V97(@8FQO8VMS\```[@`A$)P`$`B0`P;6%K>0"0:7,@ +M97-P96-I;@0!T`$"J@$`.@@P.B`BDPH!#A$)V@T3(KD"`-X.(F%NZ`(`I0<& +M-`H0+&,`0&1EF-%#A)B!P`2>`<``$D!`)() +M`"<`02H@97@;$T!S.B!3,@-4'2(`"%P=6<0,"`B8S0&%"*\&3EO;VQ-``)6`08U`0"4``"P"@&.`0]M +M`0$`(`T!$!H!V@$T90HGL``C92>O&0,D!`"3``!.``]D&O______________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________5E`@("!T +M;SL1``#R-B!B92!R96%D(&]R('=R:71T96X@=&\@86YY(&1A=&$@7,N"E)%041-15``1"!L:6)M`=%B=6YD;&4N"@I1=65SK@"@/R`@27-S=65S +M/U(`UBH@:'1T<#HO+W=W=RXX`$`N;W)GDP``2`$Q:&]MIP"`(&]N9V]I;F8$(&YD +MT`(Q9G5L+P(&10!1+VUI;FF%`1%AXP%186-T('-@`+`@9&5M;VYS=')A=+\`!,GK0`#)`0`DP``3@#U`2YA;2P@86-L;V-A;"YM-"SA +M`$!E+F%C_P```@`0+:("`)\`!*@`#*($LBP@;VYL>2!N965D?``Q;6%I]@$C +M97*N`05P`"1I;F0`@2YH+FEN"@DM]`=2;&%T97-G`!%B-`(!9@$39;4`8`H* +M1W5I9/,`*"!$5`8$T@$"=0`!MP%P!1%E^P,`\@"`;6%T``&I`5"`"X!!,B?P(R+F@BJ0`R:&4*7PP0(+`)`'4!`!0`!.D&`W((`G\"-&UO +M2X`P"`H8FEG+65N9&EA;J(!8VQI='1L91$``OH`\0))4T\Y-C8P +M($-$+5)/32!I;;<"$"@X#C`@;W#+`\!A;"!2;V-K[`@0]`5HW+5II<"8` +MV$UI8W)OFEP/@$Q:6]N +M&`%=8GII<#(6``1\`4TO3%I7'0"B;'IM82P@;'II\+`OH#`*D" +M`&@1`HT``88!`MH`#Y8#!0'(`V$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0% +M!`?.``]9`P`*%@,S5VAE`P(`&@T#U`(2<^8%87)E`3AN97>U`P#P!`#]`@.?`0![ +M``&'"0&C``)*#`!-$2)I7-S""IE9(H(`D<`L$DG=F4@ +M871T96UPC```%1`0.;`")E;LD!!RT``'P`"W$`*&1E$0`#Q@(1+.4)`H```(T. +M`)8!`!8!`$``,&%G8?,/`5\*D6-O7L#$7`U`&)A +M=&5V97)X%Q%S\```[@2X'$'1[%R%I;5<#<6]R(&UM87`I`0!>$P'Y%@*Y%P"V`A!G +MPA<0:2(3`2(`!4H``.,3(6-EA0`A3VZ0`QMEPP`"Y`(R<')O.@$!A0$`FA<1 +M+408DF5D(&]U='!U=.\"`&`$\0-O8FIE8W0M$E33SDV-C`3 +M`+0W+5II<"!AFUA+"!L>FEP+"!A;F0@>'HC`,$*3F]T97,@86)O=724 +M`')L:6)R87)YT0#P+G1E8W1U2!S +M=')E86TM;W)I96YT960@4,`4&EN9&5PJ@`B;G1_`$%R92!A!`"4=&EC;&5S(&]N@0$#=@+P +M`2!7:6MI(&5X<&QA:6YI;F?)`#!H;W?X``+U``$N("!)9B!Y +M;W4@9&]N)^P!`+8`\0)I8VET;'D@:6YV;VME(&$@<.L`@'5L87(@9F5A60)` +M("AS=2\!&7,<`A!AZ0`'+0`'!@,`@`$"F0%P*2P@:70@=W``\``@9V5T('!U +M;&QE9"!I;BX^`"=);FX`-RP@:9X``5$!`YL`(F5NR0$'+0``/@`+<0`H9&41 +M``/&`A$L\``"@``B;F6.`@`6`0!``&)A9V%I;G-'`J!C;W)R97-P;VYD)P0( +M20`-6@`">P,Q:65SPP`!;P.P86QS;R!R961U8V6;`C!E('.%`2-O9H@!`+,! +M$"UV`&%E9"!B:6X]`"`@:2P$@"!E;G9IP,1<#4`T6%T979E8!(71O(@`%2@!A="!O +M;F-EA0`A3VZ0`QMEPP`"Y`(R<')O.@$!A0%18W1L>2W,`))E9"!O=71P=73O +M`@!@!/$#;V)J96-T+7-T>6QE(&%P<')OR`,`H`4"^@#@=&\@:&%V92!M=6QT +M:7`E``.E`P(!!`!;!E4@;W!E;IX`L2`@8G-D=&%R('5SO`$`/06#;B!I=',@ +M(D#E`!(BR`-&P"`*`'`2L`,VEN("8<``J,!!H`%,7=A;H@`$'0V +M!`5%`0!@`!!IA0(`C@%EB!$!G&%)`$!S.B!3,@-4`0-)`#!C;VY#`O`".B`@5F%R:6]UP``7P%V875T:&]R,&`4D!A69I9W5R92`M#``"1`"U'2(`")P==8-(")C-`81 +M(B0#`#@,*6]L30`"5@$&ZP,!*0$`%@D`C@$/;0$!`*(&('5SW0H`V@$T90HG +ML``C92>M``,D!`"3``!.`/``+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C%P$` +M`@`0+:("`)\`!*@``-D."*($$BP:#@#7"P)\`#%M86GV`2-EPH"MP(29:`,`!(&0'-E<77J"!!S"P4!/@$`=0``%P(` +M^00!<0`!<0H(EP``/`DS>2XS30``[P0R92`B:P,%JP`!)``4(@L+62!C;&%S +M1``!'PE&;F%L"`"X!!,B!0XR+F@BJ0`R:&4*7PP0(+`)`/H``!0`!.D&`W((`G\"-&UO +M5$P`P%&!E+``-J`0`9`[$J(%!/4TE8('5S=+`1!!``#XH,`P%\``(Q`%9O +M8W1E=*\4`&`"`1X`H5-64C0@05-#24ET`@$4``\R``L00FT1$7DN`+$@*&)I +M9RUE;F1I8=018VQI='1L91$``OH`!%\6D4-$+5)/32!I;;<"$"@X#C`@;W#+ +M`\!A;"!2;V-KC2H`0#E%PD(`0``"@*<$`5+`0!U!`\&`0("@P$#OP," +MO`(/'P,8,")R9:`-`!`6$2)'`P)/`,(L('=H:6-H('=I;&SK&`!P"`###P-? +M`4!S(&5X+10``@(`N04$B1$""Q<#6A4P`T&-P:6\N-2P@;71R964)``!O`%1T87(N-;<`PB!D +M971A:6QE9"!I;E(`D&EO;B!A8F]U=$T`('-EN`"#<&]P=6QA#0#46-H86YG?@$W +M;6%T(0"P;V-T970M;W)I96X!`P!@`@$>`*%35E(T($%30TE)=`(!%``"4P`/ +M,@`%84)I;F%R>2X`P"`H8FEG+65N9&EA;J(!8VQI='1L91$``OH`\0))4T\Y +M-C8P($-$+5)/32!I;;<"@"AW:71H(&]PRP/`86P@4F]C:W)I9&=E10!B2F]L +M:65T*0$![P$"20`T6DE05@,$0`#`=6YC;VUPB,``!DT%``)"`&58V%N(&-R96%TSP`!=00/!@$"`J\!`[\#`KP"#Q\# +M&,$B!S>7-T96TN("!4:&5R92P`(VYOX@<`@@(#WP@`DP3R`B!I;BUP;&%C92!M +M;V1I9FECK0CS`F]R(')A;F1O;2!A8V-E0`&@`3R`FES(&1EP`#P`!APD!HP!4(&]N;'D* +M`P`X"`"R``$>`P"F!`(,`B$@8C<)<7)E861A8FP`!D%W48!`-T!*F5DB@@"1P"P22=V92!A='1E +M;7",!^!T;R!M:6YI;6EZ92!S=+4(`E((4'!O;&QU(@=1+B`@26;U"$!D;VXG +MU@7L#$7`U`-%A=&5V +M97(@8FQO8VMS\```[@2X'<70@82!T:6U7`P!K"S%M87#X`C!E;G21!@/0`@%1 +M`T!G:79EY@$A=&\B``6A`&%T(&]N8V6%`"%/;I`#&V7#``+D`C)P@``P0&%82!S;V-K970^ +M`TEW:7-HN@0!)@]P=71I;&ET>7,"!8P``#\``TP/4"!E87-Y3@Y1=7-E("(A +M`0!:""`L(E`(<"P@8V%P86)!``'V`@0#`07Q`&%E($%027.W!`CV!0&7`8`@ +M:6YD:79I9&P.`]L(`(4``A4&`$(``'(+`-$``#8!(71OK`TP9&%TUP``!0X6 +M.BX!`L@)`#T`$F'L`@#)"@$K`#-I;B`G`0"5"S-A9&2.`AAA]PP!UP<#'@]1 +M9FER0"0:7,@ +M97-P96-I;@0!T`$"J@$`.@@P.B`BDPH!#A$)V@T3(KD"`-X.(F%NZ`(`I0<` +M$0,"6@<0+&,`0&1E8N9V]O +M9VQE+F-O;2]P+VH`$2\Z`"!S+VD``),``6<`47-U8FUI9P!P96YH86YC9<\` +M`*8`!C@`,BP@<-H0`BP``#L```0#`$L'`1<)X65S="!V:6$@1VET2'5BP@`" +MD`"A7!1`GD1(`\A$`%@)S82!F=6QL +M+98(F-%#A)B!P`2>`<` +M`$D!`)()`"<`02H@97@;$T!S.B!3,@-4P``7P%C875T:&]R:1``EPT!\@(`P1,2 +M+NT/4'1O<"UL#`0#Q0P`,`0&";8""',5`.L%`>X/\`4@*B!.15=3 +M("T@:&EG:&QI9VAT<]P`,')E8]D4`C$%`Z`"DD-/4%E)3D<@+0P%`$(4`,H' +M(61O7P8!AP4`S@#`*B!)3E-404Q,("T@9`HQ86QLCP0!#0``BA8`OP`"*0`# +M0`41+3P``5X1`A@`8&-O;F9I9[(6%2T,``)$`+5S8W)I<'0L('-E96<``"@% +M`ED6`F,(@2H@0TUA:V5,U`0Q='ATB``A<'5G$#`@(F,T!A$B)`,`.`PI;VQ- +M``)6`0;K`P$I`0`6"0".`0]M`0$`(`T0=3T3`A`7)`HGL``C92>M``,D!`"3 +M``!.`/``+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C_P```@`0+60"`)\`!*@` +M`-D."*($$BP:#@#7"P!9"Q!YR@4!]@$C97*N`05P`"1I;F0`@2YH+FEN"@DM +M]`<`YA,2\%#V0:____________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________]G4&%N(&ES-1$``/`02#R`I!I;VYS+@H*5&B=`?("<"UL979E;"!D:7)E8W1O'2(`#!P=71>`H$@(F-M86ME(B0#:60@ +M=&]O;$T``E8!!NL#`2D!,2!I;DP!#VT!`3!A2!N965D?``Q;6%I]@$C97)<`05P`"1I;F0`\@,N:"YI +M;@H)+2!T96UP;&%T97-G`!%B-`(!9@$39;4`8`H*1W5I9/,`4"!$;V-UF04" +M@0$`Q0$R86QL=0`!MP&R'!L@P(#+P,`0@$" +M(0`$F@,#,P``B`0/-``+`"(`##4`+V%T-``,*&%T,P`&`0:`+C,@9VEV97-X +M!H!O=F5R=FEE=_,"`*``!+L%$&%Q!3!W:&^1`B,J(,0&A5]R96%D+C,L$``` +MT04=91$`45]D:7-K%@`@;F30`0@^``,<``"9`!!V7P$"MP)P960@8V%L;!(& +M$'/4!D%N8V5SK0(`DP``=0`!1P`#0@9H92!!4$ESEP!S96YTP$2+8($ +M4W,N-2!D5@("KP``&0,`\@#$;6%T=&%R+C54`0CQ!$%A8F]U4P4@P`3+/('`(H!@6AA``%4!%#0#`ED'`W@"!R$`L&]C=&5T +M+6]R:65N`0,`8`(!'@"A4U92-"!!4T-)270"`10``E,`#S(`!6%":6YA`@@;W#+`\!A;"!2;V-KFEP/@$Q:6]N&`%=8GII<#(6 +M``1\`4TO3%I7'0"B;'IM82P@;'II`3AN97>U`P#P!`![``.?`0![``&'"0&C``)* +M#`!-$2)IF4@``%1`0.;`")E;LD!!RT``'P`"W$`*&1E$0`#Q@(1+/```H```(T.`)8! +M`!8!`$``,&%G82X.`?$)D6-OP,1<#4`T6%T979E$P$/`P$W%0%1`T!G:79E +MY@$A=&\B``5*``#C$R%C984`(4]ND`,;9<,``N0",G!R;SH!`84!46-T;'DM +MS`"2960@;W5T<'5T[P(`8`3Q`V]B:F5C="US='EL92!A<'!R;\@#`/D4`OH` +MT'1O(&AA=F4@;75L=&G#$P2I``(!!`"Y"%4@;W!E;IX`$R`5$`!J$``*`1%I +M(0AC:71S(")`/``2(KT$$7,P#@)C!098`&!I='-E;&93`5!R96%D+^8`8'1E +M;B!U@``S0*%82!S;V-K970^`TEW:7-HN@0! +M)@\#60\`7,N"B05 +M$6:X#01/&0.A&$0N"@I1$19`/R`@29X9(',_4@`1*@49=CHO+W=W=RXX`$`N +M;W)GDP``2`$0:+@"`%<`0V]N9V]8!Q<@3`<@(&18%B!O<#P%"!D1!+H1`:P( +M`3<,`'$``#H`(&YK-`$!P0`&7,@9&5T96-T960@875T;VUA +M=&EC86QL>4<`L$DG=F4@871T96UP(@#P(71O(&UI;FEM:7IE('-T871I8R!L +M:6YK('!O;&QU=&EO;BX@($EF('EO=2!D;VXG=*@``+8`\"1I8VET;'D@:6YV +M;VME(&$@<&%R=&EC=6QA!E('-O;64@=71I;&ET>3X`!8P``+$!\09P2!D8737`%9UP",B!O9BL`,VEN("X +M`0!V``*4`0```P&^``7+`0#3``.C`0:`!3%W86Z(`!!T-@0#-@(!6P,`'P$` +MN@!!9&ES:RP#`\0!N6-O;G9E;FEE;F-EP`$`B0`P;6%K>0"0:7,@97-P96-I +M;@0!T`$"J@'S!TYO=&4Z(")P87@@:6YT97)C:&%N9V6?!1,BN0(@;&P\`0+H +M`A!DO@$`_04!C080+&,`0&1E0(1.FH`$B>7!9`G('!R;V=R86T6`G-A(&9U;&PME@AP9"`G=&%R)WX``P(` +M4W)E<&QA0@%`8G5I;($&`(H``V,``"H`9BH@8W!I;V,```X`"V0`(&1I:P4R +M96YT,`-#9F%C96H#`P(`,&5S`<``$D! +M`)()`"<`4"H@97AA20!`8$ +M(&YDT`(Q9G5L+P(&10`0+T,*`84!$6$&"5%A8W0@`0-)`#!C;VY#`O`".B`@5F%R:6]UP``7P%Q875T:&]R<\`%`1\& +M`?("`DT'$`J(!E!T;W`M;`P$`W8%`#`'`4$`$&GD!@FV`B)I;M8$`'$+`.L% +M!+T"\`).15=3("T@:&EG:&QI9VAT=&%R+C54`0CQ!$%A8F]U4P41 +M]!9!I;@IA(&YU;6+R#!=FD0<$.P''"@I9;W4@`D09@82`;<&42H@1TY5=0$"-0(F("@$"P`:`"-L;[P% +M`*T+(G,L$```!0L3(!$``&,`4G-P87)S?`(A`*%35E(T($%30TE)=`(!%``/,@`+ +M$$)M$1%Y+@"Q("AB:6`@@;W#+`\!A;"!2;V-K[`@0]`5HW+5II<"8`V$UI +M8W)OFEP/@$@:6]/$WTJ +M(&)Z:7`R%@`$?`%-+TQ:5QT`HFQZ;6$L(&QZ:7`3`R]X>B,``!DT%``)"`$` +M``H"G!`%.@$`=00/!@$"`J\!`[\#`KP"#Q\#&#`B\+`OH#`*D"`&@1`HT` +M`9L!`MH`#\@#"F$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0%!`?.``]9`P`* +M%@,S5VAE`P(`OP@#U`(2<^8%87)E +M`3AN97>U`P#P!`#]`@.?`0![``&'"0$K%0)*#`,*`P`X"`!O$!1T[A("#`(A +M(&(W"0","@&/&`.X%`$,`!!A#`$"U!``:``".P`199P6`#T!(79E4,` +M4&EN9&5PJ@`E;G0B`0!$#0%Y&0!"!1)O;`T&L`L/9!K_________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_________________________________________________V50=',Z"B`P +M$0``\0T@*B!'3E4@=&%R(&9O`*935E(T($%30TE)%``"8P`/,@`%84)I;F%R>2X`\P<@*&)I +M9RUE;F1I86X@;W(@;&ET=&QE$0`"^@#P'TE33SDV-C`@0T0M4D]-(&EM86=E +MFEP/@$Q:6]N1`!=8GII<#(6``1D`4TO3%I7'0"B +M;'IM82P@;'IID#`*4#`.<#]A)U2!S=')E86VU!>!S>7-T96TN("!4:&5R92P`D&YO(&1I +M-R86YD +M;VT@86-C97-S+GD`!I<`D&ES(&1EU +M`P"C!`![``'.`!!VFP0`-0<2$N("!)9B!Y;W4@ +M9&]N)^P!`+8`\0)I8VET;'D@:6YV;VME(&$@<.L`('5LO0B@96%T=7)E("AS +M=2\!&7,<`A!AZ0`'+0`$10<#(@("F0%P*2P@:70@=W``X"!G970@<'5L;&5D +M(&ENI`0W($EN;@`W+"!IG@`!40$#FP`B96[)`07L#$7`U`-%A=&5V97(@8FQO8VMS\```[@2X'<70@82!T:6U7`W%O8!(71O(@`%H0!A="!O;F-EA0`A3VZ0 +M`QMEPP`"Y`(R<')O.@$!A0%18W1L>2W,``"."5)U='!U=.\"`&`$\0-O8FIE +M8W0M2!B=69F97(@ +M)`@`90`$<@&%82!S;V-K970^`TEW:7-HN@3`P" +M`,D*`2L`,VEN(">D``,P``*,!!H`%,7=A;H@`$'0V!`5%`0!@```:!!!TC@7,N"E)%041-1;L&!^@&X2!B=6YD;&4N"@I1=65S^@*@ +M/R`@27-S=65S/U(`URH@:'1T<#HO+W=W=RX@!S!O3``!(`1!HN`*#9F]R +M(&]N9V]8!Q@@9`!P9&5V96QO<#P%)BP@8`]`9&]C=10``:P(`3<,`'$``#H` +M(6YK70$`70`&8N9V]O9VQE+F-O;2]P+VH` +M$2\Z`"!S+VD``),``6<`47-U8FUI9P!P96YH86YC9;L``#8"!C@`@RP@<&QE +M87-E+```.P``!`,`2PB!$!G0&";8"(FENU@0`I`H`ZP4$ +MO0+P`DY%5U,@+2!H:6=H;&EG:'1S7`8PM```Z#S`@*B"3``!.`/``+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C_P`` +M`@`0+:("`)\`!*@``-D."*($$BP:#@#7"P!9"Q!YR@4!]@$C97*N`05P`"1I +M;F0`@2YH+FEN"@DM]`<`YA,22XS]!0P86EL[P0R92`B:P,%JP`!)``4 +M(@L+62!C;&%S1``!'PE&;F%L``'? +M`5&%M<&QE('!R;V=R86US('1H870@>6]U(&UA>2!F:6YD('5S969U +M;"X*("`@*C``\@=S+VUI;FET87(Z(&$@8V]M<&%C="!S2P#09&5M;VYS=')A +M=&EN9SX`XR!O9B!L:6)AM`_`$ +M,R!G:79E2XS!`,!JP(2(FL#!:L``20`Z2(@=71I;&ET>2!C;&%S +M1`"6:6YT97)N86QSG0!@P$2+8($4W,N-2!D5@(#I@0@:6QV`]1R +M;6%T-50! +M"/$$4&%B;W5T&@$@P"`+"!I;F-L=62*`8%H +M87)D+71O+3`&`J@!$G-'``!!`&%M;V1E$D#(F5R60<#>`('(0"P;V-T970M;W)I96X! +M`P!@`@$>`*%35E(T($%30TE)=`(!%``"4P`/,@`%,$)I;LH$`$(`H"`H8FEG +M+65N9&GS!(-R(&QI='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I;;<"$2AX +M""!O<,L#P&%L(%)O8VMR:61G944`8DIO;&EE="D!`>\!`DD`-%I)4%8#!$`` +M('5N3@DPFEP/@$Q:6]N&`%=8GII<#(6``1\`4TO +M3%I7'0"B;'IM82P@;'II?P( +M-F5A;;4%`A$+@"X@(%1H97)E+``C;F_B!P""`@/?"`"3!/("(&EN+7!L86-E +M(&UO9&EF:6-D"_``;W(@0`&@`23:7,@9&5S:6=N +M)0P298@%`$`$`;,%.&YE=[4#`/`$`'L``Y\!`'L``8<)`:,``DH,`PH#`#@( +M`+(`,71H82\)`RL`(2!B-PD`:@@Q86)L``8`C`H!#``!+`L"!`$`:``".P!" +M96%C:#T!(79E4,`4&EN9&5PJ@`E;G0B`0`8"0`/#Q!C0@42;VP-!C4* +M5"!7:6MI4@PP:6YGR0`P:&]W40\!LP,79)8*`BH!(4]N/P@`]PP"8`8#`P$$ +MS0`!<`!`;'=A>48!`-T!*F5DB@@"1P!P22=V92!A="T-`(P'`,$/D&EN:6UI +M>F4@P,1<#4`T6%T979EP" +M`,D*`2L`,VEN("#U%F:7)S=)("`*8!$6%P +M$A%O61$`]@`6+G0``]D#`J60!`,P``*,!!H`%,7=A;G\%$G0=#P-%`0!@```:!!!TC@0# +M`',*%EF-%#A)B!P`2 +M>`<``$D!`)()`"<`!A\:,#H@4S(##V0:____________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________________________________]J4'(@71E(&%T +M(&$@=&EM90H@("!O2UB;&]C:V5D(&]U='!U="X*"B`J(%1H92!O8FIE8W0M +M'1E;G-I;VZ*``,<```J`#!E;&93`5!R96%D+^8`EG1E;B!U2!B=69F97(@;W+!``!E``1R`3!A(',K`5%T+"!I9@(!8'=I +M2UT;RUU`@#1```V`:!T;R!A;GD@9&%TUP!6=7)C93HN`5%C`@&^``7+`0#3``.C`4,N("!)I`$A86Z(`!)T70`#10$`8``0 +M:84"86\@9&ES:RP#`\0!N6-O;G9E;FEE;F-EP`$`B0`P;6%K>0#1:7,@97-P +M96-I86QL>=`!`JH!\P].;W1E.B`B<&%X(&EN=&5R8VAA;F=E(&9O7,N"E)%041-12X``$0$!&T!T6)U;F1L92X*"E%U97/Z`J`_("!)0(1.FH`$B>7!1`G'@9`9W)A;18"\`9A(&9U +M;&PM9F5A='5R960@)W1A`<``$D!0'-U8V@G`%`J(&5X84D`0',Z(%,R +M`U1S;6%L;!4`!#X!`%(#(6%T(`8@;6'F!"!N9-`",69U;"\"!D4`42]M:6YI +MA0$18>,!46%C="!S8`"P(&1E;6]N0&";8"(FEN^`0B:6_A!@2]`O`"3D574R`M(&AI9VAL +M:6=H='-M``,D!`"3``!. +M`/4!+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_```"`!`MH@(`GP`$J``,H@2R +M+"!O;FQY(&YE961\`#%M86GV`2-E'!L@P(#+P,`0@$"(0`$F@,#,P``B`0/-``+`"(`##4` +M+V%T-``,*&%T,P`&`08A+C.V"Q!SWP:`;W9E"P!Q!3!W +M:&^1`A0JI`J%7W)E860N,RP0``'X"`T1`%%?9&ES:Q8``GX'`X(%`3X``QP` +M`)D``7L*`K<"$F6@#`!;!!!SU`80;A$,`-8"`),``'4``!<"`/D$`7$``7$* +M")<``#P),WDN,TT``.\$,F4@(FL#!:L``20`%"(+"UD@8VQA``'<`%`D09BP``;<&42H@1TY5=0$"-0(F("@$"P`:`$%L +M;VYG4`8`K0LB+``-J`0`9`]$J(%!/4TE8('5S=&%R6P`" +M$``/B@P#!R$`P&]C=&5T+6]R:65N=!<$,7!I;QX`IE-64C0@05-#24D4``)3 +M``\R``5A0FEN87)Y+@#`("AB:6B,``!DT +M%``)"`$```H"G!`%.@$`=00/!@$"`J\!`[\#`KP"#Q\#&,$B&-E<$`%`+D%!(D142!T +M:&%T0PX`TQ,`40`%Z1(P?P(-F5A;;4%`A$+!8@40&ES(&[6$C%R96,P$0/?"`"3 +M!$$@:6XM`@^"(&UO9&EF:6/E#/<`;W(@`3AN97>U`P#P!`#]`@.?`0![``&'"0$K%0)*#`!-$2)I +ME(7`+4(`E((07!O;&PV$@;D%$%D;VXG[`&097AP;&EC:71LV0EB=F]K92!A +M^@\18W\*`\X1("`HTA``=0P('`(08;(!`2<0`BT`",T`%&]S!'`I+"!I="!W +M<`!0(&=E="#2$@%="@"D!#<@26YN``4F%P&>``%1`0.;`")E;LD!!RT``'P` +M"W$`*&1E$0`#J@`1+%@1`H```(T.`)8!`!8!`$``,&%G8?,/`5\*D6-O"(&5N=FER;VX/"T!W:&5R+Q9`870@;=@!$W): +M`P4P`@!;``)_`!%Y>P,1<#4`8F%T979EFEP(&-O;7!R97-S:6]N%0!=8GII<#(6``0F +M`$TO3%I7'0#_`VQZ;6$L(&QZ:7`L(&%N9"!X>B,``!DT%`#U!PI4:&4@;&EB +M2!C86X@8W)E873/`+%S(&EN(&%N>2!O9N8`8&9O;&QO=_0``21E9-T` +M$2E%``"=``#5`85"4T0@)V%R)U(``1X`>"=M=')E92>[`'A)4T\Y-C8P$P!: +M-RU::7`Y`#9805(1`$,*5VAE`P(`Y`$#U`(AT!X'-Y +M0`&EP#R`FES(&1E +MP`!S@`4=E@#$G.C +M`%0@;VYL>0H#0&UE;G2R``$>`P"F!`)G`S`@8F5``(!R96%D86)L9:(`07=R +M:70,`!!A#`$"!`$!1`0!.P!$96%C:"8"`98"$WE#`%!I;F1E<*H`(FYT?P`0 +M)`#!H;W?X +M``+U``".!`,L``(J`2%/;JH`'"P#`0/9`@)P`$!L=V%Y1@$`W0'R`65D(&%U +M=&]M871I8V%L;'E'`+!))W9E(&%T=&5M<,0#X'1O(&UI;FEM:7IE('-T*P"P +M(&QI;FL@<&]L;'6X`>$N("!)9B!Y;W4@9&]N)^P!`+8`\0)I8VET;'D@:6YV +M;VME(&$@<.L`('5L-P0@96%9`D`@*'-U+P$9``%1`0.; +M`")E;LD!!RT``'P`"W$`*&1E$0`#Q@(1+/```H``(FYEC@(`%@$`0`!B86=A +M:6YS1P*@8V]RP,1<#4`T6%T979E2!B=69F97(@)`@`90`$<@&%82!S;V-K +M970^`TEW:7-HN@3`P"`,,)`2L`,VEN("0#`',*T"!S87ES +M+@I214%$346[!@?H!N$@8G5N9&QE+@H*475E<_H"H#\@($ES8N9V]O9VQE+F-O;2]P+VH`$2\Z`"!S+VD` +M`),``6<`47-U8FUI9P!P96YH86YC9;L``*8`!C@`@RP@<&QE87-E+```.P`` +M!`,`2P7!1`GH@1`9W)A;18"F-%#A)B!P`2>`<``$D!`)()`"<` +M4"H@97AA20!`8$(&YDT`(Q +M9G5L+P(&10`0+T,*`84!$6&>"E%A8W0@H($',+!0$^`0!U```7`@#Y!`%Q +M``%Q"@B7```\"3-Y+C--``#O!#)E(")K`P6K``$D`!0B"PM9(&-L87-$``$? +M"49N86QSG0`2!Q(M@@0U +M"`"X!!,B!0XR+F@BJ0`R:&4*7PP0(+`)`/H``!0`!.D&`W((`G\"$&T:%P/[ +M`$(N("!0B@FS;&5T('5S"FMN;W>5$P`P%&!E2X`L2`H8FEG+65N +M9&EAU!%C;&ET=&QE$0`"QP`$7Q:10T0M4D]-(&EMMP(0*#@.,"!O<,L#P&%L +M(%)O8VMR:61G9>\!`DD`#QX78P\+%P#036EC84`X"!S8W)I<'0* +M"D=U:61E@@"01&]C=6UE;G1A>`""(&EN'!L86EN3`1!F+``P'1E;J`*%35E(T($%30TE)=`(!%``"4P`/,@`%84)I;F%R>2X` +MH"`H8FEG+65N9&GS!(-R(&QI='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I +M;;<"@"AW:71H(&]P^@7`86P@4F]C:W)I9&=E10!B2F]L:65T*0$![P$"20`T +M6DE05@,$0`"0=6YC;VUPB,``!DT%``)"`&5 +M8V%N(&-R96%TSP`!=00/!@$"`NP"`[\#`KP"#Q\#&#`B&-E<$`%`+D%!&D"L"!T:&%T +M(')E<75IE@4G87C*`B`@*'T'`30$`(0!`S,$`/0#<2P@971C*2YO`0#Z`P"I +M`@8B!`$7``+:``^6`P4!R`-A(FYE=V,BFP,!,P`G?P(-F5A;;4%`A$+@"X@(%1H97)E+``C;F_B!P"" +M`@/?"`"3!/("(&EN+7!L86-E(&UO9&EF:6.M"/,";W(@U`P#P!`![``.?`0![ +M``&'"0&C``)*#`,*`P`X"`"R``$>`P"F!`(,`B$@8C<)<7)E861A8FP`!@", +M"@$,``$L"P($`0!H``([`$)E86-H/0$A=F5S`Q-Y0P!0:6YD97"J`"5N="(! +M`!@)4&%R=&EC0@4D;VZ!`02N`$17:6MI4@PP:6YGR0`P:&]WFPP"I@<'E@H" +M*@$A3VX_"`#W#`)X!@$""B-N9/@``8@)8V%L=V%YD`!RT`!"T'`,T`%&^5"'`I+"!I="!W<`!Q(&=E="!P=9P-(&EN +MI`0W($EN;@`W+"!IG@`(FP`B96[)`02UV```S#`#W"!%IAP8` +MA`!P96YV:7)O;M<",7,@=Y`#`:`"$&W8`1-R6@,%,`(`6P`"?P`1>7L#$7`U +M`-%A=&5V97(@8FQO8VMS\```[@`A$)P`$`B0`P;6%K>0"0:7,@97-P96-I +M;@0!T`$"J@$`.@@P.B`BDPH!#A$)V@T3(KD"`-X.(F%NZ`(`I0<&-`H0+&,` +M0&1EF-%#A)B!P`2>`<``$D!`)()`"<`02H@ +M97@;$T!S.B!3,@-4'2( +M`"%P=6<0,"`B8S0&%"*\&3EO;VQ-``)6`08U`0"4``"P"@&.`0]M`0$`(`T! +M$!H!V@$T90HGL``C92>O&0,D!`"3``!.`(\N86TL(&%C;&0:____________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________________________________________________]J4&%N +M>2!D,!$``/`<871A('-O=7)C93H@(%EO=2!C86X@8W)E871E"B`@(&$@8FQO +M8VL@;V8@9"L`\!YI;B!M96UO2!E87-Y+@H*("H@3F]T93H@(G!A +M>"!I;G1E'1E;F1E9#@!`B(` +M$"QC`$!D97-PWP!`=VAA=)8`\`,@;F%M92!S87ES+@I214%$3450`$0@;&EB +M;0'18G5N9&QE+@H*475E`<``$D!0'-U8V@G`%`J(&5X84D`0',Z(%,R`U1S +M;6%L;!4`!#X!`%(#(6%T?`0@;6'F!"!N9-`",69U;"\"!D4`42]M:6YIA0$1 +M8>,!46%C="!S8`"A(&1E;6]NM``,D +M!`"3``!.`/4!+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_```"`!`MH@(`GP`$ +MJ``,H@2R+"!O;FQY(&YE961\`#%M86GV`2-E7-T96TZ<`<"N`1U+C$@97AP;(,"`R\#`$(!`B$`!)H#`S,``(@$#S0` +M"P`B``PU`"]A=#0`#"AA=#,`!@$&@"XS(&=I=F5SWP:`;W9EP$2+8($-7,N-:H(`)X%$67[`P#R +M`(!M871S('-U<'\(!&,"!98!`$P```H"D"XU+"!M=')E90D``&\`7G1A`D09BP``;<& +M42H@1TY5=0$"-0(F("@$"P`:`$%L;VYG50(`K0LB+``-J +M`0`9`]$J(%!/4TE8('5S=&%R6P`"$``/B@P#!R$`P&]C=&5T+6]R:65N=!<$ +M,7!I;QX`IE-64C0@05-#24D4``)3``\R``5A0FEN87)Y+@#`("AB:6FEP,A8`!'P!32],6E<= +M`*)L>FUA+"!L>FEP$P,O>'HC```9-!0`"0@!```*`IP0!3H!`'4$#P8!`@*O +M`0._`P*\`@\?`Q@P(G)EH`U18W1E9")'`P)/`,,L('=H:6-H('=I;&PF$0)U +M`P:0`%%E>&-E<$`%`+D%`?P(-F5A;;4%`A$+ +M<"X@(%1H97(T$2`@;M82,7)E8S`1`]\(`),$02!I;BVW#X(@;6]D:69I8^4, +M\@%OP`!APD!HP`"2@P`31$B:7*"$1!I>0<# +M[A("#`(A(&(W"0","C%A8FP`!@","@$,``$L"P+4$`!H``([`$)E86-H/0$A +M=F5S`Q-Y0P!0:6YD97"J`"5N="(!`$0-``\/$&-"!1)O;`T&-0I4(%=I:VE2 +M#`,,$S!H;W?X``&S`Q!DK0$#V@`"*@$A3VX_"`#W#`)@!@#S#@!0!@/-``%P +M`%-L=V%Y'!L:6-I#16":6YV;VME(&'Z#Q%C +M?PH#SA$@("C2$"4@8?L*`*$!("!AL@$!)Q`"+0`(S0`4;W,$<"DL(&ET('=P +M`%`@9V5T(-(2`5T*`*0$-R!);FX`,BP@:8(5`9X``5$!`YL`(F5NR0$'+0`` +M?``+<0`H9&41``/&`A$LY0D"@```C0X`E@$`%@$`0``P86=A\P\!7PJ18V]R +M"(&5N=FER;VX/"Q%WD`,!H`(0;=@! +M$W):`P4P`@!;``)_`!%Y>P,1<#4`8F%T979E:89`@4.#V0:____________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________________________________________]@4"`@*B!)1!$` +M`/$14T\Y-C8P(&9OFEP,A8`!"8`32],6E<=`/D#;'IM82P@;'II<"P@ +M86YD('AZ(P#!"DYO=&5S(&%B;W5TE`!R;&EB=$`\"YT96-T=7)E.@H* +M("H@5&AI0`&EP#@:7,@9&5S:6=N960@ +M=&]>`61E>'1E;F1>`3AN97?@``#S`#(*("#.`!!V<@$`X0$22!R97%U:7)E;65N=+(`,G1H80D!`BL`("!BCP&0(')E861A8FQEH@!!=W)I +M=`P`$&$,`0($`0!H``([`$5E86-H;P!396YT'!L86EN:6YGR0`P:&]W +M^``"]0`'+``"*@$A3VZJ`!PL`P$`48!`-T!\@%E9"!A +M=71O;6%T:6-A;&QY1P"P22=V92!A='1E;7#7`>!T;R!M:6YI;6EZ92!S="L` +ML"!L:6YK('!O;&QUN`'A+B`@268@>6]U(&1O;B?L`0"V`/$":6-I=&QY(&EN +M=F]K92!A('#K`(!U;&%R(&9E85D"0"`HD`!RT`!P8#`(`! +M`ID!<"DL(&ET('=P`/``(&=E="!P=6QL960@:6XN/@`G26YN`#``%1 +M`0.;`")E;LD!!RT``#X`"W$`*&1E$0`#Q@(1+/```H``(FYEC@(`%@$`0`!B +M86=A:6YS1P*@8V]R7L#$7`U`-%A=&5V +M97(@8FQO8VMS\``0:$,$(6ETH0!!66]U717`F$@82!T:6U7`W%O`+$@ +M(&)S9'1A3X`!8P``0`"\05R;W9I9&4@ +M96%S>2UT;RUUX`0!V``##``"\`Q)EDP`" +M3P0"0:7,@97-P96-I;@0!T`$"J@$`.@CS +M`SH@(G!A>"!I;G1E`<``$D!`)()`"<`4"H@97AA20!`8$(&YDT`(Q9G5L+P(&10`0+T,* +M`84!$6&>"E%A8W0@"`"X!!,B!0XR+F@BJ0`R:&4* +M7PP0(+`)`/H``!0`!.D&`W((`G\"-&UO5$P`P%&!E+``-J`0`9`[$J(%!/ +M4TE8('5S=+`1!!``#XH,`P%\``(Q`%9O8W1E=*\4`&`"`1X`H5-64C0@05-# +M24ET`@$4``\R``L00FT1$7DN`+$@*&)I9RUE;F1I8=018VQI='1L91$``OH` +M$TE?%I%#1"U23TT@:6VW`A`H.`XP(&]PRP/`86P@4F]C:W)I9&=EYP%B2F]L +M:65T*0$![P$"20`T6DE0=00$0``@=6XQ"P`E%@#6$&!R(")D969^!A$B9@D# +M&```H00C:655`0##`0"B`85"4T0@)V%R)U(``?@`$2?]`Q`GNP(/"Q<(V$UI +M8W)OQ=4`)H`-6QZ-*@!`.47"0@! +M```*`IP0!4L!`'4$#P8!`@*O`0._`P*\`@\?`Q@P(G)EH`T`$!81(D<#`D\` +MPBP@=VAI8V@@=VEL;.L8`'`(`,,/`U\!0',@97@M%``"`@"Y!02)$0(+%P-: +M%P%1``7I$C!S("A3"@$T!`"$`0,S!`#T`V`L(&5T8RGO"P+Z`P"I`@!M``*- +M``&;`0+:``_(`PIA(FYE=V,BFP,!,P`G`'!L:6)R +M87)Y3`#08W!I;RXU+"!M=')E90D``&\`\@IT87(N-2!P2!E2QN``/2`>`@875T;VUA +M=&EC86QL>68!065C='.H``#5``,<`E!O;&QO=Y,!$&8L`*%S.@H@("H@1TY5 +M=0$"4@(F("BY`0`:`$%L;VYG50)B;F%M97,L$`!3;&EN:R`1```W`E)S<&%R +M'1E;J+ +M``-J`0`9`]$J(%!/4TE8('5S=&%R6P`"$``R<&%X-`-18VAA;F=^`3=M870A +M`+!O8W1E="UOFEP/@$Q:6]N&`%=8GII<#(6``1\`4TO3%I7'0"B;'IM82P@;'II&-E<$`% +M`+D%!&D"L"!T:&%T(')E<75IE@4G87C*`E(@*&9O?P(-F5A;;4%X'-Y +MU`P#P!`![``-S!`![``&'"0&C`%0@;VYL>0H#`#@( +M`+(``1X#`*8$`@P"(2!B-PEQ4,`4&EN9&5PJ@`E;G0B`0`8"5!AP,1<#4`T6%T979E6QE(&%P<')OR`,`R0@" +M^@#0=&\@:&%V92!M=6QT:3$,!*D``@$$`+D(`/X-%6Z>`%`@(&)S9",'(75S +MO`$`/06#;B!I=',@(D`\`!(BO0012!F +M0"0:7,@97-P +M96-I;@0!T`$"J@$`.@@P.B`BDPH!#A$)V@T3(KD"`-X.(F%NZ`(`I0<`$0," +M6@<0+&,`0&1E8N9V]O9VQE +M+F-O;2]P+VH`$2\Z`"!S+VD``),``6<`47-U8FUI9P!P96YH86YC9<\``*8` +M!C@`,BP@<-H0`BP``#L```0#`$L'`1<)X65S="!V:6$@1VET2'5BP@`"D`"A +M7!1`GD1(`\A$`%@)S82!F=6QL+98( +MF-%#A)B!P`2>`<``$D! +M`)()`"<`02H@97@;$T!S.B!3,@-4P``7P%C875T:&]R:1``EPT!\@(`P1,2+NT/ +M4'1O<"UL#`0#Q0P`,`0&";8""',5`.L%`>X/\`4@*B!.15=3("T@ +M:&EG:&QI9VAT<]P`,')E8]D4`C$%`Z`"DD-/4%E)3D<@+0P%`$(4`,H'(61O +M7P8!AP4`S@#`*B!)3E-404Q,("T@9`HQ86QLCP0!#0``BA8`OP`"*0`#0`41 +M+3P``5X1`A@`8&-O;F9I9[(6%2T,``)$`+5S8W)I<'0L('-E96<``"@%`ED6 +M`F,(@2H@0TUA:V5,U`0Q='ATB``A<'5G$#`@(F,T!A$B)`,`.`PI;VQ-``)6 +M`0;K`P$I`0`6"0".`0]M`0$`(`T0=3T3`A`7)`HGL``C92>M``,D!`"3``!. +M`/``+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C_P```@`0+60"`)\`!*@``-D. +M"*($$BP:#@#7"P!9"Q!YR@4!]@$C97*N`05P`"1I;F0`@2YH+FEN"@DM]`<` +MYA,2\% +M1FYA;'.=`!)S/@M/:6YS:60:____________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________________________]J4&ME2!F;W(@:L`D'-A +M;64@9G5N8S`<``$D!0'-U8V@G`%`J(&5X84D`U',Z(%-O +M;64@6]U(&UA>2!F:6YD('5S969U;"\"!D4` +M42]M:6YIA0$18>,!46%C="!S8`"A(&1E;6]N2#R`I!I +M;VYS+@H*5&B=`?("<"UL979E;"!D:7)E8W1O%#36%K +M94QI\`!,GK0`#)`0`DP``3@#U`2YA +M;2P@86-L;V-A;"YM-"SA`$!E+F%C_P```@`2+50`)'1OJ``,H@2R+"!O;FQY +M(&YE961\`#%M86GV`2-E7-T96TZ"B`J(+@$=2XQ(&5X<&R#`@,O`P!"`0(A``2:`P,S``"(!`\T +M``L`(@`,-0`O870T``PH870S``8!!H`N,R!G:79E2XS30`"]P,2(FL#!:L``20`4"(@ +M=71II`59(&-L87-$``'O!49N86QSG0`P`D09BP``;<&42H@1TY5=0$"-0(B("BK"0"Y`0`:`$%L +M;VYG4`9B;F%M97,L$`!3;&EN:R`1``!C`%)S<&%R'1E;J+``-J`0`9`]$J(%!/4TE8 +M('5S=&%R6P`"$``R<&%X-`,"60<#>`('(0"P;V-T970M;W)I96X!`P!@`@$> +M`*%35E(T($%30TE)=`(!%``"4P`/,@`%84)I;F%R>2X`P"`H8FEG+65N9&EA +M;J(!8VQI='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I;;<"$2AX""!O<,L# +MP&%L(%)O8VMR:61G944`8DIO;&EE="D!`>\!`DD`-%I)4%8#!$``('5N,0LP +MFEP,A8`!'P!32],6E<=`*)L +M>FUA+"!L>FEP$P,O>'HC```9-!0`"0@!```*56-R96%TSP`!=00/!@$"`JH# +M`[\#`KP"#Q\#&#`B&-E<$`%`+D%!&D"42!T:&%T0PXQ:7)E40`!\P,!R@(@("@6!0$T +M!`"$`0,S!`#T`V`L(&5T8REF"@+Z`P"I`@8B!`&&`0+:``^6`P4!R`-A(FYE +M=V,BFP,!,P`GD#`*4#(71EVPAA.@H*("H@+1`0:2`*<&AE879I;'G\"#9E +M86VU!0(1"X`N("!4:&5R9;T/(VYOX@<`@@(#WP@`DP1!(&EN+;D``2<0`BT`",T`%&_Y +M"'`I+"!I="!W<`!!(&=E=!D3`5T*`*0$-R!);FX`-RP@:9X``5$!`YL`(F5N +MR0$'+0``?``+<0`H9&41``/&`A$L\``"@```C0X`E@$`%@$`0``@86<##A%T +M\0F18V]RP,B:67-#P%O`P/G"B!D=1D-`)\#$'.% +M`2-O9H@!`(X2$"UV```S#`#W"!%IM`\`A`!R96YV:7)O;@\+$7>0`P&@`A!M +MV`$3<3`<0-0&)A8VOR`S%F2W,`))E9"!O=71P=73O +M`@!@!/$#;V)J96-T+7-T>6QE(&%P<')OR`,`^10"^@#0=&\@:&%V92!M=6QT +M:<,3!*D``@$$`+D(52!O<&5NG@`3(!40`&H0``H!$6DA"&-I=',@(D`\`!(B +MO0012!F4X.``P1$2(A`0!:""`L(E`(H"P@8V%P86)I;&D2%`8#`07Q +M``+S#P$_#@CV!0&7`8`@:6YD:79I9&P.`]L(`(4``#H2`D(``*P+`-$``#8! +M(71OK`TP9&%TUP``!0X6.BX!`L@)`#T`$F'L`@#)"@$K`#-I;B`G`0!%!3-A +M9&2.`AAA]PP!J0H#'@]19FER41`.'1E;F0@ +M;&EB87)C:&EV92X*"B`J($]N(')E860L(&-O;7!R97-S:6]N(&%N9"!F;W)M +M870@87)E(&%L=V%Y2!A +M8V-E<#4`T6%T979E2W,`))E9"!O=71P=70&`>!4:&4@ +M;V)J96-T+7-T>1`"4'!P!E +M('-O;64@=71I;&ET>3X`!8P``0`"\05R;W9I9&4@96%S>2UT;RUU"!I;G1E0#\`)N86UE('-A>7,N"E)%041-12X`!^@&X2!B=6YD;&4N +M"@I1=65S^@*@/R`@27-S=65S/U(`URH@:'1T<#HO+W=W=RX@!S!O3``!( +M`1!HN`*P9F]R(&]N9V]I;FH&0&%N(&FW`!`L(00!_``!#P"A('1R86-K97(@8B!$!G +MF-A="P@8@<`$G@'``!)`0"2"0`G`%`J(&5X84D`0',Z +M(%,R`U1S;6%L;!4`!#X!`%(#(6%T'`@@;6'F!"!N9-`",69U;"\"!D4`$"]# +M"@&%`1%A!@E186-T('-@`+`@9&5M;VYS=')A=+'2(`")P=;H+(")C-`81(B0#`#@,*6]L30`"5@$&ZP,` +ME``!%@D`C@$/;0$!`&8(('5SW0H`V@$T90HGL``C92>M``-G`0"3``!.`/`` +M+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C_P```@`0+:("`)\`!*@``&H+"*($ +M82P@;VYL>=<+`GP`,6UA:?8!(V5RK@$%<``D:6YD`($N:"YI;@H)+?0'4FQA +M=&5S9P`18C0"`W(!`K4`8`H*1W5I9/,`*"!$5`8$T@$"=0`!MP%PP`( +M2PE`:&%R9!8,`3`&!%L!`4<``(X!86UO9&5R;H\``.@!`+P'<"!V87)I86Y( +M"0":!3!M86[X"T%P86=E.```,0XD``$=`U=H+`#L'`2,)"=H1`,$",&5C=)D#$62V#P,<`@5X"1!F +M!A(!MP91*B!'3E5U`0(U`B8@*`0+`!H`(VQOO`4`K0LB+ +M``-J`0`9`[$J(%!/4TE8('5S=+`1!!``#XH,`P%\``(Q`+!O8W1E="UO\!`DD`-%I)4'4$!$``('5N +M,0L`[!,`UA!@"T4``("`+D%!(D1`FL4`$,.`-,3`%$``;$6`0`&@`0I:7-N%")B98@%`$`$`5X!.&YE=[4#`/`$`/T"`Y\! +M`'L``8<)`2L5`DH,`PH#`#@(`&\0%'3N$@(,`B$@8C<)`(P*`8\8`[@4`0P` +M$&$,`0+4$`!H``([`!%EG!8`/0$A=F5S`Q-Y0P!0:6YD97"J`"5N="(!`$0- +M`7D9`$(%$F]L#0:P"U0@5VEK:5(,`PP3,&AO=U$/`;,#$&2M`0/:``+W$P4T +M&`3\!`#S#@!0!@/-``%P``*`%P+$!0]D&O__________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M________________________________________'E!U9&EN9RX1``#R!2!' +M3E4@;&]N9R!F:6QE;F%M97,L$`!3;&EN:R`1`*%A;F0@`*935E(T +M($%30TE)%``"8P`/,@`%84)I;F%R>2X`\P<@*&)I9RUE;F1I86X@;W(@;&ET +M=&QE$0`"^@#P'TE33SDV-C`@0T0M4D]-(&EM86=EFEP/@$Q:6]N1`!=8GII<#(6``1D`4TO3%I7'0"B;'IM82P@;'IID#`*4#`.<#]A)U2!S +M=')E86VU!>!S>7-T96TN("!4:&5R92P`D&YO(&1I-R86YD;VT@86-C97-S+GD`!I<` +MD&ES(&1EU`P"C!`![``'.`!!VFP0` +MT082$N("!)9B!Y;W4@9&]N)^P!`+8`\0)I8VET +M;'D@:6YV;VME(&$@<.L`('5L60B@96%T=7)E("AS=2\!&7,<`A!AZ0`'+0`$ +M10<#(@("F0%P*2P@:70@=W``X"!G970@<'5L;&5D(&ENI`0W($EN;@`W+"!I +MG@`!40$#FP`B96[)`07L#$7`U`-%A=&5V +M97(@8FQO8VMS\```[@2X'<70@82!T:6U7`W%O8!(71O(@`%H0!A="!O;F-EA0`A3VZ0`QMEPP`"Y`(R<')O.@$! +MA0%18W1L>2W,``"."5)U='!U=.\"`&`$\0-O8FIE8W0M2!B=69F97(@)`@`90`$<@&%82!S;V-K +M970^`TEW:7-HN@3`P"`,D*`2L`,VEN(">D``,P``*,! +M!H`%,7=A;H@`$'0V!`5%`0!@```:!!!TC@7,N +M"E)%041-1;L&!^@&X2!B=6YD;&4N"@I1=65S^@*@/R`@27-S=65S/U(`URH@ +M:'1T<#HO+W=W=RX@!S!O3``!(`1!HN`*#9F]R(&]N9V]8!Q@@9`!P9&5V +M96QO<#P%)BP@_`Y`9&]C=10``:P(`3<,`'$``#H`(6YK70$`70`&8N9V]O9VQE+F-O;2]P+VH`$2\Z`"!S+VD``),``6<` +M47-U8FUI9P!P96YH86YC9;L``#8"!C@`@RP@<&QE87-E+```.P``!`,`2PB!$!G0&";8"(FENU@0`I`H`ZP4$O0+P`DY%5U,@+2!H:6=H +M;&EG:'1S7`8PM```Z#S`@*B"3``!. +M`/``+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C_P```@`0+:("`)\`!*@``-D. +M"*($$BP:#@#7"P!9"Q!YR@4!]@$C97*N`05P`"1I;F0`@2YH+FEN"@DM]`<` +MYA,22XS]!0P86EL[P0R92`B:P,%JP`!)``4(@L+62!C;&%S1``!'PE& +M;F%L``'?`5P#R*71H92!A=71H;W)S('=I=&@@86YY('%U97-T +M:6]N'2(`#%P=70I`/D#(F-M86ME +M(B!B=6EL9"!T;V]L30`"5@$&-0$!*0$Q(&EN3`$/;0$!,&%R91`"$F3:`35E +M"B>\`!,GK0`#9P$`DP``3@#U`2YA;2P@86-L;V-A;"YM-"SA`$!E+F%C_P`` +M`@`2+50`)'1OJ```(`$P9&ES7P(0=4$!LBP@;VYL>2!N965D?``Q;6%I]@$C +M97)<`05P`"1I;F0`\@,N:"YI;@H)+2!T96UP;&%T97-G`!%B-`(!9@$39;4` +M8`H*1W5I9/,`DB!$;V-U;65N=($!`,4!,F%L;'4``/,!]0H@'!L@P(#+P,`0@$"(0"#('!R;V=R86TS`$]C<&EO-``+ +M`"(`##4`+V%T-``,*&%T,P`'K0/P!#,@9VEV97,@86X@;W9E2!A``"/`&<@)V1O8R>]!;!I;@IA(&YU;6)E2QN``5H`S!U=&^3!@#_`A!YP0(P96-TF0,19-4``QP"!<(&$&8L +M``&W!E$J($=.574!`KH!)B`HN0$`&@!!;&]N9U4"8FYA;65S+!``4VQI;FL@ +M$0``8P!A`@@;W#+`\!A;"!2;V-KB,` +M`!DT%``)"`$```I58W)E873/``%U!`\&`0("J@,#OP,"O`(/'P,8,")R9?X( +M46-T960B1P,"3P#$+"!W:&EC:"!W:6QLB@`!5@`%R@%A(&5X8V5P0`4`N04$ +M:0+1('1H870@U`P#P +M!`![``.?`0![``&'"0&C``)*#`,*`P`X"`"R``$>`P"F!`(,`B$@8C<)`&H( +M,6%B;``&`(P*`0P``2P+`@0!`&@``CL`0F5A8V@]`2%V97,#$WE#`%!I;F1E +M<*H`)6YT(@$`&`D`#P\08T(%$F]L#08U"E0@5VEK:5(,,&EN9\D`,&AO=U$/ +M`;,#%V26"@(J`2%/;C\(`/<,`F`&`P,!`_@``8@)4&%L=V%Y1@$`W0$J962* +M"`)'`'!))W9E(&%T+0T`C`<`P0^0:6YI;6EZ92!S#@T28U((07!O;&R4#5$N +M("!)9O4(4&1O;B=TJ`"097AP;&EC:71LV0EB=F]K92!A^@\18W\*,69E830+ +M,"AS=2\!!?L*`*D`("!A00`!)Q`"+0`(S0`4;_D(<"DL(&ET('=P`'$@9V5T +M('!UG`T0:7H+1R`@26YN`#``%1`0.;`")E;LD!!RT``#X`"W$`*&1E +M$0`#Q@(1+/```H```(T.`)8!`!8!`$``(&%G`PX"4`.18V]R0`P&@`A!MV`$32X'<70@82!T:6U7`W%O +M8!(71O(@`%2@!2="!O;F-\$B)/ +M;AP."\,``N0",G!R;SH!`84!46-T;'DMS`"2960@;W5T<'5T[P(`8`3Q`V]B +M:F5C="US='EL92!A<'!R;\@#`$,2`OH`X'1O(&AA=F4@;75L=&EP)0``(040 +M=A(#0')E86VY"`#^#15NG@`3(!40`&H0``H!`#T%@VX@:71S(")`Y0`2(KT$ +M$7,P#@)C!08!`6!I='-E;&93`0!]!!`O=@1@=&5N('5S;P8`-PP!<@$R9G5N +M6!($DP$!=08`,@`U(&%NI``"(Q-0;'D@9G)@``S0*%82!S;V-K970^`TEW:7-HN@0!)@\#60\`#B)A;N@"`*4'!C0*$"QC`$!D97-PWP``;`0!Y`,`7,N"B05 +M$6:X#01Q%K0@8G5N9&QE+@H*41$6H#\@($ES7,@<')O9'5C97,@8V]R6]U('1O(&AA=F4@;75L=&EP)0`#J0!P`/,-("!B +M!E +M('-O;64@=71I;&ET>3X`!8P`,"!T;WP!\0-V:61E(&5A2!D8737`%9UX`0!V``##`!%EW@(!O@`%RP$` +MTP`#HP%#+B`@2:0!(6%NB``2=%T``38"`5L#`!\!`#L!061I"!I;G1E&%)`$!S.B!3,@-4`0-)`#!C;VY#`O`".B`@5F%R:6]UP`` +M7P%Q875T:&]R<\`%`1\&`?("`DT'$`H5"%!T;W`M;`P$`W8%`#`'`4$`$&DD +M!0FV`B)I;O@$(FEOX08$O0+P`DY%5U,@+2!H:6=H;&EG:'1S7`8P'2(`#!P=71>`C`@(F,T!A$B)`,`J@2!N965D?``Q +M;6%I]@$C97*N`05P`"1I;F0`@2YH+FEN"@DM]`=2;&%T97-G`!%B-`(#<@$" +MM0!@"@I'=6ED\P`H($14!@32`0)U``#S`8`@PH"MP(A960N +M"P!;!!!SU`80;A$,`-8"`),``'4``!<"`/D$`7$``7$*")<``9P)(RXS30`` +M[P0R92`B:P,%JP`!)``4(@L+62!C;&%S1``!'PE&;F%L=H+`#L'`2,)@&%U=&]M871I_P(0><$",&5C=)D#$60Y"0,< +M`@5X"1!F+``!MP91*B!'3E5U`0(U`B8@*`0+`!H`06QO;F=5`@"M"R)S+!`` +M``4+$R`1``!C`%)S<&%RB,``!DT%``)"`$```H"G!`% +M.@$`=00/!@$"`J\!`[\#`KP"#Q\#&#`BP`!APD!*Q4"2@P`31$B:7*"$1!I>0<#[A("#`(A +M(&(W"0","C%A8FP`!@","@$,`!!A#`$"U!``:``".P!"96%C:#T!(79E4,`4&EN9&5PJ@`E;G0B`0!$#0`/#Q!C0@42;VP-!K`+5"!7:6MI4@P##!,P +M:&]W40\!LP,09*T!`]H``O<3(4]N/P@`]PP"8`8`\PX`4`8#S0`!<``"@!<" +MQ`4J962*"`)'`#!))W8-&``A%0",!S!T;R`A$#!M:7I2%P"U"`)2"$%P;VQL +M-A(&Y!1!9&]N)^P!D&5X<&QI8VET;-D)8G9O:V4@8?H/$6-_"@/.$2`@*-(0 +M`'4,"!P"$&&R`0$G$`(M``C-`!1OP,1 +M<#4`8F%T979EFUA+"!L>FEP+"!A +M;F0@>'HC```9-!0`\`P*5&AE(&QI8G)A"!I;G1E'1E;DT!L7,@*&9O$E33SDV-C`3`%HW+5II<#D`-EA!4A$`0PI7 +M:&4#`@#D`00%`A$L_`%A2!S=')E86WM`>!S>7-T96TN("!4:&5R92P`D&YO +M(&1I4,`4&EN9&5PJ@`B;G1_`!!R.P0`!`"4=&EC;&5S(&]N@0$$ +MK@#P`%=I:VD@97AP;&%I;FEN9XD`,&AO=_@``O4``(X$`RP``BH!(4]NJ@`< +M+`,!`]D"`G``0&QW87E&`0#=`?(!960@875T;VUA=&EC86QL>4<`L$DG=F4@ +M871T96UPQ`/@=&\@;6EN:6UI>F4@2!I;G9O:V4@82!PZP`@=6PW!"!E85D" +M0"`HD`!RT`!^\%`(`!`ID!<"DL(&ET('=P`.`@9V5T('!U +M;&QE9"!I;J0$-R!);FX`-RP@:9X``5$!`YL`(F5NR0$'+0``?``+<0`H9&41 +M``.J`!$L\``"@``B;F6.`@`6`0!``&)A9V%I;G-'`J!C;W)R97-P;VYD)P0( +M20`-6@`">P,Q:65SPP`!;P.A86QS;R!R961U8[D%,&4@`(&5N=FER;V[7`C%S('=N`@&@`A!MV`$36QE(&%P<')OR`,`PP<"^@#@=&\@:&%V92!M=6QT:7`E +M```A!1!V$@,`!04`N0A5(&]P96Z>`%`@(&)S9",'(75SO`$`/06#;B!I=',@ +M(D#E`!(BO01&P`28D(``"P$`-$``#8!(71OFPDP9&%TUP!6=7)C93HN +M`0+("0#"`!)A[`(`PPD!*P`S:6X@)P$`^`(@863\`@!B`!%A_`@$J@$`>08A +M;W7W!%%F:7)S=)("`*8!(&$@0P41;S$*`/8`%BYT``/9`P*G`0":"0*<`0&% +M``:X`0!V``##``"\`Q)EDP`"3P7,N"E)%041-1;L&!^@&X2!B=6YD +M;&4N"@I1=65S^@*@/R`@27-S=65S/U(`URH@:'1T<#HO+W=W=RX@!S!O3 +M``!(`1!HN`*#9F]R(&]N9V]8!Q@@9`!P9&5V96QO<#P%<2P@:6YC;'6]!4!D +M;V-U%``!K`@!-PP`<0``.@`A;FM=`0!=``9S`%`@;6%I;`<"0FQI%EB!$!G&%)`$!S.B!3,@-4`0-)`#!C;VY#`O`".B`@5F%R +M:6]UP``7P%V875T:&]RT/4'1O<"UL#`0#Q0P`,`0& +M";8"(FENU@0`=`P`ZP40<],-\`4@*B!.15=3("T@:&EG:&QI9VAT'2(`")P==8-(")C-`81(B0#`#@,*6]L30`"5@$&ZP,!*0$`%@D`C@$/ +M;0$!`+`,('5SW0H`V@$T90HGL``C92>M``-G`0"3``!.`/``+F%M+"!A8VQO +M8V%L+FTT"0T#[0`P+F%C%P$``@`0+:("`)\`!*@``-D."*($$BP:#@#7"P)\ +M`#%M86GV`2-EPH"MP(`A1(A86R) +M!T!S97%UZ@@0=&%R +M+C54`0CQ!`4^$A%S8P0Q<&]PY0\#G`$$>P`(2PE`:&%R9!8,`3`&!%L!`4<` +M`(X!86UO9&5R;H\``.@!`+P'<"!V87)I86Y("0`B##!M86[X"T%P86=E.``` +M,0X`SA0"^@$`G@`!WP%7)V1O8R>]!9!I;@IA(&YU;6+R#!=FD0<$.P''"@I9 +M;W4@`""(&EN'!L86EN3`1!F+``P'1E;J+``-J`0`9`]$J(%!/ +M4TE8('5S=&%R6P`"$``P<&%X20-Q97)C:&%N9WX!-VUA="$`L&]C=&5T+6]R +M:65N`0,`8`(!'@"A4U92-"!!4T-)270"`10``E,`#S(`!6%":6YA\!`DD`-%I) +M4%8#!$``D'5N8V]M<')E<],&<&]R(")D969^!A`BJ0($&```H00C:655`0## +M`0"B`85"4T0@)V%R)U(``?@`$2?]`Q`GNP($/0%:-RU::7`F`-A-:6-R;W-O +M9G0@0T%"+``Q3$A!"@,Z3%I(,@`Z4D%2$0`86!$``=4#!;@"`'@#"*\"8&AA +M;F1L9;L"$'FW`P"V!`:X`C!B969*`W!E=F%L=6%TR@(`(``#F0,"SP(0=?8% +M$&]Q`@"V`@)#`@$*`!$@@P&B4E!-('=R87!P94X"16=Z:7`^`3%I;VX8`5UB +M>FEP,A8`!'P!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9-!0`"0@!E6-A +M;B!C0`&@`0`#@Q397-I9VXE#!)EO@(`0`0!,`0X;F5WM0,`\`0`>P`#GP$`>P`! +MAPD!HP`"2@P#"@,`.`@`L@`!'@,`I@0"#`(A(&(W"7%R96%D86)L``8`C`H! +M#``!+`L"!`$`:``".P!"96%C:#T!(79E4,`4&EN9&5PJ@`E;G0B`0`8 +M"5!AD` +M!RT`!"T'`,\*%&_Y"'`I+"!I="!W<`!Q(&=E="!P=9P-(&ENI`0W($EN;@`W +M+"!IG@`(FP`B96[)`02UV```S#`#W"!%IAP8`A`!P96YV:7)O +M;M<",7,@=Y`#`:`"$&W8`1-R6@,%,`(`6P`"?P`1>7L#$7`U`-%A=&5V97(@ +M8FQO8VMS\```[@@``S0*%82!S;V-K970^`TEW:7-H +MN@0!)@\#60\`4X.475S92`B(0$`6@@@+")0"+$L +M(&-A<&%B:6QI=/8"!`,!!?$``O,/`;<$"/8%`9P" +M`,D*`2L`,VEN("#U%F:7)S=)("`*8!(&$@ +M0P41;UD1`/8`%BYT``/9`P*G`0"_``*<`0&%``:X`0!V``##``"\`Q)EDP`" +M,0\@;'ED`0#,``"C`0:`!3%W86Y_!1)T'0\!-@(!6P,!&@00=(X'(7-K+`,0 +MA$)P`$`B0`P;6%K>0"0:7,@97-P96-I;@0!T`$"J@$` +M.@@P.B`BDPH!#A$)V@T3(KD"`-X.(F%NZ`(`I0<&-`H0+&,`0&1EF-%#A)B!P`2>`<``$D!`)()`"<`02H@97@;$T!S.B!3 +M,@-42!A;F0@861D(&ET('1O(&$@=&%R(&%R8VAI=F4@=VET:&]U=`H@ +M("!F:7)S="!W2!F8<`\`5S;V-K970N("!)9B!Y;W4@=V%N=$0`$G1=`!(O/0``8``P +M:65S,P!09&ES:RQ.`/`,0#Q+6ES(&5S<&5C:6%L;'D@96%S>2X*"B`J($YO=&4Z(")P87@@ +M:6YT97)C:&%N9V4@9F]R;6%T(B!I7,N"E)%041-15``1"!L:6)M +M`=%B=6YD;&4N"@I1=65SK@"@/R`@27-S=65S/U(`UBH@:'1T<#HO+W=W=RXX +M`$`N;W)GDP``2`$Q:&]MIP"`(&]N9V]I;F8$(&YDT`(Q9G5L+P(&10!1+VUI;FF%`1%A +MXP%186-T('-@`+`@9&5M;VYS=')A=+M``,D +M!`"3``!.`/4!+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_```"`!`MH@(`GP`$ +MJ``,H@2R+"!O;FQY(&YE961\`#%M86GV`2-E7-T96TZ<`<"N`1U+C$@97AP;(,"`R\#`$(!`B$`!)H#`S,``(@$#S0` +M"P`B``PU`"]A=#0`#"AA=#,`!@$&@"XS(&=I=F5SWP:`;W9EP$2+8($-7,N-:H(`)X%$67[`P#R +M`(!M871S('-U<'\(!&,"!98!`$P```H"D"XU+"!M=')E90D``&\`7G1A``&I`5"`"X!!,B?P(R+F@BJ0"` +M:&4*`D09BP` +M`;<&42H@1TY5=0$"-0(F("@$"P`:`$%L;VYG50(`K0LB+ +M``-J`0`9`]$J(%!/4TE8('5S=&%R6P`"$``/B@P#!R$`P&]C=&5T+6]R:65N +M=!<$,7!I;QX`IE-64C0@05-#24D4``)3``\R``5A0FEN87)Y+@#`("AB:6FEP,A8`!'P! +M32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9-!0`"0@!```*56-R96%TSP`! +M=00/!@$"`JH#`[\#`KP"#Q\#&#`B&-E<$`%`+D%!&D"42!T:&%T0PXQ:7)E40`!`1`! +MR@(@("A3"@$T!`"$`0-$!`#T`V`L(&5T8RGO"P+Z`P"I`@!H$0*-``&&`0+: +M``^6`P4!R`-A(FYE=V,BFP,!,P`G?P(-F5A;;4%`A$+<"X@(%1H97(T$2`@;M82,7)E8S`1`]\(`),$02!I;BVW +M#X(@;6]D:69I8^4,\@%OP`!APD!HP`"2@P` +M31$B:7*"$1!I>0<#[A("#`(A(&(W"0","C%A8FP`!@","@$,``$L"P+4$`!H +M``([`$)E86-H/0$A=F5S`Q-Y0P!0:6YD97"J`"5N="(!`$0-``\/$&-"!1)O +M;`T&-0I4(%=I:VE2#`,,$S!H;W?X``&S`Q!DK0$#V@`"*@$A3VX_"`#W#`)@ +M!@#S#@!0!@/-``%P`%-L=V%YF4@0`P&@`A!MV`$3!<1<_`` +M`.X',2!I=&0!,EEO=><3`<0-0&)A8VNO$S%F6QE(&%P<')OR`,`@0L"^@!0=&\@:&$Y%D!U +M;'1IPQ,$J0`"`00`N0A5(&]P96Z>`!0@]`\A=7-U!Q!IF@%S(&ETFEP,A8`!"8`32],6E<=`/D#;'IM82P@;'II +M<"P@86YD('AZ(P#!"DYO=&5S(&%B;W5TE`!R;&EB=$`\"YT96-T=7)E +M.@H*("H@5&AI48!`-T!\@%E +M9"!A=71O;6%T:6-A;&QY1P"P22=V92!A='1E;7#7`>!T;R!M:6YI;6EZ92!S +M="L`L"!L:6YK('!O;&QUN`'A+B`@268@>6]U(&1O;B?L`0"V`/$":6-I=&QY +M(&EN=F]K92!A('#K`(!U;&%R(&9E85D"0"`HD`!RT`!P8# +M`(`!`ID!<"DL(&ET('=P`/``(&=E="!P=6QL960@:6XN/@`G26YN`# +M``%1`0.;`")E;LD!!RT``#X`"W$`*&1E$0`#Q@(1+/```H``(FYEC@(`%@$` +M0`!B86=A:6YS1P*@8V]R7L#$7`U`-%A +M=&5V97(@8FQO8VMS\``0:$,$(6ETH0!!66]U717`F$@82!T:6U7`W%O +M`+$@(&)S9'1A3X`!8P``0`"\05R;W9I +M9&4@96%S>2UT;RUUX`0!V``##``"\`Q)E +MDP`"3P0"0:7,@97-P96-I;@0!T`$"J@$` +M.@CS`SH@(G!A>"!I;G1E`<``$D!`)()`"<`4"H@97AA20!` +M8$(&YDT`(Q9G5L+P(&10`0 +M+T,*`84!$6&>"E%A8W0@"`"X!!,B!0XR+F@BJ0`R +M:&4*7PP0(+`)`/H``!0`!.D&`W((`G\"-&UO5$P`P%&!E+``-J`0`9`[$J +M(%!/4TE8('5S=+`1!!``#XH,`P%\``(Q`%9O8W1E=*\4`&`"`1X`H5-64C0@ +M05-#24ET`@$4``\R``L00FT1$7DN`+$@*&)I9RUE;F1I8=018VQI='1L91$` +M`OH`\0))4T\Y-C8P($-$+5)/32!I;;<"$"@X#C`@;W#+`\!A;"!2;V-K[ +M`@0]`5HW+5II<"8`V$UI8W)OQ=4 +M`)H`-6QZ-*@!`.47"0@!```*`IP0!4L!`'4$#P8!`@*O`0._`P*\`@\?`Q@P +M(G)EH`T`$!81(D<#`D\`PBP@=VAI8V@@=VEL;.L8`'`(`,,/`U\!0',@97@M +M%``"`@"Y!02)$0(+%P-:%P%1``7I$C!S("A3"@$T!`"$`0,S!`#T`V`L(&5T +M8RGO"P+Z`P"I`@!M``*-``&;`0+:``_(`PIA(FYE=V,BFP,!,P`G4P`T&-P:6\N-2P@;71R964)``!O`/(*=&%R+C4@<')O=FED92!D971A +M:6QE9"!I;E(`D&EO;B!A8F]U=$T`XW-E"B`@('!O<'5L87(@F``2("D`\PIS +M+"!I;F-L=61I;F<@:&%R9"UT;RUF:6YD5``2FEP/@$Q:6]N,`!=8GII<#(6``1\`4TO3%I7'0"B;'IM82P@;'II +M&-E<$`%`+D%!&D"L"!T:&%T(')E<75IE@4G87C*`E(@*&9O?P(-F5A +M;;4%X'-Y`3AN97>U`P#P!`![``-S!`![``&'"0&C`%0@;VYL +M>0H#`#@(`+(``1X#`*8$`@P"(2!B-PEQ4,`4&EN9&5PJ@`E;G0B`0`8"5!A48!`-T!*F5DB@@"1P"P22=V92!A +M='1E;7",!^!T;R!M:6YI;6EZ92!S=+4(`E((4'!O;&QU(@=1+B`@26;U"%!D +M;VXG=*@``+8`4&EC:71LV0F!=F]K92!A('#K``%_"C%F96$T"S`H``%1`0.;`")E;LD!!RT``'P`"W$`*&1E$0`#Q@(1+/`` +M`H``(FYEC@(`%@$`0`!B86=A:6YS1P*18V]R0`P&@`A!MV`$38!(71O(@`%H0!A="!O;F-EA0`A3VZ0`QMEPP`"Y`(R +M<')O.@$!A0%18W1L>2W,``"."5)U='!U=.\"`&`$\0-O8FIE8W0M7,"!8P``#\`!)4.0&5AP"`,D*`2L`,VEN("#U%F:7)S=)("`*8!(&$@0P41;U`'`/8`%BYT``/9`P*G`0"_``*< +M`0&%``:X`0!V``##``"\`Q)EDP`",0\@;'ED`0#,``"C`0:`!3%W86Y_!1)T +M'0\!-@(!6P,`8PP`,P!!9&ES:RP#`+$0$'*?!)EN=F5N:65N8V7``0")`#!M +M86MY`)!I0#`',*T2!S87ES+@I214%$3442 +M!@<4!]%B=6YD;&4N"@I1=65S^@*@/R`@27-S=65S/U(`UBH@:'1T<#HO+W=W +M=RXX`$`N;W)GDP``2`$0:+@"$&:Q#S-N9V]8!Q<@3`>`(&1E=F5L;W`\!0@9 +M$02Z$0&L"`$W#`!Q```Z`"%N:UT!`%T`!G,`4"!M86EL!P(P;&ESOQ`!G0`0 +M5)D!`.41`.%E8$(&YDT`(Q9G5L+P(&10`0+T,*`84!$6&>"C1A8W1[$W!D96UO;G-T +M.14@;F<^``"`!094`@-)`#!C;VY#`F$Z("!687+N$V!I=&5M$0(8`&!C;VYF:6>R%A4M#``"1`"UM`Q$SM@L`$!20(&]V97)V:65W\P(`JP`% +MP`L`<04P=VAOD0(4*J0*A5]R96%D+C,L$``!^`@-$0!17V1I4$`(&EN^``(M@)P +M:6YF;W)M8:D!,"!F:34!`'P`\`0J($Y%5U,@+2!H:6=H;&EG:'1SW``P@`K1#3U!924Y'("T@=U$!8F-A;B!D;Y\`,W1H:2D`\@))3E-4 +M04Q,("T@:6YS=&%L;'4```T`(7)U*@(#*0"!4D5!1$U%("T\``&5``*3`+!C +M;VYF:6=UM``,D!`"3``!. +M`/4!+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_```"`!(M5``D=&^H``RB!+(L +M(&]N;'D@;F5E9'P`,6UA:?8!(V5R7`$%<``D:6YD`/(#+F@N:6X*"2T@=&5M +M<&QA=&5S9P`18C0"`68!$V6U`&`*"D=U:63S`%`@1&]C=9D%`H$!`,4!,F%L +M;'4``;`:`;W9E]!;!I;@IA +M(&YU;6)E"`"X!!,BO0(R+F@BJ0"`:&4*2R"```[!P$C"4!A=71ODP8`_P(0 +M><$",&5C=)D#$635``,<`@5X"1!F+``!MP91*B!'3E5U`0(U`B(@**L)`+D! +M`!H`06QO;F=0!F)N86UEB,``!DT%``)"`$```I58W)E873/``%U!`\& +M`0("J@,#OP,"O`(/'P,8,")R9:`-46-T960B1P,"3P#$+"!W:&EC:"!W:6QL +MB@`!5@`%R@%A(&5X8V5P0`4`N04$:0)1('1H871##C%I`3AN97>U`P#P!`![``.?`0![``&'"0&C``)*#`!-$2)IF4@``%1`0.; +M`")E;LD!!RT``'P`"W$`*&1E$0`#Q@(1+/```H```(T.`)8!`!8!`$``(&%G +M`PX1=/$)D6-OP,1<#4`T6%T979EP"`,D*`2L`,VEN("#U%F:7)S=)("`*8!$6%P$A%O\0T`]@`6+G0` +M`]D#`J +M#@#G&`Y6#A`L8P!`9&5S<*(``&P$`>0#`',*2!I;G9O:V4@82!P87)T:6-U;&%R(&9E +M871U!E('-O;64@=71I;&ET>3X`!8P``+$!\09P2!D8737`%9UP"`&$# +M`2L`,VEN("7,N"E)%041-15``1"!L:6)M +M`=%B=6YD;&4N"@I1=65S^@*@/R`@27-S=65S/U(`UBH@:'1T<#HO+W=W=RXX +M`$`N;W)GDP``2`$0:+@"L&9OF-A="P@8@<`$G@'``!)`4!S=6-H +M)P!0*B!E>&%)`$!S.B!3,@-40&";8"(FEN8PL`<0L`ZP4$O0+P +M`DY%5U,@+2!H:6=H;&EG:'1S7`8P'2(`#!P=71>`C`@(F,T!A$B)`-I +M9"!T;V]L30`"5@$&ZP,`E``!%@D`C@$/;0$!`&8(('5SW0H`V@$T90HGL``C +M92>M``-G`0"3``!.`/``+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C_P```@`0 +M+:("`)\`!*@``&H+"*($82P@;VYL>=<+`GP`,6UA:?8!(V5RK@$%<``D:6YD +M`($N:"YI;@H)+?0'4FQA=&5S9P`18C0"`W(!`K4`8`H*1W5I9/,`*"!$5`8$ +MT@$"=0`!MP%P=H+`#L'`2,)"=H1`,$",&5C +M=)D#$62V#P,<`@5X"1!F!A(!MP91*B!'3E5U`0(U`B8@*`0+`!H`(VQOO`4` +MK0LB+``-J`0`9`[$J(%!/4TE8('5S=+`1!!``#XH,`P%\ +M``(Q`+!O8W1E="UO`@@;W#+`\!A;"!2;V-K[`@0]`5HW+5II<"8`V$UI +M8W)OFEP/@$@:6]/$WTJ +M(&)Z:7`R%@`$?`%-+TQ:5QT`HFQZ;6$L(&QZ:7`3`R]X>B,``!DT%``)"`$` +M``H"G!`%.@$`=00/!@$"`J\!`[\#`KP"#Q\#&#`BD6$W,*%P!5"`2`!"EIP`!APD!*Q4"2@P#"@,`.`@`W@`4=.X2`@P"(2!B +M-PD`C`H!CQ@#N!0!#``080P!`M00`&@``CL`$66<%@`]`2%V97,#$WE#`%!I +M;F1E<*H`)6YT(@$`1`U087)T:6-"!1)O;`T&L`M4(%=I:VE2#`,,$S!H;W=1 +M#P&S`Q!DK0$#V@`"]Q,%-!@$_`0`\PX`4`8#S0`!<``"@!<"Q`4/9!K_____ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_SI0;F<@;&DN$0``\SUN:R!N86UE'1E;F1E9"!T87(@9F]R;6%T("AI;F-L=61I;F<@04-, +M,P!A3VQD(%8W)P"!87)C:&EV97-+`+=03U-)6"!U"=M=')E92<]`5HW+5II<"8`V$UI8W)O2!A;'-O(&1E=&5C='--`&!H86YD +M;&4,`'!Y(&]F('1HW`'P!VQL;W=I;F<@8F5F;W)E(&5V86QU8702```@``,O +M`A$ZU`!@=75E;F-O<0(!CP(!%``!"@`1((,!HE)032!WFEP +M/@$Q:6]N,`!=8GII<#(6``1D`4TO3%I7'0"B;'IM82P@;'IIP`!S@`0 +M=IL$`-$&$G.C`%0@;VYL>0H#0&UE;G2R``$>`P"F!`(K`#`@8F5``'%R96%D +M86)L``9!=W)I=`P`$&$,`0($`0!H``([`$)E86-H/0$A=F5S`Q-Y0P!0:6YD +M97"J`")N='\`$'([!``$`#!T:6-"!21O;H$!!*X`\`!7:6MI(&5X<&QA:6YI +M;F>)`#!H;W?X``&S`Q!DE@4#+``"*@$A3VZJ`!PL`P$`!`0R;6%T<`!`;'=A +M>48!`-T!\@%E9"!A=71O;6%T:6-A;&QY1P"P22=V92!A='1E;7",!^!T;R!M +M:6YI;6EZ92!S="L`L"!L:6YK('!O;&QUN`'A+B`@268@>6]U(&1O;B?L`0"V +M`/$":6-I=&QY(&EN=F]K92!A('#K`"!U;%D(H&5A='5R92`HD`!RT`!$4'`R("`ID!<"DL(&ET('=P`.`@9V5T('!U;&QE9"!I;J0$-R!) +M;FX`-RP@:9X``5$!`YL`(F5NR0$'+0``?``+<0`H9&41``.J`!$L\``"@``B +M;F6.`@`6`0!``'%A9V%I;G-TSP&18V]RP,Q:65S +MPP`!;P,!;P=16QE +M(&%P<')OR`,`R0@"^@#@=&\@:&%V92!M=6QT:7`E``-3!`(!!`#\"E4@;W!E +M;IX`4"`@8G-D(P2!F)M96UO7,"!8P``0`"\05R;W9I +M9&4@96%S>2UT;RUU0#`',* +MT"!S87ES+@I214%$346[!@?H!N$@8G5N9&QE+@H*475E<_H"H#\@($ES7!1`GH@1`9W)A;18"&%)`$!S.B!3,@-4 +M`0-)`#!C;VY#`O`".B`@5F%R:6]UP``7P%Q875T:&]R<\`%`1\&`?("`-(1$B[M +M#U!T;W`M;`P$`\4,`#`'`4$`$&GD!@FV`B)I;M8$`*0*`.L%!+T"\`).15=3 +M("T@:&EG:&QI9VATPH"MP(`318A86R)!T!S97%UZ@@0=&%R+C54`0CQ!`4^$A%SU@TQ<&]PY0\# +MG`$$>P`(2PE`:&%R9!8,`3`&`J@!`X42`(X!86UO9&5R;H\``.@!`+P'<"!V +M87)I86Y("0`B##!M86[X"Q%PK1] +M!;!I;@IA(&YU;6)E"`"X!!,BXP`R+F@BJ0`R:&4*7PP0(+`)`/H``!0`!.D&`W((`G\" +M$&T:%P/[`$(N("!0B@FR;&5T('5S"FMN;W<0`0&9!F!E`D09@82`;<&`H<8!JH+"``:`/@5#"`6`1````4+#V0:________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________________________________________________]H4"`J(&5X +M1!$``/$,86UP;&5S+VUI;FET87(Z(&$@8V]M<&%C="!S&P#T3R!D96UO;G-T +MV`'!I;F9O +M6]U(&-A;B!D;Y\`,W1H:2D`\@)) +M3E-404Q,("T@:6YS=&%L;'4```T`,')U8X$``RD`@%)%041-12`M%`$1`?$#+@H*66]U('-H +M;W5L9"!A;'-O(@(!3``Q8V]P=@8R8V]M6P%#:6X@(KT",BYH(JD`@&AE"G-O +M=7)C+P`19'4!`!0`!.D&`YH#`G\"-&UO68!,&5C=)D#$635``,<`@7"!A!F+``!MP91*B!' +M3E5U`0*Z`28@*+D!`!H`06QO;F=5`F)N86UE'1E;J+``-J`0`9`]$J(%!/4TE8('5S=&%R6P`"$``P<&%X20,B97)9!P-X`@FEP,A8`!'P!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9-!0`"0@! +M```*56-R96%TSP`!=00/!@$"`JH#`[\#`KP"#Q\#&#`B&-E<$`%`+D%!&D"T2!T:&%T +M(')E<75IP`# +MGP$`>P`!APD!HP`"2@P#"@,`.`@`L@`!'@,`"0$"#`(A(&(W"0!J"#%A8FP` +M!@","@$,``$L"P($`0!H``([`$)E86-H/0$A=F5S`Q-Y0P!0:6YD97"J`"5N +M="(!`!@)``\/$&-"!1)O;`T&-0I4(%=I:VE2##!I;F?)`&-H;W<@=&_U``>6 +M"@(J`2%/;C\(`/<,`F`&`P,!`_@``8@)4&%L=V%Y1@$`W0$J962*"`)'`'!) +M)W9E(&%T+0T`C`<`P0^0:6YI;6EZ92!S#@T28U((07!O;&R4#5$N("!)9O4( +M4&1O;B=TJ`"097AP;&EC:71LV0EB=F]K92!A^@\18W\*,69E830+,"AS=2\! +M!?L*`*D`("!A00`1P,1<#4`T6%T979EP"`,D*`2L`,VEN("#U%F:7)S=)("`*8!$6%P$A%O61$`]@`6+G0``]D#`J60!`,P``*,!!H`%,7=A +M;G\%$G0=#P-%`0!@```:!!!TC@0#`',*F-%#A)B!P`2>`<``$D!`)()`"<`02H@97@$ +M&D!S.B!3,@-48$(&YDT`(Q9G5L+P(&10`/ +M9!K_________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_________V10=&EM90HH$0``\!0@("!O2UB;&]C:V5D(&]U +M='!U="X*"B`J(%1H92!O8FIE8W0M`@#1```V`:!T +M;R!A;GD@9&%TUP!6=7)C93HN`6!C`@&^``7+ +M`0#3``.C`4,N("!)I`$A86Z(`!)T70`!-@(!6P,`'P$`.P%!9&ES:RP#`\0! +MMF-O;G9E;FEE;F-E3`(P('1OB0`P;6%K>0#1:7,@97-P96-I86QL>=`!`JH! +M\P].;W1E.B`B<&%X(&EN=&5R8VAA;F=E(&9O7,N"E)%041-12X` +M1"!L:6)M`=%B=6YD;&4N"@I1=65S^@*@/R`@27-S=65S/U(`UBH@:'1T<#HO +M+W=W=RXX`$`N;W)GDP``:@00:+@"L&9O&%)`$!S.B!3,@-4`0-)`#!C;VY#`O`".B`@5F%R:6]U +MP``7P%Q875T:&]R<\`%`1\&`?("`DT'$`H5"%!T;W`M;`P$`W8%`#`'`4$` +M$&DD!0FV`B)I;O@$(FEOX08$O0+P`DY%5U,@+2!H:6=H;&EG:'1S7`8P'2(`#!P=71>`C`@(F,T!A$B)`,`J@2!N965D +M?``Q;6%I]@$C97*N`05P`"1I;F0`@2YH+FEN"@DM]`=2;&%T97-G`!%B-`(# +M<@$"M0!@"@I'=6ED\P`H($14!@32`0)U``#S`8`@PH"MP(A +M960N"P!;!!!SU`80;A$,`-8"`),``'4``!<"`/D$`7$``7$*")<``9P)(RXS +M30``[P0R92`B:P,%JP`!)``4(@L+62!C;&%S1``!'PE&;F%L=H+`#L'`2,)@&%U=&]M871I_P(0><$",&5C=)D#$60Y +M"0,<`@5X"1!F+``!MP91*B!'3E5U`0(U`B8@*`0+`!H`06QO;F=5`@"M"R)S +M+!````4+$R`1``!C`%)S<&%RB,``!DT%``)"`$```H" +MG!`%.@$`=00/!@$"`J\!`[\#`KP"#Q\#&#`BP`!APD!*Q4"2@P`31$B:7*"$1!I>0<#[A(" +M#`(A(&(W"0","C%A8FP`!@","@$,`!!A#`$"U!``:``".P!"96%C:#T!(79E +M4,`4&EN9&5PJ@`E;G0B`0!$#0`/#Q!C0@42;VP-!K`+5"!7:6MI4@P# +M#!,P:&]W40\!LP,09*T!`]H``O<3(4]N/P@`]PP"8`8`\PX`4`8#S0`!<``" +M@!<"Q`4J962*"`)'`'!))W9E(&%T(14`C`'!L:6-I=&S9"6)V;VME(&'Z#Q%C?PH#SA$@ +M("C2$`!U#`@<`A!AL@$!)Q`"+0`(S0`4;W,$<"DL(&ET('=P`%`@9V5T(-(2 +M`5T*`*0$-R!);FX`!287`9X``5$!`YL`(F5NR0$'+0``?``+<0`H9&41``.J +M`!$L6!$"@```C0X`E@$`%@$`0``P86=A\P\!7PJ18V]R7L#$7`U`&)A=&5V97)X%Q%S\```[@*B!F:6QEFEP(&-O;7!R +M97-S:6]N%0!=8GII<#(6``0F`$TO3%I7'0#_`VQZ;6$L(&QZ:7`L(&%N9"!X +M>B,``!DT%`#Q,@I4:&4@;&EB2!C86X@8W)E871E(&%R8VAI=F5S(&EN +M(&%N>2!O9B!T:&4@9F]L;&]W:6YG(&9O"!I;G1E'1E;DT!L7,@*&9O$E33SDV-C`3`%HW+5II<#D`-EA!4A$`0PI7:&4# +M`@#D`00%`A$L_`%AT!X'-Y +M`>-R86YD;VT@86-C97-S+GD`!I<`\@)I +M`35N97<7`@!2`#!A;F1[``'.`!1V6`,24,`4&EN9&5PJ@`B;G1_`!!R.P0`!``P=&EC\`0D;VZ!`02N +M`/``5VEK:2!E>'!L86EN:6YGR0`P:&]W^``"]0``C@0#+``"*@$A3VZJ`!PL +M`P$#V0("<`!`;'=A>48!`-T!\@%E9"!A=71O;6%T:6-A;&QY1P"P22=V92!A +M='1E;7#$`^!T;R!M:6YI;6EZ92!S="L`L"!L:6YK('!O;&QUN`'A+B`@268@ +M>6]U(&1O;B?L`0"V`/$":6-I=&QY(&EN=F]K92!A('#K`"!U;#<$(&5A60)` +M("AS=2\!&7,<`A!AZ0`'+0`'[P4`@`$"F0%P*2P@:70@=W``X"!G970@<'5L +M;&5D(&ENI`0W($EN;@`W+"!IG@`!40$#FP`B96[)`07L#$7`U`-%A=&5V97(@8FQO8VMS\``0:%<%(6ETH0!!66]U +M2X'<70@82!T:6U7 +M`W%O8!(71O(@`%H0!A="!O;F-E +MA0`A3VZ0`QMEPP`"Y`(R<')O.@$!A0%18W1L>2W,``!(!E)U='!U=.\"`&`$ +M\0-O8FIE8W0M2!F)M96UO +M?\`!8P``0`"\05R;W9I9&4@96%S>2UT;RUU8<``J,!!H`%,7=A;H@`$'0V!`5%`0!@ +M``'Z"0".!R%S:RP#`WX&N6-O;G9E;FEE;F-EP`$`B0`P;6%K>0"0:7,@97-P +M96-I;@0!T`$"J@$`.@@P.B`BDPH.NPH3(KD"(&QL/`$"Z`(`I0<`$0,"P040 +M+&,`0&1EH($',+!0$^`0!U```7`@#Y!`%Q``%Q"@B7```\"3-Y+C--``#O +M!#)E(")K`P6K``$D`!0B"PM9(&-L87-$``$?"49N86QSG0`2!Q(M@@0U"`"X!!,B!0XR+F@BJ0`R:&4* +M7PP0(+`)`/H``!0`!.D&`W((`G\"-&UO5$P"9!F!E2X`L2`H8FEG+65N9&EAU!%C;&ET=&QE$0`"QP`$ +M7Q:10T0M4D]-(&EMMP(0*#@.,"!O<,L#P&%L(%)O8VMR:61G9>\!`DD`#QX78P\+%P#036EC@`/`#;&EB +M2!A2XS30`"=`%U +M(G-T2!C;&%S1`"6:6YT97)N86QSG0!@2!E2QN``5H`W!U=&]M871I_P(0>68!,&5C=)D#$635``,<`E!O;&QO=Y,!$&8L +M`#!S.@K?!#%'3E5U`0(U`B8@*+D!`!H`06QO;F=5`F)N86UE`*%35E(T($%30TE) +M=`(!%``"4P`/,@`%84)I;F%R>2X`H"`H8FEG+65N9&GS!(-R(&QI='1L91$` +M`OH`\0))4T\Y-C8P($-$+5)/32!I;;<"@"AW:71H(&]P^@7`86P@4F]C:W)I +M9&=E10!B2F]L:65T*0$![P$"20`T6DE05@,$0`#`=6YC;VUP[`@0]`5HW+5II<"8`V$UI8W)O`,(KP)@:&%N9&QENP(0>;<#`+8$!K@",&)E9DH# +M<&5V86QU873*`@`@``.9`P+/`A!U]@40;W$"`+8"`D,"`0H`$2"#`:)24$T@ +M=W)A<'!E3@)%9WII<#X!,6EO;A@!76)Z:7`R%@`$?`%-+TQ:5QT`HFQZ;6$L +M(&QZ:7`3`R]X>B,``!DT%``)"`&58V%N(&-R96%TSP`!=00/!@$"`J\!`[\# +M`KP"#Q\#&,$B0`&@`2P:7,@9&5S:6=N962C"R)B +M9;X"`$`$`3`$.&YE=[4#`/`$`'L``Y\!`'L``8<)`:,``DH,`PH#`#@(`+(` +M`1X#`*8$`@P"(2!B-PEQ6"@(J`2%/;C\(`/<,`G@&`0(*(VYD +M^``!B`E086QW87E&`0#=`2IE9(H(`D<`<$DG=F4@870M#0",!]!T;R!M:6YI +M;6EZ92!S#@T28U((07!O;&R4#5$N("!)9O4(0&1O;B?6!P&V`%!I8VET;-D) +M@79O:V4@82!PZP`!?PHQ9F5A-`LP*'-U+P$%^PH`J0`@(&'I``0 +M`P&@`A!MV`$32X'<70@82!T:6U7`W%O8!(71O +M(@`%2@!A="!O;F-EA0`B3VX<#@O#``+D`C)P@``S0*%82!S;V-K970^`TEW:7-HN@0!)@\#60\` +M4X.``P1$2(A`0!:""`L(E`(L2P@8V%P86)I;&ET +M]@($`P$%\0`"\P\!MP0(]@4!EP&`(&EN9&EV:61L#@/;"`"%``(5!@!"``!R +M"P#1```V`2%T;W@',&1A=-<```4.%CHN`0+("0`]`!)A[`(`R0H!*P`S:6X@ +M)P$`CP(S861DC@(88?<,`=<'`QX/469I60!`,P` +M`*,!!H`%,7=A;G\%$G0=#P$V`@%;`P$:!!!TC@0#`',*T2!S +M87ES+@I214%$3442!@9)$>$@8G5N9&QE+@H*475E<_H"H#\@($ES+%1`G +MD1(`\A$`%@)S82!F=6QL+98(F-%#A)B!P`2>`<``$D!`)()`"<`02H@97@;$T!S.B!3,@-4 +MO&0,D!`"3``!.`/``+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C_P`` +M`@`0+60"`)\`!*@``-D."*($$BP:#@#7"P!9"P]D&O__________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M________________________________________________55!E;6]R>341 +M``#P)B!A;F0@861D(&ET('1O(&$@=&%R(&%R8VAI=F4@=VET:&]U=`H@("!F +M:7)S="!W``-:``!V``!-`/($92!T:&4@9&%T82!D +M:7)E8W1L>8<`\01S;V-K970N("!)9B!Y;W4@=V%NB``2=%T`$B\]``!@`#!I +M97,S`%!D:7-K+$X`\`QR92!A2!E87-Y+@H*("H@3F]T93H@(G!A>"!I +M;G1E'1E;F1E9#@!`B(`$"QC +M`$!D97-PWP!`=VAA=)8`\`,@;F%M92!S87ES+@I214%$3450`$0@;&EB;0'1 +M8G5N9&QE+@H*475E6H`)V%T:0`K871H`&ES:6UP;&6U`$!T;V]L,P$`0``# +M`@!R>F-A="P@8@<`$G@'``!)`4!S=6-H)P!0*B!E>&%)`$!S.B!3,@-4P``7P%Q875T:&]R<\`%42!A;GD@\@(``050+@H*5&B=`3!P+6P, +M!`-V!3!O'2(`#!P=71>`C`@(F,T!A$B)`-I9"!T +M;V]L30`"5@$&ZP,`%`=!'!L@P(#+P,`0@$"(0`$F@,#,P``B`0/ +M-``+`"(`##4`+V%T-``,*&%T,P`&`0:`+C,@9VEV97/?!H!O=F5R=FEE=_," +M`*``!+L%$&%Q!3!W:&^1`A0J[`B%7W)E860N,RP0``&["`T1`%%?9&ES:Q8` +M`GX'`RH)`3X``QP``)D`$'9?`0*W`F%E9"!C86R)!Q!SU`9!;F-E2XS!`,!JP(2(FL#!:L``20`4"(@ +M=71II`59(&-L87-$``$?"49N86QSG0`P=H+`#L'`2,)@&%U=&]M871I_P(0><$",&5C=)D#$60Y"0,<`@5X"1!F +M+``!MP91*B!'3E5U`0(U`B8@*`0+`!H`06QO;F=5`@"M"R)S+!````4+`;X+ +M$G,W`E)S<&%RB,``!DT%``)"`$```I58W)E873/``$M +M"0\&`0("J@,#OP,"O`(/'P,8,")R9:`-46-T960B1P,"3P#$+"!W:&EC:"!W +M:6QLB@`!5@`%R@%A(&5X8V5P0`4`N04!RA`!:A`Q:&%T0PXQ:7)E40`!`1`! +MR@(@("A3"@$T!`"$`0-$!`#T`V`L(&5T8RGO"P+Z`P"I`@!H$0*-``&&`0+: +M``^6`P4!R`-A(FYE=V,BFP,!,P`G`3AN97>U`P#P!`#]`@-S!`![``&'"0&C``)*#`!-$2)I +MF4@``%1`0.;`")E +M;LD!!RT``'P`"W$`*&1E$0`#Q@(1+.4)`H```(T.`)8!`!8!`$``,&%G8?,/ +M`5\*D6-O7L#$7`U`-%A=&5V97(@8FQO8VMS\``` +M[@2X' +M$'1[%R%I;5<#<6]R(&UM87`I`0!>$P'Y%@*Y%P"V`A!GPA<0:2(3`2(`!4H` +M`.,3(6-EA0`A3VZ0`QMEPP`"Y`(R<')O.@$!A0$`FA<1+P"`8`.`-$9,VEN("FEP,A8`!"8`32],6E<=`/D#;'IM82P@ +M;'II<"P@86YD('AZ(P#!"DYO=&5S(&%B;W5TE`!R;&EB=$`\"YT96-T +M=7)E.@H*("H@5&AI48!`-T! +M\@%E9"!A=71O;6%T:6-A;&QY1P"P22=V92!A='1E;7#7`>!T;R!M:6YI;6EZ +M92!S="L`L"!L:6YK('!O;&QUN`'A+B`@268@>6]U(&1O;B?L`0"V`/$":6-I +M=&QY(&EN=F]K92!A('#K`(!U;&%R(&9E85D"0"`HD`!RT` +M!P8#`(`!`ID!<"DL(&ET('=P`/``(&=E="!P=6QL960@:6XN/@`G26YN`#``%1`0.;`")E;LD!!RT``#X`"W$`*&1E$0`#Q@(1+/```H``(FYEC@(` +M%@$`0`!B86=A:6YS1P*@8V]R7L#$7`U +M`-%A=&5V97(@8FQO8VMS\``0:$,$(6ETH0!!66]U717`F$@82!T:6U7`W%O`+$@(&)S9'1A3X`!8P``0`"\05R +M;W9I9&4@96%S>2UT;RUUX`0!V``*4`0"A`P&3 +M``)/!R)L>8<``J,!!H`%,7=A;H@`$'0V!`5%`0!@`!!IA0(`C@%EB!$!G +M&%)`$!S +M.B!3,@-4`0-)`#!C;VY# +M`O`".B`@5F%R:6]UP``7P%V875T:&]R,& +M`4D!A69I9W5R92`M#``"1`"U'2(`")P==8-(")C-`81(B0#`#@,*6]L30`"5@$&ZP,!*0$` +M%@D`C@$/;0$!`*(&('5SW0H`V@$T90HGL``C92>M``,D!`"3``!.`/``+F%M +M+"!A8VQO8V%L+FTT"0T#[0`P+F%C%P$``@`0+:("`)\`!*@``-D."*($$BP: +M#@#7"P)\`#%M86GV`2-EPH"MP(29:`, +M`!(&0'-E<77J"!!S"P4!/@$`=0``%P(`^00!<0`!<0H(EP``/`DS>2XS30`` +M[P0R92`B:P,%JP`!)``4(@L+62!C;&%S1``!'PE&;F%L]!9!I;@IA(&YU;6+R#!=FD0<$.P'' +M"@I9;W4@2X`L2`H8FEG+65N9&EAU!%C;&ET=&QE$0`" +M^@#Q`DE33SDV-C`@0T0M4D]-(&EMMP(0*#@.,"!O<,L#P&%L(%)O8VMR:61G +M9>\!`DD`-%I)4'4$!$``('5N,0L`)18`UA!@C2H`0#E%PD(`0``"@*<$`4Z`0!U!`\&`0("KP$#OP,"O`(/'P,8,")R +M9:`-`!`6$2)'`P)/`,0L('=H:6-H('=I;&R*``%6``:0`"!E>"T4``("`+D% +M!(D1`@L7`UH7`5$`!>D2,',@*%,*`30$`(0!`S,$`/0#8"P@971C*>\+`OH# +M`*D"!C`0`9L!`MH`#\@#"F$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0%!`); +M`0&)``]9`P`*%@,S5VAE`P(`OP@#U`(2<^8%#V0:____________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________________________________________]34')A=&EO2A$` +M`/,?;BX*("H@;&EB87)C:&EV92UF;W)M871S+C4@9&]C=6UE;G1S('1H92!F +M:6QE(!T`T2!S=7!P;W)T960@8GD>`'!L:6)R87)Y3`#08W!I;RXU+"!M=')E +M90D`\@YA;F0@=&%R+C4@<')O=FED92!D971A:6QE9"!I;E(`D&EO;B!A8F]U +M=$T`XW-E"B`@('!O<'5L87(@F``$>P#S"2P@:6YC;'5D:6YG(&AA``"/`/0:("=D;V,G(&1I2!I +M;@IA(&YU;6)E6]U(#\! +M8"X*"D-U"!I;G1E`*%35E(T($%30TE)=`(!%``"8P`/,@`%84)I;F%R>2X`P"`H8FEG+65N +M9&EA;J(!8VQI='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I;;<"\`DH=VET +M:"!O<'1I;VYA;"!2;V-KFEP/@$Q:6]N!0%=8GII +M<#(6``1\`4TO3%I7'0"B;'IM82P@;'II&-E<$`%`+D%!&D"L"!T:&%T(')E +M<75IE@4G87C*`E(@*&9OU`P#P!`![``-S!`![``&'"0&C`%0@;VYL>0H#`#@(`+(``1X#`*8$`@P" +M(2!B-PEQ4,`4&EN9&5PJ@`E;G0B`0`8"5!A``B; +M`")E;LD!!RT``'P`"W$`*&1E$0`#Q@(1+/```H``(FYEC@(`%@$`0`!B86=A +M:6YS1P*18V]R0 +M`P&@`A!MV`$38!(71O +M(@`%H0!A="!O;F-EA0`A3VZ0`QMEPP`"Y`(R<')O.@$!A0%18W1L>2W,``". +M"5)U='!U=.\"`&`$\0-O8FIE8W0M`%`@(&)S9",'(75SO`$`/06# +M;B!I=',@(D`\`!(BO01&2!F60!`,P``*,!!H`%,7=A;G\%$G0=#P-%`0!@```:!!!TC@0"0:7,@97-P96-I;@0! +MT`$"J@$`.@@P.B`BDPH.V@T3(KD"`-X.(F%NZ`(`I0<`$0,"6@<0+&,`0&1E +M8$(&YDT`(Q9G5L+P(& +M10`0+T,*`84!$6&>"C1A8W1[$X)D96UO;G-T$0(8`+5C;VYF +M:6=U'2(`"%P=6<0,"`B8S0&$2(D`P`X#"EO;$T``E8!!NL#`2D!`!8)`(X! +M#VT!`0"B!A!U/1,"$!P`"-E)ZT``R0$`),``$X`\``N86TL(&%C;&]C +M86PN;30)#0/M`#`N86/_```"`!`MH@(`GP`$J```V0X(H@02+!H.`-<+`%D+ +M$'G*!0'V`2-E!Q(M +M6`D/9!K_____________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_____________U-0:7-T"B`O$0``\R,@("H@5&\@2!F;W(@ +M:L`D'-A;64@9G5N8S`<``$D!0'-U8V@G`%`J(&5X84D`U',Z(%-O;64@6]U(&UA>2!F:6YD('5S969U;"\"!D4`42]M:6YIA0$1 +M8>,!46%C="!S8`"A(&1E;6]N2#R`I!I;VYS+@H*5&B= +M`?("<"UL979E;"!D:7)E8W1O%#36%K94QI\`!,GK0`#)`0`DP``3@#U`2YA;2P@86-L;V-A +M;"YM-"SA`$!E+F%C_P```@`2+50`)'1OJ``,H@2R+"!O;FQY(&YE961\`#%M +M86GV`2-E7-T96TZ +M"B`J(+@$=2XQ(&5X<&R#`@,O`P!"`0(A``2:`P,S``"(!`\T``L`(@`,-0`O +M870T``PH870S``8!!H`N,R!G:79E2XS30`"]P,2(FL#!:L``20`4"(@=71II`59(&-L +M87-$``'O!49N86QSG0`P`D09BP``;<&42H@1TY5=0$"-0(B("BK"0"Y`0`:`$%L;VYG4`9B;F%M +M97,L$`!3;&EN:R`1``!C`%)S<&%R'1E +M;J+``-J`0`9`]$J(%!/4TE8('5S=&%R6P`" +M$``R<&%X-`,"60<#>`('(0"P;V-T970M;W)I96X!`P!@`@$>`*%35E(T($%3 +M0TE)=`(!%``"4P`/,@`%84)I;F%R>2X`P"`H8FEG+65N9&EA;J(!8VQI='1L +M91$``OH`\0))4T\Y-C8P($-$+5)/32!I;;<"$2AX""!O<,L#P&%L(%)O8VMR +M:61G944`8DIO;&EE="D!`>\!`DD`-%I)4%8#!$``('5N,0LPFEP,A8`!'P!32],6E<=`*)L>FUA+"!L>FEP +M$P,O>'HC```9-!0`"0@!```*56-R96%TSP`!=00/!@$"`JH#`[\#`KP"#Q\# +M&#`B&-E +M<$`%`+D%!&D"42!T:&%T0PXQ:7)E40`!\P,!R@(@("@6!0$T!`"$`0,S!`#T +M`V`L(&5T8REF"@+Z`P"I`@8B!`&&`0+:``^6`P4!R`-A(FYE=V,BFP,!,P`G +MD#`*4#(71EVP@P.@H*N!`R:&ESD0]P:&5A=FEL>?P(-F5A;;4%`A$+@"X@ +M(%1H97)E+``C;F_B!P""`@/?"`"3!$$@:6XMMP^"(&UO9&EF:6-D"_``;W(@ +M0`&EP``L!!397-I9VXE#!)EB`4`0`0!7@$X;F5W +MM0,`\`0`>P`#GP$`>P`!APD!HP`"2@P`31$B:7*"$1!I>0<280D!`@P"(2!B +M-PD`C`HQ86)L``8`_0H!#``!+`L"U!``:``".P!"96%C:#T!(79E4,` +M4&EN9&5PJ@`E;G0B`0`8"0`/#Q!C0@42;VP-!C4*5"!7:6MI4@PP:6YGR0`P +M:&]W40\!LP,09$X(`]H``BH!(4]N/P@`]PP"8`8`TQ$`4`8#S0`!<`!3;'=A +M>7-S""IE9(H(`D<`<$DG=F4@870M#0",!S!T;R`A$+)M:7IE('-T871I8U(( +M07!O;&PV$E$N("!)9O4(4&1O;B=TJ`"097AP;&EC:71LV0EB=F]K92!A^@\1 +M8W\*`\X1("`HTA`E(&'["@"A`2`@84$``2<0`BT`",T`%&_Y"'`I+"!I="!W +M<`!!(&=E=!D3`5T*`*0$-R!);FX`-RP@:9X``5$!`YL`(F5NR0$'+0``?``+ +M<0`H9&41``/&`A$L\``"@```C0X`E@$`%@$`0``@86<##A%T\0F18V]RP,B:67-#P&<$P/G"B!D=1D-`)\#$'.%`2-O9H@!`(X2 +M$"UV```S#`#W"!%IM`\`A`!R96YV:7)O;@\+$7>0`P&@`A!MV`$3<3 +M`<0-0&)A8VOR`S%F2W,`))E9"!O=71P=73O`@!@!/$#;V)J +M96-T+7-T>6QE(&%P<')OR`,`^10"^@#0=&\@:&%V92!M=6QT:<,3!*D``@$$ +M`+D(52!O<&5NG@`3(!40`&H0``H!`#T%@VX@:71S(")`/``2(KT$$7,P#@)C +M!098`&!I='-E;&93`5!R96%D+^8`8'1E;B!U@``S0*%82!S;V-K970^`TEW:7-HN@0!)@\#60\`7,N"B05$6:X#007&0.A&$0N"@I1$1:@/R`@ +M27-S=65S/U(`$2H%&78Z+R]W=W7,@9&5T96-T960@875T;VUA +M=&EC86QL>2X*"B`J($DG=F4@871T96UP(@#@=&\@;6EN:6UI>F4@6]U(&1O;B=T"B`@(&5X<&QI8VET;'D@ +M:6YV;VME(&$@<&%R=&EC=6QA2!A8V-E<#4` +MT6%T979E717`G`@82!T:6UEI0!Q;W(@;6UA<'\` +M0&5N=&F?`D!R8VAI?P)`;F0@9PD`(&ET3P``2P$%2@!A="!O;F-EA0"+3VX@ +M=W)I=&7#``+D`C)P2!B=69F97(@;W+!``!E``1R`85A('-O8VME=#X#4'=I2UT;RUU0"0:7,@97-P96-I;@0!T`$"J@'S!TYO +M=&4Z(")P87@@:6YT97)C:&%N9V6?!1,BN0(@;&P\`0+H`A!DO@$`_04!P040 +M+&,`0&1EF-A="P@8@<`$G@'``!)`0"2"0`G`%`J +M(&5X84D`0',Z(%,R`U1S;6%L;!4`!#X!`%(#(6%T'`@@;6'F!"!N9-`",69U +M;"\"!D4`$"]#"@&%`1%A!@E186-T('-@`+`@9&5M;VYS=')A=+'2(`")P=;H+(")C-`81(B0#`!(+*6]L +M30`"5@$&ZP,`E``!%@D`C@$/;0$!`&8(('5SW0H`V@$T90HGL``C92>M``-G +M`0"3``!.`/4!+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_```"`!`MH@(`GP`$ +MJ```:@L(H@1A+"!O;FQYUPL"?``Q;6%I]@$C97*N`05P`"1I;F0`@2YH+FEN +M"@DM]`=2;&%T97-G`!%B-`(#<@$"M0!@"@I'=6ED\P`H($14!@32`0)U``&W +M`7!S>7-T96TZ&@D"N`0A+C'!#`!A#`$W`0,O`P`+``(A``2:`P,S``"(!`\T +M``L`(@`,-0`O870T``PH870S``8!!B$N,[8+$'-E"H!O=F5R=FEE=_,"`*`` +M!<`+`'$%,'=H;Y$"%"JD"H5?PH"MP(29:`,`%L$$'/4!A!N2PT`U@(`DP``=0``%P(` +M^00!<0`!<0H(EP`!G`DC+C--``#O!#)E(")K`P6K``$D`!0B"PM9(&-L87-$ +M``$?"49N86QSG0`2P$2+8($-7,N-:H(`J\``!D#`/T%-6UA=&D/!&,"!98!`+`` +M``H"D"XU+"!M=')E90D``&\`7G1A"`#.#1,BR0TR+F@BJ0`R:&4*7PP0(+`)`/H``!0`!.D&`W((`G\" +M-&UO2X` +ML2`H8FEG+65N9&EAU!%C;&ET=&QE$0`"^@#Q`DE33SDV-C`@0T0M4D]-(&EM +MMP(1*'@((&]PRP/`86P@4F]C:W)I9&=EYP%B2F]L:65T*0$![P$"20`T6DE0 +M=00$0``@=6XQ"P`?$P#6$&!R(")D969^!A$B9@D#&```H00C:655`0##`0"B +M`85"4T0@)V%R)U(``?@`$2?]`Q`GNP($/0%:-RU::7`F`-A-:6-R;W-O9G0@ +M0T%"+``Q3$A!"@,Z3%I(,@`Z4D%2$0`86!$``1D(!2`&`/42"*\"`'82`"H( +M`,,/`TP&!D4(,&)E9DH#4F5V86QU0@H`K@,#+P(`'P@P*B!U]@40;Q@$``L% +M`D,"`0H``EP)L5)032!WFEP,A8` +M!'P!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9-!0`"0@!```*`IP0!3H! +M`'4$#P8!`@*O`0._`P*\`@\?`Q@P(G)EH`T`$!81(D<#`D\`Q"P@=VAI8V@@ +M=VEL;(H``58`!I``(&5X+10``@(`N04$B1$":Q0`0PX`TQ,`40`%Z1(PA@!+1`0:2`*<&AE879I;'G\"#9E86VU +M!0(1"P6(%$!I0`&@`0I:7-N%")B98@%`$`$`5X!.&YE=[4#`/`$ +M`/T"`Y\!`'L``8<)`2L5`DH,`PH#`#@(`&\0%'3N$@(,`B$@8C<)`(P*`8\8 +M`[@4`0P`$&$,`0+4$`!H``([`!%EG!8`/0$A=F5S`Q-Y0P!0:6YD97"J`"5N +M="(!`$0-`7D9`$(%$F]L#0:P"U0@5VEK:5(,`PP3,&AO=U$/`;,#$&2M`0/: +M``+W$P4T&`3\!`#S#@!0!@/-``%P``*`%P+$!0]D&O__________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M________________________________________________5E!L97,I"BP1 +M``#P)"`@*B!3;VQA +M`*935E(T($%30TE)%``"8P`/,@`%84)I;F%R>2X`\P<@*&)I9RUE;F1I86X@ +M;W(@;&ET=&QE$0`"QP#P'TE33SDV-C`@0T0M4D]-(&EM86=EFEP/@$Q:6]N1`!=8GII<#(6``1D`4TO3%I7'0"Q;'IM82P@ +M;'II<"S'`"]X>B,``!DT%``)"`&58V%N(&-R96%TSP!/&-E<'0"`D0*("`@:0+1('1H870@0`&EP"0:7,@9&5S:6=NH@9";R!B98@%`$`$`3`$ +M.&YE=[4#`-P#`'L``4,`4&EN9&5PJ@`B;G1_`!!R.P0`!``P=&EC0@4D;VZ!`02N +M`/``5VEK:2!E>'!L86EN:6YGB0`P:&]W^``!LP,09)8%`RP``BH!(4]NJ@`< +M+`,!``0$,FUA='``0&QW87E&`0#=`?(!960@875T;VUA=&EC86QL>4<`L$DG +M=F4@871T96UPC`?@=&\@;6EN:6UI>F4@2!I;G9O:V4@82!PZP`@=6Q9"*!E +M871UP,1<#4`T6%T979E`%`@(&)S9",'(75SO`$`/06#;B!I=',@(D#E +M`!(BO01&P`28D(``$X&`-$``#8!(71OFPDP9&%TUP!6=7)C93HN`0+( +M"0#"`!)A[`(`R0H!*P`S:6X@)P$`E0LS861DC@(88?<,`=<'(6]U]P119FER +M0"0:7,@97-P96-I +M;@0!T`$"J@$`.@@P.B`BDPH.V@T3(KD"(&QL/`$"Z`(`I0<`$0,"P040+&,` +M0&1E%EF-%#A)B +M!P`2>`<``$D!`)()`"<`4"H@97AA20!`8$(&YDT`(Q9G5L+P(&10`0+T,*`84!$6&>"E%A8W0@'2(`")P==8- +M(")C-`81(B0#`#@,*6]L30`"5@$&ZP,!*0$`%@D`C@$/;0$!`+`,$'4]$P': +M`31E"B>P`"-E)ZT``#H/,"`J(),``$X`\``N86TL(&%C;&]C86PN;30)#0/M +M`#`N86,7`0`"`!`MH@(`GP`$J```V0X(H@02+!H.`-<+`%D+$'G*!0'V`2-E +MPH"MP(`318A86R)!T!S97%UZ@@0 +M=&%R+C54`0CQ +M!`4^$A%S8P0Q<&]PY0\#G`$$>P`(2PE`:&%R9!8,`3`&`J@!`X42`(X!86UO +M9&5R;H\``.@!`+P'<"!V87)I86Y("0`B##!M86[X"Q%PK1]!;!I;@IA(&YU;6)E"`"X!!,BXP`R+F@BJ0`R:&4*7PP0(+`) +M`/H``!0`!.D&`W((`G\"$&T:%P/[`$(N("!0B@FR;&5T('5S"FMN;W<0`0&9 +M!F!E`D09@82`;<&`H<8!JH+"``:`/@5#"`6`1````4+ +M`;X+$G,W`E)S<&%R%#36%K94QIM``-G`0"3``!.`/4!+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_```" +M`!(M5``D=&^H```@`3!D:7-?`A!U00&R+"!O;FQY(&YE961\`#%M86GV`2-E +M7-T96TZ"B`J +M(&)S9'1AM`_`$,R!G:79E2XS!`,!JP(2(FL# +M!:L``20`Z2(@=71I;&ET>2!C;&%S1`"6:6YT97)N86QSG0!@P$2 +M+8($4W,N-2!D5@(#I@0@:6QV`]1R;6%T-50!"/$$4&%B;W5T&@$@P"`+"!I;F-L=62*`<5H87)D+71O+69I;F1;`0%'``!!`&%M;V1E +M$D# +M(F5R60<#>`('(0"P;V-T970M;W)I96X!`P!@`@$>`*%35E(T($%30TE)=`(! +M%``"4P`/,@`%,$)I;LH$`$(`H"`H8FEG+65N9&GS!(-R(&QI='1L91$``OH` +M\0))4T\Y-C8P($-$+5)/32!I;;<"$2AX""!O<,L#P&%L(%)O8VMR:61G944` +M8DIO;&EE="D!`>\!`DD`-%I)4%8#!$``D'5N8V]M<')EFEP,A8`!&0!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC +M```9-!0`"0@!```*56-R96%TSP`!=00/!@$"`JH#`[\#`KP"#Q\#&#`B&-E<$`%`+D% +M!&D"T2!T:&%T(')E<75IP`#GP$`>P`!APD!HP`"2@P#"@,`.`@`L@`!'@,`"0$"#`(A(&(W +M"0!J"#%A8FP`!@","@$,``$L"P($`0!H``([`$)E86-H/0$A=F5S`Q-Y0P!0 +M:6YD97"J`"5N="(!`!@)``\/$&-"!1)O;`T&-0I4(%=I:VE2##!I;F?)`&-H +M;W<@=&_U``>6"@(J`2%/;C\(`/<,`G@&`P,!`_@``8@)4&%L=V%Y1@$`W0$J +M962*"`)'`'!))W9E(&%T+0T`C`<`P0^0:6YI;6EZ92!S#@T28U((07!O;&R4 +M#5$N("!)9O4(4&1O;B=TJ`"097AP;&EC:71LV0EB=F]K92!A^@\18W\*,69E +M830+,"AS=2\!!?L*`*D`("!A00`1P,1<#4`T6%T979EP"`,D*`2L`,VEN("#U%F:7)S=)("`*8!$6%P$A%O61$`]@`6+G0` +M`]D#`J60!`,P``*,! +M!H`%,7=A;G\%$G0=#P-%`0!@```:!!!TC@0#`',*+%1`G-Q,`C!4`%@)S82!F=6QL+98(7,@<')O9'5C97,@8V]R6]U('1O(&AA=F4@;75L=&EP)0`P`/,- +M("!B2!D8737`%9UX`0!V``*4`0`` +M`P&^``7+`0#3``.C`4,N("!)I`$A86Z(`!)T70`!-@(491\!`#L!061I"!I;G1E&%)`$!S.B!3,@-4`0-)`#!C;VY#`O`".B`@5F%R +M:6]UP``7P%Q875T:&]R<\`%`1\&`?("`DT'$`H5"%!T;W`M;`P$`W8%`#`' +M`4$`$&DD!0FV`B)I;O@$(FEOX08$O0+P`DY%5U,@+2!H:6=H;&EG:'1S7`8P +M'2(`#!P=71>`C`@(F,T!A$B)`,`J@2!N +M965D?``Q;6%I]@$C97*N`05P`"1I;F0`@2YH+FEN"@DM]`=2;&%T97-G`!%B +M-`(#<@$"M0!@"@I'=6ED\P`H($14!@32`0)U``#S`8`@PH" +MMP(A960N"P!;!!!SU`80;A$,`-8"`),``'4``!<"`/D$`7$``7$*")<``9P) +M(RXS30``[P0R92`B:P,%JP`!)``4(@L+62!C;&%S1``!'PE&;F%L]!9!I;@IA +M(&YU;6+R#!=FD0<#HP#7+@H*66]U('-H;W5L9*0+`$P`,6-O<'8&0&-O;6V> +M"`#.#1,BR0TR+F@BJ0`R:&4*7PP0(+`)`'4!`!0`!.D&`W((`G\"-&UO@,QBH@4U92-"!!4T-)210``E,`#S(`!6%" +M:6YA`@@;W#+`\!A;"!2;V-K[`@0]`5HW+5II<"8`V$UI +M8W)OFEP/@$Q:6]N&`%= +M8GII<#(6``1\`4TO3%I7'0"B;'IM82P@;'IIP`!APD!*Q4"2@P`31$B:7*"$1!I>0<#[A(" +M#`(A(&(W"0","C%A8FP`!@","@$,`!!A#`$"U!``:``".P!"96%C:#T!(79E +M4,`4&EN9&5PJ@`E;G0B`0!$#0`/#Q!C0@42;VP-!K`+5"!7:6MI4@P# +M#!,P:&]W40\!LP,09*T!`]H``O<3(4]N/P@`]PP"8`8`\PX`4`8#S0`!<``" +M@!<"Q`4J962*"`)'`'!))W9E(&%T(14`C`'!L:6-I=&S9"6)V;VME(&'Z#Q%C?PH#SA$@ +M("C2$`!U#`@<`A!AL@$!)Q`"+0`(S0`4;W,$<"DL(&ET('=P`%`@9V5T(-(2 +M`5T*`*0$-R!);FX`!287`9X``5$!`YL`(F5NR0$'+0``?``+<0`H9&41``.J +M`!$L6!$"@```C0X`E@$`%@$`0``P86=A\P\!7PJ18V]R7L#$7`U`&)A=&5V97)X%Q%S\```[@$P'Y +M%@*[&0"V`A!GQ!D0:2(3`2(`!4H``.,3#V0:________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________________________________________](4'(*("`J-Q$``/T, +M(&=Z:7`@8V]M<')EFUA +M+"!L>FEP+"!A;F0@>'HC```9-!0`\3(*5&AE(&QI8G)A&-E<'1_`/$* +M"B`@("!E;G1R:65S('1H870@$E33SDV-C`3`%HW +M+5II<#D`-EA!4A$`0PI7:&4#`@#D`00%`A$L_`%A2!S=')E86WM +M`>!S>7-T96TN("!4:&5R92P`D&YO(&1IP`!S@`4=E@#$G.C +M`%0@;VYL>0H#0&UE;G2R``$>`P+``P"#`R`@8H\!D"!R96%D86)L9:(`07=R +M:70,`!!A#`$"!`$!1`0!.P!$96%C:"8"`98"$WE#`%!I;F1E<*H`(FYT?P`0 +M$N("!)9B!Y;W4@9&]N)^P!`+8`\0)I8VET;'D@:6YV +M;VME(&$@<.L`('5L-P0@96%9`D`@*'-U+P$9``%1`0.; +M`")E;LD!!RT``'P`"W$`*&1E$0`#J@`1+/```H``(FYEC@(`%@$`0`!B86=A +M:6YS1P*@8V]RP,1<#4`T6%T979E2!B=69F97(@)`@`90`$<@&%82!S;V-K +M970^`TEW:7-HN@3`P"`,,)`2L`,VEN("0#`',*T"!S87ES +M+@I214%$346[!@?H!N$@8G5N9&QE+@H*475E<_H"H#\@($ES7!1`GH@1`9W)A;18"F-%#A)B!P`2>`<``$D!`)()`"<` +M4"H@97AA20!`8$(&YDT`(Q +M9G5L+P(&10`0+T,*`84!$6&>"E%A8W0@H($',+!0$^`0!U```7`@#Y!`%Q +M``%Q"@B7```\"3-Y+C--``#O!#)E(")K`P6K``$D`!0B"PM9(&-L87-$``$? +M"49N86QSG0`2!Q(M@@0U +M"`"X!!,B!0XR+F@BJ0`R:&4*7PP0(+`)`/H``!0`!.D&`W((`G\"-&UO5$P`P%&!E2X`L2`H8FEG+65N +M9&EAU!%C;&ET=&QE$0`"QP`$7Q:10T0M4D]-(&EMMP(0*#@.,"!O<,L#P&%L +M(%)O8VMR:61G9>\!`DD`#QX78P\+%P#036EC2$`\AMU7-T96TZ"B`J(&)S9'1A@ +M`/`#;&EB2!A2XS +M30`"=`%U(G-T2!C;&%S1`"6:6YT97)N86QS +MG0!@P"`+"!I;F-L=62*`<5H87)D+71O+69I +M;F1;`0%'``!!`&%M;V1E``"/`/`-("=D;V,G(&1I2!I +M;@IA(&YU;6)E2!E2QN``5H`W!U=&]M871I_P(0>68!,&5C=)D#$635``,<`E!O;&QO +M=Y,!$&8L`#!S.@K?!#%'3E5U`0(U`B8@*+D!`!H`06QO;F=5`F)N86UE`*%35E(T +M($%30TE)=`(!%``"4P`/,@`%84)I;F%R>2X`H"`H8FEG+65N9&GS!(-R(&QI +M='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I;;<"@"AW:71H(&]P^@7`86P@ +M4F]C:W)I9&=E10!B2F]L:65T*0$![P$"20`T6DE05@,$0`"0=6YC;VUP[`@0]`5HW+5II<"8`V$UI8W)O`,(KP)@:&%N9&QENP(0>;<#`+8$!K@" +M,&)E9DH#<&5V86QU873*`@`@``.9`P+/`A!U]@40;W$"`+8"`D,"`0H`$2"# +M`:)24$T@=W)A<'!E3@)%9WII<#X!,6EO;A@!76)Z:7`R%@`$?`%-+TQ:5QT` +MHFQZ;6$L(&QZ:7`3`R]X>B,``!DT%``)"`&58V%N(&-R96%TSP`!=00/!@$" +M`J\!`[\#`KP"#Q\#&,$B0`&EP"P:7,@9&5S +M:6=N962C"R)B9;X"`$`$`3`$.&YE=[4#`/`$`'L``Y\!`'L``8<)`:,`5"!O +M;FQY"@,`.`@`L@`!'@,`"0$"#`(A(&(W"7%R96%D86)L``8`C`H!#``!+`L" +M!`$`:``".P!"96%C:#T!(79E4,`4&EN9&5PJ@`E;G0B`0`8"5!A`8!`@HC;F3X``&("5!A;'=A>48!`-T!*F5DB@@"1P!P22=V92!A="T- +M`(P'T'1O(&UI;FEM:7IE(',.#1)C4@A0<&]L;'4B!U$N("!)9O4(0&1O;B?6 +M!P&V`%!I8VET;-D)@79O:V4@82!PZP`!?PHQ9F5A-`LP*'-U+P$%^PH`J0`@ +M(&'I``2UV```S#`#W"!%IAP8`A`!P96YV +M:7)O;M<",7,@=Y`#`:`"$&W8`1-R6@,%,`(`6P`"?P`1>7L#$7`U`-%A=&5V +M97(@8FQO8VMS\```[@@``8P2%82!S;V-K970^`TEW +M:7-HN@0!)@\#60\`4X.475S92`B(0$`6@@@+")0 +M"+$L(&-A<&%B:6QI=/8"!`,!!?$``O,/`;<$"/8%`9P"`,D*`2L`,VEN("#U%F:7)S=)("`*8! +M$6%P$A%O61$`]@`6+G0``]D#`J60!`,P``*,!!H`%,7=A;G\%$G0=#P$V`@%;`P$:!!!TC@0#`',*T2!S87ES+@I214%$3442!@9)$>$@8G5N9&QE+@H*475E<_H" +MH#\@($ES+%1`GD1(`\A$`%@)S82!F=6QL+98(F-%#A)B!P`2>`<``$D!`)()`"<`02H@ +M97@;$T!S.B!3,@-4O&0,D!`"3``!.`/``+F%M+"!A8VQO8V%L+FTT +M"0T#[0`P+F%C_P```@`0+60"`)\`!*@``-D."*($$BP:#@#7"P!9"Q!YR@4! +M]@$/9!K_____________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_____________V=08VAI=F4G$0``\#T@=VET:&]U=`H@("!F:7)S="!W2!F6]U('=A;H@`$G1=`!`OB@`196``,&EE +M7,N"E)%041-12X`1"!L:6(3 +M`=%B=6YD;&4N"@I1=65SK@"@/R`@27-S=65S/U(`UBH@:'1T<#HO+W=W=RXX +M`$`N;W)GDP``2`$Q:&]MIP"`(&]N9V]I;F`<``$D!0'-U8V@G`%`J(&5X84D`0',Z(%,R`U1S +M;6%L;!4`!#X!`%(#(6%T?`2`;6%Y(&9I;F30`C%F=6PO`@9%`%$O;6EN:84! +M$6'C`5%A8W0@2#R`@`!!5`N"@I4:)T!,'`M +M;`P$`W8%,&]R>3$%,'1A:20%";8"(FEN^`0Q:6]NZP4$O0+P"4Y%5U,@+2!H +M:6=H;&EG:'1S(&]F(')E8P8"`C$%`Z`"DD-/4%E)3D<@+0P%`,T%`"@&(F1O +MGP``AP4`S@#R!"H@24Y35$%,3"`M(&EN\`!,G +MK0`#)`0`DP``3@#U`2YA;2P@86-L;V-A;"YM-"SA`$!E+F%C_P```@`0+:(" +M`)\`!*@`#*($LBP@;VYL>2!N965D?``Q;6%I]@$C97*N`05P`"1I;F0`@2YH +M+FEN"@DM]`=2;&%T97-G`!%B-`(!9@$39;4`8`H*1W5I9/,`*"!$5`8$T@$" +M=0`!MP%P!1%E +M^P,`\@"`;6%T]!;!I;@IA(&YU;6)E"`"X!!,B?P(R +M+F@BJ0"`:&4*`D09BP``;<&42H@1TY5=0$"-0(F("@$"P`:`$%L;VYG50(`K0LB+``-J`0`9`]$J(%!/4TE8('5S=&%R6P`"$``/B@P#!R$`P&]C=&5T +M+6]R:65N=!<$,7!I;QX`IE-64C0@05-#24D4``)3``\R``5A0FEN87)Y+@#` +M("AB:6FEP,A8` +M!'P!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9-!0`"0@!```*56-R96%T +MSP`!+0D/!@$"`JH#`[\#`KP"#Q\#&#`B&-E<$`%`+D%!FH0,6AA=$,.$&F6!2=A>,H" +M("`H%@4!-`0`A`$#1`0`]`-@+"!E=&,I[PL"^@,`J0(&,!`!A@$"V@`/E@,% +M`<@#82)N97=C(IL#`3,`)W-HL``!$@`/1@-C!`4$`EL!`8D`#UD#``H6`S-7 +M:&4#`@C1#@+F!6%R97-U;'1-$A%B:`4@=&6[#@%5!`\C`@$*"P,!@``/Z0)4 +M$`HJ$@&G!P(F"`:A!@`^!R%T9=L($3I4$@$M$!!I(`IP:&5A=FEL>?P(-F5A +M;;4%`A$+<"X@(%1H97(T$2`@;M82,7)E8S`1`]\(`),$02!I;BVW#X(@;6]D +M:69I8^4,\`!O`3AN97>U`P#P!`#]`@-S!`![``&'"0&C``)*#`!-$2)I7-S""IE9(H(`D<`<$DG=F4@870A%0",!S!T;R`A$'!M:7IE +M('-TM0@"4@A!<&]L;#82!N04061O;B?L`7!E>'!L:6-I#15@:6YV;VMEO!(! +MZP`!?PH#SA$@("C2$"4@8?L*`*$!("!AL@$!)Q`"+0`(S0`4;_D(<"DL(&ET +M('=P`$$@9V5T&1,!70H`I`0W($EN;@`R+"!I@A4!G@`!40$#FP`B96[)`0"(&5N=FER;VX/"Q%WD`,!H`(0 +M;=@!$W):`P4P`@!;``)_`!%Y>P,1<#4`T6%T979E:89`@4.%CHN`0+("0`]`!)A +M[`(!@`X`T1DS:6X@)P$`104U861D'`$`_`@$J@$`>08/9!K_____________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_____________________________________________________V502!O9B!T:&4@9F]L +M;&]W:6YG.@H@("H@=75E;F-O9&4-`/$!9WII<"!C;VUPFUA+"!L>FEP+"!A;F0@>'HC`,$*3F]T97,@ +M86)O=724`/`[;&EB2!A2!S=')E86TM;W)I96YT960@P`!S@`0=G(!4G)M871SHP#P`B!O;FQY(')E<75I4,`4&EN9&5PJ@`B;G1_`$%R92!A!`"4 +M=&EC;&5S(&]N@0$$K@#P`%=I:VD@97AP;&%I;FEN9\D`,&AO=_@``O4`!RP` +M`BH!(4]NJ@`<+`,!`',!,FUA='``0&QW87E&`0#=`?(!960@875T;VUA=&EC +M86QL>4<`L$DG=F4@871T96UPUP'@=&\@;6EN:6UI>F4@2!I;G9O:V4@82!P +MZP"`=6QA8`0U:``)[`S%I97/#``%O`[!A;'-O(')E9'5C99L" +M,&4@0"0:7,@97-P96-I;@0!T`$"J@$`.@CS`SH@(G!A +M>"!I;G1E7!1`GH@1`9W)A;18"`<``$D!`)()`"<`4"H@97AA20!`8$(&YDT`(Q9G5L+P(&10`0+T,*`84!$6$& +M"5%A8W0@`0-)`#!C;VY#`O`".B`@ +M5F%R:6]UP``7P%V875T:&]R,&`4D!A69I +M9W5R92`M#``"1`"U'2(`")P==8-(")C-`81(B0#`#@,*6]L30`"5@$&ZP,!*0$`%@D`C@$/ +M;0$!`*(&('5SW0H`V@$T90HGL``C92>M``,D!`"3``!.`/``+F%M+"!A8VQO +M8V%L+FTT"0T#[0`P+F%C%P$``@`0+:("`)\`!*@``-D."*($$BP:#@#7"P)\ +M`#%M86GV`2-EPH"MP(29:`,`%L$0'-E +M<77J"!!S"P4!/@$`=0``%P(`^00!<0`!<0H(EP``/`DS>2XS30``[P0R92`B +M:P,%JP`!)``4(@L+62!C;&%S1``!'PE&;F%L]!9!I;@IA(&YU;6+R#!=FD0<$.P''"@I9;W4@ +M2X`L2`H8FEG+65N9&EAU!%C;&ET=&QE$0`"^@#Q`DE3 +M3SDV-C`@0T0M4D]-(&EMMP(0*#@.,"!O<,L#P&%L(%)O8VMR:61G9>\!`DD`-%I)4'4$!$``('5N,0L`)18`UA!@C2H +M`0#E%PD(`0``"@*<$`4Z`0!U!`\&`0("KP$#OP,"O`(/'P,8,")R9:`-`!`6 +M$2)'`P)/`,0L('=H:6-H('=I;&R*``%6``:0`"!E>"T4``("`+D%!(D1`@L7 +M`UH7`5$`!>D2,',@*%,*`30$`(0!`S,$`/0#8"P@971C*>\+`OH#`*D"!C`0 +M`9L!`MH`#\@#"F$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0%!`);`0&)``]9 +M`P`*%@,S5VAE`P(`OP@#U`(2<^8%7W)E1X`\`EL +M:6)R87)Y"B`J(&-P:6\N-2P@;71R964)`/(.86YD('1A3`1!F+`"@FEP,A8`!'P!32],6E<=`*)L>FUA +M+"!L>FEP$P,O>'HC```9-!0`"0@!E6-A;B!C,H"4B`H9F]R-`0` +MA`$#,P0`]`-Q+"!E=&,I+F\!`/H#`*D"!B($`1<``MH`#Y8#!0'(`V$B;F5W +M8R*;`P$S`"=S:+```1(`#T8#8P0%!`);`0&)``]9`P`*%@,S5VAE`P(`V`(# +MU`(2<^8%87)E``B;`")E;LD!!RT``'P`"W$`*&1E$0`# +MQ@(1+/```H``(FYEC@(`%@$`0`!B86=A:6YS1P*18V]RP,Q:65SPP`!;P,#YPHQ9'5CN04P92!SA0$C;V:(`0`]"A`M=@``,PP` +M]P@1:8<&`(0`<&5N=FER;V[7`C%S('=N`@&@`A!MV`$32W,``"."5)U='!U=.\"`&`$\0-O8FIE8W0M`%`@(&)S9",'(75SO`$`/06#;B!I=',@(D`\`!(BO01&2!F#U%F:7)S=)("`*8!(&$@0P40;\,/`=X*%BYT``/9`P*G +M`0"_``*<`0&%``:X`0!V``##``"\`Q)EDP`",0\@;'ED`0#,``"C`0:`!3%W +M86Y_!1)T'0\!-@(!6P,`8PP`,P!!9&ES:RP#`WX&N6-O;G9E;FEE;F-EP`$` +MB0`P;6%K>0"0:7,@97-P96-I;@0!T`$"J@$`.@@P.B`BDPH.V@T3(KD"`-X. +M(F%NZ`(`I0<`$0,"6@<0+&,`0&1E`0-)`#!C;VY#`F$Z("!687+N$V!I=&5MH(`N47`),``'4` +M`!<"`/D$`7$``7$*")<``9P)("XSHQ:L`D'-A;64@9G5N8S`<``$D!0'-U8V@G`%`J(&5X +M84D`U',Z(%-O;64@6]U(&UA>2!F:6YD('5S +M969U;"\"!D4`42]M:6YIA0$18>,!46%C="!S8`"A(&1E;6]N2#R`I!I;VYS+@H*5&B=`?("<"UL979E;"!D:7)E8W1O%#36%K94QI\`!,GK0`#)`0` +MDP``3@#U`2YA;2P@86-L;V-A;"YM-"SA`$!E+F%C_P```@`2+50`)'1OJ``, +MH@2R+"!O;FQY(&YE961\`#%M86GV`2-E7-T96TZ"B`J(+@$=2XQ(&5X<&R#`@,O`P!"`0(A``2: +M`P,S``"(!`\T``L`(@`,-0`O870T``PH870S``8!!O`%+C,@9VEV97,@86X@ +M;W9E] +M!;!I;@IA(&YU;6)E"`"X!!,BO0(R+F@BJ0"`:&4*2R"```[!P$C"4!A=71O +MDP8`_P(0><$",&5C=)D#$635``,<`@5X"1!F+``!MP91*B!'3E5U`0(U`B(@ +M**L)`+D!`!H`06QO;F=0!F)N86UEB,``!DT%``)"`$```I58W)E873/ +M``%U!`\&`0("J@,#OP,"O`(/'P,8,")R9:`-46-T960B1P,"3P#$+"!W:&EC +M:"!W:6QLB@`!5@`%R@%A(&5X8V5P0`4`N04$:0)1('1H871##C%I?P(-F5A;;4%`A$+@"X@(%1H97)EO0\C;F_B!P""`@/?"`"3!$$@ +M:6XMMP^"(&UO9&EF:6-D"_``;W(@0`&EP``L!!3 +M97-I9VXE#!)EB`4`0`0!7@$X;F5WM0,`\`0`>P`#GP$`>P`!APD!HP`"2@P` +M31$B:7)`$!!I>0<280D!`@P"(2!B-PD`C`HQ86)L``8`_0H!#``!+`L"U!`` +M:``".P!"96%C:#T!(79E4,`4&EN9&5PJ@`E;G0B`0`8"0`/#Q!C0@42 +M;VP-!C4*5"!7:6MI4@PP:6YGR0`P:&]W40\!LP,09$X(`]H``BH!(4]N/P@` +M]PP"8`8`TQ$`4`8#S0`!<`!3;'=A>7-S""IE9(H(`D<`<$DG=F4@870M#0", +M!S!T;R`A$+)M:7IE('-T871I8U((07!O;&PV$E$N("!)9O4(061O;B>L$I!E +M>'!L:6-I=&S9"6)V;VME(&'Z#Q%C?PH#SA$@("C2$"4@8?L*`*$!("!AZ0`! +M)Q`"+0`(S0`4;_D(<"DL(&ET('=P`$$@9V5T&1,!70H`I`0W($EN;@`W+"!I +MG@`!40$#FP`B96[)`07L#$7`U`-%A=&5V97(@8FQO +M8VMS\```[@2X'<70@82!T:6U7`W%O8! +M(71O(@`%2@``XQ,A8V6%`"%/;I`#&V7#``+D`C)P`!,@%1``:A``"@$1:2$( +M8VETP"`,D*`2L` +M,VEN("#U%F:7)S=)("`*8!$6%P$A%O\0T` +M]@`6+G0``]D#`J#B)A;N@"`*4'!C0*$"QC`$!D97-PH@``;`0!Y`,`7,N +M"B05$6:X#007&0.A&$0N"@I1$1:@/R`@27-S=65S/U(`$2H%&78Z+R]W=WF4@6]U(&1O;B=T"B`@ +M(&5X<&QI8VET;'D@:6YV;VME(&$@<&%R=&EC=6QA2T`5RH@8V%T:0`K871H`&ES:6UP;&6U`$!T;V]L +M,P$`0``#`@!R>F-A="P@8@<`$G@'``!)`0#^!@`G`%`J(&5X84D`0',Z(%,R +M`U1S;6%L;!4`!#X!`%(#(6%T>`:`;6%Y(&9I;F30`C%F=6PO`@9%`!`OKP2#R`C!I;VZ*!B!4 +M:)T!,'`M;`P$HB!D:7)E8W1O\`!,GK0`#)`0`DP``3@#U`2YA;2P@86-L;V-A;"YM-"SA`$!E +M+F%C_P```@`2+50`)'1OJ```(`$(H@2P+"!O;FQY(&YE963%"!!YR@4!]@$C +M97)<`05P`"1I;F0`D"YH+FEN"@DM(*,*4FQA=&5S9P`18C0"`68!$V6U`&`* +M"D=U:63S`"@@1%0&!-(!`G4``/,!@"!S>7-T96TZ`@L"N`0A+C$M"@#-"0$W +M`0,O`P!"`0(A``2:`P,S``"(!`\T``L`(@`,-0`O870T``PH870S``8!!O`% +M+C,@9VEV97,@86X@;W9E2XS30`"]P,2(FL#!:L``20`4"(@=71II`59(&-L87-$``'O!49N86QS +MG0`PP$2+8($-7,N-:H(`J\``!D#`/T%-6UA=-4,!&,"!98!`$P```H"D"XU +M+"!M=')E90D``&\`7G1AP`(2PF!:&%R9"UT;RTP!@1;`0%'``!!`&%M;V1E``$=`U'1E;J`('(0"P;V-T970M;W)I96Y$$`!@`@$> +M`*%35E(T($%30TE)=`(!%``"4P`/,@`%$$+9#A%Y+@"@("AB:6\+`OH#`*D"!B($`9L!`MH`#Y8#!0'(`V$B;F5W8R*;`P$S +M`"=S:+```1(`#T8#8P0%!`);`0&)``]9`P`*%@,S5VAE`P(`OP@#U`(2<^8% +M87)E0`&EP"2:7,@9&5S:6=N0A4B8F6^`@!`!`%>`3AN +M97>U`P#P!`![``.?`0![``&'"0&C``)*#`,*`P`X"`!O$#)T:&$)`0(,`B$@ +M8C<)`&H(`?L5(6]RSA`!#``080P!`M00`&@``CL`0F5A8V@]`2%V97,#$WE# +M`%!I;F1E<*H`)6YT(@$`1`T!Y18`0@42;VP-!K`+5"!7:6MI4@P##!,P:&]W +M40\"I@<`3@@#V@`+H!4$_`0`\PX`4`8#S0`!<`!`;'=A>48!`-T!*F5DB@@" +M1P`/T!?_X`GZ`Q!C-P8`!1C"871E=F5R(&)L;V-KU0H`[@<3`<0-0&)A8VM``S%F2!FP"`8`.`"L`,VEN("#U%F:7)S=)("`*8!$6%P$A%O_P(`]@`6+G0`!L`.`048`"<&`)P!`84` +M!K@!`'8``,,``H08`;X``NX4`(46`(<``J,!!E`=,7=A;IL8$'3+&`,V`@%; +M`P`G'``S``"C$0$L`P%K`P`+#YEN=F5N:65N8V7``0")```P%`*!$U)E#@#B``Y6#A`L8P!`9&5S +M<*(``&P$`>0#`',*CR!S87ES+@H``0#_B0`[%P^?`4T/`!X+434@("!# +M\2`!F0(#8P``4AT9R965" +M4T0P`#%3>6TW%P3``0.F`P#E`29E`I@`!58!$TDV +M``+=#`!&!`!/``+$`!4GJ1H!U0().`,`R@HR:65S3@`"F@1A,3H@3F5WF@,* +M2``$&P-9$@3("0%!``.) +M!1`P"`(!LB<`>`!V($UA8R!/4ZD"`#P`!ZX$`3H``T(")#`Z4``'ZP``J@D# +M_0(05`T%$CL^ +M+T`@97AI$14"IP0#U`<`&@$`E!T#C0H"8P`&FP`#700!WR$&$`4$!P($&P-@ +M8R!C;4',6UA=`P$`]P%03`Z($0V,$%D97)E)"HS8V4@ +MPP,"``>`!`OX8`0$2%3-4``01`0#?(S,@+5;B +M#@93!`9K"S@R+CBK$3=*86[(`P!V"P',"`8*`P"3`.`G96-H;R!N;VYE>&ES +M=,`0!(`!)S,P`% +M7`$`9``',P`"9P0"H1(`_S-!C```D$#!#```)$Q`I@!02`Q+C=E!Q$Q]0`((0!P;'IM82]X>EL#`^$" +M`&<`!!8@"0((`D`$`)\%$WGR#@!)`!%(R"0@(&?^$@)%``#8"01!`$!/<&5N +ME"5P(F=ZP`%B0)` +M061D:,F +M!#40%&F3#P!/`0#$`B)S=1TB(@H)(P``GC<";2(A +M`X,($CMJ$]-"``!904`*`)`4$1&(!$+`.0Q`-@(,FUA +M;BX(`)D0`,,(`NTU$&60#P&;#P@6,`%-```P#`!*`#!-86JG(P/[#@06"@-# +M!`$!`P!"$4!#:&%R_PM`5VEL@$+60`03I8P`_H.7V9R86UE9``+8$AI +M9V@M`,<'071A;7"6"S!46L6&B^O`P** +M%@"[`0_Y`P(-20`*NPD(NQD"]QP!2@`$6P("^0P08[H!(&5R?B4I=&]V&0!- +M!@!\-`(',0&7!!!I=B@!'P$`!0L`BP50"@EP96^T"P&))0"D`2!I<-H##XH` +M!@VV``M5!P>."`$*$@'Y#0TH`%8U+CDP-3P*`0D!`M(4#RL``ALT*P`#3PH/ +M5@`!%S,K``#^&`/C"`\K``$(#@D!*P`%TP$)U```K``(B@@**P`04S`+`(8& +M1'!R92W<"P"4"``["0!F`0E,`!(VC!@#\P,:.$<#!#0#0#H@5&C^`0`!%P"< +M"@";*4%R;W5T)@/":G5S=`H)8V]NH6`7<``H(1 +M`($"`BT%$SI=!@3G!@8.!P&I)W!G971O<'1?(0=2*"DL"@DR-P":`0-3#@+) +M$@$^```-`A!OS"46;$,5$2XA&@:\`*!*86%K:V\@2&5I@0$0;K$`)6%RCS8# +M%@4(]!@"0``"%`L0.`D1\`9D!P'%"`(<0`#80@)K +M*P"1*5)D(&)U9\4"('-IP@$`5@$A-&*<(A=YKP$+>`$7-$\!`2D`!24##]@! +M`3!F:7CK!0!L`@3\'@JP$P`.-`#-``!&!`$S&`8C!@&^'`%F$0!+(0;V'P)I +M`P`_#@`)"1-AW4-S(E-C;W1T(MP6$"!4```+"@6>`Q-M@SX0<]0&!#4`DDME +M97,@6F5E;-0"`#4`!4$``3T*`;T?`-,4`),.!!L!!?(`2$9I>""Q.I)N;VXM +M97AP;&\!$`!M%A!E9`T";0$"92V5=F5R9FQO=W,L:0`&CP#`1&%V:60@4F5M +M86AL]R("=14!)!TR;VENP!P`QCL`1`L-C0#P"$-O;&EN(%!E`0`O/`*``0..$@(?`P!H +M0Q%SB1%0(&AAFRJ1A(MN`01;"\R`0(`($1IRS$!8`4D.B".`.%R979I9775R;/E&8C0V;61G#H@16YS0T`"P3DP9&ER"AU`CH)$'#L.P#<%P*W +M!`"Z`$`M;F\MN@HC9FF..#1L:6+-1P-O%``G``NH`&(Z(%-K:7"3&`&S`0%C +M!0%*!0/_!`(Q"%`S,BUB:18%,&9?=$<`,&ES;ZD^!"P!$F*[(3!T`*L`""@`!-XC`<8!("URD@8@+74E``87`073``$>'P,\!"PN:+L# +M$%.X$3!I9FD##P`J`#5I;F=0"R`N:,D)!I\&`+`-`7-'(&5DE000:0,($7DX +M2S!I``&8!P#5$P/J"`%\"0()!`8]"P#B +M`@]+``\`)@$`JP``^`@895L"`UH5,"!U=1L1,&1E.PP!$7F0#@*X#0'4#Q`M +M@2XQ96-O@052;&]G:6.Q%0(T`!!S-```3A4"3R(!]A0`=@$!&``"6TD"FQ<# +M?0(&U`@)4P)$-"XQ-'H>0&0[(&E`!@S!$`B"6%*"@!3`0'P +M"!!G2P41+W8C8"!M:7AU<-\I!L@6`K$``,()%&G$+R)D"NT6`&<$`H0I`1X' +M$B[('P;F#@RF`!4SI@`"DQ@%^0(#=AT`G081+$P"`),`$BR:`!`L+`0"G@`! +M.P$@8V%E$!%BF`LQ=F5RVP,$TB).$F7^ +M`4!355,MW0D!K!@'C@``TPL`@0!@(&-L87-HF@H"9RL"*``5,4D4`"@``!<% +M`$8#`ID&":Q#$"R"))$@2V%I(%=A;F?R``8\`!);FP(075\)0&UI="!-*@+L +M4P7@(E!D979I8U8!``@HI``"H`2!B87-.$62(`P$7"0,5 +M`0;#)0-,!0(J(@9U``I+`&1697)I9GE-!`%6"`!)&C%G972:#0*E/`%B"P3- +M50!Q&@&.!44R+CDN@@$".@``2`$2;%0Q$&(3&0';"P?A#R(H+:4/0"UZ*2RK +M`P`A#S$);V:J#3!R;6%>$@">'S)E=L"`9P!!U,'5&ET:`H)@P(4&"%`P+CDN,,8'`($'`LY3('=IH14S +M=7-E)QL%-``@0V^/&P`:"U!I;FET:7P&``\E!#$0`,H!`PD"!)@``L<##I@` +M%3G*!@+```4H``;4!0!C`0*--`!Z!0*)%PED`/`#.B`@+6$L("UQ+"`M3"P@ +M+68LFQ@0=#X8-"!S9?LO`)4`(2UI'0@S+6ETF``#\0\.F``:.)@`!B@``2LD +M`$4`#7](`"`4`OL(<64@>F5R;RWZ0`!Y!`&<)`.,0!`LF@H$C1*A1&%M:65N +M($=O;*H$`*,`$&)Z#0#I``&/`P").!!YR08`*$$`L"`!)@$"I"H/Y@$`%C>V +M``(I``(:$`[?`!8V*0``>`(#61L1-Z@K$"\%"0$%`!!?N!0@+F.A(0"""S!S +M("*B!4`M8R!\*``P("UXTTHE<'GX'0%T``,0&Q(WB05082!C;W64'"-O9I8$ +M!ZTF`.4%`7\``JD/#J<`!_(5"B@``%L``*D#`:<``04`$5]I`1!?WP0A8GG9 +M,0)%`7)E('5M87-KI#\#0`$#^AX.<``&6`D"RP`%'@(`A@<&-%($A`)0+2UD +M:7.G$%(M>&%T='D*!A0`=6%C;"P*"73M`?\`4V%M=6QI(%-U;VUI;F5NC``- +M!SX)`?P`!8P`!C\"P$QA<&\@3'5C:&EN:=4%`'I5`4D"`$X<`55)``4.`=() +M`9HD`TH%`),!(&QD5PD!52X`^AL$;P0P8G5GQ@4!&```0`&P;V8*"2)L96YG +M=&B>%)!E;F0B(&9L86<>"@5A`!)S'P0&5@$"3@`#`@01()L&`5(&`3X"`*D& +M`2\$!#<`!?,#$$:C`4`@8W5T:P!`)!0HH``)X```E"`#Q +M!0`R%`8\`@.Z#%!C:&EL;`<7"SL`$$^0!@#9$`#P`@+W!R(@87M6("!OZ1`J<;`JQ8`LT"`X\;`"T9`$\%`DHT +M`"U7``\($GF&``9S!A!4!`8#,P``%0$`.`03>?,0`%@2`$($`,8E`+LB`^8) +M&#J8`@)M"``U""!E>-06`$)%!#@``>8>,S)'0G\F,S%40F@!`E8Y#0P%&#,N +M&@`M`08H`!)##P@"/P`\T%`*`&4'-K:7!P&`$# +M.@(%L1,!K@T`,12E97AA8W1L>0H)82L@`.87(#1'M`@#X!(':!$!G0$"&PX' +M9P``6P$`9@`'0P)0*#XX1RGC``4^`@#4``#<$D-A($`;D"$V3R +M-`%Z$``!!!$@?AA@"@EI;G-TA`80P"!$`>`$D-`AL$`;H*!.@K,4-64UD? +M`-A()W5LG0$+M``'^0X"*0`/Q@P#&#(;"`%1``4H``93"@HF(A(G3R8`A`H$ +M1"$!E`(19"@%`*`"!.,3,F-R:5@84G-E8W5RN"@@9W.`+0)]8B`@8?\5`/\. +M`!IG$PF5'P0M``DC(%!A9'9I<^9;(W,O"@&F+5-!+3`W.C`U+OH`0BYA``'O``>L!P&*)`'R/0#]"P!Y"`A:$`#@```!#P",`P!E*`#V'`:? +M)A`L#1P!`0PD"@F&%0))$P11.24@=!86`I<$("YH+!XC863%"6-L96%N=7!^ +M*PIB`1(L'14`#`<1P=V]R:V5D(&]K +M87F+'`'.!Y!I="!H96QD(&_#0P"H!0*:``!A&P&J``"]-0"%*@(7(@#Y'2!U +M;4$P`'P5`EP.!/X&`9Q#`/$08"!B`/HP`?@"!)\` +M`6``$%\9`19E^30`E@X`J``"[BP0:'(,`2X=@'-O;F%B;'D@N0$`$A4"EPT` +MR34`IAP7>8(3@5-K96QE=&%L?`L&C`@!70<#[`$&`@4+[`$:,>P!!B@`4$9L +M97-HR1<`U01>>H#0F%C:&73`0*M!0`"$Q!N)`$0;R$@$'*D!@#,`0"_#0!3$3!R +M:7.V4B!E;KH'$&E48P&F&`-R`@!'(#`*"61E`S!M:6QG#@%3!`#Y"@"1.`^! +M#`09,9P7`2D`!58(!!,2!G($`TP``@I+`/D$"2H"`&L!`JT!`TL`!B@``*0! +M`740,7)E8W\.%RVH`042`@$:"@7$.#$*"2A*(``#8P#?+0!1*03B%@#%'`"I +M)`%."0%W-P`:,$%C:"!B="-1+BD*"48%!$,@:7-O*`$0;:,W("@I>6H""`!A +M86ME9&5V1R`%MP,!R@$D+F/I``4$`@OI``<`"@`T`08H``(T`0+/`1%F[R(! +M@@<`H!\!'!4@;V[20T-/4R!82P$%,P<+8@`([`D%!4X`$1"_X`!S8))@E,.Q8`@0``[`0"NB`0 +M;F8=`2HA``D!`'4$``0#`/Y/1&5R:7AC``6E!PMC``CE"`#$`0,:(PQV"R681(N@!#AT` +M`1`"$B`<*P:[``(?#@!U-P&C``0V`#)I;VZY,0(Y,0#7!`%A!B)E9.H=,&QI +M:U@1`-\I!SD"`O4]`&("\`%&965D8F%C:PH)87!PA +M*P8P)@',``5W``)N3@`N"J!N9FEG+F=U97-S"#`!#@`P`1`T!%PH`FD``.0``C\"`,15`HLG +M!2@!`>H#!``7`-@%"3H)(G1O"#T$B`$%-P`,B`$'N04*B`$12`T'!$<-(',[ +MD`T09=`$8&YU>"]F2!O8G:N<@!F!0%K&P/>*P(]$U%T +M:&ES+/,((6UEO"@`C0H(Y0`35Q`$-705). +M&`(&"B`'MP`!:@0'8@8`7`$&*0``*Q0![0$`G@(`>`(QD``/X&`_L7`"8``#X`"?P9,F]W*<2!G;V]D_0$&]0D2,ADD$6_J0P'7&@"_)B!O9NP+%&$' +M*@^]&@-&,&(Q-Y,,`&`H!HD=`7('`*\!-$=)1"<%`@P#$G,`!0-%`R)B>18` +M,6EN9Q@!(7=H="X!MPX#3AL!W5$!YCQ0=&]O(&9,0@##!P#.%J%N>2!P65S(B!0)@TQ;L.R4`(A=&76 +M'P",'063:0'J``/]!@`)`P"'#@#]"#!'96[8``&\`Q,H<2TP(2D@4#L!RQT" +M%@$`1!$!0@`!Z!^R:7,@;&]N9RUS=&%U*C]B=6<*`0X'1`<*"@$`E@<28``?%!@&>``5/`Q%""5P$\10" +MI`(#ODCQ"SH@7T585%)!0U1?4T5#55)%7TY/1$]41$]4E@$`[AL,(0!Q4UE- +M3$E.2XHA-&5S94\``>D-`*M%`;XI`G0&$2Q%``!5%P$Y+B!B9=X!4"!D;W=N +M$PX'7@$@=V@R`0$E``,1"`%/`"%B>4$```A9AAQ``(P$$VQ4-MQ\!&@$`)1H` +MC`(#Y14`\C(!B6<#C&D!0!`"M!4#Q@,`HS0!HA@$9P$!1P`A87+;$2`H:J`2 +M(&9E#1$%'@L##1$$40`@9&6>"1!BH04!%#6]U0P`$2AH""6@2*5=``)L` +M86]V97)R:4(1`'8*06%M92^;,#`M=&^T5!`O.QMB;&]O:W5P'`$3*$E]"M4! +M$6$63@&92T)86%@H@@M29V5T9W(/`%!B;&]A=!P%`*(!+S`YDP(#%V$;!0`H +M``4G``3)`0-^!@3"`0>"$Q`[$@$!VAL`H!X#408!"!T`?$,0;]T^`(0"`"T% +M`C(N`215!HMW`FH)`2M:`]`&$%,B-5!F96%T==\(`O87$&Y[`07*.P"I!@'# +M'@>7`P)'%0%R`0)R`%%I;G9O;-0!!/,!`&$+```"(&]FSQ'B(&]V97)H875L('=I;&S")@&X+P,Q-@*D +M"P%^``**+@9'`0=\>`+9$`#/`@+N&PK=#@C4``+-``)')@&<.P-W!P`<)1`H +M]C@$OTH`L00!@P$`?0(C;V8,)Q!F/1,+B0``RQ\071H +M-`L!8@,`K`,!K`(">``"NQX&F@``V`D+ZP`'EQ<`V@4"@0$`&QLP`WE3@'.'@(:#P.8)1$V[@@0(.MK`7TG$#L&`!%L32D` +M_P4@;VQ/$!)H(R@"V0`!1PH`7P`!B`$`]@<0)Z<6$7)5#S!K967I<0&O)U!L +M92!U<$4'`&,T`CP``'8((&]NRRM"3$1%4G8`HE-534U!4DE%4PK]$`*M!0]D +M`P`:,2$!`R$C$#99#@B9)0!6%R!N9&\!$G390P6(#PF6(S(@ +M``7\`1!)N"8Q<&]RK00+9DH`HV50=&EL;"TP!PQ?-0!B``#E!0X.`1AS(VD! +MV!-\+6]N;'DN*7P`8%)E;W)G81YA$&1M6P)-`0#;!5!P86-K89=+!P)X`-@! +M$&6X"D`N9WH*S&H`:A,!AP0!BAL2<_@4!_8$`.L%`M\,`H@X`W,S`,\!!(X% +M`GL6%#I[!P%2*@"2(0$!40$_.03W!A(LOB``>0`W4&%X^@$!7AP"%G\1+OY- +M`@`;&S7:&0&^`0/V`02U$0E'3P`^#@1=&0`?"P9?&0"[!0!&$P*V!`(?$@!S +M#024!`KI2@)D``+D2@"N```\%%!A@8"\PH5-947`)5*0&5T96-\""1A=*4= +M`:E*`5<5`=@$`JLG`"P3`W(9!<`!"WXZ`0T2`/0``HD``_`%`1`.`F8"`*\` +M$E>/6P")>Q,@P"229VYU=VEN,S(N-H*A9F]R9V4N;F5T+P4>`_H.`2\"`U8$ +ME%II<"]::7`V-.X#"5$!86X@3F5L<\<;02U,+RWI`P#V%P$K$@O``P-P`P*M +M#2HU.C$"`U\&`55%`%X#`2D/$&5>"1%YW1$`/0($[D,Q@.\.@:Y +M`P!Y``,\`?,.>'-N:6PN86YT8F5A:,2$#32`2%N +M>2LJ$"UW"`#%/2%L92\"`=01`$@Y`58#`1M2`U8`(&%L)0X`'0$!U1\#[!8! +M`!H%,3L$&9I;&4``0!+X3`P,#8T-"``,#`P-S8U"``B,#(0`"(R +M,`$`_P<@,3(S-3,U-3,U,3(@,#$R,#(S`"`PEP!+`@(`KW5S=&%R`#`P8W4' +M`0M22T`5RH@8V%T:0`K871H`&!S:6UP;&5H`@6U`$!T;V]L +M,P$`0``#`@!R>F-A="P@8@<`$G@'``!)`4!S=6-H)P!0*B!E>&%)`$!S.B!3 +M,@-46]U(&UA>2!F:6YDT`(Q9G5L+P(&10!1 +M+VUI;FF%`1%AXP%186-T('-@`*$@9&5M;VYS=')AP0$`#@,G;V9>`0-)`#!C +M;VY#`O`".B`@5F%R:6]UP``"@+Q`F%U=&AO7-T96TZ"B`J(+@$=2XQ(&5X<&R# +M`@,O`P!"`0(A``2:`P,S``"(!`\T``L`(@`,-0`O870T``PH870S``8!!H`N +M,R!G:79E<]\&@&]V97)V:65W\P(`H``$NP4087$%,'=H;Y$"(RH@V0>%7W)E +M860N,RP0``#1!1UE$0!17V1I]!;!I;@IA(&YU;6)E`D09BP``;<&42H@1TY5=0$" +M-0(F("@$"P`:`$%L;VYG4`9B;F%M97,L$```!0L3(!$``&,`4G-P87)S?`(A +M`@@;W#+`\!A;"!2;V-KB,``!DT%``)"`$```I58W)E873/ +M``%U!`\&`0("J@,#OP,"O`(/'P,8,")R9:`-46-T960B1P,"3P#$+"!W:&EC +M:"!W:6QLB@`!5@`%R@%A(&5X8V5P0`4`N04$:0)1('1H871##C%I\+`OH#`*D"!B($`88!`MH` +M#Y8#!0'(`V$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0%!`);`0&)``]9`P`* +M%@,S5VAE`P((T0X"Y@5A`3AN97>U`P#P!`![``-S!`![``&'"0&C``)*#`!-$2)I +M7-S""IE9(H(`D<`<$DG=F4@870M#0",!S!T;R`A$+)M +M:7IE('-T871I8U((07!O;&PV$E$N("!)9O4(061O;B<<$Y!E>'!L:6-I=&S9 +M"4!V;VMEO!(!ZP`!?PH#SA$@("C2$"4@8?L*`*D`("!AL@$!)Q`"+0`(S0`4 +M;Y4(<"DL(&ET('=P`$$@9V5T&1,!70H`I`0W($EN;@`W+"!IG@`!40$#FP`B +M96[)`07L#$7`U`-%A=&5V97(@8FQO8VMS\```[@2X'<70@ +M82!T:6U7`W%O@``S0)P82!S;V-K9687`CX#27=I4X.``P1$2(A`0!:""`L(E`(H"P@8V%P86)I;&D2%`8# +M`07Q``+S#P&W!`CV!0&7`8`@:6YD:79I9&P.`]L(`(4``#H2`D(``*P+`-$` +M`#8!(71OK`TP9&%TUP``!0X6.BX!`L@)`#T`$F'L`@#)"@$K`#-I;B`G`0"/ +M`C!A9&1T!`!,``CW#`&I"@,>#U%F:7)S=)("`*8!$6%P$A%O\0T`]@`6+G0` +M`]D#`J0#`',*'HC`,$*3F]T97,@86)O +M=724`')L:6)R87)YT0#P+G1E8W1U2!S=')E86TM;W)I96YT960@F4@2!I;G9O:V4@82!PZP"`=6QA2!F3X`!8P``0`"\05R;W9I9&4@96%S>2UT;RUU`0"0 +M:7,@97-P96-I;@0!T`$"J@$`.@CS`SH@(G!A>"!I;G1E7!1`GH@1`9W)A;18"&%)`$!S.B!3,@-4`0-)`#!C;VY#`O`".B`@5F%R:6]UP``7P%V875T:&]R,&`4D!A69I9W5R92`M#``"1`"U'2(`")P==8-(")C-`81(B0# +M`#@,*6]L30`"5@$&ZP,!*0$`%@D`C@$/;0$!`*(&$'7?#P':`31E"B>P`"-E +M)ZT``R0$`),``$X`\``N86TL(&%C;&]C86PN;30)#0/M`#`N86,7`0`"`!`M +MH@(`GP`$J```V0X(H@02+!H.`-<+`%D+$'G*!0'V`2-EPH"MP(29:`,`!(&0'-E<77J"!!S"P4!/@$`=0``%P(` +M^00!<0`!<0H(EP``/`DS>2XS30``[P0R92`B:P,%JP`!)``4(@L+62!C;&%S +M1``!'PE&;F%L"`"X!!,B!0XR+F@BJ0`R:&4*7PP0(+`)`/H``!0`!.D&`W((`G\"-&UO +M5$P`P%&!E2X`L2`H8FEG+65N9&EA +MU!%C;&ET=&QE$0`"D!8$7Q:10T0M4D]-(&EMMP(0*#@.,"!O<,L#P&%L(%)O +M8VMR:61G9>\!`DD`-%I)4'4$!$``('5N,0L#!A<_;W(@ +M'A=`#PL7`-!-:6-R;W-O9G0@0T%"YP($2AQ=4 +M`)H`,6QZ-`X+`,`!`.47`2$)!`@!```*`IP0!4L!`'4$#P8!`@*#`0._`P*\ +M`@\?`Q@P(G)EH`T`$!81(D<#`D\`PBP@=VAI8V@@=VEL;.L8`'`(`!D$`U\! +M0',@97@M%``"`@"Y!02)$0(+%P-:%P%1``7I$C!S("A3"@$T!`"$`0,S!`#T +M`V`L(&5T8RGO"P+Z`P!L!`!M``*-``&;`0+:``_(`PIA(FYE=V,BFP,!,P`G +M#0#46-H86YG?@$W;6%T +M(0"P;V-T970M;W)I96X!`P!@`@$>`*%35E(T($%30TE)=`(!%``"4P`/,@`% +M84)I;F%R>2X`P"`H8FEG+65N9&EA;J(!8VQI='1L91$``OH`\0))4T\Y-C8P +M($-$+5)/32!I;;<"@"AW:71H(&]PRP/`86P@4F]C:W)I9&=E10!B2F]L:65T +M*0$![P$"20`T6DE05@,$0`#`=6YC;VUPFEP/@$Q:6]N&`%=8GII<#(6``1\`4TO3%I7'0"B;'IM82P@;'II&-E<$`% +M`+D%!&D"L"!T:&%T(')E<75IE@4G87C*`E(@*&9O?P(-F5A;;4%X'-Y +MU`P#P!`![``-S!`![``&'"0&C`%0@;VYL>0H#`#@( +M`+(``1X#`*8$`@P"(2!B-PEQ4,`4&EN9&5PJ@`E;G0B`0`8"5!AP,1<#4`T6%T979E6QE(&%P<')OR`,`R0@" +M^@#0=&\@:&%V92!M=6QT:3$,!*D``@$$`+D(`/X-%6Z>`%`@(&)S9",'(75S +MO`$`/06#;B!I=',@(D`\`!(BO0012!F +M4X.475S92`B(0$`6@@@+")0 +M"+$L(&-A<&%B:6QI=/8"!`,!!?$`864@05!)<[<$"/8%`9P"`,D*`2L`,VEN("#U%F:7)S=)(" +M`*8!(&$@0P41;U`'`/8`%BYT``/9`P*G`0"_``*<`0&%``:X`0!V``##``"\ +M`Q)EDP`",0\@;'ED`0#,``"C`0:`!3%W86Y_!1)T'0\!-@(!6P,!&@00=(X' +M(7-K+`,`L1`0#B)A;N@"`*4'`!$#`EH'$"QC +M`$!D97-PH@``;`0!Y`,`7,N"E)%041-11(&!DD1X2!B=6YD;&4N +M"@I1=65S^@*@/R`@27-S=65S/U(`UBH@:'1T<#HO+W=W=RXX`$`N;W)GDP`` +M2`$0:+@"$&:Q#S-N9V]8!Q<@3`>`(&1E=F5L;W`\!0@9$02Z$0&L"`$W#`!Q +M```Z`"%N:UT!`%T`!G,`4"!M86EL!P(P;&ESOQ`!G0`05)D!`.41`.%E7!1`GD1(`\A$`%@)S82!F=6QL+98(F-%#A)B!P`2>`<``$D! +M`)()`"<`02H@97@;$T!S.B!3,@-4P``7P%C875T:&]R:1``EPT!\@(`P1,2+NT/ +M4'1O<"UL#`0#Q0P`,`0&";8""',5`.L%`>X/\`4@*B!.15=3("T@ +M:&EG:&QI9VAT<]P`,')E8]D4`C$%`Z`"DD-/4%E)3D<@+0P%`$(4`,H'(61O +M7P8!AP4`S@#`*B!)3E-404Q,("T@9`HQ86QLCP0!#0``^18`OP`"*0`#0`41 +M+3P``5X1`A@`8&-O;F9I9WX+%2T,``)$`+5S8W)I<'0L('-E96<``"@%`ED6 +M`F,(@2H@0TUA:V5,U`0Q='ATB``A<'5G$#`@(F,T!A$B)`,`.`PI;VQ-``)6 +M`0;K`P$I`0`6"0".`0]M`0$`(`T0=3T3`A`7)`HGL``C92>M``,D!`"3``!. +M`/``+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C_P```@`0+60"`)\`!*@``-D. +M"*($$BP:#@#7"P!9"Q!YR@4!]@$C97*N`05P`"1I;F0`@2YH+FEN"@DM]`<` +MYA,22#R`I!I;VYS+@H*5&B=`?("<"UL979E +M;"!D:7)E8W1O'2(`#!P=71>`H$@ +M(F-M86ME(B0#:60@=&]O;$T``E8!!NL#`2D!,2!I;DP!#VT!`3!A2!N965D?``Q;6%I]@$C97)<`05P +M`"1I;F0`\@,N:"YI;@H)+2!T96UP;&%T97-G`!%B-`(!9@$39;4`8`H*1W5I +M9/,`4"!$;V-UF04"@0$`Q0$R86QL=0`!MP&R'!L@P(#+P,`0@$"(0`$F@,#,P``B`0/-``+`"(`##4`+V%T-``,*&%T,P`& +M`0:`+C,@9VEV97/?!H!O=F5R=FEE=_,"`*``!+L%$&%Q!3!W:&^1`B,J("X' +MA5]R96%D+C,L$```T04=91$`45]D:7-K%@`@;F30`0@^``,<``"9`!!V7P$" +MMP)A960@8V%LB0<0<]0&06YC97.M`@"3``!U``%'``-"!FAE($%027.7`'-E +M;G1R>2XS30`"]P,2(FL#!:L``20`4"(@=71II`59(&-L87-$``'O!49N86QS +MG0`P]!;!I;@IA(&YU;6)E`D09BP``;<& +M42H@1TY5=0$"-0(B("BK"0"Y`0`:`$%L;VYG4`9B;F%M97,L$`!3;&EN:R`1 +M``!C`%)S<&%R'1E;J+``-J`0`9`]$J(%!/4TE8('5S=&%R6P`"$``R<&%X-`,"60<# +M>`('(0#`;V-T970M;W)I96YT%P0@<&E^"<8J(%-64C0@05-#24D4``)3``\R +M``5A0FEN87)Y+@#`("AB:6B,``!DT%``) +M"`$```I58W)E873/``%U!`\&`0("J@,#OP,"O`(/'P,8,")R9:`-46-T960B +M1P,"3P#$+"!W:&EC:"!W:6QLB@`!5@`%R@%A(&5X8V5P0`4`N04$:0)1('1H +M871##C%I\+`OH# +M`*D"!B($`88!`MH`#Y8#!0'(`V$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0% +M!`);`0&)``]9`P`*%@,S5VAE`P(`?`4#U`(2<^8%87)E`3AN97>U`P#P!`![``.?`0![ +M``&'"0&C``)*#`!-$2)IF4@``%1`0.;`")E;LD!!RT``'P`"W$`*&1E$0`#Q@(1+/`` +M`H```(T.`)8!`!8!`$``,&%G82X.`?$)D6-OP,1<#4` +MT6%T979E$P$/`P*A +M%0"V`A!GJA40:2(3`2(`!4H``.,3(6-EA0`A3VZ0`QMEPP`"Y`(R<')O.@$! +MA0%18W1L>2W,`))E9"!O=71P=73O`@!@!/$#;V)J96-T+7-T>6QE(&%P<')O +MR`,`^10"^@!0=&\@:&$Y%D!U;'1IPQ,$J0`"`00`N0A5(&]P96Z>`!,@%1`` +M:A``"@$`/06#;B!I=',@(D`\`!(BO0012!F4X.``P1$2(A`0!:""`L +M(E`(H"P@8V%P86)I;&D2%`8#`07Q``+S#P$_#@CV!0&7`8`@:6YD:79I9&P. +M`]L(`(4``#H2`D(``*P+`-$``#8!(71OK`TP9&%TUP``!0X6.BX!`L@)`#T` +M$F'L`@#)"@$K`#-I;B`G`0"/`C!A9&1T!`!,``CW#`&I"@,>#U%F:7)S=)(" +M`*8!$6%P$A%O\0T`]@`6+G0``]D#`J#B)A;N@"`*4'!C0*$"QC`$!D97-PH@``;`0!Y`,` +M7,N"B05$6:X#06Y&0*A&$0N"@I1$19`/R`@2:T9(',_4@`4*I49 +M1G=W=RXX`$`N;W)GDP``2`$0:+@"`%<`0V]N9V]8!Q<@3`<@(&18%B!O<#P% +M"!D1!+H1`:P(`3<,`'$``#H`'VYD&O______________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________:E!I=F4@95^*JRTH$0``\1%N +M=')Y(&)E"B`@(&EN9&5P96YD96YT+B`@5&AE'!L86EN:6YG1@#7:&]W('1O(&5X=&5N +M9"P`\A8N"@H@*B!/;B!R96%D+"!C;VUP2!A(&)Y=%<"82!A('1I;10#<6]R(&UM87#:`$%E;G1I +M#P,"_`(`:0`09P4#(&ET3P`)H0!A="!O;F-EA0"+3VX@=W)I=&7#``+D`C)P +M0"0 +M:7,@97-P96-I;@0!T`$"J@'S!TYO=&4Z(")P87@@:6YT97)C:&%N9V6?!1,B +MN0(@;&P\`0+H`A!DO@$`_04!C080+&,`0&1EF-A="P@ +M8@<`$G@'``!)`0"2"0`G`%`J(&5X84D`0',Z(%,R`U1S;6%L;!4`!#X!`%(# +M(6%T'`@@;6'F!"!N9-`",69U;"\"!D4`$"]#"@&%`1%A!@E186-T('-@`+`@ +M9&5M;VYS=')A=+P`"-E)ZT``V7-T96TZ&@D"N`0A+C'!#`!A#`$W`0,O +M`P`+``(A``2:`P,S``"(!`\T``L`(@`,-0`O870T``PH870S``8!!B$N,[8+ +M$'-E"H!O=F5R=FEE=_,"`*``!0H,`'$%,'=H;Y$"%"JD"H5?PH"MP(29:`,`%L$$'/4 +M!A!N2PT`U@(`DP``=0``%P(`^00!<0`!<0H(EP`!G`DC+C--``#O!#)E(")K +M`P6K``$D`!0B"PM9(&-L87-$``$?"49N86QSG0`2P$2+8($-7,N-:H(`J\``!D# +M`/T%-6UA=&D/!&,"!98!`+````H"D"XU+"!M=')E90D``&\`7G1A"`#.#1,B!0XR+F@BJ0`R:&4*7PP0 +M(+`)`/H``!0`!.D&`W((`G\"-&UO2X`L2`H8FEG+65N9&EAU!%C;&ET=&QE$0`"^@#Q +M`DE33SDV-C`@0T0M4D]-(&EMMP(1*'@((&]PRP/`86P@4F]C:W)I9&=EYP%B +M2F]L:65T*0$![P$"20`T6DE0=00$0``@=6XQ"P#L$P#6$&!R(")D969^!A$B +M9@D#&```H00C:655`0##`0"B`85"4T0@)V%R)U(``?@`$2?]`Q`GNP($/0%: +M-RU::7`F`-A-:6-R;W-O9G0@0T%"+``Q3$A!"@,Z3%I(,@`Z4D%2$0`86!$` +M`1D(!2`&`/42"*\"`'82`"H(`,,/`TP&!D4(,&)E9DH#4F5V86QU0@H`K@,# +M+P(`'P@P*B!U]@40;Q@$``L%`D,"`0H``EP)L5)032!WFEP,A8`!'P!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC +M```9-!0`"0@!```*`IP0!3H!`'4$#P8!`@*O`0._`P*\`@\?`Q@P(G)EH`T` +M$!81(D<#`D\`Q"P@=VAI8V@@=VEL;(H``58`!I``(&5X+10``@(`N04$B1%1 +M('1H871##@#3$P!1``&Q%@'*`B`@*'T'`30$`(0!`S,$`/0#8"P@971C*>\+ +M`OH#`*D"`&@1`HT``9L!`MH`#\@#"F$B;F5W8R*;`P$S`"=S:+```1(`#T8# +M8P0%!`?.``]9`P`*%@,S5VAE`P(`OP@#U`(2<^8%87)E`3AN97>U`P#P!`#]`@.?`0![``&'"0##%Q)E2@P`31$B +M:7*"$1!I>0<#[A("#`(#(1H`C`H!CQ@#N!0!#``080P!`M00`&@``CL`$66< +M%@`]`2%V97,##V0:____________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________________]G4&)R87)Y9/.(_"(1``#P(2!A=71O;6%T:6-A +M;&QY(&1E=&5C=',@86YD(')E861S('1H92!F;VQL;W=I;F<@9BP`\`YS.@H@ +M("H@1TY5('1A"!I;G1E +M`*935E(T($%30TE)%``"8P`/,@`%84)I;F%R>2X`\P<@*&)I9RUE;F1I86X@ +M;W(@;&ET=&QE$0`"^@#P'TE33SDV-C`@0T0M4D]-(&EM86=EFEP,A8`!&0!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9-!0`"0@! +ME6-A;B!C&-E<'0"`D0*("`@:0+1 +M('1H870@P`!S@`4=G<&$G.C`%0@;VYL>0H#0&UE +M;G2R``$>`P"F!`(,`C`@8F5``'%R96%D86)L``9!=W)I=`P`$&$,`0($`0!H +M``([`$)E86-H/0$A=F5S`Q-Y0P!0:6YD97"J`")N='\`$'([!``$`#!T:6-" +M!21O;H$!!*X`\`!7:6MI(&5X<&QA:6YI;F>)`#!H;W?X``&S`Q!DE@4#+``" +M*@$A3VX_"!PL`P$`!`0R;6%T<`!`;'=A>48!`-T!*F5DB@@"1P"P22=V92!A +M='1E;7",!^!T;R!M:6YI;6EZ92!S=+4(`E((4'!O;&QUN`'A+B`@268@>6]U +M(&1O;B?L`0"V`/$":6-I=&QY(&EN=F]K92!A('#K`"!U;+T(H&5A='5R92`H +MD`!RT`!$4'`R("`ID!<"DL(&ET('=P`.`@9V5T('!U;&QE +M9"!I;J0$-R!);FX`-RP@:9X``5$!`YL`(F5NR0$'+0``?``+<0`H9&41``.J +M`!$L\``"@``B;F6.`@`6`0!``'%A9V%I;G-TSP&18V]RP,Q:65SPP`!;P,!;P=16QE(&%P<')OR`,`@0L"^@#@=&\@:&%V92!M=6QT:7`E``-3!`(! +M!`#\"E4@;W!E;IX`4"`@8G-D(P2!F)M96UO7,"!8P` +M`0`"\05R;W9I9&4@96%S>2UT;RUU0#`*8.T"!S87ES+@I214%$346[!@?H!N$@8G5N9&QE+@H*475E<_H" +MH#\@($ES7!1`GH@1`9W)A;18"&%)`$!S.B!3,@-4`0-)`#!C;VY#`O`".B`@5F%R:6]UP``7P%Q875T:&]R<\`%`1\& +M`?("`-(1$B[M#U!T;W`M;`P$`\4,`#`'`4$`$&GD!@FV`B)I;M8$`*0*`.L% +M!+T"\`).15=3("T@:&EG:&QI9VATT3`A@`8&-O;F9I9WX+%2T,``)$`+5S8W)I<'0L +M('-E96<``"@%9&1E=&%I;,,$84--86ME3-0$,71X=(@`(G!UU@T@(F,T!A$B +M)`,`.`PI;VQ-``)6`0;K`P$I`0`6"0".`0]M`0$`L`P0=3T3`=H!-&4*)[`` +M(V4GK0``.@\P("H@DP``3@#P`"YA;2P@86-L;V-A;"YM-`D-`^T`,"YA8_\` +M``(`$"VB`@"?``2H``#9#@BB!!(L&@X`UPL`60L0>PH"MP(`318A86R)!T!S97%UZ@@0=&%R+C54`0CQ!`4^$A%S +MU@TQ<&]PY0\#G`$$>P`(2PE`:&%R9!8,`3`&`J@!`X42`(X!86UO9&5R;H\` +M`.@!`+P'<"!V87)I86Y("0`B##!M86[X"Q%PK1]!;!I;@IA(&YU;6)E"`"X!!,BXP`R+F@BJ0`R:&4*7PP0(+`)`/H``!0` +M!.D&`W((`G\"$&T:%P/[`$(N("!0B@FR;&5T('5S"FMN;W<0`0&9!F!EF-A="P@8@<`$G@'`/0386YD('-U8V@* +M("`@*B!E>&%M<&QE'2(`#%P=70I`/D#(F-M86ME(B!B=6EL +M9"!T;V]L30`"5@$&-0$!*0$Q(&EN3`$/;0$!,&%R91`"$F3:`35E"B>\`!,G +MK0`2.M0``),``$X`]0$N86TL(&%C;&]C86PN;30LX0!`92YA8RL```(`$BU4 +M`"1T;Z@``"`!,&1IM`_`$,R!G:79E2XS!`,!JP(2(FL#!:L``20`Z2(@ +M=71I;&ET>2!C;&%S1`"6:6YT97)N86QSG0`P`?$#+@H*66]U('-H;W5L +M9"!A;'-O(@(!3``Q8V]P=@8R8V]M6P%#:6X@(KT",BYH(JD`@&AE"G-O=7)C +M+P`19'4!`!0`!.D&!30'`"P%-&UO<$",&5C=)D#$635``,<`@7"!A!F+``!MP91*B!'3E5U +M`0*Z`28@*+D!`!H`06QO;F=5`F)N86UE'1E;J+ +M``-J`0`9`]$J(%!/4TE8('5S=&%R6P`"$``P<&%X20,B97)9!P-X`@FEP,A8`!'P!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9-!0`"0@!```* +M56-R96%TSP`!=00/!@$"`JH#`[\#`KP"#Q\#&#`B&-E<$`%`+D%!&D"`A4,<7)E<75I +MP`#GP$`>P`!APD! +MHP`"2@P#"@,`.`@`L@`Q=&AA+PD#*P`A(&(W"0!J"#%A8FP`!@","@$,``$L +M"P($`0!H``([`$)E86-H/0$A=F5S`Q-Y0P!0:6YD97"J`"5N="(!`!@)``\/ +M$&-"!1)O;`T&-0I4(%=I:VE2##!I;F?)`#!H;W=1#P&S`Q=DE@H"*@$A3VX_ +M"`#W#`)@!@,#`03-``%P`$!L=V%Y1@$`W0$J962*"`)'`'!))W9E(&%T+0T` +MC`<`P0^0:6YI;6EZ92!S#@T28U((07!O;&R4#5$N("!)9O4(4&1O;B=TJ`"0 +M97AP;&EC:71LV0EB=F]K92!A^@\18W\*,69E830+$"C2$`!U#`@<`A!A00`! +M)Q`"+0`(S0`4;_D(<"DL(&ET('=P`'$@9V5T('!UG`T0:7H+1R`@26YN`#``%1`0.;`")E;LD!!RT``#X`"W$`*&1E$0`#J@`1+/```H```(T.`)8! +M`!8!`$``(&%G`PX"4`.18V]R0`P&@`A!MV`$32X'<70@82!T:6U7`W%O8!(71O(@`%2@!2="!O;F-\$B)/;AP."\,``N0",G!R;SH!`84! +M46-T;'DMS`"2960@;W5T<'5T[P(`8`3Q`V]B:F5C="US='EL92!A<'!R;\@# +M`$,2`OH`X'1O(&AA=F4@;75L=&EP)0``(040=A(#0')E86VY"%4@;W!E;IX` +M$R`5$`!J$``*`0`]!8-N(&ETP"`,D*`2L`,VEN(" +M#U%F:7)S=)("`*8!$6%P$A%O61$`]@`6+G0``]D#`J60!`,P``*,!!H`%,7=A;G\%$G0=#P-%`0!@ +M```:!!!TC@0#`',*%E2!A8V-E<'1S +M('=H871E=F5R(&)L;V-K71E(&%T(&$@=&EM +M94,`<6]R(&UM87`H`/``96YT:7)E(&%R8VAI=F4@:0`09PD`(&ET3P`)2@!A +M="!O;F-EA0"13VX@=W)I=&4L1``%PP#Q"FQW87ES('!R;V1U8V5S(&-O2W,`/(?960@;W5T<'5T+@H*("H@5&AE(&]B:F5C="US='EL92!A<'!R +M;V%C:"!A;&QO=_H`X'1O(&AA=F4@;75L=&EP)0`#J0!Q'1E;G-I +M;VZ*``,<```J`#!E;&93`0!D`1`OY@"6=&5N('5S:6YG<@&19G5N8W1I;VYS +M#@%R66]U(&-A;I8!)6%NI``B9&G_`/`-(&9R;VT@86X@:6XM;65M;W)Y(&)U +M9F9E2UT;RUU&%)`$!S.B!3,@-4`0-)`#!C;VY#`O`".B`@5F%R:6]UP``7P%Q875T +M:&]R<\`%`1\&`?("`DT'$`H5"%!T;W`M;`P$`W8%`#`'`4$`$&GD!@FV`B)I +M;O@$(FEOX08$O0+P`DY%5U,@+2!H:6=H;&EG:'1S7`8P'2(`#!P +M=71>`C`@(F,T!A$B)`,`J@2!N965D?``Q;6%I]@$C +M97*N`05P`"1I;F0`@2YH+FEN"@DM]`=2;&%T97-G`!%B-`(#<@$"M0!@"@I' +M=6ED\P`H($14!@32`0)U``#S`8`@PH"MP(29:`,`%L$$'/4 +M!A!N$0P`U@(`DP``=0``%P(`^00!<0`!<0H(EP`!G`DC+C--``#O!#)E(")K +M`P6K``$D`!0B"PM9(&-L87-$``$?"49N86QSG0`2P$2+8($-7,N-:H(`J\``!D# +M`)\#@&UA=',@=&%R +M+C54`0CQ!$%A8F]U4P41]!9!I;@IA(&YU;6+R#!=FD0<# +MHP#7+@H*66]U('-H;W5L9*0+`$P`,6-O<'8&0&-O;6V>"`#.#1,B!0XR+F@B +MJ0`R:&4*7PP0(+`)`'4!`!0`!.D&`W((`G\"-&UO2X`P"`H8FEG +M+65N9&EA;J(!8VQI='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I;;<"$2AX +M""!O<,L#P&%L(%)O8VMR:61G944`8DIO;&EE="D!`>\!`DD`-%I)4'4$!$`` +M('5N3@DPB,``!DT%``)"`$```H"G!`%.@$`=00/!@$" +M`J\!`[\#`KP"#Q\#&#`B`3AN97>U`P#P!`#]`@.? +M`0![``&'"0$K%0)*#`!-$2)IE(7`+4(`E((07!O;&PV$@;D%$%D;VXG[`&0 +M97AP;&EC:71LV0EB=F]K92!A^@\18W\*`\X1("`HTA``=0P('`(08;(!`2<0 +M`BT`",T`%&]S!'`I+"!I="!W<`!0(&=E="#2$@%="@"D!#<@26YN``4F%P&> +M``%1`0.;`")E;LD!!RT``'P`"W$`*&1E$0`#J@`1+%@1`H```(T.`)8!`!8! +M`$``,&%G8?,/`5\*D6-O2!A;'-O(&1E=&5C=',@86YD(&AA;F1L90P` +M\!)Y(&]F('1H92!F;VQL;W=I;F<@8F5F;W)E(&5V86QU8702```@`/$-87)C +M:&EV93H*("`J('5U96YC;V1E9"!F:6QEFEP(&-O;7!R97-S:6]N%0!=8GII<#(6``0F`$TO3%I7'0"Q +M;'IM82P@;'II<"S'`"]X>B,``!DT%``)"`&58V%N(&-R96%TSP!/"!I;G1E&-E<'0@9F]J`/$'("!E;G1R:65S('1H870@.`?$#;F%M97,L($%#3',L(&5T8RDND@"P3VQD($=. +M52!T87)=``2I``+*`/$$;V-T970M;W)I96YT960@8W!I;S4`ME-64C0@(FYE +M=V,B%0`G`'@G;71R964GNP!X25-/ +M.38V,!,`6C) +M`#!H;W?X``+U``"6!0,L``(J`2%/;JH`'"P#`0/9`@)P`$!L=V%Y1@$`W0'R +M`65D(&%U=&]M871I8V%L;'E'`+!))W9E(&%T=&5M<,0#X'1O(&UI;FEM:7IE +M('-T*P"P(&QI;FL@<&]L;'6X`>$N("!)9B!Y;W4@9&]N)^P!`+8`\0)I8VET +M;'D@:6YV;VME(&$@<.L`('5L-P2@96%T=7)E("AS=2\!&7,<`A!AZ0`'+0`' +M[P4`@`$"F0%P*2P@:70@=W``X"!G970@<'5L;&5D(&ENI`0W($EN;@`W+"!I +MG@`!40$#FP`B96[)`0`(&5N +M=FER;V[7`C%S('=N`@&@`A!MV`$36QE(&%P<')O +MR`,`R0@"^@#@=&\@:&%V92!M=6QT:7`E``-3!`(!!`"Y"%4@;W!E;IX`4"`@ +M8G-D(P2!F)M96UO?<"!8P``0`"\05R;W9I9&4@96%S +M>2UT;RUU08A;W7W!%%F:7)S=)("`*8!(&$@0P41;SD+`/8` +M%BYT``/9`P*G`0":"0*<`0&%``:X`0!V``##``"\`Q)EDP`"3P<@;'GI``#, +M``"C`0:`!3%W86Z(`!!T-@0%10$`8``!^@D`C@7,N"E)%041-1;L&!^@&X2!B=6YD;&4N"@I1=65S^@*@/R`@27-S=65S/U(` +MURH@:'1T<#HO+W=W=RX@!S!O3``!(`1!HN`*#9F]R(&]N9V]8!Q@@9`!P +M9&5V96QO<#P%<2P@:6YC;'6]!4!D;V-U%``!K`@!-PP`<0``.@`A;FM=`0!= +M``9S`%`@;6%I;`<"0FQI%EB!$!G&%)`$!S.B!3,@-4`0-)`#!C;VY#`O`".B`@5F%R:6]UP``7P%V875T:&]RT/ +M4'1O<"UL#`0#Q0P`,`0&";8"(FENU@0`=`P`ZP40<],-\`4@*B!. +M15=3("T@:&EG:&QI9VATP`"-E)ZT` +M`V2XS]!0`!`,!-@`2(FL#!:L``20`%"(+"UD@8VQA!0&`$@!V`T5R;6%T:0\$8P(%E@$` +ML```"@)!+C4L("$3``D``&\`7G1A`=2!T:&4*)V-O +M;F9I9W5R92<@`""(&EN'!L86EN +M@`/`#;&EB +M2!A2XS30`"=`%U +M(G-T2!C;&%S1`"6:6YT97)N86QSG0!@2!E2QN``5H`W!U=&]M871I_P(0>68!,&5C=)D#$635``,<`E!O;&QO=Y,!$&8L +M`!!S4`51*B!'3E5U`0(U`B8@*+D!`!H`06QO;F=5`F)N86UE`*%35E(T($%30TE) +M=`(!%``"4P`/,@`%84)I;F%R>2X`H"`H8FEG+65N9&GS!(-R(&QI='1L91$` +M`OH`\0))4T\Y-C8P($-$+5)/32!I;;<"@"AW:71H(&]P^@7`86P@4F]C:W)I +M9&=E10!B2F]L:65T*0$![P$"20`T6DE05@,$0`"0=6YC;VUP[`@0]`5HW+5II<"8`V$UI8W)O`,(KP)@:&%N9&QENP(0>;<#`+8$!K@",&)E9DH# +M<&5V86QU873*`@`@``.9`P+/`A!U]@40;W$"`+8"`D,"`0H`$2"#`:)24$T@ +M=W)A<'!E3@)%9WII<#X!,6EO;A@!76)Z:7`R%@`$?`%-+TQ:5QT`HFQZ;6$L +M(&QZ:7`3`R]X>B,``!DT%``)"`&58V%N(&-R96%TSP`!=00/!@$"`J\!`[\# +M`KP"#Q\#&#`B&-E<$`%`+D%!&D"L"!T:&%T(')E<75IE@4G87C*`B`@*'T'`30$`(0! +M`S,$`/0#<2P@971C*2YO`0#Z`P"I`@8B!`$7``+:``^6`P4!R`-A(FYE=V,B +MFP,!,P`G?P(-F5A;;4% +M`A$+@"X@(%1H97)E+``C;F_B!P""`@/?"`"3!/("(&EN+7!L86-E(&UO9&EF +M:6.M"/,";W(@U`P#P!`![``.?`0![``&'"0&C``)*#`,*`P`X"`"R``$>`P"F +M!`(,`B$@8C<)<7)E861A8FP`!@","@$,``$L"P($`0!H``([`$)E86-H/0$A +M=F5S`Q-Y0P!0:6YD97"J`"5N="(!`!@)4&%R=&EC0@4D;VZ!`02N`$17:6MI +M4@PP:6YGR0`P:&]WFPP"I@<'E@H"*@$A3VX_"`#W#`)X!@$""B-N9/@``8@) +M8V%L=V%YD`!RT`!"T'`,T`%&_Y"'`I +M+"!I="!W<`!Q(&=E="!P=9P-(&ENI`0W($EN;@`W+"!IG@`(FP`B96[)`02UV```S#`#W"!%IAP8`A`!P96YV:7)O;M<",7,@=Y`#`:`"$&W8 +M`1-R6@,%,`(`6P`"?P`1>7L#$7`U`-%A=&5V97(@8FQO8VMS\```[@@``S0*%82!S;V-K970^`TEW:7-HN@0!)@\#60\`4X.475S92`B(0$`6@@@+")0"+$L(&-A<&%B:6QI=/8"!`,! +M!?$``O,/`;<$"/8%`9P"`,D*`2L`,VEN("#U%F:7)S=)("`*8!$6%P$A%O61$`]@`6+G0``]D# +M`J60!`,P``*,!!H`% +M,7=A;G\%$G0=#P$V`@%;`P$:!!!TC@0#`',*T2!S87ES+@I2 +M14%$3442!@9)$>$@8G5N9&QE+@H*475E<_H"H#\@($ESF-% +M#A)B!P`2>`<``$D!`)()`"<`02H@97@;$T!S.B!3,@-4P``7P%Q875T:&]R<\`% +M`1\&`?("`,$3$B[M#U!T;W`M;`P$`\4,`#`'`4$`!.$7!K8""',5`.L%`>X/ +M\`4@*B!.15=3("T@:&EG:&QI9VAT<]P`,')E8]D4`C$%`Z`"DD-/4%E)3D<@ +M+0P%`$(4`,H'(F1OGP``AP4`S@"T*B!)3E-404Q,("V2&`&/!`$-``#Y%@"_ +M``(I``-`!1(M1!D`E0`"&``%=QDE("T,``)$``*W&54L('-E96<``"@%`JT7 +M`F,(@2H@0TUA:V5,U`0Q='ATB``A<'5G$#`@(F,T!A0BO!DY;V]L30`"5@$& +M-0$`E```L`H!C@$/;0$!`*(&#V0:________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________________________________]G4'1O(&%L45J)ART1``#P(&QO +M=R!I;F1I=FED=6%L(&5N=')I97,*("`@=&\@8F4@2!D871A('-O=7)C93H@(%EO=2!C86X@8W)E871E/0"B82!B;&]C +M:R!O9BL`\05I;B!M96UO6]U('=A;H@`$G1=`!(O/0`#'P$`,P!09&ES:RQ. +M`/`07,N"E)%041-15``1"!L:6)M`=%B=6YD;&4N"@I1 +M=65SK@"@/R`@27-S=65S/U(`UBH@:'1T<#HO+W=W=RXX`$`N;W)GDP``2`$Q +M:&]MIP"`(&]N9V]I;F8$(&YDT`(Q9G5L+P(&10!1+VUI;FF%`1%AXP%186-T('-@ +M`+`@9&5M;VYS=')A=+\`!,GK0`#)`0`DP``3@#U`2YA +M;2P@86-L;V-A;"YM-"SA`$!E+F%C_P```@`0+:("`)\`!*@`#*($LBP@;VYL +M>2!N965D?``Q;6%I]@$C97*N`05P`"1I;F0`@2YH+FEN"@DM]`=2;&%T97-G +M`!%B-`(!9@$39;4`8`H*1W5I9/,`*"!$5`8$T@$"=0`!MP%P!1%E^P,`\@"`;6%T +M``&I`5"`"X!!,B?P(R+F@BJ0`R:&4*7PP0(+`)`'4! +M`!0`!.D&`W((`G\"-&UO@,QBH@4U92 +M-"!!4T-)210``E,`#S(`!6%":6YAB,``!DT%``)"`$```H"G!`%.@$`=00/!@$"`J\!`[\#`KP"#Q\# +M&#`B?P(-F5A;;4%`A$+<"X@(%1H +M97(T$2`@;M82,7)E8S`1`]\(`),$02!I;BT"#X(@;6]D:69I8^4,\@%O`3AN +M97>U`P#P!`#]`@.?`0![``&'"0&C``)*#`!-$2)I7-S +M""IE9(H(`D<`L$DG=F4@871T96UPC```%1`0.;`")E;LD!!RT``'P`"W$`*&1E +M$0`#Q@(1+.4)`H```(T.`)8!`!8!`$``,&%G8?,/`5\*D6-O7L#$7`U`&)A=&5V97)X%Q%S\```[@2X'$'1[%R%I;5<#<6]R(&UM87`I +M`0!>$P'Y%@*Y%P"V`A!GPA<0:2(3`2(`!4H``.,3(6-EA0`A3VZ0`QMEPP`" +MY`(R<')O.@$!A0$`FA<1+408DF5D(&]U='!U=.\"`&`$\0-O8FIE8W0MFEP,A8` +M!"8`32],6E<=`+%L>FUA+"!L>FEP+!0!*7AZ(P#!"DYO=&5S(&%B;W5TE`!R +M;&EB=$`\"YT96-T=7)E.@H*("H@5&AI0`&EP#@:7,@9&5S:6=N960@=&]>`61E>'1E;F1>`3AN97?@``#S`#(* +M("#.`!!V<@$`]`$22!R97%U:7)E;65N=+(`,G1H80D!`BL` +M("!BCP&0(')E861A8FQEH@!!=W)I=`P`$&$,`0($`0!H``([`$5E86-H;P!3 +M96YT'!L86EN:6YGR0`P:&]W^``"]0`'+``"*@$A3VZJ`!PL`P$`48!`-T!\@%E9"!A=71O;6%T:6-A;&QY1P"P22=V92!A='1E +M;7#7`>!T;R!M:6YI;6EZ92!S="L`L"!L:6YK('!O;&QUN`'A+B`@268@>6]U +M(&1O;B?L`0"V`/$":6-I=&QY(&EN=F]K92!A('#K`(!U;&%R(&9E85D"0"`H +MD`!RT`!P8#`(`!`ID!<"DL(&ET('=P`/``(&=E="!P=6QL +M960@:6XN/@`G26YN`#``%1`0.;`")E;LD!!RT``#X`"W$`*&1E$0`# +MQ@(1+/```H``(FYEC@(`%@$`0`!B86=A:6YS1P*@8V]R7L#$7`U`-%A=&5V97(@8FQO8VMS\``0:%<%(6ETH0!!66]U +M717`F$@82!T:6U7 +M`W%O`+$@(&)S9'1A3X`!8P``0`"\05R;W9I9&4@96%S>2UT;RUUX`0!V``##``"\`Q)EDP`"3P0"0 +M:7,@97-P96-I;@0!T`$"J@$`.@CS`SH@(G!A>"!I;G1E7!1`GH@1`9W)A;18"`<` +M`$D!`)()`"<`4"H@97AA20!`8$(&YDT`(Q9G5L+P(&10`0+T,*`84!$6&>"E%A8W0@=&%R+C54`0CQ!`4^$A%S8P0Q<&]PY0\#G`$$ +M>P`(2PE`:&%R9!8,`3`&!%L!`4<``(X!86UO9&5R;H\``.@!`+P'<"!V87)I +M86Y("0":!3!M86[X"T%P86=E.```,0XD``'?`5=H+`#L'`2,)"=H1`,$",&5C=)D#$61A#0,<`@2# +M%"`@9@82`;<&`D$5!JH+)B`H!`L`6Q4@;&\O`#!I;&6M"R)S+!````4+$R`1 +M``!C`%)S<&%R`*%35E(T($%30TE)=`(!%``/,@`+$$)M$1%Y+@"Q("AB:6%Q8/"Q<`T$UI8W)OQ=4`)H`-6QZ-*@!`.47"0@! +M```*`IP0!4L!`'4$#P8!`@*#`0._`P*\`@\?`Q@P(G)EH`T`$!81(D<#`D\` +MPBP@=VAI8V@@=VEL;.L8`'`(`!D$`U\!0',@97@M%``"`@"Y!02)$0(+%P-: +M%P%1``7I$C!S("A3"@$T!`"$`0,S!`#T`V`L(&5T8RGO"P+Z`P"I`@!M``*- +M``&;`0+:``_(`PIA(FYE=V,BFP,!,P`G2*5Z4]A61$``/,U('5T:6QI='D@8VQA`'!L:6)R87)Y3`#08W!I;RXU+"!M=')E90D``&\`5'1AP#S"2P@:6YC;'5D:6YG(&AA``"/`/0:("=D;V,G(&1I2!I;@IA(&YU;6)E6]U(#\!8"X*"D-UFEP,A8`!'P!32],6E<=`*)L>FUA+"!L +M>FEP$P,O>'HC```9-!0`"0@!E6-A;B!C,H"4B`H9F]R-`0`A`$# +M,P0`]`-Q+"!E=&,I+F\!`/H#`*D"!B($`1<``MH`#Y8#!0'(`V$B;F5W8R*; +M`P$S`"=S:+```1(`#T8#8P0%!`);`0&)``]9`P`*%@,S5VAE`P(`V`(#U`(2 +M<^8%87)E'!L86EN:6YGR0`P:&]W^``"I@<`K0$# +M+``"*@$A3VX4"1PL`P$#^``!B`E086QW87E&`0#=`2IE9(H(`D<`L$DG=F4@ +M871T96UPC`?@=&\@;6EN:6UI>F4@D`!RT`!"T'`,\*%&_Y"'`I+"!I="!W<`""(&=E="!P=6S["@"D +M!#<@26YN`#``B;`")E;LD!!RT``'P`"W$`*&1E$0`#Q@(1+/```H`` +M(FYEC@(`%@$`0`!B86=A:6YS1P*18V]R0`P&@`A!MV`$38!(71O(@`%H0!A="!O;F-EA0`A3VZ0`QMEPP`"Y`(R<')O +M.@$!A0%18W1L>2W,``"."5)U='!U=.\"`&`$\0-O8FIE8W0M60!`,P``*,!!H`%,7=A;G\%$G0=#P$V`@%; +M`P!C#``S`$%D:7-K+`,`L1`0#B)A;N@"`*4' +M`!$#`EH'$"QC`$!D97-PH@``;`0!Y`,`7,N"E)%041-11(&!DD1 +MX2!B=6YD;&4N"@I1=65S^@*@/R`@27-S=65S/U(`UBH@:'1T<#HO+W=W=RXX +M`$`N;W)GDP``2`$0:+@"$&:Q#S-N9V]8!Q<@3`>`(&1E=F5L;W`\!0@9$02Z +M$0&L"`$W#`!Q```Z`"%N:UT!`%T`!G,`4"!M86EL!P(P;&ESOQ`!G0`05)D! +M`.41`.%E8$(&YDT`(Q9G5L+P(&10`0+T,*`84!$6&>"C1A8W1[$W!D96UO +M;G-T.14@;F<^``"`!094`@-)`#!C;VY#`F$Z("!687+N$V!I=&5M$0(8`&!C;VYF:6>R%A4M#``"1`"UM`Q$SM@L`$!20(&]V97)V:65W\P(` +MJP`%P`L`<04P=VAOD0(4*J0*A5]R96%D+C,L$``!^`@-$0!17V1I:L`D'-A;64@9G5N8S`<``$D!0'-U8V@G`%`J(&5X84D`U',Z(%-O;64@6]U(&UA>2!F:6YDT`(Q9G5L+P(&10!1+VUI;FF%`1%A +MXP%186-T('-@`*$@9&5M;VYS=')AP0$`#@,G;V9>`0-)`#!C;VY#`O`".B`@ +M5F%R:6]UP``=`+Q`F%U=&AO@`K1#3U!9 +M24Y'("T@=U$!8F-A;B!D;Y\`,W1H:2D`\@))3E-404Q,("T@:6YS=&%L;'4` +M``T`(7)U*@(#*0"!4D5!1$U%("T\``&5``*3`+!C;VYF:6=UM``,D!`"3``!.`/4!+F%M+"!A8VQO8V%L+FTT +M+.$`0&4N86/_```"`!(M5``D=&^H``RB!+(L(&]N;'D@;F5E9'P`,6UA:?8! +M(V5R7`$%<``D:6YD`/(#+F@N:6X*"2T@=&5M<&QA=&5S9P`18C0"`68!$V6U +M`&`*"D=U:63S`%`@1&]C=9D%`H$!`,4!,F%L;'4``;\%1FYA;'.=`#!S('-4!6%I;G-I9V@1!@B9!Q$G9P($-P`2(&\``$`"`*$% +M,&]P92L%,&]N+J@`!GL!$BV"!%-S+C4@9%8"`J\``!D#`/(`@&UA=',@=&%R+C54`0CQ!$%A8F]U +M4P4@P`3+/('`(H!@6AA``%4!%"`"X!!,BO0(R+F@B +MJ0"`:&4*2R"```[!P$C"4!A=71ODP8`_P(0><$",&5C=)D#$60Y"0,<`@5X +M"1!F+``!MP91*B!'3E5U`0(U`B(@**L)`+D!`!H`06QO;F=0!F)N86UE`@@;W#+`\!A;"!2;V-KFEP/@$Q:6]N&`%=8GII<#(6``1\`4TO3%I7'0"B;'IM82P@;'IIL``7\*`\X1 +M("`HTA`E(&'["@"A`2`@8>D``2<0`BT`",T`%&_Y"'`I+"!I="!W<`!!(&=E +M=!D3`5T*`*0$-R!);FX`-RP@:9X``5$!`YL`(F5NR0$'+0``?``+<0`H9&41 +M``/&`A$L\``"@```C0X`E@$`%@$`0``P86=A+@X!\0F18V]RP,B:67-#P&<$P/G"B!D=1D-`)\#$'.%`2-O9H@!`(X2$"UV```S +M#`#W"!%IM`\`A`!R96YV:7)O;@\+$7>0`P&@`A!MV`$3<3`<0-0&)A +M8VL>!#%F2W,`))E9"!O=71P=73O`@!@!/$#;V)J96-T+7-T +M>6QE(&%P<')OR`,`^10"^@#0=&\@:&%V92!M=6QT:<,3!*D``@$$`+D(52!O +M<&5NG@`3(!40`&H0``H!`#T%@VX@:71S(")`/``2(KT$$7,P#@)C!098`&!I +M='-E;&93`5!R96%D+^8`8'1E;B!U@``S0*% +M82!S;V-K970^`TEW:7-HN@0!)@\#60\`3``!(`1!HN`(`5P!#;VYG;U@'%R!, +M!R`@9%@6(&]P/`4(&1$$NA$!K`@!-PP`<0``.@`@;FLT`0'!``9S`$$@;6%I +MVQ(`^QD"H`,!_1D/9!K_________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_________________________UI0("!4:&44.]4X*A$``$%R92!A!`#W*G1I +M8VQE2W,`))E9"!O=71P=70&`>!4:&4@ +M;V)J96-T+7-T>1`"4'!P3 +M``!(`1!HN`*#9F]R(&]N9V]8!Q@@9`!P9&5V96QO<#P%<2P@:6YC;'6]!4!D +M;V-U%``087<`$"Q8!P!Q```Z`"%N:UT!`%T`!G,`4"!M86EL!P)";&ES=*`# +M,"H@5)D!`>H&0&%N(&FW`!`L(00!_``!#P"A('1R86-K97(@8&%) +M`$!S.B!3,@-40&";8"(FENU@0`<0L`ZP4$O0+P`DY%5U,@+2!H +M:6=H;&EG:'1S7`8P'2(`")P=;H+(")C-`81(B0#`!(+*6]L30`"5@$& +MZP,`E``!%@D`C@$/;0$!`&8(('5SW0H`V@$T90HGL``C92>M``-G`0"3``!. +M`/``+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C_P```@`0+:("`)\`!*@``&H+ +M"*($82P@;VYL>=<+`GP`,6UA:?8!(V5RK@$%<``D:6YD`($N:"YI;@H)+?0' +M4FQA=&5S9P`18C0"`W(!`K4`8`H*1W5I9/,`*"!$5`8$T@$"=0`!MP%PP`(2PE`:&%R9!8,`3`&!%L!`4<``(X!86UO9&5R;H\``.@!`+P'<"!V87)I +M86Y("0":!3!M86[X"T%P86=E.```L!`D``$=`U=H+`#L'`2,)"=H1`,$",&5C=)D#$62V#P,<`@5X +M"1!F!A(!MP91*B!'3E5U`0(U`B8@*`0+`!H`(VQOO`4`K0LB+``-J`0`9`[$J(%!/4TE8('5S=+`1!!``#XH,`P%\``(Q`+!O8W1E="UO +M\!`DD`-%I)4'4$!$`` +M('5N,0L`[!,`UA!@"T4``("`+D%!(D1`FL4`$,.`-,3`%$``;$6`0`&@`0I:7-N%")B98@%`$`$`5X!.&YE=[4#`/`$`/T" +M`Y\!`'L``8<)`2L5`DH,`PH#`#@(`&\0%'3N$@(,`B$@8C<)`(P*`8\8`[@4 +M`0P`$&$,`0+4$`!H``([`!%EG!8`/0$A=F5S`Q-Y0P!0:6YD97"J`"5N="(! +M`$0-#V0:____________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________]C4&%N9"!RUWE3_3`1``#P)F5A9',@=&AE(&9O;&QO=VEN +M9R!F;VUA=',Z"B`@*B!'3E4@=&%R(&9O'1E;F1E9&0`!#-!0TPS`&%/;&0@5C2!O9K@"X&)E9F]R +M92!E=F%L=6%TI`(`V`(#+P("SP)@=75E;F-O<0(`M@("0P(!"@`1((,!HE)0 +M32!WFEP/@$Q:6]N!0%=8GII<#(6``1D`4TO3%I7'0"B;'IM +M82P@;'II0`&EP"0:7,@9&5S:6=NH@9";R!B98@%`$`$`3`$.&YE=[4#`*,$`'L` +M`4,`4&EN +M9&5PJ@`B;G1_`!!R.P0`!``P=&EC0@4D;VZ!`02N`/``5VEK:2!E>'!L86EN +M:6YGB0`P:&]W^``!LP,09)8%`RP``BH!(4]NJ@`<+`,!``0$,FUA='``0&QW +M87E&`0#=`6!E9"!A=71>"&)I8V%L;'E'`+!))W9E(&%T=&5M<(P'X'1O(&UI +M;FEM:7IE('-T*P`"4@A0<&]L;'6X`>$N("!)9B!Y;W4@9&]N)^P!`+8`\0)I +M8VET;'D@:6YV;VME(&$@<.L`('5LO0B@96%T=7)E("AS=2\!&7,<`A!AZ0`' +M+0`$10<#(@("F0%P*2P@:70@=W``X"!G970@<'5L;&5D(&ENI`0W($EN;@`W +M+"!IG@`!40$#FP`B96[)`07L#$7`U`-%A +M=&5V97(@8FQO8VMS\```[@2X'<70@82!T:6U7`W%O8!(71O(@`%H0!A="!O;F-EA0`A3VZ0`QMEPP`"Y`(R<')O +M.@$!A0%18W1L>2W,``"."5)U='!U=.\"`&`$\0-O8FIE8W0M2!B=69F97(@)`@`90`$<@&%82!S +M;V-K970^`TEW:7-HN@3`P"`,D*`2L`,VEN(">D``,P` +M`*,!!H`%,7=A;H@`$'0V!`5%`0!@```:!!!TC@7,N"E)%041-1;L&!^@&X2!B=6YD;&4N"@I1=65S^@*@/R`@27-S=65S/U(` +MURH@:'1T<#HO+W=W=RX@!S!O3``!(`1!HN`*#9F]R(&]N9V]8!Q@@9`!P +M9&5V96QO<#P%)BP@8`]`9&]C=10``:P(`3<,`'$``#H`(6YK70$`70`&8N9V]O9VQE+F-O;2]P+VH`$2\Z`"!S+VD``),` +M`6<`47-U8FUI9P!P96YH86YC9;L``#8"!C@`@RP@<&QE87-E+```.P``!`,` +M2PB!$!G0&";8"(FENU@0`I`H`ZP4![@_P!2`J($Y%5U,@ +M+2!H:6=H;&EG:'1S7`8PM```Z#S`@ +M*B"3``!.`/``+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C_P```@`0+:("`)\` +M!*@``-D."*($$BP:#@#7"P!9"Q!YR@4!]@$C97*N`05P`"1I;F0`@2YH+FEN +M"@DM]`<`YA,22XS]!0P86EL[P0R92`B:P,%JP`!)``4(@L+62!C;&%S +M1``!'PE&;F%L``'?`56]U(&UA>2!F:6YD +M('5S969U;"Y%`/$&+VUI;FET87(Z(&$@8V]M<&%C="!S8`#@(&1E;6]NP#R*71H92!A=71H;W)S('=I=&@@86YY('%U97-T:6]N7-T96TZ"B`J(&)S9'1A2!A``"/`&<@)V1O8R>]!;!I;@IA +M(&YU;6)E2QN``5H`S!U=&^3!@#_ +M`A!YP0(P96-TF0,19-4``QP"!<(&$&8L``&W!E$J($=.574!`KH!)B`HN0$` +M&@!!;&]N9U4"8FYA;65S+!``4VQI;FL@$0``8P!A`@@;W#+`\!A;"!2;V-KB,``!DT%``)"`$```I58W)E873/``%U +M!`\&`0("J@,#OP,"O`(/'P,8,")R9?X(46-T960B1P,"3P#$+"!W:&EC:"!W +M:6QLB@`!5@`%R@%A(&5X8V5P0`4`N04$:0("%0QQU`P#P!`![``.?`0![``&'"0&C``)*#`,*`P`X +M"`"R`#%T:&$O"0,K`"$@8C<)`&H(,6%B;``&`(P*`0P``2P+`@0!`&@``CL` +M0F5A8V@]`2%V97,#$WE#`%!I;F1E<*H`)6YT(@$`&`D`#P\08T(%$F]L#08U +M"E0@5VEK:5(,,&EN9\D`,&AO=U$/`;,#%V26"@(J`2%/;C\(`/<,`F`&`P,! +M!,T``7``0&QW87E&`0#=`2IE9(H(`D<`<$DG=F4@870M#0",!P#!#Y!I;FEM +M:7IE(',.#1)C4@A!<&]L;)0-42X@($EF]0A09&]N)W2H`)!E>'!L:6-I=&S9 +M"6)V;VME(&'Z#Q%C?PHQ9F5A-`L0*-(0`'4,"!P"$&%!``$G$`(M``C-`!1O +M^0AP*2P@:70@=W``<2!G970@<'6<#1!I>@M'("!);FX`-RP@:9X``5$!`YL` +M(F5NR0$'+0``/@`+<0`H9&41``.J`!$L\``"@```C0X`E@$`%@$`0``@86<# +M#@)0`Y%C;W)R97-P;VY<"PA)``&]#P@1``)D!R)I92UV```S#`#W"!%IM`\`A`!P96YV:7)O;M<",7,@ +M=Y`#`:`"$&W8`1-R6@,%,`(`6P`"?P`1>7L#$7`U`-%A=&5V97(@8FQO8VMS +M\```[@2W,`))E +M9"!O=71P=73O`@!@!/$#;V)J96-T+7-T>6QE(&%P<')OR`,`0Q("^@#@=&\@ +M:&%V92!M=6QT:7`E```A!1!V$@-``!,@%1``:A``"@$` +M/06#;B!I=',@(D#E`!(BO0012!F4X.``P1$2(A`0!:""`L(E`(H"P@ +M8V%P86)I;&D2%`8#`0"_``'Q``+S#P$_#@CV!0&7`8`@:6YD:79I9&P.`]L( +M`(4``#H2`D(``*P+`-$``#8!(71OK`TP9&%TUP``!0X1.L$"`2X!`L@)`#T` +M$F'L`@#)"@$K`#-I;B`G`0"/`C-A9&2.`AAA]PP!UP<#'@]19FERA$)P`$`B0``,!0"@1-@97-P96-I;@0!T`$"J@$` +M.@@P.B`BDPH!#A$)V@T3(KD"`-X.(F%NZ`(`I0<&-`H0+&,`0&1EA<"+```.P``!`,`2P+%1`G-Q,`)AD`%@)S +M82!F=6QL+98(6]U(&AA;F0@:70N"B`@(%EO=7(@71E(&%T(&$@=&EM90H@("!O6QE(&%P<')O86-H(&%L;&]W +M^@#@=&\@:&%V92!M=6QT:7`E``.I`'!S=')E86US$@%%;W!E;IX`P"`@8G-D +M=&%R('5S90H!PVES(&EN(&ET2!B=69F97(@;W+!``!E +M``1R`3!A(',K`5%T+"!I9OP!8'=I2UT;RUU`@#1```V`:!T;R!A;GD@9&%T +MUP!6=7)C93HN`5%CX`0!V``##`!%EW@(!O@`%RP$`TP`#HP%#+B`@ +M2:0!(6%NB``2=%T``38"`5L#`!\!`+H`061I"!I +M;G1E`<``$D!0'-U +M8V@G`%`J(&5X84D`0',Z(%,R`U1S;6%L;!4`!#X!`%(#(6%T(`8@;6'F!"!N +M9-`",69U;"\"!D4`42]M:6YIA0$18>,!46%C="!S8`"P(&1E;6]N0&";8"(FEN^`0B:6_A +M!@2]`O`"3D574R`M(&AI9VAL:6=H='-M``,D!`"3``!.`/4!+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_ +M```"`!`MH@(`GP`$J``,H@2R+"!O;FQY(&YE961\`#%M86GV`2-E'!L@P(#+P,`0@$"(0`$ +MF@,#,P``B`0/-``+`"(`##4`+V%T-``,*&%T,P`&`08A+C.V"Q!SWP:`;W9E +M"P!Q!3!W:&^1`A0JI`J%7W)E860N,RP0``'X"`T1`%%? +M9&ES:Q8``GX'`X(%`3X``QP``)D``7L*`K<"$F6@#`!;!!!SU`80;A$,`-8" +M`),``'4``!<"`/D$`7$``7$*")<``9P)(RXS30``[P0R92`B:P,%JP`!)``4 +M(@L+62!C;&%S1``!'PE&;F%L=H+`#L' +M`2,)@&%U=&]M871IGP\0><$",&5C=)D#$61Y#`,<`@5X"1!F+``!MP91*B!' +M3E5U`0(U`B8@*`0+`!H`06QO;F=0!@"M"R)S+!````4+$R`1``!C`%)S<&%R +M`@@;W#+`\!A +M;"!2;V-K[`@0]`5HW+5II<"8`V$UI8W)OFEP,A8`!'P!32],6E<=`*)L>FUA +M+"!L>FEP$P,O>'HC```9-!0`"0@!```*`IP0!3H!`'4$#P8!`@*O`0._`P*\ +M`@\?`Q@P(G)EH`U18W1E9")'`P)/`,0L('=H:6-H('=I;&R*``%6``:0`%%E +M>&-E<$`%`+D%!(D142!T:&%T0PX`TQ,`40`%Z1(P?P(-F5A;;4%`A$+!8@40&ES +M(&[6$C%R96,P$0/?"`"3!`#E%`&W#X(@;6]D:69I8^4,]P!O'!L +M:6-I=&S9"6)V;VME(&'Z#Q%C?PH#SA$@("C2$`!U#`@<`A!AL@$!)Q`"+0`( +MS0`4;W,$<"DL(&ET('=P`%`@9V5T(-(2`5T*`*0$-R!);FX`!287`9X``5$! +M`YL`(F5NR0$'+0``?``+<0`H9&41``.J`!$L6!$"@```C0X`E@$`%@$`0``P +M86=A\P\!7PJ18V]R7L#$7`U`&)A=&5V97)X%Q%S\``` +M[@9"!H86YD;&5S(&%N>2!O9B!T +M:&4@9F]L;&]W:6YG(&)E9F]R92!E=F%L=6%T$@``(`#Q#6%R8VAI=F4Z"B`@ +M*B!U=65N8V]D960@9FEL97,4``$*`/$"('=I=&@@4E!-('=R87!P97(;`/$! +M9WII<"!C;VUPFUA+"!L +M>FEP+"!A;F0@>'HC```9-!0`]0<*5&AE(&QI8G)A"!I;G1E&-E<'0@9F]J`/$'("!E;G1R:65S('1H870@.`?$#;F%M97,L($%#3',L(&5T8RDND@"P +M3VQD($=.52!T87)=``2I``+*`/$$;V-T970M;W)I96YT960@8W!I;S4`ME-6 +M4C0@(FYE=V,B%0`G`'@G;71R964G +MNP!X25-/.38V,!,`6CT!X'-Y0`&EP#R`FES(&1EP`!S@`4=E@#$G.C`%0@;VYL>0H#0&UE;G2R``$>`P"F!`)G`S`@8F5``(!R +M96%D86)L9:(`07=R:70,`!!A#`$"!`$!1`0!.P!$96%C:"8"`98"$WE#`%!I +M;F1E<*H`(FYT?P`04<`L$DG=F4@871T96UPQ`/@=&\@;6EN +M:6UI>F4@2!I;G9O:V4@82!PZP`@=6PW!"!E85D"0"`HD` +M!RT`!^\%`(`!`ID!<"DL(&ET('=P`.`@9V5T('!U;&QE9"!I;J0$-R!);FX` +M-RP@:9X``5$!`YL`(F5NR0$'+0``?``+<0`H9&41``/&`A$L\``"@``B;F6. +M`@`6`0!``&)A9V%I;G-'`J!C;W)R97-P;VYD)P0(20`-6@`">P,Q:65SPP`! +M;P.A86QS;R!R961U8[D%,&4@`(&5N=FER;V[7`C%S('=N`@&@`A!MV`$36QE +M(&%P<')OR`,`R0@"^@#@=&\@:&%V92!M=6QT:7`E```A!1!V$@,`!04`N0A5 +M(&]P96Z>`%`@(&)S9",'(75SO`$`/06#;B!I=',@(D#E`!(BO01&"2`L(E`(<"P@8V%P86)!``'V`@)F +M!A%E50(!\0!A92!!4$ESMP0(]@4!EP&Q(&EN9&EV:61U86QH!1%IWP<`>P`2 +M8D(``"P$`-$``#8!(71OFPDP9&%TUP!6=7)C93HN`0+("0#"`!)A[`(`R0H! +M*P`S:6X@)P$`3P@S861DC@(18?P(!*H!`'D&(6]U]P119FER0#`',*T"!S87ES+@I214%$346[!@?H!N$@8G5N9&QE+@H*475E<_H"H#\@ +M($ES8N9V]O9VQE+F-O;2]P +M+VH`$2\Z`"!S+VD``),``6<`47-U8FUI9P!P96YH86YC9;L``*8`!C@`@RP@ +M<&QE87-E+```.P``!`,`2P7!1`GH@1`9W)A;18"F-%#A)B!P`2 +M>`<``$D!`)()`"<`4"H@97AA20!`8$(&YDT`(Q9G5L+P(&10`0+T,*`84!$6&>"E%A8W0@H($',+!0$^ +M`0!U```7`@#Y!`%Q``%Q"@B7```\"3-Y+C--``#O!#)E(")K`P6K``$D`!0B +M"PM9(&-L87-$``$?"49N86QSG0`2!Q(M@@0U"`"X!!,B!0XR+F@BJ0`R:&4*7PP0(+`)`/H``!0`!.D& +M`W((`G\"$&T:%P/[`$(N("!0B@FS;&5T('5S"FMN;W>5$P`P%&!E\6`2T5`A``#XH,`P,!Y1$0``\")C2!N965D960@8GD@;6%I;G1A:6YE84`(2!SM0!P"@I'=6ED98(` +MD$1O8W5M96YT87@`@B!I;G-T86QL=0`!EP#P$7-Y-50!(FEN;P"0 +M:6]N(&%B;W5T4`$@P"`+"!I;F-L=62*`<5H87)D +M+71O+69I;F1;`0%'``!!`&%M;V1E``"/`/`-("=D;V,G(&1I2!I;@IA(&YU;6)E6]U(#\! +M8"X*"D-U+``-J`0`9`]$J(%!/4TE8('5S +M=&%R6P`"$``P<&%X20-Q97)C:&%N9WX!-VUA="$`L&]C=&5T+6]R:65N`0,` +M8`(!'@"A4U92-"!!4T-)270"`10``E,`#S(`!6%":6YAFEP,A8` +M!'P!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9-!0`"0@!E6-A;B!C0`&@`0` +M#@Q397-I9VXE#!)EO@(`0`0!,`0X;F5WM0,`\`0`>P`#GP$`>P`!APD!HP`" +M2@P#"@,`.`@`L@`!'@,`I@0"#`(A(&(W"7%R96%D86)L``8`C`H!#``!+`L" +M!`$`:``".P!"96%C:#T!(79E4,`4&EN9&5PJ@`E;G0B`0`8"5!A`8!`@HC;F3X``&("6-A;'=A>7-S""IE9(H(`D<`<$DG=F4@870M#0", +M!]!T;R!M:6YI;6EZ92!S#@T28U((07!O;&R4#5$N("!)9O4(0&1O;B?6!P&V +M`%!I8VET;-D)@79O:V4@82!PZP`!?PHQ9F5A-`LP*'-U+P$%^PH`J0`@(&'I +M``0`P&@`A!MV`$32X'<70@82!T:6U7`W%O8!(71O(@`%2@!A="!O;F-EA0`B3VX<#@O#``+D`C)P`!,@%1``!A`` +M"@$`/06#;B!I=',@(D`\`!(BO0012!F +M#B)A;N@"`*4'!C0*$"QC`$!D97-PH@`` +M;`0!Y`,`7,N"E)%041-11(&!DD1X2!B=6YD;&4N"@I1=65S^@*@ +M/R`@27-S=65S/U(`UBH@:'1T<#HO+W=W=RXX`$`N;W)GDP``2`$0:+@"$&:Q +M#S-N9V]8!Q<@3`>`(&1E=F5L;W`\!0@9$02Z$0&L"`$W#`!Q```Z`"%N:UT! +M`%T`!G,``)H4`=L2,&QI<[\0`0T5$%29`0#E$0#G`1!IMP`0+"$$`?P``0\` +MD2!T1$@#R$0`6`G-A(&9U;&PME@AR9"`G=&%R)P\!`0(`(7)EK0H!0@$` +MF!8`@08`B@`#8P``*@`"HA,&8P``P1`+9``&TQ(!,`,P9F%C*@<`/0`#`@`` +M*1`B;G1H`P`5`39S86V6`Q!AP!0`+0!7*B!C871I`"MA=&@`(7-ITA((M0!` +M=&]O;#,!`$```P(`('IC10X28@<`$G@'``!)`0"2"0`G`$$J(&5X&Q-`8$(&YDT`(Q9G5L+P(&10`0+T,* +M`84!$6&A"S1A8W1[$W!D96UO;G-T.14@;F<^``"`!094`@-)`#!C;VX%&&$Z +M("!687+N$V!I=&5MP``7P%Q875T:&]R<\`%`1\&`?("`,$3$B[M#U!T;W`M;`P$`\4,`#`' +M`4$`!.$7!K8""',5`.L%`>X/\`4@*B!.15=3("T@:&EG:&QI9VAT<]P`,')E +M8]D4`C$%`Z`"DD-/4%E)3D<@+0P%`$(4`,H'(F1OGP``AP4`S@"T*B!)3E-4 +M04Q,("V2&`&/!`$-``#Y%@"_``(I``-`!1(M1!D`E0`"&``%=QDE("T,``)$ +M``("&54L('-E96<``"@%`JT7`F,(@2H@0TUA:V5,U`0Q='ATB``A<'5G$#`@ +M(F,T!A0BO!DY;V]L30`"5@$&-0$`E```L`H!C@$/;0$!`"`-`1`:`=H!-&4* +M)[``(V4GKQD#)`0`DP``3@`/9!K_________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_________________________________U90("`@=&^SOU&I.Q$``/(V(&)E +M(')E860@;W(@=W)I='1E;B!T;R!A;GD@9&%T82!S;W5R8V4Z("!9;W4@8V%N +M(&-R96%T90H@("!A(&)L;V-K(&]F*P#Q!6EN(&UE;6]R>2!A;F0@861D(&ET +M3`#P!2!T87(@87)C:&EV92!W:71H;W5T00!19FER2!F:6QE+G0`0F%L6]U('=A;H@`$G1= +M`!(O/0``8``P:65S,P!09&ES:RQ.`/`,0#P*FES(&5S<&5C:6%L;'D@96%S>2X*"B`J($YO +M=&4Z(")P87@@:6YT97)C:&%N9V4@9F]R;6%T(B!I<^```#,``.(`<7AT96YD +M960X`0(B`!`L8P!`9&5S<-\`0'=H8726`/`#(&YA;64@F-A="P@8@<`$G@'``!)`4!S=6-H)P!0*B!E>&%) +M`$!S.B!3,@-4`0-) +M`#!C;VY#`O`".B`@5F%R:6]UP``7P%Q875T:&]R<\`%`1\&`?("``$%4"X* +M"E1HG0$P<"UL#`0#=@4`"08!00`0:20%";8"(FENU@0Q:6]NZP4$O0+P`DY% +M5U,@+2!H:6=H;&EG:'1S7`8PM``,D!`"3``!.`/4!+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_```" +M`!`MH@(`GP`$J``,H@2R+"!O;FQY(&YE961\`#%M86GV`2-E7-T96TZ<`<"N`1U+C$@97AP;(,"`R\#`$(!`B$`!)H# +M`S,``(@$#S0`"P`B``PU`"]A=#0`#"AA=#,`!@$&@"XS(&=I=F5SWP:`;W9E +MP$2+8($-7,N-:H( +M`)X%$67[`P#R`(!M871S('-U<'\(!&,"!98!`$P```H"D"XU+"!M=')E90D` +M`&\`7G1A`D09BP``;<&42H@1TY5=0$"-0(F("@$"P`:`$%L;VYG50(`K0LB+``-J`0`9`]$J(%!/4TE8('5S=&%R6P`"$``/B@P#!R$`P&]C=&5T +M+6]R:65N=!<$,7!I;QX`IE-64C0@05-#24D4``)3``\R``5A0FEN87)Y+@#` +M("AB:6FEP,A8` +M!'P!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9-!0`"0@!```*`IP0!3H! +M`'4$#P8!`@*O`0._`P*\`@\?`Q@P(G)EH`U18W1E9")'`P)/`,,L('=H:6-H +M('=I;&PF$0)U`P:0`%%E>&-E<$`%`+D%`4,`4&EN9&5PJ@`E;G0B`0!$#0`/#Q!C0@42 +M;VP-!C4*5"!7:6MI4@P##!,P:&]W^``"]0``K0$#V@`"*@$A3VX_"`#W#`)@ +M!@#S#@!0!@/-``%P`%-L=V%Y'!L:6-I#16" +M:6YV;VME(&'Z#Q%C?PH#SA$@("C2$"4@8?L*`*$!("!AL@$!)Q`"+0`(S0`4 +M;W,$<"DL(&ET('=P`%`@9V5T(-(2`5T*`*0$-R!);FX`,BP@:8(5`9X``5$! +M`YL`(F5NR0$'+0``?``+<0`H9&41``/&`A$LY0D"@```C0X`E@$`%@$`0``P +M86=A\P\!7PJ18V]R"(&5N=FER;VX/ +M"Q%WD`,!H`(0;=@!$W):`P4P`@!;``)_`!%Y>P,1<#4`8F%T979E$E33SDV-C`3`+0W+5II +M<"!AFUA+"!L>FEP+"!A;F0@>'HC`,$*3F]T97,@86)O=724`')L:6)R +M87)YT0#P+G1E8W1U2!S=')E86TM +M;W)I96YT960@4,`4&EN9&5PJ@`B;G1_`$%R92!A!`"4=&EC;&5S(&]N@0$#=@+P`2!7:6MI +M(&5X<&QA:6YI;F?)`#!H;W?X``+U``$N("!)9B!Y;W4@9&]N +M)^P!`+8`\0)I8VET;'D@:6YV;VME(&$@<.L`@'5L87(@9F5A60)`("AS=2\! +M&7,<`A!AZ0`'+0`'!@,`@`$"F0%P*2P@:70@=W``\``@9V5T('!U;&QE9"!I +M;BX^`"=);FX`-RP@:9X``5$!`YL`(F5NR0$'+0``/@`+<0`H9&41``/&`A$L +M\``"@``B;F6.`@`6`0!``&)A9V%I;G-'`J!C;W)R97-P;VYD)P0(20`-6@`" +M>P,Q:65SPP`!;P.P86QS;R!R961U8V6;`C!E('.%`2-O9H@!`+,!$"UV`&%E +M9"!B:6X]`"`@:2P$@"!E;G9IP,1<#4`T6%T979E8!(71O(@`%2@!A="!O;F-EA0`A +M3VZ0`QMEPP`"Y`(R<')O.@$!A0%18W1L>2W,`))E9"!O=71P=73O`@!@!/$# +M;V)J96-T+7-T>6QE(&%P<')OR`,`H`4"^@#@=&\@:&%V92!M=6QT:7`E``.E +M`P(!!`!;!E4@;W!E;IX`L2`@8G-D=&%R('5SO`$`/06#;B!I=',@(D#E`!(B +MR`-&P"`*`'`2L`,VEN("8<``J,!!H`%,7=A;H@`$'0V!`5%`0!@ +M`!!IA0(`C@%EB!$!G&%)`$!S.B!3,@-4`0-)`#!C;VY#`O`".B`@5F%R:6]UP``7P%V875T:&]R,&`4D!A69I9W5R92`M#``"1`"U'2(`")P==8-(")C-`81(B0#`#@, +M*6]L30`"5@$&ZP,!*0$`%@D`C@$/;0$!`*(&('5SW0H`V@$T90HGL``C92>M +M``,D!`"3``!.`/``+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C%P$``@`0+:(" +M`)\`!*@``-D."*($$BP:#@#7"P)\`#%M86GV`2-EPH"MP(29:`,`!(&0'-E<77J"!!S"P4!/@$`=0``%P(`^00!<0`! +M<0H(EP``/`DS>2XS30``[P0R92`B:P,%JP`!)``4(@L+62!C;&%S1``!'PE& +M;F%L"`"X +M!!,B!0XR+F@BJ0`R:&4*7PP0(+`)`/H``!0`!.D&`W((`G\"-&UO5$P`P%&!E+``-J`0`9`[$J(%!/4TE8('5S=+`1!!``#XH,`P%\``(Q`%9O8W1E=*\4 +M`&`"`1X`H5-64C0@05-#24ET`@$4``\R``L00FT1$7DN`+$@*&)I9RUE;F1I +M8=018VQI='1L91$``OH`!%\6D4-$+5)/32!I;;<"$"@X#C`@;W#+`\!A;"!2 +M;V-KC2H`0#E%PD(`0``"@*<$`5+`0!U!`\&`0("@P$#OP,"O`(/'P,8 +M,")R9:`-`!`6$2)'`P)/`,(L('=H:6-H('=I;&SK&`!P"`###P-?`4!S(&5X +M+10``@(`N04$B1$""Q<#6A1X`<&QI8G)AP#S"2P@ +M:6YC;'5D:6YG(&AA``"/ +M`/0:("=D;V,G(&1I2!I;@IA(&YU;6)E6]U(#\!8"X*"D-UFEP,A8`!'P!32],6E<=`*)L>FUA+"!L>FEP$P,O +M>'HC```9-!0`"0@!E6-A;B!C,H"4B`H9F]R-`0`A`$#,P0`]`-Q +M+"!E=&,I+F\!`/H#`*D"!B($`1<``MH`#Y8#!0'(`V$B;F5W8R*;`P$S`"=S +M:+```1(`#T8#8P0%!`);`0&)``]9`P`*%@,S5VAE`P(`V`(#U`(2<^8%87)E +M'!L86EN:6YGR0`P:&]W^``"I@<`K0$#+``"*@$A +M3VX4"1PL`P$#^``!B`E086QW87E&`0#=`2IE9(H(`D<`L$DG=F4@871T96UP +MC`?@=&\@;6EN:6UI>F4@D`!RT`!"T'`,\*%&_Y"'`I+"!I="!W<`""(&=E="!P=6S["@"D!#<@26YN +M`#``B;`")E;LD!!RT``'P`"W$`*&1E$0`#Q@(1+/```H``(FYEC@(` +M%@$`0`!B86=A:6YS1P*18V]R0`P&@`A!MV`$38!(71O(@`%H0!A="!O;F-EA0`A3VZ0`QMEPP`"Y`(R<')O.@$!A0%1 +M8W1L>2W,``"."5)U='!U=.\"`&`$\0-O8FIE8W0M4X.475S92`B(0$` +M6@@@+")0"'`L(&-A<&%B00`!]@($`P$%\0!A92!!4$ESMP0(]@4!EP&`(&EN +M9&EV:61L#@/;"`"%``(5!@!"``!R"P#1```V`2%T;ZP-,&1A=-<```4.%CHN +M`0+("0`]`!)A[`(`R0H!*P`S:6X@)P$`E0LS861DC@(88?<,`=<'`QX/469I +M60!`,P``*,!!H`%,7=A;G\%$G0=#P$V`@%;`P!C +M#``S`$%D:7-K+`,`L1`0#B)A;N@"`*4'`!$# +M`EH'$"QC`$!D97-PH@``;`0!Y`,`7,N"E)%041-11(&!GX1X2!B +M=6YD;&4N"@I1=65S^@*@/R`@27-S=65S/U(`UBH@:'1T<#HO+W=W=RXX`$`N +M;W)GDP``2`$0:+@"$&:Q#S-N9V]8!Q<@3`>`(&1E=F5L;W`\!0@9$02Z$0&L +M"`$W#`!Q```Z`"%N:UT!`%T`!G,`4"!M86EL!P(P;&ESOQ`!G0`05)D!`.41 +M`.%E8$ +M(&YDT`(Q9G5L+P(&10`0+T,*`84!$6&>"C1A8W1[$W!D96UO;G-T.14@;F<^ +M``"`!094`@-)`#!C;VY#`F$Z("!687+N$V!I=&5M$0(8`&!C;VYF:6>R%A4M#``"1`"UM`Q$SM@L`$!20(&]V97)V:65W\P(`JP`%P`L`<04P +M=VAOD0(4*J0*A5]R96%D+C,L$``!^`@-$0!17V1I2T`5RH@8V%T:0`K871H +M`&ES:6UP;&6U`$!T;V]L,P$`0``#`@!R>F-A="P@8@<`$G@'``!)`4!S=6-H +M)P!0*B!E>&%)`-1S.B!3;VUE('-M86QL%0`$/@$`O@'P`&%T('EO=2!M87D@ +M9FEN9-`",69U;"\"!D4`42]M:6YIA0$18>,!46%C="!S8`"A(&1E;6]N4$` +M(&EN^``(M@)P:6YF;W)M8:D!,"!F:34!`'P`\`LJ($Y%5U,@+2!H:6=H;&EG +M:'1S(&]F(')E8P8"5&-H86YGH`*T0T]064E.1R`M('=1`6)C86X@9&^?`#-T +M:&DI`/("24Y35$%,3"`M(&EN%#36%K94QI\`!,G +MK0`#)`0`DP``3@#U`2YA;2P@86-L;V-A;"YM-"SA`$!E+F%C_P```@`2+50` +M)'1OJ``,H@2R+"!O;FQY(&YE961\`#%M86GV`2-E7-T96TZ"B`J(+@$=2XQ(&5X<&R#`@,O`P!" +M`0(A``2:`P,S``"(!`\T``L`(@`,-0`O870T``PH870S``8!!H`N,R!G:79E +M2XS30`" +M]P,2(FL#!:L``20`4"(@=71II`59(&-L87-$``'O!49N86QSG0`P`D09BP``;<&42H@1TY5=0$" +M-0(B("BK"0"Y`0`:`$%L;VYG4`9B;F%M97,L$`!3;&EN:R`1``!C`%)S<&%R +M'1E;J+ +M``-J`0`9`]$J(%!/4TE8('5S=&%R6P`"$``R<&%X-`,"60<#>`('(0"P;V-T +M970M;W)I96X!`P!@`@$>`*%35E(T($%30TE)=`(!%``"4P`/,@`%84)I;F%R +M>2X`P"`H8FEG+65N9&EA;J(!8VQI='1L91$``OH`\0))4T\Y-C8P($-$+5)/ +M32!I;;<"$2AX""!O<,L#P&%L(%)O8VMR:61G944`8DIO;&EE="D!`>\!`DD` +M-%I)4%8#!$``('5N,0LPFEP +M,A8`!'P!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9-!0`"0@!```*56-R +M96%TSP`!=00/!@$"`JH#`[\#`KP"#Q\#&#`B&-E<$`%`+D%!&D"42!T:&%T0PXQ:7)E +M40`!\P,!R@(@("@6!0$T!`"$`0,S!`#T`V`L(&5T8REF"@+Z`P"I`@8B!`&& +M`0+:``^6`P4!R`-A(FYE=V,BFP,!,P`GD#`*4#(71EVPAA.@H*("H@+1`0 +M:2`*<&AE879I;'G\"#9E86VU!0(1"W`N("!4:&5R-!$S(&YOX@<`@@(#WP@` +MDP1!(&EN+;D``2<0`BT`",T`%&_Y"'`I+"!I="!W<`!!(&=E=!D3`5T*`*0$-R!);FX` +M-RP@:9X``5$!`YL`(F5NR0$'+0``?``+<0`H9&41``/&`A$L\``"@```C0X` +ME@$`%@$`0``P86=A+@X!\0F18V]RP,B:67-#P%O +M`P/G"B!D=1D-`)\#$'.%`2-O9H@!`(X2$"UV```S#`#W"!%IM`\`A`!R96YV +M:7)O;@\+$7>0`P&@`A!MV`$3<3`<0-0&)A8VNO$S%F2W,`))E9"!O=71P=73O`@!@!/$#;V)J96-T+7-T>6QE(&%P<')OR`,`^10" +M^@#0=&\@:&%V92!M=6QT:<,3!*D``@$$`+D(52!O<&5NG@`3(!40`&H0``H! +M$6DA"&-I=',@(D`\`!(BO0012!F4X.``P1$2(A`0!:""`L(E`(H"P@ +M8V%P86)I;&D2%`8#`07Q``+S#P$_#@CV!0&7`8`@:6YD:79I9&P.`]L(`(4` +M`#H2`D(``*P+`-$``#8!(71OK`TP9&%TUP``!0X6.BX!`L@)`#T`$F'L`@#) +M"@$K`#-I;B`G`0!%!3-A9&2.`AAA]PP!J0H#'@]19FER3``!(`1!HN`(`5P!#;VYG;U@'%R!,!R`@9%@6(&]P/`4(&1$$NA$! +MK`@!-PP`<0``.@`@;FLT`0'!``9S`$$@;6%IVQ(`^QD"H`,!_1D@7,@9&5T96-T960@ +M875T;VUA=&EC86QL>4<`L$DG=F4@871T96UP(@#P(71O(&UI;FEM:7IE('-T +M871I8R!L:6YK('!O;&QU=&EO;BX@($EF('EO=2!D;VXG=*@``+8`\"1I8VET +M;'D@:6YV;VME(&$@<&%R=&EC=6QA!E('-O;64@=71I;&ET>3X`!8P``+$!\09P +M2!D8737`%9UP",B!O9BL`,VEN("X`0!V``*4`0```P&^``7+`0#3``.C`0:`!3%W86Z(`!!T-@0#-@(! +M6P,`'P$`N@!!9&ES:RP#`\0!N6-O;G9E;FEE;F-EP`$`B0`P;6%K>0"0:7,@ +M97-P96-I;@0!T`$"J@'S!TYO=&4Z(")P87@@:6YT97)C:&%N9V6?!1,BN0(@ +M;&P\`0+H`A!DO@$`_04!C080+&,`0&1E0(1.FH`$B>7!9`G('!R;V=R86T6`G-A(&9U;&PME@AP9"`G=&%R +M)WX``P(`4W)E<&QA0@%`8G5I;($&`(H``V,``"H`9BH@8W!I;V,```X`"V0` +M(&1I:P4R96YT,`-#9F%C96H#`P(`,&5S`<``$D!`)()`"<`4"H@97AA20!`8$(&YDT`(Q9G5L+P(&10`0+T,*`84!$6$&"5%A8W0@`0-)`#!C;VY#`O`".B`@5F%R:6]UP``7P%Q875T:&]R +M<\`%`1\&`?("`DT'$`J(!E!T;W`M;`P$`W8%`#`'`4$`$&GD!@FV`B)I;M8$ +M`'$+`.L%!+T"\`).15=3("T@:&EG:&QI9VAT=&%R+C54`0CQ!$%A +M8F]U4P41]!9!I;@IA(&YU;6+R#!=FD0<$.P''"@I9;W4@`D09@82`;<&42H@1TY5=0$"-0(F("@$"P`: +M`"-L;[P%`*T+(G,L$```!0L3(!$``&,`4G-P87)S?`(A`*%35E(T($%30TE)=`(! +M%``/,@`+$$)M$1%Y+@"Q("AB:6`@@;W#+`\!A;"!2;V-K[`@0]`5HW+5II +M<"8`V$UI8W)OFEP/@$@ +M:6]/$WTJ(&)Z:7`R%@`$?`%-+TQ:5QT`HFQZ;6$L(&QZ:7`3`R]X>B,``!DT +M%``)"`$```H"G!`%.@$`=00/!@$"`J\!`[\#`KP"#Q\#&#`B\+`OH#`*D" +M`&@1`HT``9L!`MH`#\@#"F$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0%!`?. +M``]9`P`*%@,S5VAE`P(`OP@#U`(2<^8%87)E`3AN97>U`P#P!`#]`@.?`0![``&'"0$K%0)*#`,*`P`X"`!O$!1T +M[A("#`(A(&(W"0","@&/&`.X%`$,`!!A#`$"U!``:``".P`199P6`#T!(79E +M4,`4&EN9&5PJ@`E;G0B`0!$#0%Y&0!"!1)O;`T&L`L/9!K_________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_________________________________________________________V50 +M=',Z"B#V/NS(,!$``/$-("H@1TY5('1A'1E;F1E9&0`!#-!0TPS`&%/;&0@5C"!I;G1E"=M=')E92<]`5HW+5II +M<"8`V$UI8W)O2!A;'-O(&1E=&5C='--`&!H86YD;&4,`'!Y(&]F('1HW`%` +M;&QO=Y("X&)E9F]R92!E=F%L=6%T$@``(``#+P(1.M0`8'5U96YC;W$"`+8" +M`D,"`0H`$2"#`:)24$T@=W)A<'!E3@)%9WII<#X!,6EO;D0`76)Z:7`R%@`$ +M9`%-+TQ:5QT`HFQZ;6$L(&QZ:7`3`R]X>B,``!DT%``)"`&58V%N(&-R96%T +MSP!/&-E<'0"`D0*("`@:0+1('1H870@P`!S@`0=IL$`#4'$G.C`%0@;VYL>0H#0&UE;G2R +M``$>`P"F!`(K`#`@8F5``'%R96%D86)L``9!=W)I=`P`$&$,`0($`0!H``([ +M`$)E86-H/0$A=F5S`Q-Y0P!0:6YD97"J`")N='\`$'([!``$`#!T:6-"!21O +M;H$!!*X`\`!7:6MI(&5X<&QA:6YI;F>)`#!H;W?X``&S`Q!DE@4#+``"*@$A +M3VZJ`!PL`P$`!`0R;6%T<`!`;'=A>48!`-T!\@%E9"!A=71O;6%T:6-A;&QY +M1P"P22=V92!A='1E;7",!^!T;R!M:6YI;6EZ92!S="L``E((4'!O;&QUN`'A +M+B`@268@>6]U(&1O;B?L`0"V`/$":6-I=&QY(&EN=F]K92!A('#K`"!U;+T( +MH&5A='5R92`HD`!RT`!$4'`R("`ID!<"DL(&ET('=P`.`@ +M9V5T('!U;&QE9"!I;J0$-R!);FX`-RP@:9X``5$!`YL`(F5NR0$'+0``?``+ +M<0`H9&41``.J`!$L\``"@``B;F6.`@`6`0!``'%A9V%I;G-TSP&18V]RP,Q:65SPP`!;P,!;P=16QE(&%P<')OR`,`R0@"^@#@=&\@:&%V92!M=6QT +M:7`E``-3!`(!!`"Y"%4@;W!E;IX`4"`@8G-D(P2!F)M96UO +M7,"!8P``0`"\05R;W9I9&4@96%S>2UT;RUU0#`*8.T"!S87ES+@I214%$346[!@?H!N$@8G5N9&QE +M+@H*475E<_H"H#\@($ES7!1`GH@1`9W)A;18"&%)`$!S.B!3,@-4`0-)`#!C;VY#`O`".B`@5F%R:6]UP``7P%Q875T +M:&]R<\`%`1\&`?("`-(1$B[M#U!T;W`M;`P$`\4,`#`'`4$`$&GD!@FV`B)I +M;M8$`*0*`.L%!+T"\`).15=3("T@:&EG:&QI9VATT3`A@`8&-O;F9I9WX+%2T,``)$ +M`+5S8W)I<'0L('-E96<``"@%9&1E=&%I;,,$84--86ME3-0$,71X=(@`(G!U +MU@T@(F,T!A$B)`,`.`PI;VQ-``)6`0;K`P$I`0`6"0".`0]M`0$`L`P0=3T3 +M`=H!-&4*)[``(V4GK0``.@\P("H@DP``3@#P`"YA;2P@86-L;V-A;"YM-`D- +M`^T`,"YA8_\```(`$"VB`@"?``2H``#9#@BB!!(L&@X`UPL`60L0>PH"MP(`318A86R)!T!S97%U +MZ@@0=&%R+C54 +M`0CQ!`4^$A%SU@TQ<&]PY0\#G`$$>P`(2PE`:&%R9!8,`3`&`J@!`X42`(X! +M86UO9&5R;H\``.@!`+P'<"!V87)I86Y("0`B##!M86[X"Q%PK1]!;!I;@IA(&YU;6)E"`"X!!,BXP`R+F@BJ0`R:&4*7PP0 +M(+`)`/H``!0`!.D&`W((`G\"$&T:%P/[`$(N("!0B@FR;&5T('5S"FMN;W<0 +M`0&9!F!E`D09@82`;<&`H<8!JH+#V0:____________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________________________________________________]94%-O +M;64@(HLUAC01``#T)G-M86QL(&5X86UP;&4@<')O9W)A;7,@=&AA="!Y;W4@ +M;6%Y(&9I;F0@=7-E9G5L+@H@("`J,`#R!W,O;6EN:71A2!T:&ER9"!P87)T:65S +M.X,``P(`87!L96%S948``'L`\BET:&4@875T:&]R2!Q=65S +M=&EO;G,N"@I4:&4@=&]P+6QE=F5L(&1I4$`(&EN^`"`92!F;VQL +M;W>V`'!I;F9O'2(`#%P=70I`/D#(F-M86ME(B!B +M=6EL9"!T;V]L30`"5@$&-0$!*0$Q(&EN3`$/;0$!,&%R91`"$F3:`35E"B>\ +M`!,GK0`#9P$`DP``3@#U`2YA;2P@86-L;V-A;"YM-"SA`$!E+F%C_P```@`2 +M+50`)'1OJ```(`$P9&ES7P(0=4$!LBP@;VYL>2!N965D?``Q;6%I]@$C97)< +M`05P`"1I;F0`\@,N:"YI;@H)+2!T96UP;&%T97-G`!%B-`(!9@$39;4`8`H* +M1W5I9/,`DB!$;V-U;65N=($!`,4!,F%L;'4``/,!]0H@'!L@P(#+P,`0@$"(0`$F@,#,P!/8W!I;S0`"P`B``PU`"]A +M=#0`#"AA=#,`!ZT#\`0S(&=I=F5S(&%N(&]V97)V:65W\P(`H`#P`6QI8G)A +M`?$#+@H*66]U('-H +M;W5L9"!A;'-O(@(!3``Q8V]P=@8R8V]M6P%#:6X@(KT",BYH(JD`@&AE"G-O +M=7)C+P`19'4!`!0`!.D&!30'`"P%-&UO<$",&5C=)D#$635``,<`@7"!A!F+``!MP91*B!' +M3E5U`0*Z`28@*+D!`!H`06QO;F=5`F)N86UE'1E;J+``-J`0`9`]$J(%!/4TE8('5S=&%R6P`"$``P<&%X20,B97)9!P-X`@FEP,A8`!'P!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9-!0`"0@! +M```*56-R96%TSP`!=00/!@$"`JH#`[\#`KP"#Q\#&#`B&-E<$`%`+D%!&D"`A4,<7)E +M<75IP`#GP$`>P`! +MAPD!HP`"2@P#"@,`.`@`L@`Q=&AA+PD#*P`A(&(W"0!J"#%A8FP`!@","@$, +M``$L"P($`0!H``([`$)E86-H/0$A=F5S`Q-Y0P!0:6YD97"J`"5N="(!`!@) +M``\/$&-"!1)O;`T&-0I4(%=I:VE2##!I;F?)`#!H;W=1#P&S`Q=DE@H"*@$A +M3VX_"`#W#`)@!@,#`03-``%P`$!L=V%Y1@$`W0$J962*"`)'`'!))W9E(&%T +M+0T`C`<`P0^0:6YI;6EZ92!S#@T28U((07!O;&R4#5$N("!)9O4(4&1O;B=T +MJ`"097AP;&EC:71LV0EB=F]K92!A^@\18W\*,69E830+,"AS=2\!!?L*`*D` +M("!A00`!)Q`"+0`(S0`4;_D(<"DL(&ET('=P`'$@9V5T('!UG`T0:7H+1R`@ +M26YN`#``%1`0.;`")E;LD!!RT``#X`"W$`*&1E$0`#Q@(1+/```H`` +M`(T.`)8!`!8!`$``(&%G`PX"4`.18V]R0`P&@`A!MV`$32X'<70@82!T:6U7`W%O8!(71O(@`%2@!2="!O;F-\$B)/;AP."\,``N0",G!R +M;SH!`84!46-T;'DMS`"2960@;W5T<'5T[P(`8`3Q`V]B:F5C="US='EL92!A +M<'!R;\@#`$,2`OH`T'1O(&AA=F4@;75L=&EE$P2I``(!!`"Y"`#^#15NG@`3 +M(!40`&H0``H!`#T%@VX@:71S(")`/``2(KT$$7,P#@)C!098`&!I='-E;&93 +M`0!]!!`O=@1@=&5N('5S;P8`-PP!<@$R9G5N6!($DP$!=08`,@`U(&%NB`0" +M(Q-0;'D@9G)@``S0*%82!S;V-K +M970^`TEW:7-HN@0!)@\#60\`#B)A;N@"`*4'!C0*$"QC +M`$!D97-PWP``;`0!Y`,`7,N"B05$6:X#01Q%K0@8G5N9&QE+@H* +M41$6H#\@($ES71E(&%T(&$@=&EM90H@("!O2UB;&]C:V5D(&]U='!U +M="X*"B`J(%1H92!O8FIE8W0M'1E;G-I;VZ*``,<```J`#!E;&93 +M`5!R96%D+^8`EG1E;B!U2!B=69F97(@;W+!``!E``1R +M`3!A(',K`5%T+"!I9@(!8'=I2UT;RUU`@#1```V`:!T;R!A;GD@9&%T +MUP!6=7)C93HN`5%C`@&^``7+`0#3``.C`4,N("!) +MI`$A86Z(`!)T70`#10$`8``0:84"86\@9&ES:RP#`\0!N6-O;G9E;FEE;F-E +MP`$`B0`P;6%K>0#1:7,@97-P96-I86QL>=`!`JH!\P].;W1E.B`B<&%X(&EN +M=&5R8VAA;F=E(&9O7,N"E)%041-12X``$0$!&T!T6)U;F1L92X* +M"E%U97/Z`J`_("!)3``!( +M!!!HN`*P9F]R(&]N9V]I;F`<``$D!0'-U +M8V@G`%`J(&5X84D`0',Z(%,R`U1S;6%L;!4`!#X!`%(#(6%T(`8@;6'F!"!N +M9-`",69U;"\"!D4`42]M:6YIA0$18>,!46%C="!S8`"P(&1E;6]N0&";8"(FEN^`0B:6_A +M!@2]`O`"3D574R`M(&AI9VAL:6=H='-M``,D!`"3``!.`/4!+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_ +M```"`!`MH@(`GP`$J``,H@2R+"!O;FQY(&YE961\`#%M86GV`2-E'!L@P(#+P,`0@$"(0`$ +MF@,#,P``B`0/-``+`"(`##4`+V%T-``,*&%T,P`&`08A+C.V"Q!SWP:`;W9E +M"P!Q!3!W:&^1`A0JI`J%7W)E860N,RP0``'X"`T1`%%? +M9&ES:Q8``GX'`X(%`3X``QP``)D``7L*`K<"$F6@#`!;!!!SU`80;A$,`-8" +M`),``'4``!<"`/D$`7$``7$*")<``#P),WDN,TT``.\$,F4@(FL#!:L``20` +M%"(+"UD@8VQA``'<`%`D09BP``;<&42H@ +M1TY5=0$"-0(F("@$"P`:`$%L;VYG4`8`K0LB+``-J`0`9 +M`]$J(%!/4TE8('5S=&%R6P`"$``/B@P#!R$`P&]C=&5T+6]R:65N=!<$,7!I +M;QX`IE-64C0@05-#24D4``)3``\R``5A0FEN87)Y+@#`("AB:6B,``!DT%``)"`$```H"G!`%.@$`=00/!@$"`J\!`[\# +M`KP"#Q\#&,$B&-E<$`%`+D%!(D142!T:&%T0PX`TQ,`40`%Z1(P?P(-F5A;;4%`A$+!8@4 +M0&ES(&[6$C%R96,P$0/?"`"3!$$@:6XM`@^"(&UO9&EF:6/E#/<`;W(@`3AN97>U`P#P!`#]`@.? +M`0![``&'"0$K%0)*#`!-$2)IE(7`+4(`E((07!O;&PV$@;D%$%D;VXG[`&0 +M97AP;&EC:71LV0EB=F]K92!A^@\18W\*`\X1("`HTA``=0P('`(08;(!`2<0 +M`BT`",T`%&]S!'`I+"!I="!W<`!0(&=E="#2$@%="@"D!#<@26YN``4F%P&> +M``%1`0.;`")E;LD!!RT``'P`"W$`*&1E$0`#J@`1+%@1`H```(T.`)8!`!8! +M`$``,&%G8?,/`5\*D6-O"(&5N=FER;VX/ +M"T!W:&5R+Q9`870@;=@!$W):`P4P`@!;``)_`!%Y>P,1<#4`8F%T979EFUA+"!L>FEP+"!A +M;F0@>'HC```9-!0`]0<*5&AE(&QI8G)A"!I;G1E&-E<'0@9F]J`/$'("!E;G1R:65S('1H870@ +M.`?$#;F%M97,L($%#3',L +M(&5T8RDND@"P3VQD($=.52!T87)=``2I``+*`/$$;V-T970M;W)I96YT960@ +M8W!I;S4`ME-64C0@(FYE=V,B%0`G +M`'@G;71R964GNP!X25-/.38V,!,`6C2!S=')E86WM`>!S>7-T96TN("!4:&5R92P`\01N;R!D:7)E +M8W0*("`@`>-R86YD +M;VT@86-C97-S+GD`!I<`\@)I'!L86EN:6YGB0`P:&]W^``"]0``C@0#+``"*@$A3VZJ`!PL`P$# +MV0("<`!`;'=A>48!`-T!\@%E9"!A=71O;6%T:6-A;&QY1P"P22=V92!A='1E +M;7#$`^!T;R!M:6YI;6EZ92!S="L`L"!L:6YK('!O;&QUN`'A+B`@268@>6]U +M(&1O;B?L`0"V`/$":6-I=&QY(&EN=F]K92!A('#K`"!U;#<$(&5A60)`("AS +M=2\!&7,<`A!AZ0`'+0`'[P4`@`$"F0%P*2P@:70@=W``X"!G970@<'5L;&5D +M(&ENI`0W($EN;@`W+"!IG@`!40$#FP`B96[)`07L#$7`U`-%A=&5V97(@8FQO8VMS\``0:%<%(6ETH0!!66]U2X'<70@82!T:6U7`W%O +M8!(71O(@`%H0!A="!O;F-EA0`A +M3VZ0`QMEPP`"Y`(R<')O.@$!A0%18W1L>2W,``!(!E)U='!U=.\"`&`$\0-O +M8FIE8W0M2!F)M96UO?<"!8P``0`"\05R;W9I9&4@96%S>2UT;RUU8<``J,!!H`%,7=A;H@`$'0V!`5%`0!@``'Z +M"0".!R%S:RP#`WX&N6-O;G9E;FEE;F-EP`$`B0`P;6%K>0"0:7,@97-P96-I +M;@0!T`$"J@$`.@@P.B`BDPH.NPH3(KD"(&QL/`$"Z`(`I0<`$0,"P040+&,` +M0&1EP`"-E)ZT``V2XS30``[P0R92`B +M:P,%JP`!)``4(@L+62!C;&%S1``!'PE&;F%L``'?`5=H+`#L'`2,) +M"=H1`,$",&5C=)D#$61A#0,<`@>F%@`@`@!0!0)!%0:J"R8@*`0+`%L5#"`6 +M`1````4+`;X+$G,W`E)S<&%R\6`2T5`A``#XH,`P%V,/"Q<`T$UI8W)O2!N965D +M960@8GD@;6%I;G1A:6YE7-T96TZ"B`J(&)S9'1A@`/`#;&EB +M2!A2XS30`"=`%U +M(G-T2!C;&%S1`"6:6YT97)N86QSG0!@2!E2QN``5H`W!U=&]M871I_P(0>68!,&5C=)D#$635``,<`E!O;&QO=Y,!$&8L +M`#!S.@K?!#!'3E7X`0#``%9M870@*+D!`!H`06QO;F=5`F)N86UE$D#<65R8VAA;F=^`3=M870A`+!O8W1E="UOFEP/@$Q:6]N!0%=8GII<#(6``1\`4TO3%I7'0"B +M;'IM82P@;'II,H"("`H?0;#`*F!P>6"@(J`2%/;C\(`/<,`G@&`0(*(VYD +M^``!B`EC86QW87ESF4@``B;`")E +M;LD!!RT``'P`"W$`*&1E$0`#Q@(1+/```H```(T.`)8!`!8!`$``(&%G`PX" +M1P*18V]RP,1<#4`T6%T979E2W,`))E9"!O +M=71P=73O`@!@!/$#;V)J96-T+7-T>6QE(&%P<')OR`,`R0@"^@#0=&\@:&%V +M92!M=6QT:3$,!*D``@$$`+D(52!O<&5NG@`3(!40``80``H!`#T%@VX@:71S +M(")`/``2(KT$$7,P#@)C!098`&!I='-E;&93`0!]!!`O=@1@=&5N('5S;P8% +M<@%`9G5N8Z4*`C0"`"$-(F-A!00U(&%NB`0"9@U0;'D@9G)@``S0*%82!S;V-K970^`TEW:7-HN@0!)@\#60\` +M4X.475S92`B(0$`6@@@+")0"+$L(&-A<&%B:6QI +M=/8"!`,!!?$``O,/`;<$"/8%`9P"`,D*`2L`,VEN +M("#U%F:7)S=)("`*8!$6%P$A%O61$`]@`6 +M+G0``]D#`J60!`,P` +M`*,!!H`%,7=A;G\%$G0=#P$V`@%;`P$:!!!TC@0#`',*T2!S +M87ES+@I214%$3442!@9)$>$@8G5N9&QE+@H*475E<_H"H#\@($ES+%1`GD1(`\A$` +M%@)S82!F=6QL+98(!L30',Z(%,R`U1S;6%L;!4` +M!#X!`%(#(6%T'`@@;6'F!"!N9-`",69U;"\"!D4`$"]#"@&%`1%AH0LT86-T +M>Q-P9&5M;VYS=#D5(&YG/@``@`4&5`(#20`P8V]N!1AA.B`@5F%R[A-@:71E +M;7,@,P$`UP(@;64.&%)T:&ER9,\),&5S.\@``P(``^H"`$8``'L``%\!<6%U +M=&AOP`"-E)Z\9`R0$ +M`),``$X`CRYA;2P@86-L9!K_____________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_____________________________VI086YY(&1:8C!),!$``/`<871A('-O +M=7)C93H@(%EO=2!C86X@8W)E871E"B`@(&$@8FQO8VL@;V8@9"L`\!YI;B!M +M96UO8<`\01S +M;V-K970N("!)9B!Y;W4@=V%NB``2=%T`$B\]``!@`#!I97,S`%!D:7-K+$X` +M\`QR92!A2!E87-Y+@H*("H@3F]T93H@(G!A>"!I;G1E'1E;F1E9#@!`B(`$"QC`$!D97-PWP!`=VAA +M=)8`\`,@;F%M92!S87ES+@I214%$3450`$0@;&EB;0'18G5N9&QE+@H*475E +M`<``$D!0'-U8V@G`%`J(&5X84D`0',Z(%,R`U1S;6%L;!4`!#X!`%(#(6%T +M?`0@;6'F!"!N9-`",69U;"\"!D4`42]M:6YIA0$18>,!46%C="!S8`"A(&1E +M;6]NM``,D!`"3``!.`/4!+F%M+"!A +M8VQO8V%L+FTT+.$`0&4N86/_```"`!`MH@(`GP`$J``,H@2R+"!O;FQY(&YE +M961\`#%M86GV`2-E7-T96TZ<`<"N`1U +M+C$@97AP;(,"`R\#`$(!`B$`!)H#`S,``(@$#S0`"P`B``PU`"]A=#0`#"AA +M=#,`!@$&@"XS(&=I=F5SWP:`;W9EP$2+8($-7,N-:H(`)X%$67[`P#R`(!M871S('-U<'\(!&," +M!98!`$P```H"D"XU+"!M=')E90D``&\`7G1A`D09BP``;<&42H@1TY5=0$"-0(F("@$ +M"P`:`$%L;VYG50(`K0LB+``-J`0`9`]$J(%!/4TE8('5S +M=&%R6P`"$``/B@P#!R$`P&]C=&5T+6]R:65N=!<$,7!I;QX`IE-64C0@05-# +M24D4``)3``\R``5A0FEN87)Y+@#`("AB:6FEP,A8`!'P!32],6E<=`*)L>FUA+"!L>FEP$P,O +M>'HC```9-!0`"0@!```*`IP0!3H!`'4$#P8!`@*O`0._`P*\`@\?`Q@P(G)E +MH`U18W1E9")'`P)/`,,L('=H:6-H('=I;&PF$0)U`P:0`%%E>&-E<$`%`+D% +M`?P(-F5A;;4%`A$+<"X@(%1H97(T$2`@;M82 +M,7)E8S`1`]\(`),$02!I;BVW#X(@;6]D:69I8^4,\@%OP`!APD!HP`"2@P`31$B:7*"$1!I>0<#[A("#`(A(&(W"0","C%A +M8FP`!@","@$,``$L"P+4$`!H``([`$)E86-H/0$A=F5S`Q-Y0P!0:6YD97"J +M`"5N="(!`$0-``\/$&-"!1)O;`T&-0I4(%=I:VE2#`,,$S!H;W?X``&S`Q!D +MK0$#V@`"*@$A3VX_"`#W#`)@!@#S#@!0!@/-``%P`%-L=V%Y'!L:6-I#16":6YV;VME(&'Z#Q%C?PH#SA$@("C2$"4@8?L* +M`*$!("!AL@$!)Q`"+0`(S0`4;W,$<"DL(&ET('=P`%`@9V5T(-(2`5T*`*0$ +M-R!);FX`,BP@:8(5`9X``5$!`YL`(F5NR0$'+0``?``+<0`H9&41``/&`A$L +MY0D"@```C0X`E@$`%@$`0``P86=A\P\!7PJ18V]R"(&5N=FER;VX/"Q%WD`,!H`(0;=@!$W):`P4P`@!;``)_`!%Y +M>P,1<#4`8F%T979E:89`@4.#V0:________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________________________]@4"`@*B!)&=+.F401``#Q$5-/.38V,"!F +M;W)M870*("`J(#2!O +M9B<`H69O;&QO=VEN9SI@`(%U=65N8V]D90T`\0%G>FEP(&-O;7!R97-S:6]N +M%0!=8GII<#(6``0F`$TO3%I7'0#Y`VQZ;6$L(&QZ:7`L(&%N9"!X>B,`P0I. +M;W1E7-T96TN("!4:&5R92P`@&YO +M(&1IF4@2!I;G9O:V4@82!PZP"` +M=6QA2!F +MP`28D(``"P$`-$``#8!(71O +M>`0#\`)N86UE('-A>7,N"E)%041-15``!^@&X2!B=6YD;&4N"@I1=65S^@*@ +M/R`@27-S=65S/U(`URH@:'1T<#HO+W=W=RX@!S!O3``!(`1!HN`*#9F]R +M(&]N9V]8!Q@@9`!P9&5V96QO<#P%<2P@:6YC;'6]!4!D;V-U%``!K`@!3@D` +M<0``.@`A;FM=`0!=``9S`%`@;6%I;`<"0FQIF-A="P@8@<`$G@'``!)`0"2"0`G`%`J(&5X84D`0',Z(%,R`U1S;6%L;!4` +M!#X!`%(#(6%T'`@@;6'F!"!N9-`",69U;"\"!D4`$"]#"@&%`1%AG@I186-T +M('-@`)(@9&5M;VYS=')*#0`I!B=O9EX!`TD`,&-O;D,"\`(Z("!687)I;W5S +M(&ET96US(#,!`'T#0&UE(&(W`3)I0&";8" +M(FENU@0`Q@P`ZP4$O0+P`DY%5U,@+2!H:6=H;&EG:'1S7`8PP`"-E)ZT``R0$`),``$X`\``N86TL(&%C;&]C86PN;30) +M#0/M`#`N86,7`0`"`!`MH@(`GP`$J```V0X(H@02+!H.`-<+`GP`,6UA:?8! +M(V5RK@$%<``D:6YD`($N:"YI;@H)+?0'(&QA5@\$NP`%A0`#M0!@"@I'=6ED +M\P`H($14!@32`0)U``&W`0)3#Q`Z&@D"N`0A+C'!#`!A#`$W`0,O`P`+``(A +M``2:`P,S``"(!`\T``L`(@`,-0`O870T``PH870S``8!!B$N,[8+$'-E"H!O +M=F5R=FEE=_,"`*``!<`+`'$%4'=H;VQEI``#1`6$7W)E860N,RRT"A%?^`@- +M$0!17V1IH($',+ +M!0$^`0!U```7`@#Y!`%Q``%Q"@B7```\"3-Y+C--``#O!#)E(")K`P6K``$D +M`!0B"PM9(&-L87-$``$?"49N86QSG0`2!Q(M@@0U=&%R+C54`0CQ!`4^ +M$A%S8P0Q<&]PY0\#G`$$>P`(2PE`:&%R9!8,`3`&!%L!`4<``(X!86UO9&5R +M;H\``.@!`+P'<"!V87)I86Y("0":!3!M86[X"T%P86=E.```,0XD +M``'?`5=H+`#L'`2,)"=H1`,$" +M,&5C=)D#$61A#0,<`@2#%"`@9@82`;<&42H@1TY5=0$"-0(F("@$"P`:`"!L +M;R\`,&EL9:T+(G,L$```!0L3(!$``&,`4G-P87)S?`(A`*%35E(T($%30TE)=`(!%``/,@`+ +M$$)M$1%Y+@"Q("AB:6\!`DD` +M-%I)4'4$!$``('5N,0L`)18`UA!@C2H`0#E%PD(`0``"@*<$`5+`0!U +M!`\&`0("KP$#OP,"O`(/'P,8,")R9:`-`!`6$2)'`P)/`,(L('=H:6-H('=I +M;&SK&`!P"`###P-?`4!S(&5X+10``@(`N04$B1$""Q<#6A1X`<&QI8G)AP#S"2P@:6YC;'5D:6YG +M(&AA``"/`/0:("=D;V,G +M(&1I2!I;@IA(&YU;6)E6]U(#\!8"X*"D-U\!`DD` +M-%I)4%8#!$``P'5N8V]M<')EC`@0]`5HW+5II<"8`V$UI +M8W)O`,( +MKP)@:&%N9&QENP(0>;<#`=0$!;@",&)E9DH#<&5V86QU873*`@`@``.9`P+/ +M`D!U=65ND`,19+8"`D,"`!4%(7,@@P&B4E!-('=R87!P94X"16=Z:7`^`3%I +M;VX8`5UB>FEP,A8`!'P!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9-!0` +M"0@!E6-A;B!C,H"4B`H9F]R-`0`A`$#,P0`]`-Q+"!E=&,I+F\! +M`/H#`*D"!B($`1<``MH`#Y8#!0'(`V$B;F5W8R*;`P$S`"=S:+```1(`#T8# +M8P0%!`);`0&)``]9`P`*%@,S5VAE`P(`V`(#U`(2<^8%87)E'!L86EN:6YGR0`P:&]W^``"I@<`K0$#+``"*@$A3VX4"1PL`P$# +M^``!B`E086QW87E&`0#=`2IE9(H(`D<`L$DG=F4@871T96UPC`?@=&\@;6EN +M:6UI>F4@D`!RT`!"T' +M`,\*%&_Y"'`I+"!I="!W<`""(&=E="!P=6S["@"D!#<@26YN`#``B; +M`")E;LD!!RT``'P`"W$`*&1E$0`#Q@(1+/```H``(FYEC@(`%@$`0`!B86=A +M:6YS1P*18V]R0 +M`P&@`A!MV`$38!(71O +M(@`%H0!A="!O;F-EA0`A3VZ0`QMEPP`"Y`(R<')O.@$!A0%18W1L>2W,``". +M"5)U='!U=.\"`&`$\0-O8FIE8W0M7,"!8P``#\`!)4.0&5AP"`,D*`2L`,VEN("#U%F:7)S=)("`*8! +M(&$@0P41;U`'`/8`%BYT``/9`P*G`0"_``*<`0&%``:X`0!V``##``"\`Q)E +MDP`",0\@;'ED`0#,``"C`0:`!3%W86Y_!1)T'0\!-@(!6P,`8PP`,P!!9&ES +M:RP#`+$0$'*?!)EN=F5N:65N8V7``0")`#!M86MY`)!I0#`',*T2!S87ES+@I214%$3442!@9^$>$@8G5N9&QE+@H* +M475E<_H"H#\@($ES1$@#R$0`6`G-A(&9U;&PME@AR9"`G=&%R +M)P\!`0(`(7)EK0H!0@%`8G5I;($&`(H``V,``"H``J(3!F,``,$0"V0`!M,2 +M`3`#,&9A8RH'`#T``P(``"D0(FYT:`,`$0(V!L30',Z(%,R`U1S;6%L;!4`!#X!`%(#(6%T'`@@;6'F!"!N9-`",69U +M;"\"!D4`$"]#"@&%`1%AG@HT86-T>Q-P9&5M;VYS=#D5(&YG/@``@`4&5`(# +M20`P8V]N0P)A.B`@5F%R[A-@:71E;7,@,P$`UP(B;64V%3)I'2(`"%P=6<0,"`B8S0&$2(D`P`X#"EO;$T``E8!!NL#`2D! +M`!8)`(X!#VT!`0`@#1!U/1,"$!P`"-E)ZT``R0$`),``$X`\``N86TL +M(&%C;&]C86PN;30)#0/M`#`N86/_```"`!`M9`(`GP`$J```V0X(H@02+!H. +M`-<+`%D+$'G*!0'V`2-E!,"(0`$F@,#,P``B`0/-``+`"(`##4`+V%T-``, +M*&%T,P`'K0,1,[8+`!`4D"!O=F5R=FEE=_,"`*L`!<`+`'$%,'=H;Y$"%"JD +M"H5?H(`N47`),``'4``!<"`/D$`7$``7$*")<``9P) +M("XSHQ2!F;W(@:L`D'-A;64@ +M9G5N8S`<``$D!0'-U8V@G`%`J(&5X84D`U',Z(%-O;64@ +M6]U(&UA>2!F:6YD('5S969U;"\"!D4`42]M +M:6YIA0$18>,!46%C="!S8`"A(&1E;6]N2#R`I!I;VYS +M+@H*5&B=`?("<"UL979E;"!D:7)E8W1O%#36%K94QI +M\`!,GK0`#)`0`DP``3@#U`2YA;2P@ +M86-L;V-A;"YM-"SA`$!E+F%C_P```@`2+50`)'1OJ``,H@2R+"!O;FQY(&YE +M961\`#%M86GV`2-E7-T96TZ"B`J(+@$=2XQ(&5X<&R#`@,O`P!"`0(A``2:`P,S``"(!`\T``L` +M(@`,-0`O870T``PH870S``8!!H`N,R!G:79E2XS30`"]P,2(FL#!:L``20`4"(@=71I +MI`59(&-L87-$``'O!49N86QSG0`P`D09BP``;<&42H@1TY5=0$"-0(B("BK"0"Y`0`:`$%L;VYG +M4`9B;F%M97,L$`!3;&EN:R`1``!C`%)S<&%R'1E;J+``-J`0`9`]$J(%!/4TE8('5S +M=&%R6P`"$``R<&%X-`,"60<#>`('(0"P;V-T970M;W)I96X!`P!@`@$>`*%3 +M5E(T($%30TE)=`(!%``"4P`/,@`%84)I;F%R>2X`P"`H8FEG+65N9&EA;J(! +M8VQI='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I;;<"$2AX""!O<,L#P&%L +M(%)O8VMR:61G944`8DIO;&EE="D!`>\!`DD`-%I)4%8#!$``('5N,0LPFEP,A8`!'P!32],6E<=`*)L>FUA +M+"!L>FEP$P,O>'HC```9-!0`"0@!```*56-R96%TSP`!=00/!@$"`JH#`[\# +M`KP"#Q\#&#`B&-E<$`%`+D%!&D"42!T:&%T0PXQ:7)E40`!\P,!R@(@("@6!0$T!`"$ +M`0,S!`#T`V`L(&5T8REF"@+Z`P"I`@8B!`&&`0+:``^6`P4!R`-A(FYE=V,B +MFP,!,P`GD#`*4#(71EVPAA.@H*("H@+1`0:2`*<&AE879I;'G\"#9E86VU +M!0(1"X`N("!4:&5R9;T/(VYOX@<`@@(#WP@`DP1!(&EN+;D``2<0`BT`",T`%&_Y"'`I +M+"!I="!W<`!!(&=E=!D3`5T*`*0$-R!);FX`-RP@:9X``5$!`YL`(F5NR0$' +M+0``?``+<0`H9&41``/&`A$L\``"@```C0X`E@$`%@$`0``@86<##A%T\0F1 +M8V]RP,B:67-#P%O`P/G"B!D=1D-`)\#$'.%`2-O +M9H@!`(X2$"UV```S#`#W"!%IM`\`A`!R96YV:7)O;@\+$7>0`P&@`A!MV`$3 +M<3`<0-0&)A8VOR`S%F2W,`))E9"!O=71P=73O`@!@ +M!/$#;V)J96-T+7-T>6QE(&%P<')OR`,`^10"^@#0=&\@:&%V92!M=6QT:<,3 +M!*D``@$$`+D(52!O<&5NG@`3(!40`&H0``H!$6DA"&-I=',@(D`\`!(BO001 +M2!F4X.``P1$2(A`0!:""`L(E`(H"P@8V%P86)I;&D2%`8#`07Q``+S +M#P$_#@CV!0&7`8`@:6YD:79I9&P.`]L(`(4``#H2`D(``*P+`-$``#8!(71O +MK`TP9&%TUP``!0X6.BX!`L@)`#T`$F'L`@#)"@$K`#-I;B`G`0!%!3-A9&2. +M`AAA]PP!J0H#'@]19FER41`.7,@9&5T96-T960@875T;VUA=&EC86QL>4<`X$DG=F4@ +M871T96UP=&5D<`"P;6EN:6UI>F4@6]U(&1O;B=T"B`@(&5X<&QI8VET;'D@:6YV;VME(&$@<&%R=&EC=6QA +M``B;`%IE +M;F%B;)L``#X`"W$`*&1E$0`#J@`1+/```H``(FYE)@$`%@$`0`#Y"F%G86EN +M8`0U:`)%L:6)R87)I97/#`/$"5&AI717`G`@82!T:6UEI0!Q;W(@ +M;6UA<-H`0&5N=&F?`@+0`@&V`D!G:79EY@$A=&\B``5*`&%T(&]N8V6%`(M/ +M;B!W`+$@(&)S9'1A2!D8737`%9UP",B!O9BL`,VEN +M("X`0!V``*4`0"A`P&^``7+ +M`0#3``.C`0:`!3%W86Z(`!!T-@0#-@(!6P,`'P$`N@!!9&ES:RP#`\0!N6-O +M;G9E;FEE;F-EP`$`B0`P;6%K>0"0:7,@97-P96-I;@0!T`$"J@'S!TYO=&4Z +M(")P87@@:6YT97)C:&%N9V6?!1,BN0(@;&P\`0+H`A!DO@$`_04!C080+&,` +M0&1E0(1.FH`$B>7!1`GH@1` +M9W)A;18"&%)`$!S +M.B!3,@-40&";8"(FENU@0`<0L`ZP4$O0+P`DY%5U,@+2!H:6=H +M;&EG:'1S7`8P=&%R+C54`0CQ!$%A8F]U4P41]!9!I;@IA +M(&YU;6+R#!=FD0<$.P''"@I9;W4@`D0 +M9@82`;<&42H@1TY5=0$"-0(F("@$"P`:`"-L;[P%`*T+(G,L$```!0L3(!$` +M`&,`4G-P87)S?`(A`*%35E(T($%30TE)=`(!%``/,@`+$$)M$1%Y+@"Q("AB:6`@@ +M;W#+`\!A;"!2;V-K[`@0]`5HW+5II<"8`V$UI8W)OFEP/@$@:6]/$WTJ(&)Z:7`R%@`$?`%-+TQ: +M5QT`HFQZ;6$L(&QZ:7`3`R]X>B,``!DT%``)"`$```H"G!`%.@$`=00/!@$" +M`J\!`[\#`KP"#Q\#&#`B\+`OH#`*D"`&@1`HT``9L!`MH`#\@#"F$B;F5W +M8R*;`P$S`"=S:+```1(`#T8#8P0%!`?.``]9`P`*%@,S5VAE`P(`OP@#U`(2 +M<^8%87)E`3AN97>U`P#P!`#]`@.? +M`0![``&'"0$K%0)*#`,*`P`X"`!O$!1T[A("#`(A(&(W"0","@&/&`.X%`$, +M`!!A#`$"U!``:``".P`199P6`#T!(79E4,`4&EN9&5PJ@`E;G0B`0!$ +M#0%Y&0!"!1)O;`T&L`M4(%=I:VE2#`,,$S!H;W=1#P&S`Q!DK0$#V@`"]Q,% +M-!@$_`0`\PX`4`8#S0`!<``"@!<"Q`4/9!K_________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_________________________________________QY0=61I;F?\MV+.+A$` +M`/(%($=.52!L;VYG(&9I;&5N86UE'1E;F1E9"!T87(@9F]R;6%T("AI;F-L +M=61I;F<@04-,,P!A3VQD(%8W)P"!87)C:&EV97-+`+=03U-)6"!U2!O9B!T:-P!0&QL;WFEP,A8`!&0!32],6E<=`*)L>FUA+"!L>FEP +M$P,O>'HC```9-!0`"0@!E6-A;B!C0`&EP"0:7,@9&5S:6=NH@9";R!B98@%`$`$`3`$.&YE=[4#`*,$`'L``4,`4&EN +M9&5PJ@`B;G1_`!!R.P0`!``P=&EC0@4D;VZ!`02N`/``5VEK:2!E>'!L86EN +M:6YGB0`P:&]W^``!LP,09)8%`RP``BH!(4]NJ@`<+`,!``0$,FUA='``0&QW +M87E&`0#=`?(!960@875T;VUA=&EC86QL>4<`L$DG=F4@871T96UPC`?@=&\@ +M;6EN:6UI>F4@2!I;G9O:V4@82!PZP`@=6Q9"*!E871U``%1`0.;`")E;LD!!RT``'P`"W$`*&1E$0`#J@`1+/```H``(FYE +MC@(`%@$`0`!Q86=A:6YS=,\!D6-OP,1<#4` +MT6%T979E +M`%`@(&)S9",'(75SO`$`/06#;B!I=',@(D#E`!(BO01&"2`L(E`(<"P@8V%P86)!``'V`@)F!A%E50(! +M\0!A92!!4$ESMP0(]@4!EP&Q(&EN9&EV:61U86QH!1%I0@@`>P`28D(``$X& +M`-$``#8!(71OFPDP9&%TUP!6=7)C93HN`0+("0#"`!)A[`(`R0H!*P`S:6X@ +M)P$`.`LS861DC@(88?<,`=<'(6]U]P119FER0"0:7,@97-P96-I;@0!T`$"J@$`.@@P.B`BDPH. +MV@T3(KD"(&QL/`$"Z`(`I0<`$0,"P040+&,`0&1E%EF-%#A)B!P`2>`<``$D!`)()`"<`4"H@ +M97AA20!`8$(&YDT`(Q9G5L +M+P(&10`0+T,*`84!$6&>"E%A8W0@'2(`")P==8-(")C-`81(B0#`#@,*6]L30`" +M5@$&ZP,!*0$`%@D`C@$/;0$!`+`,$'4]$P':`31E"B>P`"-E)ZT``#H/,"`J +M(),``$X`\``N86TL(&%C;&]C86PN;30)#0/M`#`N86/_```"`!`MH@(`GP`$ +MJ```V0X(H@02+!H.`-<+`%D+$'G*!0'V`2-EH($',+!0$^`0!U```7`@#Y!`%Q +M``%Q"@B7```\"3!Y+C/T%#!A:6SO!#)E(")K`P6K``$D`!0B"PM9(&-L87-$ +M``$?"49N86QSG0`2!Q(M@@0U=H+`#L'`2,)"=H1`,$"!;47`/<"`QP"!7@) +M$&8&$@&W!@*'&`:J"P@`&@#X%0]D&O______________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________95!T:&%T(&%96PM!$0``\2AY +M;W4@;6%Y(&9I;F0@=7-E9G5L+@H@("`J(&5X86UP;&5S+VUI;FET87(Z(&$@ +M8V]M<&%C="!S&P#@(&1E;6]NP#R*71H92!A=71H;W)S('=I=&@@ +M86YY('%U97-T:6]N'2(`#%P=70I +M`/D#(F-M86ME(B!B=6EL9"!T;V]L30`"5@$&-0$!*0$Q(&EN3`$/;0$!,&%R +M91`"$F3:`35E"B>\`!,GK0`#9P$`DP``3@#U`2YA;2P@86-L;V-A;"YM-"SA +M`$!E+F%C_P```@`2+50`)'1OJ```(`$P9&ES7P(0=4$!LBP@;VYL>2!N965D +M?``Q;6%I]@$C97)<`05P`"1I;F0`\@,N:"YI;@H)+2!T96UP;&%T97-G`!%B +M-`(!9@$39;4`8`H*1W5I9/,`DB!$;V-U;65N=($!`,4!,F%L;'4``/,!]0H@ +M'!L@P(#+P,`0@$"(0"#('!R;V=R86TS +M`$]C<&EO-``+`"(`##4`+V%T-``,*&%T,P`'K0/P!#,@9VEV97,@86X@;W9E +M2!A``"/`&<@)V1O8R>]!;!I;@IA(&YU;6)E2QN``5H`S!U=&^3!@#_`A!YP0(P96-TF0,19-4` +M`QP"!<(&$&8L``&W!E$J($=.574!`KH!)B`HN0$`&@!!;&]N9U4"8FYA;65S +M+!``4VQI;FL@$0``8P!A`@@;W#+`\!A;"!2;V-K +MB,``!DT%``)"`$```I58W)E873/``%U!`\&`0("J@,#OP,"O`(/ +M'P,8,")R9?X(46-T960B1P,"3P#$+"!W:&EC:"!W:6QLB@`!5@`%R@%A(&5X +M8V5P0`4`N04$:0+1('1H870@U`P#P!`![``.?`0![``&'"0&C``)*#`,*`P`X"`"R``$>`P"F!`(, +M`B$@8C<)`&H(,6%B;``&`(P*`0P``2P+`@0!`&@``CL`0F5A8V@]`2%V97,# +M$WE#`%!I;F1E<*H`)6YT(@$`&`D`#P\08T(%$F]L#08U"E0@5VEK:5(,,&EN +M9\D`,&AO=U$/`;,#%V26"@(J`2%/;C\(`/<,`F`&`P,!`_@``8@)4&%L=V%Y +M1@$`W0$J962*"`)'`'!))W9E(&%T+0T`C`<`P0^0:6YI;6EZ92!S#@T28U(( +M07!O;&R4#5$N("!)9O4(4&1O;B=TJ`"097AP;&EC:71LV0EB=F]K92!A^@\1 +M8W\*,69E830+,"AS=2\!!?L*`*D`("!A00`!)Q`"+0`(S0`4;_D(<"DL(&ET +M('=P`'$@9V5T('!UG`T0:7H+1R`@26YN`#``%1`0.;`")E;LD!!RT` +M`#X`"W$`*&1E$0`#Q@(1+/```H```(T.`)8!`!8!`$``(&%G`PX"4`.18V]R +M0`P&@`A!M +MV`$32X'<70@ +M82!T:6U7`W%O8!(71O(@`%2@!2 +M="!O;F-\$B)/;AP."\,``N0",G!R;SH!`84!46-T;'DMS`"2960@;W5T<'5T +M[P(`8`3Q`V]B:F5C="US='EL92!A<'!R;\@#`$,2`OH`X'1O(&AA=F4@;75L +M=&EP)0``(040=A(#0')E86VY"`#^#15NG@`3(!40`&H0``H!`#T%@VX@:71S +M(")`Y0`2(KT$$7,P#@)C!08!`6!I='-E;&93`0!]!!`O=@1@=&5N('5S;P8` +M-PP!<@$R9G5N6!($DP$!=08`,@`U(&%NI``"(Q-0;'D@9G)@``S0*%82!S;V-K970^`TEW:7-HN@0!)@\#60\` +M#B)A;N@"`*4'!C0*$"QC`$!D97-PWP``;`0!Y`,`7,N"B05$6:X#01Q%K0@8G5N9&QE+@H*41$6H#\@($ES2UB;&]C:V5D(&]U='!U="X*"B`J(%1H92!O8FIE8W0M`@#1```V`:!T;R!A;GD@9&%TUP!6=7)C93HN`5%CB!$!G8$(&YDT`(Q9G5L+P(&10!1+VUI;FF% +M`1%AXP%186-T('-@`+`@9&5M;VYS=')A=+P`"-E)ZT``R0$`),``$X` +M]0$N86TL(&%C;&]C86PN;30LX0!`92YA8_\```(`$"VB`@"?``2H``RB!+(L +M(&]N;'D@;F5E9'P`,6UA:?8!(V5RK@$%<``D:6YD`($N:"YI;@H)+?0'4FQA +M=&5S9P`18C0"`W(!`K4`8`H*1W5I9/,`*"!$5`8$T@$"=0``\P&`('-Y'!L@P(#+P,`0@$"(0`$F@,#,P``B`0/-``+`"(`##4` +M+V%T-``,*&%T,P`&`08A+C.V"Q!SWP:`;W9E``'<`%`D09BP``;<&42H@1TY5=0$"-0(F("@$"P`:`$%L +M;VYG50(`K0LB+``-J`0`9`]$J(%!/4TE8('5S=&%R6P`" +M$``/B@P#!R$`P&]C=&5T+6]R:65N=!<$('!IZ`S&*B!35E(T($%30TE)%``" +M4P`/,@`%84)I;F%R>2X`P"`H8FEG+65N9&EA;J(!8VQI='1L91$``OH`\0)) +M4T\Y-C8P($-$+5)/32!I;;<"$2AX""!O<,L#P&%L(%)O8VMR:61G944`8DIO +M;&EE="D!`>\!`DD`-%I)4'4$!$``('5N3@DPFEP,A8`!'P!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9 +M-!0`"0@!```*`IP0!3H!`'4$#P8!`@*O`0._`P*\`@\?`Q@P(G)EH`U18W1E +M9")'`P)/`,0L('=H:6-H('=I;&R*``%6``:0`%%E>&-E<$`%`+D%!(D142!T +M:&%T0PX`TQ,`40`%Z1(P?P(-F5A;;4%`A$+!8@40&ES(&[6$C%R96,P$0/?"`"3 +M!$$@:6XM`@^"(&UO9&EF:6/E#/<`;W(@'!L:6-I=&S9"6)V;VME(&'Z +M#Q%C?PH#SA$@("C2$`!U#`@<`A!AL@$!)Q`"+0`(S0`4;W,$<"DL(&ET('=P +M`%`@9V5T(-(2`5T*`*0$-R!);FX`!287`9X``5$!`YL`(F5NR0$'+0``?``+ +M<0`H9&41``.J`!$L6!$"@```C0X`E@$`%@$`0``P86=A\P\!7PJ18V]R7L#$7`U`&)A=&5V97)X%Q%S\```[@FEP(&-O;7!R97-S:6]N%0!=8GII<#(6``0F`$TO3%I7 +M'0#_`VQZ;6$L(&QZ:7`L(&%N9"!X>B,``!DT%`#P#`I4:&4@;&EB2!C +M86X@8W)E871E(&%R8\\`\A)S(&EN(&%N>2!O9B!T:&4@9F]L;&]W:6YG(&9O +M&-E +M<'1_`/$*"B`@("!E;G1R:65S('1H870@.`?$#;F%M97,L($%#3',L(&5T8RDND@"P3VQD($=.52!T87)= +M``2I``+*`/$$;V-T970M;W)I96YT960@8W!I;S4`ME-64C0@(FYE=V,B%0`G +M`'@G;71R964GNP!X25-/.38V,!,` +M6CT!X'-Y +M`>-R86YD;VT@86-C97-S+GD`!I<`\@)I'!L86EN:6YGB0`P:&]W^``" +M]0``C@0#+``"*@$A3VZJ`!PL`P$#V0("<`!`;'=A>48!`-T!\@%E9"!A=71O +M;6%T:6-A;&QY1P"P22=V92!A='1E;7#$`^!T;R!M:6YI;6EZ92!S="L`L"!L +M:6YK('!O;&QUN`'A+B`@268@>6]U(&1O;B?L`0"V`/$":6-I=&QY(&EN=F]K +M92!A('#K`"!U;#<$(&5A60)`("AS=2\!&7,<`A!AZ0`'+0`'[P4`@`$"F0%P +M*2P@:70@=W``X"!G970@<'5L;&5D(&ENI`0W($EN;@`W+"!IG@`!40$#FP`B +M96[)`07L#$7`U`-%A=&5V97(@8FQO +M8VMS\``0:%<%(6ETH0!!66]U2X'<70@82!T:6U7`W%O8!(71O(@`%H0!A="!O;F-EA0`A3VZ0`QMEPP`"Y`(R<')O.@$!A0%18W1L +M>2W,``!(!E)U='!U=.\"`&`$\0-O8FIE8W0M2!F)M96UO?<"!8P``0`"\05R;W9I9&4@96%S>2UT +M;RUU8<``J,! +M!H`%,7=A;H@`$'0V!`5%`0!@``'Z"0".!R%S:RP#`WX&N6-O;G9E;FEE;F-E +MP`$`B0`P;6%K>0"0:7,@97-P96-I;@0!T`$"J@$`.@@P.B`BDPH.NPH3(KD" +M(&QL/`$"Z`(`I0<`$0,"P040+&,`0&1EP`"-E)ZT``V2XS30``[P0R92`B:P,%JP`!)``4(@L+62!C;&%S1``!'PE& +M;F%L``'?`5=H+`#L'`2,)"=H1`,$",&5C=)D#$61A#0,<`@>F%@`@ +M`@!0!0)!%0:J"R8@*`0+`%L5#"`6`1````4+`;X+$G,W`E)S<&%R\6`2T5 +M`A``#XH,`P%V,/"Q<`T$UI8W)O`"" +M(&EN'!L86EN3`1!F+``P +M'1E;J+``-J`0`9`]$J(%!/4TE8('5S=&%R6P`"$``P<&%X20-Q97)C +M:&%N9WX!-VUA="$`L&]C=&5T+6]R:65N`0,`8`(!'@"A4U92-"!!4T-)270" +M`10``E,`#S(`!6%":6YAFEP,A8`!'P!32],6E<=`*)L>FUA+"!L +M>FEP$P,O>'HC```9-!0`"0@!E6-A;B!C0`&@`0`#@Q397-I9VXE#!)EO@(`0`0! +M,`0X;F5WM0,`\`0`>P`#GP$`>P`!APD!HP`"2@P#"@,`.`@`L@`!'@,`I@0" +M#`(A(&(W"7%R96%D86)L``8`C`H!#``!+`L"!`$`:``".P!"96%C:#T!(79E +M4,`4&EN9&5PJ@`E;G0B`0`8"5!AD`!RT`!"T'`,\*%&_Y"'`I+"!I="!W<`!Q +M(&=E="!P=9P-(&ENI`0W($EN;@`W+"!IG@`(FP`B96[)`02UV +M```S#`#W"!%IAP8`A`!P96YV:7)O;M<",7,@=Y`#`:`"$&W8`1-R6@,%,`(` +M6P`"?P`1>7L#$7`U`-%A=&5V97(@8FQO8VMS\```[@@``S0*%82!S;V-K970^`TEW:7-HN@0!)@\#60\`4X.475S92`B(0$`6@@@+")0"+$L(&-A<&%B:6QI=/8"!`,!!?$``O,/`;<$ +M"/8%`9P"`,D*`2L`,VEN("#U%F:7)S=)("`*8!(&$@0P41;UD1`/8`%BYT``/9`P*G`0"_``*< +M`0&%``:X`0!V``##``"\`Q)EDP`",0\@;'ED`0#,``"C`0:`!3%W86Y_!1)T +M'0\!-@(!6P,!&@00=(X'(7-K+`,0A$)P`$`B0`P;6%K +M>0"0:7,@97-P96-I;@0!T`$"J@$`.@@P.B`BDPH!#A$)V@T3(KD"`-X.(F%N +MZ`(`I0<&-`H0+&,`0&1EF-%#A)B!P`2>`<` +M`$D!`)()`"<`02H@97@;$T!S.B!3,@-4^&G/#D1 +M``#P=2`@(&$@8FQO8VL@;V8@9&%T82!I;B!M96UO2!F:6QE+B`@66]U(&-A;B!A;'-O(')E860@86X@96YT6]U('=A;G1$`!)T70`2+ST``&``,&EE'1E;F1E9#@!`B(`$"QC`$!D97-PWP!`=VAA=)8`\`,@ +M;F%M92!S87ES+@I214%$3450`$0@;&EB;0'18G5N9&QE+@H*475E`<``$D! +M0'-U8V@G`%`J(&5X84D`0',Z(%,R`U1S;6%L;!4`!#X!`%(#(6%T?`0@;6'F +M!"!N9-`",69U;"\"!D4`42]M:6YIA0$18>,!46%C="!S8`"P(&1E;6]N2#R`@`!!5`N"@I4:)T!,'`M;`P$`W8%``D&`4$`$&DD!0FV`B)I +M;M8$,6EO;NL%!+T"\`).15=3("T@:&EG:&QI9VAT'2(`#!P=71>`C`@(F,T!A$B)`-I9"!T;V]L30`"5@$&ZP,!*0$`90<`C@$/ +M;0$!`*(&0G5S963:`35E"B>\`!,GK0`#)`0`DP``3@#U`2YA;2P@86-L;V-A +M;"YM-"SA`$!E+F%C_P```@`0+:("`)\`!*@`#*($LBP@;VYL>2!N965D?``Q +M;6%I]@$C97*N`05P`"1I;F0`@2YH+FEN"@DM]`=2;&%T97-G`!%B-`(!9@$3 +M9;4`8`H*1W5I9/,`*"!$5`8$T@$"=0`!MP%P!1%E^P,`\@"`;6%T]!;!I;@IA(&YU;6)E2X`P"`H8FEG+65N9&EA;J(!8VQI='1L91$``OH` +M\0))4T\Y-C8P($-$+5)/32!I;;<"$"@X#C`@;W#+`\!A;"!2;V-KFEP/@$Q:6]N!0%=8GII<#(6``1\`4TO3%I7'0"B;'IM82P@;'II4,` +M4&EN9&5PJ@`E;G0B`0!$#0`/#Q!C0@42;VP-!C4*5"!7:6MI4@P##!,P:&]W +M^``!LP,09*T!`]H``BH!(4]N/P@`]PP"8`8`\PX`4`8#S0`!<`!3;'=A>7-S +M""IE9(H(`D<`<$DG=F4@870M#0",!S!T;R`A$'!M:7IE('-TM0@"4@A!<&]L +M;#82!N04061O;B?L`7!E>'!L:6-I#16":6YV;VME(&'Z#Q%C?PH#SA$@("C2 +M$"4@8?L*`*$!("!AL@$!)Q`"+0`(S0`4;W,$<"DL(&ET('=P`%`@9V5T(-(2 +M`5T*`*0$-R!);FX`,BP@:8(5`9X``5$!`YL`(F5NR0$'+0``?``+<0`H9&41 +M``/&`A$LY0D"@```C0X`E@$`%@$`0``P86=A\P\!7PJ18V]R"(&5N=FER;VX/"Q%WD`,!H`(0;=@!$W):`P4P`@!; +M``)_`!%Y>P,1<#4`8F%T979E:89`@4.%CHN`0+("0`]``]D&O______________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________9U`@87)C +M:+!C1.Q"$0``\0)I=F5S"B`@*B!805(@87)C:!$`Y0I7:&5N(&-R96%T:6YG +M&`#Q&2P@=&AE(')EFUA+"!L>FEP+"!A;F0@>'HC`,$*3F]T +M97,@86)O=724`')L:6)R87)YT0#P+G1E8W1U2!S=')E86TM;W)I96YT960@P`#MP$`>P!";6%T2!R97%U:7)E;65N +M=+(`,G1H80D!`BL`("!BCP&0(')E861A8FQEH@!!=W)I=`P`$&$,`0($`0!H +M``([`$)E86-H/0&#=F4@96YT$N("!)9B!Y;W4@9&]N)^P!`+8`\0)I8VET;'D@:6YV;VME(&$@<.L`@'5L +M87(@9F5A60)`("AS=2\!&7,<`A!AZ0`'+0`'!@,`@`$"F0%P*2P@:70@=W`` +M\``@9V5T('!U;&QE9"!I;BX^`"=);FX`-RP@:9X``5$!`YL`(F5NR0$'+0`` +M/@`+<0`H9&41``/&`A$L\``"@``B;F6.`@`6`0!``&)A9V%I;G-'`J!C;W)R +M97-P;VYD)P0(20`-6@`">P,Q:65SPP`!;P.P86QS;R!R961U8V6;`C!E('.% +M`2-O9H@!`+,!$"UV`&%E9"!B:6X]`"`@:2P$@"!E;G9IP,1<#4`T6%T979E8!(71O +M(@`%2@!A="!O;F-EA0`A3VZ0`QMEPP`"Y`(R<')O.@$!A0%18W1L>2W,`))E +M9"!O=71P=73O`@!@!/$#;V)J96-T+7-T>6QE(&%P<')OR`,`H`4"^@#@=&\@ +M:&%V92!M=6QT:7`E``-3!`(!!``B!E4@;W!E;IX`L2`@8G-D=&%R('5SO`$` +M/06#;B!I=',@(D#E`!(BR`-&P"`*`'`2L`,VEN("8<``J,!!H`% +M,7=A;H@`$'0V!`5%`0!@`!!IA0(`C@%EB!$!G&%)`$!S.B!3,@-4`0-)`#!C;VY#`O`".B`@5F%R:6]UP``7P%V +M875T:&]R,&`4D!A69I9W5R92`M#``" +M1`"U'2(`")P +M==8-(")C-`81(B0#`#@,*6]L30`"5@$&ZP,!*0$`%@D`C@$/;0$!`*(&('5S +MW0H`V@$T90HGL``C92>M``,D!`"3``!.`/``+F%M+"!A8VQO8V%L+FTT"0T# +M[0`P+F%C%P$``@`0+:("`)\`!*@``-D."*($$BP:#@#7"P)\`#%M86GV`2-E +MPH"MP(29:`,`!(&0'-E<77J"!!S"P4! +M/@$`=0``%P(`^00!<0`!<0H(EP``/`DS>2XS30``[P0R92`B:P,%JP`!)``4 +M(@L+62!C;&%S1``!'PE&;F%L]!9!I;@IA(&YU;6+R#!=FD0<$.P''"@I9;W4@2X`L2`H8FEG+65N9&EAU!%C;&ET=&QE$0`"^@#Q`DE33SDV-C`@0T0M +M4D]-(&EMMP(0*#@.,"!O<,L#P&%L(%)O8VMR:61G9>\! +M`DD`-%I)4'4$!$``('5N,0L`)18`UA!@"T4``("`+D%!(D1`@L7`UH7 +M`5$`!>D2,',@*%,*`30$`(0!`S,$`/0#8"P@971C*>\+`OH#`*D"`&T``HT` +M`9L!`MH`#\@#"F$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0%!`?.``]9`P`* +M%@,/9!K_____________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_____________U-0("!I;G0:SA?#3!$``/,[97)N86P@4P`T&-P:6\N +M-2P@;71R964)``!O`/(*=&%R+C4@<')O=FED92!D971A:6QE9"!I;E(`D&EO +M;B!A8F]U=$T`XW-E"B`@('!O<'5L87(@F``2("D`\PIS+"!I;F-L=61I;F<@ +M:&%R9"UT;RUF:6YD5``2FEP/@$Q +M:6]N,`!=8GII<#(6``1\`4TO3%I7'0"B;'IM82P@;'II&-E<$`%`+D%!&D" +ML"!T:&%T(')E<75IE@4G87C*`E(@*&9O?P(-F5A;;4%X'-Y`3AN97>U`P#P!`![``-S!`![``&'"0&C`%0@;VYL>0H#`#@(`+(``1X# +M`*8$`@P"(2!B-PEQ4,`4&EN9&5PJ@`E;G0B`0`8"5!A48!`-T!*F5DB@@"1P"P22=V92!A='1E;7",!^!T;R!M +M:6YI;6EZ92!S=+4(`E((4'!O;&QU(@=1+B`@26;U"%!D;VXG=*@``+8`4&EC +M:71LV0F!=F]K92!A('#K``%_"C%F96$T"S`H +M``%1`0.;`")E;LD!!RT``'P`"W$`*&1E$0`#Q@(1+/```H``(FYEC@(`%@$` +M0`!B86=A:6YS1P*18V]R0`P&@`A!MV`$38!(71O(@`%H0!A="!O;F-EA0`A3VZ0`QMEPP`"Y`(R<')O.@$!A0%18W1L +M>2W,``"."5)U='!U=.\"`&`$\0-O8FIE8W0M7,"!8P``#\`!)4.0&5AP"`,D*`2L`,VEN("#U%F:7)S +M=)("`*8!(&$@0P41;U`'`/8`%BYT``/9`P*G`0"_``*<`0&%``:X`0!V``## +M``"\`Q)EDP`",0\@;'ED`0#,``"C`0:`!3%W86Y_!1)T'0\!-@(!6P,`8PP` +M,P!!9&ES:RP#`+$0$'*?!)EN=F5N:65N8V7``0")`#!M86MY`)!I0#`',*T2!S87ES+@I214%$3442!@<4!]%B=6YD;&4N +M"@I1=65S^@*@/R`@27-S=65S/U(`UBH@:'1T<#HO+W=W=RXX`$`N;W)GDP`` +M2`$0:+@"$&:Q#S-N9V]8!Q<@3`>`(&1E=F5L;W`\!0@9$02Z$0&L"`$W#`!Q +M```Z`"%N:UT!`%T`!G,`4"!M86EL!P(P;&ESOQ`!G0`05)D!`.41`.%E8$(&YDT`(Q +M9G5L+P(&10`0+T,*`84!$6&>"C1A8W1[$W!D96UO;G-T.14@;F<^``"`!094 +M`@-)`#!C;VY#`F$Z("!687+N$V!I=&5M +M$0(8`&!C;VYF:6>R%A4M#``"1`"UM`Q$SM@L`$!20(&]V97)V:65W\P(`JP`%P`L`<04P=VAOD0(4 +M*J0*A5]R96%D+C,L$``!^`@-$0!17V1I2!F;W(@:L`D'-A;64@ +M9G5N8S`<``$D!0'-U8V@G`%`J(&5X84D`U',Z(%-O;64@ +M6]U(&UA>2!F:6YD('5S969U;"\"!D4`42]M +M:6YIA0$18>,!46%C="!S8`"A(&1E;6]N2#R`I!I;VYS +M+@H*5&B=`?("<"UL979E;"!D:7)E8W1O%#36%K94QI +M\`!,GK0`#)`0`DP``3@#U`2YA;2P@ +M86-L;V-A;"YM-"SA`$!E+F%C_P```@`2+50`)'1OJ``,H@2R+"!O;FQY(&YE +M961\`#%M86GV`2-E7-T96TZ"B`J(+@$=2XQ(&5X<&R#`@,O`P!"`0(A``2:`P,S``"(!`\T``L` +M(@`,-0`O870T``PH870S``;V!8`N,R!G:79E2XS30`"]P,2(FL#!:L``20`4"(@=71I +MI`59(&-L87-$``'O!49N86QSG0`P`D09BP``;<&42H@1TY5=0$"-0(B("BK"0"Y`0`:`$%L;VYG +M4`9B;F%M97,L$`!3;&EN:R`1``!C`%)S<&%R'1E;J+``-J`0`9`]$J(%!/4TE8('5S +M=&%R6P`"$``R<&%X-`,"60<#>`('(0"P;V-T970M;W)I96X!`P!@`@$>`*%3 +M5E(T($%30TE)=`(!%``"4P`/,@`%84)I;F%R>2X`P"`H8FEG+65N9&EA;J(! +M8VQI='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I;;<"$2AX""!O<,L#P&%L +M(%)O8VMR:61G944`8DIO;&EE="D!`>\!`DD`-%I)4%8#!$``('5N,0LPFEP,A8`!'P!32],6E<=`*)L>FUA +M+"!L>FEP$P,O>'HC```9-!0`"0@!```*56-R96%TSP`!=00/!@$"`JH#`[\# +M`KP"#Q\#&#`B&-E<$`%`+D%!&D"42!T:&%T0PXQ:7)E40`!\P,!R@(@("@6!0$T!`"$ +M`0,S!`#T`V`L(&5T8REF"@+Z`P"I`@8B!`&&`0+:``^6`P4!R`-A(FYE=V,B +MFP,!,P`GD#`*4#(71EVP@P.@H*N!`R:&ESD0]P:&5A=FEL>?P(-F5A;;4% +M`A$+@"X@(%1H97)E+``C;F_B!P""`@/?"`"3!$$@:6XMMP^"(&UO9&EF:6-D +M"_``;W(@0`&EP``L!!397-I9VXE#!)EB`4`0`0! +M7@$X;F5WM0,`\`0`>P`#GP$`>P`!APD!HP`"2@P`31$B:7*"$1!I>0<280D! +M`@P"(2!B-PD`C`HQ86)L``8`_0H!#``!+`L"U!``:``".P!"96%C:#T!(79E +M4,`4&EN9&5PJ@`E;G0B`0`8"0`/#Q!C0@42;VP-!C4*5"!7:6MI4@PP +M:6YGR0`P:&]W40\!LP,09$X(`]H``BH!(4]N/P@`]PP"8`8`TQ$`4`8#S0`! +M<`!3;'=A>7-S""IE9(H(`D<`<$DG=F4@870M#0",!S!T;R`A$+)M:7IE('-T +M871I8U((07!O;&PV$E$N("!)9O4(061O;B?G$I!E>'!L:6-I=&S9"4!V;VME +MO!(!ZP`!?PH#SA$@("C2$"4@8?L*`*$!("!AZ0`!)Q`"+0`(S0`4;_D(<"DL +M(&ET('=P`$$@9V5T&1,!70H`I`0W($EN;@`W+"!IG@`!40$#FP`B96[)`07L#$7`U`-%A=&5V97(@8FQO8VMS\```[@2X'<70@82!T:6U7 +M`W%O8!(71O(@`%2@``XQ,A8V6% +M`"%/;I`#&V7#``+D`C)P`!,@%1``:A``"@$`/06#;B!I=',@(D`\`!(BO001 +M2!F4X.``P1$2(A`0!:""`L(E`(H"P@8V%P86)I;&D2%`8#`07Q``+S +M#P$_#@CV!0&7`8`@:6YD:79I9&P.`]L(`(4``#H2`D(``*P+`-$``#8!(71O +MK`TP9&%TUP``!0X6.BX!`L@)`#T`$F'L`@#)"@$K`#-I;B`G`0!%!3-A9&2. +M`AAA]PP!J0H#'@]19FER41`.7,@9&5T96-T960@875T;VUA=&EC86QL>2X*"B`J($DG=F4@871T96UP=&5D +M('1O(&UI;FEM:7IE('-T871I8R!L:6YK('!O;&QU=&EO;BX@($EF('EO=2!D +M;VXG=`H@("!E>'!L:6-I=&QY(&EN=F]K92!A('!A``B;`%IE;F%B;)L` +M`#X`"W$`*&1E$0`#J@`1+/```H``(FYE)@$`%@$`0`#Y"F%G86EN8`0U:`)%L:6)R87)I97/#`/$"5&AI2W,`))E9"!O=71P=70&`>!4:&4@;V)J +M96-T+7-T>1`"TG!P`+$@(&)S9'1A2!B=69F97(@;W+!``!E``1R`85A('-O8VME=#X#4'=I2UT;RUUX`0!V``*4`0```P&3 +M``7+`0#3``.C`0:`!3%W86Z(`!!T-@0#-@(!6P,`'P$`N@!!9&ES:RP#`\0! +MN6-O;G9E;FEE;F-EP`$`B0`P;6%K>0"0:7,@97-P96-I;@0!T`$"J@'S!TYO +M=&4Z(")P87@@:6YT97)C:&%N9V6?!1,BN0(@;&P\`0+H`A!DO@$48<$%$"QC +M`$!D97-PH@``;`0!!@3P`FYA;64@H&0&%N(&FW`!`L(00!_``!#P"A('1R86-K97(@8`<``$D!0'-U8V@G`%`J +M(&5X84D`0',Z(%,R`U1S;6%L;!4`!#X!`%(#(6%T'`@@;6'F!"!N9-`",69U +M;"\"!D4`$"]#"@&%`1%A!@E186-T('-@`+`@9&5M;VYS=')A=+P`"-E)ZT` +M`V7-T96TZ&@D"N`0A+C'!#`!A#`$W`0,O`P`+``(A``2:`P,S``"( +M!`\T``L`(@`,-0`O870T``PH870S``8!!B$N,[8+$'-E"H!O=F5R=FEE=_," +M`*``!0H,`'$%,'=H;Y$"%"JD"H5?PH"MP(29:`,`%L$$'/4!A!N2PT`U@(`DP``=0`` +M%P(`^00!<0`!<0H(EP`!G`DC+C--``#O!#)E(")K`P6K``$D`!0B"PM9(&-L +M87-$``$?"49N86QSG0`2P$2+8($-7,N-:H(`J\``!D#`)\#-6UA=&D/!&,"!98! +M`+````H"D"XU+"!M=')E90D``&\`7G1A]!9!I;@IA(&YU;6+R#!=FD0<#HP#7+@H*66]U('-H;W5L9*0+`"@!,6-O +M<'8&0&-O;6V>"`#.#1,BR0TR+F@BJ0`R:&4*7PP0(+`)`'4!`!0`!.D&`W(( +M`G\"-&UO\!`DD` +M-%I)4'4$!$``('5N,0L`[!,`UA!@"T4``("`+D%!(D1`FL4`$,.`-,3`%$`!>D2 +M,',@*'T'`30$`(0!`S,$`/0#8"P@971C*>\+`OH#`*D"`&@1`HT``9L!`MH` +M#\@#"F$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0%!`?.``]9`P`*%@,S5VAE +M`P(`OP@#U`(2<^8%87)E`3AN97>U +M`P#P!`#]`@.?`0![``&'"0$K%0)*#`,*`P`X"`#>`!1T[A("#`(A(&(W"0", +M"@&/&`.X%`$,`!!A#`$"U!``:``".P`199P6`#T!(79E4,`4&EN9&5P +MJ@`E;G0B`0!$#5!A'1E;F1E9"!T87(@9F]R;6%T("AI;F-L=61I;F<@04-, +M,P!A3VQD(%8W)P"!87)C:&EV97-+`+=03U-)6"!U"=M=')E92<]`5HW+5II<"8`V$UI8W)O2!A;'-O(&1E=&5C='--`&!H86YD +M;&4,`'!Y(&]F('1HW`'P!VQL;W=I;F<@8F5F;W)E(&5V86QU8702```@``,O +M`A$ZU`!@=75E;F-O<0(!CP(!%``!"@`1((,!HE)032!WFEP +M/@$Q:6]N,`!=8GII<#(6``1D`4TO3%I7'0"B;'IM82P@;'IIP`!S@`0 +M=IL$`-$&$G.C`%0@;VYL>0H#0&UE;G2R``$>`P"F!`(K`#`@8F5``'%R96%D +M86)L``9!=W)I=`P`$&$,`0($`0!H``([`$)E86-H/0$A=F5S`Q-Y0P!0:6YD +M97"J`")N='\`$'([!``$`#!T:6-"!21O;H$!!*X`\`!7:6MI(&5X<&QA:6YI +M;F>)`#!H;W?X``&S`Q!DE@4#+``"*@$A3VZJ`!PL`P$`!`0R;6%T<`!`;'=A +M>48!`-T!\@%E9"!A=71O;6%T:6-A;&QY1P"P22=V92!A='1E;7",!^!T;R!M +M:6YI;6EZ92!S="L`L"!L:6YK('!O;&QUN`'A+B`@268@>6]U(&1O;B?L`0"V +M`/$":6-I=&QY(&EN=F]K92!A('#K`"!U;%D(H&5A='5R92`HD`!RT`!$4'`R("`ID!<"DL(&ET('=P`.`@9V5T('!U;&QE9"!I;J0$-R!) +M;FX`-RP@:9X``5$!`YL`(F5NR0$'+0``?``+<0`H9&41``.J`!$L\``"@``B +M;F6.`@`6`0!``'%A9V%I;G-TSP&18V]RP,Q:65S +MPP`!;P,!;P=16QE +M(&%P<')OR`,`R0@"^@#@=&\@:&%V92!M=6QT:7`E``-3!`(!!`#\"E4@;W!E +M;IX`4"`@8G-D(P2!F)M96UO7,"!8P``0`"\05R;W9I +M9&4@96%S>2UT;RUU0#`',* +MT"!S87ES+@I214%$346[!@?H!N$@8G5N9&QE+@H*475E<_H"H#\@($ES7!1`GH@1`9W)A;18"&%)`$!S.B!3,@-4 +M`0-)`#!C;VY#`O`".B`@5F%R:6]UP``7P%Q875T:&]R<\`%`1\&`?("`-(1$B[M +M#U!T;W`M;`P$`\4,`#`'`4$`$&GD!@FV`B)I;M8$`*0*`.L%!+T"\`).15=3 +M("T@:&EG:&QI9VATPH"MP(`318A86R)!T!S97%UZ@@0=&%R+C54`0CQ!`4^$A%SU@TQ<&]PY0\# +MG`$$>P`(2PE`:&%R9!8,`3`&`J@!`X42`(X!86UO9&5R;H\``.@!`+P'<"!V +M87)I86Y("0`B##!M86[X"Q%PK1] +M!;!I;@IA(&YU;6)E"`"X!!,BXP`R+F@BJ0`R:&4*7PP0(+`)`/H``!0`!.D&`W((`G\" +M$&T:%P/[`$(N("!0B@FR;&5T('5S"FMN;W<0`0&9!F!E`D09@82`;<&`H<8!JH+"``:`/@5#"`6`1````4+#V0:________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________________________________________________]H4"`J(&5X +M7K0(.D01``#Q#&%M<&QEP#R*71H92!A=71H;W)S('=I=&@@86YY('%U97-T:6]N +M%#36%K94QIM``-G`0"3``!.`/4!+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_```"`!(M +M5``D=&^H```@`3!D:7-?`A!U00&R+"!O;FQY(&YE961\`#%M86GV`2-E7-T96TZ"B`J(&)S +M9'1AM`_`$,R!G:79E2XS!`,!JP(2(FL#!:L` +M`20`Z2(@=71I;&ET>2!C;&%S1`"6:6YT97)N86QSG0!@P$2+8($ +M4W,N-2!D5@(#I@0@:6QV`]1R;6%T-50!"/$$4&%B;W5T&@$@P"`+"!I;F-L=62*`<5H87)D+71O+69I;F1;`0%'``!!`&%M;V1E$D#(F5R60<# +M>`('(0"P;V-T970M;W)I96X!`P!@`@$>`*%35E(T($%30TE)=`(!%``"4P`/ +M,@`%,$)I;LH$`$(`H"`H8FEG+65N9&GS!(-R(&QI='1L91$``OH`\0))4T\Y +M-C8P($-$+5)/32!I;;<"$2AX""!O<,L#P&%L(%)O8VMR:61G944`8DIO;&EE +M="D!`>\!`DD`-%I)4%8#!$``('5N3@DPFEP/@$Q +M:6]N&`%=8GII<#(6``1\`4TO3%I7'0"B;'IM82P@;'IID#`*4#(71EVPC` +M.@H*("H@5&AI?P(-F5A;;4%`A$+@"X@(%1H97)E+``C +M;F_B!P""`@/?"`"3!/("(&EN+7!L86-E(&UO9&EF:6-D"_``;W(@0`&EP"3:7,@9&5S:6=N)0P298@%`$`$`;,%.&YE=[4#`/`$ +M`'L``Y\!`'L``8<)`:,``DH,`PH#`#@(`+(``1X#``D!`@P"(2!B-PD`:@@Q +M86)L``8`C`H!#``!+`L"!`$`:``".P!"96%C:#T!(79E4,`4&EN9&5P +MJ@`E;G0B`0`8"0`/#Q!C0@42;VP-!C4*5"!7:6MI4@PP:6YGR0!C:&]W('1O +M]0`'E@H"*@$A3VX_"`#W#`)@!@,#`0/X``&("5!A;'=A>48!`-T!*F5DB@@" +M1P!P22=V92!A="T-`(P'`,$/D&EN:6UI>F4@@M'("!);FX`-RP@:9X``5$!`YL`(F5NR0$'+0``/@`+<0`H9&41 +M``/&`A$L\``"@```C0X`E@$`%@$`0``@86<##@)'`I%C;W)R97-P;VY<"PA) +M``&]#P@1``)[`R)I92UV +M```S#`#W"!%IM`\`A`!P96YV:7)O;M<",7,@=Y`#`:`"$&W8`1-R6@,%,`(` +M6P`"?P`1>7L#$7`U`-%A=&5V97(@8FQO8VMS\```[@2W,`))E9"!O=71P=73O`@!@!/$#;V)J +M96-T+7-T>6QE(&%P<')OR`,`0Q("^@#@=&\@:&%V92!M=6QT:7`E```A!1!V +M$@-``!,@%1``:A``"@$`/06#;B!I=',@(D#E`!(BR`,1 +M2!F4X.``P1$2(A`0!:""`L(E`(H"P@8V%P86)I;&D2%`8#`0"_``'Q +M``+S#P&W!`CV!0&7`8`@:6YD:79I9&P.`]L(`(4``#H2`D(``*P+`-$``#8! +M(71OK`TP9&%TUP``!0X1.L$"`2X!`L@)`#T`$F'L`@#)"@$K`#-I;B`G`0"/ +M`C-A9&2.`AAA]PP!UP<#'@]19FERA$) +MP`$`B0``,!0"@1-@97-P96-I;@0!T`$"J@$`.@@P.B`BDPH!#A$)V@T3(KD" +M`-X.(F%NZ`(`I0<&-`H0+&,`0&1EA<"+```.P``!`,`2P+%1`G-Q,`C!4`%@)S82!F=6QL+98(2!A="!O;F-E +M+@H@("!/;B!W7,@<')O9'5C97,@8V]R6]U('1O(&AA=F4@;75L=&EP)0`#J0!P +M`/,-("!B!E('-O;64@=71I;&ET>3X`!8P``+$!\09P2!D8737`%9U0(1.FH`$B>7!1`G'@9`9W)A;18"\`9A(&9U;&PM +M9F5A='5R960@)W1A`<``$D!0'-U8V@G`%`J(&5X84D`0',Z(%,R`U1S +M;6%L;!4`!#X!`%(#(6%T(`8@;6'F!"!N9-`",69U;"\"!D4`42]M:6YIA0$1 +M8>,!46%C="!S8`"P(&1E;6]NM``,D!`"3``!.`/4! +M+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_```"`!`MH@(`GP`$J``,H@2R+"!O +M;FQY(&YE961\`#%M86GV`2-E7-T96TZ +MIPH"N`1U+C$@97AP;(,"`R\#`$(!`B$`!)H#`S,``(@$#S0`"P`B``PU`"]A +M=#0`#"AA=#,`!@$&(2XSM@L0<]\&@&]V97)V:65W\P(`H``%P`L`<04P=VAO +MD0(4*J0*A5]R96%D+C,L$``!^`@-$0!17V1IP$2+8($-7,N-:H(`J\``!D#`)\#@&UA=',@=&%R+C54`0CQ!$%A8F]U4P41] +M!9!I;@IA(&YU;6+R#!=FD0<#HP#7+@H*66]U('-H;W5L9*0+`$P`,6-O<'8& +M0&-O;6V>"`#.#1,B!0XR+F@BJ0`R:&4*7PP0(+`)`'4!`!0`!.D&`W((`G\" +M-&UO@,QBH@4U92-"!!4T-)210``E,` +M#S(`!6%":6YA`@@;W#+`\!A;"!2;V-K[`@0]`5HW+5II +M<"8`V$UI8W)OFEP/@$Q +M:6]N&`%=8GII<#(6``1\`4TO3%I7'0"B;'IM82P@;'IID2,',@*'T'`30$`(0!`S,$`/0#8"P@971C*>\+`OH#`*D" +M`&@1`HT``88!`MH`#Y8#!0'(`V$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0% +M!`?.``]9`P`*%@,S5VAE`P(`-0<#U`(2<^8%87)E`3AN97>U`P#P!`#]`@.?`0![``&'"0$K%0)*#`!-$2)IP,1<#4`8F%T979E*B!F:6QEFEP(&-O;7!R97-S:6]N%0!=8GII<#(6``0F`$TO3%I7'0#_`VQZ;6$L +M(&QZ:7`L(&%N9"!X>B,``!DT%`#Q,@I4:&4@;&EB2!C86X@8W)E871E +M(&%R8VAI=F5S(&EN(&%N>2!O9B!T:&4@9F]L;&]W:6YG(&9O"!I;G1E'1E;DT!L7,@*&9O$E33SDV-C`3`%HW+5II<#D` +M-EA!4A$`0PI7:&4#`@#D`00%`A$L_`%AT!X'-Y`>-R86YD;VT@86-C97-S+GD`!I<`\@)I`35N97<7`@!2`#!A;F1[``'.`!1V6`,24,`4&EN9&5PJ@`B;G1_`!!R.P0`!``P +M=&EC\`0D;VZ!`02N`/``5VEK:2!E>'!L86EN:6YGR0`P:&]W^``"]0``C@0# +M+``"*@$A3VZJ`!PL`P$#V0("<`!`;'=A>48!`-T!\@%E9"!A=71O;6%T:6-A +M;&QY1P"P22=V92!A='1E;7#$`^!T;R!M:6YI;6EZ92!S="L`L"!L:6YK('!O +M;&QUN`'A+B`@268@>6]U(&1O;B?L`0"V`/$":6-I=&QY(&EN=F]K92!A('#K +M`"!U;#<$(&5A60)`("AS=2\!&7,<`A!AZ0`'+0`'[P4`@`$"F0%P*2P@:70@ +M=W``X"!G970@<'5L;&5D(&ENI`0W($EN;@`W+"!IG@`!40$#FP`B96[)`07L#$7`U`-%A=&5V97(@8FQO8VMS\``0 +M:%<%(6ETH0!!66]U2X'<70@82!T:6U7`W%O8!(71O +M(@`%H0!A="!O;F-EA0`A3VZ0`QMEPP`"Y`(R<')O.@$!A0%18W1L>2W,``!( +M!E)U='!U=.\"`&`$\0-O8FIE8W0M2!F +M)M96UO?\`!8P``0`"\05R;W9I9&4@96%S>2UT;RUU8<``J,!!H`%,7=A +M;H@`$'0V!`5%`0!@``'Z"0".!R%S:RP#`WX&N6-O;G9E;FEE;F-EP`$`B0`P +M;6%K>0"0:7,@97-P96-I;@0!T`$"J@$`.@@P.B`BDPH.NPH3(KD"(&QL/`$" +MZ`(`I0<`$0,"P040+&,`0&1EH($',+!0$^`0!U```7`@#Y!`%Q``%Q"@B7 +M```\"3-Y+C--``#O!#)E(")K`P6K``$D`!0B"PM9(&-L87-$``$?"49N86QS +MG0`2!Q(M@@0U"`"X!!,B +M!0XR+F@BJ0`R:&4*7PP0(+`)`/H``!0`!.D&`W((`G\"-&UO5$P"9!F!E2X`L2`H8FEG+65N9&EAU!%C +M;&ET=&QE$0`"QP`$7Q:10T0M4D]-(&EMMP(0*#@.,"!O<,L#P&%L(%)O8VMR +M:61G9>\!`DD`#QX78P\+%P#036EC2!M86EN=&%I;F5R`""(&EN7-T96TZ"B`J(&)S +M9'1A3`1!F+``P'1E;J+``-J`0`9`]$J(%!/4TE8('5S +M=&%R6P`"$``P<&%X20-Q97)C:&%N9WX!-VUA="$`L&]C=&5T+6]R:65N`0,` +M8`(!'@"A4U92-"!!4T-)270"`10``E,`#S(`!6%":6YAFEP,A8` +M!'P!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9-!0`"0@!E6-A;B!C,H"("`H?0U`P#P!`![``.?`0![``&' +M"0&C``)*#`,*`P`X"`"R``$>`P"F!`(,`B$@8C<)<7)E861A8FP`!@","@$, +M``$L"P($`0!H``([`$)E86-H/0$A=F5S`Q-Y0P!0:6YD97"J`"5N="(!`!@) +M4&%R=&EC0@4D;VZ!`02N`$17:6MI4@PP:6YGR0`P:&]W^``"I@<'E@H"*@$A +M3VX_"`#W#`)X!@$""B-N9/@``8@)4&%L=V%Y1@$`W0$J962*"`)'`'!))W9E +M(&%T+0T`C`?0=&\@;6EN:6UI>F4@``B;`")E;LD!!RT``'P`"W$`*&1E$0`#Q@(1+/```H`` +M`(T.`)8!`!8!`$``(&%G`PX"1P*18V]RP,1<#4` +MT6%T979E2W,``"."5)U='!U=.\"`&`$\0-O8FIE8W0MP"`,D*`2L`,VEN("#U%F:7)S=)(" +M`*8!(&$@0P41;UD1`/8`%BYT``/9`P*G`0"_``*<`0&%``:X`0!V``##``"\ +M`Q)EDP`",0\@;'ED`0#,``"C`0:`!3%W86Y_!1)T'0\!-@(!6P,!&@00=(X' +M(7-K+`,0A$)P`$`B0`P;6%K>0"0:7,@97-P96-I;@0! +MT`$"J@$`.@@P.B`BDPH!#A$)V@T3(KD"`-X.(F%NZ`(`I0<&-`H0+&,`0&1E +M8$(&YDT`(Q +M9G5L+P(&10`0+T,*`84!$6&A"S1A8W1[$W!D96UO;G-T.14@;F<^``"`!094 +M`@-)`#!C;VY#`F$Z("!687+N$V!I=&5MP``7P%Q875T:&]R<\`%`1\&`?("`,$3$B[M#U!T +M;W`M;`P$`\4,`#`'`4$`!.$7!K8""',5`.L%`>X/\`4@*B!.15=3("T@:&EG +M:&QI9VAT<]P`,')E8]D4`C$%`Z`"DD-/4%E)3D<@+0P%`$(4`,H'(F1OGP`` +MAP4`S@"T*B!)3E-404Q,("V2&`&/!`$-``#Y%@"_``(I``-`!1$M/``!%!0" +M&``"$QD`?@L5+0P``D0``@(952P@'2(`"%P=6<0,"`B8S0&$2(D`P`X#"EO;$T``E8!!C4!`2D!`!8)`(X! +M#VT!`0"B!@2I&51T:&4*)[``(V4GKQD#)`0`DP``3@#P`"YA;2P@86-L;V-A +M;"YM-`D-`^T`,"YA8_\```(`$"UD`@"?``2H``#9#@BB!!(L&@X`UPL`60L/ +M9!K_________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_________U5096UO7,N"E)%041-15``1"!L:6)M`=%B=6YD;&4N"@I1=65SK@"@/R`@27-S=65S +M/U(`UBH@:'1T<#HO+W=W=RXX`$`N;W)GDP``2`$Q:&]MIP"`(&]N9V]I;F`<``$D!0'-U8V@G +M`%`J(&5X84D`0',Z(%,R`U1S;6%L;!4`!#X!`%(#(6%T?`2`;6%Y(&9I;F30 +M`C%F=6PO`@9%`%$O;6EN:84!$6'C`5%A8W0@2#R`@`!!5`N"@I4:)T!,'`M;`P$`W8%,&]R>3$%,'1A:20%";8"(FENU@0Q +M:6]NZP4$O0+P"4Y%5U,@+2!H:6=H;&EG:'1S(&]F(')E8P8"`C$%`Z`"DD-/ +M4%E)3D<@+0P%`,T%`"@&(F1OGP``AP4`S@#R!"H@24Y35$%,3"`M(&EN\`!,GK0`#)`0`DP``3@#U`2YA;2P@86-L;V-A;"YM +M-"SA`$!E+F%C_P```@`0+:("`)\`!*@`#*($LBP@;VYL>2!N965D?``Q;6%I +M]@$C97*N`05P`"1I;F0`@2YH+FEN"@DM]`=2;&%T97-G`!%B-`(!9@$39;4` +M8`H*1W5I9/,`*"!$5`8$T@$"=0`!MP%P!1%E^P,`\@"`;6%T] +M!;!I;@IA(&YU;6)E2X`P"`H8FEG+65N9&EA;J(!8VQI='1L91$``OH`\0)) +M4T\Y-C8P($-$+5)/32!I;;<"$"@X#C`@;W#+`\!A;"!2;V-KFEP +M/@$Q:6]N!0%=8GII<#(6``1\`4TO3%I7'0"B;'IM82P@;'II\+`OH#`*D"`&@1`HT``88!`MH`#Y8#!0'(`V$B;F5W8R*;`P$S`"=S:+`` +M`1(`#T8#8P0%!`?.``]9`P`*%@,S5VAE`P((T0X"Y@5A4,`4&EN9&5PJ@`E +M;G0B`0!$#0`/#Q!C0@42;VP-!C4*5"!7:6MI4@P##!,P:&]W^``!LP,09*T! +M`]H``BH!(4]N/P@`]PP"8`8`\PX`4`8#S0`!<`!3;'=A>7-S""IE9(H(`D<` +ML$DG=F4@871T96UPC`L``7\*`\X1("`HTA`E(&'["@"A +M`2`@8;(!`2<0`BT`",T`%&]S!'`I+"!I="!W<`!!(&=E=!D3`5T*`*0$-R!) +M;FX`,BP@:8(5`9X``5$!`YL`(F5NR0$'+0``?``+<0`H9&41``/&`A$LY0D" +M@```C0X`E@$`%@$`0``P86=A\P\!7PJ18V]R"(&5N=FER;VX/"Q%WD`,!H`(0;=@!$W):`P4P`@!;``)_`!%Y>P,1 +M<#4`T6%T979E:89`@4.%CHN`0+("0`]`!)A[`(!@`X`T1DS:6X@)P$` +MCP(/9!K_____________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_____________V505VAE;B!$:$ZN-A$``/$J8W)E871I;F<@87)C:&EV97,L +M('1H92!R97-U;'0@8V%N(&)E(&9I;'1EFEP,A8`!"8`32],6E<=`/D#;'IM82P@;'II<"P@86YD('AZ(P#!"DYO=&5S +M(&%B;W5TE`!R;&EB=$`\"YT96-T=7)E.@H*("H@5&AI'!L86EN:6YGR0`P:&]W^``"]0`'+``"*@$A +M3VZJ`!PL`P$#^``"<`!`;'=A>48!`-T!\@%E9"!A=71O;6%T:6-A;&QY1P"P +M22=V92!A='1E;7#7`>!T;R!M:6YI;6EZ92!S="L`L"!L:6YK('!O;&QUN`'A +M+B`@268@>6]U(&1O;B?L`0"V`/$":6-I=&QY(&EN=F]K92!A('#K`(!U;&%R +M(&9E85D"0"`HD`!RT`!P8#`(`!`ID!<"DL(&ET('=P`/`` +M(&=E="!P=6QL960@:6XN/@`G26YN`#``%1`0.;`")E;LD!!RT``#X` +M"W$`*&1E$0`#Q@(1+/```H``(FYEC@(`%@$`0`!B86=A:6YS1P*@8V]R7L#$7`U`-%A=&5V97(@8FQO8VMS\``0:$,$ +M(6ETH0!!66]U717 +M`F$@82!T:6U7`W%O`+$@(&)S9'1A3X`!8P``0`"\05R;W9I9&4@96%S>2UT;RUUX`0!V``*4`0"A`P&3``)/!R)L>8<``J,!!H`%,7=A;H@` +M$'0V!`5%`0!@`!!IA0(`C@%EB!$!G&%)`$!S.B!3,@-4`0-)`#!C;VY#`O`".B`@5F%R:6]UP``7P%V875T:&]R +M,&`4D!A69I9W5R92`M#``"1`"U'2(`")P==8-(")C +M-`81(B0#`#@,*6]L30`"5@$&ZP,!*0$`%@D`C@$/;0$!`*(&('5SW0H`V@$T +M90HGL``C92>M``,D!`"3``!.`/``+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C +M%P$``@`0+:("`)\`!*@``-D."*($$BP:#@#7"P)\`#%M86GV`2-EPH"MP(29:`,`!(&0'-E<77J"!!S"P4!/@$`=0`` +M%P(`^00!<0`!<0H(EP``/`DS>2XS30``[P0R92`B:P,%JP`!)``4(@L+62!C +M;&%S1``!'PE&;F%L]!9!I;@IA(&YU;6+R#!=FD0<$.P''"@I9;W4@2X` +ML2`H8FEG+65N9&EAU!%C;&ET=&QE$0`"^@#Q`DE33SDV-C`@0T0M4D]-(&EM +MMP(0*#@.,"!O<,L#P&%L(%)O8VMR:61G9>\!`DD`-%I) +M4'4$!$``('5N,0L`)18`UA!@C2H`0#E%PD(`0``"@*<$`4Z +M`0!U!`\&`0("KP$#OP,"O`(/'P,8,")R9:`-`!`6$2)'`P)/`,0L('=H:6-H +M('=I;&R*``%6``:0`"!E>"T4``("`+D%!(D1`@L7`UH7`5$`!>D2,',@*%,* +M`30$`(0!`S,$`/0#8"P@971C*>\+`OH#`*D"!C`0`9L!`MH`#\@#"F$B;F5W +M8R*;`P$S`"=S:+```1(`#T8#8P0%!`);`0&)``]9`P`*%@,S5VAE`P(`OP@# +MU`(2<^8%#V0:________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________________]34')A=&EO,WL/1TH1``#S'VXN"B`J(&QI8F%R8VAI +M=F4M9F]R;6%T4P`T&-P:6\N-2P@;71R964)`/(.86YD('1AP$R+F@BJ0"`:&4*2!E2QN``/2 +M`>`@875T;VUA=&EC86QL>68!065C='.H``#5``,<`E!O;&QO=Y,!$&8L`*!S +M.@H@("H@1TY5^`$`J`!6;6%T("BY`0`:`$%L;VYG50)B;F%M97,L$`!3;&EN +M:R`1``"T`5)S<&%R'1E;J+``-J`1%S2P"W4$]325@@=7-T87(0`.%P87@@:6YT97)C +M:&%N9WX!-VUA="$`L&]C=&5T+6]R:65N`0,`8`(!'@"A4U92-"!!4T-)270" +M`10``F,`#S(`!6%":6YAB,``!DT%``)"`&58V%N(&-R96%TSP`!=00/!@$"`NP" +M`[\#`KP"#Q\#&,$B2!S=')E86VU!>!S>7-T96TN("!4:&5R92P`(VYOX@<`@@(#WP@`DP3R +M`B!I;BUP;&%C92!M;V1I9FECK0CS`F]R(')A;F1O;2!A8V-E0`&@`3R +M`FES(&1EP`#P`! +MAPD!HP!4(&]N;'D*`P`X"`"R``$>`P"F!`(,`B$@8C<)<7)E861A8FP`!D%W +M48!`-T!*F5DB@@" +M1P"P22=V92!A='1E;7",!^!T;R!M:6YI;6EZ92!S=+4(`E((4'!O;&QU(@=1 +M+B`@26;U"$!D;VXGU@D`!RT`!"T'`,\*(&]R(P"@;6%T*2P@:70@=W`` +M@B!G970@<'5L^PH`I`0W($EN;@`W+"!IG@`(FP`B96[)`0P,1<#4`T6%T979E6QE(&%P<')OR`,`R0@"^@#0=&\@:&%V92!M=6QT:3$,!*D``@$$ +M`+D(52!O<&5NG@!0("!B4X.475S92`B(0$`6@@@+")0"'`L(&-A<&%B00`!]@("9@81954" +M`?$`864@05!)<[<$"/8%`9P"`,D*`2L`,VEN("#U%F:7)S=)("`*8!(&$@0P41;U`'`/8`%BYT +M``/9`P*G`0"_``*<`0&%``:X`0!V``##``"\`Q)EDP`",0\@;'ED`0#,``"C +M`0:`!3%W86Y_!1)T'0\#10$`8```&@00=(X'(7-K+`,0#B)A;N@"`*4'`!$#`EH'$"QC`$!D97-PWP``;`0!Y`,`7,N"E)%041-1>\%!^@&X2!B=6YD;&4N"@I1=65S^@*@/R`@27-S=65S/U(` +MUBH@:'1T<#HO+W=W=RZ!$4`N;W)GDP``2`$0:+@"$&:Q#S-N9V]8!Q@@9`!P +M9&5V96QO<#P%"!D1!+H1`:P(`3<,`'$``#H`(6YK70$`70`&8N9V]O9VQE+F-O;2]P+VH`$2\Z`"!S+VD``),``6<`47-U +M8FUI9P!P96YH86YC9<\``#8"!C@`,BP@<-H0`BP``#L```0#`$L'`1<)X65S +M="!V:6$@1VET2'5BP@`"D`"AB +M!`#R$0`6`G-A(&9U;&PME@AR9"`G=&%R)P\!`0(`(7)EK0H!0@%`8G5I;($& +M`(H``V,``"H``J(3!F,``,$0"V0`!M,2`3`#,&9A8RH'`#T``P(``"D0(FYT +M:`,`%0$V!L30',Z(%,R`U1S;6%L;!4` +M!#X!`%(#(6%T'`@@;6'F!"!N9-`",69U;"\"!D4`$"]#"@&%`1%AG@HT86-T +M>Q."9&5M;VYS=')*#0`.`R=O9EX!`TD`,&-O;D,"83H@(%9AP``7P%C875T:&]R +M:1``EPT!\@(`P1,2+NT/4'1O<"UL#`0#Q0P`,`0&";8""',5`.L% +M`>X/\`4@*B!.15=3("T@:&EG:&QI9VATM``,D!`"3``!.`/``+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C_P`` +M`@`0+:("`)\`!*@``-D."*($$BP:#@#7"P!9"Q!YR@4!]@$C97*N`05P`"1I +M;F0`@2YH+FEN"@DM]`<`YA,22XSHQ4$`(&EN^``(M@)P:6YF;W)M8:D!,"!F:34!`'P`\`0J($Y%5U,@ +M+2!H:6=H;&EG:'1SW``P@`K1#3U!924Y'("T@=U$!8F-A +M;B!D;Y\`,W1H:2D`\@))3E-404Q,("T@:6YS=&%L;'4```T`(7)U*@(#*0"! +M4D5!1$U%("T\``&5``*3`+!C;VYF:6=UM``,D!`"3``!.`/4!+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_ +M```"`!(M5``D=&^H``RB!+(L(&]N;'D@;F5E9'P`,6UA:?8!(V5R7`$%<``D +M:6YD`/(#+F@N:6X*"2T@=&5M<&QA=&5S9P`18C0"`68!$V6U`&`*"D=U:63S +M`%`@1&]C=9D%`H$!`,4!,F%L;'4``;`:`;W9E]!;!I;@IA(&YU;6)E"`"X!!,BO0(R+F@BJ0"`:&4*2R" +M```[!P$C"4!A=71ODP8`_P(0><$",&5C=)D#$635``,<`@5X"1!F+``!MP91 +M*B!'3E5U`0(U`B(@**L)`+D!`!H`06QO;F=0!F)N86UEB,``!DT%``) +M"`$```I58W)E873/``%U!`\&`0("J@,#OP,"O`(/'P,8,")R9:`-46-T960B +M1P,"3P#$+"!W:&EC:"!W:6QLB@`!5@`%R@%A(&5X8V5P0`4`N04$:0)1('1H +M871##C%I`3AN97>U`P#P!`![``.?`0![ +M``&'"0&C``)*#`!-$2)IF4@'!L:6-I=&S9"6)V;VME(&'Z#Q%C?PH#SA$@("C2$"4@ +M8?L*`*$!("!A00`!)Q`"+0`(S0`4;_D(<"DL(&ET('=P`$$@9V5T&1,!70H` +MI`0W($EN;@`W+"!IG@`!40$#FP`B96[)`07L#$7`U +M`-%A=&5V97(@8FQO8VMS\```[@2X'<70@82!T:6U7`W%O8!(71O(@`%2@``XQ,A8V6%`"%/;I`#&V7#``+D`C)P`!,@ +M%1``:A``"@$`/06#;B!I=',@(D`\`!(BO0012!F4X.``P1$2(A`0!: +M""`L(E`(H"P@8V%P86)I;&D2%`8#`07Q``+S#P$_#@CV!0&7`8`@:6YD:79I +M9&P.`]L(`(4``#H2`D(``*P+`-$``#8!(71OK`TP9&%TUP``!0X6.BX!`L@) +M`#T`$F'L`@#)"@$K`#-I;B`G`0!%!3-A9&2.`AAA]PP!J0H#'@]19FER41`.7,@9&5T96-T960@875T;VUA=&EC86QL>2X* +M"B`J($DG=F4@871T96UP(@#@=&\@;6EN:6UI>F4@6]U(&1O;B=T"B`@(&5X<&QI8VET;'D@:6YV;VME(&$@ +M<&%R=&EC=6QA2!A8V-E<#4`T6%T979E717`G`@82!T:6UEI0!Q;W(@;6UA<'\`0&5N=&F?`D!R +M8VAI?P)`;F0@9PD`(&ET3P``2P$%2@!A="!O;F-EA0"+3VX@=W)I=&7#``+D +M`C)P2!B=69F +M97(@;W+!``!E``1R`85A('-O8VME=#X#4'=I2UT;RUU0"0:7,@97-P96-I;@0!T`$"J@'S!TYO=&4Z(")P87@@ +M:6YT97)C:&%N9V6?!1,BN0(@;&P\`0+H`A!DO@$`_04!P040+&,`0&1EF-A="P@8@<`$G@'``!)`0"2"0`G`%`J(&5X84D`0',Z +M(%,R`U1S;6%L;!4`!#X!`%(#(6%T'`@@;6'F!"!N9-`",69U;"\"!D4`$"]# +M"@&%`1%A!@E186-T('-@`+`@9&5M;VYS=')A=+'2(`")P=;H+(")C-`81(B0#`!(+*6]L30`"5@$&ZP,` +ME``!%@D`C@$/;0$!`&8(('5SW0H`V@$T90HGL``C92>M``-G`0"3``!.`/4! +M+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_```"`!`MH@(`GP`$J```:@L(H@1A +M+"!O;FQYUPL"?``Q;6%I]@$C97*N`05P`"1I;F0`@2YH+FEN"@DM]`=2;&%T +M97-G`!%B-`(#<@$"M0!@"@I'=6ED\P`H($14!@32`0)U``&W`7!S>7-T96TZ +M&@D"N`0A+C'!#`!A#`$W`0,O`P`+``(A``2:`P,S``"(!`\T``L`(@`,-0`O +M870T``PH870S``8!!B$N,[8+$'-E"H!O=F5R=FEE=_,"`*``!<`+`'$%,'=H +M;Y$"%"JD"H5?PH"MP(29:`,`%L$$'/4!A!N2PT`U@(`DP``=0``%P(`^00!<0`!<0H( +MEP`!G`DC+C--``#O!#)E(")K`P6K``$D`!0B"PM9(&-L87-$``$?"49N86QS +MG0`2P$2+8($-7,N-:H(`J\``!D#`/T%-6UA=&D/!&,"!98!`+````H"D"XU+"!M +M=')E90D``&\`7G1A"`#. +M#1,BR0TR+F@BJ0`R:&4*7PP0(+`)`/H``!0`!.D&`W((`G\"-&UO2X`L2`H8FEG+65N +M9&EAU!%C;&ET=&QE$0`"^@#Q`DE33SDV-C`@0T0M4D]-(&EMMP(1*'@((&]P +MRP/`86P@4F]C:W)I9&=EYP%B2F]L:65T*0$![P$"20`T6DE0=00$0``@=6XQ +M"P`?$P#6$&!R(")D969^!A$B9@D#&```H00C:655`0##`0"B`85"4T0@)V%R +M)U(``?@`$2?]`Q`GNP($/0%:-RU::7`F`-A-:6-R;W-O9G0@0T%"+``Q3$A! +M"@,Z3%I(,@`Z4D%2$0`86!$``1D(!2`&`/42"*\"`'82`"H(`,,/`TP&!D4( +M,&)E9DH#4F5V86QU0@H`K@,#+P(`'P@P*B!U]@40;Q@$``L%`D,"`0H``EP) +ML5)032!WFEP,A8`!'P!32],6E<= +M`*)L>FUA+"!L>FEP$P,O>'HC```9-!0`"0@!```*`IP0!3H!`'4$#P8!`@*O +M`0._`P*\`@\?`Q@P(G)EH`T`$!81(D<#`D\`Q"P@=VAI8V@@=VEL;(H``58` +M!I``(&5X+10``@(`N04$B1$":Q0`0PX`TQ,`40`%Z1(PA@!+1`0:2`*<&AE879I;'G\"#9E86VU!0(1"P6(%$!I +M0`&@`0I:7-N%")B98@%`$`$`5X!.&YE=[4#`/`$`/T"`Y\!`'L` +M`8<)`2L5`DH,`PH#`#@(`&\0%'3N$@(,`B$@8C<)`(P*`8\8`[@4`0P`$&$, +M`0+4$`!H``([`!%EG!8`/0$A=F5S`Q-Y0P!0:6YD97"J`"5N="(!`$0-`7D9 +M`$(%$F]L#0:P"U0@5VEK:5(,`PP3,&AO=U$/`;,#$&2M`0/:``+W$P4T&`3\ +M!`#S#@!0!@/-``%P``*`%P+$!0]D&O______________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________5E!L97,I"MF.+50L$0``\"0@ +M("H@4V]L87)I"!I;G1E"=M=')E92<]`5HW+5II<"8`V$UI8W)O2!A;'-O(&1E=&5C +M='--`&!H86YD;&4,`'!Y(&]F('1HW`%`;&QO=RX"X&)E9F]R92!E=F%L=6%T +M$@``(``#+P(1.M0`8'5U96YC;W$",V9I;.@``0H`$2"#`:)24$T@=W)A<'!E +M3@)%9WII<#X!,6EO;D0`76)Z:7`R%@`$9`%-+TQ:5QT`L6QZ;6$L(&QZ:7`L +MQP`O>'HC```9-!0`"0@!E6-A;B!C$`6%N86UED#`*4#`.<#]A)U2!S=')E86VU!>!S>7-T96TN("!4:&5R92P`D&YO(&1I +M-R86YD +M;VT@86-C97-S+GD`!I<`D&ES(&1EU +M`P#<`P![``'.`!!VFP0`T082$N("!)9B!Y +M;W4@9&]N)^P!`+8`\0)I8VET;'D@:6YV;VME(&$@<.L`('5L60B@96%T=7)E +M("AS=2\!&7,<`A!AZ0`'+0`$10<#(@("F0%P*2P@:70@=W``X"!G970@<'5L +M;&5D(&ENI`0W($EN;@`W+"!IG@`!40$#FP`B96[)`07L#$7`U`-%A=&5V97(@8FQO8VMS\```[@2X'<70@82!T:6U7`W%O +M8!(71O(@`%H0!A="!O;F-EA0`A +M3VZ0`QMEPP`"Y`(R<')O.@$!A0%18W1L>2W,``"."5)U='!U=.\"`&`$\0-O +M8FIE8W0M2!B=69F +M97(@)`@`90`$<@&%82!S;V-K970^`TEW:7-HN@3`P"`,D*`2L`,VEN(">D``,P``*,!!H`%,7=A;H@`$'0V!`5%`0!@```:!!!TC@7,N"E)%041-1;L&!^@&X2!B=6YD;&4N"@I1=65S +M^@*@/R`@27-S=65S/U(`URH@:'1T<#HO+W=W=RX@!S!O3``!(`1!HN`*# +M9F]R(&]N9V]8!Q@@9`!P9&5V96QO<#P%)BP@_`Y`9&]C=10``:P(`3<,`'$` +M`#H`(6YK70$`70`&8N9V]O9VQE+F-O;2]P +M+VH`$2\Z`"!S+VD``),``6<`47-U8FUI9P!P96YH86YC9;L``#8"!C@`@RP@ +M<&QE87-E+```.P``!`,`2PB!$!G0&";8"(FENU@0`I`H` +MZP4$O0+P`DY%5U,@+2!H:6=H;&EG:'1S7`8PM```Z#S`@*B"3``!.`/``+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C +M%P$``@`0+:("`)\`!*@``-D."*($$BP:#@#7"P!9"Q!YR@4!]@$C97*N`05P +M`"1I;F0`@2YH+FEN"@DM]`<`YA,2H($',+!0$^ +M`0!U```7`@#Y!`%Q``%Q"@B7```\"3!Y+C/T%#!A:6SO!#)E(")K`P6K``$D +M`!0B"PM9(&-L87-$``$?"49N86QSG0`2!Q(M@@0U=H+`#L'`2,)"=H1`,$" +M!;47`/<"`QP"!7@)$&8&$@&W!@*'&`:J"P@`&@#X%0P@%@$0```%"P&^"Q)S +M-P)2V +M`'!I;F9O6]U(&-A;B!D;Y\`,W1H +M:2D`\@))3E-404Q,("T@:6YS=&%L;'4```T`,')U8X$``RD`@%)%041-12`M +M%`$1`?$#+@H* +M66]U('-H;W5L9"!A;'-O(@(!3``Q8V]P=@8R8V]M6P%#:6X@(KT",BYH(JD` +M@&AE"G-O=7)C+P`19'4!`!0`,2!S8>D&`YH#`G\"-&UO68!,&5C=)D#$635``,<`@7"!A!F +M+``!MP91*B!'3E5U`0*Z`28@*+D!`!H`06QO;F=5`F)N86UE'1E;J+``-J`0`9`]$J(%!/4TE8('5S=&%R6P`"$``P<&%X20,B +M97)9!P-X`@B,` +M`!DT%``)"`$```I58W)E873/``%U!`\&`0("J@,#OP,"O`(/'P,8,")R9?X( +M46-T960B1P,"3P#$+"!W:&EC:"!W:6QLB@`!5@`%R@%A(&5X8V5P0`4`N04$ +M:0+1('1H870@U +M`P#P!`![``.?`0![``&'"0&C``)*#`,*`P`X"`"R``$>`P`)`0(,`B$@8C<) +M`&H(,6%B;``&`(P*`0P``2P+`@0!`&@``CL`0F5A8V@]`2%V97,#$WE#`%!I +M;F1E<*H`)6YT(@$`&`D`#P\08T(%$F]L#08U"E0@5VEK:5(,,&EN9\D`8VAO +M=R!T;_4`!Y8*`BH!(4]N/P@`]PP">`8#`P$#^``!B`E086QW87E&`0#=`2IE +M9(H(`D<`<$DG=F4@870M#0",!P#!#Y!I;FEM:7IE(',.#1)C4@A!<&]L;)0- +M42X@($EF]0A09&]N)W2H`)!E>'!L:6-I=&S9"6)V;VME(&'Z#Q%C?PHQ9F5A +M-`LP*'-U+P$%^PH`J0`@(&%!`!%P&`$!+0`$10<`S0`4;_D(<"DL(&ET('=P +M`'$@9V5T('!UG`T0:7H+1R`@26YN`#``%1`0.;`")E;LD!!RT``#X` +M"W$`*&1E$0`#Q@(1+/```H```(T.`)8!`!8!`$``(&%G`PX"1P*18V]RP,B:67-#P%O`P/G"B!D=1D-`)8"$'.%`2-O9H@! +M4&%L;'DM=@``,PP`]P@1:;0/`(0`<&5N=FER;V[7`C%S('>0`P&@`A!MV`$3 +M2X'<70@82!T +M:6U7`W%O8!(71O(@`%2@!2="!O +M;F-\$B)/;AP."\,``N0",G!R;SH!`84!46-T;'DMS`"2960@;W5T<'5T[P(` +M8`3Q`V]B:F5C="US='EL92!A<'!R;\@#`$,2`OH`T'1O(&AA=F4@;75L=&D: +M$P2I``(!!`"Y"`#^#15NG@`3(!40`&H0``H!`#T%@VX@:71S(")`/``2(L@# +M$7,P#@)C!098`&!I='-E;&93`0!]!!`O=@1@=&5N('5S;P8`-PP!<@$R9G5N +M6!($DP$!=08`,@`U(&%NB`0"(Q-0;'D@9G)@``S0*%82!S;V-K970^`TEW:7-HN@0!)@\#60\`#B)A;N@"`*4'!C0*$"QC`$!D97-PWP``;`0!Y`,`7,N"B05 +M$6:X#01Q%K0@8G5N9&QE+@H*41$6H#\@($ESF-%#A)B!P`2>`<``$D!`)() +M`"<`02H@97@;$T!S.B!3,@-48$(&YDT`(Q +M9G5L+P(&10!1+VUI;FF%`1%AH0L`Z1D#>Q,/9!K_____________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_____________________________________________V507,@<')O9'5C97,@8V]R6]U('1O(&AA=F4@;75L=&EP)0`P +M`/,-("!B2!D8737`%9UX`0!V``*4 +M`0```P&^``7+`0#3``.C`4,N("!)I`$A86Z(`!)T70`!-@(491\!`#L!061I +M"!I;G1E&%)`$!S.B!3,@-4`0-)`#!C;VY#`O`".B`@ +M5F%R:6]UP``7P%Q875T:&]R<\`%`1\&`?("`DT'$`H5"%!T;W`M;`P$`W8% +M`#`'`4$`$&DD!0FV`B)I;O@$(FEOX08$O0+P`DY%5U,@+2!H:6=H;&EG:'1S +M7`8P'2(`#!P=71>`C`@(F,T!A$B)`,`J@2!N965D?``Q;6%I]@$C97*N`05P`"1I;F0`@2YH+FEN"@DM]`=2;&%T97-G +M`!%B-`(#<@$"M0!@"@I'=6ED\P`H($14!@32`0)U``#S`8`@PH"MP(A960N"P!;!!!SU`80;A$,`-8"`),``'4``!<"`/D$`7$``7$*")<` +M`9P)(RXS30``[P0R92`B:P,%JP`!)``4(@L+62!C;&%S1``!'PE&;F%L]!9!I +M;@IA(&YU;6+R#!=FD0<#HP#7+@H*66]U('-H;W5L9*0+`$P`,6-O<'8&0&-O +M;6V>"`#.#1,BR0TR+F@BJ0`R:&4*7PP0(+`)`'4!`!0`!.D&`W((`G\"-&UO +M@,QBH@4U92-"!!4T-)210``E,`#S(` +M!6%":6YA`@@;W#+`\!A;"!2;V-K[`@0]`5HW+5II<"8` +MV$UI8W)OFEP/@$Q:6]N +M&`%=8GII<#(6``1\`4TO3%I7'0"B;'IM82P@;'IIP`!APD!*Q4"2@P`31$B:7*"$1!I>0<# +M[A("#`(A(&(W"0","C%A8FP`!@","@$,`!!A#`$"U!``:``".P!"96%C:#T! +M(79E4,`4&EN9&5PJ@`E;G0B`0!$#0`/#Q!C0@42;VP-!K`+5"!7:6MI +M4@P##!,P:&]W40\!LP,09*T!`]H``O<3(4]N/P@`]PP"8`8`\PX`4`8#S0`! +M<``"@!<"Q`4J962*"`)'`'!))W9E(&%T(14`C`'!L:6-I=&S9"6)V;VME(&'Z#Q%C?PH# +MSA$@("C2$`!U#`@<`A!AL@$!)Q`"+0`(S0`4;W,$<"DL(&ET('=P`%`@9V5T +M(-(2`5T*`*0$-R!);FX`!287`9X``5$!`YL`(F5NR0$'+0``?``+<0`H9&41 +M``.J`!$L6!$"@```C0X`E@$`%@$`0``P86=A\P\!7PJ18V]R7L#$7`U`&)A=&5V97)X%Q%S\```[@ +M$P'Y%@*[&0"V`A!GQ!D0:2(3`2(`!4H``.,3#V0:____________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________________________________________](4'(*("`J9;G0 +MKS<1``#]#"!G>FEP(&-O;7!R97-S:6]N"B`@*B!B>FEP,A8`!"8`32],6E<= +M`/\#;'IM82P@;'II<"P@86YD('AZ(P``&304`/$R"E1H92!L:6)R87)Y(&-A +M;B!C"!I;G1E'1E;DT!\1-S +M("AF;W(@;&]N9R!F:6QE;F%M97,L($%#3',L(&5T8RDND@"P3VQD($=.52!T +M87)=``2I``+*`/$$;V-T970M;W)I96YT960@8W!I;S4`ME-64C0@(FYE=V,B +M%0`G +M`21E9-T`$2E%``"=``#5`85"4T0@)V%R)U(``1X`>"=M=')E92>[`'A)4T\Y +M-C8P$P!:-RU::7`Y`#9805(1`$,*5VAE`P(`Y`$$!0(1+/P!87)E0`& +MEP#R`FES(&1E'!L86EN:6YG +MR0`P:&]W^``"]0``C@0#+``"*@$A3VZJ`!PL`P$#V0("<`!`;'=A>48!`-T! +M\@%E9"!A=71O;6%T:6-A;&QY1P"P22=V92!A='1E;7#$`^!T;R!M:6YI;6EZ +M92!S="L`L"!L:6YK('!O;&QUN`'A+B`@268@>6]U(&1O;B?L`0"V`/$":6-I +M=&QY(&EN=F]K92!A('#K`"!U;#<$(&5A60)`("AS=2\!&7,<`A!AZ0`'+0`' +M[P4`@`$"F0%P*2P@:70@=W``X"!G970@<'5L;&5D(&ENI`0W($EN;@`W+"!I +MG@`!40$#FP`B96[)`07L#$7`U`-%A +M=&5V97(@8FQO8VMS\``0:%<%(6ETH0!!66]U2X'<70@82!T:6U7`W%O8!(71O(@`%H0!A="!O;F-EA0`A3VZ0`QMEPP`"Y`(R<')O +M.@$!A0%18W1L>2W,``!(!E)U='!U=.\"`&`$\0-O8FIE8W0M2!F)M96UO?\`!8P``0`"\05R;W9I +M9&4@96%S>2UT;RUU8<``J,!!H`%,7=A;H@`$'0V!`5%`0!@``'Z"0".!R%S:RP#`WX&N6-O +M;G9E;FEE;F-EP`$`B0`P;6%K>0"0:7,@97-P96-I;@0!T`$"J@$`.@@P.B`B +MDPH.NPH3(KD"(&QL/`$"Z`(`I0<`$0,"P040+&,`0&1EP +M`"-E)ZT``V2XS30``[P0R92`B:P,%JP`!)``4(@L+62!C +M;&%S1``!'PE&;F%L``'?`5=H+`#L'`2,)"=H1`,$",&5C=)D#$61A +M#0,<`@>F%@`@`@!0!0)!%0:J"R8@*`0+`%L5#"`6`1````4+`;X+$G,W`E)S +M<&%R\6`2T5`A``#XH,`P%V,/"Q<`T$UI +M8W)O-50! +M(FEN;P``MP)086)O=710`2!S94T!='!O<'5L87(?`01[`(`L(&EN8VQU9(H! +MQ6AA6]U(#\!8"X*"D-U$D#<65R8VAA;F=^`3=M870A`+!O8W1E="UOFEP/@$Q:6]N&`%=8GII<#(6 +M``1\`4TO3%I7'0"B;'IM82P@;'II&-E<$`%`+D%!&D"L"!T:&%T(')E<75I +ME@4G87C*`B`@*'T'`30$`(0!`S,$`/0#<2P@971C*2YO`0#Z`P"I`@8B!`$7 +M``+:``^6`P4!R`-A(FYE=V,BFP,!,P`GD#`*4#(71EVPC`.@H*("H@5&AI +M?P(-F5A;;4%`A$+@"X@(%1H97)E+``C;F_B!P""`@/? +M"`"3!/("(&EN+7!L86-E(&UO9&EF:6.M"/,";W(@P`#GP$` +M>P`!APD!HP!4(&]N;'D*`P`X"`"R``$>`P`)`0(,`B$@8C<)<7)E861A8FP` +M!@","@$,``$L"P($`0!H``([`$)E86-H/0$A=F5S`Q-Y0P!0:6YD97"J`"5N +M="(!`!@)4&%R=&EC0@4D;VXB"`2N`$17:6MI4@PP:6YGR0`P:&]W^``"I@<' +ME@H"*@$A3VX_"`#W#`)X!@$""B-N9/@``8@)4&%L=V%Y1@$`W0$J962*"`)' +M`'!))W9E(&%T+0T`C`?0=&\@;6EN:6UI>F4@D`!RT`!"T'`,T`%&_Y"'`I+"!I="!W<`!Q(&=E="!P +M=9P-(&ENI`0W($EN;@`W+"!IG@`(FP`B96[)`0P,Q:65SPP`!;P,#YPH@9'49#0"6`A!SA0$C;V:(`5!A;&QY+78``#,,`/<( +M$6F'!@"$`'!E;G9IP,1<#4`T6%T979E2W,`))E9"!O=71P=73O`@!@!/$#;V)J96-T+7-T +M>6QE(&%P<')OR`,`R0@"^@#0=&\@:&%V92!M=6QT:3$,!*D``@$$`+D(`/X- +M%6Z>`!,@%1``!A``"@$`/06#;B!I=',@(D`\`!(BO0012!F#B)A;N@"`*4'!C0* +M$"QC`$!D97-PH@``;`0!Y`,`7,N"E)%041-11(&!DD1X2!B=6YD +M;&4N"@I1=65S^@*@/R`@27-S=65S/U(`UBH@:'1T<#HO+W=W=RXX`$`N;W)G +MDP``2`$0:+@"$&:Q#S-N9V]8!Q<@3`>`(&1E=F5L;W`\!0@9$02Z$0&L"`$W +M#`!Q```Z`"%N:UT!`%T`!G,`02!M86G;$C!L:7._$`&=%!!4F0$`Y1$`YP$0 +M:;<`$"PA!`'\``$/`)$@=')A8VME1$@#R$0`6`G-A(&9U;&PME@AR9"`G +M=&%R)P\!`0(`(7)EK0H!0@%`8G5I;($&`(H``V,``"H``J(3!F,``,$0"V0` +M!M,2`3`#,&9A8RH'`#T``P(``"D0(FYT:`,`%0$V!L30',Z(%,R`U1S;6%L;!4`!#X!`%(#(6%T'`@@;6'F +M!"!N9-`",69U;"\"!D4`$"]#"@&%`1%AH0LT86-T>Q-P9&5M;VYS=#D5(&YG +M/@``@`4&5`(#20`P8V]N0P)A.B`@5F%R[A-@:71E;7,@,P$`UP(@;67/%U)T +M:&ER9,\),&5S.\@``P(``^H"`$8``'L``%\!<6%U=&AOP`"-E)Z\9`R0$`),``$X`\``N86TL +M(&%C;&]C86PN;30)#0/M`#`N86/_```"`!`M9`(`GP`$J```V0X(H@02+!H. +M`-<+`%D+$'G*!0'V`0]D&O______________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________9U!C:&EV97UVJIXG$0``\#T@=VET:&]U +M=`H@("!F:7)S="!W2!F6]U('=A;H@` +M$G1=`!`OB@`196``,&EE7,N +M"E)%041-12X`1"!L:6(3`=%B=6YD;&4N"@I1=65SK@"@/R`@27-S=65S/U(` +MUBH@:'1T<#HO+W=W=RXX`$`N;W)GDP``2`$Q:&]MIP"`(&]N9V]I;F`<``$D!0'-U8V@G`%`J +M(&5X84D`0',Z(%,R`U1S;6%L;!4`!#X!`%(#(6%T?`2`;6%Y(&9I;F30`C%F +M=6PO`@9%`%$O;6EN:84!$6'C`5%A8W0@2#R +M`@`!!5`N"@I4:)T!,'`M;`P$`W8%,&]R>3$%,'1A:20%";8"(FEN^`0Q:6]N +MZP4$O0+P"4Y%5U,@+2!H:6=H;&EG:'1S(&]F(')E8P8"`C$%`Z`"DD-/4%E) +M3D<@+0P%`,T%`"@&(F1OGP``AP4`S@#R!"H@24Y35$%,3"`M(&EN\`!,GK0`#)`0`DP``3@#U`2YA;2P@86-L;V-A;"YM-"SA +M`$!E+F%C_P```@`0+:("`)\`!*@`#*($LBP@;VYL>2!N965D?``Q;6%I]@$C +M97*N`05P`"1I;F0`@2YH+FEN"@DM]`=2;&%T97-G`!%B-`(!9@$39;4`8`H* +M1W5I9/,`*"!$5`8$T@$"=0`!MP%P!1%E^P,`\@"`;6%T] +M!;!I;@IA(&YU;6)E"`"X!!,B?P(R+F@BJ0"`:&4*`D09BP``;<&42H@1TY5=0$"-0(F("@$"P`:`$%L +M;VYG50(`K0LB+``-J`0`9`]$J(%!/4TE8('5S=&%R6P`" +M$``/B@P#!R$`P&]C=&5T+6]R:65N=!<$,7!I;QX`IE-64C0@05-#24D4``)3 +M``\R``5A0FEN87)Y+@#`("AB:6FEP,A8`!'P!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9 +M-!0`"0@!```*56-R96%TSP`!+0D/!@$"`JH#`[\#`KP"#Q\#&#`B&-E<$`%`+D%!FH0 +M,6AA=$,.$&F6!2=A>,H"("`H%@4!-`0`A`$#1`0`]`-@+"!E=&,I[PL"^@,` +MJ0(&,!`!A@$"V@`/E@,%`<@#82)N97=C(IL#`3,`)W-HL``!$@`/1@-C!`4$ +M`EL!`8D`#UD#``H6`S-7:&4#`@C1#@+F!6%R97-U;'1-$A%B:`4@=&6[#@%5 +M!`\C`@$*"P,!@``/Z0)4$`HJ$@&G!P(F"`:A!@`^!R%T9=L($3I4$@$M$!!I +M(`IP:&5A=FEL>?P(-F5A;;4%`A$+<"X@(%1H97(T$2`@;M82,7)E8S`1`]\( +M`),$02!I;BVW#X(@;6]D:69I8^4,\`!O`3AN97>U`P#P!`#]`@-S!`![``&' +M"0&C``)*#`!-$2)I7-S""IE9(H(`D<`<$DG=F4@870A +M%0",!S!T;R`A$'!M:7IE('-TM0@"4@A!<&]L;#82!N04061O;B?L`7!E>'!L +M:6-I#15@:6YV;VMEO!(!ZP`!?PH#SA$@("C2$"4@8?L*`*$!("!AL@$!)Q`" +M+0`(S0`4;_D(<"DL(&ET('=P`$$@9V5T&1,!70H`I`0W($EN;@`R+"!I@A4! +MG@`!40$#FP`B96[)`0"(&5N +M=FER;VX/"Q%WD`,!H`(0;=@!$W):`P4P`@!;``)_`!%Y>P,1<#4`T6%T979E +M:89 +M`@4.%CHN`0+("0`]`!)A[`(!@`X`T1DS:6X@)P$`104U861D'`$`_`@$J@$` +M>08/9!K_____________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_____________V50FEP,A8`!"8`32],6E<=`/D#;'IM82P@;'II +M<"P@86YD('AZ(P#!"DYO=&5S(&%B;W5TE`#P.VQI8G)A2!R97%U:7)E;65N=+(`,G1H80D!`BL`("!BCP&0(')E861A +M8FQEH@!!=W)I=`P`$&$,`0($`0!H``([`$)E86-H/0&#=F4@96YT$N("!)9B!Y;W4@9&]N)^P!`+8` +M\0)I8VET;'D@:6YV;VME(&$@<.L`@'5L87(@9F5A60)`("AS=2\!&7,<`A!A +MZ0`'+0`'!@,`@`$"F0%P*2P@:70@=W``\``@9V5T('!U;&QE9"!I;BX^`"=) +M;FX`-RP@:9X``5$!`YL`(F5NR0$'+0``/@`+<0`H9&41``/&`A$L\``"@``B +M;F6.`@`6`0!``&)A9V%I;G-'`MEC;W)R97-P;VYD:6YGF`$-6@`">P,Q:65S +MPP`!;P.P86QS;R!R961U8V6;`C!E('.%`2-O9H@!`+,!$"UV`&%E9"!B:6X] +M`"`@:2P$@"!E;G9IP,1<#4`T6%T979E8!(71O(@`%2@!A="!O;F-EA0`A3VZ0`QME +MPP`"Y`(R<')O.@$!A0%18W1L>2W,`))E9"!O=71P=73O`@!@!/$#;V)J96-T +M+7-T>6QE(&%P<')OR`,`H`4"^@#@=&\@:&%V92!M=6QT:7`E```A!1!V$@,` +M!040<_@!16]P96Z>`+$@(&)S9'1A3X` +M!8P``0`"\05R;W9I9&4@96%S>2UT;RUUP"`*`'`2L`,VEN("0#\`)N86UE('-A>7,N"E)%041- +M15``!^@&X2!B=6YD;&4N"@I1=65S^@*@/R`@27-S=65S/U(`URH@:'1T<#HO +M+W=W=RX@!S!O3``!(`1!HN`*#9F]R(&]N9V]8!Q@@9`!P9&5V96QO<#P% +M<2P@:6YC;'6]!4!D;V-U%``!K`@!3@D`<0``.@`A;FM=`0!=``9S`%`@;6%I +M;`<"0FQIF-A="P@8@<`$G@'``!)`0"2"0`G +M`%`J(&5X84D`0',Z(%,R`U1S;6%L;!4`!#X!`%(#(6%T'`@@;6'F!"!N9-`" +M,69U;"\"!D4`$"]#"@&%`1%A!@E186-T('-@`+`@9&5M;VYS=')A=+"`"X +M!!,B!0XR+F@BJ0`R:&4*7PP0(+`)`/H``!0`!.D&`W((`G\"-&UO5$P`P%&!E+``-J`0`9`[$J(%!/4TE8('5S=+`1!!``#XH,`P%\``(Q`%9O8W1E=*\4 +M`&`"`1X`H5-64C0@05-#24ET`@$4``\R``L00FT1$7DN`+$@*&)I9RUE;F1I +M8=018VQI='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I;;<"$"@X#C`@;W#+ +M`\!A;"!2;V-K[`@0]`5HW+5II<"8`V$UI8W)OD,1``#Q%V]C=6UE;G1S('1H92!F:6QE(&9O +M2!E2QN``/2`>`@875T;VUA=&EC86QL>68!065C='.H +M``#5``,<`E!O;&QO=Y,!$&8L`*!S.@H@("H@1TY5^`$`J`!6;6%T("BY`0`: +M`$%L;VYG50)B;F%M97,L$`!3;&EN:R`1``"T`5)S<&%R'1E;J+``-J`1%S2P"W4$]3 +M25@@=7-T87(0`.%P87@@:6YT97)C:&%N9WX!-VUA="$`L&]C=&5T+6]R:65N +M`0,`[P(!'@"A4U92-"!!4T-)270"`10``F,`#S(`!6%":6YAB,``!DT%``)"`&5 +M8V%N(&-R96%TSP`!=00/!@$"`NP"`[\#`KP"#Q\#&,$B2!S=')E86VU!>!S>7-T96TN("!4:&5R +M92P`(VYOX@<`@@(#WP@`DP3R`B!I;BUP;&%C92!M;V1I9FECK0CS`F]R(')A +M;F1O;2!A8V-E0`&@`3R`FES(&1EP`!S@`&[P@"HP!4(&]N;'D*`P`X"`"R``$>`P"F!`(,`B$@ +M8C<)<7)E861A8FP`!D%WF4@7L#$7`U`-%A=&5V97(@8FQO8VMS +M\```[@2X'<70@82!T:6U7`P!K"S%M87#X`C!E;G21!@/0`@%1`Q!GH@P@:71/ +M``E*`&%T(&]N8V6%`"%/;I`#&V7#``+D`C)P7,"!8P``+$!!)4.0&5AP"`,D*`2L`,VEN("60!`,P``*,!!H`%,7=A;G\%$G0=#P$V`@%;`P!C#``S`$%D +M:7-K+`,#?@:Y8V]N=F5N:65N8V7``0")`#!M86MY`)!I%E7!1`GD1(`\A$`%@)S82!F=6QL+98(F-%#A)B!P`2>`<``$D!`)()`"<`02H@ +M97@;$T!S.B!3,@-4?42`-`",69U;"\" +M!D4`$"]#"@&%`1%AG@HT86-T>Q."9&5M;VYS=')*#0`.`R=O9EX!`TD`,&-O +M;D,"83H@(%9AP``7P%C875T:&]R:1``EPT!\@(`P1,2+NT/4'1O<"UL#`0#Q0P` +M,`0&";8""',5`.$&`>X/\`4@*B!.15=3("T@:&EG:&QI9VATM``,D!`"3``!.`/``+F%M+"!A8VQO +M8V%L+FTT"0T#[0`P+F%C_P```@`0+:("`)\`!*@``-D."*($$BP:#@#7"P!9 +M"Q!YR@4!]@$C97*N`05P`"1I;F0`@2YH+FEN"@DM]`<`YA,2!Q(M +M6`DU:L`D'-A;64@9G5N8S`<``$D!0'-U8V@G`%`J(&5X84D`U',Z(%-O;64@6]U(&UA>2!F:6YD('5S969U;"\"!D4`42]M:6YIA0$1 +M8>,!46%C="!S8`"A(&1E;6]N2#R`I!I;VYS+@H*5&B= +M`?("<"UL979E;"!D:7)E8W1O%#36%K94QI\`!,GK0`#)`0`DP``3@#U`2YA;2P@86-L;V-A +M;"YM-"SA`$!E+F%C_P```@`2+50`)'1OJ``,H@2R+"!O;FQY(&YE961\`#%M +M86GV`2-E7-T96TZ +M"B`J(+@$=2XQ(&5X<&R#`@,O`P!"`0(A``2:`P,S``"(!`\T``L`(@`,-0`O +M870T``PH870S``8!!O`%+C,@9VEV97,@86X@;W9E]!;!I;@IA(&YU;6)E"`"X!!,B +MO0(R+F@BJ0"`:&4*2R"```[!P$C"4!A=71ODP8`_P(0><$",&5C=)D#$635 +M``,<`@5X"1!F+``!MP91*B!'3E5U`0(U`B(@**L)`+D!`!H`06QO;F=0!F)N +M86UEB,``!DT%``)"`$```I58W)E873/``%U!`\&`0("J@,#OP,"O`(/ +M'P,8,")R9:`-46-T960B1P,"3P#$+"!W:&EC:"!W:6QLB@`!5@`%R@%A(&5X +M8V5P0`4`N04$:0)1('1H871##C%I?P(-F5A;;4%`A$+ +M@"X@(%1H97)EO0\C;F_B!P""`@/?"`"3!$$@:6XMMP^"(&UO9&EF:6-D"_`` +M;W(@0`&EP``L!!397-I9VXE#!)EB`4`0`0!7@$X +M;F5WM0,`\`0`>P`#GP$`>P`!APD!HP`"2@P`31$B:7)`$!!I>0<280D!`@P" +M(2!B-PD`C`HQ86)L``8`_0H!#``!+`L"U!``:``".P!"96%C:#T!(79E4,`4&EN9&5PJ@`E;G0B`0`8"0`/#Q!C0@42;VP-!C4*5"!7:6MI4@PP:6YG +MR0`P:&]W40\!LP,09$X(`]H``BH!(4]N/P@`]PP"8`8`TQ$`4`8#S0`!<`!3 +M;'=A>7-S""IE9(H(`D<`<$DG=F4@870M#0",!S!T;R`A$+)M:7IE('-T871I +M8U((07!O;&PV$E$N("!)9O4(061O;B>L$I!E>'!L:6-I=&S9"6)V;VME(&'Z +M#Q%C?PH#SA$@("C2$"4@8?L*`*$!("!AZ0`!)Q`"+0`(S0`4;_D(<"DL(&ET +M('=P`$$@9V5T&1,!70H`I`0W($EN;@`W+"!IG@`!40$#FP`B96[)`07L#$7`U`-%A=&5V97(@8FQO8VMS\```[@2X'<70@82!T:6U7`W%O +M8!(71O(@`%2@``XQ,A8V6%`"%/ +M;I`#&V7#``+D`C)P`!,@%1``:A``"@$1:2$(8VETP"`,D*`2L`,VEN("#U%F:7)S=)("`*8!$6%P$A%O\0T`]@`6+G0``]D#`J#B)A;N@"`*4'!C0* +M$"QC`$!D97-PH@``;`0!Y`,`7,N"B05$6:X#007&0.A&$0N"@I1 +M$1:@/R`@27-S=65S/U(`$2H%&78Z+R]W=W2X*"B`J($DG=F4@871T96UP=&5D('1O(&UI;FEM:7IE('-T*P#X4R!L +M:6YK('!O;&QU=&EO;BX@($EF('EO=2!D;VXG=`H@("!E>'!L:6-I=&QY(&EN +M=F]K92!A('!A``B;`%IE;F%B;)L``#X`"W$`*&1E +M$0`#J@`1+/```H``(FYE)@$`%@$`0`#X"V%G86EN<`!`"@$`#,`@&%N9"!W&%)`$!S.B!3,@-4P`` +M"@+Q`F%U=&AO@`K!#3U!924Y'("T@=Q,'`+D(8F-A +M;B!D;Y\`,W1H:2D`H$E.4U1!3$P@+2#0!S)A;&QU```-`"%R=2H"`RD``T`% +M$"T4`1%SE0`"DP"P8V]N9FEG=7)E("W.``$,``)$`+5S8W)I<'0L('-E96<` +M`/T(9&1E=&%I;,,$84--86ME3-0$,71X=(@`(G!U)@EQ(F-M86ME(B0#`*0) +M*6]L30`"5@$&ZP,`E`!!2!N965DQ0@0>5L+4&$@=VAOD0(C*B#9!X5?]!;!I;@IA(&YU;6)E<$",&5C=)D#$61A#0,< +M`@5X"1!F+``!MP91*B!'3E5U`0(U`B8@*`0+`!H`06QO;F=0!F)N86UE+``-J`0`9`X$J(%!/4TE8("`-`5L``A``,G!A +M>%H)`ED'`W@"!R$`L&]C=&5T+6]R:65N1!``8`(!'@"A4U92-"!!4T-)270" +M`10``E,`#S(`!1!"V0X1>2X`H"`H8FEG+65N9&GS!(-R(&QI='1L91$``OH` +M\0))4T\Y-C8P($-$+5)/32!I;;<"$2AX""!O<,L#P&%L(%)O8VMR:61G944` +M8DIO;&EE="D!`>\!`DD`-%I)4'4$!$``('5N,0L`BQ`@960Z`$`B9&5F?@81 +M(F8)`Q@``*$$(VEE50$`PP$`H@&%0E-$("=AFEP +M/@$@:6^[$'TJ(&)Z:7`R%@`$?`%-+TQ:5QT`HFQZ;6$L(&QZ:7`3`R]X>B,` +M`!DT%``)"`$```I58W)E873/``$M"0\&`0("J@,#OP,"O`(/'P,8,")R9:`- +M46-T960B1P,"3P#$+"!W:&EC:"!W:6QLB@`!5@`%R@%A(&5X8V5P0`4`N04$ +M:0("UQ$`0PX0:98%)V%XR@(@("@6!0$T!`"$`0,S!`#T`V`L(&5T8RGO"P+Z +M`P"I`@8B!`&;`0+:``^6`P4!R`-A(FYE=V,BFP,!,P`GD#`#X'(71EVP@1 +M.N85`2T0$&D@"G!H96%V:6QY_`@V96%MM04"$0M!+B`@5$`44VES(&YOX@<` +M@@(#"A4`DP1!(&EN+;P`#GP$` +M>P`!APD!HP`"2@P#"@,`.`@`;Q`R=&AA"0$"#`(A(&(W"0!J"`'[%2%O46`$(%$F]L#0:P"U0@5VEK:5(,`PP3,&AO=U$/`J8'`$X(`]H`"Z`5 +M!/P$`/,.`%`&`\T``7``0&QW87E&`0#=`2IE9(H(`D<`#]`7_^`)^@,08S<& +M``48PF%T979E +M$P$/`P),%@"V`A!G5180:2(3`2(`!9L$`.,3(6-EA0`A3VZ0`QMEPP`"Y`(R +M<')O"AFA8V]R>`9 +M07!P4X.``P1$2(A`0!:""`L +M(E`(H"P@8V%P86)I;&D2%`:-`07Q``+S#P$_#@CV!0&7`8`@:6YD:79I9&P. +M`]L(`(4``#H2`D(``'(+`-$``#8!(71OK`TP9&%TUP``!0X6.BX!`L@)`#T` +M$F'L`@&`#@`K`#-I;B`G`0"/`C-A9&2.`AAA]PP!J0H#'@]19FER"U$W,3$W-0`>83$U,34U,@`>+S4Q`![_ +M5==&96(@,#DL(#(P,3,ZAPJ1(#,N,2XR(')E,A.>9`H*2F%N(#(X*0`A)W.K +M"T!W96)S``0R;6]VT0L/(1X&$BY,`"XQ,TP``74`&S%U``\I``87,"D`841E +M8R`P-U(`0#(Z($E2&P$(#`@*!0/0%`#O#!EE&@P`G04"VPT"3A@!D`B$(`I. +M;W8@,3%4`"!!9+8;!JPB@U]?34%#3U-8%PT`@@0$$]@\$90``P@$@(&Q<`6``'E("`@0_$@`9D"`V,``%(7#P(A +M$@]U``@)DR$#=0``3@L#=`!01W)O=7`2$`"U`R$R-!4!&3$5`0`^`0=\!`$H +M``(O!"4Q.ID>H&9I>&5S(&UE`RDQ.D4`"AH`$5/\'P+8`&%T;R!)4T^?``!U`%!T;R!I +M;8H+-F4@2-RQH` +M+PU18V]L;&6((0#C#0!*#S!L92VK(@#`` +M)F]NS0,!W`<&?`$11O0&`"H#,FP@,#4"(3`Z +M_"T`&QH#HR8'0R80968$`=\3`I4$`2X#`M$0``D+,'1R884%(6%L.P0A,CD[ +M!$`P.B!-<`(#R`8%$`,`%04"G``!\!3P``H4!$C"%`4!L87)G +MQQ0!ZA(`V!1B96X@8V]PE!$`#@,!'A($R`D!00`#B040,`@"`;(G`'@`=B!- +M86,@3U.I`@`\``>N!`$Z``-"`B0P.E``!^L``*H)`_T"$'->"0+N`%1S"DUA +M>24-8S`Z(%A!4D,$`1D``T,%$3#'`34@7E0-!1([/B]`(&5X:1$5`J<$`]0' +M`!H!`)0=`XT*`F,`!IL``UT$`=\A!A`%!`<"!!L#8&,@8W)Y<,4$`L$,`8\` +M`_L&(3`Z/1T!`@(`+`8"$`0`)@,`1P4"*@`"!0T2,``(`]0#$CHN!T`M9VED +M!@``*@1!("TM=0X`$'4.``$'!0,R#@/``6!2960M8FQ@%@#\(@&4!P;^`0$9 +M%2!E"!L96=A +M8WFU!S%M870,!`/!4`Q`,`,AT"D`4#=@@#O@$`OP<29"L``)$@.6QD95\(`%T;$&R[`0`5#@%` +M*"%E9,L#!A`!55)E;&%X`P(`P@4@2!!4D-(259% +M7T9!5$%,(')A'`0@=&@;`T,@=FES^Q0#*08`R0L#=0`T7`8P`!H4#$%+(!T5A9FEO#@D!50`%PP400<<=`%8`!_,C +M!3$%(6QY+`\$_0("6P`%NP%@26YT96=R70(@07#Q&`?W!`!+!@@-!0!_'2!A +M=`,L$'5.'@'@`0+^&`$!$A4S5``$$0$`WR,S("U6X@X&4P0&:PLX,BXXJQ$W +M2F%NR`,`=@L!S`@&"@,`DP#@)V5C:&\@;F]N97AI0(O,#G?```?,=\`#P&O#`*'`@]#```6,7P-,TIU +M;#L#`"@````"`/@DL2!B;V=U'HP``)!`P0P``"1 +M,0*8`4$@,2XW90<1,?4`""$`<&QZ;6$O>'I;`P/A`@!G``06(`D""`)`!`"? +M!1-Y\@X`20`12,@D("!G_A("10``V`D$00!`3W!E;I0E<")G>G-I9R+-*`"@ +M,`)%``+#`P!%`)!!=F]I9"!F86P*`@.2!0*(`02I!`&@!#!P:7`F,P!1$@+> +M!P`\``ME`@?\`@+%!@%_!`TI`$<0"%W()`RM!9#L04FYE>'1?;`\T,B@I +MGQ9!:7,@=6$243(U)0H),2M0969F:6-S"`%E``$>'@.#"!([:A/30G)I86X@ +M2&%R2!-:6-H +M:6AI'@#'!T%T86UP +ME@LP5')UY0X!\0X`I@0`L2A02'5R9"R&`,%":L.VF5D!0\2)P/``S!C;W)D +M`D%!;'-O)R0+L0`Q8FED`(5<]<.(`H)E`8A97/-`S!S=&$N*`"(``,. +M!"%S+NH=`XD&)#@ZS@D"&P4)D`D!I@X28)`"P3=@ED;V5S;B?G!PLR`&)W96QL*2RS +M!B)I65T"@E00T%D('5NH@`"K!`")0<#WP`)L1J086QL*"DN("!& +MF`M!;F]W+)0J,&UU2!E;F]U9V@@00=!+"!W +M9<:\!"W@!%S1/`0$I``4E`P_8`0$P9FEXZP4`;`($_!X* +ML!,`#C0`S0``1@0!,Q@&(P8!OAP!9A$`2R$&]A\":0,`/PX`"0D38=U#3H@"?$E$W`=`-`N9G)E96)S9"YO0"@D@(&UE87-U>P,!4P8".0``30(`N@L1:1Q)`5TO0'!A=&@=`&$@9FEE +M;&31`#!U*P%'(F!M;6%R:7HZ"1!P[#L`W!<"MP0`N@!`+6YO+;H*(V9I +MCC@T;&EBS4<#;Q0`)P`+J`!B.B!3:VEPDQ@!LP$!8P4!2@4#_P0",0A0,S(M +M8FD6!3!F7W1'`#!I +M(P'&`2`M!@"AP$`V#0%%",!5P8754-!"8G +M`(H!$&:;!B5L>?,$(`H))0]5:VYO=V[(``"O)4!A=&5G(QD+.0$"7!8`"00" +M+`4"EP(.3P<,G@`!F`<`U1,#Z@@!?`D""00&/0L`X@(/2P`/`"8!`*L``/@( +M&&5;`@-:%3`@=74;$3!D93L,`1%YD`X"N`T!U`\0+8$N,65C;X$%4FQO9VEC +ML14"-``0!Q(NR!\&Y@X,I@`5,Z8` +M`I,8!?D"`W8=`)T&$2Q,`@"3`!(LF@`0+"P$`IX``3L!(&-A91`18I@+,79E +M`A8R7@(**0``J`$@8F%S3A%DB`,!%PD#%0$&PR4#3`4"*B(&=0`* +M2P!D5F5R:69Y300!5@@`21HQ9V5TF@T"I3P!8@L$S54`<1H!C@5%,BXY+H(! +M`CH``$@!$FQ4,1!B$QD!VPL'X0\B*"VE#T`M>BDLJP,`(0\Q"6]FJ@TPA$P%!$P&^ +M!0!G"2$*"8U.`=P(`!0%8&QA*9!`;4E`.@3`O@D!F$!`*<$`;$)!3T/`6H``C\K#VH` +M`0S,&0)A!!8WA@A0,"XY+C#&!P"!!P+.4R!W::$5,W5S92<;!30`($-OCQL` +M&@M0:6YI=&E\!@`/)00Q$`#*`0,)`@28``+'`PZ8`!4YR@8"P``%*``&U`4` +M8P$"C30`>@4"B1<)9`#P`SH@("UA+"`M<2P@+4PL("UF+)L8$'0^�@00!G"0#C$`0+)H*!(T2H41A;6EE;B!';VRJ!`"C`!!B>@T` +MZ0`!CP,`B3@0>H*Q`O!0D!!0`07[@4("YCH2$`@@LP--*)7!Y^!T!=``#$!L2-XD%4&$@8V]UE!PC;V:6!`>M)@#E!0%_``*I#PZG +M``?R%0HH``!;``"I`P&G``$%`!%?:0$07]\$(6)YV3$"10%R92!U;6%S:Z0_ +M`T`!`_H>#G``!E@)`LL`!1X"`(8'!C12!(0"4"TM9&ESIQ!2+7AA='1Y"@84 +M`'5A8VPL"@ET[0'_`%-A;75L:2!3=6]M:6YE;HP`#0<^"0'\``6,``8_`L!, +M87!O($QU8VAI;FG5!0!Z50%)`@!.'`%520`%#@'2"0&:)`-*!0"3`2!L9%<) +M`54N`/H;!&\$,&)U9\8%`1@``$`!L&]F"@DB;&5N9W1HGA2096YD(B!F;&%G +M'@H%80`2@$@"@D4``&Z)`,Z.P_T!08'B04**``">```)0@`\04`,A0&/`(#N@Q08VAI +M;&P'%PL[`!!/D`8`V1``\`("]PT+0$D@<'7P+PF-`@`A$`,D`048+P!, +M`0#!5`&$``4L!Q-)U`@!V0L`V`<097\G``$#4&XM;6%T;P4`%5T`U#XA;W)! +M#(([($D*"6AO<$@-D2!E=F5N='5A;#PE`?%,`!\!`#`+,F1E("<*`$,H`LX) +M`,Y5`Q4_`FL.#)<&&#.7!@"J`!4P+@$@0V\C&A!UD``$K0`$=@4`7`(!F"H2 +M9=\`!C4`$$XM30%85@#E0`"T!!,L]PL!<`@P(DAI[PH@>2*U`0-.`"`N,3@) +M`<\,`*\`%#$Y``/D(09<``"8!Q5Z-#P`EP*1:6UM961I871E#0$!D#@P14]& +MT2H`C!\P=')YSP\!_A4%PQ0`$0XP)(5`EH/!,L+`)T#(6]FA``#H0(`90@`OCL/D04$&#-I!P`H``/0$!`W +MT",!50$334<<("YA)!4!3@<`$@02(,<@$R\#"`1J$D,*"6%C_`$A9&\H`%%R +M:6=H=$$3,6=S+KDA!F,``,0($"VT"`!2"@$-``&$#`2[``?<%`%A!``C`1!I +M]0``B@,,)P$-70`!D`4/E`L``.4+(&ENO2(@8V6](``7$`'0#0`T`@#K.@$` +M*@1](`!&%0",)S!N:6/2`2)H868&4')A9W1A!P,(7#L`00`#M%P1<_L(%'3# +M!R1H88@!!F@#";H'&#.Z!P&(`0\H``40,5(:)&ME6@`@8F5K'`!Z`P5&2P,, +M"@#'!4`H*0H)2PPY!("UP+#X'`6,Z(0H)Q24""1$5 +M;Z,0$"QB$0'Z#00X"U!S96=F8><%`CX"!H$``F@)`U8#`44B`NH2`S\""0A```001('X88`H) +M:6YS=(0&$',C!!!TF08)&&$#IP`%I@0(7"X`T`=T>5]L:6YK7\P2%"S0!0,= +M`#!S=')O6@(N`@/T,0R6`1@RH0T`E@$&P@P&B`$4,@`&`-\"0'-T("A<(S!Y +M972<$!(INP`"ZST"?A(`&SP##`(#/#`.=@`'80U2075G(#,O)!(WXS(`LS(` +MF0,$O`8"*QX`@PLC"`M+7-))P22!Q(N-P`%.`P3 +M4K,:8'-U:60O0@(6A``X````0\`C`,`92@`]AP&GR80+`T<`0$,)`H)AA4" +M21,$43DE('06%@*7!"`N:"P>(V%DQ0EC;&5A;G5P?BL*8@$2+!T5``P'$7,B +M"@`S$A$O+Q(#W`4P;@H)!`E386YO;6$("@',6@`G&@5D#`$%&A=YT@$+"P$6 +M,CH3"B@```L!#MT%$""1`P),(@`$#`*7`U!Y(&-L;Q`.`)4I071R>2#2*P`> +M!R)T;X`<`P,T("!SS`@`8V(`P!@!DB(!EQ91(&ES"@FF!`D.`G(@9FEN:7-H +M.@$!`@T`Y@P$E0``E`$37^45`*`'L'=O0:70@:&5L +M9"!OPT,`J`4"F@``81L!J@``O34`A2H"%R(`^1T@=6U!,`!\%0)<#@3^!@&< +M0P#Q$&`@8G)E86M**@#K#@#Z+`$8'@#Z,`'X`@2?``%@`!!?&0$69?DT`)8. +M`*@``NXL$&AR#`$N'8!S;VYA8FQY(+D!`!(5`I<-`,DU`*8<%WF"$X%3:V5L +M971A;'P+!HP(`5T'`^P!!@(%"^P!&C'L`08H`%!&;&5S:,D7`'(6$&];,!%R +M:Q,`?0("?@$@+F.\`1%AP`008[T,`>TC`.,-`!0E(6-H&P`C:&5_&B`@;MX" +M`2D!$6$A(`'*70)I`@`D`6(\A`CH["@E3 +M``&:"1)WQDX`R0L`7P,#>P("[`,"D@$0;E,R`,QH`'0#!8T.,71O=>P"`$P% +M`()%`V`!%3'A$0O^``R``N`4`GQ`$`2(*^0H!$`0!)`T)-3(!W0@$64<`0`4,XP`'"`0**0``M`8! +M[!$0;BY($6X]+0!^&@12``5N`0Q2`!8TP@(!4@`%2Q($_!]``!_ +M+P%\+0`9`@"8'@$0-`1<*`)I``#D``(_`@#$50*+)P4H`0'J`P0`%P#8!0DZ +M"2)T;P@]!(@!!3<`#(@!![D%"H@!$4@-!P1'#2!S.Y`-$&70!&!N=7@O9G-M +M#0*X"0+B``&Y"`BK&0`-.#%E65T>5,#5S0!I@$C=&\R%@"A"@#-%@"" +M$A`B^0%R(&-H96-K(H4&!%PD`T<)"Y@!!V$!`",%`E$7%W/$24%)3$5$H@H! +M=``!M64`X0(`+04"+TH!'0%`82!W89$T$&&8+0"//2-F9A@"$FG%A4''@!#5T%23A@"!@H@![<``6H$!V(& +M`%P!!BD``"L4`>T!`)X"`'@",7,@**(``'<%`.,"`E,+%RU790'I``#^!@/[ +M%P`F```^``G\&3)O=RG'`09K``+I,@0-#`2$&`"#/S`@;V:*;E)S:R!G;[0P +M`&8!`*(.(69FT0\#Q!`P.R!R5FP!`A$0:4@E$"AX``/4$@!)!`*]`@?]``B4 +M``#Z$D!I;F@`!-@HQ<&%XU0`%[0,`O18B=6ZE`2!E9%8D`38! +M#[D*`S3#`!@ +M*`:)'0%R!P"O`31'240G!0(,`Q)S``4#10,B8GD6`#%I;F<8`2%W:'0N`;<. +M`TX;`=U1`>8\4'1O;R!F3$(`PP<`SA:A;GD@<')I=FEL9;`:`9DI#V`2!#

    @?LFES +M(&QO;F``^'"@$!G@`'Q08!G@`%3P,10@E`5`@9&]W;A,.!UX!('=H,@$!)0`# +M$0@!3P`A8GE!``'.&5$@=&]O;*T$`#<&`N8H!2X``H4&`=L<-6UI>BP!!C4+ +M!VP``2P!!]D%`"P!`P="`C4"`=`H`5\1`/H&`=$H`8T&!D0``)P6`_17`J$` +M)&8@1@%!4$52331H("!ATQ5A97(M9W)A +M^#0!3@\P9F%C7@(688<0`",!!-L5#;`U$&`0@=`'Q#$&_=/@"$`@`M!0(R+@$D50:+=P)J"0$K +M6@/0!A!3(C509F5A='7?"`+V%Q!N>P$%RCL`J08!PQX'EP,"1Q4!<@$"<@!1 +M:6YV;VS4`03S`0'-!@0$50%1#0!3!@`&`@!<8A%)%!T38XH)`8(T$'AA"P`` +M`B!O9L\1XB!O=F5R:&%U;"!W:6QLPB8!N"\#,38"I`L!?@`"BBX&1P$'?'@" +MV1``SP("[AL*W0X(U``"S0`"1R8!G#L#=P<`'"40*/8X!+]*`+$$`8,!`'T" +M(V]F#"<09CT3"XD``,L?$',F!`,D``%&"`!#"`,V)`,!>05$#@,T!`&*``()`(P?!2<`0$)U;7`%*!!SFPL0 +M=&PV$3/C``"+)2!)+SQ6``@S(G)S,2`",1(2-M83`\P;`$$!049)3$4A)`/B +M$`\V``0&1P8"[P$$^2(#-A4`I`,`?%85>19/,6%L._L``?\*,6QO8[`1$6$] +M"C!M:6X:/A)UZ"H!JP85+<@!`=@U`G0>`SX5#!(!-S(N-3X)`'4>!BD`LT]U +M=&QI;F4@04))SD81!IH``-@)"^L`!Y<7`-H%`H$!`!L;,'-E*`!Y42!4:&5YEPD`3BP"C@X` +MZP(`9@\!2P``.BH59N(?"FP`P')E8W5RG%A%R50\P:V5EZ7$!KR=0;&4@=7!%!P!C-`(\``!V +M""!O;LLK0DQ$15)V`*)354U-05))15,*_1`"K04/9`,`&C$A`0,A(Q`V60X( +MF24`5A<@;F1O`1)TV4,%B`\)EB,R(')E;G``RP`!-PT`"64@;W(('0(H$P!. +M`@5@\`V`)0=V]R=&AT`!1S$S@!Q081!D;5L"30$`VP50<&%C:V&72P<">`#8`1!EN`I`+F=Z"LQJ`&H3 +M`8<$`8H;$G/X%`?V!`#K!0+?#`*(.`-S,P#/`02.!0)[%A0Z>P/H!`5X<`A9_$2[^30(`&QLUVAD!O@$#]@$$ +MM1$)1T\`/@X$71D`'PL&7QD`NP4`1A,"M@0"'Q(` +M`P$I#Q!E7@D1>=T1`#T"!.Y#,7,@*`H(`BL<`A`*!AP``IX83#%-0BEQ`*!- +M87)C=7,@1V5I?0<`5AP`'P0`#/`'S#GAS;FEL +M+F%N=&)E87(N;W)G+S(P,#4O,#(O,#4O@@%`+6UI='YI!`\``%H:@')B96ET +M96XO2P`"RA<`9@<$[8H`!Q`"M0`-OA/$%+"!(4"U56"P@56YI>'=A&9I;&4``0!+X3`P,#8T-"``,#`P-S8U"``B,#(0`"(R +M,`$`_P<@,3(S-3,U-3,U,3(@,#$R,#(S`"`PEP!+`@(`KW5S=&%R`#`P8W4' +M`0M2,!46%C="!S8`"A(&1E;6]N4$`(&EN^``(M@)A:6YF;W)M&@00 +M(+@&!+T"\`E.15=3("T@:&EG:&QI9VATP`"-E)ZT``R0$`),``$X`]0$N86TL(&%C;&]C86PN;30L +MX0!`92YA8_\```(`$BU4`"1T;Z@`#*($LBP@;VYL>2!N965D?``Q;6%I]@$C +M97)<`05P`"1I;F0`\@,N:"YI;@H)+2!T96UP;&%T97-G`!%B-`(!9@$39;4` +M<`H*1W5I9&6V`AA$5`8$T@$"=0`!MP&R'!L +M@P(#+P,`0@$"(0`$F@,#,P``B`0/-``+`"(`##4`+V%T-``,*&%T,P`&`0:` +M+C,@9VEV97/?!H!O=F5R=FEE=_,"`*``!+L%$&%Q!3!W:&^1`B,J(-D'A5]R +M96%D+C,L$```T04=91$`45]D:7-K%@`"?@<(/@`#'```F0`0=E\!`K<"865D +M(&-A;(D'$'/4!D%N8V5SK0(`DP``=0``%P(`^00!<0!8($%027.7`'-E;G1R +M>2XS30`"]P,2(FL#!:L``20`4"(@=71II`59(&-L87-$``'O!49N86QSG0!@ +M]!;!I;@IA(&YU;6)E`D09BP``;<&42H@1TY5 +M=0$"N@$F("@$"P`:`$%L;VYG4`9B;F%M97,L$```!0L3(!$``&,`4G-P87)S +M?`(AB,``!DT%``)"`$```I58W)E +M873/``%U!`\&`0("J@,#OP,"O`(/'P,8,")R9:`-46-T960B1P,"3P#$+"!W +M:&EC:"!W:6QLB@`!5@`%R@%A(&5X8V5P0`40"EL)`VD"42!T:&%T0PXQ:7)E +M40`!\P,!R@(@("A3"@$T!`"$`0,S!`#T`V`L(&5T8RGO"P+Z`P"I`@8B!`&& +M`0+:``_(`PIA(FYE=V,BFP,!,P`G0<280D!`BL`(2!B-PEQF4@'!L +M:6-I=&S9"4!V;VMEO!(!ZP`!?PH#SA$@("C2$"4@8?L*`*D`("!AZ0`!)Q`" +M+0`(S0`4;Y4(<"DL(&ET('=P`$$@9V5T&1,!70H`I`0W($EN;@`W+"!IG@`! +M40$#FP`B96[)`0P,1<#4`T6%T979E`!,@%1``:A`` +M"@$`/06#;B!I=',@(D#E`!(BO0012!F4X.``P1$2(A`0!:""`L +M(E`(H"P@8V%P86)I;&D2%`8#`07Q``+S#P&W!`CV!0&7`8`@:6YD:79I9&P. +M`&@%(6EEA`$`.A("0@`$K`4`-@$A=&^L#3!D8737```%#A8Z+@$"R`D`P@`2 +M8>P"`,D*`2L`,VEN("4&EV92!E +M0A0``/$1;G1R>2!B90H@("!I;F1E<&5N9&5N="X@(%1H97)E(&$$`/`9=&EC +M;&5S(&]N('1H92!L:6)A'1E;F0L`/(6+@H*("H@3VX@F4@;V:(`0"S`1`M=@!A960@8FEN/0`P(&ENA`#A +M96YV:7)O;FUE;G1S('=N`F!T:&%T(&W8`2)R<^D!!3`"`WD"H7)A3X`!8P``+$!\09P7,N"E)%041-12X`"!0'T6)U;F1L92X*"E%U97/Z +M`J`_("!)3``!(`1!HN`*# +M9F]R(&]N9V]8!Q@@9`!P9&5V96QO<#P%<2P@:6YC;'6]!4!D;V-U%``087<` +M$"Q8!P!Q```Z`"%N:UT!`%T`!G,`4"!M86EL!P)";&ES=*`#,"H@5)D!`>H& +M0&%N(&FW`!`L(00!_``!#P"A('1R86-K97(@8F-A="P@8@<`$G@'``!)`0"2"0`G`%`J(&5X84D`0',Z(%,R`U1S +M;6%L;!4`!#X!`%(#(6%T'`@@;6'F!"!N9-`",69U;"\"!D4`$"]#"@&%`1%A +MXP%186-T('-@`+`@9&5M;VYS=')A=+\`!,GK0`#9P$`DP``3@#P`"YA;2P@ +M86-L;V-A;"YM-`D-`^T`,"YA8_\```(`$"VB`@"?``2H``RB!&$L(&]N;'G7 +M"P)\`#%M86GV`2-E7-T96TZ&@D"N`0A +M+C'!#`!A#`$W`0,O`P`+``(A``2:`P,S``"(!`\T``L`(@`,-0`O870T``PH +M870S``8!!B$N,[8+$'-E"H!O=F5R=FEE=_,"`*``!0H,`'$%,'=H;Y$"%"JD +M"H5?PH" +MMP(29:`,`%L$$'/4!A!N2PT`U@(`DP``=0``%P(`^00!<0`!<0H(EP`09<,/ +M(RXS30``[P0R92`B:P,%JP`!)``4(@L+62!C;&%S1``!'PE&;F%L`8`>P`( +M2PE`:&%R9!8,`3`&!%L!`4<``(X!86UO9&5R;H\``.@!`+P'<"!V87)I86Y( +M"0!$!+%M86YU86P@<&%G93@``+`0)')EI@``G@`!'0-7)V1O8R>]!9!I;@IA +M(&YU;6+R#!=FD0<#'@'7+@H*66]U('-H;W5L9*0+`"@!,6-O<'8&0&-O;6V> +M"`#.#1,B!0XR+F@BJ0`R:&4*7PQ!(&-O9'4!`!0`!.D&`W((`G\"(6UOU@P" +M6@4R("!0B@FR;&5T('5S"FMN;W<0`0&9!G!E2X`L2`H8FEG +M+65N9&EAU!%C;&ET=&QE$0`"^@#Q`DE33SDV-C`@0T0M4D]-(&EMMP*`*'=I +M=&@@;W#+`\!A;"!2;V-KU`P$3`%HW+5II<"8`V$UI8W)OFEP,A8`!'P! +M32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9-!0`"0@!```*`IP0!3H!`'4$ +M#P8!`@*J`P._`P*\`@\?`Q@P(G)EH`U18W1E9")'`P)/`,0L('=H:6-H('=I +M;&R*``%6``:0`"!E>"T4``("$`I;"0-I`E$@=&AA=$,.$&F6!2=A>,H"("`H +M?0`3AN97>U +M`P#P!`#]`@.?`0![``&'"0##%Q)E2@P`31%`:7)E;?8-$&EY!P/N$@(,`@,A +M&D%R96%DCQ@#N!0!#``080P!`M00`&@``CL`$66<%@`]`2%V9?P4#V0:____ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________]J4&EV97,*4!0``/`5"E1H92!L:6)R87)Y(&%LFEP +M,A8`!"8`32],6E<=`+%L>FUA+"!L>FEP+,<`+WAZ(P``&304``D(`95C86X@ +M8W)E873/`$]S(&EN!@$#`21E9-T`$2E%``"=``"<`H5"4T0@)V%R)U(``1X` +M>"=M=')E92>[`'A)4T\Y-C8P$P!:-RU::7`Y`#9805(1`$,*5VAE`P(`V`($ +M=0$1+`(#87)ED#`*4#`.<#]A)U2!S=')E86WM`>!S>7-T96TN("!4:&5R92P`\01N;R!D:7)E8W0* +M("`@`>-R86YD;VT@ +M86-C97-S+GD`!I<`\@)I4<`L$DG=F4@871T96UP +MQ`/@=&\@;6EN:6UI>F4@2!I;G9O:V4@82!PZP`@=6PW!*!E871U``%1`0.;`")E;LD!!RT``'P`"W$`*&1E$0`#Q@(1 +M+/```H``(FYEC@(`%@$`0`!B86=A:6YS1P*@8V]R7L#$7`U`-%A=&5V97(@8FQO8VMS\```[@2X'<70@82!T:6U7`W%O8!(71O(@`%H0!A="!O;F-EA0`A3VZ0 +M`QMEPP`"Y`(R<')O.@$!A0%18W1L>2W,``!(!E)U='!U=.\"`&`$\0-O8FIE +M8W0M2!B=69F97(@ +M)`@`90`$<@&%82!S;V-K970^`TEW:7-HN@3`P" +M`,D*`2L`,VEN(">D``,P``*,!!H`%,7=A;H@`$'0V!`5%`0!@``'Z"0".!S!S +M:RQ.`P-^!KEC;VYV96YI96YC9<`!`(D`,&UA:WD`D&ES(&5S<&5C:6X$`=`! +M`JH!`#H(,#H@(I,*#KL*$R*Y`B!L;#P!`N@"`*4'`!$#`L$%0"P*("#,!Q!P +MWP``;`0`E@`0(',*T"!S87ES+@I214%$346[!@?H!N$@8G5N9&QE+@H*475E +M<_H"H#\@($ES7!1`GH@1`9W)A;18"M``-G`0"3``!.`/``+F%M+"!A8VQO8V%L +M+FTT"0T#[0`P+F%C%P$``@`0+:("`)\`!*@``-D."*($$BP:#@#7"P)\`#%M +M86GV`2-EPH"MP(`A1(A86R)!V!S97%U +M96Y+#0#6`@"3``!U```7`@#Y!`%Q``%Q"@B7`'!E;G1R>2XS]!0`!`,!=`$2 +M(FL#!:L``20`%"(+"UD@8VQA=&%R +M+C54`0CQ!`4^$A%S8P0Q<&]PY0\#G`$`>`8`>P`(2PE`:&%R9!8,`3`&`J@! +M`X42`(X!86UO9&5R;H\``.@!`+P'<"!V87)I86Y("0!$!+%M86YU86P@<&%G +M93@``#$.`,X4`OH!`)X``:D!5R=D;V,GO06P:6X*82!N=6UB97*5`@:1!P,> +M`=%V,/"Q<`TTUI8W)O2)J +M%```\S4@=71I;&ET>2!C;&%S1X`<&QI8G)A#0#46-H86YG?@$W;6%T(0"P;V-T970M;W)I96X! +M`P!@`@$>`*%35E(T($%30TE)=`(!%``"4P`/,@`%84)I;F%R>2X`P"`H8FEG +M+65N9&EA;J(!8VQI='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I;;<"@"AW +M:71H(&]PRP/`86P@4F]C:W)I9&=E10!B2F]L:65T*0$![P$"20`U6DE0"0$# +M0`#P"G5N8V]M<')EB,``!DT%``)"`&5 +M8V%N(&-R96%TSP`!=00/!@$"`J\!`[\#`KP"#Q\#&,$B,H"4B`H9F]R-`0`A`$#,P0`]`-Q+"!E=&,I+F\!`/H# +M`*D"!B($`1<``MH`#\@#"F$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0%!`); +M`0&)``]9`P`*%@,S5VAE`P(`V`(#U`(2<^8%87)EF4@ +MP,1<#4`T6%T979E6QE(&%P<')OR`,`R0@"^@#@=&\@:&%V92!M +M=6QT:7`E``-3!`(!!`"Y"%4@;W!E;IX`4"`@8G-D(P2!B=6@-$B`D"`!E``!Z``#!`85A('-O8VME=#X#27=I#B)A;N@"`*4'`!$#`KH.0"P*("#,!Q!PH@`` +M;`0`E@`!I@[1('-A>7,N"E)%041-11(&!Q0'T6)U;F1L92X*"E%U97/Z`J`_ +M("!)3``!(`1!HN`(09K$/ +M,VYG;U@')B`@+`"`(&1E=F5L;W`\!0@9$02Z$0&L"!`LH@0`<0``.@`A;FM= +M`0!=``='`$!M86EL!P(P;&ESOQ`!G0`05)D!`.41`.!L30',Z(%,R`U1S;6%L;!4`!#X!`%(#(6%T'`@@;6'F!"!N9-`",69U +M;"\"!D4`$"]#"@&%`1%AXP$T86-T>Q-P9&5M;VYS=#D5(&YG/@``@`4&5`(# +M20`P8V]N0P)A.B`@5F%R[A-@:71E;7,@,P$`UP(B;64V%3)I'2(`"%P=6<0,"`B8S0&$2(D`P`X#"EO;$T`(`H*X0@& +MZP,!*0$`%@D`C@$/;0$!`+`,$'4]$P(0%R4*)[P`$R>M``,D!`"3``!.`/`` +M+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C_P```@`0+60"`)\`!*@``-D."*($ +M$BP:#@#7"P!9"U%Y(&UA:?8!(V5RK@$%<``D:6YD`($N:"YI;@H)+?0'(&QA +M5@\$NP`%A0`#M0!P"@I'=6ED9;8"$T0.&`*!`0/2`0)U``#S`0-3#Q`Z&@D" +MN`0A+C'!#`!A#`$W`0`]!@-X$P(A``2:`P,S``"(!`\T``L`(@`,-0`O870T +M``PH870S``>M`Q$SM@L`$!20(&]V97)V:65W\P(`JP`%P`L`<04P=VAOD0(4 +M*J0*A5]R96%D+C,L$``!^`@-$0!17V1I2XSHQ2!T:&ER9"!P87)T:65S.X,``P(`87!L96%S948``'L`\BET:&4@ +M875T:&]R2!Q=65S=&EO;G,N"@I4:&4@=&]P+6QE=F5L(&1I +M4$`(&EN^`"`92!F;VQL;W>V`'!I;F9O%#36%K94QIM`!(ZU```DP``3@#U`2YA;2P@86-L +M;V-A;"YM-"SA`$!E+F%C*P```@`2+50`)'1OJ```(`&`9&ES=')I8G5!`;(L +M(&]N;'D@;F5E9'P`,6UA:?8!(V5R7`$%<``D:6YD`/(#+F@N:6X*"2T@=&5M +M<&QA=&5S9P`18C0"`68!$V6U`'`*"D=U:61EM@*"1&]C=6UE;G2!`0#%`3)A +M;&QU``#S`?4*('-YM`_`$,R!G:79E2XS!`,!JP(2(FL#!:L``20`Z2(@=71I;&ET>2!C;&%S1`"6:6YT97)N +M86QSG0!@P$2+8($4W,N-2!D5@(#I@0@:6QV`]1R;6%T-50!"/$$4&%B;W5T +M&@$@P"`+"!I;F-L=62*`8%H87)D+71O+3`& +M`J@!$G-'``!!`&%M;V1E$D#(F5R60<#>`('(0"P;V-T970M;W)I96X!`P!@`@$>`*%3 +M5E(T($%30TE)=`(!%``"4P`/,@`%,$)I;LH$`$(`H"`H8FEG+65N9&GS!(-R +M(&QI='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I;;<"@"AW:71H(&]PRP/` +M86P@4F]C:W)I9&=E10!B2F]L:65T*0$![P$"20`U6DE0"0$#0``@=6Y."3!R +M97,G!W!OB,``!DT%``)"`$```I58W)E873/``%U!`\&`0("J@,#OP," +MO`(/'P,8,")R9?X(46-T960B1P,"3P#$+"!W:&EC:"!W:6QLB@`!5@`%R@%A +M(&5X8V5P0`40"EL)`VD"`A4,<7)E<75IP`#GP$`>P`!APD!HP`"2@P#"@,0;6L($&EY!Q%A+PD#*P`A +M(&(W"7%R96%D86)L``8`C`H!#``!+`L"!`$`:``".P!"96%C:#T!(79E4,`4&EN9&5PJ@`E;G0B`0`8"0`/#Q!C0@42;VP-!C4*5"!7:6MI4@PP:6YG +MR0`P:&]WFPP!LP,79)8*`BH!(4]N/P@`]PP">`8#`P$$S0`!<`!`;'=A>48! +M`-T!*F5DB@@"1P!P22=V92!A="T-`(P'`,$/D&EN:6UI>F4@2UV```S#`#W"!%IAP8`A`!P96YV:7)O;M<",7,@=Y`#`:`"$&W8`1-R +M6@,%,`(`6P`"?P`1>7L#$7`U`-%A=&5V97(@8FQO8VMS\```[@2X'<70@82!T +M:6U7`W%O8!(71O(@`%2@!2="!O +M;F-\$B)/;AP."\,``N0",G!R;SH!`84!46-T;'DMS`"2960@;W5T<'5T[P(` +M8`3Q`V]B:F5C="US='EL92!A<'!R;\@#`$,2`OH`X'1O(&AA=F4@;75L=&EP +M)0``(040=A(#0')E86W\"E4@;W!E;IX`$R`5$`!J$``*`0`]!8-N(&ET2!B=6@-$B`D"`!E``!Z``#-`H5A('-O8VME=#X#27=IP`2 +M8D(`!*P%`#8!(71OK`TP9&%TUP``!0X1.L$"`2X!`L@)`,(`$F'L`@!A`P$K +M`#-I;B`G`0"/`C-A9&2.`AAA]PP!UP<#'@]19FER>D` +M`,P``*,!!H`%,7=A;G\%$G0=#P-%`0!@```:!!!TC@A<"+```.P``!`,`2P+%1`G-Q,`)AD`%@)S82!F=6QL +M+98(F-%#A)B!P`2 +M>`<``'`$`)()`"<`%"I/&@]D&O__________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M________________________________________65`@("!T;U04``#R-B!B +M92!R96%D(&]R('=R:71T96X@=&\@86YY(&1A=&$@F-A="P@8@<`$G@'``!)`4!S=6-H)P!0*B!E +M>&%)`$!S.B!3,@-4 +M`0-)`#!C;VY#`O`".B`@5F%R:6]UP``7P%Q875T:&]R<\`%`1\&`?("``$% +M4"X*"E1HG0$P<"UL#`0#=@4P;W)Y,04P=&%I)`4)M@(B:6[6!#%I;V[K!02] +M`O`"3D574R`M(&AI9VAL:6=H='-'2(`#!P=71>`C`@ +M(F,T!A$B)`-I9"!T;V]L30`"5@$&ZP,`%`=!'!L@P(#+P,`0@$" +M(0`$F@,#,P``B`0/-``+`"(`##4`+V%T-``,*&%T,P`&`0:`+C,@9VEV97/? +M!H!O=F5R=FEE=_,"`*``!+L%$&%Q!3!W:&^1`A0J[`B%7W)E860N,RP0``&[ +M"`T1`%%?9&ES:Q8``GX'`X0)`3X``QP``)D`$'9?`0*W`F%E9"!C86R)!Q!S +MU`9!;F-E``&I`5 +M"`"X!!,B?P(R+F@BJ0`R:&4*7PP0(+`)`'4!`!0`!.D&`W((`G\"-&UOFEP/@$Q:6]N +M&`%=8GII<#(6``1D`4TO3%I7'0"B;'IM82P@;'II\+`OH#`*D" +M`&@1`HT``88!`MH`#\@#"F$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0%!`?. +M``]9`P`*%@,S5VAE`P(`&@T#U`(2<^8%87)E0<#[A("*P`A(&(W"7%R96%D86)L``8` +MC`H!#``!+`L"U!``:``".P!"96%C:#T!(W9E/10"0P!0:6YD97"J`"5N="(! +M`$0-``\/$&-"!1)O;`T&-0I4(%=I:VE2##!I;F?)`#!H;W?X``&S`Q!DK0$# +MV@`"*@$A3VX_"`#W#`)X!@#S#@!0!@/-``%P`%-L=V%YD``2<0`BT`",T`%&]S!'`I+"!I="!W<`!0(&=E="#2$@%="@"D!#<@ +M26YN`#(L(&F"%0&>``%1`0.;`")E;LD!!RT``'P`"W$`*&1E$0`#Q@(1+.4) +M`H```(T.`)8!`!8!`$``,&%G8?,/`5\*D6-O7L#$7`U`&)A=&5V97)X%Q%S\```[@ +M!#%FQF4@ +M6]U(&1O;B=TJ```M@#P)&EC +M:71L>2!I;G9O:V4@82!P87)T:6-U;&%R(&9E871U!E('-O;64@=71I;&ET>3X`!8P``+$! +M\09P2!D8737`%9UP"`&$#`2L`,VEN("X`0!V``*4`0```P&3``7+`0#3``.C`0:`!3%W86Z(`!!T-@0# +M-@(!6P,`'P$`N@!09&ES:RQP`P/$`;EC;VYV96YI96YC9<`!`(D`,&UA:WD` +MD&ES(&5S<&5C:6X$`=`!`JH!\P=.;W1E.B`B<&%X(&EN=&5R8VAA;F=EGP43 +M(KD"(&QL/`$"Z`(09+X!`/T%`8T&D"P*("`@9&5S<*(``&P$`)8`\`,@;F%M +M92!S87ES+@I214%$344N``?H!N$@8G5N9&QE+@H*475E<_H"H#\@($ES`<``$D!`)()`"<`4"H@97AA20!`8$(&YDT`(Q9G5L+P(&10`0+T,*`84!$6'C`5%A8W0@`0-)`#!C;VY#`O`".B`@5F%R:6]UP``7P%Q +M875T:&]R<\`%`1\&`?("`DT'$`J(!E!T;W`M;`P$`W8%`#`'`4$`$&GD!@FV +M`B)I;M8$`'$+`.L%!+T"\`).15=3("T@:&EG:&QI9VAT2XS30``[P0R92`B +M:P,%JP`!)``4(@L+62!C;&%S1``!'PE&;F%L`8`>P`(2PE`:&%R9!8,`3`& +M!%L!`4<``(X!86UO9&5R;H\``.@!`+P'<"!V87)I86Y("0!$!+%M86YU86P@ +M<&%G93@``#$.)')EI@``G@`!'0-7)V1O8R>]!9!I;@IA(&YU;6+R#!=FD0<# +M'@'7+@H*66]U('-H;W5L9*0+`"@!,6-O<'8&0&-O;6V>"`#.#1,B!0XR+F@B +MJ0`R:&4*7PQ!(&-O9'4!`!0`!.D&`W((`G\"-&UO2X`L2`H8FEG+65N9&EAU!%C;&ET +M=&QE$0`"^@#Q`DE33SDV-C`@0T0M4D]-(&EMMP*`*'=I=&@@;W#+`\!A;"!2 +M;V-KU`P$3`%HW+5II<"8`V$UI8W)OFEP,A8`!'P!32],6E<=`*)L>FUA +M+"!L>FEP$P,O>'HC```9-!0`"0@!```*`IP0!3H!`'4$#P8!`@*J`P._`P*\ +M`@\?`Q@P(G)EH`U18W1E9")'`P)/`,0L('=H:6-H('=I;&R*``%6``:0`"!E +M>"T4``("$`I;"0-I`@)K%`!##A!IE@4G87C*`B`@*'T'`30$`(0!`T0$`/0# +M8"P@971C*>\+`OH#`*D"`&@1`HT``9L!`MH`#\@#"F$B;F5W8R*;`P$S`"=S +M:+```1(`#T8#8P0%!`?.``]9`P`*%@,S5VAE`P(`OP@#U`(2<^8%87)EP`! +MAPD!*Q4"2@P#"@,0;?8-$&EY!P/N$@(,`B$@8C<)07)E862/&`.X%`$,`!!A +M#`$"U!``:``".P`199P6`#T!(79E_!03>4,`M6EN9&5P96YD96YT(@$`1`T! +M>1D`0@42;VP-!K`+#V0:________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________________________________]H4&QL;W=I410``/$F;F<@8F5F +M;W)E(&5V86QU871I;F<@=&AE(&%R8VAI=F4Z"B`@*B!U=65N8V]D960@9FEL +M97,4``$*`/$"('=I=&@@4E!-('=R87!P97(;`/$!9WII<"!C;VUPFUA+"!L>FEP+"!A;F0@>'HC```9 +M-!0`]0<*5&AE(&QI8G)A"!I;G1E&-E<'0@9F]J`/$'("!E;G1R:65S('1H870@.`?$#;F%M97,L($%#3',L(&5T8RDND@"P +M3VQD($=.52!T87)=``2I``+*`/$$;V-T970M;W)I96YT960@8W!I;S4`ME-6 +M4C0@(FYE=V,B%0`G`'@G;71R964G +MNP!X25-/.38V,!,`6C2!S=')E86WM`>!S>7-T96TN("!4:&5R92P`\01N;R!D:7)E8W0*("`@`>-R86YD;VT@86-C97-S +M+GD`!I<`\@)I'!L +M86EN:6YGB0`P:&]W^``"]0``C@0#+``"*@$A3VZJ`!PL`P$#V0("<`!`;'=A +M>48!`-T!\@%E9"!A=71O;6%T:6-A;&QY1P"P22=V92!A='1E;7#$`^!T;R!M +M:6YI;6EZ92!S="L`L"!L:6YK('!O;&QUN`'A+B`@268@>6]U(&1O;B?L`0"V +M`/$":6-I=&QY(&EN=F]K92!A('#K`"!U;#<$(&5A60)`("AS=2\!&7,<`A!A +MZ0`'+0`'[P4`@`$"F0%P*2P@:70@=W``X"!G970@<'5L;&5D(&ENI`0W($EN +M;@`W+"!IG@`!40$#FP`B96[)`07L# +M$7`U`-%A=&5V97(@8FQO8VMS\``0:%<%(6ETH0!!66]U2X'<70@82!T:6U7`W%O8!(71O(@`%H0!A="!O;F-EA0`A3VZ0`QMEPP`" +MY`(R<')O.@$!A0%18W1L>2W,``!(!E)U='!U=.\"`&`$\0-O8FIE8W0M2!F)M96UO?<"!8P``0`" +M\05R;W9I9&4@96%S>2UT;RUU8<``J,!!H`%,7=A;H@`$'0V!`5%`0!@``'Z"0".!S!S:RQ. +M`P-^!KEC;VYV96YI96YC9<`!`(D`,&UA:WD`D&ES(&5S<&5C:6X$`=`!`JH! +M`#H(,#H@(I,*#KL*$R*Y`B!L;#P!`N@"`*4'`!$#`L$%0"P*("#,!Q!PWP`` +M;`0`E@`0(',*T"!S87ES+@I214%$346[!@?H!N$@8G5N9&QE+@H*475E<_H" +MH#\@($ES7!1`GH@1`9W)A;18"=&%R+C54 +M`0CQ!`4^$A%S8P0Q<&]PY0\#G`$`>`8`>P`(2PE`:&%R9!8,`3`&!%L!`4<` +M`(X!86UO9&5R;H\``.@!`+P'<"!V87)I86Y("0!$!+%M86YU86P@<&%G93@` +M`#$.`,X4`OH!`)X``1T#5R=D;V,GO060:6X*82!N=6UB\@P79I$'`QX!URX* +M"EEO=2!S:&]U;&2D"P`H`3%C;W!V!D!C;VUMG@@`N`03(@4.,BYH(JD`,FAE +M"E\,02!C;V1U`0`4``3I!@-R"`)_`C1M;W*C`E)S+B`@4(H)LVQE="!U=H+ +M`#L'`2,)"=H1`,$",&5C=)D#$60Y"0,<`@>F%@"E`0!0!0)!%0:J"R8@*`0+ +M`%L5#"`6`1````4+`;X+$G,W`E)S<&%R\6`2T5`A``#XH,`P4P`T&-P:6\N-2P@;71R964)``!O`/(*=&%R+C4@<')O=FED +M92!D971A:6QE9"!I;E(`D&EO;B!A8F]U=$T`('-EN`"#<&]P=6QA3`1!F+`"A#0#46-H86YG +M?@$W;6%T(0"P;V-T970M;W)I96X!`P!@`@$>`*%35E(T($%30TE)=`(!%``" +M4P`/,@`%84)I;F%R>2X`P"`H8FEG+65N9&EA;J(!8VQI='1L91$``OH`\0)) +M4T\Y-C8P($-$+5)/32!I;;<"@"AW:71H(&]PRP/`86P@4F]C:W)I9&=E10!B +M2F]L:65T*0$![P$"20`U6DE0"0$#0`#P"G5N8V]M<')EB,``!DT%``)"`&58V%N(&-R96%TSP`!=00/!@$"`J\!`[\# +M`KP"#Q\#&,$B,H"4B`H9F]R-`0` +MA`$#,P0`]`-Q+"!E=&,I+F\!`/H#`*D"!B($`1<``MH`#\@#"F$B;F5W8R*; +M`P$S`"=S:+```1(`#T8#8P0%!`);`0&)``]9`P`*%@,S5VAE`P(`V`(#U`(2 +M<^8%87)EF4@P,1<#4` +MT6%T979E6QE(&%P +M<')OR`,`R0@"^@#@=&\@:&%V92!M=6QT:7`E``-3!`(!!`"Y"%4@;W!E;IX` +M4"`@8G-D(P2!B=6@-$B`D"`!E``!Z``#!`85A +M('-O8VME=#X#27=I#B)A +M;N@"`*4'`!$#`KH.0"P*("#,!Q!PH@``;`0`E@`!I@[1('-A>7,N"E)%041- +M11(&!Q0'T6)U;F1L92X*"E%U97/Z`J`_("!)3``!(`1!HN`(09K$/,VYG;U@')B`@+`"`(&1E=F5L;W`\ +M!0@9$02Z$0&L"!`LH@0`<0``.@`A;FM=`0!=``='`$!M86EL!P(P;&ESOQ`! +MG0`05)D!`.41`.!L30',Z(%,R`U1S;6%L;!4`!#X!`%(# +M(6%T'`@@;6'F!"!N9-`",69U;"\"!D4`$"]#"@&%`1%AXP$T86-T>Q-P9&5M +M;VYS=#D5(&YG/@``@`4&5`(#20`P8V]N0P)A.B`@5F%R[A-@:71E;7,@,P$` +MUP(B;64V%3)I'2(`"%P=6<0,"`B8S0& +M$2(D`P`X#"EO;$T`(`H*X0@&ZP,!*0$`%@D`C@$/;0$!`+`,$'4]$P(0%R4* +M)[P`$R>M``,D!`"3``!.`/``+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C_P`` +M`@`0+60"`)\`!*@``-D."*($$BP:#@#7"P!9"U%Y(&UA:?8!(V5RK@$%<``D +M:6YD`($N:"YI;@H)+?0'(&QA5@\$NP`%A0`#M0!P"@I'=6ED9;8"$T0.&`*! +M`0/2`0)U``#S`0-3#Q`Z&@D"N`0A+C'!#`!A#`$W`0`]!@-X$P(A``2:`P,S +M``"(!`\T``L`(@`,-0`O870T``PH870S``>M`Q$SM@L`$!20(&]V97)V:65W +M\P(`JP`%P`L`<04P=VAOD0(4*J0*A5]R96%D+C,L$``!^`@-$0!17V1I2XSHQP#R*71H +M92!A=71H;W)S('=I=&@@86YY('%U97-T:6]N'2(`#%P=70I`/D#(F-M86ME(B!B=6EL9"!T;V]L30`"5@$&-0$! +M*0$Q(&EN3`$/;0$!,&%R91`"$F3:`35E"B>\`!,GK0`#9P$`DP``3@#U`2YA +M;2P@86-L;V-A;"YM-"SA`$!E+F%C_P```@`2+50`)'1OJ```(`&`9&ES=')I +M8G5!`;(L(&]N;'D@;F5E9'P`,6UA:?8!(V5R7`$%<``D:6YD`/(#+F@N:6X* +M"2T@=&5M<&QA=&5S9P`18C0"`68!$V6U`'`*"D=U:61EM@*"1&]C=6UE;G2! +M`0#%`3)A;&QU``#S`?4*('-Y`?$#+@H*66]U('-H;W5L9"!A;'-O(@(! +M3``Q8V]P=@8R8V]M6P%#:6X@(KT",BYH(JD`@&AE"G-O=7)C+P`19'4!`!0` +M!.D&`YH#`G\"-&UO<$",&5C=)D#$635``,<`@7"!A!F+``!MP91*B!'3E5U`0*Z`28@*+D! +M`!H`06QO;F=5`F)N86UE'1E;J+``-J`0`9`]$J +M(%!/4TE8('5S=&%R6P`"$``P<&%X20,B97)9!P-X`@@` +M`0H``EP)HE)032!WFEP/@$Q:6]N,`!=8GII<#(6``1D`4TO +M3%I7'0"B;'IM82P@;'IIU`P#P!`![``.?`0![``&'"0&C``)*#`,*`Q!M +M:P@0:7D'$6$O"0,K`"$@8C<)<7)E861A8FP`!@","@$,``$L"P($`0!H``([ +M`$)E86-H/0$A=F5S`Q-Y0P!0:6YD97"J`"5N="(!`!@)``\/$&-"!1)O;`T& +M-0I4(%=I:VE2##!I;F?)`#!H;W>;#`&S`Q=DE@H"*@$A3VX_"`#W#`)X!@,# +M`03-``%P`$!L=V%Y1@$`W0$J962*"`)'`'!))W9E(&%T+0T`C`<`P0^0:6YI +M;6EZ92!S#@T28U((07!O;&R4#5$N("!)9O4(4&1O;B=TJ`"097AP;&EC:71L +MV0EB=F]K92!A^@\18W\*,69E830+,"AS=2\!!?L*`*D`("!A00`!)Q`"+0`( +MS0`4;_D(<"DL(&ET('=P`'$@9V5T('!UG`T0:7H+1R`@26YN`#``%1 +M`0.;`")E;LD!!RT``#X`"W$`*&1E$0`#Q@(1+/```H```(T.`)8!`!8!`$`` +M(&%G`PX"4`.18V]RF5H!P*(`5!A;&QY+78``#,,`/<($6F'!@"$`'!E;G9IP,1<#4`T6%T979E2W,`))E9"!O=71P=73O`@!@!/$#;V)J96-T+7-T>6QE(&%P<')OR`,`0Q(" +M^@#@=&\@:&%V92!M=6QT:7`E```A!1!V$@-`4X.``P1$2(A`0!: +M""`L(E`(H"P@8V%P86)I;&D2%`8#`0"_``'Q``+S#P$_#@CV!0&7`8`@:6YD +M:79I9&P.`&@%$6E""`![`!)B0@`$K`4`-@$A=&^L#3!D8737```%#A$ZP0(! +M+@$"R`D`P@`28>P"`&$#`2L`,VEN("#U%F +M:7)S=)("`*8!$6%P$A%O61$`]@`6+G0``]D#`J#B)A;N@"`*4' +M!C0*0"P*("#,!Q!PYP$`;`0`E@`!I@YS('-A>7,N"B05$6:X#01Q%K0@8G5N +M9&QE+@H*41$6H#\@($ES%E2!F +M:6QE+B`@66]U(&-A;B!A;'-O(')E860@86X@96YT6]U('=A +M;G1$`!)T70`2+ST``&``,&EE'1E;F1E9#@!`B(`D"P*("`@9&5S<-\`0'=H8726`/`#(&YA;64@8$(&YDT`(Q +M9G5L+P(&10!1+VUI;FF%`1%AXP%186-T('-@`+`@9&5M;VYS=')A=+'!L@P(# +M+P,`0@$"(0`$F@,#,P``B`0/-``+`"(`##4`+V%T-``,*&%T,P`&`0:`+C,@ +M9VEV97/?!H!O=F5R=FEE=_,"`*``!+L%$&%Q!3!W:&^1`A0J[`B%7W)E860N +M,RP0``&["`T1`%%?9&ES:Q8``GX'`RH)`3X``QP``)D`$'9?`0*W`F%E9"!C +M86R)!Q!SU`9!;F-EP$2+8($4W,N-2!D5@(`G@419?L#`/(`Q&UA=',@``&I`5"`"X!!,B?P(R+F@BJ0"`:&4*`D09BP``;<&42H@1TY5=0$"-0(F("@$"P`: +M`$%L;VYG50(`K0LB+``-J`0`9`]$J(%!/4TE8('5S=&%R +M6P`"$``/B@P#!R$`L&]C=&5T+6]R:65N`0,`8`(!'@"A4U92-"!!4T-)270" +M`10``E,`#S(`!6%":6YAFEP,A8`!&0!32],6E<=`*)L>FUA+"!L>FEP$P,O +M>'HC```9-!0`"0@!```*56-R96%TSP`!=00/!@$"`JH#`[\#`KP"#Q\#&#`B +M&-E<$`% +M$`I;"0-I`E$@=&AA=$,.,6ER95$``0$0`?P(-F5A;;4%`A$+<"X@(%1H97(T +M$2`@;M82,7)E8S`1`]\(`),$02!I;BVW#X(@;6]D:69I8^4,\@%OP`!APD!HP`"2@P`31%`:7)E;?8-$&EY!P/N$@(K`"$@ +M8C<)<7)E861A8FP`!@","@$,``$L"P+4$`!H``([`$)E86-H/0$A=F5S`Q-Y +M0P!0:6YD97"J`"5N="(!`$0-``\/$&-"!1)O;`T&-0I4(%=I:VE2##!I;F?) +M`#!H;W?X``&S`Q!DK0$#V@`"*@$A3VX_"`#W#`)X!@#S#@!0!@/-``%P`%-L +M=V%YF4@'!L:6-I#16":6YV;VME(&'Z#Q%C?PH# +MSA$@("C2$"4@8?L*`*$!("!AZ0`!)Q`"+0`(S0`4;W,$<"DL(&ET('=P`%`@ +M9V5T(-(2`5T*`*0$-R!);FX`,BP@:8(5`9X``5$!`YL`(F5NR0$'+0``?``+ +M<0`H9&41``/&`A$LY0D"@```C0X`E@$`%@$`0``P86=A\P\!7PJ18V]RP,1<#4`8F%T979E2X'$'2B%R%I;5<# +M<6]R(&UM87`I`0!>$P'Y%@([`P"V`A!GPA<0:2(3`2(`!:$``.,3(6-EA0`A +M3VZ0`QMEPP`"Y`(R<')O.@$!A0$`FA"9"!O=71P=73O`@!@!/$# +M;V)J96-T+7-T>6QE(&%P<')OR`,`@0L"^@#@=&\@:&%V92!M=6QT:7`E```A +M!1!V$@-`:89`@4.%CHN`0+( +M"0#"``]D&O__________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M________________________:E`*("H@3U(4``#XNFX@2!I +M;G9O:V4@82!P87)T:6-U;&%R(&9E871U!E('-O;64@=71I;&ET>3X`!8P` +M`+$!\09P2!D8737`%9U +MP"`&$#`2L`,VEN(""!I;G1E7,N"E)%041-15``1"!L:6)M`=%B=6YD;&4N"@I1=65S^@*@/R`@ +M27-S=65S/U(`UBH@:'1T<#HO+W=W=RXX`$`N;W)GDP``2`$0:+@"L&9O`<``$D!0'-U8V@G`%`J(&5X84D`0',Z(%,R`U1S;6%L +M;!4`!#X!`%(#(6%T'`@@;6'F!"!N9-`",69U;"\"!D4`$"]#"@&%`1%AXP%1 +M86-T('-@`+`@9&5M;VYS=')A=+P`"-E)ZT``V7-T96TZ&@D"N`0A+C'! +M#`!A#`$W`0,O`P`+``(A``2:`P,S``"(!`\T``L`(@`,-0`O870T``PH870S +M``8!!B$N,[8+$'-E"H!O=F5R=FEE=_,"`*``!0H,`'$%,'=H;Y$"%"JD"H5? +MPH"MP(2 +M9:`,`%L$$'/4!A!N2PT`U@(`DP``=0``%P(`^00!<0`!<0H(EP!S96YT=H+`#L'`2,)"=H1`,$",&5C=)D#$60Y"0,<`@5X"1!F!A(! +MMP91*B!'3E5U`0+4!B8@*`0+`!H`(VQOO`4`K0LB+``-J +M`0`9`[$J(%!/4TE8('5S=+`1!!``#XH,`P%\``(Q`+!O8W1E="UO\!`DD`-5I)4`D!`T``('5N +M3@D`[!,`UA!@FEP/@$@:6]/$WTJ(&)Z:7`R%@`$?`%-+TQ: +M5QT`HFQZ;6$L(&QZ:7`3`R]X>B,``!DT%``)"`$```H"G!`%.@$`=00/!@$" +M`J\!`[\#`KP"#Q\#&#`B,H"("`H?0?P(-F5A;;4%`A$+!8@4 +M0&ES(&[6$C%R96,P$0/?"`"1`D$@:6XMMP^"(&UO9&EF:6/E#)%O`3AN97>U`P#P +M!`#]`@.?`0![``&'"0$K%0)*#`,*`Q!M]@T0:7D'`^X2`BL`(2!B-PE!FEP,A8`!"8`32],6E<=`/\#;'IM82P@ +M;'II<"P@86YD('AZ(P``&304`/$R"E1H92!L:6)R87)Y(&-A;B!C&-E<'1_`/$*"B`@ +M("!E;G1R:65S('1H870@$ +M`?$#;F%M97,L($%#3',L(&5T8RDND@"P3VQD($=.52!T87)=``2I``+*`/$$ +M;V-T970M;W)I96YT960@8W!I;S4`ME-64C0@(FYE=V,B%0`G`'@G;71R964GNP!X25-/.38V,!,`6C0`&EP#R`FES(&1E$N("!)9B!Y;W4@9&]N)^P!`+8`\0)I8VET;'D@:6YV;VME(&$@<.L` +M('5L-P0@96%9`D`@*'-U+P$9``%1`0.;`")E;LD!!RT` +M`'P`"W$`*&1E$0`#J@`1+/```H``(FYEC@(`%@$`0`!B86=A:6YS1P*@8V]R +MP,1<#4`T6%T979E2!B=69F97(@)`@`90`$<@&%82!S;V-K970^`TEW:7-H +MN@3`P"`,,)`2L`,VEN("0"0:7,@97-P96-I;@0!T`$"J@$`.@@P.B`BDPH.NPH3(KD"(&QL/`$" +MZ`(`I0<`$0,"P05`+`H@(,P'$'#?``!L!`"6`!`@7,N"E)%041- +M1;L&!^@&X2!B=6YD;&4N"@I1=65S^@*@/R`@27-S=65S/U(`UBH@:'1T<#HO +M+W=W=RXX`$`N;W)GDP``2`$0:+@"@V9OB!$!GF-%#A)B!P`2>`<``$D!`)()`"<`4"H@ +M97AA20!`8$(&YDT`(Q9G5L +M+P(&10`0+T,*`84!$6'C`5%A8W0@T/4'1O +M<"UL#`0#Q0P`,`0&";8"(FENU@0`=`P`ZP40<],-\`4@*B!.15=3 +M("T@:&EG:&QI9VAT'2(`")P==8-(")C-`81(B0#`#@,*6]L +M30`@"@K>!P;K`P$I`0`6"0".`0]M`0$`^0<@=7/="@#:`31E"B>P`"-E)ZT` +M`V!Q(M@@13``$=`U`=\!`DD`#QX78P\+%P#3 +M36EC4P`T&-P:6\N-2P@;71R964)`/(. +M86YD('1AP$R+F@BJ0"`:&4*2!E2QN``/2`>`@875T;VUA=&EC86QL>68!065C='.H``#5``,<`E!O +M;&QO=Y,!$&8L`*!S.@H@("H@1TY5^`$`J`!6;6%T("BY`0`:`$%L;VYG50)B +M;F%M97,L$`!3;&EN:R`1``"T`5)S<&%R'1E;J+``-J`1%S2P"W4$]325@@=7-T87(0 +M`.%P87@@:6YT97)C:&%N9WX!-VUA="$`L&]C=&5T+6]R:65N`0,`8`(!'@"A +M4U92-"!!4T-)270"`10``F,`#S(`!6%":6YAB,``!DT%``)"`&58V%N(&-R +M96%TSP`!=00/!@$"`NP"`[\#`KP"#Q\#&,$B,H"4B`H9F]R-`0`A`$#,P0`]`-Q+"!E=&,I+F\!`/H#`*D"!B($ +M`1<``MH`#\@#"F$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0%!`);`0&)``]9 +M`P`*%@,S5VAE`P(`V`(#U`(2<^8%87)EF4@7L#$7`U`-%A=&5V97(@8FQO8VMS\```[@2X' +M<70@82!T:6U7`P!K"S%M87#X`C!E;G21!@/0`@%1`T!G:79EY@$A=&\B``6A +M`&%T(&]N8V6%`"%/;I`#&V7#``+D`C)P`%`@(&)S9",'(75SO`$`/06#;B!I +M=',@(D#E`!(BO01&2!F4X.475S92`B(0$`6@@@+")0"'`L(&-A +M<&%B00`!]@("9@81954"`?$`864@05!)P" +M`,D*`2L`,VEN("#U%F:7)S=)("`*8!(&$@ +M0P41;U`'`/8`%BYT``/9`P*G`0"_``*<`0&%``:X`0!V``*4`0!*`P&3``(Q +M#R!L>60!`,P``*,!!H`%,7=A;G\%$G0=#P-%`0!@```:!!!TC@!L3 +M0',Z(%,R`U1S;6%L;!4`!#X!`%(#(6%T'`@@;6'F!"!N9-`",69U;"\"!D4` +M$"]#"@&%`1%AXP$T86-T>Q."9&5M;VYS=')*#0`.`R=O9EX!`TD`,&-O;D," +M83H@(%9AP``7P%C875T:&]R:1``EPT!\@(`P1,2+NT/4'1O<"UL#`0#Q0P`,`0&";8""',5`.L%`>X/\`4@*B!.15=3("T@:&EG:&QI9VAT\`!,GK0`#)`0`DP``3@#P`"YA;2P@86-L +M;V-A;"YM-`D-`^T`,"YA8_\```(`$"VB`@"?``2H``#9#@BB!!(L&@X`UPL` +M60L0>\%1FYA;'.=`!)S +M/@MA:6YS:6=H$08(F0<1)V<"!#<``&@1,'5C=+(#`*@`,&]P92L%`#0,"1X' +M$BU8"0]D&O__________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M________________________5E!C="!S85<4``#T4VUP;&4@9&5M;VYS=')A +M=&EN9R!U4$`,6EN'2(`#%P=70I`/D#(F-M86ME(B!B=6EL9"!T +M;V]L30`"5@$&-0$!*0$Q(&EN3`$/;0$!,&%R91`"$F3:`35E"B>\`!,GK0`# +M9P$`DP``3@#U`2YA;2P@86-L;V-A;"YM-"SA`$!E+F%C_P```@`2+50`)'1O +MJ```(`&`9&ES=')I8G5!`;(L(&]N;'D@;F5E9'P`,6UA:?8!(V5R7`$%<``D +M:6YD`/(#+F@N:6X*"2T@=&5M<&QA=&5S9P`18C0"`68!$V6U`/($"@I'=6ED +M92!T;R!$;V-U;65N=($!`,4!,F%L;'4``/,!]0H@'!L@P(#+P,`0@$"(0"#('!R;V=R86TS`$]C<&EO-``+`"(`##4` +M+V%T-``,*&%T,P`'K0/P!#,@9VEV97,@86X@;W9E2!A``"/ +M`&<@)V1O8R>]!;!I;@IA(&YU;6)E2QN``5H`S!U=&^3!@#_`A!Y9@$P96-TF0,19-4``QP"!<(&$&8L``&W +M!E$J($=.574!`KH!)B`HN0$`&@!!;&]N9U4"8FYA;65S+!``4VQI;FL@$0`` +M8P!A@``0H``EP)HE)032!WFEP/@$Q +M:6]N,`!=8GII<#(6``1D`4TO3%I7'0"B;'IM82P@;'IIU`P#P!`![ +M``.?`0![``&'"0&C``)*#`,*`Q!M:P@0:7D'$F$)`0(K`"$@8C<)<7)E861A +M8FP`!@","@$,``$L"P($`0!H``([`$)E86-H/0$A=F5S`Q-Y0P!0:6YD97"J +M`"5N="(!`!@)``\/$&-"!1)O;`T&-0I4(%=I:VE2##!I;F?)`#!H;W>;#`&S +M`Q=DE@H"*@$A3VX_"`#W#`)X!@,#`0/X``&("5!A;'=A>48!`-T!*F5DB@@" +M1P!P22=V92!A="T-`(P'`,$/D&EN:6UI>F4@@M'("!);FX`-RP@:9X``5$!`YL`(F5NR0$'+0``/@`+<0`H +M9&41``/&`A$L\``"@```C0X`E@$`%@$`0``@86<##A%T\0F18V]RP,B:67-#P%O`P/G"C%D=6.Y!5%E('-I>H,1`H@!4&%L +M;'DM=@``,PP`]P@1:8<&`(0`<&5N=FER;V[7`C%S('>0`P&@`A!MV`$3`!,@%1``:A``"@$`/06#;B!I=',@(D#E +M`!(BO0012!F@``S0*%82!S;V-K970^`TEW:7-HN@1$!L30',Z(%,R`U1S;6%L;!4`!#X!`%(# +M`Q,9(&UAY@0@;F30`C%F=6PO`@9%`%$O;6EN:84!$6'C`31A8W1[$P]D&O__ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________:%!C:&EV94<4``#P/2!W:71H;W5T"B`@(&9I0#P*FES(&5S<&5C:6%L;'D@96%S>2X*"B`J($YO=&4Z(")P87@@:6YT +M97)C:&%N9V4@9F]R;6%T(B!I<^```#,`\P!A;B!E>'1E;F1E9"!T87(B`)`L +M"B`@(&1E7,N"E)%041-12X`1"!L:6(3 +M`=%B=6YD;&4N"@I1=65SK@"@/R`@27-S=65S/U(`UBH@:'1T<#HO+W=W=RXX +M`$`N;W)GDP``2`$Q:&]MIP"`(&]N9V]I;F6H`)V%T:0`K871H`&ES:6UP;&6U`$!T;V]L,P$` +M0``#`@!R>F-A="P@8@<`$G@'``!)`4!S=6-H)P!0*B!E>&%)`$!S.B!3,@-4 +M2!F:6YDT`(Q9G5L+P(&10!1+VUI;FF% +M`1%AXP%186-T('-@`*$@9&5M;VYS=')A-04`#@,G;V9>`0-)`#!C;VY#`O`" +M.B`@5F%R:6]UP``7P%Q875T:&]R<\`%42!A;GD@\@(``050+@H*5&B=`3!P +M+6P,!`-V!3!O'2(`#!P=71>`C`@(F,T!A$B)`-I +M9"!T;V]L30`"5@$&ZP,`%`=!'!L@P(#+P,`0@$"(0`$F@,#,P`` +MB`0/-``+`"(`##4`+V%T-``,*&%T,P`&`0:`+C,@9VEV97/?!H!O=F5R=FEE +M=_,"`*``!+L%$&%Q!3!W:&^1`A0J[`B%7W)E860N,RP0``&["`T1`%%?9&ES +M:Q8``GX'`Q<(`3X``QP``)D`$'9?`0*W`F%E9"!C86R)!Q!SU`9!;F-EP$2+8($4W,N-2!D5@(` +MG@419?L#`/(`Q&UA=',@``&I`5=H+`#L'`2,)@&%U=&]M871I_P(0><$",&5C=)D#$60Y +M"0,<`@5X"1!F+``!MP91*B!'3E5U`0(U`B8@*`0+`!H`06QO;F=5`@"M"R)S +M+!````4+`;X+$G,W`E)S<&%R`*%35E(T($%30TE)=`(!%``"4P`/,@`%84)I +M;F%R>2X`P"`H8FEG+65N9&EA;J(!8VQI='1L91$``OH`\0))4T\Y-C8P($-$ +M+5)/32!I;;<"@"AW:71H(&]PRP/`86P@4F]C:W)I9&=E10!B2F]L:65T*0$! +M[P$"20`U6DE0"0$#0``@=6Y."3!R97/3!G!OU`P$3`%HW+5II<"8`V$UI +M8W)OB,``!DT%``)"`$` +M``I58W)E873/``$M"0\&`0("J@,#OP,"O`(/'P,8,")R9:`-46-T960B1P," +M3P#$+"!W:&EC:"!W:6QLB@`!5@`%R@%A(&5X8V5P0`40"EL)`VD"42!T:&%T +M0PX0:98%)V%XR@(@("@6!0$T!`"$`0-$!`#T`V`L(&5T8RGO"P+Z`P"I`@8P +M$`&&`0+:``_(`PIA(FYE=V,BFP,!,P`G0`&@`0`L!!0 +M97-I9VZP$D)O(&)EO@(`0`0!7@$X;F5WM0,`\`0`_0(#P`!APD!HP`" +M2@P`31%`:7)E;?8-$&EY!P/N$@(K`"$@8C<)<7)E861A8FP`!@","@$,``$L +M"P+4$`!H``([`$)E86-H/0$2=MT3$WE#`%!I;F1E<*H`)6YT(@$`1`T`#P\0 +M8T(%$F]L#08U"E0@5VEK:5(,,&EN9\D`,&AO=_@``K03`*T!`]H``O<3(4]N +M/P@`]PP">`8`\PX`4`8#S0`!<`!3;'=A>7-S""IE9(H(`D<`<$DG=F4@870A +M%0",!S!T;R`A$'!M:7IE('-TM0@"4@A0<&]L;'4B!P;D%$%D;VXG[`%P97AP +M;&EC:0T58&EN=F]K9;P2`>L``7\*`\X1("`HTA`E(&'["@"A`2`@8>D``2<0 +M`BT`",T`%&_Y"'`I+"!I="!W<`!!(&=E=!D3`5T*`*0$-R!);FX`,BP@:8(5 +M`9X``5$!`YL`(F5NR0$'+0``?``+<0`H9&41``/&`A$LY0D"@```C0X`E@$` +M%@$`0``P86=A\P\`7L#$7`U`-%A +M=&5V97(@8FQO8VMS\```[@!#%FQ6QE(&%P<')OR`,` +M@0L"^@#@=&\@:&%V92!M=6QT:7`E```A!1!V$@-`P",B!O9BL`,VEN("2!I +M;G9O:V4@82!P87)T:6-U;&%R(&9E871U`<``$D!`/X&`"<`4"H@97AA20!`4$`(&EN^``(M@(B:6X#"``0""!F:34!`'P`\`LJ($Y%5U,@+2!H +M:6=H;&EG:'1S(&]F(')E8P8"5&-H86YGH`*P0T]064E.1R`M('<3!P"Y"&)C +M86X@9&^?`#-T:&DI`*!)3E-404Q,("T@T`'2(`")P=28)<2)C;6%K92(D`P"D +M"2EO;$T``E8!!NL#`)0`07,@:6Y,`0]M`0$P87)E3@(29-H!-64*)[P`$R>M +M``,D!`"3``!.`/4!+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_```"`!(M5``D +M=&^H```@`0BB!+`L(&]N;'D@;F5E9,4($'G*!0'V`2-E%7W)E860N,RP0``#1 +M!1UE$0!17V1I +M=&%R+C54`0CQ!$%A8F]U4P4@"`"X!!,B +MO0(R+F@BJ0"`:&4*2R"```[!P$C"8!A=71O;6%T:?\"$'G!`C!E8W29`Q%D80T# +M'`(%>`D09BP``;<&42H@1TY5=0$"-0(F("@$"P`:`$%L;VYG4`9B;F%M97,L +M$```!0L3(!$``&,`4G-P87)S?`(A`@@;W#+`\!A;"!2;V-KFEP,A8`!'P!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC +M```9-!0`"0@!```*56-R96%TSP`!+0D/!@$"`JH#`[\#`KP"#Q\#&#`B&-E<$`%`+D% +M!&D"`M<1`$,.$&F6!2=A>,H"("`H%@4!-`0`A`$#,P0`]`-@+"!E=&,I[PL" +M^@,`J0(&(@0!FP$"V@`/E@,%`<@#82)N97=C(IL#`3,`)W-HL``!$@`/1@-C +M!`4$`EL!`8D`#UD#``H6`S-7:&4#`@"_"`/4`A)SY@5A?P(-F5A;;4%`A$+02X@(%1`%%-I4,`4&EN9&5PJ@`E;G0B +M`0!$#0'E%@!"!1)O;`T&L`M4(%=I:VE2#`,,$S!H;W=1#P*F!P!."`/:``N@ +M%03\!`#S#@!0!@/-``%P`$!L=V%Y1@$`W0$J962*"`)'``_0%__@"?H#$&,W +M!@`%&,)A=&5V97(@8FQO8VO5"@#N!S`@:70(!D(@66]UYQ,!Q`U`8F%C:T`# +M,69R93T/,'!A2X'<70@82!T:6U7`W%O2W,``"."5)U='!U=.\"`&`$H&]B:F5C="US='G@ +M&4%P<')OR`,`^10"^@!0=&\@:&$Y%D!U;'1IPQ,$J0`"`00`N0A5(&]P96Z> +M`!0@]`\A=7-U!Q%I(0AC:71S(")`/``2(KT$$',3&P7J!`,<`'`@:71S96QF +M4P$`?000+P(/8'1E;B!U7,N"@`!`/^)`#L7#Y\!30\`'@M1-S$Q-S4`'F$Q-3$U-3(`'B\U,0`> +M_U771F5B(#`Y+"`R,#$S.H<*D2`S+C$N,B!R93(3GF0*"DIA;B`R."D`(2=S +MJPM`=V5B!A(N3``N,3-,``%U`!LQ=0`/*0`&%S`I`&%$ +M96,@,#=2`$`R.B!)4AL!"`P("@4#T!0`[PP991H,`)T%`ML-`DX8`9`(A"`* +M3F]V(#$Q5``@062V&P:L(H-?7TU!0T]36!<-`(('.&EN(,01!-D/(G)EJ08` +M)P4`N`P2:P@','-T;TL.`+@B?PI/8W0@,C!K``4`.08`A@82=J43`@,,`S8` +M`[P!#Z$``"MGF]P5`%64V5P(#*!``VH`0+.&7%T;R!S +M965KD`I&@'5`@DX`P#*"C)I97-.``*:!&$Q.B!.97>:`PI(``0;`UES(%-&6`,% +M"S\`0$)U:6QK!0"Y`:)O;B!7:6YD;W=S(0$#YP4.2P$K,&%+`14P2P$P57!D +MN!5T`P,,RUS._@6"*$9`ADA$F_B'$!H87)D4P(E+W-;`E%B&0"5##!E;747&6D@8G)O:V5B`#`R+GAG!`!W +M$`&O)2%O9K(6<5541BTX(&AH`!)SF04%^P!`4F5F85D'`04/$%]R#B`H*7L: +M`"\-46-O;&QEB"$`XPT`2@\P;&4MJR(`W`<`YR@!EB(#+`$!D`P@;VPA`P,2 +M)!!S'Q\@=W(,`0-W`!(Q$`:!,3H@4W!L:71?#0(`!@`L`0&1!C!P87)N`@(> +M%P`T"`/``@":`Q%L^24";`(!QP`5,30#`X(#`L\AE`=V]R:V(!9')E='5R;JP<`)`B`2$/$&;N +M`@%9`7%A8F]R="@I1``&-04`M0$`>0`W%SM#.3`"`07@ +M`"9O;LT#`=P'!GP!$4;T!@`G`:)!25@L(%12538T]QJ@;W1H97(@<&QA=(4! +M$G/-!@+4`B$P.D`<`\T#`1T'`EP"H3`Z($Q(02],6DAC`P'J`S)L(#`U`B$P +M.OPM`!L:`Z,F!T,F$&5F!`'?$P*5!`$N`P+1$``)"S!TH2`-@48F5N(&-O<)01``X#`1X2!,@)`4$``XD%$#`(`@&R)P!X`'8@ +M36%C($]3J0(`/``'K@0!.@`#0@(D,#I0``?K``"J"0/]`A!S7@D"[@!4&D1%0*G!`/4 +M!P`:`0"4'0.-"@)C``:;``-=!`'?(080!00'`@0;`V!C(&-R>7#%!`+!#`&/ +M``/[!B$P.CT=`0("`"P&`A`$`"8#`$<%`BH``@4-$C``"`/4`Q(Z+@=`+6=I +M9`8``"H$02`M+74.`!!U#@`!!P4#,@X#P`%@4F5D+6)L8!8`_"(!E`<&_@$! +M&14@97)D`P,C`@!4!`#.`@!8*P%.``,)`P!*`F)I;FEM86RM``$3#7@@;&5G +M86-YM0#,O +M`G@5`,0#`#(=`I`%`W8(`[X!`+\'$F0K``"1(#EL9&5?"`!=&Q!LNP$`%0X! +M0"@A963+`P80`55296QA>`,"`,(%('-T7P;09F%I;'5R97,[(&UIF7'`P`M`0!Q`0-7!`!_&"%O;88'#%$``8X%4&YT-C1? +MS`L%``>@;V9F7W0L(&1E=@<`,&EN;P<`,'5I9`<``#\#$&<+``*<``7^!`08 +M*`'"$#9!0TQ%"0)U`!4QN@024SD#!C48`20!!28#`$0!$C`B!P%J!``&$0)\ +M)@.6`@<*"3$Q+G@-%P&,``:%`Q!2R`=%869I;PX)`54`!<,%$$'''0!6``?S +M(P4Q!2%L>2P/!/T"`EL`!;L!8$EN=&5G) +M``9"``+3`P`I`Y!F=71I;65S*"DX+F)#>6=W:6YK$@9%`0>'`78R+CQA`;&5A:U0!"!X!`$@`$G,S``5<`0!D``FUA+WAZ6P,#X0(`9P`$%B`)`@@"0`0` +MGP43>?(.`$D`$4C()"`@9_X2`D4``-@)!$$`0$]P96Z4)7`B9WIS:6`@)[``6)`D!!9&1IR0HP86P@2@!` +M-P)M(B%S98$#!+`=!),-!'4'85=!4DX*"1PK06ES(&/Z +M,Q5OPP<`U1U0861A<'2;."!N91PC,V%R>;L!"=\`55-T=61I8`L`E@`/2@`!-`E!;!$# +M``@!`%HA`5\``_40`/,``.D#,$1E8E\!L4)U9R`C-3$V-34.`?$.`*8$`+$H4$AUA,` +M2P$41:L>!]$(`8(`)&]N*Q8!\0P"]PM`;F]W"?P#`9<2`78,$G11``85!@#0 +M``.@"@8,#A!?*A4@>5\/!A!?;P8P*"D@6"X$[`\`00PQ+`H)2!R7!,@961S(`#/"P"])@!1 +M,#`L"@E4!`"`!P!:#0#B!@!A!0:^`P`\`R!T(",%"7$F`;L`!LHA(@H)?0`4 +M<^@OQ6)E(&UU8V@@96%S:>8-`H\/*RX@HC,`311":&4*"3$8`5\1"$(G%',] +M)P;1#P"#'`-Q`!(N_!`"MP80.$4$)&YY:Q8:+Z\#`HH6`+L!#_D#`@U)``J[ +M"0B[&0+W'`%*``1;`@+Y#!!CN@$@97)^)2ET;W89`$T&`'PT`@2US:7IE9`4/$G.*)3$@*A$)SAH`A@,/[A<"`!<-L2@I(&AAFEPEP2"_`0`P`"`@ +M82D`*RDNM@#@2F]E0,A +M(&*Q'`&[$P%-$P!7!B)A=$H`!9X'`<4(`AQ``-A"`FLK`)$I4F0@8G5GQ0(@ +M.L%`&P"!/P> +M"K`3``XT`,T``$8$`3,8!B,&`;X<`681`$LA!O8?`FD#`#\.``D)$V'=0W,B +M4V-O='0BW!80(%0```L*!9X#$VV#/A!SU`8$-0"22V5E'!L;P$0`&T6$&5D +M#0)M`0)E+95V97)F;&]WPP$_@D$V@Y0"@EP2P!$'26$`&#.%%E(&)O9(L] +M``8-`8D!`#8!,#L*"6T&$FG,$@#0`2%O=:T-P')A;F=E(&)E:&%V:2U/`$0. +M`0L,!!0[`9@)$7)R`0&K`0)],U$M3A+,&ER95<8!&@8,"-I +M9O4,!'@8`H9`.`K@-`=0/$"V!+C%E8V^!!5)L;V=I +M8[$5`C0`$',T``!.%0)/(@'V%`!V`0$8``);20*;%P-]`@;4"`E3`D0T+C$T +M>AY`9#L@:5P\`%)$`)@#`1X`&#,$0"()84H*`%,!`?`($&=+!1$O=B-@(&UI +M>'5PWRD&R!8"L0``P@D4:<0O(F0*[18`9P0"A"D!'@<2+L@?!N8.#*8`%3.F +M``*3&`7Y`@-V'0"=!A$L3`(`DP`2+)H`$"PL!`*>``$[`2!C8640$6*8"S%V +M97+;`P32)P&-`". +M``#3"P"!`&`@8VQA`B4&1E=FEC5@$! +MRR$!32(`B0H`2!@3(G`#&2*)"``6$`(U!D!N97=CM@("<0@#I``6.^0#`O$1 +M`%P"`6,$"$T!`#4"`!`A('1H2PL!>P`"G!LE.#I(#0)E#@-J)P!(`@2;`PDD +M$1PL6PT`.QH'004P26=NR@@$[`I"('-I>ND,`$,-`B@K`#0.$F&[(@#8"P#^ +M(14RC@`,7@(6,EX""BD``*@!(&)A4T$`58(`$D:,6=E=)H-`J4\`6(+!,U5`'$:`8X%13(N.2Z" +M`0(Z``!(`1)L5#$08A,9`=L+!^$/(B@MI0]`+7HI+*L#`"$/,0EO9JH-,')M +M85X2`)X?,F5S'!E +M-\4"%C'%`@HI`#!&:7BF00&U)0#H$P+X)`9A`0"G!`&Q"04]#P%J``(_*P]J +M``$,S!D"8006-X8(4#`N.2XPQ@<`@0<"SE,@=VFA%3-U?@=`70``Q`;$C>)!5!A(&-O=90<(V]FE@0'K28`Y04!?P`"J0\. +MIP`'\A4**```6P``J0,!IP`!!0`17VD!$%_?!"%B>=DQ`D4!`@"&!P8T4@2$`E`M+61I0H& +M%`!U86-L+`H)=.T!_P!386UU;&D@4W5O;6EN96Z,``T'/@D!_``%C``&/P+` +M3&%P;R!,=6-H:6YIU04`>E4!20(`3AP!54D`!0X!T@D!FB0#2@4`DP$@;&17 +M"0%5+@#Z&P1O!#!B=6?&!0$8``!``;!O9@H)(FQE;F=T:)X4D&5N9"(@9FQA +M9QX*!6$`$G,?!`96`0).``,"!!$@FP8!4@8!/@(`J08!+P0$-P`%\P,01J,! +M0"!C=71K`$!R96%L>0<`-```D0(`Z`42;AU(`0\!!38`"Q@(%C+:`@+$`0\I +M``46,2D`"E$`$4W_)@"X!D%S+"!R%Q@`E```P0*@9&]C+71O+6UA;C\.`WX' +M`'H!(`H)%``!NB0#.CL/]`4&!XD%"B@``G@``"4(`/$%`#(4!CP"`[H,4&-H +M:6QL!Q<+.P`03Y`&`-D0`/`"`O<'(B!A>U8@(&_I%P'8"P#Q#S%G:6Y\*2!O +M9L\&(PH)$P(!6!X"IQL"K%@"S0(#CQL`+1D`3P4"2C0`+5<`#P@2>88`!G,& +M$%0$!@,S```5`0`X!!-Y\Q``6!(`0@0`QB4`NR(#Y@D8.I@"`FT(`#4((&5X +MU!8`0D4$.``!YAXS,D="?R8S,51":`$"5CD-#`48,RX:`"T!!B@`$D,/"`(_ +M!R5U;E@G`LP.`%T5`7-#`-H$``,#`+(``"H!$"*:`0#Z$P##'T!N;VYEC@L% +M9!T!?@00;H`,#(O,V(#`7T``-@"`68( +M!M,#D$IA;B!00P`4,#`!`,`-D2`.L( +M,$=.55L!$"><*$%G+71AE`(&[UP`FP`U;W-E,@`!7QA`960@;2\B0'=A&%C=&QY"@EA*R``YA<@-$>T"`/@$@=H$0&=`0(;#@=G``!;`0!F``=#`E`H +M/CA'*>,`!3X"`-0``-P20V%S"@E&.`'M"T!)('!U\"\)C0(`(1`#)`$%&"\` +M3`$`P50!A``%+`<32=0(`=D+`-@'$&5_)P`!`U!N+6UA=&\%`!5=`-0^(6]R +M00R".R!)"@EH;W!(#9$@979E;G1U86P\)0'Q3``?`0`P"S)D92`G"@!#*`+. +M"0#.50,5/P)K#@R7!A@SEP8`J@`5,"X!($-O(QH0=9``!*T`!'8%`%P"`9@J +M$F7?``8U`!!.+4T!6%8`Y4``M`03+/<+`7`(,")(:>\*('DBM0$#3@`@+C$X +M"0'/#`"O`!0Q.0`#Y"$&7```F`<5>C0\`)<"D6EM;65D:6%T90T!`9`X,$5/ +M1M$J`(P?,'1R><\/`?X5!<,4`!$.,')E9V$F`8D+`.(/`%T%`-(D`!4``,\; +M`6X2$'B2%0):#P3+"P"=`R%O9H0``Z$"`&4(`+X[#Y$%!!@S:0<`*``#T!`0 +M-]`C`54!$TU''"`N8205`4X'`!($$B#'(!,O`P@$:A)#"@EA8_P!(61O*`!1 +M@,%1DL# +M#`H`QP5`*"D*"4L'`=$2`+4,$FUJ5B5I;I(+`Y@``P8=#GX#!RD(`)@`!B@` +M`:(X`88"`.D"`RL#4R`P+C,ZO#P&[A`165TG!`2*;L``NL]`GX2`!L\`PP"`SPP#G8`!V$-4D%U9R`S+R02-^,R`+,R +M`)D#!+P&`BL>`(,+(W,L7&,`J@4D86[/6P2`!40*"2A!K1<991L1`*HE(2XI +M;``#310!F`1`860@9QD+\0$Q+C$W("TM<&]S:7@@+2US22<$D@<2+C<`!3@, +M$U*S&F!S=6ED+W.+.00R$03O"T`[(&ET'00%=@0@"@E/&D!RQ,2(M+6`%%"W0`0,R!@&^)0"]*!5RF!,1 +M"ND`!H4&"5@$-C(N-L`#`$@!!B@``0D'"]4-!\`-`ED&`&T&,6%N:QL'`88+ +M*`H)$B4#NP`%[`($0!X`20T"&P0!N@H$Z"LQ0U9361\`V$@G=6R=`0NT``?Y +M#@(I``_&#`,8,AL(`5$`!2@`!E,*"B8B$B=/)@"$"@1$(0&4`A%D*`4`H`($ +MXQ,R8W)I6!A2\`!ZP' +M`8HD`?(]`/T+`'D("%H0`.````$/`(P#`&4H`/8=(!"PL! +M%C(Z$PHH```+`0[=!1`@D0,"3"(`!`P"EP-0>2!C;&\0#@"5*4%T8L<`2"Y`0`2%0*7#0#)-0"F'!=Y@A.!4VME +M;&5T86Q\"P:,"`%=!P/L`08"!0OL`1HQ[`$&*`!01FQE +M`@$I`1%A(2`!RET":0(`)`%B/'-I9V@^VP`&204!<@(!=!D`]P0&.!P`A0-0 +M,BXQ+CDW"A-TMPD":0`A"@EJ``!L`0\7$``#80`%NP803,0*'!`#*,#!U;&00!!!RY0('H0(Z.PH) +M4P`!F@D2=\9.`,D+`%\#`WL"`NP#`I(!$&Y3,@#,:`!T`P6-#C%T;W7L`@!, +M!0""10-@`14QX1$+_@`'-@DF"4P[%@"!``#L!`*Z(!!N9AT!*B$`"0$`=00` +M!`,`_D]$97)I>&,`!:4'"V,`".4(`,0!`QHC#'8+)S%BZP8**```P@D&50`1 +M7PQ%`]9G"KT,`48=`!$:(6%L4$%E+@H)3F]TM@4!3@8$BP$"B0$`IQ8!-&T* +M<@`)NAP1(LH&``\!47)EP1$&XN2!%N/2T`?AH$4@`%;@$,4@`6-,("`5(`!4L2!/P7(6%NPT4@8FS* +M*0#[(!!AM0D!R@4`U1$`'``!"P<`_PX`;VP!NB\!)@`!#D@!3@D188(3!75$ +M`>T70&]R(&>R4@`_#`!N$"1B96T+``L"`P,>`BXO`#4M`2PQ0&]T:"!:!P*< +M!0'##Q-R0PR4;VQEY!0J(`1%(#0<$1PT@W``%J!`=B +M!@!<`08I```K%`'M`0">`@!X`C%S("BB``!W!0#C`@)3"Q``#U!(`200"O0('_0`( +ME```^A)`:6YG+Z,#`%L-`7H``38*,7!A>-4`!>T#`+T6(G5NI0$@9616)`$V +M`0^Y"@,W,"XR8@<`*0`%*`!`($ET)T0*$71)'#)E8W3&`1!I%@"S<')E='1Y +M(&=O;V3]`0;U"1(R&201;^I#`=<:`+\F(&]F[`L480H``_T& +M``D#`(<.`/T(,$=E;M@``;P#$RAQ+3`A*2!0.P'+'0(6`0!$$0%"``'H'[)I +M0@A +M=""X3X1L8VAM;V0H*6L`!245!Q(#`74!!]83`6L`!2D`$47*,`8(`S-E`2!W:#(!`24` +M`Q$(`4\`(6)Y00`!SAE1('1O;VRM!``W!@+F*`4N``*%!@';'#5M:7HL`08U +M"P=L``$L`0?9!0`L`0,'0@(U`@'0*`%?$0#Z!@'1*`&-!@9$``"<%@/T5P*A +M`"1F($8!05!%4DTW`001`&A/5TY%4BRD9")R96<0`3L`<71O(%-5240S`!!3 +M8`0`LQ@`=A<%F4X.B@H78AP,"B@`$4%F"`"J!05@"P"1!A$B!RX4(KL0$'/: +M!Q%A?P`"&S4&D78`YP,`)48Q("!"0Q\`L`0`APD0:;$$`O4``"U=P'D:"`@8=,5865R+6=R +M8?@T`4X/,&9A8UX"%F&'$``C`03;%0VW'P$:`0`E&@",`@/E%0#R,@&)9P., +M:0%`$`*T%0/&`P"C-`&B&`1G`0%'`"%A"P,-$011 +M`"!D99X)$&*A!0$4-S%Y;W5#``1*&@():!(I5T``FP!A;W9E!Y<#`D<5`7(!`G(` +M46EN=F]LU`$$\P$!S08$!%4!40T`4P8`!@(`7&(1210=$V.*"0&"-!!X80L` +M``(@;V;/$>(@;W9E@J`:L&%2W(`0'8-0)T'@,^%0P2`3_`$`R+C`[Z0("PPD`9Q]!<')O=/P+`+,Y]0-I +M;F0@(VEF9&5F)W,@=6YT:6R@-P'#<0+U%@"S$3-Y=&@T"P%B`P"L`P&L`@)X +M``*['@::``#8"0OK``>7%P#:!0*!`0`;&S!S92@`>5$@5&AE>9<)`$XL`HX. +M`.L"`&8/`4L``#HJ%6;B'PIL`,!R96-U`0"S#"%S90($`BD#`$D($&``"I`2`M<",%"W8+`@5.`;%P!!H`$"W6(E!I9FEC"@QX +M#>5.``AH/`Y@E$3;N"!`@ZVL!?2<0.P8`$6Q-*0#_!2!O;$\0$F@C*`+9 +M``%'"@!?``&(`0#V!Q`GIQ81EQ`:\G4&QE('5P10<`8S0"/``` +M=@@@;V[+*T),1$52=@"B4U5-34%22453"OT0`JT%#V0#`!HQ(0$#(2,0-ED. +M")DE`%87(&YD;P$2=-E#!8@/"98C,B!R96YP`,L``3<-``EE(&]R"!T"*!,` +M3@(%7`8@9&5N$P&,+0">`0.3,1`V9R,`Y)`!L!`5X`!?P!$$FX)C%P;W*M +M!`MF2@"C95!T:6QL+3`'#%\U`&(``.4%#@X!&',C:0'8$WPM;VYL>2XI?`!@ +M4F5O@K,:@!J +M$P&'!`&*&Q)S^!0']@0`ZP4"WPP"B#@#Q84.GL'`5(J`)(A +M`0%1`3\Y!/<&$BR^(`!Y`#=087CZ`0%>'`(6?Q$N_DT"`!L;-=H9`;X!`_8! +M!+41"4=/`#X.!%T9`!\+!E\9`+L%`$83`K8$`A\2`',-!)0$"NE*`F0``N1* +M`*X``#P44&%S($DG'`-`="!Q=;@3`)-&`-A:`:P)`)@"`C8``T&``((!G&AE +M=7)I8@,!0@'`1P)5"X*3V-TZ@(2-5A7-$=.5U,`D#`/87`2L2"\`#`W`#`JT-*C4Z,0(#7P8!544` +M7@,!*0\095X)$7G=$0`]`@3N0S%S("@*"`(K'`(0"@8<``*>&$PQ34(I<0"@ +M36%R8W5S($=E:7T'`%8<`!\'`6<1`.,-`;)Z`[PZ!KD#`'D``SP!\PYX(H``$%\0FMT;W!?>P#J&0`O``;'``&%"0*5``!]``". +M!`+*%0`.``$T```J+P.W"P-1#V(U.B!07`F`Z2UW86QK6``!J!\`E@4"DP("70`#X"L1-6!A`/U#`+@'!%4` +M`3(``2%;$#N$(@"4``0/!0"*#`#2`11YHQ(0--(!(6YY*RH0+7<(`,4](6QE +M+P(!U!$`2#D!5@,!&U(#5@`@86PE#@`=`0'5'P/L%@$`&@4Q.P1S``0&.P2_ +M``!]``.'!Q$TBBL`I2H%FW@#;X3Q!2P@2%`M55@L(%5N:7AW87)E+"!S:2D` +JTRH"+@$`?@$1<#T``I(!`'P$'P`!`/______;U````````````",W%#R +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lz4_B5BD.tar.lz4.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lz4_B5BD.tar.lz4.uu new file mode 100644 index 0000000..5ad5469 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lz4_B5BD.tar.lz4.uu @@ -0,0 +1,2310 @@ +begin 644 test_compat_lz4_B5BD.tar.lz4 +M!")-&&10"+,4``!O>&9I;&4``0!+X3`P,#8T-"``,#`P-S8U"``B,#(0`"(R +M,`$`_P<@,3(S-3,U-3,U,3(@,#$R,#(S`"`PEP!+`@(`KW5S=&%R`#`P8W4' +M`0M2,!46%C="!S8`"A(&1E;6]N4$`(&EN^``(M@)A:6YF;W)M&@00 +M(+@&!+T"\`E.15=3("T@:&EG:&QI9VATP`"-E)ZT``R0$`),``$X`]0$N86TL(&%C;&]C86PN;30L +MX0!`92YA8_\```(`$BU4`"1T;Z@`#*($LBP@;VYL>2!N965D?``Q;6%I]@$C +M97)<`05P`"1I;F0`\@,N:"YI;@H)+2!T96UP;&%T97-G`!%B-`(!9@$39;4` +M<`H*1W5I9&6V`AA$5`8$T@$"=0`!MP&R'!L +M@P(#+P,`0@$"(0`$F@,#,P``B`0/-``+`"(`##4`+V%T-``,*&%T,P`&`0:` +M+C,@9VEV97/?!H!O=F5R=FEE=_,"`*``!+L%$&%Q!3!W:&^1`B,J(-D'A5]R +M96%D+C,L$```T04=91$`45]D:7-K%@`"?@<(/@`#'```F0`0=E\!`K<"865D +M(&-A;(D'$'/4!D%N8V5SK0(`DP``=0``%P(`^00!<0!8($%027.7`'-E;G1R +M>2XS30`"]P,2(FL#!:L``20`4"(@=71II`59(&-L87-$``'O!49N86QSG0!@ +M]!;!I;@IA(&YU;6)E`D09BP``;<&42H@1TY5 +M=0$"N@$F("@$"P`:`$%L;VYG4`9B;F%M97,L$```!0L3(!$``&,`4G-P87)S +M?`(AB,``!DT%``)"`$```I58W)E +M873/``%U!`\&`0("J@,#OP,"O`(/'P,8,")R9:`-46-T960B1P,"3P#$+"!W +M:&EC:"!W:6QLB@`!5@`%R@%A(&5X8V5P0`40"EL)`VD"42!T:&%T0PXQ:7)E +M40`!\P,!R@(@("A3"@$T!`"$`0,S!`#T`V`L(&5T8RGO"P+Z`P"I`@8B!`&& +M`0+:``_(`PIA(FYE=V,BFP,!,P`G0<280D!`BL`(2!B-PEQF4@'!L +M:6-I=&S9"4!V;VMEO!(!ZP`!?PH#SA$@("C2$"4@8?L*`*D`("!AZ0`!)Q`" +M+0`(S0`4;Y4(<"DL(&ET('=P`$$@9V5T&1,!70H`I`0W($EN;@`W+"!IG@`! +M40$#FP`B96[)`0P,1<#4`T6%T979E`!,@%1``:A`` +M"@$`/06#;B!I=',@(D#E`!(BO0012!F4X.``P1$2(A`0!:""`L +M(E`(H"P@8V%P86)I;&D2%`8#`07Q``+S#P&W!`CV!0&7`8`@:6YD:79I9&P. +M`&@%(6EEA`$`.A("0@`$K`4`-@$A=&^L#3!D8737```%#A8Z+@$"R`D`P@`2 +M8>P"`,D*`2L`,VEN("4&EV92!E +M0A0``/$1;G1R>2!B90H@("!I;F1E<&5N9&5N="X@(%1H97)E(&$$`/`9=&EC +M;&5S(&]N('1H92!L:6)A'1E;F0L`/(6+@H*("H@3VX@F4@;V:(`0"S`1`M=@!A960@8FEN/0`P(&ENA`#A +M96YV:7)O;FUE;G1S('=N`F!T:&%T(&W8`2)R<^D!!3`"`WD"H7)A3X`!8P``+$!\09P7,N"E)%041-12X`"!0'T6)U;F1L92X*"E%U97/Z +M`J`_("!)3``!(`1!HN`*# +M9F]R(&]N9V]8!Q@@9`!P9&5V96QO<#P%<2P@:6YC;'6]!4!D;V-U%``087<` +M$"Q8!P!Q```Z`"%N:UT!`%T`!G,`4"!M86EL!P)";&ES=*`#,"H@5)D!`>H& +M0&%N(&FW`!`L(00!_``!#P"A('1R86-K97(@8F-A="P@8@<`$G@'``!)`0"2"0`G`%`J(&5X84D`0',Z(%,R`U1S +M;6%L;!4`!#X!`%(#(6%T'`@@;6'F!"!N9-`",69U;"\"!D4`$"]#"@&%`1%A +MXP%186-T('-@`+`@9&5M;VYS=')A=+\`!,GK0`#9P$`DP``3@#P`"YA;2P@ +M86-L;V-A;"YM-`D-`^T`,"YA8_\```(`$"VB`@"?``2H``RB!&$L(&]N;'G7 +M"P)\`#%M86GV`2-E7-T96TZ&@D"N`0A +M+C'!#`!A#`$W`0,O`P`+``(A``2:`P,S``"(!`\T``L`(@`,-0`O870T``PH +M870S``8!!B$N,[8+$'-E"H!O=F5R=FEE=_,"`*``!0H,`'$%,'=H;Y$"%"JD +M"H5?PH" +MMP(29:`,`%L$$'/4!A!N2PT`U@(`DP``=0``%P(`^00!<0`!<0H(EP`09<,/ +M(RXS30``[P0R92`B:P,%JP`!)``4(@L+62!C;&%S1``!'PE&;F%L`8`>P`( +M2PE`:&%R9!8,`3`&!%L!`4<``(X!86UO9&5R;H\``.@!`+P'<"!V87)I86Y( +M"0!$!+%M86YU86P@<&%G93@``+`0)')EI@``G@`!'0-7)V1O8R>]!9!I;@IA +M(&YU;6+R#!=FD0<#'@'7+@H*66]U('-H;W5L9*0+`"@!,6-O<'8&0&-O;6V> +M"`#.#1,B!0XR+F@BJ0`R:&4*7PQ!(&-O9'4!`!0`!.D&`W((`G\"(6UOU@P" +M6@4R("!0B@FR;&5T('5S"FMN;W<0`0&9!G!E2X`L2`H8FEG +M+65N9&EAU!%C;&ET=&QE$0`"^@#Q`DE33SDV-C`@0T0M4D]-(&EMMP*`*'=I +M=&@@;W#+`\!A;"!2;V-KU`P$3`%HW+5II<"8`V$UI8W)OFEP,A8`!'P! +M32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9-!0`"0@!```*`IP0!3H!`'4$ +M#P8!`@*J`P._`P*\`@\?`Q@P(G)EH`U18W1E9")'`P)/`,0L('=H:6-H('=I +M;&R*``%6``:0`"!E>"T4``("$`I;"0-I`E$@=&AA=$,.$&F6!2=A>,H"("`H +M?0`3AN97>U +M`P#P!`#]`@.?`0![``&'"0##%Q)E2@P`31%`:7)E;?8-$&EY!P/N$@(,`@,A +M&D%R96%DCQ@#N!0!#``080P!`M00`&@``CL`$66<%@`]`2%V9?P4#V0:____ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________]J4&EV97,*4!0``/`5"E1H92!L:6)R87)Y(&%LFEP +M,A8`!"8`32],6E<=`+%L>FUA+"!L>FEP+,<`+WAZ(P``&304``D(`95C86X@ +M8W)E873/`$]S(&EN!@$#`21E9-T`$2E%``"=``"<`H5"4T0@)V%R)U(``1X` +M>"=M=')E92>[`'A)4T\Y-C8P$P!:-RU::7`Y`#9805(1`$,*5VAE`P(`V`($ +M=0$1+`(#87)ED#`*4#`.<#]A)U2!S=')E86WM`>!S>7-T96TN("!4:&5R92P`\01N;R!D:7)E8W0* +M("`@`>-R86YD;VT@ +M86-C97-S+GD`!I<`\@)I4<`L$DG=F4@871T96UP +MQ`/@=&\@;6EN:6UI>F4@2!I;G9O:V4@82!PZP`@=6PW!*!E871U``%1`0.;`")E;LD!!RT``'P`"W$`*&1E$0`#Q@(1 +M+/```H``(FYEC@(`%@$`0`!B86=A:6YS1P*@8V]R7L#$7`U`-%A=&5V97(@8FQO8VMS\```[@2X'<70@82!T:6U7`W%O8!(71O(@`%H0!A="!O;F-EA0`A3VZ0 +M`QMEPP`"Y`(R<')O.@$!A0%18W1L>2W,``!(!E)U='!U=.\"`&`$\0-O8FIE +M8W0M2!B=69F97(@ +M)`@`90`$<@&%82!S;V-K970^`TEW:7-HN@3`P" +M`,D*`2L`,VEN(">D``,P``*,!!H`%,7=A;H@`$'0V!`5%`0!@``'Z"0".!S!S +M:RQ.`P-^!KEC;VYV96YI96YC9<`!`(D`,&UA:WD`D&ES(&5S<&5C:6X$`=`! +M`JH!`#H(,#H@(I,*#KL*$R*Y`B!L;#P!`N@"`*4'`!$#`L$%0"P*("#,!Q!P +MWP``;`0`E@`0(',*T"!S87ES+@I214%$346[!@?H!N$@8G5N9&QE+@H*475E +M<_H"H#\@($ES7!1`GH@1`9W)A;18"M``-G`0"3``!.`/``+F%M+"!A8VQO8V%L +M+FTT"0T#[0`P+F%C%P$``@`0+:("`)\`!*@``-D."*($$BP:#@#7"P)\`#%M +M86GV`2-EPH"MP(`A1(A86R)!V!S97%U +M96Y+#0#6`@"3``!U```7`@#Y!`%Q``%Q"@B7`'!E;G1R>2XS]!0`!`,!=`$2 +M(FL#!:L``20`%"(+"UD@8VQA=&%R +M+C54`0CQ!`4^$A%S8P0Q<&]PY0\#G`$`>`8`>P`(2PE`:&%R9!8,`3`&`J@! +M`X42`(X!86UO9&5R;H\``.@!`+P'<"!V87)I86Y("0!$!+%M86YU86P@<&%G +M93@``#$.`,X4`OH!`)X``:D!5R=D;V,GO06P:6X*82!N=6UB97*5`@:1!P,> +M`=%V,/"Q<`TTUI8W)O2)J +M%```\S4@=71I;&ET>2!C;&%S1X`<&QI8G)A#0#46-H86YG?@$W;6%T(0"P;V-T970M;W)I96X! +M`P!@`@$>`*%35E(T($%30TE)=`(!%``"4P`/,@`%84)I;F%R>2X`P"`H8FEG +M+65N9&EA;J(!8VQI='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I;;<"@"AW +M:71H(&]PRP/`86P@4F]C:W)I9&=E10!B2F]L:65T*0$![P$"20`U6DE0"0$# +M0`#P"G5N8V]M<')EB,``!DT%``)"`&5 +M8V%N(&-R96%TSP`!=00/!@$"`J\!`[\#`KP"#Q\#&,$B,H"4B`H9F]R-`0`A`$#,P0`]`-Q+"!E=&,I+F\!`/H# +M`*D"!B($`1<``MH`#\@#"F$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0%!`); +M`0&)``]9`P`*%@,S5VAE`P(`V`(#U`(2<^8%87)EF4@ +MP,1<#4`T6%T979E6QE(&%P<')OR`,`R0@"^@#@=&\@:&%V92!M +M=6QT:7`E``-3!`(!!`"Y"%4@;W!E;IX`4"`@8G-D(P2!B=6@-$B`D"`!E``!Z``#!`85A('-O8VME=#X#27=I#B)A;N@"`*4'`!$#`KH.0"P*("#,!Q!PH@`` +M;`0`E@`!I@[1('-A>7,N"E)%041-11(&!Q0'T6)U;F1L92X*"E%U97/Z`J`_ +M("!)3``!(`1!HN`(09K$/ +M,VYG;U@')B`@+`"`(&1E=F5L;W`\!0@9$02Z$0&L"!`LH@0`<0``.@`A;FM= +M`0!=``='`$!M86EL!P(P;&ESOQ`!G0`05)D!`.41`.!L30',Z(%,R`U1S;6%L;!4`!#X!`%(#(6%T'`@@;6'F!"!N9-`",69U +M;"\"!D4`$"]#"@&%`1%AXP$T86-T>Q-P9&5M;VYS=#D5(&YG/@``@`4&5`(# +M20`P8V]N0P)A.B`@5F%R[A-@:71E;7,@,P$`UP(B;64V%3)I'2(`"%P=6<0,"`B8S0&$2(D`P`X#"EO;$T`(`H*X0@& +MZP,!*0$`%@D`C@$/;0$!`+`,$'4]$P(0%R4*)[P`$R>M``,D!`"3``!.`/`` +M+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C_P```@`0+60"`)\`!*@``-D."*($ +M$BP:#@#7"P!9"U%Y(&UA:?8!(V5RK@$%<``D:6YD`($N:"YI;@H)+?0'(&QA +M5@\$NP`%A0`#M0!P"@I'=6ED9;8"$T0.&`*!`0/2`0)U``#S`0-3#Q`Z&@D" +MN`0A+C'!#`!A#`$W`0`]!@-X$P(A``2:`P,S``"(!`\T``L`(@`,-0`O870T +M``PH870S``>M`Q$SM@L`$!20(&]V97)V:65W\P(`JP`%P`L`<04P=VAOD0(4 +M*J0*A5]R96%D+C,L$``!^`@-$0!17V1I2XSHQ2!T:&ER9"!P87)T:65S.X,``P(`87!L96%S948``'L`\BET:&4@ +M875T:&]R2!Q=65S=&EO;G,N"@I4:&4@=&]P+6QE=F5L(&1I +M4$`(&EN^`"`92!F;VQL;W>V`'!I;F9O%#36%K94QIM`!(ZU```DP``3@#U`2YA;2P@86-L +M;V-A;"YM-"SA`$!E+F%C*P```@`2+50`)'1OJ```(`&`9&ES=')I8G5!`;(L +M(&]N;'D@;F5E9'P`,6UA:?8!(V5R7`$%<``D:6YD`/(#+F@N:6X*"2T@=&5M +M<&QA=&5S9P`18C0"`68!$V6U`'`*"D=U:61EM@*"1&]C=6UE;G2!`0#%`3)A +M;&QU``#S`?4*('-YM`_`$,R!G:79E2XS!`,!JP(2(FL#!:L``20`Z2(@=71I;&ET>2!C;&%S1`"6:6YT97)N +M86QSG0!@P$2+8($4W,N-2!D5@(#I@0@:6QV`]1R;6%T-50!"/$$4&%B;W5T +M&@$@P"`+"!I;F-L=62*`8%H87)D+71O+3`& +M`J@!$G-'``!!`&%M;V1E$D#(F5R60<#>`('(0"P;V-T970M;W)I96X!`P!@`@$>`*%3 +M5E(T($%30TE)=`(!%``"4P`/,@`%,$)I;LH$`$(`H"`H8FEG+65N9&GS!(-R +M(&QI='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I;;<"@"AW:71H(&]PRP/` +M86P@4F]C:W)I9&=E10!B2F]L:65T*0$![P$"20`U6DE0"0$#0``@=6Y."3!R +M97,G!W!OB,``!DT%``)"`$```I58W)E873/``%U!`\&`0("J@,#OP," +MO`(/'P,8,")R9?X(46-T960B1P,"3P#$+"!W:&EC:"!W:6QLB@`!5@`%R@%A +M(&5X8V5P0`40"EL)`VD"`A4,<7)E<75IP`#GP$`>P`!APD!HP`"2@P#"@,0;6L($&EY!Q%A+PD#*P`A +M(&(W"7%R96%D86)L``8`C`H!#``!+`L"!`$`:``".P!"96%C:#T!(79E4,`4&EN9&5PJ@`E;G0B`0`8"0`/#Q!C0@42;VP-!C4*5"!7:6MI4@PP:6YG +MR0`P:&]WFPP!LP,79)8*`BH!(4]N/P@`]PP">`8#`P$$S0`!<`!`;'=A>48! +M`-T!*F5DB@@"1P!P22=V92!A="T-`(P'`,$/D&EN:6UI>F4@2UV```S#`#W"!%IAP8`A`!P96YV:7)O;M<",7,@=Y`#`:`"$&W8`1-R +M6@,%,`(`6P`"?P`1>7L#$7`U`-%A=&5V97(@8FQO8VMS\```[@2X'<70@82!T +M:6U7`W%O8!(71O(@`%2@!2="!O +M;F-\$B)/;AP."\,``N0",G!R;SH!`84!46-T;'DMS`"2960@;W5T<'5T[P(` +M8`3Q`V]B:F5C="US='EL92!A<'!R;\@#`$,2`OH`X'1O(&AA=F4@;75L=&EP +M)0``(040=A(#0')E86W\"E4@;W!E;IX`$R`5$`!J$``*`0`]!8-N(&ET2!B=6@-$B`D"`!E``!Z``#-`H5A('-O8VME=#X#27=IP`2 +M8D(`!*P%`#8!(71OK`TP9&%TUP``!0X1.L$"`2X!`L@)`,(`$F'L`@!A`P$K +M`#-I;B`G`0"/`C-A9&2.`AAA]PP!UP<#'@]19FER>D` +M`,P``*,!!H`%,7=A;G\%$G0=#P-%`0!@```:!!!TC@A<"+```.P``!`,`2P+%1`G-Q,`)AD`%@)S82!F=6QL +M+98(F-%#A)B!P`2 +M>`<``'`$`)()`"<`%"I/&@]D&O__________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M________________________________________65`@("!T;U04``#R-B!B +M92!R96%D(&]R('=R:71T96X@=&\@86YY(&1A=&$@F-A="P@8@<`$G@'``!)`4!S=6-H)P!0*B!E +M>&%)`$!S.B!3,@-4 +M`0-)`#!C;VY#`O`".B`@5F%R:6]UP``7P%Q875T:&]R<\`%`1\&`?("``$% +M4"X*"E1HG0$P<"UL#`0#=@4P;W)Y,04P=&%I)`4)M@(B:6[6!#%I;V[K!02] +M`O`"3D574R`M(&AI9VAL:6=H='-'2(`#!P=71>`C`@ +M(F,T!A$B)`-I9"!T;V]L30`"5@$&ZP,`%`=!'!L@P(#+P,`0@$" +M(0`$F@,#,P``B`0/-``+`"(`##4`+V%T-``,*&%T,P`&`0:`+C,@9VEV97/? +M!H!O=F5R=FEE=_,"`*``!+L%$&%Q!3!W:&^1`A0J[`B%7W)E860N,RP0``&[ +M"`T1`%%?9&ES:Q8``GX'`X0)`3X``QP``)D`$'9?`0*W`F%E9"!C86R)!Q!S +MU`9!;F-E``&I`5 +M"`"X!!,B?P(R+F@BJ0`R:&4*7PP0(+`)`'4!`!0`!.D&`W((`G\"-&UOFEP/@$Q:6]N +M&`%=8GII<#(6``1D`4TO3%I7'0"B;'IM82P@;'II\+`OH#`*D" +M`&@1`HT``88!`MH`#\@#"F$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0%!`?. +M``]9`P`*%@,S5VAE`P(`&@T#U`(2<^8%87)E0<#[A("*P`A(&(W"7%R96%D86)L``8` +MC`H!#``!+`L"U!``:``".P!"96%C:#T!(W9E/10"0P!0:6YD97"J`"5N="(! +M`$0-``\/$&-"!1)O;`T&-0I4(%=I:VE2##!I;F?)`#!H;W?X``&S`Q!DK0$# +MV@`"*@$A3VX_"`#W#`)X!@#S#@!0!@/-``%P`%-L=V%YD``2<0`BT`",T`%&]S!'`I+"!I="!W<`!0(&=E="#2$@%="@"D!#<@ +M26YN`#(L(&F"%0&>``%1`0.;`")E;LD!!RT``'P`"W$`*&1E$0`#Q@(1+.4) +M`H```(T.`)8!`!8!`$``,&%G8?,/`5\*D6-O7L#$7`U`&)A=&5V97)X%Q%S\```[@ +M!#%FQF4@ +M6]U(&1O;B=TJ```M@#P)&EC +M:71L>2!I;G9O:V4@82!P87)T:6-U;&%R(&9E871U!E('-O;64@=71I;&ET>3X`!8P``+$! +M\09P2!D8737`%9UP"`&$#`2L`,VEN("X`0!V``*4`0```P&3``7+`0#3``.C`0:`!3%W86Z(`!!T-@0# +M-@(!6P,`'P$`N@!09&ES:RQP`P/$`;EC;VYV96YI96YC9<`!`(D`,&UA:WD` +MD&ES(&5S<&5C:6X$`=`!`JH!\P=.;W1E.B`B<&%X(&EN=&5R8VAA;F=EGP43 +M(KD"(&QL/`$"Z`(09+X!`/T%`8T&D"P*("`@9&5S<*(``&P$`)8`\`,@;F%M +M92!S87ES+@I214%$344N``?H!N$@8G5N9&QE+@H*475E<_H"H#\@($ES`<``$D!`)()`"<`4"H@97AA20!`8$(&YDT`(Q9G5L+P(&10`0+T,*`84!$6'C`5%A8W0@`0-)`#!C;VY#`O`".B`@5F%R:6]UP``7P%Q +M875T:&]R<\`%`1\&`?("`DT'$`J(!E!T;W`M;`P$`W8%`#`'`4$`$&GD!@FV +M`B)I;M8$`'$+`.L%!+T"\`).15=3("T@:&EG:&QI9VAT2XS30``[P0R92`B +M:P,%JP`!)``4(@L+62!C;&%S1``!'PE&;F%L`8`>P`(2PE`:&%R9!8,`3`& +M!%L!`4<``(X!86UO9&5R;H\``.@!`+P'<"!V87)I86Y("0!$!+%M86YU86P@ +M<&%G93@``#$.)')EI@``G@`!'0-7)V1O8R>]!9!I;@IA(&YU;6+R#!=FD0<# +M'@'7+@H*66]U('-H;W5L9*0+`"@!,6-O<'8&0&-O;6V>"`#.#1,B!0XR+F@B +MJ0`R:&4*7PQ!(&-O9'4!`!0`!.D&`W((`G\"-&UO2X`L2`H8FEG+65N9&EAU!%C;&ET +M=&QE$0`"^@#Q`DE33SDV-C`@0T0M4D]-(&EMMP*`*'=I=&@@;W#+`\!A;"!2 +M;V-KU`P$3`%HW+5II<"8`V$UI8W)OFEP,A8`!'P!32],6E<=`*)L>FUA +M+"!L>FEP$P,O>'HC```9-!0`"0@!```*`IP0!3H!`'4$#P8!`@*J`P._`P*\ +M`@\?`Q@P(G)EH`U18W1E9")'`P)/`,0L('=H:6-H('=I;&R*``%6``:0`"!E +M>"T4``("$`I;"0-I`@)K%`!##A!IE@4G87C*`B`@*'T'`30$`(0!`T0$`/0# +M8"P@971C*>\+`OH#`*D"`&@1`HT``9L!`MH`#\@#"F$B;F5W8R*;`P$S`"=S +M:+```1(`#T8#8P0%!`?.``]9`P`*%@,S5VAE`P(`OP@#U`(2<^8%87)EP`! +MAPD!*Q4"2@P#"@,0;?8-$&EY!P/N$@(,`B$@8C<)07)E862/&`.X%`$,`!!A +M#`$"U!``:``".P`199P6`#T!(79E_!03>4,`M6EN9&5P96YD96YT(@$`1`T! +M>1D`0@42;VP-!K`+#V0:________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________________________________]H4&QL;W=I410``/$F;F<@8F5F +M;W)E(&5V86QU871I;F<@=&AE(&%R8VAI=F4Z"B`@*B!U=65N8V]D960@9FEL +M97,4``$*`/$"('=I=&@@4E!-('=R87!P97(;`/$!9WII<"!C;VUPFUA+"!L>FEP+"!A;F0@>'HC```9 +M-!0`]0<*5&AE(&QI8G)A"!I;G1E&-E<'0@9F]J`/$'("!E;G1R:65S('1H870@.`?$#;F%M97,L($%#3',L(&5T8RDND@"P +M3VQD($=.52!T87)=``2I``+*`/$$;V-T970M;W)I96YT960@8W!I;S4`ME-6 +M4C0@(FYE=V,B%0`G`'@G;71R964G +MNP!X25-/.38V,!,`6C2!S=')E86WM`>!S>7-T96TN("!4:&5R92P`\01N;R!D:7)E8W0*("`@`>-R86YD;VT@86-C97-S +M+GD`!I<`\@)I'!L +M86EN:6YGB0`P:&]W^``"]0``C@0#+``"*@$A3VZJ`!PL`P$#V0("<`!`;'=A +M>48!`-T!\@%E9"!A=71O;6%T:6-A;&QY1P"P22=V92!A='1E;7#$`^!T;R!M +M:6YI;6EZ92!S="L`L"!L:6YK('!O;&QUN`'A+B`@268@>6]U(&1O;B?L`0"V +M`/$":6-I=&QY(&EN=F]K92!A('#K`"!U;#<$(&5A60)`("AS=2\!&7,<`A!A +MZ0`'+0`'[P4`@`$"F0%P*2P@:70@=W``X"!G970@<'5L;&5D(&ENI`0W($EN +M;@`W+"!IG@`!40$#FP`B96[)`07L# +M$7`U`-%A=&5V97(@8FQO8VMS\``0:%<%(6ETH0!!66]U2X'<70@82!T:6U7`W%O8!(71O(@`%H0!A="!O;F-EA0`A3VZ0`QMEPP`" +MY`(R<')O.@$!A0%18W1L>2W,``!(!E)U='!U=.\"`&`$\0-O8FIE8W0M2!F)M96UO?<"!8P``0`" +M\05R;W9I9&4@96%S>2UT;RUU8<``J,!!H`%,7=A;H@`$'0V!`5%`0!@``'Z"0".!S!S:RQ. +M`P-^!KEC;VYV96YI96YC9<`!`(D`,&UA:WD`D&ES(&5S<&5C:6X$`=`!`JH! +M`#H(,#H@(I,*#KL*$R*Y`B!L;#P!`N@"`*4'`!$#`L$%0"P*("#,!Q!PWP`` +M;`0`E@`0(',*T"!S87ES+@I214%$346[!@?H!N$@8G5N9&QE+@H*475E<_H" +MH#\@($ES7!1`GH@1`9W)A;18"=&%R+C54 +M`0CQ!`4^$A%S8P0Q<&]PY0\#G`$`>`8`>P`(2PE`:&%R9!8,`3`&!%L!`4<` +M`(X!86UO9&5R;H\``.@!`+P'<"!V87)I86Y("0!$!+%M86YU86P@<&%G93@` +M`#$.`,X4`OH!`)X``1T#5R=D;V,GO060:6X*82!N=6UB\@P79I$'`QX!URX* +M"EEO=2!S:&]U;&2D"P`H`3%C;W!V!D!C;VUMG@@`N`03(@4.,BYH(JD`,FAE +M"E\,02!C;V1U`0`4``3I!@-R"`)_`C1M;W*C`E)S+B`@4(H)LVQE="!U=H+ +M`#L'`2,)"=H1`,$",&5C=)D#$60Y"0,<`@>F%@"E`0!0!0)!%0:J"R8@*`0+ +M`%L5#"`6`1````4+`;X+$G,W`E)S<&%R\6`2T5`A``#XH,`P4P`T&-P:6\N-2P@;71R964)``!O`/(*=&%R+C4@<')O=FED +M92!D971A:6QE9"!I;E(`D&EO;B!A8F]U=$T`('-EN`"#<&]P=6QA3`1!F+`"A#0#46-H86YG +M?@$W;6%T(0"P;V-T970M;W)I96X!`P!@`@$>`*%35E(T($%30TE)=`(!%``" +M4P`/,@`%84)I;F%R>2X`P"`H8FEG+65N9&EA;J(!8VQI='1L91$``OH`\0)) +M4T\Y-C8P($-$+5)/32!I;;<"@"AW:71H(&]PRP/`86P@4F]C:W)I9&=E10!B +M2F]L:65T*0$![P$"20`U6DE0"0$#0`#P"G5N8V]M<')EB,``!DT%``)"`&58V%N(&-R96%TSP`!=00/!@$"`J\!`[\# +M`KP"#Q\#&,$B,H"4B`H9F]R-`0` +MA`$#,P0`]`-Q+"!E=&,I+F\!`/H#`*D"!B($`1<``MH`#\@#"F$B;F5W8R*; +M`P$S`"=S:+```1(`#T8#8P0%!`);`0&)``]9`P`*%@,S5VAE`P(`V`(#U`(2 +M<^8%87)EF4@P,1<#4` +MT6%T979E6QE(&%P +M<')OR`,`R0@"^@#@=&\@:&%V92!M=6QT:7`E``-3!`(!!`"Y"%4@;W!E;IX` +M4"`@8G-D(P2!B=6@-$B`D"`!E``!Z``#!`85A +M('-O8VME=#X#27=I#B)A +M;N@"`*4'`!$#`KH.0"P*("#,!Q!PH@``;`0`E@`!I@[1('-A>7,N"E)%041- +M11(&!Q0'T6)U;F1L92X*"E%U97/Z`J`_("!)3``!(`1!HN`(09K$/,VYG;U@')B`@+`"`(&1E=F5L;W`\ +M!0@9$02Z$0&L"!`LH@0`<0``.@`A;FM=`0!=``='`$!M86EL!P(P;&ESOQ`! +MG0`05)D!`.41`.!L30',Z(%,R`U1S;6%L;!4`!#X!`%(# +M(6%T'`@@;6'F!"!N9-`",69U;"\"!D4`$"]#"@&%`1%AXP$T86-T>Q-P9&5M +M;VYS=#D5(&YG/@``@`4&5`(#20`P8V]N0P)A.B`@5F%R[A-@:71E;7,@,P$` +MUP(B;64V%3)I'2(`"%P=6<0,"`B8S0& +M$2(D`P`X#"EO;$T`(`H*X0@&ZP,!*0$`%@D`C@$/;0$!`+`,$'4]$P(0%R4* +M)[P`$R>M``,D!`"3``!.`/``+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C_P`` +M`@`0+60"`)\`!*@``-D."*($$BP:#@#7"P!9"U%Y(&UA:?8!(V5RK@$%<``D +M:6YD`($N:"YI;@H)+?0'(&QA5@\$NP`%A0`#M0!P"@I'=6ED9;8"$T0.&`*! +M`0/2`0)U``#S`0-3#Q`Z&@D"N`0A+C'!#`!A#`$W`0`]!@-X$P(A``2:`P,S +M``"(!`\T``L`(@`,-0`O870T``PH870S``>M`Q$SM@L`$!20(&]V97)V:65W +M\P(`JP`%P`L`<04P=VAOD0(4*J0*A5]R96%D+C,L$``!^`@-$0!17V1I2XSHQP#R*71H +M92!A=71H;W)S('=I=&@@86YY('%U97-T:6]N'2(`#%P=70I`/D#(F-M86ME(B!B=6EL9"!T;V]L30`"5@$&-0$! +M*0$Q(&EN3`$/;0$!,&%R91`"$F3:`35E"B>\`!,GK0`#9P$`DP``3@#U`2YA +M;2P@86-L;V-A;"YM-"SA`$!E+F%C_P```@`2+50`)'1OJ```(`&`9&ES=')I +M8G5!`;(L(&]N;'D@;F5E9'P`,6UA:?8!(V5R7`$%<``D:6YD`/(#+F@N:6X* +M"2T@=&5M<&QA=&5S9P`18C0"`68!$V6U`'`*"D=U:61EM@*"1&]C=6UE;G2! +M`0#%`3)A;&QU``#S`?4*('-Y`?$#+@H*66]U('-H;W5L9"!A;'-O(@(! +M3``Q8V]P=@8R8V]M6P%#:6X@(KT",BYH(JD`@&AE"G-O=7)C+P`19'4!`!0` +M!.D&`YH#`G\"-&UO<$",&5C=)D#$635``,<`@7"!A!F+``!MP91*B!'3E5U`0*Z`28@*+D! +M`!H`06QO;F=5`F)N86UE'1E;J+``-J`0`9`]$J +M(%!/4TE8('5S=&%R6P`"$``P<&%X20,B97)9!P-X`@@` +M`0H``EP)HE)032!WFEP/@$Q:6]N,`!=8GII<#(6``1D`4TO +M3%I7'0"B;'IM82P@;'IIU`P#P!`![``.?`0![``&'"0&C``)*#`,*`Q!M +M:P@0:7D'$6$O"0,K`"$@8C<)<7)E861A8FP`!@","@$,``$L"P($`0!H``([ +M`$)E86-H/0$A=F5S`Q-Y0P!0:6YD97"J`"5N="(!`!@)``\/$&-"!1)O;`T& +M-0I4(%=I:VE2##!I;F?)`#!H;W>;#`&S`Q=DE@H"*@$A3VX_"`#W#`)X!@,# +M`03-``%P`$!L=V%Y1@$`W0$J962*"`)'`'!))W9E(&%T+0T`C`<`P0^0:6YI +M;6EZ92!S#@T28U((07!O;&R4#5$N("!)9O4(4&1O;B=TJ`"097AP;&EC:71L +MV0EB=F]K92!A^@\18W\*,69E830+,"AS=2\!!?L*`*D`("!A00`!)Q`"+0`( +MS0`4;_D(<"DL(&ET('=P`'$@9V5T('!UG`T0:7H+1R`@26YN`#``%1 +M`0.;`")E;LD!!RT``#X`"W$`*&1E$0`#Q@(1+/```H```(T.`)8!`!8!`$`` +M(&%G`PX"4`.18V]RF5H!P*(`5!A;&QY+78``#,,`/<($6F'!@"$`'!E;G9IP,1<#4`T6%T979E2W,`))E9"!O=71P=73O`@!@!/$#;V)J96-T+7-T>6QE(&%P<')OR`,`0Q(" +M^@#@=&\@:&%V92!M=6QT:7`E```A!1!V$@-`4X.``P1$2(A`0!: +M""`L(E`(H"P@8V%P86)I;&D2%`8#`0"_``'Q``+S#P$_#@CV!0&7`8`@:6YD +M:79I9&P.`&@%$6E""`![`!)B0@`$K`4`-@$A=&^L#3!D8737```%#A$ZP0(! +M+@$"R`D`P@`28>P"`&$#`2L`,VEN("#U%F +M:7)S=)("`*8!$6%P$A%O61$`]@`6+G0``]D#`J#B)A;N@"`*4' +M!C0*0"P*("#,!Q!PYP$`;`0`E@`!I@YS('-A>7,N"B05$6:X#01Q%K0@8G5N +M9&QE+@H*41$6H#\@($ES%E2!F +M:6QE+B`@66]U(&-A;B!A;'-O(')E860@86X@96YT6]U('=A +M;G1$`!)T70`2+ST``&``,&EE'1E;F1E9#@!`B(`D"P*("`@9&5S<-\`0'=H8726`/`#(&YA;64@8$(&YDT`(Q +M9G5L+P(&10!1+VUI;FF%`1%AXP%186-T('-@`+`@9&5M;VYS=')A=+'!L@P(# +M+P,`0@$"(0`$F@,#,P``B`0/-``+`"(`##4`+V%T-``,*&%T,P`&`0:`+C,@ +M9VEV97/?!H!O=F5R=FEE=_,"`*``!+L%$&%Q!3!W:&^1`A0J[`B%7W)E860N +M,RP0``&["`T1`%%?9&ES:Q8``GX'`RH)`3X``QP``)D`$'9?`0*W`F%E9"!C +M86R)!Q!SU`9!;F-EP$2+8($4W,N-2!D5@(`G@419?L#`/(`Q&UA=',@``&I`5"`"X!!,B?P(R+F@BJ0"`:&4*`D09BP``;<&42H@1TY5=0$"-0(F("@$"P`: +M`$%L;VYG50(`K0LB+``-J`0`9`]$J(%!/4TE8('5S=&%R +M6P`"$``/B@P#!R$`L&]C=&5T+6]R:65N`0,`8`(!'@"A4U92-"!!4T-)270" +M`10``E,`#S(`!6%":6YAFEP,A8`!&0!32],6E<=`*)L>FUA+"!L>FEP$P,O +M>'HC```9-!0`"0@!```*56-R96%TSP`!=00/!@$"`JH#`[\#`KP"#Q\#&#`B +M&-E<$`% +M$`I;"0-I`E$@=&AA=$,.,6ER95$``0$0`?P(-F5A;;4%`A$+<"X@(%1H97(T +M$2`@;M82,7)E8S`1`]\(`),$02!I;BVW#X(@;6]D:69I8^4,\@%OP`!APD!HP`"2@P`31%`:7)E;?8-$&EY!P/N$@(K`"$@ +M8C<)<7)E861A8FP`!@","@$,``$L"P+4$`!H``([`$)E86-H/0$A=F5S`Q-Y +M0P!0:6YD97"J`"5N="(!`$0-``\/$&-"!1)O;`T&-0I4(%=I:VE2##!I;F?) +M`#!H;W?X``&S`Q!DK0$#V@`"*@$A3VX_"`#W#`)X!@#S#@!0!@/-``%P`%-L +M=V%YF4@'!L:6-I#16":6YV;VME(&'Z#Q%C?PH# +MSA$@("C2$"4@8?L*`*$!("!AZ0`!)Q`"+0`(S0`4;W,$<"DL(&ET('=P`%`@ +M9V5T(-(2`5T*`*0$-R!);FX`,BP@:8(5`9X``5$!`YL`(F5NR0$'+0``?``+ +M<0`H9&41``/&`A$LY0D"@```C0X`E@$`%@$`0``P86=A\P\!7PJ18V]RP,1<#4`8F%T979E2X'$'2B%R%I;5<# +M<6]R(&UM87`I`0!>$P'Y%@([`P"V`A!GPA<0:2(3`2(`!:$``.,3(6-EA0`A +M3VZ0`QMEPP`"Y`(R<')O.@$!A0$`FA"9"!O=71P=73O`@!@!/$# +M;V)J96-T+7-T>6QE(&%P<')OR`,`@0L"^@#@=&\@:&%V92!M=6QT:7`E```A +M!1!V$@-`:89`@4.%CHN`0+( +M"0#"``]D&O__________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M________________________:E`*("H@3U(4``#XNFX@2!I +M;G9O:V4@82!P87)T:6-U;&%R(&9E871U!E('-O;64@=71I;&ET>3X`!8P` +M`+$!\09P2!D8737`%9U +MP"`&$#`2L`,VEN(""!I;G1E7,N"E)%041-15``1"!L:6)M`=%B=6YD;&4N"@I1=65S^@*@/R`@ +M27-S=65S/U(`UBH@:'1T<#HO+W=W=RXX`$`N;W)GDP``2`$0:+@"L&9O`<``$D!0'-U8V@G`%`J(&5X84D`0',Z(%,R`U1S;6%L +M;!4`!#X!`%(#(6%T'`@@;6'F!"!N9-`",69U;"\"!D4`$"]#"@&%`1%AXP%1 +M86-T('-@`+`@9&5M;VYS=')A=+P`"-E)ZT``V7-T96TZ&@D"N`0A+C'! +M#`!A#`$W`0,O`P`+``(A``2:`P,S``"(!`\T``L`(@`,-0`O870T``PH870S +M``8!!B$N,[8+$'-E"H!O=F5R=FEE=_,"`*``!0H,`'$%,'=H;Y$"%"JD"H5? +MPH"MP(2 +M9:`,`%L$$'/4!A!N2PT`U@(`DP``=0``%P(`^00!<0`!<0H(EP!S96YT=H+`#L'`2,)"=H1`,$",&5C=)D#$60Y"0,<`@5X"1!F!A(! +MMP91*B!'3E5U`0+4!B8@*`0+`!H`(VQOO`4`K0LB+``-J +M`0`9`[$J(%!/4TE8('5S=+`1!!``#XH,`P%\``(Q`+!O8W1E="UO\!`DD`-5I)4`D!`T``('5N +M3@D`[!,`UA!@FEP/@$@:6]/$WTJ(&)Z:7`R%@`$?`%-+TQ: +M5QT`HFQZ;6$L(&QZ:7`3`R]X>B,``!DT%``)"`$```H"G!`%.@$`=00/!@$" +M`J\!`[\#`KP"#Q\#&#`B,H"("`H?0?P(-F5A;;4%`A$+!8@4 +M0&ES(&[6$C%R96,P$0/?"`"1`D$@:6XMMP^"(&UO9&EF:6/E#)%O`3AN97>U`P#P +M!`#]`@.?`0![``&'"0$K%0)*#`,*`Q!M]@T0:7D'`^X2`BL`(2!B-PE!FEP,A8`!"8`32],6E<=`/\#;'IM82P@ +M;'II<"P@86YD('AZ(P``&304`/$R"E1H92!L:6)R87)Y(&-A;B!C&-E<'1_`/$*"B`@ +M("!E;G1R:65S('1H870@$ +M`?$#;F%M97,L($%#3',L(&5T8RDND@"P3VQD($=.52!T87)=``2I``+*`/$$ +M;V-T970M;W)I96YT960@8W!I;S4`ME-64C0@(FYE=V,B%0`G`'@G;71R964GNP!X25-/.38V,!,`6C0`&EP#R`FES(&1E$N("!)9B!Y;W4@9&]N)^P!`+8`\0)I8VET;'D@:6YV;VME(&$@<.L` +M('5L-P0@96%9`D`@*'-U+P$9``%1`0.;`")E;LD!!RT` +M`'P`"W$`*&1E$0`#J@`1+/```H``(FYEC@(`%@$`0`!B86=A:6YS1P*@8V]R +MP,1<#4`T6%T979E2!B=69F97(@)`@`90`$<@&%82!S;V-K970^`TEW:7-H +MN@3`P"`,,)`2L`,VEN("0"0:7,@97-P96-I;@0!T`$"J@$`.@@P.B`BDPH.NPH3(KD"(&QL/`$" +MZ`(`I0<`$0,"P05`+`H@(,P'$'#?``!L!`"6`!`@7,N"E)%041- +M1;L&!^@&X2!B=6YD;&4N"@I1=65S^@*@/R`@27-S=65S/U(`UBH@:'1T<#HO +M+W=W=RXX`$`N;W)GDP``2`$0:+@"@V9OB!$!GF-%#A)B!P`2>`<``$D!`)()`"<`4"H@ +M97AA20!`8$(&YDT`(Q9G5L +M+P(&10`0+T,*`84!$6'C`5%A8W0@T/4'1O +M<"UL#`0#Q0P`,`0&";8"(FENU@0`=`P`ZP40<],-\`4@*B!.15=3 +M("T@:&EG:&QI9VAT'2(`")P==8-(")C-`81(B0#`#@,*6]L +M30`@"@K>!P;K`P$I`0`6"0".`0]M`0$`^0<@=7/="@#:`31E"B>P`"-E)ZT` +M`V!Q(M@@13``$=`U`=\!`DD`#QX78P\+%P#3 +M36EC4P`T&-P:6\N-2P@;71R964)`/(. +M86YD('1AP$R+F@BJ0"`:&4*2!E2QN``/2`>`@875T;VUA=&EC86QL>68!065C='.H``#5``,<`E!O +M;&QO=Y,!$&8L`*!S.@H@("H@1TY5^`$`J`!6;6%T("BY`0`:`$%L;VYG50)B +M;F%M97,L$`!3;&EN:R`1``"T`5)S<&%R'1E;J+``-J`1%S2P"W4$]325@@=7-T87(0 +M`.%P87@@:6YT97)C:&%N9WX!-VUA="$`L&]C=&5T+6]R:65N`0,`8`(!'@"A +M4U92-"!!4T-)270"`10``F,`#S(`!6%":6YAB,``!DT%``)"`&58V%N(&-R +M96%TSP`!=00/!@$"`NP"`[\#`KP"#Q\#&,$B,H"4B`H9F]R-`0`A`$#,P0`]`-Q+"!E=&,I+F\!`/H#`*D"!B($ +M`1<``MH`#\@#"F$B;F5W8R*;`P$S`"=S:+```1(`#T8#8P0%!`);`0&)``]9 +M`P`*%@,S5VAE`P(`V`(#U`(2<^8%87)EF4@7L#$7`U`-%A=&5V97(@8FQO8VMS\```[@2X' +M<70@82!T:6U7`P!K"S%M87#X`C!E;G21!@/0`@%1`T!G:79EY@$A=&\B``6A +M`&%T(&]N8V6%`"%/;I`#&V7#``+D`C)P`%`@(&)S9",'(75SO`$`/06#;B!I +M=',@(D#E`!(BO01&2!F4X.475S92`B(0$`6@@@+")0"'`L(&-A +M<&%B00`!]@("9@81954"`?$`864@05!)P" +M`,D*`2L`,VEN("#U%F:7)S=)("`*8!(&$@ +M0P41;U`'`/8`%BYT``/9`P*G`0"_``*<`0&%``:X`0!V``*4`0!*`P&3``(Q +M#R!L>60!`,P``*,!!H`%,7=A;G\%$G0=#P-%`0!@```:!!!TC@!L3 +M0',Z(%,R`U1S;6%L;!4`!#X!`%(#(6%T'`@@;6'F!"!N9-`",69U;"\"!D4` +M$"]#"@&%`1%AXP$T86-T>Q."9&5M;VYS=')*#0`.`R=O9EX!`TD`,&-O;D," +M83H@(%9AP``7P%C875T:&]R:1``EPT!\@(`P1,2+NT/4'1O<"UL#`0#Q0P`,`0&";8""',5`.L%`>X/\`4@*B!.15=3("T@:&EG:&QI9VAT\`!,GK0`#)`0`DP``3@#P`"YA;2P@86-L +M;V-A;"YM-`D-`^T`,"YA8_\```(`$"VB`@"?``2H``#9#@BB!!(L&@X`UPL` +M60L0>\%1FYA;'.=`!)S +M/@MA:6YS:6=H$08(F0<1)V<"!#<``&@1,'5C=+(#`*@`,&]P92L%`#0,"1X' +M$BU8"0]D&O__________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M________________________5E!C="!S85<4``#T4VUP;&4@9&5M;VYS=')A +M=&EN9R!U4$`,6EN'2(`#%P=70I`/D#(F-M86ME(B!B=6EL9"!T +M;V]L30`"5@$&-0$!*0$Q(&EN3`$/;0$!,&%R91`"$F3:`35E"B>\`!,GK0`# +M9P$`DP``3@#U`2YA;2P@86-L;V-A;"YM-"SA`$!E+F%C_P```@`2+50`)'1O +MJ```(`&`9&ES=')I8G5!`;(L(&]N;'D@;F5E9'P`,6UA:?8!(V5R7`$%<``D +M:6YD`/(#+F@N:6X*"2T@=&5M<&QA=&5S9P`18C0"`68!$V6U`/($"@I'=6ED +M92!T;R!$;V-U;65N=($!`,4!,F%L;'4``/,!]0H@'!L@P(#+P,`0@$"(0"#('!R;V=R86TS`$]C<&EO-``+`"(`##4` +M+V%T-``,*&%T,P`'K0/P!#,@9VEV97,@86X@;W9E2!A``"/ +M`&<@)V1O8R>]!;!I;@IA(&YU;6)E2QN``5H`S!U=&^3!@#_`A!Y9@$P96-TF0,19-4``QP"!<(&$&8L``&W +M!E$J($=.574!`KH!)B`HN0$`&@!!;&]N9U4"8FYA;65S+!``4VQI;FL@$0`` +M8P!A@``0H``EP)HE)032!WFEP/@$Q +M:6]N,`!=8GII<#(6``1D`4TO3%I7'0"B;'IM82P@;'IIU`P#P!`![ +M``.?`0![``&'"0&C``)*#`,*`Q!M:P@0:7D'$F$)`0(K`"$@8C<)<7)E861A +M8FP`!@","@$,``$L"P($`0!H``([`$)E86-H/0$A=F5S`Q-Y0P!0:6YD97"J +M`"5N="(!`!@)``\/$&-"!1)O;`T&-0I4(%=I:VE2##!I;F?)`#!H;W>;#`&S +M`Q=DE@H"*@$A3VX_"`#W#`)X!@,#`0/X``&("5!A;'=A>48!`-T!*F5DB@@" +M1P!P22=V92!A="T-`(P'`,$/D&EN:6UI>F4@@M'("!);FX`-RP@:9X``5$!`YL`(F5NR0$'+0``/@`+<0`H +M9&41``/&`A$L\``"@```C0X`E@$`%@$`0``@86<##A%T\0F18V]RP,B:67-#P%O`P/G"C%D=6.Y!5%E('-I>H,1`H@!4&%L +M;'DM=@``,PP`]P@1:8<&`(0`<&5N=FER;V[7`C%S('>0`P&@`A!MV`$3`!,@%1``:A``"@$`/06#;B!I=',@(D#E +M`!(BO0012!F@``S0*%82!S;V-K970^`TEW:7-HN@1$!L30',Z(%,R`U1S;6%L;!4`!#X!`%(# +M`Q,9(&UAY@0@;F30`C%F=6PO`@9%`%$O;6EN:84!$6'C`31A8W1[$P]D&O__ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________:%!C:&EV94<4``#P/2!W:71H;W5T"B`@(&9I0#P*FES(&5S<&5C:6%L;'D@96%S>2X*"B`J($YO=&4Z(")P87@@:6YT +M97)C:&%N9V4@9F]R;6%T(B!I<^```#,`\P!A;B!E>'1E;F1E9"!T87(B`)`L +M"B`@(&1E7,N"E)%041-12X`1"!L:6(3 +M`=%B=6YD;&4N"@I1=65SK@"@/R`@27-S=65S/U(`UBH@:'1T<#HO+W=W=RXX +M`$`N;W)GDP``2`$Q:&]MIP"`(&]N9V]I;F6H`)V%T:0`K871H`&ES:6UP;&6U`$!T;V]L,P$` +M0``#`@!R>F-A="P@8@<`$G@'``!)`4!S=6-H)P!0*B!E>&%)`$!S.B!3,@-4 +M2!F:6YDT`(Q9G5L+P(&10!1+VUI;FF% +M`1%AXP%186-T('-@`*$@9&5M;VYS=')A-04`#@,G;V9>`0-)`#!C;VY#`O`" +M.B`@5F%R:6]UP``7P%Q875T:&]R<\`%42!A;GD@\@(``050+@H*5&B=`3!P +M+6P,!`-V!3!O'2(`#!P=71>`C`@(F,T!A$B)`-I +M9"!T;V]L30`"5@$&ZP,`%`=!'!L@P(#+P,`0@$"(0`$F@,#,P`` +MB`0/-``+`"(`##4`+V%T-``,*&%T,P`&`0:`+C,@9VEV97/?!H!O=F5R=FEE +M=_,"`*``!+L%$&%Q!3!W:&^1`A0J[`B%7W)E860N,RP0``&["`T1`%%?9&ES +M:Q8``GX'`Q<(`3X``QP``)D`$'9?`0*W`F%E9"!C86R)!Q!SU`9!;F-EP$2+8($4W,N-2!D5@(` +MG@419?L#`/(`Q&UA=',@``&I`5=H+`#L'`2,)@&%U=&]M871I_P(0><$",&5C=)D#$60Y +M"0,<`@5X"1!F+``!MP91*B!'3E5U`0(U`B8@*`0+`!H`06QO;F=5`@"M"R)S +M+!````4+`;X+$G,W`E)S<&%R`*%35E(T($%30TE)=`(!%``"4P`/,@`%84)I +M;F%R>2X`P"`H8FEG+65N9&EA;J(!8VQI='1L91$``OH`\0))4T\Y-C8P($-$ +M+5)/32!I;;<"@"AW:71H(&]PRP/`86P@4F]C:W)I9&=E10!B2F]L:65T*0$! +M[P$"20`U6DE0"0$#0``@=6Y."3!R97/3!G!OU`P$3`%HW+5II<"8`V$UI +M8W)OB,``!DT%``)"`$` +M``I58W)E873/``$M"0\&`0("J@,#OP,"O`(/'P,8,")R9:`-46-T960B1P," +M3P#$+"!W:&EC:"!W:6QLB@`!5@`%R@%A(&5X8V5P0`40"EL)`VD"42!T:&%T +M0PX0:98%)V%XR@(@("@6!0$T!`"$`0-$!`#T`V`L(&5T8RGO"P+Z`P"I`@8P +M$`&&`0+:``_(`PIA(FYE=V,BFP,!,P`G0`&@`0`L!!0 +M97-I9VZP$D)O(&)EO@(`0`0!7@$X;F5WM0,`\`0`_0(#P`!APD!HP`" +M2@P`31%`:7)E;?8-$&EY!P/N$@(K`"$@8C<)<7)E861A8FP`!@","@$,``$L +M"P+4$`!H``([`$)E86-H/0$2=MT3$WE#`%!I;F1E<*H`)6YT(@$`1`T`#P\0 +M8T(%$F]L#08U"E0@5VEK:5(,,&EN9\D`,&AO=_@``K03`*T!`]H``O<3(4]N +M/P@`]PP">`8`\PX`4`8#S0`!<`!3;'=A>7-S""IE9(H(`D<`<$DG=F4@870A +M%0",!S!T;R`A$'!M:7IE('-TM0@"4@A0<&]L;'4B!P;D%$%D;VXG[`%P97AP +M;&EC:0T58&EN=F]K9;P2`>L``7\*`\X1("`HTA`E(&'["@"A`2`@8>D``2<0 +M`BT`",T`%&_Y"'`I+"!I="!W<`!!(&=E=!D3`5T*`*0$-R!);FX`,BP@:8(5 +M`9X``5$!`YL`(F5NR0$'+0``?``+<0`H9&41``/&`A$LY0D"@```C0X`E@$` +M%@$`0``P86=A\P\`7L#$7`U`-%A +M=&5V97(@8FQO8VMS\```[@!#%FQ6QE(&%P<')OR`,` +M@0L"^@#@=&\@:&%V92!M=6QT:7`E```A!1!V$@-`P",B!O9BL`,VEN("2!I +M;G9O:V4@82!P87)T:6-U;&%R(&9E871U`<``$D!`/X&`"<`4"H@97AA20!`4$`(&EN^``(M@(B:6X#"``0""!F:34!`'P`\`LJ($Y%5U,@+2!H +M:6=H;&EG:'1S(&]F(')E8P8"5&-H86YGH`*P0T]064E.1R`M('<3!P"Y"&)C +M86X@9&^?`#-T:&DI`*!)3E-404Q,("T@T`'2(`")P=28)<2)C;6%K92(D`P"D +M"2EO;$T``E8!!NL#`)0`07,@:6Y,`0]M`0$P87)E3@(29-H!-64*)[P`$R>M +M``,D!`"3``!.`/4!+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_```"`!(M5``D +M=&^H```@`0BB!+`L(&]N;'D@;F5E9,4($'G*!0'V`2-E%7W)E860N,RP0``#1 +M!1UE$0!17V1I +M=&%R+C54`0CQ!$%A8F]U4P4@"`"X!!,B +MO0(R+F@BJ0"`:&4*2R"```[!P$C"8!A=71O;6%T:?\"$'G!`C!E8W29`Q%D80T# +M'`(%>`D09BP``;<&42H@1TY5=0$"-0(F("@$"P`:`$%L;VYG4`9B;F%M97,L +M$```!0L3(!$``&,`4G-P87)S?`(A`@@;W#+`\!A;"!2;V-KFEP,A8`!'P!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC +M```9-!0`"0@!```*56-R96%TSP`!+0D/!@$"`JH#`[\#`KP"#Q\#&#`B&-E<$`%`+D% +M!&D"`M<1`$,.$&F6!2=A>,H"("`H%@4!-`0`A`$#,P0`]`-@+"!E=&,I[PL" +M^@,`J0(&(@0!FP$"V@`/E@,%`<@#82)N97=C(IL#`3,`)W-HL``!$@`/1@-C +M!`4$`EL!`8D`#UD#``H6`S-7:&4#`@"_"`/4`A)SY@5A?P(-F5A;;4%`A$+02X@(%1`%%-I4,`4&EN9&5PJ@`E;G0B +M`0!$#0'E%@!"!1)O;`T&L`M4(%=I:VE2#`,,$S!H;W=1#P*F!P!."`/:``N@ +M%03\!`#S#@!0!@/-``%P`$!L=V%Y1@$`W0$J962*"`)'``_0%__@"?H#$&,W +M!@`%&,)A=&5V97(@8FQO8VO5"@#N!S`@:70(!D(@66]UYQ,!Q`U`8F%C:T`# +M,69R93T/,'!A2X'<70@82!T:6U7`W%O2W,``"."5)U='!U=.\"`&`$H&]B:F5C="US='G@ +M&4%P<')OR`,`^10"^@!0=&\@:&$Y%D!U;'1IPQ,$J0`"`00`N0A5(&]P96Z> +M`!0@]`\A=7-U!Q%I(0AC:71S(")`/``2(KT$$',3&P7J!`,<`'`@:71S96QF +M4P$`?000+P(/8'1E;B!U7,N"@`!`/^)`#L7#Y\!30\`'@M1-S$Q-S4`'F$Q-3$U-3(`'B\U,0`> +M_U771F5B(#`Y+"`R,#$S.H<*D2`S+C$N,B!R93(3GF0*"DIA;B`R."D`(2=S +MJPM`=V5B!A(N3``N,3-,``%U`!LQ=0`/*0`&%S`I`&%$ +M96,@,#=2`$`R.B!)4AL!"`P("@4#T!0`[PP991H,`)T%`ML-`DX8`9`(A"`* +M3F]V(#$Q5``@062V&P:L(H-?7TU!0T]36!<-`(('.&EN(,01!-D/(G)EJ08` +M)P4`N`P2:P@','-T;TL.`+@B?PI/8W0@,C!K``4`.08`A@82=J43`@,,`S8` +M`[P!#Z$``"MGF]P5`%64V5P(#*!``VH`0+.&7%T;R!S +M965KD`I&@'5`@DX`P#*"C)I97-.``*:!&$Q.B!.97>:`PI(``0;`UES(%-&6`,% +M"S\`0$)U:6QK!0"Y`:)O;B!7:6YD;W=S(0$#YP4.2P$K,&%+`14P2P$P57!D +MN!5T`P,,RUS._@6"*$9`ADA$F_B'$!H87)D4P(E+W-;`E%B&0"5##!E;747&6D@8G)O:V5B`#`R+GAG!`!W +M$`&O)2%O9K(6<5541BTX(&AH`!)SF04%^P!`4F5F85D'`04/$%]R#B`H*7L: +M`"\-46-O;&QEB"$`XPT`2@\P;&4MJR(`W`<`YR@!EB(#+`$!D`P@;VPA`P,2 +M)!!S'Q\@=W(,`0-W`!(Q$`:!,3H@4W!L:71?#0(`!@`L`0&1!C!P87)N`@(> +M%P`T"`/``@":`Q%L^24";`(!QP`5,30#`X(#`L\AE`=V]R:V(!9')E='5R;JP<`)`B`2$/$&;N +M`@%9`7%A8F]R="@I1``&-04`M0$`>0`W%SM#.3`"`07@ +M`"9O;LT#`=P'!GP!$4;T!@`G`:)!25@L(%12538T]QJ@;W1H97(@<&QA=(4! +M$G/-!@+4`B$P.D`<`\T#`1T'`EP"H3`Z($Q(02],6DAC`P'J`S)L(#`U`B$P +M.OPM`!L:`Z,F!T,F$&5F!`'?$P*5!`$N`P+1$``)"S!TH2`-@48F5N(&-O<)01``X#`1X2!,@)`4$``XD%$#`(`@&R)P!X`'8@ +M36%C($]3J0(`/``'K@0!.@`#0@(D,#I0``?K``"J"0/]`A!S7@D"[@!4&D1%0*G!`/4 +M!P`:`0"4'0.-"@)C``:;``-=!`'?(080!00'`@0;`V!C(&-R>7#%!`+!#`&/ +M``/[!B$P.CT=`0("`"P&`A`$`"8#`$<%`BH``@4-$C``"`/4`Q(Z+@=`+6=I +M9`8``"H$02`M+74.`!!U#@`!!P4#,@X#P`%@4F5D+6)L8!8`_"(!E`<&_@$! +M&14@97)D`P,C`@!4!`#.`@!8*P%.``,)`P!*`F)I;FEM86RM``$3#7@@;&5G +M86-YM0#,O +M`G@5`,0#`#(=`I`%`W8(`[X!`+\'$F0K``"1(#EL9&5?"`!=&Q!LNP$`%0X! +M0"@A963+`P80`55296QA>`,"`,(%('-T7P;09F%I;'5R97,[(&UIF7'`P`M`0!Q`0-7!`!_&"%O;88'#%$``8X%4&YT-C1? +MS`L%``>@;V9F7W0L(&1E=@<`,&EN;P<`,'5I9`<``#\#$&<+``*<``7^!`08 +M*`'"$#9!0TQ%"0)U`!4QN@024SD#!C48`20!!28#`$0!$C`B!P%J!``&$0)\ +M)@.6`@<*"3$Q+G@-%P&,``:%`Q!2R`=%869I;PX)`54`!<,%$$'''0!6``?S +M(P4Q!2%L>2P/!/T"`EL`!;L!8$EN=&5G) +M``9"``+3`P`I`Y!F=71I;65S*"DX+F)#>6=W:6YK$@9%`0>'`78R+CQA`;&5A:U0!"!X!`$@`$G,S``5<`0!D``FUA+WAZ6P,#X0(`9P`$%B`)`@@"0`0` +MGP43>?(.`$D`$4C()"`@9_X2`D4``-@)!$$`0$]P96Z4)7`B9WIS:6`@)[``6)`D!!9&1IR0HP86P@2@!` +M-P)M(B%S98$#!+`=!),-!'4'85=!4DX*"1PK06ES(&/Z +M,Q5OPP<`U1U0861A<'2;."!N91PC,V%R>;L!"=\`55-T=61I8`L`E@`/2@`!-`E!;!$# +M``@!`%HA`5\``_40`/,``.D#,$1E8E\!L4)U9R`C-3$V-34.`?$.`*8$`+$H4$AUA,` +M2P$41:L>!]$(`8(`)&]N*Q8!\0P"]PM`;F]W"?P#`9<2`78,$G11``85!@#0 +M``.@"@8,#A!?*A4@>5\/!A!?;P8P*"D@6"X$[`\`00PQ+`H)2!R7!,@961S(`#/"P"])@!1 +M,#`L"@E4!`"`!P!:#0#B!@!A!0:^`P`\`R!T(",%"7$F`;L`!LHA(@H)?0`4 +M<^@OQ6)E(&UU8V@@96%S:>8-`H\/*RX@HC,`311":&4*"3$8`5\1"$(G%',] +M)P;1#P"#'`-Q`!(N_!`"MP80.$4$)&YY:Q8:+Z\#`HH6`+L!#_D#`@U)``J[ +M"0B[&0+W'`%*``1;`@+Y#!!CN@$@97)^)2ET;W89`$T&`'PT`@2US:7IE9`4/$G.*)3$@*A$)SAH`A@,/[A<"`!<-L2@I(&AAFEPEP2"_`0`P`"`@ +M82D`*RDNM@#@2F]E0,A +M(&*Q'`&[$P%-$P!7!B)A=$H`!9X'`<4(`AQ``-A"`FLK`)$I4F0@8G5GQ0(@ +M.L%`&P"!/P> +M"K`3``XT`,T``$8$`3,8!B,&`;X<`681`$LA!O8?`FD#`#\.``D)$V'=0W,B +M4V-O='0BW!80(%0```L*!9X#$VV#/A!SU`8$-0"22V5E'!L;P$0`&T6$&5D +M#0)M`0)E+95V97)F;&]WPP$_@D$V@Y0"@EP2P!$'26$`&#.%%E(&)O9(L] +M``8-`8D!`#8!,#L*"6T&$FG,$@#0`2%O=:T-P')A;F=E(&)E:&%V:2U/`$0. +M`0L,!!0[`9@)$7)R`0&K`0)],U$M3A+,&ER95<8!&@8,"-I +M9O4,!'@8`H9`.`K@-`=0/$"V!+C%E8V^!!5)L;V=I +M8[$5`C0`$',T``!.%0)/(@'V%`!V`0$8``);20*;%P-]`@;4"`E3`D0T+C$T +M>AY`9#L@:5P\`%)$`)@#`1X`&#,$0"()84H*`%,!`?`($&=+!1$O=B-@(&UI +M>'5PWRD&R!8"L0``P@D4:<0O(F0*[18`9P0"A"D!'@<2+L@?!N8.#*8`%3.F +M``*3&`7Y`@-V'0"=!A$L3`(`DP`2+)H`$"PL!`*>``$[`2!C8640$6*8"S%V +M97+;`P32)P&-`". +M``#3"P"!`&`@8VQA`B4&1E=FEC5@$! +MRR$!32(`B0H`2!@3(G`#&2*)"``6$`(U!D!N97=CM@("<0@#I``6.^0#`O$1 +M`%P"`6,$"$T!`#4"`!`A('1H2PL!>P`"G!LE.#I(#0)E#@-J)P!(`@2;`PDD +M$1PL6PT`.QH'004P26=NR@@$[`I"('-I>ND,`$,-`B@K`#0.$F&[(@#8"P#^ +M(14RC@`,7@(6,EX""BD``*@!(&)A4T$`58(`$D:,6=E=)H-`J4\`6(+!,U5`'$:`8X%13(N.2Z" +M`0(Z``!(`1)L5#$08A,9`=L+!^$/(B@MI0]`+7HI+*L#`"$/,0EO9JH-,')M +M85X2`)X?,F5S'!E +M-\4"%C'%`@HI`#!&:7BF00&U)0#H$P+X)`9A`0"G!`&Q"04]#P%J``(_*P]J +M``$,S!D"8006-X8(4#`N.2XPQ@<`@0<"SE,@=VFA%3-U?@=`70``Q`;$C>)!5!A(&-O=90<(V]FE@0'K28`Y04!?P`"J0\. +MIP`'\A4**```6P``J0,!IP`!!0`17VD!$%_?!"%B>=DQ`D4!`@"&!P8T4@2$`E`M+61I0H& +M%`!U86-L+`H)=.T!_P!386UU;&D@4W5O;6EN96Z,``T'/@D!_``%C``&/P+` +M3&%P;R!,=6-H:6YIU04`>E4!20(`3AP!54D`!0X!T@D!FB0#2@4`DP$@;&17 +M"0%5+@#Z&P1O!#!B=6?&!0$8``!``;!O9@H)(FQE;F=T:)X4D&5N9"(@9FQA +M9QX*!6$`$G,?!`96`0).``,"!!$@FP8!4@8!/@(`J08!+P0$-P`%\P,01J,! +M0"!C=71K`$!R96%L>0<`-```D0(`Z`42;AU(`0\!!38`"Q@(%C+:`@+$`0\I +M``46,2D`"E$`$4W_)@"X!D%S+"!R%Q@`E```P0*@9&]C+71O+6UA;C\.`WX' +M`'H!(`H)%``!NB0#.CL/]`4&!XD%"B@``G@``"4(`/$%`#(4!CP"`[H,4&-H +M:6QL!Q<+.P`03Y`&`-D0`/`"`O<'(B!A>U8@(&_I%P'8"P#Q#S%G:6Y\*2!O +M9L\&(PH)$P(!6!X"IQL"K%@"S0(#CQL`+1D`3P4"2C0`+5<`#P@2>88`!G,& +M$%0$!@,S```5`0`X!!-Y\Q``6!(`0@0`QB4`NR(#Y@D8.I@"`FT(`#4((&5X +MU!8`0D4$.``!YAXS,D="?R8S,51":`$"5CD-#`48,RX:`"T!!B@`$D,/"`(_ +M!R5U;E@G`LP.`%T5`7-#`-H$``,#`+(``"H!$"*:`0#Z$P##'T!N;VYEC@L% +M9!T!?@00;H`,#(O,V(#`7T``-@"`68( +M!M,#D$IA;B!00P`4,#`!`,`-D2`.L( +M,$=.55L!$"><*$%G+71AE`(&[UP`FP`U;W-E,@`!7QA`960@;2\B0'=A&%C=&QY"@EA*R``YA<@-$>T"`/@$@=H$0&=`0(;#@=G``!;`0!F``=#`E`H +M/CA'*>,`!3X"`-0``-P20V%S"@E&.`'M"T!)('!U\"\)C0(`(1`#)`$%&"\` +M3`$`P50!A``%+`<32=0(`=D+`-@'$&5_)P`!`U!N+6UA=&\%`!5=`-0^(6]R +M00R".R!)"@EH;W!(#9$@979E;G1U86P\)0'Q3``?`0`P"S)D92`G"@!#*`+. +M"0#.50,5/P)K#@R7!A@SEP8`J@`5,"X!($-O(QH0=9``!*T`!'8%`%P"`9@J +M$F7?``8U`!!.+4T!6%8`Y4``M`03+/<+`7`(,")(:>\*('DBM0$#3@`@+C$X +M"0'/#`"O`!0Q.0`#Y"$&7```F`<5>C0\`)<"D6EM;65D:6%T90T!`9`X,$5/ +M1M$J`(P?,'1R><\/`?X5!<,4`!$.,')E9V$F`8D+`.(/`%T%`-(D`!4``,\; +M`6X2$'B2%0):#P3+"P"=`R%O9H0``Z$"`&4(`+X[#Y$%!!@S:0<`*``#T!`0 +M-]`C`54!$TU''"`N8205`4X'`!($$B#'(!,O`P@$:A)#"@EA8_P!(61O*`!1 +M@,%1DL# +M#`H`QP5`*"D*"4L'`=$2`+4,$FUJ5B5I;I(+`Y@``P8=#GX#!RD(`)@`!B@` +M`:(X`88"`.D"`RL#4R`P+C,ZO#P&[A`165TG!`2*;L``NL]`GX2`!L\`PP"`SPP#G8`!V$-4D%U9R`S+R02-^,R`+,R +M`)D#!+P&`BL>`(,+(W,L7&,`J@4D86[/6P2`!40*"2A!K1<991L1`*HE(2XI +M;``#310!F`1`860@9QD+\0$Q+C$W("TM<&]S:7@@+2US22<$D@<2+C<`!3@, +M$U*S&F!S=6ED+W.+.00R$03O"T`[(&ET'00%=@0@"@E/&D!RQ,2(M+6`%%"W0`0,R!@&^)0"]*!5RF!,1 +M"ND`!H4&"5@$-C(N-L`#`$@!!B@``0D'"]4-!\`-`ED&`&T&,6%N:QL'`88+ +M*`H)$B4#NP`%[`($0!X`20T"&P0!N@H$Z"LQ0U9361\`V$@G=6R=`0NT``?Y +M#@(I``_&#`,8,AL(`5$`!2@`!E,*"B8B$B=/)@"$"@1$(0&4`A%D*`4`H`($ +MXQ,R8W)I6!A2\`!ZP' +M`8HD`?(]`/T+`'D("%H0`.````$/`(P#`&4H`/8=(!"PL! +M%C(Z$PHH```+`0[=!1`@D0,"3"(`!`P"EP-0>2!C;&\0#@"5*4%T8L<`2"Y`0`2%0*7#0#)-0"F'!=Y@A.!4VME +M;&5T86Q\"P:,"`%=!P/L`08"!0OL`1HQ[`$&*`!01FQE +M`@$I`1%A(2`!RET":0(`)`%B/'-I9V@^VP`&204!<@(!=!D`]P0&.!P`A0-0 +M,BXQ+CDW"A-TMPD":0`A"@EJ``!L`0\7$``#80`%NP803,0*'!`#*,#!U;&00!!!RY0('H0(Z.PH) +M4P`!F@D2=\9.`,D+`%\#`WL"`NP#`I(!$&Y3,@#,:`!T`P6-#C%T;W7L`@!, +M!0""10-@`14QX1$+_@`'-@DF"4P[%@"!``#L!`*Z(!!N9AT!*B$`"0$`=00` +M!`,`_D]$97)I>&,`!:4'"V,`".4(`,0!`QHC#'8+)S%BZP8**```P@D&50`1 +M7PQ%`]9G"KT,`48=`!$:(6%L4$%E+@H)3F]TM@4!3@8$BP$"B0$`IQ8!-&T* +M<@`)NAP1(LH&``\!47)EP1$&XN2!%N/2T`?AH$4@`%;@$,4@`6-,("`5(`!4L2!/P7(6%NPT4@8FS* +M*0#[(!!AM0D!R@4`U1$`'``!"P<`_PX`;VP!NB\!)@`!#D@!3@D188(3!75$ +M`>T70&]R(&>R4@`_#`!N$"1B96T+``L"`P,>`BXO`#4M`2PQ0&]T:"!:!P*< +M!0'##Q-R0PR4;VQEY!0J(`1%(#0<$1PT@W``%J!`=B +M!@!<`08I```K%`'M`0">`@!X`C%S("BB``!W!0#C`@)3"Q``#U!(`200"O0('_0`( +ME```^A)`:6YG+Z,#`%L-`7H``38*,7!A>-4`!>T#`+T6(G5NI0$@9616)`$V +M`0^Y"@,W,"XR8@<`*0`%*`!`($ET)T0*$71)'#)E8W3&`1!I%@"S<')E='1Y +M(&=O;V3]`0;U"1(R&201;^I#`=<:`+\F(&]F[`L480H``_T& +M``D#`(<.`/T(,$=E;M@``;P#$RAQ+3`A*2!0.P'+'0(6`0!$$0%"``'H'[)I +M0@A +M=""X3X1L8VAM;V0H*6L`!245!Q(#`74!!]83`6L`!2D`$47*,`8(`S-E`2!W:#(!`24` +M`Q$(`4\`(6)Y00`!SAE1('1O;VRM!``W!@+F*`4N``*%!@';'#5M:7HL`08U +M"P=L``$L`0?9!0`L`0,'0@(U`@'0*`%?$0#Z!@'1*`&-!@9$``"<%@/T5P*A +M`"1F($8!05!%4DTW`001`&A/5TY%4BRD9")R96<0`3L`<71O(%-5240S`!!3 +M8`0`LQ@`=A<%F4X.B@H78AP,"B@`$4%F"`"J!05@"P"1!A$B!RX4(KL0$'/: +M!Q%A?P`"&S4&D78`YP,`)48Q("!"0Q\`L`0`APD0:;$$`O4``"U=P'D:"`@8=,5865R+6=R +M8?@T`4X/,&9A8UX"%F&'$``C`03;%0VW'P$:`0`E&@",`@/E%0#R,@&)9P., +M:0%`$`*T%0/&`P"C-`&B&`1G`0%'`"%A"P,-$011 +M`"!D99X)$&*A!0$4-S%Y;W5#``1*&@():!(I5T``FP!A;W9E!Y<#`D<5`7(!`G(` +M46EN=F]LU`$$\P$!S08$!%4!40T`4P8`!@(`7&(1210=$V.*"0&"-!!X80L` +M``(@;V;/$>(@;W9E@J`:L&%2W(`0'8-0)T'@,^%0P2`3_`$`R+C`[Z0("PPD`9Q]!<')O=/P+`+,Y]0-I +M;F0@(VEF9&5F)W,@=6YT:6R@-P'#<0+U%@"S$3-Y=&@T"P%B`P"L`P&L`@)X +M``*['@::``#8"0OK``>7%P#:!0*!`0`;&S!S92@`>5$@5&AE>9<)`$XL`HX. +M`.L"`&8/`4L``#HJ%6;B'PIL`,!R96-U`0"S#"%S90($`BD#`$D($&``"I`2`M<",%"W8+`@5.`;%P!!H`$"W6(E!I9FEC"@QX +M#>5.``AH/`Y@E$3;N"!`@ZVL!?2<0.P8`$6Q-*0#_!2!O;$\0$F@C*`+9 +M``%'"@!?``&(`0#V!Q`GIQ81EQ`:\G4&QE('5P10<`8S0"/``` +M=@@@;V[+*T),1$52=@"B4U5-34%22453"OT0`JT%#V0#`!HQ(0$#(2,0-ED. +M")DE`%87(&YD;P$2=-E#!8@/"98C,B!R96YP`,L``3<-``EE(&]R"!T"*!,` +M3@(%7`8@9&5N$P&,+0">`0.3,1`V9R,`Y)`!L!`5X`!?P!$$FX)C%P;W*M +M!`MF2@"C95!T:6QL+3`'#%\U`&(``.4%#@X!&',C:0'8$WPM;VYL>2XI?`!@ +M4F5O@K,:@!J +M$P&'!`&*&Q)S^!0']@0`ZP4"WPP"B#@#Q84.GL'`5(J`)(A +M`0%1`3\Y!/<&$BR^(`!Y`#=087CZ`0%>'`(6?Q$N_DT"`!L;-=H9`;X!`_8! +M!+41"4=/`#X.!%T9`!\+!E\9`+L%`$83`K8$`A\2`',-!)0$"NE*`F0``N1* +M`*X``#P44&%S($DG'`-`="!Q=;@3`)-&`-A:`:P)`)@"`C8``T&``((!G&AE +M=7)I8@,!0@'`1P)5"X*3V-TZ@(2-5A7-$=.5U,`D#`/87`2L2"\`#`W`#`JT-*C4Z,0(#7P8!544` +M7@,!*0\095X)$7G=$0`]`@3N0S%S("@*"`(K'`(0"@8<``*>&$PQ34(I<0"@ +M36%R8W5S($=E:7T'`%8<`!\'`6<1`.,-`;)Z`[PZ!KD#`'D``SP!\PYX(H``$%\0FMT;W!?>P#J&0`O``;'``&%"0*5``!]``". +M!`+*%0`.``$T```J+P.W"P-1#V(U.B!07`F`Z2UW86QK6``!J!\`E@4"DP("70`#X"L1-6!A`/U#`+@'!%4` +M`3(``2%;$#N$(@"4``0/!0"*#`#2`11YHQ(0--(!(6YY*RH0+7<(`,4](6QE +M+P(!U!$`2#D!5@,!&U(#5@`@86PE#@`=`0'5'P/L%@$`&@4Q.P1S``0&.P2_ +M``!]``.'!Q$TBBL`I2H%FW@#;X3Q!2P@2%`M55@L(%5N:7AW87)E+"!S:2D` +JTRH"+@$`?@$1<#T``I(!`'P$'P`!`/______;U````````````",W%#R +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lz4_B6.tar.lz4.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lz4_B6.tar.lz4.uu new file mode 100644 index 0000000..97918b9 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lz4_B6.tar.lz4.uu @@ -0,0 +1,1197 @@ +begin 644 test_compat_lz4_B6.tar.lz4 +M!")-&&1@A;\@``!O>&9I;&4``0!+X3`P,#8T-"``,#`P-S8U"``B,#(0`"(R +M,`$`_P<@,3(S-3,U-3,U,3(@,#$R,#(S`"`PEP!+`@(`KW5S=&%R`#`P8W4' +M`0M2,!46%C="!S8`"A(&1E;6]N4$`(&EN^``(M@)A:6YF;W)M&@00 +M(+@&!+T"\`E.15=3("T@:&EG:&QI9VATP`"-E)ZT``R0$`),``$X`]0$N86TL(&%C;&]C86PN;30L +MX0!`92YA8_\```(`$BU4`"1T;Z@`#*($LBP@;VYL>2!N965D?``Q;6%I]@$C +M97)<`05P`"1I;F0`\@,N:"YI;@H)+2!T96UP;&%T97-G`!%B-`(!9@$39;4` +M<`H*1W5I9&6V`AA$5`8$T@$"=0`!MP&R'!L +M@P(#+P,`0@$"(0`$F@,#,P``B`0/-``+`"(`##4`+V%T-``,*&%T,P`&`0:` +M+C,@9VEV97/?!H!O=F5R=FEE=_,"`*``!+L%$&%Q!3!W:&^1`B,J(-D'A5]R +M96%D+C,L$```T04=91$`45]D:7-K%@`"?@<(/@`#'```F0`0=E\!`K<"865D +M(&-A;(D'$'/4!D%N8V5SK0(`DP``=0``%P(`^00!<0!8($%027.7`'-E;G1R +M>2XS30`"]P,2(FL#!:L``20`4"(@=71II`59(&-L87-$``'O!49N86QSG0!@ +M]!;!I;@IA(&YU;6)E`D09BP``;<&42H@1TY5 +M=0$"N@$F("@$"P`:`$%L;VYG4`9B;F%M97,L$```!0L3(!$``&,`4G-P87)S +M?`(AB,``!DT%``)"`$```I58W)E +M873/``%U!`\&`0("J@,#OP,"O`(/'P,8,")R9:`-46-T960B1P,"3P#$+"!W +M:&EC:"!W:6QLB@`!5@`%R@%A(&5X8V5P0`40"EL)`VD"42!T:&%T0PXQ:7)E +M40`!\P,!R@(@("A3"@$T!`"$`0,S!`#T`V`L(&5T8RGO"P+Z`P"I`@8B!`&& +M`0+:``_(`PIA(FYE=V,BFP,!,P`G0<280D!`BL`(2!B-PEQF4@'!L +M:6-I=&S9"4!V;VMEO!(!ZP`!?PH#SA$@("C2$"4@8?L*`*D`("!AZ0`!)Q`" +M+0`(S0`4;Y4(<"DL(&ET('=P`$$@9V5T&1,!70H`I`0W($EN;@`W+"!IG@`! +M40$#FP`B96[)`0P,1<#4`T6%T979E`!,@%1``:A`` +M"@$`/06#;B!I=',@(D#E`!(BO0012!F4X.``P1$2(A`0!:""`L +M(E`(H"P@8V%P86)I;&D2%`8#`07Q``+S#P&W!`CV!0&7`8`@:6YD:79I9&P. +M`&@%(6EEA`$`.A("0@`$K`4`-@$A=&^L#3!D8737```%#A8Z+@$"R`D`P@`2 +M8>P"`,D*`2L`,VEN("2!T:&ER9"!P87)T:65S.X,``P(`87!L +M96%S948``'L`\BET:&4@875T:&]R2!Q=65S=&EO;G,N"@I4 +M:&4@=&]P+6QE=F5L(&1I4$`(&EN^`"`92!F;VQL;W>V`'!I;F9O +M%#36%K94QIM`!(ZU``` +MDP``3@#U`2YA;2P@86-L;V-A;"YM-"SA`$!E+F%C*P```@`2+50`)'1OJ``` +M(`&`9&ES=')I8G5!`;(L(&]N;'D@;F5E9'P`,6UA:?8!(V5R7`$%<``D:6YD +M`/(#+F@N:6X*"2T@=&5M<&QA=&5S9P`18C0"`68!$V6U`'`*"D=U:61EM@*" +M1&]C=6UE;G2!`0#%`3)A;&QU``#S`?4*('-YM`_`$,R!G:79E2XS!`,!JP(2(FL#!:L``20`Z2(@=71I;&ET +M>2!C;&%S1`"6:6YT97)N86QSG0!@P$2+8($4W,N-2!D5@(#I@0@ +M:6QV`]1R;6%T-50!"/$$4&%B;W5T&@$@P"`+"!I;F-L +M=62*`8%H87)D+71O+3`&`J@!$G-'``!!`&%M;V1E$D#(F5R60<#>`('(0"P;V-T970M +M;W)I96X!`P!@`@$>`*%35E(T($%30TE)=`(!%``"4P`/,@`%,$)I;LH$`$(` +MH"`H8FEG+65N9&GS!(-R(&QI='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I +M;;<"@"AW:71H(&]PRP/`86P@4F]C:W)I9&=E10!B2F]L:65T*0$![P$"20`U +M6DE0"0$#0``@=6Y."3!R97,G!W!OB,``!DT%``)"`$```I58W)E873/ +M``%U!`\&`0("J@,#OP,"O`(/'P,8,")R9?X(46-T960B1P,"3P#$+"!W:&EC +M:"!W:6QLB@`!5@`%R@%A(&5X8V5P0`40"EL)`VD"`A4,<7)E<75IP`#GP$`>P`!APD!HP`"2@P#"@,0 +M;6L($&EY!Q%A+PD#*P`A(&(W"7%R96%D86)L``8`C`H!#``!+`L"!`$`:``" +M.P!"96%C:#T!(79E4,`4&EN9&5PJ@`E;G0B`0`8"0`/#Q!C0@42;VP- +M!C4*5"!7:6MI4@PP:6YGR0`P:&]WFPP!LP,79)8*`BH!(4]N/P@`]PP">`8# +M`P$$S0`!<`!`;'=A>48!`-T!*F5DB@@"1P!P22=V92!A="T-`(P'`,$/D&EN +M:6UI>F4@2UV```S#`#W"!%IAP8`A`!P96YV:7)O;M<" +M,7,@=Y`#`:`"$&W8`1-R6@,%,`(`6P`"?P`1>7L#$7`U`-%A=&5V97(@8FQO +M8VMS\```[@2X'<70@82!T:6U7`W%O8!(71O(@`%2@!2="!O;F-\$B)/;AP."\,``N0",G!R;SH!`84!46-T;'DM +MS`"2960@;W5T<'5T[P(`8`3Q`V]B:F5C="US='EL92!A<'!R;\@#`$,2`OH` +MX'1O(&AA=F4@;75L=&EP)0``(040=A(#0')E86W\"E4@;W!E;IX`$R`5$`!J +M$``*`0`]!8-N(&ET2!B=6@-$B`D"`!E``!Z``#-`H5A('-O8VME=#X# +M27=IP`28D(`!*P%`#8!(71OK`TP9&%TUP``!0X1.L$"`2X! +M`L@)`,(`$F'L`@!A`P$K`#-I;B`G`0"/`C-A9&2.`AAA]PP!UP<#'@]19FER +M>D``,P``*,!!H`%,7=A;G\%$G0=#P-%`0!@```:!!!T +MC@A<"+``` +M.P``!`,`2P+%1`G +M-Q,`)AD`%@)S82!F=6QL+98(F-%#A)B!P`2>`<``'`$`)()`"<`%"I/&@]D&O______________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M________________________________95`@:6YS:6(@``#P"6=H="!I;G1O +M(&QI8F%R8VAI=F4G1X`<&QI8G)AP#S"2P@:6YC;'5D:6YG(&AA``"/`/0:("=D;V,G(&1I2!I;@IA(&YU +M;6)E6]U(#\!8"X*"D-U +MFEP,A8`!'P! +M32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9-!0`"0@!E6-A;B!C?P(-F5A;;4%X'-YU`P#P!`![``-S +M!`![``&'"0&C`%0@;VYL>0H#$&UK"!!I>0<182\)`RL`(2!B-PEQ4,`4&EN9&5P +MJ@`E;G0B`0`8"5!A7L#$7`U`-%A=&5V97(@8FQO8VMS\```[@2X'<70@82!T:6U7`P!K +M"S%M87#X`C!E;G21!@/0`@%1`T!G:79EY@$A=&\B``6A`&%T(&]N8V6%`"%/ +M;I`#&V7#``+D`C)P`%`@(&)S9",'(75SO`$`/06#;B!I=',@(D#E`!(BO001 +M2!F@``P0&%82!S;V-K970^`TEW:7-HN@3`4X.475S92`B(0$`6@@@+")0"'`L(&-A<&%B00`!]@($ +M`P$%\0!A92!!4$ES/PX(]@4!EP&`(&EN9&EV:61L#@/;"`"%``(5!@!"``2L +M!0`V`2%T;ZP-,&1A=-<```4.%CHN`0+("0`]`!)A[`(`R0H!*P`S:6X@)P$` +ME0LS861DC@(88?<,`=<'`QX/469I1$@#R$0`6`G-A(&9U;&PME@AR9"`G=&%R)P\!`0(`(7)EK0H!0@%` +M8G5I;($&`(H``V,``"H``J(3!F,`2V-P:6]D``;3$@$P`S!F86,J!P`]``," +M```I$")N=&@#`!$"-G-A;98#%&%G!5F-%#A)B!P`2>`<``$D!`)()`"<`02H@97@;$T!S.B!3,@-4 +M,!-&%C='L3<&1E;6]NP`` +M7P%C875T:&]R:1``EPT!\@(`P1,2+NT/4'1O<"UL#`0#Q0P`,`0& +M";8""',5`.L%`>X/\`4@*B!.15=3("T@:&EG:&QI9VAT<]P`,')E8VX,`C$% +M`Z`"DD-/4%E)3D<@+0P%`$(4`,H'(61O7P8!AP4`S@#`*B!)3E-404Q,("T@ +M9`HQ86QLCP0!#0``BA8`OP`"*0`#0`41+3P``5X1`A@`8&-O;F9I9[(6$"W_ +M!0$,``)$`+5S8W)I<'0L('-E96<``"@%`ED6`F,(@2H@0TUA:V5,U`0Q='AT +MB``A<'5G$#`@(F,T!A$B)`,`.`PI;VQ-`"`*"N$(!NL#`2D!`!8)`(X!#VT! +M`0"P#!!U/1,"$!\`!,GK0`#)`0`DP``3@#P`"YA;2P@86-L;V-A;"YM +M-`D-`^T`,"YA8_\```(`$"UD`@"?``2H``#9#@BB!!(L&@X`UPL`60M1>2!M +M86GV`2-E!,"(0`$F@,#,P``B`0/-``+`"(`##4`+V%T-``,*&%T,P`'K0,1,[8+ +M`!`4D"!O=F5R=FEE=_,"`*L`!<`+`'$%,'=H;Y$"%"JD"H5?\%1FYA;'.=`!)S/@M/:6YS +M:60:________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________________________________________________]Y4&5S"B`@ +M62```/$>*B!F:6QEFEP(&-O;7!R +M97-S:6]N%0!=8GII<#(6``0F`$TO3%I7'0#_`VQZ;6$L(&QZ:7`L(&%N9"!X +M>B,``!DT%`#Q,@I4:&4@;&EB2!C86X@8W)E871E(&%R8VAI=F5S(&EN +M(&%N>2!O9B!T:&4@9F]L;&]W:6YG(&9O"!I;G1E'1E;DT!L7,@*&9O$E33SDV-C`3`%HW+5II<#D`-EA!4A$`0PI7:&4# +M`@#D`00%`A$L_`%AT!X'-Y +M`>-R86YD;VT@86-C97-S+GD`!I<`\@)I +M`35N97<7`@!2`#!A;F1[``'.`!1V6`,24,`4&EN9&5PJ@`B;G1_`!!R.P0`!``P=&EC\`0D;VZ!`02N +M`/``5VEK:2!E>'!L86EN:6YGR0`P:&]W^``"]0``C@0#+``"*@$A3VZJ`!PL +M`P$#V0("<`!`;'=A>48!`-T!\@%E9"!A=71O;6%T:6-A;&QY1P"P22=V92!A +M='1E;7#$`^!T;R!M:6YI;6EZ92!S="L`L"!L:6YK('!O;&QUN`'A+B`@268@ +M>6]U(&1O;B?L`0"V`/$":6-I=&QY(&EN=F]K92!A('#K`"!U;#<$(&5A60)` +M("AS=2\!&7,<`A!AZ0`'+0`'[P4`@`$"F0%P*2P@:70@=W``X"!G970@<'5L +M;&5D(&ENI`0W($EN;@`W+"!IG@`!40$#FP`B96[)`07L#$7`U`-%A=&5V97(@8FQO8VMS\``0:%<%(6ETH0!!66]U +M2X'<70@82!T:6U7 +M`W%O8!(71O(@`%H0!A="!O;F-E +MA0`A3VZ0`QMEPP`"Y`(R<')O.@$!A0%18W1L>2W,``!(!E)U='!U=.\"`&`$ +M\0-O8FIE8W0M2!F)M96UO +M?\`!8P``0`"\05R;W9I9&4@96%S>2UT;RUU8<``J,!!H`%,7=A;H@`$'0V!`5%`0!@ +M``'Z"0".!S!S:RQ.`P-^!KEC;VYV96YI96YC9<`!`(D`,&UA:WD`D&ES(&5S +M<&5C:6X$`=`!`JH!`#H(,#H@(I,*#KL*$R*Y`B!L;#P!`N@"`*4'`!$#`L$% +M0"P*("#,!Q!PWP``;`0`E@`0(',*T"!S87ES+@I214%$346[!@?H!N$@8G5N +M9&QE+@H*475E<_H"H#\@($ES7!1`GH@1` +M9W)A;18"M``-G`0"3``!.`/`` +M+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C%P$``@`0+:("`)\`!*@``-D."*($ +M$BP:#@#7"P)\`#%M86GV`2-EPH"MP(` +MA1(A86R)!V!S97%U96Y+#0#6`@"3``!U```7`@#Y!`%Q``%Q"@B7`'-E;G1R +M>2XS30``[P0R92`B:P,%JP`!)``4(@L+62!C;&%S1``!'PE&;F%L]!9!I;@IA(&YU +M;6+R#!=FD0<#'@'7+@H*66]U('-H;W5L9*0+`"@!,6-O<'8&0&-O;6V>"`"X +M!!,B!0XR+F@BJ0`R:&4*7PQ!(&-O9'4!`!0`!.D&`W((`G\"-&UO5$P"9!G!E2X`L2`H8FEG+65N9&EA +MU!%C;&ET=&QE$0`"^@`$7Q:10T0M4D]-(&EMMP*`*'=I=&@@;W#+`\!A;"!2 +M;V-K%V,/"Q<`TTUI8W)O2X*"B`J($DG=F4@871T96UP=&5D('1O(&UI +M;FEM:7IE('-T*P#X4R!L:6YK('!O;&QU=&EO;BX@($EF('EO=2!D;VXG=`H@ +M("!E>'!L:6-I=&QY(&EN=F]K92!A('!A``B;`%IE +M;F%B;)L``#X`"W$`*&1E$0`#J@`1+/```H``(FYE)@$`%@$`0`#X"V%G86EN +M<`!`"@$`#,`@&%N9"!W&%)`$!S.B!3 +M,@-42!F:6YDT`(Q9G5L+P(&10`0+Z\' +M`84!$6%R!E%A8W0@P``"@+Q`F%U=&AO@`K!#3U!9 +M24Y'("T@=Q,'`+D(8F-A;B!D;Y\`,W1H:2D`H$E.4U1!3$P@+2#0!S)A;&QU +M```-`"%R=2H"`RD``T`%$"T4`1%SE0`"DP"P8V]N9FEG=7)E("W.``$,``)$ +M`+5S8W)I<'0L('-E96<``/T(9&1E=&%I;,,$84--86ME3-0$,71X=(@`(G!U +M)@EQ(F-M86ME(B0#`*0)*6]L30`"5@$&ZP,`E`!!2!N965DQ0@0>5L+4&$@=VAOD0(C*B#9 +M!X5?] +M!;!I;@IA(&YU;6)E<$",&5C=)D#$61A#0,<`@5X"1!F+``!MP91*B!'3E5U`0(U`B8@*`0+`!H` +M06QO;F=0!F)N86UE+``-J`0`9`X$J(%!/ +M4TE8("`-`5L``A``,G!A>%H)`ED'`W@"!R$`L&]C=&5T+6]R:65N1!``8`(! +M'@"A4U92-"!!4T-)270"`10``E,`#S(`!1!"V0X1>2X`H"`H8FEG+65N9&GS +M!(-R(&QI='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I;;<"$2AX""!O<,L# +MP&%L(%)O8VMR:61G944`8DIO;&EE="D!`>\!`DD`-%I)4'4$!$``('5N,0L` +MBQ`@960Z`$`B9&5F?@81(F8)`Q@``*$$(VEE50$`PP$`H@&%0E-$("=AFEP/@$@:6^[$'TJ(&)Z:7`R%@`$?`%-+TQ:5QT`HFQZ +M;6$L(&QZ:7`3`R]X>B,``!DT%``)"`$```I58W)E873/``$M"0\&`0("J@,# +MOP,"O`(/'P,8,")R9:`-46-T960B1P,"3P#$+"!W:&EC:"!W:6QLB@`!5@`% +MR@%A(&5X8V5P0`4`N04$:0("UQ$`0PX0:98%)V%XR@(@("@6!0$T!`"$`0,S +M!`#T`V`L(&5T8RGO"P+Z`P"I`@8B!`&;`0+:``^6`P4!R`-A(FYE=V,BFP,! +M,P`GD#`#X'(71EVP@1.N85`2T0$&D@"G!H96%V:6QY_`@V96%MM04"$0M! +M+B`@5$`44VES(&YOX@<`@@(#"A4`DP1!(&EN+;P`#GP$`>P`!APD!HP`"2@P#"@,`.`@`;Q`R=&AA"0$"#`(A +M(&(W"0!J"`'[%2%O$P$/`P),%@"V`A!G5180:2(3`2(`!9L$`.,3(6-E +MA0`A3VZ0`QMEPP`"Y`(R<')O"AFA8V]R>`907!P4X.``P1$2(A`0!:""`L(E`(H"P@8V%P86)I;&D2%`:-`07Q``+S#P$_#@CV +M!0&7`8`@:6YD:79I9&P.`]L(`(4``#H2`D(``'(+`-$``#8!(71OK`TP9&%T +MUP``!0X6.BX!`L@)`#T`$F'L`@&`#@`K`#-I;B`G`0"/`C-A9&2.`AAA]PP! +MJ0H#'@]19FER"U$W,3$W-0`> +M83$U,34U,@`>+S4Q`![_5==&96(@,#DL(#(P,3,ZAPJ1(#,N,2XR(')E,A.> +M9`H*2F%N(#(X*0`A)W.K"T!W96)S``0R;6]VT0L/(1X&$BY,`"XQ,TP``74` +M&S%U``\I``87,"D`841E8R`P-U(`0#(Z($E2&P$(#`@*!0/0%`#O#!EE&@P` +MG04"VPT"3A@!D`B$(`I.;W8@,3%4`"!!9+8;!JPB@U]?34%#3U-8%PT`@@0$$]@\$90`` +MP@$@(&Q<`6``'E("`@ +M0_$@`9D"`V,``%(7#P(A$@]U``@)DR$#=0``3@L#=`!01W)O=7`2$`"U`R$R +M-!4!&3$5`0`^`0=\!`$H``(O!"4Q.ID>H&9I>&5S(&UE`RDQ.D4`"AH`$5/\'P+8`&%T +M;R!)4T^?``!U`%!T;R!I;8H+-F4@2-RQH`+PU18V]L;&6((0#C#0!*#S!L92VK(@#``)F]NS0,!W`<&?`$11O0&`"H#,FP@,#4"(3`Z_"T`&QH#HR8'0R80968$`=\3`I4$`2X#`M$0``D+ +M,'1R884%(6%L.P0A,CD[!$`P.B!-<`(#R`8%$`,`%04"G``!\!3P``H4!$C"%`4!L87)GQQ0!ZA(`V!1B96X@8V]PE!$`#@,!'A($R`D!00`# +MB040,`@"`;(G`'@`=B!-86,@3U.I`@`\``>N!`$Z``-"`B0P.E``!^L``*H) +M`_T"$'->"0+N`%1S"DUA>24-8S`Z(%A!4D,$`1D``T,%$3#'`34@7E0-!1([ +M/B]`(&5X:1$5`J<$`]0'`!H!`)0=`XT*`F,`!IL``UT$`=\A!A`%!`<"!!L# +M8&,@8W)Y<,4$`L$,`8\``_L&(3`Z/1T!`@(`+`8"$`0`)@,`1P4"*@`"!0T2 +M,``(`]0#$CHN!T`M9VED!@``*@1!("TM=0X`$'4.``$'!0,R#@/``6!2960M +M8FQ@%@#\(@&4!P;^`0$9%2!E"!L96=A8WFU!S%M870,!`/!4`Q`,`,AT"D`4#=@@#O@$`OP<29"L``)$@.6QD +M95\(`%T;$&R[`0`5#@%`*"%E9,L#!A`!55)E;&%X`P(`P@4@2!!4D-(259%7T9!5$%,(')A'`0@=&@;`T,@=FES^Q0#*08`R0L# +M=0`T7`8P`!H4#$%+(!T5A9FEO#@D! +M50`%PP400<<=`%8`!_,C!3$%(6QY+`\$_0("6P`%NP%@26YT96=R70(@07#Q +M&`?W!`!+!@@-!0!_'2!A=`,L$'5.'@'@`0+^&`$!$A4S5``$$0$`WR,S("U6 +MX@X&4P0&:PLX,BXXJQ$W2F%NR`,`=@L!S`@&"@,`DP#@)V5C:&\@;F]N97AI +M0(O,#G?```?,=\`#P&O +M#`*'`@]#```6,7P-,TIU;#L#`"@````"`/@DL2!B;V=U'HP``)!`P0P``"1,0*8`4$@,2XW90<1,?4`""$`<&QZ;6$O>'I;`P/A +M`@!G``06(`D""`)`!`"?!1-Y\@X`20`12,@D("!G_A("10``V`D$00!`3W!E +M;I0E<")G>G-I9R+-*`"@,`)%``+#`P!%`)!!=F]I9"!F86P*`@.2!0*(`02I +M!`&@!#!P:7`F,P!1$@+>!P`\``ME`@?\`@+%!@%_!`TI`$<0"%W()`RM! +M9#L04FYE>'1?;`\T,B@IGQ9!:7,@=6$243(U)0H),2M0969F:6-S"`%E``$> +M'@.#"!([:A/30G)I86X@2&%R2!-:6-H:6AI'@#'!T%T86UPE@LP5')UY0X!\0X`I@0`L2A02'5R9"R&`,%":L.V +MF5D!0\2)P/``S!C;W)D`D%!;'-O)R0+L0`Q8FED`(5<]<.(`H)E`8A +M97/-`S!S=&$N*`"(``,.!"%S+NH=`XD&)#@ZS@D"&P4)D`D!I@X28)`"P3=@ED;V5S +M;B?G!PLR`&)W96QL*2RS!B)I65T"@E00T%D('5NH@`"K!`")0<# +MWP`)L1J086QL*"DN("!&F`M!;F]W+)0J,&UU2!E;F]U9V@@00=!+"!W9<:\!"W@!%S1/`0$I``4E`P_8 +M`0$P9FEXZP4`;`($_!X*L!,`#C0`S0``1@0!,Q@&(P8!OAP!9A$`2R$&]A\" +M:0,`/PX`"0D38=U#3H@"?$E$W`=`-`N9G)E96)S9"YO0"@D@(&UE87-U>P,!4P8".0``30(`N@L1:1Q) +M`5TO0'!A=&@=`&$@9FEE;&31`#!U*P%'(F!M;6%R:7HZ"1!P[#L`W!<" +MMP0`N@!`+6YO+;H*(V9ICC@T;&EBS4<#;Q0`)P`+J`!B.B!3:VEPDQ@!LP$! +M8P4!2@4#_P0",0A0,S(M8FD6!3!F7W1'`#!I(P'&`2`M!@"AP$`V#0%%",!5P8754-!"8G`(H!$&:;!B5L>?,$(`H))0]5:VYO=V[(``"O)4!A +M=&5G(QD+.0$"7!8`"00"+`4"EP(.3P<,G@`!F`<`U1,#Z@@!?`D""00&/0L` +MX@(/2P`/`"8!`*L``/@(&&5;`@-:%3`@=74;$3!D93L,`1%YD`X"N`T!U`\0 +M+8$N,65C;X$%4FQO9VECL14"-``0 +M!Q(NR!\&Y@X,I@`5,Z8``I,8!?D"`W8=`)T&$2Q,`@"3`!(LF@`0+"P$`IX` +M`3L!(&-A91`18I@+,79E`A8R7@(**0``J`$@8F%S3A%DB`,!%PD# +M%0$&PR4#3`4"*B(&=0`*2P!D5F5R:69Y300!5@@`21HQ9V5TF@T"I3P!8@L$ +MS54`<1H!C@5%,BXY+H(!`CH``$@!$FQ4,1!B$QD!VPL'X0\B*"VE#T`M>BDL +MJP,`(0\Q"6]FJ@TP'0`F+P%6 +M"0#'``*Y`%!U;F-O=LQ")0H))"``S`%P8V]S;65T:5\<`.Y3`$D$`U<&("P@ +M^@4`V08`*P0<9%@!H$5X<&5R:6UE;G1,2P,O)0#;#0#]/!0M(`T#@#`/G0$% +M`K,;!O@"`^@2!&$&$'G;`@&<`0=3!U1I=&@*"8,"%'-/$P04,@%(`P#W``&B +M"6%S+B`@*%>A$P%!$P&^!0!G"2$*"8U.`=P(`!0%8&QA*9!`;4E`.@3`O@D!F$!`*<$ +M`;$)!3T/`6H``C\K#VH``0S,&0)A!!8WA@A0,"XY+C#&!P"!!P+.4R!W::$5 +M,W5S92<;!30`($-OCQL`&@M0:6YI=&E\!@`/)00Q$`#*`0,)`@28``+'`PZ8 +M`!4YR@8"P``%*``&U`4`8P$"C30`>@4"B1<)9`#P`SH@("UA+"`M<2P@+4PL +M("UF+)L8$'0^�@00!G"0#C$`0+)H*!(T2H41A;6EE +M;B!';VRJ!`"C`!!B>@T`Z0`!CP,`B3@0>H*Q`O!0D!!0`07[@4("YCH2$`@@LP +M--*)7!Y^!T!=``#$!L2-XD%4&$@8V]UE!PC;V:6 +M!`>M)@#E!0%_``*I#PZG``?R%0HH``!;``"I`P&G``$%`!%?:0$07]\$(6)Y +MV3$"10%R92!U;6%S:Z0_`T`!`_H>#G``!E@)`LL`!1X"`(8'!C12!(0"4"TM +M9&ESIQ!2+7AA='1Y"@84`'5A8VPL"@ET[0'_`%-A;75L:2!3=6]M:6YE;HP` +M#0<^"0'\``6,``8_`L!,87!O($QU8VAI;FG5!0!Z50%)`@!.'`%520`%#@'2 +M"0&:)`-*!0"3`2!L9%<)`54N`/H;!&\$,&)U9\8%`1@``$`!L&]F"@DB;&5N +M9W1HGA2096YD(B!F;&%G'@H%80`2@$@"@D4``&Z)`,Z.P_T!08'B04**``">```)0@` +M\04`,A0&/`(#N@Q08VAI;&P'%PL[`!!/D`8`V1``\`("]PT+0$D@<'7P +M+PF-`@`A$`,D`048+P!,`0#!5`&$``4L!Q-)U`@!V0L`V`<097\G``$#4&XM +M;6%T;P4`%5T`U#XA;W)!#(([($D*"6AO<$@-D2!E=F5N='5A;#PE`?%,`!\! +M`#`+,F1E("<*`$,H`LX)`,Y5`Q4_`FL.#)<&&#.7!@"J`!4P+@$@0V\C&A!U +MD``$K0`$=@4`7`(!F"H29=\`!C4`$$XM30%85@#E0`"T!!,L]PL!<`@P(DAI +M[PH@>2*U`0-.`"`N,3@)`<\,`*\`%#$Y``/D(09<``"8!Q5Z-#P`EP*1:6UM +M961I871E#0$!D#@P14]&T2H`C!\P=')YSP\!_A4%PQ0`$0XP)(5`EH/!,L+`)T#(6]FA``#H0(`90@`OCL/ +MD04$&#-I!P`H``/0$!`WT",!50$334<<("YA)!4!3@<`$@02(,<@$R\#"`1J +M$D,*"6%C_`$A9&\H`%%R:6=H=$$3,6=S+KDA!F,``,0($"VT"`!2"@$-``&$ +M#`2[``?<%`%A!``C`1!I]0``B@,,)P$-70`!D`4/E`L``.4+(&ENO2(@8V6] +M(``7$`'0#0`T`@#K.@$`*@1](`!&%0",)S!N:6/2`2)H868&4')A9W1A!P,( +M7#L`00`#M%P1<_L(%'3#!R1H88@!!F@#";H'&#.Z!P&(`0\H``40,5(:)&ME +M6@`@8F5K'`!Z`P5&2P,,"@#'!4`H*0H)2PPY!("UP +M+#X'`6,Z(0H)Q24""1$5;Z,0$"QB$0'Z#00X"U!S96=F8><%`CX"!H$``F@) +M`U8#`44B`NH2`S\""0A```001('X88`H):6YS=(0&$',C!!!TF08)&&$#IP`%I@0(7"X`T`=T +M>5]L:6YK7\P2%"S0!0,=`#!S=')O6@(N`@/T,0R6`1@RH0T`E@$&P@P&B`$4 +M,@`&`-\"0'-T("A<(S!Y972<$!(INP`"ZST"?A(`&SP##`(#/#`.=@`'80U2 +M075G(#,O)!(WXS(`LS(`F0,$O`8"*QX`@PLC"`M +M+7-))P22!Q(N-P`%.`P34K,:8'-U:60O0@(6A``X````0\`C`,`92@`]AP& +MGR80+`T<`0$,)`H)AA4"21,$43DE('06%@*7!"`N:"P>(V%DQ0EC;&5A;G5P +M?BL*8@$2+!T5``P'$7,B"@`S$A$O+Q(#W`4P;@H)!`E386YO;6$("@',6@`G +M&@5D#`$%&A=YT@$+"P$6,CH3"B@```L!#MT%$""1`P),(@`$#`*7`U!Y(&-L +M;Q`.`)4I071R>2#2*P`>!R)T;X`<`P,T("!SS`@`8V(`P!@!DB(!EQ91(&ES +M"@FF!`D.`G(@9FEN:7-H.@$!`@T`Y@P$E0``E`$37^45`*`'L'=O0:70@:&5L9"!OPT,`J`4"F@``81L!J@``O34`A2H"%R(`^1T@ +M=6U!,`!\%0)<#@3^!@&<0P#Q$&`@8G)E86M**@#K#@#Z+`$8'@#Z,`'X`@2? +M``%@`!!?&0$69?DT`)8.`*@``NXL$&AR#`$N'8!S;VYA8FQY(+D!`!(5`I<- +M`,DU`*8<%WF"$X%3:V5L971A;'P+!HP(`5T'`^P!!@(%"^P!&C'L`08H`%!& +M;&5S:,D7`'(6$&];,!%R:Q,`?0("?@$@+F.\`1%AP`008[T,`>TC`.,-`!0E +M(6-H&P`C:&5_&B`@;MX"`2D!$6$A(`'*70)I`@`D`6(\A`CH["@E3``&:"1)WQDX`R0L`7P,#>P("[`,"D@$0;E,R`,QH +M`'0#!8T.,71O=>P"`$P%`()%`V`!%3'A$0O^``R``N`4`GQ`$`2(*^0H!$`0!)`T)-3(!W0@$64<` +M0`4,XP`'"`0**0``M`8![!$0;BY($6X]+0!^&@12``5N`0Q2`!8TP@(!4@`% +M2Q($_!]``!_+P%\+0`9`@"8'@$0-`1<*`)I``#D``(_`@#$50*+ +M)P4H`0'J`P0`%P#8!0DZ"2)T;P@]!(@!!3<`#(@!![D%"H@!$4@-!P1'#2!S +M.Y`-$&70!&!N=7@O9G-M#0*X"0+B``&Y"`BK&0`-.#%E65T>5,#5S0! +MI@$C=&\R%@"A"@#-%@""$A`B^0%R(&-H96-K(H4&!%PD`T<)"Y@!!V$!`",% +M`E$7%W/$24%)3$5$H@H!=``!M64`X0(`+04"+TH!'0%`82!W89$T$&&8+0"/ +M/2-F9A@"$FG%A4''@!#5T%2 +M3A@"!@H@![<``6H$!V(&`%P!!BD``"L4`>T!`)X"`'@",7,@**(``'<%`.," +M`E,+%RU790'I``#^!@/[%P`F```^``G\&3)O=RG'`09K``+I,@0-#`2$&`"# +M/S`@;V:*;E)S:R!G;[0P`&8!`*(.(69FT0\#Q!`P.R!R5FP!`A$0:4@E$"AX +M``/4$@!)!`*]`@?]``B4``#Z$D!I;F@`!-@HQ<&%XU0`%[0,` +MO18B=6ZE`2!E9%8D`38!#[D*`S3#`!@*`:)'0%R!P"O`31'240G!0(,`Q)S``4#10,B8GD6 +M`#%I;F<8`2%W:'0N`;<.`TX;`=U1`>8\4'1O;R!F3$(`PP<`SA:A;GD@<')I +M=FEL9;`:`9DI#V`2!#@?LFES(&QO;F``^'"@$!G@`'Q08!G@`%3P,10@E`5`@9&]W +M;A,.!UX!('=H,@$!)0`#$0@!3P`A8GE!``'.&5$@=&]O;*T$`#<&`N8H!2X` +M`H4&`=L<-6UI>BP!!C4+!VP``2P!!]D%`"P!`P="`C4"`=`H`5\1`/H&`=$H +M`8T&!D0``)P6`_17`J$`)&8@1@%!4$52331H("!ATQ5A97(M9W)A^#0!3@\P9F%C7@(688<0`",!!-L5#;`U$&`0@=`'Q#$&_=/@"$`@`M +M!0(R+@$D50:+=P)J"0$K6@/0!A!3(C509F5A='7?"`+V%Q!N>P$%RCL`J08! +MPQX'EP,"1Q4!<@$"<@!1:6YV;VS4`03S`0'-!@0$50%1#0!3!@`&`@!<8A%) +M%!T38XH)`8(T$'AA"P```B!O9L\1XB!O=F5R:&%U;"!W:6QLPB8!N"\#,38" +MI`L!?@`"BBX&1P$'?'@"V1``SP("[AL*W0X(U``"S0`"1R8!G#L#=P<`'"40 +M*/8X!+]*`+$$`8,!`'T"(V]F#"<09CT3"XD``,L?$',F!`,D``%&"`!#"`,V +M)`,!>05$#@,T!`&*``()`(P? +M!2<`0$)U;7`%*!!SFPL0=&PV$3/C``"+)2!)+SQ6``@S(G)S,2`",1(2-M83 +M`\P;`$$!049)3$4A)`/B$`\V``0&1P8"[P$$^2(#-A4`I`,`?%85>19/,6%L +M._L``?\*,6QO8[`1$6$]"C!M:6X:/A)UZ"H!JP85+<@!`=@U`G0>`SX5#!(! +M-S(N-3X)`'4>!BD`LT]U=&QI;F4@04))SD81!IH``-@)"^L`!Y<7`-H%`H$!`!L;,'-E*`!Y +M42!4:&5YEPD`3BP"C@X`ZP(`9@\!2P``.BH59N(?"FP`P')E8W5RG%A%R50\P:V5EZ7$!KR=0 +M;&4@=7!%!P!C-`(\``!V""!O;LLK0DQ$15)V`*)354U-05))15,*_1`"K04/ +M9`,`&C$A`0,A(Q`V60X(F24`5A<@;F1O`1)TV4,%B`\)EB,R(')E;G``RP`! +M-PT`"64@;W(('0(H$P!.`@5@\`V`)0=V]R=&AT`!1S$S@!Q081!D;5L"30$`VP50<&%C:V&72P<">`#8 +M`1!EN`I`+F=Z"LQJ`&H3`8<$`8H;$G/X%`?V!`#K!0+?#`*(.`-S,P#/`02. +M!0)[%A0Z>P/H!`5X<`A9_$2[^ +M30(`&QLUVAD!O@$#]@$$M1$)1T\`/@X$71D`'PL&7QD`NP4`1A,"M@0"'Q(` +M`P$I#Q!E7@D1>=T1`#T"!.Y#,7,@*`H(`BL<`A`* +M!AP``IX83#%-0BEQ`*!-87)C=7,@1V5I?0<`5AP`'P0`#/`'S#GAS;FEL+F%N=&)E87(N;W)G+S(P,#4O,#(O,#4O@@%`+6UI +M='YI!`\``%H:@')B96ET96XO2P`"RA<`9@<$[8H`!Q`"M0`-OA/$%+"!(4"U56"P@ +M56YI>'=A&9I;&4``0!+X3`P,#8T-"``,#`P-S8U"``B,#(0`"(R +M,`$`_P<@,3(S-3,U-3,U,3(@,#$R,#(S`"`PEP!+`@(`KW5S=&%R`#`P8W4' +M`0M2,!46%C="!S8`"A(&1E;6]N4$`(&EN^``(M@)A:6YF;W)M&@00 +M(+@&!+T"\`E.15=3("T@:&EG:&QI9VATP`"-E)ZT``R0$`),``$X`]0$N86TL(&%C;&]C86PN;30L +MX0!`92YA8_\```(`$BU4`"1T;Z@`#*($LBP@;VYL>2!N965D?``Q;6%I]@$C +M97)<`05P`"1I;F0`\@,N:"YI;@H)+2!T96UP;&%T97-G`!%B-`(!9@$39;4` +M<`H*1W5I9&6V`AA$5`8$T@$"=0`!MP&R'!L +M@P(#+P,`0@$"(0`$F@,#,P``B`0/-``+`"(`##4`+V%T-``,*&%T,P`&`0:` +M+C,@9VEV97/?!H!O=F5R=FEE=_,"`*``!+L%$&%Q!3!W:&^1`B,J(-D'A5]R +M96%D+C,L$```T04=91$`45]D:7-K%@`"?@<(/@`#'```F0`0=E\!`K<"865D +M(&-A;(D'$'/4!D%N8V5SK0(`DP``=0``%P(`^00!<0!8($%027.7`'-E;G1R +M>2XS30`"]P,2(FL#!:L``20`4"(@=71II`59(&-L87-$``'O!49N86QSG0!@ +M]!;!I;@IA(&YU;6)E`D09BP``;<&42H@1TY5 +M=0$"N@$F("@$"P`:`$%L;VYG4`9B;F%M97,L$```!0L3(!$``&,`4G-P87)S +M?`(AB,``!DT%``)"`$```I58W)E +M873/``%U!`\&`0("J@,#OP,"O`(/'P,8,")R9:`-46-T960B1P,"3P#$+"!W +M:&EC:"!W:6QLB@`!5@`%R@%A(&5X8V5P0`40"EL)`VD"42!T:&%T0PXQ:7)E +M40`!\P,!R@(@("A3"@$T!`"$`0,S!`#T`V`L(&5T8RGO"P+Z`P"I`@8B!`&& +M`0+:``_(`PIA(FYE=V,BFP,!,P`G0<280D!`BL`(2!B-PEQF4@'!L +M:6-I=&S9"4!V;VMEO!(!ZP`!?PH#SA$@("C2$"4@8?L*`*D`("!AZ0`!)Q`" +M+0`(S0`4;Y4(<"DL(&ET('=P`$$@9V5T&1,!70H`I`0W($EN;@`W+"!IG@`! +M40$#FP`B96[)`0P,1<#4`T6%T979E`!,@%1``:A`` +M"@$`/06#;B!I=',@(D#E`!(BO0012!F4X.``P1$2(A`0!:""`L +M(E`(H"P@8V%P86)I;&D2%`8#`07Q``+S#P&W!`CV!0&7`8`@:6YD:79I9&P. +M`&@%(6EEA`$`.A("0@`$K`4`-@$A=&^L#3!D8737```%#A8Z+@$"R`D`P@`2 +M8>P"`,D*`2L`,VEN("2!T:&ER9"!P87)T:65S.X,``P(`87!L +M96%S948``'L`\BET:&4@875T:&]R2!Q=65S=&EO;G,N"@I4 +M:&4@=&]P+6QE=F5L(&1I4$`(&EN^`"`92!F;VQL;W>V`'!I;F9O +M%#36%K94QIM`!(ZU``` +MDP``3@#U`2YA;2P@86-L;V-A;"YM-"SA`$!E+F%C*P```@`2+50`)'1OJ``` +M(`&`9&ES=')I8G5!`;(L(&]N;'D@;F5E9'P`,6UA:?8!(V5R7`$%<``D:6YD +M`/(#+F@N:6X*"2T@=&5M<&QA=&5S9P`18C0"`68!$V6U`'`*"D=U:61EM@*" +M1&]C=6UE;G2!`0#%`3)A;&QU``#S`?4*('-YM`_`$,R!G:79E2XS!`,!JP(2(FL#!:L``20`Z2(@=71I;&ET +M>2!C;&%S1`"6:6YT97)N86QSG0!@P$2+8($4W,N-2!D5@(#I@0@ +M:6QV`]1R;6%T-50!"/$$4&%B;W5T&@$@P"`+"!I;F-L +M=62*`8%H87)D+71O+3`&`J@!$G-'``!!`&%M;V1E$D#(F5R60<#>`('(0"P;V-T970M +M;W)I96X!`P!@`@$>`*%35E(T($%30TE)=`(!%``"4P`/,@`%,$)I;LH$`$(` +MH"`H8FEG+65N9&GS!(-R(&QI='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I +M;;<"@"AW:71H(&]PRP/`86P@4F]C:W)I9&=E10!B2F]L:65T*0$![P$"20`U +M6DE0"0$#0``@=6Y."3!R97,G!W!OB,``!DT%``)"`$```I58W)E873/ +M``%U!`\&`0("J@,#OP,"O`(/'P,8,")R9?X(46-T960B1P,"3P#$+"!W:&EC +M:"!W:6QLB@`!5@`%R@%A(&5X8V5P0`40"EL)`VD"`A4,<7)E<75IP`#GP$`>P`!APD!HP`"2@P#"@,0 +M;6L($&EY!Q%A+PD#*P`A(&(W"7%R96%D86)L``8`C`H!#``!+`L"!`$`:``" +M.P!"96%C:#T!(79E4,`4&EN9&5PJ@`E;G0B`0`8"0`/#Q!C0@42;VP- +M!C4*5"!7:6MI4@PP:6YGR0`P:&]WFPP!LP,79)8*`BH!(4]N/P@`]PP">`8# +M`P$$S0`!<`!`;'=A>48!`-T!*F5DB@@"1P!P22=V92!A="T-`(P'`,$/D&EN +M:6UI>F4@2UV```S#`#W"!%IAP8`A`!P96YV:7)O;M<" +M,7,@=Y`#`:`"$&W8`1-R6@,%,`(`6P`"?P`1>7L#$7`U`-%A=&5V97(@8FQO +M8VMS\```[@2X'<70@82!T:6U7`W%O8!(71O(@`%2@!2="!O;F-\$B)/;AP."\,``N0",G!R;SH!`84!46-T;'DM +MS`"2960@;W5T<'5T[P(`8`3Q`V]B:F5C="US='EL92!A<'!R;\@#`$,2`OH` +MX'1O(&AA=F4@;75L=&EP)0``(040=A(#0')E86W\"E4@;W!E;IX`$R`5$`!J +M$``*`0`]!8-N(&ET2!B=6@-$B`D"`!E``!Z``#-`H5A('-O8VME=#X# +M27=IP`28D(`!*P%`#8!(71OK`TP9&%TUP``!0X1.L$"`2X! +M`L@)`,(`$F'L`@!A`P$K`#-I;B`G`0"/`C-A9&2.`AAA]PP!UP<#'@]19FER +M>D``,P``*,!!H`%,7=A;G\%$G0=#P-%`0!@```:!!!T +MC@A<"+``` +M.P``!`,`2P+%1`G +M-Q,`)AD`%@)S82!F=6QL+98(F-%#A)B!P`2>`<``'`$`)()`"<`%"I/&@]D&O______________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M________________________________95`@:6YS:6(@``#P"6=H="!I;G1O +M(&QI8F%R8VAI=F4G1X`<&QI8G)AP#S"2P@:6YC;'5D:6YG(&AA``"/`/0:("=D;V,G(&1I2!I;@IA(&YU +M;6)E6]U(#\!8"X*"D-U +MFEP,A8`!'P! +M32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9-!0`"0@!E6-A;B!C?P(-F5A;;4%X'-YU`P#P!`![``-S +M!`![``&'"0&C`%0@;VYL>0H#$&UK"!!I>0<182\)`RL`(2!B-PEQ4,`4&EN9&5P +MJ@`E;G0B`0`8"5!A7L#$7`U`-%A=&5V97(@8FQO8VMS\```[@2X'<70@82!T:6U7`P!K +M"S%M87#X`C!E;G21!@/0`@%1`T!G:79EY@$A=&\B``6A`&%T(&]N8V6%`"%/ +M;I`#&V7#``+D`C)P`%`@(&)S9",'(75SO`$`/06#;B!I=',@(D#E`!(BO001 +M2!F@``P0&%82!S;V-K970^`TEW:7-HN@3`4X.475S92`B(0$`6@@@+")0"'`L(&-A<&%B00`!]@($ +M`P$%\0!A92!!4$ES/PX(]@4!EP&`(&EN9&EV:61L#@/;"`"%``(5!@!"``2L +M!0`V`2%T;ZP-,&1A=-<```4.%CHN`0+("0`]`!)A[`(`R0H!*P`S:6X@)P$` +ME0LS861DC@(88?<,`=<'`QX/469I1$@#R$0`6`G-A(&9U;&PME@AR9"`G=&%R)P\!`0(`(7)EK0H!0@%` +M8G5I;($&`(H``V,``"H``J(3!F,`2V-P:6]D``;3$@$P`S!F86,J!P`]``," +M```I$")N=&@#`!$"-G-A;98#%&%G!5F-%#A)B!P`2>`<``$D!`)()`"<`02H@97@;$T!S.B!3,@-4 +M,!-&%C='L3<&1E;6]NP`` +M7P%C875T:&]R:1``EPT!\@(`P1,2+NT/4'1O<"UL#`0#Q0P`,`0& +M";8""',5`.L%`>X/\`4@*B!.15=3("T@:&EG:&QI9VAT<]P`,')E8VX,`C$% +M`Z`"DD-/4%E)3D<@+0P%`$(4`,H'(61O7P8!AP4`S@#`*B!)3E-404Q,("T@ +M9`HQ86QLCP0!#0``BA8`OP`"*0`#0`41+3P``5X1`A@`8&-O;F9I9[(6$"W_ +M!0$,``)$`+5S8W)I<'0L('-E96<``"@%`ED6`F,(@2H@0TUA:V5,U`0Q='AT +MB``A<'5G$#`@(F,T!A$B)`,`.`PI;VQ-`"`*"N$(!NL#`2D!`!8)`(X!#VT! +M`0"P#!!U/1,"$!\`!,GK0`#)`0`DP``3@#P`"YA;2P@86-L;V-A;"YM +M-`D-`^T`,"YA8_\```(`$"UD`@"?``2H``#9#@BB!!(L&@X`UPL`60M1>2!M +M86GV`2-E!,"(0`$F@,#,P``B`0/-``+`"(`##4`+V%T-``,*&%T,P`'K0,1,[8+ +M`!`4D"!O=F5R=FEE=_,"`*L`!<`+`'$%,'=H;Y$"%"JD"H5?\%1FYA;'.=`!)S/@M/:6YS +M:60:________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________________________________________________]Y4&5S"B`@ +M62```/$>*B!F:6QEFEP(&-O;7!R +M97-S:6]N%0!=8GII<#(6``0F`$TO3%I7'0#_`VQZ;6$L(&QZ:7`L(&%N9"!X +M>B,``!DT%`#Q,@I4:&4@;&EB2!C86X@8W)E871E(&%R8VAI=F5S(&EN +M(&%N>2!O9B!T:&4@9F]L;&]W:6YG(&9O"!I;G1E'1E;DT!L7,@*&9O$E33SDV-C`3`%HW+5II<#D`-EA!4A$`0PI7:&4# +M`@#D`00%`A$L_`%AT!X'-Y +M`>-R86YD;VT@86-C97-S+GD`!I<`\@)I +M`35N97<7`@!2`#!A;F1[``'.`!1V6`,24,`4&EN9&5PJ@`B;G1_`!!R.P0`!``P=&EC\`0D;VZ!`02N +M`/``5VEK:2!E>'!L86EN:6YGR0`P:&]W^``"]0``C@0#+``"*@$A3VZJ`!PL +M`P$#V0("<`!`;'=A>48!`-T!\@%E9"!A=71O;6%T:6-A;&QY1P"P22=V92!A +M='1E;7#$`^!T;R!M:6YI;6EZ92!S="L`L"!L:6YK('!O;&QUN`'A+B`@268@ +M>6]U(&1O;B?L`0"V`/$":6-I=&QY(&EN=F]K92!A('#K`"!U;#<$(&5A60)` +M("AS=2\!&7,<`A!AZ0`'+0`'[P4`@`$"F0%P*2P@:70@=W``X"!G970@<'5L +M;&5D(&ENI`0W($EN;@`W+"!IG@`!40$#FP`B96[)`07L#$7`U`-%A=&5V97(@8FQO8VMS\``0:%<%(6ETH0!!66]U +M2X'<70@82!T:6U7 +M`W%O8!(71O(@`%H0!A="!O;F-E +MA0`A3VZ0`QMEPP`"Y`(R<')O.@$!A0%18W1L>2W,``!(!E)U='!U=.\"`&`$ +M\0-O8FIE8W0M2!F)M96UO +M?\`!8P``0`"\05R;W9I9&4@96%S>2UT;RUU8<``J,!!H`%,7=A;H@`$'0V!`5%`0!@ +M``'Z"0".!S!S:RQ.`P-^!KEC;VYV96YI96YC9<`!`(D`,&UA:WD`D&ES(&5S +M<&5C:6X$`=`!`JH!`#H(,#H@(I,*#KL*$R*Y`B!L;#P!`N@"`*4'`!$#`L$% +M0"P*("#,!Q!PWP``;`0`E@`0(',*T"!S87ES+@I214%$346[!@?H!N$@8G5N +M9&QE+@H*475E<_H"H#\@($ES7!1`GH@1` +M9W)A;18"M``-G`0"3``!.`/`` +M+F%M+"!A8VQO8V%L+FTT"0T#[0`P+F%C%P$``@`0+:("`)\`!*@``-D."*($ +M$BP:#@#7"P)\`#%M86GV`2-EPH"MP(` +MA1(A86R)!V!S97%U96Y+#0#6`@"3``!U```7`@#Y!`%Q``%Q"@B7`'-E;G1R +M>2XS30``[P0R92`B:P,%JP`!)``4(@L+62!C;&%S1``!'PE&;F%L]!9!I;@IA(&YU +M;6+R#!=FD0<#'@'7+@H*66]U('-H;W5L9*0+`"@!,6-O<'8&0&-O;6V>"`"X +M!!,B!0XR+F@BJ0`R:&4*7PQ!(&-O9'4!`!0`!.D&`W((`G\"-&UO5$P"9!G!E2X`L2`H8FEG+65N9&EA +MU!%C;&ET=&QE$0`"^@`$7Q:10T0M4D]-(&EMMP*`*'=I=&@@;W#+`\!A;"!2 +M;V-K%V,/"Q<`TTUI8W)O2X*"B`J($DG=F4@871T96UP=&5D('1O(&UI +M;FEM:7IE('-T*P#X4R!L:6YK('!O;&QU=&EO;BX@($EF('EO=2!D;VXG=`H@ +M("!E>'!L:6-I=&QY(&EN=F]K92!A('!A``B;`%IE +M;F%B;)L``#X`"W$`*&1E$0`#J@`1+/```H``(FYE)@$`%@$`0`#X"V%G86EN +M<`!`"@$`#,`@&%N9"!W&%)`$!S.B!3 +M,@-42!F:6YDT`(Q9G5L+P(&10`0+Z\' +M`84!$6%R!E%A8W0@P``"@+Q`F%U=&AO@`K!#3U!9 +M24Y'("T@=Q,'`+D(8F-A;B!D;Y\`,W1H:2D`H$E.4U1!3$P@+2#0!S)A;&QU +M```-`"%R=2H"`RD``T`%$"T4`1%SE0`"DP"P8V]N9FEG=7)E("W.``$,``)$ +M`+5S8W)I<'0L('-E96<``/T(9&1E=&%I;,,$84--86ME3-0$,71X=(@`(G!U +M)@EQ(F-M86ME(B0#`*0)*6]L30`"5@$&ZP,`E`!!2!N965DQ0@0>5L+4&$@=VAOD0(C*B#9 +M!X5?] +M!;!I;@IA(&YU;6)E<$",&5C=)D#$61A#0,<`@5X"1!F+``!MP91*B!'3E5U`0(U`B8@*`0+`!H` +M06QO;F=0!F)N86UE+``-J`0`9`X$J(%!/ +M4TE8("`-`5L``A``,G!A>%H)`ED'`W@"!R$`L&]C=&5T+6]R:65N1!``8`(! +M'@"A4U92-"!!4T-)270"`10``E,`#S(`!1!"V0X1>2X`H"`H8FEG+65N9&GS +M!(-R(&QI='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I;;<"$2AX""!O<,L# +MP&%L(%)O8VMR:61G944`8DIO;&EE="D!`>\!`DD`-%I)4'4$!$``('5N,0L` +MBQ`@960Z`$`B9&5F?@81(F8)`Q@``*$$(VEE50$`PP$`H@&%0E-$("=AFEP/@$@:6^[$'TJ(&)Z:7`R%@`$?`%-+TQ:5QT`HFQZ +M;6$L(&QZ:7`3`R]X>B,``!DT%``)"`$```I58W)E873/``$M"0\&`0("J@,# +MOP,"O`(/'P,8,")R9:`-46-T960B1P,"3P#$+"!W:&EC:"!W:6QLB@`!5@`% +MR@%A(&5X8V5P0`4`N04$:0("UQ$`0PX0:98%)V%XR@(@("@6!0$T!`"$`0,S +M!`#T`V`L(&5T8RGO"P+Z`P"I`@8B!`&;`0+:``^6`P4!R`-A(FYE=V,BFP,! +M,P`GD#`#X'(71EVP@1.N85`2T0$&D@"G!H96%V:6QY_`@V96%MM04"$0M! +M+B`@5$`44VES(&YOX@<`@@(#"A4`DP1!(&EN+;P`#GP$`>P`!APD!HP`"2@P#"@,`.`@`;Q`R=&AA"0$"#`(A +M(&(W"0!J"`'[%2%O$P$/`P),%@"V`A!G5180:2(3`2(`!9L$`.,3(6-E +MA0`A3VZ0`QMEPP`"Y`(R<')O"AFA8V]R>`907!P4X.``P1$2(A`0!:""`L(E`(H"P@8V%P86)I;&D2%`:-`07Q``+S#P$_#@CV +M!0&7`8`@:6YD:79I9&P.`]L(`(4``#H2`D(``'(+`-$``#8!(71OK`TP9&%T +MUP``!0X6.BX!`L@)`#T`$F'L`@&`#@`K`#-I;B`G`0"/`C-A9&2.`AAA]PP! +MJ0H#'@]19FER"U$W,3$W-0`> +M83$U,34U,@`>+S4Q`![_5==&96(@,#DL(#(P,3,ZAPJ1(#,N,2XR(')E,A.> +M9`H*2F%N(#(X*0`A)W.K"T!W96)S``0R;6]VT0L/(1X&$BY,`"XQ,TP``74` +M&S%U``\I``87,"D`841E8R`P-U(`0#(Z($E2&P$(#`@*!0/0%`#O#!EE&@P` +MG04"VPT"3A@!D`B$(`I.;W8@,3%4`"!!9+8;!JPB@U]?34%#3U-8%PT`@@0$$]@\$90`` +MP@$@(&Q<`6``'E("`@ +M0_$@`9D"`V,``%(7#P(A$@]U``@)DR$#=0``3@L#=`!01W)O=7`2$`"U`R$R +M-!4!&3$5`0`^`0=\!`$H``(O!"4Q.ID>H&9I>&5S(&UE`RDQ.D4`"AH`$5/\'P+8`&%T +M;R!)4T^?``!U`%!T;R!I;8H+-F4@2-RQH`+PU18V]L;&6((0#C#0!*#S!L92VK(@#``)F]NS0,!W`<&?`$11O0&`"H#,FP@,#4"(3`Z_"T`&QH#HR8'0R80968$`=\3`I4$`2X#`M$0``D+ +M,'1R884%(6%L.P0A,CD[!$`P.B!-<`(#R`8%$`,`%04"G``!\!3P``H4!$C"%`4!L87)GQQ0!ZA(`V!1B96X@8V]PE!$`#@,!'A($R`D!00`# +MB040,`@"`;(G`'@`=B!-86,@3U.I`@`\``>N!`$Z``-"`B0P.E``!^L``*H) +M`_T"$'->"0+N`%1S"DUA>24-8S`Z(%A!4D,$`1D``T,%$3#'`34@7E0-!1([ +M/B]`(&5X:1$5`J<$`]0'`!H!`)0=`XT*`F,`!IL``UT$`=\A!A`%!`<"!!L# +M8&,@8W)Y<,4$`L$,`8\``_L&(3`Z/1T!`@(`+`8"$`0`)@,`1P4"*@`"!0T2 +M,``(`]0#$CHN!T`M9VED!@``*@1!("TM=0X`$'4.``$'!0,R#@/``6!2960M +M8FQ@%@#\(@&4!P;^`0$9%2!E"!L96=A8WFU!S%M870,!`/!4`Q`,`,AT"D`4#=@@#O@$`OP<29"L``)$@.6QD +M95\(`%T;$&R[`0`5#@%`*"%E9,L#!A`!55)E;&%X`P(`P@4@2!!4D-(259%7T9!5$%,(')A'`0@=&@;`T,@=FES^Q0#*08`R0L# +M=0`T7`8P`!H4#$%+(!T5A9FEO#@D! +M50`%PP400<<=`%8`!_,C!3$%(6QY+`\$_0("6P`%NP%@26YT96=R70(@07#Q +M&`?W!`!+!@@-!0!_'2!A=`,L$'5.'@'@`0+^&`$!$A4S5``$$0$`WR,S("U6 +MX@X&4P0&:PLX,BXXJQ$W2F%NR`,`=@L!S`@&"@,`DP#@)V5C:&\@;F]N97AI +M0(O,#G?```?,=\`#P&O +M#`*'`@]#```6,7P-,TIU;#L#`"@````"`/@DL2!B;V=U'HP``)!`P0P``"1,0*8`4$@,2XW90<1,?4`""$`<&QZ;6$O>'I;`P/A +M`@!G``06(`D""`)`!`"?!1-Y\@X`20`12,@D("!G_A("10``V`D$00!`3W!E +M;I0E<")G>G-I9R+-*`"@,`)%``+#`P!%`)!!=F]I9"!F86P*`@.2!0*(`02I +M!`&@!#!P:7`F,P!1$@+>!P`\``ME`@?\`@+%!@%_!`TI`$<0"%W()`RM! +M9#L04FYE>'1?;`\T,B@IGQ9!:7,@=6$243(U)0H),2M0969F:6-S"`%E``$> +M'@.#"!([:A/30G)I86X@2&%R2!-:6-H:6AI'@#'!T%T86UPE@LP5')UY0X!\0X`I@0`L2A02'5R9"R&`,%":L.V +MF5D!0\2)P/``S!C;W)D`D%!;'-O)R0+L0`Q8FED`(5<]<.(`H)E`8A +M97/-`S!S=&$N*`"(``,.!"%S+NH=`XD&)#@ZS@D"&P4)D`D!I@X28)`"P3=@ED;V5S +M;B?G!PLR`&)W96QL*2RS!B)I65T"@E00T%D('5NH@`"K!`")0<# +MWP`)L1J086QL*"DN("!&F`M!;F]W+)0J,&UU2!E;F]U9V@@00=!+"!W9<:\!"W@!%S1/`0$I``4E`P_8 +M`0$P9FEXZP4`;`($_!X*L!,`#C0`S0``1@0!,Q@&(P8!OAP!9A$`2R$&]A\" +M:0,`/PX`"0D38=U#3H@"?$E$W`=`-`N9G)E96)S9"YO0"@D@(&UE87-U>P,!4P8".0``30(`N@L1:1Q) +M`5TO0'!A=&@=`&$@9FEE;&31`#!U*P%'(F!M;6%R:7HZ"1!P[#L`W!<" +MMP0`N@!`+6YO+;H*(V9ICC@T;&EBS4<#;Q0`)P`+J`!B.B!3:VEPDQ@!LP$! +M8P4!2@4#_P0",0A0,S(M8FD6!3!F7W1'`#!I(P'&`2`M!@"AP$`V#0%%",!5P8754-!"8G`(H!$&:;!B5L>?,$(`H))0]5:VYO=V[(``"O)4!A +M=&5G(QD+.0$"7!8`"00"+`4"EP(.3P<,G@`!F`<`U1,#Z@@!?`D""00&/0L` +MX@(/2P`/`"8!`*L``/@(&&5;`@-:%3`@=74;$3!D93L,`1%YD`X"N`T!U`\0 +M+8$N,65C;X$%4FQO9VECL14"-``0 +M!Q(NR!\&Y@X,I@`5,Z8``I,8!?D"`W8=`)T&$2Q,`@"3`!(LF@`0+"P$`IX` +M`3L!(&-A91`18I@+,79E`A8R7@(**0``J`$@8F%S3A%DB`,!%PD# +M%0$&PR4#3`4"*B(&=0`*2P!D5F5R:69Y300!5@@`21HQ9V5TF@T"I3P!8@L$ +MS54`<1H!C@5%,BXY+H(!`CH``$@!$FQ4,1!B$QD!VPL'X0\B*"VE#T`M>BDL +MJP,`(0\Q"6]FJ@TP'0`F+P%6 +M"0#'``*Y`%!U;F-O=LQ")0H))"``S`%P8V]S;65T:5\<`.Y3`$D$`U<&("P@ +M^@4`V08`*P0<9%@!H$5X<&5R:6UE;G1,2P,O)0#;#0#]/!0M(`T#@#`/G0$% +M`K,;!O@"`^@2!&$&$'G;`@&<`0=3!U1I=&@*"8,"%'-/$P04,@%(`P#W``&B +M"6%S+B`@*%>A$P%!$P&^!0!G"2$*"8U.`=P(`!0%8&QA*9!`;4E`.@3`O@D!F$!`*<$ +M`;$)!3T/`6H``C\K#VH``0S,&0)A!!8WA@A0,"XY+C#&!P"!!P+.4R!W::$5 +M,W5S92<;!30`($-OCQL`&@M0:6YI=&E\!@`/)00Q$`#*`0,)`@28``+'`PZ8 +M`!4YR@8"P``%*``&U`4`8P$"C30`>@4"B1<)9`#P`SH@("UA+"`M<2P@+4PL +M("UF+)L8$'0^�@00!G"0#C$`0+)H*!(T2H41A;6EE +M;B!';VRJ!`"C`!!B>@T`Z0`!CP,`B3@0>H*Q`O!0D!!0`07[@4("YCH2$`@@LP +M--*)7!Y^!T!=``#$!L2-XD%4&$@8V]UE!PC;V:6 +M!`>M)@#E!0%_``*I#PZG``?R%0HH``!;``"I`P&G``$%`!%?:0$07]\$(6)Y +MV3$"10%R92!U;6%S:Z0_`T`!`_H>#G``!E@)`LL`!1X"`(8'!C12!(0"4"TM +M9&ESIQ!2+7AA='1Y"@84`'5A8VPL"@ET[0'_`%-A;75L:2!3=6]M:6YE;HP` +M#0<^"0'\``6,``8_`L!,87!O($QU8VAI;FG5!0!Z50%)`@!.'`%520`%#@'2 +M"0&:)`-*!0"3`2!L9%<)`54N`/H;!&\$,&)U9\8%`1@``$`!L&]F"@DB;&5N +M9W1HGA2096YD(B!F;&%G'@H%80`2@$@"@D4``&Z)`,Z.P_T!08'B04**``">```)0@` +M\04`,A0&/`(#N@Q08VAI;&P'%PL[`!!/D`8`V1``\`("]PT+0$D@<'7P +M+PF-`@`A$`,D`048+P!,`0#!5`&$``4L!Q-)U`@!V0L`V`<097\G``$#4&XM +M;6%T;P4`%5T`U#XA;W)!#(([($D*"6AO<$@-D2!E=F5N='5A;#PE`?%,`!\! +M`#`+,F1E("<*`$,H`LX)`,Y5`Q4_`FL.#)<&&#.7!@"J`!4P+@$@0V\C&A!U +MD``$K0`$=@4`7`(!F"H29=\`!C4`$$XM30%85@#E0`"T!!,L]PL!<`@P(DAI +M[PH@>2*U`0-.`"`N,3@)`<\,`*\`%#$Y``/D(09<``"8!Q5Z-#P`EP*1:6UM +M961I871E#0$!D#@P14]&T2H`C!\P=')YSP\!_A4%PQ0`$0XP)(5`EH/!,L+`)T#(6]FA``#H0(`90@`OCL/ +MD04$&#-I!P`H``/0$!`WT",!50$334<<("YA)!4!3@<`$@02(,<@$R\#"`1J +M$D,*"6%C_`$A9&\H`%%R:6=H=$$3,6=S+KDA!F,``,0($"VT"`!2"@$-``&$ +M#`2[``?<%`%A!``C`1!I]0``B@,,)P$-70`!D`4/E`L``.4+(&ENO2(@8V6] +M(``7$`'0#0`T`@#K.@$`*@1](`!&%0",)S!N:6/2`2)H868&4')A9W1A!P,( +M7#L`00`#M%P1<_L(%'3#!R1H88@!!F@#";H'&#.Z!P&(`0\H``40,5(:)&ME +M6@`@8F5K'`!Z`P5&2P,,"@#'!4`H*0H)2PPY!("UP +M+#X'`6,Z(0H)Q24""1$5;Z,0$"QB$0'Z#00X"U!S96=F8><%`CX"!H$``F@) +M`U8#`44B`NH2`S\""0A```001('X88`H):6YS=(0&$',C!!!TF08)&&$#IP`%I@0(7"X`T`=T +M>5]L:6YK7\P2%"S0!0,=`#!S=')O6@(N`@/T,0R6`1@RH0T`E@$&P@P&B`$4 +M,@`&`-\"0'-T("A<(S!Y972<$!(INP`"ZST"?A(`&SP##`(#/#`.=@`'80U2 +M075G(#,O)!(WXS(`LS(`F0,$O`8"*QX`@PLC"`M +M+7-))P22!Q(N-P`%.`P34K,:8'-U:60O0@(6A``X````0\`C`,`92@`]AP& +MGR80+`T<`0$,)`H)AA4"21,$43DE('06%@*7!"`N:"P>(V%DQ0EC;&5A;G5P +M?BL*8@$2+!T5``P'$7,B"@`S$A$O+Q(#W`4P;@H)!`E386YO;6$("@',6@`G +M&@5D#`$%&A=YT@$+"P$6,CH3"B@```L!#MT%$""1`P),(@`$#`*7`U!Y(&-L +M;Q`.`)4I071R>2#2*P`>!R)T;X`<`P,T("!SS`@`8V(`P!@!DB(!EQ91(&ES +M"@FF!`D.`G(@9FEN:7-H.@$!`@T`Y@P$E0``E`$37^45`*`'L'=O0:70@:&5L9"!OPT,`J`4"F@``81L!J@``O34`A2H"%R(`^1T@ +M=6U!,`!\%0)<#@3^!@&<0P#Q$&`@8G)E86M**@#K#@#Z+`$8'@#Z,`'X`@2? +M``%@`!!?&0$69?DT`)8.`*@``NXL$&AR#`$N'8!S;VYA8FQY(+D!`!(5`I<- +M`,DU`*8<%WF"$X%3:V5L971A;'P+!HP(`5T'`^P!!@(%"^P!&C'L`08H`%!& +M;&5S:,D7`'(6$&];,!%R:Q,`?0("?@$@+F.\`1%AP`008[T,`>TC`.,-`!0E +M(6-H&P`C:&5_&B`@;MX"`2D!$6$A(`'*70)I`@`D`6(\A`CH["@E3``&:"1)WQDX`R0L`7P,#>P("[`,"D@$0;E,R`,QH +M`'0#!8T.,71O=>P"`$P%`()%`V`!%3'A$0O^``R``N`4`GQ`$`2(*^0H!$`0!)`T)-3(!W0@$64<` +M0`4,XP`'"`0**0``M`8![!$0;BY($6X]+0!^&@12``5N`0Q2`!8TP@(!4@`% +M2Q($_!]``!_+P%\+0`9`@"8'@$0-`1<*`)I``#D``(_`@#$50*+ +M)P4H`0'J`P0`%P#8!0DZ"2)T;P@]!(@!!3<`#(@!![D%"H@!$4@-!P1'#2!S +M.Y`-$&70!&!N=7@O9G-M#0*X"0+B``&Y"`BK&0`-.#%E65T>5,#5S0! +MI@$C=&\R%@"A"@#-%@""$A`B^0%R(&-H96-K(H4&!%PD`T<)"Y@!!V$!`",% +M`E$7%W/$24%)3$5$H@H!=``!M64`X0(`+04"+TH!'0%`82!W89$T$&&8+0"/ +M/2-F9A@"$FG%A4''@!#5T%2 +M3A@"!@H@![<``6H$!V(&`%P!!BD``"L4`>T!`)X"`'@",7,@**(``'<%`.," +M`E,+%RU790'I``#^!@/[%P`F```^``G\&3)O=RG'`09K``+I,@0-#`2$&`"# +M/S`@;V:*;E)S:R!G;[0P`&8!`*(.(69FT0\#Q!`P.R!R5FP!`A$0:4@E$"AX +M``/4$@!)!`*]`@?]``B4``#Z$D!I;F@`!-@HQ<&%XU0`%[0,` +MO18B=6ZE`2!E9%8D`38!#[D*`S3#`!@*`:)'0%R!P"O`31'240G!0(,`Q)S``4#10,B8GD6 +M`#%I;F<8`2%W:'0N`;<.`TX;`=U1`>8\4'1O;R!F3$(`PP<`SA:A;GD@<')I +M=FEL9;`:`9DI#V`2!#@?LFES(&QO;F``^'"@$!G@`'Q08!G@`%3P,10@E`5`@9&]W +M;A,.!UX!('=H,@$!)0`#$0@!3P`A8GE!``'.&5$@=&]O;*T$`#<&`N8H!2X` +M`H4&`=L<-6UI>BP!!C4+!VP``2P!!]D%`"P!`P="`C4"`=`H`5\1`/H&`=$H +M`8T&!D0``)P6`_17`J$`)&8@1@%!4$52331H("!ATQ5A97(M9W)A^#0!3@\P9F%C7@(688<0`",!!-L5#;`U$&`0@=`'Q#$&_=/@"$`@`M +M!0(R+@$D50:+=P)J"0$K6@/0!A!3(C509F5A='7?"`+V%Q!N>P$%RCL`J08! +MPQX'EP,"1Q4!<@$"<@!1:6YV;VS4`03S`0'-!@0$50%1#0!3!@`&`@!<8A%) +M%!T38XH)`8(T$'AA"P```B!O9L\1XB!O=F5R:&%U;"!W:6QLPB8!N"\#,38" +MI`L!?@`"BBX&1P$'?'@"V1``SP("[AL*W0X(U``"S0`"1R8!G#L#=P<`'"40 +M*/8X!+]*`+$$`8,!`'T"(V]F#"<09CT3"XD``,L?$',F!`,D``%&"`!#"`,V +M)`,!>05$#@,T!`&*``()`(P? +M!2<`0$)U;7`%*!!SFPL0=&PV$3/C``"+)2!)+SQ6``@S(G)S,2`",1(2-M83 +M`\P;`$$!049)3$4A)`/B$`\V``0&1P8"[P$$^2(#-A4`I`,`?%85>19/,6%L +M._L``?\*,6QO8[`1$6$]"C!M:6X:/A)UZ"H!JP85+<@!`=@U`G0>`SX5#!(! +M-S(N-3X)`'4>!BD`LT]U=&QI;F4@04))SD81!IH``-@)"^L`!Y<7`-H%`H$!`!L;,'-E*`!Y +M42!4:&5YEPD`3BP"C@X`ZP(`9@\!2P``.BH59N(?"FP`P')E8W5RG%A%R50\P:V5EZ7$!KR=0 +M;&4@=7!%!P!C-`(\``!V""!O;LLK0DQ$15)V`*)354U-05))15,*_1`"K04/ +M9`,`&C$A`0,A(Q`V60X(F24`5A<@;F1O`1)TV4,%B`\)EB,R(')E;G``RP`! +M-PT`"64@;W(('0(H$P!.`@5@\`V`)0=V]R=&AT`!1S$S@!Q081!D;5L"30$`VP50<&%C:V&72P<">`#8 +M`1!EN`I`+F=Z"LQJ`&H3`8<$`8H;$G/X%`?V!`#K!0+?#`*(.`-S,P#/`02. +M!0)[%A0Z>P/H!`5X<`A9_$2[^ +M30(`&QLUVAD!O@$#]@$$M1$)1T\`/@X$71D`'PL&7QD`NP4`1A,"M@0"'Q(` +M`P$I#Q!E7@D1>=T1`#T"!.Y#,7,@*`H(`BL<`A`* +M!AP``IX83#%-0BEQ`*!-87)C=7,@1V5I?0<`5AP`'P0`#/`'S#GAS;FEL+F%N=&)E87(N;W)G+S(P,#4O,#(O,#4O@@%`+6UI +M='YI!`\``%H:@')B96ET96XO2P`"RA<`9@<$[8H`!Q`"M0`-OA/$%+"!(4"U56"P@ +M56YI>'=A]0``!O>&9I;&4``0!+X3`P,#8T-"``,#`P-S8U"``B,#(0`"(R +M,`$`_P<@,3(S-3,U-3,U,3(@,#$R,#(S`"`PEP!+`@(`KW5S=&%R`#`P8W4' +M`0M2,!46%C="!S8`"A(&1E;6]N4$`(&EN^``(M@)A:6YF;W)M&@00 +M(+@&!+T"\`E.15=3("T@:&EG:&QI9VATP`"-E)ZT``R0$`),``$X`]0$N86TL(&%C;&]C86PN;30L +MX0!`92YA8_\```(`$BU4`"1T;Z@`#*($LBP@;VYL>2!N965D?``Q;6%I]@$C +M97)<`05P`"1I;F0`\@,N:"YI;@H)+2!T96UP;&%T97-G`!%B-`(!9@$39;4` +M<`H*1W5I9&6V`AA$5`8$T@$"=0`!MP&R'!L +M@P(#+P,`0@$"(0`$F@,#,P``B`0/-``+`"(`##4`+V%T-``,*&%T,P`&`0:` +M+C,@9VEV97/?!H!O=F5R=FEE=_,"`*``!+L%$&%Q!3!W:&^1`B,J(-D'A5]R +M96%D+C,L$```T04=91$`45]D:7-K%@`"?@<(/@`#'```F0`0=E\!`K<"865D +M(&-A;(D'$'/4!D%N8V5SK0(`DP``=0``%P(`^00!<0!8($%027.7`'-E;G1R +M>2XS30`"]P,2(FL#!:L``20`4"(@=71II`59(&-L87-$``'O!49N86QSG0!@ +M]!;!I;@IA(&YU;6)E`D09BP``;<&42H@1TY5 +M=0$"N@$F("@$"P`:`$%L;VYG4`9B;F%M97,L$```!0L3(!$``&,`4G-P87)S +M?`(AB,``!DT%``)"`$```I58W)E +M873/``%U!`\&`0("J@,#OP,"O`(/'P,8,")R9:`-46-T960B1P,"3P#$+"!W +M:&EC:"!W:6QLB@`!5@`%R@%A(&5X8V5P0`40"EL)`VD"42!T:&%T0PXQ:7)E +M40`!\P,!R@(@("A3"@$T!`"$`0,S!`#T`V`L(&5T8RGO"P+Z`P"I`@8B!`&& +M`0+:``_(`PIA(FYE=V,BFP,!,P`G0<280D!`BL`(2!B-PEQF4@'!L +M:6-I=&S9"4!V;VMEO!(!ZP`!?PH#SA$@("C2$"4@8?L*`*D`("!AZ0`!)Q`" +M+0`(S0`4;Y4(<"DL(&ET('=P`$$@9V5T&1,!70H`I`0W($EN;@`W+"!IG@`! +M40$#FP`B96[)`0P,1<#4`T6%T979E`!,@%1``:A`` +M"@$`/06#;B!I=',@(D#E`!(BO0012!F4X.``P1$2(A`0!:""`L +M(E`(H"P@8V%P86)I;&D2%`8#`07Q``+S#P&W!`CV!0&7`8`@:6YD:79I9&P. +M`&@%(6EEA`$`.A("0@`$K`4`-@$A=&^L#3!D8737```%#A8Z+@$"R`D`P@`2 +M8>P"`,D*`2L`,VEN("2!I;G9O:V4@ +M82!P87)T:6-U;&%R(&9E871U`<``$D!`/X&`"<`4"H@97AA20!`4$`(&EN^``(M@(B:6X#"``0""!F:34!`'P`\`LJ($Y%5U,@+2!H:6=H;&EG +M:'1S(&]F(')E8P8"5&-H86YGH`*P0T]064E.1R`M('<3!P"Y"&)C86X@9&^? +M`#-T:&DI`*!)3E-404Q,("T@T`'2(`")P=28)<2)C;6%K92(D`P"D"2EO;$T` +M`E8!!NL#`)0`07,@:6Y,`0]M`0$P87)E3@(29-H!-64*)[P`$R>M``,D!`"3 +M``!.`/4!+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_```"`!(M5``D=&^H```@ +M`0BB!+`L(&]N;'D@;F5E9,4($'G*!0'V`2-E%7W)E860N,RP0``#1!1UE$0!1 +M7V1I=&%R+C54 +M`0CQ!$%A8F]U4P4@"`"X!!,BO0(R+F@B +MJ0"`:&4*2R"```[!P$C"8!A=71O;6%T:?\"$'G!`C!E8W29`Q%D80T#'`(%>`D0 +M9BP``;<&42H@1TY5=0$"-0(F("@$"P`:`$%L;VYG4`9B;F%M97,L$```!0L3 +M(!$``&,`4G-P87)S?`(A`@@;W#+`\!A;"!2;V-KFEP,A8`!'P!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9-!0` +M"0@!```*56-R96%TSP`!+0D/!@$"`JH#`[\#`KP"#Q\#&#`B&-E<$`%`+D%!&D"`M<1 +M`$,.$&F6!2=A>,H"("`H%@4!-`0`A`$#,P0`]`-@+"!E=&,I[PL"^@,`J0(& +M(@0!FP$"V@`/E@,%`<@#82)N97=C(IL#`3,`)W-HL``!$@`/1@-C!`4$`EL! +M`8D`#UD#``H6`S-7:&4#`@"_"`/4`A)SY@5A?P(-F5A;;4%`A$+02X@(%1`%%-I4,`4&EN9&5PJ@`E;G0B`0!$#0'E +M%@!"!1)O;`T&L`M4(%=I:VE2#`,,$S!H;W=1#P*F!P!."`/:``N@%03\!`#S +M#@!0!@/-``%P`$!L=V%Y1@$`W0$J962*"`)'``_0%__@"?H#$&,W!@`%&,)A +M=&5V97(@8FQO8VO5"@#N!S`@:70(!D(@66]UYQ,!Q`U`8F%C:T`#,69R93T/ +M,'!A2X'<70@82!T:6U7`W%O2W,``"."5)U='!U=.\"`&`$H&]B:F5C="US='G@&4%P<')O +MR`,`^10"^@!0=&\@:&$Y%D!U;'1IPQ,$J0`"`00`N0A5(&]P96Z>`!0@]`\A +M=7-U!Q%I(0AC:71S(")`/``2(KT$$',3&P7J!`,<`'`@:71S96QF4P$`?000 +M+P(/8'1E;B!U7,N +M"@`!`/^)`#L7#Y\!30\`'@M1-S$Q-S4`'F$Q-3$U-3(`'B\U,0`>_U771F5B +M(#`Y+"`R,#$S.H<*D2`S+C$N,B!R93(3GF0*"DIA;B`R."D`(2=SJPM`=V5B +M!A(N3``N,3-,``%U`!LQ=0`/*0`&%S`I`&%$96,@,#=2 +M`$`R.B!)4AL!"`P("@4#T!0`[PP991H,`)T%`ML-`DX8`9`(A"`*3F]V(#$Q +M5``@062V&P:L(H-?7TU!0T]36!<-`(('.&EN(,01!-D/(G)EJ08`)P4`N`P2 +M:P@','-T;TL.`+@B?PI/8W0@,C!K``4`.08`A@82=J43`@,,`S8``[P!#Z$` +M`"MGF]P5`%64V5P(#*!``VH`0+.&7%T;R!S965KD`I&@'5 +M`@DX`P#*"C)I97-.``*:!&$Q.B!.97>:`PI(``0;`UES(%-&6`,%"S\`0$)U +M:6QK!0"Y`:)O;B!7:6YD;W=S(0$#YP4.2P$K,&%+`14P2P$P57!DN!5T`P, +M,RUS._@6"*$9`ADA$F_B'$!H87)D4P(E+W-;`E%B&0"5##!E;747&6D@8G)O:V5B`#`R+GAG!`!W$`&O)2%O +M9K(6<5541BTX(&AH`!)SF04%^P!`4F5F85D'`04/$%]R#B`H*7L:`"\-46-O +M;&QEB"$`XPT`2@\P;&4MJR(`W`<`YR@!EB(#+`$!D`P@;VPA`P,2)!!S'Q\@ +M=W(,`0-W`!(Q$`:!,3H@4W!L:71?#0(`!@`L`0&1!C!P87)N`@(>%P`T"`/` +M`@":`Q%L^24";`(!QP`5,30#`X(#`L\AE`=V]R:V(!9')E='5R;JP<`)`B`2$/$&;N`@%9`7%A +M8F]R="@I1``&-04`M0$`>0`WH2 +M`-@48F5N(&-O<)01``X#`1X2!,@)`4$``XD%$#`(`@&R)P!X`'8@36%C($]3 +MJ0(`/``'K@0!.@`#0@(D,#I0``?K``"J"0/]`A!S7@D"[@!4&D1%0*G!`/4!P`:`0"4 +M'0.-"@)C``:;``-=!`'?(080!00'`@0;`V!C(&-R>7#%!`+!#`&/``/[!B$P +M.CT=`0("`"P&`A`$`"8#`$<%`BH``@4-$C``"`/4`Q(Z+@=`+6=I9`8``"H$ +M02`M+74.`!!U#@`!!P4#,@X#P`%@4F5D+6)L8!8`_"(!E`<&_@$!&14@97)D +M`P,C`@!4!`#.`@!8*P%.``,)`P!*`F)I;FEM86RM``$3#7@@;&5G86-YM0#,O`G@5`,0# +M`#(=`I`%`W8(`[X!`+\'$F0K``"1(#EL9&5?"`!=&Q!LNP$`%0X!0"@A963+ +M`P80`55296QA>`,"`,(%('-T7P;09F%I;'5R97,[(&UIF7'`P`M`0!Q`0-7!`!_&"%O;88'#%$``8X%4&YT-C1?S`L%``>@ +M;V9F7W0L(&1E=@<`,&EN;P<`,'5I9`<``#\#$&<+``*<``7^!`08*`'"$#9! +M0TQ%"0)U`!4QN@024SD#!C48`20!!28#`$0!$C`B!P%J!``&$0)\)@.6`@<* +M"3$Q+G@-%P&,``:%`Q!2R`=%869I;PX)`54`!<,%$$'''0!6``?S(P4Q!2%L +M>2P/!/T"`EL`!;L!8$EN=&5G)``9"``+3 +M`P`I`Y!F=71I;65S*"DX+F)#>6=W:6YK$@9%`0>'`78R+CQA`;&5A:U0!"!X!`$@`$G,S``5<`0!D``FUA+WAZ6P,#X0(`9P`$%B`)`@@"0`0`GP43>?(. +M`$D`$4C()"`@9_X2`D4``-@)!$$`0$]P96Z4)7`B9WIS:6`@)[``6)`D!!9&1IR0HP86P@2@!`-P)M(B%S98$#!+`=!),-!'4'85=!4DX*"1PK06ES(&/Z,Q5OPP<` +MU1U0861A<'2;."!N91PC,V%R>;L!"=\`55-T=61I8`L`E@`/2@`!-`E!;!$#``@!`%HA +M`5\``_40`/,``.D#,$1E8E\!L4)U9R`C-3$V-34.`?$.`*8$`+$H4$AUA,`2P$41:L> +M!]$(`8(`)&]N*Q8!\0P"]PM`;F]W"?P#`9<2`78,$G11``85!@#0``.@"@8, +M#A!?*A4@>5\/!A!?;P8P*"D@6"X$[`\`00PQ+`H)2!R7!,@961S(`#/"P"])@!1,#`L"@E4 +M!`"`!P!:#0#B!@!A!0:^`P`\`R!T(",%"7$F`;L`!LHA(@H)?0`4<^@OQ6)E +M(&UU8V@@96%S:>8-`H\/*RX@HC,`311":&4*"3$8`5\1"$(G%',])P;1#P"# +M'`-Q`!(N_!`"MP80.$4$)&YY:Q8:+Z\#`HH6`+L!#_D#`@U)``J["0B[&0+W +M'`%*``1;`@+Y#!!CN@$@97)^)2ET;W89`$T&`'PT`@2US:7IE9`4/$G.*)3$@*A$) +MSAH`A@,/[A<"`!<-L2@I(&AAFEPEP2"_`0`P`"`@82D`*RDN +MM@#@2F]E0,A(&*Q'`&[ +M$P%-$P!7!B)A=$H`!9X'`<4(`AQ``-A"`FLK`)$I4F0@8G5GQ0(@.L%`&P"!/P>"K`3``XT +M`,T``$8$`3,8!B,&`;X<`681`$LA!O8?`FD#`#\.``D)$V'=0W,B4V-O='0B +MW!80(%0```L*!9X#$VV#/A!SU`8$-0"22V5E'!L;P$0`&T6$&5D#0)M`0)E +M+95V97)F;&]WPP$_@D$V@Y0"@EP2P!$'26$`&#.%%E(&)O9(L]``8-`8D! +M`#8!,#L*"6T&$FG,$@#0`2%O=:T-P')A;F=E(&)E:&%V:2U/`$0.`0L,!!0[ +M`9@)$7)R`0&K`0)],U$M3A+,&ER95<8!&@8,"-I9O4,!'@8 +M`H9`.`K@-`=0/$"V!+C%E8V^!!5)L;V=I8[$5`C0` +M$',T``!.%0)/(@'V%`!V`0$8``);20*;%P-]`@;4"`E3`D0T+C$T>AY`9#L@ +M:5P\`%)$`)@#`1X`&#,$0"()84H*`%,!`?`($&=+!1$O=B-@(&UI>'5PWRD& +MR!8"L0``P@D4:<0O(F0*[18`9P0"A"D!'@<2+L@?!N8.#*8`%3.F``*3&`7Y +M`@-V'0"=!A$L3`(`DP`2+)H`$"PL!`*>``$[`2!C8640$6*8"S%V97+;`P32 +M)P&-`".``#3"P"! +M`&`@8VQA`B4&1E=FEC5@$!RR$!32(` +MB0H`2!@3(G`#&2*)"``6$`(U!D!N97=CM@("<0@#I``6.^0#`O$1`%P"`6,$ +M"$T!`#4"`!`A('1H2PL!>P`"G!LE.#I(#0)E#@-J)P!(`@2;`PDD$1PL6PT` +M.QH'004P26=NR@@$[`I"('-I>ND,`$,-`B@K`#0.$F&[(@#8"P#^(14RC@`, +M7@(6,EX""BD``*@!(&)A4T$`58(`$D:,6=E=)H-`J4\`6(+!,U5`'$:`8X%13(N.2Z"`0(Z``!( +M`1)L5#$08A,9`=L+!^$/(B@MI0]`+7HI+*L#`"$/,0EO9JH-,')M85X2`)X? +M,F5S'!E-\4"%C'% +M`@HI`#!&:7BF00&U)0#H$P+X)`9A`0"G!`&Q"04]#P%J``(_*P]J``$,S!D" +M8006-X8(4#`N.2XPQ@<`@0<"SE,@=VFA%3-U?@=`70``Q`;$C>)!5!A(&-O=90<(V]FE@0'K28`Y04!?P`"J0\.IP`'\A4* +M*```6P``J0,!IP`!!0`17VD!$%_?!"%B>=DQ`D4!`@"&!P8T4@2$`E`M+61I0H&%`!U86-L +M+`H)=.T!_P!386UU;&D@4W5O;6EN96Z,``T'/@D!_``%C``&/P+`3&%P;R!, +M=6-H:6YIU04`>E4!20(`3AP!54D`!0X!T@D!FB0#2@4`DP$@;&17"0%5+@#Z +M&P1O!#!B=6?&!0$8``!``;!O9@H)(FQE;F=T:)X4D&5N9"(@9FQA9QX*!6$` +M$G,?!`96`0).``,"!!$@FP8!4@8!/@(`J08!+P0$-P`%\P,01J,!0"!C=71K +M`$!R96%L>0<`-```D0(`Z`42;AU(`0\!!38`"Q@(%C+:`@+$`0\I``46,2D` +M"E$`$4W_)@"X!D%S+"!R%Q@`E```P0*@9&]C+71O+6UA;C\.`WX'`'H!(`H) +M%``!NB0#.CL/]`4&!XD%"B@``G@``"4(`/$%`#(4!CP"`[H,4&-H:6QL!Q<+ +M.P`03Y`&`-D0`/`"`O<'(B!A>U8@(&_I%P'8"P#Q#S%G:6Y\*2!O9L\&(PH) +M$P(!6!X"IQL"K%@"S0(#CQL`+1D`3P4"2C0`+5<`#P@2>88`!G,&$%0$!@,S +M```5`0`X!!-Y\Q``6!(`0@0`QB4`NR(#Y@D8.I@"`FT(`#4((&5XU!8`0D4$ +M.``!YAXS,D="?R8S,51":`$"5CD-#`48,RX:`"T!!B@`$D,/"`(_!R5U;E@G +M`LP.`%T5`7-#`-H$``,#`+(``"H!$"*:`0#Z$P##'T!N;VYEC@L%9!T!?@00 +M;H`,#(O,V(#`7T``-@"`68(!M,#D$IA +M;B!00P`4,#`!`,`-D2`.L(,$=.55L! +M$"><*$%G+71AE`(&[UP`FP`U;W-E,@`!7QA`960@;2\B0'=A&%C=&QY +M"@EA*R``YA<@-$>T"`/@$@=H$0&=`0(;#@=G``!;`0!F``=#`E`H/CA'*>,` +M!3X"`-0``-P20V%S"@E&.`'M"T!)('!U\"\)C0(`(1`#)`$%&"\`3`$`P50! +MA``%+`<32=0(`=D+`-@'$&5_)P`!`U!N+6UA=&\%`!5=`-0^(6]R00R".R!) +M"@EH;W!(#9$@979E;G1U86P\)0'Q3``?`0`P"S)D92`G"@!#*`+."0#.50,5 +M/P)K#@R7!A@SEP8`J@`5,"X!($-O(QH0=9``!*T`!'8%`%P"`9@J$F7?``8U +M`!!.+4T!6%8`Y4``M`03+/<+`7`(,")(:>\*('DBM0$#3@`@+C$X"0'/#`"O +M`!0Q.0`#Y"$&7```F`<5>C0\`)<"D6EM;65D:6%T90T!`9`X,$5/1M$J`(P? +M,'1R><\/`?X5!<,4`!$.,')E9V$F`8D+`.(/`%T%`-(D`!4``,\;`6X2$'B2 +M%0):#P3+"P"=`R%O9H0``Z$"`&4(`+X[#Y$%!!@S:0<`*``#T!`0-]`C`54! +M$TU''"`N8205`4X'`!($$B#'(!,O`P@$:A)#"@EA8_P!(61O*`!1@,%1DL##`H`QP5` +M*"D*"4L'`=$2`+4,$FUJ5B5I;I(+`Y@``P8=#GX#!RD(`)@`!B@``:(X`88" +M`.D"`RL#4R`P+C,ZO#P&[A`165TG!`2 +M*;L``NL]`GX2`!L\`PP"`SPP#G8`!V$-4D%U9R`S+R02-^,R`+,R`)D#!+P& +M`BL>`(,+(W,L7&,`J@4D86[/6P2`!40*"2A!K1<991L1`*HE(2XI;``#310! +MF`1`860@9QD+\0$Q+C$W("TM<&]S:7@@+2US22<$D@<2+C<`!3@,$U*S&F!S +M=6ED+W.+.00R$03O"T`[(&ET'00%=@0@"@E/&D!RQ,2(M+6`%%"W0`0,R!@&^)0"]*!5RF!,1"ND`!H4& +M"5@$-C(N-L`#`$@!!B@``0D'"]4-!\`-`ED&`&T&,6%N:QL'`88+*`H)$B4# +MNP`%[`($0!X`20T"&P0!N@H$Z"LQ0U9361\`V$@G=6R=`0NT``?Y#@(I``_& +M#`,8,AL(`5$`!2@`!E,*"B8B$B=/)@"$"@1$(0&4`A%D*`4`H`($XQ,R8W)I +M6!A2\`!ZP'`8HD`?(] +M`/T+`'D("%H0`.````$/`(P#`&4H`/8=(!"PL!%C(Z$PHH +M```+`0[=!1`@D0,"3"(`!`P"EP-0>2!C;&\0#@"5*4%T8L<`2"Y`0`2%0*7#0#)-0"F'!=Y@A.!4VME;&5T86Q\ +M"P:,"`%=!P/L`08"!0OL`1HQ[`$&*`!01FQE`@$I`1%A +M(2`!RET":0(`)`%B/'-I9V@^VP`&204!<@(!=!D`]P0&.!P`A0-0,BXQ+CDW +M"A-TMPD":0`A"@EJ``!L`0\7$``#80`%NP803,0*'!`#*,#!U;&00!!!RY0('H0(Z.PH)4P`!F@D2 +M=\9.`,D+`%\#`WL"`NP#`I(!$&Y3,@#,:`!T`P6-#C%T;W7L`@!,!0""10-@ +M`14QX1$+_@`'-@DF"4P[%@"!``#L!`*Z(!!N9AT!*B$`"0$`=00`!`,`_D]$ +M97)I>&,`!:4'"V,`".4(`,0!`QHC#'8+)S%BZP8**```P@D&50`17PQ%`]9G +M"KT,`48=`!$:(6%L4$%E+@H)3F]TM@4!3@8$BP$"B0$`IQ8!-&T*<@`)NAP1 +M(LH&``\!47)EP1$&XN +M2!%N/2T`?AH$4@`%;@$,4@`6-,("`5(`!4L2!/P7(6%NPT4@8FS**0#[(!!A +MM0D!R@4`U1$`'``!"P<`_PX`;VP!NB\!)@`!#D@!3@D188(3!75$`>T70&]R +M(&>R4@`_#`!N$"1B96T+``L"`P,>`BXO`#4M`2PQ0&]T:"!:!P*Y!0J(`1%(#0<$1PT@W``%J!`=B!@!<`08I +M```K%`'M`0">`@!X`C%S("BB``!W!0#C`@)3"Q``#U!(`200"O0('_0`(E```^A)` +M:6YG+Z,#`%L-`7H``38*,7!A>-4`!>T#`+T6(G5NI0$@9616)`$V`0^Y"@,W +M,"XR8@<`*0`%*`!`($ET)T0*$71)'#)E8W3&`1!I%@"S<')E='1Y(&=O;V3] +M`0;U"1(R&201;^I#`=<:`+\F(&]F[`L480H``_T&``D#`(<. +M`/T(,$=E;M@``;P#$RAQ+3`A*2!0.P'+'0(6`0!$$0%"``'H'[)I0@A=""X3X1L +M8VAM;V0H*6L`!245!Q(#`74!!]83`6L`!2D`$47*,`8(`S-E`2!W:#(!`24``Q$(`4\` +M(6)Y00`!SAE1('1O;VRM!``W!@+F*`4N``*%!@';'#5M:7HL`08U"P=L``$L +M`0?9!0`L`0,'0@(U`@'0*`%?$0#Z!@'1*`&-!@9$``"<%@/T5P*A`"1F($8! +M05!%4DTW`001`&A/5TY%4BRD9")R96<0`3L`<71O(%-5240S`!!38`0`LQ@` +M=A<%F4X.B@H78AP,"B@`$4%F"`"J!05@"P"1!A$B!RX4(KL0$'/:!Q%A?P`" +M&S4&D78`YP,`)48Q("!"0Q\`L`0`APD0:;$$`O4``"U=P'D:"`@8=,5865R+6=R8?@T`4X/ +M,&9A8UX"%F&'$``C`03;%0VW'P$:`0`E&@",`@/E%0#R,@&)9P.,:0%`$`*T +M%0/&`P"C-`&B&`1G`0%'`"%A"P,-$011`"!D99X) +M$&*A!0$4-S%Y;W5#``1*&@():!(I5T``FP!A;W9E!Y<#`D<5`7(!`G(`46EN=F]L +MU`$$\P$!S08$!%4!40T`4P8`!@(`7&(1210=$V.*"0&"-!!X80L```(@;V;/ +M$>(@;W9E@J`:L&%2W(`0'8-0)T'@,^%0P2`3_`$`R+C`[Z0("PPD`9Q]!<')O=/P+`+,Y]0-I;F0@(VEF +M9&5F)W,@=6YT:6R@-P'#<0+U%@"S$3-Y=&@T"P%B`P"L`P&L`@)X``*['@:: +M``#8"0OK``>7%P#:!0*!`0`;&S!S92@`>5$@5&AE>9<)`$XL`HX.`.L"`&8/ +M`4L``#HJ%6;B'PIL`,!R96-U +M`0"S#"%S90($`BD#`$D($&``"I`2`M<",%"W8+`@5.`;%P!!H`$"W6(E!I9FEC"@QX#>5.` +M`AH/`Y@E$3;N"!`@ZVL!?2<0.P8`$6Q-*0#_!2!O;$\0$F@C*`+9``%'"@!? +M``&(`0#V!Q`GIQ81EQ`:\G4&QE('5P10<`8S0"/```=@@@;V[+ +M*T),1$52=@"B4U5-34%22453"OT0`JT%#V0#`!HQ(0$#(2,0-ED.")DE`%87 +M(&YD;P$2=-E#!8@/"98C,B!R96YP`,L``3<-``EE(&]R"!T"*!,`3@(%7`8@ +M9&5N$P&,+0">`0.3,1`V9R,`Y)`!L!`5X`!?P!$$FX)C%P;W*M!`MF2@"C +M95!T:6QL+3`'#%\U`&(``.4%#@X!&',C:0'8$WPM;VYL>2XI?`!@4F5O@K,:@!J$P&'!`&* +M&Q)S^!0']@0`ZP4"WPP"B#@#Q84.GL'`5(J`)(A`0%1`3\Y +M!/<&$BR^(`!Y`#=087CZ`0%>'`(6?Q$N_DT"`!L;-=H9`;X!`_8!!+41"4=/ +M`#X.!%T9`!\+!E\9`+L%`$83`K8$`A\2`',-!)0$"NE*`F0``N1*`*X``#P4 +M4&%S($DG'`-`="!Q=;@3`)-&`-A:`:P)`)@"`C8``T&``((!G&AE=7)I8@,!0@' +M`1P)5"X*3V-TZ@(2-5A7-$=.5U,`D#`/87`2L2"\`#`W`#`JT-*C4Z,0(#7P8!544`7@,!*0\0 +M95X)$7G=$0`]`@3N0S%S("@*"`(K'`(0"@8<``*>&$PQ34(I<0"@36%R8W5S +M($=E:7T'`%8<`!\'`6<1`.,-`;)Z`[PZ!KD#`'D``SP!\PYX(H``$%\0FMT;W!?>P#J&0`O``;'``&%"0*5``!]``".!`+*%0`. +M``$T```J+P.W"P-1#V(U.B!07`F`Z2UW86QK6``!J!\`E@4"DP("70`#X"L1-6!A`/U#`+@'!%4``3(``2%; +M$#N$(@"4``0/!0"*#`#2`11YHQ(0--(!(6YY*RH0+7<(`,4](6QE+P(!U!$` +M2#D!5@,!&U(#5@`@86PE#@`=`0'5'P/L%@$`&@4Q.P1S``0&.P2_``!]``.' +M!Q$TBBL`I2H%FW@#;X3Q!2P@2%`M55@L(%5N:7AW87)E+"!S:2D`TRH"+@$` +D?@$1<#T``I(!`'P$'P`!`/______;U````````````",W%#R +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lz4_B7BD.tar.lz4.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lz4_B7BD.tar.lz4.uu new file mode 100644 index 0000000..ecbd423 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lz4_B7BD.tar.lz4.uu @@ -0,0 +1,918 @@ +begin 644 test_compat_lz4_B7BD.tar.lz4 +M!")-&&1PN>]0``!O>&9I;&4``0!+X3`P,#8T-"``,#`P-S8U"``B,#(0`"(R +M,`$`_P<@,3(S-3,U-3,U,3(@,#$R,#(S`"`PEP!+`@(`KW5S=&%R`#`P8W4' +M`0M2,!46%C="!S8`"A(&1E;6]N4$`(&EN^``(M@)A:6YF;W)M&@00 +M(+@&!+T"\`E.15=3("T@:&EG:&QI9VATP`"-E)ZT``R0$`),``$X`]0$N86TL(&%C;&]C86PN;30L +MX0!`92YA8_\```(`$BU4`"1T;Z@`#*($LBP@;VYL>2!N965D?``Q;6%I]@$C +M97)<`05P`"1I;F0`\@,N:"YI;@H)+2!T96UP;&%T97-G`!%B-`(!9@$39;4` +M<`H*1W5I9&6V`AA$5`8$T@$"=0`!MP&R'!L +M@P(#+P,`0@$"(0`$F@,#,P``B`0/-``+`"(`##4`+V%T-``,*&%T,P`&`0:` +M+C,@9VEV97/?!H!O=F5R=FEE=_,"`*``!+L%$&%Q!3!W:&^1`B,J(-D'A5]R +M96%D+C,L$```T04=91$`45]D:7-K%@`"?@<(/@`#'```F0`0=E\!`K<"865D +M(&-A;(D'$'/4!D%N8V5SK0(`DP``=0``%P(`^00!<0!8($%027.7`'-E;G1R +M>2XS30`"]P,2(FL#!:L``20`4"(@=71II`59(&-L87-$``'O!49N86QSG0!@ +M]!;!I;@IA(&YU;6)E`D09BP``;<&42H@1TY5 +M=0$"N@$F("@$"P`:`$%L;VYG4`9B;F%M97,L$```!0L3(!$``&,`4G-P87)S +M?`(AB,``!DT%``)"`$```I58W)E +M873/``%U!`\&`0("J@,#OP,"O`(/'P,8,")R9:`-46-T960B1P,"3P#$+"!W +M:&EC:"!W:6QLB@`!5@`%R@%A(&5X8V5P0`40"EL)`VD"42!T:&%T0PXQ:7)E +M40`!\P,!R@(@("A3"@$T!`"$`0,S!`#T`V`L(&5T8RGO"P+Z`P"I`@8B!`&& +M`0+:``_(`PIA(FYE=V,BFP,!,P`G0<280D!`BL`(2!B-PEQF4@'!L +M:6-I=&S9"4!V;VMEO!(!ZP`!?PH#SA$@("C2$"4@8?L*`*D`("!AZ0`!)Q`" +M+0`(S0`4;Y4(<"DL(&ET('=P`$$@9V5T&1,!70H`I`0W($EN;@`W+"!IG@`! +M40$#FP`B96[)`0P,1<#4`T6%T979E`!,@%1``:A`` +M"@$`/06#;B!I=',@(D#E`!(BO0012!F4X.``P1$2(A`0!:""`L +M(E`(H"P@8V%P86)I;&D2%`8#`07Q``+S#P&W!`CV!0&7`8`@:6YD:79I9&P. +M`&@%(6EEA`$`.A("0@`$K`4`-@$A=&^L#3!D8737```%#A8Z+@$"R`D`P@`2 +M8>P"`,D*`2L`,VEN("2!I;G9O:V4@ +M82!P87)T:6-U;&%R(&9E871U`<``$D!`/X&`"<`4"H@97AA20!`4$`(&EN^``(M@(B:6X#"``0""!F:34!`'P`\`LJ($Y%5U,@+2!H:6=H;&EG +M:'1S(&]F(')E8P8"5&-H86YGH`*P0T]064E.1R`M('<3!P"Y"&)C86X@9&^? +M`#-T:&DI`*!)3E-404Q,("T@T`'2(`")P=28)<2)C;6%K92(D`P"D"2EO;$T` +M`E8!!NL#`)0`07,@:6Y,`0]M`0$P87)E3@(29-H!-64*)[P`$R>M``,D!`"3 +M``!.`/4!+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_```"`!(M5``D=&^H```@ +M`0BB!+`L(&]N;'D@;F5E9,4($'G*!0'V`2-E%7W)E860N,RP0``#1!1UE$0!1 +M7V1I=&%R+C54 +M`0CQ!$%A8F]U4P4@"`"X!!,BO0(R+F@B +MJ0"`:&4*2R"```[!P$C"8!A=71O;6%T:?\"$'G!`C!E8W29`Q%D80T#'`(%>`D0 +M9BP``;<&42H@1TY5=0$"-0(F("@$"P`:`$%L;VYG4`9B;F%M97,L$```!0L3 +M(!$``&,`4G-P87)S?`(A`@@;W#+`\!A;"!2;V-KFEP,A8`!'P!32],6E<=`*)L>FUA+"!L>FEP$P,O>'HC```9-!0` +M"0@!```*56-R96%TSP`!+0D/!@$"`JH#`[\#`KP"#Q\#&#`B&-E<$`%`+D%!&D"`M<1 +M`$,.$&F6!2=A>,H"("`H%@4!-`0`A`$#,P0`]`-@+"!E=&,I[PL"^@,`J0(& +M(@0!FP$"V@`/E@,%`<@#82)N97=C(IL#`3,`)W-HL``!$@`/1@-C!`4$`EL! +M`8D`#UD#``H6`S-7:&4#`@"_"`/4`A)SY@5A?P(-F5A;;4%`A$+02X@(%1`%%-I4,`4&EN9&5PJ@`E;G0B`0!$#0'E +M%@!"!1)O;`T&L`M4(%=I:VE2#`,,$S!H;W=1#P*F!P!."`/:``N@%03\!`#S +M#@!0!@/-``%P`$!L=V%Y1@$`W0$J962*"`)'``_0%__@"?H#$&,W!@`%&,)A +M=&5V97(@8FQO8VO5"@#N!S`@:70(!D(@66]UYQ,!Q`U`8F%C:T`#,69R93T/ +M,'!A2X'<70@82!T:6U7`W%O2W,``"."5)U='!U=.\"`&`$H&]B:F5C="US='G@&4%P<')O +MR`,`^10"^@!0=&\@:&$Y%D!U;'1IPQ,$J0`"`00`N0A5(&]P96Z>`!0@]`\A +M=7-U!Q%I(0AC:71S(")`/``2(KT$$',3&P7J!`,<`'`@:71S96QF4P$`?000 +M+P(/8'1E;B!U7,N +M"@`!`/^)`#L7#Y\!30\`'@M1-S$Q-S4`'F$Q-3$U-3(`'B\U,0`>_U771F5B +M(#`Y+"`R,#$S.H<*D2`S+C$N,B!R93(3GF0*"DIA;B`R."D`(2=SJPM`=V5B +M!A(N3``N,3-,``%U`!LQ=0`/*0`&%S`I`&%$96,@,#=2 +M`$`R.B!)4AL!"`P("@4#T!0`[PP991H,`)T%`ML-`DX8`9`(A"`*3F]V(#$Q +M5``@062V&P:L(H-?7TU!0T]36!<-`(('.&EN(,01!-D/(G)EJ08`)P4`N`P2 +M:P@','-T;TL.`+@B?PI/8W0@,C!K``4`.08`A@82=J43`@,,`S8``[P!#Z$` +M`"MGF]P5`%64V5P(#*!``VH`0+.&7%T;R!S965KD`I&@'5 +M`@DX`P#*"C)I97-.``*:!&$Q.B!.97>:`PI(``0;`UES(%-&6`,%"S\`0$)U +M:6QK!0"Y`:)O;B!7:6YD;W=S(0$#YP4.2P$K,&%+`14P2P$P57!DN!5T`P, +M,RUS._@6"*$9`ADA$F_B'$!H87)D4P(E+W-;`E%B&0"5##!E;747&6D@8G)O:V5B`#`R+GAG!`!W$`&O)2%O +M9K(6<5541BTX(&AH`!)SF04%^P!`4F5F85D'`04/$%]R#B`H*7L:`"\-46-O +M;&QEB"$`XPT`2@\P;&4MJR(`W`<`YR@!EB(#+`$!D`P@;VPA`P,2)!!S'Q\@ +M=W(,`0-W`!(Q$`:!,3H@4W!L:71?#0(`!@`L`0&1!C!P87)N`@(>%P`T"`/` +M`@":`Q%L^24";`(!QP`5,30#`X(#`L\AE`=V]R:V(!9')E='5R;JP<`)`B`2$/$&;N`@%9`7%A +M8F]R="@I1``&-04`M0$`>0`WH2 +M`-@48F5N(&-O<)01``X#`1X2!,@)`4$``XD%$#`(`@&R)P!X`'8@36%C($]3 +MJ0(`/``'K@0!.@`#0@(D,#I0``?K``"J"0/]`A!S7@D"[@!4&D1%0*G!`/4!P`:`0"4 +M'0.-"@)C``:;``-=!`'?(080!00'`@0;`V!C(&-R>7#%!`+!#`&/``/[!B$P +M.CT=`0("`"P&`A`$`"8#`$<%`BH``@4-$C``"`/4`Q(Z+@=`+6=I9`8``"H$ +M02`M+74.`!!U#@`!!P4#,@X#P`%@4F5D+6)L8!8`_"(!E`<&_@$!&14@97)D +M`P,C`@!4!`#.`@!8*P%.``,)`P!*`F)I;FEM86RM``$3#7@@;&5G86-YM0#,O`G@5`,0# +M`#(=`I`%`W8(`[X!`+\'$F0K``"1(#EL9&5?"`!=&Q!LNP$`%0X!0"@A963+ +M`P80`55296QA>`,"`,(%('-T7P;09F%I;'5R97,[(&UIF7'`P`M`0!Q`0-7!`!_&"%O;88'#%$``8X%4&YT-C1?S`L%``>@ +M;V9F7W0L(&1E=@<`,&EN;P<`,'5I9`<``#\#$&<+``*<``7^!`08*`'"$#9! +M0TQ%"0)U`!4QN@024SD#!C48`20!!28#`$0!$C`B!P%J!``&$0)\)@.6`@<* +M"3$Q+G@-%P&,``:%`Q!2R`=%869I;PX)`54`!<,%$$'''0!6``?S(P4Q!2%L +M>2P/!/T"`EL`!;L!8$EN=&5G)``9"``+3 +M`P`I`Y!F=71I;65S*"DX+F)#>6=W:6YK$@9%`0>'`78R+CQA`;&5A:U0!"!X!`$@`$G,S``5<`0!D``FUA+WAZ6P,#X0(`9P`$%B`)`@@"0`0`GP43>?(. +M`$D`$4C()"`@9_X2`D4``-@)!$$`0$]P96Z4)7`B9WIS:6`@)[``6)`D!!9&1IR0HP86P@2@!`-P)M(B%S98$#!+`=!),-!'4'85=!4DX*"1PK06ES(&/Z,Q5OPP<` +MU1U0861A<'2;."!N91PC,V%R>;L!"=\`55-T=61I8`L`E@`/2@`!-`E!;!$#``@!`%HA +M`5\``_40`/,``.D#,$1E8E\!L4)U9R`C-3$V-34.`?$.`*8$`+$H4$AUA,`2P$41:L> +M!]$(`8(`)&]N*Q8!\0P"]PM`;F]W"?P#`9<2`78,$G11``85!@#0``.@"@8, +M#A!?*A4@>5\/!A!?;P8P*"D@6"X$[`\`00PQ+`H)2!R7!,@961S(`#/"P"])@!1,#`L"@E4 +M!`"`!P!:#0#B!@!A!0:^`P`\`R!T(",%"7$F`;L`!LHA(@H)?0`4<^@OQ6)E +M(&UU8V@@96%S:>8-`H\/*RX@HC,`311":&4*"3$8`5\1"$(G%',])P;1#P"# +M'`-Q`!(N_!`"MP80.$4$)&YY:Q8:+Z\#`HH6`+L!#_D#`@U)``J["0B[&0+W +M'`%*``1;`@+Y#!!CN@$@97)^)2ET;W89`$T&`'PT`@2US:7IE9`4/$G.*)3$@*A$) +MSAH`A@,/[A<"`!<-L2@I(&AAFEPEP2"_`0`P`"`@82D`*RDN +MM@#@2F]E0,A(&*Q'`&[ +M$P%-$P!7!B)A=$H`!9X'`<4(`AQ``-A"`FLK`)$I4F0@8G5GQ0(@.L%`&P"!/P>"K`3``XT +M`,T``$8$`3,8!B,&`;X<`681`$LA!O8?`FD#`#\.``D)$V'=0W,B4V-O='0B +MW!80(%0```L*!9X#$VV#/A!SU`8$-0"22V5E'!L;P$0`&T6$&5D#0)M`0)E +M+95V97)F;&]WPP$_@D$V@Y0"@EP2P!$'26$`&#.%%E(&)O9(L]``8-`8D! +M`#8!,#L*"6T&$FG,$@#0`2%O=:T-P')A;F=E(&)E:&%V:2U/`$0.`0L,!!0[ +M`9@)$7)R`0&K`0)],U$M3A+,&ER95<8!&@8,"-I9O4,!'@8 +M`H9`.`K@-`=0/$"V!+C%E8V^!!5)L;V=I8[$5`C0` +M$',T``!.%0)/(@'V%`!V`0$8``);20*;%P-]`@;4"`E3`D0T+C$T>AY`9#L@ +M:5P\`%)$`)@#`1X`&#,$0"()84H*`%,!`?`($&=+!1$O=B-@(&UI>'5PWRD& +MR!8"L0``P@D4:<0O(F0*[18`9P0"A"D!'@<2+L@?!N8.#*8`%3.F``*3&`7Y +M`@-V'0"=!A$L3`(`DP`2+)H`$"PL!`*>``$[`2!C8640$6*8"S%V97+;`P32 +M)P&-`".``#3"P"! +M`&`@8VQA`B4&1E=FEC5@$!RR$!32(` +MB0H`2!@3(G`#&2*)"``6$`(U!D!N97=CM@("<0@#I``6.^0#`O$1`%P"`6,$ +M"$T!`#4"`!`A('1H2PL!>P`"G!LE.#I(#0)E#@-J)P!(`@2;`PDD$1PL6PT` +M.QH'004P26=NR@@$[`I"('-I>ND,`$,-`B@K`#0.$F&[(@#8"P#^(14RC@`, +M7@(6,EX""BD``*@!(&)A4T$`58(`$D:,6=E=)H-`J4\`6(+!,U5`'$:`8X%13(N.2Z"`0(Z``!( +M`1)L5#$08A,9`=L+!^$/(B@MI0]`+7HI+*L#`"$/,0EO9JH-,')M85X2`)X? +M,F5S'!E-\4"%C'% +M`@HI`#!&:7BF00&U)0#H$P+X)`9A`0"G!`&Q"04]#P%J``(_*P]J``$,S!D" +M8006-X8(4#`N.2XPQ@<`@0<"SE,@=VFA%3-U?@=`70``Q`;$C>)!5!A(&-O=90<(V]FE@0'K28`Y04!?P`"J0\.IP`'\A4* +M*```6P``J0,!IP`!!0`17VD!$%_?!"%B>=DQ`D4!`@"&!P8T4@2$`E`M+61I0H&%`!U86-L +M+`H)=.T!_P!386UU;&D@4W5O;6EN96Z,``T'/@D!_``%C``&/P+`3&%P;R!, +M=6-H:6YIU04`>E4!20(`3AP!54D`!0X!T@D!FB0#2@4`DP$@;&17"0%5+@#Z +M&P1O!#!B=6?&!0$8``!``;!O9@H)(FQE;F=T:)X4D&5N9"(@9FQA9QX*!6$` +M$G,?!`96`0).``,"!!$@FP8!4@8!/@(`J08!+P0$-P`%\P,01J,!0"!C=71K +M`$!R96%L>0<`-```D0(`Z`42;AU(`0\!!38`"Q@(%C+:`@+$`0\I``46,2D` +M"E$`$4W_)@"X!D%S+"!R%Q@`E```P0*@9&]C+71O+6UA;C\.`WX'`'H!(`H) +M%``!NB0#.CL/]`4&!XD%"B@``G@``"4(`/$%`#(4!CP"`[H,4&-H:6QL!Q<+ +M.P`03Y`&`-D0`/`"`O<'(B!A>U8@(&_I%P'8"P#Q#S%G:6Y\*2!O9L\&(PH) +M$P(!6!X"IQL"K%@"S0(#CQL`+1D`3P4"2C0`+5<`#P@2>88`!G,&$%0$!@,S +M```5`0`X!!-Y\Q``6!(`0@0`QB4`NR(#Y@D8.I@"`FT(`#4((&5XU!8`0D4$ +M.``!YAXS,D="?R8S,51":`$"5CD-#`48,RX:`"T!!B@`$D,/"`(_!R5U;E@G +M`LP.`%T5`7-#`-H$``,#`+(``"H!$"*:`0#Z$P##'T!N;VYEC@L%9!T!?@00 +M;H`,#(O,V(#`7T``-@"`68(!M,#D$IA +M;B!00P`4,#`!`,`-D2`.L(,$=.55L! +M$"><*$%G+71AE`(&[UP`FP`U;W-E,@`!7QA`960@;2\B0'=A&%C=&QY +M"@EA*R``YA<@-$>T"`/@$@=H$0&=`0(;#@=G``!;`0!F``=#`E`H/CA'*>,` +M!3X"`-0``-P20V%S"@E&.`'M"T!)('!U\"\)C0(`(1`#)`$%&"\`3`$`P50! +MA``%+`<32=0(`=D+`-@'$&5_)P`!`U!N+6UA=&\%`!5=`-0^(6]R00R".R!) +M"@EH;W!(#9$@979E;G1U86P\)0'Q3``?`0`P"S)D92`G"@!#*`+."0#.50,5 +M/P)K#@R7!A@SEP8`J@`5,"X!($-O(QH0=9``!*T`!'8%`%P"`9@J$F7?``8U +M`!!.+4T!6%8`Y4``M`03+/<+`7`(,")(:>\*('DBM0$#3@`@+C$X"0'/#`"O +M`!0Q.0`#Y"$&7```F`<5>C0\`)<"D6EM;65D:6%T90T!`9`X,$5/1M$J`(P? +M,'1R><\/`?X5!<,4`!$.,')E9V$F`8D+`.(/`%T%`-(D`!4``,\;`6X2$'B2 +M%0):#P3+"P"=`R%O9H0``Z$"`&4(`+X[#Y$%!!@S:0<`*``#T!`0-]`C`54! +M$TU''"`N8205`4X'`!($$B#'(!,O`P@$:A)#"@EA8_P!(61O*`!1@,%1DL##`H`QP5` +M*"D*"4L'`=$2`+4,$FUJ5B5I;I(+`Y@``P8=#GX#!RD(`)@`!B@``:(X`88" +M`.D"`RL#4R`P+C,ZO#P&[A`165TG!`2 +M*;L``NL]`GX2`!L\`PP"`SPP#G8`!V$-4D%U9R`S+R02-^,R`+,R`)D#!+P& +M`BL>`(,+(W,L7&,`J@4D86[/6P2`!40*"2A!K1<991L1`*HE(2XI;``#310! +MF`1`860@9QD+\0$Q+C$W("TM<&]S:7@@+2US22<$D@<2+C<`!3@,$U*S&F!S +M=6ED+W.+.00R$03O"T`[(&ET'00%=@0@"@E/&D!RQ,2(M+6`%%"W0`0,R!@&^)0"]*!5RF!,1"ND`!H4& +M"5@$-C(N-L`#`$@!!B@``0D'"]4-!\`-`ED&`&T&,6%N:QL'`88+*`H)$B4# +MNP`%[`($0!X`20T"&P0!N@H$Z"LQ0U9361\`V$@G=6R=`0NT``?Y#@(I``_& +M#`,8,AL(`5$`!2@`!E,*"B8B$B=/)@"$"@1$(0&4`A%D*`4`H`($XQ,R8W)I +M6!A2\`!ZP'`8HD`?(] +M`/T+`'D("%H0`.````$/`(P#`&4H`/8=(!"PL!%C(Z$PHH +M```+`0[=!1`@D0,"3"(`!`P"EP-0>2!C;&\0#@"5*4%T8L<`2"Y`0`2%0*7#0#)-0"F'!=Y@A.!4VME;&5T86Q\ +M"P:,"`%=!P/L`08"!0OL`1HQ[`$&*`!01FQE`@$I`1%A +M(2`!RET":0(`)`%B/'-I9V@^VP`&204!<@(!=!D`]P0&.!P`A0-0,BXQ+CDW +M"A-TMPD":0`A"@EJ``!L`0\7$``#80`%NP803,0*'!`#*,#!U;&00!!!RY0('H0(Z.PH)4P`!F@D2 +M=\9.`,D+`%\#`WL"`NP#`I(!$&Y3,@#,:`!T`P6-#C%T;W7L`@!,!0""10-@ +M`14QX1$+_@`'-@DF"4P[%@"!``#L!`*Z(!!N9AT!*B$`"0$`=00`!`,`_D]$ +M97)I>&,`!:4'"V,`".4(`,0!`QHC#'8+)S%BZP8**```P@D&50`17PQ%`]9G +M"KT,`48=`!$:(6%L4$%E+@H)3F]TM@4!3@8$BP$"B0$`IQ8!-&T*<@`)NAP1 +M(LH&``\!47)EP1$&XN +M2!%N/2T`?AH$4@`%;@$,4@`6-,("`5(`!4L2!/P7(6%NPT4@8FS**0#[(!!A +MM0D!R@4`U1$`'``!"P<`_PX`;VP!NB\!)@`!#D@!3@D188(3!75$`>T70&]R +M(&>R4@`_#`!N$"1B96T+``L"`P,>`BXO`#4M`2PQ0&]T:"!:!P*Y!0J(`1%(#0<$1PT@W``%J!`=B!@!<`08I +M```K%`'M`0">`@!X`C%S("BB``!W!0#C`@)3"Q``#U!(`200"O0('_0`(E```^A)` +M:6YG+Z,#`%L-`7H``38*,7!A>-4`!>T#`+T6(G5NI0$@9616)`$V`0^Y"@,W +M,"XR8@<`*0`%*`!`($ET)T0*$71)'#)E8W3&`1!I%@"S<')E='1Y(&=O;V3] +M`0;U"1(R&201;^I#`=<:`+\F(&]F[`L480H``_T&``D#`(<. +M`/T(,$=E;M@``;P#$RAQ+3`A*2!0.P'+'0(6`0!$$0%"``'H'[)I0@A=""X3X1L +M8VAM;V0H*6L`!245!Q(#`74!!]83`6L`!2D`$47*,`8(`S-E`2!W:#(!`24``Q$(`4\` +M(6)Y00`!SAE1('1O;VRM!``W!@+F*`4N``*%!@';'#5M:7HL`08U"P=L``$L +M`0?9!0`L`0,'0@(U`@'0*`%?$0#Z!@'1*`&-!@9$``"<%@/T5P*A`"1F($8! +M05!%4DTW`001`&A/5TY%4BRD9")R96<0`3L`<71O(%-5240S`!!38`0`LQ@` +M=A<%F4X.B@H78AP,"B@`$4%F"`"J!05@"P"1!A$B!RX4(KL0$'/:!Q%A?P`" +M&S4&D78`YP,`)48Q("!"0Q\`L`0`APD0:;$$`O4``"U=P'D:"`@8=,5865R+6=R8?@T`4X/ +M,&9A8UX"%F&'$``C`03;%0VW'P$:`0`E&@",`@/E%0#R,@&)9P.,:0%`$`*T +M%0/&`P"C-`&B&`1G`0%'`"%A"P,-$011`"!D99X) +M$&*A!0$4-S%Y;W5#``1*&@():!(I5T``FP!A;W9E!Y<#`D<5`7(!`G(`46EN=F]L +MU`$$\P$!S08$!%4!40T`4P8`!@(`7&(1210=$V.*"0&"-!!X80L```(@;V;/ +M$>(@;W9E@J`:L&%2W(`0'8-0)T'@,^%0P2`3_`$`R+C`[Z0("PPD`9Q]!<')O=/P+`+,Y]0-I;F0@(VEF +M9&5F)W,@=6YT:6R@-P'#<0+U%@"S$3-Y=&@T"P%B`P"L`P&L`@)X``*['@:: +M``#8"0OK``>7%P#:!0*!`0`;&S!S92@`>5$@5&AE>9<)`$XL`HX.`.L"`&8/ +M`4L``#HJ%6;B'PIL`,!R96-U +M`0"S#"%S90($`BD#`$D($&``"I`2`M<",%"W8+`@5.`;%P!!H`$"W6(E!I9FEC"@QX#>5.` +M`AH/`Y@E$3;N"!`@ZVL!?2<0.P8`$6Q-*0#_!2!O;$\0$F@C*`+9``%'"@!? +M``&(`0#V!Q`GIQ81EQ`:\G4&QE('5P10<`8S0"/```=@@@;V[+ +M*T),1$52=@"B4U5-34%22453"OT0`JT%#V0#`!HQ(0$#(2,0-ED.")DE`%87 +M(&YD;P$2=-E#!8@/"98C,B!R96YP`,L``3<-``EE(&]R"!T"*!,`3@(%7`8@ +M9&5N$P&,+0">`0.3,1`V9R,`Y)`!L!`5X`!?P!$$FX)C%P;W*M!`MF2@"C +M95!T:6QL+3`'#%\U`&(``.4%#@X!&',C:0'8$WPM;VYL>2XI?`!@4F5O@K,:@!J$P&'!`&* +M&Q)S^!0']@0`ZP4"WPP"B#@#Q84.GL'`5(J`)(A`0%1`3\Y +M!/<&$BR^(`!Y`#=087CZ`0%>'`(6?Q$N_DT"`!L;-=H9`;X!`_8!!+41"4=/ +M`#X.!%T9`!\+!E\9`+L%`$83`K8$`A\2`',-!)0$"NE*`F0``N1*`*X``#P4 +M4&%S($DG'`-`="!Q=;@3`)-&`-A:`:P)`)@"`C8``T&``((!G&AE=7)I8@,!0@' +M`1P)5"X*3V-TZ@(2-5A7-$=.5U,`D#`/87`2L2"\`#`W`#`JT-*C4Z,0(#7P8!544`7@,!*0\0 +M95X)$7G=$0`]`@3N0S%S("@*"`(K'`(0"@8<``*>&$PQ34(I<0"@36%R8W5S +M($=E:7T'`%8<`!\'`6<1`.,-`;)Z`[PZ!KD#`'D``SP!\PYX(H``$%\0FMT;W!?>P#J&0`O``;'``&%"0*5``!]``".!`+*%0`. +M``$T```J+P.W"P-1#V(U.B!07`F`Z2UW86QK6``!J!\`E@4"DP("70`#X"L1-6!A`/U#`+@'!%4``3(``2%; +M$#N$(@"4``0/!0"*#`#2`11YHQ(0--(!(6YY*RH0+7<(`,4](6QE+P(!U!$` +M2#D!5@,!&U(#5@`@86PE#@`=`0'5'P/L%@$`&@4Q.P1S``0&.P2_``!]``.' +M!Q$TBBL`I2H%FW@#;X3Q!2P@2%`M55@L(%5N:7AW87)E+"!S:2D`TRH"+@$` +D?@$1<#T``I(!`'P$'P`!`/______;U````````````",W%#R +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lzip.c b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lzip.c new file mode 100644 index 0000000..8f4e06d --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lzip.c @@ -0,0 +1,141 @@ +/*- + * Copyright (c) 2010 Michihiro NAKAJIMA + * Copyright (c) 2003-2008 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* +Execute the following to rebuild the data for this program: + tail -n +33 test_compat_lzip.c | /bin/sh + +# Use lzip command. +zcmd=lzip +zsuffix=lz +ztar_suffix=tlz +mktarfile() +{ +mkdir $dir +echo "f1" > $dir/f1 +echo "f2" > $dir/f2 +echo "f3" > $dir/f3 +mkdir $dir/d1 +echo "f1" > $dir/d1/f1 +echo "f2" > $dir/d1/f2 +echo "f3" > $dir/d1/f3 +(cd $dir; tar cf ../$name.tar f1 f2 f3 d1/f1 d1/f2 d1/f3) +rm -r $dir +} +# +# Make a lzip file from splitted tar file. +# +name=test_compat_lzip_1 +dir="$name`date +%Y%m%d%H%M%S`.$USER" +mktarfile +split -b 3600 $name.tar $name.tar. +rm $name.tar +$zcmd $name.tar.* +cat $name.tar.*.$zsuffix > $name.$ztar_suffix +rm $name.tar.*.$zsuffix +uuencode $name.$ztar_suffix $name.$ztar_suffix > $name.$ztar_suffix.uu +rm -f $name.$ztar_suffix +# +# Make a lzip file with junk data at the end of the file. +# +name=test_compat_lzip_2 +dir="$name`date +%Y%m%d%H%M%S`.$USER" +mktarfile +$zcmd $name.tar +mv $name.tar.$zsuffix $name.$ztar_suffix +echo "This is unrelated junk data at the end of the file" >> $name.$ztar_suffix +uuencode $name.$ztar_suffix $name.$ztar_suffix > $name.$ztar_suffix.uu +rm -f $name.$ztar_suffix + +exit 0 +*/ + +/* + * Verify our ability to read sample files compatibly with lzip. + * + * In particular: + * * lzip will read multiple lzip streams, concatenating the output + * * lzip will stop at the end of a stream if the following data + * doesn't start with a gzip signature. + * + */ + +/* + * All of the sample files have the same contents; they're just + * compressed in different ways. + */ +static void +compat_lzip(const char *name) +{ + const char *n[7] = { "f1", "f2", "f3", "d1/f1", "d1/f2", "d1/f3", NULL }; + struct archive_entry *ae; + struct archive *a; + int i, r; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + r = archive_read_support_filter_lzip(a); + if (r == ARCHIVE_WARN) { + skipping("lzip reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + extract_reference_file(name); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 2)); + + /* Read entries, match up names with list above. */ + for (i = 0; i < 6; ++i) { + failure("Could not read file %d (%s) from %s", i, n[i], name); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae)); + assertEqualString(n[i], archive_entry_pathname(ae)); + } + + /* Verify the end-of-archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify that the format detection worked. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_LZIP); + assertEqualString(archive_filter_name(a, 0), "lzip"); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + +DEFINE_TEST(test_compat_lzip) +{ + /* This sample has been 'split', each piece compressed separately, + * then concatenated. lzip will emit the concatenated result. */ + compat_lzip("test_compat_lzip_1.tlz"); + /* This sample has been compressed as a single stream, but then + * some unrelated garbage text has been appended to the end. */ + compat_lzip("test_compat_lzip_2.tlz"); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lzip_1.tlz.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lzip_1.tlz.uu new file mode 100644 index 0000000..01e5e3b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lzip_1.tlz.uu @@ -0,0 +1,10 @@ +begin 644 test_compat_lzip_1.tlz +M3%I)4`$,`#,,/!NGC#0&C6L"2_R2/O9*^":#5/GP,U"QL$1\Q:(3S>V*OTP* +M1&9J-1:S\^>DEIOT;'&#"`B6#7ZO7%">,>LZ=:BU,Z7*^>M<3FV:GKO_?W;` +M,N31CE_$<-$(3$J*AB5TTG2\;X[CSPOI6IIPV8\]86+J37::!/_LA^/@O"(1 +MAA`.````````F`````````!,6DE0`0P``&_]_BC86HZ6L8?*M6SC8*JJ7,GS +M0IZA9CQ/^VS2N26K[BXKGC_1Z&JR]S2)5Q",)*$1RS"):7X:?OBQDJXU`>8K +M\2*:_6!:)ZD5FBGJ?II6>-V*OTP* +M1&9J-1:S\^>DEIOT;'&#"`B6#7ZO7%">,>LZ=:BU,Z7*^>M<3FV:GKO_?W;` +M,N31CE_$<-$(3$J*AB5TTG2\;X[CSPOI6IIPV8\]9>BP>V?/L._78%+F2N-; +M6V[`1"7)=_,5LD9U%73FQV-?_X5OKW0_.'N"`!P```````"R`````````%1H +M:7,@:7,@=6YR96QA=&5D(&IU;FL@9&%T82!A="!T:&4@96YD(&]F('1H92!F +$:6QE"@`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lzma.c b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lzma.c new file mode 100644 index 0000000..86a2665 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lzma.c @@ -0,0 +1,155 @@ +/*- + * Copyright (c) 2009 Michihiro NAKAJIMA + * Copyright (c) 2003-2008 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_compat_lzma.c 201247 2009-12-30 05:59:21Z kientzle $"); + +/* +Execute the following to rebuild the data for this program: + tail -n +33 test_compat_lzma.c | /bin/sh + +# Use lzma command of XZ Utils. +name=test_compat_lzma_1 +zcmd=lzma +zsuffix=lzma +ztar_suffix=tlz +dir="$name`date +%Y%m%d%H%M%S`.$USER" +mktarfile() +{ +mkdir $dir +echo "f1" > $dir/f1 +echo "f2" > $dir/f2 +echo "f3" > $dir/f3 +mkdir $dir/d1 +echo "f1" > $dir/d1/f1 +echo "f2" > $dir/d1/f2 +echo "f3" > $dir/d1/f3 +(cd $dir; tar cf ../$name.tar f1 f2 f3 d1/f1 d1/f2 d1/f3) +rm -r $dir +} +mktarfile +$zcmd $name.tar +mv $name.tar.$zsuffix $name.$ztar_suffix +echo "This is unrelated junk data at the end of the file" >> $name.$ztar_suffix +uuencode $name.$ztar_suffix $name.$ztar_suffix > $name.$ztar_suffix.uu +rm -f $name.$ztar_suffix +# +# Use option -e +# +name=test_compat_lzma_2 +dir="$name`date +%Y%m%d%H%M%S`.$USER" +mktarfile +$zcmd -e $name.tar +mv $name.tar.$zsuffix $name.$ztar_suffix +uuencode $name.$ztar_suffix $name.$ztar_suffix > $name.$ztar_suffix.uu +rm -f $name.$ztar_suffix +# +# Use lzma command of LZMA SDK with option -d12. +# +name=test_compat_lzma_3 +zcmd=lzmasdk # Change this path to use lzma of LZMA SDK. +dir="$name`date +%Y%m%d%H%M%S`.$USER" +mktarfile +$zcmd e -d12 $name.tar $name.$ztar_suffix +rm -f $name.tar +uuencode $name.$ztar_suffix $name.$ztar_suffix > $name.$ztar_suffix.uu +rm -f $name.$ztar_suffix + +exit 0 +*/ + +/* + * Verify our ability to read sample files compatibly with unlzma. + * + * In particular: + * * unlzma will read multiple lzma streams, concatenating the output + * * unlzma will read lzma streams which is made by lzma with option -e, + * concatenating the output + * + * Verify our ability to read sample files compatibly with lzma of + * LZMA SDK. + * * lzma will read lzma streams which is made by lzma with option -d12, + * concatenating the output + */ + +/* + * All of the sample files have the same contents; they're just + * compressed in different ways. + */ +static void +compat_lzma(const char *name) +{ + const char *n[7] = { "f1", "f2", "f3", "d1/f1", "d1/f2", "d1/f3", NULL }; + struct archive_entry *ae; + struct archive *a; + int i, r; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + r = archive_read_support_filter_lzma(a); + if (r == ARCHIVE_WARN) { + skipping("lzma reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + extract_reference_file(name); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 2)); + + /* Read entries, match up names with list above. */ + for (i = 0; i < 6; ++i) { + failure("Could not read file %d (%s) from %s", i, n[i], name); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae)); + assertEqualString(n[i], archive_entry_pathname(ae)); + } + + /* Verify the end-of-archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify that the format detection worked. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_LZMA); + assertEqualString(archive_filter_name(a, 0), "lzma"); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + +DEFINE_TEST(test_compat_lzma) +{ + /* This sample has been added junk datas to its tail. */ + compat_lzma("test_compat_lzma_1.tlz"); + /* This sample has been made by lzma with option -e, + * the first byte of which is 0x5e. + * Not supported in libarchive 2.7.* and earlier */ + compat_lzma("test_compat_lzma_2.tlz"); + /* This sample has been made by lzma of LZMA SDK with + * option -d12, second byte and third byte of which is + * not zero. + * Not supported in libarchive 2.7.* and earlier */ + compat_lzma("test_compat_lzma_3.tlz"); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lzma_1.tlz.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lzma_1.tlz.uu new file mode 100644 index 0000000..57fa501 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lzma_1.tlz.uu @@ -0,0 +1,10 @@ +$FreeBSD: head/lib/libarchive/test/test_compat_lzma_1.tlz.uu 201247 2009-12-30 05:59:21Z kientzle $ + +begin 644 test_compat_lzma_1.tlz +M70``@`#__________P`S##P;IXPT!HUK`DO\DC[V2OB%Z^'=ZT59ANYMTD(/ +M^W;\8!%O7<+P&=#(9W<_!$Z.7/Y<&\(8+E0^,_-\Z"D^P'N0J^4-UH"WMJ<& +MV-P6=Y[-FY$IFNZ="RF24TO.B7EP[F]BGMJSP[]OZ_P9/#J'T=;7E&&A@J<[ +MA^C'Q*/Y&I)2^T930'MJTK-98U0D9R*-X2^5__6H:+A4:&ES(&ES('5N`W2"/3R1F1:P:&Q9A +MGH2JJI9$C?8.=WTE:O<1WA@X>DK-Y#SW;I2!P;NYG^2"-(D9/E(D_0XK_H,\ +95*/V"T#E9ZO][@'R,6E&^A([.##_\M#YU@`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lzma_3.tlz.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lzma_3.tlz.uu new file mode 100644 index 0000000..bee8289 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lzma_3.tlz.uu @@ -0,0 +1,9 @@ +$FreeBSD: head/lib/libarchive/test/test_compat_lzma_3.tlz.uu 201247 2009-12-30 05:59:21Z kientzle $ + +begin 644 test_compat_lzma_3.tlz +M70`0````'``````````S##P;IXPT!HUK`DO\DC[V2OB%Z^'=ZT59ANYMTD(1 +M$Y^=;\4%U_CXKQ*F$OFZKEQUG)1U8="](V<2K"U1\Z6%H(UNQ[Y3.=D'>_G- +MCO71X+M*7WH7$D1&E9Y$XHW,(`[X";GGTO+,'&1?F%<@`.$-OV;8P1?*M$A" +:MA+1XONREMK,1('455L=X1>WC#1YW"('I@`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lzop.c b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lzop.c new file mode 100644 index 0000000..cd43afc --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lzop.c @@ -0,0 +1,131 @@ +/*- + * Copyright (c) 2003-2008 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * Verify our ability to read sample files compatibly with lzop. + * + * In particular: + * * lzop will stop at the end of a stream if the following data + * doesn't start with a lzop signature. + * + */ + +DEFINE_TEST(test_compat_lzop) +{ + const char *sample1 = "test_compat_lzop_1.tar.lzo"; + const char *sample2 = "test_compat_lzop_2.tar.lzo"; + const char *sample3 = "test_compat_lzop_3.tar.lzo"; + struct archive_entry *ae; + struct archive *a; + int r; + + /* + * Test1: tar ball compressed in one block. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + r = archive_read_support_filter_lzop(a); + if (r == ARCHIVE_WARN) { + skipping("lzop reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + extract_reference_file(sample1); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, sample1, 2)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("INSTALL", archive_entry_pathname(ae)); + + /* Verify the end-of-archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify that the format detection worked. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_LZOP); + assertEqualString(archive_filter_name(a, 0), "lzop"); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Test2: tar ball compressed in multi blocks. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + extract_reference_file(sample2); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, sample2, 2)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("file1", archive_entry_pathname(ae)); + assertEqualInt(19, archive_entry_size(ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("file2", archive_entry_pathname(ae)); + assertEqualInt(262144, archive_entry_size(ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("file3", archive_entry_pathname(ae)); + assertEqualInt(19, archive_entry_size(ae)); + + /* Verify the end-of-archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify that the format detection worked. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_LZOP); + assertEqualString(archive_filter_name(a, 0), "lzop"); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Test3: tar ball compressed in one block with junk data. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + extract_reference_file(sample3); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, sample3, 2)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("INSTALL", archive_entry_pathname(ae)); + + /* Verify the end-of-archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify that the format detection worked. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_LZOP); + assertEqualString(archive_filter_name(a, 0), "lzop"); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lzop_1.tar.lzo.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lzop_1.tar.lzo.uu new file mode 100644 index 0000000..9eeca6a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_lzop_1.tar.lzo.uu @@ -0,0 +1,30 @@ +begin 664 test_compat_lzop_1.tar.lzo +MB4Q:3P`-"AH*$#`@8`E``04#```!``"!M%"`FEX`````%G1E2`H82?@"@-F'4"+"!T;PJL!`-W:71H(%AH +M;6!T!$UA8R!/4RQT%@$@8V%N)X`&+',,86YDO#.4(0(@+4<@(H0(`2(@?B\H +M;`D`#2UD;W=N;&]A9"UD:7(O"E1H92!R97-U;'0@=VEL;"!P=01P<')O<')I +M8"A\(I0F`BP@?!\#('1O;VPND!`!9&5F8780;VXP.Q$@:7-L +M*<0K`V4@36%K98P.=!)U(@IW(F%L2`H82?@"@-F'4"+"!T;PJL!`-W:71H(%AH +M;6!T!$UA8R!/4RQT%@$@8V%N)X`&+',,86YDO#.4(0(@+4<@(H0(`2(@?B\H +M;`D`#2UD;W=N;&]A9"UD:7(O"E1H92!R97-U;'0@=VEL;"!P=01P<')O<')I +M8"A\(I0F`BP@?!\#('1O;VPND!`!9&5F8780;VXP.Q$@:7-L +M*<0K`V4@36%K98P.=!)U(@IW(F%L-'C]V%*E1 +MQ@T;(4EJ]!@CQHT8,P"`8(*QILV;.'-*K#.'3A@Y($``D//F#1V=%.^@*5.& +M#=*G4*-*G4JU*M0P8L:0*6/F#)HT:M:P:>/F#9PXH5 +MK%BR9M&J9>L6KMRM7;^&'5OV;%HZ:]N^C9L5<-W!>`WO5>RW,5W!=POK1A"*Q))+X\E$TX(<3C3?3T$-5=1152G%E%,=IJCBBC89Y]QJO2WGHFJ\$>>9 +M9;H)EUQKOS5'XW#*%8?C<3#:V"-HNP')(W-(ZLB:;P)]048:NK90(-,'6DIX(?U`7!??OOU9^BCD$8:40$6'`"```TU$<88(#PQ!0A8!"6J +MJ)BV0*ZY+:"K+KM&B%0###J$048;"NF``[YAL,'&&W?H<(<<:4RK@*0,-^PP +M?`6^0)!!""G$T,-/-:BQA1)F^-U*,+1T0\@:8DP;HB$29915)C9E\LLP1P3F +M7.81C*9(\U%SUSDF7!-*<<+,4==AI%P-WWGV79PSBD?>2GQZEMQZ>[E%-%+*)2[E,N6D\@R[T +MZTO'GCK2'`GJ.-DUQ!GRV71*2`.>>KK=IWIQJU?##83R;I/EB^Z=N_?D/TRI +MI:UJRJFGH(XZ:JD-G=I0J@"LVE"K`.AJ6ZRSUIJ)+[D*5J]^)&=P@NNP%L'WUZU_Y$AC! +M#(8PA97OA3!\BN`.5#$%>6]CBL/A1R;D/+4];V1TVU`,=](3$`E%9=::2LM0 +M-,0F1L5W29.=ZHPGNN*AKHJG"QWQLC@\L''1=5[4FFEN-SXGFO&,L8'BZJ0( +MNRMN48Q@--UPDH>]\;RI;'*"7MI4LK:V\4D&=90;#;@'@D*A$0#@TUNC^G;( +M1OZG0%*B4A/%YB8XF0UMB[M3'_?T)AF`K#O<&50A'9E(1O'-D:B,S_G@I[Y. +M?2I4[@L1_N0'`/K9#W[Y@Y6L:.4!39`A@+L:8$V`%4P#%NM8R5I6L\KPK&A- +MJUH.B2"T)OBM-X1K7!Z4EP;IU4%X:5.$]?K(O?)E0C?X"V`J+-C!$E:&A:7R +MG9US&M3,2$D[6C*/F'S<)MU&GD^BYVPR><\A2RD^1L+SH%6!)!D-6CXZ+N^. +MS;MD]$BBR>IU!P8V:!Q+8""=CHRRD01=)$)'6I55IF]3KFQ?+(4R2U0YY);X +MTU]M^,=+-7P"F``0%@"(A1%BYE28"$SF`IG9P&=",%O3[%8UKWG!;W+S@B"< +M%P9)2$Y^F1.%`1N8.EO83I)Z-6H+/:-#*XG'Y^7S8_N\:$8=UYT9V``E'QUH +M$1,5/I%^]:YXS:M>]\K7OOKUKX`-K&`'2]C"&O:PB$VL8A?+V,8Z]K&0C:QD +M)TO9REKVLIC-K&8WR]G.>O:SH`VM:$=+VM*:]K2H3:UJ5\O:UKKVM;"-K6QG +$2UM(`0`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_mac-2.tar.Z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_mac-2.tar.Z.uu new file mode 100644 index 0000000..09761b9 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_mac-2.tar.Z.uu @@ -0,0 +1,19 @@ +begin 644 test_compat_mac-2.tar.Z +M'YV0+EX`&$BPH,&#"!,J7,BPH4.$,"+>J%$#!("(,&[8J'@1HPP:%C&*%`DB +M1@R*-&[0J`$CQ@T0+4W:@`$`1(V'.'/JW,D30)TY=,+(Z4@G39N>"H&&,6,& +MZ<&1,$*.M.BTJM6K6+/V#.CB2YL\9-(,U4JV+$&,$SFBW2@UXL>V(VG$F%'R +M9(V4*UN^;/EQ94V:9@,+)O@SZ-"(18]J5=/&Q1LXR\F4D3/'19@O9L0")1@@`$$#`RTL;_X\^O3J8K[,*;/< +M#9F'RID[A_Y&.G478[Z4:0.'3A[NF@U4'``4C#>?>?>1\04;86P'0';4T;%> +M>V0PZ*!E&&:HX88412!U!A5%=**G$DDLPQ2## +M###04---)/:84&%"$64468PUA=5C+;[HXY),6L655WEDQT8936:(D0TTL+B6 +MBFYIZ:)<=)D48UXT\C73#']5R220A\&0&)%!-7;D5$E&IN:=>"Z$F6:R>0:: +M:*2AAIIJ`[$VD&L#P;:;;[55=EMNN_G!J'$##??0@``$-Q!R`,1''GWV57<= +MA!=V]UUX!I97WWDNI#?A&^[!ERJHK.:W7W__^18@``,6*)^JH;J@H(5T#$2J +MA.S!6F&#Q>;I[+/0[N1AE&E,&:U@5V:)(EM)OE7G8V+>):->-=Y8@PUI7HLA +MFT(JEE61CM&)I+KTUFOOO?CFJ^^^_/;K[[\`!RSPP`07;/#!"">L\,(,-^SP +MPQ!'+/'$%%=L\<489ZSQQAQW[/''((,$``` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_mac.c b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_mac.c new file mode 100644 index 0000000..5caa17f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_mac.c @@ -0,0 +1,214 @@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* The sample has some files in a directory with a very long name. */ +#define TESTPATH "abcdefghijklmnopqrstuvwxyz/" \ + "abcdefghijklmnopqrstuvwxyz/" \ + "abcdefghijklmnopqrstuvwxyz/" \ + "abcdefghijklmnopqrstuvwxyz/" \ + "abcdefghijklmnopqrstuvwxyz/" \ + "abcdefghijklmnopqrstuvwxyz/" \ + "abcdefghijklmnopqrstuvwxyz/" + +static void test_compat_mac_1(void); +static void test_compat_mac_2(void); + +/* + * Apple shipped an extended version of GNU tar with Mac OS X 10.5 + * and earlier. + */ +static void +test_compat_mac_1(void) +{ + char name[] = "test_compat_mac-1.tar.Z"; + struct archive_entry *ae; + struct archive *a; + const void *attr; + size_t attrSize; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_set_options(a, "mac-ext")); + extract_reference_file(name); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(TESTPATH, archive_entry_pathname(ae)); + assertEqualInt(1275688109, archive_entry_mtime(ae)); + assertEqualInt(95594, archive_entry_uid(ae)); + assertEqualString("kientzle", archive_entry_uname(ae)); + assertEqualInt(5000, archive_entry_gid(ae)); + assertEqualString("", archive_entry_gname(ae)); + assertEqualInt(040755, archive_entry_mode(ae)); + + attr = archive_entry_mac_metadata(ae, &attrSize); + assert(attr == NULL); + assertEqualInt(0, attrSize); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(TESTPATH "dir/", archive_entry_pathname(ae)); + assertEqualInt(1275687611, archive_entry_mtime(ae)); + assertEqualInt(95594, archive_entry_uid(ae)); + assertEqualString("kientzle", archive_entry_uname(ae)); + assertEqualInt(5000, archive_entry_gid(ae)); + assertEqualString("", archive_entry_gname(ae)); + assertEqualInt(040755, archive_entry_mode(ae)); + + attr = archive_entry_mac_metadata(ae, &attrSize); + assert(attr != NULL); + assertEqualInt(225, attrSize); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(TESTPATH "file", archive_entry_pathname(ae)); + assertEqualInt(1275687588, archive_entry_mtime(ae)); + assertEqualInt(95594, archive_entry_uid(ae)); + assertEqualString("kientzle", archive_entry_uname(ae)); + assertEqualInt(5000, archive_entry_gid(ae)); + assertEqualString("", archive_entry_gname(ae)); + assertEqualInt(0100644, archive_entry_mode(ae)); + + attr = archive_entry_mac_metadata(ae, &attrSize); + assert(attr != NULL); + assertEqualInt(225, attrSize); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("dir/", archive_entry_pathname(ae)); + assertEqualInt(1275688064, archive_entry_mtime(ae)); + assertEqualInt(95594, archive_entry_uid(ae)); + assertEqualString("kientzle", archive_entry_uname(ae)); + assertEqualInt(5000, archive_entry_gid(ae)); + assertEqualString("", archive_entry_gname(ae)); + assertEqualInt(040755, archive_entry_mode(ae)); + + attr = archive_entry_mac_metadata(ae, &attrSize); + assert(attr != NULL); + assertEqualInt(225, attrSize); + assertEqualMem("\x00\x05\x16\x07\x00\x02\x00\x00Mac OS X", attr, 16); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("file", archive_entry_pathname(ae)); + assertEqualInt(1275625860, archive_entry_mtime(ae)); + assertEqualInt(95594, archive_entry_uid(ae)); + assertEqualString("kientzle", archive_entry_uname(ae)); + assertEqualInt(5000, archive_entry_gid(ae)); + assertEqualString("", archive_entry_gname(ae)); + assertEqualInt(0100644, archive_entry_mode(ae)); + + attr = archive_entry_mac_metadata(ae, &attrSize); + assert(attr != NULL); + assertEqualInt(225, attrSize); + assertEqualMem("\x00\x05\x16\x07\x00\x02\x00\x00Mac OS X", attr, 16); + + /* Verify the end-of-archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify that the format detection worked. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_GNUTAR); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +/* + * Apple shipped a customized version of bsdtar starting with MacOS 10.6. + */ +static void +test_compat_mac_2(void) +{ + char name[] = "test_compat_mac-2.tar.Z"; + struct archive_entry *ae; + struct archive *a; + const void *attr; + size_t attrSize; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_set_options(a, "mac-ext")); + extract_reference_file(name); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("./", archive_entry_pathname(ae)); + assertEqualInt(1303628303, archive_entry_mtime(ae)); + assertEqualInt(501, archive_entry_uid(ae)); + assertEqualString("tim", archive_entry_uname(ae)); + assertEqualInt(20, archive_entry_gid(ae)); + assertEqualString("staff", archive_entry_gname(ae)); + assertEqualInt(040755, archive_entry_mode(ae)); + + attr = archive_entry_mac_metadata(ae, &attrSize); + assert(attr == NULL); + assertEqualInt(0, attrSize); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("./mydir/", archive_entry_pathname(ae)); + assertEqualInt(1303628303, archive_entry_mtime(ae)); + assertEqualInt(501, archive_entry_uid(ae)); + assertEqualString("tim", archive_entry_uname(ae)); + assertEqualInt(20, archive_entry_gid(ae)); + assertEqualString("staff", archive_entry_gname(ae)); + assertEqualInt(040755, archive_entry_mode(ae)); + + attr = archive_entry_mac_metadata(ae, &attrSize); + assert(attr != NULL); + assertEqualInt(267, attrSize); + assertEqualMem("\x00\x05\x16\x07\x00\x02\x00\x00Mac OS X", attr, 16); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("./myfile", archive_entry_pathname(ae)); + assertEqualInt(1303628303, archive_entry_mtime(ae)); + assertEqualInt(501, archive_entry_uid(ae)); + assertEqualString("tim", archive_entry_uname(ae)); + assertEqualInt(20, archive_entry_gid(ae)); + assertEqualString("staff", archive_entry_gname(ae)); + assertEqualInt(0100644, archive_entry_mode(ae)); + + attr = archive_entry_mac_metadata(ae, &attrSize); + assert(attr != NULL); + assertEqualInt(267, attrSize); + assertEqualMem("\x00\x05\x16\x07\x00\x02\x00\x00Mac OS X", attr, 16); + + /* Verify the end-of-archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify that the format detection worked. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_compat_mac) +{ + test_compat_mac_1(); + test_compat_mac_2(); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_perl_archive_tar.c b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_perl_archive_tar.c new file mode 100644 index 0000000..165a519 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_perl_archive_tar.c @@ -0,0 +1,66 @@ +/*- + * Copyright (c) 2016 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD"); + +/* + * Verify our ability to read sample files created by Perl module Archive::Tar + */ + +DEFINE_TEST(test_compat_perl_archive_tar) +{ + char name[] = "test_compat_perl_archive_tar.tar"; + struct archive_entry *ae; + struct archive *a; + int r; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + extract_reference_file(name); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, + 10240)); + + /* Read first entry. */ + assertEqualIntA(a, ARCHIVE_OK, r = archive_read_next_header(a, &ae)); + if (r != ARCHIVE_OK) { + archive_read_free(a); + return; + } + assertEqualString("file1", archive_entry_pathname(ae)); + assertEqualInt(1480603099, archive_entry_mtime(ae)); + assertEqualInt(1000, archive_entry_uid(ae)); + assertEqualString("john", archive_entry_uname(ae)); + assertEqualInt(1000, archive_entry_gid(ae)); + assertEqualString("john", archive_entry_gname(ae)); + assertEqualInt(0100644, archive_entry_mode(ae)); + + /* Verify that the format detection worked. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_perl_archive_tar.tar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_perl_archive_tar.tar.uu new file mode 100644 index 0000000..ca7bc2a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_perl_archive_tar.tar.uu @@ -0,0 +1,49 @@ +begin 644 test_compat_perl_archive_tar.tar +M9FEL93$````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````#`P,#8T-```,#`Q-S4P```P,#$W-3```"`@("`@("`@("`U +M`#$S,#(P,#,R-S,S`"`Q,3$R,P`@,``````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````!U= 0 && offset + bytes_read <= 131072) || + (offset >= 393216 && offset + bytes_read <= 393216+131072) || + (offset >= 786432 && offset + bytes_read <= 786432+32775)); + if (offset == 0 && bytes_read >= 1024*8) { + memset(data, 'a', sizeof(data)); + failure("First data block should be 8K bytes of 'a'"); + assertEqualMem(buff, data, sizeof(data)); + } else if (offset + bytes_read == 819207 && bytes_read >= 7) { + const char *last = buff; + last += bytes_read - 7; + memset(data, 'c', 7); + failure("Last seven bytes should be all 'c'"); + assertEqualMem(last, data, 7); + } + } + + /* Verify the end-of-archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify that the format detection worked. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +/* + * Verify our ability to read sample files created by Solaris pax for + * a sparse file which begin with hole. + */ +static void +test_compat_solaris_pax_sparse_2(void) +{ + char name[] = "test_compat_solaris_pax_sparse_2.pax.Z"; + struct archive_entry *ae; + struct archive *a; + int64_t offset, length; + const void *buff; + size_t bytes_read; + int r; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + extract_reference_file(name); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240)); + + /* Read first entry. */ + assertEqualIntA(a, ARCHIVE_OK, r = archive_read_next_header(a, &ae)); + if (r != ARCHIVE_OK) { + archive_read_free(a); + return; + } + assertEqualString("hole", archive_entry_pathname(ae)); + assertEqualInt(1310416789, archive_entry_mtime(ae)); + assertEqualInt(101, archive_entry_uid(ae)); + assertEqualString("cue", archive_entry_uname(ae)); + assertEqualInt(10, archive_entry_gid(ae)); + assertEqualString("staff", archive_entry_gname(ae)); + assertEqualInt(0100644, archive_entry_mode(ae)); + + /* Verify the sparse information. */ + failure("This sparse file should have two data blocks"); + assertEqualInt(2, archive_entry_sparse_reset(ae)); + assertEqualInt(ARCHIVE_OK, + archive_entry_sparse_next(ae, &offset, &length)); + assertEqualInt(393216, offset); + assertEqualInt(131072, length); + assertEqualInt(ARCHIVE_OK, + archive_entry_sparse_next(ae, &offset, &length)); + assertEqualInt(786432, offset); + assertEqualInt(32799, length); + while (ARCHIVE_OK == + archive_read_data_block(a, &buff, &bytes_read, &offset)) { + failure("The data blocks should not include the hole"); + assert((offset >= 393216 && offset + bytes_read <= 393216+131072) || + (offset >= 786432 && offset + bytes_read <= 786432+32799)); + if (offset + bytes_read == 819231 && bytes_read >= 31) { + char data[32]; + const char *last = buff; + last += bytes_read - 31; + memset(data, 'c', 31); + failure("Last 31 bytes should be all 'c'"); + assertEqualMem(last, data, 31); + } + } + + /* Verify the end-of-archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify that the format detection worked. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + +DEFINE_TEST(test_compat_solaris_pax_sparse) +{ + test_compat_solaris_pax_sparse_1(); + test_compat_solaris_pax_sparse_2(); +} + + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_solaris_pax_sparse_1.pax.Z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_solaris_pax_sparse_1.pax.Z.uu new file mode 100644 index 0000000..8ab27de --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_solaris_pax_sparse_1.pax.Z.uu @@ -0,0 +1,53 @@ +begin 644 test_compat_solaris_pax_sparse_1.pax.Z +M'YV0+EY`"8,'29DP9,K(F>,BAL,<+]"\85,&@,6+&#-JW,BQH\>/(&&(A&&# +M!@T`(V'$H%$#9P(^F+'GR +M)H4JDBIO\U>S7JVZ_6NVM.KSQVF +MO?OW\./+GT^_OOW[^//KW\^_O___``8HX(`$%FC@@0@FJ.""##;HX(,01BCA +MA!16:.&%&&:HX88<=NCAAR"&*.*())9HXHDHIJCBBBRVZ.*+,,8HXXPTUFCC +MC3CFJ...//;HXX]`!BGDD$06:>212":IY)),-NGDDU!&*>645%9IY9589JGE +MEEQVZ>678(8IYIADEFGFF6BFJ>:*Z[7IYIMPQBGGG'36:>>=>.:IYYY\]NGG +MGX`&*NB@A!9JZ*&()JKHHHPVZNBCD$8JZ:245FKII9AFJNFFG';JZ:>@ABKJ +MJ*26:NJIJ*:JZJJLMNKJJ[#&*NNLM-9JZZVXYJKKKKSVZNNOP`8K[+#$%FOL +ML<@FJ^RRS#;K[+/01BOMM-16:^VUV&:K[;;<=NOMM^"&*^ZXY)9K[KGHIJON +MNNRVZ^Z[\,8K[[STUFOOO?CFJ^^^_/;K[[\`!RSPP`07;/#!"">L\,(,-^SP +MPQ!'+/'$%%=L\<489ZSQQAQW[/''((L\\X\]^SSST`'+?301!=M]-%()ZWTTDPW[?334$M]MILM^WVVW#'+??<=-=M]]UXYZWW +MWGSW[???@`N^>:<=^[Y +MYZ"'+OKHI)=N^NFHIZ[ZZJRW[OKKL,O_/+,-^_\\]!'+_WTU%=O_?789Z_]]MQW[_WWX(BGK_[Z[+?O_OOPQR___/37;__]^.>O__[\]^___P`,H``'2,`"&O"`"$R@ +M`A?(P`8Z\($0C*`$)TC!"EKP@AC,H`8WR,$.>O"#(`RA"$=(PA*:\(0H3*$* +M5\C"%KKPA3",H0QG2,,:VO"&.,RA#G?(PQ[Z\(=`#*(0ATC$(AKQB$A,HA*7 +MR,0F.O&)4(RB%*=(Q2I:\8I8S*(6M\C%+GKQBV`,HQC'2,8RFO&,:$RC&M?( +MQC:Z\8UPC*,O.;X`RG.,=)SG*:\YSH3*^,RG/O?)SW[Z\Y\`#:A`!TK0@AKTH`A-J$(7RM"&.O2A +M$(VH1"=*T8I:]*(8S:A&-\K1CGKTHR`-J4A'2M*2FO2D*$VI2E?*TI:Z]*4P +MC:E,9TK3FMKTICC-J4YWRM.>^O2G0`VJ4(=*U*(:]:A(3:I2E\K4ICKUJ5"- +MJE2G2M6J6O6J6,VJ5K?*U:YZ]:M@#:M8QTK6LIKUK&A-JUK7RM:VNO6M<(VK +M7.=*U[K:]:YXS:M>]\K7OOKUKX`-K&`'2]C"&O:PB$VL8A?+V,8Z]K&0C:QD +M)TO9REKVLIC-K&8WR]G.>O:SH`VM:$=+VM*:]K2H3:UJ5\O:UKKVM;"-K6QG +M2]O:VO:VN,VM;G?+V][Z-I%B"*YPATOYT(VN=*=+ +MW>I:][K8S:YVM\O=[GKWN^`-KWC'2][RFO>\Z$VO>M?+WO:Z][WPC:]\YTO? +M^MKWOOC-KW[WR]_^^O>_``ZP@`=,X`(;^,`(3K""%\S@!COXP1".L(0G3.$* +M6_C"&,ZPAC?,X0Y[^,,@#K&(1TSB$IOXQ"A.L8I7S.(6N_C%,(ZQC&=,XQK; +M^,8XSK&.=\SC'OOXO[\-LI"'3.0B&_G(2$ZRDI?,Y"8[^_G+8`ZSF,=,YC*;^,ZSGO?,YS[[^<^`#K2@!TWH0AOZT(A.M*(7S>A&._K1D(ZTI"=-Z4I;^M*8 +MSK2F-\WI3GOZTZ`.M:A'3>I2F_K4J$ZUJE?-ZE:[^M6PCK6L9TWK6MOZUKC. +MM:YWS>M>^_K7P`ZVL(=-[&(;^]C(3K:RE\WL9CO[V=".MK2G3>UJ6_O:V,ZV +MMK?-[6Y[^]O@#K>XQTWNYVN_O=\(ZWO.=-[WK;^][XSK>^ +M]\WO?OO[WP`/N,`'3O""&_S@"$^XPA?.\(8[_.$0C[C$)T[QBEO\XAC/N,8W +MSO&.>_SC(`^YR$=.\I*;_.0H3[G*5\[REKO\Y3"/NI8S[K6M\[U +MKGO]ZV`/N]C'3O:RF_WL:$^[VM?.]K:[_>UPC[O^ +M^_WO@`^\X`=/^,(;_O"(3[SB%\_XQCO^\9"/O.0G3_G*6_[RF,^\YC?/^I7S_K6N_[UL(\]Z<=`^]J/0?9$`P`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_solaris_pax_sparse_2.pax.Z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_solaris_pax_sparse_2.pax.Z.uu new file mode 100644 index 0000000..5df385f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_solaris_pax_sparse_2.pax.Z.uu @@ -0,0 +1,53 @@ +begin 644 test_compat_solaris_pax_sparse_2.pax.Z +M'YV0+EY`"8,'29DP9,K(F>/B1@P;+]"\85,&@,6+&#-JW,BQH\>/(`'`&`G# +M!@T:(DG&H%$CI4H9+DF.C"$#!H`8#TO:J''#AHR6,T_>L(DGI-&C2),JW5AG +M#ITPG8$U>!H$C1@X9O7L&/+GDV[MNV+BZO>WAU2IDF4,E<"#0Y3 +MYER2,V[212":IY)),-NGDDU!&*>645%9IY9589JGE +MEEQVZ>678(8IYIADEFGFF6BFJ>::;+;IYIMPQBGGG'36:>>=>.:IYYY\]NGG +MGX`&*NB@A!9JZ*&()JKHHHPVZNBCD$8JZ:245FKII9AFJNFFG';JZ:>@ABKJ +MJ*26:NJIJ*:JZJJLMNKJJ[#&*NNLM-9JZZVXYJKKKKSVZNNOP`8K[+#$%FOL +ML<@FJ^RRS#;K[+/01BOMM-16:^VUV&:K[;;<=NOMM^"&*^ZXY)9K[KGHIJON +MNNRVZ^Z[\,8K[[STUFOOO?CFJ^^^_/;K[[\`!RSPP`07;/#!"">L\,(,-^SP +MPQ!'+/'$%%=L\<489ZSQQAQW[/''((L\\X\]^SSST`'+?301!=M]-%()ZWTTDPW[?334$M]MILM^WVVW#'+??<=-=M]]UXYZWW +MWGSW[???@`N^>:<=^[Y +MYZ"'+OKHI)=N^NFHIZ[ZZJRW[OKKL,O_/+,-^_\\]!'+_WTU%=O_?789Z_]]MQW[_WWX(BGK_[Z[+?O_OOPQR___/37;__]^.>O__[\]^___P`,H``'2,`"&O"`"$R@ +M`A?(P`8Z\($0C*`$)TC!"EKP@AC,H`8WR,$.>O"#(`RA"$=(PA*:\(0H3*$* +M5\C"%KKPA3",H0QG2,,:VO"&.,RA#G?(PQ[Z\(=`#*(0ATC$(AKQB$A,HA*7 +MR,0F.O&)4(RB%*=(Q2I:\8I8S*(6M\C%+GKQBV`,HQC'2,8RFO&,:$RC&M?( +MQC:Z\8UPC*,O.;X`RG.,=)SG*:\YSH3*^,RG/O?)SW[Z\Y\`#:A`!TK0@AKTH`A-J$(7RM"&.O2A +M$(VH1"=*T8I:]*(8S:A&-\K1CGKTHR`-J4A'2M*2FO2D*$VI2E?*TI:Z]*4P +MC:E,9TK3FMKTICC-J4YWRM.>^O2G0`VJ4(=JRC`8]:A(3:I2E\K4ICKUJ5"- +MJE2G2M6J6O6J6,VJ5K?*U:YZ]:M@#:M8QTK6LIKUK&A-JUK7RM:VNO6M<(VK +M7.=*U[K:]:YXS:M>]\K7OOKUKX`-K&`'2]C"&O:PB$VL8A?+V,8Z]K&0C:QD +M)TO9REKVLIC-K&8WR]G.>O:SH`VM:$=+VM*:]K2H3:UJ5\O:UKKVM;"-K6QG +M2]O:VO:VN,VM;G?+V][Z]K?`#:YPATM8HAKWN,A-KG*7R]SF6D0,T(VN=*=+ +MW>I:][K8S:YVM\O=[GKWN^`-KWC'2][RFO>\Z$VO>M?+WO:Z][WPC:]\YTO? +M^MKWOOC-KW[WR]_^^O>_``ZP@`=,X`(;^,`(3K""%\S@!COXP1".L(0G3.$* +M6_C"&,ZPAC?,X0Y[^,,@#K&(1TSB$IOXQ"A.L8I7S.(6N_C%,(ZQC&=,XQK; +M^,8XSK&.=\SC'OOXQT`.LI"'3.0B&_G(2$ZRDI?,Y"8[V+E0CK*4ITSE*EOY +MREC.LI:WS.4N>_G+8`ZSF,=,YC*;^,ZSGO?,YS[[^<^`#K2@!TWH0AOZT(A.M*(7S>A&._K1D(ZTI"=-Z4I;^M*8 +MSK2F-\WI3GOZTZ`.M:A'3>I2F_K4J$ZUJE?-ZE:[^M6PCK6L9TWK6MOZUKC. +MM:YWS>M>^_K7P`ZVL(=-[&(;^]C(3K:RE\WL9CO[V=".MK2G3>UJ6_O:V,ZV +MMK?-[6Y[^]O@#K>XQTWNYVN_O=\(ZWO.=-[WK;^][XSK>^ +M]\WO?OO[WP`/N,`'3O""&_S@"$^XPA?.\(8[_.$0C[C$)T[QBEO\XAC/N,8W +MSO&.>_SC(`^YR$=.\I*;_.0H3[G*5\[REKO\Y3"/NI8S[K6M\[U +MKGO]ZV`/N]C'3O:RF_WL:$^[VM?.]K:[_>UPC[O^ +M^_WO@`^\X`=/^,(;_O"(3[SB%\_XQCO^\9"/O.0G3_G*6_[RF,^\YC?/^I7S_K6NY[I8XB][&=/^]K;7O:O1Q4` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_solaris_tar_acl.c b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_solaris_tar_acl.c new file mode 100644 index 0000000..8159772 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_solaris_tar_acl.c @@ -0,0 +1,267 @@ +/*- + * Copyright (c) 2003-2009 Tim Kientzle + * Copyright (c) 2016 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * Verify reading entries with POSIX.1e and NFSv4 ACLs from archives created + * with Solaris tar. + * + * This should work on all systems, regardless of whether local filesystems + * support ACLs or not. + */ + +static struct archive_test_acl_t acls0[] = { + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_WRITE | + ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_USER, 71, "lp" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_USER, 666, "666" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_USER, 1000, "1000" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_MASK, -1, ""}, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_OTHER, -1, "" }, +}; + +static struct archive_test_acl_t acls1[] = { + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_USER, 2, "bin" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_GROUP, 3, "sys" }, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_MASK, -1, ""}, + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0, + ARCHIVE_ENTRY_ACL_OTHER, -1, "" }, +}; + +static struct archive_test_acl_t acls2[] = { + { ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_USER_OBJ, -1 ,"" }, + { ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_USER, 2, "bin" }, + { ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_GROUP, 3, "sys" }, + { ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_MASK, -1, ""}, + { ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, 0, + ARCHIVE_ENTRY_ACL_OTHER, -1, "" }, +}; + +static struct archive_test_acl_t acls3[] = { + { ARCHIVE_ENTRY_ACL_TYPE_DENY, + ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_APPEND_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_WRITE_ACL | + ARCHIVE_ENTRY_ACL_WRITE_OWNER | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_GROUP, 12, "daemon" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_APPEND_DATA | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_GROUP, 2, "bin" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_USER, 4, "adm" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_APPEND_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_WRITE_ACL | + ARCHIVE_ENTRY_ACL_WRITE_OWNER | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_USER_OBJ, 0, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_EVERYONE, 0, "" }, +}; + +static struct archive_test_acl_t acls4[] = { + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_APPEND_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_WRITE_ACL | + ARCHIVE_ENTRY_ACL_WRITE_OWNER | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE | + ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT | + ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT | + ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, + ARCHIVE_ENTRY_ACL_USER, 1100, "1100" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE | + ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT | + ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, + ARCHIVE_ENTRY_ACL_GROUP, 4, "adm" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_APPEND_DATA | + ARCHIVE_ENTRY_ACL_DELETE_CHILD | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_WRITE_ACL | + ARCHIVE_ENTRY_ACL_WRITE_OWNER | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_USER_OBJ, 0, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_EXECUTE | + ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, + ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE, + ARCHIVE_ENTRY_ACL_EVERYONE, 0, "" }, +}; + +DEFINE_TEST(test_compat_solaris_tar_acl) +{ + char name[] = "test_compat_solaris_tar_acl.tar"; + struct archive *a; + struct archive_entry *ae; + + /* Read archive file */ + assert(NULL != (a = archive_read_new())); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + extract_reference_file(name); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, + 10240)); + + /* First item has access ACLs */ + assertA(0 == archive_read_next_header(a, &ae)); + failure("One extended ACL should flag all ACLs to be returned."); + assertEqualInt(7, archive_entry_acl_reset(ae, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]), + ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0644); + failure("Basic ACLs should set mode to 0644, not %04o", + archive_entry_mode(ae)&0777); + assert((archive_entry_mode(ae) & 0777) == 0644); + + /* Second item has default and access ACLs */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualInt(6, archive_entry_acl_reset(ae, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEntryCompareAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]), + ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0750); + failure("Basic ACLs should set mode to 0750, not %04o", + archive_entry_mode(ae)&0777); + assert((archive_entry_mode(ae) & 0777) == 0750); + assertEqualInt(6, archive_entry_acl_reset(ae, + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)); + assertEntryCompareAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]), + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, 0750); + + /* Third item has NFS4 ACLs */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualInt(6, archive_entry_acl_reset(ae, + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEntryCompareAcls(ae, acls3, sizeof(acls3)/sizeof(acls3[0]), + ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0); + + /* Fourth item has NFS4 ACLs and inheritance flags */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_acl_reset(ae, + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEntryCompareAcls(ae, acls4, sizeof(acls4)/sizeof(acls0[4]), + ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0); + + /* Close the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_solaris_tar_acl.tar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_solaris_tar_acl.tar.uu new file mode 100644 index 0000000..028dd61 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_solaris_tar_acl.tar.uu @@ -0,0 +1,163 @@ +begin 644 test_compat_solaris_tar_acl.tar +M9FEL92UW:71H+7!O#HW,2QU"UA8VQS +M P +M,# P-C0T # P,#$W-3 ,# P,# P, P,# P,# P,# P, Q,3$W-#8P-#$U +M-P P,#$T,#

    "QU"QO=&AE"QD969A=6QT=7-E' M+2TM+2TM+2US.BTM+2TM+2TZ86QL;W' M+6%!4E=C0V]S.BTM+2TM+2TZ9&5N>3HQ,BQG +M6]N94 Z+2TM+2TM82U2+6,M+7,Z +M+2TM+2TM+3IA;&QO=P 4 +M +M "HUP@( -, ,S P,# P-0!U' M1&%!4E=C +M0V]S.BTM+2TM+2TZ86QL;W"TM+6$M4BUC+2US.BTM+2TM +M+2TZ86QL;W"TM+2TM+2TM+2TM.BTM+2TM+2TZ9&5N>3HW."QG3HW."QU'`M+6%!4E=C0V]S.BTM+2TM+2TZ86QL;W'`M+6%!4E=C +M+2US.BTM+2TM+2TZ86QL;W"TM+6$M4BUC+2US.BTM +M+2TM+2TZ86QL;W<*```````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````!D:7(Q+P`````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M,#`P,#"QU +M"QU"QM87-K.CIR+7@L;W1H97(Z.BUW+0H` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````!D:7(Q+P`````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M,#`P,#$T,B`P,#`P,#`P(#`P,#`P,#`@,#`P,#`P,#`P,#`@,3,P,3(S,34T +M-S8@,#`Q-#8R-B`U```````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````'5S=&%R`#`P&UC9"TS+C,N,B]D;V-S7V0O4D5!1$UF```````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````"`@(#0T-"``("`S-#'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX +M>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX +M>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX +M>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX +M>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX +M>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX +M>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX +M>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'@````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````'AM8V0M,RXS+C(O +M4D5!1$U%```````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````@ +M("`T-#0@`"`@,S0W,R``("`@("`S(``@("`@("`@(#4P,2`Q,#`T,34T-30S +M-2`@,3(R,#<`(#%X;6-D+3,N,RXR+V1O8W-?9"]214%$368````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +&```````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_uudecode.c b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_uudecode.c new file mode 100644 index 0000000..cfb17c8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_uudecode.c @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +static char archive_data[] = { +"begin 644 test_read_uu.Z\n" +"M'YV0+@`('$BPH,&#\"!,J7,BP(4(8$&_4J`$\"`,08$F%4O)AQ(\\2/(#7&@#%C\n" +"M!@T8-##.L`$\"QL@:-F(``%'#H/1A2\n" +"IHU\"0%9=*G4JUJM6K6+-JWO8,.*'4NVK-FS:-.J7O0Z44"4*D21$09M[(`<$FC1BD8]"DL5,& +MA)@Z;L@,=*%`012F1M.\<3/G!P@02>;,`?Q#P6$0*D"@H4,'CHX7+^YH=M'V +MK9RX<\NX4'L&1)HY(.B@J8OF39NZ:=<./O,FC9LSCA^S=0M7+ET09,K09?,& +MSFLW=%B8=C.&31TRMDN3>;/T^%$Z@MTH#Y,W]^.V;M:@IO,F]>K=GD'_;A-& +M8/3=1N?P?1R92GDY9>"HI0."NVG%3"E75%VJU77:8@3*$<88:Y2Q5AAT>'?8 +M9)5=]L(8;P3G`FUOG+$7AFV\`,<+G?46V@L'`D;B:1'2!X)]("PF1AMI\.=? +M&6Z@P=T895B76GDE?N9;&%6 +M'=@-9A=>>AG(G'/!C7=>6E.^<<=[(.KG!HYTF.E=9$&J5X8._:&GH!QYH*56 +ME66$`=UM_>4%PAU^8H=JGZ72B*J<9=SIXE%R<%H@"">(,0<9N)X`I1P=*MC& +M?YV:46<+9I1*1QWXD<%KL!+J=AA^1B[8(Z6#"L2?H)D.>2D(8\`AF*[G]?IK +MN8()"P>Q9QB+[)/02>4@M[;1X:`9VOY8K;6U)HGX8T"(;EWJDE$Q'>["*^]IG-2>7JK2+Q35N&7@D7+*9($SAFI+L30D"T$(/-&RQ"2L*(0AYO%$' +M".R%&I"J`RK+AIB0+1TTR0/-\8*L-2+%Z9.1+L@?PF37%5P;@_4)X7L#@O"& +M&>C1"G9D&"+GIQB<@F`%4H(599J^;:`F,'_D85V7&`;+)8>T<""%7:T[O/Q8 +MR4C6%?A1#9M75QB`MB8':H^JEFJH5];JL'QXGD<>'"T,-!QP:>#7L%JACMX> +M8::+VNBCJ-H6&WL.HR50K3J,ZT015TP!0@N2I7$&&FUM7ZG>?/O.;5SD@ASHT+#NV.DQDQ$(6L\!/-2`+R$`H-IB`G`%:=<%>X#P(K03>;PYC\!,< +M=):DNOPO@`,4U5J"4#5 +M'_R`8$#2HISI%'""$6H/A,)"H0KI$#T7Z;!!8'1!PK;3'.I`S`5MH(%R[/A! +M_`AR#"_#'AQ_Y$0HZHEW??J3PY0S&#:$:E)E"$X<0\6>?`W/01$,VQ_+$$C; +M++*#VG,!&EQ@&P4D`'N,RY:^4#-).3(2A#%*81I6V)>X/!BE1WV,C*^`A107Q$!LV3)@\?*VM^)M$U=/BU?"'*/-=9GK +M#=X$)\K$N2MR\FU7VV17>=X%M3:PTR[K@E`\@19.XM4S2>`S9T#YPT]U^C-L +MX0J-"V8``C31!37^>0-=Y*"E,MPAH;OJS*="A:1.W:$U&PP;K;Z`'U--=#M" +M"LT76%4CT&E._/.2EM*AIZ>YJ<4Y:>6DDG#]DB37!`# +M3VF2%#OFA/&(NR*J4%5%4WV!(`A02,P_5THI4$T4.&6HH9V*)X(^.=!&,:7+ +M%\J:AR8"RCT2(Q?*%#/6N/(T7PYZF)W.JE1DAG$.1X.F]B:SG,A%E"XG2"5@ +MY2#8&#'PK<#DCK2*XR`3S@=3O/$KL]3"//E\9#K5H92B8/,\&98V1G6`@W[D +MH*]IAM0M(_VG/EU0`^6T@8%E$$UO=Y::;GZDL$Q-JU-#N9SE/3,,8K`:Y%:3 +M)._H)THH>Y!?70NA.2C'-LUYSGMT=+D6D(=9MI%64VW8G^@"RCMT"PYER?5. +MXJ+3#HCC3J7XDJ>ZL,<-=8`8E,)@/HQ&]S=(J0MRF6N;XIT`M<)*8QE^Q\9: +M/@G`;1"#@Q):KV;A!SGB=B@.1=5#38!'X +M#0U-U.P<$0LM'I$K0UMI,-C10#0:J5>&MDX(L"A@"M#]/!D\JYK1A&VA]`N>9N +M%2L86O75,(RJBJBK-5X7WY.6TO8Q;$=P0A6*NQ;G\@<%X$74>Q*]:.*@"HP/ +M>XUWV3*;W80'!)FNU794-8?,K8ZU94M!;B)CM.R"+`=BTU=>F(M.1X,`TH<2 +M+ZJ",`0FS$'5$@3!$YYHN!LPNHV:BF!DH/"$*20!"V^$BAQ6#0)F.QO:F<-# +M8QU$OML$F7G4MO:S]=:PM+9`+6F@%'/U2>TI6$$*&`G"%(:0A"305S#A;O:X +MJ:,O.IS;3^J6%KN#+03;("5X]46!&+37`AQ!)Z-KB=B;R]#PO&S)#<`.6Q*F +M\(0W%69'P%*@SAK\1`;SA1D$2F!9NOD# +M-%F+K&X9CXP6D@`%9`\)-2A@.<-<\ZZ`,7=4(@B.&5"FKR9&"C^*86Y9T_UK +M:E.:N$*8`A%XA11AT4K9O/HM?LH@+$=3^P8MT,(PC1X:M#<+-A8<#_D[*:"_GCIX?^Q4'AI. +M^'LZUE%>RL;E;M1ZZ6>O7L8N1.J$R_*"XZBM"D +MU5VU5VWZ!FU%@2OY=FT#IFV3U6TVYW;!)@)8QT!X5UM-E&TAIAPGA7?[\RA* +MDT+.4A<'B!25)S8\LD(R)"%;%T:J,356MXOB%VSD9WYL08OJ!P+L)XS8IP!.\`:[I&6` +M4CSRQT8FPF?/@A_1\T]Y`C(@\R2K$09:XDF6U5)M\(0!%R/6Q#A.]B*KX48@ +M@V6\HT;>L1BRM1](9ALMD"T^%E]I$!`;DQTWIR!YX1K],08\HAAJ%C:85XVA +M`C*)HCV3`D7E(8HS.&O2PG)8V'[.)RB:)53;Y6CR<1B8UTFA\H*]LRT@!C(M +M.%W?-C4:YAU$!5U.,RI=19.G@U'E&"OV)3]+LR#[0RM+(SBA$I./D5[YX7"4 +MTH[]Y48)UD;8T1QA)"AR)I17D`9KD`;R-#S1X1VM\5&1?QURH0Q[,@W=1E0<+&1E)<`((1AD]LD*T +M5AYH0R-ZH"37@7>>M@90PD5W-1CMF`1\0S_XXP8GT"3RA'HN1;,>'..E@+?Q1]W,!B; +M65%I!25UPF!N`#9)<#^FB9O9]5V766+3H9D\AP=&XIEO%BHX@I.E>9M+D5W> +ML9NC$AR[:8^RJ1R8&9S4"6K!19&/*51G,#Q&X6)J@762!XBLY@)!151V9>Y8QL-$D<&!W`TAGV/@2-:0BQN +M,&/Q,2IMP!Z. +MN"N4DI*01UP692"04QYR1F=3,Q@\`C8GVE5$LJ1SUJ)L,)=UR4\'FI`_YF6? +MYTDM4*,R]W2`4D1_Z8YU\09BH`:?UP)&D0=.8WS\!)2;UT4X6F*1HR/K\8G# +ME*C;!2M14Z5P@"/]\2U6U8[G1((#HBC>>#\U@AHB``2TTD07>7U_BGE">:IG +MQ#<@0U29T2JR%FV0$E5#"IG*PARSTZ,E1G]$E2I=*F$-0XY&:I#^H8^O03=L +M=!?V(AO3]AAJNCB4]"2(Q2!I!9UF=C6/XH5,^8ZGXT:(I3!W%3$3\QB_^D!U +M@Z3$LE2MAR1Y8%YOT`)Y(P*<=3]@Q`*L2@=CL$C&!UUX%:!F61_G8:O7"E:) +MT49+)C)G,)'9>CS+`1U+%6!4LH*I%#FB6*PVB:N<&CFI2`80HJU6\QF;Q1B]*S`0URFLJ-AVBGH))3Z(UW>$1"K`YRM\AY/ +MDDMJH7F!I++#ZA\J=A^EDF+W0U=H02P/=1A0NUTZ=JV[4K/TDI+):C#E8;+< +M2@>5&9W@JE_>$3D*NU-#28$LV'E'I:(@^I2!0Q=N`(4^UJZSXR^/L40$ +MD2CFXE4QZI*@EC!*0I>T0T%E<18W&%J:,BBC5Y9^@2409!B(`2"UTA@N0B86 +MHAEWP!FR.R2C(0>EP9+GT1H*P[Y,$S=F@S97W"EM4SIP4S)H13>$P4"96!KV +MU#=^Q;ZC,SB%KZF9!NH-"YR_3RT9-B,)$N3;4NX5)ANR$M),DV_9*[" +M1$P*8$R&I4S,Y$S-LT!1Q5S??$F+>TUMD$T`Q4UR,%#6.4\&=1[/C$^_@DZT +MO$YADT_O9-L%%6B[?1["+1CI9"S_-,EH^TT$A=O&C5#\-SD+M=S`#5KE2Q=G +M]:5^IC<;U5$?5=U*3%(Z>5(L\[*1,513"U0KI:;N[5EQ5O;VTRJY<.M)9*P=8^TQ=II7=ZZ-=S#%8C"E8RX +M(N0+!N#/LZ,"G80""5U;5B#5]3G%D9M=*I+8R\/CA11D8*_HI2H4+HV<&5^! +M=6]EJRKWE5_(03N8]U\8.V`JY^4(%H,GKMA?G2X0IL\4]I#8=V'-I&&RP3=[ +M[&8A5J(KZX560VQ1"Z2[\F*)@QHR5N0U=F,Y9N>KH0`\AK(_EDP(OKJ9_-N- +M@V30NF1J-9+5EL%L49Q5=F59YN73F(H.\F4/+68'4F:8B69JQF9VBAQPQJ9D +M:F=[F6?DZ'E]1ER`YL/^YT6B8FA>IVC'9FNXAN:H\G4X.(K;J6GGUVG@`9D[ +MF(REAA0(Q7MVV&J(@QJP)I:T!KI`/C7?+FF[UFM=%VQ%6&S'-HG!)FX&*&T) +M.&Z3Z\<3'7@%SX3\9F[HEHX#%S;N!F]?-6_U1N<)#VT1[V\3'X4"QX5A4W`/ +MPT;Z=&L+=P85]W#W,RH2-Q`M?W%V:(@>!W(@('(D9W(H1V!A5(:N4QR,3"4Q +MQR`T9W.CDG-M49RM"D%V*(8E"/3[JHH=D +MM\6/&!F`"%QLY_"+&'=S1_"JA'?$LG=]]W=J'QF#5W@Z=GB)Y_831'E\#P*1 +M"(;P5Q<.N7DK)NV@IRHZ2GJI2-X_C.VKIV1+@U_.T_]X$NZ_PDB']`\Z*?G*%TF*`N6`97PJ4RV+F$468H<(.= +MAFFJRX/^_H,`*X34)N`=(7P';J#?OBDW(`_@B#R.%VPNGA7"0EJ(`88-+W3^ +MJEBP@7ID2.GD'J[W=-:0U'%#6Z_JS2&Y]>\0#;?+0V)G[)D="Q@VSM[:&43Y +M3@DA!HYS\Q(1(0HVC*CML<#($/@FD0*H1)Q*^%&Q9&.W2,5B($4=311ID%+$ +M7%A.XT-^6X05W0979."`S"Q"?5R/%P6W7#3[M"#@@'V_*!CQOF$$46P?[DL_ +MND\/=$'QXXR@41CA=:BK\%VCSP-"MA%#NB3?2#*4BG$4*C#5.0IYM44=P;9Q +M!:+B$=VB1X_!/.&C(Z*/-EF2J1=\J7F,"H(T'8Z%BPH8KXI\T1F(5"LD$F"S +M2/1/L6DDC[(&W5)WR&^S2R01PL-VDN`?#.)DR*(E6;L8:!?D&(KB3A\K;=2H +MG!0RI)@E)'53HU2(/Z%DM8S284!*FVK6(`="Z)2:850B/52)?%DEK*25HAM7 +MBEZ/X2M1$K'4XXQ7XSI1:JD4$A>XY)3>%.NR2]JOSN@E/-.7_E1@&DRY)!!V +M,]LP,M(`@W)0CBG=1:8I4=C2%D>;3IO).T0W[`2:W(!H(DT>S#N1.=64C>I" +M:W(@KRG)O:\C4IL^AT+,+N)P5/2FW[0JA!-_,!\,Y3AI.>7$G"XB4O!6F`D@ +M5J?K=+BRTU#B3@EQG'TGI!">QN#+VT_E*3;M!_148M33<$ILE"3=P2?YA+HP +MA)TJ-8-!>^DGM+*;`%2M$%"7)--%"P05:!94H.(;^!#:U:MTQ]HJ%-=9#@+1 +M(/:.P>"A3@J(DH4C"I7\*7`XM8J@'$1(^0%&R8\991=LE'C@:#IJ<0BK'U6L +MH%VO*E)'*G(DJ4`C!YT4E/)94ZI*K84K97R*QY9JAK-+QWPI;!4YQE2+\E1G +MRCNDJ9WB%G_?YH%3J$%.4<4ZI4;PE,R:4'JC3P&*3!BH!E6A.E2)2K80"T85 +M51S%H[H:D4H<^1=*ATAG_B*.%JUE"DLB5P[*/Z(K#.;*A!1[?E6`< +M=/-J<;&Y?!4<^]6_"EA0)7,LG(AAL+A1@C,5MZJF?)6P@E'<2$2*6("M-GZ4 +M]#(7D$F?TUAMJR*9C*EU<[I*KA)9Q@\XE"S[V&-2%@A86?1'^-G"F&47.N]L*O>,9^Z"M)*#85I:2TQR>:TZ@?4*E#DL6H1 +MI:OE&K9*E^I:<.MKS>2-8H-"<5`T?482)>&W&B[(M3$"-;%%V`:[()Y<8QV%0HU\Q=D +M1^Y2DPC,=P4;X(49A!?Q@G''*WD%&N859-X8;>A*UF)Z!8?J91PHQ9GC=]+A +MM%$*[Q54@F7XHB15:;N4$JD"'T2,BX`1V`(?-2O>)2`0"OWB7?;+.VX8"('" +M^)>%^%\;X@UTB`_A&D1$G/`K!PQ!)#`6,2Y@A`.S$5I2@L%"QQ+',)CBTF`S +MHD9T,..D-$+8?")A=\B$A8ER61E4V`M@86HB3+RP./8N-06=F!(S[)+P"1M6 +MV%2ETX@TSR%!14&`]GV&6)Z#:V0IB14^)C:UG!B#JQ$$SA<.P:-CQ=2&).MM +M?3&OP0;"V&HR165LBPVRDY$RV-@Q08+@(HY1##IV,S7&.ZED"4./_2,/ +M@R_\&"`C$&]@D#D=0Z9GADSS*I""94"ZB(U1QYP;U#P6>1"3(3.BN<9`3!19 +M?^8,!)`RFB$S2EG=/&40,941&:+1RI!&5!$;1`:[O3I9B)ER&9KY:[U,;P*S +MLT$/AQG;8#IN8U1FLKE1-YA9[/EK"84L2;/!8,.J&>+`9HNC1VPSMXF8)D?E +MZ!V8XS9QCD&&SO!D]UIGYR$OJ8YWAHIBI#P+5EHMK.V.\\C/.*=\LG92,*`- +M-$%1T*0'];`>V&.A<0\6]]#"QX09'Y6+HH4-B\8^W`?\V&B8B?Y,AX]&3?P' +M2<,B!02E(9#4MLQ8VNQX:6/A=5V0F?8\:AH)P6D_1J^5D.;1TU:(57,AWW.H +MC2P5AS* +MR.XD:SGK*:&U.;+6Y"=^R".AC8]`MD`YU]H`(;%K7P.OQ<_WR=<@B3F3)%:/ +M8R50P;8Q"=LF887L*90P.<;6O1S;ZABA@$2RN9(5&DMF22VY)5"2;,@HSK9# +M/YN2"*'%Y)@DD\BQ3+A78U(@XO.IM#:0\=H8AVS38L1-NHT3Z@8%9YMO,S(/ +MI9TX3<$01G_G0;F*"F6-[A,TVMP62AOU9R*(C,;1C2$X_XGFI"C>S5AI%`5)H+>4`N%R"E&);SD%OMV4$*>F^)M[.X5:2[]-+4MJXC1*:2MJ +MZV;`O0I7"(NNRJCH1*9BP:V*!L"5X[!40 +MMU)&G(HA+`@RQ2F,%><]&LN+HQ61Q3OX4BI1XQHB<S2R[%K,Y1BV5E&:^3LV*&>07Q^1EI4N]-S[0"0M@LV`[#1 +M)*%;`S*UE[C+?SIH_YT[5*$/UQUQ:7>GAMR50%;#,N8="*AWH?#>B55:N.]T +M36GH07-5V!`;*V!L?M8.)$`*:`25OB44_1HEY8*4=0^Q'D`G!`BE$+YI@%4H +MX]$;>U/Q&.MDE7@*,!!V5A!@\N9/PEEY,P_B[`;*(/,<#LTK1#00$>6\D5-R +M3L[(\'E(A^4(O9=#]&3.T0M4:T'I[9Q80X.<7A@B.E%/`]JB#HA$/J#6FWTC +MT$)]O1,8]E(@'R)[?\\%"J+(F@,=T=^[.WE'[N4\NE?]0,#=,SR(I^P%'[]W +M6'M@%1M\Y:VDHL/$)RT6WQN,D8ZOJZH>5B+Y7$_ENYRSQZ]005BD>^2JYY.@ +MW#/TK5)%A7R"S>FK139Q]<$!711A7Q_7"X.E)),D<3\F)!B[7@+R%%2OQL8-JY?)M%^W,_[A:[XP8'&'Y70 +MD>9/NR0;$Q07X6;N[I_,`^M#@2W"EC]7Q`:0H+5"'$[ +M35D`PT;S^WCH:`&.5@>(1"#@%KJL$_`+_3T,2/RDWAO9@")0#377-O1 +MZ43:DH_,E\84\*AK1Q +MNQ1#6X@,E=(R[(]WRQGB'6@84:7A=KE*66DKT4-L."&R3%@*A=U0HGS#M-06 +MQ>%;&JMQR1S6)<2'EZKJ@RH8[E`PG0["1#+D(6*BAXJ),>&9Q[0/G<..4Y-J +M*S,%Q`QUVPBBHCN(IT.3;F#AT:>)C6(KDR29*Q)VH'SUB#G5/ +M0A%FQ:<%0I^.XGV"%&IW?S9%)F6P'@,-DXJA9#0>#'L(1[,BA.**%.KD?<5: +MPOXV%%DLI!?%.N;B1JF+,NHT\JG*L!JWK=YPC0W#4$F,V+BHAN'Q +M$+VY<5*1HDI5KF;7;]14G*I,?:KBB#/7PJ@2;`WF5"$1YJ@IG*//R0ZLL4M1 +M1^N(HN*D=A0904SU$BF_%1Y-[].ZO%3K6)$U986UX)>S#9*#`CZJ!?D(MWYO +MR+B/*+$GG@;^"*CN)(`400)28A#(/FD@Y^A#39#UZKPPR&1([OS5T@!8`DM" +M%JRG:'VQHU=Q7!@DV*!D34!)FD(:(3-_5Q[ +ME7EPRL/@*4V73PJ5JFM46I-2F3XM2.R"<1[3=K7*>488=%=BD)>R,FS0RLRP +M&30G:8B%RRNQ.*_;`+UP@[.$QJ00VW9`;_IAG0GOMB44)J6 +MZ0N`UDOWI2U-%;?$G-\2081+_-6I&&;_NA!`)EVNRP'6+@L8Q8Q?\](H;&/8 +M$C#QY5#2EQ0LX](%?QDZZ#$'LQ8>K$Z\6RPQPK9$PJ0#7V)A6HL4=B;2A`MK +MES",8LJPV@&16(0-%4@YK%`TXQ[&58-GR9P4)W-\MQ?I_(>I8[*R@^&VMJI'?VT-PV,I6?\N!RQ%."PC6$ACRS +M!T-CG@DEHH&BZ"G2SI'[8GRPEIWE.HF31H2#*C2A=5*54J$(TH3CG]6N&9J2S7<&PG!NO3#N=(SO4Q+'#KM8>?*4$`L +MQN+B?G(R/4HS3L`TTQNW63:5CL._TA3&4=/N(N10"Y'#IJ?GR"6AI"N;:G2M +M75=!69SZ%G(Z7`3J.;URH%3+L5,X9SK@:63"+EQXW=;3LIKFRLMYV:>"&L[Y +M4_ERB>J+K5X+^(6@YCG^K)D*9&JJ@@J<.!76 +M23X*UXZ@S+^\=53F3N@ZHNI.C:J70:JC0JFV)=%K[/H"LG,S4O55J\,[[79CM:^:56XW[O2?N>,T;%5"I:Z7?D=<,1+*YJO$NM_Y&CL4\`CKD4RT!O#@/3\ORX0N\:/T-I'URR+`8&M9 +M%['%RZSR9K-*0,_J\:9V91UY:#8RE%:4=UH9CFM5K3&/XIQMC`-;#Q'.TWFU +MM>>I'#>[6P<#S/&MR`3I!5>=P_2>HW&]@,@U`YHA."N'Y"S6`X'0]\U'DG47MEKHH6O +M5@VF6M3M&7.DB25^*!;3PFYLQV)A[(M- +MVC'VL4+M\FIC*1".C;'?C\>*/P_T8\N?8BU!Z:_(CF7V1P*3[$"6?TW6;S]9 +M_'=ITNK+KK(O^,H&0&(35J,VQ//:H;5J4R&,=X4\2@0;*UT%KN0VNZ:>8/7+1"4!,1 +MP>(1:9%@***T]\+2UL[7W9$!6N[^7\.[U&H3+MB\O^"%1;45UGG?/@[;:M-@ +MAFV#T:BH3E6S!AIPK3;2M=Z(U^Y!@=`'?2'5YAGKB-@B7'AT;`_AYU&V2K?9 +M/MM^X8\`TC.QM@7)$F;;$G4'@Z_FX800:P:HW_+SB4+`:PG6>B1500Y/A_*=KR5W'79LQO5/ +MWN'*C8>`+3$17LLR<_6A?N"'-Q8C# +MD%4O0MK4=,NN;LJ[H1A"^":IZW9!(L%\*K8!ZT[SW)2!KX;7'8C/_"6.W:Q+ +MS6MB\;XY:?>>O>=Z5^TZQ1O2'[^1NVZ^ +M57&8EQ/#6S`B5'CHBHH7/QOOH>1X.Q3D]8^3ES"M#LN+HI!OBX*+*Z3SRJC/ +M>QI%;UXLO8_A]`(IO[AZ,TA@W">O=XIW"LIQ&)-68GP,5@KW:BG=6WYYKZJ8 +MC!98IZO?S%A\[X>:,NG6Z):+1CKU?.]4]+6+T]=/65]!1:BR+VP\';+Q#=#& +M[\O1PN]N'+^]\5+Y0N#(@I>Z:&"_M.TXPE]3]3U2U:KJV=#10A9UWULI9A6R +ML,'_ESNR@;](@$ES3$_#:U@HU6$NJ1Z=58_(6=+*P\1':U6!>Y;90I/M_/>( +MJS'^R2/UH,KI[A2\+U:P9S*00;P&$RP*"0-UNO]ET\WK*>D@T-D +M#[8X/SAC+>X460N)\%IPD2$+"E:V.]KKUPD.+21HME3R&D^AL85I4$@U;2;?DKEO,C=B2Z?$-$J-87R +MD)5V2@RYD(C3GK$QP)@U"..(38R!Y31.E-LR6RW)8+HEH/+V(IC9D:.R>5"-I?^*QT','89 +M(MPQC(N7*D*!S>-["<%RQ([8E\?4K_!CA'(O!^8'&\@B#&%V"81\PJY\PVS( +M+4QB0F2*&<( +M=$EY7_2+/]F4"]E3[IK_^FLF8JK\R$SM54X79M/5:ZNN[#1*/043RQ.8+,]- +M4H8S[B:IR9MMV2_SS;@,RP!GJ[/+]KMPTB5=)BVZ!E]6G$,#,*>-7$',(*?[89R!#W)V$>!Y.:LVYXQ%FZET=A$BWCKG5.S\^CQH"''0\U,@ +MU<^?AC^5,Y(AV$?-/`/0]-S4IE$!;<],Y#VK2RD2GWN^`ZW/^O4^3U"$OY\5 +M/K@V:WG45:NU`B=[Z*G:'FHHJ=:1C/GU>9- +MN6@8Q]%+6D +MQD^Y4\O:G!-0V3DD2+1V<8@8>XZUEE#A5EI&H.-0R2O=FD3UK5E4BHZXEE&1 +M:X\.[X"4@1CIF@)0Z;!K*49YEZ_]&/':2@7JU&NB#DQEZNQK>)*J@Z>Q.C<5 +MMJ=3#6R"6L'V4^$Z"MM0Q:OY.@\;F!&QC1DU"$=3L:T94)6RDP=`=22%R<67 +M7%4?V[2C8VQ5R0_WQK%9"F#5EG7A/1I!6VEP5O5O4Y9:!;.5!FV5'5BSN3NH +M1JV0L[D:/!L?][,Q#V15]O(>`%9$VV!56`5K=8?WAO"`;P]>)E9>26V450(' +MMEEMK`;6IO%P5B0/U]:$@%90B&C5"9)6%0K"H=PH'&:;Q8&V94>ME2K(M@4; +M*-S;1EOQ/+?5W*9;N1QV6V]E].1MP!7.P;=5)_<7T'%<57!#EIM%]11N5X]S +M574D;D=6'7*R[5DJD'I5P@%:5M[:TXBH5YF;WK&YC5>=&XUE]Q`>Z-7>AX+I9?B2;[-9Z4#ZU&ZIPNPT)/UR!Q;N%#;Z; +MZP"\C3Z>6A!7Q-D%1%P29\0M;TA<\:9J+7&LEJLEO458U)OF9;V%("5(]L;# +MI8$`"$C58B56CR#3UE@Q(`R/).@-(A$32/9C@:!O.]8&LKX)!.T;1?B^H3]X +M@/HSOQT&@)A/@LC%6$X6\0!E11Q25KDC:GP5_4\`!P`!/`2<&QC.R4"4("A( +M\8R"9%8#EX6<69B@B<$(NF1A`YM5#%YP')#AI@R^(0LY'/>48O5P7$T^ +MZ&F9/J#60#AJ45@*H?)F?3!O!N$Q\KQU6*K"J^5^L$&R%J^FU-U:=-`59R%E +M<9U"K\7%57I?G"#$CG!VR`*R1=:@<1/1J-`(05N/T+05D`@*<%PEM'EA0M97 +MX8/'>4+B5NOQB7%/?]P]%\B5.806=&\57,I0FN3)_4?>"<-EC3U<0'5TEQ3Z'9%1$\91)],TA=$?A./?`3%W$24@T)5Q= +MWL%R0B`^)UQ7?[B>P',!HCR7J&R(9M=A@';Q)_KUDC*)UT%U"U&0MUY\!CM=0C&4;76H=^N25W +M(ER'3KQ?CEC\5=?17T."_55<42;65ZS2UU5'?QV/7;ND016^DQZ7H469A^=+9G=?E1L_4>>7;HB-AT& +MA9TB-OQ)8J8=OH)0Z"LLF&H'A+!V$Q+,]-K5<;&=\]Q((?947#'92AAQ5T3EH;I2%'8:>0CV2Q`$J\8W?4'TUV1Y+-, +MA74!=K1$7L7Y0UW[YU5%]_=1_3= +MVH(<\';X73,XMV`2:X"=Y-_E2898@-98 +MA820E:,AX55*0E*%IU=E(!E>J;'AT5L=7BKVX;4NK=BI%'&D2B6>+%;P%0:P +M$B[&XF%YO-CP\N+I2L4#KX1D/"_?X9"'XXDURQB/MY&]!S_>LG1#[89:8WA0 +MC45+1Q[ZDN192\$&MI0?=&/_P9,'CIT']0N5UR#D+^;8N:3EJ4L"#)O0CE5, +M<`(\MB+(8]=2`[/!/##G'3[&S:1YFL*:!S#]8T[".0?G'4P&V9R7D($-^\N= +MM\(X9'I>B!"1?7D3&?P!Z%UD@D+2N)$9>B1;HD?$B&2-'DGVZ)EDD1Y*]C)= +M3GY02R8]10::'K#7?LUD>="G9Y,Q%T'3"3`T?65M$W]PZB5-,(ZJ]P:43439 +M&\`[ZB2P7A^CE,UZ5EOXLCLOYNU]#>!>V2#N"6;% +MS-N`[CUVB-FZIT$IN5#;/9\:307'RXF<;'(W!\ +MD%)O1CV!?!J-R)>&E7RNP\D'"\YGX5,TH=*43]%9W3"=J4\R'[GC/MTT-Q]W +M1C]Y9TU?`P4^$35-8-#'0PQ]0<0`9?2Q9U&-TK=`19$IWP,5]5-;GW:6]NQ\7U^(%O:94'6-(9%"-6A.%-H'RL!0GQ#;IS%99&]? +MD*>AM2<'>`GXKF1G9]$<)H(T5A32``X@?D +MS6C1A*OF^,$V7U3[1?H]:9;?CT9'17Z;WRG7^1UIIQ_H=TIJ?@+%Y&="]FAE +ME'.CI&DW?H.5=E%@:824EF;YQ7Z*U.SG_=5^[`X(6*T!&"/@0C5(;6L(4@IHZ%!4"U^X-JXY.AS& +MN<8MU(`WX*63`ZX8Q0J\IE)].MA42Z4IR!+XVHY!!*8ZO9)-59?U$\I?DN$A +M-8$^U<$&5.4Z4F!1104".TD5%DCLG!E.E<76!68G8.#&]NP<,JO;&3BUC&QC +M9*%ALGV%@Z"^$P?>(2Q;3^A6C3MY(,U&:MAL?6!@)>_L;'>5S@B*A1B%(+CS +M5_D[B:"T8+095I*;)_B]>80*S\PX_8B$:2'X!F9];5M;T:`):FVC55*8`(6" +M"AS!40K2.2I/*NCRW!QI6VKU"FH<9^%LM?/85BG'SW,+#CW!!]Y6<_2"PE7? +M%@P2!D]/X&;!#6YV5C)(9RV#O:57:`*!A:256#C")99I!]I##H`^P\>");Q]6EB0+&>\#7'(6V)X:@$C0IQBR!!";XWA0Z@0 +M$)FA%\58ZFTE8B>8"18,XZ$Y9M)&$KD6!F(^M:!L(2, +MUH'Y$A(_\1L*,A-ZC'?933C_W)8V2)1%!_J$_(\/(A1B60*046C`*2"3I258 +M63:%9E9E&<&I5U;AT;%R\)8Y37"3FW(96<6" +M:&&@!0(TEZ6;.>@6PG#VA^W(B20X1Q`H8A?B<*;(P`5^ +M*085ADK<&=3$16]/7&0HQ6EL09@A.++%D2-^4&=XHQV+AE!_1AIN +MEU;< +M*Y22!(?VVW`(D]A"CEQ-PBX>!3-(<`US`4'3J,TZ$F9W!9ATW))Y<= +MBG+;X>P"<55#1!HJYY6$AQ7>3T;2A4.8YNZ1'MIRZR')U1[JG +M=3V(]B5ODH1(B,!).5=UB43+@3KG(&9V[URWZ1)M)_/<.@>>G%TW8C[7;NYS +M/!&XTB("-G&7UC)WR8@$'8UH<=B($"*.>,\M=%"10\=3!EYTRN#%H$QT0^+A +M):%@=(B#1J'385>0TN(@KEI19%B>&04E-CQ +M15^B``:9B(F8Y&"T)^YT3\KLE2;:0D%=8S3480>[E_G2>_T&21V=>2=J1GGB +M\?5SRB7GT%3G?-4G5IV@N*<0BM27H0C;<76OT?8%UG5?00E9AYF8=5@#;V2I +M5(KF"%N7?F6*EY_[E20@1V*$_&77-4=X':@&VYF*20*JF+GX82`+JPB`Y2;&#'XE.2 +M+")JH=W?=VE"4++P!B&47ID&,D@)>6/>T&5U-$`7HHG&_8PPBR+9\0X.TZ,2MAB9R9A +MC/RA'K8QIHL=(R!&M]@W(N-_]-\=8BXK(P(7LNH9RQX,&,EYN`YEIC8 +MA!GAI8J'S*7DN;25R4'/6+H$C!Q>7>#AD4HA7M$XXB&-@Y[2^$'68DTC8_`T +M5@BU4B_6[OUBRHN,U[S0>+\2Q?4=;(W$TO6"429+5A2S1#8^)F>CD;=N(7EX +MH#96.&HR<&/\`N45#W7C_7(WEF-VWCF&+FUY[%B7!SB>"(*CF+>#DGF)XYF7 +MCY$ECJ,_)C`!9)*CP90E5(X*$^8H&?`O#A/$])!YCGR>1.;G461[`B")H96. +M&>CIB%9Z9*IC2.8BC&1/0DGF)<:.8QA[%S.Q9#( +M+K/M'4[[8U^V-_V/-M/C1#(09@.D,J/NX0T'9+O'F%$S\1X#F>_!0-@_% +MDXM`F[V0MYGWT#R1"C/D;E9#>GP7C?640PYG.V3^8/+I";9%K"-+'%4XU +M"A33-Y'.9V*D1^9[Y&<_PADY0K*`_YG50U`*:&XD@>;3Q)&*)%]#1RIH=F39 +MA_,Y$GU-VB>A521^Y.@82!HV<1\A.?<9DJ<$(GGWR9%YWXBFUY1H?=^)IDN$ +M$9*DS4=)%GZ8I"8I-AJDG63C5TV`DCE:E2-+HJ.>7]QY2XI^P\U8NDJ:?I]? +MRA/Z.3>C9.7GHZ%^KZ2PJ4O>5^!-+_GZ<6F(E)>6WIR3+$4QJ?O)%<@DF4;? +M]'YK&GL3_$&3N)HZ)>#,::-4-6E*+7\K4BI%?IZ?&]+SUTB=:=ZD+'4>T%)O +MA3@)*I"3CHR'PU<,DW)%H_:FC7\?6#M)J2$'C..0$$\Z2NN?^<2IM1R=!?RG +M3XH6_.0S5N2D:@!E_K?/:7U.CJD%Y)`7Z4S!IH.5)Z@`45M>9?B(!4`K8V:YF`PY]+ +MB3&L@&ED"SA3EFLR(-5$`Q)RZMK5,%*U:Q?G274><#J@$U#Y/0B5QLM+U1SJ +M:S424NFO(8%+I4/15.Y4!%M4V8]-E5'@KM.P7940F[`SL6F!7247F.R`E5.G +M>TA6?I?4SEFYO7E5:^5PR8`&EO?4''B?S97HCLSF5NV!<16\TV[H;*]&IH@-@)>:A:,C_;&%T(^_-7L +M1@^BE[&3@,5I$5B<3WO9NR%8\*7HPV`M5A5%8'AF%H1LYD%X&":$]N5"Z&8Z +MA$\<.EA@PH7#SY!E$8Z9)NFJMA&.&XOED0H2/I8&J)19858@%R9*N"EIF#[6 +M\9E'29]76HCY4:D@^ITL9&+F;RCFK<&_O:AV(``'A`R%9TE1N&CLJ$BAE:H4 +MBEE,86;E%#YPH^".N6;IEEJ(*9CFY:P8;F`\31E\1;KBIJT:H>JZD% +M!N&JC^%]Z5_NJD[<]"9G1I1T)F5H9VX*6!R-H<6)(YMAGTE9_IF@8:"9;"5" +M*J(:YPBU<=06:[AHQG&OH;8%V\F&WU8>]PG9AN16'\>>?!3%)D@RR&V:OJ&[ +M!1SB"\)A_V%OD9K&X2-W:D9RVHJ_Q6I62I<4LE#,\K] +M9"#`KND=JJ#:T,6%*0F;+&?'56P"EB%7LKD.YG(<6[/)RVD<*E>G`LRY)\(< +MM5G,R6SY83_4?DHGV^;7Y6T:1.`FV;5NH@7D)C87$2F(Z:9%)&Z2(%#7N\D1 +M48CFG-4U$F6()='G*@?@FVX7B+AOBETCHK]9(F9$.)':17"V7>O)/U?!!'1R +M%U$T(Q8N-6)^$G"BB.TFQ>D=_%T^8L8))&Z<0J)5A:<@7G:!5R1R-EXD)Y-X +M%CF)*B>4^,I)B2XGYR6-F>7.-,5GCPGDI+3T9EGXM0P=-I> +MC%&6XB82=5^2G,AT]BQ*W=/9U`&+:XI2UR=F"'\BUADH2E]B +M,G;.1MZ7HWAV0HJZ4=J)UJV=Z];Y!=2U=7"G<<0IXD%TW7)TU^6$^1??Z=?] +MG62`_\6IM(J$YZOX'25BLJ+"F-@QG@M8&\:LS&B[(G0G>6Y4OZ+E>3$2BYJG +M!K;978>>9V*A+(*BAF<)]BR6GBK8Z5DMIIX/$K8X@[V>F$?'B(/1=K6G;3Z:+OF>+`7RZBR/+C!0O>I\3H8R2?,H<]^*3D"_:L,\G=5.LX-UMG^1..Z(P@I\)F-62WI&?]2MFZM[U9V62D23?68?99GWW +M?O)A)E4)^X=UJ_-GR-C?V9\D(X!G512QBEC*:.`-2OUG)`:`_A,QXP"ZK!:@ +MX]OE@H!2>((@NSJ*H14^HRD&-$J@0B,%*N*]8D))TL@J+8TJGM/XNT"-+MX( +M"N.5H.#A"2H;U'@JJ-:(C'&-.QY^U*/ZIMW+V/C[E8UW465D@YHO.&BU)"LR +M,#QHD^>-R8WS"]T(+MF-XY+^\H6"H.B8AH"$^HU*J`'3A-)+3^CA:(]%,%+H +MXOB35:%M'A;ZYFFA!5D)0^CK>(=J+W$8[2@S]:&":K"1.V(,,IFP]\7T3+_C(2HT):*H +M*$]V-/ED9(GRR#S*4:5H?>I1.4I+&:UG/=IZV&,GBLGR>A3#K\?1+A0MK=I4 +M[)6TY6/+0'G&3:RHSN"*LCO0WOLH[;$RU-Y<=HL&;(23+IH_[C*LQ+<7[?VB +MPDPP.IB=>Y,3`7F,H@KL'JZTC+H%"R1DYD!.9MW,-`K.5*/D##9ZL&60[(QJ +M`)I=6@3?!AJ.4GT6U$H:GY:0Z.C#M^5$?"LD]$#QU6;*$\8WC^IFY$+'AT-\ +M?/KH]\K1:$_^:`\)D*)\0.1)(T223RZ?$0GS6:!))$-:\SFD.8T'U9WM$=\9 +M$$E%CF=69!EPGOT0&FG1MW094$D?2/HC?)$CJ7)6DJY8"!9**D*B9N4HUA?X +MO:0=%`LEDWI]!EH)=4+EI"I4'MF3[I&!WX1&U?R1%UIAPTD80X)/X?0DFKF5/,:33YG*ZC70[+N@!:%Q0E +MP#CI1(#%&@5XKR!K**Y'>1C(.0"5L[:"J +M%&FO@`%+`>3MOI8M*[L"H,=NG,:/>E7R@7/4'VE5X5=.ZHJIL +MAR!A":0*/'`L15.D+FW*JHP%64J9FF5G.&9=EE3J*-CL4I:CU98*6GJIIF68 +MREJ-J2Y/F>JVA1RS(&M)`M)MN&";*EOJ;;[@TC.GUC_"(`5WI[H.QV`:PJ\2 +MF?YJG_H,AG#1H)_E9"*L.M"A^EPFJN352$A=2@O6I>A6J:(=;>%VZ:MBJMZE +MILJZ<:KWE<4:#X:J\^!Y"6"5JKC;J:J[[1ZJ*C_(JOYN\67P%A!RK/TEFCD0 +MJIG]93'R7S*&ZX>`F:M>JL`/L`HG:G3BY4+[11BKCB"R*UEA&T@JA.>LEH30 +MZO8CK8IBU"K[9JT&6?!;3"B_#;4DIOWVK6H;.6&*R1.NF%164'BNPICJ*@,* +M8]686.J-*:_FF!"*F?E5\%1FDKR"(AG*K)GAGMG%F2-^YN,':)9Q@B;/FL8Q +M0L[6SXIH!JTW497`:!:M4*S&-AN&6Y3$N+6`CD)0*R"7:5J45"OL:;5ZFO$6 +MUAIJ:JW$(==J*AR'P"+86NE1ZZIMA%TPT`=MS[69"ER(J705G`_P3N8@`W1H0(\XG +M#2?P^G`*KQ&GP%FR*C%]5T-'H%R<$!TB$R3.OX)KD0AR(EF,%TTH%G$HUJOD +MA;V*=*\G6X1Y39TOY_=*%V6).4K-N1=-M,;?7Y2^NEYE(OO*TPF=4HJ:>!@4 +MG?)K?H=TSKQ>RIPHS9*Z^NMA8'SI"V$EU1FG^(E4G0";G6B=W$H!6WT=L%U= +MHBAV+HIDY^UY!X!?$*SX-2E2L.:+!;L%8[##T5MGEFZPI8IR-']]L/I;G(O\%V)VP@V<4O'J=C.(1L<(P*F#P7:[X>-:PD-U[-'GFL)7=#IMYYD>; +MYP];:R*+0BSHR:[$BO`*Z4FOF)YU`;68VC&QJQWKF2U:H_F7%#M[4K%*JWLB +M(I&+N1V)V7M6IG+6JIBMQ$C#9XU4?'8T]*)R9R\NGVIL\\G&#DG0Y^59['XT +MU><<2S`Z27;LP0C>=9^S(OW!QY9Y#N,?J[64GT:=('L>I)\QK"D\WSVN&B-G +MTH^+ALAUH[_*!GF.]+*Y$@NY*,]XPFX*F,]2TI1COKLY6B.A:&< +M8T#[.=(*%Y.=8-"Z?6OH_6`ZEE6HXQ@9ARYZK".,X^AI7I`>1:N'KF2Q@I99 +M,Y%[FU[.A$;19&!,2#LM(**D'E"[B)ZTJ%Y*^XBN>J/HT^311H\MCM5$/6I- +M-"TGRNIXHKP5]P@XZ+19#$_KT?JT*]).%M0:6:!,47LSF#+M8RQZU0(S3.W\ +MZ-0";-A>5'LUY&54;>)T&H=[62VY)XQF#EPM,I/N64[(*!R%0-9\C9GA(.\] +MHY*9/'OOK;59EP49-_E[VBC`)]<*?'0M"'`[%6`AY#BJU_:V?*W#-T92N8$M +M&QALO*,67SSJT.1F&Y\]ZFW8D(QM<(8]]:/M4W,3EV169D3(U1`1'BD1XI`@4A3;;BJ3R +MF6T+]9FDN>W;NMO&E+XM@%;J!+=,Y'`K0B62!]H<>=R2?)MU6I0VK>DC:&7R:IWF*V +M!*DG^96^MY&?6`K@ZK>U9'W[EC:/<:F1QI:BIDQ2N$?%):6GJ5O$Y&+:)M.XR86&^YAR +MN))I4XE*ON(UQ +MCHM,I7^!A:;&_MVF[Q^HMIOZ.+VI2_P]'+F3CD!)G#*YQJFLAC4\N0-@E)OA +M%G_<<0)H^4ZG6&YURAN"5%RN=FJL?;D<99C[G8ZY(*5X>N:2I],:?(50M;DJ +M)7L:YZ*D$Q6=BR?-I#,@8LUM^[GZZ4S:R]`FA.Z_]@$A$$'B@#H$):J-[ +M319F#I6#*ND2?TU&I4OX7+H+VQ08(QU5G*[>H%4R55PEJ.M5BKI?8(C*;)ZZ +M9>6?8:)^JB@J6\Q6LJLLJC,FZ[IL/R%=*:/J@;ANC8JSW:B`8%^9RKZ!`;/V +M@@@.NXGMUD"J9=Q6"[J6:VJY>[?M@K-EG/H+YIWM;E6(K_J89F]OF?;^EEPA +MG^K!W;MAH9(I#ZP,MO'QBI@JR +M/;RURSM8^)),Y27M1JK.O.LEQULVN)=A1*LJ7XZ\@&%]N?A^K/EEK3K[((9V +M,^3+Q/&JTQO7#`U?;\)J@DFLKE@X+_B6,3<_$F;'_/-B/T$OAIF^J80;)OGC +M$DH;2:],R/36A.\/O*5@@*MTJM1[!\ZZY:K5^_]@O5K6NOH&;KT(G,D9]BY;"0U";DOSOCL20IEW;[_[-">\B\<+ +M%P1EF1CM10&Q2EJ![Q(T^$;'8W-?J/%NK'%SQSHW'V^DULG;^*Z9(2NFL&$U +MA"DK1+BR*H#Q59W9$-E!"$N>J0?1K'RF%W>SBKXY*^F[LQX&G*MIF/JBAD#K +M:MCZ4D+8EJ.9?R&MK&RXR+$PK;>ON75IZKY\\JPJA^?OW[ILFKKM4./BRQFNT2;B.FW*7/2O,7=MWK^)K`5, +MG31S_&]!!'2%F]X?8IU(T0JL`+O`_@D, +MO"/*P`MC#:QQ%EX=9T4'O1Z)(6>22+T"P1_=]9IR$L'#9L?5O<9%,.<2++XV +MP>3K$WR^JK"L5\^YOI*Z[6N4@AUHP3='_)I[?<&![.IWO]*)Y7,9+&Q$G6CP +MU/F_UL"`XAM,P*9&76?^!79Z=7>PHL+`EIT.+*32!TN*Y%>7(@CCIIAB(0RJ +MU+>(<')D=X**H8&HR.XZPGLG)-QW2L*J8N"IJ[B*@]TE'"MFPO[!"VL>Q<.> +M,`T+@45V."P%IB$)BX=LL=$GL+#P2J)PRF +M"S^QO7`U+7O.=D]E,"PNXIZXG>ZIQ5HHQ[!O!RP&G^^B&$M\DK$&)O(I#2N? +M5!CS^=QE4-BP&VLD;<-RK//P#8MA/DL9-@X;PGNL#H@.+S%N&"`+ATF,Q0,\ +M#-^MGW@8/;PJV'?W<)SD!2-9@1A_5R`08OZPR0@05X\"\8$'B;F,DU@`VN`E +MQ,INLPHA-,2H[&T8$7=*&IXK2Q''LA:Q!4K+;A<:\>UBU^:R'N@N2\Z&Q'[# +M2%PUEL2^4C$&OJC$RE@R6RO#H(F?#/K,TJ"H]/12$^N@;2,WILW&C0$"3XQ7 +M)PCB$MY8A.J-YFQ1G(0>Q>]84NR$UM56Z#MKYED54VB_)!4?;%2QA7'&>YQ67H:#C&2HZIJ'1K:"GPZ#%;RC)M!9[QYLR/N@ZPL6PHUP\ +M.^ZA=7'R?#LR&BLMIS>)$J)]L2'Z%X^T@;%G/!B[,<@CK:#2LGJ*\6T=MNRY +M,.UC3)9MHKC>9'S3JBLYK2@:B8*/>['XZ)7YUIV,4'L^AL9F&;-'&O,,26W8 +M`#].>ZJQTE`_0K4ZY&N\B^J/O(Q5J]1BM8V35AM`/KJ&F5?+&X.UR:A8FT`& +MQX\9Z$3O1:.4F5H[02;'UZAFEHV^3L[Q[%2Q2L=+X\&GG^6UO&VBDQV7UJ[9 +M7ZM"\BL3GSOJ0H;'RY,\2A[7HXGM/;K8YJ/J<7K=T?"0(,UD^T/Z?)8M0;K> +MTL>:K7W,V>+'*<5GRT0^I-J9?VP_@9&F[?Z$VEZD!C)ZUMHFR*\M@^Q%0LA. +M7U8S(>.V7HV%;!U'V/Z9!N62IC4PJV1C$W`M[5-?JLEQU%G5'^+2J:E6;*43-_RMPZ%?XLEJY(![I8\X!K:0NY0 +M>9=^-X,41^%+PGY]J>SWEP+*@:E+(>'N?A$NFHRF\105[FYH)F.XSJF=/$U& +MI@;.9$K#*3@AKFRW*'.FTM\WF>*&D]6FFG*E/23,?Z8%,_LI+PKXWVLQG+*1Q6FL]O\AI\&%0KF< +M,I1PFD-I84.4"J"OU@!JN=BI8(E/W!P8Z[O%01#Y]NFC$O8VSULE(GHI*! +M#J]9:2I0V&I@@WEDRIBP[C([,/MO!7.,:NLBS#P#7JGK,LR\KHX*,0.[0EM@ +M5;0)J>H5QFRD:LR)LY+*[+JK3BJ\"J6265,J)PBEELQ/:E1H[:;,J-7*?#2V +MS&O;RRQ;G:GBKBU8,\.6;NIOI3.KNSQSG>KN"F[P[MF;=6B%1//:*^^VO=15 +MTISODH6^,]WK-&>TD0&B*C4'O'3OP&M>0:I8\\%+;1#/EJK?G.GDR_45Q"LV +MCY<>6=D\JEZ\://TK`]VO)%!/[@__(.OJIEI-YN\^N7VG/)^SP!FR]NK:FQE +M;+#J8PZKT;,:J!'FO!`FU-WS+KO5H/4#])YO&,CC'/Y$SBVAATDYPX26\_F( +M.2M9P._F#/4VPIYSR\9SMYB;QM4[[+ZZ(R'7;75'A3BF`P<54AOVZMC[,Y>] +M6.&^6COOJ;CST:P[X[N\L[[[`AFL=B^_>[DAEY"WY;'W(L]][]&Q/->%9C&8 +M66[M<(.S])RQ=EIR3&3P8)6\BJ]_PO@><8YO8J@W@\^2K_A,^4JGI*[+>C[' +MK%Z,9M@^@[[O\R`4/X,:9ES#,&BBF_;S&M>/K+[Z\T#R^EY"1BNW"$!/FK4O +M`>VSX;[G80*M:2[0OF\#?;5"T,.O!%T<'K]>ZP6=J"R'J^8&W?QVT,_OV9K) +MA=!J*SM-0H=R;FNNJ?UVA]PO"[W*!9OA[RHM)9*_QZ;Y.W+9T.GO+O=L\M#O +MKP\=_]J'U:80;?]2)C*U2H1$MP7QG/]K1EO1OR,4G-6#&P.V)Q2BU^]/(*2*N_.G#B54B#18?TXV5R-HF+=.65MQ[!CW1* +MIP3+G*'7^,JS6-*I%R8]!9.)A!$BU4G37D0GFVATSJ^D]$HM+2!U^*O3:4Q# +MG?QK&OQ*![!VR@`[*-+2!BRW>$O;P0HL'KQ+Z\%\,#[E!P?3OI&E>,&^G<:T +MIBBJS)USG2)\=]9?<7<(*TV/L)02X-DN"IZ"'6&W31M@QJZ70%K-EQ8*MP$!L@O=/,XD]]Q,["26PMC'KBTTWL/NW:Q;[( +ML$T]XM*>`C4/=L46U%FL,VUO,-C4CP,4Z-) +M&>-,O=_ZTG`3)[L.3;#]L$)6,EVS^&1"KC`-Q)TM4K[^."T(<=3/$IZRE +M]!`OH$\U*1950Z"O[,RVNE35U-D%FA%GH+?L5MT1%P8?>+L +M+D84KV,!K9<'%J^SA"-BW13?8T]QSQ(5;V:1M=:2A5[%6VA67.?ULYKCP]05 +M3TQ?'D$K%G_6!VU9G-"2UC;O1^;0$B,0;7P5%TMZX/!4<='FWQGM'XH7!Z*V +M=77MZ16B`K!(*SR2M-BU$X'2*DV'\?)(7!=EQK5+*^E,%C%M)@K*,-=EDDW; +M+.*T5IETO=->R3TML=<90UO'GG:]BG;7ZN-W#5NXC^+U4BL_^DWF]5/;&IO8 +ML'&WUU[SC[.Q_U@;)S'S=<:]&W]J^+5OK(SNU\RH<.R,AD[%,01Y'`_8F%F! +M?4&^M/&I\H=O=$V;+8\7%!VO+!V"[-9AN7=[;Y\1>T'^^D.C;/)T6&9]\D +M>?8_'IDE^C+LI2M]579PBTEB64;MW4DB=QE +MVWPGLFZ0(M>^02EH768+DD4IC)QFR\AV7XU]]W*Y5&DG3VX`=%G;=! +MLE;Z$O_H?/86Y6=#?FJ4D@QI,\F$-N97E]ZW47+6MVB[I8\ZDY9H2^H"[M20 +M^K5[ES8OJ6GOI0JNI\W@FLEF&JE=4Y3JA"F;;-^XR5*K,]FFSS/S5VMXB8"HHH[C5'Z^]XF9_O[9I>FO+N.GD:EKC>G:0\OD'3U+*E`6S +M74^>#O>6* +M.;+R#=Y=K-7OMI<;;^O:8FZ]7>:*E+]R26E0K;G7FINKK0'<+:6<^Y["E"2D +MP:U1.@2RO5[2J-F3IWW0M'[WJ_LJWQVP`JJ]\_LM?V.#47-T +M.35[;E7SHWHU/\U9,_WM>,.\\A7EW0YVJA(O>4GQFI?_E>V&\>*#GG>JNC:O +MJN\ER.NJSI?5,P)>-W?/=S/)JH#7/HOAFQE@OMZ19NP]\R9'>R%&R.K>WH;S +MTXTX/^V*<^]-$C+.P'>C)'SW6$8OD/5A#EG:JI&U?#O0SG?<'7W+E:&SBVE] +M(^T`J]8K64[MVW?57F9YWSKFZ_PTQ\YI^]1C=UL]=SN]F[?GSBKJ[CRP/LT% +MJUD8?Q>J:Z'6_%[=WXV6;+UEKDB`[Y*ZU^6;@GB]GV(%_AM>ASCH:FKZE8:%Y/Q^: +MD%`*WAKVS[#AT>H9S;ZVI^T[@QO0N:]NN/M.K3AX2:*#-]^@IBPD:AJ/QB_) +M$H3?)!CT\CNV'N%="O0K3S+AG!RMZ1]9OR5T%'Y"_P8I=$'1_;;0X^$+71YN +MX3)T^:L&?UO8".`Z5J)<.G3[RW(9)F9X/:2X!M&,ZQ#-AN._VN81_1_"X9/K +M$FVY)L!UN.9:`-?/#P("_'3=B%ATO.F';]$8HB`^`1?B*Q$:_[IJP``P&IU' +MJ]&..!N-NX[`"">,6(FCP)>XPZD4#:^;^*?0B2.O-/"/J"3FOW;HZ2>9 +M8/,T1%Y/2^1++$6>"U<,,MA%WD_+XS?8+QQ0"]!ERVUGL1C4(CDCJR[^GJ](RUT:"Y-?P]*=1OTOUN3<,$[N4>OD!J-([9.3U&G8.7S> +MI<-$>3R_WKG#)5;LGW+3ZW)"DJH +M`4'\E3-XB])8KHF5Y3GCPWP4KK*E&%L^5;LR%*@14`:(`35!#J`'U"&8`4=@ +MCFV0':`2Q`"H/:<0!/2+<#P(\`5\`4T`K]%L0!L!^_V`]\YPD+,11`1*"+'! +M7>1YKA$8H@+P!)0.:'UO_U4`]U-T$?8>V`%,MZ.A9ESW_`$,8-:#`)M]:K_= +M@]>G[Z@0+\BJQ=MX7SIP!-K]VP3J +MO7W/!HL@!/C]+M^7]S:`=O_;L_<9_#%2'.#V4T!^@-X+^.F]:L_:WY1@4YC= +M]$$F^D.#H82U=)@C"H"R>X$XU+:-9,2[=_=ZM;!>%.CJ?Q\$O`OHO0S@X/>+ +M;X'(,`9T*5D29NH\KP7!/1L@!]`B:H8.L1;(`!@^@0_9"R5M/0S@`F`$H7UG +MTQ>(]60]##!<9/B".3+K(TB!K<$UD6+P!Y;C:YXYGF.:DQC:.;X`"@"57Q-< +M^4H^^K=7_\0;1KSU.TT-1X!@G?.D8Q*"9KXW:O4UPZ4OH*E5`@`>$$:\!\K*[-6!&P-JAAWCZI3U+8.FS,GE`&Z`/*8@- +MQC5(5(Q+$N.T\>G+^@/^3<`IQ!QW@5$P*2@IIO['>`/H^E,+\I';7_BS?F?_ +MV7L39'V4'TKT!<^(;B\#-/C!_JB_[,\=N_ZTD>VC]]S^9C_J3P'57K)?C1DB +MQ,4U&#ET9?&*R2"H'"#'/HC^?,46@1"1_>Q7^MV^AJ]4,"9\:&G`[)L*#D)? +M']RS^%W/;C?N9_?]ON-""K4060FJ,/#+%P(E:C`%&`'0QG)/,RW\,$"T+P3, +M4.H^JG>5%"1[,+:O463VT3Y;/^W#`$^"M3_7C_LS0;1?!<`!-8N20%Z$$A&* +MYK517!]!RDSTMUS5LTM;CP]*XI +M<6;$`F1:&DR`ZW_`O_=I&$X,JL/LS +M,VIPZLD13D!:H8?T]6U`5K)WW`EB/]G/Y@O[6=:%N\]]`( +M5C0=&P->\OL9O7P"@T6"-!C3"PTP[=/U>`&Y'^V3@^$^Y<_8E_NBOF_?+UXQ +M;8._(0-H&VSJ-M0&H"9>Q9P1S36B0HD,X`(,_=D0I_H>E!,82!5`!1@!+0`. +ML#[+%W@_C2\#[/VCOA3`2K@-K?47L*^@`"G`^?P;PKL`R:#G3(YU24HB\C\V,OQ:L!-'^%'"=\`<^!?^JP4<.28*I<6`V/SK& +MR#\=[,$H1\FP2?;^WW_'W_"O]O^^D5L>D`_W2RD2+A$&/CKB@:#`_6<;X0L8 +M^4``,P#[7](OKB'Y"$[(`2`3;Y)L1-6"Y,:<^3WQ#69ULX+H`FT!^:<`.``" +M^Q:`#[X0VZGA6U#NHLRD(M048(;(P33#D]$$$`(,`:P'!+,[P0$0)Q#M>P)L +M%'0$4@+F0G#/4S/_B;NU',XG,\`D']^/"B"$$@&Z#38,28*$S>[&2B$&&`,X +M#B@0MX%-PSZG;4&0F`,4I.Q!;X`70*YH0"`',%1`8@("S`44"I7B`&C>N_SQ +M)R(6PQPI!QG)"^-`>Y+D<01@'4`21,ROX5<%0"C@'?(DE(1"#+.%/*`%;,!4 +M`?86-)4%@@6PP/,>>`O8X``$+9#8H!Z@`4H`J@$4@&0&->$=(Q2`$RX,[P:_/QA?L@P%P +M"J9FF;]?GP+0)N`*-*\0'GX1B8?,GQ)`2E`3"/7)!#@%M3%KCV[,OJ;C>(-H +M4N1D]HUE&3-CYP*(H-0^C/+0#:V07> +M#[9]CKU:8!V0\($4,!_0*.YY`A\83G&`^Z31@9%`'IR!9;]PX+"O#.">\Q'H +M$'9\S0;EG1@AI>4-+.O)`R]2`9V7[C/IB9D*`]4`W\#GAKG@E6A*DCCHP&> +M!*%F\2\!`PIPQ%,&B$^,`4(%V+>TT`R0%9@5%)*M)^0+K`0^AH]AZT?D$13T +M$``,V@:S"`(FV.5K,`#*`2."M4"*H&Q+,2A(>2)L&*87#AVB@J*C*V4)).LI +M!-^"PC^4@;9A\3'[:UYY%?@%`@$0PKZ'/K080"CX$I8>V!0ID/E@1M:7^!?4 +MMT`#2 +M`3B`:K[?WS^0W=<0C`[R]MZ"XK^(P;Z-E.`?4$^=?^0R%R+=A)K`;,07L`[^ +M`Z$`^X(`A%7A%1B.\,G8BZPBG1=.A=H/.;=+RA6Y:3J#Z+WK8%]P*Y@OL`A\ +M`1ICUP0O%M]@;V`&^`\J!X8E!L+EP!L@02A%21#V7HH*$8+HX"Q0(BBHXP]L +M)'H0A;_RX"4P!@`-W`D6#7I6I[\)5L`(;@$4Q`_2]T"#CYW?@&=G(&`7#!5, +M+R9[VH9MTJ!/)R@1%/Z9=P("D*)FWP]ET,<7]!`&`2X50C??PS:P1A$J8#F$ +M54R$^D$/H7VO+E@,_"K(%IP&42\DPSU0V&`]$`117FPH[<"*1/N%KN5L/!_#9X_19]KB$C#TA8&20Z==E^#)@ +M!&=WO(()0VL`!#(39H8`>8`S`/*@+X#9$PFD"5,EKK\;@`N@$2@#:/F=$2Q[MX9=`O/-UG%$6!.J +M&BJ%/4*)($405_`"$!6V"F4',X7T@FT$U7-W<`,<`:X`<,*:0*IP3JAM@,`< +M">XBD+]4B:CP3E`I_!+R"B]J;(1?X8<"PT:*0`+B"IX%C@C4X&WNUY?D,^]A +M^F87F<)-H4W`4RC7"Q6*,*Q]2`9385\@[Y<3S.M9"^%6V<)O@LN/\DF$28*-@H!!5F"EB#S]"I,CTPL=`UGB/R@[.!JN!6``6$&*`-!P:=@TS`'D +M`&(`W,(WX=209>CY@P[`EH:%_*),B990CD(WE,>P!>^&",.](::0:>@T9/E% +M#:5\4\/(H58PG3&OT2Q8=.H"'P0W0.XCAY&+$!"X`7`&ID.55PHB`8!':TMT +MB'0Z((-3#QMP,:`+V2`D`"A.OJ$D8&RA\$]AH@(4A.(@*AHJH0%J!<>$!S!@"#4.`J[8^(1W@"Q".D"_( +M`)!_X(\>"\A@=Q@Y^/V5`&P).Q56`D`B%(1D\.PT!T)!J\%(#U<)3@/CC`JWPO`R/JP`IX$^QQ3@60`=L`F^+Y2('(@T0!/1<0%%E")2 +M$8,`?($$0!!`:8`XE`(-1JR(Z#TVW[F0(DC:6SCX!SY^I8$10`T`(E@#N`$8 +M#,V#V4.@81;`11$:`A+,!C8,:#;G%AE`(WA@PBMYB91A#8:Q(9SP!4#EZR'& +M-<""#D#(!!H1--!$M")Z$N54!C`Y0A`@+]!20`T@`7`$?@+Q`&+!$;;8XR2. +M]3R)1<$?8)G!2*&Z""4N-I:(:L2QB"DQD<@I0`(L%EH`6(=<'E2`9!"%(P+6 +M`4:!7P5/(''AZ_`EN!S,#$(%0@`UP##`%C!?J.MQ*_@"A<*\X;FP"'`;NA)J +M$MIF0D1!0:LON"#VR'O8!NH`VH:A2@*`Y1!\2T*`$_T#)T(M8BYQU>93F"L0 +M);X`Z1&`XO/`4;BPJ7SQ!ZHLM@0K(64`2UA]`UC81^PWQA$=PWU+Y\)\TYS9 +M$HXN-QJ8X.%")KBPD2:8#^Z)]P,80*CO7&@C5)OY_VXT>:?A0"L$D$'=2S.H +M209QZR;110*@6/'C@Q(,$\X(C@W#GQ3H>-3K8-GMB[!8&`M;`E#PST52$46< +M_L0?BHMT0UDP_C<0L`ZT(RJ$;YQ1CBVAT2?`H*DD\<0HWB^F(BQD(P$4Y`O\ +M^L2).``?8HR$`+@'>P&`$1<#`H8QHGBA/!#RRQ4!$]>(3\0HXA2QBM@7^"J: +M"\.*6\1@(5I-Q^,C&.RM^@P2Z\0R@-@#/?C'4`OP""Z*A)0-0^2`JN@T&`*D +M8_AHTK("3S`OJ;AAR-C9$C85Q0&G@>M%)C),.##I%14[6KZE1%TQU@=6O!:N +M6UQ_34.B8:?OUZ='Q"LN#6L`VL(:0.#0:/CIDPG<%4V+Y@O7'VRQ$4@#F"U* +M^3Y]:,+LH6MQ%,+_28M"PN`@XO!PB +M%T]^>,/;8M'@69A0:#H@$XN&WA)7"9Z0;VCRT^WE$RD">,62XOV.5,!25`MP +M"C`/K4.>'Z3/51!&4`,<(&P)@8/%@,)`QV!U:B,L')@9?@(\A54DCC!S6H7@ +M!TXC78D$0*YHO_'W"_QA&28%CD(=@=LON,"<@(`AVP(T,\4OD9*A'3%'1"P4 +M0>*+&!F8H11(<($:"!%F\RZ+'X[["L^`='`7H2G6]F@'Y+W\H';QOL4IR"7* +M&#R'X('-V:FAM@'@XP]P"+6+2\)F'0ACDQ(&J!^&V+P-G`)+![.EVN%!W'5, +M`+\,/<::`.(2O7` +M&0V%Z$5.`7J0#$`L2)A(!?`":8`J8^]`-<`H%"@1_2Q\@$8J(]1L#4`<0`T< +M#M0`#P.>('L@&_@@L'/(#MH1H2S$@&6!PQ0INB@F%@('/`+*@D'10W>O0'P( +M)%``AX?B'KDC\,`Z?`/4"M83"J)25PO`U2@HN`.<$=@`XYP50Z>HC#,_2"LD +M%,MHW9Y90TTNU%94:##:1+X`407D7SO""#"!20`,54)@I[_Y!+3#[ZCL)_A"W!_<0?B#46'HH5^YPW(Z0188A73`+@%P0"Y0'TX'W/#B!6S!^= +M^JHQ9$6W7P)%.;"10"SHA[IC_4)PH'!Q;?"K`\&!)810G9<>"STHC'#-PS+0 +M\#@52<`X(@UC-<`&*!/(3>8./8?^WZL1C!`C&.:`##8WG`H1`%Y@8>,&$`$D +M_SX2"8!&XP1"R8!TV!2A%:\JML8YP'HB778W>`T`0':![<(I(UXQY^`@*`T8 +M#=P`(!E'ASE0T)@>S'=P`E*`-D%M<4OD9HV-_D@3'9<_*E!(8JSD!W8:"12J:=6Y,\ +M"7('-!=I(8BN"(`%(`(4`:P`KP0X0).#XR@(3*7T`W^,7$<:8^(09I(+^IRQ +MJ9I*&@:13O0NY1'Z@P>V%NN-M:B_B6RB]917D"B._4)^`!@?0W.1!K`PP0E* +M![F.K\4GG]FQTWHXV!@ZJCJ(_>8^LQ26#^9#6D03P@!"3S8 +M'G^/#$!!1[%@7C@`E!7"_[R&MX%Q!7<@FE4>$`%,`3`$E`$1@.?`T95OE"SR +M'E04V\=JS!(@N(`:T`($%Z8L0D?0&,`IF3#-&$J5*'J/T$>*8+,LH?!@;#C< +M-FH#J"9"C[Y`8NAZE,!L%*8.MI%5EK6@!6$V4B;0K*0%PC_V`/=`.#+C0V8< +M$?0#^0++W0*(EE;DV_;X'K6+CD7P0+6!VS`7@!BP,I(`1X#V@1'@"7!SP!I6 +M`:8`4H!O`L?"2>8GP*;0,N:%KYF^P,709YAYW!V-!T08Y(5ZGY81![%A`.)% +MX3B.:@'Y`@31V05$=RSS20E``61#K. +M&'20VYZ;P-.QYPB7.42Z`>Z0QD!P*!!"`24.\(A3`3\`>2!:F2GR)$L9:"*?"KXC]`[Y, +M!%U]8H?+(K&@#M;7(RS&!GP,V9+`'O"`4Y``V,6D!0V+H@$C17!AFY`K0?,E +M`$0L0@E^0AU,8J7ZVX/A)<19CP',@/0+&O$"X`*^`+(2E`(]P$#`S[>/V`_@ +M)#P'1`"RQF."4^",Q`^(-P(HMH$\`+3@:]`FH`'8`-H`-8=I`TXPN+AVQ"W^ +M!IJ+,X#=XYLP`2!M4R\5#684`H:07PG,N<<&^+R(+*8[U@?"8_T!24!=L"5H +M?I@F^XAVG3YD^9B#N#=Z)!D-(H+N!Z>@"$`8`":\;]((.XBA1+?F!/`".`%` +M_8R*DH^*`7[`:Z"L20",N1074\B0"9\#7T2F0/5@*@$#/A$J,8, +M"$Z2(QDC'XAO^"9^RB1$`9%%:86;Y.D`(3$_.1U@@'R2-8SHP#'!"_$>D`]] +MOJ(#2`<1@,F1L?-F20*^,7X>BH8!@JJ!(4E;\PL.)U((',F;(:I@3L)R,$N" +MSC0-4,DX1N-09Z#%&$S.#)I'@\G"P1A2]-A4^$18"L"2#80U(Y0D/G`@_!2V +M=PH3\P@I8#.A%CG,P1:$('8/-$.LPTFR!8!EF`I*'1P;WP-ODB`!#/*(T +M).4*HD)61E;"$1$Q[`--)C,^)X0N)/=D!B`#R%-P!*4"_\&3Y&G@#5`#X10@ +M"H<3T07D(/;'=L-6U,O@$S($KYL;0(8"O!/0)1TG%`MDXO7@(CA`"[.!1-X1)TGTY+BH*6AK8#FH +M)T<%^(K`I%O,+FD\FJ'<&""10L$X)"N#V#-M86TD4%H1D`=90B-QR_C-.4C5 +M%FP)-(Q0``B)35*R0 +M`HD-`95-1#MB%SB?B&AMNYQ*!`+Q8FE`'F1+F"CV'6LA(((W""?&D1%!3%$" +M&?D'GX90"2DDW?&/R`.$&QUC/H;KC&"!'$&2M"7\34B.(LFNG^6D+FBP>%%J +M%YL`8$$7X[V1+5F(K$02'\V!5G7BRBJ"B:*GT'@N2$T$ZH:CDQ;4_$!3$ +M_>@`>@@\8CR0ZT@1+,XM#::3?[<9CJ<&!+`$:`_$K6@44R1UAQM#1E +M(=*4GX;B7'5RHA@84!HD-JHQH@@]X'RHF^6&-!&&'3D%Y<3"GS!6Y +M&YT*\<:T0KQ".;!^#".X'S^%E\B>8ZY01,EU3`*P(=T(HLB.(X/BB-!_;'X4 +MNTH4F#T9P-425NE-@.O1*G.%>DOMHF2PQ9`YF.X<)3D5'DO"X+-D1^G`$4\) +M*0&7>TLK@(.@2TEX'$PN-D`BEQ,+C"^1P."[^CJD/%Q_.8`XXGW+A#6(:C4.SA>`@N:3!D"'9\MH9FWFKD,!`$X#LH%B\)L86:WV&2<5B%7#IL +M%*Y]"8"T86>!2K!3P1"\,M(*C@EXC!CAOK4=<%IF&9)]*K>\Y=Z2G.BIF5)T +M+Y@I?\CX3'7$_TCEN9QH_.H.(,4:GW:1G'BWBENN',T5:\HS@!W&EQA+NU&F +M"4*1:@XB3R>_)Y$]2%?\M/7PJ3(K#"C%B> +M^E(,WX?6`KML?-D\0O5X=FXTDKY8W[^PAKDTC%6J%M^$O[XA9I6QA^GD"UVF +M!$A86@.;A&%![E262&*:"VN8CL6X0;XO,$,PN$V^VX201P1(W6B1TC=!)&). +M#B5_L(9UX2KPBNGO:RIR,Q(<'9K9WU$0R:!YO!XL<5H`<0#E0`N`":#'-`/( +M%).2ZA_YY>>!H(&?U$KHāJ?:XDC1C,E<=&'J_M28I;U!I`J34W"`DR@F +MX%R'7#Z.X6*"6)"G"#KQK^0URCPX`X12],!]S"1-,3@5=;XG0D;(+E"#7$7* +M'BX)W0R2@A$&_G/"5`F4,5F8X$ICP]>QMI@T9&2.'25_-`%(YHZ/:DC#U!4@ +M!5Z%1@%DYOSPQ>"7V/%M%`J4J`JGWXXO4.CTPP/`(22/-L5-18ZQEGE>Y`@H +M_>B$CY/80DV";\`V7(RX#4L%X@$U`W`Q8^C+W"Z`*S\"PLQR8?:PADD1U"5JT6"YB)S9YG[LDH% +M*IN"C;]=2`L@:+!0)"Y`-$\#.(D6@()&ILB`+&5.`1(&4@*M1)A0J0*2460UZ@B9#U.`,D +M1WB:$A2OXDFSI6G#9&WT,%L`O,OII=./=WF;I!T`%V^9$4N"T5+`1L!\$S`8 +M1Q*52(%ZGTESF(G63&GZ+3M]W,RZYAF3LA?#)&BB-6N%&A&CYJ8!TD=W7&LF +M%`"2U`$VQW\A?I*[))Y4&Q>;ZJD%'RP2I;G7/&(:#6.,,TQO)EQP5!`I.'+0 +M"3N:U9@ZY?=1+F#UXPM@-GN9G`*TQ"&G\C?;0QTT_\P4LQ=\`IL2Z%@:G"/\ +M*J,9?#0NBGNNTPCAVP],&$6/.TS?0::-<1%CE`$H,5\$(HS@WD;!15@.O*DM +M7B(J%K/HP>U0,%F%E`(!#4B0Z+@Y2:Y(!G`$`#SP#\L#,0`J@!!`LHGDHVPV +M,MMZ\,R_97&S6HC%=(,!]`Z1U,.+RK(-C3`C86:JHZ2*"8`D@MKEP<@5"O>) +M!'<*`!D\(XV.@8QO(5WH4U8>"*OT]>X"+`\$1`)@KF84$'#J +M'>AWCLG(!&!!6J`P(`_<"\D`="=^PBZD#5#"C#*6-[F:%,$C@GUCF&`ND*TU +MO60A3PFFP=C"3(G-"Z:5$V@`[P-!`6_2-\E0:#-^*$V;V#T](CUS6-E:^^XY +M")B;JKY;@P\`!W`$2/[=+06<(`,G9).26-`@<.HL6NP-3@T'9_QR(U'`@:N\ +M._!3Q4W4)F*`BRD73"?>#S82@,S``GL$0@`:L!$9@703[P2H7Q(@%,E96!GI +M+9X%AXQ23Z"!IK(4H)?Q,'4T?8$88W:1J[DT;.LA--^$FDXMYRN0<_)._!KZ +M.36254C:H;X`RUG>$W4Z_*!64(Y]&[9&0$#S$V]%#D0`QL0*)HNKG`"I^R:@ +M',$HWP0.(FZ%U;GF,VA2!'N".D)*PLC@-?!PT!=TFGR'18`GP`41%0:I`!78 +M$NYA]$(,)O]Q,/!=_"`07<([7[1[$W[,))D`,(XL,"4A?`-0R]E!S0!GS&RV +M,[&%$P65YM\2SBAPG&1R!7V)VZVHB;`Q`B4B^O-%-&L21T$SI8V#K.2+]!,4 +M4S`(44!UHR.BWEG,I'.<&_:9.@9]`FFR<8E_D$E(481R2,[$X+G^!1L]GIW/2M +M"^F=>LZFYS=!]4>:,(YH&"H&E;EDTF&J9,$!/%4F!DL*]'*0\GGUIO0L`QS%%R3_81R@'A)AIP,=&D[)%8 +M15`]Q3GEP/$QG(G,F.C4!?D%CDF%ITK@[-G5U*JD%:`%]X.%(UO2,)6F`5LX +M"BF#<`1;@A-D37:8.BHX"KL9A,X4F]Q@2-;EP''LU(Z'*`T[C2J"BY**:18I +M/O64!DWXX:\.S"BA"$SY&S<*IC:ZPA>@3R#GZ`O\&1&&[\[3XEO/!?#(G'=: +M^(B9FLV)HI-O^C`03#+,)U``#D>J07$BJI#\(V]<_S1F_:>DI]$/^(GVS!1: +M%_4TY$(OH4$S7ACAFP^>RHX4Y\<7E+$BH?01$'::#VP)*(#"0]H&G#"Y="8P +M4S@<7P-5`[E09=GP5"]"-4D0DSV<@%10/R`RT#8T!>V'J,7OIPVT-&`$M7?:&"=)I;^+)L)`HJG%0#]. +M.,L#A4A;@M2Q4(FG7((6.[F:%3ZU(94`QI`M4>SQ +M`B69#<^EH6Y1"=HO!/\=01N9NDHE:-/1#FKOE'"6,D.0#0;"XN&"\M'7(VN* +M^+8$;,A*&,K1U$>G$8/6'V`F>8;X3*6S-(7BI'60]L)<[T:4P=@E0M",A!HE +M"2:A$@,7@#02L)=F(`V\`$P%6@+$@H6"DX@&;0%,`8(`+0!OII7O5N(W0!)` +M$FR/C$\YJ+R3]^B!9'Q2!'V%Z,RK)G+%OWG*^$*@`+<#P+VC`0!QV/$J>/SL +M_E`)V8I?G2RA,MEBH'0>"0`,<`"A8@,&$'H_$(26()D^.Q7$(;&2%O$"&`P) +M/L&9?9]HYP61.W!G*(@0A%@?($92D2!2KXD'=7K^+7>0:$W](^>S\GE4J#O" +M+%V'+5#!CZ4AP6BU&(P@)R('E93Z(1)P?*&I6X&>W*!3_X&+(OZS/Y`)A8D( +M*_<67@A_HL.(41C!7+6=.[N>H<2GPQI@VW/UA$(&\RB.FX4+XWG`(+KF:##0 +M%68&[P76H3PROTCDL`+Q#2B?J+9^:'"BJ-A26`,((61@M@1$#L?+3RA;TXB" +M"@!_EH8R`/Z06B4%PDX^O,R3GD(D@=V&2/A]F#(D*;6-H0.5H4I`SSD%:!!, +M&00,*8^PYZ`.FG8QG`/:.W6A:L\W85G4%UHVJ%CV.K202$J0`JQ0PK'C6S&D +M*O=_H4]AI*"BJ0B;N,-]+80#-TL07#)ASH#.]'G40E@/E\/W``]@4N,#T(HV +M01N>^D>[0(N!#)HOD%:*$5Q_DSU8@]&3S;EDT!*8*K$,R80YR5?#8N8898`V +M`59*D85PDH-"6+!E$&$6'(TBO!!?XY3`YIFY\"NRDU:/N[!00?T0**%B+(/J +M)'(8/@/9Y050+3`#51ZZ/^`*IP$(U"Z2.S!,0/UIF=X8M@0^`29#($""`&+R +M#&E\[DZT9P#4LHDYQ(YR/S>;WQSZXS4TMG`=/?*Q,[6CFT(EJ%60WV?OI`AZ +M=G0S>(K**'Z/N:#CY(MR3Q8Z\$\B)7\`J%+JVC_95[`5-:=&14?D`5AB)("% +M'DL1/`4L#[`$@(O(/,*,6F)`*+H8E7TK15#.S/`KJ,V^. +M'2=[Q<].WWK4-(IG;#0(-D4%A`*V)/9QJ7D_N`?F`[$`=D/]Y1WT0RHT5(_Z +M_M":18"V@*Q`1I$#HA*\7\H)J=%:RFJ4+8EAM#6$^\P&Y8#J9)`T-#4D-82,-QIHDP042\%Q2]3WH:D@.0>>71.K05S`T',??!QB +M`CVD[DRW7C#S;YD`Z"'`8J1`GHDZT"@H!(@#@4%04:F'X>4!WD6G1Q. +M]M*;>,V>H:MS:5BBO&L*#MN"KLYI"*8^)$4&K09%_6/YZ%68 +M*>6%+:/:PI[T/!HTE'NF1:6&;4%FZ6G4C=!6'!7D2?$`O@7)!^\LE!@CE56B +M2>&=?:*F3SREE6*J%&P.P72`=R,9E)))%=SYE?S$SB0 +M:#X(`8/NUAG`!2`C4%>*`:((,5*S:!QT2N^&C$_>F9$T*J?!2..` +M-BD))4NMQ!6@?,`A53MN3!N9RT]=YCTT1/D=#8-N+X&7@.RT]`J5H4`)H/I1-2/3D54$%#CLRFJMFJW.U] +M2X6?R\]/I]%P!JCG="PJ\XP5&,(:!:%@Y^EE>K^D(C"$H1DVC(3`6Q483`$: +M2?J/0`,SHQ*06E%1@/1E*>T3PHS?>L92K>F`%`]YRN1X*>;&(^6 +M":!^.XLPX#L1#Z`%E`^D*Q5]@Y3$7+((OFF[9",H1%<'R%#%QH6RT%-1"#!< +M#I(C8!0)01$MBM3X$`-H"2!N)(,C1VC2#&J0"&F<'XH3"H.%39Y2SWD%.'6^ +M-9.;(12B0?0S#U"<(!84^Z2:`&8/Z>HN:)L@X0`_P"MQ`M$ +M!9H%VH\>)XIRZ\@Z19J^]<2E>AH/H$$3,<`Q(#;Z0_&HA,EI1(V@K]=TH`R$ +M"C@$*C?=@)L4:8HL(!!Z)@X9K5&^0>@Q#+"MO`1^!ONH:5(6I0!T7.E)S:%N +M$0T\=8$4Y-@A(*H_O8OL5-RG!PC!SVJ`09`U,HLH)_]37Z6_QEH@%[DRP%R- +M-\J"K[T8R;N@1,(B?.UP*P>H!\G/GAA`3ZD$/:9R-8^3^]$7ISJ"Z]>`I`R> +M.W&&!@E#A!?2#UJ-B4?6!;N/1@"4P6N@#,`^G0,T$>2-LH9A@"R@IO)K?`_L +M%ZU<$H*G:41%=F`<1?4<`2@%ZA+[S?W#X%`P"`$D_YX*-4Y?)-;35[/Z1`W@ +M(+0OFH5"X-BOD^H9S(5R3)>I6E,IGS.U/0K.9&6N_KR8@@(/)9#C+J/&@$RP +M`>("\05IHYG0,S@H?:CJ!)JIGE179Q$`9$E'!5%H&+Z&UK22@E_R_"@A8`-Z +M,(@%(TN'P[G!#*#1;,P]``.HAX%-H,H-/_@!?)DB39>IKU.)JB<5K2D$0!(X +M)CZA4\A$V2Q5NC?="25P"KX`C$=0(*^!"O`%F`(4`88`50"QP!?`"?`$(`(\ +M`:@`9E4JP!Q558!5Q0)H58<`7%6O*EA5K#H%R`(T`9@`[8,E`"$DG3%59:)0 +MFAH,5=!XZJN,G%H+&7>\_V8T<*N3D^D@YM7;06M("$J!BL6E3\A&L:JJ#'P! +M4&4#+H>8RU!5S:ISU*E*EEO=0H9-6KB,(&C%4N^`;L,;LC70PV4 +M*74#Y82L:N,!KOH%V!I*`4X..@;9ZE;U"_`$N`),#Z0`/PBOG)XAKM?,6)N6 +M!Q2628"Q@XYA"J!*C5Z)&-:6]M*':KZTTX?9$W]R-1]\S`5T8_Q2!&"6S#$0 +M/Q(I$H*-"7@!KL#"$R@NA-7&B_(W,5"-Q1,*<@+94 +M)A@*P90YJB[#0:`45)=*+,!SLQX6JD@D@/2I"E``]L7Y1+.`P4!>Q;4YC$RLK"QAPI&H-+`>JP/4 +M5/4+>4"7Q3A'Q)IIHSE,C.RHKX&'2:AA08),D,V-)=0E:X!(GX0`!1`,!.>) +M+%Z&Q[BT0O=P\(<%SA$X^;]](P@+CR;XG9.VZ2 +M%3BLD1,K*-%HW^*X'0#6LHLDHMUL\`W8%CDI>0`.$`J@='+IT6Y7)%Z +M,?^L^4LW*YZ+/B61?&E2$KBA+\M!*,1`TIK@*1A<6MU@`SU$QFS24,"C"0`X/4Y6#5#HC`T'Y^ +M0=^%-@`6YF1/LJ<$A3/J$0.NI)5F@B.BL7F$40F<%>B6I)`DP`N`!1(T"UBN)5*D9G*$70;6C+;B@3H$>`%-R.70YH*.,]UF12'2A4OCE`&D`NH +M"BZ49@"I0U\/+\#A$#4B/"$3.[2T0(IT1O&D\+JBQ&0A3\L\8/2$;+AT);I^ +M,Z%>5:">Z^CAOMG@LJDA15^<'$`>$6'5U_AA&$X84"&?3@SM!`50'D1W';J6 +M7.^N]"AH@C*V\AJ7KM\P`B +M#!&N%,&09$;5RKE1M=]X7:YY&M5S1"<+(-',\769$V\81:"RA`(X3C& +M%M@<-3^VI!1('OH$8`(X'A\/[RB%91.@N"<%2`(4`:8`1=,X(_15X#K\'"3> +M4`&@XD2$J]OS1&JW6D"=7P$%)=/SA/K34ZB#J5*4472=AE%;`_J/0/FS1"N@ +M.%V9>0-,`<74RH%UIDS0/OBQL-Q$[!.P`%:)2<8*5R#J,=!%]@W%_$JQJ;%H2PS"'9D;];U: +M`W]3OE8J"N+@?K!`%.M@,%=9Y4RDIK8RRL@'I0B88D$`6T%QAVIRZ<.F5N+M#\`*Q8 +M#[]_V%B2)?MQI_E^Y(+B4T(C^P%\["_OK5D>R#<6,78Q$8LZ`/*`-TDQ)0+% +M!CZ*DP(Z`)IO7PJ0/<7ZNAH1+X!&A$6@^A>./?SX!^)^.,1VQ![S!0#6S.YX +M/QHP6=@M[)V1O^D(VPNV9"]W!_W?[%5!=/)31>C6%LS&I<;>- +MUQ(*Z[P'1J[H"8`HJM:-#0\#N4X&H&T`1BH4(V?1#6P#>("X+!U@+EO;,(6R +MLM8`MX.X57=H5.$=F%Y01.(*DI[_Y7M`;A79!+!Z906-<;UZ2-=NIXEVEEFRSEXA^3>ZT5NG^Q),H +M\PHPO<<)(@T`]?C_[`(."9T&XXY`)::2PI@X#"7@3MD`>]8YJM*@BYH"D4U$ +M]>"LI0-*+,LA>KJ#%"=.9\U2FK`6PU[I-*`<0`)``5H`50`L@'+@#\CTNQ>N +M*:0-[4I<@0*2OQC767=6H.)R0+]U2U8-Q?,JV5WHLF8EO*S#7C1#K+8KL!H- +M8TYB9S70XDK,:]02(WT*DF)BBTM?I%S-,6?-8E^XC=X73IZ\6M8S"-57(T+! +MYHQ0>[Z^49\/*28O48J->=Q991[%$53,L8::Y>00R^"PY3Q=J*_;/&D/Y +M^8ZTH2,:!EFL8W(6*_30W`XZ#2TY%'!N/QG18JU-M(AS(+7:D?SN+E9;TXMU +M,7I'T+E0SVYM.M=;@\\938!KK#^_PG`M,<:=<\Z]>@JF&%9,%&3L<5#3*LL^A,@ITLZBF5G^.-1;I:A4[")F41T!I_2#)>.A-3/T(YY9%IEAL`1H.V5[CRE;<0M#%@S&V+#NB5'P&ZM +MV>JUBR2GE`J\Y16ZJN\[FJ\_W8X(Z!107&5*NM^(,!G"ITN&1M>[)L4D1/,Z4A/7%5 +M4'MUM91>&[`.42.L`TP-VX(IQ;9)3:0L-A4:V''-DS8USC;:I#AT +MRK!UV11MG8J/H-1M.R@!@,)MRBE0C+@NG>)JP]6:Z]1M62Z67KOMGJ)1XDZI +M!"NH\3HR5TBISH%OL]>9I_9M^;IB&9RK7X>[=;<=[=)52;N[)>X-5G6[4XCYO'1WVC=1T-4-VJ5UBPIE +M;SM+)0^46=D&;#=:8IF-[F4MNQW;>N$/GNYK:W4YJYW[8K?SOG4GCE\+:HDC(IW@I>D:H7G[&+4J7`S9B0 +MNE0W)*K0@^6MYJ6[75).[LQF_DS,QP".OZGN`==Z0^#US6!O(ST$$P4W7;O\F-["6*QZY)O?VTFH64GT:NX% +M[]PWQS<0D])+Q'0YZU;9A)IO."'HF[A*Q12\_0F9JT9GUS><6_:-ZN;L6IT] +M0+!W82]ZZ=QMMU1WN]_.66QG>K<6G][N3^6_!;SY[7YG!ROVW?UR4E5_4[0< +MS^)W],&?T-^+>6:_^_%596>XJZXSP.$K=%?"S9ZEWAAPW+,3[LEJ;Q8^&S"- +MSP:K##S,U\L*?>:)XWSIF=AGGZ]80>C+`U?!DY]=\.AG\4M#TPFN@_?&&5JY +MAEAP&+GX"@EO:55IHL%%K>!DOP%5"`.MTZ0YB^'Q.QDY-3SD%PYO"*=JBIKL +M\)Y#/3PE7/0K*=&$`V*QK;!?TRPD'A5.A;;$N\*YT,1:I;PC&!>.%M*WJJ%M +M7<-P@JLQG/L+)#@/.<-]\?(A8;PU7'*B#1>Y.L0)B.9P3;0VGKD)#\?-\5PU +MT4)7,1`&&.GJ#\=%LS>IKOAXDJL_7B).=27([4CCY +MKE)@=;1''B,NDE=(JSC-P$!QECRYY2ANEU.*BUXAB5!Q/K`E42@/Y<0?>!(5 +MP(6OKR='C#/7Y2_6L;MKYXZKK3UD-4)E`E]@8.A1I277B=K'`)+4:1+$^LT +ML&:%#ZR%;).34E3!$L<-PLAQL$UOGLLQ09$(6Z:-\^A4Y;QURSF/A&7"HL=A +MT^QQ[CQ\7.(I`2//ZX3UX^IY_SATX&2G\E0*6\IU*_IYZS1?KI+`G09=@Z<- +M>$9/!3T%240.B3"1(Q)4Y!AZK,<*";?(%P90`Q?1OCQR!+6+7D@N"*/1ZV(E +MP^2EPJ>4'!-F)6>M:LDQ=RIJU3!DX;XH"Z,-TW)UU`2:=:SNCCALIJ?'JNF9 +MU&YZ*+4NB4I-IGN4Z^G1891R0+V8FE"O'L8Q(ID>.2-9_#`WPOW)IQ9/V\IM +MLJ)ZPM7$A4$L;!#*0JJ);Z1N2S6L'@2#:+?5DXA)U8H'%3':0<[2L3?W5/D= +M7>F@>1\#7Z"C0DO$A*@F%/:N3+FIA2"OT#<-#M;JK$LQ=:O?;E +M"M.[U=WUKEL/D#K&-.W5]_Z51@2'W+`LMK?(`;G02RO4)SQXMU*J@98T$NK="-/SM34]7/LX)H7K/P!N_]%B" +M]QA0DDUBYDI`AQK<>^_][]H2(5XA8(%/<#`?M0OL]W0W"C[=0)3QO#CBW7/> +M]YHOD$K^GH(OTSG?BPAN>+E[[;V(@QY@PB76H.3['A%#")WBMJ"D& +M^89\PX2JZ8\3RZ?R<_(E7>=Z@[Z]GWI/6!):!#%P^?0.-5RK\>B)(R/SM +M^S*!+$Q-7XF2#KKPBPAZ^R9^R(=F;_@OW2?LQ0;J&-Q]+41,*2P5V*ND8#G< +M^T""^KZ%7Z@7);A2TM(*_'*]M%.#7_P2RVL,X_A%^W*)$+_W`+07R*%U]^V$5GKU:PUNE5N,>N +M.0H?#->>GW/T79&@-5\(_8R\!,G.GPWSV/#TB_KE!:E^7(0N5]9/+^EJW97$T@G-'^R_=)4UKG%QL5R[E=BM/OM#5*^>K\:(*8#:+O[[#8& +M_KBLO$,J%N*/1VKA8OQA-(\/C[\T[>Q"\N?D"SPJ?%U\G$9XX-,W!`CZ@YR( +M_DA_)<"P1(CPP"1/#1K"_NB>>U=I:XR%7ZG[.Y[2_YR.#3_A7WMQHF7\2X9\ +M*>LC&(*@YQ'5^$IQB/[U,U$)U#\%D?6/V!"G?8/0/%]59]]V+-\O._C`0+$" +M.+^#^0&DP/J/"='^LS[2&/"[)H3`[X1PU(?_B_==`Q^!Y08APR0P\BOR<_Q6 +M*6>8?+_0Z8"4A=@[A'S6"9$JE4=6ZZMM#.,T__`EA0]+9E6+*X`242<$`RX-.7/YBWP/U>Y?:`W%^#!'\V$+C,&`0N +M$0J!EBFM!2)PCKD(;`0:`3._TK__GQ7PF7`R2ED"?T>O2(9.H'[V11`*A":Z +M?Y"#X5=58*QO5_@*I'O$`F-]$\):X-T#%QCU33OZ`FN!P<#ZT8).O,5/[(>2 +MD):!J(1F8#_0N/D/Y%,Z(G]3Y0&Q8+)3:PE=FP%#!C>'Y,#BX\00] +M!1>"E(>&X`[R![SQM0A60"F*H5:?S&3A(Q@(83)*C+S`5F!R+V%OOG)$#;]^ +M?V6"*02:(/I/1320I!'6`EDM0(I=[_T.#FPLQ+U^'IVH4D$):%/071E"P%?` +M#*.FJHLN[Q(8",P57'-X!8D4ZU]K*<>!TT@65':Z$-&"P=(/#0A#F^#JH">U$%PT&/]M!_=M_;8C<.HQ/)C8&CE*=^?!Y\%0\'HPY]$>1/6\ +M!RN&NN"33!Q7EF>0N`\B$O>#=D#D@'\00*@O$!!241.$"$)EUH)09]`@?$7) +MB2"$1-40L'$R1N/7VYS>XSBKY=]:(/D3'V%B#*:5>5^,)D)2,%?0K]B:8A&N +M@N%6,,(1EXG0#SP/O!$J-\R^5LM_X(_0_!(D1+!<9XN$P(+-&O^F`M!G3U'[@29K:,"ZQ'A!*`GQ)L.,?R$UP000Z!P3.@\>N_*A&/!BL*[@J;!42@H:$TV +M(U"%8N&QHZ:04WCP]1;.)\"%I4+BYZD0G\@!WOBR"EV%HL)88<"75F@;N!7F +M"OFH'L)?Z#ESA\!:A<4,"R_#]&#-L`U+64@9-/,^"W>'BL?Z[II7;XCV'`QO +M"[^?AN%1X<$F,8P#,&&2"S.^2L/)H::PO:NG:3HN/8&&Y,^,9'3A@\`ZB&OF +M"[<,^\)![![4;,C*"!A&"F.(!<.#H2>Q*[P?M7TP#-4@#L,\%<2PN7D.A(_` +M![6B[%'6<`.18WB`\SV`#($/(D,<`^VDL%`?#0D_C@JU`*&!"'R]G:%V)25)@QU1P�_$ED,5\?701KP5O#'F +M!3Z'S5/1(1J$="A],!VB#M\LJD-?93S45,&7TKS$#@ECL\-C0@"22C'=S,=R +M6Q44C\]H(2SL\#I?2*`*#[\`Q$,I@/$P`8`\?$(N#_4*V.#GH?&AQ<$WF!X6 +M3QD7F4-/XO90R^H]!!]^6>D`XT/P8?[I?#BU2!\V"T*ASE?WH0XU?MASH!_J +M".^'XYSFWO[P;II'_!^N./LK4@'/Q$UI5&!`;!XF$!LP"\2+PWCX@9A]=+Y. +M$(&&%<0+(L-U'M6,2A1B*@M#B82"X:)6D148K:8-\A*5%QP8=T`L43%`*D(8'Q+O!#G +M$@.5S5:/`L'X6)Q&+"5V!CV)QL3MP7=Q/#"E6"9:'`4%SD1HH@0X&4%-A!:D +M*!8;V<1M8C=17#*<+1&[9$VP5V$4+.O@U$F>5:Y6EW:G!D=JI>N`ARM0N`S' +MA_>)/-]^HNXSH`A&("@.55:-",4$P!F6H6AE>2@:/>M;$L4>)@RT^791)(!E +M%,>OCHF.8BCAHW@9'BD"#=6+9EYG:--#I)/Y%"SRL>[R@*(NDIJ@SQ"D> +M^U:560:>HHW`=LLE5>P&%4^5S4(P0V31J$@`^Y=Z@N5_U"\AF9ZMVH+?Y/1: +M%8>Y3IJLHA/8K]=5K&5^4@>/?,I\HUDQC)A6O!8W)W6F!@ED<:&Q6SQ7A".J +MAJ6+.H0I\*VHSEO1#9ZR)7O&+\MC))4X2(12]C\5&+E&1V+!_>F`8 +MCBV+"0#,(C)CLQB5Z"P&BY2^J^,-[4"3TB==Y!NV">.9#\O!8^ZQ$2A;5(+R +M,D>4Q$5M86_1>DS0?%5.CXV+2M#D(O:XD5E2FR=_4527,(Z$TR`"_ +M/G66.(G(;TJL1*51.(9I#`-H&J.B%#^!RJ?Q,!!JM#)E8ZK:Q%^OS_3;:/L*-9H!QXU!O\29KU*XJ +M75Z?T,>O);QQ!#EO1#V^/46SDV&0U,OSH^!O[)AT/GS#3V2I;3;8;I1P%'\L +M'%VK$:R\*7A2LGQ\O,O;&X(Y9A[&>5M3N6##00HH/@Q][1Q[CR,S@&'F.12TPYBFKO)GH]H!+H +M0Q2/W!/&H^,1\E@$3MM6`"V/E;\?\N!1\TBAA"UE9^>88 +M'O>4J0CP8'J*&[NU=#V>`6"/X`4!*VR1]OB&1/M"+'./M,&6.944U7G*\02V.H-I7R<(%.03H`59`L2!?F"C$'*B.,ZPU0;I,<`![GE`%`N +M/F>,/D@OIJ)224%%]C;L)S8Y1\C60A)R%E!;6 +M#+.0Q($MI&=(=.*%XA$-ELL#8TC*0AE2"G"&G)JJ(1&A6`:1`8@2#CF)%#X6 +ME!.1G`)#!3WFZ]YIA061(T4Y)"5R"RI9QD/R*=6`-^`\AW.9P"MI;"LW +MF#.1HT&Y,B<2/=L\`$4V(S7,H\@(5BG2(;JA2D4://FI2B17))4@LRF+I$5J +M'EZE0L1<9`?9"N,ZKM3L"GK&>E%B)&K`&`F-Y$$I(T$%S$AG9-'Q3#$*I4:: +M0D>9C+G9A3;R\\"-)!9X([]\G@-QY-M()6N.1$B +M$V"245F'@QBA7:J5C(OJ)"6U/F244FDP%2RQV*UL$I:-;&2=(!*LXNB*YEI#DO>!L:2;M>/Y0KA+'F51`&H +M)9-_6T#"P.SW;HP"B$LR`>:2N".;22P8T+P_,'_R)8$/,U7?+ZI91&P4$&LB +M!0R3E&9)/J: +MET63=$G2Y&EGUN``34U>3.FQK,GGL&OR)Y.8+!K,)LNM8IKCX-JN;9#E, +M.?^+%V%.:&1@.%F,!`F;@W>29J41$4\F%LB3`$[S9++9-I:>7`NT`-B30YB?U'L2^7">#$:E +M)WN`]DFZ:7YRVKR?C`7+MOZ3?6#MXA2`!IMNB",<**<@"$2M@1VC9]H*'-!',K$@ADY`\MB1GO"%I>]7TXQ>\RB_,!^ +M_V"4/4P9)31*!4CV%''9/2LU/$I;@H_RF0*D=-8(*0\#^E'7T9$R'*JD/(PJ +M&9J4/2V@M\I(:/_0A7E2[556 +M&X&5^0*N)9*!$7RL3,4D*Y>5)1$=B[/2)P&ME(\V7Z:5SEBRKV^4H6KYHS[_ +M,L.5*%62JG;17*F105>J*\,#[,J*0@"Z52JO]$G0*VEXC$UX*_:2#[BOO/WU +M*]4D2MZ`Y<"2O%"P-%QA"1.6"\N&9;E8<"FQ3,50+%$],U^Q@\92NMBQ!*GY +M)=MOFX@BP88A97JRC%YP5J6++,OVB\N2L,@DP(/A-%FD);U++,[R3(A&SB7V +M+!W//\LF@IYY:)DI=43@OG9\<4NE)>`Y2?-(?KM`+>V5"FCW!-7R'USEVUMF +M+:V^W,`.1UNQ`:-,)@XPD\>6$EFS9619Z+BVQ"DC!MZ6K`$0LT*WKLSMM%N2 +M1L^[W\",\EYS):`'-;!RH+4-(M3"):AYT9*XM`6':)]6.[X@9;(A?^GEA5A* +M+OT$-=C19152CH"Y5$?U+#:7"Z?Y!%59N0&Z%%W.B$48IXR@RA(VEV>$7J7R8A`:\Z59R;G\611++[/-(@SK90X'L>@([5[J'5X#]"_Q)6"U>52^I!)( +M@="7A.CU)2J6%@DJ)>=&`N>7Q-=S[_SMZ!"-WE]B7/R7]V0`9C$P2K^=5I)L?7FEE4KAMO +M,X&+IM3(:%"S\$G.Y!!OAM.9]5W<\`PUF2KYVRC_%KO'UU9M@ST3,@PKK*0< +M+_F94F4-Y#\32>"KT.[,-7N!`=86IN3OSE9%7Y*_M:LI5[8-%>S+#W3E&F: +M5VJ:>XN;IAU-IXG5+,222ZK$0HF@YA-AJ`GQ*FK>,'WY-1?4W.>^-&98LPG8-)'>&_.>\5-RP31B@XA:4&P& +M/TA&JP-"YK1AQ=D='';R>/D#">F4)GWWM-GVS+G&25D+3;_5LF@3-%#:C#(F +MI%6;)PG6)O'+?55$>GE8#?U&_> +M<_B;0FA=;Z\/%VN@&(T8.!F%",XS=:Z2P2E&>'#./".<,FK_@(43&F%SK39J +M.-47N>9+PH=3^'H59;YUF:HQ)DY]8XJ3)D*B7I<^YF+-Y@%IJC>8MAP(":C> +M.'.<[M.F8H\S3@WDY'("^6:31@-0NQKE5K +M&Y"=M%-/,+/3%GM&:(5`.Z6=!CGLS[636I;Q?-UX/.N""Q%PYX>5G3/NW'B: +M.SG,1U1U9_.UW5F0/F_N0M^$]$[&I_`/WVDCTWI^F(YSMAXGFTK'@Z$JW+&$]IR\:3;LGM_'CF +MK/NO1EZOMT):79R@AYBEY$1>OBFBCG*^CHA_G9KG\X7DF +M+'R>!(8?@]R7-71/0)_N$8J>AMCZ%M+3]ZGT+%J/'=MZ#>JXM>4Z34IP?9J: +MI4JB64\$J^5S+GE\;#_C=Y$3X%9_*W%6*FVT/DBS/4&GJ8AGLD9Z[OFX2T.K +MHY\E]LDFCMYS;\'W+'?Z/24ZJ=?;P#E4VT#X%%8G";[*PU\1P^N:HGJ>YA)' +M/E\/L`''TSX4U<;U3/YA/J5\0F,DG*F.'VK?^'R^]@`6HD]KVW/!]`F?)!.G +M/ND4_`?6IZZGI?'Z='7*/@UE1]%TA^U3:.D@R'W^$WF?5A`C+X5Y,RU@71,6 +M7(^?QTV--/-S"[QGO36HDFT$4X+J9QGE^MG\R'Y2KK>?$&KOIXKX!FI=M7=2 +MAY$,YD\U8/KSK>0?8'_*.GT>\$_YIYB*_DF-5L4^DGN<^T]Q8@W3_XE."(`: +M&YJ"!%`ZX0%4Z*:Q\,=&I5?8!QJ)!>VPA/4!A1D&1$F205@,:!59`WKZ+31U +M0)NL/6P*!>C!0X)3+8':#%&@K#D5*)#CC.H")?^Y76*@=X`9:`O4'ZLQU6SJ +M0,.H5%"6YP\4R%H9B58,0;V@CU'6]=@Q"3K!9H(F2@]HN.GF@6XZC$W;L(*6 +M,K.@"0#87$*)0.D0B<>9H.>L2L4%BH+A2UJ +M3FRASF6YM2(;.KTT30CZ0NF$'6)@H7)O&"JHYAD80P&+15@0[6A!@G>LL]TV!H7%8>Z]\BAYE#Q,W?`EJ`.316T +M0Q4=[U!2RY*XK-R.56.G25U_F6M\:&@:9YL330::(A^B`='7X&"`(+HE88F> +M?Q*BR<[$*4.!Q,SS>\U$1+.7$U%QA%/!(JK+V,`810T&4XJ.*,_W(SJ7#(EN +M%D:B18D)@TD46X$2?6/,Q%BB0E0V3*4T.CH3K1O41.=1HFN=**"+,+I#^(DV +MI->BQLZV*"V-)%,KW:E`6HT"%VW"M%VT&K,Q"([6 +M1Z%1X]R_J&=4`M6OH6GO82<'D[LHGV*4,>H855975$6HE%$6[_OY,NK6TXP: +M8CFCU(N;I2T!-)H`G:"\H%6H%E53"6@,'X)"&A^W9\,[,J(W4/+K/?H^6 +MQ^*C>FT$!>8@5@V-@ACJB,R3*("\,W^TJD*:^(\BCLA7`E*GJ."Z28T@G4LN +M2#XDMY(;(:!840HP!5[<4`&IP%?`*@`20`EH +M!9;<6.XLMY:;*P!&V`ELN;_<0($9]T6@RLT1\`B0N77<9VX>MRWSQUWD_CC4 +M`(;<-X$B=T&@)P#FKG,'!9K<%(&E0%,`+!#EG@IX!:C<.6Z*P)7;SDWH+G0; +EN@_=B.Y$MZ)[T?E5&IHH&Q=N>_C&G +M-$G]+L[\,B<7%8&$NO5K31*Y>"D^*ZG,Z=H```"KU50H$1^1S``!GP&@'P`` +MLZ042+'$9_L"``````196OTW>EA:```$YM:T1@(`(0$6````="_EH^`,7P!I +M70``;IBIKOMK%/A?-TZV0266G?2,[/?\,JE6` +M__C/SA[W1?*2J9Z!O$&YKI)!H8*&L&E>0J^FIJ\7+Q<`%!+!PAHTY\490```'$```!02P,$%``(``@`"(2# +M-P````````````````D```!T;7`N8VQA"%3```%!+!P@+ +M(*8V:````'8```!02P$"%``4``@`"``(A(,W:-.?%&4```!Q````%``````` +M````````````````345402U)3D8O34%.249%4U0N34902P$"%``4``@`"``( +MA(,W"R"F-F@```!V````"0````````````````"G````=&UP+F-L87-S4$L% +J!@`````"``(`>0```$8!```7`%!R;T=U87)D+"!V97)S:6]N(#0N,"XQ +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_zip_2.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_zip_2.zip.uu new file mode 100644 index 0000000..f8ada31 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_zip_2.zip.uu @@ -0,0 +1,8 @@ +begin 644 test_compat_zip_2.zip +M4$L#!`H``````'V59CT````````````````%````9FEL93$M2E5.2RU02P,$ +M"@``````@95F/<>D!,D&````!@````4```!F:6QE,F9I;&4R"E!+`0(>`PH` +M`````'V59CT````````````````%``````````````"D@0````!F:6QE,5!+ +M`0(>`PH``````(&59CW'I`3)!@````8````%``````````````"D@2D```!F +::6QE,E!+!08``````@`"`&8```!2```````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_zip_3.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_zip_3.zip.uu new file mode 100644 index 0000000..8e36139 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_zip_3.zip.uu @@ -0,0 +1,18 @@ +begin 644 test_compat_zip_3.zip +M4$L#!`H``````-=0SCX````````````````-````&ULI9/12\,P$,;?!?^'D0??DE1%D+EU0U`<*`RWH6\E +MIK\2%IZ<5+[RQR#V$ +MPMD`G-S]"G5'UK"\A8&)L@B:'!-4;V/_@&E-_X$T&6YHJT25! +M+6H,@E\H^L#HD*!@N;:319%I_+YX7ZT;JA/D-LCXD/,6I731AB<\Q=CZWT\//Y<+1-JL*"1UCLD!?AD +M[@*R^"+:%]PW$#I4V2Z.Q?2M^S`4G?B,L8E0C.@V&?0KY]]"H32P6`A)UY@6 +M;GA]P[<%01/9@W\$3`L``03U`0``!!0```!F;V\*4$L#!`H````` +M`(2N\P$````!`````,`'`!B87I5 +M5`D``PM$QTX+1,=.=7@+``$$]0$```04````8F%Z"E!+`0(>`PH``````(.N +M`L``03U`0``!!0```!02P$"'@,*``````"$KG(_Z;.B!`0````$`````P`8 +M```````!``$`=X%``@``8F%R550%``,'1,=.=7@+``$$]0$```04````4$L! +M`AX#"@``````AJYR/^$Y>\P$````!`````,`&````````0```*2!@0(``&)A +M>E54!0`#"T3'3G5X"P`!!/4!```$%````%!+!08``````P`#`-L```#"`@`` +"```` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_zip_5.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_zip_5.zip.uu new file mode 100644 index 0000000..9dce452 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_zip_5.zip.uu @@ -0,0 +1,242 @@ +begin 644 test_compat_zip_5.zip +M4$L#!!0`"``(`-H0?CX````````````````3````365T861A=&$O2F]B7U!4 +M+GAM;.U7VW*C.!!]WZK]AQ3O8["3FDU<<:9:-OBR2V+9@"]O&!1;:X$H$,') +MUZ]DXTMVXPFIS,[3=/DBB>[3TE&K6]Q^VT3LXHFD&>5Q2ZO7#.V"Q`$/:;QL +M::YC?;G6OMW]_MMMDCTVARF-A4.#-1$7TBS.FG*TI:V$2)JZG@4K$OE9+:)! +MRC/^*&H!C_2"QB$O,KUA&)>Z<:TG"D."[QH[F\?4CTC!T[56PFXR>H`MBJ)6 +M7-9XNE08=7UJ_S7>6GVA<2;\."!'J_!]*^UDL7O#.#.D5%_(5UU^WEK(FCS+ +M9829?C#=)%G(@SPBL2A2*DBJ'9A;_P#F]@ZUN]T&^8I)Z:4?4W$1RW9+VRU. +M/EJ2#GF*>$C&L9]D*RY*(\]G.;ES,$J@:T.P1$_0LV%1H`AZ&/J`9F`!N`4L +MP<1J_&_HN;#`B$'W"D*0XU:@[!*E/\?H&0YBF@"+`*QE!_1KU8>$%NM

    ;*(`G",>5?B +MB-DD9%Z/%=+?GZ[I]9R)MP;SYMF?>'G8M0Q_C9-&X`N<2;6ULC/!LBEC`[A,2N8`=#%CJ+2X']XO&B$&G +M;\QB5'R">5O].-[*]`I3Y:;6K7[,T[OVJT1_/O?+(M,<\$6;)Y1DP%BG+$79 +M:>J_D-6V*9X3J2\K:%/6%K*4=>JN7LFM17R1I^3$H:HT-@FI/Z8OI'3TD`A9 +MDG"8\H2DXOE$Z8`RH:%859ESHZZ*W7\G_MI%5;<]0I,D%XC&YZB$7/`Q8200FOX^:'D=V.+*C63$ +M?Y)WBK>P2\T'R_H@;B0#P)$DBIC%Q?89UC8LA3D?JT +M$@]*?W\A[<*'YKOB&2>FNR=W.U9_[R`'LASG\<.QO=ST7,OKE!O'TW/:&UL +MK9#!:L,P#(9?)?A>RVUAE-"TMYTZ&*R%7H.MM":S%"QOSMY^[KIF.PRVPX0. +M0O!]XM=Z.X;GZA6C>*9&S;51%9)EY^G4J,/^?K92V\UZD*Y^C)[2WML>4U4@ +MDKIL&W5.::@!Q)XQM**#MY&%NZ0M!\B>'&>!A3%+,"L8+HZBO@Y7IHMMP,RQ +M5Y_:4?RDS3GKO-0<3Q?''(X/NZF? +M@O3X5F(X@0D=!W%L7P)2RM$GC&KZ7/\/G[L=5+!Y!U!+!PBV6O$]TP```,@! +M``!02P,$%``(````VA!^/@```````````````"@```!$;V-U;65N=',O,2]- +M971A9&%T82]086=E,5]4:'5M8FYA:6PN2E!'_]C_X``02D9)1@`!`0$`8`!@ +M``#_VP!#``T)"@L*"`T+"@L.#@T/$R`5$Q(2$R<<'A<@+BDQ,"XI+2PS.DH^ +M,S9&-RPM0%=!1DQ.4E-2,CY:85I08$I14D__VP!#`0X.#A,1$R85%29/-2TU +M3T]/3T]/3T]/3T]/3T]/3T]/3T]/3T]/3T]/3T]/3T]/3T]/3T]/3T]/3T]/ +M3T]/3T__P``1"`$``+4#`2(``A$!`Q$!_\0`'P```04!`0$!`0$````````` +M``$"`P0%!@<("0H+_\0`M1```@$#`P($`P4%!`0```%]`0(#``01!1(A,4$& +M$U%A!R)Q%#*!D:$((T*QP152T?`D,V)R@@D*%A<8&1HE)B7J#A(6&AXB)BI*3E)66 +MEYB9FJ*CI*6FIZBIJK*SM+6VM[BYNL+#Q,7&Q\C)RM+3U-76U]C9VN'BX^3E +MYN?HZ>KQ\O/T]?;W^/GZ_\0`'P$``P$!`0$!`0$!`0````````$"`P0%!@<( +M"0H+_\0`M1$``@$"!`0#!`<%!`0``0)W``$"`Q$$!2$Q!A)!40=A<1,B,H$( +M%$*1H;'!"2,S4O`58G+1"A8D-.$E\1<8&1HF)R@I*C4V-S@Y.D-$149'2$E* +M4U155E=865IC9&5F9VAI:G-T=79W>'EZ@H.$A8:'B(F*DI.4E9:7F)F:HJ.D +MI::GJ*FJLK.TM;:WN+FZPL/$Q<;'R,G*TM/4U=;7V-G:XN/DY>;GZ.GJ\O/T +M]?;W^/GZ_]H`#`,!``(1`Q$`/P#TZBBB@`HHHH`****`"BBB@`HHHH`****` +M"BBB@`HHHH`****`"BBB@`HHHH`****`"BBB@`HJ+RG\O;]HESOW;\+G&[.W +MIC&/EZ9QWSS3XD9(D1I&D95`+MC+'U.`!GZ`"@!U%%%`!1110`4444`%4QJE +MF=4;33(RW2J&VM&RA@02,,1M)PK<`D_*W]TXN44`%%%%`!1110`4444`%%%% +M`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444` +M%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4 +M444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!11 +M10`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%% +M`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444` +M%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4 +M444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!11 +M10`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%% +M`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444` +M%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4 +M444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!11 +M10`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%% +M`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444` +M%%%%`!1110`4444`%%%%`!1110`4453FTNSF9FDC;+W"738D90TB!0I(!Y`V +M+QTR`<9H`N4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`44 +M44`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110!__V5!+!PC?FNW> +MUP4``-<%``!02P,$%``(``@`VA!^/@```````````````"0```!$;V-U;65N +M=',O,2]086=E!(7($,8L%CZ=^_?W_VQ]O[;G_2Q^0% +M/2W6E$RD&4O0*#LL9BK9&D9>L/W]Y<6NQZ,,T4/SXBB)0X9*-H?@[@!(S:@E +MI=:AB9W1>BU#+/T$3JHG.2%LLNP:_,\,]CE'>DAU#JJR&DZ,SXQ:^,)_7Q>/`_?=N!F=6^/6"J'P"4$L'"%!53P;H +M````/P$``%!+`P04``@`"`#:$'X^````````````````&0```$1O8W5M96YT +M:SS^/_T>)G(E\HNT$.!: +MYK:,8=CW4!A`<")D4=H84LH8\EUA55?*Q+"T=G&`L[.\+BZ6Y0&)+*J8K@WGY,N($BTLE>-C"&> +MZFQ9"V4-IOA2&+UL,F%P>VZP-TVFXTDT[G&?\AZG">V-(A+UID-5,51/9/WPDEAR(WS(9C9NTK,9+VL4BMUJ^I,*P'!>2,+ +MJ6YBZ(51IWE3N'6MA*,(@E.52_<@1XGTV3XE=!`&W',)&SC9+;8K)3.=BYEM +M!\?P_7']OG[X?'F"`/\K`J&/@N@G`+HALB401/L^'031X#O9;O]`2+OX;P0\ +MA\!GOSS`..(_74"9SWEG`Z]5STB[>JT5./U#X>/U%5#P^?S6@1CB[<\[W/T" +M4$L'"%=?-U>$`0``A@,``%!+`P04``@`"`#:$'X^````````````````1@`` +M`$1O8W5M96YTF^?M]U]]NVLT1]VV3?^^ML'OJ?==WI9>.?SXX]UGSYR3]^!EZ]\ +M[G1#KO3\^#_<.T-RZD$BT=6ZKKRJ]2WE*UP^ +M3$2IS3WM_=\LG?M3$JM>Y;8;-^_:87EFRZ=(M)3R]D]L[>_LN>3`7:^2N&P+ +MC_=UMF_OIP+22/)P/YF=VV[8>M71-XI)K.;MW5_OZFC?\O1K]R=Y7TNXO[:+ +M&R31NHKK.[A>W-6SXWHU3<.\;Y/$RI>V]6UN[Y<'UI"XG-L>'.MIO[Y_0X&X +ME,?OX_%6;WM/1W%:OI$DY2]XFQOZ^[;OR)PD'Q]?M?O[!SKZ7<=;G^/YV?M_ +M:!@GW+[2/MXN/IY&HX?H7[>.1X%:):-<#FP)7!9:\35Z[@>C^D\Z* +M'GOYFK\ERARG#!WCJF&/==C#CG-[\<1X[L\6SFOIM5M2-U,W>9P&B4PJI]F\ +M:3L]E-U'6@R3BTMI#E^][#K-QVG@#81;DX6-VV35_]Z^K]BX;"DER-JW;V(. +M9"_*^1E(F(;+=0G+&O!]WRLH'VL*?\KA-GWZJ[W/A^!_8T8?F(7_TX2=\ +MW/XW.7LS>0<*%5(EM=-@QTB79_?^2%\R'QT01W(K@WAH^6\]F7K?J[')MK_ +M<7GI:G%89&[_2\H_5,4[/)3.WWA8N)=U\4>\Z;!0[))BEUQ.:=DF+ME5Z4)5 +MLJNR797LJFQ7Z4(OV55A5\FNBGB3*)M`E('/-7J`OQOZ>5$RXYG_XKJ;5-+) +M(#^_-R%^>Z+\G.;1#)IIM_S&?A[Q6QQK)N=9?E%F<*3,ZY2D:EI(3_'^$E1' +M%_.;LX2.9UZFR^DR\E*!L]S%/3?R#+=1'[^M%A\IZLS!7NS?UDK\!@L>_S"/ +MSJ.6A_TC;N%^7/P1?\KJIL72?6XW![%(YP:+TMU?7J=3]5TCZ^.9Y;/WSU;Z2&>]<6/ +MQJ-5T651.=A@B!A?//L[VD4JESU"X9(0OD?54(71;T@&3^3HN:-4?VY)_0OG +M*BM$6UTD'*VNYCE45]76\$3B3JENI:[I*S5=<[E"FA%0'MHW,:L;%!=_VE?' +MR]]^NVD7S>9K?7]B_FIE=6R+LBFVR^HO?,GU8MD)U\_+]'FB*%8O5<1:1$)) +MQ*X4:@E%3=.MNP^+6,*T*BLJ$Y6K*_=7NBHK*:H_SA.."OF;Z<+A0JDP_PDQ +MC8IY_O.XF83KH1)WQ6%A/))G%>;)OG_B[[DH_F3]R>-M]2>#(;[PY^Q/7BHKJ*UMXL+7V>=9Y,Z-NN,7;H1]&?@* +M5(?MMA*WN\2IU]6XW96A<,%\S0SZ)4EQ*ZZ\G'!85ER*2U<]JJ0'"[V&%M*+ +M\N2@-Y3K,G2?UZVH+I=F!OR-JJRI?J_;X_$4:`&/IUS)X3NG9WY!OZ;OTGRB +MNGAN;76UV^W)K:VMJXZ$J^U#SII5$W>[X_&BFIKJ$D^\UOFTQX6OVZ)JWA7N +MV77RXBJW%JGQ^35#=DN*41J\(A*\1&F/F`=YQ,7;5;FL,29'OE#3&W09+G]L +M>L3HC`;GY88#JEQ`_$AXG3G\T"[QNW,1-?)9%U=B3/(::_A2L3N=7K"GKI93\HQ7\#8I6I;@\:E7I_'JR\/^:Y7 +MM4KO-'.&G#?-VZK[##-G=I#[HF*.JDWSSY!C`?Y;;8,T:WYN[$]5.6@\HL@> +M0S&\VT,^51YP75EUD9Q7IL[4"B-!/2]H5'KT&;-4N7Z>,C.^JLP=ML]&SYR@ +M-_ELPOPT7D6;J8O/QKET=27GKVW4GG?=^VHE$T,\'OL4)CHB]EGP6;OY_D>B +MD5K&I\RG6AWA]KKL?8C$2]Q\3>(>7FI;%@>-,I\[[,[S2_X'K_.BJ+Y]94+_4+U +MZ_?P[:NK#;@N7[AP^:)&US>"ABG[XV]+PB0_86S;"FY[A\1M5,K_`H7I_DTH+3W'[=,MQ:OLNO\ZW7\\H+7%;8 +M_M$GP-?L-#W/WY@ESI/H/(B>>$F4+\'$Z3KG6^L\#M&)ZU-;PU?+N78!^T%4 +MW'E!(0)=`:$']:5NLR<:7"_4.0M$W9R0YI)*"X*R]:0JAR-:04-,:^_0_-,J +MW`&OD1\.-!8M*C,4;WY5J6>YDCLM,#U(Y"&-Y_0VSTGF/9Y2W2Q^5<\_F.=?F`@W7CB)^(?.L&32:4T\UN5LB1;0 +MRDPA_.5^L5Q1P\+GEW/TT/0%&Z1(V=7A.0$]6&X:*;X`><&OJP&-;\[BH&\# +MUTU^$P.\X6*_J!)RQ)*LF%?58SY=BS\^TY6_Q.W3U4A5KL>E:Y'.F;(>71B5 +M4+^^>R +M>U*[L__2S;.MI7W]-PQT=W;ML*YH;FU9L7&EM6Q;Q^8=`WV]W9NY<[Y5N6A1 +M33BJES7P!+;YP?=1/-]``=5,G==$.;KN"FJF56F@%;:257%]&VZB# +MQ^_@47W4RR,W9[>'/W?RF+6\12>7ME$[;Y7BV@!MYWY[ +M>XNJ>Y7&KDWFZZAI=>ZNPX=.6?MZZ; +M>)8ZC]2<<^N%5++U<;*,W%]Y;2 +MC]CO;R]-;XS[LVNG[#2^E1WO]SOCTY/'^\?-[-HI.XVG +MLN--TQG_X.3QYG@HNW;*3N,;V?$AITO\:/)XWW@@NW;*3N/I[/B`TR4ID\=[ +MQWW9M5-V&G^9'>_C+GO-595<'")[VY!AD&Z\0P:77=,?SC]622TK[5$?&/O' +MO$SS^\GPGR7_)XP]QHMEFN0W1\G\^+%B-Y=GAT)DALY0Z./'2LU9_^@B-I*@P5>& +M=[_RM1OWSQF_5VU;573'"`V>4LFBM"1G1E9+"8V:A#G4>(2?"XN^^BWZ`EGB +MR1/JG/N^-GQ7T=#0_D*>3H,X\UJQI`Z.J%\:-].#IV*)`\;!;VWBPXV:E`Z, +M6M;0GB)UJ(A7:R6KOY]G?S;H>29XT\VFJ_5%9?V:-0.W!^?N^>JH??/KQP1- +M9'!X^[^(4I3FO?)5R]P2C6UR1F6$D9%OV$_ +M4A>/%UM+$L5C2_;2P?&#ZL'2@_,K2ILW[+V4;AN?>%MOR_!UYIU9I`8SX[2? +M2DDG)2TL&K(:56M/14$Z^U*GK?B82EQ-FYWC,TS]'NG>PJ(F]4ZIR3J@%B94 +M:^+M5^A6\Y;QXF;S@,B,"#4P+IFW*C0X)AIH.-&TO]W0, +MI1-%IKI7*J0AIT"7DG6DPN@7V8$-9T:;K()ZI;DA-'S309H=>#W1.+RZ(O/KK[C?EH[>'!-\S\_U;ATJ/F(.6A/ +M:&E&\"N0&!R-"=YF>.CVVT9X)J)>%2-29F'#`^'U!^]L&K*6\M!"\>;==PZF +MBPM&ACQCNG6G>FBOO?MXYE:JOU71K)522IZ^ +MT#^:/)M\)_F_R9/)7R?/I#I26U.=J:Y4=^J:U+6I;:F>5&^J+]6?NBXUD-J> +MVI':F=J5^I/4]:D;4CD9Z5OJ.])+T']*/I6/2&>FL]*Z<*\?D:7*> +MG"_'Y6+YN?\#4$L'".*$;,_\$```%%@#`%!+`P04``@`"`#:$'X^```````` +M````````*0```$1O8W5M96YT&5D1&]C=6UE;G0N9F1O +M8RYR96QS98\[;@(Q$(;[2+F#-7UV%B0B%&$H@"(%4H2VH$,C[^RN!7[(GB`X +M6XH<*5>(Z7B4\_J^?_Y^?F>+LSNJ$Z=L@]\U?$OW-H7%_/5E +MMN4C2=G)@XU9E2.?-0PB\0,QFX$=Y2I$]F72A>1(2IEZC&0.U#..Z_H=TRT# +M'JFJH=2S:,`-"[4DA)O=:KE?NRB7_5=3%32HSU;#MH1L+I&?`CAK4LBAD\H$ +MA^>8K]X)%G5,UHM8````1&]C=6UE;G1S+S$O1FEX961$;V-U +M;65N="YF9&]C58U!"L(P%$3W@GH=Y#7K@U/9TYQ,S? +M>9XL&<#?HF")N9!4=6,R@)G!O]N4?`%02P<(#(8J/94```"S````4$L#!!0` +M"``(`-H0?CX````````````````F````7W)E;',O1FEX961$;V-U;65N=%-E +M<75E;F-E+F9D%W,%HG]&TD%)*G*P;"(0P^Z)Z +M-!XSXP>V&I*S99$C]0IU=GTL)?WZ/NGK>EMOSWY6)\[%Q:#AL6E!<3"Q=\%J +M^)1A^0+;S>)A?>29I&;*Z%)1=2D4#:-(>D4L9F1/I8F)0YT,,7N26F:+B%?BKT]JYQM02P<($KD,RKT````&`0``4$L# +M!!0`"``(`-H0?CX````````````````;````1FEX961$;V-U;65N=%-E<75E +M;F-E+F9D3"HI(8S?B`>P)))W8@,G4_$COYL(C +M>05;H0O!]7O?]][[^:KJP=V*!X5HV2LHA82"O.;6^JN"G,QJ!_5AN:A.=J#V +MR#H[\JFA>QY;5(RPCPJZE/H]8M0=N4L4SNK`D4T2FAT.?<2UE!N46YA,L^1, +MAL+7TG`.FA3@'$4L\6=0F)8UX(3CWR=C\@%02P<(`"(GQI@```#.````4$L# +M!!0`"``(`-H0?CX````````````````+````7W)E;',O+G)E;'.5D,]*Q#`0 +MA^^"[U!RM],*BLC6O8BB("QK[Q*321ML_FQF*O79//A(OH)9M:`K>_"89.;W +M??F]O[XMEI,;BF=,9(-O1%U6HD"O@K:^:\3(YNA,+"\.#Q9K'"3G&>IMI"(O +M>6I$SQS/`4CUZ"25(:+/+R8D)SD?4P=1JB?9(1Q7U2FDGQEB-[5H9>J0&P%7 +M=D)]&=3HT/,];L9LA*71A!M1W.A&K+-E^Q+QCX&S*@4*ADL5'$R1MN`3R&RS +MS4P8$U(._80*V*\PTPEJN$.66K*$5?Y)_=#VHWOTT@[E[>KZVZ?>X_.O1L#- +M()X17XKPJ_Q\\P%02P<(MR#R__,```"Y`0``4$L#!!0`"``(`-H0?CX````` +M```````````3````6T-O;G1E;G1?5'EP97-=+GAM;*62STK$,!"'[X+O4'*5 +M-M6#B&S=@RN")P^^0$PF;=SFSS;3I3Z;!Q_)5W#2"L+"MK+>$F9^WPGD/$#-J=K%B#6*XY3S* +M!JR(A0_@J*)]9P72MZMY$'(K:N!797G-I7<(#G-,#)9H&]"B;S%[&*@PJ3MH +M(\ONI]9DJY@(H352(-7YWJD#3_[C*"@Y]L3&A'A!#8P?<6@58;<@L;_@(<1< +MFP&4\K*WE*!T3].!!8F7_W#,LP-E3H"GV"S8*T3]=[!_U7VD$J@\+24M]B@Z +M:9?!G7%(-U>,#S1R"_.3>'I^/*`:FP[N+4`]A?AXLO3Z!E!+!PA?-651$0$` +M`.<"``!02P$"+0`4``@`"`#:$'X^,JA?,K\#``#G#0``$P`````````````` +M````````365T861A=&$O2F]B7U!4+GAM;%!+`0(M`!0`"``(`-H0?CZV6O$] +MTP```,@!```:```````````````````$``!-971A9&%T82]-6$1#7T5M<'1Y +M7U!4+GAM;%!+`0(M`!0`"````-H0?C[?FNW>UP4``-<%```H```````````` +M`````!L%``!$;V-U;65N=',O,2]-971A9&%T82]086=E,5]4:'5M8FYA:6PN +M2E!'4$L!`BT`%``(``@`VA!^/E!53P;H````/P$``"0````````````````` +M2`L``$1O8W5M96YT&5D1&]C +M=6UE;G1397%U96YC92YF9'-E<2YR96QS4$L!`BT`%``(``@`VA!^/@`B)\:8 +M````S@```!L`````````````````RR(``$9I>&5D1&]C=6UE;G1397%U96YC +M92YF9'-E<5!+`0(M`!0`"``(`-H0?CZW(/+_\P```+D!```+```````````` +M`````*PC``!?7!E&UL4$L%!@`` +0```,``P`I@,``"HF```````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_zip_6.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_zip_6.zip.uu new file mode 100644 index 0000000..ef6d191 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_zip_6.zip.uu @@ -0,0 +1,10 @@ +begin 755 test_compat_zip_6.zip +M4$L#!`H``````'@3-T`````````````````6````3F5W($9O;&1E'1S;VUE('1E>'0- +M"E!+`0(4"PH``````'@3-T`````````````````6````````````$``````` +M``!.97<@1F]L9&5R+TYE=R!&;VQD97(O4$L!`A0+"@``````?!,W0!5#6+\+ +M````"P```"L``````````0`@````-````$YE=R!&;VQD97(O3F5W($9O;&1E +M'102P4&``````(``@"=````B``````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_zip_7.xps.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_zip_7.xps.uu new file mode 100644 index 0000000..cfc8ecb --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_zip_7.xps.uu @@ -0,0 +1,357 @@ +begin 644 test_compat_zip_7.xps +M4$L#!!0`"``(`$"K-D`````````````````3````365T861A=&$O2F]B7U!4 +M+GAM;.U7VW*C.!!]WZK]AQ3O$W"2FHU=<:8:&WS9)3$VX,L;!L766B`*1+#S +M]=NR\26[\83,S,[3=/DBB3ZGI5:K6]Q]64?LXIFD&>5Q4ZE=:LH%B0,>TGC1 +M5%S'_'2K?+G__;>[)'MJ#%(:"X<&*R(N$!9G#1QM*DLADH:J9L&21'YV&=$@ +MY1E_$I2[QH[S%/J1Z3@Z4HI:=<9/=`617%9 +M7%_R="$Y:NK$^FNT17VB<2;\."!'5/@^2CE9[!X89QI*]85\5O'SUD)69(/+ +M"#/U`%TG68YX2$:QGV1++DJ0Y[.JM[$/+;OFM%[LW +M`]`!;F$,O98]B.U_\ME4I;V*,8=]A+D6$[H!E@96. +MZG&ODKF6?=HSOFG*O^27_#2Q7W<-&;/FPX-G\+*/XFK@VS(?]&1>>('.+@VV!:,G\8F4@R-9<<%>>,S36%IA>[D_Z+-"&E@-Z?QX/61"MV70R2^91`(XVZR"/ +MF(Y#YG59@?;^=`VOZXR]%1CUC3_V\K!C:OZXGH.I#UPV'-DN<\%X>)YWULL0 +MY[+E,-'&53T+)\-D?G4#SK6^Q5BV;D\G.@O80T(BU#4\US.\T0Y?WSCC^FIF +MP^:ATR^";_.\)7\<;VEXA2%S4_-./>;I7?M5HC^?^['(-/I\WN())1DPUBY+ +M47::^B^PVC;$)D%]K*`-K"UD@77JOE;)K$E\D:?DQ*"L-!8)J3^B+Z0T])@( +M++DG2KW1(]R4#TZ_$W]MHJK9+J&+ +MI:ADM_Y');OJT1EEI_3?.6?B[O7B)!"@C[Y"VA\8'71S%>)]2#VF%"/7EUSG/#'@J4A] +M6LD/4G]_'%J<,5^^\@'+DF5:+Q\WFY[3A^>71!>?6E`="JR`4D'=$U8I6-]\YU^ +M;*<47S?^#[-?\:;ZKW=.ABLA5Z#K;0FLQ0L;\[>?NZZ9CL,ML.$ +M#D+P?>+7>CN&Y^H5HWBF1LVU41629>?IU*C#_GZV4MO->I"N?HR>TM[;'E-5 +M()*Z;!MU3FFH`<2>,;2B@[>1A;ND+0?(GAQG@84Q2S`K&"Z.HKX.5Z:+;<#, +ML5>?VE'\I,TYZ[S4'$\7QQR.#[NG#VKF25)+%K\H]SNEOD6]@22FU-^#W$'I +MGX+T^%9B.($)'0=Q;%\"4LK1)XQJ^ES_#Y^['52P>0=02P<(MEKQ/=,```#( +M`0``4$L#!!0`"````$"K-D`````````````````H````1&]C=6UE;G1S+S$O +M365T861A=&$O4&%G93%?5&AU;6)N86EL+DI01__8_^``$$I&248``0$!`&`` +M8```_]L`0P`-"0H+"@@-"PH+#@X-#Q,@%1,2$A,G'!X7("XI,3`N*2TL,SI* +M/C,V1C'EZ@X2%AH>(B8J2DY25 +MEI>8F9JBHZ2EIJ>HJ:JRL[2UMK>XN;K"P\3%QL?(R;GZ.GJ\?+S]/7V]_CY^O_$`!\!``,!`0$!`0$!`0$````````!`@,$!08' +M"`D*"__$`+41``(!`@0$`P0'!00$``$"=P`!`@,1!`4A,08205$'87$3(C*! +M"!1"D:&QP0DC,U+P%6)RT0H6)#3A)?$7&!D:)BH*#A(6&AXB)BI*3E)66EYB9FJ*C +MI*6FIZBIJK*SM+6VM[BYNL+#Q,7&Q\C)RM+3U-76U]C9VN+CY.7FY^CIZO+S +M]/7V]_CY^O_:``P#`0`"$0,1`#\`].HHHH`****`"BBB@`HHHH`****`"BBB +M@`HHHH`****`"BBB@`HHHH`****`"BBB@`HHHH`**SIM'BE:9A>:A&95<#9= +MOB-G!!903UY&`*V)=[S4+F5FW-)-=OR=V[[H(0#(`P%` +MQQT)S*--B\UI&GNVS*)57[2X"D9.T`$97+$X.1R!T50`"Y15/4=/6_M9H?M5 +MW:M,JJ9;:8HZA6S\O4`GD$XR1P>@Q:2-49V!;+MN.6)`.`.`>@XZ#C.3U)H` +MR]7\2Z-HLOE:G?+!(55@FQF)#;L$``\?*?IQGJ,SG5[1=/DOI/-2%)V@/[LN +MQ<2F+`5:)M(6 +M2XBFBO\`4(`DIE>-+@LLA+*VTALX7Y`,+@8+#H30!+I.IVVL:='?V19K>1G" +M,RX+!6*YQZ'&1WQZ5@'U.3U)-2T`%%%%`! +M1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%% +M%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`444 +M4`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110 +M`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`! +M1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%% +M%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`444 +M4`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110 +M`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`! +M1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%% +M%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`444 +M4`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110 +M`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`! +M1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%%%%`!1110`4444`%% +M%%`!1110`4444`%%%%`!1110`4444`%%%%`!14%U96UXT#74*RFWE$T6[D*X +M!`;'J,G'OSU`J6.-8U*J6(+%OF8L!T`X'%`#J***`"BBB@`HHHH` +M****`"BBB@`HHHH`****`"BBB@`HHHH`****`"BBB@`HHHH`****`"BBB@`H +MHHH`****`"BBB@`HHHH`_]E02P<(%>T[FRH'```J!P``4$L#!!0`"``(`$"K +M-D`````````````````D````1&]C=6UE;G1S+S$O4&%G97,O7W)E;',O,2YF +M<&%G92YR96QS99!-3L0P#(7W2-RARCYU0]NA@Z:,IBHCL:WF`E'J_HA)')(4 +M#6=CP9&X`BEBP<_2S\_/G_WQ]K[;7_0Y>4'G9S(U$VG&$C2*^MF,-5O"P"NV +MO[^^VG5XEB%Z_#1;G\0AXVLVA6#O`+R:4$N?DD43.P,Y+4,LW0A6JB\?L'>I_0S5Y& +M9!/'--^D>R(V*8_S:$=WT8Y+--;>-VO&)VUK/1G;/@R%^:.#E`@Q23@$A7_K +M=6&&4U]Z,\ZJ?HY60_!K,JVQ+QF,DAC)]_5KB"0Q2H.D'[8VX4$9Y(F25$FA +M1++,J1),"0K!P9IJK'7AYXLS>+#>^%[7$.!/!4!PQ-DU`"H1BZ\`S**9DHOZ +M2/%4<:IX'$P1S4Q6(,$D2O+93*1:0P0-VREY!\?G:+FLZ"71/PEEM*2X``^W +M\@^O#P6H#&]!M6D2Z]K\-OX+M2U#9[%>0R'O9X^VV=$@OU7C8PCRJ[+ +MDQ@*KK@$````$``!02P,$%``( +M``@`0*LV0````````````````$8```!$;V-U;65N=',O,2]297-O=7)C97,O +M1F]N=',O0C5!13%!-C$M1#@S,"TT-#%&+3E$,#&JOD=O((0U +M((2R"\KT%?<2J"R$>,>@;V5!M86).S-\+D)"]OF=HHKBLK!GCQ(("4J@W:.X +MM*:H9M;<40B)IB+DZ%5BT!?N-SG'P5@'>!Y9`AVB7D0MM..AW:NDS#)I4KVC +M`MH7$:)NE)H*]&\H5A9\O9##5283( +M5RI,9DM')"H&_*7L\XI*0X5;6Q*T!2P^*\+@$VG1V1+>^.?$`^XB$9_M0!ND +MDWNP]VWEXIG`ED:>HM.@Z6#CAPON=)H5^LC3;),\]>A)YS6&[<%7HKX(Y]HX +MDB`WM!2HTS`O)X,\A34B$O&IE90*VFML=ZP-%>%Q?`$NH@4D1>(X68OPA:#Q +M(]&#@X8R`)I!$^EXZQBTCD[#MD*W[R>?V+!@+)Y']8]>(&/O'Y?R;\]]I1O] +MAOV^PGZ70!7]#AD-]OL:J-.ASH?:!'4*U%U0MW3CW6*_[[+?=]CN6`30[T"M +M[\;K\)_1\L_KS^O/Z\_KW[IP^\GC@@B6PKR@TJCKH"(XGL$@\*DC=?'>?GZC0N&Y-L%+6.B;DQS@.X@? +MX"MV"O!U=`CP%0G#?86THR]%!OH2>+BO@#_`%T/AOCPZW+<@/T><._JB>.RD +MB^))HS/%PV7-XF=D>S!&&R,>(+LECNE_49PA<_9]5N+I&R]I%E>ZGA+G2_+$ +MSTDNBD?"/1ONF5`'0NTOV2F.@KM2Q8X7BU62>K$KM)VA2B5[,*W66RR3O"J6 +MR&2^8I\*GXH>M3U(7]I$OT832FPOUH'XPS)&;L6V8@M&S9S/DK4]1IG-6/#3 +M%_J5OF#60AV7H%Z#^CE%4/[D0#*;.D+=I(,AJZF"O.8P@E,:[87,Z^T.^T4= +M05_2\=C@CM]YH3EHM9TZBNY1$7"Z;T;OH/5H'QF(/+$UZ$ND1/=P7[04JT!3 +M4`&^%K]B/8<:L#Y8+/2^B?JCM6@+;D0[43",'6/=BZ:B9&1"TR`GF@VYR28T +M'5])QZ-[6!^R&:]#2?AG!`&28[$^Z![D'>MQVIH&&AP'GUN")B&<=1KB%,5N +M0!Y"?E(_:2!\8`@_U5Z.I[>_1:%?D):L9?$SE]U.2]#]8UP::"O(J<21&0/SFCP=I`BHQTTCF-DA@E-9)Y +M$IZ#3"C$D$S&AA):*D8.(LA>7;C9XMC9VELEY]O9V:0R37B[0IZKDOHIW=U< +M74B_`$],Q4@C@H*Q*]CJ"\_]U?J^]6;C%*QQV=96BNB3>>OHUU9/?`KF45T$ +M.K[1<8G,I?R1/YJK':$4#1;EN\TE2X[UKO*9X +MSQ+.\9KK+18*^`Z4E[=[SYZ4NP,I]B-D?CP7F1A[U(_B'09*W#%W:F!/J7L` +MASJ!17WFYOG<]NI6#P"M8:LIG57#7/.H!P^5BKD$!C*N+FR].@D(!_H%J +M4J6,5$<$A6-AF#HB4J4D?OQT@_5NX>QIDS!WZ^4?UEKO8_26E]XJ7CWC\(KO +MVK:05S=E[DP<%1[2-__Z]K8AAZK-^J3L&'GBRMHM^]F570%::\#V,A2N=4^@ +MLBE<@&@*-!!)^+A$(L-D;LY=J'-OLJ9N']0*V)Q54A'CWV.[='Q-TN_MMXP6,#_Z"00Q$Y$&83XPV:&L)TM&) +MQZW85]3/H9>XOTCCH!0GH01<1^M$.2@;SZ*S1./@ +M6XF!-HBFH&K<3%>))CM,=*H2ST.S\!?HF:*Y#C/%N\B]CKN=KA*]^22?YR!R +MI"E"C)#80431N(`OQ"1"3"C%))*SDK.Y=IO;_C2>X>$>N6A0ZZ!6UIW89^"^ +MA,K97H@`*"<.K'^%V+M_%_[FTM-GM^';*>*7LX3WP]MDSP?M^.UV,6M7^"Y` +M'N)\>I^VH8K$*$(@\,1<"2]!(-&/ZB<(%&DP-=&?ZB]0BW3$,"I)H!-E$3E4 +MC@#TPPQ$&67@C1,81%7$-&JRH%(T%YM)+*#F"NI%@9A0)!3@`AXXIT#")_B$ +M!,<%&,D3DCCB"V!BT!:G,2')(P4B@A()2#ZB^8XXO;1^!"]M_AKW,IZ]I;AA)&JH7`?-XD`,;VD8FI(7TGU68_6F^=; +M6MO/PV+M/O4GA.;^O5W#I85J%Y*C[&.+\FN>V'IQOH-'^6: +M\_,V#'OC`ZLF?XBPFL'<,-GGJ7FPAFLZKI&IH(LK4FF]'65\@3-@=9,$22(D +M,R2D2,ZZLY3R<.N*?+"I6W.YG.CPA3@VV9@.\ZOI8.0$7[ACM7T] +M,1^/>!'A@2$'!ZE,(("@^PQ!.,$P#YU+E@ON(D6TA,9I3W#JF[GG!PS@MBK\ +M2;@@[*<&V^!JB4RE=($BR3.:<[3>'-YI#.2NL)!%@X#[0L:SP6\`]=Z#NMSYL?FA2\M6%:#\]KO$XN:S%>.!+^B,CXF12QXPDLQB# +MF]F-=I90M,2+D2(DDHAP42"L[K&;YUM;6]IM!@1@[$GA'.4&9UU4UQJK(2S3 +M;%S&I(_<[XSKMN78`,'4[_9];OWPM95[HX=/L3Y8B7T^PKQO810V9,G4AR^?;DM_@0C$-BV]>'3303#.+K"J/_BD%`W1!IK)%TA< +MHB7S:,S!:0`M$")<(!$F(5(JD:`3Z"1D%AZRKMV1"Z:L/N_1SH97\$JOXO(#=C-R:20FU +MRA6/9A.0+^\1&YM^^2L5<>\>R]XEL8=6`K(<$,X)DL!L-"S_,4Y0IQ@\S9J+ +M&ZEE3??;.BT".T+"6L1"S"!PL9;(HS"^XP"*W:1\B2`)$9(NBTB[6Z3UURWR +MFP8A!SYN#ASML%:11IB?C1))VF!G8I@C!`9*@/&E,A&!G!+Y22ZC^#DN)%]J +M#?VQ/CCGK8C;P=AQ>>V$LX'VX`B%T$NV'B.EWE?"Z;1`ZZ>;[3+GXV2.[2`#7KT3PI%G%X:?NH +M"4TAO29LRF4MXVD]MDQHG-;^#(A[!R*5+\S-(),V%G=P["%SZ-$C29`C,'A6 +M>GKXN/$%M$CD1ON0OD[.L`<)F2_10&.=3Z0^`VGD-E#DX=<5$FZV +MVL(7ER[D/I6V`LB'`LJ%N8<'7QQ7IBKBZP0]^YNF[2JG=.W[MP;,71 +M0ZM+ZQ;?;YAH/?M.R/8"?=)S`W1I1YM>#V^.21G\K&J$?.:XE;M!FWK0)H42 +M(WT*@=<)40X2B8!'>7AT+>RQ`:PA6[F#P!:] +M;*1A\F!D,&]J9U62V-/)'&0BO!%3D*Q&^W-\Q0%HB`\B.C' +M#Q;U=5"C2$+#CX&4+AG%TW&B,6@TE2$:#\E,;VE=GU=Y;X/U1FLP7#H?2'\A;>[ZG2".4D +MX468B+VD%SF&G,F5-5`NDY"DZ9L7::1HYHG)WF(0V:R+Y=)@F0 +MXX"V]9/=>"CD@>VQTS3RPD[::1ZJQ*YSM+`;-A$[+SZ&HQVZ]3NQ-%[*T6R6 +MZ81/XFAGH&7X+(YVZ<;ORN&WT6[=^CVYLA2"1_3/KC +MLA^?U\BAT]L1%G-M"R>31Q1"Z`C4UDX>$B-L]XXG^`F40U$8^SO7B]WY*8RTW7^%GZ99?CSM,7[< +MSF]]FI_'8_D)E^[\-$[9[K_"S^<#/\']\L6W_0;'Z4/]T^+TAXH[5Q@H?:$H +MP1N?+'%0AJ%,-`;6L!R\H98K*FR^G@S[:2SLK0EH"IK)E850ED%IAK(>8N9>KAQ\4@>L]G?I +M(/E#Q8LKO:"$08F&'?AD&<:MPG.@@1D]CQK08JZ\"F4=E&U0]J%#Z#A7SCZI +M`Y[]_Z0.]A]M"4@92$+;HKW($1=;:FLY(J^%:>&(YN9FK9VX:.-IUC8W$P0B +MB)8\VSVO-H][P.0UY]DZ6FP=>=J+[%CHN&B75MO2W$SB[(RH1N`\#E^)I!&:Z34Z:9 +MQED(K#9:CN34L1F-?4S9B1:;99N[F]AF?I#,D"0B67B<5A0KG;)K16(4=;'Q +MHDTKRJ85V]<(5Q[%OAQI6+\^+C>B1_^+X=T@K_>>00OZS1HZZYXC +MQL.;Z[VKH&L"CF$*)[D#S;<]P4%!>1XM#*;A&*R/PC&R.5V>)@_IUN/S>L]: +M'WM,386LK#/O8+.*@6R1,X_+(R5#ORC[7".OB#M2$GQK0N"JR\WU$I&\'F^! +MVA=W<9ZS\^.YWZQK?4_]_LOS&X[Z'LW(7B1W?(25_7X@KWM5X2OO01-9I-#9 +M#=)-8X:QN)S)K*PR6Y@4@V6BJ7*\PEWNRC*(G)TZ&4*X7%(1(N]G>Q#0-=)8 +M9F`R+/JR"F-Y,9,!F:ZQ`');D\FBB)`K;=S!*:E,-5H'#R<^]<_8>O_9SP[95+;,#OWM^I,0\;M*'$US;_S;RY[Z;1HY=2K:' +MYDM'UOD<`D"Y\**S88XU9#:V,&=E_E'INMH[N_>[[/XX>\5X?K[N;Z^_^9EZ.N7_964H +M.8M:-U7@MM@E[M8]M^%G>0M>EI2.M`K5RX[.>>T"6?%*O^?U"PY^(YJPD*S^+N^GW2\+(&7..)C0T +M!G[ODO?_GQ-O5O26!]H$]_S',#HU%?VFIO\6Q$[[")^RCU0N9A_PG/F)Y?`M +ML]Q@D=>M>LJEY\$JS&9=>I/^YLXM\QN'-)[?*1UK/"^(RN4_O!ZY*51PX;:I]R;'9_,H=>KTCS)3 +M3^X.&7Q.='+^GK$=NVI/7EZZ<[I_XF!)Z>GE6['L-8=.A+W6_\[T]2/7?N)O +MN/KBIDFOO/OID,$EHT.?;_\+CA&_XM!E>;^L>.X-XX[34RJ"\P-ZQC//OAW@ +M^KX%OY_X8V^O,9MG35#S@W]>^.7%ORS]9MZZ89?-1X8*5FW];-YGKB\=):X* +M`K/I:REO#'GSXQ$)9Z*S[_H=/Q04$QJH_.CEKPYHAUP_5S:D^FJ+?(VX]J/I +MYV*F-=]?TD\1[/K@B,O-+[9^FQ5;D1`:,DU>+ZR4UPL^;R9P#,*>\!/V7^&X^^&)WQ#@XM/Y7K/[;*Z22*VP+WN^11\29RLH,E05&?2F382JR +M3-17&IBTJOQ2H[G$4&EFXF(?N:3<=K$N&B2O5F\V,B@EEAAL+*DUF@-"%(UM? +M:BS46XRF[Q.T7O3M^J^WC6 +MJ\O>#ZV;)_<96>+4'N%YLG'IF/:&AVL.F1H6F%N.OY>:>7C+.Z)GO>JVIXB2 +M#C1^D#-MT=OY>PI2BI(O3/K*/3;W_?@9UE$J=[#V<2ER.YB"7%)$G@ +M5+.\KH%M861=K7Q:K63*TBL?Q[67+/\I^EAYS(^B^M4%_P4?K:?PG9!PR?U8 +M)"2&=9#N\2BZ7"W#\\_)_XW.IZ8D]=/;$SL\1H9@H,E19CD;%`;S$P1LX7V:4VF%F' +MK#04&2H-Y06&$$9?7L@8+6:FRFQ@7\Z9+97&`DMIC=!TE_X6XK&L*AUH64@!O@8F"&TTC"ARF"VF+6/\YDJA<#:R?CXFH8P +M2K5&!46/:#*-AHFAL`2,IH(>81*F)41RW2]*84]J]!H +M(I\0QW`O2=-M+TG3.U^2,G&Z],S8Q!3AB-CT]-B4S$1=!A.?F!&7')LX7!?/ +MQ*;$=SOBDA.')\()%R9DN5,24X;T9S*'ZIBL#!V3F@!D8@8G+C$A,2XV4\=` +M,R,S/3$N,WD4DY$U.$D7E\EDIK)#A-FZ],2,Q"$IW?@34U.8M/38N,S$.!V, +M`P'#=2F9`)N=(C$C(POF8V*S,H>FI@,682?(C$X-F,3A:.T27$<9DZ'1"5D\V%+,RXG7`E9P!EHXSP=XOAR4S +M%3WIBX]>2Y>;REFW*C(:"C-L&R'6`CLCOPHVD-`P"<9SSEVM+ZTR,.82/?A! +MN8;=]IJ$TC`E6,'TB%.J^ +M#)S5H='1*OGCT8#YE\,!\^OA@#7RT^&@V8EVZ+9ZV.K'V[@R[L(S^W +MY<%O%.S+?D//*IOA/N35FTY"?=UK2%TI[[WBL; +M+A]X/;1">>YRZ1)![T4.SZ_C!=>LKN8: +MRZ)0*%2*2'FD6L&Q5$[M>?VF]'"1)BZ^SW,?+*1L$RGEBBB%7*'B6-1.(U_W +MNE;?]^LSJ'GC_1?>M4M1*J+D42J;E+%O%*Q_VX'(F++XR%['TFM[.!8Y`(F6 +M1REL+-GOYUP:6OSB_J@-F;KR)4&[['"C%=&P*6PL(TXWO+(8/%QU^)>_B[[0 +M26Q2%-%*I0+TXEA4;>TC/&\Y'#1OG;ILWZC)']BDR#5*0"RW2='DM[YW)VE3 +MS>[]PLTOMPW3=6)1*M6=<'._V38^=U:.IV!.ID@P>N!4.Y9(1;0J2@Y*,[C8 +MT<2KPD]M,;4P!W]4NWO;A"@U8'V8C1/BX%^T:O3P?"V*5_`BBA8:YO]W5*/92HH +M&\NUS[X9^^&')[[*'310]9:WN$L*>*M-RJ#\U)&]=NZJ6APFS=T]>-U7G/LJ +M6'74X'4]2YI/DD' +M.OB);4%2&XLR6A&ICK1K-*'X]EO*^TL40J-2JVT+?2@ESX[YY6Z<]4#[;)YJ2]]MX1C48+S +M0K!51',L&8E>U47W+_I_,7W?"\^=FB;I9%&R2V1;@*&]IG;H3_=UO1DX>MO; +M@P8.M[$H8;$CY':/BIWZP^&=*"9H[O6/Q:'.R^_:6#B*4?=BPMMFZD:3L6E5*ACK"[E"6Y +M=E+\TFTW]IV-+WGSSO/!=BEJV$B*B`B.19?0N"LS;N'^I)?]?OI^\QI8]N#'M +MKZ5G9T\0UT3P4Y3JE2VB6+07PQQ^S>OPH9;#OO\7+#?QJ*(8/U?87-, +M]V&?)0SN,;IXV<6!'9]>[=W>R0+N':VV+6/2O+^G)6W9>,[MZWUS<9]WW.Q8 +MP!$BX-3E6)3G\VK/OW%,O%ZR_..?SEVUVT7!;K5.*<7."V:$W9_E%3=PZI6O +M1E_ZR`Y7P08I>QSKG6^<.&X5BHYP/WYUJ$CZ\)%U@2O"MHQ$Z9+3'G,.I4WY +MX!Z)3]@_^Y'2@,2^`\;LO+JN^9QZYX*A1W;=SXP<:V>)8H\%-C(_?6H.EN8/ +MGZ1,N2!JO__\MR4WPEVRGIDW\O10^N.Q)8L&*',^OEKY]I>)(RK?#=L0JNE? +MI$LP]^@=*ZZQ##9_-W3*PYB:I6W&U47?)P^:[]YOW^UW;I!FNQ2Y1^-K+M[R-.0&JPS]-6_ONCA?&7!N[<9"B +MGM@AKR?>QB'1J_HOG)._\CKHL=?\S77[Y9Z/K"0@%-V__Y)RGVXMD>*);\=R +MWZZ!I$)&2LHM>_B?WSE^^W3O\-GHZ^AC\OQN[`Z*3'EZ/SPH55[Q9/4:2OF3NFXX/X +MR)EXX&O'UMP,NE^(BY\7F+T*O6]\NOG''MOF-"^YN+"DSXY%+J5WRC;%#ZL> +M=GSNJ:^S)8?.Q!"IYG,;#"]\UY%_XN&2;TJFTV,ZK/3J>NPD)/''NHQ#*^JQ +M]Z!K+[OJ=7O^U[]2_JTWXX][SBBY1W?'$77]3H6!WSQZ0BG$W.N_"!4;8*/9 +MUW]/^LW1^SWNC\T7+G8*U2;N_B9GY]-KVDN[]^^M0WB?_/+S2P_O?EBG^PEG +M%M>5_OV$;^%W6^_I+YSYZG2?P2WE7S4_F.V_(^*]U:$^5ZJN&&^\HQ\P9.%; +M&\>!J^9^O4VG&5CPW=T]\6]JVQS)AWW.2Y[;XQ7^:5OIG6_BZE0ADZ8D6UH7 +MO_IJ1](AT[D3&:L=7'N5]'RIG4CR^'E*\4J1/9E +MTH7D2$J9>HQD#M0SCNOZ'=,M`QZIJJ'4LVC`#0NU)(2;W6JY7[LHE_U74Q4T +MJ,]6P[:$;"Z1GP(X:U+(H9/*!(?GF*_>"19U3-:+6'-@`;R:\>ZATOD'4$L' +M"`0010_%````#0$``%!+`P04``@`"`!`JS9`````````````````'@```$1O +M8W5M96YT&5D1&]C=6UE;G0N9F1O8U6-00K",!1$]X)W*']O?BHH +M(HU=**X%3U#2WS9@\DM_*KV;"X_D%4P6+ES-,,R;^;S>5;WX1_&D21P'`Z72 +M4%"PW+K0&YACMSE`?5JOJJM;J+VPG3V%6"0HB($AQO&(*'8@WXCRSDXLW$5E +MV>,R"FZUWJ'>0UZX-3V=.<3,WWF>+!G`WZ)@B;F05'5C,H"9P;_;E'P!4$L' +M"`R&*CV5````LP```%!+`P04``@`"`!`JS9`````````````````)@```%]R +M96QS+T9I>&5D1&]C=6UE;G1397%U96YC92YF9'-E<2YR96QS98]+:@,Q#(;W +MA=S!:)_1M)!22IRL&PB$,/NB>C0>,^,'MAJ2LV61(_4*=79]+"7]^C[IZWI; +M;\]^5B?.Q<6@X;%I07$PL7?!:OB48?D"V\WB87WDF:1FRNA2474I%`VC2'I% +M+&9D3Z6)B4.=##%[DEIFBXG,1);QJ6V?,?]DP%^JZBA;%@VX9Z&>A'`7/]X/ +M75.9H-YZ#<=Z77=)_,_LG4[D+5UB=*;L@XLS$`GA7XJ]/:N<; +M4$L'"!*Y#,J]````!@$``%!+`P04``@`"`!`JS9`````````````````&P`` +M`$9I>&5D1&]C=6UE;G1397%U96YC92YF9'-E<6V.30K",!"%]X)W*+,WDPJ* +M2&,WX@'L"22=V(#)U/Q([^;"(WD%6Z$+P?5[W_?>^_FJZL'=B@>%:-DK*(6$ +M@KSFUOJK@IS,:@?U8;FH3G:@]L@Z._*IH7L>6U2,L(\*NI3Z/6+4';E+%,[J +MP)%-$IH=#GW$M90;E%N83+/D3(;"U])P#IH4X!Q%+/%G4)B6->"$X]\G8_(! +M4$L'"``B)\:8````S@```%!+`P04``@`"`!`JS9`````````````````"P`` +M`%]R96QS+RYR96QSE9#/2L0P$(?O@N]0@DE2&BSR\F)"U:&7JD!L!5W9"?1G4Z-#S/6[&;(2ET80;4=SH1JRS9?L2 +M\8^!LRH%"H9+%1Q,D;;@$\ALL\U,&!-2#OV$"MBO,-,):KA#EEJRA%7^2?W0 +M]J-[]-(.Y>WJ^MNGWN/SKT;`S2">$5^*\*O\?/,!4$L'"+<@\O_S````N0$` +M`%!+`P04``@`"`!`JS9`````````````````$P```%M#;VYT96YT7U1Y<&5S +M72YX;6REDL]*Q#`0A^^"[U!RE3;5@XALW8,K@B"D5\;5%>M1YS=L +M?7=^MGIY#Q`S:G:Q8@UBN.4\R@:LB(4/X*BB?6<%TK>K>1!R*VK@5V5YS:5W +M"`YS3`R6:!O0HF\Q>QBH,*D[:"/+[J?69*N8"*$U4B#5^=ZI`T_^XR@H.?;$ +MQH1X00V,'W%H%6&W(+&_X"'$7)L!E/*RMY2@=$_3@06)E_]PS+,#94Z`I]@L +MV"M$_7>P?]5]I!*H/"TE+?8H.FF7P9UQ2#=7C`\T<@OSDWAZ?CR@&IL.[BU` +M/87X>++T^@902P<(7S5E41$!``#G`@``4$L!`BT`%``(``@`0*LV0'#&B=;` +M`P``YPT``!,``````````````````````$UE=&%D871A+TIO8E]05"YX;6Q0 +M2P$"+0`4``@`"`!`JS9`MEKQ/=,```#(`0``&@`````````````````!!``` +M365T861A=&$O35A$0U]%;7!T>5]05"YX;6Q02P$"+0`4``@```!`JS9`%>T[ +MFRH'```J!P``*``````````````````&5D +M1&]C=6UE;G0N9F1O8RYR96QS4$L!`BT`%``(``@`0*LV0`R&*CV5````LP`` +M`!X`````````````````(S4``$1O8W5M96YT&5D1&]C=6UE;G0N +M9F1O8U!+`0(M`!0`"``(`$"K-D`2N0S*O0````8!```F```````````````` +M``0V``!?!BP$`4$L!`A0`%`````@`6'QO2_E8(*00````#@````@````````` +H`````````````&%R8UQT97-T4$L%!@`````!``$`-@```#8````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_zstd.c b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_zstd.c new file mode 100644 index 0000000..1d63a28 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_zstd.c @@ -0,0 +1,82 @@ +/*- + * Copyright (c) 2017 Sean Purcell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * Verify our ability to read sample files compatibly with 'zstd -d'. + * + * In particular: + * * zstd -d will read multiple zstd streams, concatenating the output + * * zstd -d will skip over zstd skippable frames + */ + +static void +compat_zstd(const char *name) +{ + const char *n[7] = { "f1", "f2", "f3", "d1/f1", "d1/f2", "d1/f3", NULL }; + struct archive_entry *ae; + struct archive *a; + int i, r; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + r = archive_read_support_filter_zstd(a); + if (r == ARCHIVE_WARN) { + skipping("zstd reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + extract_reference_file(name); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 2)); + + /* Read entries, match up names with list above. */ + for (i = 0; i < 6; ++i) { + failure("Could not read file %d (%s) from %s", i, n[i], name); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae)); + assertEqualString(n[i], archive_entry_pathname(ae)); + } + + /* Verify the end-of-archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify that the format detection worked. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_ZSTD); + assertEqualString(archive_filter_name(a, 0), "zstd"); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + +DEFINE_TEST(test_compat_zstd) +{ + /* This sample was compressed as 3 separate streams with a zstd skippable + * frame placed in the middle */ + compat_zstd("test_compat_zstd_1.tar.zst"); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_compat_zstd_1.tar.zst.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_zstd_1.tar.zst.uu new file mode 100644 index 0000000..4b0b984 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_compat_zstd_1.tar.zst.uu @@ -0,0 +1,12 @@ +begin 644 test_compat_zstd_1.tar.zst +M*+4O_010)0,`HL0.%;`Q&>>\/$2[#IQF[<1+Z3T<0CX]!77&0@R.6+/F,0+I +M.$1A$QE2`J!+*_6[_YT9_W_M1KC-EG*V>10.`,M`%3*@#F#\`-FT#J:1#U1" +M`H1!&R#A5\*'"JYIJ;C&4=B2CL(L)*E-IJT/RV?.:A_]_N +MB&[7SDG;/=4&#P";0!5D0`=8T0&R&19,)1^HA`0(@S9`N`G.!0!IP&NM<,K! +M-#8!%A]U]K10*DT8!`````$"`P0HM2_]!%!]`P`B11`6H+$)"%]@,Z6OH`"L +MM$R2MAN&*MSG`W?OJ7+4P*B::VXR`NM(1&$7&58"J*U'_&V^S$/_O]U1N%T[ +M)VW7J'+4!A``_4$%^T`],J`8P.0!L@D63"4?J(0$"(,V0+@)S@4`: + +#ifdef HAVE_LINUX_FS_H +#include /* for Linux file flags */ +#endif + +#ifndef HAVE_WCSCPY +static wchar_t * wcscpy(wchar_t *s1, const wchar_t *s2) +{ + wchar_t *dest = s1; + while ((*s1 = *s2) != L'\0') + ++s1, ++s2; + return dest; +} +#endif + +/* + * Most of these tests are system-independent, though a few depend on + * features of the local system. Such tests are conditionalized on + * the platform name. On unsupported platforms, only the + * system-independent features will be tested. + * + * No, I don't want to use config.h in the test files because I want + * the tests to also serve as a check on the correctness of config.h. + * A mis-configured library build should cause tests to fail. + */ + +DEFINE_TEST(test_entry) +{ + char buff[128]; + wchar_t wbuff[128]; + struct stat st; + struct archive_entry *e, *e2; + const struct stat *pst; + unsigned long set, clear; /* For fflag testing. */ + int type, permset, tag, qual; /* For ACL testing. */ + const char *name; /* For ACL testing. */ + const char *xname; /* For xattr tests. */ + const void *xval; /* For xattr tests. */ + size_t xsize; /* For xattr tests. */ + wchar_t wc; + long l; + int i; + + assert((e = archive_entry_new()) != NULL); + + /* + * Verify that the AE_IF* defines match S_IF* defines + * on this platform. See comments in archive_entry.h. + */ +#ifdef S_IFREG + assertEqualInt(S_IFREG, AE_IFREG); +#endif +#ifdef S_IFLNK + assertEqualInt(S_IFLNK, AE_IFLNK); +#endif +#ifdef S_IFSOCK + assertEqualInt(S_IFSOCK, AE_IFSOCK); +#endif +#ifdef S_IFCHR + assertEqualInt(S_IFCHR, AE_IFCHR); +#endif +/* Work around MinGW, which defines S_IFBLK wrong. */ +/* sourceforge.net/tracker/?func=detail&atid=102435&aid=1942809&group_id=2435 */ +#if defined(S_IFBLK) && !defined(_WIN32) + assertEqualInt(S_IFBLK, AE_IFBLK); +#endif +#ifdef S_IFDIR + assertEqualInt(S_IFDIR, AE_IFDIR); +#endif +#ifdef S_IFIFO + assertEqualInt(S_IFIFO, AE_IFIFO); +#endif + + /* + * Basic set/read tests for all fields. + * We should be able to set any field and read + * back the same value. + * + * For methods that "copy" a string, we should be able + * to overwrite the original passed-in string without + * changing the value in the entry. + * + * The following tests are ordered alphabetically by the + * name of the field. + */ + + /* atime */ + archive_entry_set_atime(e, 13579, 24680); + assertEqualInt(archive_entry_atime(e), 13579); + assertEqualInt(archive_entry_atime_nsec(e), 24680); + archive_entry_set_atime(e, 13580, 1000000001L); + assertEqualInt(archive_entry_atime(e), 13581); + assertEqualInt(archive_entry_atime_nsec(e), 1); + archive_entry_set_atime(e, 13580, -7); + assertEqualInt(archive_entry_atime(e), 13579); + assertEqualInt(archive_entry_atime_nsec(e), 999999993); + archive_entry_unset_atime(e); + assertEqualInt(archive_entry_atime(e), 0); + assertEqualInt(archive_entry_atime_nsec(e), 0); + assert(!archive_entry_atime_is_set(e)); + + /* birthtime */ + archive_entry_set_birthtime(e, 17579, 24990); + assertEqualInt(archive_entry_birthtime(e), 17579); + assertEqualInt(archive_entry_birthtime_nsec(e), 24990); + archive_entry_set_birthtime(e, 17580, 1234567890L); + assertEqualInt(archive_entry_birthtime(e), 17581); + assertEqualInt(archive_entry_birthtime_nsec(e), 234567890); + archive_entry_set_birthtime(e, 17581, -24990); + assertEqualInt(archive_entry_birthtime(e), 17580); + assertEqualInt(archive_entry_birthtime_nsec(e), 999975010); + archive_entry_unset_birthtime(e); + assertEqualInt(archive_entry_birthtime(e), 0); + assertEqualInt(archive_entry_birthtime_nsec(e), 0); + assert(!archive_entry_birthtime_is_set(e)); + + /* ctime */ + archive_entry_set_ctime(e, 13580, 24681); + assertEqualInt(archive_entry_ctime(e), 13580); + assertEqualInt(archive_entry_ctime_nsec(e), 24681); + archive_entry_set_ctime(e, 13581, 2008182348L); + assertEqualInt(archive_entry_ctime(e), 13583); + assertEqualInt(archive_entry_ctime_nsec(e), 8182348); + archive_entry_set_ctime(e, 13582, -24681); + assertEqualInt(archive_entry_ctime(e), 13581); + assertEqualInt(archive_entry_ctime_nsec(e), 999975319); + archive_entry_unset_ctime(e); + assertEqualInt(archive_entry_ctime(e), 0); + assertEqualInt(archive_entry_ctime_nsec(e), 0); + assert(!archive_entry_ctime_is_set(e)); + + /* dev */ + assert(!archive_entry_dev_is_set(e)); + archive_entry_set_dev(e, 235); + assert(archive_entry_dev_is_set(e)); + assertEqualInt(archive_entry_dev(e), 235); + /* devmajor/devminor are tested specially below. */ + + /* filetype */ + archive_entry_set_filetype(e, AE_IFREG); + assertEqualInt(archive_entry_filetype(e), AE_IFREG); + + /* fflags are tested specially below */ + + /* gid */ + archive_entry_set_gid(e, 204); + assertEqualInt(archive_entry_gid(e), 204); + + /* gname */ + archive_entry_set_gname(e, "group"); + assertEqualString(archive_entry_gname(e), "group"); + wcscpy(wbuff, L"wgroup"); + archive_entry_copy_gname_w(e, wbuff); + assertEqualWString(archive_entry_gname_w(e), L"wgroup"); + memset(wbuff, 0, sizeof(wbuff)); + assertEqualWString(archive_entry_gname_w(e), L"wgroup"); + + /* hardlink */ + archive_entry_set_hardlink(e, "hardlinkname"); + assertEqualString(archive_entry_hardlink(e), "hardlinkname"); + strcpy(buff, "hardlinkname2"); + archive_entry_copy_hardlink(e, buff); + assertEqualString(archive_entry_hardlink(e), "hardlinkname2"); + memset(buff, 0, sizeof(buff)); + assertEqualString(archive_entry_hardlink(e), "hardlinkname2"); + archive_entry_copy_hardlink(e, NULL); + assertEqualString(archive_entry_hardlink(e), NULL); + assertEqualWString(archive_entry_hardlink_w(e), NULL); + wcscpy(wbuff, L"whardlink"); + archive_entry_copy_hardlink_w(e, wbuff); + assertEqualWString(archive_entry_hardlink_w(e), L"whardlink"); + memset(wbuff, 0, sizeof(wbuff)); + assertEqualWString(archive_entry_hardlink_w(e), L"whardlink"); + archive_entry_copy_hardlink_w(e, NULL); + assertEqualString(archive_entry_hardlink(e), NULL); + assertEqualWString(archive_entry_hardlink_w(e), NULL); + + /* ino */ + assert(!archive_entry_ino_is_set(e)); + archive_entry_set_ino(e, 8593); + assert(archive_entry_ino_is_set(e)); + assertEqualInt(archive_entry_ino(e), 8593); + assertEqualInt(archive_entry_ino64(e), 8593); + archive_entry_set_ino64(e, 8594); + assert(archive_entry_ino_is_set(e)); + assertEqualInt(archive_entry_ino(e), 8594); + assertEqualInt(archive_entry_ino64(e), 8594); + + /* link */ + archive_entry_set_hardlink(e, "hardlinkname"); + archive_entry_set_symlink(e, NULL); + archive_entry_set_link(e, "link"); + assertEqualString(archive_entry_hardlink(e), "link"); + assertEqualString(archive_entry_symlink(e), NULL); + archive_entry_copy_link(e, "link2"); + assertEqualString(archive_entry_hardlink(e), "link2"); + assertEqualString(archive_entry_symlink(e), NULL); + archive_entry_copy_link_w(e, L"link3"); + assertEqualString(archive_entry_hardlink(e), "link3"); + assertEqualString(archive_entry_symlink(e), NULL); + archive_entry_set_hardlink(e, NULL); + archive_entry_set_symlink(e, "symlink"); + archive_entry_set_link(e, "link"); + assertEqualString(archive_entry_hardlink(e), NULL); + assertEqualString(archive_entry_symlink(e), "link"); + archive_entry_copy_link(e, "link2"); + assertEqualString(archive_entry_hardlink(e), NULL); + assertEqualString(archive_entry_symlink(e), "link2"); + archive_entry_copy_link_w(e, L"link3"); + assertEqualString(archive_entry_hardlink(e), NULL); + assertEqualString(archive_entry_symlink(e), "link3"); + /* Arbitrarily override symlink if both hardlink and symlink set. */ + archive_entry_set_hardlink(e, "hardlink"); + archive_entry_set_symlink(e, "symlink"); + archive_entry_set_link(e, "link"); + assertEqualString(archive_entry_hardlink(e), "hardlink"); + assertEqualString(archive_entry_symlink(e), "link"); + + /* mode */ + archive_entry_set_mode(e, 0123456); + assertEqualInt(archive_entry_mode(e), 0123456); + + /* mtime */ + archive_entry_set_mtime(e, 13581, 24682); + assertEqualInt(archive_entry_mtime(e), 13581); + assertEqualInt(archive_entry_mtime_nsec(e), 24682); + archive_entry_set_mtime(e, 13582, 1358297468); + assertEqualInt(archive_entry_mtime(e), 13583); + assertEqualInt(archive_entry_mtime_nsec(e), 358297468); + archive_entry_set_mtime(e, 13583, -24682); + assertEqualInt(archive_entry_mtime(e), 13582); + assertEqualInt(archive_entry_mtime_nsec(e), 999975318); + archive_entry_unset_mtime(e); + assertEqualInt(archive_entry_mtime(e), 0); + assertEqualInt(archive_entry_mtime_nsec(e), 0); + assert(!archive_entry_mtime_is_set(e)); + + /* nlink */ + archive_entry_set_nlink(e, 736); + assertEqualInt(archive_entry_nlink(e), 736); + + /* pathname */ + archive_entry_set_pathname(e, "path"); + assertEqualString(archive_entry_pathname(e), "path"); + archive_entry_set_pathname(e, "path"); + assertEqualString(archive_entry_pathname(e), "path"); + strcpy(buff, "path2"); + archive_entry_copy_pathname(e, buff); + assertEqualString(archive_entry_pathname(e), "path2"); + memset(buff, 0, sizeof(buff)); + assertEqualString(archive_entry_pathname(e), "path2"); + wcscpy(wbuff, L"wpath"); + archive_entry_copy_pathname_w(e, wbuff); + assertEqualWString(archive_entry_pathname_w(e), L"wpath"); + memset(wbuff, 0, sizeof(wbuff)); + assertEqualWString(archive_entry_pathname_w(e), L"wpath"); + + /* rdev */ + archive_entry_set_rdev(e, 532); + assertEqualInt(archive_entry_rdev(e), 532); + /* rdevmajor/rdevminor are tested specially below. */ + + /* size */ + archive_entry_set_size(e, 987654321); + assertEqualInt(archive_entry_size(e), 987654321); + archive_entry_unset_size(e); + assertEqualInt(archive_entry_size(e), 0); + assert(!archive_entry_size_is_set(e)); + + /* sourcepath */ + archive_entry_copy_sourcepath(e, "path1"); + assertEqualString(archive_entry_sourcepath(e), "path1"); + + /* symlink */ + archive_entry_set_symlink(e, "symlinkname"); + assertEqualString(archive_entry_symlink(e), "symlinkname"); + strcpy(buff, "symlinkname2"); + archive_entry_copy_symlink(e, buff); + assertEqualString(archive_entry_symlink(e), "symlinkname2"); + memset(buff, 0, sizeof(buff)); + assertEqualString(archive_entry_symlink(e), "symlinkname2"); + archive_entry_copy_symlink_w(e, NULL); + assertEqualWString(archive_entry_symlink_w(e), NULL); + assertEqualString(archive_entry_symlink(e), NULL); + archive_entry_copy_symlink_w(e, L"wsymlink"); + assertEqualWString(archive_entry_symlink_w(e), L"wsymlink"); + archive_entry_copy_symlink(e, NULL); + assertEqualWString(archive_entry_symlink_w(e), NULL); + assertEqualString(archive_entry_symlink(e), NULL); + + /* uid */ + archive_entry_set_uid(e, 83); + assertEqualInt(archive_entry_uid(e), 83); + + /* uname */ + archive_entry_set_uname(e, "user"); + assertEqualString(archive_entry_uname(e), "user"); + wcscpy(wbuff, L"wuser"); + archive_entry_copy_gname_w(e, wbuff); + assertEqualWString(archive_entry_gname_w(e), L"wuser"); + memset(wbuff, 0, sizeof(wbuff)); + assertEqualWString(archive_entry_gname_w(e), L"wuser"); + + /* Test fflags interface. */ + archive_entry_set_fflags(e, 0x55, 0xAA); + archive_entry_fflags(e, &set, &clear); + failure("Testing set/get of fflags data."); + assertEqualInt(set, 0x55); + failure("Testing set/get of fflags data."); + assertEqualInt(clear, 0xAA); +#ifdef __FreeBSD__ + /* Converting fflags bitmap to string is currently system-dependent. */ + /* TODO: Make this system-independent. */ + assertEqualString(archive_entry_fflags_text(e), + "uappnd,nouchg,nodump,noopaque,uunlnk,nosystem"); +#endif + +#if defined(__FreeBSD__) || defined(__APPLE__) + /* Test archive_entry_copy_fflags_text_w() */ + archive_entry_copy_fflags_text_w(e, L" ,nouappnd, nouchg, dump,hidden"); + archive_entry_fflags(e, &set, &clear); + assertEqualInt(UF_HIDDEN, set); + assertEqualInt(UF_NODUMP | UF_IMMUTABLE | UF_APPEND, clear); + /* Test archive_entry_copy_fflags_text() */ + archive_entry_copy_fflags_text(e, " ,nouappnd, nouchg, dump,hidden"); + archive_entry_fflags(e, &set, &clear); + assertEqualInt(UF_HIDDEN, set); + assertEqualInt(UF_NODUMP | UF_IMMUTABLE | UF_APPEND, clear); +#elif defined(_WIN32) && !defined(CYGWIN) + archive_entry_copy_fflags_text_w(e, L"rdonly,hidden,nosystem"); + archive_entry_fflags(e, &set, &clear); + assertEqualInt(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN, set); + assertEqualInt(FILE_ATTRIBUTE_SYSTEM, clear); + archive_entry_copy_fflags_text(e, "rdonly,hidden,nosystem"); + archive_entry_fflags(e, &set, &clear); + assertEqualInt(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN, set); + assertEqualInt(FILE_ATTRIBUTE_SYSTEM, clear); +#elif defined FS_IOC_GETFLAGS /* Linux */ + archive_entry_copy_fflags_text_w(e, L"sappnd,schg,dump,noundel"); + archive_entry_fflags(e, &set, &clear); + assertEqualInt(FS_APPEND_FL | FS_IMMUTABLE_FL, set); + assertEqualInt(FS_NODUMP_FL | FS_UNRM_FL, clear); + archive_entry_copy_fflags_text(e, "sappnd,schg,dump,noundel"); + archive_entry_fflags(e, &set, &clear); + assertEqualInt(FS_APPEND_FL | FS_IMMUTABLE_FL, set); + assertEqualInt(FS_NODUMP_FL | FS_UNRM_FL, clear); +#endif + + /* See test_acl_basic.c for tests of ACL set/get consistency. */ + + /* Test xattrs set/get consistency. */ + archive_entry_xattr_add_entry(e, "xattr1", "xattrvalue1", 12); + assertEqualInt(1, archive_entry_xattr_reset(e)); + assertEqualInt(0, archive_entry_xattr_next(e, &xname, &xval, &xsize)); + assertEqualString(xname, "xattr1"); + assertEqualString(xval, "xattrvalue1"); + assertEqualInt((int)xsize, 12); + assertEqualInt(1, archive_entry_xattr_count(e)); + assertEqualInt(ARCHIVE_WARN, + archive_entry_xattr_next(e, &xname, &xval, &xsize)); + assertEqualString(xname, NULL); + assertEqualString(xval, NULL); + assertEqualInt((int)xsize, 0); + archive_entry_xattr_clear(e); + assertEqualInt(0, archive_entry_xattr_reset(e)); + assertEqualInt(ARCHIVE_WARN, + archive_entry_xattr_next(e, &xname, &xval, &xsize)); + assertEqualString(xname, NULL); + assertEqualString(xval, NULL); + assertEqualInt((int)xsize, 0); + archive_entry_xattr_add_entry(e, "xattr1", "xattrvalue1", 12); + assertEqualInt(1, archive_entry_xattr_reset(e)); + archive_entry_xattr_add_entry(e, "xattr2", "xattrvalue2", 12); + assertEqualInt(2, archive_entry_xattr_reset(e)); + assertEqualInt(0, archive_entry_xattr_next(e, &xname, &xval, &xsize)); + assertEqualInt(0, archive_entry_xattr_next(e, &xname, &xval, &xsize)); + assertEqualInt(ARCHIVE_WARN, + archive_entry_xattr_next(e, &xname, &xval, &xsize)); + assertEqualString(xname, NULL); + assertEqualString(xval, NULL); + assertEqualInt((int)xsize, 0); + + + /* + * Test clone() implementation. + */ + + /* Set values in 'e' */ + archive_entry_clear(e); + archive_entry_set_atime(e, 13579, 24680); + archive_entry_set_birthtime(e, 13779, 24990); + archive_entry_set_ctime(e, 13580, 24681); + archive_entry_set_dev(e, 235); + archive_entry_set_fflags(e, 0x55, 0xAA); + archive_entry_set_gid(e, 204); + archive_entry_set_gname(e, "group"); + archive_entry_set_hardlink(e, "hardlinkname"); + archive_entry_set_ino(e, 8593); + archive_entry_set_mode(e, 0123456); + archive_entry_set_mtime(e, 13581, 24682); + archive_entry_set_nlink(e, 736); + archive_entry_set_pathname(e, "path"); + archive_entry_set_rdev(e, 532); + archive_entry_set_size(e, 987654321); + archive_entry_copy_sourcepath(e, "source"); + archive_entry_set_symlink(e, "symlinkname"); + archive_entry_set_uid(e, 83); + archive_entry_set_uname(e, "user"); + /* Add an ACL entry. */ + archive_entry_acl_add_entry(e, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_READ, ARCHIVE_ENTRY_ACL_USER, 77, "user77"); + /* Add an extended attribute. */ + archive_entry_xattr_add_entry(e, "xattr1", "xattrvalue", 11); + + /* Make a clone. */ + e2 = archive_entry_clone(e); + + /* Clone should have same contents. */ + assertEqualInt(archive_entry_atime(e2), 13579); + assertEqualInt(archive_entry_atime_nsec(e2), 24680); + assertEqualInt(archive_entry_birthtime(e2), 13779); + assertEqualInt(archive_entry_birthtime_nsec(e2), 24990); + assertEqualInt(archive_entry_ctime(e2), 13580); + assertEqualInt(archive_entry_ctime_nsec(e2), 24681); + assertEqualInt(archive_entry_dev(e2), 235); + archive_entry_fflags(e, &set, &clear); + assertEqualInt(clear, 0xAA); + assertEqualInt(set, 0x55); + assertEqualInt(archive_entry_gid(e2), 204); + assertEqualString(archive_entry_gname(e2), "group"); + assertEqualString(archive_entry_hardlink(e2), "hardlinkname"); + assertEqualInt(archive_entry_ino(e2), 8593); + assertEqualInt(archive_entry_mode(e2), 0123456); + assertEqualInt(archive_entry_mtime(e2), 13581); + assertEqualInt(archive_entry_mtime_nsec(e2), 24682); + assertEqualInt(archive_entry_nlink(e2), 736); + assertEqualString(archive_entry_pathname(e2), "path"); + assertEqualInt(archive_entry_rdev(e2), 532); + assertEqualInt(archive_entry_size(e2), 987654321); + assertEqualString(archive_entry_sourcepath(e2), "source"); + assertEqualString(archive_entry_symlink(e2), "symlinkname"); + assertEqualInt(archive_entry_uid(e2), 83); + assertEqualString(archive_entry_uname(e2), "user"); + + /* Verify ACL was copied. */ + assertEqualInt(4, archive_entry_acl_reset(e2, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + /* First three are standard permission bits. */ + assertEqualInt(0, archive_entry_acl_next(e2, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + assertEqualInt(permset, 4); + assertEqualInt(tag, ARCHIVE_ENTRY_ACL_USER_OBJ); + assertEqualInt(qual, -1); + assertEqualString(name, NULL); + assertEqualInt(0, archive_entry_acl_next(e2, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + assertEqualInt(permset, 5); + assertEqualInt(tag, ARCHIVE_ENTRY_ACL_GROUP_OBJ); + assertEqualInt(qual, -1); + assertEqualString(name, NULL); + assertEqualInt(0, archive_entry_acl_next(e2, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + assertEqualInt(permset, 6); + assertEqualInt(tag, ARCHIVE_ENTRY_ACL_OTHER); + assertEqualInt(qual, -1); + assertEqualString(name, NULL); + /* Fourth is custom one. */ + assertEqualInt(0, archive_entry_acl_next(e2, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + assertEqualInt(permset, ARCHIVE_ENTRY_ACL_READ); + assertEqualInt(tag, ARCHIVE_ENTRY_ACL_USER); + assertEqualInt(qual, 77); + assertEqualString(name, "user77"); + + /* Verify xattr was copied. */ + assertEqualInt(1, archive_entry_xattr_reset(e2)); + assertEqualInt(0, archive_entry_xattr_next(e2, &xname, &xval, &xsize)); + assertEqualString(xname, "xattr1"); + assertEqualString(xval, "xattrvalue"); + assertEqualInt((int)xsize, 11); + assertEqualInt(ARCHIVE_WARN, + archive_entry_xattr_next(e2, &xname, &xval, &xsize)); + assertEqualString(xname, NULL); + assertEqualString(xval, NULL); + assertEqualInt((int)xsize, 0); + + /* Change the original */ + archive_entry_set_atime(e, 13580, 24690); + archive_entry_set_birthtime(e, 13980, 24999); + archive_entry_set_ctime(e, 13590, 24691); + archive_entry_set_dev(e, 245); + archive_entry_set_fflags(e, 0x85, 0xDA); + archive_entry_set_filetype(e, AE_IFLNK); + archive_entry_set_gid(e, 214); + archive_entry_set_gname(e, "grouper"); + archive_entry_set_hardlink(e, "hardlinkpath"); + archive_entry_set_ino(e, 8763); + archive_entry_set_mode(e, 0123654); + archive_entry_set_mtime(e, 18351, 28642); + archive_entry_set_nlink(e, 73); + archive_entry_set_pathname(e, "pathest"); + archive_entry_set_rdev(e, 132); + archive_entry_set_size(e, 987456321); + archive_entry_copy_sourcepath(e, "source2"); + archive_entry_set_symlink(e, "symlinkpath"); + archive_entry_set_uid(e, 93); + archive_entry_set_uname(e, "username"); + archive_entry_acl_clear(e); + archive_entry_xattr_clear(e); + + /* Clone should still have same contents. */ + assertEqualInt(archive_entry_atime(e2), 13579); + assertEqualInt(archive_entry_atime_nsec(e2), 24680); + assertEqualInt(archive_entry_birthtime(e2), 13779); + assertEqualInt(archive_entry_birthtime_nsec(e2), 24990); + assertEqualInt(archive_entry_ctime(e2), 13580); + assertEqualInt(archive_entry_ctime_nsec(e2), 24681); + assertEqualInt(archive_entry_dev(e2), 235); + archive_entry_fflags(e2, &set, &clear); + assertEqualInt(clear, 0xAA); + assertEqualInt(set, 0x55); + assertEqualInt(archive_entry_gid(e2), 204); + assertEqualString(archive_entry_gname(e2), "group"); + assertEqualString(archive_entry_hardlink(e2), "hardlinkname"); + assertEqualInt(archive_entry_ino(e2), 8593); + assertEqualInt(archive_entry_mode(e2), 0123456); + assertEqualInt(archive_entry_mtime(e2), 13581); + assertEqualInt(archive_entry_mtime_nsec(e2), 24682); + assertEqualInt(archive_entry_nlink(e2), 736); + assertEqualString(archive_entry_pathname(e2), "path"); + assertEqualInt(archive_entry_rdev(e2), 532); + assertEqualInt(archive_entry_size(e2), 987654321); + assertEqualString(archive_entry_sourcepath(e2), "source"); + assertEqualString(archive_entry_symlink(e2), "symlinkname"); + assertEqualInt(archive_entry_uid(e2), 83); + assertEqualString(archive_entry_uname(e2), "user"); + + /* Verify ACL was unchanged. */ + assertEqualInt(4, archive_entry_acl_reset(e2, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + /* First three are standard permission bits. */ + assertEqualInt(0, archive_entry_acl_next(e2, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + assertEqualInt(permset, 4); + assertEqualInt(tag, ARCHIVE_ENTRY_ACL_USER_OBJ); + assertEqualInt(qual, -1); + assertEqualString(name, NULL); + assertEqualInt(0, archive_entry_acl_next(e2, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + assertEqualInt(permset, 5); + assertEqualInt(tag, ARCHIVE_ENTRY_ACL_GROUP_OBJ); + assertEqualInt(qual, -1); + assertEqualString(name, NULL); + assertEqualInt(0, archive_entry_acl_next(e2, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + assertEqualInt(permset, 6); + assertEqualInt(tag, ARCHIVE_ENTRY_ACL_OTHER); + assertEqualInt(qual, -1); + assertEqualString(name, NULL); + /* Fourth is custom one. */ + assertEqualInt(0, archive_entry_acl_next(e2, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + assertEqualInt(permset, ARCHIVE_ENTRY_ACL_READ); + assertEqualInt(tag, ARCHIVE_ENTRY_ACL_USER); + assertEqualInt(qual, 77); + assertEqualString(name, "user77"); + assertEqualInt(1, archive_entry_acl_next(e2, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(type, 0); + assertEqualInt(permset, 0); + assertEqualInt(tag, 0); + assertEqualInt(qual, -1); + assertEqualString(name, NULL); + + /* Verify xattr was unchanged. */ + assertEqualInt(1, archive_entry_xattr_reset(e2)); + + /* Release clone. */ + archive_entry_free(e2); + + /* + * Test clear() implementation. + */ + archive_entry_clear(e); + assertEqualInt(archive_entry_atime(e), 0); + assertEqualInt(archive_entry_atime_nsec(e), 0); + assertEqualInt(archive_entry_birthtime(e), 0); + assertEqualInt(archive_entry_birthtime_nsec(e), 0); + assertEqualInt(archive_entry_ctime(e), 0); + assertEqualInt(archive_entry_ctime_nsec(e), 0); + assertEqualInt(archive_entry_dev(e), 0); + archive_entry_fflags(e, &set, &clear); + assertEqualInt(clear, 0); + assertEqualInt(set, 0); + assertEqualInt(archive_entry_filetype(e), 0); + assertEqualInt(archive_entry_gid(e), 0); + assertEqualString(archive_entry_gname(e), NULL); + assertEqualString(archive_entry_hardlink(e), NULL); + assertEqualInt(archive_entry_ino(e), 0); + assertEqualInt(archive_entry_mode(e), 0); + assertEqualInt(archive_entry_mtime(e), 0); + assertEqualInt(archive_entry_mtime_nsec(e), 0); + assertEqualInt(archive_entry_nlink(e), 0); + assertEqualString(archive_entry_pathname(e), NULL); + assertEqualInt(archive_entry_rdev(e), 0); + assertEqualInt(archive_entry_size(e), 0); + assertEqualString(archive_entry_symlink(e), NULL); + assertEqualInt(archive_entry_uid(e), 0); + assertEqualString(archive_entry_uname(e), NULL); + /* ACLs should be cleared. */ + assertEqualInt(archive_entry_acl_count(e, ARCHIVE_ENTRY_ACL_TYPE_ACCESS), 0); + assertEqualInt(archive_entry_acl_count(e, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT), 0); + /* Extended attributes should be cleared. */ + assertEqualInt(archive_entry_xattr_count(e), 0); + + /* + * Test archive_entry_copy_stat(). + */ + memset(&st, 0, sizeof(st)); + /* Set all of the standard 'struct stat' fields. */ + st.st_atime = 456789; + st.st_ctime = 345678; + st.st_dev = 123; + st.st_gid = 34; + st.st_ino = 234; + st.st_mode = 077777; + st.st_mtime = 234567; + st.st_nlink = 345; + st.st_size = 123456789; + st.st_uid = 23; +#ifdef __FreeBSD__ + /* On FreeBSD, high-res timestamp data should come through. */ + st.st_atimespec.tv_nsec = 6543210; + st.st_ctimespec.tv_nsec = 5432109; + st.st_mtimespec.tv_nsec = 3210987; + st.st_birthtimespec.tv_nsec = 7459386; +#endif + /* Copy them into the entry. */ + archive_entry_copy_stat(e, &st); + /* Read each one back separately and compare. */ + assertEqualInt(archive_entry_atime(e), 456789); + assertEqualInt(archive_entry_ctime(e), 345678); + assertEqualInt(archive_entry_dev(e), 123); + assertEqualInt(archive_entry_gid(e), 34); + assertEqualInt(archive_entry_ino(e), 234); + assertEqualInt(archive_entry_mode(e), 077777); + assertEqualInt(archive_entry_mtime(e), 234567); + assertEqualInt(archive_entry_nlink(e), 345); + assertEqualInt(archive_entry_size(e), 123456789); + assertEqualInt(archive_entry_uid(e), 23); +#if __FreeBSD__ + /* On FreeBSD, high-res timestamp data should come through. */ + assertEqualInt(archive_entry_atime_nsec(e), 6543210); + assertEqualInt(archive_entry_ctime_nsec(e), 5432109); + assertEqualInt(archive_entry_mtime_nsec(e), 3210987); + assertEqualInt(archive_entry_birthtime_nsec(e), 7459386); +#endif + + /* + * Test archive_entry_stat(). + */ + /* First, clear out any existing stat data. */ + memset(&st, 0, sizeof(st)); + archive_entry_copy_stat(e, &st); + /* Set a bunch of fields individually. */ + archive_entry_set_atime(e, 456789, 321); + archive_entry_set_ctime(e, 345678, 432); + archive_entry_set_dev(e, 123); + archive_entry_set_gid(e, 34); + archive_entry_set_ino(e, 234); + archive_entry_set_mode(e, 012345); + archive_entry_set_mode(e, 012345); + archive_entry_set_mtime(e, 234567, 543); + archive_entry_set_nlink(e, 345); + archive_entry_set_size(e, 123456789); + archive_entry_set_uid(e, 23); + /* Retrieve a stat structure. */ + assert((pst = archive_entry_stat(e)) != NULL); + if (pst == NULL) + return; + /* Check that the values match. */ + assertEqualInt(pst->st_atime, 456789); + assertEqualInt(pst->st_ctime, 345678); + assertEqualInt(pst->st_dev, 123); + assertEqualInt(pst->st_gid, 34); + assertEqualInt(pst->st_ino, 234); + assertEqualInt(pst->st_mode, 012345); + assertEqualInt(pst->st_mtime, 234567); + assertEqualInt(pst->st_nlink, 345); + assertEqualInt(pst->st_size, 123456789); + assertEqualInt(pst->st_uid, 23); +#ifdef __FreeBSD__ + /* On FreeBSD, high-res timestamp data should come through. */ + assertEqualInt(pst->st_atimespec.tv_nsec, 321); + assertEqualInt(pst->st_ctimespec.tv_nsec, 432); + assertEqualInt(pst->st_mtimespec.tv_nsec, 543); +#endif + + /* Changing any one value should update struct stat. */ + archive_entry_set_atime(e, 456788, 0); + assert((pst = archive_entry_stat(e)) != NULL); + if (pst == NULL) + return; + assertEqualInt(pst->st_atime, 456788); + archive_entry_set_ctime(e, 345677, 431); + assert((pst = archive_entry_stat(e)) != NULL); + if (pst == NULL) + return; + assertEqualInt(pst->st_ctime, 345677); + archive_entry_set_dev(e, 122); + assert((pst = archive_entry_stat(e)) != NULL); + if (pst == NULL) + return; + assertEqualInt(pst->st_dev, 122); + archive_entry_set_gid(e, 33); + assert((pst = archive_entry_stat(e)) != NULL); + if (pst == NULL) + return; + assertEqualInt(pst->st_gid, 33); + archive_entry_set_ino(e, 233); + assert((pst = archive_entry_stat(e)) != NULL); + if (pst == NULL) + return; + assertEqualInt(pst->st_ino, 233); + archive_entry_set_mode(e, 012344); + assert((pst = archive_entry_stat(e)) != NULL); + if (pst == NULL) + return; + assertEqualInt(pst->st_mode, 012344); + archive_entry_set_mtime(e, 234566, 542); + assert((pst = archive_entry_stat(e)) != NULL); + if (pst == NULL) + return; + assertEqualInt(pst->st_mtime, 234566); + archive_entry_set_nlink(e, 344); + assert((pst = archive_entry_stat(e)) != NULL); + if (pst == NULL) + return; + assertEqualInt(pst->st_nlink, 344); + archive_entry_set_size(e, 123456788); + assert((pst = archive_entry_stat(e)) != NULL); + if (pst == NULL) + return; + assertEqualInt(pst->st_size, 123456788); + archive_entry_set_uid(e, 22); + assert((pst = archive_entry_stat(e)) != NULL); + if (pst == NULL) + return; + assertEqualInt(pst->st_uid, 22); + /* We don't need to check high-res fields here. */ + + /* + * Test dev/major/minor interfaces. Setting 'dev' or 'rdev' + * should change the corresponding major/minor values, and + * vice versa. + * + * The test here is system-specific because it assumes that + * makedev(), major(), and minor() are defined in sys/stat.h. + * I'm not too worried about it, though, because the code is + * simple. If it works on FreeBSD, it's unlikely to be broken + * anywhere else. Note: The functionality is present on every + * platform even if these tests only run some places; + * libarchive's more extensive configuration logic should find + * the necessary definitions on every platform. + */ +#if __FreeBSD__ + archive_entry_set_dev(e, 0x12345678); + assertEqualInt(archive_entry_devmajor(e), major(0x12345678)); + assertEqualInt(archive_entry_devminor(e), minor(0x12345678)); + assertEqualInt(archive_entry_dev(e), 0x12345678); + archive_entry_set_devmajor(e, 0xfe); + archive_entry_set_devminor(e, 0xdcba98); + assertEqualInt(archive_entry_devmajor(e), 0xfe); + assertEqualInt(archive_entry_devminor(e), 0xdcba98); + assertEqualInt(archive_entry_dev(e), makedev(0xfe, 0xdcba98)); + archive_entry_set_rdev(e, 0x12345678); + assertEqualInt(archive_entry_rdevmajor(e), major(0x12345678)); + assertEqualInt(archive_entry_rdevminor(e), minor(0x12345678)); + assertEqualInt(archive_entry_rdev(e), 0x12345678); + archive_entry_set_rdevmajor(e, 0xfe); + archive_entry_set_rdevminor(e, 0xdcba98); + assertEqualInt(archive_entry_rdevmajor(e), 0xfe); + assertEqualInt(archive_entry_rdevminor(e), 0xdcba98); + assertEqualInt(archive_entry_rdev(e), makedev(0xfe, 0xdcba98)); +#endif + + /* + * Exercise the character-conversion logic, if we can. + */ + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("Can't exercise charset-conversion logic without" + " a suitable locale."); + } else { + /* A filename that cannot be converted to wide characters. */ + archive_entry_copy_pathname(e, "abc\314\214mno\374xyz"); + failure("Converting invalid chars to Unicode should fail."); + assert(NULL == archive_entry_pathname_w(e)); + /* + failure("Converting invalid chars to UTF-8 should fail."); + assert(NULL == archive_entry_pathname_utf8(e)); + */ + + /* A group name that cannot be converted. */ + archive_entry_copy_gname(e, "abc\314\214mno\374xyz"); + failure("Converting invalid chars to Unicode should fail."); + assert(NULL == archive_entry_gname_w(e)); + + /* A user name that cannot be converted. */ + archive_entry_copy_uname(e, "abc\314\214mno\374xyz"); + failure("Converting invalid chars to Unicode should fail."); + assert(NULL == archive_entry_uname_w(e)); + + /* A hardlink target that cannot be converted. */ + archive_entry_copy_hardlink(e, "abc\314\214mno\374xyz"); + failure("Converting invalid chars to Unicode should fail."); + assert(NULL == archive_entry_hardlink_w(e)); + + /* A symlink target that cannot be converted. */ + archive_entry_copy_symlink(e, "abc\314\214mno\374xyz"); + failure("Converting invalid chars to Unicode should fail."); + assert(NULL == archive_entry_symlink_w(e)); + } + + l = 0x12345678L; + wc = (wchar_t)l; /* Wide character too big for UTF-8. */ + if (NULL == setlocale(LC_ALL, "C") || (long)wc != l) { + skipping("Testing charset conversion failure requires 32-bit wchar_t and support for \"C\" locale."); + } else { + /* + * Build the string L"xxx\U12345678yyy\u5678zzz" without + * using wcscpy or C99 \u#### syntax. + */ + name = "xxxAyyyBzzz"; + for (i = 0; i < (int)strlen(name); ++i) + wbuff[i] = name[i]; + wbuff[3] = (wchar_t)0x12345678; + wbuff[7] = (wchar_t)0x5678; + /* A Unicode filename that cannot be converted to UTF-8. */ + archive_entry_copy_pathname_w(e, wbuff); + failure("Converting wide characters from Unicode should fail."); + assertEqualString(NULL, archive_entry_pathname(e)); + } + + /* Release the experimental entry. */ + archive_entry_free(e); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_entry_strmode.c b/dependencies/libarchive-3.4.2/libarchive/test/test_entry_strmode.c new file mode 100644 index 0000000..ba183db --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_entry_strmode.c @@ -0,0 +1,71 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_entry_strmode.c 201247 2009-12-30 05:59:21Z kientzle $"); + +DEFINE_TEST(test_entry_strmode) +{ + struct archive_entry *entry; + + assert((entry = archive_entry_new()) != NULL); + + archive_entry_set_mode(entry, AE_IFREG | 0642); + assertEqualString(archive_entry_strmode(entry), "-rw-r---w- "); + + /* Regular file + hardlink still shows as regular file. */ + archive_entry_set_mode(entry, AE_IFREG | 0644); + archive_entry_set_hardlink(entry, "link"); + assertEqualString(archive_entry_strmode(entry), "-rw-r--r-- "); + + archive_entry_set_mode(entry, 0640); + archive_entry_set_hardlink(entry, "link"); + assertEqualString(archive_entry_strmode(entry), "hrw-r----- "); + archive_entry_set_hardlink(entry, NULL); + + archive_entry_set_mode(entry, AE_IFDIR | 0777); + assertEqualString(archive_entry_strmode(entry), "drwxrwxrwx "); + + archive_entry_set_mode(entry, AE_IFBLK | 03642); + assertEqualString(archive_entry_strmode(entry), "brw-r-S-wT "); + + archive_entry_set_mode(entry, AE_IFCHR | 05777); + assertEqualString(archive_entry_strmode(entry), "crwsrwxrwt "); + + archive_entry_set_mode(entry, AE_IFSOCK | 0222); + assertEqualString(archive_entry_strmode(entry), "s-w--w--w- "); + + archive_entry_set_mode(entry, AE_IFIFO | 0444); + assertEqualString(archive_entry_strmode(entry), "pr--r--r-- "); + + archive_entry_set_mode(entry, AE_IFLNK | 04000); + assertEqualString(archive_entry_strmode(entry), "l--S------ "); + + archive_entry_acl_add_entry(entry, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + 0007, ARCHIVE_ENTRY_ACL_GROUP, 78, "group78"); + assertEqualString(archive_entry_strmode(entry), "l--S------+"); + + /* Release the experimental entry. */ + archive_entry_free(entry); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_extattr_freebsd.c b/dependencies/libarchive-3.4.2/libarchive/test/test_extattr_freebsd.c new file mode 100644 index 0000000..7cb30b5 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_extattr_freebsd.c @@ -0,0 +1,153 @@ +/*- + * Copyright (c) 2003-2009 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_extattr_freebsd.c 201247 2009-12-30 05:59:21Z kientzle $"); + +#if defined(__FreeBSD__) && __FreeBSD__ > 4 +#include +#endif + +/* + * Verify extended attribute restore-to-disk. This test is FreeBSD-specific. + */ + +DEFINE_TEST(test_extattr_freebsd) +{ +#if !defined(__FreeBSD__) + skipping("FreeBSD-specific extattr restore test"); +#elif __FreeBSD__ < 5 + skipping("extattr restore supported only on FreeBSD 5.0 and later"); +#else + char buff[64]; + const char *xname; + const void *xval; + size_t xsize; + struct stat st; + struct archive *a; + struct archive_entry *ae; + int n, fd; + + /* + * First, do a quick manual set/read of an extended attribute + * to verify that the local filesystem does support it. If it + * doesn't, we'll simply skip the remaining tests. + */ + /* Create a test file and try to set an ACL on it. */ + fd = open("pretest", O_RDWR | O_CREAT, 0777); + failure("Could not create test file?!"); + if (!assert(fd >= 0)) + return; + + errno = 0; + n = extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, "testattr", "1234", 4); + if (n != 4 && errno == EOPNOTSUPP) { + close(fd); + skipping("extattr tests require that extattr support be enabled on the filesystem"); + return; + } + failure("extattr_set_fd(): errno=%d (%s)", errno, strerror(errno)); + assertEqualInt(4, n); + close(fd); + + /* Create a write-to-disk object. */ + assert(NULL != (a = archive_write_disk_new())); + archive_write_disk_set_options(a, + ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_XATTR); + + /* Populate an archive entry with an extended attribute. */ + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_pathname(ae, "test0"); + archive_entry_set_mtime(ae, 123456, 7890); + archive_entry_set_size(ae, 0); + archive_entry_set_mode(ae, 0755); + archive_entry_xattr_add_entry(ae, "user.foo", "12345", 5); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a)); + archive_entry_free(ae); + + /* Another entry; similar but with mode = 0. */ + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_pathname(ae, "test1"); + archive_entry_set_mtime(ae, 12345678, 7890); + archive_entry_set_size(ae, 0); + archive_entry_set_mode(ae, 0); + archive_entry_xattr_add_entry(ae, "user.bar", "123456", 6); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Close the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + + /* Verify the data on disk. */ + assertEqualInt(0, stat("test0", &st)); + assertEqualInt(st.st_mtime, 123456); + assertEqualInt(st.st_mode & 0777, 0755); + /* Verify extattr */ + n = extattr_get_file("test0", EXTATTR_NAMESPACE_USER, + "foo", buff, sizeof(buff)); + if (assertEqualInt(n, 5)) { + buff[n] = '\0'; + assertEqualString(buff, "12345"); + } + + /* Verify the data on disk. */ + assertEqualInt(0, stat("test1", &st)); + assertEqualInt(st.st_mtime, 12345678); + assertEqualInt(st.st_mode & 0777, 0); + /* + * If we are not root, we have to make test1 user readable + * or extattr_get_file() will fail + */ + if (geteuid() != 0) { + chmod("test1", S_IRUSR); + } + /* Verify extattr */ + n = extattr_get_file("test1", EXTATTR_NAMESPACE_USER, + "bar", buff, sizeof(buff)); + if (assertEqualInt(n, 6)) { + buff[n] = '\0'; + assertEqualString(buff, "123456"); + } + + /* Use libarchive APIs to read the file back into an entry and + * verify that the extattr was read correctly. */ + assert((a = archive_read_disk_new()) != NULL); + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_pathname(ae, "test0"); + assertEqualInt(ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + assertEqualInt(1, archive_entry_xattr_reset(ae)); + assertEqualInt(ARCHIVE_OK, + archive_entry_xattr_next(ae, &xname, &xval, &xsize)); + assertEqualString(xname, "user.foo"); + assertEqualInt(xsize, 5); + assertEqualMem(xval, "12345", xsize); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + archive_entry_free(ae); +#endif +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_filter_count.c b/dependencies/libarchive-3.4.2/libarchive/test/test_filter_count.c new file mode 100644 index 0000000..4885ab8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_filter_count.c @@ -0,0 +1,80 @@ +/*- + * Copyright (c) 2003-2009 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_file_nonexistent.c 189473 2009-03-07 02:09:21Z kientzle $"); + +static void read_test(const char *name); +static void write_test(void); + +static void +read_test(const char *name) +{ + struct archive* a = archive_read_new(); + int r; + + r = archive_read_support_filter_bzip2(a); + if((ARCHIVE_WARN == r && !canBzip2()) || ARCHIVE_WARN > r) { + skipping("bzip2 unsupported"); + return; + } + + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + + extract_reference_file(name); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 2)); + /* bzip2 and none */ + assertEqualInt(2, archive_filter_count(a)); + + archive_read_free(a); +} + +static void +write_test(void) +{ + char buff[4096]; + struct archive* a = archive_write_new(); + int r; + + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_per_block(a, 10)); + + r = archive_write_add_filter_bzip2(a); + if((ARCHIVE_WARN == r && !canBzip2()) || ARCHIVE_WARN > r) { + skipping("bzip2 unsupported"); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, 4096, 0)); + /* bzip2 and none */ + assertEqualInt(2, archive_filter_count(a)); + archive_write_free(a); +} + +DEFINE_TEST(test_filter_count) +{ + read_test("test_compat_bzip2_1.tbz"); + write_test(); +} + + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_fuzz.c b/dependencies/libarchive-3.4.2/libarchive/test/test_fuzz.c new file mode 100644 index 0000000..b2654c4 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_fuzz.c @@ -0,0 +1,640 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_fuzz.c 201247 2009-12-30 05:59:21Z kientzle $"); + +/* + * This was inspired by an ISO fuzz tester written by Michal Zalewski + * and posted to the "vulnwatch" mailing list on March 17, 2005: + * http://seclists.org/vulnwatch/2005/q1/0088.html + * + * This test simply reads each archive image into memory, pokes + * random values into it and runs it through libarchive. It tries + * to damage about 1% of each file and repeats the exercise 100 times + * with each file. + * + * Unlike most other tests, this test does not verify libarchive's + * responses other than to ensure that libarchive doesn't crash. + * + * Due to the deliberately random nature of this test, it may be hard + * to reproduce failures. Because this test deliberately attempts to + * induce crashes, there's little that can be done in the way of + * post-failure diagnostics. + */ + +/* Because this works for any archive, we can just re-use the archives + * developed for other tests. */ +struct files { + int uncompress; /* If 1, decompress the file before fuzzing. */ + const char **names; +}; + +static void +test_fuzz(const struct files *filesets) +{ + const void *blk; + size_t blk_size; + int64_t blk_offset; + int n; + const char *skip_fuzz_tests; + + skip_fuzz_tests = getenv("SKIP_TEST_FUZZ"); + if (skip_fuzz_tests != NULL) { + skipping("Skipping fuzz tests due to SKIP_TEST_FUZZ " + "environment variable"); + return; + } + + for (n = 0; filesets[n].names != NULL; ++n) { + const size_t buffsize = 30000000; + struct archive_entry *ae; + struct archive *a; + char *rawimage = NULL, *image = NULL, *tmp = NULL; + size_t size = 0, oldsize = 0; + int i, q; + + extract_reference_files(filesets[n].names); + if (filesets[n].uncompress) { + int r; + /* Use format_raw to decompress the data. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_raw(a)); + r = archive_read_open_filenames(a, filesets[n].names, 16384); + if (r != ARCHIVE_OK) { + archive_read_free(a); + if (filesets[n].names[0] == NULL || filesets[n].names[1] == NULL) { + skipping("Cannot uncompress fileset"); + } else { + skipping("Cannot uncompress %s", filesets[n].names[0]); + } + continue; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae)); + rawimage = malloc(buffsize); + size = archive_read_data(a, rawimage, buffsize); + assertEqualIntA(a, ARCHIVE_EOF, + archive_read_next_header(a, &ae)); + assertEqualInt(ARCHIVE_OK, + archive_read_free(a)); + assert(size > 0); + if (filesets[n].names[0] == NULL || filesets[n].names[1] == NULL) { + failure("Internal buffer is not big enough for " + "uncompressed test files"); + } else { + failure("Internal buffer is not big enough for " + "uncompressed test file: %s", filesets[n].names[0]); + } + if (!assert(size < buffsize)) { + free(rawimage); + rawimage = NULL; + continue; + } + } else { + for (i = 0; filesets[n].names[i] != NULL; ++i) + { + char *newraw; + tmp = slurpfile(&size, "%s", + filesets[n].names[i]); + newraw = realloc(rawimage, oldsize + size); + if (!assert(newraw != NULL)) + { + free(rawimage); + rawimage = NULL; + free(tmp); + continue; + } + rawimage = newraw; + memcpy(rawimage + oldsize, tmp, size); + oldsize += size; + size = oldsize; + free(tmp); + } + } + if (size == 0) { + free(rawimage); + rawimage = NULL; + continue; + } + image = malloc(size); + assert(image != NULL); + if (image == NULL) { + free(rawimage); + rawimage = NULL; + return; + } + + assert(rawimage != NULL); + + srand((unsigned)time(NULL)); + + for (i = 0; i < 1000; ++i) { + FILE *f; + int j, numbytes, trycnt; + + /* Fuzz < 1% of the bytes in the archive. */ + memcpy(image, rawimage, size); + q = (int)size / 100; + if (q < 4) + q = 4; + numbytes = (int)(rand() % q); + for (j = 0; j < numbytes; ++j) + image[rand() % size] = (char)rand(); + + /* Save the messed-up image to a file. + * If we crash, that file will be useful. */ + for (trycnt = 0; trycnt < 3; trycnt++) { + f = fopen("after.test.failure.send.this.file." + "to.libarchive.maintainers.with.system.details", "wb"); + if (f != NULL) + break; +#if defined(_WIN32) && !defined(__CYGWIN__) + /* + * Sometimes previous close operation does not completely + * end at this time. So we should take a wait while + * the operation running. + */ + Sleep(100); +#endif + } + assert(f != NULL); + assertEqualInt((size_t)size, fwrite(image, 1, (size_t)size, f)); + fclose(f); + + // Try to read all headers and bodies. + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + + if (0 == archive_read_open_memory(a, image, size)) { + while(0 == archive_read_next_header(a, &ae)) { + while (0 == archive_read_data_block(a, + &blk, &blk_size, &blk_offset)) + continue; + } + archive_read_close(a); + } + archive_read_free(a); + + // Just list headers, skip bodies. + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + + if (0 == archive_read_open_memory(a, image, size)) { + while(0 == archive_read_next_header(a, &ae)) { + } + archive_read_close(a); + } + archive_read_free(a); + } + free(image); + free(rawimage); + } +} + +DEFINE_TEST(test_fuzz_ar) +{ + static const char *fileset1[] = { + "test_read_format_ar.ar", + NULL + }; + static const struct files filesets[] = { + {0, fileset1}, + {1, NULL} + }; + test_fuzz(filesets); +} + +DEFINE_TEST(test_fuzz_cab) +{ + static const char *fileset1[] = { + "test_fuzz.cab", + NULL + }; + static const struct files filesets[] = { + {0, fileset1}, + {1, NULL} + }; + test_fuzz(filesets); +} + +DEFINE_TEST(test_fuzz_cpio) +{ + static const char *fileset1[] = { + "test_read_format_cpio_bin_be.cpio", + NULL + }; + static const char *fileset2[] = { + "test_read_format_cpio_bin_le.cpio", + NULL + }; + static const char *fileset3[] = { + /* Test RPM unwrapper */ + "test_read_format_cpio_svr4_gzip_rpm.rpm", + NULL + }; + static const struct files filesets[] = { + {0, fileset1}, + {0, fileset2}, + {0, fileset3}, + {1, NULL} + }; + test_fuzz(filesets); +} + +DEFINE_TEST(test_fuzz_iso9660) +{ + static const char *fileset1[] = { + "test_fuzz_1.iso.Z", + NULL + }; + static const struct files filesets[] = { + {0, fileset1}, /* Exercise compress decompressor. */ + {1, fileset1}, + {1, NULL} + }; + test_fuzz(filesets); +} + +DEFINE_TEST(test_fuzz_lzh) +{ + static const char *fileset1[] = { + "test_fuzz.lzh", + NULL + }; + static const struct files filesets[] = { + {0, fileset1}, + {1, NULL} + }; + test_fuzz(filesets); +} + +DEFINE_TEST(test_fuzz_mtree) +{ + static const char *fileset1[] = { + "test_read_format_mtree.mtree", + NULL + }; + static const struct files filesets[] = { + {0, fileset1}, + {1, NULL} + }; + test_fuzz(filesets); +} + +DEFINE_TEST(test_fuzz_rar) +{ + static const char *fileset1[] = { + /* Uncompressed RAR test */ + "test_read_format_rar.rar", + NULL + }; + static const char *fileset2[] = { + /* RAR file with binary data */ + "test_read_format_rar_binary_data.rar", + NULL + }; + static const char *fileset3[] = { + /* Best Compressed RAR test */ + "test_read_format_rar_compress_best.rar", + NULL + }; + static const char *fileset4[] = { + /* Normal Compressed RAR test */ + "test_read_format_rar_compress_normal.rar", + NULL + }; + static const char *fileset5[] = { + /* Normal Compressed Multi LZSS blocks RAR test */ + "test_read_format_rar_multi_lzss_blocks.rar", + NULL + }; + static const char *fileset6[] = { + /* RAR with no EOF header */ + "test_read_format_rar_noeof.rar", + NULL + }; + static const char *fileset7[] = { + /* Best Compressed RAR file with both PPMd and LZSS blocks */ + "test_read_format_rar_ppmd_lzss_conversion.rar", + NULL + }; + static const char *fileset8[] = { + /* RAR with subblocks */ + "test_read_format_rar_subblock.rar", + NULL + }; + static const char *fileset9[] = { + /* RAR with Unicode filenames */ + "test_read_format_rar_unicode.rar", + NULL + }; + static const char *fileset10[] = { + "test_read_format_rar_multivolume.part0001.rar", + "test_read_format_rar_multivolume.part0002.rar", + "test_read_format_rar_multivolume.part0003.rar", + "test_read_format_rar_multivolume.part0004.rar", + NULL + }; + static const struct files filesets[] = { + {0, fileset1}, + {0, fileset2}, + {0, fileset3}, + {0, fileset4}, + {0, fileset5}, + {0, fileset6}, + {0, fileset7}, + {0, fileset8}, + {0, fileset9}, + {0, fileset10}, + {1, NULL} + }; + test_fuzz(filesets); +} + +DEFINE_TEST(test_fuzz_tar) +{ + static const char *fileset1[] = { + "test_compat_bzip2_1.tbz", + NULL + }; + static const char *fileset2[] = { + "test_compat_gtar_1.tar", + NULL + }; + static const char *fileset3[] = { + "test_compat_gzip_1.tgz", + NULL + }; + static const char *fileset4[] = { + "test_compat_gzip_2.tgz", + NULL + }; + static const char *fileset5[] = { + "test_compat_tar_hardlink_1.tar", + NULL + }; + static const char *fileset6[] = { + "test_compat_xz_1.txz", + NULL + }; + static const char *fileset7[] = { + "test_read_format_gtar_sparse_1_17_posix10_modified.tar", + NULL + }; + static const char *fileset8[] = { + "test_read_format_tar_empty_filename.tar", + NULL + }; +#if HAVE_LIBLZO2 && HAVE_LZO_LZO1X_H && HAVE_LZO_LZOCONF_H + static const char *fileset9[] = { + "test_compat_lzop_1.tar.lzo", + NULL + }; +#endif +#if HAVE_ZSTD_H && HAVE_LIBZSTD + static const char *fileset10[] = { + "test_compat_zstd_1.tar.zst", + NULL + }; +#endif + static const struct files filesets[] = { + {0, fileset1}, /* Exercise bzip2 decompressor. */ + {1, fileset1}, + {0, fileset2}, + {0, fileset3}, /* Exercise gzip decompressor. */ + {0, fileset4}, /* Exercise gzip decompressor. */ + {0, fileset5}, + {0, fileset6}, /* Exercise xz decompressor. */ + {0, fileset7}, + {0, fileset8}, +#if HAVE_LIBLZO2 && HAVE_LZO_LZO1X_H && HAVE_LZO_LZOCONF_H + {0, fileset9}, /* Exercise lzo decompressor. */ +#endif +#if HAVE_ZSTD_H && HAVE_LIBZSTD + {0, fileset10}, /* Exercise zstd decompressor. */ +#endif + {1, NULL} + }; + test_fuzz(filesets); +} + +DEFINE_TEST(test_fuzz_zip) +{ + static const char *fileset1[] = { + "test_compat_zip_1.zip", + NULL + }; + static const char *fileset2[] = { + "test_compat_zip_2.zip", + NULL + }; + static const char *fileset3[] = { + "test_compat_zip_3.zip", + NULL + }; + static const char *fileset4[] = { + "test_compat_zip_4.zip", + NULL + }; + static const char *fileset5[] = { + "test_compat_zip_5.zip", + NULL + }; + static const char *fileset6[] = { + "test_compat_zip_6.zip", + NULL + }; + static const char *fileset7[] = { + "test_read_format_zip.zip", + NULL + }; + static const char *fileset8[] = { + "test_read_format_zip_comment_stored_1.zip", + NULL + }; + static const char *fileset9[] = { + "test_read_format_zip_comment_stored_2.zip", + NULL + }; + static const char *fileset10[] = { + "test_read_format_zip_encryption_data.zip", + NULL + }; + static const char *fileset11[] = { + "test_read_format_zip_encryption_header.zip", + NULL + }; + static const char *fileset12[] = { + "test_read_format_zip_encryption_partially.zip", + NULL + }; + static const char *fileset13[] = { + "test_read_format_zip_filename_cp866.zip", + NULL + }; + static const char *fileset14[] = { + "test_read_format_zip_filename_cp932.zip", + NULL + }; + static const char *fileset15[] = { + "test_read_format_zip_filename_koi8r.zip", + NULL + }; + static const char *fileset16[] = { + "test_read_format_zip_filename_utf8_jp.zip", + NULL + }; + static const char *fileset17[] = { + "test_read_format_zip_filename_utf8_ru.zip", + NULL + }; + static const char *fileset18[] = { + "test_read_format_zip_filename_utf8_ru2.zip", + NULL + }; + static const char *fileset19[] = { + "test_read_format_zip_length_at_end.zip", + NULL + }; + static const char *fileset20[] = { + "test_read_format_zip_mac_metadata.zip", + NULL + }; + static const char *fileset21[] = { + "test_read_format_zip_malformed1.zip", + NULL + }; + static const char *fileset22[] = { + "test_read_format_zip_msdos.zip", + NULL + }; + static const char *fileset23[] = { + "test_read_format_zip_nested.zip", + NULL + }; + static const char *fileset24[] = { + "test_read_format_zip_nofiletype.zip", + NULL + }; + static const char *fileset25[] = { + "test_read_format_zip_padded1.zip", + NULL + }; + static const char *fileset26[] = { + "test_read_format_zip_padded2.zip", + NULL + }; + static const char *fileset27[] = { + "test_read_format_zip_padded3.zip", + NULL + }; + static const char *fileset28[] = { + "test_read_format_zip_symlink.zip", + NULL + }; + static const char *fileset29[] = { + "test_read_format_zip_traditional_encryption_data.zip", + NULL + }; + static const char *fileset30[] = { + "test_read_format_zip_ux.zip", + NULL + }; + static const char *fileset31[] = { + "test_read_format_zip_winzip_aes128.zip", + NULL + }; + static const char *fileset32[] = { + "test_read_format_zip_winzip_aes256.zip", + NULL + }; + static const char *fileset33[] = { + "test_read_format_zip_winzip_aes256_large.zip", + NULL + }; + static const char *fileset34[] = { + "test_read_format_zip_winzip_aes256_stored.zip", + NULL + }; + static const char *fileset35[] = { + "test_read_format_zip_zip64a.zip", + NULL + }; + static const char *fileset36[] = { + "test_read_format_zip_zip64b.zip", + NULL + }; + + static const struct files filesets[] = { + {0, fileset1}, + {0, fileset2}, + {0, fileset3}, + {0, fileset4}, + {0, fileset5}, + {0, fileset6}, + {0, fileset7}, + {0, fileset8}, + {0, fileset9}, + {0, fileset10}, + {0, fileset11}, + {0, fileset12}, + {0, fileset13}, + {0, fileset14}, + {0, fileset15}, + {0, fileset16}, + {0, fileset17}, + {0, fileset18}, + {0, fileset19}, + {0, fileset20}, + {0, fileset21}, + {0, fileset22}, + {0, fileset23}, + {0, fileset24}, + {0, fileset25}, + {0, fileset26}, + {0, fileset27}, + {0, fileset28}, + {0, fileset29}, + {0, fileset30}, + {0, fileset31}, + {0, fileset32}, + {0, fileset33}, + {0, fileset34}, + {0, fileset35}, + {0, fileset36}, + {1, NULL} + }; + test_fuzz(filesets); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_fuzz.cab.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_fuzz.cab.uu new file mode 100644 index 0000000..4cfa4fb --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_fuzz.cab.uu @@ -0,0 +1,49 @@ +begin 644 test_fuzz.cab +M35-#1@`````1"````````"P``````````P$!``0```#X!P``A0````$``Q)K +M````````````G3U:L2``9FEL90#I!```:P``````G3TYL2``24Y35$%,3``` +M!```5`4`````G3U+L2``TJZ47W#V]K5QO-?O,*UMM1=7Z&6N(3I*B +M7Y$H"`"`C`!8T0``@@U#40&N.,IB!B,NC;`!@@1K6"S,%QZ(`(Q4^GA+7Z-Q +M>MPC#M6QMBF^#3"A)"!4#R#__T'[``````0`0$,)0S72^J;^LO[^\?\!@9<$ +M3[(/D"7DB6`%V`4Y!7D8OWK.ES^?WH/(,RQ?XK':#V<`%<.93$<2E23'(WP` +M)7`H\YE-10B('($`-H!!``R4/"3$.5!'J!3;1,@\@?1-`B@=HWZ"B`@^`"&( +M)-)S"#S&P[G2A;V@RRF$;&!`!,=HO&+@Z``H;,8AR%(.J9@/FDJ,#3,(^8?O +M>V4K7/+3XX=@"`!!VLD$Z)_'X%!H!&7IY1-0-VF)VPF='R4F#;,7L6BBQ`=R +M"_6:*GU/CI!$AA]@>9A\`EC&YR(S[1'W7Z!!OQSUC)IK20TT0=OR*6P-DC-" +M*Y7'BNFER]K*4`A,(9Q/!$\P5$\L[FO=TP8LPI\^AAD27\QHZD!IZ$2GL:^8 +MTO4<`"4Y.AE5,,C:.I;G8^&.*)I,A:M!3_=6;[RE5OS*R"?6TA0$-X3`60K/BHM/S;3F.<`#-9Z*046 +M*3`5Z1N)V-I'^O +M9O^Q$U<2F5]8ZS?2FK<94,VRT\2DOU2>GSZ"#9)KMW"^Z2BAU#YG(9=I'VG- +MQ*?V/(8N2/''>I8_?P6EYO1+]4_J(>5`(2$+W54>A!@`=W^"E;L'QT:8\-[/ +M(=#@"OL=_:MZ)N?K@^G.M"A>Y`.H5W*7?GO/X7V1_ +MV$'"#XLT\[2U]\__SY+Q#S_0FISOX&/;B-/T1?A(^O\:C;Z%TF'_](NPV!NW +M*[OS`O0Y2A>W#P$%/.6R96?&F;K@>\QVUK0=",0ET6_GY#85<;V^5_GCRY"48"Q:-[8- +M(5N^IVFN*Q]P[@Y.=_*_H"O_QN]+]4969 +M5=(\E.H;+8[+(AI*1^Q2M=+:J"5Q;8@+\K-;ZKM3S\^\!%"?M\SB;K^GFR<5 +M#*_+K(N;6O,EL^SZ=-5+Q/%K[)O8-V"%U'5>0L_R2/"A6[K._LN6*NG52SV2 +MQ&&>CA9[:JC%@I'!WUHB!AM7SH`=[7NO2QPL]--D81+0'_'J6O>EREVW;"7: +M],(<)3]RSBDD?0BEKR-`&$'\5I*<[/._6JQ1`("H*6-SYWNRRU'=CD^JQ3TM81*T2.A*"+ +M5'LQPWV.2<5=(R+X$=`^^S3=FHHS'2IG9JD.KGKM3+#FZE[UE9P87Y8WB(Z& +M?$#1[81?PAQWW:&9Y?,1JK$LLRXRM-.V(*D]U\JYX3#W'7FW4L5S]"7TN/8[ +M4Q&/5P!ZQ,QA=H1\IFOHRWNVYD15C*-L+T-9]C>6'7RFLH:&BO?ECPY_!;Q` +MU@KWHCS,^-^ +MZ#/LCR\O?](>$O]>\_+L8N`+G2PUM]*;GS>6\:%A1\=*--Q/+C*+,3D7&W\]#5RY>Y"-74FV1N1G:JRS+9$9 +MFB\V'B5R4SKVHFZ-KM\#>(-2J&^.,S6*K0WV2SW\8%PJEUN_!\MKPRDBFJG, +MN(_IL1/].QYO;D;`TV/9FMU-]?9+"WJJ[FN_>H-K#M%1P7SA:F3;T3S%?E:+ +M57(WFA^/KLK0\_=W>14EO`.P[*7Z29_5TSV^PT.+'\JJ0\PLN)MF69W:)\2- +M+5O#DLX9OMZ[S0YF#TK!1:6.6[3+7G);+S%)5>!OVFIVU@PZY\G()FA*J):) +MUKWV:;/X(O7(&,94M+<#A?Y&(X7VE576O"ZQ6R!-&3>Z7&K;GPA9\V``` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_fuzz.lzh.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_fuzz.lzh.uu new file mode 100644 index 0000000..781ebbb --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_fuzz.lzh.uu @@ -0,0 +1,152 @@ +begin 644 test_fuzz.lzh +M)L`M;&AD+0```````````$@B[!``!&1ID#Z0,GO2UL:#4M(@```#P`````2"+L(``%9FEL93&D +MYU4`@5$!`*2!Z0/I`P`80FYIQ>/Z`=-:'>9%#"P%J!\CH0"/GE$,.W6FMSD% +M*_4G02UL:#4M(@```$X`````2"+L(``%9FEL93+5%54`@5$!`+:!Z0/I`P`8 +M0FYIQV/Z`=.:'.9%#"P%J-\+H0"/'E$,.W6FMSD%*_T9?RUL:&0M&@`````` +M````2"+L(`$```!5!P`"9&ER_P4`4.A!!P!1Z0/I`P<`5(%1`0```!F!+6QH +M9"T;``````````!((NP@`0```%4(``)D:7(R_P4`4.U!!P!1Z0/I`P<`5(%1 +M`0```!YQ+6QH9"TG``````````%((^P@`05F:6QE,0``510``F1I6UL:6YK,GPN+O\%`%#MH0<`4>D# +MZ0,'`%0"HP(````>!BUL:#4M-0```#P`````2"+L(`$%9FEL93&DYU4%`%"D +M@0<`4>D#Z0,'`%2!40$`````&$)N:<7C^@'36AWF10PL!:@?(Z$`CYY1##MU +MIK40P[=::W.04K +M_34`+6QH9"T``````````(%1`0`@`@``504```7>`P`!!P`"9&ER_P4`4.A! +M!P!1Z0/I`P``-@`M;&AD+0``````````@5$!`"`"``!5!0``")D#``$(``)D +M:7(R_P4`4.U!!P!1Z0/I`P``1P`M;&AD+0```````````J,"`"`"``!5!0`` +MM*D(``%F:6QE,10``F1I6UL:6YK,GPN+O\%`%#MH0<`4>D#Z0,``#,`+6QH-2TB````/````(%1`0`@ +M`J3G504``/T!"``!9FEL93$%`%"D@0<`4>D#Z0,````80FYIQ>/Z`=-:'>9% +M#"P%J!\CH0"/GE$,.W6FMSD%*_4S`"UL:#4M(@```$X```"!40$`(`+5%54% +M```OQ@@``69I;&4R!0!0MH$'`%'I`^D#````&$)N:<=C^@'3FASF10PL!:C? +M"Z$`CQY1##MUIK@_0`9;+`0@`````+J\' +M``````0`+6QH9"T``````````(%1`0`@`P``37T````)````1J0#```%```` +M`0H````"9&ER,O\'````0!``&0```/_M00`````````````A&OY,1!K^3!T` +M``!!2H%NNP&6RP&`UD``J+*=`0!Z#]`!ELL!"`````!]%P<`````!``M;&@U +M+20````\````@5$!`"`#I.=-<0````D```!&I`,```H````!9FEL93$9```` +M_Z2!`````````````,<4_DPC&OY,'0```$$T0J**_I7+`8#60`"HLIT!_G*D +MO`&6RP$(``````KQ!P``````&4)MD:BT=H!Z:T.IZ9#S:`ZH%CJ$`A]OC1DU +M4VION(3=>H`$`"UL:#4M)````$X```"!40$`(`/5%4UQ````"0```$:D`P`` +M"@````%F:6QE,AD```#_I($`````````````(1K^3",:_DP=````0?Y%<[L! +MELL!@-9``*BRG0%8U::\`9;+`0@`````0=X'```````90FV1J.QV@'IS0XGI +MD/-H#JC&&H0"'F^-&353:F^XA-U^@#4`+6QH9"T``````````(%1`0`@`@`` +M504```7>`P`!!P`"9&ER_P4`4.A!!P!1Z0/I`P``-@`M;&AD+0`````````` +M@5$!`"`"``!5!0``")D#``$(``)D:7(R_P4`4.U!!P!1Z0/I`P``1P`M;&AD +M+0```````````J,"`"`"``!5!0``M*D(``%F:6QE,10``F1I6UL:6YK,GPN+O\%`%#MH0<`4>D#Z0,` +M`#,`+6QH,"T\````/````(%1`0`@`J3G504``+DI"``!9FEL93$%`%"D@0<` +M4>D#Z0,``"`@("`@("`@("`@("`@("`@("`@("`@("`@9FEL92`Q(&-O;G1E +M;G1S"FAE;&QO"FAE;&QO"FAE;&QO"C,`+6QH,"U.````3@```(%1`0`@`M45 +M504``+T9"``!9FEL93(%`%"V@0<`4>D#Z0,``"`@("`@("`@("`@("`@("`@ +M("`@("`@("`@9FEL92`R(&-O;G1E;G1S"FAE;&QO"FAE;&QO"FAE;&QO"FAE +M;&QO"FAE;&QO"FAE;&QO"C4`+6QH-2UW`@``Z00``&-,V4L@`H6/504``#-5 +M"@`!24Y35$%,3`4`4*2!!P!1Z0/I`P```FUK=XVV['"Z\`>$(6[`2-EZ5P&P +M^!J*0MPV*IM]&^L37/)[SD(6GCE`4$+,RA +M<%QVYXC%'H1Q`I@_B\H/L@(+W3`0@5CY6X%Q%WW+@7<`8(F7=77U]%5YG?`; +M3N&I:_6YWA$,3F@?:)>FZ!:WRP0:TH8%&:/A#VMNUUD +M[D?+:#XK%3NMR(PSF4;V"^\X0/E3JMRQ46+7\I]S@7ZJNTX[ROSD+=\7\.O# +MI:W._S>P-B(W4`=N*!<4AM0Y$,P.0&OJER*:CF[S6/=2*T4J +M8HB@[:HC'_0*&[=@,,G+98$J+TE>OL/*B^SJ]0B]?)C"QW6ESMD62-#L*]0YO*`ZHY784:YX:>BM^:'>,:IX.=Y*@R(+B)*BX24P/1>F- +M3ODP9D/YS5^9M>8OQ5I-[<^F!_.C?H\HT:!I/ZJ3)U)Z,OC8+[-;X +MMPT`HQXE(XTV!J`/FOL'T?3:#:L@[2#Y$F`?BFKE-DN]]H>'CIJ-:^/JCO\T +M.4`Z,BR&AN^@;&H.P/W[;;[KCY1@;[MRE6MWEA0[SS@BW-=BZ;/992/*144" +ME)9-=H3.#8,!KW4;K#^:HP[15TP>C!ZQL--2)IGK);'D<;J"O7.2A_4X'"IW +MB(_W\=@I^.U+$T\Q/F2:*5OSDVD#Z0,X?"UL:&0M```````````!2"/L$``69&ER,EQS +M>6UL:6YK,7PN+EQF:6QE,0``50`"HP(`[:'I`^D#.'XM;&AD+0`````````` +M`4@C[!``%F1I] +M+6QH-2TB````/`````!((NP@``5F:6QE,:3G50"!40$`I('I`^D#`!A";FG% +MX_H!TUH=YD4,+`6H'R.A`(^>40P[=::W.04K]2=!+6QH-2TB````3@````!( +M(NP@``5F:6QE,M4550"!40$`MH'I`^D#`!A";FG'8_H!TYH40P[=::W.04K_0`9?RUL:&0M&@``````````2"+L(`$```!5!P`"9&ER +M_P4`4.A!!P!1Z0/I`P<`5(%1`0```!F!+6QH9"T;``````````!((NP@`0`` +M`%4(``)D:7(R_P4`4.U!!P!1Z0/I`P<`5(%1`0```!YQ+6QH9"TG```````` +M``%((^P@`05F:6QE,0``510``F1I6UL:6YK,GPN+O\%`%#MH0<`4>D#Z0,'`%0"HP(````>!BUL:#4M +M-0```#P`````2"+L(`$%9FEL93&DYU4%`%"D@0<`4>D#Z0,'`%2!40$````` +M&$)N:<7C^@'36AWF10PL!:@?(Z$`CYY1##MUIK40P[=::W.04K_0`U`"UL:&0M``````````"! +M40$`(`(``%4%```%W@,``0<``F1ID#Z0,``#8`+6QH9"T` +M`````````(%1`0`@`@``504```B9`P`!"``"9&ER,O\%`%#M00<`4>D#Z0,` +M`$<`+6QH9"T```````````*C`@`@`@``504``+2I"``!9FEL93$4``)D:7(R +M_W-Y;6QI;FLQ?"XN_P4`4.VA!P!1Z0/I`P``1P`M;&AD+0```````````J," +M`"`"``!5!0``A^T(``%F:6QE,A0``F1I40P[=::W.04K_0`$ +M`"UL:&0M``````````"!40$`(`,``$U\````"0```$:D`P``!0````$)```` +M`F1IG-#B>F0\V@.J,8:A`(>;XT9-5-J +M;[B$W7Z``#4`+6QH9"T``````````(%1`0`@`@``504```7>`P`!!P`"9&ER +M_P4`4.A!!P!1Z0/I`P``-@`M;&AD+0``````````@5$!`"`"``!5!0``")D# +M``$(``)D:7(R_P4`4.U!!P!1Z0/I`P``1P`M;&AD+0```````````J,"`"`" +M``!5!0``M*D(``%F:6QE,10``F1I6UL:6YK,GPN+O\%`%#MH0<`4>D#Z0,``#,`+6QH,"T\````/``` +M`(%1`0`@`J3G504``+DI"``!9FEL93$%`%"D@0<`4>D#Z0,``"`@("`@("`@ +M("`@("`@("`@("`@("`@("`@9FEL92`Q(&-O;G1E;G1S"FAE;&QO"FAE;&QO +M"FAE;&QO"C,`+6QH,"U.````3@```(%1`0`@`M45504``+T9"``!9FEL93(% +M`%"V@0<`4>D#Z0,``"`@("`@("`@("`@("`@("`@("`@("`@("`@9FEL92`R +M(&-O;G1E;G1S"FAE;&QO"FAE;&QO"FAE;&QO"FAE;&QO"FAE;&QO"FAE;&QO +M"@`U`"UL:&0M``````````"!40$`(`(``%4%```%W@,``0<``F1ID#Z0,``#8`+6QH9"T``````````(%1`0`@`@``504```B9`P`!"``" +M9&ER,O\%`%#M00<`4>D#Z0,``$<`+6QH9"T```````````*C`@`@`@``504` +M`+2I"``!9FEL93$4``)D:7(R_W-Y;6QI;FLQ?"XN_P4`4.VA!P!1Z0/I`P`` +M1P`M;&AD+0```````````J,"`"`"``!5!0``A^T(``%F:6QE,A0``F1ID#Z0,````80FYIQV/Z`=.:'.9%#"P% +MJ-\+D(!'CRB&';K36YR"E?Z``#4`+6QH9"T``````````(%1`0`@`@``504` +M``7>`P`!!P`"9&ER_P4`4.A!!P!1Z0/I`P``-@`M;&AD+0``````````@5$! +M`"`"``!5!0``")D#``$(``)D:7(R_P4`4.U!!P!1Z0/I`P``1P`M;&AD+0`` +M`````````J,"`"`"``!5!0``M*D(``%F:6QE,10``F1I6UL:6YK,GPN+O\%`%#MH0<`4>D#Z0,``#,` +M+6QH-RTC````/````(%1`0`@`J3G504``!R)"``!9FEL93$%`%"D@0<`4>D# +MZ0,````80FYIQ>/Z`=-:'>9%#"P%J!\CD(!'SRB&';K36YR"E?J`,P`M;&@W +M+2,```!.````@5$!`"`"U155!0``SDX(``%F:6QE,@4`4+:!!P!1Z0/I`P`` +M`!A";FG'8_H!TYH/*(8=NM-;G(*5_H``-0`M;&@U+7<" +M``#I!```8TS92R`"A8]5!0``,U4*``%)3E-404Q,!0!0I($'`%'I`^D#```" +M;6MWC;;L<+KP!X0A;L!(V7I7`;#X&HI"W#8JFWT;ZQ-<\ESDLQ#>-O+FY91= +MO@?+_S`"5M)[O.0A:>.4!00LS*%P7';GB,4>A'$"F#^+R@^R`@O=,!"!6/E; +M@7$7?$0Q.:!]HEZ;H%P$)\YH.,]H< +MSS">!YK?+!!K2A@49H^$/:V[763N1\MH/BL5.ZW(C#.91O8+[SA`^5.JW+%1 +M8M?RGW.!?JJ[3CO*_.0MWQ?PZ\.EK<[_-[`V(C=0!VYS0\2_0M7UO5XH%Q2& +MU#D0S`Y`:^J7(IJ.;O-8]U(K12IBB*#MJB,?]`H;MV`PR5#!U11D+Z"_/*YZ,+'=:7.V19(T.PKU#F\H#JCE=A1KGAI +MZ*WYH=XQJG@YWDJ!R&E3>IWFDBLSH&=H+AD]3FI98==M/;;@-O#MU2?_ZT'9 +MV>Z&KV9B?6C-AC$X[O^PPZ739;23V`H2@29(T9[(@N(DJ+A)3`]%Z8U.^3!F0_G-7YFUYB_%6DWMSZ8'\Z-^CRC1 +MH&D_JI,G4GHR^-@OLUOARV,U\QZW#0"C'B4CC38&H`^:^P?1]-H-JR#M(/D2 +M8!^*:N4V2[WVAX>.FHUKX^J._S0Y0#HR+(:&[Z!L:@[`_?MMONN/E&!ONW*5 +M:W>6%#O/."+LEL>1QNH*](C_?QV"GX[4L33S$^9)HI6_.39R>_YC5` +!```` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_fuzz_1.iso.Z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_fuzz_1.iso.Z.uu new file mode 100644 index 0000000..07a3e93 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_fuzz_1.iso.Z.uu @@ -0,0 +1,495 @@ +$FreeBSD: head/lib/libarchive/test/test_fuzz_1.iso.Z.uu 201247 2009-12-30 05:59:21Z kientzle $ + +begin 644 test_fuzz_1.iso.Z +M'YV0``(*'$BPH,&#"!,J7,BPH<.'$"-*G$BQHL6+&#-JW,BQH\>/($.*'$FR +MI,F3*%.J7,FRIO8,.*'4NVK-FS:-.J7//JW/'D"-+GDRYLN7+F#-KWLRY +ML^?/H$.+'DVZM.G3J%.K7LVZM>O7L&/+GDV[MNW;N'/KWLV[M^_?P(,+'TZ\ +MN/'CR),K7\Z\N?/GT*-+GTZ]NO7KV+-KW\Z]N_?OX,.+'T^^O/GSZ-.K7\^^ +MO?OW\./+GT^_OOW[^//KW\^_O_^_`0Q!!`PPQ!```$;(44890DQ!!`@01BCA +MA!1***`43S11X88<1GA0%`(,)$`4'QT(0``F'H@``@"(PJ)`"(A"04(6#"0" +M`!P4E..+`;'(Q@(6),!``^"$>&)`*`+0X9),-NGDDU!&*>645%9IY9589JGE +MEEQ>V<0224SQA!%3@!#F$R#D8(,-,+R`!)D@&)$$$T5,D<445!2AH1!5S$E$ +M$5*`8`((%Q8QQ!-2/"A@"U*\0(05BDI11!!4(`H""D.D`$(,.>0P`PA%N)#% +M$U4X<0010=!Y:::;=GH#"$JX`,6D4HCIQ`NQ3C$$$G,RD82I708K;+`R$(A# +M##'(4&P.R<8P`X'@%`O#L,L<,Y`&"#VP#``,`7`"!A=L(.`SPV +M$P"4G'`69%/1=\8,'UR%V`#PO7#)%CML`L,3+VQQR1-C;/'"$E/<0L5S4VP% +MQ9E/#D`074-=^M2G,QTNLN.6>VZVJU=+[K70>FO[MN`:R[JUYF(+3KKV!B_\ +M\,07;_SQR",K`QD.-`Z!A(B#`%B'0`800A3Z\(_\A4#DAM%<""0&[YR%0&3PSE8(!)D8/85` +MM(K14`BD!N_AM%*".0&[WR$0'#PSD0(I&T8'81`K(K1/@AD!^^\@T!X +M\,XX"*0'[UR#0'SP3H(%Y)<8I5M`I(I1P`6$=!A-6$`.AE&-!61B&#V"0!:& +M4=(%I&08A>V_WHG9@$@7HX`-B-TPF@*!C`VCYA"($MZ)U8"$#:/>$`C?,(H- +M@6@,H](0B!/>R0R!8`RCQA`(%-X)#(&0"*.Z$(C%,$H+@20,HZX0B.`PB@J! +M'`ZCHA#(YS#*"8&D$J.6$(A0,0H)@0`.HXH0B!;>20B!;.&=?A`(%]Z)!X&4 +M$J,,!(!/,.>2`A.&=*PZ(&-XIN("$$J/[#8A.,6JW@!`, +MHP<+2)`Q2MN`G.&=;PL(&MXIMX!T$J-L#8A-,7H.@>@6HUP-2(\Q^@V!M.&= +MV1"(&]XY#8%D$J/-$(A,,7H,@=@6H\$0B,`PN@N!S.&=M1`('=[Y"H%4$J.I +M$(A+,3H*@<@6HYT02(TQ>@F!Y.&=D1"('MZY"(%$$J.%$(A*,?H'@;@6HZ<. +M2(PQ^NB`U!JC=PX((-[YY8`T$J-'#HA),?KB@*@6HX<+2(LQBK&`Q!JC8PN( +M(=XYL8`D$J.X#8A(,0K:@)@6HX@-2(HQ"M>`M!JCZ!`((][YN(`4$J/@$(A' +M,:H-@8@6H]002(DQZ@R!I!JCR!"()-XI#($$$J.\$(A&,6H+@7@6H[`02(@Q +MJ@J!E!JCI!`()M[I"8'T$:,C#TA%,;KP@&@6H_,.2( +M@$@6HPL+2(4QRMN`9!JCI`U(QS'*V(#$$:-T#4A"K3O!NMO][GC/>WBDAZ,C +M^3T@&0P`#@7R0<%_\_`CS-E/3]3"%\9PA@.IH0`&'Q`=#@#QF/\[`(9(`-(5 +M42!)[#P3!^)$T1?H\P&9HNFM.!`LFGZ+`^FBZ;\XD#":?HP#*:/ISSB0-)I^ +MC0-IH^G?.)`XFGZ.`ZFCZ>\XD#R:?H\#Z:/I_SB00)I^D`,II.D/.9!$FGZ1 +M`VFDZ1\YD$B:?I(#J:3I+SF03)I^DP/II.D_.9!0FGZ4`RFEZ4\YD%2:?I4# +M02*F)TL#$3:FATL#43*FUTL#\4NF%TP#T3:F9TP#@4RFITP#L3FF]TP#$4VF +M-TT#44T%0'D`H$T&@'F(IWDW<@`8)1#GE``M&!#LI``Q"$\`L``U6$\,4(/Y +MU``UV$\.4(,!]0`U6%`04(,)%0$UV%`24(,1-0$U6%$44(,:50$UZ%$64(,B +M=0$U:%(84(,JE0$UZ%(:4(,RM0$U:%,<4(,ZU0$UZ%,>4(-"]0$UV#@UR#90(U*%8G4(-FA0(U2%4J4(-NM0(U*%=0,U*%HX4(.FE0,UJ%HZ4(.NM0,U*%L\4(.VU0,UJ%L^4(,$\P,U2#=` +M4(,G5H,)(P0UJ#%#4(/2A2J:1SJ3HGFP900UB%E'4(.`A00U6%Y)4(/II00U +MB%5+4(/QQ00U6%]-4(/YY00UV%]/4(,!!@4U6&!14(,))@4UV&!34(,11@4U +M6&%54(,99@4UV&%74(,AA@4U6&)94(,II@4UV&);4(,QQ@4U6&-=4(,"XP4U +MV&-?4(-!!@8U.&1A4(,K)@8U*#AC4(/[108U:#=E4(,'8P8U2%MG4(-O@P8U +M*#=I4(-LI08UV&9K4(-+4(/QQ@@U^#B-4(/YY@@UV&^/4(,!!PDU +M6'"14(,))PDUV'"34(,11PDU6'&54(,99PDUV'&74(,AAPDU6'*94(,CIPDU +MN'";4(/SQ@DUN&V=4(/#Y@DUN&J?4(.3!@HUN&>A4(-C)@HUN&2C4(,S1@HU +M^#FE4(,#9@HUN%ZG4(,+@PHUR%NI4(.DI0HUR%BK4(-TQ0ITIW<8FJ$:NJ$< +MRAL'4C,7!``A`@LH,SK#=@LEBEQ&I*(LNJ(NVJ(P^J(R&J,T.J,V6J,X>J,Z +M&@0A$@LF8B1!,&RX8"(\M*-&FJ-(>J1*FJ1,NJ0K&B*R8"*?%Z0`D`LF^J0`,`LFPDVC$R*T8"(OPJ,`4`LFPC)E"@"V8"+N]*;O($_' +M%2+P8$]W"@#QH$][*@_^M*?S(%![2@\&M:?UH%![:@\.M:?W(%%[B@\6M:?Y +ML%%[J@\?M:?[,%)[R@\GM:?]L%)[Z@\OM:?_,%-[ZG<6I*9)`@`\]:8"8"(K +M]*8#8"(=]*8$$#1[6@`F,D1O:@`F(DYJ>@`FHE9JB@`FTEYJF@`F$F=JJ@`F +M4F]JN@`F$DUOR@`F(E9OV@`F4EYOZ@`FDF9J^@`FTFYJ"@$F$G=J&@$FPDQJ +M*@$FXE5O.@$F$EYJ2@$F4F9J6@$FDFYJ:@$FTG9J>@$F@DQOB@$FHE5OF@$F +MTEUJJ@$F$F9JN@$F4FYJR@$FDG9JV@$F,DQJZ@$F8E5O^@$FHEUJ"@(FTF5J +M&@(F$FYJ*@(F4G9J.@(F\DMO2@(F(E5O6@(F8EUJ:@(FDF5J>@(FTFUJB@(F +M$G9JF@(FHDMJJ@(FXE1JN@(F(EUOR@(F4F5JV@(FDFUJZ@(FTG5J^@(F0DMJ +M"@,FHE1JZB^$\Z8R8")1IJ8S8"+5IJ8T8")9IZ8U8"*MI*8V8")&I:8W8"+* +MI:8X8")-IJ8Y8"+1IJ8Z8")5IZ8[8"*I]*8\8")"]:8]8"+&I:8^8"))IJ8_ +M8"+-IJ9`8")1IZ9!8"*E]*9"8"(^]:9#8"+"I:9$8")%IJ9%8"+)IJ9&8")- +MIZ9'8"*A]*9(8"(Z]:9)8"*^I:9*8")!]J9+8"+%IJ9,8"))IZ9-8"*=]*9. +M8"(V]:9/8"*Z]:908"(]]J918"+!IJ928")%IZ938"*9]*948"(R]:958"*V +M]:8@&#![>@4FTFMJB@4F$G1JF@4F4DEOJ@4FXE)ON@4F(EMOR@4F4F-OV@4F +MDFMJZ@4FTG-J^@4F$DEO"@8FHE)O&@8FXEIO*@8F$F-O.@8F4FMO"GD`D'-J +M6@8FTDAO:@8F8E)O>@8FHEIOB@8FTF)OF@8F$FMOJ@8F4G-JN@8FDDAOR@8F +M(E)OV@8F8EIOZ@8FDF)O^@8FTFIO"@@@@FTFEOB@@F$G)OF@@F4D=OJ@@F +MTE!ON@@F(EEOR@@F4F%OV@@FDFEOZ@@FTG%O^@@F$D=O"@DFDE!O&@DFXEAO +M*@DF$F%O.@DF4FEO2@DFDG%O6@DFTD9O:@DF4E!O>@DFHEAOB@DFTF!OF@DF +M$FEOJ@DF4G%ON@DFDD9OR@DF$E!OV@DF8EAOZ@DFDF!O^@DFTFAO"@HF$G%O +M&@HF4D9O*@HFTD]O.@HF(EAO2@HF4F!O6@HFDFAO:@HFTG!O>@HF$D9OB@HF +MDD]OF@HFXE=OJ@HF$F!ON@HF4FAOR@HFDG!OV@HFTD5OZ@HF4D]O^@HFHE=& +MU*%F?=9HG=;LP7$K=>%?=@WRMD^DW:?[1-J`^D^D/:@#1=J&>E"DG:@+1=J,^E"D_:@3 +M1=J2>E%\#0"5RE&DC:D@-=R;2E*D[:DH-=RARE*D3:HP-=RG2E.=;2(XI=@' +MPE/9'2)`I=@\1%2*741(I=C7Q%2*S4U0I=CD1%79S2)8E=TLPU79[4Y@I=CS +M1%:*?4]HI=C[5%[9_4]LE=T#!5?9?5!TE=T+A5>*_5!\I=@3!5C9/2.$I=@< +MA5C972.,E=TD!5F*#3.4I=@LA5G9+3.*+3B#IMB'H3.L'\] +M(_\!C0````4@`32`"%`!%H0&^``!0`0\"!30`G9`#0@#B<00U!D`((,0A`R" +M,^H?S\!_%P1%!($:&``2@1-H`L!J=-S``'``!T("[($0T`$.A!\X`2M@`+B` +M19`(/D$UF`$!@*3Z(`3A@S3!%[@&9>")H$,HZ)M002O8!`2:X06P4,%[()9<@6S$I>L`VHE8$P`L3@#D$'KC`,!L$S.`1K81IT?[@P%^K" +MQG`%W5@W*83`,!@*PQ&R!;N@0/B"!2$"]D`R6!!F(1I<@[9P#>[":4@-JZ$U +MO(8X(HX$3$@AOD(OK#X180!,!&9(8$X1TBQ)VX!D7B@9@T3H0@.)&46`>C +MH.E!+"Z1(L;$T#C0T02NZ2,:V'2L+'LDR.9(^/HD621/+)(9/@BT>-:5(_L\3^* +M2+@(`*A8]VF2%Q)@K,C\:!ZKY)"\DC(R2Q[)$)&Z$)79C3OY&.VDE!X).Q(YJTCTRL/3C)T_$^K&//E)* +MDDD.22C/I*%DBXA22]9(+EF_VD^C#`#O!U)&R049)!LD1_R0$+(P6I'):ITC@>QLK5?Y(E#-@OS))2OL([>2FQI*;$E5FQE00@:VDY +MH&2LG)2E,E@^2SQ)+%5E5J0E!HPXF1EUT4)"Q#T8*=$FQUR70K-=2L.E23@+I^$\G)DAR-Q- +M@7`C\B:*I)K[T&^>S+E9,PVFFI2'FZ<@0$T8(37UY@RLFANR7D+,CADX/V;/ +M0()J,R!0%<=Y"04/WQR5H?-J:L2L63DG)HA$G+@S=^K.W=D8@DSJ!`"K,VK> +MQA,A#B-G['R86)-@UDZ5>3L59T%HG,)S;)X,?6@#C^??I)D`P&9>SEO88]K+ +M0,`JK#,<1D1>Q0?/)9U$GK-3>69/RZDO;R'O?)_P,W[*S[D09+SG5?F4Q;-Z +MRLKK23G7I^V$C0#`=ZI#_$D]`P`_1)>R,SB23JTI.-M@CXDS`X&KA$^R.3Y! +M(>S,0))6$(Z@^*2"F:!O6L\BVC:/:,\8`G$S`.S,L=)$^Z@?_:.`M",$F3T: +M$*+)#P4:)U1RVE`SFD/;H,#PF@``;%9"Z2E&>=79/)Z_HZT&@E@YI,2S@@K1'SDH1^<579Y;T#0[2@F!(P>C4K*0&5)&646#:2$]GC_%6`Z&\H%(I^#K-9RM- +MGA$3EC;0TWE+NZDW_::!-,A`4X$@38VIYR2>B72.+E)FVDF%*0#0I0'AE)K3 +MQXE,4>@U39_9U'\R3P#:8]+,0&`KT]1U!E$Y2D9=*?;DI+<3G"K4A0 +M\:<"`:#.T]:93@LJ-EV@VC2+YAMQ6A#**><!=2>`LME6E*;J1;M,7%G(-`5EEI-A^@]M:('E7VV4VYZ4[NJ5_VJZR_( +M1-6YPE.3J3IEJD#5I`I5E%H05NI$#8=)59D:U!NJ56]G&EVC!\&-4E`XZE)' +M*EHMG3(U`^)1;.4R[PI8/:R(-;%FCR!36`/"Y@BH%=6G_E4L&EA/YR,M")+4 +M&W9.>HI4S2;:S*1L,ZTZ57#P20/`6`T(=*7'R*N!X%6HZD"]H))UKC+2K:I% +M%:MMO:VX-3\$F=6Z5\JJ4FV6LI6=-D\`T%B)*P$5J5DQX&0B` +MQ;62S[Z:7&FG/HVE:C*W:M?MREWM0Y!YKG_%M\K5B_I*K^LV7:N\-2"TUK=* +M-N/J60VN396V-M>X41#DAG2UH-9TJ<)7T2I?NZM__:\`UCP$F3(S$.PK>X6< +M/=6O[M?EJE8W*@``KP$ANA[8>CI>\2E&-:\:%0FFFX&`6.[K*I64"I:\9M7_ +MR34#K(D]L2BV.@29#7M8Q.M[%;%TE<3*T@%;7X]K+PVQ%K:\(E1^"BX*`F/Q +ML-15O\+8V9I04ZR1/;)(EC@$F;8S$'[LA$6GR%7(YM@1NT^YYHHM"!WVR8;4 +M&UM=-VE=!:!W=2`$`#9*$/0J$.55<12VXEBL&F.K[(PF<[K:?]M(D3`%#:R>)B+>J4;;/8]5MN43T+`/BL +MEBV;7%;*LEDBRV.[RT#`+)!NYUJK*6N5*69FKL/VVX#;<&H8@8VTW +MR[%=L]PVHU;6M5IL`P*N?;9^5ELF6_YZ.WM,N1D(H"7;LM)MVVB_K*\5MP`W +MX`I<^@D`[NUG.;>9]L)NVNQ*;@L"MH6WL7;72EMERV/3SD`@+?H6Q"9<'>MO +M.>W`_;@@-^22A2!C<4<+PN6W7E;&,MR"6Q#R+<1-L!N7RJ9:(PD`PJP&(;,# +MP5I$KM$]NDA7*009HAL0VD:?C;@_=^+26T$; +M23&KH0V;F[5U%E!%2T49;HS(&@A6)>-66*G+8$=KTGV[ +M<#?NZH0@L*MJ):_K?;VPMR0$&=,[6RZOZ)RW;;>_4MZ"D'@_[]K-O*.7YO:8 +M<#,0<$OJ1;:,=^HZWMC+?)NO\XT(08;XWA;;FT"!+^NEN;.W(*!>W[MXV6ZW +M;;!(L.P,!-YR?-'MZIVY>O7YJM_URWX'0I`1O[N%^E91ZXM^;V'T+0C&E_NJ +MWJ];?]$H`%"C8A;G"@2=FTKY*J9%N9I6\WY+.*LP!4(#;K\0.`(?W2#S@`'` +M+WFZ,!&WZ)<(_),@/A +M8$!A,CR$,^P5?L-P&-P&&30L$-0P$(ZWMS?YYM[AFOZ,2$"%MDF8_IIA`-!M +M!L+$6,.AMPWOW3C,B!NQIPTRA5@@'.([#'7SL!+6N]YV#A<$.VQ41?"6'<.) +M&`5?WR/88\+.0%@8B-@2"V(W[(A;L2M&L4'&%$^7+0Q3]S``A<0%81)WXC`Z +M@D&Q*B[#&=;F(@D!+&[9<"`1J_XFE,C6]JD)'& +M@P,#!]Y`#(P7L0?FAE@7I,):2_I9U>$JWKNE518'A(718YS*0``8J;CZ=F-O +M6XWKL3U>J$'&'0L$>$R)?;$\5L29>'`0A)+QA_'P/V;&@]AJ#03I$H_G[SP& +MO_!L+882<8?-Q0>#'N_B8]F*-3(-[K2SM,55F(-B- +MALR%E:_'G<@P.2;7TB"3D@7"2L[(H/<7`V3P6Y$+`D8.R>?T$Y/D*"QS!W&V +M&0AC@R77XN_K=F6R4W[*?33('&7S0HM_JBVVLG6C(-QDH,Q9A7)./L@;>`KK +M4`#0=0;">E'*5IDI]U>HS);;L@<-,F59O53ER;J$>3+B(`A)&0EOY+`\BF^A +M,#X1Q'BS@I`"_`F3\;Y=QGRY&=_1/`HO!4)C=LN0.3)?PR#SF`%`V-#&7]DA +M[V2W^XV_)@C6K.)XZY9C@J!).3(ZSJ-Q.2"LEQZC5`8"WT#+=!D30V3)3)MK +MS:8YS+0-`8L)DWU^6F;)N;LW.>AD'& +M.-N7W8Q[>_,M3AP%X34'9Z)<@S-LCXDR`V&_).?JO)S7\G,^S^A9_049\*Q? +MJ+,>MLY863H'!.2\G1&S%.[+8[G:#`2,,9[?*[/H3@Q#^*L,Q`&3'].T!PX_0[H#]N_/&;SJC'>N0;8YZ9H":U1X:RX-#`=.D?K:/\09&YT0"`1 +MF/GW/F3.7'4)[6>^NJ'9LV)2],-@A"PK#231I`;^DY3:?I0Y!1 +M+@/A38?I[GNEW6Z7+@A@FBMK78.LF54T^.TQ3<90XL^6>H#5='=>Q'4Z4DMJ +M]Q!D$K6$$=%Q^CKC:0>#IC-S2[[*)QD`1)N!<#C@])B6TY,Z5:OJ\!!D1K6% +MP=2G^CI;ZIK9J<6TH7:[/:;J#(3/8:IOM7E>U<`Z6&N'(*.K-0RL]M7#U54' +MA%*-HL'R?5;,6I1%!V8"3$T+T$P[(`QMJAV;%?01E-8N +M>J8>8\.L<;GSV1Z"91L!X09TV-BUT#P*5Q[.'MMO\VY._>XU3$%`7/OZ<+]L,ETX`8` +M@YMM*V?9#+&%RT"@&YF["V=7STV[:_=B"#*NV\>8;%H(,_Q8(_MM]"V?9K6K5=T%HW_5[AE9B9XVSP2_< +M-@C46J"BV6L=H>$WZ+M(?F%TK +M;I',N)`=P$T[$B[A3"#(^7"``<05NMWDW +MYDSA*WQ[^^?\S6-]RT`@&$&QR.%^0)[K`).<1..@-A +MS"CR#,W('[DI/^4V(QE!WL)+MUW]OW@5@[]HPKS! +M&[4EO]MI$,ZR2H$PS%&Y,3_F(B'(%',`T$E8^/NNX_U572?NK"N\27#C7IOH +M>D:6UE4N9I!@^!H(-F64BV4DBLS+N3G?"$'FFPN$<.[**?@E)]/+O)E+<0P] +MSD]J^1H(ND6NO]-7SHWC +MKU5&NW-@/E/_N46_Z!0AR#CT`4S0R;=!%^@!(9_/@+O*`+7P!0=`;"GDGI%]NE"_6A#L=[NIZ9 +MZ4+R+O(4" +M@,`>$/1Z8G?AH3K'*!J(/EU]^2O'Z@!TLJOV[<#]D0>9W>YH,#LIU^RN'8!MKY6B7M`Z.VX/:Z#65P>@.,V.9_;'/RT._=;"6<7 +MI:6Q[O!]@`<9]QX0*DEL+^.S_19*\R,]PX,R6W?K?1&NH_9'FT>S>T"8-#T& +M@@T$ES+=[7A\?_"V.\@H>$VSW??YZ9SO!<&^A_(KN0`%`KAD(IZ;&IW8U.!TV:[3WS9YO[GFG:NB=],^T;6\,\96 +M?-+5B/D]'[.#3)X/")'DOO]R.V]9T;IGEN'4W'Y; +M@\(&@DKY\B^9SVMZ5&_YO%[F^>>`("%#037@NF'^*9_ +M]1H[R*AZ6P/J`[*G#PB7/LOG][$,PP9"C&GUFQO6"WN,'61ZO4#X]5*>>!/V +ME3OK`P*KU_6G?BS3L(%0:X`]S1WVV%Y@!YEI+Q"J?;+'WYG=G1I[75/J!_VN +M+_)R32`,&VNOH;.]NP?602;="YM:;Y>YO:\I]^J=RD?K-S^,XWQMW:O6FLY/ +M>4+O`?-HFQ0(!__=*_P<'602/@!H)((^WQ/\?+/?$7V27O2+EDDK]D>?1^7] +M#4."0&P@F!1V7\H7OLD/T`RO((S\;U^UE[U!=_@0']J;=5(,`(C80%`M)+^B +MG_R=KZ6#C,T7"#B?Y;?MX^Y.0[Y`6/D1G,*R<="^V)'80&@Q.9^?\_RIS_`! +M@-,7"%!?Z*_N<%_E?[ZSP?=U_MR?5"8V$&)-U.>J5#_M;^@@0_8%@MG7^MR; +MZZ_5JR]MP/[`%_M/%0#4G(&P;<[^OU?[@#\]!YF]+Q#Z/MR?XG+?P;9]:V/W +ME7WBM_(`&,[K^D2RMA%_;($$L-A!$BM]?Z:`_]\/D($/[!8+M/_STW,*OU=&? +M2)9[FC;WT;[(<[&!8%INO^Y__I(YR"Q_@=#\@3])Q\J]7]PT?G"?^?,^&!L( +M*<;Y0__QSY:#S/<7".'?^COZ!3W]S0L8'0:L0_^;__,3G(S'^! +M4/_5O^O'G.>?NO'^#7WNA:.N6O_W36G.EU_VEP>]0`&!/-&CP''#`0>A0)X`@Z!$EB0\0/J&Q'@ +M<*4"LH`R'TVWT]$Q`X%H(002@53@&Q9D0('^1A)XG1V!`4$0V`0F=3L='C,0 +ME!A38!5H!N9@0888*'!H@5@9%A@02(%?H,NWT_$Q`T&J40:>@7A@^Q5DT($& +M!QOHA:F!`0$9&`?&?P!`RS$0+!QW8!ZH"#I?088AJ'#X@2L7'Q@0V(&#X`4( +M^>5R4AWEQ\MU@`(?YE<`PEDWDL.Q"(Z"D5>0$0H&!(%$"WCW@8!:5,4W`WIB +M-2#K=P.N?RH8MN((!@0+1X^!R`P$&D4B2`K^@B!7D+$+2AR0H$%W"@(`J6`E +M6``B08S,0.!9^(+`8#3X=@49S:#%40PN:,-@0-`+*H/"WWP%R0P$(08T*`V. +M@R)7D/$-:AS7(.94#08$SR`WJ.+U&)3,0%!JB(/D8#TH<`49\:#'D0Z><>=@ +M0!`.NH.#6,HQ$(P<]*`]:!#*80"`0"AR[(.:73X8$,R#`&$PQN\!9O[>2C?G +M77[81Y5()L=!Z!$&6T$&1Q@0]!&JH"?8#79-5I?%1P.*9K(@\(0#AEUY +ME$(8$(P%.Z!0F64&&4B@0,(5!86Z'E?F$*H=1B/@AA0``*C,0=!A-X5,H%L)B +M76%!`!96A>(=5B85NAQ:8?#W#@(`K,Q`$&J$A6-A7?A?!1EQH4`P%Z*%'-[* +MY14*!&=ATC>2>6H9X4G88\`R`T')01?:A8RA=A5D((8"@6+(%\)X*U=>:'.T +MA2^AJI4!YEP;(,_E`:Z"+^`:!&=-2`(!:=@8GH:X59!A&@(`>41)6!BJ>*Z@ +M6D?#Q8(9WPU'"Z9!I15DJ',@0;C,0!!1+(:H87`(3@49O:%`\!M.AOJ>@[4: +MMH81X2+68_`R`X%E`1P*A]2A315D0(<"@72('$Y\6U1Q*'1@AK?A6`;,#`09 +MQG18'9Z'^%B+4!"4A]LAWN=@88=&!WCX_Z%ZQ,Q`T&F8A^AA?MA-!1GUH4!P +M'[:'K*"#-1X*!.RA8.B5V6I68:B&S`P$(0=^J!\^B+-4D+$@"@0-(H`8&KI3 +M_:'3(1\*A3379CB`=88QFC*&_%V((>"`)!"8B!!BBFA+!1DH(@!01[B&\)\E +M&!N"9BNADE8;-GKSH2>51TV(4@<2!,T,!`V%@Z@B#HF\4Y#Q(PH$0:*%Z`1B +M3BWBB]@<,F$``#4S$$@60B*1:"6^95%B04`E*HE@(.9T)&H=&V*"N-AA,P-! +MA5$E7HEH(OP49)")`H&9R"7*@9B3E"@0;(D&(EM'&,:(RV"/P*;^/BMB06!FU@G`F(+77*(!($S`T''X2<"BI1BX11D0(H" +M@:1H*%J"@F)!4"@NBO<;GG@2>HC%F"9(U7&"&*&HJ-+!6?"10-`J5HJP8I'X +M'A4$<02,2`">A#-BNP8+LH0W8NO'(=:"`0"FJ'8@0>C,0)!03(JQ8K(85@$` +MQ:)`<"QNBLM@D/$JSHK&WYUX*[Z%[,Q`X%@@B\IBM[@+!1G9HD"P+4*+)V&0 +MT2S*'6%B6ABJP3,#083!+7J+\&+[$V2PBP*!NT@NJGC@8D$P+H**G)Q)^!;2 +M,P-!I?$NQHL$8UH39`",`H'`>"_Z>```O1@0V(O\(G/G+PYBC9!`D'$,C`5C +MQLBA!!D58T!P,2Z,(1O"&!`HC!'C\2?QN8>78'DW^9UWE5]5)R*>C`$BG,4= +M"00SH\9H,]YF`$#-F#,RA(Y4##C-77RK7Z\X"^:(&5!IU3$"`!E'CP'0#`0% +M!<9X,SZ-UD.0L30*!$TCR!CJZ8QM1+6((*J+BQU!,Q`H%DXCU"@V0A!!AMF8.6)REF-`@#DJ +MCDN?F*@93H0MVLHHY[6,J.++&#IVB<%<'H4<"03#8^IH/$X004;Q"`"D$;8B +MW(@K^HRHW^<(X#E%`AYER/%A*ZQC0%!Q]!@8S4`04)R.QV/XN!X$&=VC0/`] +MOHYDFO+(/#Z)A1Q',Q`8%N"C^"@_,$V2'BCM,:B&CY^8Z@H>AXYP4`M)%`$$2ND$2D;@4`#)%'9`?9"D*/*N&N +M:"-V71K?KX@;YE$N9$`04<:='1D0&!'\I%L'HF8]_$T`T&B,4@6DICD)#E?`34#0<-Q26:2K*1Q$&2@D@*!*OE)8DZ< +M9$#@29*2(Z(/>3J1BH+9&[5#SG$PHRD)9WE&`@$QV4H>DZP:`&!,*I-*),7' +M1+Z":QVO"$7:AD1CSU!:P9(!0 +M!]4,!`&&/$E/'I2S09`Q4`H$!:4^Z4[=DP%!/OE/_HYP(JI'U0P$A89!B5!N +ME*Y!D'%1"@09I4-9Y2V4`4%#.5'VD'YDD8?5#`0)AT;)4;Z4J4&0L5(*!"VE +M2+E6?90!04AY4DZ,$F'DU^_ICO_>165!P%<*EJKB(!9H$`2!!F*I6&Z6 +MD4&0<5D.!)DE9`D`-)8"P6-)6>:-;%K!01`4')HE9^E:,@9!AFHY$+"6HN5G +M*1"$EJ>E\ZCB\9(9G&?8"0Z6-5H>)1>U'J]E<5D;!!G#I4!`%_65N6)_UY71 +MAM,DCBA%ZHC8BFPI$!0E=IF\VR'8)52*7!<%RF5L>A7&C +M74$0V!7=Y7?I7OH%089Z.1"PEZ*E=CD0<)?L(\267Q`$^45[^5[^EWE!D+%? +M#@3]I6@I7PH$].5YN17&C7T&0=!G^)<`9H1)%P09#>9`\&"*E@.F0%!@*IAN +MX2`6$*6&.F&]!D/%A#@0AIFA980H$%R:'F1G>D#XE10A46H2\(]VV +M.*J1>%L>M14-!#LFB>EC:@9!1H^9>D"5S67JEVC9@"YA>%@TYE$GID`07$$0R!54II5I9H8%08:8 +M.1"0F:)EEBD0;)DNII)Y4M47!$%]46:>F7@F5Q!DT)D#@9TI6JJ9`@&;&6=6 +MDWE?GD$0Y!EW9IZI:%X%08:A.1`@FJ(EGRD0^)F#YG19Y/4;!$&_D6@NFIRF +M5!!D8)H#@:8I6CJ:`@&D66EBE6Y>C)D[9H(LXR9H8]:08*9HF$<%1:1'IVEK +M%@9!!JTI$`Q%S.4S*1OZ=]*D54E-6IK69!X%:@H$_4:/<4X0!.?$IGEK/IL] +M09"Q;`X$S:9HJ6L&!+SFJ6E#TGQN!4'@5CB;T&:X210$&=WF0/!MBI;3I@OR +M9>*8J%Y\01#$%^"FN"EO_@1!AKLY$,";HF6Y*1"HF7@*1`,GF4G7`D`M!D$09O1 +M>#Z>H&=&MWD6!)ZG:"EY"@249^89(")! +MJJ71SE-2T7L:7PV!4$&'#00R$%.)SWD5N9`4V=` +M$!`1FUJ4I*)#$`0ZQ#2%!PU#C)H?Q'U^G^!G^%D('4(!@#I0$)B?!L'1>#0> +MGW=E+[1!B)_P9_QI0MR8CB+[:7]F!T'&]3D09)^BI?))>*R;CJ*D<@(-!-J$ +M]@E^OD[>I_RI@"Z@\"?YR0X4!`]H^ED0K)_WYU+I?OY"#&@&"@RA33AGU:GS +M5:`@:-)9@IA`\E<'JG,Z6/JG0,!_YIX!I=$9@KZ@KL&-`*(,!#<#$":#V@P$ +M%%9!HHA9'Z.!>$.HARB*F+4^&H@'#V5CA$HV2*B3`H,NH7+!C5"G$`1U"F1U +M(\0I8I;KN"AB%7D*09"G3%,_*!/JA4H0-T(6.A!LH39H:5,01*'/%E;1IQ`$ +M?0H76M9\H7!H`W$CK*$#01M:AHJA`@$9>H4"`(`*00"HN*%]6!PJB#8/-T(? +M.A#\H64H'2H0V*%[Z*!"$`PJ@.@@*HE2#S>"(SH00*)EJ"$J$""B>ZBA0A`8 +M*I'H)"J*X@LW@B@L*HS:!S>"+SH0`*-EJ"TJ$."B>^BC0A`\*L'H,"J- +MQ@@X*H^>!S>".SH0P*-EJ#DJ$*"C>RBF0A!@*O'H/"J0B@VBH0A"$*B'I2"J33@E0*I4F +M!S>"4SH00*5EJ%$J$""E>ZCF@:9H65WH5"J6/@?BQ`CD`@F.56E!@)7NH:T* +M(A65CJ5P*7!P([2EZ)04&J+X'7\85A&KB%DAPEL:E_ZEN\&-L)=J$'UI&4J7 +M)@EYJ0\T`O$0?BE@ZIC:!C="K2)F,:9EZ&"*)!2F>^A(I$$4$8WI8^J9Q@8W +M@F:*&YE0D>EBFH,"`+R*F'5-=*:?:6O*&MP(J:D&L9J6H:*IHW2:9D$:!#?! +MFKJFO.EI<"/@IDB";EJ&QJ9(PFRZAQ(K8A8YL9OVILRI:+""C$#*:1D*G)X( +MPND>BJR(62S"=0>,T`F6G92ARJD%$IWLHLR)FL0S:*7>JGF(&-X)Y +MJD&@IV7H=:I!@*=[*+0B9KD3Z>EZJI].!C>"?:I!X*=EJ'N*),"G>RBU(F;- +M$_GI?JJ@.@8W@H&J02"H9:A_BB0`J'LHMB)FW1,)ZH*JH28&-X*%JD%@J&6H +M@XHD0*A[J"BD0>P3&>J&JJ(2!C>"B8HDH*AEJ(>*)("H>RBX(F;]$RGJBJJC +M_@4W@HVJ0>"H9:B+>B+`J'LHN2)F#10YZHZJI.H%-X*1JD$@J66HCXHD`*E[ +M*+HB9AT42>J2JJ76!3>"E:I!8*EEJ).*)$"I>RB[(F8M%%GJEJJFP@4W@IFJ +M0:"I9:B7BB2`J7LHO")F/11IZIJJIZX%-X*=JD'@J66HFXHDP*E[*+TB9DT4 +M>>J>JJB:!3>"H:I!(*IEJ)^*)`"J>RB^(F;-"(GJHJJIA@4W@J6J06"J9:BC +MBB1`JGLHOR)F<129ZJ:JJG(%-X*IJD&@JF6HIXHD@*I[*,`B9M4(J>JJJJM> +M!3>"K:I!X*IEJ*N*),"J>RC!(F:1%+GJKJJL2@4W@K&J02"K9:BOBB0`JWLH +MPB)FP0S)ZK*JK38%-X*UJD%@JV6HLXHD0*M[*,,B9K$4V>JVJJXB!3>"N:I! +MH*MEJ+>*)("K>RC$(F;)#.GJNJJO#@4W@KVJ0>"K9:B[BB3`JWLHQ2)FT13Y +MZKZJL/H$-X+!JD$@K&6HOXHD`*Q[*,8B9D6=GJ.[%I8NK!RK5W`C6*P:!,9J +M#]&``$##.@)!K'LHQR)F\10):\?JLM8$-X+*JD&PK&4HR(HDB*R,D<^)58`L +M8M8*T;*^K$`K3'`C\*P:A,]:ALJL2`+-NH>2+&)6!_&S!JU0ZTIP(S"M&H33 +M6H82K4B"T;J'HBQBEL/PM$:M8*M)<"-PK1J$UUJ&4JU(@M6ZA[(L8M;FE+%Z +M8AMKV"JW)@4W`MNJ0;BM(RLL6+(J"2.0V;J'PBQB%O3D@[ZA&O."FQB%32+F!4\#:Z!J.&JN3*LP-,(=+DRKK/AWIJX +M(@F+:]X:36(5.(N8!4-AKIMKZQH4W`BIJP:QNH*N_MW>6KEJ$)^KZ:JSPA.\CVL:R*`LIILW#`"9;*,+%*%5;PM8I:3%\LB";FL+XLB8!5WBYCE;`VSQ.PD>R-$ +MLQK$-)O*'K,:1#+KS.ZQ>XN8]6Y1L]4L('LCA+,:Q#B;RF*S2((V^\UB%7^+ +MF/5PD;/EK!M[(\2S&L0\F\JBLTB".OO.%EPCD,M%S]:S7.R-,+B(60)M*HO/ +M(@GZ[#][N(A9&-<62]`2LS?"0ZM!1+3;ZT&K022T_^SB(F;]70/M1'O#W@@> +MK08!TJ:R%BV2@-'JL5C%XR)F>5XAK4A+PMX(+JT&`=.FLB4MDG#2_K.3BYC5 +M>\6T,NT#>R/TM!K$3YO*UK1(PDW[SUXN8M;V!=0&M?CKC<#4:A!.;2I+U"() +M1NT_N[F(6?G74PO5DJ\WPE:K072UJ>Q4BR14M?_LYR)FD5\2[5<;R`(Y(Q!; +MN[V*M4@"6?O/CBYBUA'FU;JUU>N-@-=J$'IM*JO6:A!R+4O[A8U`/]A>R]<" +MKS?"Z2)F);:I[%^+)`2V_^SJ(F8]86WM8MO%0A4C$&:[O3JV&@1D^\^^+F(6 +M)W;&-K":[4AK,(Q`IJTSN[=:MAJ$9VO8SBYBEBYVVHJPJ:T->R/0MAJ$;>O: +MW@BDK0;1V@JQ&^SM(F:A8IEM;JO:&K<:!'*[O?*V2()O2]RV5UC%[B)F$63) +MK7([T_8-(Q!VN[TRMTB"B.0MQJ$>?O;,0%N9?7O?ZK8#KIA5X+ZW +M^BV2P-\&N(VLV#`"Y66*[8$+MMX(RXN81>&FLL>+@GN:/B]BUEF6W5JX8"U9 +M-@*)N-MKAJM!;+C_[/0B9@%G%2Z)&[3>""ZN!@'CIK(@K@:!XAJVUXN8I9W% +MN#+NRWHC]+@:Q(^;RM:X2,*-^\]N+V(6?0;D!KD=ZXW`Y&H03FXJ2^0B"4;N +M/_N]B%D/VI,+Y2ZL-\*6JT%TN:GLE(LD5+G_[/@B9IUH7NZ7NZ_>"&JN!L'F +MIK)B+I)`YOZSYXN89:&-N&YNZWHCY+D:Q)Z[O<:Y2,*<^\^N+V(6D,;G]KF: +MZXV`Z&H0BN[V"N@B"8*N8?N^B%F!FH'+Z`:O-\*EJT%DNN_MHXLD1+J&[?PB +M9NEI;>ZFJZW>"*:N!H'JIK*>+I(`ZD*XKFSV-`()#E^KJKNDW@CWBYB%ZY:A +MK2Z2\.K^L_N+F,6LI;JZ[JYZ(Q2[&L2QF\KVNAK$K[N'_B](`J^VZ":[%RX` +M0.V>"-;N]LKL(@G.[C\KP(A9#!NRB^VJJC?"N*M!E+NI[+8;`'2[AJT!(V:5 +M;.;NN:NIW@CRK@9![Z:RZBZ2P.[^LPJ,F,6SU;OVKJ)Z(P2\&L3`F\KFNTC" +MOOO/.C!BUM1&\!:\>NJ-`/%J$!)O*HOP(@D*[S\KP8A9:]O$2_&JJ3?"QZM! +MA+RI[,6+)&2\_ZP%(V9M;=?NR!OE8FTC$,R[O9J\2`+*^\]J,&)6ZB;RRKR[ +M+NHV`OF\J:S+JT'8O(:M!R-F`6^:+M`+M=X(2J\&P?2^MSRO!D'T_K,BC)BE +MO?V\3J^.>B-DO1K$UIO*1KU(PM1+Z_ZR)HR81;\UO5VOD`L`I+T:Q-K[WH*] +M2(+8^\^J,&(6!,?VMKTS+]ZK0>B][RWZ@1(V:UL`8!`I>A +M%C"2@`'_LUJ,F-742<`B\%]Z([3`&L0+G,J6P$C"";R'>C%BUD\7\\;`!B]/ +M-P+YP-LK#8PDV,#_K!@C9B%V,#`0/);>"$JP!L$$I[(\L`9!!!NV9HR8Y=DU +MP4[P5'HC9,$:Q!:+)/>"(:P!H$( +MI[)^,.-QFMHQ8I9TIP(61I>(HP)3Z0W +MPBBL093"J>PFC"1TPH:M'R-FN7BF\"D\D-X(LK`&00NGLJHPDL`*_[."C)@E +MY-7"MO`\>B,$PQK$,)S*YL)(PB[\SQHR8A:61PP7P^/HC0`-:Q#2<"J+#",) +MRO`_J\B(65'>-$P-3Z,WPC>L083#J>PUC"1DP_^L(R-F>7F7\#B\H-X([K`& +M`0]OK^8PDH`._[.2C)@5Z,7#\O!^>B/TPQK$/[R]UL-(PCULV%HR8E:N)PX' +MQ+/HC<`0:Q`.<2I+$",)!K%AJ\F(6<_>0PP1CZ(WPD:L073$J>Q$C"14Q/^L +M)R-F(7L>\4<\B=X(*K$&P1*GLB(QDD`2_[.BC)CE[;7$+O$@>B/DQ!K$3IS* +MQL1(PDS\SYHR8M:Z!Q#WQ-CO#3,"*<7;*U",)`C%_ZPJ(V;%?#PQ4PR'W@A6 +ML0:!%:>R2+$&`14;MJZ,F(7T[;U:\3P,`)3%&L19_-YVQ4C"5_S/RC)B5M"7 +M%:?%3.B-0!=K$'9Q*LL6(PEN<>6+5=@R8E;6=Q?CQ3#HC4`8:Q"&<2J[%R,) +M??$_J\N(66_?88P8AZ`WPF2L053&J>QBC"0TQO^L+R-F&7Z6\65<@=X(HK$& +M01JGLIHQDL`9_[/"C)A5_"W%IC$%W"6-0+/Q]IH:(PFK\3]KS(A9OU]I7!NS +MGS?";ZQ!!,>I;&RL0>3&AJTR(V95?\+Q<&Q\W@C.L08!':>RQC&2@!S_L\Z, +MF)7^1QY(W3'&L1WG,I6QTC"=?S/2C-B5O\''H?'H.>-P!YK$.YQ*DL> +M(PGF\3]KS8A9"2!M#!\_P0#`?JQ!],?;ZWR,)-3'_ZPV(V8Q@>_Q?^QWW@@* +ML@;!(*>R`C*20"`;MMZ,F.4%-L@.-@")K$"IR*@LB(PDB\C]KSHA9@N"*S"(CG3?"C:Q!Y,BI[(N,),3( +M_ZPZ(V91@CKRCAQSW@A&L@:!)*>R/C*2`"3_L^Z,F(4(^L=*\B)<"(Y`5_+V +MVB0C"4_R/RO/B%G)8)*<)5N<-\*8K$&4R:ELE:Q!=,F&K3TC9FV#9O*93'#> +M"'*R!D$GI[)J,I+`)O^S^HR8U0[6R7:RO'DC!,H:Q*"_,_Z,V+6 +M/T@H%\KAYHT`*6L0DG(JBR@C"8KR/RO0B%D0X:1,*3^;-\*GK$&$RJGLI8PD +M9,K_K$$C9A&$6/*H;`PGA",0K+R]FLI(`JK\SRHT8A9)&"O+RM4PB30"^RO+(&02P;MA*-F$45-LO.LJ)Y +M(V3+&L2VG,I&RTC"M/S/6C1B5F"(%G?+0NF-@"YK$.KR>PLN(PGB\C^KT8A9 +M>R&WS"Z?F3?"O:Q!Y,NI[+N,),3+@C$`X-&(69*AOKPO6YDWPL&L023,J:R_ +MC"0`S/^L2"-F,8<*\\+\8]X(%K,&@3&GL@XSD@`Q_[,FC9AU'&;,&C.)>2.4 +MS!K$R9S*=LQ(PL?\SZHT8I9VB#*GS!+FC4`S:Q`VR=C.2@#?_LT*-F$4G&LV",SD< +M)8Y`C_-[6S@C"8?S/VO4B%F*(N0<.0^C-\+FK$%TSN]MXZQ!5,X%LU(C9GV* +MGO/G'!$#`*JS!L$ZO[>B,Y)`.A?,3HV8I2D&SJZS8GDCY,X:Q.Z".:S!H$^O[?>,Y(`/O^S7HV8!3&FS^JS +M('HCU,\:Q/W\WK;/2,+[7#"+-6(6R8@_Y\];,0!`0&L0!O1[RS\C"?YSY8M` +MZ[Y(XPC4@Z:R,ZA`4(/NH3Z*F)4U+L\3M/UY(W30&L0'O;WNH&_-:1JEB%EM +MXP$=0C?/`,`*K4&TT.\M"8TDF-"&K9@B9B6.+O0+_8+>"#JT!L%#O[]M%JU!A-$%\Q,Z$*"AVC,; +M/4_>"$&H!C&$8M`XZ!^680PI8A;_>,86H4EH(GV$+M(QBAXM-MX(A+0&84B_ +MMWTTDO!'?[,9AI4B9D&0AS0C[4DKTJ`T;NM(%XPW@B:M07#2[VTDC21,TA+T +M*/V8`@KM0`"@`%`!P@P`E`1``5\`I\`L4`I(0!$``F`(0\`2\$LG`43`$>!+ +M_PIY@A2P*P0!IH(O#05@")7"H<`$@`#/]!-@!1#3=4+W4`5``5``HD`%Q`F6 +M0C<]!20!6$"<,"?XTG8"GJ`G=`]Z`C--!20!0\`4`#=-"E.`+WTH.`$.R1#P +M31,!8<(00$U7`4*`KS`%]-*!@A%@*N5*_]1`=5`M5`_51'51;50? +MU4AU4JU4+]5,=5/M5#_54'54+55/U51U56U57]58=5:M56_57'57[55_U6!U +M6"U6C]5D=5EM5I_5:'5:K5:OU6QU6^U6O]5P=5PM5\_5='5=;5??U7AU7JU7 +M[]5\=5_M5__5@'5@+5@/UH1U86U8']:(=6*M6"_6C'5C[5@_UI!U9"U93]:4 +M=65M65_6F'5FK5EOUIQU9^U9?]:@=6@M6H_6I'5I;5J?UJAU:JU:K]:L=6OM +M6K_6L'5L+5O/UK1U;6U;W]:X=6ZM6^_6O'5O[5O_UL!U<"U<#]?$=7%M7!_7 +MR'5RK5POU\QU<^U6U>G]?H=7JM7J_7['5[[5Z_U_!U?"U?S]?T=7UM7]_7^'5^K5_O +MU_QU?^U?_]<`=H`M8`_8!':!;6`?V`AV@JU@+]@,=H/M8#_8$':$+6%/V!1V +MA6UA7]@8=H:M86_8'':'[6%_V"!VB"UBC]@D=HEM8I_8*':*K6*OV"QVB^UB +4O]@P=HPM8\_8-':-;6/?V#BVW0$` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_gnutar_filename_encoding.c b/dependencies/libarchive-3.4.2/libarchive/test/test_gnutar_filename_encoding.c new file mode 100644 index 0000000..3ec4f61 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_gnutar_filename_encoding.c @@ -0,0 +1,393 @@ +/*- + * Copyright (c) 2011 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +#include + +DEFINE_TEST(test_gnutar_filename_encoding_UTF8_CP866) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } + + /* + * Verify that UTF-8 filenames are correctly translated into CP866 + * and stored with hdrcharset=CP866 option. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_gnutar(a)); + if (archive_write_set_options(a, "hdrcharset=CP866") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from UTF-8 to CP866."); + archive_write_free(a); + return; + } + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set a UTF-8 filename. */ + archive_entry_set_pathname(entry, "\xD0\xBF\xD1\x80\xD0\xB8"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Above three characters in UTF-8 should translate to the following + * three characters in CP866. */ + assertEqualMem(buff, "\xAF\xE0\xA8", 3); +} + +DEFINE_TEST(test_gnutar_filename_encoding_KOI8R_UTF8) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "ru_RU.KOI8-R")) { + skipping("KOI8-R locale not available on this system."); + return; + } + + /* + * Verify that KOI8-R filenames are correctly translated into UTF-8 + * and stored with hdrcharset=UTF-8 option. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_gnutar(a)); + if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from KOI8-R to UTF-8."); + archive_write_free(a); + return; + } + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set a KOI8-R filename. */ + archive_entry_set_pathname(entry, "\xD0\xD2\xC9"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Above three characters in KOI8-R should translate to the following + * three characters (two bytes each) in UTF-8. */ + assertEqualMem(buff, "\xD0\xBF\xD1\x80\xD0\xB8", 6); +} + +DEFINE_TEST(test_gnutar_filename_encoding_KOI8R_CP866) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "ru_RU.KOI8-R")) { + skipping("KOI8-R locale not available on this system."); + return; + } + + /* + * Verify that KOI8-R filenames are correctly translated into CP866 + * and stored with hdrcharset=CP866 option. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_gnutar(a)); + if (archive_write_set_options(a, "hdrcharset=CP866") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from KOI8-R to CP866."); + archive_write_free(a); + return; + } + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set a KOI8-R filename. */ + archive_entry_set_pathname(entry, "\xD0\xD2\xC9"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Above three characters in KOI8-R should translate to the following + * three characters in CP866. */ + assertEqualMem(buff, "\xAF\xE0\xA8", 3); +} + +DEFINE_TEST(test_gnutar_filename_encoding_CP1251_UTF8) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "Russian_Russia") && + NULL == setlocale(LC_ALL, "ru_RU.CP1251")) { + skipping("KOI8-R locale not available on this system."); + return; + } + + /* + * Verify that CP1251 filenames are correctly translated into UTF-8 + * and stored with hdrcharset=UTF-8 option. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_gnutar(a)); + if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from KOI8-R to UTF-8."); + archive_write_free(a); + return; + } + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set a KOI8-R filename. */ + archive_entry_set_pathname(entry, "\xEF\xF0\xE8"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Above three characters in CP1251 should translate to the following + * three characters (two bytes each) in UTF-8. */ + assertEqualMem(buff, "\xD0\xBF\xD1\x80\xD0\xB8", 6); +} + +/* + * Do not translate CP1251 into CP866 if non Windows platform. + */ +DEFINE_TEST(test_gnutar_filename_encoding_ru_RU_CP1251) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "ru_RU.CP1251")) { + skipping("KOI8-R locale not available on this system."); + return; + } + + /* + * Verify that CP1251 filenames are not translated into any + * other character-set, in particular, CP866. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_gnutar(a)); + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set a KOI8-R filename. */ + archive_entry_set_pathname(entry, "\xEF\xF0\xE8"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Above three characters in CP1251 should not translate to + * any other character-set. */ + assertEqualMem(buff, "\xEF\xF0\xE8", 3); +} + +/* + * Other archiver applications on Windows translate CP1251 filenames + * into CP866 filenames and store it in the gnutar file. + * Test above behavior works well. + */ +DEFINE_TEST(test_gnutar_filename_encoding_Russian_Russia) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "Russian_Russia")) { + skipping("Russian_Russia locale not available on this system."); + return; + } + + /* + * Verify that Russian_Russia(CP1251) filenames are correctly translated + * to CP866. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_gnutar(a)); + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set a CP1251 filename. */ + archive_entry_set_pathname(entry, "\xEF\xF0\xE8"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Above three characters in CP1251 should translate to the following + * three characters in CP866. */ + assertEqualMem(buff, "\xAF\xE0\xA8", 3); +} + +DEFINE_TEST(test_gnutar_filename_encoding_EUCJP_UTF8) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "ja_JP.eucJP")) { + skipping("eucJP locale not available on this system."); + return; + } + + /* + * Verify that EUC-JP filenames are correctly translated to UTF-8. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_gnutar(a)); + if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from eucJP to UTF-8."); + archive_write_free(a); + return; + } + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set an EUC-JP filename. */ + archive_entry_set_pathname(entry, "\xC9\xBD.txt"); + /* Check the Unicode version. */ + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Check UTF-8 version. */ + assertEqualMem(buff, "\xE8\xA1\xA8.txt", 7); +} + +DEFINE_TEST(test_gnutar_filename_encoding_EUCJP_CP932) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "ja_JP.eucJP")) { + skipping("eucJP locale not available on this system."); + return; + } + + /* + * Verify that EUC-JP filenames are correctly translated to CP932. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_gnutar(a)); + if (archive_write_set_options(a, "hdrcharset=CP932") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from eucJP to CP932."); + archive_write_free(a); + return; + } + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set an EUC-JP filename. */ + archive_entry_set_pathname(entry, "\xC9\xBD.txt"); + /* Check the Unicode version. */ + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Check CP932 version. */ + assertEqualMem(buff, "\x95\x5C.txt", 6); +} + +DEFINE_TEST(test_gnutar_filename_encoding_CP932_UTF8) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "Japanese_Japan") && + NULL == setlocale(LC_ALL, "ja_JP.SJIS")) { + skipping("CP932/SJIS locale not available on this system."); + return; + } + + /* + * Verify that CP932/SJIS filenames are correctly translated to UTF-8. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_gnutar(a)); + if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from CP932/SJIS to UTF-8."); + archive_write_free(a); + return; + } + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set an CP932/SJIS filename. */ + archive_entry_set_pathname(entry, "\x95\x5C.txt"); + /* Check the Unicode version. */ + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Check UTF-8 version. */ + assertEqualMem(buff, "\xE8\xA1\xA8.txt", 7); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_link_resolver.c b/dependencies/libarchive-3.4.2/libarchive/test/test_link_resolver.c new file mode 100644 index 0000000..8332c4f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_link_resolver.c @@ -0,0 +1,205 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/lib/libarchive/test/test_link_resolver.c,v 1.2 2008/06/15 04:31:43 kientzle Exp $"); + +static void test_linkify_tar(void) +{ + struct archive_entry *entry, *e2; + struct archive_entry_linkresolver *resolver; + + /* Initialize the resolver. */ + assert(NULL != (resolver = archive_entry_linkresolver_new())); + archive_entry_linkresolver_set_strategy(resolver, + ARCHIVE_FORMAT_TAR_USTAR); + + /* Create an entry with only 1 link and try to linkify it. */ + assert(NULL != (entry = archive_entry_new())); + archive_entry_set_pathname(entry, "test1"); + archive_entry_set_ino(entry, 1); + archive_entry_set_dev(entry, 2); + archive_entry_set_nlink(entry, 1); + archive_entry_set_size(entry, 10); + archive_entry_linkify(resolver, &entry, &e2); + + /* Shouldn't have been changed. */ + assert(e2 == NULL); + assertEqualInt(10, archive_entry_size(entry)); + assertEqualString("test1", archive_entry_pathname(entry)); + + /* Now, try again with an entry that has 2 links. */ + archive_entry_set_pathname(entry, "test2"); + archive_entry_set_nlink(entry, 2); + archive_entry_set_ino(entry, 2); + archive_entry_linkify(resolver, &entry, &e2); + /* Shouldn't be altered, since it wasn't seen before. */ + assert(e2 == NULL); + assertEqualString("test2", archive_entry_pathname(entry)); + assertEqualString(NULL, archive_entry_hardlink(entry)); + assertEqualInt(10, archive_entry_size(entry)); + + /* Match again and make sure it does get altered. */ + archive_entry_linkify(resolver, &entry, &e2); + assert(e2 == NULL); + assertEqualString("test2", archive_entry_pathname(entry)); + assertEqualString("test2", archive_entry_hardlink(entry)); + assertEqualInt(0, archive_entry_size(entry)); + + + /* Dirs should never be matched as hardlinks, regardless. */ + archive_entry_set_pathname(entry, "test3"); + archive_entry_set_nlink(entry, 2); + archive_entry_set_filetype(entry, AE_IFDIR); + archive_entry_set_ino(entry, 3); + archive_entry_set_hardlink(entry, NULL); + archive_entry_linkify(resolver, &entry, &e2); + /* Shouldn't be altered, since it wasn't seen before. */ + assert(e2 == NULL); + assertEqualString("test3", archive_entry_pathname(entry)); + assertEqualString(NULL, archive_entry_hardlink(entry)); + + /* Dir, so it shouldn't get matched. */ + archive_entry_linkify(resolver, &entry, &e2); + assert(e2 == NULL); + assertEqualString("test3", archive_entry_pathname(entry)); + assertEqualString(NULL, archive_entry_hardlink(entry)); + + archive_entry_free(entry); + archive_entry_linkresolver_free(resolver); +} + +static void test_linkify_old_cpio(void) +{ + struct archive_entry *entry, *e2; + struct archive_entry_linkresolver *resolver; + + /* Initialize the resolver. */ + assert(NULL != (resolver = archive_entry_linkresolver_new())); + archive_entry_linkresolver_set_strategy(resolver, + ARCHIVE_FORMAT_CPIO_POSIX); + + /* Create an entry with 2 link and try to linkify it. */ + assert(NULL != (entry = archive_entry_new())); + archive_entry_set_pathname(entry, "test1"); + archive_entry_set_ino(entry, 1); + archive_entry_set_dev(entry, 2); + archive_entry_set_nlink(entry, 2); + archive_entry_set_size(entry, 10); + archive_entry_linkify(resolver, &entry, &e2); + + /* Shouldn't have been changed. */ + assert(e2 == NULL); + assertEqualInt(10, archive_entry_size(entry)); + assertEqualString("test1", archive_entry_pathname(entry)); + + /* Still shouldn't be matched. */ + archive_entry_linkify(resolver, &entry, &e2); + assert(e2 == NULL); + assertEqualString("test1", archive_entry_pathname(entry)); + assertEqualString(NULL, archive_entry_hardlink(entry)); + assertEqualInt(10, archive_entry_size(entry)); + + archive_entry_free(entry); + archive_entry_linkresolver_free(resolver); +} + +static void test_linkify_new_cpio(void) +{ + struct archive_entry *entry, *e2; + struct archive_entry_linkresolver *resolver; + + /* Initialize the resolver. */ + assert(NULL != (resolver = archive_entry_linkresolver_new())); + archive_entry_linkresolver_set_strategy(resolver, + ARCHIVE_FORMAT_CPIO_SVR4_NOCRC); + + /* Create an entry with only 1 link and try to linkify it. */ + assert(NULL != (entry = archive_entry_new())); + archive_entry_set_pathname(entry, "test1"); + archive_entry_set_ino(entry, 1); + archive_entry_set_dev(entry, 2); + archive_entry_set_nlink(entry, 1); + archive_entry_set_size(entry, 10); + archive_entry_linkify(resolver, &entry, &e2); + + /* Shouldn't have been changed. */ + assert(e2 == NULL); + assertEqualInt(10, archive_entry_size(entry)); + assertEqualString("test1", archive_entry_pathname(entry)); + + /* Now, try again with an entry that has 3 links. */ + archive_entry_set_pathname(entry, "test2"); + archive_entry_set_nlink(entry, 3); + archive_entry_set_ino(entry, 2); + archive_entry_linkify(resolver, &entry, &e2); + + /* First time, it just gets swallowed. */ + assert(entry == NULL); + assert(e2 == NULL); + + /* Match again. */ + assert(NULL != (entry = archive_entry_new())); + archive_entry_set_pathname(entry, "test3"); + archive_entry_set_ino(entry, 2); + archive_entry_set_dev(entry, 2); + archive_entry_set_nlink(entry, 2); + archive_entry_set_size(entry, 10); + archive_entry_linkify(resolver, &entry, &e2); + + /* Should get back "test2" and nothing else. */ + assertEqualString("test2", archive_entry_pathname(entry)); + assertEqualInt(0, archive_entry_size(entry)); + archive_entry_free(entry); + assert(NULL == e2); + archive_entry_free(e2); /* This should be a no-op. */ + + /* Match a third time. */ + assert(NULL != (entry = archive_entry_new())); + archive_entry_set_pathname(entry, "test4"); + archive_entry_set_ino(entry, 2); + archive_entry_set_dev(entry, 2); + archive_entry_set_nlink(entry, 3); + archive_entry_set_size(entry, 10); + archive_entry_linkify(resolver, &entry, &e2); + + /* Should get back "test3". */ + assertEqualString("test3", archive_entry_pathname(entry)); + assertEqualInt(0, archive_entry_size(entry)); + + /* Since "test4" was the last link, should get it back also. */ + assertEqualString("test4", archive_entry_pathname(e2)); + assertEqualInt(10, archive_entry_size(e2)); + + archive_entry_free(entry); + archive_entry_free(e2); + archive_entry_linkresolver_free(resolver); +} + +DEFINE_TEST(test_link_resolver) +{ + test_linkify_tar(); + test_linkify_old_cpio(); + test_linkify_new_cpio(); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_open_failure.c b/dependencies/libarchive-3.4.2/libarchive/test/test_open_failure.c new file mode 100644 index 0000000..5316a87 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_open_failure.c @@ -0,0 +1,218 @@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +#define MAGIC 123456789 +struct my_data { + int magic; + int read_return; + int read_called; + int write_return; + int write_called; + int open_return; + int open_called; + int close_return; + int close_called; +}; + +static ssize_t +my_read(struct archive *a, void *_private, const void **buff) +{ + struct my_data *private = (struct my_data *)_private; + (void)a; /* UNUSED */ + (void)buff; /* UNUSED */ + assertEqualInt(MAGIC, private->magic); + ++private->read_called; + return (private->read_return); +} + +static ssize_t +my_write(struct archive *a, void *_private, const void *buff, size_t s) +{ + struct my_data *private = (struct my_data *)_private; + (void)a; /* UNUSED */ + (void)buff; /* UNUSED */ + (void)s; /* UNUSED */ + assertEqualInt(MAGIC, private->magic); + ++private->write_called; + return (private->write_return); +} + +static int +my_open(struct archive *a, void *_private) +{ + struct my_data *private = (struct my_data *)_private; + (void)a; /* UNUSED */ + assertEqualInt(MAGIC, private->magic); + ++private->open_called; + return (private->open_return); +} + +static int +my_close(struct archive *a, void *_private) +{ + struct my_data *private = (struct my_data *)_private; + (void)a; /* UNUSED */ + assertEqualInt(MAGIC, private->magic); + ++private->close_called; + return (private->close_return); +} + + +DEFINE_TEST(test_open_failure) +{ + struct archive *a; + struct my_data private; + + memset(&private, 0, sizeof(private)); + private.magic = MAGIC; + private.open_return = ARCHIVE_FATAL; + a = archive_read_new(); + assert(a != NULL); + assertEqualInt(ARCHIVE_FATAL, + archive_read_open(a, &private, my_open, my_read, my_close)); + assertEqualInt(1, private.open_called); + assertEqualInt(0, private.read_called); + assertEqualInt(1, private.close_called); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(1, private.open_called); + assertEqualInt(0, private.read_called); + assertEqualInt(1, private.close_called); + + memset(&private, 0, sizeof(private)); + private.magic = MAGIC; + private.open_return = ARCHIVE_FAILED; + a = archive_read_new(); + assert(a != NULL); + assertEqualInt(ARCHIVE_FAILED, + archive_read_open(a, &private, my_open, my_read, my_close)); + assertEqualInt(1, private.open_called); + assertEqualInt(0, private.read_called); + assertEqualInt(1, private.close_called); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(1, private.open_called); + assertEqualInt(0, private.read_called); + assertEqualInt(1, private.close_called); + + memset(&private, 0, sizeof(private)); + private.magic = MAGIC; + private.open_return = ARCHIVE_WARN; + a = archive_read_new(); + assert(a != NULL); + assertEqualInt(ARCHIVE_WARN, + archive_read_open(a, &private, my_open, my_read, my_close)); + assertEqualInt(1, private.open_called); + assertEqualInt(0, private.read_called); + assertEqualInt(1, private.close_called); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(1, private.open_called); + assertEqualInt(0, private.read_called); + assertEqualInt(1, private.close_called); + + memset(&private, 0, sizeof(private)); + private.magic = MAGIC; + private.open_return = ARCHIVE_OK; + private.read_return = ARCHIVE_FATAL; + a = archive_read_new(); + assert(a != NULL); + assertEqualInt(ARCHIVE_OK, + archive_read_support_filter_compress(a)); + assertEqualInt(ARCHIVE_OK, archive_read_support_format_tar(a)); + assertEqualInt(ARCHIVE_FATAL, + archive_read_open(a, &private, my_open, my_read, my_close)); + assertEqualInt(1, private.open_called); + assertEqualInt(1, private.read_called); + assertEqualInt(1, private.close_called); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(1, private.open_called); + assertEqualInt(1, private.read_called); + assertEqualInt(1, private.close_called); + + memset(&private, 0, sizeof(private)); + private.magic = MAGIC; + private.open_return = ARCHIVE_FATAL; + a = archive_write_new(); + assert(a != NULL); + assertEqualInt(ARCHIVE_FATAL, + archive_write_open(a, &private, my_open, my_write, my_close)); + assertEqualInt(1, private.open_called); + assertEqualInt(0, private.write_called); + assertEqualInt(0, private.close_called); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(1, private.open_called); + assertEqualInt(0, private.write_called); + assertEqualInt(0, private.close_called); + + memset(&private, 0, sizeof(private)); + private.magic = MAGIC; + private.open_return = ARCHIVE_FATAL; + a = archive_write_new(); + assert(a != NULL); + archive_write_add_filter_compress(a); + archive_write_set_format_ustar(a); + assertEqualInt(ARCHIVE_FATAL, + archive_write_open(a, &private, my_open, my_write, my_close)); + assertEqualInt(1, private.open_called); + assertEqualInt(0, private.write_called); + assertEqualInt(0, private.close_called); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(1, private.open_called); + assertEqualInt(0, private.write_called); + assertEqualInt(0, private.close_called); + + memset(&private, 0, sizeof(private)); + private.magic = MAGIC; + private.open_return = ARCHIVE_FATAL; + a = archive_write_new(); + assert(a != NULL); + archive_write_set_format_zip(a); + assertEqualInt(ARCHIVE_FATAL, + archive_write_open(a, &private, my_open, my_write, my_close)); + assertEqualInt(1, private.open_called); + assertEqualInt(0, private.write_called); + assertEqualInt(0, private.close_called); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(1, private.open_called); + assertEqualInt(0, private.write_called); + assertEqualInt(0, private.close_called); + + memset(&private, 0, sizeof(private)); + private.magic = MAGIC; + private.open_return = ARCHIVE_FATAL; + a = archive_write_new(); + assert(a != NULL); + archive_write_add_filter_gzip(a); + assertEqualInt(ARCHIVE_FATAL, + archive_write_open(a, &private, my_open, my_write, my_close)); + assertEqualInt(1, private.open_called); + assertEqualInt(0, private.write_called); + assertEqualInt(0, private.close_called); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(1, private.open_called); + assertEqualInt(0, private.write_called); + assertEqualInt(0, private.close_called); + +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_open_fd.c b/dependencies/libarchive-3.4.2/libarchive/test/test_open_fd.c new file mode 100644 index 0000000..7da8b5e --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_open_fd.c @@ -0,0 +1,134 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_open_fd.c 201247 2009-12-30 05:59:21Z kientzle $"); + +#if defined(_WIN32) && !defined(__CYGWIN__) +#define open _open +#if !defined(__BORLANDC__) +#ifdef lseek +#undef lseek +#endif +#define lseek _lseek +#endif +#define close _close +#endif + +DEFINE_TEST(test_open_fd) +{ + char buff[64]; + struct archive_entry *ae; + struct archive *a; + int fd; + const char *skip_open_fd_err_test; + +#if defined(__BORLANDC__) + fd = open("test.tar", O_RDWR | O_CREAT | O_BINARY); +#else + fd = open("test.tar", O_RDWR | O_CREAT | O_BINARY, 0777); +#endif + assert(fd >= 0); + if (fd < 0) + return; + + /* Write an archive through this fd. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_fd(a, fd)); + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 0); + archive_entry_copy_pathname(ae, "file"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 8); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); + + /* + * Write a second file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file2"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 819200); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Now, read the data back. + */ + assert(lseek(fd, 0, SEEK_SET) == 0); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_fd(a, fd, 512)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file", archive_entry_pathname(ae)); + assert((S_IFREG | 0755) == archive_entry_mode(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff, 10)); + assertEqualMem(buff, "12345678", 8); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("file2", archive_entry_pathname(ae)); + assert((S_IFREG | 0755) == archive_entry_mode(ae)); + assertEqualInt(819200, archive_entry_size(ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a)); + + /* Verify the end of the archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + close(fd); + + skip_open_fd_err_test = getenv("SKIP_OPEN_FD_ERR_TEST"); + if(skip_open_fd_err_test == NULL) { + /* + * Verify some of the error handling. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + /* FD 100 shouldn't be open. */ + assertEqualIntA(a, ARCHIVE_FATAL, + archive_read_open_fd(a, 100, 512)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + } +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_open_file.c b/dependencies/libarchive-3.4.2/libarchive/test/test_open_file.c new file mode 100644 index 0000000..bee4b3b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_open_file.c @@ -0,0 +1,108 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_open_file.c 201247 2009-12-30 05:59:21Z kientzle $"); + +DEFINE_TEST(test_open_file) +{ + char buff[64]; + struct archive_entry *ae; + struct archive *a; + FILE *f; + + f = fopen("test.tar", "wb"); + assert(f != NULL); + if (f == NULL) + return; + + /* Write an archive through this FILE *. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_FILE(a, f)); + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 0); + archive_entry_copy_pathname(ae, "file"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 8); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); + + /* + * Write a second file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file2"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 819200); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + fclose(f); + + /* + * Now, read the data back. + */ + f = fopen("test.tar", "rb"); + assert(f != NULL); + if (f == NULL) + return; + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_FILE(a, f)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file", archive_entry_pathname(ae)); + assert((S_IFREG | 0755) == archive_entry_mode(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff, 10)); + assertEqualMem(buff, "12345678", 8); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("file2", archive_entry_pathname(ae)); + assert((S_IFREG | 0755) == archive_entry_mode(ae)); + assertEqualInt(819200, archive_entry_size(ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a)); + + /* Verify the end of the archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + fclose(f); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_open_filename.c b/dependencies/libarchive-3.4.2/libarchive/test/test_open_filename.c new file mode 100644 index 0000000..91afce2 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_open_filename.c @@ -0,0 +1,200 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_open_filename.c 191183 2009-04-17 01:06:31Z kientzle $"); + +static void +test_open_filename_mbs(void) +{ + char buff[64]; + struct archive_entry *ae; + struct archive *a; + + /* Write an archive through this FILE *. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_filename(a, "test.tar")); + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 0); + archive_entry_copy_pathname(ae, "file"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 8); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); + + /* + * Write a second file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file2"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 819200); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Now, read the data back. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, "test.tar", 512)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file", archive_entry_pathname(ae)); + assert((S_IFREG | 0755) == archive_entry_mode(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff, 10)); + assertEqualMem(buff, "12345678", 8); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("file2", archive_entry_pathname(ae)); + assert((S_IFREG | 0755) == archive_entry_mode(ae)); + assertEqualInt(819200, archive_entry_size(ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a)); + + /* Verify the end of the archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Verify some of the error handling. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_FATAL, + archive_read_open_filename(a, "nonexistent.tar", 512)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + +} + +static void +test_open_filename_wcs(void) +{ + char buff[64]; + struct archive_entry *ae; + struct archive *a; + + /* Write an archive through this FILE *. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_filename_w(a, L"test.tar")); + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 0); + archive_entry_copy_pathname_w(ae, L"file"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 8); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); + + /* + * Write a second file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname_w(ae, L"file2"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 819200); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Now, read the data back. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename_w(a, L"test.tar", 512)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualWString(L"file", archive_entry_pathname_w(ae)); + assert((S_IFREG | 0755) == archive_entry_mode(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff, 10)); + assertEqualMem(buff, "12345678", 8); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualWString(L"file2", archive_entry_pathname_w(ae)); + assert((S_IFREG | 0755) == archive_entry_mode(ae)); + assertEqualInt(819200, archive_entry_size(ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a)); + + /* Verify the end of the archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Verify some of the error handling. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_FATAL, + archive_read_open_filename_w(a, L"nonexistent.tar", 512)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + +} + +DEFINE_TEST(test_open_filename) +{ + test_open_filename_mbs(); + test_open_filename_wcs(); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_pax_filename_encoding.c b/dependencies/libarchive-3.4.2/libarchive/test/test_pax_filename_encoding.c new file mode 100644 index 0000000..2fb7f45 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_pax_filename_encoding.c @@ -0,0 +1,589 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_pax_filename_encoding.c 201247 2009-12-30 05:59:21Z kientzle $"); + +#include + +/* + * Pax interchange is supposed to encode filenames into + * UTF-8. Of course, that's not always possible. This + * test is intended to verify that filenames always get + * stored and restored correctly, regardless of the encodings. + */ + +/* + * Read a manually-created archive that has filenames that are + * stored in binary instead of UTF-8 and verify that we get + * the right filename returned and that we get a warning only + * if the header isn't marked as binary. + */ +static void +test_pax_filename_encoding_1(void) +{ + static const char testname[] = "test_pax_filename_encoding.tar"; + /* + * \314\214 is a valid 2-byte UTF-8 sequence. + * \374 is invalid in UTF-8. + */ + char filename[] = "abc\314\214mno\374xyz"; + struct archive *a; + struct archive_entry *entry; + + /* + * Read an archive that has non-UTF8 pax filenames in it. + */ + extract_reference_file(testname); + a = archive_read_new(); + assertEqualInt(ARCHIVE_OK, archive_read_support_format_tar(a)); + assertEqualInt(ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualInt(ARCHIVE_OK, + archive_read_open_filename(a, testname, 10240)); + /* + * First entry in this test archive has an invalid UTF-8 sequence + * in it, but the header is not marked as hdrcharset=BINARY, so that + * requires a warning. + */ + failure("Invalid UTF8 in a pax archive pathname should cause a warning"); + assertEqualInt(ARCHIVE_WARN, archive_read_next_header(a, &entry)); + assertEqualString(filename, archive_entry_pathname(entry)); + /* + * Second entry is identical except that it does have + * hdrcharset=BINARY, so no warning should be generated. + */ + failure("A pathname with hdrcharset=BINARY can have invalid UTF8\n" + " characters in it without generating a warning"); + assertEqualInt(ARCHIVE_OK, archive_read_next_header(a, &entry)); + assertEqualString(filename, archive_entry_pathname(entry)); + archive_read_free(a); +} + +/* + * Set the locale and write a pathname containing invalid characters. + * This should work; the underlying implementation should automatically + * fall back to storing the pathname in binary. + */ +static void +test_pax_filename_encoding_2(void) +{ + char filename[] = "abc\314\214mno\374xyz"; + struct archive *a; + struct archive_entry *entry; + char buff[65536]; + char longname[] = "abc\314\214mno\374xyz" + "/abc\314\214mno\374xyz/abcdefghijklmnopqrstuvwxyz" + "/abc\314\214mno\374xyz/abcdefghijklmnopqrstuvwxyz" + "/abc\314\214mno\374xyz/abcdefghijklmnopqrstuvwxyz" + "/abc\314\214mno\374xyz/abcdefghijklmnopqrstuvwxyz" + "/abc\314\214mno\374xyz/abcdefghijklmnopqrstuvwxyz" + "/abc\314\214mno\374xyz/abcdefghijklmnopqrstuvwxyz" + ; + size_t used; + + /* + * We need a starting locale which has invalid sequences. + * en_US.UTF-8 seems to be commonly supported. + */ + /* If it doesn't exist, just warn and return. */ + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("invalid encoding tests require a suitable locale;" + " en_US.UTF-8 not available on this system"); + return; + } + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, 0, archive_write_set_format_pax(a)); + assertEqualIntA(a, 0, archive_write_add_filter_none(a)); + assertEqualIntA(a, 0, archive_write_set_bytes_per_block(a, 0)); + assertEqualInt(0, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + assert((entry = archive_entry_new()) != NULL); + /* Set pathname, gname, uname, hardlink to nonconvertible values. */ + archive_entry_copy_pathname(entry, filename); + archive_entry_copy_gname(entry, filename); + archive_entry_copy_uname(entry, filename); + archive_entry_copy_hardlink(entry, filename); + archive_entry_set_filetype(entry, AE_IFREG); + failure("This should generate a warning for nonconvertible names."); + assertEqualInt(ARCHIVE_WARN, archive_write_header(a, entry)); + archive_entry_free(entry); + + assert((entry = archive_entry_new()) != NULL); + /* Set path, gname, uname, and symlink to nonconvertible values. */ + archive_entry_copy_pathname(entry, filename); + archive_entry_copy_gname(entry, filename); + archive_entry_copy_uname(entry, filename); + archive_entry_copy_symlink(entry, filename); + archive_entry_set_filetype(entry, AE_IFLNK); + failure("This should generate a warning for nonconvertible names."); + assertEqualInt(ARCHIVE_WARN, archive_write_header(a, entry)); + archive_entry_free(entry); + + assert((entry = archive_entry_new()) != NULL); + /* Set pathname to a very long nonconvertible value. */ + archive_entry_copy_pathname(entry, longname); + archive_entry_set_filetype(entry, AE_IFREG); + failure("This should generate a warning for nonconvertible names."); + assertEqualInt(ARCHIVE_WARN, archive_write_header(a, entry)); + archive_entry_free(entry); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Now read the entries back. + */ + + assert((a = archive_read_new()) != NULL); + assertEqualInt(0, archive_read_support_format_tar(a)); + assertEqualInt(0, archive_read_open_memory(a, buff, used)); + + assertEqualInt(0, archive_read_next_header(a, &entry)); + assertEqualString(filename, archive_entry_pathname(entry)); + assertEqualString(filename, archive_entry_gname(entry)); + assertEqualString(filename, archive_entry_uname(entry)); + assertEqualString(filename, archive_entry_hardlink(entry)); + + assertEqualInt(0, archive_read_next_header(a, &entry)); + assertEqualString(filename, archive_entry_pathname(entry)); + assertEqualString(filename, archive_entry_gname(entry)); + assertEqualString(filename, archive_entry_uname(entry)); + assertEqualString(filename, archive_entry_symlink(entry)); + + assertEqualInt(0, archive_read_next_header(a, &entry)); + assertEqualString(longname, archive_entry_pathname(entry)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +#if 0 /* Disable this until Tim check out it. */ + +/* + * Create an entry starting from a wide-character Unicode pathname, + * read it back into "C" locale, which doesn't support the name. + * TODO: Figure out the "right" behavior here. + */ +static void +test_pax_filename_encoding_3(void) +{ + wchar_t badname[] = L"xxxAyyyBzzz"; + const char badname_utf8[] = "xxx\xE1\x88\xB4yyy\xE5\x99\xB8zzz"; + struct archive *a; + struct archive_entry *entry; + char buff[65536]; + size_t used; + + badname[3] = 0x1234; + badname[7] = 0x5678; + + /* If it doesn't exist, just warn and return. */ + if (NULL == setlocale(LC_ALL, "C")) { + skipping("Can't set \"C\" locale, so can't exercise " + "certain character-conversion failures"); + return; + } + + /* If wctomb is broken, warn and return. */ + if (wctomb(buff, 0x1234) > 0) { + skipping("Cannot test conversion failures because \"C\" " + "locale on this system has no invalid characters."); + return; + } + + /* If wctomb is broken, warn and return. */ + if (wctomb(buff, 0x1234) > 0) { + skipping("Cannot test conversion failures because \"C\" " + "locale on this system has no invalid characters."); + return; + } + + /* Skip test if archive_entry_update_pathname_utf8() is broken. */ + /* In particular, this is currently broken on Win32 because + * setlocale() does not set the default encoding for CP_ACP. */ + entry = archive_entry_new(); + if (archive_entry_update_pathname_utf8(entry, badname_utf8)) { + archive_entry_free(entry); + skipping("Cannot test conversion failures."); + return; + } + archive_entry_free(entry); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, 0, archive_write_set_format_pax(a)); + assertEqualIntA(a, 0, archive_write_add_filter_none(a)); + assertEqualIntA(a, 0, archive_write_set_bytes_per_block(a, 0)); + assertEqualInt(0, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + assert((entry = archive_entry_new()) != NULL); + /* Set pathname to non-convertible wide value. */ + archive_entry_copy_pathname_w(entry, badname); + archive_entry_set_filetype(entry, AE_IFREG); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + + assert((entry = archive_entry_new()) != NULL); + archive_entry_copy_pathname_w(entry, L"abc"); + /* Set gname to non-convertible wide value. */ + archive_entry_copy_gname_w(entry, badname); + archive_entry_set_filetype(entry, AE_IFREG); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + + assert((entry = archive_entry_new()) != NULL); + archive_entry_copy_pathname_w(entry, L"abc"); + /* Set uname to non-convertible wide value. */ + archive_entry_copy_uname_w(entry, badname); + archive_entry_set_filetype(entry, AE_IFREG); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + + assert((entry = archive_entry_new()) != NULL); + archive_entry_copy_pathname_w(entry, L"abc"); + /* Set hardlink to non-convertible wide value. */ + archive_entry_copy_hardlink_w(entry, badname); + archive_entry_set_filetype(entry, AE_IFREG); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + + assert((entry = archive_entry_new()) != NULL); + archive_entry_copy_pathname_w(entry, L"abc"); + /* Set symlink to non-convertible wide value. */ + archive_entry_copy_symlink_w(entry, badname); + archive_entry_set_filetype(entry, AE_IFLNK); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Now read the entries back. + */ + + assert((a = archive_read_new()) != NULL); + assertEqualInt(0, archive_read_support_format_tar(a)); + assertEqualInt(0, archive_read_open_memory(a, buff, used)); + + failure("A non-convertible pathname should cause a warning."); + assertEqualInt(ARCHIVE_WARN, archive_read_next_header(a, &entry)); + assertEqualWString(badname, archive_entry_pathname_w(entry)); + failure("If native locale can't convert, we should get UTF-8 back."); + assertEqualString(badname_utf8, archive_entry_pathname(entry)); + + failure("A non-convertible gname should cause a warning."); + assertEqualInt(ARCHIVE_WARN, archive_read_next_header(a, &entry)); + assertEqualWString(badname, archive_entry_gname_w(entry)); + failure("If native locale can't convert, we should get UTF-8 back."); + assertEqualString(badname_utf8, archive_entry_gname(entry)); + + failure("A non-convertible uname should cause a warning."); + assertEqualInt(ARCHIVE_WARN, archive_read_next_header(a, &entry)); + assertEqualWString(badname, archive_entry_uname_w(entry)); + failure("If native locale can't convert, we should get UTF-8 back."); + assertEqualString(badname_utf8, archive_entry_uname(entry)); + + failure("A non-convertible hardlink should cause a warning."); + assertEqualInt(ARCHIVE_WARN, archive_read_next_header(a, &entry)); + assertEqualWString(badname, archive_entry_hardlink_w(entry)); + failure("If native locale can't convert, we should get UTF-8 back."); + assertEqualString(badname_utf8, archive_entry_hardlink(entry)); + + failure("A non-convertible symlink should cause a warning."); + assertEqualInt(ARCHIVE_WARN, archive_read_next_header(a, &entry)); + assertEqualWString(badname, archive_entry_symlink_w(entry)); + assertEqualWString(NULL, archive_entry_hardlink_w(entry)); + failure("If native locale can't convert, we should get UTF-8 back."); + assertEqualString(badname_utf8, archive_entry_symlink(entry)); + + assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &entry)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} +#else +static void +test_pax_filename_encoding_3(void) +{ +} +#endif + +/* + * Verify that KOI8-R filenames are correctly translated to Unicode and UTF-8. + */ +DEFINE_TEST(test_pax_filename_encoding_KOI8R) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "ru_RU.KOI8-R")) { + skipping("KOI8-R locale not available on this system."); + return; + } + + /* Check if the platform completely supports the string conversion. */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a)); + if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from KOI8-R to UTF-8."); + archive_write_free(a); + return; + } + archive_write_free(a); + + /* Re-create a write archive object since filenames should be written + * in UTF-8 by default. */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a)); + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + archive_entry_set_pathname(entry, "\xD0\xD2\xC9"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Above three characters in KOI8-R should translate to the following + * three characters (two bytes each) in UTF-8. */ + assertEqualMem(buff + 512, "15 path=\xD0\xBF\xD1\x80\xD0\xB8\x0A", 15); +} + +/* + * Verify that CP1251 filenames are correctly translated to Unicode and UTF-8. + */ +DEFINE_TEST(test_pax_filename_encoding_CP1251) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "Russian_Russia") && + NULL == setlocale(LC_ALL, "ru_RU.CP1251")) { + skipping("KOI8-R locale not available on this system."); + return; + } + + /* Check if the platform completely supports the string conversion. */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a)); + if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from KOI8-R to UTF-8."); + archive_write_free(a); + return; + } + archive_write_free(a); + + /* Re-create a write archive object since filenames should be written + * in UTF-8 by default. */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a)); + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + archive_entry_set_pathname(entry, "\xef\xf0\xe8"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Above three characters in KOI8-R should translate to the following + * three characters (two bytes each) in UTF-8. */ + assertEqualMem(buff + 512, "15 path=\xD0\xBF\xD1\x80\xD0\xB8\x0A", 15); +} + +/* + * Verify that EUC-JP filenames are correctly translated to Unicode and UTF-8. + */ +DEFINE_TEST(test_pax_filename_encoding_EUCJP) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "ja_JP.eucJP")) { + skipping("eucJP locale not available on this system."); + return; + } + + /* Check if the platform completely supports the string conversion. */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a)); + if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from eucJP to UTF-8."); + archive_write_free(a); + return; + } + archive_write_free(a); + + /* Re-create a write archive object since filenames should be written + * in UTF-8 by default. */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a)); + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + archive_entry_set_pathname(entry, "\xC9\xBD.txt"); + /* Check the Unicode version. */ + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Check UTF-8 version. */ + assertEqualMem(buff + 512, "16 path=\xE8\xA1\xA8.txt\x0A", 16); + +} + +/* + * Verify that CP932/SJIS filenames are correctly translated to Unicode and UTF-8. + */ +DEFINE_TEST(test_pax_filename_encoding_CP932) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "Japanese_Japan") && + NULL == setlocale(LC_ALL, "ja_JP.SJIS")) { + skipping("eucJP locale not available on this system."); + return; + } + + /* Check if the platform completely supports the string conversion. */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a)); + if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from CP932/SJIS to UTF-8."); + archive_write_free(a); + return; + } + archive_write_free(a); + + /* Re-create a write archive object since filenames should be written + * in UTF-8 by default. */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a)); + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + archive_entry_set_pathname(entry, "\x95\x5C.txt"); + /* Check the Unicode version. */ + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Check UTF-8 version. */ + assertEqualMem(buff + 512, "16 path=\xE8\xA1\xA8.txt\x0A", 16); + +} + +/* + * Verify that KOI8-R filenames are not translated to Unicode and UTF-8 + * when using hdrcharset=BINARY option. + */ +DEFINE_TEST(test_pax_filename_encoding_KOI8R_BINARY) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "ru_RU.KOI8-R")) { + skipping("KOI8-R locale not available on this system."); + return; + } + + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a)); + /* BINARY mode should be accepted. */ + assertEqualInt(ARCHIVE_OK, + archive_write_set_options(a, "hdrcharset=BINARY")); + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + archive_entry_set_pathname(entry, "\xD0\xD2\xC9"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* "hdrcharset=BINARY" pax attribute should be written. */ + assertEqualMem(buff + 512, "21 hdrcharset=BINARY\x0A", 21); + /* Above three characters in KOI8-R should not translate to any + * character-set. */ + assertEqualMem(buff + 512+21, "12 path=\xD0\xD2\xC9\x0A", 12); +} + +/* + * Pax format writer only accepts both BINARY and UTF-8. + * If other character-set name is specified, you will get ARCHIVE_FAILED. + */ +DEFINE_TEST(test_pax_filename_encoding_KOI8R_CP1251) +{ + struct archive *a; + + if (NULL == setlocale(LC_ALL, "ru_RU.KOI8-R")) { + skipping("KOI8-R locale not available on this system."); + return; + } + + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a)); + /* pax format writer only accepts both BINARY and UTF-8. */ + assertEqualInt(ARCHIVE_FAILED, + archive_write_set_options(a, "hdrcharset=CP1251")); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); +} + + +DEFINE_TEST(test_pax_filename_encoding) +{ + test_pax_filename_encoding_1(); + test_pax_filename_encoding_2(); + test_pax_filename_encoding_3(); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_pax_filename_encoding.tar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_pax_filename_encoding.tar.uu new file mode 100644 index 0000000..47db189 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_pax_filename_encoding.tar.uu @@ -0,0 +1,118 @@ +$FreeBSD: head/lib/libarchive/test/test_pax_filename_encoding.tar.uu 191183 2009-04-17 01:06:31Z kientzle $ +begin 644 test_pax_filename_encoding.tar +M4&%X2&5A9&5R+V%B8\R,;6YO6'AY>@`````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````#`P,#8T-"``,#`Q-S4P(``P,#$W-3`@`#`P,#`P,#`P,38V +M(#$P-S8V-C`W,#,V(#`Q-3,P-@`@>``````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````!U@HR,"!C=&EM +M93TQ,C`U-3,X-C@U"C(P(&%T:6UE/3$R,#4U,S@V,C8*,3<@4T-(24Q9+F1E +M=CTX.`HR,B!30TA)3%DN:6YO/30S,34T-#D*,3@@4T-(24Q9+FYL:6YK/3$* +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````&%B8\R,;6YO6'AY +M>@`````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````P +M,#`V-#0@`#`P,3'EZ +M```````````````````````````````````````````````````````````` +M````````````````````````````````````````````,#`P-C0T(``P,#$W +M-3`@`#`P,3'EZ"C(P(&-T:6UE +M/3$R,#4U-#$W,S4*,C`@871I;64],3(P-34S.#8R-@HQ-R!30TA)3%DN9&5V +M/3@X"C(R(%-#2$E,62YI;F\]-#,Q-3$R-@HQ."!30TA)3%DN;FQI;FL],0H` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````86)CS(QM;F_\>'EZ```````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````#`P,#8T-"``,#`Q-S4P(``P,#$W-3`@ +M`#`P,#`P,#`P,#`U(#$P-S8V-C`W,#,V(#`Q,S4W,0`@,``````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````````````!U +M``````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````!UR!M87)G:6XM8F]T=&]M.B`P+C`X +M:6X@?0H)"4@Q('L@;6%R9VEN+6)O='1O;3H@,"XP.&EN('T*"0E(,2YW97-T +M97)N('L@9F]N="UF86UI;'DZ("),:6)E2!C;VUP;&5X('!I +M96-E(&]F('-O9G1W87)E('1H870@6EN9R!N97<@<&]R=',@86YD(&9O2!S:6=N:69I8V%N="!C +M:&%N9V4@=&\@;&EB87)C:&EV92P@:6YC;'5D:6YG(&UO&5S +M+`IS:&]U;&0@8F4@86-C;VUP86YI960@8GD@;F5W('1E'!L86EN2!O9B!T:&%T(&-O;7!O;F5N="X@5&AE +M6]U +M(&YE960@=&\@9VEV92!T:&5M('1W;R!P:65C97,@;V8*:6YF;W)M871I;VXZ +M(`H\+U`^"CQ53#X*"3Q,23X\4"!35%E,13TB;6%R9VEN+6)O='1O;3H@,&EN +M(CY4:&4@9G5L;"!P871H('1O('1H92!D:7)E8W1O&5C=71A8FQE('!R;V=R86T@8F5I;F<@ +M=&5S=&5D("AN;W0*"6%P<&QI8V%B;&4@=&\@;&EB87)C:&EV95]T97-T('-I +M;F-E(&QI8F%R8VAI=F4@:7,@8V]M<&EL960@:6YT;R!T:&4*"71E'1E;G-I;VXN(%1H92!T97-T('!R;V=R86US(&QO;VL@:6X@82!F97<* +M3L@=&AE>2!N965D('1H92!F=6QL('!A=&@@=&\@ +M=&AE(&%P<')O<')I871E(&5X96-U=&%B;&4N"D%L=&AO=6=H(&)S9'1A2!I;G1E;F1E +M9"!F;W(*=&5S=&EN9R!B2!T;R!V97)I9GD@=&AA="!T:&4@=&5S=`IP2X@"CPO4#X*/%`^5VAE;B!R=6XL('1H +M92!T97-T('!R;V=R86US(&]U='!U="!A('!R;V=R97-S(&UE&5R8VES:6YG.B!B0HF;F)S<#L@=&5S=%]C;W!Y+F,Z,32YC.C$W,3H@ +M1F%I;&5D(#(V-"!T:6UE2!F;W(@9G5R=&AE +M&5R8VES960N(`H)/"]0/@H)/$Q)/CQ0/D)A&%M +M<&QE+`IM86YY(&]F('1H92!L:6)AFEP/"]45#XL"G=H:6-H('9E&%M<&QE +M(&%B;W9E*0IG96YE2!P2!S:6UP;&EF:65S(&1I86=N +M;W-I;F<*9F%I;'5R97,N(`H\+U`^"CQ(,2!#3$%34STB=V5S=&4`9GL/0!0` +-+CO?G@`````````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_rar_multivolume_multiple_files.part2.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_rar_multivolume_multiple_files.part2.rar.uu new file mode 100644 index 0000000..012399a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_rar_multivolume_multiple_files.part2.rar.uu @@ -0,0 +1,163 @@ +begin 644 test_rar_multivolume_multiple_files.part2.rar +M4F%R(1H'`!EZ2!E87-Y('1O"F%D9"!N97<@=&5S=',N*2`*/"]0/@H\ +M4#Y4:&4@=&5S="!H87)N97-S(&1E=&5R;6EN97,@=VAI8V@@=&5S=',@=&\@ +M&-E<'0@9F]R('-T9&EN+"!S=&1O=70L(&%N9"!S +M=&1E2!D:7)E8W1O2!D +M:7)E8W1O2!A2!I0H)=VAE;B!T:&4@=&5S="!S=&%R=',N(`H)/"]0/@H)/$Q)/CQ0(%-4 +M64Q%/2)M87)G:6XM8F]T=&]M.B`P:6XB/D%N>2!F:6QE2X@5&AE('1E2!D +M96)U9V=E2!D:69F97)E;G0@<&QA +M=&9O2!W'@H*2!F=6YC=&EO;G,@=&AA="!Y;W4@8V%N +M('5S92X@5&AE3PO5%0^+"`\5%0@0TQ!4U,](G=E2!T97-T6]U(&-A;B!R96-O=F5R('1H +M92!R969E2!O9B!C:&%R86-T97)S+B!4:&ES('=A2X@270GF5D +M(&9O6]U('1H:6YK"@EY;W4G=F4@9F]U;F0@82!B=6&EN9R!T:&4@8G5G+B`*"3PO4#X*"3Q,23X\ +M4"!35%E,13TB;6%R9VEN+6)O='1O;3H@,&EN(CY$3R!R=6X@86QL(&]F('1H +M92!T97-T0H)97AE6]U('-E92!A('1E6]U(&AA=F4@<75E2!R96%D(&$@<')E+6)U:6QT"FEN<'5T(&9I;&4@86YD('9E2!T:&4@2!S=')A:6=H=&9O0IA;F0@=&AE;B!O<&5N('1H92!M96UO71E&%C="!D871A(&-O;G1A:6YS('9A;'5E2!V97)I9GEI +M;F<@9FEL97,@;VX@9&ES:RX@5&\@;6%K92!T:&ES(&5A0IA +M=F%I;&%B;&4N(`H\+U`^"CQ(,B!#3$%34STB=V5S=&5R;B(^/$$@3D%-13TB +M1G5Z>E]T97-T97(B/CPO03Y&=7IZ('1E0IU2!D86UA9V5D+B`H4F5M96UB97(@=&AA="!L +M:6)AB!T97-T97(@:6YS=&5A9"!G96YE2UD86UA +M9V5D(&9I;&4L('-A=F5S('1H870@9FEL92!T;R!D:7-K+"!T:&5N(')U;G,@ +M=&AE(&9I;&4*=&AR;W5G:"!L:6)A2!T;R!PB!T97-T97(@:&%S('!R +M;W9E;B!Q=6ET92!U0IL87)G92!E;G1R +M:65S+"!U<"!T;R`Q('1E71E+B!/9B!C;W5R71E"F5N=')Y('1O(&%N('5N8V]M<')EFEP +M,@IC;VUP65R('1H870@:6UP;&5M96YT2!L87)G92!E;G1R:65S('1HF5R;RUC;W!Y+B!7:&5N('EO=2!G:79E(&ET(&$@;&%R9V4* +M8FQO8VL@=&\@=W)I=&4@=&\@86X@96YT2P@:70@=VEL;"!P87-S +M('!O:6YT97)S('-T&-E<'0@:6X@=&AO2!D +M971E8W0@=VAE;B!A(&)L;V-K(&)E:6YG('=R:71T96X@;W5T(&)Y"G1H92!A +M2!B;V1Y +M+"!A;F0@F5S('=H:6-H('1R861E(&]F9@IP;W)T86)I;&ET>2!V +M97)S=7,@'0O:'1M;#L@8VAA"DB/@H)/$U%5$$@3D%-13TB0U)%051%1"(@ +M0T].5$5.5#TB,C`Q,3`V,C8[,C(R,S4Q,#`B/@H)/$U%5$$@3D%-13TB0TA! +M3D=%1"(@0T].5$5.5#TB,C`Q,3`V,C8[,C(R-30U,#`B/@H)/%-464Q%(%19 +M4$4](G1E>'0O8W-S(CX*"3PA+2T*"0E`<&%G92![(&UAR!F;VYT +M+69A;6EL>3H@(D)I='-TR!F +M;VYT+69A;6EL>3H@(D9R965386YS(B!]"@D)4%)%+F-J:R![(&9O;G0M9F%M +M:6QY.B`B0FETR!M87)G:6XM8F]T=&]M.B`P+C`X:6X@?0H)"4@R+F-T;"![(&9O;G0M9F%M +M:6QY.B`B1G)E95-A;G,B('T*"0E45"YC:FL@>R!F;VYT+69A;6EL>3H@(D)I +M='-T"!P:65C92!O9B!S;V9T=V%R92!T +M:&%T(')U;G,@;VX*82!N=6UB97(@;V8@9&EF9F5R96YT('!L871F;W)M2X@"CPO4#X*/%`^06YY('-I9VYI9FEC86YT(&-H86YG92!T;R!L:6)A +M2!N97<@=&5S=',@;W(@8VAA;F=E&ES=&EN +M9R!T97-T0H):&]L9&EN9R!T:&4@)G%U;W0[6]U)VQL(&YE960@=&\@ +M2!T:&4*/%14($-,05-3/2)W97-T97)N(CXM2!S:&]U;&0@8F4@=7-A8FQE(&9O +M2!T:&%T('=I;&P@8F4@=7-E +M9`H)9F]R('-C2!F&5C=71A8FQE(&)E:6YG(&5X97)C:7-E +M9"X@"@D\+U`^"@D\3$D^/%`^0F%S:6,@=F5R2(^/"]!/D)A2!T:&%T(&EL;&5G86P@&-E2!W +M:71H('9A'1?:&5A9&5R*&$L("9A;7`[864I*3L*)FYB5]P871H;F%M92AA92DI.SPO +M4%)%/CQ0/@I4:&4@/%14($-,05-3/2)W97-T97)N(CYA2!D969A=6QT+`IT:&5Y(')E<&]R="!T:&4@9F%I;'5R92!A;F0@2!O9@IS<&5C:69I8R!T97-T2!E87-Y +M('1O"F%D9"!N97<@=&5S=',N*2`*/"]0/@H\4#Y4:&4@=&5S="!H87)N97-S +M(&1E=&5R;6EN97,@=VAI8V@@=&5S=',@=&\@&-E +M<'0@9F]R('-T9&EN+"!S=&1O=70L(&%N9"!S=&1E2!D:7)E8W1P6GL/0!0` +-_]75M@,````````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_rar_multivolume_multiple_files.part5.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_rar_multivolume_multiple_files.part5.rar.uu new file mode 100644 index 0000000..d5ff36a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_rar_multivolume_multiple_files.part5.rar.uu @@ -0,0 +1,163 @@ +begin 644 test_rar_multivolume_multiple_files.part5.rar +M4F%R(1H'`!EZ2X@*$EF(#Q45"!#3$%34STB=V5S=&5R;B(^+6L\ +M+U14/@H):7,@6]U+B`*"3PO4#X*"3Q, +M23X\4#Y4:&4@8W5R6]U(&-A;B!U6UL:6YK/"]45#XL"@D\5%0@0TQ!4U,](G=E3PO5%0^+`H)/%14($-, +M05-3/2)W97-T97)N(CYA&%M<&QE+"!I9B!Y;W4@;F5E9"!A +M(')E9F5R96YC92!T87(@87)C:&EV92!T;R!U2X@"CPO4#X*/%`^3&]O:R!A="`\5%0@0TQ!4U,](G=E&%M<&QE(&]F('1H:7,@=7-A9V4N(`H\+U`^"CQ0/D$@9F5W(&]F +M('1H92!O;&1E'!E6]U)W9E(&9O=6YD(&$@8G5G+"!W92!R96-O;6UE;F0@=W)I=&EN9R!T +M:&4@=&5S="!F:7)S="P@;6%K92!S=7)E"@ET:&4@=&5S="!F86EL6]U2!O +M;B`\5%0@0TQ!4U,](G=E2!A9&1I;F<@:G5S="!A(&-O=7!L92!O9B!A&ES=&EN9R!T97-T(&EN&%M<&QEQ,``(].```#8Z8%7O-C(4`4 +M,!D`I($``$QI8F%R8VAI=F5!9&1I;F=497-T+FAT;6S`S/-C(4"[3#5!2!S +M=')A:6=H=&9O0IA;F0@=&AE;B!O<&5N('1H92!M96UO71E&%C="!D +M871A(&-O;G1A:6YS('9A;'5E2!V97)I9GEI;F<@9FEL97,@;VX@9&ES +M:RX@5&\@;6%K92!T:&ES(&5A0IA=F%I;&%B;&4N(`H\+U`^ +M"CQ(,B!#3$%34STB=V5S=&5R;B(^/$$@3D%-13TB1G5Z>E]T97-T97(B/CPO +M03Y&=7IZ('1E0IU +M2!D86UA9V5D+B`H4F5M96UB97(@=&AA="!L:6)AB!T97-T97(@:6YS +M=&5A9"!G96YE2UD86UA9V5D(&9I;&4L('-A=F5S +M('1H870@9FEL92!T;R!D:7-K+"!T:&5N(')U;G,@=&AE(&9I;&4*=&AR;W5G +M:"!L:6)A2!T;R!PB!T97-T97(@:&%S('!R;W9E;B!Q=6ET92!U0IL87)G92!E;G1R:65S+"!U<"!T;R`Q('1E +M71E+B!/9B!C;W5R71E"F5N=')Y +M('1O(&%N('5N8V]M<')EFEP,@IC;VUP65R +M('1H870@:6UP;&5M96YT2!L87)G92!E;G1R:65S('1H2!H86YD;&5S(&%L;"!O9B!T:&4@8F]U;F1AF5R;RUC +M;W!Y+B!7:&5N('EO=2!G:79E(&ET(&$@;&%R9V4*8FQO8VL@=&\@=W)I=&4@ +M=&\@86X@96YT2P@:70@=VEL;"!P87-S('!O:6YT97)S('-T&-E<'0@:6X@ +M=&AO2!D971E8W0@=VAE;B!A(&)L +M;V-K(&)E:6YG('=R:71T96X@;W5T(&)Y"G1H92!A2!B;V1Y+"!A;F0@F5S +M('=H:6-H('1R861E(&]F9@IP;W)T86)I;&ET>2!V97)S=7,@PY`%`!.[9:E +)!0`````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_rar_multivolume_single_file.part1.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_rar_multivolume_single_file.part1.rar.uu new file mode 100644 index 0000000..22b5c8d --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_rar_multivolume_single_file.part1.rar.uu @@ -0,0 +1,159 @@ +begin 644 - +M4F%R(1H'`%INR!M87)G:6XZ(#`N-SEI;B!]"@D)4"![(&UAR!M87)G:6XM8F]T=&]M.B`P+C`X:6X@?0H)"4@Q+G=ER!F;VYT+69A;6EL>3H@(DQI8F5R871I;VX@4V5R:68B+"!S97)I9B!] +M"@D)2#$N8VIK('L@9F]N="UF86UI;'DZ(")":71S=')E86T@5F5R82!386YS +M(B!]"@D)2#$N8W1L('L@9F]N="UF86UI;'DZ(")&R!F;VYT+69A;6EL>3H@(D)I='-TR!F;VYT+69A;6EL>3H@(D9R965386YS(B!]"@D)5%0N8VIK('L@ +M9F]N="UF86UI;'DZ(")":71S=')E86T@5F5R82!386YS(BP@;6]N;W-P86-E +M('T*"2TM/@H)/"]35%E,13X*/"](14%$/@H\0D]$62!,04Y'/2)E;BU54R(@ +M1$E2/2),5%(B/@H\2#$@0TQ!4U,](G=E2X@"CPO4#X*/%`^06YY('-I9VYI9FEC86YT(&-H +M86YG92!T;R!L:6)A2!N97<@=&5S=',@;W(@8VAA;F=E +M&ES=&EN9R!T97-T0H):&]L9&EN9R!T:&4@ +M)G%U;W0[6]U +M)VQL(&YE960@=&\@2!T:&4*/%14($-,05-3/2)W97-T97)N(CXM +M2!S:&]U;&0@ +M8F4@=7-A8FQE(&9O2!F&5C=71A8FQE(&)E +M:6YG(&5X97)C:7-E9"X@"@D\+U`^"@D\3$D^/%`^0F%S:6,@=F5R2(^/"]!/D)A2!T:&%T(&EL;&5G86P@&-E2!W:71H('9A'1R +M86-T7W)E9F5R96YC95]F:6QE*&YA;64I.PHF;F)S<#L@)FYB'1?:&5A9&5R*&$L("9A;7`[864I*3L* +M)FYB5]P871H +M;F%M92AA92DI.SPO4%)%/CQ0/@I4:&4@/%14($-,05-3/2)W97-T97)N(CYA +M2!D969A=6QT+`IT:&5Y(')E<&]R="!T:&4@9F%I;'5R +M92!A;F0@EGL/0!0`O*TOS@`````````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_rar_multivolume_single_file.part2.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_rar_multivolume_single_file.part2.rar.uu new file mode 100644 index 0000000..e00e06c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_rar_multivolume_single_file.part2.rar.uu @@ -0,0 +1,159 @@ +begin 644 - +M4F%R(1H'`!EZ2!P2!S:6UP;&EF:65S(&1I86=N;W-I;F<*9F%I +M;'5R97,N(`H\+U`^"CQ(,2!#3$%34STB=V5S=&5R;B(^/$$@3D%-13TB3&EF +M95]C>6-L95]O9E]A7W1E"UL:6ME('!L871F;W)M +M2!T;PIA9&0@;F5W('1E2X@*$EF(#Q45"!#3$%34STB=V5S=&5R;B(^+6L\ +M+U14/@H):7,@6]U+B`*"3PO4#X*"3Q, +M23X\4#Y4:&4@8W5R6]U(&-A;B!U6UL:6YK/"]45#XL"@D\5%0@0TQ!4U,](G=E3PO5%0^+`H)/%14($-, +M05-3/2)W97-T97)N(CYA&%M<&QE+"!I9B!Y;W4@;F5E9"!A +M(')E9F5R96YC92!T87(@87)C:&EV92!T;R!U2X@"CPO4#X*/%`^3&]O:R!A="`\5%0@0TQ!4U,](G=E&%M<&QE(&]F('1H:7,@=7-A9V4N(`H\+U`^"CQ0/D$@9F5W(&]F +M('1H92!O;&1E'!E6]U)W9E(&9O=6YD(&$@8G5G+"!W92!R96-O;6UE;F0@=W)I=&EN9R!T +M:&4@=&5S="!F:7)S="P@;6%K92!S=7)E"@ET:&4@=&5S="!F86EL6]U2!R=6X*"6%L;"!O9B!T:&4@=&5S=',N(`H)/"]0/@H)/$Q)/CQ0(%-4 +M64Q%/2)M87)G:6XM8F]T=&]M.B`P:6XB/D1/3B=4(')E;'D@;VX@/%14($-, +M05-3/2)W97-T97)N(CY(059%7SPO5%0^"@EM86-R;W,@9G)O;2!C;VYF:60H)97AE +M6]U('-E92!A +M('1E6]U(&AA=F4@<75E2!R96%D(&$@<')E+6)U:6QT"FEN +M<'5T(&9I;&4@86YD('9E2!T:&4@2!S=')A:6=H=&9O0IA;F0@=&AE +M;B!O<&5N('1H92!M96UO71E&%C="!D871A(&-O;G1A:6YS +M('9A;'5E2!V97)I9GEI;F<@9FEL97,@;VX@9&ES:RX@5&\@;6%K92!T +M:&ES(&5A0IA=F%I;&%B;&4N(`H\+U`^"CQ(,B!#3$%34STB +M=V5S=&5R;B(^/$$@3D%-13TB1G5Z>E]T97-T97(B/CPO03Y&=7IZ('1E0IU2!D86UA9V5D +M+B`H4F5M96UB97(@=&AA="!L:6)AB!T97-T97(@:6YS=&5A9"!G96YE2UD86UA9V5D(&9I;&4L('-A=F5S('1H870@9FEL92!T +M;R!D:7-K+"!T:&5N(')U;G,@=&AE(&9I;&4*=&AR;W5G:"!L:6)A2!T;R!PB!T97-T97(@:&%S('!R;W9E;B!Q=6ET92!U0IL87)G92!E;G1R:65S+"!U<"!T;R`Q('1E71E+B!/9B!C +M;W5R71E"F5N=')Y('1O(&%N('5N8V]M +M<')EFEP,@IC;VUP65R('1H870@:6UP;&5M +M96YT2!L87)G +M92!E;G1R:65S('1H2!H86YD +M;&5S(&%L;"!O9B!T:&4@8F]U;F1AF5R;RUC;W!Y+B!7:&5N('EO +M=2!G:79E(&ET(&$@;&%R9V4*8FQO8VL@=&\@=W)I=&4@=&\@86X@96YT2P@:70@=VEL;"!P87-S('!O:6YT97)S('-T&-E<'0@:6X@=&AO2!D971E8W0@=VAE;B!A(&)L;V-K(&)E:6YG('=R +M:71T96X@;W5T(&)Y"G1H92!A2!B;V1Y+"!A;F0@F5S('=H:6-H('1R861E +M(&]F9@IP;W)T86)I;&ET>2!V97)S=7,@5>PY`%`"G$@X2`@`````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_rar_multivolume_uncompressed_files.part01.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_rar_multivolume_uncompressed_files.part01.rar.uu new file mode 100644 index 0000000..876b7e9 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_rar_multivolume_uncompressed_files.part01.rar.uu @@ -0,0 +1,299 @@ +begin 644 - +M4F%R(1H'`%INR!M87)G:6XZ(#`N-SEI;B!]"@D)4"![(&UAR!M87)G:6XM8F]T=&]M.B`P+C`X:6X@?0H) +M"4@Q+G=ER!F;VYT+69A;6EL>3H@(DQI8F5R871I;VX@4V5R:68B +M+"!S97)I9B!]"@D)2#$N8VIK('L@9F]N="UF86UI;'DZ(")":71S=')E86T@ +M5F5R82!386YS(B!]"@D)2#$N8W1L('L@9F]N="UF86UI;'DZ(")&R!F;VYT+69A;6EL>3H@(D)I='-TR!F;VYT+69A;6EL>3H@(D9R965386YS(B!]"@D) +M5%0N8VIK('L@9F]N="UF86UI;'DZ(")":71S=')E86T@5F5R82!386YS(BP@ +M;6]N;W-P86-E('T*"2TM/@H)/"]35%E,13X*/"](14%$/@H\0D]$62!,04Y' +M/2)E;BU54R(@1$E2/2),5%(B/@H\2#$@0TQ!4U,](G=E2X@"CPO4#X*/%`^06YY('-I9VYI +M9FEC86YT(&-H86YG92!T;R!L:6)A2!N97<@=&5S=',@ +M;W(@8VAA;F=E&ES=&EN9R!T97-T0H):&]L +M9&EN9R!T:&4@)G%U;W0[6]U)VQL(&YE960@=&\@2!T:&4*/%14($-,05-3/2)W +M97-T97)N(CXM2!S:&]U;&0@8F4@=7-A8FQE(&9O2!T:&%T('=I;&P@8F4@=7-E9`H)9F]R('-C2!F&5C +M=71A8FQE(&)E:6YG(&5X97)C:7-E9"X@"@D\+U`^"@D\3$D^/%`^0F%S:6,@ +M=F5R2(^/"]!/D)A2!T:&%T(&EL;&5G86P@&-E2!W:71H('9A'1R86-T7W)E9F5R96YC95]F:6QE*&YA;64I.PHF;F)S<#L@)FYB +M'1?:&5A9&5R*&$L("9A +M;7`[864I*3L*)FYB5]P871H;F%M92AA92DI.SPO4%)%/CQ0/@I4:&4@/%14($-,05-3/2)W +M97-T97)N(CYA2!D969A=6QT+`IT:&5Y(')E<&]R="!T +M:&4@9F%I;'5R92!A;F0@2!O9@IS<&5C:69I +M8R!T97-T2!E87-Y('1O"F%D9"!N97<@=&5S=',N*2`*/"]0 +M/@H\4#Y4:&4@=&5S="!H87)N97-S(&1E=&5R;6EN97,@=VAI8V@@=&5S=',@ +M=&\@&-E<'0@9F]R('-T9&EN+"!S=&1O=70L(&%N +M9"!S=&1E2!D:7)E8W1O2!D:7)E8W1O2!A2!I +M0H)=VAE;B!T:&4@=&5S="!S=&%R=',N(`H)/"]0/@H)/$Q)/CQ0 +M(%-464Q%/2)M87)G:6XM8F]T=&]M.B`P:6XB/D%N>2!F:6QE2X@5&AE('1E +M2!D96)U9V=E2!D:69F97)E;G0@ +M<&QA=&9O2!W2!T;R!U'@H*2!F=6YC=&EO;G,@=&AA="!Y;W4@ +M8V%N('5S92X@5&AEF4\+U14/BP@/%14($-,05-3/2)W +M97-T97)N(CYA3PO5%0^+"`\5%0@0TQ!4U,](G=E2!T97-T6]U(&-A;B!R96-O=F5R +M('1H92!R969E2!O9B!C:&%R86-T97)S+B!4:&ES('=A2X@270G6]U)W9E(&9O=6YD(&$@8G5G+"!W92!R96-O;6UE;F0@=W)I +M=&EN9R!T:&4@=&5S="!F:7)S="P@;6%K92!S=7)E"@ET:&4@=&5S="!F86EL +M6]U +M2!O;B`\5%0@0TQ!4U,](G=E2!A9&1I;F<@:G5S="!A(&-O=7!L92!O9B!A&ES=&EN9R!T97-T(&EN&%M<&QE +M'1R86-T7W)E9F5R +M96YC95]F:6QE*"D\+U14/@IT;R!D96-O9&4@82!U=65N8V]D960@:6YP=70@ +M9FEL92P@=&AE;B!O<&5N('1H870@9FEL92!W:71H(&QI8F%R8VAI=F4*86YD +M('9E2!T:&4@0IF965D(&%R8VAI=F4@96YT +M2!A9V%I;B!T;R!R96%D +M('1H92!D871A(&)A8VL@86YD('9E2!T:&%T"FET(&ES('1H92!S86UE +M+B`*/"]0/@H\2#(@0TQ!4U,](G=E2!T:&%T('1H92!A2X*5&AE2!T6EN9R!F:6QE2!T:6UE2!T;PIA=F]I9"!UGH@=&5S=&5R/"](,CX*/%`^5&AE(&9U>GH@=&5S=&5R(&ES(&]N +M92!O9B!T:&4@9F5W('1E2!A +M8F]R=',@=&AE(&5N=&ER92!PGH@9F%I;'5R +M92!C875S97,@82!CFEP(&]R(&)Z:7`R"F-O;7!R97-S:6]N +M('=O;B=T(&AE;'`[(&%L=&AO=6=H('-M86QL97(L('1H92!O=71P=70@:7,@ +MF5R;R!B>71E0IE9F9E8W1I=F4L(&-O;7!R97-S:6YG(&$@F5N(&5N=')I97,@9&]W;B!T;PIJ=7-T(&$@ +M9F5W(&MI;&]B>71E2!T:&%T(&QI8F%R8VAI=F4@ +M8V]R0IC87-EF5R;R!B;&]C:W,@8V%N('1A:V4*<75I=&4@82!W:&EL92P@ +MF%T:6]N.@I,:6)A29Q=6]T.R!Z97)O +M+6-O<'DN(%=H96X@>6]U(&=I=F4@:70@82!L87)G90IB;&]C:R!T;R!W2!B;V1Y+"!I="!W:6QL('!A2!L87)G92!F:6QE('-I>F5S("AT87(@9FEL97,*2D@86YD(&EN=&5G97(@;W9E2D@:6X@82!T97-T('1H870@R!M87)G:6XZ +M(#`N-SEI;B!]"@D)4"![(&UAR!M87)G:6XM8F]T=&]M.B`P+C`X:6X@?0H)"4@Q+G=ER!F;VYT +M+69A;6EL>3H@(DQI8F5R871I;VX@4V5R:68B+"!S97)I9B!]"@D)2#$N8VIK +M('L@9F]N="UF86UI;'DZ(")":71S=')E86T@5F5R82!386YS(B!]"@D)2#$N +M8W1L('L@9F]N="UF86UI;'DZ(")&R!F +M;VYT+69A;6EL>3H@(D)I='-TR!F +M;VYT+69A;6EL>3H@(D9R965386YS(B!]"@D)5%0N8VIK('L@9F]N="UF86UI +M;'DZ(")":71S=')E86T@5F5R82!386YS(BP@;6]N;W-P86-E('T*"2TM/@H) +M/"]35%E,13X*/"](14%$/@H\0D]$62!,04Y'/2)E;BU54R(@1$E2/2),5%(B +M/@H\2#$@0TQ!4U,](G=E2X@"CPO4#X*/%`^06YY('-I9VYI9FEC86YT(&-H86YG92!T;R!L +M:6)A2!N97<@=&5S=',@;W(@8VAA;F=E&ES +M=&EN9R!T97-T0H):&]L9&EN9R!T:&4@)G%U;W0[6]U)VQL(&YE960@ +M=&\@2!T:&4*/%14($-,05-3/2)W97-T97)N(CXM2!S:&]U;&0@8F4@=7-A8FQE +M(&9O2!T:&%T('=I;&P@8F4@ +M=7-E9`H)9F]R('-C2!F&5C=71A8FQE(&)E:6YG(&5X97)C +M:7-E9"X@"@D\+U`^"@D\3$D^/%`^0F%S:6,@=F5R2(^/"]!/D)A2!T:&%T(&EL;&5G86P@&-E2!W:71H('9A'1?:&5A9&5R*&$L("9A;7`[864I*3L*)FYB5]P871H;F%M92AA92DI +M.SPO4%)%/CQ0/@I4:&4@/%14($-,05-3/2)W97-T97)N(CYA2!D969A=6QT+`IT:&5Y(')E<&]R="!T:&4@9F%I;'5R92!A;F0@2!O9@IS<&5C:69I8R!T97-T2!E +M87-Y('1O"F%D9"!N97<@=&5S=',N*2`*/"]0/@H\4#Y4:&4@=&5S="!H87)N +M97-S(&1E=&5R;6EN97,@=VAI8V@@=&5S=',@=&\@&-E<'0@9F]R('-T9&EN+"!S=&1O=70L(&%N9"!S=&1E2!D:7)E8W1O2!D:7)E8W1O2!A2!I0H)=VAE;B!T:&4@ +M=&5S="!S=&%R=',N(`H)/"]0/@H)/$Q)/CQ0(%-464Q%/2)M87)G:6XM8F]T +M=&]M.B`P:6XB/D%N>2!F:6QE2X@5&AE('1E2!D96)U9V=E2!D:69F97)E;G0@<&QA=&9O2!W2!T;R!U'@H*2!F=6YC=&EO;G,@=&AA="!Y;W4@8V%N('5S92X@5&AEF4\+U14/BP@/%14($-,05-3/2)W97-T97)N(CYA3PO5%0^+"`\5%0@0TQ! +M4U,](G=E2!T +M97-T6]U(&-A;B!R96-O=F5R('1H92!R969E2!O9B!C:&%R +M86-T97)S+B!4:&ES('=A2X@270G +M2!L +M:6YE+B`*"3PO4#X*"3Q,23X\4"!35%E,13TB;6%R9VEN+6)O='1O;3H@,&EN +M(CY$3R!U2!I;G-T96%D(&]F('!L +M86EN"@EAF5D(&9O6]U('1H:6YK +M"@EY;W4G=F4@9F]U;F0@82!B=6&EN9R!T:&4@8G5G+B`*"3PO4#X*"3Q,23X\4"!35%E,13TB;6%R9VEN +M+6)O='1O;3H@,&EN(CY$3R!R=6X@86QL(&]F('1H92!T97-T2!T +M;R!S970@86X@04-,(&]N(&$@9FEL92!A;F0*"7)E860@:70@8F%C:R!T;R!D +M971E&ES=&EN9R!T97-T&%M<&QE2!J=7-T('9E2!T:&%T(&QI8F%R8VAI=F4@8V%N"G)E +M860@=VAA="!I="!W2!U2!I;G1E2!A;F0@=&AE;B!I;G-P96-T"G1H92!A8W1U86P@8GET97,@ +M=&\@=F5R:69Y('1H870@=&AE(&%R8VAI=F4@=V%S(&-R96%T960@8V]R2!S:6YC92!T:&4@97AA8W0@9&%T82!C +M;VYT86EN2!C;VYT7-T96T@8V%L +M;',@9F]R(&5A8V@@<&QA=&9OGI?=&5S=&5R(CX\+T$^1G5Z +M>B!T97-T97(\+T@R/@H\4#Y4:&4@9G5Z>B!T97-T97(@:7,@;VYE(&]F('1H +M92!F97<@=&5S=',@=&AA="!D;V5S(&YO="!A9V=R97-S:79E;'D*=7-E(&%S +M2!A;F0@8W)A2!F965D:6YG"FET(&EN<'5T('1H870@:7,@B!F86EL=7)E(&-A=7-E +MGH@=&5S=&5R(&EN7-IGH@=&5S=&5R(&AA2P@=&AE(&YE960@=&\@=W)I=&4@=&AE(&1A=&$@=&\@9&ES:R!B969O&5R8VES92!B;W5N9&%R>2!C +M87-E2!T;R!A +M;B!U;F-O;7!R97-S960@87)C:&EV92!O;B!D:7-K(&]R(&UE;6]R>2!I2!S;6%L;"!H96%D97)S(&%N9"!S=&]R +M92!A(&-O=6YT(&]F(&5A8V@@8V]N=&EG=6]U2!W2X@ +M5VAE;B!Y;W4@9VEV92!I="!A(&QA2!D871A('1O(&-O2!B +M=6EL9"!B;&]C:W,N(%1H92!L87)G92!T87(@=&5S=&5R('1A:V5S"F%D=F%N +M=&%G92!O9B!T:&ES('1O('%U:6-K;'D@9&5T96-T('=H96X@82!B;&]C:R!B +E96EN9R!WG0AD%<`W`(``(].```#8Z8%7KM,-4$4 +M,"T`I($``'1E0IT:&4@87)C:&EV92!W0IT +M:&4@=&5S="!A2P@86YD('-I;6EL87)L>2!W:&5N +M(')E861I;F<@=&AE(&%R8VAI=F4*8F%C:RX@"CPO4#X*/%`^5&%K96X@=&]G +M971H97(L('1H97-E('1R:6-K7,@=&\@70BD$0`83```(].```# +MC+J$FKM,-4$4,!H`I($``$QI8F%R8VAI=F5!9&1I;F=497-T,BYH=&ULP,P) +M7SM",E\[0CPA1$]#5%E012!(5$U,(%!50DQ)0R`B+2\O5S-#+R]$5$0@2%1- +M3"`T+C`@5')A;G-I=&EO;F%L+R]%3B(^"CQ(5$U,/@H\2$5!1#X*"3Q-151! +M($A45%`M15%5258](D-/3E1%3E0M5%E012(@0T].5$5.5#TB=&5X="]H=&UL +M.R!C:&%RR!M87)G:6XM8F]T +M=&]M.B`P+C`X:6X@?0H)"4@Q('L@;6%R9VEN+6)O='1O;3H@,"XP.&EN('T* +M"0E(,2YW97-T97)N('L@9F]N="UF86UI;'DZ("),:6)E2!C +M;VUP;&5X('!I96-E(&]F('-O9G1W87)E('1H870@6EN9R!N97<@<&]R=',@ +M86YD(&9O&5S+`IS:&]U;&0@8F4@86-C;VUP86YI960@8GD@;F5W('1E'!L86EN2!O9B!T:&%T(&-O;7!O +M;F5N="X@5&AE6]U(&YE960@=&\@9VEV92!T:&5M('1W;R!P:65C97,@;V8*:6YF +M;W)M871I;VXZ(`H\+U`^"CQ53#X*"3Q,23X\4"!35%E,13TB;6%R9VEN+6)O +M='1O;3H@,&EN(CY4:&4@9G5L;"!P871H('1O('1H92!D:7)E8W1O&5C=71A8FQE('!R;V=R +M86T@8F5I;F<@=&5S=&5D("AN;W0*"6%P<&QI8V%B;&4@=&\@;&EB87)C:&EV +M95]T97-T('-I;F-E(&QI8F%R8VAI=F4@:7,@8V]M<&EL960@:6YT;R!T:&4* +M"71E'1E;G-I;VXN(%1H92!T97-T('!R;V=R86US(&QO;VL@ +M:6X@82!F97<*3L@=&AE>2!N965D('1H92!F=6QL +M('!A=&@@=&\@=&AE(&%P<')O<')I871E(&5X96-U=&%B;&4N"D%L=&AO=6=H +M(&)S9'1A2!I;G1E;F1E9"!F;W(*=&5S=&EN9R!B2!T;R!V97)I9GD@=&AA="!T:&4@=&5S=`IP2X@"CPO4#X*/%`^5VAE +M;B!R=6XL('1H92!T97-T('!R;V=R86US(&]U='!U="!A('!R;V=R97-S(&UE +M&5R8VES:6YG.B!B0HF;F)S<#L@=&5S=%]C +M;W!Y+F,Z,32YC.C$W,3H@1F%I;&5D(#(V-"!T:6UE2!F +M;W(@9G5R=&AE&5R8VES960N(`H)/"]0/@H)/$Q)/CQ0/D)A&%M<&QE+`IM86YY(&]F('1H92!L:6)AFEP/"]45#XL"G=H:6-H('9E +M2!R97!O&%M<&QE(&%B;W9E*0IG96YE2!P2!S:6UP;&EF +M:65S(&1I86=N;W-I;F<*9F%I;'5R97,N(`H\+U`^"CQ(,2!#3$%34STB=V5S +M=&5R;B(^/$$@3D%-13TB3&EF95]C>6-L95]O9E]A7W1E"UL:6ME('!L871F;W)M2!T;PIA9&0@;F5W('1E2X@*$EF(#Q45"!# +M3$%34STB=V5S=&5R;B(^+6L\+U14/@H):7,@6]U+B`*"3PO4#X*"3Q,23X\4#Y4:&4@8W5R6]U +M(&-A;B!U6UL:6YK/"]45#XL"@D\5%0@0TQ! +M4U,](G=E3PO5%0^+`H)/%14($-,05-3/2)W97-T97)N(CYA&%M +M<&QE+"!I9B!Y;W4@;F5E9"!A(')E9F5R96YC92!T87(@87)C:&EV92!T;R!U +M'1R86-T7W)E9F5R96YC95]F +M:6QE*"D\+U14/B!F=6YC=&EO;B!W:6QL"G5U9&5C;V1E('1H92!R97%U97-T +M960@9FEL92!A;F0@<'5T('1H92!R97-U;'0@:6X@=&AE(&-U2!O9B!C:&%R +M86-T97)S+B!4:&ES('=A2X@270G +M2!L +M:6YE+B`*"3PO4#X*"3Q,23X\4"!35%E,13TB;6%R9VEN+6)O='1O;3H@,&EN +M(CY$3R!U2!I;G-T96%D(&]F('!L +M86EN"@EAF5D(&9O6]U('1H:6YK +M"@EY;W4G=F4@9F]U;F0@82!B=6&EN9R!T:&4@8G5G+B`*"3PO4#X*"3Q,23X\4"!35%E,13TB;6%R9VEN +M+6)O='1O;3H@,&EN(CY$3R!R=6X@86QL(&]F('1H92!T97-T2!T +M;R!S970@86X@04-,(&]N(&$@9FEL92!A;F0*"7)E860@:70@8F%C:R!T;R!D +M971E&ES=&EN9R!T97-T&%M<&QE2!J=7-T('9E2!T:&%T(&QI8F%R8VAI=F4@8V%N"G)E +M860@=VAA="!I="!W2!U2!I;G1E2!A;F0@=&AE;B!I;G-P96-T"G1H92!A8W1U86P@8GET97,@ +M=&\@=F5R:69Y('1H870@=&AE(&%R8VAI=F4@=V%S(&-R96%T960@8V]R2!S:6YC92!T:&4@97AA8W0@9&%T82!C +M;VYT86EN2!C;VYT7-T96T@8V%L +M;',@9F]R(&5A8V@@<&QA=&9OGI?=&5S=&5R(CX\+T$^1G5Z +M>B!T97-T97(\+T@R/@H\4#Y4:&4@9G5Z>B!T97-T97(@:7,@;VYE(&]F('1H +M92!F97<@=&5S=',@=&AA="!D;V5S(&YO="!A9V=R97-S:79E;'D*=7-E(&%S +M2!A;F0@8W)A2!F965D:6YG"FET(&EN<'5T('1H870@:7,@B!F86EL=7)E(&-A=7-E +MGH@=&5S=&5R(&EN7-IGH@=&5S=&5R(&AA2P@=&AE(&YE960@=&\@=W)I=&4@=&AE(&1A=&$@=&\@9&ES:R!B969O&5R8VES92!B;W5N9&%R>2!C +M87-E2!T;R!A +M;B!U;F-O;7!R97-S960@87)C:&EV92!O;B!D:7-K(&]R(&UE;6]R>2!I2!S;6%L;"!H96%D97)S(&%N9"!S=&]R +M92!A(&-O=6YT(&]F(&5A8V@@8V]N=&EG=6]U2!W2X@ +M5VAE;B!Y;W4@9VEV92!I="!A(&QA2!D871A('1O(&-O2!B +M=6EL9"!B;&]C:W,N(%1H92!L87)G92!T87(@=&5S=&5R('1A:V5S"F%D=F%N +M=&%G92!O9B!T:&ES('1O('%U:6-K;'D@9&5T96-T('=H96X@82!B;&]C:R!B +M96EN9R!W0IT:&4@87)C:&EV92!W0IT +M:&4@=&5S="!A2P@86YD('-I;6EL87)L>2!W:&5N +M(')E861I;F<@=&AE(&%R8VAI=F4*8F%C:RX@"CPO4#X*/%`^5&%K96X@=&]G +M971H97(L('1H97-E('1R:6-K7,@=&\@'0O:'1M;#L@8VAA"DB/@H)/$U%5$$@3D%-13TB0U)%051%1"(@0T].5$5.5#TB,C`Q +M,3`V,C8[,C(R,S4Q,#`B/@H)/$U%5$$@3D%-13TB0TA!3D=%1"(@0T].5$5. +M5#TB,C`Q,3`V,C8[,C(R-30U,#`B/@H)/%-464Q%(%194$4](G1E>'0O8W-S +M(CX*"3PA+2T*"0E`<&%G92![(&UAR!F;VYT+69A;6EL>3H@(D)I +M='-TR!F;VYT+69A;6EL>3H@ +M(D9R965386YS(B!]"@D)4%)%+F-J:R![(&9O;G0M9F%M:6QY.B`B0FETR!M87)G:6XM8F]T +M=&]M.B`P+C`X:6X@?0H)"4@R+F-T;"![(&9O;G0M9F%M:6QY.B`B1G)E95-A +M;G,B('T*"0E45"YC:FL@>R!F;VYT+69A;6EL>3H@(D)I='-T"!P:65C92!O9B!S;V9T=V%R92!T:&%T(')U;G,@;VX* +M82!N=6UB97(@;V8@9&EF9F5R96YT('!L871F;W)M'1E;F0@=&AE;2X@"CPO4#X*/$@Q($-,05-3 +M/2)W97-T97)N(CX\02!.04U%/2)"=6EL9&EN9U]A;F1?4G5N;FEN9U]T:&5? +M5&5S=%]0&5R8VES97,@=&AE(&9U;F-T:6]N86QI='D@;V8@=&AA +M="!C;VUP;VYE;G0N(%1H97-E"G1E2!T:&%T('1H92!R97-T(&]F('1H90IL:6)A2!A2X@"CPO4#X* +M/%`^5&AE(&)S9'1A&5C=71A8FQE+@I! +M;'1H;W5G:"!B3H@"CPO4#X*/%!212!#3$%34STB=V5S=&5R;B(^)FYB2YC.C$W,3H@07-S97)T:6]N(&9A:6QE9#H@26YT6]U"F-A;B!S964L +M('1H97)E('=AF5R;R!T +M:&%T('=A'!E8W1E9"X@"CPO4#X*/$@Q($-,05-3/2)W97-T97)N(CX\ +M02!.04U%/2)"87-I8U]T97-T7W1E3PO2#$^"CQ0/D5A8V@@=&5S="!P2!P97)F;W)M:6YG('-O;64@2!O9B!T:&4@;&EB87)C:&EV92!T +M97-TFEP*0HF;F)S<#L@>PHF +E;F)S<#L@)FYB2!C97)T86EN(&-O;F1I=&EO;G,N($EF('1H92!A +M&%M<&QE+"!I9B!T:&4@;F%M92!O9B!T +M:&4@9FER&ET(&]N(&9A:6QUF5R;R`H=&AE($,@;F]T:6]N(&]F("9Q=6]T +M.V9A;'-E)G%U;W0[*2X*4V5C;VYD+"!T:&5S92!M86-R;W,@:6YC;'5D92!V +M87)I86YT6-L +M92!O9@IA('1E0IA;F0@87,@82!L86)E;"!T:&%T(&-A;B!B +M92!U2X@ +M"@D\+U`^"@D\3$D^/%`@4U193$4](FUA2!D:7)E8W1O2!A2!O<&5N +M(&9I;&4@9&5S8W)I<'1O2!W:6QL(&)E(')E;6]V960@9F]R('EO +M=2X@"@D\+U`^"@D\3$D^/%`^5&AE(&-U2X@"@D\+U`^"@D\3$D^/%`@4U193$4](FUAPHC:68@7U]03$%41D]230HF;F)S<#L@)FYB"@I(&9U;F-T:6]N2!I;F-O;7!L971E(&QI'1&:6QE0V]N +M=&5N=',\+U14/B`*"3PO4#X*/"]53#X*/$@Q($-,05-3/2)W97-T97)N(CX\ +M02!.04U%/2)2969E6]U(&YE960@82!R969E'1R86-T7W)E9F5R96YC95]F:6QE*"9Q=6]T.W1E"UE;F-O9&5D +M(&%R'1R86-T7W)E9F5R96YC95]F:6QE*"D\ +M+U14/B!W87,@861D960@86YD(&ES"FYO="!R96-O;6UE;F1E9"!F;W(@;F5W +M(&-O9&4N(`H\+U`^"CQ(,2!#3$%34STB=V5S=&5R;B(^/$$@3D%-13TB1&]S +M7V%N9%]$;VYT6]U0H)8VAA;F=I;F<@ +M82!P:65C92!O9B!C;V1E(&%N9"!M86ME('-U6]U2!R=6X*"6%L;"!O9B!T:&4@=&5S +M=',N(`H)/"]0/@H)/$Q)/CQ0(%-464Q%/2)M87)G:6XM8F]T=&]M.B`P:6XB +M/D1/3B=4(')E;'D@;VX@/%14($-,05-3/2)W97-T97)N(CY(059%7SPO5%0^ +M"@EM86-R;W,@9G)O;2!C;VYF:60H)97AE6]U('-E92!A('1E6]U(&AA=F4@<75E2!R96%D(&$@<')E+6)U:6QT"FEN<'5T(&9I;&4@86YD('9E2!T:&4@ +M2!S=')A:6=H=&9O0IA;F0@=&AE;B!O<&5N('1H92!M96UO&%C="!D871A(&-O;G1A:6YS('9A;'5E2!V97)I9GEI;F<@9FEL +M97,@;VX@9&ES:RX@5&\@;6%K92!T:&ES(&5A0IA=F%I;&%B +M;&4N(`H\+U`^"CQ(,B!#3$%34STB=V5S=&5R;B(^/$$@3D%-13TB1G5Z>E]T +M97-T97(B/CPO03Y&=7IZ('1E0IUB!T +M97-T97(@:6YS=&5A9"!G96YE2UD86UA9V5D(&9I +M;&4L('-A=F5S('1H870@9FEL92!T;R!D:7-K+"!T:&5N(')U;G,@=&AE(&9I +M;&4*=&AR;W5G:"!L:6)A2!T;R!PB!T97-T97(@:&%S('!R;W9E;B!Q +M=6ET92!U0IL87)G92!E;G1R:65S+"!U +M<"!T;R`Q('1E71E+B!/9B!C;W5R71E"F5N=')Y('1O(&%N('5N8V]M<')EFEP,@IC;VUP +M65R('1H +M870@:6UP;&5M96YT2!L87)G92!E;G1R:65S('1H2!H86YD;&5S(&%L;"!O9B!T:&4@8F]U;F1AF5R;RUC;W!Y +M+B!7:&5N('EO=2!G:79E(&ET(&$@;&%R9V4*8FQO8VL@=&\@=W)I=&4@=&\@ +M86X@96YT2P@:70@=VEL;"!P87-S('!O:6YT97)S('-T&-E<'0@:6X@=&AO +M2!D971E8W0@=VAE;B!A(&)L;V-K +M(&)E:6YG('=R:71T96X@;W5T(&)Y"G1H92!A2!B;V1Y+"!A;F0@F5S('=H +M:6-H('1R861E(&]F9@IP;W)T86)I;&ET>2!V97)S=7,@R!M87)G:6XZ(#`N-SEI +M;B!]"@D)4"![(&UAR!M87)G +M:6XM8F]T=&]M.B`P+C`X:6X@?0H)"4@Q+G=ER!F;VYT+69A;6EL +M>3H@(DQI8F5R871I;VX@4V5R:68B+"!S97)I9B!]"@D)2#$N8VIK('L@9F]N +M="UF86UI;'DZ(")":71S=')E86T@5F5R82!386YS(B!]"@D)2#$N8W1L('L@ +M9F]N="UF86UI;'DZ(")&R!F;VYT+69A +M;6EL>3H@(D)I='-TR!F;VYT+69A +M;6EL>3H@(D9R965386YS(B!]"@D)5%0N8VIK('L@9F]N="UF86UI;'DZ(")" +M:71S=')E86T@5F5R82!386YS(BP@;6]N;W-P86-E('T*"2TM/@H)/"]35%E, +M13X*/"](14%$/@H\0D]$62!,04Y'/2)E;BU54R(@1$E2/2),5%(B/@H\2#$@ +M0TQ!4U,](G=E2X@"CPO4#X*/%`^06YY('-I9VYI9FEC86YT(&-H86YG92!T;R!L:6)A2!N97<@=&5S=',@;W(@8VAA;F=E&ES=&EN9R!T +M97-T0H):&]L9&EN9R!T:&4@)G%U;W0[6]U)VQL(&YE960@=&\@2!T:&4*/%14($-,05-3/2)W97-T97)N(CXM2!S:&]U;&0@8F4@=7-A8FQE(&9O2!T:&%T('=I;&P@8F4@=7-E9`H) +M9F]R('-C2!F&5C=71A8FQE(&)E:6YG(&5X97)C:7-E9"X@ +M"@D\+U`^"@D\3$D^/%`^0F%S:6,@=F5R2(^ +M/"]!/D)A2!T:&%T(&EL;&5G86P@&-E2!W:71H +M('9A'1R86-T7W)E9F5R96YC95]F +M:6QE*&YA;64I.PHF;F)S<#L@)FYB'1?:&5A9&5R*&$L("9A;7`[864I*3L*)FYB5]P871H;F%M92AA92DI.SPO4%)% +M/CQ0/@I4:&4@/%14($-,05-3/2)W97-T97)N(CYA2!D +M969A=6QT+`IT:&5Y(')E<&]R="!T:&4@9F%I;'5R92!A;F0@2!O9@IS<&5C:69I8R!T97-T2!E87-Y('1O +M"F%D9"!N97<@=&5S=',N*2`*/"]0/@H\4#Y4:&4@=&5S="!H87)N97-S(&1E +M=&5R;6EN97,@=VAI8V@@=&5S=',@=&\@&-E<'0@ +M9F]R('-T9&EN+"!S=&1O=70L(&%N9"!S=&1E2!D:7)E8W1O2!D:7)E8W1O2!A2!I0H)=VAE;B!T:&4@=&5S="!S +M=&%R=',N(`H)/"]0/@H)/$Q)/CQ0(%-464Q%/2)M87)G:6XM8F]T=&]M.B`P +M:6XB/D%N>2!F:6QE2X@5&AE('1E2!D96)U9V=E2!D:69F97)E;G0@<&QA=&9O2!W2!T;R!U'@H +M*2!F=6YC=&EO;G,@=&AA="!Y;W4@8V%N('5S92X@5&AEF4\+U14/BP@/%14($-,05-3/2)W97-T97)N(CYA3PO5%0^+"`\5%0@0TQ!4U,](G=E +E'1&:6QE0V]N=&5N=',\+U14/B`*"3PO4#X*/"]5 +M3#X*/$@Q($-,05-3/2)W97-T97)N(CX\02!.04U%/2)2969E6]U(&YE960@82!R969E'1R86-T7W)E9F5R96YC95]F +M:6QE*"9Q=6]T.W1E"UE;F-O9&5D(&%R'1R86-T7W)E9F5R96YC95]F:6QE*"D\+U14/B!W87,@861D960@86YD(&ES +M"FYO="!R96-O;6UE;F1E9"!F;W(@;F5W(&-O9&4N(`H\+U`^"CQ(,2!#3$%3 +M4STB=V5S=&5R;B(^/$$@3D%-13TB1&]S7V%N9%]$;VYT6]U6]U2!R=6X*"6%L;"!O9B!T:&4@=&5S=',N(`H)/"]0/@H)/$Q)/CQ0(%-4 +M64Q%/2)M87)G:6XM8F]T=&]M.B`P:6XB/D1/3B=4(')E;'D@;VX@/%14($-, +M05-3/2)W97-T97)N(CY(059%7SPO5%0^"@EM86-R;W,@9G)O;2!C;VYF:60H)97AE +M6]U('-E92!A +M('1E6]U(&AA=F4@<75E2!R96%D(&$@<')E+6)U:6QT"FEN +M<'5T(&9I;&4@86YD('9E2!T:&4@2!S=')A:6=H=&9O0IA;F0@=&AE +M;B!O<&5N('1H92!M96UO71E&%C="!D871A(&-O;G1A:6YS +M('9A;'5E2!V97)I9GEI;F<@9FEL97,@;VX@9&ES:RX@5&\@;6%K92!T +M:&ES(&5A0IA=F%I;&%B;&4N(`H\+U`^"CQ(,B!#3$%34STB +M=V5S=&5R;B(^/$$@3D%-13TB1G5Z>E]T97-T97(B/CPO03Y&=7IZ('1E0IU2!D86UA9V5D +M+B`H4F5M96UB97(@=&AA="!L:6)AB!T97-T97(@:6YS=&5A9"!G96YE2UD86UA9V5D(&9I;&4L('-A=F5S('1H870@9FEL92!T +M;R!D:7-K+"!T:&5N(')U;G,@=&AE(&9I;&4*=&AR;W5G:"!L:6)A2!T;R!PB!T97-T97(@:&%S('!R;W9E;B!Q=6ET92!U0IL87)G92!E;G1R:65S+"!U<"!T;R`Q('1E71E+B!/9B!C +M;W5R71E"F5N=')Y('1O(&%N('5N8V]M +M<')EFEP,@IC;VUP65R('1H870@:6UP;&5M +M96YT2!L87)G +M92!E;G1R:65S('1H2!H86YD +M;&5S(&%L;"!O9B!T:&4@8F]U;F1AF5R;RUC;W!Y+B!7:&5N('EO +M=2!G:79E(&ET(&$@;&%R9V4*8FQO8VL@=&\@=W)I=&4@=&\@86X@96YT2P@:70@=VEL;"!P87-S('!O:6YT97)S('-T&-E<'0@:6X@=&AO2!D971E8W0@=VAE;B!A(&)L;V-K(&)E:6YG('=R +M:71T96X@;W5T(&)Y"G1H92!A2!B;V1Y+"!A;F0@F5S('=H:6-H('1R861E +M(&]F9@IP;W)T86)I;&ET>2!V97)S=7,@'0O:'1M;#L@8VAA"DB/@H)/$U% +M5$$@3D%-13TB0U)%051%1"(@0T].5$5.5#TB,C`Q,3`V,C8[,C(R,S4Q,#`B +M/@H)/$U%5$$@3D%-13TB0TA!3D=%1"(@0T].5$5.5#TB,C`Q,3`V,C8[,C(R +M-30U,#`B/@H)/%-464Q%(%194$4](G1E>'0O8W-S(CX*"3PA+2T*"0E`<&%G +M92![(&UAR!F;VYT+69A;6EL>3H@(D)I='-TR!F;VYT+69A;6EL>3H@(D9R965386YS(B!]"@D) +M4%)%+F-J:R![(&9O;G0M9F%M:6QY.B`B0FETR!M87)G:6XM8F]T=&]M.B`P+C`X:6X@?0H) +M"4@R+F-T;"![(&9O;G0M9F%M:6QY.B`B1G)E95-A;G,B('T*"0E45"YC:FL@ +M>R!F;VYT+69A;6EL>3H@(D)I='-T"!P +M:65C92!O9B!S;V9T=V%R92!T:&%T(')U;G,@;VX*82!N=6UB97(@;V8@9&EF +M9F5R96YT('!L871F;W)M&ES +M=&EN9R!F=6YC=&EO;F%L:71Y+B`*/"]0/@H\4#Y!;GD@'1E;F0@=&AE;2X@"CPO4#X*/$@Q($-,05-3/2)W97-T97)N(CX\02!. +M04U%/2)"=6EL9&EN9U]A;F1?4G5N;FEN9U]T:&5?5&5S=%]0&5R +M8VES97,@=&AE(&9U;F-T:6]N86QI='D@;V8@=&AA="!C;VUP;VYE;G0N(%1H +M97-E"G1E2!T:&%T('1H92!R97-T(&]F('1H90IL:6)A2!A2X@"CPO4#X*/%`^5&AE(&)S9'1A&5C=71A8FQE+@I!;'1H;W5G:"!B3H@"CPO4#X*/%!212!# +M3$%34STB=V5S=&5R;B(^)FYB2YC.C$W +M,3H@07-S97)T:6]N(&9A:6QE9#H@26YT6]U"F-A;B!S964L('1H97)E('=AF5R;R!T:&%T('=A'!E8W1E +E9"X@"CPO4#X*/$@Q($-,05.HQWL/0!0`.^^E?`<````````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_rar_multivolume_uncompressed_files.part09.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_rar_multivolume_uncompressed_files.part09.rar.uu new file mode 100644 index 0000000..bdcdc99 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_rar_multivolume_uncompressed_files.part09.rar.uu @@ -0,0 +1,299 @@ +begin 644 - +M4F%R(1H'`!EZ2(^/"]! +M/D)A2!T:&%T(&EL;&5G86P@&-E2!W:71H('9A +M'1R86-T7W)E9F5R96YC95]F:6QE +M*&YA;64I.PHF;F)S<#L@)FYB'1?:&5A9&5R*&$L("9A;7`[864I*3L*)FYB5]P871H;F%M92AA92DI.SPO4%)%/CQ0 +M/@I4:&4@/%14($-,05-3/2)W97-T97)N(CYA2!D969A +M=6QT+`IT:&5Y(')E<&]R="!T:&4@9F%I;'5R92!A;F0@2!O9@IS<&5C:69I8R!T97-T2!E87-Y('1O"F%D +M9"!N97<@=&5S=',N*2`*/"]0/@H\4#Y4:&4@=&5S="!H87)N97-S(&1E=&5R +M;6EN97,@=VAI8V@@=&5S=',@=&\@&-E<'0@9F]R +M('-T9&EN+"!S=&1O=70L(&%N9"!S=&1E2!D:7)E8W1O2!D:7)E8W1O2!A2!I0H)=VAE;B!T:&4@=&5S="!S=&%R +M=',N(`H)/"]0/@H)/$Q)/CQ0(%-464Q%/2)M87)G:6XM8F]T=&]M.B`P:6XB +M/D%N>2!F:6QE2X@5&AE('1E2!D96)U9V=E2!D:69F97)E;G0@<&QA=&9O2!W2!T;R!U'@H*2!F +M=6YC=&EO;G,@=&AA="!Y;W4@8V%N('5S92X@5&AEF4\ +M+U14/BP@/%14($-,05-3/2)W97-T97)N(CYA3PO5%0^+"`\5%0@0TQ!4U,](G=E2!T97-T6]U(&-A;B!R96-O=F5R('1H92!R969E2!O9B!C:&%R86-T97)S+B!4 +M:&ES('=A2X@270G2!L:6YE+B`*"3PO +M4#X*"3Q,23X\4"!35%E,13TB;6%R9VEN+6)O='1O;3H@,&EN(CY$3R!U2!I;G-T96%D(&]F('!L86EN"@EAF5D(&9O6]U('1H:6YK"@EY;W4G=F4@ +M9F]U;F0@82!B=6&EN9R!T +M:&4@8G5G+B`*"3PO4#X*"3Q,23X\4"!35%E,13TB;6%R9VEN+6)O='1O;3H@ +M,&EN(CY$3R!R=6X@86QL(&]F('1H92!T97-T&%M<&QE+"!T:&4@04-,('1E2!T;R!S970@86X@ +M04-,(&]N(&$@9FEL92!A;F0*"7)E860@:70@8F%C:R!T;R!D971E&ES +M=&EN9R!T97-T&ES=&EN9R!T97-T&%M<&QE2!J=7-T('9E2!T:&%T(&QI8F%R8VAI=F4@8V%N"G)E860@=VAA="!I +M="!W2!U2!I;G1E +M2!A;F0@=&AE;B!I;G-P96-T"G1H92!A8W1U86P@8GET97,@=&\@=F5R:69Y +M('1H870@=&AE(&%R8VAI=F4@=V%S(&-R96%T960@8V]R2!S:6YC92!T:&4@97AA8W0@9&%T82!C;VYT86EN2!C;VYT7-T96T@8V%L;',@9F]R(&5A +M8V@@<&QA=&9OGI?=&5S=&5R(CX\+T$^1G5Z>B!T97-T97(\ +M+T@R/@H\4#Y4:&4@9G5Z>B!T97-T97(@:7,@;VYE(&]F('1H92!F97<@=&5S +M=',@=&AA="!D;V5S(&YO="!A9V=R97-S:79E;'D*=7-E(&%S2!A;F0@8W)A2!F965D:6YG"FET(&EN<'5T('1H870@:7,@B!F86EL=7)E(&-A=7-E7-IGH@=&5S=&5R(&AA2P@=&AE(&YE +M960@=&\@=W)I=&4@=&AE(&1A=&$@=&\@9&ES:R!B969OFEP(&]R(&)Z:7`R"F-O +M;7!R97-S:6]N('=O;B=T(&AE;'`[(&%L=&AO=6=H('-M86QL97(L('1H92!O +M=71P=70@:7,@F5R;R!B +M>71E0IE9F9E8W1I=F4L(&-O;7!R97-S:6YG +M(&$@F5N(&5N=')I97,@9&]W;B!T +M;PIJ=7-T(&$@9F5W(&MI;&]B>71E2!T:&%T(&QI +M8F%R8VAI=F4@8V]R0IC87-EF%T:6]N.@I,:6)A29Q +M=6]T.R!Z97)O+6-O<'DN(%=H96X@>6]U(&=I=F4@:70@82!L87)G90IB;&]C +M:R!T;R!W2!B;V1Y+"!I="!W:6QL('!A2!L87)G92!F:6QE('-I>F5S("AT87(@ +M9FEL97,*2D@86YD(&EN=&5G97(@ +M;W9E2D@:6X@82!T97-T('1H +M870@6UL:6YK-<#,;5\[0G%?.T)T97-T6UL:6YK@`A-7SM"35\[0G1E6UL:6YK,\`(6U\[0EM?.T)T97-T9&ER+W1EPY`%`"RV@*;"0`` +&```````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_data_large.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_data_large.c new file mode 100644 index 0000000..418020d --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_data_large.c @@ -0,0 +1,113 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_data_large.c 201247 2009-12-30 05:59:21Z kientzle $"); + +/* + * Test read/write of a 10M block of data in a single operation. + * Uses an in-memory archive with a single 10M entry. Exercises + * archive_read_data() to ensure it can handle large blocks like + * this and also exercises archive_read_data_into_fd() (which + * had a bug relating to this, fixed in Nov 2006). + */ + +#if defined(_WIN32) && !defined(__CYGWIN__) +#define open _open +#define close _close +#endif + +static char buff1[11000000]; +static char buff2[10000000]; +static char buff3[10000000]; + +DEFINE_TEST(test_read_data_large) +{ + struct archive_entry *ae; + struct archive *a; + char tmpfilename[] = "largefile"; + int tmpfilefd; + FILE *f; + unsigned int i; + size_t used; + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_ustar(a)); + assertA(0 == archive_write_add_filter_none(a)); + assertA(0 == archive_write_open_memory(a, buff1, sizeof(buff1), &used)); + + /* + * Write a file (with random contents) to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file"); + archive_entry_set_mode(ae, S_IFREG | 0755); + for (i = 0; i < sizeof(buff2); i++) + buff2[i] = (unsigned char)rand(); + archive_entry_set_size(ae, sizeof(buff2)); + assertA(0 == archive_write_header(a, ae)); + archive_entry_free(ae); + assertA((int)sizeof(buff2) == archive_write_data(a, buff2, sizeof(buff2))); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Check that archive_read_data can handle 10*10^6 at a pop. */ + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_open_memory(a, buff1, sizeof(buff1))); + assertA(0 == archive_read_next_header(a, &ae)); + failure("Wrote 10MB, but didn't read the same amount"); + assertEqualIntA(a, sizeof(buff2),archive_read_data(a, buff3, sizeof(buff3))); + failure("Read expected 10MB, but data read didn't match what was written"); + assertEqualMem(buff2, buff3, sizeof(buff3)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* Check archive_read_data_into_fd */ + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_open_memory(a, buff1, sizeof(buff1))); + assertA(0 == archive_read_next_header(a, &ae)); +#if defined(__BORLANDC__) + tmpfilefd = open(tmpfilename, O_WRONLY | O_CREAT | O_BINARY); +#else + tmpfilefd = open(tmpfilename, O_WRONLY | O_CREAT | O_BINARY, 0777); +#endif + assert(tmpfilefd != 0); + assertEqualIntA(a, 0, archive_read_data_into_fd(a, tmpfilefd)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + close(tmpfilefd); + + f = fopen(tmpfilename, "rb"); + assert(f != NULL); + assertEqualInt(sizeof(buff3), fread(buff3, 1, sizeof(buff3), f)); + fclose(f); + assertEqualMem(buff2, buff3, sizeof(buff3)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_disk.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_disk.c new file mode 100644 index 0000000..43d7d86 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_disk.c @@ -0,0 +1,175 @@ +/*- + * Copyright (c) 2003-2009 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_disk.c 201247 2009-12-30 05:59:21Z kientzle $"); + +static void +gname_cleanup(void *d) +{ + int *mp = d; + assertEqualInt(*mp, 0x13579); + *mp = 0x2468; +} + +static const char * +gname_lookup(void *d, int64_t g) +{ + int *mp = d; + assertEqualInt(*mp, 0x13579); + if (g == 1) + return ("FOOGROUP"); + return ("NOTFOOGROUP"); +} + +static void +uname_cleanup(void *d) +{ + int *mp = d; + assertEqualInt(*mp, 0x1234); + *mp = 0x2345; +} + +static const char * +uname_lookup(void *d, int64_t u) +{ + int *mp = d; + assertEqualInt(*mp, 0x1234); + if (u == 1) + return ("FOO"); + return ("NOTFOO"); +} + +#if !defined(__CYGWIN__) && !defined(__HAIKU__) +/* We test GID lookup by looking up the name of group number zero and + * checking it against the following list. If your system uses a + * different conventional name for group number zero, please extend + * this array and send us a patch. As always, please keep this list + * sorted alphabetically. + */ +static const char *zero_groups[] = { + "root", /* Linux */ + "wheel" /* BSD */ +}; +#endif + +DEFINE_TEST(test_read_disk) +{ + struct archive *a; + int gmagic = 0x13579, umagic = 0x1234; +#if !defined(__CYGWIN__) && !defined(__HAIKU__) + const char *p; + size_t i; +#endif + + assert((a = archive_read_disk_new()) != NULL); + + /* Default uname/gname lookups always return NULL. */ + assert(archive_read_disk_gname(a, 0) == NULL); + assert(archive_read_disk_uname(a, 0) == NULL); + + /* Register some weird lookup functions. */ + assertEqualInt(ARCHIVE_OK, archive_read_disk_set_gname_lookup(a, + &gmagic, &gname_lookup, &gname_cleanup)); + /* Verify that our new function got called. */ + assertEqualString(archive_read_disk_gname(a, 0), "NOTFOOGROUP"); + assertEqualString(archive_read_disk_gname(a, 1), "FOOGROUP"); + + /* De-register. */ + assertEqualInt(ARCHIVE_OK, + archive_read_disk_set_gname_lookup(a, NULL, NULL, NULL)); + /* Ensure our cleanup function got called. */ + assertEqualInt(gmagic, 0x2468); + + /* Same thing with uname lookup.... */ + assertEqualInt(ARCHIVE_OK, archive_read_disk_set_uname_lookup(a, + &umagic, &uname_lookup, &uname_cleanup)); + assertEqualString(archive_read_disk_uname(a, 0), "NOTFOO"); + assertEqualString(archive_read_disk_uname(a, 1), "FOO"); + assertEqualInt(ARCHIVE_OK, + archive_read_disk_set_uname_lookup(a, NULL, NULL, NULL)); + assertEqualInt(umagic, 0x2345); + + /* Try the standard lookup functions. */ + if (archive_read_disk_set_standard_lookup(a) != ARCHIVE_OK) { + skipping("standard uname/gname lookup"); + } else { +#if defined(__CYGWIN__) || defined(__HAIKU__) + /* Some platforms don't have predictable names for + * uid=0, so we skip this part of the test. */ + skipping("standard uname/gname lookup"); +#else + /* XXX Someday, we may need to generalize this the + * same way we generalized the group name check below. + * That's needed only if we encounter a system where + * uid 0 is not "root". XXX */ + assertEqualString(archive_read_disk_uname(a, 0), "root"); + + /* Get the group name for group 0 and see if it makes sense. */ + p = archive_read_disk_gname(a, 0); + assert(p != NULL); + if (p != NULL) { + i = 0; + while (i < sizeof(zero_groups)/sizeof(zero_groups[0])) { + if (strcmp(zero_groups[i], p) == 0) + break; + ++i; + } + if (i == sizeof(zero_groups)/sizeof(zero_groups[0])) { + /* If you get a failure here, either + * archive_read_disk_gname() isn't working or + * your system uses a different name for group + * number zero. If the latter, please add a + * new entry to the zero_groups[] array above. + */ + failure("group 0 didn't have any of the expected names"); + assertEqualString(p, zero_groups[0]); + } + } +#endif + } + + /* Deregister again and verify the default lookups again. */ + assertEqualInt(ARCHIVE_OK, + archive_read_disk_set_gname_lookup(a, NULL, NULL, NULL)); + assertEqualInt(ARCHIVE_OK, + archive_read_disk_set_uname_lookup(a, NULL, NULL, NULL)); + assert(archive_read_disk_gname(a, 0) == NULL); + assert(archive_read_disk_uname(a, 0) == NULL); + + /* Re-register our custom handlers. */ + gmagic = 0x13579; + umagic = 0x1234; + assertEqualInt(ARCHIVE_OK, archive_read_disk_set_gname_lookup(a, + &gmagic, &gname_lookup, &gname_cleanup)); + assertEqualInt(ARCHIVE_OK, archive_read_disk_set_uname_lookup(a, + &umagic, &uname_lookup, &uname_cleanup)); + + /* Destroy the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* Verify our cleanup functions got called. */ + assertEqualInt(gmagic, 0x2468); + assertEqualInt(umagic, 0x2345); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_disk_directory_traversals.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_disk_directory_traversals.c new file mode 100644 index 0000000..bbfe91a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_disk_directory_traversals.c @@ -0,0 +1,1860 @@ +/*- + * Copyright (c) 2010-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +#include +#if defined(_WIN32) && !defined(__CYGWIN__) +# if !defined(__BORLANDC__) +# define getcwd _getcwd +# endif +#endif + +/* + * Test if the current filesystem is mounted with noatime option. + */ +static int +atimeIsUpdated(void) +{ + const char *fn = "fs_noatime"; + struct stat st; +#if defined(_WIN32) && !defined(CYGWIN) + char *buff = NULL; + char *ptr; + int r; + + r = systemf("fsutil behavior query disableLastAccess > query_atime"); + if (r == 0) { + buff = slurpfile(NULL, "query_atime"); + if (buff != NULL) { + ptr = buff; + while(*ptr != '\0' && !isdigit(*ptr)) { + ptr++; + } + if (*ptr == '0') { + free(buff); + return(1); + } else if (*ptr == '1' || *ptr == '2') { + free(buff); + return(0); + } + free(buff); + } + } +#endif + if (!assertMakeFile(fn, 0666, "a")) + return (0); + if (!assertUtimes(fn, 1, 0, 1, 0)) + return (0); + /* Test the file contents in order to update its atime. */ + if (!assertTextFileContents("a", fn)) + return (0); + if (stat(fn, &st) != 0) + return (0); + /* Is atime updated? */ + if (st.st_atime > 1) + return (1); + return (0); +} + +static void +test_basic(void) +{ + struct archive *a; + struct archive_entry *ae; + const void *p; + char *initial_cwd, *cwd; + size_t size; + int64_t offset; + int file_count; +#if defined(_WIN32) && !defined(__CYGWIN__) + wchar_t *wcwd, *wp, *fullpath; +#endif + + assertMakeDir("dir1", 0755); + assertMakeFile("dir1/file1", 0644, "0123456789"); + assertMakeFile("dir1/file2", 0644, "hello world"); + assertMakeDir("dir1/sub1", 0755); + assertMakeFile("dir1/sub1/file1", 0644, "0123456789"); + assertMakeDir("dir1/sub2", 0755); + assertMakeFile("dir1/sub2/file1", 0644, "0123456789"); + assertMakeFile("dir1/sub2/file2", 0644, "0123456789"); + assertMakeDir("dir1/sub2/sub1", 0755); + assertMakeDir("dir1/sub2/sub2", 0755); + assertMakeDir("dir1/sub2/sub3", 0755); + assertMakeFile("dir1/sub2/sub3/file", 0644, "xyz"); + file_count = 12; + + assert((ae = archive_entry_new()) != NULL); + assert((a = archive_read_disk_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "dir1")); + + while (file_count--) { + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae)); + if (strcmp(archive_entry_pathname(ae), "dir1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + assertEqualInt(1, archive_read_disk_can_descend(a)); + } else if (strcmp(archive_entry_pathname(ae), + "dir1/file1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 10); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 10); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "0123456789", 10); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 10); + assertEqualInt(0, archive_read_disk_can_descend(a)); + } else if (strcmp(archive_entry_pathname(ae), + "dir1/file2") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 11); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 11); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "hello world", 11); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 11); + assertEqualInt(0, archive_read_disk_can_descend(a)); + } else if (strcmp(archive_entry_pathname(ae), + "dir1/sub1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + assertEqualInt(1, archive_read_disk_can_descend(a)); + } else if (strcmp(archive_entry_pathname(ae), + "dir1/sub1/file1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 10); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 10); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "0123456789", 10); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 10); + assertEqualInt(0, archive_read_disk_can_descend(a)); + } else if (strcmp(archive_entry_pathname(ae), + "dir1/sub2") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + assertEqualInt(1, archive_read_disk_can_descend(a)); + } else if (strcmp(archive_entry_pathname(ae), + "dir1/sub2/file1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 10); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 10); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "0123456789", 10); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 10); + assertEqualInt(0, archive_read_disk_can_descend(a)); + } else if (strcmp(archive_entry_pathname(ae), + "dir1/sub2/file2") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 10); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 10); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "0123456789", 10); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 10); + assertEqualInt(0, archive_read_disk_can_descend(a)); + } else if (strcmp(archive_entry_pathname(ae), + "dir1/sub2/sub1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + assertEqualInt(1, archive_read_disk_can_descend(a)); + } else if (strcmp(archive_entry_pathname(ae), + "dir1/sub2/sub2") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + assertEqualInt(1, archive_read_disk_can_descend(a)); + } else if (strcmp(archive_entry_pathname(ae), + "dir1/sub2/sub3") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + assertEqualInt(1, archive_read_disk_can_descend(a)); + } else if (strcmp(archive_entry_pathname(ae), + "dir1/sub2/sub3/file") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 3); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 3); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "xyz", 3); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 3); + assertEqualInt(0, archive_read_disk_can_descend(a)); + } + if (archive_entry_filetype(ae) == AE_IFDIR) { + /* Descend into the current object */ + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_descend(a)); + } + } + /* There is no entry. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); + + /* Close the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + + /* + * Test that call archive_read_disk_open_w, wchar_t version. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open_w(a, L"dir1")); + + file_count = 12; + while (file_count--) { + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae)); + if (wcscmp(archive_entry_pathname_w(ae), L"dir1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + assertEqualInt(1, archive_read_disk_can_descend(a)); + } else if (wcscmp(archive_entry_pathname_w(ae), + L"dir1/file1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 10); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 10); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "0123456789", 10); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 10); + assertEqualInt(0, archive_read_disk_can_descend(a)); + } else if (wcscmp(archive_entry_pathname_w(ae), + L"dir1/file2") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 11); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 11); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "hello world", 11); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 11); + assertEqualInt(0, archive_read_disk_can_descend(a)); + } else if (wcscmp(archive_entry_pathname_w(ae), + L"dir1/sub1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + assertEqualInt(1, archive_read_disk_can_descend(a)); + } else if (wcscmp(archive_entry_pathname_w(ae), + L"dir1/sub1/file1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 10); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 10); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "0123456789", 10); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 10); + assertEqualInt(0, archive_read_disk_can_descend(a)); + } else if (wcscmp(archive_entry_pathname_w(ae), + L"dir1/sub2") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + assertEqualInt(1, archive_read_disk_can_descend(a)); + } else if (wcscmp(archive_entry_pathname_w(ae), + L"dir1/sub2/file1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 10); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 10); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "0123456789", 10); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 10); + assertEqualInt(0, archive_read_disk_can_descend(a)); + } else if (wcscmp(archive_entry_pathname_w(ae), + L"dir1/sub2/file2") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 10); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 10); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "0123456789", 10); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 10); + assertEqualInt(0, archive_read_disk_can_descend(a)); + } else if (wcscmp(archive_entry_pathname_w(ae), + L"dir1/sub2/sub1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + assertEqualInt(1, archive_read_disk_can_descend(a)); + } else if (wcscmp(archive_entry_pathname_w(ae), + L"dir1/sub2/sub2") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + assertEqualInt(1, archive_read_disk_can_descend(a)); + } else if (wcscmp(archive_entry_pathname_w(ae), + L"dir1/sub2/sub3") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + assertEqualInt(1, archive_read_disk_can_descend(a)); + } else if (wcscmp(archive_entry_pathname_w(ae), + L"dir1/sub2/sub3/file") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 3); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 3); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "xyz", 3); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 3); + assertEqualInt(0, archive_read_disk_can_descend(a)); + } + if (archive_entry_filetype(ae) == AE_IFDIR) { + /* Descend into the current object */ + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_descend(a)); + } + } + /* There is no entry. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); + + /* Close the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + + /* + * Test that call archive_read_disk_open with a regular file. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "dir1/file1")); + + /* dir1/file1 */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae)); + assertEqualInt(0, archive_read_disk_can_descend(a)); + assertEqualString(archive_entry_pathname(ae), "dir1/file1"); + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 10); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 10); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "0123456789", 10); + + /* There is no entry. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); + + /* Close the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + + +#if defined(_WIN32) && !defined(__CYGWIN__) + /* + * Test for wildcard '*' or '?' + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "dir1/*1")); + + /* dir1/file1 */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae)); + assertEqualInt(0, archive_read_disk_can_descend(a)); + assertEqualString(archive_entry_pathname(ae), "dir1/file1"); + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 10); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 10); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "0123456789", 10); + + /* dir1/sub1 */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae)); + assertEqualInt(1, archive_read_disk_can_descend(a)); + assertEqualString(archive_entry_pathname(ae), "dir1/sub1"); + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + + /* Descend into the current object */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_descend(a)); + + /* dir1/sub1/file1 */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae)); + assertEqualInt(0, archive_read_disk_can_descend(a)); + assertEqualString(archive_entry_pathname(ae), "dir1/sub1/file1"); + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 10); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 10); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "0123456789", 10); + + /* There is no entry. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); + + /* Close the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + + /* + * Test for a full-path beginning with "//?/" + */ + wcwd = _wgetcwd(NULL, 0); + fullpath = malloc(sizeof(wchar_t) * (wcslen(wcwd) + 32)); + wcscpy(fullpath, L"//?/"); + wcscat(fullpath, wcwd); + wcscat(fullpath, L"/dir1/file1"); + free(wcwd); + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open_w(a, fullpath)); + while ((wcwd = wcschr(fullpath, L'\\')) != NULL) + *wcwd = L'/'; + + /* dir1/file1 */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae)); + assertEqualInt(0, archive_read_disk_can_descend(a)); + assertEqualWString(archive_entry_pathname_w(ae), fullpath); + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 10); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 10); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "0123456789", 10); + + /* There is no entry. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); + + /* Close the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + free(fullpath); + + /* + * Test for wild card '*' or '?' with "//?/" prefix. + */ + wcwd = _wgetcwd(NULL, 0); + fullpath = malloc(sizeof(wchar_t) * (wcslen(wcwd) + 32)); + wcscpy(fullpath, L"//?/"); + wcscat(fullpath, wcwd); + wcscat(fullpath, L"/dir1/*1"); + free(wcwd); + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open_w(a, fullpath)); + while ((wcwd = wcschr(fullpath, L'\\')) != NULL) + *wcwd = L'/'; + + /* dir1/file1 */ + wp = wcsrchr(fullpath, L'/'); + wcscpy(wp+1, L"file1"); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae)); + assertEqualInt(0, archive_read_disk_can_descend(a)); + assertEqualWString(archive_entry_pathname_w(ae), fullpath); + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 10); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 10); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "0123456789", 10); + + /* dir1/sub1 */ + wcscpy(wp+1, L"sub1"); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae)); + assertEqualInt(1, archive_read_disk_can_descend(a)); + assertEqualWString(archive_entry_pathname_w(ae), fullpath); + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + + /* Descend into the current object */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_descend(a)); + + /* dir1/sub1/file1 */ + wcscpy(wp+1, L"sub1/file1"); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae)); + assertEqualInt(0, archive_read_disk_can_descend(a)); + assertEqualWString(archive_entry_pathname_w(ae), fullpath); + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 10); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 10); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "0123456789", 10); + + /* There is no entry. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); + + /* Close the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + free(fullpath); + +#endif + + /* + * We should be on the initial directory where we performed + * archive_read_disk_new() after we perform archive_read_free() + * even if we broke off the directory traversals. + */ + + /* Save current working directory. */ +#ifdef PATH_MAX + initial_cwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */ +#else + initial_cwd = getcwd(NULL, 0); +#endif + + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "dir1")); + + /* Step in a deep directory. */ + file_count = 12; + while (file_count--) { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header2(a, ae)); + if (strcmp(archive_entry_pathname(ae), + "dir1/sub1/file1") == 0) + /* + * We are on an another directory at this time. + */ + break; + if (archive_entry_filetype(ae) == AE_IFDIR) { + /* Descend into the current object */ + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_descend(a)); + } + } + /* Destroy the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* We should be on the initial working directory. */ + failure( + "Current working directory does not return to the initial" + "directory"); +#ifdef PATH_MAX + cwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */ +#else + cwd = getcwd(NULL, 0); +#endif + assertEqualString(initial_cwd, cwd); + free(initial_cwd); + free(cwd); + + archive_entry_free(ae); +} + +static void +test_symlink_hybrid(void) +{ + struct archive *a; + struct archive_entry *ae; + const void *p; + size_t size; + int64_t offset; + int file_count; + + if (!canSymlink()) { + skipping("Can't test symlinks on this filesystem"); + return; + } + + /* + * Create a sample archive. + */ + assertMakeDir("h", 0755); + assertChdir("h"); + assertMakeDir("d1", 0755); + assertMakeSymlink("ld1", "d1", 1); + assertMakeFile("d1/file1", 0644, "d1/file1"); + assertMakeFile("d1/file2", 0644, "d1/file2"); + assertMakeSymlink("d1/link1", "file1", 0); + assertMakeSymlink("d1/linkX", "fileX", 0); + assertMakeSymlink("link2", "d1/file2", 0); + assertMakeSymlink("linkY", "d1/fileY", 0); + assertChdir(".."); + + assert((ae = archive_entry_new()) != NULL); + assert((a = archive_read_disk_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_set_symlink_hybrid(a)); + + /* + * Specified file is a symbolic link file. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "h/ld1")); + file_count = 5; + + while (file_count--) { + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae)); + if (strcmp(archive_entry_pathname(ae), "h/ld1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + } else if (strcmp(archive_entry_pathname(ae), + "h/ld1/file1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 8); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 8); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "d1/file1", 8); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 8); + } else if (strcmp(archive_entry_pathname(ae), + "h/ld1/file2") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 8); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 8); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "d1/file2", 8); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 8); + } else if (strcmp(archive_entry_pathname(ae), + "h/ld1/link1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFLNK); + } else if (strcmp(archive_entry_pathname(ae), + "h/ld1/linkX") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFLNK); + } + if (archive_entry_filetype(ae) == AE_IFDIR) { + /* Descend into the current object */ + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_descend(a)); + } + } + /* There is no entry. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); + /* Close the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + + /* + * Specified file is a directory and it has symbolic files. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "h")); + file_count = 9; + + while (file_count--) { + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae)); + if (strcmp(archive_entry_pathname(ae), "h") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + } else if (strcmp(archive_entry_pathname(ae), "h/d1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + } else if (strcmp(archive_entry_pathname(ae), + "h/d1/file1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 8); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 8); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "d1/file1", 8); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 8); + } else if (strcmp(archive_entry_pathname(ae), + "h/d1/file2") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 8); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 8); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "d1/file2", 8); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 8); + } else if (strcmp(archive_entry_pathname(ae), "h/ld1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFLNK); + } else if (strcmp(archive_entry_pathname(ae), + "h/d1/link1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFLNK); + } else if (strcmp(archive_entry_pathname(ae), + "h/d1/linkX") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFLNK); + } else if (strcmp(archive_entry_pathname(ae), + "h/link2") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFLNK); + } else if (strcmp(archive_entry_pathname(ae), + "h/linkY") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFLNK); + } + if (archive_entry_filetype(ae) == AE_IFDIR) { + /* Descend into the current object */ + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_descend(a)); + } + } + /* There is no entry. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); + /* Close the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + /* Destroy the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + archive_entry_free(ae); +} + +static void +test_symlink_logical(void) +{ + struct archive *a; + struct archive_entry *ae; + const void *p; + size_t size; + int64_t offset; + int file_count; + + if (!canSymlink()) { + skipping("Can't test symlinks on this filesystem"); + return; + } + + /* + * Create a sample archive. + */ + assertMakeDir("l", 0755); + assertChdir("l"); + assertMakeDir("d1", 0755); + assertMakeSymlink("ld1", "d1", 1); + assertMakeFile("d1/file1", 0644, "d1/file1"); + assertMakeFile("d1/file2", 0644, "d1/file2"); + assertMakeSymlink("d1/link1", "file1", 0); + assertMakeSymlink("d1/linkX", "fileX", 0); + assertMakeSymlink("link2", "d1/file2", 0); + assertMakeSymlink("linkY", "d1/fileY", 0); + assertChdir(".."); + + /* Note: this test uses archive_read_next_header() + instead of archive_read_next_header2() */ + assert((a = archive_read_disk_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_set_symlink_logical(a)); + + /* + * Specified file is a symbolic link file. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "l/ld1")); + file_count = 5; + + while (file_count--) { + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + if (strcmp(archive_entry_pathname(ae), "l/ld1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + } else if (strcmp(archive_entry_pathname(ae), + "l/ld1/file1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 8); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 8); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "d1/file1", 8); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 8); + } else if (strcmp(archive_entry_pathname(ae), + "l/ld1/file2") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 8); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 8); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "d1/file2", 8); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 8); + } else if (strcmp(archive_entry_pathname(ae), + "l/ld1/link1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 8); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 8); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "d1/file1", 8); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 8); + } else if (strcmp(archive_entry_pathname(ae), + "l/ld1/linkX") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFLNK); + } + if (archive_entry_filetype(ae) == AE_IFDIR) { + /* Descend into the current object */ + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_descend(a)); + } + } + /* There is no entry. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + /* Close the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + + /* + * Specified file is a directory and it has symbolic files. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "l")); + file_count = 13; + + while (file_count--) { + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + if (strcmp(archive_entry_pathname(ae), "l") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + } else if (strcmp(archive_entry_pathname(ae), "l/d1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + } else if (strcmp(archive_entry_pathname(ae), + "l/d1/file1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 8); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 8); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "d1/file1", 8); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 8); + } else if (strcmp(archive_entry_pathname(ae), + "l/d1/file2") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 8); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 8); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "d1/file2", 8); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 8); + } else if (strcmp(archive_entry_pathname(ae), + "l/d1/link1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 8); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 8); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "d1/file1", 8); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 8); + } else if (strcmp(archive_entry_pathname(ae), + "l/d1/linkX") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFLNK); + } else if (strcmp(archive_entry_pathname(ae), "l/ld1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + } else if (strcmp(archive_entry_pathname(ae), + "l/ld1/file1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 8); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 8); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "d1/file1", 8); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 8); + } else if (strcmp(archive_entry_pathname(ae), + "l/ld1/file2") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 8); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 8); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "d1/file2", 8); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 8); + } else if (strcmp(archive_entry_pathname(ae), + "l/ld1/link1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 8); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 8); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "d1/file1", 8); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 8); + } else if (strcmp(archive_entry_pathname(ae), + "l/ld1/linkX") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFLNK); + } else if (strcmp(archive_entry_pathname(ae), + "l/link2") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 8); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 8); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "d1/file2", 8); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 8); + } else if (strcmp(archive_entry_pathname(ae), + "l/linkY") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFLNK); + } + if (archive_entry_filetype(ae) == AE_IFDIR) { + /* Descend into the current object */ + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_descend(a)); + } + } + /* There is no entry. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + /* Close the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + /* Destroy the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +static void +test_symlink_logical_loop(void) +{ + struct archive *a; + struct archive_entry *ae; + const void *p; + size_t size; + int64_t offset; + int file_count; + + if (!canSymlink()) { + skipping("Can't test symlinks on this filesystem"); + return; + } + + /* + * Create a sample archive. + */ + assertMakeDir("l2", 0755); + assertChdir("l2"); + assertMakeDir("d1", 0755); + assertMakeDir("d1/d2", 0755); + assertMakeDir("d1/d2/d3", 0755); + assertMakeDir("d2", 0755); + assertMakeFile("d2/file1", 0644, "d2/file1"); + assertMakeSymlink("d1/d2/ld1", "../../d1", 1); + assertMakeSymlink("d1/d2/ld2", "../../d2", 1); + assertChdir(".."); + + assert((ae = archive_entry_new()) != NULL); + assert((a = archive_read_disk_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_set_symlink_logical(a)); + + /* + * Specified file is a symbolic link file. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "l2/d1")); + file_count = 6; + + while (file_count--) { + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae)); + if (strcmp(archive_entry_pathname(ae), "l2/d1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + } else if (strcmp(archive_entry_pathname(ae), "l2/d1/d2") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + } else if (strcmp(archive_entry_pathname(ae), "l2/d1/d2/d3") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + } else if (strcmp(archive_entry_pathname(ae), "l2/d1/d2/ld1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFLNK); + } else if (strcmp(archive_entry_pathname(ae), "l2/d1/d2/ld2") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + } else if (strcmp(archive_entry_pathname(ae), + "l2/d1/d2/ld2/file1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 8); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 8); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "d2/file1", 8); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 8); + } + if (archive_entry_filetype(ae) == AE_IFDIR) { + /* Descend into the current object */ + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_descend(a)); + } + } + /* There is no entry. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); + /* Destroy the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + archive_entry_free(ae); +} + +static void +test_restore_atime(void) +{ + struct archive *a; + struct archive_entry *ae; + const void *p; + size_t size; + int64_t offset; + int file_count; + + if (!atimeIsUpdated()) { + skipping("Can't test restoring atime on this filesystem"); + return; + } + + assertMakeDir("at", 0755); + assertMakeFile("at/f1", 0644, "0123456789"); + assertMakeFile("at/f2", 0644, "hello world"); + assertMakeFile("at/fe", 0644, NULL); + assertUtimes("at/f1", 886600, 0, 886600, 0); + assertUtimes("at/f2", 886611, 0, 886611, 0); + assertUtimes("at/fe", 886611, 0, 886611, 0); + assertUtimes("at", 886622, 0, 886622, 0); + file_count = 4; + + assert((ae = archive_entry_new()) != NULL); + assert((a = archive_read_disk_new()) != NULL); + + /* + * Test1: Traversals without archive_read_disk_set_atime_restored(). + */ + failure("Directory traversals should work as well"); + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at")); + while (file_count--) { + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae)); + if (strcmp(archive_entry_pathname(ae), "at") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + } else if (strcmp(archive_entry_pathname(ae), "at/f1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 10); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 10); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "0123456789", 10); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 10); + } else if (strcmp(archive_entry_pathname(ae), "at/f2") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 11); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 11); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "hello world", 11); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 11); + } else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 0); + } + if (archive_entry_filetype(ae) == AE_IFDIR) { + /* Descend into the current object */ + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_descend(a)); + } + } + /* There is no entry. */ + failure("There must be no entry"); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); + + /* On FreeBSD (and likely other systems), atime on + dirs does not change when it is read. */ + /* failure("Atime should be restored"); */ + /* assertFileAtimeRecent("at"); */ + failure("Atime should be restored"); + assertFileAtimeRecent("at/f1"); + failure("Atime should be restored"); + assertFileAtimeRecent("at/f2"); + failure("The atime of a empty file should not be changed"); + assertFileAtime("at/fe", 886611, 0); + + /* Close the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + + /* + * Test2: Traversals with archive_read_disk_set_atime_restored(). + */ + assertUtimes("at/f1", 886600, 0, 886600, 0); + assertUtimes("at/f2", 886611, 0, 886611, 0); + assertUtimes("at/fe", 886611, 0, 886611, 0); + assertUtimes("at", 886622, 0, 886622, 0); + file_count = 4; + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_atime_restored(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at")); + + failure("Directory traversals should work as well"); + while (file_count--) { + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae)); + if (strcmp(archive_entry_pathname(ae), "at") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + } else if (strcmp(archive_entry_pathname(ae), "at/f1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 10); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 10); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "0123456789", 10); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 10); + } else if (strcmp(archive_entry_pathname(ae), "at/f2") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 11); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 11); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "hello world", 11); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 11); + } else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 0); + } + if (archive_entry_filetype(ae) == AE_IFDIR) { + /* Descend into the current object */ + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_descend(a)); + } + } + /* There is no entry. */ + failure("There must be no entry"); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); + + failure("Atime should be restored"); + assertFileAtime("at", 886622, 0); + failure("Atime should be restored"); + assertFileAtime("at/f1", 886600, 0); + failure("Atime should be restored"); + assertFileAtime("at/f2", 886611, 0); + failure("The atime of a empty file should not be changed"); + assertFileAtime("at/fe", 886611, 0); + + /* Close the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + + /* + * Test3: Traversals with archive_read_disk_set_atime_restored() but + * no data read as a listing. + */ + assertUtimes("at/f1", 886600, 0, 886600, 0); + assertUtimes("at/f2", 886611, 0, 886611, 0); + assertUtimes("at/fe", 886611, 0, 886611, 0); + assertUtimes("at", 886622, 0, 886622, 0); + file_count = 4; + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_atime_restored(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at")); + + failure("Directory traversals should work as well"); + while (file_count--) { + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae)); + if (strcmp(archive_entry_pathname(ae), "at") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + } else if (strcmp(archive_entry_pathname(ae), "at/f1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 10); + } else if (strcmp(archive_entry_pathname(ae), "at/f2") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 11); + } else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 0); + } + if (archive_entry_filetype(ae) == AE_IFDIR) { + /* Descend into the current object */ + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_descend(a)); + } + } + /* There is no entry. */ + failure("There must be no entry"); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); + + failure("Atime should be restored"); + assertFileAtime("at", 886622, 0); + failure("Atime should be restored"); + assertFileAtime("at/f1", 886600, 0); + failure("Atime should be restored"); + assertFileAtime("at/f2", 886611, 0); + failure("The atime of a empty file should not be changed"); + assertFileAtime("at/fe", 886611, 0); + + if (!canNodump()) { + /* Destroy the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + archive_entry_free(ae); + skipping("Can't test atime with nodump on this filesystem"); + return; + } + + /* Close the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + + /* + * Test4: Traversals with ARCHIVE_READDISK_RESTORE_ATIME and + * ARCHIVE_READDISK_HONOR_NODUMP + */ + assertSetNodump("at/f1"); + assertSetNodump("at/f2"); + assertUtimes("at/f1", 886600, 0, 886600, 0); + assertUtimes("at/f2", 886611, 0, 886611, 0); + assertUtimes("at/fe", 886611, 0, 886611, 0); + assertUtimes("at", 886622, 0, 886622, 0); + file_count = 2; + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_behavior(a, + ARCHIVE_READDISK_RESTORE_ATIME | ARCHIVE_READDISK_HONOR_NODUMP)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at")); + + failure("Directory traversals should work as well"); + while (file_count--) { + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae)); + if (strcmp(archive_entry_pathname(ae), "at") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + } else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 0); + } + if (archive_entry_filetype(ae) == AE_IFDIR) { + /* Descend into the current object */ + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_descend(a)); + } + } + /* There is no entry. */ + failure("There must be no entry"); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); + + failure("Atime should be restored"); + assertFileAtime("at", 886622, 0); + failure("Atime should be restored"); + assertFileAtime("at/f1", 886600, 0); + failure("Atime should be restored"); + assertFileAtime("at/f2", 886611, 0); + failure("The atime of a empty file should not be changed"); + assertFileAtime("at/fe", 886611, 0); + + /* Destroy the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + archive_entry_free(ae); +} + +static int +metadata_filter(struct archive *a, void *data, struct archive_entry *ae) +{ + (void)data; /* UNUSED */ + + failure("CTime should be set"); + assertEqualInt(8, archive_entry_ctime_is_set(ae)); + failure("MTime should be set"); + assertEqualInt(16, archive_entry_mtime_is_set(ae)); + + if (archive_entry_mtime(ae) < 886611) + return (0); + if (archive_read_disk_can_descend(a)) { + /* Descend into the current object */ + failure("archive_read_disk_can_descend should work" + " in metadata filter"); + assertEqualIntA(a, 1, archive_read_disk_can_descend(a)); + failure("archive_read_disk_descend should work" + " in metadata filter"); + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_descend(a)); + } + return (1); +} + +static void +test_callbacks(void) +{ + struct archive *a; + struct archive *m; + struct archive_entry *ae; + const void *p; + size_t size; + int64_t offset; + int file_count; + + assertMakeDir("cb", 0755); + assertMakeFile("cb/f1", 0644, "0123456789"); + assertMakeFile("cb/f2", 0644, "hello world"); + assertMakeFile("cb/fe", 0644, NULL); + assertUtimes("cb/f1", 886600, 0, 886600, 0); + assertUtimes("cb/f2", 886611, 0, 886611, 0); + assertUtimes("cb/fe", 886611, 0, 886611, 0); + assertUtimes("cb", 886622, 0, 886622, 0); + + assert((ae = archive_entry_new()) != NULL); + assert((a = archive_read_disk_new()) != NULL); + if (a == NULL) { + archive_entry_free(ae); + return; + } + assert((m = archive_match_new()) != NULL); + if (m == NULL) { + archive_entry_free(ae); + archive_read_free(a); + archive_match_free(m); + return; + } + + /* + * Test1: Traversals with a name filter. + */ + file_count = 3; + assertEqualIntA(m, ARCHIVE_OK, + archive_match_exclude_pattern(m, "cb/f2")); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_set_matching(a, m, NULL, NULL)); + failure("Directory traversals should work as well"); + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "cb")); + while (file_count--) { + archive_entry_clear(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae)); + failure("File 'cb/f2' should be exclueded"); + assert(strcmp(archive_entry_pathname(ae), "cb/f2") != 0); + if (strcmp(archive_entry_pathname(ae), "cb") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + } else if (strcmp(archive_entry_pathname(ae), "cb/f1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 10); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 10); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "0123456789", 10); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 10); + } else if (strcmp(archive_entry_pathname(ae), "cb/fe") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 0); + } + if (archive_read_disk_can_descend(a)) { + /* Descend into the current object */ + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_descend(a)); + } + } + /* There is no entry. */ + failure("There should be no entry"); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); + + /* Close the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + + /* Reset name filter */ + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_set_matching(a, NULL, NULL, NULL)); + + /* + * Test2: Traversals with a metadata filter. + */ + assertUtimes("cb/f1", 886600, 0, 886600, 0); + assertUtimes("cb/f2", 886611, 0, 886611, 0); + assertUtimes("cb/fe", 886611, 0, 886611, 0); + assertUtimes("cb", 886622, 0, 886622, 0); + file_count = 3; + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_set_metadata_filter_callback(a, metadata_filter, + NULL)); + failure("Directory traversals should work as well"); + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "cb")); + + while (file_count--) { + archive_entry_clear(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae)); + failure("File 'cb/f1' should be excluded"); + assert(strcmp(archive_entry_pathname(ae), "cb/f1") != 0); + if (strcmp(archive_entry_pathname(ae), "cb") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + } else if (strcmp(archive_entry_pathname(ae), "cb/f2") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 11); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 11); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "hello world", 11); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 11); + } else if (strcmp(archive_entry_pathname(ae), "cb/fe") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 0); + } + } + /* There is no entry. */ + failure("There should be no entry"); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); + + /* Destroy the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_match_free(m)); + archive_entry_free(ae); +} + +static void +test_nodump(void) +{ + struct archive *a; + struct archive_entry *ae; + const void *p; + size_t size; + int64_t offset; + int file_count; + + if (!canNodump()) { + skipping("Can't test nodump on this filesystem"); + return; + } + + assertMakeDir("nd", 0755); + assertMakeFile("nd/f1", 0644, "0123456789"); + assertMakeFile("nd/f2", 0644, "hello world"); + assertMakeFile("nd/fe", 0644, NULL); + assertSetNodump("nd/f2"); + assertUtimes("nd/f1", 886600, 0, 886600, 0); + assertUtimes("nd/f2", 886611, 0, 886611, 0); + assertUtimes("nd/fe", 886611, 0, 886611, 0); + assertUtimes("nd", 886622, 0, 886622, 0); + + assert((ae = archive_entry_new()) != NULL); + assert((a = archive_read_disk_new()) != NULL); + + /* + * Test1: Traversals without ARCHIVE_READDISK_HONOR_NODUMP + */ + failure("Directory traversals should work as well"); + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "nd")); + + file_count = 4; + while (file_count--) { + archive_entry_clear(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae)); + if (strcmp(archive_entry_pathname(ae), "nd") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + } else if (strcmp(archive_entry_pathname(ae), "nd/f1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 10); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 10); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "0123456789", 10); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 10); + } else if (strcmp(archive_entry_pathname(ae), "nd/f2") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 11); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 11); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "hello world", 11); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 11); + } else if (strcmp(archive_entry_pathname(ae), "nd/fe") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 0); + } + if (archive_read_disk_can_descend(a)) { + /* Descend into the current object */ + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_descend(a)); + } + } + /* There is no entry. */ + failure("There should be no entry"); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); + + /* Close the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + + /* + * Test2: Traversals with ARCHIVE_READDISK_HONOR_NODUMP + */ + assertUtimes("nd/f1", 886600, 0, 886600, 0); + assertUtimes("nd/f2", 886611, 0, 886611, 0); + assertUtimes("nd/fe", 886611, 0, 886611, 0); + assertUtimes("nd", 886622, 0, 886622, 0); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_behavior(a, + ARCHIVE_READDISK_RESTORE_ATIME | ARCHIVE_READDISK_HONOR_NODUMP)); + failure("Directory traversals should work as well"); + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "nd")); + + file_count = 3; + while (file_count--) { + archive_entry_clear(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae)); + failure("File 'nd/f2' should be exclueded"); + assert(strcmp(archive_entry_pathname(ae), "nd/f2") != 0); + if (strcmp(archive_entry_pathname(ae), "nd") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + } else if (strcmp(archive_entry_pathname(ae), "nd/f1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 10); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 10); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "0123456789", 10); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 10); + } else if (strcmp(archive_entry_pathname(ae), "nd/fe") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 0); + } + if (archive_read_disk_can_descend(a)) { + /* Descend into the current object */ + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_descend(a)); + } + } + /* There is no entry. */ + failure("There should be no entry"); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); + + failure("Atime should be restored"); + assertFileAtime("nd/f2", 886611, 0); + + /* Destroy the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + archive_entry_free(ae); +} + +static void +test_parent(void) +{ + struct archive *a; + struct archive_entry *ae; + const void *p; + size_t size; + int64_t offset; + int file_count; + int match_count; + int r; + + assertMakeDir("lock", 0311); + assertMakeDir("lock/dir1", 0755); + assertMakeFile("lock/dir1/f1", 0644, "0123456789"); + assertMakeDir("lock/lock2", 0311); + assertMakeDir("lock/lock2/dir1", 0755); + assertMakeFile("lock/lock2/dir1/f1", 0644, "0123456789"); + + assert((ae = archive_entry_new()) != NULL); + assert((a = archive_read_disk_new()) != NULL); + + /* + * Test1: Traverse lock/dir1 as . + */ + assertChdir("lock/dir1"); + + failure("Directory traversals should work as well"); + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, ".")); + + file_count = 2; + match_count = 0; + while (file_count--) { + archive_entry_clear(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae)); + if (strcmp(archive_entry_pathname(ae), ".") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + ++match_count; + } else if (strcmp(archive_entry_pathname(ae), "./f1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 10); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 10); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "0123456789", 10); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 10); + ++match_count; + } + if (archive_read_disk_can_descend(a)) { + /* Descend into the current object */ + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_descend(a)); + } + } + failure("Did not match expected filenames"); + assertEqualInt(match_count, 2); + /* + * There is no entry. This will however fail if the directory traverse + * tries to ascend past the initial directory, since it lacks permission + * to do so. + */ + failure("There should be no entry and no error"); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); + + /* Close the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + + assertChdir("../.."); + + /* + * Test2: Traverse lock/dir1 directly + */ + failure("Directory traversals should work as well"); + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "lock/dir1")); + + file_count = 2; + match_count = 0; + while (file_count--) { + archive_entry_clear(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae)); + if (strcmp(archive_entry_pathname(ae), "lock/dir1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + ++match_count; + } else if (strcmp(archive_entry_pathname(ae), "lock/dir1/f1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 10); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 10); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "0123456789", 10); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 10); + ++match_count; + } + if (archive_read_disk_can_descend(a)) { + /* Descend into the current object */ + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_descend(a)); + } + } + failure("Did not match expected filenames"); + assertEqualInt(match_count, 2); + /* + * There is no entry. This will however fail if the directory traverse + * tries to ascend past the initial directory, since it lacks permission + * to do so. + */ + failure("There should be no entry and no error"); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); + + /* Close the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + + /* + * Test3: Traverse lock/dir1/. + */ + failure("Directory traversals should work as well"); + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "lock/dir1/.")); + + file_count = 2; + match_count = 0; + while (file_count--) { + archive_entry_clear(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae)); + if (strcmp(archive_entry_pathname(ae), "lock/dir1/.") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + ++match_count; + } else if (strcmp(archive_entry_pathname(ae), "lock/dir1/./f1") == 0) { + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 10); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 10); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "0123456789", 10); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 10); + ++match_count; + } + if (archive_read_disk_can_descend(a)) { + /* Descend into the current object */ + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_descend(a)); + } + } + failure("Did not match expected filenames"); + assertEqualInt(match_count, 2); + /* + * There is no entry. This will however fail if the directory traverse + * tries to ascend past the initial directory, since it lacks permission + * to do so. + */ + failure("There should be no entry and no error"); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); + + /* Close the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + + /* + * Test4: Traverse lock/lock2/dir1 from inside lock. + * + * This test is expected to fail on platforms with no O_EXEC or + * equivalent (e.g. O_PATH on Linux or O_SEARCH on SunOS), because + * the current traversal code can't handle the case where it can't + * obtain an open fd for the initial current directory. We need to + * check that condition here, because if O_EXEC _does_ exist, we don't + * want to overlook any failure. + */ + assertChdir("lock"); + + failure("Directory traversals should work as well"); + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "lock2/dir1")); + + archive_entry_clear(ae); + r = archive_read_next_header2(a, ae); + if (r == ARCHIVE_FAILED) { +#if defined(O_PATH) || defined(O_SEARCH) || \ + (defined(__FreeBSD__) && defined(O_EXEC)) + assertEqualIntA(a, ARCHIVE_OK, r); +#endif + /* Close the disk object. */ + archive_read_close(a); + } else { + file_count = 2; + match_count = 0; + while (file_count--) { + if (file_count == 0) + assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header2(a, ae)); + if (strcmp(archive_entry_pathname(ae), + "lock2/dir1") == 0) { + assertEqualInt(archive_entry_filetype(ae), + AE_IFDIR); + ++match_count; + } else if (strcmp(archive_entry_pathname(ae), + "lock2/dir1/f1") == 0) { + assertEqualInt(archive_entry_filetype(ae), + AE_IFREG); + assertEqualInt(archive_entry_size(ae), 10); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, + &offset)); + assertEqualInt((int)size, 10); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "0123456789", 10); + assertEqualInt(ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, + &offset)); + assertEqualInt((int)size, 0); + assertEqualInt((int)offset, 10); + ++match_count; + } + if (archive_read_disk_can_descend(a)) { + /* Descend into the current object */ + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_descend(a)); + } + } + failure("Did not match expected filenames"); + assertEqualInt(match_count, 2); + /* + * There is no entry. This will however fail if the directory + * traverse tries to ascend past the initial directory, since + * it lacks permission to do so. + */ + failure("There should be no entry and no error"); + assertEqualIntA(a, ARCHIVE_EOF, + archive_read_next_header2(a, ae)); + + /* Close the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + } + + assertChdir(".."); + + /* Destroy the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + archive_entry_free(ae); +} + +DEFINE_TEST(test_read_disk_directory_traversals) +{ + /* Basic test. */ + test_basic(); + /* Test hybrid mode; follow symlink initially, then not. */ + test_symlink_hybrid(); + /* Test logical mode; follow all symlinks. */ + test_symlink_logical(); + /* Test logical mode; prevent loop in symlinks. */ + test_symlink_logical_loop(); + /* Test to restore atime. */ + test_restore_atime(); + /* Test callbacks. */ + test_callbacks(); + /* Test nodump. */ + test_nodump(); + /* Test parent overshoot. */ + test_parent(); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_disk_entry_from_file.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_disk_entry_from_file.c new file mode 100644 index 0000000..7a41034 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_disk_entry_from_file.c @@ -0,0 +1,80 @@ +/*- + * Copyright (c) 2003-2009 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_disk_entry_from_file.c 201247 2009-12-30 05:59:21Z kientzle $"); + +static const char * +gname_lookup(void *d, int64_t g) +{ + (void)d; /* UNUSED */ + (void)g; /* UNUSED */ + return ("FOOGROUP"); +} + +static const char * +uname_lookup(void *d, int64_t u) +{ + (void)d; /* UNUSED */ + (void)u; /* UNUSED */ + return ("FOO"); +} + +DEFINE_TEST(test_read_disk_entry_from_file) +{ + struct archive *a; + struct archive_entry *entry; + FILE *f; + + assert((a = archive_read_disk_new()) != NULL); + + assertEqualInt(ARCHIVE_OK, archive_read_disk_set_uname_lookup(a, + NULL, &uname_lookup, NULL)); + assertEqualInt(ARCHIVE_OK, archive_read_disk_set_gname_lookup(a, + NULL, &gname_lookup, NULL)); + assertEqualString(archive_read_disk_uname(a, 0), "FOO"); + assertEqualString(archive_read_disk_gname(a, 0), "FOOGROUP"); + + /* Create a file on disk. */ + f = fopen("foo", "wb"); + assert(f != NULL); + assertEqualInt(4, fwrite("1234", 1, 4, f)); + fclose(f); + + /* Use archive_read_disk_entry_from_file to get information about it. */ + entry = archive_entry_new(); + assert(entry != NULL); + archive_entry_copy_pathname(entry, "foo"); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, entry, -1, NULL)); + + /* Verify the information we got back. */ + assertEqualString(archive_entry_uname(entry), "FOO"); + assertEqualString(archive_entry_gname(entry), "FOOGROUP"); + assertEqualInt(archive_entry_size(entry), 4); + + /* Destroy the archive. */ + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_extract.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_extract.c new file mode 100644 index 0000000..2b1a21e --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_extract.c @@ -0,0 +1,168 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_extract.c 201247 2009-12-30 05:59:21Z kientzle $"); + +#define BUFF_SIZE 1000000 +#define FILE_BUFF_SIZE 100000 + +DEFINE_TEST(test_read_extract) +{ + struct archive_entry *ae; + struct archive *a; + size_t used; + int i, numEntries = 0; + char *buff, *file_buff; + + buff = malloc(BUFF_SIZE); + file_buff = malloc(FILE_BUFF_SIZE); + + /* Force the umask to something predictable. */ + assertUmask(022); + + /* Create a new archive in memory containing various types of entries. */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_ustar(a)); + assertA(0 == archive_write_add_filter_none(a)); + assertA(0 == archive_write_open_memory(a, buff, BUFF_SIZE, &used)); + /* A directory to be restored with EXTRACT_PERM. */ + ++numEntries; + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "dir_0775"); + archive_entry_set_mode(ae, S_IFDIR | 0775); + assertA(0 == archive_write_header(a, ae)); + archive_entry_free(ae); + /* A regular file. */ + ++numEntries; + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file"); + archive_entry_set_mode(ae, S_IFREG | 0755); + for (i = 0; i < FILE_BUFF_SIZE; i++) + file_buff[i] = (unsigned char)rand(); + archive_entry_set_size(ae, FILE_BUFF_SIZE); + assertA(0 == archive_write_header(a, ae)); + assertA(FILE_BUFF_SIZE == archive_write_data(a, file_buff, FILE_BUFF_SIZE)); + archive_entry_free(ae); + /* A directory that should obey umask when restored. */ + ++numEntries; + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "dir"); + archive_entry_set_mode(ae, S_IFDIR | 0777); + assertA(0 == archive_write_header(a, ae)); + archive_entry_free(ae); + /* A file in the directory. */ + ++numEntries; + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "dir/file"); + archive_entry_set_mode(ae, S_IFREG | 0700); + assertA(0 == archive_write_header(a, ae)); + archive_entry_free(ae); + /* A file in a dir that is not already in the archive. */ + ++numEntries; + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "dir2/file"); + archive_entry_set_mode(ae, S_IFREG | 0000); + assertA(0 == archive_write_header(a, ae)); + archive_entry_free(ae); + /* A dir with a trailing /. */ + ++numEntries; + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "dir3/."); + archive_entry_set_mode(ae, S_IFDIR | 0710); + assertA(0 == archive_write_header(a, ae)); + archive_entry_free(ae); + /* Multiple dirs with a single entry. */ + ++numEntries; + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "dir4/a/../b/../c/"); + archive_entry_set_mode(ae, S_IFDIR | 0711); + assertA(0 == archive_write_header(a, ae)); + archive_entry_free(ae); + /* A symlink. */ + if (canSymlink()) { + ++numEntries; + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "symlink"); + archive_entry_set_mode(ae, AE_IFLNK | 0755); + archive_entry_set_symlink(ae, "file"); + assertA(0 == archive_write_header(a, ae)); + archive_entry_free(ae); + } + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Extract the entries to disk. */ + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_open_memory(a, buff, BUFF_SIZE)); + /* Restore first entry with _EXTRACT_PERM. */ + failure("Error reading first entry"); + assertA(0 == archive_read_next_header(a, &ae)); + assertA(0 == archive_read_extract(a, ae, ARCHIVE_EXTRACT_PERM)); + /* Rest of entries get restored with no flags. */ + for (i = 1; i < numEntries; i++) { + failure("Error reading entry %d", i); + assertA(0 == archive_read_next_header(a, &ae)); + failure("Failed to extract entry %d: %s", i, + archive_entry_pathname(ae)); + assertA(0 == archive_read_extract(a, ae, 0)); + } + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* Test the entries on disk. */ + /* This first entry was extracted with ARCHIVE_EXTRACT_PERM, + * so the permissions should have been restored exactly, + * including resetting the gid bit on those platforms + * where gid is inherited by subdirs. */ + failure("This was 0775 in archive, and should be 0775 on disk"); + assertIsDir("dir_0775", 0775); + /* Everything else was extracted without ARCHIVE_EXTRACT_PERM, + * so there may be some sloppiness about gid bits on directories. */ + assertIsReg("file", 0755); + assertFileSize("file", FILE_BUFF_SIZE); + assertFileContents(file_buff, FILE_BUFF_SIZE, "file"); + /* If EXTRACT_PERM wasn't used, be careful to ignore sgid bit + * when checking dir modes, as some systems inherit sgid bit + * from the parent dir. */ + failure("This was 0777 in archive, but umask should make it 0755"); + assertIsDir("dir", 0755); + assertIsReg("dir/file", 0700); + assertIsDir("dir2", 0755); + assertIsReg("dir2/file", 0000); + assertIsDir("dir3", 0710); + assertIsDir("dir4", 0755); + assertIsDir("dir4/a", 0755); + assertIsDir("dir4/b", 0755); + assertIsDir("dir4/c", 0711); + if (canSymlink()) + assertIsSymlink("symlink", "file", 0); + + free(buff); + free(file_buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_file_nonexistent.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_file_nonexistent.c new file mode 100644 index 0000000..acb72a1 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_file_nonexistent.c @@ -0,0 +1,37 @@ +/*- + * Copyright (c) 2003-2009 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_file_nonexistent.c 189473 2009-03-07 02:09:21Z kientzle $"); + +DEFINE_TEST(test_read_file_nonexistent) +{ + struct archive* a = archive_read_new(); + assertEqualInt(ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualInt(ARCHIVE_FATAL, + archive_read_open_filename(a, "notexistent.tar", 512)); + archive_read_free(a); +} + + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_filter_compress.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_filter_compress.c new file mode 100644 index 0000000..03a1d5f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_filter_compress.c @@ -0,0 +1,80 @@ +/*- + * Copyright (c) 2003-2008 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_read_filter_compress_truncated) +{ + const char data[] = {0x1f, 0x9d}; + struct archive *a; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_compress(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_FATAL, + archive_read_open_memory(a, data, sizeof(data))); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + +DEFINE_TEST(test_read_filter_compress_empty2) +{ + const char data[] = {0x1f, 0x9d, 0x10}; + struct archive *a; + struct archive_entry *ae; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_compress(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, data, sizeof(data))); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify that the format detection worked. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); + assertEqualString(archive_filter_name(a, 0), "compress (.Z)"); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_EMPTY); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + +DEFINE_TEST(test_read_filter_compress_invalid) +{ + const char data[] = {0x1f, 0x9d, 0x11}; + struct archive *a; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_compress(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_FATAL, + archive_read_open_memory(a, data, sizeof(data))); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_filter_grzip.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_filter_grzip.c new file mode 100644 index 0000000..43bd5bc --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_filter_grzip.c @@ -0,0 +1,67 @@ +/*- + * Copyright (c) 2003-2008 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_read_filter_grzip) +{ + const char *name = "test_read_filter_grzip.tar.grz"; + /* grzip tracks directories as files, ensure that we list everything */ + const char *n[] = { + "f1", "f2", "f3", "d1/f1", "d1/f2", "d1/f3", NULL }; + struct archive_entry *ae; + struct archive *a; + int i; + + if (!canGrzip()) { + skipping("grzip command-line program not found"); + return; + } + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_WARN, archive_read_support_filter_grzip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + extract_reference_file(name); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, name, 200)); + + /* Read entries, match up names with list above. */ + for (i = 0; n[i] != NULL; ++i) { + failure("Could not read file %d (%s) from %s", i, n[i], name); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae)); + assertEqualString(n[i], archive_entry_pathname(ae)); + } + + /* Verify the end-of-archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify that the format detection worked. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_GRZIP); + assertEqualString(archive_filter_name(a, 0), "grzip"); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_filter_grzip.tar.grz.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_filter_grzip.tar.grz.uu new file mode 100644 index 0000000..3f55b93 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_filter_grzip.tar.grz.uu @@ -0,0 +1,8 @@ +begin 644 test_read_filter_grzip.tar.grz +M1U)::7!)20`"!#HI`!P``*P,```L`0``\````)D```#Y.$+F+B8PQP#^C=PP +MI/#7H?$H,(_!0<=O!,4![T/;;'S,=B0_3(R1=9"=YKA%RKR-\,+PJIO2]!I*2V31X]P[DN$GOEND]NJE=5AP+]64N7$3):G02EKP>+AD`!IH`HQ(` +M```R#$'@#E`G"/SW..;YC%X%73G3%U_;&GA#Y7N&P\[%?V!^'>:#?(>JQW** +M1]!%JV?=U`TD.@:H85S[7D\VH/]%6JQ>/;HI.E&)I2N1_M4BU:942T`-IN<9%AZFZVY]'A)5%EY;Y0S/4MGN]Y +D9.U/9Y/!R!PQ$O_\1>]J_8\^I0",9(YV]K_!A:WK9='*J7,1 +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_filter_lzop.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_filter_lzop.c new file mode 100644 index 0000000..acce6a4 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_filter_lzop.c @@ -0,0 +1,77 @@ +/*- + * Copyright (c) 2003-2008 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_read_filter_lzop) +{ + const char *reference = "test_read_filter_lzop.tar.lzo"; + /* lrzip tracks directories as files, ensure that we list everything */ + const char *n[] = { + "d1/", "d1/f2", "d1/f3", "d1/f1", "f1", "f2", "f3", NULL }; + struct archive_entry *ae; + struct archive *a; + int i, r; + + extract_reference_file(reference); + assert((a = archive_read_new()) != NULL); + r = archive_read_support_filter_lzop(a); + if (r != ARCHIVE_OK) { + if (!canLzop()) { + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + skipping("lzop compression is not supported " + "on this platform"); + return; + } else if (r != ARCHIVE_WARN) { + assertEqualIntA(a, ARCHIVE_OK, r); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, reference, 10240)); + + /* Read entries, match up names with list above. */ + for (i = 0; n[i] != NULL; ++i) { + failure("Could not read file %d (%s) from %s", + i, n[i], reference); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae)); + assertEqualString(n[i], archive_entry_pathname(ae)); + } + + /* Verify the end-of-archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify that the format detection worked. */ + assertEqualInt(archive_filter_count(a), 2); + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_LZOP); + assertEqualString(archive_filter_name(a, 0), "lzop"); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_filter_lzop.tar.lzo.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_filter_lzop.tar.lzo.uu new file mode 100644 index 0000000..d5fcc30 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_filter_lzop.tar.lzo.uu @@ -0,0 +1,11 @@ +begin 664 test_read_filter_lzop.tar.lzo +MB4Q:3P`-"AH*$#`@8`E``04#```!``"!M%!PQ.T`````&71E`V0Q+P```"`]```+,#`P +M-S@'A`L@%/T',"``1OT'9B`_\P<````@#?T'-W__-C8V(`!'_`<@ +M/_`?(!?]!S<@`$?\!R`_\!\@%OT'-R``1_P7@/0@````RA````$````````` +3````````````````$0`````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_filter_lzop_multiple_parts.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_filter_lzop_multiple_parts.c new file mode 100644 index 0000000..82eaf35 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_filter_lzop_multiple_parts.c @@ -0,0 +1,76 @@ +/*- + * Copyright (c) 2003-2008 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_read_filter_lzop_multiple_parts) +{ + const char *reference = "test_read_filter_lzop_multiple_parts.tar.lzo"; + struct archive_entry *ae; + struct archive *a; + int r; + + extract_reference_file(reference); + assert((a = archive_read_new()) != NULL); + r = archive_read_support_filter_lzop(a); + if (r != ARCHIVE_OK) { + if (!canLzop()) { + skipping("lzop compression is not supported " + "on this platform"); + } else if (r == ARCHIVE_WARN) { + skipping("lzop multiple parts decoding is not " + "supported via external program"); + + } else + assertEqualIntA(a, ARCHIVE_OK, r); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, reference, 10240)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("file1", archive_entry_pathname(ae)); + assertEqualInt(19, archive_entry_size(ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("file2", archive_entry_pathname(ae)); + assertEqualInt(262144, archive_entry_size(ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("file3", archive_entry_pathname(ae)); + assertEqualInt(19, archive_entry_size(ae)); + + /* Verify the end-of-archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify that the format detection worked. */ + assertEqualInt(archive_filter_count(a), 2); + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_LZOP); + assertEqualString(archive_filter_name(a, 0), "lzop"); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_filter_lzop_multiple_parts.tar.lzo.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_filter_lzop_multiple_parts.tar.lzo.uu new file mode 100644 index 0000000..4f8fcbf --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_filter_lzop_multiple_parts.tar.lzo.uu @@ -0,0 +1,89 @@ +begin 664 test_read_filter_lzop_multiple_parts.tar.lzo +MB4Q:3P`-"AH*$#`@8`E``04#```!``"!M%"`KW@`````"W1E?S4W(`!&_`\@/N@'(``````` +M`````````````````````````````````````)!X`0X````````````````` +M`````!$```````")3%I/``T*&@H0,"!@"4`!!0,```$``(&T4("O>``````+ +M=&5S=%]L>F]P86)^0`CR```H`````$DH```!`@``````(``````````````` +M`````````````````````````````````````.X0```!```````````````` +M`````````!$```````")3%I/``T*&@H0,"!@"4`!!0,```$``(&T4("O>``` +M```+=&5S=%]L>F]P86-^00CS```H`````$DH```!`@``````(``````````` +M`````````````````````````````````````````.X0```!```````````` +M`````````````!$```````")3%I/``T*&@H0,"!@"4`!!0,```$``(&T4("O +M>``````+=&5S=%]L>F]P861^0@CT```H`````$DH```!`@``````(``````` +M`````````````````````````````````````````````.X0```!```````` +M`````````````````!$```````")3%I/``T*&@H0,"!@"4`!!0,```$``(&T +M4("O>``````+=&5S=%]L>F]P865^0PCU```H`````$DH```!`@``````(``` +M`````````````````````````````````````````````````.X0```!```` +M`````````````````````!$```````")3%I/``T*&@H0,"!@"4`!!0,```$` +M`(&T4("O>``````+=&5S=%]L>F]P869^1`CV```H`````$DH```!`@`````` +M(````````````````````````````````````````````````````.X0```! +M`````````````````````````!$```````")3%I/``T*&@H0,"!@"4`!!0,` +M``$``(&T4("O>``````+=&5S=%]L>F]P86=^10CW```H`````$DH```!`@`` +M````(````````````````````````````````````````````````````.X0 +M```!`````````````````````````!$```````")3%I/``T*&@H0,"!@"4`! +M!0,```$``(&T4("O>``````+=&5S=%]L>F]P86A^1@CX```H`````$DH```! +M`@``````(``````````````````````````````````````````````````` +M`.X0```!`````````````````````````!$```````")3%I/``T*&@H0,"!@ +M"4`!!0,```$``(&T4("O>``````+=&5S=%]L>F]P86E^1PCY```H`````$DH +M```!`@``````(``````````````````````````````````````````````` +M`````.X0```!`````````````````````````!$```````")3%I/``T*&@H0 +M,"!@"4`!!0,```$``(&T4("O>``````+=&5S=%]L>F]P86I^2`CZ```H```` +M`$DH```!`@``````(``````````````````````````````````````````` +M`````````.X0```!`````````````````````````!$```````")3%I/``T* +M&@H0,"!@"4`!!0,```$``(&T4("O>``````+=&5S=%]L>F]P86M^20C[```H +M`````$DH```!`@``````(``````````````````````````````````````` +M`````````````.X0```!`````````````````````````!$```````")3%I/ +M``T*&@H0,"!@"4`!!0,```$``(&T4("O>``````+=&5S=%]L>F]P86Q^2@C\ +M```H`````$DH```!`@``````(``````````````````````````````````` +M`````````````````.X0```!`````````````````````````!$```````") +M3%I/``T*&@H0,"!@"4`!!0,```$``(&T4("O>``````+=&5S=%]L>F]P86U^ +M2PC]```H`````$DH```!`@``````(``````````````````````````````` +M`````````````````````.X0```!`````````````````````````!$````` +M``")3%I/``T*&@H0,"!@"4`!!0,```$``(&T4("O>``````+=&5S=%]L>F]P +M86Y^3`C^```H`````$DH```!`@``````(``````````````````````````` +M`````````````````````````.X0```!`````````````````````````!$` +M``````")3%I/``T*&@H0,"!@"4`!!0,```$``(&T4("O>``````+=&5S=%]L +M>F]P86]^30C_```H`````$DH```!`@``````(``````````````````````` +M`````````````````````````````.X0```!```````````````````````` +M`!$```````")3%I/``T*&@H0,"!@"4`!!0,```$``(&T4("O>``````+=&5S +M=%]L>F]P87!^3@D````H`````$DH```!`@``````(``````````````````` +M`````````````````````````````````.X0```!```````````````````` +M`````!$```````")3%I/``T*&@H0,"!@"4`!!0,```$``(&T4("O>``````+ +M=&5S=%]L>F]P87%^3PD!```H`````$DH```!`@``````(``````````````` +M`````````````````````````````````````.X0```!```````````````` +M`````````!$```````")3%I/``T*&@H0,"!@"4`!!0,```$``(&T4("O>``` +M```+=&5S=%]L>F]P87)^4`D"```H`````$DH```!`@``````(``````````` +M`````````````````````````````````````````.X0```!```````````` +M`````````````!$```````")3%I/``T*&@H0,"!@"4`!!0,```$``(&T4("O +M>``````+=&5S=%]L>F]P87-^40D#```H`````$DH```!`@``````(``````` +M`````````````````````````````````````````````.X0```!```````` +M`````````````````!$```````")3%I/``T*&@H0,"!@"4`!!0,```$``(&T +M4("O>``````+=&5S=%]L>F]P871^4@D$```H`````$DH```!`@``````(``` +M`````````````````````````````````````````````````.X0```!```` +M`````````````````````!$```````")3%I/``T*&@H0,"!@"4`!!0,```$` +M`(&T4("O>``````+=&5S=%]L>F]P875^4PD%```H`````$DH```!`@`````` +M(````````````````````````````````````````````````````.X0```! +M`````````````````````````!$```````")3%I/``T*&@H0,"!@"4`!!0,` +M``$``(&T4("O>``````+=&5S=%]L>F]P879^5`D&```H`````$DH```!`@`` +M````(````````````````````````````````````````````````````.X0 +M```!`````````````````````````!$```````")3%I/``T*&@H0,"!@"4`! +M!0,```$``(&T4("O>``````+=&5S=%]L>F]P87=^50D'```H`````$DH```! +M`@``````(``````````````````````````````````````````````````` +M`.X0```!`````````````````````````!$```````")3%I/``T*&@H0,"!@ +M"4`!!0,```$``(&T4("O>``````+=&5S=%]L>F]P87A^5@D(```H`````$DH +M```!`@``````(``````````````````````````````````````````````` +M`````.X0```!`````````````````````````!$```````")3%I/``T*&@H0 +M,"!@"4`!!0,```$``(&T4("O>``````+=&5S=%]L>F]P87E^5PD)```H```` +M`$DH```!`@``````(``````````````````````````````````````````` +M`````````.X0```!`````````````````````````!$```````")3%I/``T* +M&@H0,"!@"4`!!0,```$``(&T4("O>``````+=&5S=%]L>F]P87I^6`D*```F +M`````+OSXAG6`@``````(``````````````````````````````````````` +M]Q```F9I;&4S(#[\=PLP,#`V-C0@`#`P,3/1A2\n" +"IHU\"0%9=*G4JUJM6K6+-JWO8,.*'4NVK-FS:-.J7\n" +"Received: from libarchive (localhost [127.0.0.1])\n" +" by libarchive (8.14.2/8.14.2) with ESMTP id m5233UT1006448\n" +" for ; Mon, 2 Jun 2008 03:03:31 GMT\n" +" (envelope-from uudecode@libarchive)\n" +"Received: (from uudecode@localhost)\n" +" by libarchive (8.14.2/8.14.2/Submit) id m5233U3e006406\n" +" for uudecode; Mon, 2 Jun 2008 03:03:30 GMT\n" +" (envelope-from root)\n" +"Date: Mon, 2 Jun 2008 03:03:30 GMT\n" +"From: Libarchive Test \n" +"Message-Id: <200806020303.m5233U3e006406@libarchive>\n" +"To: uudecode@libarchive\n" +"Subject: Libarchive uudecode test\n" +"\n" +"* Redistribution and use in source and binary forms, with or without\n" +"* modification, are permitted provided that the following conditions\n" +"* are met:\n" +"\n" +"01234567890abcdeghijklmnopqrstuvwxyz\n" +"01234567890ABCEFGHIJKLMNOPQRSTUVWXYZ\n" +"\n" +}; + +static void +test_read_uu_sub(const char *uudata, size_t uusize, int no_nl) +{ + struct archive_entry *ae; + struct archive *a; + char *buff; + char extradata_no_nl[sizeof(extradata)]; + const char *extradata_ptr; + int extra; + size_t size; + + if (no_nl) { + /* Remove '\n' from extra data to make a very long line. */ + char *p; + memcpy(extradata_no_nl, extradata, sizeof(extradata)); + extradata_ptr = extradata_no_nl; + for (p = extradata_no_nl; + *p && (p = strchr(p, '\n')) != NULL; p++) + *p = ' ';/* Replace '\n' with ' ' a space character. */ + } else + extradata_ptr = extradata; + + assert(NULL != (buff = malloc(uusize + 1024 * 1024))); + if (buff == NULL) + return; + for (extra = 0; extra <= 64; extra = extra==0?1:extra*2) { + char *p = buff; + + size = extra * 1024; + /* Add extra text size of which is from 1K bytes to + * 64Kbytes before uuencoded data. */ + while (size) { + if (size > sizeof(extradata)-1) { + memcpy(p, extradata_ptr, sizeof(extradata)-1); + p += sizeof(extradata)-1; + size -= sizeof(extradata)-1; + } else { + memcpy(p, extradata_ptr, size-1); + p += size-1; + *p++ = '\n';/* the last of extra text must have + * '\n' character. */ + break; + } + } + memcpy(p, uudata, uusize); + size = extra * 1024 + uusize; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + read_open_memory(a, buff, size, 2)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae)); + failure("archive_filter_name(a, 0)=\"%s\"" + "extra %d, NL %d", + archive_filter_name(a, 0), extra, !no_nl); + assertEqualInt(archive_filter_code(a, 0), + ARCHIVE_FILTER_COMPRESS); + failure("archive_format_name(a)=\"%s\"" + "extra %d, NL %d", + archive_format_name(a), extra, !no_nl); + assertEqualInt(archive_format(a), + ARCHIVE_FORMAT_TAR_USTAR); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + } + + /* UUdecode bidder shouldn't scan too much data; make sure it + * fails if we put 512k of data before the start. */ + size = 512 * 1024; + for (extra = 0; (size_t)extra < size; ++extra) + buff[extra + 1024] = buff[extra]; + buff[size - 1] = '\n'; + memcpy(buff + size, uudata, uusize); + size += uusize; + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_FATAL, + read_open_memory(a, buff, size, 2)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + free(buff); +} + +DEFINE_TEST(test_read_filter_uudecode) +{ + /* Read the traditional uuencoded data. */ + test_read_uu_sub(archive, sizeof(archive)-1, 0); + /* Read the traditional uuencoded data with very long line extra + * data in front of it. */ + test_read_uu_sub(archive, sizeof(archive)-1, 1); +} + +DEFINE_TEST(test_read_filter_uudecode_base64) +{ + /* Read the Base64 uuencoded data. */ + test_read_uu_sub(archive64, sizeof(archive64)-1, 0); + /* Read the Base64 uuencoded data with very long line extra data + * in front of it. */ + test_read_uu_sub(archive64, sizeof(archive64)-1, 1); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip.c new file mode 100644 index 0000000..3c72595 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip.c @@ -0,0 +1,838 @@ +/*- + * Copyright (c) 2011 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD"); + +#if defined(_WIN32) && !defined(__CYGWIN__) +#define close _close +#define open _open +#endif + +/* + * Extract a non-encoded file. + * The header of the 7z archive files is not encoded. + */ +static void +test_copy(int use_open_fd) +{ + const char *refname = "test_read_format_7zip_copy.7z"; + struct archive_entry *ae; + struct archive *a; + char buff[128]; + int fd = -1; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (use_open_fd) { + fd = open(refname, O_RDONLY | O_BINARY); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_fd(a, fd, 10240)); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + } + + /* Verify regular file1. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae)); + assertEqualString("file1", archive_entry_pathname(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(60, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assert(archive_read_has_encrypted_entries(a) > ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualInt(60, archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, " ", 4); + + assertEqualInt(1, archive_file_count(a)); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + if (fd != -1) + close(fd); +} + +/* + * An archive file has no entry. + */ +static void +test_empty_archive(void) +{ + const char *refname = "test_read_format_7zip_empty_archive.7z"; + struct archive_entry *ae; + struct archive *a; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + assertEqualInt(0, archive_file_count(a)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +/* + * An archive file has one empty file. It means there is no content + * in the archive file except for a header. + */ +static void +test_empty_file(void) +{ + const char *refname = "test_read_format_7zip_empty_file.7z"; + struct archive_entry *ae; + struct archive *a; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular empty. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("empty", archive_entry_pathname(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + assertEqualInt(1, archive_file_count(a)); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +/* + * Extract an encoded file. + * The header of the 7z archive files is not encoded. + */ +static void +test_plain_header(const char *refname) +{ + struct archive_entry *ae; + struct archive *a; + char buff[128]; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file1. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("file1", archive_entry_pathname(ae)); + assertEqualInt(1322058763, archive_entry_mtime(ae)); + assertEqualInt(2844, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertEqualInt(sizeof(buff), archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, "The libarchive distribution ", 28); + + assertEqualInt(1, archive_file_count(a)); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +/* + * Extract multi files. + * The header of the 7z archive files is encoded with LZMA. + */ +static void +test_extract_all_files(const char *refname) +{ + struct archive_entry *ae; + struct archive *a; + char buff[128]; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file1. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("dir1/file1", archive_entry_pathname(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(13, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertEqualInt(13, archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, "aaaaaaaaaaaa\n", 13); + + /* Verify regular file2. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("file2", archive_entry_pathname(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(26, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertEqualInt(26, archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, "aaaaaaaaaaaa\nbbbbbbbbbbbb\n", 26); + + /* Verify regular file3. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("file3", archive_entry_pathname(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(39, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertEqualInt(39, archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, "aaaaaaaaaaaa\nbbbbbbbbbbbb\ncccccccccccc\n", 39); + + /* Verify regular file4. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("file4", archive_entry_pathname(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(52, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertEqualInt(52, archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, + "aaaaaaaaaaaa\nbbbbbbbbbbbb\ncccccccccccc\ndddddddddddd\n", 52); + + /* Verify directory dir1. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFDIR | 0755), archive_entry_mode(ae)); + assertEqualString("dir1/", archive_entry_pathname(ae)); + assertEqualInt(2764801, archive_entry_mtime(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + assertEqualInt(5, archive_file_count(a)); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +/* + * Extract last file. + * The header of the 7z archive files is encoded with LZMA. + */ +static void +test_extract_last_file(const char *refname) +{ + struct archive_entry *ae; + struct archive *a; + char buff[128]; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file1. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("dir1/file1", archive_entry_pathname(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(13, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Verify regular file2. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("file2", archive_entry_pathname(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(26, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Verify regular file3. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("file3", archive_entry_pathname(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(39, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Verify regular file4. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("file4", archive_entry_pathname(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(52, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertEqualInt(52, archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, + "aaaaaaaaaaaa\nbbbbbbbbbbbb\ncccccccccccc\ndddddddddddd\n", 52); + + /* Verify directory dir1. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFDIR | 0755), archive_entry_mode(ae)); + assertEqualString("dir1/", archive_entry_pathname(ae)); + assertEqualInt(2764801, archive_entry_mtime(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + assertEqualInt(5, archive_file_count(a)); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +/* + * Extract a mixed archive file which has both LZMA and LZMA2 encoded files. + * LZMA: file1, file2, file3, file4 + * LZMA2: zfile1, zfile2, zfile3, zfile4 + */ +static void +test_extract_all_files2(const char *refname) +{ + struct archive_entry *ae; + struct archive *a; + char buff[128]; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file1. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("dir1/file1", archive_entry_pathname(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(13, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertEqualInt(13, archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, "aaaaaaaaaaaa\n", 13); + + /* Verify regular file2. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("file2", archive_entry_pathname(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(26, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertEqualInt(26, archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, "aaaaaaaaaaaa\nbbbbbbbbbbbb\n", 26); + + /* Verify regular file3. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("file3", archive_entry_pathname(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(39, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertEqualInt(39, archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, "aaaaaaaaaaaa\nbbbbbbbbbbbb\ncccccccccccc\n", 39); + + /* Verify regular file4. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("file4", archive_entry_pathname(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(52, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertEqualInt(52, archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, + "aaaaaaaaaaaa\nbbbbbbbbbbbb\ncccccccccccc\ndddddddddddd\n", 52); + + /* Verify regular zfile1. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("dir1/zfile1", archive_entry_pathname(ae)); + assertEqualInt(5184001, archive_entry_mtime(ae)); + assertEqualInt(13, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertEqualInt(13, archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, "aaaaaaaaaaaa\n", 13); + + /* Verify regular zfile2. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("zfile2", archive_entry_pathname(ae)); + assertEqualInt(5184001, archive_entry_mtime(ae)); + assertEqualInt(26, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertEqualInt(26, archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, "aaaaaaaaaaaa\nbbbbbbbbbbbb\n", 26); + + /* Verify regular zfile3. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("zfile3", archive_entry_pathname(ae)); + assertEqualInt(5184001, archive_entry_mtime(ae)); + assertEqualInt(39, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertEqualInt(39, archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, "aaaaaaaaaaaa\nbbbbbbbbbbbb\ncccccccccccc\n", 39); + + /* Verify regular zfile4. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("zfile4", archive_entry_pathname(ae)); + assertEqualInt(5184001, archive_entry_mtime(ae)); + assertEqualInt(52, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertEqualInt(52, archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, + "aaaaaaaaaaaa\nbbbbbbbbbbbb\ncccccccccccc\ndddddddddddd\n", 52); + + /* Verify directory dir1. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFDIR | 0755), archive_entry_mode(ae)); + assertEqualString("dir1/", archive_entry_pathname(ae)); + assertEqualInt(2764801, archive_entry_mtime(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + assertEqualInt(9, archive_file_count(a)); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +/* + * Extract a file compressed with DELTA + LZMA[12]. + */ +static void +test_delta_lzma(const char *refname) +{ + struct archive_entry *ae; + struct archive *a; + size_t remaining; + ssize_t bytes; + char buff[1024]; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file1. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("file1", archive_entry_pathname(ae)); + assertEqualInt(172802, archive_entry_mtime(ae)); + assertEqualInt(27627, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + remaining = (size_t)archive_entry_size(ae); + while (remaining) { + if (remaining < sizeof(buff)) + assertEqualInt(remaining, + bytes = archive_read_data(a, buff, sizeof(buff))); + else + assertEqualInt(sizeof(buff), + bytes = archive_read_data(a, buff, sizeof(buff))); + if (bytes > 0) + remaining -= bytes; + else + break; + } + assertEqualInt(0, remaining); + + assertEqualInt(1, archive_file_count(a)); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +/* + * Extract a file compressed with BCJ + LZMA2. + */ +static void +test_bcj(const char *refname) +{ + struct archive_entry *ae; + struct archive *a; + size_t remaining; + ssize_t bytes; + char buff[1024]; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular x86exe. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0444), archive_entry_mode(ae) & ~0111); + assertEqualString("x86exe", archive_entry_pathname(ae)); + assertEqualInt(172802, archive_entry_mtime(ae)); + assertEqualInt(27328, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + remaining = (size_t)archive_entry_size(ae); + while (remaining) { + if (remaining < sizeof(buff)) + assertEqualInt(remaining, + bytes = archive_read_data(a, buff, sizeof(buff))); + else + assertEqualInt(sizeof(buff), + bytes = archive_read_data(a, buff, sizeof(buff))); + if (bytes > 0) + remaining -= bytes; + else + break; + } + assertEqualInt(0, remaining); + + assertEqualInt(1, archive_file_count(a)); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +/* + * Extract a file compressed with PPMd. + */ +static void +test_ppmd(void) +{ + const char *refname = "test_read_format_7zip_ppmd.7z"; + struct archive_entry *ae; + struct archive *a; + size_t remaining; + ssize_t bytes; + char buff[1024]; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file1. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae)); + assertEqualString("ppmd_test.txt", archive_entry_pathname(ae)); + assertEqualInt(1322464589, archive_entry_mtime(ae)); + assertEqualInt(102400, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + remaining = (size_t)archive_entry_size(ae); + while (remaining) { + if (remaining < sizeof(buff)) + assertEqualInt(remaining, + bytes = archive_read_data(a, buff, sizeof(buff))); + else + assertEqualInt(sizeof(buff), + bytes = archive_read_data(a, buff, sizeof(buff))); + if (bytes > 0) + remaining -= bytes; + else + break; + } + assertEqualInt(0, remaining); + + assertEqualInt(1, archive_file_count(a)); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +static void +test_symname(void) +{ + const char *refname = "test_read_format_7zip_symbolic_name.7z"; + struct archive_entry *ae; + struct archive *a; + char buff[128]; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file1. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("file1", archive_entry_pathname(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(32, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertEqualInt(32, archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, "hellohellohello\nhellohellohello\n", 32); + + /* Verify symbolic-link symlinkfile. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFLNK | 0755), archive_entry_mode(ae)); + assertEqualString("symlinkfile", archive_entry_pathname(ae)); + assertEqualString("file1", archive_entry_symlink(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + assertEqualInt(2, archive_file_count(a)); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + +DEFINE_TEST(test_read_format_7zip) +{ + struct archive *a; + + assert((a = archive_read_new()) != NULL); + + /* Extracting with liblzma */ + if (ARCHIVE_OK != archive_read_support_filter_xz(a)) { + skipping("7zip:lzma decoding is not supported on this " + "platform"); + } else { + test_symname(); + test_extract_all_files("test_read_format_7zip_copy_2.7z"); + test_extract_last_file("test_read_format_7zip_copy_2.7z"); + test_extract_all_files2("test_read_format_7zip_lzma1_lzma2.7z"); + test_bcj("test_read_format_7zip_bcj2_copy_lzma.7z"); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_7zip_bzip2) +{ + struct archive *a; + + assert((a = archive_read_new()) != NULL); + + /* Extracting with libbzip2 */ + if (ARCHIVE_OK != archive_read_support_filter_bzip2(a)) { + skipping("7zip:bzip2 decoding is not supported on this platform"); + } else { + test_plain_header("test_read_format_7zip_bzip2.7z"); + test_bcj("test_read_format_7zip_bcj_bzip2.7z"); + test_bcj("test_read_format_7zip_bcj2_bzip2.7z"); + } + + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_7zip_from_fd) +{ + test_copy(1);/* read a 7zip file from a file descriptor. */ +} + +DEFINE_TEST(test_read_format_7zip_copy) +{ + test_copy(0); + test_bcj("test_read_format_7zip_bcj_copy.7z"); + test_bcj("test_read_format_7zip_bcj2_copy_1.7z"); + test_bcj("test_read_format_7zip_bcj2_copy_2.7z"); +} + +DEFINE_TEST(test_read_format_7zip_deflate) +{ + struct archive *a; + + assert((a = archive_read_new()) != NULL); + + /* Extracting with libz */ + if (ARCHIVE_OK != archive_read_support_filter_gzip(a)) { + skipping( + "7zip:deflate decoding is not supported on this platform"); + } else { + test_plain_header("test_read_format_7zip_deflate.7z"); + test_bcj("test_read_format_7zip_bcj_deflate.7z"); + test_bcj("test_read_format_7zip_bcj2_deflate.7z"); + } + + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_7zip_empty) +{ + test_empty_archive(); + test_empty_file(); +} + +DEFINE_TEST(test_read_format_7zip_lzma1) +{ + struct archive *a; + + assert((a = archive_read_new()) != NULL); + + /* Extracting with liblzma */ + if (ARCHIVE_OK != archive_read_support_filter_xz(a)) { + skipping("7zip:lzma decoding is not supported on this " + "platform"); + } else { + test_plain_header("test_read_format_7zip_lzma1.7z"); + test_extract_all_files("test_read_format_7zip_lzma1_2.7z"); + test_extract_last_file("test_read_format_7zip_lzma1_2.7z"); + test_bcj("test_read_format_7zip_bcj_lzma1.7z"); + test_bcj("test_read_format_7zip_bcj2_lzma1_1.7z"); + test_bcj("test_read_format_7zip_bcj2_lzma1_2.7z"); + test_delta_lzma("test_read_format_7zip_delta_lzma1.7z"); + test_delta_lzma("test_read_format_7zip_delta4_lzma1.7z"); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_7zip_lzma2) +{ + struct archive *a; + + assert((a = archive_read_new()) != NULL); + + /* Extracting with liblzma */ + if (ARCHIVE_OK != archive_read_support_filter_xz(a)) { + skipping("7zip:lzma decoding is not supported on this " + "platform"); + } else { + test_plain_header("test_read_format_7zip_lzma2.7z"); + test_bcj("test_read_format_7zip_bcj_lzma2.7z"); + test_bcj("test_read_format_7zip_bcj2_lzma2_1.7z"); + test_bcj("test_read_format_7zip_bcj2_lzma2_2.7z"); + test_delta_lzma("test_read_format_7zip_delta_lzma2.7z"); + test_delta_lzma("test_read_format_7zip_delta4_lzma2.7z"); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_7zip_ppmd) +{ + test_ppmd(); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_bzip2.7z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_bzip2.7z.uu new file mode 100644 index 0000000..274668f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_bzip2.7z.uu @@ -0,0 +1,319 @@ +begin 644 test_read_format_7zip_bcj2_bzip2.7z +M-WJ\KR<<``,YXL&G`S<```````!>`````````$C?FIA"6F@Y,4%9)E-9C&3\ +MZP`=+'___________________________________________?_@)[]WN.@Y +MN[WWGA!"^MXV3U\]][O5\7FH?=.[UZ1!97.O<[>5=O;>*5N]KS+:A6>5[=[2 +MUTM;ELU16C6NV5@[9M>>6&-O<]NNG4S&[9ZQZ#>'J];=O;IC6EZ<[WN*7N]E +MEBW``T)`$3!&)E-H!,GJ,F`T!-HC)HPF)E,-!II-H1IZ!I&U4_4V%/*>)M*> +MGD*F]4;U&TI_H2>J'B1^E/TH]3]*/4_2/2C]%,GJ>F#5,@TTS2>H]3:ALHVI +MY3#0A-``1D$R;$C3:B93TE/P1ZI'E/TGJFV(4T?E/0-2?I(T]1M1^E'ZHVD/ +MQ4>FIH?JFCU&@#0T#0,U#3TRCU#U-I`#U`/2#U`'J8`````TT($$T$TFU,DT +MU/-1ZD]#3:DTV31Z$GI/2>H]3U-!H]3!J:&C$'HAD-#0-`#(T:!D!H&C0-`` +M]0``'I`&@`>4:`#0`)-*)":30$8F5/:IZ;4F]*>4_5/RGJ1ZGJ'I#)Z-1H]( +MV2/U0/*>H&@TT::/:H::;4](T/2#U!H/4:-`&@```!H9-`T`:``P```!34J` +M``-`,@>2``T```#(8`````````````````````````````D20C0":`3`)IZF +MFF29B)J>T",U4]J3T]32?JGZIZ'JGM#*1^J?JC\A-IIIJ1X$FU/4T?JAZ>J# +MU'M4T`T]3U/2>IZAH-/34-`-!D`#1Z(>DT/4&@:!A\XT_D?G;6M7LI5'/D_4 +M5!:+!L^"-EG&JTI?Y_`@OP*3XUF9P/L_=C'##4R`K*4N_E1B"`X528(`/PN` +M@R0XU*JI0#Z-Y')-CTZL1%CY)PX*E&,$6UI40B2D;I3$Y*DO2\FOB_$Y2*SX="VT,"D,9_WM +M-'M[6YU>^F`]VSZSUF/J#W4%B:B7N#?2E\,R(7K:8GD0E`$"$LR``!O4#'LS +M25_1^UY.=Z7]'K=ZX'-S>9Y%NWX]TXLCZ5[>OA9DSPI]HRGB-"%0NR) +MU0T`O6]%BM8?-5%6^9>%D&3UZ0L8&V_-LV&/19<`40*KMT!$)9O"6:QN+RM@ +MPR2W79W2PJ2!F9+6T-I8AN*]1`:A8.8?;O.UX<;=_L47Z._RLORW:W6#*?\K +M@X7X>/Y7F^A`_C\#PMI[;ZN7F.5&?;N+OG`;S +M+II-`+?<,(9\&#N>1JVL1NQ(;35U-1*E"@*05-!T=&BD5*$D`XB)[/DAQ6B' +MA@S](\SG;K5^QYJ[0$C,%>VTG&)*PU=#"@QU)Q>8C(8B>?8!_QL(EYM"E)U& +MW +M8US'PE8L55W,J8P&T+&:`]&MGT:^B^]FQQP:F?T4C6-4FC8:#1#4A&`LP#,C +M!B`8#`8`(!@(`$```:I'9*NUU6LM+"@T*RWKML&==V0E3J@[]4QV=P]:FI\K +MK;@S$-M9JVD<3-V*]QQ8Y.ALY`!M7#2ZYH`&Q(4S/>-*&!^X&HH%R/!@U6C5 +M:0BJ-+;-%ASWM.Z[FAR^N\&<[B7.>7U5,7E;"3?,.PZ5DF6"CQJ&G$L,,QBS +MWG2S+)HXMHGTJ*>0P-'QJ3F)X7FA=B?'?CV3LD/&(;8]FDZAGB.5"O,.2TD7[/MVC-S(.U:U +M?*@/=-<9F>UR6&V>VMPCRVLWVD!V?)YDLL:W3W;J]S"2Q,?G2`*!@V)ML$-I +MLQ6E2S/:U&EC-(R?+@6`Q%N:"MRH*_+@K4$=A7@+K2V;6[HVGLYEHN&N4S,: +MRVN7B]U)=E:UY`)?):2/&??L!>/V4>2^ZL<[T.;9[NIGOES=Y+QFEX31U9X2 +M2Z#)-YD(8`!JJJI`/,]*SI,/)^9L`/`O0[+Q^V:)NVZIU]RS$)TM6<@YM0U- +M25@L,.,65,,@M2UA`\.A)B1D('-2$XC('P#(!X&_>$Q.2@92L]_5`4WD^*&L +MB]Y6BRF=NTO_C1@!":!B,AKN&!A$YQI'+8+\HXO'^S7HBV<2>RZY^Q]VV;4@ +MVA0*4M*"9'6QGKE[AZS/YT2C:?QY=C3[:>CT+-1JY@P"PVM!B7_([[9Z'452 +M=%+::RJA<=BVKO18*&Q&Z#7.O +MT)C[7:8J=R)4\J%FFC;'K'ZJ7ZXWHK',?BL!.Q)')$()#5"D"G&XM[>UU@7F +MY\LS")6>94M4!@N\PL!O;DE)I[V%?)BV[$&XXT(),0BADGMDJ"(QAT[.`(:( +M&688%MH*U)UC)$ZRPRPRR'`2#O!Y7`'138,`VL`.$T`CD,4PUY95A'LNY^DE +M/4^X(DA*VP%7:5N71D0Q)8+0D$TX0JX=10>__&[._&Y@]#Y!`@_]FSPLK+QY +M1CSY/I/;\)\SI%0F&H!RR[!?_I]4EZWSP!,!#-P$,41Y0F(:BW@R-RKDL454 +M/@>G05AJ?KH`.23HJ"#Y=84,/16+ +MUU<"8>`/63>L&6?)H_S;;JG?)]^]J7X0%?(ZZ%Z"<>OB&;"CG?'"+O"C?2I0 +M(%['O../Z'B(%5$;6GF8Q14C'H,5W'G*N"[FBX=Q#X\,H7]V#3J*HN=+9>'I +M$<."(H*1*A)`L9>G@BK,A"Y?]-25DGW357*Q0)V0Q/]<3>M?>LI&2`9,!G8# +M$000$NL55]A]_]S_VUYJ^"]]C$#LQL*V(L"("L,@!?&`*([8QE7R$1V>?"1, +MPXK7`9_CI=&2K*N-&MVE=!\.ARBA]7S-3;VD@V#!>(\QB[AHS\B`T6>[XYLJSZ9$ +MZO,.*UA/>N226=,IW:3T7D,AU3-"U3F0&+%?`=7YSB$TVH&["/!O]7-[E]I[ +M[_KY"^Q]KK%@@ABRJ*BZT=>?Z/]],:=U=>2TN6B*Q9C!C#4J5*N"("&OV9HE +M5B1/,E6E]M(#'J`!`D']7'[2Y>^-\?X=@NJ2YD5>#EB^!VPA*]>>VVVW+H)V +M+2L/2E*4O65-C'ZZ4I2,DC7=E=2]U====>FR[ZWS52E*4I<)8;;?4O&()!() +M%%%55551555555554DDDDE:ZZZ[+)WKZZ>W);IK;;;;;TDJPD6"H8<,T4@I% +M@<7%IP,8+LU*.X5MK3A-(3`$SK&!@-Z +M"HE%6JF,JD!,56KEFS9LT&'1::UK:W*+80(\<:BG0+5*C%(%&$-.W/++SG6! +M08I[5:YR5*-CC:;UZ]>IO7CO-:UM@?QZ!I^G0@.M(P.`0(@-((R`4J`@`(0& +M#=ILEW5%^41O=*R#IWRUJWJZKIMIT.[E)$`[5\H=Y?SV27^=2P%-[;>'S,8) +M#SXA-W\3R)YS\*RS\A@B(A4?W;:S6A[GF](7B!V[Z$AO)@4 +M.`]^^8XIJZS6"#(H`LD-2?]Z60Q4@1.Q#320C@X&IV`(_HG"U-"T6JJ:.DU" +M:3UI.0E\%HU[<`4M5&`3H:#SV@2+!2U""<#?05?OI59O*`ZUR5*!,)V)!M&0 +MT!PVA0\ZPG,9"90\ZD_Y5$3KF'3)-B=.ZTX:<&#)#?P0PIF%)5$#[>ETS6`N +M^+7/%;VB0+&3J[+H@Z@Q<0*@;MJSRR25]!:[=;C'46%8"P@+P&!+$W&<]PX8 +M%&'P_[/5]GGQ/H+=1X7.?BV!N,./BF&3#(3C(&(HT'>UUI=]I;K[K(,]##1> +MXYWB=+>7!61B:]++O[ZQN]XOF$&NH6.XQ:*!.3,>X0*)=CY(7DMENL\@LHZ" +M=`0.J)>1]]^*D<8\08I`-6PIR')MXG1WLNP%/2*E(/1I`EI+TCY8XZB"&@0@ +M:F`8U([$PM_)QMC`("U]EZPUEB:TA:PQ3U++0-EOMCT7MD.;U&*28VHV<%"` +MZD,?E5LC!!IHYNIE5#^``SO[-M0#&W0(?BB*BQ0=7OEW>\>&E3?8"8(QWUJ)+R +M$0V:U."!JX&'79,+<8PG#>0X:\3=LX&RU-J"U@9?/,QPD/&L2O#W-KI_]>):>'XL7>_L. +M?F!^3P*<0$HN_7\T+TU"IMMU5/^DRKMV_"?LZ\33(#0/U/%0#1F`@PG;B]%S +M;%B#)/3,8&3=;<=%T5>7Z6^,_0A:/U'D?-?-@GR=X0*NW +M:<>#SCL6UZ!Z#=V/:J\J\U^7+)KWB\9T#ZA]C4ZDJJPGC6H8C#:S&##"@27` +M?*HM9F>GQ]CE;ZVJJMM!Q&$G0&\G?\#R<9)=I5CVNK`/>YU0>'-P2[\S/R<.`@,>[JJ`R6D@ +MH(-'3'<\OB*;I,A0EMS;D[QJVK7)TQQD]!,SARF637'\7#N``IMQQ=@S6%R( +M4ET%\1UV&JTV!\>5'UV6BOX8'IZ_G^^`UT5)'\0&[RM^1D!&3&0G3Y._X@`5 +M'J)OU>9YC-V_U;-[CS$'VMG59;7(`60`"Z\?3#*;OLB*YH::BKPYBK6XMF-* +MH*,^X].7+M6J[5)P/2-%EN3:^/A=2I4\$J)DC0$!WC0;YI18*9A +M2FY+D2TI=,RT)4C#`"@::5#3-+:F&"L01*R$F4M*JPH1O"-B"03W& +M>/:]4`,&J$(BX2O)\5#")C?71\M4.VTJYTGT%*<89:6<6LC!C(\Z&QO]QJ%T +M,C:>[8O*65R_>-+YW/EVFM8,/:%?T?A18E"]$QB!YF8'JGL8!DC!H`'R2P`L +MI1X:Y*)DP8/14]V#!9K7/:Q(SI6LJXH0NQ::7;BP0(1E`4(O3([JK +MM-SD<^KN==<_"^('7[S"+F_.[E"P3`QMK8C@624+RA36F0W!`>*(HL%D!2)Y +M1A1T)!!0K,.X$>=]7#T'TS`GH@WS0AQXO_?V7.?`_R^X'7QEHM"P%M-_? +MBJ6ZK2-'5)11,8X&Y8VD9AF9@!(S)/<5*X\7(O9-Q%A%>OP0.,6N0W2UJ9!) +M)2:ONK\0Z9%2`$D$4O?[Z*(S\4OUIO9>8LO4_$Y#T2R%CN]=HWYXS3)T4U3P +M<<77(8)F?:C$*(IPS7Q&%61L``Z!VC:''=\<-!J['9XWD"!P2\B,@7%*!"## +MI?\*E4_XD]>,N.*VZOIZ]3=H]Q!(='@52_8Y53L/R?Z]CRT^Q]B++B8.^L^# +M.C3ZURGNUXWM;+"]=$\@.LRCH.-I)\%M2,F/?-2NN$5Y[^[#6MY<#GX.`>%3[ +MP>#!8P$"8)8?6A8(DVA@>!2$'L4!K$7MM;5JN.W[FW^*Z;C;"BX0BT](!Z0& +M+W;J&[WT;WFN!WUYW?Z'"XFYID<#VAHFZ^G.8(LK>X6]JZ=0R*CQ-89=!#K`_ +MOS"AL]?J=)@QR#D@TU)KLY9]@L9;!(,3:T$T +M"_E:;3?3S*]K-PRTA(O6<&IS\<1J"?7<.S.&\!&110!,V8RZ9DL?Z-RHA]F> +M0E?#YUVL!^ZN/SSD*FI9P\E/#\F!R9)(:0:63*_*4?0"*?;^L\ +MTJ=RU]@X^KCOHIJ39H>]\[*`)EL7?ZV$=;#@.. +M&R$<_&SK9P>]0([)53>*K,%03`X(JUS:<+0,>-JUHU2!4"I5&AOK#Q>%@ +MI#KV"Y]&8$IXNJ3V;=QMA>P%&5P"62MT=&CZI[G4U=6$@;3>-ZE>V'-X>])> +M9_<91AH_8G)2L&.L@O5ER/CUECGG/T7QL20FJ)TS-'UAR^'HH.>#@`#'7:"F +M=.6'I[T5?MA^UV2JP5)!^-Q1@(GJP#H4?7[5+-E@VE&DT5ZB,C,+(J%:R +MZ!EE44(_,N2K1CR_UD!05Z+&5=LP94^L,1E"VBC'#K*7#A8P6H&JEZY3&FH% +MS-AI.[`H&VU.'2$_NOO&<'/14P,);GS0`EZI`3.Z(#0@!51"[$H-,E`"A(GM +M50A,@`SB7Q6%@AZ8"*@0K?X1!D:S&*I3ZQ'(")JLKDVT*$7PF,+^FFA9O+C/ +M=!KYET+=):(X3PGO@]0&DL%0A%ACX>[MT;EB=37T0PN**V,EX#(SG"IV78+Y +M.U:2K:-DS)GE(%0;4:SI)*P-:!7GK.8S"=5Y$32W<+`0+BF$%W4'#6"V[XO. +M0;I:=G0`-G:HU@NC$,<`3(3Z@YHV@%/N#'C#2;6LQA$0NG=6^E(TWD>0@;RH +MX/>U1@X7!JB\$8"7:*M33_/BM#SF#!36C9&HHMFW36TBH!U8IGTA?P"2L2@)2JX:S$,5$$:PH4E+!1Q9+.6 +MT#-+%:4('?(NH#C'`_-A1S"@,,1B*@D&<-4&B,*(3FQ-=F=F"6AQS`QX*:R! +MNH`)>2'ESU7L,8AQ(+S0!GFOK82!M,PWCZ_=36MUC(C!CL-@:EN6**5*LN50 +MH$G4ZBJF.RP81>O`5E,W9+%@SJIWZ`R2N!=OL!!8+$+&D)C6'6/B!T:T"'89 +M/@T,>_#]4)E>H=]0]E%[**HQGAD-G%`%WA8S.H!!,0DL-9DU\`/U!8U0T+1+ +MALQHC%GH%+`8`%A3CI!R$5!+\AM`&2$5`/-:!^RCMU^&E]$SR!=GJ5?VT?6T +M!5CZS'76D[Q8MNLU)6"I3*/MV[P5E^VF82^(+`B!H"%<;P(B2QI=ZKG?]RR& +M6H*D2P]&4MNU@8+5E1;\O8K+,SP<;"FW!R-?64M][T.[?]&T1OHZ6^2 +MA(]W;6(B>(,W79(QQ-N?N8Y(\3TRHF.;QQ"5V-Q2P0=,EB,$R'$,<-+[CP``OL=W&P +M!648U4'@&'^3>4C2B'>')^B,=8!02@)L'//:YM"?2$.1#4`V&C]B2W`M788Y +M%FVO50%0FZV4S_GF0IR#L9T_37B_,=VITXX;,?6$=G*CKF-"8J +MFO91TV`[0:;8,0BN'/1S.M+0*U?B<"^FK4#K]_SET^RL%+TM*Z(6IHL^]M3' +MI,W]A(9T)[E!8,S_31!5Z@3\0#CWAF@*"'L453^4V4C@B;U'SK +M2+YE/>_JB0BVD`^N3!/?N?>-S+;2RZG(X3H(VK,">\&U+WUR)W#G"E2_$W." +MT:"=CH&0,AK%FG$9K!8#-7<4W9%,3&EZ-25@?8.^[:U13[MT.O!OV>+CV*.-Z1D3\ +M.PB_J7I')8N7)RFO`6W;P4=5J152$\3S?(SB9<# +M2KU3$GA%,6-RE4P\]+BX;@;Z=\Q)-0R*)7MK:(\)O0U/B*-B&^?.M(3PT:1L +MQ2=W9"A4@J64KJ?]:S'""8%0*+;:FJ$0XV;Q#`P+$*(AD4+=!T^;QTG"3UM3N[`83QCJ'6J/-Z +MG6RC@"?O5APV/,XFL:-X%9*&92-@U90PZ8L*E8;_8%H.AF<$*""#TG%20V#V +M1AXU+#]O8[(]-MJ8["D0[\I56^\L%ZM$WI1'4HS&WDN<%*%A_6@B\T(YLP4X40Q==TJFS?U]GR)8NZ(9 +M[UY1@5[W$UZKX=Y!OGM$'@KYW10DT9D6KR/*5(,B&\?>'Y]?J8!B/F320HN? +MA+YYBM/2D((GELG.=F['LXU]6I +M"%,`D,UH-^F!`7-3GVX38MW%[^1GO8[VS4_L2%Z\?G4#2),`R,C&S&`^)0(" +M:^A&#K<+%1'42,BE,93>TN9R96LMC,9Z:>_&\MOB`W'2)O0R^!D@(2`'E6G; +MHG1[%'\U:ZM&F]V:E\$7N%`&%?PMC`KD4&UPJ>:74@4?=I$ARF'3:;2;GSK? +MH[]*`R&?EM59;Y6VG'N*_P"[3'K1![FXH37[,]EKM\SDT<#5>H>O]TF +M9GC48ABYD0%&ICU(RX(P@-5ZW+SMB:?FM_Q3KB!/MN`OJB#U^5C@#D&X7*J*)\!X0L-O0?;@+,WD*=$]X3JT5MA.*J(NEN.;>4CQHS; +M+C`5MUH/>OOIFB-CB/J(72T.>0?2ZW"(AXAZ'.?])P8/1TXFQNG@D54V*(![2_FKG8[ +MG^=(C8B>G9SQ(*,:N93;;!8>\5]+TX#Q;@0=JOHH#JEU?V>I]S_)D^Y5^EZ] +M/_]_M_AVK;'BP`(::B=$_/FE>RI99CQSR?F87YP$I-$LAMGWH"(D6OMD[4UR +M[^/EF9NJ+EF+;;;;;;;;;;;;;;;9))))))))))))))).7>FFFFFFFFFFFFFF +MFFT\2"67V$TTRM.]?Q&>`@$S6#A"BA.V9*KSXW\5N$+MP#K\-Z'P7<<:<;M< +M_VZQ4XP%OAA+#B"$2'B((=`#G[^+ +M#>$>O8EGUSN@P_@^WUN^OP0%@`DT"-@6/*L@N>R0/;O2>GTO?])E?$J'2H'7 +MZJEIIZOH:&_;\";;;:;=PZ6H4]^#Q_VN@Y^"<3K00\//Y;Y7UGQ4!01,Y#TE +MQQO/G6LUVJC-AM(0>ZU7Y)C+]Y9EMLR"@;=2G>Z=-N1K!T."8TS;^S1S8REP +ML>>:.#)X[7:$]6L6]?90P.].S(D.0MGAL@9CWD4"F,S^RZL+BH_I[\QM'X@* +MN0=';>!U%H<*:-1D78/ZX%"0`'5-Z.(!QP&NQFVO\-O\7WNAV<-R9F81`:U; +MB;_YL?V[&^^/G43CG]6BR[^>^/Y_=Y[YX!]_6;'+L:KC[S'K1#IS>$=!/N4" +M%4F0H6!D>(#;^]'886<(@NHG6R'^)VY[_($N+J>/,KAZ0+@`$"[/J/HM]UYT +M!!@&1F9F#!F5Q$U;*OJ_LN$%1=C3=/FT[(PV(ER_1>>C>*!0_/S*`,M2Y(@( +MAV\'9XQH,S-NV%;C^L1%"$.<^G/H+^JX($`/;N:,;B2L@Q2L!<^LM:=ZD=E) +M!X;J(`/EQT&OVK$Z"\TFQ`.7]M`0*9(6JP^$P4\QB,E--?S(U;=1GB`C;\P. +MG[_Q9SS@K`7"_K,-;FQ',8QK&O1N/?>P1SO.(/O^E7X%J`K-A989?DA\J4G# +M-+BU!21&G^HE(A$==%+,^+XV[PM)H['C-48BQU-!30+IV1OE`_L8.\,+IG,R +ML\R"6&M-H7&K(FL7SNE'QQWVYS:]AY?0Q#RXAPWGU"BOF[ +M3O09*:49$@I:JIT*&FVY'2 +MU5S_U<]#O]>K2ZQQ0PBC$$^9]6S1ISUF-_)<.JF,,[#EFY>+(.EEE4IL$!9: +M?$D*1"9Q`<@85>G[%>"0:`7.\#!'S8)!)!1`B[7GI$>P0.%,I0C\]D_&U-`< +MZOZ)((>KJ2?4<'CCM7<"PT\CR,>+N412&*8@6&['M(P60['PH*,K19Q3;J^H +MZ]GK:"R6F"U]7!D@TI38(41D_1)R(A`,V4J9@]"KU3YN$Y>FP$0V#,+]'<=W +MS$"!22I]QN;HE>R&,GG>*A@D(`C($(Y2Q[M]VL$OL(0+',$]HSNE&JY=M/IW +M*[=9K1FX5K-Q?N$S!*B`&CAR$:8`0GE#+`+;!D`=&N%;!20H0@-AN];?#89O +MJK!PO&\'U<&'M#P`]0ZHZ,)C"&+!S$:RFRH?UY=&<3]7Y*%D'E#W&\\PLXOA +MHE'*2E9A8BAPH,,Q#7$56RB7A_JB=K:-5NCR?0+"&J/434,X-#[6:%ZV6(SX +M]8W..(D&3=+>,.5-=;H\'\H/J.*3IWC"X^[\GX+%;/>#7VQ`6ID"BIZ*D$<, +M\7\?RQ5ZXZ$V5`T*355F]PIC:%7@7`U-&1R@&'SJHB`WSZXXC;7L*S"CP'', +M?@(H^6X@/724C874GR\DG5-FF9V`>@HE_"%4"@J"2\>,,,PWL-.=K@P:C[5S +MYG&E?J\/[O%]3K^;9[756&/W-YK/.[>SMO`U_;\_[CBUUUUUUUUUUUUU\2RR +MRRRRRRRRRRRRRRRRSPL_F9U=F?X7*'=GU>UX0(Z,/1,P'ZH`@P0Q#C1(\W'C +MT2S"RR[+-3XDJOL];;6=K+ER[;4_4X6!V?]]?Q?AK)T`-+-J0/"2:J&@8Q@,Y=WWZTS`-F)P^3UN_5 +M5NSF.)-N&HU[O`ZI*=O<=:QQY;K6P//Q<+=CGNSIG3)1!&<\ISPT-$45#6O! +MB),9RLGRI0D;C=F^9113AUZKCB,]ET30VC&F#BQKH89!VXQHQG.>9QEU,.)X +MH\T3'`I== +M=F"\NW<*],PR!>W@+),$K#7I!DX,AC"!`69@`MY373\_Q`KG,O;4D;%[)I"Q +M+M[=!=E:[78-52DV8$?@.9-TG/W^#4PT'R7`+$1UVI41JOBM=%PCOH48# +MN](HY1Q*J89ZI9JX'W)A&QJBI&6JP+LJ!2J8E2D,Z,X7N8U$QIC#%8-9H/CK +M5(&=C87@1@H4H\S-:*RA;C%Q%<8,9 +M:#$19A,MN7!C.,+;9MJXG[=EY(YQCS.G6!`Q$FQ=!@HTO84$BC@P2A99>\Y: +M%1&Q.R+$1*D4$Z8I/2(@&DS$-)=U0(J0BH8`@ZF]W=NDRZ4WFGAM6-)DBR%8 +M61DMI?'\7&-XPPPH$0`O`7>2:E2Q>7CF\-O&@_L\;_1C:N"VIB%$:3F:%Y6- +M!+\/=;VQ.JSI1JKHQAH"32[AD%Z4C4$M*)ZA/1(710#Q)+=-34PZ724!+"/` +MW`&C$;(>P2UH?S8'3"WP=U[;31$B,`0SD`P&!N8H0Q:@AHSJHELD%$.&H5=[ +MB+R8H((G^CT/I@Y.;``T)Y$[`QP.+/4KI4:7V$9-O7I\PH9212D8`,SD/@:& +MI"&"G>6&/5^LW$'E!V#3BR09'+T38%-4I4K^");GL>+YO@M/D1H!(E5`[]-TQN/=7/U^>8W3W623;&4<$"N +MQ-6<)#M&H,G%!9<20:Q$?!!JXK>DK1JM"I]5!:_*J0^I*3=3,W1/_AQ=D%6 +M]O;RS%O;VK%=??O?`@LK.Z`TC(:#`($##(7KVY)"[5A.RLSD->$PAMBX+^;T +MP`LNPT(/F]">;SZC!EDZ.W=3#8\%/*.1'+)8A.(DD[EDAXU)#ZA#1DAY]Z3O +MD@'6)-C52;$@8C(&M?E>WQK.ZZ<^=S)-B'(9PQ8#&?+L(4E85@L4BLPU3%*" +M=?^5@P'_XWE+QZ&)$!BFO2F$J&!,+Y.PRX8QF6*4+1#%,1)'&'!(5JB1B8/= +M62%5(R,RAG&,"N,3`B3%**.*%%#Q@,@]M%\7>T89S1,.3A=5C0```$2@``!'(```4 +M&```$.@``!*X```1R```$-@``!*H```4&```$V@``!)(```3N```$J@``!08 +M```2J```%!@``!*H```4&```$K@``!*H```4&```$X@``!.(```3V```$R@` +M`!)X```98```$N@``#?````0&```$G@``!E@```1V```$N@``!)H```1>``` +M$B@``!(H```WP```$!@``!#(```32```$X@``!.(```3J```$Y@``!"(```1 +M2```$@@``$FP```0B```$#@``!"(```3F```$(@``!+(```2V```$M@``!"( +M```RT```)@```"8````36```$S@``!"(```3"```$\@``!18```46```%%@` +M`!18```46```$#@``!18```2.```$C@``!(X```Q\```$M@``!0(```0F``` +M$&@``!08```2*```$B@``!"X```2.```$+@``!(X```2.```-#```#0P```T +M,```-#```#0P```T,```-#```#0P```T,```-#```#0P```1N```$6@``!#X +M```0>```$$@``!+X```3V```$,@``!-(```0R```$T@``!#(```32```$T@` +M`!-(```32```$,@``!#(```0R```$,@``!-(```U$```-\```#A@```WP``` +M,?```%;````2B```$H@``#N````0R```$T@``#N````0R```$T@``!#(```3 +M2```$H@``!&8```2N```$H@``!08```[@```$,@``!#(```32```$T@``!(8 +M```2J```$:@``!0X```1.```$_@``!*(```0J```$H@``#9@```WP```,?`` +M`!*(```2J```$H@``#9@```U$```$H@``!*(``!6P```$H@``!*(```0R``` +M.&```!*H```42```$H@``#?````2J```$H@``#9@```V8```$J@``!*H```2 +M:```$7@``!`H```32```$_@``!*X```2:```$K@``!&H```2:```$K@``!/8 +M```3&```$U@``!)8```06```$0@``!)8```3V```$E@``!!8```0R```$T@` +M`!)8```1"```$,@``!#(```1"```$T@``!-(```0R```$T@``!/8```26``` +M$%@``!#(```32```$0@``!)8```2B```$0@``!#(```32```$]@``!)8```0 +M6```$,@``!#(```0R```$,@``!#(```32```$T@``!-(```32```%!@``!-( +M```1"```$E@``!'H```1"```$,@``!#(```32```$T@``!/8```5,```#_@` +M``_X```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^``` +M#_@```_X```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/ +M^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X +M```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^```#_@` +M``_X```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^``` +M#_@```_X```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/ +M^```#_@``!'X```5D```$?@``!9````1^```%M```!'X```78```$?@``!?P +M```1^```$?@``!B@```A1```(5L``"#]```=7@``'6H``!YQ```>4```'5`` +M`!U0```>B@``'S$``!^B```EJ0``'LT``![-```?!0``&H$``"$;```CMP`` +M)?0``!JD```=5P``&J0``!JD```<````'/$``!S^```<_@``)>```"7@```< +M5P``'%<``"2R```@R0``''```!QP```@/P``'^D``!XR```=N0``'C(``!FR +M```EJ0``)<<``"6]```DU```)1H``!HQ```=ZP``(#4``"2-```C00``(Y@` +M`")U```A\@``(:,``"B"```G=P``*`@``"=H```GP```)X```"A&```GV``` +M*"P``"A9```F@```)H```":2```H;@``)H```":````F@```)Q```"<0```F +M<@``)H```"9R```F^0``)H```":^```F^0``*8L``#$P```OOP``+#H``#"! +M```K[0``+`<``#`3```P5```,#P``"_H```P8P``*QP``"L2```K'```*?\` +M`"HF```I8P``*6,``"EC```I8P``*6,``"EC```I8P``*6,``"EC```I8P`` +M*6,``"EC```I8P``*6,``"EC```I8P``*6,``"EC```I8P``*6,``"EC```I +M8P``*6,``"EC```I8P``*6,``"EC```I8P``*6,``"EC```I8P``*6,``"EC +M```I8P``*6,``"EC```IVP``*=L``"G;```KHP``,6T``"NM```K0@``,4P` +M`"NM```KP```*ZT``"NM```KP```,Z```VF```-I@``#:8```V@0``-I@``#:8```VF```-I@` +M`%$0``!+(```3H```#ES```Y)@``.?D``#I*```[4@``.:@``#HJ```YQ``` +M.+(``#KB```ZP@``.OX``#IF```[-@``.J(``#L:```Y%0``.9<``#GH```Y +M8@``.-H``#R(```[LP``.ZH``$`\``!`*@``/^L``#_K```_N@``/X0``#]R +M```_A```/X0``#YT```^K0``/DT``#XT```^-```/+```#UP``!!5```09(` +M`$"@``!!$```11P``$4<``!$]P``1J@``$95``!#5```0U0``$-4``!(>P`` +M1_4``$@U``!)!@``21H``$CC``!(Q0``1C```$8(``!%<```17```$>P``!% +MWP``1^4``$?3``!%]```1O```$<```!&T```2,X``$(```!)I0``0?4``$>` +M``!$4P``1((``$2"``!#M```0Z<``$(N``!"(```1/<``$2U``!(1P``2(X` +M`$3)``!%N```1$8``$1U``!$=0``0L$``$-4``!#`P``1S```$-4``!"@``` +M1,D``$-,``!$]P``0U0``$-4``!#`P``0P,``$@U``!(-0``0U0``$K]``!- +MI0``3.0``$UO``!-1```3*,``$R!``!-\0``3=\``$MH``!,`0``3`H``$U5 +M``!-_@``2V@``$W%``!.'```2V@``$O)``!,T@``3CH``$Y4``!.<@``31,` +M`$QP``!,70``3,@``$S2``!-"0``31,``$V>``!-E```39X``%"%``!0:0`` +M4`(``$_4``!.R```4+,``%"A``!.R```3S<``$]```!0P```4-\``$[(``!/ +MR0``3[8``%!6``!030``4%8``%44``!2L@``56D``%3?``!4WP``5-\``%5& +M``!60```5B@``%44``!5=@``45@``%4T``!3J```5(```%/A``!48```5!`` +M`%2@``!40```5,```%*'``!2T```4OX``%,V``!3;@``4Y8``%,@``!3*0`` +M4N<``%+Q``!36```4V$``%.-``!3E@``5:```%+$``!2E```5KH``%()``!2 +M$@``4;T``%%8``!4^0``5F0``%9^``!6G```4H<``%*'``!2;@``5>P``%7B +M``!5[```5A,``%8<``!7H@``5\```%<&``!7!@``5T```%=``'__[(*_<*GB +MTO8J#[&TS@MGB4R]0=<':N.(W\G9G;.:/7*.,11&`00&``0)JKB$;(>X)P`' +M"P$``@,$`@(4`P,!&P0!`0```@,$#,"<7L#`:@`("@$]?9*5```%`1$/`'@` +B.``V`&4`>`!E````%`H!```M0RMQLYT!%08!`"$````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_copy_1.7z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_copy_1.7z.uu new file mode 100644 index 0000000..ad8cc4d --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_copy_1.7z.uu @@ -0,0 +1,614 @@ +begin 644 test_read_format_7zip_bcj2_copy_1.7z +M-WJ\KR<<``.C9M/"YVH```````!=`````````"._PGQ_14Q&`0$!"0`````` +M`````@`#``$```!PE`0(-````+!F````````-``@``<`*``:`!D`!@```#0` +M```T@`0(-(`$".````#@````!0````0````#````%`$``!2!!`@4@00(%0`` +M`!4````$`````0````$``````````(`$"`"`!`@T70``-%T```4`````$``` +M`0````!@````X`0(`.`$")@"``!,!```!@`````0```"````B&```(C@!`B( +MX`0(V````-@````&````!`````0````L`0``+($$""R!!`@8````&`````0` +M```$````4.5T9!A=```8W00(&-T$"!P````<````!`````0````O;&EB97AE +M8R]L9"UE;&8N@(``!(```"]`@```````,\!```2 +M````?`(```````#.````$@```(8"````````0P```!(```!:`0```````&<& +M```2````>`$````````J````$@```&X"````````/@```!(````:`P``F.($ +M"``````0`/'_80$```````!5````$@```#,```!TX00(`````!$`\?\M`P`` +M3.0$"``````0`/'_BP(```````!B`P``$@```"L!``#4X@0(!````!$`%P`/ +M`0```````)L(```2````Y`$``-CB!`@$````$0`7`%,!`````````````!(` +M``"%`0```````!H````2````A`(````````K````$@```+0"````````*0`` +M`!(````4`0`````````````2````Y0(```````"+````$@```*$````````` +M8````!(```!)```````````````@````&P$```````!]````$@```$(!```` +M`````````!(```"!`````````!0!```2`````&QI8G5T:6PN7!E`'-T'0`@<` +M``(`.P,```````"@X@0(!18``,#B!`@%)0``Q.($"`4K``#(X@0(!34``,SB +M!`@%/```T.($"`4^``#4X@0(!4L``-CB!`@%30``@.$$"`E\M#G! +M<]N-=@#KJXVT)@````"-O"<`````58GEBU4,BT4(B54(B44,7>F-="8`C;PG +M`````%6)Y8/L"(D<)(ET)`2+=0B+70R+5DR+2TR+0B@Y02A^$+@!````BQPD +MBW0D!(GL7<-\#XM"+#E!+'_FD(UT)@!]![C_____Z]V+0U")10R+1E")10B+ +M'"2+="0$B>Q=Z8VV`````(V_`````%6)Y8M5#(M%"(E5"(E%#%WIC70F`(V\ +M)P````!5B>6#[`B)'"2)="0$BW4(BUT,BU9,BTM,BT)0.4%0?A"X`0```(L< +M)(MT)`2)[%W#?`^+0E0Y051_YI"-="8`?0>X_____^O=BT-0B44,BT90B44( +MBQPDBW0D!(GL7>F-M@````"-OP````!5B>6+50R+10B)50B)10Q=Z8UT)@"- +MO"<`````58GE@^P(B1PDB70D!(MU"(M=#(M63(M+3(M"&#E!&'X0N`$```"+ +M'"2+="0$B>Q=PWP/BT(<.4$F-="8` +MC;PG`````%6)Y8/L"(D<)(ET)`2+=0B+70R+5DR+2TR+0B`Y02!^$+@!```` +MBQPDBW0D!(GL7<-\#XM")#E!)'_FD(UT)@!]![C_____Z]V+0U")10R+1E") +M10B+'"2+="0$B>Q=Z8VV`````(V_`````%6)Y8M5#(M%"(E5"(E%#%WIC70F +M`(V\)P````!5B>6+10B+50R+0%")10R+0E")10A=Z9"-="8`58GEBT4,BT!0 +MB44,BT4(BT!0B44(7>F0D)"0D%6)Y8/L"(D<)(ET)`2+10B+30R+`(M00(/Z +M!W1SBQF+2T"#^0=T:8/Z"G1,@_D*=$%E/O_ +M_P````"%P'4-H43D!`B%P`^$QX5`^___`0```,<$)-S8!`CHQX6(^___```` +M`,>%C/O__P````#'A:#[__\`````QX6<^___`````,>%F/O__P````"%P(G# +MQX6H^___`````,>%K/O__P````#'A;#[__\`````QX6T^___`````,>%I/O_ +M_P````!T"8`X``^%B[T4^___A?\/A(N%$/O__XN]%/O__\>%+/O__P````#' +MA3#[__\`````@^`"QX4\^___`````,>%3/O__P````")A0S[___I@_@*#X2+ +MM1C[__^%]@^$BT=0@#@N#X2+1RP[A:S[__]V!HF%K/O__XL5).0$"(72=0J+ +M->SC!`B%]G0=B40D!(M'4(D$).@[A:S[__]V!HF%K/O__XN=0/O__X7;#X2+ +M5TR)T(M(/(N%M/O__XF5*/O__XM2.(G&P?X?.?%\#'\$.<)V!HF5M/O__XN5 +M*/O__XM"!#N%L/O__W8&B86P^___BXTH^___#[=!"CN%J/O__W8&B86H^___ +MBXTH^___BU$T.Y6,^___BT$P?!9_"#N%B/O__W8,B86(^___B96,^___BX4H +M^___BPU$Y`0(BT`X`84L^___AZ+5>PS%:#B!`@/A8'$+`4``%M>7UW#C70F`(L- +M\.($"(7)#X7'1PP!````QT<0`````.F#Z`$/A8L=[.($"(7;#X7KU(N5*/O_ +M_\=$)`0`````BT(,B00DZ(N-*/O__\=$)`0`````B85$^___BT$0B00DZ(F% +M2/O__^F#O3#[__\.#X>+E2C[__^+0A0PY#T``0``H3SD!`@9R8/A^8/!#X7` +MB8TP^___#X2+E4S[__^-1#,2B4,(B00DB50D!.B+C4S[__^)#"3HZ8N-*/O_ +M_XM!1(D$).B%P(F%3/O__P^$@#@`=2*)!"3HQP0D^M@$".B%P(F%3/O__P^$ +MBX5,^___B00DZ#N%H/O__XF%-/O__P^&B86@^___Z8V5D/O__XD4).B#P`$/ +MA(M'/(7`#X6+1U"-M;G[___'1"0(]-@$",=$)`0!!```B30DB40D#.B+A0S[ +M__^%P'1SBX60^___B30DB40D!.B#P`%T%+/O_ +M_P````#'A3S[__\`````QX4P^___`````*%$Y`0(A/&`3`/MD(!B$$! +M@\$"QD$!``^V0@*#P@&$P'7;@'G_.@^$C86D^___BY4<^___B40D*(V%K/O_ +M_XE$)"2-A8C[__^)1"0@C86@^___B40D'(V%G/O__XE$)!B-A9C[__^)1"04 +MC86H^___B40D$(V%M/O__XE$)`R-A;#[__^)1"0(QT0D!)39!`B)%"3HQP48 +MY`0(`0```(/X"`^&B[6P^___,<"%]G0@N0$```"X"@```/?A@^X!B<%U\L>% +ML/O__P````"-0/^+O;3[__^)A;#[__\QP(7_?C6)_KD!````,=MKTPJX"@`` +M`(F5!/O___?AB=.)P0.=!/O__X/N`77AQX6T^___`````(U`_XNUJ/O__XF% +MM/O__S'`A?9T(+D!````N`H```#WX8/N`8G!=?+'A:C[__\`````C4#_BXV, +M^___BY6(^___B86H^___@_D`B94@^___B8TD^___#XZ+C2#[__^^`0```#'_ +MBYTD^___:\<*B84$^___N`H```#WYHG7B<8#O03[__^#P?^#T_^)V@G*==J) +M\(GZ@\#_QX6(^___`````(/2_\>%C/O__P````"+C1S[__^)A8C[__^)E8S[ +M__^)#"3HZ8N-+/O__XU=NHN%M/O__\=$)`@/O__XN%J/O__XE$)`SHB1PDZ(F%?/O__Z'\ +MXP0(A%@/O__P4```"+A3#[__\[A8#[__]V!HF%@/O__XN%F/O__XF% +MA/O__^F+1U")1"0(BT<$BT`%M/O__P````#'A:C[__\`````QX68 +M^___`````,>%G/O__P````#'A:#[__\`````QX6(^___`````,>%C/O__P`` +M``#'A:S[__\`````@ST%I/O__P`````9P/?0(048Y`0(Z<=$)`3I +MV`0(QP0D`0```.AFQP$P`.F+E1S[__^)T8/!`F;'`C`ZQD("`.G'1"0$_-@$ +M",<$)`$```#HZ(VT)@````!5B>575E.#[!R#/?SB!`@!B47LB4WH&<`EP)@$ +M"(E$)`B)3"0$B10DZ(7`B<B)PC'`Z*'L +MX@0(A<`/A8LU!.,$"(7V#X3'1?``````C;0F`````(D\).B%P(G##X2+0T"# +M^`(/A(GV#X^#Z`%UU8M+/(7)=`R+0U"`."X/A*$DXP0(A<`/A*'`X@0(A<`/ +MA8L5S.($"(M""(/H`87`B4((#XB+`L8`"H/``8D"BT,B)PHG&B=CHH03C!`B%P`^%A?8/A(E<)`3'1"0(!``` +M`(D\).B)/"3HA<")PP^%Z(L`A<`/A8/$'%M>7UW#D(/X!'0)@_@'#X6+0R") +M!"3HB40D"(M#',<$)/#8!`B)1"0$Z,<%(.,$"`$```#ID(M#4,<$)"W9!`B) +M1"0$Z.F#?>P!#XZ+0QR)!"3HQP0D2MD$".C'!23C!`@!````Z8L=".0$"(7; +M#X7V1>@(QT7P``$```^%Z:',X@0(QP0D"@```(E$)`3HZ8L5\.($"(72#X3I +MB50D!,<$)`H```#HZ<=$)`1,V00(QP0D`0```.C'1"0$)-D$",<$)`$```#H +MC78`C;PG`````(U,)`2#Y/#_575E-1@>PX!@``BQFAH.($"(E%[#'` +MC87L_?__BWD$B87D^?__QT0D!,S;!`C'!"0`````Z,<$)`$```#HA<`/A,<% +M#.`$"%````#'!"15V00(Z(7`=`F`.``/A8V%W/G__XE$)`C'1"0$:'0(0,<$ +M)`$```#H@\`!=!0/MX7>^?__9H7`=`@/M\"C#.`$",<%#.0$"`$```"^$``` +M`,=$)`C(V00(B7PD!(D<).B#^/]T/X/H,8/X1W8PZ.O8QP4,XP0(`0```,<$ +M)%79!`CHASY__^)!"3H@^@!#X2+%1SD!`B%TG1&QP48Y`0(`0```,=$)`1@L@0( +MQP0D`@```.C'1"0$8+($",<$)`,```#HQP0DB=D$".B)!"3HH4#D!`B%P'5! +MH43D!`B%P'4XH?CC!`B%P'4OH13C!`B%P'4FH1CC!`B%P'4=H3#D!`B%P'44 +MBQTA%.,$"(7`#X6A&.,$"(7`#X3'!>3B!`B0E00( +MH0SC!`B%P'2?QP7@X@0(L+P$"(N%S/G__X7`=*R+ACY___'1"0$$.0$"(D$ +M).B+%1#D!`B)T,'X'\'H%P'0P?@)HQ#D!`CIQP0D9MD$".B%P`^%Z8/.(,<% +M\.($"`$```#IQP4,Y`0(`````,<%).0$"`$```#'!>SC!`@`````Z:'$X@0( +MH_3C!`CIQP4,XP0(`````,<%1.0$"`````#'!33D!`@`````Z<<%&.,$"`$` +M``#'!13C!`@`````Z<<%!.,$"`$```#I@^;\@\X0QP7XX@0(`0```.F#YN^# +MS@+'!?CB!`@`````Z<<%].($"`$```#I@\X!QP7XX@0(`````.G'1"0(`0`` +M`,=$)`3,VP0(QP0D7=D$".CIQP4PY`0(`0```,<%%.0$"`````#IQP4,XP0( +M`0```,<%1.0$"`````#'!1#C!`@`````Z<<%-.0$"`$```#'!43D!`@````` +MQP4,XP0(`````.G'!0SD!`@`````QP4DY`0(`````,<%[.,$"`````#IQP4$ +MY`0(`0```,<%Z.,$"`````#'!3CD!`@`````Z<<%%.,$"`$```#'!1CC!`@` +M````Z<<%^.,$"`$```#IQP4(XP0(`0```.G'!0SD!`@!````QP4DY`0(```` +M`,<%[.,$"`````#IQP44Y`0(`0```,<%,.0$"`$```#IQP4\Y`0(`0```.G' +M!0#C!`@!````Z<<%$.,$"`$```#'!0SC!`@`````QP5$Y`0(`````.G'!43D +M!`@!````QP4,XP0(`````,<%$.,$"`````#IQP7\XP0(`````,<%Z.($"`$` +M``#IQP5`Y`0(`0```.G'!?SC!`@!````Z<<%_.($"`$```#IQP7LX@0(`0`` +M`,<%!.,$"`````#IQP7HXP0(`0```,<%!.0$"`````#'!3CD!`@`````Z<<% +M#.0$"`````#'!23D!`@`````QP7LXP0(`0```.G'!0CD!`@!````Z<<%'.,$ +M"`$```#IQP4XY`0(`0```,<%!.0$"`````#'!>CC!`@`````Z<<%(.0$"`$` +M``#IZ(7`#X6A].($"(7`#X7'!?#B!`@!````Z8L=&.,$"(7;#X6+#03D!`B% +MR0^$QP7DX@0(8)<$".FA&.,$"(7`#X6A!.0$"(7`#X3'!>3B!`C0EP0(Z:$0 +MXP0(A3B!`B@F`0(Z<<%X.($ +M"$"]!`CIC9WD^?__B5PD!,<$)'K9!`CHB5PD!,<$)'W9!`BC\.,$".B)7"0$ +MQP0D@-D$"*,LY`0(Z(E<)`3'!"2#V00(HTCD!`CHB5PD!,<$)(;9!`BC*.0$ +M".B%P*,`Y`0(#X2A\.,$"(7`#X2+'2SD!`B%VP^$BPT`Y`0(A3B!`BPE@0(Z8L5..0$"(72=1BAZ.,$"(7`=#S'!>3B!`A`E@0(Z<<%Y.($ +M"-"6!`CIQP7DX@0(0)<$".G'!>3B!`A@F`0(Z<<%Y.($"/"7!`CIB5PD!,<$ +M).W8!`CHHP#D!`CID)"0D)"0D)"0D)!5B>6#[!B%P'0]H0#D!`C'1"0(H+($ +M",=$)`0!````B00DZ+B@L@0(B40D"*%(Y`0(QT0D!`$```")!"3HR<.A`.0$ +M",=$)`@`N`0(QT0D!`$```")!"3HN`"X!`CKP9"-="8`58GE4X/L%(M="(G8 +MZ(D<),=$)`0`````Z.B)7"0$B00DZ(/$%%M=PY"-M"8`````58GE@^PHBT4( +MQT0D"`$```#'!"0!````B$7_C47_B40D!.@QP,G#D(UT)@!5B>575E.#["R+ +M10B%P`^$BT4(,?^)!"3HBQ5@W`0(9L=%V@``QT7<`````(E5X(E%U.L\C70F +M``^^PH/H,&:#?=H`B0,/A&;'1=H!`(/&`8/#!(/^`G5%@\`:.,$"`````"-!#\Y1=1W.8M5X`^V`HA%\@^V0@&(1?.-!'\Q +M]HT'03#[["B40D +M!,<$)#37UW#QT4(S-L$".E5B>564XG#C31`@^P0 +MBQ2U:.,$"(72#X6+!+5@XP0(@_C_=#B)1"0(H?#C!`C'1"0$`````(D$).B% +MP'0;QT0D"`"X!`C'1"0$`0```(D$).B-=@"-!%N+!(5DXP0(@_C_=#6)1"0( +MH2SD!`C'1"0$`````(D$).B%P'08QT0D"`"X!`C'1"0$`0```(D$).B#Q!!; +M7EW#D(UT)@"A*.0$",=$)`@`N`0(QT0D!`$```")!"3HZ8VT)@````"-O"<` +M````#[?`B<)5@>(`\```B>6#[`B!^@!````/A'Y1@?H`H```#X2!^@#```!T +M8H'Z`&````^$,=*H271?]L0(#X7VQ`0/A+@(````C70F`.BZ`0```.LXC70F +M`('Z`!```'18@?H`(```B?9UO;@&````Z+H!````R8G0P[@"````Z+H!```` +MR8G0P[@!````Z+H!````R8G0P[@%````Z+H!````R8G0PXGVN`,```#HN@$` +M``#)B=##J`)T./;$`G01N`D```#HN@$```#KI[@*````Z+H!````ZY:X!``` +M`.BZ`0```.N%,<#HN@$```#IN`<```#HN@$```"0Z8UT)@"-O"<`````58GE +M4X/L=(E%F*&@X@0(B47X,<"A+.`$"(7`#XBA1.,$"(7`=':+'?3C!`B%VP^$ +MC468B00DZ(E<)`B-7:C'1"0$4````(D<)(E$)`SHHSC!`B%R70)B44(7>F+%0SD!`B% +MTG0)B44(7>F)10A=Z9!5B>6#[`BAP.($"(M-"(7`=2"+%!^@`0```/A('Z`$```(UT)@!T/JA)=,:AP.($ +M"(7`#X6+%6#[#B)7?2)PXE]_(G/B77XBW!,H4#D!`C'1>P`````A<`/A:'X +MXP0(A+0U")!"3HBTWLC1P(H1SD!`B%P'4W +MBSTPY`0(A?]T"P^W1@CH`<.)V(MU^(M=](M]_(GL7<.+0U")!"3HBU7LC1P0 +MZ\F%_W3%,<#HZ[RA$.0$"(/H`8E%X(G"BT8XP?H?`47@H1#D!`B)5>2+5CP1 +M5>2+3>2)PL'Z'XE4)`R+5>")3"0$B40D"(D4).B)?"0$QP0D>-L$"(E$)`B) +M5"0,Z`%%[.F+1@2)5"0$QP0D7<.)5"0$QP0D"@```.CKHXUV`%6)Y5=64X/L +M/(M%"(,]&.0$"`$9TH/B!XE%T(M`"(/"`3L%'.`$"(E5Z`^/BUW0QT7<```` +M`(L3A=)T)(L-0.,$"(M"#(/P`0M"$'0,BT72)5=B+3P!````BUW0H4#C!`B+4R"+2Q"+7=B+!)CHBQ4TY`0(A=(/A(/#`8M-W(E= +MV#E-V`^-BU7H`<:-'!8C7=0Y^W]>C70F`(L--.0$"(7)=`R+1P/C8L5 +MP.($"(72=5"+#B-'!8C7=0Y^WZFBTW,.4WL=&*#1>P!`WWPZ8GV@ST8Y`0( +M`8G>BQ7,X@0(&<"#X.F#P"")5"0$B00DZ.NX.T$8?`B`^@J-=@!UH(E,)`2) +MWHD4).CKFXM5X`%5V(M-W#E-V`^,H<#B!`B%P'4UBQ7,X@0(BT((@^@!A<") +M0@AX.8L"Q@`*@\`!B0*#1>0!BUW@.5WD#X6#Q#Q;7E]=PZ',X@0(QP0D"@`` +M`(E$)`3HZ]&)5"0$QP0D"@```.CKOXL]1.0$"(7_=0B%R0^$BTW0BQT0Y`0( +MBU$$QP0D?ML$"(/J`8T,&C'2B7UWIP>`" +MB40D!*%`XP0(B00DZ(7`B<)T%HM-T(D50.,$"(M!"*,575E.#[`R+=0B+'H7;#X0Q_^L7UW#H575E.!['P(``"+10B+%:#B!`B)5?`QTHLPB86D +M]___A?8/A(M&/(7`#X7'A:CW__\`````D(M&#(/P`0M&$`^$BQU`Y`0(BWY, +MA=L/A8L-^.,$"(7)#X6-3(`\```@?H` +M(```#X2!^@!@```/A('Z`.````^$BP`[!2C@!`@/A(M&/(7`#X6+1E"-G%(U-S(N5I/?__XM#!(E$)!R+0AR)1"08 +MBP.)1"04BT(LB40D$`^W1PJ)1"0,BT(DB4PD!,<$)(S;!`B)1"0(Z*$\Y`0( +MA<`/A:$(Y`0(A<`/A0^W1P@E`/```#T`(```#X0]`&````^$BXVD]___BT

    ")5"00B40D#,=$)`BFVP0(QT0D!!````")'"3HBX6L]___B5PD +M",<$)+O;!`B)1"0$Z*$$Y`0(A<`/A(M'&.BA'.0$"(7`#X0/MT<(Z(F%J/?_ +M_^F+0PR+C:3W__^)1"0(BT$8QP0DH-L$"(E$)`3HZ8UV`(M#"(N5I/?__XE$ +M)`B+0A3'!"2@VP0(B40D!.CIBPT0Y`0(C4'_BRL````BWT,C95P____BW4(H:#B!`B)1?`QP,=$)`B`````QT0D!``` +M``")%"3HA?_'A6#___\`````=%^-E7#___^-A6S___^)5"0,B7PD"(ET)`2) +M!"3HA<")PW0Y@_O_=&V#^_X/A(N5;/___X'Z_P```'=*H=#B!`B+1)`TJ0`` +M!`!T*8.%8/___P$!WH7_=:&+5?`S%:#B!`B+A6#___]U9H'$K````%M>7UW# +MBX5@____C028B85@____Z\V)%"3HZ[6)]HV%AT.($"(M$F#2I```$``^$,?:%_W\WZV:-="8`BQ7,X@0(BX5< +M____#[8,!HM""(/H`87`B4((#XB+`H@(@\`!B0*#Q@$Y]W0KH<#B!`B%P'3& +MHAT.($"(M$F#2)PH'B````X`^$B=#!Z!X!O5S___\!A6#____I.T(8 +M#[;9?`F`^PH/A8E4)`2)'"3HZ8L5P.($"(72#X6+%RL````BT4(BQ6@X@0(B57P,=+'1"0(@``` +M`,=$)`0`````B85<____C85P____B00DZ,>%8/___P````"+E5S___^-A7#_ +M__^)1"0,C85L____QT0D"`8```")!"2)5"0$Z(7`B<8/A(/^_@^$@_[_#X0Q +MVX7V?S/K78L5S.($"(N%7/___P^V#`.+0@B#Z`&%P(E""`^(BP*("(/``8D" +M@\,!.=YT+(L]P.($"(7_=,6AS.($"(N57/___XE$)`0/M@03@\,!B00DZ#G> +M==2+G6S___\!M5S___^!^_\```!W<*'0X@0(BT28-*D```0`#X0QP(7;="B! +M^_\````/AZ'0X@0(BT28-(G"@>(```#@#X2)T,'H'@&%8/___^D[0A@/MOE\ +M"HGX/`H/A8E4)`2)/"3HZ8D<).B0ZXZ-A7#____'1"0(@````,=$)`0````` +MB00DZ*'`X@0(A<`/A8L5S.($"(N%7/___P^V"(M""(/H`87`B4((#XB+`H@( +M@\`!B0*#A5S___\!@X5@____`>F+E5S____'!"3TV`0(B50D!.@!A6#___^+ +M5?`S%:#B!`B+A6#___]U:X'$K````%M>7UW#)0``!`"#^`$9P(/(`>F)'"3H +MZ:',X@0(BY5<____B40D!`^V`HD$).CI.T(8#[;9?`F`^PH/A8E4)`2)'"3H +MZ>B-=@"-O"<`````58GE5U93@>RL````BT4(BQ6@X@0(B57P,=+'1"0(@``` +M`,=$)`0`````B858____C85P____B00DZ,>%8/___P````"+E5C___^-A7#_ +M__^)1"0,C85L____QT0D"`8```")!"2)5"0$Z(7`B85<____#X2+A5S___^# +MP`*#^`$/AHN=;/___X'[_P````^'H=#B!`B+1)@TJ0``!``/A(/[(@^$@_M< +M#X2+O5S___^%_WYO,=OK-8L5S.($"(N%6/___P^V#`.+0@B#Z`&%P(E""`^( +MBP*("(/``8D"@\,!.YU<____=#"+-<#B!`B%]G3!H@>`85@____@[U<_____@^$@[U<_____P^$BY5< +M____`958____Z8.]7/____\/A;\!````,?;ID(UT)@"+%#P#")!"3HH<#B!`B%P`^$C;0F`````*',X@0(B40D!(G8@^`'@\`PB00D +MZ.F)]CM"&'P)@/D*#X6)5"0$B0PDZ.F0.T(8#XV)5"0$QP0D7````.CIB?8[ +M0AA\"8#Y"@^%B50D!(D,).CID#M"&'P)@/D*#X6)5"0$B0PDZ.F+#>SC!`B% +MR700A=MX#('[_P````^.B[U<____A?\/CX.]7/____X/A8M5\#,5H.($"(N% +M8/___P^%@<2L````6UY?7<.+A5C___^)!"3HB575H/L,(M5 +M#(M%"(MU$(M]%(E5W(M-W(E%V,=%T`````")\,=%U`````")^H7)QT7D```` +M``^(A?\/B(G7B<:+5=B)P8M%W(7_B57PB47L=10YQG9!B="+5>SW]HG!,<#K +M$XUV`#M]['9/,2)1=2+1="+5=2%R70']]B#T@#W +MVH/$,%Y?7<.%]G4+N`$````QTO?VB<&+1>R)^O?QB<:+1?#W\8G!B?#KO`^] +MQX/P'XE%Z'5$.7WL=P4Y=?!RG+D!````,<#KGO==V(-5W`#W7=R%_\=%Y/__ +M__\/B9"-="8`B?")^O?8@](`]]KW5>3IN"````")\BM%Z(G!T^H/MDWHB47T +MB?B)UXM5[-/@"<>+1?#3Y@^V3?33Z`^V3>C3X@^V3?0)T(M5[(E%S-/J]_>) +M5&-X9'AB>&5G961A8F%G86-A9`````!,4T-/3$]24R!S:&]U;&0@=7-E +M(&-H87)A8W1ED`0(KI`$"+Z0!`C.D`0(WI`$".Z0!`C^D`0(#I$$"!Z1!`@ND00( +M/I$$"$Z1!`A>D00(;I$$"'Z1!`B.D00(GI$$"*Z1!`B^D00(SI$$"-Z1!`CN +MD00(_I$$"`Z2!`@>D@0(+I($"#Z2!`A.D@0(7I($"&Z2!`A^D@0(CI($")Z2 +M!`BND@0(OI($",Z2!`C>D@0([I($"/Z2!`@.DP0('I,$""Z3!`@^DP0(3I,$ +M"%Z3!`ANDP0(?I,$"(Z3!`B>DP0(KI,$"+Z3!`C.DP0(WI,$".Z3!`C^DP0( +M#I0$"!Z4!`@NE`0(/I0$"$Z4!`A>E`0(````````````)$9R965"4T0Z('-R +M8R]L:6(O8W-U+VDS.#8M96QF+V-R=#%?'`@)```)$9R965"4T0Z('-R8R]L:6(O8W-U +M+V-O;6UO;B]C'`@ +M)`!'0T,Z("A'3E4I(#0N,BXR(#(P,#6YS>6T`+F1Y;G-T<@`N9VYU+G9E6X`+G)E;"YP;'0`+FEN:70`+G1E>'0`+F9I;FD`+G)O9&%T +M80`N96A?9G)A;65?:&1R`"YD871A`"YE:%]F`(` +M``0`````````!`````0````G````"P````(```"\@P0(O`,``)`%```%```` +M`0````0````0````+P````,````"````3(D$"$P)``!$`P`````````````! +M`````````#<```#___]O`@```)",!`B0#```L@````0``````````@````(` +M``!$````_O__;P(```!$C00(1`T``#`````%`````0````0`````````4P`` +M``D````"````=(T$"'0-``!`````!``````````$````"````%P````)```` +M`@```+2-!`BT#0``,`(```0````+````!`````@```!E`````0````8```#D +MCP0(Y`\``!$```````````````0`````````8`````$````&````^(\$"/@/ +M``!P!``````````````$````!````&L````!````!@```'"4!`AP%```#$0` +M````````````$`````````!Q`````0````8```!\V`0(?%@```P````````` +M``````0`````````=P````$````"````B-@$"(A8``".!``````````````$ +M`````````'\````!`````@```!C=!`@870``'```````````````!``````` +M``"-`````0````,`````X`0(`&```#````````````````0`````````DP`` +M``$````"````,.`$"#!@``!8```````````````$`````````)T````&```` +M`P```(C@!`B(8```V`````4`````````!`````@```"F`````0````,```!@ +MX00(8&$```@```````````````0`````````K0````$````#````:.$$"&AA +M```(```````````````$`````````+0````!`````P```'#A!`AP80``!``` +M````````````!`````````"Y`````0````,```!TX00(=&$``"0!```````` +M``````0````$````O@````@````#````H.($"*!B``"L`0`````````````@ +M`````````,,````!``````````````"@8@``00,``````````````0`````` +M```!`````P``````````````X64``,P```````````````$````````````5 +M8```6%```!20```3Z```$^@```_D```HH```$U@``!&(```0B```2?```!*H +M```2J```%!@``!08```3:```%"@``!0H```4*```$[@``!%X```2*```$[@` +M`!*8```16```%"@``!.X```0"```$[@``!#8```4&```$1@``!*H```3>``` +M$2@``!'(```4&```$.@``!*X```1R```$-@``!*H```4&```$V@``!)(```3 +MN```$J@``!08```2J```%!@``!*H```4&```$K@``!*H```4&```$X@``!.( +M```3V```$R@``!)X```98```$N@``#?````0&```$G@``!E@```1V```$N@` +M`!)H```1>```$B@``!(H```WP```$!@``!#(```32```$X@``!.(```3J``` +M$Y@``!"(```12```$@@``$FP```0B```$#@``!"(```3F```$(@``!+(```2 +MV```$M@``!"(```RT```)@```"8````36```$S@``!"(```3"```$\@``!18 +M```46```%%@``!18```46```$#@``!18```2.```$C@``!(X```Q\```$M@` +M`!0(```0F```$&@``!08```2*```$B@``!"X```2.```$+@``!(X```2.``` +M-#```#0P```T,```-#```#0P```T,```-#```#0P```T,```-#```#0P```1 +MN```$6@``!#X```0>```$$@``!+X```3V```$,@``!-(```0R```$T@``!#( +M```32```$T@``!-(```32```$,@``!#(```0R```$,@``!-(```U$```-\`` +M`#A@```WP```,?```%;````2B```$H@``#N````0R```$T@``#N````0R``` +M$T@``!#(```32```$H@``!&8```2N```$H@``!08```[@```$,@``!#(```3 +M2```$T@``!(8```2J```$:@``!0X```1.```$_@``!*(```0J```$H@``#9@ +M```WP```,?```!*(```2J```$H@``#9@```U$```$H@``!*(``!6P```$H@` +M`!*(```0R```.&```!*H```42```$H@``#?````2J```$H@``#9@```V8``` +M$J@``!*H```2:```$7@``!`H```32```$_@``!*X```2:```$K@``!&H```2 +M:```$K@``!/8```3&```$U@``!)8```06```$0@``!)8```3V```$E@``!!8 +M```0R```$T@``!)8```1"```$,@``!#(```1"```$T@``!-(```0R```$T@` +M`!/8```26```$%@``!#(```32```$0@``!)8```2B```$0@``!#(```32``` +M$]@``!)8```06```$,@``!#(```0R```$,@``!#(```32```$T@``!-(```3 +M2```%!@``!-(```1"```$E@``!'H```1"```$,@``!#(```32```$T@``!/8 +M```5,```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^```#_@` +M``_X```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^``` +M#_@```_X```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/ +M^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X +M```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^```#_@` +M``_X```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^``` +M#_@```_X```/^```#_@``!'X```5D```$?@``!9````1^```%M```!'X```7 +M8```$?@``!?P```1^```$?@``!B@```A1```(5L``"#]```=7@``'6H``!YQ +M```>4```'5```!U0```>B@``'S$``!^B```EJ0``'LT``![-```?!0``&H$` +M`"$;```CMP``)?0``!JD```=5P``&J0``!JD```<````'/$``!S^```<_@`` +M)>```"7@```<5P``'%<``"2R```@R0``''```!QP```@/P``'^D``!XR```= +MN0``'C(``!FR```EJ0``)<<``"6]```DU```)1H``!HQ```=ZP``(#4``"2- +M```C00``(Y@``")U```A\@``(:,``"B"```G=P``*`@``"=H```GP```)X`` +M`"A&```GV```*"P``"A9```F@```)H```":2```H;@``)H```":````F@``` +M)Q```"<0```F<@``)H```"9R```F^0``)H```":^```F^0``*8L``#$P```O +MOP``+#H``#"!```K[0``+`<``#`3```P5```,#P``"_H```P8P``*QP``"L2 +M```K'```*?\``"HF```I8P``*6,``"EC```I8P``*6,``"EC```I8P``*6,` +M`"EC```I8P``*6,``"EC```I8P``*6,``"EC```I8P``*6,``"EC```I8P`` +M*6,``"EC```I8P``*6,``"EC```I8P``*6,``"EC```I8P``*6,``"EC```I +M8P``*6,``"EC```I8P``*6,``"EC```IVP``*=L``"G;```KHP``,6T``"NM +M```K0@``,4P``"NM```KP```*ZT``"NM```KP```,Z```VF```-I@``#:8```V@0``-I@``#:8 +M```VF```-I@``%$0``!+(```3H```#ES```Y)@``.?D``#I*```[4@``.:@` +M`#HJ```YQ```.+(``#KB```ZP@``.OX``#IF```[-@``.J(``#L:```Y%0`` +M.9<``#GH```Y8@``.-H``#R(```[LP``.ZH``$`\``!`*@``/^L``#_K```_ +MN@``/X0``#]R```_A```/X0``#YT```^K0``/DT``#XT```^-```/+```#UP +M``!!5```09(``$"@``!!$```11P``$4<``!$]P``1J@``$95``!#5```0U0` +M`$-4``!(>P``1_4``$@U``!)!@``21H``$CC``!(Q0``1C```$8(``!%<``` +M17```$>P``!%WP``1^4``$?3``!%]```1O```$<```!&T```2,X``$(```!) +MI0``0?4``$>```!$4P``1((``$2"``!#M```0Z<``$(N``!"(```1/<``$2U +M``!(1P``2(X``$3)``!%N```1$8``$1U``!$=0``0L$``$-4``!#`P``1S`` +M`$-4``!"@```1,D``$-,``!$]P``0U0``$-4``!#`P``0P,``$@U``!(-0`` +M0U0``$K]``!-I0``3.0``$UO``!-1```3*,``$R!``!-\0``3=\``$MH``!, +M`0``3`H``$U5``!-_@``2V@``$W%``!.'```2V@``$O)``!,T@``3CH``$Y4 +M``!.<@``31,``$QP``!,70``3,@``$S2``!-"0``31,``$V>``!-E```39X` +M`%"%``!0:0``4`(``$_4``!.R```4+,``%"A``!.R```3S<``$]```!0P``` +M4-\``$[(``!/R0``3[8``%!6``!030``4%8``%44``!2L@``56D``%3?``!4 +MWP``5-\``%5&``!60```5B@``%44``!5=@``45@``%4T``!3J```5(```%/A +M``!48```5!```%2@``!40```5,```%*'``!2T```4OX``%,V``!3;@``4Y8` +M`%,@``!3*0``4N<``%+Q``!36```4V$``%.-``!3E@``5:```%+$``!2E``` +M5KH``%()``!2$@``4;T``%%8``!4^0``5F0``%9^``!6G```4H<``%*'``!2 +M;@``5>P``%7B``!5[```5A,``%8<``!7H@``5\```%<&``!7!@``5T```%=` +M`'__[(*_<*GBTO8J#[&TS@MGB4R]0=<':N.(W\G9G;.:/7*.,11&`00&``0) +MP)Q>A&R'N"<`!PL!``(!`!0#`P$;!`$!```"`P0,P)Q>P,!J``@*`3U]DI4` +J``4!$0\`>``X`#8`90!X`&4````4"@$``"U#*W&SG0$5!@$`(0`````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_copy_2.7z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_copy_2.7z.uu new file mode 100644 index 0000000..b3d860e --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_copy_2.7z.uu @@ -0,0 +1,615 @@ +begin 644 test_read_format_7zip_bcj2_copy_2.7z +M-WJ\KR<<``-Y\RJ#YVH```````!K`````````/R]6^=_14Q&`0$!"0`````` +M`````@`#``$```!PE`0(-````+!F````````-``@``<`*``:`!D`!@```#0` +M```T@`0(-(`$".````#@````!0````0````#````%`$``!2!!`@4@00(%0`` +M`!4````$`````0````$``````````(`$"`"`!`@T70``-%T```4`````$``` +M`0````!@````X`0(`.`$")@"``!,!```!@`````0```"````B&```(C@!`B( +MX`0(V````-@````&````!`````0````L`0``+($$""R!!`@8````&`````0` +M```$````4.5T9!A=```8W00(&-T$"!P````<````!`````0````O;&EB97AE +M8R]L9"UE;&8N@(``!(```"]`@```````,\!```2 +M````?`(```````#.````$@```(8"````````0P```!(```!:`0```````&<& +M```2````>`$````````J````$@```&X"````````/@```!(````:`P``F.($ +M"``````0`/'_80$```````!5````$@```#,```!TX00(`````!$`\?\M`P`` +M3.0$"``````0`/'_BP(```````!B`P``$@```"L!``#4X@0(!````!$`%P`/ +M`0```````)L(```2````Y`$``-CB!`@$````$0`7`%,!`````````````!(` +M``"%`0```````!H````2````A`(````````K````$@```+0"````````*0`` +M`!(````4`0`````````````2````Y0(```````"+````$@```*$````````` +M8````!(```!)```````````````@````&P$```````!]````$@```$(!```` +M`````````!(```"!`````````!0!```2`````&QI8G5T:6PN7!E`'-T'0`@<` +M``(`.P,```````"@X@0(!18``,#B!`@%)0``Q.($"`4K``#(X@0(!34``,SB +M!`@%/```T.($"`4^``#4X@0(!4L``-CB!`@%30``@.$$"`E\M#G! +M<]N-=@#KJXVT)@````"-O"<`````58GEBU4,BT4(B54(B44,7>F-="8`C;PG +M`````%6)Y8/L"(D<)(ET)`2+=0B+70R+5DR+2TR+0B@Y02A^$+@!````BQPD +MBW0D!(GL7<-\#XM"+#E!+'_FD(UT)@!]![C_____Z]V+0U")10R+1E")10B+ +M'"2+="0$B>Q=Z8VV`````(V_`````%6)Y8M5#(M%"(E5"(E%#%WIC70F`(V\ +M)P````!5B>6#[`B)'"2)="0$BW4(BUT,BU9,BTM,BT)0.4%0?A"X`0```(L< +M)(MT)`2)[%W#?`^+0E0Y051_YI"-="8`?0>X_____^O=BT-0B44,BT90B44( +MBQPDBW0D!(GL7>F-M@````"-OP````!5B>6+50R+10B)50B)10Q=Z8UT)@"- +MO"<`````58GE@^P(B1PDB70D!(MU"(M=#(M63(M+3(M"&#E!&'X0N`$```"+ +M'"2+="0$B>Q=PWP/BT(<.4$F-="8` +MC;PG`````%6)Y8/L"(D<)(ET)`2+=0B+70R+5DR+2TR+0B`Y02!^$+@!```` +MBQPDBW0D!(GL7<-\#XM")#E!)'_FD(UT)@!]![C_____Z]V+0U")10R+1E") +M10B+'"2+="0$B>Q=Z8VV`````(V_`````%6)Y8M5#(M%"(E5"(E%#%WIC70F +M`(V\)P````!5B>6+10B+50R+0%")10R+0E")10A=Z9"-="8`58GEBT4,BT!0 +MB44,BT4(BT!0B44(7>F0D)"0D%6)Y8/L"(D<)(ET)`2+10B+30R+`(M00(/Z +M!W1SBQF+2T"#^0=T:8/Z"G1,@_D*=$%E/O_ +M_P````"%P'4-H43D!`B%P`^$QX5`^___`0```,<$)-S8!`CHQX6(^___```` +M`,>%C/O__P````#'A:#[__\`````QX6<^___`````,>%F/O__P````"%P(G# +MQX6H^___`````,>%K/O__P````#'A;#[__\`````QX6T^___`````,>%I/O_ +M_P````!T"8`X``^%B[T4^___A?\/A(N%$/O__XN]%/O__\>%+/O__P````#' +MA3#[__\`````@^`"QX4\^___`````,>%3/O__P````")A0S[___I@_@*#X2+ +MM1C[__^%]@^$BT=0@#@N#X2+1RP[A:S[__]V!HF%K/O__XL5).0$"(72=0J+ +M->SC!`B%]G0=B40D!(M'4(D$).@[A:S[__]V!HF%K/O__XN=0/O__X7;#X2+ +M5TR)T(M(/(N%M/O__XF5*/O__XM2.(G&P?X?.?%\#'\$.<)V!HF5M/O__XN5 +M*/O__XM"!#N%L/O__W8&B86P^___BXTH^___#[=!"CN%J/O__W8&B86H^___ +MBXTH^___BU$T.Y6,^___BT$P?!9_"#N%B/O__W8,B86(^___B96,^___BX4H +M^___BPU$Y`0(BT`X`84L^___AZ+5>PS%:#B!`@/A8'$+`4``%M>7UW#C70F`(L- +M\.($"(7)#X7'1PP!````QT<0`````.F#Z`$/A8L=[.($"(7;#X7KU(N5*/O_ +M_\=$)`0`````BT(,B00DZ(N-*/O__\=$)`0`````B85$^___BT$0B00DZ(F% +M2/O__^F#O3#[__\.#X>+E2C[__^+0A0PY#T``0``H3SD!`@9R8/A^8/!#X7` +MB8TP^___#X2+E4S[__^-1#,2B4,(B00DB50D!.B+C4S[__^)#"3HZ8N-*/O_ +M_XM!1(D$).B%P(F%3/O__P^$@#@`=2*)!"3HQP0D^M@$".B%P(F%3/O__P^$ +MBX5,^___B00DZ#N%H/O__XF%-/O__P^&B86@^___Z8V5D/O__XD4).B#P`$/ +MA(M'/(7`#X6+1U"-M;G[___'1"0(]-@$",=$)`0!!```B30DB40D#.B+A0S[ +M__^%P'1SBX60^___B30DB40D!.B#P`%T%+/O_ +M_P````#'A3S[__\`````QX4P^___`````*%$Y`0(A/&`3`/MD(!B$$! +M@\$"QD$!``^V0@*#P@&$P'7;@'G_.@^$C86D^___BY4<^___B40D*(V%K/O_ +M_XE$)"2-A8C[__^)1"0@C86@^___B40D'(V%G/O__XE$)!B-A9C[__^)1"04 +MC86H^___B40D$(V%M/O__XE$)`R-A;#[__^)1"0(QT0D!)39!`B)%"3HQP48 +MY`0(`0```(/X"`^&B[6P^___,<"%]G0@N0$```"X"@```/?A@^X!B<%U\L>% +ML/O__P````"-0/^+O;3[__^)A;#[__\QP(7_?C6)_KD!````,=MKTPJX"@`` +M`(F5!/O___?AB=.)P0.=!/O__X/N`77AQX6T^___`````(U`_XNUJ/O__XF% +MM/O__S'`A?9T(+D!````N`H```#WX8/N`8G!=?+'A:C[__\`````C4#_BXV, +M^___BY6(^___B86H^___@_D`B94@^___B8TD^___#XZ+C2#[__^^`0```#'_ +MBYTD^___:\<*B84$^___N`H```#WYHG7B<8#O03[__^#P?^#T_^)V@G*==J) +M\(GZ@\#_QX6(^___`````(/2_\>%C/O__P````"+C1S[__^)A8C[__^)E8S[ +M__^)#"3HZ8N-+/O__XU=NHN%M/O__\=$)`@/O__XN%J/O__XE$)`SHB1PDZ(F%?/O__Z'\ +MXP0(A%@/O__P4```"+A3#[__\[A8#[__]V!HF%@/O__XN%F/O__XF% +MA/O__^F+1U")1"0(BT<$BT`%M/O__P````#'A:C[__\`````QX68 +M^___`````,>%G/O__P````#'A:#[__\`````QX6(^___`````,>%C/O__P`` +M``#'A:S[__\`````@ST%I/O__P`````9P/?0(048Y`0(Z<=$)`3I +MV`0(QP0D`0```.AFQP$P`.F+E1S[__^)T8/!`F;'`C`ZQD("`.G'1"0$_-@$ +M",<$)`$```#HZ(VT)@````!5B>575E.#[!R#/?SB!`@!B47LB4WH&<`EP)@$ +M"(E$)`B)3"0$B10DZ(7`B<B)PC'`Z*'L +MX@0(A<`/A8LU!.,$"(7V#X3'1?``````C;0F`````(D\).B%P(G##X2+0T"# +M^`(/A(GV#X^#Z`%UU8M+/(7)=`R+0U"`."X/A*$DXP0(A<`/A*'`X@0(A<`/ +MA8L5S.($"(M""(/H`87`B4((#XB+`L8`"H/``8D"BT,B)PHG&B=CHH03C!`B%P`^%A?8/A(E<)`3'1"0(!``` +M`(D\).B)/"3HA<")PP^%Z(L`A<`/A8/$'%M>7UW#D(/X!'0)@_@'#X6+0R") +M!"3HB40D"(M#',<$)/#8!`B)1"0$Z,<%(.,$"`$```#ID(M#4,<$)"W9!`B) +M1"0$Z.F#?>P!#XZ+0QR)!"3HQP0D2MD$".C'!23C!`@!````Z8L=".0$"(7; +M#X7V1>@(QT7P``$```^%Z:',X@0(QP0D"@```(E$)`3HZ8L5\.($"(72#X3I +MB50D!,<$)`H```#HZ<=$)`1,V00(QP0D`0```.C'1"0$)-D$",<$)`$```#H +MC78`C;PG`````(U,)`2#Y/#_575E-1@>PX!@``BQFAH.($"(E%[#'` +MC87L_?__BWD$B87D^?__QT0D!,S;!`C'!"0`````Z,<$)`$```#HA<`/A,<% +M#.`$"%````#'!"15V00(Z(7`=`F`.``/A8V%W/G__XE$)`C'1"0$:'0(0,<$ +M)`$```#H@\`!=!0/MX7>^?__9H7`=`@/M\"C#.`$",<%#.0$"`$```"^$``` +M`,=$)`C(V00(B7PD!(D<).B#^/]T/X/H,8/X1W8PZ.O8QP4,XP0(`0```,<$ +M)%79!`CHASY__^)!"3H@^@!#X2+%1SD!`B%TG1&QP48Y`0(`0```,=$)`1@L@0( +MQP0D`@```.C'1"0$8+($",<$)`,```#HQP0DB=D$".B)!"3HH4#D!`B%P'5! +MH43D!`B%P'4XH?CC!`B%P'4OH13C!`B%P'4FH1CC!`B%P'4=H3#D!`B%P'44 +MBQTA%.,$"(7`#X6A&.,$"(7`#X3'!>3B!`B0E00( +MH0SC!`B%P'2?QP7@X@0(L+P$"(N%S/G__X7`=*R+ACY___'1"0$$.0$"(D$ +M).B+%1#D!`B)T,'X'\'H%P'0P?@)HQ#D!`CIQP0D9MD$".B%P`^%Z8/.(,<% +M\.($"`$```#IQP4,Y`0(`````,<%).0$"`$```#'!>SC!`@`````Z:'$X@0( +MH_3C!`CIQP4,XP0(`````,<%1.0$"`````#'!33D!`@`````Z<<%&.,$"`$` +M``#'!13C!`@`````Z<<%!.,$"`$```#I@^;\@\X0QP7XX@0(`0```.F#YN^# +MS@+'!?CB!`@`````Z<<%].($"`$```#I@\X!QP7XX@0(`````.G'1"0(`0`` +M`,=$)`3,VP0(QP0D7=D$".CIQP4PY`0(`0```,<%%.0$"`````#IQP4,XP0( +M`0```,<%1.0$"`````#'!1#C!`@`````Z<<%-.0$"`$```#'!43D!`@````` +MQP4,XP0(`````.G'!0SD!`@`````QP4DY`0(`````,<%[.,$"`````#IQP4$ +MY`0(`0```,<%Z.,$"`````#'!3CD!`@`````Z<<%%.,$"`$```#'!1CC!`@` +M````Z<<%^.,$"`$```#IQP4(XP0(`0```.G'!0SD!`@!````QP4DY`0(```` +M`,<%[.,$"`````#IQP44Y`0(`0```,<%,.0$"`$```#IQP4\Y`0(`0```.G' +M!0#C!`@!````Z<<%$.,$"`$```#'!0SC!`@`````QP5$Y`0(`````.G'!43D +M!`@!````QP4,XP0(`````,<%$.,$"`````#IQP7\XP0(`````,<%Z.($"`$` +M``#IQP5`Y`0(`0```.G'!?SC!`@!````Z<<%_.($"`$```#IQP7LX@0(`0`` +M`,<%!.,$"`````#IQP7HXP0(`0```,<%!.0$"`````#'!3CD!`@`````Z<<% +M#.0$"`````#'!23D!`@`````QP7LXP0(`0```.G'!0CD!`@!````Z<<%'.,$ +M"`$```#IQP4XY`0(`0```,<%!.0$"`````#'!>CC!`@`````Z<<%(.0$"`$` +M``#IZ(7`#X6A].($"(7`#X7'!?#B!`@!````Z8L=&.,$"(7;#X6+#03D!`B% +MR0^$QP7DX@0(8)<$".FA&.,$"(7`#X6A!.0$"(7`#X3'!>3B!`C0EP0(Z:$0 +MXP0(A3B!`B@F`0(Z<<%X.($ +M"$"]!`CIC9WD^?__B5PD!,<$)'K9!`CHB5PD!,<$)'W9!`BC\.,$".B)7"0$ +MQP0D@-D$"*,LY`0(Z(E<)`3'!"2#V00(HTCD!`CHB5PD!,<$)(;9!`BC*.0$ +M".B%P*,`Y`0(#X2A\.,$"(7`#X2+'2SD!`B%VP^$BPT`Y`0(A3B!`BPE@0(Z8L5..0$"(72=1BAZ.,$"(7`=#S'!>3B!`A`E@0(Z<<%Y.($ +M"-"6!`CIQP7DX@0(0)<$".G'!>3B!`A@F`0(Z<<%Y.($"/"7!`CIB5PD!,<$ +M).W8!`CHHP#D!`CID)"0D)"0D)"0D)!5B>6#[!B%P'0]H0#D!`C'1"0(H+($ +M",=$)`0!````B00DZ+B@L@0(B40D"*%(Y`0(QT0D!`$```")!"3HR<.A`.0$ +M",=$)`@`N`0(QT0D!`$```")!"3HN`"X!`CKP9"-="8`58GE4X/L%(M="(G8 +MZ(D<),=$)`0`````Z.B)7"0$B00DZ(/$%%M=PY"-M"8`````58GE@^PHBT4( +MQT0D"`$```#'!"0!````B$7_C47_B40D!.@QP,G#D(UT)@!5B>575E.#["R+ +M10B%P`^$BT4(,?^)!"3HBQ5@W`0(9L=%V@``QT7<`````(E5X(E%U.L\C70F +M``^^PH/H,&:#?=H`B0,/A&;'1=H!`(/&`8/#!(/^`G5%@\`:.,$"`````"-!#\Y1=1W.8M5X`^V`HA%\@^V0@&(1?.-!'\Q +M]HT'03#[["B40D +M!,<$)#37UW#QT4(S-L$".E5B>564XG#C31`@^P0 +MBQ2U:.,$"(72#X6+!+5@XP0(@_C_=#B)1"0(H?#C!`C'1"0$`````(D$).B% +MP'0;QT0D"`"X!`C'1"0$`0```(D$).B-=@"-!%N+!(5DXP0(@_C_=#6)1"0( +MH2SD!`C'1"0$`````(D$).B%P'08QT0D"`"X!`C'1"0$`0```(D$).B#Q!!; +M7EW#D(UT)@"A*.0$",=$)`@`N`0(QT0D!`$```")!"3HZ8VT)@````"-O"<` +M````#[?`B<)5@>(`\```B>6#[`B!^@!````/A'Y1@?H`H```#X2!^@#```!T +M8H'Z`&````^$,=*H271?]L0(#X7VQ`0/A+@(````C70F`.BZ`0```.LXC70F +M`('Z`!```'18@?H`(```B?9UO;@&````Z+H!````R8G0P[@"````Z+H!```` +MR8G0P[@!````Z+H!````R8G0P[@%````Z+H!````R8G0PXGVN`,```#HN@$` +M``#)B=##J`)T./;$`G01N`D```#HN@$```#KI[@*````Z+H!````ZY:X!``` +M`.BZ`0```.N%,<#HN@$```#IN`<```#HN@$```"0Z8UT)@"-O"<`````58GE +M4X/L=(E%F*&@X@0(B47X,<"A+.`$"(7`#XBA1.,$"(7`=':+'?3C!`B%VP^$ +MC468B00DZ(E<)`B-7:C'1"0$4````(D<)(E$)`SHHSC!`B%R70)B44(7>F+%0SD!`B% +MTG0)B44(7>F)10A=Z9!5B>6#[`BAP.($"(M-"(7`=2"+%!^@`0```/A('Z`$```(UT)@!T/JA)=,:AP.($ +M"(7`#X6+%6#[#B)7?2)PXE]_(G/B77XBW!,H4#D!`C'1>P`````A<`/A:'X +MXP0(A+0U")!"3HBTWLC1P(H1SD!`B%P'4W +MBSTPY`0(A?]T"P^W1@CH`<.)V(MU^(M=](M]_(GL7<.+0U")!"3HBU7LC1P0 +MZ\F%_W3%,<#HZ[RA$.0$"(/H`8E%X(G"BT8XP?H?`47@H1#D!`B)5>2+5CP1 +M5>2+3>2)PL'Z'XE4)`R+5>")3"0$B40D"(D4).B)?"0$QP0D>-L$"(E$)`B) +M5"0,Z`%%[.F+1@2)5"0$QP0D7<.)5"0$QP0D"@```.CKHXUV`%6)Y5=64X/L +M/(M%"(,]&.0$"`$9TH/B!XE%T(M`"(/"`3L%'.`$"(E5Z`^/BUW0QT7<```` +M`(L3A=)T)(L-0.,$"(M"#(/P`0M"$'0,BT72)5=B+3P!````BUW0H4#C!`B+4R"+2Q"+7=B+!)CHBQ4TY`0(A=(/A(/#`8M-W(E= +MV#E-V`^-BU7H`<:-'!8C7=0Y^W]>C70F`(L--.0$"(7)=`R+1P/C8L5 +MP.($"(72=5"+#B-'!8C7=0Y^WZFBTW,.4WL=&*#1>P!`WWPZ8GV@ST8Y`0( +M`8G>BQ7,X@0(&<"#X.F#P"")5"0$B00DZ.NX.T$8?`B`^@J-=@!UH(E,)`2) +MWHD4).CKFXM5X`%5V(M-W#E-V`^,H<#B!`B%P'4UBQ7,X@0(BT((@^@!A<") +M0@AX.8L"Q@`*@\`!B0*#1>0!BUW@.5WD#X6#Q#Q;7E]=PZ',X@0(QP0D"@`` +M`(E$)`3HZ]&)5"0$QP0D"@```.CKOXL]1.0$"(7_=0B%R0^$BTW0BQT0Y`0( +MBU$$QP0D?ML$"(/J`8T,&C'2B7UWIP>`" +MB40D!*%`XP0(B00DZ(7`B<)T%HM-T(D50.,$"(M!"*,575E.#[`R+=0B+'H7;#X0Q_^L7UW#H575E.!['P(``"+10B+%:#B!`B)5?`QTHLPB86D +M]___A?8/A(M&/(7`#X7'A:CW__\`````D(M&#(/P`0M&$`^$BQU`Y`0(BWY, +MA=L/A8L-^.,$"(7)#X6-3(`\```@?H` +M(```#X2!^@!@```/A('Z`.````^$BP`[!2C@!`@/A(M&/(7`#X6+1E"-G%(U-S(N5I/?__XM#!(E$)!R+0AR)1"08 +MBP.)1"04BT(LB40D$`^W1PJ)1"0,BT(DB4PD!,<$)(S;!`B)1"0(Z*$\Y`0( +MA<`/A:$(Y`0(A<`/A0^W1P@E`/```#T`(```#X0]`&````^$BXVD]___BT

    ")5"00B40D#,=$)`BFVP0(QT0D!!````")'"3HBX6L]___B5PD +M",<$)+O;!`B)1"0$Z*$$Y`0(A<`/A(M'&.BA'.0$"(7`#X0/MT<(Z(F%J/?_ +M_^F+0PR+C:3W__^)1"0(BT$8QP0DH-L$"(E$)`3HZ8UV`(M#"(N5I/?__XE$ +M)`B+0A3'!"2@VP0(B40D!.CIBPT0Y`0(C4'_BRL````BWT,C95P____BW4(H:#B!`B)1?`QP,=$)`B`````QT0D!``` +M``")%"3HA?_'A6#___\`````=%^-E7#___^-A6S___^)5"0,B7PD"(ET)`2) +M!"3HA<")PW0Y@_O_=&V#^_X/A(N5;/___X'Z_P```'=*H=#B!`B+1)`TJ0`` +M!`!T*8.%8/___P$!WH7_=:&+5?`S%:#B!`B+A6#___]U9H'$K````%M>7UW# +MBX5@____C028B85@____Z\V)%"3HZ[6)]HV%AT.($"(M$F#2I```$``^$,?:%_W\WZV:-="8`BQ7,X@0(BX5< +M____#[8,!HM""(/H`87`B4((#XB+`H@(@\`!B0*#Q@$Y]W0KH<#B!`B%P'3& +MHAT.($"(M$F#2)PH'B````X`^$B=#!Z!X!O5S___\!A6#____I.T(8 +M#[;9?`F`^PH/A8E4)`2)'"3HZ8L5P.($"(72#X6+%RL````BT4(BQ6@X@0(B57P,=+'1"0(@``` +M`,=$)`0`````B85<____C85P____B00DZ,>%8/___P````"+E5S___^-A7#_ +M__^)1"0,C85L____QT0D"`8```")!"2)5"0$Z(7`B<8/A(/^_@^$@_[_#X0Q +MVX7V?S/K78L5S.($"(N%7/___P^V#`.+0@B#Z`&%P(E""`^(BP*("(/``8D" +M@\,!.=YT+(L]P.($"(7_=,6AS.($"(N57/___XE$)`0/M@03@\,!B00DZ#G> +M==2+G6S___\!M5S___^!^_\```!W<*'0X@0(BT28-*D```0`#X0QP(7;="B! +M^_\````/AZ'0X@0(BT28-(G"@>(```#@#X2)T,'H'@&%8/___^D[0A@/MOE\ +M"HGX/`H/A8E4)`2)/"3HZ8D<).B0ZXZ-A7#____'1"0(@````,=$)`0````` +MB00DZ*'`X@0(A<`/A8L5S.($"(N%7/___P^V"(M""(/H`87`B4((#XB+`H@( +M@\`!B0*#A5S___\!@X5@____`>F+E5S____'!"3TV`0(B50D!.@!A6#___^+ +M5?`S%:#B!`B+A6#___]U:X'$K````%M>7UW#)0``!`"#^`$9P(/(`>F)'"3H +MZ:',X@0(BY5<____B40D!`^V`HD$).CI.T(8#[;9?`F`^PH/A8E4)`2)'"3H +MZ>B-=@"-O"<`````58GE5U93@>RL````BT4(BQ6@X@0(B57P,=+'1"0(@``` +M`,=$)`0`````B858____C85P____B00DZ,>%8/___P````"+E5C___^-A7#_ +M__^)1"0,C85L____QT0D"`8```")!"2)5"0$Z(7`B85<____#X2+A5S___^# +MP`*#^`$/AHN=;/___X'[_P````^'H=#B!`B+1)@TJ0``!``/A(/[(@^$@_M< +M#X2+O5S___^%_WYO,=OK-8L5S.($"(N%6/___P^V#`.+0@B#Z`&%P(E""`^( +MBP*("(/``8D"@\,!.YU<____=#"+-<#B!`B%]G3!H@>`85@____@[U<_____@^$@[U<_____P^$BY5< +M____`958____Z8.]7/____\/A;\!````,?;ID(UT)@"+%#P#")!"3HH<#B!`B%P`^$C;0F`````*',X@0(B40D!(G8@^`'@\`PB00D +MZ.F)]CM"&'P)@/D*#X6)5"0$B0PDZ.F0.T(8#XV)5"0$QP0D7````.CIB?8[ +M0AA\"8#Y"@^%B50D!(D,).CID#M"&'P)@/D*#X6)5"0$B0PDZ.F+#>SC!`B% +MR700A=MX#('[_P````^.B[U<____A?\/CX.]7/____X/A8M5\#,5H.($"(N% +M8/___P^%@<2L````6UY?7<.+A5C___^)!"3HB575H/L,(M5 +M#(M%"(MU$(M]%(E5W(M-W(E%V,=%T`````")\,=%U`````")^H7)QT7D```` +M``^(A?\/B(G7B<:+5=B)P8M%W(7_B57PB47L=10YQG9!B="+5>SW]HG!,<#K +M$XUV`#M]['9/,2)1=2+1="+5=2%R70']]B#T@#W +MVH/$,%Y?7<.%]G4+N`$````QTO?VB<&+1>R)^O?QB<:+1?#W\8G!B?#KO`^] +MQX/P'XE%Z'5$.7WL=P4Y=?!RG+D!````,<#KGO==V(-5W`#W7=R%_\=%Y/__ +M__\/B9"-="8`B?")^O?8@](`]]KW5>3IN"````")\BM%Z(G!T^H/MDWHB47T +MB?B)UXM5[-/@"<>+1?#3Y@^V3?33Z`^V3>C3X@^V3?0)T(M5[(E%S-/J]_>) +M5&-X9'AB>&5G961A8F%G86-A9`````!,4T-/3$]24R!S:&]U;&0@=7-E +M(&-H87)A8W1ED`0(KI`$"+Z0!`C.D`0(WI`$".Z0!`C^D`0(#I$$"!Z1!`@ND00( +M/I$$"$Z1!`A>D00(;I$$"'Z1!`B.D00(GI$$"*Z1!`B^D00(SI$$"-Z1!`CN +MD00(_I$$"`Z2!`@>D@0(+I($"#Z2!`A.D@0(7I($"&Z2!`A^D@0(CI($")Z2 +M!`BND@0(OI($",Z2!`C>D@0([I($"/Z2!`@.DP0('I,$""Z3!`@^DP0(3I,$ +M"%Z3!`ANDP0(?I,$"(Z3!`B>DP0(KI,$"+Z3!`C.DP0(WI,$".Z3!`C^DP0( +M#I0$"!Z4!`@NE`0(/I0$"$Z4!`A>E`0(````````````)$9R965"4T0Z('-R +M8R]L:6(O8W-U+VDS.#8M96QF+V-R=#%?'`@)```)$9R965"4T0Z('-R8R]L:6(O8W-U +M+V-O;6UO;B]C'`@ +M)`!'0T,Z("A'3E4I(#0N,BXR(#(P,#6YS>6T`+F1Y;G-T<@`N9VYU+G9E6X`+G)E;"YP;'0`+FEN:70`+G1E>'0`+F9I;FD`+G)O9&%T +M80`N96A?9G)A;65?:&1R`"YD871A`"YE:%]F`(` +M``0`````````!`````0````G````"P````(```"\@P0(O`,``)`%```%```` +M`0````0````0````+P````,````"````3(D$"$P)``!$`P`````````````! +M`````````#<```#___]O`@```)",!`B0#```L@````0``````````@````(` +M``!$````_O__;P(```!$C00(1`T``#`````%`````0````0`````````4P`` +M``D````"````=(T$"'0-``!`````!``````````$````"````%P````)```` +M`@```+2-!`BT#0``,`(```0````+````!`````@```!E`````0````8```#D +MCP0(Y`\``!$```````````````0`````````8`````$````&````^(\$"/@/ +M``!P!``````````````$````!````&L````!````!@```'"4!`AP%```#$0` +M````````````$`````````!Q`````0````8```!\V`0(?%@```P````````` +M``````0`````````=P````$````"````B-@$"(A8``".!``````````````$ +M`````````'\````!`````@```!C=!`@870``'```````````````!``````` +M``"-`````0````,`````X`0(`&```#````````````````0`````````DP`` +M``$````"````,.`$"#!@``!8```````````````$`````````)T````&```` +M`P```(C@!`B(8```V`````4`````````!`````@```"F`````0````,```!@ +MX00(8&$```@```````````````0`````````K0````$````#````:.$$"&AA +M```(```````````````$`````````+0````!`````P```'#A!`AP80``!``` +M````````````!`````````"Y`````0````,```!TX00(=&$``"0!```````` +M``````0````$````O@````@````#````H.($"*!B``"L`0`````````````@ +M`````````,,````!``````````````"@8@``00,``````````````0`````` +M```!`````P``````````````X64``,P```````````````$````````````5 +M8```6%```!20```3Z```$^@```_D```HH```$U@``!&(```0B```2?```!*H +M```2J```%!@``!08```3:```%"@``!0H```4*```$[@``!%X```2*```$[@` +M`!*8```16```%"@``!.X```0"```$[@``!#8```4&```$1@``!*H```3>``` +M$2@``!'(```4&```$.@``!*X```1R```$-@``!*H```4&```$V@``!)(```3 +MN```$J@``!08```2J```%!@``!*H```4&```$K@``!*H```4&```$X@``!.( +M```3V```$R@``!)X```98```$N@``#?````0&```$G@``!E@```1V```$N@` +M`!)H```1>```$B@``!(H```WP```$!@``!#(```32```$X@``!.(```3J``` +M$Y@``!"(```12```$@@``$FP```0B```$#@``!"(```3F```$(@``!+(```2 +MV```$M@``!"(```RT```)@```"8````36```$S@``!"(```3"```$\@``!18 +M```46```%%@``!18```46```$#@``!18```2.```$C@``!(X```Q\```$M@` +M`!0(```0F```$&@``!08```2*```$B@``!"X```2.```$+@``!(X```2.``` +M-#```#0P```T,```-#```#0P```T,```-#```#0P```T,```-#```#0P```1 +MN```$6@``!#X```0>```$$@``!+X```3V```$,@``!-(```0R```$T@``!#( +M```32```$T@``!-(```32```$,@``!#(```0R```$,@``!-(```U$```-\`` +M`#A@```WP```,?```%;````2B```$H@``#N````0R```$T@``#N````0R``` +M$T@``!#(```32```$H@``!&8```2N```$H@``!08```[@```$,@``!#(```3 +M2```$T@``!(8```2J```$:@``!0X```1.```$_@``!*(```0J```$H@``#9@ +M```WP```,?```!*(```2J```$H@``#9@```U$```$H@``!*(``!6P```$H@` +M`!*(```0R```.&```!*H```42```$H@``#?````2J```$H@``#9@```V8``` +M$J@``!*H```2:```$7@``!`H```32```$_@``!*X```2:```$K@``!&H```2 +M:```$K@``!/8```3&```$U@``!)8```06```$0@``!)8```3V```$E@``!!8 +M```0R```$T@``!)8```1"```$,@``!#(```1"```$T@``!-(```0R```$T@` +M`!/8```26```$%@``!#(```32```$0@``!)8```2B```$0@``!#(```32``` +M$]@``!)8```06```$,@``!#(```0R```$,@``!#(```32```$T@``!-(```3 +M2```%!@``!-(```1"```$E@``!'H```1"```$,@``!#(```32```$T@``!/8 +M```5,```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^```#_@` +M``_X```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^``` +M#_@```_X```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/ +M^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X +M```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^```#_@` +M``_X```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^``` +M#_@```_X```/^```#_@``!'X```5D```$?@``!9````1^```%M```!'X```7 +M8```$?@``!?P```1^```$?@``!B@```A1```(5L``"#]```=7@``'6H``!YQ +M```>4```'5```!U0```>B@``'S$``!^B```EJ0``'LT``![-```?!0``&H$` +M`"$;```CMP``)?0``!JD```=5P``&J0``!JD```<````'/$``!S^```<_@`` +M)>```"7@```<5P``'%<``"2R```@R0``''```!QP```@/P``'^D``!XR```= +MN0``'C(``!FR```EJ0``)<<``"6]```DU```)1H``!HQ```=ZP``(#4``"2- +M```C00``(Y@``")U```A\@``(:,``"B"```G=P``*`@``"=H```GP```)X`` +M`"A&```GV```*"P``"A9```F@```)H```":2```H;@``)H```":````F@``` +M)Q```"<0```F<@``)H```"9R```F^0``)H```":^```F^0``*8L``#$P```O +MOP``+#H``#"!```K[0``+`<``#`3```P5```,#P``"_H```P8P``*QP``"L2 +M```K'```*?\``"HF```I8P``*6,``"EC```I8P``*6,``"EC```I8P``*6,` +M`"EC```I8P``*6,``"EC```I8P``*6,``"EC```I8P``*6,``"EC```I8P`` +M*6,``"EC```I8P``*6,``"EC```I8P``*6,``"EC```I8P``*6,``"EC```I +M8P``*6,``"EC```I8P``*6,``"EC```IVP``*=L``"G;```KHP``,6T``"NM +M```K0@``,4P``"NM```KP```*ZT``"NM```KP```,Z```VF```-I@``#:8```V@0``-I@``#:8 +M```VF```-I@``%$0``!+(```3H```#ES```Y)@``.?D``#I*```[4@``.:@` +M`#HJ```YQ```.+(``#KB```ZP@``.OX``#IF```[-@``.J(``#L:```Y%0`` +M.9<``#GH```Y8@``.-H``#R(```[LP``.ZH``$`\``!`*@``/^L``#_K```_ +MN@``/X0``#]R```_A```/X0``#YT```^K0``/DT``#XT```^-```/+```#UP +M``!!5```09(``$"@``!!$```11P``$4<``!$]P``1J@``$95``!#5```0U0` +M`$-4``!(>P``1_4``$@U``!)!@``21H``$CC``!(Q0``1C```$8(``!%<``` +M17```$>P``!%WP``1^4``$?3``!%]```1O```$<```!&T```2,X``$(```!) +MI0``0?4``$>```!$4P``1((``$2"``!#M```0Z<``$(N``!"(```1/<``$2U +M``!(1P``2(X``$3)``!%N```1$8``$1U``!$=0``0L$``$-4``!#`P``1S`` +M`$-4``!"@```1,D``$-,``!$]P``0U0``$-4``!#`P``0P,``$@U``!(-0`` +M0U0``$K]``!-I0``3.0``$UO``!-1```3*,``$R!``!-\0``3=\``$MH``!, +M`0``3`H``$U5``!-_@``2V@``$W%``!.'```2V@``$O)``!,T@``3CH``$Y4 +M``!.<@``31,``$QP``!,70``3,@``$S2``!-"0``31,``$V>``!-E```39X` +M`%"%``!0:0``4`(``$_4``!.R```4+,``%"A``!.R```3S<``$]```!0P``` +M4-\``$[(``!/R0``3[8``%!6``!030``4%8``%44``!2L@``56D``%3?``!4 +MWP``5-\``%5&``!60```5B@``%44``!5=@``45@``%4T``!3J```5(```%/A +M``!48```5!```%2@``!40```5,```%*'``!2T```4OX``%,V``!3;@``4Y8` +M`%,@``!3*0``4N<``%+Q``!36```4V$``%.-``!3E@``5:```%+$``!2E``` +M5KH``%()``!2$@``4;T``%%8``!4^0``5F0``%9^``!6G```4H<``%*'``!2 +M;@``5>P``%7B``!5[```5A,``%8<``!7H@``5\```%<&``!7!@``5T```%=` +M`'__[(*_<*GBTO8J#[&TS@MGB4R]0=<':N.(W\G9G;.:/7*.,11&`00&``0) +MP)Q>A&R'N"<`!PL!``0!``$``0`4`P,!&P0!`0`"`0,"``0%!@S`G%[`G%[` +MG%[`P&H`"`H!/7V2E0``!0$1#P!X`#@`-@!E`'@`90```!0*`0``+4,K<;.= ++`14&`0`A```````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_copy_lzma.7z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_copy_lzma.7z.uu new file mode 100644 index 0000000..ff1ce4a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_copy_lzma.7z.uu @@ -0,0 +1,568 @@ +begin 644 test_read_format_7zip_bcj2_copy_lzma.7z +M-WJ\KR<<``-+E]7GI6(```````!Y`````````%QS)"Q_14Q&`0$!"0`````` +M`````@`#``$```!PE`0(-````+!F````````-``@``<`*``:`!D`!@```#0` +M```T@`0(-(`$".````#@````!0````0````#````%`$``!2!!`@4@00(%0`` +M`!4````$`````0````$``````````(`$"`"`!`@T70``-%T```4`````$``` +M`0````!@````X`0(`.`$")@"``!,!```!@`````0```"````B&```(C@!`B( +MX`0(V````-@````&````!`````0````L`0``+($$""R!!`@8````&`````0` +M```$````4.5T9!A=```8W00(&-T$"!P````<````!`````0````O;&EB97AE +M8R]L9"UE;&8N@(``!(```"]`@```````,\!```2 +M````?`(```````#.````$@```(8"````````0P```!(```!:`0```````&<& +M```2````>`$````````J````$@```&X"````````/@```!(````:`P``F.($ +M"``````0`/'_80$```````!5````$@```#,```!TX00(`````!$`\?\M`P`` +M3.0$"``````0`/'_BP(```````!B`P``$@```"L!``#4X@0(!````!$`%P`/ +M`0```````)L(```2````Y`$``-CB!`@$````$0`7`%,!`````````````!(` +M``"%`0```````!H````2````A`(````````K````$@```+0"````````*0`` +M`!(````4`0`````````````2````Y0(```````"+````$@```*$````````` +M8````!(```!)```````````````@````&P$```````!]````$@```$(!```` +M`````````!(```"!`````````!0!```2`````&QI8G5T:6PN7!E`'-T'0`@<` +M``(`.P,```````"@X@0(!18``,#B!`@%)0``Q.($"`4K``#(X@0(!34``,SB +M!`@%/```T.($"`4^``#4X@0(!4L``-CB!`@%30``@.$$"`E\M#G! +M<]N-=@#KJXVT)@````"-O"<`````58GEBU4,BT4(B54(B44,7>F-="8`C;PG +M`````%6)Y8/L"(D<)(ET)`2+=0B+70R+5DR+2TR+0B@Y02A^$+@!````BQPD +MBW0D!(GL7<-\#XM"+#E!+'_FD(UT)@!]![C_____Z]V+0U")10R+1E")10B+ +M'"2+="0$B>Q=Z8VV`````(V_`````%6)Y8M5#(M%"(E5"(E%#%WIC70F`(V\ +M)P````!5B>6#[`B)'"2)="0$BW4(BUT,BU9,BTM,BT)0.4%0?A"X`0```(L< +M)(MT)`2)[%W#?`^+0E0Y051_YI"-="8`?0>X_____^O=BT-0B44,BT90B44( +MBQPDBW0D!(GL7>F-M@````"-OP````!5B>6+50R+10B)50B)10Q=Z8UT)@"- +MO"<`````58GE@^P(B1PDB70D!(MU"(M=#(M63(M+3(M"&#E!&'X0N`$```"+ +M'"2+="0$B>Q=PWP/BT(<.4$F-="8` +MC;PG`````%6)Y8/L"(D<)(ET)`2+=0B+70R+5DR+2TR+0B`Y02!^$+@!```` +MBQPDBW0D!(GL7<-\#XM")#E!)'_FD(UT)@!]![C_____Z]V+0U")10R+1E") +M10B+'"2+="0$B>Q=Z8VV`````(V_`````%6)Y8M5#(M%"(E5"(E%#%WIC70F +M`(V\)P````!5B>6+10B+50R+0%")10R+0E")10A=Z9"-="8`58GEBT4,BT!0 +MB44,BT4(BT!0B44(7>F0D)"0D%6)Y8/L"(D<)(ET)`2+10B+30R+`(M00(/Z +M!W1SBQF+2T"#^0=T:8/Z"G1,@_D*=$%E/O_ +M_P````"%P'4-H43D!`B%P`^$QX5`^___`0```,<$)-S8!`CHQX6(^___```` +M`,>%C/O__P````#'A:#[__\`````QX6<^___`````,>%F/O__P````"%P(G# +MQX6H^___`````,>%K/O__P````#'A;#[__\`````QX6T^___`````,>%I/O_ +M_P````!T"8`X``^%B[T4^___A?\/A(N%$/O__XN]%/O__\>%+/O__P````#' +MA3#[__\`````@^`"QX4\^___`````,>%3/O__P````")A0S[___I@_@*#X2+ +MM1C[__^%]@^$BT=0@#@N#X2+1RP[A:S[__]V!HF%K/O__XL5).0$"(72=0J+ +M->SC!`B%]G0=B40D!(M'4(D$).@[A:S[__]V!HF%K/O__XN=0/O__X7;#X2+ +M5TR)T(M(/(N%M/O__XF5*/O__XM2.(G&P?X?.?%\#'\$.<)V!HF5M/O__XN5 +M*/O__XM"!#N%L/O__W8&B86P^___BXTH^___#[=!"CN%J/O__W8&B86H^___ +MBXTH^___BU$T.Y6,^___BT$P?!9_"#N%B/O__W8,B86(^___B96,^___BX4H +M^___BPU$Y`0(BT`X`84L^___AZ+5>PS%:#B!`@/A8'$+`4``%M>7UW#C70F`(L- +M\.($"(7)#X7'1PP!````QT<0`````.F#Z`$/A8L=[.($"(7;#X7KU(N5*/O_ +M_\=$)`0`````BT(,B00DZ(N-*/O__\=$)`0`````B85$^___BT$0B00DZ(F% +M2/O__^F#O3#[__\.#X>+E2C[__^+0A0PY#T``0``H3SD!`@9R8/A^8/!#X7` +MB8TP^___#X2+E4S[__^-1#,2B4,(B00DB50D!.B+C4S[__^)#"3HZ8N-*/O_ +M_XM!1(D$).B%P(F%3/O__P^$@#@`=2*)!"3HQP0D^M@$".B%P(F%3/O__P^$ +MBX5,^___B00DZ#N%H/O__XF%-/O__P^&B86@^___Z8V5D/O__XD4).B#P`$/ +MA(M'/(7`#X6+1U"-M;G[___'1"0(]-@$",=$)`0!!```B30DB40D#.B+A0S[ +M__^%P'1SBX60^___B30DB40D!.B#P`%T%+/O_ +M_P````#'A3S[__\`````QX4P^___`````*%$Y`0(A/&`3`/MD(!B$$! +M@\$"QD$!``^V0@*#P@&$P'7;@'G_.@^$C86D^___BY4<^___B40D*(V%K/O_ +M_XE$)"2-A8C[__^)1"0@C86@^___B40D'(V%G/O__XE$)!B-A9C[__^)1"04 +MC86H^___B40D$(V%M/O__XE$)`R-A;#[__^)1"0(QT0D!)39!`B)%"3HQP48 +MY`0(`0```(/X"`^&B[6P^___,<"%]G0@N0$```"X"@```/?A@^X!B<%U\L>% +ML/O__P````"-0/^+O;3[__^)A;#[__\QP(7_?C6)_KD!````,=MKTPJX"@`` +M`(F5!/O___?AB=.)P0.=!/O__X/N`77AQX6T^___`````(U`_XNUJ/O__XF% +MM/O__S'`A?9T(+D!````N`H```#WX8/N`8G!=?+'A:C[__\`````C4#_BXV, +M^___BY6(^___B86H^___@_D`B94@^___B8TD^___#XZ+C2#[__^^`0```#'_ +MBYTD^___:\<*B84$^___N`H```#WYHG7B<8#O03[__^#P?^#T_^)V@G*==J) +M\(GZ@\#_QX6(^___`````(/2_\>%C/O__P````"+C1S[__^)A8C[__^)E8S[ +M__^)#"3HZ8N-+/O__XU=NHN%M/O__\=$)`@/O__XN%J/O__XE$)`SHB1PDZ(F%?/O__Z'\ +MXP0(A%@/O__P4```"+A3#[__\[A8#[__]V!HF%@/O__XN%F/O__XF% +MA/O__^F+1U")1"0(BT<$BT`%M/O__P````#'A:C[__\`````QX68 +M^___`````,>%G/O__P````#'A:#[__\`````QX6(^___`````,>%C/O__P`` +M``#'A:S[__\`````@ST%I/O__P`````9P/?0(048Y`0(Z<=$)`3I +MV`0(QP0D`0```.AFQP$P`.F+E1S[__^)T8/!`F;'`C`ZQD("`.G'1"0$_-@$ +M",<$)`$```#HZ(VT)@````!5B>575E.#[!R#/?SB!`@!B47LB4WH&<`EP)@$ +M"(E$)`B)3"0$B10DZ(7`B<B)PC'`Z*'L +MX@0(A<`/A8LU!.,$"(7V#X3'1?``````C;0F`````(D\).B%P(G##X2+0T"# +M^`(/A(GV#X^#Z`%UU8M+/(7)=`R+0U"`."X/A*$DXP0(A<`/A*'`X@0(A<`/ +MA8L5S.($"(M""(/H`87`B4((#XB+`L8`"H/``8D"BT,B)PHG&B=CHH03C!`B%P`^%A?8/A(E<)`3'1"0(!``` +M`(D\).B)/"3HA<")PP^%Z(L`A<`/A8/$'%M>7UW#D(/X!'0)@_@'#X6+0R") +M!"3HB40D"(M#',<$)/#8!`B)1"0$Z,<%(.,$"`$```#ID(M#4,<$)"W9!`B) +M1"0$Z.F#?>P!#XZ+0QR)!"3HQP0D2MD$".C'!23C!`@!````Z8L=".0$"(7; +M#X7V1>@(QT7P``$```^%Z:',X@0(QP0D"@```(E$)`3HZ8L5\.($"(72#X3I +MB50D!,<$)`H```#HZ<=$)`1,V00(QP0D`0```.C'1"0$)-D$",<$)`$```#H +MC78`C;PG`````(U,)`2#Y/#_575E-1@>PX!@``BQFAH.($"(E%[#'` +MC87L_?__BWD$B87D^?__QT0D!,S;!`C'!"0`````Z,<$)`$```#HA<`/A,<% +M#.`$"%````#'!"15V00(Z(7`=`F`.``/A8V%W/G__XE$)`C'1"0$:'0(0,<$ +M)`$```#H@\`!=!0/MX7>^?__9H7`=`@/M\"C#.`$",<%#.0$"`$```"^$``` +M`,=$)`C(V00(B7PD!(D<).B#^/]T/X/H,8/X1W8PZ.O8QP4,XP0(`0```,<$ +M)%79!`CHASY__^)!"3H@^@!#X2+%1SD!`B%TG1&QP48Y`0(`0```,=$)`1@L@0( +MQP0D`@```.C'1"0$8+($",<$)`,```#HQP0DB=D$".B)!"3HH4#D!`B%P'5! +MH43D!`B%P'4XH?CC!`B%P'4OH13C!`B%P'4FH1CC!`B%P'4=H3#D!`B%P'44 +MBQTA%.,$"(7`#X6A&.,$"(7`#X3'!>3B!`B0E00( +MH0SC!`B%P'2?QP7@X@0(L+P$"(N%S/G__X7`=*R+ACY___'1"0$$.0$"(D$ +M).B+%1#D!`B)T,'X'\'H%P'0P?@)HQ#D!`CIQP0D9MD$".B%P`^%Z8/.(,<% +M\.($"`$```#IQP4,Y`0(`````,<%).0$"`$```#'!>SC!`@`````Z:'$X@0( +MH_3C!`CIQP4,XP0(`````,<%1.0$"`````#'!33D!`@`````Z<<%&.,$"`$` +M``#'!13C!`@`````Z<<%!.,$"`$```#I@^;\@\X0QP7XX@0(`0```.F#YN^# +MS@+'!?CB!`@`````Z<<%].($"`$```#I@\X!QP7XX@0(`````.G'1"0(`0`` +M`,=$)`3,VP0(QP0D7=D$".CIQP4PY`0(`0```,<%%.0$"`````#IQP4,XP0( +M`0```,<%1.0$"`````#'!1#C!`@`````Z<<%-.0$"`$```#'!43D!`@````` +MQP4,XP0(`````.G'!0SD!`@`````QP4DY`0(`````,<%[.,$"`````#IQP4$ +MY`0(`0```,<%Z.,$"`````#'!3CD!`@`````Z<<%%.,$"`$```#'!1CC!`@` +M````Z<<%^.,$"`$```#IQP4(XP0(`0```.G'!0SD!`@!````QP4DY`0(```` +M`,<%[.,$"`````#IQP44Y`0(`0```,<%,.0$"`$```#IQP4\Y`0(`0```.G' +M!0#C!`@!````Z<<%$.,$"`$```#'!0SC!`@`````QP5$Y`0(`````.G'!43D +M!`@!````QP4,XP0(`````,<%$.,$"`````#IQP7\XP0(`````,<%Z.($"`$` +M``#IQP5`Y`0(`0```.G'!?SC!`@!````Z<<%_.($"`$```#IQP7LX@0(`0`` +M`,<%!.,$"`````#IQP7HXP0(`0```,<%!.0$"`````#'!3CD!`@`````Z<<% +M#.0$"`````#'!23D!`@`````QP7LXP0(`0```.G'!0CD!`@!````Z<<%'.,$ +M"`$```#IQP4XY`0(`0```,<%!.0$"`````#'!>CC!`@`````Z<<%(.0$"`$` +M``#IZ(7`#X6A].($"(7`#X7'!?#B!`@!````Z8L=&.,$"(7;#X6+#03D!`B% +MR0^$QP7DX@0(8)<$".FA&.,$"(7`#X6A!.0$"(7`#X3'!>3B!`C0EP0(Z:$0 +MXP0(A3B!`B@F`0(Z<<%X.($ +M"$"]!`CIC9WD^?__B5PD!,<$)'K9!`CHB5PD!,<$)'W9!`BC\.,$".B)7"0$ +MQP0D@-D$"*,LY`0(Z(E<)`3'!"2#V00(HTCD!`CHB5PD!,<$)(;9!`BC*.0$ +M".B%P*,`Y`0(#X2A\.,$"(7`#X2+'2SD!`B%VP^$BPT`Y`0(A3B!`BPE@0(Z8L5..0$"(72=1BAZ.,$"(7`=#S'!>3B!`A`E@0(Z<<%Y.($ +M"-"6!`CIQP7DX@0(0)<$".G'!>3B!`A@F`0(Z<<%Y.($"/"7!`CIB5PD!,<$ +M).W8!`CHHP#D!`CID)"0D)"0D)"0D)!5B>6#[!B%P'0]H0#D!`C'1"0(H+($ +M",=$)`0!````B00DZ+B@L@0(B40D"*%(Y`0(QT0D!`$```")!"3HR<.A`.0$ +M",=$)`@`N`0(QT0D!`$```")!"3HN`"X!`CKP9"-="8`58GE4X/L%(M="(G8 +MZ(D<),=$)`0`````Z.B)7"0$B00DZ(/$%%M=PY"-M"8`````58GE@^PHBT4( +MQT0D"`$```#'!"0!````B$7_C47_B40D!.@QP,G#D(UT)@!5B>575E.#["R+ +M10B%P`^$BT4(,?^)!"3HBQ5@W`0(9L=%V@``QT7<`````(E5X(E%U.L\C70F +M``^^PH/H,&:#?=H`B0,/A&;'1=H!`(/&`8/#!(/^`G5%@\`:.,$"`````"-!#\Y1=1W.8M5X`^V`HA%\@^V0@&(1?.-!'\Q +M]HT'03#[["B40D +M!,<$)#37UW#QT4(S-L$".E5B>564XG#C31`@^P0 +MBQ2U:.,$"(72#X6+!+5@XP0(@_C_=#B)1"0(H?#C!`C'1"0$`````(D$).B% +MP'0;QT0D"`"X!`C'1"0$`0```(D$).B-=@"-!%N+!(5DXP0(@_C_=#6)1"0( +MH2SD!`C'1"0$`````(D$).B%P'08QT0D"`"X!`C'1"0$`0```(D$).B#Q!!; +M7EW#D(UT)@"A*.0$",=$)`@`N`0(QT0D!`$```")!"3HZ8VT)@````"-O"<` +M````#[?`B<)5@>(`\```B>6#[`B!^@!````/A'Y1@?H`H```#X2!^@#```!T +M8H'Z`&````^$,=*H271?]L0(#X7VQ`0/A+@(````C70F`.BZ`0```.LXC70F +M`('Z`!```'18@?H`(```B?9UO;@&````Z+H!````R8G0P[@"````Z+H!```` +MR8G0P[@!````Z+H!````R8G0P[@%````Z+H!````R8G0PXGVN`,```#HN@$` +M``#)B=##J`)T./;$`G01N`D```#HN@$```#KI[@*````Z+H!````ZY:X!``` +M`.BZ`0```.N%,<#HN@$```#IN`<```#HN@$```"0Z8UT)@"-O"<`````58GE +M4X/L=(E%F*&@X@0(B47X,<"A+.`$"(7`#XBA1.,$"(7`=':+'?3C!`B%VP^$ +MC468B00DZ(E<)`B-7:C'1"0$4````(D<)(E$)`SHHSC!`B%R70)B44(7>F+%0SD!`B% +MTG0)B44(7>F)10A=Z9!5B>6#[`BAP.($"(M-"(7`=2"+%!^@`0```/A('Z`$```(UT)@!T/JA)=,:AP.($ +M"(7`#X6+%6#[#B)7?2)PXE]_(G/B77XBW!,H4#D!`C'1>P`````A<`/A:'X +MXP0(A+0U")!"3HBTWLC1P(H1SD!`B%P'4W +MBSTPY`0(A?]T"P^W1@CH`<.)V(MU^(M=](M]_(GL7<.+0U")!"3HBU7LC1P0 +MZ\F%_W3%,<#HZ[RA$.0$"(/H`8E%X(G"BT8XP?H?`47@H1#D!`B)5>2+5CP1 +M5>2+3>2)PL'Z'XE4)`R+5>")3"0$B40D"(D4).B)?"0$QP0D>-L$"(E$)`B) +M5"0,Z`%%[.F+1@2)5"0$QP0D7<.)5"0$QP0D"@```.CKHXUV`%6)Y5=64X/L +M/(M%"(,]&.0$"`$9TH/B!XE%T(M`"(/"`3L%'.`$"(E5Z`^/BUW0QT7<```` +M`(L3A=)T)(L-0.,$"(M"#(/P`0M"$'0,BT72)5=B+3P!````BUW0H4#C!`B+4R"+2Q"+7=B+!)CHBQ4TY`0(A=(/A(/#`8M-W(E= +MV#E-V`^-BU7H`<:-'!8C7=0Y^W]>C70F`(L--.0$"(7)=`R+1P/C8L5 +MP.($"(72=5"+#B-'!8C7=0Y^WZFBTW,.4WL=&*#1>P!`WWPZ8GV@ST8Y`0( +M`8G>BQ7,X@0(&<"#X.F#P"")5"0$B00DZ.NX.T$8?`B`^@J-=@!UH(E,)`2) +MWHD4).CKFXM5X`%5V(M-W#E-V`^,H<#B!`B%P'4UBQ7,X@0(BT((@^@!A<") +M0@AX.8L"Q@`*@\`!B0*#1>0!BUW@.5WD#X6#Q#Q;7E]=PZ',X@0(QP0D"@`` +M`(E$)`3HZ]&)5"0$QP0D"@```.CKOXL]1.0$"(7_=0B%R0^$BTW0BQT0Y`0( +MBU$$QP0D?ML$"(/J`8T,&C'2B7UWIP>`" +MB40D!*%`XP0(B00DZ(7`B<)T%HM-T(D50.,$"(M!"*,575E.#[`R+=0B+'H7;#X0Q_^L7UW#H575E.!['P(``"+10B+%:#B!`B)5?`QTHLPB86D +M]___A?8/A(M&/(7`#X7'A:CW__\`````D(M&#(/P`0M&$`^$BQU`Y`0(BWY, +MA=L/A8L-^.,$"(7)#X6-3(`\```@?H` +M(```#X2!^@!@```/A('Z`.````^$BP`[!2C@!`@/A(M&/(7`#X6+1E"-G%(U-S(N5I/?__XM#!(E$)!R+0AR)1"08 +MBP.)1"04BT(LB40D$`^W1PJ)1"0,BT(DB4PD!,<$)(S;!`B)1"0(Z*$\Y`0( +MA<`/A:$(Y`0(A<`/A0^W1P@E`/```#T`(```#X0]`&````^$BXVD]___BT

    ")5"00B40D#,=$)`BFVP0(QT0D!!````")'"3HBX6L]___B5PD +M",<$)+O;!`B)1"0$Z*$$Y`0(A<`/A(M'&.BA'.0$"(7`#X0/MT<(Z(F%J/?_ +M_^F+0PR+C:3W__^)1"0(BT$8QP0DH-L$"(E$)`3HZ8UV`(M#"(N5I/?__XE$ +M)`B+0A3'!"2@VP0(B40D!.CIBPT0Y`0(C4'_BRL````BWT,C95P____BW4(H:#B!`B)1?`QP,=$)`B`````QT0D!``` +M``")%"3HA?_'A6#___\`````=%^-E7#___^-A6S___^)5"0,B7PD"(ET)`2) +M!"3HA<")PW0Y@_O_=&V#^_X/A(N5;/___X'Z_P```'=*H=#B!`B+1)`TJ0`` +M!`!T*8.%8/___P$!WH7_=:&+5?`S%:#B!`B+A6#___]U9H'$K````%M>7UW# +MBX5@____C028B85@____Z\V)%"3HZ[6)]HV%AT.($"(M$F#2I```$``^$,?:%_W\WZV:-="8`BQ7,X@0(BX5< +M____#[8,!HM""(/H`87`B4((#XB+`H@(@\`!B0*#Q@$Y]W0KH<#B!`B%P'3& +MHAT.($"(M$F#2)PH'B````X`^$B=#!Z!X!O5S___\!A6#____I.T(8 +M#[;9?`F`^PH/A8E4)`2)'"3HZ8L5P.($"(72#X6+%RL````BT4(BQ6@X@0(B57P,=+'1"0(@``` +M`,=$)`0`````B85<____C85P____B00DZ,>%8/___P````"+E5S___^-A7#_ +M__^)1"0,C85L____QT0D"`8```")!"2)5"0$Z(7`B<8/A(/^_@^$@_[_#X0Q +MVX7V?S/K78L5S.($"(N%7/___P^V#`.+0@B#Z`&%P(E""`^(BP*("(/``8D" +M@\,!.=YT+(L]P.($"(7_=,6AS.($"(N57/___XE$)`0/M@03@\,!B00DZ#G> +M==2+G6S___\!M5S___^!^_\```!W<*'0X@0(BT28-*D```0`#X0QP(7;="B! +M^_\````/AZ'0X@0(BT28-(G"@>(```#@#X2)T,'H'@&%8/___^D[0A@/MOE\ +M"HGX/`H/A8E4)`2)/"3HZ8D<).B0ZXZ-A7#____'1"0(@````,=$)`0````` +MB00DZ*'`X@0(A<`/A8L5S.($"(N%7/___P^V"(M""(/H`87`B4((#XB+`H@( +M@\`!B0*#A5S___\!@X5@____`>F+E5S____'!"3TV`0(B50D!.@!A6#___^+ +M5?`S%:#B!`B+A6#___]U:X'$K````%M>7UW#)0``!`"#^`$9P(/(`>F)'"3H +MZ:',X@0(BY5<____B40D!`^V`HD$).CI.T(8#[;9?`F`^PH/A8E4)`2)'"3H +MZ>B-=@"-O"<`````58GE5U93@>RL````BT4(BQ6@X@0(B57P,=+'1"0(@``` +M`,=$)`0`````B858____C85P____B00DZ,>%8/___P````"+E5C___^-A7#_ +M__^)1"0,C85L____QT0D"`8```")!"2)5"0$Z(7`B85<____#X2+A5S___^# +MP`*#^`$/AHN=;/___X'[_P````^'H=#B!`B+1)@TJ0``!``/A(/[(@^$@_M< +M#X2+O5S___^%_WYO,=OK-8L5S.($"(N%6/___P^V#`.+0@B#Z`&%P(E""`^( +MBP*("(/``8D"@\,!.YU<____=#"+-<#B!`B%]G3!H@>`85@____@[U<_____@^$@[U<_____P^$BY5< +M____`958____Z8.]7/____\/A;\!````,?;ID(UT)@"+%#P#")!"3HH<#B!`B%P`^$C;0F`````*',X@0(B40D!(G8@^`'@\`PB00D +MZ.F)]CM"&'P)@/D*#X6)5"0$B0PDZ.F0.T(8#XV)5"0$QP0D7````.CIB?8[ +M0AA\"8#Y"@^%B50D!(D,).CID#M"&'P)@/D*#X6)5"0$B0PDZ.F+#>SC!`B% +MR700A=MX#('[_P````^.B[U<____A?\/CX.]7/____X/A8M5\#,5H.($"(N% +M8/___P^%@<2L````6UY?7<.+A5C___^)!"3HB575H/L,(M5 +M#(M%"(MU$(M]%(E5W(M-W(E%V,=%T`````")\,=%U`````")^H7)QT7D```` +M``^(A?\/B(G7B<:+5=B)P8M%W(7_B57PB47L=10YQG9!B="+5>SW]HG!,<#K +M$XUV`#M]['9/,2)1=2+1="+5=2%R70']]B#T@#W +MVH/$,%Y?7<.%]G4+N`$````QTO?VB<&+1>R)^O?QB<:+1?#W\8G!B?#KO`^] +MQX/P'XE%Z'5$.7WL=P4Y=?!RG+D!````,<#KGO==V(-5W`#W7=R%_\=%Y/__ +M__\/B9"-="8`B?")^O?8@](`]]KW5>3IN"````")\BM%Z(G!T^H/MDWHB47T +MB?B)UXM5[-/@"<>+1?#3Y@^V3?33Z`^V3>C3X@^V3?0)T(M5[(E%S-/J]_>) +M5&-X9'AB>&5G961A8F%G86-A9`````!,4T-/3$]24R!S:&]U;&0@=7-E +M(&-H87)A8W1ED`0(KI`$"+Z0!`C.D`0(WI`$".Z0!`C^D`0(#I$$"!Z1!`@ND00( +M/I$$"$Z1!`A>D00(;I$$"'Z1!`B.D00(GI$$"*Z1!`B^D00(SI$$"-Z1!`CN +MD00(_I$$"`Z2!`@>D@0(+I($"#Z2!`A.D@0(7I($"&Z2!`A^D@0(CI($")Z2 +M!`BND@0(OI($",Z2!`C>D@0([I($"/Z2!`@.DP0('I,$""Z3!`@^DP0(3I,$ +M"%Z3!`ANDP0(?I,$"(Z3!`B>DP0(KI,$"+Z3!`C.DP0(WI,$".Z3!`C^DP0( +M#I0$"!Z4!`@NE`0(/I0$"$Z4!`A>E`0(````````````)$9R965"4T0Z('-R +M8R]L:6(O8W-U+VDS.#8M96QF+V-R=#%?'`@)```)$9R965"4T0Z('-R8R]L:6(O8W-U +M+V-O;6UO;B]C'`@ +M)`!'0T,Z("A'3E4I(#0N,BXR(#(P,#6YS>6T`+F1Y;G-T<@`N9VYU+G9E6X`+G)E;"YP;'0`+FEN:70`+G1E>'0`+F9I;FD`+G)O9&%T +M80`N96A?9G)A;65?:&1R`"YD871A`"YE:%]F`(` +M``0`````````!`````0````G````"P````(```"\@P0(O`,``)`%```%```` +M`0````0````0````+P````,````"````3(D$"$P)``!$`P`````````````! +M`````````#<```#___]O`@```)",!`B0#```L@````0``````````@````(` +M``!$````_O__;P(```!$C00(1`T``#`````%`````0````0`````````4P`` +M``D````"````=(T$"'0-``!`````!``````````$````"````%P````)```` +M`@```+2-!`BT#0``,`(```0````+````!`````@```!E`````0````8```#D +MCP0(Y`\``!$```````````````0`````````8`````$````&````^(\$"/@/ +M``!P!``````````````$````!````&L````!````!@```'"4!`AP%```#$0` +M````````````$`````````!Q`````0````8```!\V`0(?%@```P````````` +M``````0`````````=P````$````"````B-@$"(A8``".!``````````````$ +M`````````'\````!`````@```!C=!`@870``'```````````````!``````` +M``"-`````0````,`````X`0(`&```#````````````````0`````````DP`` +M``$````"````,.`$"#!@``!8```````````````$`````````)T````&```` +M`P```(C@!`B(8```V`````4`````````!`````@```"F`````0````,```!@ +MX00(8&$```@```````````````0`````````K0````$````#````:.$$"&AA +M```(```````````````$`````````+0````!`````P```'#A!`AP80``!``` +M````````````!`````````"Y`````0````,```!TX00(=&$``"0!```````` +M``````0````$````O@````@````#````H.($"*!B``"L`0`````````````@ +M`````````,,````!``````````````"@8@``00,``````````````0`````` +M```!`````P``````````````X64``,P```````````````$``````````'__ +M[(*_<*GBTO8J#[&TS@MGB4R]0=<':N.(W\G9G;.:/7*.,11&``!@4S^M8<&. +MP63`)`;+,KS2"?Z;A7RA_=0$&\'"AAXY)C^XW9C3((:>FU,#`MX3R^HAEXQ` +MW/V/);AC03P4*HO-^D@)`C6HHPG!%`$%U86]?<,`<*I^42Y[@7]MBJ?,QX3M +M3/:EZ9/S)=617P5Y5PZIU*:8JM;V!QV(A,(RF!F:C2+OF&6]C`#8M3!B-GH, +M)PY1-;%69(1/24\>8N]NI*`*RQTX*!#U)B' +MXKW5%V6Y*;=1\]!=G:91]&D7!#43@0-P7``RF#3BJBB%M%,.7\)4T&U&X/C8 +M(4LW\ASM]>54Z@W1_9`Y0CEW_N9NJZWW4]4HZ+``;=&4+41:XH6=V/B0#[WJ +M(5^F^T'@XPE].>(76"[6@J7/$,#_3Q.^?,D1G90(-7#9N@JW\W:I<_X```!@ +M/'"(&^G]6XWUER>23R-9*V(/<4/R5B3&S +M"7\S:FU`^C#>_:,*%#(5*,IB!S*]O_15LX>H!Q!D_\VM,"PZ>:N6=BRN-=V= +M;8TR>_16]XO)!,A.D@6P8A?CZ_F5]Y=LR5(L0_`-GEX7GC8W3"%D_*N+DI*? +M<<`9203"1\B,5J$NKBQHD#];WLNRL5=_I/F(56'DZS_[30XJJ6`%1N59KHI, +M34]#8GP&HK\5L?&1B\W3[53)J.$==T?J@L".%=K\:(+=23HOAFY\)[RYNK6G +MM_%6\6J+[6K>Q@(&1V3,R4CM@RS(*,9ND0\DP`%]N-8Z\$_!I=>$FD +M6-@V*1+[X_4)1^T`S7A=L5?A?\;7>+&9J?QRU9T<$I,GGM99UXHTC#[. +M<1Z:'3+=7"C\.5#<_IX&%MCL$FP4:Z>CD,7_>K)W5]^R>!3._10]``$$!@`$ +M"<"<7B>!;H)T``<+`0`$(P,!`05L```!`",#`0$%;````0`!`!0#`P$;!`$% +M``0!`P("!@$`#(>XA&S`G%[`P&H`"`H!/7V2E0``!0$1#P!X`#@`-@!E`'@` +:90```!0*`0``+4,K<;.=`14&`0`A```````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_deflate.7z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_deflate.7z.uu new file mode 100644 index 0000000..2780eca --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_deflate.7z.uu @@ -0,0 +1,313 @@ +begin 644 test_read_format_7zip_bcj2_deflate.7z +M-WJ\KR<<``/O&9Y`````````#X7"C3M7`MX5$<5OIML8`F; +M;FQ##3;859.*+81=")(GYK4\-*$42(N6-&R2#8F$)&;O0JKAY64UU]O%J*#X +M0(GX0$5%I1BUQ020%$6,@!H+8H"HNR9JJGPDT,KZGYFYNYMLD/KV\W/;DW-F +MYLR9,V?.S)R9>[E;'26+#`;#%$G\8J18R0#*JFE-?/=M57Y/N;DRW4].FB#XL:G:Y"E<62ST+ +MS5(1TF\%Y`/*6%O\EP=8)>A<0#9@!=4%O%+D%P`6`(H!RT3>;,"]@.G"IJ6` +MQP!+1/FK`>F`UP.6ZK848_(H8#5@ILB+!TR1QOX2``L!;P2L!)@!5C%&!\A>P#>3':+D%$H<`F@2-`/`^9++_]G^"MEL1'T7;?AF23P5('OFX!G +MQKCTW?1'C/>K0KG3)@->2WX]01L/`&R`UXW+3P5D"CH' +M,"^B['[`&P`/BG26\*VW`,C9'"+_38#%$?5,`L^:0(\/"X/N%_V,%48\)M+= +MHCQ#I$_&\/0\D3X@TD4B_1;!OT2DOQ(SUHZ[1;I#I(V"OP'X;C%N;32'F1U? +M")XRC*W_2GV>Q/'T!I$^'\O3'QXGOU"DWR;2\X6\!T4Z1O3W8R(=)_AWB?2G +M!?]LD?[YN/[WB?9_)])_!.R[8C1927]HVSG.C_X4,Y;_,R+]&]'_DZ%YP=/- +MHCQ.I*TB_?.I/'TFTCYB?@^\G]OO;LSDFEP%U7PO(>%>4N43Y(\OOU\D3IJ)#_:U'^=6FL +M?=TB?4V,9RWJGXB0GQ,SUA_7B72^2%\7_;E7I$UB?+-%_X^)\BQ1_H-QX_$: +M\.]!>WS;>"'X(WW-%?6GQ8JTX/\0X+D(_9[4UY])O/R6:*]%\']]9P?\C +MT9]6D3XCZK]GW'Q^FZB_3O2G9=S\:8@9ZR^O&F<_I^`OHW(Q;^3+X?D]&_PE +M`V%^3(LK4\'=Y+Q7YXGZB_65]_QLG;+N@D87\)<8-'KJNG@"%3 +MJBA^Z[*"TJ5%4JUG@[.A[IVNB@;/ADI7LU11UU`G2Q4U0%+%XI*'"PM**AY> +MM&BE8U7%JH+"$D>%5/'FC14K7.OJW+*KN:C>Z7:[W"2[HQSEE? +MT=`DULKJFK75ZSS.)NK):;)1FF#LZJB!B$2I9OJJID(D-"C +M83T$SFA$;*IOEQDU55-U35PVF^OK&*JG.[93E)Z7&)MG9 +MO(XIT=CD:@B)J*FK=XU1J<995R_5U-0[U[GE1O2+<38UNYJ?`WKZAIJ&JGMNH9JJ0)B&M;M<)&^WB4?\9`%)426Q4VB!X8R-K4MTP +MCY[+\WFMV\GD\NAOU']AJ?@Q#I6M>?SWM9GOG$P1[-Q8GG<(:>+.H?U&Q!1Q +M]_*]-BZ-[XEQ#_&])VX^WQ/B0KYEQ;^%K8UPICDU8B;B` +M,!9],^$'87/"L[`N$\:FG$PX'3$_X3E8VPG#U5()V['/$L9F-HMP!F)YPF]$ +M7$)X`6)XPIDXPQ'.1GQ".`=G-L)YB(\)OPE['^%\G),(%^#L1[@0YS'"V(37 +M$"[&?D,8`7XUX<6(BPB_&=L'X1*S>E#1*_E]&&B:SG=2703IY\ANH73741OX_0)HMLX_1S1[9P^ +M3?0>3O<2O8_3YXD^P.D^H@]Q^B+1G9SN)[J+TP-$/\=I/]&]G!XBNH_3PT3W +M<_H:T7Y.CQ(]S.F7B![EM'2%[&]@M)%H$Z=-1"=RVDQT,J<3B;9R.HGHF9Q. +M)MK&Z12B,SEM)3J?TZE$+^'T3**7P^GE1._C]"JB#W!Z-=&'.+V&Z$Y.KR6ZB]/5 +M1#_'Z5JB>SE=3W0?IYN([N>T3+2?TRU$#W.ZE>A13F]C]H_A_L_LS^DV9G]. +M/\7LS^EV9G].[V+V)UH2/_OORM1?*0/#/H=)&3(N#WJ,*_RGV_D/)8\]NA*S +M4?.8M?)$[W5?ZS>,:AX=X;;,UV*]7?*<_72^LAQ)W'%6?IW291B,!PV,9-*V +MFW,\+[!R/<\SU$G':]3+T!PFU9CJ[S&FT@'$[U=;4TWJFE2CFI'JIP+_8&][ +MZ$<:#IFVY5V$]I)L'DQ1NHS[39`4/-M!2$OTGO4,GHRC;M$4EVNH,;8E-6URB+<_0\FU9 +MYS8G=0;QTU)2-?!JI/50^?$M"33VTJ#?=X2=[[HW_2'KW);[M47+58=96XR_ +MIK$U`JV'L[K=%WP;I<$O^0X_0)5\S[R>$'31RLQDGC(3*I<'?/(#>AGOE]!3 +M\YBT0Y)0'J`U>)@J(*5^4T6^,_E18:M8D;7F^&H]1/ +MN5`)&(Y2A^1,KKE:;J8.)0R`,]RMX&7DC^OH1LE^71V.L)18@[8/S8J#'&_R +MB\%@!\)1='W(WM61/P!J=Q(R55\B_O9X=^$OG^Z>A([B`5H`+#MZO/G()MVP +M`ERD]:;'VR88>[Q/A:A](>H3(6I/2*!ZO,=[()1_,$0="E&'0]1G!"5/V98I +M6;S:LZ2C-VC9H7E)3Z29MK-"%6R"4OIC>KRYH>P21E'/S:`"RF@\1#R=3,*N +M@UJ\?%MF.N%9.4RAC9-4AK5IJ=3ULYYX#,]5&AYYAEJ<:D0%6ES',>_-)WD7 +M(.>Q$K576Y*KL9ZHNV=2Z8I,]63WK?NS7F@U;S5F'4.MW8N]64PX9AHUEE6.5%7L:90(.G +MY6<:F)&\IZ#=-.DJ=0H4:]OG.>LK_Z56:.XI3C6-8%2!C?2H`'L(.FOVBS8+ +M$J,84CB#^G0Q-;MW"6N6:&Z=/41Y,X7Z>UAOEU!>$I5^@JCC*&%41^X`!'LS +M0FYB\7:8D&4_&^F,<(&G,YD9B-%PR5=L3S;T4FOD5]0C:MV7GZC&(E-=E6J$ +M]IFAAGW%TU^A%ADIG^J$C&Q*DQ"@Y='ECV5'GK26$%.(M9A@(NJ4G*_MIE:5 +M8P8ECPH-T[M&>E]S3&/Z^9+N]:VZYVYUI9DWVME0_.FT?IA\6X_04O*XT]4E!^G/FH) +MP\B&GWG':A]0_`;T=09;Y2Y8O(/GN?>1+U$Y_$\?DG"FZBWFGL<,Y%W"YNZS +M-,?OLKQ7GSE)MH$\"J/9@$T_I5R^H71;X`X^XB.7*&$C/^]NM<@4=@K*5,VI +M_H#NW<7"B[PEK!K6&\]K16AU$P,24:0!ZRZ^C]DW@_+?H[)4P+>[7?@X@C5: +M5'+)Z!A:W]/?XGTS71.3R&",F&5>,QL?[!1>$L#SC21$=ON8+U$:A;QQ5O"H +MGF3N%JJ_*Z3?9X@Z!MT8%8@2[?%!,>YZ1BT_!9TU_5QX7[1HCT\WALIR`J%. +MH4(BDY!,W;OWY]'="T2NTKE1ZS5S0K;9C%XE@JR<+/PU8.]2\BA;LNS&(.13 +MRZ26KUB*T0"]N>#*(5'S.IMCN% +M]W^FSWN04ZD^;QNGK#[O/DZE^+R?X%2RS[N'4TD^[P%A.Q_;*)B9[%_8CZ[?T8N*[\WJ-V>/X;W4E\^ +M]D@FVBMJ!+?,5V^Q.O8+Z\_%LXKJ;B,*1RZKY]3NV+U$0Y#G,FW$83%/,UV1 +M]5<;/A!1P_<4LP^S!2M0;J`I*XLR4FF\=FH^2AUEVF#_I,SU/?&JEU3@DG^M +M_DP]&?LLTZD[J)P+JL]/^;[G>758O:ET!=R(%@ +MJG<8"4W$!6VB\]9(=5:E)D9VG8]FA7K>\'QN? +MYR?:6W*]IR"JB$>:':EBE>OHTF5..TU1?:$)[)!1:+*T:3$GI7BLT6J,5I0B +MMJ(W8\S\FF,83;&Q9;JI)]4^?X?Q*I=$>M$5``VQ46@5TLSKUU@8I9Q(85MV +MNS)JE*?P.*0H%(>@O<@X)!QV!-K1`Q3-#OF6LGG(8-DY3L%P-!'09I@&^(Y_ +MW>$WD;V0C36]@[H+?IKE7)(V;?@*CTL#M$>+,C\;U9*?AT>5TJD1:=]&_=SF +MPS#B"B;XCI?XB#^R?2AS$F;.]/!1Q^<=^C/FP)-&U3MP@P<:IR\P61+)TF6R +MTTZ<&7Z-G`&XZKWN?08,RPQPT1 +M3O@-=#9(80<>>5%XQZ$NKOTZLU$,B8A(QPJ;J22.A'3D\VV\0-_/,\5^[IG3 +MD<2)!SJ2.3&CP\9YDK09K-4+GGCEC$G,)2UAE,61GONU:<7\$#9-3$"/6:\9 +MJYPQ=*3PI7+2]C/;>"`A9I8?S'P<$Y%%JL,7B?>"7*4E,&U.T;Q+%J>A#O-5 +M&B8Z7%L_S,0[0\(T+QFU)X[BY:YN5KA*?>';B1B*3F;7P<=8_]BQ)5G,;2ZK +M?3=&RLI]R`AB7&C[\F&[*&6M/W/`5,2FY,Y*9,5/U88X; +MNLKS`AWT8&K_-22)\ZK.61RJDR$H%"=?U:LG70UE&O79K_SZ)>5,8D_(&HKH4*BV/V2.S'#;2:&VD\-U1J^&K&W22;$*W+ZA)%$L.LDS<\.D%):4 +M*,B)ABC`R'!QM#U>"F7ZPUZ13W7T\C`99A@2)"P2%N6_&LH<"!OGCJ;5;1-N +M,T7/I?K1,OWA)JUZ)3^;<=?$[(AP<6U&,IOK='XWLO.[/B'7?@1^S28IJTN% +MX=G:RPH3^72=S:?KMB[D\>)M>T+D/B(Y0_ZS('U[!V@:KV$[USO)4P6]&?3^ +MX:OAC&V4,6L@G*%0QI*(C/=0QLP!-GGW2\!8`8;U<]$,JLJNF1*D4,=2=(/0 +MDA#V,FP6U)],OEPN[?#SCCW,NW#HPRC4IF7RY359+\WEI?E4*JP2)O,_$B+7 +MAHTQ3+E"^=_1`9%I'1C_;"`9TO,ZJ(AF][ZOBV.BB+4Z*8,VU8XE`V-+3AT/ +M59(ZQU6BC,%N_6X645Z25FY2^RB*U0,Y/[,KV^1.)#V.H$?L,4RGF;BHU=<: +ML4NV.8(^1Y!%)?:N4\=)=BB&G`5V&@8@>Y"OOVLO&DTU/8[G4=]QD<6!9?VJ +MX_Q@+M6S'#VF^&TURN;G)376LH/X#))RTJ`<-RJW8CP.I<>@."Z:%4=_C!*< +M2G(O]FRK%9[N,[XIRW%^4Y96UF\Y$M/F^",[DCK^Y#-NM5_WI7C77J6'0JO2 +M_^@K[,V=O%'S%7XJ=_*F5-:F4XT=_)!6AG+C.UG-XG=2U<'CXA:\\+M@?8BQ +M%JBQO-G0_#.F#EV@M=9RY/LY"?1ZPF9S1R^0]E1;!DRJW&B1[T%5,A%X,RY2 +MS!<;Q"^@G)C%`LL>AXE6[0#L]NA*];@O(U\92M22GJ[ENZU7,SY-VE/*]M^A2X)V17_]IM2/MT1;GD$U#ZB@+MP35T)O);2]K,'ELH5UT^8 +M$/>>,%IV=-)X4IO^;[,G7)E$@SD1E58#6R'YNN?93H2K@N64VGN\,V9LTC`V +M&3>44/[@YSOCPXD/=QK#":^]BU.!SLFAW/:( +MYR)B?LFJ8X\(J$?Q[&!6/UN7VCJ*^>JQ49MQ[2I?H'R./;`F33Z3K_P`&7AY +MQ*TQ.P'PA-&O'P>L^G%`+0_X +MWLVH[LTI7$Z)+J?L`E5(8)E/4.8I9-92IK^=/R9@3X;XPX*$(19=RE/8LR%M +MFIFML"+)_NC/5KMH4I72XFR-.@&VO%:+:3.Q`^`I>]=Q;B]S:FA=RBE,;IVT +M[49\N^<<'9CHCF/P#)>+^);?62>*F^U\^)E,4M1CW(]UQ[6\E[Q0N'`^]U%Y +M(9SWY)V.I@\RS9A/BC52F\:JG+UME3F156C*B';[@;UW:B\MLO*=F/,CF77G +MFJ,[U\L4DO?R6FS90,RM868V-!8?#8IHU3].DP=#FD3SYR,G(G_S3I'?RO*C +M^?-NDY\V0;MIHMWQ^?FWR6^]37[>7]'_P8AVP^MH:+_-5,NOJ*7]G_%V*>$IS7.QUD;["$I6H)^5=)6:9.8:)L1N2@ +M)FTG71T7M16T_EUA(ZJ5]GJ[M$?,LDDKL*+8<`Q'>KXL3H50K2B192IL^`R: +MPZ\\'XPM\X_T(71ZS3&U;!BW7%@Y^U'8E=5K>;_:BX$8V3RLE5U4':=%ZK1R +MTZ"5]2I]00RC%L,"LWS^O,73CXNPG3V./K9K.`98%V9D\(N&25K9@%K6IY6> +MQCJ^4]L\;+\.#R2?A6H=K(ZK%+`N6X02N]J);W997V +M67Q:F=]PTI=R[^O*SV>]N/4)_OR+L9XBPYS.<@R!2:R*GN5:`@9*M[A68"*C +M!Y1C5C[N!::6E9I!O=262,8T0+8N>S<>Z9W +M*?T!I>XG\=O#C<&0#=?TB=>$IX42>^=%> +MF!7V0L4Q8-#*^[/*!V@[SF417I37#?YXC*=]5\LK9C/3P\XH\`=M1B(YQB/$ +MLP6S`V\Z^,ROLI]5GQOYD[@#+.O%^QBBA4!W?PQEL_$0#WJ.R?="D#J-LF#! +M_>2G@5!,4-ZKEIL>MQ*3#.%8<#"%Q[UT6T5-]\3X^=22(Z:66"N4=]&$ +M&,'HQ/B,DPV].>PFL'F6;JO&"?<+>U"W5FB&&K!F\3O9H/R`7GMAM*4K(BQ] +MPARVKCTXQKX?CS*YSDV&#S'[`V/&X:,1YY?M0ZT(1.G5%/;T%K/,?E:SX>'@ +MB'@38A&;/+C5'^$7\>W:(F:=18ET\F3S>DL)/U6/BALT7^EI%H@RKV./7AO=ZB))RXF;"IJ$6\:Z.;^\/HAZ/AJ)%$ANNY-M-K/N1 +MH`?7XE^:40VVCR71=:J$N1]G%?]HB3/1].Z@+%X=?&1#<6/O\YX8H2M=?AW+ +M5&(YM*10CO9$$CJJ[29+:46T#:3@'2B@9"T6?Y/P@AA0(JP03_KBO22UA`W" +M4_HV$'JAH,,D"#!/].:!YF.-++9ICV5H2V>JOD.43'B)V1N:[OTNTOQXFSR9 +M=SS)RG'BZ8C]B`Q"1P06@&M[20KT^0YQK*&0VZCKDZD3?OV.8?%,/]M@Q=#0 +MN.J[\2NTO>0HX"G?'C>#/U]`G)1YM7Z +M)7*\QA[_8A+-X[:YXT(BQFDNR1[\,%N7]W*C)FF/SU2/V7Z]_6:0?&7OP1%Z +M=&\YF#2F7$N@?OH*@NH/6!P2NSCSGL=RNU^\ +M'[Y%@VC6WV>@X8X4DTBA25C,8F.D#E8>G(1UB'X6P]=*U@_L-0B&O&?Y'-T] +MX1Q-XG/4YZ52W][OCW`>"66AFY=1/)\_N2..RF@1_B'=+_A\2/*'LS`_!B%R +M!+X^;@3X^W>L"U[R9>KSN&Y:_8P'U'*Z)PA`8_9FPJ*)WDR@=KC&T&_,^N+M +M2.WG(TD2?#[B^2MRS.(-!QP#^\4#+#QE(Z%D+J8H8^[BFIH[Z-]UL&N&DXZ? +M/C3V81KG^AC6)X_\MZ.J4P=?[-8:,5M6?5%WJ70@S,]S@WM-PP.(I_MJ@>.>O@E?R>>N#?+3IE6)Z +MM5)_WTO.4EX,RAN4%V_1:S[$Q6?UIC?SRZKB]HPOT+^NEM^@,*D&PR5$(QU: +MV3!_>4ECN9Z:[2<.2F+)X5D^XQZ5$8,_9#'3T^B6EW2ABSM68%3^8!C?`19W +M?5C;S20D?5MEQ*`J7F:.LLOX?3A*G'<-ZO-V2738,MKN<`E9GUN(ZM/UD5@3 +MQ,-L)1BD/V2AOQ'3DDL3HXYD`JW3A +M#I7@=JP24T+4G.(%[_6M\P;+QWEA +M[&V\\+@AZY(\2\LC>]/A/MH-[P$/<\-+GO/<#0U/KPE-A4U-XZ?"RW32"/>\ +MT1JOCN;J_IDK7*-]<"?O^T0+12@\&MM-T\2]'.N,`=X]L50S(W)MQJ]LZR/\ +M:`*OB3(5>YWN-C,.&^K?LX:MOJUOK'YYOL$-LX,;2.F*01IHK^*\GMZ_:8%C +M9E"8J[WN^S]N.L\_KG-JN@$AX$@*@@Y]05JC+TA"O"BA++T'2I'E-W0O-U.,&5H3A6*WY8O."UW[)WHO +MM)B%#^S47=#R?GV\O7]MN>?>R1Z;]`Q^BTW%%["Z#(=6EPRQN@1NO[8H3(8A +M8#EZ7(1T7T6<)@ZZ=]PYQ[B29S6_M*+W9K5'3):C?3AK><^JCQ"SH2V9>,4P +MQXS=F+B/1RPT;-X<+3+PZZFHP0]$6S[G$5QAL8Z7Z(L0_W\8WAQY`'!9RS/]BC# +M]ZL.OZZWEB.EN&&^IHZJ/T,/SO5/Z4&+YWZ-[&OG_%1X[@K1 +M4ZA_N#@]]]N1$;7LM-HS\NLLH)/-]^64G<:3J1OVK@`JL@K],,AO?0\'D=6N +M__BS/V/'VLO\J>O=]@O!7DU90\E!(W(\P\H)(Y[3@1*CV5E6]W- +M5?1QK3E5;L^H^4]G9/Z",2K')U7;.K2FYL?M): +MY?3@2QM6I[7JR2I\1"$[_`$%M%I6NFRE5%2R%.3#*T)$Q:*'5Q0YI%6.%:52 +MP2*IH%"B;S54XXL14)9QT+>VK&C8FHV_U?@KZ/"?.OKS=E$D_L(K"@J+BK,7 +M+5ZRM&3YBI6KRAY[F[.RJKIF76W=^OH-#8U-[VAVRYY-+=*1YRR!S-N`^@#E"_LC!L76O +MB/0YX&\##GT5EQI?Y7E;&.;0&**C827JE:#\#8!$P6<`K@+^XU>,IJM?X7G? +M!_X\T0`/H`90"G@0@1?X* +M/7.%R`GQ<>I!#!C^8@@EN5%VUM,(QDNSD.>VICWHL:;-?M!M%7\E0O@[KWJ6 +MU=:29LMLX33^0`1*XNO)H1G$2];9"ZV2JZ6FI:JENJ6RQ;4.G]2H=*YS5L$G +M\=-=S.JN;?3`N>"^UJI:9[.S"M^0@2//KK76-;AE>+"UL<9JFYUEG>EVN:QR +MKT4GMY6`LIHFXP2F#IJ^P6-/3T\OCI35K7OO:R4Y3I;DF +MOB&A>8H\=:-TYY6C0:P<;WS9*P>^UW%?;$Y2+/_FV^IO!H,VT`?PTE9)K/3_ +MW_]__S,_>@A`N/XR?W\]N9^GTP%!_&(8#O^21#W#.U=(AE:3X3ZST=AFX-^S +M3`%8#P>#TXFAZ"YCH31%0 +M+K`*,$O\^W8)P*U]_!%-,;[727)+5",[`3ZC&$WQE!_+O_.8")@6\8U(^3*_ +MS+3A#^G_"L`K`8=]1A/1,O#=P/F`>P!D@%O!8&,Q\H/`I,LP\`MP%T?1'U`.F`A8!G@"4`# +M8`M@)^"3@*\`C@+.`"X!?@^X!;CK0Z@/2`MHST^VV?XVF$[6,_T7#F6_436Z;8YL[9VZFU9Z1;Y[]G]PH?:A/M)EA_V]QA;^5/]U=BP..[*R4 +MTF%"%SZGE][0*+O2"PJ7SI:=ZZ3T6J>[5DJO?K+!_>0&AND\E+ZNP9.^$6%A +M76/#F$0%RM`*\7&BJ5XFR77XRS[^EEZ#!(H:V>?FD9@V_KO" +M8KV?S/C$MZ#97A;^&05^#2".^,3^4PR^EIAPN5'`ZT7;,6)?>@8;4'LL-#^&FV_ +MM1%\H^`;!5\3%8ZSW_H0'_^^>!,V;'-QF"]1X'?H?"(N:%T-O@G:W13A!VW@ +M:P/?3F,TW]80G_CF-V9.R@3R?(*/#17V<>J8;0*^#T7(LX'/!K[5$_#M%7V( +M%7%!&_CZ:-S&CY6U3LJ/EO?E"+Y:\-7>AN]P!%\3^)J<5!;-]RW& +M%XZC9/"E&J+'[2CI*?CHNG)?);X5&,%G%?@XDQ?^$5_!>+\/M1G^78:CG9Y@ +M_OX%```58```6%```!20```3Z```$^@```_D```HH```$U@``!&(```0B``` +M2?```!*H```2J```%!@``!08```3:```%"@``!0H```4*```$[@``!%X```2 +M*```$[@``!*8```16```%"@``!.X```0"```$[@``!#8```4&```$1@``!*H +M```3>```$2@``!'(```4&```$.@``!*X```1R```$-@``!*H```4&```$V@` +M`!)(```3N```$J@``!08```2J```%!@``!*H```4&```$K@``!*H```4&``` +M$X@``!.(```3V```$R@``!)X```98```$N@``#?````0&```$G@``!E@```1 +MV```$N@``!)H```1>```$B@``!(H```WP```$!@``!#(```32```$X@``!.( +M```3J```$Y@``!"(```12```$@@``$FP```0B```$#@``!"(```3F```$(@` +M`!+(```2V```$M@``!"(```RT```)@```"8````36```$S@``!"(```3"``` +M$\@``!18```46```%%@``!18```46```$#@``!18```2.```$C@``!(X```Q +M\```$M@``!0(```0F```$&@``!08```2*```$B@``!"X```2.```$+@``!(X +M```2.```-#```#0P```T,```-#```#0P```T,```-#```#0P```T,```-#`` +M`#0P```1N```$6@``!#X```0>```$$@``!+X```3V```$,@``!-(```0R``` +M$T@``!#(```32```$T@``!-(```32```$,@``!#(```0R```$,@``!-(```U +M$```-\```#A@```WP```,?```%;````2B```$H@``#N````0R```$T@``#N` +M```0R```$T@``!#(```32```$H@``!&8```2N```$H@``!08```[@```$,@` +M`!#(```32```$T@``!(8```2J```$:@``!0X```1.```$_@``!*(```0J``` +M$H@``#9@```WP```,?```!*(```2J```$H@``#9@```U$```$H@``!*(``!6 +MP```$H@``!*(```0R```.&```!*H```42```$H@``#?````2J```$H@``#9@ +M```V8```$J@``!*H```2:```$7@``!`H```32```$_@``!*X```2:```$K@` +M`!&H```2:```$K@``!/8```3&```$U@``!)8```06```$0@``!)8```3V``` +M$E@``!!8```0R```$T@``!)8```1"```$,@``!#(```1"```$T@``!-(```0 +MR```$T@``!/8```26```$%@``!#(```32```$0@``!)8```2B```$0@``!#( +M```32```$]@``!)8```06```$,@``!#(```0R```$,@``!#(```32```$T@` +M`!-(```32```%!@``!-(```1"```$E@``!'H```1"```$,@``!#(```32``` +M$T@``!/8```5,```#_@```_X```/^```#_@```_X```/^```#_@```_X```/ +M^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X +M```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^```#_@` +M``_X```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^``` +M#_@```_X```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/ +M^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X +M```/^```#_@```_X```/^```#_@``!'X```5D```$?@``!9````1^```%M`` +M`!'X```78```$?@``!?P```1^```$?@``!B@```A1```(5L``"#]```=7@`` +M'6H``!YQ```>4```'5```!U0```>B@``'S$``!^B```EJ0``'LT``![-```? +M!0``&H$``"$;```CMP``)?0``!JD```=5P``&J0``!JD```<````'/$``!S^ +M```<_@``)>```"7@```<5P``'%<``"2R```@R0``''```!QP```@/P``'^D` +M`!XR```=N0``'C(``!FR```EJ0``)<<``"6]```DU```)1H``!HQ```=ZP`` +M(#4``"2-```C00``(Y@``")U```A\@``(:,``"B"```G=P``*`@``"=H```G +MP```)X```"A&```GV```*"P``"A9```F@```)H```":2```H;@``)H```":` +M```F@```)Q```"<0```F<@``)H```"9R```F^0``)H```":^```F^0``*8L` +M`#$P```OOP``+#H``#"!```K[0``+`<``#`3```P5```,#P``"_H```P8P`` +M*QP``"L2```K'```*?\``"HF```I8P``*6,``"EC```I8P``*6,``"EC```I +M8P``*6,``"EC```I8P``*6,``"EC```I8P``*6,``"EC```I8P``*6,``"EC +M```I8P``*6,``"EC```I8P``*6,``"EC```I8P``*6,``"EC```I8P``*6,` +M`"EC```I8P``*6,``"EC```I8P``*6,``"EC```IVP``*=L``"G;```KHP`` +M,6T``"NM```K0@``,4P``"NM```KP```*ZT``"NM```KP```,Z```VF```-I@``#:8```V@0`` +M-I@``#:8```VF```-I@``%$0``!+(```3H```#ES```Y)@``.?D``#I*```[ +M4@``.:@``#HJ```YQ```.+(``#KB```ZP@``.OX``#IF```[-@``.J(``#L: +M```Y%0``.9<``#GH```Y8@``.-H``#R(```[LP``.ZH``$`\``!`*@``/^L` +M`#_K```_N@``/X0``#]R```_A```/X0``#YT```^K0``/DT``#XT```^-``` +M/+```#UP``!!5```09(``$"@``!!$```11P``$4<``!$]P``1J@``$95``!# +M5```0U0``$-4``!(>P``1_4``$@U``!)!@``21H``$CC``!(Q0``1C```$8( +M``!%<```17```$>P``!%WP``1^4``$?3``!%]```1O```$<```!&T```2,X` +M`$(```!)I0``0?4``$>```!$4P``1((``$2"``!#M```0Z<``$(N``!"(``` +M1/<``$2U``!(1P``2(X``$3)``!%N```1$8``$1U``!$=0``0L$``$-4``!# +M`P``1S```$-4``!"@```1,D``$-,``!$]P``0U0``$-4``!#`P``0P,``$@U +M``!(-0``0U0``$K]``!-I0``3.0``$UO``!-1```3*,``$R!``!-\0``3=\` +M`$MH``!,`0``3`H``$U5``!-_@``2V@``$W%``!.'```2V@``$O)``!,T@`` +M3CH``$Y4``!.<@``31,``$QP``!,70``3,@``$S2``!-"0``31,``$V>``!- +ME```39X``%"%``!0:0``4`(``$_4``!.R```4+,``%"A``!.R```3S<``$]` +M``!0P```4-\``$[(``!/R0``3[8``%!6``!030``4%8``%44``!2L@``56D` +M`%3?``!4WP``5-\``%5&``!60```5B@``%44``!5=@``45@``%4T``!3J``` +M5(```%/A``!48```5!```%2@``!40```5,```%*'``!2T```4OX``%,V``!3 +M;@``4Y8``%,@``!3*0``4N<``%+Q``!36```4V$``%.-``!3E@``5:```%+$ +M``!2E```5KH``%()``!2$@``4;T``%%8``!4^0``5F0``%9^``!6G```4H<` +M`%*'``!2;@``5>P``%7B``!5[```5A,``%8<``!7H@``5\```%<&``!7!@`` +M5T```%=``'__[(*_<*GBTO8J#[&TS@MGB4R]0=<':N.(W\G9G;.:/7*.,11& +M`00&``0)J8R$;(>X)P`'"P$``@,$`0@4`P,!&P0!`0```@,$#,"<7L#`:@`( +M"@$]?9*5```%`1$/`'@`.``V`&4`>`!E````%`H!```M0RMQLYT!%08!`"$` +$```````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_lzma1_1.7z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_lzma1_1.7z.uu new file mode 100644 index 0000000..11c2133 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_lzma1_1.7z.uu @@ -0,0 +1,287 @@ +begin 644 test_read_format_7zip_bcj2_lzma1_1.7z +M-WJ\KR<<``.395S=/#$```````!D`````````(2-+0,`/Y%%A&@[WP)!,(6+ +M]:YDCG/TF9,6Y4@I6&:W,\L.GXAK)SG^7$ASM;Y]KP;]Q:,S]93R>,&)>5<, +M&FZE"`#6^N9W.O9$'UE^T-50DI_AD]BN$0G/D?)@D^5S4+=>0I338+60+5WO +M?S\=&H#(CWK#P8A*.F39U-N85;*`7:QH4MPY]Z"R4@0-G[PN0P/I&4U*T@DV +M'"`CQ@7=GL@J7_2-A[.]&`<]D>$^(9=0(?Z*\Z.%M#RG1BD;5#6(4_PL?`47 +M!00BJ=5&HZ7@@B$C!NO::D+1C%8P).\)*UDX0P@<+::RMJNW=<@+:$ZER\IE^S3<>=HCZTG +MM[:O[2?'(:Q@840D]\]5Y73NXY[]$A&S9_<=T[^)S9E-I@,/"Z%N3%P8EQ8N +M.<>T1U:G?9*=LX1R,65>5\LCE.PG__FU`+L]UUEKFS13]3C4N`J/2*#MK;D6 +MR_YC0[KZK#6ZDVED3OA(WO_#+'G.!7!DNT&:A<:N8%2S1T,0<.CXWI?5110E +M(]/(V5U26WQEEBY"+^%%%QQ*$$LVGS;&M##OO=PE)#7IOV]4!T0>MCVFR7A^ +M)`*]D,D*8(TTY<\22+QK022#]K1P8Q>ZDOE"5%*XR1S_RD)#8:OFV8PM<:&: +MXO9&=U7J?O95W3V[0_>S$IA67];6D(/WJJ:Q>6%"L4.3$3?0E!!$%?%!2/7& +MXB4BNO1`#[FYN$MKM,TL^'./,4GY)NO_;YJ7P +M.<8Z"R!*LK]S`B1=P4X(^JK3]7X8N(%H?=H&K>KB'G7(0C'R=1Z0Z`IBTR?O +M>DKYV:WR$Q0MRO.CI2E[0;'KUGX`,?^8H_"$EOK=81Z5Z4VZQ'O;;O;-'3N/ +MM(@343API(#U5#X1=PK%4)/F?[I"DE\39HS<'P)7H49\16$$ES92A@%4O+Y4 +MAD=?Q`Q6L[^+YH+AJ-Z!]8./"Y'^Q"*$TJ#,%/ESOJCC)X:D@0R_?J)%YC&F +M):9`]N(:_,O,>0]$-QL,-?ZE@EH7Z=TEA\M7949(]"*65FN\?-CF(U?7P0?R&\DOWV5DVFK[.JXEP>WU1IL?6K&/CWJ(7%PM9 +MZI:B)8)Q$N-53QL+1O[;'7O/7/O^;3JY[WU7(!DWS`YXM'QL?+>("XZ7)FJ3 +M#T4640CH[0Q8U319C-]L^2259=A(C)[[!/*9P+!6MXIH$N)1*Z:&QIZ7]E*8 +M%(B.D'_@P=8!H(?*X?N@HB+MAKFN3F][.%W':*1!5I4=/"TFY>,\=4<$EI/) +M\S[27U*=0/;8!0P4W/=5+RC"*W]L[Z>GIXO;=$L;^CKMC. +MFK$GA0?W<=3^K@8Y^D_FAZ!W7WZ#.6HO6/_:M&X<5E:R +MAU)=J;SF.%&+0R;V*[FQB?;-D6E*-E9A9B[,4F',0KL8S]AZ3/3,AZ!6('R] +M)>:,3R!'4,\HCK1#'3_?PE4$NKGPX,R?.IK6$:/[E%8278\-K\&D4\:14"/( +MJ(V,!$2BJH@D@[TOT`^<-9#'>!Y!%G[3Q4L[4EU[56_:"*>E#X'=E='@D%RN4=E!\F6P+B>NF-E.')J;D/S +M>](@#H.CZB,"S;X1F.)O-8.%W0+\OBW-QVYBLHRW$*]^CP(Y/U\G<3B;CDT0 +M]"EG+*#EDEZI35$5+9S&_^!_A78^X7/<2I.4Y;"H60LCL"Q.5U=,LHK4"6W:HZFZ?(LI+*? +M1?]2$%"5;V^Y]A>V$A;XY*$P"@WF:#I'$>>Z@'G8"9##/BP&7S4PR+!4&:25 +M@0#?WAT5NTR6,RW,0XNFDRGJJ'"[!B#`M[^0! +MB$_UO("?`8';,_EYIF/`YS,HY7,OO1Y`A$BAQXI(K,:Z?[$DK[LF1JP-RIXI +M[\KEKZST5NF-26U91M2>F]R-?H6.97>%;M$0B&E;\FPR!_8150K#<]3V($5- +M6SHJ[/"&TYD;ST3!R#@B92\![8+L/;^9;:^+(C'(Z[&A,_Y7P=$6SKYQ6J=0 +M*0/@I?K_Y@L:A'XR_=%D=4UM5^8.7CZKI3H%Z.&F'T_0IXB6 +M2\2+(R4=NDDVG8N]A(]M&ZH6-!N;N%IEGNP%1\$646$4*?JTOC-1%3H/UB]S +M-NON.J5*JN\71XV9L`?IV0DNQY87`Q/JQERXF.B<<1R$A7$ +M??LEM.:+%*JG+/SM23OHC_X[]'*WW.H;R658END(V=8SJK]K^DVX!XR.GLR_ +MFS_7>CF[]F7&4V3E<#!^5`/B!C955]_-N(F0[!^%U)G(DX,Y-SWE%.TJ1,KN7K_JS^OH?.6U\4@Z>K5-0[1GY` +M57LW:6>GO'!>FU^^MH"`=0.VICBJW_"`.AN^14_AL&:(BY,W +M+\E%!4$G^;3$!WW_)J>_-%0KHJUB`ADT\]#`$ +MW3*]RC&JDCHP0&BAT2\;Q#N>&MUFH8&I[^72X/_V&S]J0[4:!R+L=FR<(I>K +M3G<79].'1C5M'U>E=@A:6<8C&M4)IEIC='07>AK,.RT4,[9^6M!/QSSK`/9& +MI/X#T`#T0[ZY:H-6_F*QC:."_0I<'O:3-EJ910,KJ[^>E@H2O$OKG>0HH/;\ +M>`:*1^*-<'X_;P-,1-C>?E?<23A=YI-VJFS]NL;H`D?>=%N\ZC)L4V5TO-RL +M,S:O8KM?0')<[`-@&.`>$;')_TT/3IZX02G6'789"M6-5^4_;N;L$B053#PY8*6KD%Q\#"G99 +M*RY0Z]!B"5/58PTJAH.UI_> +M?7]0O.%'W&>\4J*)FOS]X!HZC^6GLFA%'@VA%5#''Q\V@K:?WJ>\L3D"9G\% +M![+R^KAFA7Y:!61'?B`@^9'[)U]1R,&85*!E\A5CGU:'E%0\O$LHS2\"B(18 +M$R)+4?8NA^8`SJ]-5YD)A:3U7\GMJ,K(\79#AA8J#X81K0]V6#WSKG7W7G1] +MWTS59JPM\?#9`DSGO[3FCJ1U>0F[XY,5-D!`)ERPIK8YNZ<1#3T^S:+C8/16@5 +M=L/='P>_ER`"1V@R?`1@:Q1[!6=R<"SM.1N==H%HFO'0C;.%HC""AY8(+BC0 +M_^(<;#3G4^ZS(=R32LH'F5REZ:9J?G-L9X46GT)QPNQD%CIER2^OB@<;/$ +M_%R:QR)8XMOG._E1^&KX=&ZLC"B'D1YVJ;&*&^[OM/-`LW*+@$^IEI1*2HUN +MJQ$;!@T3%"-OC(Y!&.N$]^G=1CAVWG>^;4K_CU%0O?[>H$C:%&Z#9RH1=WZI +M-'G2?PM[0DM@VUD@'#-X[!I3X\F&Q$/-C9._6,;]T=KCX)Y#+K,"OJP?9GAK-^S5RJ)0LK;Y3A54> +M@BNYR?&'45;186QEIU)WBT\DW7B?FWL.W>MQ@X.Z>"2*RFEB$JP=]&M4<+V> +M]D82H%QX6X:9COZU1JD]$X=;-3)%D'S;\?5L1[^;7F11T)=3:EQ;3M#([X>4 +M>&:!^+/A#!=)N+/]DT'U'1FKJPXL=@G^!$A6=H049Y(?^4G-.Y.4J(BY#1.4 +M:$>D@T;H$PNN>VP6G9',Q;\'M$']7TDC +M/%-"4)#^/D2F%I!-LN&EJCEVS]-O:`+MVO0,`YI(KBH\>4I`AQT>X'U5 +MT('3V/#GB:4M'08,UE]/U:&?L]AOUO6U$NF:J\#BSS8'[5F"/95"R)[@B@^( +M_]/+<%9),KA*@T80#.%W^/LT\['V\G=-6-_`,Q8=,W"*9.8P@^@YN))H,NOY +M4W@9@ZTU-J@XV.(D=_XT[[">*B,8"9RT/@M,K3(/J\Q8T(/_QSJFC-[EWGPV +MDLJ=P'\G6VL2'<>CKJGX$)05&0H?$N4,=*`+_5?7W7@?[KBY*@$<'%7QWH>& +M1A6<5`$UD3B8;S@,[1!$--9<5)=Y\0MU&;I860&<'[2K:C35?'HKD.YL1#(/ +M_N\WBKS'7LT6Z`7I&6JZ*4`0E,!)N,,`S\L-7)?K&;9;I81V+/*(=<[ZW;%I*D+@@"IEC63J81?NT^^A/!B?OJZ1?6IFN` +ML,JZ`]?W8FW'LNFBO+EJ^%>$*E64)G.V]D?]7FHW3G24:D)`BB6.R)PC>@T/ +MMH1)Y2]ED,YCW&6Y1#H.N`M\NW&B(K4/GEXYR4]/3E5/JM&7(TBV9#Y73UIJ +M"74MB'_A_60"U=9$<:=?E_:EQ#$Q['-B%F4Z'\V\^B?(>UWEK:?:N9:&]7VN +MQT"K/+E7./L_%?*NNYFS?WBHYFQ.MTF7[U%<(M&(>,>E4FK[GJC2,B8B)J[W +M]@R5F;=);`Y+[*PK'#H@PRD3RVKND8UI9/\:#<>R2`H<]#GY@H6D,GKG_+@O +MSOG[5;B=T6?,IKNB/)37_L8`3N" +MCV04E30(C[`_,C1ZM\8:&B^^KOU5L$`AL/B4[FM$"'X(X,3>V,:21%"T%K_= +M",4-.[%]PW[1EW0*.N;E=7M&MR14C4SFP,;2RTAT93N<6`4Y'.]' +M<0Y*G?\Y)K'Y,`E[^!:SZ7;[J%F(,BDT)O\.4%"^OY7BYH=[M`;APMZLWJTV +M#PLN&E9SS*W%+IK"\`](5W89"?A2QZE;+:.;UU0V*!4@-OK9WM:")2G$X-G+ +MYDLV!!0N[S-``]+V<'+4F9,3Z/IJL[?+K6%^$LW7+/+T28:LZHN_^^%)%O;V +M`!$@U\W)O\%V1=N1KA?>#2.+$,J5I\X]`L7D@B_\LHJJS%\C@&6O,)W^$1^X6SH@Q;4\*F6*L<]"^U7,:ECU%;Y;Z^AY9QD+86BL72A*#)L828G*3ZFID +MP:@S,=0>12UD`2LN_77?>SHB3H+5:(J['1-,?=,CL]S+Q5:`=U%\;L;^S03- +M*=G[8HV`*E5O4<@A)[3-2Q(!23U#1&MG_9B/`IT9E&\^J3SLK[ALL*HQ:F5T +MP7H>R>=_SQ.6[2K^^;]C@3A9ZQQ_1''XFFAE@R1]$R:,;WYJ9><8)B@P,H`Y +MP>:6RAX5-?]\Q,TY;A\*B58&9FYM_ +M/5(=II"YZBL!Q07-BQ7''E@?+M9(1A(^7K2(_K_0^1!%-R"BG9%\WX$S&BQI +M447_A:E]3`MY8L3$15/PLL,,V.D"<#!TS&&,2D>/W15B5L`*5Q,VXX3>OU:E +M8M.QP!MX`_DR^G^>>F$ZJ%`#44].FM;>9R>],DI:A+5J4M-\([Y<'B$8HT6O +M,3L7$@>Z6V23)DXL30&7P!MD^*E2C%HN;RG0#P:#?^H$9WSH\QV.A&\N_#PE +ME#(*4>VY3*]&JS-JQA;>ZVX*@>\RR'>XPOO[Q/-B89$#95Q>^-#UX";H%=R0+:J`P\Q,.US(!JB`7Q6EO8AC@:1'HJ!DV +M\R$FV#MK0'W.*XGF@LVCAF0BY*_CQ@8Y\>9KAXX$<*60D=9]I1`^V8!;IZJ1 +M5\1HK%V;2.$5*(11I^PR9$L!=LS0.>V5)8=N$`J3X-?:&W$02^%;ED7R]>'E +M3G:C,5I"=R(S#>;VFF!T:8H>:N\A;$3`DZ\[QS*(TM['0KDC+"PJ]?;?LX)" +M]RT?;(0ICY;HY/XV4C]LL^9+6<:]Z"]2>V*7*82U#8X5`WI%\]/_FJ,J?[^& +MP&,U*C?*1!%W!JGEO"EL]HQ.G#\ +MB1&H%Y:ZLO@L^0TH9"#?80.54)Y:)NR;2G_;/?66G880!=2O?"(Q4&^TZ-&J#+RNDBC<$HYE6M7ZQ_RKG/H;+MJN"J[SNK[H*>V^OFI@^GJPQ-0 +MVZM-/PMMC7(C$7W6IC.D$NV'S'^R`["3]:2:)ZU4E"-\FO-GFK)T=U[O7*>/ +M9&F(F&)=3D`5J'B5WE"G9-D4=I".:5-V_I83LAB7+V]2#']4.#T9J_O9UD?, +M@ONJR/4A`Z1)* +MJT?P_B,SW4S,;XG4><,28D@FJ%N66*K&<1&R%E2*"5&O%[>U20*LM"@$-WS: +M2G[W3L-3;Q\IXG#N&GXAEB$ENVP+`]QWWI;FUFNFZZMC6)[@AGZ44AJ:/[!* +MHCE?QE',)MJ!0O-N+!,F(5=0#\][W5:O6)6"NV+K,DJB-KHRE-1BZW_Q%TW3 +M9.+UJ4-UB-P&!,GZ(V(D1/4E+I%R,=[OZ,5[[W<#:.F;)&.'6P:7R82KS$=Q +MBQCV_D+<&B.1F?NVQFNA5#-UD;VRE3:Q1>20U5U0CSDH\6+IE8D'&T3`X)V@ +M/G-NDUCKD15JBL@DX]8XM(;XEX%\JU/O^977K]H4$CKJ>N^/F2\6:7IE-D5$ +MWV?@R"XQRK#!F8CDKD*84=P7]!/+$U5\!D$&:$8--5F@!+QO\_,N:@8QAP.> +METO'5=*$*7^!B&C,<7].Z7>;D?+A>ZPQA$BF,<9^/\/\"#:/9@867V="7`M' +M6;4Y4..L9^9#-Y:ECQJ:UVJ/TY+=N0`1"$82TGD$2O.%/9:-NX,_KLBYXFR2 +M!AY-\F>4\X-2,6^GP57R?T%!]JEGA@IIM:8G)._0!'Z,Z>(1CO2$#CN-&!D: +MW=^$#VYAHWK`*97^NZ";B18_)$&0$,P54J^T+]Q:1&X7ZOX +M+.6-SGM=)-;O6X(WW`6.EI%")'=N?^/'91?K1`N.!">2.%4RLKR*&UX;S+1" +M\PVI,2L&5X(&ED%7HG&)//_$)+O\_F-OH4'FF:+SUT?L&PK(K;I+IX@W6B1![(%W +M2A>[GK>WE,34L\P7KQ07_QANUF7(ULOVASH42%#LT^!]CHL3D>"Y2"[DF(`S +MT3/='[0!8%[XDG/ZI,T^X0JXA:IRH]*>X= +M]"Z=V.LJ1;]78D8*DD+[!]%)2%CX=G^<@_9MIOC`_8_AA"(TPBH7XN-*:]1V +MF<`QGL87I#TH.+%QJH][(T5NE40+NI"CP%<5NGZ*?;628\O/:4R@[<2)3O+! +ME*I9ERFSXK:\&N3(-+9_O0N69;#7VU7U@Q`-&42_6O5T1J$F<,A?,GW92OO, +MR+V^>0`2"XIT4CEF[<)^AZ#).1%MS4B!:!E">OT'X'.*<&SJ.R6@F$EC%54$ +MF36,5'`;Q([%_M"\#G\WH/$M%L/F%^=YUND)Q:J^IPPSS^3E(&QT*75E^,)M +MW#[_;$`)>3].RC7!."?J^0/2,S8(0"SL\QO:(OR!!1J)MDM9@OPYW\& +M:H*^6B-X6!C,L!Q9/1*]F.8FNJR,&2.]!B/EQYT6*[RF0`_('NY8DC493"!# +M[_8)N+5KG.`')R.``AW^93-2"9?),:`E"?N1N`B0[C21TZC#T5*WJR8AH)]; +MCBEV41)9?5[&7(^LTPRIU^A@,;Y8/-9H9.2.@0+OP`IH+*&A0J*'`U/X%3\7GN+,C);X*IE +M)FD27"H8M*O/VT^J5%(-F/9L;)FJ(1H&U=##?58FI(N4ZC=C:+NQS]1O*D"E +ML:C9%MF>5$M#%YO&2@%&TII1N1M234_2CF`9!;?P>,9WKE^4+%9J=DNM$OTA +M04QHA.U=\2^:]X$!!L^($1>51^JVZE]J'!*H;BZ>.GE&O!4,=T"@!>>/L&\$J@`%=`;*N=ESG(OAG7MIF`(Q2^:_W`JH\IU@DQ^KHZKRM*;HOB5OB0Q\-[\U")X@PWIU!I_C:[4\X.U +M]"!MK&&R.7\,>(*6ZE,\2^TE?2,GJ9WYAJXU6L"5VFX-5R%>L])(PI"$[J1@`2L@#TC@E[0B8H"MQK +MOIUWTIUB'E7.Q$`MKQ&*OT*V$27$CIJK;*CEO?=6PWJBD2\!B5'N72(D?>$I4!I[06.KT!)Y:^8B3E$A\6]GVKQ5H$- +MX\,#5;HA*G]>TQ[58K!(*%N"S0Q<(&=ILTVS_6!K>@77J#T8].5$(8%8V[M^S#"]#LO@=SO4$ +MDMK!M3083U<&)`DI+4^*.W/A(J-!(:R5#N3+"^LUGH!(/T7O3#T?A;=!AR>F +M&AFC3:2S/"'3'!G>V80+^\>:'A<^;H#1)E[^&?=WN*C4>E\8)[61*2L^><<;#R8A]"'5ND6O&_<'@C +MD"CWV]FE_[1);\69),/-(+,LJ.0LU?\H]XL8_:7H($?.0)&_"HQG,3&]EBG5 +MG2W%^1-%OU&WDS@Y6?$`^;B)C`I]!83*J#II"K<]X1'6YT,(JU!HG35]1X*S +M-5,5QA;;UJ!D1=0%3I?PF::/OZ<#L;R=$U\QS1.H.=Y+AEC.K)V!E])AA-S. +MDA!KDN^QV]F62-./+*.UTH:114D"$V$DWD#/0ME2$7S:X(*:2#N,#_QI>28\ +MKDT-3,MQ%:]@6H +M*]GUT45V.6$YM+*Y,`Q=QC(+E`H"&\85Q"3.&FB6$+IQ=$_^HA`N$;=SIDL-@1?3\>O!E;O\[$YU^(*"D@ALTGYRJRF<*+]`@[O!L.,Y9)3XPOHE[D2K5$LD',W4Q>/%F\+/'"2U/W5(E= +M=I9FG8(OQJ,M*1GQ%+%`3@WP-A,.*:T(>!\C6X+H6[?]`JJ2%]6QX&(A=:Q\ +MUJIM+))_2U.!1"!5[<8U5AZH-@VYF$C.Q2VV^AM!11S(=G;M#;*N85A^C%4I*V9?@T_ZA@8&3#]%">19T>(+BE_$:EBI7YB!'N< +M33*E_Y(CHT6.,H8#WG[0W6:79>/K<1M9FB6'B_X9\I";A;Q,[1^.O9_=(<*C +M@3']U97@UWA/Y=W4=$_FR\SB61"7M3!)+>;]&ZW+0#4*85?-$^YUVT?:7N?Q +M0_AF%#BW'`L\FJ:18?4X!NR._`[7GE?61$.FY\..[%QZ2^'F&W]Z(+7X(0;R?[J'5 +MN2]KY%$HDA^S"*VK;TQ,Z$8K3A-:)>@'K`'FO%ZX*KRLKG+P3:,,.V"@QC!S +M^DN*76M228@B^B&U20&!KB-8<&L;ZL]W4H#38W]M7^72 +M.W"!1W,5VV%8LV>:KDE:%9F)*ML^_&]6-_O?)H;R!Z%6NLWK$H/0KXUT!!I( +M.GD=DD,'GWUVF>1DX9:%G"1^#<[VJE5@!B@P"5:X1(?!J2A+`6"B```58``` +M6%```!20```3Z```$^@```_D```HH```$U@``!&(```0B```2?```!*H```2 +MJ```%!@``!08```3:```%"@``!0H```4*```$[@``!%X```2*```$[@``!*8 +M```16```%"@``!.X```0"```$[@``!#8```4&```$1@``!*H```3>```$2@` +M`!'(```4&```$.@``!*X```1R```$-@``!*H```4&```$V@``!)(```3N``` +M$J@``!08```2J```%!@``!*H```4&```$K@``!*H```4&```$X@``!.(```3 +MV```$R@``!)X```98```$N@``#?````0&```$G@``!E@```1V```$N@``!)H +M```1>```$B@``!(H```WP```$!@``!#(```32```$X@``!.(```3J```$Y@` +M`!"(```12```$@@``$FP```0B```$#@``!"(```3F```$(@``!+(```2V``` +M$M@``!"(```RT```)@```"8````36```$S@``!"(```3"```$\@``!18```4 +M6```%%@``!18```46```$#@``!18```2.```$C@``!(X```Q\```$M@``!0( +M```0F```$&@``!08```2*```$B@``!"X```2.```$+@``!(X```2.```-#`` +M`#0P```T,```-#```#0P```T,```-#```#0P```T,```-#```#0P```1N``` +M$6@``!#X```0>```$$@``!+X```3V```$,@``!-(```0R```$T@``!#(```3 +M2```$T@``!-(```32```$,@``!#(```0R```$,@``!-(```U$```-\```#A@ +M```WP```,?```%;````2B```$H@``#N````0R```$T@``#N````0R```$T@` +M`!#(```32```$H@``!&8```2N```$H@``!08```[@```$,@``!#(```32``` +M$T@``!(8```2J```$:@``!0X```1.```$_@``!*(```0J```$H@``#9@```W +MP```,?```!*(```2J```$H@``#9@```U$```$H@``!*(``!6P```$H@``!*( +M```0R```.&```!*H```42```$H@``#?````2J```$H@``#9@```V8```$J@` +M`!*H```2:```$7@``!`H```32```$_@``!*X```2:```$K@``!&H```2:``` +M$K@``!/8```3&```$U@``!)8```06```$0@``!)8```3V```$E@``!!8```0 +MR```$T@``!)8```1"```$,@``!#(```1"```$T@``!-(```0R```$T@``!/8 +M```26```$%@``!#(```32```$0@``!)8```2B```$0@``!#(```32```$]@` +M`!)8```06```$,@``!#(```0R```$,@``!#(```32```$T@``!-(```32``` +M%!@``!-(```1"```$E@``!'H```1"```$,@``!#(```32```$T@``!/8```5 +M,```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X +M```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^```#_@` +M``_X```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^``` +M#_@```_X```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/ +M^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X +M```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^```#_@` +M``_X```/^```#_@``!'X```5D```$?@``!9````1^```%M```!'X```78``` +M$?@``!?P```1^```$?@``!B@```A1```(5L``"#]```=7@``'6H``!YQ```> +M4```'5```!U0```>B@``'S$``!^B```EJ0``'LT``![-```?!0``&H$``"$; +M```CMP``)?0``!JD```=5P``&J0``!JD```<````'/$``!S^```<_@``)>`` +M`"7@```<5P``'%<``"2R```@R0``''```!QP```@/P``'^D``!XR```=N0`` +M'C(``!FR```EJ0``)<<``"6]```DU```)1H``!HQ```=ZP``(#4``"2-```C +M00``(Y@``")U```A\@``(:,``"B"```G=P``*`@``"=H```GP```)X```"A& +M```GV```*"P``"A9```F@```)H```":2```H;@``)H```":````F@```)Q`` +M`"<0```F<@``)H```"9R```F^0``)H```":^```F^0``*8L``#$P```OOP`` +M+#H``#"!```K[0``+`<``#`3```P5```,#P``"_H```P8P``*QP``"L2```K +M'```*?\``"HF```I8P``*6,``"EC```I8P``*6,``"EC```I8P``*6,``"EC +M```I8P``*6,``"EC```I8P``*6,``"EC```I8P``*6,``"EC```I8P``*6,` +M`"EC```I8P``*6,``"EC```I8P``*6,``"EC```I8P``*6,``"EC```I8P`` +M*6,``"EC```I8P``*6,``"EC```IVP``*=L``"G;```KHP``,6T``"NM```K +M0@``,4P``"NM```KP```*ZT``"NM```KP```,Z```VF```-I@``#:8```V@0``-I@``#:8```V +MF```-I@``%$0``!+(```3H```#ES```Y)@``.?D``#I*```[4@``.:@``#HJ +M```YQ```.+(``#KB```ZP@``.OX``#IF```[-@``.J(``#L:```Y%0``.9<` +M`#GH```Y8@``.-H``#R(```[LP``.ZH``$`\``!`*@``/^L``#_K```_N@`` +M/X0``#]R```_A```/X0``#YT```^K0``/DT``#XT```^-```/+```#UP``!! +M5```09(``$"@``!!$```11P``$4<``!$]P``1J@``$95``!#5```0U0``$-4 +M``!(>P``1_4``$@U``!)!@``21H``$CC``!(Q0``1C```$8(``!%<```17`` +M`$>P``!%WP``1^4``$?3``!%]```1O```$<```!&T```2,X``$(```!)I0`` +M0?4``$>```!$4P``1((``$2"``!#M```0Z<``$(N``!"(```1/<``$2U``!( +M1P``2(X``$3)``!%N```1$8``$1U``!$=0``0L$``$-4``!#`P``1S```$-4 +M``!"@```1,D``$-,``!$]P``0U0``$-4``!#`P``0P,``$@U``!(-0``0U0` +M`$K]``!-I0``3.0``$UO``!-1```3*,``$R!``!-\0``3=\``$MH``!,`0`` +M3`H``$U5``!-_@``2V@``$W%``!.'```2V@``$O)``!,T@``3CH``$Y4``!. +M<@``31,``$QP``!,70``3,@``$S2``!-"0``31,``$V>``!-E```39X``%"% +M``!0:0``4`(``$_4``!.R```4+,``%"A``!.R```3S<``$]```!0P```4-\` +M`$[(``!/R0``3[8``%!6``!030``4%8``%44``!2L@``56D``%3?``!4WP`` +M5-\``%5&``!60```5B@``%44``!5=@``45@``%4T``!3J```5(```%/A``!4 +M8```5!```%2@``!40```5,```%*'``!2T```4OX``%,V``!3;@``4Y8``%,@ +M``!3*0``4N<``%+Q``!36```4V$``%.-``!3E@``5:```%+$``!2E```5KH` +M`%()``!2$@``4;T``%%8``!4^0``5F0``%9^``!6G```4H<``%*'``!2;@`` +M5>P``%7B``!5[```5A,``%8<``!7H@``5\```%<&``!7!@``5T```%=``'__ +M[(*_<*GBTO8J#[&TS@MGB4R]0=<':N.(W\G9G;.:/7*.,11&`00&``0)I/&$ +M;(>X)P`'"P$``B,#`0$%70```0`4`P,!&P0!`0```@,$#,"<7L#`:@`("@$] +M?9*5```%`1$/`'@`.``V`&4`>`!E````%`H!```M0RMQLYT!%08!`"$````` +!```` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_lzma1_2.7z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_lzma1_2.7z.uu new file mode 100644 index 0000000..a8316cf --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_lzma1_2.7z.uu @@ -0,0 +1,240 @@ +begin 644 test_read_format_7zip_bcj2_lzma1_2.7z +M-WJ\KR<<``-^VG`E^B@```````"``````````+K(8KX`/Y%%A&@[WP)!,(6+ +M]:YDCG/TF9,6Y4@I6&:W,\L.GXAK)SG^7$ASM;Y]KP;]Q:,S]93R>,&)>5<, +M&FZE"`#6^N9W.O9$'UE^T-50DI_AD]BN$0G/D?)@D^5S4+=>0I338+60+5WO +M?S\=&H#(CWK#P8A*.F39U-N85;*`7:QH4MPY]Z"R4@0-G[PN0P/I&4U*T@DV +M'"`CQ@7=GL@J7_2-A[.]&`<]D>$^(9=0(?Z*\Z.%M#RG1BD;5#6(4_PL?`47 +M!00BJ=5&HZ7@@B$C!NO::D+1C%8P).\)*UDX0P@<+::RMJNW=<@+:$ZER\IE^S3<>=HCZTG +MM[:O[2?'(:Q@840D]\]5Y73NXY[]$A&S9_<=T[^)S9E-I@,/"Z%N3%P8EQ8N +M.<>T1U:G?9*=LX1R,65>5\LCE.PG__FU`+L]UUEKFS13]3C4N`J/2*#MK;D6 +MR_YC0[KZK#6ZDVED3OA(WO_#+'G.!7!DNT&:A<:N8%2S1T,0<.CXWI?5110E +M(]/(V5U26WQEEBY"+^%%%QQ*$$LVGS;&M##OO=PE)#7IOV]4!T0>MCVFR7A^ +M)`*]D,D*8(TTY<\22+QK022#]K1P8Q>ZDOE"5%*XR1S_RD)#8:OFV8PM<:&: +MXO9&=U7J?O95W3V[0_>S$IA67];6D(/WJJ:Q>6%"L4.3$3?0E!!$%?%!2/7& +MXB4BNO1`#[FYN$MKM,TL^'./,4GY)NO_;YJ7P +M.<8Z"R!*LK]S`B1=P4X(^JK3]7X8N(%H?=H&K>KB'G7(0C'R=1Z0Z`IBTR?O +M>DKYV:WR$Q0MRO.CI2E[0;'KUGX`,?^8H_"$EOK=81Z5Z4VZQ'O;;O;-'3N/ +MM(@343API(#U5#X1=PK%4)/F?[I"DE\39HS<'P)7H49\16$$ES92A@%4O+Y4 +MAD=?Q`Q6L[^+YH+AJ-Z!]8./"Y'^Q"*$TJ#,%/ESOJCC)X:D@0R_?J)%YC&F +M):9`]N(:_,O,>0]$-QL,-?ZE@EH7Z=TEA\M7949(]"*65FN\?-CF(U?7P0?R&\DOWV5DVFK[.JXEP>WU1IL?6K&/CWJ(7%PM9 +MZI:B)8)Q$N-53QL+1O[;'7O/7/O^;3JY[WU7(!DWS`YXM'QL?+>("XZ7)FJ3 +M#T4640CH[0Q8U319C-]L^2259=A(C)[[!/*9P+!6MXIH$N)1*Z:&QIZ7]E*8 +M%(B.D'_@P=8!H(?*X?N@HB+MAKFN3F][.%W':*1!5I4=/"TFY>,\=4<$EI/) +M\S[27U*=0/;8!0P4W/=5+RC"*W]L[Z>GIXO;=$L;^CKMC. +MFK$GA0?W<=3^K@8Y^D_FAZ!W7WZ#.6HO6/_:M&X<5E:R +MAU)=J;SF.%&+0R;V*[FQB?;-D6E*-E9A9B[,4F',0KL8S]AZ3/3,AZ!6('R] +M)>:,3R!'4,\HCK1#'3_?PE4$NKGPX,R?.IK6$:/[E%8278\-K\&D4\:14"/( +MJ(V,!$2BJH@D@[TOT`^<-9#'>!Y!%G[3Q4L[4EU[56_:"*>E#X'=E='@D%RN4=E!\F6P+B>NF-E.')J;D/S +M>](@#H.CZB,"S;X1F.)O-8.%W0+\OBW-QVYBLHRW$*]^CP(Y/U\G<3B;CDT0 +M]"EG+*#EDEZI35$5+9S&_^!_A78^X7/<2I.4Y;"H60LCL"Q.5U=,LHK4"6W:HZFZ?(LI+*? +M1?]2$%"5;V^Y]A>V$A;XY*$P"@WF:#I'$>>Z@'G8"9##/BP&7S4PR+!4&:25 +M@0#?WAT5NTR6,RW,0XNFDRGJJ'"[!B#`M[^0! +MB$_UO("?`8';,_EYIF/`YS,HY7,OO1Y`A$BAQXI(K,:Z?[$DK[LF1JP-RIXI +M[\KEKZST5NF-26U91M2>F]R-?H6.97>%;M$0B&E;\FPR!_8150K#<]3V($5- +M6SHJ[/"&TYD;ST3!R#@B92\![8+L/;^9;:^+(C'(Z[&A,_Y7P=$6SKYQ6J=0 +M*0/@I?K_Y@L:A'XR_=%D=4UM5^8.7CZKI3H%Z.&F'T_0IXB6 +M2\2+(R4=NDDVG8N]A(]M&ZH6-!N;N%IEGNP%1\$646$4*?JTOC-1%3H/UB]S +M-NON.J5*JN\71XV9L`?IV0DNQY87`Q/JQERXF.B<<1R$A7$ +M??LEM.:+%*JG+/SM23OHC_X[]'*WW.H;R658END(V=8SJK]K^DVX!XR.GLR_ +MFS_7>CF[]F7&4V3E<#!^5`/B!C955]_-N(F0[!^%U)G(DX,Y-SWE%.TJ1,KN7K_JS^OH?.6U\4@Z>K5-0[1GY` +M57LW:6>GO'!>FU^^MH"`=0.VICBJW_"`.AN^14_AL&:(BY,W +M+\E%!4$G^;3$!WW_)J>_-%0KHJUB`ADT\]#`$ +MW3*]RC&JDCHP0&BAT2\;Q#N>&MUFH8&I[^72X/_V&S]J0[4:!R+L=FR<(I>K +M3G<79].'1C5M'U>E=@A:6<8C&M4)IEIC='07>AK,.RT4,[9^6M!/QSSK`/9& +MI/X#T`#T0[ZY:H-6_F*QC:."_0I<'O:3-EJ910,KJ[^>E@H2O$OKG>0HH/;\ +M>`:*1^*-<'X_;P-,1-C>?E?<23A=YI-VJFS]NL;H`D?>=%N\ZC)L4V5TO-RL +M,S:O8KM?0')<[`-@&.`>$;')_TT/3IZX02G6'789"M6-5^4_;N;L$B053#PY8*6KD%Q\#"G99 +M*RY0Z]!B"5/58PTJAH.UI_> +M?7]0O.%'W&>\4J*)FOS]X!HZC^6GLFA%'@VA%5#''Q\V@K:?WJ>\L3D"9G\% +M![+R^KAFA7Y:!61'?B`@^9'[)U]1R,&85*!E\A5CGU:'E%0\O$LHS2\"B(18 +M$R)+4?8NA^8`SJ]-5YD)A:3U7\GMJ,K(\79#AA8J#X81K0]V6#WSKG7W7G1] +MWTS59JPM\?#9`DSGO[3FCJ1U>0F[XY,5-D!`)ERPIK8YNZ<1#3T^S:+C8/16@5 +M=L/='P>_ER`"1V@R?`1@:Q1[!6=R<"SM.1N==H%HFO'0C;.%HC""AY8(+BC0 +M_^(<;#3G4^ZS(=R32LH'F5REZ:9J?G-L9X46GT)QPNQD%CIER2^OB@<;/$ +M_%R:QR)8XMOG._E1^&KX=&ZLC"B'D1YVJ;&*&^[OM/-`LW*+@$^IEI1*2HUN +MJQ$;!@T3%"-OC(Y!&.N$]^G=1CAVWG>^;4K_CU%0O?[>H$C:%&Z#9RH1=WZI +M-'G2?PM[0DM@VUD@'#-X[!I3X\F&Q$/-C9._6,;]T=KCX)Y#+K,"OJP?9GAK-^S5RJ)0LK;Y3A54> +M@BNYR?&'45;186QEIU)WBT\DW7B?FWL.W>MQ@X.Z>"2*RFEB$JP=]&M4<+V> +M]D82H%QX6X:9COZU1JD]$X=;-3)%D'S;\?5L1[^;7F11T)=3:EQ;3M#([X>4 +M>&:!^+/A#!=)N+/]DT'U'1FKJPXL=@G^!$A6=H049Y(?^4G-.Y.4J(BY#1.4 +M:$>D@T;H$PNN>VP6G9',Q;\'M$']7TDC +M/%-"4)#^/D2F%I!-LN&EJCEVS]-O:`+MVO0,`YI(KBH\>4I`AQT>X'U5 +MT('3V/#GB:4M'08,UE]/U:&?L]AOUO6U$NF:J\#BSS8'[5F"/95"R)[@B@^( +M_]/+<%9),KA*@T80#.%W^/LT\['V\G=-6-_`,Q8=,W"*9.8P@^@YN))H,NOY +M4W@9@ZTU-J@XV.(D=_XT[[">*B,8"9RT/@M,K3(/J\Q8T(/_QSJFC-[EWGPV +MDLJ=P'\G6VL2'<>CKJGX$)05&0H?$N4,=*`+_5?7W7@?[KBY*@$<'%7QWH>& +M1A6<5`$UD3B8;S@,[1!$--9<5)=Y\0MU&;I860&<'[2K:C35?'HKD.YL1#(/ +M_N\WBKS'7LT6Z`7I&6JZ*4`0E,!)N,,`S\L-7)?K&;9;I81V+/*(=<[ZW;%I*D+@@"IEC63J81?NT^^A/!B?OJZ1?6IFN` +ML,JZ`]?W8FW'LNFBO+EJ^%>$*E64)G.V]D?]7FHW3G24:D)`BB6.R)PC>@T/ +MMH1)Y2]ED,YCW&6Y1#H.N`M\NW&B(K4/GEXYR4]/3E5/JM&7(TBV9#Y73UIJ +M"74MB'_A_60"U=9$<:=?E_:EQ#$Q['-B%F4Z'\V\^B?(>UWEK:?:N9:&]7VN +MQT"K/+E7./L_%?*NNYFS?WBHYFQ.MTF7[U%<(M&(>,>E4FK[GJC2,B8B)J[W +M]@R5F;=);`Y+[*PK'#H@PRD3RVKND8UI9/\:#<>R2`H<]#GY@H6D,GKG_+@O +MSOG[5;B=T6?,IKNB/)37_L8`3N" +MCV04E30(C[`_,C1ZM\8:&B^^KOU5L$`AL/B4[FM$"'X(X,3>V,:21%"T%K_= +M",4-.[%]PW[1EW0*.N;E=7M&MR14C4SFP,;2RTAT93N<6`4Y'.]' +M<0Y*G?\Y)K'Y,`E[^!:SZ7;[J%F(,BDT)O\.4%"^OY7BYH=[M`;APMZLWJTV +M#PLN&E9SS*W%+IK"\`](5W89"?A2QZE;+:.;UU0V*!4@-OK9WM:")2G$X-G+ +MYDLV!!0N[S-``]+V<'+4F9,3Z/IJL[?+K6%^$LW7+/+T28:LZHN_^^%)%O;V +M`!$@U\W)O\%V1=N1KA?>#2.+$,J5I\X]`L7D@B_\LHJJS%\C@&6O,)W^$1^X6SH@Q;4\*F6*L<]"^U7,:ECU%;Y;Z^AY9QD+86BL72A*#)L828G*3ZFID +MP:@S,=0>12UD`2LN_77?>SHB3H+5:(J['1-,?=,CL]S+Q5:`=U%\;L;^S03- +M*=G[8HV`*E5O4<@A)[3-2Q(!23U#1&MG_9B/`IT9E&\^J3SLK[ALL*HQ:F5T +MP7H>R>=_SQ.6[2K^^;]C@3A9ZQQ_1''XFFAE@R1]$R:,;WYJ9><8)B@P,H`Y +MP>:6RAX5-?]\Q,TY;A\*B58&9FYM_ +M/5(=II"YZBL!Q07-BQ7''E@?+M9(1A(^7K2(_K_0^1!%-R"BG9%\WX$S&BQI +M447_A:E]3`MY8L3$15/PLL,,V.D"<#!TS&&,2D>/W15B5L`*5Q,VXX3>OU:E +M8M.QP!MX`_DR^G^>>F$ZJ%`#44].FM;>9R>],DI:A+5J4M-\([Y<'B$8HT6O +M,3L7$@>Z6V23)DXL30&7P!MD^*E2C%HN;RG0#P:#?^H$9WSH\QV.A&\N_#PE +ME#(*4>VY3*]&JS-JQA;>ZVX*@>\RR'>XPOO[Q/-B89$#95Q>^-#UX";H%=R0+:J`P\Q,.US(!JB`7Q6EO8AC@:1'HJ!DV +M\R$FV#MK0'W.*XGF@LVCAF0BY*_CQ@8Y\>9KAXX$<*60D=9]I1`^V8!;IZJ1 +M5\1HK%V;2.$5*(11I^PR9$L!=LS0.>V5)8=N$`J3X-?:&W$02^%;ED7R]>'E +M3G:C,5I"=R(S#>;VFF!T:8H>:N\A;$3`DZ\[QS*(TM['0KDC+"PJ]?;?LX)" +M]RT?;(0ICY;HY/XV4C]LL^9+6<:]Z"]2>V*7*82U#8X5`WI%\]/_FJ,J?[^& +MP&,U*C?*1!%W!JGEO"EL]HQ.G#\ +MB1&H%Y:ZLO@L^0TH9"#?80.54)Y:)NR;2G_;/?66G880!=2O?"(Q4&^TZ-&J#+RNDBC<$HYE6M7ZQ_RKG/H;+MJN"J[SNK[H*>V^OFI@^GJPQ-0 +MVZM-/PMMC7(C$7W6IC.D$NV'S'^R`["3]:2:)ZU4E"-\FO-GFK)T=U[O7*>/ +M9&F(F&)=3D`5J'B5WE"G9-D4=I".:5-V_I83LAB7+V]2#']4.#T9J_O9UD?, +M@ONJR/4A`Z1)* +MJT?P_B,SW4S,;XG4><,28D@FJ%N66*K&<1&R%E2*"5&O%[>U20*LM"@$-WS: +M2G[W3L-3;Q\IXG#N&GXAEB$ENVP+`]QWWI;FUFNFZZMC6)[@AGZ44AJ:/[!* +MHCE?QE',)MJ!0O-N+!,F(5=0#\][W5:O6)6"NV+K,DJB-KHRE-1BZW_Q%TW3 +M9.+UJ4-UB-P&!,GZ(V(D1/4E+I%R,=[OZ,5[[W<#:.F;)&.'6P:7R82KS$=Q +MBQCV_D+<&B.1F?NVQFNA5#-UD;VRE3:Q1>20U5U0CSDH\6+IE8D'&T3`X)V@ +M/G-NDUCKD15JBL@DX]8XM(;XEX%\JU/O^977K]H4$CKJ>N^/F2\6:7IE-D5$ +MWV?@R"XQRK#!F8CDKD*84=P7]!/+$U5\!D$&:$8--5F@!+QO\_,N:@8QAP.> +METO'5=*$*7^!B&C,<7].Z7>;D?+A>ZPQA$BF,<9^/\/\"#:/9@867V="7`M' +M6;4Y4..L9^9#-Y:ECQJ:UVJ/TY+=N0`1"$82TGD$2O.%/9:-NX,_KLBYXFR2 +M!AY-\F>4\X-2,6^GP57R?T%!]JEGA@IIM:8G)._0!'Z,Z>(1CO2$#CN-&!D: +MW=^$#VYAHWK`*97^NZ";B18_)$&0$,P54J^T+]Q:1&X7ZOX +M+.6-SGM=)-;O6X(WW`6.EI%")'=N?^/'91?K1`N.!">2.%4RLKR*&UX;S+1" +M\PVI,2L&5X(&ED%7HG&)//_$)+O\_F-OH4'FF:+SUT?L&PK(K;I+IX@W6B1![(%W +M2A>[GK>WE,34L\P7KQ07_QANUF7(ULOVASH42%#LT^!]CHL3D>"Y2"[DF(`S +MT3/='[0!8%[XDG/ZI,T^X0JXA:IRH]*>X= +M]"Z=V.LJ1;]78D8*DD+[!]%)2%CX=G^<@_9MIOC`_8_AA"(TPBH7XN-*:]1V +MF<`QGL87I#TH.+%QJH][(T5NE40+NI"CP%<5NGZ*?;628\O/:4R@[<2)3O+! +ME*I9ERFSXK:\&N3(-+9_O0N69;#7VU7U@Q`-&42_6O5T1J$F<,A?,GW92OO, +MR+V^>0`2"XIT4CEF[<)^AZ#).1%MS4B!:!E">OT'X'.*<&SJ.R6@F$EC%54$ +MF36,5'`;Q([%_M"\#G\WH/$M%L/F%^=YUND)Q:J^IPPSS^3E(&QT*75E^,)M +MW#[_;$`)>3].RC7!."?J^0/2,S8(0"SL\QO:(OR!!1J)MDM9@OPYW\& +M:H*^6B-X6!C,L!Q9/1*]F.8FNJR,&2.]!B/EQYT6*[RF0`_('NY8DC493"!# +M[_8)N+5KG.`')R.``AW^93-2"9?),:`E"?N1N`B0[C21TZC#T5*WJR8AH)]; +MCBEV41)9?5[&7(^LTPRIU^A@,;Y8/-9H9.2.@0+OP`IH+*&A0J*'`U/X%3\7GN+,C);X*IE +M)FD27"H8M*O/VT^J5%(-F/9L;)FJ(1H&U=##?58FI(N4ZC=C:+NQS]1O*D"E +ML:C9%MF>5$M#%YO&2@%&TII1N1M234_2CF`9!;?P>,9WKE^4+%9J=DNM$OTA +M04QHA.U=\2^:]X$!!L^($1>51^JVZE]J'!*H;BZ>.GE&O!4,=T"@!>>/L&\$J@`%=`;*N=ESG(OAG7MIF`(Q2^:_W`JH\IU@DQ^KHZKRM*;HOB5OB0Q\-[\U")X@PWIU!I_C:[4\X.U +M]"!MK&&R.7\,>(*6ZE,\2^TE?2,GJ9WYAJXU6L"5VFX-5R%>L])(PI"$[J1@`2L@#TC@E[0B8H"MQK +MOIUWTIUB'E7.Q$`MKQ&*OT*V$27$CIJK;*CEO?=6PWJBD2\!B5'N72(D?>$I4!I[06.KT!)Y:^8B3E$A\6]GVKQ5H$- +MX\,#5;HA*G]>TQ[58K!(*%N"S0Q<(&=ILTVS_6!K>@77J#T8].5$(8%8V[M^S#"]#LO@=SO4$ +MDMK!M3083U<&)`DI+4^*.W/A(J-!(:R5#N3+"^LUGH!(/T7O3#T?A;=!AR>F +M&AFC3:2S/"'3'!G>V80+^\>:'A<^;H#1)E[^&?=WN*C4>E\8)[61*2L^><<;#R8A]"'5ND6O&_<'@C +MD"CWV]FE_[1);\69),/-(+,LJ.0LU?\H]XL8_:7H($?.0)&_"HQG,3&]EBG5 +MG2W%^1-%OU&WDS@Y6?$`^;B)C`I]!83*J#II"K<]X1'6YT,(JU!HG35]1X*S +M-5,5QA;;UJ!D1=0%3I?PF::/OZ<#L;R=$U\QS1.H.=Y+AEC.K)V!E])AA-S. +MDA!KDN^QV]F62-./+*.UTH:114D"$V$DWD#/0ME2$7S:X(*:2#N,#_QI>28\ +MKDT-3,MQ%:]@6H +M*]GUT45V.6$YM+*Y,`Q=QC(+E`H"&\85Q"3.&FB6$+IQ=$_^HA`N$;=SIDL-@1?3\>O!E;O\[$YU^(*"D@ALTGYRJRF<*+]`@[O!L.,Y9)3XPOHE[D2K5$LD',W4Q>/%F\+/'"2U/W5(E= +M=I9FG8(OQJ,M*1GQ%+%`3@WP-A,.*:T(>!\C6X+H6[?]`JJ2%]6QX&(A=:Q\ +MUJIM+))_2U.!1"!5[<8U5AZH-@VYF$C.Q2VV^AM!11S(=G;M#;*N85A^C%4I*V9?@T_ZA@8&3#]%">19T>(+BE_$:EBI7YB!'N< +M33*E_Y(CHT6.,H8#WG[0W6:79>/K<1M9FB6'B_X9\I";A;Q,[1^.O9_=(<*C +M@3']U97@UWA/Y=W4=$_FR\SB61"7M3!)+>;]&ZW+0#4*85?-$^YUVT?:7N?Q +M0_AF%#BW'`L\FJ:18?4X!NR._`[7GE?61$.FY\..[%QZ2^'F&W]Z(+7X(0;R?[J'5 +MN2]KY%$HDA^S"*VK;TQ,Z$8K3A-:)>@'K`'FO%ZX*KRLKG+P3:,,.V"@QC!S +M^DN*76M228@B^B&U20&!KB-8<&L;ZL]W4H#38W]M7^72 +M.W"!1W,5VV%8LV>:KDE:%9F)*ML^_&]6-_O?)H;R!Z%6NLWK$H/0KXUT!!I( +M.GD=DD,'GWUVF>1DX9:%G"1^#<[VJE5@!B@P"5:X1(?!J2A+`6"B`'__[(*_ +M<*GBTO8J#[&TS@MGB4R]0=<':N.(W\G9G;.:/7*.,11&``!@4S^M8<&.P63` +M)`;+,KS2"?Z;A7RA_=0$&\'"AAXY)C^XW9C3((:>FU,#`MX3R^HAEXQ`W/V/ +M);AC03P4*HO-^D@)`C6HHPG!%`$%U86]?<,`<*I^42Y[@7]MBJ?,QX3M3/:E +MZ9/S)=617P5Y5PZIU*:8JM;V!QV(A,(RF!F:C2+OF&6]C`#8M3!B-GH,)PY1 +M-;%69(1/24\>8N]NI*`*RQTX*!#U)B'XKW5 +M%V6Y*;=1\]!=G:91]&D7!#43@0-P7``RF#3BJBB%M%,.7\)4T&U&X/C8(4LW +M\ASM]>54Z@W1_9`Y0CEW_N9NJZWW4]4HZ+``;=&4+41:XH6=V/B0#[WJ(5^F +M^T'@XPE].>(76"[6@J7/$,#_3Q.^?,D1G90(-7#9N@JW\W:I<_X```!@/'"( +M&^G]6XWUER>23R-9*V(/<4/R5B3&S"7\S +M:FU`^C#>_:,*%#(5*,IB!S*]O_15LX>H!Q!D_\VM,"PZ>:N6=BRN-=V=;8TR +M>_16]XO)!,A.D@6P8A?CZ_F5]Y=LR5(L0_`-GEX7GC8W3"%D_*N+DI*?<<`9 +M203"1\B,5J$NKBQHD#];WLNRL5=_I/F(56'DZS_[30XJJ6`%1N59KHI,34]# +M8GP&HK\5L?&1B\W3[53)J.$==T?J@L".%=K\:(+=23HOAFY\)[RYNK6GM_%6 +M\6J+[6K>Q@(&1V3,R4CM@RS(*,9ND0\DP`%]N-8Z\$_!I=>$FD6-@V +M*1+[X_4)1^T`S7A=L5?A?\;7>+&9J?QRU9T<$I,GGM99UXHTC#[.<1Z: +M'3+=7"C\.5#<_IX&%MCL$FP4:Z>CD,7_>K)W5]^R>!3._10]``$$!@`$":3Q +M)X%N@G0`!PL!``0C`P$!!6P```$`(P,!`05L```!`",#`0$%70```0`4`P,! +M&P0!!0`$`0,"`@8!``R'N(1LP)Q>P,!J``@*`3U]DI4```4!$0\`>``X`#8` +>90!X`&4````4"@$``"U#*W&SG0$5!@$`(0`````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_lzma2_1.7z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_lzma2_1.7z.uu new file mode 100644 index 0000000..a9a19b9 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_lzma2_1.7z.uu @@ -0,0 +1,287 @@ +begin 644 test_read_format_7zip_bcj2_lzma2_1.7z +M-WJ\KR<<``.73?8V0S$```````!>`````````#]5#Z3@7ILD\%T`/Y%%A&@[ +MWP)!,(6+]:YDCG/TF9,6Y4@I6&:W,\L.GXAK)SG^7$ASM;Y]KP;]Q:,S]93R +M>,&)>5<,&FZE"`#6^N9W.O9$'UE^T-50DI_AD]BN$0G/D?)@D^5S4+=>0I33 +M8+60+5WO?S\=&H#(CWK#P8A*.F39U-N85;*`7:QH4MPY]Z"R4@0-G[PN0P/I +M&4U*T@DV'"`CQ@7=GL@J7_2-A[.]&`<]D>$^(9=0(?Z*\Z.%M#RG1BD;5#6( +M4_PL?`47!00BJ=5&HZ7@@B$C!NO::D+1C%8P).\)*UDX0P@<+::RMJNW=<@+:$ZER\IE^S3 +M<>=HCZTGM[:O[2?'(:Q@840D]\]5Y73NXY[]$A&S9_<=T[^)S9E-I@,/"Z%N +M3%P8EQ8N.<>T1U:G?9*=LX1R,65>5\LCE.PG__FU`+L]UUEKFS13]3C4N`J/ +M2*#MK;D6R_YC0[KZK#6ZDVED3OA(WO_#+'G.!7!DNT&:A<:N8%2S1T,0<.CX +MWI?5110E(]/(V5U26WQEEBY"+^%%%QQ*$$LVGS;&M##OO=PE)#7IOV]4!T0> +MMCVFR7A^)`*]D,D*8(TTY<\22+QK022#]K1P8Q>ZDOE"5%*XR1S_RD)#8:OF +MV8PM<:&:XO9&=U7J?O95W3V[0_>S$IA67];6D(/WJJ:Q>6%"L4.3$3?0E!!$ +M%?%!2/7&XB4BNO1`#[FYN$MKM,TL^'./,4GY) +MNO_;YJ7P.<8Z"R!*LK]S`B1=P4X(^JK3]7X8N(%H?=H&K>KB'G7(0C'R=1Z0 +MZ`IBTR?O>DKYV:WR$Q0MRO.CI2E[0;'KUGX`,?^8H_"$EOK=81Z5Z4VZQ'O; +M;O;-'3N/M(@343API(#U5#X1=PK%4)/F?[I"DE\39HS<'P)7H49\16$$ES92 +MA@%4O+Y4AD=?Q`Q6L[^+YH+AJ-Z!]8./"Y'^Q"*$TJ#,%/ESOJCC)X:D@0R_ +M?J)%YC&F):9`]N(:_,O,>0]$-QL,-?ZE@EH7Z=TEA\M7949(]"*65FN\?-CF(U?7P0?R&\DOWV5DVFK[.JXEP>WU1IL?6K&/C +MWJ(7%PM9ZI:B)8)Q$N-53QL+1O[;'7O/7/O^;3JY[WU7(!DWS`YXM'QL?+>( +M"XZ7)FJ3#T4640CH[0Q8U319C-]L^2259=A(C)[[!/*9P+!6MXIH$N)1*Z:& +MQIZ7]E*8%(B.D'_@P=8!H(?*X?N@HB+MAKFN3F][.%W':*1!5I4=/"TFY>,\ +M=4<$EI/)\S[27U*=0/;8!0P4W/=5+RC"*W]L[Z>GIXO;=$L;^CKMC.FK$GA0?W<=3^K@8Y^D_FAZ!W7WZ#.6HO6/_: +MM&X<5E:RAU)=J;SF.%&+0R;V*[FQB?;-D6E*-E9A9B[,4F',0KL8S]AZ3/3, +MAZ!6('R])>:,3R!'4,\HCK1#'3_?PE4$NKGPX,R?.IK6$:/[E%8278\-K\&D +M4\:14"/(J(V,!$2BJH@D@[TOT`^<-9#'>!Y!%G[3Q4L[4EU[56_:"*>E#X'= +ME='@D%RN4=E!\F6P+B>NF-E +M.')J;D/S>](@#H.CZB,"S;X1F.)O-8.%W0+\OBW-QVYBLHRW$*]^CP(Y/U\G +M<3B;CDT0]"EG+*#EDEZI35$5+9S&_^!_A78^X7/<2I.4Y;"H60LCL"Q.5U=,LHK4"6W:HZF +MZ?(LI+*?1?]2$%"5;V^Y]A>V$A;XY*$P"@WF:#I'$>>Z@'G8"9##/BP&7S4P +MR+!4&:25@0#?WAT5NTR6,RW,0XNFDRGJJ'"[! +MB#`M[^0!B$_UO("?`8';,_EYIF/`YS,HY7,OO1Y`A$BAQXI(K,:Z?[$DK[LF +M1JP-RIXI[\KEKZST5NF-26U91M2>F]R-?H6.97>%;M$0B&E;\FPR!_8150K# +M<]3V($5-6SHJ[/"&TYD;ST3!R#@B92\![8+L/;^9;:^+(C'(Z[&A,_Y7P=$6 +MSKYQ6J=0*0/@I?K_Y@L:A'XR_=%D=4UM5^8.7CZKI3H%Z.&F'T_0IXB62\2+(R4=NDDVG8N]A(]M&ZH6-!N;N%IEGNP%1\$646$4*?JTOC-1 +M%3H/UB]S-NON.J5*JN\71XV9L`?IV0DNQY87`Q/JQERXF.B +M<<1R$A7$??LEM.:+%*JG+/SM23OHC_X[]'*WW.H;R658END(V=8SJK]K^DVX +M!XR.GLR_FS_7>CF[]F7&4V3E<#!^5`/B!C955]_-N(F0[!^%U)G(DX,Y-SWE%.TJ1,KN7K_JS^OH?.6U\4@Z>K +M5-0[1GY`57LW:6>GO'!>FU^^MH"`=0.VICBJW_"`.AN^14_A +ML&:(BY,W+\E%!4$G^;3$!WW_)J>_-%0KHJUB`ADT\]#`$W3*]RC&JDCHP0&BAT2\;Q#N>&MUFH8&I[^72X/_V&S]J0[4:!R+L +M=FR<(I>K3G<79].'1C5M'U>E=@A:6<8C&M4)IEIC='07>AK,.RT4,[9^6M!/ +MQSSK`/9&I/X#T`#T0[ZY:H-6_F*QC:."_0I<'O:3-EJ910,KJ[^>E@H2O$OK +MG>0HH/;\>`:*1^*-<'X_;P-,1-C>?E?<23A=YI-VJFS]NL;H`D?>=%N\ZC)L +M4V5TO-RL,S:O8KM?0')<[`-@&.`>$;')_TT/3IZX02G6'789"M6-5^4_;N;L +M$B053#PY8*6KD +M%Q\#"G99*RY0Z]!B"5/58PT +MJAH.UI_>?7]0O.%'W&>\4J*)FOS]X!HZC^6GLFA%'@VA%5#''Q\V@K:?WJ>\ +ML3D"9G\%![+R^KAFA7Y:!61'?B`@^9'[)U]1R,&85*!E\A5CGU:'E%0\O$LH +MS2\"B(18$R)+4?8NA^8`SJ]-5YD)A:3U7\GMJ,K(\79#AA8J#X81K0]V6#WS +MKG7W7G1]WTS59JPM\?#9`DSGO[3FCJ1U>0F[XY,5-D!`)ERPIK8YNZ<1#3T^S: +M+C8/16@5=L/='P>_ER`"1V@R?`1@:Q1[!6=R<"SM.1N==H%HFO'0C;.%HC"" +MAY8(+BC0_^(<;#3G4^ZS(=R32LH'F5REZ:9J?G-L9X46GT)QPNQD%CIER2 +M^OB@<;/$_%R:QR)8XMOG._E1^&KX=&ZLC"B'D1YVJ;&*&^[OM/-`LW*+@$^I +MEI1*2HUNJQ$;!@T3%"-OC(Y!&.N$]^G=1CAVWG>^;4K_CU%0O?[>H$C:%&Z# +M9RH1=WZI-'G2?PM[0DM@VUD@'#-X[!I3X\F&Q$/-C9._6,;]T=KCX)Y#+K,"OJP?9GAK-^S5RJ)0L +MK;Y3A54>@BNYR?&'45;186QEIU)WBT\DW7B?FWL.W>MQ@X.Z>"2*RFEB$JP= +M]&M4<+V>]D82H%QX6X:9COZU1JD]$X=;-3)%D'S;\?5L1[^;7F11T)=3:EQ; +M3M#([X>4>&:!^+/A#!=)N+/]DT'U'1FKJPXL=@G^!$A6=H049Y(?^4G-.Y.4 +MJ(BY#1.4:$>D@T;H$PNN>VP6G9',Q;\'M$']7TDC/%-"4)#^/D2F%I!-LN&EJCEVS]-O:`+MVO0,`YI(KBH\>4I` +MAQT>X'U5T('3V/#GB:4M'08,UE]/U:&?L]AOUO6U$NF:J\#BSS8'[5F"/95" +MR)[@B@^(_]/+<%9),KA*@T80#.%W^/LT\['V\G=-6-_`,Q8=,W"*9.8P@^@Y +MN))H,NOY4W@9@ZTU-J@XV.(D=_XT[[">*B,8"9RT/@M,K3(/J\Q8T(/_QSJF +MC-[EWGPVDLJ=P'\G6VL2'<>CKJGX$)05&0H?$N4,=*`+_5?7W7@?[KBY*@$< +M'%7QWH>&1A6<5`$UD3B8;S@,[1!$--9<5)=Y\0MU&;I860&<'[2K:C35?'HK +MD.YL1#(/_N\WBKS'7LT6Z`7I&6JZ*4`0E,!)N,,`S\L-7)?K&;9;I81V+/*(=<[ZW;%I*D+@@"IEC63J81?NT^^A/!B?OJ +MZ1?6IFN`L,JZ`]?W8FW'LNFBO+EJ^%>$*E64)G.V]D?]7FHW3G24:D)`BB6. +MR)PC>@T/MH1)Y2]ED,YCW&6Y1#H.N`M\NW&B(K4/GEXYR4]/3E5/JM&7(TBV +M9#Y73UIJ"74MB'_A_60"U=9$<:=?E_:EQ#$Q['-B%F4Z'\V\^B?(>UWEK:?: +MN9:&]7VNQT"K/+E7./L_%?*NNYFS?WBHYFQ.MTF7[U%<(M&(>,>E4FK[GJC2 +M,B8B)J[W]@R5F;=);`Y+[*PK'#H@PRD3RVKND8UI9/\:#<>R2`H<]#GY@H6D +M,GKG_+@OSOG[5;B=T6?,IKNB/)37_L8`3N"CV04E30(C[`_,C1ZM\8:&B^^KOU5L$`AL/B4[FM$"'X(X,3>V,:2 +M1%"T%K_=",4-.[%]PW[1EW0*.N;E=7M&MR14C4SFP,;2RTAT93N< +M6`4Y'.]'<0Y*G?\Y)K'Y,`E[^!:SZ7;[J%F(,BDT)O\.4%"^OY7BYH=[M`;A +MPMZLWJTV#PLN&E9SS*W%+IK"\`](5W89"?A2QZE;+:.;UU0V*!4@-OK9WM:" +M)2G$X-G+YDLV!!0N[S-``]+V<'+4F9,3Z/IJL[?+K6%^$LW7+/+T28:LZHN_ +M^^%)%O;V`!$@U\W)O\%V1=N1KA?>#2.+$,J5I\X]`L7D@B_\LHJJS%\C@&6O,)W^$1^X6SH@Q;4\*F6*L<]"^U7,:ECU%;Y;Z^AY9QD+86BL72A*#)L82 +M8G*3ZFIDP:@S,=0>12UD`2LN_77?>SHB3H+5:(J['1-,?=,CL]S+Q5:`=U%\ +M;L;^S03-*=G[8HV`*E5O4<@A)[3-2Q(!23U#1&MG_9B/`IT9E&\^J3SLK[AL +ML*HQ:F5TP7H>R>=_SQ.6[2K^^;]C@3A9ZQQ_1''XFFAE@R1]$R:,;WYJ9><8 +M)B@P,H`YP>:6RAX5-?]\Q,TY;A\*B +M58&9FYM_/5(=II"YZBL!Q07-BQ7''E@?+M9(1A(^7K2(_K_0^1!%-R"BG9%\ +MWX$S&BQI447_A:E]3`MY8L3$15/PLL,,V.D"<#!TS&&,2D>/W15B5L`*5Q,V +MXX3>OU:E8M.QP!MX`_DR^G^>>F$ZJ%`#44].FM;>9R>],DI:A+5J4M-\([Y< +M'B$8HT6O,3L7$@>Z6V23)DXL30&7P!MD^*E2C%HN;RG0#P:#?^H$9WSH\QV. +MA&\N_#PEE#(*4>VY3*]&JS-JQA;>ZVX*@>\RR'>XPOO[Q/-B89$#95Q>^-#U +MX";H%=R0+:J`P\Q,.US(!JB`7Q6EO8AC@ +M:1'HJ!DV\R$FV#MK0'W.*XGF@LVCAF0BY*_CQ@8Y\>9KAXX$<*60D=9]I1`^ +MV8!;IZJ15\1HK%V;2.$5*(11I^PR9$L!=LS0.>V5)8=N$`J3X-?:&W$02^%; +MED7R]>'E3G:C,5I"=R(S#>;VFF!T:8H>:N\A;$3`DZ\[QS*(TM['0KDC+"PJ +M]?;?LX)"]RT?;(0ICY;HY/XV4C]LL^9+6<:]Z"]2>V*7*82U#8X5`WI%\]/_ +MFJ,J?[^&P&,U*C?*1!%W!JGEO"E +ML]HQ.G#\B1&H%Y:ZLO@L^0TH9"#?80.54)Y:)NR;2G_;/?66G880!=2O?"(Q4&^TZ-&J#+RNDBC<$HYE6M7ZQ_RKG/H;+MJN"J[SNK[H*>V^OFI +M@^GJPQ-0VZM-/PMMC7(C$7W6IC.D$NV'S'^R`["3]:2:)ZU4E"-\FO-GFK)T +M=U[O7*>/9&F(F&)=3D`5J'B5WE"G9-D4=I".:5-V_I83LAB7+V]2#']4.#T9 +MJ_O9UD?,@ONJR/4A`Z1)*JT?P_B,SW4S,;XG4><,28D@FJ%N66*K&<1&R%E2*"5&O%[>U20*L +MM"@$-WS:2G[W3L-3;Q\IXG#N&GXAEB$ENVP+`]QWWI;FUFNFZZMC6)[@AGZ4 +M4AJ:/[!*HCE?QE',)MJ!0O-N+!,F(5=0#\][W5:O6)6"NV+K,DJB-KHRE-1B +MZW_Q%TW39.+UJ4-UB-P&!,GZ(V(D1/4E+I%R,=[OZ,5[[W<#:.F;)&.'6P:7 +MR82KS$=QBQCV_D+<&B.1F?NVQFNA5#-UD;VRE3:Q1>20U5U0CSDH\6+IE8D' +M&T3`X)V@/G-NDUCKD15JBL@DX]8XM(;XEX%\JU/O^977K]H4$CKJ>N^/F2\6 +M:7IE-D5$WV?@R"XQRK#!F8CDKD*84=P7]!/+$U5\!D$&:$8--5F@!+QO\_,N +M:@8QAP.>ETO'5=*$*7^!B&C,<7].Z7>;D?+A>ZPQA$BF,<9^/\/\"#:/9@86 +M7V="7`M'6;4Y4..L9^9#-Y:ECQJ:UVJ/TY+=N0`1"$82TGD$2O.%/9:-NX,_ +MKLBYXFR2!AY-\F>4\X-2,6^GP57R?T%!]JEGA@IIM:8G)._0!'Z,Z>(1CO2$ +M#CN-&!D:W=^$#VYAHWK`*97^NZ";B18_)$&0$,P54J^T+]Q +M:1&X7ZOX+.6-SGM=)-;O6X(WW`6.EI%")'=N?^/'91?K1`N.!">2.%4RLKR* +M&UX;S+1"\PVI,2L&5X(&ED%7HG&)//_$)+O\_F-OH4'FF:+SUT?L&PK(K;I+IX@W +M6B1![(%W2A>[GK>WE,34L\P7KQ07_QANUF7(ULOVASH42%#LT^!]CHL3D>"Y +M2"[DF(`ST3/='[0!8%[XDG/ZI,T^X0JXA: +MIRH]*>X=]"Z=V.LJ1;]78D8*DD+[!]%)2%CX=G^<@_9MIOC`_8_AA"(TPBH7 +MXN-*:]1VF<`QGL87I#TH.+%QJH][(T5NE40+NI"CP%<5NGZ*?;628\O/:4R@ +M[<2)3O+!E*I9ERFSXK:\&N3(-+9_O0N69;#7VU7U@Q`-&42_6O5T1J$F<,A? +M,GW92OO,R+V^>0`2"XIT4CEF[<)^AZ#).1%MS4B!:!E">OT'X'.*<&SJ.R6@ +MF$EC%54$F36,5'`;Q([%_M"\#G\WH/$M%L/F%^=YUND)Q:J^IPPSS^3E(&QT +M*75E^,)MW#[_;$`)>3].RC7!."?J^0/2,S8(0"SL\QO:(OR!!1J)MDM +M9@OPYW\&:H*^6B-X6!C,L!Q9/1*]F.8FNJR,&2.]!B/EQYT6*[RF0`_('NY8 +MDC493"!#[_8)N+5KG.`')R.``AW^93-2"9?),:`E"?N1N`B0[C21TZC#T5*W +MJR8AH)];CBEV41)9?5[&7(^LTPRIU^A@,;Y8/-9H9.2.@0+OP`IH+*&A0J*< +MEN]^="*Y&E05'`U/X%3\7GN+ +M,C);X*IE)FD27"H8M*O/VT^J5%(-F/9L;)FJ(1H&U=##?58FI(N4ZC=C:+NQ +MS]1O*D"EL:C9%MF>5$M#%YO&2@%&TII1N1M234_2CF`9!;?P>,9WKE^4+%9J +M=DNM$OTA04QHA.U=\2^:]X$!!L^($1>51^JVZE]J'!*H;BZ>.GE&O!4,=T"@!>>/L&\$J@`%=`;*N=ESG +M(OAG7MIF`(Q2^:_W`JH\IU@DQ^KHZKRM*;HOB5OB0Q\-[\U")X@PWIU!I_ +MC:[4\X.U]"!MK&&R.7\,>(*6ZE,\2^TE?2,GJ9WYAJXU6L"5VFX-5R%>L])( +MPI"$[J1@`2L@#TC@E[ +M0B8H"MQKOIUWTIUB'E7.Q$`MKQ&*OT*V$27$CIJK;*CEO?=6PWJBD2\!B5'N +M72(D?>$I4!I[06.KT!)Y:^8B3E$A\6] +MGVKQ5H$-X\,#5;HA*G]>TQ[58K!(*%N"S0Q<(&=ILTVS_6!K>@77J#T8].5$ +M(8%8V[M^S#"]# +MLO@=SO4$DMK!M3083U<&)`DI+4^*.W/A(J-!(:R5#N3+"^LUGH!(/T7O3#T? +MA;=!AR>F&AFC3:2S/"'3'!G>V80+^\>:'A<^;H#1)E[^&?=WN*C4>E\8)[61*2L^><<;#R8A]"'5ND +M6O&_<'@CD"CWV]FE_[1);\69),/-(+,LJ.0LU?\H]XL8_:7H($?.0)&_"HQG +M,3&]EBG5G2W%^1-%OU&WDS@Y6?$`^;B)C`I]!83*J#II"K<]X1'6YT,(JU!H +MG35]1X*S-5,5QA;;UJ!D1=0%3I?PF::/OZ<#L;R=$U\QS1.H.=Y+AEC.K)V! +ME])AA-S.DA!KDN^QV]F62-./+*.UTH:114D"$V$DWD#/0ME2$7S:X(*:2#N, +M#_QI>28\KDT-3,MQ%:]@6H*]GUT45V.6$YM+*Y,`Q=QC(+E`H"&\85Q"3.&FB6$+IQ=$_^HA`N +M$;=SIDL-@1?3\>O!E;O\[$YU^(*"D@ALTGYRJRF<*+]`@[O!L.,Y9)3XPOHE[D2K5$LD',W4Q>/%F\+/'" +M2U/W5(E==I9FG8(OQJ,M*1GQ%+%`3@WP-A,.*:T(>!\C6X+H6[?]`JJ2%]6Q +MX&(A=:Q\UJIM+))_2U.!1"!5[<8U5AZH-@VYF$C.Q2VV^AM!11S(=G;M#;*N85A^C%4I*V9?@T_ZA@8&3#]%">19T>(+BE_$:EB +MI7YB!'N<33*E_Y(CHT6.,H8#WG[0W6:79>/K<1M9FB6'B_X9\I";A;Q,[1^. +MO9_=(<*C@3']U97@UWA/Y=W4=$_FR\SB61"7M3!)+>;]&ZW+0#4*85?-$^YU +MVT?:7N?Q0_AF%#BW'`L\FJ:18?4X!NR._`[7GE?61$.FY\..[%QZ2^'F&W]Z +M(+7X( +M0;R?[J'5N2]KY%$HDA^S"*VK;TQ,Z$8K3A-:)>@'K`'FO%ZX*KRLKG+P3:,, +M.V"@QC!S^DN*76M228@B^B&U20&!KB-8<&L;ZL]W4H#3 +M8W]M7^72.W"!1W,5VV%8LV>:KDE:%9F)*ML^_&]6-_O?)H;R!Z%6NLWK$H/0 +MKXUT!!I(.GD=DD,'GWUVF>1DX9:%G"1^#<[VJE5@!B@P"5:X1(?!J2A+`6"B +M````%6```%A0```4D```$^@``!/H```/Y```**```!-8```1B```$(@``$GP +M```2J```$J@``!08```4&```$V@``!0H```4*```%"@``!.X```1>```$B@` +M`!.X```2F```$5@``!0H```3N```$`@``!.X```0V```%!@``!$8```2J``` +M$W@``!$H```1R```%!@``!#H```2N```$<@``!#8```2J```%!@``!-H```2 +M2```$[@``!*H```4&```$J@``!08```2J```%!@``!*X```2J```%!@``!.( +M```3B```$]@``!,H```2>```&6```!+H```WP```$!@``!)X```98```$=@` +M`!+H```2:```$7@``!(H```2*```-\```!`8```0R```$T@``!.(```3B``` +M$Z@``!.8```0B```$4@``!((``!)L```$(@``!`X```0B```$Y@``!"(```2 +MR```$M@``!+8```0B```,M```"8````F````$U@``!,X```0B```$P@``!/( +M```46```%%@``!18```46```%%@``!`X```46```$C@``!(X```2.```,?`` +M`!+8```4"```$)@``!!H```4&```$B@``!(H```0N```$C@``!"X```2.``` +M$C@``#0P```T,```-#```#0P```T,```-#```#0P```T,```-#```#0P```T +M,```$;@``!%H```0^```$'@``!!(```2^```$]@``!#(```32```$,@``!-( +M```0R```$T@``!-(```32```$T@``!#(```0R```$,@``!#(```32```-1`` +M`#?````X8```-\```#'P``!6P```$H@``!*(```[@```$,@``!-(```[@``` +M$,@``!-(```0R```$T@``!*(```1F```$K@``!*(```4&```.X```!#(```0 +MR```$T@``!-(```2&```$J@``!&H```4.```$3@``!/X```2B```$*@``!*( +M```V8```-\```#'P```2B```$J@``!*(```V8```-1```!*(```2B```5L`` +M`!*(```2B```$,@``#A@```2J```%$@``!*(```WP```$J@``!*(```V8``` +M-F```!*H```2J```$F@``!%X```0*```$T@``!/X```2N```$F@``!*X```1 +MJ```$F@``!*X```3V```$Q@``!-8```26```$%@``!$(```26```$]@``!)8 +M```06```$,@``!-(```26```$0@``!#(```0R```$0@``!-(```32```$,@` +M`!-(```3V```$E@``!!8```0R```$T@``!$(```26```$H@``!$(```0R``` +M$T@``!/8```26```$%@``!#(```0R```$,@``!#(```0R```$T@``!-(```3 +M2```$T@``!08```32```$0@``!)8```1Z```$0@``!#(```0R```$T@``!-( +M```3V```%3````_X```/^```#_@```_X```/^```#_@```_X```/^```#_@` +M``_X```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^``` +M#_@```_X```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/ +M^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X +M```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^```#_@` +M``_X```/^```#_@```_X```/^```#_@```_X```/^```#_@```_X```/^``` +M#_@```_X```/^```#_@```_X```1^```%9```!'X```60```$?@``!;0```1 +M^```%V```!'X```7\```$?@``!'X```8H```(40``"%;```@_0``'5X``!UJ +M```><0``'E```!U0```=4```'HH``!\Q```?H@``):D``![-```>S0``'P4` +M`!J!```A&P``([<``"7T```:I```'5<``!JD```:I```'````!SQ```<_@`` +M'/X``"7@```EX```'%<``!Q7```DL@``(,D``!QP```<<```(#\``!_I```> +M,@``';D``!XR```9L@``):D``"7'```EO0``)-0``"4:```:,0``'>L``"`U +M```DC0``(T$``".8```B=0``(?(``"&C```H@@``)W<``"@(```G:```)\`` +M`">````H1@``)]@``"@L```H60``)H```":````FD@``*&X``":````F@``` +M)H```"<0```G$```)G(``":````F<@``)OD``":````FO@``)OD``"F+```Q +M,```+[\``"PZ```P@0``*^T``"P'```P$P``,%0``#`\```OZ```,&,``"L< +M```K$@``*QP``"G_```J)@``*6,``"EC```I8P``*6,``"EC```I8P``*6,` +M`"EC```I8P``*6,``"EC```I8P``*6,``"EC```I8P``*6,``"EC```I8P`` +M*6,``"EC```I8P``*6,``"EC```I8P``*6,``"EC```I8P``*6,``"EC```I +M8P``*6,``"EC```I8P``*6,``"EC```I8P``*=L``"G;```IVP``*Z,``#%M +M```KK0``*T(``#%,```KK0``*\```"NM```KK0``*\```#'+```J)@``*B8` +M`"HF```J,```*5X``"NM```KK0``*ZT``"NM```KK0``*ZT``##X```T)``` +M,]$``#0<```S*0``,R,``#,I```RY```-.```#1,```U\P``-;@``#7+```V +M0```-AX``#6T```UM```-T4``#<@```WN@``-I@``#:8```VF```-H$``#:8 +M```VF```-I@``#:8``!1$```2R```$Z````Y``!0A0``4&D``%`"``!/U```3L@``%"S``!0H0``3L@``$\W``!/0``` +M4,```%#?``!.R```3\D``$^V``!05@``4$T``%!6``!5%```4K(``%5I``!4 +MWP``5-\``%3?``!51@``5D```%8H``!5%```578``%%8``!5-```4Z@``%2` +M``!3X0``5&```%00``!4H```5$```%3```!2AP``4M```%+^``!3-@``4VX` +M`%.6``!3(```4RD``%+G``!2\0``4U@``%-A``!3C0``4Y8``%6@``!2Q``` +M4I0``%:Z``!2"0``4A(``%&]``!16```5/D``%9D``!6?@``5IP``%*'``!2 +MAP``4FX``%7L``!5X@``5>P``%83``!6'```5Z(``%?```!7!@``5P8``%=` +M``!70`!__^R"OW"IXM+V*@^QM,X+9XE,O4'7!VKCB-_)V9VSFCURCC$41@$$ +M!@`$":3XA&R'N"<`!PL!``(A(0$(%`,#`1L$`0$```(#!`S`G%[`P&H`"`H! +M/7V2E0``!0$1#P!X`#@`-@!E`'@`90```!0*`0``+4,K<;.=`14&`0`A```` +"```` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_lzma2_2.7z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_lzma2_2.7z.uu new file mode 100644 index 0000000..8a31482 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj2_lzma2_2.7z.uu @@ -0,0 +1,240 @@ +begin 644 test_read_format_7zip_bcj2_lzma2_2.7z +M-WJ\KR<<``-OBM(#`2D```````!Z`````````']'IDO@7ILD\%T`/Y%%A&@[ +MWP)!,(6+]:YDCG/TF9,6Y4@I6&:W,\L.GXAK)SG^7$ASM;Y]KP;]Q:,S]93R +M>,&)>5<,&FZE"`#6^N9W.O9$'UE^T-50DI_AD]BN$0G/D?)@D^5S4+=>0I33 +M8+60+5WO?S\=&H#(CWK#P8A*.F39U-N85;*`7:QH4MPY]Z"R4@0-G[PN0P/I +M&4U*T@DV'"`CQ@7=GL@J7_2-A[.]&`<]D>$^(9=0(?Z*\Z.%M#RG1BD;5#6( +M4_PL?`47!00BJ=5&HZ7@@B$C!NO::D+1C%8P).\)*UDX0P@<+::RMJNW=<@+:$ZER\IE^S3 +M<>=HCZTGM[:O[2?'(:Q@840D]\]5Y73NXY[]$A&S9_<=T[^)S9E-I@,/"Z%N +M3%P8EQ8N.<>T1U:G?9*=LX1R,65>5\LCE.PG__FU`+L]UUEKFS13]3C4N`J/ +M2*#MK;D6R_YC0[KZK#6ZDVED3OA(WO_#+'G.!7!DNT&:A<:N8%2S1T,0<.CX +MWI?5110E(]/(V5U26WQEEBY"+^%%%QQ*$$LVGS;&M##OO=PE)#7IOV]4!T0> +MMCVFR7A^)`*]D,D*8(TTY<\22+QK022#]K1P8Q>ZDOE"5%*XR1S_RD)#8:OF +MV8PM<:&:XO9&=U7J?O95W3V[0_>S$IA67];6D(/WJJ:Q>6%"L4.3$3?0E!!$ +M%?%!2/7&XB4BNO1`#[FYN$MKM,TL^'./,4GY) +MNO_;YJ7P.<8Z"R!*LK]S`B1=P4X(^JK3]7X8N(%H?=H&K>KB'G7(0C'R=1Z0 +MZ`IBTR?O>DKYV:WR$Q0MRO.CI2E[0;'KUGX`,?^8H_"$EOK=81Z5Z4VZQ'O; +M;O;-'3N/M(@343API(#U5#X1=PK%4)/F?[I"DE\39HS<'P)7H49\16$$ES92 +MA@%4O+Y4AD=?Q`Q6L[^+YH+AJ-Z!]8./"Y'^Q"*$TJ#,%/ESOJCC)X:D@0R_ +M?J)%YC&F):9`]N(:_,O,>0]$-QL,-?ZE@EH7Z=TEA\M7949(]"*65FN\?-CF(U?7P0?R&\DOWV5DVFK[.JXEP>WU1IL?6K&/C +MWJ(7%PM9ZI:B)8)Q$N-53QL+1O[;'7O/7/O^;3JY[WU7(!DWS`YXM'QL?+>( +M"XZ7)FJ3#T4640CH[0Q8U319C-]L^2259=A(C)[[!/*9P+!6MXIH$N)1*Z:& +MQIZ7]E*8%(B.D'_@P=8!H(?*X?N@HB+MAKFN3F][.%W':*1!5I4=/"TFY>,\ +M=4<$EI/)\S[27U*=0/;8!0P4W/=5+RC"*W]L[Z>GIXO;=$L;^CKMC.FK$GA0?W<=3^K@8Y^D_FAZ!W7WZ#.6HO6/_: +MM&X<5E:RAU)=J;SF.%&+0R;V*[FQB?;-D6E*-E9A9B[,4F',0KL8S]AZ3/3, +MAZ!6('R])>:,3R!'4,\HCK1#'3_?PE4$NKGPX,R?.IK6$:/[E%8278\-K\&D +M4\:14"/(J(V,!$2BJH@D@[TOT`^<-9#'>!Y!%G[3Q4L[4EU[56_:"*>E#X'= +ME='@D%RN4=E!\F6P+B>NF-E +M.')J;D/S>](@#H.CZB,"S;X1F.)O-8.%W0+\OBW-QVYBLHRW$*]^CP(Y/U\G +M<3B;CDT0]"EG+*#EDEZI35$5+9S&_^!_A78^X7/<2I.4Y;"H60LCL"Q.5U=,LHK4"6W:HZF +MZ?(LI+*?1?]2$%"5;V^Y]A>V$A;XY*$P"@WF:#I'$>>Z@'G8"9##/BP&7S4P +MR+!4&:25@0#?WAT5NTR6,RW,0XNFDRGJJ'"[! +MB#`M[^0!B$_UO("?`8';,_EYIF/`YS,HY7,OO1Y`A$BAQXI(K,:Z?[$DK[LF +M1JP-RIXI[\KEKZST5NF-26U91M2>F]R-?H6.97>%;M$0B&E;\FPR!_8150K# +M<]3V($5-6SHJ[/"&TYD;ST3!R#@B92\![8+L/;^9;:^+(C'(Z[&A,_Y7P=$6 +MSKYQ6J=0*0/@I?K_Y@L:A'XR_=%D=4UM5^8.7CZKI3H%Z.&F'T_0IXB62\2+(R4=NDDVG8N]A(]M&ZH6-!N;N%IEGNP%1\$646$4*?JTOC-1 +M%3H/UB]S-NON.J5*JN\71XV9L`?IV0DNQY87`Q/JQERXF.B +M<<1R$A7$??LEM.:+%*JG+/SM23OHC_X[]'*WW.H;R658END(V=8SJK]K^DVX +M!XR.GLR_FS_7>CF[]F7&4V3E<#!^5`/B!C955]_-N(F0[!^%U)G(DX,Y-SWE%.TJ1,KN7K_JS^OH?.6U\4@Z>K +M5-0[1GY`57LW:6>GO'!>FU^^MH"`=0.VICBJW_"`.AN^14_A +ML&:(BY,W+\E%!4$G^;3$!WW_)J>_-%0KHJUB`ADT\]#`$W3*]RC&JDCHP0&BAT2\;Q#N>&MUFH8&I[^72X/_V&S]J0[4:!R+L +M=FR<(I>K3G<79].'1C5M'U>E=@A:6<8C&M4)IEIC='07>AK,.RT4,[9^6M!/ +MQSSK`/9&I/X#T`#T0[ZY:H-6_F*QC:."_0I<'O:3-EJ910,KJ[^>E@H2O$OK +MG>0HH/;\>`:*1^*-<'X_;P-,1-C>?E?<23A=YI-VJFS]NL;H`D?>=%N\ZC)L +M4V5TO-RL,S:O8KM?0')<[`-@&.`>$;')_TT/3IZX02G6'789"M6-5^4_;N;L +M$B053#PY8*6KD +M%Q\#"G99*RY0Z]!B"5/58PT +MJAH.UI_>?7]0O.%'W&>\4J*)FOS]X!HZC^6GLFA%'@VA%5#''Q\V@K:?WJ>\ +ML3D"9G\%![+R^KAFA7Y:!61'?B`@^9'[)U]1R,&85*!E\A5CGU:'E%0\O$LH +MS2\"B(18$R)+4?8NA^8`SJ]-5YD)A:3U7\GMJ,K(\79#AA8J#X81K0]V6#WS +MKG7W7G1]WTS59JPM\?#9`DSGO[3FCJ1U>0F[XY,5-D!`)ERPIK8YNZ<1#3T^S: +M+C8/16@5=L/='P>_ER`"1V@R?`1@:Q1[!6=R<"SM.1N==H%HFO'0C;.%HC"" +MAY8(+BC0_^(<;#3G4^ZS(=R32LH'F5REZ:9J?G-L9X46GT)QPNQD%CIER2 +M^OB@<;/$_%R:QR)8XMOG._E1^&KX=&ZLC"B'D1YVJ;&*&^[OM/-`LW*+@$^I +MEI1*2HUNJQ$;!@T3%"-OC(Y!&.N$]^G=1CAVWG>^;4K_CU%0O?[>H$C:%&Z# +M9RH1=WZI-'G2?PM[0DM@VUD@'#-X[!I3X\F&Q$/-C9._6,;]T=KCX)Y#+K,"OJP?9GAK-^S5RJ)0L +MK;Y3A54>@BNYR?&'45;186QEIU)WBT\DW7B?FWL.W>MQ@X.Z>"2*RFEB$JP= +M]&M4<+V>]D82H%QX6X:9COZU1JD]$X=;-3)%D'S;\?5L1[^;7F11T)=3:EQ; +M3M#([X>4>&:!^+/A#!=)N+/]DT'U'1FKJPXL=@G^!$A6=H049Y(?^4G-.Y.4 +MJ(BY#1.4:$>D@T;H$PNN>VP6G9',Q;\'M$']7TDC/%-"4)#^/D2F%I!-LN&EJCEVS]-O:`+MVO0,`YI(KBH\>4I` +MAQT>X'U5T('3V/#GB:4M'08,UE]/U:&?L]AOUO6U$NF:J\#BSS8'[5F"/95" +MR)[@B@^(_]/+<%9),KA*@T80#.%W^/LT\['V\G=-6-_`,Q8=,W"*9.8P@^@Y +MN))H,NOY4W@9@ZTU-J@XV.(D=_XT[[">*B,8"9RT/@M,K3(/J\Q8T(/_QSJF +MC-[EWGPVDLJ=P'\G6VL2'<>CKJGX$)05&0H?$N4,=*`+_5?7W7@?[KBY*@$< +M'%7QWH>&1A6<5`$UD3B8;S@,[1!$--9<5)=Y\0MU&;I860&<'[2K:C35?'HK +MD.YL1#(/_N\WBKS'7LT6Z`7I&6JZ*4`0E,!)N,,`S\L-7)?K&;9;I81V+/*(=<[ZW;%I*D+@@"IEC63J81?NT^^A/!B?OJ +MZ1?6IFN`L,JZ`]?W8FW'LNFBO+EJ^%>$*E64)G.V]D?]7FHW3G24:D)`BB6. +MR)PC>@T/MH1)Y2]ED,YCW&6Y1#H.N`M\NW&B(K4/GEXYR4]/3E5/JM&7(TBV +M9#Y73UIJ"74MB'_A_60"U=9$<:=?E_:EQ#$Q['-B%F4Z'\V\^B?(>UWEK:?: +MN9:&]7VNQT"K/+E7./L_%?*NNYFS?WBHYFQ.MTF7[U%<(M&(>,>E4FK[GJC2 +M,B8B)J[W]@R5F;=);`Y+[*PK'#H@PRD3RVKND8UI9/\:#<>R2`H<]#GY@H6D +M,GKG_+@OSOG[5;B=T6?,IKNB/)37_L8`3N"CV04E30(C[`_,C1ZM\8:&B^^KOU5L$`AL/B4[FM$"'X(X,3>V,:2 +M1%"T%K_=",4-.[%]PW[1EW0*.N;E=7M&MR14C4SFP,;2RTAT93N< +M6`4Y'.]'<0Y*G?\Y)K'Y,`E[^!:SZ7;[J%F(,BDT)O\.4%"^OY7BYH=[M`;A +MPMZLWJTV#PLN&E9SS*W%+IK"\`](5W89"?A2QZE;+:.;UU0V*!4@-OK9WM:" +M)2G$X-G+YDLV!!0N[S-``]+V<'+4F9,3Z/IJL[?+K6%^$LW7+/+T28:LZHN_ +M^^%)%O;V`!$@U\W)O\%V1=N1KA?>#2.+$,J5I\X]`L7D@B_\LHJJS%\C@&6O,)W^$1^X6SH@Q;4\*F6*L<]"^U7,:ECU%;Y;Z^AY9QD+86BL72A*#)L82 +M8G*3ZFIDP:@S,=0>12UD`2LN_77?>SHB3H+5:(J['1-,?=,CL]S+Q5:`=U%\ +M;L;^S03-*=G[8HV`*E5O4<@A)[3-2Q(!23U#1&MG_9B/`IT9E&\^J3SLK[AL +ML*HQ:F5TP7H>R>=_SQ.6[2K^^;]C@3A9ZQQ_1''XFFAE@R1]$R:,;WYJ9><8 +M)B@P,H`YP>:6RAX5-?]\Q,TY;A\*B +M58&9FYM_/5(=II"YZBL!Q07-BQ7''E@?+M9(1A(^7K2(_K_0^1!%-R"BG9%\ +MWX$S&BQI447_A:E]3`MY8L3$15/PLL,,V.D"<#!TS&&,2D>/W15B5L`*5Q,V +MXX3>OU:E8M.QP!MX`_DR^G^>>F$ZJ%`#44].FM;>9R>],DI:A+5J4M-\([Y< +M'B$8HT6O,3L7$@>Z6V23)DXL30&7P!MD^*E2C%HN;RG0#P:#?^H$9WSH\QV. +MA&\N_#PEE#(*4>VY3*]&JS-JQA;>ZVX*@>\RR'>XPOO[Q/-B89$#95Q>^-#U +MX";H%=R0+:J`P\Q,.US(!JB`7Q6EO8AC@ +M:1'HJ!DV\R$FV#MK0'W.*XGF@LVCAF0BY*_CQ@8Y\>9KAXX$<*60D=9]I1`^ +MV8!;IZJ15\1HK%V;2.$5*(11I^PR9$L!=LS0.>V5)8=N$`J3X-?:&W$02^%; +MED7R]>'E3G:C,5I"=R(S#>;VFF!T:8H>:N\A;$3`DZ\[QS*(TM['0KDC+"PJ +M]?;?LX)"]RT?;(0ICY;HY/XV4C]LL^9+6<:]Z"]2>V*7*82U#8X5`WI%\]/_ +MFJ,J?[^&P&,U*C?*1!%W!JGEO"E +ML]HQ.G#\B1&H%Y:ZLO@L^0TH9"#?80.54)Y:)NR;2G_;/?66G880!=2O?"(Q4&^TZ-&J#+RNDBC<$HYE6M7ZQ_RKG/H;+MJN"J[SNK[H*>V^OFI +M@^GJPQ-0VZM-/PMMC7(C$7W6IC.D$NV'S'^R`["3]:2:)ZU4E"-\FO-GFK)T +M=U[O7*>/9&F(F&)=3D`5J'B5WE"G9-D4=I".:5-V_I83LAB7+V]2#']4.#T9 +MJ_O9UD?,@ONJR/4A`Z1)*JT?P_B,SW4S,;XG4><,28D@FJ%N66*K&<1&R%E2*"5&O%[>U20*L +MM"@$-WS:2G[W3L-3;Q\IXG#N&GXAEB$ENVP+`]QWWI;FUFNFZZMC6)[@AGZ4 +M4AJ:/[!*HCE?QE',)MJ!0O-N+!,F(5=0#\][W5:O6)6"NV+K,DJB-KHRE-1B +MZW_Q%TW39.+UJ4-UB-P&!,GZ(V(D1/4E+I%R,=[OZ,5[[W<#:.F;)&.'6P:7 +MR82KS$=QBQCV_D+<&B.1F?NVQFNA5#-UD;VRE3:Q1>20U5U0CSDH\6+IE8D' +M&T3`X)V@/G-NDUCKD15JBL@DX]8XM(;XEX%\JU/O^977K]H4$CKJ>N^/F2\6 +M:7IE-D5$WV?@R"XQRK#!F8CDKD*84=P7]!/+$U5\!D$&:$8--5F@!+QO\_,N +M:@8QAP.>ETO'5=*$*7^!B&C,<7].Z7>;D?+A>ZPQA$BF,<9^/\/\"#:/9@86 +M7V="7`M'6;4Y4..L9^9#-Y:ECQJ:UVJ/TY+=N0`1"$82TGD$2O.%/9:-NX,_ +MKLBYXFR2!AY-\F>4\X-2,6^GP57R?T%!]JEGA@IIM:8G)._0!'Z,Z>(1CO2$ +M#CN-&!D:W=^$#VYAHWK`*97^NZ";B18_)$&0$,P54J^T+]Q +M:1&X7ZOX+.6-SGM=)-;O6X(WW`6.EI%")'=N?^/'91?K1`N.!">2.%4RLKR* +M&UX;S+1"\PVI,2L&5X(&ED%7HG&)//_$)+O\_F-OH4'FF:+SUT?L&PK(K;I+IX@W +M6B1![(%W2A>[GK>WE,34L\P7KQ07_QANUF7(ULOVASH42%#LT^!]CHL3D>"Y +M2"[DF(`ST3/='[0!8%[XDG/ZI,T^X0JXA: +MIRH]*>X=]"Z=V.LJ1;]78D8*DD+[!]%)2%CX=G^<@_9MIOC`_8_AA"(TPBH7 +MXN-*:]1VF<`QGL87I#TH.+%QJH][(T5NE40+NI"CP%<5NGZ*?;628\O/:4R@ +M[<2)3O+!E*I9ERFSXK:\&N3(-+9_O0N69;#7VU7U@Q`-&42_6O5T1J$F<,A? +M,GW92OO,R+V^>0`2"XIT4CEF[<)^AZ#).1%MS4B!:!E">OT'X'.*<&SJ.R6@ +MF$EC%54$F36,5'`;Q([%_M"\#G\WH/$M%L/F%^=YUND)Q:J^IPPSS^3E(&QT +M*75E^,)MW#[_;$`)>3].RC7!."?J^0/2,S8(0"SL\QO:(OR!!1J)MDM +M9@OPYW\&:H*^6B-X6!C,L!Q9/1*]F.8FNJR,&2.]!B/EQYT6*[RF0`_('NY8 +MDC493"!#[_8)N+5KG.`')R.``AW^93-2"9?),:`E"?N1N`B0[C21TZC#T5*W +MJR8AH)];CBEV41)9?5[&7(^LTPRIU^A@,;Y8/-9H9.2.@0+OP`IH+*&A0J*< +MEN]^="*Y&E05'`U/X%3\7GN+ +M,C);X*IE)FD27"H8M*O/VT^J5%(-F/9L;)FJ(1H&U=##?58FI(N4ZC=C:+NQ +MS]1O*D"EL:C9%MF>5$M#%YO&2@%&TII1N1M234_2CF`9!;?P>,9WKE^4+%9J +M=DNM$OTA04QHA.U=\2^:]X$!!L^($1>51^JVZE]J'!*H;BZ>.GE&O!4,=T"@!>>/L&\$J@`%=`;*N=ESG +M(OAG7MIF`(Q2^:_W`JH\IU@DQ^KHZKRM*;HOB5OB0Q\-[\U")X@PWIU!I_ +MC:[4\X.U]"!MK&&R.7\,>(*6ZE,\2^TE?2,GJ9WYAJXU6L"5VFX-5R%>L])( +MPI"$[J1@`2L@#TC@E[ +M0B8H"MQKOIUWTIUB'E7.Q$`MKQ&*OT*V$27$CIJK;*CEO?=6PWJBD2\!B5'N +M72(D?>$I4!I[06.KT!)Y:^8B3E$A\6] +MGVKQ5H$-X\,#5;HA*G]>TQ[58K!(*%N"S0Q<(&=ILTVS_6!K>@77J#T8].5$ +M(8%8V[M^S#"]# +MLO@=SO4$DMK!M3083U<&)`DI+4^*.W/A(J-!(:R5#N3+"^LUGH!(/T7O3#T? +MA;=!AR>F&AFC3:2S/"'3'!G>V80+^\>:'A<^;H#1)E[^&?=WN*C4>E\8)[61*2L^><<;#R8A]"'5ND +M6O&_<'@CD"CWV]FE_[1);\69),/-(+,LJ.0LU?\H]XL8_:7H($?.0)&_"HQG +M,3&]EBG5G2W%^1-%OU&WDS@Y6?$`^;B)C`I]!83*J#II"K<]X1'6YT,(JU!H +MG35]1X*S-5,5QA;;UJ!D1=0%3I?PF::/OZ<#L;R=$U\QS1.H.=Y+AEC.K)V! +ME])AA-S.DA!KDN^QV]F62-./+*.UTH:114D"$V$DWD#/0ME2$7S:X(*:2#N, +M#_QI>28\KDT-3,MQ%:]@6H*]GUT45V.6$YM+*Y,`Q=QC(+E`H"&\85Q"3.&FB6$+IQ=$_^HA`N +M$;=SIDL-@1?3\>O!E;O\[$YU^(*"D@ALTGYRJRF<*+]`@[O!L.,Y9)3XPOHE[D2K5$LD',W4Q>/%F\+/'" +M2U/W5(E==I9FG8(OQJ,M*1GQ%+%`3@WP-A,.*:T(>!\C6X+H6[?]`JJ2%]6Q +MX&(A=:Q\UJIM+))_2U.!1"!5[<8U5AZH-@VYF$C.Q2VV^AM!11S(=G;M#;*N85A^C%4I*V9?@T_ZA@8&3#]%">19T>(+BE_$:EB +MI7YB!'N<33*E_Y(CHT6.,H8#WG[0W6:79>/K<1M9FB6'B_X9\I";A;Q,[1^. +MO9_=(<*C@3']U97@UWA/Y=W4=$_FR\SB61"7M3!)+>;]&ZW+0#4*85?-$^YU +MVT?:7N?Q0_AF%#BW'`L\FJ:18?4X!NR._`[7GE?61$.FY\..[%QZ2^'F&W]Z +M(+7X( +M0;R?[J'5N2]KY%$HDA^S"*VK;TQ,Z$8K3A-:)>@'K`'FO%ZX*KRLKG+P3:,, +M.V"@QC!S^DN*76M228@B^B&U20&!KB-8<&L;ZL]W4H#3 +M8W]M7^72.W"!1W,5VV%8LV>:KDE:%9F)*ML^_&]6-_O?)H;R!Z%6NLWK$H/0 +MKXUT!!I(.GD=DD,'GWUVF>1DX9:%G"1^#<[VJE5@!B@P"5:X1(?!J2A+`6"B +M``!__^R"OW"IXM+V*@^QM,X+9XE,O4'7!VKCB-_)V9VSFCURCC$41@``8%,_ +MK6'!CL%DP"0&RS*\T@G^FX5\H?W4!!O!PH8>.28_N-V8TR"&GIM3`P+>$\OJ +M(9>,0-S]CR6X8T$\%"J+S?I("0(UJ*,)P10!!=6%O7W#`'"J?E$N>X%_;8JG +MS,>$[4SVI>F3\R75D5\%>5<.J=2FF*K6]@<=B(3",I@9FHTB[YAEO8P`V+4P +M8C9Z#"<.436Q5F2$3TE/'F+O;J7)#ZL;Y@JYC6[]@E%9`SU*4E_91_/UGTP] +M6`Q.3?S`A/:;-2["5G]4PJ-M0.OP,X:S5W+`V(SK[)K`V2XCN('B@"LL=."@ +M0]28A^*]U1=EN2FW4?/079VF4?1I%P0U$X$#<%P`,I@TXJHHA;13#E_"5-!M +M1N#XV"%+-_(<[?7E5.H-T?V0.4(Y=_[F;JNM]U/5*.BP`&W1E"U$6N*%G=CX +MD`^]ZB%?IOM!X.,)?3GB%U@NUH*ESQ#`_T\3OGS)$9V4"#5PV;H*M_-VJ7/^ +M````8#QPB!OI_5N-]9+R[;;6`MP,RS%^5G3#E1 +M#$3`EZ4@PLLD)TUJ]29W2HQ36\-=H27+^)ZQZMGD\C62MB#W%#\E8DQG..#C +M/9M:G'U=IF::L0KY"PNDIM2JTYWYG`?P2=]<56=5Y3W^#(;]L#L&FLK\H>*2 +M^^U'LPE_,VIM0/HPWOVC"A0R%2C*8@+R03(3I(%L&(7X^OYE?>7;,E2+$/P#9Y>%YXV-TPA9/RK +MBY*2GW'`&4D$PD?(C%:A+JXL:)`_6][+LK%7?Z3YB%5AY.L_^TT.*JE@!4;E +M6:Z*3$U/0V)\!J*_%;'QD8O-T^U4R:CA'7='ZH+`CA7:_&B"W4DZ+X9N?">\ +MN;JUI[?Q5O%JG+V<$1J=N3`-1YK/E*FVQ_;`40;LJZ^7S?[/^OQN!VA>-KS= +MJ5#%T:U^#O**)TU\#7Y`\\%GB^UJWL8"!D=DS,E([8,LR"C&;I$/),`!?;C7 +M+MR6QLHPXQCR!P^O81:5^\8(Z6!:R)8)SB/GF.O!/P7)U*,]G44C?,,M0*7J +M77A)I%C8-BD2^^',N$$L'OU"7,W2$S59[!ED>..B2/FI$&+_G(%M6=OH96B= +M*36WZ;/MFF=9_1$5'Q33GD?M`,UX7;%7X7_&UWBQF:G\* +M-(P^SG$>FATRW5PH_#E0W/Z>!A;8[!)L%&NGHY#%_WJR=U??LG@4SOT4/0`! +M!`8`!`FD^">!;H)T``<+`0`$(P,!`05L```!`",#`0$%;````0`A(0$(%`,# +M`1L$`04`!`$#`@(&`0`,A[B$;,"<7L#`:@`("@$]?9*5```%`1$/`'@`.``V +?`&4`>`!E````%`H!```M0RMQLYT!%08!`"$````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj_bzip2.7z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj_bzip2.7z.uu new file mode 100644 index 0000000..7bff5c0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj_bzip2.7z.uu @@ -0,0 +1,281 @@ +begin 644 test_read_format_7zip_bcj_bzip2.7z +M-WJ\KR<<``,N`-_N2#````````!3`````````$X%(H!"6F@Y,4%9)E-97.&0 +MG@`A^G_____________________________________________@++]WN.@" +M5;2VN>I2<\E)ZWC9'+[>1Z>LW93YCGH\J@9IX>[ESG%ULGC*K5V-K;4$LZ>G +M*]8D=N='30&D-:7%;>[=PEZVF;W=>]X]WI;F[W>ZVGH7MV'I+VWO>F&^[KR> +ML^ZJ6<]IO3[WT@]?<-"0"`0R::`"8%/3```#49,F1IH!E/1-H1A3R9&&C0J> +MT8F":9H4RGL@!E3RGE-L0I^D;1E/2GY3::&IZ!3VE/4],3T4V3*>IIZC]%&@ +M:$3(&@$T`1M")O2*>1HJ?IM*;(R-J2?E1O5-ZIYI3U/-4VFIY3]4]J:F3]4: +M;U$>4]J0'J-&@```/2`>IIY(-J'J:>4:9/2&@&FAZ@-`!IZ@!@TT$(*9&(:) +MB)M3R%/1J;U-I39!B!H3!-`>ID&@>H:/*9/2::>H,(&FC`AZC0```#(``&U# +M0!H:#0&@````$FE$2":&53PTGHIZGFU4\F3-"GZ"&*-J>D/*:#31[5/34>TH +M!H](!ZC0T`VH`>HT>HT&(`&FGJ#30:&@]0`:`>H-```:!H`#&5-`-!D``T/] +M5&`````:``:````````!H````````````````````2)$F@)D#0!&C1HQ,4P( +M9-&)B94_*/1/48I^BCS5/$]34\*>D]ZIJ?J:CQJ/4VJ-DU'J>29/*/(:C(VH +M]0\4;4:;4;4])Y)ZC0:!IIH;U(/4:-&AIZCU#1_\;'^SSLZO8M)4OYVHY%(M +M@P;/0&R\QZM9+_+Y4&`!6/Z;DW`[7MI2OQJI@6%*KO\*F((#A5)A`!V[@(,O +M3D177L@'QCR>C-IY]6(BQ\)PX*E&,$6UHB(1).MSQB4JY7O&=Y-RF;;?^KGF +MK*[T514?;G4^'.>[@7#\?JET#XP$,6^T]F=V]9#;FTQP<"V?,";,64W66TC: +M646^[=\'N&_K\QH;@]+&L0H^[RN3JE[\R(9-M,YN(U0!`A9F0``-X@8]N"E7 +MP/*WOB^GS.?T(HW6^_`[VW;Y=\<.1QGSEB[E3=VC7LK=(T(50]K:@.%D4*HT +M`N!JV*AA\U1TSYEV6G,GCP"M@8?TX3#'*9<`4"*FM4!$+,W9+-=IL]M@,,DM +MY#.E6%(/I,D,R7M8]M8A%K%$!IM)U=V?>X]R9LG,"?:8M$= +M(S/9]>J7VJKFWIMJL[T")M:;(K,QK"MJD3>L:]D;NX\DQ_SVZ"ZF-T^RE#5J +MH*G+RD'=]ZSC/D&^8WD*^D$&[W[>^QG67/!;1W0NCUN_8W^_L=K8N$0$IP,9 +MY>/N@!APF[5718"H"X4&)M=066.T=9!@=F&1%FG.Z6V7(_/-_ARW_T=CK*'7 +M@NPH!#'111P1W4%481@F0!+92#>"MM@J39O:8:?/3]';:=]4$RT`X^,B-)KZ +M_@7>G]FHYDQW'I-=:ZZ.B="E^F<^WK^]/]+Y=U.@=D['UUY<>F84OD3`]GWD +M(=$[0P0=-5('XU**^>59+\(_^=-+L-;7@0>1>SX' +M+@-;KG)Y4JJ7:LN3[3")GHD-]AV_U%DFQ@HZT-.@L,,QBSATLR +MR:.+:)]2G"Y9JDK-/46L!5Y+\6DK.%#N$/9YAO^@Y/N*B7N6*Q=@*K6-V<-G +M3/([W5$D*E\EBT7,=K=XHB[?T5J`#SFZ>M*"#=QIC9\Y"++&!5F!'$=\8*:, +MKZ>0J5#YE#Q&0.E3U;#E];3F,\Q][?KD/5,[].R9RD.D>U@(0F#*4W:4>V0I +MR`E5%GZY:+8.U"=1$,F0=!;*W4TX^*)";.VWE3/Q!Y#CE"B/=-2L*UV+VN%] +M,6:\6N*AKNJ":E"D%U1U+UEX(AV#D)K:O.L!ZC&5`.3*5W0J`D:W;<3J]&\I +ME`:6S`AF*8D!`(%0,79DV_:+#:R'VEZ.-BFZ52&\9/B?N&2XKYCYFH7@R&P9 +MG&]?J-G?%!U7J3)2N;$CRU0*,UW7*1%;>< +M9C7[PI5$3/IF#[_$VU%(X@TD'Q#IPP]ZJ"LC$R-IK^PZ#9JK;G3U9[XUQGLL#>S9.IEO.Q<2!ASL0:T@3+6A;UT9A!=< +M&&B=#$E1Q[?CE848 +MBB&^T4571ZNW!E"HHQ!VC>3R:5S,B#!FXDVWE.V^E\OLZ:5\IKJZZ7$>3G?`!JJJ +MI"8R6=2ZN#+=K!YK)C'-T.[ZF%KV+-S(1P-H`$-"!I"S7P]CVU^J&8$14#HF +MHRRPGTNN<@YM0U:DK!88<8LJ89!:EK"!V:$F)&0@>98$ZA"&\R`.4F9GT^6MT/:5):H.B%L9!1D],@V8]1ENR2V_9.:4,L/3_Q+UAJ]U^?Y2F!2T*LVFM1J7+$^W[BSFO.Z?E8(=O;/!BJP.0UAR +M$F^^^,ZQBP'.A$A@EF"+-,$"6<'%[WT,V&;E4*U5^=FS+%P38\@/=4(8O/"* +M$L&UUE1L?=LV_-WJ6N(WP:Z%]N8YVR\JACE43(6K/(V30?N9OCS@=8S#[YX$ +M^Y))7"*4U1I$IC<'(Y&LL"IN?).\1*SSRN84!@LUK19![EW&(DP38@W+!7J: +M2-)D@=AWUDF&!)JP@?]I"L""BPBD%D4G/I#C*D`T0A,L##)(6V@K6+,8DM=! +M`(FQ(FP2ML0VA6@]Y"2.&U2,`*[$"-ZTD"ZYBF-?)*L(X_'Z>5%/G$2$K;2$ +MK#`2MR@6`T$-+LFDA$V@H!JP#NR0=7HY.-!FL0Z7EA``1#\_AT=1\_V>KJM' +M:^M.?_4?;;["^;59HSCKS[N=;Q=7QV=J<\8+.&"'1IS][G?*N25!/U2`)H#W +M_48#@,EZ)``=64(I$'KLK@4"1-L)9%CT<#?>!\K\7J?7J$OR7Y$^C_-U'H(\ +M2,HS4(F83+$'[LZU7\U8@>5,]'%A,T%5=^2:-[YK0[0QJ[(0Z=Z`VDXAUI]T +M3V%SK9[8QG!U.ZP^WE:+@^'1P=7A]!,C`=^R"*@=PX:M]&>.<8 +MM_)BANJE!`O@_0=0>C"1`KLAR*?O7!`A,9S:I>*=R4)X<"3]1=:-$=%$!OAN +M,L'@5O=N,%-F>=IM_5_1.8[C]C,^5]5[\GK>S>]+XO_ +M/=K94ILRG#+$,@B($R.P5D[_MI32?X?G9:5F^RWIP/'>)6>Q]#OL7?&O\AQN +M-Z4?P,,2,IH;><6!$!;&0`S9@"G-Z8X6;0B&9JD(AE#O6>Y)Z[MO%Q-R;HP[ +MOD[L#^C5Q=`].T!!2*X`#K*,+KD'UX@?GL(>SOY.J[/<7[?-,@N95M;BL^MR +M/D_?4N_7_3Q_S;\Y;,.LVO?6%UN/Q_9<_G^,S<^')D0$Z8!>,=$8+F#5H0JN +MR0"M,6ER;.P_'(H6T8<=J3-GG"4+&;.8Q?T=U,-)J@B&S:D`9&9&9TE+Q.MZ +M\$$SJ_HY5[Q)>,YENV`()`CB)]477G51?N[M,?_#L%@BLQ95%5V([,]#Z33& +MG@79DM+EHBL68I<%J5*M+1M%GD9N-JX-,R;F/-D!K*0`@2#ZW:=CZ7`_K**;R\FYSG5P!^-((@N"""""2.%5P?#@@@@8TF12U;ZY8H +MHHHKMWM[>WQC9P;V]]9G744444455555%555555555556[N[N[O$ +MXFUQ>/?);U]UUSG.=(TH:#$8A%%#Y(8,P1F0%:D02J4$>$\,."C8I3"P`%G"*JC/A$Q2/OD8,/A`%A\RF(S'*4"(?$#`)US<`>QY2$A<9@B(AV7&SM>LX" +M_0S?*D:*0H/0T>6QG_[Y>_Y7H?H]+\_;['#O_N9`:;!%UAR)0E0T$Y)P#:_T +MB&Q8D%WY%;KJ@`0U8K^:T50>,_?[:Q]?R//\R[W%8[MKLQH*W:_B8_I@?<;N +MD[V_\(W/TKGU:5AZ$1C.$#!M#9O1E9!5!2'&:D%).!G7>?^T]9/$@;Z:"AS[]V_8]&=3L[;:!!D4`6)%+/.J0D2JP(H8AII(1TN%TR1 +MOV@^G0%[/68&13S#9MQA\^RQD?=,."3R&'-X]`W&;$`H0T'S6@2+16:A!0!Q +M(*OG2JS]R!YE[*L@2&B2!V;`J2'-8`?M))UR0F4/D$GEE1$YC#GDFUS]#8G` +M\>#)#BP0PIF%)5$#[:ETS6`O$+7/0-D[]"6,G4671!U#%Q`J!NVK/%22OK;7 +MAQMM8Q@)\#!&74F(,:[K\X9V2&.UQURS +MP%[50)U!E,J@42['7CN*V6PE$%C)()@!`ZN%B8EOD@"H&^/3#4$`U%%*0X60 +MA^7L[>P%+/*V\'IZ\C=='N[-J*(;]A%MZ[-8M(CZ+VSVME?KY65")%(95N**[GR)5BYSO)*@=` +M`744(;;`==SZ)I.K8%#772*B_3/I+]\\,&-#*5H%U!/^!\)I+3W7GNZOY;/P +M1#)"*@)!Y6=9>SC+Z_RY6?(IE^YT7(E4W74%],*H^5IPO1AJ,./%TSL1F9:] +M0%#T5NE(YUP"SVZ`J9%VU@-"8`?@<.,&#$O-+"!C,C*9(L,/3R;6V%+IG11D].4$[0F;I9FAH&EI:):G +M:%&AI0C.O4+3]'..LGN6@VK!M%5B122"4"`D"HBH66"Y?NU7;PC`!4:#)42> +M^Q(QVL90*,+F1D9*J82&DYF:C"I*'$!L88,?8]7M&>.;-4\XKJ$EV:B:A2UP +MF0>I!7*JWVUM1;03QE=,B0R"\=!U7/-OB?0.'UFNA'Y5)"2"=A@+`K`-#'<5 +M08C;1X%.?L.J0*EIZ]AP.,-0:_2-NK2L_!7,DF7'\8^JJH50J$!\4<1GBJ:* +M$>7DY/IP)YA`0D3*G,`P(B`B*\.XTK.=R,&QGS!X5%-WL(G"C$XFPNT`.9HV@:H?>$? +M#P>Y/8AU_)S#$L=;2,7@E2\G04AFJ'5@4/LS%Z&Q^I7S +MMP<9FV!8*$P%H:][S,UV\?Y8;I"^TV0]46OW->TK:/2A#:VM(F[0S-/W\7;4 +M8\)`6VP`'!Y5:?PL3W\E>\UYA0I`AT<@X[>.F0`[7` +M"Z\EDAN&\UM)!S'T>.KPYK%KD7#&24%&;OW!<7%LUWF3KLTMH/W'D%0F%,8T +M7@L:S*,MZQRDX`DM&5IKV$A&";7D.O(!X;`[EDMW]QL,9\%QA,MTS+0E2,,` +M*!II4-,TMK#`L04J!6$)G+*`N1(IEU&1"8IA1(B"P/&<)H4V,;2W#$5D97A1 +M(0M:SD#X7=;OVK[0&3E%BH*@!E]D20I;"(0QJ\6:?;6\^9-A,HJ"M-P+*,1* +M,K);Q'>XMIET"H*$TN9A&*8T.4(5"9-B,3V\8UX7A@6K_0.]<"*%D1$&7BX* +M!01!&6>V8Q,&F,&%84_IIA5PP0L-DF$,`V;`/@I'6V_/YGPXK<645Q)9O5Y4 +MG[U(ERCCHA_",5&`4ZP0'P?]4#XM[QM3,S!6+RBHE6T^(1BU&QM[ +MFKA8:^#V4(`X7P@,I8.X*_=3JUYD-\\41BI,D,HB]CDH`^V +M[@.GC5QKI=5^)Z77RLH1@Q..-!E\Y339?1Z[\+O=OV6"_L42B;IAWWO2]^?A4&HJ.`+D<,"(%L-G7BQ3"U/;V0W/9IHCT>(2O!PH0]@0'TXP#LEH"U;%&%'H( +M(-"V.]7CR["S!2GB=DB"-7$&0A=C"<\=GZ^H'%&4_/**V]7NU#D,HR=&FF4. +M/B)=0:>;U`&V8VD99EY8!(RY/9V+@_[\GW1X.7GZS#1;1>7F]`YQ;)#BEIR4 +M"B?(?6<1!ZBY>F'M"*^`$H$T'UF'=FF,_$+RZOLN^6+A=C*-Q+06>RST\_/4 +M-:L:\-JH92%(5<+6"][]DFFYN'[O!`03;R7(:2SF<'@P\<$N/MD?`!VS[3,4 +M0Z$\9^R$(-?J=W?!#GGZ`E:(-_&$"R9.T(+G*.O\914+RHZ@FBOQ0,S_@R,M +M647,GF>9#N8_`Q8MA*C+9]RBJEXG6T2O>1.&'$JS +ME]];2P+2D8\$`)K(8`LZDA:$$XM9'5M8T]OEZ*.8COO3FG"I[=.SD4+\G7C< +M%8SRZ!#,OF-.4%D5^LY:?0#T:I(,F^51!]C4D&.['7PWV'Y&@(.OXZ04]T+_ +ME-;:^V-]HH^'?0]CE@(A88GZ^%>"C@:AX"PF,Z0[0S6@$E+*+J/,/&FFIV.\ +MSH]WH(,J@J!5*'@;3B:$>LPQP>6V--WE!"@A +MWFZ+;._0!QZ!]"(`C`(HG]R%'@DVA@HO\;D_7GV$S +MP\#XKO,%MA8P2$7[V0#V0&5V[I+'BIQWU*#Q8VGY=!=_VY/^.MU#_!H>3QMW +M<''6^VDDY$&2("K$20&$C"+$8V-#2$QC:4BM2!=O[V0C$L&&_>W4HV_C<[N- +MNB!1P.@EM\9\"OD=;@7F$AX3`A@Q-&'"(:7>9F%G;,`9F/72HBLJJ[,C392! +MRD!B%4/B.(I`$.F@E)AN@@BO+!U-RA;H>DU0<#G^1B4!F,1L*>&!X +MP&XU1/*]M5"V+!"$N?JP4@6"S+N@&@ZJC<\3#>^211"9%@)QJDH:2ANCAL#` +MSR07=E=30S&:'+%(W8S$GK\<%Y$4YV=0MF8PBHYOEKK$(CB0,4B!OF39YUKJ+^@U+2RMMO[MT'9Z4/`:(!@RSX1<\65 +M`&L&7("A,C.KCF,@&XC0;OIA'1`LJ-FZ="[]:S>8:V3!$'3T0*%Q#H:D#,&9 +MF%*`IELZ(9P$'.';Y,-:\RE33>IN$;9LE\T+7H?+S`"A9SNU<%=-AP' +M(.XG)DU`U`4\OQS'1#4L6UP60CEX^IUUPWV\0SY,0NWB)2(16#XQ8VLL=0H;^55*!ZV7L;`\GBT-KZ!02=;4H&9;AQE9W>K"[#V`9"7 +MMB5;31@"8*M&X:Q3JY^JXJ$0!F1GC]LZ<#K=OV8G7Y?^HRB^0_A>$Y9QCS$% +MY9]2$>XSLYWDPBV6,U.?,S2%896('1=<'$`'GWZ2G?.:/+R'6>Z'4Y_!GJQ8 +M2+%NF3"(\P'@2?1Z&%1L*#0DXG%C*!!51J,@&(P)`32EL8#$A,80]W.J%,BO +M@J`#!$R/+3'1T01<BIEZ0PA.",&!3!`PLW32TV#1Z>RD":$2A-\ +M[I[8AJ#26"J0BP2[V[N5,L1-&M"IY161DNZ9&!Y^/6;A%*UFM`DQ!/&IFRPPG`#$0`OF`\! +M29AZ'(8;F6644%0^#GA(>/F?G+"9/@\/<%R3"`+WI0A%6ZY2I8C%*&B6(JPA +M`*A`R]>KS(V5J*+;===`Q`-I-80\"%D]`:BC,@9E%,-:H50$&1!`AF48@8LE +MG/H`RSNT%&!\^B[P&^<4,^!&8$!B%A6LNC0$V$Q<#(+QA=;&A&'%OYTYY4JP +MU(MIJ,X`7N94#A>JOUX90[$@K:`-%%U;Q(&WJ!R#Y?$36OZQD1@QVVP,>?4< +MZ9+NIJ*%(CE^Q^P6_J8T$@NC7UP!&2S.42.&A\>Q(`:D6`#!?R$`M%JIF,+Q +M<4BL64&C8ISRE8*D?X%>5:4P7Z=95J1@U(R;@T+;IC8`%WBUF=0""9!)WK#- +ML4`/UY8UQKL03UF%I"_HH&<"``X:5$$K1DA<>Z9@#-M&2!5.8'P5IK\>W(K5 +M/6]M8ZWL8X7QT)XEZ:]Q+GJ8N=O8[F='[<>(J.J-ND-#(F +M?;B2IP5;\GKO6IQ73DN&3O>S<"L[.)8ZW./D86S'DWKNY9Z:N/09D)>TAS.M +MUC/75X?8Y'1S%R%'RVTI23=W%AQ0$'MU^60IQAF\G'HU+R9MY_NLT&AGJ-9>UL7<^Q\; +M1"H3C7A?HB/#A3B>+PX.)RJIW.+RGA`P[TKR#:AJNXD`I8&0#(KS`L64[D`, +M<"[I/Q6F+`6"I:N:J;UQ8>A-%3SB6-D(E/2X=[`:6/-S%618_":0"H>T]M3F +M%]0`$',I"Y#ZSDTJY:=MZ]]*1@#&>/R8'N).J6F'L93:O7_ZK&- +M=+J4!M#C0^PZQ'R99OSM*&9["5 +M4>@&B+@&DV]W7`2+BS^9M07FBQB=,#K--J7"DML!=^5NOZ^3 +M[56L#AW^/R%P,!P^OZA=;M6D+9@0+A(@8ZL.L8."3ZI5&/UH +MN]T`Y*H9Q2NP[AAOS<0U62ZA\[IGYUQT^YJP<5/M?U;YR^$R$G&(`@I.MB1[ +M=LAKY6VV$\WCI=F<]]0[FVLZNUP-!9R3<3'H\XT*4YSIE!#A(;0HN> +M_4.ZZ1-J#KRC#=7JPY0!'R_9>9T1L,22;?PK9*;HB&6_\IT1V%K"$+G(TN6# +M"<63I]7J&UM6SQ[M;_N_89UG676GLJJCI[A&G.- +M#4Z;?X4SJL/"T3R)`HD;I@@ETUJ"Z7&)17"W>FU[H/*96E-PE-ZK)UV\-$MJ=CC<8XWQ85*P;3+%D)-5:BJ.B-I=MYM.NZ!C>P$*763;W2\@L!2L+*G#D +M#(:Q=!86Z,@+(66,@."8*YCLUUEE'SS'?F0>N@2&8=7"7*D(_[T7%C&)O/>TL\TAA(;/]+J]?S?.V[MO0W&-?CMOONXO`] +MGK&:H/^(./Z0%KY$WUN#KWXB#P!X%IT$3V/+1F#&M0T3]NH<$3\)D%XBP#25 +M).%R4*$]GGK?Z%:B)G'S#I?U_'G@3$_]\4W4XJNE@=WI_;OS[C7YX%?)I*]Y25BOU,0$T-=U"X(N`,5Y!C-([HK_93>($^W +M0`U4(?G<\P,>:?0I:V`I1"07V)12`K5>$A`IF=/PC_TA>I51B$V(HO +M)Z_.6;A1C/7.,;;CX#U^AM\SH6"[EI`P8Q40'B1IUXB[F89: +M,V`-D!86LU\%QBFB-C$?RHW"=N>B&6L*B.`[QI`4(TH449MO"B+)\QK8!V:D +MQ8IJ9.L^O(NWKQS-TWTM/@P'('1%.!@4=;PT@C$FP]9]GO[.4'59ES&[B);) +M)*$5U]OD^'ZKHLQ][%S%I$@/L\WDYGNIR.'!\R]689=2,*J5"`\S0O&JS5?S-N27!WSWK +MCC[,>>>>>>>>>>>>>>?N:;E%%%% +M%%%%%%%%%%%&FC>,<3?W_PN#@X,>4[?H.2N[`O3>5/+"BA/>&2J\R-^P;A`C +MB@#EFK7VYS"I1($^D,LQ[K,^]8J0JS_M]1JL(/:P$9>/);!(,F8721;ER=XT +M"KWF//M!<%C.^5D+)J!")#OD$.<7@)/;>KPS$;$?@-6Y^.=T&H,?XO4^%?6@ +M*`"1`1L"RVRK,QGC#PQR^#\'I+#!ID+'-(*=TA8^9RS&:CV"#,_2J;^W8J]W +M?I#/QG@<.8[UXK&9)HS'C%C.11TK93]74\J`@+N5_+7U'UW$R4!!GKUX#@;@ +MY@Y[$4T:O<2@61=(BM":CC==.2RTDB#Q'*AM%SU!UIBTI6Q4)7C!!F/>10)] +MO/:R-1:T//^%M[GH&>CTCE[?)&DW%!`6>8;\)B(]D#49%Y)\,!X0`'B&ILWP +M5L@.Z`;4/)[Z8\ZT_'V>_\^_=08,`@,RMLM5_71=2OR?V;R2!";>1*5Z]]BC +MW-ZS_WU^KW\8]`Z68P-S`J.ZU.AJA"AU-&IZ1S4B[FD38E!H$2&\W8-M<=H6 +MS:4E8B"!,NEM$'WCR)WN\W@IR&HY?W5VH6P6FD*JTC6V8$OSOU;Z>/'Q-4$! +MQ6VQMC:AY',,IN\9@@J(@\#=42AF9P$20X614HY>1U@$U^'>S09:M*`2]P%R +M(6#O'>HQBHS,X=P*X+HR(H@ATYD\2K@%YU_2%!0![FG_"`NW]6)5JEZ#%<"? +MWM[M+W$UU0=ZD@L]W%1`!Z\?=VR%\W6"OF4H*S2;$`Y_4JA`II"VS#TV"HF8 +M[)3G=FC:WM+.\!&Q]L')^1RJ#XX5P+AS<&Q?P&Y[*([%C&M1G13YG%1B=KY) +M(^)R==:W=>Y(++86V&J_##[$I.&TL(HMX#P2I]&B>01 +M"HL$6>HKMU#19MW`K83F,-B$_C=>9E\'C.]+@>!H>U27I+:565#\,L]P7-3W:%J +MCX79*+WX@UA)D"D`T(P9=(BQA8BB1T;$,1%Q);=:1S]Y(C^43L]`Y5TNMY)9 +M@94X_?CJ7D18X4_5VPM*>4@&D3-MR[B)!UE+=KX@A[GR>%X?\1BAQ%=7*,+C +MG_TL^K)Z.Q9B$!814(%$3TU()0-RFU_A#_)BO.<-I0-"Q]36=QFGSW#*P`5= +M"]G".N`69-_DGB\B@.`S`NZ')/XY&P@PZU1\LD'/6$#UDU(XS%JISDTI71:. +MM+0.NJ3&P!N#8->2,W,'-D57.=Y<2#??RDLR>3#J6=:_;.EC+SQBLHA:MV;( +MGS]:GADM1K538#```````````+/]999999999999999999^+G]'.KGG]7T1Z +MP]W9V/6ERC)6N)1730JFJI#8AR4A)R,G)S:S"RR[+-+JJNLL,[:V-G:6EI:W +M>XV66Y/VX&U]_%I:7,5L6GJ:G(QZ#$V2V]]SCD>[Q>$EW-*$-<].JJI)&-JV@'.G#\%_G" +M0]I\/D;A<*?<'!>H:%MP[2E2E,/#W:KU]Y(\LK&BE3UB5Q)2:ZT-8:Y@JML[ +M)R=)$DL,D4.ZUK(&2AQHB`S1N[)PS9.IYYM#>,['\=\E)W//,Q5#B>Q%R6*7 +M3T9QR<[/U5/M!!T+`6G@:7!OGY(6CL:F:]'AVHJ"2OJ.?#7(,BF^J6\B@:.H +M@I,U@LB:@GGC<)FFX3=0WC0AI<&$BJD9%$<5&!4U"2Y6>'89^LF++*L%I-HY +MR_)@"+.8+UHDZI-A52"0C@X-4Z?H/Z^)-14W$8JQ;TF)=LW)B0KM6QB"B$$( +M02CFH0%8)J2!H3WH)1J3FAPX0UR)8'Y1FBAB/*[5P@>31C9P=EC"'$3?5GZW)ICU'9=MM:12=9/C +M;T$`PR>`R#6RD8)G"6?*I5*E,BB)!8C75\_/SSQ/$D'1$62MH&:8O:6MOW6` +MNI+[&#QB?J^E;W6$E$4!&/&Z4K\,=AHY-%X5*)A#1G%E6]2+LF/",/KLA>\= +M%$Z&GQ?FM\-I-@`?#5?HTL%#7P^\>35T7UFEUA&3]V[: +M<&AJ0AT&^\7&C8CQ4]!F(/%#N#2"R0:C:NH]`NF;FK9\:,\!04T13YZPC-V'2J; +M@L1O0TXE-?5R_3\B&J.:D&4=Q0`_,%1H4MC'7?5$J&$&])$/70RW).K,$7BZ@="'EO[[G +M!E$??QFSUDW?71DWWC>BO>X]/`<$JCI,J(?H2)-?Z3+O,_;MG9VIRLN]0/+( +MWS<%5$X'15]53GA=AA@\O,UB7C(/)\]>2SQNUZ_7U/`Q5Z]-R[>7)5T]6NFS +M1>BU?@8M'LU[&5\*IRH-$4ZI?*HSVW[+>%/_=T_!"N;S>3Z;Z7=]/\SV +M_X4/1%4N[2'V#MNJ*_,X%%79$@CQ+/DX()"0Q,*0F_8%EP_&K68A,%(V#I/M<@0C!,D7W3&+Y^^"PSFCA/&T.>Y6=1S'X=PW9W6/IS4L2!#0OO +MY\3^=]4Z#Z'ON:W&@/#!OGP,QT/`JOPI[+F\+H:J/[-W&D^'&N7J*"WDD'2< +MWR?%84?_B[DBG"A(+G#(3P`!!`8``0FP2``'"P$``@,$`@($`P,!`P$`#,#` +M:L#`:@`("@$]?9*5```%`1$/`'@`.``V`&4`>`!E````%`H!```M0RMQLYT! +*%08!`"$````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj_copy.7z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj_copy.7z.uu new file mode 100644 index 0000000..3883ab7 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj_copy.7z.uu @@ -0,0 +1,613 @@ +begin 644 test_read_format_7zip_bcj_copy.7z +M-WJ\KR<<``/3^:6)P&H```````!2`````````&3-#_Q_14Q&`0$!"0`````` +M`````@`#``$```!PE`0(-````+!F````````-``@``<`*``:`!D`!@```#0` +M```T@`0(-(`$".````#@````!0````0````#````%`$``!2!!`@4@00(%0`` +M`!4````$`````0````$``````````(`$"`"`!`@T70``-%T```4`````$``` +M`0````!@````X`0(`.`$")@"``!,!```!@`````0```"````B&```(C@!`B( +MX`0(V````-@````&````!`````0````L`0``+($$""R!!`@8````&`````0` +M```$````4.5T9!A=```8W00(&-T$"!P````<````!`````0````O;&EB97AE +M8R]L9"UE;&8N@(``!(```"]`@```````,\!```2 +M````?`(```````#.````$@```(8"````````0P```!(```!:`0```````&<& +M```2````>`$````````J````$@```&X"````````/@```!(````:`P``F.($ +M"``````0`/'_80$```````!5````$@```#,```!TX00(`````!$`\?\M`P`` +M3.0$"``````0`/'_BP(```````!B`P``$@```"L!``#4X@0(!````!$`%P`/ +M`0```````)L(```2````Y`$``-CB!`@$````$0`7`%,!`````````````!(` +M``"%`0```````!H````2````A`(````````K````$@```+0"````````*0`` +M`!(````4`0`````````````2````Y0(```````"+````$@```*$````````` +M8````!(```!)```````````````@````&P$```````!]````$@```$(!```` +M`````````!(```"!`````````!0!```2`````&QI8G5T:6PN7!E`'-T'0`@<` +M``(`.P,```````"@X@0(!18``,#B!`@%)0``Q.($"`4K``#(X@0(!34``,SB +M!`@%/```T.($"`4^``#4X@0(!4L``-CB!`@%30``@.$$"`.$$"/\E?.$$"`````#_)8#A +M!`AH`````.GX#P``_R6$X00(:`@```#I^`\``/\EB.$$"&@0````Z?@/``#_ +M)8SA!`AH&````.GX#P``_R60X00(:"````#I^`\``/\EE.$$"&@H````Z?@/ +M``#_)9CA!`AH,````.GX#P``_R6````.GX#P``_R7`X00(:(````#I^`\``/\E +MQ.$$"&B(````Z?@/``#_)#A!`AHP````.GX#P``_R7DX00(:,@` +M``#I^`\``/\EZ.$$"&C0````Z?@/``#_)>SA!`AHV````.GX#P``_R7PX00( +M:.````#I^`\``/\E].$$"&CH````Z?@/``#_)?CA!`AH\````.GX#P``_R7\ +MX00(:/@```#I^`\``/\E`.($"&@``0``Z?@/``#_)03B!`AH"`$``.GX#P`` +M_R4(X@0(:!`!``#I^`\``/\E#.($"&@8`0``Z?@/``#_)1#B!`AH(`$``.GX +M#P``_R44X@0(:"@!``#I^`\``/\E&.($"&@P`0``Z?@/``#_)1SB!`AH.`$` +M`.GX#P``_R4@X@0(:$`!``#I^`\``/\E).($"&A(`0``Z?@/``#_)2CB!`AH +M4`$``.GX#P``_R4LX@0(:%@!``#I^`\``/\E,.($"&A@`0``Z?@/``#_)33B +M!`AH:`$``.GX#P``_R4XX@0(:'`!``#I^`\``/\E/.($"&AX`0``Z?@/``#_ +M)4#B!`AH@`$``.GX#P``_R5$X@0(:(@!``#I^`\``/\E2.($"&B0`0``Z?@/ +M``#_)4SB!`AHF`$``.GX#P``_R50X@0(:*`!``#I^`\``/\E5.($"&BH`0`` +MZ?@/``#_)5CB!`AHL`$``.GX#P``_R5.($"&CP`0``Z?@/``#_)7SB!`AH^`$``.GX#P``_R6`X@0(:``"``#I^`\` +M`/\EA.($"&@(`@``Z?@/``#_)8CB!`AH$`(``.GX#P``_R6,X@0(:!@"``#I +M^`\``/\ED.($"&@@`@``Z?@/``#_)93B!`AH*`(``.GX#P`````````````Q +M[56)Y8/D\(U%"(/L!%#_=012Z)`4``#,D)"0D)"0D%6)Y5=64X/L#(MU#(M= +M$(7VC7RS!(D]Y.,$"'XUBP.%P'0OHP#@!`@/MA"$TG0C@\`!ZPH/MA"#P`&$ +MTG04@/HO=?&C`.`$"`^V$(/``832=>RXB.`$"(7`=#2+10B)!"3HZ!,``,<$ +M)'S8!`CHZ!,``.CD#P``B7PD"(E<)`2)-"3HH"@``(D$).A8$P``Z(@1``#K +MT)"0D)"0D)"0D)!5B>6#[`B`/=SB!`@`=`SK'(/`!*,(X`0(_]*A".`$"(L0 +MA=)UZ\8%W.($"`')PY!5B>6#[`BA<.$$"(7`=!*X`````(7`=`G'!"1PX00( +M_]#)PY"0D)"0D)"0D)"0D)!5B>6#[`R)'"2)="0$B7PD"(MU#(M]"(M&3(M8 +M-(M(,(M'3(M0-(M`,#G3?12X_____XL<)(MT)`2+?"0(B>Q=PWX-N`$```#K +MZ&O,`````#G!=^\YTWX?BT90B44,BT=0B44(BQPDBW0D!(M\)`B)[%WI^!$` +M`'RT.<%SVXUV`.NKC;0F`````(V\)P````!5B>6+50R+10B)50B)10Q=Z9`5 +M``"-="8`C;PG`````%6)Y8/L"(D<)(ET)`2+=0B+70R+5DR+2TR+0B@Y02A^ +M$+@!````BQPDBW0D!(GL7<-\#XM"+#E!+'_FD(UT)@!]![C_____Z]V+0U") +M10R+1E")10B+'"2+="0$B>Q=Z?@1``"-M@````"-OP````!5B>6+50R+10B) +M50B)10Q=Z4`6``"-="8`C;PG`````%6)Y8/L"(D<)(ET)`2+=0B+70R+5DR+ +M2TR+0E`Y05!^$+@!````BQPDBW0D!(GL7<-\#XM"5#E!5'_FD(UT)@!]![C_ +M____Z]V+0U")10R+1E")10B+'"2+="0$B>Q=Z?@1``"-M@````"-OP````!5 +MB>6+50R+10B)50B)10Q=Z=`6``"-="8`C;PG`````%6)Y8/L"(D<)(ET)`2+ +M=0B+70R+5DR+2TR+0A@Y01A^$+@!````BQPDBW0D!(GL7<-\#XM"'#E!''_F +MD(UT)@!]![C_____Z]V+0U")10R+1E")10B+'"2+="0$B>Q=Z?@1``"-M@`` +M``"-OP````!5B>6+50R+10B)50B)10Q=Z6`7``"-="8`C;PG`````%6)Y8/L +M"(D<)(ET)`2+=0B+70R+5DR+2TR+0B`Y02!^$+@!````BQPDBW0D!(GL7<-\ +M#XM")#E!)'_FD(UT)@!]![C_____Z]V+0U")10R+1E")10B+'"2+="0$B>Q= +MZ?@1``"-M@````"-OP````!5B>6+50R+10B)50B)10Q=Z?`7``"-="8`C;PG +M`````%6)Y8M%"(M5#(M`4(E%#(M"4(E%"%WI^!$``)"-="8`58GEBT4,BT!0 +MB44,BT4(BT!0B44(7>GX$0``D)"0D)!5B>6#[`B)'"2)="0$BT4(BTT,BP"+ +M4$"#^@=TSB!`B% +M]G4:@^H!O@$```!T0H/I%]?_____=#B-M@````")70R)10B+#>3B!`B+'"2+ +M="0$B>Q=_^&)70R)10B+'"2+="0$B>Q=Z:`8``"-=@`Q]HGPBQPDBW0D!(GL +M7<.058GE5U93@>PL!0``B848^___H:#B!`B)1>PQP*%`Y`0(B944^___B8T0 +M^___QX64^___`````(7`=0VA1.0$"(7`#X2%B/O__P````#'A8S[__\`````QX6@^___`````,>%G/O__P`` +M``#'A9C[__\`````A<")P\>%J/O__P````#'A:S[__\`````QX6P^___```` +M`,>%M/O__P````#'A:3[__\`````=`F`.``/A2H'``"+O13[__^%_P^$O@8` +M`(N%$/O__XN]%/O__\>%+/O__P````#'A3#[__\`````@^`"QX4\^___```` +M`,>%3/O__P````")A0S[___I7AT``(/X"@^$X`(``(NU&/O__X7V#X39`P`` +MBT=0@#@N#X2L`P``BT%E/O__P````"%P`^%,@,``(NU./O__XN--/O__P'>C40Q&`'0B00D +MZ&@3``"%P(G##X03"0``BY5$^___C4`0B0.)!"2)5"0$Z"@4``"+C3C[__^+ +ME4C[__^-1!D1B4,$B50D!(D$).@H%```BXTH^___#[=!""4`\```/0`@```/ +MA.!$``(E$)`B+1U#'!"3PV`0(B40D!.@H$@``QT<,`0```,=' +M$`````"+?PC'!2#C!`@!````A?]ULXN5//O__X72#X1B`P``BX44^___BY4\ +M^___B858^___BX6L^___B95@^___B85D^___BX5`^___A<`/A#B!`BA1.0$",<%).,$"`$```"%P'0EB[T4^___A?]T&XN=%/O_ +M_XUV`(M#%(D$).BX$P``BUL(A=MU[HM5[#,5H.($"`^%LP<``('$+`4``%M> +M7UW#C70F`(L-\.($"(7)#X5&_/__QT<,`0```,='$`````#I5QT``(/H`0^% +M*OS__XL=[.($"(7;#X4<_/__Z]2+E2C[___'1"0$`````(M"#(D$).B8$@`` +MBXTH^___QT0D!`````")A43[__^+01")!"3H6!$``(F%2/O__^D`'```@[TP +M^___#@^'%_[__XN5*/O__XM"%##D/0`!``"A/.0$"!G)@^'Y@\$/A<")C3#[ +M__\/A/G]__^+E4S[__^-1#,2B4,(B00DB50D!.@H%```BXU,^___B0PDZ+@3 +M``#I_AP``(N-*/O__XM!1(D$).@($```A<")A4S[__\/A)`&``"`.`!U(HD$ +M).BX$P``QP0D^M@$".C8$```A<")A4S[__\/A&D&``"+A4S[__^)!"3H&!0` +M`#N%H/O__XF%-/O__P^&P/S__XF%H/O__^E7'```C960^___B10DZ!@1``"# +MP`$/A/D$``"+1SR%P`^%!0$``(M'4(VUN?O__\=$)`CTV`0(QT0D!`$$``") +M-"2)1"0,Z*@2``"+A0S[__^%P'1SBX60^___B30DB40D!.AX$P``@\`!='.- +MA93[__^)1"0$BX60^___B00DZ"@1``"#P`%T5HN%D/O__XD$).C($0``BX64 +M^___AD?``#'A2S[__\`````QX4\^___`````,>%,/O__P`` +M``"A1.0$"(7`=0VA^.,$"(7`#X0!_?__BX48^___A<`/A7K\___I,AX``#'` +M@SWXXP0(``^5P(F%0/O__^FR&0``B00DZ!@4``"-1``"B00DZ&@3``"%P(F% +M'/O__P^$+`0```^V`SPZ#X0_!```BXT<^___B`&+C1S[__^+A1S[__^#P0'& +M0`$`#[9#`83`=#V)VNL4B`&#P0'&00$`#[9"`H/"`83`="6`.CIUYSPZ=>/& +M`3`/MD(!B$$!@\$"QD$!``^V0@*#P@&$P'7;@'G_.@^$RP,``(V%I/O__XN5 +M'/O__XE$)"B-A:S[__^)1"0DC86(^___B40D((V%H/O__XE$)!R-A9S[__^) +M1"08C868^___B40D%(V%J/O__XE$)!"-A;3[__^)1"0,C86P^___B40D",=$ +M)`24V00(B10DZ$@2``#'!1CD!`@!````@_@(#X9?`@``B[6P^___,<"%]G0@ +MN0$```"X"@```/?A@^X!B<%U\L>%L/O__P````"-0/^+O;3[__^)A;#[__\Q +MP(7_?C6)_KD!````,=MKTPJX"@```(F5!/O___?AB=.)P0.=!/O__X/N`77A +MQX6T^___`````(U`_XNUJ/O__XF%M/O__S'`A?9T(+D!````N`H```#WX8/N +M`8G!=?+'A:C[__\`````C4#_BXV,^___BY6(^___B86H^___@_D`B94@^___ +MB8TD^___#X[9`0``BXT@^___O@$````Q_XN=)/O__VO'"HF%!/O__[@*```` +M]^:)UXG&`[T$^___@\'_@]/_B=H)RG7:B?")^H/`_\>%B/O__P````"#TO_' +MA8S[__\`````BXT<^___B86(^___B96,^___B0PDZ+@3``#I,1H``(N-+/O_ +M_XU=NHN%M/O__\=$)`@%@/O__P4```"+A3#[__\[A8#[__]V!HF% +M@/O__XN%F/O__XF%A/O__^GK'0``BT=0B40D"(M'!(M`',<$)`C9!`B)1"0$ +MZ+@2``#I-2```/\DA?#9!`B+E8S[__^+A8C[___'1"0((-D$",=$)`08```` +MB50D$(E$)`R)'"3HJ!(``(D<).@8%```B86`^___Z8TD``!\"H/Z`)`/AQO^ +M__\QP#'2Z9@C``#'A;#[__\`````QX6T^___`````,>%J/O__P````#'A9C[ +M__\`````QX6<^___`````,>%H/O__P````#'A8C[__\`````QX6,^___```` +M`,>%K/O__P````"#/1SD!`@!QX6D^___`````!G`]]`A!1CD!`CI=2(``,=$ +M)`3IV`0(QP0D`0```.B($P``9LR)3>@9P"7`F`0(B40D"(E,)`2)%"3H*!,``(7`B<7UW#D(/X!'0)@_@'#X7R_O__BT,@B00DZ'@1``") +M1"0(BT,P!#XXN____BT,575E-1@>PX!@``BQFAH.($"(E%[#'`C87L_?__BWD$B87D^?__QT0D +M!,S;!`C'!"0`````Z*@3``#'!"0!````Z)@3``"%P`^$D0```,<%#.`$"%`` +M``#'!"15V00(Z(@0``"%P'0)@#@`#X43"```C87<^?__B40D",=$)`1H=`A` +MQP0D`0```.A($0``@\`!=!0/MX7>^?__9H7`=`@/M\"C#.`$",<%#.0$"`$` +M``"^$````,=$)`C(V00(B7PD!(D<).@($@``@_C_=#^#Z#&#^$=V,.BP20`` +MZ]C'!0SC!`@!````QP0D5=D$".B($```ASY__^)!"3HR!(``(/H`0^$6P8``(L5'.0$"(72=$;'!1CD!`@!````QT0D +M!&"R!`C'!"0"````Z-@2``#'1"0$8+($",<$)`,```#HV!(``,<$)(G9!`CH +MB!```(D$).C0,@``H4#D!`B%P'5!H43D!`B%P'4XH?CC!`B%P'4OH13C!`B% +MP'4FH1CC!`B%P'4=H3#D!`B%P'44BQT3B +M!`@@E@0(A#B!`C`P00(AA%.,$"(7`#X52!```H1CC!`B%P`^$P`0``,<% +MY.($")"5!`BA#.,$"(7`=)_'!>#B!`BPO`0(BX7,^?__ACY___'1"0$$.0$"(D$).@X$P``BQ40Y`0(B=#!^!_!Z!SC!`@`````Z6,I +M``"AQ.($"*/TXP0(Z6,I``#'!0SC!`@`````QP5$Y`0(`````,<%-.0$"``` +M``#I8RD``,<%&.,$"`$```#'!13C!`@`````Z6,I``#'!03C!`@!````Z6,I +M``"#YOR#SA#'!?CB!`@!````Z6,I``"#YN^#S@+'!?CB!`@`````Z6,I``#' +M!?3B!`@!````Z6,I``"#S@''!?CB!`@`````Z6,I``#'1"0(`0```,=$)`3, +MVP0(QP0D7=D$".@($P``Z6,I``#'!3#D!`@!````QP44Y`0(`````.EC*0`` +MQP4,XP0(`0```,<%1.0$"`````#'!1#C!`@`````Z6,I``#'!33D!`@!```` +MQP5$Y`0(`````,<%#.,$"`````#I8RD``,<%#.0$"`````#'!23D!`@````` +MQP7LXP0(`````.EC*0``QP4$Y`0(`0```,<%Z,0R"`````#'!3CD!`@````` +MZ6,I``#'!13C!`@!````QP48XP0(`````.EC*0``QP7XXP0(`0```.EC*0`` +MQP4(XP0(`0```.EC*0``QP4,Y`0(`0```,<%).0$"`````#'!>SC!`@````` +MZ6,I``#'!13D!`@!````QP4PY`0(`0```.EC*0``QP4\Y`0(`0```.EC*0`` +MQP4`XP0(`0```.EC*0``QP40XP0(`0```,<%#.,$"`````#'!43D!`@````` +MZ6,I``#'!43D!`@!````QP4,XP0(`````,<%$.,$"`````#I8RD``,<%_.,$ +M"`````#'!>CB!`@!````Z6,I``#'!4#D!`@!````Z6,I``#'!?SC!`@!```` +MZ6,I``#'!?SB!`@!````Z6,I``#'!>SB!`@!````QP4$XP0(`````.EC*0`` +MQP7HXP0(`0```,<%!.0$"`````#'!3CD!`@`````Z6,I``#'!0SD!`@````` +MQP4DY`0(`````,<%[.,$"`$```#I8RD``,<%".0$"`$```#I8RD``,<%'.,$ +M"`$```#I8RD``,<%..0$"`$```#'!03D!`@`````QP7HBS0(`````.EC*0`` +MQP4@Y`0(`0```.EC*0``Z,@3``"%P`^%#_K__Z'TX@0(A<`/A0+Z___'!?#B +M!`@!````Z=LI``"+'1CC!`B%VP^%K?O__XL-!.0$"(7)#X1I`0``QP7DX@0( +M8)<$".FM*P``H1CC!`B%P`^%(OO__Z$$Y`0(A<`/A!\!``#'!>3B!`C0EP0( +MZ:TK``"A$.,$"(7`="W'!>#B!`B`P`0(Z<`K``#'!>3B!`B`F`0(Z:TK``#' +M!>3B!`B@F`0(Z:TK``#'!>#B!`A`O00(Z<`K``"-G>3Y__^)7"0$QP0D>MD$ +M".A8%```B5PD!,<$)'W9!`BC\.,$".A8%```B5PD!,<$)(#9!`BC+.0$".A8 +M%```B5PD!,<$)(/9!`BC2.0$".A8%```B5PD!,<$)(;9!`BC*.0$".A8%``` +MA<"C`.0$"`^$TP```*'PXP0(A<`/A"'Y__^+'2SD!`B%VP^$$_G__XL-`.0$ +M"(7)#X0%^?__QP43B!`A`E@0(Z:TK``#'!>3B!`C0E@0(Z:TK``#' +M!>3B!`A`EP0(Z:TK``#'!>3B!`A@F`0(Z:TK``#'!>3B!`CPEP0(Z:TK``") +M7"0$QP0D[=@$".A8%```HP#D!`CI^#```)"0D)"0D)"0D)"058GE@^P8A6#["B+10C'1"0( +M`0```,<$)`$```"(1?^-1?^)1"0$Z&@0```QP,G#D(UT)@!5B>575E.#["R+ +M10B%P`^$0`$``(M%"#'_B00DZ!@4``"+%6#`/ +MM@*(1?(/MD(!B$7SC01_,?:-'(5@XP0(#[94+O*-0M`\!W:+C4*?/`=W)`^^ +MPH/H88D#ZY.+50@/M@1ZB$7R#[9$>@&(1?/KPXVV`````(U"OSP'=RL/OL*# +MZ$&)`XM%W,>`:.,$"`$```#I*3,``,<$).S;!`CH*!(``.DC,P``#[;*.PW( +MX@0(?0RAT.($"(N,B#0$``"#^7AT$P^^PHE$)`3'!"0TW`0(Z"@2``#'`___ +M___I*3,``(/$+%M>7UW#QT4(S-L$".GD,@``58GE5E.)PXTT0(/L$(L4M6CC +M!`B%T@^%E````(L$M6#C!`B#^/]T.(E$)`BA\.,$",=$)`0`````B00DZ+@0 +M``"%P'0;QT0D"`"X!`C'1"0$`0```(D$).@X$@``C78`C01;BP2%9.,$"(/X +M_W0UB40D"*$LY`0(QT0D!`````")!"3HN!```(7`=!C'1"0(`+@$",=$)`0! +M````B00DZ#@2``"#Q!!;7EW#D(UT)@"A*.0$",=$)`@`N`0(QT0D!`$```") +M!"3H.!(``.E,-```C;0F`````(V\)P`````/M\")PE6!X@#P``")Y8/L"('Z +M`$````^$Q@```'Y1@?H`H```#X1]````@?H`P```=&*!^@!@```/A'P````Q +MTJA)=%_VQ`@/A>(```#VQ`0/A+<```"X"````(UT)@#H,#0``+H!````ZSB- +M="8`@?H`$```=%B!^@`@``")]G6]N`8```#H,#0``+H!````R8G0P[@"```` +MZ#`T``"Z`0```,F)T,.X`0```.@P-```N@$```#)B=##N`4```#H,#0``+H! +M````R8G0PXGVN`,```#H,#0``+H!````R8G0PZ@"=#CVQ`)T$;@)````Z#`T +M``"Z`0```.NGN`H```#H,#0``+H!````ZY:X!````.@P-```N@$```#KA3'` +MZ#`T``"Z`0```.FT-0``N`<```#H,#0``+H!````D.FT-0``C70F`(V\)P`` +M``!5B>53@^QTB468H:#B!`B)1?@QP*$LX`0(A<`/B,0```"A1.,$"(7`=':+ +M'?3C!`B%VP^$B````(U%F(D$).BX$0``B5PD"(U=J,=$)`10````B1PDB40D +M#.AH$0``H?___Y"A(.0$"(7`=#NA+.`$"+LTVP0(A<`/A5W___^[0-L$ +M".F8-@``QP0D.0```.CX$@``@#AD#Y3`#[;`HRS@!`CI@38``(M-F(L51.,$ +M"(V!`/'O`#G0?B:-@@#Q[P`YP7TVP0(AC^__^[:-L$".F8-@``Z-@3``"0BQ4DY`0( +M58GEBT4(A=)U"HL-[.,$"(7)=`F)10A=Z1!1``"+%0SD!`B%TG0)B44(7>D@ +M2P``B44(7>F`3@``D%6)Y8/L"*'`X@0(BTT(A"*+`H@(@\`!B0+),<##H````H?CC!`B%P'5RH1SD!`B%P'1)#[=&".@0-0``B<>+0U")!"3HP#<` +M`(M-[(T<"*$Q=PXM#4(D$).C`-P``BU7LC1P0Z\F%_W3%,<#H\#$``.N\H1#D!`B# +MZ`&)1>")PHM&.,'Z'P%%X*$0Y`0(B57DBU8\$57DBTWDB<+!^A^)5"0,BU7@ +MB4PD!(E$)`B)%"3HP%8``(E\)`3'!"1XVP0(B40D"(E4)`SHB!(```%%[.FS +M.P``BT8$B50D!,<$)'+;!`B)1"0(Z(@2``")1>SIJCL``(GVC;PG`````%6) +MY593@^P0BW4(BQZ%VW4FZV&+%*A0.0$"(M-T(7`BU$,=`B+02"#P`$!PHL-^.,$ +M"(7)=`N+7="+0Q"#P`$!PH,],.0$"`&+1>B#VO\#5>CWV(E%U"'"B57PBT7P +MBQ4,X`0(`<`YT`^/+0(``(G0P?H?]WWPBU7"+`H7`#X3"`0``BT`\A<`/A;"%]@^.>P$``,=%V`````#' +M1>0`````BQTTY`0(A=MU!HM5Y(E5V(M-S(7)#XX<`0``BWWP,?;'1>P!```` +MBUW0H4#C!`B+4R"+2Q"+7=B+!)CH@#L``(L5-.0$"(72#X37````@\,!BTW< +MB5W8.4W8#XW7````BU7H`<:-'!8C7=0Y^W]>C70F`(L--.0$"(7)=`R+1P/C:X```"+%<#B!`B%TG50BPW,X@0(@ST8Y`0(`8M!"!G2@^+I@\(@@^@! +MA<")00AX4XL!B=Z($(/``8D!BU7HC1P6(UW4.?M^IHM-S#E-['1B@T7L`0-] +M\.ET/@``B?:#/1CD!`@!B=Z+%`!5=B+3=PY3=@/C"G_ +M__^AP.($"(7`=36+%`Y7>0/A9/^__^#Q#Q;7E]=PZ',X@0(QP0D"@```(E$)`3HR!```.O1B50D +M!,<$)`H```#H2!,``.N_BSU$Y`0(A?]U"(7)#X0W_O__BTW0BQT0Y`0(BU$$ +MQP0D?ML$"(/J`8T,&C'2BFP/```P>`"B40D!*%`XP0(B00DZ)@1``"%P(G"=!:+3=")%4#C!`B+00BC +M'.`$".EP/0``QP0D`````.BX$@``BUW0B5T(Z[!5B>575E.#[`R+=0B+'H7; +M#X2^````,?_K'(VV`````,<$)(G;!`B#QP+HB!(``(M;"(7;='2+0PR#\`$+ +M0Q!T[HM#4(D$).@8%```@WL(`1G2]]*#X@*-!`+0PB%P`^%=O___X7_=":AP.($"(7`=3Z+%7UW#H7UW#B50D!#'_QP0D"@`` +M`.A($P``Z1!!``")5"0$QP0D"@```.A($P``ZYF0C70F`%6)Y5=64X'L?`@` +M`(M%"(L5H.($"(E5\#'2BS")A:3W__^%]@^$,@,``(M&/(7`#X4G`P``QX6H +M]___`````)"+1@R#\`$+1A`/A.@"``"+'4#D!`B+?DR%VP^%B`0``(L-^.,$ +M"(7)#X4G!```C4W,B4PD!`^W1PB)!"3H&!(``(M&3`^W4`B!X@#P``"!^@`@ +M```/A/H```"!^@!@```/A.X```"!^@#@```/A.(```"+`#L%*.`$"`^$^P4` +M`(M&/(7`#X5J!0``BT90C9W+^___QT0D"/38!`C'1"0$`00``(D<)(E$)`SH +MJ!(``(M&3(L`.P4HX`0(#X1T!0``C97+^___HRC@!`C'!23@!`@`````QT0D +M!$````")%"3HJ!$``(/X``^.%P8``,<%(.`$"`0```#'!23@!`@!````H2#@ +M!`B-E04``(D<).CX$P``BUX4C4W,BY6D]___ +MBT,$B40D'(M"'(E$)!B+`XE$)!2+0BR)1"00#[='"HE$)`R+0B2)3"0$QP0D +MC-L$"(E$)`CHB!(``*$\Y`0(A<`/A8D"``"A".0$"(7`#X54`@``#[='""4` +M\```/0`@```/A*@!```]`&````^$G0$``(N-I/?__XM',(M7-(M)*(F-L/?_ +M_XL-_.,$"(7)#X2Z`P``C9V_]___B1PDQT0D&`<```#'1"04(````,=$)!#, +MVP0(B40D"(E4)`S'1"0$!0```.BH$```B5PD"(N=L/?__\<$)+O;!`B)7"0$ +MZ(@2``"A!.0$"(7`#X6,`0``H3CD!`B%P`^%A0,``*'HXP0(A<`/A&8#``"+ +M1RCH8#8``*$7UW#H43D!`B% +MP'4*BSWXXP0(A?]T,XN-I/?__XL=$.0$"(M1!,<$)'[;!`B#Z@&-#!HQTHG( +M]_.)1"0$Z(@2``"+E:3W__^+,H7V#X6+_/__ZY:-="8`BYVD]___BT<4BULH +MB<(PYH'Z_P```(F=K/?__P^&[@$```^VQ(U=X(E4)!")1"0,QT0D"*;;!`C' +M1"0$$````(D<).BH$@``BX6L]___B5PD",<$)+O;!`B)1"0$Z(@2``"A!.0$ +M"(7`#X1T_O__BT<8Z&`V``"A'.0$"(7`#X2._O__#[='".@0-0``B86H]___ +MZ8)$``"+0PR+C:3W__^)1"0(BT$8QP0DH-L$"(E$)`3HB!(``.FT0P``C78` +MBT,(BY6D]___B40D"(M"%,<$)*#;!`B)1"0$Z(@2``#IIT,``(L-$.0$"(U! +M_XG+B<+!^A\#1S@35SS!^Q^)3"0(B5PD#(D$)(E4)`3HP%8``(E4)`R+E:3W +M__^)1"0(BT(0QP0D>-L$"(E$)`3HB!(``.DN0@``BT<$BXVD]___B40D"(M! +M(,<$)'+;!`B)1"0$Z(@2``#I($(``(UV`*',X@0(QP0D"@```(E$)`3HR!`` +M`.GW1```C;8`````#[='".A@.```Z;5$``")]HM6/(72#X4\`0``BT90C97+ +M^___QT0D"/38!`C'1"0$`00``(D4)(E$)`SHJ!(``(V%R_O__XV=RO?__\=$ +M)`@`!```B5PD!(D$).A(%```@_C_#X0U`0``QH0%RO?__P#'!"3-VP0(Z(@2 +M``"-C6# +M[!BAU.($",=$)`A*````QT0D!`$```#'!"1DW`0(B40D#.@8$P``QP0D`0`` +M`.A8$P``B?:-O"<`````58GE5U93@>RL````BWT,C95P____BW4(H:#B!`B) +M1?`QP,=$)`B`````QT0D!`````")%"3H6!(``(7_QX5@____`````'1?C95P +M____C85L____B50D#(E\)`B)="0$B00DZ%@0``"%P(G#=#F#^_]T;8/[_@^$ +MD0```(N5;/___X'Z_P```'=*H=#B!`B+1)`TJ0``!`!T*8.%8/___P$!WH7_ +M=:&+5?`S%:#B!`B+A6#___]U9H'$K````%M>7UW#BX5@____C028B85@____ +MZ\V)%"3H"!$``.NUB?:-A7#___^#Q@&#A6#___\$@^\!QT0D"(````#'1"0$ +M`````(D$).A8$@``ZY:+E6#___^-%+J)E6#____KB>C8$P``C;8`````C;PG +M`````%6)Y5=64X'LK````(M%"(L5H.($"(E5\#'2QT0D"(````#'1"0$```` +M`(F%7/___XV%=`0``H=#B +M!`B+1)@TB<*!X@```.`/A'0!``")T,'H'@&]7/___P&%8/___^EH2P``.T(8 +M#[;9?`F`^PH/A6____^)5"0$B1PDZ$@3``#I"DP``(L5P.($"(72#X6D```` +MBQ7,X@0(BT((@^@!A<")0@@/B#8!``"+`L8`/X/``8D"`;U<____@X5@____ +M`>EH2P``BQW`X@0(A=L/A=,```"+%7UW#H="R+/<#B!`B%_W3%H@>`85@____Z7UW#)0``!`"#^`$9P(/(`>G)3P``B1PDZ`@1``#I +MMD\``*',X@0(BY5<____B40D!`^V`HD$).C($```Z590```[0A@/MME\"8#[ +M"@^%7?___XE4)`2)'"3H2!,``.E64```Z-@3``"-=@"-O"<`````58GE5U93 +M@>RL````BT4(BQ6@X@0(B57P,=+'1"0(@````,=$)`0`````B858____C85P +M____B00DZ%@2``#'A6#___\`````BY58____C85P____B40D#(V%;/___\=$ +M)`@&````B00DB50D!.A8$```A<")A5S___\/A(0#``"+A5S___^#P`*#^`$/ +MAA`!``"+G6S___^!^_\````/A[4#``"AT.($"(M$F#2I```$``^$%P,``(/[ +M(@^$#@,``(/[7`^$!0,``(N]7/___X7_?F\QV^LUBQ7,X@0(BX58____#[8, +M`XM""(/H`87`B4((#X@]`P``BP*("(/``8D"@\,!.YU<____=#"+-<#B!`B% +M]G3!H@>`85@____@[U<_____@^$@`(``(.]7/____\/A-4"``"+E5S___\!E5C_ +M___I6%$``(.]7/____\/A74"``"_`0```#'VZ:A3``"0C70F`(L5S.($"(M" +M"(/H`87`B4((#XB9`0``BP+&`%R#P`&)`J'`X@0(A<`/A>,```"+%-2#"+0@B#Z`&%P(E""`^(,P$` +M`(L"B`B#P`&)`H/&`8.%8/___P0Y_@^-W_[__Z'`X@0(BY58____A<`/MAP6 +M#X01____H#P#")!"3HR!```*'`X@0(A<`/A#7___^-M"8````` +MH#P#")!"3HR!```.F64P``B?8[0AA\"8#Y"@^%LO[_ +M_XE4)`2)#"3H2!,``.DI4P``D#M"&`^-7O[__XE4)`3'!"1<````Z$@3``#I +M\5(``(GV.T(8?`F`^0H/A:K^__^)5"0$B0PDZ$@3``#I85,``)`[0AA\"8#Y +M"@^%O_[__XE4)`2)#"3H2!,``.F64P``BPWLXP0(A`R!^_\````/ +MCJ<```"+O5S___^%_P^/O?W__X.]7/____X/A8#]__^+5?`S%:#B!`B+A6#_ +M__\/A9$!``"!Q*P```!;7E]=PXN%6/___XD$).@8%```B0`````#XBD````A?\/B+H```")UXG&BU78B<&+ +M1=R%_XE5\(E%['44.<9V08G0BU7L]_:)P3'`ZQ.-=@`[?>QV3S'),<"-M"8` +M````B4W0BTWDB474BT70BU74A7UW#A?9U"[@!```` +M,=+W]HG!BT7LB?KW\8G&BT7P]_&)P8GPZ[P/O<>#\!^)1>AU1#E]['<%.77P +M3_____#XE+____D(UT)@")\(GZ +M]]B#T@#WVO=5Y.D&5P``N"````")\BM%Z(G!T^H/MDWHB47TB?B)UXM5[-/@ +M"<>+1?#3Y@^V3?33Z`^V3>C3X@^V3?0)T(M5[(E%S-/J]_>)553@^P$H6#A!`B#^/]T$C';_]"+@USA!`B#ZP2#^/]U\(/$!%M= +MPY"0D(/L#.@P%0``@\0,PR1&&-X9'AB>&5G961A8F%G86-A9`````!,4T-/3$]24R!S:&]U;&0@ +M=7-E(&-H87)A8W1ED`0(KI`$"+Z0!`C.D`0(WI`$".Z0!`C^D`0(#I$$"!Z1!`@N +MD00(/I$$"$Z1!`A>D00(;I$$"'Z1!`B.D00(GI$$"*Z1!`B^D00(SI$$"-Z1 +M!`CND00(_I$$"`Z2!`@>D@0(+I($"#Z2!`A.D@0(7I($"&Z2!`A^D@0(CI($ +M")Z2!`BND@0(OI($",Z2!`C>D@0([I($"/Z2!`@.DP0('I,$""Z3!`@^DP0( +M3I,$"%Z3!`ANDP0(?I,$"(Z3!`B>DP0(KI,$"+Z3!`C.DP0(WI,$".Z3!`C^ +MDP0(#I0$"!Z4!`@NE`0(/I0$"$Z4!`A>E`0(````````````)$9R965"4T0Z +M('-R8R]L:6(O8W-U+VDS.#8M96QF+V-R=#%?'`@)```)$9R965"4T0Z('-R8R]L:6(O +M8W-U+V-O;6UO;B]C'`@)`!'0T,Z("A'3E4I(#0N,BXR(#(P,#6YS>6T`+F1Y;G-T<@`N9VYU+G9E6X`+G)E;"YP;'0`+FEN:70`+G1E>'0`+F9I;FD`+G)O +M9&%T80`N96A?9G)A;65?:&1R`"YD871A`"YE:%]F`(```0`````````!`````0````G````"P````(```"\@P0(O`,``)`%```% +M`````0````0````0````+P````,````"````3(D$"$P)``!$`P`````````` +M```!`````````#<```#___]O`@```)",!`B0#```L@````0``````````@`` +M``(```!$````_O__;P(```!$C00(1`T``#`````%`````0````0````````` +M4P````D````"````=(T$"'0-``!`````!``````````$````"````%P````) +M`````@```+2-!`BT#0``,`(```0````+````!`````@```!E`````0````8` +M``#DCP0(Y`\``!$```````````````0`````````8`````$````&````^(\$ +M"/@/``!P!``````````````$````!````&L````!````!@```'"4!`AP%``` +M#$0`````````````$`````````!Q`````0````8```!\V`0(?%@```P````` +M``````````0`````````=P````$````"````B-@$"(A8``".!``````````` +M```$`````````'\````!`````@```!C=!`@870``'```````````````!``` +M``````"-`````0````,`````X`0(`&```#````````````````0````````` +MDP````$````"````,.`$"#!@``!8```````````````$`````````)T````& +M`````P```(C@!`B(8```V`````4`````````!`````@```"F`````0````,` +M``!@X00(8&$```@```````````````0`````````K0````$````#````:.$$ +M"&AA```(```````````````$`````````+0````!`````P```'#A!`AP80`` +M!```````````````!`````````"Y`````0````,```!TX00(=&$``"0!```` +M``````````0````$````O@````@````#````H.($"*!B``"L`0`````````` +M```@`````````,,````!``````````````"@8@``00,``````````````0`` +M```````!`````P``````````````X64``,P```````````````$````````` +M`00&``$)P,!J``<+`0`"`0`$`P,!`P$`#,#`:L#`:@`("@$]?9*5```%`1$/ +E`'@`.``V`&4`>`!E````%`H!```M0RMQLYT!%08!`"$````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj_deflate.7z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj_deflate.7z.uu new file mode 100644 index 0000000..8c2ad8e --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj_deflate.7z.uu @@ -0,0 +1,275 @@ +begin 644 test_read_format_7zip_bcj_deflate.7z +M-WJ\KR<<``-7%?>]QH>=Q4N-!@,8R3Q,4IQD@%IW6Z3.1WIX0I>GB[9I='2 +M5.DMTB1I%.$$3:`!]"!/$`\P`>(`20;`#I.98"+PB:+.P$!\T)8@O1B\BGE[ +MR2;JUQ-3U`/V&B6I$(U'B7HCDI;U`-01=`,'L'J3@.D&`/HF2`:>'%&W[#=R +M>7(QRGZ%.D`*RE(BZF=65VUP-[K+9E:7SW!75Z0UU*8YJ6MSQ!@6UKO=>2L* +MI,X%%BD?^+L!.8`BUA?_S`>L%/ELP#S`T'0IYF058`U@JBA+`(R1HC^)@`6`^P`K`!:`7.2)M!"0+_(/`>9(;_YC>(.ZN(C\;;>@&272L2*] +M,P;-Y&'X>/H2\_V6<"FWJ0D1^!2`%3".FYPT&G`7V76,/NX&.`#O&%:>"L@0 +M^2S`[(BZMP'N`4P3>*:PK00XTFAT`-BG'%"B<<% +M?DS4IPO\E)'CLP5^4.#Y`G]0T"\6^->-T7K<(_`V@9L$?0W2\6+>6F@-,SV^ +M&CICB&Y_A[9.XCF^6>#/QW'\R6'\\P3^'H'/$?RF"=PHQOLI@<<+^MT"_YR@ +MGR'P%X:-OUOT_P>!_PFP_[+);"?Y(6W[,#OZLS&:_O,"_YT8_ZGPNN!XO:B/ +M%[A=X"^,Y?BY2/V(]=W[$:Z_\5C)Q8)^NN#_':2]5TQFDY!OK&@_7[3_O>"U +M0.#]HOTD@8\3^-N-''\`:<=EG=\J4>\6]7W$OT>KMTE'!?_?BOIO2='Z;1#X +M:V(^*]'^9`3_+&.T/6X4>([`KXKQW"YPLYC?>6+\QT5]IJC_\;#Y>#OH]Z(_ +MOFV\&OJIYG-%^XEQ`A?T'P>P;H"WMU>E7P +MVR#F_UZT?SYB/%;![]-F7M\+O#NB?L6P]>`3^%L$WBSXWROP(P*_1^!)P]K_ +M1M2K`F\3=>LYKN^E8C^\4[3?IOF?8?QVB'R2T+^$N,$C5U53P)`AE12\>VGN +MD@?RI4K/YM*:JO>[2VH\FS>XZZ62JIHJ62JI0"*5+"I\*"^WL.2AA0M7N%:6 +MK,S-*W252"7OVE*RW+VQJD%VU^=7ES8TN!N(=TV9IQY9SE[>6"O72G*=1VY` +MWBV[:V26-LCU1%M&5'.EDI+-&TH:-I145VU&GZ@KJWL,A0UR>:U'KI,>+:VO +M:92J:LOD:JK<7%ONIM1=7U];+S74U-57U<@54FE9=4E50XE<7[6EJK2ZI*9. +MJI`;2AK<,N-46K:II*QR4\E&3VE]N<0DV2)M+BTKJ4"(1'A=53EC@2SDJ-D$ +M!EP$=%-'E.$:J=Y=6LXRFS?4R[6/EE%S3U4YB*JK:\NDJH9267Y,JJV32^LW +M,B%JZ]PU81855=7N*)$J2JNJI8J*ZM*-#7(MQL4HZ^K==:7U;D9=4EVZP5TM +M0>*J^MH:J4(,>%-5=;54750=C#UE:0,-],H.I6JB5"N0H>;W9M)]^B5FU*)7-U`PWYT@P=S +M);L;JV3JL9ISKH"%E#%=$3_JH8)QJ7BTODIVT\2$)VI#`ZP4'&JK)$^#NQ[E +MM9M+N/K+2N3:$K!F-E3MKF%#JZR7-M;7>NHXX4804F<-K+.RRJKJ<@R2F9A4 +MXBXOE4LAY(:&!IJ?>AE%4.-"A-`ESC2GEG'0+C[B/P-`&E$3-P(W"-JXR);4 +M5J?12GDY;W4KGIP??8_X3^>*#Z-0F,_CGV].??]HBF!GQ?&RP\").HOV&Q%3 +MQ-_.]]KX*7Q/C+^7[SWQ<_B>$)_-?7_\`NXSXQ_DOC%^"8Y-\+FC#?!_E$*$ +M%DK!>R>E<)ZME&)/VDWI*/AP2B'!4Y2:T3^E8Q"O4#H6^Q"E.`0EXR$WI!,A-:1+DIG0BY*;T#LA-:3+DIA1!QR5* +MX;Q[*+T3_IY2!.(!2BA[B$TKF(X2G-P!F.TGF(3RC-PIF-TOF(CRF]'WL?I3DX)U&:B[,?I7DX +MCU&*37@MI078;RA%@%].Z2+$192^"]L'I84X>U.Z%'LKI0]AGZ9T&?9W2A_& +M_%.Z'/-/Z0K,/Z4K,?^4KL+\4[H:\T\I#H/>?DM@_43H>1DA)RTGH,+0G$9H +M,S1E*[XEPJ>05552-CAD);R9<+..MQ!NT_&=A"?K>"OA=AW?3?A4'=]+N$/' +MGR(\0\?W$YZCXY\G?+&.'R1\F8X?(GR-CA\F?+V.'R&\4L?;":_3\>\3WJCC +M'80WZ?A)PEMT_#3AK3I^EO"].MY%^'X=?Y[P@SK>3?AA';]$>+N.]Q#>H>.] +MA)_6\0#A73K>3WBWC@\0WJ/CKQ$>T/$AP@=T_`;A0SHN7:;Y-X1Q$^%F'3<3 +M;M-Q"^').FXCW*[C281/U?%DPATZGD)XAH[;"<_1\53"%^OX5,*7Z?ATPM?H +MN(/P]3J>3GBECF<07J?CV80WZG@.X4TZ7D!XBXXO)KQ5QPL)WZOCRPC?K^,K +M"3^HXVL(/ZSC:PEOU_'UA'?H>#GAIW6\DO`N':\FO%O'ZPCOT7&9\(".-Q(^ +MH.-;"1_2\28V_T9]_;/YU_$6-O\ZOI/-OXZWLOG7\=UL_@4>_CC_4*3\QML[ +MX'>9O?VF92&/:7F@E?:.5OY![>I5*^"Q5(]%+;;YKOJW?MNDS*=C[O8Y:IRO +M0YYY@,Z@UF=LS>?E=W@[#'T)R",%FM1T?:;G55:OE7GZVUN`HEVZZC(KIM1` +M`#M6IRF5#FHL'^B%>,K65+.R-M6DI*<&]L-I$>$:JFS!?M?7U1K^D/3]YJ;Y +MES`Z2;;TI7@[3`?,Z"%TOHT2U>8[[^D[%4_UAC,G!'U;WV);4'L)' +M34E50:O2"/J+3VQ/A$U!YL"FL^QL?.S1/V9>V/XV=>$RQ651%^';'-TB.(0A +M;CV2>:SAHG^+U/=5_Y&[J:'_^^^D!/*H119279$9#(J#K1-1)]^MU?/Q"7E5 +MCUDMMJBK"M4'"]6\J9FY4[?;F#2B1Y)OJU7-FYZ9._WQW[82FVVCV2#Z?J7F +M,P$71@BH">=_A@GT@YCRY-S^9N59EIF[++8\*S-S5_ZKY.EZT_(D9^8FQY8G +M)3,WY5\ES_H[WJP\]LQ<>VQY4C-S4_]5\@R,D`>51)+#^.41/\Z&^N/UHI(( +MXOV]X2B-6\[S!N_X)0U0SN"C4(HM-,#$7E#JPPR]+,KU +M@>]'*(3UX[RJ#$1H3_BS'?W3X\'+E_QZ*-1&X;_BZG=VM.7T(K:\)P%3>(6F4)ZL%*2:T(@<]P`N%),4^1$.C.ITL\:_/O#)1=3]E+R#*!29K1I-E$,V%GY!QU +M#TGD/6[PSB<"PZ2.P:ZW'U>9_/ZDV_TK)XQ75EC(R)0DWANOH[[;(;M2DL3\ +ME9=9NT%]W.P+R4O413G>H=%6WQU_A=B+[$3<.`[$F!S8*E;R`*8(&(:'>>E< +M9&$+?!&[2`"+SG@[S(#*?"'/M]4]Q)J,8D,<=4]KCIH^RL&?J?E)VA#51\R^ +MBYY7U*+^V1/)AUE]WX8_V'&27-LCZTJ*3]#XU<0!5,&.?0MOA$+1(PJNIO4> +M,,"1H$Z=S+SO1:LO!5C?\]S*R5Z)%G9._>X5-JU7*+X";N$L1!M'!60.07JB +MYWV._,YMUB?NN*FOW"1'[WQ)F_A)9[PO7_,>L\+4_$1K;;[V5R(M9!8U>[R2 +M;XXV.*I0+%P!P9LI^@HKH/[--F:UOD+&JA4.$7[2F,4SP=7+5W5%D5X +MCLROB45O,`WS#,SE8I8;5!\Q9'489N,$QE1N\#-[IC).P%;5.%ZY2B\Z/8Z9 +M?IC7[JAQ?)ZPX]8/3:0Q,"Q8AS%$=QFP,:X>/P3G2\&DYJ1`6>87Q&IHA\"Q +MN_3X(Y6JL-+@_79-"7P$-L8QF=1Q^PNQU1$,XJ(IYZU^7Z:3C\5MQAXJC(B[S'#J1P#J/(-S1WR?.7%OJ06`Q7F4F&> +MT7N"[5[VOA.;O?MY_G4OR^IW@NV>_;RW-)?M]!H6<_VT%)J7[?89YCVMX- +MK9/%+B:O%I_5PS*,<^?]%C$ +MGX/8@G7A$RU"V^0U=V%JVETASN>L%`$T=%94"Y[NT(Z2&<]WQ(B^(T>P@'#)%> +MR/D6JB;+]1=_%S&,6/@IPM*322/^M6)>L._S/3^%&V,4I8@+?)4T4.&#JEG^ +M\RQ?Q_)/L;S,\H<%V[_/LY'1'XQ%K_BV4N1P@ZTJ>4VGKPEH/`V:K;TLX"S\ +M8*DJ0I)F6E9]V$#>T&D$Y\`5A%)]`RA419S5(A1DCQ1Q9:HMEGIXGT%_*H[$ +M"=[K4JOUB3MODL4XSP?WON-68?)!/'ZN/ICM.X-N\OG)H(7V]%3A +MF1,)Z1!]KF01]%DZL>69T12\\\S6EO=2L?&4E("]1S&J^2DD?,=V+C8F)132CD*[V%AB)]4%B"E:R,R+Y,83?>X8:/R30-5 +MH)*XL3!XD`9T,H6%3*W>(9,\AL6(?Z*8)3\J1H2,PV-$/20,-D&!K=`&2&:\ +M$"81%=YM_0;KKC3T?(N!ZI%?T/9.B#;9W,NCL;60XZHK8*9Y0K75]VX4!.O! +MLXU4"A[DU5AOIVUH?>UNTO;`97Y>F4[$1U%$,92@#2R>P.BXV12^$&F-O"QU +M6)E_BW8_X(?YX;HP]+X;W%(?WM&?0?'3)/T8[??UT[[\F$GQ]5[C@>+9BXR? +M1/P.@I_&>R_R9"X?E4@!%MS7+>,GZJ(7V(F::L59=X*9MLI+U_1-K5(VYVB, +M%HO`*,GZK.\ET%2@G=GZ;,<] +M9VA+X=O-J!WGZ"%/^'(E0$C@,D?^PNS"ABJCQ-8$M;DHEZF)25?XJ>;7)M)& +MLCB=CX]'8\L5FG*Z(+(_R;HK#3-_D:A]-"F=\73FZCC&"%8JKW[7AJEL9_-! +M[P_VK1;CMOJ6HPW&SAET`.&\6_=@QBU\#)_EW`Y_WV3FW%%V2&5VH+SJ3WJ" +M%S+&;>0NM-OL<"![%_R"-FC?6"!^7T`L'1H\L[<)-%"&=1T;>MNQP!T&I&,. +M4$DPY5XVKQ7:O!*;;_X5*__N:;":<_;.^('+PKF4W<.6&GLMB'D=S7SB^RED +MUDC:Z"'X@==0I+6XHK4H"+=-%SE!DGQ%8Y5T):K"="6B<^]O;WC/V3KCARY' +M%?[1>\Y(A5$-7XNB.6<83E"0RJHU%Z.M,/.$,`=';UBF2&'%VAXV'ILN-A_> +MF)U&FT+"EZ+>#T!+[ZK->QHE\3*]H()&()7KR' +M?%GR%;Z_?XU=.Q)[NFVL,F@.9OTGL/:^=J_N?'QW491N$J[L;6'"KC"AC;NC +M&=P=-76@O.->C:QI+Y&%T?T:RHESGA/$_GV]UT0094I]/ZVF-8C#!;X-^(&! +M*]&%350XO3>ZT$N%BX<5?H@*IVJ%OHX#$O+6Y@OD\@>$*WS[-;J*(G9T/3R! +ML$1)*">>.>X43>$..#>^%>NK06S*P77DPS+X=O-`6X`KYB$^],-/BJ&K$S/X +M%I6L461SBAQ.$=9P-)KSB2AT?;1B!WAM>-!_Z!;C9:,-#N&5B^'/%Y/1\_PV +MJB:/MO];XHI$$L/#IMV.0A;^MRWN'5E[YD2XL=0>HS$5]AW3GM_@=)&D%IL1 +M0P\XV4F+'1ZT\"!@%O/%KOML%!HG/8+`6.SO3-ZI>+##?6\XE&MQA?RN$(M" +M*VUT!7/F!/47/L],1Q.:7GJA`%EG^(Y*G;C^DLEEZD8XBE]@9I*A'<3W? +METWMK4>/>P.."N^V%R4ESMK\=503K4'RGC)X3YB\-XT>E[?3X'5=LGA=/49O +M:*RU^7F)^KC4V50I'(;?='^FZ_E',]6B'NLSQA;7G]BUC.O/?M/CSJO^%-_Z +M*_2`>F7:G_QY7=FCMZC^O,]FCWXTE?5=JL3U?5PM0KWI_:QEP?NI:=\)\50M +M[P<@O9>1YBIQHEMAH/?,9OKIQ];$3P+OF$V73#_*2J17R[99VKJ0J#M;TDU0 +M\[5&>0+8D`K1)OV2:-,9%\*'L?*>G,X.*9TN,^UVP=Y9;#Y6K5!.^--SO/TV +M->GI2AX)^7:3#DQ/T\@HMLT@VV%K+/*DV,XCT3MC&PX/^TV/J"9?N6`SA[&9 +MWAN337)L-B2W[9%UQ=P>VJ:^@:$&"_&V5_3S;L3PRO&B'9?I`0)[M+CCNI1# +MSPY.H7+[P\#V$[8-&/(=>#2V`2E[NK"5KH#.'WQ`+KEZ$I?CEX%>/6FR-C^+ +M3#O9!)=N/((L/(HO@1 +M1-&0.!C8ZBJ*5 +M%>K/=\7ZEQ777G%@&\)SS^D]S/>VG&2!./>$6]3)KUWA3KB%=.7:RZ9Z'',. +M9G_Q09J\91%/LBK'B1,I+S`%AFSZ$=6N'5$;V9E^:'8\?V+1R<[>,AR,F';M +ME+@8=)H$!PJN$.UC6`>M;;3=TNF)"?V]](M\:RQ&W?=R:%'LO8\QR20F0^/I +M`4"Y=7>']9F.`]0@N.,^ND38JTXDGOX=TJM_E#*[MM_M_R#+'=N6POD6"K[Q +MQ+=(XZLFLLIU%_G9(W`3E96\4MSBM/)'H>PI.7\@FMC/3BKR&/:3P+ +MVW5$D1UODK),$UXQU-Y/Z2#'L(0V+_N(FY/&NU1CBYE=FIQQ=IS@.K=PG9\6 +MOC"W3P1S4[]/>=X_QQ?N+/V6SBR5P.;%XF;LIQOM:TA?5K +M6H-/[.3+RT8E*PPLG\/-2EZ`!78J?-7S1.RKGD8CO^J9QJ1F:X7O#R!&4^:Q +MOB+%;#I1W!+-C&Q*2YUD^1B7JP=YGXRI"LOQB=ARK!?,ID0R"S?:'KO13R7> +M*">RD6;8,R/O7H8S=,=F^%W!<'Y,*9)B-6K<3`VVZ@W8%%O]EV&"XF9GIG:S +M,TS":=$2ZFVGAL)M<[2V>OVV7:)NJUZGMYVOMYT?J_X3NEQ3;B'7%%VN$74Y +M;U"W]0WJYM]JK(__-2S/M&'R1.\W;'UD*,6O*2>4;3>4GRJ>(;6ND-V/=+KZ +MM2?G+R'5;DCJVU*X2WK`^NQ"<\`V!R)TXAI0N^13E_3[4\R"R#-7G>^@7$@> +MR\C79^!]]1-*MXI^BE]3T27>4HEL7836MKXS:/!#9P>+V/J^WX9#/YF&XNI1 +MCJL+,XY=?YO!U<-*E:)>=57V.'POZ56.HP*CMB#NH6MC=GVKZHO#.1J\NO15707?W +ME8XTWB+]FI<]M);GJ_D6[X!A;+Y-?D5=:L/P5]D#35GA.V/Y>S'N-K4GWB=$ +M/#'\1K/O@']+.-[,AO_USF=W8Y/.>R^/5EQ=:HX9#]^RXE-Z2$T!ZT?.DE.:L-Q7'UQ5S\63-5\&ROTLNDVJ*Z`]\507%%@L!NA[=N/*T4#N-G&3M"# +MRH[,+NM'9A@QT"Y,V."V`;7HDN(Z*["SWNL&M:C+VQW"=*M&"J*/DXO(8<^; +MGZ6LIP>7W[L^P"[S\08R);UL2)/3^07=*+6H5RGJ5I>`O\9]^QZ\)[-9=![3 +MP,/.MG/!`C:E3K:1<3U,M-NQ\O`FG-_R%N=YY?3@GXD;6X7!]`6D_"Z\PR=Z +M#1[.QM\3]QB)A,TE.[V-8T\\CLNW@[$RD8JA\0-D_\&Z^7JLU3Z>V8!2;.X[ +M''[?5RQHO%;&GJ3VI=!YA]\>DUB=1B8)7\YRY'+.7Z8=[;P?H,4WB!DV^DVC +M#5U9[(:_?KJFW]H8>^,NMCT6.FYLND;2DK +M?FH/W<.\'A^6ZKTLN\R_[\D,Y'AZ/8::'*`"W+J)OS:GEK2G +MTZH[.(X>MTC677>,8M=GX@^8.;&!-E8JXFQ`S^8C(TE[(GF5O3AU`_'' +M-QGC^)[\!1*9U9"+?`P8U0[1M?FZ)"A*W4/:5_-I&TS!.[U(DM4X?"?A!6@D +M-F@Q@<:%]VN50C:Y._6M+^)%-86]3R>0E4#0,.H-MX/Z&V[[V!L)K.-%#G5U +MNOK`5,5_F-#$&WP>F[\;1Y=N/T`9OXI)'LT5EF3GJ>ULQ!Y-BF3'RH,V?A!3 +M]Q$WR/H]HEHK'(1V2^C;:0"2(1!?')"`N&>K8"]R3@VLOP^%*8*BGL1=&`X^ +MM,AFG+J/#!0K?;2(0=1$1R\WPZPH!?!#PUQCQ-/?Z[&#X)?CHI[^;J'GT;Z; +M]!Y:\<#LR?QTN-M$[[/14F(K47LXE:"RUWO@`&9SW;XIIRGF?Q;UH](;;D^R +M_6H?GYPD]9&IRG'';W=<#Y&=[CN$4NN'7C'0?_8L +M!`>?+J#]',$K'0:SN2'Z]\3T/TFZ__'[B,*_[T>#G$XRZ;>7BY/8@UUK,_TP +MQ:GF>**A#>PG$)0)Z?=3D6+AUAX\0U(5]V#"(V?[6S%F.]CN$N_#L^'[:`V2 +MWD:H:F$!J'I9)BZ?Z\Y/;=Z`KR7B[3O'(EJD8,.BO1]?!YLF3*!X2T)[!T(XY97\ +M^7L''ZFEC?X>EKV=:!-*/.7ZQ;W!POSAFR2;>*9$OJ_`.8=OR6E^^1M#*]%N +MVPQ^WRPD\&;<+M\IQE,8@UP;O^\8'A"$]RQ3%INQ\(ZS?1+?;8Q1NPU3E]7_ +M':Q#K2]K\U>!"9T7C.A/7/5$WM\S%9""WR4V.W$S7GZ)JRB0'/'2PYH)^ODI +M'"\$?&8Q>W<@+.#V#8)MI+80]?0NRQX.VU]2/P]0`DU))FK +M0]P2V1]0R7P=K+'QW5/.]+X>DC=[7[_)W[A0]Q`U]WB/OHM?1A>TIG^9?OE& +MOL?+N!L,+R%";5.+!OA+QBHK]53L.'E($FZ9%_E->Q66Z?L)26BFO]-Z&L/T +MD5QT6<\J3=X_&D8,R,0'U/>DNH=Q2OJNPC)]"A2M.8H1^AH>7XU@ZUL+'KQ_ +MK0NA,39VO99FB&N.>-!UK^8/U]BTEZS&&&$:])[H_0;*0(/'R$7M8QI\/<1N +MR9I1(K2XEVO1VOQ3BIZO^D*/S^VKP/K7=D(FF_49RZBH/9'$#]_M06>9@_*] +MVHGX%/.D)#8W2CR/N!TDVB$G<]#S) +M6[;[V3AX#\*:6!?JY`[QIOF%V`PF1#&`:3,&3%#!YU:+@O%74KC],7][YD'] +M%OK^J$WH/(TEL4.\'O]<;%$ZI$A11._#5H/51W]&&+$B8OUVMX1M8)U[$X_LT2TFQL:WD[4LC6F +M7/U/KJ]3UF:%EM5-+*MREL%">XV]4^R[^OCLON)AJR8N:HKV1:V:$X;,E^3I +MZGR:5[HT&[EL)H`FO&Q>\CS/EXWAZ;7AI?QHW?!E/&/$PAH5>V']2A(+2RRI +MTTO%DKJV-4$9RL::>EA;4]EB3>4\I%M!:]\NKK-;.$D]K/XX"J/5$FVX'XO4 +M2O3B@5#:!(FMC>3AUW^,8KBWWQ1AV]$6?"9"]N`S0$:HVZBI.KAJV3#O4ASE +M700%=_E;_AE_O^8-[7'-F[='KM#F9CJBL+RWPX@A6S]D&^'SGXX;Z?/O0)GW +M];NLS;>QS%J\N$"'XJ+LULN$Q7)LPKY'"%/(SXV:W1A8U\$U#^NU +M/@]J?V!@^UWPX`H>[\9RJ9\4WGTM&U[8H*^$#5KI[@B,PA,[_V)'5,,<@ZX6 +MO=V+4>WBO#VCA[=;'+/=^8AV,1K-CFRDQR^9-ZW^7]^D.\+P!(#9,RD(&L;)&057:*+T=#C%O.N%T$/*P)TRN#2X6^1PB/W+W,/IHXN"3 +M*\C-8P%B]5W#ZOL61A'Y;#!X#\T9VRO6B2HQ$%[]ZO+H]E\9WKZ4VNOU/XBJ +M%P*$'X?:?!<;+<(F=WU)TI>']2//_56W/U\3D!';[4<-4=LM7T7:K:/2V?<= +MYF9>A<<=((_[S1M"DG0AR?CE$5[K.=CP&_M<+^-O8-9N/7I"'`F^06]H!,9I +M%U/9(-$CHT_&CB:>DF*8OF<-OQ2GORM2'S9;CW;C_L)W7D&V1:$&AI9DHA$PC#?87B4CAD=#PV==J'\8U.BGT +MO411&.&X4U9IAR+FK[W]#OY'YJK'IFY+4HHNT8,#5W>GJXOI=:#3]3S+7/>= +M$8\JK"V?9W]6R9^.TE_HJ$7=RC$\??&%X.[QW,F3E'EJ2Z[2A2=B@U>58\Z. +MO@G8)K*V]6]YR(DGU]K?+RSIHB=?KN=5%RB?AZ6-'NSVGI<&7_2>=)"QX,_+ +MQ[8S+W6>V*CX^XKK@Z^B.]<`DF/*0-_WK<]U>@?>IK@"GH+,;?V/QF=Z!NJ? +M8G^>A$X_,UC<[2VZ)`T60S((SWR?\B"^F;^COR(2'0X6]09'K<9S1O;RPY_N +M=0648Q=^;WT&?\+@>DT94GZ)D5SH&=.)GB_\%L6O70A0Y87+E!]#X\1#H`N_ +M'QQ4BLXJG8._S41RJO[.K**S>'/@FK,CF`/F:,P:]4`YO_<_%!+%K=J'O^]A +M:EO_,G^#9[SS8JA+]:XEM,^$$L^`]Z0)[U^`EGZ7R#&1_R11JOA!W7GVAOHR +M^@'>F64-GIE5LS/NHY_@G5E6+U>EK9B^Q>Y,FYLV:U::TS[+XY[C/OLE=TX#?N:NTNQKK[*E2X8J2_(<*5S]0L'+Q"NTGY*8TS+-/ +M:9"F>*094;\,MR0WW\Y^#,Y>45L/BIE$5.V1IKS7$_ZA.=:XO*K>72;7UC]F +M+ROUX-?X[*7VLL?*\$-K\_0?64.O14N6KI#R"Q]`]J'EX4S)PH>6Y[NDE:[E +M2Z3T@UEY14;*ZLV56^NJ:U[7WV#['FT49KY!9,Y$Y`/ +M6`)8#2@%;`(\#E``&[]F,C=_^9^'58=,9C?@$X"60[QL*7C.`-P)L$3P'SP4 +MW?:RP"\@_2[@\#=PD?@-7K:=I1QJP_F1L`+M"E%_#\`FZ`Q(RY#^Z>LF\Y6O +M\[(?(?T2Y0$>0`5@"6`:X$Z`!?!GR-HEY/T:T@\#IKCM4S;8IZRT3WFW1!FW +MR(ORY5KA6-&QK=&_&S>QM* +M-Y:6P2;QT4S,WE!9ZX%QP7SM996E]:5E^)U)&/*,2GM538,,"[;75M@=,S+M +M4QO<;KM[@'_-RA?4MI +MO22=OPC=-J#9/'MU@_V1&3#3OVNDSF(0%M!"W%PJ(T^_U&A/2TLK3I#6KKWK +MKM&EY@V6BH2:Q/HQ\M@MTM_W'#7"<]SWICT'#B9WQF4EQ?'?A5[S;"CD0/X@ +M;OL*XZ3_?_[_^9_YT,,^2JM?YG\+E]S#\31`"!\C2_5/DFAG>/]RR;#5;+C3 +M8C*U&/AOWJ<`[$="H4E$D'^;*<]G3(P7Y1F`E5=#H2PSYB7&NSYD +M>B).\(N`8I$J`(O$?P,[$>G6;O[HM@"_Z4]\"Q43.TU_WVLR)U!Y'/\M>!M@ +M8L3OR,LO\TMX![Y(_G&`.P!'_"8SY66DXY'F`"8`2`$X3-06H#R$E&090-JZ +M$[KY!S^DLW`J/BT].I_;6DWFMP+2``L`2P'K`#6`[8!=@,\`O@XX"C@'>`GP +M"N`FX+:/HCT@#;``L!2P#E`#V`[8!?@,X.N`HX!S@)<`KP!N`F[[&-H#T@`+ +M`$L!ZP`U@.V`78#/`+X..`HX!W@)\`K@)N"VCZ,](`VP`+`4L`Y0`]@.V`7X +M#.#K@*.`A'MWEC0(!^],FY66#O_N +M=,YT.&]#K^F[*YVEV*O?43T7"S]P_310F^H +MJIE9W3"S;'.=D-.9D>9T_'LDC=4S_A<=9]RGJ=PQTS%KYJP,NS-]GB-]WBR' +M_;W_TA[9+S.+3N=F@,ULO=-TNW/.O%ESY\UV_HL[I1_S%GVF._];3.$?I4]K +MJ,0!1R[=(*5!A6[\Y'9:3:WL3LO->V"&7+I12JLL;:B4TLH?JVEX;#-+Z3R4 +MMK'&D[8%86%5;4T44H(Z]$)T/%-7+1/G*GRS'XA.JP""JEKVD\]I[DK\/#1^ +M)[NDLAPMH\M8;Z6;J\JD-#I2-0#GR7O+2():,-O0`)06)_V^^3_P&2OV$*,D +M_AT:(!.'_]LCPM^/9G3BWXMA>YG^,8GT[8!XHA/[3P'H&HUZO4G`.T7?1K$O +M?1\;4&L\;VL0-#;`3+$W&<4^5CB&]J^1\LWE>T +MQ?)^R)?(_TT2O5_^60$80VW$OBCJ2JEN)-UW&)T>1\F@2S6,G+>C)*>@HZO3_1OP>^(1=':1GF#\]`_1Y0ZW +M^W"?^N=E&-K9&.OW;P$$!@`!":\V``<+`0`"`P0!"`0#`P$#`0`,P,!JP,!J +M``@*`3U]DI4```4!$0\`>``X`#8`90!X`&4````4"@$``"U#*W&SG0$5!@$` +&(0`````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj_lzma1.7z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj_lzma1.7z.uu new file mode 100644 index 0000000..fd6b4e0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj_lzma1.7z.uu @@ -0,0 +1,245 @@ +begin 644 test_read_format_7zip_bcj_lzma1.7z +M-WJ\KR<<``,I&RS\_RD```````!9`````````#FU5W,`/Y%%A&@[WP)!,(6+ +M]:YDCG/TF9,6Y4@I6&:W,\L.GXAK)SG^7$ASM;Y]KP;]Q:,S]93R>,&)>5<, +M&FZE"`#6^N9W.O9$'UE^T-50DI_AD]BN$0G/D?)@D^5S4+=>0I338+60+5WO +M?S\=&H#(CWK#P8A*.F39U-N85;*`7:QH4MPY]Z"R4@0-G[PN0P/I&4U*T@DV +M'"`CQ@7=GL@J7_2-A[.]&`<]D>$^(9=0(?Z*\Z.%M#RG1BD;5#6(4_PL?`47 +M!00BJ=5&HZ7@@B$C!NO::D+1C%8P).\)*UDX0P@<+::RMJNW=<@+:$ZER\IE^S3<>=HCZTG +MM[:O[2?'(:Q@840D]\]5Y73NXY[]$A&S9_<=T[^)S9E-I@,/"Z%N3%P8EQ8N +M.<>T1U:G?9*=LX1R,65>5\LCE.PG__FU`+L]UUEKFS13]3C4N`J/2*#MK;D6 +MR_YC0[KZK#6ZDVED3OA(WO_#+'G.!7!DNT&:A<:N8%2S1T,0<.CXWI?5110E +M(]/(V5U26WQEEBY"+^%%%QQ*$$LVGS;&M##OO=PE)#7IOV]4!T0>MCVFR7A^ +M)`*]D,D*8(TTY<\22+QK022#]K1P8Q>ZDOE"5%*XR1S_RD)#8:OFV8PM<:&: +MXO9&=U7J?O95W3V[0_>S$IA67];6D(/WJJ:Q>6%"L4.3$3?0E!!$%?%!2/7& +MXB4BNO1`#[FYN$MKM,TL^'./,4GY)NO_;YJ7P +M.<8Z"R!*LK]S`B1=P4X(^JK3]7X8N(%H?=H&K>KB'G7(0C'R=1Z0Z`IBTR?O +M>DKYV:WR$Q0MRO.CI2E[0;'KUGX`,?^8H_"$EOK=81Z5Z4VZQ'O;;O;-'3N/ +MM(@343API(#U5#X1=PK%4)/F?[I"DE\39HS<'P)7H49\16$$ES92A@%4O+Y4 +MAD=?Q`Q6L[^+YH+AJ-Z!]8./"Y'^Q"*$TJ#,%/ESOJCC)X:D@0R_?J)%YC&F +M):9`]N(:_,O,>0]$-QL,-?ZE@EH7Z=TEA\M7949(]"*65FN\?-CF(U?7P0?R&\DOWV5DVFK[.JXEP>WU1IL?6K&/CWJ(7%PM9 +MZI:B)8)Q$N-53QL+1O[;'7O/7/O^;3JY[WU7(!DWS`YXM'QL?+>("XZ7)FJ3 +M#T4640CH[0Q8U319C-]L^2259=A(C)[[!/*9P+!6MXIH$N)1*Z:&QIZ7]E*8 +M%(B.D'_@P=8!H(?*X?N@HB+MAKFN3F][.%W':*1!5I4=/"TFY>,\=4<$EI/) +M\S[27U*=0/;8!0P4W/=5+RC"*W]L[Z>GIXO;=$L;^CKMC. +MFK$GA0?W<=3^K@8Y^D_FAZ!W7WZ#.6HO6/_:M&X<5E:R +MAU)=J;SF.%&+0R;V*[FQB?;-D6E*-E9A9B[,4F',0KL8S]AZ3/3,AZ!6('R] +M)>:,3R!'4,\HCK1#'3_?PE4$NKGPX,R?.IK6$:/[E%8278\-K\&D4\:14"/( +MJ(V,!$2BJH@D@[TOT`^<-9#'>!Y!%G[3Q4L[4EU[56_:"*>E#X'=E='@D%RN4=E!\F6P+B>NF-E.')J;D/S +M>](@#H.CZB,"S;X1F.)O-8.%W0+\OBW-QVYBLHRW$*]^CP(Y/U\G<3B;CDT0 +M]"EG+*#EDEZI35$5+9SLPO#7YC4(/'^E+!1? +M^*3VBP3&G9$9CU2`[V+^+*?N^CKX/5VXN]BITG#,SZN85C91X7OQC*NK9_X/ +MLBT1D8WVS!OCD4C7_3>4N>6Y[.58AS6TD<_W-2HXTD?5O2$`?JW4#>E1DA(` +MHQ=#I"0OK1YBL'?/Y$@>3"0_Y+,WS'D:N2A4EH3`]F2 +MVFSKLME)Z,E9_,4[!'G+XCO\^^`Z\^_ +M!QY_7[O&*@MP8&R9/?%Q"XE@16@O\T+PU]?>]+QO%2RW(E +M^$A@,C_K8V6Q,(\<*T?3=QQ4D)]CL-8JTO%EV64)I,+2`_,\J._L2^N5B1N7 +MPJ])*IU6?/,23U8+;W*OE:A@V<`;](1`&8U>JD6(DW,D!F]^H:VF;L,-_%X> +M,)O/C?JM)C=5^AL,$UQR5IE^&Z1LE"T4OCT2A?W*V(0FZ=[^9O=[0L[DD:O6 +MTE:IM]=YK:4\#5<6Y>]VU@73]UZ689)7!_EKHD0T^P))9P%J]^#P><2"YV.% +M>U#Q<%/(S*4JZ+.0NU!_ZK^5M7!QAIZX:/Z32G6WM(_6?(8E9)/OGY..D_/. +M%.`#A_`A'J3"O.005L(]?6EP;FQH7HX1HF +MCAR1ZQM^6(:4S7GX!F9"T=U-C/O+M%,($IH< +MF+1P]=.-IA$C!(-S+&9]!:S%,;25N3YB'YX+%D?E-2=`D%!!Z27@>!`2&G1F +M-=33R'N8/38:0'UK8R-M.OE^?B@GK<]_L?9*.CSS19I'B[TRS5DPH]XZ*@=4 +M'N0J@P[$RZJX07]PA()D$BJ>JM2B14.HY/8P)=2E8[1@\';&"H3/)K\^2;9W +MJMT1I_^!-`'/V15^*=!%]QH43#I-"Y#'9@90N#0PDZ7ZG*X +M0/K*DSL[`\0HY64M4W(^[Q"I"\HMJ\:D/N7K3 +MYEO^MPZJPEH2V,*E=IMWQ8"E;5T[__9''NQO$.S;KOSY&Y?/G:5J#A\^T)?$ +M'+?-WQ$Z`'JWI3Y6^9:>JX)Q";!98%$S/HR**LS"4XW8"A%>9BDORAIC[W%M +MCJ#K];":3B4`,5HG,6OW`)L)@!N][4&Q\=V,!V`H=CUN$8->`C$7%9!.USIY +M%$TS2]-DLCFIJ/U,M32BDU!R@0)&:<1L7G:H>H#$GO#/7J>FABW=>4K(-;FM +M(PYL[]WV;8O,LY8:J2@V$53&XU`0`2]F/"[->8L@I4%MFH#ZVLDC/@T#HOKO +MQ3B_.`*!AW+0>7---V)6VLC%/Q8P(?K*&G7;RPF!6=-6/1=4MNA]7W<>H%2) +M6-5]EI]E8CK>-9?A/04EG"9L'E# +M\;IO)#E1-^C!(ZO0H&NE^W@N(3UFG?:I:3P,"#DQ41-K1@*#QE7;]W+$_3L5 +M:1$\.("#"CK--V!Q34.3GJ5-9SKJQRW^4W6SU*"-9<7U8=SX2)+KW'LG]DD> +M@FUA#W_-)WK%\.&\#-_?W.YZ6Y]/1;Q\5),6=LX8F\5?.%]X6<71?;:-^U4` +MM)T(J'EN".ZP>>ZX>;'B_*JQ3QJN?0<,D.5:AB.FA[E5-=-"@O4!(F^R\05T +M8`E-4F!NS5LV(VL-(M#[6!("]1#8;-@LE^V\4*!U:SXZ5@'PPWSI0M.I+($7 +MSJ._H<]-!AJ7>BW$J_#44W$;-7S9L/8*SBN=U[)6I$)(U6E&\8D6B7@5F\D) +M&:U?,]>Z'[6^8E&1Q91HLMEX-7SQM&/P4;ZH/\AF3]9;CL1[ZXSLI/3,Q,VT +MB6BM;E*X,404UJ]\M,L`_R!NT+M``JB>+=-*+;8++B:CLZTF%IME1)&SI`2A +M_;*=>Z[VZ)([-+/O<-8[!@QP"`(J#I3+6R9KMD;<`B&;;Z,TJ,(47QZEP5>B +MF,0.XPN@FLPW0,#7KZ"_`.7^R-JS#H@@6\3N_S-OWF=^J+!Z-'?M5*ZIA=F_ +M>\[088#:U,JEEAE6PM[PX2+CQS13SL/9X%LXF%Z@UB$T'(ZU?^`SO5Z7\0,%I[8@6GD8'03Z> +M:YJ:R>N%?0Y$_O[6LZ?BNRCA=37A,R/,$<>LH35**HTHR$&\Z]1&[TRX0#S1 +MFB"EU2??5S'ZP=^@VVD@,%Z/3C?/R&5PT(J.4;GTKD;]].XMT8G\F\QQ7:-/ +M`*V+!74(GVTBGJN/LYO[@/`Q8@X9N5DZ^;S[9'("+9I\$R&('_CI04"%BKKU +M$8;RDI/->GO2X-)JR/LL`;#\F[X/ILE)[S,7$=OI49NK*YZK_H[C;(U!AU0$ +M6+3;W"1A!/DY/X7G0J@FVI[_Z2[R?2-YS#=2.A9`\[";'@_BJ_8@ZS3*LW]: +M,0(83P2BHK#=<\)9>-J3&3V.R0MAB;Q=6Y_ON<`S-@Y6*H3UDD7B;-Q2?F:D +M--15N@/$^-]81!-&0-4@?-_7ZOP[4228AV`5VGVSOM'']2\Y?`%?^?![ +MKCTI]H[V7VAS[QX2;5XE["D^I\5[O0AN[!#6.P7H@4W:85X`7W8[ +M7=.^#]'OH0JBCP58C':P-3BIP4#OB?%4K2A;:$E8$C/CN!#!6DB.'ZX&HE5SIQ'V_<&HTDT=.P'>G[9U&,^;,3X:OO_!-[;UQ8*Y/G +MD2]*"H-R3*+B!%(L:9&<`5]0]6`KR/<2ATPN8A]/"#O*.O@;QDQ=:+&<.$@KK)K/PKZ90:#3X^\!S)474V8(Q/S0I%"A^O_ +M6M"EW9EC=(ET]FT[3E=A=OA=@T"KA@8@1@%D[B.60ONF^,$KDWGXGJ3UH-]X +MI=BWT5P*"`/+V$U.1B3$5GB_KM>W%?5S(3F=VO^R-%4K2!/M1[FX7D36Y&Y` +MU-N>@6D:>QJPZTL^/R10SZFD2NF`G*P[3]R(9JFF@KL(4&?!#`/H[O]9-9"L +M3:^?RYBI:*V1)-^@C./??0=5*_(QA_CD1M28HUI#&QI]ZEJUT/KD>I"*2]L! +M?Z4+V/`23D=D.(I+9OSG4D='N_ZD''(6034^793JDG'SP7R:CL_ZBH%@,>25 +MJ5=7-H5])9HT8(:!J;FP?90%OR_EX.&[K87] +MAY:`OJI"ICPI)&/6=._AI"AYHM8V/,87`C'O!0'$7OS +M@##S9B&,,KHM9@::[=#9;TVMYW(QO0T\@SMFFAN!=W/U?VPY41)+4CY[?_!< +MNW,W#U,GY_CN5XY>IV",=Y.8)[W]U8Y;3IBC/^N#/`M#(5#P%Q9L#[.ML0%' +M98I%"`G*I&"M`$`7.D,=)!=4]`>H8M9 +M(4I0A#O\]'3(PJ46Q)-;/K-/`5JN",&%"+Y,<-MWE#2-(%V&#>H\\.RHP.]S0-I#Y>E@%6*7Q6FY#*Q&JJ]UW@4WA+,%QE3PPE$8$AS?0O7E<./2QA"5TV%"1% +M(A'0&.[WUV%$,*3.B*:N"8VF*#AU5\Y^8P3WP#7MPTG)VPP#CY9/>N6R9>0] +M).7-KI?S&LC-D.R0!>&^ECY%Y:#?W#HK,#H:3NE5X;M(Q$^U;\%%EBMP@/MI +MS:[EF^7_SUQJ,Z1VF*;),:QLT]CG4C1\)#W\C'4SBJIEUX-)C!Y\6P +M(ZR)/5`:/6_"!UQPQD"^8):+>OG1JHV,3AV%-NN^6R<&LYDJNT3G3 +M\+,?-^B#/?U[/)WSW;&$JD0^I>"MST3DTA4,92>9$3W*HE3E=<`T^@J]\"\I_1@$8P?LYX2=&>TK(H[IDX%#;# +M/052%71UXW$ZM=B7/C./*XPJN8ZV1+&IG$`.V/A"1SL]X@]BN6$Z\L81365T +MRE8"[=YV)6H9BJD@6Y'F`5@R(N6WU+?]VP^US7$WD/&2?ZB:"W=0;ZN0D^>\ +M7`!WCK\DV`DLQ2Q/].IURR&!;Y6)0XVIZ[_3K%QH@_/$Y=U[T`A"[/A:#NNE +MY(59/4G6UVR]J1UV\>)UAD#/V*:1%61;[\F>802&'<-ICN^PP2FHR>6NZNWNAH27%QM4#+H'N] +M+1^%CG`[:[9>S=%M1$$KOK_]JL0+]6+-:]9>AY=+2U\NR4`C3@E,#WWFW1DV +MA*E'.T5\,EV+<:]-A=X!:+G!`F!(9I#4'T^GFR]6D^Q%CR)L`B!0O)0(OF>\ +M3#U@%O^#US4`_Q_@A8*Z1)7%(ZQ%J?6M-$8'\NG=)!4C`MPGVB3&2E[9$38( +M/3@US1,"70*H&87;S[!UC;\*'*>3B(?@G;I3FAPQHWIU-1Z0<22D_[R=_8I- +M;V5*Y;(S,-]<%<6I`?>M!6@.'?)8-U\$.QK9/5Z)QT[JDIIW?/5RJ9([\+W2 +MZ_3!GE7JO@]RBM/C]\_O?J.*]M2KMQB-5/.3<1`\H\RQ2O(7,09O0?X-9*[Q +M"B#HGK\B5.FYNX:5QE+7C!.:C]9,$[KPXR#I6LR2ID1EJR/,)OW%AE7[+>'N +MI%$H907$J5)49IXH#DNA! +MD--=$KY]0&N]Z'<,+_>A(YZ?YK'4`@,^:N?-3@A)

    ;`2,&](DA-\+6/.WM!X0,.T8[F'-?PAX# +M0L?`J#M!ALYFK*I_(_P^(Q^*W4MC((OYFP@Q7RI'W1*IR/8R(\7-A%IZ-S@\ +MXSB/G*3=?/Z5S;*RL7+@:#=0M/.;(5EFT4!R"M6A)YM3U(/+>OG_0)M[[CD' +MKM;*8UGWC!D5I7GPX"@?!$[RK_+AR7;=O/-/^T]&OE?RM_N%..M^T95Q0#0\ +MLX%LA(05LDBT2UJ5(0UFL[6_Z_F!KAW@2!A^I25>BAF8XNXG +M1V?8;M,'%TZRVV\0*!!4NFVG!A*@'_(WU'=8.7<%)XI3^8.N4#3-LW<(^ +M*PNNKKY&I/3Y69"B2=V.W0$BTD>3S$C1F]!T0QNDP8:;Q&S7*`?G+GU7=_HND#LS58$JQMGR`RT81!J8@XZ_.D1)<0IUO8.'@9I!6#.B. +M@\2WO'G4NP,5N?JT?0W.,UZ70[3%(UJ`O7%!5$22^4F[&9A=NZ6TBP+L9@9" +M"H[/I;A2*\Q1P/1T$NC@$PKB]0_9N<:]Y_5YF=&M@6/R>6/2MHA];6.[EQ*D +MK'7!P6?8PN@_(N5PRW4M[A=*#X?C&5;-3"82;2VM]46--D'^+$N0F$A"2OC'&8LCB[,0TY=SP11Y57AOOV^%I^QJK?+.UP8 +M6?:'9U*'*1*QYX?:[&[+X.[@RD*A6BUDW09G'33JZQ`BDN_F>DUYP9I,OPM5 +M(RBT/&BIEIJ4=,;#2^`:VZ#-,]NR[!KXDKC;3:7X8P"4(L15=&/WYL#*W>/V +MG'18))_@*80Z!3QR?DN05D#)$320O#Y)4\.0PME&.N1IZ2Z[0.6,!.E_O&L$ +MG!\UWULP8^IW_W*.O^UK'OW(!GTU@G!2HXZ0YR8\"5X4"9VB,\N_ +MOW&P,^];7*Y8BC#P&JV0`/>4<&2-$=^4F(\\3:!!$GN9 +M\NG!"),B+35?.J0@)Y*##"4/2%SV7__/,;8;Z8*ZER_S`T"%S]_1Y)V+]!Y_ +MYNOOV%+(QZ$;\V7^GU3T'%X7^G1LFW(5`")S?)"ZY"VV:08!;)=@B(-+SEYB +M>#7ZHN301+UFJMH#DYKTH[>)I9&`C=>KV_/B#7D:0-N\#.;BQ_"`/(V!RGSI +MR[40/"&/U'JB=^Z5#$^R7Y]0M$,C@IUI.^P9"M/E.!0:<+PB^_"HD[GI;X@0 +M!52M![84"KTU*3'MZ+]@[691I>:X,(S1@ +ML>4$U%7Q27("H2^J2/)`M#8JV-8RYP!>[=8*0']+B3"R`]S\$&'I[0&>VGJ/ +M/Z#RNQ[F8X:I?;P$W]IRSJK$>+\C);]&ZC\H)O`Z0%$147&IK..R.I$_2$F' +MO4Z&,&YMVP"L"NN@2A[A4@,<++T))G&/^,->Z=^M%4\?_XMNBLX)8[M[OCQ@ +M=T-BJ@TLP)[ +M;CV!F&@YN@:/VR=*&U%T#0?T&(IO2FJ\[Z4/$U_V.-/CWO:U%S$^H^'*,TT? +M@<.0:LH+MP*>KD;02H58$)9VW7P-"KF-1GE3;R>\O-OT,^*G\*"IZP2X**1: +MT0,F#J_QAF3-NEOTO8S'(<(O@7*?,K;)3:_.K")@Y[&;IR,@;[^!U%*\GK\E +M2C.G=3..B8KJC10CDI@>4&73_CW0]^&VUKU1[`&`HZ@FVZ;ND%:@.,-9#Y7< +M-.#4)^^EZV=?7$354;O:D0/>?3'&47!!571?:./5N/XE>@F.?7-[6!=B*`M=`Z$8%(-8-MW:$_2WB@12SV,!$P%(&!H8H]UNM>=5G_>GMN$W^Z"FG +M<0K1N@P[_@-TO/DJ\A%7@G4OM^Q$H?[WG%C:ELB$M2UE.U1TB-<2`$MI``@*- +M5,#;]1%S1$241WG.SBJ`BR#5(6DTF==42ZA2[68+0#VN]'1?9M,"GM\^H?YH +MC%GH&!'GZO1K+PXY$#[L'=6"?)X;W`*9`Y@,]D;/:Q!0=N5<#[GTIVWEJEC8 +M\[!OMKUNS,/N1"OO+W"";$9\Z;+12Y,R8K-!+T&2"WU>G:_7T06IGB@@_7DW +M!>A]`\3>"Q_TV&9=`==*MAY?RR@5EWM<:)>2FTKEV +ML3[GSW>S3=>[2EP!F?F5].N/*_(2^GWP`26*S=3`%0F`.WP5V0YD/1K:U"HC +M3ZII\^%@FE@I2)LKKWMW-YR+EB\H%MFF$Z3TL6= +M+K;Z>EJ=G'VZZXPR,<`K^]F89P%*8%S6#J`U836CGIU[P(?7^!3\ND`<4K(\ +M]:.KX3O\!W!IOYK"K0U9,D=!270*T)?GU?,L>)1T_C#3D:*Y!ZOJCF=HX[(" +M/=Q('%YX.:V!PQ;U2F-"BH2P6$G%6_(8MGO:)Q,+8HOM:<#%;JI +M:XVG-%^\G70`LFB5>24!<]N?^%?.W>?&FEGA+BVC%.6/"P'=<%K^(8BM723" +MY!&*Z)<>^ZY-6S?QB"43$Y)C'A@^B?`L!/@D0=H2\$*ALMV(&' +MFV6)=PC[[8>!84`9(:STD8TW:;/N"4IM]U'9FFL>I^J:4Z\H[#?Z^6N%/DU9 +M(7[NY"SF+V?$N@_G'(RLM'2%V423A3XFY/&WRNZN\;$068UBMF)8N:(UC]IVTWBM^BL*VR8D4QJW4$QD_U[52VC +M"%QYQ4[-K9V43U]?W:O=!2%]HR]6LK.PJW?1)P*GUO!"(`("4TT2J>0ATND +M>DE7.D9-SW.K1*E7"&6:.`L]6\VIH4\*X7^3`:8]QC*\!5D0!^J_ISZG0#N\ +MGQQ,IU?*50;I4)#T\'?YR@V1BQ=60^[1O,2+1H#8"=C#Y3LW7N@MW!SP*%J8 +M_@P5B)OD.V5P7.RZ%WV\H@]9%1V_`F"B&OJR[^HYP--,N?N;GQURPIU6.FOO\.I1(?[.E30]7RR-;7I!WDFM?A&%6/]XI^F-Y0WM[M'EK#-D&S`21RI +MQ7'A!P"94]4RS6L)AL,(7HDW4MV6`WI8::90W2_'8W3!]BN<$S/K.C41\9X'YTAYYA1FV;&*)%(TH:U6;@.Z +M<8OS'A4H`]7>7I!K&Y9ZHA)^,MAL^ +MH9N'U(G(ZWF-;_XY*SYGB,.Y>U$YY+Q(RAD1V7>6.^[".?8P/1(CWBCE?Y(> +MY,GU*$9P=9_V/$Z=-?VD3'O#F,=`8L-;(QJ&YM9O\J>)E(DC[J\"@;>0*'84 +MX\F2Z?,:(*3,Q'XET;J]O9N2A43DK +MBK`!N"+>+B2YC?G8OJ&,B19LT2$JA6T7*;$CKV,`:`4O$!RQ*%J\BKE9+1TN +M^:'"LO%,25X$Y]T.A\29P<3%IL!7&7$!3B!EPWTQJ8.WV,[9)FOF&9B."!^E +M;KJ*DR_G9F*(VN'K[\;%#\:RW60'%5-5;W@OFSL";N--CN[0J-M;O/@/0GS>MFP;N( +MTX785X)P#R%J$SN#YTE5K6CNQ8<84!T(/']&.P,<=I3^O86VP?ZA=Z<@\!L>]8]_/.DR4B!9X/&L&=]N1B5D_196!UGJ\]4%>:I_ +MJ@)>@LN+S]!-?QHT+]D5E_>#D:UYK6.WR(/>([$:3)<4.%I*-@A/IGNY:RS* +M3S2EDLW_2[LV2;LYCM&3\?.=84'RA +MUR=WVX:;A"2DFQ!E8S-I^1<$R`HZWV3?-G]8:Y#,.>A@=`^A;Q?C.V(S=_;( +M,[?6(:F[[");ZA>\H47?VSVG!PA;)3(/MIYZ>'#K`;$8/=OK*W7]Y)+=I-O& +MNZ\B+.&*/D=Z"$T:D^3DO%T1$$``(#(NTHB8(1)H( +MX;#B\$T[$X37,SL]?XDR'KO62?\%3>ST&[ME+XJ(\Y?T?PS9CZ5&,@$E'GCZ +M>3;7RUCFF[GPTS:A;AH>/&+EL;?#K#A^NGCWA>/$M").DS@4PZ3\;T96 +M@VW+?A-+_Q*=HL,2<+\R1G3.#(RC`Z&L]^227?>G]"A%\F]3B5WPD:I12I&V +M<,(N6,.',^$%^X;]L%NZ9H'Z!KU!@+E#R[K1(?M]><;/FQAPLS?>N=XKTYEL +MN-PIY&*VB$-%G-%6-XZNICMSXD6&,EV(J@@.-R`I`XR2`G^,^T,0G++HSITP.5B/&132Q\O0/2LH#C:;Y=.'<;S8>X:KKEX%(3( +M25#P.\@!K]%$*O$UII=CHST9VI[VNC=DB1Y^[X31T*GTG +MV/_Z9@%CORE;KG^;=;SZVXUT#:,W$=9:TO$H%I^!34,9%O3F&AET@#7+XV?Y +M)9$Q7;A@Z'%#;$CF]%6R28_.XCPCJGL@B+^[T@$$!@`!":G_``<+`0`"(P,! +M`05=```!``0#`P$#`0`,P,!JP,!J``@*`3U]DI4```4!$0\`>``X`#8`90!X +;`&4````4"@$``"U#*W&SG0$5!@$`(8!M@0`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj_lzma2.7z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj_lzma2.7z.uu new file mode 100644 index 0000000..a61aa70 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bcj_lzma2.7z.uu @@ -0,0 +1,245 @@ +begin 644 test_read_format_7zip_bcj_lzma2.7z +M-WJ\KR<<``.X#6P&!BH```````!3`````````-AGR._@:K\I_ET`/Y%%A&@[ +MWP)!,(6+]:YDCG/TF9,6Y4@I6&:W,\L.GXAK)SG^7$ASM;Y]KP;]Q:,S]93R +M>,&)>5<,&FZE"`#6^N9W.O9$'UE^T-50DI_AD]BN$0G/D?)@D^5S4+=>0I33 +M8+60+5WO?S\=&H#(CWK#P8A*.F39U-N85;*`7:QH4MPY]Z"R4@0-G[PN0P/I +M&4U*T@DV'"`CQ@7=GL@J7_2-A[.]&`<]D>$^(9=0(?Z*\Z.%M#RG1BD;5#6( +M4_PL?`47!00BJ=5&HZ7@@B$C!NO::D+1C%8P).\)*UDX0P@<+::RMJNW=<@+:$ZER\IE^S3 +M<>=HCZTGM[:O[2?'(:Q@840D]\]5Y73NXY[]$A&S9_<=T[^)S9E-I@,/"Z%N +M3%P8EQ8N.<>T1U:G?9*=LX1R,65>5\LCE.PG__FU`+L]UUEKFS13]3C4N`J/ +M2*#MK;D6R_YC0[KZK#6ZDVED3OA(WO_#+'G.!7!DNT&:A<:N8%2S1T,0<.CX +MWI?5110E(]/(V5U26WQEEBY"+^%%%QQ*$$LVGS;&M##OO=PE)#7IOV]4!T0> +MMCVFR7A^)`*]D,D*8(TTY<\22+QK022#]K1P8Q>ZDOE"5%*XR1S_RD)#8:OF +MV8PM<:&:XO9&=U7J?O95W3V[0_>S$IA67];6D(/WJJ:Q>6%"L4.3$3?0E!!$ +M%?%!2/7&XB4BNO1`#[FYN$MKM,TL^'./,4GY) +MNO_;YJ7P.<8Z"R!*LK]S`B1=P4X(^JK3]7X8N(%H?=H&K>KB'G7(0C'R=1Z0 +MZ`IBTR?O>DKYV:WR$Q0MRO.CI2E[0;'KUGX`,?^8H_"$EOK=81Z5Z4VZQ'O; +M;O;-'3N/M(@343API(#U5#X1=PK%4)/F?[I"DE\39HS<'P)7H49\16$$ES92 +MA@%4O+Y4AD=?Q`Q6L[^+YH+AJ-Z!]8./"Y'^Q"*$TJ#,%/ESOJCC)X:D@0R_ +M?J)%YC&F):9`]N(:_,O,>0]$-QL,-?ZE@EH7Z=TEA\M7949(]"*65FN\?-CF(U?7P0?R&\DOWV5DVFK[.JXEP>WU1IL?6K&/C +MWJ(7%PM9ZI:B)8)Q$N-53QL+1O[;'7O/7/O^;3JY[WU7(!DWS`YXM'QL?+>( +M"XZ7)FJ3#T4640CH[0Q8U319C-]L^2259=A(C)[[!/*9P+!6MXIH$N)1*Z:& +MQIZ7]E*8%(B.D'_@P=8!H(?*X?N@HB+MAKFN3F][.%W':*1!5I4=/"TFY>,\ +M=4<$EI/)\S[27U*=0/;8!0P4W/=5+RC"*W]L[Z>GIXO;=$L;^CKMC.FK$GA0?W<=3^K@8Y^D_FAZ!W7WZ#.6HO6/_: +MM&X<5E:RAU)=J;SF.%&+0R;V*[FQB?;-D6E*-E9A9B[,4F',0KL8S]AZ3/3, +MAZ!6('R])>:,3R!'4,\HCK1#'3_?PE4$NKGPX,R?.IK6$:/[E%8278\-K\&D +M4\:14"/(J(V,!$2BJH@D@[TOT`^<-9#'>!Y!%G[3Q4L[4EU[56_:"*>E#X'= +ME='@D%RN4=E!\F6P+B>NF-E +M.')J;D/S>](@#H.CZB,"S;X1F.)O-8.%W0+\OBW-QVYBLHRW$*]^CP(Y/U\G +M<3B;CDT0]"EG+*#EDEZI35$5+9SLPO#7YC4( +M/'^E+!1?^*3VBP3&G9$9CU2`[V+^+*?N^CKX/5VXN]BITG#,SZN85C91X7OQ +MC*NK9_X/LBT1D8WVS!OCD4C7_3>4N>6Y[.58AS6TD<_W-2HXTD?5O2$`?JW4 +M#>E1DA(`HQ=#I"0OK1YBL'?/Y$@>3"0_Y+,WS'D:N2A +M4EH3`]F2VFSKLME)Z,E9_,4[!'G+XCO +M\^^`Z\^_!QY_7[O&*@MP8&R9/?%Q"XE@16@O\T+PU]?>]+ +MQO%2RW(E^$A@,C_K8V6Q,(\<*T?3=QQ4D)]CL-8JTO%EV64)I,+2`_,\J._L +M2^N5B1N7PJ])*IU6?/,23U8+;W*OE:A@V<`;](1`&8U>JD6(DW,D!F]^H:VF +M;L,-_%X>,)O/C?JM)C=5^AL,$UQR5IE^&Z1LE"T4OCT2A?W*V(0FZ=[^9O=[ +M0L[DD:O6TE:IM]=YK:4\#5<6Y>]VU@73]UZ689)7!_EKHD0T^P))9P%J]^#P +M><2"YV.%>U#Q<%/(S*4JZ+.0NU!_ZK^5M7!QAIZX:/Z32G6WM(_6?(8E9)/O +MGY..D_/.%.`#A_`A'J3"O.005L(]?6EP;F +MQH7HX1HFCAR1ZQM^6(:4S7GX!F9"T=U-C/O+ +MM%,($IH!`2&G1F-=33R'N8/38:0'UK8R-M.OE^?B@GK<]_L?9*.CSS19I'B[TRS5DP +MH]XZ*@=4'N0J@P[$RZJX07]PA()D$BJ>JM2B14.HY/8P)=2E8[1@\';&"H3/ +M)K\^2;9WJMT1I_^!-`'/V15^*=!%]QH43#I-"Y#'9@90N#0 +MPDZ7ZG*X0/K*DSL[`\0HY64M4W(^[Q"I"\HMJ\:D/N7K3YEO^MPZJPEH2V,*E=IMWQ8"E;5T[__9''NQO$.S;KOSY&Y?/G:5J +M#A\^T)?$'+?-WQ$Z`'JWI3Y6^9:>JX)Q";!98%$S/HR**LS"4XW8"A%>9BDO +MRAIC[W%MCJ#K];":3B4`,5HG,6OW`)L)@!N][4&Q\=V,!V`H=CUN$8->`C$7 +M%9!.USIY%$TS2]-DLCFIJ/U,M32BDU!R@0)&:<1L7G:H>H#$GO#/7J>FABW= +M>4K(-;FM(PYL[]WV;8O,LY8:J2@V$53&XU`0`2]F/"[->8L@I4%MFH#ZVLDC +M/@T#HOKOQ3B_.`*!AW+0>7---V)6VLC%/Q8P(?K*&G7;RPF!6=-6/1=4MNA] +M7W<>H%2)6-5]EI]E8CK>-9?A/04EG"9L'E#\;IO)#E1-^C!(ZO0H&NE^W@N(3UFG?:I:3P,"#DQ41-K1@*#QE7; +M]W+$_3L5:1$\.("#"CK--V!Q34.3GJ5-9SKJQRW^4W6SU*"-9<7U8=SX2)+K +MW'LG]DD>@FUA#W_-)WK%\.&\#-_?W.YZ6Y]/1;Q\5),6=LX8F\5?.%]X6<71 +M?;:-^U4`M)T(J'EN".ZP>>ZX>;'B_*JQ3QJN?0<,D.5:AB.FA[E5-=-"@O4! +M(F^R\05T8`E-4F!NS5LV(VL-(M#[6!("]1#8;-@LE^V\4*!U:SXZ5@'PPWSI +M0M.I+($7SJ._H<]-!AJ7>BW$J_#44W$;-7S9L/8*SBN=U[)6I$)(U6E&\8D6 +MB7@5F\D)&:U?,]>Z'[6^8E&1Q91HLMEX-7SQM&/P4;ZH/\AF3]9;CL1[ZXSL +MI/3,Q,VTB6BM;E*X,404UJ]\M,L`_R!NT+M``JB>+=-*+;8++B:CLZTF%IME +M1)&SI`2A_;*=>Z[VZ)([-+/O<-8[!@QP"`(J#I3+6R9KMD;<`B&;;Z,TJ,(4 +M7QZEP5>BF,0.XPN@FLPW0,#7KZ"_`.7^R-JS#H@@6\3N_S-OWF=^J+!Z-'?M +M5*ZIA=F_>\[088#:U,JEEAE6PM[PX2+CQS13SL/9X%LXF%Z@UB$T'(ZU?^`SO5Z7\0,%I[8@6 +MGD8'03Z>:YJ:R>N%?0Y$_O[6LZ?BNRCA=37A,R/,$<>LH35**HTHR$&\Z]1& +M[TRX0#S1FB"EU2??5S'ZP=^@VVD@,%Z/3C?/R&5PT(J.4;GTKD;]].XMT8G\ +MF\QQ7:-/`*V+!74(GVTBGJN/LYO[@/`Q8@X9N5DZ^;S[9'("+9I\$R&('_CI +M04"%BKKU$8;RDI/->GO2X-)JR/LL`;#\F[X/ILE)[S,7$=OI49NK*YZK_H[C +M;(U!AU0$6+3;W"1A!/DY/X7G0J@FVI[_Z2[R?2-YS#=2.A9`\[";'@_BJ_8@ +MZS3*LW]:,0(83P2BHK#=<\)9>-J3&3V.R0MAB;Q=6Y_ON<`S-@Y6*H3UDD7B +M;-Q2?F:D--15N@/$^-]81!-&0-4@?-_7ZOP[4228AV`5VGVSOM'']2\Y +M?`%?^?![KCTI]H[V7VAS[QX2;5XE["D^I\5[O0AN[!#6.P7H@4W: +M85X`7W8[7=.^#]'OH0JBCP58C':P-3BIP4#OB?%4K2A;:$E8$C/CN!#!6DB.'ZX&HE5SIQ'V_<&HTDT=.P'>G[9U&,^;,3X:OO_!-[ +M;UQ8*Y/GD2]*"H-R3*+B!%(L:9&<`5]0]6`KR/<2ATPN8A]/"#O*.O@;QDQ=:+&<.$@KK)K/PKZ90:#3X^\!S)474V8(Q/S +M0I%"A^O_6M"EW9EC=(ET]FT[3E=A=OA=@T"KA@8@1@%D[B.60ONF^,$KDWGX +MGJ3UH-]XI=BWT5P*"`/+V$U.1B3$5GB_KM>W%?5S(3F=VO^R-%4K2!/M1[FX +M7D36Y&Y`U-N>@6D:>QJPZTL^/R10SZFD2NF`G*P[3]R(9JFF@KL(4&?!#`/H +M[O]9-9"L3:^?RYBI:*V1)-^@C./??0=5*_(QA_CD1M28HUI#&QI]ZEJUT/KD +M>I"*2]L!?Z4+V/`23D=D.(I+9OSG4D='N_ZD''(6034^793JDG'SP7R:CL_Z +MBH%@,>25J5=7-H5])9HT8(:!J;FP?90%OR_E +MX.&[K87]AY:`OJI"ICPI)&/6=._AI"AYHM8V/,87`C' +MO!0'$7OS@##S9B&,,KHM9@::[=#9;TVMYW(QO0T\@SMFFAN!=W/U?VPY41)+ +M4CY[?_!IV",=Y.8)[W]U8Y;3IBC/^N#/`M#(5#P%Q9L +M#[.ML0%'98I%"`G*I&"M`$`7.D,=)!=4]`>H8M9(4I0A#O\]'3(PJ46Q)-;/K-/`5JN",&%"+Y,<-MWE#2-(%V&#>H\\.RHP. +M]S0-I#Y>E@%6*7Q6FY#*Q&JJ]UW@4WA+,%QE3PPE$8$AS?0O7E<./2QA +M"5TV%"1%(A'0&.[WUV%$,*3.B*:N"8VF*#AU5\Y^8P3WP#7MPTG)VPP#CY9/ +M>N6R9>0]).7-KI?S&LC-D.R0!>&^ECY%Y:#?W#HK,#H:3NE5X;M(Q$^U;\%% +MEBMP@/MIS:[EF^7_SUQJ,Z1VF*;),:QLT]CG4C1\)#W\C'4SBJIEUX +M-)C!Y\6P(ZR)/5`:/6_"!UQPQD"^8):+>OG1JHV,3AV%-NN^6R<&L +MYDJNT3G3\+,?-^B#/?U[/)WSW;&$JD0^I>"MST3DTA4,92>9$3W*HE3E=<`T^@J]\"\I_1@$8P?LYX2=&>TK(H +M[IDX%#;#/052%71UXW$ZM=B7/C./*XPJN8ZV1+&IG$`.V/A"1SL]X@]BN6$Z +M\L81365TRE8"[=YV)6H9BJD@6Y'F`5@R(N6WU+?]VP^US7$WD/&2?ZB:"W=0 +M;ZN0D^>\7`!WCK\DV`DLQ2Q/].IURR&!;Y6)0XVIZ[_3K%QH@_/$Y=U[T`A" +M[/A:#NNEY(59/4G6UVR]J1UV\>)UAD#/V*:1%61;[\F>802&'<-ICN^PP2FH +MR>6NZNWNAH27%QM4#+H'N]+1^%CG`[:[9>S=%M1$$KOK_]JL0+]6+-:]9>AY=+2U\NR4`C3@E, +M#WWFW1DVA*E'.T5\,EV+<:]-A=X!:+G!`F!(9I#4'T^GFR]6D^Q%CR)L`B!0 +MO)0(OF>\3#U@%O^#US4`_Q_@A8*Z1)7%(ZQ%J?6M-$8'\NG=)!4C`MPGVB3& +M2E[9$38(/3@US1,"70*H&87;S[!UC;\*'*>3B(?@G;I3FAPQHWIU-1Z0<22D +M_[R=_8I-;V5*Y;(S,-]<%<6I`?>M!6@.'?)8-U\$.QK9/5Z)QT[JDIIW?/5R +MJ9([\+W2Z_3!GE7JO@]RBM/C]\_O?J.*]M2KMQB-5/.3<1`\H\RQ2O(7,09O +M0?X-9*[Q"B#HGK\B5.FYNX:5QE+7C!.:C]9,$[KPXR#I6LR2ID1EJR/,)OW% +MAE7[+>'NI%$H907$J5)49 +MIXH#DNA!D--=$KY]0&N]Z'<,+_>A(YZ?YK'4`@,^:N?-3@A)

    ;`2,&](DA-\+6/.WM!X0,.T8[ +MF'-?PAX#0L?`J#M!ALYFK*I_(_P^(Q^*W4MC((OYFP@Q7RI'W1*IR/8R(\7- +MA%IZ-S@\XSB/G*3=?/Z5S;*RL7+@:#=0M/.;(5EFT4!R"M6A)YM3U(/+>OG_ +M0)M[[CD'KM;*8UGWC!D5I7GPX"@?!$[RK_+AR7;=O/-/^T]&OE?RM_N%..M^ +MT95Q0#0\LX%LA(05LDBT2UJ5(0UFL[6_Z_F!KAW@2!A^I25> +MBAF8XNXG1V?8;M,'%TZRVV\0*!!4NFVG!A*@'_(WU'=8.7<%)XI3^8.N4 +M#3-LW<(^*PNNKKY&I/3Y69"B2=V.W0$BTD>3S$C1F]!T0QNDP8:;Q&S7*`?G +M+GU7=_HND#LS58$JQMGR`RT81!J8@XZ_.D1)<0IUO8.'@ +M9I!6#.B.@\2WO'G4NP,5N?JT?0W.,UZ70[3%(UJ`O7%!5$22^4F[&9A=NZ6T +MBP+L9@9""H[/I;A2*\Q1P/1T$NC@$PKB]0_9N<:]Y_5YF=&M@6/R>6/2MHA] +M;6.[EQ*DK'7!P6?8PN@_(N5PRW4M[A=*#X?C&5;-3"82;2VM]46--D'^+$N0F$A"2OC'&8LCB[,0TY=SP11Y57AOOV^%I^Q +MJK?+.UP86?:'9U*'*1*QYX?:[&[+X.[@RD*A6BUDW09G'33JZQ`BDN_F>DUY +MP9I,OPM5(RBT/&BIEIJ4=,;#2^`:VZ#-,]NR[!KXDKC;3:7X8P"4(L15=&/W +MYL#*W>/VG'18))_@*80Z!3QR?DN05D#)$320O#Y)4\.0PME&.N1IZ2Z[0.6, +M!.E_O&L$G!\UWULP8^IW_W*.O^UK'OW(!GTU@G!2HXZ0YR8\"5X4 +M"9VB,\N_OW&P,^];7*Y8BC#P&JV0`/>4<&2-$=^4F(\\ +M3:!!$GN9\NG!"),B+35?.J0@)Y*##"4/2%SV7__/,;8;Z8*ZER_S`T"%S]_1 +MY)V+]!Y_YNOOV%+(QZ$;\V7^GU3T'%X7^G1LFW(5`")S?)"ZY"VV:08!;)=@ +MB(-+SEYB>#7ZHN301+UFJMH#DYKTH[>)I9&`C=>KV_/B#7D:0-N\#.;BQ_"` +M/(V!RGSIR[40/"&/U'JB=^Z5#$^R7Y]0M$,C@IUI.^P9"M/E.!0:<+PB^_"H +MD[GI;X@0!52M![84"KTU*3'MZ+]@[691I>:X,(S1@L>4$U%7Q27("H2^J2/)`M#8JV-8RYP!>[=8*0']+B3"R`]S\$&'I +M[0&>VGJ//Z#RNQ[F8X:I?;P$W]IRSJK$>+\C);]&ZC\H)O`Z0%$147&IK..R +M.I$_2$F'O4Z&,&YMVP"L"NN@2A[A4@,<++T))G&/^,->Z=^M%4\?_XMNBLX) +M8[M[OCQ@=T-BJ@TLP)[;CV!F&@YN@:/VR=*&U%T#0?T&(IO2FJ\[Z4/$U_V.-/CWO:U%S$^ +MH^'*,TT?@<.0:LH+MP*>KD;02H58$)9VW7P-"KF-1GE3;R>\O-OT,^*G\*"I +MZP2X**1:T0,F#J_QAF3-NEOTO8S'(<(O@7*?,K;)3:_.K")@Y[&;IR,@;[^! +MU%*\GK\E2C.G=3..B8KJC10CDI@>4&73_CW0]^&VUKU1[`&`HZ@FVZ;ND%:@ +M.,-9#Y7<-.#4)^^EZV=?7$354;O:D0/>?3'&47!!571? +M:./5N/XE>@F.?7-[6!=B*`M=`Z$8%(-8-MW:$_2WB@12SV,!$P%(&!H8H]UNM>=5G_>GM +MN$W^Z"FG<0K1N@P[_@-TO/DJ\A%7@G4OM^Q$H?[WG%C:ELB$M2UE.U1TB-<2` +M$MI``@*-5,#;]1%S1$241WG.SBJ`BR#5(6DTF==42ZA2[68+0#VN]'1?9M," +MGM\^H?YHC%GH&!'GZO1K+PXY$#[L'=6"?)X;W`*9`Y@,]D;/:Q!0=N5<#[GT +MIVWEJEC8\[!OMKUNS,/N1"OO+W"";$9\Z;+12Y,R8K-!+T&2"WU>G:_7T06I +MGB@@_7DW!>A]`\3>"Q_TV&9=`==*MAY?RR@5EWM<: +M)>2FTKEVL3[GSW>S3=>[2EP!F?F5].N/*_(2^GWP`26*S=3`%0F`.WP5V0YD +M/1K:U"HC3ZII\^%@FE@I2)LKKWMW-YR+EB\H%MF +MF$Z3TL6=+K;Z>EJ=G'VZZXPR,<`K^]F89P%*8%S6#J`U836CGIU[P(?7^!3\ +MND`<4K(\]:.KX3O\!W!IOYK"K0U9,D=!270*T)?GU?,L>)1T_C#3D:*Y!ZOJ +MCF=HX[("/=Q('%YX.:V!PQ;U2F-"BH2P6$G%6_(8MGO:)Q,+8HO +MM:<#%;JI:XVG-%^\G70`LFB5>24!<]N?^%?.W>?&FEGA+BVC%.6/"P'=<%K^ +M(8BM723"Y!&*Z)<>^ZY-6S?QB"43$Y)C'A@^B?`L!/@D0=H2\$ +M*ALMV(&'FV6)=PC[[8>!84`9(:STD8TW:;/N"4IM]U'9FFL>I^J:4Z\H[#?Z +M^6N%/DU9(7[NY"SF+V?$N@_G'(RLM'2%V423A3XFY/&WRNZN\;$068UBMF)< +MFD;<":E*@8N:(UC]IVTWBM^BL*VR8D4QJW4$QD_U[52VC"%QYQ4[-K9V43U]?W:O=!2%]HR]6LK.PJW?1)P*GUO!"(`("4TT +M2J>0ATND>DE7.D9-SW.K1*E7"&6:.`L]6\VIH4\*X7^3`:8]QC*\!5D0!^J_ +MISZG0#N\GQQ,IU?*50;I4)#T\'?YR@V1BQ=60^[1O,2+1H#8"=C#Y3LW7N@M +MW!SP*%J8_@P5B)OD.V5P7.RZ%WV\H@]9%1V_`F"B&OJR[^HYP--,N?N;GQUR +MPIU6.FOO\.I1(?[.E30]7RR-;7I!WDFM?A&%6/]XI^F-Y0WM[M'EK#- +MD&S`21RIQ7'A!P"94]4RS6L)AL,(7HDW4MV6`WI8::90W2_'8W3!]BN<$S/K.C41\9X'YTAYYA1FV;&*)%(T +MH:U6;@.Z<8OS'A4H`]7>7I!K&Y9ZH +MA)^,MAL^H9N'U(G(ZWF-;_XY*SYGB,.Y>U$YY+Q(RAD1V7>6.^[".?8P/1(C +MWBCE?Y(>Y,GU*$9P=9_V/$Z=-?VD3'O#F,=`8L-;(QJ&YM9O\J>)E(DC[J\" +M@;>0*'84X\F2Z?,:(*3,Q'XET;J]O +M9N2A43DKBK`!N"+>+B2YC?G8OJ&,B19LT2$JA6T7*;$CKV,`:`4O$!RQ*%J\ +MBKE9+1TN^:'"LO%,25X$Y]T.A\29P<3%IL!7&7$!3B!EPWTQJ8.WV,[9)FOF +M&9B."!^E;KJ*DR_G9F*(VN'K[\;%#\:RW60'%5-5;W@OFSL";N--CN[0J-M;O/@/0G +MS>MFP;N(TX785X)P#R%J$SN#YTE5K6CNQ8<84!T(/']&.P,<=I3^O86VP?ZA +M=Z<@\!L>]8]_/.DR4B!9X/&L&=]N1B5D_196!UGJ +M\]4%>:I_J@)>@LN+S]!-?QHT+]D5E_>#D:UYK6.WR(/>([$:3)<4.%I*-@A/ +MIGNY:RS*3S2EDLW_2[LV2;LYCM&3\ +M?.=84'RAUR=WVX:;A"2DFQ!E8S-I^1<$R`HZWV3?-G]8:Y#,.>A@=`^A;Q?C +M.V(S=_;(,[?6(:F[[");ZA>\H47?VSVG!PA;)3(/MIYZ>'#K`;$8/=OK*W7] +MY)+=I-O&NZ\B+.&*/D=Z"$T:D^3DO%T1$$``(#(NTHB8(1)H(X;#B\$T[$X37,SL]?XDR'KO62?\%3>ST&[ME+XJ(\Y?T?PS9CZ5& +M,@$E'GCZ>3;7RUCFF[GPTS:A;AH>/&+EL;?#K#A^NGCWA>/$M").DS@4 +MPZ3\;T96@VW+?A-+_Q*=HL,2<+\R1G3.#(RC`Z&L]^227?>G]"A%\F]3B5WP +MD:I12I&V<,(N6,.',^$%^X;]L%NZ9H'Z!KU!@+E#R[K1(?M]><;/FQAPLS?> +MN=XKTYELN-PIY&*VB$-%G-%6-XZNICMSXD6&,EV(J@@.-R`I`XR2`G^,^T,0G++HSITP.5B/&132Q\O0/2LH#C:;Y=.'<;S8>X: +MKKEX%(3(25#P.\@!K]%$*O$UII=CHST9VI[VNC=DB1Y^[ +MX31T*GTGV/_Z9@%CORE;KG^;=;SZVXUT#:,W$=9:TO$H%I^!34,9%O3F&AET +M@#7+XV?Y)9$Q7;A@Z'%#;$CF]%6R28_.XCPCJGL@B+^[T@`!!`8``0FJ!@`' +M"P$``B$A`0@$`P,!`P$`#,#`:L#`:@`("@$]?9*5```%`1$/`'@`.``V`&4` +<>`!E````%`H!```M0RMQLYT!%08!`"&`;8$````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bzip2.7z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bzip2.7z.uu new file mode 100644 index 0000000..07d231e --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_bzip2.7z.uu @@ -0,0 +1,37 @@ +begin 644 test_read_format_7zip_bzip2.7z +M-WJ\KR<<``.O"&:?B`4```````!&`````````%\J8&Q"6F@Y,4%9)E-9W9C" +M^0`",E^``!!`]_H]/^__X/__W_!0!>&V6UMJ7NU;KNQ4EW6ZT)32$R9`3*3T +MFIM-,*>H/)J:/)/4!ZGJ`"43""FC23]2&@-`&@``!ZFT`)3))E,AJF:GM*/4 +M'HFQ(#0`!H`!P``,`````````)$@C4TT94S94TT;4-``````4/DD[A^'IM)O +M4?;TRQ^=[=^`4PYH41W1A=WR^]==U?7AJZT?W^$+2+C,Y+0@8D][(7^]64YE]_LI/:HISLZ?Y64ZGYC@P +MS*=_?2LN-UY*JV%5P0;L##"6UP:G==&QL\DDAK:=U6@2DV*#;7U,M*%L[[XG +MED];.U`1615GK$ZU;&)0DY.CIX3F4>.3Z=,88NYAOA`BGC+*-U\EMPS.A2K. +MEGU+H86+IM8H0T:(D98'LKYE*3>>"SC9UCCY,<8BN&W=; +M@J9@5.CB/?6G/Q73=1SS;,-N0XZCUB'NH?O;1=NLIUMX^,BWPF> +M)[2>L'[WKK9_:/=]JY3JCFGX'>H7>?:5AV&%5UB1\I^]NJI76^C0HZY!(XT; +M+Q/HJ22Y6GFO$2JJJH4&@ND.36VTQGP,W[C-QR/;LY#@J&9OG=Z>E9/?PPM% +MY6C"U%C@82X'(C=;T40TA%@UT65V&A:0,$%,%E$W5Y,:.EQ)5Y!9R%Z$?H.5 +M-V>CCZB?'#'8^93`*&+HSY..MS.;&:PL[0R==&-#V,E-L*0J9W`\E6I57)DH +M-ECDI8S*">01&1AIQY5B5-%GHU12>*;9%=022."#&9&+:D\;HNT')3 +M><"$.%[1,";-,`U*&V5L(8\MA:Q"3>H'$J'V4O8WH;D=)4QSG(8Z"$JUG93TP'1Y(T_F5=HH87RNA2B>,\-#E\K`W$M$C-F8P(9.8@EQD(A]&_(&SKWPETM(:8VG +M.$V)@?(G(S>\1ER":3^\P@4L]2S#_;.%]PBW$?5:%TUZ8&M(%6$F%[CJWB&) +M>'ZF_-`B.ILR9Z.Z,@[I1F8I.ASC<[L9L6CBM\LT@O*$&<"#A/@0D8X2FI0MI>6 +M3M-W2RD4-Q%U0:-[!&`R&MSG,,:2BKDDD[1U( +M-B9%;RND4Q&Z_/<&)=.:(5!$FD#4X82S4(D"&3&WV;7\*G*M1-39@QS_\7FPNRIS`$5!@$`(("D@0`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_copy.7z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_copy.7z.uu new file mode 100644 index 0000000..2429834 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_copy.7z.uu @@ -0,0 +1,7 @@ +begin 644 test_read_format_7zip_none.7z +M-WJ\KR<<``-!QGV(/`````````!"`````````(/;BV,@("`@("`@("`@("`@ +M("`@("`@("`@("`@(&9I;&4@,2!C;VYT96YTN;;\I7YC.>1BQN+EC0JP:,/8'I^CO'+,+O1BT_V!J25R+>!(6$RN.N7/`:E<835()Z+\30 +M7HIV[7[>>JA7V-Q4B,BA%R4UM#?HQF-[B9DE>M/_1#ICKKVX_%8F!1KJ*HFC +M3WIYZ-+^$,6\V``````7!H""`0EZ``<+`0`!(P,!`05=`!````R`R`H!@8KI +#-P`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_deflate.7z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_deflate.7z.uu new file mode 100644 index 0000000..bf4f051 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_deflate.7z.uu @@ -0,0 +1,36 @@ +begin 644 test_read_format_7zip_deflate.7z +M-WJ\KR<<``/.MOKA/@4```````!&`````````#5T;:VU54MSTS`0OOM7[`W* +MA/`:#CR&&==1&PU)'&P'Z*DHMMH(;,MCRRGAU_.M[31-&08X<&CCR+O[/797 +M23::>VZ#` +ME.(^H0L4&_FA'A:9OI;TAUBKI +MQN0YU1!KKG9D'#(3+F+SW-YP5=-XIG2ZS*#563A3%*HV/_2Q,1VOMADXW)?< +MO/'X5*4.)P<)#>)N*:-!-1V;3EB$5FWW`^X=&H]#]5M/=5C\Z]FW@ +M=H`"Y<;N\2!\F$9;\W.E:N;`&/3B<9JK%KU:!13I:_;IP.M-WT@FIK)[5@^0 +M*-*#7J%VIITR>?,:AW=VX\GP>8GB]6Z<_N8M8UPV;579VEVBIM/U96J+JM9- +M\]NDF]HX?=GH/V<4KM9Z_))/G:J?%,KA''U/_\+,87"J=HW50'<+9%?FNN612&M3N68T3(YJOYO1O-N8%@PDH_`FH\2-R72^HRT*,.)AD6%-T6#;EGT_TXU. +MO_VR-QAW=!%U#I<%5150$;*S+8934K_#/!/= +M[I3ZIC>5J6<:D2R+"P\4=;]IG04;6V%0M[KVG"DXEM=EOT/K+YU>S.I?W?=SWP8/Z`@4MJA6GUP^;DG>?#CBZF80MUO=494B-]_/M1 +M9AUE4PZV=2=K4X(JFUHTH\&'NONTK?,*FYDKDW;"1]W45NBY<;C&>$[09SRP +M'_AW=]A3BRGHW/*0!"WNM?=L3,>,^*H]ZF#1-@X"G!I60ZWM]LZ%AA$:[K01 +M7UO]?Y*\,<=W/B<]L?4PIX7"^AG-Z+K65;TK`(.03&5,<7B6?/(C07A> +M1N%'.1$3.KV@9"K(7R73,'H8G]"7+WZ,B`3)^7(F +MD84RD;](I(A')!?!;#61B_,1G:X26H0)S>1<)@A+PE%7_=E'B0Q6,S^BY2I:AK$@YC^1<3#SY5Q,QIY<`)'$ +M1[%(*)[ZL]D].:<";/S3F>"2+`?9D0@2YCT\H48`+T!D-J)X*0*)!Z@6\R60 +M+T:$Q"!:_?N:6>7@U4DYDP.@N/5:9S(9)4(.@_# +M24<_-T```4!$0T`9@!I`&P`90`Q````%`H!`(#WIL+LJ*%14J=_<,7#6T/3RFH$9!9G6HOBE'E<0M' +M0-5!6&]I9Q(LNP>FO1,4C"0-HJF]E+UO?$`OP,0L]9]-?IRQ"#_84'^\-:$G +MT3JIHJE5;*\M)]-TIEK1=3?[2#(5!+N!_HL=H!H_R)BU+F9HX\D5.\?T=(M` +M=9=W4SJW579?/KS>1Y+'M^%0#4C+X<'3U$3C&%='!5[\EF[@4#2B9^U]FY)? +M`J8B_0+7B.I$N.X)PP3;'V&J*6VY.!&;Q7R,;M8N$$GCE7A'DD("6>XDN+^7 +M'[7.>5XJAT[)1$"IP%"H\ENNG?(IVD$"4B#R#;E,KWX0"(+I)G\I;FDXUW0: +MG\77W)*"$2C1DY7G2A@X<7?HF<0(324$@RQ94+EXCPV;A\!J_=-IO`PB]JI0O;215>3NFC>&L@A8ZVO8G: +M(Z+'4*>R53SX'U!L=#-R5/?1CX"K49RW+6#"?:O9#&F-VU+]XA>-H/+P67D. +MZN0JL3&7/ST/0,:N;-K'@%MH5*U@'\5C)M\[!]I6*3,C]3NA^OCP?_.^L? +M=17`;X\L"SHC@$#^"05.3&=DUY$\848Q-SC.@/%KQ:P`5J3YZ^,Q\-/Y(6LQ +MP?6TCO52!37-BUF`NWYVMM2?O%GP33Q3P%?#">B/A68F2MV1P'FKVPF);5);K1B +M>8HI`'2@,V/:[^SK\W]3Z;KMD.*+:9B<=!"$;J;;UE5*DM)][UB? +M]6V.JGB<\EVIL3WF^NX79\"D2_^:2*;[&U%K7_@JZDKEF1,3>-*2=:I*Z6Q%6C)N$U>TY[(C`P/L=7ANK-S3-TT\L:SL.T*&Y0>E +M.GQ/D;-/0XPRM5SL()'1_^7U(H`O&?G,YY4X%=>F@:@Z-KF"#'$:)WGH[<$, +M.1GS0RT6+#EYTEZ8W(/*D52"P-B('Z;VJ('L\]V;[3YB+264VOM'M9 +M/U7+D0$Z>XTTR0PP685OJ%/<& +MJ2F(<2MA[/"%RY6$59Q4^<^.2E4`K*^\*=EF4`D<\@V"R2>@9+%ND3R*?DVC +MY?U5RIHO)]4_)8R<3XLHQ:ARO&7:7!:VK==FV^WJ;$;UM<&(,B#=E*6P*"V"T5QBA@I +M!4R$!8.UO\`TE@9K9&W_'H:$?K3:4(%MF):*_OVK^A>=63C@11U@T1I"1Q?# +M6CJRJNUTIW9D'7P=!P341-$$(0GVW+S/D5NL-H62CQW"4(";.>F1#VI1`SN^2//BUZ2!*N-S5?\L%+&&+]KQ%-VW#[C)/0LX@$90T;HK*16"?-10DTO0 +M>).+H4UE!^5"8EZY\AI;S5W!&-W_GR_7YP*YD*]*(84G3+C"6?R[@K<$M+8" +M'9V'M]T:$P]LZQ6A3#<)_X2D.=BY9BP7WN:17-HZ=K8E9V9>'#%.R$L/'`U2 +M%RBA6\@>;DV"%M-2Z_VL]=$Z/^)=`$-)$CDP#?3I3M&Q"21C?*R@#L:;1=** +M>6J6M\$JO&[IM%E1\K(KV#CK]1!0:?M>([H%FUMVGTU,`#D*,+%)&$FT""V` +M3=1]S*'&PDK^6@#Z,&X][V6I0Z^[B8*7P?4_5N'E9`)5*.4!K2G`=(U@/RV> +M"C?],9@_Q]#\G67)I_,)+$U?R>51LS+,1<0/C$RW$8A_)U)K0:!3GQA004^( +M:U*X8T!*T_1#W1V4@6DMD&89Q$$,KQ\3F%!52496 +M3-!]GJ5^KWZP[LWX!PPEUI'YM$#^I_KLT9X0#)6@K!PWB_NF@ +MWT8/RU2Z8]AY4K"=0@6$,M"\?8/]ZFR2&1&`_!3U=IC.6Y0BN!TA.6C(>Y)E +MI%0?'CJGYHT2-)@CS.KV"@Y<=3%Z4N%FE7E--^Y651G3+2.IEL@BMU6O&1?8 +MX45]0!(O%9X!M:1>K`YGV^_O%/GM_5>+640WA4F9R0420YS.DVJ\99T+VE?TO``CRDOS!&U(=)T6!7O'S!QZ!/&Z+KD=FN8U)\$M19IA^ +ME8N&#-K%0\KB=RE(0WMKCWNFP/9(//7_,0.J@:`(8F,M63OAJPG&`F/$\U>\ +ME?3``?\,Q!FODDU".=+F\0>6-QN([3HC%L$7E(5*FNR9B/R`O\&8;<:8U"H- +ML?X;3TE6(>O0>/9T)7AX+(SZ6/D?FA(.D-JE)"38_Z9*0\%&R+`7Y%"/I@__ +MWF;"!AYKPC`NQ$A]4AFT!ZXW6G-CK3HE&(*Y:LP^FG8;+QYXJBN"!P9@CWYC +MNX@XHZ>]I0YW[,6RH'.JY%\J&"UI8,UC!6+9BR$8ISK9U>KC)*JZYH[[*XDY9`UXU/1_KC'"'5G'Y"&QDW`4H^?0 +M0ZOI`F$V4_#7+OH<),CK;&JU[^F#;AL<5FW0%]&2.AG#K,3E8:ZIWK+P[/`-['JND8[[^DAI`"ZV>]]YO#83_2-Z63 +M%G!2V?XI;66V?((CDM$I#793L`;V]-/[,8_!%6_S2H=/G`\M6 +MQU;]^=M/BMU/?,EQBMJY>6@=21H3LPE5LF9XL/AB4+8E.WGE6X2T!O\'-(WM +MEO'%E0`NU;*PKPV$PR-M9Y%1`&/MC941*O9L=CM/9_A8#*38Y6[=4E-`I +M(M2?3[;8&3''0#RMMF'CW$_6L@E1\V%9^U]/F&G=&[-!=R-XO]=I0O55K3CBY:66KWS>^MJQ\9$VL_2VBB\1W1^A>=][1UMIL$].A,T,W?A5IA:W@/'.WAF: +M2*K;Y']X8D/,;&X,YW-(C:O>"*@5_EZP#J]'/X,'`OZU=@2/&;O@ZX(!^?H\7>I'OPXHV(.@N6[6&;7[*G'YH*M+W>S84F&^UQP/>!^$/*J6#8P);S!S3ALHDN3_BL+3>:8#XL,V3. +M:69'F<4LN!:2(9RP#:V#A)'<`%`CMNJ[^WMKOCK^K.%J_T`@RA.`LPH:_W`3 +M-#"&2!B6PZ&30#4F:E.)@1&KRIB,&JIR13OQY'R]Y(%?K\"/VL'(M&JII +M'VO>J3U#_:[LB-JQZ9>*2.D]2_@U1`>CDQ"L3M0W(D09XTJ$>+T)\6[8[0.P +MPWSWY$R7A.VC[]3SC&-%I$,#)0V$A_%KF."AMKSX/IG2T%BRNZHN$2`W]O[,:4=$*F=AM(#HRD(`[!&`Y3>]="+V`@C<5[5D6J?GMYQ<" +MDEL"N&A@L)PW_T=K7L6HBC3@-5W`S9W2DU9A5/'LQGM4*9TW[;#=LDKA[Q`H +M(XK*DP6REW[4U@-<@"%&K4^-I5Q]W>)[+33W#8X5-LY0(6)P"*H]IT$=PL2; +MV7]>=7S>WGG?H%DV>=ROMC->C]68@]YF;!!6F53BEQ_L +M`0$I*5WKS*W7G>]2YHHA1A)DI11RZNU3 +M(HXMRO2C5)*;!Z4_Z_S;E66MJ%"%X@KZ)>2,IA:E+O:9F4EHL#'D0U](# +MZ$1=A(5"RQPB"W:DCM$M957$TTX]?;_"W]'#,6[#T%:=BU%45@G>`(0W8HH;2WP.:> +M7X.^L`0,QC6'QB.4'<:H_;?[HH55KK+ZZ(K(;#4BU/6 +MM]A-C0R[-7?A!\A$XV)ZV<;3>(#PWJ'G`A1H^M73&2TBW80SG"6\;_OXLLVX +MYX"RW]>A3W+`BH'-7?H)$L"JS&0PLA@6NZ_KV+$G$NV'N&&+PN)M'G5`7X^S +MMS8K5ANE%#L&\;1RA3@"QV;B\,S=(VM7*6P.8;7>YK]SQZ5)/T5IW\X7J/F) +MNH5RK0RF!YFU;``:"/K48?)96)H:VL/WCSBK@FI: +MEG7O*9+W1\`4#U^CUUD)[A!W)[`::QDFW6+FWM>5AA5A[NZ/@G]K[-;E=Q/+VX04AU1D3SFJ35+AHSQ.:LL*B@;,;S@)LR> +M(C]7B^7VTH$RLX+1JGD;-V!+R,*5G%7QYY`>AG>9RA"1YQOM]^O*Z# +M^.F?[5K(S6HC:U-CI\J@^=LXH<]U0=.?[:QWLN2_*H:.S/\_)XG%V<6-"3:+ +M\(K_EQVPN-IU^YY=#6Q+')ZE(BAR.DE[]QV?,&/$]UVN:H$VV&H!3S]=(Y88 +M^?CP.6IHOHQ&NT/)MOK%$E90.VO&>3\%W`0*6I@[$&"OKU1/Q,"7YI)EYL2Y461?+1& +MM2<\%E#K*'87RWDOF@X<;E4-LEBB$0?(CH5(ULI^S.D9:)O9D\52XM*N7>?_ +M&UEV@C3$3(!N;`>4-CU_ZCX?WFHBV"K[,!:08Q[@@`Z%).)!O>(H__Y12NQO +MV+%>&TZS;9\1Q@D3WF_'37E%S"6@N;K@^&PS;2PQY\,DRW>;X^MK/*[QW(:@ +M-`IW$&7U>3@IG%W\HDOMTO*UU>->\P).[R-8?@JD?K.5T:8`V,N8_^@0 +MC=YQ'VNPS%3#"4\BVSY5-VJ&*D6Q(C1_0B#@<7A?>/-_Y:F^S;O4J8-0->_C +ME`/I>\%4@M:.9?:,@/`*M6]4[_H#":*BPKM&-*.XBF\WHW,P,D71^62[3?"9 +M0>H01XC.;&/,& +MY1^?\5W9A*]LMIDHV:MDE@%?@SG"L)XLS]6;!X8B-#.%83SI.T-!WH_OZ*]6.6"(DJZB8:+4[# +MBI35;.F)C)J#^-Y1G_\/1-2Z%/^WML]Y`U`(!\%AO+R*+ROH'68P#W$]LNW4 +MN$23ZM0$*FWW>5==F.;B1#(4J&&7G;4?$7KD[4_0Y-S;G`<%O5PS_M[2\-]A +M4-EF1&L$-Q)`*YG38`;^"` +MQ$&?&V04*(>I(MSZJU>0BGD$KM,FR7P5Q[#/HCE9-_]AY)VF?;R%-I!%14OB]F^RU,^&Q-2>*XPN!&O""WQHB?EB7MV +M"*:BJ"UO6@U5(I]FX^]WAR+(*+TWZY(07;Z4;JMJ/35+;LRL*`0;'E87GUX1 +MXXBG5K!JQN^86V)%,-@BZR([\L(;]/"@FT*\#TS]UJ9&="`[]&@CSZ!CU9]Y8>(V&PIMKA*-%[A +M.67]I'72](-.H6+$I]S=NVIW&?Y9CMBGC'^U.[=+F9W5IW?X:BY$Q&7VE5VM +M."JPM-ZU!X?$YEQ#SCP3=H.3WDSV'JL[*^ZBU)2:QC=4$)*LG\18N&6#B&.) +MSF`5A9(^F60I>/Y7)YC:\(HQWGPH1@I?8*&>QP5[T*!'9^EMJ`[I9^%_[>G8 +M.$Y1V9$HT_(QKYGJ(Q=,;J0:<]2/0.4D[5M#XB\("W)S?WHS&%5W\Q0*)24B +MW47>9%4PG-92JL+CJHF("1+\P\??,G2>F"LZR360WKT.5XQDK@/Q@U0- +MMH2GF"N[F,E`U%L/3>U.^+SOM)/[Y!#H8(WNN56"1M)7)+9 +MZX^`QY$)VYV&C4A@5$MV6)N5QO5N[,XFLTN5(_Z/W.V2(MCY_4U9 +MIU'0<=YJOE&61^+4(+]"K%=,748Y;3;C(SRFD*LA,`Y\6%4DL!^'FUY8A-L1 +M'A)`Z#TQ@VO28XW:]>[$--59(S74PX(BG7CH3N:@MK<*!Y5*.77(A@:>[^FTV$+8V(Z[4+?PC-,N^K%$@->=:5KJ:(4\,*H6:W#Q87-,*CL\45D1I +MZ-BH)<:H'4=BMW(;TV+LNXVB`&U-JGZ)9"1_1ZC#T-+E@,QT][:&5UOYS^Q__\X[:=U5C&&: +MYL?V6CRK"/?%X=\K&]FRL\WD*$I@M8W=LTVS@EHN"BH,`&/65-=R2M6F,'&H +M&C=6_(_'8,6H5_55K>K#]2Q$82F7NP1[ULZOQH/Y$K[I-5A!=P?E1?;("/:_ +M=K^,`P316_*N15(@$('MM6YT^>[-&<\01RX!A_]AW?NVY%T;Q:,O8&"A&$\0 +M)C`VM8:WDF"6>H8JHDE&JL1!D]Y:50%*>`?_Y759$N'X8%38HE4P:<'N_DL. +M:E<2\AHV_WNS-O?Z=IZ].=Q$&Y4H.UK^.08H_V6/@LPF2'G2XMK#U]$I7NE[ +M2-ALYI2\T$TRJKUG1(BOH/"JEWN\O4AF3O)O0&J#796>G&/`5Z$/%]8Z(0.' +MS6T2$U5H=9/6>/9UR>'3NX\7\T:9F>I`2[!9>1:[PU"U(]\9DL8I[,YI]IMA +MN,8K3-\IIPCNL;*93)O"Z+*>_K%9]KYKY1O*,IF0@#V6E_:]3+1`>0IHIAVI!\T@MGNU7BK43RFW^X>!9-'$VON:PR,#VU]^!"O6V)V%*\OX +M80:!WXNCD!!SGY!E[,C)SK::L-;*TB7S'WNS62B1&)[PC>U.Z;EA"H16D<#Z +M1"C/>M8$_ZR*#;#\>*DO))@"]4Q;K?[W>?2\#B)9&YH&&1#*4)FXIV_7-.FV +M-EF]2(:P=SUY3G]8)6KO"J'#(.7L'W"^#SYQN!I`DCF4>4-!'`C/*/`%23(Y +M3O=L^=4*9VE-#4"46RX(!\_7L8'%,;'G".''P\#FK=7C#D>*[,3I?%LS=8H6 +MD>]BOWEC@)*B=YI)M;#!]<(!6"SM(`HS*7>1R(,]:S +MIXBX8:"N7'.PR2<.)P=%[(/N6R(C:!=!&D.O4LCN[ +M$0U4^%:/8&>*MF/8G>+`]+D0%1W=LR&O#\BPED>!L%)0@)9C][;4@>XSM\9. +M:)@-;`P;C2R[(9V``#!;2B#!((RQ_=Z6A8FC13AC)KPFS,2C#KC@0,,!=4?R +MNT"$]8]=HQTZL(EN1[58BJV!V[57>%W%7X>JOLBE`M$2#H$]D*^XG5$W&.Z" +M,UMY\(ZZ?PZ2Q8I97T1HY31%^T?DEJD<3B#IQ[R'N(RF;7Y5?FA:X>SN +M(7R,Y(H;,A)1F"=-US`;XC%_I3B;D?T7FD;8![YAU#I-;%CXW7JK^PX\LV7F +MA2=25.UV$OSP6%60;NVVTJ4.A4_NXC%ZG +M@OV7P!"@KL+@[/0U@YU0RLHH(\`D2/S8NE73/1759@?VG-[#^5K)-V( +MKC6BB"B-J9LJ?F(BIO&UP^-/FN6/E+:U3+;`=]/`ZK5#%!T+@O#UKQQ$3>V` +M#?N3<3,8.])L;@N:L%8V +M%G.KOPN7][!"[<'*KR+>`%0ZO_69&2QU.UUBS4>G2\R`)1#0[B9[]O"E4N)/X +M/RH)DT><1X-KU`4F93].H>N,X2VLZ]+;::6/Q72]V6FY42.I'7X@@09-A],I +M3!,:C#/^]1Z>LS"7-]A3=Z.>]>)V>F1T\KH9=\5.07;*4JCJA"%Z`\C>PA3V +MS>5?9UUE[S7/+R7B>K_&UGZ!Y7%0@A(T?$I=:6GZDM:)'2;2-S9/LO8OQ31K +M(M^>-'.XA.G'!TF$BW7LCL,IF@6.0JR#Y.\(P;V!X74=#QH1T0%T%C&SCI$* +M^'_2-=-9JNC"#ZJ",4\]LE*,%0[5'OKA9P\,%&QZ%F +MX`35=#VBJ>BXGVQA2XH#.SYX`),GM0SI9](2TZX1LH!+S*$BXB()*)C5L;LD +MEB6YHX1"HN4=2%H*$Y:LNC^=5-M>#$I5YA)@WM].QN[0];"PJ&F#?,.BVJRM +M27FN=O8,P?\`P=*M!EM!DGG[H_UZ8<,B>%`A%P!,O[/%@[8_5"DYRX51)=.` +M\PHFMJ90"*@XI.^8F,9'T%FYMW\E%H5.4L`XRO\.=X.+42F7Z?%=UH.#\WWG +MJ#_"]0F<4,V6G#T<7-ZA*MP+`CZ:N`KRI$N5NP1N%\2=SNAY40I2%KO\6QHG +MQF4KH'C;5@VCGO(394SKUP$USQF?(B`3ZU:FP9BR)&K,KC1`$X./> +MF-TOJ2C,?Y!9K!B:J`Z''=?RG,I%\TB)I;KUTT-A66=SHB=B`D57L*\B9X:Y +M]7CA-Z&[`7"=9Y`<"1V08NK?,;CS*5A#>0SOT29]?W+:$2WP(IR`6#;7(U"U +M5?H&ZQM#?;Q$RJ0!JKC2I#K3/(!P6;2EU!O,1:,2B%@4-;YL>TXPH0)@I7`P+BM<:Z +MD'A$\_+O7XXGNHD20)0N--U#>LA+8IBW&@FWGG%SU[A%"$$L2560DF&G&SS- +M9'V/_$0KPRN_X[QMJ^@2SK,YT4RYG,Y[19OVYO,1[RM8HV4X+<>8GD%0#9>. +M\[9%/ZMK<@#&:I79^69,&>(IMYR7E>\;$&:&@S;'?%=7X3)7J$BT>)0U_TYQ +M9ZE9!;>)S@$)V(2M7+YD#U6:R9XKNH58$`Y0[?!,!E_%;P$@9M[J4!2V;?7J9KR@DK_5&0Z4D%.>R% +MZ):(=I#:@8@P47-WUYI]GC3)=ZHM-RGW3DV4RF-N:;/ZC;F,`%XF:J3$DR^- +MUO.%(6\"F@9D]+N>"M+.`UPM7OEQ]FL +M=+*8#`?/-V6:^@Y%SEG(<..;Y;(H^$H,G%&\,DFEB?*"!6]@VYG!GOOC!NCP +M3GP'Y[:+1P$N#*F?6(UV)A?.XYS62=)&BQR:)TO^'6L6:O?TNGOHF>AE>VW3 +MQ+^7)L[9\V>8!"AT@0/(5?/]9""`>7U]FAMD(3>IHQ +MFM)CGJ,V"3X.3!Y`BWH9:/`L%%IV03`3"CB*>Q[@>,M.GO%(M,16IR[4N-H7 +M0_F1S`[>>ZR>0L8I041N/:1`ON +M)P)JZ15?2%&?).C&0JD<30`?_:NO=WD!HX_O;?[SFKQE1X-)C%\Z\("^ +M.SP??@UG)[9(>E$''Z.VX4CG=W5`"XDM.(ZO43K*UNWT/9:2?8AT(),]T]8S +M(D-VQM8A9O)O0Z%6U-FQA`CSH)+QSN1O#H]&B%7JS5]TDHP%/><[;6B +MV#FVW&`*ZQGAFSV!#"#H/B=8Q&%J\"SR8@&8R;`P1+6\A(\8QC/%$/.?1ITG^19+V--7 +M7A8J0;PBPT,)1REB/^984W3T;E'-EF6/QO\N<>WJ-M6\MK//H)=__J-E`'17 +M:M=Y]>J5K`:?=";=62H6^%BEO%*IF.JF`/4N_R7<1IW&[@#EJYZ"_S\W<^%B +MDRHSI!"+1=?<+J0,I-+A,Q?:K.?FGHOT-M#2;F\(-L_L:"48C+`"W#!ZU&0J +M^B)6X;P)5=7&#^E5`-:Y>[.UFGM#3X+KP1-W>^F,Q:;@T:YOV?Y]J4CIVM2L +MO(/=LOCHY@R&HP3IP9LR))TK:`OW/A=H4-HSPI."(I`[)R&CI6[4)!1J3"3F +ML;%]WD8X8O^[L1T$1#(2V;+(X&L$\F\8:>>KQ8:IB#.F).O(1L3JB^MW&%F`99/EXP1-^>*@"NT3'^,,:C>*E=#?-$'-P+W*?DFGG+RV(V7Y1DD%^13&2K\[( +MW6&D;*IGQGN@/@75IQI3B\.R$[WG%`][8JZONR"G!MD>;DO`M#S7.#F+2*EP +M\)D<(Z)5E6_\NXRI#.8FPSMY[SR1 +M_Q!M@A"1["=3C!MC$\I=D&4_,LZ6.VB#9(R-0:RC7N#H)8`X;.R(OOI>%0(- +MA^G"&8WSYE=:$LH&KI0R8\A\(245F%S>,>*@!\DIFN2D8>UUFRG,DY/3B"QY +M%R^8%]#BE*SP\LA-J#*BHOP^KL!#4'S@7K:BXOM6>]K(\:Q-Y#9M&:0''!W1 +M2).:.8;W=B;:*A7[8UE/I^#OS#!+K-%75./$>*Z/-R$5FY_2"9%Q%+IGF-,8 +M.*!/U+B49C6!7B9CFH3^#$0IUM\_EL[I;^:[K^$7E\.0B/0U::D"<)>I!H=4 +MT#D:R$E]*;2(U2?8>I2IO<-9=&##O32K$-T=0#`6I@L3"W*;&YZ21.V`TE." +M&42I%D-,[&UY!L>A:]Z)MW,9(#X)6@3*40H\EU5C!:"1]KT_2Q+9W9)HD):2 +M==I=*F'KQUX_VQB00Z2)COJ$;..3>7=7="`"^CY+(%/>)=4@"<1L;*;0`D_2 +M[PS93J2SI=MS)=:M=P`7"*CE@##"6 +MJZ&B:%LTQI65O^3"$0@KN6.+'+98S#SRV?B;N/Z3833[SOG(O]W?(!3SSB'C +MU7R"-#6+C'Z^/>6D/4Z"<\%G;E:.+1#F/4R.=BU3_1&FE**#EX6'J4E?-)\- +M"O*X52TK19<%1A'L$4O:<"H"D;RD[`>S3ARV(4)/F%J;! +M\I$,R!+>M8+'/K3SSZD/"3Y(01+;E1L,G1YU-?,T^"4:!!^$PKA7T[ENIM$P +M]888.#/ZFXZ9Q8&&BNJ]O68EJ^6D12?)S1HDFSH:C$\'LW"DB%7QB;=I$X'F +M,#-2AV!Y:FS]=QDPR51@_7=7,H,P_X6AR#'*VQC$3@?/;KZ@$RT%+>)?!"1K +M5XH^VQ&9SQE^1NL[GQ +MWX4^.,=&6A()!6RP1%Q+U"K)'U8C:BC`Q1"_NKW_Y#R@='88JUY7_"F##Z&5 +M94Q?2'(A"$PQ%%\;_\2:3:ZFA6%?8PY97Y9N;2`+BG@0;>B[[`;7MH$T7XB_ +M>M]K821YHVV6#)5`2CQW.EK4:LPGE.!4J:W#X13RQOA7"NY$)-%M]\R'VH1< +M3GYYF"S2`%941%][8L@\,,VZT\+0#:?FNF'-ZV*->]#M3PN2>M'7ZA!2V*`& +M`J@;^%INM4.S]N+M@TXT9[]P6]Y!3-4\VC^MM)E]GMP)'D+1&R\FAS'C2S,P +M3/SNG2`;)J9(`HJ&#XJ^(T81,J2[H4Y"!($_@$X4!+E0`(:7F_'=A4Z5YLF( +M3L%Q.UKWM%E$$YD<=JZVX2:3`6F2@M(O"&T_"/!5&'-E3=++;:#0D1=?U*_Q +M?]5%7@%IJ3R=)`0TDKU"D=SG"[K1'M5R/710FDWP[',9W$JLL)-,?LK4;\Y2B/&2"XF?9MK[48':8.M^0Y/H-Q(H>00X.;">\'%$"@;DL.)[:*R5]V!W*N4")7 +M**KA;-."B]"3`R4)5TMDL$Z=BUGN^'/UJ.,&N-T:(E$'X"HFS'.(F7U%N@]2 +MRP4&YHX`8\^M)$$[#?U,&WK68/#!.[]+Y`+;Q@DXORL?,"^]*I;[I]YDMX&Z +M2%/6I]O,]R>\&JA^Y%Z@WFL]TMS/VX]*VJQ)FQ>(N&'@$WW7VHC5/ZK,QL3A +M`D[`7@WAN34HL2U:U?I[&O$1^,(-]$6(!E56K&>](Y%IYD:-'L!:.^A][3AY +MBX+Y;0A`W-)")Z^PM!W4(3&M\1K!42/KVXK?&`_#>$(+)N";"DQ;S9A\0%+N +M4LP93U4+7)B];I)0,SR"9^BU"H9H!%F='-GP(=5>U:7@D>ITZG&0SPI9"@:$ +M(;D.M$PIWS]._CP#+!L<&!@K/&QW\>'&\DAZ14_EV"FT0RL9U!;G`.&G$5'Q +M*H<;>XEOE+M?```ZPK@`B.JJ]H]EB+!K>0-;.2-,>[(V1T0-'NIXE'OD%]TZ+>2:"TE?K1#Y:&=@0@ +M0<8"CL@H)5G*2_8GG&B6UN[&]?B)]O_D>2%)UIU_';T.!GV+=4(NH1YJ"5.R +MK6VT]E)]M%&H*,9-H1^S&J)ZD?P@P_=:/BF7`2V0BZ^GV?O#8^F58L:)OPXS +MT#X'.''TMY!JTO-(C6YUWA68@2VX6@+UQB[3#QIZ +MGZO?T9/<_!I,F[MV(=L+3R-@,63-I,1XX>?[N9!BR0=O-Z@&0TW&B7[VM'Q< +MDS,^-V\NCX:D!F;?7Z\6?`J@3-S'Q)>HU"10U;L^^;0'X!N*BLI[`%X^/X;D +M![C/25?/J8J1$PW6D[UJ[C0LV6<(QV*(L-LPG/!,_^\C1J7YYOE_O'>9,LI! +M!@YK6$%OD\O,>HRNU=KFN(7#2U8WTF_PS^*%C+O>-*NN0P0$'%>QQHA]Q;)B +MF*J!C4?H,CAB><5PO"E>@FT0@+VEJY?F.^GD8P28:?QJ`8*GZQ.I9P"V"APO +M/_7RBZ\VNE=ZW.@J4;21,]B$=33[D21X`-]08D;V+'[I4K<.0QLX,D@"9<(- +M^Z#1#-&\.)4[6DX]^@=-;'NT`1.^N@N*LGW&9E>DYBAX4N4\6\T_T'ITL6^= +M83<]PJP560@+SXZ\S++[:V@R[C9G;K"E.R5BUC@BX#X$1,R5]L'*HLO2+(:+ +M8:=@06<]YQA"U&>&7%ML#I?*Y3(SO$1!B`3_+P!X\9GO4B$M"(S=;F;_UU9T*`FOU>O)\/_$4"M@C1K7K^)_4CBMCK0M3B].-[>G0) +MZZVJ/=4.8Z>?(248O?);T8WJAMTCN0[%PTWU[.-CUO'5>4$T75'Q)O5".',A +MGT!WALW&R8DV>TY,J6^NQ?*=BLL^?G,#U3'U;#1NN,RZ7'HC@#5?(D:X!;Y` +M\&6!WI[+ODO46HR("Z.4'3LK^KO&$ZFS,WE?,DYJ>#DK4';BH'!]D&?X]\YC +ML>[%;DF;E$"#%"@M8LQ#H2]K.E2K^Z"ZG8YC$\IN88<0E>>;``"ZH1*XN8)D +MX*'L[KI)>'W6L__0P*T(I_4693<;@A%\-#A6\H*XGJ#/2T46JOAK+^YGH`;F +MI=\"5S +M0"FO5T"UX#J-Y#.SW'\YOS/@H6I('!`YJXDZT&`K$"A7USET[I3/+RU#9]ZL +M6,(TT&9!TY,]1FG=_^:X987GD_2DY[[GWK19QP.39)F7:#P9`&=(.K5Y`CC" +MDWW/9"P%48&0'VD8$%HTHNVG.Q%O]/.<^_)P0J\C(.IAY/;-!]6(=#/O'C2\ +MIBR:31K8@[[QY<;Q\1=A5[QSR"8B2-A/F1)3G$?91>KY_[94@'N33WWK%.M$ +MPR-G$YCMD;W7S[?]<2V4^=NS!V0SG8%&!T-^5&QL]BLV49Q+21RT7-<@&M;& +M;B^Y$&YDVO301F&2C2_?`7=#ZFGY'TDZO;AF9_\9)65?9]V#>`NK:&'^?!"I +M\/W08`7$K?_^S=FA3-2_H.^K1.%[X%VBHIMRS924QBI5M29].U@D[CR>\LY9 +MFCH"/RB?/8KRL7>1K?D;!CK +M2JFRV+?#2"/_X5W]-J('=:Y=YXT>)V*&&^\]E$Z*?W"N+H1_S+2)"H3&@;4/ +M*](.UZR,;LITE-#=%EIO@6%T%VR9)*LCQV=&T_7S%_;%%L_JSSM4YW'=$C^' +M(]#AS$97_A3&IZ"$+':9E%^'7]1?^:'!@U7[Z5$IXAPZFLR^ZC+=0H+(Z&M[ +M4WH0O\;*[V%&.:C-W.1Q;].Z>PWGQM/Y!=`?/+!#[B]:3839+81=@GM//`3BP$']S^^2NH^K"Q[AZT"AK36LR\;WPW."@%Y_F +MT3>FH?8UMQCKAO]LV%%IK2:_C@.;@6"LT_IV2K!2EYX(!K]6027B#J#P4C+; +M[;>%TLKN3']+5?HCUK'Z5Q4DO!61L0H>D4'1^9&M'Q?E"MSHE/-4,=8MJ/$2 +M(C&0OV6H`*50KKOLVM-XB_5>-]==):(Z'$ZF3%COR%=S,7Z7/&9K=3/7>R`( +M#I$$ZF_YC]W%\%J#$%R"/`5#0-V_6S-^C5EV9*;%L)G::QU\GY]D(H@5AC3Y +M4R*.IX/!N"R99ZFT?@3$7D@>P]]=,\#"WTH$EB,Y[H0_0\Z_H<7[Q/<%($H8 +M\RZ3@,Q[!SKSV4]QXCB*3GIZR;M>OZT,YGZ$@?QT<;CSYT4*!!)F9F3-^\!Z +M(EFOXEYT&%J8U<%T"HNK'$9AQ=D)Q90RC4!OJ]-1.Q0EGQ1QY<,QX\A;J2XL +M@(@5#\!`)/)88#'LT$IT?\F8*%_&@1W^N&(PSJ$+<)M[`F@NVC91DB7)+;3' +MZ'K4Q=ZQWU8YRVC_VR;'EA@%8U]=#2G)W(2XE0`AU(\%/OC9H5"/;&7KXE\W +M?.8XVL<-,[,I\)HD=MS=Y2THV(3)!9-(E+.NU.DWMSN]L_/#NVH+?XJSH_0A +M@8%X-`4)9ZL`J_A78C'DF;G"VB"?P$O&ZQ=Q.0%'6P`N\GOZC0*)=4L'JVO; +M[-8=?M`X>;>X'ZO42T*L'SVG26!RP%RFHTXITO7+J8%U_U;6]2K#?8BB;JS; +MT:%^:II9#9NP`&"(M*-G;17!KI]F28/&7+TLGK"6?\4=@T/>TPH$5F(FPD"]OW-9JX@E$!`V0L1:-'V3Y% +M/-P1(CGA/<#AS@)>J+:>E?K,$S=\WS+#W^KIDQ>>YXE80`\NTRO%0%F?DL@O9.'[8HK&NW. +MJ-U"#/7M=^=+H1@.R48J4L&BPI,+7UJ/X%"W]K[%K2*`&5_9387H7!P'SL(O +M@+]D4VV'`$]+\!"'M.FT!@5XVZ(]!$$]4,/;Z90?;94YG%5D(0"PSRIDG(]_ +M!404$.3*!<^K"A^IN?(-?#M2F-U,5_W`(B9E+MTAY%-5CRLQ^(.H*0PW/1R=]4)?8MVX(N1 +MT0'<,8)MN9_Y3_&G!V,YHH$!<_:>=;HA^AYX`KLQ^097HXMTQC-ZPC>!P*W$ +M"G$]P0K%2R!NI6;K??%9@$A?&>7-:<-W1TB;V0]U=$6HT@5@V]EAI(F#:W=T:HH#2G44M_AZS.IHW4E +MQ]?O%PPW9S&1?%5F@JHU@AX5T8$A(L:RP]A41DR`@<;V++D!O'G21X],J*MM +M?8JF).WJU!H'X5:L\?JAF(=`^2:$DW6V=+84UTU>%5_\@:3KH\02U!LM^M3% +M:)_4/GM"^_=M?]=>!K^L\R_<^VU!FDS]Y*,PF>NB"IR@!NVP'3@A*7VA%VA0 +M/XX(;+U[82(4]!.:]?2\SA,3BYL]I5DO5*NB3(N$E=C;.A$O+9(-8HD\<)ZTJP!O#0\LV*%!3*)Z>\KUXQR +M5/VO#I"EAZ6[2^=M@3B4W[`"-+^69K#M*/UN)=P;*$PRK;8); +M*&-+!7WXR4ZW;\2?2X?0M?@77]Y9IGT#LIQ0SCI>G=3($J +M%#M3&-6[J"N'BA1/T*=AW1N\8IXP)ZZ>"CJ;$KZU3-FDZ\:ZZ4^7`\$#-38V!_53T>Y<#VN7TL4!-#1#OSMC +M9Z#15ND>K9:PI@(KN=/GBSH4%S`&]2+3_8^#E\$3OBQWH'MWU6T;\Q=EP@_# +MH>O6BB#6M^"MN3!^=RE]MRZ"VEWQ'$D>@++.[("^\LQ,T*SX`6?\!+7*`*7? +M)]B=1!^YI&86T*6-0.GM[.*7M(>QE[HO'8,%S)947!AAL$+3%*]9Q.>TZLE#68 +M2XK1;PK=54+\A4J[L'=#`@2$XV'.6)DCM7*!+-I=LEGZO'+O3"B5@&=#-MP? +MIXE5:9*Q%S$#0+3OYZ#:GU,#ZA'*H6H"9S#%8='*\L%2)=QG?AB+[Q\CFIQ^ +M&^GX_?+E=EIL_=UM"@F58*?A*`YO`X?O4<#+Z!R`Z#,HD_<@3.W:]T"4_$>3 +M@[.U&%JEV-%KZ(L<-X?*5AEO2#F&@"YXX!=T)Q+HO2*T*,[<[O9VLTVTKD9R +ML:4S"ER16"LL+0(MC&_*DSQ?MZ1.G)2LAFM";J;(RE1>!<$-=GR&6]JN;T/D +M:'#_JP004=/^\0WT`J8T?(V05T_<["1R9KGA1WP@YBF85J;6R"9R^0=;3T6/ +M0L/M7[8S7Y4/B%[:L_-`$'G(#9E<^DS_,HE14SH&;%`F!<8(%[%W$9],MG>' +M-%6S!I<*40F<$$*85-P6Q!9B]&"VU^R&K$LLQF_&\Q^H-?=05=-H&25;A<5@ +MFKGV5>BK_JOD]'8DYH1C&>8?S(X4,.AK7*(0B86_\`T'&'=D62W;(.=92\<^ +MQPNGQ<$QDL>PVLPJ0"Q!71D)]MM!JV?"!,GOMMI+]ZK=85$Z"4V<<8'RT<2, +MX%W@\GJRS/B4_W4XS-8N%.J#$,6LT2)V>X?I3H?*K*83&3J=-<@A7%N'6#QG +M[*XC&=@%O=^!AJZTE$>VCH5%B$,%,,YS!UB3K\:[__U_/?W_L^9=+$0[]%34 +M$%2A`I$X_W$51X*$Y]?)/CQX'%U'2W`E#Z&.'5)\N^35,U"1;LY%E*C6[(NX +MNI%F&E9B(R19Y]:6\_A/!(>;^%9]LF./CM)1G`TT"Y=]=(8/X5N.70L*B$*; +M.8/6-;0\5)V^)[P(ON +MAA0'%ZWQG,!H&+GT"UYVTWI#G'6J:H`LK]COP.Q-+1Q)9N8]8YYYD^I+K;^R +MU`7(;"V/W//3P5I:!AX'0>XL:H`*B*>:.^LA0W'"I5YI;T+Q6+1(%+[VJ+)9 +MN^7\BFZ^U"$2)%5*7BK9-VI2N06O@'1 +M\')`*S#DBK>)L],YQ!G$#2#?*#E+K]?(?@;JW1@]6N1XNW&USE=O`IRR$#%_S(^ +MLQ.?0ZVF@+88#8L>CE[7&[I;2\I2=%DR+MR$-:4QV#A94_)A&,+FQ=UN6_>P +M989E%2:S:SVHZ2#*#`+*,X*NAX>"NF4YS9;V$<#)'L\R_8;51*F1>3X`,L8S +MM]]V4(%%6D1WU\7>+)7*/+EOW@S!/D57QR9#R3M:&N6SJB!B.5%AY20`P\UP +M12;DPNX'ER`G4E,87<\@D(.0#:7.%-H+V'&"M[!JAM&<:4P,F[,3*)CK>5KUU^MZCY>>NH`H'[3A'K]=&Z6 +M!?G>SAB]^W8W0HK)%-\4LG?10`A,G0;XZ]1S'[-7(T^>16]B0LC!;`3D.DEN+^"6'X[=A2O5D5;IU-M,KP^N783S%ZE\C,*\X;@P5X:QV^;T1Y#)%* +MLC@7GEE.\,]*4<[3!;`7GH#8/E]72:C]TCTEL:;387`2P+CB-^H*J!1^[C@4 +M%!55-B[<$[F!I*EX]=<5W0W=NP9ICH*JN4V6O1ZA4Z=4H_&GR`PS1]7GE:AO +M]?39:FOK'Q%GNE)%^FH>-98O$#/U?2`B@GD.G&L4_7`B`41A..V_D!!G3_8^ +M>G^$CBM*_#@W@>@0\#W#5\X1\&C*R#&=EZ(HU`90ZB6^9I*4Z'FH_\,L_5*= +M!$IL#Q7A3S!IYO!P]T5%9EMB7DM:A_78]9YN_[]+RZFJ4V>J@0SA#[NP-D#1 +M:C"-(%KC&'R>WHUS>%I2?_`H,_NJQ.C'4QLJS'XVE\)HT#0_.?[$2%/[!=K2 +MHK47V@L3JAGSL0&6M_HO>!KX61&'6#G;RZ? +M!%%NBHU2-_V7X.*[9ZK;\N0N=9M\=$>EL7#]NHAD\7*FJKU.^E:()]6(2ZR! +M3PPIS`"1YC$SY8Z/])K`#883#9&Z8:`W63_'WC1\^#.6!H\='78>HD(7]:M% +M]K(`0J,F>L/0N2LE$+;>/(89ZDD\U6W+CA<+.S'I_G+-S,*@N,HYR3:4#@,@ +M`MG2V"[EA$K`^P:O`^(.:(.B'FK@-M[`S"I$9W/**,=?C>5;I/!L0OST&X.D +M(&ZI*&\4M8D5B3-S,33)*R>/*X4I<8!V0>6YW'57OY? +M@S$?1(MILODT@KL2K2^^_L(;43,(W==PA>",I\?COZUI5C^UB6&B,[(<^_$+ +MYKU8,9";R/_2@+9D#WQ=@^0G*EM'TC-58)&V8JBD=]VJUMURJQH2=RE]&2WB +MN^;BIA!)ROUGE4Q"T3`@"TK6XT8E,^W0'N<*(4;R +ME=TAXS8SQMYES6>SPIVB!EOVR0I36T/D1_]WL5W#5N<`=^C(QRWIE?N@3?TG +M_Y8__>U%Z?BL^N9Z;F\<Y53SON2&L61A<]!T_4?%:EC9&GU84U/1A-[?4#[-9J%Y +MPD30#+9`6#_G+]%`";]Y\D6(OWXAZ)]]K%`D[B*+H]V2=^]M&[:Y_^L?94I= +M=M2U@)%LT]N%GV]=\A3GBB-K>A2PTBJE%<,<4XPGA)C(/1+S1*(E3&P +MA@6$5)V",Q[0E6;-*E0=*A6T5U.KY^_C66Y'44^BP35>=31^5S>,T3;IH^"$4%^3OM/P796=[G_HXE!"5@1+V#?H6"# +M[49)5#Z-6K_XMB;K;,MGSN_&I4"VT%%A9#$J&FMN>8)_\(G6@-]ERD58.OQ" +M_PZ@>Y'+TPY0Y2T3%TMN/,V\.16J8&X"5;AMM)85SNS$6Q[_8+2A9^V[>0T4 +MZNHACJ&`])R!9R7BFS=:[OL:HPQ@V'KC?/.[0-)\/2GV<5=TTD@X$``!!`8` +M`0G`648`!PL!``(C`P$!!5T`@```(0,!`P$`#,#K:\#K:P`("@$6V^8W```% +M`1D)````````````$0T`9@!I`&P`90`Q````%`H!```M0RMQLYT!%08!`""` +$I($````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_delta4_lzma2.7z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_delta4_lzma2.7z.uu new file mode 100644 index 0000000..951da15 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_delta4_lzma2.7z.uu @@ -0,0 +1,407 @@ +begin 664 test_read_format_7zip_delta4_lzma2.7z +M-WJ\KR<<``1,P\W78$8```````!B`````````-6%26G@:^I&6%T`)QO*P@;2 +M+(;6`.G?97%G65J_4ERCV:^K1%6D4`M822)8PY*%14J=_<,7#6T/3RFH$9!9G6HOBE'E<0M'0-5!6&]I9Q(LNP>FO1,4C"0-HJF]E+UO?$`OP,0L]9]-?IRQ"#_8 +M4'^\-:$GT3JIHJE5;*\M)]-TIEK1=3?[2#(5!+N!_HL=H!H_R)BU+F9HX\D5 +M.\?T=(M`=9=W4SJW579?/KS>1Y+'M^%0#4C+X<'3U$3C&%='!5[\EF[@4#2B +M9^U]FY)?`J8B_0+7B.I$N.X)PP3;'V&J*6VY.!&;Q7R,;M8N$$GCE7A'DD(" +M6>XDN+^7'[7.>5XJAT[)1$"IP%"H\ENNG?(IVD$"4B#R#;E,KWX0"(+I)G\I +M;FDXUW0:G\77W)*"$2C1DY7G2A@X<7?HF<0(324$@RQ94+EXCPV;A\!J_=-I +MO`PB]JI0O;215>3NFC>&L@ +MA8ZVO8G:(Z+'4*>R53SX'U!L=#-R5/?1CX"K49RW+6#"?:O9#&F-VU+]XA>- +MH/+P67D.ZN0JL3&7/ST/0,:N;-K'@%MH5*U@'\5C)M\[!]I6*3,C]3NA^O +MCP?_.^L?=17`;X\L"SHC@$#^"05.3&=DUY$\848Q-SC.@/%KQ:P`5J3YZ^,Q +M\-/Y(6LQP?6TCO52!37-BUF`NWYVMM2?O%GP33Q3P%?#">B/A68F2MV1P'FKVPF +M);5);K1B>8HI`'2@,V/:[^SK\W]3Z;KMD.*+:9B<=!"$;J;;UE5* +MDM)][UB?]6V.JGB<\EVIL3WF^NX79\"D2_^:2*;[&U%K7_@JZDKEF1,3>-*< +M/L@/V:2=:I*Z6Q%6C)N$U>TY[(C`P/L=7ANK-S3-TT\L:SL +M.T*&Y0>E.GQ/D;-/0XPRM5SL()'1_^7U(H`O&?G,YY4X%=>F@:@Z-KF"#'$: +M)WGH[<$,.1GS0RT6+#EYTEZ8W(/*D52"P-B('Z;VJ('L\]V;[3YB+2 +M64VOM'M9/U7+D0$Z>XTTR0PP6 +M85OJ%/<&J2F(<2MA[/"%RY6$59Q4^<^.2E4`K*^\*=EF4`D<\@V"R2>@9+%N +MD3R*?DVCY?U5RIHO)]4_)8R<3XLHQ< +MU*%_PKX_M,LTP$2ITA\+->:ARO&7:7!:VK==FV^WJ;$;UM<&(,B#=E*6P*"V +M"T5QBA@I!4R$!8.UO\`TE@9K9&W_'H:$?K3:4(%MF):*_OVK^A>=63C@11U@ +MT1I"1Q?#6CJRJNUTIW9D'7P=!P341-$$(0GVW+S/D5NL-H62CQW"4(";.>F1 +M#VI1`SN^2//BUZ2!*N-S5?\L%+&&+]KQ%-VW#[C)/0LX@$90T;HK*16" +M?-10DTO0>).+H4UE!^5"8EZY\AI;S5W!&-W_GR_7YP*YD*]*(84G3+C"6?R[ +M@K<$M+8"'9V'M]T:$P]LZQ6A3#<)_X2D.=BY9BP7WN:17-HZ=K8E9V9>'#%. +MR$L/'`U2%RBA6\@>;DV"%M-2Z_VL]=$Z/^)=`$-)$CDP#?3I3M&Q"21C?*R@ +M#L:;1=**>6J6M\$JO&[IM%E1\K(KV#CK]1!0:?M>([H%FUMVGTU,`#D*,+%) +M&$FT""V`3=1]S*'&PDK^6@#Z,&X][V6I0Z^[B8*7P?4_5N'E9`)5*.4!K2G` +M=(U@/RV>"C?],9@_Q]#\G67)I_,)+$U?R>51LS+,1<0/C$RW$8A_)U)K0:!3 +MGQA004^(:U*X8T!*T_1#W1V4@6DMD&89Q$$,KQ\3 +MF%!524963-!]GJ5^KWZP[LWX!PPEUI'YM$#^I_KLT9X0#)6@K!PWB_NF@WT8/RU2Z8]AY4K"=0@6$,M"\?8/]ZFR2&1&`_!3U=IC.6Y0BN!TA +M.6C(>Y)EI%0?'CJGYHT2-)@CS.KV"@Y<=3%Z4N%FE7E--^Y651G3+2.IEL@B +MMU6O&1?8X45]0!(O%9X!M:1>K`YGV^_O%/GM_5>+640WA4F9R0420YS.DVJ\99T+VE?TO``CRDOS!&U(=)T6!7O'S!QZ!/&Z+KD=FN8U) +M\$M19IA^E8N&#-K%0\KB=RE(0WMKCWNFP/9(//7_,0.J@:`(8F,M63OAJPG& +M`F/$\U>\E?3``?\,Q!FODDU".=+F\0>6-QN([3HC%L$7E(5*FNR9B/R`O\&8 +M;<:8U"H-L?X;3TE6(>O0>/9T)7AX+(SZ6/D?FA(.D-JE)"38_Z9*0\%&R+`7 +MY%"/I@__WF;"!AYKPC`NQ$A]4AFT!ZXW6G-CK3HE&(*Y:LP^FG8;+QYXJBN" +M!P9@CWYCNX@XHZ>]I0YW[,6RH'.JY%\J&"UI8,UC!6+9BR$8ISK9U>KC)*JZ +MYH[[*XDY9`UXU/1_KC'"'5G'Y"&Q +MDW`4H^?00ZOI`F$V4_#7+OH<),CK;&JU[^F#;AL<5FW0%]&2.AG#K,3E8:ZI +MWK+P[/`-['JND8[[^DAI`"ZV>]]YO# +M83_2-Z63%G!2V?XI;66V?((CDM$I#793L`;V]-/[,8_!%6_S2H=/G`\M6QU;]^=M/BMU/?,EQBMJY>6@=21H3LPE5LF9XL/AB4+8E.WGE6X2T +M!O\'-(WMEO'%E0`NU;*PKPV$PR-M9Y%1`&/MC941*O9L=CM/9_A8#*38Y +M6[=4E-`I(M2?3[;8&3''0#RMMF'CW$_6L@E1\V%9^U]/F&G=&[-!=R-XO]=I +M0O55K3CBY:66KWS>^MJQ\9$VL_2VBB\1W1^A>=][1UMIL$].A,T,W?A5IA:W +M@/'.WAF:2*K;Y']X8D/,;&X,YW-(C:O>"*@5_EZP#J]'/X,'`OZU=@2/&;O@ +MZX(!^?H\7>I'OPXHV(.@N6 +M[6&;7[


    *G'YH*M+W>S84F&^UQP/>!^$/*J6#8P);S!S3ALHDN3_BL+3>: +M8#XL,V3.:69'F<4LN!:2(9RP#:V#A)'<`%`CMNJ[^WMKOCK^K.%J_T`@RA.` +MLPH:_W`3-#"&2!B6PZ&30#4F:E.)@1&KRIB,&JIR13OQY'R]Y(%?K\"/V +ML'(M&JII'VO>J3U#_:[LB-JQZ9>*2.D]2_@U1`>CDQ"L3M0W(D09XTJ$>+T) +M\6[8[0.PPWSWY$R7A.VC[]3SC&-%I$,#)0V$A_%KF."AMKSX/IG2T%BRNZHN +M$2`W]O[,:4=$*F=AM(#HRD(`[!&`Y3>]="+V`@C<5[5D6 +MJ?GMYQ<"DEL"N&A@L)PW_T=K7L6HBC3@-5W`S9W2DU9A5/'LQGM4*9TW[;#= +MLDKA[Q`H(XK*DP6REW[4U@-<@"%&K4^-I5Q]W>)[+33W#8X5-LY0(6)P"*H] +MIT$=PL2;V7]>=7S>WGG?H%DV>=ROMC->C]68@]YF;!!6 +MF53BEQ_L`0$I*5WKS*W7G>]2YHHA1A)D +MI11RZNU3(HXMRO2C5)*;!Z4_Z_S;E66MJ%"%X@KZ)>2,IA:E+O:9F4EHL +M#'D0U](#Z$1=A(5"RQPB"W:DCM$M957$TTX]?;_"W]'#,6[#T%:=BU%45@G>`(0W8H +MH;2WP.:>7X.^L`0,QC6'QB.4'<:H_;?[HH55KK+ZZ(K(;#4BU/6M]A-C0R[-7?A!\A$XV)ZV<;3>(#PWJ'G`A1H^M73&2TBW80SG"6\ +M;_OXLLVXYX"RW]>A3W+`BH'-7?H)$L"JS&0PLA@6NZ_KV+$G$NV'N&&+PN)M +M'G5`7X^SMS8K5ANE%#L&\;1RA3@"QV;B\,S=(VM7*6P.8;7>YK]SQZ5)/T5I +MW\X7J/F)NH5RK0RF!YFU;``:"/K48?)96)H:VL/W +MCSBK@FI:EG7O*9+W1\`4#U^CUUD)[A!W)[`::QDFW6+FWM>5AA5A[NZ/@G]K[-;E=Q/+VX04AU1D3SFJ35+AHSQ.:LL*B@; +M,;S@)LR>(C]7B^7VTH$RLX+1JGD;-V!+R,*5G%7QYY`>AG>9RA"1YQ +MOM]^O*Z#^.F?[5K(S6HC:U-CI\J@^=LXH<]U0=.?[:QWLN2_*H:.S/\_)XG% +MV<6-"3:+\(K_EQVPN-IU^YY=#6Q+')ZE(BAR.DE[]QV?,&/$]UVN:H$VV&H! +M3S]=(Y88^?CP.6IHOHQ&NT/)MOK%$E90.VO&>3\%W`0*6I@[$&"OKU1/Q,"7YI)EYL2 +MY461?+1&M2<\%E#K*'87RWDOF@X<;E4-LEBB$0?(CH5(ULI^S.D9:)O9D\52 +MXM*N7>?_&UEV@C3$3(!N;`>4-CU_ZCX?WFHBV"K[,!:08Q[@@`Z%).)!O>(H +M__Y12NQOV+%>&TZS;9\1Q@D3WF_'37E%S"6@N;K@^&PS;2PQY\,DRW>;X^MK +M/*[QW(:@-`IW$&7U>3@IG%W\HDOMTO*UU>->\P).[R-8?@JD?K.5T:8` +MV,N8_^@0C=YQ'VNPS%3#"4\BVSY5-VJ&*D6Q(C1_0B#@<7A?>/-_Y:F^S;O4 +MJ8-0->_CE`/I>\%4@M:.9?:,@/`*M6]4[_H#":*BPKM&-*.XBF\WHW,P,D71 +M^62[3?"90>H01 +MXC.;&/,&Y1^?\5W9A*]LMIDHV:MDE@%?@SG"L)XLS]6;!X8B-#.%83SI.T-!WH_OZ*]6.6"(DJ +MZB8:+4[#BI35;.F)C)J#^-Y1G_\/1-2Z%/^WML]Y`U`(!\%AO+R*+ROH'68P +M#W$]LNW4N$23ZM0$*FWW>5==F.;B1#(4J&&7G;4?$7KD[4_0Y-S;G`<%O5PS +M_M[2\-]A4-EF1&L$-Q)`*Y +MG38`;^"`Q$&?&V04*(>I(MSZJU>0BGD$KM,FR7P5Q[#/HCE9-_]AY)VF?;R%-I!%14OB]F^RU, +M^&Q-2>*XPN!&O""WQ +MHB?EB7MV"*:BJ"UO6@U5(I]FX^]WAR+(*+TWZY(07;Z4;JMJ/35+;LRL*`0; +M'E87GUX1XXBG5K!JQN^86V)%,-@BZR([\L(;]/"@FT*\#TS]UJ9&="`[]&@CSZ!CU9]Y8>(V&PI +MMKA*-%[A.67]I'72](-.H6+$I]S=NVIW&?Y9CMBGC'^U.[=+F9W5IW?X:BY$ +MQ&7VE5VM."JPM-ZU!X?$YEQ#SCP3=H.3WDSV'JL[*^ZBU)2:QC=4$)*LG\18 +MN&6#B&.)SF`5A9(^F60I>/Y7)YC:\(HQWGPH1@I?8*&>QP5[T*!'9^EMJ`[I +M9^%_[>G8.$Y1V9$HT_(QKYGJ(Q=,;J0:<]2/0.4D[5M#XB\("W)S?WHS&%5W +M\Q0*)24BW47>9%4PG-92JL+CJHF("1+\P\??,G2>F"LZR360WKT.5XQD +MK@/Q@U0-MH2GF"N[F,E`U%L/3>U.^+SOM)/[Y!#H8(WNN56 +M"1M)7)+9ZX^`QY$)VYV&C4A@5$MV6)N5QO5N[,XFLTN5(_Z/W.V2 +M(MCY_4U9IU'0<=YJOE&61^+4(+]"K%=,748Y;3;C(SRFD*LA,`Y\6%4DL!^' +MFUY8A-L1'A)`Z#TQ@VO28XW:]>[$--59(S74PX(BG7CH3N:@MK<*!Y5*.77( +MA@:>[^FTV$+8V(Z[4+?PC-,N^K%$@->=:5KJ:(4\,*H6:W#Q87-,* +MCL\45D1IZ-BH)<:H'4=BMW(;TV+LNXVB`&U-JGZ)9"1_1 +MZC#T-+E@,QT][:&5UOYS^Q__\X[ +M:=U5C&&:YL?V6CRK"/?%X=\K&]FRL\WD*$I@M8W=LTVS@EHN"BH,`&/65-=R +M2M6F,'&H&C=6_(_'8,6H5_55K>K#]2Q$82F7NP1[ULZOQH/Y$K[I-5A!=P?E +M1?;("/:_=K^,`P316_*N15(@$('MM6YT^>[-&<\01RX!A_]AW?NVY%T;Q:,O +M8&"A&$\0)C`VM8:WDF"6>H8JHDE&JL1!D]Y:50%*>`?_Y759$N'X8%38HE4P +M:<'N_DL.:E<2\AHV_WNS-O?Z=IZ].=Q$&Y4H.UK^.08H_V6/@LPF2'G2XMK# +MU]$I7NE[2-ALYI2\T$TRJKUG1(BOH/"JEWN\O4AF3O)O0&J#796>G&/`5Z$/ +M%]8Z(0.'S6T2$U5H=9/6>/9UR>'3NX\7\T:9F>I`2[!9>1:[PU"U(]\9DL8I +M[,YI]IMAN,8K3-\IIPCNL;*93)O"Z+*>_K%9]KYKY1O*,IF0@#V6E_:]3 +M+1`>0IHIAVI!\T@MGNU7BK43RFW^X>!9-'$VON:PR,#VU]^!"O6 +MV)V%*\OX80:!WXNCD!!SGY!E[,C)SK::L-;*TB7S'WNS62B1&)[PC>U.Z;EA +M"H16D<#Z1"C/>M8$_ZR*#;#\>*DO))@"]4Q;K?[W>?2\#B)9&YH&&1#*4)FX +MIV_7-.FV-EF]2(:P=SUY3G]8)6KO"J'#(.7L'W"^#SYQN!I`DCF4>4-!'`C/ +M*/`%23(Y3O=L^=4*9VE-#4"46RX(!\_7L8'%,;'G".''P\#FK=7C#D>*[,3I +M?%LS=8H6D>]BOWEC@)*B=YI)M;#!]<(!6"SM(`HS*7 +M>1R(,]:SIXBX8:"N7'.PR2<.)P=%[(/N6R(C:!=!& +MD.O4LCN[$0U4^%:/8&>*MF/8G>+`]+D0%1W=LR&O#\BPED>!L%)0@)9C][;4 +M@>XSM\9.:)@-;`P;C2R[(9V``#!;2B#!((RQ_=Z6A8FC13AC)KPFS,2C#KC@ +M0,,!=4?RNT"$]8]=HQTZL(EN1[58BJV!V[57>%W%7X>JOLBE`M$2#H$]D*^X +MG5$W&.Z",UMY\(ZZ?PZ2Q8I97T1HY31%^T?DEJD<3B#IQ[R'N(RF;7Y5 +M?FA:X>SN(7R,Y(H;,A)1F"=-US`;XC%_I3B;D?T7FD;8![YAU#I-;%CXW7JK +M^PX\LV7FA2=25.UV$OSP6%60;NVVTJ4.A +M4_NXC%ZG@OV7P!"@KL+@[/0U@YU0RLHH(\`D2/S8NE73/1759@?VG-[ +M#^5K)-V(KC6BB"B-J9LJ?F(BIO&UP^-/FN6/E+:U3+;`=]/`ZK5#%!T+@O#U +MKQQ$3>V`#?N3<3,8.])L;@N:L%8V%G.KOPN7][!"[<'*KR+>`%0ZO_69&2QU.UUBS4>G2\R`)1#0[B9[] +MO"E4N)/X/RH)DT><1X-KU`4F93].H>N,X2VLZ]+;::6/Q72]V6FY42.I'7X@ +M@09-A],I3!,:C#/^]1Z>LS"7-]A3=Z.>]>)V>F1T\KH9=\5.07;*4JCJA"%Z +M`\C>PA3VS>5?9UUE[S7/+R7B>K_&UGZ!Y7%0@A(T?$I=:6GZDM:)'2;2-S9/ +MLO8OQ31K(M^>-'.XA.G'!TF$BW7LCL,IF@6.0JR#Y.\(P;V!X74=#QH1T0%T +M%C&SCI$*^'_2-=-9JNC"#ZJ",4\]LE*,%0[5'OKA9P +M\,%&QZ%FX`35=#VBJ>BXGVQA2XH#.SYX`),GM0SI9](2TZX1LH!+S*$BXB() +M*)C5L;LDEB6YHX1"HN4=2%H*$Y:LNC^=5-M>#$I5YA)@WM].QN[0];"PJ&F# +M?,.BVJRM27FN=O8,P?\`P=*M!EM!DGG[H_UZ8<,B>%`A%P!,O[/%@[8_5"DY +MRX51)=.`\PHFMJ90"*@XI.^8F,9'T%FYMW\E%H5.4L`XRO\.=X.+42F7Z?%= +MUH.#\WWGJ#_"]0F<4,V6G#T<7-ZA*MP+`CZ:N`KRI$N5NP1N%\2=SNAY40I2 +M%KO\6QHGQF4KH'C;5@VCGO(394SKUP$USQF?(B`3ZU:FP9BR)&K,K +MC1`$X./>F-TOJ2C,?Y!9K!B:J`Z''=?RG,I%\TB)I;KUTT-A66=SHB=B`D57 +ML*\B9X:Y]7CA-Z&[`7"=9Y`<"1V08NK?,;CS*5A#>0SOT29]?W+:$2WP(IR` +M6#;7(U"U5?H&ZQM#?;Q$RJ0!JKC2I#K3/(!P6;2EU!O,1:,2B%@4-;YL>TXPH0)@I7 +M`P+BM<:ZD'A$\_+O7XXGNHD20)0N--U#>LA+8IBW&@FWGG%SU[A%"$$L2560 +MDF&G&SS-9'V/_$0KPRN_X[QMJ^@2SK,YT4RYG,Y[19OVYO,1[RM8HV4X+<>8 +MGD%0#9>.\[9%/ZMK<@#&:I79^69,&>(IMYR7E>\;$&:&@S;'?%=7X3)7J$BT +M>)0U_TYQ9ZE9!;>)S@$)V(2M7+YD#U6:R9XKNH58$`Y0[?!,!E_%;P$@9M[J4!2V;?7J9KR@DK_5&0 +MZ4D%.>R%Z):(=I#:@8@P47-WUYI]GC3)=ZHM-RGW3DV4RF-N:;/ZC;F,`%XF +M:J3$DR^-UO.%(6\"F@9D]+N>"M+.`UP +MM7OEQ]FL=+*8#`?/-V6:^@Y%SEG(<..;Y;(H^$H,G%&\,DFEB?*"!6]@VYG! +MGOOC!NCP3GP'Y[:+1P$N#*F?6(UV)A?.XYS62=)&BQR:)TO^'6L6:O?TNGOH +MF>AE>VW3Q+^7)L[9\V>8!"AT@0/(5?/]9""`>7U]FA +MMD(3>IHQFM)CGJ,V"3X.3!Y`BWH9:/`L%%IV03`3"CB*>Q[@>,M.GO%(M,16 +MIR[4N-H70_F1S`[>>ZR>0L8I04 +M1N/:1`ON)P)JZ15?2%&?).C&0JD<30`?_:NO=WD!HX_O;?[SFKQE1X-)C%\Z\("^.SP??@UG)[9(>E$''Z.VX4CG=W5`"XDM.(ZO43K*UNWT/9:2?8AT +M(),]T]8S(D-VQM8A9O)O0Z%6U-FQA`CSH)+QSN1O#H]&B%7JS5]TDHP%/><[ +M;6BV#FVW&`*ZQGAFSV!#"#H/B=8Q&%J\"SR8@&8R;`P1+6\A(\8QC/%$/.?1ITG +M^19+V--77A8J0;PBPT,)1REB/^984W3T;E'-EF6/QO\N<>WJ-M6\MK//H)=_ +M_J-E`'17:M=Y]>J5K`:?=";=62H6^%BEO%*IF.JF`/4N_R7<1IW&[@#EJYZ" +M_S\W<^%BDRHSI!"+1=?<+J0,I-+A,Q?:K.?FGHOT-M#2;F\(-L_L:"48C+`" +MW#!ZU&0J^B)6X;P)5=7&#^E5`-:Y>[.UFGM#3X+KP1-W>^F,Q:;@T:YOV?Y] +MJ4CIVM2LO(/=LOCHY@R&HP3IP9LR))TK:`OW/A=H4-HSPI."(I`[)R&CI6[4 +M)!1J3"3FL;%]WD8X8O^[L1T$1#(2V;+(X&L$\F\8:>>KQ8:IB#.F).O(1L3J +MB^MW&%F`99/EXP1-^>*@"NT3'^,,:C>*E=#?-$'-P+W*?DFGG+RV(V7Y1DD%^ +M13&2K\[(W6&D;*IGQGN@/@75IQI3B\.R$[WG%`][8JZONR"G!MD>;DO`M#S7 +M.#F+2*EP\)D<(Z)5E6_\NXRI#.8F +MPSMY[SR1_Q!M@A"1["=3C!MC$\I=D&4_,LZ6.VB#9(R-0:RC7N#H)8`X;.R( +MOOI>%0(-A^G"&8WSYE=:$LH&KI0R8\A\(245F%S>,>*@!\DIFN2D8>UUFRG, +MDY/3B"QY%R^8%]#BE*SP\LA-J#*BHOP^KL!#4'S@7K:BXOM6>]K(\:Q-Y#9M +M&:0''!W12).:.8;W=B;:*A7[8UE/I^#OS#!+K-%75./$>*Z/-R$5FY_2"9%Q +M%+IGF-,8.*!/U+B49C6!7B9CFH3^#$0IUM\_EL[I;^:[K^$7E\.0B/0U::D" +M<)>I!H=4T#D:R$E]*;2(U2?8>I2IO<-9=&##O32K$-T=0#`6I@L3"W*;&YZ2 +M1.V`TE."&42I%D-,[&UY!L>A:]Z)MW,9(#X)6@3*40H\EU5C!:"1]KT_2Q+9 +MW9)HD):2==I=*F'KQUX_VQB00Z2)COJ$;..3>7=7="`"^CY+(%/>)=4@"<1L +M;*;0`D_2[PS93J2SI=MS)=:M=P`7" +M*CE@##"6JZ&B:%LTQI65O^3"$0@KN6.+'+98S#SRV?B;N/Z3833[SOG(O]W? +M(!3SSB'CU7R"-#6+C'Z^/>6D/4Z"<\%G;E:.+1#F/4R.=BU3_1&FE**#EX6' +MJ4E?-)\-"O*X52TK19<%1A'L$4O:<"H"D;RD[`>S3ARV(4)/F%J;!\I$,R!+>M8+'/K3SSZD/"3Y(01+;E1L,G1YU-?,T^"4:!!^$PKA7 +MT[ENIM$P]888.#/ZFXZ9Q8&&BNJ]O68EJ^6D12?)S1HDFSH:C$\'LW"DB%7Q +MB;=I$X'F,#-2AV!Y:FS]=QDPR51@_7=7,H,P_X6AR#'*VQC$3@?/;KZ@$RT% +M+>)?!"1K5XH^VQ&9SQ +ME^1NL[GQWX4^.,=&6A()!6RP1%Q+U"K)'U8C:BC`Q1"_NKW_Y#R@='88JUY7 +M_"F##Z&594Q?2'(A"$PQ%%\;_\2:3:ZFA6%?8PY97Y9N;2`+BG@0;>B[[`;7 +MMH$T7XB_>M]K821YHVV6#)5`2CQW.EK4:LPGE.!4J:W#X13RQOA7"NY$)-%M +M]\R'VH1<3GYYF"S2`%941%][8L@\,,VZT\+0#:?FNF'-ZV*->]#M3PN2>M'7 +MZA!2V*`&`J@;^%INM4.S]N+M@TXT9[]P6]Y!3-4\VC^MM)E]GMP)'D+1&R\F +MAS'C2S,P3/SNG2`;)J9(`HJ&#XJ^(T81,J2[H4Y"!($_@$X4!+E0`(:7F_'= +MA4Z5YLF(3L%Q.UKWM%E$$YD<=JZVX2:3`6F2@M(O"&T_"/!5&'-E3=++;:#0 +MD1=?U*_Q?]5%7@%IJ3R=)`0TDKU"D=SG"[K1'M5R/710FDWP[',9W$JLL)-, +M?LK4;\Y2B/&2"XF?9MK[48':8.M^0Y/H-Q(H>00X.;">\'%$"@;DL.)[:*R5]V +M!W*N4")7**KA;-."B]"3`R4)5TMDL$Z=BUGN^'/UJ.,&N-T:(E$'X"HFS'.( +MF7U%N@]2RP4&YHX`8\^M)$$[#?U,&WK68/#!.[]+Y`+;Q@DXORL?,"^]*I;[ +MI]YDMX&Z2%/6I]O,]R>\&JA^Y%Z@WFL]TMS/VX]*VJQ)FQ>(N&'@$WW7VHC5 +M/ZK,QL3A`D[`7@WAN34HL2U:U?I[&O$1^,(-]$6(!E56K&>](Y%IYD:-'L!: +M.^A][3AYBX+Y;0A`W-)")Z^PM!W4(3&M\1K!42/KVXK?&`_#>$(+)N";"DQ; +MS9A\0%+N4LP93U4+7)B];I)0,SR"9^BU"H9H!%F='-GP(=5>U:7@D>ITZG&0 +MSPI9"@:$(;D.M$PIWS]._CP#+!L<&!@K/&QW\>'&\DAZ14_EV"FT0RL9U!;G +M`.&G$5'Q*H<;>XEOE+M?```ZPK@`B.JJ]H]EB+!K>0-;.2-,>[(V1T0-'NIXE'OD%]TZ+>2:"TE?K1 +M#Y:&=@0@0<8"CL@H)5G*2_8GG&B6UN[&]?B)]O_D>2%)UIU_';T.!GV+=4(N +MH1YJ"5.RK6VT]E)]M%&H*,9-H1^S&J)ZD?P@P_=:/BF7`2V0BZ^GV?O#8^F5 +M8L:)OPXST#X'.''TMY!JTO-(C6YUWA68@2VX6@+U +MQB[3#QIZGZO?T9/<_!I,F[MV(=L+3R-@,63-I,1XX>?[N9!BR0=O-Z@&0TW& +MB7[VM'QHU"10U;L^^;0'X!N*BLI[ +M`%X^/X;D![C/25?/J8J1$PW6D[UJ[C0LV6<(QV*(L-LPG/!,_^\C1J7YYOE_ +MO'>9,LI!!@YK6$%OD\O,>HRNU=KFN(7#2U8WTF_PS^*%C+O>-*NN0P0$'%>Q +MQHA]Q;)BF*J!C4?H,CAB><5PO"E>@FT0@+VEJY?F.^GD8P28:?QJ`8*GZQ.I +M9P"V"APO/_7RBZ\VNE=ZW.@J4;21,]B$=33[D21X`-]08D;V+'[I4K<.0QLX +M,D@"9<(-^Z#1#-&\.)4[6DX]^@=-;'NT`1.^N@N*LGW&9E>DYBAX4N4\6\T_ +MT'ITL6^=83<]PJP560@+SXZ\S++[:V@R[C9G;K"E.R5BUC@BX#X$1,R5]L'* +MHLO2+(:+8:=@06<]YQA"U&>&7%ML#I?*Y3(SO$1!B`3_+P!X\9GO4B$M"(S= +M;F;_UU9T*`FOU>O)\/_$4"M@C1K7K^)_4CBMCK0M3B +M].-[>G0)ZZVJ/=4.8Z>?(248O?);T8WJAMTCN0[%PTWU[.-CUO'5>4$T75'Q +M)O5".',AGT!WALW&R8DV>TY,J6^NQ?*=BLL^?G,#U3'U;#1NN,RZ7'HC@#5? +M(D:X!;Y`\&6!WI[+ODO46HR("Z.4'3LK^KO&$ZFS,WE?,DYJ>#DK4';BH'!] +MD&?X]\YCL>[%;DF;E$"#%"@M8LQ#H2]K.E2K^Z"ZG8YC$\IN88<0E>>;``"Z +MH1*XN8)DX*'L[KI)>'W6L__0P*T(I_4693<;@A%\-#A6\H*XGJ#/2T46JOAK +M+^YGH`;FI=\"5S0"FO5T"UX#J-Y#.SW'\YOS/@H6I('!`YJXDZT&`K$"A7USET[I3/ +M+RU#9]ZL6,(TT&9!TY,]1FG=_^:X987GD_2DY[[GWK19QP.39)F7:#P9`&=( +M.K5Y`CC"DWW/9"P%48&0'VD8$%HTHNVG.Q%O]/.<^_)P0J\C(.IAY/;-!]6( +M=#/O'C2\IBR:31K8@[[QY<;Q\1=A5[QSR"8B2-A/F1)3G$?91>KY_[94@'N3 +M3WWK%.M$PR-G$YCMD;W7S[?]<2V4^=NS!V0SG8%&!T-^5&QL]BLV49Q+21RT +M7-<@&M;&;B^Y$&YDVO301F&2C2_?`7=#ZFGY'TDZO;AF9_\9)65?9]V#>`NK +M:&'^?!"I\/W08`7$K?_^S=FA3-2_H.^K1.%[X%VBHIMRS924QBI5M29].U@D +M[CR>\LY9FCH"/RB?/8KRL7>1K?D;!CK2JFRV+?#2"/_X5W]-J('=:Y=YXT>)V*&&^\]E$Z*?W"N+H1_S+2) +M"H3&@;4/*](.UZR,;LITE-#=%EIO@6%T%VR9)*LCQV=&T_7S%_;%%L_JSSM4 +MYW'=$C^'(]#AS$97_A3&IZ"$+':9E%^'7]1?^:'!@U7[Z5$IXAPZFLR^ZC+= +M0H+(Z&M[4WH0O\;*[V%&.:C-W.1Q;].Z>PWGQM/Y!=`?/+!#[B]:3839+81= +M@GM//`3BP$']S^^2NH^K"Q[AZT"AK36LR\;WP +MW."@%Y_FT3>FH?8UMQCKAO]LV%%IK2:_C@.;@6"LT_IV2K!2EYX(!K]6027B +M#J#P4C+;[;>%TLKN3']+5?HCUK'Z5Q4DO!61L0H>D4'1^9&M'Q?E"MSHE/-4 +M,=8MJ/$2(C&0OV6H`*50KKOLVM-XB_5>-]==):(Z'$ZF3%COR%=S,7Z7/&9K +M=3/7>R`(#I$$ZF_YC]W%\%J#$%R"/`5#0-V_6S-^C5EV9*;%L)G::QU\GY]D +M(H@5AC3Y4R*.IX/!N"R99ZFT?@3$7D@>P]]=,\#"WTH$EB,Y[H0_0\Z_H<7[ +MQ/<%($H8\RZ3@,Q[!SKSV4]QXCB*3GIZR;M>OZT,YGZ$@?QT<;CSYT4*!!)F +M9F3-^\!Z(EFOXEYT&%J8U<%T"HNK'$9AQ=D)Q90RC4!OJ]-1.Q0EGQ1QY<,Q +MX\A;J2XL@(@5#\!`)/)88#'LT$IT?\F8*%_&@1W^N&(PSJ$+<)M[`F@NVC91 +MDB7)+;3'Z'K4Q=ZQWU8YRVC_VR;'EA@%8U]=#2G)W(2XE0`AU(\%/OC9H5"/ +M;&7KXE\W?.8XVL<-,[,I\)HD=MS=Y2THV(3)!9-(E+.NU.DWMSN]L_/#NVH+ +M?XJSH_0A@8%X-`4)9ZL`J_A78C'DF;G"VB"?P$O&ZQ=Q.0%'6P`N\GOZC0*) +M=4L'JVO;[-8=?M`X>;>X'ZO42T*L'SVG26!RP%RFHTXITO7+J8%U_U;6]2K# +M?8BB;JS;T:%^:II9#9NP`&"(M*-G;17!KI]F28/&7+TLGK"6?\4=@T/>TPH$5F(FPD"]OW-9JX@E$!`V0L +M1:-'V3Y%/-P1(CGA/<#AS@)>J+:>E?K,$S=\WS+#W^KIDQ>>YXE80`\NTRO%0%F?DL@O9.' +M[8HK&NW.J-U"#/7M=^=+H1@.R48J4L&BPI,+7UJ/X%"W]K[%K2*`&5_9387H +M7!P'SL(O@+]D4VV'`$]+\!"'M.FT!@5XVZ(]!$$]4,/;Z90?;94YG%5D(0"P +MSRIDG(]_!404$.3*!<^K"A^IN?(-?#M2F-U,5_W`(B9E+MTAY%-5CRLQ^(.H*0PW/1R=]4) +M?8MVX(N1T0'<,8)MN9_Y3_&G!V,YHH$!<_:>=;HA^AYX`KLQ^097HXMTQC-Z +MPC>!P*W$"G$]P0K%2R!NI6;K??%9@$A?&>7-:<-W1TB;V0]U=$6HT@5@V +M]EAI(F#:W=T:HH#2G44M_A +MZS.IHW4EQ]?O%PPW9S&1?%5F@JHU@AX5T8$A(L:RP]A41DR`@<;V++D!O'G2 +M1X],J*MM?8JF).WJU!H'X5:L\?JAF(=`^2:$DW6V=+84UTU>%5_\@:3KH\02 +MU!LM^M3%:)_4/GM"^_=M?]=>!K^L\R_<^VU!FDS]Y*,PF>NB"IR@!NVP'3@A +M*7VA%VA0/XX(;+U[82(4]!.:]?2\SA,3BYL]I5DO5*NB3(N$E=C;.A$O+9(-8HD\<)ZTJP!O#0\LV*%!3*) +MZ>\KUXQR5/VO#I"EAZ6[2^=M@3B4W[`"-+^69K#M*/UN)=P;* +M$PRK;8);*&-+!7WXR4ZW;\2?2X?0M?@77]Y9IGT#LIQ0SC +MI>G=3($J%#M3&-6[J"N'BA1/T*=AW1N\8IXP)ZZ>"CJ;$KZU3-FDZ\:ZZ4^7`\$#-38V!_53T>Y<#VN7TL4! +M-#1#OSMC9Z#15ND>K9:PI@(KN=/GBSH4%S`&]2+3_8^#E\$3OBQWH'MWU6T; +M\Q=EP@_#H>O6BB#6M^"MN3!^=RE]MRZ"VEWQ'$D>@++.[("^\LQ,T*SX`6?\ +M!+7*`*7?)]B=1!^YI&86T*6-0.GM[.*7M(>QE[HO'8,%S)947!AAL$+3%*]9 +MQ.>TZLE#682XK1;PK=54+\A4J[L'=#`@2$XV'.6)DCM7*!+-I=LEGZO'+O3"B5 +M@&=#-MP?IXE5:9*Q%S$#0+3OYZ#:GU,#ZA'*H6H"9S#%8='*\L%2)=QG?AB+ +M[Q\CFIQ^&^GX_?+E=EIL_=UM"@F58*?A*`YO`X?O4<#+Z!R`Z#,HD_<@3.W: +M]T"4_$>3@[.U&%JEV-%KZ(L<-X?*5AEO2#F&@"YXX!=T)Q+HO2*T*,[<[O9V +MLTVTKD9RL:4S"ER16"LL+0(MC&_*DSQ?MZ1.G)2LAFM";J;(RE1>!<$-=GR& +M6]JN;T/D:'#_JP004=/^\0WT`J8T?(V05T_<["1R9KGA1WP@YBF85J;6R"9R +M^0=;3T6/0L/M7[8S7Y4/B%[:L_-`$'G(#9E<^DS_,HE14SH&;%`F!<8(%[%W +M$9],MG>'-%6S!I<*40F<$$*85-P6Q!9B]&"VU^R&K$LLQF_&\Q^H-?=05=-H +M&25;A<5@FKGV5>BK_JOD]'8DYH1C&>8?S(X4,.AK7*(0B86_\`T'&'=D62W; +M(.=92\<^QPNGQ<$QDL>PVLPJ0"Q!71D)]MM!JV?"!,GOMMI+]ZK=85$Z"4V< +M<8'RT<2,X%W@\GJRS/B4_W4XS-8N%.J#$,6LT2)V>X?I3H?*K*83&3J=-<@A +M7%N'6#QG[*XC&=@%O=^!AJZTE$>VCH5%B$,%,,YS!UB3K\:[__U_/?W_L^9= +M+$0[]%34$%2A`I$X_W$51X*$Y]?)/CQX'%U'2W`E#Z&.'5)\N^35,U"1;LY% +ME*C6[(NXNI%F&E9B(R19Y]:6\_A/!(>;^%9]LF./CM)1G`TT"Y=]=(8/X5N. +M70L*B$*;.8/6-;0\5) +MV^)[P(ONAA0'%ZWQG,!H&+GT"UYVTWI#G'6J:H`LK]COP.Q-+1Q)9N8]8YYY +MD^I+K;^RU`7(;"V/W//3P5I:!AX'0>XL:H`*B*>:.^LA0W'"I5YI;T+Q6+1( +M%+[VJ+)9N^7\BFZ^U"$2)%5*7BK9-VI +M2N06O@'1\')`*S#DBK>)L],YQ!G$#2#?*#E+K]?(?@;JW1@]6N1XNW&USE=O +M`IR +MR$#%_S(^LQ.?0ZVF@+88#8L>CE[7&[I;2\I2=%DR+MR$-:4QV#A94_)A&,+F +MQ=UN6_>P989E%2:S:SVHZ2#*#`+*,X*NAX>"NF4YS9;V$<#)'L\R_8;51*F1 +M>3X`,L8SM]]V4(%%6D1WU\7>+)7*/+EOW@S!/D57QR9#R3M:&N6SJB!B.5%A +MY20`P\UP12;DPNX'ER`G4E,87<\@D(.0#:7.%-H+V'&"M[!JAM&<:4P,F[,3*)CK>5KUU^MZCY>>NH`H'[3 +MA'K]=&Z6!?G>SAB]^W8W0HK)%-\4LG?10`A,G0;XZ]1S'[-7(T^>16]B0LC! +M;`3D.D +ME;'FEC90`JK::$Y[8`U(2T6H@BUF`)8-PPZ`/`4+NB +M,Q5;.$^QD+O=>N+^"6'X[=A2O5D5;IU-M,KP^N783S%ZE\C,*\X;@P5X:QV^ +M;T1Y#)%*LC@7GEE.\,]*4<[3!;`7GH#8/E]72:C]TCTEL:;387`2P+CB-^H* +MJ!1^[C@4%!55-B[<$[F!I*EX]=<5W0W=NP9ICH*JN4V6O1ZA4Z=4H_&GR`PS +M1]7GE:AO]?39:FOK'Q%GNE)%^FH>-98O$#/U?2`B@GD.G&L4_7`B`41A..V_ +MD!!G3_8^>G^$CBM*_#@W@>@0\#W#5\X1\&C*R#&=EZ(HU`90ZB6^9I*4Z'FH +M_\,L_5*=!$IL#Q7A3S!IYO!P]T5%9EMB7DM:A_78]9YN_[]+RZFJ4V>J@0SA +M#[NP-D#1:C"-(%KC&'R>WHUS>%I2?_`H,_NJQ.C'4QLJS'XVE\)HT#0_.?[$ +M2%/[!=K2HK47V@L3JAGSL0&6M_HO>!KX61&'6#G;RZ?!%%NBHU2-_V7X.*[9ZK;\N0N=9M\=$>EL7#]NHAD\7*FJKU.^E:( +M)]6(2ZR!3PPIS`"1YC$SY8Z/])K`#883#9&Z8:`W63_'WC1\^#.6!H\='78> +MHD(7]:M%]K(`0J,F>L/0N2LE$+;>/(89ZDD\U6W+CA<+.S'I_G+-S,*@N,HY +MR3:4#@,@`MG2V"[EA$K`^P:O`^(.:(.B'FK@-M[`S"I$9W/**,=?C>5;I/!L +M0OST&X.D(&ZI*&\4M8D5B3-S,33)*R>/*X4I<8!V0>6YW'57OY?@S$?1(MILODT@KL2K2^^_L(;43,(W==PA>",I\?COZUI5C^UB6&B +M,[(<^_$+YKU8,9";R/_2@+9D#WQ=@^0G*EM'TC-58)&V8JBD=]VJUMURJQH2 +M=RE]&2WBN^;BIA!)ROUGE4Q"T3`@"TK6XT8E,^W0 +M'N<*(4;RE=TAXS8SQMYES6>SPIVB!EOVR0I36T/D1_]WL5W#5N<`=^C(QRWI +ME?N@3?TG_Y8__>U%Z?BL^N9Z;F\<Y53SON2&L61A<]!T_4?%:EC9&GU84U/1A-[? +M4#[-9J%YPD30#+9`6#_G+]%`";]Y\D6(OWXAZ)]]K%`D[B*+H]V2=^]M&[:Y +M_^L?94I==M2U@)%LT]N%GV]=\A3GBB-K>A2PTBJE%<,<4XPGA)C(/1+ +MS1*(E3&PA@6$5)V",Q[0E6;-*E0=*A6T5U.KY^_C66Y'44^BP35>=31^5S>,T3;IH^"$4%^3OM/P796=[G_HXE!"5@1 +M+V#?H6"#[49)5#Z-6K_XMB;K;,MGSN_&I4"VT%%A9#$J&FMN>8)_\(G6@-]E +MRD58.OQ"_PZ@>Y'+TPY0Y2T3%TMN/,V\.16J8&X"5;AMM)85SNS$6Q[_8+2A +M9^V[>0T4ZNHACJ&`])R!9R7BFS=:[OL:HPQ@V'KC?/.[0-)\/2GV<5=TTD@X +M$````00&``$)P&!&``<+`0`"(2$!!B$#`0,!``S`ZVO`ZVL`"`H!%MOF-P`` +M!0$9#P```````````````````!$-`&8`:0!L`&4`,0```!0*`0``+4,K<;.= ++`14&`0`@@*2!```` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_delta_lzma1.7z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_delta_lzma1.7z.uu new file mode 100644 index 0000000..d1e40f6 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_delta_lzma1.7z.uu @@ -0,0 +1,280 @@ +begin 644 test_read_format_7zip_delta_lzma1.7z +M-WJ\KR<<``/D94YN,C````````!6`````````$-]]%D`)P@\ZLN'Y_OA"<$. +M>]Z/8&Q;PX#$!$?ZQ?PR&S?06__\,PN2SWN6PB<',Z:`2?+W5NIZQP1?:,X- +M*G`\OL';&5F`W80F)['CE68*4/!?&M>Q_R#$Q;@`Q@F5(I[U[F/8COQ0BL\Z +MA6GS"(1>NNT7UW[=_>9;7AG*PCEPPQEG^3!\L_BGG$>(P!]1=3USVU32.):[0H>JF(9*O[N7&AHVJBS +M+_&-5L$(`LTXLA>O"]0KI-^&2EL>6`T68&4T4AV?J'CYW/4JT7.9.]2-G]B` +M'$Z\$3P'1!].A&N'IZW.+$-/U@QTY0DOB0"/L0"BO_7;OC9A1#M3DKY_.!]1 +M@3UR451\>I/;:`.VS3SJ_MO_/E3`@#\&]@Y4][!$,U$05+X.O4U<%Z5*<`_P +M\X1L?(("JO0$4+7GCN/AC5<9]03!N8NSHL=P`_H>=M-A>$-:*G]-VZ>[H'XZ +M*?@%RJ8@E?SWB^`3Q3W[5__+&^[9`2E.A0WT,QG2>)P$BOJT=@0*>."DT!.: +MNO#(K.M&!)"@[;<'(._$-_+HDP67X)2/Z@UMT`^&8/(YGP%A%XL'FS85[J*&VTE7SDZ+@]K<#2Q]BR^!: +M$0&$?Z71(7DJ,*];&?AJ,8>3!`!J'4O*I=CQA:$X1-_@(=NAG>4N`#LXE:52 +MOI"G\%QQ[MUPDA3A5"".^SSO/RAV[IF3*EC2`$*^)I?I?:Q$X'PJ$[O&[H1S +MET$1SXX\SSK&LAYG4QWR51.W["K]U5Q+C!C2(3/]/K2$*[*UU%\M7;$%2K<+--6SY8!=SBR^I6 +M#[I2UTLHL]J*Y,UD8UL!AMC!SG(/X6[*S3G_DP3'.R2%0%_L@ +M-\X(DBY',.J?&`)$+Y"EH%HR_5Q6-!;S)O"4WEJK:_O>*XL9?1ZO1LSTLU=* +M2\`I_R0L;]GSS4X75G>R%$?VWSE8O,U>P-VV#!H7-.4P]1C.NZ>GXP`,X5.N +M.%?[DGZ2XC$*1_V#]G(_RCD#M^-8%?(D83N#1SY-3)(EFYT^H<&HCX60=X$# +M#3LE/JGBC/:$DQ@ZY!+:5GYP:9\-H)9&E%P(<7ORV2P*\^NJFD6@\YX:SQ_K +M_?E2=;*.EQ]Z.4HKBRP<+*N3>-ZR#UW,R?>/C;A'K^/WA=(X`XCDYXD( +MI`H%!NUJ5A/J^8Q[,PH3(F*9!498.OS4%&Q[)(!=%B(<4;MT0.+>_9OZ;PI0 +M/7G@A%0>MN)310Q1^^-KXW!@913&8Z!;=.:6'0GMLNJ0^@DYO/Q3QLQ]]9RM +MX>2?<>)66*R$?+F$S_C#69"K9\P):$TB +MYMG*S2@AR2;12;=1YGI\<+5(>F#R9'VE[_NA\#RQL9Y"K%,AL$+34Y:I9P/G +M%%M;X+0K#Y>T]K5FN=\,2?RQ^$Q77](@_'6HOQ3HY%CVIUD_OR(IO1>>(9_UJ4DSL!D=]V'^ +M*+UYF\S&``SA(AO589;-MK#V>AC)I=/#=B49L!+,MAJ(#KV;>82#S>=@@.8% +M`^C.[R$H2`F1-@5'@3BW: +M772[UL#!!3DRS^&#&$9-ADFJ@R%S*?T&#%HB"HMQ9(%RRH]&QCTT3'#:?!B0 +M7`!&`CR`T?-ZT-JOK07K,;!D:L*L47U5[-='$_"\]12X(]Q>0Z0$P553`?YZQA.U,'_!NT:K3KZHKN/!+MT2>HRWQ@X%1H@_ +M[.:Q[!S?0=GU+>RQU]Z;VYP87DO)3R.&(F`K"6]*JC3QB*;=Z]6B)M'9N%`* +M&@D6+AZ-B%KC2FR(D6,(X+,=94.(6T7R-Y\3;`3+G5@[A8BS'N>Z(\+6:IAF'=6(/B&5`P>P/ +M-."-*9K820*=E>S#.6EON]"QL,K@:O4K(V=U9V*MF?U:2=OVU!CG-@]1H95\ +MMRNM=X/#2TBEP\7'*D7IRCFMJ3TN\;UES!;;"8?=Y'BA>.A?6$ZW3'9<,@0, +M3-B(K'*F7E)/QUUX"#`]^\"H,OD*C'0@;AYZ=!K;_+"4@$MT_7$/(]UGE5&+ +M@CWVE11WZ)6UETE,BJME(D`T#SAT_7&(B/9D)W>N60ERCMI^Y>'HP/S\Y*C6 +M+3"&90U<5:FW:7YPWB/WTL+\`/=38B>"V(DFG#:V'NFK`WM03Z]\.K8 +MSXZS+W!'W7P@@@=AS^DH[]Y65 +MR6I-C7,%B;-$BB(Z\0(9V;,W%C4L-US:PMM[C[/;\+QC.+&PT1H@6AQGSX2! +MKPB5,/21QJ"9;SP2$*OM5)&L.D2)!;O6J?L]K``#(F^F\1]7XLX=66`SU>W0 +M>IY:WK.UY;)\UFMV3L%G/3:S;1J&4L7I#2)^":\8S`-U+OG)6*@ +MA6DM,XBJ>1F0HT=E@#K5CT`,C,&&O]X"97"W4Z;B_0R;I-X$VFI_\%\!8F],IUUJR/4*XD*CE#E:1#$V!I!GZ*6-K=W +M:X;?]7+(3BC8'CR<-CK2_CS:N&2$OW#7++#94=YH>78TYTI+&N*&9&(!E;(@,4WA>5Y^^TKMRON#') +MN70FKU(AD%EOY,,*ENSMLD)3=**-F@@8ZW&7*?O^+]<*;N>Q_,'^TI4"YJZU +M':R5E$A_R+G-IO]4^U41ARZM;8][Z$OA<-!S[A`5`IL<&1'M4^*#2-X&L$P5 +M=D[N+M9L4^!3S2-`%@"V;-[(&)S/1Z1.5)`(R*6S[#UE_ISL@]6''(DO +M7:ETF;UD^7+,;+?%14BJ5DA,(37%:H=3^M4B&P'O^J/Q]'6Z4^>7:4N'[&BN +ML?*1R#,X2P$BSI3$G*=(9='']16_)+@B)F%7L#GOU_0O-D)A_N4L#HXX?+M> +MDJM\^V=?ZL;4^9J@-6<_0S'.AU&ZT6RE/Z%Q>3?<%[R_0JAW[<=FSX-U&B$` +MFKU@I7O<$-QW)SSXQQ4G4[`?$\3R"7'\#]+'D:H^\U-%@MLL*O,R3,%O +MS>P&'=_R;'$&B^N^9\P;+67ZF;JW!XQ4;(9SO[E?-`$J+%^%G1%PWJ+()C0K +M4U&=P(D#^-16""L81BR;?0MSFXM;O@ET.0'@&S+/J(#U$/=9FN!&,`;UDWDO-`/"NRLAA[RD&LO*U$2'D>`O65#+7$!#XQD.2^N&%7O(Y?2*XX: +M#-B*1D>U_USYJLJ*;98ORW0AK]':_E+5T=NDIKO3MP0!A)0DC3YR-Z).T@.E +M`U]L+U76`C894>4N"]@%4WU:0AS\G#RW!MX\?T%\S$K,DIHTP8@:K`*X2;`- +M7E`B?7.@W+Y%AV&KPCR9L%9U!,"0>GRBA.X@U3GI[=A\?D +MF/&E@CB3!3!=\0ARGD_MPR&&*@DI;E.S"L7M+]$>O/,B\\6E*A;C*Q3SF@,/ +MIEV;SU9="P)31] +MOM;"7LB+2*:K-SV>K$WC+\IE`8I]`81U\R2ML.T`L*%,Y]JI.SL.YOTZ_S!) +M%60%EQL%V3GT$MT[5PA6T0M(7>6T`)5K1:O-`EJO)@)<4CG[J;0`2E.+1%,/ +M[8=M\I8-+^S<:H84WJTQ.F^R';X[=^:]'_QD[,W@NC%R=#XPG_'-R#E*7J6O +M!""049K6@5[`6_MHF$R"-K:,K>;CK@3KT&XE5;QU62HL>*[\?/24#1@5:+8E +MB,#1F-L):1JFY.Z;8&\-D%$F5>DZ&8[!"Q<[+CQH*U(UUX-5G$MK7N:63Y!32\EM.;C^-:5 +M%Z8WV$?E?O2PBNSR_N[5%;IW?AL+'M3M`X7@_?`_R6G*__"0:@J:B/VK?K"J +M4I912,:+!K(6:ZE`K$$)`>8>Z<<9VGCQN\3*QIH_KU)P$7,VIH=LCJ55-N5Y +MK.DW($-*L^CGL=-8DU"E$^^E"N[=S9%*&%]I1[)6K3]C\')R"6;B6W%_1-,+ +M.]\D"\[H#%F#Y$0T"$Q\YM=1"<7=Q7E=7++JM>_'IF%?CU[?P=33.#_?U.:6 +M32_T[CK:@6\;/D?!UW]V/D_Q,]A6.3ZC$-\@R!&=/MX:1(="+K[TU0H^V37W5XXR;4JKT@#"76N@P0,]\;$L)BX3*3QBK +MXOP$7J\6*[$!>F=+9<)Y+PN)C=49&/&H$8E7/V/_J6O4?@)!DZ& +M*$,23=I]VY08XC)Y@DH;"BFX;XT4G@HYSYJ'? +ME3@`-T*%BL5A+3:Y#A/>=%M@&^1!;;HT:Z"XJ&C'#*D^X7!=LV%4VV=D?B// +M>3JDTGTN0+FM#&L4'TE1U743(RFT/&7=,#$?5?5"*6J/7]25?4>U[;8&/I[Z +M;M"*%U"R[;3HKIPBB[]G@CYT,F<$X85.FC\J,DOT.\/_?>8(%HJCW/CTA_^. +M9EP7KNW)2<3#'R'.Q<\QX*@JI>LD;/_.-X?55P2>WO_TP0C3P@AYT?AEW'5, +M8SH+/[@F(X`I>:VUHH-@;,T?.LS3W%M*>J-B>WAY[]!"2O,.3QK_88V_-)0N +M=H6,LCQ#]FJ!<&M<6(4B6J?:NW'(K@/#^O9(I7D\L5@QQM8VM8I5==&#HFA* +M,*=".PHO$L`@F)W4C5.+-J$@)L3UU3/ZO2^S$+0KTX:-2;PG[3Y1(;6462]( +M-`H;2%K^>"1``(JAO6EKN>5*W5:B_(>)=60]SG]L#@\H@V3@WJ+%]*S4:/[&N6&=DX:<%;;4O7K_UWIF +M-9,X?NA@_E+G&3[N6B:)&^@BN%#MT#UF=3 +MQ#<5?UYVZ:A$O%#+(D[?W*>`8TL,>`,G6?OUV#R*V83#FE8SWU&!I,=73_9_ +M6^OD&5Y/D"H<6;Z7Q9[(#Q&Y2@\YH8#Y'Z+K:B+,4TO1^(JM+QM('M4X2O=/ +M5Z!$[<;SIYT:CSTK7[<\_9T'M/:HLHP`#$ILHW9FML'GJG8%R!A.O<5$ +MQ%G9!K\1U7&ZA?0&GPG7S5YX.0PD;^(=V/<&Z6ZJAWR5A1DUV@T'QQI6-/F, +MG1!0",MJ@A4@;I8D=O\,>@#\B>'8X&T0$)8;3+0K] +M=>G@K4:()T38G$_(A16)CG2U9'0H_O(1O1EIU-<$E:S22MY1`MH&%FLMWE0G +M$B0[QBLL$T_C3""DWAIW`V"C30&K2Q8=-;/FN5X;"7?;-]\7KCX0[0IW0%!T +M(E#UTN%4;1$Q$G4=XKOH:C+%7$0#*TO9I*'EC0SOZ_3VR[N8S#F_"J\A!6]B +MG>"TP`^7,JKA6K>D:[5:1(OZN5"EAML%U$V?$)D1U$:-SRFT\Q0*$G[\;A6' +ML9Z\76EC'T@W,,CEEE##.@!NOE%Q^-Y00=37MC!=(J;"M(FU#5,%-5'1=DN. +M?90=HS_6.G!*^LB>+::+K%LCO'S-U?Q>YB7)6((& +MBMCGGW)ZJY].)LYJ1B5%@9Q(`V +M>I0<-MJPI,W-8_<"/J\"E^M6Y[=F4CE]CC@U:7%+S*,@?'X +MP7C?=C]S77H47<`;$-+AB2'?5SII!&#'!0-3:`)#9.+`\ZAH>VY;.X'N!\*M +M*9G5FQU3S]:P@]-`OME.K`N,,2^.Y;TTGVK]#\%X1+F`Z^*.G#0['7+5BR:G +M4LJ#"&Y&T`W6:82SA[C0.)`W*:N'Y*@9D`.?G8/`%Q9#31VG7SCG@+7L&4+C +M<@?'@MRBJGK7_TH;@F,9)G1D`XC)P'J9@N7H??+GVV:M3E`G"?V@>%71:O5* +MX;'7IIMSJKH\N$^.18QUA$H5<8WZZ:,NZM6(^:#F*15I[J5%NIM +M>$,DF7E!B,MX0C:E-F^M$GLB(RP#[]Y.R^9Y>1US#=4@]*&Y3%F>:]1C(?]'#4O")9CM2?%>02'.)_HJ +MR\OMKZH#5^S0[.185IWTBPD6KV3W-O"=5_O)4LE=9RW98[@RTRMEDR5Y7C-A +M%;R1LE.%#YU16M!O\4TY!S#N<@_*$I(1&6,XGIDUU>ZW%LU,F;<`Y2TY:,1( +M!2;]WV=*NQ81O//B'!H<=]H1];IJ13/ +MZ_LD<3IT@4V;^/0R5R`L`>!-Q`[8E*@U$#T2H97`M\N]^Q705Y)3YH=[=4C` +M@:C-,E@Q+8.XV9OS`^,H&DKQOTMW8LB61D3)Y\&7;ME9\>5#/_?:X!%T +MA6I4ZU5\=2>(&H\;L0CY*)`>A-]84HU]\42D+8(I=)GPV-&55@%U\8-(#$HK +M6[;,I:!ZG'L"TFL*(VA],B]Y6LR2 +MRSQ;GQ"2H.NPZ8[YL6Z>FVC9T:;^/0I\:#:]>VS&Z3^$9[ZHXVAZ:AYS+W*/ +M)!<^L"H!,<:C")1:VME$JBGG]L59CZEW[C$9'MSRQ@BD'BCL.*,7=+*8$K/W +M^#':];GD-[YJ;;0UL\D+W+Z+-C0$[=M6S.Q7/.\KR\[60([1L(0*PQS\\7Y9 +M4(?#O)X;S)S44M\#69LR"LQ&*[HGATFI4V8%X6H#8<(2&\6$E5"!QOE]LV[M +ML&GJE2R@):=\U@*CY^9F"Z[:6]SGQ&5.T"+*DR5JP5\W[0[#4>9"75+,2TSZ +M>R:XE-B1QD4Z4A#L)X +MM34\;DDCWY`"`;Q0@_"^;=LL(F0[YE0H+']L=/&HQ7XXQDTZY?"DDV`6-0J7 +M#878D'C*^``8"B(E,+(:FX.EU.]C&H<(M44S9TS>:0@OP,FFY_U"CNGE3M2^ +M,2_L]^LR@S*[=1$A5FXJC5>(G@4B=!"Q3[:5$>!<[0(1&XUNPHM061.DG.#( +M-0MZ['KBN@G)%XL#L`S_O<,A-?[(>2A/$YAFRL.S\TDF';WP2J$8-PXFZ_@3 +MZU-:WQQ[TD*0847@^')SZ.8E63.PL]@("!,7A0K:CG5?S$OI:_F'X5O$_:@5 +M:B\3=G6ZG&AES$6PK`.MP,STG/J!_O9CEBB#&O/R0PA64 +ME+Y+]OK`!'$OXMOF+B$&*XVLP2/CW*>D<.1W\U?FTWRA(C^,`@MF1/_B'VN. +M-%WLVJU[EA"E;1(6H@ +M3*)"`[36&@[?IB-&?I5ZB.'D!6V_ODT?WKNJYY(%O:GDE&>+I<`>ZY6$-VJ4"A6>-A87.:TSL1R;U7V+*>Y#B6$S0RNZK0]3G<2D1Q8D923C.IJTG. +M8"1_+Y!%\$J@!G3;^P6SJ4A*OHZI"5AOA_QG&LVB0VH;4EC*TU_EV;@1,E_* +M#!MTD^7[B8;P*"^+K#G?!UDZDI49QL+\,")7-ET$-/`,6C8+!^I2:)DC8\+! +MW]/64DJ!3W.NG:4>>U:B>](T^4@NU4N(]MP)3%&K,6D=R<)&P[`A^]VV!F6\ +MT^P@5:@NNJF%]ICXND]T`*POO7<:S85Z>7*_I_+(N;VN:$Y."U*7Q%MIG!2_ +MU0<:9,G!YG-DFSTT`&0J +M!\7!!:20-*-0?F$P=L3)'7IO\)SFM3X=%?!__R]ET +MALQ@!*Q0([\V2>(I='370+W;>YW$KV[Z^DGC*`H@S5\G"V0U_Z"@-Z-5:-MU +MIHM)]]3U3@#Q,Q+_CYZ]T\@"INZ;KX?9JE\WA:0_DZ%MWB*N=OQ!,A)*YIC& +M2XQ(/]>NE^<%>NY# +M)BA].AF]S:[:L9W'_1N$$^[2EPGQJ3G`"X^R52LXR +MM!!"9#E2+AM(*D=N,>!"A=.Q57^Z&P`6H'0]R&-B410DS8`BV.:WF])S>NO& +MWZ9]J)69UT6+XZ6_3%+_ORUKJ#C80_`F-(G:(MN*(:H#H/$;3:R&EAG/M[JP +MYFQ([TA9R.3'.1?PSKQKERD<*%24DBJ<53[E5U@D!8"Y`KRY:I`>ANI%B_>5 +M/]C\D6K,;RYX)IF51K*"57#8CS#J5I,6D!-IZ87S<(':=1/%\EH_W"T(B#.6 +M_PX)C@(D?+#Z&A#OOF"!%Q=BPN`B>S]JI0I/@SYSUXPN/A +M+Z.EVEKRE!G+E["AW`%V4]8I/J6Y-$J@5AM+SOY`^KKHY9-;#!(P7K0HM5"^ +M!T13A%X-1LJ%+\G1FLP;#Z9+*/P$F51YI=?]@O'#\&0ZC,]=HX=+N+L@3=,U +MEX]S%$"*KI3324[R7<7?1X<66:2)NE=_>T\OOJ$G3L2-U*TN]`=I!`9#\7G@ +M=S"U$JD4W#C]V^A!^^$AF]I_''@S\52C(006+;YEKX42BSKPU<7\E,];'CPJ!*7&?,)J%K%WWLI!2M6,RU1#VAGJ]J#:^G<`&@/2*D0,%[Q2@X%?YA:^ +M$&P(CXNA9Q-8BGR&BEY@2)D5=/5'8EJF/ +MN7I3E8!>!Q%*5T(S.1$NMD7L5=]=\N4I)V)'W5^+#SI#;NGX-8?`W23W>P#! +M38U$:\Y4K<38[`WU_?!NSQL)OP80;:E6WJ'$&ZTPB%64L,1^`4AK*!B66B]. +M*R:X3J)?YPU'-',Z]TC%)27C6.E:[==+^5GE#\B,C'?93H?HSY_OY4N47LKT +MQ?6A-47HE>4OD%450&B`+6+$`]<[.A9#F>?),P3@/8M%S7$WH&\4;3\;FT/> +M!!E(J__9P?+7S[WL#$.=1A.931E8*:"#[%5=2Q'X=W*O9JD0)TF3S.(;OX&S +MA;LYB!!;<>/V%%Y[?71\,<'P-A,0(FY.E+/PTE@EJ_MT:A/YO\<@^]]A'!M7 +MQAG4W_+,48ZS:@:XL%!H-&&!@]X7*N9BU9^1ZM@4%PA=0+801N,(RNC+A2.- +MZ$K,2NN80#26H("4[7-,DY-/WG[),^G9)3R?L`U8,4V%PF!&\* +MU5AD9/X(.(LSZFJ5,1';1?,70G6L'E(**;*FZZ,Q,^,GR>C3:)AISAENP$.^ +M3F\^F8MT)B(+"W+%U>DZAF=#)<(-#CR3SV>J&-4F"YW<)0HDQSR!^"J(T\]M +M(G-T`U!;U6J>P1;YX`F6K^KL,HD&48,_+5*X/W,M_12A1:OCP&!,>US&I7(V +M"?9$/D0AI<4C#D#G&9N39K6<%-9BN!?MNF7ER^05`,]J +M_^Y#V.R)TW-%&Q>A^'UQF0S]'U(=VMGY?*F_VB]AR*!5*5-UL`>5`(\1%UUI +M!M8(D%1C8[KC_WXX:#^,TRN"W(A'1]UAUG:./MC?4]BN-7J'5'%*S"&\Q]#O/]Q(R;&6+T!1K +M=_N`.18AF-[<.9F(8'^[>@;(:@KJ%">P7_OIC)(QH%'0QPA&8HG +MB(:/H,6[?5:,+C^C5$JQ`;BF\)J9A^VW%/W5YG5R.]H5_/"+`,44$56V>'PE +M0I7;BKO6N/!@\?TRF[9M4&01^#'>6@VK=AWCTNO;=8F*U-^<9A[8ZZ5?L(\; +M[:9QT^:P5:X-;6,F-YJ]Z=((0C(M2*,F4V;_%`+E?N,I56]7`DA%S5MR];Y5 +M^S84E?MKPXP!5.5A:M2GE8L@+P>2JAJV6XUOSKT=)Z&MO(U0D,V9IGD@>E,- +MLCYZB1RS#W +M]4+!XN]$&NC+8:TCKMD@H/P6YS@S!7R)/Z-7B?G,\C\])9E).3;]:.*R[KBF +M$T??^@]CQ']B,_U(`<0BM>S/UY)+UMQP[>VN!\83`P^?G>2,304F)Y600:,7 +M@ZNG+3$$*`.83-NP[%5<&.D,/R"`7&4GL[\XE)"+:>V%J+-EW*>UQJ6FY!P@ +MF>[N"QQ$XDUD*-K&*Y&KDG516QKKF/_I\]^E7+T;6U#\H%JFO\@5I-[Y$IU_ +M&[<.2@R6K`"*^PL?5^SUZ*8I'+`PJ@J06!WW#"C26D.6[K_M0P@QN#X8?V== +M@GI$8)NDQ2U?C4FQ%B>K](U$;>`#E8VV='OG,]TK"ZGBU$A'X86A+T;IMYE` +M7:U[V\*0ZD@$N>Q^G]IIVV)(W1UHUQ%D%*\`E,?+XRR9%ECFXS5_7<\T%_\Y +MG5PO[#'OVH*\:ZF?2VB@TLN\(X[]W7!F@#=4^=>!HY4%$P=`V*QV-!N-#@^+ +MMVOUM,5K`8#13E7*R$Q)ZLL/`K;WH[U6PH6E]PI.OQQP;5Z4NCSL+,4+Y3KY?ZJOU_NF +M5.?8;CYK6:7-CV(=8RXL:86)LACKZ@/S5N8!*4/(Y03K:,8\/D'V*(S<95WM0 +MQOYX_HTQL1N5*+`Q6>'(PRD=2P^`E`P)J;8,SP%0!W#H#BQC!F`04ZG:U;L% +M*\C)(;!PVF/(+Z-]J4ZW#2^^48>.BR+AB-7"LORBGOWY5`H[BA$N)W3Y_R'( +M=**C^G91I%XJT=,_GA<>JD+3:(#LFGJB*LW\5&CLB:>.#F8E%#6%)]:1X]0] +M!Q>C[GS26W)#J-E?W@Y,W:76#:M3O+FEV4\)OVL1C2ZI4[>$`'*__O;+ADT* +MSS>RI1G]1Q7`VTP(4UE!K'#)BSO^6KM4EP(#0^9AL)H#"T2>C/^UG:@V,$8(P(TD;8UDH\I6X%##=P$YP>=1F?/_FCF5MR3$09%F7KE_S_._VR@RMIN6PY'OQ;_S-F\;%Z!1*FS706[ +M`K^VYM[A&%VSP?$YECDV4C7C"1/PW7^$QE08@5=2IXY\)\/DBOI7X%-*O*PF +M\VIEOS.DAF5'PZ@`:/VEH#(C4IS;`./"23BL0!(IH`'V^@X_9-359J@[T]DC +MH!8.(H=OT(K'&.@&0OM7`;NO(_SB/[WUFT`?:*1`Z:?'[(O\QU*CYG&.^IIE +MO3AT`LXBX.GRVW.+-GC$&T-)&J/TYB%<7:8$V,DBJ0ORC2$`D2_2#[9GB.99 +M1P)9L:"XMY09G0SWX)!"4=BHQMQJ+1O!H.:Z1$1VU?5O).[A#""/!6H4OV3T +M%-EZZXN>YX!S\MJ]2+:3<;^ZL"@T-'%''*\9T.I!S28U50QV_?"JK[-B$E;O(ZV8[]K7E#CAW +MT'@3)`[]"JF2#DPYOD9B8MTK)0G),(W>J;@-IM)X*C.1;:_S>L+.8?M;?J78 +M[-L1R]6R2+%^2@KD^7W'ZA\5UB05TXU@B3CBJ( +M7!\/AQ5H\"_\SA +M=:F;M`=D%61]2_7LS#":2[P7TS^$H&GU$*R:!=#4ZPB1CA^<5BR#4PNF1%!5 +M'Z;/4>,#S:M_C@;_YT.(0W6)LD0O$&.Y1-;G;T\F5"G1@00RT$=Q2=`X[9Y^ +M820^U%%$.#V32Q:..ZE4O;;B!/5)UDZI6]P*>N]@^4]+A?JV3& +MIWD_]]F0RO)'#!#]:(<7^A:'S$?@5A%FN;@:-(I\P/%%5$;2]=[LX/-G +MCV^6$A\Y=NI'-?'3$*=#FO1G,P6#%Q^>.W@RR-J\O#MS`YIHR/?H:4L*Q65T +M5D%MZBZ]X1`\)@_P#Q)N[PW0KDL1OY?#&$([VH2-^&E)&4H;KNS)7$!(OI"- +M>O84#:X+5*N`1V&G;ZQSMCAZ/RM*W$,'(=7^)772Q.\%Y^*L]Z/8&Q;PX#$!$?ZQ?PR&S?06__\,PN2SWN6PB<',Z:`2?+W5NIZ +MQP1?:,X-*G`\OL';&5F`W80F)['CE68*4/!?&M>Q_R#$Q;@`Q@F5(I[U[F/8 +MCOQ0BL\ZA6GS"(1>NNT7UW[=_>9;7AG*PCEPPQEG^3!\L_BGG$>(P!]1=3U +MSVU32.):[0H>JF(9*O[N +M7&AHVJBS+_&-5L$(`LTXLA>O"]0KI-^&2EL>6`T68&4T4AV?J'CYW/4JT7.9 +M.]2-G]B`'$Z\$3P'1!].A&N'IZW.+$-/U@QTY0DOB0"/L0"BO_7;OC9A1#M3 +MDKY_.!]1@3UR451\>I/;:`.VS3SJ_MO_/E3`@#\&]@Y4][!$,U$05+X.O4U< +M%Z5*<`_P\X1L?(("JO0$4+7GCN/AC5<9]03!N8NSHL=P`_H>=M-A>$-:*G]- +MVZ>[H'XZ*?@%RJ8@E?SWB^`3Q3W[5__+&^[9`2E.A0WT,QG2>)P$BOJT=@0* +M>."DT!.:NO#(K.M&!)"@[;<'(._$-_+HDP67X)2/Z@UMT`^&8/(YGP%A%XL'FS85[J*&VTE7SDZ+@]K<# +M2Q]BR^!:$0&$?Z71(7DJ,*];&?AJ,8>3!`!J'4O*I=CQA:$X1-_@(=NAG>4N +M`#LXE:52OI"G\%QQ[MUPDA3A5"".^SSO/RAV[IF3*EC2`$*^)I?I?:Q$X'PJ +M$[O&[H1SET$1SXX\SSK&LAYG4QWR51.W["K]U5Q+C!C2(3/]/K2$*[*UU%\M7;$%2K<+--6SY8 +M!=SBR^I6#[I2UTLHL]J*Y,UD8UL!AMC +M!SG(/X6[*S3G_DP3'. +MR2%0%_L@-\X(DBY',.J?&`)$+Y"EH%HR_5Q6-!;S)O"4WEJK:_O>*XL9?1ZO +M1LSTLU=*2\`I_R0L;]GSS4X75G>R%$?VWSE8O,U>P-VV#!H7-.4P]1C.NZ>G +MXP`,X5.N.%?[DGZ2XC$*1_V#]G(_RCD#M^-8%?(D83N#1SY-3)(EFYT^H<&H +MCX60=X$##3LE/JGBC/:$DQ@ZY!+:5GYP:9\-H)9&E%P(<7ORV2P*\^NJFD6@ +M\YX:SQ_K_?E2=;*.EQ]Z.4HKBRP<+*N3>-ZR#UW,R?>/C;A'K^/WA=(X`XCDYXD(I`H%!NUJ5A/J^8Q[,PH3(F*9!498.OS4%&Q[)(!=%B(<4;MT0.+> +M_9OZ;PI0/7G@A%0>MN)310Q1^^-KXW!@913&8Z!;=.:6'0GMLNJ0^@DYO/Q3 +MQLQ]]9RMX>2?<>)66*R$?+F$S_C#69"K +M9\P):$TBYMG*S2@AR2;12;=1YGI\<+5(>F#R9'VE[_NA\#RQL9Y"K%,AL$+3 +M4Y:I9P/G%%M;X+0K#Y>T]K5FN=\,2?RQ^$Q77](@_'6HOQ3HY%CVIUD_OR(IO1>>(9_UJ4DS +ML!D=]V'^*+UYF\S&``SA(AO589;-MK#V>AC)I=/#=B49L!+,MAJ(#KV;>82# +MS>=@@.8%`^C.[R$H2`F1- +M@5'@3BW:772[UL#!!3DRS^&#&$9-ADFJ@R%S*?T&#%HB"HMQ9(%RRH]&QCTT +M3'#:?!B07`!&`CR`T?-ZT-JOK07K,;!D:L*L47U5[-='$_"\]12X(]Q>0Z0< +MR!0]$;@AW;DC'-S)FN9,@BU!RG26IWA;(4UK3$,0R):9:)[H!'P^P0;,&.`4 +MJ'\M11\ET?&^&P_1BU":9)5*1$U1!@UP^[&<[V'_(#F@V&KCC6K6"$P553`?YZQA.U,'_!NT:K3KZHKN/!+MT2>HRW +MQ@X%1H@_[.:Q[!S?0=GU+>RQU]Z;VYP87DO)3R.&(F`K"6]*JC3QB*;=Z]6B +M)M'9N%`*&@D6+AZ-B%KC2FR(D6,(X+,=94.(6T7R-Y\3;`3+G5@[A8BS'N>Z +M(\+6:IAF'=6(/ +MB&5`P>P/-."-*9K820*=E>S#.6EON]"QL,K@:O4K(V=U9V*MF?U:2=OVU!CG +M-@]1H95\MRNM=X/#2TBEP\7'*D7IRCFMJ3TN\;UES!;;"8?=Y'BA>.A?6$ZW +M3'9<,@0,3-B(K'*F7E)/QUUX"#`]^\"H,OD*C'0@;AYZ=!K;_+"4@$MT_7$/ +M(]UGE5&+@CWVE11WZ)6UETE,BJME(D`T#SAT_7&(B/9D)W>N60ERCMI^Y>'H +MP/S\Y*C6+3"&90U<5:FW:7YPWB/WTL+\`/=38B>"V(DFG#:V'NFK`WM +M03Z]\.K8SXZS+W!'W7P@@@=AS^DH[]Y65R6I-C7,%B;-$BB(Z\0(9V;,W%C4L-US:PMM[C[/;\+QC.+&PT1H@ +M6AQGSX2!KPB5,/21QJ"9;SP2$*OM5)&L.D2)!;O6J?L]K``#(F^F\1]7XLX= +M66`SU>W0>IY:WK.UY;)\UFMV3L%G/3:S;1J&4L7I#2)^":\8S`-U+OG)6*@A6DM,XBJ>1F0HT=E@#K5CT`,C,&&O]X"97"W4Z;B_0R;I-X$VFI_ +M\%\!8F],IUUJR/4*XD*CE#E:1#$V!I! +MGZ*6-K=W:X;?]7+(3BC8'CR<-CK2_CS:N&2$OW#7++#94=YH>78TYTI+&N*&9&(!E;(@,4WA>5Y^ +M^T +MKMRON#')N70FKU(AD%EOY,,*ENSMLD)3=**-F@@8ZW&7*?O^+]<*;N>Q_,'^ +MTI4"YJZU':R5E$A_R+G-IO]4^U41ARZM;8][Z$OA<-!S[A`5`IL<&1'M4^*# +M2-X&L$P5=D[N+M9L4^!3S2-`%@"V;-[(&)S/1Z1.5)`(R*6S[#UE_ISL@]6' +M'(DO7:ETF;UD^7+,;+?%14BJ5DA,(37%:H=3^M4B&P'O^J/Q]'6Z4^>7 +M:4N'[&BNL?*1R#,X2P$BSI3$G*=(9='']16_)+@B)F%7L#GOU_0O-D)A_N4L +M#HXX?+M>DJM\^V=?ZL;4^9J@-6<_0S'.AU&ZT6RE/Z%Q>3?<%[R_0JAW[<=F +MSX-U&B$`FKU@I7O<$-QW)SSXQQ4G4[`?$\3R"7'\#]+'D:H^\U-%@MLL +M*O,R3,%OS>P&'=_R;'$&B^N^9\P;+67ZF;JW!XQ4;(9SO[E?-`$J+%^%G1%P +MWJ+()C0K4U&=P(D#^-16""L81BR;?0MSFXM;O@ET.0'@&S+/J(#U$/=9FN!& +M,`;UDWDO-`/"NRLAA[RD&LO*U$2'D>`O65#+7$!#XQD.2^N&%7O +M(Y?2*XX:#-B*1D>U_USYJLJ*;98ORW0AK]':_E+5T=NDIKO3MP0!A)0DC3YR +M-Z).T@.E`U]L+U76`C894>4N"]@%4WU:0AS\G#RW!MX\?T%\S$K,DIHTP8@: +MK`*X2;`-7E`B?7.@W+Y%AV&KPCR9L%9U!,"0>GRBA.X@U3 +MGI[=A\?DF/&E@CB3!3!=\0ARGD_MPR&&*@DI;E.S"L7M+]$>O/,B\\6E*A;C +M*Q3SF@,/IEV;SU9="P)31]OM;"7LB+2*:K-SV>K$WC+\IE`8I]`81U\R2ML.T`L*%,Y]JI.SL. +MYOTZ_S!)%60%EQL%V3GT$MT[5PA6T0M(7>6T`)5K1:O-`EJO)@)<4CG[J;0` +M2E.+1%,/[8=M\I8-+^S<:H84WJTQ.F^R';X[=^:]'_QD[,W@NC%R=#XPG_'- +MR#E*7J6O!""049K6@5[`6_MHF$R"-K:,K>;CK@3KT&XE5;QU62HL>*[\?/24 +M#1@5:+8EB,#1F-L):1JFY.Z;8&\-D%$F5>DZ&8[!"Q<[+CQH*U(UUX-5G$MK7N:63Y!32\E +MM.;C^-:5%Z8WV$?E?O2PBNSR_N[5%;IW?AL+'M3M`X7@_?`_R6G*__"0:@J: +MB/VK?K"J4I912,:+!K(6:ZE`K$$)`>8>Z<<9VGCQN\3*QIH_KU)P$7,VIH=L +MCJ55-N5YK.DW($-*L^CGL=-8DU"E$^^E"N[=S9%*&%]I1[)6K3]C\')R"6;B +M6W%_1-,+.]\D"\[H#%F#Y$0T"$Q\YM=1"<7=Q7E=7++JM>_'IF%?CU[?P=33 +M.#_?U.:632_T[CK:@6\;/D?!UW]V/D_Q,]A6.3ZC$-\@R!&=/MX:1(="+K[T +MU0H^V37W5XXR;4JKT@#"76N@P0,]\;$L)BX3*3QBKXOP$7J\6*[$!>F=+9<)Y+PN)C=49&/&H$8E7/V/_J6O +M4?@)!DZ&*$,23=I]VY08XC)Y@DH;"BFX;XT4G +M@HYSYJ'?E3@`-T*%BL5A+3:Y#A/>=%M@&^1!;;HT:Z"XJ&C'#*D^X7!=LV%4 +MVV=D?B//>3JDTGTN0+FM#&L4'TE1U743(RFT/&7=,#$?5?5"*6J/7]25?4>U +M[;8&/I[Z;M"*%U"R[;3HKIPBB[]G@CYT,F<$X85.FC\J,DOT.\/_?>8(%HJC +MW/CTA_^.9EP7KNW)2<3#'R'.Q<\QX*@JI>LD;/_.-X?55P2>WO_TP0C3P@AY +MT?AEW'5,8SH+/[@F(X`I>:VUHH-@;,T?.LS3W%M*>J-B>WAY[]!"2O,.3QK_ +M88V_-)0N=H6,LCQ#]FJ!<&M<6(4B6J?:NW'(K@/#^O9(I7D\L5@QQM8VM8I5 +M==&#HFA*,*=".PHO$L`@F)W4C5.+-J$@)L3UU3/ZO2^S$+0KTX:-2;PG[3Y1 +M(;6462](-`H;2%K^>"1``(JAO6EKN>5*W5:B_(>)=60]SG]L#@\H@V3@W +MJ+%]*S4:/[&N6&=DX:<%;;4 +MO7K_UWIF-9,X?NA@_E+G&3[N6B:)&^@BN% +M#MT#UF=3Q#<5?UYVZ:A$O%#+(D[?W*>`8TL,>`,G6?OUV#R*V83#FE8SWU&! +MI,=73_9_6^OD&5Y/D"H<6;Z7Q9[(#Q&Y2@\YH8#Y'Z+K:B+,4TO1^(JM+QM( +M'M4X2O=/5Z!$[<;SIYT:CSTK7[<\_9T'M/:HLHP`#$ILHW9FML'GJG8% +MR!A.O<5$Q%G9!K\1U7&ZA?0&GPG7S5YX.0PD;^(=V/<&Z6ZJAWR5A1DUV@T' +MQQI6-/F,G1!0",MJ@A4@;I8D=O\,>@#\B>'8X&T0$ +M)8;3+0K]=>G@K4:()T38G$_(A16)CG2U9'0H_O(1O1EIU-<$E:S22MY1`MH& +M%FLMWE0G$B0[QBLL$T_C3""DWAIW`V"C30&K2Q8=-;/FN5X;"7?;-]\7KCX0 +M[0IW0%!T(E#UTN%4;1$Q$G4=XKOH:C+%7$0#*TO9I*'EC0SOZ_3VR[N8S#F_ +M"J\A!6]BG>"TP`^7,JKA6K>D:[5:1(OZN5"EAML%U$V?$)D1U$:-SRFT\Q0* +M$G[\;A6'L9Z\76EC'T@W,,CEEE##.@!NOE%Q^-Y00=37MC!=(J;"M(FU#5,% +M-5'1=DN.?90=HS_6.G!*^LB>+::+K%LCO'S-U?Q> +MYB7)6((&BMCGGW)ZJY].)LYJ1B +M5%@9Q(`V>I0<-MJPI,W-8_<"/J\"E^M6Y[=F4CE]CC@U:7% +M+S*,@?'XP7C?=C]S77H47<`;$-+AB2'?5SII!&#'!0-3:`)#9.+`\ZAH>VY; +M.X'N!\*M*9G5FQU3S]:P@]-`OME.K`N,,2^.Y;TTGVK]#\%X1+F`Z^*.G#0[ +M'7+5BR:G4LJ#"&Y&T`W6:82SA[C0.)`W*:N'Y*@9D`.?G8/`%Q9#31VG7SCG +M@+7L&4+C<@?'@MRBJGK7_TH;@F,9)G1D`XC)P'J9@N7H??+GVV:M3E`G"?V@ +M>%71:O5*X;'7IIMSJKH\N$^.18QUA$H5<8WZZ:,NZM6(^:#F*15 +MI[J5%NIM>$,DF7E!B,MX0C:E-F^M$GLB(RP#[]Y.R^9Y>1US#=4@]*&Y3%F>:]1C(?]'#4O")9CM2?%> +M02'.)_HJR\OMKZH#5^S0[.185IWTBPD6KV3W-O"=5_O)4LE=9RW98[@RTRME +MDR5Y7C-A%;R1LE.%#YU16M!O\4TY!S#N<@_*$I(1&6,XGIDUU>ZW%LU,F;<` +MY2TY:,1(!2;]WV=*NQ81O//B'!H<=]H +M1];IJ13/Z_LD<3IT@4V;^/0R5R`L`>!-Q`[8E*@U$#T2H97`M\N]^Q705Y)3 +MYH=[=4C`@:C-,E@Q+8.XV9OS`^,H&DKQOTMW8LB61D3)Y\&7;ME9\>5#/_?: +MX!%TA6I4ZU5\=2>(&H\;L0CY*)`>A-]84HU]\42D+8(I=)GPV-&55@%U +M\8-(#$HK6[;,I:!ZG'L"TFL*(VA] +M,B]Y6LR2RSQ;GQ"2H.NPZ8[YL6Z>FVC9T:;^/0I\:#:]>VS&Z3^$9[ZHXVAZ +M:AYS+W*/)!<^L"H!,<:C")1:VME$JBGG]L59CZEW[C$9'MSRQ@BD'BCL.*,7 +M=+*8$K/W^#':];GD-[YJ;;0UL\D+W+Z+-C0$[=M6S.Q7/.\KR\[60([1L(0* +MPQS\\7Y94(?#O)X;S)S44M\#69LR"LQ&*[HGATFI4V8%X6H#8<(2&\6$E5"! +MQOE]LV[ML&GJE2R@):=\U@*CY^9F"Z[:6]SGQ&5.T"+*DR5JP5\W[0[#4>9" +M75+,2TSZ>R:XE-B1QD4Z4A#L)XM34\;DDCWY`"`;Q0@_"^;=LL(F0[YE0H+']L=/&HQ7XXQDTZY?"D +MDV`6-0J7#878D'C*^``8"B(E,+(:FX.EU.]C&H<(M44S9TS>:0@OP,FFY_U" +MCNGE3M2^,2_L]^LR@S*[=1$A5FXJC5>(G@4B=!"Q3[:5$>!<[0(1&XUNPHM0 +M61.DG.#(-0MZ['KBN@G)%XL#L`S_O<,A-?[(>2A/$YAFRL.S\TDF';WP2J$8 +M-PXFZ_@3ZU-:WQQ[TD*0847@^')SZ.8E63.PL]@("!,7A0K:CG5?S$OI:_F' +MX5O$_:@5:B\3=G6ZG&AES$6PK`.MP,STG/J!_O9CEBB#& +MO/R0PA64E+Y+]OK`!'$OXMOF+B$&*XVLP2/CW*>D<.1W\U?FTWRA(C^,`@MF +M1/_B'VN.-%WLVJU[EA"E;1(6H@3*)"`[36&@[?IB-&?I5ZB.'D!6V_ODT?WKNJYY(%O:GDE&>+I<`> +MZY6$-VJ4"A6>-A87.:TSL1R;U7V+*>Y#B6$S0RNZK0]3G<2D1Q8D92 +M3C.IJTG.8"1_+Y!%\$J@!G3;^P6SJ4A*OHZI"5AOA_QG&LVB0VH;4EC*TU_E +MV;@1,E_*#!MTD^7[B8;P*"^+K#G?!UDZDI49QL+\,")7-ET$-/`,6C8+!^I2 +M:)DC8\+!W]/64DJ!3W.NG:4>>U:B>](T^4@NU4N(]MP)3%&K,6D=R<)&P[`A +M^]VV!F6\T^P@5:@NNJF%]ICXND]T`*POO7<:S85Z>7*_I_+(N;VN:$Y."U*7 +MQ%MIG!2_U0<:9,G!YG-DFSTT`&0J!\7!!:20-*-0?F$P=L3)'7IO\)SFM3X=% +M?!__R]ETALQ@!*Q0([\V2>(I='370+W;>YW$KV[Z^DGC*`H@S5\G"V0U_Z"@ +M-Z-5:-MUIHM)]]3U3@#Q,Q+_CYZ]T\@"INZ;KX?9JE\WA:0_DZ%MWB*N=OQ! +M,A)*YIC&2XQ(/]>NE^<%>NY#)BA].AF]S:[:L9W'_1N$$^[2EPGQJ3G`" +MX^R52LXRM!!"9#E2+AM(*D=N,>!"A=.Q57^Z&P`6H'0]R&-B410DS8`BV.:W +MF])S>NO&WZ9]J)69UT6+XZ6_3%+_ORUKJ#C80_`F-(G:(MN*(:H#H/$;3:R& +MEAG/M[JPYFQ([TA9R.3'.1?PSKQKERD<*%24DBJ<53[E5U@D!8"Y`KRY:I`> +MANI%B_>5/]C\D6K,;RYX)IF51K*"57#8CS#J5I,6D!-IZ87S<(':=1/%\EH_ +MW"T(B#.6_PX)C@(D?+#Z&A#OOF"!%Q=BPN`B>S]JI0I/@S +MYSUXPN/A+Z.EVEKRE!G+E["AW`%V4]8I/J6Y-$J@5AM+SOY`^KKHY9-;#!(P +M7K0HM5"^!T13A%X-1LJ%+\G1FLP;#Z9+*/P$F51YI=?]@O'#\&0ZC,]=HX=+ +MN+L@3=,UEX]S%$"*KI3324[R7<7?1X<66:2)NE=_>T\OOJ$G3L2-U*TN]`=I +M!`9#\7G@=S"U$JD4W#C]V^A!^^$AF]I_''@S\52C(006+;YEKX42BSKPU<7\E,];'CPJ!*7&?, +M)J%K%WWLI!2M6,RU1#VAGJ]J#:^G<`&@/2*D0,%[Q2 +M@X%?YA:^$&P(CXNA9Q-8BGR&BEY@2)D5= +M/5'8EJF/N7I3E8!>!Q%*5T(S.1$NMD7L5=]=\N4I)V)'W5^+#SI#;NGX-8?` +MW23W>P#!38U$:\Y4K<38[`WU_?!NSQL)OP80;:E6WJ'$&ZTPB%64L,1^`4AK +M*!B66B].*R:X3J)?YPU'-',Z]TC%)27C6.E:[==+^5GE#\B,C'?93H?HSY_O +MY4N47LKTQ?6A-47HE>4OD%450&B`+6+$`]<[.A9#F>?),P3@/8M%S7$WH&\4 +M;3\;FT/>!!E(J__9P?+7S[WL#$.=1A.931E8*:"#[%5=2Q'X=W*O9JD0)TF3 +MS.(;OX&SA;LYB!!;<>/V%%Y[?71\,<'P-A,0(FY.E+/PTE@EJ_MT:A/YO\<@ +M^]]A'!M7QAG4W_+,48ZS:@:XL%!H-&&!@]X7*N9BU9^1ZM@4%PA=0+801N,( +MRNC+A2.-Z$K,2NN80#26H("4[7-,DY-/WG[),^G9)3R?L`U8,4 +MV%PF!&\*U5AD9/X(.(LSZFJ5,1';1?,70G6L'E(**;*FZZ,Q,^,GR>C3:)AI +MSAENP$.^3F\^F8MT)B(+"W+%U>DZAF=#)<(-#CR3SV>J&-4F"YW<)0HDQSR! +M^"J(T\]M(G-T`U!;U6J>P1;YX`F6K^KL,HD&48,_+5*X/W,M_12A1:OCP&!, +M>US&I7(V"?9$/D0AI<4C#D#G&9N39K6<%-9BN!?MNF7E +MR^05`,]J_^Y#V.R)TW-%&Q>A^'UQF0S]'U(=VMGY?*F_VB]AR*!5*5-UL`>5 +M`(\1%UUI!M8(D%1C8[KC_WXX:#^,TRN"W(A'1]UAUG:./MC?4]BN-7J'5'%*S"&\Q]#O/]Q(R +M;&6+T!1K=_N`.18AF-[<.9F(8'^[>@;(:@KJ%">P7_OIC)(QH%'0QPA&8HGB(:/H,6[?5:,+C^C5$JQ`;BF\)J9A^VW%/W5YG5R.]H5_/"+`,44 +M$56V>'PE0I7;BKO6N/!@\?TRF[9M4&01^#'>6@VK=AWCTNO;=8F*U-^<9A[8 +MZZ5?L(\;[:9QT^:P5:X-;6,F-YJ]Z=((0C(M2*,F4V;_%`+E?N,I56]7`DA% +MS5MR];Y5^S84E?MKPXP!5.5A:M2GE8L@+P>2JAJV6XUOSKT=)Z&MO(U0D,V9 +MIGD@>E,-LC +MYZB1RS#W]4+!XN]$&NC+8:TCKMD@H/P6YS@S!7R)/Z-7B?G,\C\])9E).3;] +M:.*R[KBF$T??^@]CQ']B,_U(`<0BM>S/UY)+UMQP[>VN!\83`P^?G>2,304F +M)Y600:,7@ZNG+3$$*`.83-NP[%5<&.D,/R"`7&4GL[\XE)"+:>V%J+-EW*>U +MQJ6FY!P@F>[N"QQ$XDUD*-K&*Y&KDG516QKKF/_I\]^E7+T;6U#\H%JFO\@5 +MI-[Y$IU_&[<.2@R6K`"*^PL?5^SUZ*8I'+`PJ@J06!WW#"C26D.6[K_M0P@Q +MN#X8?V==@GI$8)NDQ2U?C4FQ%B>K](U$;>`#E8VV='OG,]TK"ZGBU$A'X86A +M+T;IMYE`7:U[V\*0ZD@$N>Q^G]IIVV)(W1UHUQ%D%*\`E,?+XRR9%ECFXS5_ +M7<\T%_\YG5PO[#'OVH*\:ZF?2VB@TLN\(X[]W7!F@#=4^=>!HY4%$P=`V*QV +M-!N-#@^+MVOUM,5K`8#13E7*R$Q)ZLL/`K;WH[U6PH6E]PI.OQQP;5Z4NCSL+,4+Y3KY +M?ZJOU_NF5.?8;CYK6:7-CV(=8RXL:86)LACKZ@/S5N8!*4/(Y03K:,8\/D'V* +M(S<95WM0QOYX_HTQL1N5*+`Q6>'(PRD=2P^`E`P)J;8,SP%0!W#H#BQC!F`0 +M4ZG:U;L%*\C)(;!PVF/(+Z-]J4ZW#2^^48>.BR+AB-7"LORBGOWY5`H[BA$N +M)W3Y_R'(=**C^G91I%XJT=,_GA<>JD+3:(#LFGJB*LW\5&CLB:>.#F8E%#6% +M)]:1X]0]!Q>C[GS26W)#J-E?W@Y,W:76#:M3O+FEV4\)OVL1C2ZI4[>$`'*_ +M_O;+ADT*SS>RI1G]1Q7`VTP(4UE!K'#)BSO^6KM4EP(#0^9AL)H#"T2>C/^U +MG:@V,$8(P(TD;8UDH\I6X%##=P$YP>=1F?/_FCF5MR3$09%F +M7KE_S_._VR@RMIN6PY'OQ;_S-F\;%Z!1*FS706[`K^VYM[A&%VSP?$YECDV4C7C"1/PW7^$QE08@5=2IXY\)\/DBOI7 +MX%-*O*PF\VIEOS.DAF5'PZ@`:/VEH#(C4IS;`./"23BL0!(IH`'V^@X_9-35 +M9J@[T]DCH!8.(H=OT(K'&.@&0OM7`;NO(_SB/[WUFT`?:*1`Z:?'[(O\QU*C +MYG&.^IIEO3AT`LXBX.GRVW.+-GC$&T-)&J/TYB%<7:8$V,DBJ0ORC2$`D2_2 +M#[9GB.991P)9L:"XMY09G0SWX)!"4=BHQMQJ+1O!H.:Z1$1VU?5O).[A#""/ +M!6H4OV3T%-EZZXN>YX!S\MJ]2+:3<;^ZL"@T-'%''*\9T.I!S28U50QV_?"J +MK[-B$E;O(ZV8[ +M]K7E#CAWT'@3)`[]"JF2#DPYOD9B8MTK)0G),(W>J;@-IM)X*C.1;:_S>L+. +M8?M;?J78[-L1R]6R2+%^2@KD^7W'ZA\5UB05TXU@B3CBJ(7!\/AQ5H\"_\SA=:F;M`=D%61]2_7LS#":2[P7TS^$H&GU$*R:!=#4ZPB1CA^<5BR# +M4PNF1%!5'Z;/4>,#S:M_C@;_YT.(0W6)LD0O$&.Y1-;G;T\F5"G1@00RT$=Q +M2=`X[9Y^820^U%%$.#V32Q:..ZE4O;;B!/5)UDZI6]P*>N]@^4 +M]+A?JV3&IWD_]]F0RO)'#!#]:(<7^A:'S$?@5A%FN;@:-(I\P/%%5$;2 +M]=[LX/-GCV^6$A\Y=NI'-?'3$*=#FO1G,P6#%Q^>.W@RR-J\O#MS`YIHR/?H +M:4L*Q65T5D%MZBZ]X1`\)@_P#Q)N[PW0KDL1OY?#&$([VH2-^&E)&4H;KNS) +M7$!(OI"->O84#:X+5*N`1V&G;ZQSMCAZ/RM*W$,'(=7^)772Q.\%Y^*L`!T````%`H!``"&-JAYL,X! +*%08!`""`M($````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_encryption_data.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_encryption_data.c new file mode 100644 index 0000000..adedbc5 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_encryption_data.c @@ -0,0 +1,70 @@ +/*- + * Copyright (c) 2013 Konrad Kleine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD"); + +DEFINE_TEST(test_read_format_7zip_encryption_data) +{ + /* This file is password protected (encrypted) with AES-256. The headers + are NOT encrypted. Password is "12345678". */ + const char *refname = "test_read_format_7zip_encryption.7z"; + struct archive_entry *ae; + struct archive *a; + char buff[128]; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + assertEqualIntA(a, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW, archive_read_has_encrypted_entries(a)); + + /* Verify encrypted file "bar.txt". */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0664), archive_entry_mode(ae)); + assertEqualString("bar.txt", archive_entry_pathname(ae)); + assertEqualInt(1379073980, archive_entry_mtime(ae)); + assertEqualInt(4, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_is_data_encrypted(ae)); + assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); + assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); + assertEqualInt(ARCHIVE_FATAL, archive_read_data(a, buff, sizeof(buff))); + + assertEqualInt(1, archive_file_count(a)); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_encryption_header.7z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_encryption_header.7z.uu new file mode 100644 index 0000000..cdabd24 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_encryption_header.7z.uu @@ -0,0 +1,8 @@ +begin 664 test_read_format_7zip_encryption_header.7z +M-WJ\KR<<``-1(7)]@``````````F`````````!I:QVF.6KJ?=[:U9:-!,8A0 +MB6O0&LG!?DD:R_'07!.!NV;/LY)*FIFWXUI[)=TPG&";5C%*%S+LERGW+.D%XK*'>5.FQ>74JN]"%`5%TTQ[@L^# +MZVV`LJT"61@``($S!ZXQF+DAMZ?L<`,6_>V19<3;V2;&..`F/OY`DLGI +MB?L"X_1-'%<>!(3'6&[GTF&K$I`20KWW0T2OU80/'3WLJ@2\\?YH6A7J\T[" +M5JH6Y6_..SN-L'T>$^";VM@^(Y(^]N\E588GW68QK>M[C@$[AM@/<+RH]Q!& +J"GI1?FZ````7!A@!"8"$``<+`0`!(P,!`05=`!````R`N@H!F[7,7``` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_encryption_partially.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_encryption_partially.c new file mode 100644 index 0000000..68290aa --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_encryption_partially.c @@ -0,0 +1,82 @@ +/*- + * Copyright (c) 2013 Konrad Kleine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD"); + +DEFINE_TEST(test_read_format_7zip_encryption_partially) +{ + /* This file is password protected (encrypted) with AES-256. The headers + are NOT encrypted. Password is "12345678". It contains one encrypted + and one unencrypted file. */ + const char *refname = "test_read_format_7zip_encryption_partially.7z"; + struct archive_entry *ae; + struct archive *a; + char buff[128]; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + assertEqualIntA(a, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW, archive_read_has_encrypted_entries(a)); + + /* Verify regular unencrypted file1. */ + if (archive_read_next_header(a, &ae) == ARCHIVE_OK) { + assertEqualInt((AE_IFREG | 0664), archive_entry_mode(ae)); + assertEqualString("bar_unencrypted.txt", archive_entry_pathname(ae)); + assertEqualInt(1379079541, archive_entry_mtime(ae)); + assertEqualInt(4, archive_entry_size(ae)); + assertEqualInt(0, archive_entry_is_data_encrypted(ae)); + assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); + assertEqualIntA(a, 0, archive_read_has_encrypted_entries(a)); + assertEqualInt(4, archive_read_data(a, buff, sizeof(buff))); + + /* Verify regular encrypted file2. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0664), archive_entry_mode(ae)); + assertEqualString("bar_encrypted.txt", archive_entry_pathname(ae)); + assertEqualInt(1379079565, archive_entry_mtime(ae)); + assertEqualInt(4, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_is_data_encrypted(ae)); + assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); + assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); + assertEqualInt(ARCHIVE_FATAL, archive_read_data(a, buff, sizeof(buff))); + + assertEqualInt(2, archive_file_count(a)); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); + } + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_lzma1.7z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_lzma1.7z.uu new file mode 100644 index 0000000..1ffb08f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_lzma1.7z.uu @@ -0,0 +1,37 @@ +begin 644 test_read_format_7zip_lzma1.7z +M-WJ\KR<<``,/HZGJ9P4```````!,`````````%+Y%"(`*AH(H@+[^>`@;QG5 +M&B5-,5-_QRM0L>#MM0W$-S'BJH_8IY"*#4L;0'F!$MLGK8$6R7(_0JIF4F188LW.NQMITP8HMUWF\XR7X"-6 +M&\D7'8\P-Y0ID%$5:_E*6FTAD,UZ*C8?&[QBA +MQ(`^4DD*>=?33B/"4^$0QU4+CRBV<#Q%I'ES]CDV4..(`?$2ZB3)Y9=*8YWP +MKD55I7'(RB6:N.K<<#K;4`K?8S5S74$=%X:A@F!?`%"G+4V*7>T.:+#D%NX- +MO"&K@R&0W=5=#NWE4]:?]-1"<@XD,`PD^@*?QWL.PCMHD':HB^7%580>+:B: +MO-PW#(>)-?"@^,U>D1Y=!9F0\6.0SH[GLR.<#T"+F'3+T``?$Z)4;/6X\AS`:@KC>Q'$IU70=EY/" +MI070FD?O5Z0^K4N`T=F%GBW`6JH+RR8H+@R/JYB?/IC01HJV+DQI**WD\"]) +MFE)I[P]9(OI08OF3`L#+:(H)F&6Q[Y+0GKAC:L!I6*NP(+ALQC@TQ[ALSYJ] +M1B`"6XJH3U%?E3+DA&F$]B0PH*]BYZ%_(8.P1]C1PODZCT1OR.:UM>7>W);S +M5IG800B9F[_=KY9L->M0JZ'C$?"&8X]Q+FU)*)I]F=ZH:2:[\.>OAP1IS +MS/%E3R69K`@/-\N#`"&QKEICZ;24_0BUA0CAEC&AHVWNM5/^CN&0 +MI;+M\"W1W@6-<,_&_OFGHG!&G+9(RA+9>OS697XLAU-((X>LQ^ZVT@F40:88 +MKTV4E(**WG*)U$-F%DT:#XT"I%>D3H<&/>)9Z8C%7 +MQ^#L9(.[[6#NB@B3J2('BE5;T*DM[/[UM+[O:MO6H_/>I=T]Q.)Y``#%>W!N +MA0,"RXLKB"M\7A$C!/;J+>F.U)D&3*>[=BTFB#4""R:)G=90L/;3[OZ\\5C%]"RAMQM_U,38(.3V- +MY[%HZO,JYWMJ="AK?7_"$8PI_US?N!%-+/2&VP13 +MKI2,&K,>[J2_X%LN:)1"&*"R(U[4$O._I5^`W +M0Y9^ZD6\Z7$!@B4T77'F +M$\[ZG7\FM@"?`-[S"MF4PY^:C$H!!`8``0F%9P`'"P$``2,#`0$%70```0`, +MBQP`"`H!Y1S\W0``!0$1#0!F`&D`;`!E`#$````4"@$`@/>FPNRIS`$5!@$` +&(("D@0`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_lzma1_2.7z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_lzma1_2.7z.uu new file mode 100644 index 0000000..70b03bd --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_lzma1_2.7z.uu @@ -0,0 +1,8 @@ +begin 644 test_read_format_7zip_lzma1_2.7z +M-WJ\KR<<``-GH*;IF@`````````B`````````--W(LL`,.P]5,<,713`O:V< +M)`.JE)L$6^G@````@3,'K@_/;NZ,!\A#@(.!6_^L@!U0&A2&3>R/[PWL=[H6 +MI6B>-7,"LEFSPJXL&_5`VI+39=)!5AVU_MRZJ-'/$T<4 +M$.`BV?:<->IQ$-K,-DX=!*T>*)Q&M+J="/NB=:8'E1X3/?KZT!XEN'99V!2D +HL??E````%P87`0F`@P`'"P$``2,#`0$%70`0```,@,@*`<_EW0D````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_lzma1_lzma2.7z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_lzma1_lzma2.7z.uu new file mode 100644 index 0000000..4de527e --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_7zip_lzma1_lzma2.7z.uu @@ -0,0 +1,10 @@ +begin 644 test_read_format_7zip_lzma1_lzma2.7z +M-WJ\KR<<``.;^9[-V0`````````B``````````(\.`H`,.P]5,<,713`O:V< +M)`.JE)L$6^G@`.``@0`670`P[#U4QPQ=%,"]K9PD`ZJ4FP1;Z>``````@3,' +MKC&9Q;Z1",.ZTR=H7?D(*P-]#*^T-I.U$V\S<> +MW,KQ]&30$$K2G.A@ZB\TJ2%=E9LVPJES']:2`CL-F<22BZ>*M00K1&/TM`@;QG5&B5-,5-_QRM0L>#MM0W$-S'BJH_8IY"*#4L;0'F!$MLGK8$6R7(_0JIF4F188LW.NQMITP8HMUWF +M\XR7X"-6&\D7'8\P-Y0ID%$5:_E*6FTAD,UZ* +MC8?&[QBAQ(`^4DD*>=?33B/"4^$0QU4+CRBV<#Q%I'ES]CDV4..(`?$2ZB3) +MY9=*8YWPKD55I7'(RB6:N.K<<#K;4`K?8S5S74$=%X:A@F!?`%"G+4V*7>T. +M:+#D%NX-O"&K@R&0W=5=#NWE4]:?]-1"<@XD,`PD^@*?QWL.PCMHD':HB^7% +M580>+:B:O-PW#(>)-?"@^,U>D1Y=!9F0\6.0SH[GLR.<#T"+F'3+T``?$Z)4;/6X\AS`:@KC>Q'$I +MU70=EY/"I070FD?O5Z0^K4N`T=F%GBW`6JH+RR8H+@R/JYB?/IC01HJV+DQI +M**WD\"])FE)I[P]9(OI08OF3`L#+:(H)F&6Q[Y+0GKAC:L!I6*NP(+ALQC@T +MQ[ALSYJ]1B`"6XJH3U%?E3+DA&F$]B0PH*]BYZ%_(8.P1]C1PODZCT1OR.:U +MM>7>W);S5IG800B9F[_=KY9L->M0JZ'C$?"&8X]Q+FU)*)I]F=ZH:2:[\ +M.>OAP1ISS/%E3R69K`@/-\N#`"&QKEICZ;24_0BUA0CAEC&AHVWN +MM5/^CN&0I;+M\"W1W@6-<,_&_OFGHG!&G+9(RA+9>OS697XLAU-((X>LQ^ZV +MT@F40:88KTV4E(**WG*)U$-F%DT:#XT"I%>D3H<&/ +M>)9Z8C%7Q^#L9(.[[6#NB@B3J2('BE5;T*DM[/[UM+[O:MO6H_/>I=T]Q.)Y +M``#%>W!NA0,"RXLKB"M\7A$C!/;J+>F.U)D&3*>[=BTFB#4""R:)G=90L/;3 +M[OZ\\5C%]"RAMQM_U +M,38(.3V-Y[%HZO,JYWMJ="AK?7_"$8PI_US?N!%-+/2&VP13 +MKI2,&K,>[J2_X%LN:)1"&*"R(U[4$ +MO._I5^`W0Y9^ZD6\Z7$! +M@B4T77'F$\[ZG7\FM@"?`-[S"MF4PY^:C$H``00&``$)A6X`!PL!``$A(0$( +M#(L<``@*`>4<_-T```4!$0T`9@!I`&P`90`Q````%`H!`(#WIL+LJ7ZI7Y%&2NU]#ACBW?#O?,F:0#Q9-3ZZL%V%&9)")/O0#;Y`ERR*'#+W +M']$)-E\['NQ`D+7V<4:'4&A)RGS'C>O$2723_A19>9;,$\2C0JSF4UU1"T(U_'3]MZO4WCT/KJ!WNF7\9M> +M2GXEEV9?@RB[9!KSM8!+'_BZX-=+ZQ1=P9AK2U;$U,*>;OX +M0@8/5\`&O3SX0XVTNXGBYWV3][>(89;V#5^B(ACH].`\.-`]#JV +MHNC>TVUX7KVNCA.$;7;W.='`FN@O/(`Y]AZI0RE\93@;9W+HV5&%]I;G>GYM +MI16P"$LPQ&GJL'4'2!:_9C9;<>&"`IM1Q`FND+]]7G4"<0;=..Z_B#^JL(X +M2K!SX%3;4[HJF:50YAG;(F)YR\%_Z=P9PR]DD].*[V5GCWK+\0"PW9=6;PI< +M/"P0T.4O-3K1JV[F=R;7WK]AX:?IS^*O)8`8M^1OM^"SPN97L#JY27PRN?'7 +M+I?=AF\-5G?_6`!]P/J8GJPX'D8.%?:+BW?;LQQ&0TR=//LV*B#.`D*=/,$M +M+M7`:BR$9OJ(R>W5(G]52E%MT9EO:`P.5O%)]I?41B3FK-7XP=/H%%3>^E80 +MT?LM@9V`^ANS95,LQ*9V()?@7I+0.^E]41$[("M"KF,FCZ;0G"J&FSTP'L8G +MNE8*QAE^PQ/!DZ`J?4&PU:(Q!B<,:8B>\$EC8V:$?SS@W-,QILBTWA:#1TF0K(\L*,>S +M+OS8S*UWK;Q]5`+,A8T1MG5(S&EP]C3,T*3KBOL+_4B6502_0D;R5ZW&6M=] +M[-/6Z^@?ZV**CE08_T(K$LJ-:&^3_^AU,8HKMJ;FUD+;MO\MA[K94?PH\QFZ +MVXDVU;ZL^QXG=8TV&.(^VX7:(FM_$AN[UVG$@^FF5,/\J:U[=SQ?P`]F]VO4 +MLDRP[_BGA"H#QT!6QKVMG<@UWAB"GT<_\E^K0[)J7YIK#J4!H0])7GU,XPYZ3_=BO4/HO,@/H53SID +M5?H$8$_JYJU<[WO_`([=&L##U@@&TSG]TO&PL1-KZC`Z-3/23")$^!&'A8M^ +M$;)#(-PGSS20[90Y0-2/=W+14Z2K[0>`L$==*1#1)I$J-O(;S%"9W4>N0.L1 +MG:FOM4(SY*&HUF)'U^^0=JKX4`9U:#("A_ZTG85E"A\JA$!4&F9I%A8.S5:*[T+`TJC8U.4][SP-6"DX/&8)42:!6A>)>2\%O +M;K5>3\@H=I@JO9J=SQ_ELQX"=6+3191GS[K2$-,M=`$(R!O)G]U&GKPTY9-H +M\M-BUW4G0;.GV2LB\85M;0,$`73VZD5N9F5Y5TA&TTG-H4)!K._H0SL^R7)?E$@ +MMT3WC0WZ8>%+K-/&F$`0X>8J&FXK4S=#:<\@;*_&P"$I+*^X"H"D5K-OWH,& +MRD%P6`GJ2M!]_<%EUB`,ZCY=#W8$FA(D'ZZ>:79YF)FY12ZJ5_`[8;6DH6+GW'+!Y,DE'/:@ +MR45)C`>>/6O3+9.GWKN1K$;HH+*;XJY-S60TGB;[Q5O652H+2_8@[+,`]`W0UDAT^NDY9DCXF\]*?MV>KY0^( +M1.)H'^I9R/DH:WZ>'Q.'DY/IV\/BV<)AX,!@?'P +MOGPQ,EPCA9>^Q(:L1`81]IXY.E#ZC)@K/3RJFFY.&I&STW.B4!&HS$U";4($ +MM]05YW/AYKDSNKUGNX^/?M)<$&FA=Z.YS-7H;PKL`,8X,<7\:O@CK(:9HB9<3/QJ?:3;[YA"D0G`HI1^='!@:)+Z)H6%5U+>%?@V:/:TG=O:RZK\-DO2 +MO\"SNRHQ$9?O#E@F)?X(R&@WX+[U!TN7RS,,W*_.\2ZV7UJU*(_;-T<^?*;D +ME$0:8G[&U!^US'W"SZF;&+E6UW8)^5(_<+!_[W1?5W2X)@2>(AO*&)J$XQI6 +M\%]WJ2*.9$M0))3G!\6:P9>5=Q6T09C@-OE:H!8(+S8G.,'-#N77=8$Q4.6@ +M\I0>B728L0]O^0JWF3XI'=4:9VY3*2Z[Z=4;3=[$QSBEZG6GV@QLH-V1,:@0 +M5L/`VG+1RZYA&?>@Z4!=T/Q/B&G@M`PG\M5#?!%X8:JMV%3ZU2,Z6^,GU#!0 +M:X+)+MM[SDL]R\U!S%SA(ZG*EU<)_/OGA-&^6:<^7%-#R,\L5_F+H0UB!_V]T+NC*%X_BR_X_R,EV>K&.F@@8HC%F\ZK[?+*UC"!, +M3HEW+2^'4B#B@,-#^[$U]X\$RB??28MPX6M.D_1+@!XK*C&241F6>"]](:7%$J-59U&IAX.*F&1N\P`5!&T`D(V$8TJ1(+CJWJW:98B* +M%N2<7<`YY_?7=#^,DZBE%S$.=-L0DKTK+T+KV>YC5C">Q=_]U<'K,3((%JQ] +M6K8.C\2&%$:-X-[H;WK>"%EKNFJO5/B!4\7KAI]'^2U.C((O,J&$>%9U/)3: +M7=`G_3BY[&F4W67V&3R5:?141*6"^>ULO9J`HW>GCN +M;)`ZF-^-+Y#;4R^,#8IG@MNCW[WA[KKKJ7Z.S3WK)J;>Y4X/$OMA6&249PSE +M^"M;RXH0B_\_)ZV"[8)]T(1M&MX.6IB2BJ%%#00"',25?S9>3$@(0W!V@ZA& +M(U$6<+YK#]AD3L +M=J.090H:E5RZF`7M3OZN)T%T\*T\MY"OZ_B'[&1.=R.@LQPZ>-(P/T['BO&C +M3>(:C,4:2UNFZ&2M]P)IOLJBX;C#)PY5G*=JPAXXVZCCOKL6*<0QZPUK\0O_ +M_\%0,@`NW>`(!9CQT6QWM9%_,K(5H]K"DLRUW56EY-+M7K`ECGQ/E&0P7!&V +M)&PZD11#0OB)^7,=@PZ'")M`D%F'8Y8^LY3<+8)/=PY="BQL[W:U&9&]HP$3 +M<+<^=.M]@J:K&8I?EDQYF;"SC/Q#T +M;(\]9H"Z.E%Q.6LUCT$8$B6^L1O1.P.X/#C!-R_BQ:+[C:+&.^T:FN'F[-/10^_VKQ^ +M2V!9RX9'T@U_+`5@4AYNP%$:,^?"84J\6$'IT<[E7PHPZB*3@8&MJ\E(:AUO +MILUW\77FA!2GGT!A9QAP5*S?1>0/2Y[5>,$2E+Y?W=5[NGFTF#28[=0RAF:$ +MH+3.]HYS!!ZMS,M7BKNDQ0%UWYR7`IS"(Z@`)X;HU)VR,"[Q1B&IYPYY'FI!WPTX1KC9\F/@`.\4AZ\.J +MIJB5X[OAXTR)%2:866ENQIG+="3MFC9S?7H1;)$>1"AX=MUY+AJ=ZV2Y6X/O +MH(1W@_X93V#':UY88;]^RO&-0-MNPB_F+C;+L7R:7:Y^"-M.'`Y;N0(10J`I +MZ,A`AD&#@S!5[ZHL$)P!*4,N/;$, +MIQ4@7Q6`H`8W=EIG#=QJ-Q^34O=@Y*%7BS +M!1AR7N:EC=J1(B#G4FX7.IUP"-E6T\X:*@R1K`W'=?,6KYC*'E +M.IDQ>6LVPZ/B+(#%M]/85)2/X26+#7ZCO:P8\EG-$1MK4_Y$G8/0IRVTER6+ +M;S(((YITJ1G#`$=4QRGZ`#Q3#6J9T)WOIBR`^\B7V>-V0Q=@5Q7USCI>E/J& +M-Y&IRT*%>$BL233JUBR[.B,J_)O]459@@2XP.)D`M)_D\6F]!YCEA]D^RI?0 +M<^L^?"1$;WW>\D,MO+H2ZK3WC&O<+BCWXNG/2/-`R<`>MO1-HP5?,4.V&&;E +MKE4B('N!YFR_IC:#)W$4AFE+\)WSJZUN_/;0(6`C0T\.O9Q2-Y'H`,0F/3SM +M@XUA1H.!\HP:JK^-Q:P`NM*53:KPP^!7A[DDSN":ZO=&Z'X\4[C):T`TL*+@ +M6#RD3[9.T"-B//%BO6EAV=DW^CRB"6+AIYW+TS=/+I;74V*$MQ;WC`G(/Y7W +MTS94=V\N[31FJZPE]S$4S;^(?*I]5S9,R%<60(^DJN!"]VD^!-$?Z=TD/2LUA*]* +M9H2O\_'4&-"`II"M!ERA'!Z]*$"K>\*(ARO@B?5 +MHMQ/)H+8>_"*MM@%WB7E0ND>PP(NL4^)2W3W<&=VN#VQ2\JHCFSYVP_F," +M+81Q60"2:9ONC?@T?%3V_N!6/SE[-XA)9BSH#`MFW+I-H$R]C12K>@+$V!)& +M_MPZV\9#N8:::EZ_Z1F";.7(8^8F%=2?[N71\Y6*@H+J(:G?J3NBO +MWOG?TV+H:Z9?DVX^![.*`V3 +MD?#+J.$<%?&,ZY'[@+8IO\-FL;\-!`_(F6+RFKG2B'PB-W +M.V#0KCHO[4/E0.E)XF/7AG9F0LH0(#!5/N3:4G[)=-:*7?*M*=06)R3UIJ<* +MPE,M%TFHW8\T>KJK'.R!HVY([)*CA94(@FL]^!B";$<\'DL86J<4&>V%ZS2D +M^\HZ_)I.GU;GN+/1ZXCARQ'KOE&QT+>V +M.>Q\!JEH8>G\/F(*4J2-GM?YB"U*]QPG3GJQN)R=Y,Q;J'O9-2$!!]N*H0*]@#H1-M]=:GO)A&'DVPQ4EO:P!S#A +M$3Y@\N"22\L4BHTQ#%SV1*'82BRBI`ZPV&'2ND7%BR_03SPLK!LZL*2AV6UT +MR7XV:E.(J"2['_CQ$0WG"/%F7+4DO4YPERJ!L*`?7'3&DI=`:4]X)P2Y!5N19V@W1@RI+:?DA$[SZ$XU180.AP%J4DI25";F-9?M].(-_G=*@<0V1 +M.BZUN.N4ZR:26"=<4LV125$XYQD)[YH*K\.>QF>)^!2C5MKE\JRV^.&B;)MK +MK$C'$9Q_-GPH)OKUM&D.J!0;9AC>Q[HFF_,DH,8CD4H][4;QZ_US//J<%W3Y +M[?@#@8G(.M<_ZG_&INAV`5"U@,")`,QZ\`!D#G*0M\NEIW9%)Z\'/LQ=9RAJ +ML)DXC+G.4"$WO<@A_)=YT]^MF^<\XB/$''DI\/JBL%9JMXCI@F\1\Z]ZG@LS +MB/2E,6"(8LYA#+S!+]R_9!!KTKT6D\KM;\_6_G`>Y5A,&AX*,6+#2 +M8=E?W0W?L4.W/W8``N;-Q>+^A0>D_178*1K[_*);FB_[2L-LO015#FZ[T-\# +MW_>5$\_74TF"\._*4KYY'^5)6+^%;&H>X"-I3![@`BFC)MP@8P&9(]'90_R8 +MK\R?>3EI*N0V)48'1)`[Q;*M^B%//-IX;>DM%_E"MB,\L;O2'#2,DZDM:$$4 +M7^W_()&D5+@>H0O""/^UC,IE46^8""5EU`2?5;UOG+363+.E;6G'#]A*OG61 +MP:$B2[.G:4.QH)BHW]('32(N+6!L-A,>&S^+X,]AC<,YN5M[WY1O_(.3/C^M +M_B0$87M:'COA"AIH!"6F7^`[&X41>313D.W_)"0&#!^Q./U_)R[*"@LFF.NF +MI#`($"-E;+\,EN^]P>L3#B`'WP3]1(@R +M6ER+JS&TWD#(\=WRE_5A)(=I.(<%71X'J6T_P51X937/`1]V;8T^PTI#T]S2 +M"+,OM[,0:KK,CS+Y%61W^5/,CL3#65X&NHX4SDPKG/F0NDKOK@0MJ7JG9!+E +M-Q7_@NYQX0O9/JX3"$D+.QU.$W4^&"]XY7$B0VT)2)3[C&@F:#S5]9:>D#&^ +M0KK775&&30U"RZNV]=9VHPHDQ&R[SC#\0+:@'69V#3MK"RX*E]/*@Y?E%C8/ +MO(`TF=1?2T([+H+%END]W+ZGX:MJ(FNTKLEB.?,G)SV?EU@9#SEGLMYK4`^&M\I)[!"K&&BQ4# +MI>RRF#&&$&:B[2&V$)T/"13]K[S[(=6M(\(IC2/$"WL)#SCHZHYU_`.W*K%> +M=KUGCX<1P^;7]?VZLL/8UK)R_M%?-]%CNF:BU-?G<;M?D+VN=,:?*RPR6`LD +M00X"Q=2Q.H1HM`**BRU_.>D'7ZRK*%*OW:/\)9K\,``JEK.,@AJ[SS+=/F`# +MU0MF.G#VRVOR_K$T%0DCS`1[/:H$X!_`&W/B1._K+-3`V:%7&&QZ`@7[EP$) +M1W%6<_KO.-`OE3\93:R2Q8H;`I^W=F@PQY_N@Z,]#3E+G=/:,0U;3ZYH!L]IQ1+ACK[5&F)5OD\V6.7O6Y.+3>/(I#J^ +MW82,N>24#>"R^'CR?/TP/'M#+&OAAA#O^6ZBZW;_8-04,E<4C9BL)/LS>JF1 +MAXA)`#^D&A,)8-JQ.K0()@5XV_9C0;Z2K1RT`.:PY/DMBM.?./O.%ARB;4Q$(";3(< +M*'#]FG?/11A&9WK;\&L,OZ>`ZN=!)E:8N)9:DGICN\FO;6`P\Y?@Y7E)97VW +M8-V="CWTR=M$X,IT7_O:\_I/#8Q>%6@%]#*6O=@^CQ8]\">+`I?_XLHXY8.;2H6X\W_]Q:@Z_[-&7 +MN)8:KT,Q^1XL-[X@`:91T`+3)V>0]`-GK3(8(3[".L)LUK!9U3[EOYFX,"=5 +MU2N[-?:4%M^WD_(2Q;[O&G'D=)@U0WJ!8O7,ISNMH6_4W;74(\D(EMJ(2Z2? +MKG"?M]JFR]*V&[!NAT]]/@84P%2R6KZQU39A=K'\8(#G#]VA##^,Y*T?(%E^ +M$ZAO:-E[CX`@Y_*[M\HD8_#"5QJY'GX8)H\H+OJ`U:(X)HRN*?)V7]YZN`JE +M?B/"=_APG@NXPU']%29T8)XVJ=U+0M3//`56K@_?U(8ATY0$(#%27]'JR)W^ +M10M=)W>PFM&@:0%Z%<<:''[="W2YR[=A>91]\'8E\#L_9`^#@JO\-.2%*$7F +MR-GIPED#8E""_`1K/=5;8Z?;.?0[UJ.G[+J6=`1E'YD72KS5M +M/O77V_O/E&(L?K!W/%%*N="4MC+M8>B<`WS)LOLN*&5!0J+2*PV(.SP@2+M7 +M8>LL8'#VBFY!?2DT'D(;0?]8SX@271HQB@`A`$'ZBHU+&L&[C1XM#AT9RJ13 +M"0!_ON:H\4YQ>^7TBQ9(]X:#F?80TTB=O3_W>C\9X4=E@%U6Q&^94'J@4Q:1C6*>O.F=Z/'M=HG0!_.S]$DO()[7"9A*D+M7>>9FM-V@3G4T-2 +MRY1:ZCU<.]^/U@(!BG49OL_V&@4I&S#8M%TF+?2R*]')065)K%A.[_7)K+<0 +M`?$ZY=4+B6U]*0Z$D:ATPIBR[,5H3;I7Z#5YAXR9&E*MR>DSI[1%\WS]N"LS+W?:5P"=U5/*,LSVJ +M;)8C"[5)-^36`=2MA\W[L9G'6ON9U#W)_+AU9E\=Z69.\5JC7-QISP(./D$( +MJ+MH`5+U)^,])Z]92SFI:(6@MU17,`K30$V<8>*'8N,@XI/599 +M12JJT9:&W"\60UZ9.2`J;(V]"409D%531E=A"DJ4^H=%*)8N\6@;/.;CYF=1 +MMHBVQ0,2M.\;$._4)72,K17B!:=2<)HOC#/8ZG"G9?KH?M^\%Y8>'$]LZ$") +MG54$P"D)4X4K/OT,"ID5'\CMGW4^9N@V,),;L75.TVR?OS8)-\A6<=(JI0R# +ML:WTK>.1T-<,BSR+]5CWNI%3+1GJ;G0.'H\R8)4;_F/N+AJ+(_$NQI?B#"8F +M!WEMDH.WM3MD<^.Z82;7FL<%.B:XPZV):]PO6?(Y7)DV$'&&()N(U4ZUGX=E +MRJ&/-+K7\\(?UXZB1^2-_O=`77U'H:)@3Z3;8@F?*_7H3I9T"&P*/>A"%8B! +MAD#`53B*OW4^\1+I$RF3V!Q`.^2]Z"H8Q1F#-44CRN3IZO== +MA`Q]F"6Q((#H7V^6Y5#@AQ=D7D6[W]LQ +M(K:P.IZK:P4:SUGP^TP>5!7>*?X:/A8J4?9+SO.P79>LX)5W.GE!S"\1ZS2J +MU'$,XZ3E2R#@_^X8E.E-_$EM4.>3$5:3P +MS/>@A%K,_XH:DA8D^;["<7GL/X!A=,0M>"PE'41++V?8:4MV'=ZJ>RBLQWJV +M2^,-?N$V>1II'ZE-U"^O+0#NP-1W0$,@C?NR%/T +MR@DA=EJ&";[3A%>CWM:P4\&PN*U/M6\?:GE%09*3:$Q#S=W>.6TZ7VZK+^5C +M%5RG*B9^'D,D)5\DK&]"%^B>V(N4R$1]SV76;.AU4K;G450JS>"UBI4EKH1L:S5\ +M^,!G;60:&\'O,C51<1)4V,06GE3U/8;0V7T`>\5N[N7UGX$XREJ"NWH3UC`V +M%)GF$O@_097?T^4FT@REC09*7W-T-2BV9DW+WD^V_%C*O&!L[3(,T<*(,CWT +MH3-`3152[H8;@*.R:W%%UP%$].\:2#5`N#1NCSJ8/1T`17M\1V(3,#0TU:A+ +M,<>JR\_2KW12B;.-XSK$BKCGC``F9(O;M$JL`WEEHJJ9_$<@ +M%BUO[>[X/-45/*\'J@/:Q>[TXZ9U^?[WO/&T\SLLS4634>9J&DFW,C$T`W\5 +M*6J"W%)D?+3OU5+QA/KFY3MVQ5\1`8/?!X[>%:3M:)0#)]P.[GN]R8P5AI4# +MF07/@R/"='NQ%8EZ;Q?^HM4+LZNI:R2^8@\A&!G +MQ%CB?!-?M'4^J5V/P? +MMU<$MB[*VB/T3>>[L^O5U/%B^"=\/D:AP\`N@HHUY)Y_HI'#Z1^!`>(-YU6% +M?_]961-](1[TW$1;,U_"<;C->,J>P\;9/Q +M&0'TJ(['HC,(':B#!?EXMF#`'8F9`^,_792<[Z-0%^<[+V8R\5J?E7X$G$&[ +M=6\")WT3#O#]\;CA-J$Y+Y96(\EQ,[Y+F?"6NLA_JI:L<]'?*9$2>NF9@JM* +M(.9BKON1U5)>*#B,*S$6_>4M7JXAH"*1?_O-9)-(F7[]=1-+,?32T7X?2J#S +MO=/W2Q6HE"4^(//X.O?]4^/@BF6V4KH23"Q&W)77#[80[P&V@+5L6Q;5(=:J +M!R('TLUU0)E>\K=6#=[5"\ +MTB*Z%,8CX*91/:YBH`EHRFLYM$#?)7#Y4$-!&I?`"%&_^LYV4!G(=&P\E']0 +M(IX*?@@!4"A]9\(R+2XD8'\Z]& +MB4[&P:KQ[S<@#D/A!%X[Y;.LCOS)A6/!'Z+!^K7..?/?"W\4?E`]ZIV>2KW, +M(K$BH$`3ZIVD_"$+\<54Q26(`=;XH0!3Z;:S=[J8WN(>G*]NR0M#?%GM8Z15 +MND(="&^?@7D!6+%G+&@P<2\<9FG!Q$-=,8JNJLU[W\:`)T:3BW0N[-8M9,BG +MUW3D#E4F^R72`=T#>;MMPO!S0$SY,Z?T\1?+ZSE/ZK/F'4%=T.1"*'QTMN.% +MOPQ8CL%)?L::N$C=VFTB%^PJM:0U +MCS@"\\)!_,H):(W"QLN;,91S8MQL+?;XRI$.,D8RVN`_EF$FSNFBIA*Z3.33 +M.R0/]13X``$$!@`!":@H``<+`0`!(P,$`04&`````0S!`)``"`H!]R-)#P`` +M!0$1'0!P`'``;0!D`%\`=`!E`',`=``N`'0`>`!T````%`H!`+%6SZ6=KN#\\G\(P'R$.`@X%;_ZR`'5`:`Y&`K7JS*U;!.)J3]3@J +M?#'*:Z""L7Y*%Z9?L#^PQL3)[(BVML.S!-[#M+-]`7ET='1S test_read_format_cab_1.cab.uu + uuencode test_read_format_cab_2.cab test_read_format_cab_2.cab > test_read_format_cab_2.cab.uu + uuencode test_read_format_cab_3.cab test_read_format_cab_3.cab > test_read_format_cab_3.cab.uu + +#!/bin/sh +# +# How to make test data. +# +# Temporary directory. +base=/tmp/cab +# Owner id +owner=1001 +# Group id +group=1001 +# +# Make contents of a cabinet file. +# +rm -rf ${base} +mkdir ${base} +mkdir ${base}/dir1 +mkdir ${base}/dir2 +# +touch ${base}/empty +cat > ${base}/dir1/file1 << END + file 1 contents +hello +hello +hello +END +# +cat > ${base}/dir2/file2 << END + file 2 contents +hello +hello +hello +hello +hello +hello +END +# +dd if=/dev/zero of=${base}/zero bs=1 count=33000 > /dev/null 2>&1 +# +cab1=test_read_format_cab_1.cab +cab2=test_read_format_cab_2.cab +cab3=test_read_format_cab_3.cab +# +# +cat > ${base}/mkcab1 << END +.Set Compress=OFF +.Set DiskDirectory1=. +.Set InfDate=1980-01-02 +.Set InfTime=00:00:00 +.Set CabinetName1=${cab1} +empty +.Set DestinationDir=dir1 +dir1/file1 +.Set DestinationDir=dir2 +dir2/file2 +END +# +cat > ${base}/mkcab2 << END +.Set CompressionType=MSZIP +.Set DiskDirectory1=. +.Set InfDate=1980-01-02 +.Set InfTime=00:00:00 +.Set CabinetName1=${cab2} +empty +zero +.Set DestinationDir=dir1 +dir1/file1 +.Set DestinationDir=dir2 +dir2/file2 +END +# +cat > ${base}/mkcab3 << END +.Set CompressionType=LZX +.Set DiskDirectory1=. +.Set InfDate=1980-01-02 +.Set InfTime=00:00:00 +.Set CabinetName1=${cab3} +empty +zero +.Set DestinationDir=dir1 +dir1/file1 +.Set DestinationDir=dir2 +dir2/file2 +END +# +cat > ${base}/mkcab4 << END +.Set CompressionType=MSZIP +.Set DiskDirectory1=. +.Set CabinetName1=test.cab +${cab1} +${cab2} +${cab3} +END +# +cat > ${base}/cab.bat << END +makecab.exe /F mkcab1 +makecab.exe /F mkcab2 +makecab.exe /F mkcab3 +makecab.exe /F mkcab4 +del setup.inf setup.rpt +del empty zero dir1\file1 dir2\file2 mkcab1 mkcab2 mkcab3 mkcab4 +del ${cab1} ${cab2} ${cab3} +rmdir dir1 dir2 +END +# +f=cab.zip +(cd ${base}; zip -q -c $f empty zero dir1/file1 dir2/file2 mkcab1 mkcab2 mkcab3 mkcab4 cab.bat) +# +exit 1 +*/ + +static const char file1[] = { +" file 1 contents\n" +"hello\n" +"hello\n" +"hello\n" +}; +#define file1_size (sizeof(file1)-1) +static const char file2[] = { +" file 2 contents\n" +"hello\n" +"hello\n" +"hello\n" +"hello\n" +"hello\n" +"hello\n" +}; +#define file2_size (sizeof(file2)-1) + +enum comp_type { + STORE = 0, + MSZIP, + LZX +}; +static void +verify(const char *refname, enum comp_type comp) +{ + struct archive_entry *ae; + struct archive *a; + char buff[128]; + char zero[128]; + size_t s; + + memset(zero, 0, sizeof(zero)); + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular empty. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae)); + assertEqualString("empty", archive_entry_pathname(ae)); + assertEqualInt(0, archive_entry_uid(ae)); + assertEqualInt(0, archive_entry_gid(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + if (comp != STORE) { + /* Verify regular zero. + * Maximum CFDATA size is 32768, so we need over 32768 bytes + * file to check if we properly handle multiple CFDATA. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae)); + assertEqualString("zero", archive_entry_pathname(ae)); + assertEqualInt(0, archive_entry_uid(ae)); + assertEqualInt(0, archive_entry_gid(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualInt(33000, archive_entry_size(ae)); + for (s = 0; s + sizeof(buff) < 33000; s+= sizeof(buff)) { + ssize_t rsize = archive_read_data(a, buff, sizeof(buff)); + if (comp == MSZIP && rsize == ARCHIVE_FATAL && archive_zlib_version() == NULL) { + skipping("Skipping CAB format(MSZIP) check: %s", + archive_error_string(a)); + goto finish; + } + assertEqualInt(sizeof(buff), rsize); + assertEqualMem(buff, zero, sizeof(buff)); + } + assertEqualInt(33000 - s, archive_read_data(a, buff, 33000 - s)); + assertEqualMem(buff, zero, 33000 - s); + } + + /* Verify regular file1. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae)); + assertEqualString("dir1/file1", archive_entry_pathname(ae)); + assertEqualInt(0, archive_entry_uid(ae)); + assertEqualInt(0, archive_entry_gid(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualInt(file1_size, archive_entry_size(ae)); + assertEqualInt(file1_size, archive_read_data(a, buff, file1_size)); + assertEqualMem(buff, file1, file1_size); + + /* Verify regular file2. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae)); + assertEqualString("dir2/file2", archive_entry_pathname(ae)); + assertEqualInt(0, archive_entry_uid(ae)); + assertEqualInt(0, archive_entry_gid(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualInt(file2_size, archive_entry_size(ae)); + assertEqualInt(file2_size, archive_read_data(a, buff, file2_size)); + assertEqualMem(buff, file2, file2_size); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + if (comp != STORE) { + assertEqualInt(4, archive_file_count(a)); + } else { + assertEqualInt(3, archive_file_count(a)); + } + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a)); + + /* Close the archive. */ +finish: + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +/* + * Skip beginning files and Read the last file. + */ +static void +verify2(const char *refname, enum comp_type comp) +{ + struct archive_entry *ae; + struct archive *a; + char buff[128]; + char zero[128]; + + if (comp == MSZIP && archive_zlib_version() == NULL) { + skipping("Skipping CAB format(MSZIP) check for %s", + refname); + return; + } + memset(zero, 0, sizeof(zero)); + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular empty. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + if (comp != STORE) { + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + } + /* Verify regular file1. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify regular file2. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae)); + assertEqualString("dir2/file2", archive_entry_pathname(ae)); + assertEqualInt(0, archive_entry_uid(ae)); + assertEqualInt(0, archive_entry_gid(ae)); + assertEqualInt(file2_size, archive_entry_size(ae)); + assertEqualInt(file2_size, archive_read_data(a, buff, file2_size)); + assertEqualMem(buff, file2, file2_size); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + if (comp != STORE) { + assertEqualInt(4, archive_file_count(a)); + } else { + assertEqualInt(3, archive_file_count(a)); + } + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +/* + * Skip all file like 'bsdtar tvf foo.cab'. + */ +static void +verify3(const char *refname, enum comp_type comp) +{ + struct archive_entry *ae; + struct archive *a; + char zero[128]; + + memset(zero, 0, sizeof(zero)); + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular empty. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + if (comp != STORE) { + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + } + /* Verify regular file1. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify regular file2. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + if (comp != STORE) { + assertEqualInt(4, archive_file_count(a)); + } else { + assertEqualInt(3, archive_file_count(a)); + } + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_cab) +{ + /* Verify Cabinet file in no compression. */ + verify("test_read_format_cab_1.cab", STORE); + verify2("test_read_format_cab_1.cab", STORE); + verify3("test_read_format_cab_1.cab", STORE); + /* Verify Cabinet file in MSZIP. */ + verify("test_read_format_cab_2.cab", MSZIP); + verify2("test_read_format_cab_2.cab", MSZIP); + verify3("test_read_format_cab_2.cab", MSZIP); + /* Verify Cabinet file in LZX. */ + verify("test_read_format_cab_3.cab", LZX); + verify2("test_read_format_cab_3.cab", LZX); + verify3("test_read_format_cab_3.cab", LZX); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cab_1.cab.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cab_1.cab.uu new file mode 100644 index 0000000..bc6ab41 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cab_1.cab.uu @@ -0,0 +1,9 @@ +begin 644 test_read_format_cab_1.cab +M35-#1@`````*`0```````"P``````````P$!``,```!K"0``>`````$````` +M````````````D3U&I2``96UP='D`/````````````)$]1J4@`&1I + +static void +test_read_format_cab_filename_CP932_eucJP(const char *refname) +{ + struct archive *a; + struct archive_entry *ae; + + /* + * Read CAB filename in ja_JP.eucJP with "hdrcharset=CP932" option. + */ + if (NULL == setlocale(LC_ALL, "ja_JP.eucJP")) { + skipping("ja_JP.eucJP locale not available on this system."); + return; + } + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=CP932")) { + skipping("This system cannot convert character-set" + " from CP932 to eucJP."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString( + "\xc9\xbd\xa4\xc0\xa4\xe8\x2f\xb4\xc1\xbb\xfa\x2e\x74\x78\x74", + archive_entry_pathname(ae)); + assertEqualInt(5, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString( + "\xc9\xbd\xa4\xc0\xa4\xe8\x2f\xb0\xec\xcd\xf7\xc9\xbd\x2e\x74\x78\x74", + archive_entry_pathname(ae)); + assertEqualInt(5, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a)); + + /* Close the archive. */ +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +static void +test_read_format_cab_filename_CP932_UTF8(const char *refname) +{ + struct archive *a; + struct archive_entry *ae; + + /* + * Read CAB filename in en_US.UTF-8 with "hdrcharset=CP932" option. + */ + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=CP932")) { + skipping("This system cannot convert character-set" + " from CP932 to UTF-8."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); +#if defined(__APPLE__) + /* Compare NFD string. */ + assertEqualUTF8String( + "\xe8\xa1\xa8\xe3\x81\x9f\xe3\x82\x99\xe3\x82\x88\x2f" + "\xe6\xbc\xa2\xe5\xad\x97\x2e\x74\x78\x74", + archive_entry_pathname(ae)); + assertEqualInt(5, archive_entry_size(ae)); +#else + /* Compare NFC string. */ + assertEqualUTF8String( + "\xe8\xa1\xa8\xe3\x81\xa0\xe3\x82\x88\x2f" + "\xe6\xbc\xa2\xe5\xad\x97\x2e\x74\x78\x74", + archive_entry_pathname(ae)); + assertEqualInt(5, archive_entry_size(ae)); +#endif + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); +#if defined(__APPLE__) + /* Compare NFD string. */ + assertEqualUTF8String( + "\xe8\xa1\xa8\xe3\x81\x9f\xe3\x82\x99\xe3\x82\x88\x2f" + "\xe4\xb8\x80\xe8\xa6\xa7\xe8\xa1\xa8\x2e\x74\x78\x74", + archive_entry_pathname(ae)); +#else + /* Compare NFC string. */ + assertEqualUTF8String( + "\xe8\xa1\xa8\xe3\x81\xa0\xe3\x82\x88\x2f" + "\xe4\xb8\x80\xe8\xa6\xa7\xe8\xa1\xa8\x2e\x74\x78\x74", + archive_entry_pathname(ae)); +#endif + assertEqualInt(5, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a)); + + /* Close the archive. */ +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_cab_filename) +{ + const char *refname = "test_read_format_cab_filename_cp932.cab"; + + extract_reference_file(refname); + test_read_format_cab_filename_CP932_eucJP(refname); + test_read_format_cab_filename_CP932_UTF8(refname); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cab_filename_cp932.cab.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cab_filename_cp932.cab.uu new file mode 100644 index 0000000..0d51f10 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cab_filename_cp932.cab.uu @@ -0,0 +1,7 @@ +begin 644 test_read_format_cab_cp932.cab +M35-#1@````"4`````````"P``````````P$!``(````(_@``;@````$``Q(% +M````````````=#ZO5"``E5R"OH+F7(J_CIHN='AT``4````%``````!T/KM4 +M(`"57(*^@N9 file1 +echo "0123456789abcdef" > file2 +# make afio use a large ASCII header +sudo chown 65536 file2 +find . -name "file[12]" | afio -o sample +od -c sample | sed -E -e "s/^0[0-9]+//;s/^ //;s/( +)([^ ]{1,2})/'\2',/g;s/'\\0'/0/g;/^[*]/d" > test_read_format_cpio_afio.sample.txt +rm -f file1 file2 sample +exit1 +*/ + +static unsigned char archive[] = { +'0','7','0','7','0','7','0','0','0','1','4','3','1','2','5','3', +'2','1','1','0','0','6','4','4','0','0','1','7','5','1','0','0', +'1','7','5','1','0','0','0','0','0','1','0','0','0','0','0','0', +'1','1','3','3','2','2','4','5','0','2','0','0','0','0','0','0', +'6','0','0','0','0','0','0','0','0','0','2','1','f','i','l','e', +'1',0,'0','1','2','3','4','5','6','7','8','9','a','b','c','d', +'e','f','\n','0','7','0','7','2','7','0','0','0','0','0','0','6', +'3','0','0','0','0','0','0','0','0','0','0','0','D','A','A','E', +'6','m','1','0','0','6','4','4','0','0','0','1','0','0','0','0', +'0','0','0','0','0','3','E','9','0','0','0','0','0','0','0','1', +'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0', +'4','B','6','9','4','A','1','0','n','0','0','0','6','0','0','0', +'0','0','0','0','0','s','0','0','0','0','0','0','0','0','0','0', +'0','0','0','0','1','1',':','f','i','l','e','2',0,'0','1','2', +'3','4','5','6','7','8','9','a','b','c','d','e','f','\n','0','7', +'0','7','0','7','0','0','0','0','0','0','0','0','0','0','0','0', +'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0', +'0','0','0','0','0','0','0','1','0','0','0','0','0','0','0','0', +'0','0','0','0','0','0','0','0','0','0','0','0','0','1','3','0', +'0','0','0','0','0','1','1','2','7','3','T','R','A','I','L','E', +'R','!','!','!',0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +}; + +/* + * XXX This must be removed when we use int64_t for uid. + */ +static int +uid_size(void) +{ + return (sizeof(uid_t)); +} + +DEFINE_TEST(test_read_format_cpio_afio) +{ + unsigned char *p; + size_t size; + struct archive_entry *ae; + struct archive *a; + + /* The default block size of afio is 5120. we simulate it */ + size = (sizeof(archive) + 5120 -1 / 5120) * 5120; + assert((p = malloc(size)) != NULL); + if (p == NULL) + return; + memset(p, 0, size); + memcpy(p, archive, sizeof(archive)); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, p, size)); + /* + * First entry is odc format. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(17, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertA(archive_filter_code(a, 0) == ARCHIVE_FILTER_NONE); + assertA(archive_format(a) == ARCHIVE_FORMAT_CPIO_POSIX); + /* + * Second entry is afio large ASCII format. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(17, archive_entry_size(ae)); + if (uid_size() > 4) + assertEqualInt(65536, archive_entry_uid(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertA(archive_filter_code(a, 0) == ARCHIVE_FILTER_NONE); + assertA(archive_format(a) == ARCHIVE_FORMAT_CPIO_AFIO_LARGE); + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + free(p); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin.c new file mode 100644 index 0000000..7b0fad2 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin.c @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/lib/libarchive/test/test_read_format_cpio_bin.c,v 1.2 2008/09/01 05:38:33 kientzle Exp $"); + +static unsigned char archive[] = { +199,'q',21,4,177,'y',237,'A',232,3,232,3,2,0,0,0,'p','C',244,'M',2,0,0,0, +0,0,'.',0,199,'q',0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,11,0,0,0,0,0,'T','R', +'A','I','L','E','R','!','!','!',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +DEFINE_TEST(test_read_format_cpio_bin) +{ + struct archive_entry *ae; + struct archive *a; + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, 0, archive_read_support_filter_all(a)); + assertEqualIntA(a, 0, archive_read_support_format_all(a)); + assertEqualIntA(a, 0, archive_read_open_memory(a, archive, sizeof(archive))); + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_file_count(a)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_BIN_LE, archive_format(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_Z.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_Z.c new file mode 100644 index 0000000..6afe691 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_Z.c @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_cpio_bin_Z.c 189464 2009-03-07 00:25:33Z kientzle $"); + +static unsigned char archive[] = { +31,157,144,199,226,'T',' ',16,'+','O',187,' ',232,6,'$',20,0,160,'!',156, +'!',244,154,'0','l',216,208,5,128,128,20,'3','R',12,160,177,225,2,141,'T', +164,4,'I',194,164,136,148,16,'(',';',170,'\\',201,178,165,203,151,'0','c', +202,156,'I',179,166,205,155,'8','s',234,220,201,179,167,207,159,'@',127,2}; + +DEFINE_TEST(test_read_format_cpio_bin_Z) +{ + struct archive_entry *ae; + struct archive *a; + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, archive, sizeof(archive))); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_file_count(a)); + failure("archive_filter_name(a, 0)=\"%s\"", + archive_filter_name(a, 0)); + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); + assertEqualString(archive_filter_name(a, 0), "compress (.Z)"); + failure("archive_format_name(a)=\"%s\"", + archive_format_name(a)); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_BIN_LE); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_be.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_be.c new file mode 100644 index 0000000..164396d --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_be.c @@ -0,0 +1,57 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_cpio_bin_be.c 191592 2009-04-27 19:30:09Z kientzle $"); + +DEFINE_TEST(test_read_format_cpio_bin_be) +{ + struct archive_entry *ae; + struct archive *a; + const char *reference = "test_read_format_cpio_bin_be.cpio"; + + extract_reference_file(reference); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, reference, 10)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "file1111222233334444"); + assertEqualInt(archive_entry_size(ae), 5); + assertEqualInt(archive_entry_mtime(ae), 1240664175); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + assertEqualInt(archive_entry_uid(ae), 1000); + assertEqualInt(archive_entry_gid(ae), 0); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_BIN_BE); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_be.cpio.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_be.cpio.uu new file mode 100644 index 0000000..f29b071 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_be.cpio.uu @@ -0,0 +1,8 @@ +$FreeBSD: head/lib/libarchive/test/test_read_format_cpio_bin_be.cpio.uu 191592 2009-04-27 19:30:09Z kientzle $ +begin 644 test_read_format_cpio_bin_be.cpio +M<<<`"#P\@:0#Z`````$``$GS"&\`%0````5F:6QE,3$Q,3(R,C(S,S,S-#0T +M-```86)C9&4`<<<```````````````$`````````"P````!44D%)3$52(2$A +M```````````````````````````````````````````````````````````` +3```````````````````````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_bz2.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_bz2.c new file mode 100644 index 0000000..7497bc4 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_bz2.c @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_cpio_bin_bz2.c 201247 2009-12-30 05:59:21Z kientzle $"); + +static unsigned char archive[] = { +'B','Z','h','9','1','A','Y','&','S','Y',134,'J',208,'4',0,0,30,246,141,253, +8,2,0,' ',1,'*','&',20,0,'`',' ',' ',2,0,128,0,'B',4,8,' ',0,'T','P',0,'4', +0,13,6,137,168,245,27,'Q',160,'a',25,169,5,'I',187,'(',10,'d','E',177,177, +142,218,232,'r',130,'4','D',247,'<','Z',190,'U',237,236,'d',227,31,' ','z', +192,'E','_',23,'r','E','8','P',144,134,'J',208,'4'}; + +DEFINE_TEST(test_read_format_cpio_bin_bz2) +{ + struct archive_entry *ae; + struct archive *a; + int r; + + assert((a = archive_read_new()) != NULL); + r = archive_read_support_filter_bzip2(a); + if (r != ARCHIVE_OK) { + skipping("bzip2 support unavailable"); + archive_read_close(a); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, archive, sizeof(archive))); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assert(archive_filter_code(a, 0) == ARCHIVE_FILTER_BZIP2); + assert(archive_format(a) == ARCHIVE_FORMAT_CPIO_BIN_LE); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_gz.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_gz.c new file mode 100644 index 0000000..3cc8f15 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_gz.c @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_cpio_bin_gz.c 191183 2009-04-17 01:06:31Z kientzle $"); + +static unsigned char archive[] = { +31,139,8,0,244,'M','p','C',0,3,';','^','(',202,178,177,242,173,227,11,230, +23,204,'L',12,12,12,5,206,'_','|','A','4',3,131,30,195,241,'B',6,'8','`', +132,210,220,'`','2','$',200,209,211,199,'5','H','Q','Q',145,'a',20,12,'i', +0,0,170,199,228,195,0,2,0,0}; + +DEFINE_TEST(test_read_format_cpio_bin_gz) +{ + struct archive_entry *ae; + struct archive *a; + int r; + + assert((a = archive_read_new()) != NULL); + assertEqualInt(ARCHIVE_OK, archive_read_support_filter_all(a)); + r = archive_read_support_filter_gzip(a); + if (r == ARCHIVE_WARN) { + skipping("gzip reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + failure("archive_read_support_filter_gzip"); + assertEqualInt(ARCHIVE_OK, r); + assertEqualInt(ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualInt(ARCHIVE_OK, + archive_read_open_memory(a, archive, sizeof(archive))); + assertEqualInt(ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(archive_filter_code(a, 0), + ARCHIVE_FILTER_GZIP); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_BIN_LE); + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_le.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_le.c new file mode 100644 index 0000000..2d0484c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_le.c @@ -0,0 +1,57 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_read_format_cpio_bin_le) +{ + struct archive_entry *ae; + struct archive *a; + const char *reference = "test_read_format_cpio_bin_le.cpio"; + + extract_reference_file(reference); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, reference, 10)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "file1111222233334444"); + assertEqualInt(archive_entry_size(ae), 5); + assertEqualInt(archive_entry_mtime(ae), 1240664175); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + assertEqualInt(archive_entry_uid(ae), 1000); + assertEqualInt(archive_entry_gid(ae), 0); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_BIN_LE); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_le.cpio.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_le.cpio.uu new file mode 100644 index 0000000..f7fef98 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_le.cpio.uu @@ -0,0 +1,7 @@ +begin 644 test_read_format_cpio_bin_le.cpio +MQW$(`#P\I('H`P```0```/-);P@5````!0!F:6QE,3$Q,3(R,C(S,S,S-#0T +M-```86)C9&4`QW$``````````````0`````````+``````!44D%)3$52(2$A +M```````````````````````````````````````````````````````````` +3```````````````````````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_lzip.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_lzip.c new file mode 100644 index 0000000..d9acf09 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_lzip.c @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2010 Michihiro NAKAJIMA + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +static unsigned char archive[] = { + 76, 90, 73, 80, 1, 12, 0, 99,156, 62,160, 67,124,230, 93,220, +235,118, 29, 75, 27,226,158, 67,149,151, 96, 22, 54,198,209, 63, +104,209,148,249,238, 71,187,201,243,162, 1, 42, 47, 43,178, 35, + 90, 6,156,208, 74,107, 91,229,126, 5, 85,255,136,255, 64, 0, +170,199,228,195, 0, 2, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, + 0, 0, 0, 0 +}; + +DEFINE_TEST(test_read_format_cpio_bin_lzip) +{ + struct archive_entry *ae; + struct archive *a; + int r; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + r = archive_read_support_filter_lzip(a); + if (r == ARCHIVE_WARN) { + skipping("lzip reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, archive, sizeof(archive))); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_LZIP); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_BIN_LE); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_lzma.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_lzma.c new file mode 100644 index 0000000..9a8a23c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_lzma.c @@ -0,0 +1,62 @@ +/*- + * Copyright (c) 2009 Michihiro NAKAJIMA + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_cpio_bin_lzma.c 201247 2009-12-30 05:59:21Z kientzle $"); + +static unsigned char archive[] = { + 93, 0, 0,128, 0,255,255,255,255,255,255,255,255, 0, 99,156, + 62,160, 67,124,230, 93,220,235,118, 29, 75, 27,226,158, 67,149, +151, 96, 22, 54,198,209, 63,104,209,148,249,238, 71,187,201,243, +162, 1, 42, 47, 43,178, 35, 90, 6,156,208, 74,107, 91,229,126, + 5, 85,255,136,255, 64, 0 +}; + +DEFINE_TEST(test_read_format_cpio_bin_lzma) +{ + struct archive_entry *ae; + struct archive *a; + int r; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + r = archive_read_support_filter_lzma(a); + if (r == ARCHIVE_WARN) { + skipping("lzma reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, archive, sizeof(archive))); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_LZMA); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_BIN_LE); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_xz.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_xz.c new file mode 100644 index 0000000..b19c4fa --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_bin_xz.c @@ -0,0 +1,72 @@ +/*- + * Copyright (c) 2009 Michihiro NAKAJIMA + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_cpio_bin_xz.c 191183 2009-04-17 01:06:31Z kientzle $"); + +static unsigned char archive[] = { + 0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00, 0x00, 0x04, + 0xe6, 0xd6, 0xb4, 0x46, 0x02, 0x00, 0x21, 0x01, + 0x16, 0x00, 0x00, 0x00, 0x74, 0x2f, 0xe5, 0xa3, + 0xe0, 0x01, 0xff, 0x00, 0x33, 0x5d, 0x00, 0x63, + 0x9c, 0x3e, 0xa0, 0x43, 0x7c, 0xe6, 0x5d, 0xdc, + 0xeb, 0x76, 0x1d, 0x4b, 0x1b, 0xe2, 0x9e, 0x43, + 0x95, 0x97, 0x60, 0x16, 0x36, 0xc6, 0xd1, 0x3f, + 0x68, 0xd1, 0x94, 0xf9, 0xee, 0x47, 0xbb, 0xc9, + 0xf3, 0xa2, 0x01, 0x2a, 0x2f, 0x2b, 0xb2, 0x23, + 0x5a, 0x06, 0x9c, 0xd0, 0x4a, 0x6b, 0x5b, 0x14, + 0xb4, 0x00, 0x00, 0x00, 0x91, 0x62, 0x1e, 0x15, + 0x04, 0x46, 0x6b, 0x4d, 0x00, 0x01, 0x4f, 0x80, + 0x04, 0x00, 0x00, 0x00, 0xa1, 0x4b, 0xdf, 0x03, + 0xb1, 0xc4, 0x67, 0xfb, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x59, 0x5a +}; + +DEFINE_TEST(test_read_format_cpio_bin_xz) +{ + struct archive_entry *ae; + struct archive *a; + int r; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + r = archive_read_support_filter_xz(a); + if (r == ARCHIVE_WARN) { + skipping("xz reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, archive, sizeof(archive))); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_XZ); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_BIN_LE); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_filename.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_filename.c new file mode 100644 index 0000000..cf4f5ac --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_filename.c @@ -0,0 +1,860 @@ +/*- + * Copyright (c) 2011 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD"); + +#include + +DEFINE_TEST(test_read_format_cpio_filename_eucJP_UTF8) +{ + const char *refname = "test_read_format_cpio_filename_eucjp.cpio"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read eucJP filename in en_US.UTF-8 with "hdrcharset=eucJP" option. + */ + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=eucJP")) { + skipping("This system cannot convert character-set" + " from eucJP to UTF-8."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xe6\xbc\xa2\xe5\xad\x97.txt", + archive_entry_pathname(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xe8\xa1\xa8.txt", archive_entry_pathname(ae)); + assertEqualInt(4, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_cpio_filename_UTF8_eucJP) +{ + const char *refname = "test_read_format_cpio_filename_utf8_jp.cpio"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read UTF-8 filename in ja_JP.eucJP with "hdrcharset=UTF-8" option. + */ + if (NULL == setlocale(LC_ALL, "ja_JP.eucJP")) { + skipping("ja_JP.eucJP locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=UTF-8")) { + skipping("This system cannot convert character-set" + " from UTF-8 to eucJP."); + goto cleanup; + } + + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualString("\xb4\xc1\xbb\xfa.txt", archive_entry_pathname(ae)); + assertEqualInt(8, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualString("\xc9\xbd.txt", archive_entry_pathname(ae)); + assertEqualInt(4, archive_entry_size(ae)); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_cpio_filename_UTF8_UTF8_jp) +{ + const char *refname = "test_read_format_cpio_filename_utf8_jp.cpio"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read UTF-8 filename in en_US.UTF-8 without "hdrcharset=UTF-8" option. + */ + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualString("\xe6\xbc\xa2\xe5\xad\x97.txt", + archive_entry_pathname(ae)); + assertEqualInt(8, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualString("\xe8\xa1\xa8.txt", archive_entry_pathname(ae)); + assertEqualInt(4, archive_entry_size(ae)); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_cpio_filename_CP866_KOI8R) +{ + const char *refname = "test_read_format_cpio_filename_cp866.cpio"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read CP866 filename in ru_RU.KOI8-R with "hdrcharset=CP866" option. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia.20866") && + NULL == setlocale(LC_ALL, "ru_RU.KOI8-R")) { + skipping("ru_RU.KOI8-R locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=CP866")) { + skipping("This system cannot convert character-set" + " from CP866 to KOI8-R."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xf0\xf2\xe9\xf7\xe5\xf4", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\xd2\xc9\xd7\xc5\xd4", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_cpio_filename_CP866_UTF8) +{ + const char *refname = "test_read_format_cpio_filename_cp866.cpio"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read CP866 filename in en_US.UTF-8 with "hdrcharset=CP866" option. + */ + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=CP866")) { + skipping("This system cannot convert character-set" + " from CP866 to UTF-8."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\x9f\xd0\xa0\xd0\x98\xd0\x92\xd0\x95\xd0\xa2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\xbf\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_cpio_filename_KOI8R_CP866) +{ + const char *refname = "test_read_format_cpio_filename_koi8r.cpio"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read KOI8-R filename in ru_RU.CP866 with "hdrcharset=KOI8-R" option. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia.866") && + NULL == setlocale(LC_ALL, "ru_RU.CP866")) { + skipping("ru_RU.CP866 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=KOI8-R")) { + skipping("This system cannot convert character-set" + " from KOI8-R to CP866."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\x8f\x90\x88\x82\x85\x92", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xaf\xe0\xa8\xa2\xa5\xe2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_cpio_filename_KOI8R_UTF8) +{ + const char *refname = "test_read_format_cpio_filename_koi8r.cpio"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read KOI8-R filename in en_US.UTF-8 with "hdrcharset=KOI8-R" option. + */ + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=KOI8-R")) { + skipping("This system cannot convert character-set" + " from KOI8-R to UTF-8."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\x9f\xd0\xa0\xd0\x98\xd0\x92\xd0\x95\xd0\xa2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\xbf\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_cpio_filename_UTF8_KOI8R) +{ + const char *refname = "test_read_format_cpio_filename_utf8_ru.cpio"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read UTF-8 filename in ru_RU.KOI8-R with "hdrcharset=UTF-8" option. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia.20866") && + NULL == setlocale(LC_ALL, "ru_RU.KOI8-R")) { + skipping("ru_RU.KOI8-R locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=UTF-8")) { + skipping("This system cannot convert character-set" + " from UTF-8 to KOI8-R."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xf0\xf2\xe9\xf7\xe5\xf4", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\xd2\xc9\xd7\xc5\xd4", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_cpio_filename_UTF8_CP866) +{ + const char *refname = "test_read_format_cpio_filename_utf8_ru.cpio"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read UTF-8 filename in ru_RU.CP866 with "hdrcharset=UTF-8" option. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia.866") && + NULL == setlocale(LC_ALL, "ru_RU.CP866")) { + skipping("ru_RU.CP866 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=UTF-8")) { + skipping("This system cannot convert character-set" + " from UTF-8 to CP866."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\x8f\x90\x88\x82\x85\x92", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xaf\xe0\xa8\xa2\xa5\xe2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_cpio_filename_UTF8_UTF8_ru) +{ + const char *refname = "test_read_format_cpio_filename_utf8_ru.cpio"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read UTF-8 filename in en_US.UTF-8 without "hdrcharset=UTF-8" option. + */ + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\x9f\xd0\xa0\xd0\x98\xd0\x92\xd0\x95\xd0\xa2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\xbf\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_cpio_filename_eucJP_CP932) +{ + const char *refname = "test_read_format_cpio_filename_eucjp.cpio"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read eucJP filename in CP932/SJIS with "hdrcharset=eucJP" option. + */ + if (NULL == setlocale(LC_ALL, "Japanese_Japan") && + NULL == setlocale(LC_ALL, "ja_JP.SJIS")) { + skipping("CP932 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=eucJP")) { + skipping("This system cannot convert character-set" + " from eucJP."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\x8a\xbf\x8e\x9a.txt", archive_entry_pathname(ae)); + assertEqualInt(8, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\x95\x5c.txt", archive_entry_pathname(ae)); + assertEqualInt(4, archive_entry_size(ae)); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_cpio_filename_UTF8_CP932) +{ + const char *refname = "test_read_format_cpio_filename_utf8_jp.cpio"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read UTF-8 filename in CP932/SJIS with "hdrcharset=UTF-8" option. + */ + if (NULL == setlocale(LC_ALL, "Japanese_Japan") && + NULL == setlocale(LC_ALL, "ja_JP.SJIS")) { + skipping("CP932 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=UTF-8")) { + skipping("This system cannot convert character-set" + " from UTF-8 to CP932."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualString("\x8a\xbf\x8e\x9a.txt", archive_entry_pathname(ae)); + assertEqualInt(8, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualString("\x95\x5c.txt", archive_entry_pathname(ae)); + assertEqualInt(4, archive_entry_size(ae)); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_cpio_filename_CP866_CP1251) +{ + const char *refname = "test_read_format_cpio_filename_cp866.cpio"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read CP866 filename in CP1251 with "hdrcharset=CP866" option. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia") && + NULL == setlocale(LC_ALL, "ru_RU.CP1251")) { + skipping("CP1251 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=CP866")) { + skipping("This system cannot convert character-set" + " from CP866 to CP1251."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xcf\xd0\xc8\xc2\xc5\xd2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xef\xf0\xe8\xe2\xe5\xf2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +/* + * This test only for Windows platform because other archiver + * applications on Windows translate CP1251 filenames into CP866 + * filenames and store it in the cpio file and so we should read + * it by default on Windows. + */ +DEFINE_TEST(test_read_format_cpio_filename_CP866_CP1251_win) +{ + const char *refname = "test_read_format_cpio_filename_cp866.cpio"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read CP866 filename in CP1251 without "hdrcharset=CP866" option. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia")) { + skipping("Russian_Russia locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xcf\xd0\xc8\xc2\xc5\xd2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xef\xf0\xe8\xe2\xe5\xf2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_cpio_filename_KOI8R_CP1251) +{ + const char *refname = "test_read_format_cpio_filename_koi8r.cpio"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read KOI8-R filename in CP1251 with "hdrcharset=KOI8-R" option. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia") && + NULL == setlocale(LC_ALL, "ru_RU.CP1251")) { + skipping("CP1251 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=KOI8-R")) { + skipping("This system cannot convert character-set" + " from KOI8-R to CP1251."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xcf\xd0\xc8\xc2\xc5\xd2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xef\xf0\xe8\xe2\xe5\xf2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_cpio_filename_UTF8_CP1251) +{ + const char *refname = "test_read_format_cpio_filename_utf8_ru.cpio"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read KOI8-R filename in CP1251 with "hdrcharset=KOI8-R" option. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia") && + NULL == setlocale(LC_ALL, "ru_RU.CP1251")) { + skipping("CP1251 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=UTF-8")) { + skipping("This system cannot convert character-set" + " from UTF-8 to CP1251."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xcf\xd0\xc8\xc2\xc5\xd2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xef\xf0\xe8\xe2\xe5\xf2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_filename_cp866.cpio.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_filename_cp866.cpio.uu new file mode 100644 index 0000000..5f06585 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_filename_cp866.cpio.uu @@ -0,0 +1,15 @@ +begin 644 test_read_format_cpio_cp866.cpio +M,# ${TMPRPM}/BUILD/file1 +echo "hello" > ${TMPRPM}/BUILD/file2 +echo "hello" > ${TMPRPM}/BUILD/file3 +cat > ${TMPRPM}/SPECS/${NAME}.spec < ${F}.uu + +rm -rf ${TMPRPM} +exit 1 +*/ + +DEFINE_TEST(test_read_format_cpio_svr4_bzip2_rpm) +{ + struct archive_entry *ae; + struct archive *a; + const char *name = "test_read_format_cpio_svr4_bzip2_rpm.rpm"; + int r; + + assert((a = archive_read_new()) != NULL); + r = archive_read_support_filter_bzip2(a); + if (r == ARCHIVE_WARN) { + skipping("bzip2 reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + assertEqualIntA(a, ARCHIVE_OK, r); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_rpm(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + extract_reference_file(name); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 2)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("./etc/file1", archive_entry_pathname(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("./etc/file2", archive_entry_pathname(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("./etc/file3", archive_entry_pathname(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify the end-of-archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify that the format detection worked. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_BZIP2); + assertEqualString(archive_filter_name(a, 0), "bzip2"); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_SVR4_NOCRC); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.rpm.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.rpm.uu new file mode 100644 index 0000000..884ca94 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.rpm.uu @@ -0,0 +1,47 @@ +begin 644 test_read_format_cpio_svr4_bzip2_rpm.rpm +M[:ONVP,``````7)P;7-A;7!L92TQ+C`N,"TQ```````````````````````` +M```````````````````````````````````````````!``4````````````` +M````````CJWH`0`````````%````5````#X````'````1````!````$-```` +M!@`````````!```#Z`````0````L`````0```^P````'````,````!````/O +M````!````$`````!,F4X-3)F-39E,#,W83EE.61A9C`````$```1F````!@```GX````!```$;``` +M``8```*``````0``!'0````$```"E`````,```1U````!````J`````#```$ +M=@````@```*L`````P``!'<````$```"Q`````,```1X````!````M`````# +M0P!R<&US86UP;&4`,2XP+C``,0!386UP;&4@9&%T82!O9B!24$T@9FEL=&5R +M(&]F(&QI8F%R8VAI=F4`4V%M<&QE(&1A=&$N`````$L)MWQC=64M9&5S:W1O +M<``````20E-$`%5NFEP,@`Y`&YO87)C:"UR<&TM;&EN=7@````````````````````````` +M`0````$````!`$%30TE)('1E>'0`9&ER96-T;W)Y```````````````````` +M````````````````````/P````?___SP````$$)::#DQ05DF4UFX89DX``!= +M?X!,$`@`*`'_X"(D%``[9(0`(`"2B/50T#0#0`](9!%(C1,0&GJ`R`M@PQRG +M ${TMPRPM}/BUILD/file1 +echo "hello" > ${TMPRPM}/BUILD/file2 +echo "hello" > ${TMPRPM}/BUILD/file3 +cat > ${TMPRPM}/SPECS/${NAME}.spec < ${F}.uu + +rm -rf ${TMPRPM} +exit 1 +*/ + +DEFINE_TEST(test_read_format_cpio_svr4_gzip_rpm) +{ + struct archive_entry *ae; + struct archive *a; + const char *name = "test_read_format_cpio_svr4_gzip_rpm.rpm"; + int r; + + assert((a = archive_read_new()) != NULL); + r = archive_read_support_filter_gzip(a); + if (r == ARCHIVE_WARN) { + skipping("gzip reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + assertEqualIntA(a, ARCHIVE_OK, r); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_rpm(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + extract_reference_file(name); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 2)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("./etc/file1", archive_entry_pathname(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("./etc/file2", archive_entry_pathname(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("./etc/file3", archive_entry_pathname(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify the end-of-archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify that the format detection worked. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_GZIP); + assertEqualString(archive_filter_name(a, 0), "gzip"); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_SVR4_NOCRC); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_svr4_gzip_rpm.rpm.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_svr4_gzip_rpm.rpm.uu new file mode 100644 index 0000000..54d305b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_svr4_gzip_rpm.rpm.uu @@ -0,0 +1,46 @@ +begin 644 test_read_format_cpio_svr4_gzip_rpm.rpm +M[:ONVP,``````7)P;7-A;7!L92TQ+C`N,"TQ```````````````````````` +M```````````````````````````````````````````!``4````````````` +M````````CJWH`0`````````%````5````#X````'````1````!````$-```` +M!@`````````!```#Z`````0````L`````0```^P````'````,````!````/O +M````!````$`````!9&9E8V,W,#4T,C@X,V1D-&8P-6%E.#4Y,S6QO861&:6QE +MFEP`#D`;F]A``````````````` +M```````!`````0````$`05-#24D@=&5X=`!D:7)E8W1O@$!@"1O'?9"`(````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_svr4c_Z.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_svr4c_Z.c new file mode 100644 index 0000000..29aa2c6 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_cpio_svr4c_Z.c @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_cpio_svr4c_Z.c 189381 2009-03-05 00:31:48Z kientzle $"); + +static unsigned char archive[] = { +31,157,144,'0','n',4,132,'!',3,6,140,26,'8','n',228,16,19,195,160,'A',26, +'1',202,144,'q','h','p','F',25,28,20,'a','X',196,152,145,' ',141,25,2,'k', +192,160,'A',163,163,201,135,29,'c',136,'<',201,'2','c','A',147,'.',0,12,20, +248,178,165,205,155,20,27,226,220,201,243,166,152,147,'T',164,4,'I',194,164, +136,148,16,'H',1,'(',']',202,180,169,211,167,'P',163,'J',157,'J',181,170, +213,171,'X',179,'j',221,202,181,171,215,175,'L',1}; + +DEFINE_TEST(test_read_format_cpio_svr4c_Z) +{ + struct archive_entry *ae; + struct archive *a; +/* printf("Archive address: start=%X, end=%X\n", archive, archive+sizeof(archive)); */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, archive, sizeof(archive))); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + failure("archive_filter_name(a, 0)=\"%s\"", + archive_filter_name(a, 0)); + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); + failure("archive_format_name(a)=\"%s\"", archive_format_name(a)); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_SVR4_CRC); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_empty.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_empty.c new file mode 100644 index 0000000..2556503 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_empty.c @@ -0,0 +1,45 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_empty.c 189308 2009-03-03 17:02:51Z kientzle $"); + +static unsigned char archive[] = { 0 }; + +DEFINE_TEST(test_read_format_empty) +{ + struct archive_entry *ae; + struct archive *a; + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_memory(a, archive, 0)); + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + assertA(archive_filter_code(a, 0) == ARCHIVE_FILTER_NONE); + assertA(archive_format(a) == ARCHIVE_FORMAT_EMPTY); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_gtar_filename.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_gtar_filename.c new file mode 100644 index 0000000..f81796b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_gtar_filename.c @@ -0,0 +1,501 @@ +/*- + * Copyright (c) 2011 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD"); + +#include + +DEFINE_TEST(test_read_format_gtar_filename_eucJP_UTF8) +{ + const char *refname = "test_read_format_gtar_filename_eucjp.tar.Z"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read eucJP filename in en_US.UTF-8 with "hdrcharset=eucJP" option. + */ + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=eucJP")) { + skipping("This system cannot convert character-set" + " from eucJP to UTF-8."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xe6\xbc\xa2\xe5\xad\x97.txt", + archive_entry_pathname(ae)); + assertEqualInt(8, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xe8\xa1\xa8.txt", archive_entry_pathname(ae)); + assertEqualInt(4, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_COMPRESS, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_TAR_GNUTAR, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_gtar_filename_CP866_KOI8R) +{ + const char *refname = "test_read_format_gtar_filename_cp866.tar.Z"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read CP866 filename in ru_RU.KOI8-R with "hdrcharset=CP866" option. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia.20866") && + NULL == setlocale(LC_ALL, "ru_RU.KOI8-R")) { + skipping("ru_RU.KOI8-R locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=CP866")) { + skipping("This system cannot convert character-set" + " from CP866 to KOI8-R."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xf0\xf2\xe9\xf7\xe5\xf4", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\xd2\xc9\xd7\xc5\xd4", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_COMPRESS, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_TAR_GNUTAR, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_gtar_filename_CP866_UTF8) +{ + const char *refname = "test_read_format_gtar_filename_cp866.tar.Z"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read CP866 filename in en_US.UTF-8 with "hdrcharset=CP866" option. + */ + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=CP866")) { + skipping("This system cannot convert character-set" + " from CP866 to UTF-8."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\x9f\xd0\xa0\xd0\x98\xd0\x92\xd0\x95\xd0\xa2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\xbf\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_COMPRESS, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_TAR_GNUTAR, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_gtar_filename_KOI8R_CP866) +{ + const char *refname = "test_read_format_gtar_filename_koi8r.tar.Z"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read KOI8-R filename in ru_RU.CP866 with "hdrcharset=KOI8-R" option. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia.866") && + NULL == setlocale(LC_ALL, "ru_RU.CP866")) { + skipping("ru_RU.CP866 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=KOI8-R")) { + skipping("This system cannot convert character-set" + " from KOI8-R to CP866."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xaf\xe0\xa8\xa2\xa5\xe2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\x8f\x90\x88\x82\x85\x92", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_COMPRESS, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_TAR_GNUTAR, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_gtar_filename_KOI8R_UTF8) +{ + const char *refname = "test_read_format_gtar_filename_koi8r.tar.Z"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read KOI8-R filename in en_US.UTF-8 with "hdrcharset=KOI8-R" option. + */ + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=KOI8-R")) { + skipping("This system cannot convert character-set" + " from KOI8-R to UTF-8."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\xbf\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\x9f\xd0\xa0\xd0\x98\xd0\x92\xd0\x95\xd0\xa2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_COMPRESS, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_TAR_GNUTAR, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_gtar_filename_eucJP_CP932) +{ + const char *refname = "test_read_format_gtar_filename_eucjp.tar.Z"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read eucJP filename in CP932/SJIS with "hdrcharset=eucJP" option. + */ + if (NULL == setlocale(LC_ALL, "Japanese_Japan") && + NULL == setlocale(LC_ALL, "ja_JP.SJIS")) { + skipping("CP932 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=eucJP")) { + skipping("This system cannot convert character-set" + " from eucJP."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\x8a\xbf\x8e\x9a.txt", archive_entry_pathname(ae)); + assertEqualInt(8, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\x95\x5c.txt", archive_entry_pathname(ae)); + assertEqualInt(4, archive_entry_size(ae)); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_COMPRESS, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_TAR_GNUTAR, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_gtar_filename_CP866_CP1251) +{ + const char *refname = "test_read_format_gtar_filename_cp866.tar.Z"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read CP866 filename in CP1251 with "hdrcharset=CP866" option. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia") && + NULL == setlocale(LC_ALL, "ru_RU.CP1251")) { + skipping("CP1251 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=CP866")) { + skipping("This system cannot convert character-set" + " from CP866 to CP1251."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xcf\xd0\xc8\xc2\xc5\xd2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xef\xf0\xe8\xe2\xe5\xf2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_COMPRESS, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_TAR_GNUTAR, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +/* + * This test only for Windows platform because other archiver + * applications on Windows translate CP1251 filenames into CP866 + * filenames and store it in the gtar file and so we should read + * it by default on Windows. + */ +DEFINE_TEST(test_read_format_gtar_filename_CP866_CP1251_win) +{ + const char *refname = "test_read_format_gtar_filename_cp866.tar.Z"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read CP866 filename in CP1251 without "hdrcharset=CP866" option. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia")) { + skipping("Russian_Russia locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xcf\xd0\xc8\xc2\xc5\xd2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xef\xf0\xe8\xe2\xe5\xf2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_COMPRESS, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_TAR_GNUTAR, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_gtar_filename_KOI8R_CP1251) +{ + const char *refname = "test_read_format_gtar_filename_koi8r.tar.Z"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read KOI8-R filename in CP1251 with "hdrcharset=KOI8-R" option. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia") && + NULL == setlocale(LC_ALL, "ru_RU.CP1251")) { + skipping("CP1251 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=KOI8-R")) { + skipping("This system cannot convert character-set" + " from KOI8-R to CP1251."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xef\xf0\xe8\xe2\xe5\xf2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xcf\xd0\xc8\xc2\xc5\xd2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_COMPRESS, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_TAR_GNUTAR, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_gtar_filename_cp866.tar.Z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_gtar_filename_cp866.tar.Z.uu new file mode 100644 index 0000000..a6fd80c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_gtar_filename_cp866.tar.Z.uu @@ -0,0 +1,10 @@ +begin 644 test_read_format_gtar_cp866.tar.Z +M'YV0CR`A$E1($H"#"!,J7,BPH<.'$"-*1`BC(HP;-6H`L!@#8XR-%3O6^&BQ +MI$4;`&+$J$'CQ@P9*V&0C`'#Q@T9`$#`F,BSI\^?0`'4F4,GC!P0(`",J5,F +MJ,.E39U*G4JUJM6K6'G"DY?N7CEZ6<.*'4NVK-FS:-.J7JG/$RY\Z[D!L.+7HT*=2LER-KWLS9 +MY]:N7SN+'DVZM.G3J%.K7LVZM>O7L&/+GDV[MNW;N'/KWLV[M^_?P(,+'TZ\ +MN/'CR),K7\Z\N?/GT*-+GTZ]NO7KV+-KW\Z]N_?OX,.+'T^^O/GSZ-.K7\^^ +1O?OW\./+GT^_OOW[^//KKPX` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_gtar_filename_eucjp.tar.Z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_gtar_filename_eucjp.tar.Z.uu new file mode 100644 index 0000000..87fa582 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_gtar_filename_eucjp.tar.Z.uu @@ -0,0 +1,10 @@ +begin 644 test_read_format_gtar_eucjp.tar.Z +M'YV0M(+MTN>"#AXZ`!(J7,BPH<.'$"-*G$@1`(R+,&S0H&'Q8HP;-6)TA/$Q +MY$B,&&/``!`C1HV0-63(B+F29`P:)D&LK,BSI\^?0.O,H1-&#@@0`,;4*0,T +MHE*F3:-*G4JUJM6K4Q7]O7L&/+GDV[MNW;N'/KWLV[M^_?P(,+'TZ\ +MN/'CR),K7\Z\N?/GT*-+GTZ]NO7KV+-KW\Z]N_?OX,.+'T^^O/GSZ-.K7\^^ +1O?OW\./+GT^_OOW[^//K+PT` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_gtar_filename_koi8r.tar.Z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_gtar_filename_koi8r.tar.Z.uu new file mode 100644 index 0000000..bf4ce01 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_gtar_filename_koi8r.tar.Z.uu @@ -0,0 +1,10 @@ +begin 644 test_read_format_gtar_koi8r.tar.Z +M'YV0T*0ENU:,&H"#"!,J7,BPH<.'$"-*1`BC(HP;-6H`L!@#8XR-%3O6^&BQ +MI$4;`&+$J$'CQ@P9%6>@A*&RAHP;`$#`F,BSI\^?0`'4F4,GC!P0(`",J5,F +MJ,.E39U*G4JUJM6K6'G"DY?N7CEZ6<.*'4NVK-FS:-.J7O7L&/+GDV[MNW;N'/KWLV[M^_?P(,+'TZ\ +MN/'CR),K7\Z\N?/GT*-+GTZ]NO7KV+-KW\Z]N_?OX,.+'T^^O/GSZ-.K7\^^ ++O?OW\./+GT^__G,` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_gtar_gz.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_gtar_gz.c new file mode 100644 index 0000000..2541f99 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_gtar_gz.c @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_gtar_gz.c 191183 2009-04-17 01:06:31Z kientzle $"); + +static unsigned char archive[] = { +31,139,8,0,'+','e',217,'D',0,3,211,211,'g',160,'9','0',0,2,'s','S','S',16, +'m','h','n','j',128,'L',195,0,131,161,129,177,177,137,129,137,185,185,161, +'!',131,129,161,129,153,161,'9',131,130,')',237,157,198,192,'P','Z','\\', +146,'X',164,160,192,'P',146,153,139,'W',29,'!','y',152,'G','`',244,'(',24, +5,163,'`',20,12,'r',0,0,226,234,'6',162,0,6,0,0}; + +DEFINE_TEST(test_read_format_gtar_gz) +{ + struct archive_entry *ae; + struct archive *a; + int r; + + assert((a = archive_read_new()) != NULL); + assertEqualInt(ARCHIVE_OK, archive_read_support_filter_all(a)); + r = archive_read_support_filter_gzip(a); + if (r == ARCHIVE_WARN) { + skipping("gzip reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + assertEqualInt(ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualInt(ARCHIVE_OK, + archive_read_open_memory(a, archive, sizeof(archive))); + assertEqualInt(ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_file_count(a)); + assertEqualInt(archive_filter_code(a, 0), + ARCHIVE_FILTER_GZIP); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_GNUTAR); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_gtar_lzma.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_gtar_lzma.c new file mode 100644 index 0000000..280a089 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_gtar_lzma.c @@ -0,0 +1,76 @@ +/*- + * Copyright (c) 2008 Miklos Vajna + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_gtar_lzma.c 191183 2009-04-17 01:06:31Z kientzle $"); + +static unsigned char archive[] = { +0x5d, 0x0, 0x0, 0x80, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x17, 0xb, 0xbc, 0x1c, 0x7d, 0x1, 0x95, 0xc0, 0x1d, 0x4a, 0x46, 0x9c, +0x1c, 0xc5, 0x8, 0x82, 0x10, 0xed, 0x84, 0xf6, 0xea, 0x7a, 0xfe, 0x63, +0x5a, 0x34, 0x5e, 0xf7, 0xc, 0x60, 0xd6, 0x8b, 0xc1, 0x47, 0xaf, 0x11, +0x6f, 0x18, 0x94, 0x81, 0x74, 0x8a, 0xf8, 0x47, 0xcc, 0xdd, 0xc0, 0xd9, +0x40, 0xa, 0xc3, 0xac, 0x43, 0x47, 0xb5, 0xac, 0x2b, 0x31, 0xd3, 0x6, +0xa4, 0x2c, 0x44, 0x80, 0x24, 0x4b, 0xfe, 0x43, 0x22, 0x4e, 0x14, 0x30, +0x7a, 0xef, 0x99, 0x6e, 0xf, 0x8b, 0xc1, 0x79, 0x93, 0x88, 0x54, 0x73, +0x59, 0x3f, 0xc, 0xfb, 0xee, 0x9c, 0x83, 0x49, 0x93, 0x33, 0xad, 0x44, +0xbe, 0x0}; + +DEFINE_TEST(test_read_format_gtar_lzma) +{ + int r; + + struct archive_entry *ae; + struct archive *a; + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + r = archive_read_support_filter_lzma(a); + if (r == ARCHIVE_WARN) { + skipping("lzma reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + + assertEqualIntA(a, ARCHIVE_OK, r); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + r = archive_read_open_memory2(a, archive, sizeof(archive), 3); + if (r != ARCHIVE_OK) { + skipping("Skipping LZMA compression check: %s", + archive_error_string(a)); + goto finish; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae)); + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_LZMA); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_GNUTAR); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); +finish: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_gtar_sparse.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_gtar_sparse.c new file mode 100644 index 0000000..6d15a47 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_gtar_sparse.c @@ -0,0 +1,309 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_gtar_sparse.c 189308 2009-03-03 17:02:51Z kientzle $"); + + +struct contents { + int64_t o; + size_t s; + const char *d; +}; + +struct contents archive_contents_sparse[] = { + { 1000000, 1, "a" }, + { 2000000, 1, "a" }, + { 3145728, 0, NULL } +}; + +struct contents archive_contents_sparse2[] = { + { 1000000, 1, "a" }, + { 2000000, 1, "a" }, + { 3000000, 1, "a" }, + { 4000000, 1, "a" }, + { 5000000, 1, "a" }, + { 6000000, 1, "a" }, + { 7000000, 1, "a" }, + { 8000000, 1, "a" }, + { 9000000, 1, "a" }, + { 10000000, 1, "a" }, + { 11000000, 1, "a" }, + { 12000000, 1, "a" }, + { 13000000, 1, "a" }, + { 14000000, 1, "a" }, + { 15000000, 1, "a" }, + { 16000000, 1, "a" }, + { 17000000, 1, "a" }, + { 18000000, 1, "a" }, + { 19000000, 1, "a" }, + { 20000000, 1, "a" }, + { 21000000, 1, "a" }, + { 22000000, 1, "a" }, + { 23000000, 1, "a" }, + { 24000000, 1, "a" }, + { 25000000, 1, "a" }, + { 26000000, 1, "a" }, + { 27000000, 1, "a" }, + { 28000000, 1, "a" }, + { 29000000, 1, "a" }, + { 30000000, 1, "a" }, + { 31000000, 1, "a" }, + { 32000000, 1, "a" }, + { 33000000, 1, "a" }, + { 34000000, 1, "a" }, + { 35000000, 1, "a" }, + { 36000000, 1, "a" }, + { 37000000, 1, "a" }, + { 38000000, 1, "a" }, + { 39000000, 1, "a" }, + { 40000000, 1, "a" }, + { 41000000, 1, "a" }, + { 42000000, 1, "a" }, + { 43000000, 1, "a" }, + { 44000000, 1, "a" }, + { 45000000, 1, "a" }, + { 46000000, 1, "a" }, + { 47000000, 1, "a" }, + { 48000000, 1, "a" }, + { 49000000, 1, "a" }, + { 50000000, 1, "a" }, + { 51000000, 1, "a" }, + { 52000000, 1, "a" }, + { 53000000, 1, "a" }, + { 54000000, 1, "a" }, + { 55000000, 1, "a" }, + { 56000000, 1, "a" }, + { 57000000, 1, "a" }, + { 58000000, 1, "a" }, + { 59000000, 1, "a" }, + { 60000000, 1, "a" }, + { 61000000, 1, "a" }, + { 62000000, 1, "a" }, + { 63000000, 1, "a" }, + { 64000000, 1, "a" }, + { 65000000, 1, "a" }, + { 66000000, 1, "a" }, + { 67000000, 1, "a" }, + { 68000000, 1, "a" }, + { 69000000, 1, "a" }, + { 70000000, 1, "a" }, + { 71000000, 1, "a" }, + { 72000000, 1, "a" }, + { 73000000, 1, "a" }, + { 74000000, 1, "a" }, + { 75000000, 1, "a" }, + { 76000000, 1, "a" }, + { 77000000, 1, "a" }, + { 78000000, 1, "a" }, + { 79000000, 1, "a" }, + { 80000000, 1, "a" }, + { 81000000, 1, "a" }, + { 82000000, 1, "a" }, + { 83000000, 1, "a" }, + { 84000000, 1, "a" }, + { 85000000, 1, "a" }, + { 86000000, 1, "a" }, + { 87000000, 1, "a" }, + { 88000000, 1, "a" }, + { 89000000, 1, "a" }, + { 90000000, 1, "a" }, + { 91000000, 1, "a" }, + { 92000000, 1, "a" }, + { 93000000, 1, "a" }, + { 94000000, 1, "a" }, + { 95000000, 1, "a" }, + { 96000000, 1, "a" }, + { 97000000, 1, "a" }, + { 98000000, 1, "a" }, + { 99000000, 1, "a" }, + { 99000001, 0, NULL } +}; + +struct contents archive_contents_nonsparse[] = { + { 0, 1, "a" }, + { 1, 0, NULL } +}; + +/* + * Describe an archive with three entries: + * + * File 1: named "sparse" + * * a length of 3145728 bytes (3MiB) + * * a single 'a' byte at offset 1000000 + * * a single 'a' byte at offset 2000000 + * File 2: named "sparse2" + * * a single 'a' byte at offset 1,000,000, 2,000,000, ..., 99,000,000 + * * length of 99,000,001 + * File 3: named 'non-sparse' + * * length of 1 byte + * * contains a single byte 'a' + */ + +struct archive_contents { + const char *filename; + struct contents *contents; +} files[] = { + { "sparse", archive_contents_sparse }, + { "sparse2", archive_contents_sparse2 }, + { "non-sparse", archive_contents_nonsparse }, + { NULL, NULL } +}; + +static void +verify_archive_file(const char *name, struct archive_contents *ac) +{ + struct archive_entry *ae; + int err; + /* data, size, offset of next expected block. */ + struct contents expect; + /* data, size, offset of block read from archive. */ + struct contents actual; + const void *p; + struct archive *a; + + extract_reference_file(name); + + assert((a = archive_read_new()) != NULL); + assert(0 == archive_read_support_filter_all(a)); + assert(0 == archive_read_support_format_tar(a)); + failure("Can't open %s", name); + assert(0 == archive_read_open_filename(a, name, 3)); + + while (ac->filename != NULL) { + struct contents *cts = ac->contents; + + if (!assertEqualIntA(a, 0, archive_read_next_header(a, &ae))) { + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + failure("Name mismatch in archive %s", name); + assertEqualString(ac->filename, archive_entry_pathname(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + expect = *cts++; + while (0 == (err = archive_read_data_block(a, + &p, &actual.s, &actual.o))) { + actual.d = p; + while (actual.s > 0) { + char c = *actual.d; + if(actual.o < expect.o) { + /* + * Any byte before the expected + * data must be NULL. + */ + failure("%s: pad at offset %jd " + "should be zero", name, + (intmax_t)actual.o); + assertEqualInt(c, 0); + } else if (actual.o == expect.o) { + /* + * Data at matching offsets must match. + */ + assertEqualInt(c, *expect.d); + expect.d++; + expect.o++; + expect.s--; + /* End of expected? step to next expected. */ + if (expect.s <= 0) + expect = *cts++; + } else { + /* + * We found data beyond that expected. + */ + failure("%s: Unexpected trailing data", + name); + assert(actual.o <= expect.o); + archive_read_free(a); + return; + } + actual.d++; + actual.o++; + actual.s--; + } + } + failure("%s: should be end of entry", name); + assertEqualIntA(a, err, ARCHIVE_EOF); + failure("%s: Size returned at EOF must be zero", name); + assertEqualInt((int)actual.s, 0); + failure("%s: Offset of final empty chunk must be same as file size", name); + assertEqualInt(actual.o, expect.o); + /* Step to next file description. */ + ++ac; + } + + err = archive_read_next_header(a, &ae); + assertEqualIntA(a, ARCHIVE_EOF, err); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + +DEFINE_TEST(test_read_format_gtar_sparse) +{ + /* Two archives that use the "GNU tar sparse format". */ + verify_archive_file("test_read_format_gtar_sparse_1_13.tar", files); + verify_archive_file("test_read_format_gtar_sparse_1_17.tar", files); + + /* + * libarchive < 1.9 doesn't support the newer --posix sparse formats + * from GNU tar 1.15 and later. + */ + + /* + * An archive created by GNU tar 1.17 using --posix --sparse-format=0.1 + */ + verify_archive_file( + "test_read_format_gtar_sparse_1_17_posix00.tar", + files); + /* + * An archive created by GNU tar 1.17 using --posix --sparse-format=0.1 + */ + verify_archive_file( + "test_read_format_gtar_sparse_1_17_posix01.tar", + files); + /* + * An archive created by GNU tar 1.17 using --posix --sparse-format=1.0 + */ + verify_archive_file( + "test_read_format_gtar_sparse_1_17_posix10.tar", + files); + /* + * The last test archive here is a little odd. First, it's + * uncompressed, because that exercises some of the block + * reassembly code a little harder. Second, it includes some + * leading comments prior to the sparse block description. + * GNU tar doesn't do this, but I think it should, so I want + * to ensure that libarchive correctly ignores such comments. + * Dump the file, looking for "#!gnu-sparse-format" starting + * at byte 0x600. + */ + verify_archive_file( + "test_read_format_gtar_sparse_1_17_posix10_modified.tar", + files); +} + + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_gtar_sparse_1_13.tar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_gtar_sparse_1_13.tar.uu new file mode 100644 index 0000000..86a59ff --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_gtar_sparse_1_13.tar.uu @@ -0,0 +1,1370 @@ +$FreeBSD: head/lib/libarchive/test/test_read_format_gtar_sparse_1_13.tar.uu 191183 2009-04-17 01:06:31Z kientzle $ +begin 644 test_read_format_gtar_sparse_1_13.tar +M``````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````!UF4],S$T-371E71E71E71E$AE861E``````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````!UF4],S$T-3$AE861E``````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````!U``````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````````````!U +MF4].3DP,#`P,#$*,C`@ +M871I;64],3$Y.#(Y,S8P,PHR,"!C=&EM93TQ,3DX,CDS-C`Q"@`````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`"XO1TY54W!A``````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````!U``````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````!U``````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````````````!U +MF4].3DP,#`P,#$*,C`@ +M871I;64],3$Y.#(Y,S8P,PHR,"!C=&EM93TQ,3DX,CDS-C`Q"@`````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`"XO1TY54W!A``````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````!UBD:;,V!@T8-6)NE&'#10T<-#;>R(%CAEV28_3R9?LW\(P8-F[`<#%C +M)@T<->#6>`PBC.2^E07;J#'#Q>J-F5DJ<`GBB),J+N;`<3JGC(LV8=2\D<-V +M]DO;N'7S]MTFC9OA/6#,CE'[=N[=$V +M9]RY=212"9YD1EOO*&`DE!&*>645%9IY9589JGE +MEEQVZ>678(8IYIADEFGFF6BFJ>::;+;IYIMPQBGGG'36:>>=>.:IYYY\]NGG +MGX`&*NB@A!9JJ)YB](D@1PZ>U&B#*468484RT11###7<8!8(&-)4PX=^DN@4 +B5%*E6.J*746JTHN'2LFDDZW&*NNLM-9JZZVXYJKKKKR&!0`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso.iso.Z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso.iso.Z.uu new file mode 100644 index 0000000..989c112 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso.iso.Z.uu @@ -0,0 +1,26 @@ +$FreeBSD: head/lib/libarchive/test/test_read_format_iso.iso.Z.uu 201247 2009-12-30 05:59:21Z kientzle $ + +begin 644 test_read_format_iso.iso.Z +M'YV0``(*'$BPH,&#"!,J7,BPH<.'$"-*G$BQHL6+&#-JW,BQH\>/($.*'$FR +MI,F3*%.J7,FRIO8,.*'4NVK-FS:-.J7//JW/'D"-+GDRYLN7+F#-KWLRY +ML^?/H$.+'DVZM.G3J%.K7LVZM>O7L&/+GDV[MNW;N'/KWLV[M^_?P(,+'TZ\ +MN/'CR),K7\Z\N?/GT*-+GTZ]NO7KV+-KW\Z]N_?OX,.+'T^^O/GSZ-.K7\^^ +MO?OW\./+GT^_OOW[^//KW\^_O_^_`0Q!!`PPQ!```$;(44890DQ!!`@01BCA +MA!1***`43S11X88<1G@0#`6!Z-&!``1`XH$((`"``@4I,$%"%0PD`@`7%%2C +MB@*IF,8"!UR``0O@"!#0B0=V:.212":IY)),-NGDDU!&*>645%9IY952-K%$ +M$E,\8<04('#Y!`@YV&`##"\@\24(1B3!1!%39#$%%45H*$05;A)1A!0@F`#" +MA44,\804#PK8@A0O$&%%H5(4$005@X*`PA`I@!!##CG,`$(1+F3Q1!5.'$%$ +M$&]*2JFEF-X`@A(N0.&H%%TZ\0*K4PR!A)M,)!$JEKSVRJL,!-800PPPW"## +M##+04,,-!((#+`S"$FLLLLHR"P,X!&:K[;8$`O!LM,4>F^RRS1;IZ[GHIJON +MNNRVZ^Z[\,8K+Y/_U;O8/P(2:*"]_/;K[[\`!UR=EDF`T,0;;H#@Q!MV0*CJ +ML3HDJ\.R('RK0!MKI#''&V;,4;$+,+B@:0MO@$!'&7/0T8*"89#QA1EOR-%& +M&'2XH'')80BL\\X\]^SSSV<=6..00!=M]-%()ZWTTDPW[?334$?=&XD!U4BU +MU%AGK?767'?M]==@ARWVV%K/./1`-PZD(X\^`BEDB4,>:+:-`.`8T-H]_A@D +MT26:2/;?@`N^>:<=^[Y +MYZ"'+OKHI)=N^NFHIZ[ZZJRW[OKKL,O_/+,-^_\\]!'+_WTU%=O_?789Z_]]MQW[_WWX(BGK_[Z[+?O_OOPQR___/37;__]^.>O__[\]^___P`,H``'2,`"&O"`]`,` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_2.iso.Z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_2.iso.Z.uu new file mode 100644 index 0000000..688ec36 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_2.iso.Z.uu @@ -0,0 +1,35 @@ +begin 644 test_read_format_iso_2.iso.Z +M'YV0``(*'$BPH,&#"!,J7,BPH<.'$"-*G$BQHL6+&#-JW,BQH\>/($.*'$FR +MI,F3*%.J7,FRIO8,.*'4NVK-FS:-.J7//JW/'D"-+GDRYLN7+F#-KWLRY +ML^?/H$.+'DVZM.G3J%.K7LVZM>O7L&/+GDV[MNW;N'/KWLV[M^_?P(,+'TZ\ +MN/'CR),K7\Z\N?/GT*-+GTZ]NO7KV+-KW\Z]N_?OX,.+'T^^O/GSZ-.K7\^^ +MO?OW\./+GT^_OOW[^//KW\^_O_^_`0Q!!`PPQ!```$Z408<04Q`!PH,01BCA +MA!16:.&%$!Z404$;>G0@``%\>"`""`#@04$>2)#0!`.)```%!<%8HD`EEF+C +MC:4($)"(!V+HXX]`!BGDD$06:>212":IY)),-NGDDU!&*>645%9II8\R%!@# +M##C$0(,,,6Q)PPP$DI-EF%QZ"::89,)`#H%PQBDGG&=NV>67:(Y9YH?_]>GG +MGX7](R"!!@)JZ*&()JKHHL<="...`AU80:0`!`$B`!=0.@2CG';JZ:>@A@H8 +MGR]>:FI`DP9@*:F9!BCJJ[#&*NNLM#[EXJ,#R3A0C3C:J*.I(0)P:XP`S!@0 +MK[W^RF,`+DY*T*3&%@O`&P@X4($"!I"C[(ZJNI@I09E&6R*UUBJP@+:0@NAJ +MK>RVZ^Z[\$;7;$'0[CIMM==FNZVZPI9*D*XT`M"KK^F&&(`)`%A0D`4&%&0` +MN?F20RF(!`CAP@XQQ*OQQAQW['%S:)3!!AMO*/#QR2BGK/+*G7I;4+CV0FPN +MNL`>..R_T@8\<(X%AX@P!@5AT#!!#^,[\\0!$$#$Q1FS[/334$M]MILM^WVVW#'+??<=-=M]]UXYZWW +MWGSW[???@`N^>:<=^[Y +MYZ"'+OKHI)=N^NFHIZ[ZZJRW[OKKL,O_/+,-^_\\]!'+_WTU%=O_?789Z_]]MQW[_WWX(BGK_[Z[+?O_OOPQR___/37;__]^.>O__[\]^___P`,H``'2,`"&O"`"$R@ +M`A?(P`8Z\($0C*`$)TC!"EKP@AC,H`8WR,$.>O"#(`RA"$=(PA*:\(0H3*$* +M5\C"%KKPA3",H0QG2,,:VO"&.,RA#G?(PQ[Z\(=`#*(0ATC$(AKQB$A,HA*7 +MR,0F.O&)4(RB%*=(Q2I:\8I8S*(6M\C%+GKQBV`,HQC'2,8RFO&,:$RC&M?( +MQC:Z\8UPC*,O.;X`RG.,=)SG*:\YSH3*^,RG/O?)SW[Z\Y\`#:A`!TK0@AKTH`A-J$(7RM"&.O2A +M$(VH1"=*T8I:]*(8S:A&-\K1CGKTHR`-J4A'2M*2FO2D*$VI2E?*TI:Z]*4P +MC:E,9TK3FMKTICC-J4YWRM.>^O2G0`VJ4(=*U*(:]:A(3:I2E\K4ICKUJ5"- +MJE2G2M6J6O6J6,VJ5K?*U:YZ]:M@#:M8QTK6LIKUK&A-JUK7RM:VNO6M<`TG +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_Z.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_Z.c new file mode 100644 index 0000000..6492706 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_Z.c @@ -0,0 +1,103 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_iso_gz.c 201247 2009-12-30 05:59:21Z kientzle $"); + +static void +test1(void) +{ + struct archive_entry *ae; + struct archive *a; + const char *name = "test_read_format_iso.iso.Z"; + + extract_reference_file(name); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, name, 512)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_file_count(a)); + assertEqualInt(archive_filter_code(a, 0), + ARCHIVE_FILTER_COMPRESS); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_ISO9660); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +static void +test2(void) +{ + struct archive_entry *ae; + struct archive *a; + const char *name = "test_read_format_iso_2.iso.Z"; + + extract_reference_file(name); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, name, 512)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae)); + assertEqualString(".", archive_entry_pathname(ae)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae)); + assertEqualString("A", archive_entry_pathname(ae)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae)); + assertEqualString("A/B", archive_entry_pathname(ae)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae)); + assertEqualString("C", archive_entry_pathname(ae)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae)); + assertEqualString("C/D", archive_entry_pathname(ae)); + assertEqualIntA(a, ARCHIVE_EOF, + archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_file_count(a)); + assertEqualInt(archive_filter_code(a, 0), + ARCHIVE_FILTER_COMPRESS); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_ISO9660); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_iso_Z) +{ + test1(); + test2(); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_joliet.iso.Z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_joliet.iso.Z.uu new file mode 100644 index 0000000..4642fec --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_joliet.iso.Z.uu @@ -0,0 +1,66 @@ +$FreeBSD: head/lib/libarchive/test/test_read_format_iso_joliet.iso.Z.uu 201247 2009-12-30 05:59:21Z kientzle $ + +begin 644 test_read_format_iso_joliet.iso.Z +M'YV0``(*'$BPH,&#"!,J7,BPH<.'$"-*G$BQHL6+&#-JW,BQH\>/($.*'$FR +MI,F3*%.J7,FRIO8,.*'4NVK-FS:-.J7//JW/'D"-+GDRYLN7+F#-KWLRY +ML^?/H$.+'DVZM.G3J%.K7LVZM>O7L&/+GDV[MNW;N'/KWLV[M^_?P(,+'TZ\ +MN/'CR),K7\Z\N?/GT*-+GTZ]NO7KV+-KW\Z]N_?OX,.+'T^^O/GSZ-.K7\^^ +MO?OW\./+GT^_OOW[^//KW\^_O_^_`0Q!!`PPQ!```$PDX4056(#@X(,01BBA +MA`)*\403$V:HX8,'X5*0AQX="$``(AZ(``(`6%"0!10DI*)`(@#`04$SHB@0 +MBD8$(,"!`1`@0$`E'KCAD$06:>212":IY)),-NGDDU!&*>645#YY1!%.)#'% +M$TDT$<25(&CY!`@YV&`##"\@8<04(!B1!!-%3)'%%%04@>$04A01!!5/2`$" +M"D.D`$(,.>0P`PA%N)#%$U4X<0010<#Y9Z"#%GI#"S(0:`,(2K@`A9Y2;.G$ +M"YU.,002;R;HZ*2"9@J##9@2>`,(%2Z1!!4@U!D$AE7VZJN3KN8`0Z8TR!!# +M#3+,0`.!!`0[+`S%'IOLLC`00."UV&9+(`#.$FLLLLHR*^2OY)9K[KGHIJON +MNNRVZ^Z[2?XG[V(""$B@@0$Q`4`2`#@!0!4`8`$`"`,73/#!!B=,\!``$`&` +M%``\`4`3"E>,\,4=?EC""T5P%"20`)P(``8%84`R0AH,%*,'!;%L8T`XZLBC +MCR"/*"+&.%NL<\X\[^QSST#_+'301`]M=-%('ZUTTDPO[7334#\M-<9'`-"Q +MO_Q.$?&^$P,0!`!5=TQPUEL3G`,`-J`-``P`?`$`$@`8`8#6!,O-K[X=:YW% +MW`!08777"S_\]]=^2PPQP2@`P'`*!<<`P-EGSU!PQRX`L+?$`/M;M<-?XSVU +MT9\7';K0W4+[[;3,EAXMN-1:J^WKVZI^>KC5C@OO[;CGKOONO/?N^^]'SBO\ +M8?_86Z"(PR>O_/+,-^_\\]!'+_WTU%=O?50'SE@S``,`T(%`!Q*1!,37EV_^ +M^>BGK_[Z[+?O_OOPQT\8\C*.&%#W`GT?@/CDR^___P`,H``'2,`"&O"`"$Q@ +M>P[$LNT9```?`%]`R`"`-`!`#@K,H`8WR,$.>O"#(`RA"$=(PJ'0CV4B>J!` +M(G@@"EH0@R6,H0QG2,,:VO"&.,RA#G<('D34CR`U&DC,=C0BFMG/9G.#P@$" +MX(MW/$P*!0A`(*"`!1($H!U?$T@0VH&_@0R`?D#Z$4$$0`4C:"``#L@1$7ND +MQIFU00`$J``-1$"`(12!`P$@&$'T6)!V]-$,/QQ($&\4-YD548Q!"H`4H"A% +M*EH1BP/98A<%\L6"Z*@@9#0C&MM81$[VZ(UQG",!```'[Q7D>R\+62'7:,02 +M#8!_BXQB(IS0!`2T,`UR<.05LQB0+8IQ($0DR"7'6,8SIM&0;$0F`4`I1SH" +M@`\`"$%!0J#"@1@@1Y6$HP1'M``D!$$*1%#5$ERP@QC$,@"S;$(##H2&,,B! +M#&Q(@QO6H$M2!&(@@2#%+P42S($,$YC%W&0`LDD`;!X(CLP4I26B.L_^"+H$<5EG<6O=`"0N@@2)8"J'^%F*/M"%%^060PE"S8)`E*#;#``$`(`& +M`(0AO11D0P4!X`8`K`$`7ECO0-I+D/=*-+X\`(!^W\!?`)P!`"T`@!H`P&#] +M6K`,`*`#A&6[7_UB.,+]O6\;`(#ARFD8PWC(,(V2NTOD*EOY +MREB67A&DT(X`*(`*A]AM$J#P!4+E(`9[0D(10&"A(2R!S4D@`I@45"J9"$(4P!"G`*PA36[&^F0406&&C56C" +MFI5M*FE#@4^S=G2I3YWJ9]/:2YR^:.6RS.YVN_O=2D%#&=A@4@7`^][XSK>^ +M]\WO?OO[WP`/N,`'3O""&_S@"$^XPA?.\(8[_.$0C[C$)T[QBEO\XAC/N,8W +MSO&.>_SC(`^YR$=.\I*;_.0H3[G*5\[REKO\Y3"/NI8S[K6M\[U +MKGO]ZV`/N]C'3O:RF_WL:$^[VM?.]K:[_>UPC[O^ +M^_WO@`^\X`=/^,(;_O"(3[SB%\_XQCO^\9"/O.0G3_G*6_[RF,^\YC?/^I7S_K6N_[UL(^][&=/^]K;_O:XS[WN=\_[WOO^ +M]\`/OO"'3_SB&__XR$^^\I?/_.8[__G0C[[TIT_]ZEO_^MC/OO:WS_WN>__[ +MX`^_^,=/_O*;__SH3[_ZU\_^]KO__?"/O_SG3__ZV__^^,^__O?/__[[__\` +M&(`".(`$6(`&>(`(F(`*N(`,V(`.^(`0&($2.($46($6>($8F($:N($ +M^($@&((B.((D6((F>((HF((JN((LV((N^((P&(,R.(,T6(,V>(,XF(,ZN(,\ +MV(,^^(-`&(1".(1$6(1&>(1(F(1*N(1,V(1.^(10&(52.(546(56>(58F(5: +MN(5^(5@&(9B.(9D6(9F>(9HF(9JN(9LV(9N^(9P&(=R.(=T6(=V>(=X +MF(=ZN(=\V(=^^(>`&(B".(B$6(B&>(B(F(B*N(B,V(B.^(B0&(F2.(F46(F6 +M>(F8F(F:N(F^(F@&(JB.(JD6(JF>(JHF(JJN(JLV(JN^(JP&(NR.(NT +M6(NV>(NXF(NZN(N\V(N^^(O`&(S".(S$6(S&>(S(F(S*N(S,V(S.^(S0&(W2 +M.(W46(W6>(W8F(W:N(W^(W@&([B.([D6([F>([HF([JN([LV([N^([P +(&(_R.(_T:!4` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_joliet_by_nero.iso.Z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_joliet_by_nero.iso.Z.uu new file mode 100644 index 0000000..8a5a263 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_joliet_by_nero.iso.Z.uu @@ -0,0 +1,64 @@ +begin 600 test_read_format_iso_joliet_by_nero.iso.Z +M'YV0``(*'$BPH,&#"!,J7,BPH<.'$"-*G$BQHL6+&#-JW,BQH\>/($.*'$FR +MI,F3*%.J7,FRIO8,.*'4NVK-FS:-.J7//JW/'D"-+GDRYLN7+F#-KWLRY +ML^?/H$.+'DVZM.G3J%.K7LVZM>O7L&/+GDV[MNW;N'/KWLV[M^_?P(,+'TZ\ +MN/'CR),K7\Z\N?/GT*-+GTZ]NO7KV+-KW\Z]N_?OX,.+'T^^O/GSZ-.K7\^^ +MO?OW\./+GT^_OOW[^//KW\^_O_^_`0Q!!`PPQ!```"`DJ.""##;HX()??/'@ +MA!0J>!`6`@PD`!8?'0A``!X>B``"`%A0D`45)&2B0"(`,$%!+Y(H$(EN&-`! +M!0,@F.&'`8&(8(5`!BGDD$06:>212":IY)),-NGDDU!&J:`314CQ!`A"5"&% +M$TDX<00(5C8AY9ADEFGFF5#*4""!-LB0@YHPS$`@@2"H&0.;;L(IYYP@S.GG +MGWX"`.B@<_+XWZ&()FJ8``(2:&!`("`H::243FIII9@&5`8L7N@C4*:@7FHI +M0AAJB$4)+Q3!48@A`C`B`!H4I$$&"<7*(@`7%)2KC`'1:"...O;8HX>A%BNJ +ML<@>JVRRS"[K;+.50OKLM-!2:VVUV%XKJK39=JNMM^!^ZVQ`3@!0!@!R`/"& +MI$(`4`>Z`+@!0!KQ`G"&I%(`\`0`38@;[K_^CAMPM0-;6W"S=N+Y)H%[TIDP +M#&TN'*>??1(ZJ*`6`VJHHAQW['%=_S1:H(WX$N;TP`T0(=&'C5CF>N^>:<=^[Y +M0R2[:.CD`A4=P.6?IZ[ZZJRW7G*+N1*TJ]@^OWTS[+JNW6O;P)K-:@`J`(!! +M0<,C+3/930/](8ETF`O`'``T[_KTU%=O_?6,M3@\0<73OG3R?A^(N^RZ)UV[ +M[T';,'?==[N:]]Y]GUUT\^="W[P+T0.`1_X[`(`X]@`,H``'2$"N'"AV&R/1 +M]@Q%O^?EKX`0C*`$)TC!RX0N5QY"VO`.U$#[5?"#(`RA"$=(%SJ480YT,$,: +MV'`N$KKPA3",H0QG2,,:VO"&.,RA#G?(PQ[Z\(=`#*(0ATC$(AKQB$A,HA*7 +MR,0F.O&)4(RB%*=(Q2I:\8I8S*(6M\C%+GKQBV`,HQC'2,8RFO&,:$RC&M?( +MQC:Z\8UPC*,O.;X`RG.,=)SG*:\YSH3*^,RG/O?)SW[Z\Y\`#:A`!TK0@AKTH`A-J$(7RM"&.O2A +M$(VH1"=*T8I:]*(8S:A&-\K1CGKTHR`-J4A'2M*2FO2D*$VI2E?*TI:Z]*4P +MC:E,9TK3FMKTICC-J4YWRM.>^O2G0`VJ4(=*U*(:]:A(3:I2E\K4ICKUJ5"- +MJE2G2M6J6O6J6,VJ5K?*U:YZ]:M@#:M8QTK6LIKUK&A-JUK7RM:VNO6M<(VK +M7.=*U[K:]:YXS:M>]\K7OOKUKX`-K&`'2]C"&O:PB$VL8A?+V,8Z]K&0C:QD +M)TO9REKVLIC-K&8WR]G.>O:SH`VM:$=+VM*:]K2H3:UJ5\O:UKKVM;"-K6QG +M2]O:VO:VN,VM;G?+V][Z]K?`#:YPATOYT(VN=*=+ +MW>I:][K8S:YVM\O=[GKWN^`-KWC'2][RFO>\Z$VO>M?+WO:Z][WPC:]\YTO? +M^MKWOOC-KW[WR]_^^O>_``ZP@`=,X`(;^,`(3K""%\S@!COXP1".L(0G3.$* +M6_C"&,ZPAC?,X0Y[^,,@#K&(1TSB$IOXQ"A.L8I7S.(6N_C%,(ZQC&=,XQK; +M^,8XSK&.=\SC'OOXQT`.LI"'3.0B&_G(2$ZRDI?,Y"8[^_G+8`ZSF,=,YC*;^,ZSGO?,YS[[^<^`#K2@!TWH0AOZT(A.M*(7S>A&._K1D(ZTI"=-Z4I;^M*8 +MSK2F-\WI3GOZTZ`.M:A'3>I2F_K4J$ZUJE?-ZE:[^M6PCK6L9TWK6MOZUKC. +MM:YWS>M>^_K7P`ZVL(=-[&(;^]C(3K:RE\WL9CO[V=".MK2G3>UJ6_O:V,ZV +MMK?-[6Y[^]O@#K>XQTWNYVN_O=\(ZWO.=-[WK;^][XSK>^ +M]\WO?OO[WP`/N,`'3O""&_S@"$^XPA?.\(8[_.$0C[C$)T[QBEO\XAC/N,8W +MSO&.>_SC(`^YR$=.\I*;_.0H3[G*5\[REKO\Y3"/NI8S[K6M\[U +MKGO]ZV`/N]C'3O:RF_WL:$^[VM?.]K:[_>UPC[O^ +M^_WO@`^\X`=/^,(;_O"(3[SB%\_XQCO^\9"/O.0G3_G*6_[RF,^\YC?/^I7S_K6N_[UL(^][&=/^]K;_O:XS[WN=\_[WOO^ +M]\`/OO"'3_SB&__XR$^^\I?/_.8[__G0C[[TIT_]ZEO_^MC/OO:WS_WN>__[ +MX`^_^,=/_O*;__SH3[_ZU\_^]KO__?"/O_SG3__ZV__^^,^__O?/__[[__\` +M&(`".(`$6(`&>(`(F(`*N(`,V(`.^(`0&($2.($46($6>($8F($:N($ +M^($@&((B.((D6((F>((HF((JN((LV((N^((P&(,R.(,T6(,V>(,XF(,ZN(,\ +MV(,^^(-`&(1".(1$6(1&>(1(F(1*N(1,V(1.^(10&(52.(546(56>(58F(5: +MN(5^(5@&(9B.(9D6(9F>(9HF(9JN(9LV(9N^(9P&(=R.(=T6(=V>(=X +MF(=ZN(=\V(=^^(>`&(B".(B$6(B&>(B(F(B*N(B,V(B.^(B0&(F2.(F46(F6 +M>(F8F(F:N(F^(F@&(JB.(JD6(JF>(JHF(JJN(JLV(JN^(JP&(NR.(NT +M6(NV>(NXF(NZN(N\V(N^^(O`&(S".(S$6(S&>(S(F(S*N(S,V(S.^(S0&(W2 +M.(W46(W6>(W8F(W:N(W^(W@&([B.([D6([F>([HF([JN([LV([N^([P +F&(_R.(_T6(_V>(_XF(_ZN(_\V(_^^(\`&9`".9`$69`&>9`(V6X` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_joliet_long.iso.Z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_joliet_long.iso.Z.uu new file mode 100644 index 0000000..030dd3c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_joliet_long.iso.Z.uu @@ -0,0 +1,71 @@ +$FreeBSD: head/lib/libarchive/test/test_read_format_iso_joliet_long.iso.Z.uu 201247 2009-12-30 05:59:21Z kientzle $ + +begin 644 test_read_format_iso_joliet_long.iso.Z +M'YV0``(*'$BPH,&#"!,J7,BPH<.'$"-*G$BQHL6+&#-JW,BQH\>/($.*'$FR +MI,F3*%.J7,FRIO8,.*'4NVK-FS:-.J7//JW/'D"-+GDRYLN7+F#-KWLRY +ML^?/H$.+'DVZM.G3J%.K7LVZM>O7L&/+GDV[MNW;N'/KWLV[M^_?P(,+'TZ\ +MN/'CR),K7\Z\N?/GT*-+GTZ]NO7KV+-KW\Z]N_?OX,.+'T^^O/GSZ-.K7\^^ +MO?OW\./+GT^_OOW[^//KW\^_O_^_`0Q!!`PPQ!```$;(44890DQ!!`@01BCA +MA!1***`43S11X88<1GA0+@6!Z-&!``1`XH$((`"`!@5I0$%"%@PD`@`<%%2C +MB@*I:$0``B10(@D"!'3B@1T6:>212":IY)),-NGDDU!&*>645%9I991-+)'$ +M%$\8,04(6SX!0@XVV`##"TAX"8(123!1Q!193$%%$1H*446;1!0A!0@F@'!A +M$4,\(<6#`K8@Q0M$6$&H%$4$086@(*`P1`H@Q)!##C.`4(0+63Q1A1-'$!&$ +MFY%.6NFE-X"@A`M0-"H%ETZ\L.H40R#1)A-)@'KEKKSN*@.!.<1`(`XPX!!# +M##7D0"`)O\(0[+#%'IOLL@16:^VU!`+0[+/%1HNLLC"00&2OY)9K[KGHIJON +MNNRVZ^Z[2_XG[V(""$B@@0$9`8`<`)31+P!"`#`%`$0``(+!"!^L<,((#T$P +M`%(`\`0`33"\\,46(VR0B`/E4L(+17`TI)``I`@`.`6!@T%"+`HTXP<%P8QC +M0#KRZ&,`0))<(HD8]YRQST#_+'301`]M=-%('ZUTTDPO[7334#\M==143VUU +MU557O`0`20@L,8)>']SUP!,?G`,`-J`-``P`?`$`$F`/?+"^73,!0,@#9^$U +M%7=3C'#`57`-@-T%AQSQP28T_'#$(3L\<<0%'^QPP2U`W/;#5CPLN>4A!W&U +MU)\W';K3VPK;K;'?+ELZM*A/&RZVL%>K+;"F$]LZN.(:#._NO/?N^^_`!R_\ +M\$K.:_QA_]A;((G'-^_\\]!'+WUQ628!`A5HU`'"$V/0`2$.(!2KP[$Z)`O" +MM@K(X$*!Z\<0A@V9MJ`$""VH\08;:91!1PMLO.'&&?2K0QK(4"GZG6&`YP.! +M"Q;X@C3,X0W3BZ`$)TC!"EK0*;B8P8%JI+.2`<`#`CE0#&0P`QK4P`8WP,$% +M5\C"%KKPA3",H0QG2,,:VO"&CF$>C4I$LX&`,``C+.$)4XC#(AKQB$A,HA*7 +MR,0F.O&)4+S/@6#606=HC(<`B(&V`#`#`-```#50VPT`H,*SL4V+,N"B%\$H +M1C("P(Q9W&(7OQC&M(VQC&N+8QKGR$8[NA&.:%0C'=N(QS/*<8UU!,`=WYC' +M0/(QD8L$Y"$'Z<="ZE&0?53D'QLYR4Q&,H]D`$`:]A7%4IKRE*A,I2I7R%[4@SE"D,WLJ3,3!4`*`1UH00^:T($PU*$$@6A!>%20BMHHHQOM +MZ$Y!*E($D-2D5;TJ`'#QP8*`<&8>].C-M=\RK$M/)UKG@MD%[]*MB^TK6P@/WK7A&[6#*D00XJ96D' +M"C)9@^B+(/K2!0!F1!`1&*`@!A#KCT(HI`78-:TNV$$,UAJ`MKXUKH8-[&D/ +M.UO9#I:VM[5M;!5+V-KR%K>[+6QD`U#9@73@L@,Q`G(%HB]";+8@G@6M:'%& +MVA(M``E!&!2NG+"$U*XVJ*YMP('0$`8YD`%_;EC#4`-`BD`,)!"DF*A`!!#1 +M$LDW(`+@K(R@RM'IDL"_)[5J2=M)X`*+<[U%76@[[@L`^BZ5P0(`(4$\P%^I +M?O2_4\4J2DFPWO:^-[Y-K2]3"9)?Z%;8OP#.ZH`-S.(6N_C%\JJIA'V(TQ[Z +M]YXC8RU!#8I0A0:$H1`6,81G+!`*:[2_&0[P594\X)I:5"#RS.F->VHB'2/8 +MQP`XZD.%W-0G!P2C1[;P6)FL80&3`,9H3K.:UYR9E\6LQF'-,(Z%="`W$T1F +M\]3IA>>\LP#`X[F=_2Q!0IOAZ@;`BMNL)C2I.4QM1O.8S!2F-(.I3$A/4]*6 +MIC0VNWE-;EHST8V.=*6S*6H`_/E@!#D86.DY5CX?NM.*=C2C)PWK4%]ZU)P& +M-:UUG>E:[_K1I+[UIC\-;$Y_DY1IU*_+!#T00E_8T!```!H`$`92AI(-H@1` +M3=?`YFY[^]M!"("YFI,4:A4$4!T<"AAZ5*"8 +M``*,/\$*#7\3"*90!2A`05!46!.D3CZ%)&!A36TZ.)SD1*>1TZGB5$C"$*8` +M!3<%80H'#Y03J!"$(:2<"%L:0L>K(`1<3<'@>S("I'@.J"2P:0B.2L(3G#!R +M3TU\4Q`"^L69[G2H@RE/0[=Z$O0$)JYC/`E-R&X60&"%)S"A"DTX>)YH]6\H +M/"KJD!(ZT8W>=JE+(>XYW[H+[,WXQCO^\4%!0QG8T#\%0/[RF,^\YC?/^I7S_K6N_[UL(^][&=/^]K;_O:XS[WN=\_[WOO^ +M]\`/OO"'3_SB&__XR$^^\I?/_.8[__G0C[[TIT_]ZEO_^MC/OO:WS_WN>__[ +MX`^_^,=/_O*;__SH3[_ZU\_^]KO__?"/O_SG3__ZV__^^,^__O?/__[[__\` +M&(`".(`$6(`&>(`(F(`*N(`,V(`.^(`0&($2.($46($6>($8F($:N($ +M^($@&((B.((D6((F>((HF((JN((LV((N^((P&(,R.(,T6(,V>(,XF(,ZN(,\ +MV(,^^(-`&(1".(1$6(1&>(1(F(1*N(1,V(1.^(10&(52.(546(56>(58F(5: +MN(5^(5@&(9B.(9D6(9F>(9HF(9JN(9LV(9N^(9P&(=R.(=T6(=V>(=X +MF(=ZN(=\V(=^^(>`&(B".(B$6(B&>(B(F(B*N(B,V(B.^(B0&(F2.(F46(F6 +M>(F8F(F:N(F^(F@&(JB.(JD6(JF>(JHF(JJN(JLV(JN^(JP&(NR.(NT +M6(NV>(NXF(NZN(N\V(N^^(O`&(S".(S$6(S&>(S(F(S*N(S,V(S.^(S0&(W2 +M.(W46(W6>(W8F(W:N(W^(W@&([B.([D6([F>([HF([JN([LV([N^([P +M&(_R.(_T6(_V>(_XF(_ZN(_\V(_^^(\`&9`".9`$69`&>9`(F9`*N9`,V9`. +M^9`0&9$2.9$469$6>9$8F9$:N9$^9$@&9(B.9(D69(F>9(HF9(JN9(L +MV9(N^9(P&9,R.9,T69,V>9,XF9,ZN9,\V9,^^9-`&91".91$691&>91(F91* +MN91,V91.^910&952.9546956>958F95:N95^95@&99B.99D699F>99H +MF99JN99LV99N^99P&9=R.9=T69=V>9=XF9=ZN9=\V9=^^9>`&9B".9B$69B& +4>9B(F9B*N9B,V9B.^9B0&9F2J90` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_joliet_rockridge.iso.Z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_joliet_rockridge.iso.Z.uu new file mode 100644 index 0000000..9f1dd09 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_joliet_rockridge.iso.Z.uu @@ -0,0 +1,68 @@ +$FreeBSD: head/lib/libarchive/test/test_read_format_iso_joliet_rockridge.iso.Z.uu 201247 2009-12-30 05:59:21Z kientzle $ + +begin 644 test_read_format_iso_joliet_rockridge.iso.Z +M'YV0``(*'$BPH,&#"!,J7,BPH<.'$"-*G$BQHL6+&#-JW,BQH\>/($.*'$FR +MI,F3*%.J7,FRIO8,.*'4NVK-FS:-.J7//JW/'D"-+GDRYLN7+F#-KWLRY +ML^?/H$.+'DVZM.G3J%.K7LVZM>O7L&/+GDV[MNW;N'/KWLV[M^_?P(,+'TZ\ +MN/'CR),K7\Z\N?/GT*-+GTZ]NO7KV+-KW\Z]N_?OX,.+'T^^O/GSZ-.K7\^^ +MO?OW\./+GT^_OOW[^//KW\^_O_^_`0Q!!`PPQ!```$;(44890DQ!!`@01BCA +MA!1***`43S11X88<1G@0+@6!Z-&!``1`XH$((`"`!0590$%"+`HD`@`<%%2C +MB@*I:$0``B10(@D"!'3B@1T6:>212":IY)),-NGDDU!&*>645%9I991-+)'$ +M%$\8,04(6SX!0@XVV`##"TAX"8(123!1Q!193$%%$1H*446;1!0A!0@F@'!A +M$4,\(<6#`K8@Q0M$6$&H%$4$086@(*`P1`H@Q)!##C.`4(0+63Q1A1-'$!&$ +MFY%.6NFE-X"@A`M0-"H%ETZ\L.H40R#1)A-)@'KEKKSN*@.!.<1`(`XQU""# +M##340"`)O\(0[+#%'IOLL@16:^VU!`+0[+,P$&LLLLK"0`*1O99K[KGHIJON +MNNRVZ^Z[\"[YW[R+"2`@@08&9`0`<@!0AK\`"`'`%``0`0`(!R>,\,(*)SQ$ +MP0!(`<`3`#31,,,87YRP02(.A$L)+Q3!T9!"`I`B`!@4A$'*"&DPT(P>%!0S +MC@'IR*./`0!927BQP$ +MUE.#[K3H3V\K;+?1@KNLZ=!^.ZVXV,9>K;;`GNZMM.&.>W"\O/?N^^_`!R_\ +M\,0K2>_QA_US;X$D(N_\\]!'+_WTQ669!`A4H%$'"$^,00>$.%1:@P['ZI`L +M"-LJ((,+!;(?0Q@V9-J"$B"T4$<:9%1:_QGXHP^""P!\01KF\`;J&?"`"$R@ +M`A>X%5QHX$`UVAD`!@"`#@CD0$1(@L08R,$.>O"#(`RA"$=(PA*:\(0HE$SS +M:%2B@%!0(!8,0`8WF,(:VO"&.,RA#G?(PQ[Z\(=`U,^!8B9!`P#@`Q<,"!D` +MD`9^!?&)4(RB%*=(Q2I:\8I8S*(6H;+"F)'(B`)!XH&6V,1^;?&,:$RC&M?( +MQC:Z\8UPC"-[(,%"@MQH(#;KT8^"U$*>#0P*!PB`+]X1,2D4(`"!@`(66!"` +M=GQ.($%HQPL',H`5"HF/`Q%`!`?"`2H8X8$.V)$><]8&!2#@`19H`0E*>!``!!&$%H6I!VW=$,=.6DR/"+H9GO1)4(H29ZLT)2I5R*A@02Q(LUY>,YA]#,``9EC,0R;" +M"4U`P!C3(`=D-O*1`8DD)@4B`$N6:)\!$8`%"=*!:@8@E,#,V3E)J4U7`H`0 +M``A!04(`QH$88*'?%.8"D!"$0>'*"4MPP0YBT,X`O+,)#3@0&L(@!S*P(0UN +M6(,]21&(@02"%``%0#^AF5,!2)0@(3`H0D=)`HQVTY6>B.A$*RJ0BR8TH^ET +M`!.>`*HO*.$)3'#!G+`PTD*Z$YXC.!`;WN"&,[1`#6]X:1GHT`(SI($-96B! +M&\+0AC*X@`YEP`,=W`K7F=94(#?MJ3^C21"?3E2HJ0U6)"@#`XQ^0C2P\ +M#H+1))9(`7!JPD=#VM62-@*>##C0'/+0AI?&U)[M",5`0M&.P0ZVIX^-+&3A +M,04FE(!$'AAK6<^:UC2LM:UOC>M2A.[,$PN48_*S<5^4Y>;%,@=<_1+ +MHG972";Z+FKQ"0!F%N29!"%L)N,;D$Y^\J"*C2YTO5G=!COXP1!N#8!YHP06:VW:?>EV6N]S$+[/-L;*=+66?6F,'`&`. +M`,@#`,A\92`#0,@1#K2@!TWHHPJ"`%74TCUGHP`J6\#*@EL&H*C +MDD!58WO*UIN"T+AU[6YXRQM,>3(WOI.@)S`Y`=BB;D)'LP`"*V"U"DU0=9YH +M)6HH/&K>D"KWN=/M<'I+0>+I8S[K6M\[U +MKGO]ZV`/N]C'3O:RF_WL:$^[VM?.]K:[_>UPC[O^ +M^_WO@`^\X`=/^,(;_O"(3[SB%\_XQCO^\9"/O.0G3_G*6_[RF,^\YC?/^I7S_K6N_[UL(^][&=/^]K;_O:XS[WN=\_[WOO^ +M]\`/OO"'3_SB&__XR$^^\I?/_.8[__G0C[[TIT_]ZEO_^MC/OO:WS_WN>__[ +MX`^_^,=/_O*;__SH3[_ZU\_^]KO__?"/O_SG3__ZV__^^,^__O?/__[[__\` +M&(`".(`$6(`&>(`(F(`*N(`,V(`.^(`0&($2.($46($6>($8F($:N($ +M^($@&((B.((D6((F>((HF((JN((LV((N^((P&(,R.(,T6(,V>(,XF(,ZN(,\ +MV(,^^(-`&(1".(1$6(1&>(1(F(1*N(1,V(1.^(10&(52.(546(56>(58F(5: +MN(5^(5@&(9B.(9D6(9F>(9HF(9JN(9LV(9N^(9P&(=R.(=T6(=V>(=X +MF(=ZN(=\V(=^^(>`&(B".(B$6(B&>(B(F(B*N(B,V(B.^(B0&(F2.(F46(F6 +M>(F8F(F:N(F^(F@&(JB.(JD6(JF>(JHF(JJN(JLV(JN^(JP&(NR.(NT +M6(NV>(NXF(NZN(N\V(N^^(O`&(S".(S$6(S&>(S(F(S*N(S,V(S.^(S0&(W2 +M.(W46(W6>(W8F(W:N(W^(W@&([B.([D6([F>([HF([JN([LV([N^([P +M&(_R.(_T6(_V>(_XF(_ZN(_\V(_^^(\`&9`".9`$69`&>9`(F9`*N9`,V9`. +M^9`0&9$2.9$469$6>9$8F9$:N9$^9$@&9(B.9(D69(F>9(HF9(JN9(L +.V9(N^9(P&9,R.9,T^8(` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_multi_extent.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_multi_extent.c new file mode 100644 index 0000000..dafbfd3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_multi_extent.c @@ -0,0 +1,96 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2009 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_iso_multi_extent.c 201247 2009-12-30 05:59:21Z kientzle $"); + +DEFINE_TEST(test_read_format_iso_multi_extent) +{ + const char *refname = "test_read_format_iso_multi_extent.iso.Z"; + struct archive_entry *ae; + struct archive *a; + const void *p; + size_t size; + int64_t offset; + int i; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualInt(0, archive_read_support_filter_all(a)); + assertEqualInt(0, archive_read_support_format_all(a)); + assertEqualInt(ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Retrieve each of the 2 files on the ISO image and + * verify that each one is what we expect. */ + for (i = 0; i < 2; ++i) { + assertEqualInt(0, archive_read_next_header(a, &ae)); + + if (strcmp(".", archive_entry_pathname(ae)) == 0) { + /* '.' root directory. */ + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(2, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualIntA(a, ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + } else if (strcmp("file", archive_entry_pathname(ae)) == 0) { + /* A regular file. */ + assertEqualString("file", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(262280, archive_entry_size(ae)); + assertEqualInt(0, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt(0, offset); + assertEqualMem(p, "head--head--head", 16); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + } else { + failure("Saw a file that shouldn't have been there"); + assertEqualString(archive_entry_pathname(ae), ""); + } + } + + /* End of archive. */ + assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_ISO9660_ROCKRIDGE); + + /* Close the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_multi_extent.iso.Z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_multi_extent.iso.Z.uu new file mode 100644 index 0000000..79100f0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_multi_extent.iso.Z.uu @@ -0,0 +1,67 @@ +$FreeBSD: head/lib/libarchive/test/test_read_format_iso_multi_extent.iso.Z.uu 201247 2009-12-30 05:59:21Z kientzle $ + +begin 644 test_read_format_iso_multi_extent.iso.Z +M'YV0``(*'$BPH,&#"!,J7,BPH<.'$"-*G$BQHL6+&#-JW,BQH\>/($.*'$FR +MI,F3*%.J7,FRIO8,.*'4NVK-FS:-.J7//JW/'D"-+GDRYLN7+F#-KWLRY +ML^?/H$.+'DVZM.G3J%.K7LVZM>O7L&/+GDV[MNW;N'/KWLV[M^_?P(,+'TZ\ +MN/'CR),K7\Z\N?/GT*-+GTZ]NO7KV+-KW\Z]N_?OX,.+'T^^O/GSZ-.K7\^^ +MO?OW\./+GT^_OOW[^//KW\^_O_^_`0Q!!`PPQ!```$;(44890DQ!!`@01BCA +MA!1***`43S11X88<1GB0#0<*%(`-'X48@(D`((````H4I``%"5DPD`@`<%"0 +MC2L*M*(1`0B0```!D"!`0"8>V.&12":IY)),-NGDDU!&*>645%9IY9583LE$ +M$D($(<402"1A11$@)#'%$R#D8(,-,(!@1!),%#%%%E-0482&5TB1A)U29.GG +MGX`&*FB2,A"80PP%WD!@#&PJ"@,)A<)P:**+-DH@"01FJNFF!`(0Z:0Q.,HH +M#(Z28.2@J*:JZJJLMNKJJ[#&*FN5_]6ZF``"+AJB$0#(`4`9OP(@!`!3`$`$ +M`"`@JVRRS"ZK[!#&`B`%`$\`T(2SS6:+K;(&@3C0B"6\4`1'11*9XHHM$J0` +M!@EI,",`'104;XX![=CCCT$."221(6KK[[;_!@SPP`(73/#!!B>,\,(*-\SP +MPPY'#/'$$E=,\<466\P$`$D("T`0T@(`+1(<`V`%`.,FVW&QU2:;`P`DD@B# +MLKQVO/&XQ69!+`!4H&RMLE>$W''/XTZ;,<9('ZUMT@\SK?"GB(9:*:F70DUI +M@98^RNG6F7IJ:-2B9FTJLK.6;?;9:*>M]MILIVWKVX?]DVN!(<)M]]UXYZWW +MWL4EX801:$X1!AT@/#$&X:&"0*`.C.I`*@B?*L!&&F*$(<<8:*1A1QF0NW"# +M"SD0&`8(:O_/+,-^_\\]"#5G>-^T9O_?789Z_]]MQW[_WWX(>O]X'Q#B_^ +M^>BGK_[Z[+?O_OOPQR__5]/'._W\^.>O__[\]^___P`,H`#S`PGJ$01'`[&7 +MCX`DI.&=B%A0.$``?/$.:4FA``$(!!2PP((`M`%D`@E"&_0U$`'<#T@D%(@` +MA#<0#E#!"!H(@`-XM,`@T1!?)&B#`B(```@<@`1#*`('`N"!@A31(.TH2#O< +M8,`6IBB!"+H7`_55I`!(X8(9W&`'/S@0$:8P("8L2(\*LL(;O3"&,Y2B#=68 +MPQWV\(<`X`,`/E`0.N+#1/B(8@U)``@''N!-<7+!#F)P10PFP@E-2,"!S)"& +MU&DQ2($82"#&1I`'5O*+`!``'0GR@3/*\(8,!&60=,A#'Y)`CEXH2"KO2*0\ +MBI*/?@1D$01)2"P>,I&+;&09'DF"2`IDDB>TY+> +M$@"=*$@G$`&!@4``$:\4$9'^"*=9#K*0`;BE(@'`2$=R$)*2I.2W@DG,:!*D +M$\E\)3/=:,H!VO.>^'P+C,(0GL`$KV+("DD@@IQ`,(4J0`$*3Y`" +M%=P45Z\^80I)P(*;NLE6.ME)0U.XTU:ID(0A3`$*<0I"8$$P5B=0(0A#F"L1 +MS#0$KU9!"%N:@E/[!+@^';8(0TC"FX;`U"0\P0EL?4(5OC1+"`663%"X;&8W +M6R:U.E:T2?!IF5#[U20TP4M9`($5R%J%)I!)K5,8@E'#RMFZ-O:QD=UM9W]+ +MV-.Z@*?8S:YVM]L7-)0A#&1H00N\"U[QDC>\X_TN>L]K7O6&X;WPC:]\YTO? +M^7+WOOC-KW[WR]_^^O>_``ZP@`=,X`(;^,`(3K""%\S@!COXP1".L(0G3.$* +M6_C"&,ZPAC?,X0Y[^,,@#K&(1TSB$IOXQ"A.L8I7S.(6N_C%,(ZQC&=,XQK; +M^,8XSK&.=\SC'OOXQT`.LI"'3.0B&_G(2$ZRDI?,Y"8[^_G+8`ZSF,=,YC*;^,ZSGO?,YS[[^<^`#K2@!TWH0AOZT(A.M*(7S>A&._K1D(ZTI"=-Z4I;^M*8 +MSK2F-\WI3GOZTZ`.M:A'3>I2F_K4J$ZUJE?-ZE:[^M6PCK6L9TWK6MOZUKC. +MM:YWS>M>^_K7P`ZVL(=-[&(;^]C(3K:RE\WL9CO[V=".MK2G3>UJ6_O:V,ZV +MMK?-[6Y[^]O@#K>XQTWNYVN_O=\(ZWO.=-[WK;^][XSK>^ +M]\WO?OO[WP`/N,`'3O""&_S@"$^XPA?.\(8[_.$0C[C$)T[QBEO\XAC/N,8W +MSO&.>_SC(`^YR$=.\I*;_.0H3[G*5\[REKO\Y3"/NI8S[K6M\[U +MKGO]ZV`/N]C'3O:RF_WL:$^[VM?.]K:[_>UPC[O^ +M^_WO@`^\X`=/^,(;_O"(3[SB%\_XQCO^\9"/O.0G3_G*6_[RF,^\YC?/^I7S_K6N_[UL(^][&=/^]K;_O:XS[WN=\_[WOO^ +M]\`/?FOJ2_SBTY<.86BD>)&O_!8PGPW+3S[TG2_]Z#=2^-C/OO:WS_WN>__[ +MX`^_^,=/_O*;__SH3[_ZU\_^]KO__?"/O_SG3__ZV__^^,^__O?/__[[__\` +M&(`".(`$6(`&>(`(F(`*N(`,V(`.^(`0&($2.($46($6>($8F($:N($ +M^($@&((B.((D6((F>((HF((JN((LV((N^((P&(,R.(,T6(,V>(,XF(,ZN(,\ +MV(,^^(-`&(1".(1$6(1&>(1(F(1*N(1,V(1.^(10&(52.(546(56>(58F(5: +MN(5^(5@&(9B.(9D6(9F>(9HF(9JN(9LV(9N^(9P&(=R.(=T6(=V>(=X +MF(=ZN(=\V(=^^(>`&(B".(B$6(B&>(B(F(B*N(B,V(B.^(B0&(F2.(F46(F6 +M>(F8F(F:N(F^(F@&(JB.(JD6(JF>(JHF(JJN(JLV(JN^(JP&(NR.(NT +M6(NV>(NXF(NZN(N\V(N^^(O`&(S".(S$6(S&>(S(F(S*N(S,V(S.^(S0&(W2 +M.(W46(W6>(W8F(W:N(W^(W@&([B.([D6([F>([HF([JN([LV([N^([P +M&(_R.(_T6(_V>(_XF(_ZN(_\V(_^^(\`&9`".9`$69`&>9`(F9`*N9`,V9`. +0^9`0&9$2.9$469$6>9%O"``` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_rockridge.iso.Z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_rockridge.iso.Z.uu new file mode 100644 index 0000000..5f06cb3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_rockridge.iso.Z.uu @@ -0,0 +1,206 @@ +$FreeBSD: head/lib/libarchive/test/test_read_format_iso_rockridge.iso.Z.uu 201247 2009-12-30 05:59:21Z kientzle $ + +begin 644 test_read_format_iso_rockridge.iso.Z +M'YV0``(*'$BPH,&#"!,J7,BPH<.'$"-*G$BQHL6+&#-JW,BQH\>/($.*'$FR +MI,F3*%.J7,FRIO8,.*'4NVK-FS:-.J7//JW/'D"-+GDRYLN7+F#-KWLRY +ML^?/H$.+'DVZM.G3J%.K7LVZM>O7L&/+GDV[MNW;N'/KWLV[M^_?P(,+'TZ\ +MN/'CR),K7\Z\N?/GT*-+GTZ]NO7KV+-KW\Z]N_?OX,.+'T^^O/GSZ-.K7\^^ +MO?OW\./+GT^_OOW[^//KW\^_O_^_`0Q!!`PPQ!```$;(44890DQ!!`@01BCA +MA!1***`43S11X88<1GA0#Q@,A$$/'QT(0``F'H@``@!84)`%$R14P4`B`'!! +M03>R*!"+1@0@0`(GDB!`0"D>V.&12":IY)),-NGDDU!&*>645%9IY9583MG$ +M$DE,\8014X#0Y1,@Y&"##3"\@`28(!B1!!-%3)'%%%04H:$05;Q)1!%2@&`" +M"!<6,<034CPH8`M2O$"$%89*44005!`*`@I#I`!"##GD,`,(1;B0Q1-5.'$$ +M$4'`.6FEEV9Z`PA*N`#%HU)XZ<0+K4XQ!!)O,I&$J%GVZFNO,A"8`PPYR'`# +MIC'4,$.P,)#`[+#%'IM#LLL22`*!V&:K+8$`/$NLL<@JRRP)1OYJ[KGHIJON +MNNRVZ^Z[\,;;Y'_T+O:/@`0:6.^^_/;K[[\`5[=E$B!,48<;!9-B(TX`J!C0#SZ"&0`0NY\XH%30'%` +M`+Z\`X`44A000"!08$%N.T$,%$0[5P\TP-0"^5B0`%08H4$`#O3X8Y!M)+#! +M!`^`0$+GGX=.PA!%2)1*((N."$&QX` +MXHHS7M#C!4E.$.668Z[YW*-[#KKHI$]/`@!P^%Q0B&^[C:#<0>Z>X@!;_QY` +M(DXT@<"!9*0A1^&')R[0XKL/)`#D1-8O$/.79PX^W<_CG/1,!P`Z`$`#!=$` +M%<+`BX#P(@R5^]_U[!:``[@)3B[800S,A[XF).!`9D@#&\H`OP"0(A`#"00I +M]!>0^R6/A0#@G_,D&$"Z5<]T?#A@`A?80``\,(*YFR#O3K0`)`2A4+IRPA(R +MN,'`G2]]#3@0&L(@!S*P(0UN6$,)3YC"%4X.?R>"H0S]%\0:1J]THC,$`$ZA +M,ZJ=XB!FC!R1%""G)B1QB1K\FQ,;D3X&'&@.>6C#%;-8PG:$8B"A:`<84?3" +MR4V!"0LP$0%".,+*]:]'`P"2`$B`24V>T7IK8^-`+O!&@]Q0='(D8AWO*`,F +MFH^/38@B```I2"RN00:%/*1`$KG(18KQD7[T'@`&0(X3B'P,YR#7,()>(5&3R?.E()CA` +M10$AIC$)``!D.D"9^!R@Z!CQS%%*DR#*3&4`MID%.W:3!N`4'"QE20Z#G,8AZS>??4YS*I)U)']%,@I(2C!`5*4(,JL08) +M#`&8'3:KAU7MFY.O= +M`F"^X,6O>(WC65D-"U(S)I:``(3JM`$V^[)5JZ%0J3Z*ZGWQG>^&?:O%#I\W@.[ +MP+0XSK&.=QPS-)2!#6QX@P)X3.0B&_G(2$ZRDI?,Y"8[^_G+8`ZSF,=,YC*;^,ZSGO?,YS[[^<^`#K2@!TWH0AOZT(A.M*(7S>A&._K1D(ZTI"=-Z4I;^M*8 +MSK2F-\WI3GOZTZ`.M:A'3>I2F_K4J$ZUJE?-ZE:[^M6PCK6L9TWK6MOZUKC. +MM:YWS>M>^_K7P`ZVL(=-[&(;^]C(3K:RE\WL9CO[V=".MK2G3>UJ6_O:V,ZV +MMK?-[6Y[^]O@#K>XQTWNYVN_O=\(ZWO.=-[WK;^][XSK>^ +M]\WO?OO[WP`/N,`'3O""&_S@"$^XPA?.\(8[_.$0C[C$)T[QBEO\XAC/N,8W +MSO&.>_SC(`^YR$=.\I*;_.0H3[G*5\[REKO\Y3"/NI8S[K6M\[U +MKGO]ZV`/N]C'3O:RF_WL:$^[VM?.]K:[_>UPC[O^ +M^_WO@`^\X`=/^,(;_O"(3[SB%\_XQCO^\9"/O.0G3_G*6_[RF,^\YC?/^I7S_K6N_[UL(^][&=/^]K;_O:XS[WN=\_[WOO^ +M]\`/OO"'3_SB&__XR$^^\I?/_.8[__G0C[[TIT_]ZEO_^MC/OO:WS_WN>__[ +MX`^_^,=/_O*;__SH3[_ZU\_^]KO__?"/O_SG3__ZV__^^,^__O?/__[[__\` +M&(`".(`$6(`&>(`(F(`*N(`,V(`.^(`0&($2.($46($6>($8F($:N($ +M^($@&((B.((D6((F>((HF((JN((LV((N^((P&(,R.(,T6(,V>(,XF(,ZN(,\ +MV(,^^(-`&(1".(1$6(1&>(1(F(1*N(1,V(1.^(10&(52.(546(56>(58F(5: +MN(5^(5@&(9B.(9D6(9F>(9HF(9JN(9LV(9N^(9P&(=R.(=T6(=V>(=X +MF(=ZN(=\V(=^^(>`&(B".(B$6(B&>(B(F(B*N(B,V(B.^(B0&(F2.(F46(F6 +M>(F8F(F:N(F^(F@&(JB.(JD6(JF>(JHF(JJN(JLV(JN^(JP&(NR.(NT +M6(NV>(NXF(NZN(N\V(N^^(O`&(S".(S$6(S&>(S(F(S*N(S,V(S.^(S0&(W2 +M.(W46(W6>(W8F(W:N(W^(W@&([B.([D6([F>([HF([JN([LV([N^([P +M&(_R.(_T6(_V>(_XF(_ZN(_\V(_^^(\`&9`".9`$69`&>9`(F9`*N9`,V9`. +M^9`0&9$2.9$469$6>9$8F9$:N9$^9$@&9(B.9(D69(F>9(HF9(JN9(L +MV9(N^9(P&9,R.9,T69,V>9,XF9,ZN9,\V9,^^9-`&91".91$691&>91(F91* +MN91,V91.^910&952.9546956>958F95:N95^95@&99B.99D699F>99H +MF99JN99LV99N^99P&9=R.9=T69=V>9=XF9=ZN9=\V9=^^9>`&9B".9B$69B& +M>9B(F9B*N9B,V9B.^9B0&9F2.9F469F6>9F8F9F:N9F^9F@&9JB.9JD +M69JF>9JHF9JJN9JLV9JN^9JP&9NR.9NT69NV>9NXF9NZN9N\V9N^^9O`&9S" +M.9S$69S&>9S(F9S*N9S,V9S.^9S0&9W2.9W469W6>9W8F9W:N9W^9W@ +M&9[B.9[D69[F>9[HF9[JN9[LV9[N^9[P&9_R.9_T69_V>9_XF9_ZN9_\V9_^ +M^9\`&J`".J`$6J`&>J`(FJ`*NJ`,VJ`.^J`0&J$2.J$46J$6>J$8FJ$:NJ$< +MVJ$>^J$@&J(B.J(D6J(F>J(HFJ(JNJ(LVJ(N^J(P&J,R.J,T6J,V>J,XFJ,Z +MNJ,\VJ,^^J-`&J1".J1$6J1&>J1(FJ1*NJ1,VJ1.^J10&J52.J546J56>J58 +MFJ5:NJ5^J5@&J9B.J9D6J9F>J9HFJ9JNJ9LVJ9N^J9P&J=R.J=T6J=V +M>J=XFJ=ZNJ=\VJ=^^J>`&JB".JB$6JB&>JB(FJB*NJB,VJB.^JB0&JF2.JF4 +M6JF6>JF8FJF:NJF^JF@&JJB.JJD6JJF>JJHFJJJNJJLVJJN^JJP&JNR +M.JNT6JNV>JNXFJNZNJN\VJN^^JO`&JS".JS$6JS&>JS(FJS*NJS,VJS.^JS0 +M&JW2.JW46JW6>JW8FJW:NJW^JW@&J[B.J[D6J[F>J[HFJ[JNJ[LVJ[N +M^J[P&J_R.J_T6J_V>J_XFJ_ZNJ_\VJ_^^J\`&[`".[`$6[`&>[`(F[`*N[`, +MV[`.^[`0&[$2.[$46[$6>[$8F[$:N[$^[$@&[(B.[(D6[(F>[(HF[(J +MN[(LV[(N^[(P&[,R.[,T6[,V>[,XF[,ZN[,\V[,^^[-`&[1".[1$6[1&>[1( +MF[1*N[1,V[1.^[10&[52.[546[56>[58F[5:N[5^[5@&[9B.[9D6[9F +M>[9HF[9JN[9LV[9N^[9P&[=R.[=T6[=V>[=XF[=ZN[=\V[=^^[>`&[B".[B$ +M6[B&>[B(F[B*N[B,V[B.^[B0&[F2.[F46[F6>[F8F[F:N[F^[F@&[JB +M.[JD6[JF>[JHF[JJN[JLV[JN^[JP&[NR.[NT6[NV>[NXF[NZN[N\V[N^^[O` +M&[S".[S$6[S&>[S(F[S*N[S,V[S.^[S0&[W2.[W46[W6>[W8F[W:N[W +M^[W@&[[B.[[D6[[F>[[HF[[JN[[LV[[N^[[P&[_R.[_T6[_V>[_XF[_ZN[_\ +MV[_^^[\`',`"/,`$7,`&?,`(G,`*O,`,W,`._,`0',$2/,$47,$6?,$8G,$: +MO,$_,$@',(B/,(D7,(F?,(HG,(JO,(LW,(N_,(P',,R/,,T7,,V?,,X +MG,,ZO,,\W,,^_,-`',1"/,1$7,1&?,1(G,1*O,1,W,1._,10',52/,547,56 +M?,58G,5:O,5_,5@',9B/,9D7,9F?,9HG,9JO,9LW,9N_,9P',=R/,=T +M7,=V?,=XG,=ZO,=\W,=^_,>`',B"/,B$7,B&?,B(G,B*O,B,W,B._,B0',F2 +M/,F47,F6?,F8G,F:O,F_,F@',JB/,JD7,JF?,JHG,JJO,JLW,JN_,JP +M',NR/,NT7,NV?,NXG,NZO,N\W,N^_,O`',S"/,S$7,S&?,S(G,S*O,S,W,S. +M_,S0',W2/,W47,W6?,W8G,W:O,W_,W@',[B/,[D7,[F?,[HG,[JO,[L +MW,[N_,[P',_R/,_T7,_V?,_XG,_ZO,_\W,_^_,\`'=`"/=`$7=`&?=`(G=`* +MO=`,W=`._=`0'=$2/=$47=$6?=$8G=$:O=$_=$@'=(B/=(D7=(F?=(H +MG=(JO=(LW=(N_=(P'=,R/=,T7=,V?=,XG=,ZO=,\W=,^_=-`'=1"/=1$7=1& +M?=1(G=1*O=1,W=1._=10'=52/=547=56?=58G=5:O=5_=5@'=9B/=9D +M7=9F?=9HG=9JO=9LW=9N_=9P'==R/==T7==V?==XG==ZO==\W==^_=>`'=B" +M/=B$7=B&?=B(G=B*O=B,W=B._=B0'=F2/=F47=F6?=F8G=F:O=F_=F@ +M'=JB/=JD7=JF?=JHG=JJO=JLW=JN_=JP'=NR/=NT7=NV?=NXG=NZO=N\W=N^ +M_=O`'=S"/=S$7=S&?=S(G=S*O=S,W=S._=S0'=W2/=W47=W6?=W8G=W:O=W< +MW=W>_=W@'=[B/=[D7=[F?=[HG=[JO=[LW=[N_=[P'=_R/=_T7=_V?=_XG=_Z +MO=_\W=_^_=\`'N`"/N`$7N`&?N`(GN`*ON`,WN`._N`0'N$2/N$47N$6?N$8 +MGN$:ON$_N$@'N(B/N(D7N(F?N(HGN(JON(LWN(N_N(P'N,R/N,T7N,V +M?N,XGN,ZON,\WN,^_N-`'N1"/N1$7N1&?N1(GN1*ON1,WN1._N10'N52/N54 +M7N56?N58GN5:ON5_N5@'N9B/N9D7N9F?N9HGN9JON9LWN9N_N9P'N=R +M/N=T7N=V?N=XGN=ZON=\WN=^_N>`'NB"/NB$7NB&?NB(GNB*ONB,WNB._NB0 +M'NF2/NF47NF6?NF8GNF:ONF_NF@'NJB/NJD7NJF?NJHGNJJONJLWNJN +M_NJP'NNR/NNT7NNV?NNXGNNZONN\WNN^_NO`'NS"/NS$7NS&?NS(GNS*ONS, +MWNS._NS0'NW2/NW47NW6?NW8GNW:ONW_NW@'N[B/N[D7N[F?N[HGN[J +MON[LWN[N_N[P'N_R/N_T7N_V?N_XGN_ZON_\WN_^_N\`'_`"/_`$7_`&?_`( +MG_`*O_`,W_`.__`0'_$2/_$47_$6?_$8G_$:O_$__$@'_(B/_(D7_(F +M?_(HG_(JO_(LW_(N__(P'_,R/_,T7_,V?_,XG_,ZO_,\W_,^__-`'_1"/_1$ +M7_1&?_1(G_1*O_1,W_1.__10'_52/_547_56?_58G_5:O_5__5@'_9B +M/_9D7_9F?_9HG_9JO_9LW_9N__9P'_=R/_=T7_=V?_=XG_=ZO_=\W_=^__>` +M'_B"/_B$7_B&?_B(G_B*O_B,W_B.__B0'_F2/_F47_F6?_F8G_F:O_F +M__F@'_JB/_JD7_JF?_JHG_JJO_JLW_JN__JP'_NR/_NT7_NV?_NXG_NZO_N\ +MW_N^__O`'_S"/_S$7_S&?_S(G_S*O_S,W_S.__S0'_W2/_W47_W6?_W8G_W: +MO_W__W@'_[B/_[D7_[F?_[HG_[JO_[LW_[N__[P'__R/__T7__V?__X +MG__ZO__\W__^__\`,``*P`%(``N@`3R`"#`!*L`%R``;H`-\@!`P`DK`"4@! +M*Z`%O(`8,`-JP`W(`3N@!_R`(#`$BL`12`)+H`D\@2@P!:K`%<@"6Z`+?($P +M,`;*P!E(`VN@#;R!.#`'ZL`=R`-[H`_\@4`P"`K!(4@$BZ`1/()(,`DJP27( +M!)N@$WR"4#`*2L$I2`6KH!6\@E@P"VK!+<@%NZ`7_()@,`R*P3%(!LN@&3R# +M:#`-JL$UR`;;H!M\@W`P#LK!.4@'ZZ`=O(-X,`_JP3W(!_N@'_R#@#`0"L)! +M2`@+H2$\A(@P$2K"1<@(&Z$C?(20,!)*PDE("2NA);R$F#`3:L)-R`D[H2?\ +MA*`P%(K"44@*2Z$I/(6H,!6JPE7("ENA*WR%L#`6RL)92`MKH2V\A;@P%^K" +M7<@+>Z$O_(7`,!@*PV%(#(NA,3R&R#`9*L-ER`R;H3-\AM`P&DK#:4@-JZ$U +MO(;8,!MJPVW(#;NA-_R&X#`3R/Z#$]JL?U +MR![;HWM\C_`Q/LK'^4@?ZZ-]O(_X,3_JQ_W('_NC?_R/`#)`"L@!22`+I($\ +MD`@R02K(!Z2/ +M_)%`,D@*R2%))(NDD3R22#))*LDER22;I)-\DE`R2DK)*4DEJZ25O))8,DMJ +MR2W));NDE_R28#),BLDQ22;+I)D\DV@R3:K)-#)/ZLD]R2?[I)_\DX`R4`K*04DH"Z6A/)2(,E$JRD7)*!NEHWR4D#)2 +M2LI)22DKI:6\E)@R4VK*3RLMY22_KI;V\E_@R7^K+?Z?O_)W`,W@* +MS^%)/(NG\3R>R#-Y*L_ER3R;I_-\GM`S>DK/Z4D]JZ?UO)[8,WMJS^W)/;NG +M]_R>X#-\BL_Q23[+I_D\G^@S?:K/]4I/ZZD]O:?X-)_JTWW*3_NI/_VG`#6@"M2!2E`+JD$]J`@UH2K4AZI/_:E`-:@*U:%*5(NJ +M43VJ2#6I*M6ERE2;JE-]JE`UJDK5J4I5JZI5O:I8-:MJU:W*5;NJ5_VJ8#6L +MBM6Q2E;+JED]JV@UK:K5M#6OZM6]RE?[ +MJE_]JX`UL`K6P4I8"ZMA/:R(-;$JUL7*6!NK8WVLD#6R2M;)2EDKJV6]K)@U +MLVK6SRZMY/:_H-;VJU_7* +M7MNK>WVO\#6^RM?Y2E_KJWV]K_@UO^K7_ZVO_;7`-M@*VV%+;(NML3VVR#;9 +M*MMERVR;K;-]MM`VVDK;:4MMJZVUO;;8-MMJVVW+;;NMM_VVX#;`NOX3V\B#?Q*M[% +MRW@;K^-]O)`W\DK>R4MY*Z_EO;R8-_-JWLW+>3NOY_V\H#?TBM[12WI+K^D] +MO:@W]:K>UVNO[;V]N#?WZM[=RWM[K^_]O<`W^`K? +MX4M\BZ_Q/;[(-_DJW^7+?)NO\WV^T#?Z2M_I2WVKK_6]OM@W^VK?[[`/_L%`.`@+X2%,A(NP$3["2#@)*^$ES(2; +ML!-^PE`X"DOA*4R%J[`5OL)8.`MKX2W,A;NP%_["8#@,B^$Q3(;+L!D^PV@X +M#:OA-#@/Z^$]S(?[L!_^PX`X$`OB04R( +M"[$A/L2(.!$KXD7,B!NQ(W[$D#@22^))3(DKL26^Q)@X$VOB3/($.*'$FR +MI,F3*%.J7,FRIO8,.*'4NVK-FS:-.J7//JW/'D"-+GDRYLN7+F#-KWLRY +ML^?/H$.+'DVZM.G3J%.K7LVZM>O7L&/+GDV[MNW;N'/KWLV[M^_?P(,+'TZ\ +MN/'CR),K7\Z\N?/GT*-+GTZ]NO7KV+-KW\Z]N_?OX,.+'T^^O/GSZ-.K7\^^ +MO?OW\./+GT^_OOW[^//KW\^_O_^_`0Q!!`PPQ!```$;(44890DQ!!`@01BCA +MA!1***`43S11X88<1GC0+06!Z-&!``1`XH$((`"`!059,$%"%0PD`@`7%%2C +MB@*I:$0``B10(@D"!'3B@1T6:>212":IY)),-NGDDU!&*>645%9I991-+)'$ +M%$\8,04(6SX!0@XVV`##"TAX"8(123!1Q!193$%%$1H*446;1!0A!0@F@'!A +M$4,\(<6#`K8@Q0M$6$&H%$4$086@(*`P1`H@Q)!##C.`4(0+63Q1A1-'$!&$ +MFY%.6NFE-X"@A`M0-"H%ETZ\L.H40R#1)A-)@'KEKKSN*@.!.<10H`PQR%## +MKV;"0,*O,`0[;+''PI`L"016:^VU!`+`K+/%0HLL@200V>NXY)9K[KGHIJON +MNNRVZ^Z2_\6[V#\"$FB@O/CFJ^^^_/9;799)@-#$&VZ`\,08=%0J@\(Z'*N# +MM"!LJX`,+A18<0QAV)"IH2"T4$<:9%3:\1D@1PR""RB_D,8<;_CK\LLPQRSS +MS&G=0L^!-0HIT```9"#0@40D(07-1!=M]-%()ZWTTDPW[?334+]&8D`UDLBS +M0#X'$/3047?M]==@ARWVV&27;?;9:"<-"8TV`H!C0#KRZ&,`0.I,&VP3=.%#EQSHAT0^3IKJL!'X2\"!YI"'-L3`CH@+Q4!"T0X_ +MFJ@@/"J(`"(Y24G"8PI,$(.)`K`%*_KREV'`(@3I41!Z=*$@77CD.VHI2;\9 +MY)+KTV06FD"Q^=4/E$T0)0!(V089H+(=JA0(*UWI2D`"0`#+9.8[<*E+$_42 +MF/"4HC`)@L/(!<\+!?'"(]W!S'^XPY)IQ*0TFS`#3PH.F]KDY@R^&!``40E*0(QD$"0@IRP +M-*<`P$>0#1B2>KTC@2*UISK\+0"E_U,I2P7B4I@2)):4NR!!.G!31>Z4D:8# +M`/X4`-3^";6E+X5H3&4)1()\H*EI?&KJ3(?+(9"(!QJ5(5@'X",!+'*L;]T> +M`'!)!!+U(*UJU=PA`\#6<\95=3PEJYM(Y`.\YG5Z.^JK6P/[UZB2]+&0C:QD +M$W*[00ZDC+M#8TY_)Z0#U8]X=SQ>0!@GTXA2SK)8`VM.&*B1A"'ES4Q"FP-U` +M.8$*01B"?X-&*_E600BXFL)V]V0$2.4-4$E@TQ`+ISB).@)3"]N;Q*:$`0I9`$$5G@"$ZK0!.[FB592J.ZC2`PI"V-8 +MPT`NL12([&`7NZ"Y8`ZSF,>L'S24@0UL>$.E:C`#!9#YS7".LYSG3.,[S>\R,9C7'X%ANUK.@!TWH0AOZT(A.M*(7S6BO\#G-:XY!H!M-Z4I;^M*8 +MSK2F-\WI3GOZTZ`.M:A'3>I2F_K4J$ZUJE?-ZE:[^M6PCK6L9TWK6MOZUKC. +MM:YWS>M>^_K7P`ZVL(=-[&(;^]C(3K:RE\WL9CO[V=".MK2G3>UJ6_O:V,ZV +MMK?-[6Y[^]O@#K>XQTWNYVN_O=\(ZWO.=-[WK;^][XSK>^ +M]\WO?OO[WP`/N,`'3O""&_S@"$^XPA?.\(8[_.$0C[C$)T[QBEO\XAC/N,8W +MSO&.>_SC(`^YR$=.\I*;_.0H3[G*5\[REKO\Y3"/NI8S[K6M\[U +MKGO]ZV`/N]C'3O:RF_WL:$^[VM?.]K:[_>UPC[O^ +M^_WO@`^\X`=/^,(;_O"(3[SB%\_XQCO^\9"/O.0G3_G*6_[RF,^\YC?/^I7S_K6N_[UL(^][&=/^]K;_O:XS[WN=\_[WOO^ +M]\`/OO"'3_SB&__XR$^^\I?/_.8[__G0C[[TIT_]ZEO_^MC/OO:WS_WN>__[ +MX`^_^,=/_O*;__SH3[_ZU\_^]KO__?"/O_SG3__ZV__^^,^__O?/__[[__\` +M&(`".(`$6(`&>(`(F(`*N(`,V(`.^(`0&($2.($46($6>($8F($:N($ +M^($@&((B.((D6((F>((HF((JN((LV((N^((P&(,R.(,T6(,V>(,XF(,ZN(,\ +MV(,^^(-`&(1".(1$6(1&>(1(F(1*N(1,V(1.^(10&(52.(546(56>(58F(5: +MN(5^(5@&(9B.(9D6(9F>(9HF(9JN(9LV(9N^(9P&(=R.(=T6(=V>(=X +MF(=ZN(=\V(=^^(>`&(B".(B$6(B&>(B(F(B*N(B,V(B.^(B0&(F2.(F46(F6 +(>(F8F(F:^!,` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_rockridge_new.iso.Z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_rockridge_new.iso.Z.uu new file mode 100644 index 0000000..3ef253b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_rockridge_new.iso.Z.uu @@ -0,0 +1,208 @@ +$FreeBSD: head/lib/libarchive/test/test_read_format_iso_rockridge_new.iso.Z.uu 201247 2009-12-30 05:59:21Z kientzle $ + +begin 644 test_read_format_iso_rockridge_new.iso.Z +M'YV0``(*'$BPH,&#"!,J7,BPH<.'$"-*G$BQHL6+&#-JW,BQH\>/($.*'$FR +MI,F3*%.J7,FRIO8,.*'4NVK-FS:-.J7//JW/'D"-+GDRYLN7+F#-KWLRY +ML^?/H$.+'DVZM.G3J%.K7LVZM>O7L&/+GDV[MNW;N'/KWLV[M^_?P(,+'TZ\ +MN/'CR),K7\Z\N?/GT*-+GTZ]NO7KV+-KW\Z]N_?OX,.+'T^^O/GSZ-.K7\^^ +MO?OW\./+GT^_OOW[^//KW\^_O_^_`0Q!!`PPQ!```$;(44890DQ!!`@01BCA +MA!1***`43S11X88<1GA0#Q@,A$$/'QT(0``F'H@``@!84)`%$R14P4`B`'!! +M03>R*!"+1@0@0`(GDB!`0"D>V.&12":IY)),-NGDDU!&*>645%9IY9583MG$ +M$DE,\8014X#0Y1,@Y&"##3"\@`28(!B1!!-%3)'%%%04H:$05;Q)1!%2@&`" +M"!<6,<034CPH8`M2O$"$%89*44005!`*`@I#I`!"##GD,`,(1;B0Q1-5.'$$ +M$4'`.6FEEV9Z`PA*N`#%HU)XZ<0+K4XQ!!)O,I&$J%GVZFNO,A"8`PPYR'"# +M##/$,,.R!)(0++'$&HNLLLS"0`*!V&:K+8$`/#MLL<M]MI,0V(CC@#H&!"//@(9@)`^GWC@ +M%%`<$(`O[P`@A10%!!`(%%BP$$`[00P41#M:#S2`U0+Y6)``/0]T`15&:!"` +M`SW^&&0;"6QP00,AD$"ZZ:B3,$01'`2004&S&]1.0>VX\39!.0Y$M^AW#WDB +MD2@.7OCAB2_>N$"/1_XSY40*/Q#F.'+N.>AUCU[ZZ:FOSCT)`.`1=$$ARATW +M@MD'GW<``WAM?`").-$$`@>2D88B1:`A"`42E=.6`()34@X^,FO`0="0QCD0`8VI,$-:X"A#&EH +MP\L%<(?3\^%`@'@](C+0@T9,G2,``(]_^/&/\#B('2M')`7(J0E8U&()!=?% +M1LB/`0>:0Q[:8$8TPK`=H1A(*-KQQC?>4`!]_*,?X3$%)BS`1`1@H0L1B+T! +M`$D`=W0E#E6WO=9)`@#O$*4?`V<0(X(@BBE:P"$3B;$2OL^130`C`"1)R3.N +M00:7S*1`-ME)'7XRE[I\1RD=H**`#(`.;8!#0%B91UH^T)S?HP0`W*'+?[CC +M(*3#@`,*<`)@$DF864#DKI8P@RT>\XN1G&0EUS"#:&J2DSKTY.78J4MWE!(" +MW03`-\-)`(&0LY;=PR@Z6V<)`+2CG;?K92U_2<@I#G.?-/!G(P&Z3($ZDP8& +MG29""8(B:U[NH[IL1RDE<*"*#JFB$@6G.`%PT7.6LYP=94<[V2%(#Y8T`/C4 +M9Q9KH-+"(5.9S!QH#6(:$&HFU*8\5*HNV5'*"!SHAJEL81E8V2-9PK*MK]PH +M!#NZCG:N`YX)D"<][6G2?";2!E4-P%4#VDPTVH"K`/`J317*P[KJA$ +MAPI4H@;1`4?5:#G9AA[=&7!KY]L1^J`HO"(Q\GB77%Y`'O=)QD[OLP'!`%OQ +MJ%F-`D!WF1-([T1KQ](2+P#O0Y[^5`N`YA5DHVA$^<5``5#@%<*20!"E_`5`YB`"DD%`$$&!K"$M";!"(>5$YWL9#`[ +MU9<*21@"W^`4A"F<=U!.H$(0AH!@HMFJOU40@JZF8-X^&4%2?!-4$MPT!$@E +MX0E.,!BHYMLI"'GXOBE><8O%M*<0SS@)?!)3CO&;A"98,0L@L,(3F%"%)IQW +M3[;R+A0BY6))@5C$)%;RBZ7@9`SCV`763;.:U\SFFZ&A#&Q@PQL4T.8ZV_G. +M>,ZSGO?,YS[[^<^`#K2@!TWH0AOZT(A.M*(7S>A&._K1D(ZTI"=-Z4I;^M*8 +MSK2F-\WI3GOZTZ`.M:A'3>I2F_K4J$ZUJE?-ZE:[^M6PCK6L9TWK6MOZUKC. +MM:YWS>M>^_K7P`ZVL(=-[&(;^]C(3K:RE\WL9CO[V=".MK2G3>UJ6_O:V,ZV +MMK?-[6Y[^]O@#K>XQTWNYVN_O=\(ZWO.=-[WK;^][XSK>^ +M]\WO?OO[WP`/N,`'3O""&_S@"$^XPA?.\(8[_.$0C[C$)T[QBEO\XAC/N,8W +MSO&.>_SC(`^YR$=.\I*;_.0H3[G*5\[REKO\Y3"/NI8S[K6M\[U +MKGO]ZV`/N]C'3O:RF_WL:$^[VM?.]K:[_>UPC[O^ +M^_WO@`^\X`=/^,(;_O"(3[SB%\_XQCO^\9"/O.0G3_G*6_[RF,^\YC?/^I7S_K6N_[UL(^][&=/^]K;_O:XS[WN=\_[WOO^ +M]\`/OO"'3_SB&__XR$^^\I?/_.8[__G0C[[TIT_]ZEO_^MC/OO:WS_WN>__[ +MX`^_^,=/_O*;__SH3[_ZU\_^]KO__?"/O_SG3__ZV__^^,^__O?/__[[__\` +M&(`".(`$6(`&>(`(F(`*N(`,V(`.^(`0&($2.($46($6>($8F($:N($ +M^($@&((B.((D6((F>((HF((JN((LV((N^((P&(,R.(,T6(,V>(,XF(,ZN(,\ +MV(,^^(-`&(1".(1$6(1&>(1(F(1*N(1,V(1.^(10&(52.(546(56>(58F(5: +MN(5^(5@&(9B.(9D6(9F>(9HF(9JN(9LV(9N^(9P&(=R.(=T6(=V>(=X +MF(=ZN(=\V(=^^(>`&(B".(B$6(B&>(B(F(B*N(B,V(B.^(B0&(F2.(F46(F6 +M>(F8F(F:N(F^(F@&(JB.(JD6(JF>(JHF(JJN(JLV(JN^(JP&(NR.(NT +M6(NV>(NXF(NZN(N\V(N^^(O`&(S".(S$6(S&>(S(F(S*N(S,V(S.^(S0&(W2 +M.(W46(W6>(W8F(W:N(W^(W@&([B.([D6([F>([HF([JN([LV([N^([P +M&(_R.(_T6(_V>(_XF(_ZN(_\V(_^^(\`&9`".9`$69`&>9`(F9`*N9`,V9`. +M^9`0&9$2.9$469$6>9$8F9$:N9$^9$@&9(B.9(D69(F>9(HF9(JN9(L +MV9(N^9(P&9,R.9,T69,V>9,XF9,ZN9,\V9,^^9-`&91".91$691&>91(F91* +MN91,V91.^910&952.9546956>958F95:N95^95@&99B.99D699F>99H +MF99JN99LV99N^99P&9=R.9=T69=V>9=XF9=ZN9=\V9=^^9>`&9B".9B$69B& +M>9B(F9B*N9B,V9B.^9B0&9F2.9F469F6>9F8F9F:N9F^9F@&9JB.9JD +M69JF>9JHF9JJN9JLV9JN^9JP&9NR.9NT69NV>9NXF9NZN9N\V9N^^9O`&9S" +M.9S$69S&>9S(F9S*N9S,V9S.^9S0&9W2.9W469W6>9W8F9W:N9W^9W@ +M&9[B.9[D69[F>9[HF9[JN9[LV9[N^9[P&9_R.9_T69_V>9_XF9_ZN9_\V9_^ +M^9\`&J`".J`$6J`&>J`(FJ`*NJ`,VJ`.^J`0&J$2.J$46J$6>J$8FJ$:NJ$< +MVJ$>^J$@&J(B.J(D6J(F>J(HFJ(JNJ(LVJ(N^J(P&J,R.J,T6J,V>J,XFJ,Z +MNJ,\VJ,^^J-`&J1".J1$6J1&>J1(FJ1*NJ1,VJ1.^J10&J52.J546J56>J58 +MFJ5:NJ5^J5@&J9B.J9D6J9F>J9HFJ9JNJ9LVJ9N^J9P&J=R.J=T6J=V +M>J=XFJ=ZNJ=\VJ=^^J>`&JB".JB$6JB&>JB(FJB*NJB,VJB.^JB0&JF2.JF4 +M6JF6>JF8FJF:NJF^JF@&JJB.JJD6JJF>JJHFJJJNJJLVJJN^JJP&JNR +M.JNT6JNV>JNXFJNZNJN\VJN^^JO`&JS".JS$6JS&>JS(FJS*NJS,VJS.^JS0 +M&JW2.JW46JW6>JW8FJW:NJW^JW@&J[B.J[D6J[F>J[HFJ[JNJ[LVJ[N +M^J[P&J_R.J_T6J_V>J_XFJ_ZNJ_\VJ_^^J\`&[`".[`$6[`&>[`(F[`*N[`, +MV[`.^[`0&[$2.[$46[$6>[$8F[$:N[$^[$@&[(B.[(D6[(F>[(HF[(J +MN[(LV[(N^[(P&[,R.[,T6[,V>[,XF[,ZN[,\V[,^^[-`&[1".[1$6[1&>[1( +MF[1*N[1,V[1.^[10&[52.[546[56>[58F[5:N[5^[5@&[9B.[9D6[9F +M>[9HF[9JN[9LV[9N^[9P&[=R.[=T6[=V>[=XF[=ZN[=\V[=^^[>`&[B".[B$ +M6[B&>[B(F[B*N[B,V[B.^[B0&[F2.[F46[F6>[F8F[F:N[F^[F@&[JB +M.[JD6[JF>[JHF[JJN[JLV[JN^[JP&[NR.[NT6[NV>[NXF[NZN[N\V[N^^[O` +M&[S".[S$6[S&>[S(F[S*N[S,V[S.^[S0&[W2.[W46[W6>[W8F[W:N[W +M^[W@&[[B.[[D6[[F>[[HF[[JN[[LV[[N^[[P&[_R.[_T6[_V>[_XF[_ZN[_\ +MV[_^^[\`',`"/,`$7,`&?,`(G,`*O,`,W,`._,`0',$2/,$47,$6?,$8G,$: +MO,$_,$@',(B/,(D7,(F?,(HG,(JO,(LW,(N_,(P',,R/,,T7,,V?,,X +MG,,ZO,,\W,,^_,-`',1"/,1$7,1&?,1(G,1*O,1,W,1._,10',52/,547,56 +M?,58G,5:O,5_,5@',9B/,9D7,9F?,9HG,9JO,9LW,9N_,9P',=R/,=T +M7,=V?,=XG,=ZO,=\W,=^_,>`',B"/,B$7,B&?,B(G,B*O,B,W,B._,B0',F2 +M/,F47,F6?,F8G,F:O,F_,F@',JB/,JD7,JF?,JHG,JJO,JLW,JN_,JP +M',NR/,NT7,NV?,NXG,NZO,N\W,N^_,O`',S"/,S$7,S&?,S(G,S*O,S,W,S. +M_,S0',W2/,W47,W6?,W8G,W:O,W_,W@',[B/,[D7,[F?,[HG,[JO,[L +MW,[N_,[P',_R/,_T7,_V?,_XG,_ZO,_\W,_^_,\`'=`"/=`$7=`&?=`(G=`* +MO=`,W=`._=`0'=$2/=$47=$6?=$8G=$:O=$_=$@'=(B/=(D7=(F?=(H +MG=(JO=(LW=(N_=(P'=,R/=,T7=,V?=,XG=,ZO=,\W=,^_=-`'=1"/=1$7=1& +M?=1(G=1*O=1,W=1._=10'=52/=547=56?=58G=5:O=5_=5@'=9B/=9D +M7=9F?=9HG=9JO=9LW=9N_=9P'==R/==T7==V?==XG==ZO==\W==^_=>`'=B" +M/=B$7=B&?=B(G=B*O=B,W=B._=B0'=F2/=F47=F6?=F8G=F:O=F_=F@ +M'=JB/=JD7=JF?=JHG=JJO=JLW=JN_=JP'=NR/=NT7=NV?=NXG=NZO=N\W=N^ +M_=O`'=S"/=S$7=S&?=S(G=S*O=S,W=S._=S0'=W2/=W47=W6?=W8G=W:O=W< +MW=W>_=W@'=[B/=[D7=[F?=[HG=[JO=[LW=[N_=[P'=_R/=_T7=_V?=_XG=_Z +MO=_\W=_^_=\`'N`"/N`$7N`&?N`(GN`*ON`,WN`._N`0'N$2/N$47N$6?N$8 +MGN$:ON$_N$@'N(B/N(D7N(F?N(HGN(JON(LWN(N_N(P'N,R/N,T7N,V +M?N,XGN,ZON,\WN,^_N-`'N1"/N1$7N1&?N1(GN1*ON1,WN1._N10'N52/N54 +M7N56?N58GN5:ON5_N5@'N9B/N9D7N9F?N9HGN9JON9LWN9N_N9P'N=R +M/N=T7N=V?N=XGN=ZON=\WN=^_N>`'NB"/NB$7NB&?NB(GNB*ONB,WNB._NB0 +M'NF2/NF47NF6?NF8GNF:ONF_NF@'NJB/NJD7NJF?NJHGNJJONJLWNJN +M_NJP'NNR/NNT7NNV?NNXGNNZONN\WNN^_NO`'NS"/NS$7NS&?NS(GNS*ONS, +MWNS._NS0'NW2/NW47NW6?NW8GNW:ONW_NW@'N[B/N[D7N[F?N[HGN[J +MON[LWN[N_N[P'N_R/N_T7N_V?N_XGN_ZON_\WN_^_N\`'_`"/_`$7_`&?_`( +MG_`*O_`,W_`.__`0'_$2/_$47_$6?_$8G_$:O_$__$@'_(B/_(D7_(F +M?_(HG_(JO_(LW_(N__(P'_,R/_,T7_,V?_,XG_,ZO_,\W_,^__-`'_1"/_1$ +M7_1&?_1(G_1*O_1,W_1.__10'_52/_547_56?_58G_5:O_5__5@'_9B +M/_9D7_9F?_9HG_9JO_9LW_9N__9P'_=R/_=T7_=V?_=XG_=ZO_=\W_=^__>` +M'_B"/_B$7_B&?_B(G_B*O_B,W_B.__B0'_F2/_F47_F6?_F8G_F:O_F +M__F@'_JB/_JD7_JF?_JHG_JJO_JLW_JN__JP'_NR/_NT7_NV?_NXG_NZO_N\ +MW_N^__O`'_S"/_S$7_S&?_S(G_S*O_S,W_S.__S0'_W2/_W47_W6?_W8G_W: +MO_W__W@'_[B/_[D7_[F?_[HG_[JO_[LW_[N__[P'__R/__T7__V?__X +MG__ZO__\W__^__\`,``*P`%(``N@`3R`"#`!*L`%R``;H`-\@!`P`DK`"4@! +M*Z`%O(`8,`-JP`W(`3N@!_R`(#`$BL`12`)+H`D\@2@P!:K`%<@"6Z`+?($P +M,`;*P!E(`VN@#;R!.#`'ZL`=R`-[H`_\@4`P"`K!(4@$BZ`1/()(,`DJP27( +M!)N@$WR"4#`*2L$I2`6KH!6\@E@P"VK!+<@%NZ`7_()@,`R*P3%(!LN@&3R# +M:#`-JL$UR`;;H!M\@W`P#LK!.4@'ZZ`=O(-X,`_JP3W(!_N@'_R#@#`0"L)! +M2`@+H2$\A(@P$2K"1<@(&Z$C?(20,!)*PDE("2NA);R$F#`3:L)-R`D[H2?\ +MA*`P%(K"44@*2Z$I/(6H,!6JPE7("ENA*WR%L#`6RL)92`MKH2V\A;@P%^K" +M7<@+>Z$O_(7`,!@*PV%(#(NA,3R&R#`9*L-ER`R;H3-\AM`P&DK#:4@-JZ$U +MO(;8,!MJPVW(#;NA-_R&X#`3R/Z#$]JL?U +MR![;HWM\C_`Q/LK'^4@?ZZ-]O(_X,3_JQ_W('_NC?_R/`#)`"L@!22`+I($\ +MD`@R02K(!Z2/ +M_)%`,D@*R2%))(NDD3R22#))*LDER22;I)-\DE`R2DK)*4DEJZ25O))8,DMJ +MR2W));NDE_R28#),BLDQ22;+I)D\DV@R3:K)-#)/ZLD]R2?[I)_\DX`R4`K*04DH"Z6A/)2(,E$JRD7)*!NEHWR4D#)2 +M2LI)22DKI:6\E)@R4VK*3RLMY22_KI;V\E_@R7^K+?Z?O_)W`,W@* +MS^%)/(NG\3R>R#-Y*L_ER3R;I_-\GM`S>DK/Z4D]JZ?UO)[8,WMJS^W)/;NG +M]_R>X#-\BL_Q23[+I_D\G^@S?:K/]4I/ZZD]O:?X-)_JTWW*3_NI/_VG`#6@"M2!2E`+JD$]J`@UH2K4AZI/_:E`-:@*U:%*5(NJ +M43VJ2#6I*M6ERE2;JE-]JE`UJDK5J4I5JZI5O:I8-:MJU:W*5;NJ5_VJ8#6L +MBM6Q2E;+JED]JV@UK:K5M#6OZM6]RE?[ +MJE_]JX`UL`K6P4I8"ZMA/:R(-;$JUL7*6!NK8WVLD#6R2M;)2EDKJV6]K)@U +MLVK6SRZMY/:_H-;VJU_7* +M7MNK>WVO\#6^RM?Y2E_KJWV]K_@UO^K7_ZVO_;7`-M@*VV%+;(NML3VVR#;9 +M*MMERVR;K;-]MM`VVDK;:4MMJZVUO;;8-MMJVVW+;;NMM_VVX#;`NOX3V\B#?Q*M[% +MRW@;K^-]O)`W\DK>R4MY*Z_EO;R8-_-JWLW+>3NOY_V\H#?TBM[12WI+K^D] +MO:@W]:K>UVNO[;V]N#?WZM[=RWM[K^_]O<`W^`K? +MX4M\BZ_Q/;[(-_DJW^7+?)NO\WV^T#?Z2M_I2WVKK_6]OM@W^VK?[[`/_L%`.`@+X2%,A(NP$3["2#@)*^$ES(2; +ML!-^PE`X"DOA*4R%J[`5OL)8.`MKX2W,A;NP%_["8#@,B^$Q3(;+L!D^PV@X +M#:OA-#@/Z^$]S(?[L!_^PX`X$`OB04R( +M"[$A/L2(.!$KXD7,B!NQ(W[$D#@22^))3(DKL26^Q)@X$VOB3/($.*'$FR +MI,F3*%.J7,FRIO8,.*'4NVK-FS:-.J7//JW/'D"-+GDRYLN7+F#-KWLRY +ML^?/H$.+'DVZM.G3J%.K7LVZM>O7L&/+GDV[MNW;N'/KWLV[M^_?P(,+'TZ\ +MN/'CR),K7\Z\N?/GT*-+GTZ]NO7KV+-KW\Z]N_?OX,.+'T^^O/GSZ-.K7\^^ +MO?OW\./+GT^_OOW[^//KW\^_O_^_`0Q!!`PPQ!```$;(44890DQ!!`@01BCA +MA!1***`43S11X88<1G@0-2\,]`(U'QT(0``F'H@``@!04A`E$R14P4`B`'!! +M03>R*!"+1@0@0`(GDB!`0"D>V.&12":IY)),-NGDDU!&*>645%9IY9583MG$ +M$DE,\8014X#0Y1,@Y&"##3"\@`28(!B1!!-%3)'%%%04H:$05;Q)1!%2@&`" +M"!<6,<034CPH8`M2O$"$%89*44005!`*`@I#I`!"##GD,`,(1;B0Q1-5.'$$ +M$4'`.6FEEV9Z`PA*N`#%HU)XZ<0+K4XQ!!)O,I&$J%GVZFNO,A"80PP%RA`# +M#C/0(`,-!)(0+`S#%GMLLLLV2^"UV&9+(`#/1AN#L<@JRRP,)!CYZ[GHIJON +MNNRVZ^Z[\,8K;Y/_U;O8/P(2:*"]_/;K[[\`!US=EDF`T,0;;H#PQ!AT7"K# +MI3CHD*P.RX+0K0(RN%"@QC&$8<.FB(+00AUID'&IR&>4;#$(+K3\0AISO"'P +MS#37;//-.*>5BR8'WDBD0`0`P(%`!Q*1A!0QL(@!T0!((<4733QA11%$!-V! +M0$,:+84,06<@T```:(U#T!X`'?;1,P2M@4`%G"U%#D%_()`!;M/0]@8"'>`V +ML0`$#<*.;M<0=`@"*>"V#4'7&-`";M^0\^.01R[YY)17;OGEF&>N^>8PF1C0 +MC28&+=#0`6B=]$!+!^`TU%)3+7I`5PN@-=<#>3V`V*\#4#8!6J<]T-H%:`WW +M0'(;H+7=`^%]@.DP]#W0WPAH+?A`A"N@->(T`K"`UHYS[OWWX(BG;QDD-N((@(X!\>@CD`$(^?.)!TX!Q0$!^/).TU(H0``"`04LL"``[0C" +M0(+0#K`19`">(]J0""(`GPWD`E0P@@8"X(`>_2A(;5```R0@`@R0((0C+"$) +MAE`$#@1@!`6!H4':49!VN*%]!,G10.3WP?I-L$BJ"^``"WC`!"ZP@06!8$%\ +M5)`*XBB#&^S@_$`H0A*:$(56)`$`]""T@@P-?N]#T!1]>+\`\.YH,0"@`!/A +MA"8DX$!D2(,<8D!$!"I0(`QTX$"42!`F4G!H!.$`%#GH0?J1H)!43*$)^0`` +M+1*$!%0(`R\"PHLP9'",CCP1D0[@)CBY8`8(^,QG.D?C`AC81I[6+ +M:2\Q.<\BK%2?6,VJ5K?ZFAM"52`Z!:A'!XJB@B;5I'ED*$N?6I`,2+6'\*3I +M.[`!OX +MREC.LI;+`V]<2V]/+H,KQEM\'KW*D3?6I?$ +M*>V;DXFKT<^QV<4TI>O5"'*U.(MYO4"5P69).5\9C#BM9Q9N$P<]D`[XM\59 +MW+*F-\WI3D/EAI062*'#'"2]/KBD9LXNFK$6:MC].8O,[6(@GQL_,E>-Y'<`8M*8E$GY;#0!+SSN1L'8M%^5&$+DI&]T_/9ZSBRQ'&D@;X-5F./&T +M/>Q,A_OC(`^YR#MR0XT+Q.'G]JDLU7UG2*M:TA0T>4`^\&IYNEEW!3&WOB$N +MRWY?G->GI2"\=5?S*RH<`'\C"/123E:@UF#B\ZW!S]L==%LF_7DW1\[U +MKGO]ZP.YX=4%LO2=JYR@N5[W=3&^:I>./2`@*'I<,UWR@J#<["&N\]1?[NZ8 +MVUWN<^4BX0A"N(>?W8S7@[IGY6B#O9L8YK88$4 +MGNECUGN9V!O_G:DTSJ,E^5WVEL^[=)6N_5Q/[ARB3U>+D)6 +M(#4R?-.YI_C/WL#QU&X[<7\?$!%0?O<>U[STIT]]V-Z0^0`(/NC3/?M_`UW@ +M3<2^\W4_=YO;&P"H1__K>7AH7(M>UVO_/BV;F'[5DU_#6A0F//[!__[#XR`> +MM6.(=S1"Q5>9P&B+)P=(-7KQ1W7@1T'[UW_\!P_/5WXF-`2-%0#<=5/5UX$> +M^(&:PR?M$``*0`6'$$1)``5?@"G#`BE(4`0@@"%#L`0QF`1$<`0PN"MU(@6W +M$@2B`H-0@"&1,BA,``)!*#4V&"<@,`55``500"A4T":2\H13D`18T"9O`H-R +M0B=VLH1VXH-4D`1#H#]P$@13`(.#X@14$`1#$(5&8RM&6`5"H"M3\()]8@22 +MHC^"D@1N,@20D@1/X`1+""H\V"D0V(@4I&"EW*"EIN(9M.(EX*`67&(:!Z`(@.(NT +M6(NVF!%H4`9LP`9O8#BW^(O`&(S".(S$6(S&>(S(F(S*N(S,V(S.^(S0&(W2 +M.(W46(W6>(W8F(W:N(W^(W@&([B.([D6([F>([HF([JN([LV([N^([P +M&(_R.(_T6(_V>(_XF(_ZN(_\V(_^^(\`&9`".9`$69`&>9`(F9`*N9`,V9`. +M^9`0&9$2.9$469$6>9$8F9$:N9$^9$@&9(B.9(D69(F>9(HF9(JN9(L +MV9(N^9(P&9,R.9,T69,V>9,XF9,ZN9,\V9,^^9-`&91".91$691&>91(F91* +MN91,V91.^910&952.9546956>958F95:N95^95@&99B.99D699F>99H +MF99JN99LV99N^99P&9=R.9=T69=V>9=XF9=ZN9=\V9=^^9>`&9B".9B$69B& +M>9B(F9B*N9B,V9B.^9B0&9F2.9F469F6>9F8F9F:N9F^9F@&9JB.9JD +M69JF>9JHF9JJN9JLV9JN^9JP&9NR.9NT69NV>9NXF9NZN9N\V9N^^9O`&9S" +M.9S$69S&>9S(F9S*N9S,V9S.^9S0&9W2.9W469W6>9W8F9W:N9W^9W@ +M&9[B.9[D69[F>9[HF9[JN9[LV9[N^9[P&9_R.9_T69_V>9_XF9_ZN9_\V9_^ +M^9\`&J`".J`$6J`&>J`(FJ`*NJ`,VJ`.^J`0&J$2.J$46J$6>J$8FJ$:NJ$< +MVJ$>^J$@&J(B.J(D6J(F>J(HFJ(JNJ(LVJ(N^J(P&J,R.J,T6J,V>J,XFJ,Z +MNJ,\VJ,^^J-`&J1".J1$6J1&>J1(FJ1*NJ1,VJ1.^J10&J52.J546J56>J58 +MFJ5:NJ5^J5@&J9B.J9D6J9F>J9HFJ9JNJ9LVJ9N^J9P&J=R.J=T6J=V +M>J=XFJ=ZNJ=\VJ=^^J>`&JB".JB$6JB&>JB(FJB*NJB,VJB.^JB0&JF2.JF4 +M6JF6>JF8FJF:NJF^JF@&JJB.JJD6JJF>JJHFJJJNJJLVJJN^JJP&JNR +M.JNT6JNV>JNXFJNZNJN\VJN^^JO`&JS".JS$6JS&>JS(FJS*NJS,VJS.^JS0 +M&JW2.JW46JW6>JW8FJW:NJW^JW@&J[B.J[D6J[F>J[HFJ[JNJ[LVJ[N +M^J[P&J_R.J_T6J_V>J_XFJ_ZNJ_\VJ_^^J\`&[`".[`$6[`&>[`(F[`*N[`, +MV[`.^[`0&[$2.[$46[$6>[$8F[$:N[$^[$@&[(B.[(D6[(F>[(HF[(J +MN[(LV[(N^[(P&[,R.[,T6[,V>[,XF[,ZN[,\V[,^^[-`&[1".[1$6[1&>[1( +MF[1*N[1,V[1.^[10&[52.[546[56>[58F[5:N[5^[5@&[9B.[9D6[9F +M>[9HF[9JN[9LV[9N^[9P&[=R.[=T6[=V>[=XF[=ZN[=\V[=^^[>`&[B".[B$ +M6[B&>[B(F[B*N[B,V[B.^[B0&[F2.[F46[F6>[F8F[F:N[F^[F@&[JB +M.[JD6[JF>[JHF[JJN[JLV[JN^[JP&[NR.[NT6[NV>[NXF[NZN[N\V[N^^[O` +M&[S".[S$6[S&>[S(F[S*N[S,V[S.^[S0&[W2.[W46[W6>[W8F[W:N[W +M^[W@&[[B.[[D6[[F>[[HF[[JN[[LV[[N^[[P&[_R.[_T6[_V>[_XF[_ZN[_\ +MV[_^^[\`',`"/,`$7,`&?,`(G,`*O,`,W,`._,`0',$2/,$47,$6?,$8G,$: +MO,$_,$@',(B/,(D7,(F?,(HG,(JO,(LW,(N_,(P',,R/,,T7,,V?,,X +MG,,ZO,,\W,,^_,-`',1"/,1$7,1&?,1(G,1*O,1,W,1._,10',52/,547,56 +M?,58G,5:O,5_,5@',9B/,9D7,9F?,9HG,9JO,9LW,9N_,9P',=R/,=T +M7,=V?,=XG,=ZO,=\W,=^_,>`',B"/,B$7,B&?,B(G,B*O,B,W,B._,B0',F2 +M/,F47,F6?,F8G,F:O,F_,F@',JB/,JD7,JF?,JHG,JJO,JLW,JN_,JP +M',NR/,NT7,NV?,NXG,NZO,N\W,N^_,O`',S"/,S$7,S&?,S(G,S*O,S,W,S. +M_,S0',W2/,W47,W6?,W8G,W:O,W_,W@',[B/,[D7,[F?,[HG,[JO,[L +MW,[N_,[P',_R/,_T7,_V?,_XG,_ZO,_\W,_^_,\`'=`"/=`$7=`&?=`(G=`* +MO=`,W=`._=`0'=$2/=$47=$6?=$8G=$:O=$_=$@'=(B/=(D7=(F?=(H +MG=(JO=(LW=(N_=(P'=,R/=,T7=,V?=,XG=,ZO=,\W=,^_=-`'=1"/=1$7=1& +M?=1(G=1*O=1,W=1._=10'=52/=547=56?=58G=5:O=5_=5@'=9B/=9D +M7=9F?=9HG=9JO=9LW=9N_=9P'==R/==T7==V?==XG==ZO==\W==^_=>`'=B" +M/=B$7=B&?=B(G=B*O=B,W=B._=B0'=F2/=F47=F6?=F8G=F:O=F_=F@ +M'=JB/=JD7=JF?=JHG=JJO=JLW=JN_=JP'=NR/=NT7=NV?=NXG=NZO=N\W=N^ +M_=O`'=S"/=S$7=S&?=S(G=S*O=S,W=S._=S0'=W2/=W47=W6?=W8G=W:O=W< +MW=W>_=W@'=[B/=[D7=[F?=[HG=[JO=[LW=[N_=[P'=_R/=_T7=_V?=_XG=_Z +MO=_\W=_^_=\`'N`"/N`$7N`&?N`(GN`*ON`,WN`._N`0'N$2/N$47N$6?N$8 +MGN$:ON$_N$@'N(B/N(D7N(F?N(HGN(JON(LWN(N_N(P'N,R/N,T7N,V +M?N,XGN,ZON,\WN,^_N-`'N1"/N1$7N1&?N1(GN1*ON1,WN1._N10'N52/N54 +M7N56?N58GN5:ON5_N5@'N9B/N9D7N9F?N9HGN9JON9LWN9N_N9P'N=R +M/N=T7N=V?N=XGN=ZON=\WN=^_N>`'NB"/NB$7NB&?NB(GNB*ONB,WNB._NB0 +M'NF2/NF47NF6?NF8GNF:ONF_NF@'NJB/NJD7NJF?NJHGNJJONJLWNJN +M_NJP'NNR/NNT7NNV?NNXGNNZONN\WNN^_NO`'NS"/NS$7NS&?NS(GNS*ONS, +MWNS._NS0'NW2/NW47NW6?NW8GNW:ONW_NW@'N[B/N[D7N[F?N[HGN[J +MON[LWN[N_N[P'N_R/N_T7N_V?N_XGN_ZON_\WN_^_N\`'_`"/_`$7_`&?_`( +MG_`*O_`,W_`.__`0'_$2/_$47_$6?_$8G_$:O_$__$@'_(B/_(D7_(F +M?_(HG_(JO_(LW_(N__(P'_,R/_,T7_,V?_,XG_,ZO_,\W_,^__-`'_1"/_1$ +M7_1&?_1(G_1*O_1,W_1.__10'_52/_547_56?_58G_5:O_5__5@'_9B +M/_9D7_9F?_9HG_9JO_9LW_9N__9P'_=R/_=T7_=V?_=XG_=ZO_=\W_=^__>` +M'_B"/_B$7_B&?_B(G_B*O_B,W_B.__B0'_F2/_F47_F6?_F8G_F:O_F +M__F@'_JB/_JD7_JF?_JHG_JJO_JLW_JN__JP'_NR/_NT7_NV?_NXG_NZO_N\ +MW_N^__O`'_S"/_S$7_S&?_S(G_S*O_S,W_S.__S0'_W2/_W47_W6?_W8G_W: +MO_W__W@'_[B/_[D7_[F?_[HG_[JO_[LW_[N__[P'__R/__T7__V?__X +MG__ZO__\W__^__\`,``*P`%(``N@`3R`"#`!*L`%R``;H`-\@!`P`DK`"4@! +M*Z`%O(`8,`-JP`W(`3N@!_R`(#`$BL`12`)+H`D\@2@P!:K`%<@"6Z`+?($P +M,`;*P!E(`VN@#;R!.#`'ZL`=R`-[H`_\@4`P"`K!(4@$BZ`1/()(,`DJP27( +M!)N@$WR"4#`*2L$I2`6KH!6\@E@P"VK!+<@%NZ`7_()@,`R*P3%(!LN@&3R# +M:#`-JL$UR`;;H!M\@W`P#LK!.4@'ZZ`=O(-X,`_JP3W(!_N@'_R#@#`0"L)! +M2`@+H2$\A(@P$2K"1<@(&Z$C?(20,!)*PDE("2NA);R$F#`3:L)-R`D[H2?\ +MA*`P%(K"44@*2Z$I/(6H,!6JPE7("ENA*WR%L#`6RL)92`MKH2V\A;@P%^K" +M7<@+>Z$O_(7`,!@*PV%(#(NA,3R&R#`9*L-ER`R;H3-\AM`P&DK#:4@-JZ$U +MO(;8,!MJPVW(#;NA-_R&X#`3R/Z#$]JL?U +MR![;HWM\C_`Q/LK'^4@?ZZ-]O(_X,3_JQ_W('_NC?_R/`#)`"L@!22`+I($\ +MD`@R02K(!Z2/ +M_)%`,D@*R2%))(NDD3R22#))*LDER22;I)-\DE`R2DK)*4DEJZ25O))8,DMJ +MR2W));NDE_R28#),BLDQ22;+I)D\DV@R3:K)-#)/ZLD]R2?[I)_\DX`R4`K*04DH"Z6A/)2(,E$JRD7)*!NEHWR4D#)2 +M2LI)22DKI:6\E)@R4VK*3RLMY22_KI;V\E_@R7^K+?Z?O_)W`,W@* +MS^%)/(NG\3R>R#-Y*L_ER3R;I_-\GM`S>DK/Z4D]JZ?UO)[8,WMJS^W)/;NG +M]_R>X#-\BL_Q23[+I_D\G^@S?:K/]4I/ZZD]O:?X-)_JTWW*3_NI/_VG`#6@"M2!2E`+JD$]J`@UH2K4AZI/_:E`-:@*U:%*5(NJ +M43VJ2#6I*M6ERE2;JE-]JE`UJDK5J4I5JZI5O:I8-:MJU:W*5;NJ5_VJ8#6L +MBM6Q2E;+JED]JV@UK:K5M#6OZM6]RE?[ +MJE_]JX`UL`K6P4I8"ZMA/:R(-;$JUL7*6!NK8WVLD#6R2M;)2EDKJV6]K)@U +MLVK6SRZMY/:_H-;VJU_7* +M7MNK>WVO\#6^RM?Y2E_KJWV]K_@UO^K7_ZVO_;7`-M@*VV%+;(NML3VVR#;9 +M*MMERVR;K;-]MM`VVDK;:4MMJZVUO;;8-MMJVVW+;;NMM_VVX#;`NOX3V\B#?Q*M[% +MRW@;K^-]O)`W\DK>R4MY*Z_EO;R8-_-JWLW+>3NOY_V\H#?TBM[12WI+K^D] +MO:@W]:K>UVNO[;V]N#?WZM[=RWM[K^_]O<`W^`K? +MX4M\BZ_Q/;[(-_DJW^7+?)NO\WV^T#?Z2M_I2WVKK_6]OM@W^VK?[[`/_L%`.`@+X2%,A(NP$3["2#@)*^$ES(2; +ML!-^PE`X"DOA*4R%J[`5OL)8.`MKX2W,A;NP%_["8#@,B^$Q3(;+L!D^PV@X +M#:OA-#@/Z^$]S(?[L!_^PX`X$`OB04R( +M"[$A/L2(.!$KXD7,B!NQ(W[$D#@22^))3(DKL26^Q)@X$VOB3R^-Y +M3(_KL3V^Q_@X'^OC?[-O_LW`.3@+Y^%,G(NS<3[.R#DY*^?ES)R;LW-^SM`Y +M.DOGZ4R=J[-UOL[8.3MKY^W,G;NS=_[.X#D\B^?Q3)[+LWD^S^@Y/:OG] +MV[-[?L_P.3[+Y_E,G^NS?;[/^#D_Z^?]S)_[LW_^SP`Z0`OH`4V@"[2!/M`( +M.D$KZ`7-H!NT@W[0$#I"2^@)3:$KM(6^T!@Z0VOH#4VOZ[6]OM?X.E_KZWW-K_NUO_[7`#M@ +M"^R!3;`+ML$^V`@[82OLA[;/_ME`.V@+[:%-M(NVT3[:2#MI*^VES;2;MM-^VE`[:DOMJ4VU +MJ[;5OMI8.VMK[:W-M;NVU_[:8#MLB^VQ3;;+MMD^VV@[;:OMM#MOZ^V]S;?[MM_^VX`[<`ONP4VX"[?A/MR(.W$K[L7- +MN!NWXW[2OOYV#M[:^_MS;V[M_?^ +MWN`[?(OO\4V^R[?Y/M_H.WVK[_7-OMNW^W[?\#M^R^_Y3;_KM_V^W_@[?^OO +M_[DO_^7`/)@+\V%.S(NY,3_FR#R9*_-ESLR;N3-_YM`\FDOS:4[-J[DUO^;8 +M/)MK\VW.S;NY-__FX#R3_OZ#V]J_?USM[; +MNWM_[_`]OLOW^4[?Z[M]O^_X/;_K]_W.W_N[?__O`#[`"_@!3^`+O($_\`@^ +MP2OX!<_@&[R#?_`0/L)+^`E/X2N\A;_P&#[#:_@-S^$[O(?_\"`^Q(OX$4_B +M2[R)/_$H/L6K^!7/XEN\BW_Q,#[&R_@93^-KO(V_\3@^Q^OX'<_C>[R/__%` +M/L@+^2%/Y(N\D3_R2#[)*_DES^2;O)-_\E`^RDOY*4_EJ[R5O_)8/LMK^2W/ +MY;N\E__R8#[,B_DQ3^;+O)D_\V@^S:OY-<_FV[R;?_-P/L[+^3E/Y^N\G;_S +M>#[/Z_D]S^?[O)__\X`^T`OZ04_H"[VA/_2(/M$K^D7/Z!N]HW_TD#[22_I) +M3^DKO:6_])@^TVOZ3<_I.[VG__2@/M2+^E%/ZDN]J3_UJ#[5J_I5S^I;O:M_ +M];`^ULOZ64_K:[VMO_6X/M?K^EW/ZWN]K__UP#[8"_MA3^R+O;$_]L@^V2O[ +M9<_LF[VS?_;0/MI+^VE/[:N]M;_VV#[;:_MMS^V[O;?_]N`^W(O[<4_NR[VY +M/_?H/MVK^W7/[MN]NW_W\#[>R_MY3^_KO;V_]_@^W^O[?<_O^[V___<`/^`+ +M_(%/\`N^P3_X"#_A*_R%S_`;OL-_^!`_XDO\B4_Q*[[%O_@8/^-K_(W/\3N^ +MQ__X(#_DB_R13_)+OLD_^2@_Y:O\E<_R6[[+?_DP/^;+_)E/\VN^S;_Y.#_G +MZ_R=S_-[OL__^4`_Z`O]H4_TB[[1/_I(/^DK_:7/])N^TW_Z4#_J2_VI3_6K +MOM6_^E@_ZVO]K<_UN[[7__I@/^R+_;%/]LN^V3_[:#_MJ_VUS_;;OMM_^W`_ +M[LO]N4_WZ[[=O_MX/^_K_;W/]_N^W__[@#_P"_[!3_@+O^$__(@_\2O^Q<_X +M&[_C?_R0/_)+_LE/^2N_Y;_\F#_S:_[-S_D[O^?__*`_](O^T4_Z2[_I/_VH +M/_6K_M7/^EN_ZW_]L#_VR_[93_MKO^V__;@_]^O^W<_[>[_O__W`/_@+_^%/ +M_(N_\3_^R#_Y*__ES_R;O_-__M`_^DO_Z4_]J[_UO_[8/_MK_^W/_;N_]__^ +MX#_\B__Q3_[+O_D__^@__:O_]<_^V[_[?__P/_[+__E/_^N__;__^#__Z__] +MS__[O____P!@`"@`#H`$8`%H`!Z`"&`"J``N@`Q@`^@`/H`08`0H`4Z`%&`% +M:`%>@!A@!J@!;H`<8`?H`7Z`(&`(*`*.@"1@"6@"GH`H8`JH`JZ`+&`+Z`*^ +M@#!@#"@#SH`T8`UH`]Z`.&`.J`/N@#Q@#^@#_H!`8!`H!`Z!1&`1:`0>@4A@ +M$J@$+H%,8!/H!#Z!4&`4*`5.@51@%6@%7H%88!:H!6Z!7&`7Z`5^@6!@&"@& +MCH%D8!EH!IZ!:&`:J`:N@6Q@&^@&OH%P8!PH!\Z!=&`=:`?>@7A@'J@'[H%\ +M8!_H!_Z!@&`@*`@.@H1@(6@('H*(8"*H""Z"C&`CZ`@^@I!@)"@)3H*48"5H +M"5Z"F&`FJ`EN@IQ@)^@)?H*@8"@H"HZ"I&`I:`J>@JA@*J@*KH*L8"OH"KZ" +ML&`L*`O.@K1@+6@+WH*X8"ZH"^Z"O&`OZ`O^@L!@,"@,#H/$8#%H#!Z#R&`R +MJ`PN@\Q@,^@,/H/08#0H#4Z#U&`U:`U>@]A@-J@-;H/<8#?H#7Z#X&`X*`Z. +M@^1@.6@.GH/H8#JH#JZ#[&`[Z`Z^@_!@/"@/SH/T8#UH#]Z#^&`^J`_N@_Q@ +M/^@/_H,`84`H$`Z$!&%!:!`>A`AA0J@0+H0,84/H$#Z$$&%$*!%.A!1A16@1 +M7H0884:H$6Z$'&%'Z!%^A"!A2"@2CH0D84EH$IZ$*&%*J!*NA"QA2^@2OH0P +M84PH$\Z$-&%-:!/>A#AA3J@3[H0\84_H$_Z$0&%0*!0.A41A46@4'H5(85*H +M%"Z%3&%3Z!0^A5!A5"@53H54855H%5Z%6&%6J!5NA5QA5^@5?H5@85@H%HZ% +M9&%9:!:>A6AA6J@6KH5L85OH%KZ%<&%<*!?.A71A76@7WH5X85ZH%^Z%?&%? +MZ!?^A8!A8"@8#H:$86%H&!Z&B&%BJ!@NAHQA8^@8/H:0860H&4Z&E&%E:!E> +MAIAA9J@9;H:<86?H&7Z&H&%H*!J.AJ1A:6@:GH:H86JH&JZ&K&%KZ!J^AK!A +M;"@;SH:T86UH&]Z&N&%NJ!ONAKQA;^@;_H;`87`H'`Z'Q&%Q:!P>A\AA"@>CH?D +M87EH'IZ'Z&%ZJ!ZNA^QA>^@>OH?P87PH'\Z']&%]:!_>A_AA?J@?[H?\87_H +M'_Z'`&*`*"`.B`1B@6@@'H@(8H*H("Z(#&*#Z"`^B!!BA"@A3H@48H5H(5Z( +M&&*&J"%NB!QBA^@A?H@@8H@H(HZ()&*):"*>B"ABBJ@BKH@L8HOH(KZ(,&*, +M*"/.B#1BC6@CWH@X8HZH(^Z(/&*/Z"/^B$!BD"@D#HE$8I%H)!Z)2&*2J"0N +MB4QBD^@D/HE08I0H)4Z)5&*5:"5>B5ABEJ@E;HE<8I?H)7Z)8&*8*":.B61B +MF6@FGHEH8IJH)JZ);&*;Z":^B7!BG"@GSHET8IUH)]Z)>&*>J"?NB7QBG^@G +M_HF`8J`H*`Z*A&*A:"@>BHABHJ@H+HJ,8J/H*#Z*D&*D*"E.BI1BI6@I7HJ8 +M8J:H*6Z*G&*GZ"E^BJ!BJ"@JCHJD8JEH*IZ*J&*JJ"JNBJQBJ^@JOHJP8JPH +M*\Z*M&*M:"O>BKABKJ@K[HJ\8J_H*_Z*P&*P*"P.B\1BL6@L'HO(8K*H+"Z+ +MS&*SZ"P^B]!BM"@M3HO48K5H+5Z+V&*VJ"UNB]QBM^@M?HO@8K@H+HZ+Y&*Y +M:"Z>B^ABNJ@NKHOL8KOH+KZ+\&*\*"_.B_1BO6@OWHOX8KZH+^Z+_&*_Z"_^ +'BP!CP+@7`0`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_xorriso.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_xorriso.c new file mode 100644 index 0000000..ce71a56 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_xorriso.c @@ -0,0 +1,216 @@ +/*- + * Copyright (c) 2011 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + + +/* +Execute the following command to rebuild the data for this program: + tail -n +32 test_read_format_iso_xorriso.c | /bin/sh +# +rm -rf /tmp/iso +mkdir /tmp/iso +mkdir /tmp/iso/dir +mkdir /tmp/iso/dir2 +echo "hello" >/tmp/iso/file +ln /tmp/iso/file /tmp/iso/hardlink +(cd /tmp/iso; ln -s file symlink) +TZ=utc touch -afm -t 197001020000.01 /tmp/iso/empty +echo "hello2" >/tmp/iso/dir/file2 +echo "hello3" >/tmp/iso/dir/file3 +echo "hello4" >/tmp/iso/dir2/file4 + +TZ=utc touch -afhm -t 197001020000.01 /tmp/iso/dir/file2 /tmp/iso/dir/file3 +TZ=utc touch -afhm -t 197001020000.01 /tmp/iso/dir2/file4 +TZ=utc touch -afhm -t 197001020000.01 /tmp/iso /tmp/iso/file /tmp/iso/dir +TZ=utc touch -afhm -t 197001020000.01 /tmp/iso/dir2 +TZ=utc touch -afhm -t 197001030000.02 /tmp/iso/symlink +F=test_read_format_iso_xorriso.iso +xorriso -outdev - -map /tmp/iso / > $F +compress $F +uuencode $F.Z $F.Z > $F.Z.uu +rm $F.Z +exit 1 + */ + +/* + * A test for the iso images made by xorriso which versions are + * from 0.6.5 to 1.0.1. + * The xorriso set 0 to the location of empty files(include symlink + * files) that caused our iso reader could not read following directory + * entries at all. + * + */ + +DEFINE_TEST(test_read_format_iso_xorriso) +{ + const char *refname = "test_read_format_iso_xorriso.iso.Z"; + struct archive_entry *ae; + struct archive *a; + const void *p; + size_t size; + int64_t offset; + int i; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualInt(0, archive_read_support_filter_all(a)); + assertEqualInt(0, archive_read_support_format_all(a)); + assertEqualInt(ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Retrieve each of the 10 files on the ISO image and + * verify that each one is what we expect. */ + for (i = 0; i < 10; ++i) { + assertEqualInt(0, archive_read_next_header(a, &ae)); + + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + if (strcmp(".", archive_entry_pathname(ae)) == 0) { + /* '.' root directory. */ + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + /* Now, we read timestamp recorded by RRIP "TF". */ + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + /* Now, we read links recorded by RRIP "PX". */ + assertEqualInt(4, archive_entry_nlink(ae)); + assertEqualIntA(a, ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + } else if (strcmp("./dir", archive_entry_pathname(ae)) == 0) { + /* A directory. */ + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(2, archive_entry_nlink(ae)); + } else if (strcmp("./dir2", archive_entry_pathname(ae)) == 0) { + /* A directory. */ + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(2, archive_entry_nlink(ae)); + } else if (strcmp("./file", + archive_entry_pathname(ae)) == 0) { + /* A regular file. */ + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(0, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt(0, offset); + assertEqualMem(p, "hello\n", 6); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(2, archive_entry_nlink(ae)); + } else if (strcmp("./hardlink", + archive_entry_pathname(ae)) == 0) { + /* A hardlink to the regular file. */ + /* Note: If "hardlink" gets returned before "file", + * then "hardlink" will get returned as a regular file + * and "file" will get returned as the hardlink. + * This test should tolerate that, since it's a + * perfectly permissible thing for libarchive to do. */ + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualString("./file", archive_entry_hardlink(ae)); + assertEqualInt(0, archive_entry_size_is_set(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(2, archive_entry_stat(ae)->st_nlink); + } else if (strcmp("./symlink", + archive_entry_pathname(ae)) == 0) { + /* A symlink to the regular file. */ + assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); + assertEqualString("file", archive_entry_symlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(172802, archive_entry_mtime(ae)); + assertEqualInt(172802, archive_entry_atime(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + } else if (strcmp("./empty", + archive_entry_pathname(ae)) == 0) { + /* A empty file. */ + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(1, archive_entry_nlink(ae)); + } else if (strcmp("./dir/file2", + archive_entry_pathname(ae)) == 0) { + /* A regular file. */ + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(7, archive_entry_size(ae)); + assertEqualInt(0, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt(0, offset); + assertEqualMem(p, "hello2\n", 7); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(1, archive_entry_nlink(ae)); + } else if (strcmp("./dir/file3", + archive_entry_pathname(ae)) == 0) { + /* A regular file. */ + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(7, archive_entry_size(ae)); + assertEqualInt(0, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt(0, offset); + assertEqualMem(p, "hello3\n", 7); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(1, archive_entry_nlink(ae)); + } else if (strcmp("./dir2/file4", + archive_entry_pathname(ae)) == 0) { + /* A regular file. */ + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(7, archive_entry_size(ae)); + assertEqualInt(0, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt(0, offset); + assertEqualMem(p, "hello4\n", 7); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(1, archive_entry_nlink(ae)); + } else { + failure("Saw a file that shouldn't have been there"); + assertEqualString(archive_entry_pathname(ae), ""); + } + } + + /* End of archive. */ + assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_ISO9660_ROCKRIDGE); + + /* Close the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_xorriso.iso.Z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_xorriso.iso.Z.uu new file mode 100644 index 0000000..b69a945 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_xorriso.iso.Z.uu @@ -0,0 +1,61 @@ +begin 644 test_read_format_iso_xorriso.iso.Z +M'YV0``(*'$BPH,&#"!,J7,BPH<.'$"-*G$BQHL6+&#-JW,BQH\>/($.*'$FR +MI,F3*%.J7,FRIO8,.*'4NVK-FS:-.J7//JW/'D"-+GDRYLN7+F#-KWLRY +ML^?/H$.+'DVZM.G3J%.K7LVZM>O7L&/+GDV[MNW;N'/KWLV[M^_?P(,+'TZ\ +MN/'CR),K7\Z\N?/GT*-+GTZ]NO7KV+-KW\Z]N_?OX,.+'T^^O/GSZ-.K7\^^ +MO?OW\./+GT^_OOW[^//KW\^_O_^_`0Q!!`PPQ!```"`DJ.""##;HX())3/%$ +M$DT$<401#V;HX$$\%-2A1P<"$$"(!R*````B%"2"#0G=,%"*,A04XXD"G?B& +M``DP(``%``@0$(D'1CAAA1=J:.212":IY)),-NGDDU!&*2636#PAA11"M@"# +M"S2X``,(,A"8@Y;L\,(,-^SP +MPQ!'+/'$%%=L\<489ZSQQAQW[/''((L\\X\]^SSST`'+?301!=M]-%()ZWTTDPW[?334$M]MIL"Q;@@`4>&*F0%%J(H90'<5"0 +MWB#^2"(`)J*H(HL(N2@0C#("/I"-..K(HX^OBABDA'47.>GEF&>N^>:-5GEE +MEEMV^66G8\)0YIDPI'GKH'L^46B=H>/9YIM"]GEHF*R_?FBBG/?N^^_`!_]H +MJI>N2BJG:GY::?&LEIH\1,2/VFKR(;9M?;.UPHWK]=QW[WVL'UC1`0J(?)HX +MC0$QGN../?[H-P!30'%``+Z\`P`46)`00#M!#!1$.]432`#2,8"!#"`=!Z&" +M$300``<8(0"0.]`#(PB`&ZV/1TYH0@$@.(0B<"``,RA("`W2CH*TPPSF(\B, +M%E?!QK&/@I(+`/[TQS__`;`@`RR@0`Z8P`4V<(+N`^*K+.@X`&1P@P0`@!H` +M0(."-!%]BB/B"]TGH@$0(0E2F.'^^B>0_P7P1P0T(`(-HD`&.A""043C$%V( +MP28@X$!D2(,0&(H!8!H2'9/3A&2F8RTUF,)(`,$,:V%`&`.#! +MF,A4)D&8R49._F@!2`B"%(C@)B)4*7WT" +M$T#@UB=8(0E$*,(40#"%*D`!"E:B`@B,8"6Z/F$*2<#"8*6)H9%.`:U-X.LG +M@W#6)`PA?M,,PA0P-(0GG#4(0Q#L%:):O3YA3!UV0H,UB"`JG3>UJ08#7(E0VFDTEKA/HBJ4*22$+(+""7*O0 +M!`SEE;18"F5A"A&"PB82Y(DLW"0?#R1( +M+@;$BSB$J4P72M-;EK.>1T0C"F.D0L752)=[!.F(ZFO#5QY2EHFT)3EO"5$D +M`J"2F1Q(#@Y0D`-\-'(!0$`TIRF#:J8TE0(-2"L=K%^%#H2AN?SO+C/HRW2N +MLPPRJ*0."J(##A/$P_5TIHA$S-@9F#B@V60Q0F/J8H'`V+\4!G`O#X34,HQP +MO5C.\GY0:$>"X#&^]9SOB0=Y7Y<*L,41;NBK9%S$`/MHP.<#\R[G*T-4DAD` +M^#4DFL.I2"@_5,H6KN0."K(#'P\$R+L4\WQ?W=\)_ +MGO&4;X"YVN_O=\(ZWO.=-[WK;^][XSK>^ +M]\WO?OO[WP`/N,`'3O""&_S@"$^XPA?.\(8[_.$0C[C$)T[QBEO\XAC/N,8W +MSO&.>_SC(`^YR$=.\I*;_.0H3[G*5\[REKO\Y3"/NI8S[K6M\[U +MKGO]ZV`/N]C'3O:RF_WL:$^[VM?.]K:[_>UPC[O^ +M^_WO@`^\X`=/^,(;_O"(3[SB%\_XQCO^\9"/O.0G3_G*6_[RF,^\YC?/^I7S_K6N_[UL(^][&=/^]K;_O:XS[WN=\_[WOO^ +M]\`/OO"'3_SB&__XR$^^\I?/_.8[__G0C[[TIT_]ZEO_^MC/OO:WS_WN>__[ +MX`^_^,=/_O*;__SH3[_ZU\_^]KO__?"/O_SG3__ZV__^^,^__O?/__[[__\` +M&(`".(`$6(`&>(`(F(`*N(`,V(`.^(`0&($2.($46($6>($8F($:N($ +M^($@&((B.((D6((F>((HF((JN((LV((N^((P&(,R.(,T6(,V>(,XF(,ZN(,\ +MV(,^^(-`&(1".(1$6(1&>(1(F(1*N(1,V(1.^(10&(52.(546(56>(58F(5: +MN(5^(5@&(9B.(9D6(9F>(9HF(9JN(9LV(9N^(9P&(=R.(=T6(=V>(=X +MF(=ZN(=\V(=^^(>`&(B".(B$6(B&>(B(F(B*N(B,V(B.^(B0&(F2.(F46(F6 +3>(F8F(F:N(F^(F@&(HZ`0`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_zisofs.iso.Z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_zisofs.iso.Z.uu new file mode 100644 index 0000000..ef54ca6 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_iso_zisofs.iso.Z.uu @@ -0,0 +1,63 @@ +$FreeBSD: head/lib/libarchive/test/test_read_format_iso_zisofs.iso.Z.uu 201247 2009-12-30 05:59:21Z kientzle $ + +begin 644 test_read_format_iso_zisofs.iso.Z +M'YV0``(*'$BPH,&#"!,J7,BPH<.'$"-*G$BQHL6+&#-JW,BQH\>/($.*'$FR +MI,F3*%.J7,FRIO8,.*'4NVK-FS:-.J7//JW/'D"-+GDRYLN7+F#-KWLRY +ML^?/H$.+'DVZM.G3J%.K7LVZM>O7L&/+GDV[MNW;N'/KWLV[M^_?P(,+'TZ\ +MN/'CR),K7\Z\N?/GT*-+GTZ]NO7KV+-KW\Z]N_?OX,.+'T^^O/GSZ-.K7\^^ +MO?OW\./+GT^_OOW[^//KW\^_O_^_`0Q!!`PPQ!```$;(44890DQ!!`@01BCA +MA!1***`43S11X88<1GA0+`6!Z-&!``1`XH$((`"`!059,$%"%0PD`@`7%%2C +MB@*I:$0``B10(@D"!'3B@1T6:>212":IY)),-NGDDU!&*>645%9I991-+)'$ +M%$\8,04(6SX!0@XVV`##"TAX"8(123!1Q!193$%%$1H*446;1!0A!0@F@'!A +M$4,\(<6#`K8@Q0M$6$&H%$4$086@(*`P1`H@Q)!##C.`4(0+63Q1A1-'$!&$ +MFY%.6NFE-X"@A`M0-"H%ETZ\L.H40R#1)A-)@'KEKKSN*@.!.<`0K`PRQ$!# +M#300"`,)OPKK++'&(JLL"NXY)9K[KGHIJON +MNNRVZ^Z2_\6[V#\"$FB@O/CFJ^^^_/9;799)@'!%&62`,$49<$`H`PC%ZG"L +MPS`P#*P";:R1QAQOF#$'PRX4"(*A']>11L$Q?'S&R`Q_K`<(+K3\@AX7O^'O +MS#37;//-.)=U8(U""C0``!@(="`124B1\]%()ZWTTDPW[?334$M]MI,(T*CC0#@&)".//H8`)`]EWC@ +M%%`<$(`O[P`@A10%!!`(%%B$VTX0`P71CM8##6"UT$$2)``51F@0@`,[]OAC +M&PD(4$$+*)``NNBDDS!$$1P$D$%!KQO43D'MF/$V03<.1+?G=U<^9`"#%WYX +MX@$LWOCC!4E>$(\%79[YYIW;;7KHHY=^>O4D```'T`4%+7?<"-;]H^]"#N!U +M\`$DXD03"!Q(1AIR(*XXXP(Y7OE``DPNY/T".:\YY^*[6_0^1[W4`8`0`-!` +M031@`P,,Q``V&.#=A":D`[#)32[800S0I[XF).!`9D@#&\H@OP"0(A`#"00I +M^!>0_"V/A0#P'_0"2`()3@]UI=."$2`0`#CH@0`/H$(8>!$07H2!"HQ(X`(; +M^,`(TI"")5H`$H(P*%PY80D9W"#ATK>^!AP(#6&0`QG8D`8WK*&$)TSA"ING +MOQ+!4(8`Y-T-L7>]U.F0ASX$HA")"``C4L$0`-A`001I$!M",0`*@%,3K(A% +M#0INBXU8'P,.-(<\M(&,9BPA,$(QD%``HXTF>F'SIL"$!9"(`"$<(>;^MZ,! +M^$@`-0R`*V,XQ]2YC9`#P25!ZEBZ0RY`D8R401;1%\DF>!$`E;QD&=<@`TUR +M4B">!"4HWTC*28(/``.@0QO@L,K-\;*6UBM@Z101R$$>Y'0%^%GV\A:`7V9A +MD;E:P@R&"%HA4`^+TK&A-JUK7:A$]M0.15#B$ +M5I,`A2]8*@C``IO@$J"6P:@J.2\`0G&,Q3B-T4A&;+ +M6-\"5[A@RI-MD9L$/8')N8U-0A.HF`406.$)3*A"$_B:)UI)@:Z/&BZD:GO; +MW'Z7N%(8;VN;ZP*V^O>_``[PS&Y`CBE8(AG;L,8!]JC2!P0$'P4("!,!,.$* +M.Y#"%[:PA#/,X0U[&,,?UC"(1RSB$G>8Q"9 +MRE>VQG+7]8RF,I2F_K4J$ZUJE?-ZE:[^M6PCK6L9TWK6MOZUKC. +MM:YWS>M>^_K7P`ZVL(=-[&(;^]C(3K:RE\WL9CO[V=".MK2G3>UJ6_O:V,ZV +MMK?-[6Y[^]O@#K>XQTWNYVN_O=\(ZWO.=-[WK;^][XSK>^ +M]\WO?OO[WP`/N,`'3O""&_S@"$^XPA?.\(8[_.$0C[C$)T[QBEO\XAC/N,8W +MSO&.>_SC(`^YR$=.\I*;_.0H3[G*5\[REKO\Y3"/NI8S[K6M\[U +MKGO]ZV`/N]C'3O:RF_WL:$^[VM?.]K:[_>UPC[O^ +M^_WO@`^\X`=/^,(;_O"(3[SB%\_XQCO^\9"/O.0G3_G*6_[RF,^\YC?/^I7S_K6N_[UL(^][&=/^]K;_O:XS[WN=\_[WOO^ +M]\`/OO"'3_SB&__XR$^^\I?/_.8[__G0C[[TIT_]ZEO_^MC/OO:WS_WN>__[ +MX`^_^,=/_O*;__SH3[_ZU\_^]KO__?"/O_SG3__ZV__^^,^__O?/__[[__\` +M&(`".(`$6(`&>(`(F(`*N(`,V(`.^(`0&($2.($46($6>($8F($:N($ +M^($@&((B.((D6((F>((HF((JN((LV((N^((P&(,R.(,T6(,V>(,XF(,ZN(,\ +MV(,^^(-`&(1".(1$6(1&>(1(F(1*N(1,V(1.^(10&(52.(546(56>(58F(5: +MN(5^(5@&(9B.(9D6(9F>(9HF(9JN(9LV(9N^(9P&(=R.(=T6(=V>(=X +MF(=ZN(=\V(=^^(>`&(B".(B$6(B&>(B(F(B*N(B,V(B.^(B0&(F2.(F46(F6 +@>(F8F(F:N(F^(F@&(JB.(JD6(JF>(JHF(JJN'`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isojoliet_bz2.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isojoliet_bz2.c new file mode 100644 index 0000000..eb33c0b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isojoliet_bz2.c @@ -0,0 +1,141 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Based on libarchive/test/test_read_format_isorr_bz2.c with + * bugs introduced by Andreas Henriksson for + * testing ISO9660 image with Joliet extension. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_isojoliet_bz2.c 201247 2009-12-30 05:59:21Z kientzle $"); + +/* +Execute the following to rebuild the data for this program: + tail -n +35 test_read_format_isojoliet_bz2.c | /bin/sh + +rm -rf /tmp/iso +mkdir /tmp/iso +mkdir /tmp/iso/dir +echo "hello" >/tmp/iso/long-joliet-file-name.textfile +ln /tmp/iso/long-joliet-file-name.textfile /tmp/iso/hardlink +(cd /tmp/iso; ln -s long-joliet-file-name.textfile symlink) +if [ "$(uname -s)" = "Linux" ]; then # gnu coreutils touch doesn't have -h +TZ=utc touch -afm -t 197001020000.01 /tmp/iso /tmp/iso/long-joliet-file-name.textfile /tmp/iso/dir +TZ=utc touch -afm -t 197001030000.02 /tmp/iso/symlink +else +TZ=utc touch -afhm -t 197001020000.01 /tmp/iso /tmp/iso/long-joliet-file-name.textfile /tmp/iso/dir +TZ=utc touch -afhm -t 197001030000.02 /tmp/iso/symlink +fi +F=test_read_format_iso_joliet.iso.Z +mkhybrid -J -uid 1 -gid 2 /tmp/iso | compress > $F +uuencode $F $F > $F.uu +exit 1 + */ + +DEFINE_TEST(test_read_format_isojoliet_bz2) +{ + const char *refname = "test_read_format_iso_joliet.iso.Z"; + struct archive_entry *ae; + struct archive *a; + const void *p; + size_t size; + int64_t offset; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualInt(0, archive_read_support_filter_all(a)); + assertEqualInt(0, archive_read_support_format_all(a)); + assertEqualInt(ARCHIVE_OK, + archive_read_set_option(a, "iso9660", "rockridge", NULL)); + assertEqualInt(ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* First entry is '.' root directory. */ + assertEqualInt(0, archive_read_next_header(a, &ae)); + assertEqualString(".", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(86401, archive_entry_ctime(ae)); + assertEqualInt(3, archive_entry_stat(ae)->st_nlink); + assertEqualInt(0, archive_entry_uid(ae)); + assertEqualIntA(a, ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* A directory. */ + assertEqualInt(0, archive_read_next_header(a, &ae)); + assertEqualString("dir", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* A regular file with two names ("hardlink" gets returned + * first, so it's not marked as a hardlink). */ + assertEqualInt(0, archive_read_next_header(a, &ae)); + assertEqualString("hardlink", + archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assert(archive_entry_hardlink(ae) == NULL); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(0, archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt(6, (int)size); + assertEqualInt(0, offset); + assertEqualMem(p, "hello\n", 6); + + /* Second name for the same regular file (this happens to be + * returned second, so does get marked as a hardlink). */ + assertEqualInt(0, archive_read_next_header(a, &ae)); + assertEqualString("long-joliet-file-name.textfile", + archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualString("hardlink", + archive_entry_hardlink(ae)); + assert(!archive_entry_size_is_set(ae)); + + /* A symlink to the regular file. */ + assertEqualInt(0, archive_read_next_header(a, &ae)); + assertEqualString("symlink", archive_entry_pathname(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(172802, archive_entry_mtime(ae)); + assertEqualInt(172802, archive_entry_atime(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* End of archive. */ + assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); + + /* Close the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isojoliet_long.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isojoliet_long.c new file mode 100644 index 0000000..4283c39 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isojoliet_long.c @@ -0,0 +1,149 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2009 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_isojoliet_long.c 201247 2009-12-30 05:59:21Z kientzle $"); + +/* +Execute the following to rebuild the data for this program: + tail -n +35 test_read_format_isojoliet_long.c | /bin/sh + +rm -rf /tmp/iso +mkdir /tmp/iso +num=0 +file=""; +while [ $num -lt 100 ] +do + num=$((num+10)) + file="${file}1234567890" +done +dir="${file}dir" +mkdir /tmp/iso/${dir} +file="${file}123" +echo "hello" > /tmp/iso/${file} +ln /tmp/iso/${file} /tmp/iso/hardlink +if [ "$(uname -s)" = "Linux" ]; then # gnu coreutils touch doesn't have -h +TZ=utc touch -afm -t 197001020000.01 /tmp/iso /tmp/iso/${file} /tmp/iso/${dir} +else +TZ=utc touch -afhm -t 197001020000.01 /tmp/iso /tmp/iso/${file} /tmp/iso/${dir} +fi +F=test_read_format_iso_joliet_long.iso.Z +mkhybrid -J -joliet-long -uid 1 -gid 2 /tmp/iso | compress > $F +uuencode $F $F > $F.uu +rm -rf /tmp/iso +exit 1 + */ + +DEFINE_TEST(test_read_format_isojoliet_long) +{ + const char *refname = "test_read_format_iso_joliet_long.iso.Z"; + char pathname[104]; + struct archive_entry *ae; + struct archive *a; + const void *p; + size_t size; + int64_t offset; + int i; + + for (i = 0; i < 100; i++) + pathname[i] = '0' + ((i+1) % 10); + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualInt(0, archive_read_support_filter_all(a)); + assertEqualInt(0, archive_read_support_format_all(a)); + assertEqualInt(ARCHIVE_OK, + archive_read_set_options(a, "iso9660:!rockridge")); + assertEqualInt(ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* First entry is '.' root directory. */ + assertEqualInt(0, archive_read_next_header(a, &ae)); + assertEqualString(".", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(86401, archive_entry_ctime(ae)); + assertEqualInt(3, archive_entry_stat(ae)->st_nlink); + assertEqualInt(0, archive_entry_uid(ae)); + assertEqualIntA(a, ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* A directory. */ + pathname[100] = 'd'; + pathname[101] = 'i'; + pathname[102] = 'r'; + pathname[103] = '\0'; + assertEqualInt(0, archive_read_next_header(a, &ae)); + assertEqualString(pathname, archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* A regular file with two names (pathname gets returned + * first, so it's not marked as a hardlink). */ + pathname[100] = '1'; + pathname[101] = '2'; + pathname[102] = '3'; + pathname[103] = '\0'; + assertEqualInt(0, archive_read_next_header(a, &ae)); + assertEqualString("hardlink", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assert(archive_entry_hardlink(ae) == NULL); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(0, archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt(6, (int)size); + assertEqualInt(0, offset); + assertEqualMem(p, "hello\n", 6); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Second name for the same regular file (this happens to be + * returned second, so does get marked as a hardlink). */ + assertEqualInt(0, archive_read_next_header(a, &ae)); + assertEqualString(pathname, archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualString("hardlink", archive_entry_hardlink(ae)); + assert(!archive_entry_size_is_set(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* End of archive. */ + assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); + + /* Close the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isojoliet_rr.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isojoliet_rr.c new file mode 100644 index 0000000..3c19516 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isojoliet_rr.c @@ -0,0 +1,170 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Based on libarchive/test/test_read_format_isorr_bz2.c with + * bugs introduced by Andreas Henriksson for + * testing ISO9660 image with Joliet extension. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_isojoliet_rr.c 201247 2009-12-30 05:59:21Z kientzle $"); + +/* +Execute the following to rebuild the data for this program: + tail -n +35 test_read_format_isojoliet_rr.c | /bin/sh + +rm -rf /tmp/iso +mkdir /tmp/iso +mkdir /tmp/iso/dir +file="long-joliet-file-name.textfile" +echo "hello" >/tmp/iso/$file +ln /tmp/iso/$file /tmp/iso/hardlink +(cd /tmp/iso; ln -s $file symlink) +if [ "$(uname -s)" = "Linux" ]; then # gnu coreutils touch doesn't have -h +TZ=utc touch -afm -t 197001020000.01 /tmp/iso/hardlink /tmp/iso/$file /tmp/iso/dir +TZ=utc touch -afm -t 197001030000.02 /tmp/iso/symlink +TZ=utc touch -afm -t 197001020000.01 /tmp/iso +else +TZ=utc touch -afhm -t 197001020000.01 /tmp/iso/hardlink /tmp/iso/$file /tmp/iso/dir +TZ=utc touch -afhm -t 197001030000.02 /tmp/iso/symlink +TZ=utc touch -afhm -t 197001020000.01 /tmp/iso +fi +F=test_read_format_iso_joliet_rockridge.iso.Z +mkhybrid -J -uid 1 -gid 2 /tmp/iso | compress > $F +uuencode $F $F > $F.uu +exit 1 + */ + +DEFINE_TEST(test_read_format_isojoliet_rr) +{ + const char *refname = "test_read_format_iso_joliet_rockridge.iso.Z"; + struct archive_entry *ae; + struct archive *a; + const void *p; + size_t size; + int64_t offset; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualInt(0, archive_read_support_filter_all(a)); + assertEqualInt(0, archive_read_support_format_all(a)); + assertEqualInt(ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* First entry is '.' root directory. */ + assertEqualInt(0, archive_read_next_header(a, &ae)); + assertEqualString(".", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(3, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualIntA(a, ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* A directory. */ + assertEqualInt(0, archive_read_next_header(a, &ae)); + assertEqualString("dir", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(2, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* A regular file with two names ("hardlink" gets returned + * first, so it's not marked as a hardlink). */ + assertEqualInt(0, archive_read_next_header(a, &ae)); + assertEqualString("hardlink", + archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assert(archive_entry_hardlink(ae) == NULL); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(0, archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt(6, (int)size); + assertEqualInt(0, offset); + assertEqualMem(p, "hello\n", 6); + assertEqualInt(86401, archive_entry_mtime(ae)); + /* mkisofs records their access time. */ + /*assertEqualInt(86401, archive_entry_atime(ae));*/ + /* TODO: Actually, libarchive should be able to + * compute nlinks correctly even without RR + * extensions. See comments in libarchive source. */ + assertEqualInt(2, archive_entry_nlink(ae)); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Second name for the same regular file (this happens to be + * returned second, so does get marked as a hardlink). */ + assertEqualInt(0, archive_read_next_header(a, &ae)); + assertEqualString("long-joliet-file-name.textfile", + archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualString("hardlink", + archive_entry_hardlink(ae)); + assert(!archive_entry_size_is_set(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + /* TODO: See above. */ + assertEqualInt(2, archive_entry_nlink(ae)); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* A symlink to the regular file. */ + assertEqualInt(0, archive_read_next_header(a, &ae)); + assertEqualString("symlink", archive_entry_pathname(ae)); + assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); + assertEqualString("long-joliet-file-name.textfile", + archive_entry_symlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(172802, archive_entry_mtime(ae)); + assertEqualInt(172802, archive_entry_atime(ae)); + assertEqualInt(1, archive_entry_nlink(ae)); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* End of archive. */ + assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_ISO9660_ROCKRIDGE); + + /* Close the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isojoliet_versioned.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isojoliet_versioned.c new file mode 100644 index 0000000..011b5e2 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isojoliet_versioned.c @@ -0,0 +1,87 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Based on libarchive/test/test_read_format_isojoliet_bz2.c with + * bugs introduced by Andreas Henriksson for + * testing ISO9660 image with Joliet extension and versioned files. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_isojoliet_bz2.c 201247 2009-12-30 05:59:21Z kientzle $"); + +/* + * The data for this testcase was provided by Mike Qin + * and created with Nero. + */ + +DEFINE_TEST(test_read_format_isojoliet_versioned) +{ + const char *refname = "test_read_format_iso_joliet_by_nero.iso.Z"; + struct archive_entry *ae; + struct archive *a; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualInt(0, archive_read_support_filter_all(a)); + assertEqualInt(0, archive_read_support_format_all(a)); + assertEqualInt(ARCHIVE_OK, + archive_read_set_option(a, "iso9660", "rockridge", NULL)); + assertEqualInt(ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* First entry is '.' root directory. */ + assertEqualInt(0, archive_read_next_header(a, &ae)); + assertEqualString(".", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + + /* A directory. */ + assertEqualInt(0, archive_read_next_header(a, &ae)); + assertEqualString("test", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* A regular file which is called test.txt and has + * ;1 appended to it because apparently Nero always + * appends versions to all files in the joliet extension. + * + * We test to make sure the version has been stripped. + */ + assertEqualInt(0, archive_read_next_header(a, &ae)); + assertEqualString("test/test.txt", + archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* End of archive. */ + assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); + + /* Close the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isorr_bz2.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isorr_bz2.c new file mode 100644 index 0000000..fb4f4a8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isorr_bz2.c @@ -0,0 +1,206 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_isorr_bz2.c 201247 2009-12-30 05:59:21Z kientzle $"); + +/* +PLEASE use old cdrtools; mkisofs version is 2.01. +This version mkisofs made wrong "SL" System Use Entry of RRIP. + +Execute the following command to rebuild the data for this program: + tail -n +34 test_read_format_isorr_bz2.c | /bin/sh + +rm -rf /tmp/iso +mkdir /tmp/iso +mkdir /tmp/iso/dir +echo "hello" >/tmp/iso/file +dd if=/dev/zero count=1 bs=12345678 >>/tmp/iso/file +ln /tmp/iso/file /tmp/iso/hardlink +(cd /tmp/iso; ln -s file symlink) +(cd /tmp/iso; ln -s /tmp/ symlink2) +(cd /tmp/iso; ln -s /tmp/../ symlink3) +(cd /tmp/iso; ln -s .././../tmp/ symlink4) +(cd /tmp/iso; ln -s .///file symlink5) +(cd /tmp/iso; ln -s /tmp//../ symlink6) +TZ=utc touch -afhm -t 197001020000.01 /tmp/iso /tmp/iso/file /tmp/iso/dir +TZ=utc touch -afhm -t 197001030000.02 /tmp/iso/symlink /tmp/iso/symlink5 +F=test_read_format_iso_rockridge.iso.Z +mkhybrid -R -uid 1 -gid 2 /tmp/iso | compress > $F +uuencode $F $F > $F.uu +exit 1 + */ + +DEFINE_TEST(test_read_format_isorr_bz2) +{ + const char *refname = "test_read_format_iso_rockridge.iso.Z"; + struct archive_entry *ae; + struct archive *a; + const void *p; + size_t size; + int64_t offset; + int i; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualInt(0, archive_read_support_filter_all(a)); + assertEqualInt(0, archive_read_support_format_all(a)); + assertEqualInt(ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Retrieve each of the 8 files on the ISO image and + * verify that each one is what we expect. */ + for (i = 0; i < 10; ++i) { + assertEqualInt(0, archive_read_next_header(a, &ae)); + + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + if (strcmp(".", archive_entry_pathname(ae)) == 0) { + /* '.' root directory. */ + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + /* Now, we read timestamp recorded by RRIP "TF". */ + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + /* Now, we read links recorded by RRIP "PX". */ + assertEqualInt(3, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualIntA(a, ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + } else if (strcmp("dir", archive_entry_pathname(ae)) == 0) { + /* A directory. */ + assertEqualString("dir", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(2, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("file", archive_entry_pathname(ae)) == 0) { + /* A regular file. */ + assertEqualString("file", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(12345684, archive_entry_size(ae)); + assertEqualInt(0, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt(0, offset); + assertEqualMem(p, "hello\n", 6); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(2, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("hardlink", archive_entry_pathname(ae)) == 0) { + /* A hardlink to the regular file. */ + /* Note: If "hardlink" gets returned before "file", + * then "hardlink" will get returned as a regular file + * and "file" will get returned as the hardlink. + * This test should tolerate that, since it's a + * perfectly permissible thing for libarchive to do. */ + assertEqualString("hardlink", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualString("file", archive_entry_hardlink(ae)); + assertEqualInt(0, archive_entry_size_is_set(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(2, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("symlink", archive_entry_pathname(ae)) == 0) { + /* A symlink to the regular file. */ + assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); + assertEqualString("file", archive_entry_symlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(172802, archive_entry_mtime(ae)); + assertEqualInt(172802, archive_entry_atime(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("symlink2", archive_entry_pathname(ae)) == 0) { + /* A symlink to /tmp (an absolute path) */ + assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); + assertEqualString("/tmp", archive_entry_symlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("symlink3", archive_entry_pathname(ae)) == 0) { + /* A symlink to /tmp/.. (with a ".." component) */ + assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); + assertEqualString("/tmp/..", archive_entry_symlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("symlink4", archive_entry_pathname(ae)) == 0) { + /* A symlink to a path with ".." and "." components */ + assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); + assertEqualString(".././../tmp", + archive_entry_symlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("symlink5", archive_entry_pathname(ae)) == 0) { + /* A symlink to the regular file with "/" components. */ + assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); + assertEqualString(".///file", archive_entry_symlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(172802, archive_entry_mtime(ae)); + assertEqualInt(172802, archive_entry_atime(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("symlink6", archive_entry_pathname(ae)) == 0) { + /* A symlink to /tmp//.. + * (with "/" and ".." components) */ + assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); + assertEqualString("/tmp//..", archive_entry_symlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else { + failure("Saw a file that shouldn't have been there"); + assertEqualString(archive_entry_pathname(ae), ""); + } + } + + /* End of archive. */ + assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_ISO9660_ROCKRIDGE); + + /* Close the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isorr_ce.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isorr_ce.c new file mode 100644 index 0000000..1e57acb --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isorr_ce.c @@ -0,0 +1,226 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2009 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_isorr_ce.c 201247 2009-12-30 05:59:21Z kientzle $"); + +/* +Execute the following command to rebuild the data for this program: + tail -n +32 test_read_format_isorr_ce.c | /bin/sh + +dirname=/tmp/iso +# +rm -rf $dirname +mkdir $dirname +# +num=0 +file="" +while [ $num -lt 150 ] +do + num=$((num+1)) + file="a$file" +done +# +num=0 +while [ $num -lt 3 ] +do + num=$((num+1)) + file="a$file" + echo "hello $((num+150))" > $dirname/$file + dd if=/dev/zero count=1 bs=4080 >> $dirname/$file + (cd $dirname; ln -s $file sym$num) +done +# +mkdir $dirname/dir +# +time1="197001020000.01" +time2="197001030000.02" +TZ=utc touch -afhm -t $time1 $dirname/dir $dirname/aaaa* +TZ=utc touch -afhm -t $time2 $dirname/sym* +TZ=utc touch -afhm -t $time1 $dirname +# +F=test_read_format_iso_rockridge_ce.iso.Z +mkisofs -R -uid 1 -gid 2 $dirname | compress > $F +uuencode $F $F > $F.uu +rm -rf $dirname +exit 1 + */ + +/* + * Test reading SUSP "CE" extension is works fine. + */ + +static void +mkpath(char *p, int len) +{ + int i; + + for (i = 0; i < len; i++) + p[i] = 'a'; + p[len] = '\0'; +} + +DEFINE_TEST(test_read_format_isorr_ce) +{ + const char *refname = "test_read_format_iso_rockridge_ce.iso.Z"; + char path1[160]; + char path2[160]; + char path3[160]; + struct archive_entry *ae; + struct archive *a; + const void *p; + size_t size; + int64_t offset; + int i; + + mkpath(path1, 151); + mkpath(path2, 152); + mkpath(path3, 153); + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualInt(0, archive_read_support_filter_all(a)); + assertEqualInt(0, archive_read_support_format_all(a)); + assertEqualInt(ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Retrieve each of the 8 files on the ISO image and + * verify that each one is what we expect. */ + for (i = 0; i < 8; ++i) { + assertEqualInt(0, archive_read_next_header(a, &ae)); + + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + if (strcmp(".", archive_entry_pathname(ae)) == 0) { + /* '.' root directory. */ + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + /* Now, we read timestamp recorded by RRIP "TF". */ + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + /* Now, we read links recorded by RRIP "PX". */ + assertEqualInt(3, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualIntA(a, ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + } else if (strcmp("dir", archive_entry_pathname(ae)) == 0) { + /* A directory. */ + assertEqualString("dir", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(2, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp(path1, archive_entry_pathname(ae)) == 0) { + /* A regular file. */ + assertEqualString(path1, archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(4090, archive_entry_size(ae)); + assertEqualInt(0, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt(0, offset); + assertEqualMem(p, "hello 151\n", 10); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp(path2, archive_entry_pathname(ae)) == 0) { + /* A regular file. */ + assertEqualString(path2, archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(4090, archive_entry_size(ae)); + assertEqualInt(0, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt(0, offset); + assertEqualMem(p, "hello 152\n", 10); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp(path3, archive_entry_pathname(ae)) == 0) { + /* A regular file. */ + assertEqualString(path3, archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(4090, archive_entry_size(ae)); + assertEqualInt(0, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt(0, offset); + assertEqualMem(p, "hello 153\n", 10); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("sym1", archive_entry_pathname(ae)) == 0) { + /* A symlink to the regular file. */ + assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); + assertEqualString(path1, archive_entry_symlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(172802, archive_entry_mtime(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("sym2", archive_entry_pathname(ae)) == 0) { + /* A symlink to the regular file. */ + assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); + assertEqualString(path2, archive_entry_symlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(172802, archive_entry_mtime(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("sym3", archive_entry_pathname(ae)) == 0) { + /* A symlink to the regular file. */ + assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); + assertEqualString(path3, archive_entry_symlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(172802, archive_entry_mtime(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else { + failure("Saw a file that shouldn't have been there"); + assertEqualString(archive_entry_pathname(ae), ""); + } + } + + /* End of archive. */ + assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_ISO9660_ROCKRIDGE); + + /* Close the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isorr_new_bz2.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isorr_new_bz2.c new file mode 100644 index 0000000..4c1b569 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isorr_new_bz2.c @@ -0,0 +1,207 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_isorr_new_bz2.c 201247 2009-12-30 05:59:21Z kientzle $"); + + +/* +PLEASE use latest cdrtools at least mkisofs version is 2.01.01a63 or later. +Old version mkisofs made wrong "SL" System Use Entry of RRIP. + +Execute the following command to rebuild the data for this program: + tail -n +34 test_read_format_isorr_new_bz2.c | /bin/sh + +rm -rf /tmp/iso +mkdir /tmp/iso +mkdir /tmp/iso/dir +echo "hello" >/tmp/iso/file +dd if=/dev/zero count=1 bs=12345678 >>/tmp/iso/file +ln /tmp/iso/file /tmp/iso/hardlink +(cd /tmp/iso; ln -s file symlink) +(cd /tmp/iso; ln -s /tmp/ symlink2) +(cd /tmp/iso; ln -s /tmp/../ symlink3) +(cd /tmp/iso; ln -s .././../tmp/ symlink4) +(cd /tmp/iso; ln -s .///file symlink5) +(cd /tmp/iso; ln -s /tmp//../ symlink6) +TZ=utc touch -afhm -t 197001020000.01 /tmp/iso /tmp/iso/file /tmp/iso/dir +TZ=utc touch -afhm -t 197001030000.02 /tmp/iso/symlink +F=test_read_format_iso_rockridge_new.iso.Z +mkhybrid -R -uid 1 -gid 2 /tmp/iso | compress > $F +uuencode $F $F > $F.uu +exit 1 + */ + +DEFINE_TEST(test_read_format_isorr_new_bz2) +{ + const char *refname = "test_read_format_iso_rockridge_new.iso.Z"; + struct archive_entry *ae; + struct archive *a; + const void *p; + size_t size; + int64_t offset; + int i; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualInt(0, archive_read_support_filter_all(a)); + assertEqualInt(0, archive_read_support_format_all(a)); + assertEqualInt(ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Retrieve each of the 8 files on the ISO image and + * verify that each one is what we expect. */ + for (i = 0; i < 10; ++i) { + assertEqualInt(0, archive_read_next_header(a, &ae)); + + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + if (strcmp(".", archive_entry_pathname(ae)) == 0) { + /* '.' root directory. */ + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + /* Now, we read timestamp recorded by RRIP "TF". */ + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + /* Now, we read links recorded by RRIP "PX". */ + assertEqualInt(3, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualIntA(a, ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + } else if (strcmp("dir", archive_entry_pathname(ae)) == 0) { + /* A directory. */ + assertEqualString("dir", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(2, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("file", archive_entry_pathname(ae)) == 0) { + /* A regular file. */ + assertEqualString("file", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(12345684, archive_entry_size(ae)); + assertEqualInt(0, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt(0, offset); + assertEqualMem(p, "hello\n", 6); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(2, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("hardlink", archive_entry_pathname(ae)) == 0) { + /* A hardlink to the regular file. */ + /* Note: If "hardlink" gets returned before "file", + * then "hardlink" will get returned as a regular file + * and "file" will get returned as the hardlink. + * This test should tolerate that, since it's a + * perfectly permissible thing for libarchive to do. */ + assertEqualString("hardlink", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualString("file", archive_entry_hardlink(ae)); + assertEqualInt(0, archive_entry_size_is_set(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(2, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("symlink", archive_entry_pathname(ae)) == 0) { + /* A symlink to the regular file. */ + assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); + assertEqualString("file", archive_entry_symlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(172802, archive_entry_mtime(ae)); + assertEqualInt(172802, archive_entry_atime(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("symlink2", archive_entry_pathname(ae)) == 0) { + /* A symlink to /tmp/ (an absolute path) */ + assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); + assertEqualString("/tmp/", archive_entry_symlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("symlink3", archive_entry_pathname(ae)) == 0) { + /* A symlink to /tmp/../ (with a ".." component) */ + assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); + assertEqualString("/tmp/../", archive_entry_symlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("symlink4", archive_entry_pathname(ae)) == 0) { + /* A symlink to a path with ".." and "." components */ + assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); + assertEqualString(".././../tmp/", + archive_entry_symlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("symlink5", archive_entry_pathname(ae)) == 0) { + /* A symlink to the regular file with "/" components. */ + assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); + assertEqualString(".///file", archive_entry_symlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(172802, archive_entry_mtime(ae)); + assertEqualInt(172802, archive_entry_atime(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("symlink6", archive_entry_pathname(ae)) == 0) { + /* A symlink to /tmp//../ + * (with "/" and ".." components) */ + assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); + assertEqualString("/tmp//../", archive_entry_symlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else { + failure("Saw a file that shouldn't have been there"); + assertEqualString(archive_entry_pathname(ae), ""); + } + } + + /* End of archive. */ + assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_ISO9660_ROCKRIDGE); + + /* Close the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isorr_rr_moved.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isorr_rr_moved.c new file mode 100644 index 0000000..693caef --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isorr_rr_moved.c @@ -0,0 +1,273 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2009 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_isorr_rr_moved.c 201247 2009-12-30 05:59:21Z kientzle $"); + +/* +Execute the following command to rebuild the data for this program: + tail -n +32 test_read_format_isorr_rr_moved.c | /bin/sh + +dirname=/tmp/iso +rm -rf $dirname +mkdir -p $dirname/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dir10 +echo "hello" >$dirname/file +dd if=/dev/zero count=1 bs=12345678 >>$dirname/file +deepfile=$dirname/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dir10/deep +echo "hello" >$deepfile +dd if=/dev/zero count=1 bs=12345678 >>$deepfile +time="197001020000.01" +TZ=utc touch -afhm -t $time $deepfile +TZ=utc touch -afhm -t $time $dirname/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dir10 +TZ=utc touch -afhm -t $time $dirname/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9 +TZ=utc touch -afhm -t $time $dirname/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8 +TZ=utc touch -afhm -t $time $dirname/dir1/dir2/dir3/dir4/dir5/dir6/dir7 +TZ=utc touch -afhm -t $time $dirname/dir1/dir2/dir3/dir4/dir5/dir6 +TZ=utc touch -afhm -t $time $dirname/dir1/dir2/dir3/dir4/dir5 +TZ=utc touch -afhm -t $time $dirname/dir1/dir2/dir3/dir4 +TZ=utc touch -afhm -t $time $dirname/dir1/dir2/dir3 +TZ=utc touch -afhm -t $time $dirname/dir1/dir2 +TZ=utc touch -afhm -t $time $dirname/dir1 +TZ=utc touch -afhm -t $time $dirname/file +TZ=utc touch -afhm -t $time $dirname +F=test_read_format_isorr_rockridge_moved.iso.Z +mkhybrid -R -uid 1 -gid 2 $dirname | compress > $F +uuencode $F $F > $F.uu +exit 1 + */ + +DEFINE_TEST(test_read_format_isorr_rr_moved) +{ + const char *refname = "test_read_format_iso_rockridge_rr_moved.iso.Z"; + struct archive_entry *ae; + struct archive *a; + const void *p; + size_t size; + int64_t offset; + int i; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualInt(0, archive_read_support_filter_all(a)); + assertEqualInt(0, archive_read_support_format_all(a)); + assertEqualInt(ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Retrieve each of the 8 files on the ISO image and + * verify that each one is what we expect. */ + for (i = 0; i < 13; ++i) { + assertEqualInt(0, archive_read_next_header(a, &ae)); + + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + if (strcmp(".", archive_entry_pathname(ae)) == 0) { + /* '.' root directory. */ + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + /* Now, we read timestamp recorded by RRIP "TF". */ + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + /* Now, we read links recorded by RRIP "PX". */ + assertEqualInt(3, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualIntA(a, ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + } else if (strcmp("dir1", archive_entry_pathname(ae)) == 0) { + /* A directory. */ + assertEqualString("dir1", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("dir1/dir2", + archive_entry_pathname(ae)) == 0) { + /* A directory. */ + assertEqualString("dir1/dir2", + archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("dir1/dir2/dir3", + archive_entry_pathname(ae)) == 0) { + /* A directory. */ + assertEqualString("dir1/dir2/dir3", + archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("dir1/dir2/dir3/dir4", + archive_entry_pathname(ae)) == 0) { + /* A directory. */ + assertEqualString("dir1/dir2/dir3/dir4", + archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("dir1/dir2/dir3/dir4/dir5", + archive_entry_pathname(ae)) == 0) { + /* A directory. */ + assertEqualString("dir1/dir2/dir3/dir4/dir5", + archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("dir1/dir2/dir3/dir4/dir5/dir6", + archive_entry_pathname(ae)) == 0) { + /* A directory. */ + assertEqualString("dir1/dir2/dir3/dir4/dir5/dir6", + archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("dir1/dir2/dir3/dir4/dir5/dir6/dir7", + archive_entry_pathname(ae)) == 0) { + /* A directory. */ + assertEqualString("dir1/dir2/dir3/dir4/dir5/dir6/dir7", + archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("dir1/dir2/dir3/dir4/dir5/dir6/dir7" + "/dir8", + archive_entry_pathname(ae)) == 0) { + /* A directory. */ + assertEqualString("dir1/dir2/dir3/dir4/dir5/dir6/dir7" + "/dir8", + archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("dir1/dir2/dir3/dir4/dir5/dir6/dir7" + "/dir8/dir9", + archive_entry_pathname(ae)) == 0) { + /* A directory. */ + assertEqualString("dir1/dir2/dir3/dir4/dir5/dir6/dir7" + "/dir8/dir9", + archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("dir1/dir2/dir3/dir4/dir5/dir6/dir7" + "/dir8/dir9/dir10", + archive_entry_pathname(ae)) == 0) { + /* A directory. */ + assertEqualString("dir1/dir2/dir3/dir4/dir5/dir6/dir7" + "/dir8/dir9/dir10", + archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(2, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("file", archive_entry_pathname(ae)) == 0) { + /* A regular file. */ + assertEqualString("file", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(12345684, archive_entry_size(ae)); + assertEqualInt(0, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt(0, offset); + assertEqualMem(p, "hello\n", 6); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("dir1/dir2/dir3/dir4/dir5/dir6/dir7" + "/dir8/dir9/dir10/deep", + archive_entry_pathname(ae)) == 0) { + /* A regular file. */ + assertEqualString("dir1/dir2/dir3/dir4/dir5/dir6/dir7" + "/dir8/dir9/dir10/deep", + archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(12345684, archive_entry_size(ae)); + assertEqualInt(0, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt(0, offset); + assertEqualMem(p, "hello\n", 6); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else { + failure("Saw a file that shouldn't have been there"); + assertEqualString(archive_entry_pathname(ae), ""); + } + } + + /* End of archive. */ + assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_ISO9660_ROCKRIDGE); + + /* Close the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isozisofs_bz2.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isozisofs_bz2.c new file mode 100644 index 0000000..adf9624 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_isozisofs_bz2.c @@ -0,0 +1,190 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_isozisofs_bz2.c 201247 2009-12-30 05:59:21Z kientzle $"); + +/* +Execute the following command to rebuild the data for this program: + tail -n +32 test_read_format_isozisofs_bz2.c | /bin/sh + +rm -rf /tmp/iso /tmp/ziso +mkdir /tmp/iso +mkdir /tmp/iso/dir +echo "hello" >/tmp/iso/file +dd if=/dev/zero count=1 bs=12345678 >>/tmp/iso/file +ln /tmp/iso/file /tmp/iso/hardlink +(cd /tmp/iso; ln -s file symlink) +(cd /tmp/iso; ln -s /tmp/ symlink2) +(cd /tmp/iso; ln -s /tmp/../ symlink3) +(cd /tmp/iso; ln -s .././../tmp/ symlink4) +TZ=utc touch -afhm -t 197001020000.01 /tmp/iso /tmp/iso/file /tmp/iso/dir +TZ=utc touch -afhm -t 197001030000.02 /tmp/iso/symlink +mkzftree /tmp/iso /tmp/ziso +TZ=utc touch -afhm -t 197001020000.01 /tmp/ziso /tmp/ziso/file /tmp/ziso/dir +TZ=utc touch -afhm -t 197001030000.02 /tmp/ziso/symlink +F=test_read_format_iso_zisofs.iso.Z +mkhybrid -R -uid 1 -gid 2 -z /tmp/ziso | compress > $F +uuencode $F $F > $F.uu +exit 1 + + */ + +DEFINE_TEST(test_read_format_isozisofs_bz2) +{ + const char *refname = "test_read_format_iso_zisofs.iso.Z"; + struct archive_entry *ae; + struct archive *a; + const void *p; + size_t size; + int64_t offset; + int i; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualInt(0, archive_read_support_filter_all(a)); + assertEqualInt(0, archive_read_support_format_all(a)); + assertEqualInt(ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Retrieve each of the 8 files on the ISO image and + * verify that each one is what we expect. */ + for (i = 0; i < 8; ++i) { + assertEqualInt(0, archive_read_next_header(a, &ae)); + + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + if (strcmp(".", archive_entry_pathname(ae)) == 0) { + /* '.' root directory. */ + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + /* Now, we read timestamp recorded by RRIP "TF". */ + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + /* Now, we read links recorded by RRIP "PX". */ + assertEqualInt(3, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualIntA(a, ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + } else if (strcmp("dir", archive_entry_pathname(ae)) == 0) { + /* A directory. */ + assertEqualString("dir", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(2, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("file", archive_entry_pathname(ae)) == 0) { + int r; + /* A regular file. */ + assertEqualString("file", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(12345684, archive_entry_size(ae)); + r = archive_read_data_block(a, &p, &size, &offset); + if (r == ARCHIVE_FAILED) { + skipping("Can't read body of ZISOFS entry."); + } else { + assertEqualInt(ARCHIVE_OK, r); + assertEqualInt(0, offset); + assertEqualMem(p, "hello\n", 6); + } + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(2, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("hardlink", archive_entry_pathname(ae)) == 0) { + /* A hardlink to the regular file. */ + /* Note: If "hardlink" gets returned before "file", + * then "hardlink" will get returned as a regular file + * and "file" will get returned as the hardlink. + * This test should tolerate that, since it's a + * perfectly permissible thing for libarchive to do. */ + assertEqualString("hardlink", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualString("file", archive_entry_hardlink(ae)); + assertEqualInt(0, archive_entry_size_is_set(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(2, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("symlink", archive_entry_pathname(ae)) == 0) { + /* A symlink to the regular file. */ + assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); + assertEqualString("file", archive_entry_symlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(172802, archive_entry_mtime(ae)); + assertEqualInt(172802, archive_entry_atime(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("symlink2", archive_entry_pathname(ae)) == 0) { + /* A symlink to /tmp (an absolute path) */ + assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); + assertEqualString("/tmp", archive_entry_symlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("symlink3", archive_entry_pathname(ae)) == 0) { + /* A symlink to /tmp/.. (with a ".." component) */ + assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); + assertEqualString("/tmp/..", archive_entry_symlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("symlink4", archive_entry_pathname(ae)) == 0) { + /* A symlink to a path with ".." and "." components */ + assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); + assertEqualString(".././../tmp", + archive_entry_symlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else { + failure("Saw a file that shouldn't have been there"); + assertEqualString(archive_entry_pathname(ae), ""); + } + } + + /* End of archive. */ + assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_ISO9660_ROCKRIDGE); + + /* Close the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha.c new file mode 100644 index 0000000..6a53976 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha.c @@ -0,0 +1,294 @@ +/*- + * Copyright (c) 2008, 2010 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD"); + +/* +Execute the following command to rebuild the data for this program: + tail -n +32 test_read_format_lha.c | /bin/sh + +#/bin/sh +# +# How to make test data. +# +# Temporary directory. +base=/tmp/lha +# Owner id +owner=1001 +# Group id +group=1001 +# +# Make contents of a lha archive. +# +rm -rf ${base} +mkdir ${base} +mkdir ${base}/dir +cat > ${base}/file1 << END + file 1 contents +hello +hello +hello +END +cat > ${base}/file2 << END + file 2 contents +hello +hello +hello +hello +hello +hello +END +mkdir ${base}/dir2 +# +# Set up a file mode, owner and group. +# +(cd ${base}/dir2; ln -s ../file1 symlink1) +(cd ${base}/dir2; ln -s ../file2 symlink2) +(cd ${base}; chown ${owner}:${group} dir file1 file2) +(cd ${base}; chown -h ${owner}:${group} dir2 dir2/symlink1 dir2/symlink2) +(cd ${base}; chmod 0750 dir) +(cd ${base}; chmod 0755 dir2) +(cd ${base}; chmod 0755 dir2/symlink1 dir2/symlink2) +(cd ${base}; chmod 0644 file1) +(cd ${base}; chmod 0666 file2) +TZ=utc touch -afhm -t 197001030000.02 ${base}/dir2/symlink1 ${base}/dir2/symlink2 +TZ=utc touch -afhm -t 197001020000.01 ${base}/dir ${base}/dir2 +TZ=utc touch -afhm -t 197001020000.01 ${base}/file1 ${base}/file2 +# +# Make several lha archives. +# +# Make a lha archive with header level 0 +lha0=test_read_format_lha_header0.lzh +(cd ${base}; lha c0q ${lha0} dir file1 file2 dir2) +# Make a lha archive with header level 1 +lha1=test_read_format_lha_header1.lzh +(cd ${base}; lha c1q ${lha1} dir file1 file2 dir2) +# Make a lha archive with header level 2 +lha2=test_read_format_lha_header2.lzh +(cd ${base}; lha c2q ${lha2} dir file1 file2 dir2) +# Make a lha archive with -lh6- compression mode +lha3=test_read_format_lha_lh6.lzh +(cd ${base}; lha co6q ${lha3} dir file1 file2 dir2) +# Make a lha archive with -lh7- compression mode +lha4=test_read_format_lha_lh7.lzh +(cd ${base}; lha co7q ${lha4} dir file1 file2 dir2) +# Make a lha archive with -lh0- no compression +lha5=test_read_format_lha_lh0.lzh +(cd ${base}; lha czq ${lha5} dir file1 file2 dir2) +# make a lha archive with junk data +lha6=test_read_format_lha_withjunk.lzh +(cd ${base}; cp ${lha2} ${lha6}; echo "junk data!!!!" >> ${lha6}) +# +uuencode ${base}/${lha0} ${lha0} > ${lha0}.uu +uuencode ${base}/${lha1} ${lha1} > ${lha1}.uu +uuencode ${base}/${lha2} ${lha2} > ${lha2}.uu +uuencode ${base}/${lha3} ${lha3} > ${lha3}.uu +uuencode ${base}/${lha4} ${lha4} > ${lha4}.uu +uuencode ${base}/${lha5} ${lha5} > ${lha5}.uu +uuencode ${base}/${lha6} ${lha5} > ${lha5}.uu +uuencode ${base}/${lha6} ${lha6} > ${lha6}.uu +# +# Finish making test data. +exit 1 +*/ + +static const char file1[] = { +" file 1 contents\n" +"hello\n" +"hello\n" +"hello\n" +}; +#define file1_size (sizeof(file1)-1) +static const char file2[] = { +" file 2 contents\n" +"hello\n" +"hello\n" +"hello\n" +"hello\n" +"hello\n" +"hello\n" +}; +#define file2_size (sizeof(file2)-1) + +static void +verify(const char *refname, int posix) +{ + struct archive_entry *ae; + struct archive *a; + char buff[128]; + const void *pv; + size_t s; + int64_t o; + int uid, gid; + + if (posix) + uid = gid = 1001; + else + uid = gid = 0; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify directory1. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + if (posix) + assertEqualInt((AE_IFDIR | 0750), archive_entry_mode(ae)); + else + assertEqualInt((AE_IFDIR | 0755), archive_entry_mode(ae)); + assertEqualString("dir/", archive_entry_pathname(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(uid, archive_entry_uid(ae)); + assertEqualInt(gid, archive_entry_gid(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualIntA(a, ARCHIVE_EOF, + archive_read_data_block(a, &pv, &s, &o)); + assertEqualInt(s, 0); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify directory2. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFDIR | 0755), archive_entry_mode(ae)); + assertEqualString("dir2/", archive_entry_pathname(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(uid, archive_entry_uid(ae)); + assertEqualInt(gid, archive_entry_gid(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualIntA(a, ARCHIVE_EOF, + archive_read_data_block(a, &pv, &s, &o)); + assertEqualInt(s, 0); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + if (posix) { + /* Verify symbolic link file1. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFLNK | 0755), archive_entry_mode(ae)); + assertEqualString("dir2/symlink1", archive_entry_pathname(ae)); + assertEqualString("../file1", archive_entry_symlink(ae)); + assertEqualInt(172802, archive_entry_mtime(ae)); + assertEqualInt(uid, archive_entry_uid(ae)); + assertEqualInt(gid, archive_entry_gid(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify symbolic link file2. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFLNK | 0755), archive_entry_mode(ae)); + assertEqualString("dir2/symlink2", archive_entry_pathname(ae)); + assertEqualString("../file2", archive_entry_symlink(ae)); + assertEqualInt(172802, archive_entry_mtime(ae)); + assertEqualInt(uid, archive_entry_uid(ae)); + assertEqualInt(gid, archive_entry_gid(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + } + + /* Verify regular file1. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("file1", archive_entry_pathname(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(uid, archive_entry_uid(ae)); + assertEqualInt(gid, archive_entry_gid(ae)); + assertEqualInt(file1_size, archive_entry_size(ae)); + assertEqualInt(file1_size, archive_read_data(a, buff, file1_size)); + assertEqualMem(buff, file1, file1_size); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify regular file2. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + if (posix) + assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae)); + else + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("file2", archive_entry_pathname(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(uid, archive_entry_uid(ae)); + assertEqualInt(gid, archive_entry_gid(ae)); + assertEqualInt(file2_size, archive_entry_size(ae)); + assertEqualInt(file2_size, archive_read_data(a, buff, file2_size)); + assertEqualMem(buff, file2, file2_size); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify the number of files read. */ + if (posix) { + assertEqualInt(6, archive_file_count(a)); + } else { + assertEqualInt(4, archive_file_count(a)); + } + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify the number of files read. */ + if (posix) { + assertEqualInt(6, archive_file_count(a)); + } else { + assertEqualInt(4, archive_file_count(a)); + } + + /* Verify encryption status */ + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_LHA, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_lha) +{ + /* Verify Header level 0 */ + verify("test_read_format_lha_header0.lzh", 1); + /* Verify Header level 1 */ + verify("test_read_format_lha_header1.lzh", 1); + /* Verify Header level 2 */ + verify("test_read_format_lha_header2.lzh", 1); + /* Verify Header level 3 + * This test data can be made in Windows only. */ + verify("test_read_format_lha_header3.lzh", 0); + /* Verify compression mode -lh6- */ + verify("test_read_format_lha_lh6.lzh", 1); + /* Verify compression mode -lh7- */ + verify("test_read_format_lha_lh7.lzh", 1); + /* Verify no compression -lh0- */ + verify("test_read_format_lha_lh0.lzh", 1); + /* Verify an lha file with junk data. */ + verify("test_read_format_lha_withjunk.lzh", 1); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_bugfix_0.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_bugfix_0.c new file mode 100644 index 0000000..2b4160b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_bugfix_0.c @@ -0,0 +1,76 @@ +/*- + * Copyright (c) 2014 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD"); + +DEFINE_TEST(test_read_format_lha_bugfix_0) +{ + const char *refname = "test_read_format_lha_bugfix_0.lzh"; + struct archive_entry *ae; + struct archive *a; + const void *pv; + size_t s; + int64_t o; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify directory1. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("f", archive_entry_pathname(ae)); + assertEqualInt(776, archive_entry_size(ae)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &pv, &s, &o)); + assertEqualInt(s, 776); + assertEqualIntA(a, ARCHIVE_EOF, + archive_read_data_block(a, &pv, &s, &o)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), + ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify the number of files read. */ + assertEqualInt(1, archive_file_count(a)); + + /* Verify encryption status */ + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), + ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_LHA, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_bugfix_0.lzh.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_bugfix_0.lzh.uu new file mode 100644 index 0000000..34f5fb5 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_bugfix_0.lzh.uu @@ -0,0 +1,19 @@ +begin 644 test_read_format_lha_bugfix_0.lzh +M+P`M;&@U+7T"```(`P``$D*U4R`"],%5!0``,;<$``%F!0!0I($'`%$4`/4! +M```#!FS;%+&?H/SZ_`=2K$ +M-,5VE5(EVT9P)2WPS:$ET@K!861T3'*N&!9P1"!)<58 +M77$ZCA;PVAGN>:E@6E`;&<>"ZC!Y63H&,DLG*7"!89A!JAN$L?(RDL_4`*!5 +MFWE%HD>>J)M8]^%^EM_SX;PSL4PVL.5A30:MQ@.E>3">;0[^XNA:([UUF>FV +MLJS"HLP=\5-Y)HP)8800U81@-`7,)<)ZD6)*P7'5$BBE@NYFR%CS>"PRZ6`Z +M8JPQ)&7:HGF$^/FQGF_PQ;'VBN?WET90#=W4S(2%Q9+!.>\`MR,`]Y;GQNU* +MFV]2K+=B$EZ2M6[KKUMXA2,NK[\3?3>^;:NB(+]2)S/?J*C<=Y'\SN?1Z7-T +M."&"A!R%6"V5"ZI&W[UZFT>T$?;.=#MVH9@V=/!#*$).G2G(Y4.Q*[1AVL?6*_:94#("2J<.Q< +M2F+D][."[K,$ +M^*>G*P8XG*=--.O:V?F58URE?C"9Q>FRRHW0RHQTQ\`IS.%ZJ:J2YKXH6C:+ +MHAD@<2N;;[H(/YMP]]_/=25P$K"=;&?2)-\6HA5V6U"%Z`/3MMKL6>%KKCGI +*+1"40KV_/\%````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_filename.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_filename.c new file mode 100644 index 0000000..126a870 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_filename.c @@ -0,0 +1,221 @@ +/*- + * Copyright (c) 2011 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD"); + +#include + +static void +test_read_format_lha_filename_CP932_eucJP(const char *refname) +{ + struct archive *a; + struct archive_entry *ae; + + /* + * Read LHA filename in ja_JP.eucJP. + */ + if (NULL == setlocale(LC_ALL, "ja_JP.eucJP")) { + skipping("ja_JP.eucJP locale not available on this system."); + return; + } + + /* + * Create a read object only for a test that platform support + * a character-set conversion because we can read a character-set + * of filenames from the header of an lha archive file and so we + * want to test that it works well. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=CP932")) { + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + skipping("This system cannot convert character-set" + " from CP932 to eucJP."); + return; + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xB4\xC1\xBB\xFA\x2E\x74\x78\x74", + archive_entry_pathname(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xC9\xBD\x2E\x74\x78\x74", archive_entry_pathname(ae)); + assertEqualInt(4, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_LHA, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +static void +test_read_format_lha_filename_CP932_UTF8(const char *refname) +{ + struct archive *a; + struct archive_entry *ae; + + /* + * Read LHA filename in en_US.UTF-8. + */ + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } + /* + * Create a read object only for a test that platform support + * a character-set conversion because we can read a character-set + * of filenames from the header of an lha archive file and so we + * want to test that it works well. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=CP932")) { + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + skipping("This system cannot convert character-set" + " from CP932 to UTF-8."); + return; + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xE6\xBC\xA2\xE5\xAD\x97\x2E\x74\x78\x74", + archive_entry_pathname(ae)); + assertEqualInt(8, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xE8\xA1\xA8\x2E\x74\x78\x74", + archive_entry_pathname(ae)); + assertEqualInt(4, archive_entry_size(ae)); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_LHA, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +#if defined(_WIN32) && !defined(__CYGWIN__) +static void +test_read_format_lha_filename_CP932_Windows(const char *refname) +{ + struct archive *a; + struct archive_entry *ae; + + /* + * Read LHA filename in jpn on Windows. + */ + if (NULL == setlocale(LC_ALL, "jpn")) { + skipping("jpn locale not available on this system."); + return; + } + /* + * Create a read object only for a test that platform support + * a character-set conversion because we can read a character-set + * of filenames from the header of an lha archive file and so we + * want to test that it works well. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\x8A\xBF\x8E\x9A\x2E\x74\x78\x74", + archive_entry_pathname(ae)); + assertEqualInt(8, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\x95\x5C\x2E\x74\x78\x74", archive_entry_pathname(ae)); + assertEqualInt(4, archive_entry_size(ae)); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_LHA, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} +#else +/* Stub */ +static void +test_read_format_lha_filename_CP932_Windows(const char *refname) +{ + (void)refname; /* UNUSED */ +} +#endif + +DEFINE_TEST(test_read_format_lha_filename) +{ + /* A sample file was created with LHA32.EXE through UNLHA.DLL. */ + const char *refname = "test_read_format_lha_filename_cp932.lzh"; + + extract_reference_file(refname); + + test_read_format_lha_filename_CP932_eucJP(refname); + test_read_format_lha_filename_CP932_UTF8(refname); + test_read_format_lha_filename_CP932_Windows(refname); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_filename_cp932.lzh.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_filename_cp932.lzh.uu new file mode 100644 index 0000000..1517014 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_filename_cp932.lzh.uu @@ -0,0 +1,7 @@ +begin 644 test_read_format_lha_cp932.lzh +M30`M;&@P+0@````(````*:2#32`"&4A-!P!&I`,```L``8J_CIHN='AT&P!! +M-'"`))KERP%TJNDQFN7+`72JZ3&:Y'0;`$&:91,VFN7+ +>`:#K$3V:Y + +static void +test_read_format_lha_filename_UTF16_UTF8(const char *refname) +{ + struct archive *a; + struct archive_entry *ae; + + /* + * Read LHA filename in en_US.UTF-8. + */ + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } + /* + * Create a read object only for a test that platform support + * a character-set conversion because we can read a character-set + * of filenames from the header of an lha archive file and so we + * want to test that it works well. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=CP932")) { + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + skipping("This system cannot convert character-set" + " from CP932 to UTF-8."); + return; + } + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=UTF-16")) { + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + skipping("This system cannot convert character-set" + " from UTF-16 to UTF-8."); + return; + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Note that usual Japanese filenames are tested in other cases */ +#if defined(__APPLE__) + /* NFD normalization */ + /* U:O:A:u:o:a: */ + #define UMLAUT_DIRNAME "\x55\xcc\x88\x4f\xcc\x88\x41\xcc\x88\x75\xcc\x88\x6f"\ + "\xcc\x88\x61\xcc\x88/" + /* a:o:u:A:O:U:.txt */ + #define UMLAUT_FNAME "\x61\xcc\x88\x6f\xcc\x88\x75\xcc\x88\x41\xcc\x88"\ + "\x4f\xcc\x88\x55\xcc\x88.txt" +#else + /* NFC normalization */ + /* U:O:A:u:o:a: */ + #define UMLAUT_DIRNAME "\xc3\x9c\xc3\x96\xc3\x84\xc3\xbc\xc3\xb6\xc3\xa4/" + /* a:o:u:A:O:U:.txt */ + #define UMLAUT_FNAME "\xc3\xa4\xc3\xb6\xc3\xbc\xc3\x84\xc3\x96\xc3\x9c.txt" +#endif + +/* "Test" in Japanese Katakana */ +#define KATAKANA_FNAME "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88.txt" +#define KATAKANA_DIRNAME "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88/" + + /* Verify regular file. U:O:A:u:o:a:/a:o:u:A:O:U:.txt */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(UMLAUT_DIRNAME UMLAUT_FNAME, archive_entry_pathname(ae)); + assertEqualInt(12, archive_entry_size(ae)); + + /* Verify directory. U:O:A:u:o:a:/ */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(UMLAUT_DIRNAME, archive_entry_pathname(ae)); + assertEqualInt(0, archive_entry_size(ae)); + + /* Verify regular file. U:O:A:u:o:a:/("Test" in Japanese).txt */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(UMLAUT_DIRNAME KATAKANA_FNAME, + archive_entry_pathname(ae)); + assertEqualInt(25, archive_entry_size(ae)); + + /* Verify regular file. ("Test" in Japanese)/a:o:u:A:O:U:.txt */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(KATAKANA_DIRNAME UMLAUT_FNAME, + archive_entry_pathname(ae)); + assertEqualInt(12, archive_entry_size(ae)); + + /* Verify directory. ("Test" in Japanese)/ */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(KATAKANA_DIRNAME, archive_entry_pathname(ae)); + assertEqualInt(0, archive_entry_size(ae)); + + /* Verify regular file. a:o:u:A:O:U:.txt */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(UMLAUT_FNAME, archive_entry_pathname(ae)); + assertEqualInt(12, archive_entry_size(ae)); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_LHA, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_lha_filename_UTF16) +{ + /* A sample file was created with Unlha32.dll. */ + const char *refname = "test_read_format_lha_filename_utf16.lzh"; + extract_reference_file(refname); + + test_read_format_lha_filename_UTF16_UTF8(refname); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_filename_utf16.lzh.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_filename_utf16.lzh.uu new file mode 100644 index 0000000..ca5da7a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_filename_utf16.lzh.uu @@ -0,0 +1,19 @@ +begin 644 test_read_format_lha_filename_utf16.lzh +M@0`M;&@P+0P````,````L/5872`"IW%-!P!&I`,```T``5]?7U]?7RYT>'0* +M``)?7U]?7U__%P!$Y`#V`/P`Q`#6`-P`+@!T`'@`=``1`$7<`-8`Q`#\`/8` +MY`#__QL`078S9B"U0$H^DQ_F(+5 +M`2CZ3'^8@M4!!@``GW<'``!J`"UL:#`M&0```!D```!V)L1=(`*CNTT'`$:D +M`P``#0`!@V6#6(-G+G1X=`H``E]?7U]?7_\1`$7<`-8`Q`#\`/8`Y`#__QL` +M00IF#4J@E-4!L"5C?'65U0&P)6-\=975`08``$%^!P``5&5S="!I;B!*87!A +M;F5S92!+871A:V%N87L`+6QH,"T,````#````+#U6%T@`J=Q30<`1J0#```- +M``%?7U]?7U\N='AT"@`"@V6#6(-G_Q<`1.0`]@#\`,0`U@#<`"X`=`!X`'0` +M"P!%QC"Y,,@P__\;`$'D5O!-H)35`?4-F(*15=4!Y%;P3:"4U0$&``"A+0<` +M`,.DP[;#O,.$PY;#G%0`+6QH9"T``````````-3`PET@`@``30<`1J0#```# +M``$*``*#98-8@V?_!0!`$``;`$%%!\Y.H)35`3/_]%&@E-4!,__T4:"4U0$& +M``!>;@<``&8`+6QH,"T,````#````+#U6%T@`J=Q30<`1J0#```-``%?7U]? +M7U\N='AT%P!$Y`#V`/P`Q`#6`-P`+@!T`'@`=``;`$'D5O!-H)35`?4-F(*1 +@5=4!Y%;P3:"4U0$&``"M>`<``,.DP[;#O,.$PY;#G`#D +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_header0.lzh.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_header0.lzh.uu new file mode 100644 index 0000000..8fa8b92 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_header0.lzh.uu @@ -0,0 +1,11 @@ +begin 644 test_read_format_lha_header0.lzh +M)L`M;&AD+0```````````$@B[!``!&1ID#Z0,GO2UL:#4M(@```#P`````2"+L(``%9FEL93&D +MYU4`@5$!`*2!Z0/I`P`80FYIQ>/Z`=-:'>9%#"P%J!\CH0"/GE$,.W6FMSD% +M*_4G02UL:#4M(@```$X`````2"+L(``%9FEL93+5%54`@5$!`+:!Z0/I`P`8 +A0FYIQV/Z`=.:'.9%#"P%J-\+H0"/'E$,.W6FMSD%*_T` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_header1.lzh.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_header1.lzh.uu new file mode 100644 index 0000000..303c9bb --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_header1.lzh.uu @@ -0,0 +1,13 @@ +begin 644 test_read_format_lha_header1.lzh +M&7\M;&AD+1H``````````$@B["`!````50<``F1ID#Z0,' +M`%2!40$````9@2UL:&0M&P``````````2"+L(`$```!5"``"9&ER,O\%`%#M +M00<`4>D#Z0,'`%2!40$````><2UL:&0M)P`````````!2"/L(`$%9FEL93$` +M`%44``)D:7(R_W-Y;6QI;FLQ?"XN_P4`4.VA!P!1Z0/I`P<`5`*C`@```!YR +M+6QH9"TG``````````%((^P@`05F:6QE,@``510``F1I40P[=::W.04K]1YX+6QH-2TU````3@````!((NP@`05F:6QE +M,M45504`4+:!!P!1Z0/I`P<`5(%1`0`````80FYIQV/Z`=.:'.9%#"P%J-\+ +/H0"/'E$,.W6FMSD%*_T` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_header2.lzh.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_header2.lzh.uu new file mode 100644 index 0000000..d5d7591 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_header2.lzh.uu @@ -0,0 +1,13 @@ +begin 644 test_read_format_lha_header2.lzh +M-0`M;&AD+0``````````@5$!`"`"``!5!0``!=X#``$'``)D:7+_!0!0Z$$' +M`%'I`^D#```V`"UL:&0M``````````"!40$`(`(``%4%```(F0,``0@``F1I +M6UL:6YK,7PN+O\%`%#MH0<`4>D#Z0,``$<` +M+6QH9"T```````````*C`@`@`@``504``(?M"``!9FEL93(4``)D:7(R_W-Y +M;6QI;FLR?"XN_P4`4.VA!P!1Z0/I`P``,P`M;&@U+2(````\````@5$!`"`" +MI.=5!0``_0$(``%F:6QE,04`4*2!!P!1Z0/I`P```!A";FG%X_H!TUH=YD4, +M+`6H'R.A`(^>40P[=::W.04K]3,`+6QH-2TB````3@```(%1`0`@`M45504` +M`"_&"``!9FEL93(%`%"V@0<`4>D#Z0,````80FYIQV/Z`=.:'.9%#"P%J-\+ +/H0"/'E$,.W6FMSD%*_T` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_header3.lzh.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_header3.lzh.uu new file mode 100644 index 0000000..e612826 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_header3.lzh.uu @@ -0,0 +1,16 @@ +begin 644 test_read_format_lha_header3.lzh +M!``M;&AD+0``````````@5$!`"`#``!-?`````D```!&I`,```4````!"0`` +M``)D:7+_!P```$`0`!D```#_[4$`````````````#!7^3$0:_DP=````0@_0`9;+`0@`````+J\'``````0`+6QH9"T````` +M`````(%1`0`@`P``37T````)````1J0#```%`````0H````"9&ER,O\'```` +M0!``&0```/_M00`````````````A&OY,1!K^3!T```!!2H%NNP&6RP&`UD`` +MJ+*=`0!Z#]`!ELL!"`````!]%P<`````!``M;&@U+20````\````@5$!`"`# +MI.=-<0````D```!&I`,```H````!9FEL93$9````_Z2!`````````````,<4 +M_DPC&OY,'0```$$T0J**_I7+`8#60`"HLIT!_G*DO`&6RP$(``````KQ!P`` +M````&4)MD:BT=H!Z:T.IZ9#S:`ZH%CJ$`A]OC1DU4VION(3=>H`$`"UL:#4M +M)````$X```"!40$`(`/5%4UQ````"0```$:D`P``"@````%F:6QE,AD```#_ +MI($`````````````(1K^3",:_DP=````0?Y%<[L!ELL!@-9``*BRG0%8U::\ +M`9;+`0@`````0=X'```````90FV1J.QV@'IS0XGID/-H#JC&&H0"'F^-&353 +(:F^XA-U^@``` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_lh0.lzh.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_lh0.lzh.uu new file mode 100644 index 0000000..fff88c7 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_lh0.lzh.uu @@ -0,0 +1,13 @@ +begin 644 test_read_format_lha_lh0.lzh +M-0`M;&AD+0``````````@5$!`"`"``!5!0``!=X#``$'``)D:7+_!0!0Z$$' +M`%'I`^D#```V`"UL:&0M``````````"!40$`(`(``%4%```(F0,``0@``F1I +M6UL:6YK,7PN+O\%`%#MH0<`4>D#Z0,``$<` +M+6QH9"T```````````*C`@`@`@``504``(?M"``!9FEL93(4``)D:7(R_W-Y +M;6QI;FLR?"XN_P4`4.VA!P!1Z0/I`P``,P`M;&@U+2(````\````@5$!`"`" +MI.=5!0``_0$(``%F:6QE,04`4*2!!P!1Z0/I`P```!A";FG%X_H!TUH=YD4, +M+`6H'R.A`(^>40P[=::W.04K]3,`+6QH-2TB````3@```(%1`0`@`M45504` +M`"_&"``!9FEL93(%`%"V@0<`4>D#Z0,````80FYIQV/Z`=.:'.9%#"P%J-\+ +=H0"/'E$,.W6FMSD%*_T`:G5N:R!D871A(2$A(0H` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_lh6.lzh.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_lh6.lzh.uu new file mode 100644 index 0000000..22ad4ac --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_lh6.lzh.uu @@ -0,0 +1,13 @@ +begin 644 test_read_format_lha_lh6.lzh +M-0`M;&AD+0``````````@5$!`"`"``!5!0``!=X#``$'``)D:7+_!0!0Z$$' +M`%'I`^D#```V`"UL:&0M``````````"!40$`(`(``%4%```(F0,``0@``F1I +M6UL:6YK,7PN+O\%`%#MH0<`4>D#Z0,``$<` +M+6QH9"T```````````*C`@`@`@``504``(?M"``!9FEL93(4``)D:7(R_W-Y +M;6QI;FLR?"XN_P4`4.VA!P!1Z0/I`P``,P`M;&@V+2,````\````@5$!`"`" +MI.=5!0``C24(``%F:6QE,04`4*2!!P!1Z0/I`P```!A";FG%X_H!TUH=YD4, +M+`6H'R.0@$?/*(8=NM-;G(*5^H`S`"UL:#8M(P```$X```"!40$`(`+5%54% +M``!?X@@``69I;&4R!0!0MH$'`%'I`^D#````&$)N:<=C^@'3FASF10PL!:C? +1"Y"`1X\HAAVZTUN<@I7^@``` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_lh7.lzh.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_lh7.lzh.uu new file mode 100644 index 0000000..1eaf55c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_lha_lh7.lzh.uu @@ -0,0 +1,13 @@ +begin 644 test_read_format_lha_lh7.lzh +M-0`M;&AD+0``````````@5$!`"`"``!5!0``!=X#``$'``)D:7+_!0!0Z$$' +M`%'I`^D#```V`"UL:&0M``````````"!40$`(`(``%4%```(F0,``0@``F1I +M6UL:6YK,7PN+O\%`%#MH0<`4>D#Z0,``$<` +M+6QH9"T```````````*C`@`@`@``504``(?M"``!9FEL93(4``)D:7(R_W-Y +M;6QI;FLR?"XN_P4`4.VA!P!1Z0/I`P``,P`M;&@W+2,````\````@5$!`"`" +MI.=5!0``'(D(``%F:6QE,04`4*2!!P!1Z0/I`P```!A";FG%X_H!TUH=YD4, +M+`6H'R.0@$?/*(8=NM-;G(*5^H`S`"UL:#6UL:6YK,7PN+O\%`%#MH0<`4>D#Z0,``$<` +M+6QH9"T```````````*C`@`@`@``504``(?M"``!9FEL93(4``)D:7(R_W-Y +M;6QI;FLR?"XN_P4`4.VA!P!1Z0/I`P``,P`M;&@U+2(````\````@5$!`"`" +MI.=5!0``_0$(``%F:6QE,04`4*2!!P!1Z0/I`P```!A";FG%X_H!TUH=YD4, +M+`6H'R.A`(^>40P[=::W.04K]3,`+6QH-2TB````3@```(%1`0`@`M45504` +M`"_&"``!9FEL93(%`%"V@0<`4>D#Z0,````80FYIQV/Z`=.:'.9%#"P%J-\+ +=H0"/'E$,.W6FMSD%*_T`:G5N:R!D871A(2$A(0H` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_mtree.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_mtree.c new file mode 100644 index 0000000..df6f6cd --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_mtree.c @@ -0,0 +1,744 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2011-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_mtree.c 201247 2009-12-30 05:59:21Z kientzle $"); + +static void +test_read_format_mtree1(void) +{ + const char reffile[] = "test_read_format_mtree.mtree"; + char buff[16]; + struct archive_entry *ae; + struct archive *a; + FILE *f; + /* Compute max 64-bit signed twos-complement value + * without relying on overflow. This assumes that long long + * is at least 64 bits. */ + static const long long max_int64 = ((((long long)1) << 62) - 1) + (((long long)1) << 62); + time_t min_time; + volatile time_t t; + + extract_reference_file(reffile); + + /* + * An access error occurred on some platform when mtree + * format handling open a directory. It is for through + * the routine which open a directory that we create + * "dir" and "dir2" directories. + */ + assertMakeDir("dir", 0775); + assertMakeDir("dir2", 0775); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_set_options(a, "mtree:checkfs")); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, reffile, 11)); + + /* + * Read "file", whose data is available on disk. + */ + f = fopen("file", "wb"); + assert(f != NULL); + assertEqualInt(3, fwrite("hi\n", 1, 3, f)); + fclose(f); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_MTREE); + assertEqualString(archive_entry_pathname(ae), "file"); + assertEqualInt(archive_entry_uid(ae), 18); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0123); + assertEqualInt(archive_entry_size(ae), 3); + assertEqualInt(3, archive_read_data(a, buff, 3)); + assertEqualMem(buff, "hi\n", 3); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "dir"); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "dir/file with space"); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "file with space"); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "dir2"); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "dir2/dir3a"); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "dir2/dir3a/indir3a"); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "dir2/fullindir2"); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "dir2/indir2"); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "dir2/dir3b"); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "dir2/dir3b/indir3b"); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "dir2/dir3b/filename\\with_esc\b\t\fapes"); + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "notindir"); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "dir2/emptyfile"); + assertEqualInt(archive_entry_size(ae), 0); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "dir2/smallfile"); + assertEqualInt(archive_entry_size(ae), 1); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* TODO: Mtree reader should probably return ARCHIVE_WARN for this. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "dir2/toosmallfile"); + assertEqualInt(archive_entry_size(ae), -1); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "dir2/bigfile"); + assertEqualInt(archive_entry_size(ae), max_int64); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "dir2/toobigfile"); + /* Size in mtree is max_int64 + 1; should return max_int64. */ + assertEqualInt(archive_entry_size(ae), max_int64); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "dir2/veryoldfile"); + /* The value in the file is MIN_INT64_T, but time_t may be narrower. */ + /* Verify min_time is the smallest possible time_t. */ + min_time = archive_entry_mtime(ae); + assert(min_time <= 0); + /* Simply asserting min_time - 1 > 0 breaks with some compiler optimizations. */ + t = (time_t)((uintmax_t)min_time - 1); + assert(t > 0); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* toooldfile is 1 sec older, which should overflow and get returned + * with the same value. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "dir2/toooldfile"); + assertEqualInt(archive_entry_mtime(ae), min_time); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualInt(20, archive_file_count(a)); + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +static void +test_read_format_mtree2(void) +{ + static char archive[] = + "#mtree\n" + "d type=dir content=.\n"; + struct archive_entry *ae; + struct archive *a; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_set_options(a, "mtree:checkfs")); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, archive, sizeof(archive))); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_MTREE); + assertEqualString(archive_entry_pathname(ae), "d"); + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_file_count(a)); + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +/* + * Reported to libarchive.googlecode.com as Issue 121. + */ +static void +test_read_format_mtree3(void) +{ + static char archive[] = + "#mtree\n" + "a type=file contents=file\n" + "b type=link link=a\n" + "c type=file contents=file\n"; + struct archive_entry *ae; + struct archive *a; + + assertMakeDir("mtree3", 0777); + assertChdir("mtree3"); + assertMakeFile("file", 0644, "file contents"); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_set_options(a, "mtree:checkfs")); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, archive, sizeof(archive))); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "a"); + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "b"); + assertEqualInt(archive_entry_filetype(ae), AE_IFLNK); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "c"); + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualInt(3, archive_file_count(a)); + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + assertChdir(".."); +} + +DEFINE_TEST(test_read_format_mtree) +{ + test_read_format_mtree1(); + test_read_format_mtree2(); + test_read_format_mtree3(); +} + +DEFINE_TEST(test_read_format_mtree_filenames_only) +{ + static char archive[] = + "/set type=file mode=0644\n" + "./a\n" + "./b\n" + "./c\n" + "./d\n" + "./e\n" + "./f mode=0444\n"; + struct archive_entry *ae; + struct archive *a; + + assertMakeFile("file", 0644, "file contents"); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_set_options(a, "mtree:checkfs")); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, archive, sizeof(archive))); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "./a"); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "./b"); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "./c"); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "./d"); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "./e"); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "./f"); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0444); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualInt(6, archive_file_count(a)); + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_mtree_nochange) +{ + static char archive[] = + "#mtree\n" + "./a type=file mode=0644 time=123\n" + "./b type=file mode=0644 time=234\n" + "./c type=file mode=0644 time=345\n"; + static char archive2[] = + "#mtree\n" + "./a type=file mode=0644 time=123 nochange\n" + "./b type=file mode=0644 time=234\n" + "./c type=file mode=0644 time=345 nochange\n"; + struct archive_entry *ae; + struct archive *a; + + assertMakeFile("a", 0640, "12345"); + assertMakeFile("b", 0664, "123456"); + assertMakeFile("c", 0755, "1234567"); + + /* + * Test 1. Read a mtree archive without `nochange' keyword. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_set_options(a, "mtree:checkfs")); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, archive, sizeof(archive))); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "./a"); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + assertEqualInt(archive_entry_mtime(ae), 123); + assertEqualInt(archive_entry_size(ae), 5); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "./b"); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + assertEqualInt(archive_entry_mtime(ae), 234); + assertEqualInt(archive_entry_size(ae), 6); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "./c"); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + assertEqualInt(archive_entry_mtime(ae), 345); + assertEqualInt(archive_entry_size(ae), 7); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualInt(3, archive_file_count(a)); + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Test 2. Read a mtree archive with `nochange' keyword. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_set_options(a, "mtree:checkfs")); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, archive2, sizeof(archive2))); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "./a"); +#if !defined(_WIN32) || defined(__CYGWIN__) + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0640); +#endif + assert(archive_entry_mtime(ae) != 123); + assertEqualInt(archive_entry_size(ae), 5); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "./b"); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + assertEqualInt(archive_entry_mtime(ae), 234); + assertEqualInt(archive_entry_size(ae), 6); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "./c"); +#if !defined(_WIN32) || defined(__CYGWIN__) + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0755); +#endif + assert(archive_entry_mtime(ae) != 345); + assertEqualInt(archive_entry_size(ae), 7); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualInt(3, archive_file_count(a)); + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_mtree_nomagic_v1_form) +{ + const char reffile[] = "test_read_format_mtree_nomagic.mtree"; + char buff[16]; + struct archive_entry *ae; + struct archive *a; + FILE *f; + + extract_reference_file(reffile); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_set_options(a, "mtree:checkfs")); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, reffile, 11)); + + /* + * Read "file", whose data is available on disk. + */ + f = fopen("file", "wb"); + assert(f != NULL); + assertEqualInt(3, fwrite("hi\n", 1, 3, f)); + fclose(f); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_MTREE); + assertEqualString(archive_entry_pathname(ae), "file"); + assertEqualInt(archive_entry_uid(ae), 18); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0123); + assertEqualInt(archive_entry_size(ae), 3); + assertEqualInt(3, archive_read_data(a, buff, 3)); + assertEqualMem(buff, "hi\n", 3); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "dir"); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "dir/file with space"); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "file with space"); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "dir2"); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "dir2/dir3a"); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "dir2/dir3a/indir3a"); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "dir2/fullindir2"); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "dir2/indir2"); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "dir2/dir3b"); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "dir2/dir3b/indir3b"); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "notindir"); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualInt(12, archive_file_count(a)); + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +/* + * Test for a format that NetBSD mtree -C generates. + */ +DEFINE_TEST(test_read_format_mtree_nomagic_v2_form) +{ + const char reffile[] = "test_read_format_mtree_nomagic2.mtree"; + char buff[16]; + struct archive_entry *ae; + struct archive *a; + FILE *f; + + extract_reference_file(reffile); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_set_options(a, "mtree:checkfs")); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, reffile, 11)); + + /* + * Read "file", whose data is available on disk. + */ + f = fopen("file", "wb"); + assert(f != NULL); + assertEqualInt(3, fwrite("hi\n", 1, 3, f)); + fclose(f); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_MTREE); + assertEqualString(archive_entry_pathname(ae), "./file"); + assertEqualInt(archive_entry_uid(ae), 18); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0123); + assertEqualInt(archive_entry_size(ae), 3); + assertEqualInt(3, archive_read_data(a, buff, 3)); + assertEqualMem(buff, "hi\n", 3); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "./dir"); + assertEqualInt(archive_entry_mode(ae), AE_IFDIR | 0755); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "./dir/file with space"); + assertEqualInt(archive_entry_uid(ae), 18); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "./file with space"); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "./dir2"); + assertEqualInt(archive_entry_mode(ae), AE_IFDIR | 0755); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "./dir2/dir3a"); + assertEqualInt(archive_entry_mode(ae), AE_IFDIR | 0755); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualInt(6, archive_file_count(a)); + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +/* + * Test for a format that NetBSD mtree -D generates. + */ +DEFINE_TEST(test_read_format_mtree_nomagic_v2_netbsd_form) +{ + const char reffile[] = "test_read_format_mtree_nomagic3.mtree"; + char buff[16]; + struct archive_entry *ae; + struct archive *a; + FILE *f; + + extract_reference_file(reffile); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_set_options(a, "mtree:checkfs")); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, reffile, 11)); + + /* + * Read "file", whose data is available on disk. + */ + f = fopen("file", "wb"); + assert(f != NULL); + assertEqualInt(3, fwrite("hi\n", 1, 3, f)); + fclose(f); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_MTREE); + assertEqualString(archive_entry_pathname(ae), "./file"); + assertEqualInt(archive_entry_uid(ae), 18); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0123); + assertEqualInt(archive_entry_size(ae), 3); + assertEqualInt(3, archive_read_data(a, buff, 3)); + assertEqualMem(buff, "hi\n", 3); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "./dir"); + assertEqualInt(archive_entry_mode(ae), AE_IFDIR | 0755); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "./dir/file with space"); + assertEqualInt(archive_entry_uid(ae), 18); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "./file with space"); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "./dir2"); + assertEqualInt(archive_entry_mode(ae), AE_IFDIR | 0755); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "./dir2/dir3a"); + assertEqualInt(archive_entry_mode(ae), AE_IFDIR | 0755); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualInt(6, archive_file_count(a)); + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +/* + * We should get a warning if the contents file doesn't exist. + */ +DEFINE_TEST(test_read_format_mtree_nonexistent_contents_file) +{ + static char archive[] = + "#mtree\n" + "a type=file contents=nonexistent_file\n"; + struct archive_entry *ae; + struct archive *a; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_set_options(a, "mtree:checkfs")); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, archive, sizeof(archive))); + assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae)); + assert(strlen(archive_error_string(a)) > 0); + assertEqualString(archive_entry_pathname(ae), "a"); + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_file_count(a)); + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} +/* + * Check mtree file with non-printable ascii characters + */ +DEFINE_TEST(test_read_format_mtree_noprint) +{ + const char reffile[] = "test_read_format_mtree_noprint.mtree"; + struct archive_entry *ae; + struct archive *a; + + extract_reference_file(reffile); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, reffile, 11)); + + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); + assertEqualString("Can't parse line 3", archive_error_string(a)); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_mtree.mtree.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_mtree.mtree.uu new file mode 100644 index 0000000..f1c9d60 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_mtree.mtree.uu @@ -0,0 +1,20 @@ +begin 644 test_read_format_mtree.mtree +M(VUT7!E/61I<@H@9FEL95PP-#!W:71H7#`T,'-P86-E('1Y<&4]9FEL +M92!U:60],3@*("XN"F9I;&5<,#0P=VET:%PP-#!S<&%C92!T>7!E/69I;&4* +M9&ER,B!T>7!E/61I<@H@9&ER,V$@='EP93UD:7(*("!I;F1I7!E/61I<@H@(&EN9&ER,V(@ +M='EP93UF:6QE"B`@9FEL96YA;65<7'=I=&A<"E]E7!E/69I +M;&4@F4]+3$*9&ER,B]B:6=F:6QE('1Y +M<&4]9FEL92!S:7IE/3DR,C,S-S(P,S8X-30W-S4X,#<*9&ER,B]T;V]B:6=F +M:6QE('1Y<&4]9FEL92!S:7IE/3DR,C,S-S(P,S8X-30W-S4X,#@*9&ER,B]V +M97)Y;VQD9FEL92!T>7!E/69I;&4@=&EM93TM.3(R,S,W,C`S-C@U-#$(K!GIC*XFR0`$```J0+:$XP```!D-F)H[#SE9+2' +4+E"L=ASXUI%R(I"HD'ZA(5?1`Q`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_mtree_nomagic.mtree.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_mtree_nomagic.mtree.uu new file mode 100644 index 0000000..be08910 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_mtree_nomagic.mtree.uu @@ -0,0 +1,11 @@ +begin 644 test_read_format_mtree_nomagic.mtree +M9FEL92!T>7!E/69I;&4@=6ED/3$X(&UO9&4],#$R,R!S:7IE/3,*9&ER('1Y +M<&4]9&ER"B!F:6QE7#`T,'=I=&A<,#0P7!E/61I<@H@(&EN9&ER,V$@='EP93UF:6QE"F1I +M7!E/69I;&4@;6]D93TP-S7!E/69I;&4*(&1I7!E/69I +M;&4*("`N+@H@+BX*;F]T:6YD:7(@='EP93UF:6QE"F1IF4],PHN +M+V1I7!E/61I7!E/61I7!E/61I7!E/61I<@ID:7)?P[;%H<2'('1Y<&4]9&ER"@`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_pax_bz2.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_pax_bz2.c new file mode 100644 index 0000000..8c5d28e --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_pax_bz2.c @@ -0,0 +1,69 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_pax_bz2.c 201247 2009-12-30 05:59:21Z kientzle $"); + +static unsigned char archive[] = { +'B','Z','h','9','1','A','Y','&','S','Y',152,180,30,185,0,0,140,127,176,212, +144,0,' ','@',1,255,226,8,'d','H',' ',238,'/',159,'@',0,16,4,'@',0,8,'0', +0,216,'A',164,167,147,'Q',147,'!',180,'#',0,'L',153,162,'i',181,'?','P',192, +26,'h','h',209,136,200,6,128,13,12,18,132,202,'5','O',209,'5','=',26,'2', +154,7,168,12,2,'d',252,13,254,29,'4',247,181,'l','T','i',130,5,195,1,'2', +'@',146,18,251,245,'c','J',130,224,172,'$','l','4',235,170,186,'c','1',255, +179,'K',188,136,18,208,152,192,149,153,10,'{','|','0','8',166,3,6,9,128,172, +'(',164,220,244,149,6,' ',243,212,'B',25,17,'6',237,13,'I',152,'L',129,209, +'G','J','<',137,'Y',16,'b',21,18,'a','Y','l','t','r',160,128,147,'l','f', +'~',219,206,'=','?','S',233,'3',251,'L','~',17,176,169,'%',23,'_',225,'M', +'C','u','k',218,8,'q',216,'(',22,235,'K',131,136,146,136,147,202,0,158,134, +'F',23,160,184,'s','0','a',246,'*','P',7,2,238,'H',167,10,18,19,22,131,215, +' '}; + +DEFINE_TEST(test_read_format_pax_bz2) +{ + struct archive_entry *ae; + struct archive *a; + int r; + + assert((a = archive_read_new()) != NULL); + r = archive_read_support_filter_bzip2(a); + if (r != ARCHIVE_OK) { + archive_read_close(a); + skipping("Bzip2 unavailable"); + return; + } + assertEqualIntA(a,ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a,ARCHIVE_OK, + archive_read_open_memory(a, archive, sizeof(archive))); + assertEqualIntA(a,ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_file_count(a)); + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_BZIP2); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualIntA(a,ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar.c new file mode 100644 index 0000000..1425eb9 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar.c @@ -0,0 +1,3810 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2011 Andres Mejia + * Copyright (c) 2011-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +#include + +DEFINE_TEST(test_read_format_rar_set_format) +{ + struct archive *a; + struct archive_entry *ae; + const char reffile[] = "test_read_format_rar.rar"; + + extract_reference_file(reffile); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_RAR)); + assertA(0 == archive_read_open_filename(a, reffile, 10240)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_rar_basic) +{ + char buff[64]; + const char reffile[] = "test_read_format_rar.rar"; + const char test_txt[] = "test text document\r\n"; + int size = sizeof(test_txt)-1; + struct archive_entry *ae; + struct archive *a; + + extract_reference_file(reffile); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_filename(a, reffile, 10240)); + + /* First header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.txt", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(20, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertA(size == archive_read_data(a, buff, size)); + assertEqualMem(buff, test_txt, size); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Second header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testlink", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(41471, archive_entry_mode(ae)); + assertEqualString("test.txt", archive_entry_symlink(ae)); + assertEqualIntA(a, 0, archive_read_data(a, buff, sizeof(buff))); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Third header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testdir/test.txt", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(20, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertA(size == archive_read_data(a, buff, size)); + assertEqualMem(buff, test_txt, size); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Fourth header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testdir", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(16877, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Fifth header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testemptydir", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(16877, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Test EOF */ + assertA(1 == archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_file_count(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_rar_subblock) +{ + char buff[64]; + const char reffile[] = "test_read_format_rar_subblock.rar"; + const char test_txt[] = "test text document\r\n"; + int size = sizeof(test_txt)-1; + struct archive_entry *ae; + struct archive *a; + + extract_reference_file(reffile); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_filename(a, reffile, 10240)); + + /* First header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.txt", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(20, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertA(size == archive_read_data(a, buff, size)); + assertEqualMem(buff, test_txt, size); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Test EOF */ + assertA(1 == archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_file_count(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_rar_noeof) +{ + char buff[64]; + const char reffile[] = "test_read_format_rar_noeof.rar"; + const char test_txt[] = "test text document\r\n"; + int size = sizeof(test_txt)-1; + struct archive_entry *ae; + struct archive *a; + + extract_reference_file(reffile); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_filename(a, reffile, 10240)); + + /* First header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.txt", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(20, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertA(size == archive_read_data(a, buff, size)); + assertEqualMem(buff, test_txt, size); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Test EOF */ + assertA(1 == archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_file_count(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_rar_unicode_UTF8) +{ + char buff[30]; + const char reffile[] = "test_read_format_rar_unicode.rar"; + const char test_txt[] = "kanji"; + struct archive_entry *ae; + struct archive *a; + + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } + + extract_reference_file(reffile); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_filename(a, reffile, 10240)); + + /* First header. */ + assertA(0 == archive_read_next_header(a, &ae)); +#if defined(__APPLE__) +#define f1name "\xE8\xA1\xA8\xE3\x81\x9F\xE3\x82\x99\xE3\x82\x88/"\ + "\xE6\x96\xB0\xE3\x81\x97\xE3\x81\x84\xE3\x83\x95\xE3\x82\xA9"\ + "\xE3\x83\xAB\xE3\x82\xBF\xE3\x82\x99/\xE6\x96\xB0\xE8\xA6\x8F"\ + "\xE3\x83\x86\xE3\x82\xAD\xE3\x82\xB9\xE3\x83\x88 "\ + "\xE3\x83\x88\xE3\x82\x99\xE3\x82\xAD\xE3\x83\xA5\xE3\x83\xA1"\ + "\xE3\x83\xB3\xE3\x83\x88.txt" /* NFD */ +#else +#define f1name "\xE8\xA1\xA8\xE3\x81\xA0\xE3\x82\x88/"\ + "\xE6\x96\xB0\xE3\x81\x97\xE3\x81\x84\xE3\x83\x95\xE3\x82\xA9"\ + "\xE3\x83\xAB\xE3\x83\x80/\xE6\x96\xB0\xE8\xA6\x8F"\ + "\xE3\x83\x86\xE3\x82\xAD\xE3\x82\xB9\xE3\x83\x88 "\ + "\xE3\x83\x89\xE3\x82\xAD\xE3\x83\xA5\xE3\x83\xA1"\ + "\xE3\x83\xB3\xE3\x83\x88.txt" /* NFC */ +#endif + assertEqualUTF8String(f1name, archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + + /* Second header. */ + assertA(0 == archive_read_next_header(a, &ae)); +#if defined(__APPLE__) +#define f2name "\xE8\xA1\xA8\xE3\x81\x9F\xE3\x82\x99\xE3\x82\x88/"\ + "\xE6\xBC\xA2\xE5\xAD\x97\xE9\x95\xB7\xE3\x81\x84\xE3\x83\x95"\ + "\xE3\x82\xA1\xE3\x82\xA4\xE3\x83\xAB\xE5\x90\x8Dlong-filename-in-"\ + "\xE6\xBC\xA2\xE5\xAD\x97.txt" /* NFD */ +#else +#define f2name "\xE8\xA1\xA8\xE3\x81\xA0\xE3\x82\x88/"\ + "\xE6\xBC\xA2\xE5\xAD\x97\xE9\x95\xB7\xE3\x81\x84\xE3\x83\x95"\ + "\xE3\x82\xA1\xE3\x82\xA4\xE3\x83\xAB\xE5\x90\x8Dlong-filename-in-"\ + "\xE6\xBC\xA2\xE5\xAD\x97.txt" /* NFC */ +#endif + assertEqualUTF8String(f2name, archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertEqualInt(5, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualIntA(a, 5, archive_read_data(a, buff, 5)); + assertEqualMem(buff, test_txt, 5); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Third header. */ + assertA(0 == archive_read_next_header(a, &ae)); +#if defined(__APPLE__) +#define f3name "\xE8\xA1\xA8\xE3\x81\x9F\xE3\x82\x99\xE3\x82\x88/"\ + "\xE6\x96\xB0\xE3\x81\x97\xE3\x81\x84\xE3\x83\x95\xE3\x82"\ + "\xA9\xE3\x83\xAB\xE3\x82\xBF\xE3\x82\x99" /* NFD */ +#else +#define f3name "\xE8\xA1\xA8\xE3\x81\xA0\xE3\x82\x88/"\ + "\xE6\x96\xB0\xE3\x81\x97\xE3\x81\x84\xE3\x83\x95\xE3\x82"\ + "\xA9\xE3\x83\xAB\xE3\x83\x80" /* NFC */ +#endif + assertEqualUTF8String(f3name, archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(16877, archive_entry_mode(ae)); + + /* Fourth header. */ + assertA(0 == archive_read_next_header(a, &ae)); +#if defined(__APPLE__) +#define f4name "\xE8\xA1\xA8\xE3\x81\x9F\xE3\x82\x99\xE3\x82\x88" /* NFD */ +#else +#define f4name "\xE8\xA1\xA8\xE3\x81\xA0\xE3\x82\x88" /* NFC */ +#endif + assertEqualUTF8String(f4name, archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(16877, archive_entry_mode(ae)); + + /* Fifth header, which has a symbolic-link name in multi-byte characters. */ + assertA(0 == archive_read_next_header(a, &ae)); +#if defined(__APPLE__) +#define f5name "\xE8\xA1\xA8\xE3\x81\x9F\xE3\x82\x99\xE3\x82\x88/"\ + "\xE3\x83\x95\xE3\x82\xA1\xE3\x82\xA4\xE3\x83\xAB" /* NFD */ +#else +#define f5name "\xE8\xA1\xA8\xE3\x81\xA0\xE3\x82\x88/"\ + "\xE3\x83\x95\xE3\x82\xA1\xE3\x82\xA4\xE3\x83\xAB" /* NFC */ +#endif + assertEqualUTF8String(f5name, archive_entry_pathname(ae)); + assertEqualUTF8String( + "\xE6\xBC\xA2\xE5\xAD\x97\xE9\x95\xB7\xE3\x81\x84\xE3\x83\x95" + "\xE3\x82\xA1\xE3\x82\xA4\xE3\x83\xAB\xE5\x90\x8Dlong-filename-in-" + "\xE6\xBC\xA2\xE5\xAD\x97.txt", archive_entry_symlink(ae)); + assertA((int)archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(41453, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertEqualIntA(a, 0, archive_read_data(a, buff, sizeof(buff))); + + /* Sixth header */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualUTF8String( + "abcdefghijklmnopqrs\xE3\x83\x86\xE3\x82\xB9\xE3\x83\x88.txt", + archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertEqualInt(16, archive_entry_size(ae)); + assertEqualInt(33204, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertEqualIntA(a, 16, archive_read_data(a, buff, sizeof(buff))); + + /* Test EOF */ + assertA(1 == archive_read_next_header(a, &ae)); + assertEqualInt(6, archive_file_count(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_rar_unicode_CP932) +{ + char buff[30]; + const char reffile[] = "test_read_format_rar_unicode.rar"; + const char test_txt[] = "kanji"; + struct archive_entry *ae; + struct archive *a; + + if (NULL == setlocale(LC_ALL, "Japanese_Japan") && + NULL == setlocale(LC_ALL, "ja_JP.SJIS")) { + skipping("CP932 locale not available on this system."); + return; + } + + extract_reference_file(reffile); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + /* Specify the charset of symbolic-link file name. */ + if (ARCHIVE_OK != archive_read_set_options(a, "rar:hdrcharset=UTF-8")) { + skipping("This system cannot convert character-set" + " from UTF-8 to CP932."); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + assertA(0 == archive_read_open_filename(a, reffile, 10240)); + + /* First header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("\x95\x5c\x82\xbe\x82\xe6/\x90\x56\x82\xb5\x82\xa2" + "\x83\x74\x83\x48\x83\x8b\x83\x5f/\x90\x56\x8b\x4b\x83\x65\x83\x4c" + "\x83\x58\x83\x67 \x83\x68\x83\x4c\x83\x85\x83\x81\x83\x93\x83\x67.txt", + archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Second header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("\x95\x5c\x82\xbe\x82\xe6/\x8a\xbf\x8e\x9a" + "\x92\xb7\x82\xa2\x83\x74\x83\x40\x83\x43\x83\x8b\x96\xbc\x6c" + "\x6f\x6e\x67\x2d\x66\x69\x6c\x65\x6e\x61\x6d\x65\x2d\x69\x6e" + "\x2d\x8a\xbf\x8e\x9a.txt", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertEqualInt(5, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertA(5 == archive_read_data(a, buff, 5)); + assertEqualMem(buff, test_txt, 5); + + /* Third header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("\x95\x5c\x82\xbe\x82\xe6/" + "\x90\x56\x82\xb5\x82\xa2\x83\x74\x83\x48\x83\x8b\x83\x5f", + archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(16877, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Fourth header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("\x95\x5c\x82\xbe\x82\xe6", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(16877, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Fifth header, which has a symbolic-link name in multi-byte characters. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("\x95\x5c\x82\xbe\x82\xe6/" + "\x83\x74\x83\x40\x83\x43\x83\x8B", archive_entry_pathname(ae)); + assertEqualString("\x8a\xbf\x8e\x9a" + "\x92\xb7\x82\xa2\x83\x74\x83\x40\x83\x43\x83\x8b\x96\xbc\x6c" + "\x6f\x6e\x67\x2d\x66\x69\x6c\x65\x6e\x61\x6d\x65\x2d\x69\x6e" + "\x2d\x8a\xbf\x8e\x9a.txt", archive_entry_symlink(ae)); + assertA((int)archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(41453, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertEqualIntA(a, 0, archive_read_data(a, buff, sizeof(buff))); + + /* Sixth header */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualUTF8String( + "abcdefghijklmnopqrs\x83\x65\x83\x58\x83\x67.txt", + archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertEqualInt(16, archive_entry_size(ae)); + assertEqualInt(33204, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertEqualIntA(a, 16, archive_read_data(a, buff, sizeof(buff))); + + /* Test EOF */ + assertA(1 == archive_read_next_header(a, &ae)); + assertEqualInt(6, archive_file_count(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_rar_compress_normal) +{ + const char reffile[] = "test_read_format_rar_compress_normal.rar"; + char file1_buff[20111]; + int file1_size = sizeof(file1_buff); + const char file1_test_txt[] = "


    \n" + "

    \n" + "\n" + ""; + char file2_buff[20]; + int file2_size = sizeof(file2_buff); + const char file2_test_txt[] = "test text document\r\n"; + struct archive_entry *ae; + struct archive *a; + + extract_reference_file(reffile); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_filename(a, reffile, 10240)); + + /* First header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("LibarchiveAddingTest.html", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(file1_size, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertA(file1_size == archive_read_data(a, file1_buff, file1_size)); + assertEqualMem(&file1_buff[file1_size - sizeof(file1_test_txt) + 1], + file1_test_txt, sizeof(file1_test_txt) - 1); + + /* Second header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testlink", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(41471, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertEqualString("LibarchiveAddingTest.html", archive_entry_symlink(ae)); + assertEqualIntA(a, 0, archive_read_data(a, file1_buff, 30)); + + /* Third header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testdir/test.txt", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(file2_size, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertA(file2_size == archive_read_data(a, file2_buff, file2_size)); + assertEqualMem(&file2_buff[file2_size + 1 - sizeof(file2_test_txt)], + file2_test_txt, sizeof(file2_test_txt) - 1); + + /* Fourth header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testdir/LibarchiveAddingTest.html", + archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(file1_size, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertA(file1_size == archive_read_data(a, file1_buff, file1_size)); + assertEqualMem(&file1_buff[file1_size - sizeof(file1_test_txt) + 1], + file1_test_txt, sizeof(file1_test_txt) - 1); + + /* Fifth header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testdir", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(16877, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Sixth header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testemptydir", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(16877, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Test EOF */ + assertA(1 == archive_read_next_header(a, &ae)); + assertEqualInt(6, archive_file_count(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +/* This test is for sufficiently large files that would have been compressed + * using multiple lzss blocks. + */ +DEFINE_TEST(test_read_format_rar_multi_lzss_blocks) +{ + const char reffile[] = "test_read_format_rar_multi_lzss_blocks.rar"; + const char test_txt[] = "-bottom: 0in\">
    \n

    \n\n"; + int size = 20131111, offset = 0; + char buff[64]; + struct archive_entry *ae; + struct archive *a; + + extract_reference_file(reffile); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_filename(a, reffile, 10240)); + + /* First header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("multi_lzss_blocks_test.txt", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(size, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + while (offset + (int)sizeof(buff) < size) + { + assertA(sizeof(buff) == archive_read_data(a, buff, sizeof(buff))); + offset += sizeof(buff); + } + assertA(size - offset == archive_read_data(a, buff, size - offset)); + assertEqualMem(buff, test_txt, size - offset); + + /* Test EOF */ + assertA(1 == archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_file_count(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_rar_compress_best) +{ + const char reffile[] = "test_read_format_rar_compress_best.rar"; + char file1_buff[20111]; + int file1_size = sizeof(file1_buff); + const char file1_test_txt[] = "


    \n" + "

    \n" + "\n" + ""; + char file2_buff[20]; + int file2_size = sizeof(file2_buff); + const char file2_test_txt[] = "test text document\r\n"; + struct archive_entry *ae; + struct archive *a; + + extract_reference_file(reffile); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_filename(a, reffile, 10240)); + + /* First header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("LibarchiveAddingTest.html", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(file1_size, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertA(file1_size == archive_read_data(a, file1_buff, file1_size)); + assertEqualMem(&file1_buff[file1_size - sizeof(file1_test_txt) + 1], + file1_test_txt, sizeof(file1_test_txt) - 1); + + /* Second header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testlink", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(41471, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertEqualString("LibarchiveAddingTest.html", archive_entry_symlink(ae)); + assertEqualIntA(a, 0, archive_read_data(a, file1_buff, 30)); + + /* Third header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testdir/test.txt", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(file2_size, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertA(file2_size == archive_read_data(a, file2_buff, file2_size)); + assertEqualMem(&file2_buff[file2_size + 1 - sizeof(file2_test_txt)], + file2_test_txt, sizeof(file2_test_txt) - 1); + + /* Fourth header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testdir/LibarchiveAddingTest.html", + archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(file1_size, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertA(file1_size == archive_read_data(a, file1_buff, file1_size)); + assertEqualMem(&file1_buff[file1_size - sizeof(file1_test_txt) + 1], + file1_test_txt, sizeof(file1_test_txt) - 1); + + /* Fifth header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testdir", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(16877, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Sixth header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testemptydir", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(16877, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Test EOF */ + assertA(1 == archive_read_next_header(a, &ae)); + assertEqualInt(6, archive_file_count(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +/* This is a test for RAR files compressed using a technique where compression + * switches back and forth to and from ppmd and lzss decoding. + */ +DEFINE_TEST(test_read_format_rar_ppmd_lzss_conversion) +{ + const char reffile[] = "test_read_format_rar_ppmd_lzss_conversion.rar"; + const char test_txt[] = "gin-bottom: 0in\">
    \n

    \n\n"; + int size = 241647978, offset = 0; + char buff[64]; + struct archive_entry *ae; + struct archive *a; + + extract_reference_file(reffile); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_filename(a, reffile, 10240)); + + /* First header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("ppmd_lzss_conversion_test.txt", + archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(size, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + while (offset + (int)sizeof(buff) < size) + { + assertA(sizeof(buff) == archive_read_data(a, buff, sizeof(buff))); + offset += sizeof(buff); + } + assertA(size - offset == archive_read_data(a, buff, size - offset)); + assertEqualMem(buff, test_txt, size - offset); + + /* Test EOF */ + assertA(1 == archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_file_count(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_rar_binary) +{ + const char reffile[] = "test_read_format_rar_binary_data.rar"; + char *file1_buff = malloc(1048576); + int file1_size = 1048576; + const char file1_test_txt[] = "\x37\xef\xb2\xbe\x33\xf6\xcc\xcb\xee\x2a\x10" + "\x9d\x2e\x01\xe9\xf6\xf9\xe5\xe6\x67\x0c\x2b" + "\xd8\x6b\xa0\x26\x9a\xf7\x93\x87\x42\xf1\x08" + "\x42\xdc\x9b\x76\x91\x20\xa4\x01\xbe\x67\xbd" + "\x08\x74\xde\xec"; + char file2_buff[32618]; + int file2_size = sizeof(file2_buff); + const char file2_test_txt[] = "\x00\xee\x78\x00\x00\x4d\x45\x54\x41\x2d\x49" + "\x4e\x46\x2f\x6d\x61\x6e\x69\x66\x65\x73\x74" + "\x2e\x78\x6d\x6c\x50\x4b\x05\x06\x00\x00\x00" + "\x00\x12\x00\x12\x00\xaa\x04\x00\x00\xaa\x7a" + "\x00\x00\x00\x00"; + struct archive_entry *ae; + struct archive *a; + + extract_reference_file(reffile); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_filename(a, reffile, 10240)); + + /* First header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("random_data.bin", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(file1_size, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertA(file1_size == archive_read_data(a, file1_buff, file1_size)); + assertEqualMem(&file1_buff[file1_size - sizeof(file1_test_txt) + 1], + file1_test_txt, sizeof(file1_test_txt) - 1); + + /* Second header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("LibarchiveAddingTest.odt", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(file2_size, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertA(file2_size == archive_read_data(a, file2_buff, file2_size)); + assertEqualMem(&file2_buff[file2_size + 1 - sizeof(file2_test_txt)], + file2_test_txt, sizeof(file2_test_txt) - 1); + + /* Test EOF */ + assertA(1 == archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_file_count(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + free(file1_buff); +} + +DEFINE_TEST(test_read_format_rar_windows) +{ + char buff[441]; + const char reffile[] = "test_read_format_rar_windows.rar"; + const char test_txt[] = "test text file\r\n"; + int size = sizeof(test_txt)-1; + struct archive_entry *ae; + struct archive *a; + + extract_reference_file(reffile); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_filename(a, reffile, 10240)); + + /* First header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testdir/test.txt", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(16, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertA(size == archive_read_data(a, buff, size)); + assertEqualMem(buff, test_txt, size); + + /* Second header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.txt", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(16, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertA(size == archive_read_data(a, buff, size)); + assertEqualMem(buff, test_txt, size); + + /* Third header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testshortcut.lnk", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(sizeof(buff), archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertA(sizeof(buff) == archive_read_data(a, buff, sizeof(buff))); + + /* Fourth header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testdir", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(16877, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Fifth header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testemptydir", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(16877, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Test EOF */ + assertA(1 == archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_file_count(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_rar_multivolume) +{ + const char *reffiles[] = + { + "test_read_format_rar_multivolume.part0001.rar", + "test_read_format_rar_multivolume.part0002.rar", + "test_read_format_rar_multivolume.part0003.rar", + "test_read_format_rar_multivolume.part0004.rar", + NULL + }; + int file1_size = 241647978, offset = 0; + char buff[64]; + const char file1_test_txt[] = "gin-bottom: 0in\">
    \n

    \n\n" + ""; + char file2_buff[20111]; + int file2_size = sizeof(file2_buff); + const char file2_test_txt[] = "


    \n" + "

    \n" + "\n" + ""; + char file3_buff[20]; + int file3_size = sizeof(file3_buff); + const char file3_test_txt[] = "test text document\r\n"; + struct archive_entry *ae; + struct archive *a; + + extract_reference_files(reffiles); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_filenames(a, reffiles, 10240)); + + /* First header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("ppmd_lzss_conversion_test.txt", + archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(file1_size, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + while (offset + (int)sizeof(buff) < file1_size) + { + assertA(sizeof(buff) == archive_read_data(a, buff, sizeof(buff))); + offset += sizeof(buff); + } + assertA(file1_size - offset == + archive_read_data(a, buff, file1_size - offset)); + assertEqualMem(buff, file1_test_txt, file1_size - offset); + + /* Second header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("LibarchiveAddingTest.html", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(file2_size, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertA(file2_size == archive_read_data(a, file2_buff, file2_size)); + assertEqualMem(&file2_buff[file2_size - sizeof(file2_test_txt) + 1], + file2_test_txt, sizeof(file2_test_txt) - 1); + + /* Third header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testlink", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(41471, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertEqualString("LibarchiveAddingTest.html", archive_entry_symlink(ae)); + assertEqualIntA(a, 0, archive_read_data(a, file2_buff, 30)); + + /* Fourth header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testdir/test.txt", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(file3_size, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertA(file3_size == archive_read_data(a, file3_buff, file3_size)); + assertEqualMem(&file3_buff[file3_size + 1 - sizeof(file3_test_txt)], + file3_test_txt, sizeof(file3_test_txt) - 1); + + /* Fifth header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testdir/LibarchiveAddingTest.html", + archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(file2_size, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertA(file2_size == archive_read_data(a, file2_buff, file2_size)); + assertEqualMem(&file2_buff[file2_size - sizeof(file2_test_txt) + 1], + file2_test_txt, sizeof(file2_test_txt) - 1); + + /* Sixth header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testdir", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(16877, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Seventh header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testemptydir", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(16877, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Test EOF */ + assertA(1 == archive_read_next_header(a, &ae)); + assertEqualInt(7, archive_file_count(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_rar_multivolume_skip) +{ + const char *reffiles[] = + { + "test_read_format_rar_multivolume.part0001.rar", + "test_read_format_rar_multivolume.part0002.rar", + "test_read_format_rar_multivolume.part0003.rar", + "test_read_format_rar_multivolume.part0004.rar", + NULL + }; + int file1_size = 241647978; + int file2_size = 20111; + int file3_size = 20; + struct archive_entry *ae; + struct archive *a; + + extract_reference_files(reffiles); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_filenames(a, reffiles, 10240)); + + /* First header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("ppmd_lzss_conversion_test.txt", + archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(file1_size, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Second header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("LibarchiveAddingTest.html", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(file2_size, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Third header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testlink", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(41471, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertEqualString("LibarchiveAddingTest.html", archive_entry_symlink(ae)); + + /* Fourth header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testdir/test.txt", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(file3_size, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Fifth header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testdir/LibarchiveAddingTest.html", + archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(file2_size, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Sixth header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testdir", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(16877, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Seventh header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testemptydir", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(16877, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Test EOF */ + assertA(1 == archive_read_next_header(a, &ae)); + assertEqualInt(7, archive_file_count(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_rar_sfx) +{ + char buff[441]; + const char reffile[] = "test_read_format_rar_sfx.exe"; + const char test_txt[] = "test text file\r\n"; + int size = sizeof(test_txt)-1; + struct archive_entry *ae; + struct archive *a; + + extract_reference_file(reffile); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_filename(a, reffile, 10240)); + + /* First header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.txt", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(16, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertA(size == archive_read_data(a, buff, size)); + assertEqualMem(buff, test_txt, size); + + /* Second header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testshortcut.lnk", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(sizeof(buff), archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertA(sizeof(buff) == archive_read_data(a, buff, sizeof(buff))); + + /* Third header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testdir/test.txt", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(16, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertA(size == archive_read_data(a, buff, size)); + assertEqualMem(buff, test_txt, size); + + /* Fourth header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testdir", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(16877, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Fifth header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testemptydir", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(16877, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Test EOF */ + assertA(1 == archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_file_count(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_rar_multivolume_stored_file) +{ + const char *reffiles[] = + { + "test_rar_multivolume_single_file.part1.rar", + "test_rar_multivolume_single_file.part2.rar", + "test_rar_multivolume_single_file.part3.rar", + NULL + }; + char file_buff[20111]; + int file_size = sizeof(file_buff); + const char file_test_txt[] = "


    \n" + "

    \n" + "\n" + ""; + struct archive_entry *ae; + struct archive *a; + + extract_reference_files(reffiles); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_filenames(a, reffiles, 10240)); + + /* First header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("LibarchiveAddingTest.html", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(file_size, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertA(file_size == archive_read_data(a, file_buff, file_size)); + assertEqualMem(&file_buff[file_size - sizeof(file_test_txt) + 1], + file_test_txt, sizeof(file_test_txt) - 1); + + /* Test EOF */ + assertA(1 == archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_file_count(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_rar_multivolume_stored_file_skip) +{ + const char *reffiles[] = + { + "test_rar_multivolume_single_file.part1.rar", + "test_rar_multivolume_single_file.part2.rar", + "test_rar_multivolume_single_file.part3.rar", + NULL + }; + int file_size = 20111; + struct archive_entry *ae; + struct archive *a; + + extract_reference_files(reffiles); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_filenames(a, reffiles, 10240)); + + /* First header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("LibarchiveAddingTest.html", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(file_size, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Test EOF */ + assertA(1 == archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_file_count(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_rar_multivolume_seek_data) +{ + const char *reffiles[] = + { + "test_rar_multivolume_single_file.part1.rar", + "test_rar_multivolume_single_file.part2.rar", + "test_rar_multivolume_single_file.part3.rar", + NULL + }; + char buff[64]; + int file_size = 20111; + const char file_test_txt1[] = "d. \n

    \n

    " + "
    \n

    \n\n"; + const char file_test_txt2[] = "\n<"; + const char file_test_txt3[] = "mplify writing such tests,\ntry to use plat" + "form-independent codin"; + const char file_test_txt4[] = "lString in the example above)\ngenerat" + "e detailed log message"; + const char file_test_txt5[] = "SS=\"western\">make check will usually" + " run\n\tall of the tests."; + struct archive_entry *ae; + struct archive *a; + + extract_reference_files(reffiles); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_filenames(a, reffiles, 10240)); + + /* First header. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("LibarchiveAddingTest.html", archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualInt(file_size, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Seek to the end minus 64 bytes */ + assertA(file_size - (int)sizeof(buff) == + archive_seek_data(a, file_size - (int)sizeof(buff), SEEK_SET)); + assertA(sizeof(buff) == archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, file_test_txt1, sizeof(file_test_txt1) - 1); + + /* Seek back to the beginning */ + assertA(0 == archive_seek_data(a, 0, SEEK_SET)); + assertA(sizeof(buff) == archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, file_test_txt2, sizeof(file_test_txt2) - 1); + + /* Seek to the middle of the combined data block */ + assertA(10054 == archive_seek_data(a, 10054, SEEK_SET)); + assertA(sizeof(buff) == archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, file_test_txt3, sizeof(file_test_txt3) - 1); + + /* Seek to 32 bytes before the end of the first data sub-block */ + assertA(6860 == archive_seek_data(a, 6860, SEEK_SET)); + assertA(sizeof(buff) == archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, file_test_txt4, sizeof(file_test_txt4) - 1); + + /* Seek to 32 bytes before the end of the second data sub-block */ + assertA(13752 == archive_seek_data(a, 13752, SEEK_SET)); + assertA(sizeof(buff) == archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, file_test_txt5, sizeof(file_test_txt5) - 1); + + /* Use various combinations of SEEK_SET, SEEK_CUR, and SEEK_END */ + assertEqualInt(file_size, archive_seek_data(a, 0, SEEK_END)); + assertEqualInt(0, archive_seek_data(a, 0, SEEK_SET)); + assertEqualInt(0, archive_seek_data(a, 0, SEEK_CUR)); + assertEqualInt(-1, archive_seek_data(a, -10, SEEK_CUR)); + assertEqualInt(10, archive_seek_data(a, 10, SEEK_CUR)); + assertEqualInt(-1, archive_seek_data(a, -20, SEEK_CUR)); + assertEqualInt(10, archive_seek_data(a, 0, SEEK_CUR)); + assertEqualInt(file_size, archive_seek_data(a, 0, SEEK_END)); + assertEqualInt(file_size - 20, archive_seek_data(a, -20, SEEK_END)); + assertEqualInt(file_size + 40, archive_seek_data(a, 40, SEEK_END)); + assertEqualInt(file_size + 40, archive_seek_data(a, 0, SEEK_CUR)); + assertEqualInt(file_size + 40 + 20, archive_seek_data(a, 20, SEEK_CUR)); + assertEqualInt(file_size + 40 + 20 + 20, archive_seek_data(a, 20, SEEK_CUR)); + assertEqualInt(file_size + 20, archive_seek_data(a, 20, SEEK_END)); + assertEqualInt(file_size - 20, archive_seek_data(a, -20, SEEK_END)); + + /* + * Attempt to read from the end of the file. These should return + * 0 for end of file. + */ + assertEqualInt(file_size, archive_seek_data(a, 0, SEEK_END)); + assertA(0 == archive_read_data(a, buff, sizeof(buff))); + assertEqualInt(file_size + 40, archive_seek_data(a, 40, SEEK_CUR)); + assertA(0 == archive_read_data(a, buff, sizeof(buff))); + + /* Seek to the end minus 64 bytes */ + assertA(0 == archive_seek_data(a, 0, SEEK_SET)); + assertA(file_size - (int)sizeof(buff) == + archive_seek_data(a, -(int)sizeof(buff), SEEK_END)); + assertA(sizeof(buff) == archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, file_test_txt1, sizeof(file_test_txt1) - 1); + + /* The file position should be at the end of the file here */ + assertA(file_size == archive_seek_data(a, 0, SEEK_CUR)); + + /* Seek back to the beginning */ + assertA(0 == archive_seek_data(a, -file_size, SEEK_CUR)); + assertA(sizeof(buff) == archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, file_test_txt2, sizeof(file_test_txt2) - 1); + + /* Seek to the middle of the combined data block */ + assertA(10054 == archive_seek_data(a, 10054 - (int)sizeof(buff), SEEK_CUR)); + assertA(sizeof(buff) == archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, file_test_txt3, sizeof(file_test_txt3) - 1); + + /* Seek to 32 bytes before the end of the first data sub-block */ + assertA(6860 == archive_seek_data(a, 6860 - (10054 + (int)sizeof(buff)), + SEEK_CUR)); + assertA(sizeof(buff) == archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, file_test_txt4, sizeof(file_test_txt4) - 1); + + /* Seek to 32 bytes before the end of the second data sub-block */ + assertA(13752 == archive_seek_data(a, 13752 - file_size, SEEK_END)); + assertA(sizeof(buff) == archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, file_test_txt5, sizeof(file_test_txt5) - 1); + + /* Test EOF */ + assertA(1 == archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_file_count(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_rar_multivolume_seek_multiple_files) +{ + const char *reffiles[] = + { + "test_rar_multivolume_multiple_files.part1.rar", + "test_rar_multivolume_multiple_files.part2.rar", + "test_rar_multivolume_multiple_files.part3.rar", + "test_rar_multivolume_multiple_files.part4.rar", + "test_rar_multivolume_multiple_files.part5.rar", + "test_rar_multivolume_multiple_files.part6.rar", + NULL + }; + char buff[64]; + int file_size = 20111; + const char file_test_txt1[] = "d. \n

    \n

    " + "
    \n

    \n\n"; + const char file_test_txt2[] = "\n<"; + const char file_test_txt3[] = "mplify writing such tests,\ntry to use plat" + "form-independent codin"; + const char file_test_txt4[] = "\nfailures. \n

    \n
    \n

    The " + "large tar tester attempts to", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 4576, + archive_seek_data(a, 4576, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "hat was expected. \n

    \n

    \n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 20111 - (int)(sizeof(buff)-1), SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 4576, + archive_seek_data(a, 4576, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "hat was expected. \n

    \n

    Large tar tester

    \n

    The " + "large tar tester attempts to", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, 0, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 20111 - (int)(sizeof(buff)-1), SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, 0, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 17749, + archive_seek_data(a, 17749, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\">Large tar tester

    \n

    The " + "large tar tester attempts to", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 4576, + archive_seek_data(a, 4576, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "hat was expected. \n

    \n

    \n

    Large tar tester

    \n

    The " + "large tar tester attempts to", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 2236, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 17749, + archive_seek_data(a, -2362, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\">Large tar tester

    \n

    The " + "large tar tester attempts to", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 4576, + archive_seek_data(a, -13236, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "hat was expected. \n

    \n

    \n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 19985, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 4576, + archive_seek_data(a, -15535, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "hat was expected. \n

    \n

    Large tar tester

    \n

    The " + "large tar tester attempts to", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -17812, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 19985, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -20111, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 17749, + archive_seek_data(a, 17686, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\">Large tar tester

    \n

    The " + "large tar tester attempts to", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 4576, + archive_seek_data(a, -13236, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "hat was expected. \n

    \n

    \n

    Large tar tester

    \n

    The " + "large tar tester attempts to", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, -((int)sizeof(buff)-1), SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 17749, + archive_seek_data(a, -2362, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\">Large tar tester

    \n

    The " + "large tar tester attempts to", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 4576, + archive_seek_data(a, -15535, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "hat was expected. \n

    \n

    \n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, -((int)sizeof(buff)-1), SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 4576, + archive_seek_data(a, -15535, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "hat was expected. \n

    \n

    Large tar tester

    \n

    The " + "large tar tester attempts to", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -20111, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, -((int)sizeof(buff)-1), SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -20111, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 17749, + archive_seek_data(a, -2362, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\">Large tar tester

    \n

    The " + "large tar tester attempts to", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 4576, + archive_seek_data(a, -15535, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "hat was expected. \n

    \n

    '0@9&]C=6UE;G0- +M"J'(=."0,0````````````,`````8W?:/A0P!P#M00``=&5S=&1I61I +#include + +#define PROLOGUE(reffile) \ + struct archive_entry *ae; \ + struct archive *a; \ + \ + (void) a; /* Make the compiler happy if we won't use this variables */ \ + (void) ae; /* in the test cases. */ \ + \ + extract_reference_file(reffile); \ + assert((a = archive_read_new()) != NULL); \ + assertA(0 == archive_read_support_filter_all(a)); \ + assertA(0 == archive_read_support_format_all(a)); \ + assertA(0 == archive_read_open_filename(a, reffile, 10240)) + +#define PROLOGUE_MULTI(reffile) \ + struct archive_entry *ae; \ + struct archive *a; \ + \ + (void) a; \ + (void) ae; \ + \ + extract_reference_files(reffile); \ + assert((a = archive_read_new()) != NULL); \ + assertA(0 == archive_read_support_filter_all(a)); \ + assertA(0 == archive_read_support_format_all(a)); \ + assertA(0 == archive_read_open_filenames(a, reffile, 10240)) + + +#define EPILOGUE() \ + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); \ + assertEqualInt(ARCHIVE_OK, archive_read_free(a)) + +static +int verify_data(const uint8_t* data_ptr, int magic, int size) { + int i = 0; + + /* This is how the test data inside test files was generated; + * we are re-generating it here and we check if our re-generated + * test data is the same as in the test file. If this test is + * failing it's either because there's a bug in the test case, + * or the unpacked data is corrupted. */ + + for(i = 0; i < size / 4; ++i) { + const int k = i + 1; + const signed int* lptr = (const signed int*) &data_ptr[i * 4]; + signed int val = k * k - 3 * k + (1 + magic); + + if(val < 0) + val = 0; + + /* *lptr is a value inside unpacked test file, val is the + * value that should be in the unpacked test file. */ + + if(archive_le32dec(lptr) != (uint32_t) val) + return 0; + } + + return 1; +} + +static +int extract_one(struct archive* a, struct archive_entry* ae, uint32_t crc) { + la_ssize_t fsize, bytes_read; + uint8_t* buf; + int ret = 1; + uint32_t computed_crc; + + fsize = (la_ssize_t) archive_entry_size(ae); + buf = malloc(fsize); + if(buf == NULL) + return 1; + + bytes_read = archive_read_data(a, buf, fsize); + if(bytes_read != fsize) { + assertEqualInt(bytes_read, fsize); + goto fn_exit; + } + + computed_crc = crc32(0, buf, fsize); + assertEqualInt(computed_crc, crc); + ret = 0; + +fn_exit: + free(buf); + return ret; +} + +DEFINE_TEST(test_read_format_rar5_set_format) +{ + struct archive *a; + struct archive_entry *ae; + const char reffile[] = "test_read_format_rar5_stored.rar"; + + extract_reference_file(reffile); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_RAR_V5)); + assertA(0 == archive_read_open_filename(a, reffile, 10240)); + assertA(0 == archive_read_next_header(a, &ae)); + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_stored) +{ + const char helloworld_txt[] = "hello libarchive test suite!\n"; + la_ssize_t file_size = sizeof(helloworld_txt) - 1; + char buff[64]; + + PROLOGUE("test_read_format_rar5_stored.rar"); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("helloworld.txt", archive_entry_pathname(ae)); + assertA((int) archive_entry_mtime(ae) > 0); + assertA((int) archive_entry_ctime(ae) == 0); + assertA((int) archive_entry_atime(ae) == 0); + assertEqualInt(file_size, archive_entry_size(ae)); + assertEqualInt(33188, archive_entry_mode(ae)); + assertA(file_size == archive_read_data(a, buff, file_size)); + assertEqualMem(buff, helloworld_txt, file_size); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_compressed) +{ + const int DATA_SIZE = 1200; + uint8_t buff[1200]; + + PROLOGUE("test_read_format_rar5_compressed.rar"); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.bin", archive_entry_pathname(ae)); + assertA((int) archive_entry_mtime(ae) > 0); + assertEqualInt(DATA_SIZE, archive_entry_size(ae)); + assertA(DATA_SIZE == archive_read_data(a, buff, DATA_SIZE)); + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + verify_data(buff, 0, DATA_SIZE); + + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_multiple_files) +{ + const int DATA_SIZE = 4096; + uint8_t buff[4096]; + + PROLOGUE("test_read_format_rar5_multiple_files.rar"); + + /* There should be 4 files inside this test file. Check for their + * existence, and also check the contents of those test files. */ + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test1.bin", archive_entry_pathname(ae)); + assertEqualInt(DATA_SIZE, archive_entry_size(ae)); + assertA(DATA_SIZE == archive_read_data(a, buff, DATA_SIZE)); + assertA(verify_data(buff, 1, DATA_SIZE)); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test2.bin", archive_entry_pathname(ae)); + assertEqualInt(DATA_SIZE, archive_entry_size(ae)); + assertA(DATA_SIZE == archive_read_data(a, buff, DATA_SIZE)); + assertA(verify_data(buff, 2, DATA_SIZE)); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test3.bin", archive_entry_pathname(ae)); + assertEqualInt(DATA_SIZE, archive_entry_size(ae)); + assertA(DATA_SIZE == archive_read_data(a, buff, DATA_SIZE)); + assertA(verify_data(buff, 3, DATA_SIZE)); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test4.bin", archive_entry_pathname(ae)); + assertEqualInt(DATA_SIZE, archive_entry_size(ae)); + assertA(DATA_SIZE == archive_read_data(a, buff, DATA_SIZE)); + assertA(verify_data(buff, 4, DATA_SIZE)); + + /* There should be no more files in this archive. */ + + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + EPILOGUE(); +} + +/* This test is really the same as the test above, but it deals with a solid + * archive instead of a regular archive. The test solid archive contains the + * same set of files as regular test archive, but it's size is 2x smaller, + * because solid archives reuse the window buffer from previous compressed + * files, so it's able to compress lots of small files more effectively. */ + +DEFINE_TEST(test_read_format_rar5_multiple_files_solid) +{ + const int DATA_SIZE = 4096; + uint8_t buff[4096]; + + PROLOGUE("test_read_format_rar5_multiple_files_solid.rar"); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test1.bin", archive_entry_pathname(ae)); + assertEqualInt(DATA_SIZE, archive_entry_size(ae)); + assertA(DATA_SIZE == archive_read_data(a, buff, DATA_SIZE)); + assertA(verify_data(buff, 1, DATA_SIZE)); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test2.bin", archive_entry_pathname(ae)); + assertEqualInt(DATA_SIZE, archive_entry_size(ae)); + assertA(DATA_SIZE == archive_read_data(a, buff, DATA_SIZE)); + assertA(verify_data(buff, 2, DATA_SIZE)); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test3.bin", archive_entry_pathname(ae)); + assertEqualInt(DATA_SIZE, archive_entry_size(ae)); + assertA(DATA_SIZE == archive_read_data(a, buff, DATA_SIZE)); + assertA(verify_data(buff, 3, DATA_SIZE)); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test4.bin", archive_entry_pathname(ae)); + assertEqualInt(DATA_SIZE, archive_entry_size(ae)); + assertA(DATA_SIZE == archive_read_data(a, buff, DATA_SIZE)); + assertA(verify_data(buff, 4, DATA_SIZE)); + + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_multiarchive_skip_all) +{ + const char* reffiles[] = { + "test_read_format_rar5_multiarchive.part01.rar", + "test_read_format_rar5_multiarchive.part02.rar", + "test_read_format_rar5_multiarchive.part03.rar", + "test_read_format_rar5_multiarchive.part04.rar", + "test_read_format_rar5_multiarchive.part05.rar", + "test_read_format_rar5_multiarchive.part06.rar", + "test_read_format_rar5_multiarchive.part07.rar", + "test_read_format_rar5_multiarchive.part08.rar", + NULL + }; + + PROLOGUE_MULTI(reffiles); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("home/antek/temp/build/unrar5/libarchive/bin/bsdcat_test", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("home/antek/temp/build/unrar5/libarchive/bin/bsdtar_test", archive_entry_pathname(ae)); + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_multiarchive_skip_all_but_first) +{ + const char* reffiles[] = { + "test_read_format_rar5_multiarchive.part01.rar", + "test_read_format_rar5_multiarchive.part02.rar", + "test_read_format_rar5_multiarchive.part03.rar", + "test_read_format_rar5_multiarchive.part04.rar", + "test_read_format_rar5_multiarchive.part05.rar", + "test_read_format_rar5_multiarchive.part06.rar", + "test_read_format_rar5_multiarchive.part07.rar", + "test_read_format_rar5_multiarchive.part08.rar", + NULL + }; + + PROLOGUE_MULTI(reffiles); + assertA(0 == archive_read_next_header(a, &ae)); + assertA(0 == extract_one(a, ae, 0x35277473)); + assertA(0 == archive_read_next_header(a, &ae)); + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_multiarchive_skip_all_but_second) +{ + const char* reffiles[] = { + "test_read_format_rar5_multiarchive.part01.rar", + "test_read_format_rar5_multiarchive.part02.rar", + "test_read_format_rar5_multiarchive.part03.rar", + "test_read_format_rar5_multiarchive.part04.rar", + "test_read_format_rar5_multiarchive.part05.rar", + "test_read_format_rar5_multiarchive.part06.rar", + "test_read_format_rar5_multiarchive.part07.rar", + "test_read_format_rar5_multiarchive.part08.rar", + NULL + }; + + PROLOGUE_MULTI(reffiles); + assertA(0 == archive_read_next_header(a, &ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertA(0 == extract_one(a, ae, 0xE59665F8)); + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_blake2) +{ + const la_ssize_t proper_size = 814; + uint8_t buf[814]; + + PROLOGUE("test_read_format_rar5_blake2.rar"); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualInt(proper_size, archive_entry_size(ae)); + + /* Should blake2 calculation fail, we'll get a failure return + * value from archive_read_data(). */ + + assertA(proper_size == archive_read_data(a, buf, proper_size)); + + /* To be extra pedantic, let's also check crc32 of the poem. */ + assertEqualInt(crc32(0, buf, proper_size), 0x7E5EC49E); + + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_arm_filter) +{ + /* This test unpacks a file that uses an ARM filter. The DELTA + * and X86 filters are tested implicitly in the "multiarchive_skip" + * test. */ + + const la_ssize_t proper_size = 90808; + uint8_t buf[90808]; + + PROLOGUE("test_read_format_rar5_arm.rar"); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualInt(proper_size, archive_entry_size(ae)); + assertA(proper_size == archive_read_data(a, buf, proper_size)); + + /* Yes, RARv5 unpacker itself should calculate the CRC, but in case + * the DONT_FAIL_ON_CRC_ERROR define option is enabled during compilation, + * let's still fail the test if the unpacked data is wrong. */ + assertEqualInt(crc32(0, buf, proper_size), 0x886F91EB); + + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_stored_skip_all) +{ + const char* fname = "test_read_format_rar5_stored_manyfiles.rar"; + + PROLOGUE(fname); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("make_uue.tcl", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("cebula.txt", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.bin", archive_entry_pathname(ae)); + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_stored_skip_in_part) +{ + const char* fname = "test_read_format_rar5_stored_manyfiles.rar"; + char buf[6]; + + /* Skip first, extract in part rest. */ + + PROLOGUE(fname); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("make_uue.tcl", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("cebula.txt", archive_entry_pathname(ae)); + assertA(6 == archive_read_data(a, buf, 6)); + assertEqualInt(0, memcmp(buf, "Cebula", 6)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.bin", archive_entry_pathname(ae)); + assertA(4 == archive_read_data(a, buf, 4)); + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_stored_skip_all_but_first) +{ + const char* fname = "test_read_format_rar5_stored_manyfiles.rar"; + char buf[405]; + + /* Extract first, skip rest. */ + + PROLOGUE(fname); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("make_uue.tcl", archive_entry_pathname(ae)); + assertA(405 == archive_read_data(a, buf, sizeof(buf))); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("cebula.txt", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.bin", archive_entry_pathname(ae)); + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_stored_skip_all_in_part) +{ + const char* fname = "test_read_format_rar5_stored_manyfiles.rar"; + char buf[4]; + + /* Extract in part all */ + + PROLOGUE(fname); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("make_uue.tcl", archive_entry_pathname(ae)); + assertA(4 == archive_read_data(a, buf, 4)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("cebula.txt", archive_entry_pathname(ae)); + assertA(4 == archive_read_data(a, buf, 4)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.bin", archive_entry_pathname(ae)); + assertA(4 == archive_read_data(a, buf, 4)); + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_multiarchive_solid_extr_all) +{ + const char* reffiles[] = { + "test_read_format_rar5_multiarchive_solid.part01.rar", + "test_read_format_rar5_multiarchive_solid.part02.rar", + "test_read_format_rar5_multiarchive_solid.part03.rar", + "test_read_format_rar5_multiarchive_solid.part04.rar", + NULL + }; + + PROLOGUE_MULTI(reffiles); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("cebula.txt", archive_entry_pathname(ae)); + assertA(0 == extract_one(a, ae, 0x7E5EC49E)); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.bin", archive_entry_pathname(ae)); + assertA(0 == extract_one(a, ae, 0x7cca70cd)); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test1.bin", archive_entry_pathname(ae)); + assertA(0 == extract_one(a, ae, 0x7e13b2c6)); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test2.bin", archive_entry_pathname(ae)); + assertA(0 == extract_one(a, ae, 0xf166afcb)); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test3.bin", archive_entry_pathname(ae)); + assertA(0 == extract_one(a, ae, 0x9fb123d9)); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test4.bin", archive_entry_pathname(ae)); + assertA(0 == extract_one(a, ae, 0x10c43ed4)); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test5.bin", archive_entry_pathname(ae)); + assertA(0 == extract_one(a, ae, 0xb9d155f2)); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test6.bin", archive_entry_pathname(ae)); + assertA(0 == extract_one(a, ae, 0x36a448ff)); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("elf-Linux-ARMv7-ls", archive_entry_pathname(ae)); + assertA(0 == extract_one(a, ae, 0x886F91EB)); + + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_multiarchive_solid_skip_all) +{ + const char* reffiles[] = { + "test_read_format_rar5_multiarchive_solid.part01.rar", + "test_read_format_rar5_multiarchive_solid.part02.rar", + "test_read_format_rar5_multiarchive_solid.part03.rar", + "test_read_format_rar5_multiarchive_solid.part04.rar", + NULL + }; + + PROLOGUE_MULTI(reffiles); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("cebula.txt", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test1.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test2.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test3.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test4.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test5.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test6.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("elf-Linux-ARMv7-ls", archive_entry_pathname(ae)); + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_multiarchive_solid_skip_all_but_first) +{ + const char* reffiles[] = { + "test_read_format_rar5_multiarchive_solid.part01.rar", + "test_read_format_rar5_multiarchive_solid.part02.rar", + "test_read_format_rar5_multiarchive_solid.part03.rar", + "test_read_format_rar5_multiarchive_solid.part04.rar", + NULL + }; + + PROLOGUE_MULTI(reffiles); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("cebula.txt", archive_entry_pathname(ae)); + assertA(0 == extract_one(a, ae, 0x7E5EC49E)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test1.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test2.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test3.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test4.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test5.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test6.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("elf-Linux-ARMv7-ls", archive_entry_pathname(ae)); + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + EPILOGUE(); +} + +/* "skip_all_but_scnd" -> am I hitting the test name limit here after + * expansion of "scnd" to "second"? */ + +DEFINE_TEST(test_read_format_rar5_multiarchive_solid_skip_all_but_scnd) +{ + const char* reffiles[] = { + "test_read_format_rar5_multiarchive_solid.part01.rar", + "test_read_format_rar5_multiarchive_solid.part02.rar", + "test_read_format_rar5_multiarchive_solid.part03.rar", + "test_read_format_rar5_multiarchive_solid.part04.rar", + NULL + }; + + PROLOGUE_MULTI(reffiles); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("cebula.txt", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.bin", archive_entry_pathname(ae)); + assertA(0 == extract_one(a, ae, 0x7CCA70CD)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test1.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test2.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test3.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test4.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test5.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test6.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("elf-Linux-ARMv7-ls", archive_entry_pathname(ae)); + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_multiarchive_solid_skip_all_but_third) +{ + const char* reffiles[] = { + "test_read_format_rar5_multiarchive_solid.part01.rar", + "test_read_format_rar5_multiarchive_solid.part02.rar", + "test_read_format_rar5_multiarchive_solid.part03.rar", + "test_read_format_rar5_multiarchive_solid.part04.rar", + NULL + }; + + PROLOGUE_MULTI(reffiles); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("cebula.txt", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test1.bin", archive_entry_pathname(ae)); + assertA(0 == extract_one(a, ae, 0x7E13B2C6)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test2.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test3.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test4.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test5.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test6.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("elf-Linux-ARMv7-ls", archive_entry_pathname(ae)); + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_multiarchive_solid_skip_all_but_last) +{ + const char* reffiles[] = { + "test_read_format_rar5_multiarchive_solid.part01.rar", + "test_read_format_rar5_multiarchive_solid.part02.rar", + "test_read_format_rar5_multiarchive_solid.part03.rar", + "test_read_format_rar5_multiarchive_solid.part04.rar", + NULL + }; + + PROLOGUE_MULTI(reffiles); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("cebula.txt", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test1.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test2.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test3.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test4.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test5.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test6.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("elf-Linux-ARMv7-ls", archive_entry_pathname(ae)); + assertA(0 == extract_one(a, ae, 0x886F91EB)); + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_solid_skip_all) +{ + const char* reffile = "test_read_format_rar5_solid.rar"; + + /* Skip all */ + + PROLOGUE(reffile); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test1.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test2.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test3.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test4.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test5.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test6.bin", archive_entry_pathname(ae)); + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_solid_skip_all_but_first) +{ + const char* reffile = "test_read_format_rar5_solid.rar"; + + /* Extract first, skip rest */ + + PROLOGUE(reffile); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.bin", archive_entry_pathname(ae)); + assertA(0 == extract_one(a, ae, 0x7CCA70CD)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test1.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test2.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test3.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test4.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test5.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test6.bin", archive_entry_pathname(ae)); + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_solid_skip_all_but_second) +{ + const char* reffile = "test_read_format_rar5_solid.rar"; + + /* Skip first, extract second, skip rest */ + + PROLOGUE(reffile); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test1.bin", archive_entry_pathname(ae)); + assertA(0 == extract_one(a, ae, 0x7E13B2C6)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test2.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test3.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test4.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test5.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test6.bin", archive_entry_pathname(ae)); + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_solid_skip_all_but_last) +{ + const char* reffile = "test_read_format_rar5_solid.rar"; + + /* Skip all but last, extract last */ + + PROLOGUE(reffile); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test1.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test2.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test3.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test4.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test5.bin", archive_entry_pathname(ae)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test6.bin", archive_entry_pathname(ae)); + assertA(0 == extract_one(a, ae, 0x36A448FF)); + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_extract_win32) +{ + PROLOGUE("test_read_format_rar5_win32.rar"); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("testdir", archive_entry_pathname(ae)); + assertEqualInt(archive_entry_mode(ae), AE_IFDIR | 0755); + assertA(0 == extract_one(a, ae, 0)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.bin", archive_entry_pathname(ae)); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + assertA(0 == extract_one(a, ae, 0x7CCA70CD)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test1.bin", archive_entry_pathname(ae)); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + assertA(0 == extract_one(a, ae, 0x7E13B2C6)); + assertA(0 == archive_read_next_header(a, &ae)); + /* Read only file */ + assertEqualString("test2.bin", archive_entry_pathname(ae)); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0444); + assertA(0 == extract_one(a, ae, 0xF166AFCB)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test3.bin", archive_entry_pathname(ae)); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + assertA(0 == extract_one(a, ae, 0x9FB123D9)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test4.bin", archive_entry_pathname(ae)); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + assertA(0 == extract_one(a, ae, 0x10C43ED4)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test5.bin", archive_entry_pathname(ae)); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + assertA(0 == extract_one(a, ae, 0xB9D155F2)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test6.bin", archive_entry_pathname(ae)); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + assertA(0 == extract_one(a, ae, 0x36A448FF)); + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_block_by_block) +{ + /* This test uses strange buffer sizes intentionally. */ + + struct archive_entry *ae; + struct archive *a; + uint8_t buf[173]; + int bytes_read; + uint32_t computed_crc = 0; + + extract_reference_file("test_read_format_rar5_compressed.rar"); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_filename(a, "test_read_format_rar5_compressed.rar", 130)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.bin", archive_entry_pathname(ae)); + assertEqualInt(1200, archive_entry_size(ae)); + + /* File size is 1200 bytes, we're reading it using a buffer of 173 bytes. + * Libarchive is configured to use a buffer of 130 bytes. */ + + while(1) { + /* archive_read_data should return one of: + * a) 0, if there is no more data to be read, + * b) negative value, if there was an error, + * c) positive value, meaning how many bytes were read. + */ + + bytes_read = archive_read_data(a, buf, sizeof(buf)); + assertA(bytes_read >= 0); + if(bytes_read <= 0) + break; + + computed_crc = crc32(computed_crc, buf, bytes_read); + } + + assertEqualInt(computed_crc, 0x7CCA70CD); + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_owner) +{ + const int DATA_SIZE = 5; + uint8_t buff[5]; + + PROLOGUE("test_read_format_rar5_owner.rar"); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("root.txt", archive_entry_pathname(ae)); + assertEqualString("root", archive_entry_uname(ae)); + assertEqualString("wheel", archive_entry_gname(ae)); + assertA((int) archive_entry_mtime(ae) > 0); + assertEqualInt(DATA_SIZE, archive_entry_size(ae)); + assertA(DATA_SIZE == archive_read_data(a, buff, DATA_SIZE)); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("nobody.txt", archive_entry_pathname(ae)); + assertEqualString("nobody", archive_entry_uname(ae)); + assertEqualString("nogroup", archive_entry_gname(ae)); + assertA((int) archive_entry_mtime(ae) > 0); + assertEqualInt(DATA_SIZE, archive_entry_size(ae)); + assertA(DATA_SIZE == archive_read_data(a, buff, DATA_SIZE)); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("numeric.txt", archive_entry_pathname(ae)); + assertEqualInt(9999, archive_entry_uid(ae)); + assertEqualInt(8888, archive_entry_gid(ae)); + assertA((int) archive_entry_mtime(ae) > 0); + assertEqualInt(DATA_SIZE, archive_entry_size(ae)); + assertA(DATA_SIZE == archive_read_data(a, buff, DATA_SIZE)); + + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_symlink) +{ + const int DATA_SIZE = 5; + uint8_t buff[5]; + + PROLOGUE("test_read_format_rar5_symlink.rar"); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("file.txt", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertA((int) archive_entry_mtime(ae) > 0); + assertEqualInt(DATA_SIZE, archive_entry_size(ae)); + assertA(DATA_SIZE == archive_read_data(a, buff, DATA_SIZE)); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("symlink.txt", archive_entry_pathname(ae)); + assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); + assertEqualString("file.txt", archive_entry_symlink(ae)); + assertEqualInt(AE_SYMLINK_TYPE_FILE, archive_entry_symlink_type(ae)); + assertA(0 == archive_read_data(a, NULL, archive_entry_size(ae))); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("dirlink", archive_entry_pathname(ae)); + assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); + assertEqualString("dir", archive_entry_symlink(ae)); + assertEqualInt(AE_SYMLINK_TYPE_DIRECTORY, archive_entry_symlink_type(ae)); + assertA(0 == archive_read_data(a, NULL, archive_entry_size(ae))); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("dir", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertA(0 == archive_read_data(a, NULL, archive_entry_size(ae))); + + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_hardlink) +{ + const int DATA_SIZE = 5; + uint8_t buff[5]; + + PROLOGUE("test_read_format_rar5_hardlink.rar"); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("file.txt", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertA((int) archive_entry_mtime(ae) > 0); + assertEqualInt(DATA_SIZE, archive_entry_size(ae)); + assertA(DATA_SIZE == archive_read_data(a, buff, DATA_SIZE)); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("hardlink.txt", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualString("file.txt", archive_entry_hardlink(ae)); + assertA(0 == archive_read_data(a, NULL, archive_entry_size(ae))); + + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_extra_field_version) +{ + PROLOGUE("test_read_format_rar5_extra_field_version.rar"); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("bin/2to3;1", archive_entry_pathname(ae)); + assertA(0 == extract_one(a, ae, 0xF24181B7)); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("bin/2to3", archive_entry_pathname(ae)); + assertA(0 == extract_one(a, ae, 0xF24181B7)); + + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_readtables_overflow) +{ + uint8_t buf[16]; + + PROLOGUE("test_read_format_rar5_readtables_overflow.rar"); + + /* This archive is invalid. However, processing it shouldn't cause any + * buffer overflow errors during reading rar5 tables. */ + + (void) archive_read_next_header(a, &ae); + (void) archive_read_data(a, buf, sizeof(buf)); + (void) archive_read_next_header(a, &ae); + + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_leftshift1) +{ + uint8_t buf[16]; + + PROLOGUE("test_read_format_rar5_leftshift1.rar"); + + /* This archive is invalid. However, processing it shouldn't cause any + * errors related to undefined operations when using -fsanitize. */ + + (void) archive_read_next_header(a, &ae); + (void) archive_read_data(a, buf, sizeof(buf)); + (void) archive_read_next_header(a, &ae); + + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_leftshift2) +{ + uint8_t buf[16]; + + PROLOGUE("test_read_format_rar5_leftshift2.rar"); + + /* This archive is invalid. However, processing it shouldn't cause any + * errors related to undefined operations when using -fsanitize. */ + + (void) archive_read_next_header(a, &ae); + (void) archive_read_data(a, buf, sizeof(buf)); + (void) archive_read_next_header(a, &ae); + + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_truncated_huff) +{ + uint8_t buf[16]; + + PROLOGUE("test_read_format_rar5_truncated_huff.rar"); + + /* This archive is invalid. However, processing it shouldn't cause any + * errors related to undefined operations when using -fsanitize. */ + + (void) archive_read_next_header(a, &ae); + (void) archive_read_data(a, buf, sizeof(buf)); + (void) archive_read_next_header(a, &ae); + + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_invalid_dict_reference) +{ + uint8_t buf[16]; + + PROLOGUE("test_read_format_rar5_invalid_dict_reference.rar"); + + /* This test should fail on parsing the header. */ + assertA(archive_read_next_header(a, &ae) != ARCHIVE_OK); + + /* This archive is invalid. However, processing it shouldn't cause any + * errors related to buffer underflow when using -fsanitize. */ + assertA(archive_read_data(a, buf, sizeof(buf)) <= 0); + + /* This test only cares about not returning success here. */ + assertA(ARCHIVE_OK != archive_read_next_header(a, &ae)); + + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_distance_overflow) +{ + uint8_t buf[16]; + + PROLOGUE("test_read_format_rar5_distance_overflow.rar"); + + /* This archive is invalid. However, processing it shouldn't cause any + * errors related to variable overflows when using -fsanitize. */ + + (void) archive_read_next_header(a, &ae); + (void) archive_read_data(a, buf, sizeof(buf)); + (void) archive_read_next_header(a, &ae); + + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_nonempty_dir_stream) +{ + uint8_t buf[16]; + + PROLOGUE("test_read_format_rar5_nonempty_dir_stream.rar"); + + /* This archive is invalid. However, processing it shouldn't cause any + * errors related to buffer overflows when using -fsanitize. */ + + (void) archive_read_next_header(a, &ae); + (void) archive_read_data(a, buf, sizeof(buf)); + (void) archive_read_next_header(a, &ae); + + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_fileattr) +{ + unsigned long set, clear, flag; + + flag = 0; + + PROLOGUE("test_read_format_rar5_fileattr.rar"); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_mode(ae), 0444 | AE_IFREG); + assertEqualString("readonly.txt", archive_entry_pathname(ae)); + assertEqualString("rdonly", archive_entry_fflags_text(ae)); + archive_entry_fflags(ae, &set, &clear); +#if defined(__FreeBSD__) + flag = UF_READONLY; +#elif defined(_WIN32) && !defined(CYGWIN) + flag = FILE_ATTRIBUTE_READONLY; +#endif + assertEqualInt(flag, set & flag); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_mode(ae), 0644 | AE_IFREG); + assertEqualString("hidden.txt", archive_entry_pathname(ae)); + assertEqualString("hidden", archive_entry_fflags_text(ae)); + archive_entry_fflags(ae, &set, &clear); +#if defined(__FreeBSD__) + flag = UF_HIDDEN; +#elif defined(_WIN32) && !defined(CYGWIN) + flag = FILE_ATTRIBUTE_HIDDEN; +#endif + assertEqualInt(flag, set & flag); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_mode(ae), 0644 | AE_IFREG); + assertEqualString("system.txt", archive_entry_pathname(ae)); + assertEqualString("system", archive_entry_fflags_text(ae)); + archive_entry_fflags(ae, &set, &clear); +#if defined(__FreeBSD__) + flag = UF_SYSTEM;; +#elif defined(_WIN32) && !defined(CYGWIN) + flag = FILE_ATTRIBUTE_SYSTEM; +#endif + assertEqualInt(flag, set & flag); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_mode(ae), 0444 | AE_IFREG); + assertEqualString("ro_hidden.txt", archive_entry_pathname(ae)); + assertEqualString("rdonly,hidden", archive_entry_fflags_text(ae)); + archive_entry_fflags(ae, &set, &clear); +#if defined(__FreeBSD__) + flag = UF_READONLY | UF_HIDDEN; +#elif defined(_WIN32) && !defined(CYGWIN) + flag = FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN; +#endif + assertEqualInt(flag, set & flag); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_mode(ae), 0555 | AE_IFDIR); + assertEqualString("dir_readonly", archive_entry_pathname(ae)); + assertEqualString("rdonly", archive_entry_fflags_text(ae)); + archive_entry_fflags(ae, &set, &clear); +#if defined(__FreeBSD__) + flag = UF_READONLY; +#elif defined(_WIN32) && !defined(CYGWIN) + flag = FILE_ATTRIBUTE_READONLY; +#endif + assertEqualInt(flag, set & flag); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_mode(ae), 0755 | AE_IFDIR); + assertEqualString("dir_hidden", archive_entry_pathname(ae)); + assertEqualString("hidden", archive_entry_fflags_text(ae)); + archive_entry_fflags(ae, &set, &clear); +#if defined(__FreeBSD__) + flag = UF_HIDDEN; +#elif defined(_WIN32) && !defined(CYGWIN) + flag = FILE_ATTRIBUTE_HIDDEN; +#endif + assertEqualInt(flag, set & flag); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_mode(ae), 0755 | AE_IFDIR); + assertEqualString("dir_system", archive_entry_pathname(ae)); + assertEqualString("system", archive_entry_fflags_text(ae)); + archive_entry_fflags(ae, &set, &clear); +#if defined(__FreeBSD__) + flag = UF_SYSTEM; +#elif defined(_WIN32) && !defined(CYGWIN) + flag = FILE_ATTRIBUTE_SYSTEM; +#endif + assertEqualInt(flag, set & flag); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_mode(ae), 0555 | AE_IFDIR); + assertEqualString("dir_rohidden", archive_entry_pathname(ae)); + assertEqualString("rdonly,hidden", archive_entry_fflags_text(ae)); + archive_entry_fflags(ae, &set, &clear); +#if defined(__FreeBSD__) + flag = UF_READONLY | UF_HIDDEN; +#elif defined(_WIN32) && !defined(CYGWIN) + flag = FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN; +#endif + assertEqualInt(flag, set & flag); + + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_different_window_size) +{ + char buf[4096]; + PROLOGUE("test_read_format_rar5_different_window_size.rar"); + + /* Return codes of those calls are ignored, because this sample file + * is invalid. However, the unpacker shouldn't produce any SIGSEGV + * errors during processing. */ + + (void) archive_read_next_header(a, &ae); + while(0 < archive_read_data(a, buf, sizeof(buf))) {} + + (void) archive_read_next_header(a, &ae); + while(0 < archive_read_data(a, buf, sizeof(buf))) {} + + (void) archive_read_next_header(a, &ae); + while(0 < archive_read_data(a, buf, sizeof(buf))) {} + + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_arm_filter_on_window_boundary) +{ + char buf[4096]; + PROLOGUE("test_read_format_rar5_arm_filter_on_window_boundary.rar"); + + /* Return codes of those calls are ignored, because this sample file + * is invalid. However, the unpacker shouldn't produce any SIGSEGV + * errors during processing. */ + + (void) archive_read_next_header(a, &ae); + while(0 < archive_read_data(a, buf, sizeof(buf))) {} + + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_different_solid_window_size) +{ + char buf[4096]; + PROLOGUE("test_read_format_rar5_different_solid_window_size.rar"); + + /* Return codes of those calls are ignored, because this sample file + * is invalid. However, the unpacker shouldn't produce any SIGSEGV + * errors during processing. */ + + (void) archive_read_next_header(a, &ae); + while(0 < archive_read_data(a, buf, sizeof(buf))) {} + + (void) archive_read_next_header(a, &ae); + while(0 < archive_read_data(a, buf, sizeof(buf))) {} + + (void) archive_read_next_header(a, &ae); + while(0 < archive_read_data(a, buf, sizeof(buf))) {} + + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_different_winsize_on_merge) +{ + char buf[4096]; + PROLOGUE("test_read_format_rar5_different_winsize_on_merge.rar"); + + /* Return codes of those calls are ignored, because this sample file + * is invalid. However, the unpacker shouldn't produce any SIGSEGV + * errors during processing. */ + + (void) archive_read_next_header(a, &ae); + while(0 < archive_read_data(a, buf, sizeof(buf))) {} + + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_block_size_is_too_small) +{ + char buf[4096]; + PROLOGUE("test_read_format_rar5_block_size_is_too_small.rar"); + + /* This file is damaged, so those functions should return failure. + * Additionally, SIGSEGV shouldn't be raised during execution + * of those functions. */ + + assertA(archive_read_next_header(a, &ae) != ARCHIVE_OK); + assertA(archive_read_data(a, buf, sizeof(buf)) <= 0); + + EPILOGUE(); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_arm.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_arm.rar.uu new file mode 100644 index 0000000..19a8904 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_arm.rar.uu @@ -0,0 +1,916 @@ +begin 644 test_read_format_rar5_arm.rar +M4F%R(1H'`0"[Y3SZ#`$%"``'`0&6P(*``(S!/"8R`@,+SK\"!+C%!>V#`NN1 +M;XB`!0$296QF+4QI;G5X+4%2378W+6QS"@,3JRFO6QUI@`R+6-Q5@&9E5#(C +M9@!0A]YP23)D@&0D%C"*9$%8Q!<.!6645P45%I6X#%14]2"<"*BL0%2E*W($ +M.!`C8<"`G`DMI:E:*RM+:5HVP6"E$:RH-LJEKG`8D1`8J+8M%+O6\SOOS>]P +MP*W@]^^]]^^_O?O\_?@,MV[UO7!YPZUKS7FO-<&'XMF9UO>=[S.MYG777>M> +M;SN;DWL,_O[9(3\'_L`"`"K_L@`J@`(!_V0`90`(?]D`(4`!`/^R`$J`;;_M +M````MPQ/[73X?J'#APM<_SE:E63YR7GJ,$?>*[1@M]#_ +M7-+GLGV_:RC'WX>N[[[+\[E>\YW`M1[YLMZGK.N:2+5"\MTU`V>I+N:G,0(> +MF\_P^8]_7^3Z6%_#H^]TWLO<:W.?J7J`\=4^TCG"WGF8+Z#$Z5:J6T>$P@%Z +MRD]/8W#4%*DL\)WZOFQ/^/=,M!6OGDSSZLOID)N#U=)H^4\G".X?5=/G,Y;Y +M_\F2AN<,\APP@*7'W6D^K$V&%TSD5GYQGN;'_`+=6\NKBROP!S!H8>/]M_6` +MOCPGM>`=W716-+,M"`'Q8;NO>&_ODU/*+TH7P:_1K](OA%^I7ZIN>ZMC/J*I7ZYN/Z]3V'T%J7QRYL/>14Y)?MU^Y7[MA[V7I +M99OWWRGOU_KKYAN+^PQGV5/@K_::MWVL8]7]?[(A[#O^UZKIO`YO1WW`0?F]B'A/S\'W.FYSWZSI:WU:'#W;OZG!Z;< +M&=ZG23OEY_N)GRZ[NM-,O/!TE'29:Q7@K;&9;Z +M>VY6GS?L_MZL",WW_/_G]&ZQ.B\S\T[7]'X.GS/=97.;;H+M;>5T/F:+U:K4 +M^]=^VZKJN7<7OY->]A5/U-;^D!NEZ?U^!I^#/7;S?$$7V>J^ +MG=O5ON.RF'N/@NEAH/^,;([7"?%UGA_-]KR:NZ^7R6_[_Y^Q][4?7I_@T-'U +MOKY3P>HQ70W;[FN_#=M18>%J/*JL]Q;W^J[>7O]U[UUV_TH-ZYGO_E^G8V.P +MTT-]:^=^BN]^Z\MO]Q5'COYWR8T7I1 +M*K8Z^%S%-:1>7_)]W^EWO.N_?YWZ^:O'0?ICZ3,_-NH-VZKW?9>9[ZF<]OSH +M7?^-[U)CKMZ,7X_SZO1O.+\')>W\7M83[_Z;KTMX_)_3O/I6$'[?*_-2\KHJ +M.D]6;%/>6$O\OV[>?O^SS5TRWK^4[_'U?3_4_7['87FSM/Y4'I]=Z;_]6=!6 +M[_O(]7]C&WU]?.^$SQN7]+8.NA[_YM/6=+L'_:X^:VV1KIS'='LA`\KU^:SM +MOI\S7T_Y>/_2_^][FT]ZA->=O>1M.]J7AW=J\-S_/Y:Z:Y^Z=7/# +MKX(*KC7^++`O7"JZL95XX*OQ?=8Q5W,O4ZM559I0U7O%,'5*KS9+:*LK+QNY +M>==2&P[%]>%]QP)<5Y20&+G3+\/6JK6'[N,6Y5I\,(YFB&R\O.Y^4WSQE5RC +M#O9>7YLCMG+@KNIS\N1=%*9V7I:V4XJ3?RDVH)=^*2ZGMY8F_-)5 +MI>7CD-9RX+NV':2R&OTEUDN5;IPIEYW%4OY<=&4Z*7^^2(;#2XK(L-'+G5(I +MJY5Y\E?;67%=2:4/CC8R^[E7?9+EI"6IE]O+D5[(+,RX:_NY.TG4BGQU]C +M+)+"J;!B]F2K!RR"_-R%9=V9>AEQW;J84N5;F2WR7I?9-12_WOG$L7(1=<9> +MW5?R$7W4RX(X/K37N&,NJWZ$*IEIS+Y*7^_#E.#N45.)@ +M]HI9'9.4[%B_>)-1RXIXZ89>^4I?*NOY"\U^E-#+5=FY3F9<%&E.*EZ77DNW +MDJ\69S^636N4N^.(I+3RYM^KD*J_683R7E_))5P)Y5?["&R"8O$F=GY? +M[^^066EPQ9@?2XZD,OCY>=D#2LU7BR;:95^(IH57[LEP4J_UGRJ8N&<)I9+. +M#2XBKJB9UL)5[8_>/E\(C=:7.OWFE`5?K,.F5>'E-M)ODI3DY>UR>0$GC.V[I@Q@C\;E, +ML(8^NK[_&8EN>$^<;EW[OMUB+`'&0RQ^#%,3(B?;4#+=X/ +M_Y#+Y83QG[RR$^L;CLFO?UC`9H9#N\ME/K\;Y!'';23Z]7D&8@TZ$J"^<>T' +M&G?;8['`K-4_@KYC<@"//;XSON[\!<3\XZK8*O*0&3^$GXZ!;(Y')]]E\\#')/]W>.[J +MK6[RKRQ#RGT*?LEE&P)$F?_N01+8_'$I9-PGYJ^[0,?NK\#ONW$D"_?>`/O' +M]OE"/SW60`/ADV1^C+]ME.V7R`#Y[P2F5[?MN[`\1^\JJ95/L$P"@GWE>Y-. +MA4?0+VE/8/ZQH/^+=OE?`9+[6R@/\Y,D>5@?@#T$OH#F$T]@/6-[H);OR9]! +M?(K/@#\`_B%_A3[EFS.33^ +MP-"Z(.,GD.[6!^,ACD*X)OD3]A'[!?P04],H_^.`^._2:?_D7@G>>[[S&9-L +MC\$GT`\]!@DIX*7II"&?O(Y\L9'&$'7<&2,5+501=XW'X]!"(_J$\!%UX +M';X_+&M,?WG?"0R(E-A2$R*)U".LL)8)>VC#*`_V8P)OB6CR!<9/C#V +M,[[(B?CP%N[R8B\:#O(ELCWC)7;-7W+3Y91^.U0WRA#D"FBO(/Z%.0F[[SM6:S[W>0$ADN^[L&\I/^'"]BT>LKC@,R*`B! +M(?I!Z-NX[L$>LCX&4!6!?@V;P*O_WF1Q^-^NB#O'(D_)9>6[+P8X&I^^UE!L +M^(NFZ!9?>.%W0BZ[EF6^@LGS*Y(6;IFR0( +MQ0K)G@(O!!R*C\"T)?=RB\A/Q5CUE$1:6BPF\L>LK+5L2_?==YW^0XR(!G`J +M/2W:B[^S=>@+]W6-/TR@[XUWZ0OZEB^M5W&3)7X*GT;HY8WDJP9Y25*@Y:5O +MAD'LE^07&])L7M``)]FX?2.RB6#UD:OOLME987)47?>=LR?[EH6,R/?,TXQV +M7QN,QN62[K;HOE^`NNZR619=%2][_=MWPD"#\`^1.QLI!W65:)XXZ'C,8W\B +MJ_R=-^SZ6PG38?&7_G8"W4X?JNEZ;&8#G<%QH-_Z$0NF$#`\[S[3J/S7\Z^A +M_],GQQ_?&_X(N3\''^_(N%6G],?Z9\ROX2T]+&3MDSF3RF?HZ(_]IFG6$2TA +M=%Z'%\;K;>=H.?]/BSGMQ/%U'.;;B)#@;5]^+KG\3#?>Y7>T'`G>&[XG$=W# +MSASM#[?);^[\*Z_`]^.9^5S\_SN?EF?C>_!=>%=]_R7MT4;EOY\O[',_OIO6 +MYW]N`W'0>C4>?T?ZNE\WJ/S=7YG6>5B?(Z_\'9?=[3QNUU61T_<:3N_#RF@[ +M_.YC->#X.:S&=[_093P^[TG<:?(ZKM?&[3[O9?@Z_R,3Y76>9U?YNH\WI?U= +M'Y]1Z/0;C`?MYWUJ;]_,^QR_\^6C47_6#EMY?/ZS"Q__J.W/_#_=YHQ[N88` +ML'W\5X[O^ONWCG/7$^KW_+B.YVX^29`^(%I"L9_@OK>IV/6^3]/;T<][WO3WM4GUOQX?983]8!XX%!.\/IO.BWJAMKYO/I>E@[,& +M]`K^"O'OW8&_^3]R(_!G^UI0;QRL?$>6"^O7YSJ?T.OF`O(/\>SS#CB@WP'? +M[U.G_3>9`'IC^L&RI]OB?*FOD!_V]1>PV`_Z#OHDQ$L'Q3@(^`GX`?L!^T"P +M%`/SG?6!)T&X!7ZVH;]NODF@/X"/W/^F"?V^Y0"Y`_P*@#]'Y4!ISX@%`_W1 +M^>">;K\`'Y6\',S*9TXU&0=K`WI@[C1A`Y%TS%Y[P'*G_]O_RS-=\8/A:=)\ +M^69EH?Q3BW_[W]R7/,&L[-R/=_7L%2^*->J7E1L%3'*-BJ=FHL509#\;)B=L +MH>0;][GCOEO=>0_.MG<2_2!YKI%UB?;B/+?]4C4V0L=Z/VXU'N-%&U-OM)%S +M#KU7GUX:^77JU\DO5+XI>$OAEX*].O`7I5WZ]"N^7>+K*R\J;CBJJW5=LO$7 +MM5[1?;KV2^S7L5]@O8+ZE>O7SZ\-?+KU:^27JE\4O"7PR\%>G7@+TJ[]>A7? +M+O%UE[CYU5;JNV7B+VJ]HOMU[)?9KV*^P7L%]2O7KY]>&OEUZM?)+U2^*7A+ +MX9>"O3KP%Z5=^O0KOEWBZR]Q\RJMU7;+Q%[5>T7VZ]DOLU[%?8+V"^I7KU\^ +MO#7RZ]6ODEZI?%+PE\,O!7IUX"]*I*U)U;72)U]*7Z\!1KII;W9W\3A;@>0O +M^"ZATU]^48/HQ'V_UA-_I[7U8RT#2R%H-A%#H_TC=X&ND.(4HQ>!%!]>A,F5 +MK"/_Q-27EE#ZZR3P6%X??F3*AV0#FK$NL?M:KS!9_$CUM0(;R!**DQ?G7\3`Y_/70DX^]/MPN=4 +M_6@(DCHM:O)(4?<][H;QYV-].\;G&Z&8`4`G!":(BM@/N11U4HV(DY&T/F[7 +MLS%[<^]$1;S.X8+&4[+N)0[,]LY3P&'Y9DAU7"C#5F>X:N`,[(+)D[/`6Q<] +MS)DX"C*NUO-0@=3VIWWC="(N$9C\C'>`T+5*J4.5(F_OD#5']'RPG43A<%W* +MB93OZZ-:*1]U<=VPV^#$7\=Z7_)`T83/6L``7B).L"`SPAVRO^AE!(GJ`JJ2 +MU5=(F7P&S,II8`IN]@E!0HOHC_E%<=%)*5_K0:4F;%"&)MMY)+U6HOLDC4,, +M4RUE$9I`>8)@@,S?1+V)H7VR$7>9IHDTKE1DE+H`\1AY"DGOZ[4>4)#?WSQP +M](E->K^FK_W6"ZS^7EK7T0<$^RRVIR6OQ;,O8OE +M%*\H*6=L<7.X?:8J=/\9]Y:=Q:S'_'8TY)]8,$^>Q_]8'APUI/V/^"$/5G]9C^O&IRY6E?\?SM&'___^VFP8(9\@KX)=^O$"AVO8=2N5T; +M0+V*_MR%;6OS\7?N*\0Z&OKI'KJAC]O*?68:7E&L#QB[$+0M7`G8=Z/.6NK! +M<7W:Q;=_H8NW,\LO<@K*!M9'H&+$/5HMYS*=E4:$R\2/1C!9^[*Y91NR(T6` +M'C@+)_.V/6-0HV3.D-AHX8C]>E!L2D +M7827=^D28G"R\V%NA7=CW++PFU/NNEJ(?87<1[2MBUR`^VV)\PDVB;)'2^?; +M^UB',2M4S!FG#M6,.*Z$C5M+(Q5W8/LJ73'F=I'AB +MCS.D6]TX94@PNW9H3`L2Z/W]XXQGVFD=F?;EL9"Z!35BA@R1MB:3L([82="+ +MU\PP/0'6U]28^44,#-1KUS0H0%1QFXE\P5?(-@K\IJVZ.67JU)JA*7`Y]7*W +MYA4S42XP*B5.58:GDN-;2O4]5Q38J2%CR\&7?$!KS3;?3-!@"T@%&=.D6G2( +MFQ-BVIET#&FBI8&>\5&(9AAM,$T3`OAC>\=M&L)LEH%ZF\*E9$W;":\^/YE# +MP@?:"4OAF[.FU;-+9B[0'0S#'G!^9FP[R24[^4MWI;I@=L1'&JR]M\"+`$,*_1Y +M,FR%I2$>.V4)F;-#=HHFL4FRN(-`V4^HY9O^-_/TD.@DG/*`W%\4,[5D;=<\ +MRTIYK!1 +MW!`:%?AA>VI/N8,O]4+K6=()HGZQ,<.SYU4#`!0C_I8SJPS41T^];?&P0=M\ +M>BAJTNEKS3.'WRI8M\G%XM$@<@2H)$DO:_=%+:"V*3VFP'LI4#J4@NU3,,G, +M^(_<7C8$9L2)<+H-_*X4-JQTI+MC?PAU5I9&B;`.09W1:(7)RZ4#./_'OF5# +M4GZKA11OU\6I=KB?W$S^,,ON:0VR'WBS#X%)NE:[$S=VQG7J?,HE%?3>@R9/ +M!8G1?;@9EVW4;+%B'B^57V!]WPQ>*W:C+L,_ +M4B??:\0`XVDI=^FHNXWAX^\.?+"T4MGZ$DUDIAF7X9&PAG+<0_=?NDV&HV"U#DA;.30&S-X!&VY +M\H2$PS#O-?)3[MB*B!5\;TYV>VE`V3;#D#@B+:E)X5G>O,RSE-2?N'):H^\N +M$35L.L]1G/1K3/:*2PC%O%YW\"AV2=:$.LR!M##I2%V_9DA?7KCE*/50*BO@ +M!S(V0KF:%Z-*,2G\$JC::1FC,=M^W["Q#9-^,60>0=7(JH%Z,]4QQ.KI`SPO +M:N$/M_#E%C2>('".I2S9Y7V#AY`SDDL/%F#=1_9$+8:PR?91_RFA@4%,)LZ) +MMK(=PA37P,@C-I%>DB$?G9'":SNS@8#6+5VH!`_8-$%PCPI6/UH`^;"&=#:K +MV'UK"*A.\\7YWE_!)\>N$?\?JCS=0_"B@LS<9\9V\"GUQ6>I%*TJ"!7);YB" +M&2&&RAUN_V\6UI!,L0I-<&'SE^973T)(P]XJ+AC="L`;=TP++2H'CF!CHEV) +M+]@7+5.`(]]M1:40HVI$@96"&]T)!MK%R9DTB[>4MJ""%HK'1B/_'4?Q9^_I +M$VVFU8/YP-XK5+TMZO$Z9D"[J'#3EX%-?(H7X\&&$45C@7#_T,$(N'S^.=K4 +MVS"+.")B_<`&HW?+I'I.TA\S;,-)?B(VL`F+=$O! +M1CE?4"J$"N6R9&=#GX';OC7$*%&QH5@6D9^#G`Y0ZV/ +M]8_<^_]>1SI)NG,,HCJPL7ARG9ZI=;L42AD]^[K_%9^^E9GO%+$:*63WOS+- +M9?&+%M9R8AQ>*SAVKZAG)!YA9`S4C,FF-".MT[+-O2(V)V"+T]P+../'U^;:`8\ +M2;V9J\]&0C;$DTROGIJ3OA\50*7\)'.$-IA=;;F72>H`QF.-".J7\*-M0$\T +M5;'$7LD.*,HW^;D80Y`"1-NV?+^;B +MO7#3)RS3J7MR909B](ZJPMXO2,IA3T",RRCV4?XR2L2PUXD_98D]JU.XBX>B +M%&AKRANQC_*0Y`5JI<66997'"+7G[U_,#S>@_O +MW>)@KU(0EL7`*BSLDFDQ)HPO1;%AADF_"O1DRL:9G%":^3 +M]=$;M:FA['NBNLO]E:;>$NKL`SCM,F7G56[4W.5@R9J72"VAJSFE9:J/-RQ( +MJH_>YSH0H>RS5AJ=\405OMH%H^DOM!:DMDN6(9SU\3<:#L6>!AV`*1FD;CBMKRS)HMDD,T0M`1$W9!4( +M\<%HG:/@!*JMH'D"$:Y%!S],?)WQ./NJ8;HR<_N0M[^`LANT+:)?$1]&6=Q +M$9.G"D'B)6.68=:3MF2*Y\@94](F`*Q62(=X'N8DSSS%NZ_5W*RW:K*K&+*[ +M-DCC#3HA2_!B-G;Z%A))[ZBD.0'K;"J`W>D4:C-X>]NI;M4;:[//J-W?[56N +MA/VVW)XIGH'5-"JGE#4C0\<^0P.B]G,G(,/=,@L,'-F%*4#\9W+(>3HPK!E. +M8C\$V!.&+A]Y^"$GF^?_,(RF*HVSVHF[J'H8KG)LVM<60TB228GGJX>W'J1; +M>J'EQ#7$\,EU^_Y@QZKGXBF7L4W9ZP5GC"KKO`]-+XA<:O2IA^S7EJ,3$2$'31'$+[X\-`XIL,%X/.RO0<,>(+YL +MJ;946[O_KLB@O-1>94-0^C4FI$''&"H%=C?DLJ5DTK9N^*A;X^%K)]@T8Q*W +M=%_G:4K>*C@V*6C>(W-=MXHPF6>-6PFS,PQB2^TZL33<)NQXYKJVHK9'8*;7 +M5"3+"8IK#3C+"XL*:;E_XABSQ5:985\*1M@E.)4&+YSQ;EBH6>`/G.2>S9G! +M75J->V%`MXLAMB]4^F(N;#+TDUC3%VBD=D3C13-"U[/V +M_N@JRC'E\OQ]DI.I3Y=U\*,[:3[PB-'WHE>NQ)]A^5_QJFLPL;)-K&2V)!:<7%\OEJV-L[HU#X;C3(XML^B'W9\JS@&* +M^'-)I=]TIIMJ;D-*`V`)'LZU@[9`[3'XZCSYC[Q*UP0-P:-P3VXZ)6S72W+" +M'JFJAKCC"+B&_N@,,`QEX&ZD=T?O.KGS?T'1RA^UGM!.TJ.//Q#!=A;K>D%&@U/+@5?2Q\3HJ/"OU).K=@1`(?<" +M2$74Q=Z/>@-4@8)[P?ZB+R]ZO7T#N]QF@W?*=3TB6`9H`1FY`90W^P\M1$#R +M[=P"=CYNR<[N?URO5F161-%%1"RA>?;-THV9F;.]GPT381TTG>R4Y#YV7;Y^ +MW]X5E>C,,,<[_/FFA#)*8_]")R]*<%WH2.R%@,D0[)!Y=9/05M> +MZI4R(EW`=7ZDN!B41Q#K@7&8%/1_XI)HRCZR7-,T,BY +MJ-B('J2!'EMF26GT-+WBJ2P.$BV_`&NC=PV6#6;Z*5AH(ST/S@RR5=J(*OO? +MZ)SZ)K@PLJIN[`WE@.AS78#TYAZ7X:RE&"V6P@WC/??(IW=^010RG(4%4KWZ#(P4&U"Z +M7L_=(IF'DI+4'W/+H\?%#GU9&A+@K\IH9% +MR%%J)]`V2DMSF[?L%%I`3P?>Y@, +MW2MS'V*]E)Q)/F2)UAB_B +M"VC[6[VZ&S3^_!\P/'UD2ZR'L[/P(%T2(;,]8:\A?&%/>#/N@,?0$R=0/MQ' +M+_2BWN)C\MQ>><9'XP7L'J"1.$W,+\@'ZI`JH@._];'>0_.U*45FH;S`BA%/ +MNV''R_JSR)$IJ532JSIK^,7.DS<3T'UBDUX@\@I(>`EZ3?(T8:$52#^-VR+/ +ME%#8OF7D@B[,&QG7PH=)4$B+K[G(I$K+!T, +MI[?E-+/V7*(::F$G&N4'H1DX88!AW_-Q$EW84D'^YZX1VZ=*@>YEG[DB$1<& +M0%/RE5K<6^%K)9T!128;&[D678_XAI03004)A@Z,/5:^1,5:]E$C_:AV!$8N +M/.A>74L&_OGHL&OVR^R#[FW/M:OW8$V'51N@#FQZ9E0OB]NH_VO-EME=E7MU +M="2;'V5;MU="U@3JOZL,;=C'%Q]:IQ5^CO7$+.1BB=D=6*R$OT017\I0]U$5& +MA9N1;S3-D$H9=JHO'4\0DF[_\SX[_8K^#'=0?L_^`34?^412L9`/NGEYZ"8> +M\_TAV]Y'[X"LX:]C+CKU93HQ,%FPL:W9GE%.>[W01(%7U,;BU]O?L/VEY"YN8M)Q^?<1"EA_FN\7WB]Y7]A$!B8_F,#UPP +MWU"R'QKT>F20X%ANJ&MA8^&"YV^#6T&&,0V:,.&F!)6]<)-A*'REP-)QR3)* +M";KCKP$%ZBV&.B2*-;(3-RW%LX*,`)K,/M@NR#FY$Z_'W<-A:=33X@8LP?$# +M(8>:\2<0Y$W0#(J=SV;B.W^;!B'BV??YI,Y5P,,:.!7 +MHYMIQB.?C)FS(86B0%;NQ`4<0OJNTCWXPYT;',LFQ$.!@#A#<;6'$+1*!9U5 +MEF@8+;\MQD`7-%V0(KR?S($3&PVNEF,L1-UB:*)L=KNI'ABC$.LNS3\?8\!5 +MBS)N1A>!^%-V.!#TTGH`>(C=F%,FK.&4J4%6P!]OAJ#A-'GZ1 +M6%&AV?2452\9WD8YH"DQU3.N']>+3R&62O9/#/T,=7VCD>)\)>15ZG1H^5T9 +M^Z=JOG`K=@9IG,B7%@V58Y[!+DHX9LF:`?!Q5*=AZA-,B:QN&C3.-$6,Z1*O9D<\9U( +M1Z<)H[?>)(FY.`O&&9/FD(QO^JNH&>2IBTJ,A@!F86EWR3+DQ^)&$W91UK$1 +M?NBZY`6T.T0M$?&1S8EN&3R?&<,Z=#[WRRDD$^+V/3>=.-%B:!W0@7?NW)(M +M8M$Z<:>!KDF_@R/,V)=M^_6*D;(H'%C9AGM/`US-LBSP0,Z+8B^.]=3T,&`2 +MX`V())F[N7K-PCCS/2+C[?G6P]B:+<;\V.&N/YE.&P@31EZ6SJ@'68;H?ACZ +MA"2-AB_I.F\XL:V,GV +M[%RP!:21&;.*-I6(/VCD/(0MFJLA$YG&V+`%&3!*U#9"+I7_[@3]B#V)F;#> +MN:=#[VLP`9B>A%=67:Q+J'E8`YQ<7'A#A%AB6)6;9`3N%T\9X?M9]J$RAC:$ +M[Z\#")@Q>P`/RR"ZS%X6-0,F[_!HDDBISE!!2#'3B]+)>%]+?"%<:%&%EHKD +MG5Y-PQGO9P`#H8JDX"#[TX$P:J),+<>_?6?UK,:Q04LL)>@LB/0E!>E20&+B +MKVLH?+A4%,7D`MS38(64V>$4&H'AIMG6!EZL4(:%4"&+L/`P;3;^7J,A24RL +M,MIP@?-9#'EI]6,S@T"Q`NT9V;XM_#:1G;Y)@>Z$\LTSF2@N,1'UTBG@&L=; +M(^)JLSPA1P67]B)SGV`'7V4G"=!GSP3HKFF^H,.VCD05G(^WHAX.`/=*!]QC +MI=.:(,")DPB1Z6RG)'[.A4O84="7)J*82XG)2I7V$C4[Y1;AQF\[&H4]?'Y< +M*3)+X-]/-;1<]_B>!$*7<,&J2F0S4ZUW.LU%QN`9?W)'P7]W:VCSUS4#[.<0 +M3T^-Q*"]`'LOSR!HPXT)'E5]B6A(!.PET:PW"3B^ +M;)]OK-&9MLD6_4OY.YH599(54RD60=PLT+ZXF+=)/&X4(`!C1H[L6%]6BMK% +M2RI-+,!X4Y'OC9 +MY?]+`!<#KE@,<%7W+C1*GXKXJ"#@JBEF!'2L$G71I/%4*UJGXS%#1X?0JX^Y +MCW!YI+9X%!3L)@$.N&?E/>)+"WFAB<'._NNB<%%L!_J^UDBY!;7YN*C"WM_[ +M#%O_O%[%*<4KQ>8]]7L%S`QZ;+&3$F"%O^HO0H&BC0G\-7A_TMU>Q_S6B>L: +MK%B?^T%&Z`N0GIDJEA;_="RZ:64+?YRW1HAKTQ[7^D,T7-!VK8^DK-.%:[5# +MB,YFP$#+%%O!?2SO^E1K6\M-HI-F&GF;C$+8\SLSGO/-SSC]G6C!#,QIV!^2 +M))A8RSX>GK/:@@E&+C\HR$;'J)0]>X@Z6U%!;I=4M/''\ZII1/JDRI.J0X81 +MM[LS66E813.PZ63=# +MO0#FK-HW2A`[J]C(%SVJG!RH#F"(H`P-;=%T=?'PI"ZSO4M5'TT\7*H'GKC2 +M[[F^20X`V=?Z@%C@CGAB[T,PQP( +M.U"!+$1%&&]:1KN`FP7`B&S8[$'M>+X#QTX<:3?3)9Z,6%'QJ@:7@/>JJ)-E +M"K3$DT>:WPT:`V6O"9?B97L+&P($].%7=G%0\G21AP.&#KA=7"QC:4BG'QL( +MW-%J6E$S_-9G"0EV2#;6R0:ESD9KVT#2YP3WEB#0QDV`@->8#1AE$&+FDW2: +M/`S6T6A?Z&(_Z<"U7!EF*H2J./[E/H,(JLZ)`<)< +MZ++9$7>3V:\.."?=.T[-%63PM`:>^O&Q^$-9>UN[.[K#250`=/T#@"&ZR.#Y +M`HW^A6]`&E#0#8L,[D9\M6IEX&&!V0M9R:BA,6GMXW)K*3HSL&2"Y>5F=G0< +M(QTQ4&2C3,\8'2R$IGGO,"?8F^A([T@N'+9_R`P\/$_1>.$EZBQ+SXO6LK_G4>?8]G +MCFW1+>-T.,@U$)Y-P-)7KS`,Z=(6J]TS.]80!IE(=,[^M-DS3TI#$<#Y!ZWZ +MD(4E:%A0KD5XZ"RPW_FB^Z`3NK+NGLAN*QWV$,;2YL6>I?0/6@Z=#SH6^Q$7 +M-RBHG;YKF]KRDNQ![SDBXP(C^'2:9-7U9ITV3??`%L[_IF-P%"$(^ZV1]$&J +MU.QO:N@;Y!RA@LK/VR1[7-EOV0[8<-:]89N**AL-/(S+_]X5) +M>XR$;G#)W9Z]#',*/6R5P??BKC^8/!3[80^\=9`PW1DYMA[5>9,>]7QB[EAG +M%[I))_LU]^;(N^ETTAXTI!%9)[-VRP>-!5+>`R%.Y<@[&S%R8H69:P8C!@5D +MXC9B(5;H*+58>@UFFG-M?VI3'7IG56K\]$G$/K(4)T +M*O`NR9V)05#4`DT]SJ;#8^/JK3LTWPD0-A^I28WW`,Z^!K(UC,*(JH:S2]8> +M*U:!K;%C57?_0Q9SHRV]7&'/C>PE^BQ0=E0S%F'/C:5.9T29,'6UE#V[R\ND6?N?+_]>./W +MVZM9Z,4Q\_^0@.J;#2V^^NK#L5Z,)`;;GN5&JY*3?;$4GW]Y';,M'F'/^,:; +M]TK(G:,JZZV-\"ZJQYH:[HR3J0M?O$3-D"5:B`RNC&]DV_QX +M:#%W*>8>C:P@GP2/CWK/1IV",XZDS<3-8`,`/JR)8%?+[PHV\/N/R#6`V6`S +MIX6F`J^"UCU?\@:;'4@)F8-I(+R\5('=FO90=+K%]$M(W!,,5#'WDK(>`JSC +M`2-2B'(Y^EE&6PPHTM0RL'\IGH9WEDDYT8_GL#;H+V>75Y)]["_IN.WEF'Z0 +MR;8I^`.&&0L<^5/8)[S=LP:"VV]_:!=1X-5>>M#8:JB,\%CV%G^=B/PGG$#T=Z( +M_KXO$+_D" +M3?]T"/TF:Y.&N*SPGJK\[14"/0'@DU%4F+LH%JWE.HMJW#.,$!I)MZIFF3-J +MT?VI.V9-9FJ[:(Y(-)FSQM;(^27I?.N43P&D@4;=5,GBP(6A%43E0ZC.7LH? +ML\"(VDP^X`BU=;:+;O_4BVM]V\6X/O,C*(=&<=^<+68:HTTAS+)@`64V'O6C +M1'%S&EDR^53A7#_I8PW=`B_@D.$9V93DF?)+)\6QIV::VA;T9%R7(0=&UGRP +M:EYT&ND=7P044L3PXT)[*'3[QM]4[A&0T5W`U4CH`/K=6637QE#1:C@;^W? +M8,GDY!`FE.`YAZ!GJ2S74/&Z:UL-3(G=L;+NRC\H3)M"\!WKIB9%7MF[ZTQND/%LM9G +M;17`?DA3M%9N@O'P0K&KSR:'Z(9MH&E$ZE*N1"%$S2O6>B>T2+/F9P&M(M3# +M"J\$2[%IRV!:*7;60#1$6U#25$]G1G&T0T!V;B2HS5%A'8X;2:Q0&"0 +M23.4<4C^(L:$*_)R#L#7!44H]^?E#=_5C00\OAIJ>F:!LK)F`X_2W9Y3MI2V +MHM\7SL&RP$L'8-62ZC;8?-0LXN]8>1P%!%"O_1WS)M5!P^?^A(Q;#2BRM]LF#"T0+N7=R1^+GIV= +MAQ8(OB)D05]DQ1LDYC@,Y"HV_47P*=XO1[DR>-B78:+3\Q]ULLT,X84QNU!" +MJ62);%EPX#.QY8NW_61KZ:8V)I0BJ3F1MU)1?4-J;-1>+`\^/WJWO#0HS<7" +MFD.&>-E2KM1V35,-^L5=4:$0U`BX:=F3L+^S7QN[.RV`A681L9T+N#IMK5WM +MHI=46[GU(NZ647"P]N9TNR675-NLRM]:&78T->'J333H:4\,VV:MS]53`,65 +MQNVYL.?`PAU?J%3FBC%7H(=9OBL0K"*Y;)!L"6F(#.EF"RO0VK/.2]4#/(-:%E`$N?D#:`C>EDID"8W`,8DNMHI'O\AI"'5=WA\H +MVF;:_@B?BIZ*[<4M"V)A[O\2<^,.?9],9`ZX9]VQ\RYB]$9#('I2+2_CW;'R^U"C!*:=?!KVY +MBX*^%7PR?=8SG-EME=,719O9:N3#_[%_VX$[QMED=<-"3:FK06=FY55Z*]U; +M/#3-<759K@[+5*,6#>(5M,SIP(2"'FY@;4X;0`KK'[;VJ1T>;6][6+:]-9!W +M&Q("66Z"A5O-+P@AD] +M'KI&3K%;..#@*@.@=[@OFV[/)[766T$2_@M,)J;P+(NFV`K69W`9[5\7IA4: +M^%8I$/P]V.3T;&HZ#CQ63BRJ0#;;72*+)6[:!KIB^(\Q&-)[+\U2X"G;M:$, +MTNDQVRT6=6](`%B9V7"P6(5K3D!E\`-D`SB^U*M&X#OD-"(XNC9E,Z$/BH[I +M8D^J^-H,Y]6QH-K4A#H,2H=!0<(GQK\K".W(39O093[V?T"M-VSLE#H(Y?9` +MP'*+(;G7OZ[4#79W]E\(_Y@_C"D]<,>87XE[7X%R^.+K*7TDN))*8M*L'H;T +M:2Z0V^`'*N?UK*-H[YKI@OU?=4B9J6E>C84B_&"UR*$+]L7\5]L#T/Z*5#)' +MU%&7+[5HL@;@],&F_B1B`SOO=+ODF2HBC84,&@X0M5G(SO`"7F1]C&GKB%)> +M`2D!?JP#J/X&/1[O8:6O?'&9Q8,Z8[P +M5[3K'GH>CG+.@DELA3!*C0:Y_E%33M[79R*E.UXA-!?T+)S`!3-'1QT-V1S` +MN``V@&Q]-GJPG4["(]@#/5\$[1MX2:73+NJ;T>;B%_^3[6AZ,[.AQ#&@\8N4 +M:D\;MIB5/!HT'0W9GETZFUB(6/&45'.D6==Z%UCNORV_Q<^T8K!#34,&3MGB +M#',8ZJ\]$-1GEDG.(-]R2H +MTS)(9XH1)="G=R2B[52LK%KOJSQ%*!8(=`ZE<`]6B!F\1I-\=4"8;$RHR0OU$Z^U::0SW&B8A%S`'J8ZDDTUHVB%B(PV@( +M*V=;?A]P3U]9VXG/*6N)NW\O#_2OH5^EEM"S_T6)/]>,;<_XL+& +M-L5\7#8K_[Q#C[97L_]PQ+TLN1AM)6V`1LU2\FE&EMAM*O]C9FAKUC19X8^6 +MG:3LMLY4+/E(]BH%8K3A6++XI7@Y=7XO`WRN[Z--F/"_:KMA*Z82O!Y9CMJE +M=/_0V7+*[82NG_HCJ-\*OQ.OWTGN_[>]U/*[Y/^BB_^I;+B>W*_$P\KMJV>) +M>6JM&=AV+H;(J1%IL/Q3Z8DY`Y'8=5,=VK.XF55,L\"UB?K)X-AVJVL^ISY? +M]D+??5\*IG6?,AP8N;V-J,P>)(_U")/(:PP=R29\OP?W&-R(KU>/%5F7-&3* +M$6!'L/3,0NAN.Q&ZZ..J]'"W.)3.#*C"@,OB1H_HQ=[)[IE)=EDH&Q8=GP`5 +MJ,\9YH5&?ZO42)V(/*= +MU.$B.=KM(M*L(::CT-2$,#>A+SXT<;K&\,/]S!X>-AH]@SY*CH*23%`^@YV1 +MX1,VBJ"!]"\J*_>2.>6[%,](H'00Q$?H@_K4_WA)EBUY7YV-^9@IG3/$U'$' +M5[/%E->%"AB.SQI)@)K,O_1D>F>-=IY%VIG,9S-XF.-/L]W-)J$V,AAX*F#] +M"D]9G[Y-3Y'.C.9!]&+ZRV>%RW7$)4N'K/9,8Q!89K/(&=CX8.>:XPZ*@+A\ +MHG.?'[G\N^!N%>3PZWJEIOX2(>2WIR0CJDO)UWU(Q0.%TLX!; +M1,(R.VYCSGX:X7UL:9!&%YL<=*%%P?TM=MK9QF]L@D;IVG_"=0-["M>BX64M +M0_,4P*@$$[X3.>7QS]@&U(T'PB[C/JV7%;+BV8V4B.!Y8[?7'@Z(:#@[D-I4O;FYX.5>2-6[!6]B0(S[1]6 +M1NWI$#8F/[27$RT8GF!6,G,CR?#W]1&RV'>'20%-CQLR8PZ\KM(^-&8+2/4A +MPH_:*4`=F?>C(M1JS]J:>N(CUY!C90ZIEG?]4EHM";6X!E%K/C]@M6F>EMB= +M#/W+;$3,L,ML+VR4X.4ERIB(4X4D,O;FL;U'F,,N]K>3UWT/5FG.BQ#=L +M%3I\T)\=(%+IXY?C4!DX[=1M82#141/.F/?,W)K%>O#%=%UDE#MYI60H4:N,>;0XTKP:7UET4&J8Z3,XDO"W:5\U'],(O076[^'$<7=-P1GZAE4F;%XA#!C0K#PZ9"'W +MP#2,ETF0EK%8:S%)336KA!&IAQ]+K1QD9]8S(H`'L0)!"-UY5!!I;9634 +MEN_';*&BEMD;4F=HJC5'\`ZUF?1B^3SWU&]WM:"\QN>U_/Z[;6@O.P2;0]%P +MT^"E"I)A)6IA']C(YXQ?/"G<^9Z@;7$;X3+";'G)=# +MJ_:@!7VZ.,$DST1QP]%"1XA-V]#N;1U#.GQ>4DVNUG$R+L-^0GE&%$W)^OM0 +MK>QP2B^O5RG6M@#EPCJ5\/N^Q!X5<4E\476^YI@+I#?L'%Z.RC\Z?9TV0`\- +M-89M8:Y#05,J'37(+853!7OI(.]@25"TZ;9;SR`AB7O=YXU'"J8-%J"?JQ/Q +MJH%AM7=\%(7,B85[FMMAJ;4(XVM[V(O#5`^[,GQ6PSV(3VU&J1I&D#@EF;CJ +MI3<#0#L +M!`^RZUFF&^H0]-L>G,TN?V\F6;IB_'68LLX8?#"E72?A.1?4%0UC.W"F&>SX +M-ROLP/1D:8_=\%ELM`3V)3D,3&+.L'Y:=?\OTU9AKW.,B![$]@JC22=8(6$@,*,$I +MLL(JS^&?P/>`-!MMQJBCL<1TPK:RL8!PI]?9N8'5$B;FS^'9XRW!4O +MH"[WH;\`=P/P*N24B6Q$_UYIL88=ASUA/(9(_)&)Z&&58XFI9$4_B<=-`UYD +MJ1'MJ,&RI[!)7#_UT7T,#7`=TO;=LP.H$YB#A8^#&NL#\D3:&/=W_C6TRYFC +M8F'!(V?8XPT%?<::6\=3-JO\2G)KCL*?G#-W>FCF6>IC?0XBNX)L&#8_P.\':LV45CE_RB]+WG(1O\7%RKU>7\7!_Z0L_QIFO5_C[%7, +M?NSF6H^"KIOJ]"N[7M[NKHWBNG;K[)>P7T2^77QZ +M\)?!KTJ]`NLOP)Y71:JZ;->Q7UB^?7RROIQ\]KN.[X0;A`9:!U3V'OZ<7(VL +M;M&P?(SH!F0*37?W6I?_1$!ES=-_PUG/219Z-UV=<;\4XO4N!R':_0I8DF.1 +M(K\.\Z?<@8?YIV^4CM;<$,BZJR0]XM2>)`POO)8,6?,GY2C96)E_,8'>R7PJ +MF!^51!_,OO?SKY?]"\3S5ZG:+O/U+VBG662C4^>O2^@OHK->VVR]#Z*\)3P% +MYW;J->IVB^[7N%[9=^%(53#L5\>SRMQZC(**/*$"N?J33?XD;V'8[@5;6R/U +M$[.+F8B1/4?>:-H6+T,'%4\-K,.G=.A2A\>I`1>,0[@8<5A]`T=RXG%6'[YE +MOBK;!O-F'3YZ<<9:/6@^T9+M4],-SA`) +M]UA9)R/7S.@HE"XS@&R=#D@PY)RZW91]^SWXN:F6IPA9^1\+/Z.DS`VV^N:9 +MP+1T4-H?G3RC\`"P!*=& +MT/S-^.^"=L_BJEZ`DQW8_GD#IW$I#:*\DPS;/?;#B=N-;X]8S1,BH"<[P=0L +M\#DC3U#^)=4PXS$>8L+!Q[AW\9/R,8O%9>L()CG/"W'N`3I\\-YG<$FFBG4N +M0JN#MN,H-)$'AN<=.4V=A/M=,'R\,1N\!EXLSL+DGQKCP[ROUS.E^"9W?(]SYXJM`-J4T[P>W`S`;/$^HN6 +M"8.W:L!,B4[-PVI?LN97K>*I.SN%LP&JL[&2E-!./DM5UZ*@FG[4W@!(-=_= +M[BEG&=;(( +M0"*?]&EK4/ARI!UNY!HCN]A.N><,VI<_9_)-KV0LM0&[D;L8 +M;!9:6=1BSFDE2QJ=N0(9Y=L[[D1Z?NQFZO-;[JG;$9\PTH7UN72F+P0VO)/< +M-GI8$-#5M"*LOC"/T3"ZBIV]?]!M)'/0*D','*QG4'91#V-2V0B`%"BTX+VI +M`7.1'#\OEF=4DQ=M<_9AT(Z'%)HZ+H7C:!)=NKQ?7.*JK`6J%EU7#.QP!?K. +MQ/F2X4*,.5*>4X3MH9,%M.=13;;R6VNU0L>H-OP;W3RS.KICS#*NTR,).UDLXNY7QRZ'IPI +MR`3!S.20%&UD.+(>.7ZX +M_%G03+]:9N57?JS**7R0R!\`A'!IG1H.UY@TN6DKQ5NUW*[DD:989I=XN;6. +M&&I,OEEYLQ;\\B22&KTX@4)5"1"[+J?XHNLT$RZD<,\\EY?VE(*:^1^)K'3! +MTMSCA0EZR>S=L5+.P82U(PU]8^YNK[E+\K5>>8!%N#VGPZYBO&EH/(P]R1O1 +M6#WF>HT_!Z9XZ)7[GHPZ5(=!62TUA"C&LQ6M.26A,]SR+W8H:2UE[9JQ9^@( +M:_01(\B.G+\41[SZ:UZ9?M4$_$>LCRC1V;YQ`#H,<&3JN/_79I;P6C?(SVQK +M;@H2:='CRK/=]CJ!A8[?@?WSX^$LL/&Y1;%CMU2Q;JO!/5"`T9"`,-.=^YFC +M=E0SPX>(Z;=SLG3!`A=*3GKH_P!B!_"(*%TZX^RQ,@$<>=[J?@H16W$K/X*S +M@..(^],FUP`R(TF29FT.%&?<;_!3NZ2&UH+IMAYU]E8R=+\DNP9!(M;*'BN@ +M.2>Q::I1T>BO,UP!S/Z\81[[]Z:G*`'+Y>25+6K9U+($#,.S[`H.1!;=71GE +M57!R:/,M2LZS@YU9F')7=783SRKULQ-5>19L:MD'V;9!=A%RS:?%:L,,FF+% +M&%H[N&=/M"HSI_^_?0'Q2;$%-M4_?,+["+LDS&G%]S5W-AQICP9DX_[$Q>Q3 +M/SFS^%L@<$SH$F3K_U]]RYHRN+TI27-L>.%!D=H"K:=?"=`@X0Q8,1D"!!!V +MJ\'"J1][U*QQ$DHZQ=\N.[#.!.1';(="HSLU?O,-B9,HP,,.0SJY/V#V'$CZ +MTQ[I\!YU!SL2`I2I7W#.QL3[*W![Q*+BG8)P+&3)HD7)TV2\_*-`(?2JUGD. +M;`374,!!V;1T]Q#AI/?+(@6*3.SC^"AL-D>K^U6`JX3?+6..!`_0%*)VQT,0 +MVMG(!/@N)@ZV/ZRE*`WF$Y9,L/:-%-8D5<&*(>-?=O)3?)MA\VU3-+,V#3JR +M6!685A^)--A3&+37@UK.-(Q'?7)N'1\($ZX_C$]*R2>81P)UA%0T'>,I@H^N +M>UT.-V,PC=&>9C[33;'R\\(>D=.HBQ=\K5MLWDX>-`T=O,S=&?T>>F9ZS +MF^AA1MSP;IKG);GLQT'"<&>]',-3"6]E=)>@+H:"Y$&'N +M*`?O#-==XW[]3<[GHLB/[I=))(?28)IJ<^JRK[L"IRBKWLUPNVS&S`#,? +MNX/-9CTN%@)39I#H-J.C^:6S[`,@C-KV).V +M?"EUQ[Q8=*2<3Q;\P+6`[DT7VTR)Q&=&>IP&$,P'V-#?++3WA16T(MFGQ39L +M?<#.WARVSH_UA!8F*62R!$"T8>&8!C#;1V&R7=D@3%G"RB*O;FDS'D`@TYDS +ML/P`&%(>ZTN<69X$]Z*V!!G3RN"P@X9/-&&\1X6P!Q%G(83"L,`,LV!I6"F> +M6/)2)E'2'9CO10'0>210"$0?*C-.KTPW#V!82<.0<,RM9++Y!SC($?J3(0%6CNPF2$DL#4R!V\8V +M9_>.W+"X8L*<<*9$I5Y/R:;X7U+.2$-LB3OC\!F20CP_P+@_`AG7X#D"CHPS +M(8BA%Y^0@MM%)QZ'49DH)MZ@`99M`[YI;,Y-M,<"/KT9]G6_;Y="5VUF9%C* +M9X^`&:?YJ,.>2^@)#\^.YLA^-:.,NGF_U!7DN;.H +M7@5JF*#P(V)X<:86[16FORH9EIP2\9_0O)'Y)G\JBOS$SPIIA2+Q2G(]GL^% +M7Z!0D]D?L"'=.YUW!F>YY@3/L9WA+?8KN"E"Y`'-8<9CAP#SSK:BWB=RVB)Q +MYT5/\/W/8P<,%Y51\RZ^L7.>=>2.U&3/0S1:ALO%&@UU5):ULVI.>!KJF7B#S?V!RS/:1D33JB6BQ+& +MC;HQ8;*%%/=NLRBG[ZOMIT(2\FQY'=INM>$_)M(5&["`"BM4M?ZS?.S)K;6L +MB*@[2$I`W8FT3;2GM4G<'8LE"3/Z,+NRT\B:)4@8-0Z"WN1*:F0U^CV>-UDLG7J=`U5TF,1EY!4HQL.B7/(>?#A+K8 +MH;_:!MZ%3M;^LTR"];L6DM8YQI-LW$:_!8<0.&S,&Y".*!1QL@A:5'CK]J`. +M?KLMLK8N;1[V*G12&[ZEAVSLA+I?`75VD00P[$GIT>."Y!0+2A`C%B>NH\<( +M3D6:--\^UR.LQCW%!"K9'BC\ZUK%68:=;MLW%FQP^Q,-7@Y-CXJ9;CS% +ME&CI`R'&&YD:"!\;94 +M08M5LU:60SRKSV`+G<,TU,\?\G(FF3C$GK>SN"/M^_\1+L3C3EUES!IDQW)) +ME@@XA@`XV'X$'6QOA9WL#A+KN39G&WYY530GCX:X(T/9G1S.X*?I%B6G\;5*#>+GPJ6\4G7T,U +MKHXDL\-5BA]A>J;1G7E:M,=')*4R'6S@]CBS;@%GB(JAM4OR-C4'AV^-O)?5 +M.!'3LL]AUHZ@A,#AK)BEA1H/7\H\$JE#G/[K#5TCFVG_5##$RCJR/1!48,H9 +MW[D,\PM=%F7N`"B:ZV +M0.SR.-3,N1ZC9ZYI(\OWF..22PFMN48;]%C2^G`=G&7IAN\U^Q..@0DNC)*" +MC[>+O%YU>=70C(0#\HDK=9P,Q$9XSUR8LJXE,0U=&*#/J9O=>O6>',*GW6W@ +MXVMO;7/<>)P:`5#U'<7`R)MUP71^^H&13Q\QD>%OFLEPK^]P[@IPV6\)&[$] +M"J"P%\2U/B(R\>?685JIEF!#<;9AVFY\+C%EHL+,0W(9EPS:;=6K/9,%1`)? +M75K(YA4TJD?>1[A@YKN.VX3>5$SO8?-.DA+[JZ.A/:'G"Y*6RA3 +MRL0+7T7)\+[-]N?UWR19?1F1CY&LA>GLG;:8S&F4A@4@.I";++I2SV +M8YKA>EW#*-#F3LBF$H(JX)LX7%270IG/*2E9=+@WA17Q;3<9254KCKU;)T;8 +M[EID<'ST=MD!SH;]P8.AL>$;H4/V!6$XT7AD@!&G,1P-/U#(,R\E8)]K\K,< +MEU29,=CMR,]3%]WU=%& +M*D'5E,GKHEK&O/0QIQI[([AZ@6^@QGR<5(/2K"]X,@N3LDY(?**;56 +M/K'DHQ1$U.>%PEIREX0T`X>W7,?RX)M+ONYV?"ZC[%CPNI[,>3/V.:X1=4-U +M`%)X\T%%2C(Z8T,/A4H5Q@X4D<6.D%&]*^T-Z>LNYB#-6B.R/>01$,^^430`RT?W +M6)@YF,Z?::+0)H1A)^T9C7YTMR8_OE.RY<=.SZV^'6GG#_<[TU8U^";D6^&(Z@?7/^8O6E)*V#P.Y)VLB6[L?>LGZ2)*F%,]:25) +M>YG.8.DB.H7WF-7&%:DTAC_"RX*7G)%G""U=\:T[@J*8%_05CWO8:%#Z#R4: +M"+E;"2/:=$$%LD^H"!M+V3,X)N3,KB7'PJ*@[_D-2PH=:U]!_D@9 +MTCD01B[.Q(&DS43-!UP4Z6S;F>2FK`]E2BB&@B&F6JK9RPI2'3)3BW9$)K4< +MNAUMH'9^QC.O8=:8'^*YO>M&JE%OHM?,3H>CC[=BH72C2V=)$P1I`!62D(G:_(1#;B89XOW-P$EP8#8''24Q0T!VX'8A=RR>G4O3C]K4M@)PNBO-Q4]V%A/38\<# +M]WR;)L8=)-U_<1,4"J-,-75FWVBB/;FD'/:V)>'9L&]IO8;UDSPP+U*T6+9Y +M,`:F/V[!/BXEX<0+.@#),.I)8&951#(S10!0=[Z%T6)6V[!`XF0D=#`8@:06 +M@&V8,<+&=;:;$`ALZ9C74`H($FN@Z'',Q`@8,!R)@-P9"01&YS'S,?.8ICMZWU77\I55[NJ^W6_=U7WOOV]_5>JVKN_%?BOQ? +MQ0[^#BLLB[D,^R!\F0()UK9IB-0U,K31`G>;[K/3O9^2F?K-58>FE"].,F9N +M"8MYQX,W'X5"#.1=['E-\R$KIVSEEEX_2`,V(PVPH7P3.QFZ!E,GS5*1P,!\ +MI;CU14)RT\PBNYPR9*AL!];QXPQ6V)R5N3+!NJF92G26%HRZJ0I1I)OJ".Z/ +MG*!.>*#9@3Y]3/$+<]K(B7W'(9QYP9E)VG7?E49UAMSVTB*5.+7H7J.B.'JR +MLS%XAM*8L;3ZE%M.!0&&78R80TAYF/OJ8A8ACH(ZR_3")E^)H#($?#-<('H@ +MQ_QYSQH\$0-VS:QDS+1+_3*C*'AG<8L=WNG].]S;2:4`9Y9DB7<).E+Q9BX5+U,@8*A!XCBQ7M:HX +MOZ(;,@%B^`-Q2P3E@I;R"S(IT?_PD*-@J(+0^]J +M)2B5C7:WJ#2=7E4L-E&4L(1&/MBO)XI:X%N&(O"F$Y7^!>7DUVFY%[D2I!C; +MN`9G(<3>2)]H=#A>28M;@"+I/,P701G'X'S\5Q22SYM.FX*6N^N^?&]!-_8M +M=Z+]YQ+M)XOTWWA'#D@4@1.=L`4P%XCJ,;B;6SFG!4)PX)#7OZA1N^GG7-M& +MMDC1Z[!"FIQAI3@T>:;TG&'8DFG&0J3BCWKYT%IC?^H8(;"7=OGA$1`$],7M +MY?W_ZJ=>I$#I[WM#!+4%U%H1H=S<=/;@%GFO! +M'G6EK_[LN-I.KSU+[UDWZSFGS^!EQIOJXAMG$7O>&]I[`VUV86K`Q< +M%%(OKK5POMYB!J/ABW9LL2DRPJ,C-72"_\D#,HS:\,!"C6O-]A'*06E[\6F- +MY>FY:!=J+XKR#AWE+L5\3BYU,0-Y]J1;&XK=,M832^HBNH];QPR6Y/6&>=6, +M#8UB07Z4U*WUI*4PKPQ1+^VG_0P$I?#6QSCFO7O9I7C>*[E]A2G*!$*-@O.L +M_'E4^[FF'6`N"&PC<#:7?(BK#$!SEBR2H,&(K@&M&,Q$EY(A*_KXDVKY$@L) +MSX82OJPU?=\6;5\D)5A*YAJS#;2(&594`/@+4MX3U/NI&)B\J]Q`Q;7`5E.\ +M4S5@K@UD/VM#S6^\5S[KQ"D)@X&U5^*E7O2%HG5_%T=[*#/@OMYBH.N1![@M +M?$GW;I7I,XCV"V6JU]$*^Q9PU*P+?&!K(6MDP'!F[E,!@,AT@!-+`'ON1926 +MW=.G&1.ZUWZ(@Y\G=/?^4+A']Q.8B:N-_$"8L%`@&F,.*&0CWA(\IUUQDB?`Q0EFV@ZA[IRESMSOX\U3\".S&6X9[O-7V#UG!&IL5/,33]J6" +ME4RU"8TG",@-WN6%B#K\]),T]'6<$@&-J1Y<;"+-DBGJC+YCC%ICX+B).%$A +MF[`<)TXV&8G<-@"Q7R:1]>D?>8%OQTDG];*?19A@X^CY$S,19T*NO +MV.:OAGIOM+N470JYO4B`WOK2:TT_K(&`R>7G+(H$HUO*,%*L4MU#22286U6N +M8H3[S%P(;,F++`D5$`G]=[.1UKNHW]P-^_.MC!NSLZ6=(BA+;:Q0,"\.09NZ +MX,<#,Y,B":I:ZZ==)^K>X9X1*#1!*,&28R9MY&!Q$6P1;9G#)ADKUY:S9D3W +MRTNZ>,\X,=:%QF4%I=;QOXNBFR")\9#?U1KM@*39KP>=J:-\,Y57/7*D5LW2#@,-%A'H8^B!1Q[R#%UZ*A>O"Z`;"@'P#@W@ +M282R[2E/#%],R2LVU6"4H;WMXA-I1RKF=^S>[5E3+\ZR<#Z$U@4_UK!QI'%H +MW_>9/'FD]1_M4NJ!CIJ[V[K4'N+-@ZC',BDWT!A?$LX^*8?%J:M`ZO&`J"2_ +M.;]$NG/>`?/5"^S8C0K\1=U^9%]MD88X5]3N^IC+`NI*-\]B^OS1HOHY5R_R +M4%[=]B::)KDP;6*&>RBJB70U8]_0,DL2!(5QQ?JH("GS\U]K("7B,8S.L635 +MZ`DF5\`"=]+3!#OM,-YP6Y>J.F!W]4(J2BSDBC#^)71X;\7+P6Y>;EB$99ER +M*G)^:3S`LV&+A=#.T.=Y'AJJ5_(C&]&M&-*C8PN%MOP9"*5HIX,-)#W/A^T; +MIHL-N>!(G1>U)BUPUZ-CR3I:PZ^!(>J"/7K0(H>E#DP\/H<8RA!9-YUP_T*E +M18:#,V'!$%7#'H'PB"B>PF9D[UB@'$ZAR%K,8'>Q)-&]/)4%6+4O>4 +M,3@6.%WG']HS&+;S$#6QCHSC>>"J.N&EBF2/\;:Q]ZRXA-D*-V"Y5>:0)D +MN(2?W>2)J+5GA6`RFT=]!(IQ>Z3=]EA(2]MMI+_EB3>`YL':F$@`-MIG,'5Y +MEM>Q7NY7NC;\I5`]BO8\@X%T_*XFY=I!9,ICT.%;1E@1^$EGW'$EC3A5U,>% +M'`[@VY*!)IF>8P?U??]YT-$BG*C8@HE[/#> +M(FC3W7R!5;?&4#9(3Q":^U826>;O3M*P[%510YB\^RX:Y\O3=#!A)HV-8T=D +MFODO;AQKHFP;HA;6XHY7#17U?M4,C&)$P=X,6!''$8!EDHTWZ"L:V.]I=C.1 +M$VO'8ZA33#L)^/^T7!4JOL[3\&."?_SWO\0SI@C3N0S^WF3_WF?&]15-`VTW +M/MQ&X3?K:EC>Y]*FU*L4CW>@IE;];NG>$9Y/\D`.=M=J&""-;O^20GE]U+>= +M^[R?\LP\7'88Y-"8"G_07?,&2T0GQQV6:,F42D7@2`SZP;A9QG[7Y[W.)QD1 +M)HR3V/:QMU&D=]$_9[/SGVF*&&_[ZZ_G]D)5;RZG^1>]3Z9K\AHLP^8^OJ(Z +M\ON&?4R(%1=@=?!N38`]/L0&C>*=7=]9$N+8L^\@1/3WL#!6."JS`HPY,X6N +M3(KP:3DYA[S-VT^YEI)U;4R>."&I2#1\?VL/EIZ._0[SNKR;EQ7.*NNBW&75 +M)B*188(:]49UL=*I%'79U?1Z*Z+(OL>T*JCVGF_.DO%6$I@ +M\S3',O,8JL@@WF(>PMQAF$%<),ME"P@,N@UZLH0D6[D\HNZR^%/^B'V:TY$* +M,$<>EV6W.'_D$(#+VA-R]`&\1P_OM[1LID6;C_BW4MG>2CC[K[\"P"N8-SL9?K!:ZW:(I2-*(@!'R\M2WO2\%WME4&4[)%R,O1U +MD<:Y67H^9%LPU&?H=!D,2B5(D*^YJ[PUH_C9?M2%=(UQ)?3O5C!:XGG4HQFO!\[93CR5)L&(Z0'7BMS!'6>7679KY$?G-%.#,B06A1JS.F3$ +ML:+`=1=`7GP)!#W]]4CJ"9"KC@-V)ZM%\*6)#33FFI0QZZG3G62&;[QKM)&; +M".-(W2B_RZH7\Q#C+7>1X48"2GDB*)LX+&-6RW%'*I^]>ZT6U,:O9Y1=\^W8"K5.O,UF"=W/]D@HVR@ +M83X"Z!J58DVQ115B(I6A6<(Q-GV:-L@(],V(UI0DLU1O,1?%-<+S+8M?L]G- +MI1+IKSW^AT>,AB!>M/VB:''8J6"DF(W`XVLEIY/X!YSF_/O0(X-2C*J.]=32 +MFV1KOL&%WA4`^;R+W&6ZYJF?/T7-!,K=^P]D.I-M@+S##,?<.WTM<`3NGATW-9M.4/;P7DXXE.3&_$Q1C@*1,?=*QD7B9/R['UBDJ/OELL:^;IGV9\ANA9F?MP +MQ7%7MMF['`3@PSM+]=.6@/K<00B.K.A[/KG%@A4YFG]SW\CY\#Z8S.&_''"! +MC[FA7A[G`7O_Q-%`WHK.$"=3J4\>U"@#="WB-<0F+DM9TKT8L&UO._^ZZ8PP +M/?^:%$2P^P++R24(Q`T4A)WIN=AL-!PTP;N1#:3%:PV*))Q>"QGR6FNV?7,X +M,>;O[E+<%J)^F%H&Z&Z'2-8&G`;,%Q@R_! +MA`MZ(:`H&%442&)#2L]2%-/B!KZ+O@`8@4,3#9FC*]&=,^^%`E6VS7^F77K*R*=#`3*$CC>01YA],748IDJ&M76AY#7I2PV +MNCY>3PZ5GB6JO&95>3RD'`"P!N/@AE[U<1_(AYWA^T:\X"[LXPX%[/ZS*+-L +M>&:ADDS-A/(]*?>7L_ZB;V*N%*ZX-4Z&&^7&7P!Z,;\IURPD)"@<3G0K@H*: +MD:O=@E#[""Z*:'$@IEES0F@5?0S)QBE\BW%D,,Y"O=OTW8JYN(X0%0#*'B#C +MLGWU]/@:&Z@@9LPT7J;S%8]DW$(8#%2'XUY2I9G@/TTVC6%.YO(0)=R#@VP4 +MQ.,'WPT1*+N>:8Y(0X[*^XM[&&AH)O&IY,\?YL\@&BNP=-%K#D/@`:HZ]\A/ +M:-YN[U-&$3?X`]B#">?,5U$70I_JF`F7::U2G+THT,6*)HY@ +MK:3H8"8[YX&7E8?1`O3%\ZOL0QAT\&1%%!#1"*\\@T_QCX,_\=,7W[G:%Z(Z# +M)0A1]D3&=MHZ-_5TLRMC'7VE/!YQ6:Q;K$WLH5S=Z0,?IY$DRAR@/S_/H8X; +MYB]E%//93ZL%3093.+,&5@QL`+6"'X>=?A'IF+67) +MYG8K79$+FC<4%>D$!^)H-SX?P2HG[R,R&^&I?-X3&'[+['/$<`JETNDP:1R= +M.IAO/B!CV.=$TFA;]'7-X"3?VJ3,5)K&38__`R^@Y@S8G[T#B%?*308C]0+LPXF +MZE\C=A6X5C0W2%UQ;W/_6!2.1K881%6H(#'077'O>^F&XQ9_U!=C%%EB':Z, +M4`<&:%,_;,*#+5AL;S'W(09''_AR$OE&O0Q(Z]:59.].+ +M4&0/<9O+F4MJ+,M'X0E%I-UZIR)"0$4BHT2IU0K@QQ\^2W1+X:A%B4AT$1]2 +MQ[8*5-_M_G\A;X;V[ADM_-0<6C,Z;>1P"1I&\&X[4'@#>:/='M*CIOU&I&E5 +M?TP--'2VB./Q/`.M+!WO44:!;(6?0-V[>E;&L6R?L4ZJM44__ +MYO35E_]`)S_I*]F,W#J^V*CV+1N@PF&^XI1SNR`I-JYMR>XY9\L?!L'4]4*!M>\(O0V$7O +MG;-U/6^M&,=U:,"3#D(L*<&H6?*D[:4^9H%]R=Y%[WV/^RE)LVR\\_Y3#[%[ +MM2__P7NG494I=+H)LR^=BFQ#4G`="598LABGV&+^$TJ?/+/I1/J.#U$P\0>8 +MT=Y9Q?RWH]O!@9!UM&Q:=F9R/VL#PC"`?']B6QH\NU$+\T()6AW')T9(&>:9 +M=0?,&)E-D2WC2//SGGW>&3AQW&X911F[.R36W?HG+7>Y/!=3?VE0X#C<<*Y< +MO+8H["7BE9FEK11PK'"/04OVA0K,M+3N3)X$9JKS=.F+H08Q'">\&(!7#.HY +M=,]\'DPQ="8Y.V&]CO&-Y_0"DBY^RNPP!8F2VQ?0Q7)0\337G8O!$^">)PH\RV1]^.*FD517ZY +M\9E3^2#?Y8C!*8A5Y9&AO8O*(RG>V4HX>F!>"(?XCBD@H0%B3-#%P7(#?X2/ +M.]/F%BQ_YA`&JXT>-!`QUG0Z/X`1!YV<+D#K,MV\/E1^'F_2CU;B"'=1_3Z@ +M!G*ZRGCP[C?AGRWH@EM=]'Y6<#'Z.6JAY[JICP3W](#Y<*/M(\+N&X_[*Q$Y>E\NTL +M02H(3K+6KDA%UG!-CJFZ;ZX'HPG%@;MRW1!K>+'%Z4";R89F7AAIO&KD\OK1HU`A>%CKJ/R\JZ7765,>K +M",RW@0(\!K4#0G]+H)"O=AE\&+$J,0.MRBP7O!=0#0'C^)VG-YY693>;0(IE6]?)$S3`2. +M:.=:3GG]68MTPPW.-/67PPJ]"MYQC%R>8JVHWB@G#%T]MD?#YSS-'.I!%QE% +MODLYC2@$#,F,IX%U7F$#&P4MBIP:U(])T4Q!4.!AG3*L[<;$>9 +M-P]5M"56"XQ&2K4]#HK&$<%[CD().K=4U +MX(353W=@P0TB!G"^*[=:\&PB&?Z/,?TPPF"K&GH5',58JD%RTO,O`*A;J;S0#OZ1.8-3.4O*78-&1%X_* +M`MY1%8Q%#92E;;^)X!U;Q+,$JO&]NGFN?4NPQ:C/^!5Q'0OYLD)3Y3S7.MY@ +M3^>]1A5&CD;J0[,V#P\/+`5'%QAJN1GZBJBQ_&[8>?E +M6K^G!NHZG+D#@=`C-N?L2!Q"KZ8+X[6"^GKS6Y6//#!M-V_%8P1]*XKGR-.6 +M*Q!F%IK&+.H%$ +M+OQ[Q1500WN\Y;`<20GHQX(K82`T9%J#`%"-!)2"VE%@/")_/&"37DZ(3V#; +MBFP/>O;YH70_DRIU'K>F/Z'X&^;\_ROM^$^]=^^^ +M`+R=AKW#A!UZ/N'SCGK\I=B)D0_[B":YZO>?XZ;:"L=BPG[[AX_2<+W/QCP- +M9G?@%G#,7=/UU<`2]6YJW@^:WYN(5N>:W,BW?OX\&)41W(#I/&W8>?@J[HIP].EZN:33#4]%8&(G+7?R,T#E`_4\>M'B`K=`>[?1XKR[4`G+BW- +MWQ=UN8[R1O)1=`#[1D]GW0S\"Y[1$>A4E(L3@2'2,.HD8;%0AN +M-`"Z4)65&M")LO4RT@HRIK!4UPEZ:6>9C>K2Y1>,])MLN;4F.RC;&K:/_T^) +M=/.G^)9D'\FSX,C_.\U^,BA:Z3+SB8;,O`P[SX/A69 +M%Z6"<43]O,%/SXCT%_Q^%D$*-W=%:=%K3R0@UX4&!'NI-*I0MHA8XL#H*66F+,27[LS;W')0:%#3TA,C'LGT>H"^5?8>@FGZ/ +M1EBJ[X<7*)^X@B3#YP1=T)'')Y9DQ?+LF/^%:?PQYU"D!1@_J.Q.WK>AT=9%Z\.D$5+!#2H<%P*LV*T[;I5`K]S_P1HD$I_/-"+61#N@\-!8 +M:;C<2=TT1>H$-!KD];X5VGCUJ8Y/G?"IN<\+OGYH_#!<4-46>61KPNR!!^13 +MRH`')\5@F>BZPFMN_4+I-MSY$/8+FZRX<=5TXK2@&(_.)`^DH75'Y-I.$B_! +M)7JR@U5K\:8Y.&LFY4#\(%P6R:A!_S^$Y%6\*&)0IXY]Z;T`&QKAP*W)-F4# +M9RQ+CU0FYRQ^3AEYN&;27GJ-RR2@/@*7KXTRLX;J>.$LU34@#>1"O6C"BXR2 +MIIZ'2KVAM.Q'*-(Q-V*^CZ9+MA'D87=&?%^)YIS!A?2`(UO(822=.ZG7Q+_S +MOZC?[R<&BW?/"0@TCHS7NG-Q"8K*S%8FYHUIRD/S'!;5YWTU'N'J?[ +MY12*=VWYC;[ZBC/J>(WMRW\>_\[20ICBK-G>K +M>:!1I/1#K"P+F8(JY(T1<8=(\S:GF8=7$H+!`[^L8QG/Q)88E/F44^.KF&8B +M#KG(]A$N%0Y!="5SXZGGW_8:F^?.$*G4F3I`Q%7$J<2W$02V"P7]<-7-NI +MP'.^83]PQB$P3&0Z=U<<2JSZF?;Q*I:J;!-+9$*8)@0ISZ#*`#8`8;E[,L\, +M)+6CUN_T*/U`SYQY\_A_.HBGWY[B^;GW',26F;V[=PWZ:,Y;S>@0U,^-&0ND +MXT=&:6G*O2N*QOPKU(FF5IH#G.N?H+NWLO>A4#NF! +M(?Q_JR)Q]_"`4@1CVK49@(]>C9B*/TL0=$R6?"D0S-Q+J8Z7&<68J&_[/-F# +MW&`!A+V/IJHG(>Y[H`=OLUQ)D,F9,%] +MM?(LH`]XJTJL+RCIJ5\G"8*S+7#[IFRMA2R%1+Q&-X1U`;2OC^8]7R6K3"O# +M=Y;QHV[BCEI4.-XEQ5\28?Q_@7SS5((;8`Y1++/AWBW#@66L#_-X=_E/]+3*[_X<.]\,AM@WRGGJ`J9*D#!1"#PU!JVX7VXMM;C2/`U[D\ +M2F&1OEK%@+D8EWX'@'_&^UD(<"`G%OEV.18?L]!-@4U4TKA[4XIHX\^,V20R +M,BNLOL0V):G>8JPG15LS0'*1F/9.*-3(,TJ<:BW[=V2?0;'!Y8FK]_TE&/-Q +METJ:S$AKTZAR?./Y:YI@/:?P8`1B8OHS$9-J2P_4\%S1P3B;.!)(UK>LWQ+CT#;<:SKJT70:TZ +MF3QKU>DX8N*O9XAU')2_WR74IEUEKO;WV9+UA=$YI%3G-V*;/PP#/PMHU^HC +M'%OOPN6:4OXH`Y\AGYVZU>_LC0C/[D:Q<;7_]8I2+<7KUY&;VA+GG;Q^^A[M +MG7!>\^8]W=ZLWO?1R[/$P+CF;MWAR7#CL7?*YVIE-(YS\BAO2=.=I]2]''A# +M7WM+Z[FOJGS@KP2KT7#;@_F$;X-?A)8T&(4"2@P9 +MR<:\".,Z%'?^_VH([NXHU.7'-CAGJ:6SK*=9M>? +M5&TW1/9CA5%R_V(4)HP`MNZ<:A4/%G;S`OD)5DFJKC;MVRNWKJYF%?M_ +M$KF95^W^I7*.N9!F.+.PH\),VCFI*<^K_SP5S_(&/?^_@6>:^211QE+\1UA; +MQ6_$4\/!8#YCPE3S^>IZ^_WZC8ERRVT\JGI^1]Y_I^'_) +M-4]1?+RS4G.]-%'O#I?!_HS8MD[$/F*+`]4#=*W*.RZX]G"E`;G^J37]A<8?&6'@P%:B>L>+"/GSEB? +MZ7NY,-`^;>[@?2FI&UIW9W*KIE;ITW.ICW,S;"8F>='X&FW8//JJ7UU].?<>C=\U6@Z7;DIU;T:J8FDQ,PO\0$U9? +M=&P[O2-=<*%M9X_@,ZH7O/;\%G= +MWK,/>_H\"68]=P,`XY^_=XDZ<[>0I,4F)=^AXGK +M-[U?"2F!BZ:+1?!)[_@HQ9OJ3(L"G[^\&>"I=G8G^$CJ`MBSEQQH\[<_S)2[ +M$B(J-"&O!!YF]"H9['M(>0,<]O7+_JI&IRMKO +M?X\:F`$6+A:M`;;E\[NUH7$VZV.86.DM3I\-T<4"PTWP4LL*K +M],RKZOU%3D*WAE>8;OMNDT6`:B`],#=J0%G8_$G-S'XW]6/CB!W;VGS?J%KM +M\-AH]O]S@1_#\+()-D0N\CU,N3)4$0FN]I1!5D`X0%O>)UW61W$3N;J/II,R +MJC$M+LRWX#?`ENP+/.B`)FE=)DZ,U`(:RO$?06N)_QX#7B]?DFC[XX"WP&A6%QICE<=`XD +MS'_()2S2OJX93YD6_TJX=3.]>HR:F\IQ[+E2O9*?"5/ZK[\&-->L^K)J.C_ +M?QOAUG'SU?%GS%["X*RDA?+\K5+,G(^'<*F?4QKOAK.^4TMD%@`B926QLJ?7O= +M'5#O9B(*Y'PZ7J+4@LDI`9%(8P]LZBV1.8HLYJM#7NX\S?O>-O(X3<]I4Z9B +M^9,7VEW!@%E\P\NROO*YUS%]43UW_M`F?5!YHZ\R+_8= +M1&0.J".J](0%*GX!O034O"P8#S4'7+OAEYX:[=?LG#)SAU![2SW +MOG,A$_/',<>]`O8+D6;3&\#>?8;7@GE$W.+W%H+B=_IAKXA4&$IC/>;VD?+J +MX*;&6+3OI,-%\[VIQF0 +MJ1M]>U!">C2B.I_11!U!B^N)[HP/ +MXY?S0D&E32)4OKG$K4T\KP13SB'KQVX?]RCRSWM7%Y823`Z-[>O@45!,KAI6 +MV2I0+R\^SWQ3-TV+WZD:-+II,.VHQYYPWF*>6(HWH&/U_J-KYAYGJS2:N$)B +M7JBEZRCQ;V,H\'E/*:*4Z_T)G90I!56?@SGC^:8YXEZ_ASQW.V5!4<2H3F$> +ME5I`B6_ZQD.AL:CD]63*`7$TF!'=.3HG1G2&5Y$!^$,B#2(AH"QZU]N..\9I^]YN#AN>G>9^G4N5T=>F5>F4NUT=8:K#4NUT=9U5G5+M= +M'6<59Q2[71UPRKAE+M='6$JPE+M='6;59M2[71UFE6:4NUT=9E5F5+M='685 +M9A2[71U@JL%2[71U@*L!2[71U?JK]2[71U?*KY2[71P@+Y[(_7^5"NPR5ZMJ +MID18#&M-CLCSV*#L'!,BLY.03/H5#(FYPGT$&*YT[?4@8?&R'QTP+CA00.-R +M*5+8:AM?9@4,B@'-UQ,/`NO#P_G>ES\/YYZW`F1X_:AO^YK+,5?*S^@3<_3, +MQMV#FM!&9C14=%_C$QU][]@,P9:_]=]`?X>\?]2H?^A<7F-ZG@KSV(718EW( +M#7/7D'L&\=V#S.U8J(MY(00[H_BD,_(`/K0^[[\&(_L#IEIFW$$B>N$?S6F&DM +M:;Y,2Y%M(.JX9PT$61N\F>\S8C3],F!;KKRXNKDBZN9$QB^3'F8FYNR +M9W@ACNU)*K@`4DTC1-FB49O2I=;B#AQ1*U%MH$[%SP%K6H&TB?RPVN$#TOOT +MXFZ%\P).8>&HH\03<@B8D7SQJZJ?[L.?>+C-S^:)`N/S08U-'$,W-PIY+?D3 +M$:/=]6&.1TR`8W$,3/2Q)'`&U8?_F`.]ACI#_J<:"M`$'5+H,0,>()$86C$)\S&X-"67+1CF7$9 +MSND'QS@0L03"4_:(Z<-3:M`:\H$Z?MU"34P_FWELATH%LIK2&F<6_,8[#:!%>-BO9!O9O=\Z-K\/&@;A>Y,6"CT-"F`8XH3:\5_"CV^_ZR/,TNZCS +M$;N3W_%'Y\;EG:[9?6\1"DJYE +MT=/B>-X9Y4SKKSZR=[K4(D:S/7($:6@@T;J-V,I!6CB!3PQJTU58CJL]<8>+ +MU@ZP]ENL/C]\*Y*H><(9N!>P@)WL[CH^R,XBC.3T=;F73#9FV.7PXPD-C'X@ +MQSC3$7AQW[6B&X),FC'`L-%NE%L/C"?[\8-K!MZ>.S5*B!4\RL:O[EW$[L>_ +M(2(HBQB<;DSL*5]&'Q(?-^;*LW"M;M,H3J3@`(46XOQYID[!B +M7UT04+I=;83&;D(A-_C-*8B4PRCF+=DZ^T^-1O?VIN&EQPY@7#B.?97F0D%; +MI+7A(C;B61CV+C-V%7'Q_D"*MNV18O]`!*C(A4G%7K9]TG9_[H%V28(C(`S#..K5Y=6K\C +MG6V9I8]V]%NR66+,%*.%8??$YX.1,R0A1V.Z'78=8,"(R%^99;J[ZFJ8+$8T +MB"7*N1S*DS,M7-P5=.:TN,%%1DV +M]&1IT,X48W9)DG1D&PJH\+?`N>&I:BU!=T=LX=EEQUDOOL +M)LZIQ?CVU\2HJN2T==PT!0QYDQ*D',MDHX2LX94B*,TK.&4]@J15$%Z`'[:C +MZ;).]Z*.(SC.`SK%LV44E3MAS^_,!`)5T[FW()6]6YK3MX93\UU?M5(*1+#7 +MHNAD)#WUT!IM_Q7?%FW\?CS$\L'J9C3(2\,><(3-U5XTBZ^CP5!*/L.,-,#,XT +M*ZXY(NDD;11FA^1"0[H$$-X,-%CD-%+2E<$9WC+9A5F%:WA".;&_IX#KW-Y7JZ$HUTN>`2QU_VW-SCEZFR$5-1NI4[F!KN9!75.K$U+4$ZY7 +M(U`'!:[#%1SN(EXWRD[M+51YK8VMWW2^`PC3$A1";![W2]NO/D)2;Z3[BDRE +M@6^D#'=<&U\%23*&EGKLW6(#)*0*CE)3CJ9I?K"`IW)6`1M5KIO;A('0C\KY +MO%`_*V':F(OWCA!C,ID-E4:N57^WJXLN>=OO+`^4Z*0.,BI^9@'Z'Z=[B1>& +M?R_0)D`?IKAXJ%^%TS?W@P^FO]$$3?IH(]LJ^Q3XLV[)TMP8L\SUQUQSWM_S +MJ*13F&]4WSV[7HJ.=B`_O&.,_^IT\OH%S/#WI)+%+/&_81*>M5SU$/]K<22X +M_X%'CJ>*?>N]U1Y)`ZYUV\EZ3^Q__IPH.F`)ZWQ-V$.2<<^\=O$_N4;'UG28 +M_V;NHCAY)"7/JJ/><=OAU%=\+?WYV2=\XPBW\$NO%Z=TYI9VB1=<06EZA1KP +M4[.H!7U;M*^KK&?(Z!\CMG5,TW.-@PQ]-K^1Y9EYGSEA55=315UEMJLP7^V5 +M\#'@?)(>^E_>I4[M6:M3;JSGU/%5F:/EX[F9M3YBLCY&;Z;F:U3ZRL[)3'5G +M:*>>K.B4_"K/>*8GJ*Q8J9]6;)2TW*8=LXT$NWYU3F',]HISZLZ%32JS,'RU +MSF8:FG5G1GKOG,P77QY>&PG7R59TCCY;F<,?#SG@H9:=\>\IU+M=&87\&CI&&#)=\ +M6NW<>*WQSUX[SF`YE^J^2X^6WYC?G-^HWS''FO/)7\SY1C)DI]]XN/A1T'#- +MIZB-H-,2>^,=6FWTO`X`/.`$J/E`I,WDO.%^\WI#+"OLJW;T3X_O$NC+FF=G +MI.>C5277-TYZA^HP5JW'8MUS=@W9M[=OOF[63"(;MO?./!;MV^(WQ6^.W<-^ +M.WY#Q,Q*GIY>&=,]"]0Z_.;^:WBSU/M]4W5UFU)KQW8(E@^/Q>,2[U\JO1RG +M],O=YIN;;)N8L5\L_@^,+AK&]FTOTVM98V0^,B%KL:K*UUEE*I'5K(5P^3SI +M]D,F.[2_E"2@3^#GO:ROU[5!:5NTLP+QMP!R363:S+5$&'&C_4'=K"AO'>_. +MY#NHK6;:^/;**CR3B`=T>8[!KKFLQF

    :01STH)UC8''Q"QLSJV%YRP +M=8HME&P1:CD4DS^$9F$>R^RFJ,'8W7\"<.ENTM:]H,.C1\':!!PID8"II1RC +M3.+4;HH(.H#I'W`(K6CA5M6CU[TBUVH;F'T*M+"G%BGOR6"U#I)-@TY@GXXS +M37:7=/5Y,J'85Q&QM'$LFZZ8'TNNJ-7.8C/*]1O81X#@# +M>F>U>#W49_JZ!$RN>6G5D0>DN,W_N70?'0T2?^%9":&,XL_302>:'PDU9SF[ +MK:2-43F1J1S5&+9-EQZ'>%;IV]"^K_58]8`[JX/W`]S2B>\!4.']J,5-\'[H +M,>5E)4_;O`5!8M1-P$KG++A%T,GT3/(?->Q;TN?387XJ9O)%2.`1,R=/.@:E +M'?#F'`S`/=R^&'DH/5;AVZ""F*W%FITL7X3SP&`BBUM>`I)X2#E<_Y%8%.\\ +M748!$YVS!K]'K5.)J1UX`A,+=]GJT'*P&Z:MOZ%6CL_0(Q!]0(6$V,Y)_P4S.J7& +M-!.^<9I84!PDL@AB[F%YU>GKHE5_Z5Z:C!;G-!T?_AP$2NB8VC+N3-^+]L7- +M[Y?A.*1*`K^C7-DTK5>Z/"#S38(Y,,2Q_A%1J`22)UPO"WY%_$[N?"8>=HE$Y$N(\]*W_ +M0MQ;Q2(1<^;UJR)YC'[R6JQ5^`>(PKH(/9#AQBFZ>`8)]]JS<89MX3+X9Q[! +MW5DN91\>5-(?]2-H<)ZK.[T5M!(=B]U4LV'6\MI,AS&5SZRLVRSRH6V-?BOO98 +M0$J`U$YY7(M(8/)J']^&VP=5(_93RIK*EZB_X]8H\QZW:OIH/ +M8TT-N$R;FC:];8S1ZR,I/BZE$_'A!#RF"OR4S*>6/(ND!I63A_=V[#:E5E7V +M#SMM"E%-S&,\FO)J#B*5)[)A$<+I5U@3)=.C+PR?;/0P$*S,C16:[XN635`& +M-N0J9"RR&'W6;NQ2^I)]Q^T72%Y[L.KH+\/[4>T1SD:+"W4D"3.J@J;TAV(L +M4$IF.N;9@VLZXNJ8*G.MKD=7"KT?<3BG<34:@$32)^201M_KDI;%Q;KP4CA!L- +MY$T-_M+3LR7(ZEQ":,SK$C&(8+;GT!DY+9/IKYL_(TD1R(+*8V9]^! +M-[W92(1U"TKBO-VM!!])4K8E"4B,.(?"YOA7S2']#[&8BJ4,F?OOHA\3Z"9_ +MO4J5RH[4';B=?J*V5>2GX#S6T@T;\SVLY'&>Y?$8J50'2A>^TR'.L"`T2#@A +M$?1'>,KRJSP:[^S[0G4R)78/+J[5QT(H-DI5N94(62'RPD0AP837V'_(+`M! +M_(4:SG2BS=1C"&A<,'^]Z8C5C(:6UI"B4M/'#*VLVV)-NNREH+=3J&B5DO8& +MC$CH`IY(8OAOG[=/JUU\V[#=G<,5A@,V(D(.\\4'.H[;!`R[92-5-XRN3N#\ +MOD0JY;G@N:*$]O-,9G]>[0]UNXHPE^PP:XT.`?Q5]2>]X$KF,PFVFTGLN43( +M;30/BD<]D\$5E:[1O.P!K2>E:T4ZC95=\?FQ4=DH$O02@L& +M"^1033,<0*@WNNKA.LU@:HR;)1G64/R:'A#]5$?0L_^74J:#2\(O.\0K>`HK +M^D>J1`&1'J<)3$$?RA8P.Q4<&ZB$HR/"@M2_I_8=ZC[KS7 +MYKNS.7.$V0RC)5="J//2-7X`+$1A>G5BGFII0-H8<-WCY?59/V>QLEPO\[RA +MN:<\I).+_$ZN/\;D^):C+80E(+*3\*K[NB1]4:@91F@MFQ +MLZNH?J2N.!7:/_!!E/*1!Z`WHNR#=1\9S'?+'@8L5#U&=P'J[-%K@@106'W, +M:TF!ZJ^NA5LJY>UV_#GXVWX.28.P.HLL5(U3DJ=.+MXI+#0245ED:,3YY<7AQ]= +M!R@^_0UXEZN^(-MB,$I@*_S51QSJ"HKZC+T=8Q^:[$,;Z9V*%,O&?E5D +MJG&NXW/HU27F:L90U1&N2'N[RCX5[(:%9F%_]N_0Y:!/WBVE@?CKK"7E(HY9 +M+21N'$-.32<09T6";S7YB3;J8T:`M!2728&CT(Q8 +MJOFR+R13L,EI%"JB?&:-VJ%P,#OI]DVS4P=5!6LWH;Z$H8Q>64`CG +MC%T(`1R#+"Y,;]76`)RGQ$SP+[.NP.'FV?]6-Z,RE7(I-VO9Y\0L]D^)>^K3 +M@`:&I88@Q67$8=!;S#T&4Q')T\D^+VH>++_J*F5H1U,I33K'J<^'ZX:GAK&1 +M^1)2T7MO]:2X-TZ`QS32@4\Z".%QB/UX`X578A@"T'Z5-^I6D54:24P-TH&C +M^U@FC7&_*%&["S$PQ/_@I7J;X#2YV/CE5U.G:VKJ&U1A;/@AO=0/"]MF,=RY +M)TD,UB[G+EO$Z&A*I'\[35H."G]U(TL]Y%-6?,8#>-M\F$0:L>C$`N\\@T:K +MKZ;^>;77=#RH]C+=O8]5ZH]L:IZEZ5X_I:#'84#'-Y@ +MPVOM@?)$BQ[>'.WZ@Q4-W_WJ([P:``TP0M]J->;V\G2ZQIS'6M8%4BOK^?H( +MU;__0K0TD7I\EK+,$7#O:>W_/=.ROU;X":Z]&9J!DYKY,Z(%?M\*#9I`+_R0 +M-96HI2NI6B8YZKLG@2JYB.BE+L9L2:2A6QF%W1-R@?PZN:%43F=V7O1 +M9N@KYW"/!4U-#R0F<=JGS6B;UI$\W&+BKJ`0&O,_(M->_E,[-VA_Y8SZ:22X +M3#CF_:\1-M=AHHU>+1@1L072$S?.J\Q^4('WB:]C/<11FA=9XL\_E>%` +M5\O%.*P`*]G?<"Z9AN=^/:!X;ZH\APBG7T+/HQEVXAP`=5*UY:"-2LQ7L59# +M-5+7JIZ8U1_=U!I9O:G(@/UQ%Y+)A/WC`-H2O2F-1*"<,8;?\8>U#O2G6:V!=GJ]@HT="\VC@=(.D'9"2ZB41N!E^9ZN8O"N] +M109>X>(CL.%U+MK[S_%6FS\U2UN_FB=06TFX4.J444A"R^LAR-9Q$3C30=*>Y_>V1GDT'A%6 +M1!#:-\GBDPCP"L6^^H,(R]M3!..(,>1%1W9&;N6C(QY(]!^I"D,',[8>XH6L +M=FNXL/^V>&S>1R2`T8%?K'DDJ,?]]D6)SAIK+VSM9]0W8=X];3[TA[!4D?NB +M+N]I02+&5"C35,1*QUDZPL+-#%CG7,`(;%>!I);,^94$NDGPH"R<&R\-E\K' +MDP?KKI:)*C7*9!-T=0.4+"9]X=SRCBUKM(W#M9)A2A35]D9GY8PK(N%ZU<6< +MF6??N'?FK,CG0'R?$(3^+SY?V,B+,T;'(>I-N&BFZY8"]L/O=-=>GLY`96`6 +MM%CW@2Q:L"'N:N@G5>26..@(A>:U*8/0[4\6!$HAT'\D^`0&<#!"]9<6HEDK +MKVO6"B<`-9UZ!3K]@VV*%B.H4-EY>W:H!Z.V^FM!(55$&2PV^;?7.`)N,^!G."Y<([S +MW9#DQ@V0G*C&.3>JN,R-!,W!0+?CX0C.C1$7*7@XIB%^N,=/9SR0#I[.-8"V +MPD:9W8H3@Z^?5%3'"$)/ZN6J,:09;]D8"*E\[0^Y#US:2AZ?4B:GB5`<,)!+ +M@78P!ZHU33-1;-X2.B/\*:VG7WX38P'N%9]&).]9^?/#5M22*\S\M!&&TZJ3?-=A*M%Z`^V3 +M>0IV[*?#?44SH'U'B,NLT#S"?@?VS.>&ZJ>1P,.L#L2.DQM_N4*Y0-G`&][Y +MB1Y6(=#E,.+HRO*39Q+8[]2O.;9VKBPWM\?R@_DP9^@MG2(&RK-QT=-0-Z!O +MR7I?ZIARG4:$B%+V";,O3P5(;_^TDY[]9F:Q +M,]$4=IPSCJY!>[$F*M:PM^VZ1'-51,%4%;_8N97.5OX5KXVP]$HQ0J4.NA2V +MJ>F1ON_.`,=:[%RZUG-&9,=$,OK`*2W+E"[Y(A^##QW[_;8G1*<*EV0)^MJM +M,J>"!TE[1[F&#_)3,P'JQJSQQ7QX*'L8O=5CU\@3$'THA8)SOAVS+/:M$>I( +M$KZL>%%!/*@BQPM2BMA)1T"FX7\]*-#1.D'%#5W1$V0-0.T5?.QJ)G%NR4;7 +MM1U@V,S$F"NTU!8@P'EZ;ED[)"!6";9GJG5JO+M*C(=.D''23`\!!"`8HT-\ +M1\CL`673V]9Q\HZ4SBS.;(0.A_>8?LM(T7)`CQ`Y>\(7-*>D7.),9YDRT87[ +M[LABS,:%8NP)'3T28HUP)_Z"JR]DRIV`ZN(UWX4/"'D0)<=LW&U?]FH.[6A" +MBKAF)EHYR]&[_)M@=918(\2>UZ;CPFFCZ.!]7JP=&9J,3:9H<`OEB&KSI?"2C+E2Y!R[RI$YB(`F>X1 +MJ0&;64F6`W'7&N?H(:$]89+U,H;P??X[!--J_!U@*&.1HG@DD<>:85X72./? +M'N/`0V3,H#^K3OD.C%Q9>GC_`I$*?JLWI+MYN_ +M%*:<^\J\PV^:!!(W&-"MC\B+P6>*UPA:#H(_$)E?%VABBW1V?"H;.2)3B`$` +M8=._!NA5R.T%G_+0-ZE2JNT#KR[3H)(3=C[T;K/ +M>N;4LWX)C:[()`8B\9,KS9P["IL,L*BDN^IV%1$)S,(W;W;%8QZDUC9.!?JT +ME(ECVUT6);0/]4=Q_Z!F8C*'@]68J!-(TE>+V\0XGE)W`RI.*.&IN.6?4%[N +M9MC5,J@,'RK+MP8)(:Q95P0""-]ODS,(/_^KW&^D"'TGZ_4D]=Z,G*P(%,>?ECDC&?VX3(->BV+AR](!)1"_KA2X4,JSC[FQIZ9GGQ'UY,C_SVY +MFP]9NEL@2>+Z$5_$["1#L+>3EBYLI,O<]ECIFVQ^(IAW-9+?,M*(6G1)>E[M +MVZE.V%T>DQ+JB?CNCKL<0'"(*/`),2A-Q-5X!N;M,:7P,7_6XRF +M?Q-&<-'K<96*;SL?W)"9VMJJ%WR,"06L1Q\@F'$\!!0^G)V?N5SWG/Z1I\-5 +MZ.Y'0P5L`(S.4$4!"Z(+<*Y2*"0EE3!71HU5;4&T^0((T42DI$"WCVY#`B>N +MZ0OJ!HO(FK6@+2`0:A:]_E=J'!EUB`(E[.LO0UMQ*K'JN=ZF1+`1O]"RC?;B +M[/U9L*8>]1KWR5=2#0/X<-O1":Q$ITZ>J6%4"WB&WV9055H_,]*N.1^YZ]Z( +MTP!$C.<(5H)\9\[7F40@TYK4]#M99L\3M]'E$ALCG8X_YC?(T8%."R/\J\WC +MJH`-P:3?YG&4%*"4]K3F)QPU[`&E%'4T%/I]-432'"1?E8CZ>(660L5(-X\O +MS4C-VDD)?EO!L%+9HJW.00AE7Z$/Y[/I91H'R'/;B7F*B$99/C^[ZK=(#2X?N2 +M`EC7ZA9\S@JIGI32ZWEC9C`QC3MU('P'\]J_>(`54Z'BT9AS +MI^;4`/X0K1O*)$2^6XMGZ/XAB7DA/8C)$8^K\6 +MYO3R'I[`8'76RT'ZW:XQ$+WE6,XA80O).X?#DF3[4R8_*8(@1K8)[V%5+H^E`"EB(/(M=>3B +ML>X(/-CP9'7[KVBY_RQ!U_8I?'QA/6 +MUNWZ7,]K9:K>QCXMB_UMI&;5EWYFK1R&< +MM44C:1DO6@FA(U-WV/Y>X];Z"=YXA_ +M63^$/'6#Y)":++D_-N07_4?OA\N*%>(KH&;-78VP@\JBN-/6#43NEL&AO7S% +M_WH`Z;\1]LEM<(T&K+J7"ZZXKI4(RG.*0H%\,/ABXEVDQ+ +M8TQ.YB0^Z$ON:7->`==F>3VIV=5-N)=R[R2&6$/H^K@W`5%@<'@N,4+F$KUQ +MY+.7/!G'UHI)AT(&(0IW[<>!V?19O@8*>NOU^L23YQ&CB3Z4`XR"0O"%MR`) +M?&0>]QN<,AIBZE;1B>DP18RRR2QX)7/-WCZNNAQ._[@S0UC_/AZ=BP@'J2:; +M,OYL]Q^4A<2OLU37&$'9P\AR>.:X2.,P`&H@6A+]J)70B<,R&:5;V?$?>!Q_ +M2U`!A.W;"#B8')BP'A#DE%7?41LMT-N\JZ:50C+6*+JE`_("YJHFE?^^F'-> +MRJ":>^+@3"7<>MB?#%J='L9^8YBX?A"^BDK\_,C +MG06\%8#V!/^.7[)I5(G??39U/JD`M/72G\!H'`+XY@>=,S6C[DBIB5SX/TOC +M!)%]9.:-@HNH(]?'4_)TO_*25)-RRR@P+`FZ<91!`Q)?8)7(+!/%V.K3\N!/ +MFY1HW6."*7->,$98>N?$J)7UZ98+8^GNXG)\9,:RHP"5KJ>R8:$02/L3F:M$ +M?JZ/.`_$\MR^$OEN7.M1@^?#S:9WS-'U5:/#&+.7[?V*FT+&S4MOT&G<)KT7 +M^H(KKDW.;$,[CK7?\6=.E/<.'OT@MX+`%J4#!2'J_^3U].IV$1DUA)C2YX'Y +M6@S_%^2K!98O=NT,4CV:'2Z.R>].D.:5)8?NXP=(7ZLB#"!$ONTKR6YX.PBO<\SLK\R9%C`.=FCSVAC-VJ(T5TL7_4($3^FUIC>Q/[. +MEH#%MLMXKO83!(?Q#A2:R&H-'AM'Y00NSPX1E2.Z&BZ=!@Y`HA3$W[-3XHO8 +M=.J#!"=$TEC^!]W6OCT\A*C5[-X+L]PGG49O[ +M&XR=\X\W)WRGOL18Y5R)(*D*SQA#,SA">NNL\JHB6\D=6IFX>V%5-5G5S*6U +M&ZI(9]FZWU^"#^!V>,EAC)3!6BIQ>1[$%@[`1'(<*@?R^H\W:U7C)1K>@H:^ +M3B>VWW,<@JV)#)^-Z&-30,3P)VY$#.&['_@?O +M>?$?+-E?2`QR:VZ15#4[QY#PI`O"KGD'IX5N9>(/D84VI3%7#+-<`$/=D!00 +MJ>W0P=9G[!&MI>P^(!J@8K$PJYO<-Y!YURV^^0:\I)-`/J9C;R%D7;5=_X"2 +M0`^KH]ZWQOELY&8?.\=#3B1G^LPS6.3XF3(M +M_\&\!,LF.8],/^JTR\HY:UT_;0,0DP9\EHV*U4*6$;P&;E>(1*+-&B'=M3W3 +M:)SCTWOH1FW;-5A:(\R*")&Y[6R4T'*_;]:S(`L>-69L2,07$L)GQ#8;0,IR +M)J^R"ZW474!5=FD*J5\MQM,#9XM3CS-0Q[W?=_W=E3."PX@C,\IEUL@:2)&1PRX`P;/Y8VAB`P]DT1(\(T/NC:' +M2^IOIDO@/-\,U\Y!>EO7,Y>=(ESW8VY1MM_APZZ5S22!@`*.TV8D"3^$*8Z] +M5=T/IWS`0CMZ>M,_WL;6D"\"MR.Z/N+`?A2L](MQC& +M:D^(IO(2"]`.#["_[H3N/^K82J6SW'L;./=WR#G8ZGUGB<\I2-],1S#DM^7* +M`4@'$\3#>^`#-R(45(3<5[.%]D,K"LN=QP"J^&QY_:Z3^>>A#KK!'GJ)+R'V +M$;AN9,2'#DB6T)JS&2]KJLY$:JUB40`](0J_]V!XV^@!2USO-U[>=#H-95LQ""_\LK#;5V +M:P8-+^64E(LNNZ*8VZ19;Y,@\R0UXPT\8`?NBX9'W&<98O%!LYR!@IVQ5ZI, +M$3^&]GR_\@D?]:WL13>%>&NO5]B8M?&EN<_7ZXTK +M%I83Z>RW0*RAK,*2)8$KY>G8,1D=\XJ^MS+[U"&"$0&`^!R;"FMY`[6N>M:? +M#J?E&=G%#]35SBDQ"2!_W$O'?!/#TJNJ8PZ25O5=E1-YHW):H,[X,'KUR;(? +MA3!U0T3R>]SVV:#_Q['0FO?>25:%I`!@=_ +MBO<^!KR%PDM5@IV!-`I3)7_9/^D$CIH#/WV9Q?%#IE&#HCWUH,N]W2G6K^'A>5!(#ZN%6/U?]C&BS2E%:)9@ +M.?M5TR.NS%;9F*CL'CJ?;C2WVX77LQFHNCA1\E]1`XK:RY_LP,/DVE;#XL40 +M8--A"ZON(\G"6RX48C;BK0'P3J2J?B0J>=N%H'IQ^2FL;7L?%8ED-@,'"!*@ +M?H?YUW%E&6&:+`@FD1PDNLL)'#7*9)_\W4'M$+YKMA69@-GAC$6Q=%C$O?%P:PM5/B>N +MGEOQ!C@#*+/V-&='CT>.X(=-U(WC:)2YVIEX_P+-(LZ;`*RK[`3^R6J;31#8B!<(P>/#FE7W9*^?!>+DQ1L&&2A'R[K9C50+&:,MOM>5 +M<$DM\`VPV*MU>@OD6H'2^\%B6X##E^YY:$@YL4F?%6<]?Y#_D4%&I +ME)`#_/WS&#BLS^F`)D?1`04*;%20E%!WM4NJ8#/C\W7K91D]9#EHOTE85SU) +M\F^9RWS5C^(UV/.4[>Z(\1-+>F>#9RQZ_JW@)EQ +M!#:2:(UW&M?WU`EU..O?&RY2A(0S1>2.S&0?)F`5;X+A?GO_PR2X1E;1>NPX +M!?7?92I!9>(Z)A\.8+;6-G!_OJK^#L^TQ1Y'C1KDGY +MM7AW#L:PGL'SC.9D:MF,X:)7OK*\BW>L5OZN4P\)A#/E],R^`'O?Q+7B2K>7[F_^L.U/*"/DL4;X_GU3T#IR?LKZZ7.AO<.@3Z*!2?I6-#S=3RRY,3MS +MI)?004Q-Z64[=3=-LPQ`J6.Y/,ZF$9SV4'7^KNLS%5NE$TVEIJQ/K73U_R+1 +M)5J3NC9<9RT>8*9W^KX:7=SAD/;_Q]?7CJCG>(>#EY$:SFCV$#MS?>B6/PKJ +MW!*[..PZ*)!L($,:[$'W/1[R4KMO>_DL,<%0IN(ZA^'3H?__KER*'>GBHADY +M^7J]ZHWQ58M4")0U>!/BF-%%MSSC>P(2(*BA:31!DW,_AY$]##_U([!<.//6INWL(U.1Y9(8(;]W"_<+J9_ +M0!\RQ<^%!->%2+M2J_,IU?"WUSW*[5`;-L%?LE4RL2SD!YJ(V-&)$%),L\%B +M-9F>"^&)@3WA%L5F<2!*]YXDB7DWK7@5=2"PU9"#,$_6A8D01$-B;)G_K:<@ +M"\(S&2VT>S1(YW/>,V5T@G\QPJ*CY`<,^R\.]T>6`P,`(@(Y'KX,K`-BHA``L7OFV.P481D&XB"T7> +MN2`FT%$^H<=UV[`3$LVI)6.,$+&T-O/^\X:\74"0U>.T&M,]E@_]YM*HEG_^ +M",_&8EF?,`F11I'RHRM?>5'D6=Z36`\/21?`=G,1HAH:=9E#W93$15PJ<5<& +M(I@7H&Q0JP2F+O/4D^DD"-YP2>3/:2#=U>4GW,TB-98EW%CR<$`:N2X\A^KD@N`*ZG.AE7[P7G\X[ +MK5]^C_;E$#0FE_\)'%%O^ISI_UM_9Y;K^1\0+SMITE5).P0,+R)U((Y(J]/> +MO:V4[DWHV<>P7W2A%/('7`\,U))N1MLC"@XW"M=Y0`H@>DYLO-Y*E3-9.(1* +M[=2$FS>KF@US#C&8`Z#SO7/;R&RR$VX*:_(Y;PA8*V>?$/>0!44HG2[<489B +M"_^:@\31\F,NP;RD#?&%GRBSN..?`&'\(AX$7_4&-NII4[`F? +M,;34Y*UL&P\5"F94T\$-*09?FFA[?%M3T0JDN7<#Z*U+>A-7_]%0F&8Y8P0, +M-`:K$9_T7<^N,*LO2WCP(P[H.JL_[WX($.,9DWW?U0Z$)"/2'UC(+X.$`):> +M8]:C;MVY(S)D:];D^>CPS^)-6]Q"+]E>0H724KKO(Z*N5C/87OE9-Z;?7L`6 +M5AYL7U05>9N*+1'/1*0F#J>STX&#Z47D5.DX&0ZGG$]XPFH%?\B +M.74:8\+GE5?QK_&"B-4SVW[Q/;],;](.1>ZA%XD+WN8!R2K;CSD<.($Z+9") +MQ1JAB-%YH9_QR4=.5-A`Y`";X^%\,8&Q5 +MPA7!CVWQD."8 +MK)0[IQ-B+HZ*R:8(9XP!EI6U`M]A7UU)U`)C2[Q?E8KU\%_$$H*G/2W8N5L( +M[PY@O^#4N.>UX-3"X2`#2?T$?XM>AF]")N@%G!+S#@'#_?(^8U/L'N=;;K!7 +MKXDU"Y-;ERD,W!S+=[95I'Q>*$[&=8WLKC`.&IW?/A+*G-4'(IDT@,)5:;)_ +MX/(I+_%AVC")[JZ3)OV'\:.``[)Q9/R@;C(I>`\^AZI@G([M:OF5)"WUQJ;- +MAYW:-TWR;6$DX'$#G6+'9WUIF+)CX>N:):1K!J?B4P'7R:TQ1PZS&&"2'2T) +M[$/?&R`!,`1,\\:IR5GESFK19?P;K-"),?Y#[VCCO-L?L.\XF,EV^$Y:IBQG +MX::GE\':1Y.\DY)2@R;HD2,ONRC/Z+*1$?`W=V`\3Q(=\YT.T(I,\*/J/D;+ +M>1Z-X5."N@Q1&,Z.=!R_CNE==H);%S"#F-S3)IY\M6C&\\,0!OG^?IRN:%`] +M;MH_46]I^A51O#"#GZC@JTR8V@`E/7$)%K14QD'+)KK?UQAVC,!47%8]VER- +M@W"7M+G#N`S*I`/3Z/JG@(XR1I=#LI(^*CM.OA_OROZGKG\[_-0_:/3?IDEY +MQ?,E\^5`''2Q-XT0U"9L^WB7!N<3Q$7_$#=?&U`CNC/^J+(JI13Z+I(8P`<@ +M3]+,?=%MSU6QB3\=9A:1"DO4VJ,E0TEKWVVO4V=?WW6_%-CW>WL:,"?(XGQQ +M!=]:'<80TEW$57$15,;-<-EVX)`_1MJR(CTCW/T"3BGZ,VL/DULR51*5`$FM +ME6+Z'F:6KW379$[UR=3`BLM=4&>:%'*P:DVYF,3@]:INO@C*YG2X=>XIFZ72 +M)7DUD-2+`9S1]X%+W80/J;R7\H344)'%.!Y1/(U70T[H@^!II7&$IZNB(90% +M9&%M;FL)!.D]%G0+NH]*)F3L*30&'>"541'QO/!H^4X79W*=E*"].L`L/`M@ +MHZ3^7MRM3FJ%NF:IM<$K.BC35-JA.ZW!+$+H6X@Y[*\SZ@L&_0'1&25@V]W@ +M)K/A"-$D((/TLXQ)5`^>=I3RAW=)0]ZHNYU:E:*ZS7Y'R$(`U^2T=X($=[== +M%_15V=]&?$1RM44.GLT0+CRG#J!A\"6$@16M%XX^8U"S]`8XC,#B!W%C+N^6 +MEM8GK9,E(WLTG7IC"5-361EIQ#>(^B$3.67[\P2M*#8%V,UIA5EIP=J,DR=0 +MG/L51X0S/!)8-M44<&LM#]N,M:-$/-@)-""OF<,_+G0)B.:6`FX=-/$R;,+- +M@/TQWCRHC!V4EV>JO+M:HBD&N]V4G;T5%B%,X4XL(1BRT"?9M#$4ZB/V_-0T +M7RV33569!!H>!BT2()J^G]()#7`CRO@G<`F0O/G0(1F/$=VQ-%$:N4N@* +M;,2;)ZTHA=:J(VN\P0$2;?YN4<[NS>T[LEA94<6_.>ZAS0@E3#V(1U +MIS9ZD3ML>95^(ZYUHGE&DJB,:"QUN.,6@PUEU...W%L7(JV5N9H`<[('ZU+G +M,GMR(5VFH3B1`,PM(;JXGM>DYILO$UH*+19XL;2[()NQT)=M6NUZQ^>)Y\,R +MD?IQZK[1)#J&+\W"Q3E4B/+UJ=EKZ.?*\(\[J*"1[:;U= +M2,K*68M`/29\(3*87;1FC17TYT#(M^"]EGL">3)+@)@6U\AM=MO##H%BS"Z4 +M\*O5EE%D^9;P9I)4=ZKHHB,3O\ULQQ$FX*>-1$`.)#J:@^YB/]&^D11-#"S,Q;U3_ENI"A0,MNFSKID-RT$75'.:H58,DZ14V#PGG%+$N@HE:FI`1 +M_<08R00]@]>@;*?XX;E%E$?CQMN\"Z%;!K,K^KA:^P-:J&::19Y/L;R4A*?_ +MV5'LX+^2'024D>68-2&D=K`X3_"+B,FPPGC!,9>_:>5_8,_T3):"V=89=EU( +MZ8_H?S&;HLE[:[G^T`WB?PU87)K.&SC?&'(=*?#MQSA0&O*GGQTU,#(3*9(\ +MS-:^KV"KB4`_)YM&%;U)@-FH3!6]FX6\FC]7+M`[NTU@X_,_@F[^%^Y(4HL0 +M=!V/?H#Z%#PQ'J5C+WW0?*SA!%A7T#[J&55L-+]*-F1#L%ZY`&WAB@Q]5LH7 +MXEDE?73_*SFC@AE"I6_.CPGSS<;DJAS#J_69P&8Q80/X/@!CR-5"#E!19YU3 +MW6!^%&ZO^$Z%JF:%O'&4V)(T;(E-(2%G.%VFY6P,>?6FSY\Z+ABZ;>P<.DH$X)U\=.O"YV?0?$ +M?PF?V6STGP\KAXM`5*@WZ%^5V9=BJE*&&/^I:P9LY7LG-&A16\)XGN;N"@PW +M=0*^H*50M867P*JO_1?U)]4X(I#PA3<9,MNB=_-5]AB]P;F`4?!T9T3US04% +M:V*7L2)C88#/E/ON"0FYX7G][>/).W2(0P\LVM-?#W\2MBF.>65,P@_U]^KP +M1B!#C\D7';-+E@STR?$*F^)>"4\Y/83$>X+E9(%"I:W&=O9:SG\]X/!@V*KU +M+]*@DS6I5KYU2Z.GV#.KX`4H(%W/J%62=2`43H=3=FA=HHIDS=)$!GTAZXZ> +M[?4"THYKUQ=3)VAIN8?+'W+F%>NKWB6NJT5 +M*=4>UHGYDKN[*P`T77$ULC2M.GUKWK/Y/UC%GKBC.#\#`&QI&R2/3X8)]/LH +M]BUX+9CZN,XD-[X"?T&49=*$_OLW*(S/OF:*BD`H]F0W59?)WF0UAD:F9+@` +M'(8&G;;TV(KSS-L-MQ>L,"FPSJ$9T&0]GUKG''Y4I%%^LE.R=Y=\G:^1:ASO +M/GL4X)GP0]$LCZ,G4!8F=`(*-]5$DL-25YB$FED,OD#US= +MASF/$&9O#J\?AB/@_4?U3"X$#Q?!G/,0+NV@)ALKYMXX,+[6MYCP:JBT[@C, +M(GC2_QY?D=Q!5=_2#U$<'4:WO^.L*]&:(?O:1+T<&2+-;>R2ZL6^1FH?TZ+L +MM$)ZSHQ7>15[X#6JM.3`!9/[A.L]2`3Z]1:15"4,C7!L>BL9#89L]X'VIF>Y +MIESG1O6\XZ\+A/,<'DFMB,M2SV\!`%(H\;)5O8+1T^.-+R+[^(#]QTP,!@(! +M#F?TH!RWW,69.9A)R@C@!RX#7OKM()L=@0VC'*Z4N57;7/?HV4WX/4AN\R9DB3]SV9N!O_7&FYP/D&OO) +M1^SRM7#S/$=B/[=H!:I[J5_HZ8@Z.!J;B`=$("S:LBH&^4M:YR7`_O5PI8D +M_=<$-[R+,PJ3/^T)N^3!2W:TQ^^LOP2"Q2Q/`TZ/^:%@<:*ZXU%$ +M2Z']4NY00`&!T*]$)5RX!J=2SA%SME!L.4BMP5G>#HFZ3MDZAMYU7#;E08*Q +M!PIRSR0-I14Y,G3[EG?V>($1ZT,-420'`*F^9IPI!:M'P!EN]:)TAVX-T(,& +M-ZT&X'U(4EN/M4`0DD:1V01K&?:!/9UO$VP>43E9[H[^O,4@J"4FOV+^!&RV +MD75`S3%RMD$M=3KA?HRB&XRB]/\(8H8$E?Z9+LMN@^ZT6E^.*1T4&2,D)HCC +M7'04)E`"N$QAL5:V"]9[V4T#0(C2PS&D([69@>'$O>+D"8WDX(/V84Z!_T+A +MJ%6X'GY1@=^K16FHGJSAF+R2^T$T59?3@TBIP.\_,,["450^/3%+NCL;DFZF +MC+#=44T03;V\7W7'&Q_C"N^L8P0>+F@5.$E@P!P5:=\=H*4*Q-_:Q*?)ORBV +M>(_R5BO_BS2"&M9*Q*/>!2JEF1NWEN_Z;6Z1X!:EP4&UF!CF53*Z&=9[XR2O +M'PW7LN?TT2+/BN@=G/1)%3>OXCBU`&9 +M,ZT;NK.!'4DKF];$&&I3*HEJ]8DG>N%^G? +MX!"7(0+UD(5$=G("NUDIBVLRL-);CTCK7FKOG5#>*1JHK#^`(;_892\9,H;O +MC.4B2-]9YA7G1DB`;T+\3>8(KX6A*-B1A-N+]$H!XCQ7G*O%1OM^!.B$WSMW +M+S5"(93)GS?^5>J(CQIGDU+"8N,19Y9`)*]C-G8'6FFM/M:EL4L.KI8^3 +M+I`#T,(5^.U(>=-YC7\MU?!>7,*CSO05SVIEQQ1T.5]?XH;.T;Z3.T?OPO#( +MV:"CX02:4NG2O=^<9(*C81.RN$9I!VHCV[*P4S +MD/4@[=5LX]\E(*_?%K/%R"TL'M:2>@G`2\GQ>!'_.P]`?LTJ]&-#Q9\.-7,Q +MEDZ2;!?HHSBV.SQPH\'2D^7H8*"$:#CP_1^2;MYU7N+N29$>)@P/C:G9Q]A] +M!X`S2"B5#WXXXI8E2`]G$V&2'@S_IND;1/]":8A62/YUANX%96\,\@R:FKQ* +M;[!+D_QV$>\,;^0?P[P@.\%`B[&;X>QXU91<4^VTL_ +M\T*U%C',JM3L:OPX&$0JS.O;9PYS-QJ@#$#3ZJK(OVH`@YG16M1@G]'"#U)=;BX82,!L?*I'T[L\1LCLBY^ZFS5>J?QL*_"W,+M1C_A +MN2WAM]S-I<=)K^@#^FF8``$0N%RAOS(\:XF/RB'C([M)%K*S0/[+W`(6?B(T +MBZIL&NFL';M9TUU/C%-J(K&"1IW3A<1M3T40J55/6<+^A9?RP=\19/A$8T,1 +M[S[YH"2+=N*4.M5$8)(0UZ59=[`R>"0L`3_*&3>0R^5WNH"%7(JPPH%&<0S; +MO/-Z$98%_?*5G`'0N8U-`3G]$@10$?L$0W_;=Q8P^XD:)XB2,X&\*>=,AI'1 +M`K-8A7&%9*$U.<,$!S&U0['LI=.M^:"X%9)\A16N0[H>5B.PFB3\2XW&063` +M]/YX/^G]QEC01VQ_0*&8_G)P-9Q7+[SPC,A2N8$O!=UK2LNZ8'!?^`RNB^9* +MZKI.9E0=TOG=U&C2E;2N31U^<1C8T6@4SB`P^+_)C4@0&DIPK@)1H7(6:!)G +MO]3+R5?]RCMGHY06:3U-JAB@I"!!<2FJ1"-5*](3K,=@+77L` +M?-=7UH3;*!4%?1(J8^KE`%YY(!MI#GO:XP4]U=]7!3-T)_0Q^T<'I:JI&.E>`)G5?/5JMB,ZG6@=@`X'ZELT!3+X62E=U/VGI_FI'_4-W +MKNAH7\ZD`KSE=L%>X.'BOZ1*?J2D\A"`[*].I$W+O;#^,*FOFP#A'7!A$!AQ +M,(%?="@M9/]?]E?$`4;OYU:BF`^X=Z^^`M3MJ\CGD,>.Q;8]53"M?DU+"V]7 +MJB"UHCR_8C=;GI'..W*$`UUA-(#>WLCT\D"V]QE7\:S:2K1V[C=&0UVC^PS+ +M4A@4\NO%O0*MT&W!^-^\'DWU)R9(%N(*IE>C"WX9&AM?3(-,VCMA`+LEM\#E +M08#A.`L&V<.Q4+ON4[CWX-W1T@@^92I?@<&DF2*FO5.%U$I4YO8'?BS.RD%HO$%;G-+QENP'B7T">$ +MZE1A'R+)%'`Q9T]?4=2_XM36B>:MB+S&!V7U/S:?7KSWO2>=',(Z8/[%]46) +MZ=.*5F)$_[H?^[-:V;_G\E4HZ$]4%(T(5EZPJT +M>Z*F_L+/12LP1ZDW.%E9^2Q#!8`&N +M5U;E/8D^RDSK*UE6KJ-L\Y9.'#6EYU&&U;\+B*\=L+:BOI.=$?LL%C>I;[7- +M16*GBAKD5PV_0`<)Z+\(,% +M];UA#%`4MW]57!+D[,GMU:Z^%_-2/#+;`!-ZQQS#U[3$YT-5H2.BN*A5KE<6/WIR#I[7D\RC7CM580TZ/? +MH(,/F)RI@AW1QV/;R1:+^QMXJ()?8E%0]8$9,2JR<7 +M1?;PY%[*P(G%>^D`<]IQHUH29ZSDJ).S84`E.#/4LZ@,+>H4F)#R7&B538/Z +MUV4G!78:J9(%4=CS%_FVK?\%`3C8[.E9WH +M6-!;:$)2,TI-L][E,PGFDR#.Q4HOA\%IV$PB[%,]<+M>E,W"X0FON$(,)I9R +M*+65Y3^.7R`^3O_)^$CX[JSFQ((6[F4)$)42X/L>["*COH`XO:_RY,I@BA +M5#160R&3&2\WP9!\)2'_HGB*61"B3X^OGXMHEWX84'Y!D<^`P +M:?`51_2^0G8;WB2\M5:AX:]QF(Y^>%)0+"PLZM\]9.#B0`-:9EYPS4SW4L?* +M3M85-<6&]L3BZO)AF4Y_KIR\3^LG\2.ZXW/)5%Y+.RJF;,6#XN3B!L;5D'8I +MH5N%.'L*V]Z]%M3RY_[`+`ETO=ZEP5)?O*3G3JK%`:W\[O=AJ;:O\(K$TT.B +M+$=+`%RJ?E%H,F#2\4F'4(H/LK#\@``9G?IXT^\/$D%?+[#4%71,=`E< +M`;+P",%]V"+24H3Y1#$M6:!WYH5B-0?+DLB^I+M7R_9R+.I5?X5OG3XF97EZ +M9I#&+6)3R-OJ^/KGT+]X_K5)W=>&L,':7=+ME^GN?RP_D=+".34#\B*T$L`_ +MW(O,-40*EQ"-DV5`(^#N2TW`8&??\EU.:$=^#=6].W>B$MMCGXSE"7G&!PVRHT0L,6#=SGR>L(@P5\`G*:@WLIMA`"$0>"'2R,<%:.PN_ +ME""0TFH?+1LNS11"5H_U&F"H>8V=(;!YZIT@-\@U[T+BG&'_PA32)&G<0&BW=)YQ&^QOZ\>'Y\ZQ0"$,8'>BQ+0. +M9$@TV?IC$_WO&]9XJ(>1+&2Q83J@X-USE.I(27_G06;NYPE:N%` +M*+&DB<7"*H\TVBC&KI+J1.0M[&<*/#[3$Q:')[!*3P0,PMC0//S[ROB +M`6(8/F4SS=O[%$O5ORFC3MBJ6H/JY@4C\:'XABQ03J0F`=7[>06TT[)E/;'? +M[>65[1'CSD[(P\=1DE2>5OPKBZ_V&GY,06RJ?JJJ<%TVBCWCXS!.C*H-6UXD +M.L*X`1N#K7:WP!%VG(@L!:<_!+GC`XY(@Y1H:O)X>W?+]Y4+;Y)FC@Z@,.";M^AS<5XICSL6IHPWPXK>$ +M#G\'S#4KOK`CJMT`%B!8UEWOYD`]V!E][&DS-%#0E$;<9R$2_X0_R%@W3:WI:\%2J_1E-`M0"(%9!$MBK^.76&&T`<:+**>42#>?/ +MQCS(0ZZNG^04B4DUCL9XIE)K^,U2*ZL9J`AV'%FW<"+UXKNF\*ZG8RI;/5YTL21\D`5`#; +M(>A)@\9_'#N;63:*[R*<0((9>K-;C[]&2#Z/:]; +M137G[];P.9[,(@A?@V]B:Y\NU'_"_-,9[!N.(7[YNC+#*O"%(QQ*^U"2N1@! +M>#V69_3,AO5G`DW)O/HCL.8BO]IM''Z]93H19%U%`C+[8XI9P2A@"2HA-;#Z&.2S7ED2!FL<5@:&>O_E7O0-]\$!>0A25$=:.JNZ +M&F"X.Y5Q[^7_A0DT<1HCIJ(D5C(2&9N?I)&XWH+MGM#!0!%*;U//)N!F:Q(L +MG#SS]PK:*$^):^0[C`#+BZZ$O@/F5%@O8)7ULSG)M$UT9W'"QB&*!!F"M]X] +M?K;]ZEZL9`7G5GS9C'%8N00=JUT%=ZT++Q4:@,GIPT`+HGPEYA%.\T:^@2F)%_9(^U +M+KY%5DM%(*XJ"H;>IJ&`'4LW675;`C2<\(,:)B!%#8>0W^`0E0I&^M:IE.BT +MN8@>XO1?YWGFJJ*W!KS',_Z!'C]%CFCXI2TE=2$^3[1%P-)9#7@0I$(0/8@5 +M`AZK7DY5X4(HP$_O(?AV_Q.).'5IHW#-&@72$B*C>YN^ZE8D/OZD4T +M&#Z2^;#H,2_B]"!?;,&7>XLZ!UF]^B$J^=EVUF!$02XDK4>U[0OKM[6K@)"= +M4A]EN2B5>C7MLQ2_,QAJA\3LV@3-=2UD)+IJG:]P*&PE^[-Y5)M!:10Y>N,&L8'4>NVB(:BFU62B\SD$RU4"90XB"$ +M-W?'46-#T/5_WEA-=Z>G5Q.0^%PQ[P"!2#7QG8F_MND$X`FB\@GR"N.5?Z35 +M$[OB\H^O0HGQQ%V7/J%*X15K@!LQ9XX(DCW`$51+`7TF&IMR2FJ4^/#+_H?* +MZH`R2AP)LO250/7I34HLP3I$T)U13U@5 +MN^%!]ATOU;60QI+,UN<:6>?NR3%P>I06L/'JF9=]4!/;C_"^/2GP.AKY:!?6 +M!CIMC1;L&T9N9_;LQYJ*P*7@%?_LL3;'9_Q*D@YL2KC$6],R:+MV?RE[\@)Z +M]3)`I<<&ZX:28I<^PS4;)3,8QZ.ETQ2KN$Z7&9"Y)H5NA9RCTO\6=><':"UO +M%>,X:7W8P9Q'[D@:PQA.=7W\DBT1OFU4AY-"E`$H/S92H95PY]NFEO9.1>,OP4)19O(R +M"/K?I"0K\RP-CO_)V2&Y9I?\4$`H%([$8;.9R&"$0`QGP0`P(K^DM\L)\0*, +M:X^V>Y?Z=C=EY8'F7%5A:+^^1/PHD7DC\:-6+4PW_VT#M^]%T,C8#UP.9N0@ +M*EJZ9Y)J0.BX+[:O#`7B3#NM,\9N6A&&>XEX9KE("[7L+=S5/!^_@PZ!+QQ* +MMBN?LJVL^*?O/SL,M#C+W^LE.P5=4(*R: +M?"Z(A2&JK^YIV7'F07^@BY=Q00CNW_)MP43>NBD\Q1R4W-"!0_\\QL80_R58 +M=4_U=U^Q9U0(J+<7Y%O=DY$P\F-X6H3:JV!W153]P5`T$B.%O!@.4G2"W`+[-\I3J,B5*.]H>(8[+6M1FUT8.9T;6X2UZ32 +M8O\UT`R@PI,6D))&>OOG`$/@W`6<#/070;N3V +M]I]=>DO*0V:@I)]W8-IH`?XD9PU> +MK6?U3K(_D-QTRD7JG)](S-@.O-T<6%J.'+A!*P`:3(R"T"B9%0.:$`&YHF#, +M(])C1L=4^_BU\#D.]^?HI^/95^Z[OITR#RQ8^\,10Q/,<-L32-A&/+2&G?12 +MV5G8F\?()V7(Y^92,PRD\2!.5'/T#"2GK",$%+@"E$%A=U)&7_JL-]8T^C_[ +MA?W]6N2$Y823>7-I,]X&##\PX^>-2C/6PNSQ:CS^PA<83:4CB*S@O$&O+/`M +MV@%*O5Y[.!L5L0<0/,;B-:<(3,'>10BW#]VJ6&C)9)WCI17>=L[_KZJFP(;7 +MHV`!>V*W!07Q2U`-=ZH8_.+IZ_H@)`W3%.'VLSN+BDM1,.",=EQBZ;65'6*@ +MH&#B-',:Y`S53NJHU+EC:8E[&)GATMQS#++)B,7<[XQLZ#"?03!Q^C"0Z@K9 +M]8F.!4DDX9;X"*-PXLOU>MK:K6ER7Z;%F$H<]>1D6;Z*,:2V;3X;51XO7^,5 +MSJB`M[DTC.]I,`96N5L:F+1]/DX1-#7TDL#3?Y>2/2W5A`O+?V;+4B^PXO8) +M%T*VDI('_LFU#\R`S=U'291J\QT`N<:QR2Z.7M^J,^3*2SG>U^V.J@?5`:3P +M;Q<,XBNHC09D+=$<"WJ)&J`-?^202*YMPQK8T6-J3#PZW'X; +MC.=S`4^\EE!L0TC32CNJ+<@X=9D)ZWZC/B]%A[?X\6_IPHQBHB8@4?PHB!3M +ME]<59K+_]$C0U]5!3`U0O^GD5@B@E]^&E"+4D9)FE^!V-_,S2KY/O!B_>OFL +MMQFGTS;O!1K'J$EB#P;F(UY^$"T\8B$-L6?O*XE\G_#J4QVT3BP+T`NLYM78 +M<_JDX0P-$"QP/)Q]?._.E27)-?8D^2`7K(W-QYUR()?G+(N>K4_&*ROZC0<*#GSMU#8).#?+=J2/@4C/[I50A::; +M2=;$E*8KX`[0Q.Z:6KJ2'9CHUI1=7Y(^*_M1%2U*DU_/Z/J)\47>5W3=I$X& +MSC&"X'3)M3DC&5K9AFP,1P``SX\[RI&S3[G'R1/;&NQ'&U(WS8=%K1/- +MD_2!`YN--$:5UPA4R2#OMJ-[_;BSCZ5JET993RXL_@$DUE8O\9V918 +M5X8=48EA9.6$JGIOBMCCN2;UX;"AMECD/.()0SKGG[N_R=+`J.[)8&T@#`$? +MA?G]O=#TMBZP)?R0OO+^]D@&B2Y8\=J]4]\I-+I:J9M%ZDA'R,AZNCH +MF%=LN4WDT1ZVFX""$7]+@_!=*]8D#$0H!!NOLRJ^?+,O+*0NM&P7;/9H96:2 +M''6I>`8@#7$#?40OUQ%*RIG^YKQUF7)YRT*.#42C"Z%_563D^1P1% +MOQ^E2-.NS9!]MT,8YPJDS0'+BGNP7*I]=W1!SRO\6)%A`F$97^7,&B$ +M,>$1G&JZ)@ZBODQUF!QIB6(*%V,BO"D$7EOMYR&VPW-$_MXPLTS_*AK;.(8: +M$'P`'ZWG?[B[7Y5')L6&H[#`?Q'2W$W:A74S#@:`MI"0D;`U`-Y&SDVW74>? +M2=($6"=7P(?(@@]49R`_8!N58>S*&EHLR$B$R?XIP!/ +M!ND>J:EAJ/T.R"5*U@%Y6`H::'_R1<&S,J!3RJS11ZO)7PT+<_3GCPHHQ#R8 +MU5[X.G,HP&1(C+9PL>DDL\8A=B83IML9&&3K:%8F2NQT%P +M);_1&FR.$YHACR&I1*'@)*B4Q4>^RXVS_LJ5\>)&H#[2XK>D!3L#9\-[%A/I +M*>V.;Y?:=UI2SVK^$_7;XR@[$LZ#4$_7"F@=6)<[43*4$PY<6`B#5JO&90QE]9N63+YK2#8E/OR%W*P+`BI%1G#?GW&2EZ%0>A6OFE/P7 +MQ?=;:;:'X`C\H2TPM#S%G_\G8X8,X9K1(VON)V9)@#-UHS1<>EU&`N0S-PB3 +M`H%/DCYV;ZKP=E,JY)'%%_`)'1_['=Y#1\>$P9P4K2^Q6?LIWBTL**&@RN?_ +M_P.MY$AA>D(W"1:U%.&S^TGF?;:SCQ*7+,A[]SH&.$6M2;_4W +M83Q0JQ[#Z:*/_F$EN(7#>K#5"3).5( +MX_,=@E[LP[LAPNPK"]F`JOZ$``QYXR&J4GQDJKQ0"663L= +M3'V2,TW\`]*JQ<%S-:9(1DS7BP8Y2TX%T4`TI.`X +M#R4M&_RLUN1+][&]9GVQ.[?V+LM(0Q.6-2W.F"C4#UXC<#RX_)JA8L:^-946 +M)&84U(X'7D!*5"^`&')*+DW2PN6F$0(+641A&B*8-/%\#3JZ76)&M;X_CP.Q +M[#'-MM+8Q/NYEC139_*[X6.D2WC`M+T#2TX/@3D0D?335;F-S>.TCD5I;E]C.C +M*0A7!970A>5('5<9]YMDMD][638L$==QK_GK,<.$WQT8"AU2O3:H1F"Z#O'0 +MVFU&(S>Z93"*X2VO54J`CY5BU)R*ZOZU@./#S5O%+;*8['&)*'?#*/GL)_*# +M@#^$KG'7GI?:5B`*NHNEG[RL9OB>^V:[(BU\9:?U\:DQXQV)@A;N`*AFK%63 +MH8@G/]MV\LON-%;V^LT.?((.UT/.5INGOU[YO2(8)HF#XS?2>R5%D'`L5I9! +MD/]A77A_SK>;+$WN[Z/)4"M8XZ0DNZ;@]0G=[!KT<;$QK9 +MC-!6CTG^.MW,]`ZO_[=CCGI)FR\*PF/K%:[9<4TR/->RF-MPJ7K90@_A#>:+ +MO6S/K&NY?L]N/1,RZPE6JTP(9NO6:YBGY1HE*%9VEOK_>VU[/W[$]H6J#NO, +MD&-Q'$?;5KQR_1-##F'=3IVI,C+2R@J=H) +M(B^Y^C^P[G#+LY"?L7T)!>SZ<4=9$NF[BW#"V-?=[N8(;6626TXXSM)KS_#? +MM4MZB3<*]RUA@.X_DR"5WKWX=3(]*UV8G"CA+=.1LG&1+3/1!]F(0F-&F?]V +MWN&(/]X\H`,);_=`AFV[S<,?P$N^.\Q/X>(#8;J#$U#N7=.)78A.1EEK1)N! +M]5%T:T_4I-*3-G+,5W!I!OU1:WUW+*FY38"63$X?0/99!K_I14.21F98K!:V +MHN(NP[,V?T4$-*!907X4B76ZX1EV5?H*%0.@JF.(SH*UTN7V5[7[,5F>V!AO +MX87M7<"JOQM64_=>@.-]!_@U].R/U4TYLN1L-,+#P'&4_JLW4RFT-'4JLK1# +M*6G.DJH($@;,I"22"1?A0=JP0Z2ESG(7J;7/PB^H/,WM#RWS'CQIQSY._8TE +MOTF=,R]*\D9=J*!3JVTJ/9("*F^8E+\L6JNL5OJEJ4RW'%/X>[&:A(%&L/_% +M*/-*(_%'#,QW.`8TB#L$^Q:(X$?4,=;86[*#A6AHDS;%9RKK=`R.@)VN9./Y +M3+E02UMY@;7[63C#P2+;BH3#OJ<:WOU`2-PX9?'0VIBOG#]<02WB).< +M6XX6G!MOVNV^[0;[/QSF/\(9OB^QJX5VCUJ^2(4<"1QQW6LJEM5XJ)2/-F25 +M.9.S,>__JSX^\&M$T(>VD:&=@[MMB.3\;?D!S36Q<;H5;EQZJ3[Y?UQF+!RHU. +MYJ*?P*6HY7=VV6"HW3)RJM00O==\OQTND&\O?FI\_2-BI7Y1GB9`#P*5?G_P +M.:R/1/VT>ZI9AA@0K/;I%?%T3GEOPL=.WE,E#NJ`+S0$F;,99I=,\WQO^FIL +M8A)$:MN/AF]%04_T?[BYF!@]YMI?I%MAJ4<'\P,AE7DW75-:F*/0^+AF&N7D=B8_ +ML\629Q9WOW_-B5SMSY3ESTHR9C2&`ZHP;%B1] +MI.)P:P\US?6T!MAV.E3NJ*:=42GRGG;=\4HR&SR*EKPVH[7PW+51%CD=3/^P +M'P!W/SJ+FU1U+.;.':Y_D=*9L3,5X9;B0=)0GML^NC\-N] +MEJT563]Z8"?JOR4P?Q;4\SVLS>8Y6)V!LTV(MVZ;.'"%#8960 +M(K?XV(7XFL_['FQ6&3H'72O\",_QI<>!5%TLFK+=B6:KOZ=GPYL*XR6>X9@G +M\%=1[G1TJ\8 +MI'O(`%WL5S.0-GV$$IVP09\Y&!9$H:773)>;ZBQ>_]CS*SZEJ!76QZ*JBO`=%6CW/'_MJ +M`C2F>EN[GV4WZ:_E9;11:N=ZSS>,;()&W7#HZ(&$)U?.!EB&E4#"CS]%,)JX +M3&H.2Y8\M7[P@_\+R+!5>8(@EYT4XS`<=YE">5%S68+\Y=$J(*[72O22C3SN +M!/.P$V)U[IK),\F/S'5IF=3M+\JJ*!%KA-F*UB3+!9N#&,*&7:`8&G2EI==S0EHWDJB7L4;#(6N;!RR&/UJA_:R) +M)\?L\B^/S`Q)4D&.^'BC[!CD-XYWK@I/QQIBY"=V-"]=];`I@/C(<"+PBB)1 +MR'/.,_CZ`*RQ%)5Z=[0NRIX2`CK@==/#X2X#]_SD(VWFIXNP=TP=HVD.>W63 +M-W]37PL0G1?&D.?#D#J'`N1XJMJEG*?GAVC1:Q"T86H6.QMA.)\PV9@`P\[? +M\8$G#10I5,Z4@"9G6>3+169\+"%:573@_W!B5Q;RQ/]-\T/'W*/P>XD*IGE< +MH%!X_>*AOI#RJCE]S6D-[4^NYL-=,Q,*J\0KS.8)E;5X3Q7"U#9^O3H_B49> +M-((@>.C7A:3];>;/U3-LKD8`]$]@:>=PR+>(1%KFQ9Y,/N[!QI5E"GG>AP/Q3A(Y)6/$BO:-WPF/+9$-#&L-`\_OLSSAM*M(E+.`H],I+C(5AMP:5(X +M-T?6B:6YBU2)M*QF)G",`\L.BX'AGL3_0HO]=XKT8B.<^WWG;F,[\#A#E;6^ +MGV^7E;.R=!:YPKF$Y\+#,A%,0O@HKB4I,Q62P>5P_`H%.O9X6"UMLT>DTX/8 +M,C:"J;:Y>"']2_+R[LWATGKWRPL-U&M/9XI!2:^3_ZH9W^M(KF;'%1QJ>;8( +M$4A5P;>OP/@I32=($=[AMR@Z;`#;@H%VKO[<#.J;W&62$6WY[U[57^D&M3!\ +MTI_=9\:"ZIK_3MWL4K,)=/*95_TZ^A0[W>[>9O!&2$-/*UGME(R9460B.JPY +M*4<6.[(NDK^#_QW\P':(Y=::-ZY?.`FHLI!M)/=RO3,A,=33OO9IB?NE(.1J +MLVE6.Z+_D$M3VJ-5Q&9?`E9 +M3\,"VYJ.'L:/O:S?@TH"(Z47],42K..91SR;OIE^D^J/-$>%Z&=6*D<#)YWX +MP)C3Z&`9R%;=EE89JF/B+LOFI@2_F8TT'?N +M-]DX'AB')5TF/Y%1M7G0OY"\64/,:AZJ]9QN.3'#-[/DU?6U2HCWJ\K,SCB. +M)W:7-)9HP[S?M$U1$FMN29`:^Z&S8-699F]CW))_O6T2(3^9H$L%7(MJ]<8, +M5H_(!]UXTY%@&P`HFA!Z>?`3GO\"$7";YV_^(T*@_8Y=S%AC`\4#O>J$,"%7 +M]!@U.M*U)S=+UE/V$N?DKI0[,NE'WZ#,,'!T0CKI`,$H[6?R+>:&"_`YJ<2M +M5:;A::\;T_,^&IME+G>72"0(Y?5C:L\>MPB!TI^2:@`8Y2+Q0R<5EDRC^TF3 +M5\)L$K98Q$!J)=X`=@^+OML@A0,J].X?5IERNC9J%`.;I@%!';U?>JN!`'': +M9+*]8M>!HYD':TW3W;RD?;,@09I>Q#S'-Y]]))9@R-775BC5&_>+I+9LU7U_ +MY`D_G?H&-8Z%`05O"VRTW:E6]DD',XT/EP3&*/G]$#[_O<@30[U7.UY#>.B= +M*E5UR:!*F[H\5Y*.A[>V:Y'# +M%\)]T=.+):6H6AI-_TK2A*-K;'\[CT+.B^4\(\;^K>58H)F&MDDKK%CGO?ZG +M8E1J@T8B9@2BZ"NZ_-&#.WN'N?_AW(Q")<)P7>;%CUK^ +M"EJ;9?S'"O1+#D)6FDX./*Q2Y-M=FL,6#JE7/M@$N4=M@=2(BU;8_Q1@5WX^ +M+Y3DT95LCEZXR=HWX>PT]TWA;(V7;7-2 +MR=K<'OW3.@F&"UO8P.CP=-*?A4I49QR,+Y)\A:)7*V':>\1%47Y$NX5\(2[T +MV$LBX.\"`%"=?5M`=Z2_5Y3I9B!>JNLO]7G8Y>-&L@5MJ)9H-S:K8&V1T[() +M<&E_]&LX#*$56Q8$!K!$"P>IL/.+",=8@,)?NF@:1!H&7'T41J,XQ98E@BXI$:3GL\"D+H*H!BZ1@T%FV +MLU]%\5+=@2QTZ5/*-!RIZ<8,)3:67\$L'D.&J#[R*A\Q6!B0H@10'&:H42IC +M>?8.D!U3F/;]D\9TV\AW9.`&B(0U8IP/D9*+9?KG?@@SY"@$,3AC +MKQ+(9G$VA4Y>D*#-?19DY51*6LO"+3;G>`_I`NMX?SC4W%U>)?QZSW/K=8'V +M\WHN@=CO$4^2N#TH7VR7@G9R:4/F!PK\XJ!N2#8P>MH)%_:*&`OR]`"&U9/< +M5X*T\7)_&$/GY4XPQ!(#'#,'&5YH6CI9(H[-6L?+,`K*AW +MJ!Y$]'%P,WAP7*D/8?>RO='CEH$M'_MK-H9"[^3O<4X'R%/9* +M&.W'*(@'S3E<"%1D8I5^N)^:I%2MB]^B%'*W.FLOLRM]S3/6Z.+1GU] +M*3D7$ZQS6O2N(QQB,XLK?D\-7\FC]N4S@4#!4;:<'::Y;/P5X<9T^V><9ABYQ.LL +M&D._.AA>$87^4OG5J4D.362Q?LNMZ34^*QGD;ZG_O7D.&L&9RUVG0MV`)0(U +M0[1SE,M62HW5.H6BN_9]3P$:K3#O_&#+\1F\@,6MW3I(*D$RMZ9GA"#WD#'C +MOM9>VB"#KYWZ^/9@87Y"1T4)&1PD3J"IDC=E,A0IQJP1/+"?+L][':902AVP +M4IR`R=G;O_\[!R7'7I=;;IM[5YC),@[:K%Y;0'TEF>LG]9M$>F=ZJ>'% +MO-CO"L7`$]`#D'EO+N<;XI.`PM!HZU;:>NN@*D8!SY"C@J;#"G95,T(9J236 +MWQ5E+;3G'!!G/P:E<='X$!64V2X>L7'D1T5N1:\4Z!V +MP+@NC8K\??%MK0J?=^0;5%VAUC3;@H(2P8[&B/H0.;N5SL&^;%:I%4"GC#K` +MX!7OX(J(-5KARU(%LO>NQ("*CK)^V166@$D\(80762A;K7U3JUBXS\V)]T;0SNWW43RX\BB0GR(0^MT\?HQ=$(Z125>8WAJ$3:2E]^0%: +MRHHL*_(C:L67,)BE@$NW&0^NQ[=`_S1+FO\QQ.$K#YV#@6Y:!U!+V9_G8/NL +M49<$WV*ITB?>^CO#![HC9ULZ$B5O/,]/.P:E@++O>3;N7!X=(I&XS@L.B=+: +MU`.">9B4&_O-6@I)RF[+U7I\#P0)4*&FKDS3)Q2+Q-$/92">D)8P@`0\[V+I'O>UH]:D&V3+-T6W\ZXV?8\7#VTIOX*UE3DG9TBDV9I4,RQ/<:A[MFY.`>, +M=[8NHI7'".TOT6#G$F(40C^(MBOZ!WDP!$U/DXT^IT(S0J1'JL4T%'E;CPFD +MS6FQ72/.@!]VH\5KR: +M9\-U=ZSN.UZ7#43.8CZ_LR*9+R:*3N'7_0QS33J27O$1LQU9GRE0:7FZT^G8[9A +M?<*#".Y7DG6Y/@+<"YY/UH_%K,K\*B;H)0H0G-_NV*>,<*MI2VL1T;+\> +M$CV"#\Z1S=;V$:ELFPC1*D3JI-@]UZ5J9F_&QK99L\_5@,PBHMJS&%FZT^YV +M=RVEL0.#CJ'<&HV/^+8$.I,.Q36;(JY.B-7PMJ&T^12?":$_>A]/EB"@',.J +M#3P9\J"$C_>$Q2G:5^YK@:KM?:&;N&&=D%T`_B@IPGF;79N/SO\NKW0P.->6 +M46V1[OQ:Z2JC)4&-/SQP_8IJK+"PX +M*WP(J2)O*+5(P88LD%8(C+#?/S0"NCOJC^K@'+OZ)%,K9F.1=/FG#2H6G*D' +MK;(6-M2H@`X!+5CPIKU8KV,:LAP.STZ8(L60-0+31Z'>7HIP2A85_=*MWJ`+ +M04U&/U53N87%!/2 +MI74:RR1*^N>)*)C4GRY[!,$E)0\@58Q!&=F4[H4'-'BGX<4!ZZT]I\=;#;\XIN: +M9*@IG@49F-XU\,=9;3W!0OW/PO7%J`7U1?L;2L39@>4.Q?M`(GKL*B.\DW.& +MVD+TLU>(RL+44(?I?DT,T0J,J#OK@R'T;P0*W,QT)%ST`CMD%+84CJNZ*FYV +MA!L3`5'G;N@P9]23]P7(B-_-ON1 +M3LZP3`59I0AY''-8/\E*0(S?NQY_,,\GXB^2./&FQ0-ER7'-_6\#J>PF069YRS +M=[SU1(*R"_UZ^PB"Z%$`INO(B3+W7+'>=_X##F0L`G-DL[&+(@90#(R%05U+ +M2LJ#GP[@A"#>#?LD#[U0C_IG6_@IWY`H[&Y:HQO!@$>^(TUH*5F#@C$JJ>/. +MG.V=-4'@9)-+(!4!W.?_TP,J5A7:JI@VFZ'YHK%K0%@?# +M?M[<1ECNL?5CS`3?8;8V75.!W1TN\X_C\=KC*OZ].091,0ZYS4?^C($614"M$(7;. +M^Q=GNT!38(+_PUC\:%BV0/9$JJKUHK@UO5(*TH=".-DPE[04"^3E]3`3WZ_] +MEQ+$]O\TI>SOA]N)U6LP$`HH@&=X*6,\I1^#+R-GC +M9#`Z@#?=;?4D6B:LBC.\)9H0B.+,!2T0YB<&*S[*L*!#)@IZJ3!5`-+F2TO3 +M@MHH0,(URCDI3RH=W0W*4D\M^FP/EL(N": +M5*30@T@E*X.M/-H(MZB_IQ2CCZD#7FNQ$D?$@IX=40!F?3`L0S0I%$I[:&!U +MZBNI2._K1FN"N>DS#OZ"=DT$@N\#JMCJ1Y^BS1N;\J6\'3#]2)^P?P1S7;4H +M')K$U,3\Y:1)_3M%*)_!7A`,*:C8BSQJGDA92@=%UCG`O`;)*07MT3%.W)9R +M_BV'YU95TK/1P).)0WA^L_L2,]D5]!C$L8E,"UZN9"V7>E2Y$9A'$)LIA>3= +M3KQ=FI8"RG<_JP2J1?LTH*H.>E0&4>NQ&]=@SKT0S:%BM\XQ"5KW4S0&"6^` +MI\]20%I(\4BSI963I@]@P2'SLV2K-=T-><:K.S>0]*X(X#4QSTD62TW%1.D:"!!K74L%T +MDT\U!0.'&$PG0*BJ93.[9QB*6A%?"BT`E$EH4A:M>1>JLN.OA`1$D!GD4X,_ +MSQ4)6O_,Y;\W'TQUQ5C+,)K\O;L#&PLKO+@6KS_(4B5Q<5;MV&,&>,%Z\`

    AA3\-O8:=T2N9J!9)IG\&GW/,1R0R3]RSF]O*P1J2 +M5>`LM^`E.?<1I)_:`M\YIIU,N[M]!9]K#-,RHH<3BS-CCB-X53LO<-LO$1=+ +M7'$8MWO;>S97S&M28,E80,XY-"ZKJ[OGYY3_6E_-D&SM\4_[Q%`S%KXN,19; +MC1GW0,M:YW./[%<-_#,#%A;$!5/8LLF/<=_U0ZOWR!+HU!!')V+&ZULOJ76> +M+P)>Q:@&O$*`CAYYJE"-<)GHTZAF[AYBSE76.(>P?]AHO65<@B5OKWP%YLX:?6+!<[<'ZHU +M;7=1V0W7.EQS%>.@CC^91,NI<#H[X,R18,OVE,V'CIB*_@PGWZ'I1"?BV_H7 +MD"CJ_IJ,&1.1'/):+*(F]/:=$BV?S'*1/,-)I*J:J&9VW>\($/@4,;J!@3#" +M8MZ?D.[+!.1D+<-%U4&X=6Y";C/G3ZM!TP:"8X0[*;Q!A6RHC/(%T7N!#USJ +M@@C(U>78J7Z,GS^.LYFS60)J7S@#]%TAHG152@7>6E5K>*49+U'`7,\+8"-5 +M/5TQ[AM(4I$OAY^_3/GRXH,;4W50O@'G7-P=[_[*YI6IJ\YCD +MIN3;G67@@X[>\`DWQ01L8I#OV!-#6M4@\NZ+/8A.NV3\X!="9^)NKL/@NO<- +M.S>9F,WP1FM^/Y`9X0^"@SZO4N3F;1L7(/HX.K/>7O_'E^F/-;4O!RX>:1[W +MSC5#0V+_#(F&)5PD&8^YUI.BR;+)9"7M,]6.Z9H.UC4JFIQ8%HG>ZA<<8TMB +MU:S9U-4"Y,LH_I]5=&\L'>GO73A[*+,.)R0PPU/VMXDP(9RM$6?VIF\6NTHT +M)$0NO`K?6PUHU2/Q%/7,V8D'IM%(2;""S%#\,QXR_LWD.T.O!8,#&!X4A-\& +M2S[Y\*H0QOSO7<)0*RC'DM@U)#:,-8W8^NANJ6"FR9#))'NG$AZ)T5;$?^;8 +M#EO_-.\R53LJ"'5,0=FTP_,\+D"/W%O78JZBR?'3.J6-]=,&2'0GJX$8':)< +M,3;ZE*+CXH@/K/;P"]Z\6QI]VRIL/<`J.G,J@VA6&0?_LV"-IZ7]E9LH]>^* +MK2B=>_/CZ*LV%#CVX)"-\QD#/2-?G+E,YG0W3Z[+69BF>Q5M.!3J)3AR7]F3GT'+[)2U3Y9&H[<$8GW)*%#^0O93 +M'8&]ZNV:O"KHK8A\MZ`+)V<7`SWNW!&G@$H=UF3SF0U:[77.HD<]"N\!HO$: +MC%KF^]CL"15),+(?J.H&XBL$.=GULG2G#B+.0H50"KGYW%4%G+`T+=A5?5T7\'./?K)O:>Y;"O!8E!U-GC`0Q5$&K*E(KK,8F% +M?K>$TB[<79R<4K@CE^%:@/?9(RTZ[&Z9\@2GU41J]Q/?D=A.CY<^%%(PW+X- +MNYFACT*_L1A[/6=I^1_D_HZ['M!1&D^%:5;9(E`O*Y`M4Q))6WJ +M&+";3XW1"LNSM-Q(L\^2$N5,NRH"R:Z)9?D!G!A+0^U,[#K!8=*9WTST<7SX +M<`^KOJ#K]#K +M%`\;;925KT'..N/*[XV7?>!.*_P)H\3=#`#Q#T9XQC="9RQZBA +ML+?VUCY_WSK&EC]H4D3=2][.OSN9/##*"LR/[+:J$V/WG'"<^4RMB28EH1H6 +M>Q>`)9^8_^F%5X%ZBC^(TOY2BGACP!^O\!1'>GLM[?($6,)T(]BC5?@6<:\@'OQ]-9<=,(8V8QXT5E@BV:LMTN]W5\-2::> +M1FW*074>UEZJISX>AV*SW.&HUO9F10FG_;4W&#M;=Q89<_D2:.D^X"'N30,1 +M)5+_Z19S=H;:4CRK,4`&^"KX<(CX[6`&;3Y,#;%00@;R@C,0OT*&W6<[F-)M +M;4P[F)]I!YC4A@9"+)4>H>`[ +M";60ICQ-J3$EBS@"5;U!WA/:P3V.92-5VA@3=])RL&]]>2F*T@(K?"`'_K`6 +MO5B+V3%0.4PU6\""B4K8=<>0E_2YR<%"WD)\G31>RE`0`X@;L/Z]%TQ(*AA$ +M0.@E<7Q8M/=II!JPQR*"[D,OJC"W;T9:BK0_=6]M30]6CB;V"9Z)2[(KU6J& +MT`6'L&;N)EI4RC9+S4YUE@R'IE/>"N;"C.XTUX8RR+/6OA69<#S!LM!R+Y(- +M_(FE*,B#>DS'(*.77/>P>GF_TC8(V2JX13)0,N`9[GQ]B[N8KM")UZ96,$4< +MJ[,"K;*7*+6ZLO@?/\BF?@G7OC*[W15PE!96K/31 +MAE*!G.4[8--0F`Z<2)H)A&5J4+#5]-YJ%ZAW*#)K6>B+,>`5P^@_8&T\F"?U +M^>U98:4]7XA_R/[=PNU0QBP-B8WC>L3&5=(/KJ\F0=&:,CS/=H!VY('BD7!?5(;53/3Q6/. +M:,RLN#\J7D:\\BQB<+]W;4B@7G__)YT3ERMD$.^;V4<0&S.'::RCR>N,I%-7 +MCYNWJYUG(K$^V/@VUU\>+?C'2W*H$Q(471&\JL&.`V$I?=#F*D++DGEL= +MFG2@OYU,JG-)5<1ND;D8`&'/C9I\*1@QIWL))U*N +M2H.7RI=GUJ&Z\(,J5G7=7U?V!6NB,%G>C\:]C4AB;2-OA:+QDU6:@!47#D?X +M0R%DZ53BL-SZ2!0=8D'W$<%(`73I!8T+8\P5(QA>C@HOM` +M=[99!KQNY5+T`FNJ;T-*U83MU/E$3)*Q>\Z8=B`@]AAZ/V]=X]^WH:GYL<8@ +M(DSU,A;DCL83H@5]%T'UESO=.:@N!-29K?@BPNS61#"/EEY?PC(92LZG^U@. +MG09U8RPAZG0WA^;-4DSG&=*9X9E1@JWSS#=YM +M`&I:U7&J](CETVD'MA)I;)D<";1!B.-[#<=7-='0=L6("NP*,)LF@O9%`L\1 +MBB@+7^3CQ^'D4/:60A_;.B"ABF(;2Q@G'\>$`5(#8)0-3EO^V\SB*J$8MT.I +M^\V0:ZJ`LK7)/9"\^&28HYXH`C[F:&246OE8M>%_YH[[0\8FEI6(S%)I^^') +M!-*>L`./.X*4CP0J:N*"XDK,HM?R=YA2=(LJ.P3O:M)8MZC`0G0;[,2=>(]] +M@RH;"[9@XU5P)'P@M><-5$J_BD\8(19NAXW2X)*@JKQ+9KZ%'K@[+ +MKC.\TA:)A$_VQ!,U5D5O>@1Q01O8L[TQ4V#8<`VFEX5_]#J6)1:#'F7>0L?R +MP8R0N9./F_RZA[W8:IQJ(M`AB=WBRK[ZGU$I*E$`!9'%Y\KG6,?HX#O1HX\. +M&>=UGW2:!AR#H5"]]0\Q?)-;F+,$-A'7+\>_4!_;M#O5-,I>7$/$8390@P0U +MI>WRY62$ZCL?S%!1%;;`T&(I,@XJOG&$:Y8=J^05(<8B@8UP39VUA\OY2C/1 +M/!0`F>2T"CIIVWWGF_Y3Q)--;+(:B/O4SDJ6N1'DY7^S +ML-4:3'7+2&O<"25IG&-KV9%F9(QNQ*Y#!.K":Z=@C^+:H=&8SS00PRRI+%&6,I)8I_U`FG"L'`" +MPM]0G.JI&7\`-G<.XF0:&;TGHEB'=_&#*0I7O^'MY(H`QW[(78_\GL)['M63 +M*8/D9\SCDONR3)S>.'/C[`Y/;8ZH1-S\-?2"(7AO.(L\4RL\_\]FB#RD"I/T+,)@%3K9$/#G1W?7%PI`K?-.U!>P#)MR'U=1>7['$R1`V$ +M>FNO&#.BU9LQFJ4])3Q?^M2MY//9<$2/;FN(?>5SSN%H><-VN%.E7JPU1:Z? +M>O77P8MWE!A43G)3UQYX.8T*2;VHPYG&8/[8->1_P0&2MQASBE(^(1.(+7>4 +M_R@R66).00HN:(LT^(\5^!_/!17,,NA0XQ%M]02(&[D'V;I8QG6>FHCY)GB5 +MGI+TB4$4?XP\"<(VG(@L*1$[7)<-[-."\@=D?+-DNLVHBYI^(]\C6TE;3<4& +M4JA;"6\SA+6HF>$D,T\M55;_ZJT#ZR8WF3GOAH(6=T/ZK7N.?(%C!3BA#9-% +MSMENQB;:\_T=),MWZ`2U&3A;R"HIQ#5DSMBL%87O:14V'$O"^ZBLQ%*0\&X. +MF^8Z4,3L.R<(@\V3':4RO.Q\\KM/`F%O9*G07.,-?,8@[V&#H4,-_3,<'O$E +MU^,O$SJ;U(U\@[(+D,-T+JPC&!V#/[JIBY7S172T>D5[5ZVLYKU/7K/@&A## +MS>A&4DM>[!^![C+/*D]1W](*QV51&80Z*Q+4"^94?J&PH!?*1@B%21W^7FF< +M)ZB=QP/)**KK5Q4HVI[_YCVWB(ODB4+]^L +M-]W(7U*\O26N7->$*].# +M?&T()YD(G#9D=R_8-4C=@#HFBO16BV+T**)&Q1>9=H0)+GPNMX\+YDD8&`4? +M5S[>"0T\57BBDYN<0+?<45M1V(T]/V-*APL9[E_ZX1$E6;!^H8+-<''?YA%R +M=5-<+2?)@N%#@R96D2,7-UZI6-"X@T>#17EF$*B)XL%KE:%A"BBRT;*TP3PC +M.YTR',T]9VP[8S$#Q?+-J]M+5\^0=C<[*/N`I1'T:V8;1 +M#3B)63;3S5!#3%U6$55B/:WR^T!6=87P:'"#*IG-90)0@ +MB[_3@8`>_"?`D=R.<(\S&-)<<`RUWW$*2?L4/AT$KE'KI"7`!\6B?$L".50J +M)GWDJ'9AOX5K>=I=JIMC5M7\VIY)3G3^&;;F_T5DJ!3G?^?K.!YQ5D:^IN95 +M/UP;&BH!A3?&EF8*$+D8&D@HFE@I73D)HO$=)3Q;![[;?AV1**Y'^W8/H@R& +M^L1U/7$I7(7)4?_YQX8G&,0.X5J6>C)TA!-E/YNU[(-%C2`?W)?+]+VXQHQ% +M!^L:E0X"*V3RG*01>C=OG6Y;ED?G?(KQB2TNFC,NN+ZS?!VHOMX05],F30$X +M,NIK&\U73+V@X'[]00C57*6X+M9H4!A_$^3:>]"M*2V=6%9H[>M[21,`N&@( +ML";DS4790T:E2:Z@;H<;R80[4R;Z8:4#(VJ3KH$VC%U0,DSLMU=GC%&5;1FL63[TK'-1;4V^P;)?(X +M0P28/(;/>SX?:C.+:/9V5?[-Y(5^XW.E_D2%'[#+#-H* +M0!>Z2*!B6;HC_1<\PG4BS9-L'U/PGF:=3G_'%5<)^=I"KHY/S+\1O7*`R[RU\L4R>4GQIN%3H5>S<8QG[F+%=HI>5W_GO]A"=,D%Q] +M$RD<02:^CY?(_I95QTO>@%]T1AR!GHS>AVP7<^'X+]R!Z?)MQ +M5OY1=EGN2V480Y(020>].68SFL]?1^O+?+:]4.L^@"GC1>Q(\9$B3$RK*S9` +MK#%R%A(#G?%PA*O#O))`1$/M#52?T0=#JBDF&C,N0=`%][A\T&_@S"W/LX3+ +M7&:.[T632'J9:VI#*9KB=QLO#UEZH82^?U?"8]A\/V22#S37A-6NB[Y/8W]% +M#M0N,+DDBE.-@YF>G(7NB3`.")@%%Z2MA_BAJ7ZU=1+1IU$P(#=4HM6--G_Y +MPE;E?%;WK%K19[8CA[,WU%65#=12_NF%SDNQ6.YQ;J'N,58#YZ?!I.<`=&AD +MEA +MEL:,2VY&-R@!=?&67.2_:0DAFX?.\6+)(>"N!2Q%JM/?(LMW3%,X9?'B9#^_VCL +M^PRA4ER=].ONU]S*,W$SP2FM^0TGR`;_+!&6.GB76HB_'.Q8X)GF5)I`-AP0 +M'B-T'H=/C#65@K6.R=SF7/@\6X`?F@B$,G>]S!(B4;`Q+ +MH?$@D+3LVWG_=P*9!.>2'*MTH\G"-RB&@'>2$<7+L0NC`F5,,35 +M6(Z-<6!3*N"[NH,>:&K6<_VGP+M5(P\:&B-[#04"4OB(-NK6,5?,[+6_A@.` +MHV(GAQ_'LY1M20V<54'UQ"Y7<'%`CC@ZLC_L+PP;-[IR=R*W\`9!9`%2EA4% +MY014'?_A`4RSY.J@X"?WN-FN2?:C#Y(#Q_Z?Z!9K?:GE7S)3DG# +M1.,:'I53*A._<<>9*-E/]\>1"^M@_<[FCQS:%?0?PQZ4J160]=B3,TJ<13WL +M2FO7J3*'"+%238EKD^P?W?0H:1;66,A(3&=TZ-]4X;^>(E([(=HY3*`)E#YSIC@WT5X-%\!NG"H[7#X:6%.'C +M=9#N6C%1(U+75L`F1VXD2P`[J7MMZ2<-XE9OB:(>OWKQFE7DYG' +MGIOND.,;MD"IN^1ZQJK9YOPZ,)!9.FJ)(MLR>==$B+US=SHD,"=.W2M5QK5. +M`D->Z9^'$EV$;N^9/O7.^[OQ79';SWSZ^:CF(:D;=;^(VIT+0!. +MM7:%_]^J]E$')%70"=#W;Q'9A +MF&VISR6=JF?0B1-6[?T0B+!ZJZR`Y@%PFE!BS[32EA7"PMF>="?F[V<=L$16 +M0UDHSN#JRP@'`+16;>Z)!0O8L(2/?!G2Q[YUP,.A01)W*DA&EZSE6Y73W5%8 +MQ":=<8@Q5]RF!@8;<2A4^=XP[NHM^7D&TP\M7.E>VE[PUG=[W^&2EZ&WL`V#Y4CH&?\/O^68 +MF\3&\AY+CM>IL$VFGM3^*V!"L6CR&50%1'4U6WJFK-5M5?G$R.E8`3;8&8KF +M:3^'PH6T%4BXO\=+R7\&1;>H_RZ@)4HK<1O]Y;;J1H4&>FB&M%*[_"@]L:N? +M!EB(>T\T-8;FN15*F[EH9I#*4O0$,:TV^94(13HU?)LYXWB8!&2_*S!#KF`G9B +MP^M?4G["!U=*HZ%>7::#>U4&/>M$X[4WBH^ZPN0C-\VYM&3:U-AUIE,LE4BGM.AXLKLK8UYR`0%VI;P +M/V7<(OSV'7D?+/QH//I?')4UTYX"U17-4A&K$4K$I7[\%0=7R4\;87B!^UJK +M+:,T()1=5?XR%UE'0\YB/6ERSO*QQ<&8.,R,EL(;4K+@I*JY="NP:*;GJ1^L +MEW]E41:)=1*SU[AE;9T1W_+/#D_V5M]\TRS:=*V=/.+W!=7E,@O+>FB>KHM* +M+$0[X#SW15I#?@2]"YT^Y;5\%?+4M#K,1X5Z!([N<4^YF1]&C"]._ENAA3T= +MM_'AN16^D<\D[_XGGJ??#V2(D*Q5=9E"0BACMJ\[Q((B9%=)6FE^0 +M+R@R((C.'@A<:\.7'6Y'_,VL%$)2DEA.Y#@?LM*3T3S2H_SXS<4#YJF;4!$U +M/08"U&XFC^+%+Z?\1`>T<`LI>X0AG5FBNX%1EUYR%$3WJ[8[X3*%SUJWE'S1 +M'%WB%#]YW368=4)<;&+#1_VE-&R\'4QH1`2'YB_!MV@3XG:9B63)@4@]=Y-E +M$%7;\'%AI7YZW0IUH6@1]YFWN*\@DZ:B39*EU$\Y7OY;-<"X(1V><<(0(Z;S +M7%BV=^Z_'`Q"-XV?YKJ78N;N9TNF+?89:96=&;'F,.=GZ?4=7[`3CHV_(G=3 +M/+Z=B($^3`UOC:LU,P:,E)@G +MK/(L8Q(,HA('J0E4TOP>Q>6"_L0KPJ*0JF9!CF#?1R9.RQOC7Y%.CAH*Y=1. +M+F]ABI!%ZU7;"@D2AJ2A1*%^>5QCXZ1#ND+X$JSX](CST2.1$AG(UZ6')C%< +M[);?9JD26GX4`=C1GM61*=:M3ZD.)]`T4`%I>VLF=A>^9SH.L:CZ26F??_Z` +M1-5]E!$!%1@:,WQF4KY5Z[A-2+NC3$^N\)I;#.!-[G/*%+Q#`]#S9U&C=KK, +M*L&$SJ:DG0$?Q+?4FF`XU)H$*3SV8YSL\^3DID,`REFJ9GV0#,FJ]P]=ZT7%Z5J?UEQPU.,&8$K_@"79HT'\_N4EXL:PP$OQKJ(F%KB-VL^J0R]> +M,\R[+OW1F^(!:4J"ON&;;TO_)2_`.64@]#Q4+`"9]C\CO[XDB9^:IL1IQ/ZN +M)3CQZTOR<;R'N=8YW3:'KD[G:\;+;1-&/80+G2GW',-?>3SY&W.?.K%(,4T[ +MB'7RF*NC+5)M31Q,75[+'\0=YZIMT.`DV.EIQO.=T0:O*"/O)8/:O?/O7X"S::A*]&XQT/69.7US:?]9;.[WVU#Y)H'JBL7 +M71+!8'DZ&?I%8H4NDBRRZV6];^:NKX^&N>'94TXB*NGMGRYL.\2-QJC24[?K +MQQRCU$^[P"1P"8]KX%\F\?(.ZW8:SDVP*#.]0+:Z@S*]`P>JI!!,C8J^^'=? +M)[FVB6IQL4F3I28$K6FL8C%_<(5A&F-Q1^MLF>GA7HW-K7);0!;XK=2G'VGH +MP!3PGR7=G05V,!C(_G%XHNU/`N:J6`-N.2U`.\HRK3!3LX:!E$MKKW^[7-DG_FQ6?^>='1>_B +M,-A6.M!0:PRL/%4??47XE%TU%Y$2JW'K*N-[#[+^V-G[JMQQL^S%=!)#3(AJ +MA"=/>!QO>9ET['/%LT),OR/I'%IS96_G7&L81&2&BEM]]/_I\EKM>AGCY86E?NL!3HRA(B` +MT=I#P]!X!DL58<:"N6MY\FMZ%*2$(`38;CBAKG0-63XB!.+1P"DWH:$AUTI3WJ&V0QYG&Q:G>Y49"C/`YM5\)UUN\-/4%"LGU+B1]68QDU!O1@? +M'"WR4=ISQC%<@>OO\&YNMV2S,YUO32K3PGOZG>VJ+MF]23$!P:3I_RCB$T:K +M@$VFWAU%'380[,E)6^\,[U(6$/?B3?;>YWA9^`B):&XTP5RH;I^'STDCVW<[ +M@#@7B0M-+1#@2<;^=XF']F/O%2$$[%[@'LO!<]U7LSAW7*W6',&".\ED)/GK +MF)JA+S),/A"ISXD3DIN/CU!Z/((0+/QFZ#-+949(C.RIFXY-#]8+M8")7`8_ +M?+`7<]B%E4C\_++-A##O[;6=/!GZ311(3+:Y?S^S_[_LLN]IJTCP))FE?]![ +M`1>V+0M1$AF@9T1["5B*_1$+L:33<1+E[>2`(=MV)Q$[_V7,#Z'5Q$`;GY@_5?M.I[1O46&_']!/(\VPK/FW7:;<%92 +MF!XH`3/]#P7RM)F(%`IW2UBC4=OY/(>O\]9SCNZ$G/HY\YG4!HGWM;NU@!'& +M?&@UUH**6RI/WF`[.3?\CPZ1/M< +M]#B3#_MOFR/6U_Q6:YTP4RM&@>W<`1KJD%EN[#>(Q&%DW@\20U83.R';Q."QR[^PA"+W+*4WB40"NK=Q*N)U.&;6CEV'$0 +M+64C\R[!F\?UU$!3W;X'USFE;.(:Q=3=.36"OMZM_"9/&=H1!RGA,M-@V]9@ +M'!F+'R[1WEHQX7%[`._7(6CP.AP'P"\[\]R^=A2PPV#"1O!DY?3#0\[EG]IJ +MUKU.8)H'!!H[4Q7=!.:?T\I%J#B&5,2-H5B.+9C9S[J,N5+>3D):[Q>L'4-B +MJSH?"?S#H1:[LF:U).E+H$!ZY3TT*\B:>01?J] +M!M:2?T2=380YE@DC`3I!W(DE4TX+2O7.F^^R?%"%Z&TS(J":/V*TQ/MT.3@W +M/S_]D%5Q:Y'KQ>3&`:MP$(Q>*([10 +M5P=;H^+3-;AOT\\$_%I0N1I\UAFJ^8`NPQ&NL)XC]6YJ70ZR6/`_UHF82:0!.]B;^\O +M->38!'WTO?"XRCEV,/)/5(O.]]XS"%6.$B,;H!')"W +M2]+#9-@E^^LX<1D#F@O)C[.S__T/_#EJO_WC98^-WV$0XVU^'=Y=U,DWYR37 +M$\=.A'3K/8*>X^1$TR^4]/%`/:40<"<#\JH*`5&\7-$B=::B6_G[&?,`)&6> +MR*ZZ/F>_65XO3$T]4J+J[H8\76AG +MBVOSWK4?_QX0,5-*_@^(9@%WNEIR%4#'.)AQ0PR/&/BL>'ZL6+'FHLC?(<$K +M91(^Y8ZVW_YA`-O]\AQ!(0)D.X,"G:"$G*@03,Z=KZ3+^>5$,0P,,TS`VL`- +M['I#9;@+!C?XWF?PPJ4'6""$$E%T5/@%:FN4FHX?B%!V8W%D4)O*T)_6$N,Z +M_X[NPT;G1:%T%QZ\-+;59W^TGH-<212XEL@A(10$7)6@:8N+WB$ZF#0,^7*[ +ML^W4:`4'IPJY-[2.=;Z#2$6@9,)G=63'0A\FXC>B/VDQ^YVPU`0PGC"&X[)W +M]N`8MP/T&P4!SL8]WSU=*_5/\S:<-8\4V,08.%A<2@Z:)HZ!F) +MX5S5"^YNNO6CTOQ>Y`TW1>_X`TO04`IDYD]GYTK\T.Q8B_#5ROD0'GZT\MTY +M>`;"G^G5_1B_6X2*#]>`B'7K, +MI?`7G4I(398$U?T3.AX_R`LB';4`3EZ_#FW_'#`7_21RON9%HS]NU<7.!VJ3 +MC*_V^8A_9I3GL@#L9U@AG007F56@4HPN6=N\AKW!E1;>2OIU2JLU.$].C/HN +MD[YXG;78<>!UD/XSO"4SU>(1[2(',/E2+W$49+>5W@5L*"Z0EG5$B,]K$DVF +MH";5)?#38)4^5+Y$+"B:Q)TF(M\'_Y-AB:QE[NI7:U^.`LC=?H@RA.@$P2\G8M".D2X29Q]>_Q\KHR-&C@467OL;-T;E)P>8_4RT>1WM<\P" +M+$:;$&8U[0_,\_88*]`4_@'D8G+TR)0!X/*`D25LYS473N[6I]Z25NTH;T:. +M7IE[67S#%V_"68(-$_`X73PEA9KDB8@A_2SY=DL*`_(OW0%Y`"WX +MXEP9]T9\Q.F>,J#P4%BS)^TT&1I8_4;=)BQ'0P.>GV"L3C5YB.(17R9.ZE;32B +M2P3L)5\(F'FH)!!D6P/G_0VQ[,>O455OG1-3@J8>!]_G:EW+T.R16/B3"D%X +M,8`+KF!KGA8K*=^LEXDW:'&G@?W<3B +MWO@7K%T24H%$F43;'-[:7DQ)B[$PK[S=)F1/7N/,^[>':'T'D&8UM":)?%)] +M:E#GA58UX8JMYN*%G;'PW1UI,N)TE/`$REF43?@X.,1WP)[LM]L@ +M,7?]0!''O,UQC@0[.+HJ&ZZJ\^X8("5X6`S_!CGB1MY^&9M7^MDDHYHLOP&V +MIR(9_(76OYA)58(JR_5A5%4+A1=&L?)N_D(@3D>NM\]@MA[N]9P_OC*+A(,^ +M<*_^>MD#N<>2R?*921%.@5CR#[/J"N+S9>28>X3N'4/U0_.D#%(UFM`3'9P% +M""E9AOE*@JCHW@_?6AL=.OGVPE1DN+337`K2U_\SNESHN?K9PZP**9\-Y5-/ +M:RI5V.E,XUSU%:3I]1Q0#3`]D?^QGG!(Y'B060I/7.,\KP($_(LQ"5+`>33[$`Q/?0G[-5KYIB[OY/9MYJQ=1FU?:/_D$ +MB84")]EK]S>@V6@FEA$!>DFPHG`PA1"69,E^CHP&:XQ2LMJX;,^$S%O*8H%M +M`32F,LZZ,6411>3MMH`?Q_ZL;U72WX$7A]8G$)_]X:O1*8'Y+)<.65U+1B,4 +MUH(;P(6:DEH-[_U2*;3GW&\P3R'%D_6&[&-F'Y^ERFD<%VZO)UTKO?>?\P,H +M)XE&2Y/:J=PL/W(8ZM\!MWB=$7#W2`J`M=$'!4ZNHT$JH;<_N=D]]APF:W(I +M@1FNSWV4XW-9M7/_U',SWBIY.;C9&VDPJH;'&]B64+H:'8@85Q8YI9S1*53K +M>;'X06P)8N,@CJJG/5]/E2+,Q4@PF2WTZ/7%XST\$DT2'$#KJMDLU4HYF^*+ +MN"M.YHY=A%/*CCF@\NW'@9O2DN22`FJ]`T\C`PQ6&C0-JJ(Y+PWX[CN,...C +MMIRFQ`L44!YN5_Q`MNB;ZG<38T.[%YUAY +MN&@'EH/6EU#/2$---G#2=K3AF=?!-F_VB*I(1\]=O!9L@YE_"_C+&ZQ*9`,\ +MC9F"Y+"D)UU%W4#)]\S2O@N!NO1R-7S'?FF%P$%UA-2V_% +MK_&'AEP1R=.5^!I&%7Q'#Z8M)C#T3K=@!6]-E,WL\UDN^`5DU5AX9K5.PM!)/#K>: +MR#"8)V[T6TU$%<:\5$LN36!C(G708V[,O:#K.&S*XX/4I)&#Y5/V&EBY&X_. +MIX">8+&U:2C"KSHKS9+4NG-M9F*D"^*T#BEZH94Z?*JH>\?#PYOJ3G(SS74= +M6?9\/D)N:"%,H,79*PR!I^SZ]W40RBJB6Q)*YP`,.)U8',B81Z>94TP6T_'& +M/N,.G&.\NF:6O,VY*C6S>?_2,`-/'(#AJ"K+_8:K[MQK(@[@2ZOA0VU#MTY3L+[5.<5T_:)]2P-Z!U\?J[%4`%PM0.V8G(` +M&[LCI.8%&X&A5).-!.DU5/;U0QN"K5'4^C*$8(\PI&*C]&$)"XI5/^&_ER=> +M>Y!L=_#56Q46<0&':E[.A"C\Z=FRW3R%)@!.1T?LS3\8;9.Y>\-?_(--MV"< +M^]GK(%,QAW*%XV-`\RE':%P/$L,O8)V27"-`,CXB"/W8*CI: +M?3-B_C$V]RUM&3@''B<[\<4T`2E(WR1[-$%CX=,(O!X)-!;6`<+;&.!X8FS/ +MAW3+_T5!D/&>[TEF31L/F\^#I1C^7VO +M$AC6_&\_5%7W"OW`A=4%NA>2AB&0QM_@*'GT+FZ`[*C=CJ):J],\LAU\&,&C +MWA%&S7'96H;A_6-:;"..*5D(N)+D4-N3V]ZK9=SQU189U,P/XG5 +M$3RB@CJ?.GY(^<^'1)7PSN@+2G>@AO`H]*3ES%Z``D;P#2;V^0[=6_=F0RKT +M'AN>I.'*C(-)`FM:[8X&0>!_;XGK#;X)6:@]G[:`Y5%FF7,Q]J8QX@'5]TW_ +M/(Q6+TC,:ZZ.-MS*3DB)IROY]E]QUYJ#.2R.=A)M<8""[`XDFI/:$&[+R(H, +MOW\*706NHI)(X9175Y5E&CDGWRY05L7JX"90KH*/)8Q%?B.=:QT_=MIF/ELM +M6\]7.I";#^@'+*RX_OOKD%0QP,&9"RN)&AE,$\>N&\E18[HU;Y2O9QIXA9KW +MHH_6.KXZ@EQ)RN>^[!S7QI!C8$8'K7K&^(J$&P+4_^7D\]F27\\4">!6+YEY +M:E:(NB!(%Y/MT[K(B./]-KS2H*;]6%8IYD>40(.?:H*D[S\),:+V!DD/<0,BA>*[_4^/I`!<[C8<^X.FB3Y=07]!2SFHH:ETP)XT +M-68`.XFC>-@PXY$U55`60E9"N<)%\\N!M$O\N2DNV(9P"A#7SD`9P(M+U:!-TE3A]O?>_J#H!W,7 +M*B7_))6,CRM.202G7MPA@?2+E:[I%B8P9F?JS=W_]F/JF4+%+"ZN;3S^WAUZ +MO6L7",=L5-,6-+TK&3<(M=YM8VVE\I"NU"K!@M<.QZV3/$_%;X+ZN^TLM>\M +M/>ZMH1?&HC>YV<,Q-1T2H2')?LC%RY;E,_G^".ZOS4U2D2L9Y/Q`1?50/AI' +M_C8,!,DI?HRYUUM>3RD$.?O?3"KK6Y/TESMYNBX&>D;F2TR.+(HD)S:SI1I3 +M"$H'/:2"-8S+[9&8KW##JO[)ZX,_%D2GBE?@-HB`H#%J#T6[$W9MEWR1C(5K +M$'!"*>5[(7\1"EX'0J:"QV/\2VY'M!W9KVGA0^XKL:I-MU2\T)/O2UVM-N`+-,C2=%]]'SI:7#N*PPA$5K,--N +MZI@>,(SS*';PJOU2?FD2@_SN +MC>8C!G^1AI*E.BX?UQ$-6\_<=@"YL!&+X8QS"N2ID^I?U`U<#RC328P@/0`$ +MJ/NMH`C\6'JU=93:;DMD'3YZB"55,4&T5IP=:6R@8G?=YI?QO@E`9Q_3Y/NJ +M_*JY^K`W(%+!KQA`I*$&6@X%/DX#$RS]UA5/L@.#O.AE +M2DH3$0VNVK,F@B!`PQJI0$R0F;R=X +M9$N\\HEM6:S+]A#U"GV-`<(X>W%)N>U`T#B+MJ%,6;(ZWFD(]`G_^]/*AH4= +MY/V2-.32&1]X9W:DD>$R8GEJI4I_TSX+J@>+H'UBY]M:Y<]MDL9IT%1>:B_L +M4J6"-,A/DB6[H^8XY$O1:[7SYC7K[\E*U**(_=*:2W*)":&5H(%I2*6X;O"=631GVIW%W +M*&0MP8,$R;\BR1%&H#`^DW=X7,K(#A"0-,.:DW\)Y!);\=F@HO.QN,T'U'K/ +M`Y4:_NR3%(,^D,OH$1!F+ +M9'[09E9(9X-?'F-<'8[;6=4)S8(@)-Z/U](!#$/D9257"FZ^@D]985Z8L3BG +M6BM_['`=&IRBUJ`$(>HP6SHA0,2QRNVVVT\YTF(U*]T-]Y\+&?_6>/857)W: +M[1CUWLR,X4-+EJSL-3'QL?+`C9&9UGL!T$A__8>1N0N=P(LI?W(-ZU[C3XU? +M051?VKD@[0T3Q[8S=[#ZL6H1N%$-B-:P]8JPVH56M6B;YPIRW`ZP29K>C2=' +MZZ-:CXF?V*F\@CIHYC^YS\61$_P`5NY7:U:$-C-1A15_M@HX7-+;E/E!E4N& +MB@KA'GP2'/W\*#).4,`51(G(#ZJ'LASLQ?S4"WK,@_[P,Q^\:R#N&GHJ=:WG +M]'Z\6ZJ<6DYN/M>#H((1U6'+B*G'1SS2=GH/C,0`D%M3QUF%-#ZM/<,ND!4- +MUVU;:TIC]G?R8%$I"!I\M8KN!&_Y5UE#N2@Y@):^*>RF&G3MOGQ9\5RJ$[K9 +MH?SHVA'CR^?A?LWW>-^\6JG$$D"WI[%LPHD?\`` +M+[6/'G,JI(F;:ZJLO(K:)5L5+S65?;*+63K@T+C#S*7/:E-&NM(27G!-Y20V +MB5./_]^!GV<:2<(86V+D4%?E,N/]/G!DV,X(CB3HV\C!*2_B_&1H;_TY[=:\\6U2<$?]?I9KH7H,G,8UBJ' +M^91MN^GD%`(NL;0M#[)44OE0$]37X0`/%%"\J>02R\I;+(>"IUY:H" +M**PO^((T-+Z'?98@IB:WOHN6Z>7-B;MA+5OS/C0&>>I(MR9DG&`B+ +MYPUOP>FN-YQM+AW(%1,`2H'4TY9:YJK$81,MN1\_,VO*6:9?IVJ8$4M/;_?Q:O1(__C'Q>;?UCA9(T%_E!-+ +M]0_NUOW0[8.,E@W;IK7U:O,J=[R3'10%I+Z[#=8,^!L<[FIE9:.LK1!)_F2" +M!?//GO?(SA"&US?]4HX_>PT;7I>HQ[I +MYJ`_[RP$3?6QJZ(%\.;`:M%UOQ70UV^[M]3_S<8B.3[U\K!`O%C.@#<9W +M-HTYB@^250X8KH<\",=(1D;Y[2Y@Y"&F[67'`Y,!*,L.H"^\"JK#;Y&6DB>X +MN7L.T?E8$445%\#GRB$C2Z[`_<$1!R@+#=G,!P0+$M<);0T>;>6H=7%F]8P7 +M<8L&+%?#` +M-$Z"V((3$@@4@F+L]@H'TT='Q';=C5> +MI@(^K3A^@4Y0(\.]AB@B^DEL]YX_'.'&T:6FX#LQ#WY8:5DI`*60!+XD8I%- +MC`8-X^KZ_XU*9\Y;WLVGLFB>7+7$3M(D];1@MS1EY_JAL55EW;75:35H`/`H +M^$M<6IH&PY^"XHLQ`G&2+([4*X@C&/E@BUQE5\LL%9&?2"M$P"H=C2@R! +MH,LQ&P"["UJ$:`1++SX^FJO(S5_P0_*"]$DW=,`AD(//"@P!:GN9,PB5:$)* +MT,5*OA]?;B)D:@:[2,@S=S02L_ZVLEI(P\QF;_:/"?WR`&&@<9SL]^.20URC +M(GL21!],M-Z/$G#OX/'2KTO]!]#$-Z27U*30O9,RS):B!+ +MU#OLN*C2#,/.HW9\FZ*27HV:GW)4T"JPYBR:S+COC$/37U0>\[502\>'L`TZ +M1L6IU,;_'PS.SB;N]!5LS@_8KHXT/?GG^G(?S3OUE>?@V"01K>2XDA'9#':)M:Y +M&`/`=KW\P!K^LT$0!&VF>$C>L,XJTEY5PJ0-`V?VWN\_>ZWH+*F`4%>QL["4 +M4X>YA1K6)_E#1?'1AGZBE+(<;B'C#.46?PYV/A"(PQF22LZ7B,RVXDM*OQ7S +MI3>?VJP`BYP?0Z\G6,\,+&B;GY;F`RZ>M^VBX^MYXOK.09B*V&[!W&P%!*L- +M$5RH;5D&$TKG4:O&XA=FR&=VFU8?U&*JU>#L&A?QQC4*XNW*E$62OKY/*T%E+O:_<%<%WWVW1@#^S9Y@-J8JX#=EX6M=Q+'J+MG$30B4 +MZ+-/3K])T9;`F`N8H3UT)MY8<:!%;`NF?8W4C2#@/01O"OM3@#AW:,)D@YA0 +M6E3UXUWOGD>B6;[]S='^X$)9VEK!_3.'>,S_Y`%Y7O9P+P3ON)/3X[M!0'P2 +ME#M$+3(DBM[(9.:;A`?9#++F;PK9IST`#3/$!>FN@+ZXUM&/Q5/V1*'RY?R; +MHS6O/KJ8O?VU3\U%I"\*B`Q2YL0*AM +M5AFXZC(P%7T:K#JHKUO!J4T]:[R_L]\TS:Q"YF/YN+);B,0.N6B`NQ<3?3JY +M"?<+$'$:+`,J_;K*R(/@"WB_\N,?.%E$@$,@O(7N"TA.T[!N899R*VG^JRSF +M6(5-N\3#=%='^OV] +M#YTDIC_R#JU4O69L4B;=:+GK0"OQ8 +ME$@E<8&P4Q41S-DC\"2\?XBYZZ%@7Z2B$Z^'OC3!TB<&9+Y2,$JAG6;DFK0[ +M$]?0>1[1\!"^;*$UP12A8K2V##V"13Z!HQBC66?*P)AZX>[38]V6$PFJ7]+E +M@(WT1?%ZQ3JYS2&BQ1_T3LNW?V\+2<*.5 +MBEM_Q(,(%0[A5#BJ;$:\<6&,WBG:C.[AD4]5Z9/(NIK*,^754WX]O23TM?@JBUS89K`,9X_NV^[==]?NG_7XMU(U3&'8BXP!!>Q1FZ'VJ-*%!S)RTFM-@2>A8RKXZP@B90%O#S$L1TJ-15^,OH^/ +M8LJJ@!V'@:_;/9F.C&0#2W"^P*!HET%!GB`LG`:<_388U/P#.E0ADU4DQUX& +MH3EX8DWLK=]^$%)&`K`A4I;!R+K($LS39[T@H>DD$PS\U(0S8L'$<#[L%EU. +MQS@E+H/,T&?XCFLVL[WD&"&FL"=#!+V`W!EW,*]-]5>Z1+107BOZS+15"41\ +M:>)D^IR4RI/!1.:L8)5;;*LD^XN"-=%3"@L<_?.1EG2IT"4T8?Y9Z#X2N#9A +M*#OG=A`G@^W@7A^Y"XS/-L6W%2IBTZN\\%2Q +M[Q3][#^U9QK,49\JB7Q(2[M^2\JG% +MK;(/^MC,.MGWU!AE#6LBFQE,I_K]7:Q`FN?&Y!IIZ2LBV.?#6LPG[F!QBRGB +M+]EHW%9'V+YHZ@QB4E,BT?2T[5(S(+[)5(B+JD;HALSH8UCL5Y]V+PT<3?VW +MB.\4BWHIFCR`TQ\<)>G1XS$;R7KN$' +MZK^W*^.3GU@"2/Y]["!`$,0VL])QO[1*!EHYW;" +MY?3PU#1*9FW7:Q]6+.D#S(YI7!'=ZKR?1Q:B`;L5W#ZATI[YMYUJTB:9]I>( +M8MESX!9/:S1.I!EM-0;H$8-DX"K%3^_Z?S'_" +M`WP6B&T'&]`B7M\B/)[EQL:`&$<$_`"C!OD@5SH8(9)B"58,1TT<:\(ES-L<&(LP?7J/%,Z5+`B*S]ZS4#5K&#A`>SBR#V*L64_1M1M +M)2^ILX^\OU'V;_3TT*3@XL#4?JN?Q.%8@@I`RE38E'V)]SJ;&J2D^@N?NQ@T +MGY$?*_H'Q<@CC7AI[W3\CM6<;!-6[,D$6NZU&]@5OMG$YZ)3S_\/X/DKE!0T +MB&52&?S+JLCI#$P"2(V;3Q+;]2Z_@C8/]9Z9VF%5_I>K(RRFL0>K>Z7QG.BO +MQE!UQ2.!\+N"MV.+6T5VIS_+9H_M1S3'7KPPNP[&$L`)*FG(`]^S/^@"-(+U +M+8@6/:0GFQZN*3&JM"3I.A9XM,+5:[\4?RX*7"BN2U5EM"6F;G?4A;J2+UWT +M/8A<=>L82/*G)[CL>Y%E6M9LG$>WZPI]%#@$58BV.L<=DS;-9<7!W02PT2UR +MH1SP74CW(/*7Y?-CD(0WNJV(^(\7,A!^'N]M>A]>`X8\M]:D8?HQ47@YI-&Q_DA.`.S4QU?>0 +M/>]/FV6SH?G2LRO/-;-LGG'H2B@79(@LP)CH\0\@=+*EH$\6P3)@.VD=+B(Y +M)G`;E:VRRB$K48W!=^?.7QF#G&T\HIFP&&>XI>+->%HAGDCM3]P$S;K;\WD@7]Y +M2E*?09/-PD_\?]13?O%,3]S8GHF$]9RWW+WQYT+*JEAO2U#(`?9`C1ISQ?+L +M3Z45/.5"(OB&1,0_7E&E5O;F$MW+@O]#OA0>&&L3A^`Y>C]9U^<+@R;WT&G/ +M^5Y`82:%B"K#Q3.ZS=G)3L\1+V4CL&P+#LT(/OS[YLBM?)5.X;:`?\FL$X\^ +ML;YZ0F;(X>-:?SN%MI`P1*_?;(3Z8253X,V249BIWVPH=M&A>K\B=8/5*^3Q +MG_!,=;)WL*2@$JJ*4(EN_V2DO/HAUK>!X4>W#G5*33OSL`!V7Y>P8HLEK4E> +MYVF0GN_J=H0WFD>\[_8^(T:`;S84=6PV*4@K_JD47==)H$EXC9+K)SYOV$S: +M[EP!6^O(6W[173@RWM!K&[%JJ;@U`(X:1G71B +MP33_Q_O&K0N\GSI66^)U25:4X=QP\[PAXX=3#MWOH`X&)/4-$*D*3YO:;,6; +MCDIK01.\@BE#U[%QC2LR!LL`=%>6RPGCW65)16#6>?8QKDKKU4)YTA(>J?<3 +M6RDG#>`ID=074IL4"+U,726T%_+CD+$RDQX;FV0E#;9J9JPHH0Y+;=$2FUQS +M6(HBH`S6<^&SKHR?2LQ;[S08[`9('O@D5)=G9!'D0\&_J;X'.%D]THK4T1RB +MX4AT[%*7V%`-O`1EGW+2W"#5_`._]\OC/J@.8LX,/(")++GIQ@>UR/%MR@[: +M['B8""@'/#SL@25937=#WQ@<>1AJ<;<#(.:8W8&%:JT+ARSSH^]+O3EL1]*= +M9HZ>7<2OFTV:Q5L`7UW='J)GK<7'F"2V&0C/$`3<((\0D3U_Q#%%IA!N#8]B +MPZC34<\B=\05H8R[Q?*N2>4LSO1R5[53:DPG!?JR#//S146/.L'`:7O=B,M#O1YJ>7#Q*L* +MKK]<%U_K[N.J#J@`FO[6DD?=%`_F/30SX3L57:\$L>*12J\_C +M.KP0!]4=)RIB46=,QZ@Y8=B=D[A]I#R]F?\G3"R4-`>*OPK"&=$\SG/[]A/C +MNRB6NXQ[T1?8N'=J2]9,+Z3KO\4;OY^W%H.F5-=H2+.)64_]7/V@[LA&PM`[[.`^K:?6S(I7 +M:_6PF)YXKO[AF!'*MJA4#P.K:SCO;O%,70NTVF9;*"+_Z!N)LOA)PQ]#OB:Q +MISF,N169`6BZF%$7#SF!#]Z5C=*K1G]<8)6$&1:%O0%/1\EZ$F$`JV$2]&4> +M8P`JM#L_XIT-@O'H*&3P,TRA=&2U36@Y]_$OJ=ZB;EI5B$ +MX;&T7],\8"7FF3O!OO7DZZG@BCQ=%UY*)9%(K@)02PNL%T(4P@X'!N%`&E3W +M^<1AFQP;,1Y2SC;GHZO7912Z?LL>#S6>>VQ4QB(Z]D)KA?2L1OW>OP!OV``< +M0T[13[I+;[G&7*P-G),`?08?48MN5^0+B9W$_`18F%?3`Q.KJB@8M9<%T8S' +M7Y5LPU9Y=`PBPN_GC?F*MJNN$D;JN,@?`VQ<%UVU +MB)4Z1KE>-!&JZ;N+(1I#'X1RP4Q:P"Z;T3U>T;&9,YVT4?=^`:\9O!IDV6L% +M+5]QR8+%L8?=ASKB&L8,XEXLVL-./UL5-X$6BC".QRE)ARE",%,1PXL"Z=&O +M[D[AW5\P">BS2U`'6H,*IL^\C-U?(SP%Q&%D3-E5U*!S7?K*I0`QYKD)X`/P +M>B(1&UA.[0K#,-L:7/UC?:TO0*SN3F`\RJ>JPPN7\@AOM>LCRBJG$JF[HTL/ +M%KRB9S3W)(0L_I^YYH%L^T=V*P$E^FHC8:<&ZB"DR`&!+EKV.NU(P%&;'`ZE +MZ^$TU`F@VP:%G(((X6%63:D393FZ]>,"'^G_Y=<]5=[+N`'96G).C'K),W[# +M&??!H8`,J*1J,T'.=P]JJS;BK`V,<_,PX(0;Z=K?#;;1>,/`8::AZ>C3HDZ` +MD*.E+(]2G'+01C=45KB\P\>D.BQ0-E(Z:6ABV=*&M;=1DBP'6V(G`&7-D%P+ +M$QY&@VW*(,GOE:Y&JR[##(B>W5C38KW^%@EN@B2`!NFU +M5U2)\-V5BN3R#.<#B:6>Q\;F>9RJ!NI')IOH_U;+4GRK/46L6Y6Z$D])?!_? +M=,.RXB(:H(8'7F'(;;*D%R,./KXE+8>Y1H562(0C%0",'NW\(OE)7-BS^H`" +MGXBGV?'`^%$1-2C@C\D/15$%(H=V[U>S8XQ(8V8HEHB\K+B45N@U>M1UDER1 +M>UZ=%BQ(XH2@<"132#;J&:MR6."P5\K4^&M>XL.44*HI;F5NI39=;B[8LH`E +M/%95>;#NY6"&>2W34;2BJ]N2*G#F?Z)LQ:9`A%X?!/K2V<2`"%S`G_HIBE\D +M"L&C%A_G]\0"I()SRY8)U1P`)Q.4'IMO&)QO6186!(X90MJC+1D!L896;(=N +MA"_A40%J^FK5_S,^_T@Q=6`5+8$5=7U=4Q$+UY(+7RT!Y**U>V;1`LHF<*!\ +MD@:",&FU9Y(Q#@R*_]N)+_?.0F,5K(T<-^&5\YY_BS.]/#=X[_/6:%K>D0_Z +ME=B:8XWK`;KK?4K&I):%JQV=$FP;7+;Q(EH>!^O@]U"X@U/(=MWWNJI!/S:# +M-*@\W9PR(S!J*F:PLJSH:SI*OA=S$(79AF63OY;NA>2VWKF4&6$!L_KK7H/@?,^4R+\R:"N\B[U#Q7WA?PU1K0*4\Q:IR;0>K-)J6*]-XEW+#Q&W^Q8.2RYZ74W>'H0JA +M",59=7GS,@VWD!K+T=],G##FU.Z_U]0:]3MOB6./^QR5(P;\YV+>)D%>35K6 +M+\WBW=HO!VGM`G,^5]K8MM7D39_.H"2B^>;]Z`E=S-/)0ET#^#Q5DJZ&_(Q? +MZT8SO\Z`0WRYJP4`-;`.(T+5BC%$9W#J(T/J.?\^V5.2HO$/:P19%\$+)7$#J..(="ZM* +M3]F0&"P\3MR/JI;7O:%SB3]GC\UGHDO`E?8):,R5N[1;Y,S1[?_,[R3TT:33 +M+$O8LD6*DF6.^SBO&N1.]>GLE[!.ANV&86)[4?.O%F&(R%KKPLS/JD@L/>B( +MFIF@_I9,B1W,L29!GZ:#U._OQYTA]!D?HHNR\`BP5,,71I9&&>2_9>0[,\XY +MI&03Y^IZQN%D?:PA\Z*B>`XMA%'=:R?F+0U]=5EI%+G^OM)!!P\_LEON0TG0 +M@J@XQ2Y(-F(1=[P,;\]RUGSV<8J5V.?`NQF5]+Q,9#H.9)@P;M44IQXT4QU1 +MG;;&)_&LW!=;;6]F*;3)Z8;PO,BSCEVW_G[`*:LKJV+K +M&(CT+NOZCQH)_%!UNW*+[,K)&LP7X3U\4HEFLCJ0/WXG]7P5Z6++3A>TL1-E +MD\,(CJ8FSUK$N0B$R;[*<.8I'*_1GQ2'*+*E++J&@QC,EBGVI +M8#!NK0S1P@PEQYQ6SFFS;\F\B.>]&TI +M5H2*K(CXQ7TCAMPG#%]EXU=WP->T?[&VMJTUJ,TUN*JE!N=&=-SQS+D?::5\ +M6@4=<2U`HA[V;DV\_ZOHR]EB^5"`O!+?M;(K8BICL*Q#P1#25D_K*Q+&"1+% +MK9NM>L[;<::OX4A_"S>?&=7[T56G[V&*'?EG[%3/^YRA3,P@OI^`*KQE22=M +MJ0'4P$;#[<==GOIUK+0.#)1GS3/N9C +M]VH^7'Q@I?9J3M`3_H3WQ"FQ[B-O5'=4PH*-)&;X."[BLB.S'ZK3(0!=ZV<0 +MWA5ZO5Y#?CZGDS,BH3-J2C$EVHYVKGAM:@G)F_E#.Q4X2AA_T]+@W9,6+`ROVV3,!&5*HHYN`L9CK#=')[>JZ)WK7T5?_)E$R*JEKPSJJN +M^G7_A(BSW7B/1UVLSK7XWXLT%Y]0&-5WDF@.X$BO?K,0NVV.AZBO\(6`VBM[ +MHY,80#RC&@SKS:(&3,8W9.LB6`/8$_.[,J87G0 +M&/%A,KM#\3UFW-8M_,1:/MTT1[++RGN*J2D5-XGI!XE^6#MIU!`F*F(@U989 +MDU'I2]2VN@I4AO+B?'+C"D=.20]^IBP2RC5@(B$"WA/X[+J[7_FEPTZ<$D!] +M'%*=[AG/A^BF]2H&;\"=8`HB#R:X,-[2":!1A;-D;(HYY,3?7NFM4//*Q*C/ +M?Y4N-$(:L,#H](R]1[YI@[11^C`F6!>LSIQ+=P_P-\F;"";,ID.T`WVJ"3>6 +MR)]JRW_)B_!2!M-IZ@\(:!+_K;<&Z5S]^@/W$(.[OI-32:=1[SE:9_V"CQ@( +MV:'$+GY$/>_%^R_"#0?L]1'[6C+#&R:\&SA*7]K,$.K3`AW^_JG-EVODAEQK +MK/.C'#8NL+@N&KTL/AT392/)73;.G +M0QME>_'-:OX+&((*OSPQNUR*'KW,LG8QTR5LX0WU#Q7KD&WP=;AB^1X@GFZ: +M2EL&3"2P$2I<@IS>W,YS^9]D^1I[XDEOYQ@+#ZYNTJCKK.#7>Y[8G@=Q,:1[ +MY%8:7`'S-ML":4CA3Z[.#O2-^GYM?E$:1=% +M88S3GE9-8&*:.^R`D[^OL,8(I43)(#OC._U!4@#5 +M81S,JQA[JNU_L@=DYMRBF9#V0DK^,VZ7MP&3("MP(E.Z5)8D<"K%D8^]PO'S +M:$*L15%7T(D7*"U'*O"V5<#?+E)#-J)G7^]0%X/!%]#E0D6)&_/.IQSTBDD' +M3XQW1ZAML9$FF:J\FGFZZ5>/"^2?(#)Q@_>;P#_T!LZLDE`)'#H56F2I)7GR +MO'CAGGQO@5[%AB_@)WW`S3P]!E]N5B;P:TA-1].K +M+^.J97,PK0F8=MY/;SBS9%&CFHLKHG_I#D@:0B\M]6"7Z*.&WX:F +M9O+U%8,#GG%Y+&U%]0;!?>EUZ?-B'0\$&@9W%F-\8^X#4'6@MG:HOV2,SGZ9 +M+53#:-E-7G/`8HQ1NV^XL1_(2;OY5VQ0`U')Y/]?"#6GF3N)LRKB1F\^/\T@ +M`,GXOYF_U_(3$>+=72"L36.7K(U]2.\%$ZX.M[.WTY#`Y@GP.4``?E>P0W]B +MW_@JNNKBSA@+LC>OY_I*,?TI_=*;+Y'QAE*4=#@Y>*_^RM +M9?$\Q9)L@N&B8T,OTY,O>1S2`^51@J]F]KT!7KL;D-DK<)/"9>3VC_CML4P5 +MJ=32"UN2>JTQI5]5]WO,I#W1>S,S[!0\J`M<\+(GT#%_S('"&9R21<:O/Y? +M.H"LMJDPMFXES]!L"4H:F=XASQ/WSUWAF@(`8#6T;<36&X`U+T3M-"2/XJQC +M)Y!2Y1*U'J'LPD$3&0U[7^,,CO=_[@BT;WT^,]/H"%EC$99' +M0;.T8:V`)]/=?%DY\-)\HW-WR@\SU]3J1LW_3+5.>]C$Z$WY1[W9B)Y7G))?[X["`!5-UU30:'Q:IZK;2A,\?7 +M>KK([J:[J+W>_:U=[+3V?VIZZ%,U>+5NL\_50._N*3"['E:M^E`-4Q.A#$KQ]%N`;*O\H9ZBK@;J_L$N4X?B"!E_'*NZ286-A$ +M4F_KNWD_DL^PR&306$%^\#1\87 +M00K6>[QM*_^(_U@+G9`(?G=B->!G&/:N`2=[57K56G7A^Y7]X(E?Y/^K[?0: +MT.D>)">Q8HTNGI7K49M:]6LL3,SB^)3+5ZJ%[P@AL;7I5@ZMT"H\O5.*?H!U +M,P55W>?)R2_QKB[7W5.W<0>'^LD?B__D2,S3W1%5$/^4?QH]EK336!G(Z+&+ +MB[DA0633.)(!1K=MNY*+C4[5E.^1"P3+5GPR'+P^^[;<>#(TSN_]^RU^DZ.6 +M5W1L9=T`[`7$`_=4&Q#VB,>X&Z[\+S]SE-X03'&37-_P;"P5#+9+;'7;"HF0 +MVY*>:]G4D3O4O@I>*B_AF"H976RGTS#GGU^EU.1\[\V!"CK=3JTOM=W"H`)K +M(*QK+(.EL_AX*16@E92FJ+*=RC-(MX7U;4B'V-8JMUX/7AYZM-K)("\\^^OZ!B_U7KO,$8&W3&O_O]_KT"(YO0EQ +M$($>Y>N\98L&^WW774/&=\`DMJJO-&O4UTN6YDE/Z'5V#D/H"PH4K9))O'F: +M*H-KM:F"J.%3(GV1\5`![ZNUE-;;0I5!.#2G1Z)B2G$OMQ<=>8>52"/9:SW' +M<(LPP&)5+T*=DQPU4LN%(0.@(4K9-^$R]-X462#14/OJ'V,3\W^R,08KMX#5 +MJ4_?-XJ+;R()&+L-2BR.J'K/$!.`I'W31)1F[CPX01D?7E9ZHB9,K(5Z)?=X +MN)8R2,'"+0_*)>'"Z976F]5#:TI0A:%192SRSCB?[^QE>C^\*N%W9D?A5F1M +M5-XG2;>G%398R0G2M(^B`OQ7?34H^\C_E?M=HWS+]L/G-XL^_-"YR>&/TE;" +MF@->P%59&U,]"[X0]I9G5I-`3&3%/^PC%KWKM!\.,P)*W3`F\.>'D43L*HN>:2+L[YQ^ND +M8%L=`VL?>@SAN>`L*!S^8"`$IX`<25O_$_1<>]NBYK^Q[72DI)NFUIT,#P*[ +MZX+&;_N/5V=8]`2I-OQ\/\U"?2\&?='4L6>LC";H#$1PAZ"@>&88L('Y$1X" +M'ITJSD"C';XLF?)J,Y*"W(VB"T#T`1S2"9L\G0RA-,SZ)JT'31^F:WPX8C)` +MSYTI>ICW^8KEJMZF*#TLZY^7^[PNN)'HP]=F.W4)R?FWN@87UA.W%^Y;^E=D +M$$KO6>9KKL'90V9'Z+F[]MZGS=%$JMP0(F1X;WEJC4U``EM@`3]TMU])C0HA`*#XKQA +MFU?5?YIFML7)Z>U!],>-_W^;8[O"BS+NEU35BM`O=-`:"I95L=SCI_]]2ESN +MO3L'I?K^^+ATD9/R!\Q):WM0.1(D)@>\G9WP`*Y9U97 +M9+W$[@Z(WU!2D>"(?X#G-"KNG9YY9LG5&<[[/6DG$7X2XU:X!:U92V#%VQ.= +MO3\U92/>N409_%&FD7B^#=M(87.992!DW@/1DKIK(:F<;OQM=S)/FAK^+NR' +MM4]"+`8:F`$GZZVL:*P!.!F>Y%%P,S]DN)+X"(/MEF-,`0R[TSDR<)_`('84 +M+?*.")D-ER_KH+X(*7E0T@)?M.;'-A"#^+]"JU(_7LR!8J2'RX;=X`_0M.WZ +M<%DS3](;Q$9GSI"U+^2?:_05\/J-\0H1X$?0='$2TJC+Q]P,V0)D39-NQ'EG +MT.*A+IK+:1?,Q39=X>`DI]G1[.T0@K9<6"OMR^)_M\!EO&AZV$4%+<;F4V$P +M;.Z>86]G_49>G4MZ@[IPWQ\"),H.9![\$H!/7K]OCU^J$`[LF$O^"GV&!_B- +MEE+W_NJM%HP-I5,D]W!)?T-]6'&:KJ<#C8@M0HX_ZX3WIY"G:M5/P(I05,38B5Z@(K"`%A +MT,1PK&*JYBZN`:\\L@M-^$YS$&_7#E)T*$I*/RS8&%@]6>.66,'D9../HA/2`SN'-PP+9 +MOF*K]ROJF&'W/I6A[P319E<_0"A!7._I+TAY)N0N->_A=R@W[=VQ8G$W*9/W +MC-ET<.:!KP('B^TF6L@VMUR>/P/II_%+]'4&7JL;PL)MP,E1^_M*^.#I5C02 +M,=/>VE,=@#C$PY<$!,MX.A][#UYUXWF$/>D%^>M87E#'#N:A#1'^,#=0L:/A8(-P/>=H +M1SQJ?B,4._U`$IH7(@SW$8,,'C:G3'`H/<3#T+L2NP:HDARTI=&(O&)L8RH? +M%O=H\*L506>5IC1#4]!#*6:V,6E#N-F'=7+AGTSRH6P\]:5OD=NIB'>;WN4M3V +M=GOB4VIN"BBXVKI$8$,7R:QB\M83ZVHVUH*S"X4VRZ9K0'/F=ZG_959,)ET1 +M2WO`;MC!T':0KM2LK//P;^#:X.?-4%%4.5<[.0:$+ITC#0K'`"./2U'9_T'X +M9QNZ#Y`R?DD2@ICA:J*'CQGGX=GLF:>X3-.2JO;HJ_I[#IJ&#-/GDO>20B:9 +M&RJ.-@J94F=O^NFY&,9R2WRP3T]Y8[9H:ZG#,O!\&K;OMJ$G7)[NPDW%Y$Z$ +ME,QLR?3DBJ=Q-D"[R@=$%>V8<3%T115_,Z+[0L";NE?RTDK$&/:P+NG!H;10,J#_W1=LLJ>_R.%308%*Y9'(JAY=.FPT?24H`F>L&4<8W40%>/X +MBA'2?KW"$OJZ)KYO6F=98UR^=1=J/DXR;."YZXLN.)5>,("9 +MI*.X9.AGNMFJ$;PF,8KS&JE0J>1L4R$'?)C&YZ'`?]\ZYDH'AJHR=T12Y8QM +MA:VX@/8J\H.Z%_:].T^ +MUB0#"6ZS%$4X`F`"Y]^%TI-]IXS/O5#SRQ1[[TZO]C_(Y&32J?J0R;,K,4FH#CP&BS#RK +MPS")*G878,1H;HGB3V>O!38I.6J08'PBO]45GPVS!N4Z'O!8K6HI[RZMVQ^\ +MI\>3@DG/^>$6'GBUV"B;B&-DCJL&=PIV7DRE5#E;:H-PS/.:(EN'#7!IGFIN +MS5P*&X:.ZE>>.+E<*,PA`E*[A(I![>P%-8(/YC30ZQ_VEB-)M3T931'M-'K5 +M54WT;2=BM&02]U-OJS9I:U?&/09K8HS'PI[0E:2C5+_]&AGG3$Q+B#D1$Z%: +MGN[G]X*=OSF-82?6\/L5E:-J,IMV97GE2[5L*R1)@%E.6B%5@IX''.H^S1;W +MO+62(B>[TBQ$&>F1GN82Q_*`;_?+_RUQO.?XB6<7).8$813Y\B50V7J''0EJ +MDH\+AWH+P.';$4!QHT#0$WE=1\\XO+(C82BBB!MP0#K +M6@:YA(1RF(BA#1R-PFK;+U?8704-G/^?EXRF._B(&UCC*/_WW0+DT +MEUI*?JC4NR3H&LGR_AZXD6+C\S_YW4`\-<4;M+2.+CP4\3)1/]'`,'?$ZCN\ +MO3;M?.KXUV?K +M#A7T)?5I9-^ZJ-JGI4$56^RRC[?W_M%F("<.@XF5YMR35B^GSR%3M)5NDZ:# +MZ3LB&>MX365)>X8-5I$^9&Q%AC3\Z<1%M;#$-BURON7(J1#+9[*0QC7J>&;Y +M(`K-/!_.PM_GG(_O]D2^_P=U#W41]^?L/%<'\?_&P;V;W'WGXMD$.5L[>A03 +M_^!AGZ/Q?*7$W+$YB&ED-\%41J.]4@A`3*N-?=+@?W)@R@\$Z->,VZN9!SQC +M#$+=C?A#"4K@J(L:5E'4.U;AYUFDR/SR;8MD\,N?Q>+Y/<.8/0Y`6ZSLEKVN +MSUVWA9P!A&\4ZCFY!.%*\X:/*L:P&1]M2>O`6##RHFY'7YIKG,\7X/A`N_]\ +M;K054:/]N>C+:+Z2=VTK95'F]"N7H!A0;'>SLP[^49$LRZ"+$+A)?5^HJ#UD +M1"'*?Z_,H'K(\<(4GT!6YM?+O%M[RHGEYVME,0`7"8SDFA9V!X+&X3-56,6^ +MVW0`-WBN2]3_/#20+]!#WM\MFZKNLJIX@@((F.HW)K3S\?12H#SM#[=N&$D# +MAV)FT#>`R.OUZ(U\'6RKZ)<"Q"="0_L,[U7*%]<=#F$*P$/,04GM)<+0^5#1 +M/-V]@NTBYR,)).J1G%9!5;RLG(P"`,;N.%U%L\&R1^AK=,?Q5S8_<+7@Q`K!D,]B"'RPJQ +M54P,6=@+<8E!40XK5P9'K$;JGJH&M2]Y640#C?A-&&EQMTR)$3';1X::]4J^ +MRM`["I6&\D@6NL%R?F(Z*1Y%MT2R54.O*ZL_<=XWH(X,.UB]PA5WP&8DCV/T +M6:Y.4((+S*).`S@H1$-!JT_(&QF?GY::$-&I5X#%ZWNA7CM-)#1LQ7<:K6IE +M.VB>]AT!;]XK$`I8[)#N:"*09M0!)\X)!"J,.\%JTZ@N1+74 +MJA1D*73$^CX^E%2@A>R^GK#!QIX`&Y=8^6G&+CB/>K46O4\&/SB2O'!Z-2?I +M96082?13XR^7;01ZH9#QYJB130V"+40.CB%D:U-2/ +ML3#[M443U!6I#\_`7'0BP#[^]\C=<&A43A1H5>$*+FW6>^,-X`3(`NA!QY/RT#C'%%3SQ +M5BU83F#$HH%<":$!`*L*Q]RTVE"]"1Z7Q0N9@I15:&+/;OOWB?WCW@]!4!FQ +MT09@Q.Z'8Q!I?0LA:E'MJ8,6BMSNPGPKRDM0=,:N&&$ +M":#4RO+AWV""34O!*'Q5]^Q*9\V;Y[&&H`KR_?SD&!IOQX?7I5N*G]WA)]9I +MG9Y].22.9Z$2*R@>H`Y9IT"A_'_Y-\#SZ]6>!V_2&.03WIVE.3U>25DT:^(P +M?A8[X./@ZT#FN`H%@B[[OD;$971RQ%KL-JNT^(5)#P1J_"#."._%&HK:6FO8 +M$FFTZ$H%R@IKAO;3[N\;[&P%L(O;N=ONGC]XX4/4.1"4\@=)/F,VQLN.H4G2NS"%GH5U[2]#^C +MZFN&&!.&&>MNC9$)DI\`IZS7X\;&_JZCC"-'AN@%>");8*K-732MS2OD'MHJ +M6@T9N&.$$+]C<:>A0'Y4A@-7\\#G=3^P_-9>T3VFM'A6.GS!,!.QS1_:AU[, +M!YVWP9LH%8&>M.UW0MNN(&B,*K +M&ZYE3A4]G0\%BCD2BJ!H27"FV..+=69U<=#.0&A>88PM3>G#_-E=-0-%K<3$ +MM4^'&6BO*ZJ!XR(5U,Y&TQW5HX+QQ6;AJ7L]_#W8SA_J"G=[E^V@*H!O.@5M +MQ@;0[(F!/(_/Z7A)YWR.Z48UKPD$G&" +MY^(-MT(%<,A<3T)-?YRX[(?O%J/$2R:9 +M5"GD-S?*V%?A"QG8`$>#K;9`N;2R*[`K=GPMKM42.6C\4&>]UK(JO*9S41.K +MSCNKH+?^T$0HR):9U,W<6+^0ET)(26901NO\ED`B>MW-HMM>'SK='HU=A[C[ +MXUU1-_791,D4Q<%2=1_GA!)29+Z!>6@>J`X1J+8)(@O$Q1`^=K_QEM`*-CZNND150S%>]K_1(VVM+$U<*(P=:&YR2&:[:`D#"F +M'&4G,)N!,%[R<\5!C"_0[FZPQD^RRE3OEI!J\.6KRBG-Q[IF%8O_(V7;DL_> +MGO`M($GOV9(6`T@NJ:BAG82M*,<`^ +M33-[_#(DS^M%*/&"*K/RT*PI9[/KOL7;`G$#JJPO13E*K13J=-87_Q,R:3\N +MIV3J$$=S4Q1:F!L7*HKBX/%.0&,:,,B^#`T3YIK[>*`#K0?)`Y^P.X@SXY)B +M7BU,FTSP>+_;Q(RB$7/>!`[AR8JAB[.[^0`'.%!@BA34S'R#W%I%W"MC,'S- +MO4Q#\&HQ)34J`A'.6NYAAZ4>P$`!5[3\FI0M7,!@1SC0H'>\,8Z/=BN6>MM!SHS%:*5K@4*]2X4K.E`ZXXD!<"(A"W)#\BU]&E)>MK8"P +MY"D2[9^3X[[[^^<6E10NG(0@HW[&+%"4R8?C46]SIY;FUV8TQOAP[?(OL+*7 +M;7_\TBH7(:I!!)T63@4`$U9@``")EGJ;K[?FP>Y!RKKO-:^!:GJ%":>&.%-N +M,(%?-.S81MG@*>H>/NAPEZ_>U)2/)4XU"NG+EHR]NRLWW-ABLK`PYMWF`.RN +M!AO?4H4K/VC:0-$Z!XM+4KOB[URYD<:0BK(S/Z$^T$HT/<$6MTB=1:LL,&F& +M.<\:+ZN6<)(-;85$M_!V`JAH%>RNM<2Z[9U%XQ35C4BQ3=^IR4)?TS*'&E!T2562]H +MS^SE3.[!BW*-?$DVD<$4P)$A>L;7W@*1A'"TO@=:#MOK?-^MU4,+:V +M$@H.\@=D"D`*_(SO%HG:@("0C6?/!36SA/7H5TDI@@EP`3TOI^ +M%EXHG"-M@$ID[6./&)MBT'$N0;PUH9@(KF +M2Z:9;$/+S#:Z8-BQH.CR?$C(A;H>>:>%TQBB56TQ`1#D?RA/8'<)2/D5;#/P +M64SKS3/MB'RHX +M:'-JF9<)8L6DFC357IL?QZJ35,^H^`Y88/-*&V9SPT84R3F'$F'P''M'S<4[ +M5LS*,:6JH\,/JA5O-X)V6XH=(=N,`>7>&W:#PZDEZ0^#!D%B^L=`M>`FMSW^ +MIU89$UIV19Z.&YNZ9SF\6M9>PZ^4&K8.*`(*KH?Z='O7*4Y+YYK;2&?+R]$+ +MFDBIET0+CL;.#7^5XJ4`ZZA#ZV->59X-6B)MK->10H7U>^`'J+>T;O-@70]: +M3'-,P1,++?&6PH):OC89#YXT"KD'M$6IY8O4M&!K@ZWOAZ1,\2B"^Q.SL,8 +MJM,48O815$.$VU_"ZEAI0-MI*R0OCVQ@:D"C7VS^_1)#8(P1IP+'Z?#/)M2D +M3J+3^C#ZDM=TINW-C[":HD3$A,P:]P]_CS@EV-B]2U\(08OY%6G:$H6SX*=."Y4O#8O)4%96-L%DK5^%MK,]%\*S@;-2DL7\(J68 +M5?2#`E16)CU7\D+@F'8Z]:#RX`3;3FF9@*P^SF4LM-]B +M2I]IFQ-XTNR@DN(S^Y\_FGO`!07B9HQ@D)R+\[52J] +MF#8W,U/I+]_],&.)4/Y9=IPV_T-@2B`]+OAG!E)U/!'./N]=,4:)YX)6+PR^ +M2TN]?4V9XY_M\=&\B(+T5V^WEP#4L]SJT+P(Q#66>E$4WC'@4>'#\-ZED3L3 +M/[&#SI]=)3A?=)%EZL<#.CA;RZ5Y,LGD$!I:0SZVE,4^[3XN?\O^TCVHDMRAX.1M&0CPN4W8HEM]]@!=P[@.<*^(X.TQ1')(]ER^,L#JW +MESS0VD/2)!;%R"PE1KAC9`K%]`.4XI\1BD]2$#)=!*NVL]]U\>3>^BPQ[;NB +MLNUKQ1V!]<7@O'9P`<])014H!BT[Y'=G/UM35GW/&U?%%"!9[`U1O&(#[3G< +M(9+1!EX-QJ0%?B:3F^!K7%2T_EY?__A__5-WFOTS,T=:I2_XF0>P';2*,W5QG`\'M$@)P(OK=&+Y6 +M?9,XQM6@\A-YQ+P+B?$;'P3M&L'RO(>/3%)`(>1+]A/T]Q`Q6`^2KN%'MM_' +MM&QJ]P!R0/L\D3)T\H\9&SPCQT);GPVI.@;&^E%R"9T#*/OKE0@'9H!;/'G/ +M\F'*UY=L*3"?H?13^J;I'$2 +M*D@V553I%50;3:?O!;DB#8UA@M1.Z_ADT8J]+23ZPD2`,*X6[G#@P%`%>UDZ +M8E=R_TEB>!*T7AIZ^@$9#BZ/7I75()URUO=J9:#0[+A)4;('0BQ9RAG[4@XW +M"?9"YQ89<.D-EB_BP=?8$N#Z84@&E%G5"[LQ*Z1?OS4B>N48?7S:5N-!9%/F +M\=P^/JHKPR\AN*3-,3'1J('N\`6=N+:*X+=28!FB[(6X\PQ]O.+8\WW=NDX- +M94XB4_T:'5A/P=1O?GXH'QNEHL(E5YRP=H8UJ`8"3G6XP'G,-]<'<#836K>* +M#D7J`3*/;!9S]K150>8>2IM8P7"@<;U]MOY4)/C_73445.EFGOQ(P?3S`5PO(A-"X +MHP/:EE2M2:E)&?*>]!A29.]XC;X_DUZEJ8Y\^F+$9Q[QS;=-&&KP(F/-UQZ0 +MOL'(M!"6[051[;6V70]JKS&95!Y?&UGZ!V+3OH#' +MBLR&/A$Z%%Z;CGV.-WJD'_H*WS`\0DZ(8JM=7;+_402<'X^1KF.IUXB]AQ0? +M/,>YI(@CQVV30#AF*^Q/NQ2+.?U[%]=J$R0'*A +M?AI]TN_TH;>OK=Y3O.+UI.??[2TX&/[UA+IZZ]2*\^&,-"W/+O@LT=,XNHSR +M&Q`:[`:V*4>C!]K5)AU3P_0'CRUPYB`)0"0]`+11EC=]^)PU;UX)8>E\9_R: +M33@.0]DO$&<'Z^)Q)*P,9"_`"+Z:]>&KM(S:$`(CYRFQZRG_CWG4Y^Y'KVA= +MJ]2"`807;-#4SLV_TLK:(X_"[9U(:I'3Z]+9_S1KKYUG9G7/$$FX:=`^"+<< +MJ8-`I`9%JBI\(N<1@1#QT9RK5$H%HRW@NO@.9Z9X]&E+_@[%YKV5-M7#ASO#^]^[0\^O#.X0EVQ+PP-I7@/?').4A +M=YV,YNU92'F$N52!,XQ8W6[!_M)NXK;%,GU +M0MCI.S2\=4[*^-&5=%4@SD+1B#9MI??7.ZT(1^V,2;T9[\D*O;&E+@E';6HB +MP\4$#HR(7ZRX^@FT@EC\6'J=U. +MV+I/T(+L!WI)UB*;*7%.O#N,QE1L44^:X:/[W2C$?_)B-%ZKVWRH4X^^B8)# +MD94*\S2%$K\3N:2T9E=:'/XBGNV>S>I2_IXMY`M]&6%,3ZD_HFOVW5@D((2$ +M_Q1>,:AJ]B?N+1?*`JFC2/H9:@\.E>7./V90D3!DR0FO7XS\:_Q1`36&S3&T +MCE3IG=(@F2E/-^0B?AI5<#9*ISN6\V',-:JEW002BJDXVL%48N&JT13U) +M?6`M*?1[1>E::W,'D`@?3S)&L>WR4Z9!/#7]UE)"K_0;!Q6_35A^*%CD7?U] +MP^]&3Y:+4FK8Y@G&C61I\;=#7M!$Y#(KB9KTU:HF@>OU_>$-TCR;_\7S(3$/%0[EUX.Y?=$+B5?+/\/\5F54*%0$]3634,A-.;L +MIEU/:HRT(37_ZM6<5`37HL^13*#I?U%$/#:O::9>"%#.,_-"T`0[AT'=?^4R +M5D_VA@CZ$@#]\?Q1Y8&C)PUZ$8]&B?^^O*&4A?M`?BX-.OT2B-Y^E@$+LWCC +M'R7CQ,5G@6T>=MYU,23X[TO/\A=&C#-U+T6]_,'9)0Y'5+`O-7\W<"PU@4Y< +M)HZT\Z%$%&X8;C7LCDB8US,)*:#A[GF6J'.XE(J0'3`\8(S(%3'DRP>ZLI3Q +MJ)S#K@4%1&WY]^K`_OI\Q%#T_^;B#;[O$P:2$H3+7FV0392B7FI)9S?, +M:,JA+_KM;H.C>7?F=K(!$SI89.\MCB@'Z208@_PWH+%R:6Z:QL]!IBP?0D`% +M+B]]2?\;`%MU[8=5/3Y2L,]^BSH6\I;65S/QCF]:?X;`QL(&DB:WWAXMJ6V6 +MC)&M;:%BQ3OS_5BD7BM_R)O(?0VUA.($+_PXF4G +M:-QZ.7/H,-?VOX!VD%87W;P:,,2(4KZ[B`4+TN"4'FQ=&'#HI'/&CK?$]-^. +M8DO(?--91TE2<)Q(V,J,6*D8F1VT0ZK-[._.RRC*M[FR3I29\'2.XRY4&,D) +MI>J\3(`;IS6-17_V:[,%&K1`IFR:+,*>T/4$.S]\YKE5/X?956>7]M"@551+ +M;$A@IACJ*0N!XRO/\MOHE*)ID+VM2ZW*#AW836*;?>-![X,-!OP45SPF5G5L#X$(U)A6'0/=^C8:WIO73FQEW%0L`&JB\^.;'5^Z +MO017AZ]/CS4[:`M,#/KWG:[:.@7BR_1=NV`7\D8V-1RDJCV^WQ=Z/$76./%)-D5707Z:#!:4JY:*?"+7;+(J:VY +M>[KY3:D=C5$6#?@!MV_QFK)F`+[W/Y?K5`>&A6X#:8T$![,V!B$0@\#LC$N7 +M>*FHDX_VQH!8Q +MFDV0L?R@OGT$$M1YIG*70NU]7A2TLI_'_[16-2C@83^L<U2W\Q7W6J'L(47!*PR[QR(<>T.1A@9QS7Y_B^KG?2G3H(F2>!JJNG^1^HJ909O +M_P`.H$"OQ:EBA)*KG#PR*(2J!5Q&"H>3_O$/$9G5L(W-#+BH2AHYS#S"#`T@ +M^K'_U,&1??3(`U@0L&>7DZ%CH",%_ +MXO5_ZC5=\+2?&LAL9AHF$-\2^79=E<*)C.4X +MF='/]S\/$LPU;I``@H0)`GRFI_XSQ[ +M23*XB%G1#M3V./,(_^]5=K%X)TU])V)6^\MF$JY[X1:#<"2#`9%>F):\/<=6 +M>!,6M^CS(!I0#J7A'_;GZ).:RUVTT6YLI*;2G=Y9M.V?NVZ.RZ.-K +MY2NL_3-VAC;UP56\1B&R$N(%5,K+_-:"86(%+:,U(,5ETQ8>N!F(Q9^D,BCP +MN6&7I'\<9NQ@B1'HMW.PW%\OJ_C`.AP>^4J<=WWXM'`D6)VNKBV;4%$GM\R- +M"KT4(2K2T'"FE_;(]C0NEYP^'S>TD@KITX=`%AX>8N6[0-=Q,XP-L2%$-R0; +MG+.L+POP!AX8&2X8LP@>VRG1D9)12B^`AA%IQ)IUXF(26O-MH=V-5KM:M2!D +M'SQTA)&\]I4N81UCQ#T!LJZ.&S4#S-"%93WP8;/5Q&?)3$;N +MM)EC=W69_DT9$*7%(0'3XGC=PR]M('ZXL*G\(Z"+W=[0,^]89QK_[0(F_UX: +M[4N>H8;HH9QA(SU`KXV5+1B(EYPC\IR^N8G.$*A*,MA6*R(UL'"B=0M@1BIH +M3$UXT81??M:<:YH(P_MR5?H=A)*2U6H.X<1"S--2;&+G&&2F'*\X0J25(IUF +MHI+HQ1$+3V-@N%O%*/7N1&2P0%1S6UZOA\(RZ-[*:(O#L*4%\)EPUDKQMR#+ +M]C*F$]%%J=?H_"'#V;!,9OV8+EF3,5EJY<&IA%L4CI7:KO<-;\) +M_AH:\D<5CR'.>V0QYD=AV/P_.\CC#8015SKF#/Q.3#\/E3JQYW!@$3._YA&T +M0T_2HDSPL/Z9#(OVCR(1+S3K,X6^G]WXAL5)2'V#401N;W*:,Q3(2T=F#?+^ +M/MPG5@AH]1^M?/%GBY]--[T)7F\RDAV*TXW%+[_!%0C#3C^]J4N,U/C>LFJ3 +M]9N%06K4E&W3 +M;1K&:76IJ@'VM"B&.>Z;76QQ!N;%%"_^A^),QZ\`P-HQYO!:W&W>D=L&^2=W +MCR(K"4B[GYIJ(Z`&N3T;[YFY.!QHCB?.O;*-GV,BBR#P!*>5)JO4(8GYCG-" +M!5>LBY`5AZE!?Q^CP&15/U]1Q[J:S-6WFRE* +M+UCMRG+1L_7?T2C@`S)SN17KE]*@53B8\366*[5,7SD$ZYG01;^5AQK]Z)B" +MF;>C5K*],L5B'*'9K9.09?*3E6-78,O^_Y,DG$MT4NJO%Y\2<&=:QTPU<+,+ +MJXV,UZ!Z==F?&JPYVA5T&D]%4Q=H,G9(>*H;I8(,U`8@]F]#[;7^;$%Q6.A'1&Z4MTV6&!M`_%C+PL/F$%L3]@KGI'T +M\EYIG,J%>':14CHZJG[=V*N"4_A)YZZ^9$%[0^(^@&U5E<#7[/&0\KM1NKBY +M:YI`@-=VF:9D%0$Y_$>H'/Q_4;`"I0L'*ZSW9/I=.S;3B0A"+/J*[0C:,N`[ +MGDA1JUW:)#U#_I8/%4P0[;75Q<%(+#'`&WLS(NW^;S.18ZX'/UW$HTXL3VEHG0 +M-MG`)B>5+5^P*ET*/0A`Q"1?:1Z]*I'_3^WFN$5]GO"DC(TKCR!JPHBV);;: +M5NM./C8*ZI=?$-X@PN`-*P3%$F?)U#E\9]T#A35>H_IE!9XHEEJ+?49W,U`W +MCHS<-M>5R._D-SV57"#)CL9$9F`#;MDTP7]5+&Q>DU$57OZ0:M&1MM_K8Z^N#G=?[J(^?M6U2P:\! +MKN0KE.4R'=QM8*)12J?LJ=R/M`+J1,K+;.IK$3Z6V;)#I>;AM\/K\TI(K(S^ +MX0AUZBXW&)-P4N==1`@`OC>D^@#XXE:2I[I//0R5U'7CV`%3L>3.;0>>\O;< +MB]L.J/UQ9J8(NO@?*#1$U($;",%.8;;V98]EP#T6FBBIEXL$BR@ENK[N1_-^ +M;22,6*S3MYR:Q0_?2A5HR]1->P*($X)`>`=YY_Q#E.Z*VH.CVIS7W\O%=6C2 +MWY%Q+XCX";J;VF_U!G/[2*SV;:[8'1++NW1MV.TMX!U?G"3]>H^4?M+K=%V5 +M.0/[I-.!_-=++Q8VY,A.JOHQ(2K687EZ +M//=AFE%BR2\A'"C(!.R7),H!:+$E!?UXMZH)[*AW,Z":BBM:;S#]YP5>&+/N +M790+)BP.HA(8G`*M%_Y+@&3(\_'9TC\KWXM,#\V4>W3VI=X&!93VSF!1SN&; +M>?C_]#M^R=%?7WJ6AML5S$F$JSI:[PRVMTK(_ZSSOKP),Q@X%H")45.(B!JE +MN,>2L=@S+?,5Y%D/B9EL%Q+X:,X=XHO9QAF8#G)4?MPH(\2!V!RXFBHA&6C< +M^5F`C25*AC]DIJ_LJTX0KF_GL[@3$)JPA7^78;'"H*Q:(H-%0):8<,'AA74YV#M>L&YX44P885/AYLTA4K7L@>1PQ5&<#\ZZ@OM'"0HL: +M=GZA,,Y'T@7],N:PD-&$P!V&EI2JM^^[7!M"S4F>52K\RHT*>HT]U.%N'4$` +M5;:`7@H;_:UXZ45# +M&.WJ.008V$$:/?"+_-P`MZ5^;GQ^]$%%(KYZ/VI;N1FWV%EW58A**D("_A#3 +MK9<&?&DO3ZP.`M.62R;)[*^0P]5#;M#$U/.B$\Y&.O#*4SR+<2 +M^>R"C;&>!LU7\5>_9MY0%MG+4\]6+0[Z"F&.7"(85(@0NF'9N87'V[=O_9&' +M%2Z5W+%--KS5H;(_"2Y9\@WTC,P'R0`3'LSE#7W*(%,7LV,>-+QD8F.W!*!2#WQ6/;M02/;&![@LF7E]'2G?>.NNZ2@+XK'G$XQ-(F[SW/Z#+S'=, +M"5L=:VR=MV1\5%UE8EKW_D>B%3O^_Q3LG:WJFT&]0&)_X.BI7-)_,7J +M4(E^QJMU)5^\WXJI0D`X4I19EFZMM+46@223 +MM5I=74[K2;&8KVQ +MMOU%2(H15MME;GZ^5X9B%35%^ENA9IN9_Q[@\:V^G2XGFAKDK?--6JL)4NWE +M8.^TU,?US.=Y7;KAIU%#6L*JH57J1@#0M`4E=[_;5:38O]`$?9,MY,8@CSR1MHPAZ?!\$< +M2T;]3V01K,<';+[#"YAZ]Z'.Z@P`VU4=0U<%]K'(P!,',AZ:9X%M=/?`?*(8 +M36TOA>\VT<]S[^OBR'5@-F4LMWABLMQXS.I\"A\3N/B8NY2J%@G)!XKD]U1P +MK*HK5M7GMF-V/)LR^!&8U9<"MM>=)NQB[RP'P9]N00FG\44MO9$LVEZ)77Y8 +MDGRK0EETG;.WKKWIB2#2%GC>.Y:#2(3DM=&W[DXH!3,MH'^)N%[%X4*_X,6FWBR@HXPH#0,EM7D8>OP`=#C`,*S43G)3@*^/X7$1. +MV@A('N/IUN)QI31D.B1)S>`PUZ-&WFTT,D&R\Z$#9:#E<^DH]4?^SXF`9+G- +MN8/-S=BN\L`S,J`$F*Y\`G5,-+#;_5ZT$A2EG?/4]I\-=U;Z?%#A6/LS!%N& +M38=WF+J?P)]@6&`KBW*ZMKJ_@FEDR],TB%TD]D%[.M'WE3GEB^JP#M%+>4CG +M2>QMZ.212%&6HUDZ0+(KE0Z^KL0=RV`1<&<>&WKI+`#ZFBA*DF/)`Q$@)M?* +M9):[8KP?FD%CC#M_BL:20IG(['6?H7;?"9$$MI\M+TCY%VR`.I`UC">IE4BI +M04S&9C;(K28Y\/92F,MU7>_A_+>SEB73?YBVXVPC9QYTL^R!BL"?>, +M!KVUQ"P8["O3Z8LC^*6?H(`^&=$`%!R]REH'Q`N#A1<^:*1 +M$@4HMEFS!0!0L,N@D7#]*Z\6C,\;II=@%#,\V2I+'4!13C_X>*^YDF0PJO\G +M>-\O7>A_@[AYLUTE";7O`ZL06L:1U?"ZHIK`2F.G<'R-">%`1;M_38ZB/3=3 +MY:4OF176J1I$ED#]"Z=%ZP*&WU&!:&@-PZR19 +M(^'F!#!7,ACJ6T/BH>U13KA',F6S]C.9G]`.:*X5#-X$6UY>KA0OD@J@RO:P +M+5K>T-7_M:,[4PVU7*-29F0^ZS!/VZ@QA&(NT0QX6)LJJYMS/0:^_Q(1,^FC +M'K%Z`_BAP2(K6I4D6C6NV!$U,6+78"?X'%>]3\NCTFWO)K6^1ZEII^=\""&- +M"8W6P]Q5NH#;"C!.=:JO8XCOW:P+HVR?R<88)M6(E0[XP5B>#21SY,70_$#H +M6F9I;JWQ"9;'7O8==GF^$[^7EH261"QW%C%O0]TQ"ZZ3WECF>PT%NJH17DP" +MD7/7-K(,EH3Y035VIKW*A&4E:=+ED/=%"KB!4]/X[;Z%-D6@P-YW[[E[S[#6 +MP^:<[VQQ!Y[J#?]9L+VJ^C%G%\U=:"8?EORRKK\,GI_E0YJXPK>7875[8VXJ +M./:N+2$\H=4,>QA264AOJ>+A*[[^C..2BT\D5H[U\,`ZF^_MY%L)SVVW8-%^ +MWEF"@6[I:]DV+MV?;;QM[OPGSPK/8$$U`.%1!F\BQ$&U`Z%4WS1$E\@51/T7 +MQ0V+0L]I=Y`7)*5"XU#IC8E"M.'$6%B@8+['$>)31;>QY6N#!U;?<7C1ZT(" +M"(\#SQ<%TWL!QEX3DI#!5E!]4$/()E[4WJ/C84<11(9]-;,=_W/5QP7K.3>; +MR"6?N0(\#UO!O.I^0%8.H-5T>T".==EU8)OXTM1S=BQNI"6(U1!4K>39++?& +MB>T_'?J`NQ=(E2M5R$<;X'^UT^@.8XU:\Y.D!@.Z394ON;=:\9X6_2?* +M(V_PUYSR1%"CG7]Q"I.RW#M7H.'^(*OAOV1,0["Q2>CP+[.16M^FK3[]1"'16 +M'1WB'3C*V('(+E>]RAFFS">XH(709>$M<#"[OT#NQVG'^8=^\@3AC*#YA0DO +M?X$YV%%@/$;D6J=AI:;,'\&!I=L!^PDGTI;4O)_P/->&]4N2&*8Z*TAO?<@% +MJ$S-3ZIIP\#!,"J'^EU.C/4+91;1FX/BU:O@LK277 +MY8+/<;HJ*M09&?S%ZC.NH/UGLH>P+-F@6_6]B0-PN=]Q&""%P[>WPP_QI^:/ +M*23"0/KIM;8<=@\SN`,##CZ4!CG8\56%R!]2:E1TYI=F[(#((%B3P>+N\Z)0 +M-R2.UVQG:;[>=GV@"!`#SB*T#D_-(Z';X/=]QNYBO4P+DJBU@S5X81_A@Z8`_ +M8KAJT]2#%#E\\?^BT2X0?O*V#B+P^7U?+TP)\Y-_I\F,^+#6A;PHD@[7I%.T +M+GW$#ZOW3$`Y:GS+E4H*&6NATBP#:++YEL +M,^)3AT@I(I*80EPZ=^39AWR9T6#'B)I#O[9(M(W/"$1A>^*QOTY=_K'TG,0K +MF^\JP65FS[-G-5AX9,N +MZ,3GN'?DC8P0J@+5E*,Z;%\LD'C9<@&+26RL:O6B=?-PD62#`_G(;#462^MI +M2X<'3Y)W8AF>;4CUG`#PEZB)Y*P!.Y\9LUU>V!!8PRH:^-].^:\_$W/H9OF5\KYC#.:>L]E1^FK! +M*.H(.]0#&(/B^&1MHB_C6;A?X^!:Q)8=SD';*AW#, +MK^?&W9&HF`;5/Q7&V$VL^]1Z-'Y0X-%AU_%&AXX\]SZMA@\1PL+U*?%E0_2\ +MP*W!+E]=!;GJ,8=(E@&C(@I.\9#-6T<3^&.*UJ=[[,1\"UIIP^Z/]3;7#2?6 +M5%;GWM[9$X::F>7]U.()@4'2NS5/$]-VN82?T<=!(TBN+RYT_`=$B47JXK_7 +M0I#R9AFP&GI6S4M:/"D@5$-BEB9"QB,H-I_)(I@I7_C[@-+,FL\! +M<^9!%Q+__U$U^&8U14=<8"C/^4Z_\:JP:D))]IJJOEPTD/X +M5OV3^;I?]T,9,4/:-AB69V3X[S\%:G62ZMO70'M^CEJ.1C0O>0_L!%8VQ#`? +M>L\`K5_P@'0ADP^5T^7FQ:[[7^($P&1D1BJ$P3=G2> +M+0+/]V$0@ZG!CA5CC6N5?U)>1'T'.=R.H"]0)>2(\`^!(`[7^2W2*76"T2>Q..=-)Q<'Q&%=XE*SWC8J:96/'AK2WQJ6@( +M2&K'B$^LI!/K2Q_/<\[.B*^/Q%W'[+2BA,.[_Y\Q-&M#^)"[/`' +MJ.==\MWHQMW&90`.('1F[2"M\;+>&N$<2'^278+(FW-IVX%V7;(!:6DAGN%` +MWU0#2&9.T:8:1#,T9<\U"&U%BQ\G&9EOWP?WC:EW-VP!"/Z]$O9&;UID7>\ +MK$Z9!!QW"UY?R8%A8E+U5])GBY"N)*TW(GPD2=I*8B7_1Q-"B66;:9@QJ+-@ +MC7GQ%>GYA>U/C:-,WYVP_B5YMK/67/TA.4["D+]C1N5%C-`_&5N0KO9R98NH +MFI-<=6ADT`;69R^5J9:7ZLLA^.:E&%1)P4@%]@;-]F-UM&V:MKP$;T&6.W_] +MI)?W0A4N/BU!)HRC3TX0'*+?M32)/_H_"8Q8(DBQ=4,OYW;72@1$1;,=:7/; +MNV20B0_$685TH!F\5T20+!9$880N:@W(#(_`.VS1CW`!5GG2LN3U6]^.FS7;\/$E2A^AKS^Y.V8"$X(:K&LZ97B) +M:\*$OJI3\.XKZ-B[Z*ZI!PF'%6;]>$)`/C+N- +MGI\@$^VS;NC0(3Y]K(0)X(1C%T2?`8MRN++NE#.!@DD]^5C#'^%^%J)9RH"= +M/PIBI"+GB^2;Q`K5#(BG7#!CS&!WYB8>(D1W^<(W@G[2I8.V"/MJ7(V7!87A +M+2-]9CH)?4&/A0JM;AH^]*75$HH[S)(77DU3]BD)RXK_EY:VMJ]!PW4VGW$_ +MQ@D1U(/3W^[-\$>$;Y1QV2334\FTQ`<-J)886V(SHDN94BN%)J@6D$R?DC>[ +M@GH4CR!,S?\\682+2A$;[M0`R^X7I&:GGSL)?:G]IV;5'?6 +M_K:-\,L"3`^-4N5Z^)?/5R[`Z^648=9Z'>??`'FQ +M"Q&'?<*EY/<\=PB>'"KK=%ZRRU;^.ICQ``Y9!6S?U?`V2DT#FAY:=HRE>448 +MAA=C]W?Z\[]'$0PS@1OQ\YL%=<$8H&%`%HY4YC\!U/?-Y:XY(\KJ)TZU;7J9 +MSWM_7TBVB!UH?RB&Z=TUH)@,'*-^GA>CT1;&WP7C:JX(RDOZ@0I0@@$_H%5[V`L]K"27X@N%1OPJ]_HP+FEQ`?I;#13%O=U4LP,X>-3O]L,]LHC1]4F@+ +M5@G/[C@]_+^BQ*$)YPW=?%99E^M-&[6*HBDS0D*I0J8S"?AIJ'E/+\%//E:A +M7@`$MGHFNJN%^5_2[]-HB_1++T-^46A-F),Z+[RV'5X/)9$H.2[)0^ZSI7O" +M?Q>GVVAY_G;90=40#&%^ME>#`Z5H"!/*Z` +M'DUDA@S<"9WZ!6'J`!AC:_ZZ>8[/'G3EBGQ0,E>/98$/[U&MXL&]-I$E9CXU +MR_OX"XLAS8"/S;@^5(:+F\ZBW2LV;H+',D$4L4Y6)'(NRV5S6\H`;+*DN*]" +M`K!`5]71*_I`_#4&0VMHX.W$"DIF6M[]:-U'+4C;]2/"6T@;$,W7[&V4/+RP +MY-!:%U:I%#W7V&B&+1`S!D),H_`,.Y0%H/&0/O7JE_%YTNOX4B2SZUA6XL>! +M?^%O\+L\PP4_IS4^*=F7\0I1FV]IEUY?X/(5)]84X4)^6S%\-5\*%"E]N)2Y +M(&G_.W#[=C%[BS=VD_59_P1JVSO0H$G?V'&UN->"8]?#@+.6JQM1AC9"PGF* +M37D1<`;C?C!G(-^?.UV3[4&K)G;45/MQ+`]X7MR8<[W$8V2WP1>S\J2RD,1: +M>C8OG*`Z`.U>UX%]IJ&;(?5;**H=938:UHTG`NVY+C+GX!^ +M?JCW`H4\W677S9L$G*%OUT(*YN7`@QE7>L#W^Y^JXQIG*M>T>$:4AD2`$3$6 +M^R';`1.X?!,14D*@X2\;D1=S`NGV[O1+5$>I'0]PU?A)0-3N#9;`\DUCD0?: +M60.PNV".!<6D)"&XZPV%9?Q`1@3+'CF!9CO/!$\L5DF*_X[/+=`D-H4][!<.FGO]7^@17QB`F;G>`OD?/@MQG`H'?>- +M0T\/RL3+H#F&4_KIUD:1-E25PM-5-"#D3H];H99OVIY5TL(,$O9"UWQ`7$$K,T[Q(Y;+);9:(;2G\D^D=GDT? +MP58,FZ%"&3-W7K#_W0A:;MRZ^&]JDD*++]>GHN1/A^$"GYZ+LVWBRY2-0G^_ +M`G0SOV`4;4OPMX4,B_)G+8B--*RB/--\[\\:@%^_QTQSKK,5O&K_;[V$4,O* +MFI1;Q4=#,GO6BU0*%1%!DE(J-K5KC._Z),??PL(KE6("`F9`O`C:VJ=JMWW="'XF\9M+BE@$!21U@!# +M@Y,U&KE/[-8P"[P6@K90NSY?1&ZU?Z9X(,HW:?$\RPR`4EK)Y*`"_55%2IQ= +M=2RX.6AXKJ62K#FB"]UJPA"^2F&/+B)#%5FNY[<8"10""DF3@1(?&Z?>*5!7 +MZL@#9GUI-7H(>5AFT/K55W2BJ![?JVQA0)C$X(CP'>.P\*P[\]FC-C#!;@I+ +M2F_!Z/C(-"=]6_!?2N>JOFSSQB`449<,1GVLV]>*CO2%(GQL*`A$&ZOM)0MY +MU-L"T12WDHO]4*YF%+-HX4AB-IN#(X +M-\G8:%!^-)9R?HP>W"I@SN!!0RQ$Y4RU.:#9+^;]2R8<2 +M"2FV7Z1J\$SS]ZQO@E\%_F-#Q@\)CV?2G9'4%YAJ=/\\BZ3V=6"-7DVM9J+V +MW.`CUY?U580V@N')55R)_Z9>N^R2#KR*+HK'.R\2XQBM;0^"IN@#.WP0Q!EH +MUPOR[(T#WJ4)JX*+#@(C>:+_V6+S%(6^<+[LV?XN2A.LFHW<'$*?2JT +M-_DS,LBC$.N6'B-_Q;O@*_\GR11:FB6T&H6.MJPB@8V/ZNJWK1_V +MU659N4R&C0>?!7QZA7D$CS.Y.)_?0?ESRHS_A&A&2I&Z9D9ZW\M,^P:6M3B' +M1\+0L'Z+2S$%^/8WA&M84LF`93F9>6?Y:]B>P3%IQ(DV(2\XHW%YOVL11"2G +MV^[7`;;0]?\YX.*XE4/[^GE/9!R/*EAZQ>UZX;',T&3$Z^T\? +ML=-GE_NP@',QT\*%^9"?C.SJKBM\VRP$21]V"A82-`ON&;/,:DBPOQB=`S)H +MBG[OMX^"\NLHQK+,,/>DQQMK$7#K&H0GDO=-J#E\0C?T,27C&4%IHA-*P:]L +MDV00D+IC9&>RWD5NR\?K_L'=W$-X)[[0[C.'AXMM-?;*8P[H([%"AV@0RJ_5 +ML*"!(NUXP8`T=,.2H=<@-CC7@OW.`!KD^(TQ@]%(EM%3UFS@6'QV!.-:T?,8 +M&J2^=7?(5A@X3;Y;Q +MB)92]*?X$/CB<@[@)$3)=E=3."E6O+^GBL>;&,`N-.[Q-].TC67<>3?!:]^U2V"?TA8;OW?S^!Q"X +MJ\HJ*3^_G+JO1;CTW3L8D.ZIF7V'^39HFPF2M4\O?9/?(RI5DD__S23J#,YW +MHI9LH7\2JZ;U%V;C#&D=[@+ZS5>IQ*]]7/76 +MJBZM,F8PYXXPBX1B/5&+&YFHD*=*9`W3);]@\[8[QV)DX`A2KXW)6O79X["' +MRG7K?/(U#E#V+:H#>==0/S[4'X`;8YV1 +M6?6VNZU'@/WEL"I200\5/.(@?I-ZKMRL?N;)8&21QO[+?_(<[Y$"N"G`51.$ +M]^PBJB&`"RT@6)I/+$%1>)ZM?91IPXYGR>H'&;>Y,JI81+EEDLD->" +MO=LL?.4A(&CO='O]6IZ'],=C1JUPD5<,QC*:!+#';Y8T[R]XPV<3&?VCS@M6 +MX:#O)[0ZY3%J![MG6&D_@`.@A\;(?[HU(8I]L2KOV'M>;G=-0>G$KC`#L:C[ +MUL4EI,"_IHUHJY>T_5\(\41AQ0Q.YGWN,GK#DTNZ7`)_/78UWYU>!3;;7CPQV5\0V+[J +M:GP[SC79RHA,K)$D&UZESO*]B5I'F@(+86<-^:+8J_OGMH/_FQ(?;=MUOZ?N +M_"9EU($XWYFP[UB"*JUG0)(8+1DRT`[/KS:\Y2XO6K,PV$SVLJ^*7G5]4#D0 +MJJ(M5IB#W*%)%G[UG8&9%$E(IJGAS8%H0`:H)T\+N11S<'"DEG$5]E`)=`GV*;.W$DW5%.454F5Q1V0]@99`R4A=)B8T^W22, +MJZ]F?>TK'1OH'%INRD1Q_UMR9+P%ODXZOV:]-\'B%QQ4F'#9^.7-*:T5M2^H +M0T-.3)]##7BCF_(S#7JU+>,NZ.K3V +MQ?.V^OZO$`S4#J>?;SKI!_PN&!2R&)``XL@ZCT`$=Q:)2TO7%9=H^!D$G]L$ +M$9K@(Z(_&O,*)/"XZK9RQHT3C\98_&'W-8#FVSGM;(:`'^^&BPN^V3#>@@_Y +MP(O99#B(J\K:GT[3))=`<;[[X5NEE>;S?)*=JGZ.9!)]\6?,V--3[Z,P1,:K +MR1N?9K]GG,VL;TDND5+K=2@(^RDQ/_MQD"6O?*\.6J9J:%)S/NEX+7[L\=T/ +MU/Y+-FJ63?[SP5+Q#IW.GZY.=$,#[XW3&BO4,YC"[:5.#RH*JWB=[[RS2YFW +MK+;"?D.G3VS&AX5J85ER1-]Y4/H(%J-_TV6CI918]WSN=/8>W'>]B]NOM4C# +MS[G'+#D6_CZC6"G"7O<.I(M8!;^TV>&BKG4'ZEX0;;TBSGA!YN!G]ZGS*P!2 +M?OOMCHK"^I/Y4HV'7&S[@Z"V[8,,_$3!T&0&-M$I38VJ$K(GEAT?EVO[KS=3 +M=IU(2!T!]A_Q(8M`JA]N>-0TL++[I(:3'>%*:;FO]MX9K]EVS`R[XQD6>D[@ +MY+[UGT3&ETC`Y2C%&(G'1MW[E25+OP9CG<=S;I\OYKM.\_YX$@!I]E48XRU) +MT&G./M*H]D7Y%4=))I3YX2?0P)6+C1VGB%L9IFI.SVDV$.011JF&J1K&+]BK +MSF_>FA=:U3+Y+[X>Q[[_[E;6&2ZD2'J917S$MX\!S*71<4O\(IRI+RU/V@'J +MH8#,<)41],2]/KWP!P\MK_6/CI;`D:WA8ULB1>^K(5321]J +M`5=9NQ_5+)496KE0!?(=+G:$*<"`HXPTIK*SGN_W9I@Q37O$1U;5^R3IFTV7 +MXLGN`I'.167-'[R'J,>_)(U.[,7(VUV=2-6>B+=CIR&R0)$AU:\ +M77L$ZW'I*B(V(PN7G5.E.HO]3=N`U/N<-02.T3^.#7$A4CM_(H?T7UM)XT`/ +MR"IBC4&O<<3(.BR35=[XQ16>S@0I@U(;B++>&3S5-Q`+P\&M7)[UT@#338T? +MD'%A#PYX:76$]FVZ$+,+ +MRQ11[+9NW@/D#[;!PX9BAU"LI9V%%[)X&Z;O]?\BB`Q+C+">$CY +MP/&;_CZR^;3:$2-1_D$/]4;>8;SE:>/7.QC7C6^U3JVAW@F8:G4@](5;PN?ZTM/$E(6A7;!Q/R@#JE)B*U*!HBC4=2 +M9B(DGN>O2)72Q]GS%10W70XCBT%#@TZW&O-'Z?":;1\D*+&3T^% +M1M:)##7/LD%=9AX%QA#!+;B7.#]U:(H*(1?"02"`[>[_O=(J@-65PV6<)<9! +M4GYSQ=8P4`;932P&M^J^YE=MY*&&<^&]S?L<\LJ1)G@G@VC?1Z]&[,C#:#`J +MGO50H%Y2*GT'OG&5)2Y-AB7Z=0.:IVI!I^M]!6L#EW--WS_$D30BBFZ'\A;6 +M`KWGP!+AGXJ)E"D#),5,T+VBF'J1,?J>T.Z#G[)'PE2RBQ@.ODI(PM-Q4M,0 +M,""@T/Z,^GF:UIQ6%O^&&>3U+"U@_I0NYEU,?MI5CI2^O>E +MUBA8#+'-GM==KR'NBV&I<\B)_VNT^TIWP>GVQ`/A;K5U2#XB+#N@!)9S_N8: +MY@+;DE6@Y746H40?J[/1QA@#PH!+=H45.TR4PUQ%B"1-1$>+4HZN.G@-AUAO +M$R3Q:2D[+XGS4EA<'253I->CEDKI&^^!-9MQL]P44C?JXB@!JD(;O.&IM*"EU/09;F5K* +MYZ*L9T`ESZIF.8H:"*INPQB;==^[CYT'F5A"V>\*E6\\Y$!?@AC7DP00\*ZJ +M$2'/,GXX@S^=IIY@FB/I%+@[Z$9J*4<4N/1H>_W*0.H/=6Z52M@SB5;00>GR5@0]B!(=+Z\UGD)%6F^`QX.;H0`>T-SS]IFS +MSJHR/0$N@_[WK!>#9E)8E*E?].>9T">M2=^M"(IONF9C8^#8*RSH=;CG1J7= +MH).=0_.F2*.FONWVT4M9'B7CYBK0Q5"K%Y)]%A!`_'%\+L_ZM*,E53E$\57? +M^;]:KT!-2NG:IOZ,`:=I3B%$MY%VECH]QZ0SG`;_SQH-+3>:!H&7".@FN4R4 +MJD7$;3>..6U$>.C3L2UR.-Y,3B+W)AMPAHLRWXZ>Y+=-F\$X2,(G^KC"#D:& +M9CM0X03'=HT*`_8`S[A)'FME4XXO +M__I!Q89#><_W-MH>\'TCUSQX0TM#984?Z\WE%%>KK,YAA\;QXL)R"C* +M!RB9`)=\]W4S:@RLTY:/@)Y*NCU*Y4PH^M!+TVGD"4C"AA,,KSM!]FFO7.]E +MX=Q)_2*.78)7,MWLKG8L&]4PV'$XO>)7_A3+++O6[\*S9RT?[G:2GCZ^.Y67 +MP813B-_-ZI0DG*)K5U#N3?K<]GL`X?>`_1J#";"K"I>0OB%QHUFS5`4=N@FO; +M7]X<=?IVA=0-W><#^I +M)7D\97BK)+3<[UZN$-;Q4OU_*CZ-&ZA_F0AE5$1B7B>=,J/CN-C5&O*;_""P +MC1VHI/URT4[:.?-VS_GY$)3$LRGA):F(RX)'=B5) +MGR9M<4BB'@\\(![3Z,4CWW'=ITD)W3DYF +M]5"(VHV96KNAV2,QRJ9WR[2A/E$?;5\]<`&I[-;PZC[@2/F[79-E/?#==+CW[' +MY+(<^T"17S^U!@W&PI)W<_+3C&6*E(AY;G5RZS"D%>9^**Q=XRA5)W4<8ZF0 +M"Y4\.D@H^0/MPY,-G]%/1U>J8=J=@,?%GW(X4!X:CP0/O3F$-Z(.P8FRV%>4 +M&"6(-EP84)`OG^?^7D"HEA2QHG>]>DI%(,&.IV&0&:&M:0-5=V%H'0US_B'\ +MHK9E,NH^U8,>C+;7X@R2?NI9Y!MCZ-)&U"PKDODD+^XNIWBIEDA2?G" +MGX53[QW>"&JS0%OM/[>"3Y)`//>*9($$`QO<"#/_DW,_17[FIN]5,`4_0#MH +M=`6AM>#`Z>6/MO +M[;X%H3K)'[<)KKL_])WSV6:H&2R[T9Q.AO<<9GI5B92\*]9Y?A.JW_U_TH.V +MJXP0V^C:&3'6?UY?>'+8@+A'<&&U4!FHU^Z+'T6?K!6ZB`+(^9!0XXJ"I@`U +M7I4];58#S=L?0C?T^W]^R"/`R#618(,L[NG3*F)E!YU?B^Q33ALR*C\P!^Z# +M^$:B%KIJ"R+W]AFJ2@]AE_TXBR_4H6)X;;J]:);ADE^TA]=LVD@V;,SXF!/3 +M"(;U*`[T-.!IG7\U<46\L-2ZSVOB\8MRTL[U:+#+Q3>`L".[#!&L0%.HE:TA +MTM"9^ALL)DF([*M=36J;$)]Y9@+;N3(7,LMU=-\"&LE`T$@B)OZOW?H<2P&G'<98F(=ET7/F7X="G`W]5#:&,Y`[0;\@46 +M9C!_C![PZ39*CL`B8!N!;:AB=K0BH:O+LL8MO'H6G&47K7F\YT%_!"J`"O+8 +M*6Q?>8W4&&/&9_1VI!*IK!P0]CM\AU,@]1N<50,%,_/F*L:*EMQ@'YFBGQ*R +MK-KS-H_5F&(,4X^,KG'>BF;#U=NBS%\P#ALM>B-+K?I1]K#YS2*2H1E%\A-3 +MM^BJT2E]E4T>*K'F99&(=VFQU/QT3TX[8"Q&QB:=?F?;:BH5UPPG>`Z;J;Y8 +MD,WKMXAK#."&V_6ZF/R6Z2)RRA:.F@@SR.CU7X]#.L0H7A.M-)0N$-?/BMFQ +MJM=0YRP,PFGGAX\4:99V,+U@G7GD`9\:TFQFF#F@!2,#$(H^,2V5%KU-%Z.\ +M7C8<4#[B:!6?X"?-9_E::]/^X&%R/RO5F,."[BF>YR'H5W624]'R+B,2_`42 +M#_$SCT@J`SE,5N:I9%&A/RCFR][JOKTD=A"P>ZL82QG],3SYUYNL>O''Q+D* +M^J<3C`DQ*VM1)9?_S(W"0Q-A\8W;TK84:1=C(FF<-6<0[\,;/I5Y^NYDE^L] +M,YWCDF*,T5ODV+]F4']Y[^%>&?JD'W5P1T(-W-BW0ASXIT?FQWQAMEK'/&)6 +M1Y5="F)7XKL1`/$&0VX3G5^//M"&-;8"S2)X(U(8=5ES$6N9#5POE7\>OIX! +MT=#2O:_ZTQ%G!N]&O=N5&*5]=\'9I)!\[?-\J^&+>GV`)9@`Q>/-WD6VI+I< +M9<0XVN0QFB7`61!6W#^U?A:V3KC:)M3)L\\_(?9<7I4]_L/NF3^AWUK6F>8` +M#NN"JO62G#>$*\YFA4(5J/-?S3D.22>PWL_BUHKVL?.*Z[*3P$NHI']C?O2? +M$?.1"ACL_Y>?51<[Q">2PYG(0._;@H5[V*=[FQIL!>)LW3 +MY"FW>*K=O=6[`;Y&M"EOSX(7D^'B!]4+)";T*]MT"7@BI<<]U)#PKHNI/!XY +M4%1Y`X'6$[,(N'NQC6OQPVAVJ"1MV:8 +MJ['QSOJU7#^!'E>D$9S;#'X_44-DAGN^76]N4HUA];=B/Q@=X#R9 +M%2@0C8]\;T2.1__=G6*FU3Q?2P[#/I&6-^3B.;5$D5P?PKI9;VKVY&-]D`)4 +M$EQ7.OE7XJ802*;Z7T*VW^K_,:`HT.5&78MF5O(2AICOU&)2FB4@H%UJ"B*C +M`](TB*.]<`$YJLRHJIZ#I*(D +M[M5)6!&CG14"PB!@I/@#,V\$'OB]ZRO0#E1,^$WV;^`47I"W+PAV`)U+QCP. +M&E7"HBBO?L8L&T!W=G\.00,JT*8G9LR@LJ@P"%UMJ'?"Q0(W09E+KQB6(B_\?29-3@)E9FHSD0Q[6.7 +MQQ@_:(JJY0E!U5MIM4_]1>^[@&34F@:;9XI#'VD-(ZA;2]D&'!U5.3)^I8+# +M87(1DZJRG4TH&\)2[LYP@?^@K$)N"RO82[KK?C@:OF(P>B];)L;7.)XK90"5VBKNXGFEE^*5Q;#HRZ3P1:R;3S;-G +M/'0`31**.E<\:6(P'EA&45*0:UYP`+]?2`Y-!3[^U".N712A*&YO[I3RBG=2 +M954),``?]D"+Q$\>WN6B_0;LZ=6&@!$VS7/S3-T#$DV.WC+"V)G(%%[RQLKV +M_F1ML\&E>1I7O,SH+$2WD!33XUD^WRRTAVUC23S/://(MI[ENY +M\-I3NA^049"GHFAE[&22@(D49_4_QDB?3V1*A*4'S\6=^/0YEYF:85C%%%=" +M,CH@GJ<40QK"65#7)6( +M5OB@)=PAW'!'YRWZXR&WC$OLQ:X>%O9\8J-X=_20F*D6:GX)R8>[X<(UW(X4 +MA5,_)X790Z>/Y>9_H@?]T9W<=PJ=+XNS!4S!V2R-DZ@2:CT47%":,[&"+LR' +M(<[W>02?M@E")T#0Q'/,B7T8HC4$PS22B@M]OQ`LJ$+$*"(%2D&[O>6^NU[UPZ_Q6+H%9+T7< +M4L$1B!0`5W:F]R4!4<38B`C%>N%L90<7S/0!'YF^=?$(<5-32^-7/*-A?99J +MSV:_#._+]=8;ACR67%F3>@!XDB;&WJ.$%$9/Z!P"6[,S:2R/I<$W:WW`IC0J +M_0_I0[$>M%DEQ*E(91'?;\-J=D!F][=R.'.5=H%^<)836]$3A-Q3>B(/0NR2J +ML1-<"%1T!6/UP<)F(GS8+FJ<9\&=-E[HM4B94I`X8[NH0W*)P>24)[J**>7! +M-3.[M"9&J=-@M!.2DJ2WH1<=>06FV%VD`[ZVJU>!X +MU+V0M9:]]W'>;W(['<76W-R[\,X0M4/OEUO2ZXST"`(4`&`/_9#O[N9AIBHF +M2\.`ZM$B9ZV,,P%N6I6'<'BR75*6N/B$GK3$BF?G^6,A?E)-%Z3]^^$IRA^S +M@>B/C_Y-S1>J=)0Z4GF;BIEB7B*UHB%2X$$B09_8^_1%+-7O8*?8' +M^W^,M^%*]:X["]ZJ@,^?%CI\:"BZI7BIUPHO*X#U`=;.4NUU91)C-K3UL=TTFC04GXMF54]R(;JV\JZI['CFEQ;(E:*SB]*Y3=TT"!;4GH# +MB2;OYDM1XG*N&>1-0*EX!<0R3%"(7#+@Z3L#73S;`Y.B@LIZ_C`S$7!O%21& +M[[L*7#!HKZ9$91_966SG+SS-CQ,XE<"JRBAK_V<[B0@;+RF"8:US,RSY."4V +MHTEQ3:W6#8)8JE13E.S)NT'#F]`8@GMPLJK&>OCUPY?)D8J];-&6;YY=\O_W +M($)X&8)D^P)*484L13P/#])U/\P(>37I8UWT-(=MR\"%EPYB84=<#.Q;`8R+ +M2NH'B/NV^][E3%H\^XW6`+;AK@,8ZBH%&SJ\VZA.W^K#NY%5\IV37)6ZW:S! +M2@?YQ<*!7E8#B9SF`^3$*`-R%^GF3EG>OZC4,^'FYFJ5N157+XB+N3/T#+PO +MMR!-I;L=>M7N]N9`F7;$Q-`OF_X3C]$0[ENTV^'"`S7OV(W-]GEGP0^$:Q,; +M(?C<I1_`\47+I]C;_+Z5*Q+`N3B/%TS2Y$S(H^>( +M-)ZH+OV9QLCE5*E4LK_A\7\MB(G'O9"ZIGQ9F7:^"!B,%U1)^!_9P`..2BM] +M"&?2VTHFT[[\J1_`*C4N!T3O'+V<[KR<=?FR[<(HX17ZG):O5GYQ31.WN.A? +M.R`_>AKE18@.!'A?([RJ;_V^N7W>[!J%T/80HW1V!.+X6_.4M%6;J&1Y>_OX +MK`7Y;*V&*AC1['5*C![<\LMV_U'4@FW)^AD_QOG7/'1)(UQ$2(#/?TENS"W1 +MO8LA[+V\)*UQ)WP?FY24'@RM0]1PKE=2,$1QRC=%/&=VN+D:L88R/&4[02Y) +MJV]V*TG5L&N3MT8=7<=1BFBG9SI3%$`//$3:CC$S-\^ZP:PH$?PGN#C+S:IN +M\YNO840Q6T,91%M4+^=:@[&@]FV\MWL8D[KK85R:):+YO%&>'U9G'"^8BPC6 +M']C_#`)V<#"KVGW^Z[8I!KY2RM[S6NI0-/`?PPNLX#8&`,'M7:FH--WSP5R0 +MLD?2@@>N3-]0+(0F7DF6*IJ`+A+\.4<<:+/+UA90\YU>3B-^.'D8(M(NR>,)"+Q?RKYO(TVYJNW)+@H;&&FV$V?\# +MK/AB6\*1(D@?,+EL$T4PV[QWX.,?+J.E6DU0Y_9]3*9M&T2J:U^LAN'F\0C& +MWG$H5PAR9E8YIH2Z0J@1FS([))C\(E%FHPZ/JX*$7RHHEK +MV"UKW=/4M<-Q?]=S\LH\I/.ZICD",ITO./%9ZHQ&#^O.,WG+7ZA +M[L.#YO9^:P$QW)J>\&4)E-7"H=V:'=LQ1,]NY.R5M]QT/FH^6KXM+[JQ>3=_ +M6EU4V"'[$+RZF\9CO0+_GD3I`PU(CZL2C`OD>+Z3`HAOPHP(_J+F3U??H;MC +M,1Y,']/'SK'+#(:`O&)W94O:./&*U8Y>9(/, +MTBVR%#G?XQIX7!A`_ZX3`(AFBYBQYXA?[":&#$U&!$8;R5`GAPFC1,%@P5Z) +M$(,-79'AE/*X;4SH3B-;#TZ9(C5^ON^UJZ/C-%4LR?*"]$>_$,G(']#S$=/@ +MC)SH4)M2?'3+\J?8H0!VAE.KFC[(=@L4J?N)T8>AQZG)B?0N%?P(F/@"6E7( +M<1NL$+@#J4XJ1F[^HDY3'?'J#\E:[<)\6ED4Y][=5XH!*%I<6LF1B0'H'"K* +M=E'*TR_P)K(_Y?`N.GP$O';P"^;-7K1]C225JUI&$]ZJ\"+W-#$48\T%$?K( +M1G,LA&)#Q4-7MC"-#(DZ*M2;7.7@?FPF20C]D;9XEX`SS#2EK?R.8B1]TFW< +M_)5<[?B65LC+(QHFOD1V<2JU[P9]@_-;"];N3F9N"J&`;CP)7XUI9?5G';?R +MTF@:6W0#.<+(DTN0`[TV`3+G@X>X7?D^'"1P6#K?X95Z?/+L2<0>,XA2G`V' +MK5DZE8\$V1E<-Z("V!1D>+EV?G!L0A34U5.X8YP.SWU0V)S;6A6SYX0"$9%9 +M>`^<:B$'S+RO+PQX*,KOF<,L1NG^LV]>=3P0032JN/YG`PRGV[]TV`^Q3X]% +M0>NY@'JU1A\-0$]!KQ5-]E+7@9KT^1P.A\E_/U'#$7+-8,*XCIQ)SV_5\Z<= +M9>0D._W!(_-L=YIE#$,44DV?.T`VPG@O.'>XEDD6(:,09?]&6,?D8RQW5%U1 +M8%UB-8\KS*<12W-BUKGZ8H"55I*"XJ0.`&6*:_TGD +M=AP8A5'GTS+W_C;!9(8]CHI+$%RKD^2]\K0@%S.@^+C!`-;,(O4W:=Q7C5HH +M;""[<>>K8_S',!?!G*B/6SZO+S!5'D!4K"L+.AM`]'VS^C-PO3!KN&"FG-^% +M'Y45W?SWZ/KS=J(\*9-RS+N!17?(/.,_XHUGC[,LWP/5+4[8A@LSNIX;R4>^ +M2[!YTNXUH(L3_NP-YT+BW]IMMIQ]D;24JA"7R]?=*5^;*\UN2O&TTZ+RP`+4 +MU',L2`YX^-\KU)3MWC,<5"F6Q#^R4C+Z(X(`3%V<9XSS9P'8II_]FH@SNYB]M +M?[F(300!X00+3`3RRJGU?-=\,Z+Q"]6P`DSMBXW""ICP]3-UY5,L2]OGJ&:H +M]HQU*X/@C48'U@Z)U.ADF`8QYI.KYQITDSY9G>(9[@6\_=$R8EN^'(PS=5A2 +ML2,O!<(D$J'&[2&8T6`)3-OJA4GS$8LM+D*>\!+BCW`(D>DE>JCCI+Q".X_2 +M]P8Q4RK<,_?ENF-@MY)G$E>S&B_&?1LYZW(97NV&!E>$\\,"0@KCXU7!A;=? +M;9>&Y^"G-J_3ABK?6&ZF(Y=RRDP]G\WJ38=[L3!/9-B7NXK\F-#_PT%`TOQI.TWD[([, +M@#AP)7;!?_`A_C*2Z1F6$5?4,)R>3GM8_UV?)8"S?,_3*F1[; +MKS1WK3ZQ,*&1P7RK]FR%%L&_<9CFMUFZ<)EK)>U26>SMNR-B?Z;T#U4K)`(V +M,#JV^JG*/S75W?8SA%SIJ7ET8U-U$XINU..FXYO4NKQ!I[$Y/3RDJSD2%C?G +MPD.8=R43GO%UC6>R0&'U##@D2]ZXH33IFUQQSPN_Z"MBWV3?>UGGH.^4GB:F +MU5G@HQ9,(59+$VNR/C">.:W]P)9,+"!?+O`E"5R-)4[''+E[VX*1\3LO$Q51 +M73Y'+&_>E$Q=2'G/EG]]\'^1IZY_#_8%O>Y8_X&`J@CF%5_KC#Y=+ZSJOE*. +MAA%IE2!Y'`*`ZT*B==VD#N#,!4[/(PJ`5-?:!5,3$I'EF!DRG+Z52`XIO$'( +M1[3E0H4$1KLL_7TX$&C?3[ZU-&2K&R^&4C,)O&$``8<%`,_.[!]J\B9`[W&780;EKI#]H@^"`M$R6F!J$SKE%$H\\=;'#)PERL3K] +MGSB88R0D6X_X2APU3OD@'$N#`,+\]5&+(,\M4IVR7"P7>&DCMHDPU];'EIF% +M%,.'$@$NKT5Z-LB,&&9S\1FHZ4&$G+V6!UO%!E+3()=!H9-H`'(YB6KZ*52@ +M4A]'(I5*46\XV5FHJETJC.&LQ54/">C`.Q/'T8P#;#W[E@;^>[[FPB-;KD= +M-`<$@*,K*&G.BU>N%;K^/;M1?:RF`8TQ)'M8U@N`NM&2O +M/4'PF30$][A;O(<#W1K/U4OVEN4[6\SL4/9.2E)HW$<_&YT;#L7ZG=9ZK5$POH=>O*C1B\H!(VXW$#V"QXI>AU'RHDS0C?B% +M*0KVSU"+]JFQ'#ZE+>=D@P3G1CY.T06DM +MTRLPMCQ7_$DR,60[&+PT.3)K_JFRQUJ(.9KIHI>9Q?YRS$)]$]^0D"LKRLDD3K=1 +M2"U2*Z0[+NQ1:X&:R`P72A7:HB-C3PHPM12`B?$>\>ALJFO2D[]5C>Z&!0>< +M$V8!`I).QY]ML]T4]>XN(R?>IX2CH8YV;]NQH@,O4T?V-NQY)BR3%6^/%(6, +MGV"J("G.VYH`?QRV?W_R50#16_]QX/[I\D^4UMYJ5\)Z;G.@]'7E&E2(:LJ* +M7=CT3:3-YY8E%%S+ZG+5?-"(EWXG/]`21IIR="H`%9A&^WUDNT)H$QGKM&:H +M-@BEZ\6G%JJ0K#ZU67(JAMGT]%EWC=P;5&H./[*(W6].+';XH_.^@%9[K;Y< +MJ6:R=2$@F%*B,1_+0*C(:%WL='DODHN*'!$?M?<6<2@UD>/DNBW*LQPR%..@ +MUGU2!+EXUSB+KU8M?(W5R0P0N?S5=T6O"-C#]N-T5TN.[!)!;S>='U>4=YN< +M1J826#5DXB"BG(S';W\@BP% +MB\>+_4B<1>),*^#/H1Q5N4E<0JZ[TET6_B`SEL(7T4`RH]L$3+(:V6XX/GX@ +ME`'2C0Q?(0GKSB,"D]0X1*X"FJ_6_D^Q-UD$"N>H!+R0R\+R,4ZNYQSNV&L$ +MB0H$ZY9"-H-@:*W!@.5LX2PC%^%.32;-4&6'YKH>S4PMQ&LZG)0:4Y:2FC$. +M5E>W(0BHXLK6-AK34?!OV'CASH/J+M*_W)T!@^SKPIX1J[82_+7#YSN:U\:3 +M9PIXFHO;,LG8K"^8`L2#L[#.&ZWM!>0+$9M\/&U2A)Z`P&,OX1?!UYQT\:8< +MEXW[!U[>#%GB:ADF5W-B\^([BFKLN2J(,J[B?U8O1@"]@AIY1"GA:GU-594R +M>$S(![1@RV;$*B!/'%#N?3V/P+;(8/O/?HB$4#YX1//+,Q7U5E0>;(31!*VL +M[B5'I[MQLN0654#EP@($Z-:RAH$&0D1542B>+?0Y0%;YD,B5M^&00F6.9FA, +M(GPN@C-.S8=:ST@W5N6OYRXJ!`80U2N +MT%.`OFC!S+TM)\&Y*(M5J-;/>U(%>5V-U/0HP3Y<19V88/I*LQNQ<7=+I'0/ +M4K?$\UYJ8YS-'INY52EE51?65\I!%P5Y%/C)ZO@4XNBT>-ZIQC_$(^M:)H;3G,L7GG9O_0"A.M0:*1O>]>/H^/^'K'5W)KFWLT\P\C__(!(D^$0 +MP1$-^)JY-8/&$*L@OI6[SS--A9`4K.IF`1 +M7LBR\PP[GR2=8UR03:@,#=0/7WRM^H7HPU'QVMQL"JI8=-<0KQ-2PLTSS)/* +M@@(C:D98IP<,+Z^+)L%"H]A`&A-1?H5OZYCJANV`8@):P1_N47.-?'L!VS&U +M4WW43V[Q*UAZW3,"XY(FHQ[AK+55Q>(9)*@+4PK@J>NELLJO'7O#G=#5MN%U +M-L59<>0-0)@7P.142.D3M_DQLV/HZL=HCB^&K4C53?I!I==`:=PPK'>?=-?@ +M1;BWQ0%2]J'Y_@5QQLH.]OR?&,GGVOYU22L)=^:H1,N115% +M8(#&,<,@J_$?%.7=<@C09K".]3>VT:,?B!-XY!<8HAG2::"#`5H.B$QA6F?^$4WSNI'B0ZX,\7/[W^[5IX=R,N2P04""4BJBVHL)%YT`IPHVSLCA;SEI!4]K\@97>'V-"*D)4RW<)14M1<"5LG2,'_?VB&N; +MT>=J$LWF(1(1O2$9ADNM"U<9J&#XQWVPC.R7$2X;TC-?CCU$O*J3,B6SKQVS +MQB!1N91_6FI4YL<'O0:6\_#XM(((\8?@N20_".L0Y@S11+]\>GUQ[CB&?$Z! +M:,^8NZ`)X0Q]U#=DOW-APQ:K:^K]\_U^=8B,\@F;4V1^`_<8'3UR7Y/H3KBH7. +M#_8(XZFI]O>[:]8(CAH'.^GA=JJIF%B6%YS`Q<<5<-*2T29T);J)CYPHA^6@ +M18\ERJ4W^W3^U,"AXZJ5PI]1!=`B,XI^6#Y6(1@B=9B`4E$XZE%[@[3;1+G; +M5%2,_QE]MI@*0COT/1"0=0M.$)[_FOZ\O!EXP@AIP9OG`T4;&1JT0 +M5OEA+WS5,:7[,[8'98'US@`6B4@CI!M=##GW:=D)8N2P(Z/<0Q[]_K.-/&]H +M4R`'.]*\EHM)@4$?BXQ;FGWNX0:+),,^NM^DO?@'YE&R\D`3\"\_QCO\\Q*`?;^O!\>>&$D#$R%:951`]P__"U?1^0HV>-3<5I^1.@Q>OU#JK +M^GIZFHS>*[5`CCV4J'8=N/G.ZXAW-?XU@R@0.1,5R:!E>W2]B&PJ],.'98C! +M/8KFTX($\[.4;MB,`.-36W'@->21#FJ!>I3D!5\\/RKGS^F;8W7S2$?>15%A +MB)\`'!VU%)LT@YG1`(:?Z^2G;"'D=@D(R+3D9>$*0Z,;390/A[FK+_RAW\5;UB!!EU)_)AW85OAV!-0ZD4-7WV^<%F&N8YRW;N0P +MP1#YL.LNR$O6IP^]$53'1$7%_N*CA#U42.V90%=*F`G'1N7O!`NFQ$Y$%)F' +M,B:'?DN5*2G2A(IPZ#1E^57[6]MJ6K@*TO^F"2XY2C9H<]V+]+PI186M*;=W +MSE)"ATA%KG)ROZ!!3VWS)7=M3D,+Q#ZKG#"GS*1B&8:(W^WF81$>C.47Z:83*MZ\;6)9AY3UN+P#-5N-G0ED^TJF)]Z7JJVP]92 +M%D6*?F7+([!SUPFH=,WZW$0CLX03#H*E=LN'"MM:I`DSJ2C88U#58E/2](?WJG[RK#TX;1L]B^B8:,,"B +M]%ZHFQHWW^%UL$8/':7FO;Q)H]NA+EI/"DTN-5?0C1'R;PHWF(J0GF\F778$ +MG7YGU!5(!J&W;B*[M"?RDL-"7`!'$SE?1DTQXU);S6VO" +MYG)3=W9J,;%BS&]L9U!OBQ/YRG(Y:&Q6*Y&:V#DW7"/_88VAQK'E`\%QRGM +M3<:/LT\/:CY9A&1+.!=VZ(%JY&;MYZ+>U>1ZB&FVCA0-4JGC%)XQ[&BL%64@ +M9)6!$C5GA/7R!-^JU*\I.J,!/]PM%F;XRH\>2I6.,9F!I8^2:A(1N1%S+ZJM&S"#V[=B30YE9 +M,S%)@:R;.AWB$7V>>L\.9^F7F*30PV]_)98RQ'Y +M6H/.3G*CLG)(1LW8`/_(SSL)ZUE#2VFV`9'<561C986K!S0(R_-,J)ZX-T8I +M.@)(U-Y(.5LZC\39JZ-$\0L7N/,UZ?O11\G,Q81#^<@OZCV+\7W?@>>K=?L?Q<"3L(!+G@@X9UK/+W=!6".S@+TP@ +M:>.#O>J'V$8$[8ROJZ==B5][!XPQDXS +M;!WQ*.V!M`R8QH/N#SBD=:V:,9JI1ZTWI +M)J!5=,#T7<9P9?H'E6JN<:3$0W8?/>2(Q'JVD71J_:TVT5M'A.`/\788M`A\ +M'\=L`G4D&+:W6BAB;P@OY;MZ]-[!URP)(U4"XWRS7?L_2^#B'1D#R3%CD9W6 +MAE2\:(5]&R>/J&.Y@9U5'RQO?VXM1OEB.D\N;X;UH6)8^(H1=7DVX[":R@OW +M+>,`[(1^8].(/.FCQ/?9''-L>JKDF$J-@.&VS1T?6=;GJ_G;!<%W$QT> +M^DF^CV;M%?7O"2Z:`)P<__()#P$R^R&@-`[.$NX#!5&\`<=RC1/PG0E,<\LG +M=+D`&C0TFV/0"`%LW'.'+>PZ*O4;+H0LKW],UZPFP-1082F.^'<7O(2Q(@75 +MZCQ8-HU`A12@<1-W-W82N?5K0^!?3_OP$H!`5V,.*_JU3FEIV5HP$8/*FJ_& +M1GR.5J>"#7BP2IQ[U@XDU`4B7T11=]_3T@[4:00FP_X'ZD?'1YRGF=T* +M3SGL_V`9(!\#(L +MZKZ.BF#YO-@>-J)5`:4N.VB_KKU,*M>$XI0=>R^L#%MBVAPK*.X\GV^DSMJ%G21AB/SJU_!9^2&/EM%H +M'#0QA)9^MSF%8:^EANEHK.LKL/3Q1L8<1&JMV27\,.$9/19&E1/KECI4#/GQ +M][PQQ,Z'KG`@TEQ@L3VF((OFD^3]8;^M]=3[V0XGXI`%M9!\(*)?/`0$Z(2Q +M0L)K@2T+HH%,!/`31+,6S[W%XZ^$`!;(#:TMU1_>9D'&^_#5`%FU&P08SV2% +M@!:P\YQU4=2==B=BXXC41LRFSPD?FZY4,&2\B73G(1']PE^27+]I9WM(#-44 +MAS\I_N8&BCR1\[@^TF*8'2V.A07G'&<>K)%+`3A:G@Q<."B1PKA/EUOI]"`% +M,\^(RW35,!ZK:90$8^BX2=R&J=JF=4KCO^)^(3.5T,L!X8KVRE4HQIHY#XJC +MA*(DQ%`'ODSU&+Q/,0-%7K6FXS?*-=6AF:U>!QXH]1OW4VI9:6IOVQ]%2 +MY9^[89YD82[.5M&_-R=SAW4V,5V9#]F_(&;J-TZFKI?(*YMSWT2WL:=:;>1( +MQ\"[A"('@S)QBE<5K!2M:7&!6#C-4>QN)E>688F^M[;56^?=)'IC&9Y@C3PL +M$\!==,#ADS);M;P/Y7FMN8!5OSOW4\=\?B'K@9+%#>\[SH.3D#`-/3RQV@9&Z)L.VH,B?Q;&\95#";:6Z +M_K0#P'4U>BWE1M>U]I`4:<#KRK\*VF6Z,P9^&:0;\_ZOQD"JLT"DS-@(\!LFV]RTUB\9Y?IRA+]RMX0\AI:?AYT\ +MB3H$?-JL<_"3%]"H?H6K/_8@!>/Z-LK:0CK\HQ!.*#TF8(L>Z+:%4R3_KL0> +MYF[]*K:VMOYFA^0]0R[E?4[!RYV/*2PWK+K`Y"^P;TM=2[X!:T;^AV<+T"3T +MC`],"+V?$/Z,\)T8_%MM5T;=8)Y7`<"/PO&NGLH6(TBVQ.V55SO9FKU7L4AY +M=>#0=ATQCT-C>VB`^FJY@?"BD'@.UDD:C#:J!9PX*(^@-@Q8I:^S7!22JA=< +M3/7=0Q+4M`";"X&PUJMX$Y34L,.]\_YS6>8WI>!)@3T")\;$K#/[O*/_)M"I +M*'?RRG\410;X)<_$"VW:+W4ALO0_43GC3==!?+Y2`BV?S$4H]+H607/O@G<* +MW/3MZ>^]S_F*WQ#XB>'9HD.R9=UF)TRI+PAV.>:*HO"T>BLN^*P["?-HO*^F +MD0LR_>C'B0IA:[$:QL3&=D9I1JED&?$NV1E*A<>`BMV3D(7$!_S$OPE[@*4G +ME:21!\:[]G`38'29*?:H\NE]*:T%&7@4BUS7R;_V83;=R'UNYGAI*:*33]]9 +M=7=F!`@#NODW3D-.R!E@R(:EUMUA'\6X?S*!LN0E;)7N(AR[?.-S,(-)6VD: +M=T\UZ&<>V[T9C491LV#1IJ@>UI84+L(I2H/FE6%D?B;6\=\&C3$&%&4(S2"6 +MOARJPJ+XSHZTBB?U6$$NQ)"'8Q]8>NQ'XO'DD-1CZ/`[)Q!@6+OUI-`SH_9_ +M^6*9:[Y"V1U(32S>8B[4J#-9DZ52X49!W?*0.^K,:_Q^LYV+SG,KHNF2O +M;OL4N>\_3+%5V:YH/QL0\&^E/'E^&NOJ6LJE[W4-URT.VH>5S$EP,=;`D8(_ +MESSR%Q0/57!T0UC,&_*E[96*]N8V +MAO-_T#"AVSIBN\LX[XQM'F;QRO"+F4-$8G@ZAO&CUC>9ZH<06XD81M`6&N$# +ML]KF)+.GVW:4'K@&]8],B?)O^T,.0R$I]O79+:)OLN@&CQ^9+)8Q`R"U[G]_#>RP14<]&YQ`!MA^2:$>PW!79GX7H] +M?].,]0V5'Z8[^-]-FS_G38(YQ`*PF[":,(K_F\^Q]N:]!4DN.O.FAY9,,9/? +M*Y'E_-+OL='`Y/+1#IUI^B*C#,W^.R],E^N/LY2__;CH/RQS-T8/(H^@(_((A_=/R9H>?$&;YY)NC,,%\NLE2BXL>UNQ'3N +MCF;;I\U3UVG#D5`&PX]F7@')C.R@O=?YS5-G:?>/^09',/^*32?\&(CU^.T4 +M*,>.8[PO6M +M16^[H4RNFG#JZUT24:_-FE_5!1B4LKHG"F:=2(R&SDPVB(V&* +MJ)/O;/B5C!/GU(**T+13`3ED.9M95C%0`I;+0%)M:T3D&X""R6A[*V\S++BQ +MVB%\$//!$`J93-(I$W9A,YHKO2G%#R5YY`1(_4QSNKZZX<898>;`JC078&_7NVC:'783.3 +M.0K?\7=-1BO$M,F?0%,]!+X8HA$\C2,B30C[C3]8K;'UCIC2C+.JY*;TICT3 +MQNN*X4LKBR:#/1YK.D6^*599"\_8"W4`+^9+K?2!TS>_AE:3T>S(K^TFZ^_Y +M:TDJ4;MDLO)"Y/SBJ%`,S0_?0@4P^>GZ6XMTW9G[GYPZOO;SS-50J4IU%+8& +MA(&2[IS\@F%@=B*B?5/@UO@["O<-JP&(?=HZ-2OO:F++W);7=B"H1PQWG9UF +M,3A@X>-TP;0=^0@#9^K>I9`79W,]V:&WTH4@2V2/%CC;?3VW(:7^B=(O +MS,:(#FN%=0[S+C\)`D8D[CA[.&2*B;$(??7C;CFKR +MCW5K+_JH9NM>YR;PKAZC.?%32N$S*7 +MIVT-;J_PPA?2W!V&^Y2#BNHC-XJA+6]",+*,&6QH&3[H\:/SR.A5)(.FGGUY +M;B>YGY&FP3C)?!CJ^(B.`P\+"E#JBM6O$/XI9X^G"(_'_T?+!Z#'H)1C+XB85AC"=>]Z'O#]+=IM`SI]"!.C +M:(?%A*%XLGCWI/8WD$[#<8(GH!F +M'R=)MIG["1!_A&AL=81M\>(4Z]=[B(=!CC69O<5Q['^$,G&U[:*0H/X#< +M1=,S?J-LK<;=ICQHC1!S02ME2L%:YC`,S[E@91ML*>OZ"4V3\((/0GEQ!P_X9$]J`5F`!8( +MRDFE&@>F7818B5:9&S2>/*R^YP(FK*+6+F3U`Z5A#W#8&$8_.4+X#I)5Z>FN +MX![P.?X[9%>=(R +M,U"NE*PIW#@W@J`$9D)EQ-XA^4IH`0)RKC4"UG*QXV,[7D+!LH*5"5ENGSR2 +M+_YF10NA3<(>&")XO.VKVKIO=N&FARP3EUGM[?>(+I@J#^OY11^(YFNSNG<$ +MMUGC312)WA&:V'A6E.?OTUTEC=,#N6[5JU7U)U\+*I3D0.F!N':%IC +M(;HJ-"-T`.@8;[,BE'"Y/4C>OQ%>##RASK"9(G"'?XTL9N+3PP]/*7YM!WF1 +MSE&(.A-"!V!L1B_61K;A#YI=UEU91!06`&DF./QV0M2QBFN3[#G$%-?N9C^M8;Y=U +MA?'V#V8I>&9:\%<\QV-CSNPN^MJ(A'IZ:.Z9]&-@;@K5+%GTU]>0I0-E4@H. +MPZ,@AWS20F+#`]'8Z.E:>9Y.LSN+N;JQD3WO(%8YS4M% +MRVPOV@(>-;^E\2O\FP1\?2`\O&?1;EPJ]H&=*RA*7<7SSSN,;=N-)+L^_2XA +M0[^R'N1+//%Y"#FJR6P'&/L5#A+\V72SQ,>LT$I<&5@=D:0775M;YU??H9/D +MH(@WCRE?)"1ZDB%+%E.DQ6>R2E8#J@6KOR![C9HQ,J'Y8^'Z6OK^9%D9H'#T1;O>2O-RK['?.>>R'LT&?2"U#EM/(KR"J,=,O +M4NCXO`"PLM)S$C#^?#'>F.3*J`\LX'Y`.9=2G\Q.`4C`/PP7;JHPXMZ3,KD; +MP%Y"0/QK]?S-4,AB]4RR!!0&6;O*0*TJ.+,V'Z4 +MO2)HKH;4=0IV:=-O!^--&&A7[T7IDMUF/=(IEQZ#?\M.Y!3NX_W(/N7Q*-._ +ML]#B\'F9$P1@_!`/`O)H@.U!UA"3)NAM8L0IPB'N::GJACDVFFY((B3@BSL_ +MG*V9%&4GAK\N:Z9]257I?5WQ65#MD+P3J<5K')TN7WW"OD'T91K`'D>-9#-' +MO75&UW>V.6:&>/0` +M20PB*FD@5HL#)ZJS#[5N0]N[!+IJLAL[?(,#R2F`^-2]DG/JH33S.`5W;<+YCO+57\:VIJ<5!X6>N;'QNG:3W^2/(*`5B7SZ +MC.5AO5T,2D^^)C+-+'F;@'PJ]6(4-(X[$`>W%043HX,/I4^W]Z9(XU",S;ET +M&`3LT(5B$"SM*8ZQ[>-W&WBQ'MI.$&W:(BVFD!-`,)DQ/K#DYF?^O(>;)D'B +M0CG,Q\-_$,`W]U1GB9]`/J;UI:`MQ\:_G:/;;5PHLV;!@OI_-T26G_Z&=&0G +M6.4J99L^5"9G6TK)KF.%8/%#WBAD5KPUEW$K99+XY)D%(^_CY'R6_S0#SDJ: +MX:(:$/^NU' +M,S\<5D%G8G0Z#2"T"?PSQ77P:J0#;[)\Y0OVAV(*203=1]W$9Q^HIRA$IG,2 +M&]%[_D42!&KAJP1J7'GSMVJZ@,'^F[8V:HM"^'B%N4=N.7D>I^C<.DZ?%+_W +MSF>!E`%1)R)."%$![P?7]F+G@X$%[=.3B,`2;&H'I,DZ=8]Y?DMKNF?EO4^L +MIWVD!(GH!G"M6!:6O$?ITUL3,5XEPJQDT2&$X[G3*>9(CUI@&FWU4`8%M[M" +M[/-YNY/\_+>>5_:L0RQ!?M#KVD",%L)=X[X(ZK]%&X8,"C)U"%#4[H&&-3%< +M^'[J$#%QDSZ#!MQDQL0M]DT:VS'9PZ-/PDL3;$D%JC0G9^T_^3H)#4N6EG3$U."E +MR`->-=4._[]0K,:R;/<76#8@M_RAB*"+FT7+@B2S&G>C!U]2M)E02F0'"]!\`'HH6-,47P!4XYY.NKLG$-L7!=GI6.!'<&&3;_JP81JW +M=$\1^6(:WD5=B\HJXA(7WIG#-]!4J_1N;9Z7,3B]*SA6!]SG^PBC*7R2X@E5 +M]X]W*UUAQ'/4/)_,D+Y'_%U&_PY(,AY%D[K\\J2:A4V$E)S88@3'I!8/KZ2C +MEUR6`/D`$$1BIIC3G%"[G]![Y3+SG*$6DI8Q)QA!BF!3?A$73A((.90P?"A] +MHNM$U:E!3ZM3\K`?JX>BAF9'K<+U9=V?/DM"_@G<6FD#/*FK1;25SMKV[D(+ +M-S$&$0'76BS#]GZ8XXG#[8F8TZX;G2?.<0K47-:K[.W^CW>ZHI[1$#J]XPM? +MG(W_0\D=DC$P&4:7D*/"%5SL;T'L/^"BG@B-_:1`8\L>+BQ](:%=IY;/S>63 +M&1!@>H@=3#!B!<83PSTL'!\?N;J;R3AN+M,M9LHD'D8OH/3L(SHJWT+<=_DC +M`=`,53"NE"4!@B(O9?1,877$J9^]VP`?:Y+^QEG"JJ=N2[$@C*-\M7TKK?@@ +M=!5R@'M^.$@P;#1X@OI8]#8O0FFF`A^AE'89J_9$Y77Y4/[ZQZM[3L0C!#&8 +MF`?FQ!V.UX$46M:"1/+42IY9`L@7$3R&D'7?[?HFI@3G1W,[\,2X23B)0!-\ +M3OLISZ71OLV;GSEPM6NI1!'5R1,+3Q#:<_KDH<2"$?,_M\%:FU0/(LI6)#HI\)BJH,"W0_[TCBLMZ:^<5>ZDR9PX'/7.*;Y +M^G1G"R-H49[5Y#-[%^B#O_FJW.[>D.T5XD#M*1\;Q.^R7.*PV!5?07I-&4(O +MGLW3Y0FIQ2R78320Q0M7B#O(R-+SN\@YSL<^4I'.66M[)#X*2H7RO]!^K@.Q +M]Z@K/W3X((Q'Q!L=8B8WQ'5H9\V0P4N7J).M.<_A^6Y1^R`Z'F!9^3(G#'UC +MZD/+MX1N`0%SFYM\N+XIP?PA*,3`J&Z7GN\NS0!,%Q'_D@!WQ:>[H3-UTLJ6 +MA*[EMFU_U18*MMAEAUZAE-_:U`2EPSFB((8GH%8:!O`Y1>CM'`W@+JO1TE!_ +M44+ZE<[@PVVCOIO.QG\G'!B)^X^I@WFHN@PUXWPOT?LD/G/%`#A!=*ODB_4E +M%]4=AUFD>J#K^52A^JL8"L*NC.(JJBM+1D?LO$NRZF#1[X$CP="Y;DZ*RT6A +M*Q2GZ.(XD$#YQZ"4DB)W/]I#2C;8DV=_*+;Y3;S*7M#7@.X:59R3AQ17J2D9 +M1./V$S@D[<^<*!M@8!2)N\S202E>1L2.?M*(4DW\I11HB5316[V(?D&A@#2% +M7.O>[//B1VN=I5%)L]+UKFPJ.]O:E@SG;A@F=K9`N\G=6+.Z[*J]_;EP:$?L +M[3N3"V[;0PR'.LHR=QE-M!$_G&5B=E_ +MJ?"L+SJ)XG&!"T!@2$'H5ZH@8LB/7AWJLKM,TH5!@E=0DB7(/):QE!^,$L[/ +M?U]:YJRV(&I/H=&F#.55X8U9>RZH:KCH9\O;WJ%WML8V7E?T!OY+P]EA4%#F +M'I(#'D:Q7P/D4I.F59MS`!*+@>OFBZC,S::;; +M4E8Q-22+$22XSMVY2V."I!4$SX[.R#IR\9IWU0'(.2R3"3:X+%T=7`H>ST)? +M`L*3@9(%X)F6M,I01/I1.SPOZ83P/"A@;.('.QFD75R/I0#&@^,Q! +M=S)H<*[<_8T'+8S#2$.'%S^\AH"8`96'(&7![(%P`D\.7I>?$".#+HA[PV!+:+.(DU`J.E/9HYJ1TZ0X8L$U24U +M`UTY$$3/MO(V7?X22X`]B<,6-W"HP]X[/"/[XH&%K_ +MF@@(N;`WI-1QB[@1@?]-E?YO&337'E@;OI=20XI-6+U7LE17`7'!7'R +MEYF*P=0,VC?D4.Y?U`:@,\1C*O*[3,_T6QGMBSJ]B:P>=\MN9-T..SX +M*6FR,R?MYT7I/`%Y^SLC1Z+Z1XX\A@D +MX]8NBER-H[Q8OWLBUCYI@&@?FBH32: +M=)`09MR?J*BX/:?C@YX[D^P#[^F55VKEQ-P3*Y350ZQ +M&A,INKG7U#M]0LK7MRC'#L[#HW]7#'7%E'YO$*8'%+?/?`9E)J!39\EW/EIA +M#FLR1?OJK*)*1GCW4IEE5%13>7YR4V%3'L;I7+4W'95;X=;X[6=[LCQX40B6 +M=2M)YO7O"(!1_RTV$;K4?8P8*#HJBM*K+&W!M[X2_#]D>Q=)C2T3J2\&BZHT +M5YS3$ES6-;,J=RNM^_10?T,W#H_JQL/A2LLQBS]1+74$?%C%O#W'&C@>A=_X +M."AQ)35 +M3?5LT(Z<,=M*L;C_Y(EQ_I#P0R8@/6,7^O!_`S86=]P>?A)Z?BR7 +MV"&&[39?X+3W.W$,RYK0Z]YI4SN8\#1,-!=1R?3WP)/:U/D,/9O!)`]EK2%: +M8#`>T-C>P<_]&&J$^TJC>"6/EOR/G#UY&/'$H*5*4R5&E!I@^O0)ZW(8 +M.!(J7;>%2;!5R9]K(REXY$U3>+7(3Q\'QX',2]R&7Z\8?PJ8S@]^SAXEA[#B +MT,Y6K[`_N]IL,6L;R__-&[8$-F`SM3E03AOS0P2&_@'I;ST:"2MT\C;+*M3A +M:NG.9%%R5!=DR+`5FT5<@MG8&]3ZT<_G7-3W[_:Z$-*HAR!8PJ2U&KR\24@I +M_!?(P"4V6-C'*Y^IG^%6L]S+"LZ,=;A!Q"1KM?T,BIMP#\7O%QEHTYWUP3Q! +M'&*_Q^5?VD#Y_M4A\HF$X!C(+WJT1J@;[%70K(?4K^R01-A3^I`L!2`,053)G0V4DS<$:PMK+Y9:=6TZUK%7'#J53:] +M(@V'E4H@'Y>SZ!96N&:7KOVVF0YFVMYAN?46)`1Z8U]53$H"CD%'Y/%3Q7&; +M((XF3R+W6CC]G=_!X/FSSP(\@/5*.NF1Y^E-H\$KCVVCW#%Z!LNO/?=_P<-+ +M"%`Z0&^66MB2J#MO#I7^V,MUG/?IX\1QX1*TY;N^A_(%@(0\&V]Z,WKPND^# +M4&_J6PGA?!U7_%F'+RST"EV\\`AZB7O\+"D`4.HK*BX]L:0CWZ0L\>BSP82; +MFJ#-JDD!M%;)[WB&C:#+6,'0@-&6+JC`W=Z^SO`GNBC&%+Y)[YMLL!@=>?CG +M0B,$@[@<1N25D[)(9D4FX6,@<,:A`GEK1X-LOM*5_&HSJ-G^+WE/E9>>_A+M +MMF#F5&B$N;Z9L#,+[8S:MC5!L0H[A&*'6G`3&W&LL?SMET43TT3AUR>,K.SV +M')NORP:D3^D.>G3H"8@?%G*^ +MIX_C+PV.OV:@>M>@AR,X6(EQ-(1?$:GQ[K`./_H\+*^^T\'^]'N9A=O-]<5:X/1V'*0@*?].8 +M\'[Z?@XNY*@?Z)WO\)7P^^VD1R;9,X82XW*`=3T&-/$)`$W'!*H+*%;IN``B +M6=+R:B,.F)0MQ6)K+ZF&,?O+-@,:&@MR0'#FVF!)C1B-69+/")DUN\HJ>1TQ +MXP#LJL0?*EVJ$'V5@A9#[3KDY<#Z4WOL/X+<3]+1@$N`.HKM_]BSX&%#SH;X +M"P:[<-E*)A4(E'FB]8J^1Z;TO-MEPV6G47"VZ[;_+UF-B9HH9`)*PL6OFPX\ +M__Q#M53YY/6*X#A[^R'@9_>YUK_R+E=6[&MI`RA[]J;+OCM>"+&@JMB?5-#_ +M%YKI'`$HM^&V+H5]]8^=V%XL.8S?H?LGOSKGHT1#WDP_THXWZB>JH"L'94O, +MNE@.'M7M#5ZLJR@SI5$9$"?,[:]*G&0F;O,"N7EMY(H-X/4_JM.!8\$\8"3^ +MATX-)(%Z=UI3$RVW=4!N-3*$BSPW.O]+6E]`<-8KQ8M?U2\X)[N[H$V0(8EH +M)WNZ5'GB]P'I-*O[43A@A%3,?+@6L*&Q)-@(*.WXE#?]5&#=:I?H^[C9P^SV +M5.CBWB:5/M&Q@\C"-/--$2=U+W:%Q0=^H+_V0BCD2$)`RQ6'(>7-Q'K8E>S(#SY+/1=-ROX8.>.R)/%/N&B2 +MRINGUY"2,F$@:&!>>#X%H@&;)Y>M4*2:'O-JU$EFY!HY6#C="X@":,>&/UN> +M'NFM(]>Z3\-UEJBY65RGAI#BCMFI;.QJ.7MCFD9<;ZBM',J%Q<7'-VF(^+): +MUCL1F"3UP=*YAB4WLK:_1MD,<$G3@DKPL79'Y+S_)T@GE;>U].$EZF#+XM-; +MY]>36QEYI=%+KEH_!3UG4`].RKATQP`F+PBQ$^+L),YG1-++WU@+YZK(2$5" +MFEXN0ZHX:/BKBG6CY&Y336P<.3\6WF.*62'(XGJ;-W5[H*Q8Q2$]_+,IBN>/ +MB*`CH5HSI4.16N?6AR0'`:>1LUJ,P:N,[A4R)$I4MC8UC>OK0"C3P#9N?Z^D +MD9T[+!@W1"";*KY\(5"&L.+J$D.FS@<0TG`H#]P8NTZ0F:N__9N69<[,M@'Q2#2%*[G.D +M?F\*A3<*WM9/;`5'@,ZNZ*&F1/3S;J+/C72@3U'H%9>EJI!$U:/2&1G-H%)O +M;PMD4>D,G#6G#8A;/`],FUTRJF12R+\I=E2U0@/L]G>I(9`.40F>[MT(WH]< +M\/-?[3S1#SX]L!4H]1)A1\G_EUD&(GGW-/D-,V^"Z5-D%6`]LN%ZT:#31:!] +M8J(VKX740T_UFUHW:K^0%LU;18EPC2:\P>%.-"O8M0S+YM%(Q!8<(TX4<.H] +M=;^=\6_B)S!.ICHY\5P,=/?*FI%EDR=B;%,NC(1Z"^.+MQ8: +MWK_O_$AUD'^B^''M_L/J6M>B(@GDR\10K=L +M^!O=,H]E^&O_>JQC/M];:1*A*(P+-Y+%%\F4N!*N8DH'R)/<-Z4)2)T(]Y+. +MB2(M4,+"C-$*_403`%OVD4CK']<3`\ +M-5O.6HLKE:(/3`JNB'FM-+>66:C$F&%+R1BG*F=Y2KSX0OG+^\6DPA9K7TD.`F1>,U&`I+ADD/\,V#8_L +ML:%=A,JD4)/2#4^#@DZ0$2$6;*]43*3/97FZ?5S$ +MX=1ZQ]9KVJ&()64YZ#.\B.@A=1M[&N8_]2C#II7BCAB5;U)OW!AAWVMVA'IS +MP_-7\;(S15*YR9#^:WIE8O1LO]10JW#OKL +M+G%+MDIIU5V`)MZ1U;JD77V_(J28B]&IV-1PF^O2V7O;`5CM*2&T]:&.RQS< +MA_(W#.^(]2KE@HVP1&!J;.CRZ8U"RP'7+,,&8>W]J;[EQLU7`1A^H+>+'$[L +MA\?M_QT8+7^2>C;.;XS@5399YO[._=LS:^V`87F0C7*#*I)$,1&VG@;H9?&R +M$&%#SMLKW6]:$_@CS/V>[D;?UQ1E['`#JP#*)C1L,'O[.%-;+=6C5FIU[N\^ +M6TN1J*>_*)+P4:8AKW+E+Z0DZ.X0(.K,;XZ^UMAX>=-G2#AD7?=3,@H>V9PX +M35F,"RQA'"3]4/5F2O%,6YFAA_I?:.0>91>IX)/R`>'/ROM*[0G*^;F-)]>I +M$GWRV+ER(W37L2Z@-7 +MXAH[=Y[&A/L^R,UX46CF[!NO3$)#1X9SA1L)&*ZF4[F^*Q?[V17NU0I7UF,% +MY:/"D<\^*`Y)I++=KE0N58#81\%0C3'N)_L^HD`>@)(`(+O'_JA%E"("<\@T +M\^$/?7A]+^(1,CKO0'CXDKV[<%\)R#'5"@')^8MQR(SG"`4]`R%-,'4<=YN? +MBQ0(E7S@$2$^\MAL\_B6X*>9,KD14B3FG_CJB0#R?TIK`CVQ&5G&:[T +M#A/1D_8Y^O6N`QW>.+OAV<$R=,U+%>M:@\J0UUX[W/QX4_$0OF7AL+Y7-CUZ*LY +M'0$=*GA/]80M&SE@YLW6TG]-DS2'F"Q[D"K<8=?X2$T,HVGJ"E.65$EH`3N) +MA?M(:6`>#!WX8;^`^TH#5D!8YDX'HAF/"L9DRR107F40PJ0=!@@*0;,_=!H# +MIGR.Y51O@C]M8HLF)^H@DB)>O4H6(H6UZ/,2AUCQD8593-IK +M&.::K$?:ADY(7/J,E9DA938:36T_&S^=E]KCF4THQ&R$336M>.O.X/D7V?LZ +M$_+VFCI;=D((0:^-OK=ODJV\]>.1KJ=`9SI38T'-7'[80THXL)%E^A_1OD7( +M8NR^DY"]YQOS6TQ7!SX#G%0V@XB+,H-1HS*U`MX07DGXG;&_R"TXL<^KZS-7 +M7;FF5FWEKPN4"@56%*5Y,4C/]4/QVRA\B.X^[@-%E/E.,Q_""'5W_DH[TNI- +M>(".TEU(+\,4P0$^*1JS'A5*P-8DA\OY*+*J-25ZWO8Q$R6MH%?9C3!FV!AV +MGW56IZNJ;?K#0$^+3Q)!Y%^:(G[-_,E[."("]J<3!"C[/Y,`,@?, +M.`X)B?WX7J"E0__2S$9/'+RJ'XD!W*9L(R,W\V$EI +M,/J_G$:I1U%UC2GH$>"N$.K6`I#_U98>O(3=P3BKB>BHRC@5-DA+W94[7)O' +MQE6OD[A6/Z.4?+QN*L$4^MN0^4()I-!DJSTNI@W5PXWR)A:X7EO>GT+$NU.7 +M2W4'!$^'AP7@.,"S-T^J@B'>!_S4Z>ZK'&R>AYD`5*U*W'_>$NB%_AY-Q:.D +MA&"_FF$Z%IT?PPD(T*#W:$?P'!2('Q:U#P38,DM!]789?_\FE]O*W>V?KSD< +M,%CJ%K.E&!#2-GG3?W*M/H@@_T`%LP'>J#MF7@<%:BT5^MSVG[TPC@1T381@ +M(X%+UAB`@,8%6G:``'EY?2^1J()B]R%A\3IQ=V:+:D+A,BZ:&HSH/W#O2Q'M +M&3#>,B%1F'[:N\![']0/S],]X?2@P+`C3-W]794/K>P-6*F5]"(,XG4.0I!0 +M,86'V#_G7<0*3_$(6?4Y@()NF^73K&IIBH!J(^"N'+:T%U8S=SNARBVJ@(?; +MP1ZCI_<8\]L04:.,:MHAV3,460/#$N2K331^J"\`Y9OWM0--YNC;=\&?7(1Y +M'QQ!0`]6^"F`%0U@[V%^\0TXFNHT\3-M$29Q,,49+X!O!N!WQ"Y@;`?B<>!^ +M[`J+4R)G/D[WWXE%"DAI-LN5G;BO%W*@J&8_+**YKX*F90K&Q51^4K)Z[`67 +M#JNUC1'L<1@GPQ<_$&R7X$6?#"8@]X@5B)EP0/>H]1]6FX-XTHBVZU&)JS@J +M"Z>B0'"'Z#5[_]&?93CI1ZZ`2H&_Z30,P"7E +MM+>9,P[6VD\8HQXSDH-\^X'8^284P69_M:\@G1@\A#VX+>_Z%XYSHY5QC>JUWJ15.[.7Q713<^R9IR6ZJU)CWUNKL`@:B +M$+LY'XJG41(BW;P89&"Q5-N]#O^1=(A]H+VNG4LL"LB>DQNN,W1=`_0I\35! +MVI6FU_J(D2+/*!+3OI1-H:5U,2(!!"3SH.X2VX4L\,OGH*K&D^B*OI<[6Q.J +M.*=50EK@-Q=B![.YG9`7U9EGH`@S.P\J_1DAD$0SO<_J2O^O0[\&;Y+-_15R +M1[SO)9$K]GA3]X^YTQC"?R3B&59;^7&[ZOGN=S-XJ!OA_@42,`P7S<6PFC*< +M$%\#:+U!,PHF7'0G$[N?1XKJU!69*EP"%E\-[A%A(!N\>HA;+.6Y6^3`YI=+ +M);LWB);_W,YM!S.[00YH':G5`.=-+Q#[A7R1W*E7*):KYYKBFM[SZ^9_1A35T?111O.B-MG&$1OQHP5V0<5 +MA5G*6^E_?:)FI!4MHY[U#,Z;OI)Q<_N-O'<"H;ED(NU?U>-_Y/EOT)M$>3$( +MS<&Y,@FO_^A(S/W4%`T,L!%`HO^CSB$\(1_^13A$YB\7=C8&'FC,\<,R*9E) +MV[^6^:LJ6A(;R"U/1D%X4_NBG\'$^1NH[8*L+:$#*3(9%!34Y_*3%\!:/4;T +M.\5K3"!ZZM90B&LD"+P@$)K)(3R'NW0P$Y^<'D4:06,A*41R"AX3I"?-_@,6 +MP2L[YZ;YB2I(,0!QR1K=8$V0R$""D#.H`VUN&[AI"ED5!N'+)'M-9O%E^18 +M](8AW8^P57'I- +MPF=GZ"V34OK@DWAQJO6.&3"^FFJX>R2&E0T-=4W*-S\L1,J`"("H\Z3J0MIH +M:DLPJ."?UNP'F>D.IT[F?S_.J=A']'E>S/I"2_-J9QX,U +M64-'K+=K8!`/H(":LN,*S_)@*M:LT1VED._@\8H3OP\'UNEE1^+`P6YC<3C\ +MC+W%8^LG^WI$8F/=%Z525=$'3ADL.5JX_U)B#4=;!1`S$4%]0`_9U!1'/*S] +M)ZX,XSWH^.'.4PO^SO.U[Z%(_D?_YF!6X[N4Y6)B6]I^W< +M'J4YEWIX_[K0PP/]NFML"/<4>QC=D5P;,Z+!A-/E^5M[MAA-6'T;8IOVHF:! +M=./_UKOUO@W/?ON`$9T_MP6?-,:&_&=%/!#:`]7L@G7",FJ73TS@(KJ4!/S: +M/!CF6&&F)1W8QU8V#$*K)CCAX856=\8+RS/T&1PB=YK7Q0I-8M1$AC(!OL@, +MDFEWVR6X;->NFGHEN#?TRE"PY1'R4X*`@AM5,SE?_UIA.&.$EX +MPBQ7L:QZ#2:JGB\]CI!5)CIG0:7;E5FG7D'SVI?#/'L_6?IQ=/?)%G7`=ZQIT!HT?P?_K(RJ..9/AJ[@""U5U-?__;#8B3 +MY,_?+PFCH#IRLM$>#"IC<\M5!R2`MM:($35]Z4N@BU`O&K15ZXZ8=`=F*6E! +M9`UZ=U82P.T^8 +MH`EVWTD3'$RF>]9>?2DIRBE>'S;4`HE@4 +MW!%.0SZEVW(%<'@>`1IVQ^42IFI*LJ#>32`II^K5(^#,'.E;9'L>[%C<<'E# +M!17:9D4[T\,S4;/OQ4)]0BU-H4`T/J>8W"4CNLG!O2HIHF>8'B)[(3P,&9H) +M:U,7_/1K>]C402#V3DBXN1>?:!+8!6YD_8X6Q@CF#,#/TO:M8=VB`7:A9]YS +M31U`<%)/<[P''QDU&(\E!9=[B,ZG@QC=!Y:N;RZP)'PWNZZVU8J];[)&>RQX +MZ7PDQ`H'`-GKUQJ\H!5Z,8WFQN`...O&SS]M&`FIW;?.G[FV,EKUV(UHN8.I +M+0O=Z'*/$IO,Q)'H(XW;*"L6B[]JL]'`C +MC46]OT..NG2N9S8NG,FEYIZ!XD=_D.5RFQC*LX]]]!]HY'@R@D&T%E:IA,VX<&_,3J`TJ3F#Z +MP28(W^`7OV2L-7B);JID0^G\B0RC3"9]3.*MH)+FG<24N5(@(:U*0[(NU"7W +M"+B-H*\%UL^P$9.Y*':0?]$:JYT1)*BTJ2@*_"?+S/K[V[[S1!V,,(,4F?*F +M55G-L_A1?AR(4:`:#:'Q8$I1D]S=EK/]D_C$ARD%L')/D>#X^NH8_%)VE*+' +M9<],\NOGVVV3?R\WI^CB>H@VTN+\P=.FHM*O,?C%2,L)D=/3+P(VS/2G*%(E +M<$*:2.TE%R_'P!`9FCE!=1YJML[DN)#*90+:+5QO53_>'\4SM-U#"QX^M/PN1`+>D)U$)H)]2E +M+0J!?QTGA3_.):71]#'47CEK?YEC9MHHS2<\RG&?\D0U2Z7J*]B5EP:X.)-7 +M%'L#-AJZ:Y0MQ:N)8)Y`Y5DHN1+ERQ$`> +MDO/_65?`Z*E6_F`X0XY1+(ZD1"!.'877]UL^/(53;:F+`GOD/UIWF$(S>6+[ +M5%8H=7MDU^B>#5:6$:SSWJ8^1&2#(F-Y?4FVO[;%#7674J8`>;[$)G7>C`M7 +M@NH'Q^([*^AF6!WAO\]"TE>JZTC,G,@I:YDS>`PCO9--'C@529>&G55II[^W +MT$MLUCU`T>8?+(/]_,00QP)YF%OA[^9P/H%U""EGNA@\QUADW%&?B\([SJI> +MI71VDGZ.DW*X>7!"21V?+'Z(E*<_"IX15XN:$5F^0.9`]]A"O5P(Q5]I1I20 +M08-N,1"G?I%[V-W%"]^]]:7XT0JL6FSB&V7[TWH(+DN_HK4^)^PM[;%A8-VK +MQ&SPTP^D`C@O-VUN8FN0V'4_A5-;.`:V5/P?O.'5/6)"V1T!T^FP,>%$]-"U(V]!*"1.1$N%^]*D"*_"G*F_QCH+;!);^+BQW +M$ADX,7ZR^MM@\_@.SOO7Q)J0YZ=IIWI#"48F$`?>ZWB8Y +ME1`]D&&[B=#:H$>@ZHW6FOP_'PE#[PQDH +MV">BD!+^I>LD[H.U$_BG0$>.)K_'&=Z\N=ED*%:_^O&?#(4U=(:6`/5JA)!Y +MV"'Q/E;4U*;D%!F2FS/)B.I'I*ZE'L#+6[G>0)^F"@?D^>O0HQ-#3HW!,.UH +MT.[`UR:V(54UV7/0YD)[8L=O6*4LW63*OX4K,7[1RGQNWE;1Q]']9SG_`G(O +M-T>U#5*U-]Z)&YZ$E]/2EE*51]!GKN&_Y:#8_H28KIALW\$BQJA'TF=;;-[D +MY-_.3=Y?'A2"2//C]"2X6^98E/_BAR=N(0UND`<@9>LTJW`ZMP +M>\6:=L`@&P,Y@[I(^CGK8'B8D$:?*-KG&_XHQ,WC.C.-6$SU6-B6LVF$""/I +MA;.MR]?NVP39,C9AW79?WVJ$0E!9Z&?3'Y(KF`-IKK^C +M:D:HDN3?*K*59]XF1`3JT/T0FV#/-:^!G%5N=\G72-9:#S*-P:Y>$0+39U/9 +M-!U3DMKC9S,?'(&-=:LW<8;&?ML;Z!O&\^'E7TX\E7%&7(:>T/FQS8IG19DGUGHUS4(`I7>0JBR2MH^Q/Z:X +M*WJO5W!43Y0P3CI2Z%1H7\YM##30/VI,'YMQRLG$]1[1>'HJY'!'-2<(IP_IY4VX?4BT](9:)IU.T_O[YC(TJEERRZWHY+=P"PPT%W^C)Q,F7C +M9T,4<8R/?FF>!Z\9`+ME_L'(?[;M6PXK993,5WMB`]J&8C7:-D\8)`0 +M0JHXBV`C+_6'J,_?6/B@?-.QD8CS_4?-NM_QO?:.2@M\,?-QF6G+ +M.^C?4PPGX[N4F7`/K-(XW_^VU]W\U4G;\5ZU?-!8V!_3O7&]'RVS/M'?/.RO +MEX[$C5HTBX-^VMSPUI)0OW@%+$26$9'`2):<^KAWHD!*5FR"TL0X+=19B%"K +M$=?2J0=<2,=B7#T>AXS%-_ZFS/G!N?R?N;&!NI[LEEPS/](IZUL%(CD,S3YR +MAZ9V4R76!&E*E1K)7@?RC1FC1]`^?C)"E5[ +M\/FQ\_&ZL&;+ZXAWIPHA.XWF%A&GD0WM1O(&H/>G1#I"_/OD+@V#&VNP.DRZ +ME#K2)KKU6"!7(G9^X\R8%=8WU]76AN'M-#/M;@^HJ"2P +M&GP[.ER5"F$?V_9Q0VY(FOI=[IJE`Z.0CT`REM\W2_4-OC57UL_OJ^*CO2-V +MHS1GXOUA"WJLAG5M/I,\ZU/N"&M%E"E7X9##"-<*^*B=%]=]XJ\=X5@((0.> +M+0@+^$DL?J3^@9?NL9VWF]Q>&"\%,QS)]J9>EE9D(7 +MV'_I.6SM05K$F'/SMOT8VJJ9"!V/PW8KF?`C/M6P=` +M`Z1R;1C$_+CLH$6E86,8:GMV$>2X))FV4S +M2Q1,DHN"M)VU7P1)S*?A`CEKQ4N@JW9D2H2`.6J;/ACEO=8#^Z&+J>4>CZW-X?W;9ZTO,LU(-./"%.]?PY- +MA[LY,$W7GWO"7(9E^^\I8_,,W`JOJN7Y"@E7TD(KQP@@`YHP]3YOP:&^>('[ +MPNW6GD+A0%1L4\RYBX>Z+^0ZO?"M`&-C"CM/\0SPH_`.,RDTF+RQ)Z;AD_-\ +M"0@`!7_IZF/)?31SEG#34YH[5X:%\'FDT^Z_7F0'!"#FXF6#7H$JU]Q0 +M'P97/^K1@DJ#9"+S?JAK[HG_+Q-V;7OD*(+/YB?&H;M(OT]_2I6Q["QMLOD5 +M*L^,^)9=G'0/:>C@L(VVT#ZMS>#JV4"B^?NL$Z&$)"&:_,!HY<&S8<^#\OCZ +M'C_#5N":Y2H_J&BGM.VE5I.F2G,,PD"\9M1V:X_5+1BI3V_R!&%`H4&2F6&K +MJ04P>7K*[2(^&G9'=Z?&O\$6.F@==?GTM5P<1\,WE2X99-H\#!5?5R;5,&N[ +M%W)^LON.S*J60Q:`;%^RWNBQDLV59(.*AZ[:OK$BH);+0[B%-A+Y?.P&=]/T +MY79O$@"MM39V+4D_6)-L%%M4#;%R9RVZ.7@AC"/-?YDS`P@YCK7?#(6P#D= +M6`3!V8'G;VN+.7%AS:_IHA2+1S3`(1[;_?GVUG!_:#\,OBXD^6WR?<0MJ(TT +M9>N**ZG2'B#?P%E2P5V8D32EZV^(7(QT':0*H>&<6GWT:S^V*\C22R:VC4+! +M)O1*ITX3I3<+_MTL93'976PNV_!`]<-G*-YFCK_UD('Z,[-TX+PP?IVGU@D> +MS7H56`":WO&&^JB6V0:FIK_=N*!3_=.P$/1H.UQHEMAFW^&SPE^.I/`3ED\* +MB\V&]=R7_!QQH>+WZ4Q*UJ^B8S,9,47C!IO@H&$HX>Q[U$EUNINL2TUS)8K> +MB%DD?@;*;!GA'EZ\"+8`9I6#W?\#.=O'&&K*$*>^YQ_;/A76'F;$T@`MC@$: +MI-%U:((PG?R_`'=\_]V,.H!P78WQ_[8F=:L#99"S6Z33]V0``!B=GW?PON<, +M!VQI1'BIY9,99IBX#8^4<)=_/7F+'O*HK?/G#S1815Y^P1OI&T#1QY`?,*R@ +ME8O?U)F)D0I)*[H4M].9W$WZ@#G)(4(-8FHIMF_I]/P@!*GHM'?(2G\0X +M',9#9TW53VZ7\D;>?6!2AOKOBRO*G@J%HLT//%*_++A#5307X+^3I$UJ,*Y1 +MI^DYEI!2%'%/)[V_#?$MO?:AI%24)N5QO_#5MW^7".OHP;8OG%\='Z/!M$;E'U=3)+=;B9>HLD\!17PE8CFP)\+$34N47V; +MGPH-HA(S/GCO%#_V7V\2+:Z0A!-'+++ZD[;3YM3&3?C?,12#AO&*4\9)APUW +MNU^=S4.\VC-FNQSO7Y+-WIS$A)\T&UN+;KF/JQ`'670V%F\:I2,S=CO20+5L +M>M]&"[0H!E''N,T[?%JCPDIH#RXD+HI54AI"O()N\5Z<`-)67-A]!J17[VCF +M\LEC^Z)]M(C4`$R9W-M[/U!P!['1Y*)7X5MBRNL_0BH'V+7>D1;PLNFEFJ?0 +M;A=B8H5P9MV8:X$>%W;+DX%X/[YRIHJ&ZV'.9H)T"CYY%,Y](Z('"U">(*!" +M:5">#4=QJ9;J"$G(<;RV9S2UW*2UGF!8_748GU:=5,:=XS2.,':SS.I.K1*V +MV%V!F,'D2*[<%%=6'AP[7("5^=2LQ<:&_K1<%MN;((Q>: +M^NLHD2,QW=V4*FRX%AN$>1?'Y@S0>;VF?82YP?GI5*@IDO-5)<*R\25?IW"O +M*B>>KJ\53O,@F+0B*:O8*CN-P`BXP:K<4#4D=*0.'XYN&;&!8L1I6>`.QL/S +M/Y`-C\)>VBP\"!GN(6?R\!9C`/_I(`_Y"+VW$=1V[^&^(Z@HJ4]XFM^TB2(K +M1LBZ;_`RC^[J37B4N_E+T4/ZF?;%+X%!6-,H6I@1S>GF)['=]R4+UX,W%9^N +MK=?_P<0^C)@_YBMZI::RIG&Z^>+!M(@(Q7ECU?`!Z1R/+7W+?7;V8U=G_=A/#4[Z +MJH`GV(!H5-,9:QMYUK3N+BCS1N6)S6CP__[2=LG^(.H;.SW=P5%]78X_I@TT +MFD`&YGQ&HF]=LAG40(,HB=;/@&-FNO-]W$+MF_^QI"D0"<9F+*OH'#*71&-> +M-&#DX)VAV3`,XYO#IB-JP=\$?]]&6*8>0`=R78.RZ-WJ_?G%4`1+5[@&&/#> +M@X[+++(PUB1C=#9E%_>$->98+M_%+M5@M+WGC=4).BJ/U8)&F6S'L3)-@O0Q +M^T\,_/&-BX=[VMP11V)5+W1.N2]9"@L,OHDKR<2%PX,=QL1OO5/^?M(WC^=8 +M$*K\/2W?*U\_AB9)\/QS9,KU0-16?WLSC6:HA8^=#;9J4U?F50 +MOUELI%(S\>&!$1")/4(X45FH6*.*\XSZ;9Y3'U\A1%6NYWKD9^WG?ZHQ1^Y^ +MD?C!R-X`9YM*QVT'0]#VVAD\:V9X)\Z=(#^5OX][G8@BT<>K-8G[=W#LPA`D +M=Z#R:EN+G<`=_$\01B;90HEQCL-NWNR@-KPU9K;42)#2,D[4WAW9Y`.*#VG;8E2]K^H&-\.IT$P/PTHW^3`DZ/J6/, +MZYE,/,"$5*WSRGM>P74A2+DRCM:;7!U1K3_I4RVT')*(O7%F[88;YG@+?DP* +M9A(MKO)P!JR$^:0_5IR>YM*@^?`<'G@5C"QHS,ZSW='.Z481\9N/Z&JB/+34 +M8]+._K[B[);#B=2H?T;4$#B_$SR:.Q/R6Q*44R-YP +M4KD@XZ<'V>,V_]=\;_=F0DOMYCN5V](KQ/C9C<3Q2E)1R\T?A7HWD>DXMJ4; +M?].;35SOIQ,8T:U@P;CSJR21 +M`<\Z??9]@1E%.L#TVUR%32TM,*Y80C.WP>]Q62&(X<;D6XJ"XX!WX5F=MU6B +M%!'KR--WZ!0$KPNNU2X4E`^,K)5ZABG%<&G[=:GWW@E((:R?`\S+0J@C-G0A +M#4![R+TEBC4H<6`9EMOH&6E*`D03G:74_5AO$5L/H&0:V +MU8)E#N;2D6+9H$N3A''E,0>=I%&M^<`$KZ@.AGP"7Y`30Z1T;63]$Q7MI:-. +M`X,AE1WM1DR[=QD?]2!$U#%,1.?U+G4%G#(&V1W4BRT_2C,!2#$RA3[.!]!H +MK)OVTO>!*MQ05*QYSVQ+N\V2#.BW$:I@GH'M3BH),65%;GU[]VUU +M,I?LSCFSO^(15O<_;*2!J,+\]Z9:+U$\,>-$%]4;.3':H\I/AIRE(!0]Z.I: +M%=8LZB%K&1"T\_E4VYPLK+DT;+J:**^,!LCFT6Y1\/H!+,%H&T/I?Y`^4;)D +M*7-`+C?.;7>>!KLT,9!G@^3]/0"`,[CP1BT%TTGAA]?QSRV/(#KBS.S4/L5> +M4EDB,0#%R/HGKTG0@7_QO#_12@U&*`*?[[)"R%[_"D6$,G@-H*#D(&.C@'GY\,;+W;'&T&51)D0DV$<]5-'^:QHP8,W:6;Q06[KE`"'*5 +M%Y!`*9;W-N'YBL_I/M363E*03A>>3?O6[,?_;]BB'S[7Y:^Q<0(MC +MI,=$R];GNTBX!@!4Z!9,`W'DO$2A"0C5(!V;T<(H51ACKV&,DG`4FY#NW=0G +M78P"#%*BAF][AV$?P%)I\<#2A`[&=I@./3!6(]=#T,CI*)=/"<.?5&L4*BH; +MQRN(7GM@=0F#JG?FH/]:*8RI^E^U0V_UH5:2U]%%#,4RA.LH]MSQ?RJTF961 +M^PP?XIS/CO+05,8Y!A$/^I6L)9/?3`J;YRH0%X5%Q?TPL%?71.`=<<[B[_K5 +M>0C6.M7,>W.#@!2@[`NBFE+G#&`2=MKZ=*Z*9J_3^F5AR]11!"6G1$Z0/ON/ +M\R=@G-O>7@`U*,_A`BGBK[SFL$'>D3(0QJ[^S#Z&%3VR(@(O:W_6&XV*QG-Y +M%+6M[;S6$2T@U#J@Z +MT=K8Z1$K>KDQ+XF_]^/U@=#Z\I7GD<=#.2KH8&#[83;,UMZ.J;CRG&0$F&4X +MRJ@]6G@W:,GJJKHC=:BHFXE[0>A_YM'?%S&:RUV36A_@#9 +MZ:-U5;KL<0I"\KY2H'B6)%==A6\8O)C]FJ +MKZ.S'WIEZQEX7U\6O\W=A=8R2I8&=]@M0+G6.9."9SSG>7G2QW&I-IQ&E=J1&OU!'L>0?^+/^`;T;\B6 +MT?`U[)`/C1FG\QF(T4&;4R=C;\U7SC+![&.+D+L8NHFN:\E7/4=AIGG"KX,1 +MQ:3L)[*\T`_+4RPG.QN_ZM#0<)')/VE.9#]#=6:J>GZV/G#=``O)F!K!\#7I +MB:(9Z,4_,UC]`:AB]2I+-72-?_O(.)><`E0J2TUA:V&-;<(R0L\,5@T59#B"H[;G/,Q;#JP>=-WYL(`6FPJ;*(A.H=`W0#X +M&,/M,O%`;6UEAA=3+Z![(W$#>*N6//9+F$M4?R@^*E?B=I7H,>!=CZW:CZXJ +MD:)3=8N:Y_D#!&DQ&HBJ(B/-[F-TDIW[]RG7)'&25@NR?#5#6;GS65?SZJ5` +MJV@)&(OT7_X>,`_\C^JUO6I*!0AV7]PW0&PY>BR3GFQV27TC*")[TF`NLE_, +MP$OG\70>[R2[KVS_65.C_LA440$:4&*_R*BV-J!:0!J-:_AG?'O!8 +MD_"WUVHR1BSWD6,`#!91Z2M%@)/RX.I@R*C22L^R']U"N:"2DS21C5(@&UT(2*N>!_'-#5)Y41%VJBM7((41^=[H\.V1D' +M;NB8_0T5=PC8O^6+')B_,P=SS;BSF^#!_AV>LV.2IC5NR`\#NC\2%R6:QN09A2[+CY$W64D^WP0T4**_M8)18>+.8# +M!WBB/I9+I<*3%RRB6H.DUER`]PKUSI%;=J)0`AE+J`4XMKT6BF2SXG76FD>F +M.^`TDZXS,Z_B>;5YG9L3H+93&X??.G&UNUY8`AAIVV_5O,2A+XN.LI_+Y#V7 +M^%.[@$+_P^;5O6@ZG:"/:2RKIG>(AM/08H`1[#KOO>C'3(([W4OHVL(:.YHDM\;W<;8%P7O)+; +M*0-=>72GC"#F"5I@3K_=U5Z3@F&1$Y)J:7TJ^J%<#P(^[I=Z'-^MZNZM([E@W5T(Y)KH4.0W[P%MR1>LQ.DI$S(_$J7-D>00<:S/0IF>^\"P"-GOXZ[&B^[5]P!,0BT$H49OTS9?_67K +MR=VY&N1AI1126!EM(FX^*FLFFF%RR#8+]1HWZMPN`X4@`]K7=XH(?NCOWEVY +M97M+HV]3U=\X>?W[`HH?[^VY+XJAZ.IBT2@E:+`5J16B*S]UD0A8>"_*[W<( +MA!*RIF2P(GC_X6B[!4/.K>>'8$/P8N>+R253$=X#H??C6%F:.CO;A`C]DKB! +MW\1PJ*6CGW6AGG`PP"8^0I2?'T;=>'76HQ>=!@D9 +M-H1_7F*[.DFF>^N[WT$&NY_-PD=M(A14M1(,`:_MQN4'LB-A:I*^>4(;Z6VR +MJDU_?W!/*;/*[;!56$:Z9()[&,2GW8;\D2N'<"7<`S,62Y9XLU>:%](DH$E% +M2BG+JL%2=_?"2]C#Y*.WJ32:E;@XMN'`3)#3XDW=,='B'UA[^?6H67"*#:/= +M'G'4H01RED-O,AII_%W9U87"W+@%B\&%H-$CTR:F,FV0('/[`BI(;IR=%M]N +M)!V#*,WLIQ)<5`WK'BII=`YIKN3#.!2#C@J/ZVGMEP=N4/0#@H-7(WMX,DR- +M:=8Z^*W2``'I+M?2`\TL[!.=#F[DA`:;GGQ +M!BQY41<`:XH#G%B5K$X&7T7=I8NL7P7A^,\(M<>@)'DH;:H=*^E92+9J)A_& +M;)MBM$B+AZ-75K&D%WQYR1SUR20307*J1U_RYM97GSHA7%.B-XKZML>.-S\M +M^):B#6G`PH%2UUTWN%]-.R+?._@X<(9Y3&KT:-C^9H3SWYF`(*N%_,7F.'^? +M4!RC(\_S;\/Z"-]_X]TT:8&;G\IP"2S\0+VGTL@M26XOE5=,G9I6[H6ZA0'A +MJ!LI)!C:$>`@D0=/F9/+BW_$NE/NFE7W73K`%>.;`K2_*]H]/?"2#-,*("/J +M:K%(V%OSM("'C]?EY938ZTYK2"%58RZCP>-O\"[@MU##9`W>BR+5['*+3/2, +M_+J82`'\/WXZKYD9^]RUT;TF\=WZG/HN*M;RE#O8J1?=7F4G/K`^4,D6/&72 +MN4_8*`]DB\T'U*69Z6!;+WLT14DHT<:"XC368>7'8'@R@]/TC9S.6MH(AI,W +MX1#CIT=Z+CH\HNAM0YQU+H%'$TF6R:T)6+J#$C@P0_WA,N57C`#OS9*12=`* +M&*$2`T2FQ9Y_V_T1[SS4`4..@0A)ZH]/-,HP@W"9\C+YX8+RZ=\Q@@NJD`E$ +M[FX^7'X1$07+$H__U;X;=.NNK9\H'O!%VQJ^K+:1DG?P4WGCCN%[:$YSSHL< +MM4PYBY;13T+GQI@/*EP?UPPE7SV#U$BF#YE`,8C_BUU34N^+9A#ZBZ5Q,`85 +M\"((.NNX7/YO8CKV=K<^9!/:L`'1?@E,8MWB[;LR7(EF6/RE5\FALLO9>:]% +M8+VM,`EY-==LUJJ@.1SIP:.!W%')C7)^7N&J-I/.SQXD;S*\C5].'JZ0%`DS +MQ)8@YPR;-,SJ%TJBSH@@U,`77/:Z=R%LG2P+KW7I:!U=73F#$Z9I`NGDQ`#, +MTN;"'"UN\"?Y[$11#XC\_Q$YX?"R_+^CH(S6RFU?,;_A4(W'BPYD(J%D2G`)UY>)+Y3TNM#G0/L!_Q])X4+]RX-">5B +M[AQ;EVMA/F<-I5UR\CO:0VIWD7SR)OB$@A`\[3R<@T;UX5H:X"M[3S&R:P#: +M]NO+!XO^N/'VFLJYP\#N';7^J\KN@;PW0U.*D\A:!^89NFVD+Q,O8DZO)2?% +M'T3O@1"@YB4H@3CLJ(1BX+OD(/*.Y^*-M>\@(B*<"^[W+R)'U[T"L]N]D`8= +M$JR3-MF;:=-M@W#O@BF6S&TUP%<47%A6W\0B,.A*/CE+^QE=^K&W]:"6]\-I +M:%31//:;[3=NN`5I>IOQ531V!%"6GW'7,5Q/EJM@EVLO_[8,.5"$]W&=\ +M_7I<0@==ZH)P\>WUN\-261Y_1EN,Q/(-?F\='5(Y=!$/=BO&7/Q +MYM<3_$"G"M3E]=??FK%UJ+!(H,<)?D$`GVB8"%I#`XLV2;YXGFU$;"Q9\,W^ +MC!LT<:QT8G.-*EQ<\=)V[TO)D4_T$T0T7CG<=<[A[=6@&MPOPF,"=IT6^59@ +M?5<$;3<5D_?_7>Z4P,=`:2U+JJ4+ZXLM>?GX+0J/%BNJQROG]2YG6&8@;<,( +M%3A0)\E)T"!GEOZ?M?NT>&%\X(2^X]'8JT&,*Q)_E*?3ZS*Y@HIKGF*T_Y>. +M;#.!L53ELE>,"]V]\0S-2(+,H,0'9M[>.X5<+T>&4XB&%7Q5>=9%)A"V)N>1 +M_;DX3Q68@L/MTO5(ONE0.VDO>LF,IX+['G* !LHS+XF?R?9.QDO!0D1D'8 +MC2HP3V*'&#O/@P?B!&>53QEU=3TO3/!]WQ7]Z\*GFHYGE>6YSNKTW'BC7@2L +M=:UC5PKQ_2.%=RE5(=20;3)W]K[KM?CS"%<=3Q>I@IS6%*,U*3+\.9D5L#$: +MNGZ*`@O/0QB?)DI$89Y!UR?Q/0WA0%O)(%M!X5QUW6F&P(V[V1< +MFD#!$0_(A[ZJ<\\?5?K\2Y)$M;U'4=,N;L[9Y(C$8V!I1%$IRKTU@IE$_MZ/0I/=*RR)`0N6?PAD$K7]3T\C`HPJ&TX]5O0.+WE0` +M:K-U0";W#)O"^9SQIA0MN\#Y0N6*$R,M)5OAO9CI@QB8-<[AD,WS2>.>KMYQ +MM:D^.UFT]H"'H*3EZ;R.34D42Z&62&V%A*BV['B[E\7UU6Q>BX&)<(.D!C]>@L>24I>=YQ;620]^;,@%,G=C^?90 +MV*MK,.U]R+C/G9X:`]07?MKMUJ"#]8$E>[`%; +MUT$K(G%*)AC%-:Y.NL\@>:HJ=.9HX(/&AOR@.H:^F'VNOQVUUO0"]N^R:_2FL];[P\TZ512J\@VDH +MY,\G0.WB??,#PYL>BB_Y'8]$,(ZQ%0<$B'-DN0V[OC\H>T?7;ZA@[4BMN&&' +M_;ZKIAA]6/`[_3,Z(N:U'%`(OE'TL8 +M]4WT*27LB0M=L=H4(/HC<.62J6&X#<'^7EP^K_-+U\%/5\]9'>J%=JL.I"8O +M+02940TA=IR",[S=C;4TISKI8!E#Q5K*-&<9,@,=O()-K6N22,1[?CDQ_I.A +M]9\?++!\\R2A>*8D0G')4_AF'` +M$F^O6C6JI0G0=R+IJ_,LTWD\C''(&"3DP5RK"D%(JJ$YJ%\@^SOD_8]0XA69 +M`5]/C4&4XQ[PUYHHX\5S%9&IWE/5E]JA=E+!&,Q#I'\DBW_@KV':Y3"A\O"R +M$G);E]64HJ6A&/8V\#0/#_5*?_4>HIK$`=\UBWT_`%.#%?,389J3RAX8)%,F,EK4H-)=C=+0L&:BY0DI&NY@.`L_D^O +M>N3R0\)P>+U$T[2^YZ>!O[R:J,YIB8)JC]#!GB[IL^#-+CD%_&QIUKK#T\AW +M6:W)*-Y)FY"DUY\9IF]'@'7FRR([TMROK,HG>5#=((Y;XYZ5!?I3K/=/(MUW +M4FOFA?OE5M1VW7U<9QGH)6-@^D);3 +ML@WFH!>\BGO!II@E_N)'T:M[;D9I.$C9WUU4$+)#MWK4TE40G=5"$,(%R1(( +MD8_N[,#ELQ?0HR?>_:9WU58:)K6.BA8(#CRZW]%@5+=MO,*"5J?^<.TDP1NEJ^DL=4'6$*_'X4*&B#V=+ +MTS7)NGY1'VC$Z-0H8AAO`$MPY,Z_0<-E6)2!/6`7L3_,*@2 +MWCO%BNQ';VQS2W)XRO0=[]R>0#<%&0(5CH'6'XF.ON+L73E)L2X,//OT5K88 +MV+?HB@@#?)54<-K/E8#]W+*ZTG<5!A:2SL\\,"\"KS=-!(3O?^^V4=AOVO$Z +M:OE9FHI5O;5S.P^^QKG,U9[/+!B(CCA"#[-/!X&]%[+/D.G$J(M2L>:[O4I# +MRTN\(#6]'P(R_'!.'B%AT^"J!VI=TXH7OAN'GW_0!*F#!AO+&KA8\N[#'GU2 +M,I$=+V`:A+A7,5[)-PSE])B=7+N_#C!COB93Z[7%J?C:`@TS6.LE5_@/#OMEB>'F3=5^)`JP=1&T@_:]AJI:*UMKE:=R69_^):B(NQT +MS-"1P&F5UF&+M.0?$N/+&X:Z(=)&P/I2E1C]^#E* +M`S7!`Y.U"QB\<,N3#HQ0',(F#A&"_/-U1>"&ZAM7>!C5T8VHE;K"\\_&3:^L +M(ZBG1\I-'G+S?T$2`_(8QR_E8/4&T3;MVOVLT5,ZGEP]ICEE14UD^?WG#EGE +M\ED303@LEW2>OG=Q+HQ@7V3$V4,;<:GA-T[QB=@5CV].&6TWJZ5$+8G;?S7) +M`H:B/AC`PC>;3P,YU;%Q.%4$1V^DP-+E7`9:0M6W52`!Y%A4AC=&(#<0)-O9 +MT&?AB<3J@'_(=\42L]H^=,1P>-5.S6AYRW-`M=)R_2)#CQ[N!L-YD]SIV!_C +MK1S&.NO=[QEE+(:[CDMZXE^?!@XFN/H4`%&O@U'<]P2;7S^=,S,2`;R*&?*@ +MC.@8<8#>)UKQ#=2!\TA2^MN"0$]Q.N%0\U#Y6%36FIRGC;#^ +MMU;AW*IN+,G+*SZO*+CS)<:C]-X5T=5BE#VRDK.P\Y#KY_<'4G_FPT)49S$Z +M0]YY=0GI(5VB5[X'U4EV=)-A?DG80Q^@=DUL30JXN5F>^9+.I,EN"8#$2U>O +M8T$+-KY`*ZDTL?%9>EWO&7H89E.*(M2.\GC;(YS_%5LO<3`6=PD3D_KNEWKU_^C!6^;)20!9:4%0Y> +M%LK9TU#@-:R*NMO?65L/`CT=9P,2GY(U]^Z%Y6?;G-Q8AKL5BBEN61!S"0-B +MU2HWH6_@/UMR<9/DL.\1#)/,2F4%:`2E/"EZ6TE+*D@RW +M7A)G[YT[@3CUX;FUW/IR$E9[E>8U->D(\SU/T-:K8X4D.HT&[J9/QZ$X-T*1 +MBHT(=A`C0#LQ(;$,4S5>H>0,\2-',/KG>TME,543W<$!+:@^XB7'MY%T@G*' +M;4;HF>[=:T,:P<-_.!^0_;A,0&-LC5213K/QG''T-#YT4.'=JCK/[T)_V`1O +M#7>I\^1P+^IA657^ZBDA$42\`44GX*>HB,/]+*(.!G`(-;7K.+/<+^V?,-`.>C8.B] +M_!&\#9QEV4(]I1)`<2P[G!"`&[]N'I4MPO"-%CU]L\IOF_"@'I$13?J3OC0K +M"A*:276]TV8F5F+S4+TUQM,"-.UEY^`KLMLG[S'# +M!_EQ^"5MR;$6+@K+WS@52^+]%W>)C"G1R;S.OGFL.K>VU+D3IW@WG4=8ZZ!' +MF\F3;U/O/!JJW1.+XW/QS@.(2?]1]W3U*T%1ZEK(U*[GQ.BTZ^8RQ4$]7&PW +MAEOQ@+MHIP\'L$3M!-EK-C5HJJGM\@ZP3#CDJO.N&WA('O.FSTU.A;,J%Z$& +M>_]\[UYG_AEOEU*?EN';ZD-P2]#YK*U0UZ8X/V%:/-,2)K[_92E49/Z2'F@N^31I(\7<5@6PE-'8)50_F=XOI@%"'/D70VY1V+6"YZ'S +M.WL&U175B%6\\@Y#T2>NX\#-C$Z(M=U4%5$2=%L99N@Z?XMZAH-@=\%@8'K3 +M]]T4:?<,]X,)^RG8KBKEFT\"W!D9!L9[E.=:0Z%4G\%R;+$W?`_5FR*3II^@ +MP\:(;U!C;/1EA6E5JARM[8D9MW`H;PWW`0'C5L8W7:QY@!C0TI(3J*%1][7I +MY!9<_!WW+FQ<7J!)4]B!\O%<(?HRP0*#EAG4\X%\Y1:U6_*/69XS[SCU5XA' +MI(2+H:5-.V2?B*0AI+OA\J`^C8M)Z,1B/+=`$WQ0M6M.5?*.<;Y/_XJL;0CS +M/(Y_OK6W$J-TKXP1Z5JK6E?9F\$KB^IWA(UIL1\"K5@`JE*_=[?>M0D;VU?@ +MYGBN\?9LY)2A=:7`>P4R+/ +M%94:@6O64>[&6A&"7W'RO6PTZ1$VL,;EM2#LH\+N2'D^&/-[C!%5K>5B?0$1 +M[O"O9BGKB6[(7/D37Q/313_H%, +M@H55Y?&0[K>\7K!D77!'V"T,L5]V +M`(W$.HE/6B._G85]-`R6S/YIN;<$U5A%N@*?[<9NU%,]KE"UJ'$P490,R.>H +MD%$@[;ULWRXJ+>,'%[ZUX.J7G'^3+G-@_(C$7!OM/-3NA0PGNSN;<^SICV6` +M>@P81M_='4U6DVF.4RXEUV0;P\NT_7L_Y-KJ'GD^R-[TL:(/=B&4.U-\(F7$ +M'<_*,<;YUO<.B!B[CSO#'94OO+<9?\L\N4QZCXG5K.HVZ0'0K[#"[%.T7I2@ +M<0=T60TC(-2'^D5F_\P&G/GC`/$\T&K3S[R:+8P2A6I?4%K\=9"(CE*.8/CK +M.'%]_OLE\<7=?2+F$1A`S&51K7,&;3#(EJ7=*:H7DHL?E%-^@6Z)6PEZ^:2M +M%`F.CV9C/4/_&FK'5:%H&K9`#Y50F'.=+&(>S6)A4(+HT)A#-=ZW&Z*(D64W +MT8HH!]A6M;;.L&VEE+Q(>CH>V_QHW?`.PM[`[!,M34>K4*_@:PLD6<]V;5$B +M(!T23?ZJH^]OBKU<-RB8*NT53!9$].&D7+0E0KBH,1,L[FB),'ENOT;@3'Z; +MY!/FTW8:ZB:G9F"34*`VL2MH9O-[=-S/M&)1^3W,MH@Z8:O]]%,0"ZQ]EB76 +MG.Q"FBBI$C_RA4/?[8"%3A=K+>LB$H0#B4]CUG<2D>N_UQ*D#?Y)6'J'A +MX@ODJ&U)H8>J7R-$@A1834E=*;8;F;@J>SG\?W]MI@C\V>/@J",9P7S_0YT= +MI(<[1$DMM)#9'I-$QN=US5LV./M6@[%"K1,C\"4'!Q?[0-']*R3(@;8BRC$6 +M)";J\$&/^,ZY^?1?@?MKA@SY]>9N0XGY>=S;5J,WC/>7*,-I.-'D-G^*]<1[ +M]1-MEUK@BH,&#$3VD7C#2]1$2RE=,>2,:=)5%ZMC)0C1C*K?HYK696WO,^?Y +M#;'B7TT"U*;TLH:5"KQ>$RFEFJHJP$POFW;Q&[\^)+^F5,U;L\I+3.+@_TJ3 +MUL<^M+!I%18R=\=9;9D&I0X'E:5H6V9**F\:M:+N?6;Y4IH$%9A;_L"3W]HQ +M"'4R'=3Z9CD-6PP0IN\6_C5S!O=("L19LW07RZ1H0ZY"\@A0>E@78=5%7A8# +M.)W(-`W:M89L%'>`HSH'OM+K\'1@@(@8T^<6)*\+W)@I5K-ITMN,@,JPQR>2 +MZXBI<`E%W('/4`3AVBW@WA#Z*Z4[\4-+0:OYPT3]0T/Y>SJ*#;[=K]ZLXQ0' +M%`J5>E^?*@@H-[#FE[P;#C(@@Q.B[U!A;R3TE+__%1^+`\45-)^QQ(;YBR`$ +M>^[CU$R&8=!GNO53Z/I/J>.-0&#_+W]Q`<%EUWHHRH52:_9O+-_&S)7H96:( +M21(-TBH_;\3MB)"C(VIHP?ONX/^J9;J+X*[Z>;V=8?5=--\=F6WU4\1#`G(4 +MSZ6P+S_96!B-2VPGQ87M*E5]H,IQ2F%G@/^'<1QR"5N*Z31RQYE4>!%H#S:T +M#Q[ILB^#1IY5C7KA#NU":T>2CCDZMGX(O[\P8`=6,%IC+^$I0BDW@NRLAB:O +MJSC%B(B0Z$)'(:-2`Q]W$\Q\(\1O+[..<'ZM@,XH\?&(B1"#LSW(8B1RJ!8U +M.V@KGV8$N1UH!2[]0%TPX?93B?$TGH^XT>471-BJ +M:DD)P3,//=UJ;3;"[,=_[@`[OS&^L0`AU..N#O-Z)Q*UM%R//Y67>[AI\@&\ +M_@$#?JIZGPUZDF<'R6PF2$W1;RR3@I#E!:]0;7O,6030"TG?K+Q`K:Z#(I$9 +M(>_XIH2R"6$4W<](V(:RMBCEGP^/IAL$YU^Y'>T*28"N@+!W)JAK/#C&U[[S +MAS*J-+%>"\Z\5)@RZT]6/%SE0X0%7=5;H.+F/FJ5*4PGW=W/8P@B2KI`%R[# +M+]_9R99;].Z<#$P?\JYY!`%$RE(;DKS)ZNV:L[7_[=_G@):-=3@_L%Q60I!9 +MR!GJHAY7E*L,E>[>*] +MG%'G?BJK>#X@'66,_38.E\/-<&1&I]RV[VC;V752I$AGY->MH[O_]$D1"]E1 +M`14-50;_TC!I7/G"XD`#D:U$F?*+P_/4T(-$LV!P]KR[.A2!1`CNS"ZJ/Z+/ +M.P>U9QSY,#:(O\P<%$.&,AI>XT3HBJ0!=`(X;\5U<1:J#H[Q^&F23=71,=4V +MWQ?_Y.JK+S*B&J@9TZR3779"6LEWV=-TW)V[SK..&3`H3SDQM`B,-41L"4.< +M&`VYL$_9HZQ`_"QSFV00$6HC$RG?%78PNP@[Q,B8C?^K',G']D.8:\QEZ@:, +M_Y"S@K8#]#W\Z@&Z1[J0C8'>L=>)..T&-NY&4#%S'N?:0N$9W6C@.1.E:K.P +M$-2]^$BO"2_C@6$2\R4B@X5.J8*)A6ZPY"Y,]_C?A20CE&[=QA#B"9>52@RF +M3B';ZO79KIA\06$9T1CUE]L,K&8^$PQ.I""R1#51O%3'9.;Z0&>)Y_.:P@(] +M2DD1*N0_Y7&>N0U3OZN%ND)MGXFMCC.04KM;0=+_RO*L(=/QX`_-J6&;;CJ1 +M'4-R]=;J#BG\)Y`F$0IH$>G=9K?8B4V[_E>6D9++*;A>/@OUNX;[P3'$:IIH +M>1!:@PD*?`9;0##BX/$M\IC04PC\(E!QU4J";*0K)'8(&0^'HD$<;T(+>'#[ +ME=J;IUKQ[0/5Q9Y&R@N3^TRJ4NK6FP!"J,\5Q4?^IYHL[[%V2;ZK:O>IOE$N +M,,S(")4M?"TNL2>KAXBI?=,30*- +M[)3DSM=0D1.#`PW\,$IO,VIV=ET:9!AL4>@=FJ\)WE@5[E$UD]OJ_YJ?5$_P +ME`O)3>3-M$]^9_49%^UN::,_JW`UFBR73;L:R.QF9T^8DJ`81)YX1-Q&8!IQ +MLCLP;07,^/WW<:4-0V0<4U=R(#HNM;Y2J[3[V(,`I(S%/6,\K-XF6/A]ES9HJT7!C;_34^ZHRBR$(!O./4/+E +MF0&D<$W/#*.F!$GK'_*N9Y-`:Y;K7L][@=A!?%S(RM1MQIY +M@+^G*$9"\!M)NZ^,2P_MV!A28)E12G*"%Y +M,G#!-]^HR*1TC"7<<@@$DN70<[7)$!AN7!O57,TXN1<()M9]91X)C]Y&$ +M=V"GN`P-LRJBEY?\L%P7+XG)@#=UVR?F$E;P,X<#W;;VF^A///3:C$%+M%]D +MRN!_I:_QCN5U\(B58X(]GVQ=/Z$"E* +MLF0+[QL%\76PK.1Q`M`2_"GZHW3EEDQ?]`7\/LSZN7N\#RN%Z3=X74M(D*A*NOK=:,,; +MTT4(`3WF[1V;4-QYM=7!T=J%I&*ZU[*U/4D%O_\I]RH +M`4X.;1`.\#-]VCIME`\BI)K0'+/ZE`8@7VSRS>ZHS5T2LQA30_WKD38XD_6RQ@6$KAF0:KM%!F4>Q +M[4)&V9NUV.'X(:'K^3/9'7S9TB2Y9;:'B2_/)+O]'(N5_=6VQ\*+DG=SG$:? +M'ST5YXQ-:/`L"-A;."LB#('=T95$/= +MHF9_V/:T,1!O&'2]JX436G`T1.+H0__C[YERTNM;H(N,J<[NTF?17W^H8SL) +M]M09Y6FVV(5?5*J\DE8_2FN%$FQ>6_V6\D"I??&&'])!3,']L>EL4YF>[GXV +M7>CI'SGIWJ^L^J?<;TUZE"I;CK(L\7]3&2JVF^OBVY-HBDRDM!`21JN>V)A6RV8$LW) +M[O=*;U/OJ^N]R'1B>;#ELM!95X<">RQI?_-MG$B,3AJ4X(^R6Q%K.D]ZW52S +M$][=^DVXW/N=;3ZWJ>H@5IPRN>T%&BEAS`*SHH= +M8X87@NV(B-[+R;]U;+8>.^KZ$.]T4;]JM.;ZE\J\/NHPS/G%+1R`%I#C&35& +MGH;2#_]*.VI?/S01PW$7A63.Q37['_B4W/"-N4/!4&J9E)6Y/*SEYVQOH6P< +MX8Z+?TM`*.G1QD6RY?"VBE(\YK2@#+RMQK_O"D'YW7`%`)6L!UUIW\449',<]VU(:2/Z'*_L.#P[OKPL[2X +MG?*I?/3T$(N:G\`*8E-3D++OKGJZ3ZJ-M%9O[:;)4^^X.*`OP.4N`G)NW,A3_C=B&@T#.F^F8Q1_WO+*1W8. +M"S(BC%''^<[I-X&2NZO*C'T?>8QZN48U;&5RR:V$A5/XYAC*@5%6%'E7$T2L +M2=6"JLL"KOO#X-_^&M#-IJSW4][_0?7;`*=4)@N2#B37G('Z3*D;I'(]E>K7 +M&TAD`-P%^K^-Z\IUU)72]>0QL1WA%2$51^KII4\' +MF38=TM%5O^9;&:Y;Z:WQ<4,&I%_.!C?E2&;'\#6:HU+XB5&]=VSFWL4'.UIA +MX*'(ZYZ=&"6"[NG!DL:IM=Y9#@'.8Z'"/[H#I+E>]?!8PYG@D!DSD;UE-:NO +M^\V+.VNE=C]S8CO#D4/0(&X8D'=Q!SFC&*@K;5$(O.J,F+C%(+4Y#[LF>"]Y@3U>F[R_0^NV*3WXBWX-8TBDFN8 +MEQYW[O:6OA$:GD:8RI^N##4)&^"N.PAK1;.9,O'-I#C0QJ*0N_5"FL/W0;V> +MPBBK3;48,AN^`Q94#3YXFC`O?%FU_"O$8]8YZX'$\#8DFQ[3&,PK))I3#C6T\%]V +M]5=.?.A+$U[&:&YZ_3-]C-B<%K&#>)*QJIEW3DL\QO'E:=IO):-7S,A+G:T3 +M-C[2M/.LVS*")O4/F4_[VG9HDJ!U010XUV&1UIOBON:25%H575RD$GFU@JH$ +M>5FKMN8A;@7Q>5<(-KX4>4\*LR/LI2MT&.`,HL._1N[T"XUZB^]G="+2[FJY +M45CV[)+2&_&OJZ@JS\X;!8HFRH/Y>ZFCC_=(WL'DN."?>18C:S>47HL@$#+C +M'DD+GO1)HV9[&68+9HG>#Y.UH/)49!5+Y``R!B(NRN13KT+=')@J.Z!W;EKQ +M(]7_V0LJD[]NJ'SF1254$W(#]63=2X)FW%DK*,JY5.R1X6^4EF&=Q_<&G11Q +M7A0QO+M;FK2QB'+@8!7*JP:T=V__/.3#8=(64)D+D[&@B5DCAQ.XY)1.5HJZ +M/<^I,LRX9(_8SM#"Q8\`Z#9'(]L4>AO_"V)"R0[;*[+=CIA90ZCOU/N5!&@3 +M]^H6)@\$_&BB][@!BIU$3=<24I>`_1:-_TP)F:>.&6+L)]WG6)4T91/RB=W'6;)@JB:2!Z_2D]WYHQ%G +M_5"4I7?V7)!OM&""CYUM%+DG!MI$*O$LPR0:HGEQ;Y08,"BX;.DG5#``$T9L +M?P'P\_N!OLFR3?\J`%DL0:5U3N2CGY#/TJ(O0PT7>TQY9CPXTEMRIL1#2::+ +M@Z!EUHOLKSC.X$.H[J[(%T<+UUP1CI.XUO,/6,I"VD7ZNF.RR]<3JT +MS!.SG$I[T:+@]#-HI'56YPFSI'AI64F$_B3K%8JM>DAD![26!>":YNQ"5;+L +M*O.L8;3I\$4[)(+S$;DK +M`Y[P7Q:28.%`OG#(1/L4\ASQTUO51D_"`%,;[H_M\GJ;SCD:9>3*W+7-3L[V +M_BR;6E@+$:O4U:D"E,%8JA_;WC3:[.5OWG?YWXBI#RR=!=`]-.2-SR16]@_J +M+66:4;,:#97F/3+'!5:';2_V$O8P[3Y0`3]TFD$3ZOG+?]`FC8?,7[4'QM1A +MSQ^CM<;I,D6/J!%*,%YY[&X*N!^"6TG::U053(A.:%4^5])4GLR#-$XSW]-M +M?[FLY.BR9DSMC8PSB,W<)PQ'B"PO3V`HAR`(`![IK7K.T^;+FU^5="-O)/'0 +M`"=LZ^4]8;U/?5"=C"U;V@0!]WVWQ)(L]\"_+>&*`_GX+M +MWY7.S-?$&;_[C'D#A^U\FI]*O0?5CZ#[;\W<:`;M#B`\PL;+M$+['YX$]A!! +M>O8$^CG_=;;W2"=[\E9@#UQ9*7MYWL/LZ<8-R'935!G( +M(]`!T.E)\]L%(J;+K-'F81@>+E!CCY'D[/7%<\+/J`VJDZ`&T%-MG$N0HPJ] +MK7G89A6F&T\P3+4X?XI'#-VZ/QBA('$_V$<#]G``<)PN7M)6*6<;J\N]X<_C +ME/;4_M`F':$DFWB`6(*)[.9?ZFWMGV&"'/FUO&U$<(&OT(=*Y1<5!)/B4Y7D +M7I_(,9/-`K+CD'QB_\"LA"E09U15%0X@%F)UNJMI]_%)+0/)AIHIBXT,]H@5 +MK\FZ`"67]$%8T-H0V!G-`14L"F2__[.GY8?!LT?8X%@GZ=LH"G^2JCO&@^?_ +M[@^*;1G.)2&IEQO8:HM&IN01\.5W+EO3'9+X((K+4KD'6E[-.0T.DY]FP7 +M6,LK1Y<\CR<]1:0ZBNW!D!"'ECXJ[5EZU8 +MT2F0*7;MBD/(_@G.GI;2/5!&J7N?,F`U2U/M9]I-0P#"35K^TD9^+&/WHE`?QH$PV+=__Y3RF)+- +ME`&:`7R/^:;]7LH:ZXY^W@IG8/NMG@@Z,XPIH:J5[CMJ'``"4 +MR9X(U8/O'"ROKE%D:4)`1')*+<>'FX%(X`-AF4X;NKF,3YY\G4QI42FTQ@PW-N0X +MMB?1'4)'!Z2I%/-[)7O!7\5U^B'35-05W3V9TM"Y)"$3!P3Q`2-N]N-W/E:K +M5TL;SVO5F6Q2D5,9\GD.L9/LF6TQKT-UTL,[!JBTW8'NOD+K-,_%UI[X26:< +M_,2#K:>'=&UIZ\XL.-D$] +M`"=8?#ACSX'@F:ZK#5`(,M)1@H&I?EC>(*&U-@"L(A\E+H=)PSY>,X)8L1L! +M37L4AAF:VZCAW&GVO])5&GC!-Q4T*SDY&[C%@J-$>^R,2YOB: +M!&VJX-W[+@S]D+:"I:MG.X"-:_9@%BS7YT*C^#^'TP=-LNZ.==O^:LR?F0WW#Z@6((R!V'P+M+;3%OTRS`%<3[ +M"S-;6%1@ZO.$(0]:"]^H)'HI(@++MP(1:2!MZ2FU^Z*][(F^GE7)A]C4TB4`#+@6UX[<4X4QB`YNT+*L13(N +M-)TTHI#PV0>=V8Y[2)P,SB&*NN=N,%A#9`2VC8MY*F1M4(W5SZ#>S/"".FAM +M0WV4',@0(;_],BK7I`0**A$PYT)[`[7L+/<%T5WAI93<;@L:E50DU(97('9) +MD!]ED!`%\NP++$,/^P::"06'=?@FF0/]!\:K&A[O#>M27@K>9=[_*FBM!0UQO;E,8N9C +M?V\UWZV$0V'H2Y9"A1M:<`-,`D5JQ`1"97.8W.=+OS:7>-S2(%BJ>-^5?[46 +M5G$N>(_+@'UK9];L%_@MWU^H'FV8?86KVS+8FX[G%X%UW$XD/:!/R?)->B=* +M^_)7[PG]QK%6+-_PQ/T`'EF$)&Z60,#4SX;^X'TJC +MN&VMI.O*&MVP)4%9"3%UP*F^R#;Q+T"K9UUG^XB*B7EA!M%!+7FV.2 +M3M$DN5<"#0T%`MLY588+Y7V!.DQ7N"(6+TM,7`%GH5?.EA@=H]^-)=+ +MMCGNZ;1&-^&E-<50HS.Q-?G;PY/C7\E(\4K^??A"=GS +ML*&QLA$`N,KMM;*/U$+0)LAS^0RK<;6H4&BD20HOU@^1?)MFOC0&T1^C& +MD<>1GU$;AZA_G^TA,%M5[5W0Q>44OHZ+C%4#M&%&].Q%N@LZW*B:7$++TQ6WIPJM-Z];.'B65W +M-6T6S.G\XE2]:`L2![J59(*5*(5-!N%3V)B!21,9D.+L8WI]4/O;.HM_@P/*4J-!\ZNX?UUP,\1\$:,H%20RVW)-#!\? +M@+Y'%&>AR5*CWN_3#]5S>1RY4["KSY[,*%6 +MW^!ABEAPJ-_=IHGN:X)ZX!`>L0N-8[OH%((/U![&S_I]#"](M1J*"2C>C<&_ +M0.+^QB!AF[61`*!WBJ`S*\Q3M-HTU$4`HIR^,B>,S1?CVS`-(J,H+1=#O7%) +MMJ45SMV,?)+=42*OEP>8V`\N+;0]_P90(LLQP&5+[B\X1HU]NSC_8W2)P)W] +MN&?:NE( +MR<)KR7`DY*N/.0^/IVV]_TK+ +ME__6M^XPU'^=$U0)6%@2%-7:9HQ+]H>:P#[7LNKP!23,L7?-"K^_\UPS8,-! +M_5"A#]%!M'0!9Y.XG(1;UZ,3QSVEY8A[3C#G(8MYCB7M"R#E!@O"<+3_#Z+) +MK@([UEYD_*9FB1.K64$!L.QH"WL`:HOM>?G9VY336P*?_4'0HOGNGG\_]+8<'VNFK;0ZGLP+\UW5M32YQ?#4T, +M!7T*`N&4:_%+QTKU&:L"$+K!4%L65^P%*O;KW""^P,F-C22QAO?<7YI)GM=, +M!SP4V`Z+FHX1D\MY39T.+#!EWD"S6[M/Z4$;8)E1`T,-@OU@B,['G[MUQ`!4 +MO/[RW*X+S]Q+&8;*:Y_6*V]L[F(=U4P:SN-UC\<9OW:Y)4=>@8^=-*V:1A`S +MG^'R:&"OD0"CXS%XP'HGQW0PXT]EL)>!?_>:Q#:>VMBY.M +M-0%E;I\GOF,^?_UY]=TH)XQ])71G09AAUO8XIQ]8&5_X;9MUV$K72U.FYKJF +M+3*/H1,\LK"CJ!^<#,(3WTS;,E$J5# +M!$C417!MY_[<(U<;B%H'H31V; +M+K<0[,C<"(7P$5E]]<7N]Y#]*7#8/'-0'!:Y>2V_&ZDF71&-SN+05&>(LPAZ +MW&'->O65]O@]+DAU[HW^K*8G4SA^H<=@.R=2E%+5FX@33OZ +M)VF/3"5PUPU-(&+_5P#8#;*S-W?/S[+,G4/0N&OZR51+MBOXD&)V5'R&J,X" +MJB&_EYX6$.9*GGV*_ASIEP%)$,=<#TJA:1\A4QP&W`XX1ANF55K@>.&08<@V +MTWKA^%T22YR]$,*Q`;*;\$+ZG+(5/^2ZW%B)FM-TJ%LQ%;+EJFT=]2.29?O" +MY.@#C)&GMW&3G66UJ<`R9K#::-_2L$++/EZL!W\H+`>5R-'8>+XG@HRR]LS+ +MAC/P$.K*(YY7Z6:DB>YW#&$:O+^Z"A4C2R;OS*\FXG#,WSW]P.*?,E>%0#N]IJ)_4;CL9^159!QC +ME-@.N;39S@'--'D^ME2$M +M'%.'-Z?#Q13M*39*([?L*RN=_^2.8)N=E'*'G^ +MH8W\?HI)S@UHS%LTVNJD;3^E,$UMWSHB40T05]LI?\W!P2;J7$P4SP\S18CO +M7M29H/._1BQ4G)I1N/=2%NE_[)<4L41S +M`]./A*C5_`I('1/S10@6;V&*Z<,>4A8X./X@D51_ZD +ME5N+@'9W*I!JM^Q+_)V^()3;*G\(L+J6.))7$Q:RE`+;\1Q^6),?Z.\C513- +M?38K@R5;G+JFW;73SJ5++C?]>@QM/N"VW002N_:<,>?4PC1JMUK0$5((?%@0 +M)>@",D_"D`MYH1/!+SI!7+)+4D2>'FRJW1,P$'%]"=R?Q1_^M?N!B*#R8%:VZZD:ZB^[-2[_L]]?ST%`.KK6M&'E#V^R@1#H"HIG3)O<<]=V,% +MLT&Z]:F[IQ[X6KXI#] +M,N\%,I09]*28`MP&V9\2I2VM/NBU0O_0]*4A?A_VK#4_WYH=^4V;E)(\NXIT +MB>93Y1?=^65WIIL,8D.<"DN_YG*C5EOWS?DZV1B"*XZ.%V`F'^54N,`EZUN] +MR`DR7LN12@T-R\'?CQ%X+'!1]ZSOE6&R>^% +M=0*V01"8NUQF;HZ_)PV75H9IC3R7\IJPEVO2:;>X#E,`&D0<$!P+<;$L"3P^ +M1\2"6C?]`SL?\2Z2X%;624.WH_,]T;P_LYL.5/#:M"5A2^R*]JT63M&/X=$H +M!/9!&;I_VZ&BZ-/-.JM"RGJ&4<8[;A@)ME%54&,PVH(&_QW^S_'`AUO6_56V +M/J"S3E+GAQA9.H1_\"+EV[%B]$*1F=@ +M=*=Y]HAY5A4*3$JP+79%.FYR9P9<_+OS\0O.*MZ>]@(#(IW?^('(&?=-2AJ- +MA?ST?\JS37?P>H"!ZT8UQ4ET)FK_:,^5DSCMF?N&M'1E,$S"44FLJXN\=9!( +M;-LY,3#(#S<550>$X]:R`*!BW$W3`8(-8?*QFCP#.'&IM95$+\M(= +MDZ>8**XSW%Z6+:?S9'HKN[:B84RX'>U\-)7C-XI_F/`Q1\-QPA/D(>//G21I +M9%1E`II?I,H)5]HO;K9*2+'^9HP'P2>]6\$%?/3'I]9[(U8NC<\TUE0*J:F6=#D",TR;Z9H.6F*+$E4F/3:KB#X:!F*@1V",A6&& +M#80HW^'NEJI]X&O= +MX:>C\)()EUOF@//>>>3O]B"^=D*";6\*KWY.6_D)OV0,)2(A]>]?J1K\\D0" +M/&;TV?\G&*$8,(B'=H@\T7);QQ):H"Q=,?]9M9JO(3P*_?C];R"UO_CJ+]-,=K3&_Q;=O6*5M"$HBH@?>9?S8-&F9.+O%2L<<7^@KM(M)&SB,DS]("S=%NT*'V).%PJ%:8D7BP`D2GJ'HE[Y, +M6QWW2N6HMZ$WJM5$]<^K5WBUV)";R5Q['TM[#AM,!N!:"5$\<"?$,^^,5)J@ +M@AYR/(2O*EN;0P6/@O!@2$4P2?/D;HI/-:WEYL(8#+,CX:[/:JY1LH2R8:Q[ +MR@IC"-"?6-9MH5KO8=&FJ98T"@VS*TMER8FO?6(\-SL'&W*[1Y&+.VF:WQK; +MD7IE7W7,C]8S(LYJ6P9R/0I!E'!@=I'(%6"&LOSA_> +MG;[#C;GTM+HVQ2$>Z%G-\MB4=M[QJW-J\,/SX?+,%ZKFV+=Q#`5[?\9@!/_W +MOB+2(-GNX`)L0T!RR'FP[R&^/6U*V()5"XOT(OKH2[2S/,&_)80 +MKJD;"Q4R\R9PO^Y&14TXZ!!P/'_:B%NQ!:*)*DZX1$GY/_%QJW><#$4"=",. +M>?+UD247F""S2E&GYUW)&*&7\`7RL^/#IYX&$V8T9?X`[N)KM5L0%:XI:5>> +MIR9`;$>"<\,'O-YCD[('HP\;/W7UW&;7_PLPAHZ`?OQ3.<`MQZ%S<\4[/*PS +M@J_9JB(5A?X-W)S)NL")^Q[WB<1-E'-T<1)7LT@;M>YWV-.]7//-DM +M-ZS\?U1TOCIX=F.^(+J!S>H>LCUY]@@ +MQ=I``PY19J6[O03MJ,&S4"+H8///?[Z?J&B8PVL>,LR:K?!F=A7*:B7$!(P,[+S^8Q?4!>(-,3G`C"3KZWU=B+[STHH%!$OS^F<-B]:P\\5A@B\S[3S(@T] +M9CXUQ:7*T)*C_7U;!,X";KU:6CO+%?9$$:EBS/L]$A83H@"%"96'`&E)([Z0 +M3.8T:,X.UZPH+*B7#MZBF-\:1271$K#"HO!L[HX4B]2VP>+YTLE9G#E7I:R^ +MU.QQ<#&.=PA)/ZA!>&P?V+@S`>'-=;T..72='M$E+QCKV(_^G9N-/[_-J,CN +M@&Y?L>V5%`6=H8Y+;_8XVSRL!28CN*B9_<$=$":4'M9LNG?HD7GIQFWKX*`Z +M[I9[K>D-\<47=-7&+`YB4H@$$`6[\V1,%IBYR26TUHX`V20]!$6(\W[V+5HJ +M$LTE]^?'G#>*S#;ID;4$8O+Y%U,F//1+-I$(1=W'*6IBTOXNM>/\X\@!5>][ +M5%1P'GB,B%L;/\4RHSQL0WB`)#-JE"15@+P6""W:D0CAR: +M;[J3M/"QN:?]5/!IE"*\^":[,D]O/EW[N:RLSKV_H4#,&/#JJV>8S%#Q'O6I +M.H,TQ[M]5&G*.EP#UFI:ZL7!F>Z9$=02WC0:>^N(F;W-0_O2 +MN$!T)]L)9SR'YWDN&=>ZOL-@=<=9X6,63@SB9&><$K>[EF\1X4SA,%'[. +M=Q&5@>17*Q]+V-&47"CHT3C*PC04CSZK(%FZ7C+9?X+CU:F*H+T@X'U8X]]G +M>QKL3@B;.5#(.K]\H*SU3#B2S`T@SVX4!I.6QNBM!29MRF+PRQM +MSV!PQ_>BBA%V.)4( +M)TD209KWV>J'8]Z+#8-DR:9'SS")>::6/`EE.)[I6G_<&CN+ +M'%OB(58?6[=Q&BVHN<[F>O6F`/,"%9OL?_O]7]=4D6)W?SUY?MUUL<%Q_#OC&U,Y?NW,ID8L5;V^O2)ADG*A@&I[B3JQ>W!^$\\%+( +M^#'0THEC"V0KZ!Q!4ZS(5:92U,Y>?_^EEV(;Y?:"\4+`<9>$)DN*`UY?PUI6 +MO[-RL):2(_0?M<>2C&-<\[L"\?HW8C0/LK'^Y>(6'._+R7@Y[C'<_JL1,E;6;4UP`EBB[5%*8=@&>J$,2!S,MY!,^Q*>E@DB/ +MFTI,T0]K`09;QN%0T+O\]:(S`EL^(M=;KG1+4(M#K<@CT,0>X9<9$:G(TM>0 +M^+7Z;@?5`KA[C!7]KIF:V%4][%;D,J5'?._YV+LM'0Q-*VJTB#-C82FJIQKL +M'&D'$S;LA_VQF!*-7;L]%RA,G$M8U:B\3;X^F!#6!QOL*O'N26T)MWR%/DN4 +M-*E1SHC_MNM-SW^4KLP$NK[3-W^-@'DI>,)`YQ]_T(!42A0KQ,>U8>0'\94V +M86-C.$$*(KU16XCS?L5'EK0XC;`0!V'&F,>&6-RY+GY]& +MKSLP^:)>7PJ600C6+A%M-\$C_^VKQN7B-RMAME2201JVL$<-$Z^=4TC6^IF+S--X*]^KQW)[U;Q!7=Z#428S3@LFH +M5\(JDHDJ"ICZN\8L5@&`)!$%0"=@):O0 +M*^]!@0O28L.$S5`PHN\[NO)L(>6!!/U((/B; +M$24GJ:Q,#87W<],\I5430)EKU'B]1([MS1RO\_A<0MM5PL1;,1=EG9LK1FJ9 +M.#D6]FWE2]79919H'Q\X@E.ZT:H;M9[P!&F9RY>M3[:.$8V*@Q"VQ"P\@-WR +M_DSS=BM$J!0@U1^O8$4Y0&)`7I?9KV2VE0?Z_JR6#FSS^0J2Z-3L<64_2XI` +M"+.?M"#8W9^WAT-"*]R5UJWHB)P/S"QK6Q]^3G9L7=WBG<=OGF%1I*5W="OA +MC*19S09`#$:I?T,B6ZQ9!%/69;'8BEX=V4:7A9LL5KZF2)E9N7IZ22#[[D!- +M;:?.Z_8Y)8+W83\GIU,78^S[$A2G\UME`K7C(4$X7,"7;X^N1^=*X]MC'(>O +M_P/)0*OGT%TA3M&&G-(VP[L?Y04V^?^S*P8W\(OR-@#:W6]G+.$V8]_]7+VY +MQ#'=8/C<*+U9%\)J<;[;*Z_QYOIK@T1M/2?/`TBF-UD]RTVT%4'7@@_C8JHYV:A^H/ +MVEHYX??&I8,E\;VT,#",3D9YJ-\%;=(:R!FCK#&6#+P1Q53I)*+C?%$]]].V +MVU?=7)YN\NU39)LV\:A2RNLM&NH[E'YX"9G[[ERI6(+*AT5:O/3.DQR[ETVL +MILW0*U^1T:I12U(WC_._F=$)?$VQP%XVT((GE]I/3G7:;#\O]'L>G1D!N,#) +M"/E$"P4M-/2.BG*<]`;&??AT.-*]+4^@UF\FO5098%%R9BR3I=KOP6>C)PI'0Z^WUF1[4MH +M%S$0QT13=1A:#U_BR^TF&:HN4V%3J<7U!,1))=4U(,&<00J2=]+[/3B_M@&7 +M^I7\?9%(55;"-^$R(:"HUO'W\9I]?-)D.9<%5IB7CIX,\%5BK2VZQGK-2C#0 +M)+O%1Y._'YA]`/TS+4P-/9-HC][B8Y:O;L2(C:+!&GU33 +MF_%>9'90$$;3A*8N^@A6]#P\TB)Q'-$Y!AHA?3MTVWZI..5E/I@2$DQ0KS9= +MX.U>PR&9=XWH^8(E3[$&X*D@PU-$?.Y$+MQ&TGLSOKRFTQP/"S8JH,_GW?*3 +M@9=^?^T8]CAMR7-4&^;8@L&A9L!8TB2V6J5\YS5#*:]55)Y1T@&V_?&8F+M" +M-1K3Y[N5EJ//1WOGE9&7\G0E?^_D5F5/H0F"%#5H2\V6$OA%\(MY-AJ +MHC$&R*(C`'OPSN)Q/1ADAA\+$AB2T[!\GSK>Z3'1V"/;Y<6`N^NLY^)9TRQ] +MJY%<#`6'O126)V_Q_9P*M#NRWOA-^"M(EMA)E-!S'VG`>3%NMQL+N6%!G!"" +MQD80S1\0I`ZTK4G@[[;V,0BB0_[T@.KP^'K\%Y_TD>[YD339`(?![TC+59RJK=M@U5'@)DYTIOPV?I;]BD)ZA?@P&FEG_Q,LRF^ +MHHV(@PUFAS"[V)\_FAAPX69^N\7'($UH*GIEG;YK#.\_]V3D6.X]:5CK6@M/ +M"U@1TEBD'P,BC=-V3:L_?]86UN0*_4L:'%"MM/ +MH\]\]]_13F*3?5P2BWW,[3A7T.;>^D0!3RN3WDTSKN43]&[TU+E=(,^R"LP\ +M'8HQX4B?+0F7``;W-=F->/:99*G&[FX367!`Z`!7X*K9)F%N74]>+,M0Q<"$ +MOXL/8L6I@\D`/"9!0EA]:YW1]O-,L*I(7:C6N=MLQ9C9%Q>Q)KK,LJ9*&*_K +MF4-K!R$+S*^:YQ;2%4#QI>\Z-5)N-.9K[ +M7O0`B2>.LZG4=B)X95A+_$%JFQ-\8]0\Z\J**-NN6D=S8OZK0CF@KC@K;Z6^ +M\R'!%[H/2B$2?WA:/J#P_YD@=T^@CY<0W@;CG_I]]#H@L`::.GJ>I>ZE\[.) +M\R.4OZ-VE[P@G`(B%GSK`E M3F45/%!V7\GPNDLH/8?58ISFV.MU!"Z0HP +M2"*@27:DOC5O04E+I0`NIK<[B["M>C0\;L2_--/-)33_SZ81FYF<_9 +MKF:X'2\HF%JZZ7697XIY;\%%61;/2/K!:6:-80V>!F6SZ!TI5>= +M%27!Y4W'L;=,U,G09X8/:JV9)TK`@'YEQR='F=<\FR5<_DT/,6L-OEK>DIP9 +M+.X$M-K=`5C6B"@T;=MG.#V;?/_P.CTZTZ77&YU(0G?12JXS/10SJ!R#%=&N +M$[!4UWTX/H+LS0-;@&_.#9B\$(F*%*XPL[)*]!'8ME_;U-_>W?'Z +M]=#S;OFZ1"""D +ML-^6<2<7M7;XAO<^_10O2%;F0'6\=>=2SHQB-D-A;NHV;PA'>C^I +MRN&Z;")!,0F^!]*EJ]#O!B+1]@(:[&4M8!G!N[>ZK0'#L3\H3">-):^?[89;&_ZV*Z,8#0[702>"=5F+]HC(:'?R]6X7OF +M-%Z0M!A]GXM527;(;9.Q7^G?9>GK7MXXK[MLS![*>*79GN0'^/[??S( +MATAXF4H57";6DZ,)6IC1.4Z,^-[:/[,W(K_6V\Z:B^0VD7=XQI3!:ETNH_JW +M.XZ?C(N-]:0P^]^7@IBW&-#T\"!P)#H>B*#L,&&IG^-]IJ>"^?_7];!N=&X5 +M`?<8,MO313J8AH1(H&WDFX))'QK>LR2*^<&&L;\>Y[&P97M/ACGA)1[Y2@YB +M`]]U:KCU="%]!90TC.X.96 +MS_W*K,3\HDPJ%,]GJLUVE0DCLW2#W/=54K6$BY`0S#L82@/:I +M9(QL7/SZM2TCC0"T-=]\48F$IN..4$[':G)Z[)`S8C%#`].W*AF3H('$-7ZL +M7ZIZQR`75>!<-WR=N)H$HN-A5?$FYG'MC?!\*@XX`ERH$\!BQ%5 +MS`0\9**U7EL-C)0W1$O<^V$GTX^P_$RESX6CPX'H8P +MH^!M*@52F8%$Y\:^*T4`N3O6U9DGT(B!;PC$_`0D'!#"]+"IP0#5,C'T]T[: +M-(;$)SAKX4C9"+EQ=+0'U;S6PO6G6.V&*-OG=A:HP;7C_/LW+P7&D;TIWH`Y +MOK`E<1U5TM&,_;M?K#"IB,";FL3P6WQWS:8.%:Y7U;_=&X:O]T5MB[T]%V(TQ2\U'/="39=8]9L-.7A3;[FZ&`6M;D^YI.3P=G +MT;J^;SDT5V1\FP?;X.0:=2@.(7YM!FNW(O@F9V*HP2L6I#TQS'+$AF+5.O?3[^D5.%<)DR@V<Y`DDW@([^:8`DY_Y2A\[[^]!7U-+/>6CB" +MHC_T6,[&/X-H(3`P^9A:>HD\:%X(4EQQI>(TFNN`U]28>L)<@5>N&SZ&7F>K +MKMRIH/:R1RM-XN/6$PZ60_ZO@\U,X>=7EML7&$<<&)R2G^4KA7OFEA"VUUMV +M,L*M'G-1<.B#]F(];O3-1=E7*3K4^35,,8[29C[5G]]K-N'NB(.B[*JA<1?R +M2#A8B'`D4C`'874C`U.T+,I^3\%^G6"&N4*F3FS-9C#G2.UY(S+TQ`2YPHYY +M)J4W,9*:98R#=6? +ML__(11D]D1&!%1O6&EX;.>&?"X!R&59?XXQ-T\)I-9^'#TB$"\*^@?JD2F?! +M'0Y-TLB\[:6'@\$U`A)((52&(DX^Q`S+T<$?;RJSE$'^?KVI.XL)@W50#-2D +M'NY%5@ZNIH&LFON=U=7@WL9?OO5^BP1)'DG&'7<*7Q(!CC24,18'I;EJ'C1M +M0IH-77^,;6$`QKF-ACK^F(69;EB@+]0\WE%'O3!2:32QEO^]]9R37++3^22L +M37K,YH3NEHP81:64&EM$?3/ET[]_/Q41E"0_EXW52[.[Y7LUA"VP+BR*%,IN +M@.DV&LN+?)L-,PN7RU9D`+FL`#2FVB%;<&1=1SO#*UB:^)!I)_`5]9+=LX3I +MGFIBL#:2VJV])]][F+G&9N6V5RM47(&I1#%4_+Z[H@\@`P0=`=B%3(.X&"8M +MD^(J^T/B^/HYQTGR9I)/PO^0)Z,*VA8'LWJA8@T@T;>Q5Z2S0,`_M&BCM>KQ +M?:D&4Y>(]]?.B0Y,&O+.B!28R!?.[SJ6N^T)^MD:UZ0>K+M)3<`Y1\^<;$=) +M0S551PCN4QAJMMGQ]/O+_5XD`[&<0WNUGK=*YUJ`)./*_]UF.D$U"H62;UUI +M9.-3QTI94^`)?NL>>OC.#GFZ`:-"`A.%<#P&$E7`5*,K5 +MPMKV.>?J_G?I&"X6*?NP\6;DO?I%>909D.4Y'.^$72T`+P0I@E;]_HG39Q[L +M^S1A,T`Z>L.E*M,PQ)6@KX:37>:T$1?LL4(0DH3[7P91G>/=#*A[`9MB2L/M +M^XIU,^3^QFP:P26NK$FO;CWDT=ROHP5WDFGEJ,R6`8(?\AS.M_\1RW4E +M("84ZB]16`D_EC!LQ:V9?S/Z]';7V89LB+>UCQL/:C=%-^:=OJJ1F783!=N' +MSPKP6&337T6Q\X!9KZ5Y,3D#[T$&M7Z]7]J+Q.S5%42L3S@2^C>2QY\7^1R[ +M$'CR!O`V!'"HF88UK\\L5#YNVM0IK"GB\0SZU/@N,8Z]?RC?;;@-L=8B5-EB +M([D$:/%1)*JN(/90/Q@$4LZOZ]G^\W;/4HK%96%VNS?SWW$117E%[#0[*1A0 +M99!>[6J4V-10CBM%%'I4O)ISU+`7M[QC8D.GM)4J?Q9AG.K>`;UIO4_44!Y# +MJ7W>ACD=I<`YX+##DYR)QE_DP'Q7VY"`+7#V`1]/2"0-.CZVSP3X=*9U:0C+6PO/,CPWQ` +M;V4'%^K']<&)IF+&,4M8\_#^$&%K5$7>/PO5IA%,4BQ)`UP8\`AT^_G%Y5HC +MZ#;KD">Y.2X>T=GK&7=L'&5<$P?_4_2*,)A:*(U,LG:_E`O,=TR6<<8$&@$B +M]R!8W4>0&_A!X4Y)GUS6:AVST,QA=NVY\+7S_ISY7X3+7'`&F#X)B+`I1$': +M,AU<"A&A?L_"&UC;-^,[/"N]#NR +M+)Y8)^#K1,!O%KP`OWZ5?ZMH;DF\?+!!L`K@*N[B?MFAPMN5,WU83V]<3\J- +MI:WSF2\OWQV(HKW[&=6$2/F\;"TQZJF<;:/N,A_YJ%@R\X0`]+UC`ISM+>4K +M.F+B2F[B=8^A$+[UX[LE`YR>K6'HL6+G[XBZ9ASDQCA@X?I$;"$ICP6_'2N6#M_PP,=F&*4FFIX9*2>$2#R!,/Z\Y#_4 +MYLW"&U=>``8-\^>ZO/6^V\N^[!'ITO>/*385PLK\1W=P"3A^T-Y)C=-0&C!O +M4R0VP+UR??8N*6E']6_DZK9SS5:SR$2(3!YH#T9IIV#7-%.YC\++Y"#@)/V#!J7<`MJ@F(72#3],!>6)9A)JW&7>4`1 +M+V3M&,W-K$4)(@;0!OV-9=+M;GG.:%I(>=^-XV7"X +M)+M/LRD"3;X5&E)0I_3@[&,BH6%.3#-`\YGW0XES4U(NAXB[I/YHK23-H-N-9RT"8V!T'1 +MUE_7H'^";-%`''UA&,Z4_NQ<;J5%JECE5RKQEZU5LZN7K;C"LO:;.=Y)FIDV +M">)$$67V^OU)&!,;I=W=TEHTP"Z>7\F#1U[9(RL)O]5$=L(N7O"!;EC@*>8' +M5*)%J"/5G,!+A]K[@8+$(K-[[N5*G*IE\Q%1K]T*MVU>^.1K,_#KM3.Z1DL_ +MW\3M!VW'$BW)!S>A@MME&5K(;!8TONHB[=Y7MKK+%FH,\:.`C/L8H^N3RO2_ +M:KH*WO/_$E"=?/C:=8UUX)@3=4GWM=E.V_R9[(OH+9J+E;XU0?\G3\?2K6)- +MY9B$]"" +MI6JU)[B=]9(0[>8MNO;Y*5KO@A7-6!XB5#>$]Q!Y\&\T<(]RI)X$G00:^$*P +M"Y?BP+IV:9:JCA>2*;LQRS>DJ9W\VU@!,W.QV.YU=")Z$ +MLPP-%GT3,+IMTN:4Z[``^0[(U^N]$[0P2,7'/?<2K^,)58J]T04 +MZ0\*K=>M&?B"28Q!-S49,V+_=`QSC`[VRL3A)!9M +MN.E@8=->R:$]7UL@MK(&-+/-&+7J/I9$LVJK$V0%OJ(!_[^\`[WB0@GGGJAB +M@*B*`S#PY^C#:%#"QCEN2MKG3F2Y`\P2CW=SZHZ7B6$O@/_GB@5WY?KB8UK' +M1_A).-@\:J=2%J/M\0Q/)W#VL0V)YE?C&^Z"ZHGZ7F'`[`X7(3+\NR@[N<5U +M)*_7?G@=BXQ]=`9;,)$FJCY/$"'7!\O+D??+-4;*1@!C3G_O-2??9@9WGU)3 +MMI:N&EHPML1`D*"4?K%R1WW +M*2PW:!'H)9Q;VVSS82M6T+JYH%&XQ$L&..,F`WH&XUQ:8PH>TA +M^H.,ZBRN2-6=_Y/+4$B@9B'H#*&WMI=[:C_K+#0AO5\(0X\](_J5H,9W2V'O +MI3@"I:WY+853XAA$/^TCO&^)=+DSD0,-_",7)WM]+]X*YF0URJ +M+U@";`9Z7%2/,1IK\8\>K8"/_TS-(1CFT_,B7B29%.>*/^U\YW?\G-1X'$D@ +M]-#[()A,\#YL-4XNF%GNU`*WU)79.K]5_1)$'?A>-,7&KE_J;0(;@=7\?:&, +M*4M=C.B;$Z$OBO=$" +MB/5Q6:BLO;=/`:EQ<2/])C'Y43$8!&O61EDFN+Z.3#M2<"?4KF+]0PLR+-U: +MGD/3EZ78CRCV:&F*KNQXSF:=U6K$UZ/H@M[MELL^81_F3-:;F%L;OX0Y/2UN +M@_OWFT!SO$A[!W2."ONZ`"&^T&"9_*R:=!L398__XX("6,_UD",.#1J_)?'] +MN61FVL;:D6J^<'&PX-L%AQ+_3.3Y&I'>8U+:=1I36,[@U>_ +MPL$H3$`=7_7<59*#F\3N$3-7/%&#]-F,EGE>\E4Y80H($%A.4J#S^J22]Q,V +MQ0G>@F;*E5K!/SEHLUK%1.&0XI!3#YDBB77K@N1Q@%N9^`7P[+ITAA^![3_Y +MYHDUNW*<)69?K3W'SHNHDK4R5L#:$3(2F7%)FO(KD0(,LI\X_F,?M!K?:!<: +MF[2>:%8Y3/B4I;\THR7F-1C=3R@4"LQ;;^=3^#E`61E"C"];F`D-[POQ86SU +MX<.!)3C8+*WU37'FLZ'_UI!QX'P#VG"NB5[]!FO8 +MI#$FQ42[,=Z1:7\1P"V(H$!-E>:-7B/,14N(/I9=IM,*(#,&F[#LLB+(0WQD +M[`T5'UO_L4I+Y06H[XT[K6(N6Z;L3^/5:?=('N/PQ36A5K4^%$5YDM;*!,)^ +M,/2>UUWF])&1-%\*."%D()/;3CC+77[TCJ!!&WG]WOR2=KKD-;P%Q-!"LYHK +MH..;>U;#WJ1+EG.887VK).1W)A??Y5V'X&;?XA+OY-!2]K0O,P:$4LXJD> +M;G7R>R;7^5K)VCT=V6==ROW7%[9R@$8K>QAV?-#IA7A!OOYR>$Y'O\,ASV;. +M@)2$36S^O[(ER*Z1*H$]=;_V35_CPY>C]Q]!VAF*3^^W_4?G.&(5]!C3!V:' +MAC=L\ZB35O#W11PU6O;B`#V+%G?[;$UUQ9YR0V;1^;SAK<:`2X&=JH_B+,>1 +MLV[2G'8J>!I[U33-QLHO@G?TVM\81N8Z9-"D8GL>M42N-:7Q:*N^!9EA +MD6=^EC%O5I#^O8NF=`BW?CA],%O3B8[E;O"UB_P/8.2I7;.LW\F`$Z#@EDMN +M<$&TI>\1\;3>L>G'H9;:6,>X[&:_1YMF(4Y[?PKM>/N?U",NXP?A[L6\Z;WC#F'HG'5FS0][*_#:-K^JS01(N!A.R3^87C&3Z +M#2*9LM'I]"-\[`[)_X;_&+WZ`:!]B$JN_$VQG.DJO(K&*R`"O7RS3Q)N17U@ +M%_+KBI?!?%0XSUG%*V(Y)H\.JD)]"W"]]I@&("0@#8$!^C=,6I+/D\M^4>64 +MD+Q')CN_C-J@(2X\#O'X9I&F#/J<5[U[2BB@\UAOMT[:V;[$4D0`',A3>(YD +M=N3'D"3H<%NF0OS87:9I!U8IR^Z(3X?HBCXT1'GJ^^+MT3*@%SE0>8DQ0Z5? +MG[?L\+*E2E,RKK<`,?*L>I_9];5I$-8YN2P5OO;O6\WA0;#$;HI'W;*C8"I# +MM`%E6P,X]S).?J`+R6^@=22RJ;5M_J]S6=9-(=UQ2%@S?)IU0R$HU]5%/S\< +M#<4&%4P[36))H<>HN73CEY.=1](/T?BD&F5`,_(:*`O#N+XQC+2KW)?DE!]C +M8S[-_"]M&#R!J'-6.O\@B4Y%!MW*Z<>`JNR(38Z%MI8B&@.6H5Q!!@MND8-) +M#*KXD<)`UJP0ID5>ID#-X*6,K/##N7?'ZA`M0OT%[P2WE=QU3]1V[8`#A7IX +MS/^B3EP9W7:@C>2;1PB=;;NN="%-1\;)IMINO4LZ%O6$9H6\XO"= +ML'^W.,5H(9$#[<.40H>E[(G9D.U"\LZ_1*K[X[JNPJY;H2BZ&AG0+ +MK)"W\J')@C<)?-!*"[Y(#M6OO9?"XINA-H5P00!NAU[?<(9)+((HQT];H +M$MB&K]]$V36E:\*/BH3IG8E64GBZ4!/SIG1?R.#D1*`?(SWR^]#^8+_&.;:[ +M`LJ;'?%+RF<.^*4CRI%APLQ!#Y]*[A8Y.\2_>>G'7Y=LM>;LBR=UMA^`+6V? +M>'@G>@,#N*2,Q\CUU2+IGF?QIZ?\U_J#4!BKPF>;F'T_Y"6&?)3$MJ.>6F%F +MK\;H^T-[&"$=F:5\D-KD9E+U0_U=E"2ZZ(LXWI1ZWLQ2^7`ALGS+[\1+[E[8 +M[9[4&6?.$B+D!#FN=7D>T[*2"%@X.&$\R)D^/=HS2?G(><%0`'J"BW2:_-4' +M&)O:@:4+?%[457V0D&HPN#L_O1#BYI@O>FT=C33P_ZYK,P7U=,?4%!N?V1>X +MU[=P5_.4J@.#)CP@Q5'BO%^+^>N(,:FEF]5N8XFK!8656-N!*H_LBS-CSLBB +M4L*];<=.8RPY/92`X.T7(!.2J]<#GX04ME(8L\ZZL(U:\`&\B1NM^';67G$V%'?6`QO)UZ^'02?S4JHOGH'PD] +M+!`I@+XT"^MM1ST_Q)??M?6)-D0.BI6!#D.7QK4SAT++=(+ND0I^G"=XZ_I6 +M2/VB,0PQYD'^*9/Y$#$&<9)J/8@!6\A6_M_#>'G)ENG`BPU551KT4 +M'W([;W-$?BQ"`@HY\BU;/W=$D==2>^"7[:.PH!.)Q&V6:AUXU]29@]63_"1< +M$[X55X>RLRC(:GPV?-!VH9<:NTT@7NR]ES6&^?9$K9FDNOW +MIZ("6"`GD(J:QCWU-$:,:JO,W?N_>E:L*3I<1[I#S*_8(8AJSK&3)*'$=B6' +M,'[%W*UX3%!K3++1[V:!=A;98YBCJCEHQ+;!V(=^#+KUJJ`6-\]/(BER$AV= +MIE`/^=:8GS^O0XKP"XZ?RA>C"$600VPE*OS`#VF8`,^JP(M`JRG1C?W$,+]? +M"0D"O<*[C%)Y[N*SZ\USC"-/(D6S#]!T)\O!9R6]7DD=!1PU[@X*@##8+G109BW4CE:F5 +MG1CY]A^(12.Y>RW6599@>T;]BO"5]?.5):8;['X=9%G3:1TZKY'-`"U446DN +M/?#G!%&"L(I)ZBK!O["]#.)7\(O?1]=;N=D*_1P$O3?CQ +MU;#[1W>8M*5V(()`X1G)BVCA*:',\GEZEG(@L*D<>U3#:SD[>SC*PV, +MX^XH^\>E'SG!7%CK9%5LNFI_Q!$U`5Z;+[53^J36/RML7<^OPDH(2%(NWW2# +M"@++-QMTI$>ZE`[EB_]W:2BL'UX;I:,)I":T(54Y`I.<+(M9C>?_D2JY&"@J +MM.=*2S.3U91LZFZ:]U8#*`A/ZVIN&>/I>Z=W7PU\7KM\PE5Q(MW5_F#-].SJ +M%1K@"A";6N'KH._(]P+8$V[NP^CBZ1+AKT8+4S:A$C$5C*2&S4G82(=$`F6& +MJ#N;MG<(?8I;\U`+]*:Z=K`H^4)X!(N%>B=+GG0*W"-CV1*6+KDY\$!.;"O- +M+K=G<(C'C(WOMF"^;*LS<+0^H;#=T-$WLYLZS%OP--<9%PC\ON>!%S==XP?L +M[RL"!#?5.FN=448S-?[B!1&]Q#S(18(3J3!Y?PO,M!P1C1I9EE(&W)>/5]"3 +M<$OY,6?YYD$#%/F`>&F7V6J$+P`SL<'IHUR\>&MBQ*=^K*0?<5(7G)B\MDK! +MLW61*U[6EH9-YGZP=$S5\$Z!E)5XZ8!VVGKU$<%4)GV73S_N>T*2+:L?VBX* +M'%(M^IQ)U;]DRX5W\]WAHJ"%(JJ0<=$6B-.GV34Z^`P>YXVP1&H9D.39ADR/ +M9BI@C)F<[OZM!1NS^$R6[2/?.GZ,S0$05Q[*`.5MS#J-'`TS9/S +MV#*G5PB4BA^C:P*LYT6K*NL%:S9#V9H^`XQU2BCE=E/]V6WT_8%GJU4;GN^G +MZP65#DO%>U<"0*1:6_)]4Z1M5@WP>$G<_K:A4:?U_`?$7!@3E3E66=1XVQU\ +MA-F/+98OD;+Q?WV[S9E^Y'D)]%+"NA,BQL>*T1\+YMM;E1L)NS9[;OV=*US[ +M5I#)39YV<$X9Q<*T[R'B"!=^D!;C?'JZ3[1?`E:-:>>K[YA`.!=\%:P_]RXD +MB*,#*O^4-H!?;#=$[2`D94W35W6NLQN+%>[L(W0/2C]SP#)'M$E`F/X1U;FO +M/K6BG'ZK'Q0?=56O^P[2@!RU%ST^>$<0L$]>*@WRQRQ(F=E%DO)=F@2<.+-> +M.8@U@#."!5?S`QSN8$5>\>G'B#Z4?CA_[%[+NNO'H\A$^"K^:F%RZ,LR7"YD +M?>#OTE?HM!A;P[5TCP^V=GA:K-60,`>1"=]M."NT!XIH1"77S-T#+99\>QK@ +MNA%J_Q]N#F'`5R"\8\SF`P*AIMWDW3[]L1`G-ZK^'OA_>>8-32_H8-ZU+V<< +MF$%24&U(MHR(\0,89+/YHR6$\XN2J#XED+\:D=$;UHO4BK$/H;`I&,]"VW[Q +M*K(8AX#KK=3.`B(8]F[&(/JD^2:YJ6F9'!Z.:N7V.R7:$YPT#?^C'.4 +M)?=(T#^GU6JT;QPLV7IG%Y#:E(G2S@Y&A_79W2,2,]809WRK'E)5VX"=%R*B +M>F(__''W-!V.KT^H5=KK:L.HK\O`')71V(G,+7I`OR]AMNO:;@'FI.LGL.CA +M)F7]G0?1V%YVAKD:,7'%S@%XDPL.]?30)ZI\'\=Q.2EAV:YNN=41_!D5A*-T +M<`J9R*I8U$*6E8WJ`A<>)2.SNFS]'G]7-D7U<>*SB)\-NS!!CNN1Z#O%:\WA(=SXZOP8ZQV8 +MA]=SY$HNPC*O60%-:ES0QXC$+<&E86#9=9L$NWN@7M48O7`E]VK:F:KXIEVT +MK=TI/GM!A82Q4FQGD8JEB:#8HJ11TSK#Q)(- +MTHLVO%`,-U\%P,5ZRGWPX[OJIN`/I(9*DXYAR8E[M[42Q@`66*,C]Y\!]'G&M.&&?YHO0>P#QN=,')@F(I&\:Z +M&G-+5462T9W]Z)S9Q5<)Y\"_C#*]HE\#E??<:RJ>6_^D&A`.XV7_`#WY:>$ +M;I#!6DW6\1T*RNA%"'Y;+4L!OYZ%!/=S0.Q>]-F57V!QT4VC2O=.8)[(@UU"WH[/K%(2'`'`0X>'JR9KIU +M4T=+.)P0+:&=U`42H*XMW!25F;RD-+T87*/T3"0-^Y4DIKU!XGZC]J(?*8Q+ +MURC'1P!?DED]PP-1VKU#`+$$$_M&B6.T0@-S"TA9>L8R6*#U"M(J45GW"A+Z +MK?)JGDAW@=*C9?;8P#G_,$Z'2NBPD`'MK40XZ3!:16ANX'YB;JX"&/.`P2`#YR<-,RZ>=@-A:SXU'/V?[^UL9+H*&AH(D +M05/4V?JWPX\\6.2@D^R."GG8Q1Z\/,+DRNL"?I):;18V'N(0*AKH!^.' +MC[%1'[XS'?I+%T8)!B)7A +M)]ZQF.Z4M=ZU,A:95-_=B(J_(RHDK:/UE$URG/=0C<&8>S*Y3;H'I1YTN,]H +MO[+J/2?I`K5EP2OE@D)KKR&0#>[$_4-'%T"Y`52$U7-4:KY^-Z@"G30QPR3P +MU=9.=,K62\Y_"Z)0_A\EO:SL6OAEHSEQLRVOH,LS`IF<:84PB"SR3']D!REA +M0YTG%3:&[34HDY+U!9@!I$(SK_.%!G[-*,\YHRCM<7\9Y.#L8%#',6S72"^= +MZQB\'GZE(!M$$)SVM37K3=ZSRUKD"L9DN;\6SO]AFC5]A'=J,)TI?[U;D39E +MC==F`QFVT,:\(F$D[DV?Y=^RJ1/.HG]D5 +M:I:\W`WS-(SB.`+06T(EK,IYYR-=)U4BF=X'/["3E0@JSZ0Z[3E +MW.D$O,^_`4MB$\3WFPUZ9"V#TX[9[8Q7YU1CW;O&S/V!S+/,?3:R5):[;S'B +M^Q"KB`_W(?VPQ5D9):%+`O*M%AMVJP,X3]?/".&Q;D2D2$^[8P'I2FKV11+\DFFL$5U2Q(KJJAQ")<..A&Z4 +M'X8[913IX5`A842[S+3\\_K)MG&M%TO@UFXT#1!.Z?-AXT"[=VHOX+G.?W;$ +MV/N=T="LE'!I.-.1QNDY6U`8!LA)0D,/MV/GU[-J1TTQY'X6U^-9&&'=L)89[L&(WRM]0/CPH +MP0CH'I,/2G-MJ@QWT:)2'IS['BSUIO$^!"YZ[G:,S^:D>)NM`E.S$F;4SA!E2%Q[R3@KO__R9"(T`8W=>B +M3A$PR7J>:(^<]_,HIA6*<$V33=*18+S3ZJ)80P_-)T/;LJTH@&-Z>V;`S5Q< +MN@1:Z!ZAYXFAO^`!FLT7'/)7C5C?.7K>D!>`6&B7>C1IM&N]+:X([RGZ#?QB +MTA\A#31CULLQHK[L%B//$W,(V;10U2<9#N*4NSM=IB93`[4(\"05M6@B%REA +M)+@_QD5<_AN3_RDDO2U-4"=F&=16T&SPSM3VS9F:/FM& +MSK$5%.U\HR(."E[59JZ_,^::25*F\OPW$$T`'^02HA"^2?\1M=$X>"KE/G.1 +M\ZL&E3`)`AB.5%8_U)YE2A!5LC^@>OD3T40HEPV21/"BZ=G"!@B+S/3N!]QW +M93=.Z;EGO!_?<305[L6`1)==#`6O?^F\02`@M>4_:S\F\Z!4;;P56TS5M**S +MF3]P!DMT4=&T4]FZ0;!D]-.=M5#C*+O:V,0I\1VM$#?>3:=6C>,7N%Y00MB_ +MZK*IC]EM(;=81*^+'XHK9"N&PNR6<=L6LK+^<'/JR+N"UJM#C*3(3C]3W5\\ +M1BOA?)J$%DQJJEK047)8I]^K)@+QU,YVI!G?J>[0&VFJV*XC(^J,2_5!$\+O +M%S.#C-58Y(JLLE'*N,^G_-]9$L"X844*QX"M)3F +M03)\,YGMOM[K;9Q'NG9+(M\@S%[TY.@M#R);ED%J7XQ7(LA#D9SLSUT>Y1;CSK6%Q +M(_S73?&D$&&SW`'9/_L,11OGX_+@0VF$0/6+JD:MO$WXD0EE#.D29MU0+WI41X"JV59L&UY]H1^U%I0;&I%ANJ9.#X1/,^)LR5M^&?4SF4UG"]VSK#0`1U"!\]5B%0_]I +M2.+S@M3+\$&5OPB2URMV@VW_2LP2'_WX^E\^FK^70?LGE<;$1A()=8K/ZGG/ +M*:TE7?Q%6!K]'L.^VTD"\_9G1+20,1O.IH)A/L2SC%A\2T,RO42Q/8!JBNDN +M/]S2SN'?[LQX5:Q9/KN-8U,3+;GK[8@]=3#^Z^N0>FN6[^?A.*&8TFW/H)EU +M!C&'DE1J:)1%F<)[J2;<&1*FE._9R-L2_O0 +M1N2D?5&(KSN5.C`.90"SV1DIH4"#1:LW7W-,]`(RN+_"S*5Q8&`V_WHC]YGZ +M(DXXTR']KW:]ZJVXNKV35FF@KA-,).32#J$+?H'Q7X:G:710S/*I`=IX2*N, +M5[>*_56G1^@<]4(Y!P8N]@"S>6Z(TP_V5&G1)B0Z\\H+E&(T_7>42HDI`VG- +M'#1J%S4TP]7`$A4/.>\G3B\1*OQ^]0L>\84RI<"OH#F)M&?I_ +M8%FM[O@[C7XL!I$#>IH0"K1AO;\J%L)P32U[-#P6 +M]=X3,\OQ-/E8"_WPT-M;<7--]=D`2XW<)BHMHK75+MZHK`E6U-DW=_Z&4;D8 +MZB:4CQI)7ZJ,[IVLX8QJ-ULQ]4\VH1R0L5&'LB0_/C*+A1%#LUVJVQH<-2?O +M$%H23WSQWK:#__2F#%2DJC/(&E=!@PX%CT5$5]81U6M]L],I +M5K>/8-L)$60@=`9>FAP09JVA"14BGE8>)^<<7HT9=%YV8#[ +M,*%T7=B<]P-%W:%EXC()@S7L07@C?5BP8*WVJQLP*9X,&A[N?C_)*H<[L4:A +MNK\]G]G$>RW'?7>0VX?76)@!$O/U/G">FZ-8%;Z5`:Q7&Q3E)T+V7*`I*]DB +M_W&;-5WHX_8Z.>PHD\J3;UF#3`+IG-WT$9P;?26SO*N6OBNU:J+,[MA`J'#S +M^/8^2)NL5&MT)]B;VWOSU'K+JY-MK-J@B,N="6-W\V/LQ+`4Z2;GEB+([P,R +M2``!1VR.C1Z=/Q-@D"PS@J>X35,VU12!FFRT:]G8>H9E]]M5JP5TOUI)8FAT +MS%[?IJ`X9;O%F0>_`FH%(,NVRF&_`/H,\<4/TQKO84]>WX334DWS/#.WFT#; +MGK'@9%I%44R^W[KR#<`""JNBLJ$R8_F#"&(R3\TYX)7,`>@`06$309KUEQG7 +M>"@%LLYF'./RNU$WOD3`P]T3Y67.I;Z=5@"'6FYAMV*/*;MW&-8*/!@]V6PJB6,H53ONA!VS4*'U::J9SU`DZU7B,^+S(41$.P'M> +M[SEH9K?_*WR:RH4+*^<5/8>3_X1?/)NK1GWJ@[8FH;U\OP[6QQ)=SZH'#KC7 +M(=;AI\<&]U,MH@]FB,L:T-@^[.-6PS_$/#IIVQ/,:EG_^AIYSZ+.KHR@]^4T +M"@)WRYBIPTDU@C7&%W=?4LXM90FA;DAA\A'[E'"3`+D^XN^1.Z)CZ-*_$JWK +MT.B9?'8H9E7T_HH[4=Y-W2ZT657=/`RML91&M)=JPMXT3@D^1Y='MD@9=\QR +M5N8JGQ::!<>H_A[16$.OGV?3O9\Y"<N(? +MQ2%7?LX_S7%;#;'UZI2<]6P\0=ZQ-_0`4N3&+__E-=L!V`""\/0+V5)^>Q)3 +MW8"H413"3U87/Z.HP#FYFZ/)PTBW@TY&)J5(GO?4DX=PX+)8A(BM\+0"V%( +M$US?RH]V8/H/W'UX@F0>B?9/9>'3'O$P(M#;TS/'`I@4F0'?Y-BZUZ6-`?VK +M2-?>$J\%;'<_]8GJ"*6HL*IX%'AE!9-X#8:#PT\B^I(:=DE4%AP)=O2'.ZNI +MQYC%-5<9`UZU(ZW76HJ?[!#CXTTK9."DJCT`6%P"4F[DTT]OS&>>V+%X.1QT +MNXX7=-3VX.K/&[S)(I_E1D(6I-5U?>CJHR,5IJVKZ,26:C;=>@WG;#M#?(-? +MH3.TZ^\ETCG4L@N33\9HC"=\%M$/6$Y3S'#>5B-E@G/31103K]'6I**6@UP[ +MHJWA'<94*Z0#"+>DDZVAWPQ>P7O^6Z_,V9//-'[\'B_.4_V]N/Y((F-B4CYF +MAN_YC05=>>I6VC64C:YMQQ)U<0R +MP%>@^(M1$7,PQQ8+`("802SI!"LL$5;MSL`W2Z(3D%SE +MCAC'=B30P?7D$"TP7)-O>#6']5U@LG%*8YRIFUZ*6D;'>UK91?_^=HDD%&Q] +MAU4V?9[AC$<$%)[=A/8C@4_[I6S^;B*`/39BCE3OVE4V-^H?SKS*U#^(VV;Y +MRP<-3^M,T04F`H$O+$\%):HA21F0\0HF]+3Y7>_,3YP +M_/+=U?_2&1N#'SX>'HM#\'"5]/]$C[7^U"^K475*.YJO-M=D%JXI:4+3V:]2 +M?LE(;Z0!?=A,?<\HH>`FRNZ:)ZJ8@)7$.T-)1:(#S8:F56UU'X*Z%EA4:S\- +M,>_KMUM3>7Q/]:%^+-&]"^^4+P2,[E-70?W3"KWW%<_!RJ/"V^8E04:M>5FU +M$H3:V/N?FY;6=?PF"\P#XFKT+0K.45%(`4J@=4F_!:$3/<&>ZCK@Q!%(1>J# +M9I3KGLQO2;2K1RJ;IY?H73C-"'4@(`#_%/CF]8"=BS`),O>Q5IDGKJ*&K_&) +M%]X#VUW:I0\0L]ZNX2"'/I+WDA'9GC:!P-2D0Q".J.L>+>4BY212#QSD1.L! +M*"V(+G$Z]!`+VW]`Q/AZSO$4\.'@PV\$`M/PV.W1^F`M(^+Z0XT::VAE4UF[ +M]IG8",\?>.K)H^8^D$]0168Z1I"J/CBK4F@-^4N#!H\,GO=M1VCWX1$YX0+Q +M=+8)$5='4$6(7'[/KM$Y,Z9H.L*3"#TK-30=;VY9'L"'B_A?M+`$&_%ZK5B2 +MRN9`H"1ZN#9NVX2H)6RE#9]@?],L<$TOGK7T4G/5-J(T6M1>*-G$R55LU0>^ +MN31OAH!_"QRTP)H4.#E2@>&OZZX43G2-)71(WIL-\:223%YJQ>>1PMHLK)J* +MDBM,HI75)#D)48Y#QTS[GF-"=^IJ>%%=9HH.+%5FRJSP3:#*!U'=.B*AH'ML +M9GOK.)S9=B9R,Y0<%TVC*W%49`.#%$O(HM7\<[LSK=!55P.1\FS:W"DR:LJD +M.>J2A($%_`\%-V.Y*?A$9-,3&5L7W!UGS-L)^VP.6'F4+T4&$)(X+E%VVWD@ +MG.I39S\].IL#5;BR05$_K;4B'STBF+4(1N;+-I"WDA!F6;R$B0P257U*EP>T +M\\[:>+PCMUO53&0DAOMKO[25P_ETM?/*/'0`$O/_F$>`BCRHXF7?O.4U[7-# +MT93W/I:8,I.`PG=P[Y]@8#\:U$J^PTB7U9!^1"K +M#*6T\318.!RDM=H)PS94,_W&)U=*(61SXR*26F\E\4S#OR@4/5TBY&M\!;&! +M*612LS`A2SBKPU8>W6WPFJ!`E*^#Y@0O&F_/T`K-BL=`=N1$)V+VHE(@HE%A +M,$O'6*S%\S^CVSL'DOUA5YTRF5-?5\[IU^#ZP3DF7;"5H$5E3L"'^^:9C+:A],C>`?':8Z23%W]F$4WXD1H`&^(5231#9NL9U4KK*##*8)G +MVSP';\I'(-3Z06*>^HRP")RZ@;6G$NL=),IV'9OW!B\;W^]X+!Z)@^^0Q.K_ +M-3"R?MZ7,XOBS^]'H5C;5LU!PF82?6C,Z]"$D7?4G<'H;-N)`MY84LGSE5=% +M<[^D78$>"U=C_GW$\%-#Q_=)F\195$A4+*+W$S!A_.$8STZ%QL^&=FR&]J8_ +MAZ,Y-)3\]A@J(5*2GNV46P7%]B:-QF0#8W(3XDUV:WL#UMD)!#8LY\QN4G1< +MB61D&GO$E(VXR1LGG$7K(KXVA\\#_U'Z2`8#28%FN<']=(FXHA+MCK^5-_2DP(ZGI&.!B6D;#8' +MR[R;5;1($2G?(CI]3=U%KF5BQL:JG,AQZ?!TU-@'^\2'-B^QICIG_E:/#@M5H^P +MS=X:UW%M[JQ_L#"FV@IT0APU:4-_">9+:TX_`6_[Q&LH]-9.XL2"2DRVS-RH +M-5+\%DY$K50YR'K``K_!@NN,(!)H5#L*"/'Z' +MBLKU7(:M:R9PG'H](X)=*[O)NMI06P!Q8R/=`/$T-9!#V5"L +M"Q1+"']S8]2Y#P"=36V>'@V7%/31.!K!3T[=..P/U6DLB.JI!T;Y)^GRL +M_C[)7#=?]L_7O#!7@-QVZSB&Z;L&#`GU3I=CIIK#8#:]_%N?\3'M!CF,BH\# +M<*='B5ETZ=L^]5[LGX4E/%.P,+L\N?0%C@1OY'C/UN;"?;UH%CWYW3`BL*R< +MG86&7JH?*@Q[N-;%NZ*.1)4_]R1-:?QB]-)6%RCX8XV#_L +MU;%.8-W!CJ.S>@Y`Z/;)1"'MS;7:=5#U2W7-WVLA9OPM9BZ*8%;5K4B-?S@J4BM1/9%=NS7`.O6; +M('5BHPC@TYK6R!?\F0Z:&YQMDAI*H+&$TEF6)0(P>-E`]WCDU[Q_@S?4CH5G +M#VQ'RYJD(IAQ2%FN8I"P@;`UM*81!ST7RV"3I5"B/KTOEGF3,SB%IR/L6RP> +M<33P@2-()2D%U]\)UZM(%J,1E22X$#S"1X^LE](QQ\=*[,[@!7G&WQ1PHE.< +MB'_%O\]S0#B*2S%L"D6M#38CK73U]MQR3G$&Z.LZ2JX>=KQS>#SN?\^ +M455@)IQE[[<[&**E--H6M-[Q$`Q+9.*$J]G(JQLV"UB#T4GC2XK%2W\ULY^B +M\6`\"EEJ63+\XR_IQ#$&L5M4X^8`S?N*U/4J*5RO)!!\HX5=0@T$NUK<(S)@ +MSWIC5J*>^:"YQ90P32L8%\??H-KJ0N/P_J+]@:N84/#@'TD25$0076."T42K +M!&"YH5T?E\")K3TK.C#*>EZ +M#C`+R__3D.^$*>Z-8&@5=/4S0-]7\$"C0G,2YH.WRI1%/>S!/\%E8NC\&\3K +M&I;`8WBI<_BR"5R-_Z/MCJ2X*59SM8[DV-Q<=RH0S:UE&)T#H'C!WN)]+8,= +M,4V:M@J@U.JA?B@@"N&D,!LFEJ61=`1@\$8+SN@L!4'*[50OF![21 +M7.5('<5P=,FO'OT"(=/J1=8"U[RA-1>66@UKLSWUN\Q\'^U$MXD-A/E5O&MX +M5S8]FA:FXI6@=3S!"(L>&$''A*FCQ_NB6$+-LMUA:R0U'ZXLI`:DTWY)9A".-;%RH3S2TB3B,Q.\B?IW)L5^3-(>: +MG]7!P-SI.*2W2]G$+KG%M0^<2:0YB;EP:V\YN)*QT%EV)0R!X@T=54QK\A=E +MW>KD-3)KP`>W5GM7;GI!?HDMZZA=OC-;MS4\2]%KB)-JM-.R_<-9['AP%+CG +MX$M^BG9AUYUJD@;+P-+`!9:4D!E].47L-(\>B@%<^;ZT&Q;(]B;S$[ZW>%2X +M786#_V=.]6(E/U"C)M-D4U^8/ZY,,I1[*D@0);&*,##[@EBN]==NDDG3@1/) +MFYC->M`QA2J>:J+Q_0;-7'S2>L0&O_&9M2UU#NO3\D1]>_M.!:)NI46;9XV) +M2SPRIJ1=ZJS'@`SY%VO0QICS/O/Z3)GM?3:2D:WN63D!H(JUM9F*[R\Q_%1 +MB%]L@V9;#Q)XGW8@_+)4BT#ZEE"7$:VL,T]5/HPP+ZTB$V@>'FQW,3N +MNJO*FBSOF:JJ>M>:=AF#_XGPOJ*0&*>TS!G;DXQ$X@!!61='H9*\_G$*63TP +MJ&TO:^'NN/;0X"UJG_8J(8+Q)S/##MR;F"B=L9>A+:MA7FME"^<)/\@G=%'5 +MF'J4'M);S",.Q@H_@N_/_61(-'D;F+.-<.WFB`_E*]\I&=O#>NS/'H3@B<2$ +MO_VT`,$C=E^!>YO.=(R>%>-/FOX\-%-A!>%Y%J:$6Q?J2[RF5R(U%77$!$'W\K`V$(_D;U7^"KL6 +MP5(R8LJNBG`C;N-XCV(7R;;[B:VXLI$:U\;'KV?QNH-Q*\MGTO0LG-\NGOUA +MMY@010A7.YRS0HSV1652GBAT7^VQ'X\2ME1OXKW9AF^)`[9@)$7THOZPQ:@=M\03YC#A,'ZPL +M\$S#>-R6-CKC3N,2UGV;P[W>^@(%*F&!&PC)076FN:VP1G8?P]:R!-E.O6LK +MS$WJ@5A)(KB44_*`F[V:?]!/HNHP+71&.G_>?`,(U6U!;?+[*/F5D+'CF/3=U@K#E4PPG7$A*2]('5W4.>2 +M8Z[O=I>'+SD>+J28>%3&=-4?[#84:9A8*H'P=O)[ZB8GLS%0;^5IG!P&:48+ +M.EMLOF=`9UH-%+7GN2'!EY\I<[M4_7\H>O^K3S`N4[OL[IKK,8!LW:-[V?(L +MKX^;B(^6?3,R:^N('"6<%M:$IUXGW].4`MI3JH4#_Q+V]$0^#A[C?GFDMN3N +M*WH9QJ(B-H.5C&C2&H$3V%&;_T`1&Z8V<0-DA286:J[<2_&+8EXZ'8%>7A"4A9!(>U`P)_<1 +M8FA:(\_?YN`FK"V(-:_`:N>V;&'+O\.P_B9^7'+&E'-54]^M"/[Q,&UTE7GZ +M51XNA<3"B0Y;L-+,%NB4L[\=<.FN7^HPPWZ#=@;9%-97A"QJ!+3T6ZQ%3:P\ +M:)MMA[-23#^QIXM7W]6B/RYD*\<,-P#D;67J#Q,8]UAF'M(>Q10=J5U0Q.;> +M,Y$-IOROK-I\50_62,$C?ZI0T.7IW%$&N(&9V5X/":XUSE\XRE42PMR;*W&]Y?%U//U_QR= +M3F:GMWH>GC-J%<&4J]H!'"J("^\^,!=NEF"NN/\=*(9;;1M&Z>$D]5:4;)O>%;)^( +M=]9SR2_QO?:=F;LY/'-"#C +M;EN%CM_H`>7^">R/:A_93`D53F>C=%`AUO"WII:]G(9MLXK#QVB1I8C6<]CH +M,X_:PO9FZ"O$D:?HPAF"#;4Y-UOXC1[5]5HZ_78X=@9#\0#^#A8I0>$,>QPS +MN5&VAQV2<=KLN/M;#ST''.LWJYF;I3'$E!E4/^66ZLV7Z`EPQK@_WP5C>&,B +M'M)_!3$;]X2A/WI>&M_FC$FU1_"EW-JX*I9^8!OTE7%_"WGIO".Q`-D>N7P\ +M8?QK%77E`UKBF"?>F\3T^FL&I.S;M6XJY'F4[,?&!6>;.I(6RF$I`*%XT\K6?MX]F84?WTH?<[#8=1\-AB+> +M;5<#[S92T;TA043P`:D>R>N=,,DSZ1@MBQ"6Y6'[8=\,(CI_*5&50QUTY7(- +M@[Z5'<=#W!<-%4G\MA)2@MGE,5EMM;Q;`OT@V5BC2??<]..:#,E(V2RK30W!V +MC7YE<##VZ+K7$Q;/G=+ASV'L:-?3+BGUZPS>I92.L47O:!T:%@>:%E#B?F!I +MV`^K@`7_BS-W!H*$$V_(7L,C'YD)IN>_THI+@M)PZODF +M#L3X46&VCK#>&TDT#S&*9#2Z1AT``[!^T&.+,GLZO#S-\*"^LRS(SN.F>HEZ +MJOB.D#%+;HF0E<>8G/HK4L(EHK291?+7I3<#Q$6\K/14P5 +M$XL]<.5'>D%K?M&2PVF06WE?STED<+5P>#C8V'E'U\FG3@"86YBVBBZ-F1F3 +MK!3__5*4F0E(R&!V^X"&O!M&N;^FGY=)^#I=E>H\PO+Q]F2M@/4.!Q9)GDU9 +MGQ7\_PE8-Z1E*&3Z@Z#JLX7VGF8WA]1#AB*2F3:6%>=?A)F[>$8J&F@3>7%[UJ)(;&^5ZRS?^L*]2&@+&7G8 +MRM=.+J/*7)5Y$[%'TPI$[/:/=T5ZZS?0Z,XER/5"R9$\BVB&<3*LK&_5NA\6 +MI0:T--_T+>A%V_7[?Q!XI0WG1_<#:%T)+G03C:'M=QMU^.M3?BI,OC5'(Y@> +M."!2YSEAU#M8MI6W!?C#W5.(JX-%+),.JSL/:R6`<1S6M(_")=/=0D6,<9,` +MYAV#@QKX946ZRST%-R58YL3UO4$_;GK=TEQS#-&"FQ[(D1?I7[89*_BQ)+%M +M=T-DU8(\W<;$:JG/04^V3(E8P7,ZLJ"N8WYXZ&O$X=N2+CR\H"8(SXF0-40-RJN&88=Q3&XY,3<=*&SK',]/E5Y+:B%UTQ2 +MVQ[&X>A0V$+M?I(&B+.-S+H9,FN^.'=?8'*A:)'9VU:9MZ/KWEI'HA9FE-;Z +M)4I<2!].[_>%^?SI*;"D#LB=^?E]/0L-`7EXCE +M@S],FYGCN7S:.FV`B-_,VV:7BOO^0)%G1WE0:!H"&C.9"Q1+DK8D7\D_&7#T +MCFL]WM>](1Y+MRCGK]S-JONQ'+WXD'R9L?ADG4P=?&?KI3%B.Q\QW_+T0>^Q +M-8A6(A[M:,#"A%50DLWLN-WZW-#52P&7)%<1@#))R_BQB$CL'6.+%E*J&*B<.U881_?=YBEU?,\F",2W.--%%5@33Z#51(KI;[*@@^ +MJ'$!#SU04(OZ`=[TDZEMD_=[7RV<8R&=+71:M4<1*^W5K?GWBHPU%HG:` +M<';HO.D?%B+[(]18(3/BGGJ3IE/$\0'#A1_>1FT-NK]"M,%I:\QN^\-2R@9> +M.5*SQ'C"F)MK8A4"QMF5@*^*7V=:4);M>*CN,.-H_$+/[75RF0GX*5Y=K:=LZ=SC*WF>PLW6%HN+FJ>7NTX/%# +MPG3;903"6.:A:+'OYZ?;>W8J` +M-BGPI-%=L,P*O<^S-O[RE\-D[:#09W8A&VA)M[&++'T);2;%K2>5#=-W:VAM',(C]65F\@1"#=(,<%=!N,=)T5`\LLW'.)Y!\W"N<]Z_%.GO1C8.BUH5::0/=F +MZZ8?[G^=8E17*-FB0C//OG-<4J2O\A<1%Z-#1J<;ZJ-^`CS!<@<.38^.>VXA +MSSMWZ#9&IH:3`H`T:3-+/=%NDG/P!O(4G8^\ESCR3@&T*/Z5I?Y0Z.Q!S=3, +MO=[_-LO:03DIG)9K$IMLCB2J)"62`":`6@'03?F.D=\O^B6P_W +MAV*=[]UQ80'/CTV;OZ<4CJ"OZKV/=9EKFFXYY;NR:^MJ_M%LD"OS@"M0RF&- +M<\+X@,BV$#::^ +M(S_/??QV/EK*#]QH:9?":[V86D-N`&M3"QV>]!VV>6=?X:!GVK/>,UG';!,K +MU%E"L<\@CT^)"UEH)T`Y"&8A.UP.ND%"*+W*E/I7NOT_[?;!",$19A-`5,Q( +M'D^H=E;4>W(0HYNA`7XJP^A7SZ7QM-5A?8%U:*>PGC(\M\R0D]4*L6D'%0!= +M^(^[-)U6I<:*'%L,X_&FID/6!AKBJ_*!2W40E=)IJ2'_4("2^LMU`;PD;_70 +M1@L@;S/Z@Y4I`<3%;J?]HSB:BV:HUL;O_"*O0@V,^9C36;!?-!!?3ATG%719 +M+M'NSM4T6NDB'5+XVK+D7!_M04"03ECL7C`3Z9/B'8O,4:OR?/)L0$[Q/M4P +MD_;=/,@VD,N6R"?C[TOS'QR$@0!EW37@HTH6FZ<6&(XTB)M9*A@_2D$FO%""&#\ +MR.QML27OOU8?]P-N)::[_B+,`*.\G8 +M932.1^@7/Y_8A7_26"UAB.2AP3?(YLAB\[SL)2YRKH<;A=TC%&ITT:.Z!]UC +M=`JR"#)^\<&J+#K'V9@QW?8T$-N(YJA;*`08QK?*(#O=U@7-['WA>M@3-L>2 +M.`;4`]5:?CH]DP[HH5/1[O$?._Y55OQLC=RD;TZ"LR5J=$(TS4+K-NK?3+=% +M!+ESX=)U0UUU//0V..P@;WIN6>A\G.RDD,X\LL2@_4D)J?)BTHL.J=/3^2WG2O!? +M\=/#THQY0ZXQ6DD8+[2RHJNL,V;01CO:'XGR\TTO'/8-<8/`5Y# +M\>JDZGP.(1846265##VQ")E!!/`D,;*VO*R)WQ]!HK.!/S]'=:UIB/*7$:ZK +M9TO1+M/1_K1(QML>CD3`/O);FY4C!HX0N92V2^AB1 +M4%0%0C0K#X2!^E:/%!SUQ)N0\R/,O0*#,\%JSU1-<^*5S`40`[F@I'G63>"L +M$K@;HDH,=&K)[V,V69$0YCOTFLV$)%0[1CK9'K9NB/"9J/'M&KPFA`G],=:O +M+5`;G;TEJ=6]E$[ZD&%XCCI7[%8B*3D"LM^5@G2]&:OA.EFHGLN-^SOR6DQ0 +MB$T6@_!PL-`?C=JAJ/Z?-FU1/]A1;'I&'W;W.UH%<[A(PW?"?5].UISG<6]] +ML;ZT[9P'!2"CQ?+E10GM15M:U*XPWA<2$6T +M.]-.Z'-PH/,O\L3CK8!:O*S\HT*WCQ4JW`2GP6PT7N!:+2S9!?" +M>,O-!6W6YZ``C-FBJ(GD8<-)+&]'D"#VU#\4/1$-_FV5L0$-2%U9N3.R>Q(X +M@ARP=;)]JE3Y<6>M`)P9#'YX`.$ID,6(^15;=1.7QN_]2%A&R_3CP5!L[J7O +MHF@6?D>HH^M'6GDSM:1(?]%:]N<)4\.QV5.!M?:A,V934MNJRT)9BFNB/0Y, +M>Y4FH@4(OMC1<),W),,9J>UGNFC.Q-.ECA*AP`P]OH*%CDY8%BOLK]/[.>&\ +M"PZDZ6\#)*'_?EDM&KL4D-%\*LK@@MHA=,-D92]*9PY8ZJBS'4?\A0U7+]G6JW!C:ZKL!4HT)XJ +MHO-Y]P9%[U[M_)VEO949-X%6>OQA>^O0E/:#U"%ST+8^G/&?!TUNCR"S(!H@ +M'ZZW)U*M88PQ?2#*I;T8%+G$UH-`!T$[4`^*E +MO-PC4=-H!X8QHE-5:KZ7A1D?2J%/7K@//XLBK+)?0U[L6Z&U5*](*0<=@F\, +M`(?5V._(R%RSDV4?KP%DM37"PQ"1N#W4E.8)I?);QO#0QTNYL;2D0?7R]R[I +M/HS@3#VXO!F4-#`G3Q$;H*M]3+.9&3[A&XB<(*(RG6RA!3>+^MR/1VGR7MV@ +M,7\&+:'[.!FL:"C@D8,>YH?+07\W#PO%;`LN)9N)@@BVFK +M#[3ZR*G(7<79K@0E=T0SJ-YQ@I`"/K +MFK8'=,@*]L14&)PE5`.^2JY\RQ=9(6G5_?=]Q72B6\IC-A4$-^LR/0DX9WXJ +M=22>G'D%2-R_J-M?7O0D>+10AR`4CC-17H5*4AHEO'7AD-Q9I,L/'HVQ(U;G>R82+X$8OYX1J+%&!BJSUEGA) +M%FPAC=BF3$=U&C,:35A'^@8'5Q&?1/V^KXS:D-HW=F'ZX9`P;DAY^.WJ+=C4.I6Z&B( +M?T!EFQ,CJ+1CY59_6C:-?&X-16YBXI%+WHPYNB6TXU&3&<)]W43928;?AU*5&M`UA%'2 +MY@9;@L9S.SQ&*6`XHC?3LJM#QTY`\>)CV]RB2KQ=DK0>D*(AD*2-G\."&#W' +MV$`$1'M7(EW+>_\-H/FA:XHN$$39*FABW1J::!N%]:$A0_(#B^!2^@\%RD;5=*P2J&<"T6#IJ^@5Y+BA-'2%/WCE?*A9&+Q1R-&,+']\\1 +MO\XYJ0WGS7VD%KFO`_F\^Z02*6C[2R?D7G=Z<1D]4@2XYX2Y@GOVRDO_0ZF@$HZ.U8A?!`/!Z=%EB*0NTZROX,PB],S>? +MV=`K?0!+[ET)RB_T`Q^B$WVXII,84*`<9?5^\V-F+!(46O:.F16RLGFP2G;, +M4STZ^I+>70\(8U5WD!%GTLE!RGL4]E1BD^"\/)PVVC>?T=ZLR'?P8NJ/#P$[ +MXZ;X(XO7B8X\\!?3TX2C!U4='U'/K2+5#K#YY7CQMV,)D,BZ60OX=#LNC81\ +MX]">NIQC&6^'%(#^(#ZBU*0P?Y3EAO'Q^U(FU;1DC`67/\W:-=)0;AKR='%[ +M:W46Z/'VP!EGM\/#C=/H;[6&8$`'(OCJP2=,*EE6][RU+/3A=)\?LZE45MQF +MQEWT1H3*^7Y\"9D^>1KMRO#(,#\3%H[A/"BF0&OK7D[K[-$T6W%V +M4=@]?NGBD\]L3LN[-:(2->A<=K&4357@Z,#T?A9!6?0=#^5&/`\J)M=[#5M% +MIK6*S%JH*-'N0[#CC)B69FE,>I0-@J_PX&($XE4_X+9]39FV;.+S(SES'AUM"E_\YO8FK3\>WLK +M8D_ZYI"'MDT!2^[GILR(;9O(HG(;@\?P0P\">8P%2(^4).J#X:H5<%,&,F?8JP/= +M&)MNX^0YB1;1KZ1'BD2N11UU+2!J<3!6K7KK]Q=01/9P#B6L<@2(5#X66,P= +MZ.#MN1L^2K7IXYIA+X=`S[,K7W'HIB&)_W;[<5:=YY;TKJ_`!]D';#=/A)28 +MY*'C,'!48Y;W'=];W$S:OW(57*\\(2:C;L(9$J63$Y]4PPA;"CLM]4?5,#_/ +M*&P>Z$'9<4+P>-HPT@;=<[QNNSLV)GY'99&UXJ-R:YEQ.=2S8`L1L#@RA!1S +MF,7^@V0$9+961J0ICX3MJZ8G!M-:R4`\N6S%`WS[<)15;1FOQ4[Y^+\))RE1 +M7>K#]UZCO9O>J$3R3T]1YCLZ:!P@SOA)O5WTE +M\X.U_19I`D@UN['S6#98,40XGT/QLA3OC0[V0LVE$-98'SMJ$=J( +M1Y*60Q2.AVZ5YN""S]OM'&'D7@90YEZ5N`E,XQ[`NA*)U_W9RJ)XJ[5&?-;4!&O9$X!1DV3Z!IISR +MO*H5&3Q4Z.REN^62I'*W&GWIC.$ING)T/]][(!FG^QMC[EMMR.7,O32G`?$J +MV'V_V2N6J:@,&2M`:M^1:*%E5C>C,SNX`!9*#=N690VM_0BA)+BY:C%#-OO6 +M63>I5H#^_24.D68HWH3+5,(AC6IQGT;3<)--9+F>_\9/O$BSLUGAX=LD>3E; +M6WYDVK-9G>/Z+^O&U7*+E7QN!1K"Y3)66)W:""G'H0\/IV7I)E"E!S5$J,+: +MW;]RP'?ZPWL4'R(JX@>=,3#A21<2OJ@S_'7;07YK0;W1L'!-C0CP%2`]^DZ% +M:&R7#H)ZE15W2E&>`R!]0W5>,&'NLH`:",&*U.R>4:; +M.P'O2_FQJA-6$T$^.\I"+59'[!Q^B3EE/JY^'=_?YZ/CY:/X2M3;PS`U41Z> +M1\64:W46/$5>"V@_JHM&CPQ8G$X&:`.\(6*_24[II7%Z\(1H&.GIEP!NL&T& +M9=K-3SQJT5(@T5:T:!$<2.R<[)W!O_M/6T]\NCY@JIDK*F&.&\[LY'JS?,7, +M[$W[B'766'H8VIB[(\ZS`IQM'L^+"UTJ/HI9R*DI#%CR'-X'?2>Y=U,+DS.`1.3"R),U*!FTH)Z_!5F4]W*$X;G\'@Q; +MR")L+4YP2_4,J-8,4!*`EAR*R#728_U8H."Q2!RO"\-':@,6WM)U0ORYORI,O>;K),YY_MC?0^' +MI"OTF^H:/>@&8PML#7;WK-N+!!4G5ZXYC:P^[[7`C^NK+T+P&^?T3;>^KRE# +MOZF$M`#2=,?_MLF1?LFWCJN;)+Y)L3G]Q>`^OGAF>0LZ5I-"Z2>DDI5(N:MP'"*E5('K!OU+(PNP/Y_F8D%6@7G-PQ"2-O`GI@CC.&GB^"[^6G\M +M#BU1,+-DOQ6?'X<_]5T&&)4W]?YIL&_S& +M1;Q0DA:CSA;1\RL,;Z.-4<3FY*,A4;>),*3ZH@G9`&')2LXIS%4'E?Q/64W< +MEGYZ0/?87K^XI0X7]R6NCW$>1PDPA622Y<,F&@E8:'3-80J7I3^D6?Y'PKQ" +M%%P;)-A$:=;D61E!1UE,9J'"0ATM$VE..E54W[%Z<]?C;I.T;4(_J/^$F=1G +MP#4"B6*^0>YE1N%C$\=UTJP>-_?9MY\CMP1D$I`%3^-E%H;X#$H0GHF!99A` +MR+Q +MR$$O1*I-O%\NO+_+YX)U-K[RC=%H/7(3Q)DA1J3#8U0-")W]6""A +M&D.*]7;4\?B=6-X!(G+EY&OY;>[Y@KW8BV)CVOV]+6Y1OJ>BUDRX&+34A?@)D8#%CZXO1@WSN'=PJ;<.2JF3E6P<^ +M`QQ)$^8(O,RG#]%@L+@5(ZUB'F]R[B&ML]GKS?IP:$U=HCL>ZE(B1"+"+4!\ +MK,HA*Q>F+2HQR+FNH_\?G+R@>.:3JJ3CC9E1M5\?=4;]@-PZXRU#1FH`V**X +M4YE:_?DH-@<(L4SVT^2G;@N4Z3M4OAE-?NAO?LR^,;17]KCK"][,G,#TN/T3QX +M"%T#!YH1]-=[F@_K<^68!*'$N'AYC08-$N-D7T.@81_V*_<'&Q_Y/WQETJRP +M)>G#`*:07X```GN)ZV\*;U;?9`<[YL3`@=T$ZRPRZ[YC'<,KF-)4D< +M4!ZE8]]W#GH-"_8<_EJ3">)P?6;)?ZPMH03(@F2_VJ_1&&7&QR%,ONH8'H:Z5IM)`/:J_X474ZZ[N<0G=VAWQ4R<+2R#0%6"6[5QV)E"+=ZO^Z' +M]0S.@M\?-%G/(-+:1F-376@^.%$!>/8+,0#WQ--BB5G[+#:RMPAN(O3.;3,G +M9PKBEW-7**J[:?EQ#H`VB9`.^]JBC@MW?(B+\\2Y7)-1UIL:BP6)7Z"TL&(- +MN=M>,$MY_'#PG/F`-/%'/8UQGLIUD),479@A:)OA9^;`[H<3;%#EVE,Y_595 +MU:\P5X%NW>EAH@R8SR](M80K_B:*!AKB39$1$MZ9OS2NDVAU^W2$1(+_BR%D +MY1NE_F"B/]^K6>8;*^K^L,4LZ^2M%HC&:>JQ_A?TLGXA1N=.YQU`HG#.R?9Q +M`74:C"0O%E4ZZY?X7J9/_<6LIV`(:]AY"O`RNVCZQ>R:DU_E6M,)L'N[=P4P +M$/RFY'Q&WZ6U0ZUOEY,)9O3K##M!Z"J5>'27+V3@,^;C: +MZ:HDFKSS"IZI[8X`11[2&\R3=XH+29Y6[TXU0L"PKAD3G=)ISBNX'@`="N_+ +M_>Y9["5>QT=Z/X[.PXN!H"@QFMS!AG@#J0)$,2]K/?R'O:IN3!X8Y&$^7G\2 +M/=U5&C5.R1\D].XVA&*2IF$`K?"Q:&[&.DT*T3ZE]2ZT8HK185E?#'922MH' +M1>\+1I1K7.,,Z::,I4>HMD;`V"H(S23_%[9A%PX]HVG7<` +M?#(=9L4^O?A/8_9']#[:7"HDRL8?BB.'4;"6:U:_5,5XF?XOFN+,_AC@OC;X +M6V3@1_.6TSGR6NFGI4NH3`*)PX6DJ83B>#9JX3?RYXL3_#6ND428#7!*<:&` +M(P[#I"@:2MKN?!!3.3;]#XX;H5"YL3BN"GS>C7RA!5=N_0$$1^_[>F6*"6 +M'?E$L^K;;^$N/1J-5MXLH)[1W/`K-4R&* +MIRK9H&.OUI"R,B(T!5@F0PVNMGB3;HSPD]N1?7$E_7;P`4=OD-B[4\R\W5S8 +MXG9BV7:\YXXIZR=H78ZQ5LQL!?E9JB"6#S=[(E2OKUM(6S:W/?(WL-41GG8W +M>=PV@H2(/,'K[`;Z)AYKCIT,`ONPF7D?Z;V)C@G>R2R_XW0M(^04*)^;=<:9 +M$B]TB<^PH74^1).I!76%^8^2WNKF[[H,;.XI*_^"W!R":#A%X'-(=$M5-3@E +M"#LJ)2_R$P^JEN?QOK<52["WPEBH9.%\>IS89[V=[Z9QCDD36Q3/N_3)A&P8 +M'\]%FV>K7_1U.N:JG"T_T7F"%D:@)W6;S/W?_S](RM%BAE_QD/(FW?`?.VRM +MA\4TU%8,XB1XQF[;H=]1VE3RA7@M2-S$79++\DRDS,CN?UZT0X;IT:FP=!U[ +M`6J_/#I_'RT7G[]$Y=^J962_`@=.C)_>0K=+D-GJ?2?U24]N*02BG&.+.*O^ +MB9$I=V'32#!&XCL)*&QQ6[:W4H_\,^R.Z43K!E.3'\_10`.=ZV9%M*F`7%KU +MOQ18.L&PJ>H,2VCURH&/@?W&>]0R?.]#PP[+,UOL%6-_T\!("8!"1[U@T;;2 +MNT036_W9MR*E78_.M*&BW\0A@8]'T)"G$8PL>%.'GUA^Z,*ZP^?XKD/.=BZ5 +M9Z_ZA:TS7JPGQ2FHJ$0JF0LJ5U#:)`<.K8LAG7!0!%0 +MTS*$E5$M^+A6_Q%QW6B[^T3BN`J1%,5G\=10\O$HS5(^34E/`._$.]_H=?4S +MDUE*=`1E^#^-[V+@`2ZBSLJ3FBGHRCOMB4W)[/HW4;T +M0XK!U[&WC#+M*`^:G/7RA17X853L(I@8>2IEDV4PZQ.RE6:H'3.7K-*\O#W< +MCGQNPC-'7=6,Y.=SX)J!V'KUC42V*<)+I!CZX.,G?94N56P_H!S8#&([2C/C +M_W-LLXM;WRAK^3TP(%;'_AB;CZI_K1]K!;E%4O1[HFKW'+NU]?\)DUG#_=9> +M[.SN<`._M&^$AO_!&[&0R\*HP$T*/?IMB>^I3G=P:JXD3\3T<+#NVQT(FA!K +M\4Z+';V8"@VD]65K2RG\0JT_AR5?!)[^5)_0[\%K("0(SJ=>OM"68C^@6VI? +MV@WP&<7HQX*K-6L`@XMCXBY&T2E@A`(Q6J7L.O5ED[8,4Y;,<1D`WY,5D@!X8(5AV#>PG:F"!]!* +MDRXCPD!4Q&KQJ\K9=*GW;0\++-6(,IJV(F?(KM^=[7>EE>&MP!WA +M5V@:(!(HILQ*JM:8H^?!"(:MEL?_`!=@XNVAK>SJ@H,3"L->RXELB3A$E$!B +M08%?L!35WP)JX2_%I0B"`+4Z?Z;NXD91PABR;4$.2?#IL7TS-TG;Y&=)QU9, +M1.TDZET.50&-Q_@OR$.D)2*<.CBG'D$B3IJ +M&-'_8T%+15&L2=S>!DHNYM0*54BP)W?B,A&[)_*__*530)]9\HP4>#S=BKZC +MI-#VA/-7.]2K7A+:X<:L4F^GZJ&>B;T'!E\T^H: +M#;CMAA%7^"$#-Y3CH()8T),2-WBE%_-@`A#%M&?O"[]1;R1%SWC@">X2%@%4L!'3>W#-^@9D]B@B1=< +M/>SHR3UB_1O&/ENR9NN;9\2:6LY9R&CT6%_0QT2ORP#D+S"Y@NLZJ1$W%&\P +M#^0V6]J):-I-HBVBF$S> +M/DSK]Z=5#_8PVTU0L7E-N?J3[O4$/ZZ@F0G(74!/=`9\(>/YG:Z^NH3XBHD> +M_\2D9Z%B`B"*BMBM0XI[]'3)#4:84I*N#>VKO_(3[GQ;XAD#ND>=R5R=&"*M +M;&.=;]JS)@#!MAO`"\`?O@-?B?*N\U$582IC5DJR3D!$7T-5DER<=DX=6J@T +MBB]FB$;KJT:S@U![UR'^[4WX'E#"*?W;_2!#;A9(TJ'FV.Y61+-C-[!S:9S= +M#>UV)";7ZPF0B+Q?-L.O!<Z1F_CC]C`>B +M4:&I>VO$!(95ZMGSL+]V-/;OZ8')X_K,B=:ZOP)[5QO@UZF97X/`,_7M@EY8 +MZ`ZDA*61Q&^"LW.A(=NBOW%_Y]4PZFK-3=ID291?CF$M4B[47OTNZD +M#J;P-T$;M2ZZ7LY\DDYH?.`N'T[ST_0T3`(D9K)C+1C%T31./X@'"2V6BV.O +M+H#)4_T:OPL`=(AK^4S8="]D,6&549Z78=L5T'1YZ-KW.]_/[B9AEFR7@JUO +M2\'Z.FOUW2R"O%'`TI2Z1HB+!]=8A$;9LQ] +M^R5IJ[WX6]"8G]Z4?8X+`/-Y4E6H,\&+&"?"ED-!S>_PV@R?E/A3P][Q!D`V +M=,"E$3E(FHXI:!VYF)$`]$U$?$#O0N8;;YERL!DL!;9J(R4JO&H1PWAEJ<)% +MM=LOGO-DQIW@O3+`$%5H"*\*O@5(!KE-[0/!$Y2J(MM12T:G=?5R#[J]G&8. +M27I1/+-%Q5_;3?.!F;8ET?F#;I&Y0)G<5)PS@ZGVDZC?CS`_<%?B^"(3Y8"J +M5]A.D3%2GJJ5@HB3:`I\GI757RHUMVNJKU*G\!*DW#J/>-'Y%HZ_/OT2!9O; +ME#>L>0=VF$`,BNZI291Y4V751@);11R_W3:>=*?RKZ534T6!MO!BH7=N916N +M[L&IFY`M<0,+A0J0.^DEP%C/1YO/X[2+65!Y]?7L`<-*@J^\VBTC0JU.`$_?&B[ +M>PRP>/+X+[S)6Y_)]PKYU0+ZR?#(\D)X^6=A,:72U'+-.EU06)_\P\EQY +MA\_41B$.-6U1>?`W,'J45#D4$V>-H,U-H@`H)Z;+DJA.7S>I8[)/TI^.HU.% +M7Q,Q79P&W:T$J/HD9!A35@VFD +MBM6NC_(_?IIY+L1J%\GNC4>XZ\E;@PO2"`&2[$Z2(,[5S +M>(J<%:JAHF:\(,10M5^.\WA,YFFZU']*PPV/HPY1$/Y4U5*8V3WY/"G$+I+#Y93^<4*8?]A7>DX"%HT4) +M?]RS*RL-BXT(L'K,[Y[MW4&^04D].UOY*P+D56AX>5(I=C9NN-7OS5M+VI#= +M7WDVN[U3M-.H?'&LX;U/-O/[HNKLABS/GE')^^; +M)?Z_7=`VZ/))1'[QH"P4TLA"M'BFO@#\5;+F5+;G3&TF0@J[O^/RSDH;Z-\% +M?O1?<-CMZVN4+&!344>,`JN+G.M>&QS/%7#U,B6?M#2T^*DHB$0Z%_=30E9: +M2PKV3O`5:$U>Y;]\&_("#24/^A&ESY%^'3,J$@#\1^Y'ZX#X4(0A\K]W%N*A +M]0U'*H2TY6NZGTJ&^B7V)FM +M<'-E5Q1:V\T9LRS#4+_-EMXY']WO`C*19^N70'^N'9N5()+D3`;WB^Z`>8>Z +M^*>K8+#B;/#ROY`)&%[;V4I>$6[M/;!V'C/..]G.\6V1\($*M,($^J!]E"$H +M2@&Y25Z'JI$5D6.!RMD`T!?X)>I\+'R!X3`D>_IV,.BE: +M9TJS!8NY&>:K?;`FPT]G_T\.`<#200^2V:.-:=HZDQG&)(HH4M#TD$)4JCVY +M`'(U3$I;)TR2;RS*^MZL%;B5[(>,R-'V%:,5.:ZW6OH)?TM6)@I'9>K+$-=( +MND6TT$%M-^2@:&Z&3#*T1%Z`ST5Q^&8RO`0/MD;4'F%."QR49_`<=<2G^89N +M]`^GS4Z;`0`H>,C;\?^27L,W3I.OU"_OV`JID.REK)UJD>:,%)PX;_:QI>7G +M895#B0>)[L1FP:`3H)8/'\7.9!3E`E!E$@J\D/*?K@W@93=Q;HKBO+#3!BSD +M!C>18O=V#<:RL87.2L^8"%5/!/0H)BG4N?JB7E`&2]UW46O#N(F"%_O[[TJG +M+/!XOK4J!!Z6(OH8%T$H:^C*_>1!ZL]J.W$OMM/C0:F$PM/L,>AA8!OY9$"J +MQ[C^5:K>!278O_,5(Q>@-T"B^&&>;I81B.-16MU,S>,]3/(KN;0Y@J@O%7M) +M_U@T[?36_%EN-1EH'J8[@,S]$7]]O:R0#-QR0#'JH?U6/"?,6`*A`[VP5&U\ +MA4DR+Z5B>%02PD64<.$?%7&,3@0LHF$TNG$*_<*T?2H$]=XKSXW$P\(=HM&LY)5:RX[()0UF;3FP%\5-UBAO +M9L]-D7:YPB+1R,VYKRQ@?4CWWJZ25!=H8]WG5>B>6C(6@>PK?955>-W(;W,@ +MY^2\^CN*VWF,F;XEI6-:=,/OO0Z$7-U:?<)N$^6U*.;BEKB9HL%"4L(OG*1L +M137_:.QQ)[:G)D289FR/XPN‰P-9T7MBR^[M>RY&SS/-"J?=S0$%J9TR^ +MN;R;R,0<;\Y3^0>).Z%2\'(&TK"9,NI7L//E=[64JY=S\-[4[`@8;^K"^-M(4O]F7XDO4QX._1+ +MP1M5#Y.OAW+YM;_'CV[MT!]G^"7L<>70LX/^ZD#-4OQ][+-C`A+1FFO&T786 +M6"<&XA-G'3`S45FQ7F,+VJ@.>NPQW72*B(ZK@=9TF(*]VES6LM6IW*^PO'I6 +MJJ,TB(7M/*ZV7X)(%$Q#3R?[CD49T%7I0?!-8MWYBR4D0PH9P":C2O=%D<)] +M_8*_!H%92Q6D\_E5$X.''7%C*$!6)U@EA3FA?^3VGO:*'0%R:=(3#2)-,#\> +M!@'-^L`#WRH3Q?-86$;[+9M?>%J0C^<5=R'_D$I-B`!^1SKKDF)CE%J@L@+% +MY'7`:W*P`JAIFAW@YQSN/9@0W>;A)FAS`3,YSGIO](Z:^83H=&MS+=H(@X%7 +M3%P-%<."QO+:X5D6._[42*`OG$P$7_\'PW"^[-[_I%[O67CTB6VD@2"=T +MH^FR1!Z`7]M'DL5E-CFM8-3G(/*3%BGB\=/:CPWLZ[AEK4?L:<\)%!0*8G*N +M]WQ._BCZ/EVKB3?Y80`3,LQ?3Z=:C$`J&067E`M@]ZNT3JH1*T-.U`N>2P\K +ML4#GRQ5W:AT,M1H>W7L?/@JU&1SG!99"74*[?JR]R`'_]%JO'T-Q";Z_NKT-,\I5;.W +M#FZ@WCHAV+^O?`$?L!$7ZO"^-2>_8N$9][C$*Q\2#W>"$00>%8+ARR]"V4B@ +MEOQ054RB/Y>=EKP\X7_>YDZNY'_0/E`?3&MGU3L!P1[&G*B/<,R_G-&2*[&U$EH@VY"K'L=_5D/,2(<&>,[,/*KAN&S#7LRRO +M-3D^*NE+)%FEM/L?]EM6S#H$M5B_-DR,6<,),LCH:%/$``BW8K\$YPE]IA1%=.F4)Y*V:6V8*> +M&ZJT/+#55]$<\3IP(TJ6,+UAU9%Y6.+C>_-Y:<**.E&.!6.>@4+$05A4/3SD +M':;*CJ:S1S%+'I\C5RZY3"SUFN:RA@3#,SYZ\GL6B_XY5%!_6*/N5-!H:!!B +M^T&LIY0)[*A1])2(=MJ)HULZP,QPL3IS28>KG9_FQ%:6S9[VMS9C#EI)-Z^/ +MM?Q7J=#W3OA,5K+WMR;(;?`D0Q!.+UKQ3[,'`D`8HRMN'-]P4W,KWG#8OO7( +M!FAD(MX7*5QZS)0!9!D46USM3O%W"^[*J6:+C[C4444=7'_G92.`LV#T?6*$ +MI**WO@M#VSG:)#JI7FDE\PQT[EO9)]W63_T=`RB?(($1I>*G-NR(_56P3SMW +MB-9MT3G/V1++`'.J]0F*^G>&X2Z`SDZCZD%W`2%'>^M>"G+99\ICL>[CP2RM +M4O$J.M04RBF^-L$MIY^??WI\0_]ZZQ*$("RTQ]TH7LFV0),J3(`WA]4YL*B% +MJW/R9.6OCB.(Z4B,(HX2HA;,_:G:6VFN0%XV +M)1U8-34H3;1#!"`OYY,_?7_T1!(/-9*[5]3]%\8GC7W +M0FMR?[D!(M;Z,$!'8OU((2YD/=J:%5>1O$OT3Z/?X^NUDXC)$4`KDP%#V^GX +M9Y3'%AI?7\]V&)V%-,E@EGC\K/A=EWR?_C%#2%-]%7Z9NN$^Y_9^X^=\5@5V!/CL2EDK?).1 +MW+682IR!KFVPS+JS!Y/],!'J2BIO*[`)31STX4N2"IFE2(M03K%1B@(.)T'? +M9Z2F9._KY+2SP4YMI4/N1=&&12#BIV]WA[2T`_P#XC"BH*\'5(KUF`Y5>G4* +M%^]J)(C,:NFU-[LB"X[1[3A_O3D$DB4($H`,:O_#1AE;K>K%Q*@C/C)PDG[; +MJSYFU8YF(5#O'^U\>+]F!8<+W^DIL^%/@3`PW*S>';MWR#!O,'#[@\0;ZB1- +M&.&`%L+CB4*\T$LAW`L,@$JD=A>-*\:Y]5![D*?AVAZ>>S$3!TO&>U55\`3O%+'L'K4.%Q%>T####FPEDQ`_>F$F7\SZ,;^^S,N[?\BMTE),LX&"&>@:>9#LI.7W.Z +M5VMB\#`.P$YY32!V+8',MG;QV87!7D,!X&W`C0.PGFR_XPNB/74)S*JWM!1"-Q^UUJ3G6DR:KN/;HB:%X-P8NGAJ>,-("!N+^%_75M6`HA +M822+2(6K\?K>][,9B.<@6 +M`091(-'/"DR#B9/IM5X<^T+S4?62'(%=:-O+LYK%R>FTB^T$E.\;GCXU&M=H +MR88V="W0F(@R,C5')Z_.61_:4T*),O5]&H%%S::$M*JHX=6S)IQ;:I!"KWT% +MN/OXN?SH2#L?]A+JF.%(XVM)$.]-.ED.;%AF-D'4.CB'Y.:MM,CIQ)DF70LT +MO>900G#R>^4[?R5(.4T_-Z[+I`!4AH855']LPHP77E7(L)2.'&B_#0=&:1Z1 +MT>9CY=Z01L+0DRPIK1CTUG;N04VP/+:B%]B&3WZ/ZH/3#) +M,V3(AS.+=':RL@]9EQ%%G&P<'%]"P"U#0'JVKXK42J@'M(%?YO$$!G/Y`3?5 +MR*7+=J32((Z8N9NU8%76+4K#5P$$$")CCK3JR16C%SF($F=M^5]02RF,LA0, +M*BHCN1]!7C8&14:]-\"XPFM8-T=39^-J#TZJ4>2]XRWU0>&$T5#,'%IM\N2T +MS[LJSQ:`?&0'6O9:Z3=> +MB>N($`@_N&SH7-%=4RJVM$6;8O75=RE__4C1F]E0P,T(H1`R(:1&:(+9%KL\ +M_QB.3[3E6O=QC9?UIP*1`/7'17M.`I:>?>/&9%MNND&!8?FYF'@T7WH +M'K&ZWC,-_GXJ);6[U(Z'?43KV,F*>]KA.G9%ZABB302T7+>SHLAYI%7(Q40C +MPV-8FLQ%49'P-E@8HYEK\`*3R=R'.V%X_*:L/:A%`=&=66B.X]9O +MV$.P^G>BU7_96M.HF!WY1FOC\;_8_XI63V4AQT?=XP2.&U\N[T2DM]/OCS*0 +MTYOLQV(@&J8`N;+RK$OI`2$B�GT_C0ED',*UH;[H,(O!^DRO.U3EP4`&G3 +M&3]]P=$+K* +M[.QEZ?1^1EL&*C$*P75*U[F3/]=^=89$'.YU'@G+*5LLRX.8$VY>G0YU0*0G +MOSD-N..GDD&.K<9M'/Z,-5;SA7@K\EX\L?35Z$",21*SS.2>DLNX>\7B/ +M?#KK>W:4@Y\`YR.(5M[W0T[+_@+QO[0L!#H"X_.G#,4JL-`&7[2JK'_ACWM, +MS);D1V@IAA7O!O+1)'I4,5"[+R%S$//9^>T5UX$V(`&KA!#*M(O3!DWI?OG9 +M4*9HPW;#(X*O8R^-T]NU`@;(<+K0XM)2,IK_E4FUWHYS:0B?>PRMXB:.12+3C$64J0!4E@XB1:U?.$?P>)FN8Z`.IW]JFIECB",M"DK$[9'PUDIJ> +MDUL)B\!L\BX#\$L@_"1NB/EN?T#9#0=?"*JL][@Z)>G_]3V/BG.%3Y(_B6.^ +MR/L<\1D)60SA#F>$Z?^Z_LW)X6S(E$AVZ,'P=$N1JQ<5MF//S.3:I."6I,L, +M1-T>KG9&%Y1ZF8<#D\]Q2X4DL'3D@UC4M1ID0!OY<<4Q`\;E&,@QM1\LQXSI +MU1VXA_OQE0WL0"'(8M)L8[GV6`;D'_G2!DS!F5$7RV:52R>@JH5@PMD\RAIN +M02A"1T"H'TE"?]K31VXUBVGJD0_DR2;%9X?@LZXAH087(S=T">Q&KJ$?.[]=%.;*7>#7W@;RU!'+4T'<-.AI&0%BBHT?="--[G +MX4T!`<6.9P*W7R8/Y9+FO-"(Y_S85V3\G,R*>NR\R="[8]"(Q%LJ-"`\;TU!0TD(Z=3=G`)75M'(!,*?M@I5W[U,"OKR<;E!R^ +M&UE0GLJ)M@BGZ2J0;"4W'P;>$C@Y($&5*JM?+E-0ISV2+DA!E;1ADT0MM+\&D +MH+#V1,<8>FX9TF:A,FP1B_K5BY!^N1JY(RB(]NX:A/M#4_0VOH>JW9,O,_C7 +M[]/-('NX=O-C!RHAWF1]20U5E;&R&QR#2Q94Z[1Z+-H*Y4I%W'7.@X,"+1SK +M=]^0A('N!;3F7.0Q7=+"S`F!*_8\\9#]IO`@41!,Q7>[>)TL7DIRA=PX``(K +M#J/P"FLL/(^7YO$=EZ=CQ6\G-^3X_(>'K*^58033ULX7*NJT>2(H7O;H2E(" +M)XABD._"$L]:N[!O`Y+#*NWQ870"(>\[IT'`@X@ +M<3_4YAD&8XI.LI!ZVNK5D%(V1_T"L-^&Q3G?*I1_OE`;&6$XCJ7X*P>?!K?I +MPA(*1U/2(KJREUSK'T&I@(WJ8M48>DO&H:6IQ'^Q"=S(+4:8DACLK(.J.J_B +M%ZPBD+3X!623<[7EL15TI9$/4GAPN.R)/$D!9G\PRI4L^WJ=S@TK/JDMW^EGV%*,&B\LE+B21?# +MYCGS0>@K1*]K9`FL_8+R.Z@QL\*E:(<6'J34GE'_R4H\[G_^NX7YI&V1;P2O +MU-:4W7>$TH.B0/?E)]V3=E>6)*D5$NT1:]1T@';QF]R(0XW.9.>^KZ"U9%/@ +M82'Q?[\K)5Q`U&+:3FX15SQ,`#%(D9U5^[V?4D=]#&(K`R+)DOQ,5&9#(+O# +MC3*0EP80,J\AZ/24PT52`U"9V9N<.]_LLMRVG'<5JQ\1TE*DG6:N.&\#+)F; +M7>LE^]KVNZ-"?,9*7Y((UQ,G"9Z/I!_XW +M36YI+=4#@\@D\R\_WN?<--];9Z@I%_K8*$<0YAOO0UMP^/@O.I?TE[#"40T>B9ST7_2:G2>GK&-J:HE +MK;TUH[-?$8W+Z`5=,T>P$`,8WR"GV&IPU%[IY+,ZQY7Z/NL7B$+=TKNDDSV. +MQ3^EIG^*2G,?"=1_E4;B%(`H_`X6/\<30+NAK +MAA[2U^T#`PJ0_9&5\@2,K(9I_';7@/N`R7Z3/L'\KL1\3_Q[8^S0[&;C;YKL +MK"*)EQ*EGHDC:>="A2'QCC@RAIRO3Y/&$ZP]XJL:C!7V4&M?`*REGVLC9T[= +MI35#%_]3TYNYY*B._+^)-P:ICO1`\E>K%25]@-#)T?`&H9$6._C4EK4?@+]] +M/T2Y?8BC9&+;D+K/(+0=98MM])IP356O#3S\J@R_!SIP;TGY%S2G0?J$.2XM +M0A&[D%1),`?D?JJYX2>L_DF,@")P#,#^<1I>;-*.$M"(60D+E,>2(S)O]LUV +MS]\&=[WUT,"CC"U\Q(Y%)Y9,]%]&KK[(B(T<*56!0.S@IDD\IE`5IQ=KX3Z; +M8']SMTOU5SW'%D)(\Y^=;*[4BJ0D2ZVTO2F=".;W9A?&1@7$2HZJADEN2XK@JM]]$E2-`VW2WJ"4NE0J +M"XNK*#QYP6WO/!;-W:Q@1[DL)0*-K\O<=N#9BEQQ(^9TI1-S"<"X1Y-C`9?E +M#U>]+!TC>V=L^I[D!-TP">A;SH)17710RE+M:B:37,=9=WJX8$&.#+(3TXG_ +M`8S.LDV[X.'-U6VK3XD\N_J?9\2(YY)!`N\2.8$A=,.$ +M)M,HK^#>"4>9THS""".3-M"#SN*>"KSW4D&XP_V."G%'GW$?@]H."7_!W4I7J!.BK^7SAW)W +M9R/9`+,1T[;(M1:;Z81@@6OV5_K>':5*,_ +MVD.74<;K-(C_IW;@);@MHIK3;YP_S*.(9 +MQ^DH14C,L;_2QJW1WN$W^Q&ZL+@*CR('M%X^@YH*&M6"9&TR;GCQ/6@+K#N5UF4V' +ML3-'[6'!7Q_T%WE.="7^?!D6C!=,)(^5JM_R:.VKZ-,.V>8GZA?ZK&_D\_[6 +MZ47MC6D$(%\WY,0)A#3%PA#ZUL3_K61(Q02SP?;V^U"$L8U> +M8*B9@I_H58N:$_@]R.YMM&F: +M/=973J@@+>=G9RX9_DMQH3B=Q!H.'(T(K?`I(IQL``^`RV%#)GEX%MNW?G78 +MAWAN=>FJP"]^%FDRR]41-4#7S;6V(B%DWXK4;:`ECUH]B#IB]$*M.4MYU5OW49O)LWM^H?83L3:'%$^OF +M$N;GJJ[Y6TRA[I)5V#XD1?W_7N6DF7RM`4;F;U['7Z215Q\C.;QSA"9#V:HT +M>L",HL+G[VO!&F7UXBJ1,$KH(*?@4CZ?L39:*KUOBBHAA0Q6@*G4O?,"-.64 +M/?@\7T`>#@E_@,%2R['J):@QU>M?6E',_?:J&:N^C6J=TU#P[^'523IW5?;_XD&HR +M0?E#-CFEYIF)(;:9EY_OS1VNK$5/;K +M`Q1K";L:`45)T.?ZK%^`&EF1E\?<._#GNBX%BK8@590@"O+=E#&5'H/J7O>8 +M$D:NT6S`[25SFP=V2TFZ:XC`2U=VK[RU@LFYRJ=J6\Y\43$8KE?L%`"CJ$1G +MK$Y\Y:'^EW5K@K<1KK+KJ&8L.MY2GF6/P"#Q-5JLN!676[\49%"`3F=IGNIB +M96NIEYKCLML:6^(2.5N8'P.^]3&N3FD1JHP7[HM5;[*5[RSI0(5(YEV]EH75 +M_DC*MN+%S"^&@;VYQN^SOR6;*M[996+\>5(HF?J*S"67L/H%/*HT)RD>/MH/ +MR#M?(6)5O5OQ(RSAAZJ7D?Q#PR<^MUK#UHHU?2#7D)DL7_L]H/5M+)NQ]Z-: +M:4X2&=-I_8[)C+'*]F<1;'L<01+*ZT##XWU^C?-;`6<14^&^A\P?Y$:1&B +MC70F6PI%#1MSVF6QD?;J([0&3B>W-;KO"H&KW;90MY#41?R29R'LDW#FT'S) +MC\S`:MG1E=-PHRFDN-AT25ZU[NDJM>HSLVQ-FA70V(%-V.I`+HP+;]T1%>,7 +M'M;Y7DUW4V@"4.ZE"L0@[?:NZA>W!PPT82;#3^<^X.+;_[R2=;^;/!T/V*[6 +MY9U]:NZWXDYY'Y,KHIEKQ4MX>MT,*U5=%Z/L44[VQ6C9;2%.H-^*(@X*KC!] +MC&?>P]][$P4,*O5-7E!:)=>7-[]5&29X$_/,@W>'>>0,&E%@@T%L>I*CD')?^>TPN +M!WKX^O^D#*A@_N;D`Z/P#%?\4B;$^SDIQCS^X?^*1*F\FQ59]),J6#S9BUOU +M]4HMU^37PS3O3V4A"R`P]RVC"SAZ>WE77,;I#(Y8VK^9:J^/X?`FH(U6`&8. +MX>/"R&APV#6B19SHV(8X/!IS&]OC=L4_7Q3>=MY!0&H(J#E^_&UC9@@KXZN: +MFB\&9A7*0A(JJPD*O(#UYUW8NS#P7%\ZX0M?>G!$4`\+"P0]0NFF%_C.TZFT +M[\"X9Z]6>&TG91?QTV_,%`VA@;LT1\T+)#J.P +M2<]7$3RO,((A#N^(*Y\6.@'9KK&" +M?G0-&^V/#_A<@[J=01(>:,?KFS(=GR!.`X`8@BQA?JEFLI'?\,Y-M>!%>"<( +MF0"Q3@:8ERCB`RMKG`UPR&B\#Y7_P&N3H[>_ +M0@3IM"G->ZLJ=V'DM#^J4A3+@2;VK7S*;H)_`98@TK*!DI4$"E:(,ZE;HHCC +M2K*TK?U`8UUY/U0/Z(<0*U[SBX'7&>]?^%^+,XY)L\\\^8W4T-L4R%BXC"6+ +M(UTN0`QZ203P5LDEDT$L)3_%%O?1H'L^$;L$/`UR[3GCX..$C;)5Z9NO7$;I +M6L86PMV\'X/_93&$@$)3A9@-TDR[M^1$0NK$^Q?*O^/%GI8Z&N5^8PID +M`+E'3L=$6Y8;Y&SE8*EP%L@D.8'#R]4T];9T0U.U\JIN?Y=Y"TS'*!;;4EM2 +M`#`@TZ[(!JE"J%Q'W(-QT80)!?VEDIZC3>QDUT>AR7T?E7T[]BZB'U8L;FS7 +M"&[M-0P+-?M1/N^4=!"O\0OTD]7\["8<''!\X!S6F41'53!FQYRLVWZYLT@I +M:ZYBR>*D>Q7*EG"=EPNY8Q"6;IJ +MN>B*0H]N+H9+L<)RU.(BQ'KVJ(&EXZC+E(<:MZ9[H!`*)1*W$&/NO/_$\(AL +M&\CNEYY.YJ2XN3US>8#YMZLN-`9W"HV?05>J'B!L9(*M:+D/2C[R])@?*_:. +M_/;4W-&^1TOT>Y@WSN835E:'Z!VF[I[2"#UY#$UG>.C'S7BJG.6^@\WUZ;)\ +MT.Y9)A2<99<_NR"NGZ%W^BX+C[DXANDW.J,9+`12&`0/AK,3'"0/O2*^-`;! +MF(>79@#`QWCQ[O':"ZG=(OJP2Y9*KB=>]XYS6MHI?56OIU,1V4$BLZJ=A.5[ +M)(+UDZH*NR:9\T+/3U474JRYE/VB*%G-CEJL9H@)M"?=_6(A>8/#0)DO)>AD +M"_YVI36]`2HI(&&GXZ!8_N42D"SMZ\KI^S]R!?/)?B?ZY!E[BUTQCX+/I'D8 +M7?^%/PEN;WJ"C\"UY-HWT#'8N!?CX,"[UJZ9;KWSCU+!QM^$_(HNA\LPTWT6 +M"'I.8SFU43@.31E=:L+M^MM#91$D(A)*X;TYQG%8VV$V_)>+I'O.X;`A61X[ +MDO[@.F5K^,9*$FY/)%-(PH8,4ZNN:\?!W*HXQ&TMC]_I'3.!_! +MA_E^JB(:L!%?T'+[J-)]?BER=*-]WFVMF@2">! +M=3@Y-[XFM=],"_W^SFCY"]+_'98:%,L<]+,I2=1.?]%!,[2Y-ZLQ-9`FVL(T +MP$%7$V48I\UI.LG:_KCA5;&MZ7?QJZR((@D#'L%*K1%#\(*<0;9U6%B^.= +M;@7X\EK$$IGA;H,+9G=5ZWM^,B.+@._=]^,-E@[G!<_%=6*?"G5.OAGS$S1= +M(YR*&A2_S?EU[1?/?U,B6(*NUF!$EVVU@);]3P=;]OSJ>WP9SU$6BV-V:_1UJ>5XLG/).T/81.[I`/Y*T^^MVB2!S?JQ^FC0\RWEH\)EY7TC#\=5PYG3`MXY^\\BT8N`5:JS@2V$U5QWFNT91Z4L)?560:/C,146M> +M*S^T6=#Y99DM_R!&`_T8-EW7C"^@Y9JQ\4_O.I&J5U,F'+%\H3'U(66=[L#Y +MT!&B7YA*\D[H@:!?(LYB9P'=LB8JH05DU?4QH]6BRKR-:$4,K!1'J`]#S^^_4HAE@!]+'*I,[>+BR^Q2;'A +MLK,H0CKMQ`[//^\_,N\L>3XOBL..,CW* +M358&9&-8MAMUP0+[.#0EW\)/S-]]P1#,X'8&)%32'R:V2%QI,HCC@_>8_(14 +MQI6M$JL4FKZ=*HG#\(N8Z9N,(L?S=A_[,ZE8[:&E..<"3C=&`T7_55ZCA$5Q +MO#G$2G-(MB]HH%D6T[K)_/HY'Z::3Q;?2Q]-B^N#2H]=W3^`33WNP&ZR:8+Z +M3[=.ZY-$V!II0'2-"2Y">JFA4;-;.#I0JY[CIQ4J8.RSI##F!)YCPW#7CFXA +M((F[^(C%OZI-&2"?28U"7)3)XQ54;7\]HCMU2"2!<(G2'V +M!UI#5X?9IA77T8>[BY`>)J>JJX_4"XQ&#.Z%C'O):5GN#1@C[# +M_R](:?\85J!BRB$-*9`93*XCJG!;_Q4.9*M-M[YJ(W*=)94!ZQW97HLB/GCP +M`5%V[`JW,G')N5!.1;%Q0"Q\*':A77P%^Y\=8C=^M^U[VGMWBFC59.2R[?6& +MQJL'%9(EB5<4N%O^!X@KA;)VRH-[,3(N9+5]0OS1.* +MX*47VIO*6Z6-:6E:JP&:.B_6/::QFE-\:5')LWOPY`W%W*^%I"DYZ1/W8RD> +MVC:W*X*B8QP\_!6P)[9G93QH4UL"2;Y%P2GYH07;'UW +MMY?H6P-YSN>>WG^GY&!UM4^,JX=BXQ7&[-=Z:Z?VBJZE.M]6_O-$69%=SK\\ +M>\[/C4+&?,\@8?DAY-M#;!;9OJLG=Q8KD3Y9>]3>]7"S?8PB+DH3( +MDF0+6\3SS"@FGS"+Q/OV0V=Z.DQN$>'>U"L*K''"%K&3HZ/1F-UM6**$\DLV`0B4E?TN%SA^NE +ML=6E$1=K]%*IYQ/W\9Y?XL38:](AYOZ__N(-LL=M?^&%*[_,AK+&C3?Z#$P"3@AJU^%DL0D3/I'X,)$S+C)=4&A=;IM# +M:.=H:C>=P&`(]"M4_PEG&H@XLD\&XFT!8\5]@B6_]%EUFL%E5AS.@+Y.IT(3#D]3"'*+-,G^537&FX^N>Z%Z +M`6(E!ECGH=//L@WANT*"-KEF.(&H2D!6@Y0CUPF,.#EADYM#V;OF7"K%R,\4 +MMA3Z5,,OY#5Z+?%.LQ0CS/ +M1@Y5%AP`)S]/O(A=7#VEC0^YE%!AUO^SQGNE*L2>3!#'[>>\Y/T:/$.+`[]%V$J__[8B;KY8C6#A +M]:V'!>:'_5O$+%>^]+49N/IQ0 +MXRKW-G/>`O3K)009U/24`:/:P^Z2L$T\YUDQ'9$84))_[UF(KA$:`UN87*9& +M^7LF/164DI]RZLTW_QT``M>+T<'16]P7]9T&Q,N?D###+IYH1D^ELF9K`82` +M0B.GILICC3]*!]?$#F<(78"JT8'+^B.[W1=;226E[](R=T"9.#Z8"YM#XR[N +M[A_G%$!=7C+E/*>O.A/$Q2PZ"F'0U]VR(HGA+!Z[M_V5LM3^H?LB40$<:WXU +M/[RQQYB3/8)1:+8[^&O,QKZ@X=/@6T2>IUG!:2[7QU_9+/?9#0@K@?$G=%M/ +M(>0$+B@][].PU!*G18YFH"^C_]L;[TGLW>.1#OME)Q81%?+\#)6HP/OAI?V% +M>8E5Q?]>8WL*/LOA>+0`\]Z!)=:JT/F*`MB30/(Z^'DZ:B\>?N5%8?J#C3+E +M=2%Y;VLC,Y88)6QJGKDK4H4*C>GCU\[D(N2#%1"Q(-BRDG,@LU-$!)+KR>K:@:25SVR@-N +M-R]JUV316RJ@G&N=0PEC3'O.-IP$.N2[[LF1F^2 +MGV-26;!;)$/9Z]7P8FBU\^"',+T]1/Q4LK;3TU-:4=+F^X'EKO6]3&T6`Q#< +MP_BS"C4<+*?I=OC.A(`%.6'N_3?(KB=XSY3,G$(TE9B2>WQ6B=C4=%`9L:(R +M%#[2I=H61M/*6\Q!3`14JZVQ*RQ.HA:S9V'GR/ZJ4.H:(9&T0?GCHMI25[

    % +M'8FN^A,5I`V/B-[1<0D#MV"F)GR0#XGG_*%!8(C;IS2O.5+C'W?\9 +M'-:\J1KKZ'"D\N0)VX,L$2KE%?`VY_W);8.Y46S?`^\&KJ0=Q +MUM'AB;*C/B!T?Q8+--.@?R^57\8D)'CA58VV^3AOT$IQ=>EA=A\S$\.0AC]\KWI)59>`. +MG!7J6EX_W@[8X9#&E(8-S2Q'WH-`^"(VJA:P3EB$NG4FG/8P1EN/)9XF<]4( +M&2/2>%;>CU)HGU3]&@&'?1-+N!%45%U@=$M_(PTCU8405W9@0M=IB7B&JPPF +M6M\&_MLODU7VO!^P>C]C/(]CQ^L"#AG':Z"3S@L"$]MET30/SRC6O,8@K2:U +M?^HUTB+LH!)C=F;;K&5^3`"4G&N0+!_VL_7(\W?5U.;M)]*Z[$"$;;,/+F +MVX1\F7A29Q2+%2B^%C3T:0@6U/\]]!PGVRI6^Z3-PSG$C)#D;(_(#>:4IQ4_ +MUR9[K!KOZ5&S*MQEF]+, +MY,L<[4=+X,YU]06CD3@)@%NE]K%^YV#G&7(@72KF6P_"I\:FXO*D9YE-_!M[ +M4_E?T'@+\TING4!B&`600S*$-L^;>"'X9H>J)VP:'[7["P@#:G+E%!TI7H]I +M4"9,(U,'K+Y1'=J,A,@$=N--L1D\?#>WE8`HUV'`D<^8;I_7'")H):HV7`/X +M^.^8^6693#W_+9DA(1X-)6DM9XEH*VPBL1Y7)R`BO\.,GZ +M.HH$["T>@Z)*VJ6.!OV5[Y/U +MUXC;1QW4CR86HP,;6U1 +M`:_UL--M3]A_G$<5U,NF#>G<3\)Q-M6RSZP*1]S)$ +M*JVICDR=6FTD%\0F[?#3^$2FUS3!$#RO]YH**<**0_0Z +MQZLQ/>%KNT=30/OXQR=]X;`*D%^_HB'YS@H%_>5@QC[+53V(W8:=RO7X-_]7./E"M^=8(W&[7L]S(#N&8+"Z493EDP\)BO9=F>^J_)^T"57Y.L_OO&J +MP3!-MD]61R>JJ+[!68G#=/;-YLOD'[8O[EU$;_J-(8BB2J&-R(MZ4J,5'FLEZYBTY$P>QRHZ?RU9<'>P]-8@D)K3ZTW`:?A$-YDZ++G3&#[0JAM_-AFO!T+L:4B +M@X]V=.WCJ<*;K+_FST6J*SOPD4_%VW)0SD&)]M[U\$_\"L.XQ/ICPL*=TR3[ +MF7?QA*IVG-E5:4VDG3?,Y783(5A")/4'/[G`T9T#IATC].;-?-,A%W%%O/(CG"BH>I +MOD&'G4-3&CK&,^3CEO=^52*SGJ9Z;>SBT3=:0.>>7#-@/\??1!HCGC]26[8\ +M2V;;,0[1RHQT%@C86$TF&H3AFBQ?HE5L+FG=TD.41D?;"FC4B\CB_E +MN:B$J`=VK:$)8J-6>!NUWF'H4OS.D0LWD^[2)/='-+=X%H65#+$"GY`E^"(S +MKV7CA/OSIU1@ZS$^Q:1A?(YBMV][H#IWV.:3?Z'P8PC%?EOJ4[%]8.#>H;R/ +M&^W"_S5#/E?H2R!-9=:VN,$#G4AS +MJ0ZK',=@V&N'(Z`#RUY>ILXIE_4 +MM%J87ZE:RQ?((_OO+9`>[32NCG-*_A^+AJ@T*%+3?2M:4G0?ZZ7<-H!C!54M +MRWH8::Z9R>H!G-TA3L3-/=83BDPL-AQ-\W'4B*9U*:)UME['.$DMN$V?2`X2K\LH59CI6?-G`]HF.$H`.)PN/(E:S@@ +M%IF+L$V>F!T=*O[EJ3.G3&#YJUD?.#M$CT#@-.L;*G\GB+J,*X;B]@^-08GS +M79$T]%VW+R/+X+]$_XK,DB<%S2D%9M9?:,U"C.:B&+7[P)A' +MI\^UQ8NR%6$X3]'XIKS$[W&`IC115*K^*;;NK.`0$>%2+]-G/OI<'6\N)@ED +M$6R26Z*W.K1A?[CP02`_@=DFM9KF>>[^S5M'TRQ#E$D7/Z&9`9V\L\X!>2F, +M863]?QCWROI/47NNK-@HN[.4M,[7VUS:)O[Z$5P;G?=A3K?W6^,K'`%CN[UM +M.FR6MTC3&JV-<%QA^G&!#YF9\-[%,&`9V"5OB([(YKP^X472X!0\)N\Y>699 +MMLG3#8+#;01=J*76'3H"H`;M@LW=+Y7*370S/#H._S7Y(%4SND$M>/JN+BB_ +M\Y+&BNI7KPW7>5[?8@DYQE!1,$?4S)WT-RU;P74:_X3#K62KQ:`87B#0QR7T +M8T@00O/O;]O,T!SMNK?PSN25:U^#W=RNQ4Q-)_H=*0[+EEO("KLND'LVA^R8 +M\(U?!2J7'TB3",EQ:8AZR1WMT>9^!$HTZHU7=>)27LW.5SZ:L[$ +MVUC(:8J]2B%3)2@-*]:%>/3XX'".`=)?;(X@H:S'?'O\=AYDEGXA5E3A_=<$M`F +M3$3'E=E8\8*ZVTS8.<`C54\GHJ(0$GO=?MBW?`\_O;QI')Y$T6J*"=!52\:= +M7E*ZT*8;U]G3_H#:7(<@V41?5?;AF#&FHQ5L;:NLZDN=2HG^4R;%4(%H.O;7I?S.E:^)5-3!B'A4X:VA +MQ12WPJ0@QD(5@04K53M8!"FW+-]Q"T/*/SZ\U>D51'/]T:8&*J!L4/ZROK[B +M7"(56U4+3XK/3'?NIKSOOWX/=J/]]6M0A,/S=W:SE_%(+_(+%**;Z01YPF=J +MD`76USS26*4H`WD"V5A^VG??,80&^G%FC)7%?.XJ5G$Z2\JILS4Z05_W'_IX +M&,[WZWONSZ]AC4-KS->S>G:X`M?$X[^(1KMF>Y_HFQ]?6=D=LOLN$X"ZXL^_ +MB-!@+K-J!".7O'(+FGCB/'?=)5,MT,QS:X&"?J`G3.UT@=)XS$:VN+GO$Y6+ +MPE,38P9)DH+8H8*4+WDE)N=+Y24%5&"C^6,^,U%(Z*#63R5Q%EZ+D&,0B[/T +MO>L3_@Y)E!03PC,/14Z6.SUV?GH9Z,]@REKMJ5K[P@K$NG0,X%4XS;28@,Q? +M]%.=>IA[#*P-(1TL4?.4\*PQ(2+3%2Q!&3+2+.AC<=QD/D9I +M27M+*;$))SFW00;SO_5GD8:SR$-_R*]9LMN^O&M@WK8_G_T<*8NNJD$PO/C[ +M<"(V3SPBR_L(5.J7^#LN\&Q+%BH@LV`*:1K*%4&ME_\^:%*!R=QM[U9)).JR +M(?B7W6$&NR!K7P(B/POIL(.IZ6SI:< +M69GGJ$@2&),T2B%8PR:160!T>>=%FA";J:>9CDOO>=AO!:>3Y'\D\M9<`@$HV3>OF[IEZ5LA%QW-!LQ;)M!BVWQ7,YKH)MF_4?'DCVOT)D?)+]JGG +M3#FF;L6RH!]S_Q4W7???8UN@F"<2P[@7S(Y7[FC[Q3UBY#KT7H*-@=#^[(+Y +MJXV$"7P)0L2LE2"4VLV[,3"S)J_M,(^?5>0\S=9]OBEN>2Y@RU!S._I;HXSK +M.^BN4"OY^FXF2J(L?5Q6[,1]&CF]FL$9_\JZJGR:6OQGPUR[ +MM8_L?9._@)4,`IKI:L4XAN`LN<8;\_GUDN58X8;&X$3;X.+H/8T`3738Q6,G +M0Z]E)(YY:D+K$A'*E8`4MF/IH^3Y]\_,AV[)Y(!4*:8."H&#L\8N:>1$:?GN +ML`UY%)<+W5S%7&911NC@_HSZUV6B*5$ZT2S>Q=.SEUC/Q1!$/V9P>X.Z%^HY +M,?GI>26_3&>VS(?M)Q_T8Y>`*X6D($TEBRP+GBJ\#R^69:S?>=4UK3O2_,=$ +M2RA$E:[&THS+/VBIN'$/#$T\5[(1#ZS44X4@[.@N1+20;'3[UI*G5*(TQ]@, +M-YKW^:.(I>HJD,^=7@>>(F8`PY?(7>$8Y`*&V?)3'"EJ5X[A*%_JSLZ\X:"" +MUC&7,PR*<-5BQ/Q6\)D[3`T+;SHGG\D+J(1J+D:NATD,_]IW-4E^G?'9.'AI +M(#=)`T8?1'\GR.*NOM8_74@EUZ!^1!N.'<+!8-60Z#9X]*]2.9C3;?L&"T[0 +MM"C<=UH?!E=D/.J14Z6KRD.?Z)(W[DI6F,YJ+/*Z.*DC\I1S8!_Q4EJ,59Y_ +M&#D-36QPPC4"'P'4RV3%WO6HBO$!)Y\56_Z2,\TS8'SZ'TQ^C'W4\7"B*4-3 +M.B&O!U%!3KAX9-F!6W)^6A=_L(JE&`$'IFP)6V9)K%N7W(?FCQ\:3\??5PR%"%;T9$J,R3#^8"EUGO +MZXK67N)+Z>24D@C&///4M^L%N%>SYK%W1!KKA?HY'QV2+OR;RGAPXW#E)[K& +M1>H^``BC\=T;!DA%2="8BW0?F??I@5<;1L9?L;V[*G:TQT2M0"&0/GI_UK_N68:-@[,XPW +MU>5.(:=(P&[%#1\+MA1^L*2BHH'=`4F'O$FXN6.\M`2*C&?X!-L*X(5\NZ\E +MRG\O=B!HR/LX/G.5]G[*CDIXR2SL`0Z:^H$DYJ:MG)\E!2`T.?F%]RZ[KWF, +M$/RSH.OQ#3HXK,,-<.]SA5\2(ZO+K+M92CIYUM0`*@'>^%VM@"`+V%I0.)R4 +M<]HUZBL[E5A25.&?VJ(Q2=8$EW4'FS9Q&"0(D_;!P'_`40/0-NPZAH'&&(0[ +MF`:"/BB^)N>]I)*I$TH!A%8(,S6T>U:-<+)8C!?`*V%S`(!?,C_][U#2YM[D +MM5S@FZ/B45S>=G<"%Q*E%N2AK,TV2M,$6Q)UC_"3V65='9N!LA7'9>/LL:L; +M5N=.PX*M4A+%I!^@B%31(7*01@!_/C#]W6KI%/3_E4M\4<3S..I?]K`\[AQG +MP<&TK$BO:`C.IF:)G2IYU=,.J.5U?OY@*29H(6_;2U^N::3JM:Y@&N)2;/"? +M//E>I6A.YUH"]+UW1H$1D[V\ICJVO?.T= +M*OW8;)+`TW`9&Y)3;@]F.P9RO.).3.O[^/G[Q:66YYBSQ@O[9 +M*Q$V7&`P)1^X`9I%^V@\9J@ET_B=KEJ];"?=?4RY/;ZEP"'#V0>Z`P?=V]`I +M6$VW8B'1$)>)@1_*_[;::\$1R:%-PWI#TK-:"+`0'X]8)#'_;5RW5]1Z5=M, +M=>9'.SW[N@7?''>"QOPRE62_=T1]5TVY2O/:FA*E),.\,A%*.N7X;OX?IVM5 +ML@88V6E_+IW===WZ%P7[3WSM6O=?1X2DHF>K92PXWLOC&34),IZD0"S: +MN2\$0*J%/:I6,-K@+N_T=NT_CS=&R6V@50C(4D"J-1N$6QS+Z*-&!O_CF"(7 +MM;#S*3@`-KH@T2\SAJ5CIJ:$Y+UT0S;2-5>2`K."78-JC#E-;>I=WF:`#Y##]YGL0$8K!\.#`;O.)Q!=\/M(C>PA/R9D/F[Y##>8I>./@3=HU;X^WNY_KS2/2R>`IEC +M3JU"]S4B:T5_9^UQ5)!'PGT2#8?+>T0M)ZFS[`9KVH:-1D8,/+>S?[8=U;(_ +MG3U9\?"4F[2*YC6]N'.L74BIT@1=YTT4JQ/6K8RN.,MN11@,&[6E'NZ7T$9F +M5JE82O_Y#T1C7`_6!$?&_?P:1%[('8Y2O@7BE<_CZ[,<-2IEM>*B7)W:R2UC +MZO$VMFU\%C2V6S0JMW;4@=!_:Y5I:1E/2L#[,@GEUZKWZ_K=S[:_D@K0NZIX +M<"#'8(&$!1APRRZJ-]@,Y1="N=5N/H[TG!?C3)QA&I!<4R&0*>!M'%$S[:[< +M8W.<`Z;/5W1OG+5@Q(_VSO-&.%,9CL/Q8V-K^G\6_@LJ^SEP\>!MIB%BJ[);*4(#/NU@KLDA5G6OZ_#6MWNKJQ,\RJ/I +M$SH8'7%,E7)Q_\-J9.%HZ:[EN8)<,E5T`52N%K"8L)W=1(F4Z'7Q25 +M>U]@L):$;=*5$R$;]3P!ZPJOAV&;=78UG+PD;;!;VO@BYTF.QS^Y+T=\:OGY\,^G>B=XZ+=#):)MK&>Y_F&00&EG">Y_^H< +MW8P5SE,UNX&^'5V'V'V-%DF\%4N/CK(YZI"^QN6HVZ@D!S*]?;P\X6V^^?;9 +M^+^YK-SX((*\,(]_EBO))W*ZV_[(2T7SLF)Q[BL:N-:`C;`H[)>./ULT]6-, +M?_W#S;K%MGX/7"-;_4YP@9>GG:_R!Y98PU9]?O2)*P,MIU38ZM&ZLS7GPK]7 +MQTN5T=67.)?)_DDT.CCQ5Y"CQ1A"!C=C.TU(K[#+UXJ89"F@`Q`EA#<(`VQQ +MU*TPQ!JM><7B$Q<# +MLW\J\J`),<=%A8)]YC%J?7+VBT_(F5G!XX1BBUHF>'_@RNI%^ZQ%9WL@YO]- +M3ZV+O)(/SD3AA7?6R=KF!R>WLTS1H35>;`+(`J/:F>.D)@H\ +M:N-M"@%^8QO>MB?P%(JC%:3S&,9+'FK[+H+\OA_"LFC#RE&_A@9I9$%G.\P% +MI+U:N\9H4HWM@,D>[5)J`J'+P"LYUR>0NG!WEZ)S/!+D6PKA(]WDS-D/W2\/ +MOXB$]8FA-^B`YQVI8D3>.AVR7?$7)FGB<,B?/!1I>O-3:DM]'OA^OP8BG!-! +M]V$_6,YEY#G1"&3U3%#*EN;?H4$8]VL.]M[J&'BEN;:JHR)WHPY43"RBBV79QHVUL +MS//N($-8L+MZ!!DML=T.N`>-^ISM0L4H".HH_P-],3`D +M0[K^6<>>/ZWG'!1O-CU(MONIAA,QW%**NIV<;0#20/7N/R1Y0N(ORB4JEVYM +MBGB1U!Z!NF8I.<3^[(S16.)(55Z5HY_27_&\G/K5`S^,>Q]D,*4_,^#)^3TZ +M0SN1?/,J'K%OS`#+<32H7AW^[VY-:V[[+#!5S]26T!IFUI\L?G0_6#U(//U[ +MPVX.$WE/`W5.VVP4M;EBM3SB5+4'88#4#8ZQB[?]5";^A(#TI@I6H1;;;@'3 +M:");HV/QIEA%P%$A:OPU[,2/4B9[HE[..MJA-N!:&%(V`NUI4:"JR1CU'J:, +MP2P?TC,MSO)=,ZN!:=.:&9H\'CDZQMX#'C9:8%1G5M/D=.:D:L7OXU`3\%J; +M8U"+S.K+`XVLVF(&1F@)PULZ7#]]&'SV,?+"#&,CE++9N/D1VIUPK?J\?JCQ +M-5J93)ZK_]!(S/U4%5F0T,#HS@C,:H\'8<_'QJ<'7!:.?IUU,E*6CW!3[J,. +M7])@L>VX@I\^8<-+6;=/Q<[4*'"T#:+*0,57LFN:K)5:@8V*&2?=;CZ?[#(I +MD_31NN[!&J9I_G=#L-Q3`]4PU)N(7U&>+XB`K?VB;AZ%'?J(*U[S_(RZ!@NJ +M\H&P#OSFU$.MH<)5P_M0A$ST$^=1CG)S50>60\6)KKI,);\6QB9D=P4]$Y[B +M&V9VSDG-VI!MK!_`<&>REDU_T**IGG74YO7PI-2X5CE$[3@XH=U'0-`\E$S: +M>(&LM!]FGJZ%$1XAN/7.99T0:('.3]]5V=]Y@!H-L^CJ&=34=[LZ.8^C9NQ/ +M9,S`:N%=GN-(3#N$:N-,$(#+'MGGE2?LDIE`_G*?R^/E7#?^O%`N3^V#5I50 +M-':-UGSN,$3-Z\;)/TQG/+?IM^L;T:QR?D'(. +M)PEO)Y_(P>'J^_$+.%,J1C&_M_M]NT=XZ-/5!YE1;+/"*G']%5#22G>U&'N_ +M6_A)EE!BH$/4+LJ=29&E#=R`H7BU_^^^^%;:?6@S?:=0=`[R)#<#]^.VH6Z7 +MK3L=V>5A;Z4H+P>>R2]":[=\WAK(B@;=<#H2>SD**\?JSQ*#, +M(J^8=IG@=5ZX._A8M=6@FIH_Q%1PEMM!,IH=FQ!03F#2BDSBR#EE/V*#TJ$KVPV0?3%:D""%=HV^`!D+8MTN=&+@2I7=*RV&Z+\RH',$5K4HN2TTY2,'U0O4+_6HY$\H +M;J4C*4,CIS8,%7ZXP+KZ^:!+9"ZLQRW(E0]"W&\/3FK&N+Q]1-A +MERN)V,@![R$*S[J!5]5-1TB-AEQG\*JP=?HU@$<+&1E_/J\HK)4;-0RT_&8, +MY="'M7)UWK)0\'7G_UGN&@4U@W`(\XO`R#A:,!S+-$?(J"(612ML2L->N=0! +M9L3@N>LC1,NT_EAQI_@KNY&TR8F4R6%M''JJA#@TD>1,Z1-I%5QP:@$-*3.Z +M*_PGQN8")]]8&V=@D&G21[LJ[VC]-4P9_S2?\V:^B@P8LCRD9'EXG_RY6)GM +MR6/N44PX_Y3%5^GI*.J5O`,=4O^#E-;YN9"[?(BF6[T8&7^$-A$;6=KSDER\ +M[%3C69BYHQ:1ZL.&M*4A(+:9%'S=KHL6[#OC2.W^CR3/EYF"I$OK-2"2F(`^ +M&`!#Q+-V^?ZO<+Q.<,V'G(,_$$S1QW8YJZ_R\^/RC8287,1,PK6J/%`X',TT;.5G<04`AE+JV&['@`4 +MPNZ;F()LYP;5'9;E0(4BZN^#:V)VA5Y9FV?/]\/+V2Y>N+N=IB-WB4L+U_&_ +MUO:33?V+KBZDFA<"KZ_-!4HG@RF*%K#Y;`L2L@>2]GSB1[I`"P4N<#UWCM*T +M&P:U-0<;0)(`87``^%YC?3#Z#58C::\EQ;HQV^DJF7FX.]W+\*;T^M=>D/@! +M82[")4>"BV.!570@UL>8@4V%,@[L#($'K/?1D>870G*/7?"Z-NBKLTU//T\O +MX5$D9-#4D\6B"E%5HN;,+_36A)H61I05`5&&'HNXSXEY^T:RV%V?,DAR4"+@ +M?AL>+/_DW1]N-,$#< +MN'(46_IZ-PDB6DF8RVV7(^F8* +MW]K,-39NG6X(B765Y!$5,VL-*$I::%A\61NK.:DV/BU1V4"Y_W8US5H,#)>"UZ3-QI=;$)W0$90AF5YSB`\T9%* +M(O_\!/]V-\7D)$F6&O$M.FZX?\4\GNS)YBU$D8H4?[G(T-W-DWB@NKP)#KP+ +M9(J,$MI9M"PWZR_QWWACMAKIJ->!TI::0K>__T"([DD[TGKRZ"U-Y,K2=2_D +MNZ[Q.:EOBE8^L<9;_`;LA-JXS7.`E<+CP.?LR*_U_O?.3)8,A_I-W3'T/@_` +M:B2XU3RE0J9>O4OHE:;)A2I2/;1Q:`ZM[V2$RTUEOJH+4P_(C.[_=_%MZ]`3&** +M@A32GQOTNT/%?7.8PN2FZV?D6XIPLQBS:30/HR_Y>%_O?<9"&-1"&S^@1G]7 +MJ`R5/6S2ZDV-"8\ZO\%\F\N+\=GA:9TOEU]0NF;9"T:TSCEC?4Q'2YG8:,O& +M0X%+KX&<8IV.=)LMV@GNQZ=MR&=N>&`=3$T98SS=,/3E#;L5$>7O\K9PIYFJ +M\V2J3%J3W;5P!)24D,Q")>KCG_02@8OL]7_KUYY;VY4".#5&9C]--`&P-P1C +M477%)2,-JWS,&L? +MDZ<6*W73'M)-);V:=Q<1;A$793]Y.O>0+C7,4JM3VES@_>9BNXRZH]M0"66- +M-KOB,F\8.A;H21*L=O<D>;W2JG3[4D=^(=-E'"E^QEH +M5,)K`.E-(W$03R0[3N,=*PN\?UI'2S;I-\?J?3?I4)C(@.*R\Y9CZ_`!BB)I5:7EX(6F)95:=^W'=%J3^R/>VMR+L7 +MF*5\<:^M`]VBOH#)-XVQ)-J+.,VV/DH\QP^QBXG0W`?5JW"):+X:O4CNA>55 +MUCQ+`WU?$@HP"7F&X>ZFD@)[$_^P%AK6QJ]$FLT9*"A;U>3I-R]5GPIH!2F4 +ME9XLX)H9%U:OZ/0=8+!&&-W^9(4:@K":XD".N5>X7NVQ$".=DEZIRM^"V$;=?U'J\.3ZFQ1,SDAD#N`H='\H`$JC?P_JM;:K(Z0/AU4/ +M8Q.\G10-N$SS')MS#J#7RU3!D?(B\Z_;$Y]V@Y6?TL5E4BCH3298KO_7,8VJ +M@)\>0.RP2M@S\O^F[05`-G#U.!1!"=2NKNF^8Z]E63LBN?[5S?V#'G'QGN9! +MU7\>A($\>-.._9W(#]#3Q**+['7A.IET3ZZ2!OCD9;2GY7Q=*0P9![.<1`#X +M"HIQ`VIKNNC-G&PQ;D&]1Z*Q![2 +MJ-)]&P_6E184;17U1TV(5RZPDJ]PXK6CA%/>!38&JG`I"_BF5*\$01PK%++, +MU(2J70QPP(NMTZU;UR/=&28\X*F8YM@F<5FP7"$6_@0>,Q_Z$]E4]5M,ZCFX +M:@(D,*W*9C)9DZGXU7X,5<^[[B%S@MHE)]1^[S1[OG+2.])Q"0!/CA +M*4>2X;E<;U;F>[2YK,'K7.SXWEV,>GW?UJ-;O$:$WT,;3"*SY\@2W5S0=>6Z0W7<9=J^6QPT-BU@J/Z,+-%WV>+E9DS6-W +MQ^H<=M\,QPM5]V1J]F&(9&WT^RNFHJ8(#TXX?\S1F767W,QYG`S5QYZ3?%_N +M]%/=SHI&LO?TJ,VC)+.]DOELB58])4?[5^9_\A$OR$+Z(.P4SYTN +M;P'"XLU.3=-\_LYV%O?_N;_K8C1<_]K!*>;:TOS]=A6!]1VRZF8L1)NHGIW' +MZZWE(7/&`>G-K?,DM#:IZAJKAA3N&?0N;2:OBH1$..W4I)Q\U?!S<0-<(ZW,"8RYLN,OP6J(G?E*HNWJO2RT +M@KW:YZI\:`8TWQ<`TQ#%ZD531BRC"*:F#H<]/\!'8\#V=&LD%UHDY+9<;:P:B`R, +M4S_>(:J)$,&\NAE>09RERR4D/AT+8P>LFT9)H_=FN.+J.CWFDHZ;GF+D*:,I +M>V!4,'_$*=_R6=%#HAVIK\>IC:,M/?":T/W)D1A[5C`9@`[QE'OXFHXZ6$0O +M9`,<3$//2@<=WJ/%]-MQ^.5DC2L?"B)"FBBV:4US8+GV.5?K]FTR/%1G])7P +MF3(?6+P4E2`.0:G49)<$#S#.!!,>2&+\>N:UV^)>4LG]/] +MJ&"'\^YW2-0P+VF3"EM_W#HA^)<_@A3$@#H(G%IU*B@Z)$)7;)NY1MJZO`DY +M=HZDY0[]0T^0U0D"='9;B%LHW6O*_19)A5#M5:/*VA4(KN5K<]UGS:7\]*'[ +MI2Y7$Z43'J\PRP\ZTM!:^D@LQP>!_7W$?\]VRN)&+9Z,,E<@7IRO&9>6E.ZK +MT#3A?8!.!V&=YI9E_%OSUU-N,8RR?3SB@%I(1A8KQ3P5M(-Y%_":^Z/J_,&\ +M`>7AV^K"[?`PM.&.!5Z")*F[$88[2=546'N1OW'&0[G\[WKP*4&4`L\;.`-2:_]75V;:Y_&,^HX?/R4N:5O:(>8M5NV0,!RN"7IDXLR(9-O0-P?L"SWQW;:Q(?^#(V4_CCU +M'-GEM%-5+PD*HN]ZWS8!^HOP6:$C<[2/0L*)??Y^3%TX8`-W56!BL2&DKL@) +M;!KVT][9?MIGZ<3$-DWM4TL1HTJ6`LQHQ[9B14$5NC`+6@:PWNII<9+5=07^ +M=*L!S>]&;,KM/<-25-O'>S.<*`WI!.5$V88K:F^"72Z0R&;-PI%W@%6("16YG'&6-_/I^U\A\XN56=\T4UE5+ +M)CMJ)TODVT+O61@B%VBF^S'\[M5A5[-/N30A6%7K0<4*U/L,O>?YH2LU0N?@ +M`7S7=9NLK(LD-[&?3JLM.JB_/'-8YW^@I>8>]-@["LGILWHCT0_R<5SGM43( +MRJ*EOZ[H:!J_Z%RV(\L/"/7*$\][HQWR':E?@KL@KD]D2YPROU35Z?U0AFI@ +M.QL,XHFEU*"#KL#6P6)OC@4@)A2&IW9L=$V12NLJNOLSR;MXLUB&0?@,Q<%* +M:5R#.9>8+RY,I"O%IZ90S\K%WXLFEX\ILIP(OJLPPH#H/V3#/3W?$FT&C'UOEW@3!Q#(*N +M[C]HH7G_Q9/X>K6!5KT66`I(ZI +MAI+,OFHCSZY4-A[7RX93[22LAI&NZ"W\2*$H0ZMKH^UE++8`+W<0&`!S($/W +M<7KS;'TU_T9N]YPLD++WQUECXX*QEQ6R9O;,+ +MG>_)),.?BZJ_R^U0ZE&]FNVM0Q',@F]TDAN5K%1FA/'.U?&E'BQ?YNB*X=,+ +M2MD5R:8W2PL>6.Y:X5@FP3DX`[5%G%B$^D9`770+IY\!%3]R#E%/KAF4#E.O +M;4.28E_Y^.^A?5(@\SS'*?H!Q3MF5#C7-\=[%\W(:XUBR^JWA33BH+D?)K8_ +M75^]4VNLL"J83`RIC(YA87?WBDSR_]PMY*0RM1`B56,$^!HHY$/1)OH,J.EM)?F5O&%J.3,'XS8YJI+6PLOV:=0@@VV2@43)L\10*) +M+)/B3;_7^^/XU/.V,U'19FB@S&\4C9PB,GXZD21J;@I(`\C`Q2C=4\L[\J!` +MET2T_OT5SLY(NTE];#R5<@L+V716AD0JF,LS@!K?\F(YDI=#+Q:@3-?-CU2V +M[Z^1U(X(W/5)75P$5B9OL=4Z\$8%`>[?%?&6;>TR'#ZU)EQ+&J3U+ +MR,D`+WURJ2T$(=`PQ+?4BQTM?#FH]O68!?-B4?")=S7+0W(H5I9OD^V("D!A +M?*WRR:3J[;;T&@/K@OG&:DUHCSX'-IO4,:L),+8;7QD.L$D^A0-*9A!)@NJK" +M,^,%"(F1UKF.+/?A`'.&=]P+^8M/W3*NQ#P@C2/Q8L)D"+"Q_+`;YE$M9GBS +MCX.,'T?L=5#-$L5LY4=A8?0"]Q-MLB_AZVMYVN0Z)8LO/BL`?-."%?MC,MM> +M,UWI;`J`2'WLO+)\'#/G\LS@>`>+,E.*:NRJG;B$T0_F=6!<[5HEM>P4RI+G +M-!@W&#RA@7.]O&HS!TK\U8;,8;2,'B9M@1^VV.LJ!!YT\P:K)>-"R!8Y>J18 +M[0Q_XD%0RN1-AS:CI4T>`['Q\1P6Q3BU#=O_]>A)H$=L`%&&^QJY82G,\H6N +MRK/E>^W9YCWG+Z'E%,4,MS%2-::OL;=Z[U7\57<+N>..0D"5=211T>V$D]NX +MEVS-6X3"2O%J1A]LFL1^A+EH1C'2M+-9)'_CF>]R`&/8TC''4;IVUZ( +M5[V[2*&Y1[N0#AF0!98QOA+@4CU)[G'LN\!C('+_&2P95,JZ,O$Q;W*]&]F` +M3+V3DO!USP*M(N +M>AH0'9NU!>I33S6YFRK-TY=(XX<=3HL9B!:BVX,CDF1;X<5%X!$XYB(JOE[& +M"UNZ(H0G)O5AX[3Q<1GYC%N`@Y(_.FNL=+99G4///0++],A_,5'42^]G'QP3 +M6L;`N:TTD=G]K.C?K,9-MO7@81(GOT,?+-8>FPO;!FHSZAT"WW*_WH`/H6M3M;]RVTGMFQ0R6Z$0*\Q_MI??XDHR +MEX(]?/"$(P;JA?SXXC0.$5FL9HKZ5#S,-9(,O +MG?5,58C,$(8>/>TPK6.`_6=@0OW6H:>O^MCL_Q$QJ"8%F+H(4-7PW%-3;/%` +M@'6YKSE_AG)-DM/58$0WM3@Q4WR(G%!]6"X,[\-&0[#].+,V8ZJ9>U"IL>>+ +MMCGB=K-P9VJ7O0]X$#=?UG9A;%#%]4"9EV>,U=I<(R@QG3LXO.@%C*N_-0ME +MJL'?/*7AA#82']REJ_+@+R?'/>M/.B/%*P&#%A"0SFJ0=P0)\#^V8R3W7[H" +ML!)UY>W9R5)/BX@AIH..'QA>GX3=>C)/W=IAIYNZ?A9AFXD2O!^Q5_D&/0!B +M&879KD!609^=1'S=V*7Q$KL#7R;F\]^)Z_)E>B'F@1P'(3<%"R:_.S^!3'J$ +M$R$>HK+Z'J'C#8L%Q*\CZE^SY.6!,'EXG+E^;0>53A@8Z[^]P''1&Q;,P+^6 +MM0*HROYQZPA-Y8O;]9X4HQ2]"((?1'Q%T=U6B7[H)]$ +MD2PP*US'QJXB:*;!;6T!$QD\( +M^5\]!1=@TJ]3RLZAA_=FM+Z1,400'53.4[Q#'A)`0P_D=>" +M2!\T0__!#VH#;A?)F'QH2=^!]_[=9J),HFH6\<'2KZ&@4N7J,R%9NH,RC9(? +M8L$51<0,@M$CP&?O75^R8?=JC"^*<3%#PG0ZWJ+WE@D2%Z(V.PK)Q!),9__S +M6E[>#E]L+.-1`,=%"YT65.N +MX%_N%V1W52^4H%;:6;?Y]I6L:F<-XYX?`?)](>&9(8:J?,P\NLFQ-Z'` +M,ML.:_39MGN@L\1]HX!T%W4YS7)J-`7KY!;F)U;#H[C9L%%)4([33_J?%ZP< +M?T\ZO'7P53EYYIE#*LWW!$)KEAZS+@.I1Z,DM%J`76/BFJLN_2UW`-T]PAI@ +M[JI<<7CN&B!8D/GECRWY0ZS&_/)4E^C'O"G\9;6PG(L&[5,J8H#NY991O887&NP=NHN`!= +M!=OE7OX;6QD,$&O^M`J3V3`VE!60J<;X0K-?`%XC#SCU*EH*FZKK9!PWYZ=< +M-`Z;W"](WPZQ3M^Z_MOOTP^'.--K:RQ;-Y'#ILY@[!Q;:9EG]YS^WX*#+2P8 +M:*0VN]>!1_6C7/^3Z;4%>0!"89F*[5Q(I5X1P(.I317OY37L"@*6&$"3CHE< +M!C._12_`<\LCG+_^F4'SFF'6U\FY%2/N@%^ZZI[(;GL(^+VX&JO\D.DNP'DY +M]R5F,,&$7B59.77!5' +MOXKL`)7(8ON43XN#TIF80-DB-0*L1?6YL$=9%)7>+.%M\@65 +M#;J#7$_]^+3/A:M8+P1_IA$[H$5XY:U5K*WE.APAW\NV>.30(8;-JB'1LYNM +MQ_>6J4.]]@N=$T;0UWG+0>E9J`#NV\-MY_C<3^5#&E/"@+&'ON^,]_I_W_9M +MT,8::D1?KM]\-&=I^%3S^W[Q;"M+SX`&4Z`;GV2U:+PW_L1I,>@'DC$,%4.; +MB"@'(C]OJ$>QZW$A%1PHNN1PK>SE5,*/3XN?JT'$J6:%D$@H4.\92_020LQ& +M^KE,^465S9-!^QA/:]423X7QK.16>/O8T=LB).RO%Q8L`0MH>F8?QYLJSX6S +MS&E@@SF?)*Q82_R,>)6%&IN)F$0B;Y&^@$SLK"#ST;JJ&53<`XS +MO4$#\3FCJ+09L0LE/Q,)%WY4. +MB)G6PUQ99`AQ!=LJ$.MZV]6NW)FYA$C93I!M##Z<0,P.?;S5_SC@'OI+8B\[ +MVT$;0RBB%<0&__:8`Z[%8-"R%SBUF3%[U"0A[&HIK2F(`$0YRU,IN`MG,$5$ +M36WU^N60X9MH^K#-1A_N#V1%_EH(WC[65;-BA!!&(L.\9A"CZZ[(?+-?KF\?XU\&,#S(M;#?&2QF72 +MQ:#R2Q:"6)*J&5J8-885H11#^J4"2V_>Z+*"/^N"VQ5J*?`*K)%>;UW/PRA" +MF)AXDMUXD$GY:!W2;#>-5&IH34ZV>71\3A?`>I0LQ5&.UA:9:O?J4#T=U!UR +M!%T(`=(P\>3(*!.EO;7DL$_`@4E1T$AJZ0C/M[Y;9C2,Y +M$5#("S\FK2R)&WA2SD-'?B%\(D0L"W-IC,8=I3';!8)G*I,[RBBY$D=<&6DJ +MZF,#>^@=NMV5<$X56">4I-27F(3`42NT.E[R?!/AH_,Y\@7]+_?JLC+>) +M:J]&-:D_'H(]D/YJ:]W1YP\OA/'3"PC2E`G&5FGE&EI#R]ZYZ-'N[W55)D9Y +M=_N$>,/V*E,C@68U>`%]\/ZJ*9A9ES5@8XVV.2AI.%R!Q@C"1\5 +MDQ?#OQ/M&_(#<)JW6[#DE2`Y]+E@M`WRWPQD!'"OP-<5H\ +MPOZ%^E1KJLIPAGZ]+X];4$>"U@,-QW=^;49N^@WL^AEY)@Z/FG.ED[_YD&^Y;W4HQQB)D*G([S\M=R=B+1`('5'M2>7.IK +MASGF$[;PUDXF8P788$-Q9?,M>4 +MY4^D".K5)?:;1@%#Y*!SB+G@-;2?(OE;B;:/2?;C6"'D.VR'ZPRLY2$(1-^2 +M_\?<,P*G4M681JF&4JLGWFVTXEF<7P\5V_Y;Y@"`B0A+I>C`(P[A6GV8T*<` +MJ+T>J3^8Y8&+:%WXX+U#%N+_5M-)+%4NE6E=ADH__$:X34Z4ER7BNY8EIM:V +MK]?N!225>.NHF?^6.&_RA?""B\F^:JCW70UB/%>?AM0I#<]@4I3UR(2\MI#' +M!S9?ZM?;A[V%ED>O@HP_RG\Q+X):A#%/.S^TM]8S7'LC>0"GB;9"*\-F9P5#"8GGG+]VJ`DD>6-A?\;`J +MPF5A@5*21/H%H<-/DX*+Y3K53M()QI-7]:KP9`A76GA$*P\6`9:GX"3OP0RF +M[0>A/O^PX6$UTCS[VT\[L:Y27"5BQ;P7#_^9@,'\*NQ\"\HZ*;)@B5RS`7`? +MVY>YG(8[Q4QA8#X2*1<$/=;U_WW<[R=D69XC!9(K,[JQ!C8SON2C;]\3]/2C +MDA6HWA+P[M()I(GNW][T$9Z$Z"1\[E>>J%B5_:"69WTZ:T9WQ!LG?V9&OP\/ +MS6:0YJ4`BH`BYQ&0"(X!SN[9+M748`FNE+Z51C&'-&#S!!!UBT"[#HK)C2VC +MB@E4PV9)L?;K.KS3X5P1-ZRZ#6IZ34RH+H.K].A@[.!-I&K\?&QQD-@*-AGN +MH>?-.CVW\/Q=T/KDOW&`*@3NX8(2$+_27]Y(-:^Z%LPGR!W1'GW$%U6*8)UR +M.Z:?G>'AU)4C9:^.KB[]\?\V*V/L"<0]X3.^1A, +MD4T!]-(O=D5>[D(=);/`CI8TAP>+43B:2L/BH_;<'M:K.9K$&O'3BS,\SUC- +MB6^!'#,J7@;<^QA.IJ`?2)$-25OB35)VC4J$/CH\6/`G!F,KD*TI#P*WT/#^ +MO_JHLX'A04UT6^;&,^A%?/AG$&Z^.@6R7_D?TI=2R1CTXICD4<#-K;W'F4S7 +MG&^)>:!:HFJI%9DYEXP52+!<_F30V40*4U#5WJ>X-^C2T008;ER`O+,)T3`\G55B`JMD!1F_;3X\ME%U3,`=$&+GSF +MLF*5U$^$+,$G*-U/!5-=3`A1;]H,$EFPH%$-]$*IZ*].B&:WEPF@!6YWB@LB:K?<6 +M6Y^.00HP[C8[`PKFY;&A\BY6C05T9*+8M1#LN47DFP43%LB1$<\Z_SD5FXF= +MSO-I-&%1^670F[+#5VFS1L&)W#>B?WM@1\%Z;4OVU@O$S'->1$%^L63%[O=V +M@_GNZR-.&/=HH>P;JF+`AGX1)Y77V0IO[M&S`M2`"*(\U%0#_3"EC8(FR"4U +M!FH_*3>PSRC2(P:E>4=CR(;MI_+(/\`U\']J\#4YKJA(JW17;Y!,3XYO>PP? +M`-[0;YE`E?6MM[+U0IYV>!,;^-(1P_H`UM!#./E;X'#J\"DGOCL*NCI?+`IQ +M0ZK7_H3)H#E\;CL"$<&C7?"D2//F*8GRR[))M10HO:,!S#W*_N6[Z1"@0Y%& +M\5N7;NNB2JU/3>/7F3073=+3A'P"!--?AZN)_?5RYG1>@OC[\P<85I>R1?*X +MF/IK;JBM+=)8`&#'HQ$&+Z)@X-P2K;`N]@;M020U6O"YJ]NU$&M5X-C[0_?QBW#S +MJ6)@K6_]V-HE^!:,19,?""@011-J?_I)6R&RY][4_'M+O=9-%H/E%2!;@Y]R +MK0W4T_;E4&68N[UV9SCSX-JV)=3+6-)RT5Q+P&&;2[I\@"2IVVY`!*]L:0V, +M_J2XA_>,W,ASN*Z*NK7EKD9T9VEL"V$)N^H0]2^C"/YQ>R6M6$!$",9,"J2TH`KX)=Q8!>?K7/9M8",J<[H +MQJ([O]P%6Q,KB#$9`A=W;MV(->V`Y(0N2),1CH(CES#0KATM-QR+O>=&M*%N +M$.@3?D$[PHWC@59Z%[%`#3HP"%P\@_3P]C@:L-;[WW:\ABY_L<,`!" +MU1S[8FYQ*=-S_IN,^<">'LIXU4_DKDE.6?^+>$DES=9>+9K6HZ3^B6>)6NKN +MZX#%P$0S]GL<,UPXTHYR8)6ZTF(PN&D$T"!]IRV5JYEI,&>])&K"IX#,9`K2#@):1I[.K$[(;CM#LZ77>% +M)6U@[1B5CH?(4$TGR:D[,91_Q+RILUNB65QY+"/=&PR)Z(?I!9F7LWQ>':6- +M>Z@Q='I%!"P[@Y/ +M"+_4]0:%G;O=WHR[*ZW6D72(]4(E_[5K8$(T!"KQB4]E9X;\"\\5$I:]'X)N66P7PD +MD4KO2&UJU,@3]X$^K%D;.Y+$.-])$<.TA!W,)DU8>$:B?YZ[4:N+Z10YA%M# +MDRP8@`.H3'P(M'5O^6X`1;8P2J/?9Q4^4J?4&C_D^57A@&N"+AE748X`R/Z! +M;"(XT5"I0&1GNE5OL(YF* +M\[+3&&85-&DE/#Q\O\"CI'Y)`;P4@!EQ%O*VI4.CXL3UO+9R!H9'UYD%ICU.4'N%GYTQ_J" +M(P[1+[^HUX8-9GZ,2H/>4#'5':%6]2)D>MR`@JG$"SIP$/!ZUC>]-)UL/'KD +M&>K.9>!>^NHP-T`IO"A*>)"!(DF%MKA=YU9[K1':=3-46?.M7*(-+^>R7^]& +M]'HJY'7\+M[%0\TJ"\]P\4A @%Y5S\$*])(SG<8"J.1_2DB.?]HESXHFOP:]V$/XRDZN[* +M<2KO'+)>B`O8B6MD,"66+'N`_T3*OXH$."D=*-3AR,$^Q3KP7'%>&#AB?/#0 +MJ:W2:[QX(5[8>EG4BV>_31%I[ +M]6?=@;-WTR_0L&L7\KKCB;J":0?!=]M@51[#MC09JZ`IR@C_V%K[!I':@VQT +M[_Z_R;2UU47,QB98NR0L!HB<1['H%U/YT73[WY/"]A5WVYJ?X>GO35"9[6YD +MYXDVU1)EU=BL"Y%UY(&P'J1ZDRQA!JV`I^!Z<)VM5XOL?/H;_?"%IG)4V`L] +M-JT$QTDY-U[.]R#DY`Y+-JM5_E?4HA`*FJT>Z:/I//OE;LW\0\UK[%L+T[&+,= +M%JF65!YC&U]RJWK-_\7U8SH:]HO*N`RKF2CM98%;'_M]&XNN-:)K*?Y!2[(5 +MJNRN]5_,1.9F5#'$/?]DA04"#P6YN\"ODY9KI[^2+;VEN/VW5MW$W@)+\NJ- +M-'\(-CTBTO.Q1JA9M5+?#9&.PS[3ANK*_0W=P$MC%$^` +M'.T(RI^V=`(#G3PJ^S+4RJ(TP,'P[3!UU[4P33SR#&7G08>'*#[`^'$86D@Q +M*6?TRZ`)@9F4"%//AO=Q7A5.MNRJ^"=1.+R=#N2=CJ9H7^Q23*:Z)(/N%>/$ +M=>O1_/@(OP*`=G'['9=R0%F.^ZYQ9[+/V4E:$5/:/#7J;LPRS.3ICII7"-$+ +M^>AAO)3['_!^.,Y$V3[@93G4E9.I;\MIRSXL\%)=&G^`7>Q>;PCDMK;?\(JY +M73Z_$GL$H\V!Y8:8P9!'?9C.@]U748U$=QSO=C!BU/SG-0Y*%ZX;CD3B* +M$#-&,65=W<>AM_"DH%D`>NDX2.O(W[:7Q]#.DQ,&5M*RE-6UY"8;+O,T%(\V +MQLA`Y_BNT=!^BR#O:+1'X\T?,E*0*RWO#`]LS8(MU<,#Y?N:N*77$LR);:@> +MI'N6)Q_[J:/.N.>VN"ET3FHH_E$4]3-$1_!B/`7/%HT=Q@L-L+.TE]ZTAE'# +M50A@P"#$+#3F[*6P#J4P`(A5=KYZ]NI"?FZVNP0FFEH/K4U<\M660'<,P]@! +MJ?%J,:?^4<"1>V7#%TNB(=H?S1B`(#`"5J*AK)$[`YHM=6RI&?O7<.LO\VL5 +MJ$@@FX756F2R!A2HJPQ)Y[3"-0P>*4/V3L6UILM]7OR>/N#*8M.:9KVC@Z6J +M"9<@LS:=V(_X&#(XISW,W@#.B85&0K`0PSJ6<-O +M.*V74C7I[2%99/8TN6TK71;NO\[WD&_1+C56&BT)>MH-9;:_XA*X$GJ6]J9A +M-O$X>Z$511-B78VI'$E=-(67S8_(3T;P+25/.N0!<,:6%-97D+B\I=6=_?UF +M8K*/.3%=OX*&E$ERK(2ANXL$5_V>N[MPJ>C[RUZY!WM:AVY7#C^U?.@M/IN3 +MC?H2[30FM$\5T)7L8*)PQ/$2;9Q*(OL)M2'$H-3.F`*UZHP^/>87;$$XP&34 +M_5U)9J"#Y?KV:(5!=AY%FZI:5S4*&$5?RD&Z9Q08KY#U$>%YE*LO-8A-YL%2 +M&KZQ["<:,;?J(U85L7T6N6Y:VJ"U;GWWB1]TGWH.Z=;6Z6,(KH<\$PC8TFS# +M%XLM6$ZQ]_&SP>%_4-QH+33=)1LY6()WXX':T,4M'*NXI]'-S(A009HDB5NH +M$UO(K,S&8-Q_5-3R"84@TB;U=X\*?R9*7\S3>B%0BW[#YF7Z6& +M*7/D1**S),QF[XD'C&XT$ZPB>>WIV=4I24O\/M_?/SX1^[MM1T)PN=\"+P7$OM#.KE+D#LI>$2\ZT!/P7CK76,#<-*C)@HKM^-;P +M9%'I?"T/6:R0ZHE%59[I49; +M3N8CQ>N9-=6RH:\@O238(Q=K01LT,IF"KT=H^`K!9$&QIP]7F!+6#]IUN"O# +M0C5"0`A??+@!YAKGRP7&SF9>01I_HJ4&3- +MF)(5&Z43"B"[?W,!KV_<%FM42,/'[Z?$-`XXHX.ALTBOWB@:ZII,9TL2JNDJ%> +MMIYH.#V_"R_3B48T?MT$LGF3@`;!S]D>G>5FLNV@)BC>8HS!]TPAK!:)=&73 +M`HR1*WJ_KOS&%<*!,/7,&**.L@&UG)`UTMW$QY[N6'3XZA07'7`NJ38$\OO_ +MM3LJ3(QNX>?\`9LH\T19'CFN5=J)YF"R;%I'VX0$(]4]N>LA);TGVJ'ZJ?\& +ML<)D5">A$RP8(#MVL&93GS<[$JO7[_BQ*,BLJL(A%F$=`U.V:?TJP$N7,9>S +MU/V3%9[8I";!\H$L)XQQ7M3\+!3T>>*Z(?U:?])/TZ\5US&.`Z*[G>SXI(F+ +M-&Y]/([O`F=GFJI(LD,,A!Q7YV="5F1I0U&\)+1--D-D*8I6I9I*5G-+&HG4 +M"U'F_WWU),'<4WI1FG7IF_12H+U2[[2QJDLR*[EX-R&*[M`+W[E-/I8XLT7U +M5;>Z*\3`;PWJK\%7-L,8^+7GCP=_;Z+\,R;#+A[\+ +M#I[EDD-V;89),24+05$5.W5%;0A8D&BZP<@!@UE1E:+IU,4AC]PEEHA__GV1*TU!2!M9X#\8NC&4LP0>VS\30/JF +M.R#$/R32E/!I67:NBEPM$(8VJ1J*T=L&]B"PBC:6D0Q[1".`I"P.R/<80JY9 +MFI([3FNB*_O7"U-Y?E8SUPLQ3&_3SV`M&5U`!7^LW7TMW*`;A%ACRGXRZ6C; +M6P\,3A-36$&.OBA]ZSF#.!#-R$S9WS+*>^^N5_9TXV>I65B.UCF8GO>2#;^;+,]EU_$F!0NDED$3%*7XU,;'VV:\\GH]$;]90"3\H]-43'VOM,, +MA&+*0AJM70-T_I'J6H\M-W+?5,$XRD)I?$1D=9AZHPIQ4J=<>C";&- +M`.B[:'3Z*B/P6,2FVD,Z-C>X``.F\`K.1[/Y\;B_>7;K[&)*`QXQPIW?-3S:T.J,4^>"AUI`3[$JX'FWY)7$9$>91BG['.D2Y-V%J6:O`RVM4QP]""'K?O!)C7E<^@^;4 +M1$7G),YDF3N'U]-G'5?3G$F9YE/6E +M?*M'@6NOFH+1*`DZ)Z]64%@5S#2F]8)$]/7G]DYXJ06\>[YS?'J +M$?:PL?Y63>$59($8A]:(OWTKNB1']$H:A$5XXN@@@$,NJ/EZW;`H]ZILI&0S +MG11ZS'>>W*9\5PHA9;=4P@0:Y?4J>CDJ+O^U(T'4\)CQ>.5-F#BBH;(U.4#J1(;U!0MAWKZTF"B=^M"9*@ +ME?16NFN"06;08(?J9.,C<-R#*+2A>]*;687=\VY6MG8&H6!091C]8/\0_#Z[ +M`%1$';>JY%7HD>X4#SG#&BXK5`5]L=:FS7^A!@/V&VNST+61,:X."O,M=2>H +MMQORH/)(T`OW0&HAG^2ES-5;:QB4IV$W,%_A)E&*LZQ_4'1*FC)G[WCU`SP- +M.Q4=\&;?!3)L./UE`<\8006#I='"1\B<"]4.P`*G[P+^&CYK>G#/%[D#D^#X +MT7A%>TOVH`!KO?\;!BHHW<7>Q]JL4HO)-;U!'@]K$;U[Y-CLV04T`M,+Y'=' +MXU%*.>]'FJ:Q0=.]3;V,7)S1\K,H;B0D +MAA'@U?D6N'^CI3D@>)1![)`;2"=_!?`J3<`@1SZ[#H--/(CQ:FT%5DA/M;.X +MW2CDB6.V$);X$"XKI+9N\UB[A3H^$7*1#?7#+8ZSNNM>O76],OE';F8;QCMI +ML=P%7\Q3G2WN9U?GD:4RD!9C:PO0RJMLQ;Q#8\<^M(EU/DDK!V7IJ]Y=F\TJ +MQ)U6?#Y7N^N/U9IUFRYH4SHI#!(_NKZV0N_+@H(.X.<*&/GGD#TW\XK?/DC3 +M&BCS8@Y51>5-Q#CXQ`NAA,UU268<"'\W7_ME\X?H0#NCS?!PJNW[%DKFT@=D +MF0E.?)SGR"S*"O)\MG=H3Y8&!;1B95[O]IU[&"<@&ZU)?5N;G_KVCM_9A-V0EA>^ +M)]SK-:N56YZ:\.O^&0=S'S:^<3FFI2$^ +MN=-T+1T*W>A4W0)^)O1[JH'>/<8AR`G!6=Y,C#Y(^)Q9"GW`HQK!M^-^%\:U +M8?FR`L@YI:E*[JJ$KFZ$-,MSVUZAB2\VH+;D[.S:P97/[Q;.6`")D#U`F$VF +M4+WD*BW$>K\PDFRVQ-"KT5/HI9T\\1HD5W=0\A]`AJB2U#8=X]!^='.76L0# +MO1WO-,^CZC,=%6I6O!PC#%^!XADWC7$C*DQ7G#NH:#]=`JSXN9/_]$C4_=0, +M#0RA$7_7B*07*0]X(&2MI8R_BX,G%@8>_-I>><-'&OS[=W#3T1AOL`37'&=K +MS!-N9:5;*/"-`_$Y6*,!>,+'RL"(^]A`8'DU=_A`G^O4*_+6%_HJE*7,!OY. +M63/2Y;59:,8?_0$*-R)PM2CFRPRUV"40G#GT+@U3.20XP^!-AS`$\A$")/X/ +M8Q#$R=4%]/!X#IW48-[69U>?]\A&\D6HLXG_+\<0'L2>A;#6\H(HR-$%_&-` +M=S>>05`P*?1CHDGB\P;CQBQ`)%\5!`"MD>]9:7@RHJG(B$3F(EY&NK>Y[O8=J"35-C@/R:RU^U>1RY$R)=\M1* +M"BEN2I$3(Z$\C;:5OY0%K<94(D!6N(-=Q/E4V5D.X"W9799RK9R*3*DI'^/U?CX[+P=E9] +MK*UV4RY@YBU[%S&N>474_OYKVSIK7HH,3R;*0P>0!X:!_)BM)#:W10>.G)`I +MS=S$+H!4#OGFAC`T1SL>DLMY%A-1&$)XWQKV +MH('G+@ITFU6*A+4-+V)8,>FB1O^SQW^2B_'O+<*T3_]]$[(E8B44&K,DNEH&5E +M9@3>!6'!MM,&^@>-V&S.;)7TE19EJN8<"Y.V`\+5`D3+VO6:9D/?446'ZK]@ +M5-IS-?M7TAB^*A8!"MBSGL98SO"!2"#-BN!PYE;`_S1>+W;)RQYXC=P7]9?G +M-36!M4U5-[L<1`Z?TZ9D[>>)S-!*;C]NXTI\ZKK'/!"",:NBD1T,B'PPGP=W +M=ZY2RUDYQP)%:F^1I!VAPIPN?+M?9)/E`?L'6AHD`-H!UUWFVR7:'"UZA9&U +MXUZIK`7J2^(1XO-1:W7'*51/L0NF";HE7?EN.=I*MA1'P\+QC]:D3T@*6SL5;IY8XS?,"JF-5%VX`T-)3?S_CCYFWL]"1U^.BYK. +MJTY=]V!,6RX +ME'=91X!TJ6E'U-XWT/1B:B!JY0JT17'',74,L*N<_'16164X97(4W7K92]C8 +MJR]ENRV5WJ80CSDB$?)F*/P7'XL*TYG/XT,T/A)<\;Z^P1_YD;:7`CQ*=9&P +M=L3\LK)I<&WF/H2-]%!@)%O<_#-J_Q;%LYGE>SSF#.QUFJFO/F`/RCHTP.$O +M_BI29^2&I=/2YO*73PL*5'YT/-?IM:P +M>E05"WF>0"&`X\X?_XR[[20TJDY5>HWBN>&K+$ +MK4B@C`?]A7+U_W6RGE)4GE^UL&:]H6[Q<&$I2*-C^22"0OA]U6TM7 +MG1!JT6Q)R(71E.:D\Y=!])@Q\JUDH:*P#O`)B**_HHH"+?&NLW<,M!5U*N.< +MC22>[ND[!DLPC+6VH>M*&9;5I\?4J)9)05VW-ZT:#V%6`OU#9^%>!+@_[OMZ<%'_UC]>I+K8V-_7-$4MIZ+P)_:P"'5!*=IUW603Z> +MO3._OD;N1W +MK(`Z:ZZCU1Z*KRTOJ%L[HO-= +MZ$IJPG(Y7O.9V,V@B4B0B&CX1NA.*I@@=UF@60B?E&W,HIF/*ZMM,M9P+ +MEDIZSU_8J9$>]A?CXE)*4Q/A1B-_YX$,+%F0*N)">FDT`XKD[UW3EB+9\.Q` +ML:?A`=/+WS'_LH64T&W\*5FV:DMWU6,5KB+U);>W2I%%2WCS[&`H(* +MZHA^=OX+ILIY0"R)<.%/44IU#>IX+(Y(!=Q<-CM=;3%=JK0V +M@>I0TN*$M01[:P7.`>8AY/6OTD@>[Z3,?FM<:3\(#1/"L?X5+]LIA7UF//_@ +M=N-,SMB?]8AO`I1N7)=HY45?-^^L2ND?SUQ]6!>&Y,-V@[L8=[ +M-.2,BTS)KH=BY;C`$$PV$M#SZ]6:I\GS*^[M:C-S/ATB7W@[:A3RVOBLJEK\ +MI3[UJ[)#@Y#]2WY$N8S3:I!.(,(KNWX\/B._A+!"U@0FD!(9U:[FLMK_\TI_ +MW,3,R71T5%IF-?9Q1D8O)4,\TOU_NIL7Z_#?^T<0N6K")]76NFJCF7L+#:ZV +M`FMWEZ6''KA6-TS7>\>R[%W59D0HFZ.VQXK.IF%RL"7A\2`]8P.<9;_:8S0K +M3ZVJ0/47C_>Y9?6H:UE_#=9'*?:HG4ZW3_5A.9UI3:=/5RH4T7/$<.%WUHCX +M/V7X%TB=F+_V2I&IHL3`;']3D@&;U[IZ06J- +M0VTT=QVXHL53QL)QWVG"3_`F%8V()KIR$W):.0*8HGTB'?X5]Z@"7W])^E>Y +M#)Z[>!M#_^88A;21L#3RS.^E@1I-JRC%`H6A*Q(.N-T>SQQJ@[G#EX(_7JO& +MF)]+>=0Q(4H[472KY<;\,'$/GSV3=?*[IL4^]NF5/98RL*U3<'I=W1DAL6OW +M"*3KC*7",TD?#P53$/SE57!J0L),!=V!M`P^XURVN[ME4"J.X9&8MH>A*$T@Y_1+%`+L`38=J8P:CJ1$ +M;6L)D^[UR^N8[F7SG5!^-F&DCZWO4)9%.G`L(6SDRU%G$?,;39:9'='W.<[SZ#&H2R_.JG4/\ +M<[X]K6OS^A"^_8'?/G=A/!@FWR12!=X!Q#'VC=V8Q#!H'FDKWUJ%7A_Y +M#=5!167F"G#W*_]%=@(-PM88UHV@OU'GP@!,;<@C,[N!%-)A/67"L#V3!G2' +M@SE?:#2:;^=%2Z#!K1Z$7O"9K`VD$'Y'1_I3.D!*--JQB5_&E?O1-&ZX1EQM8?7S +MGR=B4?,FY9TB327GU0E_3_E2&A0=3#T'MW +MMQ!28D;9D>LP^TY,5*O\XFSZ0DK*YS?F^D=@ULL6PXZ]ZDK;=?1GOG33SS\2 +M1Y_^>`I`THBUF;EY@T/:5`7('$03U34X,RE/W.8SS;7R.AMF!@90M*XA>:7] +M)77:,@T],IHRO#?O`.3OX54E^;4C[Q;AQPM/-_,BD+;'QJ+C)NZVR'5/\KL_ +M9TRSJ.<>1\T@:$M(BYW1.T$597W^$S<7K=FD>L#%7%1P[3^3S)+4.-%H: +M67Z)SK"X/[ZJK3Y'%/_CD46;G1#XNT4`[,[5GD#\]&3UD\4\]_YE^.&8CM2` +M!N.QVO5G4FJ/8%N=;-`RG2K*SE7'KRYO-1*AA>8@VX;JI(EPXZ.^T_F9J[*^ +M=:#XO\H?+30@Q5(5)$[`4-R;C.;%_2&3<$$L^+1[_UV'.LN:&J5\\4OF.8$= +MS>$P1?$-=BCA1BC[_BP-QKE-U%"@*O;NE*)@$?B8E^"M67YG,&3_9N,>0!33 +M.NCX15C3T6G24,1?VY5RSH5JV'''&1DI83'Y:P[RDH:HCZ/I.VF7!F#V\:DY +M!0L'157:SU"*T6F.6V""^>P,\)X;8@UBO$*]_@A*LGJ%@N=+6>`E4$*>-!DN +M<)2L55=H*,XN\I7$Z9CIXO$<@;)3HE(89%-+$O\LW/%K?%;F*%#XI:MA_QZ_ +M$K5C.W(>H+.^XZCUA#%B9^J^8Z4=F=&/$#ZLE]8>4X\?479N%WMLUX73N_S/ +M]]"4>!(M99"U)0GG>#/M'I^9ID/"%%2$Y.PA_#R#7[1(]*-PP,O!!W[3E_M9 +ML#/>AL4*!,XEZXCFAX]E]02S)U(FHNY?_DM?5.VIW#M1^&40BQBKEPY?%VB; +MDE"^&5&2JER?BR@9U,_>C;4K8!9#C&=H*U2B9I/[Y6&'^*N+ +M2T3H-+$5GUSQE(&="$CJXV,F=6KKY$FP1R8\HQT8!%^BTYA"NY+N-3V_`P"1 +M?IR)ZE25:I<@![%QE.$2IO7!ZT.AD..\5C&CU>,C@!9TE;J$TH^X%T:)K6E- +M3:?.@>SIWLP"VN_R->97:DY$S#AX-D%MN-PG*%49=#B![*'+'GHJ +M=!B/-4"8CIBD?T#N:K#VU6DR*"E/9T@1#[5U2_F!]@*ZEJP=>K#4:&^+F2C` +M*E+8PX6SFPH4/DV +MD$UTCM"L,P:Z.LXSHO[T1A9Z-L8'*;-4H3 +MC,.(,GD +M'W<0H/!*!TEQCZ9;0M`/").,!+H$`;K>02&#TC5"Z8=BQMU%'`8SZI6*W=XL +MZO#FUU:-?P@D=%M:SBLK8:'\EF=Y@4UJ4D8MB>1FLR:!F2X^KTU>M2CVS+MF +M)L55;,$"?JV<5PZ[@"5M#\$6'\,ZB9QH]=$)$?U34MDF?\L_+V9FT3D-CSZK +M*!'J+=/""JYAU.N05;/EIRO:IU7"@&*]LG,3?LJ37<\V&]G1L%/!\F":1%S- +M9U5&4=J.F)>G5FJ+(_]E!15+T.9P`?3VKX=PS,Q4ZNRN$)3A?!K'+Z$ +M-UJO97,_3L!2&48)+LK6TJK4F`#9=F01M@E4X-@W`PG%#WK.=B7&$?2/$H,[ +MX2RRHD`.9Z^;NITF'<_VC!BE&8?GX[`R=OY;/A:8_[K"NIIC5)ZVDY%UZL9, +M9"(OD&5B+R@_5IV,'0,T1@IWQ3NS5O!5##1:^#B>?:JBA2DM=1X!EPW[%_&[&<:#]3ILQI,XH+_?^OI +M>G5IZT-Q^G``KP="5!(9B4U=-O41C@#_'_V)A40EZK7R&(&&T]'6)8<'U1&YX6.0*\7KDH +M%H&5.4A6ZA3,@$16'=^^XX[;P;9]Z0"..-KA+J>@Q5-(K3`&T*]T,5WCO\A5 +M<\N=)J<.6`NLPDNZ0P+\9<`8(+#F-E$AZ`IZ.\E6%5:^5X0X=7SUA!8LR(ZH@'Z>* +ML1H[&9"1B-6,!C)H]D\H0$=M=LI?Q+JL?1CLO4@P(L#WN1V"]PN*A5T +MHP^1PMR@VOM29$.V\!XV:30,7)0%ADM).1S,P=;"R<+(M9.W3PYXRYZ(4+(7 +MR+XU/J#TL!O?>_[5!M>43Z*^PBGN8'.`&Z1C(!"6Z6<7:[W.4P#KN7>)Z(CR'0A>0ZF0#5&NET,@[S#H,`UA +ML)XAW9KJS59!K?K-SFKT7N?V%`"G(),T,T3I/:V'D:AEDEV+^/H^%648AI3^ +M187U:8,4.J>01%KP[Z;##)*&B[$SI+\S+APUF9"G&>A$)>'C"VB&:?]' +M-,UJYRY4-^1?Y_CN'X"(I.4RF%$UK#K&9C0Q3-MBC3VN9HK(7:4Z;2O@N5Y2 +M]L([S1D],!T3\^[(BN*WDM[MS8%&D"I"I7BD_@QKUNW9U!*^A<%!N6+\5_U* +M(.*+27T03>6W[F-5_"&_6,(CE+SN9)WP140RJ:LNQ1KD6:)O6![/#(QO7_P] +M;[_=->M:521./7#W#%0U=?C84:Y?*X%+HA"7F*]B;KN0N#!_913*`^_>C>JZ +MG''L::P?WT50PW;8Y'QCDN0Q,O4$KQ=\6F1B=5\Y9QE.A-CW<;! +M=4+]?/IS:]GP&'$@Z,JT-GT,O`+T%)*YI@HF.:?_HID.`29G9-`D.F,O$?K. +M9?L4R`7I()KR&FA/Q5-B5+OR:QS>?-\DVP>K>7F2ZH$6R10XE>O]NC=S2:FM9 +M]M)7_HGG+HJVQ)!GQGY9^F23.WG,R^(H[GZH4$;_35A=/BXYRM!R_M8TIY`, +M!*6W:@:V6^WG;C79(RN37F0/0#B!'AU.QW">,6MAGS;@;2=FOXP5^K&4MW2; +M]OX0J+"D#N<@IKW<^U6A,1>,:=L`S?)&9>H^/\:-"_3>"Q\=J$GA'#WG4\6$([`QXY+8=A!2;MZL0L_^(V(B;'A4"'QMC8P0Z!+S@ +M.2G!D$@+@K*I0(_8A'HW60Y*8:/\D_`Z*^WAZIKHE^7AD7J-R%/+WJ0Z,5!X +MVI[)8,$!(,R*O6,O-6$[5^Z^S$,C&'LY"-CS)?P02+[;-Z<)0>&[>++$1)0+ +M_^T_C[O`9@["&(@YJ?#U.J#9\`MITTJ?AQ%=QIG_8I)3)VD+$!J()\PL@"?W +MJJ3`AH3:6OTF='FN3M86`L".X22`\9/YD5!3=#MO\F#6<=M>DLZ"/:; +M@NG7DVPX+=-ZR)'2`0'[7(=.,F&.2>`(FDAK-Q_M![+YZ"HFH4^MH4_BV^<< +MCI21; +ME,8AR']/J386;0%VA()900YT04%'X'D:3_ZG+(6KE#X4HSQP5*(#$=#PN(R2 +M,&E`M#8%P]ASO^WR6Z+EN#X3?MDDJ'(R1V!P/.2OFSBC9RX3#`T8Z_R.8/[S +MA8\6](C_]J_@G&=E_UD3)V)W+]<$B-O4#^-\@U664G/_KV`%0[02?B8EMYC7 +M54&OH%=PMZHVE1PF7YD[X5;Q>^G3E;'>(3_#&@(16C3CTAD&DV-X.R$=Q9@< +M,"/I*6]T5-1F%E.I(V].@K%?M9HZ?\%_GP-$3B2J6&>D"VS]-"-O%@0Z>HUO +MH`PQ74:/__0\SUL7)V>D:IC44(*6M^TEAI83]7%2B +M1D#>3@X]M19P1QWGTB.F0*EH*C==IK[U4"E@@76F6(PMOJRC^<'5.`(!:HSE +MB,]6J[#YP9I$OV7._4/:L/U(4"V@<'7!M$X)BE,XXGA=J2)>I28ELG?A_?Q +M#8.Y^.>;TI)$,M$9)$C2U8^M!?-N7WKJ6>J-4P5#)UD11/$%X0:.7UE'[MEX +MB'"CK*.Y.S[%_LC+F1P[53%"J29!-S,/H"QE/C/=A9((YD*-;#C5BSN[6]A(M"T)JFH,YT*UEC6=C9P=AD)[I-!RZ3<<6?2!?1\ +M.[2TO.IZ:X]-.>P,VAG(;`Q7+X7UIW*,.L+F+%%[X7\NUGF^&$2BV84ZVBS' +M<&XOT,AZ0-2%T7%:7YXZ'Y\^I(%YT&0X0:D])ZMO(GV]48=Z8@FI>7+\F9,9 +M"_UF3E0B)O$XCPASDF$LU!V38R#B@$H@A:I$SG +M!"E44SU];C6J3D8_-.2(Q/0.@B@=E3!YEV-;%?+(9?*S*9-4HR5FHE.\FW5E +M>#S0;LE&?G\^'LK.]EZ?^\84,((8'EJKD;\FH1:&_@S:17+O*I\Z&\J?MT;3 +M#\V5+#%NVP`[N4+VO"[XOHFQZ]6(KH3[_&=**\0TM*3P1QF!+"?(TT*C%5-T +MW?F0!LCXF1B7)/GG3!7U^7J7"W+OPFV#^Q4/YE,X!E:2``OQ]!!/(*(QX=U/ +M4&.[@8O6R):6XUU81Y*!H[RU.0%'%=B,^-*?K/B627J(B/VU#?S*-UHA5E$A")F9;\,:QY9!0_$P>F<7&>_( +MAA/R`>4$(ODK?3\6AS@^D_,0C%:M-^[^7KU""_18'W=TZ>RX +M!#NJEUOBD=VRJ.B6;8#TNVB7'CH#S3DC5`8Q*Y\3<.)*YP!Q-,(LEBNA:`58 +MN>_&YO[.IK!N\"Z[E%Y6CJ-$M"Z)YV;2W.Z!L_0]HH[M!57?[MJ"W&Z#3=3W +MJ-Y27+.098O)\DM6X8#F[[[YF,#U"(%B>JL&5C.\OC_C"T`M*J*..89#IN,/ +MY/>%Y>^2&KR/AW..`F1(P=P^(BEOW5P55AO*T(%;+1LSMR=<1G@'7TG;VIY/ +M,0=II[`#"-?2T#_9CQ8HH;@,\+'#[81*;XCYYE+STN+E2Y6[")MZ+1BUS,S&9MTN&9(X2?ROY6_<[?^JWN7%^Y0I?;Q+08\[ +M=08BF.P?P\1^JV_LO>#T,Q'+_\5=(V&)M8P(`'9;JL;JAQ]DT$+7;B%W+'>J +M[*,HB5D3]M.NEW)T#+*[-`K>?",[_[U_)[@__2\#Y6-,/"#<2#3P/>$=[;@DN(TS>9@8HT96'%*J^YVN[]`/-9 +M&A_]57)^Q2;:Q^2*+$2'H^4D-+U^2D;8/.5O9&+E+)**G`-]LG+E2,GL2TF_ +M3,RP"]UX;7.OP'X?U;YR2`SI0I[\,1Z^J]<;$6XF#Z^3Y)+BL!PEQ]F3\3BU +MD:7DCO'T]V`8CI1TMC\11=/3<$N:2K<8/TZL3W%X>CGZO++T,)WW""]0"[3K +M(3*JWAP;0-"@@S>3IGZR*7F:TJE0]W]D`65LDM4;/A[&SQ850\PO`7^8(_K( +M$J47Q!<>#D]G!B@?XJ>LX`9G&LBT%>19N1=PGX48HVE2ISN@\$3(#G915!UL +M:8&4;IR``M1`[N"^U]+AQ>M21)T>(:P!?FWK@1I'-'-4//C`V&\I6H8`1/GJ*(,; +MM^F<0IWS$!0J1HJNX,XK/$1&2F@Q]'U3^(I/*.RI.,JBBE""73T&X&5"J-*V +M#P,\;H^3S^G2=G(J&3KZ-@`:.E5>8&-4W06VWDO73ISL:F<+PP;?@'9O,K6A +M?3!Y"]"8M8*8%4.M$,=]U6-PO"VV]Z/3S_ZC$9:>'9EMC&;Y%N`1(A65K=/# +MW.IGBHN7JG=.^Z7B3QMY94RV65_L#L3N,WNH65CJ>15:6YLW;8M2M;O7R8PP +M&^`%SD-E@$XRE02E8F3IGU_):[>9SI2<_YL3B7N5"HI$\T9=Q\4/E?6M*[`# +M^*>[Z7%?);INS:Y4^&S%T&MD8351_FK+:BF:5GO$O;I)XTF(%)\1WJMW:TV4 +MCV(#]OB?_LH%%)5B^&"(/YR`"E4)-8^62G<0AU0)EQCJ1#0;U;PXY09U`*91 +MDR]P-,?#;O9%8`5P#:&&YD+GE)`QH:XGK'0[TN<BA&[1?_ +MHQ#?]-JGM++2U67-C0W.X)42U+,)G0`05J@/8'^/G1#^9B +M)Q!#6;J[T.Z.MR^&H1R@/+C`'$\!+IA`E_2#MG;-:)%MF#/$"PRY$="[]X?? +M!&7_95#@Q!!3VIZB]UR=`-0^^-\^^=U4=`2G^(._J_X9)C! +MY#"M:=RI\*\R591-F&T8O(]N<`%"`FQ-=*/$N2AB=7:_I.*++Y(0>MU;>"\5 +M&>(`UT\:'CU=RB\.G<8$9N7!! +M42'31QU,J]$TD60*4%YIE5Z_X*: +M)3PMO/I/.-P[K!_$_:8(AK?AE%L__6JGN]B+'S3FNE^L??TPB+CZ4!+`KXJL +MVZAWOL+[M?T,_Q+??OS\)$Q>0ICF8MN[=21X,UB2(*DV-.]EU7'Y5N"OF=[J +MGLO$P9Z>"P%G!=,TQ.SY12LI&B4I-\'(_54\NA_XVF1<5%FP"K13-3[7K@@2 +M(UZD:S09M\Q`;8XX/F +M^@@EE.E]8M=;CH@0Y%7E\>RXAFP0`%BL*!Q,!GR(?>_/1/7.RIZQ^_K^VLZ`P%407VRX#/NR`+>HQ8Z]T +M76"H^`49M@K,_"32GGPXR&\+:CS1[/8&@>+M^]*ZI"^*@-T(/-/L#F,YBSPJ +M2E8W_?W_!T1,1U8;5.8U`V,3QF4:]SL_ACX,^D7F9&2U;7>7C>#JA+:B[C6- +M"MEH_$.K^=)D^X91&G-\K^L[?)&?\C +M/?#"+%&>OVXJN9980VE?(VC$\\.:Z9YE.2B@+H$2.TX(T9K\-^O""U>=F)9B +MGJWF_>B$X^U#R``MFOI$9U57C4+F>B2)=*Y;NTH@)K,/NL;ILRDRS8J'^U,# +MA?`Y;Y-U/T_=(+,<147BRN/M:;6%2/KI^\&WBM8,E8MN0.Y\@QK?7K1 +M1<1R.$=+(?U>$!\$Y@6,@`!\U\M(F#\S>Z;:]#CZ4K6^ZO%Z`XH/PJ4[XA!# +M+JY!M@,N8E(!IOXE1M:-+F<'JN"/"A9("8NT]>:;D785;R2W@A/(=)SDF5<^ +M5ABND.]/+\^*!1P"W>=?Y=)W(%6`;3>[N5/L!SU@W0EF="/%9J=XGPM3F(D8_F$ +M)U-CQ)M\.=%'9)RVK03S_KWS,\,,A7*L:-JF/<^3N>=V'.P;'\S2\L?T$,<< +MA5"=M:9(3$WZ3WLW_P/2HKR"[QSBYMS7Q__S$&OWVV6W&QMAFE@ +MEO]]D_2K9Y^0YY!1[N<_UZ&B;L:3[PI387@N$H9S(8;I^;F:@`G#G38:42@> +MWL>G[#UAY]Z`U"_7$`[)MF%^]_`'!B)@RE)W:2*#)/$QM.WVR1WW*E6 +M?KADM1*#T;-?:%[LPQ.`-:\LK\&W,VB'&/.+/ +M/JYDHH<-I)>#_!;#QB\2;LAK".S/.A;X8J=9DXDFEE5LR2H_K[+RHDU<7VK_ +MVW[G.TY&X'07#H]#''^CT](AO7[7P=%[U-T0968_YBKGWT3]F4KG?-"NL@'Y8#UX/.S75Q.L` +M/ESZ*47?);G(V<\`(\1(L>D7@BV9M<$>)ICM$/L@Q/&N%XIK\S^PL"\\_&M4 +M$--,]X&)$#-D$1O#8OL41$C]""U/87.9[/?;DU`H3#WLA*^L7,SO.`0Y2T]K +M8((.8-%?V5Y([AG60X(RT=2E&/`$`GT$,1-%+=S9(35$H\O6<@R@ZJ\4Q^," +M.E%H(#.WJOZGE`NR^)!<&RJ>OG'T`,PM^C3%>(6IBX5QRNK)#\W868:CI4#] +M!2AR';4P[=0P/&&:!:`J/5FA)YH\S#,KUZ,IQP*=/41)*'?MW^EESZ$VI1V%TFXOJ\=2Z%G;=&-KIIBS;45($3TY8(.F!%7W9(**7AD#K4 +M"+./?\VT)$YQ".^3LF\?(:#F.B-\8CBKL6]9%H4_"QF +M0Y+"1R:K!CA`HP4%_"HU$:ENK`E?8M8"J3AZ,UE9;T"5(T7*3[L+'>B0X2C0 +MU<^NG*9E]'R/54XR\20GEBOH(?OERI03C^+C^L+T^[LP"3=C#F1*\07V&64( +M//)8$[,GK5)4J[<99+\LB#X\*-UP"3U4V"C58&U1SWFWAWK$.$'((Y +M'.V2ER[/@VQ\[-00W-'@/62(3#<(XL%A:4ID*S*WECXFQV?;95N/\00A.)&7AF#%Y:&]B!S"J10]N?\3&V1 +M\9T0O3D+N-@NM,><@JLS]N@(+Q$ZM=N8*Y>Y9A0@F$[R?M!O@_%QBP;TFKB? +MRO]8N%92$.%7//7ABQ9^&SM@]R*M*GD[?VX7X/=*V*XIMHQX_&+(V^O0D[_D +MH/H%36$5B"`D!-;*P];8$@GZ0L8S2.W&NFV%E*2JNMKK<;&@]O2BN8J5"-AP +M,KGTZ?1'7&#',"?RE';7$3"A6<6/$?KR,1P`'8_&E3S7`;6"S'F/"P#/#?V! +M0`A/GIRI3):B];FO\)*)$HXYJMUW;(VY\)8?_*SX2:+]-#K3Z$Z>D(^PD4E- +MD>M:(363:7M?9''$,TDBR5:75)Z*+JPN?=%*17W9]D!3A8A);,'$USCYM@?.M`H +M/[8@=FH[9I!)`WK')@=JCV`:0:A/(;E;7^'B7+D]&Z%"2T,_01Z6^B!^SZ1# +M6-EWRRBU$4-Y;^9@`V?=S#86\*9]>[(#>`"Y8LUN"=S:W"<34!17/--^3L(# +M$#O:>RAAIJ*>%Y +M>NEUJQQW_H@:N5LX<;\X&'+AT'6!GD!79=/KG]HD[S,QGU"R-4Z,X&H/#5-IHW!YT/F6PG;^E?C1 +M7#-?V5(KE_,0YCT,*5I9>WO[:,@7MZL6&%[O)V/:ENCAZ+"8_0)<#31CVD^8 +MTA)0J?(=3F@$3/PC$>$AT1VM%4^2)B`,=$+Y]I^:%(BR&75*=18(LYLZHP0E +M1AA"HU5#H7?LY:G_+%UVS@W<5)!?/S2.L`$3_-"L/86 +MMMW>TAG),-SW"3/%%*)=4.!<;%."<%N76RAO`PA$2C!XK\5QJ?P?::*<<5@_TE;O@YXV^FPFT9!6[%$B%9W*^%+B4.$PP&KM6*P"+'$1 +MA8/#1;YW7>\SJKRDB'IGK^:1:2SB7$JIJ-.<4KJ2B+M\9!\PVXE](+CYJ[SV +MXGRK,S4R29C"@;T7Y6=>7$;""[W"+*TH8P;%F.R,PY7%L^/E[(@;'N[>F>FA +M)O_@RF[S3N"L_?%M.QHFBUO!24Z@+(Q;+YTM`W+5;D()[)RZS=7!-9*9PX\XPK(QW:CR.0IYAY(+<5&I +MY439''^/+@DQ;)/OJ+=%U[#3FB_-'6@XTE-&A7=_!_\B!T!)\7XAR;`>8$RH +M)F'KMQT3VE>5LG5U6+0N3.:"5WVZ2,&/Q-_*)HL#.8[J??>E``+?Q^\QOPTT +M0]Q!3D7UVROT<0WO-$`L/V($JE7U18@,:DMQXY)E1SZ#A)RN6-65HS-V+Q&>52_W3MU*"\#ISK +ME*6DWOOS<-9)PLNF1R6&<_RP5%UAI%3]EA]K,;E1'`T"!-.18^UJW&4N@HU(U_ETKB68TP3FXWY0H,#OYYV;Z3!1H%3 +M]`U?OD"E,4)?G*1=3M_"QA4JG6J9/SG>D;HHCUUV?'%+5[T@J**0=8[5>([+ +MGLM)+M!!90$4>0SD7#6(,6A12QUR-N]R6'W)B,MOBFQME(-15?SQO;7'#P5= +M_OUW/'#6/QFM0A3@TC!Z^9^#R.#&;UX:1/K,07^)K%@\\CLNXVHF,!_D>I`W +M5]\<"_+392WJ8G39[*!,%8B9JBC,&_0_ZUO+_NMQ=Q5SE+'7JQIEC`L'8D'! +M."-*B$@&FYH6<4,9-B7)5X?Y1(L-Q7A<.=0^=5Z&B-YFELZ[<-NY/W4(+I21(,I![]]\]1*T`P#NP +M#3A7JV!I-K;63Z8Y1I"W7(::]`YG)J4-(0V<#RRRHU&R)38F-W*-'P=^&BBT4D,?\95G7)U.F&CGL1?(+?MME8P6.HW +M0K;V,"!PDI+,2IP>):\X]^T.B0@G#5[N*Q>[FK\UF(E^$[T5V#KQ()H-,B+- +MD+')ET,O+>4FV7OFVPPT7;!EA"/Z^*[//`L''+".\.!4\[4C51!=T%7^)M9/ +MHGUN\0*]_/GPB=`*&4),OC]#WJ-J9,T@C);"!][+?"B?D7*>S(2EE/0CNIVV +M5(;<+EDKX%./@%U%C%!=F?[1.,05\J4&]11Y7FZ8WL@\[`$R8(V"%;5_=,#SOMXG"B3B8+[0Y4;;TQ>._ZI(9CLGAF[%T0[J@ +M8"YPB/D;L28UR481:'G01'PDC&MX:X_FE3!N)QC@85R?])?0/UDV/*8Z&85' +MD1M=N*3#:='-^0>999+_L6J]`5']+_%WVGS[D;RL+5$5J9RW\C058^V5N9$5 +M;=9F5*';K]"GGM=OF[,^JL;/G\#*YLJ@L'PR(`?E$4=YAQ%.$6=_)ETG +MG64QF';27[Y1QC!W3:$\1#5@8^PE:)1S9%=!GU>.QUO!%QN2-@@R1*[?2X=: +MGG>H'S\"N)+UN=I+48KW;?RDTKG:S4KK+&&$L\Y"-E9^3=@0MV0KP&'^&+_C +M5]VA!%"D,<6X&)21^ADA/%17RH3UY3#:J]!"KN<<_4OCZ%?$,MOH'5(O^*I' +M"5O,)0?_O-S7EA8\HS,Z_U+)G5/AZAR%`;1/.E8].!/T5F,J*NQEBC*-]!0'W?#91A(OFV=C?(5C7'NP_])>AMN@P1:1?;I(LUV$* +MD*2HO"+9:*\7\XRP/7^URIFX^?;_Z[>.^&<*PK^Z[9)I9BI!18@'X#/&VAX_ +MA.,-Y$9[,IRYH.V@X*%%W[X8&-,<3)X.A#X6EEY0:1(?Z\9'=Z."8ADJE@YR +MNL)!/>:-\_K8!3Z!8:*KV@8X2^KDU'P%T#>\90TW]EI0X7QZF2Z6_AFKCIY` +MT:F]V1X'O78ZQSURE^2#WV4?#D_SXYRF*S`!J?\L59XF*ZL":H=++?82#` +M!(45,3:@=P`&>#;3^>]&UXE`![Y16/3T:4JG)A[.<=M0`9S"C8+/ +M=>2A(\CD#X:^S08@G;*338X3`X6TK:+M0H#IGR/$S>P8KNZQMAE:0@:RZ5`A +MJ9,)1FZW\URYNKYL8A;H+K@=^MA%RU.;.[1['?S[7V]F?OH9YF(212;DP@DP +M^'0EV)]+2]P>[%\:K"$_MBZA"!6`XOFI:K.W#5)2)+YSZTDP6`E3DB[%&KHN +MJI7J'2;=:(;B9/(&W9?&FB,NI+;EVQV%6A'D@=)(%`'7Q/M*/IT->E(,3_BN +M.Z66FFV-U$,RA35X']C'\W)V.59:\ZMN0%A$44?X"2R>?:&`7DJ=HGQ6,Y49 +M%?-83KV-B869V2<_1"@!RE$'4^V$`N?IC4^Y%>.='J:/_4*&9"I +M]TL$*X1N"U\O*_Q3+0E)#28A(9W0ARX$\8#MF&:%V3N/>::GUV-/PI'=[Q5# +M?9%^IA].$=2'JY;86$FER[X=C%)I\&'U5K^FMQI1=)B91!WE#45"@ID-'ZZ8 +M=9Z_(,\B0Y*(M8U"@V[:U,?)G`D_\>O^03#\I>4T6M2F='1&084YSSDZ#^!6 +M!K.#(W#L[C>**DISG26UA<+3#1VM>GFF(8,L4]`_Y*5LYA.>)KT6R`[]T=.1 +M;>%X-RAB,OI"Z=O/!2%<#$Q@BZ2=7-BZ:<3@/;(K.G*"3Z:&^-*WJNB8%!WG8X@1.(_N>S5=.J#$"0H\>[WR@--,&]RAX-J+AOIJ-4"K +MN3[2$.H@[-$A``VQ+7S)'AYJBGDT]]`;"U:71FIBO%$R`!2YDX5:JR%OEDI$B=0" +M@'P(DW;XGAWEO@9NB&O[P,G_(?+VK63HOV=MTO18$=_ZVT[\`!N6^%YE]82P +M-[JAB%BY^0L^`]E>,>`^YXX^550C-R^%L`^\$BO=T?A@Y?2A<:$%O1H(2\:) +MJ<;G,IO]W+X<.)\$O>X^]SV5E%7<08L][%$/4I$D4WPLR;I%+CCVZ-$;G]+W +MQ,"'V>C&CA_SLG:FP%RY0T..0;IU[MS$!9;+'*9^G*%*TKULH"8[*6DUVY0GO.KD<]JT; +M!NP@7\^M1T*-^$MS2@!3.]73$)CDM>3C@XPP/<;0KA`CHUM+#4M-LIA`$!*9 +M61_F!_E!,@`8>A[!/S:>'7:!HN!NY0M1RJKD_O/Y&",(?T7VB!ZT/P7O(&G" +MW;H!W^\KT`89\GW_++$/+7CI!,LRN$EUD#Q_9\0X/.3]+&W6/C-+D)IGO,6% +M6MF3#,(X\7M/_F4LD,+YSG]"WQ!571FOX5\1&LZD>Q4/#Q_""Y=CAY&R#G*+ +M1V&IKH`)/N@18FQ[IH<2GULWDQEE=[O0LP9/8TYBMNJ1``?ST7H>(N,M+B/F +MZ&_)520'22:8*[K-<:HG,/IE$'06L8/-Q:"#Q\\&7SZB]1$`:A[(DS9A5"#' +M_6NQQG@<]<8-(8]<0F',.2R^_N)3V::WN#7E%^G13\Y.-_QPK6<,)S?BK:%M +MXZ0O:]7=2?T[N85"+*ORZ-M"?;,>1/1.+%A("T>$;CP.1M=@!F`O<]Y/5B9O +M$R$?8;LD4)4)&#]FZ/KCK&L[CO4H&3I^Q\]7EK8N+[='QR?"=A!4Q^PTIS<3 +MJLTT62P"W\!8]YK_'EOHT$5MKJN3#/&9]/MFG%I79&2RF_]\6DW9W$JK6(;: +MZIU*V[=HTSKM47"0D25.)]&KX66P:^IL+)Y=Q#X[N.A?(/QUD"J*.5PNXL[%R7WA:*]1^IX[64G2;!"A18OHS(=U:]QRC2!2HT(@`MR,:F(G]EOTEB*M)4&YNTG4QQ.%%//#%=J +M-5GO%#/M8,-ZXNPJAYD;%XBLN*E8KXV)_0(98SL$6"8C4 +M5;YU`;;I-"P@>\PDF@`44T/S[V,P*>D$C$?%3B<6%(H!R7Z@>"AAK7*BKI9Z +M7,\Z>6H5E?:]I=LAM(7<'$/U)XGZ531X7Y>(+T,'#Z8+9BL]K;33CQ98JU5# +M)!-_4+J6LQ&6VXH'___020S/V0$540_UH]J/Y\UJU@`<>FB#NJ2U0A.&RGH; +MMX(?$[US.D9TB$(/M[6R<*56\XID`&3W9Q+AO5P>3 +MXR_%X:[TK<#DP3I[O5:#)ZS3+M:F^*4.NJ-WNMF3Z6T(59BX]4Y#.J%W"$(=DQ,?R_EDGN$/_!"I-@>?(J!5+A +MP)CL48$R!GL-V#R0Z&K!*GNK_(74WYC%46YQ0&X+`"+#+N5B3H+7B6Q2>M4> +M&>I;-$7S??)1(GZY6OZQL_KL9*PCMFJ`U')FK#7X#/%$76[J`DA4U8-6>LC?ZOO`TSJ$DFDQ(TAU^T0;AD+@SDD&95PQY7%YY60]^J5PCN2 +MJ;3+1F7;.9`59MN[:Q3KN;Q*M^T]ZLI9YW'8\;6M3NF6B8^S73ZW*%4?<6,L +MW:PWQ?U7AVA'\L]P8^$"XZY*COQ'J:YPGT0;YY:!B*"0YAQ'XX*4ED]>35EX +M[0U#1\5^CLFEI(NWQ@&?S2B$L\3W7Z(4*CC'C';_ZVS%'OHN`"HEN2';VPVL +M`9RHKT+K.Z.*]JV,XIHFV3TF)BDAD.REC0]RKS^GX+KR@\[ +M%:[KQ,X1\X^\C]3'_JMZ2:\H]3$C@1J;9P5R,RE=6CK:HO`:I;]I)JH=PGFM!B@(\7H%$FFT+U&9'AWFPQ,CB(CQ.TRIH09"$9W8-S-C0"X--A3NWP2/+0B +M:^6^"5X/?!,]G(2&X`:+CZ'.(@&(SM=BX_A@,&`?`?\M\R\G7:V(N_V`F9D< +ML1>08]A^IG"'>"_=,1;J!KV2*QD_]EB\B5F*`!FC8Z75SB#!<52D6=O+YH'L +M3"H5D()T>FF@(A4K0PT458@=B$LEN@G#`2`*:.@M`G&PSYEJ*\!88'PB]7ZV +M%IJ868LC2.0(RS>6CH@6NK(V3?\#1[IXHZ@[[TV[LK:V,K$G[X%`?UH9*HP@ +M04+@[@VB8>@/L&E)=?H7B'.&-L:*`72,T@2%6']->)35_`F\AAM^(AP!BXH-9S;.Z&H* +M'>_/EN"I?*VVS+^&H73M-8M+@M&&EV-.)UF_`#>&U=$%R5)RJP*K1:$$YMK- +MM^\!%M\=]5E8I5'!X0Z9],N&##/O/)E*38^K=R5.X8KHFL2-8)88W[VX7N7Z +M\%][%RZY==!W?4&02*CM$X=/,CL3"R>2I`>C$8[^%5AD>$8$^A1#Y+,3AYLN +M3SU3.3/@_=<.8^Y-+_!43.!8LZES0<0]0SGA9Z;C/\D)")509%I"!Y#WT'3" +M&5=225B6&=(XWHPG\-"-?=P,WB=!:3)35A]\G[/`&Q9(>QWL&R=Y8"J0G+L; +M41FP!5Z/.![BU[$N'`O3I1`X9`U6]Z,6P.0QLUZZ(^8I0![9GQU90T*(DTM` +MBXH$I,4P)EP92A'#%_$H,@SIRSMF`G`-OF(Y91YZGV8XXWH5-"J!Z$9C-;5X +M2A@:FF7-*>P_A]Y%#MEDG20]C'.AS +M\J:3^Y>_EG=]7`*[Z)*#-GXV`%;%7609J(+8;V=-,UG?K;S*A^*BENWK3TYQ +MT=*RC19Z6!KJ3*(9<[J44[Y*G!#]0,3>N\I/GB/(1$V285XZ[)`C`/Z:(:F\4@S7IY]9`L) +M>+B)6>O2@\%\V.VWU^EO-Y6OLCZ4NVK@V8@YYS=C5>1L^([\HP5F=3^2L/?1`)%:)JO]<8[;HT]Q+*!L%0*KGM:'V6;SFBWR8IIYGCIO3_$%8 +M5K\"4Q1>]MZ1)KT!1"OO(3K1%J=/Q-C06%,?Q-/YUS$'+)/)_#-"A9_;5:#7 +MOV940JP$9^3,X+2D/#1QJS]_#P.K!$AE?%75,-=%?R5J!][[0=\;`Q5-MD=' +MD.`%5[AT(ON$F'JI>`-J8CINB.06(,+?6C2(F,B+N!J^X9Z)0;[%FKV^S3Q\ +MU7%^Z4P9_+6L\L'G/"3*$#$F"/:QT"9&%&?%?U]NK$.7J3_IUUL>9C*])47_ +M>`T5G`"C4DZ_69`0PRK_0)M0R]%36$XMV:SG[\\VU2A.0Y*R),1E6'K'_E"% +MZE[:^6<>GX/LQSA8)3!6V/MC1.:N_G<*37H$J&)61448P*@.L?]0[>/H811$ +M=:14[H/`8-9F*"\.1?S)H0D;U>`KL1#T$_Z2L&$LZC?G\Y$#R@Z??EL,M=_I +M-+F5A+R;IV`W2A8+V2$=R']"T7J9.21*OXKE7>UXST55*R*47*5!B],8DQ!*8!K2%K>%.HJ/H^*@318R),_^* +MGMW?PQK_J>-I<\4#WTUBS1=:,R\*<14140(UVBWR."(ZIKC=91KE,"[RO+>L +MV_(!1'.1"W?\SXVM"5A<=+WL!:THG"AU#"_+"6NV:1#V\^X3+ZF-74XWT49WD:L*T?$703$J +M9W@+^<7I-H7^%0./B4Q:FMS`YI./G5F(<#S:M^S0/$!M59AF6IVGC[GHP0@/ +MQ$9^JTAKN:")Q'2!5@<`9L9F.=I3.N(X[LU^=2^?B:03L\#2(X@9DCAO]%X4 +MF$;&-?I-J-Q6D5??]?):[?U_H=;HPI[?.1C0L4DB+BW'I=(\@Y&!HW,H&KY[ +M0-K5K#[&F9XQW;M[[,O?[O+DVER1MNGGHMX2[CM$2+%1#T%/8^=-;@DU@&#U +M]D2?*D+?,6EE<0.GMG-1VJS4)F::] +M@W$Q_+Y&(4&)57F3(04#^'+?$>6<-8&5G%H1<#+5T;Y1*BMKEG^;0FC:N[TZ +M0H.`B@$BF`6=I?F\6(W#[&WYRW4KE_E$2-$WR#DJ71-$/))/S-T3!%%D1A=? +M!X&M0!>B%8Q.'0Q5R.^CPC`CW%PF!=QCM_^@>'J[W-)P],2[^2F]NK^Z-N)' +M:4ZVA-H3-/6Y#K'[;A5:!RC%'3EY:,:,,]$UTAH(L&A[T_@([1$.#IXS>P^& +M!C1$&^W]?QC4@?L3^:?XHF8[3=F-S`V.NII<,J=L@)/G>HP*F,"[Y:M_H@^Q +M;8;O&DBQTM2DCK59HPSJ_I&`"?*YE=^W%\H07@`BIG7VY,;9]:1N:=[ILT6C +M61D.E866$C`NAI,61C@9IO&P-(XH[;8$X]>N(K\+0-$*@8;$\^CI1/_!NU+, +MZZ3B4+/5B7PP4^L\8(.],6@XTV`Q@';BY@2%'8"FB_?/ +MAIR)):L-DL0[Q#3ORN+.(T!,L\Z0)94XEH&AH=I*E;X?TIGF#[@A%"VB)I/M +MY#():Y<8XW`X>^QH!B=A#5.B%8FY!F55@PZY`G>D7.,>3HFD]M0?ZN"2)%L9 +M[4S:=Y[^,#.TB'DPK^:ZZL,Y!:!.R(87-TFID5ZQM<9&H6$K@F?ER7Q7"1!] +M'8!SX_JE&ROTSQ">+-:CE!O)"HV"?OPP3FX;^%E7,KOK:S(*M555.(DFG.F) +MFC8?C`LI[R"5*6^-^^-'?V$_BA5?\`P1-:%W]GJSV3<.CQ83$,0!!=U3CX=K +M.;2,D537P\X@B/8?M?,,J:_@P7FT;@L^UTTM_#9U,^WYUA)VOX?5!GO4[.2P +M>C)>B67SDJ\,HE]3%H&$9%U6F$M\,SU5%3=J'*H8_@%8X7VUHSIJS(2#F"+. +M'$T=Y)Z*G2V7'ARBWD!#92\3O=_T9I"?THNG:C8*>LZ3:K1,#RZKIJ1M5(HM`K39,+,&289@TZ;X(KIFE9L_5 +M^P5Y(:]'89[U)SWWKM07,@%^UB)2+V'6SRSO4O_)1.>V5,!E"-&@>'^UVPX$ +M=U;)PP.V-%IN;CSG6:]JZK.5[,C)5RUQ%X$O2@Z1@2@($&NH!81"3$KTUJR7 +MRUIJC]."[10P\6^-SF8A2]1^AKK$N],,$?+Y%Q;@)X?)*"?!/K:PIOS;(W&P +M^E?VG`00;7=K[LVQHT70?#U]0`+%SEP[?(KW[Z^\W`DQ(J7!WT!XL&8O*49= +MZV#"V0840CJWQT+W:J@^";,UP^@R^>\`,A6?<4ZWUHP-(-CO)#VNNB-3&\\DT``F@ +MC&`]T#,*N@XI?7K)!`_Y@#U3'G)IO(MXJV'BXM\TAP?_A*-I<"(0_9^^^6[O +MVN;F2!=&1"Q(F!K(%C))\:#EIZFUQ1:'5CD-)!D'K@X]?O!5P8]JR-:Q$N*[ +MJM?Q(ZO/1&Y#(H`SFOT[HCZ>3A.74167ZS*/F&"@>7U19C\%R=A9WRHRA$$; +M^UEE3X3FKDPI)O+DGLW;52S!/(%A?U03BC4HGA8#@XL2%RB=NZS.E(#2-*S\ +MN1UIV=%4\83+;UP-C8DY"#T2@3X.(\)%S\VJT)F(BTRTFRTD-'_3A8/6/X:7 +MN0C%$8@RZP0*$LZEEKB$A)F_RU3V`@%4Z]CN5'32(HLRMU@%A,S.3[ZMJ*/Y +M/`J13R-770\95U6G+MRE:83?LV?14/_&^4)TV"76JI]NL=^44A[36=OF_X(E"YL(A@_,4U0\9O@#[ +M2,(O9C!-%QCI*2D^]+Y?LSF5UK`:N*O1(2Y3U\I[OH#:B<5TOX51=N][]]H" +M^J46*;M]]GI@LAWR`K1#QI*.,%ZBW4K=KK4M47[`\O$[?VE!]/2@^&-Y9V&+ +M6%Q@J!W%10(H@1$U/6V+$S]="N$D5ZZW-Y"OR:=[WO1;CX;W$6LV2)]))(>RT]L.EG`Z$;GK&NCA^A!@'" +M2HTB#('QGL;^9E>O!#AATFM:]U*C.`M;C$M1^8<'%Z^)M-ZW,JZ(G+4_))]X99MWE4AYM$+OKHE$HM:#^#:$-O$?Y-I +M8-`E9Q0>YE/;IJK?0];('$UVM\(H\Y[G9:W42MU`P.3`6TU[Q"8J(,Y)E(Y* +MB(>-B`LE'U<\RTS`-%81G>[$7(),[6RV+%9M]"2T??TH_;CWI3M%(K,32Q*;E1OY,=9>0:5>/[(PCXFU`+)]XN.P(.@(6Z1 +MQ$:TFE#;9D$>4SJ9>B=YOR9\BU`X,5($ACI5KZ5ZNRX7YH;=.W@JH%NT[_<" +MGC<7V$NU=\1\;X=W*6`;&=*OELI6HNENA$,KY7D2A='W+DV!.=>%]/U$B7,0 +M7O.-,_WOD`S2,`_B'CU`::/5/1J]6BE6H\9>PU(YAE>I8/2].6AL#JQQB=:( +MQVCQV1IVB_Z3O6G_?.@G&7J]/EBU1$J.$T>5?MNX\H,*%;KK=JP;:Y6=G2N= +M^B$@7V1Y8W],MW8O-W<_"XC[>O8LYW1B-^P\'PTYS8@)1-;OTZ=)5;[&K@EP +MOT$0E_+8>S%G)22DO(C3=>1U:%A\BN6VWQZ.X(SK2K>^N2**I*12>>?C3OI$-@)IKOJ#`?YHTUL#T\$_?$4G>OC7#MPN^' +M8S'0`=1:ZB@!:?_[L/&01V4;;Z)]89.9(K8CWJY=/B!/U;+%`PZ5:*Z0V7YA +ME4#0ABUL*OL.Y?M9A%!-`X&M<8GQ`;&2JH"26MB^$5]5(67@2U,L7'`C*19X +M'3GY*+P5C`@>YKH]$Z/O&EHBM>/MY*5I^#.M;^\G=]*O5,ZT5*2-ZXFMXYYZ +M[#=J)(4QE9$]E&4P73MDZXJ32,J`SZS`?K=4_KD?+:HN^CG<&D] +MF%PP(@L`_.M(!L5Y%7_*I+X2%U33?"IF)I!BQAZA>B,0265TMEF?&,F(\O_B +M!)ZHA8KV7VT:Y@4=-_O24+PPQ;.=8?U=*J-5(VF'%R1IE=`_TM`6BIFFBU&K +MR[_K0N2,023[3`Y0.KIR49VI&;6'5?@RG?7AHYG9PK[V9^]6HX"(10`0JQG_ +M0I8@/X#C50*L6V9$;"INV*5:W]`W5[JAL"N860TOA%EX"YP"?T(FOU^&_[SW +M#.+7N25O:.*AK&;"S28=2""`K5]@9"I<<.:)>S$Y`6R6((&=!T&+QTTJSI7O +MI\H]I367$!PF15:C[EX=[+@NB?66"`F,H"5P['&[Z*GP;V5QD\1,JALL/\Z0 +MX.2P]4Y,9(_]S9.7;L41\P_F/RY;W3@=O?IH"DMBD^C;'!A1S.'J/;E""V=P +M,40`5/A-$$)IF9E/SC(GP/E<Z0F&G+D=M7W:F(=V1D$Y:7*(Z`,'5J#593&\M +MX<@[#[`KLO"SSQ3'IZIC_A$&=('VN_D5C+E&:?E\3ECIAS"[40`&89VU'W(: +MD>H8M%JC1G%M-DYI[__`SCXE)NGQ(GJ`APRYZ))D#,LO9KC>K-$`F2E%`04% +M?QI@=*?6?8&Z%`=`2!A2X8+[[^;=BY*C/"AF5PUK- +M;Y8"^&G]%<.0<[]/WXY+4"WRNUJ63G6*G>0N=*F("(X.#6\*'$_W^XJ./=D2 +MH?QIE@,DT^0)[1U?O#=<'L',JN)U/4(U"\C/G*^^=!W(:V&BWF< +M+"X:_0D+); +M,@K",:N,]T7OG)805[R#EPWBQEBM0II(2M%R#`'&]64'+3FO_=\Y5G0'=_F` +MVK47"R_Q`+V:+8?MQ+8$_@*_JD&^O^7X*;;^S8K?PA9HPW_<%"=:-60[J+FJ +MO*=N2HOW9YBZ7T"?F.9'>"]=7PYY&9LI@H-*%9=6W7KZVKUG:-/ZB;.D_6L)WDBU;)@D/M1DL2K5\[Q_G%#>/TC>/<4"_NN/MV-WZ +MB74J/%0?L3AWSAW5"6L2EV:?U!Y@;TI;IC+>7)&;8JAWIP*'<00,+P__LJ!D +M^]VP*0IQ[]H+EIL]8;EF#UROM.X#!7C/@!!B=0#`G`$KDZ3(I*,6EH7:O[WW +M89F[4TX_0R;0)"_3IM[",UQ9RK'CHP?!V(Z#%4I"6S)5"K?Z[(6O4#)13/J% +ME#4B:3S(Z)3-Q"MV-[+T`5``@[7>]51_Z^%P99)34LFEWW4&`HP111VQ2,*A +MGCK-.EED`ZP6R&U'HL[[:+#%SO#*^&K1.2XU,]\DL&%DT01_*A8\N@4]WH`7 +M*NDY=AH\TWCZ1M?Q976%`9EASK`O_4MWDBH^6:<&$3JM#:3B +M1OMYH33U$-8#4A>DW)@<11ZB4$Y*\*,_'AE\_IYN4BE%2XL1@1=K`X7?Y6"'E'RU71^FAAE +M@5IAQ7<>;D=C_Q\E"L`([SKF'#J`D0$J($B;)Y'"X3YG[LWI3??B(4G.IB'# +M"-0P83ESCAD+I*42OZ'LUM>>((_M[6$@W<>S-N*"K*HP**5\%.]+#&W>V_J+ +MU=RCOMJHR-%Z;,^J91=PMQPF?TA'73DA\&,$SMRP'QYXBJ=`OPF__2PM#0SD +MR^ZX[`#8U]_Q9MLX[C"^AHI4'?NT^(\J1AZF3[]9H,ESIN1>?I=@I2!P9 +MLK81J$`1O7US!:8[8!8ZT8F,"&(;&YVGLH#81)$\:4<*%M_X\I^ +MPO']L/)585./IJD_S5H(PQU]`-T;Y>L*D.$7<#?^_A%*I']XG[(1>)V-;4,GLF,"^UE#Y>JA'S0B!;6>16+\C:_]4*)W4N&Q +MHW9GI*S[Z(1D7F?Z/WU@K*+$DL;07-S2,D7PKC>X$(XQ"CP\M!3/KSLJ,T+G +M"9.!-7OD[376(9LV%"^S+'P,P1\S>[/K#]:#E&4)O^#CT@[T=U\0%3=IY)V$ +MKOGK+:+,:47;ZBS^"Y&FD6X*`VM;+0&\P=!'M[5R2YW_EU46#J3C<)-E`]AE +M5Y#H1<7`S^R9_^Q#D]B#Q\B0G&H=&FPDLTSC[;U(KV#6A-!Y>CT""M#7/']7 +MR?F%1"%GZ\.K*$(.W(QDR3+RJ:\A9UT'+";CW0]QI%?4_N:D\1G%OCYB-A\> +M';1\?4!Q!!4I.[2-];'@^LVYIBE%VI4^*98?XCG@I>LVOQI"X:*:4[=?*;0J +M$1^P04[^>?[(F?:]X7ZS`FE=&3_9;]__ +M7?EEWF/%E"W"BSEE2XR&[,#2"R?$A)-H.,@E17<(0)]!O8B +MNFKU:PD;M$MT<]RJ)4\:!]]K7:Q`H&R?D9V"O+)[E^ +MVP[L%&I3^5O]7Y)_B8EXDEK9O./ERX^]_`&Y.049[*"TH3"K;_/4\Y0?JH/: +M3JX\OS-G9PNA&#$T]TLMS;1Q!78W0U$/=L^>_';DP5LU(K)7O$2['N))F_9. +M^\5+DV?(8YSW8UHI`A="#V,P_XRS85W6BG<4BP,C#7/*7S7'4VX`HWAZBOR`\=U#=_$ +M:MHDX*%.;D(H"LUL_OG[(CY +MMK./LNW@/BW>DMY\2!M^HT2[434&VLQX]I%#2'D0;APZ.)I76T>JGHNO[V6I +M9^PZM$O*^%IWRA/IY>`0TGJ(X".`0YIJ35N>UV,?3V#@F+?K&1H]^7W0D&/X +M(P03O2GKHN$*N,L!0]'T3"Z6WHHK$<'2%?-?`WP/!EUC(81O8)ZRDJ=_(KE: +M@($*#;T\Z7,_CUN#Q@:<$+;BI5_71*9>@?(!J?=O2R(C#8M4*-#=6Q?EG@7Q +M(K]98J@*-J+)@+LDL^U?(!8PI9;A`W;8!\IB]FVD'5"47,.L_A5FVFI!RD8G +M=E!+#:FOIXB=TH&7:17#_^`_74W@:F"S&AOD\U?AH"]*`"91$`\*-Y:QN'2( +M>15G0S4T*)=R307_+#?/[OXC$JE#3Z?Y9MJOL`?S!8&BA9E[Z^'$4K90,9QX=3D%STDJ[@VYQ4QQ&,OL87'>3<"(J%?O;Q[)1O-,P':=FHG"S)UCZ6+I!/EYAYAL5(G3U&, +M#GG%1]UW]%1?^&[6:/XMCND&(5]JQK=&"DI(_!G9OOTFTBR,_N=:Q7A"3J). +M3/:&^POJ=9P?-O9:5:V:>5>PAHNY\26-C5P0=48C +M7>4V=Q?KU'Y7P"2!WUD6" +MF-`#]O=I\?Y!T%#.03..LC<_J]FE!2LMPB5?BBNC^P,)KQX\`VJ>70IJ'UF+ +M-Q`?(F^M9I$CB#NW]B8K`O$-Q!.:8!A)T<(84#K8BZQ%J'J.C+VL%>9[7B/; +M-GR@(M2;=QZ5#]\I$)`ZKH[^0+6)Y6,LI08Q(NAIC!J! +M0PQ2Q!,NH\N,Q4E'W8]COHE94NG[LTB6.L-`CD="09 +MA`]AAY&.V_W$H'^!U]\8:Y"EIOZ'GY/[@K:0])SD9N)&Z;@NR4S;F$$R3C(N +M8<,G`[5Q^8J#T&K^,&T_X8TRI#81_9\CT6M^)`E$@5T$HM+?F'Q^-I570P2G +MJT]C!4K9C%XMX485?XN*EE"C5ADMY#CF^Y"[X6/=XY.!%V3C>*2N%&5C$.\K +M4UCAV47(?:SDC9JT=,#&0`3HHBG5]M;\6'NDB*2S94M?#\@)J)R=.TZF((:1 +M;'!/8$I=;..:3"0J;(*7+>M".Z)\,Q!1FST`*K+?,[4L<5I0BX5'U1>R6TC_[Z67 +MM$-,@^T%J]D\8^77#TVK.ETDV"L96)8)?'SZ:?WOPO,FQI&5@O`RXPV'/N#^ +M@!B_I./$H1HVX,)-6>SDX-$1Q]/5P=?>PA7NI*Y_A%)KJM&%9T'^*<+6,1-K +MR,6>68<6Z.;M@@]8*5LW(6MBLW-VMD' +ME&I&2B#/&06G,V]9>6=J%Q7Z3!YQ\DE:EFS>U3TV'CLB)0HK+&9AM9E5Y +MBLA13U?1OI(%E@WL.]C\\CEAZ@OW2X%"2JUST($^F;N17WF.DOS[Z3YY`GJ$?[_WX(/V(4O +MZ^#X+++A@2`SK318[9>(EN*GV*:0`O#MS`C>;Z+55!R25ML?ZS"3.I-FEM?\ +M@F',VZ'8S68V[UA_C)>2L`7\0+GM@K-\LBAE@YXHR$".,I>L"WK8'A(A?SHV +M-'J0/T(1T\9.8HJFDH2=,A(,PFYS?V#SY0AKY^D4;!OM5]$'O8",&\>;$+,Y +M<>T]J@@XBSV<="!HY+'$A0[N&I=^FXKM(3_J!-24SVEVI7LR%]3)A%+VGL!] +M(52`=6XPB@SX>PG6PBQ^FH;(Y3/.PYLNC3%DN +MV=]'+PLWY,A9`"$\U[;^N@U&5GBMMQ,U-.L1Z@7:"AJPWI6>HRYS:N3V3.IM +M;%&+#'N55,5GO,YY?X"VHNJ(P]X_#C($"IACY]"M%FL0W:L"[I2&$E&:9('F +M0EQ!12!B?U,]/8"32_9D1:CBA5$"H?+XY=PWZ0?#$M?L6"W3!-53#I7/8">V +MJ8^I$\OG`/.CL?E8V]9J9Y*,LAC6OVI0=XI"0SC!-7=HWONH-'TLG'!"_6Q+ +M\\4$,G`04(S\KQ(#:4E4I(-5[O7S_>38SDC3'R$3N/@;XK1J3EF@4MSF7-N1 +M-J@B^72/"YQ&H.97U2]AAB#8JLB^/&2Y"O^1?6KI1FI.,=#/K:S,#U=VI%?M +M^V2<8RUUM?-"Q!6/N8,.6J+K_)V7:0]^Q:N<]1,YBM'^(\B]H4-F=R.XFG?89/ +M)9]M6H\;[NFPYKDB^BY5^Q. +M((O%U_GG`\2N?AZ]9-(=GM!E(OLV_$6#TCN8._,>"HE`W"%W>..-19&`@2YL +M:QX582'(R*_1G7<>LSC[/Z.R1<=QT[?(X9QJ(E!D4,Y6K/,]OB>7 +M'B.I.JT8)!PN-2Z!;C<"4OB*NUFG)^P\U[JL`*'H[._5$K3%:".M"S%F5"M#ZCC0TICQW,,R$\%C/NMEX%N6:9J2 +M5<58V:U4.G*OG5FJ^Q`O"U6!^<,O\U`TWGE?NDZJW7;=[.P6YUD<]7.O]8)EG6, +M[-"TF5]RR&==",_JJ*=L@S;\Z>`7BC;C-;)L4V:@K\43[Y_A0H=VSF?U +M7X&?2+7KKIK3HV]B:5&G:]#C9%PT*0,!=N8W0"9YU;F0_%O@^Q\E<`(W_K\K +M<-:ZD<#@U#JVK:.S685C2+E!+^SN^1+XQP6T+,8I`*\-2-!7]!@`=P0ZWIU^ +M](R'B,'01?R!BN-Q.*02ODD@?ZZ7Y*\I>'J!T/#]39-KIA@H"WC^7M!M_B:' +M8S:B667OZN(WK6'=(X9BAUAU\,6;^@RLF9,&W[3U_5"6]MVSWBE'*?YH:@TR +M:@PPV%E3Q][E4[O1R;@A*C4:>QMT,GG2E%*XW'&(^2V)O>>ZQ1EPN;93P@J6 +M7K3Y*QNI^6(M7]C_E<.PJ=D&&HVE(5=G38&XWKV_P-!(C>!YV2H#;]42#!'= +M@$$4;`(5*\ZOO[=!&C,T)`4Q^S#=33)D"R?O3,SM=+9*@H.7$UM5?D1(IU(* +MMQBOF,]P-LS,&TDZ,Z`#27=&4=IP9:Z``^A"ARVUQE[G(7-XG=H +M\R3&%R#OZ#U> +ME7`P=*OME9"U;XG>O]"F>KUL'6B3./[_-C)&D;0`C`41>0QB1_-YC4EYQ?/Q +MN\JV@+,<*``J]).BI`@"'#LH3%RGWOU@HU19Q%V'7[$U'X4$XJQU.320=AJS@.Z6?E\X@ZZUX9`9]6 +M65$_7ZX?R_94M%V\^%V)8JQ8)(OAN$T\Q_8\[Q.E`YNY/$NG=FS0"A:BL$"\ +MYWSO;X[SU(-RM_L;1C1Y06`+4]ZL2V`=D?]$GOA%U#'$Q#S91"X_CV[;G__#-ZM +M(?:KAQ02#2WYA(ZY/ZO1+IV8)MH)^_OF<0/OFAZR!SDLY:9,"J49CX!QA +M#_'I3(W`@T6Y3:*L[5A_7F!.!J"`5GWW*_1LI@.*9(TDF_(*;J._.@1W> +MIM7=I691?#&'"=JKQI=AAYM\YB5AX!FOW!?M:AG9[YW03D%61`AF?N_NW#F( +MN(`_)'Q6B1K/CB29]N-,*?YFTJ8,RSLI)V<""J;S2:A! +M"]3>'W8R:(@0<'*0@T&+(0?D\>+$L$7-.]4Y5(J,]N[1HI.%R/Z_D:2_;V@$ +M2P,2T?VZ8-3R$R_8X!$WYVI^SA@+P2+-NUB"_RM5:?C:CFJBCZ`WF!%[1?(A +M8%TQ4NU_2:"D=X#=8V"]7R%MD$Q:7I3U1Z)*^%5(V3NV1HQQF3?W(^@-FS'3 +ME'K0;8/9.8N,J3INXE/Y]1HYAOAGLDU@>-*:MJYZR&0292IE07$LKLR9+UHT +M:22B\4/%)>,WK`M#F)/E:5S8$PP8@Q9N=:N5@*OT442?TY#$6GWK`R=59.Q3 +MF%YI4HFHBQRN!(??&^.&ZT[1I49'D66"CU(YN'"!YKX_C4\)_+)<.%3)W/TA +MI-T+/TSQ[E(MS=42/VJ+#EA4`VN-04^^EJA/V[[\7!RS4]2<$I'&3[`#'5K(+IP0[!4%];<7 +M4@`VA:@P*+5CI'(BQV";AL*4!1[J5JL]0"Y?P;?;<15WP2XGP%.?W7@\T!4R +M@4"K?`&(O`]PL.`]VP7_IVAN$08FF&W"R7S,@5LVD"F6(#A!0EV9ZD-:CR-; +M_6=T;`=E(EF9K/G_T%//*=PX48VP(3K/TKL7!CS3)&@S36]:KUP-JD1.`QGE +MZWL9<3K&5%\U9FP@4XV/)WR2H;QN26Q:=U0T?XE9C,U8_UF$M`6SCOY]^VY. +MYB)UZH;!2)=R<`TH.X-K6YJ=NA9/%^`$)]+)Y#MM,QV*3T%5D=-V+[O) +MK@*=6NSAB2F/L&8ZP:P.<(IG6Q&TW>[KS(@1,^I(&<5N>,WGYMR>WP&#^GI& +MSZD"?3^OG'DK^T^0A584G>^Q;RDIHOR*P*?:?R\44$NMB9E@J]Y.BT7\V"@2 +M]<8;SE]3"$!1?1^5;,TAZG0R7HD/F,U>BXS$R'SM%N&[OU`"@,U39R^I;K32 +M%>4TV\&<``>@RPN!VDS;V +M>K_[?N>4FN8.DS?3WK8)OEF'KETCQ1=\9@O_GJ&@GR5+:).OAK+"5`Q^=&.M +M"J_%L@:6SS:\@GN&W]T`+R^7!.QBD4D58\8A!71*,:16:]K^@$M%I4WP8R_; +MMW!1:F;[,\1)(-MCZN!YKKGNN_3Q)=?4X>-ZXSJ]UD\7P0WN)%,*4(ZE;"[[ +MPA.)5IBWQ";V2#*X2^AO3W2GKH'=YU$$NAP.QP&WY6W^`6>8MVP#3L];T6F\ +M7/T4)KR5L.TINCES":G/^#$VB+<[N9FI"=-Q0A6AMX$#6;F06I+ZH`*7&)CU +ML2V*0[%A]IBKUM85@;G;2.6=\0N=#DW,\-ZZC.G7L`,O&61F[`!A9->)ZY9R +M@T_-/"O=ELL=C_-L)5B#H30Q<_433V61V>BR+[/X]%R>YSCI"PC8EBFD<4]; +MZR#B?*PPQKTD*B[2SKTA?+7^U^@T+]':MKOW_2)1<%*7WAF><4JV@8,.0PK_ +MX=J!E]5KW<-P_3/>$:P?79DQC02VJ.!S^A+@KIY77BB(,(JPEPP`[]*0*FI^T]:)9R^W^$13:N(,B8,("R&E)NU0R@+09;C_R +M>+%?@4$G%1!WTW<%JG&==$E.@CPBQ>+==H"[*W:0*/0NU:5?>X!CAE!Q@LOP +M7IV0OC%TFF`EI.R:=#ET!ND[^Z[28AY6,"WNH[V7UYVM!'^X\SNZQ:M_H+)] +MENLBE9L_1O4!G6Y6G;A,'"Q#7O0TC4TVPCQ1#9<)JO7%6WJ&0#5Q4[I%8:QA +MK:GAF'#0SUP+,(;W9E0]>V%*@?%JA`L82P_$U@W0ZF*UE6'&(8_U.`Z.E10: +M.C'.NTX^OL^ZE,]9'X&%N3(VXA*F%4./L#*2TJJUO"GG6CYU[*1J+\&$A8;& +MQXQ?2Y)+1FY40]`@;/FLLF.GD[KX!CKTG*@B@F>]?UCBZ2+8'R&T>K->^:';#?J"),<_:";@^.N?]$!SJT4&.)EZ>.1$*ER#J@%)-5\L +MS^NG>OFBEQVE\<,TFL;<3/PDQ0-(_%1__`M]#.6P\>W\=FLL0;QCM>M;>H.V +MJ1U\LC=D_<'4&?XC4/!H&XY;%TDZ;>(F;7/\6[B.HT+7[^N%SJ!/DAYF1]21 +MY%/2X=JI@B,OYI1EE7J05F0^ED"D+EQF-@95VT5C_XN2G8D3N3-R\KN1=:+P +M+SG%QM1WHN&KC&JU(/C*`X+)(58.A&W"P/ +MJ3"!2`II]-)HPY\Q:;Y5F1XV$A79/A3#SL^)[#)8,S^&'$80W6'"MYU4)#A*I\S2/;\J[]`7.46=/QJO69,3[`*D-7K+2_[U)< +M:]M9S7KDARLT/((6N37[,YK1Z90*BEWBOCJ89[7.%8K?$2Z37%: +ME(H_QHB:/7U-E.">?+!7>RAR&,@PW,P`/]AZL]R*:9T2B0&2?FUT=V%QQ6=& +MJJE)Y@!W&``;,@U[TR!O#Y<7F0.H?NT75E"6/J[>5J^#5SM]URSW/U%9+'52M,B9_E +M5W*/Z+!-5_/3T$GGN=S76?).``FRQZU +M9+>9KW)'QQ3C1(CR/P2CAE;VX&W!?RF8=0$ +MYZJ(L!HSI;R#G=R.KR!ZT]!-\#<%/G+E_J?48L\R')@@*PYI%@FHU$7WQDZ0 +MD,>&=P3WI1C"62!\1M3HRPW(NMQ> +MJE]]M=-VY+S,S(!4+&9+\6`@AX+7'VTX\PP%@\F4G41M1OP/*%=;K,:IGQZY +MN],ZNV'OTVV6U\'0WKK#O +MQY$*S,"ID8HG5K%W-."?/8!H%)[/X*=L;Y"K +M3_"XB97(QYDO5K4=<@Q`0SO0S$KWW>1GR/8J))LTPZQ:E;H904YX*]Q54DQ4 +M>/%?DW/E8@R)W?7NIDJO\R:OZLU$'X\?[JE9-2 +M[#X!+7/?83H-N(*%;M>*'HK??3?*#8W-;Q1DEK9"D!8/.JUN+A%\7*OXD.&6 +MEJ??DXH8N&A#5Q4O)/F0@"@0)<#>E#M*L0R#5<>__PZM&4[@!CNGERNY--GE +M9&]`PD.\9B%^[_2.(9;]P.`0C=&6?\3[>!5&C<%2^T2S9U"1^1%?[/*1%0O9 +MO]UVT.Z^Z800_@![O#N(R7VE(ML7;U6/0^8`OTM2*'KD(0*U+JC-G*/VQ[.^ +M&G/4DZ)8N:/K];TXM;#$4\%QOIVPF9PT3GH)7@=C<&_E_8;,3*K<6MSV:U5]QJ!9 +M>9]=_3NI&P10=)8SQY_-`G7`S+RN"#\R]^S`^P"O3HV[IQ]%-_X +MK'.O%GT/A;PGT'G\1);#"5G642[#T)KBO(OYI?2;:@ +M17@(:4CX?>$GJCJ5S?Z!U./O9REKM""*G\5:H;OE&+C4<5572P:GIVRT2.#6 +M]N]P=,2")B3^U$_7WQIH.2`4K7;EQ?QSP`^9-&7N$"62@?+ZC4@:/H'F/;C8 +M=;Z_DE`6M!*2\CG",_QQ.5![]VTQF(`66%LDV#GEPBBO4E7A#"8=J/\*Z>V( +MBGJ,MFJ1)7P1O)P5#".Q:"V58X!6O\[>M9(;92JOBCF?=.I%XH3$6I=02R)6 +M.#Q5:IR@2:BNLAE\R%5RE]3?"TW^8_:9`S-NB5-O&D.)[_PG_=PI,A;TL4A- +M-Z;G/0[NQO#5$&\HC@*&.YVWD(+*G6#E`G")5F@)U;#1*#"2*ULHTR*`TALPJ,@=NVWQ&L,7G +MY]9Y-BK&8D:&QBMJ`==A&2!ID*]]>&K<_^A:KCP96(O9TB2Q(/*,^U!D(0$:+BT]G%&BSN2R# +M%PF/R)LWM:4M\PST%F6A#F).92%^OC8T+ +M,GR*%U@R9J?^3__H2)53V-4!%0QFF6DR;?\M@:FBG]>C0"N0[*KPZ3;7R)R` +M[X5S>-8/5`NS*`B/_C,D8,VB"N=W&!Z45/6HJ_+V8\FHR;B&Q.==8&D:M+]1 +M^9>'2XDW,)W"9::<:X%9$(XA=:0#7%QG&L2>NNFIGKWR,@N^AS6J5M:+=]9= +MG>D!$/:19ZY2/"?GY87BLD`:C<_HE.Q0?+1(JL86:,559?AZ/KPW3??F;P0Z +M`3)@6Z5'^WDV&<"SHQF3;#\EHMV'$0JT.W@C:.CJ*J446<6GK5V=1^4>.+3^ +MSZ5_S!BF=+YX"W<186L9O!DW@TQ``^B!U[K0C\;Q1Y:`K@/1D\QJ:?QI3*V. +M!0,Z6"&[;E3S.GDBA;*O)@_/@`;D9\*8(.%5R*ZU0`[;4K+8C\`)XB(,:M]%4XP`W_4=\@M0I.]E"X7>_:/SJB2FO%!&=9IUTZ')$;J8[0T_3()UT8/,V'?+%VRA]QJI8^= +M`:]C,$7_UF^6\MD<]$:1Z[ZVX`+;C,)%A#V>7+3!C=DT=-7>1F\3=^S"+J73 +M`\P/]$=C_@R!&I3B@S7WGD:VLR8/9&?I2M$D\KI\52"@@IK)\,"N)BYAM`=P +MAUVA43Y5E8,UC)G,95YV37?Q:Z!CAH@J3MDHSM;@5BI.@6&/$L&I?FYL]8^R +M`A5+OR365T$<)243A%IYD9<>?]\37AMA2?2$?,H#@.4&^8_YO<$W%`[=E&T( +MFP:/@F_*^R[+@6&T&%+MHNEB3W!#_W,UF7-=H`!/OHIYXC5!A!"(,G`U`0%D +MGE6L_CDV;>,*HWZRANCE?W[ZOJZFCS"ZZQN()%R%LUBQK$P!U>F24\DXK-Z! +MT!,JNN6SJ?L8_BR+9%\A.C:3*))2*]R!O'J).^M]J[PH@V+EO)X0S*Y8T7=O +MT%)W%PWQ2OW$:7WR;Y,A&^]#`;T[WR:>*W>B2.C^SRMTP`HTU@*'0GN4RK^^ +M_;N40E8$&<&\'2GO%KB8-ZPG\>>)JF)Q?1YUD>L43N\.Z6Z-86J[4['-SA#C +M?HT.Z]#LU]B1"\Q8!_`1J!*]\!199LXW2,`IZ(_SE!$NU\Q+_X)8#U#)M(YS +MA3NDN.G__CNVVZJMVNQL/J^'/7RO=:9AM^6IM#0,J-_Y.;RO(YX[N&WRCV-6 +MZY<\$8:,%FB`P7M95M/Y1'PI):P&9W,5JKF.(2QU3SLNYX<<[+ZFP>,>_YAO +M&`J9));U+Q@>_-4`G=$68X>G(;IYXWD)86+.*W;`CW/7SKKI/54"8=ZT +MRX$^/Z<.'"BC5M]HKXPD+G(ZY6K>39C>^KFNSASOZV>GT9I>S-KRK8B6&8)_ +MV4_*MLG21XWSZPJX62[ILV'NFD;(-F(.]P419?+?P&@*W3U?O";QO:3ZS`#Z +M\`C%$<\KCMEU7X\TLE%S/[N;$\#[Q'.*9DK?Q\O3?<2N,FP>9^W).SM]^&O;I^C<&'!:32_P4RB#`/#K=;%6E]K%I'3B560!]GMI9B +MR-YOO^W\%JMM&X^I!JLCW^H< +M98+=U"&O_705JY+7P09+[J61C*\PJR-0A'H]PHDB`7 +M*2[,*H)FT[!+=6#J%^J8<2AQCM#80SKHHQ)$'PY[:X'EK.<9[&]=)G_-PS@1 +M@.;W3EU.*)U9F]HK5B&;:[UKND1.FF([3>K:`5CF$-$<4 +M.[-ZZ$9-EQJ4=2KLD0_VYQ6(5DM>M7&M+RT\1J-CS5=%7A*?P`2=A6C*D[14 +MYD%OB5@`P/>5RD]9BKON]`,71?CV.MP?&JR4J:#.C?),FW"J#H6#>>KKOL$U +M^X*^`>EO)-1IA(_-R&#*:B_%(N4/N*(6DLA`_6@,I(E5F*9ZHG]0) +MB`\90'/6QE\K7\*79Z`TM;5\K5N%AJ.R;W +M40*-V\<)R172&T=KT"*VTO0.C1:S^?\Z"_6\'-K4",>+[ZM(?]!:R[U]O63* +MR/='G>*@`S),-@A)*_/=E![KWCE1(OCS;6/"`FWI^*2/'H3J7E-'CQ)2)QS^#3G6X?467A22%.5<&S]^AD[UL+ +M$CBT>FH;47:@X(,,U,L'UB763%'^+@7TH2;3ZDJW!4*=^O=S/-Q&L9TC>H;R +MYX]W"?D7`TB%FN)VCU+`16\7?;H?B/^`0V3]2\0MW_1D\"6334#T_D&D:(LZ +MR=3MXS=';!4')/3[B$?Q,%H5RQ=MT[^WJE-)N>QTG[JA?_/,JKZ?^@*V)3K8 +MY+YUD'9&=_%4H"&Q&E=S-.,,<1B5JJ9-KN0:[>$.&8U.L&]I:0B9"4[YK>-@ +M\9"J8GF0NM'<"KQM&0/ZN;(GM"X8=:\['(D'Z%G_U5QO][MZSP8[6M_ZELG>Q +MP93>$^A1-(&WM1<=[PZI^YOIA_$3OXF+#G-,Q +M?"6N1#<,2-X!:\L^*J4H"N4TL35-!$J!E)>5TKKG?^6/RE"IA3Z9W!60`T?1 +M^1VB=.I66%I@*S7'YQK(OFKYB_E/6W<1S`*%K^FN#D*X3D,I?\^GT_^[=XX\ +MAPX^[G-/\N:=P' +MYR>X&MO`0E,?\NKC(T)I.D1!];*Y%YY6_8#-`XII_4.:I$W^Z)@YS%[#;[I[ +ME'K/$_G`SQ69`50..AZK\0E3=O%0>='YH./M$D):7I8F6ZP.P]^[:M5+-4@^ +MIR?8.,G\+/RDM1:RA\BX=@\KT:*=>`%1VBZ'@6>!I9_IA;7$A[1^A210C9MP +M>1.''$WS7R62&`^,LYLE`6D/^5+-.%ZCXE1D/3U&4D4*0LXEP)1U*^QAA+?6 +MWC?XU;7\TQST+FQ.XL!4IJ<&1GUS/C-&'DL$2C<45,673.7A;ER4IF`L>>K9 +M*J\FW8(S;_KCE],X51H2O="/=]RL*@X=]Q3'&G%8!C1OIZI#NLY<-1V*IHC_ +MY.)`$_%\W;F?N-Q[L&\ZU?X00NS4Q3EX.IIC8@%][:/8_JZGEKF%*N):BFMI?<``<@CZ**91>2QT50Y_`R +MEN4G`+W.5\J4[^#),DX]W?H+QZHPJP#%Q(L^M/O;^"MKWN`D?W.; +M8\J$,#0DP&M6C+AX/@LD)32\(G +M7^)&SDJ"6E0G]M5V**1+9Q`4E!VL-@^928$?O]BV\?+^E#<@"./A6X+'+9"N +M>8CWE/)Y+U_R"K0N,;;=Z5K/5#YC$?J97]:NUL\W7I+@=X]$I&0D+Z& +M#[U1'.#B^0,SPA3?A3AY4*CM@DFX\B`^)O@I*9G`XXE(90[6GDT%+70O0+GMV8B5V+UR/Z5"P<)S(L3G)'F_[VV34R?YS7A(V"3 +MOWH[LF!@=_/*.L?\",7Y)8+;K-*7<#@)-ZK/"OT@*@EL'=1E"F/*+BQ=-:W^ +M3S+^(IQWW&0Q*K3`\DOJVCW9?GEX#9\IYIAYSYPFLNQ3PI,2B1*5VNPE&M[^ +MZ:!B92KP15K4+A2G&Q-!!ZNLW.MG1A]!Q^'%'=C`&7/A +M")-[,=Z0;;RU<03VE1RE#L"8CW4T*E0$V1ZKLB;N-6H`##?SF0+I21S(M-05 +M170*.R#7(`)IW.QR::Z!ZJ.NRL$_;X,_(DJZV=S=;B=L>*]VQ3T-%SLG)+O; +MP%]_4Y`WW$3PJDU!7`M[X2^1;]H"`1G+$8Q<6"@3H('6'2AR.JO@,0S:YA,` +M=*^7X#GPN@3AH0/43=7,[668IL_D]8N[(I@YD!*"A$!1S2:CRI[R*7#OZ8#+ +M#LS'B=.9%5&P(.RK_US83C*RJH!<>+QW*PM_F*GM?[^5M2>\X[AW% +M*((G(A1S2P=6$]T,&V*>#\]@$!E>>/Q$MKC]=/1\T<27*]L9)1+-_9:&GM1A +M5*>+;,#6WP(+[-/KV8]*`[TSH[^XU-1>OF +MY_@ADF.-$E+@TF'`(&.6DK"554?AXRT)KL^7:\2X<8D]QTD]J246'IH9X#[VZ1:))I#U9)WO#?K^M[&,5P(Q`?)@FQ!MQ/1L$R4E5BK1MOK5[!84?C3^?/ +M]+M,,\2B(#N9_"L#L*U\H!I?N%T_2G`.7AS'D\L8U!1'JTVB.5:E#>X44%9K +M7S%Y8.8T#F#(N@\PZDC6&\U'@G_3E[Y@?R;W9$9`_\,J(@_D-01>@!O;`3[J+R,`36[N+2W^],KM#/R4<)2.O6T/HB?W<9"/P +M@C`Z$0:8\,`4R$KK-DY;KN&-:PNL+I\)!EQ#4*2DW.%VS!T>^@Q3`VF-9^Q# +M9:D=8TNB$:FH_W<&.DR!1E_4YNP&GH5"(N-'+OCPQSWVQB4QKA>18Y(]F%XV +M;8#B7W2]#V@)-23%:C2I:?V$A;`.I:X0^Z2G&^M4K-AB".+=F1,M45-9`6-J +M/FN("WK\#(TK*NJEL6BB/2"+Z$A7(G)[YN]PQ_>??8'SB<$<7K7Q4/Z=+X#> +MT?F.@L@7B4[S*CD1P^RB]O^YL[`ZJDDXZOH;"8-FH4,UZKV[3TO9''.1,+53 +M\).N5=NBH;\)QXBGJGY!"S%5>026U^&DHFT9PZ$XUIY\S +M7<1$8YWG68Y>UDR(MA=]R/RWY\F_#R=5A"82G.$U!OM0_A]:E8&=CW&:#+FJY'BNR2L4Z^FD`H>DD_I]3:L6[G0R +M6P;U/L2EHW]3X`5SK4><20!F.;8PYIN;!H;R+,9_E>H8\PWPP3%([>5/97X/T`_NH94P";=#->G%4"L35HJ]21!WDSE#!.=?I +MYIH^[\@!/R'Z9XE`*+$6:6\,TRL/0$]^P0:JV]:;ER+R_!(NQYZ_18.0$WNK +MM_1;WQGM0,3]W0G&^]$C6BU'^<+H1>-;BSP/G$PGZV[;NWT0QW<(LLKN?Q/0;E+"&HWO,V_QIBM1Z1DYBS<& +MP0`MODJH,N7R#77LK6(&.>_'1'3/RL<_-P#P)7E8 +M`1!Z_!2'6UP8Y$;'%V`&^"RMKYADENK[WNQ++NXJD3"&$.M;SL']IF=.!5-0 +M5A+9]A(:*H'0YM`(&>?-@6HEJ(91:%I"(#D6!B(D#W+]-`)AO#4]][0^M.HQ +M[!'M!%P5"ISNA>P<&B1?,'MTITC@`X.`$1:^V]Z\>R8]O6KCJ"LS.+:>EJ.& +M[$TE\7;-=L6H2=H/\-);A!I`@$_NWX`O!MIE>W[4>.@+N-%$3$/7L$9J@++6 +M[BFO6YX>"#9=:^X$TW3O$:8FY]5-YZG^%\*/\>HU#:G`UB&INR5) +M"5G/MQJ838)O"+)F52"SLO_>$0^)@=8(9.V;(!"AVB90T&TD5!:3`?G,%$_2 +MIW`CO1GZ+4E++^A%4+TMXP+U%_+F<%,@/O1O6LK>AN!ET4;S3W;&B3!1]9SB +M\$MO*W*N6#VY%MX#RA\`>0%4?W&GD(NA''V:4LN.)[5=7I6MCSY225`G48&3 +MV.DSR=JR'^393\Y1EM%\W*P*(V5AO[G!5JOA:_1:1=X3:E_=#S@A]%US@/`- +ML(45*334-K1LCZOU5RN.1,9[T\XH1M\,N3P8-)9`^:I[X"^UNQO6V/5*'2:MQ7UA?_&1YHZ7_T-R*-[+=FX\CI%DLX5A(63]!6,Z3/*$MY +M2YQNBVT*CB\8V&_8QRS*K#D?IC$C';L_[,6-O++FZ>1E4^,!7OTK"\@,P(=]&E'#0TW`3KH?* +M919J&'JY`JYR5!PN5.57O+9A:#FJ>OHY""5;#_UYCRZLL]+;JS=3J]L0)V^?L7!*V][2O9EXBIX%$8)N!75''IVXG]^RE/)_S`F +MM7^3V."9N9X+Q8/LRWT-E48J)1H\P`F++YX_/:SM=KRCE8J;4-\[??D6'R-3 +MF;83,`C%]FI(2$Z=W9Z/?#7:9^>$?1CC@Q-6A$H-GL?I$7>;22$+^4N7:&M< +M[LM(C[WBH>-)Q!N2Y,4^+/[6HMD>/$EJ4V)R!,6#+WIR\"VR9JL()+0\!*8X;@F&C&;OO_O-'.`%)\'$XT9<'\;0:A]G+NXJ93U +M&URJ)@DF6RSX5&:XRVQCZK'@XM1D-/TG.&+YUPXZ3]` +M@9SSC+S,Z\,1?FE+UMF.QA[%O_>B-4MUE2UH*9.4`82GJN\K&1&CNYR%9AQD +MX6YFPW-+=BY`;^L)W`9?!LEL.O@^#ZQ:"$%TZ;>%-[;BA)&UO7!B&G'U4KL_ +MVRY[$`%WF!!8."IHZL^\#U3B^80:251<>6BO-NI&V5'@X(8$XP=J@66$)2CO +MMN2YDJ):2D]9_?\X\GK:_#?ZF$X]L_:?T&ZBNEB`I'XK]C(Y.P)(_C^=4[]+ZL,__] +MU4DM+'N<=2,2[@',JN35M!SC-`3>@F303VO"*%\&H)H=ZX1)ZAR(!C&8`0FO +MCX[>B>;'42V\]5)/VLF[$4 +M)`_FN)7KI%BG8,=^?ZJD[G&N14/,CNXH(2I/.K0_[B#L6`@G@]5+#;`!P?LW +MAD\6-F(*,*D[&K4^/[R20>!("DVY)G%WI,FF[F(]H"7A1)-'%*JA6\]U[DO` +MM*.$"I5,)EOR&CLE6.S;*801`:CTQ9=IFX;X]CH[CK0W4G7.\EYW)C]6>G?> +M)P;^#I&K[OSZYQ)%C3Y+S5I).XE_>"3C,YBO,R=AMIWB/!C-*K3WAX*+LM_4 +M,RAG7^&=?HJ.';7MXPMJ4TM'OE:H1B3JA@POFOT__@M3W33SO5(@9(/ +MV-([>?I;!6C6][2QTFPP?E_/==:)1S,A.P\9H)E3J<4.[5=-!'L??49$;"XE +MF(Q'1=[!N\_A.:(J$'X'MKK1[=!:Q;.M6&32`IHXE%WC1 +MO5C"8*!,_]&ZA#^60(E;,@*U*"T>CV_3?L&M2K<;F4Q@'3*^I;2FB4&^:AC\ +MSW7&:[UM\_=A3XA/`GC1O+B2C@.73L\:B7FEV3>TBCS'JW:T9XI^TO#B_V8G +M^F'\E=RD/$7.9:+ETB5G7L,&52O=7:V)XPU.I!5/X]A7Y%MQ9+'D'7JZ$L4O +M7Y?BTP"5(/7%K'+6NQT@O&%`WYLN;4IE^DF]Y^.AR[O,0:5`@G'N"`;H+#C4 +M@.(UQOQQ9FF^*%Q,:?72]ZT]]"4?(7NYG9T8O^]Y;,2`/]8_T_V+T5K=.FDS +MOH;+(*6W#7GD<+#IBI#R!/M-\+S*>"0^9EZ9J0&2F1/)-W3-<)$\J6&2DK;T +M[GI"QJ4.F47@#.L+$]DJJK=WCN!_#I8"_^5,\#F:K8X8^_7UF"&7"*A:KZ&! +MXAE+4FFH%$E_>%`"M!SQF[.!$V]AB3?R4==4U=/1\D$JV44_?9`3QPF"D;EW +M/UL.A`0#%AH(B@QEAB=QBC>O_4<7TW7*FFQE%ZT@5SI^,^@D/S*`,ETC%)5( +M*N&%Z;-.+>.%\:4BPK+A.<'XDI^L!A+KMX^JTO3P_2Z>YEP@4HJ]'CKI1P1- +MZ:O,*IO$G=Y;NMGUV**] +MV^B:W"?E\GI'_^8B^$?%$Q9I,6IK404W$\X)'7%^6;:;UGE&2T/K;/?XZ`J1U.SL;7NJ@"<#JV2, +M**S_L$SR\E#O9(J!F!15\-6,OIH_K:F*=2*09*2#&^QK!8]\,_BB@_S5VS-_ +MFVU>FQ"950\W!40'GAC2Y(5*NJH`L>K;I5'8C[OXZIU%STQM``")T5(,Z'7, +M-#C1]R4FSDVPN>8/Y\'LK(Z<63P4DY)]B"ZAB4!)T]90/90VQ>B@*%(<;!YV +M5.)-"RMI8X@@`RN9=-D&EA!#X@&2R6560<>?MHIE'.1XX2D4`[>QT_I`*`\P09]Z;[5R^_,;" +M'8U5)@T;MB%F77&4-`MMQP&=^!!IHZR>KDFRK[5)5GZX<%PHQ]FIC<($JGBDD5?K4`39YZ^S2,EUJ?_\L&&R#CEJBCTE#Y1S3VU)C1A6G"ISFC[SA&!SH6=9 +MJ0;EJXAVZ9OR1M"5@DA,*O;-N`C8@?%LLA\P`^1[X#&`?5=*91M#@+VS5T% +M1.L^B^1-LC=0GHW>0ICW;[YCOYIHT"NM^:P)*6G\XRQ<_M=S6Q4'M;TI\!:7 +MEV5RIN`/ZI3B)5N)2A67`Q<@!*D5N6H%^.N$6G?8S_Y8I)^DD`?8,6GV)CT.J7JHR\J;4\> +M+-6K/H>OJ5"44IKKN:I['RJT'$/W>J4V(%B*WMW):<)O[R<8=^AR:@@75-HN +M)`7C`7&/2A7ZB#__VR3@H.7'?S95)-EHB&;K.EFB2E"R[A)`['#KID)QQR8` +MCOXOI@:XH![,Q:G/;N"SDA>;_Y?$9\=[U*%%YR,88MI`E>-XE)JOFK*L`OK>C-TD`_DXDU:O&:QI6KSBTG#[Z^;140"JABO)= +M5NI%[?)NK,CR0!EA#.\ZSGP33QZ*J/XUR"$N9X&*%Q-QN(^9IF1"3-0NE%F` +M(?&S*L>Y,6CSI;EO;F4/:V2;]#G+.&`HF=-;0=(>F+>.Z6SK99GB[FS^"<\H +MLJ17[VD\*'V3"!DQ#=65("W2R+2#GM16BY]V^2Z\I_+7SJF?4@5OA1ZV)LZQ +M46HB;X,W]/%Y\#&],?S[U"2WNG:NN:-XL:)JSW:/'-=8%#H +ML)KQF3M0.(=`YSXO"2Z^8G9;B#,>=OQ>2!BG;);.^SWWI!MPC&G1'A?4DIS! +M-[,%&`2YOND%!9$%6G242]I)(M<@(E#`3EAM0*)&YLOGP@IJ&[&39'D%AZN[ +ME_K_"Z(YX1M_86Y"6(?:XDRS0*9*]U,YD@8Q-4W\,QG@!P;%4PZ5T;8WGOZT +MG6GD#I$("&I8X[9!OI#-NSE?V4H[IQRWB`7*`JCL1J%'P"@KW,?1,+=449?N +M9`T*W&3R!@L.E_*(6OXC-%6Y7LMO)-+JJ%!=;F#@U[F$T5#74L8!0H(A.[Y) +MB7$^]O+4K>?\)OE%0/^PEA8T+LZ].EW]JWK493UZ:0LHZI!S3G;I/J2 +ME)PT_FB3=Z<#>6AQG^-A'/;+@EAQ?]Q4?VJ&--)Y#^#_^HJ,2*0S--#MLCJ! +M$C(5OE>0HR5NBJ<.(Z)\+E?L90%9-5210[1MYF+C"B9@2]GEI8!:;*+EML0&L:` +MYU\>;*$0@=>J0016:`<_&:>">C'=#N4@W]_?EY9V#PDMQP@+M7J&?GY`LZ,V +MV/VNK.*KWW2#D1",!;&BTZMJLEDJWD[EP!4=^3F[Z8*E5<(FL*IR +M]M"[QA\<]>,*QPE`=!NLE).\'$D[W`M"]S4O;2S`W_2YX1JG^I%0PMVO8>CZ +MWHK]@5^R$C`D2&)1Q'/_=4YW)',+V=G8;S@+BN'"IZBSCBY2^@;)@]1+_271 +MAZ+'6"ID2#C`9!+.0)UEG'X@UGB]S(6LW`]T +MZ75,2AN='@#ENF]J,.!%>':M(O*\<\^ILA>J(VB).-/%P:`W\YMOAGI)<@=6 +M!)T`Q-#S*OA2#:N:=98!^>S]\"11OT&<(EW_ +MN&NV)*<#KU>9`*QXCBX3Q>I&KNK(,H;D8B59>3^S#ZO57K[:7ZTY>U3;(/>8 +MCD$+00/V-3X.MD;3)]#2E\"=WG\9ZT9`%`?5KVR3*S(^(5*7!Q55(K3&?IPO +MVH7W*F-VC'DZ=TR2GG)!!&;QA?X1W?E[0AYVH4@4`8]<(J6(GNXN`L!0G"?S +MKS7MP^M]^-P9!WXMMP87L%>LNR;2%1S +M1YGU+]GO(D/9:'XWQ"3S>9<'N'!<4\;0N'YPHH`2.D=R#-<)[KMZZ6IATCBK +M&_YG73/[*9$^G9Y;8KC!()YL6K75JV>9.7JJ!]B4#4:_R`HQI@MS58>TC;A\ +MOBN6C5(?Y>#1M:BRE2F_Y*B/[,;,2H\4+(O,B<,;MTP&^[+!33Q%_8I!SI&2 +M-"'=FYC[OBS@R])**8+-%\M"1R8FX$.&W^_JVD+7%Y"+#\,CIV$I9.R[;Q8O +M>MJ5Z%I8FADV`M(":]_5@W9OK,8;Q9G<\_$"4?+YY*@ +M3O7L(THMP=\CMYC"`2+Y_P+7\*:O-\0ID/?/8LAN(YQN\DM0%6M]$FW-PU^P +MKZ'0*DF;9EB+`S]H6MZVQ>>B,I.%^-PL8M>LB1T+)@#LAS5(XN +MNMEY:IA.^@9S$UW\UE&6:8;"[@CD5!$;P0A8_X3B$C("\/._<;Z +MSKS!W647#_PS8J.@<$3ZF+O'XBG[?7/X+N_KN,1R5:O'56C#M*4#C&"41PH0 +M"HT1,NW7ILA-:=`'SQ#FF!7SWNA(%Q/;8&N[47U':N?)#J4;6\],D7S[+@;F +M]DM(HT/VPP[%/`VC`%3_6'GZ/XEJ*[@B)(M%LB'\X+#MYO1?=Y8?:(\7JY89 +M^AA!-U[VJ(+)DEZL@)-NNO7\D4)ISD%`EI@/6'T?ATN8*)*]`8SB@RI[R^CC+%)=((>`QST?RG!6M4:-47H'':FD15?:[H\W\!1;V47.1YN]#2G,N).@8X?624QNG*2N[IHL@.XS77,H? +MSVD0QY1N7GI[:'59G;J%9;.[1-04UZC95B9^EK9G%ON"*_E\+4N`LX%`=A-R +M&E!0X7_N`:_$$+3&8+B&_M*"N;N^E7,PH-`AF[,RK+$%1^C3`/CW(9.A'5?O +M@?51>%7(D9D^"YBI&[S:#'`)P[6JMM\^+H[<#0A(HA+\\S7A8$EKKT65.D$6 +MZ(&AW];9.*PD'I.QQ^GO0.&W3&#%?'FB>Q'F-^`T8S9H3A]$=8G_8+/[%&.Y +M;/:[T^_^KF0;V:?A>AZS:/X*@9NP"5RW9)!J8$>#9?<[==BBT$GU +MJ^P"HO`2.^23VU-_9G*704`#)&_75.$'RI8IH[G6L>>#*>W]V_B'FX`GNS[2@^J+0+KW)OGLE$GQO\$PLJ3KFT!ISQ*Z-^`;)RX +M1X_QT$J7R-`Y$`(2CK&B4#74TX'Q;101C*LK_N5S%D +MQ9M631/?!XO4SZRW-/Y3H.9RBN`%LIW<8BIZT07?84$,]2PCAL+VKR,=-6O& +M;NYHG2]D.=,FXE";4[B)K%'\3V]$0:WM?RU.-O$CE-'O)`5*>'(VFP"H6'@8 +M*<]"#Q`)?NL[)-QTEKZ(Z?ZI!&`.$E@T%6LA$M76%0R$&;BZZ;\`65EJTMIK +MC8>TR1P#D)^AZ!:S=YIA!.6V].SV2`^AZ[(-0"3A61X,4(U]AR+WU!#;*`J; +M9$0A?T_B,7+AL;J\+C<+RDR]-I^5(;DP<4O`.)O"4!W^7.)GHS5IT^IZ)L?! +M1#&53FMA,I'_QT/&<8SD$.)G3/B>CI\B/'A*H6]AL#29#P>ZEO:##E6"DT+/ +M"*MYA4HUHE6+EK8D[K,Q$*!><*[P3Q&4I^=2M979%5/)JKQ"=`XK3B.O=8;G!X"G1`+J+GG/\,S[3P/ED90Y?-IP(^S"5'9T=$<\(K\ +M_T.)6LW>_`-\@+ZU]<%FW,AYGZ`,OI&9?45N:-;EPG^QYQD7TIE2QY@"8)F: +M2F(B$%]/PVB0MR7G6<)MWW.IBE-(?M_:Y(GTWG>UXE!323\1`>(E@91/>VE#Y.Q_40)X?$O`/I'Z +M9T9N8=/('*OK8-`"=(BW?J`1%A-7TR%D'1S,UC*L>;\OVIR1H:)'DNB53^_9 +ML2E+F/HGMOU1S[&_^AY9^#,SE;B\?0@F.X68U)YK!#U.UT]D(^A?RIOD7A^@ +M:S/B2?CRK5X+%S/$QMM\4O05T&]WH;8@\4>L5LJ2XLK]N0%0LP+0#O/Q4P$2 +M"826BL.XU;F7L"FJ%.&SKH;TQ*X`AN)I_U'65=20/]%6,D!:CYEJM$V:@("H +M(%'YOHG!!=L_UB1DD![S_R`DXF)_/MH92_)"[3\6)6ORHQ%O"AF;ZEL'S9*^ +M9"P'6$#(DQQR=XJU9CVW&OY\6K\5&Y1&^C[LZ9)!Q8=ZK[AE%R*X+[^2F(62 +M6]W8?G8C[HY(SYTQ[XI+ITC5XA'+;G<,S,'4<.)X&[N/I66K +M;M&-\T'2J0WA?X^7DUMW_U^RFPK)EUU(G?!2OW-)>YP$QJVYKMS.%9C[&H4J +M/V"E"-*?RZZ;E'2OUQ(8F8:/*@^Y:.[I-EWT)@QK95ZV-4#&[)7E@U2@PXTV +M]U1=OM'*YY?\G'4'L#!52$.*!Q\="I:__C*2ME!6<5;NGQ3-+4VFUG8GR`T) +M8+KVJ^R)9QNKI\4A0#*Q0!1GFP3H]1["HRAWZT6(SG<%L_M&=2]/5X-31.%=@$CTNL-SVXDD?O*5@*@1(L&-CI?0BEMS>'XS)H8?T"1#:. +MZE:(R2(18W_4@#@O`[^0CDJ7DDP6U4)<<^7S%98 +MQ1[>U2+Y($&$=BI&LO!3TWO%QFW8,.SUJF+BD)M0QSUA<]/8"6PO3EF7.@Y= +MC7MF=CTH`4RCCBK""U_$)IG\JOF.?19#Z0X*,H=K="CHS4 +M4:DX7BXV4!CV9AFL&37I9WV^BY\YGS!K<2IQ.E@$5[I,"#.\AQW1@(267PDOR?D[YD +MW+S^]#9]0WZ]SS*3:"V`"Y>"LCN=W3:Q5B^UK^WIAAP/]_IO41PU&NN1MH*R +M?-,]X02SA@.,[*4G#PCX`ZJNC-0>QA(03YC^]((/PXZ"C$UU25!"_5V)?U8 +M_6^*96]N@-UF-M?-(SG<)O-Y,*S`TJ#O'HQGEVR%@-9F1*@4UPI&4[D7PB_K +M+Z0L\;,L>^ZMVN+V^$43K\IQ!KG052V_,Q]Z.!DD%G$E#-C&PN3JX#JC\0IW +MQB^\\_.7N6M=#'EJI[F\C+$56;[NAR>I\6[#`@3^[LWL^[ZZ>,M-P0;4/#>^ +MM&W5,"II7//=&Z-:GH +MYIF5XB,;=VL8.2;-(V6#/%L^]W\/("YJ@6AO(1U/VX*RC=08KTLH'3:$_4'\ +MMD1'7M1E\[,U*]YBV@LPAWDP9M(OQ3+M'H2O4^&TQW]2=Q`Z[K0/D/UW*"F^ +M1!/Q2)>!>ZR.[6ILP'B_37/BB)SZ-AZAE%_O!W5L.GUC%TP,Y*0RL&:I<(C' +M&P!'K"PHD[9@!Y,A!TE5'M3PB=QS+_#R\Y6(W.)Q0^W9BT3[QK>?$8/&KI6@ +MT];TMJP<.&>X$^RR:_A*F=`V5>1G#+5:;=`/V!*:7S>+],^1J#GDNSFR$AQ; +MX)R:!J=.-C>>7*[./[HZRXJHNM4$&BCZ)"PB_=.$;J_%J<(N%"U5FMS=_CYZ +M?QQ@6&1^>M"O3Q,3DLF`2`WYX/2T%7Z82*+1RI3M2J(Q)657O!VB>F'CK7W. +M&/4_6F97O5^.,"QUA?C3.*P/.17(KB0$"LLHV"K0V^5J@$'2AM8V5WG`!]V/ +M*#("$MOW*#63EH#60)T$P:1L8'."+,-ZV_270^8Y40^$S)%]G0C'XRIN)8C9&1CQ-G-A`:WKA?G/["A"2W\8I@PUW`>FTR3< +MRR,4^S&Q]7^JJZKOC#N@RQ"G-J9UF5XQ5K';76#EA3HMEX"<*.7,:2+.?]!Q +M%4HLZN)G)Q:#L1O8("C#&5W.@Q6/H&L5M"-7E6'3+C*P`VL*N-8NXCEZ-MKO +M&='U%QP)(]@J)W/!^V(-LXM!F2ZY("\UKU3FX#RLRM.5^K,E\#,Q:V8HM;:O +MM4^;#PE7MVIYHF*?7*(T-XLC6OPL44\W72Q5AK8'D9Z$P'-R?UM,RR[B\2>5 +MEY;RG+?_P[&>8,,\Y8@*,%?YP#C`J3^C[P2@)X&TG2LSSNA_.:A.]>N,&*): +MN.BLGR_H\\<-*@UPP&P_'.HMS9Z]P#CCD-E!V-9;!(ZM1\'ZP>Y638KX*&U8 +M+-K_BKA[O9*L-CP7N(N`9(-)(OP@0.(>.D4$:E:``AFBHU\3W1=O_\UB%Q!: +M-*20`3;O;-'.8Q#+.0/.^-9FU\)NV>O!H08L4[9 +MS`WP(P,&&8/D_MG$QZ*@').!1D(F>)T3SCVP4X^U-?^C7L)'T#KC=?0SVUFOJ +M>-&ETX$'X/^YR^\Q'@$EMD\A;2*+1I+VHAZ$$'P?U7_/G\C?5W`U'\DVUF+GK/^>IJ&[4X_6A +MX4U!M),E8$DF(%L<9?PPXD$2+ZD#Z>RG-=B%9>%,_IB).C-N9N7FW#RCDGFF +MYAZ/?:CIGT%J'T*EOGTH'5C'B0<+O +M-WAF,M]_RE&,11]\(6OUOP@9,C2#*OY"[1)P2#ZBM)8YGC-SVUC*F/7/[,`E +MH2)*Q*KL[$7C*AW,?E-H&:E_FR4[:*671T@Z1]PNS8*2?1CI(),?937:N8B3 +M8C]\FHUHTJ%W6.QQ1F&&C--!`%@]9)RZP-N%*A?I6WR$H(T\-@W8L&MKJ$!Q! +MH!9(.NT-AK:7L,%`DYOX4@KIW:T2C!*S+&(ZI@BY=793AF&6#9"&E<-<="S, +MI]!X@OOFBGS$B>K+'YGW)T87-A2`J"`IHX=I%^&*T8IRMUK@\@H,7-H#([U> +MO__4?#O%L7A=19W(::&^3\Q4LXVI4D+#)).AX",[4$?'%*SYNG2>IIXD_4?J +M*58_]/82YPB4N^7%6?)B`_`'#;UW^[?RMUAVF@;61/I);7-UWVH.Z97*5S<$ +M1TW\2PRQIY?:08*'B>(2-N.WWKF +M0$MN1[L`D;,0S_$.NAN3$'DU[R@KLQI^UU]W&*4(=HW^DNYXFGTD2`G?D\LF +M"3\:+%:VO6$;K!)`>_BGCV(5I87-3,CH9+M8/:AZZOYIMZ2P/@7$3D9WY%_. +M`75Z]:09QM@+DP"U3?A=X@GB!Y'MFVL`I`C&H4.AX,_T`[-.G(\9_$-7E5MB +M-68Y8RF'7_?+NUI.]Z"WUILET7J6H/CM%QS_'2-!5-#=4<));M;8+P1F^NCJ +MP-HD>DI*B"!W_<50PM-1N:8EK]:G?"@)L&B:#N$3/IGNY2E2%Q +M2V(+G2.I+D>W8#1@<_:`AZR4_99#I02W6?M0D05=4NTZ!;[N +M2(B4UHA;]C-/>Y@2STUN\L=226:OZ/'&^>S/@4,6HXOKK.MY+)2F<07A1Z2_ +M$A+9-BG[(476*PD#X1BO;%T$&:]XC;,%6B4E8&7CE.$-OB5IA)9;H62;5IR8 +M:PEKKH.3WH`2CJ"^0;H[2$$N\(_ +M+F0&7J.MO'!'[YTK=1H:EX\8/<:\LI'N)P9K^"1F=>'3HQ="K+ZEB'"$DI/L +MKE':'TS&L$!!TF5_Z3%E<&BFE;_\UP*5K[SE]]?B&Y'_?'(ODS#7V+>1]E_! +M*O7W-GF<.%L3FZ+)WF!/J?2G-[9MQ?XJW;#C7[1\W90-FDCTU#/\L>-0U-V& +MK`(Z5*GKY(]FWLG>E`43URB\0BZ[\4DQC1J+W`5D)X9ZC=D\4>S*R>]E;A(G +M3W^S`%E3LW5&AH6X6'KI"DO3EPKN?>MBDH@=V;HH`10?)%L./*T9/:\&F4A$ +M9FYF2F0M70,+/[JEWX'V+-'Q`LRQ9PBA`[V-_989HV9WR[Z]V,J=`S`8)?V( +M.OWMYM_^\NZM;XZJKM)OO85C0DKW!KX37:F811_L2YH983(,.CO>F=O(\4Q! +MNG3)H_X+4[""=O4C!NZM'5B09:4D +M*62T%T\.`A`A?-_1I.=(_4_R*H2651?C*4Y0\XD[4&*%#KNBESJYQE05_(3= +M@.>!UJQ+#>G/0=D\X_MZ26K>02?49$>138'(SC5G?Y-]PF$M+&[\&4U(OF`UOGPZ7P?B5=0TA_C\09D +MM3]^KF,U1>K]P(88>XPYC<+4?C">4KDP@;;7QFJ+,S^J^@$\V"A8&L=1!V_1 +MC>O^[L,`F1(C,JC)<1>%)_=R(U@G:&'6GH&-EG'^[1P.Q=LO]@WW?^4?*@KB +M^+-@Y*K7#S1R,?3'9"?+6!RNR^NV61T@J[X5H/](:8WFRN!_CX"#]_^@$C`_9#1`1$-NHU`C;J+X2%`"/0,&!6+R]U'PR/C8)>/YRB;N;`9 +MO,^ICN3H:222\S5I=L>(E*X4K`)+)37&DUH#JZ.\,PD)(HJF"T?[=>00OH$# +MD1(ZS@5&G*F-3?G(BXM_UH(4XB'Q?2K.,.T\H`K0JV1-%7OAN'WQ^3\P(BDC +M5M.]\8!TT(>D$NA"L9D`QUU-O&"] +M)RV01)6M4Q`>'X^A4YJ1?I]P\9:^=Y[$"S_@,-(T-79HML. +M2=KE>Q]\.!2=8I[7Q)(I&0$B0E_)[T8'"0]+OHKZD)TD^I7@DQ< +M9!(2?LT\PE2TB:NBJ45,*8J]8TMA2D0Y_.D7'S*:8LQ=V=J8HVW_94B%C^T> +M/C#>]2]#(XQ;PP[QLBII:%*/#9_I^A57[Y6!:3\Y/U,:F +MK`JMW'[G)N(CH(#IP/(Q__P\8O:NORA<;_0,(@D^MY[L,:/;!=/*]95/Q!NC +M;RLU+$&1?^**8F7`P>$N*,5#"-:B4`6TO6ND8Y/.@'AM7QMGKI7Y>`2R4=&> +M!%U;(H\B4)!>(HND\%J:M;VE7T`L+5'X?0+@HZB#-H%5Z6<`OTWLX_ZI@$QM +MFI?&AOC&&"7M/\=@MWQ0RC-]^%9=0NO,D4)=XJ5FJ*+=3BY$AF?EG]D1U>41 +M*I,Q!LPW6*"/7X2%TT3L"ZFM/M;3\&4L;;3H`6?%J3$?M^7O'&(> +M+ZC5HB!YV&5_4UQ>1D0(3"YJ"-NJT'G\8#-PHD6O-Q<^/I5'V0!25;C`00EK +M9`!J"%9:=J:MV=" +MIO2\!<.2Y;(1DCO/"#&;^5KO'6%:]2:M3X#F"OW@2!0U4I9L?*V:9F?R:6W(E'/%X1-,76S50Y]DL?5-5A08O]LA8L/P5'Y=MV'06<#WBVF"M1S95!N!@/ +MY7S8N9@JZ72G0YX8DM,3;F$G]0V?HEI;]U8\&1!@94#U<`@Z**!>16@[H;(850@6GF7@8[KD8YMT@:7_2:7N/.C#R +MAI'VY>G$T1>G2ZL1PBJPUTDU0$;HK+M!T;5:P&+E.(H]Y&96S9'KE#D`EB.7 +M)M)GM,?',2\D[*^DEET#:93/.\FYA%FLG,+(824@/P0W*Y?LF8_P[RU<)5^* +M7@R@:=.?_;4]5\.I\=.6L.)(US>![Q8EYS4F3&W9'1N$[SR1X6!=_I@2AF3: +M$+Y-A1X$?^B4$)DH:^,DY1.:UA$\.MZ-92\4KH3U7O?HW^I?V598 +MW\-9%/Z])XDV''L;C1M1TMA`(QBPQ,U.&OO@]$[K&&#.836QE2P,QBN\\+AA +M%'YW+4!0[[!/[9@0.VZ+=-`EV]6F2 +M:I3HKR8/\_X8%Z=Z)8GC-\13()1<]>.!>W)3:88LQREF[7AU``$)U(D;C3;. +M*)4!^W;SB,-/JFGYD&GO9^@I6.VEPXI&5;`.J/RW4)=E;(UUK4!6@__D"#DY +MB^-F8J:(B5/`I@DQHQER6+8%_^+/7CN@!RS8/N3D;1(AIFA&#)QL72"/H?6& +M;9D%I[6%ND\7,W[8;74'PFD"+SO"/=U,\*[%63BBIF6S&IB)FAN*_@QX]-+'%=)ZQ86&+W&G?UW`TL]3_O*L+UK5/R+ +M4L>O3]>%*XJ7S*ND*<#];HU"!RDR.K-1'_/[%YJSQAV[W:UDIT!N04-4=MDP +M`9@^GGNYX9JOE:?`7`%71`BF>R4\FP&*%]L7R`/M^"B?+E#'K"LW5V80(EGY +MK($FU[,?\'*QBV;J3BGK%T,1;B"PS^GN>J?T.K".R$R(7?H/`-RQ+?YR!8N6 +M)BV#!FZEI4^?>6Z.Q;@/@&,(6*G+X%9/7F'$/'%2RX"Z:40(V16@=@Y[V5A] +M0AI4JC4@YRXN@8E`:0N&SB==(^_E\W?":K&&I",WE_]6[HAU*[A9T +MN364"8(A+?4LM05[`RTYS0J2"/Z)WWORWI$6D"LX"U4`!(=TFE3$6?$*165Y +M,:*#S\74T38"G[,>>]NT4F%?V?L@[VFCO7W6PL1)")8=<-!7L%`JW1C^E:[9 +M"#R50HO8TJX)FV0`I@[_*9];9P&N8E"K^#$]_LZR0(2PPYW#?T\VEO( +M.F5EUK._"WFW<1#E)WGEOIT:'95'?UKQN)1R&H.B[2EM.B8;U-T!A`RA-7I[ +M&0S='3]WO,I?%@$?YF>*@-1$=]J(W\22BLVP9:;W7&[*PFF'!D_).HV0:R_P +MVTR-+RP$E26C`ZN=B"FX"0!D;1!RM:G:53!FKEO]%Z.W=!A^EL!23EUU;V(C +MV.?*^AHB/Q[UU +MAZWIK.76)I3.5($CN.U_;FA()6I@D^,KHT6C#"J]]E]")ANMA&EHHLPYMHEE +MY=W22E1*Z"KJ]@@+_+?#1\67P_=VCBW-9&FK&4LX#+`,]BL("%8F>UQA?_I8 +M%E;UV0RI".#LC2[`A;!9IDC@0,OGN>AR2:LW#S/6W8-UH3X],U*=88'`X@V; +MNXXLLNQGN\4V_#&VN'/>@T2(QQ.SN\>4'("M:Y=.33KKA1$%S-OT8]AZVD#X +MN^^UC7X3K#(V)".K8S3R(_I!NFE!YWA&D$8T\%_7\LF@@&B9D/4]CJ+'/BAG +M\UH/YY@[%2E7;RJX\NM38PN!8\D%^03)\!J&0Z"6?\U36X\S460*R:5 +MNIW+BX?@.K8/?DQ./^U\>/M\@*L/NM[W]24J@%@PPZ`M\_W=-YY+%:TE0?D$ +M+JI<,L4Z*$PYXZ8?CE^&_"7`YX!7\6)/S=S$71*#N4U,X306E#<,MAA&_L,# +M*`TH1*T]RH$9S+(IFY5/@XT(F9TC-NHK@FA?(:P6`-A[U+]<*]L'R.D34N^? +MZ$D4`],SPY6)9`4ZY/#9$0N-1;()^TYWD(89M@*AJL,"XH8@&R1;D/+%_OX; +MCA6U%E[#0@@,1_PEC:T@RA9TB6J$EZ#.6:8@(+YK$JI+V_.7?\=\!2IJ='CL +M-(8R[9DDL'3,6B$[4X%OH,H5.97B@IM0*$M0S1(']=28 +M[Q7"T$."[ +M.RZIQK62@:Y?],/])0`ZDGXN@_\[ZH]]^N&,'$3,&0/9Q)B"P,_6%)(.;@*' +M%'_T=;&BCX2_0G(TB1+UWD.!S4587QBH;!*OJFX*(0F!5N^FQN#"M@@Z@/J' +M>]B>D!2ZUYVMEDV`\*X8FQBJE:7)%9K98E,HPY/( +MQ$XRTM*$`P'+$)VH225K"S.-MS)\+GP%1S9L3=[*B1U(95+NX?M2^I!Q?MJT +MJ>01):%V*YN]OY%!R?R<@LA;]>&,'EA7G&2*UV)I,)',7-4#`A+B78DO\7]P +M*BJ..6/-$_L8L(=6B$=\P`-H:IZQWT,`Y9BT>!EP.6'VT%H9EFPGJH)!HLA. +M80D9S$0W_E-$?[KY1KJUC&+68ON:*X&`ZD7!"[Y2BC9:E%=L29^LMOC)1AM@ +MI>2:;53+^#\,$4UL,@>R5`5J17?WT`)RLO1L)3BPGC(<64B3]Q0H9.$],[,\Z:SW6Q:7Y!<9.:&72#)&/M=]8);*C8F`QJCSW*-` +M^`U6:N$>TU7:S^,>=_8/L(,UNS&K$^^8+$$W#"'@+[&?%H3IFKK_VI+JYITG +MF#8+@KMXUNMS5:4NJ`/C63P2=,-B?)2)D\Z3+>>PSIAMBD89_;2@@K3@9#L( +MQ5#:H?WJ79!K4Y2_3270]E[CCY9/C:Z=3K_/F2'=4>5%UDHDZL8:S&O;_Y9V +M8YR!+$S@H37@E1NG5>4]-%%B"?.5RY"'DNG@.0K1#GD0L.UXA;6(4J]A]<)I +M)8MED-$V+LK`)]19FZ:&')<\=@KL4[\#98:DB!`+G#-DXI +M,6=<9,5+Q0X70\+;Z)=28$&[H7)`0=$Q+SCL4-Y``Z`44*N&JR4Q%Z +M@U:QHN6;+^CE4LJ1BBBJC/NN/4[RE4_5@;M]D5U)DP>E'Z_+2U*N97F]05]Z +MZ(R`I]?M!P_]M-1<4#"%S10<:C@0.H)D@O'N!JXYRB(D)V5,4S0%%`.1:V1% +M']BT>":R`5N^A=9]-?!EZ6,2L=9<8JJ$)U;_NH#Z0C:=_2W"/!+RD69+1/7T +MCAK=L9"R';_F/^*+Y!"U19'G$\0<_<#7@?5V +M?@#EFK*DT=^",,A7%KJ\\"F/$+>.O_[($)AL./MJ98;=5+$G@GXZ"!A*,Z9, +M_8N`ZHF=ZDYN50==4]^H3=!;^"3&>FS(,6O=HCJ)8T7PO65^["3 +M/%\+RF8\=`086A./'_MCB$`--#=(0"/U/+<<_(5"3*Z5_U.=E)K,KCS>0`>\ +M'W3YPX/`Z>#C$+1<$M8V7.?N-&7*%EXEJ:P&A[1I2C+CL!8+=-Q^D8R/2IFH +MRBHV8G_LPJ,'\NNV+S$S^FO#I]J&=^@XWDZQ=&7"8$.-(K6S6HEYSSDF8*FG:QE(I(/!_ +MUT("SP.JG.K@T3NZ9T4,^VY-D_P\PY=J!Z*2X_CMBCO2-`[*_"`W7^%L8X>Q +M4^(`<+&]UG('WO2&:6R!WEJG"QCC!/]@ZM^=Z`X+33=B.J'N]"QGL.#-(W*3 +MU>;BV>ZAOVU!Z]L\&W+ZF7!3^/X.V_^(<_LRL'JO+F;Y#W*FC42'F,(281MC +M9CQJ?0-ZN.;G,)%Y]0)E]X=?AKJ^<'X'MXG-2\QAB8>Y1S?W@`AGK`"7C:U!Z0;,$S?G%'X9UQ#9O3:$2F7CW +M#ED<&N'$.#P>?CAV.&R;%M#[+.*(*-"4N_^K@TRP.HE71.L +M+(>C7(*&*QE[=^:$J$BG$::TIOVC-,T^\9<;]/F^J;ZLL'5.0(]!:0"USG>K +M&`9HP&OT"O]_J>HH;"%C.%QA3G@4((XAY;S,W^LVL`()_DL2=A?D/*ZIW_^U +M:3SW(4^/=H;5F2BKB?MA=LM[A%1SMBB"`#=#;/JL!Q-XE/_;]KXFXPI#:O\- +MK?F@'+[3*CW_T04"LS;)"M74I*MD>_(A`=V7M?=?OOB+W]8W'QU@BQO33<<& +M9JG/T4?A<.4$['NPX[SI-9*>96K;AI/A'%^>/ADIE*S7`@K0D!TVLGH*76]& +M;Y`Y9TI`F(]"GD:IQ+L.S:$;6#:62=1'B`INJ!1,QSR==IA[6N59B1]>!!M9 +M/M@1)U(@&X7;*.'T88M:4BP?;L^B"GN-)#(5D!@>-Y&`PK9-'@K;HQ*A6R5] +M7419=-(?S3,Z>-W.GDBOIZFJ-8[AALHH8N*O' +MC>VO[QW3=(,"E?`FZI_5&:REO36R3;$GG47,#A=$,;H9&8!(@&C&_2OYB<&\EQP`J4Y2J,F+ +M;Z2^(`=V7.RS7F^!7_\ +MES&7C2J\TCJFGPA+/=K);6BETO[_;@#)UMN(C\<'TX,+(`K1BYKX#/C: +MLD3F7'!O>>S^.WB%![)9M3*K129T +MA#K<$["ND>IK`-':A;EZ/'T:-(_4.)!#4)7K.P629GS%NE_8D#>(-"::Z;M^ +M3R1%-2TX=UBV0[F2-;QKIMU!MJ*]BA23"-M(6&8Y%WAQWT4KQY:1"#X7IOVV +M8\^]W!;&U=3M.^G4,/5TU<],L,T_L\DQ[CQ]%XH%B=KN@Z"6R<]?U;7D':^& +MO0QHK_Q37650VFB3G=7<69\'$\G]=R_E;ZIBB;V49_B&$P),@QH6EA5SAT&? +M]R+H,\0M^+?J\2M55NKA>PKU;48!#A`Z2]"^0XU._R+`V;<7-I#.0B*ZYDBD +MT4<[J/R^+%^,JJ7C/`5SBRRN9$"FQN;G/9G`K!'E>_#=)O;?4\6H-#H[R)@M +MD986_YLAZJ0=E$?;KL/"M#:_A84!DCK"N9+,+[]Y&S*H8M!$3=QW`V..\#AD +M/17T7^B!?YO2T'*]H>QL4M2/R@,5M4E^WC/-J+`_`8*OX6-^E_NE7U@#1]TI +M\^54\_+OB&%6LU5VYW@7O>+Q>3!*BEZ'IJ&ER0IZ:+]/RY\=BQ\\ +M_IH/##_(9U0B&\8H%:7JP>/A9"]G@*&N;.=0,#7G,;*K((^Y[!KZ4L402KG^ +MKG,4%,5BO#_UZ9+>B&EH_:_]%Q`S3BVQO(]KL6E+@8MW*^P_!ECN]UQ;/TJ! +MUO"F;K0BNZ)/>DIWL)#\QPY\0WH:F!B:&"VYI,0"1X7(PW56CDV:>/M +M/[W!ZM#I>0K%SAR:*(9"]]T9CC+@`]\+2"4SL-FS<'>F0=.CL&2$O^6-=Y]# +M4HYE]!NP&?YH&H^V2N4\&8J'Q67+`YE@>Q4S#/<'%7YD@UGF`]Y3MW=E,A0& +M1$$+]`8_=^"BE82<\K["()DKDVG'R.I;IR!N6.FLHMI>1MH>%E;1HSBNWAG5 +MO$5:*3@'X2T=[;L\8MGTEHO$H6-LZDRW[8PS-$H^6*Q_M(A!ZQH",0'F+6J# +M=0?W$`>W7@\CE=S`GIQRPN(LK`%&QR74=+3?B1JO/,VOW-WLK39NT`7\O<_/ +M552P20&"`,:#\><%@8'\XOC/U;=^QW7+O_2'YOM!(UEHB3(GG:+^ +M6##3/[)ADFB&#H%E7A<):;X_A*UX'UP[LH>Z/)(:Q?.'X^&&6&DS8SQJ6@ZE +M7Q3:9?"IT8O[@0XRT9)W@YJ+J"VAPC1')"C*RJV7TLN=WR%L:%W^YLTG)#[S#K?,)`?KF6O,5.#6>OA`)8E\" +M.@-24,D&Z\V&RL)!.HBD%VPAII`=_>WBMS3BQ,&:?.DOG&_9YN/@*\*27MQ- +M;-_1E(4%.=J=K_2?@#3Y'-L6*08QTR2@J^=GDAV44?E%6`WL02<0)G>Q/7@[BKCZ?Y>?6XCB8X6C3!E)5L] +M*T7Z/6HN0[:M1%_[A\.G@%GS@ +M+IK8Y<1*%;2G=$:Q+.OL]>I9!%S;*L[,8I*F.!O&TCZ5,?9UW3-(C:".LJ;D +M5$WE`Y'+_^@MR>)*486EIJ(+I2@9XX?<;]R4^;\2`[)RDBUU$`D*';$^,^;- +M<$VYZ?BNC7TZK@384-5I2>[`,]@T.LU;[(3<2';`X_B*A:)YYQDG9PD*MEPY +M.*I3*EI;A$9O:I<2>F`NH."B#K!IJTQY,1 +MNG)IN&*%FMH>'+HMZ-V@+UO4P-@)IJ5TAJ'@/T`%88(]\:`2`-<\8&"J5*DA +MD^ZR_YX4,*-V)&@`QF%E0K3=OVZR$#3!&7LZNH3;BJ>=]'8R_^(5WC\A83F? +M?K****06>A"\8GP`\VP#2<$_1;J&3VX9[-M=Q`A3.<#]($P.QP(U%KT=,KX: +M`F?:;8HD`=T#=AY\@RU%B$GCASN.S`:^R+"1Q;O,"H_0_2_&:8S^4U37;C2='B0%`BT])(LR80$K?C;DX!N^"F-T0H?\`=9$0-FI#)OYEF,WURGI&82 +M?]";+\KR!KAC].0A@@-@;+(`VI9P2:$[D?`$?6K9#< +M60TS1,QI*B)3$["$QWG&P\X_54Y8F:1I5CB)@**#6Q@T?]^%$FI*:SWO\+Y) +M:CI$VOR8[SB/@@^&Q\R6BNHM[="C)S(S0K1D=FDSC&28_CYI]S,P?6KCU[*6 +M@9`QO88>B"^`GPU:Y9J3#P.VM%=8'CJ5$6VBZ^L&?&;I@Q(=)*":D3Q_KWT8 +M24U8"7U=A\B:36D]:P8@SZ.@FQ2%!?[_-",26R\7XW3>;7A\VF#PXO*IB+\* +M$/_KHW55&EFT3)6UK:MH(%XH<#BSG2B-A*9NI`/GKPL--H;?N#,>'L1LOB@0 +MP^\LKG&3C3TAJF4KQ_&>?SC_2O>T0?QMY+ZW*A4'27":+/UCT-DY`7*3@.V] +M"#RZ-DL;JYH0^328&^\$9C7".=,@ZQIN;8+F9'F.N"@['K!A!:>+X`[./QX8 +M].MSA[.`#Y^Y3R8('`T2;_\+WBC,IP5AONLAQ"0$&D79I^6TC^#G-&"FP@IW +MSY&@2(B885_\W^&I\!%?U^FG>-1=+>;"*&AA:K'&H6JIXXW#Q(\-.!$19':O +MJ.R(@E!#FD._LO`V?!TYC5L3UL_>Q:74Y8=0Z[/'2PSPF&UBC0TGO8^V +ML:B"Q>E_4WDV0B6'^^O78=[+-U1;JI^>T8UPUX5D9^CTK6C">[9-\'KUSLOY +M_=X-0BQ8<])'(G%(X:RRMNW8&.I+?ETWIWU>'$G76&7A#EGQ'1`AL'.+ORLN +M+#=KXHQ$,OP4IQJ+.OQX6<(380I&-Q8=[G^"*D_J8F^0;C="NYID\V(W'$B* +MZ.%BZ>8DJTE$*8VN00P*N`_JY*+`Z]#E!=B'O(`W-H'J4<^\SO@-(R#T&7),4//(BL.VHS/->!Z!$;W-&^A%1Q@C]4.3V2]GG#(-^"G`>`:GZ@%I6O +M9:X_[!DODOQC4KE=RCB_Z+)K):'(D[>>>L,#>7!'$Y#C9/P2E\\+^O_CYQ+X +M;]4V:J3,>IW)=L;*[-VR)'S]/>OQS#<@2=S[0T6WE"7H=C__;?&&-L2@87JZ +M_?.X=+$F"B7[%;$,6*%NED_3'8+6K?MIY-V/;'YRC4=@(*('PZ4GRQ[NM,<% +M5!(DL[)8P^QQF^_-%,NX`C!D@5$#+.Q?PO7;?$XDZ[8O6K5Q6Z("?(I8$_Y2 +MGY/SIS33MH`?5O2Z:#*3Y5(?;0\@LT@MSIXW2C,+_)B`$P^9.].#NT26GQR! +MK-B'T%-J%1@S)Y:9IA]ONCJ+7WM>`F7\M6R3Z*&?^S+A;V>-Z'0L7+I"T\(& +M_DIF?(]0[8M_"():0/>#I,OFXJR_Q?8+O:-9(C\+%=4,5K"E-XLGGI+U]03T +MEZ4%(?'1;37#X;!]Q28CCT(QJ!DA^X+XE/_@I!,I/X`0X7NVXYE4Q=12X7O3 +MPD&3RH&GP%KCE](+PU0/70CD%>1B78BZBIYQG47._]D`L^"P&O#?;IL1>^KMEGI+;^G(^FW27*R +MD9^?4I@7<'@#>Q71[U/O1\^ZY[C@4/5H;^70W1=*KL%:0[?S(9CLFP)8VRIS +M4?K6&N@-D!9$@@_# +M:@$SMC=?<\JZ458+LPO7%-GNN\N6'W`R-A/,.Z!%*6+X3([<]S)74CMZOX3I +MIFRF`TH;,XEI1.R`&!@%R>3R3_?G/-26!A@=)5^R*:I<@@[%C\^DO?PQ^Q +M((4R!-.QL(B]$P:QW(.US/UMVLG":GB$R,.`V`IZ)+@236(3:K-AAZ.<#<_W +M]?BK>;GM@_)N"$G*EY4S]7%H2_/94CPT]LF2)>ZT;?HZFM;8]FF+$QM/K.\K +MO+ZSP>+F"5I+YPO&RB&C"SG+*'32.@V<.F3)X0$GZG946<")%N91N3D8BNH( +M:&O]7JY4IIS=2X:B49A-[=5%O:'PX*YD_W0L:L-D +MQV$OGQ](*1>]L?ASL6KJ#T]B2@:-F.#D<(2XC.F5<&CK" +M*''GA0K7@A:Q"O(:JB)*`8CYT4OJRX)JT=%2"D'RB0XPH\ +M\>6EOJGZAKNF6Q!7-IK7PS7USTL#4W@92OE=:A;ZD;MC*A/GN,L^X8;D&LRB +MYW7NWIYK8_6K1*F]D]^0QC/8S<,P/65M +MZ6NI-^K?5%5\@(W#CGS/J329?!^GS/B68_.2JHO:Y,-4*@9XGN8VSU4S%C*> +M<#L]D;5*!Q^CIN7=KQOR_ZN4QT+JKB%LY!Q!]4Z9%8H:!GC-@2S`K>H%7ZEA +MI%2I=ZF$T6AWI;T[6IEA;RRI@67-5N-6>G9>&`JS:W[S<&MUO*[$"5Y^'?ND +MREJZ$9JWKR(RAL+C=/*[6W`)6RZ302(@Y/X#@7;`\2C+%)9%-VP4* +M`A4]F9]Q`G9L`;>(A/%[:14@'4=5=^J9=J<>@^B>F24UA/A"R&;?'H0T![09 +M[3Z:4XJR<3$\^//O&]P;_]+P]5I21TJY-_D>:E5%XDN%6\42I,DI##X6V`D, +MR&Y%KK24B2\E?(32X]+M88W%XPE70-1>3&FD"O%"X$A=W[?RH[!U)L>*'%9> +M6\W*7PZGN/OF`P.W[BD99SJXV5Z!>DT2Z''+A?5C^?%Z>4Q0B$(`Q;HE(TX* +M_A/%H^;BPA9^EV@XD>J2DI>1^YOFWL,X+PW#C\T:]DN?/[U\"@IL=B.OL*IK +MY"&)1P?)-0XA:#,N#BC!,:,I0)_V%(9UA_7#@^K9^P?#@EE7I[>')D(UMV'' +MNJC<8X9]["X+,#(L(W[BF:B35'2XX/Y79"C:+ONYW"E3B>Z7XGJHK_A=,):F +MFTI5?]$Q*87>-,6:&D2W(%2M8]2N'_&@"H,21&%==@+;G&[U+-PJ_+!E3Y[L +M[B@KQ+7PL'12G--#^.W"9PQBWMA&?=KF!!_-(LBL[4AC/FNKYV0)NP-6G6B& +MRLU<7'33MQ#AL=+1CF-;]5GD)\]]'2S9-3*N@CJ]Q>J"6#()GGI)/,E&^J&-.4)X+#/VLF#,-;JW%6(51/OC>1A3DK_0!P`D@<&/3 +MTYXDQ-(POMOJ!6\@$V;!V*'VW6AH3W`HN``6*9L6++_^A*%FZ%DXX9=#B#'4 +M>PD"Y!A13%J>-`$1.LT8.*+XG2?@3"+=G,!.BS0R:-E +M-];55./]V)#4AZ*9@(!]?^B(*Y!N!F*VK;E/A/TQ>'U[\,M!-NVA^&2D+.M< +MD.#]@&LGT'&`X +M1$LNBFBB15$XL`RZE>V;/85#N1Y9W5N=Z-"Q7H0/;3T/$Q!0ZTR0"'=83,B.BAQ@)2\FYC!=_>?RF]Y((VR_Y4#1WS +M*JZ_H)JON5ZSO;,S27FBN2K/49VKS('HOH!*FQM0=V":,N%[3R3X101_.>V:-AM6A$ +M++5WGIS0>/Q^65$II["F?#<_*DZSZAG5_#C5VG:]/B;E6Q77NT=-[0X_(Y@,+_)4CNF(*#]-AR3!;E8=QC)NH7(@Z1#TE +MM["(2HSZBX@>5+55ZHH?`F,R/^VC1#B\<:^C&=CM:CKP)>PJO\=Y"1ZS72JT +M#C2Z!COG%'K[V'LL>'#AIL:#EU0 +MW`ZQ'2GSGLI_TMV-^9OM>@JL+,Z].1[/&7-47#1[YZFVZ^%/-SC&7%@?/UX_ +M7$N;K0\G.NE"V`E.;KM(2+74<;4=PL[<9,$7*`\/'Y;/LG;RR79.N!C^_TRE +MEF+WJJTA,ZK;AU#=3S-#VF>SH*@^I0G*BV`2HVP#!>%RT%,@ITV[K3T?*1_. +MB^@KZCV:>W>,8XAHSH9>"F)/]L;2,\:#`83 +MK)'9:?*FS<-*V_/]S-IO&BW6H/=0DA:7T``*W?'&]29Y,;(O?]9IRH'J[*4> +M%RH5Y,\)HG.Y@?ZR@E5[7G9SS'ECWPC;_7U]]ZYCD,U=S%DR041@/F;#W^=, +ME[1P^U]GR!B_E&TOP$$4A<;X9XR\D8O>%U0\N3-MP;\;=-V#$QB^G]=H7IB +MV_R2X]&<#A[/`E$/5C""'6CY#A:*=`;3%9-TD)(DJA@E7P>0U##;]/$W,&?S*`[8M)TJ8I#6K!IZC?3A=!BV.%*S[=1?^T[5]?Q1:?8_F[]*58<^ +M]3_"`8F[D6F7M*_[,D0>Y#M3GZ!]"8?#X&HE`"/S^>HSJ&1`(.A51A=R7%(L +MG,;:-Y57V[\7D>3&BZP6)'/CX:]93#+'>L91>YL#QOEFXYAH68"^27(8A+LN+7H-AD8%-A^=I%1M]]\7YS[HY*GIKS1:O2@^M"P-O`K<]+&3W0RT@;C +MTP0\Q?4J<6JHEW"`3^OB4[(*P-<_ZKL^]T>,M!+2.YG'FV\@*Q/^BB@U,AF] +M"CG/Z?WJ==^` +M]07N\2^V[\\AQ\8ADDDQ5ORYL=I$TV>OVO8J39S_P1H4PK+"UC]8J+F8IQ>1 +MZP\OS7$=/+VXS%T_$\5/"KHF__254R0$Z:K_7?7#N:A3_)3CQ/GYB!N=PQ4C +M9$L'W/P*>@;YAF"K"X*`.Y54]"\Z,+*9N_0ZV@O/>B/T@Y22]R\[*Z6)/4I0 +M-A%:N+Z;?=5Q'Q;.'\]'8M +M#`N92=*4WU('Q,'/PR:3OXQ$)PJ@%YVWC^B=^["Q=V@LJ;\J8/+.]DTS)1Z0 +MOZA`"-\.?^8&#?*_3H]L6(W")R<[:D +M0T>Y_R^'NB19X?ILO,`_EEI?/"[5Q30S>*EG\LLVZ>;LF0W&L$B-]N@--=1V +MSJ+$O3`""9]@1[RGB3)[L4,_/QNOJ0_:1N\NZ!93]'=PEL\+4@\!:',9I%=L +M('&7O2T$.S#$A]A-181D=W?^(QS(.:K=D/58!B1)-^PO,TB"4HB52Q@=Y.L[ +M9FBO-#L_JJQIW.AB2AE5%SBUGJI#Y)=F9L"0+?R[194#XM`3F2H5DU+[ERJI +MQ=/?+,X8K'":PB%'FRTV8[N-S,T,.TV@A_>J-F43J7"`C`$-+-_P,O;"ZV+K +MWF>0%%^C470U]MC4KZBN-0C(Y-WR`'^D@'`])1<#YON0TK6MQ+#3/S3+08&O +M!7&&++/2+Q"'LKD8Q(WY!RO:8M-_EE9(+8Y8NK59]@QOU[U)7AP^?H1X>,D% +M,DEZF3`M;8`S1-.V=CZ#MNUV+I[T\$)[_WDZV%<_L<-MF`Z2:C4YEM(I!08< +M9R']&F*<$[]?^Z-CY--]N%(DDLY>W]EN&=9Y["F`Z.[\&,I5I(W#:+/0.YPH +MV1=JL=IF@*C+!A#9$)PN0=#:HMZ':/290GSTQULD611 +MX,MLH8&)[LPYSQV#W+^Z=!]7Y=(YCL +M88N.KN@GA/Q&+EL@I/$;TT./Z/AM5"U(6M(4D:CKXWV[IQ([XDGC44&D? +MAAU+==*9A6?\;KC478&SL0\6R^NM*Q1"NKI7A6V]Z%T*FP2A=,!\&:EYT11D +M%",<_P0#'S.-TS_7L^X-M3!V18DI"GA]Z:6&`8KZ?2697P:%%G@I>/;1&S<%D;I88%.H&'AC,4?9A&%JT`ZFQVD).ED:\0_M%LW+7Q?%L$-!E!O1`<%<$ZM^(/MC-4/\' +M5MDUZCCDMTLS_&0*4F(4K8_#AW8#;%=I1$_)JC:]-Y?X<;@YZB,7TU4C(A'K +MT`;T+SJ8_I'@BHO[R/R3/@98M%Z'`C)M8,=@LY1NC.7T(H^S>V3KW.Q77:1L +M6L@C'NF3$9-@VV\GPG44GWQ`:A^FW;P8-_?SE>M3$`B/O\B6!S'[KO2=>Z?Z +M:ZO$Q1&RG;9TQ#LBR!O5_4H`(?S>5SIS69Q13M/VW'-;$5)<:Y`1=D`BY>>/ +M!Q-^BQ+SMK9V*JUHA-2.LH.*7OO&C/F7JUAIEDZAA[>ABO"3#>PB$D"79F2> +M9MTV12PK'2(VLA2,].82ENM470+$`(5:HF+BI`J$EV6YZ;=VXY,C4#8$MQG' +MQ]\635$\:U8-`B]328DGZ5R>\SY;82\\98V/@A +MDDXB9S?\1Z%'T>\UA;:E*_\I]$%Y=',"T[532ZGHF=[@WR/CVX* +M5D1L72$;[5EC2-2/QTR":U9%J%='@HCI/_=XV(GM[;VYPAT[9-KR#XC!W<72 +M3G*A=V0?J&[!^K!X,K6NE:G;,&HM=Z`Y_VF?(I7U@VQNBPPU"[4R`_XSO/^6$W0 +M0%WHLU8RAIWAV4O<#%V!HP&"=^K&,TW&6.Z,2(FF!D$R"P]_37(3DV%[ +MQDD/U%5K`^-=&KW*Q/=&4JQI1-++(AR< +M(%X4_OAA&VR#PNQ1"V3%RZ[,6@`Y_?73)(J@)IXH5LSEZC*@!K-F]_#5R#&8 +MV("^AE-&G*HT[+)Z@@?0[V$,]'S\BV_Y?YI'^5F<[YPZ/DKRU]NP90O$BH@ZD%U,6X^\)F"=XWKVY4) +MEJILL25\>("'/#W3>"]@M5A^_QI-.6JY>ZCS&Q0&&3A#!Z3F->>E#[AEG:,G;G'5K6$B(G4S8(RO+,8= +M\_Z'.*TM&-P[7XB=)>=_1?-1=R%K71K:MW]WGP2<1 +MM5U`O6;;">>&8WC8:-$5+X!8HZ"+MT[Q])2MT?W/GKYI.H_H[&PXGT(7F[?0 +M_?J[A?SMOM5`[NWO'=;[#+';U` +M3/)I@5HN_]/7CQJ"!Q&,KK,^(I +M]T5PEL^!HE-@%E"AW<8%IO\,Z0!&Q;-T!^%CT#`3F#B%;90O9T*O^$?-GX3_ +M\MB2T1X9%PW`B"*C=N93&,QWZW*>;'O&>6K@OD?52?]T08@$LF)7.NP$J!9S +M%^,]\$=%G7>J&I%Y!W%/,L6/PA(0.B947R$0WK$.U-?,K$Z#4T?[6B9^ +M?OH?[6-;/`>BP@"V(B0VN/DRK(-LDN9`YX;YQ5]@F`RS9[[`]2NBF8&Z+?_9 +M5(DKK2)U6#'9ZVW9MY%YT?&T2"^NZR_D?=_7OMGVC#DV))M +M82I`B1[(A5&^#DDZLH@H=8M +M&,JME($;8J*7S)O>ZHFV*=&54GQ\U9<0HHPRZF,J*G+^0+/]S=_B'\Y[->2> +MGO@60M]&J`Q0LNQ5FR,?#C'H1@;6)TJ1M3T[8",1D_;NAJDZ%SP1MY9\.A^@ +M2T)2WBWM.[/)F$KKWMR8#NKSQ8$,6P%S3A,/-5[NXQ;`_&+^J',2U*WBZABA +M.F3^I_-?SDP$0%-Q"#'<234=IHCF2L$K@N[RVI93>?IO2SIFJ"+B"%II!#FH +M/P\>\ES<+!F]]^&F/YCA];I0OM204S;'^0 +MTH:5L\`4Z!6;@@C+DHJ2Q!,^DG]7:KM!_R]!,7S(ZGSC)%^^`/(^0)ZO,&VL +M64'IDD,C4PLQLZMKM(/F/?A(4_3)"^*P2;2[Q-:2UY-57!#.U'QM*&Q*UZ[& +M*U0_:EY5A:[KFN!ELA@$%"("!ZGU*&[G+4D%ZYXKLN@Z1[Q)%L\`!4SIA-*(YNI<4.27P5!2G/>WY6^+2> +M5T5^3(M4$8IS#-"4"4C(W;MHC2U\[T):NB*C-V;'D8D45NKY<\EF+H=M4W^B +M3H(^4X(E%IZUK=79)U<-3'],N!]+$QS=;`CF0G0O"=<("W^ABEYT@SGP.W>& +MJ+[A9GZ*B7+HPEW6NZ7+PQ\A>LW>.H.=W3H.69'W'83:EXT^ON^;V-OGV\O- +M?>(C.K`>N\TY&3SRAHU._MK28ED::1#%!@U?\;E_#@3MC-Z-\G'9(W4]4?IO +M(;S7[BQVA_?QYNFB#DB89QP8]H-$[MA?[EVF`UV)#R.39$OMO@QB:_/C?F=/ +MKB.K1[W^G%,LJI@%$=?*F%7@ +M(=4UURY/Q(5C&7>+@75GBV?LXA#K`=[*9@PE?KMA-!Z[>*!TDG[$LI3T#0NO +MKS-N7I3*;F+L1F%>EV!J3&SR(VP#4LURR0X4BR)$GHAD'VAT82=`O2F)+^T] +MFWBRO@CQ-GCB]!*Y2T7#4I\>6\TKRO5663N:^=DPLCJ0P$-P)??R<_%=9L:" +M*Q:]VTY;GV52)35F5_@:85EK*^=Z=^#DR=DALZ86Q"IB8C+`FMK_!#O>]X%2 +M&=FB`%T10Z^)NUR2Z2!SRL16N$_$%3M!N-; +M]\8)H30MIM8>'BN*8VW`SW(/=+=H3R-!*=GV6UJYGD/)"J41.CI*'2TKK0XU +M$GB^>ZT8BBI=_J]::K/$=LC.:C7XJ@74+QEK7X1`/1]5OKOBC$Y3.Z"2//KR +MXL_(<7DS0R/J36@SCZAMLO/"H"=ZN^`E'8ZO#M;(1J97$`4^C0;Z+WM_'2IY +MUH'(N#*2DP_#RP +M$QY$KB;84?*_.'O?]`;L&JRND_+0KXJZMEV>@(^9W.K"*PA +MD:ABFR0'>L2UI:5>9HT$1#,R#XR;JG+US& +MO2$7])%!E$>"JR>66:_*TUF-(;=RRU5`N7JVWOMW1<5+\2K;8H3L]9]?&=F+*[^I#Q;[3.G^MTR*`&"7WMGJW2^_;%* +M5*S^H%.>$Z:EAV4=Y^^W>$C*5M>C'Y0!Z/'<LH +M0L)IQJMQS0.$IS8Y$QZ\(O_P#X$LCGDYF,54B_9H+@QKU^8+F`&DRD9ZG:#+ +MT=W&P'D=%K.&GGTRT:Y-5;):O9NEKMNM0TEER].*9!180/9;$P\1,C(4*63@6Z:5*HQ0);Z.0`!Z(3*5;)M4`U)/%!OO]<+>9QH>1,+O0``J:XWQQP#("M3#K3R%9Z:/;C/%''F.L1:I#Z[JAFU\& +M.V5"4MC1(5,EI[**^]&]74*91HBY%^YL:C[)\ND(#,*`Z.MO9H\I\CPMN,!: +MV>^SL%1_IRYWMD+`YB)2C:CT;D%7KZ>B);"[.H>VQ(,=\)R+4,<,B-_D/MO' +M/]_7L0TBCSB)%R<[,LAV7)[M4C4?1R5M/4^)V\3+R@D:*SU2[*0B?O4?CU_K +MECQ_X6`S+VOURRVN_4LDH(`484R:L0($C6`/[&\Q]TAYS_6/U\A$C^[V;=-R +M$(A7,=QG$X/G?DT>K2P\J891>>H9L,>Y`08/OX"WWLVRHIK6O.ZB[QUG-AN) +MAQ#G%/:Y#5-SRP<1/*07V+C8XY_\_Y":T,([S]'I'R2=V8]YNPP(#DN4X2`L +MPWB=_V%Y-=Y3.\O?^U,8M_YA],+O03]QB5,U;:4TKS4YA0(%9RJ8&7_^@$C` +M_=$,$-#L2.)H[*J)1JT%#TKCV>7&\8Z6Z0\>Y]#'&9C/+(0%SPL]?TSJ+G.) +MX45C:TZL9+OP/L:'HB7?G"8Z]4)\&4:X,6[BE+?O8Z&$2N*0AQ:S$4L.]$K3 +M%D(%'LY>"BBHIL`J(1EA5RZ>?ZB=9GW.JAX^7PEGJ-]8I$LIV2GSUFA;I.2F +M6'/2W6TC.LG'W!9^]=#9*J8M.M+>97//Z)'H=0]:A?'L?T[M:>.B?E>7W!&9 +M&T*DBG+AAP_ZNK"GE*E,2J<]+>\(HQVT6+H[Q*:N+H>ISLS0&OL`7(^W9H>R +M02G6(\MRA6GL^C_O.ME^\;K=_\#_9=J-4[.[)B@T/_S3C>ZS(NR.UL4EAL\- +M(F%D(Y2-"V\;`HV^8M*;(].I-17@[Y=$YV1S(V5SBZW="/HB=G]7-?.>H6A6 +M##G8-%R*O!;@\=;KI;D:J(B83%$W6K89I$HU"H;76E'JM,*KO^%?.K +M4@4?_*X;;+86O9UXS_^RN1%]J$:S'N`4P`\'4MGS4^:IM&Z9@QNC57.(PB#N +M36-?W[`0#I)J0_K$F\0M$:U(A<:[?"9'Q5U%(LYL)#Q-'^^9,MPF7-$V`WP% +M^!&H/<5O<)$)(>_4ZQ99V-MHE0. +MQL:NF:+?A`"I$&8^YII[YF$XM>Z!]%R101M?-V5J^$712H/)B&;?@;&R*=@I +M_()'FF7D27YKNSE"_^Z/WC(/,+N_Z_3=2M)_+&ON7=EAG+\;BBOVEUJL.9/9 +M!G!,4P*O\8@>&G?CY_;O#&U/30UQ:H/7(EFT:^-'?E0@N]>:,L/!I8Q20,)8?7MOR0YGEL`NQ&RR7$5.6[\`YR0^RT'8%2_#P!VKJ+G%M9GA=\Z-?CM>,>88U*$5;<(P#;PZZ?D& +MED%[&';F09YE:+CV^3?[K^;(6&@98+?3M.X2FZMBGZ_\,+PEJ_H/,E63X-?U +M3C[&]_K%-;FB,N4%+($\E@6<$(=0L41NU6N*H<"17FWG`_7IY6>$,=L"^A`F +M\;!YW^&0!]>G0":"&45$PYJ!VQU[@D2/!A1B#F*6$0;GC1X/]S"&(ZEQ6U-2 +MYN5=%$\#.FHD.X**.(8W=;G\3GY$F/WL=2T'P.E>AS?&'QW.)`QV@P4 +MOL[O#T/6^_B3R\'%UTK1"^*R%5"2Y`6I2*SAW'#2?#WG?8?I4C*D&_2.*ZL: +M/%\8-+=,9Q`26,:S4JZ0H-ONGQS[CSKY6&2%UE+^HDJ\4%B*A_>6&T:T#!J? +MMBO3)ZU3GI85:X?/*U`=3E%/BQ.V#IJ(O#U:"X&FXDIJ4)^P1K\:%-"=?5UP +MK-@^\`0GF;?%J`LQ]>$>EE:A-!T<*MSORIM[OM:BJF*&M.2>KXE]84V'*!"Y +MK2<>P#-7+Y$-Z>F/``CVVEF+<5+Z[U#C:2+VO%Y8CK3W>AK%7+D'&XYBBC)[ +M0&>QZJ:$\POJE*H=`"29RED%=`K'G99WSN7#YTI%/(SP:_B3''5%0*(Y8V:> +MX^<'QO1IF/5>Q131)%`60GSZY%>N_'6_9_>*R%_1R44>35J3"$/W4`R0N;"" +M,HU,//<`DG\O=R1G-9&@MT`-,CL!Y@]X[J"&%5/G#3)T%OE75(*::QH:\ +M0_\&(Z0K8K7"Y%+X6BPGAG(^1E!@C]]D>6+N>:[E3>000J_OO#E$$5P=_,$S&^J\C9M%8UKZ%(:S^BKC"WS\ +M8NO<5#IKO*]]EQWVM^LR1>#8WC,5W#\L!(T65^[B&[&\\*Q"C!K*'"B@\]#. +M&J!W\OG7_E[VC#U>O'&%%1!1A]=V'0H`U^$C/!@+!(%+IK%\*XJ6.\XH',_] +M57MAQV9B*(1#&![9C$AK&EF)P+EZ=BLLO)?ZVP<,7A0W(+<\\UQ,3I&)[TO) +M/Q4#+8\HP3K,:YW3BQRN3&DO%'WL2O'QF<:6V`5=\<\=YN>!==-VX_@?\)_" +M*P]?-7%#N]1WB%1.U/?_^[]\^,72F]6H??P<71R!.(>V7"A8PRXY6#JBE+43 +M)75&6DP%,$.=A6LN5)#B3DA!'Q.(5\W!05^QF?#+FJQ_AKB/L"&::FPV[0JM +MN@SE@L?YQ']9G=8>\8MA'`8:*W86$HM.E&<0D'$CS;^97];S76JT)Q66_[VN +MRSO]/%+SM6\5?(#DO!W^FX78H-5E`]V@R7R_ +MW,`A7ID'[^%SX(RO>$5`_]YHZ:!(08BL30&.G%G=G(G8H4K4;[*3_6W5R$#1 +M!/G\P[RXHP>0M+=XORT">]NHC9:E*M#5:^MF\QH'=0`;W<"$(+$IZK4;,`HA +M45DQWC*P15;!!>R>8;RWPIDV__4'_#3[+4L$I#HP6#VK7WS;[CBV(('92)K& +M9II'Y.D-[)F:0$"8>A84ZLG&`Y(,U1YG9?9ECU?282#C7F'+E=_FVU/GC1G@ +M]^!A;V)+9MP,/J/.>/]_7V,[-GS6HB=S-?M8@QCIA("#R7Y&B"SZ4S=!$)F, +MFWA<=?`W?Z:RHV&K)';("0![W,F5"$RNON%3-"9K9S.3D6I.>2H77 +M6NWN/P7JTJ`-8P)Y4*JP@7C)['E+AB[!EIP3N6E?1.82:NWZ_+PI8=(=@.@] +MH2+]$&`0+=[F%2^#2+R)$2>1860T4TP2:_(V79V6 +MUK?98):\V]K`Q]N!S+:!9?0F$M%*6/'24LHMD\&,P^:F`N.;?(N5<]'KFIG^ +M0MHG\;RX:#M*&;W2-V6GH0?%KC-RWS@1[S5%8#J8U6!`X5!/A5%FN!SUZ"6< +MZC(X>SCB2*-CX/<4ARC39*+%TN1@_A`4M4$66WIT2BP]]'A=&3(AX6\V2WN, +M\&^LY@RJ>]8/"2_(81R@D(!][HO0^4=)5[K^\J0Q\%??LNE1B@P-:%H31=0> +MKD&L&UNZZ@W:07)@)B(L'`SLL:SU'$V?1G.=NIO.\!\;AVJ[%2T`Y\/);&",Q`(.F4G8E'XYXUMH#[F& +M6*A>@*01("ZC,F&HC]TJY^YS=:H8L +ME&L/OSL[9IM'I\^FO\=-G3G^N*901[.EW_T;V7G)Q+U<@Z&-FLY$ +MT&K;`A/2=_Z66,.4K$!A*^:*Z&SKQA^@FX3,=PQ]GKZ/$=Z5-<0TW8T-N@$; +MN"[N9-GU7$`Y*R!SF38OULLJIB9W.*ZDR>BEL,I"Q1L14.*-PAQ,VH;>@Z)0 +MS>\XJF(WL=1:>?>#R-XQ67@.A)+)$A<%?$L?O_DMM[B,%X:$>F3_UR'-$P*G +M>-UHC8MYCWB;_/V(*07S8\E;,`6FN8$,5D[_D(^==`16+N4\2R'\5R0`M*S< +M2;E.CS-V]9O%M?7CWMM'?C@[F@)P=H +M'G>YB89;!&>+#HTZ]\#AYUTN\^&S#O:M7K@]JJXW=-#@\G9G47::2[BBVB"! +MO>7.->T&8'UGXND=31;,+QJ'6[HG=:*FJ8:=?IC +M\W8VB&9\3S1I.H6E4)81*^.8(3(*9,PV"??IXB1?C-0/%'&',,X`$SD(54ZU +M-,097G?.:=1OSO_$;]@8J%"0JB+,^L??GATK['Q+/W4"Z@!\VPSY#1C.*=[) +MGI-UE,[CMS7'_@,,X^1IR$4T6?'J8I=5P/VSV-;>L$-NHC7:"]]*A +M*'H4>4]`_E0>%!Q/W6!%@7C:8T2NA[+TE!FN+A,U&,'@7?!:\NXPS=M(?:]$ +M@,)8O=>_Y$XGB2*\!$*Q<=&QBZ#_\@XW\0)R>2W'[G+3'IP(X+""99)`>Y!# +M6G'@%^G8DQ5874EA*0.W79N92VE>L@(2X7MQ]E5>5J;NP[1?&J-PS@=IKT*) +MI4WZX,TG`$UKHE90=6A!-9;!^$,OS:-4HJ7OEK7OA#=/ZUJ5./.'0RJ!+BLXO0DWLD#'S_VLSTM?P+^'@WF/' +M?J,B^_*F!?$K*><2`;EM`^X\]"WRK[`;&0$<>.PL):H/KF^!;Y"%[]8)Z^XM +M;*QC^@%&(+[?D@&ZK.^.[)^Q?S#\]\YT9]4):N6H`UFQ;D.U!8SIB`87BX8: +M5XO-(2NCQL\7%E!9%*A^Z8*B1NQ@F_GO=#Z"_IU`'/?>=WD)H/ZH@[P`M:/9 +MR7CQK8/H!%UVR#$_C;J,&S7D8KJ2S8;\NMV3Y0-PZ89;3>.:H/F&/&@Q0_"X +M8_V*R<+#V))6$%!NTG8#[']=_HXF5A;]#ELU=!!9UBI0UH'!3J&2& +M?I;NJZ&`/>GZE,:"+?O\\CNQ96T&='`$]I:)2W&'7^^6,/B&$Y`G>MO>I-[\ +MNNPXEBPTKN/*7?K=A5+H&FW7?3^"!7:HHR3GX;0S5_4`YH.,DO"#5,&]2^!V +M$VP@7DGNR8WXO-155.9+H4,E"^\W3'``:1AJ?D+)JD7QWE+WY7N,+C&TK\M(^4[\]?+W)K'1>\)TNSW' +M63;1'`Y/)9VI^M$!-G^;,%FS))J`TE,T4,CA,S,P0H8UFI+:7N;Z)CH/?'/B +MX[%,XADT#:#I]0[B\],$2G!7A)&4=59P=1*ZZ +M([BVF.D4*ESV+O2.[%DZ.XL^UB!;QO]TBXPX+AJ@W4X3DTARF_MUWR^:8COH +M*3GRQ3GPAIZ:;NM!#BP0!V2#"7%`L^R$X\3"%+:7M1 +MDY_`ZM(RH6%>JB-7>RYJ1PT.,06D:UG5O;P/L.99J_<8JT8\J3LZSTIVLX$I +M]ZS%R`&N"CJH=3]CK]!Q45G-P:L#9/,X>BQL;R*<2&B^;BUG990Q`(ED.5?M +MV\8NWQCD;9?M'[?"-)9G*N]/D(5]39IZVC,JEQ>KR2!*:VLK_Q;M-9XEG8*] +M7V7D$PU4V8>AN^I79*&H%ENAQ)'LV).'('&--O6Y*B-68#961L\=TH=K'=\9 +M)_WFBY'-,PGG-^O/)>10E15,[@^XWPEV/8'T>D9O%GK:.C7H5"*3*ZW/Z5HN +M;,)N)VT=_UTPO1GU.CKR"=-)--L#+M.\F5IA9N2R:L;KZ^$8W1Y1*5Y5N6[PA>C36^TK-/D?V_#=H)I%O)\MK;G^"#3C599XAT-.?(\;:_ +MV^E7F:?+4K!7L1R>@\&JT]20Z(4O%.[03L+?`OM&6>E^C[^N]T;U`00#/8?^ +M-7M3DR^\`0SEV-K>Z$J&3ZC^7?,K@-3XX!@:2^@0T(B]YZJON;,TJR2>1Y"P +M4*'0JE'.P`X*.V&E'$I3!T>3UA(Z50P/0I]WH;!"D:F/]1;^Y!JSJ>TSKF#` +M*:S0/`,6CY\98FM/FT*@F/B]]-TZ'9$>7,,V5"UU&?)D,P<\M`8(Y?M-;A7; +M_)O?X.[[=^1>I<"0K-9/Z-<'<0,3EAP7?%)Z[H(PFNM`J5]:Y/.D!S$]#R-\ +M8+P]\7=X)S>P:[/5&%\U?5R'H_HKN1791'C+L3]!<23B`%^M8YH*#(MR5-,1ZP(1CCIU<6O]41!=#NK6TH?WFJ%+9$`2\J1 +MH><4B1)K2&6;#(["N5!K`?_93T6)OZ`(6\%@:M?=[:_[/'_E`D=/1QS+T\H? +M/YQT4P,[K$&I&9%I><#X,-HG +M+2;41/]/B!GJ?<']@4S@WR(&>HYIB^CNQGR(I;]3 +MIMKW#3;VO%_!5K-?=`9'@^9`JZ'#73SOE-#]B)#Y_3"(J$:&\R&KWVTC*S_= +M*KN#]H5BV*]`Z>N=2N98-(-+G'[E6\X@X2?VC22!'<$2N8"X\J+*/[3*?P.\^`(F7J*=!2:D#/,/_1\BB1H0[E)4 +M#^0?O("G7T8Z7?RH@`_PQ`^*?5!%4NV,QB;R14MDSWRD6B"Y:J +M@(/<$A8_B`]Z2UB")]H.C=.+/@8D*1TEVXO`43B?5R$X#RZ$Q=TP@S5"JV$G +M,Y,U!.,Y?PKFZ$2C.$YU<8VJ;'IO9-DUF'UI96.#:*/^.KF>%Q'97!=G`&TI +MQHE4T(3X'6/![,LOO2M'$;4\)^[M+_$UZV$*CK5^-A=-P/X+[A6;PWB&^H]> +M7:>2(V%:9?*#2DO=?J80%$#F=."D&YMZZY8!;GO,1(GS,(06VDL$Z@J7O=OG +M#N:Q5N4/`C9A+5PG9KQ']PS["&Y.-;PH/!,_H$&P@M9D")F(;:ZFA.O8A,1D,[&^??KEDD\I+680EVON&[3 +M9=-)3(S9M4),/AK<+!2H>#*;%1CS4.#'1#6&M6M&8-,[BUP6?+6U6QV;>Q-] +MG'Q20-@LX8]RI9'QA4TXIT#?9^%!\)/MVC\\!#X\N.N%7>5O]E;F'3YXT\ID +M_=@^@*1,H:E)=>,M[8UV=&J./L`@+7O3V;9_HUIFK@(/WWP+Y=*H53`CR3!% +M2E"=2!.2WM954@:9UI:+M->'9$T#67P"<)G&%:2;9#G\`>W1]VS`JJE>V:#N +M,!58!P.4IPL*D1*P$23<5HO.\V%NF(J3M`.(]'EV]J=]-P;="2;-JG7>?SYY +MP$@)FC`9(?\Q4`N8,1VV$$44P,)+WIMAHDW?$H+OU+KKOG;<9Q2]6G$%J2J,FQ +M#1EKR`P&B.,^;' +M-<-^S&,V_,:QO&9=%=7N\ND77FG6D>6?'D+`TR/-R +M.)-U77WNKJZ+&JN_P+E-UU[X*&N=IT[XGB`(&&R;%DW"+7'^F@*5&TC-C8G? +M(!;(?V^^X(CSR%:!6M(4UH!3;E\%.#T(G`=S:/G&&AT'>FPM4[@*$^2%Y"*; +M;4`_S-B8S384`JW@&*"0VC++LEMAC&9QF*"_BYNG&B-#T,#UJZ@&;LUG>NM_ +MSF'&I1*?8V:O,MX0V:A6EV<0-/KI.LO:^H4TKIT?86S>@8N<&>-";VFYL6ER +M#T1)(OV7N)A)*O`@F<&L.WC=95C".+.@52@89-O@)XU-ZLAC:1'`.)TT>X<6 +M^W;,R.C@?1;#?T@GV4T +MF@]%2GH%X0=8+_66U3].STY8K,$,^*=D+[^>46>H.-FAE6X^/=1W8&-1H>&! +M1!3O0H@9.%VPI`Y'0"#>P*+U(K]L\3;,:=T]D)N8,G'P`Z_<61]_NC;=CZ,4 +MK)`G*$46TOE>0N=&0:EP7RCQ267T"[F$72H\`N)^[8RF:($[++J&S[BVNDJ? +M#OZCB7@H[K+-.(2.0EP#\;D7!0']SG*(GD_#J$5XUUV(#,I$KF1RC^;.[4?, +M#Q2;391,.).HJ.7E^V"X,9WZ%*A;BG-/N=!(6G>-JO^O"'Z`1`2 +M(V.LZ(*0)6U&=-"3B-/P<5E'$`QIAZO*C(,H'O$:+M%4,`0E9,]A?/(6[$T/ +M);$&>D!%A7Q>"D&(TJ0B%]E:^1WEMW6\B3F#1[BL1^^72"3,(U0V*RZX@,-H +MWA%#H^L['O[($U/>;13O8(R^@"NRTYA-D][AYP)!3Y3)C;DO"Q^'IC!;^,:=G/Z'IS` +M"^/>5LNTVLH"C047:G\DU@9>=0M43KASE@OZHLYAZ>F@%AGD$+5.)K]AZ-%$PH[/:?:(F +MR`J>C'BT/H&=-_IQ)7YIA%K+P0)6Q$=>;^^9BV*XWT_G3A;[QS_QVD1,'/3M +M4SV3*!@%#*9%C55K]YX1W,8?FC)8S707^H!=P.(2E=([V#$I3T44'UXQV%4A +M6'J^,XO"^2-6&V8RV"Y5[F2_)FSU-VD=Q-%BE5=JU1(;KCQDMX+]P!1[(G$N`S4W6_9PF]M,W#/?EX[_X`/.WNOB#R$]YX(46$ +M*+\"EVELH1T+:SKJ-[6BD7;?W1$&*;!7X*W#UY#3ZO$CX>29'%=T7]0_8'"G +M8=DN^KMSB8)2^!QK<,)TM'U?Z63T`NJKWBFTE`+L8>0#,X&LH7%*9ZX7FPM] +MQ##OW,Z_@!59$/-OQ7L.+$;3'+]0AR&A]_EQ\<%1[?O%RP8B_14%JUO$!5?$ +M$H%:*N#L2F';;IQZIP(9Q&1E!>%,.PG6D>,$*3#?PN92+!6V.)%KH7A8<".7 +M$K)&.B#*V+^3V.3`UD&??[COBG,I,"_!HTECH&OR+Z=44X4/&&VO,U,CN'?] +M?*VF+3[8MU8$;D2.BS'OPL8(:W`AUR+>7@GRGP`Q2JXW&PG;V0LK`:X>"JGW +M>XO96\;J98T&NJ2_:1(D!SNJ)V\\;Y^:8J.LI:CNS4S/`4OQWOS1I=]B`#)-O`R@.[/!W_=%2[S#*Y4"3;[`E^+=3;",S>>T9[90-VO\@D8'2BEZ6_G%:5>'B*SY-QVF;J;9ST*8M82%P&:V-=\9" +M@IV@1GQJY9K>$G>470/*?.!.R^OVLZ(_L=X`JB507H)]\[O&+V5A)]#JARZ? +MBM9!43FF7V$%XWH0:+YO4T1SE_+!`GC>_\N))/@SXDZP("LL4U<0(&IH4&S, +M]3*E"6AM+DD0.3;F*(9]6,=S%FG59=S,RYR@=%-8S/D+C!ZRI`7;>BM^88^_ +MC73,.6Z7+]8=D(ZDS10]?1[`!,*?U8%MX&ZKR:;9,!P/>1@;U@'AW:IO/(R/ +M&=:(/6(L]4WW1CS9*&6:'O%)2__K#8M`FP(9_9KD,%`^AK'F0JEBY'U(#1.. +MO9K;6SS)'6ES`E92W_C:MU,J;0&]6LYT@!M%F(A.OS'`)D%?J**AN)/5#DD<*/C16/-G@4^6$F7R%83889MBB! +MT.GN3;77,05S>DH94:+(]M(O3J_5RK*#/T.#ZJ.)Z?QX8_[^8ZT*.UW@M4TO +M+Y`&G"[]9Y+&[+;I(LZGU_',[G\F6"TZU;.OD./GQK*S)^T6KIA6C.J_F<+2 +M1>.\6JE!/L!)(C]N`H84^M37F2N(.1@?<'@183?I):#ZX.9C'"H];C\$(5",1$09?_OB<]GE_/U?',)3VAKVF#P7)K39. +MZ::X^>LMQ!#1DJ`7M*`U<+#.0UO\-CMFEL,\]!>[(+"KQ\H-5`8J:=Q?_^;> +M&ZRGT<.5RD940"*-ZI`]U5;Z3%C)0Z[DA'FTM/G3KK.8RTH#1$01ED_%O)&$ +MS8TP7RH2F5;F2%:K$:FF?QH45@^[B-&2+T55)=0**NL):!`Z%FNQ*AX+AV=H +M^GTVZ7.@6J(!QD6'D]U!02#D]W[+U0OR5=%Y^(*-@*_IXQ"^2DHKUP."U$D)@<[*<6_DNK5CYP; +MBR_;YM$ZK_1FPQTHL\J%YD09O4+'ZV[-\]&$\7AV^A6V7"+ANJ/XMI_=VKL?TO&U[K)+2)WPC\; +MU@'Z6*%A(7!*+J:C&VRJ:-'"%5(-E1(95HGNU5,A@GNV':D^HKXU6ZU?+)!* +M4OU9X'<9$J6;J?4>?$WZ/B#3C>XKU"CW8VBK;#<9MGIF^5!\<#X^J%KO@*16 +MFTONT/7F(Q5R=!`H'E";E\B&8B4QT%U<2*S.KSW9JCWW:J9T31;_E6[ZS8)7 +M@P'AX,W(%:W7Z%*!=Y)&[,I^N`$C4`@J@KOIB +M1,O4B%J0D9HO.)2^M.@9\9TC[L\5(G%.3>69"`1([MV)VA']W--7^W;^I'L/ +M='H4)*W9)9W>Z-%E+0>()/)4-C`2,CQ3(]5/X3+L)8]]0UK!><..VT3"S7+( +MY,"CQ/NT"./A2CWQ@CHX+L,#0/?/)?'P3;\@`?LWO@+,R+>@'-06W(VN4:[& +M9P,>QR-LI5E/VK]M0?$./P!(#.+-4\KEQ?! +MN(LL^\Z!^\1_C'A`/6:9JXIR17_J8Q;T>8W_`A''PB>FC>F5%BZ/I&))41GP +M0DG0K[A$9I<;*867*"MY6I==TH?$FC=^X!N9Q(9]A/,]W.S>L3%DEO2YRZ%@ +M7DNXP@1`(1O\R#&@E$L_VIZ`I=!`)%Q!KSGO?UN\-YN8/@@%3V^QG159,F9' +M54:@05CI.$>L5./"_L>?(<:NPX0CCJ,HR1H51,*ZI2W6\"+>VE^I!5PC:A,! +M](]*?MF?9)>,H;^/3*B.@7;]Q\4ZQ3S=I6UD?:TE*&9L'I) +M84KU*0L=ST/D2]A.)Q`<]R^N5.JFZQNLAO`:@IGC?''MWDS\A\)U)FDK;1[, +ME0]JVL1F.0\@T?:!YL&CMA9'I?;T5+NZA^/!KN*.\7 +MGFP')=E9WC)# +M<,*C%_N'Z=L]H72VJ/Q%&=`&8//7CB%`I=/[W= +MLU"'S@>KP^6$.'H1T09)4#PQ=9>XSZWV@E'IEF?Q4+B%U[UYG*A_7[-B7#_# +MY%?EH!!#3+`!0?SP\95004=6K?T>*S8N!97Q&U&N$.\O[6_*M4=UQE-=^U7$@::+UQ/KA/ZISID&,:[%W4ZE).>L7AS4P((R<,L +MK:\&C1QE+XX[)BW&@E>T;'2<;*K06#XM$M7S/72Y:RXJ4!][FVY,<8YW3W&- +MR"IO)/@+%0`;?M8-S#>$7_%(%/P'=T3^L:5V$;3O&YA`UG715VK;@VK5G^'' +M>>?@-^(J9F#F>)VQF%0+9!#R7T.#2G=0_JK`2WY]2O[?7+$DA1J<.BRF"D%M +MDX/!%(/D`I>TR5U^$PN<=0,H.?&\I(%N%W^_[;#$ZN+.P3/9[[`G<%8.$1$J +M%Q@EW7TC%5?5!=CDA8N/#)B=,SEO)YQ4`?W`^5@!\-#<&3!.\14`-MBU)O;" +M`T5K!)9R%7V52(!#WD+=G@ZQ7'>>:)!!S>3][*$_/056BAFSBR*/$V=?$'+? +M<#02;N\J)<*IXR9V4=HBZX/;+#+*Z%K]W^L:GLT.CE@0:D%S_O5MOB +MX*03\@38SK!.9,+A`ZP"(@+C +MFTP?$V[3\QOH0-@K=<^K0']"B_\BRD.=:[`8FDX3:!RZ%Y!&Z@(T&W\*>(;B +MEC3M8B=5H,1UX,D(Q?F1Z"B0^N=(^NR-.5F"?JCMCB)$$+9?1_F"2LNB$AA$ +MY[3.=*?K.LP4]JJT+LP\TT3B)K=49@=Z(?*WS/,7^Y@+#:38@$6#1MH%<6H0 +MXG3X=3[*/=AP),18(4'*T +M6G(X&6H`4MV=C9_(*S\,^8:?@)&8:ZBP37BQIX_+F19VTO?#RP#L:9!A()ZM +MXN$IUPPC+O_BW;K=IU(\.89B"KA/B>BGTG@Q<7,D>[W.N0^^/'BE+E^U6V1Q +MU"/QV]B%S9B1]DGEN_AM)TL[PHJ!L2(D34LKO/QH*H3P%C2F7 +M9-T#S5QM3L"J_SP`@E-/W+3"J!WN8YNO@;(_8VM0&!5,7PGSWWVX8N9VL48 +MUB"XY4<&LJX3\U-:RGS&6#J;Z/=)15%6HTS;8Q8#K6LLMUC#8ZAO`[R0%I(H +MXL?,/_4AB^S!EH1RR9.FZ#HR855W;UI#"9]TF&MR+[$K5:`G\Q%9S>=+][5RMCO0,'M)Z4VSTRA-.']J6;M.JAO&U'$2"\]'-:$#%$6KQ>^3,:KXPJC%B;:7?/9-^@.<^(W9 +M>X7A;@78^0201JOFTQW!'F-"D^]I)'IO2,*.!5[Y1"K@P.?BI"4-.JXNG3!\ +MP15SCAC80M[J(^%(?*HNM"N\$.[=USL_$'$>VS1TWT0VR<N+*2-8Z)@&`D=?N,CL*FQ>70[JE2;P)0#:`^HZ\^E/KX6^91<(1`6\1 +M-2B#=OUI,$9'CBI3]KII,;Q2?SD_',2M2X],6#YHW`J9S(2%GX6JT6Z'.0Z7 +M55N^(`^=LWR,&^IFAN<+08B0=52O +M^>F5<2AGVH2VZPNZ,!:KF%_`EB)JHAP%O+?TGWSIP\?>=U-L3A)%>(=T5V,% +M0B?.*T"K^+24B*ZQABHWDHS:F"8)."7I:STYP;(:68 +M&63D[6("*_1L--EQ7:9_?9!9`QBS2'B&YX@FO<$1\DIE.WY[L>S,8WSR&<0\ +M2PRY)J`&)Y5V:VTC%AXOE&>)\]94EM1SP#2_9Y)G?Y8A5N,DN.U^0BV<,:HCABV-N=!+(!8"U/+3Q +MW",3HJB/6,7]ATK"I:^D;M;7W_^LHG:C%J=C93Y4)1JMMWXO#0T`.YW,!0'] +M'CZ6BO*Y3@B@#`4E9NDB'"']JDR;%#,447Q\$S$H/8UB@=5\N]@62N/`(=M6*B +M4Y3K^P>D+JTO8-=(G:A!\Q>'P^!N%:F5ART1KWJ83A/)?1?TUXU)+.I?&C(5 +MR1>0,[.#9&$%[4#X66)`T(7HK&G7!A88JK:O[?4X$*L(7)%A_C%SVG-&U&98 +M+;-`O^^K[6%6]MIRHN8T1QO+0"L&^NE8J_R[55[S5J!D'-VT@",IW6.RE +M[^0&[)J,WRHP0?2X,!DDT>EH_!^FX"V^IEF)EBMSHK"C.%\A/P?4`^%IVAT2 +MVV*J8#K9-MY$P[6-2XU7F#4MQ!6@2+7X\K_3"\\0 +M>K)'_..E8,%.N)5)2,O4!FIQJ*KD__IH/12.!BZ@ZBDE4*'4>(0M"S +M4+VX)7UK]V!7T8:_$M"Z48>;TGAKP"2F$F-MGRL3YO->K^\5UF9_I3] +M#?QE[*2H_E"$%JV:!V6,[<:JU?KERN/%&W*->0R>F;<:S0_4LA6+()MBY;<' +M8P^FFRJD)=:ZC=Z[&:QL(N5[-:0C/S'&Z]4FUJO^`-<0(#ZL +M=1;^)@!:]LDMOBVWHUKWN?0]X#M,T`;((`,.G/Q)J&<5\%MM>'M((Q0[6?M"TS6>"1>7QXMFF!6[F4Y? +M[<%B_0?W,"F9G\@DMRL%?>L\3&_FO]]F$1XZ7+=>,TO3RB69P^I9I^HP%9W_ +M2"*@_<>)XT[$F3;VF%''\CJ?4=9$6[(A>[Q^C[[@X[3,3.%96,D;L9G))-O_.I/<%0?P@<6K8N1JD?4QF9RL@ZB^QB\Z/V<*94'F219.,@.5V>S +M=?*DH&C<]J4OY/XX$ZUR:"#8*0SNNCOL:J`#XM@EG:*(?_[MW +MN*2HE]\^\)PWXRF']CBXHI\5J"V$JAD2(P!?:4:59HG1'`4*$[U.Q'"-TP@6 +MS^3]\;SS+S\57V4Q[G=%00:\^TCGVZFJ`@?'[O*Y[AFU_N[&,H(83WDM(\09]"+1'0%J:\!7Z;PUPF; +MQU^5P23U38EYWV$]$PF8/O_R2*P'(Y,R\&+.!V%CK*E,^W[JF17D5;%8*)0: +MP>F,`J_,A]=`6=S/(&IQASZ4#X\5+%Y>A^U27!Z%%*V;DF5TF6K'2!PL58PL=+?+;Q)N^PZ`\7:M5 +MZ8HX&Y40!YR-I0MOFF&F5XV-KHX2.H8V$N!O#-H%TUTB>$G]5F*FI=ZCR"6S +MGF='*V>G=2PHDR82.K$VF#1%<][^M@TK6P`/Y^)%SGLY<9I_$VQ7B-&XNV\F>7)Q2(NVNITK*,."Q;YIR>Y=!\]!K +MGG^0<)>IK%3X@;$03$+T:CX"+QF5(S7P +MG:`W!OO`B-+=PMGMIU:&+W-&06-HSI(OA\3:!*,?RVCP;4&MJG(02*SY9%(= +MB\O0E-SF?@ZCS-\(T[3G(<6%*%[D2EMBE)R3!*6KAND8MN>:JQ"%HCBML`]Z +MZ/KDC[P"`"BBG9!WPRKW?#Z3Y,_G11DM=(Y`C`C-&PH4N]FJ#(`6+0EEY/0I +M`N_#>3RZ?ULF)S#I6A81-8F]4NP+ZS=I$RTW"W[4&K:Q +MSB-1Z:2OUB`\URL!-)XB@@PJ!B8YC6710J[F89*TM>'O[(MGGH?NZA`EGQP= +M;3]R7\#-F`#BM`HB9$N>@0?G,'P/DTL2<7@FXK>FT9V2&JMC^PU4 +M1ETD;5TC-28OP$6F00%3'`XBBO$B31$`(&P!2Q)/ZV!?:.[)C#1D(FALW,&8 +MQ"+T=PD'7^3<%!C?A9R"C1'P`IQ+BE02@T)V^^P9@V002J.`;I>!MF^8#2@R +M30W'*AJ!L2! +MPRS/0U*HC9.Q(V'147:P$)DDW'22,PDY308BKL=U8&@/MNQ^\B+?4.>$L.11 +MW3T3.KLJ/6X7>[^`MF*!FN7,M-AP+[RP<(&>U&+@ND@0$/!CWB501OYF9*D. +M$*\PP`LRWIL@CO'R]!/K.HH,')*6;B?0\U3\*8_E(1JR,1-+'4G<>.=N>FM5 +M]9B8S_0$4DA4$C_MB00JD;2XX3A%#7%M?DP\HL@^MYXRH$4;<;BJR^(V;.M!-;$Y0J`QP`"<2Z3#' +MZ>G(H7$M^-?.+INL$3:'ZON$$B!)-%)L]4)EAPH3)>1]8,?YH![8_,/3ECVG +M61$][ONNZI7\G@57DZ2^N/2+&5)Y#"*M^PMGP"M[WC2K6P`&5,O(Y$VY$FN_ +M3DK1D?T;=*"<#@V_^%,V$!O?Q`T-54]-SPCJ(`=#;;QY.D3Z&],P(L_?^GG. +M2^QZBCW63A!2^).>L['[M=H_/G[ILOIQ%O-8ZO/'R;P\6!?/R\T +M95@$5Q8H`D5]F.[K64A+&UZ7WVJ^P$)OJD/'&W^&!"/6,!+$(2W7CZU-%IDG +M[%U^)..)6MT=E)]YP%7+?E1/9I,1I-GW4CJXX>8X0V8[P?S_+YF]*X\`MN]N +M4P.L)(V"RP$&DV1VS0K(?/-(N6Z*X!TN6"QO&1IX8`(:^C[ +M)$GKH9'-:]"$SHRKP0/+N8O%'Q#@46HQ/"Q0;DG@MA+[(.!*`\#D%2XG?S7G +ML4+^)F:)XY@,F'@3%FOUZ0@TYMT8]3U3<*BC7,H^CE$#VP*^_AX^$&:L+K:2 +M'.]-UZG5]9Z?"6X^I0=.M%7R$8&N$O0UB1MQ'\&&;J4U')JO:5(1KS#[_X1C +M*2AAI"$//7J2\7Q;7+GT8"038?^WR`6]B(%VA]-3@?H-+_O/B)P"@"X>/E#; +M3L%TBHV9AF:R\.EII24BRI<_(S>U5$DYHY&@#TBU[6R@;&P(F%<+X/'_[:3E +M.G?15:VQ5X!#%`K;Z7Y$4\V+-,S>*CV2[W`_>>\R" +M^@E00`@D,'BY$1I_O-@5E`@QCW;X%);NR7<[.R6*(!9%FS^Z&PI8"J5RQ'B6 +M^O+UB9]9LQCP1CF3LG)VMF=FQ,3%;&'U'VH^<40$,2W_"S*>F?CYD3__\0YE +MY(67`0@INZ@=RFE>?]M?D'41I\0,J9J9Q5"]^@2V^7\U?:2-VKN\4[ES\S6P +M4#Z68(N\+B?AZL4'8L-3]>MP!(Z%\4?&I+N9G,84B^R!>P\-]+5$">'#.FMT +M*'#F%6[^HR$E4]('=>AQ52P#QQI0/U@'H8U1C"1*`ANV8]Q!N*-#8G-P9J0. +MJ/\H2Z]TOP"6+3D8O%IF%Y6I:G,\%Y-R,HU!9XB5-03:PG8?)#$)7`5M>>@9 +M+NDXU4`Q@]0V//28)UWJI2EC+KW']2G9+:)>'2=FA31>-;6"/B@2>LP8"R]9 +M]0E3%$VRZI!YW0`DL#DQXY,77J^T[Q2&10L:ZUVAQ$AG*YDJYU-.YKJ4',OU +M30&#_T:3\^G&K/_A_&VY,DOQP>&]4AT#&I!Q2+1I-$Z3$SA?N/M.16PS/CWK +MI(%GI,`/-[!D$U3B'$U,!;<8..S,,*T/U$XI^&`W/L)QRI-6+_E4GYFQC5I6 +M21'#?WN^0"=Q`(,I2GW^SJ-"=+(`/:4O9 +M5"(Q(`>M,`.;OOWZE0962KFTS,;YTM7.EZXJ5R)?0T%\A!FS5E)!-&`;$=Z& +M)0>'2T"*@XV31:A8[6&T$?JM&0^Q86&*\LN5Z32:7LB +MD<9@@%[&_)UK0Z&27AA9XC;Y6%,?]XH'9$T//\EM&JDPF--KU%OU:1_!3.*Y +M6FK+QWGHO>H'OT9-3GS4Y6D4(@HSQ=;GIJCOR(+S?-.[M0V[2!T85,^4M8-8 +MSO8:2;T;(FK600M$!\I"X>1>SPRJ+7,G0BN235)?3[P0S&N/R+&+]+,?#>AF +M'IM,C6>=8K'E*OW(TAUQ4X+38O94W\YH?JRQPM$)M2`*R4^#CX)S;430W'-Y +M3@X_ZQJD*0ZUS2^#*S?4!T&(DTW2TRQ4NDE#-K\TG;,8.+^K__1(S/V5`141 +M#':/E&?\.&OR3L`Y#-,LXPZ0%,D*G%&X23,=Q$W2$J#=H$=YF)*I?S=$67;_ +M_](,C$'_O:6IR"T'%Y.+2EK18]X?Q(I? +M127,,L4W+:LY3\AF=$%?MLKQ.:5!8AXE<4)TY!%HH[Y\O\=7F833+$V4Q64G +M+3-/O=]<:IN-Q^&I@M4(M]8L1\55$%@&J+K?4Z4O%I35R\T_MQ6K7S[G]/]!QG87KBHR6"U-&NBQ58C1I]6Z>_!*S/KD +M-J[:T2<:_9GG&A)N>>O&##,FJS`]$-@IS8/3;L:F+D>MNCM28AK.DYH^SY%E +M!R:9P))/Q``WAR=EA51AZ?C++P1`;`.P')L6`6]^ZDDC'^24W6J)O\S\+#=[/&T?81)X%C9=O&@,C_F;;B&\.<J#J_-/;MN/E-8E228\^S_?@F$.[`,`SL$_QF-L"H7=[!+$Q]"*%&9% +M\W]W4.[%H*&43+3]EP/G>I#X?7,S''FQ4R%W$;0GE^K&("VV\7 +M&%?9&C(%$XX]"="M^KPO$N%TFLTII@5^00P(25D%0VU +MA_+Q]$V\2W//3^*JAYDF4L>!L_ +MH?MY^-V]?X=KJ:>S.3M/*DT?T#[6C,`)+JPJ&.*QM8R5XBLB*%NA&Q:,6O`TGJEC`"Y24% +MU!1?YW%(IBA54R)XSM^%Z,R/]-Y558N7&X(P(WH='YZE-VK,JVE7?*G5UK:% +MGE$\"H(W3J+I=O$=Z],%$T+<"LL;U69(5M1;M)TB1,E&&\%7J)#TXY[9=Y.8 +M25I\J[X;0I6;B"DBX!UAMIQ.ZY#9RAQN]BB'"IPZ+Y)R\$,*7M0KW(=:Q:Y9 +M@8C19L39["@MHN#^8WAT2$>&JA6JA)J2VLINNH0$$C(OOJ@?$O0^M/$Q7_\" +M!OJP`9;S9?/VX.$X+TEW>[NJR?N9(`?*BI*FU-4_-^NW61LCE<4M"T*/+1`S +M.02/Q;7CI+7/[F1U7Y?!&4'M)&-SD](>G%^T`>!(Z+0JI4%N:^8(R,$NR9,N +MEBR*O-FQH2`4OHWR=P&X37ZT\J8OPD';LW,B?-,W';@+EX'-9XVXD]S-ZXJ, +MNYQ`HA9NBZ$$?91R#+&XD^?A.F&75"BU9W8%[>HIK.#<&JR] +M$#_R:W\U?\T5,FCFHM>RSL$*@2%-K_"0G1BA,PC/.E@%TQBRBF.JP';2#ZC*P'\(72_FLOE\L2OKX<7T@/SP^(U]&:'UP%7@DGOUW +MP*YY=*)O283\JQP@_5T8``,D?NYT7-K\R2"//[K1KRTIVEV@DXSH"&@$7/#[ +M[OBZ>;HOW$4YOU10SW7"047;O8C3%SJ!MON38GC8=A?QDS;5\!`NO"6'=L*\ +M554[6MZ7)W$1*G:KGD4;R4P'15WWCK\=DR)N;J&TBU.:YJE(`A=_GUHO=>4, +M0XPPOZ&3[!M1T&?C`$#1C&;3V/]AWEY+`1%YXL7=L'7!,2%8B_&8*@I*5CS/[A27'.2T[N&Y7LLQ4&9"J1Q0RF]?!TU,=SA#K75*8S*:04.@3T1APV6I +M61R8`!S'50C5M?^T=#T=*&)ON&CJ"'^<&W$`59M`LCY4^E05QHI])S;NWL0# +MZ+%ICX#FEB8F/Y!$2OCQ3OQ=II74!5AJR]F61G*=]O9\3!?B\"2JU[E:_9IQ +MKC&"9>;_`G'CAA(_,=?Z7;%)']]MG.N3%UN[\3*7*"$MGD&68RVXMD^FV_G, +MN/ZKF^!<);M[)#;'\`O:[R$\D5%O-30PJB)O`QMINYKU&Z\ +MTZI&!4W(3`XKJP/S=3'HXD9CL/6@!(SR,MCO:']O=A@90RX)75GA5,J:34Y= +M,XF4*F1P-?2_1B,4._D5B/:)P6\12NX+*_C$>>MV09`\BPF0ZEF/@B&:E-4W0\4[:`"/XP,NE=7O*95R.5ULP,:J[SY.&S2W8YFGQLYM7=;/NC]C"A`R[85=:%*!WL28"]U&4J%;,9HF1?.RMC'R!> +MAY9Y>%95CEJVN93J:_YQ1UO>+8?+*"D-CAVVD*HAUZWA4]N[*!G-+!<.KOM: +M>SYO/08USI_#G0ML1E7P&)5I$W<9(L%%\7M0SYJ!@NES,*R]AJ%QVOE8(W"E +MS?8EP6[=QW8XITZ.*:XY0"3=D?D54SS^@*-%IZY8LHVQ?] +M(`C9(7G+I4/,RV8Y[@$PX-,5?2N2MX=_>,;`)!/#Q!!>OG@/+DH_Q)52^R!1 +MZ82D9-23:!`G7JFG%"+`\ZD^G/$JG+V74WT?&$0/+T'(#X3B^W5;3D]"LKI2 +M!&_D>#,\C0#0TH4V)X6^K\9BHYNPJ,7S-K#2V2`%Z"CNW;D%/?IHEKD*TB`` +M?R8M)L(:^2','FF='Y=KIEQAI&9(>&U]B7'_Z`_(QP3`:VINVT@Q,MQ8^W5C +M2RL(PTK'VT3(2RQ=6#0^'6B1#<2UC?L:?HC?DA +M50[9@FYML2)EP1J>G0&SN&)*?[]K2Z+6J+R?:6(X?6:UH0GOJ;$PV!SV45C7 +M7'[B5?^='191H@HG"NCO2ZK4T"+@8X]*C$DI0U[)W2$FOH$Q`P1M.0,T;M-( +M';B[RN#BU@H;"":.5JD#^F08:C1!2;0%_F)QXUHSY0#(+`G10(,4]O`(WO03_MQ-RT`B3S +MN%GE[9=L,=.:SD(-[VY(ZSX$ +M`)-^<>711RXT$/``RU*_46JX5-W\DM8.E,]ER^X6]IY0Y?9TN9"+P@_LN^%, +M0///G.Z\_R=B+(-,.S-+,:,].^)\#J,Q;49< +MWD;>$&F2TWHLPJK8P;Z#;1L#:`93F`V4A86`+&_Z8+`3L#7PS6;U:JM$5_U, +M0:%Q&"IQIA.Q^]*Q,,SHPA!L\3%[#92DW+:W9&*X?C\_GAMK@V4"$\:.\(2] +M>XAN/AF"_`)SM4YS,0Q<_<7"JZQR'57!(-P$$OLR6LW?2T/;@E>#>J0S<#8, +M'!JJK$NS14+,<%= +MM3@[WZA6-P,O3$C?X=.>CPD6?1TKYA(>L([4%]MVU>BW1(N$=5-!,S#H@3,T +M"(CID*I[P0XDST\V&:P[6>^B]+VO4&>;$O5C2P6-4SUEB]/E7^9@786%]=!/ +M+YG!UNY_X>4`YJ>AEWO0+U=2N1O7D'^?P,"\J0^S(R9TG?:J\6(`A4<)S'WS +M1O[$B4HBX'#27=W955Q#9)!C+7G@J)`)1FW'B<^8TS'HU5<+OA=<>;7%?=DF@8;!]FOO)Z'_U()& +MV7F#U<0@XVUH`>H6P?2!K#*@7D"#!N0(LWRLKKJ`3E$MP67*5GNC*GOJ3M#_ +M@#)03X'#1J,[DQ,X6_N!P:4NZUS)<>7S&:K%T$P$UQ@C6J>=/!R*0ZDI\^+S +M\#C)6[5D%($*=*J*!<3@GNS6XYZ<^J=-O&6RTU.3C-AT1:1,R$-).J$DZA78 +M32UT?1P[;RP-8.%K34'MA1N=NM$-T-59P%\O6V>^5'^,;UFY"T +MO*B"`#N2!)`#QA@VGXVK2/^@Z"+K\`\IIP-*C&#O'7[_>V@&LLD)Y9IMF*$AI2V(S2RY,NRC-G[EU>7[P7VT)V^^I +MB;-'M-EQ3O$DU:Q#9)6U^CR"$1!%>!A3ZT0DP/DCU12L*1&G*`S_RT'^N/2+ +M4;(26';7V-KW>T?EHYARTD,.<:U>4;K@BY\W-1VF72.N$]IWI0LK*XWTM;T(3'?O. +M`:CS<@<0C=6SDN&(I''W2==2YV0")>Y.P.W43L,I<:4]8_K[7H/=0-!P_!=H +M3T69LC2#NA1:`__CS8OH*^7(KG((S`5.#98JZ_-&!1TA])X1GAS3T]TB`)I/^YVV&WH@A;$8;_D^Q/A)VKP'.#N=ZB%XER7 +M-;]ZP,G]8YR88&>V%8&/QSWJ'%.S?3+0&JU`PXP?S!R^";%VN?&2I6#1D3'5 +MWRT^KN,C[R=)>*HEM^2;&WV3:!$2D*!W1YB`2KN.E4;+A7CMQ!\&)DOZ +MD3`PVE9I\1[>F.[>DR^N*^YQ8C3P_)MT0E8%SKFTM_O;EPPK%>'XI`T.32Z@ +M56OV?UZ>^0/OX>\QM'BV\+2K;*/6J9!$644\9K-1KH0_F/]1?F,_99FZ!B%: +M)73CRO[A7'P<^4;9B&5@%R$6J]._/U2BD\4*D/QI^&]A$X9S,M00/ULY0"8< +MAMLI__SS?I<^O#,^]1E.EH3L^9/QSBGR$>KFN%%G5"QQXGM>\\(S6-OQ/G>7 +MQ&2]@7["C`=U(".7&,M6X_`4(%PLB/G6U_RYU!ZK_C]M89-&9.FWV@`6&`6\B",YQJR +M<#0SKFS60NL$A%T60R'\?(ZNU&MK8@O35TD9$3O5J`A(B!M^8NQ;9+. +MM:<$54<]J?8>N[B-FY-.-_V85419>"Q$LS/[$GX&:+=LK4E](5OYJ6+$96W0 +MJ%>==AXV2)Z<3RO2/^B&A.`).VT@!_%[`'O&!T,4^3K8?Z*IF""NA,__M"VC +MR'E#]KV:FS._X\`)XB'80$S=P:;^HA7"$O@O/\&^Y`VLEI)+,R9\T56AK[4A +MR/C9J`88BA9Q%:OY/9N=X9&*/SY;8CQ2B<5'>"5]^??YMK2TCF446X*:^XG. +MSM?='8`-;G73L,Q`*[\CL"@X3=P@-%_\[;1\O8#.R&+.RW=@2-^HZ[1(6]ZV +MAN%:Y#D#H-KJ[FBS*+'N`_0TSM1>&?/+,V-Y/BQ7G_,9X75QPS).JP1'1U\" +M[K=')9[/Y;YC@(81X&1A_,%+;WZC1J.60[+^."VIC$KA'3.I\95L#%L38_41 +M%=_V&5%.O9*0FB(D,A[9^Z?N<2#>"!)_/,L\;OIUBZ-T*YC_0IC&N,K7,"U: +M#R+)HS3-`/Y_5^!)UH=*?):'FVQ>`Y!T)122MR;VDWMV:,1_@)&;HB><9KQ/ +MI..]U$H_X.Q2?T#S#I;-0-B#=G]IJ&P6_,(\(]U";99G/$C)EX_N%:"6FG]/ +M>)HQ34*9]<%FC"5RH4],KB)*W^!_R`7E]S,BVDI1:W2<`5W721IC^ABT^+EP +MP(1?IWR)M?.(/?'6+EZ:=8)O]9$'\5BDYPPWA5=HU$U_'(G#C__K)SXM%H*) +MPUX%Q>I>#,P"MNXO4GO1.3;V!FU5K'O7L'`RM,_+Y!_B'*1,7\@!DA"D&,;M +M`OD=H9_,.LP\;3;)[#L9B'2S(B716MN8 +MYFPNPFFO7UL_UODEK9;>EFC)_FE;Y8V<%#7H8>+13]BEM@=:'ORE>ZD&--V[ +MXV4Z6!\?1>16/1JMT8K2I"@'03%A+BA5$/F&B?/?I_861,K.2!4Q1WUY&!S; +MLR4L?I54"(:H8QV:Z*56W[1]X?BC&9YE#`4.9+S$R[:08\T,[2%C4B![W+(S +MF+5JU[CW.TV_`Y`E6'KKG=I[QI'V.*P%Y4AZ]<^E1BAM_SQ71P`Y*6814V+I +M1Y2UJW*ZEOF',J\%O\$H?/P^)[K2+RJ1?VJ/AY//MT]/611^&@+H:WIWX5(. +M]J83U5"EV`TR0))`<"B@/FW`9(`<0]*84\Y=_]Z;`V'71;G:]0'?^8KJCB/' +M"6D+5"P7&?+)A[\+:BF=QBB:_XFYYZ01:MQK_%2XLTY<"\PV9I768ZW/P@T< +M*L)Z<<0\=KETF=HYK7J@].\%Q6$JVT"0M42+BIZY'`&_T<-";*WI%%G4ZLX% +M<).S3WEF5BR:+.?\-08C7DV&CEHIJVY!;D*.U*`F>?KE&%'.%XW3.L^Z*>7? +M,8$(OUOB1CA`K]`R^V1>O'@(I419W[.S6>X)XOP<;VWS(H3QD?'S)>I:(>#!9ZN*!@1,IQ#BZUGX,^$9W;!4,HU$ +M)5)XYHAS?GQ/8^6U-%#GB8L@L#E[$M?Z5E/R75YM8E84.CIR&ZP?ZX;VN&9Z +M)"J0QCSG0J7X173!N*V_[';H+IBS;8:\3VV8:2MP<3H_3NP;6W`(Z+2[R)DO +MF/K"//T(Y0G +MB2B4C_D(OE=F"=2H1Q6;K*FZ&:\.!N96/;"KMC]2"9^J%V[.RT!NE&T)4_)YM.A:5=.288#-;9`0JA +MRKT$4UTDOFXB2OIWW\*1LY(!<@82`E`A.IB:04K3^`[#HIQTY>U`'CWT;@PD +M@L5J?,8XYZ(;.!-*]>B2BBP_=3:82HA*5U3VX@AZ@(%AO[JUL!4+VK)EYN5H'#R,0YL:\IBQ>&\@;8V>4=^*7(P^1]Y0.+WY\\(?$4O +M1)]">QLH"??UUEK)==P&"VQ5#"RGZNL_.8=Y*R&YP)RHR9[Y&P\-:S:/CMC6 +MC)'B7#R2/FK4NEZ\GR3<38-@\*EUH4XI>;CRGT!$O8&AFYHY&A7J2'.M39)U +MF_:M5^_H`!TD]SYR;I]-03_0ET.9N`M(?3]]@CVHTND[F +M+LANAZ`>.@NM,!T4?R&FV5<+'<3"-3XX,OJER,.S,(?N[.)F7AAKT[E&H?Y9 +MI95:"E;*\9[@`FXMZ?3YD=&=$MS#T%)4D1UA.VA"':\OOA76,Y.:SDS*EMI: +M82S#RW3),=5A7QROK&&_#YN3YZ9SV;@WO7N([XRO61 +M[[5[V'G=ZIVQ;72E48.>M.'LK`@'`"9LOT%0=8,QW8)..0?Z2" +MA:PA7S/>#P*,RW^G5JH;<')HO?9.?,`?*.:Q;US38ZUAD:3VI"$_3`_RQ8'X +M%F:S$B.8WTAR6/X>7W[41%Q<8D1J/8G[T`*"HW]"Y6D'3Z[V9/]5%WJVRD[J +MH,8,P/D\/C2W/5O?_7F0&H3.$3X/'$B/GU8&??8!)K(JZ)](5@UNFA*"]->Z +M\Q-I_W(OGL:`7UG])WG;AV]>B7HZ#-Y6H58'1>HM.$,%>KHS;G&"TS:MT_:[ +M+(E8:;1%`X#6"Z3];WM_AJ4$_[)ETJ?*/KKONEB;0-/&;X +M?A,U5Q%[%I-GI<%8V=H(0;II(]>.4"V(/ZA+]2>Y-"/#TG92K#KZ(FK.AY,@ +M&P#E5Y2T'[`XT1G&9JJ3.1#DNN>_$T7D$TT[+81O'/4D>5EU5JTAPB.'%^^; +M\54-KMO-!KP-MU813\F)W:1"\[=4EF-C=SVLS`&$;FVUF(A]A2J%IWH>\ZX90A`X'V4S%`'\ +M._*3-AL17!GGUEK@4MCL:<_LSX)M;D;WC.CQXI*2SM"UQLGY-FS=&<5UU0#? +M!-U[GE+1?KY(/<-KG+G@`L\019BM!A:MDH@!77SU0Q*S-&%WM2'.VUK[)R,^ +MTUMN$0;*L=:Q"+O0S4'DPOF?Y>*&DYT((6WVBM3F_%27+N&ZB7:0>-`3;3\O +MC#E%"^$+MS@(3T]NC`TNC#],I+$_=YG_EMRDTX)8##X`U(6`*E8A\'#-ED1=5SX7%C" +M]R])QILMLAYV52:,FJT_OA<_C26IW(\%QKG*9&_30:HVOS(NW28T]K\@#[(= +M>#\S@"3N&V'^2.3*?=]#92?'\Z"#VC>/T:DX*3QN:I;1^_$-]T8](I#F3^[9 +M8[V`]0Z*Q][*$#8&?PJB/`AW18FV)?6U\FZC#[O?:CGGZOX?`<8HBHUY"4"B5R)F;^#X6] +MP)=2LO%85N88M&"%MGLL +M8N["($EZ!1@H9>6=US;]8'T&M>0+6,`Q,D/1#!H@Z3F +MNU)XX)AE39,>#=P=,6E$OI5VC4C'QR:GLM:@XO[V$@4, +M"[^;IL6SXC#RA3Y2I$.S*C+KR'#;%KFB`Z.2;);/G["01;T39$E`_"#PHE^. +M8?-@U,_:[K0EHO"M-P]O%^SAFWWT#?YL&^F-2$2%@<5?Z&NQ*J0#>2.D6%VI3D)0\^P&NA78Q05C-ILC_[5PJCZW%X +MDN5>:67<:@Q,LZFXQ54SGH&,CF3#$CFQ%UIQM^3J]$[L2W5NY];SK%=]`H/> +M(>+B;XK">Y>>:C!E1K66FHD6+!215CD@;C"@NX+XG&UCVV[AF:T)82%"+6^VDZ!TA!AYP*9B;XP/"-GAQ1=L=,G3_0['9IFN-Q*^?SC+_!E\T6(&@XC% +M>!/O;\*%YE#J6,(6Z71#PIV7.R>&@$U9J +M4R(%W(N/YKO_-$7ZI"G:&:/2X/TF7T7:-+,I9[0&?P'.:$([L$<:-6^W(NC= +MF[+)KFUT8D.)".E#([]0IY;SF]GBXJ*G",3@2 +M_O"`MM%_FK'&R9OA@LTH()2D3CUC^#IBG)01_QB!/B0 +M`@I=G,D3;_K+"5G*G-5J_,QQP?Q_=HO]_=;;`,5<@,.-(,]]\),.9*/F#5>1=!^&AFO7)Q5@T_ZCC%!,(X^K+:0Y +M!`U9S/>Q;R`@?]TN^T@S7K8I0!@Y6<"+X':",NAC?1\/$G^43Z0>TNF@3X!8 +MPAY="T//G?]C,7?D/?\CH4+2S+)+'.\=1@&0$A?JR@K9)BH4X`7`XY`'<,HQ.$UV[)HHDJ546EF2!/>KO8 +MV5H(L6:M3U+^2K+H`_*JRU5*_1]T,29A/(ZOA>J=DT4^-)M9#&L22\]AB8%3 +M&--=>Z)-&=2L3S7''2U+S.]U&&,%9&_-$!=DC2O,?9;(\C]X!$5)[1+3A![% +MJ::QB<#C()CU>CV6Y,$LG$B<>R!:8TGKC@44A78FVF8[1<-A\9'FH)CXX!7_CAM +MT_LR4(]B`;8S3:Z3,`F>GLA(!<1BDYB6V$?N0BU%&7[]K.?52B<1@3X5AR0V +M6\<5.I<S2*SFKPLR)QP@L2J4F`#.AY^0:\!^TC0(&?S0J +M7$&@J>!X-&9,C9J83(COY_MEM4K^:)UQA9CL';?,*P/1`-=4/N2?M +M%:?87WI?@:#1:_UBMDPS1V,F)Z-!"']I(V^Z:/V"O6HJ:4+S3 +MW.N&'=AJV()GMUFUIX0).DE">OZN>%/$A2B.G>H\O1XC%:K;1\7N*@GJ_`"\ +M3.RZ`1M^(D/0@@0!KGH,CB2FLB>:EZ-LZA`V.-*.K;C<#^ +MQK@ALGO2;+)*F1)S?[`10)XDG1?*@7Q=!X/[AJUF&F[J+1;L6UZM#^,I'3G9 +M_4,-"[[F4$T1=E5FP?Y"L7_FU&!B<&EL[:H/JMTSN!B#:)K*GI$E>'I[<=R$ +M!U;6%Q=NU,'MG*5*BBG<,=H.4NYU1W4LPH0MRXT)X?MOSM%6D?CL!@Q5$L/2 +M+A;4>J/L>-J_#^!S/*"E0UZK%U644I6*R2HV,^U0AGF/V2[+QI/K:<5.2!\: +MGW!"_"V;C5>8;0SMXLV/$$ZP+K;O&299F("DJ<%CSBB98I@Y5(Y2TO55<]`@ +MLH7I2O+V.Q(1MZ+R$3P32+000[I22":GWSE_/WZPU.0((OJ&2Z:D$(A08L%(?G`3)M^4#_\[QONQP5YV<$:$O'0FYOI1&9$$DV(&6K;_ML +M@P6[[E#/_PN3%KVT.8[-]-Q11JBFYP_*1EN5&,$4@C<$]Q?PG$^6S'+9"K!8\:V9&TDN3K^*&A6C=] +M:W)O]NSE[1S>?EJ@7VPXP*RFSE_D/G]1>VIC_1![]HVUEMK5I6F5PNFAI[7= +MHL+_L^ZG`.K4-4,#6>#H4+GU>W/F=3$_.)3R8*YZE_\!PW$$1+''10V,H>@O +MPE`L4M#CMV)O.$,>!%]XCH@WJP:&MQF1C-RYD[%I[I`#$X',VE+-UV#?(G2D +MX=`'FU6R@I&+9Q)&-*SC+A4Z&CZ0\A4$Z_$HR#F1%"-,?4+06 +MWKVB'34S`&49_XEUA]XHLD>53"VZ\Y^N!-6"4D`840O;8+;P0]HYP1"HE+W< +M#!=_EF:R6Y4SY\K9Y@G7FS>W)3%48KP.1>J94_E5VC`BI!%F@.Z:20N> +M(#SCV]S;6S*4I8JZA;"/'1R4[2AU!*%;U_0K.SS;"R!K:1M<5J+??N,2`4QN +M*L=L*(VY!-[[>EF@5K.1KMO4^F9+@# +M]$0'$KM)6>#4C4FJ`4;^\V;`K]\X."!@U0XB80`B:5T3'DWA`*<&J70U02^Q +M)V4^"'([(5;WP<)MG'4+Z(:]'"P$"8O +M=#5^M]M04SMA-_$;M>926PDP99RYO/__"-\>S.8%/T,$Q^2G12&P>6+N+XA$ +MIDW[^"I)AA*Q<#.+OD6A!A#!(C#4Y[PPAB9/A,O-\1$"W.^J5C[F1%*74=-. +M(3SK]1R(UA`<_^?GHV)CKX72U<.`]&W5?SES%B.Z0$O)1.P)-.CI!2!F +M_P-QJ&!P'!VQW'S@,GH.RZU8'ZUCC^AG8WI7.SX(K18EY(%^'`&;T*ACSQC_ +MLG*U=""GL\SDG;:"F==;,3_ML"_6"QF-#60-;,AA9GM4TN<_P.SV)+O3+725 +M'NX39,%/T_9C]WT'IC<-3*P`Y:S_G&S<_;JWE^46!F;/"IT$E2[$VU;9AY=. +M4^L`!XT7LI)5$X"W^&"#OB))(?)5#!'N2/QNTTEHQ;CSN.`8$:%25G6&G*KVS*JP\ZBS79^Z8;]V\A@#A\OU'Y,G%`PA-?A_%$1*]<:[63O6U6(0TF2NH+M2)7(%10,VIX8F60)E$OZO%N9;A+ +MUPW?NNRV91"0?.-B_G1EVS+4O$>V2^\."O +M!>LJ%6AKS_I#5)U]YV5C&XX,)/'`D4X!8A'!*[=*PM,FLAK;&?AMW;>]L_,* +M!5)G&.2$P+M^VKK#<89-Q69]"W07=T`>7G$#+WY--A1W>U^QK*]*LF`,-*H[ +M(UG@8KO)\SB3EJ$D +M@CB\V\NDI?R+MA4&`FEN0AIY!F_H9U)F/[\`FQ$NA1HHV8`C"$E+_E=PJ5B( +M,RM0&)<)*[[-6(^#3X)"4'0<59?#=@#JGB[.5K/+/VS66%=:^BWDZB-HWW1T54>(?I$]IHU5RV8-O)L7349H6IVENF +M!YV:Y._K1?-M2&]"X2NQM;X0^2%+_.JZ:M@B`I4C74$;7;G\T:G,+B5V$S?N +M!5F2\N-G@CD6C,2KY,)\PCXQ,4O`VW6#T#)FR5/_"B@X@AWEQ(X!$1OM,6DR +MQ/I'T<].Y\<95<#Q?`R:=-0%";^917*R+T2[HV>R;TL3!XBRE)F34_^X8!&I +MRB_-YZJF#2+%+UA.ZR0O^J3973/6M-VT2R-4_U')D$71QF&@EC8M+D#DM;#! +MZJVL>:[8\"I-`&=P1'OG8I=>-VGXADX[WN330D!X%'*[^`9N2!]I$ +M1L0[369ZMJZE##[0Z*E&F)3Q8D%,,F=C^^Q(/ZU@])I*2 +M4P4EW^3_G;C@$61XZ)R&-(T'T!TX22)DB:R((B\S>G4<>KE6Z-_C*W<%:,%U_*!B:1(8%)% +M=O<;F1/+J4K2+;5#2G+3_6+S/>.JU*!O^2>Y=#GD9,/KE*SHCO3UZ6XQ2IIF +M.+6?KOI8.KN'YC64+L_<.G'WC&T3SB%]ZI:*;\*HOALO;ED*4&TIIX]6\#7] +MC38[&DR0%F`G)AV<+P;*^W)ZVK!V(J=_25*6KZMF8"U'G<:#^3J=615SHH[. +M#;AWX"3%S%NZ^2PKS3QER4`-5)A9JM0.9Y^79>N"#6SM'CM%OTN;,$W +M=']NY38Q9"@)W&_T&=TM[L>GK-M6#DA-4?^&@TM6>D]7Q13"KLG$"EWOA;*+#8W( +M3WV,U&4(COI%=4#BLT&2(!9=H.,V`^N]I?*3-U5;!&:!#OF.Z,?QFJGEQ.!! +MGBQSX^^:3J].\&03SB%5L],8->='RJ_##&HQ_Z4ZA1YGD[<<`K;J;_!\=X>> +ML'O7WH%W#V%XG6;N2=>Q%JPT`,C/`\D3.2:UWZ!\([*7Y9D[;:%P#AII8#5L +MY`-G&'6F5Q"[5#^_&5\2`/PL[BU#I?G@+)YP^4-K:/M\/?AY,?8L:DZHR,V> +M`!2_1L-`J@E_#W`897-*@8:)C:%@E3PV$QDION(;ILCJ[T9W&BB5MH])6F8. +M19;9*E!_Z[5)8597I612'I"WO&.HOHY.E?P1H+7W +MBCC0F:OLSK@A1!+%#MD8$`)QENK3Z8"WT%!271$^=B),$JT=.W(H#N*?(9LF +M3<+Z"ADF`DOJ[31I?YK0='OUKW^8@3_* +MN.8M/)OWRC"@NEW!':EX*%$!F!5GX+\'U"4H&)&$L"K9*/].E4'=?7_]<_GE +M!4V,,)!7X4)Z[SW'!/XHOPK`;S1E./?D/C3\A-<"L=O@"E\I:>D`#5Z.NU-; +M6]FZB..-&>WP9P?M('.\()NP<#9Z#7B\H(.MQP2Q$),0`0]A_\RF=]*[G'2I#H,Z4F--&K8:MQ0P' +MHG\LOMGN:1LW(2!G)?Y%O*7J-KU9_)EE&HBC9M\V#'EH@I$V01+*]8&;M>;= +M@3?Y<(BF.6'UV1(7)OG[!RKN,`3O=6!^/E0(_RF(C(XK?)[+",AZV%HGPDL( +M0O*._T*W*M*KX@/F._18__H:U(=,3E9$^`7I!_O+W\K?4,.J?KC*%B"."-85 +M_!UFH4@6>>S)O_M5K,->>!%5G12_$KO/3&W//>O`A?5YU`,@0JI\:8RCK*L. +M'ZK0^%25!$#7:L"AN#.YB<:.%\>!I&B8@2&XC"/U;$)6( +M]PUI97[.:J8*%CX>I_L@T@YD*_I#%T-K3R#/&#R_L^E.M)6#1L%@L\,4\6JE +M!*M9:9%T"92VRQN;AJ +M6VZQXHPO#YO/QH]87L"X5(W^C9$HZ_OA>"_`_8H+]?GV+!MXX(C"L#;0TVF(9W/! +MS-L;0$(9V,(9%5'%9]G\@FB07O!PBL366W_CJ6*\Q##Y(]9X/^`"34(J78#2 +M.G89YC94\F@/M0%-Z*Q"2VYFA$/(LK11Z@C/C`E#,)TI9)#]!Q:^T++3^W&[ +M6BB$I-\,5`$4JMI$3)4QA)Y'?N[U*;?S,4'%R@M:CCRK3T@+,!4B)>O]+7;X +M!M.R^W>0+,I*0J!N$69$]]P:SUAQFT/#S4BHA>Z+PIU*<[[FI-[_#W>JU-WE +MN%GA9_@3V$UA\."G6!J#ATJP"['"NU>4KK29C--$^&C4IW#K%54_Z8.X9;]H*8-8T2S +MX-XEVH0H0-O=T\O4GZQ?TVX?!!D@R.R5)C+M[Q\8!P?(TJC="H?->>J8#CP6 +MYF0<(L*ASHL!XZA'G@7LFU_ZWP?'"'X'J_IBU>G^D-^_7<#6(;A5+O`1/[V= +M%E1Z9]XC9D3&_U&FCUE:-`W?#ZQ35@RHYP7_"(*N`0$Q@I;(H'Q+6\!KOC`F^.K6PYX).S#D93'-F!E:"TA5EE]6G5 +MD%1#25`N^169'W^T%&2?*L(^%N;$V?P?$4"WT'<,5H`A\>+DD\H.I>OX^H=( +M.JLI679-L$``1Z"#5(I7@/B9]N@AF%;0>-HVE$GW;`UJ>5!1IK>7H7H?F;':,$LJO#$&7BZ=!UK>%:D&Z[9QA;Q"`/W(YXFW]S'=GW$#J +MNJ2--O+DGW*K>ME^6E!%-;) +M-9M'M76*"&Q"/I,,.X``&F+C6MGH=[NK48=X;/PL(S>4?%\A]G8Y637C*UM8 +M1#C8.@31S=Y,5O5P4X$7!1TO]/WGJ=N-UF0,XF0%Y_N%'P?*$5VYD5]L[D[" +M$TCZCQ#JA=O9D:LZ1KOX_1T%EU^3Y,7$ZO[":T:S6]):8J`:BO?\FE`)8KXD +MOKUV?77IB*X8P@F+.B=5+.8S.$*`?BR\81$DV1$7C^YA!&:=`IM-:4ND17@I +M(J"'@)AUAVJLPHG^.CVE6NS,Q#V3X,'>:1B#*;\D,6AJ;O;=2 +M3!I0&&]YHD)CF>Y$N[["+T-#'1,K1@@`M44$1Z_L6`%Q49QKEQ-H.K_7Z-K3 +M9FV)XNGNV?A?7SYRPHTY2R/"=+//,;$Y](:0TK1>9J:0*E+L7*<[0K#:18_F +M<:J0U4:8E9YW?*.M)Z'!$VW`\MH'CX�:Q>C"#OQ:=2GK5C$"P$WG43]"0! +M%6!:W(Y.-P6S`:5SX6=^6$\$K2;UR'V;"PVIZ<]%GW>]60PHC!J4K9E@B+$ANKQ3(B\47:[QV]F+37S0W,AI-5@CKKT]K +MFQ!1)-"NDLF%_3V\^D?W_SS"K"&`0`/_5]$@@M&.@`[B[]RCRWL/M-?Z!_FU +MT#(ZC6("2_XHV9,U60'[`:$H[NOAO:"*_X&O$9@&E3216,'Q3E>I8LEY[)&9 +M`AI:P>/4Q`@/.X`Q*_I)=[.A9'G`DR[UN[FD.0M9TC&?XG%=B=AW +MQ!3(`*\W;Z$H&'36^?F_L8.WJH/(%+J:BO?GIG7"Z&G&M!"2=(MZ4$'''+`7 +MRU,VU\X9D=9ZUBUBY/\O1,6/[R;&;!>++U/]"@94[P[YH.+:I[B&,T6#QLU9 +M>X1>6:D%S;/']9X\N^I;)SE!!VJR>,-XT10^Q3?MZXII*DX;B93I\U);O.,( +M/)PA>12!SCERZ2N.O8K3XX\&@0VO#1J^H94F="4FDK4`E>?#,S*)SYT6\X_^ +M^RP\%0%<##&QJ_@L8%0S)5,6M@8\\'8]TZ\6%N5.K->$8$:P44MS%D@?U0,W +MQ133XQOZ[`"M:U6LSY^1@2N`T93U)00'*V.C%_$@``1_!H"=/2S)4)?@WZSP +MDX"`P7,^G&\X"+W6VL/V5RS9M3NGCS/W@**44#8!:E?4S-I2^0@(,%$Y=;-/ +M][/#J*=(FF'"$UHD-6LIM5,?H:V#\Q6P6)V"M[V`#VY8@RZG[']8\H.#Q%O( +M6TS* +M;RZAJ6Q($3A5"`TD0RWK[*Q\)34=V!DL0 +M%71R1HF!VA@X0%3V]S*T'#**TY]]B<+T+@L"'P5H\K#+6\C&]2JXWCHK[0">) +M/]@%B?:`$D!&:L-0A)?;C)R!I+H8;.U5-\C=[XL[S'G1'!B>G,WQX3!X1@]X +MW_R^H#O7,3F'*0ZZ)4]23IRUJ/E[0,`%H?C-@^S&>4UQBKB:!=)\B!N_=_]` +M+F-_#<=!@[=X53T"TIFROWC +M6NZH;\($O]^,C0B(>=8'MZNZ +M^(K+L<2.S"AY=SR\Z878+U@]TK>Z$GW&JU#-9DN=2GC:!QUF6%$K5#(I/\8M +MP],Y=SX[7VVA]TU*<*]8PB.BP_'<\<3D;JU(S>4/NPWO@DVET491$T +M'9'6E)[0H]\ED[C<0)*8W#G=D51M]*+'^ZMGZK_-^UX]1W_^D$T_D!IE'R;: +M,?Z9P262>C0/^-O/(6=\"J!&XW$7$!J28Y^F(BX-/8J.[JT[(F_$U3./*1/W +MJL46VHM0J$U#YZX8OX)S"EZ-\IQDD_,"M-A:'(82;D8>T#XLX-]!BQ]2`/K_Y>\MT(=&DU019*AA2__B/C%[;CE)PYLQVPO"(*\09#9_A2%T?5 +M['3X;_L#$@VXQYWZKT0XY4HA&@^D#>&N^]1.?X) +MH(_F(G)P617=QFW/]8>#"Z.NY78U(=W% +M1R4J+AIL!X[ME@6'0E0=FY=ZWTN&81`QO`/E3@?!"#8;/4-Y_5>(F^X/("HF +M?R2B_@8\@NUA=ETR$^,*L+)O_BP9&#$IB5&`F+Y/0K=3\F6#;4Y/NO>IC%0N +M:[WIPJ$].4-AA\$Y9-QFJ["ZO-)\(;0&:[9I$,A(<_,HEAA5+'+1"-9(_Y?! +M2=[SZ8.YBW)O-Y*S2290K +M1#%(>=:+D`K=SOD7[ENAKS/V)3E9&8&=58EH`>:9]JHOQ*7\JYROK3-0@$YP +MK1,5K]CKMZX!,,6/@OQ]R<@01_0#/A].T(\"DRW7Q`+%D28K0*TA*TZ=^J(+ +M"@@S06.BRCR]+WB6C*\OWX0:8,T"&74N__^@2-D3U93,$1#("F$$8W0",A32 +MW<;D9.24)+[707PZ_[]0[)!:$N'U#

    )^2H2"@M?6ZH&L!<(N\"XE%<1XX +MJ1NS#S?WAORF#U695CI9!1:;[]@`O6!AU%9^WY.7L:`H"YH1CFB)J&3#D.Z+ +M([!F%4&*<,!80X6PSGN74PR*,<7]MM6GT3ZWNI/1>>_&)99 +M3T,'K/?L/)*L080A["H\Q;GXS/]PGC#N1V\"G&2":NS5LT+B9;H:\=)W)V;R8/,$^E_[T;81!)U1#OJ@D>O`Q9B7[< +M"XA7[.HD"&5_C+PD093;\R*B0'3,Y:3],-:RHK;BJ.+C=2G.>!FL(S/73 +M_[/6+1/YER_'`O:Q?YQ2W'YI3O,[$1T>NYA2.H]QZ,O=0?#_M&1/GDF/^',] +M8NE\"W;]KW/LU,01<$N$JOQ5U(]F7\QIPP/1TE-M]]1O>%=`!QM>X9 +M?%M>$1J.UKZ4P"(A3ST-S7BTYG4?\%%-IDJD`>SS<6TTA8[):6I5#$62(_(+ +M4_$%E8/P(9C.9#*C6$71D=)KPXB?^],-:I[IA)4NV4$(D%2W],>'<+]F"1)L>`"Q[YH=X":P)K:KF=9W=UW!Y`RYD7$;0 +M&QUL$A<._!RE$6>QX@&MDWXVY`K;E'Y+JJ9ZD?3U&:1QAJHRTFP4E +M99*.N8ZR9DGJ?V>"D$:OG!=:"3>W8<))9XZYP,EYE"9G,RP;BVN`[F\\.S=X +M1MHEP/C\.9RT5TW2FTYKQOY;H&_;!?LVT10H06MCD&X,:JOFH$Z`M`@?P\S5 +MU7!8O``0<^\GM6?46R&_&73$MQ`0`LZ%H"-_'#.<]UN+T7OV)CXV^Q&/*G"T +MN@TOG,W6GBL:[K[*%;[?TK5+X,H*&:"S""$7>!TECXL>E9K#"H?]<8B[4EGS +M>9W1Z&SR[Q?LAE5F'N8_--^",OGR;8_KQF,V0EMA,4$J(Y/)W5,Q)!_9"IQ) +M]#OV$C.J('>PUYD6-42_1!W,_\)\(48&5]=4HER.6MQ>4U92X.'BA^1-PB%= +MNT?CD-HJXOA5%%2`VP[C>HVF:4E1;(M59_Q#X3/L60772W]69S`.2[0BDA9L$ON]W;Z>+L>5#K[D?V +MM:L.Z!Y*GEXA@I%G18^CNA:I=K8#TR0<,^1^D;N#HDJHV0YED!:PXK\,I%7!N@I01#6_JO!2 +MR9$5G+^%7<,#MNCM4HIFS%?';)&7U&$Q,1>`S]Z^A/13CE4-,/5\/=7:G$7? +MMH[7:+,.TDU^8KP)<\WS,>7@9'IM`3FR,FXCZ^8WSPR59KQ6\IKZJM!ML*WZ +MV_H;.34+]H9&XEDE3?^Z*_BAY$'%6+(_'!%-K3(+J$C$2\39=090\ANE`3C2 +M"P$=%,N8U9,Q@CWRVC!&QCP<[`]%P*BES!^32S:<$1#J[^H?SH>*7[W0?^RH +M6?8EMQ[[ET-#D=BG3^^EM"27;3H@:,WT$L;XGG?0UD1W.#&?*7_/V5DC+O<- +MVRT1))NJ*O1\M]LN;&E.J*;64W.#7PPDWZP(77%&`-B@2:>!8B#*]A-DCL<* +MO`&H/!NJ\E'A!3!32='O4#B:4P@JEOD1AYTD!EL\",?!/)8]EDX]=IBW3Z^3 +M*-Z#.N1KG%.1)G".C=6]X'`]].UHJG=<'IH7E25 +MDDJUJ&.Y(TKILIF)9M84;K8\]8_^,!V5J8_Q"1M1]8V(>LGJSI'S[[G\2,_3 +M,:S;.^CRB`2:88-WS_%0'BKT@$>[ID]ZM)S_7<$[F!JN8T\(2RK."PT&NY`^^JY,/@"9C=)^"A7C_V")>=@! +M*+P*T!C8$0O:P__=?5T% +M**OLVFD/Y'*<;45,54K-U#EQ<-Z&J69FNY2(2V".98VKO16>0*IUE1:K'_$> +MIE/4<+HB=]8'#DA$F'I8_R->'<8H0!6FEJ;)T2TTDEU^[K4+T(<%B,*TB`XU +M)\!%BK`V9Y?;)XWE#:Q^3PT/SYR)(K1RJ^3O\GHZ2>N'/LM_&-U1E%&>L)DN9Z()+X3[2T[$HN`<0"B,[^E3FDX6'#:^J3:&LG/'W +MSSR"13@SK9!.]%KFPJD\N&A56[RN6O-NIO93U@>TREAIS6DW$8#4,`WX86CM +MA7[XE9_%$6Q8#R2!,(\5W!2;*4_6I9V[=B3)2P&C,[R#WX.2-N#$-A#DPTAY +MTXL2%"J$2AV+)@FA?!BBNN&)!I?ZBD7=S`$7Q":A_8]I#OLXG@I9FZ8GCHN! +M@O=2#ES'2V2I\GJ+P]#&\YS^0/E5U3-.XJ16<<*_P+#OSOW.9'`JM(`Q%8'O]#@-B\ +M.MXQ=R#152%>>"WZJBC%]S#"%0X +MP$^(61^^23%'=.&R(!FWR*\T.2N/',/Q"]Q-++_4\7>S,BKUK6S%,*K9:=12 +M%G52HM54^^<5S`L$7&/U4S;]UPU_*X-E7,E:Q3OM4NA[0D_5'M$:)1HA#Q%VUR9HH0/VR,=\Q`8MP1J@;CCDCZZ:4 +M*0F[+_E,.9-83QFKEK!EN#2AJZ94'@WL]*V9/V<8B?VFG\FJC>.Z$&XPO?B'KSA4:`5$F[/SVD%;-:R$(E!ZU^=**F@ZQ&G=W$)?T/WX5'6QQ[ +ME;_R6/IC9<3ZC_QG#;W*4"ON:]ZCT>(871T&4Q)B&F]<$.:K21$";:;V$&8& +M),`:%"TC!BSPI%J@QV![9['JS+8@80BIYV#'^5QG\Z)\D7Z)I_H$,P$.7!/; +M35_H[AB/O2OPX;-I47V:'@A#EZDIFQ*N/0<0*9SM?X=JIN)[$!/($>'4\.F$ +MB4-J2@M>WUC(R/X'0T:K\NBOIMRR9$`CP]Z>TN(>IO!C6-?V/E<;=&K_>(L- +M_Y348ZOT$6AAWZI]ITWC[P^HF\,FO%AI?8(9UT5^@!I!29"(W8&[VFUX8I`3GHJ/E[\Q.9=:R +ML,YTPGPAPF*WX'U?.*C>(T('#D]#/_(G-9KTX:+ZI2;>787*JUYJR_N( +MF4P6@,BY).E=BZ=-;LXN/,<\'B&R$V,W'#U@?C,Q[=2^[#F[M_^5 +MSKZ2E;I.#N]!'*ZIG-_MU?<*0E#WMR/?/,9\:A_];*1._R%0^]H>;KTP&MO< +M*MSR(940/K*>Y7?U!*M'DKXY66+0Y5%,F_G6]4GOJ[(OK[/\"@PB5?#J +M5DD):@OU(P@5R`^_9RWV;N$ZJ]^%5? +ME/('G3X3WA>]14.?:1)X7_@:CE$,:F5,:!43^"W"*14WSKI,(AC2T5V,+DQU +M6::';-!<9?#-4]H#N[G$S?I.0,*?WL7J:UC)`5'#R%^'K^X\YIPD@.T&2)02 +MB27"EXI+,L@Q]1D\0S?V?J<:0B;!<<65_57M1!)J.M),(Q0<>THE"V;O:>(3 +M\R9&T,)6#,CJ.F2WVM`Y?TP/8B2B'?T[&46\_:AT'Q2*?QOH66'^U +M%LZ/R"&PW$^"114;CU^D_^2HSL:`E_*0,!#Q%273#N,9I8_NFQC%K;G@E(8$(T$Z +M(P-<.U2#Z:"U^W'`L-!D^BFTS,HHRMKGJ"Q1]:3R#+G1/5QE(34V*\TP)<]+ +M]J!?7ANDT>"";RNTW&,_&E-D&M"(.L?2JN6RR2(VHIOWD-R=-5^,`[88;TF* +M4X40G)$P`)37RP!B2%06UZU5J974>WI-=V7@8]?8A=1G_]4XK8A +M5WC9__B_`Q`'7,DY:Z>_%^`?#6[()UI!0 +M+"A3()@:@8ML'VU!5^)4F]/ZO][N&"SM1L#6@1,KVL:X"R]41_E12OS7>13# +M%K.:Q,%"^:-9&=EEI`4#/>4Q/U>S:AC(M$27EE#H)U7YQ`DZ:637)AU^EEX) +M@GW^#W!OXZM!PVN#S&/5T97NU3*B:?'&AV$]2%=\=I2OL:_/:G\9E\UB&[/. +M=TDNGMVDE9ZI[/DWK7RL8B_4B&J2-[Y?KWIF-0V?`8$%QNM!^&WCT+R).LY, +M3\]*,1RH*57I78IZ^(IIT`2XBANTXS21AJ=:*68RB_!PN`+*B8\NF +M1&E"0:XOC0?"]TTAPR`R$ME&FWEES_O4F6H>_*6OC36'UC.YXQL`'.JX<]6S +MRH7H-T*24XCR'ITH[8W1CIPZ_[]!..O8LZ#KHC#GU%UC+0^QCZ[KZYQG`,4P +M>TW#7Z_\G&+ITHV/=6N>2"O7X6W8U$N7`5U>3-L5Q3'LT$F9[X#5_1UNE7=7 +MT(=KD59EV*X/&PZU$B_XL5ZT$:VN>&+G2PO*;J3%_6O/ +M3!)&G*<*Q.,1I7-DLNJ"3C7?H?`6ZE)]D/G2O!^Y3Q2L/0-+$U]@)CL`U)0( +MS.D,2@(4)W&&0#,.3N9'56O6"H3I@R`<9O)V?]GT5K-^713U;KP%B[[_`OKT[?UZ43^]RI$YM[WHM"$%^-43"[)@T\6,.L +MV;"VC$95G(II#]H8[4FPZ=K^"G!`\K">QJ'G$3VA0%(YV>I2%#5E[,[COSV> +M6^G5W56%#7*<.]`@LKC:DL_67`D?#R`B,*'RCOFUV* +M_%Z$45KNJD*._5*-N.O(?P.FUK4/YFQ[>1OR@\HO:49_N"19?1$UQ(RNX`78 +M;5,A]$YEMO"/Z6&@)XU4A,4U&*M\P,AR5B4)6:T?_#.)269>AIC/-'ZJNV_C +M=CV'R.:IN.H`&GH8LM;^@D)*RW8(8J](.2Q/T=-]JK=W=-=_#%-)X6]:00R( +M^Q_2CW?H!,HR<*8/."GS0CUP:N%NU1`ECJU'L1DU<711[Q;'1/\Z@)C=O`$' +M'N?3U&!)E-W![M?^":4LE1R_5K6U51I3QYE#(ZOV-KH^3MPT7J!$49 +MWP\N%4DRI"8]5R!MWB=U`?NPDV;ZB[CVOL@E*YD-#3&;&U-B#B:)#/*]BGIV +M+JG2YYDS3/+!PUJL.40*OR"BWQN*O8=WL/?-XPFS;=RA88^U&,([.@# +M^NDD-YC#_>'=Y`"?^+MGMM'*L++B>BNO(B1G"XNT,7JDSJ/IHX.6(V')I4^6 +MAZPIC"A3(9],IQF!;HHX.#N?\UJ3XH69K=H'PJ"$Z\5\ADTN(<:3`G$X@HE? +MC<>N?M09[CVZ7.1]%E)MOQ;V.SW/HI7IGK+N>2$/7-P6V=0V[\YO5ZBWF4Q. +M,,K1]Q?DYL!1%V'.GD30EH-F1]K+>_-_8YLSJBMZ&HI'*IV44\U.41IQ`+;, +MH_>C>SI@S_`G[%$PM?RYW?_,;&E(( +M>H"5-Z&-SZ@;LDDFZL\D&M?EZ23EB?25LKVPX<'JNX,)?ZO2QBK0+5)3W`@O +M/TG=6S?OD"/DS5B5)KD[E[(?B=J+\9R2@47N8V%A8;D"V$`U?QT[![;P +MPT0B,QO:W0N;+N7,HEI7-[1"M)Q=1`+T/P^"Q0))?;P#3C;X'=4+.NRS%^D& +ME4I*[@D:_*"O&&_U:^#<";+TJCOP#M=M'%&">.L7;+Q6$JL-QQ^`%!\9C(;6 +M+Z;D"@(&'76FT;TZZ77G+\R-AB]HH(]MN:N1L$Z',YS14`41XNXY:4AVQ3R/ERJ,T_;,WM=ROQ +MMF_E6?U+J8&4]^B#2*)1X(^FD)J.#UK@&I`#EH;(!H&JHRRNG>_&:E>C;>0M +M4W2X73]CBDY\W&S1;%YG,QQC904\.Q=&*1XLLRJ)M"+D!R(#=1XXP$$*B6XM=_NIGU0A[M-*6O9[YD:5=]G;U0._V213HFX+DQ%PL/MS>S-3;H%1>,DX)O-@A$<"+V14)"F`0)!*\WYH-) +MN,(;&&",KE!,RHY=OL"QK2_&W8Z0[*I<9R?"'Q.M,3X$3540O +M#U*N"**%(>W<3F*V$I,#GZ=A9/J4LYL#E_7OJ"SQC(M;>O7'H&N*T'_Y[P)G +MM;YC7^?)5AV7/TV:#)D[U&*">!)=58\$.@-7&V)5GT,C+*->+EG=H.QZS%,[ +M^S%UR-_9CP-H]6F-Z91^T/>8D\-.F<;LO]2HG5A!_M29FY.SM/^+KP*"R%BI +M?3?8#MV&)+56,Z30N"AQUCLV8>PX]B1>F*_DIVJ0 +M+6*6?.#HZ<)EI\]F17U>HB%'!>WT=!!4*SYV)D`6TQQ=P89>S$_8=R(K6-W< +MN45Z3SHP\ORC*R"`QE3R@?&C#3%Z`/-9A:U`45^_F@`6YF>`%AV4?J._WZT3 +M&N3CH9/CY%@4B6+H +M.#N@F19H+#]\R%M-S"E5A1CG_D\L.5>ZLV"ZWYWT3>SX1_3L03`),S,_N-\? +M;-+(KTNR@E:+%Q@6I=F7:-)`R_/N^OF&3.'R/M-+QZJC"=B46=&U^1C1V +M/@*Z[#WF!F1_/QPR\-L/UVJG<4R!#&@C;J;17F./_,!JE:7X;;%87X.[^C)U>W#'IX8+UBOC#^*?1K"YVB:#F3"S9F&L=&;-Y%E(/^"8#DFB1K\O+,MC_/5?B+(M;9]!JWW_7M!!OC^ +MP;RPX\MY:`5J#A<(1]"27@7YDBA]GYGI^\%:M;)-_:`"WCD/;8D.`V;4O47)#[5:+*OP/+W4)+OW5TK^6$IIRFPEM)G\5*/\_5DSSYX%C]H@.7SUPSH]0_5UNED7:DLA_:UX7<+Q5 +M>4-:W^$U7\U-V40WK8201MSHE]@-]"@A/!\[RB5Q39!2;]3@GQVVQ+N+E1 +M!H@!.Q(CE+3%@ZBY@"RZPR +M/`I'(W@:MO"&OV/J>SA8%W#IMT1F3_;]"0\$PZT^,?SO8Q?+Z!QMZXJT)7=9%U4LXMTK$6O@:.(KC1CM +M1V$67W28J80_;GPT11XB?L&^6Q'([>U/A=#%&3=LJQ34:\?Y:!`0>3Z3VAF4 +M0#;,M/#,5W\P2]YJ+^'$!QX?#J\=1.]S"0X*C^G=PAF5[EK9^G\:U;Z@]+0D +MQ&@N"TZT.A$=T&F+4(MO*>.5AX?!IO)N%1K4RK&D1X1>:79ELOHSIZ>LA&=4 +M+`\5"FA:SQ]XHQ^N8*BN^H6!3\-^4?A65%=?-B56L.E+Q.^7PK!7/7'&484E +MIB417<&.J:S\N56GV>0KH9-PM7"8:A7,BJ`M2^3D-_M+#!U#+9::<[:!V0G3 +M=*'#8H<0\%T"T\\"A7H=?UR&KVBH?4MDYA1HO955-F.,8?J5MD5O9^*X[N98 +MMTZDW`I8&QZ\X;M$/'L<=^@*\.MP]"R`>RPB*&R-OP5[66]'"8"LQ;'`WKI- +M/AMNJ1&V)-T.&`(L$?3M8NJ/E6Z"C.C0$M\L*4(7)YWRE'$-#??6S[B[?ZU* +M*!35>::K71?HWL%V:Z[XC=5:BK94FBQQI'+X,P^2ZND9HP*T*P[,',<2QMLR +MA>)DY@5;#W8'$!I:=9S&`D=79&?YGMZ]OW.##8&*'QL@<%J$HVX#T"4JTU*O +M:%YIW2&R_+&V^(\R:0_6GE.?:H/!!4S]T?B[C]W>!4%PKDHC+VV+^A#2`# +MFWXRLK+LT3.,#/ZN3='Q#@!P4!&>^"A]]A^Q,DOWB`D1]^;S:A(._P-9'MSP +MK&!1\:ZSO'?$R\RZJ!:9\L,-<8PX/$$)5!+M:GHTG_S82$M[]GKQC?I(!EJ4 +M[G7\JO"7M%#?-.:\/:\"'J"V8'9,?QEP9&=K4#S.XMZ:D'#CGN(&'CF5T`9$ +MLX35#&*G9-^@H#Z^4\G0B+$#[#D;/9:B*UCI*3%U!,4$>ZG\9?/0MR=QUXJH +MZ5T-^?+^=S]5#'#`2ISOQ)"RNB1S(C#=;T#30`E/+S=]+OW`.S$KVT\K41&Q +MTBQ.C$V>8*Z^#$DY%3YYI/S!D&?-JR"K74/CR2F([%OUAN=XVG\MV^@4@#`H +M&_A%&:V#F!<+5FW&'*[F-\/8+D(PG:XZ6!OW*C018I];-6>7ZU>JS0-(?ZK? +MHFF?/G,G]`RS4K=.Z@N:==NAO.5I3'+,J@FOL^OI,ER_!)L +M)EEJ[T>&,&W"GGB-$^YT_C>,6D+MRAJK9\Q=6B.M)EM?9&'8(W[&K'P=)O:P +M<@7,"T=CF-CLDFQ=>24;]NQF(0#H[3KH(D_HV2Z'#RH^W032@[\Z1F6[L\EH +MHPHEC@5#4?;1ODE-#Z/'0"BJ5>/AJM3*N+!(@3.2.:IP56-)&I&.1:4O5#@?G$\029$#$;0(Q^P.W7=!>QBA<@\H$FATV="SULC+^G]E$E-1B]91JC +M6]=HV5[A0EU8ELEYP2T.=<,:_=.@W_&62RU[U[\&]?E(A<'6!4`)IZ8"4H(K +M67LF,"2)UM!.4Y([$?G]7CQ)W4,1AY5B#N0&!?PP/QRP(B``05054GCZQO[H +M(40>51.&8^!Q@2RF/Y8!?`J/]A)^V*IS'-%,,%ZWLI2XZ\:"EZ>X9FN\:V\/ +M(3/(Q60:G!`K(C&!3XX"Z8ZFVM'X6&9)Y6_IP`&G-&W%/E@(:$F8M^GFWQ\* +M0I<,+2[CUAE=D47K1>$]%GK!L%JQ'\!=T*@2/&=15Y^(:W\V9M"/U@IKWQN3F3%;0T +M4OFDCG<.S'@"OVM\2[P3<3*:"X$4,5+(ZZ@7*"@;!-\#P]2I(0.ZF,)@W)KV +M2KUY4C*F!B"'4MRREF:S/-IK"J2ORE>5.1P>'H0'1F-]#WOD$?(W]AC<[A!-CX +M7`\=!$I=3H0C7!9$NI%!PRPU)&*SCH+Z'T@>I.L'P +MD[;3S*S49ZHCEQN@CV\WAF%UU&))&AFOFF,%C^7UT_(&[P#RCPW7\5)SNQ5R +M6"@&)%7P>>`*RH/D79/E*34GCO^@F#YALZ%5XI1MGMID#!\W?Y]>]I?TB@&Y +MH%YF5OD/5+PKC[^V%J>M5Y74D7#IY@1V[&-^[9#T8!AHK3%]YCO4==#"]IYJ+9]T7,Z-('\+X +MWPGL3,+7?=^N-K,50UZVP[90G7-)G>X0NUY#7CN)3[_& +MV(DS2QBG"!:;3X\\9C]:AZJ5>B=_7O%41-7K^2I'B((&%MS`)C"Z%XOV^,9Z +M4`\(088*Z%@][N6HPG?_LX`)J-'[67FP#>@?L`%#*E99QF>6\KTOL75N.>@T +MTUHD`3SDL'6=H9$C#GR0A+J7VQA?5'].X.N5D9^1G8"S!T#DA`M`&XWLD>79 +M2:3VKB39[]\GZQX;\69J"-XRD-.@+'6!(@D7\?5F>UQHDF*6M[T8BZKS=^B8(JJ!4PG%1% +M,\LQ@`-\W)NW8:[LQ_V"LF8O+8S\6:::)#LJ.NS#E[>`=-WK1144`#6+KN#2S7.=F((E$6L^9QM^GO.TW$>*@4?!0.&KD*B"Y&DN(T?(LL:[M;]]%6 +M5YP1#'O:E-OOBL6\8>;A/3<3CGD8!W_0C0VVN8]D'6I4&Y[\CIS+8CE@W*>) +M(\M(*A9=9'W!$/',:3)&OX9DF='Q.+#=WWS%>(O`&78#^B#K8`_GKR,R$5AO^F-==.2C3Z$:,&& +MQ,_GIQ$*>XO8>;A7Z-/HJ.*!^6V$[*O9!LWZVH(,OBZH#><.O?Z8KSR7.MH\ +M)O\(J%D)'*11*KVH:JZMM"YG]WLDKEXN5U1STGVMXZ__Z#/E+/K.%.J-C2W< +M;,U:X&P80GH1]]8?9\:EMWZ7+J=ZBY=U[N9`O$Q@EP4-&G[B`SPWM2A[)<7_YLDNMQ^'4SGOZ/FOAYS]U.IWN/X)N8^_!D% +M"I%-#@?9:F'7U8RNU8@+&!?$H,)Q"N\:Y%]GFX0I(Z<0R`!5^$6^#7 +M<59V#"'?.08?7(7!T\A_-U(IZ>K=-JW]M61!,A1!UQ;8(M+`@M3P59N5ZE:AQRBRK:O.BKY1#J3F&H8U(0D +M'NH?V?(A*C:3*GAOR*G;7@7*4*JCCVA:_/[#Z[+'>VK$M7A&V;W,A70B_^UJ +M`1#'?HPCCQ5X0K?V0F+FO;\G@N+%%BJP7IKTF_ZDP7GZ:ZB==R21C%XJ$14E +M[QUMIIK%Q?SC?:JE<2++I.=?ADR`?,&%R9M`1-BOE-W36+/.7N\094Z$206@ +M;403H"1UT329]XH//>ED#'2DW6<@R3;O#'NQTCQZ(THIS"6HQES\!4FW,=9&=PC+:M#N=1_5%&NZ1Z/H2`#931% +M@.EG$ERG_;+0CC<)"$5[`8ID-!-K/2,]3S5_:Y0Y,2,84BSB,[ELVCU*,_/Q1F#U-J$U4WB>W%Y1O)(E84JDIW,PS>`8 +M("JH;UC*`R<"2Z!RPRYJHBO"WP#EVJ^DY!JTBSA[LU0(C>FR"-FY%L,738?' +M5WWX;65P()F,K>N:&ADVICL&L$A&63UG"&JP>-!?CC]+J80,C#GP5OK>6.%6 +MW?+J7K>E_$Q8'`C%$E>)C]5KUK +M?R^5(U/?Y6I]O*>)YPV0E36'W`23HQ +MXDZW09\;(G,QW`]I`+T#6_!?*97X?@BKE#7R5-J)\'.I]F@SME*=FV[*CG/+ +M+?-/R91$51FA80Z2HUHE+D+C$X//2U=$`7RQW\.0+HR2[L.`0/T[U.29J]') +M_D.G[MDK.Q=:\7?#+S1V547?K(1E"&0E8^\ZH`'\?DX<['@N.ASVVPL[+#=' +MGZEM@"38N$!!2HL(C.C;KG49YQM92O,CV3,20(D[[0,["D97 +M.Q.-LES2W'])LJH&!R](167EF!'AZ/(7S3\;Y +M[1`QA*3'5(YK&3JO62_(<"KZ-\P(1.*\::Y7-/JXG/C@Y?]#N6D?HK!'7 +M3[5J2":%XO(=%5/H1@@U_6'J&()0I;:'7JGSU`@=A:W+K0@3CP#+$WAR<@SG +MRR/2]E=%NM]4F0CIYPT,7[Z\]O$D;,ZBH7Z-:'B +M(/YL"QFY_53=0>JM\;.??*7-S3QE9>OX/FNU +MY\*QG3+YWM<`9?3_W3[H\B>U.'G(A6G0UOU% +M"T1-3WYUN#;>,8U*]&4ARA;^ +M@H_P?!0RXMJPLZ'`UMEDK,F\KB?(@[]*,$WL5A228S=9/:%S8G?Q.<2!O3,A;L*3FKVGZQ$J-"YLPX$M2# +MD'FD:OR1,9PT,0VT*ZGB>"0^TS8VH.^8*J!D__?6*3$?))$&!($UK!0R\6#I +M9U\V:9UIIV.R$4XV3S'/9&?C;9>2BOOL9,H>,QVTA:/P<(=NW[*]DC)F\,<+ +M8C8ZI@GTB^RW:LZV"[-=].\@":5A22`9?QQ/:*=$R!.:.+?V[V><`LI&TV;. +MS\_S(NY)2A1>6A(G'H1*#N#&(MUHXQU9SP/<^=0,^F))O[]-\\5?'PGUXC85 +M4QW@GZH;V'V"P)C%'L;D-5$I)%&;TZ[7B)(P[>'Q=6&%N3R`Q#_8_/;X;$4N +MFV#C(X'>X*@6->&F8C9]>NU&MD3O_3]_STU+BKE&^K^H:U=,M^Q.AYOV6FAI +ME^YE^%&'O%TTQ=A\J0I=6MS.S\0:4CT33;>PR]J]H,7/Z&T-1Z.2'XQ^DYEG +M-\YH]K*@C"8+GB+;Y(0T(EO%_7'L8EE&S-PZ&51TBG$CV?9J%+!5OW+[!?;K +M.&?'!IW_]E8#``;Y<0G#XEN$M:E]&45OJG-312&*HQQ(+A`L&,B%8Z5#3F.W +M"F].),.]&V`2*@$C7`C!HSTCRGY\'O]U9^VC'<%2QE+G$N^#%E7PU6ZF/75E +M7*GZN-1M;$4BI\DQF+2$ZU5D!U5GY#M1K]Y:+NA06XS*EFH`*E.DK&`Z[;9& +M@)J7?GOON*'HP_(6SBU68!AR3''=&X:A59GM1X7Y]_078.`@>')CYZ]XX,NM +M=-C)XGT+0T;B2A=D5O2[^Z'B2-G'-*I8:0SU#RNP][Z"+@K<":]]F>3V0W!` +M%="78,H?G9X239#3>?LL958GM*!.D)]K)HLH6[N/BQ%D^+:7#%:_SWPZ7P,C +MKY=HO<3M;T("@\/"X8X[+Z.*B;3ROIDEKEWN:)<$AS@K['H+D5TIM*$P$3', +M$CVM-15M*:K<^)X<4.7P4ZA#`"CT#,!61X?R#^#V2B' +MQKO"%TOI]T)#91RS,LN1]976!1W[J+3340:HP-GQJH!A7+UVX4K1FF2@IJ14 +M^2C8\5M:Z..UWX].YW>+DL97.HM#[PHWCE5O/1[SJ>9[6G_4&>J +MCB,\]T0_PL'F/A=A_"XC\5/]2I0`X.E#0&S[N;%P,1X+/]`2^?6*OZ6X:!Q( +MM'(8G-GL+_Y05KEXXD:37%C_B+`,N`>M._V!$8P#T_"L:LS^9*L&OC%GCWXN +MRR36:$H%/S40%KS1\LE'[H1F@E/&MZO$WJ!*FY?CBBB=8B*9249TP%8FI4:X +M[`)"L$0!4M4A$\=SO%QIZ47SB5PZ[4]JNK6$]YV`3-NJ<[HJH6YM@H*1JV+5[?BR")@V$8_*HZ$[M1(\R+]NK=*')B&4NK8RR%PSEPN@?K?[M'S-R] +MR?V,8ZP[UB6"!D&G-'GI4G^7\>#+R@V$N<#0PD/\^,0:>)T/YKPF +M"[D/@E[;?--E+0.FHK=,B9`SJP$O70&D1_)%:$F4$X^Z_1^,2%K3/M1.?^P\ +MO32-;PH77*$3F%7$G"9&&%+->@4UR)Q\4[8PH2Z&&G89]<`']DT&XA_I0 +M[!/%5H`COWMH;=8?/*OPENOQDOW['"T3UW9,-!M5)@!%4ZH#!`)"^X]9Z!,$ +MP4FT.N;+_ZU!3Q<]9]X<\@B(3O19C"=0\\):U-_#Y6/@GAV3!)$D +ML8FB@:WY/ET+/-&=7QJ6^*7H\[=2#EXW_O")9S^1!^"UNV'.) +M2F<-(H)4@M;)@NGYP?&1RR:MVH;[3`.;P_!!N_$^4RD'.-[5KEQV2"++U%:[ +MM^)+M>76.+&0=>4K:I*+1OK/1H2NZ<0;YEADH>]Q#KPD_6KM2]_J>$2R00(> +M,X2G9MN3T]7A4E35UK26?VL9L8(WR<0 +MNR32\1QX6!U(;L+\:.&(I@/=*H;OZV15H<\_6483MSQ6]A^]D>OYDMXBM0Y= +M,!:F+A9;GD2#G$PY2QH?,B)H"OF;D3=0ELZ8\;@+B-!L0>^`T97!/6YTLG"8 +M^(0E-/&"$\7BCX,SX-%_NCXE%Q8,$A(Z@TQNH-HIL(I$MUD.%G6)JLB&TY\^ +M@6JN`I9Q$R6Q/@JVA&F&F2=08#I:8U=-+$MU[.Z)>@#RA2\Y/ZGT,\4DD-63 +M?1S)3IFL3Y"-X_G(MNO;*5DQ@:R49 +M_-O\D:*)O$S?98'OC##5W.XT4K:A&1@E^,JXNVZTYKHSN2`DN'U)E$-F@T=& +M471+J#E@5!04`$9G):8'SSP:,(L:+XNS?S`TS!B+WR3YY8RXLMF=RW)^,;F! +M%)L4L%BS8,]TX#],=V.\ZBFYFQ.0$RBYO4>&Q]WV`MHE59],3TUT=[T +MM^9OD)D5/)^E5HC_S9CNR"N9X*T=LR/PK][?NI#(V:WF>QBU570<-L2[/U#9 +M;2_,N]Y7=J-O[6D2@O@J[O#YE8Q_0_,>H8@[>S=NO_=89 +MQ:.NZ6[A@=8C5N3["`!AX+F.8]H,-IL\6W#RVFZ89/T69P1KU<]^YXIIM6E? +M?>4R2K+"QCFMN7VH).ON@=9Z=O<.T^U1PZU#;7OR72MA;L6-8(UW/62IU-:. +MD&LHFYF2QN?H%E*SD_VHR^KE`=]K^ABCBPU@8"2;VMN_RD%B$#G^H:8:U\ +M`2#6PBII/JZ`]S2"GFJ=`T`R&T*^W]..$@[D,OA!\T9Q&FE^5OYD/6A<%?L: +M3$>YT^YRO+2%UNFK?J*GB1UV +M(#WXLDP3U30E3W88`.!(+>,2[!/2L"!4NA"=E5K]Y#X^J +M>!FBBFHO\WQ@*1#H\_/^'U5NM"'F8D7>=EI=N$8ORN?UR +M)`S3/G()1G>8Y%0!H^P"N=E-X@N6G*1]=FE.O;,[W5F<7O-"55ACXK52FJ3I +MR@?B72`BT*UV$E:2#7F(\O"/`6[Y;//2U;!A%KP@[?:^4'/7@/&T2$2Y=%DR +M?K*V%5=:K:QD!5V?!'L+#Q[>=!^3)O9O0"W/D3`^3_<6;]>AMI2HWU[I,4@#WU!!OUZ;UH7M-(N*1$E[]%A=3TIB#[7#*I])[+'AK/W=Q!IL!EZ7U]2.2VZ +MTX$_``R:?",L']:N%I$,?XP.AH*IJ8VY4>TF,QR=35T+79N#A%6C6?.CNTSB +MU'OF.T'SFK-@Y+@P1T&Q\(-X$-!D\#%Z+P)F.'S:>>=.8Q,_8GXV%Y],:*2G +M@`9I1L)6?>7..$XEY>75M%M.L4-/CZL4R_7$,XRLT[A&A;),5G.9>_"M2&A0 +MD)L?`$50R4Z76A]Y/?59YJ4@V=X`)P#P21T^$YMVLFK_][0T"]YR+_C[ +M3:R9:U%3F@(GYQ[!>&^+ND1/(^8>K,B*9D=L#E('?E%J(RO!% +M%&/T<2/EL4=R'H+>C26#(821+8U%A2U#-VD^*R1!K;-35-C4MZMGO/2G+V=P +MZHAZWC[Y3!)@]12^FJIVP^0:A/;_`/=7U4GYOA$&!YQ)*EBC>LA0X+VXCM+?$W)\N)E*]8G-TGC4:%\7=/`$4[(F=0 +M6P-,"H\9#XL^6';TI_,;+$HJHD-H7^T[*V8%C9`79/GN!K@.+W2"]HPY^XV' +M?2#W3])(6LO;'7=^8AUJ==LEPYV)U?,V/Y(&^^\KR]7-8=_GI)7^HT!\M#$M +MI`9^@OZOBHQ]=EE0+FK#-"=C771_<"#MN`2+Q["WZB+Q:DQ^TX]P\..>%6-` +M52/*$$$F_`/S/MEYB/CG9JL+2O6#9#TLQ"[R>+_8"`^KY%(H(R/"2'U/:S1H +M![DS`K'EVNX(K\6M29!(I/EFTB"J5Z^X0ES>1M!>K:B/(X=$)X.:N9MX +MB9M*L0YS%'%NXQ:*#AXWEJ4A#D&9D(/S,??F)&CQJR5Z5,BLY^IQWH3-(!'_\DB/W54`#1"_Z,2ATKTU_&*KR*:<.,X>GYKS +MBD(4_J.92U".P,[N"QQ5@D242?DHD+C6R"8W:9F=JM!)3B>[$<`=N31+"W5. +MOMR9FB1)[/*(4$NX63T+RGQRJ_UJ[[8KY(<03@EAT`ZM!T48Y^P_4(,U.P$; +M)RSA7>C42*%@M>]DZ@^SXF6OLB.YU=E]R`ULWIMW:4,KZ0`_Z)^:_R'%SFC) +M#Q.RIL[6F?MS?"YFY;,@99T:F:.1]_X8#]&G3!#Q9_"A8M#!XJ3S#3<-^?_M +M&E>V-04RKF"?<6%$49DV1\?"SS"FB8X848%9)K>:4OJ$ZYO]?#:F4==>")%N +M^06U@SNO))SW[4*I(+_1VW +M3LY8N@BTJ3_]S@RH'?.6@GAE)W$3G`?2CP!"4E3[:2LR8>,RQA;KYAI*_7N1 +MO7JX2#1B366C7#(TUWM/ZP@F\"3\)J^.1,&T"\/87;^^FT1>U)IXM5Q1_D@. +M-#"T'HK#^VZ':-K58G5C<9$Z28>%]C"H3F]+YC@\EUZ;*8HB_'@4>O->'LVX +MGZORWVBKJS8G`0]&R]OF5[X8B^6J^[U$-E;4]P]"9@IT[]7I0V$34D1-RWG` +M'<\61[.35K?]]]'$OXOC +M^*[7L$<]&I42EE7`C[^"(A4+ZDKKT<'CIGIL>#%TP.0D3;QP#+=I@3ZVVP:R +MZ_YS9B-RN6]V:9*9[3.M9`5:+V-5-(>,87Q['7\]1";]PA5UB:S\*DMK;*`?8/M)51&\CAT'6#ZV#F=KI/_)(WG[ +M'*90XCQ^E[-@->E2\S3M,#C3:4!W_7.Z]'B#$.51`2RK##^"8K3`_^07&MUC +MI!T@T;?]O$2*]FRN3/)2MVZT1*//_"],^$0S*.O^IU_[=['.UH#)'!Q?P"2@ +MRW`.-3[W/O`$I>02A*WZ*G_>B#0*'YRV>8A-W6?4DCRG&MYPO_HZ[1VKEVP% +M;*@&E*_>5M`YHH,0]93`>A/%7G+D.K1D[]^(SSB`[P>*$);_NUK]O`_#K#K) +M\5N&@7K#)R_PO+(=SJ$(N'E##98N<@/1_&1P,>J?TU.4;M +M$0WH5ZBQ6AZMG*#&>H%U6@H2RU/^3MZ2.)GY/EQRFU+*M)-MOZX8&$W3=;3V +MA$C[!\GHKWAWI:Y/@RE#<30+M)STQGO%:T;#3KRF/.U_!;34T>DPRI*U\2Q: +M5>G/"(0:S7VR;/?LROHW&#KT/(4#^X^`'/=YY$.2B8MY'&("$Q]L4[IQ^XR$ +M8=B[;B;FR5Q1O;J>7KB21)M+$27UW2=XR$6"5CS5G`]:3L,+-VD.B9N98%H% +M>?F(T=KCXVM!%93]FT;RBWITF?:O-I+47QI;:&U& +M=V9R"8]E,B?*IN1)-")*0.2^1;WAMF7G?&:9R]O[N)CTK.#,]]4(UT\R2\HX3S"',^K\2MI1AW\"=>9@71JF +MFFC`@DXBL>`WS*PP:9[`3&4NBQ':++5O^J8\S;4FPQH5,>_T"0+U.SP*#%2M +MA)D@<'&[C.APN\F"V2I21WMPBF9.GIE\>'K;^`$4"GO%89&J)[YECDFI76!0 +M7F^!J)OQIE;)ADB=G?S`'7KG?JTO2+AW7>.^140RIA'?<8@3XC&?!KP\?T-# +M%Y;:[SN$--W[55CJ>X])Q3.^M2QTHVP#PU-P;C.62XF4$>9K'Z5<):(,MG0[ +MB"^8\,*/)<[GK$TC1-4&7==O2SAY1Z`C:N!B:R%'?0:Z!$3D7^?264#G)4#J +M4AWE)3/<&*K>0JDH!)=&#?CN#--QU]$B`JJ;+G7LJQO1,![ZOH@]H7J(X)][ +M.&_=*`V+D<_N'LJ +MO!@_:I.@"A=;[/\_L&<_.R`-EI((6UDKF:%8Q9C!?G93/TX(\,'`9T6Z9&[QJW,\Y*>EK +M^O'8&-Q7L"N0!4^YOVT61>1WN=D$<,S7&XL9!LN_UC\==+[3I^W1K,9H9(R]?H\89PHTS' +M6!J)-[1RUJ*)96A:['8\-3(DZM[!Y2B&I8VN/Z.%SJYH3O&6HK)?.OU+8][, +MQ_=;O2YHS:@=G:22)/*"^:&716Y+/1VU<@#-KX(J^A"Q?Q5[S3AQ0&50 +M4CC34R\O3`J1R!GK4E81RETZ8V<[C0= +MSW1:M[(AE%RBXY827KK:>C8^@X(;%O!O?LZI)29NP^S/BK\65*F,8.;>X38) +M@G?6T6:M$U>Q0;[MC5.(W]\`IE3!.=&D!SF129!'8&DK,J1IBG("0GVP-M2F +M_P4N90U#MH3PVG9%6>XWWDPEQYKI*#9()6U&B'HMO(Q5)M\./05< +M#[!U?ES-EN^L2S:+])/]6R`?^';&]LLAGAD'%% +M,MAP-BZ31&_Q)(3*A98^)O&6GJFF`AO9,9X\3;H'^?Y*.F6C:JM#[5>,B`]9 +MWR5.'5A8UV"C.G0F`C`J'ITDM_,LW`-`G=%74<.2N%-H!D2-.(TKW+YC>\H? +ME&I+R2#_K#Z4$I\C02JC_S+D\&3:2(3#$F]XKN;>$[&TM7HXZM+8P-3P+G_? +M0Y7\A>0^\V,]-0BT'-M1U.PD*&)FBH%?DMB6_%-8/:\;L."9`F#&*GPT^RB< +M_#BL/RT2\R*:!X/?",P*V<%`9];A:T<2Y\E%]S@`H>!Y;,_]?B<2`X?,_G;[ +M`/F30OOCH1W/)F#4U`TP%+E/(:!0@ +M0517)K-O`4T&UK=U_G!31JGAJ76H%3?<$-\ITG>V:-%6\^H-HQU@@X#R>J$O^9:&71=(N7A#/RK#T$EMA:^Z +M:Q6)-Y=?FO`F.A09!&DHM;,(DW`2]GIF\>1(<%[_U<7R=AX+K6"TZ +MLZ^C',#ME./$LZ8:S>(&WK%60=I%)3=#[KS1ONN'1>IL+FR1ZGX0(S0X/.8* +M:1S^[9>]Z&6@?Z:7FFH<]'AGHHTO]5T=Q%F`"OC9*A]+-F_G@:5`K?JV +M^*INTGSW-FO]+0;%7T7FI3;.E*/"'?W^RANO?\`Y"%P<>E1Y/0&8'[F9<&S, +MEN_?[KUM$'B3D)BBRX`J:;H,3U'.D\-BJ<[3%Z.Z>VEJI`B!;:8)*B%6/$R0$]'K^X@L_#=,__6%F5CNIQ7+L3U\-JTZ?W_5]1T=8Y.2#M9*2Y-"?&($?N-0>M4IK'PS:;51 +MG=6`F3XM14?FFE!5M`;7SJ5=L&`Y8@WL,,-U>]+D5N%L\WHHGJ+2`_;)S,4' +M0=WG.8TOZ"T)5VSH)XU>*"_R'GA;2I2X*V?A70G0C%JG9^/<3O_+\8A[#J_" +MJ]M4ZP$0$V&]8<)3R_CSHMG\%?:OHK0,%Q.52)*L+Y/P"L-U&U2A6`+J)0A:/4T;X,R;AZ_6/?`\RKL%VOU,J%XT].(?D> +MW9V2(O7SL[0T*_''1W0H4-+?;_4WKPZ*;2I]21*41,9,`EF7N),K,V?4T9E_ +M4%PF-_F66D7I--#5D)O5P=P<[F*2J,K"OHS_\4B&QB9S.-M%)MC(NP2X1RWBK[H+H@ +M_=^)U5C"OA(3.*$U*7<2U*XR/^,/"K^LAM\+F[6VK<1Q[W`.5:__AXQ\X&^C +ME8>K"T-^EPQ>EW@%AIS#!FQ*>H$H0W\I=Z#WY:2&^R+AE*\+K`;]&-G@(,K# +MB073*N=0/:%'4]3BL(-G*IY:L/6W^B(]F:)RICA&BZB.!#\YY6,KO5N?/XJR +MJ2PDEB158\@3P^Y`M&)%1=N>L*,R1PY%5B3.+X)N'+Z0$U`QA&)R[]R0#YYLXF%5C_CNGF!Q'3>5)/#HS&EC6@JH?0FE5P/7]O`>CL7Z[ +MYP<_'D2+ZH0C077&TV4/K".CZ#G!P2S[5U_Q@\Y:R3$^CI?R&(!N/9Y62+"R +M,K*Q]DK`3<`5LXB<4+JE,$E#I["E.FK5.B+T)++="5\$H1"*`PNL`G>_?M`+ +M`#+B)`+AAZ$M,@66Z'RM'I);?0>$4G)7#3OGU`6L=3;<26:"\B%:"B583:Z@ +M#[L=@7OKQ-9H0/6V-A+?0_ON<,G2^LX)U& +M$&7D7K+2:9AIXG%"!=[_RQ:7OD#K*Y44RC<01#[]P>4INWN3OCHN9+-"ZI!5 +M)9!6%]D()H'6>'TGP/#J'K9COIU!"[.>5A-$29H,Z"]&1>GEOA4TLQQ,%,7D +MET(@$]E?8*0NJN`'<1QJ'XM1OJ=3/R?(\AA!B*F*2<.PU,_MIF65MXY9!'7M +M7RDOP);_F49LC56[8"UL9^>9%UO45R1^75K=6S25O?&E,MM@MV$4R7M$X^H[ +M3SH`D[:H>\)[QO^1_I1M@A@1&K[#H&H`VY`/ +M)O\PXWGFMK4ZM@/YL#>;]?AF$+HCYJF+OC)AH@(C]R?4`<_!/9XAH`^7, +M&36%7?RT%X([<9ER_H[_QWJ\81\VFK@GJY&#K:Q7*?BRG)B4['=+3E[D<;-;O_@W$&%8#(KVNWSJMA>&(;P!2XDFY/0Y +M:QWNX*$[#3R)W<(ZPFEH9)NT]98(-Z-C33][J'K63!OZKY&"@D36>I3T9/UZ +M>'3[!GAI?AI2_0#3T@3*L1`3E&H3Q:#3O=:.)Q:H8)TP/8AC$\7[>$ +M=`65&XD`!3J0Y(&.[IF)3ZU;Y2+C+@/@H&O)YAQ +M5HY3HFHN'>Y.IG99MPG+.9-M-V&''YA!]S67HO/QHN15F<.@\PF2^K\@'W3N +MR!31K1*I(_,U&N@]C)8;$B^M6U[9H(94SQ$::$-,O.(?H,_@"[W^DJ#F$,DU +M/>F*ZYA&L6WI8`K?@V2J3&KL+!YRP5A=:E'@*I.S=T:G4DSL5\;>QRT&G@J4 +MC9JCA(EP[7]>=]U_25O.D2@T[Q$4U#`R7 +M=66C[!HFX/+-&=W?0"I#T/EAGW/-SU@CX3FATR1R6%?$P>Y+V.O=`C(R!WEQ +M_X12[=4*Q"0*7K(A4;B>5:*)G%-[KNV&GM"\24QE[]BY4G3I +MH_^C;CF>_R";HW)_H;D` +M0F./0"GY>=#0HX.9R7188S6T876@/;[DT['<9[NETH)*&NE=\U49?7NBD$[& +M#Y$+@O497*I[[(T^ISO0`B9@:,OV4("CZ[2Z24WB'.;GXKZBDF<[/T;)>A27 +M,-#951[-5-NE[O0S3IK+H]&K!]$N'AN'-@Y8R2:R`9XU+A$H"(.W:SYF5DS1 +M:K@L(<3*=#$#L@VV%%F\HM*(CH=28A&^H`@0-]EZ<#'S/O"S^IQK\S+$"[X! +M--YJ;KRS4C;,06:))-7/33?_,5$FZ.?OE&BH@B@G.%\.)V +MELVT9%`?+!OQ!PT3R4P:!,P=R::!Y1I3&J7>V#F#XHHM6+I86U'45:D<`YU& +MV'7OY?6L6&9)[1)<6TZ?T1IF!X!^P@K0,;&M?Y$NP\YG/M@#(I&='VT^L#GR +M?)DNO&KL.:)T&#:&MHJD#2R4D:FTP>EW'9(7SPJ9\+X%56K!1H%%A]V[/AEG +M2U=F5#IMQE(2**GQ.3Q+\,"U*Z]<+1(EUKOXZNP1)B7_;6V^]\*@NXA1OW<% +M5*F=G-B:@B)^Y24$\7RI8*5\&'HG+`%"SO#B\HY]RP[CL2'#\H4 +M_?&U%!1YNIZ^ZHWKP]H"+65.>AAC3917KK=8?1YBS'G\&>JW>/YWQ>ZU1PR, +MT\/]2/#$D]QUX"1]\NAKV9IU/-6@^-X%4O!]Z=C]J@HQEI0*L:4N\^==TZC*F[5-K^- +M01F(8G?`5EK$[HN8<%'G!7-#6T"S_;]%-T-%BE%(.V-BX"C>K)1V=;=R:4;) +M!7R6=54[7V[$;KHVLFETL%8:KR`%O9<(:EYBX0JY<7R^,-TZ-QP.O^_\^^F3 +M/,9,HG$B+QYLO2XUFBFFKI56W=2,'!=[LE`GN(,JZ>+A!+8+%SZLN4.0!@_V +M1&[,Z/4FB5S?I0'O3I)D(GNE"+!;T0?7XSA]W*S&L8P&,#\$9TM%;[\CO:QB +M5:0J1:#K&;?+^[01VF[K]"TT0H%0OIV;NYO,QZTQN)O;^B_WJYV#C1N:3*U; +MM><(T^G1Z:#.Q`V:'\QK +MO-:>FV?G +MBT&<6>6QQ@E;-X-B[WVIJBLF_C:&Z)PFC'I=>N[NRTM8VVD-FP9'_5ZH3,*% +MZC58A&FS])K>DMS@HX_=D599?>6[_V@,?BSC'\OSTNB]I\L,GM6.L!\`;`VD +MX]-O6'I'F')AA34D3@5_OIJ,"1-&_E3!(]RZ;D52YWTM)Q!;\Z3@W#CR6@+? +MQJJN_##P[JG(`%]\Q>HGD2:#L%UQ._]7C+IQKD=+"3ER`!=G_=A#3P_AY]GU +M@!^(OW"0#S/KVHE!)-7)=_>$85DC)/99C^EYCLS^06+S[W-7P+TDT(E!\6]* +MK#N.\KD>/H5M>FD3=LH;=O:.EGOP,VC?TS-%KZL;Z&XI5P@5Y',-%D +M2!N;ADM9[7Y8FW9!7,-F[O!#DVWRM]572)M*/?_:OCMQQC#+F\8>4N,%3P\N +M-Z$\V.9D&Z6;T7.S@/%WVI6%[Z&LXS+PB'<;">GIVRHD_2OW@/GE^7J&!*@L +MPF7%;PKUH'JUM`(',6756<#SEHA<4EK)_.#6 +M[7HBM!.<6"&((7(]IV;04K(NGU\'B1M;3LMBPMBI;69^E5>IC)-300/WL8-_ +M4![AKYL<(8+:92[*G2R@0$5B"K%XMM.+4:6M,0.U=9!=AF'](#NU-)J&=JO.P0O+6X3 +MQ`FGS@5L6_>C(O&%80:9QO9\^K/;*WKH3 +M24`SVA3O>9B,^"7S?OK&:#NR8=T2(S$`\-^"FG$U;?UB$*=<\=%0R'2LYO#Z +M3"\)B4"%_1DPNZB\,CP7=YN=/)?Q5*4KD>@>^)W&+"A?M6K+U^_KPD',5V.# +MY2<^"!8,RBG3%G'Y9:1,5/45*ZV44FZ(/.9U$M.,PA%#(L<1P +M`8WO-*&]Z.6T%3"CW;7!;60C+[5).1*&:2PX\T!R@%'UE=+=@):XO8M[8EFP +M0,\EVRIO23S)]DL>SZ/=D>-SAK(UJI/V'$9`FU/5'-/R'__XG2'W[D^"AIRA +MKM`")D4V/?J!:-[K?8X6G.G)*?H`""YF*E)*F<5:^H6"HQ_.N''O3SR;EUBM +MCJ7P`=[DGW*IQWW.!*X8:D4DAE!2HAU: +M$,J)GY2)*]M+7\2E,.&_ASO!?,2+/)3W6%#=_[\34;H?6T*N2L#)0@_:#H+1 +M`]`N:.(,OR-_O&6*^P\"YR?TO*B&;]=+O^EA\-VV(88RJ +MY[.N?A=UFFH6/<0H\UC7L6EZ^TCB494.U2SKR+-/8=#X:YO%0$'G:@8SY%PQ +MK4'LX;&K(8P!%J>/3F=C3S,T2GC',4.9%:*UW8VB-S)76(V43CQN/.0RJE9G +MCB&4Q<.,V?VXBFX%4OB:TD(IY[WNF=8-+&:@/GZ7]^5AAGLF8=/#4YP%VSF^ +M>8X!LZ%FZ+#A(ZIK,( +M),:$GQI_GCG?9/;UH+@E3P@02$6BSLPG!\0?>]Q6\&\9Q%Z?3,^KY5F/9X5D%7T%H^T='X"I%TH8'(3C_DZ^ +M6BO6;9C'9R6;#'\71;2A4-]DG2X=]0]]@ZAC%>".S\T5??X$4=26AL[KZ^<] +MO*8CA&JHO7:N#9M*+(J4TI)+SZ-^QY&7@BX]JZ%]6MN!6JV]MKE_2_;=ZZR7 +M71=Q9^_&E'U0V"64,IFKL)P[,-GANV%3;P+256P1QISV0[#Z'7SEZ`3M@X@I +M*&C&/0$-I&P/OO(D7VY*%V!^]B28;BZ606I:WJJ@M8^3TA@)HN,[`OBPBPEF +ML@J>G?W[B4Z2>G[JB(4O#G@[ZA!%O@#$$W4_22-?2&"6!'.#:%_P)1E2-#V$ +M#L^.2?R)1Y&\ADKOYM1<-I;&19A"2^JR9:AJRO@_DK*19D6M,G@Q9H2V`=LV +MFOM':G1P29W%LM=MG`T*J'0;GNUY],!,^[_GV"\3:IR8R7B+;MGN^RQALQF5 +M>9B\)^T+N7OIBG9%WC[OCVDF8J>^>8(8F:,ER+]'SRM?"%*[8HDV\.4DH<4B +MP"[A1\L210B-+O34.;;SR?[^^( +M$+="K;?$$JKL8EU5EJZ*:YT1&,LW%L.EL'CD`[HRLS/3A54%\.]6HTCEV;(7 +M/`K_QG`:/:PC)X"_=T +M#>`[`%.5E2<"8C4AO4]G=GO=%=&T,:?D5V"RL.G0T?8,/8.7MS!M+4C^/0W/ +MFY[C>[:I4:+`2IOE\J?R?IB/F'\S7`+DQ]N]D-Q:\^'L6-+/@)I#S\GL$:XQ +M,1W]F#2X*%>$)`R:GK_,$-9;V`IPUOZM#)^"VKU!1^0[+X3;,`R+?K(2.\PV +M&-`L#TX(*#@S*$7:4_!8[ZMRM9*"\:Q;#>-:N3BT[->9]]^@$3\[?W9E(1K" +MH35HP--(9,R)9T/&T$YE^)H*-%>3;9NMFP)0Q`2'ZUE;/XMY2F++;Y<1\9JY +M7Y-;,<#]?NK#[0),-X;"/Y#!2:2L]8-ZNK:%K1A;5A?/S663BP;D!^YSVWQ5 +M?D6*RC02QDH=!X?*(/P4@B9;G)@V6D-AA;>,2U=K9/*QQ:F;OA%C5Q= +MU>,I)$V&(W<"@)F4U!->1%P4<05/GG.QM>'K;OU@&W`4',IAJCJ["UE1)JBG +M0Z#+4J`@+L]S@8+WJG]!8PT(&L1>&3I4M`5;3*ZUG=TY\R19K<]MM,Y"7]"R +MXM.VFO&I>G)!2?:6LG.C"\WXET25Y[;F&0OHC+&`VM`=:%"BW+1QI=.GDKM0 +MT1WC)H/=6BPHJ2CFS3LF8@\O1PTI[30LYXQ+UO^Y/54).7T;2`U\:W06$';B +MV"0KGXP2T"KYA +M\4C/'C19(PB!)7-H_&2`MH851Q\=%Y=E6]'T!=@?N#=A;=[O50!_RY[ +MO=R56NOY%O65<)1+)J6),8C52K57G!<#HM:^Z">9[3,N,C#/]W0"/7V+/SBE +M>KGREAS![A6M!(::#Y]]%=%:L<[7CM8[:+M^JCOIK]:EL#4>*+9F4-BL/!0` +M$<%OI:O.G+N)T(;AU(\@90IM(F`654!JM;U)_-T\6Y.MS$=YD15T-YI-8$-R +MS]H0G='.H[O$\RJX_13M:=/SXFM"&K5`W<5,?-L_LEU.MM+]L9M??F16*-MH +M;@G@-]T5CWC-#^F'`0&PN%[H.O/DHWD_7*H,MPZ_'"5(]C;HKF"5F<@PYVW+ +MTN6A1,Z.()AO.8O$F`Q>[[FG8@AK]D/#/>%J\W-8^YB?`DY2!#OTTM"OH+N/ +M*1$_&2J!80MXFL?;.Y94@*8\*O4]4`PK97@/+X]I?JTX\^$^KZ=Z>.:/&,73 +M2TUH;1E'N[=S73MBF+.1M'=5`T^S2)%L,_#7^X/L&PGL83^,IIKSBN3`Z1AW +M@\@=WY``6#80@-:JT^/VJZZ#VU[?<\+ZY3K<^75.L-&!P2AUB'G()K""?!V? +M(SDUTT@L#S*N?)65JJ>2H^C&NR'&&U)6/-;0Y=UF#'V/Y@3KP?H6K4`(G-FOH,A"?Z?'G(Y'LF4]-/=Z&#PD5R/,-L41/ +MA;4QQ07>8I4_H(M:@E,3 +M*CG]R3FYASF\$^[LIV-[I7YUE8$!QHPY5&Q<"3'D_T+UCAM>97,$=)?]=0N) +M'AZ*G9";7Z;ZRJU,DC"YAXKFOE)!88$FZA4W,G,V"_FH[U7PPX"M!SWBCVU1M+33DF4^G]X\B, +M'M(S[>FFB@HA2!>(O5P=2C]6I)FMKNKX;R)AKU$("46DT_OZ>.1NS2K[43_; +M@F?7'4#IP2[^6R`LO9=67ZNE>@QYC^U@WVHS$1HSQ`9:%T?(O169I`?;OVE# +MLIZN00@/]^C9=XB:0.:W2BL-=F+5:L&W7SD\#9#=W,*6+X5*+O6,OS\&"HL[ +MZU'$\54``>Z]&U^M`:QY_TW= +MQ.=7A[1>-/ZF@R(+71!O*]/S];+!L_LMYPJX`B2+8!SNB71K24X+8/U&ME;T +M)8K]$LB?M#$/Z_V^_RB\X;9$]OB=SHEI*]6`944(*D\F@[[=A$=A7"(=4ZM'9*B-9"6*QU9+IR#0D6)?KU-(6F'9EY#4:)X]P*- +M!Q#PLK&LX,*B2D1D(+H13>WG:0EYEBP;\,[,,#$^8?`X)D/IAD>O[V_!Q\3& +M93>`$]P9F9Y&AR:.KXA'AZ$=(,I?[69'TY`XV_[J=&3AJ>V#]T6U(@Y@3P8] +MN^W\;)*[=[OFH.G\]W` +MZV#`$7[EZ;7)HN*F)6NZ1(SC'HT=&&*Q=5R"9O:TP@9EXHL6.>*P#ZG>DVR< +M,\2^.=O^:F2Y1Q*2K\VSRS17R;31X>-XI#D0`%=H/S[BH]<$!F/_/P=YH!?, +M$M::^@7=)Z0P<-FDWI]L(E(UHJL)F*I_ZL@?1U;Q[K9C?]PDI!*W,3K`PM)Q +M5CF/)E0K3+KU':54,B=UU#CU;/5G7';GGOVL\RNO_WCR^%RV0&O14B$RI1/+H@@@:0"N;WX&R:)T0(-;<_#LAW`;DM-,%3,T0O3XM*RF_ +M5;YE`5S-*-6[1\HPEL/MQNM'B8SF4XU$ZL['(J3!V<50!N/.$TLJWTN\3T91 +M_'PM5KZZ`CO\7#PDLR"A'$64X^ZSU3-!"^2CI'`-(@P!Y:0^1!RJ/Q0PJ6-< +M,V6?UXBBU1=R_@SJF@0*%Y&IS=V_\/O(.]EDN=PP<.JK6+*,4&9ERCW$ +ML/FT[^Y6SX`!*,CNZ:W:!!U7]L%FA1^4]"LV*ZZLV_B'_B\7(='WGJ(TR6Q. +MK18[?]`EAC^%D>@^.T9-WXJAVJ*/J,;X(7B'8+Z.#08S&QJYNJ1,$2P]AFLI +M,%F0#6((2$GVU0K1N)V=PS"\J@0"ORY^9,UF@C"7);:2HZG&3GQ^5E0T@S54 +M)W+JN9"^`#7%%F?.UC;$]1 +M)>-3$M<+-WN7:I(\,7%4H^#B7ZG"OD6F7YB[]@3B?,MQH-4'M'YIS[W(<$*B +MS"8E'(29.=SZY;X4`9`P'`X;-R:M+LD=,J2Y$-AO6CL&WEH31&\GLVY;?0O6 +M?"U"^BPAT4F)5^3255@TN?#`R?]WBT29'_VFN4QK[-,.IQCT^@&$'K7N+H3^ +M4AE:],<339^5"X*6-B)?/J&VJ@`BZ$)LI:(S8I\]@15-"M\`36?:2<$=R"`'&8O=&=2F84!#$DE_G +MQKTJ@XD7D)JN3"X2)ROW];HSPI#E!4$P0FH`$UIT?'-G3E%NY8_M%!BP2-1)(?.7Q?#CR[. +M-<6E%R:V-A[7%+A`BQ2/PGL$%#__)57&;IP,>2K57Q-NS(N3@9B-`$40#*^R +M7<4.J?^`BB)[I%E7?>&CZF$W.-0>\XF>-AG3U37FMV4 +M*[_9<`#[*>V%_OY[%_ML$Y/.%"`.8)-&NS5]V<7,PRK_]-,T9:T1L%G>D/'W#J1)9,4 +MP#IB03#"EDYR5V(IXE)^,0)57.#WV$&V1+%!=P7L/A.WWNPT/S\2>FUXB\P# +M@..5GL^U.R0-XB2LWZ%H!^!;P.6.[-J$PZ[#11N$<%&Z#3G8PN[H[:II$6)L +M63\A%MG[`=M:TW4M22MM,5R$P3:EC6TU'W:$Y?7*X5"8V\#4?:6V9:Y,?]9" +MJP,26<7#",.N;G%E3YHT`SUUJA$1/T^X3N0E.."3B'L+&EM6L&*Z7.E4NQH) +MT"D!YI\FQA1=*G3E'X>%GPJA@;5?EKFB_'7>B&H*B[,L8CP<6`G7^*J,J6N) +M&JO%//R`OPAR'D'JE$N\6N!!'O/I2Z)*3EB;H12)=:IX2L@^'6&OR/O"2WZLSO,C7[Q:J.>S^&@U6<_%DR6Q]RT&-.NP:WE +MJ*Q`5V>50[NF-UI8G;JL]/=#\ZFDE\?00I+J%0A$MRF6_+1Q";GB?D!`$B53?@A?F2GJ[+: +MEX6@X$),6QN8`W`K$NT1.1X/6VD.ZLUWJ^57[#8KLDPYY#LU=UJ`.B5^ZK@T +M,I:PBH6YTO`02/MKVP;::( +M?MG)!AU!:7U=D?R6];D:<#@FRLR@PB4CZI1LE6+_WVGH3YW +MWBO.@[I^8O^ZP*)=83`V#!)]6X-B5FW]6@I]U5O"H]M`@8:](Y]:,T/X!?N' +M!,`7\%-G>-88OL)I91A.5.M$C0WKN1\_%W<1.=P&K"@S@ +M-9AA>J"PW>WJ3O1@N91;\X*1>@USG7Z7CE]AT@37U\^A/=^L@U)VSD54)9J' +M*LOSDBH#5N_&-6:IL]P;V$G);I.+Q!H\Z2_Y,9&@)S3?M8*`D@O6%)PH71#> +M8C#:<7N_V\(L#8>>M;JDQ]+2906;+F9ZK6X?'^6$4O0X;+?QWQ]*$] +MBXM$YLI!QGVTL8+=+6TO+6!F0,:O0@4CI@TD(;__[TC/?XA&OFOL<50D@5H` +M$#L)R]F+Q8,UA*!(':>JT!]PN+! +MD!(+MD3$97I!,)JSWL?H<'CRKCKP;TPF4?3 +MDD`3MS0R%>"G%R:QL>T^27&R?L:I'Y9'QX%Y0]J_QZH+ID<=5YX#@U.XC<&+ +M(!Z"^SP%-ZUT-JXCG=E#%A4XBDH%IBJ=A^;]KL^C*$LW*)YD_TG.#"IG +M0WD3!+MJ(3VYH4_:>.]W3[J2V+0SF%7TIJA;2_EQ]TRC+MJ1H_UN-QG7V1+C227!VTJKD?E+>]?^P.TF!Y"+KNE +MBW1.:)(O&;XVD`**W_.Z;*!V%,WD0?WB1W5YYGRK;S<[/N#G9Q'S##?A,C2H +M+***?2CO&%8M-?`,1#!,:RQE"I8=>CJI0X>S"SOK(4_,[78KUSO9W-*ISC&7 +M*,[W_7LO`CY7WKLA_7V]&\T%Q/&FGP-]R@EM,?B<3_OT1;T^_Y>LV$S9&*IO +M(M^(`Z+$;5=#+6WGB]DI.(EP]8X^`QT`NJ4COX`BE@;_,$GG_2?OGE*4>U\@ +M7/2_@W)L%I+2U"_X;:LF\8=0S_P$B"^%/KG[P`S-PA(&Z\X^U)'76`O"^$M9 +M0XN)X?E1)/]8=VWV`1^V,%K$2_6="";32$]53`_\;V@!:_/:.\Y0$\>0=![P +M!7M81+R3('@PKZAJN0MV;-:2N>NE"C5)^5HS'.6VBU715F/#;Z8/2-Y2%^EV +M_28%D$@]W*VQ675(=9O6.$-"!R*R;_PTI5;UZJB$D;MQQ>$`"/2=]UP,R(VV +M!'1$[W[03!\I[86DT\VOT/.-!8V(&`$-9>8/)0Z#G<_)?O%RVRXD=,[MXQ0GJ,L6."2P&4_A0+$0F=B8IH*)VKKRQ*]AR<62"? +MK\J%"TSA%R923Z(AF>B\-JKHG_6$ETF.SM,-*L:7)?)L\*:U>U#=0$=^5[%\ +M2+O'MEU42(%.S(A6D"QA='EU7!V`T@!Y6UYALWJ))AP9)M[$GM7*G6B)H*C\ +MNJU`"OV;TH-6FMEZ*2Y_('1B2+T,E4[&DK\^L/($M775?P7H`-^[/V1Q/QY!8Z:K_WO5[BP.)F!TI@!HOJ>C^1+Q:8HX8 +MEIV!-B]_U!_X:_G&/V:)V-@5=^(]4R2H._?P3972I!-;C&414$ +M_QPY=*OG==Z*LC%!DN^B&D'5F4@;3^L60[]1Z6A^K78PIK03T!-]H*UP)TL. +MG*,L#%-M&V=S+_7QV^KP6WR,$[\5?,N40E"IP+IE1:+SP&S7B;LN!O)WU+CN +MI&,6)`R&'NP!0P%`YVAMS(#9_-YB0J5!GE/VC3Y$PZ>KGJ1HE;S,AQI"[B[)H-U +MPW)A"!E-;QK5L*ZE`[H?^(7Q:,[J_A@%,G9MX:D$F$"1IA;$$30),N$M`#T! +ML:9Z'CP&,.U\$/.3[$[?>KA"TFO)%]';_J&5^[$N7TX_^Y3?KOY>!$Z6UR,' +M"W*:K0?^A@9`)_S2LTV>XQEJ?SK[C%E+[=97GS!;:Z&=\W?#Y5_2\YQ).Z/Y +MW:ZD7((YY)F(_%`EF*IFI3,Q?.)CFKYCKH7.:S+I`;3R#U$QG_9P,$8826`J +M(%0::`;UL/MS:>0G!42CW+P,(GX0MV[@TY9(URN/TGWBL!2/IQ##&RYO13C +M3*W+V#/B5:R7B%]'1:2Z[+\]HHN?*1KO10P:'67IN`ZRNHX,AX4/>Q\_K9WN +MD1+.#\45Z.D1L\19US`'BE_U!-:9_IYW%,""W:HEUO*LJ@H +M>WE<-.8TA3$MRNP3$Z:JC`QQ]0K?XY@-#C6)YBHC\(PZZZ,IZ'O#L5Z&7AH7 +MQ:DL)!/GKWB=]N=JJF'2SC:)@X&IVK+JPEJ*3T;XK[L0ON*X&V +M1(4%2Q?6"@C5?DLWUYY5@3_!)Y5Y>UV([V%0/$BD%.P#3&UF*8GF0BW@K_S/ +M:KC%A.T[L:77(F31U=APP)Y;%R7MLM91@X=*T$!G."-8./1P=XFC`@I"Q +MT[;?%!PF2.?S_1(@=HD+:63YM[\7R&?LI..,V6*-6.BKOM8^+D'T+F#Z>T;` +M8`(_=I@"SC_$R4'_1?M*G,9;6S!>.O,G*OL$KH]D@@9:9W9@TW+F/J\($PNY +M$R2.J>>S9]&Z#$=W%AI_C<)R>]7P@`(7\3BWM\@!F:610V-!3Q9\0OCE1MP0 +M%GV='38S()&6$J\0RE0R*-$:Q%PV9+N:W?8TPB+M,)3[TMC*JI,U?>ES;-Q0 +M!SV:H80:^>O\Z,V59\%\]\*D=T,@/-W>CUY<&" +M607Y6)R#0*\I/QYYJ_8G#NNQVI7=!034DG^<]`$_V=Q!"K![D+C:5);% +M9:5T9*`Z'TSN[HJ?Y:J9]V/^AL&.9%<+`W\#Q``?ZJZMNEQ"@GR`B@W*3/HN +M*`P"VS'9Z(4CWQ_`'O!_`I/@L,4/V0>[$\G?$Q&.JM-!I[G1U-PE#?(9JQ`_.0C@�C#/_/8\W(]"$(8 +M"WLAE;L@E$$3M2Q"'E*/>D,5(YA;N9PKPXV!"W]JJ@Q#Z?"$D=#)JM`3BJ(W +M=JNR5^6HA5S+20685"@:_E<`:$2:+FP5N!"+&57E,=%1(+,.. +MK<;/G7'BG'*N78?2SMLS$1,XZA_@*;Y3(-B&B3D$_N'X5SR>`/9=Z[.Z7;_Z +M4H>:3DKF#&7QL]]WY9/Z,/S2H!FMR:671P/>W`WG><1Y`NBT9D738@B'.WO+ +MQE7K<@3Y;KRJ4M/XSWK;(;,^>3ZNU"L^N86EEF_!';_*1DL16"K.59M2%=*' +M3%#P>Z;HB.)%>5S.SX)U1I!!2,+<1!^?][J1Y;!I1!03@=R0H.`;^Y"X7;F.WB"9?4#!9=ZH+,), +MWJ9"2L8OW-?U7R11#"S[91<)#4O7UR[G@",-I;)4]<&]%#0*4B7`#!M:SI9MYK\Q;S%J*2)M[*A2'9);D1+4IW:']B5:\A\?)Z`3_[Y;/8J7QC6\J;6MKPM=YK^O +MUCN"15[U>GFGE?7$#0B4WBO6%_X/Q6!)@4KM+UX!;H97;UG_F@-3YI);&K#0 +MCXH`9W%N>3+-Q+?V0F41\81E;29T/4>\^+"0K4_:#;B"H!IC\S3`EBI"D)6G +MM^GU9CM>@I8OQ^MBB*?_4#(R=Z'%`%T$[C%NX.:,9U+OJ4]UIHP*)'E2D'&R +MFTK/H>9A\)PQA(/-!MNM0/(-H)S*7!)G?*=_:+UM*[SIS:RJ.D%(6#!S4W(5 +MA!VM,770D%',](LTWF]DD,+6T,?[=Q!>2#W./,J9Q!_>H=-:@H(&%0G61B3' +M8!C@Q*I>[E*AT;45*H%[3DC6-J;J>^AT:G-,]!%PG8M'2?H"DTZ\\AJR@BG*`-+D%:=#2>P!Q!02$/[=TZA"L*6=_Q#6`#"6F5FXSK5\C +M1G%+%*>FU46L%>]KX"V:.>*OZ)J:OG.1DW\U)&UN).4_BZ8 +MT<2?I=$^B1IOA8/B976!/`>0">$WVG_MP,26@"<9:<0#:WKC<*TNZ]4:3-DG;F489Z'LQD.,:*-372>82KS.[:WA\>J720: +MU%EAI%38P#FLKUTFG+,M;VBK(*!`IP_HQB7]#8?410`P=;*' +MA(4%D=-HL@NI=[[8LB(,S]S6_X$CZA/=I_[[.?;4;;--4-\/OX7ES5RK43TQ +M[.GX<@M:7',?&G+ABYE*K'0/G#_I$O2;E/<*:OX7404U=8)7+4*@_PPU&7$7 +M!LX6W'I17H%>ZJWWW/F.^WD;YKPZ +MUDN0^'WZ7`XT1SD`%'D"TD;=>VE<#Q"B99'F6<)@P)/2_!?-TL#K^CKBF +M^-'!-(2:)2>C6BR<+_-/%WLPA$(_!_#-#/%;-BS:ZH8'6@VC9J;O7:X^W,GD9GW +M%E::%:\8VHK7%_5S?0WZA;2:HQN6P[\FK>YE(-.5N-BN*GBH1\V(&ZY\G@BF +MX@/L<1=\I#"`F"+&B[$O+/Q=(B-4)>>P'1N.-E)1W=;\=9RF_..?L$GRG@M+ +MKW5,JT'-/7##BM/SJYEXI$K<5V..;NIQ.S3,67+I$+Y5%\=XE7W)%,=9G7F2 +M.,D6R6Q$M#TL!H6+?W6/+2Z3'[+H5:=Q4?%RHC'A,IW'K'QC*CT>#LO3F[Y;V7!WL5DT#(AX]K5Q<1 +MQ\'E7!_$3N#;^YR`:5>OAN'5KY`;T"@[I8AFT +M3N4G^&+%\H2J<5'9>)G2Q4F!K*>Q!E7%/?T^+FRE:;"/L_@4H9[,PV&M8M[O5['M]BD9V+_:7 +MTJ*@_FUA+?-T#M_IB&]E^^'1#(*FZ?)\G4=`UX`JB^N+V-'$@4K(HVM/#1_K +M%O!8:N)L"$<0U:J7(.%D^=XPDSNC'%J<+=<5+./WJUD-M3OL2ZR\4FR9BQ4( +MN^/2K>(^9:%!]7EUC3W8N&.5$@MA8QYZ!":S%VJMQR9)O_'Y^S8H`TCI3[N/PXQ&V[DATLWB&&A<57G!# +M,_%X:?$VU.E"I"'M?!YB+4L+1O=5$@Q>)Q>U10\BCQ/G3P^3D:T#E@1?'U6. +M@Y'(=&FA*T@QH[]>^%RM$6`X0SY+<`;SV<2YPA,I=R<4V"!^?,C%_:3)>^CDR+4!K4+D&'D!/L1XA++6]JF<]NAGLYPV=7Z"=+M^G\P\)!FE"="E;B%"$HA[_CU4.T?]H+_=@.-X#XN/* +MPTW_3Z+`5O;2:5QZ.7#9_Q;E:I(U>IL>R5^6@9Y%2IMI%?5Y!QSCQSC?R$)3[Y.9HKDBIG=]PHU'1.TVQ,0="5FK('S9^_PJ&!* +MK\#>2QG35$$<:VG6>6]4*G=_@\JTP4PDW[@#@>8EP?![%%([J,!WZ/Y*'9D1 +MK8^^AO%LP&L*I0T$"B*7MEM3)VFP[*!%@NX/XX)!H-HK?N4*Q?TX_SK(7];` +MZOR[(?C`,7<=3_<.SF\Y_HF$5EO\IAEDJI@VI=6,UYPR7_X454Q^-IW=U^!.# +M$C2=*R\97G6'1/TK!7FF?ZS/*:.XE1Q0;:>D%JXU==[$F0=0T)&!*EP1<^ST-JLX3@-BU`BW2,7^'+8P\7UK.UIR/Q +M0O/D_:IBH'G_07Y$<']4Z3LJ3B]^O5RD?".U6L$?O1K?7Q^=T"I>O#/I&AO6 +MN"YO/[[5!WK:(1Q3$*^O&?$D"EZ1,!DV!S]/WUB$J,0EKSLT_[>CK&([U,RB +MV$V;4=$,[H5VA"N?'DT78]IL7%WGIFBSMR+403/Q@G?0AG2LD8W2M8C!0`'P +M$19X#JU[K.LGT0Z;,?7R9;_@M+(-7AW+59_>-`M7^.&G3SZU%9#YZTG^$*/# +M4AOV)OSZ!7;3?=JDVIAG)Z.DW'ZE=="`)SXJ8YM +M$%')_:]@$>"ZBT41`S:HA_TO+&=O);ON@5U*\SYJ@9E22UEY''MU5EB.ZWU'_PB>3^M*Z2ID`=!B+X2BSRY;\M"`6PC9OJRD3=>_V#%39RF[A=B=^4-; +MZUH#M`BZMA1<:/W5=3LD6)8V4]&\K\'CS3`WN#4;Q:<.$-*`7.RXSH_D(,E? +M(4'367REB7+.C>S[H;EB?R10X4W;T)'-XRCRO_M>O8$4#'E*/=P@>]&:B?=" +M'MSD"\C.PYY&S::=*S;$YGS8Y`#<82 +M:V=2,4]U1C[4IGZ'8IW%L3J;ZJ(P+#,;5P'`N%[3:I:$D[ZN[Z_C>*/BFS)#/AXHC9O<5I^UMRQ$[&H\+Z +M7,1`7HG%\CT6Z'0@%X;C"0.7=&!"3,9,$U>_BF&2DAA`LF+X3#,/(QUZHAG\ +M:`S=881@"/[3^'IG$#6#SJ0E9H&8J\(S>PQ$M")*)Y'DK$0^I$.@GVOAV'1_ +M6$-4WMZA&G-:@YRG)5[[X&O5K_T$#??C9-X<_X\*".8M'B)^CVSXY'Z39P\- +MQ0.1-,[NNG&!6@L#K:D88#$'!CBAG1G^H#UEX!`\+1:['K-=,F,5)4\PXP9? +M8TAB_OR/,*B%+G<*/\^\?U4R:LJ:.!\;<\B@.&PEW!^Q.>7N+R+38V?)[Q#V +M)XX[4/$H3,0C:X='S?!I>R1RP:\HV`UV6`^\L/)YE0IO?^^/X#=2_QNL^_+"ELX)0V\JP<*1X9XIHD_<*WX]?41* +M4<:2O7Q/8:)DR/!RY\Q4>W_!N'WNTM^`9\/KM#UN))NG._-O$SL9#56+(G^@ +M/)$<'I_E*W0Q:M<:%;J(G0@NSON49.5=9SHY;MT0N8*.#'ZJ4#J:7[CM\`): +M^V!1?X)0OK/=I3>;F$&6&%!6+/P2"%@J+,FQ)GZ$H6:0Q8GN-[2\OKLAUMQ] +MA>Q(F4W@U$YX']H"]UHGB#M$ONN01"FISVQ[$8T`G]L*TY9@(H1H]1('-.Z[ +M++-GOVC_*19K(K0&U99BQDRNLR)0VR@IC)7:Z3V"N[(XC>GA-.7\,3+K;U6W +MN=>5QCHNJ"+E8:O1:@'KBR_`\'6?+M8,]'LU4&G_F%7KMZM.-RD81NX\(HM\ +MA&*O3&&18Z5>H2;Y9Y(&-XJ#2!$Z4\ +M?[P@)(<"N)(Q]\D +M@E$9#4DR7WV!*G5/C'\+4$].LC56/'@";N%L%?GMYW$.'>UK*1;.>Y,(M[2L +M:''/L$H/?>I.P==A/I>`<$D_HTQG1^W/3)JES(X7P%6R_9*@V@4UV=!^RU4[ +M>E15]B:E)4;)[%R6/)!FH#/_L,!OI`:@2XGPU#,VKAZTEBI_;:/+J;N<' +MDR9:D(HZ*/'5L\_3BDWZWB\48&8J4!HP0W90K]]PN?(;@1$M(+/XUU$N"?9G +MDZ7*U]?LS>4>-);I=MX`.F`[(0?D`TBFX(:"0*Y,<#^:8NA=K*&H`B2BMMRA +MC+R1,9UFUV4N+9LL+.>,U*@B.,[S8U`C_WH"<&`P4-\GV0.B_IEVDP4#F"+E +M"9%:P7PS(EK@0[,A)3L;LFV,Y$HZ>;;"'",%M&C=`/Z1M?G";?AJ;2)DTF3P +MT?)ST#AM"#XM5MA.C3,@3RR=RS)!.^ +M#3V#7X&(M@D/VR,V__V"]C++^N???N7.SC5IN-\63=@$?NOEFZVQJ8*-&5N:-QG)/E!,MUT*=$C]>@36CB+_HH?:RJ!6)S4%J2P"?>\+/RM^@.5WF2=SX4 +M`8O>/N<)\PH\!Q/O]`%,:2D>A,;C6V0O)G'!$.\N$5GL`\_U&6+B+(/:FN\, +M`F,OD]%6`UCC(0!C_(@$%0J)\IOF.]U%_"-`:MV0C>7NEN:WE3%?[^J8+8OVV!@[O?ZL)O>>!?4RR)#7M=R(G5ST_T#!H*7S@6(H7YOY`W=70*+I[DFM:9R,-%HIQ +MSG=C36@$C02D1,Q^UI +M@'P8U_[_*JQ?(`&%TLBP<9T=T]U[!,K!?Y$QM,D^K6RJWQ9/&4@%@LK3X=+Y +M*),_-,/JXH>Y.WB#=H1D:$Y42M<^!T;`]*HKN5JF2N;4,*H6PRX\(RZR0/39 +M).CI1G\S-$,OKZ8U`F#QVS&ZY?][4A0JI)0_Q-*%G%JXK7_RA*X2_G-F21IQ +M5BS]2NQWYGNWEEC+>^/.!EO^H#ET%`=QO$5!UK>J'%5JUCG5LV^FHRO:;.`V +MX&<#^)*(GSQ622N=YO3;&R36$,_33O]Q_GXTU4#(L8T_367[G>:WVWNV'[H- +MDS>5:BKPE]8&1K5FV,FU&Y@&,'N_!53*KDDXBBE>`U/J%,UUJ]OE]-R*=Y>W +M^ISW308S6*-6,=0R)]@!HAE%ZKM=]@\L16C2>1SQ'83['G/`[Q^][+U)/0`H +MUU:`M6?W1_F9*4S&8]T^B5(AY#,W-#S@/V0;4=$#3OU8R(F7RTJM2L# +M8Z_E9:>9,Y[$)<(B.X&O_69!1QJDE0YAGL2X`HF.XH6^D,= +MP8_=WN[>79PB!=E;(H7W]11S(N,MV5S2!UK/]HO\,Y`[+*5) +M/4U[HE&N([G4Q'II#N^_JQ?_%E"S-B6#*+8+H%)09FN_8[,)CP\$^KHBD;%,Z;#59P[QI:ZBX%%8-76 +MJ<_-XJ(>^N/HH[$<%C]$Y5>9NR]DQ$\W$6RHD +MYY]&K.-J*-I,3U0!RV*]2A1_?ASA<-BIB'S(V9>:&PW5B!:R[SN(YM[:IO>, +MRW2-E4!7=6\0CS&8N9::&UXVA7C5-B1%L^_M8C:J&P$F(.B5EOD-*9@`WT_AQW[B^0_^)@G6FNWP>Z[G1*+&4#5?(O8VR-,$%RH +MO%R>+5PE-@M_-()!Z;W'\D,6J75K39KO3'2C'3_%CQZ%>_[)$,-\[BO: +MRZ^F*T@!NM:`JV*T6S@Q.B/0FN+C/[UJ]=3*AEEY)%$(?(#0-\)T* +M\WY`L5&:5&R?T".J(%T^[PO,[F<< +MV@\NU4K(.A&7KJZ$LD6(%*+$^`6)W74I(F].D.JP1W]YHWY,*.Q)]FS^=-MI9((]U-^'N;GA=JB\@93@6H5\;;" +MANJ-)+T(T3JAXA1>44-`G(;%(5+T/PTH!C\+NFL:=SJXX>FQY-_C`L@,/95- +M,$.CH%Q*]JBT7M"5R!B_._?Y@IK]TD^?7+KA)R([GG`-V@]#8V-M#X47Y_@X +M)QM%4JLMYGU6))?^J/5;+2MMTVRA,G&/TH]=*4!;'IFQ)^-19%VC*8_%2`&A +MJW(Y/.Z>E1^W/HM_2)"SV5%NLLU=HS&9>+K-.H1`E;>[$H6YQCGIZG@*X0 +M]5"F/_%:Z"RF34:KR`*]U0LJ3%-U0L0RER366WM<*"X?1)D&8.0AQ3Z`N?[O +M.70J(Z\8G(U)WAXI3'V])ENZ!J;"S:+=_=[U%P3O]M8LC&2Q051MYA)T`*TV +M[RX&\>RF8ZLZ9;>`=JSO3K/N/5/O..Y2LT42PNOL?-(<`;'$*V/=DN1_6N1\ +MJ^JY@K`]'>WP&#C58SZ&J:R\@O18O+8O.6)->L7LKFTL21OB??-!`723E`U+8)9R%)+L4+`<%CEAJD@CQP[5X,FH<\8K2("#7 +M@GE/"Q(:SUQA:[5#%XOG(%$GB00)85@R+:@Q,\IJX6\D`ZI-G\#SC'47*C98Q18W4V#B=4M, +MPR$9MT3Y5Z"-S+U!=<>^@[\D0OA4K&GFPA7-BK-58EC$QS84!^NE;)_@$FFT +MN=Z3KO8>-Q@$0IR$J3;$;B;$!1_JA5$,2TOXDOABQ\SAS3RKV<"LOM4:LW@:\@\' +M`M0[+]>62G=VE`L]=^1.+HDN8C +M-V%3F/6=.\@5D"%6GM#L%JYFH5Q@5U&?"F0H)HRT?5165B][6$73FZ+'C`=Z +M5M#]XUX-*:>UI25^<5/2"_*^0X7F"B@#'DDF0-D``7:[/0CV\D\;<)?(<0-H6+)%LU-71UCW2UU:;&@U5ZQ@+3M +MK-N58?!*=Q!_]"I>QTIR.1C1I$K%T,.U!N@"H=#':!#P1+BHEQU@G6W9'XA> +M\QCZ3X_5>$PX,6K#5V?-/PN3EHQ4%EN6&$O[:V+M/KJ+':BZSQABW*HEFV&Q +MG*(B/&-[KXL+'<^EF87I[-4/]U&,/K]QMVDCK^](A)`E0^C*D0^2#!3PX)W1 +M-!N[/^5^3NBU`Q1$^B8IM51DE#V:SK`9_D+!XBZ\OW?P9T/7Y8$[;;=*UWZ\ +M`7R?RR[FWCF'I'QDF02O_RSR=S4D)E01H",MD5:EYY:*&JR)%V9:(1MX%#*?;0]* +M8*J'16-.]#;'.9"TA*L/Y%DBC:.B^<29)=@B7)G?.SSH;P+B)38'!8U +MAU:'/=:AEBD$.`RL9'0A+&2NSER^(3#&;"3*!6J.&ND'EZS`*3RO']GO:*`9 +ML4G,=L?G[W2G.EA@,.7C&K"F^SX'$E"E9-$N&S3""?`>/*3)?LCU8&<273^G +M:+_&"/"]<>)=8K`T^I<>`(W6B6T51RM,>D@R:!_%OP+<$&ZFZ->(%*S-2NU_ +M-"%S4.>6TS&-CDL6JX4M'ZO41VS\C'_W57[2FAHNLV`5"HOY./)=LYS,6\Q\ +MX5\6G=@.AH1%2-P2QH&+TPO(5:;K^7PI+PEW-.[%PX;93<]A1]A^$/SE;S&7^4A)3[(B$%)-@HNQ +M`PK+E3PPH[*P4*SE^]K0G59EJ(O<2W`$>EQ02!$&75)O;GK)/V!SGP*]%J\(C6>AVNNBVPJ9]^ +MJ0IS,S?:&R_"8M1OY*AK]Z+C:,9V'04W6I<`'#8,-KBB!JR82,N2TOJ +M-M]-8KW*Y`Z@RV):>FNZN7H=8S>YT?J>JE2X\/Z(VZ2+CE=YMKR^:L5Y\5CZ +MW6#1&3YV`-$WBL3YKXO,UZPS(JQ]T`6H8$0VDF0!@*511F?9JB:<6_0;3J_$ +MU)E"SNU`JQ31[E-`"ZLQ;$I4UJ,"E+5C8AWG?M=SFH$$/I/JN%@__;[ +MLMT/<[G$]M,6<819P]!K:)F(O#!DQH=6YKD%F#'=EGLXK0'8X(L/%,E0\5;@ +MK`.#X>.:_Z#>?F6RV`+!2H1=_TKOC7)Y5#6Y,2)="!+`4>6;K^4N+Q,T?8S4#A +MU,'928F%45;5]IO;3`!MBN_>BRLT'T,DK75.YY`DV=X4].[%("?F7$T! +M`PGY;C&I?I`W(6EI_G)!!/,*Q6K::ZL#2_Q6TSO?:/5PGSDXQQ^3.=6L+.SB +M=VL0Z7HH4I.@(ENV1&6EZ([\5#]OI.O'FN@V,??#J3^D!5T\L1P-0`>UIMJD +M3,HRW]`C''AZS)R`^\0Q9\"'R!%*C:4!3OF@`0EHW*B;+CGZ-=->#A/X/B** +MQ$`2DNO[-J/M8.P=?\\E&;#`.,[5E>S#.<]TL9/D?!/IK0VO#'G3[=S1Z+P63(!L&DGY8RF)BY/#&RLR*-,D]\0$O-[:YR +MU>>XU,67>$2@&/N#6A67HZB5)U&IPM:1_(HY#2H7D0M&F:.'\"M4SZD6@-R* +ME-D^EM'TG$3D$K.G34BJR9&`ISEZ\9`;Y#(9%IR8F3@O]\_D]JF`@15)XBQ= +M59FX*^?NB``F>Z?8*XZ"*4#<:(>MA]NB(*,R[7'3ABJ1&`BQ&ACP]'%JR_ +MB1UTKX%T.>BVJM,C8],.+,.>\3RQ6+W1R.9IGO&FEP@Q%RTX+#-%*TYD +MR$E@_HJF=$!FA&F7!>A_$L2*QE;(W"6W'P +M)%P]6_7ZR8O&(I2X""5H%EA@ZR?_E[O08$6A`!O6[ZQ1(_(2;82-1Y`<D"KW*,T;\>X]T2`A:N5`#7'O^G[IB9);3L%:3_R#2U#RD!<-8P\$M1V@G5\D;6BT2/C0KT[2+K'!2FH]FM4"',61^"<25^0PT%`X1Z +M3$K?%P[@R\_R)\H6OG]#-2AIZ +MHS':J'5MNA%8,$3+;9W0I=#^RC+5$)62[L)%W__N]:'U*&(NXLE^71-K7XK% +MLI?O$P<$;Z:V_V([_E3:;I';KZA=H9+:[E_^^8&VQTN'+Q(+<>ZCQBE8GS?K +M[.9YSO]%?RIY\#C0[(//#0\F<3#K3-.6(RJ)06$8BA(PZ(YDHL?0(7&>,WG0 +M6E]+OHI$B1]?5O/*/)<^7A_0N1S\^Q*:R1[D.2!30L`PX+M`$\!->.\Y;..JL +M.@6F?5\V^@H%@CN[T!6V0.R8S_->+_8YGN]/0QFH_ZSK09KTN7]&T3[MIY)1 +MT9_\Q)>KUU8]3IQ>;#VJHGW"#I?@LQDED1^L)%N&GW)P,X>J#`)S,IZH1;&# +MUD6X1?@AW3U^X'O+`"6XPH"H!S>RB\[*;1^0T86`1B/$HUA1QJ"^L-P',L>D +MK<`"NH1A("/(5PK7RN"2;VY]!4Y^^>@N`C6;I9JNBOQ^9N+*:?-J(U7,+^ +M(#7:+"/O]7*484"T?X:T%T-P34K%NAFB%?4>>AUNN).$:&"K\9_GV\:P.X.# +ME!PNO%B_/R8)&C2DB"ZVBRY]J\9Z'Y?9ST"+4GV&[LA%`"G6$4*A!'?NMYJS +MA9U9B\TH.P;GUWFPF"Q.C0\2ZHQ-*&_UCE.F0A-"ID'/A:CGGX"!T\%T@UWQWHS!$A8&9<"J8R>SLC +M`0X$X3E;/R)@H^@>Y!H&C-]SV^*WX>0CN/N/VON\P\3G_#2:F1&12OS6Q3\G +ML2S>4#*M85KT__QI`:`V7/8R8;?K^F.]Y:ES3!;F6#N_NUN#ECD(A<0%AB!H +MQ/&6.L +M01>&R2*#1`*\F>UU'&0G!_<0XD<92):9+C&0W&=$^P/1.3WY&]^#^QKEQLG` +MZW'5:Y&GHX5.^6:09-_#76_"$\.JAO';ZI8O.9\E6BL@2U
    Z=Q1^:<^CUFG2QO))GH8)QVE5/%'^K<1B:O/%0AOTULC) +MYEB\9M)+X[$0OZV!^+BZ]0*99XXE4?,B9K0\1+"S)0]P2C8(C5SGFJ-Z"F%$ +MX:>U4$ +M^!U]C;VL"DT!];1#<=63D9._[6KET#W-\7.>\Y0`A,3IZ^:0R^5VFI!RC*:Z +M_D\@$QR=CKZ$Y2SM_IV)*+LJ+W"@(T?0-@#5&)XB<_MX#WC'S_;>IN^F62%^ +M5`2Y,P4=0@F4LAEU,:'>"\]AQM<$Z?/*Y.L``PG574769?&8/"9_CW!_=".J] +MN_'AH@JMI".M#1^>%3J51D`:1VUCO*B?:/1,_^Y/R&-#Q=K9&#KU+LGFO2)N +M2&[-RH7R&X@3B%--%'_=+UKMC@(<"MM21"TVU:LZS[])!/&5QZSSI8?%*&0$ +M)*#?_3@^H_PLHA,+XRH'6=5XW_8L,$HB0-HAXP,#G>59H5E7%G@,EXTB/I'5 +MM+P+L:,<[E(5#^/'$%;W43;^_&&'DOOO">9048+86PC@S!:$`DKK));8&\K$ +M56IL0W>ZV'LY.-`7S5^EV(([.!)DO5NOX,9=0^3WA)3KW6D,KB[E)N?X%$I0 +M0CY`WU$<;_T;TJUZ;"E]_++S1PF0L_J?$U9H7BC3CQ>$&,+*!=J7A=;G&^0,)698:C`_>PNA("/C +MZ>`M7+%CX0^%!=V.V9U^UGY6^JZYOJY,W79>1 +MK5X;9T>UM>9>5O4)(*&QG),.6WT2YVLO9KTVQF*O+44/?JBGOOK?B^>(L/$P +MCM:02#_";PA^"3Z[^BGIE7R@.P>,(2M8#[E7G/.V_K;$L<12ZW61]>1")H#& +M"KMBW?MV+\@-;;FF1R6QTLZ_6(*_QS;`3;N8@"5JCQLQ/5[[+!>/7PLM8+@= +M125*.LH=_<`U0%R`8D)LPCCS&F5CZ=>J1.+2J3_0IANGNRW76TJ,CO%7)O#? +M#,=GW-':%,3*L(&$BDL@W@WM=*65VP54R\B!W5`G0UN@F;BV&]UR&0QR20V@ +MG*[>SWSS>JJP[M]C@GAQ%^3/)[6Q336)?1:#(3_Y;!JU%,=:]88B*XKX'.NG +M@OS)[J^#:LD7EUEO63OW=A%^@TLW@8;M^7*;-+<$T/\)K,FGRT;7=,]M#^9` +M>2_NS=?BLP=EDBY;/YYQE/?^RFM$B!=/\E".'PV5?S=)W* +M@K?(#@:LMH?3&!4.`QQI9VAE7B]&'*V6`9EEX?(U-AQJWB,%.^6%;!EUNO[. +MQ7YN&9/7&X,$P_(6%K_)XPYYA&*6F/=.*D3KG2,`1!E=EECOR^A=3E5>SP0] +MLE)`R)G4E)QZ!FK;Q-@%C%/_A=@X1EDSAG"0PV*@:%*8(UR^IGD5 +MO:6F\#>=3O&H[[[D*3%"H[[2"F%=*GSOBI*J.@(>AS3A8D:M5_6^VK-5. +M(1>!]Z(+2)A#A?&2#>``MBLU%5WFX>C3*7BQ.]7"#.P]E_`"!@`/`=)Q7P#D +M",.ZZ<>\Y^WR9D'\ +M;#SK:HI=%A\T.#7;R?E=P?F?ZT0-NG#+9*6'%I--FK"M>C?.4?AK8[3W\X), +MBBV\UX?VH^J'UW;S1OZ/IP?>OV54[#"GLZU0QF;@I^V"]9P7G+!Q$UWL,GOU +M%BO)#/U"NER@HD/L).G@::@>MU-@\GG%ME^!$>8M0UQ8[Z/ZXRG9*L]3!RSW +MX#?.XWYR38GIWUT028O_73AYU$E#&Y+O/\WA^:,O?^UV(I;@H*2!JU:X\-K[ +MJ6ZRSE9Z.3N\L7`/,B7C0IU=1+AM8NY=(@BZ["5`((.XHW;7I:<$9V[]T@HQ3&SYKCKXY8/ +M0/(=C-G5/$Q##7QU=*DNUD6&088E&#[7+&2>X5)FDMKL]JF@>EF[)T?.@3G>Q6T#_6MSF5F/N%,N1UPK9C^3N]M:K +M,MX$UDK4#"0;/O@CCXG+MYM%X#9G_O&53-\4Q8/>R%VAJ#SC"XUAP14XD)2@ +M*0PX+P.U9#D^_UF*;%&:B3MYDKR5TH+&;DXB`Q[2YU2 +MQ$+B59<=,]:XLKB#B'O<2S.,`)&(6H"DUHD22**"LKW&H!1A^]/Z$;)0O<2# +MA6*F?U',JBHX&WW#"(CR2W@`QW-0@!5B_&;VI3'3OU1:S?AZ[T4&SD]7WJ.B +MA22H\F^#*C-FX!/Y9VXC#=J,&Q$`1+Y2"IG^9-/?F2X_H5X,K8J6UWL(GB'( +MA$B+-67Z2._+YT/FBI!ZETLE_CB8Y]2M^[<+I)<_W39'RXU(MN[FKZQ2%P&L +M&%-L2PNIU60EQ=8JB)N`':XJ%-G3*)E@-HUI:CT1#XKO: +MEU:KCRV)F9VFJ4T]%2@7^S#DP3(*\EWK8UB7(_>0-JL\YO/$6M#$B4.F/UA^ +M.TYI;][@>,KL'C&&ZO'B%@@"C_Q:[EQ6-=";P#$:.F'>O%#:1DQDBZJ>Y4G[ +MUU(^:(\D5_>9&FB@PAQZ[QTQ)EF__*8T.UPPERZ8F19\DR"&J2\3(^\=<*_6 +M8'-_E`GXC2+2J;$47$X:0M=%F$ZK1.>Z4>0#AP<:!HQ%MZ(]\D9BP*Q,RD6" +M^%A>H-B_H06`XY@*:AU9N8,%C(-2(!]WC6*&<-:W3\4QKY)[2Q2`7\L5ODQ5 +M&X/;O[]B#R-W!_5+`4'[LXV6NT2NU9@C;>IE]P5OGTA;%K5FG,IGL;HD>S@+ +M5@JQ]:XGT0\R^C$*$#&A&_"Y"T>2_E)KCE4*.@*O5DB0!RP/@1S/S`F\^)`T +MG0(K7%:D*0T^L!1,RQ/[CH>D/P($B^-G7&264Y_"2`H4[!Q9Q_TF679'A!5. +M+"X\CI/ATV;`QDC<>%/M6""H`&BH"GCUWL__/D*-!.'O"52@_I:WE=>Z' +M>'$%[XC_RG`>4-;F[M82@EC1W=U&XTU]YDN/_ND(HT_&>?GEYZWM, +MY_^H)BF[/O-<]:_@MONK/&;?[(C&42J]]H][RRPO.3/$=8Z:9\,Z".\$]K@1 +MMV/I/B&T[7AL*W1#YIR2AD'="F_HH +MYIF3I@?E_P,>[6":U*).:Y3)/34-#\M>,MC*.`X&=&JE85RZPH[(`!5\Q!)1 +M-D@LC[K8T(X#2MG_%#H69AFMM$E1&3?NF.K5->53\$4Z_^:S@X;G1I=5X9Y+ +M`84M&U?5!/?`C,81>D!%[#!]G[3Q/%6,P9\GK![-AYGRG#='/7*3)PM`"16^ +M8Y]*40W]K7ZP-B34I6"2TK^R2R`;SY*)NF;![P"FK6P=&3D$-WR]$^?>9?VX +ML4PP75)N8-2-WX(UZCDE]1]_&%1R#ZT4N'8[,D +M==AD+(<31>\%J`/&M#B@]YOL']`CE\$VUH4):[ZT322L+37!X1DAW'8.`-/I +M*NSOWN:/K^9H(T3]F$6\D

    /N:B[YC(B\@P. +M2O@NP_F*$]JU#<2@@.S90)E'@EK,\:22=BB,ZMQ37FF8QOJM-G&R_#*W9W!E +M?H1F-+3<5FI\^WHBXR.=BE]\?9&Z;'KWQ)<+I[/YO8UE0-,7`T$P/]"`+$\7:G*33K$$ +MC`KO$ZO=D8-I&7C6]`FUAI-H*\1FPTIX8/2'O$:1RF8;JR02G-8S=E*Y.JJOM^B?Q&:?EISBU@X$:!ZTIG*.K4K?5 +M@=_4+\7-'RMW/9Y`CULQO;/_66_3%2CEJ1.D%LWJA?B?HC/G70!F$H"$82*8 +MR>EV$;.'I)O84\L1_:@A8E=Z!1+DF(Q4$;R[!+.9PB]@8-].)C>EUM4234H> +M]V1$N0F:]5TM[8^6AFY/\&:O56F/:1+_I5AXSUW:WPY:N,-EQ>#L9)*0(3\Q +MHZ@DJMGAOW?*QS?E;3[\Q;"GHS@:+T +M%)9P2PA-2^"_CHPZ0\9MLA"-R5Q!CLY9OW$^,V\G!A%2MH*3]?[PR-?`$-(I +M="?%0!MPY8`^#D%_&W_#SJ1Z_NU,*]J'>0Q<0R6`EQN'(#JG,A/()@-AW1N? +MJ#&@&9%4WGD)5)4?AEH`21J^JCR17X,R,:%\8Y_WU\I9E='VDA#9CISD4$J@A0($I/S2?J)5J%< +M"`B8TI]OF[FT./9'70?)%EW;+KO]2_;"C4R+QQLT<%Y +M(S*!D$1W&N-H-[FB?HCA\LFMD2`Q(0 +M&7=85)7>31 +M"&LJ8J:Y9;]!S5.5!Y%R?ZI"EC%5Z0Z']-\\RJ&@)F\'I4'Y8B5U0+EA[0** +MU(\*PPE'-YCJJEDCO9DTRL1&7D[C])GK_54+EE;:B)(U'.9NCGM.0T.8/2SP +MN0!'R`,C\#^E"7C^@V;!NA3J>_>$O +MWZ)U5M5>Y@5RS>VFP>=]#_MZ+42[;TTI%CK-KI2CU$F=&16DW9G%WW@]7[[3 +M+=]H+YQ#`.%XK3H,TK*LIQ443!EVL080?:_LW"1CA^:N']+DS'S=[DFHR+)] +MGF0^8?8QI2&?H2W'`3()*I9\T"M^QF,;W@+/IUQ6;IN]N_SQ`FZ>[3^1#:-? +M=`S>/1"U;->D1+#8`OKUX^1^"4QV%[ +MOHGME`XIH+UL3PT4KHT0-EP0NGT=HG@BD;-I7"/V>O)%TW#5-ZH\=\EHN8W^ +MI2[C2**:N8;R9,[CU$,4X_MUY2]V[R75PXU,J5BQTM21;#L<[;E=5DA(@LQU +M^AXC"+X";^OG=,S8K#MQ^MI-+JT0#6!_I:T_O%4(5C"A2>Y)!R[_AGHJ,EFP +M[(-=J*+JO%MO5SU-!R*O4XUA+I4OM@OUZ078!G101R#8E`-F*#2CS7TY^I@V +M3KOHN",%\Q,^:/GH*B]G)PMT7]E-F3@P.0LP-%WKIV_W2CSTM^[9?+_H]OF% +MZH2FHPXA?7(Q[(9:66CWE%Y(!-ZGJ$YI?-.!UV[W5\D!8BB'V24.ME$N4XW14H+,!2"F#L7!@BQ("ZGL?]=BU5A!4-&\?_<.FHI> +M)VH=Z@W1?S#:P7.X]^:J+M-3'<&'MDE?,T'/*]4?. +M*C2M'9-A2GCD.'MFMAT,/8GR()6=FL%U[H)9;_/^_QB +M@&WLE]4HH"`R*:V5\8_S<\_#7/Z+%`'^Z+6R*Y(NQEWRZIBK2*/O +MG3*W_"H;6Y3'TQVME"YIX%?16;I+A)ODUA_<,]-:\-5,UW)RNR.D2-L2JY?J +M&L(2;LW"1_!HZO'5J`%D3R*KH2SZLY&V9\?954H>J%982R8^MKUN/J\>].9^ +M^4B:GOW$][_`:16`^`*T-Q;@RSX]C7G",K)([8(?/XZW*Z8_8HA,5O%2NR%[ +MG(<8++O:_LS)=-1\6;UYS&NA+UVY+JH%&1T>?:N\)3Z]9K1-L$9-2'J\PH?>&`BN-0X2ZEVUC[ +M"_.FB5DR_H$@I#W\/K$EQBL8K$X?)]I,YI)-&TED0W[AOW>ME58&-E;[V1,R+\O82CG%3S&EIHQ`'SNXP_Y(PY3\N2O!6PD)/+ +M9W#]F9J+A>`;>K6OV#*H!,-:W/)6]W43ZJQ0WB[3@`Y'7;==P_8MG;Z*S!%T +MD8B@P=U?N"I$VUW;CYJS`5)AZ?D'=1VMXT=`_'&=WFGI8.S>[5:1=HS"C,=/V`""G45=))+X@C*<(?Z.QZ9>*OE8)3>(`?>)QM(SM&-^L$"3IPT^P +MDGA"4'+R4-[<)`Y$J*-DY.TZ4R-F`X=B,(![9(XQ^C^DFVY=M2I&NN7VOM?0 +MX%&@XKNEO\WU_?28-CKFN0/R7"+"B^%]Y*83QJG1@D+^*+%0M^I7_MWKFL*4 +M*&S?\Q555])Y*C_=MJH1I=F&XG)(.'.=@DD@5,7JBC`M08^LT,QN&Q]X*?B^ +MX;I9C9VCU=.*_F&,Z-.V8ZD-#QKXZ0"`X8IUI:\$U<)D0'U+7\9)R7>_,<%5 +M>Y/]OP;KZ*_'(:5'4"[JUT=&*BP*9G%3]2=[6H#BJ$4MG697>^AN +M<4\'A!@)P@SYEL*"$+$>QL'B#^*8HI?7J_YK_G&1B%;W%$H&@Y:E1P\+`Q]> +M^QU_V-_L5TJ/.H)QCJLL,4[#%`Y@Z/W7#(:HV#-GE;P=7(&YG5BB4(RP*2K, +M398/^^;9'8IJ,.TGBNVU[Y1X&7?2O0R2F7SFZ<\X)*;D0'P(8O/U%"*P6;ZK +M(?[4W6*T#J#\/'UY)O3B,C0&+5,>*H1=S3KHD5H/P943$TAG\`3.?T.H<%<% +M_>8QKWP!?N1\G0#`R65\E;>!_VM"3Y*@Q_T#:/,A%4LM-M_9*CWZ%%VA^_SY +M[VP\1(H/,$FA/0J!"Q($1NFY74U?22!0-/6NM@+^O()1O$\>VF-6E'@"\6J/*//CKSP5L0!';:T2G +M02(":U.*+]`?@ZF0RW"P;SP7,(.7J7Z+$SM%6$,_.4#^#B?_A-^20:P,S.$@ +M_+PS:&OBJ`5[$"*FN_`,9B9[\7L9_M#(\'<\MT57%/4&!P%!.'8;903Y6?D* +M,G)+..*\5?93!M#LIE*,C855B#XX,UU@!1S'EU-,6WUS5$GN&:MG2:%72;57 +MK0$")36BQT__ORPR@9\`!R^ +MK%-,#+7W<2H;:D3U&)#)[?14WR:6_56,G]^,5N;35P]'AUUEAOM230>].^5H +M^?3N==;P/L8J[L`6VA5ICY=P"VC=P298M8>DRJ2HS)3]UP(9`S4YBES +M\CS"%[4@45HM\+`Y+$C>]N$?<@CES(DV*^B'4P_-\R='LC%$"E*X_O(;&H?4 +ME'X(O80*+6E+?CIP6U;EALMVN]@BYZ4BJVHIIOXD)0=1IX\TW-ZP:!01JQC_ +M4=1Q)Z!(I+&4/B60H^MEM$RU,G9T.,"+XY=(U.0L]NK'+'I!0<*X+*9==3]' +MW@#?EG<\D6QWIQ7QH01*@PR.N2@ +M+PLM*/\`7="$\_JNO?HT!R:TE?5'G6`K`S-V/3&Z!$.QIS1&N45\L;M((`U- +MH*E32\%]59.D$*HV,,^J'6Y4A,VTR2C\BCW+0$KV4=C2IL7HK0CZW#7>EHU8 +M9GOC#O?"B(V:G"61<18<^F6Z&SDA#$0*:EF5\62CNX37V:^LM`D/X"5\=A+E +M[$66.+)%.1U>4N.F6U]\Y^?O;9*GRBH?3\^,%8M;IVWE[^DD_"H$98+^9 +M$\A^_5)6TG'\%G\G$DCKMT1]H"951WB7?/T9/=67D#4PHY1)B4YY*T6+4J9\::Q9B2(AK%V?C)S1. +MQF347N7Z-W$TV#&][J$)(4+W530\,C<2-=@.,@>Z[[9V]44ZBM'L[M:#H0KX +M2-#U=_VWV8!CX>/+R@(&'.12-@1N&+N_O5>^@_%M1/T?'>9GFLEXK +MK@__;&P&?'AS,VFY^TI^(JYT-1-;G;RNB'MGL_]*-3/BI\0;CO_10KI/*`-O +M\9,@'P(U@1Q32JR[G\[H@O>\&X4 +M[%-M(%&%M`']$>4C;#]G[WX3T<>PMG28=$[.)U"-0);>@N5K95`MM)O,-V.2 +MAI4F%MU*D^J:)U8,>8HWK%E;9!]H),\D$'ACU`-IJMF; +M>\"O"MPT#KBVDM4+)3;"J/>X@8YR4"LCG5QB#V73#E&,N+U^*Z&UQ?NC649E +M#=IN>?\F++(NZE!IKE`V)I[L/B57J*8NH(=V;((-9Y[3ZG#*KOW1IJS*!M-Q +M"^LM)??N.NM!`^J1_KC%.L-:K?FJNE[T?,&NDFT\W?!J]@V#U9`8&Z7*D2K\ +M9JZVO^_EY(TJ-%;+!7-]RJ:GSCWRI_/[:N3/6KS#^;(I<'=R%'&"YIETGM;9 +MOM^BXY[0^-U5K\1+:HVN,#47C^`89:+S.=ZO +M*7IW8GN#>HWB8S:J-7;0\#+VCH#%,-C8:-9_0=E1LF9O0U-"&EVFE:B.N+6H37RW>&>71.'ZX*1G +M\;!4"1=[RCE):=R&0"W7HB;DQ).25M+QLE/)<'SS=<)$C;D,'A3IK&<C&@T*S"!J?>Q#+FRD)>L5H:WN:Y3:\(O)6WPB)?"#$F##J052!K^2Z@K[ +MT[OE%^=,(34Z5L4/9#5>-&1<'D!!+Y9;Z5N-6*)!<7\5?UU5ARM!^0;5#.6:9\`.R`I4OQ(J`8NC&!Q#]N?E55([;`0OL]5[HN36?,W +MY1GU6-IL_B!8^-2OY+_8!2]F/)@\*9#I8`9;0IA*L(<*]Z(*++=M5Y5Z,V?! +M6O/%=S/J@4003MH\L*'W(C3%,*J/#IJUU][08Z7[EE/&H$&+-B7HRJ28O!V- +M&#P]DB.=ZY^2&!O6,93NQI6/^!37XJC7Y.-=95?__[M=?*2T!XHEY_INL.RY +M<_[V2SA*-?4RT+:YHYCJEWPP,CN+1HS)_KL0O=0DD\FIKXG<@TEBUQ"2@&@& +M@;@EF$0W.$W/!N@-?&8&>RS7>1?*C?MN4OU_RO3+=4(?T@^31XE'=W'H;]JK +MNTU)GK!%CB]Q1&Z=5L-\CD"WL0+A`VKKB+C$T.9H"-]AQ,]D4R&-WI%AP3+F +M'G66F:G$_,L.^;=C)L3M4DN6;:,+@D<$R$P[%(.Q=EJ^P*BO;_>Y3(95+&?AT[%&%3GA(%$SE[RQ[W+(W*7CX@/)126.?*-@V4KC/: +M>X?A:(@1ZX602W!<`SUSCLLU:)MF2&JN[)M_DT`>\`(,4SVI +MU^*%%&?Z!HN(,/HHNB!2J#7`[5WUH%TSS?)+@L.^RBL;B00Q!Y97-E6=(Q<$ +M6]9/`(-11;$O&P'9GY5'KD)%`TDOJD]R5V/&T+G9$DC!J,_45FTY>8-,1SMJ +M[R:U,H2@<0K5G\4B$UX/D;7_ZWW+";YTL\X-_RP[U&=R`+M +M.G`,@28'_O#`^F:8.BDC;2<^P++&](X%R[;47>D3+)ZX^DI,!E^ +M5I4%8K@8NI-4R)F3+G,,]J!Q4,!#`(<:S4!4J(5"_6KW,QM:>Y0LKX>WO*S) +M-O[^*5!+^1LYN0,NI)WXUP!+EU:ZR7M2&0N^N$7#-&V(&?I6-V_2R. +M4M'O0,SNJVFR^TX!/B@;G.R+L7\`O?GPUK`EB[B[2[1G*NN.-3_.*R(,![W& +M'VNJ%$>H9W^:4R.Y8=*9?U#S_CZ30:9D5*7IE2VO/R.?H;-!M;*]_/1H;Q?/ +M`91=!&:X`JFZT/W,):U5#Z/;]#['78;/(194[.C20S%$X#!@H=A/`O-;?"/X +MT,&<;06*+TG4`JD0_7E`C*%>Z^)46PUK$G\LJ%7@M,L@RB*TY%_'6NGJ.Z+R +MED(ABU`^#8*JH.D9/)'G_CQNX.3--O:6NB2F^H(T[]FLUSTEGF/H_C@[>@OT +M9WK2[%UG^(!.M;19HJL!!XMSD+/$Y5N_I1EE;P[()Q4W7\![%*U^!5.6*(]2 +M51TI$WZ-+'S0N1@I\^`-Q"Y008@FC2W6,CD+&A+5OT%$N;=MK.QB8!"&Y:;(O'N=,7W1EE!-4^!Y&D +MIK%!XB1^_'TH1J%<)D+H-'.?_]!(F/X0V14-&I_4T4FF*;_T&GZOE@VHV\EF +M">TX\[+F +MK?15\X?*<3S].*!N-G8WH*GU4MUG[&UQNCQS>VP;N]C3;(7C^I!`;:IU8#,A +M4V6O!"L4+<7!JRZ-F9[')M.2#/'R>J6Z-B5%2M%=SH9:Y< +M;=GL+"_D^Z=AP'Q:X?&!&&J4D=?R90JFP2_Q*AL*V3<+2QA7TEDYRFQ3\@L> +M5W:Y8+'`]THX03-2TG\IW@-%>U`G?WAK@Y3?N]&()4=7X_I.&PM8+]9H$5B9 +MR[LG:0!/9SMB(%Q<^$9J.)B']5%I(&8N4../NNL"LDOW[=5-S`K3R[L1D/FS +MFT,Z1@?4';"91ZQ/TK#LJ>G14D(DXKA'0_VP.`63JDUA#BE(:S6^Q'V$+:[[ +M_#8#Q@.#;FK]:)9V!M-U.0Q,K<0\W:BDXYRIV5T<\/I$MU*4!R,\.`NO2C;T +MYPK!'A'X]/QB9&[J44]HS@N&X3HY0/UBD:K35IKA>?9/VUHD-+C6G[9DV/B+ +M\K28-C1TB4XX*&20=]K_>:#ZDUI-86@(6TK*`-&W^``]!GPS#&DN-=2]A;P; +M>?QX/J4W*:2+><>O:YC#SZ6':$$A+\I%(VE(I3>C$^:`$33'GZ?9O\A`S2JU +M)2K:Q7%:6@,L?!M)OO>[92NG<`]H&^Z`^6ZBL!#IML==_M%(.0,\^C07"X-5 +M;O5.!J[G0O[:(R]WJ5UQ689SZ3!)DN*0Z]JYE^_5BVI%V7XT$*'NN6]0(*FD +M<308]KWIR/*O4Q3*]QS:0KJN24+'2?2-X?"?TTB^;QV4=2!QGW*]4_]-;*;G +M21.`#,D,1&L;D;-4"]SNK`+Q1,HUG==JY_'#4)F!;#HKVET=O(]0URL62C8EOHO`^8(H#TV?I]VETUJH5Q8`@Z*I&`)E^"W@(\6 +M"/@5,=W)!PE\>KBHQP]F;BZ*Y"O(W,)!I9I@'F'\]$4VLKI.;]J^IH.$_NZA +MCFQI)"PL:![*H\\-_1KY4L4]W4GAI(8PE\BE*&5=F`>6-VX-H!":).X"^YU5 +MO`@5NU*XKNED&\`:8?];F,!:%@4;!74YK*M8D(+GYJ)$UY2)_T*HRQ#<6DY2QQP^Z +MU3Y=S53X@$K)TYBNRK"LKE.NO +MOQ_!B0EO;Q1FDN7+=#>Q.'K]Q1,%3W;22_D``_VR&L2@)9N-.((8P8)A7?`? +MXDHM$&:Q_:R._TP@CKZ,G;7N/W(!VAL[6@GMM03DD,:CI=%\@WJH\70LT>ZE +M['$D)OXV>HP-(+DVYQ`?FO:/?[4*`TODSM8AVB"CT*;N/G>\$I;MIN2M5,NK>7\JH&HN"6+3W0%J +M+IOK^O1I2B!^+%@W%T3QYW9DREGN&1FRQ.9(F2-H)DG9XS`OBGE6*/;P@:&. +MW[MT\,F=G$LV".C>SGBB-8V!4>XP5V[S+B!W7W[X5@S3\K0\MZXM?:S>"B/2 +M^')38XUVK>KH2*$+0/+);$=W8VO'/9]?GE)ADV8@2NA@$`3+BWS*+=!C;JUD +MABT]BHI!869=@Z[K]MVZXDF2IW/4"*WP1552XGU))2>96@J6K+7Y,^E/ +MJ4B"N@S?JZ$)K*=`>/B_,7O0$Y:]A\[PBW +M_J,8T4X\EF%<\9CV=RT+&KWH?3"8CP6>4Z7#N9)6L=LI6YFV)*X4^E3&;D/"E3RWO-=)>>$(O+].WZW<$O>\X7?]='`35F/(A] +MV:(L-@%L?(!JS[$'!$S%6E,IQ`Z3JFK`ZSQ&MI.4NN>0W.-=U3(V]D>N59^% +M,B4*VZXI?)$,8X755%"OV!;ZF>HM<.JL#R("Q,4FM_;&J@\,?J7%8I@0!`#5 +MDT>(A+!NB*!\IG!AS,:3*A7;PKY1(]UIR>=7/-<:%"$3?IL09A7ED+IP8L=: +M,UCU`'#Y*T_I?[H:U*B4'Z'>?,Q\"A!_F2<=4U9L/:8X\&==%Y[#KOJ +M8>-V,^%R-\#2BSF'ZE]=6WZ'.CUS6>!8K#V7='0:>9-4YNWY]?HTYY5P26+E:?..=4 +MQ6]FL=I???^JB.4Z0/&CZB6P8B_(<]IZ0);\*PP$CGVGG'S;>O-P__!4N/&,#;_//G`UZN'K2P5T>^:G&P;O#;\1CE.;BS+_:*191YLQIHS +MPAZ"%CNA_Q@!@]\C1U3\A5X)8H=>=7*$8X&5SHVM*ML:,6 +M.TRWU6!)94EG$5?(VRDU;X>/%,EZDES64)TFI>P +MY2D4YNPC*CT;)9O!M=N;0Y;J=9@+[*WT^`PB'[;PU5-D41[N3CJH%,R\U,K[ +MD]+L?!!4HU!^*2C"7AI<6VH6!W.SOV'>VNL\IBV&[PQ;8V[`G-JF]LP3-(58 +M64=F8R"`E?_#5C>#Q!=P2BNRQGEVI1`N0ZR@D;!G.,DMLG#'=F,J((010ZS( +ME?:@>#1_S!W0`MB\Z/R=NOY@;C +M/8`UXE]P5(-7A-\>1/WV1)Z"X^-:J<((*/3J<7CEUH:H9US.\\F:W8LL]/C; +M(=LOZ!Y)><#O!8=PA9&O-8L1X3J$YPNJW20)Y?O_C0?LWF4PCQU)WI4-7A4F +M7;:!&&?UV+=RL':IV:[A`C)>[$C;/L;'%%P-T_FK]]HM8$W[0:>(TXF>DJ5` +M0_/K$\$H>X)T@^!(1F-:O0`)G?".,A"C4X/=G>^/?%,^[J%S1DO#*O7+MU=I +MW%JV>9G>]'-8V_:U08V=,@9S\H/#`=KR(J01:\X34A[".R(!/`DC?EE=@7,> +M&XFU\D0+:^.#H>\P.JU&:];& +M>SZ2P)&>]AWSW4G[/BC",X"!P+,L8)98R\JK:HFM".-,;JD`TYTMI#W)G5\Q +M/YW>HGV78$S\MY%!P!6/2!O[Q<]@U`F,,%E7U;(Q--;#3,$&4TYG*AKU!K[/ +MW8^1CH`T08:>,[\_DB]NN;K'_4/PZ`^[VB)"KPQO;55@Y)B.)KW3EY4D'&,>8?E2WRDB6@-Q9>/RJ6E(#Z'"8RQJ:9]U/\H\#(+46#= +M(KB\WG.,6Q:L5E#\P\1U%Z_/699=;"YN:"V41B=5B1&GO'PSOMF"/W7Q5IZ/ +M%5F*G=O.]EB:]O8>C>^9\!K8_;VZ\$HX\QJ+UEZIKK1] +M>>FT1\@X0,BNL0+0JP-)R;>%T4PY:1SGI)AS_=FVL5UY^@#(7UN:GTW_VO:: +M5M!^":*^/P4)"*AK>&$MK$.@"532YJI$RC_8.<'ICTA"M5Z,+G`-EMZPZJ2> +M85CZXR>/'66F3<9$KUV.#!@S`52"A8OT\*Z_UO:$8$*"1O4Y<[M/4SSI5-CL +M%^77/M6DC9Q#_\5/:XF^GV5M)O4&*06?V3GB#X]SXSSBPEI+R(>0QH*%*ZB- +M!WV0@1F%2-7>729SO*,JN_56*_1F?%/Y@UGK +M]0S=5W!K)Q=2-VBDO2^IMTPJJ_3R]S">?U\ZEXC@=HP'TVRB'#T`JN-F-DFE +MQC+@BZ^TBFT/;8'YSRVR=NRG\ZM(-S.<3XLM7\-TFJ!U3^W@8XC88)7T=9TC +M%S,*/A&#K,9?!&%H'#-FD$H!CU(BW@)C^<(6<`=+'B!$NV.<#T^7P'W$>('6 +M8N'>F5+/^D*0X^@J'-"G_ZM2GW3@@I?&T'>6J^(O\0LE+Q?0D1O=&9MK12LH +MIQ'ISR!AF;11:2=P#.:^5$_6FM1MC?KD,XE1G)P2Z40Q35'9L-0==Y"E^'A"6&KQ, +M#7AEO67?S^K&AEI$/5\38&V5$:F4BZJZ#8O,Z9&2BE)*>9ZS$N', +M!9F@"7:R?GG>%N@DQM<+@U"5\V^3SJ5PN*UH6W'! +MUKR*%P0M=KWI6Q53NIPF"FNL(0MB0`0CD\8ZLX8:$_&"L3:RM.$'64XFZPB? +MM,+(!'?OEF6#)KNDS7=D-<[>4*Q^62/N'%.A7WU$;03-4B=289P]O8?@WW') +M*43T74IP.[!OP&1J]HD71$W6((3S:%S_SL29_.7.WDOZT)P`4ZU#!MWS@^$@;US6NJT\4G4WM*P +MMW[&"DW(@%[W&="02O>D)Y7>P9*GD[=CE002\%NNJ+5%S:5PB8B(=:OB?6GB +M);-^!(RGD?G0'Q2W`7[NWAXLVL`R:09IEH^^&-53L9X''? +MP2"0^QL21E?IQV&1+N5@,&,17&MB)5HK8N1ZK$_#"@POSZM#H>NQ<=50E,Q@C_;M]Q86Y9*FE1KM9L,@ +M?AV>1O-=Y/S6'67NYFOWBW@6.<'5/=LN!DG&HFTMB(975`:X$-8&ZJU1S#`, +M0IGVK$5&RG#,)0GS(-28+FQC!4&*C]+&1.NBG$R7XR;8N9ME+".,OCS,N/8Q +MP9,8<\Z5:1LV4)T(WSO_@)7IZGV5.*2L>R!39"Z!,;\`H=(?Y+*7<;"]Q.&C +MF,2RY35M_\=%_\!]6.!J`5K_)1VU*4[-ERS:.Q5AWO4>%/QK:66IZ;YK"VO]9V&?D-_[[0GCS_I$9^"P1/,+)YI]]#Y=GAIG+`0% +MS:HRNR?`",WBK$+V*F/S4>N7^!%/Y,9IX9%-)5]67-3IKN<(CN[DB>UPQP,IG49T#V1&ZB<;M[:WMQZZ>$5WU$,G#F.;NS +M!MKK4V(*[VTTO*!IW-&?T&&J?PY0<8P\[V\59<,F[3_+4S6J*?1ANIPA-:2$ +M\&!Y:@DBW\.4VU6V5P[]FN%W05VE9WH#;ID3D)#0>2Y4BXB=_"H,1(+=[%I4 +M7FA`0,]X%*0/D/,GOX(8XB$9SR\B$D(N;KR]I_UN8*UVR\D=EP*>X1EVAWT*_T( +MJ-/E/55RZ7]O\Y:'H3].=\:V4=/M@$LJ'HX1F1E![U;MN0W5MMKA+I&?J.AY +M,26'`MR+%%5D:H5QIV*F4%""(8IWM'IENT3(LZ=:1PF+CF\[F#;2A4#*"4%#)!B,Y<5CD@$"*(.;+S(U`(@LX30F:/SC/<212D=HO +M]JBX1W_2O?KIH:-@]DF_JF#UL>-,QV>+)R!!]%98$$FX&\UCC6:%;&PNZ5>F +M7FG5$?$1/;:1\"4Y5TG<*LUO[')T:4QS\4)2!R:U<( +M*M3S3X/JG.'V-!U@'-X&GGZBB7GJ"JUNS4+I!PPS0RO,,9US6+--\E=X2\N_ +MI>V#T;5'O\C"3LP@A1.M-XD%\';D#"__0AG5K^VQM4#+7K)O^K>FLC_KYM5; +M4\9_^+R>YYX8&KZ:[E^%D,\":`*D713OH/.(9Z&B;%"?Y_K^7]U:&_RJ*J(' +MF23N-Y:$U4CA7_W2$&!O6<&C4[`#)>/^K218<.PMC'C;#^:7!Y;/>._]8Q*, +M$"3[-Y722XKU=G:TKKHY_VIV*9-#CDY?PBO!Q-LK#8O_?_A44_0A+*%9A86QR:^Y1-H.Q]JU\ +MJ>L+SACTVW]7#K=%+3,[*>N'A)14$C"@3U3&57P?ZP'VWP,+5/532:>0:I#_ +M.^D^P==(CN&?36([.R6MD-<6GO\&Q/7%O?O]5Q9ET2C-?YW\4JP)$10?.O$^ +M'Y&+R+WA!FE;TI_N0F"U:@Y5[BO'1*B(:,N7Y!PEV)11C-F0>HVMK0-1AD2QK4+1Z^82T4;E5.9>L[&F@0X0D#-\,N +M'3=(9_;N\K,D,QM^5?-ZSA$K#7[*G-HTB0^M]6;\CF*Y+>:WQO2(R*:3)[A= +MB0]AG;?8^A,QYEKH@(U)/X\_>.O,_RSBIB0GZS*[U>RSJT64A5]>$ +MNL=-YIB#4,%UK,O1C,S:_#N;^!/2%7FT"/_5JDD_'0MJ:86 +MV(ETNPIO^>9+/C(W1V'X\G-;>*LPD>Q5$+X-$G!TPTO1]?*J&5^I\S:UY=OV)@ZH3DPUI(=%F3UU&K(@M +MQ8H2QW?V_:,HT2FBZA]1'?&\Z,!QT19*;1A"5),QV*3`D;.[.T*FMO'`[3"0 +MPL7O+HWFX9QJ#Q!]EA[U2^^H$,F!VOR:]SQI)PIX99P"0#Q1*""0LS]`19;$ +MY/:H7G3W\D$EJ*I[!;KSI_21#[YAF,?Q?G9`#1DP5];&IS:>E_`#B@9IF]RC +M`V,9R97DXU=#=^C]7$Q$L`^$K?A;4_'C"M;"$W(DX`QY:?"XO8]YWVMQZ"V\4)$6>,W)Q; +MR6_D62G8`U:\AJ^9;TIA145SBU`FDB(ZY`EY7!)HIVLO#D]?`@W1"/5&@6-T +MU^5\VWAF@)(\UI^1&9[I?*38Q]R(/F7":8F#VQQGVE<`[*A?F8(D`4:':QL' +M?[\07I,Q%+SW*SCEG7KJ+N,2UQ+C)#F;1?$38$]^(]/.>4;KSNB@EL>8Z74? +M#FW?6-Q(0&,8+]O8%^+?(EZHOOP88-KA@!Z!V,!<'D^R5!<=P;.;I?A_GMT< +M-GL3ODUK:W6D6GY^@`2A!N48 +MI>@C.0?#1QEB^GX3\GI-9%J9Y2_7Z?@3WUJ!&=8/P2-V8)U*)D,"JD$\I':/ +M]DW[;:T/%SLC4=5W-H=8E5HNAT:=+#&9#"RA0[@9F_B/J;[F4(F8-!V1W!`' +MO`2Y./]/)DP5\1PVB6#]M)8_4]K/_P%4U+&83K2E<.:A?BS2_.=ED+3-U&3F +M%[[,D2Z[K*:^+RX>@[H;6O22/#UL=.)-J2.$6)XQWF`)'B1+;M7G(;J`\BLM +M_7S47_%9WJ1^UYVC&O.\0N(^W-RTR96E5;LRIAJ0,\(R*!CYP,W*Q$+H5^&1 +MO'BXW^':[NPT?91:9E93?1D`WZU0T*.%*\FK!LPV,J\H$22Z;O54K;`$==5F +M[&'N6KVN.\9CAE9*!2U05%2)82LN%49I'DAK-+8*5HO2^.B>LLMW4WX"/A./ +M52?=T+^ +MK:I`?[-<:TX$8-S,Z-@EVDM$I71R90.&;H%L=`3+2S3L^]RCB5HA19E +M11KDL859IK`_:)P9VZ.IC6T3064!C8I+JL@->^M" +MXPD@\>G"GWQ=!V.D-VK6(@2C&K/3)[T=.B+'\_)WT>_9_7Q=-!2R2W=N3V>A +MMR4A_NX-FBH!<^?$&1]6XM<)VC3@YFJ<)D"(*WWM;9_:^19W&KRI+5>LF$+' +M"7)=9`AUC/,%BC4\)L*,;#?"2&O7IPWT)`Y%T7W^]*J@.F)]V0*HD]&HP>`] +M'C& +M!TAWP&JC-^]MJ*_M[O7RG7_XMYW&Q-0'W@6\8#L3RBKWVZ2KC$C):/,ZKB2C +M_6SHSN[1!U&7[L83""):H?S6%X-I(CBI,:#GU]_+)K4X5^!-U08EDCWSKAIS +M4O,G9#6_E,J(=Z(V4\YBOA;[D9IT>_6O;)08LGFHG=;-C^'!YQ+$LW@[HLL' +M\R`;;>N?F8K2!N$JE:5F7S:GE38Z)<6R1JO4&$WD="?+),`54.6@V\TS6/R2 +M2%^.T?*4^51K-DF'AKGJ+W02M%D`_10=H[;C_4#]U\BDWI>&&NY'T>4&T5K+ +MRR'F65O'TZ$CN.1^3F)LL#L!PP4#FS#-[!_7=XRSZGI.!Z(Y2;^W;HY_="`3 +M.:%R@ITCSWJH7!F21OK;B"H%=8.$!-#8(Y>P`5TAS0T$,\8E`^G=&'71?NFA +ML5W/5(Z$NPA&%P*$(#Z_'6"8X=FH1G_R[.2,/R[XJ\.@'+SB#O1M<6D)EAC& +M49IPROCL6&L4X/-VV8`A`N-9;YR"^&/=/&@XQY-^!CR_@!4B.Y)4J +M3PXT_E'^D'VA8&Z3XE!6CRF=YS*"QBY0TB>CDR@K@1D0UA(5\60&%MRD36+* +M._/C)+9LL!'XO-W(WS1X=(_2*!T1:F#+%+"J;G2;5,.$WMY9JV6B=3;8[EOY +M7(Y<)"/.*'/*3%Y*22CCCYAAQRR,5$!0Y(%"MQQ*A1>TT$.'*7Y_XC"^PDBK +M=%2Q:C(->8+]'UW=/89.BRT2>^-E1G$"VU]BA=NDW4T/_H*=Z*<#H1` +M?"[#.MQ4=S5/MBH0"(FW:(I1^FAC,]L%V1YE+(E0Y!PV;FR'30WJ5OS$]+YK +M[(79\#$O1CV=!/H.">O1;37B7)ZP\J/R0E?VN:I@C\E2[_GO5[#5I,<)@7=U +MSN$/*H#U8)VN32Z)^9L0CK#'K!I)&"ON=3E"E][]#/FZ%H^:CM'P#M`2V\QW +M3@^%Z!5W=1P^L#J*=M1_71W*(1$H4KBHH_.]-T/H6TJJRX28B0\1$`+;!^T[ +MXRQX*@\+R(-[%^Q)FF/"]/)/'73=>CTAU<.WL90M,ZO0@^_UV7%].&>^\0EO +MZT9$*+( +M#[3?'+Q18>Z>G^`HLM\U$:("?")PF?C0( +MRP^.F:L5WY(A482F%Y:M`@ND/-8:"-E^(FB?J2Q81.?BG"9U'=A>9\+/Q(?5$+H,_F]8[; +M1NN#<(3P&7H.M74',FMLK(E1)26T%',@CK8B&!VOG@WB@IFAH(%R_GYQI481 +M%E?75AU]ZD$30KDS\9LEYCS\$/&\2UP&`B"B1RY%+SX7.A1VD4UJ +M]'J!(_#_CO`8_3AM#$EZ)-]7`X`O1I&+YVMSUM +MKYO-S2G\VJT^6;\L/9Q7'A22QC]P96:P)RGK#);^S[N3YSLIP+[F)//KVAB* +M2!0AQX`IG5J/BLX7PHNAWS`-[TQW*#1)Z!/J4^SH-I&!;,W[.P_W+H!M%6Z! +M6<-Z,:S`8H$=]A9U*H7'\45Y +M?5ZZJGO?11:\2"XAAJI=/0U9C!$-"YWE-G=IC*:"ZFJ(IZ,+.BF_7$>KJ>M\ +M7KL@WD(^0^@AIV<4R\:$'C?;C\%C-S@I9"1MOX[A'B>^13;?+^IU\8(@$)60 +M,B+8J-HVE&WCI_LD`%0Z*278DB>3?GED.K!&1-#_W?Z>=/_(WN5D`1Y#7)*Y +M'F*_[2.E6P +MQ\=E5.LB^#]Y!$^+<1#I=6DAP*W[3:@63`[;;7D)(YR!W9H-#6JW8#[SD%"\ +MS&\_H&;66GH7YRW_`#XTIOZ@/M\%VT#TX<\X<$*&:IP,-Y=JLA5.SE>Y-3]4 +M\IP!]@DQ*MZ.3IHE^>(M$,#(]>UL4^1Z/Y@D4:I(IC["VLS-+*TI13)>O3/H +MUDF&[EZ:.Q,Z-U'%3\Y0V4!<(U%L:T1V2#A'?>""X0]*UN`9@Z%N"_"%R3=D +M@R=7QTUI17+A)@G^M^YFPNYO--<>HEUK@OWF># +MYO7BA;?R+$P64\.7T`L-4K\##N_JR@%PJPO=#%3TLO=Z?*)0WT3^VG+I#*%6 +MT3INR'),#!Y(HO!'8L(=VI!_O%4!U2%#NSFM.F0*4+&IH2$-9]/4"?NZ9C0' +M^<3,ZUH`K.K5_W4=7)3$B\:RX"XBA^6$=`G6=?O!4D?'H[B0W0T'=L4=.VP4 +M1:@:?-:9HWYX[6:0'7E!HQA%,>HML&1Z#??C_Y4?JKL1111A1RB#'#+4:N8D +MP,R=)K9O!F3D]R"..BY:9Y(R6'#,*H(ME-NE.U;CR;P;=>]#+2)4]?24+JZ1 +M8*$RWFY&&I[;%$H8AGUCB6$U6K-LD*X[`*^+Y#]K,_M6M<6;:KW1,C@QD6H# +M.'RKW\[1VVE?1U8FE@?#*H^EJ+$!GL19%[R5+]X-X?S)BZH1C2KDYDR]SMF9 +M&==O=OCIL29Y4FBY/?;YA(%N("CEQ#,[Z$-$EI@&+Y>)]IEQ"Y*=%WE,#*^X +M58@D(AH7_N17S<9KA]O>+5+3Q;WYOF\1.QG8JT=:.O-$JS5??:E9P(TC.=6H +MGB&RAOTM?J)J$6,\Q%.SS(N6A,2Q?=`5L8K.C"IM?'05*'=AZ;#&N<8'#'6I +MNF*QF5P'O*LA"#Y"E!*!F9BL:Q>N,U74J4O*KKF./4$0-)[,QEQ41,#D+V*_ +M?#O[[(A>%$E"V#[>_SXB?:A +MOA")4!E')!<.F3GP$O%0!EU[X2?I(PW[?7P^U[ +MRFNY(5K2ZS]HZ>\K[K'K##ZE@24@6\C(TGBBJ8C)*V%'Z9S:#[QWPL"!Q`+]/*2^;FRQ(M*8:&`H^),5)2'D:7P0LC5;I01,!6\VE/6';/P"([WL.%5MU3GAP\DY\;XR>14T'S'9,E-2HIG8ZEVA+ +M"C'@=]DE_O9GN#76P174\Q`DA+>_6=?B>%KZ_0T^OBZ`4&_O+?]TVF?1=QNE +ML2#FE=#*B)3DT?[WS\T/K1_*&V1EN9Z15'N%4Q$Y=V#E?37^:(-87_TD[Y,, +M@>!X_P>IU'YGQ@NQ*FU$T5E5)7YV^X!JN0H7\<\Q*K(RCS_Z71,35URPW\/"<>\P5]5(^^>Q +M2.]E0%7R/MO#;%B(7^>W+"#*MM$]V2+#"+YEVH<)?]QF:49(WC.]:*$=GYW` +M%=BT@LEOM:9*%O'1;O"E2:#*2W2/"W"[XTF!3!,84;[7P;:ROW33KBDPK6QI +M3E(S3`RIGS=/^&!#A.N*4ARZT6A7[>QNW,`"\6(E'3?WT.B67S9I?RGT.7`OVD;ND;_V$,',7=.28>XS1&/EB:`]G1?RI##0G='W*_N/ +M::FD#+;O_G7J/&Q?RLT0\4:O_L?H6W8ML*$F%A3,[&[.20)Y +M>^#*_?8)3)#'E>Q?^8CCKH.Y..8!BFO';U;A2<-"%!_$;T$%6"@;*`[Q;7B= +M0P;#%22!RR5R%DC0?]>7$%J8<9N"J9ELTK_G"M%IVJ!'L`5T!TKF!N0J!!O` +MP=VZ#\:^<8(1V$YP$)U=R@_!HLN[:`OMPOR;AG,P96];OYAPB!8K1+XE: +M->32X%B3JJHLYC"?C[(AX9^T+I&2A+\N*S'!"_OM&:-'H0D_W"U[@_F8JPFN +M;),UE'W]'\<_?FUF2[%5GNWL%65;W78DFU^J_JTZ+IJNF4-KCOSO.M-PF$2( +M_W*+DP5%9NJ$:^"_S$Y5W;-=L\#K.);<.%T)9UP95C]IN=`!50GHV.GGLQ>X7Y\99W`Q_/T8;" +M`%V74,(8OO]'8/7^*GAE\5,S(N;U+:V2W#"?5-J?>*>>6_@8O[:8YP=^IAW$ +MC91YTE3'J<+Y#0>C"ZQ_F'Y3PL6-X7'\BRB4R$5G@AKXF0&H'<0C?JK1@]7= +MQ>M`ZIY5GJ;E#LONIM%63_H2Q3\HX!WLX%:?49,:.8[&$2>-+Y54%HZ#_WI^ +M1R;0<5"F*$POTVO^*=N3@\G@`]\"'!]CG6+C,CMM-Z_.S_*R0O7:E9?9D9:$ +M"1@L82&38/$)>).\F83T2K^-X7U7RFS^U;N8"T#L'083]59,53K2:ESCE6=W +M`,7I8?)]]%`EI4ZG,(UGU?S[[Y%NB$;G+FM%'Q=`(ZW1_P5WU2(2/+XW\R]S +MI-@<9_9NPS@_`J97RD=>`*.\/=JU\/6:%J`ARN;WD/[7N2!]P: +M'`1X)+OV+"\Y=0_E?3Z-@_@J4W#Y3/(R]"MGS#BT2[ZL5`25ZFT*B(K%#4$1 +MGF_>`H8Y;1NYQJRA&6_'!^`A.B#_M0[^:_C[U +M$6"R7K`T;P2<8YY,=',49UD$9G`XC40X_/BT!TJ8?$,WKW@>L6@,0Q^>P!J +MA^5P/U*B$)/$>X4;\I\$#8WM<:2#:X4F&ZCUP-Z(WIR`BVHC9/[V$6VCJ&7K +M]#.%OLV)L=6@LC=(#(5W7(B2]+/)$O:FYZTR)ZVX37]^1-8F\=7`2"X_/3U3 +MM;M&](=Q#.71D,&^AEUM4LFE`>RGG#)6QBD."3J].J<&79J.UOR^(@C`5Z#% +M_&!`Q-F[BT.\/'`,VN!3ZKA)1`XJG#71O/)+MQ+\"` +M,QG>LN)PDF27RE*7ZHNS8RN10I(2F`FLLL4NZV!84XQ_>_Q&P^0/8X09%O8< +M5DAVP<(2X$\QA:J[_:\,_EPH)PF!?L?'+9J%?\*NK";RKD)JK%26,U79=1=$ +M8[ZT6"N80Y-U8=Z>8BZ7X00Z!`ZQ=`M(7#!TS_!/@B8@R6;U-;0Z;=5:L\"> +M:&8E.WXLI@;[[JZ'OHG'J0(OWC/^*7&OOU=#9;67M2"L.!P!C6=4%?72Z7YJ:1UVS,CFR9:E\.G<6_--NZ>#H*18AJ":JU4AA +M.^]%0IC&[MVK.(LI6HA3J-]I9$B)*@IG?7K`KDH:I01V,0300V* +MKA@DR%!GQ5O^UYIT`UU4%',]R#1;#G[\1F2TLAVA"_PG1QW/5V1J("37SGB+ +MI-[\%"]/<_5>%D1C&6:]%(Y`]H)GW?0^4)(3O_Z2[R.S31&%KHB6Q#%3WB4A+^^5\(&U?]1 +MIX@S2_JS9FT"D&HJ+"SX>+T.3)*7(YSJ(%3)DW@73S\6:9RFVJ=NE&LD@=,) +MAVNZ1Q2]P7>?WX4J8`6L5S&:.@.IJ";EV)'3(/7G[A9*L7YG>C6O:=.$/'Y1 +M>57;-E4F,+LE/`/+#U'EHUBKH&==589(-C9-`'*%8CFL\[_!'&'?]B/1#"3NR`G5D6W\0D)&]X<>PM`::[[3[0>@+S9 +M*BKIW>"W=)]"X)XXX&-0'M"[>QIPRC=0]E&]3_,\+)U1# +MA"Q[YKHHE7[1R`ECZ[])PEM[S_=!EJ[W$<)1'#(J!CP7N>/I&W[!]Q5VG,!8U1Q6+_,\:/.Z.*A+AW3!P\!G +M?0-L0VYC!R-[%H#P\3\.]"C7X)]7J*`=5\H-NR-4V\,LF>(ONY/C+#02C-X% +M$;E@1G8.'F]2T:F'G2-Y)T.7CLR)R\?/(F;R]8-!?'XZ(MI)I7J7I,V)KQ7H +M!,"+>@5"&60SY`37\NL=K]*=T$.8WXGS6NW%X\3OW6O]`/=II[B.D"AQN0\^ +M?3>3]QB7?B;FGNMI>IT(MF/CMMMQ5D`$M<@4QR(KH5[GUHS8+#1&5;:R2T]? +MYJ[YO'2:'03;'`U`=/&%^0Q;'W +MGJPG,EI,%1K"6\Z-83$88EQ%X#P9)2/7(NR/^W=#-8ZXIBR#] +M$U_\?KK)@_?:C4YXP#L"R5Z,!'':FSJ^XSMAHR%!H0B]KMI[$X*H^WBSR&PL +MLL"^O@KR>)F/OO36)4RR9*!N618F`VF%"$BJM^N&D8]+FVH?!O(30'_)P*EQ +M4NEOLI"[-:X'S%,@';!<00Z*B<6C +MF6 +M-XWON-8=9DB>!VO10@8:5`]$3Y7%-3-'GZN/GT6&X<58::H;U+"6T!F)4H+] +MAI'=@44Z*)(',V$H8+*EC%$\#IK^$FMUPZ)A/VD3H2()@3T6FZ'N//"BT('S +MOO)/RC%R;V;0M+06':=N#2T\%'L,?Q\"-O[?`DRL#-B!X%*4P:6/_>;V#/^R +MDD^@OU__K?+^OA1!VRG:/NC_:+\72ID;G=,$Y,TO=@U4OVC&;J/SH[6\SXT> +MEJXND0.#F/)[+9AZGQO\6`B.2`3]#AS5N-.NAY].2IEV;*9ER]BMCJ5/ +M:'0MV3ZP:C9I)K.I%#'O^PW3<69E/=^VKV1Y1DZWRV'_B_'I]U6/#,B+ +M+MID#LZ(C_%KD'=H^=]#O"*#>LD!=C0K@PUQ5)R6V$V\:_ST>NH^?RBKK83W +M>2(>:BS))?!<92_0$(^R&^%O'![RVM$(P&QA;H;J(B"V6%1.6>="L6;3YLB\4X%!C7(^.NGQ/B*N_,H=T[,1$*Z2LA! +M!.E%>"U'G74P11W=/?C*BDO'U<;5CH`TE8S[R,OLF@:>YB.Y7NI(2HZ@D)&Z +MEAL%Q#P_Q&A6=B=8I_+HAC>*'AM#R[8UMT4:&ULS!H]KF,(:5DW0]08_=13$ +M&&9)(,1+6R$=_J*%RV2X#]:B703)NJO`[7A7%.,(YHFE&6I=5M%0)'A*YSSF"[XEPHJ&5%V0D67H&;C#]M9 +MJJ,(S!UC34/U"A7XC3LWM14Y4F69SF$!304(!I2AFQQ@FU_J,K&:/RFM(+G;UH[ +M+XZ9VU.N>2@CN''JC<'\U@*_X7%F`%\M[B"GZ5JVJ;X$YPM!&`ROS47=CPXS +M$CP.T\C)/XFX\'J?^:PG.2E_C_6\K03I-Z$(5D=IB?EQFA@Q6H&TD<'I81!7 +M]\8K#TY_[WIC`@S33T=:ZYEHFAL9$:+-6UG'QSET$$_N(B- +M0!=EJ$(@&FE+"^LT?Z^9J'5TD]B#3'$\$(]93_:?C,0NGF9$UU5?CH>]E%Y0 +M)R^X+'9X94MJ'Y(:=/J<\?JPYER%_XGFTYD3PF2'W'E&UOH'E.P0XV]@\P,? +MK^I8):.DZ.%[RC!2M*9!@8'N"ESW)/$3XUCU4:!8OU=XA:PM:LYE.<[U +MZL8YFX!6S"DXSFM[4]9K7@7[GSFJBCR#TR;>MA+57A$Z^(_YX9_BR]_R6WAC#JT_F.*4:'O>-&F1PK('^?K^1XG&%' +M^'X<4^Q.W@@#/":0$R$+PB!Z#"5!D>WK=MDD09._P.INIV_PBJ`<#AB&A3)*,&,1V!>3:5,US:2P+ +MGAP7R3C`0;-NUQ>K#M2!`U:$Y?1)7R7]9$=[U3<0%Y+OE%$Q@!&FU6H#)OT1 +M#:@._W;2(!#AM)\01NQ"?\\N;2N1JML7#;LU*RQ:@N+@_L7FC!G;'S[=/W\, +MM5K5O(XRF^\)'0I!0I%8Q[AQNM"JX%'Q]UH/(OQO*I'_A2=!"H&AD14GNW%6 +MB+QV8`3+BX)*"`0QZ\3^$9RL]-%T:I3`ZM^.>Y:SO%[L#7QTQB*Y2GK'CYX0 +M_+Q4GC39^=>_E]#&F12'2MDC`(V5A_"A!F':S[)QG$*E[\OM&-;E,RZX.3)HWM^7K1`K`/HK4UENX(\ +M\VU>$?$HA==N_&1L_+S!1+:4:_(VDC+,BK+6QF>Q(+:J^4!7WXVS&L9[.(UK +M/P52#D9+^F"6V:O#8-=0-,/X;R:/L3>BRT>Y#':\,!)VPMB#\]1!171'1J(RGO> +MPC'W3RG"E:+I&*&"L:2^"TO$4*XKO1;&#=1*R7%^H7NEE?9@E;;!A.3=>(J= +M<=I%10[JC66R:=5;AG-D4;D2CGJO5]59_+I2V!)7Y.0-^]8.:*X:5/G41,K. +MWVC4H@]6U(&(497XJ5DXVD[K?'%5*$:=`O#>9PTCT')\ +MVPSNGG"GU9_H,+#E82:F(Y^*6?]_!G@P.W#!=II:/TXJ +MC;`9\SK#U:!3R[*@'W^/%6AH)PA+&7B,4OD$K"1SMCS)3F`7D.B1F+`F9C;A +M6?'6Q-%B\4%L,:7XE15PT,AH%7+7#I=.18P:PV+I;:JVA@^H:?@VN$XY-SG1 +M1+66](V#;T=(VW@<(6=F:!RRD`1+DTCM#&ZQ7#N+[IRJ!(ZYR8O4B3NP/$9+`'/\Z/N14!^)FM_"@NEW#(.F>G2:9 +MR=/#C`R7JM-LM$?:9=&&.1T$.DB_-4%E8M$#+B=["\RNQ-$[7%WEW)@/Q9^: +M!C"BM&K,+5/*!UTOOWK`K$_S*T=89PXFVGOL+#3S@:BF%+!:WDG>R1@&YT0[7XH5#H#.A.T?DM;Q9 +M*ET<<8"W0\O*VE_(3]8&]!=/$E9:'F`< +M%YL)M?Y;YF;N^6,V\AX:.,U;W[T\/2++"GG,>YB0#D#L7GOLP(8MXILNDH+G +MXN_,#_/W:8KU[.P+@ZT<,K%O\C62&%([5"J`X9B"ZS[$N>IQE)BX=<%&UC\3 +M`'(14I#ZW6;X$8Z#8QO]GZPZW2FK)9Y0:>IA1=FAFIF7'<%>)R:8A>\0]022 +M_.\E?Z9]Z/V$B)-4]YY[5,"3IQDIJ5@*JPGZ!6FJ;8CI:LDT$7J@EI*GW\:M +M[9VDI9-&_G@AYJ#_JW=Y8!FIV,,T>)0>Z?%QQ./$3S71)9=`/.&HZ +M8?<#T55O-$>`:X369_=?C/-&2[:<>H!VP[6E^>U?$'55"'J37"&*ZLW=V4'_4H/)TE-K +M(KE/CR1Q&?E_6T6MN0C'"7<^H[":2IG[5M6QN^8=:D;6&JO[\^^S*+GJ=3H: +MMC>-4NPL-J0")E*X@PG0#6#U34ZAG27F>L&].,FWQSCO`[Y3,(30&#-!H9^^Y +MX;C>FYZJ:J@V>E8F[LN@*7/DL^9AA#TB]W6X"&58I(%U#]CI6]>9X$=0\?8% +M27*[!O<`'6C>3J=F]J<+#=V<>G(^VO397Z6AUW+AJ,NCLM*@0%^Y`QV^32_) +MKLE#M'4O/!A&K,`DS0UI*$=U)YH#P%NS:4CTEI?IX2!/N^:WJDE7)I$'O41` +M[:\AY,652%@O=7O#*JW3S&@3JG_,W:1YT2P2`"SWRJ:*28KUN$G$9+:\17,5T2Y\P +MB/"7^"%]_SM;Q>B?.N!$=AU5$8V&=2&UZ+\A[O88^]P(>&S.D +MX.,@SU2`FQ[E.DO5=?$C?_^9>>I\_(.QKB;T#?L??TF.HJ1@^0;?6%M"^_I` +ME*+LNDJ*_B)CVX"3>;=CLN>JF)>5\9'TXNSX*@SX"8\$0JI&(.VXHHIF!OWL +M7L!V[8L3Q9X?/#C+KZC#.HWXQ-/H%U;XM4&[`80Z.R2O:HX/]YWZX:B;!*31 +M]@U*HL/#+0QL)-ILY>,JUP"O%J:(XCK=<'MF9-V=F>4,#_3@U24.X;5BND3' +MNF5K2#$;0=EED76[FI9IUF?_MN2AVSI-M%V-&(&J,L/DC8BT>.OVB^(-&X0S +ML.KPB^D0*V13=E_S8(&!<$`.9-E!??E8_SOU#&5*_WH1!6+MV[VYR6G\B47I +M^==LT6#>E.(MM]Q:\C+JB(HH*_/.D!B)[$`7SO_AU;K5CO46DSIO"&`3_!8/ +MHD0$T2K%Z+#`GR8`A_AXQ@P%S.YB`I)@6L)LSM;S39O(B7X1@3&]VU,3G=49 +M:N[L%VW+=%TF5S61!`7.K;E#23(H04?0V:T!(_;-)A+X%I=ZS!#_L/$U?M$< +MYC"B()W'S]$13-_O744C-]2PQEPJ8']T(X"Z9GDAK"`T+N&IHD%"H&+G+D!: +MIJF4J=J&&68`[WGI3N$1^8Z37*3LIFTW80^"]WIIA,XNXWJPQ?U(LXUB.1V9 +M:`VU$06YZ6@"FA!#.=PI14O;7[7.CP=E27R?.I4G#-W*X_"A1SQAGWW7YV*">Y<[=94&::,7$LSKD"^SD8-S.L!A^;<3M&JMUJA[ +M2T#P/I),6T"@&X_O%MR_X4B/!F],J/.;VE;S?9F/^/3H-Y+W1K]AH\0XJ"5F +M?CDZ]GY,MZ=JL(QC9S%UL('S$&D53ABA4C2XL%6Q5D:N>I/+Y-IC+9<\I`>\F2JH4\3M3B*)S7R$M'W2UN# +MAI([#?ST2CD(#@R#XIB5BPMO>>:5`EQI!D4:JPU";T9D>-SH^3)8LOA+_S'F +M0OV67+5U#UFQ\EL(ZQQ.HQUD=&ZD.31D'I4(;9TZ@^!3)QU=506O\7UPNX'; +M1K7T0=I\ROF/TA,._B?AO69E;8;E.V"#8T#0U_[7WZ!$ZEL>IF_U&Z"('%ZF +M@)@-&%JERTZ1Q6:@O93;RD:YBW4U@*6+0Q8/!T1V1+3)8)&?E6+"=Q5$J?`R +M\W61N,8K$WA4MR&01UV!:X`AJ`U)7S0*=-ZYNT4[6FRLM&+!FY5[L\EL;[@H +M1VD]%?\C3Y-9_&WP>C16@C;.#?SK39.AW=M@1XAIISB785*@??+GK`Q +MRF>@IR__`07+D#>#VK28:"T+L'+>7-0WSGC&51_00NMBHN.V^B7:K_&6;@5C +MX(D-,CB9M1!WN5/Y^B$A01PV5`S&?U/]6:/O``44L_9E/_RP%5ACHM;2AKYN +MLB?'IKUSU9G\FE..E!5U$<%1V>B(^281]E$4S^^R]JDV<3B@O(AO*3_H#(BQ +M78C=-=\(+)AZT49'].[JH`^"MW^D6N3?SB7EG'-P]A(U;E,,.-G83%[95[7Q +M'9@B'<8.4JC"NM2$:2OCPYH906"LCS?=MDO1_W/^-?HS9;83%%]@5&(WJ62( +MH);=.OD"%%RIUWQU'(4YSXQ-9&*L0"$R,DYH>04FO,?D166*0(7\F. +MVAP).Z>^`!J5KI#,UHZT.8U.L&&P,XC(@FSEXA9N'#W)N7^<.[.F\Q]\]-3M +M$!'!CN<<_*);/HEZIFB!+)^!RFF]MP$HIFS(C8<863Q#XK@PTLCV^:^PAV.^ +MD_B8MJ<'H)T_/W(&/% +MG1$S=6S&S*]>XC7TA4OVZT!:?VA>@_[T)5__F\4CR?6B;WI^AFNE.5=R,:#M +M(FO@_G(1D>HO2.04BUEE'YBJ;>/UDXP%LX!F)_EC63=D<%0%-AVZM$!(46>D +MRVU#NN'+P\U%CFI/?_#2V`!HFT)V,? +MCF>3$,6$1:EPFD*RE-8,HI8?5_<)I/'-6&EL" +M/AM[*.'H?69)?\+8<8ZB*/C+K_[MVN'KJ"0BU$[N>A6C%A'YU,%CJU3?4-IC +MF%EX7"DK`V>"=-O#S=Z%JAC@&4):R=%7MLZ(<,#BE7Q]P-,)W&VS%.2.Q0_& +M#.L).VGPZOR.UR@_EK^O0]>F+%#KCY?15K,AH*B]L'S6W:#P0"!1CU::/]$E +ME@2(PI@L3?KIQ8T1HCOK'I6G]TV@V[X$NJQ.9KL@D#ZI=$0\K6]P5FE7>JR' +M\_2WIIZ7B-N(X>UN+"(ZA=>`HDA='XZV.+&\!6BPR'!%42)%!)W^12=OY9_. +M',"TGN$"[FDH(FGPH>,J;W0[%$7*]PT=O0R?J"L,+/S18M6<#;6I#!R$H/H. +M1P70C-KB(BH5L<$E/Z2"M.^.3-+\,DE:WJ!*E$QY=6#??I\2B8P:N)3<%%X?]N$Y$R\R*'-"#KH#:&>30D1IFP\>7FQ-'4M(&: +M?9]-\)T"PQ]]_@"CZF/.PC=0C0CJRO[FF:<^R[^4^;WD1=$MF+6]#_%.<&>3 +MZ2EN9V3DY:7H>G*N1K>9]ODSP?@P]CDQ73Y].3D;*9\+RC_1N?[3J.)^H372 +MAZ$4I2&^X!:8Z>*$9D[3(=Q<\T +MKN?/^Y1[4/_!8]D_ZA^K9TR\D@M@TV?1J3T=L0"4Y1U`5\`A?$[R>6Y+ZLFB +MI"N3SZN,&DQ'M]5N^;1I_YYLMN$?E<4%=_0#8E`*S +M19J>,8^3T7G8U"*TGXJL02IN:AA<+!I#[UWGFHAE,/)>2B8U#5$'E(;IBT6K +M[HP14*V^^V4@47W@PF%R[BVQSO-$-,K*+G888T#!K9D=*>)$SB +M4GS&:;J;46[9A1OQ"_2YSB>>CYZG`VL@L5/G2Y*TSS1'RY]NQF[R8`#;YXIL +M^:N1[I0^F_H/[_7?V*5Y/DR:])'Q_$X!F2L!,ZMQI.8+ +M1'M?Z\M;/U9G;,=J%%F4FYEFA&X"`9[*R#,$UKOP' +M39*D>O`[JJ]:`@<)&U)=VDEB[J8E6Y8E.-W\*%!'MF_W=S)?A)RC69_+O,FA +MW`_TY+7/SDZXI*QX>M^#X$]V7]I;;1M@'\2A8DG$,]].RR1I\H=G)W')-6:4 +M2=]78U7-RNV/BA(/FR0G_2+M^HO#^`BJ3'T<;Q;DG/W2?&LU&+O?KB*7U1U: +M7'#N;4BCC>61;4&X\/><-M//UE/Z.^D.,A+9%_NP.>EY\]MS`4].R/ +MP(LJ@D@4C6U&?GB-H[H83%3_V@TTHC*/1GJ^6=\\EO,AE,#=S#NE7D*O_"E6>J'LCV5-0T;E30%?"(X1R3LLX +M1H8V(2X)L'Y74:E\<]%J6#@IM`VNPY*O$UH\XLMCVIO(QZZ0OU9?JM)Y?J-S +M>]!E`H_,K^#>(!A#JJU`,-YPAZ=6@4+)`TSYMX@+%\N=K._NVIXIE\Z>.C%H +M2ET=NB?Q<<@K`?U<)[;]]1AN5+L%%GL\G.'MF2OWQQ=LD^#(?LP1*1U^OH;TYB29X.NF:QY0:VT?>- +M_%HBNTF74N$)^"`(N7\])701K6Z.4H:ZT%.TGMH.@34BA2W8&YW\H>[HOYAU +M_?,K,!\%HF3>Y<9Y5;\@M%8J][?#S<)XB +M1C,WK]^'VB?]>3)OXO"&KUS<]ST?P +M@A6A^64K08-\$^M&UJPSS57J$?5-1*2_:VL%E3F\D"#`%K(.:=H)55U-#WBM +M/Q=1[%+B=A_?T+<^0W/IWUR9O>HM7_]HCZG._@^=5U!*7'9B:KXS^=)8E=$X`JQD#%3S(6ZOR^&.9XMWF +MB`^DVE3I:RU2!BOVDQPJ!CB]6G1WD\W3S2XS2TWJ6P;&$U8'#TC6$GWIW&!C +MLL'W;F0"[JC4:L(>^X5GQY-^,)J1$PBM`I+ZK;'B)FH8H702+%3?>N:=B(45 +MDHRG1*6A/1!S3D19U:S\_<+_!0BT&4#$^WP8#%FT(!\DZP5)VKYE]M&=\1X7 +MK\X1MM2!%#":Z>!O1&$])^YEDK9QA9XF_=JRPE`9NU]EBV,CVX,I#5! +M%>'NEP0E:'KJP/&<<$GM7=K%6IDW%3S$'4<[3'#0L]WF_%AA +MSW&A<*'X&\B;-0.$LAPS8IM(QWFNJ?ANG)8A=Z6L'LJAH?93A,XD[O-(!9<% +MV<^JL1#$T1*W/]%ZU&TZUPQ?OIT`@<0S6+IO!IR$ATQOGHJZ$!4J),/XB#U'8M*^U8^<1(`>O"#I*Z_[/ +M>)?\53X[!,W%)*U?W;-0I6LU,4R1SN8'".U5-5)A/^GL0E,:V+'F4Z$>Q9$K +M`LY-!!B5M71K0LX"6R+L*(A'2PN#V]>$M`%(!P91E(_N7`?FRNA)8&_UV\BC +M!_ZO1&;$S_G#AX_0G]5!MPY6=#!,&R#4]:R![C,Z1ZSQO$/!Q#&_Z/-]Q&PM +MB1+I04*'48&XH3K3Z34R"A\QHG;E+;*%"QL(3P3B&-OA;\DC1=PGPXY6'8'6 +M:\AF[27+0>F*UK-LHTAL@&\Q5\\B1.^FS(R3"Z_P7Z2_B$.46882>P%S>#S` +MZ`]>][5:<3@7Q+_[W)^+L]D,ZORW`U:KG!C;4;K\+HT$1X)5/\X[611M\A[349I4Z[EO*5*O6C@F@A[+)XZM3:;&[;N6!>_S8'E[M +M^\NY'(YGN#0@GG,F2U$3#.3O>A#AY9'?[AW4?A;0-5IH#ZKHM;\(E!SPI/ZT +ME=.[W%BD&@Q1BYDQ6//3XRK+8"!$G3J.4^'NJ.@>\5?U&(8#$UZQ +M?&WURL8F=R]B]][`O5I;GN)TWH/`X,Z&4I8_0:Z\"#UP_:3B3X$O/CUY_2XZ +MOH[Q7H[G-FX\M>F7&FHD0T_>%@+$Q'!#J(@\OJE&:H4?WFF_J_WQX$X?6RDB +M+G%H+:![)<$]CI_VUNZW6I..3FU.?LE*X<75+*N):XW>+( +M582_W6OPPGWHET)"Z&]^SD\,M@!8N65QI*.(,RYA8T?:7XBTBZMIB=D8QUVVB^8^EF][ +M0E=2F<3WIOTR7_:U[$3-RIQ\VRMW(.\T\9()$_QR`#CZ[\4$&GGGB6=W!HDJ +M@R&F7\G]U`HVP0&JJ=ROP"Z:EK!9>5RX[:N?G3S>.*2;!0!X^,:_?%[K0T8" +M^$&"89R4P2+!(MX$R9]!,\R6VT!Z*VB-MO9<==NVKP\EI`BG&0)H#X@8'`@7 +MA$W/N[/QO(^F\9?VX&TI=JR>5:D3[O0T%4W6.GH^Q(@C`+68C_IKXC*OQP;U +MU0GVHEK;IJ*U-41G5_R%[%D@DQES""_ERFRC%R?,ED5]9DV\!#WA==0(II!E +M+ZXD3LIQ:PH"+6NJ@2TI>6V$QT9()&%O\JVD/'E3NFR!IJR@&)C73+KXY]K" +MX/GK3SMX.N=ZBC/#)+#YP08>7CI.S_CDGN^KS3D7)HU@6Z<7/K&`_LKH(25; +MB(@MBZ\-_5&:3)QR/`@M6<%1],&"4"!XNFGVG;PLZ<6KO65,A3Z%<];#N?"U +MVU"*,"24[%F%URVPK68RSE\QGRX"D'OT +MI--ON>?WF[1X%?!^:3=<,_&44I%=K"4`@=H@I^NM@\-AT>?&KC6,>@V\_]AW +MSIQ.QPP[7FS*Z]9B8RE)R1G0M8_@PQ8$NDB$$WE;2"2@#$ZV\"NM'M7%HC,)+S!;G`MQ)V"VO +M!`%99#Z-A\%=,57]ID2A-O)0I+;VY>48094:\.2@>AE]*N2$J._ZZ9'KD\RU\D^F1(/ +M`I.?N*HIF+-)C5!KZ4X>HE+O<2@SHL`C9N2#"_PT;3'X=(72!8-2N:(3N>SR +M,4Q.M]ZS0U>R>.GCJY7B#W\W3!TKJG\-AY)V.;)_TX@Y&&<:*$6T;PRKIU58 +M.[L8W4+X4QS"P=7%8I/+.K:%3A^_9F4W#`?N9?1%J+!+GF.$YUA^9XB'0H](&Y7F,[34`U3OR_R/U;990& +M(6$K$<)X-I'T7IIL,D6%+0AY'T*NZX?;S)#8CN&!F.^O;:KEB>3RX(@JLY!,FH2)]."4H2ZDSG$N+&%M*YK,P^ZTM' +MJ/EA-K(Z_64HW*&&1>5I6.=R@%B!QG:[>`C/74@MO"C+R3_)@!B90N_BJLLBQ-X=$$Z>P#PZHLST1&.! +MGH\%L4D*<1&R/,:6J@Z>=.$JWF04X\WO48,9"@KE"B&!:L47:E% +MSBC)'(:R:I=&^XF\P1VSXSBX`N0A28$6G#9[NL:\'*6_ +MH'Z!MH<"+--/B:&/,RAVMEHSK+!'239>>@DF]SC+[\$A.?4#GD3VE\#_3X"" +M8TJ&XK:>U+H,Z%9^$5G4;=[8]^)-\4,[6O/Q/];EY248]_@^9G;93](Y(&W" +M&HB9Y)+!`2_CPX3_.X-1NET<35XQOH9'5GS-`D08T+6MTFX1ND+]L&]T! +MX&7UWNTM(C3]C/'"RIIDB&D)2%IMB_MS6Q6L:"`ZL([6SZ&34NH`M=!' +M:E/M"[%8KR4>Y)X8NWG;\N_1 +MAN=WG[2DC^X^5\AF-\.,SKE:_+^C'=*"K%=QP?G]4;[Y)`;-`U)\DJI#U':MR(3G=2T(_U_>2:P8VWL".H'?`;]G^)HQ"9 +M2&]-Q)_YU):C^>'EF!DP@1395\?TOZ#^D\C)V^5@:B]07"1M+Y$)I6.9Q%VV +M>,7HH=M$PUFMKTK$^]UFNU'7G#$\F8X][*X0Q,NI7SEG>E"EN='QGCW]QL^X +M<<[F1$$*'\O76M8((4N`LIU`[9?1UT,7R"A9X?A@Y:_?6G$@Y>YQ5+FDC;P;O(3IX7+QAEWD^G;5U\2J>7$=>7[` +MX)>=#Y+`#[%:;!1V8HI=Q`7I;VM966QXUTLFB9X$H>WXTFN<\WCJX[)B=.XN +M1,I)H%Z!I_U.2^!XM/%]\W^?,$"T>37Z'E[")YIH5,F2YH#5&G$\4\TN^@>: +MCJWSKC37'S6>NU$/RBAVX\3AX$-Z9=ZY+%AE#3A[)L:^]2WO.H%V-*K'I:^E;B/K')E +ML45P7,UWH#V6D<=?FML!KC%\)I.RYOLW9K6S=D5W1&ZUF=)GH4KJ/>J@2>,R +M0J]JJ!^V2W4DDPFD=J'=VO3G5F5P#2IK([IFCX6:M=S1*,V;JXY@T7>JL\1= +M7*6AYG8I$^4`\'W8GY>EF:RS5'S_6#75W#`(C#%`^*\Q5BLP`;6#V%E/4]U[ +M2J^S[KGI1&TB);^QQ=\7?_G!#Y)MV"*>_S.:(+;ML.P#G,+47+%+JQ"O%CGJ +MX0KL6/H+,+8@K3$NYS5/'<'_7$9%/Y_W3W>F'P6Z`#8F4OL<]JWAG!$F&X4* +MWZ#V`BL%")4W&?8*D-R_YD57(^V/CU:Z7.'0V,_=KIX8Z)_[ +M;N3KNV9ZCX$3(A["^01>E0=0)3$_>'IAQ(:FT*?CN)JR8_N+KG.]J_WY$YK4 +M=EX:6__)8?_&K,8\:JKTQDWY*QC"Y(DX*=934@.Z1=1:2XM_RNLOZ9?IR\\1 +MSD(%7.8'G'G#ERE0XNAY+![E#S:ZPO4B5YUDZU\TIPTSP=Q"20X]T7?=$OJ^ +MDLV0-LC'RP3!SK\__.$`PXCV?#4F]48IY$4>X5%HIFXJ-I8[M0G)^2JX:YA* +MN@[0S!6,IFMS@:D=L7*AX%S1INU7S'HTDS]0:\:%J=38%H52=%M_D2QAWI[& +M&@SKIL3[-<[43<7LCM7#KF_R?2&5'/$Y=&_;.CQ"RJQ.V,KX&4Q\@LV?2;"Z +M/I]46C6S;WJ+`6BV3<:QCI)7!W]385#\$&52JYP\&.>2HW.`+*H67[WNQ"C"@$_@>FB(@(Y/T3QG.]@.@ +M<614!MV.&"M1>W#>I$D'T""BJ(9MM9BY!XX"`KUDDA_"52:Z&_\'^WE_9O%B +M!UH:9\,;HV-0QR19ITFKZ?C&$W'3;R]D;O%N3Q*P75C0CI.5$Y?%&X*(17SA +MPBZ_ON'E%I_)-D$#*AD/3?D-)*`NV',6KGJ&V7.<70)JTV#25A(^H5ZO>*+3 +M3*:&C>_4(NA)'Y9*GL5O8#UWI9Z7?L7Y8]:.$=^ZB98F!0E\]R?W4T.CF/:Y +MT3WE*OC2Y#]A7,:4"_U^9!S>04"-""MXL_O\[-O9KL3_3/E[WI,A_SOU!.9) +M_<[$IO@96DDPX1]'B$RD5%/3K9&$!%B(WL7$`SG55S'TT863JW6]U;*@ONQJ +M>.A.@Z%;-@X)'LW(6XHH[Z9N*::O<3GNV#RZ$ZF(F5Y?]N3BMS4@_&]D[F^7 +M"_ZG^,C*YA0V:`^G%NHK0)4C\ES$S?^D<;!>I/!N%XX,U8XO0#:%I6"EV*GU +M=P6%7^03/7#,?ZY&XL&1#B)@/?L6+!%CTN9YTGT[@[`7BPZ[98#JMZ?C$'(B +M^V(OKO%+HK@`$7:NAPB>^=7A=H=D^^OKSNRM6H_+RG-"2-DDU#4UY!ISFV>- +M'9'UXO\@K=H0;9R$M2(J5HG#62W*GQIF:@[326?!X\AXR')U?:(;=A'&7QPK +MZ.9.3%VU21.M\.W`>Y,3Y`C&OX8[")@L4^BK?N#!"4:DSV;KGQ1XNF"BHIM% +MHJIY&#_QGO*..6A)]=-*X['QM%H$766^M%S+2ZD$^C-@4H,16/N9XY-E<]J. +M@41%=36:A<(F8Z`KC)L#@AZC^I8L8W<-@5BGD/>&GLX5N`@6&PBQ6HQD><:& +MQH(MWEG-_G4NI^;5U=(KGWY(QW%><#%@J+!YS=F*!%_[SFY)#)I$90YV9(`Y +M%R4BZU=2JP>JW;`L@3*R]N'2K-/L2#-F!:2&(0-%1:_<"5G(59"!=<>#?64+9`/Y9!35+`)!ZR:Q[/?; +M)3.MT[Z[B#$DTHE%:X@@D81%(C`!HLY)&ZA`TA854$7;O_T,80=K8/D&;Y`< +M1FZX>;36_*-B%)I, +MGD-X3L0#_LBJZ#P(F02NBHC>?!B.[*FT:-$)AJ74057X/I2#X:6#NF][CJEX +MRD7H&.5CF>U#8_NO:]8+I)LO,VRJ"RFDDT+;TQG5B>>6=HI"9$FO0U;%..II +MB[&O8&Z+:P$+A[\P$M"UJ137>[)D/W(W&'+"VC>BG&B^QT(6-N?4@F3()Z!Z +M:DL_W(#@.M8\5**,YMA[PCE3//FLB/;K<3:3ONK2.UJNOK0GPJ2)*P*$)/*@ +MXRM!N>%BIH@+

    0H"M=U.^6@D^363V*G:WO@=(U[$/]YO^(GWU!$/^]1T07 +M1HHK6?EII(HG-\LI%K%0D"-A??/CIOU@F$10@DX_NH[$DK1!L".H$.I+9M:, +M$Z7>:\&BV!\GM#$%>M=)Z*!LY)5254/[N!`9WZ\O2H@X=.+FN7\GAX7^)&9? +M(4.:VEWKE7QG^8(E2K8Y.`[P!EC\`1AS-[I[+_\4Q))$3]G:A]K=7S^`Y0F4 +M]J:"A9>W_ICY/*>CR^?_&=?0HMR1'K=I\;W^S21RQ]:*BJ61+`ZWGB81563G +MMLQON(^[(-%YU-9F1TYF.AO%.0*'9$?J;/=-2R***=3U\KGEKS_"C?F)F5*V +M_/R/U&^2"@+D*+ND2U5$`0V)FM>).TV-J>+U#L688$87'J:)0>W,YD6Y1E +M0\)YX(D"6*17(*?S,AT:1Y$'MLF;HR],"J8G$69UKPW\NHEO,'=43D5P4P@S +MI#D;0SD$*HVAC&XK5ZRL@OV"A%+]`-Y'1R:1F7=>ADF0BX!G&W^HF<_X:)(# +M^M9TZX)[<4&%Z'[P!^20Q&G-"8+CUN1:1U!/JM6,X8)('OWQI16LW,(V_9!- +MJ=VL49=%<)Q+-9O^6SDJN/YZO>GBW?P$YI4KK[I.",L)U?-3*`M0OI$)@$Z' +M/HHUIF@'NC,QI9-[CLJF&(D5"/NBOA2V)>F@S/H9>80=;XD!JZ!#V3:X$9QZ +M!/7'C"G=$3M!YPE^Q,(;K+SPQ2I4N9R8O<+T`>#Y/O/CD1K.X-/M:79D'\/W +M:2]0:9-"J`,"",D1?ZR''2&6ZSSJ+62 +MJ7(LP3%4W/D476&\WT03K4+Z86S[DQ3LB7>(G7$40B27<(9'J86:+CZ"\)=4 +MJ97N<$L@5/^-(38,?K2N-?'CT`8S[@(&0*,E"(&LK+Y*=+_6XG"_.NKS$<;F +MQ@LY20CO*?6NZ?Y&X3QV>MOP5U:K]M;4<=F9^7Y@@VD)*].Y>10-`\M&]Y(* +M)U%L/@G&&5-=:44'Q%QX0!OU;Y<84/W'H)QY&`8HG("QA,!I>OQ$GULWS!'+ +M8CY>0X]I[Y]2T"8;Z>8SH7C2;:;GFQTU4H`62$[E2EH,?-1M]@:`49A9.(^\ +M5SJ(R$:YE$\^IX,9\)-V0+V@AZ^M5,.F!*G +MOQZ*-K(IYC_3 +M]Y"=O=ZH`U@)KG('B6;[-=4N!!YOT5ZY;M^9TTM9EE#A3#[^O2EAD3<'RA>7 +MWEGK`"MTZP;*;946GEZ175354E+"!@=*8-0(+A]T7&VJ/HQE!I?/-126G:;Q +M*P#"3I]=HC:N*1K5;82("6/U=0@./ +M')N25Y73:EZ78IL(1G4)04>=%C*0S4HSWTEU=G# +M240D[V[*/YQE?XGD/9Z0GFO5!F-\AP9;T5B,T]$&@M^38%`K'NL-D[W6-1P1 +MA&[Z1"!M:>ZC/$LDLNP](N'8H[O(6=:&G(;E#.*>]IG(E(`)*&V,?Q**4"^( +MI2(Z7.":[G,)TPF:%@_55,>9Z[9-CJT7^ULEMH&\5+H)K1Z#P=H56M*51O]P +MV1];*<;F)Z<8N.YN!!C`9`(T\C/4_BK?)^3<0:BPH2S*EA0%I.9 +MMEKZ2_KZ;TX;':`R),G'M')$0A4N,7?7HF7>;2%-G]+=I"4-:=9OW$M%,RO* +M1X::G1<6$WQY[!#2V^3K;4^A.9BHJZDFF?@$U#+;*$'V;!=0^RSGFR3:0&6@9XC[3T<]&%EOQGQ]JX?@X +ML?L@]<::P./K$$6=]+'CBYE!;CY$^R_G_5`G[JZDO,!.P9S!*E9G:[7PPT`5 +MB3.FC$@?/Y-60CN@D@(G!(FVC@_H>75I2GDWA'I:P@1<]?7TD;:O]4+Z.^^@ +M8%%`:+#FET$27HGL(@LY@"4: +MOZ0XG/-:/GRFU$X==4%)\?>1-,X.A284H1ME[N;(W[CH-Z9,SX!K@9^..#2R +M(E)=X6!R+HK%_`'E'79Q6]W1PW:NQ<(UL=QU2T\$X<2V6>05^P>`4RY8H"9LCRL.3]#1+ +M7YXHZD)W+X?D^M\F$NAO$JHH,S%964EG6\HSZI$5MZ>OID:ZL&*RPQ03\529 +MR-9_;:LR,N-XIRA>XZHM]MI-UTDV3DI1/ROEY-8L2UL#MI-^]'W&A^[VHQ,Q +MK:2"C)4_44/#%BYQE#OY?]_@FWY:WSYA-&_G8")M+SZMK8NLB#MW/GIQ<^$" +M3]C6T_8`ORB`7I/H":\ULO=D:$8U(I+R/G13\S2%7"+Y=]JYF5*>G,8[ +MT+RAE#:!]W=4WP36B&P[68SD9I;$^T!O?;2=Q,.T4M#P/X'_,3B">D^CBM;@ +M:&Q-TA'W(C[@A`78CG8C]`J=5M(&3`P/;@YBQJV>"B26$)K(;[MI6^47T[7[ +MH3AI4S?=W'+O4?,,0NH^(J>JFH?M*G[J?'R+]DI^OI[_X"#1$[HB>:@'I\,% +MP_5+9,BZG6U\.AW:APF]W&N)*Y>:XT[!3!G>7\!%QFN-GK#IX<(B3G0_) +MNUKD#.="L4\1W"G.?"AX)T&=6CFNFO*JGV/OI6Z(88)5W38\3:--IA8D +MG5PP@RB^KXF69`:)_Z7&0XL_?K6MOPB^[I++JNJ>[ZS$#\9#D3[57AF]#S73 +MFS8J]<^9>')GUZ!].*@?)-7S?/Q)N>7\[&_1YFC=5OF*R:^@6\:W7.3UE[ML +M^R0?5>A#H(%-)//EK1\GC^D9?%ZHX]]I()UG;]*W-_TJK++_UM'35*T`*"`6 +MM_6Q$N#XB/^F'$6U9C8$;"5H(9SA8NEO.Y*5F5OW/D_**1=P^$U`V4_M2\;C +MTHPRJ;(A$-P.;EH"-?ATA):9,H)U!*IMC_L_U*D=<\*I50*"T%>-KZ:W_U(A +M<'IL$L]![.M^^V:-Y[/UK.`J,M.-QEVHH$FHN#W-9SI4N>MTV;$F!-82->-S +M)[F-&G`"&CF=1]W"!P^S<0^WQGP,7X=RXOF,6)_!O=58@]Q5]!&2IF!+&/SF +M8!"F$D;3TL4I9%89,'_#PX3S],-^(;@`D\5!2IRD\-N[&LJR/4_/F1BX;X:Q +M,IOYEGN,UTTPIQOEX-:UL8Q&OD7VC<\.ZKM.\IUA-GB48KXG>' +M@3?3LP>OAB5:,GQS=&RP\&%:;41[='54]3DH.0Q`9RYG)_-5&8:)B_D@*-GE +M0KIKTA%.&SAJ4`<)=DABSRTON7J0;]_<+9=Z\PVDTME"V9SQ;.0!N+&!35[F +M,5+M%5R-"<=FK+RK([MT0I?>'6FC1[/+$4UE,,XNEJ"=2S=I6CL`WQF3E_\A +M(?9L(A2+1M_E=SD0%V>0T5,%Z(E86-1>U8#4VO'N+[O[TM2F,/AEJDM`-B4J +M\6O4_V`8"B!YPGMF*,3)F%H:X.54Z+J+HSFO8L*CMQ/`L3-6YM#8KW0EYJYVU`T6N'HIYOP5!B<2HOI-@= +MC^/V.<,Y&C:]8-N^R)RB8'W7MCEDWO,#=26%6X&I6OAV]EXY'_]Y:(LKFI#S +M1N426ZLB,>XA(`D$5.SL1>&349$TA-A0$**!:,?B?)-QJ>):B@^Y]?Y?0#7" +M[-3F"SW;-0=6IF1H8' +M1/Z`T".B"P_[5_^JC(1\0>5^V"A5R5/;SRPN'GV+.TE\'J(CY:Q%47T+4.<+ +M&-F5I/S?5-IY847&41%B,9^]&_*J,B +M;I)GD,9[4_2#?W?OQF-]@1G18+E7\K;59@?[V%X_:^@?0+7DKMYGU&9"4R`] +MA>I-=(53>O#Z4!#+6B?%'%C*C!0T`X&2I&(R;S8R-MZAT/YR7;S,JB`(H,97 +MZ?[:R@NIA`I9]<4KS2,V(9APCRPVHK1VD^VX$5K5\W$+=D2*^B[;AO"E^BMI +M\7$^-2\X$$D=%0-9:&PP#^&XI9BC-7G9\&!;(6P;P:$\!9.@=0_6BFNR8Z;2 +MM_\4FC>B=B!J[")L',]D6%,(YP^`Q-1)XWW78)#*VOR773-']/U&9/\[KYWN +MJK,VJ,@.+9J;J/1K)"KOI7-_?V((H(I/WF8%#L] +ML,#%)-!)`W491@,8?R[;&\]YM.C7Z4TN:%=HHJ%69C6='LVA!\M"2Z)#?"@)O18T%84H(R=2:(KU +M7`_FB:46&H00&2/AU?9`2?>+RS_@E!N6(*.8 +M6C2=?PDJ;7?!(BU+_QB)FT-5T.4(?LC3(3`*P>T"YJV@8_:[9'3 +MK;SF/QC;.*=_F)&NCM7!H@*^4]\'DA-HF1%C$N4FD.=UWB,N!!_2]$(6#]%* +M!K9H0X)^'.ZM/@A,A@-!V9M-X3N[?B4"RYT=2QW8X8O!!B-+!'&)0D=X3F<= +M]9(9$)V>\`^M\7,J1:RWI?-#@(X>,AMV/0VX7 +M;E>7.S.6+?N:-D#XMU&7Q`4=6YZ7E2G[]HZ$$>KIBQI[>`#:LF<'W'[N][N' +MNV2Q+1[[?A-&Y!0*(DU7.&\RA_R5OEIJKNN`N@;;@V\(R^"XTM'(-PU$-7,B +M9PM*W5V`3F3D4D2=V3UG\;9!;#V;+3%3%;Z;ZR/VSI7*E5*1'*HD<`750/I' +MQ"]-"*]H_@-DM2;2>9-H=D$NU4<`FE@V#7O[H\'D27Z3HVLFIK^NA66^=4$85KC$6OI03#`U2E1*UCL*^?U(,S_R%^J5A]H#Z2XO+!QS@(^I30 +MD%D6)^.2VUYH*10P0)E%OWJ)E%@'<-@)O#5RB=U9)/G=UW7T;9ZQ4]4Y_Z7@ +M(6,28IS2JAVF//P5NU1A'?B17_6('T#SX8!;`&[V_;5^`-`\*%GKVMNRF)V` +MFPPKX2\%_MX"T*,=V.)D6)QI92!3]WY5YTGH`E:,[W^))13:S13>,3$V;M.% +MZ0X3Y82!J6VEZ,)2&R>%B(6O#@>&,:=*9KX`5@E.]=[Z9YD,_'7>+#U+'@&$ +M>EO&#]ES`U#.4>Z:LX.N5?=*$4:-)AXQ-=?"4D +M39#EX!7M%M)/Y;G<,BN2`/)#_(_&YHD-9)3M@Z16;Z>&O%Z*E;'`3V$[,#GP +MW?KZA5HKF5DG0=Y\Z@P:]!XSO%@L@7\X[U?)U]3.'N7*AF75/>3?`H#-<+4WF +M04X^0/'U!F\^6#1%7!BC"YAV&5^M#+Y>Q5Q944 +MH8O.9FP\Z!M"JP`A98^1#\0N'UFIG;_SGNM,X]Q-!$_7.G$NA]#0&>0BU2&4 +MOT3X#4=`#&Z@J"1\Q(!>;;C/(S\**&462*`34MB?.^Y2D+/7W/EXC7/,]JR/ +M%[O&E:=Z28=E9:MHV?RLZ"JEAIGV8*2'2FOU-)$A$0@_[*.>IN3=O=@DW/KY +M`?/_^DC0_=5,$-#3B-Y(V86'H*!QIT.EL%_+6#X7E"I@,SB:G9VWAR[UF]>X +M@.)'C&:5NCAR]7_/>4YX0_TKB",.+G\:I*!65Z=F3F%7*F'/;`W"#^+[SDWX +M5,7?:(.R%$)2I4T$5W%GHJ]RSE":^#Y@3>)OHBV4C5&HLO3-H>T"\I2;W?7- +MA?&Z6-X>:AA!;H&:1RAE4!Y8-'JU19*N6?Y98H@O#A9JB&PNG3<YZZ.D_Q\U_`!=R@PM3A/UT0X3`.7G:-IC)7,C-=`A@&L)%;C^[9($M8QLLL +M+!7\.WO4=R0_`[0TNK6KZCLCXR##%M.WEE?Y35` +M73>DF(/I)'6\!D+^OW#=NP88W/A6X,VKQMO)'1.]=:12E&MZ3G#8<"3NV2*5 +M$$7UU^+Z4^*8:>C_>3W=$^8E':_FC>U/8';T\](6U9B#%3L26JC=L?F.`#`U +MQ?:(W:DVU?P>A^F'DKGY?;GNU-PH9/UVA:@*1(+A'L']>`WELB\'["FB3>"S +M#'N#"J@L>W9LEQP*3QC\572"ZQ8BYC9\N5_2]-/=(1CVRU]H<2J@P=88!?9- +M-HS590.M-7^3--E46O#5K`_)D=$FL#S(TOJ"!'0"4Z]UW"3INO:OT:R=GD`[ +MPDYS:YIXDE9+5--J4.HS75V#"NVJQ]0Q[TQ@N1*Z'O8MF_IOQ/A=6TH5&"K] +M(#E<_N8F?WVAY3,FFY?99-[N==OH1@>0AA?Y#W`Y%J8Y@ +M4!W5`&XJ2UA'W?:;HR\.JE54E8%";:[<)536H%5>]IUDOXR;:X,<-B7'PY=% +M`.*%CNC6X994&,^-YN]A)65[`S`!^V!MNAU)878U^DU//?=;6M&Z;@GB,])1 +M74ZK.=2Y(E_5_@3@HG?0ES*W2L_G];'4;^\DB)4J\C5B-;3%"--ZL9%4ZNWC +MEKA%@TCA5>F+D4!BDNUV7`$*OC>4\VP:G9FCV=%B%#9H.0CPI#NG4?_LK6.<+EL=TML'E8,8^;<-TWR^B<1MK3 +M)#(":YL2'BZ*J+,'C<"H?\*^;Q>)V3K4,]!I1N@?U$$:7@K632OCC+@>C'U> +M=`]$O+$^W=:BM!I-7?.T`^Y`5P"331HKM+&^R>5IMD@.6P+?BP>:W-"8U-"U +MU,,79<49X9%-:^*X+8?-W9FGG#?/E3.P2^H70F5)+B[><7CTS@0C!1Z;R:C0 +M;RWG?C+A_T=EG.+'I&QWYB!40?;K,D]B[F-7#I)MM2Q,Q76\!W0N)B=NXK7] +MU_HL&W,8`,1HP8Q#,*[QG:N@K8CLIYX^JQ'A!/%KU%$68!Y2% +M]C9O:V0^O,=MQWO+1G66M7_`K5^%/VHA)[VH"%;-3_3EV]N<)BP:8&^^(?`] +MJ@UOT776@_&*959,10$?N+"DU1>@;]U4U0^Y09.4'L23Q6,RW7Z^4LUI;.4" +M\9"*<`A2M7TH[)L;PB^TE#/>V[DC1Z:6W3T!1XDPP&8L5RN5 +M.V)K>S +M:T-MC1I4=U1MMBFSML1G>CHMT?CGWKB<:-IVX+9D?( +MOPBMXS^QU$FQ\*P="8VBLBLV0DF?UVGRRD7(DTX%G86>(`R\*!TI.M<9`-A> +MT-DB[(JDI$7$>>7IG"RF4=>&KL]QL.BV!IVT +MR^#\1$V$1"K6FUR;^+W`K\>[>534VYR94O%6./`7>5'B77.DH:ZE:"9T8)/3`.)BWOH"* +MG'[+#C:X>+9%&[_:5FU2I4W]&/_OZ7_9BJ$7F%C5F.)W>7*9D=I +MPA0Q$V/6J-/@Y6FIS+$B[CYN605!%H'H'JFBYM'JT>MN;M@)"^]:#\.Z/)?T +M/OKI'#TZ&*^G)]OS20BT9K0A'&R:MGVQ#**]Y&R-COP`,==F-D^+!ZS#B9<3 +MF8C5%/*%&K)K2:4_7KLD>^?(;(YEB*>>4AZ+-'_ZSE@RM,<=F!\CQFUNA7_0 +MXD_7(5R$')U2CH9#A%G+/1@CR=0=))+T[P_M><^D/R;(("9F'Y)8)=.G#H,\ +M%1\])"7-\Z4ZP6K\&NX'9I.O]T*-.JN'PK[S`]V>-5&EY[_J$* +MZRZ?7S"E?"<^(!P*D`W`EEZ +MH-B_(G=PMT'SDG6'O=;(^Y^^HY4<47.82@*Z+\%@5PB=I.`?P#8S`0+ROG\# +MA?C:0!-Y^^%]M82V([$VMHK[9?1R"M@QK,]]^('.T&U6ICFL/=V'VW(2SZDR +M@;(#`-1562O"E;L:?NH3.U9U33'J5X_NP^3FER/4T>F\#V%#&AV]I)GN,:,L +M#G:M),.$X,Z-_5%\;OJN\+2C>HQE]W6+F'%G6S.?/FD!J,U@K'M'IO]_5``L +MUKA'*WN#"@.!#N2'+N>#\U*X/QZJR1>E6P[@KPYP;8'`(Q[5"V'0)@+9)=JN +M#'[#QA//8MC'=YTG\5IF_4.>\&J8F=/JPET1[`TK7#*__[GQ)K_S"DUXEM1M +M>R*1'<<"?WH3ULX[GJW+(Q!#A;GI]#G=0_.W:41]85WP)%";BBF,6@,U9,J! +M>99(P\Q1R[',W\8RK4U,^\"GD'_&0';%*6*MLTWR>Y"(\.03>V_5UM,H?F*2 +MP8\QH?C&%,Z/C7!2O:BE$'["M-BY#).W@8OG1])!5%-#, +M^J?9L;U<:%H88.,,H"*YI]Q?N]0WJ=5U+7XHCG_%6"-JCGD11?#2?0PU,JLP +MMRT4H$D)[#RLBME-$Z*_JVMJD!W>[)JHG!/U"@^MC\`.4ED!^DB8'HWA7L"+<8,S98"-).$%'D(7-QAF10SW$C\*;XP]O&*( +MZ,!QGR64I"/#-7$?L.L%!%F!<,CJP[,W$:!_ZA=HS63;\-OZ/#]!P&2;`8F@ +MKPE@GS\:)5I@@4A;0%A:0%E*B!K.+,BA`QTC#Y]7;A0L3-=LZ8C_;RG;-\*$ +M\#Z?H"I:Y7YPO]4?WRBR!I0U@52Y+_8^LA9%/PU7TR;STQ0;#`$D`'X215;" +M@URW&:@>RZ[U +MH`#Z14V?KX4%WU,^4]N)ZX01U"$G4^[LQ^=P;-US&UT@ED<+V$33M,ZTX)R. +M0VQF/B#F`-TMZZ-[3[M1EWT52A>A*%]#GG[FT!4+58U9OJIQ&=+:;;-B1L;?^)HW>B8C<&AUL22!\"&=2X.X]79)VL`%5&73?J:97&E.$5RHPJI*-@KX5:1SZ9,:CI^M +M*5M.V#ICJ,"0*(Z8K1\^P#")W#\)1Y?/WU;A+*EU/=_QISY'VL<+T.] +M+5+I_QH8#I7SH`4*GQ,)Q*'L'`4,\X3%"8NT^6E"P,WPA&HFZ])_9*4]MZQ& +M3?BWL88I:@I5".>0U!G'4=]S)$%-L5X:-OF24S,P4GLAP83=%8 +M:8<7@WO)77;U\_[S.9I,,E@?HY_=LT;>1Q(($FR6?Q/Q`M\N?HJB2:$J:7(" +M6KHRP$0\/YG]EW6/Q2F%K#?IK*9,!_?H^-`B:J3K8^SV1.CG@)'K,P7$W"@3 +M9X5BP_^4_)/#[];"X+C^&)W3+#J5SF.)'09N<(.C>%M@T+REHX1EE%B>J +MW>ISF<.SM=>)3#!:B$D4!0L*1&PU7&+A&PP5:QJE5AVDH3OZ7U!0[P2J>_?T +M>E2:4'D"27X0XEKV*3^7\#PVU`"02-[NH:G6[7VVYSD37::+NI.?O3/1006P +M;&;,G$+8W60,'D;$YWB6,),.!(Z9D]G-V'CJR9,$!BZ*Z6$BI82:%X_)UR>F +M]O6;<),21)9P,HLG>^HKW<`\G,#C$8Y'Y^#%>L@/K02(,,3Z,AY,E6M%9NF( +M_5I2?KM%P1(FBV@(8\>,&61LKH-`.A=CO<0R?:`T0[6Y*P"1)[0]N;@3^_*Z +MSRS'+&@@"2\U;\.YOCG29PB0-4@>7UN=F;2'/;UHC+EJOL*)TWXU%B^=A6&Z +M4\N1$7%_NF8!E:BJGN*Z[OEJS8E*AE@".49-`.,(=+6XXUB +M[`#8'I[YPU`C]:@JI9B6&"5#&%PV^Q-%QX'AVP+BPE5*0?\+I]"\8#@L0Y6F +M31LR7OME`@QN'S^)O:T(5 +M:G59`RJ+W?C*C?,V[OU +M:B#US;\CB=LA'?;M7E&9$('P94^;`.BTQ;"5.]5$]>@NY"8P+0W_'Z/J$?Q$=Q5[:.Y>Z<-!P+1 +MZ?S;M>KG<;:/W21^F`5,J80R"=C:J")"F'7VN^\X3DP,9&(5$E&`JD:!L:"! +MO8((.7%>/872PC1W+J8Y3/2/;[X<'9[QWE[P1R:XC=!9ZAG`;%B*S"KCL0)O +MMIK9$TL)E0=R)^:T;H_TM2,@+0/R6_6(6ZK1;L/#"Z4+._ADQ[(J&8I5J]O6 +M3#-:,HT1N]N'#/F!K7=+#9'4JU7P`N,%6V:YQ8TC7HGPPDKPI-X/RG:P!FZ+ +MJQ_[`T!3*1-OA13E1&=HND0)HOXQ$\5Y?PCF31:>:F+'E(8TC]$QX"@R9! +M+R7D(I]U-J0^"^99)Y)W<\'&@E)91FZ8\N]P(WB:!N)22O]WIRRKL]W/F&S% +M[T:/2!PCE6KMD2O9$_2MYCAGN+XSDF++-AZZ!^J;2FC2<@B20#-]!9M*M;6'>UQ(G1Q_FC/2\+MRXG:_?XEYK0X2PM;=@+MP2 +M@QX02H%+8=YT#&QJ<#R'@:MI`Y6-V#K'#C*[MA5LH0_\E@AIWOI\=WFT@[8B +M,VTA:B_+V];G],;$O\;UG#WSG#"=X#:Q-[P-;4J.ZCG24A[+OY3E>(R*$T0: +M7FID"6X$2;HQIZ8(UA=]W]V`V]N'$;/23+#R30Y"(#HF>Z,@20,]F=QOMF.@ +M)R5[_)H==*NJ:%?F,19.9:*K6!-QGU12,`N/^(#?*=`/OSF;?Q/:'.\/6>NR +M^3FIQS'?3INED_[4):3AK6O9_)YDXBR<""VB&TWV+,YVZ45>/F-'*4K(&=JD +MM4[A<_F`F7%W*EB#K2%-A^K&F9K(Q2P3)`ZYPK6'->!Q=L5RHZL6#4%S^%_] +M'?H7U'S;[[:?"*(]%*QS-;4TQ<42QI9QT*D/]>?,[=@.+ +M;`>@5Z>_#2.N"A#A`_'JW8`[RXILKW&G/Z1_2":>\Y:NL!8.5U4=U"2V9-"N +MJBX]F:M,SM0[>,/T.]5K8FV7O?4CR]&$'1?/\(@Y/DBTX,4J-D^:8GBEW.)> +M47S99L2%#SFW07V$3N>:4F/W8_E4VH^FVG.>)"CP:"JZTT'C'`S-5AA9%,OA +M_I)$<*.]Z.M+UK.I<7/#]Z%F#O\J,^B3_%X3]J9*ADV!\HT1?GX!$G<%Q4DK +M0.:PIH^-,2<8=#L4UVD;.*I39-O"2V&6X)3`.N1AR]0E]OW'[0/^K.&G/[[T +MTFMTU_^H4A%W8.;M"7QZT"FM1BZ;;TN[,+MBBG08,THF*6L[[VIQ;N/$ON>'I>*=BZ= +M1+#-5Q9KEXPM303Z29#I>173`BTRBE:.N`V:!+?))X;ZAU2/L1#.*2M1]UTJ +MK83E1CH@G38`#K9=I"M@]9MQK>,JA,AI>B,6#$!4]ZJ)#5"%P0:-;07A^;@N +M=Z6Y.6_L1F]ICIQL6U"/PS5]__:II,0JB=[(!6\">8B\':XC<%OP20Q9\@2% +MSNBW]D@O!B$,0&P)S(3,W&E%>*P2MA%;QS]I'E#[?N:_-+3,[_>R'RQX``NJ +MHOG2.%X6)P?;R8&EB[=+7:)75$)?6W^KE`H!-F+$9K3(.P06(F7?CVG]F[\] +M`<2:D223E_R3%VTM*57=_YJJBCXL`1\X+;?^!4%\I[0-?-`@4W=.&4V.[>DH +MDOM6%;]PS4E4:)5-"'N#@UYDKQK#H\#7YB"SR!2S32)OL2`.%J")>5VDHJU4 +MU-*J&2?29/UKPXM26&TP"E9Z:'?5O<21OA.?\-Z"UK_!;8C#,SEWD"'N0T() +M0/D\+(7/QXX&W&0KW1[F7#L1R0"G\2+#@5@_.^&6RSI-C!(V+@3Y8FE3WAY, +M/G;T5P+E+'DJ&;L<&0.#*C`:A'M\Q8>=Q-2YQ1O]KM@J_$V'Q;R!J]'L4#=6 +M@1`2'0,R)'JY5]$O/%CK%)7D"HRH9`8R%ZC,:>L;&"1'P'-VN![U&X8H(<[5 +MFMS!2>QP06U$"2H+52JUK[J#<%K`T_.@%=40<*\DNQ5&/159*M(]0@MBPD?U +M1>RV1C/D4R(MLY&IWL)R=YJ,-"LJ.1A7QN)VQD6M;:?1^E!H*,PE3$A>JE*9 +M$`)TYM@]NV5G2^Y.7H6Z9C-_ZR!I.>MSBAF3MB_]39"ST3/BRU+O&=RQY785 +M";WFMZ4]E@9@(W21;8)`NI +MVN@XOVXPE_/0V$>-3?*J,C)U0()!W_J'O%3!)=URD[I28ST%/0R`UID[A"$+ +M15>F'F:!X0*0F")"=;QVX"K?DGHP,I):'QOR(`'N:T1U6=4-_X$5#?I1.8(<8X1[S#+9C]0SXP>Q6*1C%)IS`^%AL +MVT\IUN,3F%O.IV]>6F`PT7$SOC5;"DV`?N;^0_=N5BP:54C#)A6E\G&DI3Y2 +MHR76^IMXYA^,^X(HQ!9B:9])W1-,U2FOH6#^7;=!-=T,!R$>?AP>4YI/1@6!1K]J* +MLN6(,"QBN:M?@K.F`D.\IP\OV,6+B-`L&>`F:5OKAD5'DF^S!"5I.>?;@X'] +MI7_Z\WG3;62'$QC9\]GEK;*K^53L"6JS=MHJ/;&OQ%YLIUVU>MO0("G$N>OD +MNU+U<8%IK__#>6RU?X07=.+?M/)VTX=6J_=3X`\O#0JPC8;9M2Z#,T`GIQ1U +MBHQ.G,R,M('X6C6YTJWW"@9)9,WL@5D;JJ*/RTA_9V;$D-Z0JCV#]S&Z,'#/ +MK5$+3;3^.NH/:<,Z<=I;L)W;,TRC_(H?F41W0(58/_7GV$(I_,?68OC)VQ<# +M'$XH+ZBOLB\ZFW,IM8EM9>?Y[M8?;;\4_&]9,`U:9QX844U#&D,XQ-QPKPX9 +M^GM2%DDH",E/945M5ED?!BAE!%VF%59)=")5%,"ZS +M!30_@A?O4T*UO6.:S<\20:M]I/*!P9:3.;*MLCD*"G$U6P10ZO*X26)&S__M +M)RCB3MC/1U@?9<@OM$!NEAY'1@V:RN-B`*+5S5.5/G)M6B3"!LF2[@3(Z9,? +M0DZQX#'D+E*NB?B+33\LT36XTS(SFH",;`&L_CJ^ENBU@Z\+@%%8B8\(H\W) +MV&N@=]L>MRH@HX,LB:3F@=.\NU=PT(56)B)]3_'D<,NFX_Q5V%;-X&+=7*>D +ML?.\0FC8I?;]4"#N*1:\/ +M?3BKB>BB5P6^!3OGMM,/E50,032CQX<\9=?XL1/RCC]KFIEY;SIHU4W\__W)+VPT*A!)_GHU_HV$*S?="J\FAMI2YH9/QSN5K>Q!D=Y+6% +M<9-?F^^MU.+:4*DES74&UV$NH5@,O\S6M6%&:V8&Y.93*]`@*7CDEG6.()_/OBOT$,Y>`5IB%"%8ZCO\VF`N:`M +MZX7`4G4KHI[H,P1W"J@2.7'ZM[UY#/*JABCA00=M%MOWZF#:C!:YO@SD%V3I +M#Y^=M(KD_(1GNK%T/U^PHS@]R..6D^Z\/?^=-8&WJ9'%K\?/U6`&Q"$?^:_! +MRN`=0M^97!1\UL`)KUP^XKG&J$@_WC5&(9@P&0==VZJUQGHDM6';?#H;VAOR@E';GA5YA1O>A(:ZHX"V76D(EE!":JI4. +MR'?+6BKM*;Y)Z5F5^[UYO@:WP9<]LTXCJX?&3Y=O`)8L.'A848/9G^._S1`I +MPTIA%NI-'3NP\G][H#:@]]MK7..]#`F3=Y4-4PT=;]D+GC&CV"&F53^!F#C> +M*2->S=A58J_:VL>RN(6[>*NML8LW]B:?*T`2,>T-/Z1%D:1O5.UCY%4-#AV- +ME--1W"$BD5MHCVT<1OG"H:G!S87/;,B(FU),5FEB7 +M+&Z67&A8!RDO9Q5*H"SX(^[7:E/3ZO!$[=73VY13T$_[#`_6Y/4P3-5$<9R\NB]+'T&%X5[_8.?@%-0 +M?YG?F85J#,!S9;9Y2)FB9R!,*1-`#KC=5Z&'S0J/9R$Q'5^VF!+HP!J_[#UEQX<:(G0D_> +M:E+T@1O!T(]SCS/+GS[`DN9?!KS$#]Q"5%ZP7@]8'9(,4A#9])E(,AP,2G:> +MQ_\L@-$-G*=$V'@K'#"=N4'S4UY[DL3V0?]BZ["I';IBVC#E53P1^0WGJES\ +M!W6W&)"P:H5D*;9I(C/<6I^1WQ/>'C11<&H=,V+$",#CPXK+K +MS<&>8T$W2ZO)<@-&`W@>'1=?.,FAJ)FO4S;4XX6WI,M@+8&`Z+I'><\P8\:I +MM%D2R9.!WI`MG>@JJ\L[.LJ[E$Q03LILD"2\._6 +MI`&[?VU>D>-V4R?&0\,"0$`]IZ(H'G-M!A` +MTA,/:JL&]GN90#O#+IZB)'B&`BVH<86V[!P+ISGD=-^8R:`2F9L?B>RV +MULMHK4.2E7C@D3IN3X+U8.`-A,ZY/FK3#\YO!::\`+6;>8LM)P+R[PDMM>QB +M2:/,^*2A!W72D>,FPLTI7.Z#F;W2Y#MZ[,]:T7L[Z8&V+2 +MH<1D\YM&+G/H/%PSZ_"`+7+MMMJ"6K_&:#83UOFT;G9/!L@I.!5M!,L(Q,X9 +MM=]-2%D.AX%\5J(J9/Y+=JT:-97D,\KX"A&$3@BO?K2 +MM8'`QN$%RN!<6%_CJK$:NQ+&6WUK^HR&9CC8PHN3@)$TQ4?D!"G2O*L,% +MR[3"/3"Y\F>HG].#?'.Q9">^I)"'*2?0FA/^-TS)*N'1.#$6=FR,94)]Z"IA +M/)`VKZ&(:41HG2%![2YE*20BJD'P"8%"M8!7C11KBO.+[$+8SK)2+;-&_NQ; +MN[C+/UH9Z+_`-*LGHH359L:CTH30S%9(&:"OFI*+M#Q/=\I0O_62Y**2RQ%E +M@)\C5:><^"ZDC.7\EO&VF[J7M6?E-L)1WUTJV +M("7Y\B/\Y-2.OF(1%S,3;N+EC`_XA!(5;[^N(0ZN([38<[3IA1/C1.W;'H`G +M0P1!R"G#8="D`E(T/I&"GC+Y^T99J^S95N!WJ[7I)9;Q^&88+NI!B,OV8267C>:/YV%/V@G4>C1R&!$GL\C_.@-$2EF?LGO)G"";=+H>"V +M6^73M@@S`@OY<>!C_J1*]\=-F_7+^J86_BA*"L&@IGNIB9454^^V2A'/$4;M +M.&K^01N(+H.:$24X0GVYB'MRFI%MT, +MVQ1S9,S9U+?A\DN>,__![=F!IY.N!SXPSTPG5GG_G:)T3J/9LWZ2MKG0[G8I +M\J)).I/BZPI>'8I^OEG6XX*4S\JN23XWD#G-OB*>BWN!7+.U`[)>T&##AX'4 +M`"PNP;?\\?FQJN#*T-F!3,??"UT(#D7G)7;ZV2,2@^C)NJ`;@2#+I>NOK`AV +MSO8CE\C;I*"4+&T/,>K0X<[,?<\L/Y>@Q-G;=1D-=Q-:!.0B'%%I:+CT`&!+ +M;>$#UFK1-4ZITQN4PQ$(OCG5U7UG!H.,+3ED$#FLZ_0ZZ^6!/H=V(PB3;4)] +M@+'G1[R\)+Q;-,;LA1S^J7M+<(6I>]-[.B''YD7VG9X-/ +M3+'FP5?:'D"(.<)*_`(PEU4((DD>U+$KX&&R52U^5:P^*5@*?Y%Y89VM"<=M +MQNRQ,D%_?H;;_.KV%K>/["\\91HD&%\5Q,;A"E/1)R!QMVRR*ACH<(PP"VF\ +MOYJD-QEN.:QL4B0U.HW7$@P;0:Q`8[`O),3,E[>=472M\=15[IW"L@`'4@8K +ML[];QVV$>]7@(8:EXAB%-ZY=M\FU0G[2>+9.,53V*N:G69U0M@L\NRF]^/$Z +M>45GV7=_Q"OAW#(7JG1"V+4BAH(;,Q'5LQ";T:V?>E?Q5_UIU^.&KR8$@88> +M#Q$J.`]R:*O^2U`3]A/'W"GK&:'_16[AML;ML2X2;W#SLP+`K>U8PD#,_%'^ +MRG>'?48\>:*P+9C]D;A:@$N:@YU$O1PE8+=E?JTF3[NZAK?TWFAB:O%[I)YW +MB?DWAF+FYD8X44E6\YD7,.B45NGH049UETBB:T*QR +M%4%-&&W"=>>N]QBR18A[A)T +MSX;C3@$;T?A^<V8`%P[ +M7SEKGQI#N16,VNC7_TAJV.W%#\A4?N5UTF(IIYZ)X+\!$9ATV-=^*8_0L=%- +M)H',P\9=FC`!"/I][IIM^S;5!:79&90!X_F=:[:ID'X[Q(T_>]X)+MXL'K[G +MX0%7\`'2>_]Y%DYD3T5,,2P!]IA`DKKH;0>R2;Z$<%MH +MSP*U`]!Z5YN%(E4P/L0(7KG72)_5JQ$9R$1''^>0GCQ'6I2-1DCUK^^HY+6] +M;V/?87(23\#^*W,5B-E^D'&2=)Q4K8\[]"D$``VL]X^LJZW6^<"!X\,7ZH%4 +M`K4X_2CK+TMVI)6[_65BOBP!%><:.5BF!A.JG)(&-VS,PI_ZO8/;I29S\M_S +MOF+O,C2MALOARS1)@T?IB-<8/3=LGCW7@@^_, +M>^U"P1GM>RQ<'Q'T5J"&]Y_&$JMPU=:%`F+[9=@\L1`C%==1,@J1$4Q0\6KG +M9$0:_AH!XYEGT+38D)$.,7:*BQ!>WA)O'U#=+K%"TY`8ML#=7;EI*5-J_-G< +MO--WR*OL!Y\#1632T;Y%G$DD791/'&)D;\CN^/!\@ZT+'(Y53IY@I?X+'O]9 +M*I7/!^75IOQW@-S+^@/U:3]2/L.K_5&+06@R4$6#C6:%8:>>0PD?J>?<3'\` +MD[FW:936,!<;F_5OIRH=J\L"T&^_F<>[0TEA+F"R.5:%J6E[AF=7[ +M0OYD?S*N-KD;$*CR(D0AJR]3:*H#;+B)55Y+KG/9@7WS"T4YXLD.X=*OSQR) +M_SEXW[@_G8`5C29-^,UIHKSGNG@#:URXO->X15*"GD,Z"J-,!3YMI=7+8R0Y +M`9@]XV\BS/#RK>S4QE1[G93M2(1=]>X0#-4CLV;^#\:_HV^U]*ZTIO;SL]`9 +MZ%`Z5A="O^33CY7KX1LBQ0]]*VR,:5Z):?\[J.;\97?8WR+TWI\T-A"=#\+D +M'L5G2K01[BYF]@-`4_C]:1G=?37G7]FJCZ/<))H54\4]`]L<[YN^5Z:W73E\ +M_Q2AX2%.%7B@2SU,"JH*<6"/\>D1^UJH3',B0:6O-"CVL2!)#TLKJ1M`A]8& +MQG#4PSAD'%UXX+<3?([W`[11%%^;,]_"V*MU6%]WG(]&K/4R)1'*L8J)Z%96LS0Y[V+?J?PUR,UYC-J2D!^G'EO?5MT$+:XIAX*^T>QNX:2#&:[ED.0!]MC)'V%]$-)/ +M[$?6F>7CV;__9KUN"S0V@!7AH2[T@P[]@UXN66!^T]"*9-9_2KG:7JL4,D(^;B*>^JN5QD +MCYAH%F,U3J34*+B%C'5@^.X@'JKW5U$]\6F&(#P+1V-+M;L08XCT.F`U'RY) +MC1!0^`E^.Z]1Z(7M(-1.5+Q<;?'G[;/84\1%')&Z,U-'\D\SWU7(G4+K?E$X +M?I6/7%VB;V0X^QFT1>$\*_$A3#74W/69D3=>A/7&[I^_BJU.6)/^S_\DWCRM +M[,PX7KDQ2Y?<1>-E:++S=2WD;F=CC:+]!W8R_=59@,I?+/3V;K4-!,3;I`Y. +M3DU9>E@8,DC?HMN@4VA5[(C99;5?:,>U96+F=.<@@O@`=R!>)2[7*.>>NAAO +M_)?'IX'XM@`OO=&K8^7BN!MO4?P$F.-50C;NKSN9FV9JF(B>,.IG!I/ZM+E1&QA/,\7XS]SBOMT3('DTX,DG8/F&@7I&6*I#3"\V.WI-Z*:' +M.4C]RTUQXD1SL^5$&<7A[J)K:E^,MO2=G`(+K.P,^*]A*SRBD+%X"`+WG$,D +MMT[OP#@WCCUX!GH6Z*J'`OE)J4+:))D?:*(=+D$(O@X]WKF+UN:[GFAVSGOU +M.D>H0ZJM=V+FXUOY,,C%E44U@:9=6AKL_4V?ZQ760O6=MX?8:HS34?337?Y$&)HV.]W&$Y9<57XG(13DM:J^?YI%X^%XEB_ +M(O0]3UQ9/%IILM%J>D4\\3EE&EH5J%SRC3 +MUX*GX!$RI(4-ET2[%^'MQA0T#0RS(79+]H]3PIUD.00PU$;&FX8X/215"W)T +M-C)+\!"TEOOZ?U*.!#P/)F;HJ,N<>*+@AY[LG!:)A]PT+7']EI\(48\LAUSE +M0ZN%M___2Y((HV=R1_"BNX\UP?G_:H;I\")M9FU;V&#;S/:_Z`^22;-.P$I# +MBHW[XILA^>:O&O]DOEK^@N`Y>@%@9&->2SG.@F@)](?7!S3R"1 +M);;QI'$R=R>]01V>R;I/FS_)-]AT072K\$A:2RH-VJ451=K5$:.15FEM%UOF!>1ZB8`&>BP1/),I%CXZ@%L`G +MK^K'H<3(%N1$IK"`@O[/V*=@;0\#C2"4"12J@3$Q\!1^%MC.+#662\$5W];A +MC+%X'>@,%HP&;M +M7]*?6!>M;(E[A&[)$JH6/KZ:%>^I27:^X+/3(#FM6-$M*P`Y\V/6D4F_NMVI +M3Q]5;PK(7JCK.`?05.H1YH$DK,SP$ +MFAK%N;Q0\`&6'(_0?F&U9^P2J!G)?HGFJU+7.90?18]56L3&J..@MSTYDJ@6*+44>I[Q20>02U#BY +M8$=D>12[-OQXJ*"'-7H<=`TD:_D5"EHW[EY]`SEG.+/8QPY_F231?#VXGH.J +M%3!V$D95X)?JVJ:=TQY)B +M\^NG2K1D#YJ.E<2]3/S2%\';2TDD>OX+SS@.C]PVG%UD6M7W_?W^TSK\=J(*0P:"_&>D0, +MF=8'/_:I+EHF:=('-O+8\6],H=L:B)C3DL5)&'B9[[4:?R9'6S.2V5Y2M[(5 +MF+KHU?C7TE`)19$>_-/J(;KETL/FWQ\7WDK0F=#SR!0:8$Q1^``%Q7="A&?'D.P +M#5\XG6/S*#X6&'-I`Q4A+JI#V,U5!(I!`KTPDIA5UU&U5\E`(#7'N`=3"!'# +MP-JFL,?+JDB/UW%]AT66-'B\<[!!K$!6HX`C'S?%K"H^JG8*^+NVB3]K(XY- +MX2<6<&4+"C\C^1+*:B0'JLX,E@'6"Y1ZY'HL?PW<&>JTV-UFNL?I<1RTR2%:FI7UYERH&\E=)HJE=I$N+ +M;%YQ-Q=5ST+Y5U'Y,4<6]B"_YB12&5,TK.BJ,3X_8J3CHGBL3&[7WODS=!?@ +MA#V0@`X45T\0N>,?@$P+B%!T*>Z'0>;IEH)'TF?C@(*.K/"#]V +MVA+?%Q]+=XCY +M0#:\/4PIFHP27PJ`O`-7([9_>BKQVYV6X*D4.)E']:Y`EE,X/I&95:(%FUPL`.%P. +M!2";B?R+*HW79807"VRK'%AG6I4.LQM(^#`B0K:8'S@"_A66 +MV*@9BWGCJ$TVAWZ5T(N0N8L^]=],ITMFW-)PA*KT]0"%K=4S_.OABX^\LS1/ +MWYG6LA_$`\^<-%@LQ3E;?[^_M%;6W^`W55_?WW8'\RIV`OH^/S)2CY6N20SN +M$W9`O#220]DY)K%_#SE_I-#?%CV5(^[\M7NJ]&*PM'S\UK2`:?TN=R>Q?/6H +MB42^^4,D;FWFA5&-HU)+E:D35,OM*4VT,EE1H<<++?%< +MG=*>4&:OW$M8CD#8YVZ>`KT3FZ-1/:T(+N&A!1O/#_K@G1/G1IZ"<(@D;4/4 +MR9U=Y#U%M6>65@^0ZK\I^%>#F]_OCEZ+F(MFR/0M-0.? +MP-*]2JJJYAZ2U5;#_U$7GZUW[^,@9CO&=G3IB%84X5E"Z]9E==Q`72%A6?N7 +MYS+73;4)HV*OUB<`#TM5A]S*%LFLZNOD8-C"R:6CO_*P8D8\G]BF=SK[S*N" +ML*0(%3:E>&'MT$S8?_D60-2>T7)Q/WSR[L-@(D8M["P]NK +MMF1<47X$L-`H?"Y;4!8;!9`",&:%\;0PY1G8PK)]&BKTUW&^^46BS:LOZEQZF=*8$G@3L*3OJZ.7N\_OVU<2F]^.NW'G($%K9CM@ +M(!F#%7C`!\T@4GIIS9OY??`\"C6:>,_V#W:23^2*^PTS]`.<'KFK7@=X3-'> +M!J'\[5GUZP>+BHALA_*O-+^,(FEK,ZW".AD6^`KM$*:-_KEJ8Z9P;2N-&1;S +M?OI^O!YZO;4*047,?BL$3G)+SM1`XP'K"!/:"(;9AFC?1=RJYGLVBA"F8C +M;JV\0_U*>3!)4Y\86;HV&K,N8P7CA_'CM)XAI..)Z'!N*@`I33RO,,&! +M#8D8FP@I)]A:[N;PEXU%G)W82+1*:+(18)"^3.+LY,#T>:W`'G0$D.=?)AI- +M#D[B5]VQ-DC3/K#R:KP6L:6*A^11.A'/8,-A%,BA]:[?KRZ;YB^8N@#!7!O@ +MRQ_[4S;?7I(Z9ZKD\.9'D)9*;_T'PL=28PGN033IRM;R5F:#XB(ZY=&(86G7 +MQ[I^ZP3P, +MX2$-#,^Z!R\_1T\BG8G)7.D7@MYNUC +M]>HLVZ?'X](A1[QCX&8+B6,EGV"6>().O+)HHC/`N+*>_9Z,L0QEK".3TL:' +M]JD=&=(90A_,V$JP1N0J1OH]-MPQ%2;%"L0Z2B<*[]')KD]B\KYZ +M_N6-?6$.Q#9->XXO(K](_D0!_D8,!I4P\*PA7&'U#'/RYZ?PHI_^%S=#]`6I +MY=PJ0AF6JWA%'2H^%//#&$IQ"B=!,P%P()T:5>F]+>.G"V@YV; +MU4XN.3%JOT-.6UVB%S_-<(;8Z[)9V"J>"1)(VM?7T]:_5-WCNUE*5L3PX$M. +M.]+6*BWTD<-;\?_@NGUM<9H[ZV2;,YM3_]1J`.MG!I<&8^*Z-]M\\T&..T"T?3]6?Q5+F52OP>4T?;6?Z.F62I#>DEUP]\<%$^P +MW(@71B3A4H<&@]+/Y+2[&:C-A7M9.>O>/I@*J'_,:=ALBV<7\A__*XE%AO:Q +M<2QCH#?6N9X#!U\:TM_Z*%'U\"]$?@X3:8I"V3,*J2T#;<(="JG*O3RK"6&6 +M\7_!J`7M[/MP`/?RZ;'DH%_!:C]V)MBF6]#UI;!X;(Q8Z8,?SU=^VTV5I'D. +M<_N\N:,Q9@'IMJ_XJLRF4:)+>N;8\A7R0P*IDIK&G?TI8L/]=/[[J2(N[CAT +M"K";,GE&3TPYM.6QC^B_]B%,-Z7 +M#N+1!^WI2M+4!I/"[@];#/"WX7Z9N3S^/J9S$(18;_D]3E*HV9G4 +MJ*WC!-EN871V;?T%]A0`F?YC5DAMPCEWW0M[5FW!>1ZX?L=7'@5ZP6$=A9)^H] +MF7%1U6'M('\VKV?M@='EEOKF.6V'Q5_&)&NK\6U5Z\9P`R +MTCNVX_F8BE\8YWB,Z*1A?3/%E2#%:[X^_V^[@]YPV$8%#,-5@`,>NX9K7+*) +M<1JC&)6DQ1Q\%<&U3Y$SR;BHKC0@T_VYED@'.!-Q3E7`L$@E'N'9S"VUT& +M/,%`5F$_5Z(V$:A/W`+I84$&GF(WA1YZ[TM5>JXB@%.=11\51-O060^@JMYEK]]FF92Z3 +M$%0]27)@)YDL:BD*;4$<^/'!,0(8T+S7INVY"]*P4'WSA>>2@WBWN\W:*UJ? +M\C4_J65`>)#AD*YOYHNR[]7U0+VY27-[I5CBRT +M6_EHL*ASK?R'2)BX(E:G1`-3:UP0=O:]P-/T+`T>L-M$--C6\D\MQH#OT,(! +MGP+%T<@GG'(]J=I'>'C)-TAOGT<`.F/1BMM="3:51@0]X/JU3YUL?>$,+]&& +MA65*C;Z868@EGA$"0DO%3K(_,3,MG7W5YU6T(PQ4.(8**;WSUQD_B?;4R+,G +MQ8/>0[%EXRG@4HV&]'11.06$_<*IY7O&*8>A;$W+<9^V[<1!H0WN)#6R@=)/ +M\5:.@@R#`_W*/1T=1K448!?E1@MK&E)W_#X12*2'(S/<1?,IRB>4HH)CZ*78.RO>0D"WKY)V^L(_1T%4B@:J^6P' +M@*\@]`WT0!<*<=J*R4>Q&OG[EZT%]7_1>F+M[66MN4%!`M??'JS@K0V&XQUY +M5_QO)RM0@T'[`FQ,)XO92&2$P$V\7^W>F)-*NT1V7'`-WH1!=I5P`F&$8OK3 +M4>),[G+>&I?)XS,V/HDR0%@%#OF=ON(B?VFZ +M&B$&:-^*2X-S-161JRD5#31Q;_Y)[]'9)D$$2 +MW5IR)?JS:,XK*F"#^K'Q&8*:2#RL`HDXB::(&RKZ9IN$!0K@CR6%`^L]M,FJ +M8K!BTD%K3TWT96H\9JE>,5]5PNQFOZEB3_WA0+J!L_@%0?&+;W;O.]1%TT5Q +M$G9N85X)LP?>1,O.]*^;B`O./-&RA#H->*]Z*G(R+91@6E9W"*2ZZ74()_*F +M[&*,(@JOIS+^>P('@,881(BI5/HY]V+L#^9;,DEGF>.3\:6R6]Z'*%?"B/ +MQ$Q-?OF])\9K2.5\H+%9RN2D +MP))[W#@RT/0`*W().969R9[VI?.]Z>@O/WORVP^1C_6#YG\]B>I0011;-GY0 +M`KJ[*.10RH)3+J(,7QKK+9`U47@:VT1Z::R:Y%^Y[38V)+C&K +M#:&?0!T@=J=1SG%D.K&35N/]POOHO\%BR:P4OZ[^JOL4(,8D?W71")4BGT&\ +M5;IRB-_M@\0S4OYUB`IW!=NR+TKJ$=Y9W@FY94[S#(RQETEMDV9J:#U[+KY. +M!RG(-3N11%K#.>T+'F<]8=RW8TW)"XA-ZA?/O\Z)&/,`&'`_&,G+GRG<.AO: +M[RM9&WL,GS=5BSK^$(-B=KHA(M#OWE)AH;,:0-?PVS^?ODSM$'B3]-(&,@_# +ML+N5]W=S`^GF4$I$`,_OV)64,HF"'F6[>..P73I-EHV8QTT!Q)_7DV-Z$6(_>>L+IL$E#HHTC*@2)2JK#>S?PZO*PY`XPSB$HW&T!L!/I +M7^NA",'$$),A[DM!!?A#9=[(1%.I;=)`=P%7/NG(96T&D^QNN,;H"7W,D2H#$\U*QO*SP4'"I>?H(3<\O[;%"\V1,55+BOE)'U_;! +M[(0X^/[TG*'+4:?U;2Z%>827>M:AYAP?7A]P3S28;GD`;60RQ +M(/[HP"9?H/KDF(20CE:HO42R2*Y>V^=7(RC/74YT/7#O;KRF1`'6AJ,V-R47 +MX*L(?*3!I1K\D)<[]90V(6G.<[88.2>`/L9D'Z@[HDF4795V9_O\TUSS4KG# +MBP#Q$&JK4T)8E]PV$(2G:A,821;8?#/OF0N_M8;+/-+H@K9!34RGEQF.8E[_ +M"UIJ?QH+I&>L/4TZ\Y^5U9)H1\N8+^3_7! +M`^FH*^M^AF/[)J!V72=Y,<8?LH4ACY1^I#&Q5''4.PSM,9?ZL?P]*B'%0-\2 +M$J]/^#ZG66^DO;.#>EQ9P@'S\8`]?O"H--C@"5="?WF'BX!D[A@:+^.I<&^D +M3.A+^PU#N[D5"K?LIDI.55-/`V!D#Z/&7$ZF*6$H\V<"5;[^F:/7/.00"-WF +M\XXY]4TX\6=&3U3!(5*^B=WRJQ#ZB@&25UQ=<,;M;-BXO5$6^1N6>0I*"&GP +M%[*%7\KA#@30R-B)E!Z\XR:C=Q_RV'ZP3/2)6=4$;_Y&(&UP8"BL4'@'ME.,5M,_AE]SGG+`J^5=B+K\I +M2=1XUET5*IUG4`V'$@E,)MV/[`_-RJQ2R$76M$-0\>AD'5#%@._WY`'?Z)"' +MC]?R)67I10$D1:WQR;2E"U5$&*,1(Y1CW\&[W]O$B\) +M22M>)FN(4_3;^/2M]\C"A#.9X?^00"@F]MIP%)\EPA5.=Z]WTT'YAE?OBT=N +M",0E?3=JF`VU*@H+(`5P0CN)VQL-QHK&\"DW<*S._LH)GBP9Y'`;=@'R$L@I +M,@!FH4"8M;>0+)>*Y?+S=@UD#(6;''\)7&,K%E"T-8Y&;[%_*P4-G%-[*TF? +M/(ZJ?)]5P76M/VZ3$%XL3)\VQIH#;#0P4T6\E*!A9,@0T,F(*62Z_;/8KW\Q +M[7.L7>NQ&IV6<9$[MJ3;@"6?;513=U,WVO<#E7@L7@TY2ETX\4"(FS8B5G<] +M.>O(N>!/90A.F02XT=\,43'/_;=YN:V?\FDU3Q0BTPQ'0:>/M861E"VD,CN=Z^< +M(VD/OO+(VQ+%X<^/+C(Z$?[&Q%5RAHB[M,L%IY&LJ^CK*HX5K"CNXYP.YJMO +MSYM<\!1D7P_F;]F080ITR9H^,^SZZL1-H +M-:,3WNYV0./W1KV:#L)-))MMU)ZM7KW83DF=KS=^9;%ES=EC9H744GS;FK/X +M^O$J?R038:/[[(F4OUY]%@^QHF;TW`S\.R-U^O(%&#:O@:^:*3H_(SW!>C9% +M]+'/R@/LQE<(H(?QPL::J"IYP)ZEY?_6Z#YQ+-<;:$CACFD9E&]T9)/R-(F! +MY5J`'E[7L:&9!TK!+8H:/BLT`]HM%#A+Z'S4VTK,'_W"J8H<`A/C)!(5F)IV +M*,KMM\)->UCH3_74K5%2:?C%G3"^"!1)V"M.-<3EM\Z.Q8)W><\*ADG]9I,7 +M6;$0D)A+*XQZ$Y9^E>X630RH4LX6,FX-YTVE!A>,!KOP_?B8Z+?\ZQK'JM"3 +M!1?>QN5B=(/J^1]E4Z\#/3*>!JI=(R1RV90,W-K7T5#(I:9":?"ZE]NH386.I.&$!,VTMZPZ5 +M$/FZ7SZAZJ/V8/)(*>RB%I,A"$6W_+G>J]Y;)%3DQA>1XL3/!!Q#?_N,1FG> +M=J6$<,SCPFZL6R0;,H60]J@=MVL',S?.&K-S%=9@T;@10+NL?^ILESOSR9D1 +M\AEO[?=S;`2O2O[U7V\4IJI-KFT?88(RY[/DV\VQH$7>M(]J'W8 +M#!I]48T!,"GX2AS!BC@E&W)!?HJD0)1AALC'*GN9@4K8UCP,UJ>4Q2NX5;?X+9';/B'D"&ULT@;G=)4II[8UK],+@LZ=:2G9P4UU4R( +M'0*IX]GZV-)?G?'F)"YVO2&6ZSC$6(MAE))0J_I8"8LYW4HV+6ZC3QA_`P7` +M>6J,OH)[B3\>&.*UV;H#65R$;L=8#^(AF\UU)?*[>H+V);M(@'A,J%SH0WBX +MKV?NU'CS-&2[6`>]D)\UAF4[>7-89A!^F_/'Q_6V).B1U1=, +MWK#FBP3'G1/5.9N8P"[2K%EPS3=\6>Q-:)9VN*"U1V$J!.?X1USBWT>[KEJP +M\+B>(0Z%OW_]'=-[$7?+<.B:7/;[TSV!>LG-..N)M=IB._FO8 +M!TV.=H"R")<-;)QR;2?8?1#2QR2H_`%;;"![!ZL$5;`J&#W;Q6.=N;&4I[(? +MJOK?N`G^A]VJDY@ID\6N^\_"UT]C;$__R;'WSYA20)Y!5<.&N:#V^3ODWG>; +M0JI_G;Z:%':QPA8/!E97KG+IA%WEKDQ%U5T0XX".U%)XWNQ]QPK#EI!]0S*8 +M;RU-/4M/P&381HD#%9#O:;69!Z/I+W@M5'6.(GI$*SOX[2E:WJ/L+\'R.>"T +M7%KAC\N76*]0WDOL>7M"F&LJ5^(`D],14+[M87:=:ZH;/SV*K]`6""%V_%=@ +ML3=W*^),`_1=AICAV/.0RK6&ZV`C4H%WT'?-/0XFA@;XH2KRGJ-EEPY1)V@F +M!:4.[V,_-'X0R?0I4WLS&??+^=G+JP$2;^7F-7&@[D;4M8)\=U3+H="JP5&G +MK#3?/0GH\$"?XKRJ>I@!OU/RY(4F*<"F)9,\9(?*8QNIX@K+`8'QEKBO&F7* +M@X-#YWLQR55G$5@&,,WBSK830T*,.#QJ(>D_I!<>+FFV?EB_1D"(#B)6''<& +M,T8,ENI'#\*9Z$XJ*FR[:ELL>MP@-#Y;U=(0G74%']/.HV?99+#S'23-M.WA +M=N"=P&:Y]&_[H!O@M#=VG*O\O'O,;QL08WON@&JZ-NP:%E&_ATNG^FT!+.[J +ML(8)1I0H,P==/T*'(=XTA:#F(N"(F!5J>*2IWWP',T=HA5C`(:`,]F?9@-(`I!WD9FG$9 +M6_V:BCR^M1Z]'-PG@>%!8O,?[UCM!9;%W[E*R[5ET'&P2=(Z.AC>1#G^[G>T +M=Y(I07/!TTUB<*X&,W1\[O?VG_!9UY>K0#394$*6!"07]X +M,?2-FTG8T_B3SK[+&6Z"_?!41GJ^:G1?[A*Q#).TEZ$J?U7@XW194<:T3=G# +M,[PG.E="#`8UD"57=K2,\*$#>%T=HDWQO&*2\I.GQ_SP5KN?E+8.&H`$"2>Y +M@6?Q3-9JNJ[6$F?9N@@8^H +M-[4\V\L2Y1]A&JG/+$\MA;ODV-:`D^E-B3U\L0Q]&[O.(4.P;QJ[XL6UX)_8 +M`K#RJSZ9^)IB4>?>-BQ\X2_*!!]\9^H[V`;`_%['XRA-H9M<2Y[4`.9P?4^/ +MX3`K=F*]Z4()V"@`[!7!OXVO6]Z'.%=.+W-$T+7`[I-I>2P2@V.C.Q8:D,KKW%^\!_9`,YUG-BRS7\>C+/WKBV,8!$YV[H:R1 +MV?TA.0;)`3(T=&HM0&';Q0'BZ7W'#Q)'C"+'I"8<:!>I:S\9D)AE7\XZJXH- +MFEN]9-ZHR&&>^Z,'IHY>Y]R![V('L#RIYO;[/X:8V*ISZ]3=R(QJ*8[(B"=: +MII&1VB%=^(1,3$=Y_K48]MWRM5ZH/`0')[;+F`#R`PH27A&+0YV?K,./!MHX +M.)N*06[BA$:1ICPJZC-P%XJV3`D%CH('/\).VPLQP*(=[/^WWO\J&H&0XY_E +MDOY1D'9J=)1317M$1BZ]WGZ:VN]XHP9L\>)!Q>=!:6\HP5?623,8$H]MT]7< +MCOB>K9P9M35M+<`NB&VSC?MW-ED5="[;#I'V%GNRTY#Q3L0*5:A\]SK?+LMQI0YW:_][B#%2\LH*NJ/+&'_1>XD4G5`A.' +MBUSOC-#7HM,?;RW2M"MLHO]GK"?X8;J*'`+#-N74K%UL?D"S6%+3M;I55OT$ +M'SCA.TM>%8]O6J\QD)]B\^1>;9N^MRAK&&:J*[*VCGA4X[OS]!&^]0DNV6*4R-4:8 +M@X2A1TYD"(D%[>=9#^9_*0M#*R%%F7-^6LSVUD4D1CEKH%Y!XP%,H\E>F58:B&:E-%FSVNA3,-*"/38F^R7 +MYE!,'A,C@MJFVU\W,"QY\L)>8S-N6\^.,SN0@,83=5S64V<&S^FH%;\:*)!+ +M2MQ4C(O8N@N1L$VK;6HB8T^Q*>[=.4J,>%@E3;68?@\;V +M*I1K^167"'#K,TD*3HH^3T3H;7'U0!'UBH?Y"*K2[%BO5"]F5)&ODK9G^*"2';[':-> +M&2SKH+#=93[0711[(0JUN+'7?$,(QM)N`[OR_>4>[A62JRS=`WNO2\9BOJ,_ +MLI^//]_=M^!_GQ^N^S22Z)HRZ[F2!/5O?.-[FX[Y$O +M-:]7TZ-!&+A#K-5-8(F7QES0Q=P-:7&U:'?>5?U/RTAP-;C#B!EM[LLZNT\9:+[7IR5!T>'C#W0]X)W$^2Q`6LHGD$&=#_^;&4& +ME3`BOFR$"A^`MQY)#:R8<,=)X6&`<5*AM(_NY`;92N3^")B-[^>Y4BN,2@(_RQT?!81(NX6 +M?%A&V:);G%&A>PCV2J1MB!WU$:>DBFV`H_\2:[>!1"P8OX"]U*N&:\>$2@'V!N#&! +MM)::[#&Q.YF5X[[;QFK9TF]JJTA(XG$O6/!5/OR-]7G%-D<>E=@[@QW +M*<:)"H.LM_CCHL/,JQ(0>\GWM6(3)GM`#%"@6=0=5!@EI9](@HV5].GN=;[X +M,WM;J0@C#G1-DEH8=3^_DF'E0\!![1YQ>BNU!,]O<9QQ8B%5@0KORPD;$QN` +MD^5%<_=(YM56M^4!1D/3?NL"'E[#ZSXO]2(Q9[(#9UYFGR9U?FZ*YU1:FL!: +M,"9D+D'F'ZI5A.@C6.E%0:HG\`PCS%;%3;F[%77^FY?GY']MV"$(K^)<\_BT +M>I)"8O;)+[F-:J+]27RIZ;_L;3B4V'-S_J0=C6/]>G\R]%89?M.=LUG)=.\, +MP6%MR]RQ8RWXO!-M6Y4$8/,K7)E`NAD\`[#LZL`LM=>^":?1 +M9Q0(:D")Q=Q>@E(M8`A9N[.U_@>S+2JU)DN.=:@$@ENJG"1ZZG-NKURAK"4SU#C9 +M__M&;L>(D)4%O0-%`&+O%M/@[8;&"!!K40<1<%9GT9^^D/M7:A^$N:-H^_A" +M"YJY"KXX,<;"I1V*8)J;K-4LNE,F-VE?LX'(J1 +ML7MI+9-P9>HMZLZ19+(L3KJ^6\*#B(SV;.NF$XH@EZ%(H7!ELH#.U+T@QEY_ +M.#1JAM@B)G>-Q)N.8/*'VGL^,7=^HL,=\X;*#.#?#E[KFSM8B"B/_)ZI*L;[ +M*K##!Q;IT3/POF\8Q*OLH9.QZ!;0(2;]6`89FRF&7,6W11Q2YA$7/34D)I#=%KK +M0$VU^;X21(_/W\?Z/R<#K43L1G2*;-3/<@7K\J_.2\@)4"E=_AV2\+%W"[+" +M`GQI.PY:609M?-=X(EE7^B^*SZT+&CA3^D4>-H3R-\0+"+;/YIJG +M@+`V1PWR(%=8@[S:VL!JN2:RNNYW#:-;BZ@H-62MZDW@J.P@1:LL0[;>=$YK +MI!6T))+<^="R-MAEJ['+'VCD.+CGDA7)544B=^YG42TUM$D2>IJ3M)I414HD +MJ'TIMU^4X5:DRUF"E`I,HPED[:0J,HJW\,[]ZWK$=;$NG7?RU3IO(9`JEP8[VP.A6@>*EV&;:0I +M>86_5XX]T8!:.`^6FZRFFP.6"N43!F6FL+K[L#PY9!77F7)%7`X5#KG`22+DYC.BG_8K=G'% +M1:]0P;L'AM)O]>#96.D/E\<.)@:B/A`$XETP-_QM\58DS0-,.C1`CVS4%N2>CFK7BY@.1L`T0K5L.EY@( +MWA$[+!D/7`TZC#1S#JVQ5+2+PR4J>G"N(-IFM'SK_*&#$EV%??E(AZ^1,?*8 +M93(C!'BS_W()D00_*9`?\COO"ZG`&&W9MPB]ESNB5L*U93=XE$=:(Q_`'IM+ +MV4!V2@O*DE:E[/4[K\F`PADQK->#'7A\815NMWF#?B-TUP*#[CHXP'^'2$>ODTI'$L)_ +MJAH[8$_0%8-B#B:.'%_*7I)?;D,QZ9X4;4%@%IITXM"G6GX!]X8$\%"5(M4@ +M,*^$5AR-@7@N9*+2MR=V("KO%GFH]D0M4X:>!-1;6+_W,7E_.KGFGR6,U=QA +M#&WF1N7"\PK3XJJDJ?4HF>$.3;>Y3C&)-.(@5!#A<0E+`K +M%]^E\M<@$ +M-;TT>#HQ05[;[:DO-Z.`*6'3[]SG3)?VY/,'SHJ]%Z^T;'%3$2RXNMEPNAB) +MDS!WO+?+798J\+5U`Z#)`7[&>`<5H; +M6%306Z)>AKQCO#\.Z^9B,?*LEZV`]])'93JD%VLW:F`QT![EWLPH5;>)/&7> +M26-(L$4YM^NI8G^?,(9+]JVM7V?_>4"OD@,,9:FE`>^7N"?ZZ9#3F@^F__!C +MT+>[,_S[3!O2I)9'F][61DV=,:DC8L>T,"B+XN!Y>CR?UK!M5-HN4\L#^#?B` +M;H@&F]V#AUJHL\5!"CDS$C=4O1*9-O#H0@N$='YD)^5U9->MK=EE6AB:"?PS +MUG`SG*%[]$($L!,::6A0*AFC.]^?S[)LR]([ +MHR6M>E9RUP!C[S[BAM2L>=@Z-M_38\K\%6':S2CE[?CVQ4[YT0$,]*3E1E6I +MZ3$M_--! +M5VRB4`<=7?L!27P9W,DFQFYS&+*[;"D#D,DG?02$9"NJ+F]Z8=:5FCF3-H3K +MI;*HZLP_84?@<(.2'#:*P(6#4D!M/;WV!LI.096Y8V( +MH(4Z8MY2#4_CLF+"O;<5;IFW3FC+]+^4O-)U>4C!SPU!Y3-1=N]68<)^5Q&J +M1&M*9C5O,Q,,X2B(O8V^VFU8S>G-;$E+\:*5JYQ%W!Z-.C9>J+]?<]=TNF?_ +MP4A^WC?_;'&V)-@`T3#UY>9BPISBAU[R]-[VC5V&!5SGJH<1E?V,%W1Y2I`T +M;XG\F=7W1PK)MYIH4YNL3'UM'XB]%JJ@>18)ZK5ZPI4J\4_]-[R7A4B60?X# +MXJ&T5L!W"K3TS]@@ST3\\+`(>P-]@KPZSER6H[SCT*.BCQT0MIXXKH&KB%8@ +MHR'$4=PX[0?7+AZ>(Q5CH>5)XWCO\$!0=\\86DP/H#3J;''[\]371T;YPY24 +M8ZXM0+FQ:7_6O;P<4!_(255QL:-"`QX,/!`:&XD.B@FE\XF.LQ`O#5@LWZJYJ0R +M0-6D^ALW^#D.F6@R#=ZC6W5HPJ=/&G$7D%400T8LLF8 +M7!4+@:Q;M'J*\YZ!#H$*GR6J^IBL')`6)IZ,L4Q)BH4?YA6>_8-WB5-'>?`= +M^^F1;+0'"^\FE22/4&1]3CHW&Z8M/1/B]@+7?()$5:T4N;( +MN+V6^A;$*Q](VIB[Q0$<9=Q$JE?^=0_DMHA9=^"FEX&.HV\TE%&4<$)Y.W#R +MNHT_-O)6ED2/!)'U":HQM&Z0EK;GC%Z6=;#DKPRAX1W;:`"^/\37A7>JNCCF +M3HO.-:O!9&9/=;8KNLQ):F#(U!(R"3#^P_Y]7(_#$\`1E;X+-@Y`[=N@)YR6 +M21?@+I0V?WYQLBM=#_^11%T.IM.W?9A`J#G]X`,:&)&C*>:^'[M`E(-9AVR= +M$`K93Y:3S`[6E%O?G#.>,TE/*&T*U,TOE[V#<\CI73;NG65LA$_UE/5-7(8? +M[Y;1.^$[_:=WU^=QBH0E5%*(SOSFF)G()X]M458$G%:;!^ +M&L:B6V>X89#_,S8JSE6/4C)4[.E8)C%5S/!=L*&(V?MEL_Q*<-`L'2Y/+4<# +MBL*!6^WQ]9-!/NPM?_9YC<2*NI/'*<90V^]>,>7VG%*I#6$:2:@$]3YK_ZAE +MBT#/?&6#'IM>X#_LG(]/^'S/:/.[MJU$=(`^F^73%V8A/FFTK&`B#)P3/$VA +MC7`2.#S46A`Q`8!HD4<&G/H)BI,%4%?7$9W1@'2VE;)%B2H'<^]/>B9":SNG +M823%^>+-TX6K<-.?YZ]9"1U3]EQ9\Q-5,2V`^5.3P;\ZF:(^JS83"7.B["=% +M5RFB9HN%Y49#O/LLX4)5P<.>_,7:8V/-I^]AUV372?W1_7X;:!A.4-68[+?R +M<&??^R,XA&K-6SEIO8?6!?PX^.ET%>,"32]H7>`O;-@E0"O*WX0!D0(>IG`P +M^EK9.&ON8E"+6EM<&,OA*J=2VUV--5SNXHC+!SS954?1'JO<%EV783:ZNM2- +M+]'4R900^ +M1Z#==`D%\0VXZ>K!\_Z1AV5W]L_)%TF`$GBYIP00S9V]7#^'5I9NL_W$28L? +MK)-_=@8_8[3QF;'D.\)2L9L4]]YQM4-#!$,&@Z%$FV$+VV76M_2T]@/#;]&;Q$4EBSREYUQBI(1:%*U#,*7(5E,0(B2+]3U\G +MZMJ[R>Y^-K^`4S2_Y^&[Q-X6@!XHCF>L%#AJ&UD)K)YOIG62SD2O(+Z9_AB] +M6NR.[$13XMX*DDUPVCQH[?U[F.DXZCG:EE9M">U).&9Y[I@QJCH[S:H2-V_# +MAF7A+PM4J2!?SZR?(!&M(TW!;FTJ%5#2&30_I&-;PJS8UAA7\":`2V/A:T`] +M%]R73;^=FZXDAOXF&^L831J1&5C:K--YX7E'3OV"XSC\N(1;_R:EETMTSV,< +MYLF5F4>P!N90CWGD*74==K6813%=@"9O-(1!V&JD;G^C7`.JZ^21:<*62NB> +MV^]PG4D60LZ2[_1ZR80""E5`SZQ04>X^/V,I*]6=&JNE2#QI$Q+RE`16:CCX=!UD)L +MYM3]*.S@"ZA4Y`Y4W+4D]5(I*RQ:U/6,,B`VV#R.9AD";Y)$WFZ9-D,=K=@C +M9>*HP9TNAE05C=:[184QM+1O$FC?W>0Y[PRQ`PSC;$1OZOU282,J"JD."D>5G*?'` +MZ.M8?0$+'>;]M*8KO:*T"/@D(Z!'2MYV??#X/U,O>=@7,DYTL"QXGSU^]JUTP2(6JP +M%/ZXQ3P2D)6\H)5^1V4PYY.U)[E_T>\;M'G#A2W*9&NZ1*YZE+I^7$[*/3PX"AZ9J(A+U[,L +MSUY,R8[UBX8_&RD0R8HC4\[*D$4=+K"\QBXRD42E=G*64#V>!6V&1%:P@UUL +M6OV%9PCS>1MAT&+E!S_@U/@)+@Y;[V(=9F7$&?ZZ!-(7A64NS*CY%-_Q45-J +MPB9/XL>UJ"M1ETQX+:`\LXM!+5L$ABU%EC_*89U9"O_]TJ`N2H4G@.=+Y8BQ +MG9,)[I&<$-MVFNK5Y@*.,*J)C;>%$..=TY+9"WC@52U6M!4S-22B"N?T[030N?B&-N\-=`G`2) +MO*>QE(W>>=7>&"E)N0)EW9%7;:X4^=H#JZ2D7 +MV_'O[4+ZQ[@C0BPFMRC,+;6%=1=\2.>N(ITR)D5Q$70U5"F\G1\#Y51QG\N6 +MGT3U2:,Y`W'T32O"6T,,@&J'-FF.(VK588IQD^IJ-SVB?%*4SA677U+.>6Y,'%QY:N,XE1 +M`:;NV'OX&!T8/WV$'W\W0/-N-+BR=C3;8<7];:TE8D*Y*_%; +M^U<84]FM&"!"%*H&&1?$.X=&F`.&`HZVX!HA,LO(,O%Y,:219K&0=\3D`!)$ +M#>[(6M`X+_AC`H,"0VG4,%-IL&0S.BW@?TQ!9FI!K +M=L*AQF/5_QO4PAJ[R#T9]_>LKTBFM.$N590,'(="EV]@[&]&[C`4_:^TV/-W>B,K>VS0(9>U@"\JK&>`?TR";67@D"JCO8$% +M7%!'JH>_^S*YRTLIDSKU0-BU"OM9K>P6ALBKJ,(T)1\/.9$)V#XAH?:'^"6X +MA4`SX,1XRBG"-BS!3]FW[\^IT`Q(`$9=@)+45,,?(S:6(D$]C"&1R#\1*`@6 +MV)&0S(Z_=4:M993$5]"R,RO3MU!5X1-IC=C[O!30+X\LR +MF`W056QZ3L5*<`"N!E`.1"D54(U5JC*#:`?-A?*S._!@ +M9J`/#:_$7U-X"7($T+3:4=DZ<]+7.F'KDM&VO!N2&S +M@CQ?UIN]?Q&*WI8\3,,KQ^KFNA+3Q<$ZC+I%,\\RB^AQ]FLL>J#=O? +M+N-R8CZM)K:?U]L:>%O*S64FHK#7ZB4!B"W@,-/8(MX8Y.F9O%NM'QFLPZ#-IEJUV$$>W`9-><:> +ME!NJ>'CLQ&.YDA?OZ?C@WA@N)L%?SDO-[ZQ1H@)2IY#(C<>?[-R;"U"%J."I +MUX&&>-Q)(@8L/3>H'D00ZFUW6&%(:'*@<`W"=2'$;VLC!54[9_\FZ9$90(ATO#I;/!T&-Z<5((G1?522D+CCLKV4:5AY9OEVG +ME).FBE2`4RE%-S_V[PG63(OJ]+`Y0WN&^8FFHV-))_M#,]QH0^14BK2PCEMF +M#R9FTZN7/&,3A*(T+?1%1>QC#8\FK7GL#:HG]I2,6``%]+!U*_03*AJC),PK +M.%=Y:PW"[?,GQ'/[!6F"@W<#FT([4<+`TH"DZPJVOP2C@1V$T4[(^+Z<=U>P +MD-,W*/CYD?WWSZMJ^=0CAFXOG+$UD1(&:*OU5#EH6N92:_)]\&\=E/NS"W +MN.O/:;'^R+*B1V\X";7G/J^_YE))7B0^,$/4V8H(6]=G'1'EW#W9\53!&ISW +MG461H#4/N0QG#OY?[L+\`B*H23%`K;YTQY#A5DP&#_W':"APA-V\%F\^K$8P[EU,1ZR0>"D5E9GA>N/-Q:R3'25>.)-C9IQSMJH +MEF*KH_[?AI[($M_Q%!5O$#4P`UU/O:3GSS6T$O1CMO*'@5$>.^FX0SW_3]^Y+< +M[Z%W1H.*[>4R8%1#N^5HLPHV0&1'ANP&/B?K,:X;Z"]K!S',\4=QYG!DJZ(T +M6`UDE\IL'E@LLL>#9RQIDY[RGYR9(L.@[OF+`-]\4:U!\V>X-P06\D66@0MB +M5]'].2@R@]OS6RA7HK7DX+]P+M@EDZPT_PV%>4V$NI=V!$(W+_C+HO`/1>#N +M%*D'M]!50&`5^1`;S@)`&R4T\Y)?;E*\"UN5#0V\,P`G<<2B<)M[HV-N+%!Z +MP8LH@5^J9P]0?;UZCS>1FR;9^9HN6%)$Q_46 +MKJ5?#=<,M+-[&A)(H_&\(>%O-AJJ+@##KVD*,));E8S=H.Z6R07:G9SP89<&:P7N,?#]!D/1V"]Y&*J(O!!=C`AS2JIC85]%3X7&5BQ,;R` +M%([R!X4/F^&Z:@`E@O93\EO>D*WQN9&4@,@MWR+6O'A>.\(-B/F"X#*N3[F) +MNDRGZ0%%H\2]5IU,GVGA"SB;B\@&V3[;DA,IR"Q1&GARMQ@9^@<(L[61;JG6)?;?$HG3&>(Y*Z='$..*Q10%IPJB6./7CK0_$:%2$:W69!U,;^3COT3KXJ6]`FD_1_UCIQ,((_/[5 +M,MA!7:+(-MYMEW6&H-[%Y4L/.3+3I-\+IF&.QJG8XOTI2AJ#2H#C3@3O)W8^ +MV9L[;#73D[NN]E9CL;16@6*VK_*7X!!Q1$&2"-CN17 +M143+.EWRN]`L"R*RP-H4HZ#R9@_6%'Q1\I7T6X6%A'D +M5QS>3J?&]Q8I=P6I[7N]0<\'_C5+=8&D`)PK3O;:G(+S3+I0V&_Y&SG'W_S5 +M%_'-?D>*'F2=%J`X`^8F8ZV"N&D#*(H7+E65L +MO[>1`]TD/";V9>^UTO=],O?38H<"LS-%B=; +M'EIN:T$MVZ1U^WAY=$-^K,!UAFNN`-*MU3@M=B +M]U9+UO&E4.H4I(7M).I@3/G$&%;/[LYH5M&^JYD4>KFO;I7"GMPQ&O3C;+-D +MF&K;/+SYH.L;.YBP)$.3@#SN`"'0ZI^,6+B-'0?=9F$H)-[WLDKIH6)8T&)C +M2,+"8)CS]>!EWYD"EY#\Z_U_93P)(!#Q>7-HX87IJH&*DEL=0Z"$Q/^.['*; +M41RVB(Q2/O:I>2RRZ0H6;/;)&U\9?3=U]J_7)J@ +M=?NDEGQIL"DKD[@6-(L2`E^*]:VCSTG_N?<%;KEN6O$]'PJ=7U5GW=II2P?$ +ME62#C?-8?:-1>59SSQYWI!P^'6%"A@=;FY#NH-C5Y@)9?NV4`#FP;)--7"2@ +M*G`QDR7"D>9I.;-)`L0*>>!H4-.2?ST*0OD@/Q;FB1>X6`0MB-9JTZ$QJ?59 +M*N^J_9=XI4A:V8O^8.:GGN=->AD,C^7P\=HM!FA93X^;D?\^4:D^5P3TRTM4 +M:26A!&W"!)[<\'%1%!AN5ZL`C'YNZ6H)(]M\+`S7@"5BY.3=^XJ]XWP#E:/K +MW0-;5?)`NQA/*C+KJ<+6R*5X>_,5J*^+,D%O^R1+0,H#FKX.15_)\`\:5NV] +M$,IZ@I[.8VYZ\XI"\JG]YDZ3]/8[2PY0Y#>\I?!]GC"E)_ +M-?MD8IBR&G]KJIMD;KBM[G#K;-M2PVJ!&F;*<]8V3Y5,IU60!)Z@:3R4;*3M +M'(TJA*#]"T:F1"8O[-A'R#X9%AC*1_#S[I%38DF/&#I,:)EVM<1'WK[R"4<( +MCCOEU?\VDDJ#8V@%,:E3$&"!#!_A[OA<`76R=%!$W(M<2#AK<,1DG$>9"I9S +ME5TG>[-EHQ$_AI"*P^:`417/ARKDRM_9FDK?K<%@*+8B1G50VY/&SB%OI<&> +MHES)W".*O:$[`MCDZ;I&7 +M(8-D<7[D,3O6>EP>G#N$\+K-`WGT0S6+MFWQJA8?([[:?2UV""G5C2TF^EKX +M?J^DYEC@9A7&PD)?\%[(6@$D0*W(V76A^%OMN^V_PN6RQ1R."V,82VW96W"U +M&Q;PN"NI#'?T')$$E,@-25_/_5,^R$IJ4YRF!THX7ZULR%$PGQ^*@PN77J/H +MF&GH*1%8Y-/Y((Z`;S,"F63W+;>L+%/,E!]2=GN2)?+7%WJ"J.I5>01H8HFI +MKDR_SI@+,55[UXF`?\%:5)$VRV\[D"^E!#=M,LI1%+NPLJ[XO<;2$=;5^5@#Z=/)K +M%=,"8#J.J\O0S,XNVXH#8VZU/1H/!_VY=BFWT&]H\LSF)LR?U<:B;=71LXS +MYF;VO3F4>A\(C0?>(2H+DX0<1[T.G0/B1GJ".3LE[?_\[\%7#>*/*N\"E%?9 +M.O]4HYS]/+[X30`?)OTY!:<"_V1F7<::H.\K_?"ZKC134T?X<>G)%_XT8KG< +M@:U;$]Q[O:X*3=I>;<# +M)LJ@#$(=@7F'KH*G]I%LL8BGJ1Z'54Q0E:S@AN?9N"NY_4VHQ]*-WEVD-(]Z +M']TAI>O/]"B`%/4OAZ`U`AQ0WN`#J^#Y;_\&"%HY%RBTZ/?05S/4HAAJM?BB +MX.GP^>/A@[@4JL!V+7!)&W%1!]'FCWY5M2:"6=Z_6[U0PCM^##*`[X9#XBR[ +M]OJ\Y+A;>YY6$+OV!\_-I-1`?!/5J(S9IUW<1S;O(??(Q>"I2`W4QE5JI>IS +MX&">)'\,&[SN12C^[CE!B]*+IAJ^6;GA^:*.TT>T!F9MM8R1BTZ[^'`!>5Y[ +M=[9;>NK#M?V=%X\]A2)"6W@J")YG!?>0-U#!3"ZC&%R@QRL%UFPB7#V-2+U` +MJ^1=_K.MZ"+;1-MT[?4@J??-3#EX]?W+?-V2LTY`!("$#S +M*&DFK6YB%T_<+F[1!V;3-Q(I+KKHXW +M`Q6UC-L,0+6J%%4__(!(S7X5`,S)&1/\!(@A4@^_XX#(6#H%C3K8J0P_QLC* +M;_H<'?"H(3RW2+A@\8#@@.RALO8H'%2U"9!T&-G7<;VPRC9S9B^@:*S.2(LD +M*+LKATZFW;9JN.`1_X-SCE,"CE6L"N"J!ZC%%QE@!OD``VPM_`MW)2W'/+`M +MR%@W6CO=.JQC7TR$H\.9P?+YWN@.EEAIH`!)2)WP2[I7>QWZCQTN8],?V.>L +MKVH+3.4)W8Y21UHON3SZ;5PE)[]55W;SJL7YMOVS2)X_?#B2]"0F!9#M61+\ +M#Y3TA16FX4B3E7F(UFJ`B(0@2XK/10%9K!KI>0+OR_BW8TY?K7__S>UV@"M? +M#?DB4=_Z=PB^BW,PEYK2]K1BTI]GI@./RY-$&WJ<77'GAI[2&DT_6D.)L^6#4%! +M6PN#(!V24P\%LX==,%;>N8QQ4R86J*V@=AJ343LT96T>E2/GV#)T6U5'$V,9 +M3JN9<2MKLLJD6=)8W-?^;5;S!FTZ;KP[%E&8CX'F_]7C\]BP3/%W!MI).A2% +M:;%:=)`5TFW)F@13WW!&`WH`L&],?O86KX]'#V2C;4@B?F'2)[0*FH4$X0IA6KW%+QH$T$%^"%DR9?U.U]:C'I[W>2@C +M1JW_SW*@E+6@UA;Y7MKL4R2-;1^$PM4AJ5\-56; +M2Z7]?\-^8\6=%@1;A7O!OJ=;7R+C-#5K$^4#PL#OF^2;L]2?XLY4\PED/PZ+ +M=M>WC!OI9@K3JF&&:ST%1_R+R#`W71*OO"_MRM.%R]O"+_<7,F"C%(;E43<= +M-'QEQX,JK/7*971\4.WAVW`C]0@T!T,8Y:%B[ +MC\[QN8(&V4U+.O*-03?I$(5LL[5H/C\EY&S*"WBO=R5W;@$A4\+4%=S8I=P] +M$%R)>.[^JC5V/^_'AU^+`1>!N]U/V<6IL4!.M.6*"^$8`L;?7E9Z.D12SZQ\ +M`73:=)7-"9ZN2!\%EF`)5N-_\=/Z%^?(&@9+(?:[X>5*FD +M2Z/OHN:!-"J'PF_T\'%IQJ.B]_9KP8L]T^&XV1YU<)7&!I@6=,A`T[L9[!HY +MFC:Q`LB[Z,!6=+P7>N4+42GKT'`X^Y!Z9B;MLXVA>^NB#@'G1*%L-FS,B>&H +M*K![>Q"A)"'E7H"X5\](6[]K,Y!=T;BGU<8]]6HQ[I*E%:9=+>TB9H>V`/N6 +M/0K55'F;&"=6K$2IS3#Y+OYC%V*H#MN!>)62BW!M.+^:T@'Z\9==BS>=4G1M +M3SVC-O(*&FDBE=M9.^O1IM6K#,0G,[E"S5H!"%8[!_H+])ZF+>AW4RGW6'C( +M?2':SNSS,\&[#.B8BB@: +MXH:]#A49\Y-XK9V&,%UC3"$W)@;5OBS%_R5D<>*.R&#R'`W0)@8+-,#.@^K7 +M)N%);U!"I*(!)I8,&ST:U/H"P\;N6,%HW68H,9"^DB]-F_3*%^%BYHP8^->/ +MAS9U[),W5`(P0_05+9?3%&D`I%\-\4Y*AI]MU/@'''1,Q_)R^P85799:.C8PL(I!W=(M2%,J,/8WJJS.8@<[ADJ?Q;>]'1%3R4?F) +M+8LNI)5Y$O=-_S39OQ-F4!OZA4G79-]<1EM6G1FF$#&.4[HMO!:'I5+@H!48)\#]4;"%8_L%T/L/3U.2(RS\LC/+ +MJ0;I'3KO+_>M>(@/.PN2WA-F)E._J3(M*:1P$"(_TN,D&`*(;,R)(/2!,)CQ +M6W#2I'&`?4-=YQY1P\UUDRID!ES%]J(1H3X&,=1T;3396C5BA)TT,T?ZI9"]#&GQR00PP"M''`NU3%\ +M1*D*7MXWYL/1*NYHL@"ZK\A=H%-_'M!_?@C-TWR+PE?L-TN161;<$N8?+_<- +M4A$J,U;FC22T,2DOS +M5PR$UMY3^2ZO))5A."6#EB&F2_6Q)(R@+C.W3MLSA<8I1%6*%*"4W0M3AJM? +MHE):.J>%`XM/S-UZK>]&@5ZZ;@#;+!];U,\2#DMZ1@A(S+;&"8PI.R*.<<=NL/O) +M?U!^V_R!\G%NPMCJ0^HI:]WJQ:YDPW!,Y\(U#"@YLXLGJ81[;)G9=8#*#3E/:D>0>!F>R& +M*5YG?,35:J1\\M%UM@+B!EUP;QBPAK2@.@O'*)S/PO=:.]#DMK2AT30J?-LA +M,D;X#/&M5,2)":U^34G4*>R$2G^L^A]DP.'V]E1(5<:"M7PP._@"9E5:S&6( +MG=^M:3^7T_7/3@P`5O";W]>!\#`67)QX\0\&7?11F+-T'F'E<^,_.\#G]62V +M;E.QOT_4U'/)#UL3Z&!V[>[L?.EWQ)J&)&8'(MS=<+=[J="QG:`P`Z7GBZ*D +M[7PD>`@]SH.98--;*-R"?T87A`?"P+7L(P#[[19`>7B\!8`)PNG +MY(M-'_#,,%V9.(+0F6;.^G>WMF +M&)(W(/N'2!FM=5GZ[>,QSKN0M*K`(P6%#/4BCJL]PK;QEUO%M5%PK<"XH=,( +M@AY=^/2;3`%XLQHN?=K5;8;T+(LHRLS)QQ0B_:=HBX9S'RM$M`AG;171?F'K +M>!1I^PX\K,R.*"_7'/$5P@N%`B+M/8PM:'79>_,VQ);K=:)4_OOEU1/)()32 +M?6)$`?:X@AA2.(DD^)-XT*=<4FTKC$/SZ84TN:Y#Q"\=VMD0JAU"\54]:W(/W[!F?3'C`I7YN +M/RI-93&).N!GTGV[J9:WGH<3U_A!=PNNG;K:+C'D4)V(MRY-&\HH!-#C!T`P +MJT2>I`!0*0[HG[87BDYMW^5FMDIZA*>(X_S%JJ3_;3L$,[T;R+0OK#+D^#4[(U5-NBZ2:R!;@3Y&/-A3HF__OY=G+"URY?)"K-PQ$AY]-:3%/$ +M#Y3&7XCK$YD+*ES7`1_8-;HCQCTC\] +M9O;&JMB#/[Z)B!6V-]CR5(CA2]U(?'\R577EUK&=&_ZD19$RT46DFWG2RV*" +M3;M-?#=*[\LD-4PW?8CLU.M$XA1;17.IV&QPX +MDU`2M2T8-1G4Q'9*^(RI]T#E'@^*DN4NP'$X'[\?/>WIJ1]16AK)8-5<>3\_ +M2X\>YLJ9W%Y;@?.REDL&G.%B]0=W<8[5-\DM5',Q:2I:PVO8JJA1B79.;6"* +M8E,7]622PB`X6V4^T^%[*M+I^ +MS!M40C[Q(,'VTZU'*66G?HGQW\JA&QMGI*DK"`KG/)[JQE'<:>Q$`7,/)EFD +MFKR;G^!5I22+K\L?-W$#Q)T\<#UB#CV8\4`_.=0IX=HHGH?V0-'U:`=A6"`N +M?X]L)]3YA(TGV89ESGBIEJFI4CJQ]M?#,J53ADJT:>4A0ECHSY]X6'DZ];-U +M"3A7JJ(_;FQ?!4^R9W0#5P`;]5YJNX=H/4RG%_797ROIQWAPCQU2GBP_E%%Z +MC[SF0&Q2]J!%O5X/>!_@YB8KR-\&JU,I*`B2LN8QDDS;DL;$%! +M0]"Y`ZN*ZNO1)W`XK;YKB)"*BW5I-L9BMI0$:"1=Z+1ZPM"(4FCV%!GJ8P.5 +M^EIT<,%;4_OUNU1,"S#9*T%;3\EGO;H#??5$G2]VB\08C`$*G4A>%HLA$-[' +M(F(IV*7DF)N`R045##\-6UT9UY#X#*2<$/K/_T0OFCW"12QB::>>2R&YN=-Q +M7=@-";[$]X[0Q_WM$9&Z;!,9P!7S2`T)-(E4(%I1[_4==2"4W0+<+Q+"]9K6)E`T)A&&Y'0EH#@?, +M1J;>BV8T]^G\ZR85[!S=I"?E^5M`?`4"O#$-%W>W&A2+$G2_"=WK`_8G!?G7 +M5*%B]G>2)5BA/$R/9.5Z@)B@7XG7;Z5^PMMHJBS<[4$BO\GP!$<+(& +M"&]=A3.@GB>!H"J0\*JNLV[TG4QD(.,!Z8K#UMT\9X#\^B^9S_LA$[@-G"]; +M,+)MQ>I+NKZ`4HF9M83F#7IW.+)FS-F4+(:VG>-]Z%I'`WKO.+>QGC-[O9WL_="3 +M<=0%M$UX`G[EC:3=W6Q`J!XMN5UV +MHE#TS,R_(2I#WQ7+-SW4,7]"]",+)._S?'.^:V@%O`-"I^M*<(@I-\+T]V>Y +M.7R]`IR/^&B4>G@Z=0WX'D8QJGPXQI@*'30J +M)#FCT9MM:DI1)0X#3?NG#U3-L^4LEU'E\1+$MNQ+-Q:-)WX&$XJ,27#L=5>V +M!4B"/YXF\A%H/?/YNT+63^]DP>3%BQ/5/9`8[''#0)=5^G_^*8(HCTGU5O#D +M,,Z]7404GYSB72I=Z#=G"(#KDFS(#-&\G\H5]:BZ4BX@.=R0UV;O]DER0V"F +M#0;#;=YY$3H#Q0*]R3]L@HI6GW1>"$0CDRQ$-K<.HJ;VYGWVS,&5H!>2N_".X<,U$_+HZ=6+SYX.0`D0OM&4KB^0]48LI-`B4/=(V,( +MSLT1U+,_?`XTW3%?C-QG=PQ]"`KJ*%[HB@J#*BY=7G*FZ7*/RM,>P=O7M=2; +M1U_J.M_.H/YJ>V;2,5"9A6FA$A!IPHDE+=/5ZH"`*]S.;6/RP!\+XUN3"-B9 +MJ291?,"B+1&-GZ>O;"KIH_VIOXO'`8=YLV!_7]QT][U32((C'RJ0B++(90*H +M^9A(!XU);*\#2MMG18VX +MM_LXWVCI-FIC,^_=P/YD-BDW>L1,`C#MZHP\YK1BA0P3.W+O6>Z?!3QBNOCV +M>MR>F`'T:T9PM!9@G$*F9T:6+E'OR0$K+2",FNK*`U@J1)E$?JH109&(ITA" +M[GAEX97[(Q!R3Z3[))V6#@T*?04IUM#'3IT4"*83E->2:J!T&&>K`\=ZD:L) +M/\V;&J(4DI06+$/HWN#2A/9028`N'UR,TH/`)1E'9O!\F)>#?'$Q;K5'@Q +M36IW$"Q5U($Y&P490X1?*5 +M/?ZERZ<\Q,]I%`\&I,V)+3T]#AX!KS%]3Q4TC#G\*>ROGG*23>7 +MM39'*AMD9SY!!-WSZ!=E$# +MDE#*N9]#(%6LF-.G]Z0X@KUK\A"-]KJRY?)5]@=>'GW15#`,[)[H\\*P??5\ +M%L!$O"G0SB-:T21OU#UXO3HC*1$S?W*@P]7\/#"!\;E<0`(HEL$H_4853P.* +MZ"!^$@D.[/6Y:;PQ"7*A7)Y].#9J>J[:L%^=K+J?Z:*U:LC+&L]FNYH@Y:FA +M$45_D1&IJQI`!)B)#84D\,4-]9-`+$IUE(@>%D&KGC4KY?H,[3E2@2H?PW4+ +M%N:1]LQA1QF5.4,IX+PG-VAV!PFC@+,][E`"B-39#Y8P1ZDY6&Z;U2 +MP6>=CULQV^\2HD]W%K_M,H&-?:#8##\*N(,I(^Q#92Q$0^4?LQQ;;Q`.*-HO +MOB3AL*5SJYM#9:O5`*,P1:%"P^5??,?0!LGI>P8YD9^`I1(7U+BKP6YTM% +MU-7]>`2*7QA$QYN153?DUJ.JK:.-F$^F-N)T")VYYG>B3<&,*#/C,PRY?V4MV.WG)585@U_F:XR +MM*!"67]%INT(9MAWW%O0N*(RE+38'B[()%W:DNU)`6QSW!H8-'*%5"`HN7VC +M*GTF=(&37),>`_7($7&^2Y-QPR'T^'A08SBYAB>6V"E3 +M>/3ZEB@BJM1^6'-,`B7BZOBQV8U&%6)KXI#-`\@GQ/C5T0PMSJ=*<7K>D)\3 +M-YMV/3`/<\>#C^TZ(8VQ%2_`NE\KA+*QW,M(3?SK?[*BC?;5B8KZ0PAA0*3: +MXZNB)7"0.T:[OPP80[)0)0W1,PY#_(NV]RX)FF];Y(,KN6S>X,$5!/,&/4NO +MOLGM&6^'`Y/'9J,)NN'$`RZVR)[,"(9QU_1M;_.H1OL,\_7O&ZFJJQD5AQ-Q +M4"Q:-V*6&R8K^.C>$?$N\+(TGV4OUC69K++?.QFA#](USLL*YH:EP;25UOHD +MS,V/)6W6YC^5-+S/61B15")>`G4]UL3;Q(\F4O/W1*BG?N_YWFTJNG],BK<( +MG91L7+XQE9"UEM-B,8FI"3G3>K1O%W3@?IDJ$4OBKVT:R!9W0%4R1$";%Y+R +M]A=9/BM0S+!^,B/EP%Y[T@3M.U%/-]RQV1X!KRYVR-EMBK<>HI:Z]\N3309O(D4%Y0;Q"E7H(LHAC#@124MX_YB&VBHJ[?%5-_-]%,0*,&/_=_ +MM?<-6$=#W?!H]TZ@\P75.F:=(486*89.;RQ]9_P?D(FY_32?G+\\I&-E[;%* +M.SI490N\NB1N6<\]#G8'R/Y!J(.8T-!HF^8(DF?IE$M,\0;.Q[H6Y03'QN<$ +M6%01O!V435ET^VLD?9?6B,H6(N@S22P("JR10Q#>5CU-^A!S6)Z81%V`FOHV +M\H\$P;1/AS3UGZ:FHE=XM4&(5=]FVU2,WWGPPZ@[V.268)7'S&^;K(C@N:+] +M#G\N>56]_]?.T-W63];,L0OT-S<8S;U,W7R11)4UV#N5U7OLEXAL]+:(Z,8` +MCTZT&KSJUI1]X3E=P*9"#,\[\%38GV%%@%Y.DRJ0KW'Y25'8FL^OO$XA +M%=JUUN%S@FJZF1D(BR1$J*+I*W$K=(\ZKIA$W";S;5&..W%2V9XQ8FQ>ZAZ* +M8??P=."(GA-!LFJ(VPL$8WL5X,SBVMI*/[R8XO;"5XMSKC#DC4;F>$6=!1*1 +MR(2^&A:C%3WXY%0=_:B[`;H>4AJ'5,6S)`4'H:;9LK`:5?QCE>3_/);1*7O;,!4E)R/),C8N6SXPY[VT/X)Z5<-H +M.`Z=MOLQ19\B+_CIA3K;.$/*[/HM&,1(F#6/)?T_:5,E4D2*HUVB-""VM:;,K;[R+Q@95O5 +MK%K=@6IW`/Q>A''-,-S'0*N/H7\XO=AFE#2\J?^Y%U: +M@YD9_,^CK`M+;>S6(:CE_-"BT5^!/J.@@CI*%'OZQHX,]Q?7;B_CZF&Z=#Z- +M5E"1LHL#-.%^:'EALTCWBT@"*;G878:9S@"[Q\_&:[C!M9&1#0L/.+CX><## +M4D"6I]D`F>D`2WB1S;6UDIW$LV_._)D#P!I^/@U"3#?XV:ZB5>6GM9L6"U>* +MT=!F`.5Q\`%@./1%NU]4`SRW>7?I4H5YBJ@O?1GLK)CH:])"\;@.[30R@1K$ +M%H5L,2DI-@*!J*GT1B':3&;S3X +MWY&.W-/_DM%,NJXP]1@TQ6"NW+N81JQ5G7"?P*`%Y?/YBQ#TF:$SM=TI)@L# +MQ6=:=NH/&)"B2#.7#O^K42B:XI\`+;(7BO(")`.+>,Y`$_=$Q-'ISZ>/`+_' +M-[O5$\WDI2;68M88=J6:BX]=%B[ZYN9?. +M//E!04)K8M"7,\0+BL-'M8J%5YIC<'7(./8X0ML\,#/["5V(.F18N#,1F$WZ +MK5;^:,4[.*03'K(^(3ECGFQR*]8%B@S-3,]0XX&7.)AO'")X>NK_('':AI:F +M@K"HW`2`A$K0@=2AZ!XM+\^[GU%.>J&=2?/?`MB1OR#&/RM&9P:6;16G9S[` +M8^##F@E9^V(/1([RFFRQ9;GA'\?8YLZH;KBFD^!K#$"1A<=& +M7M,VPERE>:='+]4W89H\`A_N%/7-=EB5M(209C,VRX:!C`59/W?;LN;:6F1A +MD*YA)&)A9M\)SG;TV%[G;@-0P_.[9D\+Z>W'2=-$CW7OT9S;\M6$'/O@#+&0 +MZP55+A'R`\=7/TEXXR"6FH2V@38\/*6LM#*[L=%WIK.T*6_F'3[4SNZY!$JW;%I9H+7 +M\+YE;H)K5BG`[41*U1OJT!+@\`^?0=G)-=+GOR%E<&6;'/M&B2?Y!S+':^BP +M"H(W%S5\;OLXVH)X>K%4)_COL#T(44ZZOO6E?XID`GCVQ*AYA;UK,@JXV-;L +ME+T#97\_'?1`'61?7A,G&>KR@?8K_5-^VQ0Z5,%$]WY<"IYV?:2P94970_II +MR6O051'Y*W55A6A?`#A_.7!=M[]L-VDF!$7U1WOD"4`YE2TEU1*AP2-M[QX7 +M6UCXI>@R7O^A\W),XMU*S[`7%,R2?%F.`2Z.P\Q,1?[\F.DF-=.D8PGHHF@@ +MD-M0\-8*W0,/BTB#&7:?^R)/9-SDHK1-H>67CS'>T84E1A:.?0I2=2ZN<&T` +MI<*G*"'D,Q40Y?@QBP,$R(\[P=%RQ_GWQVQ:P-C#3RM#^Z@+/_%UMD!?'"S^ +M&4\@2\&&_GHE8&K2:!YQL,-D*4;2EGG(]A0^I=;Y]O2TE&DW4`75%3T3!`-3 +M5`+;KE2&/SW?7'VO78PM"\Z+>"PZI3!'U/_LFYC@8-#V"W< +MP+1_SZC`T'K/`#?QG3TU`W`.$H"E*3&%3D[^Y>WJX4VJ)4L0R_K%H_SN[]8' +M/7KWZE2)58DN1R"1X<_I[A?^9P3JEX0,[ZRM?:Z*A>)73^,\J:"U[\)46M$+ +M17WEW3-ACF['`V(S.QA#UUV@M\X"`M94O-*"4U=8:4)6<>*96<+4,G"[,4$RHDFQ +ME"Y<(3GX)]"&<^UG*T9T?LN#JP7(+QV95^%H:K>[`I73X5@(XR?C,DKAW< +MN['PK#Y!$OGM-4(&3>W>H[;BI.)>ZHK_IQ/WX;R+U=-=`EW5"IW:6`CR%-.% +M';B/O<\%5%2SO>$AOLH4-3?6TZ_7.!^?EYTBS_G7N`63Q.\>[8HO9>7+`SZ_ +MQMD!;1.][!`?E4P/F4A1OPS:VOH.JO\W4O[3'1U4T+IV.2/OGT&V]+6FNW>H +M-;.&->NZ+>"S<\)QP;[J9'6"Z,]EUR"O1Z[95II*@MY6HWTFX=/_>)Z3CO2_ +M-@_[Z$>>[D@K3O-'[,IX6Z(*DMW+AU(#-?YK_55/7?%4B73T%I-?!2PQ/?YY +M)GVCP(^\VN!SJ;&J7;IE/U-<*1NEOAU#OEV_?4&ZZ]T2EKX7#U+ +M]R#':T.E8Y4A;3TL9E3L4>X14T/*_M['1DGXMG@AB(1'@KL7D+ZP$O\OV!15 +M"F):)5^#L0*UFX^%-M[C"^!5/#_;8[ +MI]M/4]$2T$@\[2I:P/4+6V@T94[P=X"$)=>L\OTDZAK5U=-,:4T_^PA@7\UI +MB[DG]ZA&??67^C(R+GA")&MX1PEQ3?#_&3]HQAEF'-_E<%6P'75B39^G>DQ> +M7V;`-Q%K:9U*<;6:N_HJ$L&YY)-D$?H7.Z^,076G("T8TH@"W4(#4(;D7C&P +MJ)V$>X,*8<;UQ9=DGJ8+')T;E\7''_\[LLEEWPVSSNK/'$VD%Z2<"7\H +MXTXO6)3IZC]Y>P*_+(KMUG$\5/JK8*-;_W8[$\FE7_^+J!)@#%KY^'CPY,*2 +MOZ'Q:V:C8$J];"L!'FG_B/`=578TY.IAX.2T4A%\><0,2>8 +M'9JAKG+MQGBB:GN&3TQN.'@A_@R3HSQ!Q>8VFQWBFT#X$T`.7*9L$LE#W,D3 +M7'5(6QH-L*:[]`+2,E4YOZ&K8]7"!^;IT6L4%N=$Q6ZW$?\!:ZK5`6RSV:5, +M`&&K8`/1UQA2HZ0K9`K`2%LRC0CE!0/S+2B<=^6G!9@/.,0<7XY]<[-G7D%I +ME8_(9_E[7H>$)L4*BK0H*9JD4-K1QA-+KWS%P*G3SI4S"%(U5/GY_M_E'D*FL"C#_)QH^Z;T[H`#Z`&B*'])!3;;1_P*X;A=777:9!(L'`H+X#J3_\F!-.U,5IMLDJY<>.MY&@1B0 +MYGM5IC&ZL*Q[$85`-[&FLC]>+TO"8J%%ZZ +MC#``D+Y3._M0GT;7W#N)B$YSJ!.ZA*6D0V[/;C]ROP7D89,K$8(T=/8]AYR) +M+$F0AN"Y;V!C6=,.G!&VJB*Z[_DK`KUGT>]LJ"Q!G1>!E^]GU2C:'"HIGX=` +M*8/R50+DS6LGH;0A2CD3^`+P@4E@/:>0C6BT)]SP]`-=5ZY&ZX"<978N_D+X +MI-#>XDU.@D>QK&*L"BG$M[M;4U]>C9&J-BJ*I&[N.I!C!DGDQC9)2JJ-UY4' +M..OU,H=OOF:MR.DZ.>62>M<^*KY[$>"4*WE-H7%2<)R)_@WB/.&CFVTOP`[E +MT+7!:QXY/V2".&N\;<#9*H*]#X_8_Z=Y0):X[(<9TT%5RN&:U>]-@&&G4A9: +M5.B&`2)0H_3H/C41SD-M5=_[RID +MJ.!1B(C=>:KET.?B\#QZ-/"#@TA2DX88RD"6.OC9_M$O1;11#+OT4GVS]67P +MORP<#[>*#9'_CYP:5%3^"2"P@>;&,!-]#I&(.U!HG`O>M96_X+[9F;?'BIO= +M3$B(`F5;:[_HO35EM9G[8;D=BF#!2],*R;=V'G<$T/H=>.)^MT_+MG!?Y9R'A-$`*-F7K07I=KP1RS`,\NA1`=T;;^25KMAB`9MG]9#%,/[ZC2>+HSR,&$=` +M,4(%:G%?E$)PYG)ZZVR`P9G5-B<2-2G)ZW)JE7?ALF#HKU_>0)[:KN>61 +M1.3K,:!AK0I(A`XNE2)'7M^R"C\-MTT$*?LH*VOU6^Y%`<2LGFPC[`P'XDH. +M!Z!]Z'RO/"2.G6C:Y=&NM`,Y`)/8%9UP:`8]WTE(SKDX`3WJ'4CU5:#?GI^K +M`45J-/Q@6XG9'-9&LL]5164,KD7M#ONB*\=L*C0QQ\5]>]VI!SJ4\P)=KVVM +M-R/,WU,MB_TR@`22O/#<>0Z`$<@D^A%C@SS4<.4/`F!9K?\$A-@7-4JFP+- +MF_;Q&%(&.<-1E^\V0G9+/L[Z\60$2KH",E;2LT0F10@I.66J#4+8 +M&3OPRZHDP)QJL*($%8D?X_O4=(&`)[]@^6\D?UHA=G_-S5R#T([HN#WT&'NY +M'33)DX6VY=/I@8B>08[_7-$79A/,]=.D9#+VP^<,Z$5O5-B),Q6I:T8*:3.%J_ +MC,N%;>3?_Z2("ZC_KGJ_RZ%1SH[A>&+`9&AG#VO$3U.PYB`187#\_Y*#,_3& +M9)(I>SH\BDLY;B34R('O=7U$CA]B!RN%D3#5=S'4%)+7!1LBS5[Q\_G"':5@ +M6C_CU\,9,<-%8+KN0CJ_W4N2P_#>%C?:Y';(A8_O-",3Q8I8LYD0/6_.`0$D +M^#5$]!P*12]^V[U*`H4U8M_LK*^9^16&S_B)9K6>9G!*ZNNJE#B353K?:%C$ +MKI5A2FHQ1@[\\'"Z!F'*EEP-T1&+N`^!TOIURY3^Y:KMZVZ9]N[:,SNL%-\YCD*.<$ +MQ``#E^P\(]7E\!\PSC(.'$[*N\5W/YJ6#O-WR'*@])4#-JR/ED(Z8&@+%$AKPZ0WR-[YQ[4G8'++.3SG +M6*$1^YVN/BB%F7S8:B&53.&O@W9A=T\`:X@*!39G24.H6;KIQ^1&2S?Z&>=\ +ME;G!+?XU!6[33L6NNN";7-1B%.A(9/:5`/A(@EU==0VTT9L13HKJD$&S$\[D +M0>LFR\JSB2F,7L#HGW1H*34L"OTH"_@FF+S4=Y2,]@UZ*MH_EMB!_DHQ#]G= +MW%(?!=,'EAQI)4".PBB61G'C@YW0R#N7I'@9R),UNMSJ>XZ#AC#'+`"=P]GD +M3CCUR6Z7(<7P12Y5_HP0E1LW..SDZ,@F*WFF3(4M)9&0)C=]8!)-PMC/[)JR +M*($/L>G8\XDQU@VD>WL5][`B40SI%F?>2O]MAQAT:P'ERU6UF$OF_X1^PI&S +M?]R4(^;:^,>%*6]D-UZT:;)2Z6FB5&C_+(B%:+4J@`4$2?X\Z'P=O40':[%> +M7J^L;K=_T/6;%_M:__77=22LU?3%$)R1ZSS4A\00`-/*U@C[H#PX;Q)\YC5^ +M4P,Z(QCTE0FH8SH`!WPI[$IF="VI(4#6@/M!L&0:L3]`<#\,"C +M?7.3[]\6'K.5WEC!P]U0*ZX3Z?1A,NHG04!K]4%:^2OUMDK3JU6#XFG%?$Z3TA.LZP?'H2-E\15H4KB8J +M7UG-+`8UGU46@A0*>*!,Z?C.38&5OW2TJAWY#T-&?5[<_K^];)H_;A7?5W%3 +MY0J/X7$*XB+>JL\3UE0+SZ/( +M/FQ"OF?.QB[L>MA%4NBD'=[YC9N:NZV]HX,2,0_"[ST%`0R%&)C*QJMA0C._SCNZO74J4@O=/=V)I#?7*=!,MO_S7W;\@61+;`)R>BL$959AV@@=J1_I5- +M&C8(Z04S7=JM"M[%]9D6+7Y/2)2S<3O-Y7A<'];^.)24"W;HU83H*!7N%<-%RP.PD. +MO2P#`;B;6W_=;TM`]M2U":PAFYX1642E9(M7:J?DKW1-`!AT3XO9/:E +MC@*9HL2T@&L-84]CH2#"8V1`C&."1I(R5?,B;47C[8[C(V6&T,CS6`AK'.+0 +MBXDR2'JMO&NR:V4%SSJ3U?!/>F5;4*%"_)]%XDUE4S&=I0MO!(KR82/CE;9E +MA;]'P(QJJ3W:=L0O)="IU5]3RC*&B'DB:""T["R1S=,O8TWPR5R69C6:(?#% +MA;D@G@/SLH&YR7C0+"^I[4(/G#<1E&KTJU,^;]^KN%6N/KSF)P*8)^(.!;DI +M-1G(695O<(30:J_H2M-+4/Q,]RCSU`4#9F*:VX6LFE/ZNB-]^Z')6?``[B:Y +MRW3IX:Y2.*=4+'?;&BHK^.6*W!1X`[_7_EGBS+KV7K=?]LX)[#K8G;3)D8G-H^_*GW9]"K'.*X +M_86<^1[T(!3^CR?6H.EI!*4/=61UY'Y&=,2I9QYTQ\@H81MGLWX"B43ZT.!$VT_\!!CC)9#3RSLD"!ODA\I@#!!4&USTPB%]2M#U#RIAX2K'N^4=P +MN?K`P'LU%^C1.FI4R5]H47E`$:1XH;#-%8. +ML>YKE5R@?&NTKQ:*J8+:3M3?:M73':9U;Z<\=#&U(![FP+"'\E_OPU@MEHP$ +M.T'V%]G%F-]NYJ0(ND@U+:"%LW%N#4`24JQ;$8,"."2!([D=)5$W'#X +M7?2D6Y(*[<&,Y.*>$=5D@*O$/[I?]FEW^U+ARWR;!A3]/=%\JHUVB(?XGB`E +M&GP<*Z3+]9X=E[CU;,!D.1G#0#)IL-*MQ04]P5(*0&=J#S_[BZ@QO9]UG/%,5\4TE(D*+>G>O0[X.L)#$Z/#?R,L.524]J#^'H.&5\JLI4PO7/+&35#=%$M>_':K0>81/D +M^2SL2`SE=:OWHSS9;3$,*]'&R@\V-;0J;BEH0Y+M'+S+Y(I7M_J_S20DQ)*C!B^I:K-N9V_N. +M(%1?U/0R(?EXV(^8"JO)%BL!%M,!IP"B[(<1*O_9#O7)S%!'"`PQ;= +MR9T7+(+334@3CFW'RJ%#^37%C9VO+/_^F@4%2JI*3`>+)M_&JW#/R#+4TQ +MZ4&(E(2J!^8_I3?8(.6OS+L5894V_6!1@V^Y3*VL@/_O8=@F#NUMLU'^L1=,ZI\T!=_CP+!"7P@T.FIIN(QSK/+3WCMLEG&''[ +M+$WM(`S`X#;`L@7UO*[R:*;YF-108B/0U2I],+/Z&)$H$R.@K,PR8>3X"!G- +M>)&5O[?/K\O%%S"S'//"E(F-O"N7&Q<5,JW;!%KC7;KJ\X(('ELU4H0Q'R[-9]54+7KRWHQ_,,*S."@^FD= +M[R?YV1*L!0#<\?W?*BE7(MFY[`2:F"C648Q-K.DK@>80W;.(<+`]X`'TJ?(T +MQ)'4,UIIE.M0; +MS6G#KT9:-UKCGKLTQ'%@_$)0=RKU!/OHTJICKEC6K<6:BQ'R"D8PTY\5NRD_[;T1;XL?V/;^*O<[Z%5*`7G +MAS>6YJZPU@_SNC(79T1'*S:PH_#R->%?L$IP4Z=4K=><6*,@"!T_W>E5Q7!: +ME:KI(3,:NU_N[:.>Q>0QA/D-I(.XN@ +M.M(,9DHR+=S[M##R[@L_8A1:*__"8=6;,+`6S:A&#\#H:"&+'3<'[XK:KHR47-1QBRL5"N11[G!==J&S2<9 +M6MQKU`S0W%(0/&7WNTW32:%KWPF[G<[&9]ES,H* +M=;;GT#W.IQ_V<("/+8V&**&J0)HKBQ*)7OEIE7B75#S^5'^)3WCVI=7PIKH7 +M+MFO_J&TCDV=0R\Z0M%J:,-.".'6,;DS)'"A=!Z:9%]@/<2[GU_ZIWQ?$FQ) +M/K]K2AN+K2)GC^/2#RR7HK;9]W.RTUA9] +MK2R!BC&H4A`KL+%=J25GMT+@6%7-:I"UTEO+9`-A-Y;7QY(X(1G+5#!D]9]. +M5QY,")X*]`=UB?73OZ,'%/22VKD%J_P,'.O!9`Q1OPP%#!^,([T2QM/P]D=; +MSW7@Z.@'KF4>\)V!&8/2V/=.)4-N[&YR1C&4]N?W8ZU28H-)X-0Y"J4,;H'= +MO]7PG4VQY@4K#Y"@/9"M=?4]]_3-IB.4QY^$KIX#4L-/DTC>?>#XB:J4OFQ` +MF3.#_=B($^YBF#IVTV*&V-&#Z7SNK-%-':G4Z95QXS'(_E+S]0.8P#%!PXC` +MX/)_%E9+]E(2$CBO?2(R`9J,B)JA1)8)QF0=^9.O(Z9!_V^7OC3157-7*"`>W!SC:6U%X+,#^9C:*8^ +M%CTR!O#*@:FA6HB2H(H\!.W<)_"6F/<*,,/:,W_@$\.QZK0TX-=%)MO:&\+O +M^QRQB_':6(E"J7-!OZ4\^Y/`JFY^Z"Y8S(()4Z?ZE`SYB_.D%R3+NPUE`RL" +M\]VD.-.N[)MI3,Y*:L/UQ'5=(W\:FD_MK)W"0L!.SD*3/>&]#!Z#S@W>>#Q*4.? +M5//GZ9(^$G_#5N>LQQ;0!V?&*0_>\",NX(T_F@#"'<]&>=R2OC,:B_!&TZ(B0Y$%:2!XC2Q +M-LX7=$34!,;\4&PG'P36;-JN%F[E:L9.(M^A1/Q'/()'@>/H&D#S5DA5"F.7 +M$AB],'+))6-J*^B.FB9WTH%>O//8^-,.^81TIL8G\".,3V-A6*==&`Q+(U%) +M^41HS';N#,IF`@4.&NUND/_CZ&M@4+A6=E%&"$<%7,*D($L34VI.6HB".H=U +MV)*<#D>PQ,?GB:V6RBW0FCC*]T)PE275_%!)9UB%$7AF=>#2(`B_DQ[_OWPZ +M$K4Q)8]RA0%K$)28`%PSTDM_`B%UL2C[)BGSAE&*(2ZR>0G72[F'7K$:U<#MG!).6:TJ=">T(+/^%WG4U +MY,_N_G'\/S4P-\F5I;Q>VQ330^S[50%WA3G.6R/:(2`\)9V2/,]?TEU"HVN# +M$8$JAN<5?(ATQT[GO0,.J>7P"+Y`=F+J[P(/CA6T%'VF<^%MF5KVY#<^#-UI +M,=[0F^Z+(LIY&AUBUP?\U=*2L`>U,1[A#6J4W+Y;'^^1='!@5UUFS=13>#5Y +M2/JO&4)7.@6XYD51_40[E^@Y2,Z#K/+P'VS^\3&=J@A6S]0"$GUIK&@UGWJJ +M"D@A52B(DPB%M?)Y%D4]%RN+\'I\2,[YPO+?()47V)$BI_S..VL*'0#9S^8-WD8FJ4]9IEKOWK?"#,/-:P +MFRF)G.SO'N7X/&JL*_#&`H`4R:))UJE,#J*R/O!8#.ZCCC@::9#D$*/2?HT72A'5G/;(-X_-](HP_/@*5 +M1.VP8`FJ80N"Q!6-/6!S=+H5;HE-!J:AW95.2B*HY$"R\CQ958GY41C)$("U +M0#H/D<)TTW&?E'ZQ@3QJE\ZEZ>OT@@?Y[6[,M"('Y8NDXYUZOMVH:+C9Z#<\ +M"&GK"F\>X3@'^.&(UE*RW80=VXN+XU%7>*BU:F)5A-[T/R$2SJ!Z^)LT)4&E +MW<*#@6;E.Y6-DGED%5B9C5;_T.K']-!_(``EB:CL.KSY/RLL-E0'U8#ZZKL6 +M\8"9.9A#1ID]_#/\CCO()#=#IV=6;2<=_RB;"/"@\$A>@B7`;N844]QD11B5 +M/QN=VOJ^:$QWU#B5URE:;-BFL,"*Y&P5*WL]721>`(7>P;0"HQ3;(W5444;C +MF):*V#WCD1=C$7:+4F?/7V(ST-%0@-4#?O#'[,ZNB98S%`.F9(![<":P.)6C +M!9+EN1GZXG'`=/O\\4\I9O@KJ8Y[V*9&$W4HZ6SZ]6I'+"4EXPQ'HFY),73R@(QSVO-`6-A,$O!C +MT9U9LSUFF:&D0LI8CWLE;[):_PD]:Z*Z.*"F#&9R*:&Z78C7Q=MQ[W^4[AB= +M4M()IQ\R'OM@CT;8%"/^KV!^;)0+)Q^9OCXD[5WV/^O)[X0@)G\-<*@0"TN; +M]UAD&D&*]@HYYO!WOQ517#1B4*IY7XX]<_M3N^R,_YM2X4>Y_N'D=`PL@_QY +MIG0R*9`R"'I1K;IF^6R/.^`:0CL5.6\F67@#J%*[A>ISQ.!?<6J34B[8`%0?@;_.@; +M#^9CQ]`%GC_>![,0,H/+I@[\EAZOVZ0M2/QQ'D1HE8\PWSOTH5RZ["X2T=H< +M_NO9HB7^AX:H?9)\F&0UG$'9*^':N,U9G'6LGIY"#1LO_QLB:-@Z?WM/T6$1%U5U#LYCV/^4X6B<-C94*I_A,DIP5"-] +M3[9AU-9"$&VM0401ID\"P;]*B1LT%6?$*021]>O_FQOR5MXXL-Z,>&2Y3U!` +MP+\.]F:HX7DN$;'$ZY4+DC;W,2!&C8S]M,36G/&V'"K\4->I-HRIE7]BP&*6 +M>JY@Q%*P..Q^WT%.J/LV2*BM\\M=\3W*-AT7RMZ9:L3F5^%=K*G0G_K;D,.N +MB[%(]?Z:WJ43WQ.SYO_>]FJ&7U6CB&H*6!1E58M*GKEZ3YY?T%1G"\C$,YM! +M)'?^4!'9B:"#V_SF\?JFTY@/MYC\V@SG#I0N_W/:DM^V"?L-NQV;@@+F+060 +M@[F`J'C3/!WTDP7ID67!';(G4E<'YI-?7T>UFHLC79V/`ZRUO]26N@@?",%X +M1X'QH9R#HQ:<*3OR33.'AU%(;KKGIKD&Z:.Z'B,I&N1<%QU#BH1Z#1L-'"'I +M'.Z?6;B0KJ,*.BT7Q_/H_F\+._,X1'FJ][:;RM`*:FV9_6HJP>+Y%Y3Z,9GS +MTZ9INWDNV3^AZ3M)=SK\7SE]^2Y-FNQT#G+]+W1+#]:I13>4-T%$6M/$7C&H +M?2Q,1#LI%0S2,=EEFW(R+'6U`(IP,A!+\F-XC7DT<*?&>* +MVG_1*AI$@$P$?0GJ"(0)L6!3Y2YB40N6DW%-/-PF'OUL&NCH>ZMW5).=FST7 +M5:C(4YYGWKRL9!#`,$ZF!W+"&II_7K^L1!#\R=95F88Y0>W>G>\;2ET*[B/F +MY,L=%9$D3MHW;VC!_(L:ICU_/H-?D9#8[V,^QCNVGED_4MDN\&ZTWO!!PPF! +M3!\T456<&@NO&E3B8$2ES(./P2O""H(7%7Z(XL<*C97\#PB(/+9`NS!33 +M>OTP="Z\5L/-L+82HH>_J@VX/P$*/"1U))(`X,P2\!F`>^1YRGA*8PZP/E*( +M=K3_\;2%0F)UG$K>)=.V5HAO9D5RL'V]>M^([[.-WTB5GC#&IB5!H;@@?,%[ +M[]%5_A?;[8%2M@`6U#$,TDWP"_)SKDG91!>Z&2W\E!T=]W!$.H[">=P"DR\$ +MQT<`7]HHAV.+U7,<@J#'"[QXSJUD]@!(]==F$)^!GUZ`G,D#J#8BEJ'(*^69-"OSR]_#49JG9A;X]#,#L;>*I4X?=3L"-`CI-P?A3H4Y_(F`\< +MKWY5O%B,<@!=%^QL:5JTB@:K)4J8&Y']":!:^!_!BS%!(`H.W6X6=$E$_5C' +MC0R\+:/BTESO< +MCE]T"3B.WEZ7)81(A@<6=]MQQT/[EO-+4N.U[AI)Z5P#BT?M$RPIW;21%BM\ +M"Z0QP=&ZR3#S*NS6*IT#"7*UNNJ1M:=N_W,J]O>ZF0'P%TV&[W__XQ(9,4?F?1OZL1'%9?,M4P +M0:_&*>3VE0!E@'[USQ)(*3+M4A<^WJW\.P\MG(G<\1"^-:;/6@69`DP$0I=W +MRN87+"F4(NE":=/;]&`9'O%#OQ-6`R3N9@*^$AMQ%FFW)H%B$W(FU?0N`$RYT&_F_.':)1PZF"%6H$OL0Z-:&:`VX#%?:B(4!,@PW` +M$(%&,(Y6:QRQ=?W]477>(<#Q;\SWM[9C1S0=R"-SWULMR@;+OV-39B!F#2IQQ%:[^QG>W*C/LT5 +M/=Z,ZK73H?=('_KRA3M[.M/8TL)6A%%@:S<@82(+%(EF@<"8[O-H.NDU_E]. +MV+/(1(*>\%\]CRQ]!\%9M?(,Q:1EKC_AO24<*@S<[W!4T* +M:(RP@)0N

    )'E!?>+%^3J(\K"Z40/[6<^\9)RV\R,$J.P3W2WR8F?]4Y:&S)N71C> +MC06-R4N3_9?%3OP\#]^8?449X],]^R37QT9::OU\;H7#H"&M"\2F1!0E4RJ- +M/YMV?WF#%(=J],+81>-!!.TLC%^5^,?]6,]+\=,`')B]-LB8)V_,R7@SU_OG +M+W4L0D%:>X:',./VQ<"8]NAWYL,;^:&WDMAQ"*'$CT`1PY[-ZM&#'4LDJ06L +M;#Z%V!A2TL4C`F,^"O72I4M,,6JR7AZ)^<31K7N\J:&2BU=.X`D(T483"ZJ3 +MKOV7FK('7$&Z2VQ$\'&B#X9`69YQ-$?A@])+?R9+05`/E59W1Z9N8Z,CDS +M/5:L-1"R^QY8EH0@Z/:E*^R&2FX7SQIWL6T7DSMMT=@`I7/A[6ZE&^5:UXP4 +MJAC<=W1'JP,08X6%3JB>ND\+O>P^H%"V,\OZ#/&Y!G)&+%7](V.E]0MU_YH-MD@EIBJ,YF>S2 +M?.LEH-R/P'KEV,O?+W179LQ;GT/N[`?KO))NI[/K',C!>8Z(=-!M,O.-/1L_ +MWT!$O(X831S.Z+7"GOLUC4!IB5[&,$R&^6B_M@H1QY%VR6\6.Z3R2]K<"O`W +MAT[MM]_^?/Q218/^)TQ[6UII*_<2:'WUOUF.*`]YU3S2"JEECF +MASA"N-RPYEZ7[\W$9NP\':\HA'2#E.^LRM]E'*,;5"G8L%R"(,2&:?4$Q$YL +MJDJ0J%.A(`:+I0[YV8Q"!P/]_KN*/!V&CM4E*9&)(X\QCA1U1KZD5U9]/+X7 +M]MQ-?X405WX9I[VF`X3NC8L2"@50%O_1&*(&AS88/(#M-T#W3O2Y(-7B05&6@+X"QO +MY"W3B$!/UPN>$&NSE^LK!(7L+Q1"^`PFX(V>K:Z09=&!\C<364;/H_K06"<5 +M)H1F/!-^8'%Q/!I(V%[/VPY"5_=$SM["EHD?RRR4%;\Y%#]C1`S\S>F +MLIKEA.4AW717__R>#I.8?N=&U,;H1:\_.[8(?GH'0WRVE<7&VWT/>'P*=Y23 +MY0K;$G4!(IS-W3FRM4N4MO#M&TY$V.R02VS7?5?PS,5SO+/AWZ'6)5348@_W +M-KJ!9>HRIQP6VF#6A&5=3>:MYY%X1,[1S-\[[Q-` +M@2%7YK>5HF!M(!W(4_TXZ=<;TKD2G5\LA2H7CQR+@]/X8.85&2L-9WW-1K +M8'1$>K!RIHR!WEB3@M2&P)6\'`RU +MD)(02'/\%CKZ#261/V/'"RO3[KZU_B@@>T][G!F:1WPS^CXRX)2[18 +M[%_1.O:$M-O+PXUJ[6B1RVD3*,=OC,$7>-:'T3KZHR@=KM)^3R*6SSYM[9;. +MMA0>Y-Y;>\!)*21RS\&WZZ,WC_6UD$+A%XVUZ22$1Y4HE5>VIQNO49Q!R)+] +M=X:`P^T7X?#YA!';G8O\^L_-I!BI#LM07UKU;S=P<#91,[R1B]JC]P@?]N=5 +M=NJ5_A->K[HUL*@]OW8:4]J(&!$1?_1:2D.O7U&%B+$.1=I*`&$0<_GL%VP# +M_\>('*UIT_)&7O#&3-77+#]0=&;-H5:.]A9R-A1T+?^YG"_$$.?+;-A7L+-\ +M`;'K5-V225;()<#G9.?(6TLZPPGO@$)`G%*+PM47WP\ +M68Q+[GK:9`M#EV-J3-Q>S=VYP8RNQ5-$[?XD#4?[V;G<RBZO40*EXX/V#V5SYDK`D3JJ*L_!CYQHZK\Y'E>[Z)$EN*TIM"(STT,:$KUT_?V'<('`W0'F7*T69H_;K.H4<&0*WR6%!,RE?W>&:LM\4!'0M2H6/5_A> +M1\,04L?8F>V[)3?.2T_A&'1V>N7N,ISXX)_WR-V.P]>D;9/"9E=.9KCLX_=G +MR7(SNKH7#8T3[;@`=Q++V44H`8',9N_S6%]%;O=DH8FY1\"99XZ+0E'06A5? +M1J\T9/*5S1FX&@Y,DV[=5PGF;2J`[(\<.%O_#[B8E8I8VEY+UO)X`13Q#`!G +ME1Y\XEGX@RCV;,1C,[R\2`6_XG!J*M*U+#KVX>GV5#'WK#1E?^Q8P'H*KPJ@ +M%$(K:=60FQL;P@Q]A0[0P\F.T3W;FD)$&!*['Q&!PCGQ4DQO>>;FU-I7GC\P +M9QV*OUS^RF#4N<&).<-78J5,@[A.\:_#&@S9G$"=K/>P6KE.Y0@;:V_`4+[- +MT8'$#9]EE]G;]HAXOAUM)E'MG?1'HMU,S:`H?;*&1=Z__**T8?0<(M[=SB>* +M6(-6HY1M59WT(7%V&Y2AB7K*C\?I^!?(M$#T5XZM4]ZN8/$QE8U]SG"1$2=8 +M"/?DO&OI'[BX6,W1^I;XU>%/_-KAVG?TLL5`E9(YI%#3^%PX"OS5D:]DZ14T +M(;B-M>U:?]6>M)N_,K^J"/HO/,C(?J71RI9=:!/ +MY@3CN."5E +M^:;CANPHVEP#&7T["5<-BM&JQ4W+C;-*!@]0Z;PHK:9"N3C%3[PS(V/ND]", +M^5!DYI)\VG%GA=.>S!'*5HLP/!I1\<,%Y850/G(D8^!;^*H#DO&^DAJ2P'MT +MO@#AHU_SS<9(TK$?RQP":TI3MO5\?W6%Y`S57^'.[SM2'%7LY\*C(_%:K6,Z +M_(G[X\,H!$WG4E29G9L?M'?4&F6.-SKP1>2?8:P/^8?#33,H[8R +MF+6S'>K10.+-0I`;^W$BM]4^ZEUZGT>?\.E4^P`P.'?^@H7O@G3'4IM^&J@( +MCD>)_4-P,U\SOA]9/Z,`R-,I7CUA<;3SQ^\WK>5_&F45/A,4-[_DNF +M6--:^].'E_5\8HBHI2129Y-]QLW02:YK5^M[E@5:S>:-H!,Y5:,B;O>1J-)> +MR\V[!%RWM@![]J9;'F'8GFV";[(;/Z,+NG*I%31L0UY+Y)):>=O,3B"_T.50 +M*J%"%H?CG79R3"^R1ZG.85!8B:+G:A+DHA.IE+8LQ`R^32C77W3EIC+3_U=^ +M2IZ_TM+1,OAYF&Z-#6XZS"@U:DS"3Q*<-:QC"*1*T)UFH3A4U&36^20QXFI: +MJ8!,TX62'`B5(#U%1&CYK)Z1Z#HPK=HW[U6A1-#"]9TL:W?#B*6OG*(2#[#- +M3C<_4V^A[9O="J``AD@)O9#_Z]N.W4J:A5MOJ4YV]1[]?Z_?E,L(/3S`<:9X3@'8>5)!@]^N"FW]8%4(%_K4/(/]M.#`*'@;,$5-ZG__W+096]Z"!8"]*^.,Q6#$)*+,6B?C56Y] +MIFE?-`HT`_R^=,CQAX61L`:0]^6/"&.'86>?"^3M^.C^`_W"&[>U*\,+@QCA +M:C`A>Q@JF/NH;,XA6?U*"M'5E=>U&83'J=/'SYMI`W/TQ!.+@X3OVP^$HDR +MSZ9MD1[];,U0M#(11,&<82IH'3(RR-@OZ1%3SMC\WZCQ8$"V%E_<%I1@M!>Z +M9>V#IX`%I)$3:8,^74\.$92?('[7B$G!WV+8O[EJLB8TH`_6`OO]%2+@.2H: +M;9\$K[3V=S,P^UGDKI,4+].&4==[,9%*6ET[=3(-KGP5&N2Q`$5)WA<6K7*! +MO/9$#GD7G^'8)?FI.RV9)>\&@'@>?$(Y?U+1%8EYVB@":'@)['>F'--C2<=G +M;A@@16F._4NN66'FTL5X.2HRB?)CTQ*:1;*%F`,C"'@]Q\953QS8%LA&P?$;3W@3RH^2*6E7#-.@U[Y3 +MC.Z>G+KS%@E(X=(3JE8ANZ73GD.]&*1[1=$/3DT-3`!LN'9=[>$14.0 +M%5#AP(WS,H]3O&D6XC1)B]]TK%#35V_:_4OQKYG.4,TI&>7F-GCT2WP2)`<) +MHZ5UD=9/R!$>M[CU+BVG7;T1D6WBG_[NJ-LQ'4\\^DZ1S$@\4(.OVND3XVL:%BXJI +MR(*[0G,K.A00K)ZZ!E)[NH^S,!@<>S%8JU[*^4:E/0-]K(>"B^6G%3!5GRXA +M3KM>FR@G80,X'GQGB(]TOG0!)?0-$&+@_$5*W6HTK3V/<0&5QJ`2HN5!G^W7NM +M&"VXRW/,,Z)XQUAH2BV@WCRV#"WZB44W6,!6332$7_P@>MOGR +M3A>MZZZA+`'JA!I.:LG@VAYGZC.ZL:FX_$T'/P?V<&TZ4!K7I#??3J0+5:X_ +M>]Z<_9;QTYO"J$@=$Y#:#JT?F*4E'OE4T(:@F;[.4-W5*-)6Z7*]W;B>^<;# +M:DG`3K.H-9Y\A=N9G^$)<.V`8%VHEZ/O+(J7^(W,#X\NS;B2:E1H +M?"6Y30B8_C-J7IP91D8\2RQ.$S*(>*`[=99-D3B4?DC`?XU0['TMRA3?15JA +M_,64&&KYF/_]$5CQ30)ETXG_G/* +ME\I^C*NY0KR&G8.V3T6\XC'EMNY4I!C%:.F\H(JXS-P@>$LALV3SN +MV*P.ZZ-0/#YB0RE);.E+(2IIWYP1N'>=A@FUHA$;9WU_O)UFQ(H*5!77]SA+ +M*<9HHHC<1G]RI/8L270/@XU;P,G=S'2](&DH$WH92M,[S +M60P5_TYR:A@]V5??`"^AFZQR0-EKMNFQM$BOA4"&I]&"=^E9W2FA_0-,9*69 +MR1#$^P!2#!`D#3_@X*"8AJG=XH.RUGYQ39$" +M_!MR4%JZ'G)0$E8I"74Q%%(JLPWWAQYD^U(6*H)'^MQ7=!:8O'M<7`OD5?L4 +M/9S-YPJ*F(CD?.RXFFKZV.;KG9\&IWYR5W2-6OXQ68,Y30<<4;!OA;#52Q5B0KWE9/TF06I`K0^'19M0\.U(BN19?IO#6'-&6Q +M;WA8NQ`1-!MMMA-9ZUD;E';HLAT0#:XD+V,NPV&+WI(YXFMJLQ2?Y>-"!KIV +M`HYEQ1N:Y1?9"-2%7"");*!J:XU?6FY,*,[ED@3[#?2><46LS^B<5C/$U.GM +M=9-&BNC(L0D8D!]:R`]UL$WMV/B_(LAVA31]T>W.M +M@XH1Z+:+;M]3.;"'_-JGZO<=!_IAWE.Z\;@/%JB`J:S0W?6?X[E;AC0 +M;2GTW`Z%*AXTZ^!&\I24HBGNJ$HV3B5G]R^YS]*OU083]"1Z!+*-\]^#_E+N0Z],Y:]=<0:> +M!4UEY$J.$N:%:-KL3+-WG\(TQ.A4K0@+S1;9_AJ$')<-[+6AU)E*?S7&:=;I*=S."J?W5F2D)_(:\$"R]]?>5 +MI)KD!MN]L-UE+]$@XW_9G'0UOHL?TYZC=D,P2#+CGWQ5(F3($D@%9V-E@I)/ +MY#Z1UT[N*$I^/1^)Q!O7XXZ@?!`V8I5D;Y(W_C*^V`T%*U\)!H?:`2D\Y6+! +MR.&0X@1L1YI2(*J^2VGRUYD^#[CM>`.C5P3)&$!]+/D;0<\7!OK_]FJNY/%G +M-M^3H]L;TJ39XY?J&241*^$/&JWG^=^)JN!;&ULQA@Z66\RN7/=;/*=^`1Z(I=(:O"=;S6= +MYS&YAAV0>?2;1+HUWA/>S.-@9T1Y;#):5+-2O9ZA%_\"+@!<(/`:D\#-*:QF(NQ]-.2$CWGE^ +M]ZBVLB(RC21=U=(\4]SN8ME2XN'A9:8(_'"P06MI8#$&;6B6-AY^USAS=)X' +M.5!C@N'07,`>%E/)=@=`.!EKEEM]*]6,\';*1]]6:]JEH($_(0X6S:69L/,W +M8:DYO<4LJ?I@8*IL]N^J]XS;X&7V"RB&3I."E5%O-,X"L++=[9Q5[LYF8ET4 +M+00*\F=`X3(-(DOS5334R\HMJ5;_:.;FM-I_G.E>ZOA).*U(^33SM`K)ND)[ +MEY#Y]MH.B[(@]W/89K]F]7X2F(8A#(R"54^UB7Y&/Z-+-P^5JDF)H+O!I1N_ +MPQYQUTSFA-`G2%Z$F>U@?TX9`8$UP*_JF=-EIX#-X%JS2V810Z%SU`+==]$. +M+5'KO6R#^@]'(;>)I3+:*1KUSU[EZXLG,2:#BL7OGH_Y#Y>PN\K&%D@7K?,; +M?\#VR->%02?UZ11.:?*Q`G9>.AG3:+>#)N8S['Y'/(:O21[27_:0QFQ4;0?U56%9.S!![BS^>BEAQ3 +MG\H+.BY*\BHO1'XG:F5&\MLN'_'-D2C[/\UR4Z26'_^QE_Z,XI/?&?AWS\)\ +MEB6'H+;J%I`Q&AG8Q&;D.%6R0P^0ZY7<(Z?LYNW1MF! +M](>6M^JB4"J)LPT@>L`ZF]Y,<,%O2?@)Y;WFHI`<4(`]`IX,^FC=9*CFB!DK +MIIL6533M$D4;2W'-...S$CB[GPK265;6=(K1?U@*4D+[0E#5![1=210%JC'- +MZ(ZODFMMNOC&")B:A2&P1>`H_4@2_]H&((=>!#"U^M!():P0L#=2Q')2?R(B +M+(NOA56,-Z,K$X#>GP'+X1["$F54(^X>'=GQ!P51ONAN]\VZI_D5N74=\HKU +MDDKK^=#:1]GHCULPRK]S/"R-WCH<3.$\#&OI0ST8;2A@`9'-I50X)X39P#&L +MZ`SXP]`I-9,HU,'N#PPE"J680>MHWP'6WNI*CR7O&"X%`6[G,^-*RY,9X\=U +MOC1Z;X0I"Z:*(!9X4-?/$O7Z]U`#XW-E,]/:3M:NHK!E1,J96-ZD5Q6_.^\% +MI.%)Z4IR_1$S0T$I(B0=/R2>96W,Y>!7JD="TOX/N-8BNET%F:]O(B'#4'_< +M+'`!Y[F=I5W'`]`AV:!-\4=BN[94&LRKV(;W7O"/E]-!@E$CA.5O\?RQJ;HC +M/GLOT"L]H>Z*]4G5U(>!U32#!',>T#=!N,3W]#C-$)M9M%(F<;Q55!\IKH\> +M:]6J\8J,E,##U4%2['-J=P0,CF4I5F(;041:U]VU/D^QP\&L(QWTI8JES0_. +M[(^]ST0-:EK]I'6$9?T!+VK+LX+6&.GOQ8GETKXU,TK-"4)AJ&1R<*$34,<5 +M%D4>-T148261,#7U^D'M0BE"`8QFC$JX8E'M%RV['3L8E`M"Z7D#1#SUXQCB +M2ETL@`(5+&$NDZ$Y4U8GSU9IX_TQT7;_0QF">!I9@@;9I["3O^MET$+?-*#D +M6D\3Z*H;_^]Y+J +MFEC*$4_!59.PNV3XD$2B!=(Q'M^Y(T9S\X%K.=>F8M/FCCPOQE$#A"_*MG!8 +M+@4N:^0)!R2-4B6ZYUTZFK3099U>U*L7\##2)L[(.;CC1 +M?:/8'FK$-0\.<*AC<;Q+IZ\#GO9>I33*ZX+G'L0MG2BZ&8$#^:J6P^1BLF#<)-66'_;IL/.=GA3)\@B-6@PKP. +M+]GG@9>Q^^2!31%W8*42Q*N.D#-SFV/\M[(?Z"A?0'VR,)9#>L/B`VY,Y-73 +MK3/R/^#D%M3`"SJB7;"-:;SFKVAH=A6>I[V221<,PK67+N<'I)V/$_;>.;5[ +M&TYC,'OK-I)1#PQ+B#%%RA)J/]TQ7!&H;Y9.KMYM;?MA\(B,,=R_2SO`'YW\ +M(X;E0:)W)W`)FM9?5[+ +M:)JI?1R3--OY=!+5N5EX4('KC>D[8TK#1NJ"_[PG&V<7HWWASC.:\QW]]Q#/ +MYC1%:O[Q/N-//[*2ZS+ZWN(:O$+I^`48]=>NR-#+L32NTF"WD!:!SQ."#;'0 +M+\8Q1YGK':2MEY/&MYDI8_FP1A^(@6G2KWN7WD@0R!,TYKU>&%,1-)CR!]Q- +M,NS/]4>T&,6Z!^)Y95D!QUVKB?2\QOWL8]J-)NMLQM#&%W=P*2R<4N^*(8=( +M_3EE]A(IST%C%#^>)G1:;-QO84$@$Y!S(47KI&\^<)F441%SG14-2S:9;WYO +M'I4LT:$HW8;#SSZ?1.C`V$L>&2-FZ2N20X`>I>2YG1IZ") +M)LV40D>FI36M+*7_'`'.!-Y4/M5YGY&V4AOZXNV;MQ%[%1W#D#,@BKJ+#.X[ +MZ7/ZMFM#W0.660YZFU-R"7!4U%`3?DHK%S30?MU9"1]0DG,^2'SEEZ[.SD,6 +MB"L)]_/W#P*-6>I(JM6;2"GSO\'&;S2LCWJ5$(RT_)KJ@_5MZAHD`R*A3 +MD$C,M<@FR:EA_J#X.;]5_8BQP0A?]-OD^$>;83T\1L')EW/=(0T2;IZ!<[HE +M;E/+D)$\7_!:WR-IYF?23.1WL_6/0GU0!]CI=Y/['&I#[PI%8K7D(Q*\*3/<.P<1Z&IF^=5KU.LI/XJPF#KX,1 +M^Z^`@QPO<+3''XV98&H-,HJ:GZ:#>&LW_4WPLIH.@-DK1L-F)U*P<_6.;S^% +MFIU>=O):IS9I!EB_(ZZT*;ZY-@J'L%\Q;.D?T0U7UA^9%\"7)I7X'P'WI%`R +M^D,X,%%ABS!K"*K\2S*,9V^IDD4A3$['+L?:5*6#Q92J*)-[:2F1_W\\/_Y$#KA+=2FP +M"JA6I51.V!R_P9A/'"![*2`D?NW!X=[%'9&?D'O1!^`%W)_L0?;PHLLHC5[. +MF5+FXQ,;B+?1K:N[#"HBJ@&/3=>BJO$,%\WUA?.HF7^B;7G_X<@VHT@'DW(^F$NKC3BN$M_!;S3V5^L28$2YU=+CWHX7?W +MQ,^UE44XUO_S(=_@L]!OCSW4@WQ,TK'Y2156+Q9NULWI]4+>S_IMP=,Z7UFQ +MDYW,.8QJ7V-F/=I#59&V19(1X0U+#C\\$A\CP(E*GJ +MZ%PLUHP<27A6>E`B<5HHF$:I[&&LJGEC4IFM+#,V-CWEVVL!XAZ0PXFX57@B`SN]4`>_SRSN+ICPGR:E*A@Q?Y/9K2"J_L0V,S$-[P +M>Z9#;F'1/DX9$GNB>@RNA][;U%LR*H"6G$ +M$"<_8RTDFC\B3?IE-""K@X24!,D*,TG'L%%YJ#@;2"9^?Y/Z("%4.1+Q/!$M +M^A6,"S!H;U[U?Y'KVU\<9+7H`12R5`]P6,RK>]>O/NA[,9"*HOB\<<6%[YT' +MM$$&NX5-DZLV[E:/E)&*/OV\K.N6#/J,:N%-N<['Q13D]X\?!![PO92>#1M_ +M=%V!ZF[U-U&EP1^L^7HL-&'L!41*J@KPM-;:#`EBZ-@?QN9F3-:>^% +MA+G9$+&O\O=YHDF_E[2%_,]*'>'D68/#+(%:(-7\O)44&YW1E +M)%]UQ).SR2@\9!#?8Q-/SU69741CD;6,AY+BHFH7EVNW5*7+-W(5L1YCF?#@ +M0+>E/:DE94\81S?B'8E5(VXJ2[6L,0^2.6P?8)7>>.SEV@&OFWI5(6PFI%'^ +M3#`0L$H6]4:_OQQ@G]MF,AJE:$E02V*2J_#JK`4^D3E,,KO[B;#H&%)7T;S) +M=_=@[)B4!ALONMY1(Z^,GTHZV9;@?)+A]<4[\=,\D!!QDG=FKAG-KJ83<2(' +M-=R<%1Y<29ZZ;';KXB=9/V,KRB$(?FB!50`V,,2`=1-?5O[_LJ8>"A19-EQI +M$^,1$&>U7VGXF([U31$+].SE46#*FW= +M^8A`#)P]")J#@"&-6!B'^3OK)RIA?U9]4.MU+"\$%3H91]Z\\?1;4QB(@0W0 +M]*3CB'.S6G7K06SL__.J$*IO%5""TXE=@*AN\YS1,,YIGJ(FORW_]O\%X_,# +MS*59:9YBX`W=O"3N!YDWRKZ2U!-HO&DA^>CG@JQ;@_DJTH=0,+C^8OQ#=-+I +M!7NK0V]77'!BDHXM,!4(;WFN'W351#`""%TXA\8IKI\$2^+`WOZRF7G)XCKA +M`9&6S2U:4K0E_9\BVVVA:<1IQQ*>EGKLZ6ZQ&VK9,2*Y^`3AL&`@^0X(VC#5 +MZ-28$^$GWHQ.`9-+7P\XGII#!#V3SR]N->,+^FS-`V**PX7=T=MEOXHE+&,7 +M0;9E-&XMCDS-XJ[Z.(',+Q&79ODU/>3&M&H1_HG[[G-I0YK/2OVG8>G+9'E( +M'KOV;GHT`0HCLYZ\UF`T>_'5'WH3!0+09YV)ROL +M^:%"?.0MH/WD_\)%_VTUK4&MBE"G%)/7"'+*-9)T%!8D]2J9@H_2Y> +M@,YD<1J>5D#A!HN6G^&K&3P\$;Y]1CHJVG>8DNQ=[PRZ,R#U24Z+1?"0.Q9KL!B=@VVH&6D'+Q#BM3,?S-RA7?Y?."WL3LUA2[*7_2.SICO* +MQW_V0)WDH\2`MR7'HSHR:K@D=\U<%1R +MC^N,/$8;,_/.$`$LH?S*K7ONFF#_Q+^TOO:SMMT97)C4<3U2!EJY41W",+L19CT +M;27A_&#*C65+CCL0]$7F<0DBFQ[1];3R2UYKQUJ]V5\WJE')!VOU'I*9O95[ +MH'#'\O0]II^V68Z,X5=JC)D9OX"._:;(X6PO,V&TQAGLH%UA_P8L!L.2%L>& +MIZB/6`(*JG40O0[]!1?J6\QB^#7(X^TS[CO!D3!F$&[R/F,DK#-ZV.9!B +MJJ"%?Y.QBM:RM7\,H'N=^TIIK-E.E_R1-UDFR+=)*V.O:L")2ZB9@(+2GFXX +MKY1E@K84%U+3L0^F?8"]AWQXN6F-VLJTW^'9_H/5ZM?U_C3<_/K4M4X8,-E7 +ME_H.`:$=74N0L[P;^7H1-8L(9V=L[7DQQETE9M]P"HY8=>F2'`SH2#_^R6GG +MT_"'2DK'U-%D"KJ],=%+6&`OHE7W;<\@[9C)QAC4H4ZZN$8LYC'Y%]I-J(-) +M%MLIBZ,)GQF[Y4%794T,"ZZH4M:IRJKX0`6"^-P>9%7D,N%)8[QQ +MD7SGS8+?1/`*[F,!TDI2P->;`"QFX#*HBV$IMGV_$FRP=NWDV.>4?I*ILB^H +M.9%;]D^#UC^X]NDQI=%D5Z[*/U+1!^PUE43B( +M+TK1A9V;)I8E4QOCZBN_"I#`MQ=0L%N[!^@H,G+LDQ#-L43&!K5^`6C1D*YT +MVKO"DL2VM\4J\1U3S=O]*D7Y^_:?P/616,V%_'6EBDEH9_DP@\.I0/X3[.?NFB8/L33(]"?(9E[A-*CZ/\+VV<"R0>`4D5O_OQ6[JW_QGE2-D(7S +M51[KM/;[1_M9;".FID<"%-K[&C3\@*>K4&A4YV^JT;G1H;XH7PQ.EG@Y*CU6 +M(8O?&+X2>^*])7)1?SE>YI[U:@L?"K?.?Z88%!+WE]EF6YQ';X8.2GL(T[@! +MZLZ*V/;<*C\`K-?J#8%'+CRITEQ?^2(?HY@'?+D:]4!F2)&%O_*T)$/L8#3H +ML7?3I.926%=#F+@5F'1B;QY5&W^#HEB0:[`R%0\?E1QIP7068;:C]_Z8OSL4 +M"'O.L'2RT6@PR7(D&[L=X2VZ)DE=9UN3T4C/LREP+S)3F*4=">1X\TVMVT_! +MKN]7G(QU,%NCYR*==VN7JH):1B_SJ8VYC"U7MI5[3ZWS4G[6G0BC=)MT5SLP +M9W8#6M)#>FZI;^R*8)83XWFCO55C>`Q>"@P6"?B?3VZ8=/;QF9@"R5`-._10 +MP7\X,KE*(+!`&BY4ZV`'];&J\F'PQ<6NM(V3K,%HC(^/+PA&;:+L92@1Z3G] +M,!)$!1^(:+WS?,=�O>J*W'`4.9*ZLBQL?B]%=,4.\Y)8HV,[IQPZJDZRX> +MP^`<9L]7JB.I(*60J,&WV;AY:@5!IA>NIG]&I:.618NT9[.;@`T>-Z2A+8<9 +M*2EN5*O)9RMQ^QL^D]#F1+YYD@K2?>./\#CE[^(%(+&P^HH6)@L*DX4O/A^3 +MRZ4$MBL%:^OUU_W#($%9W<95&D^26FH"(3&E/2'&]>^^T-^7>/'DU\X"FW$/ +M9%%`\7-'J)5LT%R'SQ<7]_E2_M8":]R +MF4B!I??NV"GJ?W(R:?VG>1FJ"H?1\#1.QRA+NL'W;II7U/%=;J[V>I0K6J6Q +M,?7GU+8S!3BI*%$&)YMOR3J\[LH\G;J/+1_9HZE##,1YF8:I/;O.R8]UIU8' +M/%[(WWV#)6WM7'K]:PX"G8N3*E1;8+EI>[1)UD+R$B+2[J+U.ZP"9@1XNBJ@ +M04O'(OP8CA>'P@8_R)8PO`J.&[HUM]PC3C0'WUF24--4#];G]OD[-_5XD9V. +MW(2'5^GFVO7V=G(/'MO>+$ZUJ7BSQ%QR:UZM(&@%,(>41BJ:_A$D_AA[L4?F +MSE.KC>CB$>0Z[:O"8DJ8^&7KP-/[O?VF9PYRT%H50+%E.CXP5<5>CG8"7U/[ +M8/10-T`H_09Z7:=!&`1;=?W%C#Q'4,/G^?IT]#&%$]T/9MK6,TB.'R-&5GM7 +M3#FQ5&&F[9YS+X=B +MMTFB@'?7&?ZX^9'XI:2YP,]()XC$4%?P&V9&YBVU>SFPAPL(`(42=CO5!,!$ +MW@9NI=@RNX;HR4E]#`!B,&.VIUK1;^BTCEVS]1)9&C'%%>BTC2PK%78H[Q5K +M&.VY`_K]5U>2X?_.>8W+&PW8J_"K+2#*)MB1 +M&X#A>]!P6X\"F7`#2DL6+`]`PC+CE!"W#[_Z89\*>AA[\=#%GV%:E+K[JO(O +M''N<[;RH0MNR;G?-)!1@%D;2-UTZ<7%,/;X7)&6JR&$Q/-ZA3-+^=I#"9G#; +MQHIW/9,^;B73UU:?RZ:.ALM:L%\AFF\#Z#3<&\R(,\=8KT+'RBJ*&DG">!Z] +MMK3IP([<]NY0V"MK^/*'K=4Q"5J-Y_A%TAH-[Y8]G6(6UY2,;O:MY=$X1SB) +M/_5-*5.5<9RQ1XB$HT1B^)5YR4B-A#0SL.ZF-9"B$XT?TUI!HAQ/V-PTRC*4 +M)EI%.7,40@V`_=4"@)4>];#^:8#$/>A<;\SB2?Q2X-5[=3S!')EX@^=80EJE+`7IJLYKUL[Z')E$ML@/8`' +MLNWD6T*CFZL@&&0=M^9YI%:<.VJ';OJ2GS`OHFK]V@6VJ$BBBC653H>*<;[D +M8?C4*B0WO*P.,]=)V$D7X;:TJW)1(UY$P()!(=:\V%X0(8/9AU*6S>%4H9=D +M2&,6=9VS#!GAH.>,ZYF1A4)8RG]3\TZ<&F>@B-!'=T%(:>HK7ZYKC"WZU,HO +M^5(+A3]@A;ESY9?:#GW4H><\`,**M5WT75QR`;Q'IE$VB@4$O_\@2-$]E4S! +M$0S_ANC!",6FF#/P3*G'[U#%QJ7ZM$M^0)%II`^?G;G9Q)1@GT;D:#ETB>O/]_J3*!<]7U"`Q5!Y`)'G3?/Y]`!R +M:UMNO0LQ'IYMB_.&Q4O`8*[):PB)\A/CTW/KB4J>LT$>^C" +MW$*B-FSF2CA<&XK/9_I`+?6NT]AIU0ITWB"8?[-;@V'0CBI6I11`[?E==`1T +M6>$9C*20!Y1Q]P2-[.MN+;)1@AG\>4\RKQRF&IN/9,@>B2[-F>S64%N,^POB +MJ?%/35J5$!WG4TWI)@\\3\,;5DZ]+`>5;CX;0,P!+\(^[QFLMU0*&4G4`E0X +MC,Z._$"&KX)#*,YYHR136%7,"SX\"]W4EG*@J38`O.-B@JTGV-^)KU8G%M)^ +M[HSP5'3?L4/GN<)5X@M'FFE07'H.6QT3QQG5.)]G8!$K"4'83I +M\*APF2M0H3_&+)_@8'$_/P-$4^&9#'>;MJ993X:;11(RU]LW]N&SFD@T9P3? +M7MHA]:)W*;T>S8Z!76,!&4?C.-]!Y*(/J^';P4Q&XRE$?E)3H4EJ'L/\03LW +M;[4L;PGG;)LOL45?TBWL)#G +MK4<"EX_%.BE>8]DT+C(A`KC$.M)YMTMYV]"Z#)447H&$1HZ`X_`H'%F:7!S9 +M6E^T4(`O..C6PL^L@+Z(L;^3*8Y_$)?XT@WDET0+V:A&:,KJ-@"LU;;U\]6%XQ#H55@R9X:I;(,@DT:(?#*ME)5Y@YAA+PE'9^0?L8AMEMN\-L#']UUE_?=(_WH +MDNS7P-#W9G>_UG40A9H$)M7 +MQU+`CTVSM!H[31TVH64](L,D0I:@WJUK.J$4J1"`A,6LP1<#1-GC/75XXFD5 +M"KK'4UH?47,UU'F(RN\RCC>`GW:8\1&=;!67U2L%M$C\_@:/#R6NL +MYZD4K"SG(NK1!>!FJFJ^*T&9UWP(L(R/7LWEL2Q!F0_SM>5$C:$8"F-;UG"' +M66018CXS^K=7PBHN$!67>GC2P"$T:UH&.EU:5?M"2RA;4J=IV&Q,%OJCU'3Z +MD$%S='$W;.K&,O$'H9^>$MGK(B1OE^/`&'$84A4U2ZZ;[?,A?.RJQT* +M\L&TRE"UWY-H1\QK![TIG/BS +MQ1SQZ.H,>J6S?0#&9`"`^?NK[B23FQYAE>-FICU^#,H;SI +M#34VH__)H`A\53'+!1@`>=*6JSC+!P7O4,:5A$"F/E78MX[J[RLF"0RQ^B5I/O+,PZCO\5],4OS3KZ&`%1+LM=SR +M4-3Y+BHOX2/--CM'U,N/A`:B*`3N/X?>*"/:I7ZZVQ;UR-$"(=RE"^)@[R$: +M9%#6'%(,Z(T^6TN2"=L*/:V*;F\L1!`BJ5G#=L$[$$E,&KVAQC$?5O_R8[Z5 +M?W^@1>(ZKI1A?#K8H,O-`QO/1$DQBY6G^=>E.3BLIW+1'Z"/``94RP/W/2V$ +M/:#;3@\JDAB":P+C@`\^]8WQ]+:&>W64;**$%6TW)N3?M/-/LAO\S*,3WF#K +MS&-V_*VX*F@0Z+^V9N8>7&#<,?H\CLRB?YP[M76P:Q^`'=\T]-@QX.&-E8CM +MPG.!3:2ZCM0D1FF$L=.\;D30_3IZ2[6+$ED^2MG>C1NSZ*A," +MYSD>;>%DH$6M.Q++NLL(`C^!8$C(N0VSQONG?]$VE>Q)UA+^B78K#;8-+^PO +MD@7`Z@/:%I!^!_I1<7L[0%89X(1[*//PN&)>A;G-J/T*[W\A0!IT +MXV/.[;3^CKMKJ2.M"K+$+R\^]=99V> +M&KVS#!Q!!"XWW!+)ZPPXX=XFI^7:.%$!"!PO_T$H$3;:%)LMA]H)5?885USL +MBY[(WMT+P&#/-V>(O&$>#LOLEIWY40Z:ZU5..493TS3J\\9\3-P" +M72&TDXL5>TCWPW+_^"D"T;4!"&`.V+I35607D&3<4D?+/MSI(MY"@Q(=DCMV]K^Z +M>-IMXEE6/*0]:NM]C;!\Z00XQO +MP!TGD/?O?!UK_#*Y%34*WWKUVE7PQG#F2:K=LU:>C[F#37O)2B^U;2Z&7R^& +MC-ZJ;%(RR1Y6NZ!G]4&GO_PZ4NWU;48KX35ZF\.<'8/E<0UKV:(YGQBA/%": +M3*4,UZ"L/!:@QYUG=UT'>')&G?^B;R`2E+;3O#UOTZ^MI(Z.)CIJI$3[1!B0 +M#]MC7'B('4)(U=;9YZ4K"Q66N\3D'BW^YN,"68W4R3O^:\>Q*7[H6_/>6RE1/AY$N3X +MB^6.G-^ZR35;8'/3%,QNW(?V\QVS^8X"A?M'(2(3HB99@CGCNT)OOXML!"ZI +M2UL[]>R[D=DZ'G&A@`^-/WEO5IE"$T]N;I1Y!UTI"@*0"R138`&2T9[QD^U5"1 +MD$]TI*X<2JJ,"%HD+DTPNGI'1.J,W3G:*;X3$\_T@!,#T9!JX7_T>]5Y`$IXA_ +M?+X3!87?Q'=G@Q+`N75WV-&##)1!=@K1>-2[S`S$!V%N?Q*OP;YS;QLE*,%C +M.0B?MYV9N'NXI[B(?YD%SJ@>!"4FM[!!F$9S#+.$LM\#C0N%T2@2('FLW=Q< +MX`HB6L7L/-4*K&(V8%_@6/?_T9V$@>],30H,SP,1"KDJVS0R,9]FOTX:QF;G +M2.Q6;`$?6"EB@N8L,PRWML8(Z%%;(06RSG;RC2+<:;O^X8&'H-7A`8&1#D\L +MXX/%W%]E2XHHL)/HFCX1?Q;V.=,ZN/F4=64)ZJ9^`$@'0#PDQ:T;-HN!.E?" +MA6B<*>U%*MEDLA]\-)<:B;ZO+CI`.$02`T_H^V[$APJM2'F#8%356'8#P>CT +M=+\7%+6 +M&N.E_G?.X$/G/F:XR=`6\9$6`EZ,_CG09(W?Z8=XGP.[^+Z)BIEV6+S^U^.$ +M7,'C_(4QR,>,Q3*Y[;NKFK"#%]3%'N]>MTZ/[:=3I4K<1H394Y^OSMR:53'5 +M?_7&C&V:H\SMQZ?H4@9_-!NCOU;O0FD04:0'?B3$?(:&Y9^JWS&<0OH]$.\? +M[S9XO;6EY^3:ZD*7@;>%<]M?F^>I;AFJ2>^W^>RT36F`KX)FKA3FEN.WM:&C +MP5J@L.T1O<65/((EPZ2(C`][%L9ZC#?TTJ!%5LV@&?,-6)INS\B"=ND^^]&Q +MK]:3:06P\!IV,_K0^A3#]ZCFY +MT$S=@M3&8Q#?$)JA%^`Y+J%SK@LPCY +M?ZFRSBOB1FZ*L(-TG;<\K;_.K@REJ@[$;Z\RHW.,%J[E:HIFGQ*^L/_#8#>5 +M.^LD@/77OK/$-$!PK[BG$_ER%?&0&N!'_<':](^^9DQC9SAF%T`#?,UIF;.>>X2[4&D9H(BIXI`:C0@._K!E +M*+/B&(JHG";.?VZ>E"G(R7]B9>?9B'K3]=YBRZBBYY0RN<5:4*:WFIPC:K`K +M?P=`I382_V_1UD6ONYZ51`NPMU8^/HU7'@A(:#]$2/%0K(@RQK'Y.L3(GBP, +M'!5M-1F+;(A#_^5$)1$,7&/3AK&&@[??0B8J'W&?#/!Q,3:=#@744%RRI[+P +MHW_05?'N+Q,?5-6@-/:C$M;*J).8=]_L.[Q+>P;58IW0!J]"'(W@1*0YW;"Z +MH<>X"L[O*]P4=UE:U.ED<.2)#W)"[&.*9:%XI?R^O+[R5R5 +ME3N`CTK)LVD7>%:/4:E.7MP*E[4>77_'P"2G>+86+JW&A)F/L0\U!774S$1G +M[9TG^P4I@(,+1YAY?6%61S8-3@HF4*#OZLN9DUQ4_(4^RDX;ZN"%-07<7B@M +MMME3=YLSELV2[B()V$BO(AM3%#A+D,)&`HH";20?_M.M<_0O_CT!/>O=+$8F +M`B2Y)V6$C?=?.J0AP.PNPE!O?V'LBTQ.((,&F-E%/1C'JXHYGZSF_(D=`6EM +M&+)'&'@*F,&F&P-Y2&I7%76T^ZC[M]H,UKQ@=@<[CGR>ZKN2N$A;I5W*<15< +M`P='04H,(07,I,VV/@3;AQED/4;A9T`(5.!7/09WV,])4@G6["+).D[H)'"I +MU6D9A(!B9/?*%!?[4SW%5YAQ&N,SM2@O\32JZ]GW+&HII?V)C)`.U)QR\Z^L +M0JOZ4R7-75H3WOG:P7;B.VTL!@5E%NBAO+B\4,"J&=^]IF6Z5$&3&^9KQ@2YGR=A +M/`7LM7PCD3I9B>2]$5^TBQ!9]4Z5ULHKN6-A94^KMP8'/"@=4'*%$C>O2VRT +MX.LO0D3]?\#F'+G4@^+%J2;'&(<&JJ;>/G`-%L%O#V$`B=0:LZ[KDJ78:Z*E +MU;'<,5FF:)^N<\#-RQ5ETNO%#BY]GPVBSN[B\`X=4DW+9B79TH-XY/?VFI&R#$`Q*WM60D^Z[MV]=1#4B7"@S6?,- +MP7[O0+0`>GQJ!!M);!^*<9?"N%.)#(&:!X)CHC_Q%\L +M7,)#$Y92T+,L)PNX6N[.^.V-MKZB'-.@J6RI@`;\J0:XCSTPSW73P,N*2UDT1^O!0N%BXY8LF;LJ8"[L: +M-1+(,U6G!'+4U:,+51P!VTI.ZT+O)N#U'B +M>>L0K`H\CJU3CR\N-7SB4PC6<\7>=A%?W3G?PWMZK)IN0H(+SOX48:9Q^772\:ZC))2;#Q%CX0QIXM;W:6+[ +MAWDBS&X-+OXC',?5Z[2*FPD\?Y=C@SO40 +M!1J]`GRLER\_U$\!^6%H2"LRHI36Q/LMKAQ#A:D$+P$-8&RX.&8_DEMM4/LI +MWO[V>4U):3D;6>5W+`5E0`E`2S#3%RD'XN#PHVU6[E."?/VG4I[&[-A^JJE- +M-)^WVCO_UC*$9;3-5%]M`1T@`?3]J7*;91&M"'6^$2F:J#DX58`1GGFFZZQ- +MW@5_JA]?^]ZPTPH5+EJ9EB=2^U'VC5[[7G0>5HAW&W>7=->X^F:W'PK%S\I# +MUH0#6*2L$J5O$/!Y:NU5GVK9O1!.`-$&`&*DH[PW!\F(V*D70RC<;'=?868O +MW$U;J)8[RMF1E5KW$I?S^W,IEE2_G:G@-44*`MP1KNL:C;[W[YR3*/]O!7\& +M="0&IB7F"H4NC):L1;,Q4C7\,))"_B86.,5MUR9V;Y1$YSF354IW%C,[)K6S]-SKY?^ +M$ZX540E-4KO=Q;E,P\=$=8ICUM,?B8U,,"TA\-`NN<54_]-93.[MHB`PIUA_ +M'K/2XE2OF?F_*"((+34IP=OWXGF3N:-:155-]=PG`F0I*FI[BA0,VFCQ;]FN +M"<^S?,7_9HRTJ!?#-28$KE7[W-,-H[!(RXK5[VD^8DAN9V>TR`)[5YL4WWN) +M@7.D/_GVOEL[X?7Q6!Q(?\4(=-*C>2,BZ=_WNEI1.!%?4,R^$==OQ3;0@,B< +M8_+B,T%4J8]VF^1@`8$B0M5G,^D:,&(0D%KX!G8VDU[Q43CI:%@@1GO0)2K' +MQ/POW@?9HCU)>B2S2+@2%K!Q+UT`)M80X0E]`!`**_I:`?9-)W9^E'L7(^>H +MA-D>CO!#DOM,N)H_"@ES,6B]3E]BHWI +M_04M<;[^1$]J3XV2]+)],2ZY`M>>WNUE;6.`VGPW.8ILA(0Q92JZ;^;%-?:/ +M!TWEX:ND\E/0<8.2'O[D=0B:E?=`%[E +MJE%LEC4_\7B)TZ@$.KJ2FRO_79DIWDA^1D24>G_.[9AZ%7RT?@*E$-A^%PVI +M,9X0\[3L>2)$>(#&4M8D7A``#M!#+"Y<+W1([$N=.=A!;]N=M +M8)@MGGY*2IK.GVE!'%#J^(.OZF"J7[VJ+:]&2>D+9O'J[3YI-*7A9K3;IFCV +M_!V3ZUL$<"D7;$,9#CJOZ,(,.=+EP%/>NV"RGHCJ&$.@H(Z68I`_C"!N`C]1 +M-/FWM5HU'89=$1ZK3&/,!&C2?(&:L#JW@8^)_.;T:!!G+)-(K'D]R*WHNZK/IDB]A2(;5H3" +MPT8'2['D5Q/\D^#,L+)C3,5U5ZP+@>^-&670D-:_DC'MT#=/%>CSZ&.I/4^R +MVWD^Y:_IO8;^H/\)=X"Y%@3GB? +MW'`H]8M'":+ZQF6J6S>LHZ+1F"]?^.;\U0D(F/&=JC_ASWE(RU&J^0W2$,3Q +M)V6&[!UH+WWP5;"`XJE4Y`0CK!P+0:#W%S*+4!6#?=JO>7<-8\4QI +M5E/2DM%260.FM:%+?4'-)@"UV?6!ZW/6/JY^X_0%&/ZI!!+X^HQ3]L$G +MKY.%XK*G[>PHG@)S2_+N&,K`M_F,S8C/B;:BKJVA$1C(288]I51$XT+FT^M2 +M^"M=+3J@M/T.7(<;I*XI!6:`!60)5LT!S#EFVZSWK4#3E +M_K-FCO+9:C4.3V]\>)&%O,GI-]FQ5>?$>1T-`$BX?5-OX$\3O-Y6=F"_2+`! +MS:_5\OV#(R):A%Q842&<_-56$!0`)+N)B9-GL*6?8*Q?)KN]B!>7*^/V@:OH +M65[?OVW1[+>[!?^A'4J'+$9")+4^Z+KQHB&3S^8D0T:;`TR&G\=N.)7I?$Z0 +M?VBNM%&TYMIL2\MX+6=C+?8N&YE!U'P!*KDXZLU,JP0PX*1'T>K +M8",1)%?+"$NN[)WD'Y2Z-$.(L6V'QH>\-ZB&$PO[K>GH'@8]?6HB>6EQT=&> +MV38:3A5N')*%G0&,UP0;<']T&>J*`@ABRA[DRLU:0H2"LJBC4;70`D*/E +MBDC\>^4)5O;C'.$ZR70`#/L7G?X0)S#W4^@?V:^R8G%3 +MP=S8!9R9)QYRBFZ.9J3@B""R/H9*5F+B+#%/UR(`X(/YC#7D#,UT5$Y),ML" +MT#XLK1MB5<#?XG^WUVTN>9#N.TPXR +MG8-0[F?FG\+,70[$:Q[!:4LH96?(SN@==R@J#/+5>*31V$/ENG'W,F)/TZZ9 +MXR;AXW3D%*&_;LNY/OEX#@/:%?/JWJ$#JO^S,\X(N/H>6>93M//0`6KS_0P0+_. +M\R&WX\IL,Y]B`:^!%8-C+J3XHT4#Q=R7,X?%;GU8/+=##TCY^%LT`(?D.0)S +M7[%L3/,B)]R9EA3A>CT9THHRMN_P/\44Z1_0V$M:=@/.J%`,P8%X28Q(=J;9 +M*8;,&]!_4W+Z;P\;;F.L[_QKKYS4I?]`EP\4:0(@ZG`)&?AD-"^+HEMT\[62 +MHJ9#GF<56OM/:;:/W\5V\JW36KS]2VV4+MG-YW)8%/4-)?!=&*-SE>V'VSA" +MW(F9V*ZR8H)O%H.J5:_RP:'C4;V..-9/HKSC5,"EAE9*.=2$1U[U1RP>S)VB,@RF\8`G>7%I6ZWYTDE8I72J_+@S`WFHQ-858Y +M7T0+9USGL^(^KU1%8@(H%>@CX9,/5A`[4G]]6:U=)D;1)OG?"A$E4_Y9=%IR +MM&Z]<\_B6SZS<[=T['=)1_F=4#KX6.F<"S"E<)&+ZG&0:L;@I`*)T`1$Y(10 +MK@FPO]?<^#L4MY9:%5DGF-(I]H\-OSRD&+Z@MVC6<]T)8T,,NZXY`_BY(3R< +M*F52-":=0OK.Z^L,.J3KU@_@1WK!)9J+7>ZW5B%+V(:''=:@M+3;E>4A<`Q: +MU[%+7/P'''M6V/;+>*IG2ANOA3+\$___^R"]SEI[&D%,KZLS;\QE.3'%_I%* +M>H]'.SN+0[O9J&7VZ]V5T];0L6Q:>1F"(H5!55@?-5(LY<;2FN8LYB!$7G'( +MS2R2T\/<6,.?ZCG9D./.MAGXGPQT^*,DWKU=W[A`5MROU;:?MVC\2$&5(VK4 +M)LBI&P:8),[H,R:!B$`-CI+2Y^L\9_;CC4?T2>H<)/&IB6&RUTEW5+P/!3RW +M[^'`,:0Y=@I8R5U;(#O7]-;CFB3P22MDYGGH2P;^"PIJ=9G&FTTBNZ*Q8 +M+NMO_X3ON+;`!?36"F]D,S;N1(2FB>.ZH(#^L__LY(*"K&8F:180)EA^X\*: +MPO'.S[V2_!A,P^V)HB<.JUVBG>)S$5=BM*\P-#1B_B7M7N4BBT(S,_RL&L07 +M'+`KT`O22?*2><#'($OZ)B)?.K@6"X38[[UQ=1FBO\HE0Z"&A)U1VE- +MZ/>IOWAJ"^F#R#DO1QS1LB%(FED(]"&C)N@&05H7),1$61'Q^9;-JV4I7,Y2 +M9/;OG3?:AS\?8V_N]63(:@>O)^.D9E)19HA,F0"Q=K8.@MM2,;MJ(Y;>M/E\ +M$;[[:@,8_YS6';FG",Q'T9O4TCDJ0ZXDAJ;IN.>(:\))M:4.'#[GF>[/YV^2 +M%?(VT+18/#$-`\]IJAHL?(5?G$&Q@/^E[BX9GF@X#*35-71P!%J-_1/ST\@: +ME4F]I4P04$N.C11:@O68$B0R`F;M5G\8VD6Z-2%[55VM`&\U>4B\VU`V3==2 +M>2W(PQ7>2'Z+85\_02T[A!I![K>FT$'!$IK0R8Z&.^<7%7L3^A-W&+0Y'`?C +M"R._FG%8SZ3$[@4[#F2;13M!ZSJY><24=JG> +M>X!D[11P(#P`*Z7:?0"F_"9,,\UO-;S,[+G;/#KA!/P-'+,-D+$%>C$K/7#* +MK#W#\=06=P?+8\>\44KV#7X=?#ND,LPS7MAI9@^9%2N_P/"B:V*$'FT=GI4( +M1&[P0A*9^/+<@/R-D<7V:\I#7$YT"8,,2JIB*EFO$AUQD2S8CKH?=BBNJ4Z. +M\@<"PNNZRH,;;I:1(W(K^C[A@A6N8?P@*K.#2^/ZNSV&Z0F7WD4$9VEOHGAY +M$)3%I\UT8%8HU(,A_P=EKORPI4]W7X_5B-(D4^=#/N\=ZW7U5`D$P9&.H`(4 +M@.9=J$@\A=]O)]X_VR9@:3;S'B7L +MSYF0!O,&HZZ8#Y2&0^/[-]="=.RI=7,RB=U'FNK&0T&Q$-#3O7SI$/\,.?WR +MJN7C0'_UTA!S/GP(R\4HCA+OUCNK'CZA_<'U>%Z"Z:7XUX6X;\)$;RO0\M@_R",_25`G^,*5?])QSF2]$,-VT^S\?JP;#NWT_87* +M(QJO;N`:=$MPUK1$VU**V@MN812._MUWB$1,&C,.$4K/[%8 +M2BOYK0GD\LS,7!_!3=LW8,N^3B^^V>&L)L^NL^0GCXR*?5[$E=8@00D*3NZ5 +M.'T-!C:[O&^>0NNN*ZU?']+J$IHWF;!X=#A'N"('?<+'_J(_!2]JJACAKH*%I +M-ULV-B&VD6E_5]AJ*%BX]`Q=9(+E7&M3^T34H33P"G8$'?JWP^)P%N]K@;X, +M6@`5BAP>F9-@+P)^4XB""_DZ9T5_Y(0.;)B4-G0+AK&0XKV)`*36#P?L88\N +M:MC.$K[BST;:'J83$KY>-;EMH&C3G,S2`:B([?8$8K2C+%JU]IJ)8TFE%S29 +M<>>B.S\9:0WM!_/Q):G4)5;_?(`$95RFVP,&&2E)T"\4D]AU(SUF4J,T41ZS +MAZHX>$+*@E&??`AU^Q524$T.0RBE-KG2&/)W>4L'VJ8Y)+H32:P5PU/BM4=C9O:A +MP>UFU<<(:Q/2"=6.[2A5<(*O6;YE0>A0"K"Q`4C_2R1,A#IUGPHP/;^6^J;7 +M]@S4*IC);#+1.$1G:M=57\WV!V_C'';$4GW\SK0EH0FD$H,%A"/.E4Q?;J)\ +M]#%O^/7TRL1IL^?,I=)7$[5(%8XJLLYMQY'!@A]_/D[FER4CG(!6T8B6:S\" +MUCHT&)Z0NO&@_9G:XOB$+^7/BC]O3SQQ($"(,6*\PA5G,B;^DY)=(%":I>2! +M;^DT%!4$4^CHA'QQ@?]/[>@\IWU41E]N;9]IPP=?*[H""UC-/?"]4+G@YLR9 +M4$3.P.[*!+Z)9DTSP)65U3P)*1\TP8GPXU=-QK'Q8@JA.OQ@N]5EL=4.0;[A-WV!X% +M-3_?)@/IK"JZ;"]/9A-4=Z"-([K*I33/S'$Q_WD*L0R2Z4.-M664[(!VO-[G +M@_4D"WDV6CQK>]47Z-G">76LR(.2'Y?('G`\H*!GNL1@K8?>5C[K% +M?^%Y@8M"\89^3AU*2GRZ)CT$6Y[UY)(K"QZHNY)F +M!$/W,HU/!IF_'Z9N2V1&`\'RM,AA?3_CJY3YYAO_G0-%J)4%LZ8>R^E(_^VV +M'@BDY#8S*L$`P\C#E.@<3VX,!7._-SNF^3=J"K%J<__*;K+'/GL&X3?:W1O6 +MUX2"1@*"+/, +MG[2%OV$9MZE.8-Z\_P(DC9M8K(0_^"H/FP+#W#SF>MK)&0B9Y)+"J#DVG32\ +M>O",A.*MH6YQ-'4WTNBW;L.<2ZT*U5C9):;L8>\.)>B[>GN0R41&1/&B!0N? +M\*JT?'LY`^GD)XM0M.O(+CSV`:0<]&7^<2,KT$G<3^6S_((L&I=-VF(@[2^8 +MT'CMU_#_IO@+I+"4B:6>:3+]T$01HHN@:WC^$5]%, +MQW6>JWTS2/$G,G"#JS2B=4BIQ!"D8)L&'^X_:[L.EY"5`:%<0G.[6JYN8D<] +M_P(;K<_>?(OXD]"#)4`@;E@H!(._&O?*)\CGJ*"MV))]<':S=OB:Y"@',)"$ +MG?1*L`L/`,C=PI=X1^LNL[?OS=1>/51?RWT]VR).B%C`-1_)20VL6N@=O:?R#UNQJ8N.-TLQ[3OUA;`P:[0.F>%0J@!_ +MEAO*PXKWP#T9_D@WOA?'U2Q](9\\FWZOI<&3T29Z;N_P>,6..1XB-1`>'`NQ +MIC\N+G$CHE.0\E7B35W&CMI83_`&\6O2R.6!LJ]%ZGG>MQQJ<)<=@O^<\-ZF +MDKDNZI.^5?\IQJVCRLF>-:U:R@J@N[=_FXR[HU%BG@H#7( +M3WF<-'./A;M!_A)3VPJMQX'Y)Z`CLMP! +M`'H#@/_/^IX8)=Q&?.F=^1EJS=+REAS-X7E(Z^WUW>SN-='%/L09$^C!QKCS^]))X+VF3;IC::OTP\$;YX)%S1RC;@9W`YZXX3 +M,7&Q%T/%L7`-ZU:^41 +M+186(CD:NR;LRX5TB;@W$:Q3ZKK^4)>6F[:V+6+;_(,QHY!+72_188/+F\;: +M`RSA2?@Z-8@DX8BA@2V:8[J]C +M"BXV8G*Z@)*OQU4-L1XH^@*G>W1.J[]^;/)@\XZL84I!H.?G"$2.^#\:U/5. +M/&M=@N_K(ZN-\&L9)DESS[O@0;! +M9GH6W0"TEG$`M[MC!\F^5`\@YRJ'H3%1J$WUBVA03/A+C1:P;A:+%'IVXD[Y +MDS)6KD<'FL!8L4^Z?584L.3B6V_9(J(\`D0TAA)Y=O@M*%-224_&XW*``GF+ +MN)6(BUOZ'.YP;KZX_?7,2J3TV'ZUB6V(IRG)P$B)&RTD1QB+H\VAD4B#9%X7 +MA*BJ%J?!^RE\F5`H75VLY9G=;[V(SSM/H07^=E+QVHC7BQ'D9:_:38U6]VH4 +ME0,.J`+CVMAH[(&GRM@YC2VS36OCY#Q+H14R8\%,>R(`F4:&L+FYHEN[ZWE8 +MO(7VC!"64OC'#\%DME-4:8IC3=+$+JV/94W5UTH)[@D9MTBB1#->^$'?%\C5,'8/`-%J@+QSW[4O\9D5^J>% +MD,X$;1]D4W;K4&8XUCQMJF,I$??#MY7@RT:8?FDSW,.\N3)^5_G1Z_2^1Q>3 +ML>(_ME>O/OS8037B]7;H2!3A"$P@D$H]WMA9:R>82'#='EJVJ?9N`6I\P&#W +MPX]\7&3O4Q]9H'^VKY)M(AVSS&V4XZ/7(H?#6,==KP`"\T.O!_8N''6_S/RG,>;Q$'+M`70TAMAR0Z#9*O;%V`]+,@Y +MPI+HJ$8UG6=^I&=QYSHST=Y,F%^#R8Q+]< +MVL"*&.]NE\B=YO&ORNP3/\M7+@`"K85A>L;X>><`ZC>:8G7_&B0,I81&.BU6K-0`Q/! +M7VJ0PIP"ODS+#5&@'XD)A-7R?-H%#$#0UTBUR%BG0*IWF+'0'LF,Q/(*XILK +M#`\!\53-#Y=BK-?4.=IJ6S2`4*O([QVTJ.><"-7*.H+@Y**;[)RKCR7+WPC* +M/:DUVD6/;**'@7:IW::=^W.-U- +M_3IN@W&#FO(@?T`_,2B=@`4BUW_/=.A?.912ICXWI-+G8BCS"L0!2G:[ +M+4DCV8+8.(G`8T7A@E\6=G[\'Y2E]4&V39*(NQX+H0G&.#]S7M#H:BWEG6[, +M[0(\.F:J/<9(@`;L+TV4(66OVR;U.P3612Z+J-E_F'#!G!2:`=B63!Y]3!]( +M]/]ZQC[Y^#"'5FDDL%!\7X^&=@ZWV/W.@#/GMQ1R_L:/O_80WDQ6K.P,(Q1P +M^]OFW&^KN@:%FMJ_4@P,BY%F>X_#'CM^'CI1KFWXDCTG\*[J.OT(?;NUG2VH +M7!:#RVBE_RS>HDJA`,4Q84%UI9.(7FX-79(VWLY?P+WJ(@*%%K%+/[%O5@!V +M^R#8VMW2=6,K.:-24GC\(RVR$`X^1GCV9?[W!9K]6U#MF_7O"%0S>!*`-5%( +MRK+@I9!+/W&2,)+Z1&+C">M)0"N?QP9)-SU0.K6T`G<.94E.LR_0U:ME)>OO +MYL-YOW53E$Y>Q/9OE9YP/3WD42>G` +MVX>.LFWAK"?\!R\8'*DMIG/2=UUO5!F`I;`[ +MWXB.9\U#>\DV1L(.G.B)KLL9P_N+7>C9*L#'W\=M)%I][H))#\:!R4,QN`T4 +MY27T)OM%_3$W:]0I3JB.4);GW7(IA*GG^V^Z:28?QI'FP,I/S=)M,54&=;-^ +M\T<^[&D"LVO+_)%&53WO.NFE7.`WM\D]F8K$-FI&5J6(&&7CO"%,M^:GVF_< +M`YDH+?6VB=R-=2SB')'OA4[8QU.35^ +M\:UOP6_*OJ&JA4+8.XV=/V&.!T#=B&A4`5]MP89[ES!P$?=:O6DT]PY7NP;E +MN/:51_V"E5%/8_CB$-C2E9V^5,]\?UDK+BQ&6&24KCWMS$FM\V8#9_SA'*/V +MT_!I_2I1U`35BY(X'?=PK!SFG9_%NT]:T79YRU,B&5W`"H4>8NM'-P?Q@CK\=.^<.<&$X"0P=<%9J-BU*&_*? +M.'[$E>+C`XC=E3?@@;AH2)B.?8-V*=S$;I^@)?S.\#/Y6N*MV,[*TT +M/(ZSMF^V=&@C3\XI"@Z`]K/*BG!IPAEQ[HNV9MTW7`KWUN:GF&ID8PH?.+!! +MOM51^E*`UW\,6H_7O:N(UBM411U2?2W(UNOV*#6OSA0K?UL:Y_S]."`?N)'Q +M;^BS`8]S-)7O3$B`Y6/[DV`1VCY*DI`P&)T:F!1018M+FOL3K0K*H`(*H&`" +M]XX&94VP9Y,3EY +M*7*=C[!1RF=!D?UN5V8O/*Q1SMIYD"PR38_%;.8L(0#:A?W'!8<>E^\X61B! +MWD!CBQFOCRJQ(U-]O`*&)QTL:7'>+3$>8]0[Z^C+W.C@#X"HR?Q1P@W-289:V,T`W'U-J*8KSIB"9&Q;:9,\'&0%Q:M)V:*>MZX8)`0H\72V +M>I?:*OA79&A@112DTH;-C7K+LSM)8SC#*T3?Y7\P@PT(R%"@D +M_;@T`]=LAK.(LG6PU%!F]+S(0IG]$-N@BW>2@[PI +M^+TJ)E;<[$)O%WL?T["JZ"P]N7'@U42Y-0%BP4F<%H4VI3GN5=:9W@*VEH`; +M?+P"W<@J?/_%IS#S-[P*,$LQ@'W%E!H&0<_6I\N'6%RA&XVUC:E+ZP]KQA%C +M/Y#?A=H\9T`[CY33#C:#&DZSODG4W:W?V\PF5'O>L0GC#4&.1]H!F>7AJY_& +M4BZZPJ<,+K=<-BW*B`V><)IW$S(&EG)WILL%PI?01Z^'\N(RCX"EN7'+?K^2 +M#<_F:4<)3/"QQI=$YWD=I^Y[ZI"&[ORQ;W]S:M:`XSLC#94!V6WNX")KSQ6G +M6%J84[/U/^#@*^BO^S53UFT*$LT])[# +MC])KZ:8/+`LC^]V&+=Q0@+_M7*Y!EN;/O37$K'EOR!N%IC0?N!(GB$."31^U +MRQKVH]->.Q\O3Q>.0L\U"CNLT.T8+OF/G&)GP`VKYRR+.P?VU[GH2EP+F(G, +MH$LQ8?\M\@%@&FPK!.`CAXU>ZTEO50'@:66V14IXRE=C)Q_5G$74^CCQV<0C +MHB`<4[XRSA7KNNH?E]BC4_HLS2!I_WFW8#S_`OT?@Q'6Z1+V:V!K@?I%>^S: +MQ_%::.%Q!7%IKA`(AO8_?C&L/PY*J4.;-6,-T>S>>:*QM974B#T2\39*3HG? +MV6*6H#B=*ZE].5I@QC,.^X&`Q%J$EMT4H.&G1=OO-QWD*?G:/),OUAO1UNQ. +M?L`?_^D>H\X7!Q4?K<-CC8MKY5RL-3'TH\W]IBUKA0L[^7YVIPH/";=9-DMR +M?;WB-VSXO%;T3G>CK30'N[$Y<\DEK+;.XO^X[+[DM"7-LAD0';>Y_5TI7,Y" +MH''3DM40MLQCF[S!,2#+K2ZQDV +MOI^-J5DA/!5P5RW;&V9.K-#3,`!*=N7.W/C=D*W:>5XK'>19H89BDM@5[^M_ +M$'9JJ;M8$:U%M-]3JLL(V!8=:-Q^(34J3$'1VQ:@5B6'1;6D++7UGKDIKW#L +MR_)1%`V4K:";XO +M[*5X2V!12+Z" +MKC@R>9\XQ?:VS_G7**9SN_;*6"2P2W;A_]:N+3Z2)U6.;+^&?2KD,:MK'A1" +M"\XLXU)9Z'$@@.U?GG8#$PF4;;O^E[(ZBVV<)H@JUSAX[QF=*%D(]/,]P64U +MV'>L?.A+>CQWP1^8(P15JGL=!Y0F(HVEP2V*?[^#+V!+?2QQNAW@RYS%'T9? +MTV/F'"+S^EF8I`-ZOY]EZU*1KIXQU8.3N$!]3*0(%O:!+`@ZY>F3\"^WFR0. +ML85YTI.DP$GS^>&I=DS'HV*`5Y^7LOR!@(9;;1#-$%!5TLEJJTUF\HS#5GA\ +M0U*R]THW$::[^YX*:U4*ZCBPJO(E3>-Q6ICD297ZVC$/X@I3HLE$1Q`41)S$ +M\$"U4US]R'L8%C/-/:%`B1F4OK%]CCQWCP'FE>FS,]=73346?T(ZW(O[EBG4 +MI`OX(LZCL3/,Q&!1Q6HE,FF2@L$Z5ML[%FO,%.64KERF=F`4KHTEWY,Q1P2U +M0UR'"TT([_L;1KS[.\\1FM"J9TQ6/%@UTO=4^ZWC;%HW@8;GE:N+IH.T@S\0 +M85VN?H>,@D=-CI4,TMUR0G-+\&AV0_+7,\8L&4HPSAZ)%L35,_66I%](G"/":!V*H%ORKGG@+SHA)T)RO#@`'!B&ZT2M9=.;D\H8+)WABOC__*,S6IN^S#Q(1@2LV +M&_+^(YD7OO/GD\#4=L<>2=Z2/G(9I9?.6HGMQG""-G5+=MIN"TB_V-K_G)^BB4[=0EO:18"[+[:KC)@#BB+R9S7EF27 +M]&#PP'T1()I*H:S8X#A;Z&;$&D.C9-'P`(9B_Q^5^6["9N6S1(FQ0?<6C][< +MZ-G9N>U0_"DSMU..!H6\2.RR%*_FX*4V)N$.EN=:>%+'$VZ13;HI^D_2CWIZ#X:54C_R\>8G0D']L:$D-/#SUF5)+ +M17O%:R=WGKW`U-)6R">I%)F"99.5TAS2'JI>%<*DW,*(SZ.Q;U.HKR5^O;JW +M@3_@=]2T0"8(6%25NH"WJK@/@O]BUJ:`5&9"G62LXFA6*%\>N%9W&JVF9[(@ +MHEWF:J=TS&J94?FZ09>(%S]Y5>S#6821"&Q7VL;G3Z@DPFC8/[L,G#BFS1U" +MDL'LY[RRR(KS?T1$4VD8IF +M@W%4B1@3WQAN$AI)TSF1XS6AH33QC`>1`0@@*YBY7IL>MW`UC#VZ +M,Y(&'\3Z6R/*P<>8V-AJJHOJWK\VX[P[@@)/_^1(U1?9#,$1#+",_@C`,T/0 +M_A$GR`*U2<9_:'XI75`!P\K-JKH-<-7HV4O\D-VY +M@4&@M/26[#4&S>QE!4:IX'6G01>1?HC>14`"[8#\S]N,L_&$/02B9IUNQ87R +M'U_^+\**;QN(#N6`K'U+,*^R;!:2="^T)0!5>.$]@QS==Z>)-&5A]8U(WZ6G +M:]RK8V#.,WK:#N<^UQ?Z#)$NSPR)DQD1!5>X3Z4QDBW4Z]%8W']:;>(.YB+" +M'D?5^0-0%*.IL&7[_E[WX"$Y(CO>WJ82,]V_;G;:/>EK`'4:. +MLZ[I<#KE=U$J$5BXZT#)T.@?"*9\Z;?C"\6>HGT&VWJ8:'>1.-BD!1[*6^E^ +M7]%T"`A!DY@I%\-&]FYGH:]W,=2$4J94H?[WP +MI`'7R=P$D:0GAOP<1SLPPE'9=J2%BX@<'9NS:^V_+Y%_P`^#L(K1MK5NZ_MI+N)W#S5!G= +MW>H,:P/%P=1"IWJ0#C(M7."Q9CRA$%=]IQZV/E(S^FX*1/X^]1/1.I!L!(0. +M%<7L+^Z.8*_-J%^8QLL;$%W9=(D!*<#N$LPE[-R1#@,C!F*[14>R[(+7A6 +M`FB*=*K'>094V"I[+CDR(O[+*1K0"H^MOONTB`9X38Q1Z.V=<&3]Y#$2-4YN.6E&2K`@NGNV^2Y(YYI!&;%6!J,THDQ8[@\BA +M1EH.$QG$?5.N1K(7^#'XID+T3&@-:/.=%/J..@.$?478^FZ,W##PZU5C=>\- +MDJKZ%\O^-?CA0XS+R4EZD)M6$*OM[*0$2RKL=JIN)L6Q+B47@K(#W*4IZHHD +MQA-W.5,IE8KS(S@U`7)PCA^"R`?HRFPTC-4>@A$PDOP.1&O"?$ESDT.\]Q]X +M(]=5_7TGDA@G2]C:69QLHYJ(?1UC:P+-N=@I(>]3)=`8 +M,_E%ZMOG!_#5;Z!E28F8H;`JLC4,6M\SV-B[X9#DX<.O,,_H#6A4S1(LB6V/ +MQ`1;*1>3=P8A^NP!L\TD+.*@W6WMZ5*FWX[,)V2@7YV!JME"KM')@DR33M&A +M95/.+]%XI8/C!%],-&FI]/Q\_MGW+#:&?\_R);QQ!AD*>% +MP%,,:]'9I/D39-<67MN3;[IUS*6+`?SB8">N+%SZSU%I"HVN2#5@K0OWR[_L +MN].SD.D)+J\4/H#]86+/@"NUD1=8?JI0+.V"]DOMIGUE7]M0"K6%,F2JB'WB +M[[K:JW:QEWRSW,,L([W4UW\@"7C>?A57%#K(#@GXT:%'<@# +M4MAV>`/+E'D*VDKD=Q*XY=,FF2S%H?/^OD6JY-0D.XZ>5GR(+/^T@X4,.8=W +M4\MW5SH0(/]0R0/^*EK!9N'BT-*@KR=S`B^2.1!?]J3"I9Z(?3%&H#-[3\*_ +M.83K$>U3C*%OQZ8Z!ASS +M'/UQRK;4GRT_K^G]^^N*8S&WG,NOU6[IJCG8KRZ2,R4 +M*?MOM+E;\VV*:+FVAWZ=_[>&H%OQ-FFLS[]I=N.8R"NAF%Q*5R,.QV@YQIU1 +M49,U9G@0S',/S6ZF\3ZZO"<7+0FK?!-Z,M$H4O>Y,3CMO<5-IIA@K=6KJZ/,QC#2DOW'7HB#F>VS=] +MONVP0MQ"O5\,F)/(0J(B^>]=3T'[E4E28=Y>P?.3ZD7K6KV!#9=W\!RVP@,Y +MF?%LHQ>9-B`^M1>:*\]@;7(JIT'KH`'CH!9Y%$H9@ZD;-AX:C_Z@P%`)&&9V +M_8==_(T1M^1M18NBR`)^,4R)6A9D-5YP@QN-JVW((V7D"(=U)2I"AI3>[?Y> +MKJ$O\I]4@<38=UNVJ6M03U1S@[V#`Q3W$`17R5Q\A=B8VVA\3I!AXIA/(!TI +MY0YO2,:`993\`N\L1;\VX.0E)Q*T@I]/X`G[R6EVACF#>C":8!/.U0,3CJ3* +M)+]OKJ:_]U&@DJCQ*"IJ@R\;P.6>>.7GAM.3JU(I9!6 +MXFKS2HM.%8R^/#>MN;QC)/#M7.WO2X`4CP/,],2>VTB:.8)";$IC&M&9O:_F +M=2=/_/#'<*(B.8)DEG%B`2FC,\E>XJI::)Q.'H%3CT0?#>F>\=DIH*RO)\?I +ML4\5]%N74Q9!G/1IFRW6 +MQI&(ATMYXA\$_@%76NP3YY>H%"5[W$IJ]-)E7ZT".$`7U%!W!:9^7J58/\)- +M,PHJ98\;NV1@=R95C-TP>@F^?'+GT?_>(9I)XE\*H66F_3*/Y]ES)OMH;7]^ +M]6%*=M/55I;H6(=MM]6&4:*S48$1ZNL!/:C!ZE43Q5!-`N^!#&4:"L>@O\!W +M0/HGCQ<*55`6OMA)*%P,6]C;6[H\[G=AD:C[RE8Y1B,]#3H(*+5X)7\&5*@\ +MA1FR353-126*0'L4AF+C8C__!K+K=(FO'QM"O&MQ_U(,TY@ZK[\X5$X/I4D@ +MH>W1[HEO;2Y.JL;C[2$!->^Q;*(6XBUGCA(`P\K']B*>>'$E$ES=+6^HG;JU +M7;GRSFBGK8X0-\0`[BY7=>\_@G@T,O8S1G3AKA[XX&SB%I +M<)DPJL[`+K"W2R;:OA9#LV=(HR<)@+-3\Q&6D?Q8WF1L>@MQ7M5/$6Y`SX<, +MW#ND]@.!@VDANA:E>5SMYO!L!D;RZ);T&#N<2OMSY92)QL)SRT1I\!V@Z"9^^_$!ST<4?9CLU5457=*EUQ@Q&E3S3GMT:CT +MV4NV_"ELX-UNR4$`=M5SA=%,[7=_T5GDAU(+DK=M.@)Q#\W/8)9'DU(12\\C +MY8Y0-CU)E_Q[4W6U(3G^M%(Y[SHA6GLZ"D*PV.F\,F]LOT,$=3QY7HO5\4,9 +MW5M%#5-2M;'J@RL&5EB@2\%2-)\?E#I35+LR?8V%'2?>!=*_.RUI]_#V"V)5 +MER_X>?EE'/CZQR"K>0L8%FZK=^0"8M5-N4"*3?).&ZASV@->)D:NG$NQKTRZ +MCJGK=SGM?X!T4,-2-1.@HIF;;75!U0Z>?^9`*54;:NH40P"4^0:X!59YTNIL +MS7)6HEF$[/KG:TF+7.9V<]0M%$25HT1NO[]:5#\"TUM)"4/SL#:7718D +MA:'2ZR"KF[%D=];(C_0/&BJQ]D=LY(?RE--[:I^_WD$DD=:`J[>)'@91.EP] +MJ5],*K]]\B"VK"L_G?])U4&R+O&;40(7J8-"`+U8GI.'XI1!(^3VF7['X5J" +MJ$-?M\OG`8:R1GK]^_>T:WGPD:KZ89=H +M8I'IS5':D1M*@N^AZ/W(3PG5IDJ=7Q3B<(VA4\O5OEDY\=:AVVG(T8-Z`EI_ +M>T>5E1@,7?Q9GX&[U(UOLJN5_)QO,EG`1!O+D3$`2;=L"?`%C(P#$8S.'[.PQ'9W'7D7$49(=>,>T]#?J)9L_YU1J:QPERSR0#QTMS/]+)HR +M'-7;C=!SIVV7UX$N!/2C$HN,QR6[_4#5THSF[DIFAX53?SFS*/T'R'@)@@A@ +M>SBI'E)<,.C6\O?OD,PO!][,X(6B=@443$,,A)*7DQ0PVR^]W=3C!*U\MVQ/ +M>^M!J3B@ENU-.$`H![G-*-[([WDQX`:_=60:#*]#U86N'YX4.*-14[^!CUV3H/MLF/8DV4> +M3VI/ASA4)=F^"UJKL`+'@JI[X'47E$BJ!(>7P3V[FX\MPCJLG*G9+0)4@/>P +MMB+JD=*YVY;@?(G:6BS*/[C.35%=,="_PW@MBM#<\09@;L$68$&2^)7S6<'5 +MTL.68;7>;^A8VSD\>,X4LY8IB6D='-Q@O1*N1(MPYH:VELCH[3M*L;J-&TM^ +M;I45-0>,"7R+A2'F&PKG:'QW$=.:;`OX_N45YX$UX[EB*XHL,\=DJVY?("M6 +M3Q^_!["R6`'DXY)2MRC\,>H10PK*T#]YL5 +M@>O@2FN\7A*&0&U]*)U5OH@TZ26@8*G2<8O+"NOW)S^0O1LB@TILN&/Y78U` +M`I-K1D^3L=4<3(M1PU$`KIR2CAF8#@IY@+H2L&@!/KLS/7W\O3D'<)<*>'W4 +M-2&@BFY:W79F84-0Z-,TY;GV;OH@@+F=MX1VZV,4NDD#(75.4Q?=X"+:AB_- +M\[\2GV=0!,BA&/WAPE@H?7/KYRT3%UPX_0C6ZN(XSN@%#?_W +M/@ZXZJ25'8'8BKLN0\$CPQ?M>RUEJY)?YM:*!#9F<675W7[(1"I6OBKL.`8I +MN*26UKN&,J.B:W"?/".8L""S=O/OI$X-[(9@\O^E>`*E5A'F1!5&M+XZ"1&@ +MSCI])9`=2M>&%OENM@NH_$B:8X2"2RZF`,RM=SO6?F,Y0"F]^0V\"Q=;O1^L +MNBG%F&-4QM)R!W89^1-)J]-ZZD',MTRNG.)K_/R4-C15S@UG6M#B<40^S_J1 +M'N]_OH0D'S[1EC4@\H +MTE&A>-BK84M7L=)2OHMWJ%ZG^=A=Q-.,#HEI1M>L!FI"L&$O[Y[/C38B*H;C +MG`&%Q;Z7B41P!'A#.!+S^M(>4/.*,@B +M'.-$EOWBDE&KU%.X!+'*&9AQ.%FN#6*N;1;"4IUDP[Z:FT"9^]65"]*VK&GEH:?::GIE^A7 +M.197L<<=7<0_>FK=ZN>= +M/CGGY%<#]'!?GX48Q;.;%;DNG&-^`#HW!1%?_X&'9U6XM'P%K*8F4?;8&FB+ +M?DC['>MZA2UT/'F6QT,6XU/,%3-S,O'T^LH#5((Y&GK%86?9@\-&3M(>-VSZ +M#/J0&A`/%85=;DD%D$?&2;[XP`H><2+E$=>9P7OI(U[:'_^7X=SH70^OSK&& +M"5F>\F!-)B&!J2G-@Z$;@2,DRXJ&WF4!S(6J'G0U;SNC=_)Z:F`=RB;[R;:1 +MU:Z$@3]]P\]WT\?:X,(;EFQ9`\=Q8TFPI4@OC_E/_P=_`-7>IH<:DOX%59J[ +M/D+[A3I_*V.\`VURZ/\@X%J;3)59"H;/5/6-R>RS#_7BKR=:V`<1>M+4-U/9 +M?JWIO(CDK;+JMHQYK,T_NZ?1)%_*"=/Z%=&*>A$%2A]J9JFLXMO*HEOKON7B +M/%LNUB"]J$P%N+A<=6X(]+7P`JMD;P08L;5MO(-!+LB2V;%\R)UXY8O.ESA3`P=;1@W?L&O6 +M?D=FA\L+S&LD4Z6<@UM?;]Y[="#'_&Q=``.JH55:I'5=G(+BL?Y[4KRFUH;!\OS1PJJ?C123;PA&NI6+]-39 +MRQU:4ADWC*>#^=\-NE,A/+;E!^/$L5U5O(8U1/"WU(/M70#9#RU!1#'=W2"[ +MO#\U%?I:*/%NH.;)TX/'QF4\-@8O?+D8`_@ZD`2V^#&([%7S.:P^2`^72T;@ +M7L+(/EX1<2I]#>#$SF.=^W]$EM_*C)*%-D^208C)>Q2TQ8?_2#B$%,^)R0/` +MW?F''J+!$9K4^DB_%1E$B'3\1I0-&KD2D&N0IT7QT@-M>^55J`5^%#)@>*7( +M@2C3K.CRYLG[,LR!K,[N?C%TQTZ_!:4R)$(OB9SXKME3'KR%1#F!.6E7_9LG +M^.LB\3L*%KFJ$65K=E\NW#_<9U&&SX6G85<7.Y#/?7I^ +M(]JM,G%YT3Y%-$*_QXS'*A65G$JU>";EK?X'`DR%K8'6:^(0LY[IR7G(4 +M;$#C3Z8%!55BIX.`U\(NQJZWCS06LU,ME]$79\V3*?13+G$`G]`E]\W77\MS +M0'%1:P]S@R\JS(.E2WW"N)"CY982ZP_A)0[D:X/,9F%G0C>":_4-Y]U/M1ZN +MI=Q-:\CM/EAW=DZ1D6EL>1RB6_F:]2@Q1.ZI@FJ1`Q<6P!8M<`;O:FMW%X)[7).@G1A`M95@I9`BM/ +M:N(5P06[<'[!W51?GZ^XY45(J#NL;O`LA;^Z%FUA6]IBR8'T+!CB[!QW>P%K +MC&C>@M`V*!G=K@?Z[7['Q`?NYE9"?A6/,,VMT`I#IFI[:>\_7;,9V:?>^3I7 +MX3JT^PC0/M3`&[W8;T&5,RG^'7:TU?:?8U6CWBJ\4U8@!T.5:3U9CN6W32V' +MK0SW-'!U@!MW8#VAOZ+P9,<'A@N@J*'0Q)X?%A)G:E,JR@')0WD,P!P5#@)N#B`)83<3\5-Q9TL8"Y]+BB3]5Z?7Y;2QO`Z5_,7@B9 +MJ8)`$21LZ0N"V$FB*XQ'S#CDIG-*QV)1.FL^E_I/+G`&49QH]DAG8?+DEJ-V +M585V!TM+N;$!R.@M1WU.X^CF2]"&X2(%..V"%%3)ZC6<=5D2A1GQ;L,.2,>" +M5#F($FG,^:%@!?6.5!J/:-(K/M)%C"T$1E^X`.8T%QA+;AEEGP"FV,(_U]V!*N:M_1H,U=$3#-W7E:Y3%_^4?@) +M'MS5O]Q./FW-R3K0DHL@H6NH_1)]:-)9TZXGV0EK +M*IJP,P$CUS":16NR1(?-$CG/OE1'L>E^(G6M_G!F+`5&PV7JCXRN>^@'_RG= +M6UP_.`8_*/WW[C=XU:+O+S#%=57U/1ENY9VF0CN8^X.34LT)NSAPE4>ZP`/% +MGU)Z)IM$9!E=,';GBS-.[!QS'F\'2L/FYC?LFR8 +MUE]CDYZKRTZGOSI?$X#:\I[82 +M99??F>4!.^B@>D;0".DZ)(@<[:#,+\?.&^P16"0%V'Z2$GGUD*^\76&F'I=+ +M@W9`B6AS-03]!R)E+;!CR','%?G'+\+%+UEU5'0!--2%ADH^NEJ1_G_"J,/H +MT()T7LM<4/O_8NX>6(R&`*>[PU:),M2G0"K17"`BEXT?G0POV!]X9$A.M2WH +M5;!-KONJ@Z^!IU>9%0C_JKBFB28NINA/L:'5Q=OER;-M0EG7E%P,LZ36EK8L&22I0 +M>=);\MP.A=ZZ#RYQN)8U2JUD,7R+"+[\I;\H'%\I?]$PZQ#]-!2(,"I[#X4T"3[+'(L0A4"<\E@X@U^,V5F +MVD]]?D<%=:GG3UASE+"076N?ERGVT*)<\1PF/%:_=(8J`033RE/UQGXH+/!L"+P;`S]$U[CDX<9A]TR2DY- +MN.]GM;H0)^?&G0*#Y)R*I#F6V36TNMB`.1-5-/GH+'N]8V6<9K0"UQ]GNM7S +MP,[W)VS'G=`+2AK\CN_\(C +MXC3GYT4%D4\%GT=!.^9^P;3B9#.$2H+XO +M4T&$.#JV,3XE:(M<>`YPH*Z*[64`O%5RG/AB;HA/&RY"HJ/%"G_]R$D.*.6Z +M"A@AB;=BJ.H;L$=A50R_+6Z@_])A.BQ?,88GEZU +M7?T7?I5<(E[=$][!6"BN%/*D8':N6S(2>\R"7X=N<&AD"XPOTEH_ +M$B:;[2':`47@*'F!^=411D5XI:2-XUZ>.SWBXV$]*=X!7DKR*LO(ML_39T7_ +M`0"U$:O^0*J#&_*(K+$*1"#-U[5XM9J6`@531W^."+@E1FP[+_'QBBPR^(^" +MSW?2NL_#+;%_!%';6E]K93HE/UB&+R0D$`J(%(O/)'#VZ&FOCUNC`D] +M`\2SPBH?NK+OE_GIR_ATE^K9/$GFQNM0V.X^5DIF_T-.I$WEO#$F.U*:=@`V +M/_Q=S/:^U0]7)V`3W^!\=?`I`D<"T)TZZ,<3"0">=X/H%Y)/OT1\F`Q6"'V` +MH$$0$.S/["'5>"NI+C9O]8/MCN26HEEJ,/X0[\^EFK'',O]=L!A)T+L,=6KO +M*?N?A:!+6PZ&^?(/B`\[."$&JRHBXO`B6+NG@7!O4_Q?AIJ3K@6>V[-1@H:*!:I7JPJ2H[+U +MR8YL?8*/Z`V[UJ;S3=O%L'@X.-$$AM@(^:K+P<:W?)2=A?Z!_V]&@=_1J::K +MIYF.Z/="S#'7FK,]0IK@[8TGF65$Y:6.X0$>;!*5WA!?7(Z@@GLMH#*O/0A# +M#JQ$QK`"/^H<18SE&@/4XKOP\>UU!YD)0Q.B"ZA1`'+F$(#2]E^U/[<#(H6B +M@]%Z8J^`@HM5'U6T^Y9"9@XIIF+>N!IO!!25"D?$0!>[*[N?/@+3A! +M%;&D:DI*.R`D_S8[PJ+YTD[ZJZ(&(0GS%/'[VQ&)!#CL@1+Q?TYD6I_`-?JS +MXFW7*@"5OAU%ZS7?-&#V'6[0(U1$0>R)_CZ`<+ES9?&Q4HU<@+!W%LJHD)7E +M>DY8NKFQ)C/VG6BWQ@0B\C*P18@H6XB;QI9B,G<1`42@2&#VV(JYBAZ2@V0Y +MN5KWXXO4+789\(/E+C![[U@Q__T&$"`(_G.)6T38L,&D'#VL5`_&QW!@:&U1 +MQCYIYZRFZ#G5[GY.-S[$GF1>VTL_"/$3@%.6/)&;4C`^J+ +MA5]8MS=3C_#?B0NO<5X^S'>C6?)A;7.:_=G&94%!&0]N)@7/KKZ/7&;^X4TT +MP`M`&Z"S^JRG_4JDTRI6`Z5]+&&T.?^2)( +M,$MTC+NP`S#2?;=.2L1R7'A9U6LDRF-!1/]T+3W3S=QE7ESOKFAR"7-(G(8=9AOH-^P_+Y0A,YB:U;__=9W0;+1T +M"20#,(Y"HV+U[Q_94O=%+GZ%37@'L:S+Q!K$#")B_OW2RWSNF'A)M8YK;Q7; +M9J4Z;#?P,L;8#P%N99Y,M*[J4:*]:HNL5Q)A0EP*],!73+4C]X%9VK0-1;3# +M+)>FBHO07J&RH.3C@Q1&J]R-VBU`'#_1W#X^_8UD0::,/15\LT3SE4H'4]X"7Q( +MYSQ0,\H=A3?11R(7%%5NM_">EK6>%0J:`&5O;NZYP'Z[X46W0VPCNH6\)^5ZF!"BWQ7E2PQ<>"$#:"(BR"Y:J?@"*?: +M+X*M#(`WE#[_]7#*Y-X`DBY2GJ'V"EJ0R-_A'[^C8]PL(2J)?90M>&"*\][' +MYNS#J&%98NP73UOAU^C)T=)#$@$U]=":S<&?9V42B<&.`-'_R+=R#ZT@7!`! +MTRN7UW2"F<&%TUD!+S+#:9/!!W48+YB[R;*J\:O6/($F;-_T-H+XD-&7/LN.:J<)^WG2)52F8&-U[8J"#<>Y@NR`-J$'B8 +M^Q8$#?/(6=5A/,+QL$#!3)!3)E),*QG0Q*Q*PYX=L:31\0`ZRWUI^UD(ON5@J%&-@7,LX.D_9+29&%AQ4/F"Y +M8M9HI`RZVQI(5^Q2KD*_0$AA&/Z$CT1YLTX`1'$(6<$.#"KQ,CWV353-V?O3 +M**?=9>PJ"_-="25((E2`&0_U-@_,8*1@K[\C3QK#-=&:]7,=<+XHLQ`8:ELM +M`97$98?5B,_G83$&W(UMQA\Y_3)S"PFBK)_%A!J0'<`PJ%HBRI/"_]6_VAWZ +M"'@]Y.2$$:C`S\3*-'K@)7^E]=\JZUEP/C^7M,?Z34XY^O*H>HE1GZ('L2V4 +M%T#OL!\$_"97B1!`UO_T+M_@9DYX5(IZ.4%6$KWRWDH&(C+1\I9K-@["9YLC +MHN'-@EZ_\7BU8_^?34^1$N$L?.6A]PKYFZ(]^6WO$U:HED/'W>#L.QL_SW?5 +MQ:[D,?6WR>=("9>#;9+!8=9O\VYQ2%&92D.J-8$.,1049-88J7^#:$F2C\I% +MF;GL,/1:%;LX'[:KURH+(D`?,[6"9%P,AE_;6"UN8YM?:Q:LM+/$Z]H/-UD2 +MO5\X"'0.@7[]%83I*V7QH7,B/*;A?(`*0-<+[QM/NHL'&`Q98=T)Z<@9B/-- +MW\I[9-=]#$''A6F^5T5+;Z_)XJ%0I;MMRQD!X!UW-<'2*<[F*\T:=%P:JW@% +M2)Q?-@8;_1^^JW&V$7723:<:)?G_=TO"\/7:XL#HN>HO#^,>-I.Q^EP +M05[+!UG%X.M3$8&VPHNWC5+=!'RH@.@FI5&\ +MZH^J%,R8M[JED$V_M1]?V#%)L(K/"9_$-($JRL!:W_H3)WDO-HD6BX[JTYMH +MIY'1J&ZV22*!OW2^B_4GLK_.X9%:5)#<"7R[PY@01:Z0>\A-_&3) +M6G/62/"W#M"/^TW"V:(GN%ZGG':+F5PI6EA:(,RTHJY7NVOZ<0G9H4+$TIL` +MJUWAT:[7+65''T$SU_S(8:=8$GT.N?HHY5:&F?M7R]G(9)%*1&&*']O1:G-] +M%W5^[:U`RY%?,]D&+W4HS60*+2K6VOE-E_"@6HY"S#@/%?#ND@E^+SN2#7"X +M2ZG?1I.J2\I2))4:$2DW/N=.:4*8[X:[6[`0*F.\+KC"U`?^130<9$I)]CB- +M9G\MJU<5-O='G#C+3H-[&-#MOL(5V1'PO.I[\&AG45^9JOKP]X>\#T`W!D-/55OPU$)7O1NOB+",2M[DF;35%1@%(PA8ZH8Y.% +M.['$7[^&^!"]T^:HAFS=[M@O4_WP%X5E?*4 +MRRK"B5/FN*MBE^3*@9]B@#%FU94(=@E7O#IN5IYN,!6LJ(]-73:4Y%_Z+$GR +MMTLT<<0:F2.C:H^6!3$HZ75V[)I(ATB*U$(K%),$D\R=Q!R7O?;44\TAZ]UA +MUL(>>IY6"&9_$/4=RI!+#AO&*CIYIIW95*U/!A%Y44-5V#!!0G^98/\::$3H +M&>`=Q3Q@^6N!=2`GN?C(5MY9<>6^+]MM*J;S3JD.VZ8M09F4SO?G0X7;#!P# +MK.]W=>0Q$L2/)Z7W(]BBJHT&Q6^7T#N0/Z1`T>-/3G1P;V_`T&:V^`3M\W*4"@]4"Z +M?8?V2^S+]$Q$A#F=^EDLS*P*S!]4$,.\:8ND'9NDHM%F\@5W*=RAU\&YVU,X +M0RTHD+-*HLYNY^F)[HOI^`8@6KW@UR*M>"BW<7[Z'=7VM( +MNBTOL4"U%H.;M76UGU4])(+>\@,@]I'T(C!>!&J5XTFQ@M2IS>WZ7OIQFG<' +M=XH'%-^7AB9C*2=M+K.&;DYR9\M4%`/G@67I86])XGQ:M\N9?A0:$(CBA631 +MJ]73-DD'C$U_$21FOT_7:,X%"K,AY1O;3[8[L)^]$CXU:E1K(VZN?/!4.V'& +M.@G^V:\F[6@H[TXN7K+0IT;.^!73#]$L"G)^-TK<9H?(Z\'N%XCI&TJK\[<8 +M:[%6`Q38[(,G+I84D83B(=MH%Y3@[C``CY7T9O/314(.!MG)H>]H4]B],*2 +M2EJ5;-2C6!9+'1SYU_.GQ?)XE`0K0;'Q8]J#.$*CC@R&]#FODS$VGV0`;2_( +M-LR(TOC8U3M$A%1AP99G*FZG8/6=V;)L8/9\`#Y'H2&QZ37(;9')LLV)_+(Q]0/=>H;DMO*AT +MSG[(/I@G7#D=!#9K=57T7)@V6"9@/?Y3Z>7UO2%UBW_]B:L7DWF.Z)GN7:*H +MXIP!F+RG&Q14LXT+[*I]PJ^!/7;[4'ELZSO.:Z5)9IU^,07,D,3/]%0Q#7B0 +M0%7N&=\HZ,4V4".[/4XHBHHJBHR_5U=?SU0^XU@[=*61R%-:;*)4GN$<[PTH +M1G>PSPFD$)Y2M"3WA7P1((%=1HPG*59$2,Z2!OG)C*47R,N1I:]OEO`Z[!8@ +MK-0(DQ5J%%5[&YC^PKMZ!7%[`U*(3!=J!9N5!P<[)*[8T1&-ZZ]JTY7G-KNU +M;8X+!$@R>.6E&_+R`PO#J'5GLCD&0YPKNR&I"S`X07("]E-B-.T;P#"S +M;IEKY'((>"?;[,RK+O^K.W0X"]R&!5+T0_^[VI]([\[$77\VU1DNLM3S!_`V +M9V`92+3E16=]*1J'_1@8\O6D8!RA-75OZ/6.\Y*Y\[:CG(H.AJ0D=^JM(&MKQ3!W'BN0SS'>I@VRPZ +M&%_G_QP_^IDV4.>C6!$,8620.CHVT +MG3^FJ'\D(@:55VHB`0+\#?K[Q>)(@<4D>?4#A.TP!3B,KSSH:M!ET3Z +M,FR8MVY2]`9J)[`N;4MEZ`K4UVK4&KLTZW.\,[>#;];9ADT"?DS0[9MU();H +ME0+@5\R;+$/!4B@@6[[:_+W1]QQHKS@(KI7'@S96O&+R9_KPE:\017YUWU,L +M[T!\CMQFQIOA1U^'`Q5OZ#[B5;*S?R_,73[5L2171KN;=57DE6^7-V\:(28! +M`J(V#5L1Q<+9/MP&@4_Y[MAC*MEWQ.7K2"\=?_%2H1Y*MVJR2$4373RQ:H8Q +MP"E6L/R\QKK4+?>NVGAG_^+`C!:.`";ZN^7H[3F=X\8%?_".C_)?QZ_EOY,3 +M]O/CKXX)=M7XH_^!OL+Z]KV?8[;"UX`*A=L7<1:+):N"A +M$[^4B9"9318*Y=H`8I#Q`3HAZIFK3`TG7)N7B#`8Q2,4/=[8K&M[!,2V^2`N +MTD1*QMD*L0#)]-Y]Y6K;IA(:OZ]IVH7"6?/8`D,_PH=WDSW=N/#!%^^LU[165V6U5M:3V/U./*86 +MA:UK4Y*\W"OI@VYHYR?O<&`@,%_8@PE9JZR!MB[QQ]AZX4=T14*0BR&LUND^ +MF]'5Q*2!VME=M\,;07/+SQH#D4@OA[]Y?]@(HA*T?2D(/KA&A=XED +M:^1@>^O?-LP3O/!L;T69W"C8`XLFGR2Q9P&^R,7-W8>4"`KY4T`T"9203A<< +M/+,*!-V^-J\Y$+JXX&WU8]2BS@,/`4L3-G,)E!5"Y9;5Z!WRK/%N5H/2'4,,6O^KLST +MBJ8+DK>2:?WG?I)NHR8CM*5XR_:KQY@1@[Z;[DAZ$,_!Q$O<\)#?[!@!AY;] +M-TY;(4(@A\U%J+L]+W_1NPI?$7[R,]"+T*U2U'63*%YX>3]R+@5'W-^W2%V8 +M=ZX!\(D*3=CJL)WA\>4.*A)QUN`-Q9#E.-4HC,/9?H6/XY"LN"4=DEL)`K1X +MCMQ+OT:S0B_4.>AI&@M5)+DV`/*H6^?J(F`5/TA+ZV.G!-[8TPPG!T$V\F:- +M84`7IYSYAIP1W*,?006RZ*4EK_G4-T@A!,'M&:C1;3QWI@HANDZFY@%@-I1A +MB-.#R^-)[TH7AW'LRZA2T%@MS-(L025%4<-=@IB=SL*XR9:(#[=0-#QVK&[@ +M::AQ:$O9,??"#/:P80[0?\``B[[20&19;"+,'-`P*0CEL2(9Z>;LD1W +MFD3&`,1YX<=_:798IEIURPEDK]C&!WL!2AQ6;V>3_V?\'F^[6'\$0-;RYZB_)+#&;%R_A47?6H3YVIS?L'\>7`S&E +M;AB@^*>I@0C7L(%/9B_C2)D`@?S;J%Z`;4F)1/R*7TC-[BPH"^]>NI1V+D49 +M*;>&8HXKMX2LZ4<(6#IYK5=-,Z1^/".-549[S5-J&#.NKS$F%9[AOPC/M@'[ +MLN$_U*?YL;&+-KT +M<:8,QX]III?I$R_C$77*+D:.HX@7E:5X'5*TK?1!4=]^15X"UGO<+Q&73_1& +MN]S>^6]]1@9&3%Z+Q/!+-8?V')<0['B+U@?(S5<,1*C:<5AB*XG_SHDE@]-? +MK1'/H3Q5#/`9F5"'!/U%&"5KA!'AXPP.IT8=BA:S.+FJG\)+0_ +M#\S2%!F'W\?G%PWC(I3V@V95M7*?<*\"81VHV^&PYLS>"&D63KLA3&]IZWJX +MU46!]1Z:V9YMH%+1_Q:1='%(ADX(4!_QIA+*R<"*I2/3QTC\4>SMM/+MAS/. +M\VI$%FR6L(T4C,H;]6R^5X;,#OZ8[R0Q4!,^:Y8=W'-P2LH5P<"T;=9*H8:5 +MQA#RAP<+#C-7MMV_A16VK?V(;66+J$;IJQZ3(95L.9&9C]7[X3\105&1P'J/ +MBF(!HDWSI0PEN$Z'U4+1$=)D\L#:IY>KIC,EQI,!XAK&JZ+^C%A*(O_DA_^Y +M@(Y;%WY4HV+'32+MFMD)GU59[]H^L2SJ(F'YH&SK1LI`=4,VPFT",'?0(T1.JIXM0A3CU<8(^0,] +M,P2TFY2U,%/-'=5"!JCY0>G1MCRXM15Z_V$S3OM18/-2Z128TS9U'S_TGZHK +M^X8R_Q/:4ZHS[X,-T*#Y/_S:89+X*#]ZJ`C&,+A*<%T^U0\6II*]_V#E(`SZ +M\$`PQ"V$ETU0=W$V3>1^TX>P25'U;LGVBO?RK-=0>AR*N+:31#OL>C[,2BP# +M=9+FLC<'ZS7>?N15E/C%]8S3M'!G42*Z_P`RKOPV!736AHI_28-L4Q2T97GP +MLV:,J%DR*23.M=^=?"&"E?@OL8#3]OPZT9-%,LF0%QL6!_8"!;DS=(.`UU7M +M!%=1HL`&Q:G1-N`U5Y1 +MCV@$\B`5]XZ`'5*S,I5768!W1T@6+%E[D",(V)T3A%I;\;@QFG]!/!6Y+:(O +M&B>F<^Q4PJ_1&KG?$$F:6J8F\=,SRR2I.L($/H)Y[&J!=+\_GO^6H;EQ?$P` +M_Q\M<9]X-JJ4J3"F\\D: +M:A,;7G6B1I:`IX#4TQU/DC.)6;$C'L?'+W@?WS^L3CAT_(ZVF,:<27:$3<-/ET=;E>UYM`Z,)1R_23^FJE# +M-?U^!7*FRF]KOY=SPD61U-9SX=.IGX6=%: +M-+*#FX]^P[$.`F&:KJR&?F@@8OC2^Z`FY4V(AOZMY]"(&)*5D14S3&[KX.ON +M.:WOW9^83NBO)&3"[3OIW)"*7%1SVM.!UYT!XGY0KDL1Z@Z;1W!-D'F+5I". +M:V+)`P%R'^J(L*V[SR2\T.3]KDIJ-8GY[G?W3SF")62L8)[2TXTYG[#Q:B2E +M!3M#;MD2`8M7U\YT=#00[IZ$:N9*)+J+KYOH"IK6FZXO4O&A@284TB23^HUY +M469<_4]2@J[&Y(06_($R\&T)Z1PEXU@I#YK'O:EPO@3K$H+E +M8(R<2W+@,3REP0TXPW3%5-UA,;[M^?]6'[!S7'B2`+"F!QBN^(H1&3Z@^($Z +M@M?+?N]0:-#A"/;]+6J"W`<=R%><,3-Q0-S;<.A,(!9+=&?RX+G5\5/1%2VE +M\NG^X/MUU"<'IJ?".?+M\S4N(,O49%]7C$I"0OB))@(A+23]2Z7X2BNR%(;T +M?[P_?>)G`+3[R7-=A?^@`6GEFU5L.4A;GT_7!45GUP4X^Q-SP#(>8UN&V8?: +MC4!93AYTPV!HHP"-W6U5?9:G?HS67O/F65WIB,_!;^6=+(LVHZ1.?4$#US1' +MG-?=C*#D(UOJTIA=!OPTD\[T6D6JMCNJA&)Y4\QYGE8[$)E59*D6S75X!V4Z]P&)C?4_T^L`#P17=K@$[=SFY0B#U8R?L`7PMS"[7I:,@F[J,/&KX< +M.4_)?!,*[BR]3DKW:$EVH[D)L6,#END\CI.!`>CX-B(?3'>,;.PFFGSZC&<^ +MT3\_5BLHN.2"XRTO("GK?Y[OZ>)V4O$"QJ7'G"`Y:A73-#IV;U00Q%R=FM7; +ML7:^[OKL3%#SGH'&@#;S5)+JO%Y:LW)&HL8YV7%&-?#_D5[//_6"S2,HMJZR^3549AOQ,4C0DR'S@2]/G+\\;[NY9%U^0.1 +M9]LE4:!U'Y?R7H6(9)-W',+G*N%:&:>JB+K8=.0Y6+8-KDI;Q%^5YQBBI=24 +M0[!XY(@[HVH70ZX149X"TRA?EW/K5!S//=K;;I7M +M\N\.%7!IILB/8HVQ0['*_M1^L5XM$`!$I[`\`RGMY@UFR$K>H][J&)]A_Q&5 +MQS^G<\-$/S80W:&9R20>S6$W#X7_P-5!EH;`J384G&W8`*`]")ZH@-D_LZRB +M>VR;Q#I+;"YH6\YAIX`K[/8XHR^&DC1501WA_;((P=6MCD;&9)&?I&LNM:/] +MAO%HR.N)@)ZH*8"`(B\F&_(PYEWATMV)&1[OV+'WM:U6E$NH2@=IB+M#V#QU +M)!U^?A.>,D@5P,)89!G'F?[`%XV+T1*W<&CECZ1[+38?9_P9498@EG\$2*%7 +M(Q53J_AW&XY8)ISR/W0PQ`5'^)Z\T0D8:GS)WCN=9\6\R#XKA@R?Q=,_I63%G +M>EN^*?FZ1B:S&9Z`@#ZF?4\E\K/*Y@Z2.@?:J!M_+7MRH'$%>"-(QS(%YJ]6 +MTW-`@ST$ZF=R5`+WL`2YBE[!Q2-9 +MT+Z5F8+_,UC=8F`*8<7%$`F@.0D4!0@UL5`;&F&)NOWZNM"R."058X7Q7N%*?G^@4N-^)B,OSSR=_>Q +M]VS]PSR:VR.TW +ME2DV7-J(;QXX*X(H4_OVA0<)[H=*]7`*.J9`W+E("P\<,H".L@:KGP`=Q"5` +MNRN\TF64)#Q+MVAK;R7`32X%ESFIS49XMSPWNZQ_OG,5 +MP8WIYP3AMUD@2/";UR_<&Y5%?$*+F)!,\2JJ:1#Q\?8H0U03\:/_5$]X5@$' +M0^HFAD#FO:C'(!+$)_$LUQ4J+_7*D]B1;C"]E?R[F\E7*##"5W'15=]\H +MGONV(.S'3EEK]L]IU-&"B,-^F9YY/DG^>-N]9)1`X9WN;Q8X!XV)`W'4X!E* +M'EG-(T*<7*[!:=SI,07?A")[5YF0D."`-A%7GY+]C#;?EMD%DH:OZ183-=?2 +M9ZR9I\GI^21B[RMEFRQ1W*V@EP&#JW>Z\`OA(F>+P\;5;MP/].,2H"+2".YS +MWNN3#?MK-Q1(F^E++HHQM/-Z4B8=5W9=H#`1D!E/YO(B^+1^,H@ZI8@B`C2E +M9ZD`<>=LD[`.+>+5V,0CA8LI)AD60UJQ%D9))O=6P$)4?7BXJM2D,Z84+ZY3 +MU%RJ+W!M0M4NX(1L8^NJ`3**;G+3HI;U?S@8#KGW$>"IERLB&2U)W`*5[^`# +M(,_0;Z2"8>;.]GR:#6,&;@>@=6S[`X+(K?=%@8B^A'NU4PA,<[KH2KW;!%Q,ZM!,@SHUL@@&1.B +MY<(SWPM +MZ/<@8#;4K\1FK3],K/J[1T&J9L_[N0?%HVLP"U6PQ(@YQ\'\E=[RM?W`BVQ7 +MD[S?8)A^D;C$T3@X^B%?`*>_&.`^@$=@V9#G-J"/,Y=%:E]NN=%`!O'`G'\ZY3UD%AEWN_-C9^:GGU?_<2,'_;FYF2O2<+3& +M,'@4HX+5WVA%:#.6W;RE5/`7P8!+=:",]^AU/-O@$?NA*B4!'4P+$UC0XL'K%18`9M\M20D(>N/XJ, +ME_"AG@D;LF-P!Y`@(A4BQ!;FB]D"<_4(Y0.[SY%)^]KIW5`;_5DA!Z257!8)"J+YZV4W]O.T_4PT4B'Q,<_K +MZLFS'??B'0N/D`HSIB73%=\70PZ4%GE;_%)HZ`9ZTF4Y@&NE[.*X,\$*2JQ. +M8RW+?W$@7]7?_N[]S.0`&A;5T#VW53QOWB"#7S;?=_6_6QK +M:Y<^J195)?J1UH97RB,PLQ"3O[XP9!NKF$Q_/'`N`-U5I`%6Y,01%/WW0@87`1 +MO$;/Y//((11%.Q]W67UF&+B-6 +MVJVDY_HRL_JCD))1F!O"4LPALU%I7`^$/;(7LYX!4)-]R*ADL*O2$:SZNTCL +M3>HYYFF-$JY:2V\EXGQ;A09X!#G08F2Q4'G\R+2VZ5+N5=FHU#U+UXBC6E@_-+E(?TL=OWEHI_2XC\?JQUL2.G05)T.BX>J9 +MXFD0#!IAI3Z?`@#?XJ8^&ZT>J7R&@*=\6`DS'L!?OLL"[N9ED-1(._=4/>^@ +M7[68^/S7S,E(KH_<&30G+*>97%*3(H,W@IUYY7O0V$8P`_ZL8ZDV.A380X#M +MP&8E*%M<,6/GGYFQ!AY95880>[MIXFE80D[J'"7F=S%`.FON>L-PQLS_:= +MP9+LH5#MC(WH5\RD38F(AEDX*3CN0_@J:PC^(N(4H_<\'>&OO;>#YA1Z;0D)[TW1J[)=')L^>[9T7?/CY^>- +M:.FP8-;D*!3V+QM;6BC?V6_#=.S83B*C!BVK/F4EI1A_.4-1'I'DX_#FEB![ +MM4"/+7PW7-7MKIH0A,7[O!G/^!YC_@ZF9$OGK"CRTSR+8)M-_8>:A"Y]_IE> +MG*-^LVB6FFFWXT^=:QN*5ELU<4>1LWD&CD/5>8AWL:BY><3O2GR+XOO^?&E&[JQU]&18JQ[O,ZR$#=:]+:-L'+AYVP694.U53>7,OFR +M#2AN>3W>SS:7SJ(:748=_!-/C^!.="6^8OKT,KIHF07'(_;P!/LVR?/Y?YB/ +M4O`;3<2/G98&1RYZNE<+)`X7VE/X,LF&WQGOW`;UDMM(-M$TU=SM/JT%')[! +M;PW8"J2LJ@S]_`DCH,I+:X8HEXRVG>^].QD3:SWK*#C46>5:!BN\EA@EC?RE +MH^)N)DRGX^'YX3KL;DE(S(MS:,5P?`2C[5`'`('`.\]F9YYPD#+-/C/\(G`& +M7"%*[!>/KX#RUOO(\A6W9^HXB*E"X?0$T/!W\1-DU#_Z=LCO?$8*!B@'?,82 +M@SA+H,(9L!;E:1>CFUS#09*^`MO@'GH;@B6N7^KS +M`/5AD,6PT+7O=P`H%/,LCX#`XG,",Q'E3HH"1A(6G[@./=9JU,PVRJ*AJ@P[ +M*#=L0K22I-;BL8/V:[F)U>Y^)@,L6E<%9`2]EJJIG\Y'.D9[,[]AE83+Y:A^ +MA0T+1V8`&O]%-5MPAR-Z`!LC_+7$/1#I+>]6L.K^FHWDZOU+1DOEQS.H(/(; +M/+N68.JR_R\>^(&>>I9XC4#(2A"[ZO.C6K<8>E\N(T;L_+>N&0[U,7>!SO*/ +M(YNT0QW]X'/`R_(=6U8%B1]*1@4R=:Y*]9E387G0E_K9)'-N^#;%<:YR[$5Z +M79@J5YA4V4?Q)HV96H?6TY!P8:G+RCB41^GY?:7>W=Z:IE\`I@CWZC>I/7X< +MYL.:PUUS+J&';.7<(\3ZDC.97MYKU^`[!U;&@@:'E]>LM5`D<-8' +MZ)MJ).-)9HS<38>"GR8JO&[=BK___/+FYN_QTM!C>8J-^@X$HX>\NHJ&JFNM +MLLZZ@[Q)K;D)4.2,]N&H$^>Z61OL?452\-7G$1UG/%XQ"@!PZI0XL(,:I1<4 +MI+-1""NU94=:8?X@)F%<_*]#E[CC+U`H!BP$)A&+V]^D&E.4!:*S,+P";X*1#"ZM'VGW*>H8M!%MF2GN18? +M0B,;QEXT`96E@1=#VA;`;,,2J2*-YHW-O"C(_>?B2&9@,WUIK164@/LHTX9Z +MA_5$NVN3=33V@R[O[;+7O_EXHJ!HM*`V%V#J7BXR\_]"W7CK9O_E(Z%LA*^,ON41T\%W(]FIJDOGG`D\`]08Y7IN],(NICT-S&A;=#)@*KJX +M(NC6=&J2H*&7[U;#TQUY%?7(O)W-M$CAJ8U,H>5)`BL'5'I8\=^Q16S/OK0Q +M-GJCRAR')%N5R`EZ@NR\-+X_LC@1\"PV[#:-+OT>CTK$/B]/*)=DC>,R):1[U3S$:N:FO&? +M"\L,!45/N9V-Q<3TH-N2959\0)R0_[NQ1R!9/FYW$QQRNOHTJV+OR:TCFV+U +M`7N[&$JAS>FNI"`SN(IA^\0V89Q<'M97W:D9X(5RS/`2_1DSSB,@,W]]#,>2 +M#=V&[3YI[XC[T/F&R_]9\NJ':K![7[<7J;/A,SAR/1I@6,L&9&4]HD!E@-?; +M1'MX-GD_Y4AY=G,N'=?JQY!-$P`3..B@E_TR%S\N5SQY"PRPK,B**G(\CW._ +MD^)`$F.+,[8(X)/?YE"U#<]#+S]B5!AP%$X=)D\KO(VK\4$7W.[B+[`Y?4/] +M;/PA''4U`+2#J:MV*Z9SI[@I'"G,?_GH.^C&*=MZ56#L=R"8>@&;Z;FEI!GB +MG.'X`VK;?-@F(L/\;6YLLO3_5A@X>[=M^;,Z0)S/%E,YWVF@@YA.27`T,,-` +M]Z:`STB,6P`_\"B;4(Z066%_((S(DR6DMAJT`KW+J>"Y0N-A6VENSZ>=DPP2 +M@W-KY;_M'V$W';.%-MPD;\DJ>=T(&5KMOA;Y[0F+,#)XV^61'1:>&F!HI#$L +M_(K`1XZN+?:&:$<`3;4[G$4,+'>"`J7T3]!B9(SC=5\[`[:E2VA4]XGB\1G; +MDA^:7J(KD]B*UMW]G^T')W.Z@V$Y#E27:0]J4T6C0(%WW,V[:3_O'05DA&M\ +MF7W[V.+)AZL*O[^-&=9A&E81+@=<*O;KL_SU2H>?@8].-Z5GB?YBR5%0CEJX9V)T$$HYL$*?^S6K19 +M$',D_'2*R!M&0MW37CP"W\9)T'C!>3G;([5K^ZW`R2@@!LB2K7G'@-FF^^#%51>!`!FN!CJIP_K1#O4;7=RS:7WMHX<^@%!&ZA@!Q//E0Q +MD2;G$!_/X1H"%"<-L)N#5`SZN*CAR6RW`5ND;.#V/Y6IS?)@_?C`P\/)W^&P +MTMK-;\`O:%P45W>8;+'U,AW_(TG?5:.<+_MZ4)%I(Y[INFAI/NA*M'R`+9P'"L7[PJVZWGD.85ETO1 +M#<9HA!E)D\_0+*[=;ZQ-U3Q$G<(B5B^O63]#O?),2'&#%RT;8W1305:?Q&UK +M[V1,*_]OD"6^;XVOI-;&I(8(A''>&,Z.B=_&:E+I81?U_7*^@Y[A+B?7A6-+ +M"\VY"_>""(-1!K^GX)L43^]76V>322/!GR9:=Y\?O9V`ZWFXL6 +MH)/G/_/#TJ7ZF.?M58YCE4UON%2I82P9'T#YP.*4UP#$'J,^'M.KIDQSNUET +M@$%O[/4_]?Y3X15J;_FZ`M5L"B?J:$?<];=1:.N#^ +MU2IA@PDO/XJA<]SI?W$DQF=]KZ>JUP[G[>J_O$Q_JVCS/1'E[%[O?#[5SD9' +M0KZ;`$5OW]SS+X_DRH8)UC13\RYH7-UKZ1HVX%*'Y6_O+PHO^-6%+]S6N)[3 +M=M3'N.:6SH830M\#RUJ?_,U+X>#'O2$K5`K'1[79XE>8N9)?Y$(P2)OFIM+0 +M%0+((P7T5#CG`4^\G[+,:*@`">C4\?GORGV +M7(_"6![)JB3->O!G%([B/.+]]8E/YA8L*"O*<.]'O+8!L4[.X=\>PY=XE +MZ(C+V$F!>-_,O00Y\*S1QGOE7(&&$B]T6PN(F74YS3X`DO+Q&9)5$3*@Q3\ +MT4(T#)&J+L&*L/<_O;VC;?LX>UHQSSE^DI!W%_33;.5-YE!6+(U5.M5G;[!R +M`J:?!C5[NN[)Q&Z+/+(4='-_T<->``[T@OZ,S#@[9_-UE<#=C=#[K]:5S=D]>[%5Y.-CUXX"CU+GFA,N!+]O63B4IW'MUT)6TKJ32B +M_V(01EOU$#07UX32-)60:0IT:-9>&7M-`187B?;CY254N3HR(A$)`,)J\=6\ +M^-)0TA(?32--G6=:Z(/1.?2O[0G[9"SD'ARXWW_W07`Y8QG]7_LX1A&,.N; +MZ.KX..[_"[,[!5P)RECE#M3Z!&OT2YU>H!DQNO-332L0P$F?KHD5],74H4V4 +MBQG),`8O>CDBL@UH5/RG[V?Z*P!H]7KO+T.#LYWHC@)$BQU]<6>AZ@Y!L+,^?%M7%$3 +M#TE."T(RFY@+02YV`!G/(:`7!J6EHQ"'U0^5&=0XR_G#,H17=+E85\BX_U#5 +M:8/6#O,F/5]\'^COU@6'$N'-N:W8I6&M_7=FYO_N84K=*YSA1MDUF?Q,:]A`G1I-,R)RA0L!8%54/_Y"4RV+_LZ9%"Q-4D`B +MUE4SQ^*#08SD8@9IGI>+-!"4G3 +M?(=;7X:NF746S+FY_\AR*HXO4*L*WD(&V8/U+)$Y\C822DBBXCYO&L1\-S7I +M$[(THX30)04E6,S(5F17_>.>M)&0?-C&6&T:(3=L)[-;I-,\T:&>O0.E6`@3 +M-6=I'S]?A)8`?T-S`Q5&Y'=C;+/[O;OW+,1/'12Q\#.'Q2#$E*RG@=A/+-4GG-%0'_)6>!+ +M*E>-*=+>3_VN@&;YS5T'+='[_G")^$F#]/2]/4JDIG!?*1`\RYDQ;P=;#U67_2IU\_G="S7U(0CK`S6<@SJI[+G6[YB^=*A_"@C$<0-#;81W!.>?W +M9RJU78D,6`K@G>VV\AOT]\*;AZ[@E^DO3GI]CR\L`*RT1>0:!%HVB%45=3O$ +MPV&D;3Z"QG7X@3S/3]ZN@_1%57"U`9IHN*UZC-+">_G7K/DM&CQL\YUR42D$ +M_6E,#8@&O&3AQ'N/@S6`'\43=M#K>:Z[&%A5X@B\'_EK5$6R_"\J"L&F6GML,RN4/I6$EQ"W^=V7>9 +M"!142"+3V&T#-WQP"*`^E^1?..W>M'4)[5F(.X)]59JP67Y*[I'N>Y:B" +MR['%GF=*]Y]V)I>!(1+?"A49/&V`YJ4L()^KCST!'UMJJ]WP@@YU&QK'CV=; +MKYO0]GEP.K2Y3.!2/!&6/-(&`XNX@.PI_7"71-18PG1]9&]'@;Q$=[<>GO[(/F3J"Y_F1WP*@%6(B+[&%W2JA3'_;> +M5\*;&`Y-F`1Q)=[)G`F<08[9@O`3I2>1#DU^#\&2EMO#7YE_E3$<6@ZM>H&7 +MS[J2Z`-:>#-_X9#L9JID0,:)1>_1,5\FM4Y&S_U?7L66T#EQ;W:N'AWL`GW_ +M&KCU=--ULM^);^.+^' +MB];:T:3L6],]+SS/:/G@F>_EY!0_URMR$_2G&^4_QF+\?(=_C>>4"3R/\,Q/_;17(4ZXXUHJCD^LW9/]T&?9(?F +MH[!>5\>V1P9HXIMROX7->VBEE3T%9;I'F4^G***GQOTKC)O1.K_.R$]R0C87 +M2*HB/G)*&2__!*!TZF>9/\#S.=68K"T6U_U82GF'5'TQP;M8OP*7D"13@'NC +M^W@]LTSG\DO:%`R2XWLOOY">8)05VSLWI'[<:XUZ$EQ<`D[L2<;+%5NY&L#A +MN79Q$1<3,NU`.5&5M3H=;<\+@GO'B.Z`#&?" +M".KB,-SR?UN/(UOGN-.7%2,E9Q\>P>:`W"[0"(NG@/DQ%`CA]RA' +MVS%O&=$V/X/=M]@LL)//SU=)ZX`,9C[LM!J_]%$+&R36 +M&)I:9?IEKMU.2RTLV&*BY<2&#UML@UH2#VSE+Z42?6Y,Z$BDG4^Q5N#TWBU* +M0"]0<$)7*[E$)N$OY-RGH$@&[OI+RGF74;C,$@5?!D8V8FPHUDI3%Q&JM1AY$0&[XG5%QWU%44!Y +M!>\OJ\A-PXJK'9,SK':UVYD^7A:580':#!^BQ.'R`<;7I^BZ]ZF(Q9AO$XWR +MDVG&8+37IV=$A-<-LO61?;DR?QX)W_M@F?LL6?$VWYF'@_LX[7<=U9D.(ZI0 +M#^F,!U+GH)TY"XZ2[1Y/@M4+VA]C>JK0/-1F@$KME&F`TSLL[\P$LHL(L`EV +M_LKN7(W^JPL+GPL@DD/6XUN9$4![.BS-($"^%5;@;E?'_[\IF:2#U4ZY&?QJ +M+YH%@EP;V2IT6Z1/Y&@0-E,'5\-6`^;0M#]BU3PCO9@=21$,1XQP=B944CX; +MMM?3_QNU)"H^6<[.XNVRK3Q[GILV1'NO6X]M&^)9,+3D8.W3+`9`ZRAR*K,E +M?_UZ$3[5.;.WAS]RKTWN!@_X7CO'421.6)D$:2W1IN +M4RLT"5H-LKP:?9\9*":YI7>E)(DT'37XITW"LNRLW-[P+HISADX +ME$GN2;\^$,1C<+L%".(4J*J8XEG$"IG_%1!:!<^+2T7SS5V&7##&$.QU6Q(* +MK]<<\L5T["NXQ06/8@PTO@1:)^\H4,!E+=]HH"9DU$"5-D$XP!!BM=%LI+@"]@YA +MV0RW]@GD2&81LBZN-1AH<=*OXRN +M"R-9U\XT.A7TGEPKR)-L?OJ$R4SWT;MQL:<>$.1[[`)UVP69-BL +MQZ@5*-`JWVB8Z'LR(2G0'*]FAJ&5B,G7K0#:D;8QD^>BZ!M]VRN--V[RHD+Q +MG@'8[*V&J:!2P59TP)%GSM/D0YS<]$[5&YN&\@CSE:DX0(K)W@0&>4@XA$^%H@.XQWV3/R0G]K[7&@N=E%-8V[N1Y?NC,E[B7,IN!ID=-Z/LTBBTFK +MZ/]=#%""BZ@<[WJPO-!RU17(V0'-SL\XB#PXIDPDAKH5_B;A[P%3+6+-5\+^.\: +M^/H%%$"^V"6\LL:8CU[2$CT:F(HK61W;_R\.O-Z`$_SFPU<55TBNWE(P"$T\ +M6I*F/7@00L6JOJ(1A@*0T%!6"GFCO'>BGPX.=XATY"4HVI-T/RII0E`<^;19 +M*VRP]#3Z:;[#SG/L1%;QG8MD0(2ZC!\,&;P]\ +M;Q43+J7K?\:'OY.NC37K/`LP.]/2RVMGKV^8B`#661P'YKI(B*OU,M3-`*&W +MB5$_KEN/T9ET>-QY[\'\I;&!\LIGA2F,=*\]KZ"W!.'S1[RV$,2>IO=J"*6B +M!O!:*HG@39/KBL]ULKTZTX1;`B=*Z13")9NI2&&M[6GB.H+FT(S?*F'!!C&NQ@=W<8F;[!?=?TW,)EL8L;CX+6;BL1G9)P0L0-ZQNWXRC0 +M)IOUCS?7:"N-A0HFIA+2S>:#;6B*5M@*MSO_G%-8U^K\4OI,E_.3Y'O;@7 +MWUC>>G3?P6T(H':(L5W:/6E=4/<;23H:G1$,9,4RO4U%@3YB%M[_= +M/K.W62IXW-BVC=U%R.[B5"8>'A1#BN=.;-W:H-,?@(BJA]:K%&#^&^2:-RLH +M%_R/,1`/BC0PC+B_Z&=%AIS]MC/^^/"B6@&/Z#MBB?I8%XA?.-'W??D/3\:/ +MC.QL%DS`F^E*"!520UK_!AJ8SA7K0#_DZE8PXN9[_#P:M`,S6.>+VVF>Q56Y +M$H).FC9R2/^QLQ57AQE:U@0:?\:>[@=8U`G0?^?UK8[QE@47<1^0]6`S(Z[1 +M"2H^RNU*76@1PT:IG6YD.<&5VGFIM6H8KB?I=#72JU-K=-R.LX;)T%4S%?Q& +MB7>XKI?4OQA!DK?W5<-N2`NZ]7W3OC\R'64RZY7='SX?2F2=`4Y9Z7XE8;-V +M>W`0[_Q67Z9.4Z(T5J_+WO6R7&AV@X<]1`X()'_)J'BMS4G]'SO!22>'0:<, +M+@#27BI+]/RI>[5*$"UQ:D+@G.OUGS#-KB7/=TWX!$!BW68H>-/ZL.T@+)4EXEWC5$'F^_E;L`_:%'S59:GQ:`-B%:_WGNG2 +M,)ZYFM^RAXYS\>V$(HLH5()%7<,"NV^`OW1DW0/\`53+S,$@H/XDTZL=@\?]R[%:9ZO!H%MZ1S')A+`%7V'S0)ME;I]) +MW*+G`X6V>>>M-@1*V@,^WLWE=>6A(VZ-,[\I2E-_3H&)+9BJW\^*9VT+4?8Z7#:1,2LC;1["U`YL +M2A*-KYLR!ZU\+I%;5:[GXF;=&E9 +M5V]*^*1[AR<5A^9(:DP<<@$6'?+T%G!JM(N`@M;X6%:#JN_7`F@\Q*[!6YO^ +M)B`A(F6#;7HB04QT8V8NQGIU.^&=WRV]1K63$]_3%$V5XE[U,GMJ*[FB53(; +M1K?]=G&%#.K&'Q\WK_XT3!5FF[#]*=JED2Z$4BJ\AG`Y(7Q3-^;*B1;=IX?V +M?U/^HU]^-N&'J*W_$_:Q+@B=K(`9(^XK-Z`]@1;'$Q(I*:=^GL=#$4#!/?K94)Y1A<%_P\1C-,S24YX/Y@C-@QI@ +M`EQ*I&8[$=ICJ#D!X7+)FN]Q6Z"R!YA,Z.D/AI!X\BYKBAX1,`Y82=//8E +M1;&Q.\2^V6D71THF.59`N^D[0H]),7*Y)P/ZCXS0$LI'MYLT&!81M\&83:/: +MQU%30:+NF?"0$H#T\LY]49=&PGYV>ETT-,W3ZA/(D0$T8JQX(*D'=7>0")^@ +MQSD]:./7O)O8IVY!'_""1U#`\/7Z_:%+Y&"=.]6(34E+2&VO(D#/]-CJK&[4 +MW).;98U&)+LJM/5PE-%?6_LF[,`>NL&X;?SXQ/::MT.8Z5:#JF$A8@>#SX28 +M%<&L11SFE\V;8*N(5&P\0*!JVT+.JBB3MG/0!]G!X3I)VR^:/1C0O#F[O#IR +M03W(A3=Y.S;A_[+;,;#M/D%4%02:84:#;,#P=]?K@HT.9ZG9G\3+K#!&:',W +MQN:,,T]FJTF6N+$1Y$OB/'8U`ND:8_P?JS)Y(" +M/D1/[HP\3X"O#?PV*YS&S+8*]2N%0\$^NV;Y/;BHL1"55,C[^Q*/%/N^'?J/ +M='4DMM.\&%:I_1PY7M"&+JYI&*"B2!`HL%$&,"?,%T8E;L8>$,^XZ?RL>%=: +MT$$:X+G9BMKN*?=U_P83CYM/2;TT#]SC1*\C8&&,1*=!B1OY;6LDJRY(R_T> +MTQ(R/`.Z<'5.HRINXSU<3TJ+(#O2]7,0P'=,.#>4U610]S$"51@/DKREJ+(+ +M48W8OE<"%%R]E(4H3BVH/=7,*4T7:H"GAS74B626F77:3#`*6D,E*,3S9D`GY78%ABME<1')-X +M.#MB'@=&F!\6$1S204$/[%Q[G3HI)FBD(,@[.!UYKFE]]=XX^NT1.JJS%V]G8@R-Z&/UC$C>3 +MP=*&M2HPBKS1$101S:N44N[:X+&89`.^>KL=EJ"=%./[3'PX0UI[E\5Y;TC:*GJ;QD1W?W>Z(JH[=KIE +M)PSM"=C"^/)-&C\E.;P[N,(L"YP6C1A4]"OMHBM)S*]RHH'5%>CY#1"RM?LA +MJ82HSES@"9)B$W[&'=ZQ27>R +MF"%EC0TSA="FR$;-SG9U>Z,XTTR8*D9,/0E??=CU-B8#>E;BBC2:-IA=,CN/ +M\S'];,R"S>(V\Y0;)-P!^JK@[N>D<-)*BDS47Q'+;T$Z@AKRZX8>203DHAP%ES$[3ZC3: +M=DFEQECJ"6M2#:\2R]6S(;@74:V]AS2<>`Q'\#+ON3U2J30`X8IP]N<0J:!J +M6\D)U[O80.HN,W_"UK(#I#I-."FH0PQ^G/?\R^H:RP%#S=>):8'VHA!>IY^8 +M/SX?L+XQR>S"R#VDF)M/R!^/.X&`(@9BFP*=CM33N%EH\5R:?7'S7\C;?U*7:M6M3J@9=:8BD&S7;H/UU@F`BO737*3@ +M.TQBIP*]&EC\[UCOO9=Z[#[P-<;_G8'RU:)@#1%]#Z+U\?].V8^BV:$;9FFU +M8!DP"O\,.?VI0W%N$OV.>S-[VAI'L&RQL(C,X*:I`Q>\(?ZL[]O]`06E +MHR$.B;)%>_;.2.BK>><%I3G.H9.?@"0K?%NIS>M^JV]1O0I6P_"ZNK!8-6LI<))*&Y@6)+'_XO +M29WQ4^*.04V@ZMM3"&>[S";U?G-V\56`6SW6%V=5Z2(`A@][E`AZU:W'H$#? +M:Q>N[AN_1]H/:$PU[IZ9S7J#(S3N8C)D'(1`GW9)F_W8`;:J@@MM +MT03.?X5KV)4A3^1@\COUXR_/*7'K7B!N +MG(?>W&N&P(0:GE$,K!S5IFJSK*2O3P+O?3;KU9021^+<>!C2ALH!Q=@I&"7. +MZ$\Y:2.FZH04P;M=>STDA?=!]!5@2!'*M(PDI^,-6EM&M+.W4MXXCM`NE@6[ +MK#TYEO%G0':Z4=]IK+[+K`^>W='^)3@(!RBO^59XF-:'#666^R&W,U<\9WI9 +M;P94`#0_T$CR'\'-H_E'EFB\82TMW;.C&O@W>2KFP^\05,4R$L-??2IALF*- +M$TO@,E`QV5)J![.K@VZ-W*)F>.,]EWJ3W,9(GHRUZ:58"2(`%MBF'(YN5DM& +M;O9Q[?>@GF856:ED.ME=<[!B=2->C>!DT!$1B[$CFF$N"L#&/PM2+SEV/%6K +M1:/VP;AD2&ZM-`E);UX14HPJIB(P9CROZX>N?/;1P%)ZTU/N4U&7B9-^D*F5 +MIC#<]-9]C+`WU0:0BTM%%"04L$`"KIX!1!&W--FM:Y:0X%&9\RBZ)YD?A7UQ +M?\C7K[*=P&,@)_\J5'N1M)N:8F?WE^+`0Q)$?VHJ,6PS(4-LD05IX.[J@XEA +M-M.UCH*B)\0*"TGYE$HD4%3VJ!5]J#)=]UT\L9N=6=R__7K"L17TY$8KDG]= +MSF@>T+.3>:3Q=SX%FT(#000&VQ9YVX*R/*Q9X84`)X>I&3_945$@S5B9..T+ +MF=`H'O+6$G;QS2+*HKIXRQ`PO]G!J-+8(09*GMZRL3.`O:_THP8N^]@?2=&0#"ID4--D([ +MM18J`CV,1D+ZM##+N?U-:72FNS">GAW?7NP\4;@W_4^&A1FREC.I;^NA'-TO!G#@("-]6816T@2/(-QR36*302\E4$,3"*!NX:X,X6 +MLY*&`3XP4@3?H+C,J",X[OD+HE<"8O+4R/#._K%I'DL:B-!P`SZL?KR7O:&J[1CLG@[ +MUYE1/UB`?I[2JC'3`6(/'>V^WK&CM8S:>]C.:&Q$HA(J(":J7#0\%;9YM&6' +M&IX)7"=7XZAR%*.%TT4E1^3M!]:Q'Y!'>RL``-;P/Y)B`J8%]U`<+2NM6IL` +MQ51F%6IO.J3?P)'@5?'.<\U[(Z9:#>4"-?89O +MX8@1#:.WK0H,HIL_P`B52A!R+:/2',JT'EW/GM\21+@S>$E0F^@+]+ +M`%=E)S`9ZLU.8V7YE.V1"]UUX.69NYB!OE+U*?0R=MQH%W&^R&"EC-*1[=W$ +MR%2S?D*>YG3R@C`Y5AA>_9=&X@.H,7YI31TYI%#!TBG' +M9'4]70*CYTWJU0;(P9!F*NIY*S@%!;T\@H>< +M4J7ST6:%44KQHUXUQ_9,R9DH1/=5P5)S_M0ER[''ZB4+\B:AKPD(P/%!P7+H>^I);&'P(]1YAM24B[D@8G8YK$>`1F!-2N=^WMO``-6 +MZ9[HU5N&N?YT7=8""S@>'K,?'S('W3G$&)P'?7WTN`TCE<>,(QJ#-S'&.A:I +MQ,HNR'OC-\1N@O?R-)^S)`_?SU!J8-6.\=_7<#$9/ZM1L85;]F`]7!UNP+-Z +M:%VT8#SZ$"]KS-QHT1@Z*]59SS1+9:*Y2BF`4\R'+B%U'OB[G"`6!KK[86VI +M[K)A&G!DV^56P3BM5\738P6H4A,7C[VT#9&.]YK2ND"5O@M5>'*S0/3I<7-R +MB2>&=(I>Y[P(GXHUTF6%[/E-P5IQ2J3B2OJVA-77-0VQ50\^($"XK[:&G6^9 +MT"U8,U.XED88!2:$_>7\5]=+P[O>I$\3N9$R@+JODA^J)/:QPW^?MB:H=+9: +M[\@[)^M.`-C/`%T+I@&B+"H%F[47:/A;T$8)P8]4SQL?K64\87D#"QAP1B'`O[%C^PXTSTL(ZSS`F]NF7D("WG9'5F +M!OZ!`-"AM[]E^7(])0KX&8L?7,=Y8/?T[+S[CA:%_F98MCSQ"A"]I=WTCA-Q65&8"95Z7I,ZU#\_91 +M$F2'&7"C&>(Q9AOFYF*Y>'GDH3!-X5O'!3>)<^]_%K4W7J>[^AN\5#=_:C]M`HE%8(3/`8ML"QN":?!AV`ZF"ZI%K!4%.BTR3D^A!ANU<^IJG +MF8N,P(&&$%QSSDEA8K6/T2K6[#-EWC<%!60FC.FPYCB=A>QSO2`H`0\[`TO^ +M5^W&AE:_$*T+7?:T?-5+Q@14 +M*PR?[2]%B\X5X1OT%G[V_C5:#UWT;5[\M5(V?+=OC&&,-XV<--G8ZISPP%Y6 +M+92;C8HDM%I:Y^U$YD"_T%307/I.G9/.AOYC%*7_`;O_7R1Z=\ZUO%.]&-.M +M49$0O)ZR7<3_(/['M/0B2.HBX?!U>D'*6ZE19I*HBPK +M/)\T9-")]>-V0WRF/'^`_)Q8DPX*-:?),X13R1+-4(()J7TX5.*[;7]@S9`SD>1ZY'D^;<@$/.#'6?Z,L44 +M7J/-4.OQ`Q9!A3M"E%4V0-Q2Z2=8]D@<*=J6@(*SZ[[LB[8^8?>O +MQCR^\N1H)9T92KZ55V?C8*9^K?:4Z0PNBD>UOEVST)>+]CR?:CJDN(O4T9R" +MD+OQ+G*'"`7FN+SF_4;AT>OIW4N<3:=WA:O<+.%E8UV<6TJ5U$>VXCK;!IDG +M-]B%,;9>UV8'^A8@9*?'`JA/(9!ZAE?I(S=)2B?RIG?QDG#)2#'Q.II#9BX; +M5,\JUHC:9/COGV65NY@OE:L1V_FYZX>A`P9`;^U5X;+C(,$\ZZOO^;,(BDR= +M9X%)4K\LE-]%2-K+[9CN%5@[^2;K[3/$9,(*F,**I_%[>I?GNSG7U3")^_A$ +M<**E(4?G62]%4+1`)G55,TM5\&+3*"=EGYY +M@PK3YJG2):S[9><'!=>9)9&IH>8']-?\4\O]9N+:>'M;['A\_4-`,5PW<:LI +MGQQ.K+PM-=*07@'($,ZNQ,^H5M(+;D.7E2Q^,U3M8Y#U&W.7'9]_#@/Q]&7"]<$'RIYK%WI3BR0H(0@"2& +M42AG*4M"O\@]$GM!:&/H*8\R@L:L#Q6JQOM7("=XSWLE%F"CZY%]]3+'WXQE +MNC:T+'<#56&:ZN?C,0_K74?"#/NOO/FCO2]PF,Q!G?[A%0>68V.A"]9UMP=2 +MXWM#29TA"_SCPWCZ#&O(3B67FH,)6L6@`:NY1`)MC0A5R"C;I?\B;-9J[8TO +M.WT_#AJ;&PA>`^?;JX\;KH9<(_?;^/CE!JEX[P^GJ +MC[W44A?\/XU_ +M]AC";G*+CH)C_D%+WY)&E%C9AXA]!L57[^$R[\@SL<:`Y^6RPHY1?6T%E[YT +MQJ`D9AN%PB5?3UFKP\Z7ZMTW)I7X]<],A3]^)I+VV#Y$DGC&9 +M\#T>@R@SS:\'>CX9FPZW::YY83+:27CUHU1T("]1F'"#3:VTDDC(E?5&@.^^ +M@@QK>=60]J45@.6L@RU`1!+E)%Q(.Z*#H4Z&9&0[.N_/9H(KD*`_7#I#-A,VFJZT#5Q?,)&9:,O)O%M-O<_Y8&!I +M_F,]H2 +M[#ZOP3LNP1ZU:_7;`>$_?P;P?4.W9ZG@X\D2_G)O9;H?5I'LN^=P#OW3SISO +MG",0<C+\*0@ +MI8HXJD='Z@]B7GK_&H9@Q*$^5?]64O8N&\D$I5!M%.8UE0/5Q1-1^0:F]6K9 +M),-9\HOARR)F8Q_/4?JW(&J6W!UYO&)UHX@0MCOTYE%XG50T +M$19%BM?D"W+)]Y17Q/\]54E83OEXOD*_;<]*"XG^]$MB\R7N_8.#W&G`>5F+UA +MG=!ND[5@V'24$BB`]^/E=$WU:0H9:0HG..8NY%H/0'/=--3CB,+A4DAC__02(T^4`T1 +M+"2_Z:>&Z.@@'I61SS6#QD`P7Q^E[:9:B"A$A*^Q4'X1&*"T`;<(8]2X;I*F +M:D9>G\L2:H>INTCX\INRSFNA'/K]M,8F@=@0C07KOOW`%EO6X%JH=9N9P5`? +M#73,"M[VJFM;29XS['^_D?7]%AL`B%RSMB:G]W0`)_F#1 +MR/5$EHQWF'6V"3^&RQ5<'(&52:I<[?]9]]B-FOYD>>_+Y#J"=J!EE`&R%XA? +M8589MJS7>[T[<,/A>KNM+WBT;AU]%`"'8!+5*",T-YACH^&/CB8'T:X:I/() +MZ-[UB\C>+I[2G0&YRG!QFA3Y+$AD4$S5B<:`Z`WL&*_K[2\W(BI=K)+V07;K5V/B@Z&J$U`Q:;H5M* +M<6B!;4IBBTO;NGUOOGGH +MN3K"^,KDY@VNXY*_X;_ZE0@XARJ,1^>GA`@N]!.+U%HYO8$PLD1R06XX$\B$ +MQ;S#*^+99EL?@4LP&E+?=4G_GII9N[LIOFZE>*LBJDEQI5^O;9O4;337A<"E +MP'>V45;>8*?\,D`O."^M>%@W\V!+.!.B&1GN)TQ/_ITI#PO#ZKJ3 +MFBEG%IQ"0,!=*M]:UBGOZ)1<+@?D*J5D4O:H+=/?3O[I=ANKDSNQ'?7$+'I+ +M,2KCN)4)M-DW6`'[!HFA5AJR2F:%S9:4Y9QF;4*A/AR:F\<5P;(R^E]K@Q79 +M:K@=5S!_`%N=]10!AA>[%JGTH:UN=V.KM^"LG:N4O\-C2[FT$)]A20";X1'8 +M1@:>A=%#<8XOD^!Z"Z]_O,$S*+'WB$/HO-KH-]VQ@HVRBAUKPOM1:U"F_GU/ +M3`I/W^`9H.FN?KY2XW$<&C/744NO?^ZF9H4?3>2IOQ_S\VVD_6A@BP[P.(.G +MW.4"'4>#*MJHX5HQ(7WE"_+/O[?C4P4*+4ES@".]63OX"SS!R]TXH"]K%>^+ +MNA]R.HKU-*^7%V56+!Y99E"M*RI(MZELV(Q_TJP!6L2U&@UKF2N^>679S67_ +M_0:3D![IN('9`9G\'.SJ'AF7,.&4N-G]H']7B*L1N?:#UP%*5ZR%4)'>.A-3L&\"ZBIF]/4-[:=%_LAN-69V-BFJ" +M3$IW*9))<#P@#'HW7>&CH,6(N!OI8O +MC_GBS*#I.UF^=LH46?H)NG5JF]N6NR#_-J%F%K_S\AC-(E6SG7#?(HWZ,$"`'"$J?6P&!=ED%@,*X9 +MN=1IC!EYM0B,F<-#^R>EZA:=[`]I/VR,1LRREAO7'5*D$50T\&)7@4&$W",0 +M:E?UHQWNK8@//F`E]9?+B@+0)%5;`G,VIJA]"M8^WLEM$O=X/H4^+ZXU/6,- +MQF1%)VWFZA1[AMWX1)_!\CCA:@WHU6[*#54!.!I(J`RP/1"8&NM(.-UWT4)O +M2RT+NP,3F4V(@Q3-_!?7=Y9FHG=`:=3\X`!F&9T6$F@D"K0OYMZ.!$MH'X_$ +MQD!T+""BYYYJ;LP1=:"Z-U'1"];_PAU9[=)^Z0,I;XZFR?:R>;"T,LQZ821N +MXJN$W5%XP-:(D_@#2'4H@4M.FKZ=R*'9-PR39(Q+\6+P4+YB +M#DH>^GI]'80>M[WS`G/6[[!+LT`E?YT[@961@FE_WJYW%"NT;`E"1U#:9[;4J( +MK_VV)!R'=>E^<81J!3'F;OA";UK-E'-IL')@!SB&&!LV_D`?2:IZ4PV+$0AW +M-G64\D_G2'PAP@A'+D75>EA0=8[?/SH%V1^207(0XON=L.6\8S0IREZE!:WH +M\CMSIN8Q4->>50UT#:;.COT2X#+OI4[+0<_3/>9&+?_:JYN'WIKI'IVQ)AJH +MI9```.Y14->\(;VT6U_?R$MGB@W%T$K5 +M`QLO=J.196-J,>G-745FD=GS3P!9Q&>\?!_)V?VHC:CJI[M$4N>E-5 +MJ[?U+B2'>`TN8!41MM8BIF!B_-9V'Q#;E#H63RH3*N8V',`K-13-XKJ2:(VDDZ1]5*':+P`F +M&Y-?'KJT(0?<[[VWNFYGB3(\$+-\WZ`FM_5WQIY1(]O8A02_*A[B(B<68*KJ +MZ.8V\T5#G87K:'N-*F1<_@'6G6ZP$M%TR:)3;Y8"H0_['E777&4Z:M=^+1"%5N2+\=\FM5'];F56%6)>OSUI\X`#$6J/VRBDT83_L,U1K\#6 +M8SY,[12[K8T6\8%B^_7H(CBN^C6?+?+F:#FKO:BABJ?.P#QPK"7.6JR3`3C` +MV=RI4"C.KD-*-9R2C]_'W['8\AW(;G:3Z(C.+DL/=,)*=T;KG$*'XBN77:2G +M\85.),#;?V?C(S&R2954G*40A'28'A`P:5YSZPX$C]>:8;M:V8?HYDW(!(L( +MO6=]%O[RC)&OMOMPC\?,F.GA+K#0G$2!]=*XL%2'?J$KMD\(:_T3D`^F'J/7 +MUKEVQC,>O\'4[,C=QE<^'[9BN<5DO0J7D94TL,12D7((K$WPZ?Y15X0)(Q8X +MUFW/=#F-ETH4`?F\+<'Q@&O/QVMT8H>NE5<_A#J]UP[\'_"9N+[#<8H%BJ/M +MV6Y.(-MJ%&5;UA_,1)`LJNU!]LWSW;DL0(I:VF'DR)Q)G#J>%J(ZV_(M9OAT +M:;_*T!5-R*7G1N:P&*44O5R4?)%.!CLSYM4V'-Z#RF_ZPI*R:Q`>XXY4!A35 +M=/.7_H.!=_/IN6-SGS*$_%9Z4UV +MB(,1P(]`9D6>,4";ZVGPZ1L"3_B65_I-,OD5&YJU5_RK"$_9?8(@*!CU#6VO +MDWL7)#R>4'[@CFUWAC/-JRH7H^&0,--7]WWR@GI@WVI6KB#9_K'+I*LJC$]9 +MG(((8\N%#7S(!I(5UQ`/^`$GMIW\%ECE!3MO_5W,%L?A%^B59TP'SB8TJ3)@ +MCMUB'G2ZPWV;R61>R9R8Y2^!/(=LG)**,1,TN0N)4U#=/<3,-87'.G&P?/:<*&QO0%Q+ +M_5YLHZYC,#5?A9/%H&^FL=^=I.T4$8VG-JI^[5H/W<[%98>)>>J^W#*^"KKW +M^5,$^VN'U/G%A7:*YNE[)?`U/>M\XGCH%CFR4@'M*_RA5Q07)B#B]XFD7$/3 +MCRSRTQO^F?IGPCHEGIN\P4K)E;*=[I)!(T?DEK<\B'G+CJA"-KMBNM3^S-$]3/;`B^+`>`,TM0LF/T6GF)_]5!996K10U7 +M&_BVCY.7]J]\T9>.EH1M$[AO>I94R.AF<^5&LP,V]`@D.6)<\WCM6'[,(8P51$ +M[2?V]^[A`H=P*@6FE"=?)]^.%`(%,0-7N*:M)03]8[XI0<>;RA,#Q-#RQ[3Z +M[8L9AJ8TSDDGD(.@A'4,,!]#9"1Z/-8V8C"P[IF"+%NY6,.WO*E!0T;1[QIF +MS]M8+EV5,13)I;20QN9!<38@6[/!Z(N+?8JEA8O%W[4MK-$&\V;AZU;0 +MRBJ^5PY$`&\7C7"2C64^R(RK%_0$GF>A3-_<=?%SZ*D5#>!ZKAV<2\$"D&!J +MJ&9F)B2JVS/IR_T-A;#]4@Q_CUWE$IK>!:3WH5U<_BE"X?_F/=1D)Y>)L:HG +MX$VPB>X]_*0J/O"R2-[G)\`XTJOK]%"$GNAY#^(H(E`07X.?A&55ZP)?T24# +M@PY4`RJBN"V?0F)ZG`/\3W;9?8<8L7]PD0-#+FH<^6L..*[VCF_;?)V.CI/A +MHZ,F#*[F_=H=$NEL@G[PRR^'*D']`2V!YCQMPR4F20P#J10FS&+J*1NJ7D3G +MR+90L<6)75`H'UE`K\#)-_O$TQ83'.&]H"5$[.K//7]9#H0TBUOEBS53J>X0 +MGBZ)!U5\*'9(U0Q(!/LW_C^T8'9*VKKP=:XN)8H22W=OWL^3EH#9`>`3OI]X +MPD26)//I0JY?>6!ZS$T/**=(EDDZ4H7Z3O +MZ$N$FZLQ5D;V9^+EM%TQ_'U\3`Q;M\62D/(S-1*^@*6F>S\L2WUK#HF3=@^% +MBL/CL]%JW+MMQ@M2/A\PEZ'PQ#^Y0(R[*N*09KW3!9*\@:E5O^?Y0P1BGKJ, +M$VIFYL;#'>6>>*Y2-_;I`QC4HCQR\=#G;U(MDP5I3M6"J7:P8$H5S=^Y +M#;8P/RDER>-WK-8&:X"T>.6%RME($,E5I6M%)=U5A#)`^G^,S6V+HKV"@;S] +M8T6?(!<\,9#/&5'H=6L^N#DP*_GBMO"0_"F4QMX?"V-0[,@BC&6>_85MX"8#'ZN=<1!G71LX@RR11V= +MTM;K_W`1H`=J83*)ZT6^N+;)RPC.M>"F^9:B\XU+`1D6*6WE.89HI?4^SGX` +M::H45Q5SF<51VI=,Q)#)EC%+B?*HY9Q_%*)^^R)KMGA2XT`Q;N$LVC +M#97O#WS_A6\=IY-8;YD4ZX573]Y'.)Q+S)5JK;569G8[_]@(AH*%*D*X^:BC,[EEIQW6^40GV29LR, +M3`7>3!9&N^X$KDY1'<3>99IZ(%^0KJ6>]F'ZI,\8L5C"7Y!5C)"DL'N]% +MNC=)%D,^WW+6:@EC/-J>9;N&;QO$D3KAT2U]^/"[:1#Y,IA!CY+>TK4EYA1T +M`;9F)G_+OR**9%_C]\!=`^Z>Z#TA.[I8)2$*_?>*8:,YXG$_1L,!)\PZ29K. +M=,Q.UE1D`5PW*8$Q;M-Z^=IK8[S?'`_B8!MZ'WB,)I,84);\]=]W:^"W/\/."Z<'2/ +MJ`I&4G/5"@7GX.Y_5#OSCYHU"7$!M;`HZL!.KH17VM-"+LP!%GD@72%&?9XM +M%AF1PXH=],X$>44GK)A1!+M+[P@,>I3M;6QKGKO7;3=IM9[74")$O)ZR31XI +M'X+W3BPTP1'`B[K;>[B'OG(/&W3)+;(*WWB\2PRF3&:=BFR"NF]@I;P'ME@K +MF^+FS=I\-I?`!TR0EI4-U'RBN*=HIQEX^IEF47[E]T3Q6KW'IO^$1L13`[/: +MY(XHQU4,&8E.*8]PDP9(XY/<=A5T?S[_V+G1FX)&E*0E?!98`!2&U)T\.S#/ +MG.@949K7Y);,^PXQ+$J1F%*_]]S"2;3@QU<&/S]U.Y:B]2NPGSYCNAOU_C4V +M&53D\X?Z6PM(62]`765U0/R-CP'RT1`75MP*X;R?(2MI?+^B743*.W^W#T;5 +M'4JN189!''Z#!S_F(CGM\\R@/`0UT=.8Y?+2'H7WJ6T9)D_B6IQG?1L1V +ME<5@]QL!U3[W^$::^=[9$^<(F*B=V!UGT>.80'2ONZM[843T78#6TYW2ZO^7 +M+.5\&93$.4<7RIOD(359H@(7ILT5!,)J[0TW-;_`O1^^B;ND^P3!KT[,?9>K +MF'W+""LL6H%*0CD*JM#TI^WC0F35J'JC]/X+)5_V0Q\0=-GZH!>3%=85>O/NFG-1>^Y5?:1Y)%!PG9YC`..*9D.&MGRS-+-W?RX_ +M'-=5@Y%;I(P#`S4>],>6G5HER+?40(APT_KW9?+L;^>H3"7QU\IQ5RC2\M+C +M>Q]LRU\#,6:[!$[^#+)7:\)VQ3"DQ3]PWSP>]N\^8JKZ]H$"*W)-6Z>V`&"U +MOXRI3G-70N7-$CMY#@M^K4MA`)3).I>6BJGG/\Q%]+XX_1N[EP_,)/E+ZO`3 +MXSKAI;G1QH#7.,_06IWL96MZT^9'D'W&AR_Y_*@9$,P-K"C$J'&%_HULM1"'ECU.W. +M(6BS6"RDVM0*>!AVB9!?CSJPM87F#C'!CW+Y:B,X/+J(\IEDK +MRPO23YV[HLR_>(SY$S5P$;Y#^R`"0"&#?/*@2XVAJR7:0$HM0(4J;\G7OW?U +MG59Q\C=')&5&;FA/>$DD;"KC-_832\C\NQ(N7>SGUB.!<"[$J?1MYDT&>^6T +M.FTV<6K>[6E"8,L83;WR*Z+\%G&*']=$A3>I!+_CW5??NY$%$THYCD$UK5"M +M-N<[U%06(,<[E%R&ZGI5`@90??_AM0A032DF]A8AS(CZ8G[ED5" +MY.TAG&B6.J%^N_CUNU])E\$C]M7>T[A%RA"6)S]<-;<6;1>F>=S-P^+#RE<- +MENRB[-\+*X.M1B6HZZQ3)2,&M\O$P_]"C["V\6C8KTE34;/X"?C!FYK"8,UT/+ +MR(6J#!P#?TSR'SOV:B@;)]6;XK>71RM6`5N='OJL`6OS(,I@HKDCW!0/'#C& +MH,@G%Z<#3>=1C[J"*,B]R?L1;#44'OQ,[Q"_ZQP##N&V;H'6Q7?$/"LZ1=\N +MUV%TBCVMVPNLE2`%1$6J)4@DP17@HF3TY[&)HE)*RPAV0W)%'\29T0)2N0K] +MPWSW_>*.MM&?,G7MN+,%X+3R^G[!./!8?,9JV6.3ZR/9`H'SH#]((I>*D^6QF9+YC"5+HSLI4>5$C +MM_.CPV56[G#I(6Q*6O;9BO*2%:N@S)L37@)M3R".RGL'Q/0;W[J:?[OS&;(Z +MQ,-Y(#RSB5B-BF+.!/Q6)J4KK?Y5:ET@HJ&5[GL[JU^M!N#9-;'\D0[ +M$[D()`CUQSLF#UA@;_<[?:L?B8[F7BKJPI+[%8&TC.8((78JH$&BAK(E/U^?LKJ@, +MNQ9W-9;&C?S"2.`TM.P\7D7&!9)W`?1B^Z8^(V&!78>G/71S?(-M=T;8"IP\ +M,@5?HZ)Z94(Y8<=K?JF4-P:"86O_O=@H+\-B;.Z^8V:/W#DB3P$I;#>X0[O0-E=&]-I"#I.#\CE+?3=,%=3L"1<=PYW3H37UV[7Y&BJDC5U +M&KT1?>:=J&6?+XT0-FWG")A\Y8B#*_7413Y1V>W+Z&K;!D>EZBI6HY5K?+&^ +MP;*Q4?@_N$*#"XDN4QR*6"M%Z]KI[4`Q,%+?TFA/R]I9 +M!/&,6G5ER]140#4*>,'DJ^8$U$S='1%OTE*.S91=J*,?F=.<(F]_P*E06VMC +MNH"0D$N')=7(A`,C5GIGHD`@13O"86T^_E;ICRT*SD))(L_XTGIW`9Q6+=P" +M^YX4?.V?0=P]7G078OMM'_^H]'N"_[SG`-4R'XZ3[Z%JDJ*T()`"R7@EP6JO +M!2['P9)X*.U*1P8ENA:?_>ZIR-S'O[)#S#VLN4Z2!?D4`+&G8*R!X8K\V.4A +M7[3MLTX:.*;T`*E:2=%]&QO#*C_E[/1_F_==*>.YH&NTL:?'LLC4)1'P]>`S +M?2S.1RC[7Q#NM_J%>,*5YH(Z_O^)<)P"9ZK?XB4!9))%"87%>([E]$@7X0AN +MJ,(I*?L\_6F<>13($VS"T,TD,)@Q"7]JO'@U"B(90;OQ":DT6;*-ZDOY"J'$ +M#?.\YP=<@%I&NB$#S[ZA!G2J)YV>U'\RJGW +M@6?:2Q,4I1Z##%X>_@.44:L8=X-T\2/F*Q)RHAV,'I2^6GJF^@%->TFVA:#:&ZA'6FV-DMW/FKOT_>=K;8!.3;LN_YF[ +M7`K(_?P1VIZS.$RL?(DYE`M+/"KS,.\4&/#[K[#&9?TH),@8QZV`1(HF@#V_ +MZ31-19].YA]5B`E\20KCR[MJWCE7S]&=`RZU["K*>&4>?6ENB@C5?;U*O4]* +M*]3)';,,$*2N/H39KF&`;`L5@TJ*#/1XBJJ`A^]QF(D`!].BV^@RD@OV4M%M +MGKX%8:GD!L1OW2^/\)WEJ]W`!?)/DI#3*XS7YJ*"&AOAG,JN]KMZEYHAL7@; +M]\/5$BEY\(+D`0W`ZT%`4&GN#5Y=W*PSM-+:@4K:7EUDQ-#_+R0T@T$$EK2A +M2@@T.A+02%2^D$*X$DT&%2TY#U]>A(C<#B`0Q])E/W63L3P[L.CS.AC8)(Z& +MO%=?SI#((/3>@:T`?E*%7K@H6[">\)%X/P(?RB(F!ADK]OUT`]Y= +MP=U2ZW_,*:ZH;6[JQ,=0N?YU/?E-G35B@T/M(8%\9UJY'A&$T6&?MAQ9),7" +M.Y72&)X*`GQ6^5(Y>"`^0H2J8Z) +M-BA.B-@^G^H?T'YMRI5K=D9=AEP>^<9?WP+8G>J??.XN'B>FN[+VZV@UNJ^[ +MW?:Z"XNV5%)I]SIA`%NDKC._:/+3[N,PY6G,HS&(/T2'/]M!"$\7)==U]O]0 +MM,0A9E[M6'M3HQ"KE;&G\QE\R_$T:('!K#'<,^.[K;^:[Q#?U$V*O[RH!>1T +M=='LC\>/H.\'].=Z[O\L7DN63 +MW<"L8?X9J,%`F56;HGCCE-;M*P2369Z".;A"'E_)V4Z&DT=SUUGJO.5PB/ZM +M-U>O^_<<*P]_5%U(DM%H9*+M":/0I=^UF^*P4=OB?%/15FD*DSRE20;@YP") +MGP+5D^17)5;Q<#1-TU'Q826V!=Q6?WH_RM^$" +MUN*!/#0K)#[J@VELI.8?*UW0-I)I$1E7VN^MKOC%+,8U;%4`V]QR[&@1%2&7 +M&[?)2/$&5--KH3I-:,!?;;G14ZSD8P23T(EHW[I"$5NTE`/I^Q%96PZ0EURZ +MS8.EX.YJZ?KQE&<4)6&%?.17F\D\Y4@FY<"4V\&(IUT!)9,MYOTY +MF[\3=>!D#ERB_[2>K,0EJO(EHZ`^R>=>G;6T^-%Z7@9:N-4WH$==]LA_5IF` +M)IZTZH<]V5&*K2\#*MB8;Q9V`,RT\MMPT8#*"H(TYL[H3DNZ!,B)%37#])B> +MW9SZ4]=U\\\A[!MV6.$C1%L+C-=,]YJH1&2_D@O%N^L[8KRTTI5[M]SK(>!DOR!MZ=%T$`1W59WR(W!BM>> +M2)O:FPP_C/J"!3MA)OJ/'#PCM/*<_*L$A^W06J"H'31Y)5?7MPY>?Y5H5GZ8A5)8AQ=]T9G"E-4B:5Y_!7"P-)#Q/<2S2LZ'J` +MQ_TB:EHY//WKT$]!LQO7\JN/LMRO%9Q%>//(6R6GKLGV`,K=>2C0Y^<5+[7+$-?(J<)0I^#EGH=06 +MK'*+(^"L"(50GE-OD\;"X$H]H:/QK]%6H?R#EHLL9ZC;6@-RU].G"C(#-(^OQN=+0?$72)+?&95'ZAFLJM;@IU\D-YJE +MUY\;N(VICP`V6X.3BV(84O-Y_7*)!OHCO8%5!W`AV2Z7`.F+@'0.>4#57_]! +M0)SR.*IO80)T;8@KEG?WT_U2()#M%*J4Y7YFO8"R?IL*,68S4QQ=HHL=!7\7 +ME"_?1*X9IB_'#"-,S1#/A-[RRQ*$+A0V\0+P1@\V'%8M3EY +M6Z^F(0%_\P$A49V.I>G+O]-[/?C5&-SA$)P!]V/*E0"W)$'=HVYCNEXZ)YAR +M%SOMZI$/R[\WCXEK34EL!P7&80:"W03FP^>(Z"],61$?HZV%V#4IU>-&C?Y? +M(>LA(!W.36EN:=W(K>=?NO(H&^V!"EG\.%9?X<;-C.%2[@%@K3JJ$,6=4+SM +M'6R7;[^6@-(&HU&?8E:IBS-M6RT%`<`21-OJRA^..4=L6?DQH@Q,E80J, +M0[J+D?/7DW646?>37-(#44ER/)\^CN?ZR'"I=IDOLLOF,A%6I^P4C9]@V'>9 +M$WNS,;@!^5]6#^&5PRB./C+OF<5"`+D!AA6WSRJZ$>2:\%K;TBB<-/(5]B$/ +MM<6),DX%"/V\BW8JEG!10?/EG`V5A?3G"J4DH"]M#S624P^WZ>:>;%".2+%L0`N4@(BULA>H+*!O.HU +M%?KQ"&-]LJ]%PGX=(W5')%;=\ +MWJ+VU4.Z1(R0D3J;;<2R>"$B#\GGHF]XU?FE?YW(L;#?=*^^B>175.Z.P6** +M@2-M=UR0&Y.]%,-&)5ZL:OK>47("Q,_"&->PAAFHY?$?-6,NH!8:X/TIV1Q*19`%;EB#75'B!@#WS\Y`2)0Z?_@T(^!E+_74>(MOVET6PRH-B>Q&!?#^FJH0$/RFWN7\T?W`F"_?W-_ +MIM$W^A6>#P?"^_Y;162!Q*@]4MHV]G>MW:/XS``P`J8JIC-5@]'^V6BX0(5. +M0UMK&H^OX^%=U@B'**B:WZK;=-U%=KE(7RJ0+^?MC%Y5;J$V.3%`5O52,#7! +M^//6IV6)E4]V:5BXU][VG_`AC^]#A??@F9JAK4HA"43)@4E4W +M?-KP7_2NG*5;V^:R/R+[^XX"U!HWMG%++C$?=.9DZ2S?9U5ZX$5""8:SDV8A +MHSB]V@>2Y"X@MS:;\'9.`%9;:&;$C:T"A(&`G?BTGZ2R:@6O+>0KM,BL!.YI]C8S771$I6);1H[CYB\&O:L:- +M<#A%C/9KOABLJ8O/F\?P38-?:Y28P4^\)/K8_`92]5DP<%CDBKOCF:\2M'W] +M-+8`FV)U+RL*"[;P2TCNBC-0BH__+XSIKUY>T\2D';)!/\P3'>36&'KU<\9>G'PX43!DH!CEA*"^;B*`/"D28(HEY'O6L6*0.L +MD,7.UC\;#8`F#__Q&#YM4=/:S:#9]T>.^NNEVT2R\TO'[-ZP$;JY=@/M)P^E +ME$?8ID$&M_DYGXX=`L',:Y]FGPWA!(*A1C)H)\63(D`E@_EDA;IE#_Q#L?-^ +M#8@"$&W(_-DI-/4)R`5.UK*[9.A(ZJ^,K-]#GBC_IQ9UE3Y*H;8FV&\OP8[2-CBA/"T+,3,=C]%1>3=V6<>.(Z"<&JY!(&]_#J?8 +MF3\]$2W/3'2KA[5S-%#U\%B/Y.\-G*75IIBBNQ`+3E,*A8O53V:.$OT@[8+\ +M0,-XT7P7=B[;L8J924EO:N9`.LLW,,&-.D!9*$V<9974S]EP2F/@IP(JKU*F +M>T?N#/=KXV6?_M&5J']LAG76T5.F++]6_1B@M[J^WK&"YVG7IA(Q-N'1%H_S +M3VJ>'N!8Y73V"&+8*V>OZ\#H]86?D8^+FG2DOQ[ALWA[X\N0'!^FE +M<3L>E=DDRM"T@U^1-VE0NAZ#IK?NE>0>5>C$SVG!K'TVC1]AN^.O_@W](4^\ +M7N$EL2Q'H./=+K8.<#@AM!H6KQ)%W+2DPI-&:$O9'H5&RM*_W?.IT/)V$MGN +M*X-,)@3IWPR'5* +M%;,B,$8@QVK^CD)8S<.?8MHENVZ]`\G[UEN]LA#-V-G`3*C\`*P`2[^[QU?R +M"G0@*O=CLT_9UPF);Q2J2KE;V*[$L#$>%M^+A,'NI5]:C5?P/RSV_*`:#,-< +MENU]1FOJS5,:QI)8C9U");:MPT>UEH9%@2V!=C[3H;)T3]HZ:I9\VA11[E@R +M7*2(X#;Z7#RQ@EXG&T07302A>%]F']LJH@P5$&Q&?.]Q?E5NV^VLH@11*EEY +M-Y$YI'4J:ZVF./>EBZ`M"\P(H/O6IYRC%KUV@\[4?EC(_D +MQD7S9Z75";QL?]`]W7S?51QA>NI^@3<-9TI#=FL;PSX[F^&*Z^;\#7UI(ATP +MSZUB8ZD8]1CI&:?S0TLV@_M#\_$B4<`4RNOZ;!IG[)N<"X)>7JE?7X&1;OG^ +M,\?M29Y#K32^@S._Z'F9/T1UO.DUA#CJBH)ZE,RCL50K4/2HSSP:$^TQ>M6K +MV'2J@EQ"0X@:JYXE3#=2-M@.:^/5)+?.8WI/EC`.5[#J(WWWX(CHL)FTJWCJ +MSVGOQN)DR!N\DP`7UW$IWLJISMU8(@JH1:G4045 +M>Z]MBRA`>W_M`./90<=6/T0BR%[]^OSL*+;4<%;.<&F(_?E9XCX'./&`RL21 +M?7<[."LSN*".RH?8\\5W(KUH']E_&/=0J%"3B&^,P9*Q[^E-E0"&402AN?;# +MHQ`+>>?"X"E&1(Z'4>;`JFF5UKP6;_8,72Q"X,4BM]Y,2/`+M02_^OZ/2("G +MZ=V55U&&!@+,IU^E.`,R0,Y*O9GL+>1[KPO.R@E(S,$8^0\")+W!W/+("&:& +M553X_!+O6W&MC^=23PK%H]HH%4_JGLI00>MARH69I[!^VFSRTQ1F%X9V&(_Z +M6?(?QZ&/Q;J0%%+"HKENGD.# +M:13**(P^D"&4+4(/6T88N(W>GQUV"X'Y'$?=J/.?&>?NX/PVM("8'",)*.@6 +M/A?NEG&$)<50]:OC-MRXU/AGZA.@,NCW)6OS#72]P4\1"-_@*U3,8>N][FQZ +M_?+,^U$@448&?"RDY;NWQ-.(S;5N)XV];P>3RU%EF/-W'LRK;%-R+*)S?5VX +MWPRI1-ZA6?E@2`1AF!:;(#$"GLJG=CY9>VD0',5WC0(B,7^">^N9JX0!NFG. +M3FL8&O;H:AS"OX7_Z:U"DWB`+\QO?OF33RW)C6JW(^^,-PWS@>ED08OI0"X\ +M,`6)B@:U+:[?Q3[C2Z62:*^^)FR0QS/7P*7SA.3)]S8`YV;'DF%"/YH,[@U[@*'V&>X5Y^OM#^MN>:S +M=O0O2X#6V5[J\4QWT0.:@76#'V!L7P&`=2.:OR+48>BWQ_E\+KZQQ&N)2)7(9+`102Q>?/?+ +M"[Z<\`&I_$Y8Q^]Q]$D>/0C4!YKQ3S$5"P@)T\!A8=:6=:-13$!!9_'G0O(? +MRZ(9)MO*R0*JK8F9]&#$X/N6/FJ;;ZNNDDL4D0%G\]@]?+\!ZEPTPA8V4(8N +MS%1`1O]%B+RS5/L9JK/0-+"M;/;PVM)Q4$1L:@HM(HL'G:TA,K.5Z^^RH(8/ +ML'U"S8NQ%-1G6<]+_?]VX6JE-,[AI*C-(D4@4!@:?=S]L2K\UFW:XBPF,T1B +MQDVVRTI>4*X"=&\A@J4BU,@4:TE') +MSVW1C#91#[7MB1&`6!RE`^!`32@DP'(1V($M'F6L3P1N)KV<82KD,_#4J09^ +MFXG'B:G)7E)5;KM:4&XG:MHLS/<(Y>3A0PA(MQ5+8LE5@)M-/?9/*CHYKT\8 +MO0,3+V?\6S#YNN#^Q%C0PKJHWL55,4&$_ +MGWDL/;O;^.WI7JB&\J=.;`6;G;NL'0Q*O2JYG@M&G^S!ZG^4$3"M!0I0V8<; +M*P>W^T'YTOJSB]+F`B]>4O7TK?QY/Y5.H8$GH!$[/*C@=6AJY!LY4DI_SES3 +MPF,6O/ILM]M#[/,H6G+T*R8IK8GWB>:E%?I\Z[SNV7E#]N>-(5\2$7=_`Y-T +M^!LNB+S9F0Z4]O_YIV+8G*.)@R@ +ME%BS@O0Z+@:`_)9:(QC447S]:,N$1"7XVSBNMZZB/;S7IU=&X7GOE&-.N6X! +MF%(Q12,/@-:_VZQ2TP+D%F]_QE*:W#.L=2I>NX.*E^_S]NW%LV[0EZU\%PZ& +M(=E=BK"<=[/NTU&^.%"["0C1#5:[$=D;UY]%O*IG[;#%)L3`W9,F +M?!\%2GYHA!F1"0-`7.KX@YBP1TG9C*GO#"I+-E/3*CA.^;6%7 +M0(3Y#$/F@N366WL`]+"&_^?XBTL;06ER#OAKB5U6SCH9B50@44SNRR%((NL\75S\W[LCS+9]!+'VHFFP$$XZ4W:)#C8[I)+8!U]8. +M_X2T>G0457EW/>KMV2\`\N4-(U4:@LG],,YX*,3KD=M8H'>[Y)5I=6UWF;/X +M;C[M")?%5G@1_A5!2YQ]IE,0ZQ)F#`1U-'0@4(")&^X)XSB4M[GHU52W,N2) +MZMJZC^B.R$]H&5BZBPHPOK#REO)U80A#EH1E@>VO"3*[E^=)XB&?TDIL3&W$ +M6KZBQ;#;[?`)\GDQ8MNAT.>WDEKU13>%$-.A/'L__P7FQ/3!C77ELBY\`QA( +MU9=HT)X'8OVHT]%%4SXX5Q=A#[.;N,SA\G*_^DO>\"Q]/4`0D[2A-F/UTPY* +M27[/G2B1U0!C?'(6K`\F%0+28AA_(3TGX8BZF0.F-AWP@Q2X\OHS0GOING\VDB=&<"7?PU-M+%>]&VLU[XTP4TBYA:/ +M3:<%TD&1S71A4+&]>X/Y"N$G9C"WX5 +MEJ*'0*_HEUBX]?S_+)J;;!-6Q(%$TW`FYTGZ[OO8GP@UK.QGL4"I,8SRO358;]12 +M*F&ML/AN8([:/FX,KS>FJL'1_=8``;.:4G! +M=)>N_ZG,K\)V[:KQ4A"E#%JJ)RU#]!\Y,T1F+4CL:R^*.L-'#2*+5FG&J5V% +M1&1&)5K`0S8;7-AS_YF+"!]2&'28LNU1]<$^;F)[\VR@OTAC@I';,/%J<-1A38J[E*N> +MV!>EYOQ\*;G%*JZ3;F@^C53QX7X$4!98,"_SKZ? +M<;D#4[/8G/($-Y8J>WRC6`[@/5W=G*UM+C^+A'TKE3*J%P+^^"8KF,*SP(P^ +MS/;]?W9\R.#BD3R`D1UWVV0X@WU1FE1ZY/J6AG]JSR?#[`GY9J+J):-^D&*< +M&:@+[A`>J%2EQ")K='EQ9OB*=DWRZV+2HW:0AZ&KA8H:T+WX!(YM[#"H$PV\ +MYWEYK,EZN'?&P=!&6\64+H4A^F#YLY_6G-/B`JX)PXX]*S8#S +M28($OH+"%@N"-`CZ>/=`J:;@@[1(2*WK7RIWSJK94\:P%J# +MRVAMX^J/]!\PUV6W]JP4Z,98;20-%C>;[>!/B#SVD5SN^(6,.I_N6/:.I04< +M4?_W1_-L^"NB3G5[&(&"KBP"XVZGSUM*>:93=3[?>F[29HAR,86;2AIX!/R' +MG(71$R!VPL8QFWU?A-;)G5#2N7BP17O%)AK]?L&KC(H1((=<7SG +M@LX6HCS[Y?QSG?K3^B]_9-.HA+(0#R@Z^DZ\1>.H'$:%U^.5*Z +ML<+;&YOW8O$M7-DY^F"C&X'!RE1?2D]S<)"+/WJ9(GFLFI,JTAFHA6#*4H/, +M$^4<@7R+/64MZ/+#6GBJY9,M7\?7Q48C]ST&DY0A!WG0@^-(S!:J$<$_L]@I +MD8PSC=QUF(8`'/&<'K(*)7V@)`_M;]`1(N8#K\W: +MB.J[452I<^>=N<#463/D6BWT2.3I>EU+\G:@&R:Q_&TA/F+A>=.]@6@HC'K5 +M([W#X:N.P+DKD'QQX?OM31H@9-6%"')A/%L5D7SUB4)3L!=:P[*"PF7^I)[=86,6+2"K?A4@02I%PV`05UYHZQ/@+ +M/%C838J"_ZM[M3NJ`(9`48=X./[LJUIF4>2;:W'Y$]0:?BT-4B_D +ML`&`5,.]K4#HVD'M#V7@$&WMOW+T^7*J^KI4O-[,H8AJ_('A@=?-F"-3.GY. +MGP3H6C_MHJS9F!5>Z`.*@LPYNY/F0?!61`-%TQDBRA:Z_H]7M'&.N4Y/2.KI +M75\!CRXB-\.XY+,&.W\A==O:HA_@9U5N-QRA>7,E8J0KI(#4*PZ"Z8GYV2_# +MKV#Q:AE2WSR#-.Z=F;J=2@3'+J*.<$`QSXTA@7.UO+/`F$H0`\WA,)5+(V2_ +M],SU4#OYM\/X@:@&\Z$K]W@59I9=&)8-=1BZ2PC'KQSY8\H2RZT8GK'@LK-ZAEREWM;V[??J/(Y4QM:!P-?G+) +M,]07Y]`?@(_.O]'O\S%_5:T6Z@N@7_4?!/IZD8@0V[W29V623># +M;:B&CM!W^W1FY9+N_^R]OYLWO4OL`SKRK=L\DVW@0/_@V%02>?!H:H]'#98@ +M=JX!V9U?CUO"NUU`1$90;:$8A&VUBM;^I7<5=0?@12_GQZ2&PSKNWL`;VKOK=E$,U&)+GN/]_&'UYZ1* +M]3U19=6_GOY+8[N\[5#38.+RP+.6IMM,Y@U!#2@DA&T;SV1^(B]/QKB1UB5B +MND1X>`=7>2/NQ+&(`[1=6;C&#%WI%C9_DC/2A#//5;DEVA!W@A_?'5S!'(=* +MV9O@1? +M!Y/O.>%W(+'LHE5>A5:'[WI_=-^>%;2Q:IC5$YC0@AWJ8!+Q9`'1@2S$N&G' +MIZ]`F]0]?4X^VD/#A[M98"UHH@Z09BWNZN<+W`I5N$LE;[U[`GA8;]U +MEWO+Z1#V#;X1,F')U0T'<$M5'V%>.J"@YM:ZLI#Q@Y"=*C.ZE!FA8GU<3[45 +MXY;E':F\_2`$`.3\+[?;]!@Y"MX%(B*@3=JED0Q@$)=#B`K'JM(E_`C@7"*M +M(QUPW_O:-814ULKKEH8W`5#),T%C[1 +M_M2#D*?>7 +MHFAH.'A6]#C/-1*YE_0'?_%4C0,)XLC%,3_??_G7I:.A)*:'4'Q?=>/3CR@< +M[RP7JAR.OXEOP(H2]IWFJB'D2(XT$WM3O"<"Z@QN=,[CB+`'W?EV7ZZ"R5+GRI4%C8VHJ4EG +MF'+M?38SN-^$&LN^5UXAK?ZE4YZZ.1G4;]T?%<$"T<)30HVYW:?-9N5_Y)CJ +MH7(E[B&T>0;:,!ZG5\9\6"L1/]@/$P'79\/%T`07!"-5QI-UHMV=D6`GAUE= +MJ-.)VT2ES-QT\V@Y.8\<^M[OS9;^1C#,NO2_GU!`':QM5QJC3@Q:O7ZE!6W4 +MW:&(R0@CI+HFX(`&G-)0H=A824$?BL,9B2GG'@*EAU$V&N8C@C_GN/9!U\2F +M=V*5C:EAJX]'TT+2=D!.@,'=FJ.%TEF`%7-!,YJ::]*Q%KWI&RO/$Z0)SZH7 +M6/BG=MVPU.0=WVSKM,_4THRDAW`3+[R0JC'KHD\,-?+/*-@5?&K>W[9QQ]&H5O>GD"GQD^46`6DK(X +M(L<'3+]HAQ3B8C!L(ZL^*NB:POP%A:U"F?J>C`W6.,/A-6Q'#)1G28`K +MPHLYH^*<=EOX7^Q^K5,\IBF4>^T"_D*7`Y"]*#Q$C?1RMA4*=,?;RT0V9$A+%YK._UAGJZ`M[/H&RY--+7/'"UFL/V:KMV6<_$)*8+U^(-@-]8!O+`I8 +M?<&A#Y@X;#2.-"J\F9:5<1-F3+U=1&11N<7?RY1^8VW31L. +M/Q;+\:;8/G.BN6FW=W?F(0(F&(!:%A-/RY]XM;_#AGE$UZ^2+^'74V@CB]-2#"ZR"'LQMWG0J7CG3N/4AV!B)*2R!+&H +MP7^7^!GF%AQGU[_SN1:N%'=#A[D&U+N4=U&J>D^*TUZC3<%(O/JFNE-*8Y +M!A_H+W6OYSUOGKVJFL+]H=*+X`I0P:83!Y$[5L#H`(+[>5!)5P=DOW^OSO +M=$KDSPX;H:D3U?:Q3!CB0'-=Y^=A6ES;4R[.:YY&Q\=^X+NU3;/<*ZMC#745 +M5.5H;10422V.W_M9"T\(A\SK#BA)5HF@;?$$XR$>HP*B09+\\@"F6D])DI6O +MB,7K3B=C:,!I..WS18UX)V9CXEA!;\&`WB/T3RA\;T%Q;!'8/F+VEL'SYO"$OQ\B:* +M,60;2E+BS\;[B@)P-#-AM10-ST7=L&ANUPJ71O3A"/B#G4VE3#NE#NO$D?ZA +M4(?#!M=N%*Q<@ZBMYSUMR:#C8_)U_,T8I2]0:*9-KJ>437CD+J;&)HQ."!/. +M.I"(&3D\6=X+V9CI^EK^:0`%*?6Z?[_A%+#QY-5/#E($$0$+M0RR%I'G<2&(/_)K +MG&PQQ/9.5X\;(8"V'*.&@XC84V>EP%N;5DRW&ZLS#@!M?IH\#K@TJU]SH]5V +MO-_.CX`X@*1[?DQPD14@&GM&P8*^F@5&N%4*&&$+D[66[Q)9\V)YS.7MQ^*T +M$W-@9):D>+@0XB[S[>9!OJ2_TG],'AV76=*F_DFFQP^#]X(*/W7Y1H&XQJ26 +MR$ZM2$:@XE0ZM*4:4VW6@G=_HK4UX43!L +M%+C'/(BM_YJ,!6F%/";]S:9\YX]G"RBG/NFGR,>\,@8C'0D^PE/.?XSE2N\. +M?]R/0JG_TX@"4K#X2&%AA*F%!(;1T&OA?'QIP&RD:HR,A"8K(P>MAR@8YL<_ +M9/)"W0S$ZC^PRB^IPF_^K']AFM.JI%??28R!X;W'\.`IN)R6=W]EY:*XU,): +MM5K#=C3RBW:UGC>P#NW\Q$^:1VE.ZM`/ZC(C7_!*-XWIEQUPMAO<1P+R;UOZ +M:TJ"!#AG;>C#-SJ"K);.:/N3ISZ5JQ#U3KXLWMB77;&9FS0O#P]=9H6X#;]EMG-_!39G$,*HYSP16G>`J(PI/E=QX +M)EPI8A?RPSH$=(>WKOB>&%F?L^6JP`T]H'96=#!*'RA#C@9P`"Y^L6:!-+&_ +M-YZ<]*.4>WN9F-.9)I2;IU1@]D'A?4!(K"/J<'!H]KH!?IQZ>[)Z]KR:5EE^ +M@GI+ZYW$JX:7^A!3M8N&:L:REV.6="U#O_4"FCTHH.:@B*4V95E;$/-!C^1X +M;AN6R355`W/N*O/SM&3XSU;!H=>>.1,D4I"4R7*TRI2CA!$<>8J8'_RX,H5+#`)&QK7F@'B$*+LZ-(P_ +M=XF`&M$SC76#!/0EE#CH$$B@PJA!TUKKB=U`K"D%E>`:U]A$S.3?K=+DLMPQ +M))H0^.S6OC(.QQN40^BAN(QS"T=61`[NL_I1/_814OV?^K0OU%6B'))IIT5= +ME[&KK];N;1+X$2R!N.K(B5A"&\+>)"=[.0%K(=B++OJ4"GHN6^X +M;G>?+>%9U1ZWY?X\S$=TD;+K)=>MK:+:*^J@)LA"N!)(;W4\H?:[WL`U)#7'IGG;BZ9]=T7W90MFO'(;ZNF9TI,CAN>+FR--VP8ZP,Z +M*ER^)^JEV:J2;6,X.[:NFG$(=-NJ&<#3&QQ.=%/DT5S&42!W8MOF#^L;1Q#2 +M%'Y;EJWD/4Z0L-PZ.?'!.)T)M!C;L)&ND42$>32@\.9E-[-K/5K%$27X^!%, +M79KUO*4=/&](;NK'%Z6HQ8/+PGQFH>'%\I-?N[]1^LQ#N%-IX)<!M4W$ZSY&7OCZ7R$O?SR]OA=&["[*`A0MEO[,@= +MI=03KLN0<5A!=5R*#MFL`/SMKYE:YS8`M&.W(QNC)HOU\+`/]M5RX&H]Y2QGV12@L& +MRCQS.2S7U..,@/SB;5`\CB;DET8NE`4PE\HK@$$]0%IJCC[<,'8[07=/@3,Y +M\1LT]F*KNEFS3,$,X-##VD]P4HT&0128JLI"-O_K/NTD@L$R!-&<3"T.^`)M +MV1[MU'@FIA_/OU1/O +MD$7PTF>YX%3K+(?*6\SM/VVV88SZXL%C;G?VTZ-A79!!DH!D2K762]!ETL/T +M^.H#E;*SPN<\4^%EHT#P#5YTJ(/`([55-F"O<-UG@[_%\^$YL<[>(>_@'SDJ##,''?P`8``%]0CU(N2DW[=FK%C^\PZ +M1-J1HX@),D8?`O=Y>].[19>!$C/A+>KR3($]R!VS!C$@\A5X3[-6 +MQ41#*'Y@(<0^I.)X7%BT2+(>CP#Z_3$JEF*0[#53HOCY?/^VL,5D7@P+EC:! +MA$P[\?1SVU<;#$*!`A(3_)!""C":@GOJ6F_'CT]S0.D(,:)*S;*#8,+VC062 +M>SMC-GIK`UV@,WJ"3_>A#B_F(GR?/6CC(WTQW%U93WQ<[T^ROKV*:-BLTX5_ +M^+&@#K"W_N>5*#;GE?2/Z1LX**JELJX?L*(7^:3GE-$NZ.Z[\=TO36A!YD,( +MK_FFX0DQ652"P2A3!%7UTBQX'&EA`<44EI?5K10ZGV!4C;8!SKS +M@WJ^]\/%'9?FV$["VOKQ_:\<$2;=?M8 +M/`>0=;<45[(X,4+$5B;#7Y:MS9#HD9`KM.Y+F_6YJ0V3\[*(R=_?#IG@_;WN +M81:)Y19=DAST,W?5I,Y@/RAH.Z+S(#`@96S7.J9.Y>N9P/CKHA@A6TKO):YC +MD00Y'`Y,MD4!4P#8/MY.]/Z>Y?Y$ORC-@Z5,C5&(G,.^,L"FH-(_(9%-K295 +MPT8^#5MPK/4S>XTJ*W740:Z.KU%Y>Q4<.W +M?MCUGF)N.9RMK:GZJ=IAJ_@72TLC">0L2SQ3=@DSOZH3-/(EDK(RH?:5Y2PB.S7?OE(WY1?E@@EIN,V_Z/475@1UB +MM10L&1<+E''J;(X>![!@P.6^J2;7@G$:OOQ`H5G*B_=6FHK^9)YU(,)YS;QS +M"T`/)82"$;(("`+18FT(DVKQ0M';67['"M(&AF3K%'T!>)A"TH^:Q=*J^>A! +MU%X##TBDBB'P=0"E0D1MZ0VM>/3NK\BY*O-J+??$5,;EDE_#*UG\UM[;X%^C +M>J1R-ZI_4,5E$?RRF\4!2#-#JG'ZWR";$L)0.4DE`F??Y>`+7XVHR[3KC4SG +M'/5SI0,RG$^XG''4#I2W^&H?#"V)0P?/-'`-QJAI5M%P=8Q^DU2%6`J!GEL3V'R9_?=&M'DN`1Z+"J6[UH@V&OZO +MK!S$-Z6P+KU#>[UEG4%23@@4[^9)`E@"NIR-B)K,,N.?O/GN>V2YYI%/*1V# +M>\O)38V&\2NW;?56(_@)0^CM9]-T3CZ#[E#7X_-'=2*FP*(S`9^>I8CV%E-, +MB5TE)L=_$W.\_1"(JA(B@"%/'%\N8!6C_!,2S5*QH`Y#Z,4M6X\V1K(P>;*E-<)2 +ML_AJ`!7-'%`.'DK[ZI7(L2?0UL@^N5-"8K%A`=7..]B2R`9B.D-'^(&(4!PX +MO0U62;A&7`AT<=BWU^.W=MB;X*&^3Y#>W&&+U"4R!CVH^K[2H#II-1!LR,SHWJ.3J>2U\@GGA,B0&_4_%+0\(0 +M]#YH#M<5=A6Q?!U>50H;W(U9<%0,-XN`G&F4OSK5K?,U\6)03%7J"FA)7U_+ +M]8*+-=>/I9#>W"E.J/\=SK`SUK[M2EH +M,X)+H_B[42UUT%/32_\KV$<5@@8O)U[1FA-!P^0KZ`U4`$KNY"KY,K,908_R +M#D"O:A_4N;P;?\DQ[)'K%QHB0J3TM[N+V.V0NXPK^*\[>N@?(H8]ZC1VVM[; +MKU$IOU)+<12[93-+]&'KO/D$2A`-(GLX^CM,&,F=`YLB:8>Y/9&5\DIX$@8Y +MFO+;7!N3,&U'3D3*2^^&V<,2K>H)8A=J +MSB^E;[Y>L5M`(+E)'H8P8R1B"6R9!`&<1#?H>=>?Q8P'/<1<`3&-R9CZY`AJ +M[LE[>J5`I"X7'@KR9!G,(:N9N'VVL4=+/6LI3;,@&Q9"C>T3GG:7<0'HL\@5 +M'3YJ'?#K'EN@>)4::8)R!3TQDFY*^]+1[$W%C1-\(@O)D_V>NLXJ(%K`6O7R +MG:$%4AP)-=++YQ[$=+C!]IA<3V-:Q(I+P][CMGM*R]^RP\D%<1/Y`T-1R,7^ +M@1MJC.I+AG.['_^^@M"2R>O:P?IV1%5)>(2];*]6V!K_TY?O;WW^=F]GY0:0 +M^@Z-+3.`2Q,,B[KI%KS.J)LS8522D=:VQOF")MN+'.EW!_3OW:`&_]B +M)^,6R_(8/$-X14E'6IS0I1ZWNC*B'?9^.-L0ZKDN`<5U2K.CJ=!@N+;/ID$T +M">65=?6%`$2#MZ*EO_ASZR#/&WMUK231`3)CLD5N<%*7?)]NLP`<'@.!;KX14A*XT4PB%XBG%ECY,8@ +M,6,?3N(EF2G+]E4M/J7`CGU;=IQ;P064`@FM62X,+@ +MNT?J%4)P/K<1RQ[`0@?/4^2QO]-.N_I)O``%P/5&6H*%P\&M>A%<&DG>8_CB +M#+E\H_H1*O9Z%:DK4H5?YX0!4^UH"!G987%"TFD'HQ2%-V0YGQ^%4UK]*9I] +M@%F7@^E1EW&*&">RIK/64Z:'V0`KITD5R9+&QA.2NV_T7OOX*PV2?]*PVR`F +M[S*L[TTE\YF? +M+3^MY6V'\;V%GD2AG3Y,/S"Z/-2H(_9RH5*2:05WO]NB/UF.PA"/\&)%Z)1[ +MW'&R@6]AQ30PN+\!NB[6L\2Q@.NS`UV%_VJG^*LX1?=G_?9+SK4CKA9K/$MK +M!?>8*_.V,XBL25;?;;:E*MIG%[F@L#Y>GC^AIHRX!QO&/$;5X`Y.-L&'_>J> +M=/7:3#*C_(7_^498M$N&IBP5BF'/0D.D*%)CAW'B`)IAMX?O-DO$V;TSE>4V +MK/[X^RE-=*-P7^J=1-/O';,34FA?ZWJ2D8`R(^IM#QP,TO#4."(O^?O[_]^D3"6CM5@0!2D*2^_WO7;V8O +M.[Q:-J'OIH5Z&GSQC5P8=?/WF:87R@2.W\VU;37@YZK7)^O5O1(DBR.M?H:[ +M%WLZ-9BDM:&R,+FK*VIRAV2LI(3TP::[,4ZP(MWQ +MVWS&9SZ,KL\::/(*8"O1NW%M*O$03(#+W;=1,<1,NCNE7EGCDL*)K:+TK]@! +M%&BRCG+_`N@+)+=TPUS#D0W0BFR2)].[=3\I*5G58CXPLY!><8S.[^HPRZ%3_"/BK,3^ +M$R_[=R`X4VF-R3*]=.G^MD(A"EY7]!N=.K[X!^#QSAG= +M/7^R[3^FJ"\G9JH_P<1`>&SN[B%6A?&TS81P&I!TH&_JV&P'*6TYMH>`'2>>MTD>FTC:VE78RJ$NW\^N?M?^ +MJ#Q;#\O13DI"R1MO;^@E(5,]_ZN2J)>O!O@[$9T[!&4TP!OS;RH-A(#!"DD& +MQ?'7.KA507K)2UO&$94E%Z^$M7Q?0@(#LA1&_G7=QFBK^#JDSX(9[]?*2\!% +MA\%2J4/[C%?$",B$L3/0]M89J,,'P7T.;J.UNO/F2I_UB+P+HBBTQ7O7QU$E +MC^254X1+&!8W+JH(ZWV)5?)]!UUITRXZ`H[R^VD&2[J$Q3V)P_>MY&#$^[Q1 +M`H965Q<>?LJ*Y-(3-\]1?Q42?Q,89=21\<[I\IVCVIX.7'Q%<&",6>[!*EM+ +M0RE5XYHA5L:HF4C20_W2((J1RY^Z,N9A6[N<86(LA7-9="*=?KSY.-\XF"E] +M`F,K"-:XAQ)>+3'\3]WEF;8>C.E6W7@._9B[Q]A`$L+8[%)S(&VQF1#^`DQV" +MJVFDW<.FA>.RK]N]ZCJO**K[G'6[@Z4W!`A^L[HV!M7W:[WP87R=L +MQ"ZN^Q':(M%[(I7\G@)G+X*3S:/[[%P=F;,G77YV"3@9%36V=)T04\@^6-KC +MNO.D:W>K<7`'"B<'B<:L/B=H$R658B$+9\Y<0"TM +M[H:,V5-2@&\C64,@XM]%%`'`R8AYKY7>.-)R*I-S:5\@ZJ]&C6^^KP]]'Q!O +MZ'6`62D'@'2M80D\YO%.Z41:_^HO6)V%8^L@]5\F@T0I+QF3H>_);+3L^P!, +MA4I>=`;6PL!DU>2]I5"=U4JD`"Y'88]J]50D5O*KB=U<06SJ*&R1R[D +M,W5FO.UR4IGC("/(ARW^$@"QA^14>J!HJZ2N;6$W`*8)M:"O8@,$4^N`J51; +MCU-MFE$S(*8TP;IMJBY_U>DU4,Z*S90)?V7I5%_"NS*&`%\#7P.*U"(V1/D` +M(B-X22W8$3@@OH4'1I9#[Y'%P&TUX.#+=R_Q=+&`Y!X^5FZP1W*@7*_*+<\\ +M#0:]>D3FDG*%8TE(E+-W9MP70_>E+8L]O9KQ6E4OO[*&`8PH6T8]-TM@H;!9 +M#N1WUW=#-KYXLL8W`I^[T$OA'9):4$-K>:HHL)+%P%;*7WO +ML.6Z"L%Y>ZXR1YR:VH/.JKB[*F#>I!:8>+&BE6YN-R@ES%[FF0(RWU[VXW0; +M:R\*9$5"MS[M",8Y;M"OL2!YKWT4*!IGJWLP:%!ZYJO(O1'Q\"F:#$G:9PS; +MK99W&4%R4_6RG"D5W$XHAZ[T&.B<;]9M9CL'=[N592X[-1E#]@A99+8RF5KT7PZEOD%PGLTD& +ME@^O^EQZ*-G'`0!8$^`]L1,JY[LU:K1PLGOP3)).K/J;;!@PUV?FZZUN3]RU +MDCW(E*R@BY[G9C0'8*\FO2(O%?1K_GYES<.S(NIP_4:)K?TPL9^A>QGQY^46 +M9@WX`J6X=1)AP4>_<>>=_#:4GRK1S9V.$$SK%U#FX!T"#F3L%M9MW$0?;W0^H+990O +M?,S/W7%A?X_2C"3(=8'5*_2FOAE=+FG.@A`?\TL]H\0*2%]&;.,3;H.E/NNE +M[=8^#W`E-&D(K8A6T19H/JTN27#A2#`18V]T)6%B?#9T;&)5VCW`DSWH0HQR +M?Q*G?FF,3QZPW]E?)10**5'9YE"-NN_J/U*!R#FXNU'J(:3A:>`ERP9.DJ8K^=^YL*EYQ.HW_MF2]]C/1*O_2SZ&4!@ +MX"H-(3;MZ9M+\,OG)@`@[+,7N*\\8\5>&O^5!A5>02UOW`L(VE$&]#<1C.]R +M3>##8L+>:*3%&3"[&W]S,03>KU%1;;@$$'^I@I\0@?QRWM3?1G+;__#;"^Q9 +M@"0+%`'@*,YVH0($/`U^;<>S<63W[K=JYK6KCO*+*B/EQBB"MZY7ESWS>#9. +M65O8TUS[O/W4@BSY(T/PFUF:''^K"I=2>(5R&I;C/0_?T?Q\O!:QG^<+5:H7 +M$5N<0N$%B]1B6`LFO:7NCN(8@SQ]*FY\[TYSAV'9@?LSG!=NZYS.+YA"42#% +M\F@B%R'-S"W0O\>7I"PI:8G,\VQURS-;([8RP1.:0TQ\]XV$,,C7KJO^SU:= +M$:#Z]9E.PNHA7RQEF"LW)O_57:?-V\?7M+"12@&-V-S +M_V.1")ZY1HU@MRD%&B)QJ/!YDF0Q,UC8GIBQ$GOR2WHNACXN#11`K/.@%`,I +M\&R/4"LLI,_&Q/`,PH%U3)X5QIJ]IAF_U(P@U(#=Q=Z"``=X!(%4U=]1%YGZ +MCND(I%CUV[=4*CT!)3TFO?EH",))O,[\F6&OCV#-9)L:0^ZJ[G%,@$.;4'?W +MT!CC*_470FNHUF[LR+-Q<-=U0>YAN%9KP]$X`CJVC:Y>\V*KIJ4'9Q*.Y9MF +M%F'9&1FMD_+'K#_=:?9/!^E\JKEI016'091I/B:\UJ/;!?EM^:Y#STSUP/B: +M<>6F''GU^?A*FC9$VH,6O\#Q`EYO_*KO++Q(FW5@!'9$F9[S$36`_.^HB'/!1HW +MI(])-):YHT/_G9JML:6V(!&^=;L_\"8W%NEQE.I"V+A1&/[OXC8_)LE@.8!> +MC]D"FQ:^!GBD/XWD,1-M/T(9EOK%LO\:]TB<>)WYE%)I[R'!4.=Y*BJG?*KF +M>H@M(8KP?D%FK\7J&%TB[)$*Z7^LG+HV\>]69UI65'_YN_[8D;[VLU-,5_")>SK$M +M"X4\E**:$:!)K,-_*H+^;+7\D!+._-ECR$DZ%+0@UIDE14H+H"S9C&OF)F81 +MY25X(UZ,A%H4^Y8K$UM0,%J%PK6/CY=%.R">R#"C^7=G+A0$-'YZ7KO+ZHG+ +M!F9'#E^$#.J^CWSYC7J0BNKR@I.G!4^-NJ+VC8F@"Y--=ET. +M3\='M)5%&STT>?2'HI)6"LU.(_\(B*(B>M+,5Z0P;?4^L.TD0P*"?9O3S9KE +M3L[2OTYTWOU>U:FE^?O4-%N?W>P4`RJ0/D(25>?!4+3CR)1?Z"2H-P`UO]VI +M8R959QIJO)N0E6:AVB+NULW-[9N.Q+N"H.M*+['KE-E6=T72JLETB=R$,7Q( +M=OT`8S:>^:EK?*Y^HA%^*$L`O!`!PGT,U32D+#&/&W[:VF7\52HPFR1CB@03Z+-/FYK)!HPS%<#:CLN+GSB +MJ;90<.NT$IWELPWDE[P*NP?W`=19UD5"75JO]Z]&`M&RJA4D"F1>"U3)R_8F<90$!?[J7-/=X:66@#;TF7;T8L^?+C`Z).0125M4\W']" +MU-&7$]L;;BYY4@YP/TU"RB""WMY833!>W_-N=(]Y$TO"M1_>S';;SX+E!NU^ +M:'ID:Y_EO@8)RAV55IE>7*<(]-V41Y38B36@;$5-$4KD+PB^4DEK2EMG85>G +M6$1SVJ;;#`,GO`NN6-LK6CB#T\E\:!]]E[9WLV\.`J8A_BC$^X_==1P;#PGT +M,XJ?`,XIA%=,[7Q&JN7=WTD\AD\#V)PV?U12`XQ<3WHIL<1PS&X%@S%E+^`^ +M&[C>:2=P``Y3#:<(0@@DO!?<+*RXP^%#'.^D?:2YJGN3`M!;E[I+]T''HH9` +MC,VE&"^-R16VNTB&O28H0@)>COE2FD(5PE>=O1@J9[^*:\8M26[CU-)KR]#= +MD&I4HFA2V2^9EHK\GN&'):7;">5>UON"]RNJ+=LSE$.T$]I^A%0 +MKC`,^Z^>X5G:YLZQ*S)0#DTDJV$[4`1]3<(9T03\4&2%YRJ5-/-B=*%';M5[H\*S080&F3RVD?W@&*8-P&SH@QB;WZT,\FA!>GD[;9_%II +M\:$:(\%XRCK1[4(YB&44!E&X;%\Q7H>73F2]TO$#WX@AQF"RM-_)M!6X5%;E +M=HB5M3BP&AO7C\UAG2F$FS@(Y)5O2!$Q.`FC@RDPXT]C1]?]00R$79Z:Z5+P +MR#]A.6'R9=ND<`I-%]JFNZTZEY_T)!<%IS[Q!20Z;9$6\,`=LSA:TF(/U$;. +M/%\+0KFE63D+ASX990DAX0>M692KNH>T\!;I?5$$9&K).)*:($9*4@_'0)K: +MCOS`_@398VQ,$9U?#3\K[(>]6NJ\)'-VO,G_EM2=R\E_R%VT>FHOOY4NUK*K^86HT:5)+ +M)O3AJ46UOBHR(!T\]9"G!1_`<)9,B/^8%-`9E!'6"7 +M>01D$)X8/SC\KF1?%S..,P?V+?4(!',^2KM=U$_;,Y:*NLZYB!OGPX><1XR^ +MW.ZP'@A`0LXR/HK&);\U4_VP)WT`8TE5K;%], +MCJ$H$6^;=04S@I0%2^VID+15^#^R*O6ZD8$K2H(D;Q*EDUNL,E>-8PYZ+"%T +M<$DA6VQ6P=.R-ZX:-';FJ`SZQ:@;(&[07ZX=[MX\T\.Z5965#W+LGE:K6P*] +M"TF]Q!GULM33&612WM>4&+]L$V3DIH'AB.,`!`]!7FSQP]G%I:G^>35W)][5,UM- +MU!1O;(AB;\>9GJ$.ZUEN,MV:)Z#G`X"[PJ$>2,+VD?`\>LQ^)X1T@4JS'@>L +M?&29U]DW]L#1&^H.HZMW#]Y0]LNP4\WC*;?^-^Y898S+*AQ;_6X*TITE1DF+ +M5*@2"F2NJ7MU#=2@]%[IE*J+#$-/ZWT2G[EUP4%2K\!+-_$HK)DS@;V]\,%O +ME[#.4G8>DX=>35-/-1+/^I1A/*(,&H-U=07MHH4=/E]B7;M6>IT*$P0%-Z718>;F(Y-YVEDDSE'E.PJI%)'=3_PDIR%K(_Z +M:W2F^<]#WV"$"B%?_\,_A6%:Z6=DH"X28Z>J=41`=@2XEN+9[+C)*0%;THOI +MTT42X@TN;C69!T\SEM[R/MXEF;F=^!/S]'E%-K.ZI?H*9>8X4('J+>LPD"$YQ%E^[FF$>T,H*?6FB\W1$'"F6F1O7DPOZ482#$&)($O!P\%O1+ZGZXH* +M^G\NE;Q&-NY7"_VQL\E"LV@.!?KU8Q]GC`1,OMI=E?R`*CF_J6KES0P*.ZO) +M?,V.+"&W9ZFOFK*&L[GXUY"CUVU=5E+.8VQ0F;[&H:.;0HFI)8.D71[S%A@% +MT#"OPMOZ-3-0DDI)%L*=NCI14X',8,_%9:E2`S,HY92_$L1KQ3PI+ +M7@RFPUEA_VF1PXBWU>EFT(!5PI>D-Z9 +M(+TB;J3!1H5 +MXT:(*67[DI%*3.KIH2V\_+'L?KE7J)-7IP1U$'<^HHX)6+F""`WV34'9C@S8 +M]JP-!U&^>$<"_=`AUUJB:(5RB"I"9;0/3?0WE'_G0]#PD6M0IA+/J@OGJ\]! +M:W(+-QZ8A<^1!TRHIEE%V)*S/TC8:)Y29-SDY%8Z*'7,R\3#PW$`(YY<^`A? +M7T\GBL'UV!X,7%D\G/S9=<^K:(A6=*"X/B(J8FMQ8UL05AOW=4Q)2VPXA%H* +M2AB?<-S'QL"N\E2H.)M\X_M/V,B#/ZZF1!(A*""*A+G/(:9?QN+SOMR0Q&8" +M7.^8WD;_/N#H!MW'@EK6FKNV<4@SY_.XR/N[.X!\U*TIS9NB?3A5*D2-K[&C +MB28`*.O?2*[F(],VR+!9UTWMRV$>L/#-PLBWUWS,*VK!%QUPM\M>%]J>0JZO;5-LME$8A+8_O24'O3UBGK +M\*+MH3]J`%926(PP-QF2#F-6Y&44Y/6P-$+",9@(_J^^\BV_%;%(_Z4&01A) +MO4\RAC%QL;?`DZ)[G>#/`"S80YZQ$Z"?=']R]G!6SD&_N,'Y?U,GO=B3%W35 +M6V[WN?G4\KL<0UP2LI\FX\I4`JA1=R#WYF=_8\GR>8Y-!KIH3/QJ^G=1#+S; +MN_/8$S!-L2^7TC0!4VRMWS6WS;(8X3HQYJ])/W-Z6+>!`X?3WH\^MZ)M+VZ( +MIU!PO[ZMJ[%PFYBJ8;F$B"CA2?%/M$T8+<_J[K&G\VCK/-^ZD=BB$W9XSJ`C +M3>#A2H85GC_J24'"P8LNTT>GN1]&\O/!>HQ,]MMY&5RDQA$;$8W9\L9GA'RN +MU[\Y[<#@<[`A`?3'.<>S-&Y&&K-;>5Y>9Y6_&:W;5_*U.'\XA8AT6AT5U0$D +MG@=EEIK<7TQ:-K.UQIOB25<'6*M4^GO]D==,'S!4.IS*PR+*'TWW/(I>Q4#: +M7_A$3;E#80PF1;=HA`1;)._%`\%_7*8%Y4I/5`U>N$Z31K\6X5OOU=@ +M)N-W-"0S0^%R:8<[A\#NL]&E;??'J1`Y\426G^3!AGA:Q +M7]T&;W)9>G&VB:N*W_=[26\/^+RL;9AC`60/O;C"2O=[^E,@X',_'(F;)0O8 +M=8_YJ\*]-YL1A(+[#WR3W>$=H>HG`+F"GN&V'28X#*\H/*"T/L@WO3*$:4@I."F'=.$E\JC?1$&3_P)] +M`@#IW<-A$J-#C]Y)OB"+'CA?MZK006+>]Y%EQJ[_7/+`1A.A[+O\*8`17QE_ +MZ&BK5W:_\D4RIU;OYJ@4E"2%D"7E]F3[S3HQ?#*BZ@`8GL->G46W3334.8`- +MH%21S(2+Y;*MB?I#.R8<_1;P"Q'B.SYV<.0@U*/'6>+N(R/IHG#E-[B\W+^V +MZ)R#/[IF,=S>7;SN';W6\)S.=R_HFF_&+Z(':5<:#7K-B=V8N35)SK1!1I>\ +MN02]&$$PNVBEPD^4Z&[D!9WYPN!<&#D)]>+W4:/, +MNT6_$Y<2H9+A+IUZTW9>01:B/\VFZQ5*=SWCQ0U0=]4CMF]O +M#'@#-Y`.21[_1B";S/\*#P.CF2*[I\QR6KM8&?G07UNP=.`AR.E_[1;MT*_? +MVW@2X.&'NX!412O(U3B%LV#?>0*A4L']34/&;AQ.0]/?%/<`W1P*0@YLFJE[ +M>2JA);T:[TAXAC\OW`.[IVZ_*9)C2%V"3JG%T6\ZX8+AV96`!8F&DRBV/FP3 +M<'P8'S&ZV%1/.J(@FHO&^_J^H3H`??IR!73%&]\'O:2-O,)-1;#P7T-M2>D) +M[4?W&,*='B1;R8RX5"@B]V5D(_)PY]A:T!!E\F`*]-,.T^=\ +M1<:W/N@67E!S'&;!Z"A4+#@Z>(61%QV)%D!9?>/KY_.KM[LC[M@54;"G%M-9 +M_PH$7"O/L`J>:?,(ZW[S]#+F>W[:TYR0[4EM$GY\A1I,E)M@`_0($8'@]]A- +MRV]=6G;:Q"4Z_7A(,%Y1)(T1GS>C?IOJYY46"0<^XL3(4'/$A^8!1QN:"Z*WD\:=B2Q8DWP/Q'8G4\_J)'"1 +M\&/J4+2Q+&LUYIM'.&_!9]:_'?B+L#@VKS)[^GI1T\EOBA@B571\8IC2U6!+ +M_7[$0/(5),_)RN`NE`ZI75=`2` +M<`$P`(^H7Z:<$U\PE];\_.<[26'[IH@##Z'=)RSL)A^)TERJ\B)^2*+86!W# +MVH'=<8VUN0?VG7&K_N&[CIZXBWXUW9AB`D%_`T/#\_O]QI[8*4/?'^ZW\!0% +M;OL9V&R%;,)@<7Q#VDE_GZPA_&VT=6W6:JCB;Q$0OC'KS:3PH]N2UJHW^^G0 +M27OPO',GV[L5GGQ?";C%&'N_)^TF,DU3;YN<^Y)`L?W+L(8HO^C`D+I7>.2_ +MUE:E`)3$P`USJ"ZS*1O.C!@-3$P5*:Z1Y.-9'T0)-=7'A[9[YQ]'@&V+I)$D +M'3E:+W/2@)VA"@[815_&Q]`IF;&IRRX>]3[D)E!)*7CF]'-*3$^7=^6FX:45 +ME@VP/G=U/Q1JU@<(AEDR+&54!-*G*IQL+4[B-'TF=ED<5AYC6P^9H/-!L+P. +M/A958QK@8@B(E_46!@VGO`O-(N(%9.=8J!3,DW%:>I9JPP'/?. +M64Y`!V1/V7"PL`)!+9^'6:ZXX0T^Z$"#W#7$*%5O3[4RS'INP43RPL!VTQW5 +M.]5/J`47`P=F*W1$\\@_UN5F@0C&1UX +M&9E)P9VJ6']*CP0-_PUT-2B?/[1H/`GS"O^`!,%=%$JDPVP5YLUJ6_[V`H7[ +MC#BQV)P`Q0B/760&V7$UO_K7XB;>.N-)+]5,#U[XO-K^TL!2<#COUIQ&'BTM +M3L=IAK)XN#S0<51+/0/PK_VRGP^GM20T@,>Q>#M7(C0N/M^M90"_Q7?XAB?O +M@PJ/;[(2-V-RH@ +M1I,E8.T.N^_DK1XF%?IA`OB:R7Y?1+UZ1"0X9L8A_E@O%5?S8*\[/-SA\B6_(0DQ$]R; +MS;)FW%:@(0[,8`JXD95G^^PJ9:Q$Z+&17!0[__V=VE>8E>_,T^&?M\L+*SFE +MQMQ_\S3_S]I0=>"/#1SX,#NFIQ\YRJJ8M8Q@!F=CR,3K*`)UJ<*E#2E84XH. +M)32DA?NW4O99.HTT+'CL5#U;5J@MK#>BU[U[+XT9\/O,KM+U +MWP35B^;%HB?X(]?;XACZ:55<7*WE&\?@:F!;)?;WR+!X)G."L+)J#_+XFI0X +MVN,F9=-TIH%K'763R:SG\MK=[$QIF\A:#D"`P:H*8;>Q+U5HFLOR5;12_)N% +M7'94X)K`A-8<"Y(T_L0)`J/E<%[M;*IGZ6]HV]SLJUH-0*D5*PU7GEXMM;([ +M=0]L2%LW[D;8ZXFH^6,_%+>-'C;/*;2$D1I.M7"PS,Y!%BRT`VR,=4\.5JFX +M?*OO=";5\B@UNU"1>@LS#50WGJ!J=#LZ$D63RBRK^@6D66"^-[SS[BLY;_,4I(I!25'^*5%EY]<Q_LJ9& +M6RPD7_>'Y'O$R-(?\@N<=_9$MQ8'(K%:7!_*,YQ-B,^Z6G;L8#Y4/_]*03WX +M-W+,-6,*1&$L).Q?O[Y8KF[*461TUE_F:&O%1X>,%5GIQ#,D4"V83']*HASV +MK_T_4C%#+146I;JCZ;KTDPDUKBW"6Q6F2/E*$U2[& +M6.Z_+MNUV1(QG&VL*87'1FJ`G4=:2=<19H8SH&P\^>& +M+6>K&+%06Z1)MPADIS#%@0-=!1P'6V^JB>>-#OCH%&PI(E;F$-'B1X?IVFTV +MJ^O_S01@E[,HS/4S;0[S@_9+5:0$6[^\APM%HG9)ZBL$^U85*(V2#7MT]:(D +MB'DM!S`:X_A&(2UAV_Q:/`S]LW&BIJ`2LN!K'.-2'V&:V$:#!ODJUC16>*Q5 +M&IWP:F/O8)"%^@@M*_GEU>#K!KJ)TR<%B2U/! +M'E1!]?LC@7;1<.2'?O2+A<<=N"2,M?4:'CPN6A,#H$#&!]SG._RZ*-#<6OER +M8#V45_TLL4XX?7D!*\F5;K$LK`5<53N!LVR*5#;D7=O%.:]TP),Z[(7\1OO1 +M/=6,(MQ+ULV#.:#PLZS-.&3'37G#T_?R+H'>:_.:*/YP6*`'#[4&*IP@H^E +MP5Z+M>&`IJW[51%+,.75A/,I<$JR(<1.K=X%%QK"<>3)$6I@`34[Z>- +M2;ZQI(,)`8VYWL9Z.#XY]\`9BF+=:!ZS,YB]6K9/BN:^C'<4HYK#V_1E`[R+1Q=,]QZ;X3SF]M<6#P;WF=@2875&9NPQ+2+#5C-=*K^DKS!EAL8 +M1BB3\"7_X]VWW\_(,;IOY:-W"2Z$;\J[4H9G33SMAK&\'4OOR;1L@7JIFN&\H$1;!3\Q!`$%M>7'K$)!HJEX+<*[EA:7ZWTA24?%/\@LQ[UE:D +MH(:4T:!ME\Z2Q6<)7I$5/D\;Z3'+L]U[SX_!^'R%,^ZG'VQ_5QE.)V=:]IWA +M:Z$4\66H(8<&1?Z*UZ=QIGI&$N@8J/,B'UF/]+JB)>VGA-X^CA_1:#.IP3G`'<,WX4^604O,N8KJ`K,YPA;\JA"M\_7)@2:& +M5^*C]0:O:$4&^2"#?LBX]W&3ULOO@-W+X6\M`BWMN`#.C476S'T#4>F<%..H +MK"(X]*J\'!9/'`QIS\Q$K.N5H73N"CNZ*1C2=]$;.%1>"XA$)[KYO80LA +M>WLQ+^&HDG$ZP,DR><>XF#]$:A`F:1>*C`%`V#CL/?9_.^\(T7#;A"6UV465 +M76`Z1!/JR-4,E-LQ<0;NN!3W*SK(0(/CAT'X\YR[&P/G2JXM_8O?;2S&LE$; +M?N=O_]B_?>!JC/1<)>OCX!U=S`OU^K]E&0MHZ7*$V@)\R_ET-0AHDC4TL&7@ +M#S8%5<0N=9\F&IC0,L2&W.UC]M1,'$X6W?7\[R`W`,T"95$[3*<:S2_2HT2U +M<&'_C<4FF5M\UKQ,]B3WO4\_]'8;J>R[D)TZE7"-3(PB1!)!G4!) +MG<[$*9H-1P(=EGF[@?WKI28!`3#%%3I=HAD^\<&NAP9ZWR'Q]-%ZY6RFQ&M.8K +M2A%AZRXO)5#F"N7?F!4.))IF!8X;(@(3>/*C=5J>_GH0%&O_((5D[ML=WWZ2 +M0Z^VL:&0#<.LG3`3\0/0N=M1%_&..%`[`*UV>1*9C2V3AHG$`*T5^UZ1!]G@ +M0DI.C1F5A3OSMBC#!#"%-ZZJ&5U+TG-%%;G).P&&-8RR7.#G,=M)_EYF089? +M)%'KF9AL)NTU&G92)V]QE4!?D-"![GFC2&]M\GWL-<&"S`.["[EP+6DM2O;> +MB6H!#QA;V]>VU-$LRM+-TD.'K2A"R$@&P@:[08"66?2$*M^>:7#RD` +MBE/Z?@]FSP8G3O=W_T7`77H:JH0PT[>H&;P[MMGHBS]#87=,H6W1%X0YNWBO +M,1"TPW,.BO%04)5T^O[SP[>EQ%?MRD;Y;&UYL[>2^-SPPBBSD1S5< +M[CB41O6QFR$K>NJ]MES!Q(^]3&1)QW^OZ,WQ01)M?9Y1H%I`<1CTEM:#R1S, +MD&-X!)BG:'C_::XC,LW;)(.)3W4MV:SHEP(0B3`M@Z3C*%L6(IDMY';?,/`' +M3_O%HLJ$9.J0E\`)0E^NZ;@K83#8.!H)#TXF4[*M^8NBV]5RF1'[PT"?TXFJ +MUN.!;+.[R:>C"F09J&D>6@S,H%#DB?J'ZA"X6Z^R[+?Q/MZ8113)Q#4R@0*/ +M7[G2IH\KDG*)%5DM$?]LPJL]N.)MMO:7L,40)XE^14J7`JKJ7ZJFS8:G"A8' +MX?S&GQTMWU>,O`)O'[N+X+!T$_'5[ERK].U[^<20&".%> +MNJIR<:^IK?D?M,H/0'^_1O>/TWMC26M*D^8,0(9JSCB!-K:^F(PVWJRJ%5,_ +MB7$H%<^3!6#W[$SAJ?\EAE#KFGKY-:BWO&,SZQGG8\;(G;0]#5>O%,)UMA4& +M&80`Q>=47F14$YQ*N&O"JY0(9$4$1-P<5512*-\/ORUIR?:@#1DD=!/\Z(=W +M(\T;XX=-J,6`^@8[N1G@[(-6TD3,966ZBBAKI0#?C?'4XO$;H'<[X-K7^:6\ +M^02KK=,;TTNQ6WUPB!08@SOA_!*D +M&[!QQP`"P.:T7)Z)1;.U[?[=GC<8H7YF4=,EKZ;A69SGOR##%QNN/1%&!4B1 +M!^I]Z-7;6\`#S1:QE!R9]A?(TX_9:`F8^V?Q1<9I+27[#3*JBO8_D(D;!M6, +MHK&D<_U>&.0D>RYH/EK%[KP*G1IHL,GAO&B;#$<$T5^:X@^2;8AK@OP6=6GX +MC/"6U@!E#0..V7`/<ND^A)HW[_R805?S!#QN)12G$JU>06 +MDHL7*G;[]JM1+S;60=0"]EC@C7>3S\X.W(,`.5NZ-R,I-Q\ZT1IV'ANUG$M>,#8OZ`'U:1<`?2Y^SG0!SC)H%'CCL +MTJ,4HQE>\5G6R2J--/PK=3T +MPY_*DC8.'T-:?G.=HPJ5B]4(JP3@'F"12 +MS8O?T1*G'!SWDD1-T""46RDSO@X")V@O4\CK&]H_TV9"&<`UDR3!]A6=>;O/ +MZ:Q1*W-?33Z"H$03O-1(9?+28&*MD';E2;(/XC?GI)5Q360R!TEJ4C##`[O$3$S05`!QZBCJ^R.LP!DME&753("08Q[66`. +M"6?:[+RB7A)N]D;J(T@LA82!+*L],M;SJG1T9;NG`"E&A-19>-L;GD?`&H7E +MK$,@9RKBB>_IY&`=PQH"=5;1ZCT4M>F.SWU0:,>:$66@V=O8HO_U4>!!#:M0 +M;@\`)B$OT9CLV/9E/&I_%;E8\CZF'5T3$LMQO`9'ZU^;$BTPM%@'R9#WJ+T? +MXL:.(C5:SJB!NT.U8"=!J`B9**#QPE3E&>$_;76RY:=O8LAI$3@I\U6;2J]/ +M+.RHF;B6%;MJGNV,4\V6]+\X0YRDUL<)2D&P!!`(AA*H5*]$E=.1PJ,:C6$O +M/`6&>I#\33#!>[.MS`L);*54'?XUA5`K*>OWY?;?C!/+7R( +M6MB;H]\0AC0L)[\M)SGMT*!;CVG%UQSY,@@DDNOY'O\^_E(P=41"9@Q3)P@' +MDX0(`\K*#\F'HO9(CA16*H,)SM-\N=8./:AIRP2)DE^4G418Y@]SM_=GS/PZ +MUQZ*/-;5\=BF%HBQI4@=DZ,/4._0[P?5(4A44SL]385(J,4)*U/I>9SKDUE+ +MZS0P4AF';&.CS;7-'CDO;W5[7KMTJ:9X3/CD,!]E%.8O8WU_X%$#&N]7GW?1 +M@NCGL0%'++?/-G0\[I*,8PS!:]-W5H0$3(S8TSIM--00U6;`--DZ1U/;T-LT +M8#UU-UGJXSP]]*.Q_(G*=E3+IO<<$\'QU61MTK;$-FIT9'?]K7'&[?`F58X/83N@(^4D;^P*R4.U/<-E(^$K246`EWA$&4#\QA;?3;C'!K/'-?R!00,=4Q=EC +MX.=[Z76O_(N1_=BOQ$HV9#H0@^YGS>1W?8>ER-Q67-B"2])S$\_^E`[SD@)) +MI+PUB\*<;7!!>)C[)OB7,.;YQZ%)44/BFOO8>?K]5F<::Z\@F:AK%9V0(B92JFM8.\7&EB[>Q?<-&6V+%_5EN4/ +MV])Y)NXSHK423K-^J]A_-\=T]\WT"'0Y"UD^?P[E,77(&]?$KY +M\37FV(?4KX&N/CZO-121$U/H0@1G?SKH]O28,=\R.-7/O\)26#=)CJ,/XO%0 +M],PBBJ/#OF+2B3@3TXS-7"!1&@!;QG=>>@M761?X8&P";\;+E+P@L*L^@VX$ +M/?[^2G8D].Q)]1"`G_0>2?6TY^&-0&I=)U^.H-P%;7OB)AL^*M8'`$^+[%' +ML?$KC!7]E4R(\I3Y;X\'M#)!V7ZDE6NI$$Z>=!,;E5?P%=)<3>-JX:]P6#YB +M-''XSUA+^5J@>ALD@+5+;@4U"%(<;G]ZZY#3[TS?52>WVLV,"YJJI,4,NJTL +M$9:.'`I#.<9L@#K]B\L,SR"4L'[JY>\2I;!KPZBWI'LY65#(!9_%PGCA5Y2< +M\:,@T/IY3>T$7V\.(5DD"6L''PK5O0#X)")F">/D,VBUY(M(C4)9H7$O8I#Z +M["()N*UYO2(=T"*(S\^J-96ZT3*&9:XK8[^8#-F;\)T[?8Z2RENA_2K+Z8!' +MA;CO/Z6AHOPEHCWSW#A1F?/Z_N8"!VEE5D/I3E&LI[R)/+P@?H9PXKIJ"=&PQ: +M=\[#V7*6T$>$%>9AQ6\EJ(\2FF`H;)Q]6(>;E,T0^'O)8M24?<8@X@;%.Q!` +M*Z-Y0F7+YL6+W20P7YN_5@")5HGTU$NH%*)DW?[O7;_RIY(]+.LEJ4^KLY67 +M!20X`.OAG58A)+^D=#0(G<" +MH_7.K9)S\9W4(D@$OLK)ED)B+*%_U'GIEGE%D9U_T0TUXV)#71;S5->CH^Q] +M`5I/"PW)?L+H'3'Y0:6*=R((7?KUT`AY>#@48#K[H.MUN]G45/1BP72H_8O@HB_R;?^F%0ZQ%!SNZQ:\D@LQ.I +M.\@;;QPW.>U%NH[R_W0$V^9'^<16B+5Z1NB@A+N=9A,([A`DE0FN\[QXN^S9 +M$-?0B8JB@ +M1@:JX.KPL/KXWY1\GW!['C=M()`=Z7FF!^1&(4Y9J.S0`>@*_*G8O3/3<98[ +M[@\`X1X=.W7P8Q.]8L:#,T1.2?SA%9LDP=0!M0*H4'T@AY#YG2`47/N3W4$` +MN+NK42ZU1!&Z`T:&O=*(4JQ%C_$B8M"-K,)5S@0]`;;[>UMT.D7J]3GSR_1? +M5\+)YW=),)WTTF5V3#YTZLW9R3B=9<5+W)5 +MRL_:GQ;ST9LB7*:U:.3M@G'OAV5X7;`GK]78UCS/@?QKBTX$5$4OAH=.%<0N +M'2"E66B6BH^W5G]5N[6";08QOKA^&@C"NCM[[4A&M9"97,",M=!%J.M[#5,L +MSMM!?\2:A4"RK#6PIH4RK+3.BP'$%OD_\%X! +M>4@HC0/E3"*=/^UO%A-!P\MG$..)?.4)YSZ[WBF02R7)DZ@R+=@#O`G.V=FE +M4OT3%1"&K_LQ.0@<(F/+SUIU&B+OGJBV3.,AQVNM +M@SHNIB7KW%^1@J:"J3%'B;#M7E+A$\\I7;4LGX$QXXPL5Z0H=LU-Z^XBTN[E +MU)6B=3[6[CDP49-1095)D6'^QTT[9((@E?"7$A_W[W)&)$,:N,-E- +M9MJ+QG01BNFB:?$^G\E2'Y%CEKKE*#5'!**33S4$8B+;UH#EI.>]D5U02Z3> +M_=O["KL74:PFVD5D@'5"8^I)\!%1+@.4JP4W%NJP^;^T'F#DCC]^]_%K8PH\ +MBB9;.4\,-7*(:H#+P2W#;`L3XM].DJ:_&+`..PD](]:X8M1V?;@`.H[VH!*L +MZW/CW5"F=6DTL]"NWY)],JK/C-?N&U=E/X91T(YT^D[,NIIN6>(S$<8&65^Z +M$MV"N+;CYEC+>+.J$.9(KK&L+8D"AN]Y%@6DQ*:[C,/HZ.Z?FAX6[7B]NL=< +ML^>2P^*YWZ2B6TVA]<-GOF4U%TYL=HL9!Y,5K>XNR)1&=CL#I3_\@+4YC/[^ +MT(ROIA#CWA=MTB'ES1(4^N'=`(B(R/P/,&BR8:Q+?7\#L%%=GTTEWD3-Y/-S +MQ]2\/B2-,@>T6ZR4H!/GDT(EY)@6.VB*''#.HM6`;K`HTB>E-X,?@6/R+N/& +M.5R?Y>&'%+ZAU/>7UJS)%H\YZ)[%J"P/GUJ?S#XIX!9P`SQ)0>L1"\84K+0R +MJ>P@N:L7`3_T[U/A<2NP?U(+')FZI%J!8..&_PIM*57)^CI['2M,KN23ZXR# +MV>QMA]S7#8ZF_X5/`07JS1_PW"?;3M'D-K-.GU2Z%!%,(I?IN?,Y(9F!84<*ILXR +M21YW92JD8X,D!Z#)=WIW'5=)@*-=>D0_S!Z146);SF-F!'V +M#R9$"RT/*;W5@,X+0L=KRL)OVVE@$5W;@^#F/ABE."[W96(]#?)*=%U* +M'!)HPT3^U1PK;CIG[_E-`="7*.3_7G-8`AC<4*#DR>07\"LU62?\Y+^7XW/A +M/1X4&9&Q[D#L9,[=3DUY\,]Y'-R1,?I(*NE2Q_:6K9ZFC'WCR\E_9X>ML6OH +MOY99VOUQ2GVBM]XCL@CB&4-TH.MEPMW13E8L,,OW/IGZ6T/3:B+.Y#,':9`/@6&T9^A2;-(W754)33J1 +MX;&#.F?52$31^+$,6>RG-;`;:Q(!!TX0[WPIR/_HV7"C4$7-,"I&'-I_A00J%*&!/`KHW+AR(('=( +M-5'F8@\BIG)\.V[#9H;2O->7G +M]##&VP2ARZ:L[@\S^GN23/V''+WD0"3M)5*AMA3+DRJ%,^%*E61EVR4P9?64 +MOQ2[RR7$A4O_F"UPY7(.G5(&`7ZG)P/_DHTW4DZY6>'66'5H3C$2P46PBP83 +MG$G\)U=;AK<%O"`5T>#\]DQ_8PU_`)C!CN3AYT6K,RB5.&2M+ZXESW,3!@3" +MS/U%6:7\YPL/Y(FSIBA6XMHVXVVUE&32@5AZ>AM>;8MZ0`FDT7W%[/;H'NZ5 +M]G[\,#3J%;$OL6Z[]X`@ZD\J@E@ND2M6##C68B'CRPO!XHD$0+J\:.7%.0FM +MEKSYQDX]Z!S%;OYTUNAD;/3U`[ZS`]GA)U3&^OB3',!F*HC5L\5OS\\>=@?Q +M8);WTR[#L&A@S9P$@WR`K)O@.H^DX&2C4R>KJU(%ZL]5Z7WD$*%8T@YQ"%>O +MTZ:$J&EDZ&B9N`LN)=GY/@#_-?%NRT&)HJWQP-7^UL3NHZ'X+M$2(W`!_J2A +MS/71'H@[#66<,RSV>CVY[L'T%PG8PY9^_2Z(%\/DZ0Z8A>Z+W*==OV*I2<^= +M"@@&$A0#]I[;K&"**Q+;GT0&I#83A5Z"Z+*HNW'";0G(3$M)\T +M,O0LX4)L-FADIF0GLP;GEJL=/FL:Q/3LJK+WY?DMU\3N]78Z[1_$8#/!FZ7F,Y_K\&Q7]'NQ-<(_ +MP&=@/B\LYTOEP4IWG8S.0\%W4J.:8Z#\UG/W]FO*+8BB6JA +MX^U>1AV.@+28/O,R7N7J!UZ4\*[[LD* +M7HS8,C^`Z7A-5G7U]$R\M$,X#VD)8[ZDL"(Y&O-*7'P90CF!C`A@A&B%2N#O +M(;9MK!L#07_4!347U?1W=1>[U<=#Z0?_*@WU)9C%V0H"48*^@.6B3T4U[^1J +M,!D/[-)#ILWAO80?F*[3D$>8DRZ2"S;MUXN./R!CL'7Z'8B%C"IRRFB*YSBW$6NEQ^8/0WI3<=Z\58-?ZT%8RUCX3(H +M]<=&T&D-&`+(G.&>S\=Z"X9&B\2)>.)`Q1O]L5J@!6=YY&[4(Y*G:5'9)VRRN8.#8_02R%J':2Q;7"7>;AR]WN;/%>V +M;*"`R5RM^FV(_X.J>\RO*?_.5`P#"M#>OF_:7`-PN4[]E(@!M7I[*B&-[0"@ +M8E`D5A?OHV)GG]A?3BCVV\UX0,^0&'U\8)L2_WEFNLOC.R/%RY[(RD?-*5:! +M23E#`!DL(`3&^V7,B?2=Y]^,[>K+I6H%\:'D>S:`AX^ +M+:B#$5B+??A5F.OG0E;$ZZ!J@P+).`K"EA7)D[7XMLN+`,9G/$5;6_?I<_=9 +M\+;KT/_&;A/-*O-6P,GA@J`7XI0/\H*,)P%]M*6S8)7I2-_9\7/S5OT2]0/? +M4_A;^O;92$U94=\U7R"70$NR0K:HPWE7,*]`0;]5T8Z=&/$P4K'09`0%(X.* +MX]MHN9B[!2O9W=^IV5A/;84@%-P\[X@#=IYB4*BA*H);95MQSU:WPR7F'EEP +M1-A??PZNW2Q^P2(-'!-P()2\#];\1N(^.KWZVM`Q/A<-W[D\5\Z*DD2Q03DAP#I7-YHY)]M;/,H9AO^YAB/'#X)?9% +M2DX\VR;:>]DAL"18 +M=O548_2_?IO?(G9Y%V8,_6VBT)I5@!@9T]HJ53(CGL7Y>`>W67=+NY(D('<: +MIS$;QD%1><)^G)V@*`6I3D"9<[EM$^3#MX+BM:(4P;I1#0Z1E1'*EI]RSL5Y +M(Y]NNWLU[>F5O+&V+$U*'K-_YW:MFB(;@/N`Y]YI'G+"^(CVCX#`"2RDD-^[ +M8O"A'Z56N[QJA\YH]8MW\8HEX5H3]##64#IIA,3$PY/V"354I<5W*;Q,!/WY$0*KQIS5_NX.0GM55C,W+$BJA!&# +M7D'OWHVNB=YL7W!-T\6)'BB+*^X^9GE`(PE&&-01LRW0/EF"%_K96*W`8$<$ +MKLS9AE31K*N+-9[JM)6S:'+@*PQ?&<*C)Y,A;5TJDJ,EETWH:?VH";*\&#T)&\X@2N?V]"0:]#KEUSV4FQ\OX=BGL5X.](%0<5XP&>:7-/ +ML1IX^,B0<$PJGH@C\Y9.)XJ!6UFD:_GS%FDH&<83C6S<>)L:3$'3\5+UL_XS +M(ER5/]GZE:ON_*MK6C0\27&C%N[-,!OP>'VD1E0#,9XU=9K@11!U]V.;O?C' +M0:;C@4*H[-+KN;Z@7JP,R\GB3B!Q#L_6_#%3(7-NO)#=43N_%B88AL2>@JE5*K +M7N\,).K_I[P"U3CV=0F9:/T#2*Y1R`(S4-@S0_.5ORT%S",)0&4_Y%(Z0H+Z +M"\Q[?[;Q<@6[H,X?3$3IRF60CR_P'_HH7VM08KM>XWZ[[W:Z +MS`HY>H0&KZG!)'N*O0G24VZX\Z&.ICQL_4+"^&_J9Q\^:'Q<>V1AT*V(N[55 +M>09J/]0J-!Z_NM`/`R5_1H8'NJ=,GU$U\U?BBC:MO<>*3/T8N%7AZ`$<+DS +MN+P`FPO-/FX*\-&H;G +M[B>'R'AQ(@PC=S;O57%%J"(YW-]*BT>?,X5ZL(%`W5._^_F7JE6OET[<^92- +M+^&#_^`/T]X)V/ZJ4O2%=W#R0K5-7-+] +M?(JDN6&.X'`R*3QH=/Y,"8*)::Z<:M%ZAEPL)E8+>)U89Q2O50`8^Z]>V(>= +MKQ/>UYZ)*]W](6SN`,*9O]M60!5.YU]O< +M(10]K]G96TS2S_YN'`:8"=BO-`1$XR5J*]F0S4S[KG1RON)J9Y7&H/Q&0/]T +M@U#'(+F-RLMW:P.9OU?0RGF"J"REC/N];M +MQ3J2./U>BYHYZ..5)BTL;LT7*-8,.UL`]-:B%G4S]'`KJ.FT=O0Q2=95LXD$ +MS?,,HS[L`"?MKB.4XH01!CY/2P-Y.@E./[>?1!)),?:1G5\`MH#?DHP-&.#9CSV58$/\IP433G3$0:E]AJYXJ^H]X&5S*O4,(5D16X2!B.WKL*2K\X- +M8B02-`89M-GT1U9J=/!.KA`M+Q#66M[,-O&.X'[-'>M68Q3`GC_%P$O_"_$% +M\]S^NX+=/J86+3VR9GV34`4Q)6!/TJ*X=Z[QEQL1%A>,&`6!EG,Z6>:=?8,+ +MB[S-Y'5D,725F="!;=8X=V([(5>!W9ZUR($4_`;&-W +M+1,,TUX';,+]==(!*AAX&%]7?UC3/A7N-S*9#!MK)E5&L'#Z2?I=\9SZ)CMK +MP6[0^HP\17;!O\^L+OJ#2).FFM*OGKEHCN`^('XWK98`( +M#`#03IR9_:^5/M@6PMP5<55-0=]!`7GIQ;A+"+XTQDK=EQ7Z8IB1MD>[_H:% +M;NJ?:_07L[KW4E4R-8SGIL%YNQXW1V'C"N'\@"5-6G63^*(S03@,S4TK8_T. +MY\K>=!)XI2WL&H--00!/V%3'3CQK(RJ@`7JATGZ,RQK-Q)8K-]HS;WM9HLT< +M_.&[7/YS'UX3Q=[Y$)GNN\O@#<@<)^N$9S?.`.P1LE[@8]]ZW86&VP71>&ZL +ME8$+M"-`YIA5L7A"M+WABB6J$S9CEQ^G,;H)29BY25[X_(#C6(CKY?)@0A9_ +M6`[<)J#,U(>QW2P%XJ>S>]IL#:>Z/7/0MC_4)";$JB&IZT1F:N_>C?L=DRBQ +M(P.%F9-60<67@S*^9$[)2KCOY9/0V,=1E%S";Z488>,-GN4$!.S?`U.&`!4]AQ)DR>/S-P:Y"+%W_)OJV-70EO'4I[R$1!_E\71 +M7:J_WZ\RMB;P%;M,T9)C"Y1I4OMC&7KZI^..^-Y[%U=;&!$DZF.=)4@DJ,3P +M"F4W?>`MGI.)JX-T4V=\8'F^O;`Q05/-AS&>L5!N\G.K5JC8MJ>(6*,1D@NT +M`UPU."-46Q8.]='_'Q>+:M.%N1"1[`72'Y=DEPD"*("@-:T6^4P_Y6605E#T +M`VA[1C'HCI4[%.=@*WRF.F$#XTUQ>^LH?Q%P$AK&O+0^`T*MJ<\_S%9DORC= +M@#D0B^<9)WO1YL3+0[G.]&YI[:4LD56 +M=N0H`>'W;;^(ZN4W/AE:QY@?!S"0(S_AQC(WA*FD;YIFC\Z.R;,AH3;DNV&< +MO`9_4+7LS2CT.2A[7@P./FG1D$:9A=082C_F^VXC&Q[XF6"@C9TE+5X/EWF[P]L)6,TO[B,@O=KWOI+BA\^.R'\?_%'.A=6) +MC73HZ8&\+)3LI>+E0DUN?8/T>2,ES>51,-[7D,+XJ\SY');KFLPZ5N9[9T.KGIHN%]$$%#;&E?T]W3XB5;DW7E5$XL2T5,/?PR]VT3S +M?'I_;T\4\@V<5I?[R'A[)6S+0J,TI^&%;L`Q&XO8;'RK8[R*;*::8+\/B/]L_6#WN=/-:A#)JMBPP +MZ?O,OA.^-^N&-W?%,EN'K3#$3YM\'8^9_MMRV>D0$]NWESNW,->H>GD)<+3T +ME\9-"L#6N+09Z(A-5Y^XR8GK[R-2Y@EO^FO+M$;T,#\O$*QX-A5)(=-:R/_I +M[DA'UB:EFAZXS[^[,P?G+4QD_%]`OYVD]0+="FV1<4R1W+:B'EQ1>-+E>@72 +M?/I:-&=VW@9T]-SO?T$B5H9QH&CF=@086@5J/F%KN_B_.'00A@"./=>X52+7 +M_%EFR8"E4F)`<50-@Z,#`G!&BPA(^H19TGE540K+$!E$H3"KWOT_I,DTI5":*BXC +MND'>BE7UV1;@W49TK+&>V[,\@UJL@(M"^T +M)[>,%FC\?]0:94N)B?8C/$>5/]"]J5"V'8O?C+.##:\D8UBD0&>WR97$9.#] +M?W-YV.!H/3?]L4FR>32K,#K3A,IZ&59-^,+,T&/ZH'M@3Z5QDTG:H#B1T&A. +MK;L*MIZLZ\\KO-YAD^1A]Z6&PJWFT+V*.^T#R4O%F)N]MUDTI0I&G`] +M#F$77M91KR#8;DBS>QH!(Y5T91Y"0LR,D'59FUA;H9R_4V>.@Q+TBP/5U-&' +M3+VL"*ER$+X3$]BG'1(EB_`^MJU:( +MD^9\FK"'J;R6M3JU2$S/I)B^*=OH$JO&A"U2[\$QF\^/E8<;Y-R2J:D.=-=4 +MOU;0A'\1,)RF=N=8]IY%9*XYW>2]FY0YM,+?/35(G`G8D7Q,=I<5M:*Y-J&] +MT+1Y611=Q%6"%VC!JDUFK87GY9CA8`I*/$H`^I53>>4C.[=RNX(=)N"=60`' +M=W-1/@$CKO8./T:_L+JRA6X]>%<7[VH"@S0W))S\<`\#=YX_96'"?XN$Z9BJ\/';]HEB\!>4Z@R_=BOE/KM1_DGJ>KV/_MR_#ZG1VFKW +MIYFNO1!C&.F`N?D0$`FY\A:.L1X\RIR#B>7?:5F]WL*FSW!Q[-=57\MX,OG4 +M:?K(HH79]1&;!,^-0H"?B'R6O9V"-Y#1>Z9AOH``_2[_&<#1;/?:, +M2GTL,5S4X:UQTN'P`IK[]D+B$>/)>#)N?E7$#>)LVB7<\^P&_C%6&"IF8M_& +M0")V'2BMGB8",1CO%Z:UY5:*X5)5%..!?^$GR)@#8\%RJ +M',4UI?9[:A2E65MGS_O`W/_.X)5G]VP1(9[92SU.):6.%'(*`"6Q_@U,L?'4 +MC9;HOKGOG/DA@R]T5X]*L]+`(+OIG=H.[.2,/-:FL7[%IBTHWHGUO>'U(X'Z +MP_E;P`$QNT?@I/$A0D4+>O:+,?BA"%VG-///'( +MM9)R/P%/=9!G5`RD,^"0Y5BOCDI/V<$'K6C@16:_@";MM\F(IUT+B/!R\<(V +MZR?#/DR'X:QY\4VN-=M+_Z^JYKC".Z9_Q=&YUS256O-TGGE4M%`O-H97_ +M4$7FX@`1T$35@CW7J*+6`E%UHKO1@#W/TP+D#E9LRNMG@))!Y^%M5DK7A;,9 +M#S.4'JF_-O/F$EU>C01<6QMH=P1WI?:OD#Q"``_'J?+-FN725*%C$Z`6]_73 +M\RDEV-W*P"AMB6&:`'>D,I#D4-;.E_YT#085\,I;>QZ4YC:=:)EH2_J$Q2A' +M'8T1S8(A6*R8EC%ZNNN$PG0&4P>69A?`,*S?8UZ-2#4LA#][JW<$Q1)TT`)V[,"\`_J7)%]GD0LT=YTZ +M@163&M#3'?T77P4+A']#.]Y(]0G!2X\@0N0G.SL&&KLE4DRLC()O"(KQ'SKL +MDN=@!V,D\TJOXE8:YKUKY]-^+#-;12CQ4P@9PI-/3=&F%W$,JQO/NZ]7:G(Z +MQ252>,:-]?8?WBMMP/W8+5%"B$%9L*6/T$JR;`!S4M8M01B@K%^^:K7@2-%_ +M^]#0@6Z?ESNOSH[.EP[<\MUG388IL?04[5.3XKJ`.?QO_LJ7N5>"U8[Y2H(CR +MX53&E"KAP^;I/AJQ:5RW^E1-5YQ>'!#2@=N[I"$#^ST!$"(EZ<6. +ML;AF?RU]1';9@``HOU57$[CUNCIJ&"%)FEJ/<,P$>Z`_+BL>0@RW9QL"]1U? +M?W6*!ZI//%Y`IU+LIR!IN-^O?*#(^@.DH]VOS,',J&M`&]K_B>AY$5U-- +M0KB!]-?"AC4`RW*)632ANC5=R:<5^5F,9)Z%/6\1I[I(^D +M/<-)/8!%Z6()H;!>6=/HR("\U+$;R8DKK1!PTB&'RKPJ;.3?ND78`234`ED6 +M<4]-;E'PJW;6#+PML,6PI<3*RO<+QD!MIBFS6)+8& +MY&#OW4)].(._G45!/T*W5EVVLPPB#W$9V>0FJ#Z$F13OFO)#I"JS9P+Z2N%UWLN(*JC,A52V,2PCDV+>W\4TR +ME,T^`V?D97^S+>IU;Y;MS+)ME#S^JIN@%#U]6>W +MJ,V6*)D'.5Q@[<)$H!CY9!J;[TH2,2(SE)90O@HZCA.\*EJI"AYE`F,APB,' +M;@2ZXOEGFWN@J=]!V?`=G3_$!Q25M8;/\];3.6#]Y..%50=<\#WR_#-C(.J2 +M[$A8/8(P'A:W[)7X_85DN?`ID09ZE.@'LHAL9YY6#KR[+ +M7B07A`)Z3Z5IB6Z-P\#+PV/;GP[C]Y=30>1>G0+(H^'M5=@+VYS,P?(?"EC$ +M%E?M*C^*XO_TCE5W`4[I*M#W>12>DUEF)190JJH0T0P$SXA_,,Y=(J`')7T8 +MV;+QE6XSL_G]W";-!02I@/.>!"[^8#`Y((+?KF"WHR/_FVQ1B4[9[!0,!`$__^D[)HQ*)=(3M/_:T_HTH,6(CRMYWM9-6%!-W9+C$]W$2WLMC +MDSAVAS*^=A,?*:CUC:2J][BK&3Q!G,+6-P]OF8O7>Y+B0?Z@'`1N_?B8]-ZU +M>UZY+X>$\YK9W=8RXH?E&>C_G$_T&B_`:7H!GR)[!EP`T]1"ULKP-`MU)Z3G +ME^[5^:T#5PB+T$_,>0K&U'S8[?T#&_<`6HABKAPB>J8?//=-,7T\GH$[S5G- +M>"R<]PQBSEO0"B%%P>6D)MZ;8&4?;%28B#B64B5;0X&E+<@D^W=B,$KN*0%< +MP*,Q>M0,$M=Z7(Z9"IJU[F_5B*',$C^;$#&^ZR +M0H,8&J'#I%6[EM;L\V0K@>_,><6,A"=KK3+YX)0\(,&QL*+D&6;^.[XH,4L" +MQS0%B,&U9P^T24)HT5LI;S`TPJDB'$K#^[NJ@`K`&WT*P=<6XRICB.N;0E"9 +MPZ*E*>Q[W!AJ\JUI__2%26B(I?WF]JU)'K5\%`Y`U)H#EZHI[41_`SL$6["< +M6.B?AM4X($7+OW=33R/V>#GWJGX\\@"+(H!S3*U6CU*/$4M)'L^V+K/%@-=[95U@!,\#:#U-66_%5'_=*@N2Z.?%H,;+R$0#Q9=B% +MTG(>Q6!7VF4\2M:2=0P_4-%.<&M=\*Q53G,84^K!*V[OT!,Z-:K6,>L1]BGX%YQEL`C,-QM4GLSW^5V4UMRXO&41_]ST]GM"L:>$WF-^N+ITL%O& +M\\T)W\67=YI?HHFR+RLW\H^Y9$"-\G?]X.I[F5>-V?42*KE]?FJ?U/`+@'IV +MFG03S$'V(8$'&Y)VAXJ'*35Q.!DDT&H]U<`>4ZCR<:.O0UMT28]L/_!7%3A# +M2M_?QXK/=+AL&:%]KO[]`@=`HVH]G[;-_>DU`$F''`3'G51>PZ-R'N>%,0_+ +M.2F.OLFR)E(_,%RX`3C#PF+\^+$XRAK,QAB]#5ORSXJQ=A>KVG):*06_O95`EP`_C;F,32UE-0%W-/ +M>C)0]HXBA(MCNZ`%0Y%N>]Y@Z&9^SX +MJ.CJO9J?6+@$!G(V(Q9#)Z>Y^5\;KVP?B8M>^EZV"5'X.:%>7^J"C&QH4;WD +M=S>\]>;4U@@8:G*F7:K?_DW/9WPE#$EA)\D;5""X0^O6Q9[]MWHXZ@U.`%J` +M42T;"=8DBRO-R!C:'Z$0M=FVSC+MG-M,7/Q4N;K5GLY5H_ES0R0[&OX8Q!), +M8:C/DR\"JH6VAVZB<*`L"8E2D-,$+SFR[_A9?5R$#V92.>_[9JXDJD)E3A9J +MK`94RK6W:MFZU5+/H<3%#U$",?)'*^US)H6"(*.\`.]84P"VK4J+M\KF&;5. +MHB*2@*C5-?V.T!9,Z*K<$A[SI-Q*-(J,/T&-F*R:`$`%>1SV,^=.SS/H49<7 +M/RF-K0V!3)"N;&L]20-#XE/JB,'$K,;0G`8@9H1`^I=-P+"%O1P1$3]RU'Z. +MS82;.N0UTLV,!*%PU.]QJSP'B+OX^29+_[EJ[A7TL>J#;!;@-,!7QYR)-3Z( +MP3)E/K"5^-F3XXK<7G:H^"K(W?T>B`?1G;PXJCU]&'"4J#:I3KQV`H'1093; +MS9*BW[T\05J__7T$'H$#U6:^"W"9-3C@GX=+_T:,"0M*ZT9=V#HPIB4*P,M) +MD_@N_D4GTY5I$E/[M6?TO$9D1GZXD<600%RY*>4GKMX+<_+;C]3=X7]?,8`/ +M/P(;87_:N'G$-A?EEDX,HLQNQ[`&=?D,4,=&"):=*?VML5+KS.%8B]G)Z,8, +M^_EC6_H?Q0GF'2!E$R<116F!4!U[%HOAQ)KL>UZ,.RM)8S%OK9,P6'%4X,)S +M$A).GLPJQ6;VA#PAC:ZNG1&:QI9XS>W4BH#]NC,;`=F-?YSLN)& +M&=3*OBQ8$;=N0V@C[X;`ZF]^?H$[77O/(?6"?4OL"YI2FFZ;L\TNN@W-^*P_ +M6'B+R<55[=]P)48)$*)U66Q9\7VH/RP/OF;O$KFTAOHI&=YX.M? +MSL'6J%URD:"69JNSR,JV_@EXWB%%4*C&4EOX&W$*(89,[7\A[:LGRY:1-SO? +M+Z.EOL7?QJ=*;+57;'&83QR..)OG8T/2'E5/BH\B-QIM!6W(%UKC8[D]. +M#]/LZ@C40=)!LU(Q\$C$3-JKBU(P\5^6O5%<6.NIK"`T!$T;Y&TQX&4#Q2%` +M>S7?AX@P`'QO.D_S\,^-S:^9`N8IQ(DVR^,C]#EYU,[\2Y)E<9ET>0M%T?W!,JH.8<'3CG;0;&C5QEF+V +M!X-<<&DS":,B7A%!6#K((8"@6XL!(=>FHG1ZP+K6'GRPP%TD=`J!B)+S.GKV +MH&00L/GOX)\%A-Q!L4HSZ.6M1=12W<'A6[QOG^CF1?#P.S-`(@4OAGHPJ +MG:V2XZIYJMQOKU6Z3.5\/M83PW:;8'BWT3L-^05S[464-.%TERZ!MBYVX!%. +MU8ZG@Y='UMQ.OZEZ.M+,KR +MU<6V5OGY:MO9_Y[DUVA('N,^H)!,9QBQL-B<0R"3XIOJ0 +M6/6[E_'#^JBMZ8HK;"YK\-7[;E5[)IC7?>(](IG/FI,10"*"IL+NS]M30PA[ +MH!ACIO1L>((;@N`'G!]-,4KJ]G+1-_4=G2-!B3P"*]M*1T(GM2+,!3]DZR16 +M"2%'0#P]A@:D@5TXB2N[,H#9+]\%0;CTJHQ=@F_>?8>-BRXD>P)Q:G)^9\N5 +MO?*6;-@JJB@S6Q#ONH)IO+5F0,I,L;00M)K=I9NR-?J":F;HX7^9+@C7&VPOP;W0KTXQ;.,H4SLOJX4)WYZRX;[%52"P)&EUWXD*%ENASFR=C +M*'O\,=@ID?@"WU;*8]BHP-RBX!H#4(Q^V\``H?("V3=Z?IZSQ)F(4G4I8^;+ +M5,=PN/[T\,'(F:.%KZ5;EJL_7Z`JYD7L;*D'\"?6Z<]MP^[V($0H0_&&],#C +M:<,]_6P:KGO\O\V`0S,_O#2[DE@'F71HF)0,EWVY4?7%IK9\`93K>%[ +MRA3CG0J-;WP=TJ^Z/<)N=3 +M\!D)%T+V-+SIH"<"/_!HO%#^GW/J?^T[(WAB*$P;KKD%],B[DH+E>%:+NLD4 +MA]37LAM7P!\@QCKN)![*J?"7A(GDK<95X9=K'9[0G?X((>"7Z@R2%WQJ]HM2 +M[L.NM!`IOX?JT,%CN.+NDNJ91/N:%0!O#&RL%>!P_1]6@E,B0:O(+OR,^[)< +M7:0:=3^_9;JI^?HK,XX<^04=2Z3UT?E6T9.CBU2F['/Q9#$^*%G66PKOC?X) +MX6==4(`H&)R;N21X^2.]CABG76_X3B#4QV?=3KN>4N9#BL^"-4]M6<7\P,1I+_ +M^A?0$)S@053CR7?7&N[+F+(CB;'R',49+*=DI,+JX4T)\J6 +M6RZCVAX_M0A+,S;1[WXHY%`O60.KON,AO_V,\6TNJYZ:7YRRX^?KK(?AT)[]VN=CER:]RV^^ +M;3Z0\<&;N;[H]L*^(Y3H1K8QJ$JLD]Y*F$7H#V?. +M5BO79'9LG.IR0!)R1<>E,\GP9U>PW8CO6/YF^?0MV&#AZ`#[T`$&$7YPMSQ= +M'0MPO[>>$U=D$^JE#K.C%J=5;XXQ7638_MNFK[:\H^I;GZI?$DE'OC)L.8[J +M@6G)R68,;4`NX>\W`DK(-%(`#=F01^\1M3.;'>P^(/1$VWZ!R%X,,N*<1^!H +MN:$(>*W/`^B5-K6D/PJA7BU`?K2J.0J7_QS?U:6$@"%AR&27I=F.'6/+%GK6 +M`PV@OZ:I@'T4MW5>]6_*+.FO;HF:KQI9V=@F'& +M=2=XA%K:(GP,NK.+W\>P^!X`],;,(K6+R;$[J^AVXJZ[*:"TR)%2#M4HXA7.BCN;^@IX>/`T% +MV;6(1>][A,I:OTF.GZQAIUUGQ(3$)7?[*3&^6Y1M&W-FCNA<1NY&,6AN*'"\X0`4H>C'`$ZQ-,Y9U",Q-D">//49DL8&K,LOS)GG;92$H?N^ +M6@P[;E=`4)&6?F%B+YIM^AF?YQ`\I7]M&',PJBIW`>I_L(>,6HYI`V&ZA:.2 +MA4#XATD+S(^+T991I\J%2!@Z=HY+-4-0]NI*M04)+V`58_T-LFS,?N>@$)!9 +MG>79!);N-,\&4)>2L^[Y*57!LR>U.6#.=`[*TU]R/L-V.MPN:(W(K3\)F1O2 +M*$-1H4`IF7PR`0V^'X5EC"^&XV;#5,7M@B'92%^7I8?:S:DJ@7XL($AAH]NA +M!UU]LSW-JY3'QXU@AAO8/H=K:3!I*+J2+B?V=-2V&]BLG)G0)>SK3]/$@BJW.-N_WVXZTBP#T_T91YA +M#J-86'DB3D]9@MK//?V5M\.A0E)II?>L\MHY\ZDFL0GUKU4E3N!;'@@&+KU< +M?:,S_8_GTMJ.M/03^+`M'*[>U1^&@Y=:]_\"&R4Y9,ZX0[[=E;+[[%`N-S.:2?J"K +MJA,X"><(F(T^S\G1?2:UAF1CF02Q@A>C(UZR/UR#?>HKLKS>=U7*JIL^J-?F +M?XOH-@O:"/<\=?%Q(B8PG,'`>Q22X&S0 +M`?HSP*IG=8IJ&!#VL,#TD@++V1ZS^@.[N$\(NRL,%WM>K2ZSW^C +M(4\UJMGO9?:@W2)/JV]O'CX-WK;[?1F!C[:1W45`B.KBVYB^]N.8QL/U>D?N +M*X0EYX2$-SG(NY?2RBH1DQ.QZDIL!G/S78(3H?0T;3M*9L5JSY4%&P45$5B@ +MOM?:-%0O0:SD.:8E[SIKRA+\\*\$JUL4/LM$,!S^JLV.RV\^@Q&8`'GB]G/B +MCM\(RD,9$IZP8OFFZ19&AR_=ULTH\W[P7BAUK#P\GV<&+4)C>$DL9Q:SJ-H= +MIL:LT7AJ"Q51LC]+5!?(&3,%^5%\]].1F]0YH.QC#O\SH2YSA7F);R):KF;TKR5R#Q7Q&_9[YN9.GY#/" +MGKV>(!/P\SI=&E7YY233#N7BP34.ZN[+)S$-8R+:[++K,^28\/[=P=B(M[K% +M$#X1LZK7,XNTDSH'L3.<#&+NT:@;&A6+16,PQ +MC>'QQC&6]SA7JFZ#;Y!R)R!%+DV^L_Z9W%NU'(^SQ(=K1RNR";R<+H5LVIMR +M`]"J:%D/4I>,UFBHR%G8"?].FCN0(EL*35R_F$([V=I)#'H:*"M19?W9!8Y$]U]%RYJX +MW?#4A-?QF26/Q"O"^/`DP=1(>LZK/3F1XYHU]9%3I9\K`!#=#>12/#E+6GBL +M5R+Z;)KLBS;)VVQ;#W!#72%="W9L^'`F"(]&,3(^B&S/U8]K]V;>\0H1'[-M +M`?$Q>4N+5+@X16Y`.-)K$7'^ER_<.G"1JZJG&LIE_![<&T<2]Q7,9?3(_[_Z +M1="TM'ZJ)E,]Y>/C/FG&0>Y=,_]36?SB^S876X_`2W<]Z,`9"K^3`HV +M.R]9H@WAIII/@]>*GJ3]PH@*VL:PK:33%>NYI[(D].R':C`W@P)I8!\G2-<, +M5Q0("A0!;*C"ZE;]8.8[[]9D]SL`\4_\H]NA:&1<++T"?\]B"1XFEIU:?7JM +MH-L-(]TC9->7;!N1O^FQ4I6;O5T8M1YO9/"78OUD,AJ24OG.,'>LU +M);_$HW&WVBI==$#WA2]Q+NH(84$NF_F$C#4Q+`.!`/AXE19HRX8H[A*R=F+""LV +MV%$AP$WB7\XCEEAH*V\ZB>)#P*Z4AEYZ79*"4],=:?.]VB7V=#EOAD +M@)>]?68PBG\BK<6JQF_3@!N85"B&WV90M)P!'$D.)9!?M5M +MY%^-F>72G87:.5E#L>3Z=A)#]8;9FQ*G"#YFD(V0K[UEGU,.R&/44/!&V:-6 +MXXPV\EW5/WI87-W-5![.`-$%E=9L)C#()B<3$Q`M&/->A,+HQ-[H/7LO<()0 +M@#@Z]=!HMLN3SZE]"`OZQUKXNBUSSO[RQ0- +M3P;[>%Y&[D1R",*OW1_A](N.#I=1HDO3FHO^;Z##Y)&`?*0/Z0J.?T)3,8&` +M__60,*=@=5(^?6?[G0:O$1W=_AX%'_3W(C>H3KA +M><4&'5RN/*ZP@'S_V3.A&\,6$?GUF3]ZJA%%M$^QFH,B^%%JV.Z0]H'I/T9O +M"%^S1Z]*S%PN?_Z/%?B-Y8B7;`\1!(OH*Y@X,F+'+'\[F+,:3M#$*$$QON%"^M`8,7W4;2TC_I(N, +M57ZQ&OGH3XN=N<^/NSWHG7R9W3X8UB +M9M):T0;7_BZ[4:DPC#`<;^AAI,)!_5U(]N,_"O5#'==>]39>K=%TG9AF>G<@ +MR>J[\N3?QB;F^"XWS-2JRR5D.IF[YR8C\K*^FK( +MNW2L/T9E?P(N`48'3?#>%'C84.0AKP8_'R%/[6_(T_U5ZBM<'5*2%@4"$(WGSX/1Z99*Y.7)CGN_,BO +M]Q7"USWW-7KG8F!/=`KL&T3#5`<%<>PU?>U7_WXU*J:?G-^@P`HEG,(YWWY1 +MHQL50:BL3RZ2*@.5ZZ&ON-S0BPP/KY?E@!Q6<:$"V'MB+0.*JZQ,*Q*Q%=25*,UG6.%#`F+].Z^`D +M.(W0H3N8F&FV5>[TSCT];RB:*V5WV7=B\S2WQZ_>GYZLZU#E-_*JCZ +MIUW'TJSP,A$I`,YEH*B!*.0^U'E#QA6?7`;.#53?.>UY:?]..W` +M.*\%_D>FN!7"H=/A(D@W%ZGWX,T=!G?6"66N<0A[(/;U?<3C/!2T=F+_WF9% +M\/``7ZK&`S"!*A1-$`#`MY=$UOR"K9WIJG]GC4]WL+0^##L.JR4-$N%L?1EX +M51HM'585QQ!,4M^.B>XQA6@#7;YU+>^D\&J")%P>.^N%/! +MR65*C_9%99Q2("3?'89L3G&5C4^ZR!.7,0I&)Q@\V?;;\-O$@4PZ"AD+\AG% +M:)IE+'29`)LU@#K-QH)VAO&:YJS*GQ/*NZ<8)[+Z_H*-AX)^+*[?;`:Q+B%K +MO^IPZAF:(6VL:>N`&;[62YE%\O#0,"Z!8J/0Q\G[^-?'C-S1"OIB?6F*E/EW`%[ET1-`7=."6I +M7(OR[Z'SV(TW?OZE/FG'`N!9YAY;>;=".HRL.4'CHJ%K:A7)%8GI^E44]L +M!#0$NM1S`=NT1LVCZG18<4O1PE4188PXM,KV&%U^<;HYBO=^$=F( +MZ3U7N[)!+=CPD]="2L@X]+8T)!F271%-LR>\8+;%+,-A5!=^ +M&E4S0/W-^DSX)5[__/"DCIV\H\-'5AH*/^VD:$N&T*?(]N'X +MA?KIF'=CL$SO+2$"1GRKWA3RDS4YMN\8YL>MA[C%S"@826PS56X'PT*4QCW$ +M\A(@@J_./T".1",VJD`'MZF=U%)0:!J1E5V>R'PU/(9D(E*8? +MOSU6,#JK](8`:CY;P<*Z.Y`EV_ +M8V2+W1J[O:)Q8UO$SC`9*L5QY#S?"JIM(NH].?Z(J*%D[+T`8![ARU[2X+FH +MR_,_%5?Y4+CR>[?]@AF]VQQ.7;4HV?WH<85DX:[$?#$P\GDP-U-W^F]796 +M[&N["W2LV"=_)NTL4/F&%[+QA\M0F&[VV<0/4'!#>R1ZZRZ7 +M6XI,VM8[PMA%,Z>$I(5I51U^Z):BD1`(1FI[\RW^N_$$&N1%4M"L%TS-]\4FOF +M,D9O@2(6CJE9PG='(DCG;H8[)G>)+_"Q +M%C6<\7;7;9WF?GNX6X>B3GK%=Q/3&TKFFK*HGC)+9+;%;N;-(>]SC1&K'ZWM +M'X$(PC&E%FAWIH=Q<*T)[?<%=MK=(%9**&G-(I*RWY[9SJSU' +M]&FMYVV-`)RBO0X/E)0,;G2RW\$)VR7RQE!#1?P^![;[R"74NC(2X4?+6]S4 +MNEUO5Q+<7#$E^7Y[TEHFC_D8*'[>6Q:H1CQA#L:AC2RRAM!/MS1%,1%V!OBS +M`L3D*VCHXCJ$TC=>L3-:4$])A?)UZ+Q>L%+`_$Q4_!W1!-74J896W1W\A*H6EH!;9SN7,@P7Z)9+B +MW:9S;4=DB.2(HDY#R?UNCFS%7W3H_A)'_O@^938) +M3HFNB^E#+5<23ZUF8$I'/*';K$T,@&$A[7Y`B=R'P1O6[S6]XNGMM`%5!MO` +MLP9W`L07X9J7+E4PL/F1^VQ`M\/"?J%5[,&>$ +M/#&(:8-!Y'+3AB'AOYD*DM+Y*3H)LYZZ<**>O5^>0A=@MF2C7PBD8N@/U.,U +MB#77B^--W6I/+5]W5%_M<$>02DFS;\?1VZTAX)AL",+P$TDBX*_]#_[(GWL# +M#8N7_YT!B/4B)Q`%\>)@*Q4`7Y2&.SBYC<]XAO5_5N>KK1:@'95<9/*D<@8^ +M=9>1W`LYT7BBRX]^7/FQJ_G4@0RE@56+*06;`=BO,63YR$U +MJBY9]$NV:&3D_>N.)FSHTT-7Z+*`&;`^'M;#%(2WFS)BDOU\A:[Q+PU2YZ(Z\:!M9-&) +M?ZH`?CX4I +M\S8K:<+;[`T8SPTR6!KOMQ!5>1?G#P&-+FS)36BBV6HD].*D#9[ZZ'%:(/LV +M3*(9GU4^SJXH;GLBF8A7I+H*.5+V<&K\_B15'>C^#,8,]8PW/<)`?"'!310G +M%IVB)!<(5QP)GVVI&^2.&GC8;#B8.R"6LQE/&]%DR2^ +M9=#@'7=(XBY2&63+/'8<2G>W?Q"T6?7`:(R%R#,3>2#'OBAQ!). +M&OS7+%T4$\%T:R?=`\==?`YD.IN:I)'+?`H?G^(N9J=1(462-+E`'N&*\/.> +MXR(Q_+(WZ!1%N;G:X64JZX@`A51BRFX>#^=K_R07N`F10ZB4W<0_=,!%^YF0 +MSV)4I[VL2GNP`I^&M_JKA%_H)&\5V!MNY]A\X/26-IT\QZ-*TM$2Q2B8GK'] +M)WBF+AQ_@>Z7]#XK0V2GU"Z1ZJ0\Z)E:/ZFV1#1;.)8I2'?'EQ9/3'*YW9B\ +M`/)YDFB[8+38$X\&;[M%HDO*;JT-QCVQ6H'V\L%;)@_EQOH#38`Y"RRS,9>S +M!0*#NY8">9[WK$H0H0Y*B@.W^QRJ0+!;C=/A3V[5? +MF#.T\DD[E0OXARC\L)&1A?*ZL2J-`191MO"M`;,"/121,(\3T'J8]_C$G<66N=E_G?N +M(X.SNM.4%,\IQW'HPG^^[SG"Q]4J,-]2^2+68 +M-)I#)QP2Z>`3OXF"\)-(6AOI>PJMY7Z0$RE0WSR$YR[2=1-5WIPN`H+"C;@& +M9H#V$ADGWH\:C(CW)8B +M*[_A9+$>"M]`MI".JZSE7%VM\W)0F/!6N\\`CFLG7X;6?T`_S._/68WU(P]_ +ML\V$$-S#73*2S7Z[,]DW?P4%M(^EA`8O +MN[$Q@D!71;U:2R!N+">!T/BH*C/;Z5S%Q*G$GTMG).$`NXD6X*?J17$C627L +MGT<^,WJK[.-=MQCD?RNKC3O^=5%;B*QFX$-803@D9QKX0IDPMA7YD/8F,954 +MU.999.X%4ZZ# +MLWMV^]4NDQV8"DL=K@NN2:\6:BAY;3,$04J\WZFJ$H\S)FV+TGHH2?'*MH%) +MI'?F,7USJ;;)*Q]6L]GT(=_P4%Q?^U_!BJJ[%)-;Y\B99O$AH85[IWV-2'#D +M1CH'W-$[F2JP#B*LO](\)T<-?NNO1LD%,XO29KZ +M%ZA=O'0/#]G87ROC=G.+:)ANTVTND\W#/`O/WM_XUEX,/B +MBP-DHD5"'?M"M5JYOFWSSE(NWK"0NU&-HSL7<1B&J_4/.0?$`=R91JH1>>3J +MC8["9B?A;0'(`D(&UJ"?.PV6Z5;S5G)2Q%S[W61A%$=,@P#+#RP9(J^.9J0L +MXNYP>(.N]\VR2?RB?W$G>)A"@R`A3^7X(]:CU;Z_C%13+W0R4M]G>`OFQ +MHK"$M0!;3;]+\&JK55F3"?=C1F'HS+8DAL(JBJ]D+(K#_-3CIOR\MT_LEZ2D +M6-T:-2-F7+<]'6R[,3:+J__`:Y'P.!V3"%GG@DR0=Q:"6#DND8,!@`<%`K]+ +MTO=JU1;7^.5^8_;&_4]'*(IPGOR9^8;/N%?@C<>S^[?)3IV'E,R.>:*/.$?R +M37VIPEG;*VC^\K&7`O?0UP;ATL[_:ZCTQ,MS:L'VP8OSU%57ZV[T21J-?"FN +M.7GH>$A]$HCSM0.]\W[(I+6ZZ/06I,/>-"/J\7(.RKTV*5%W@! +M_>ZXVB2'4C2R#?)\F@`>\;XUW!V[X=,_DK`"!)NUW\4/'/QA4`#5V@7F<&BO +M[':;C"!$`\$FI9Q0>:I'^]OM&5IOF=#F?:1RE[5/-=0/A8)K:J:>!.,19MO0 +M8I*6Y(\8@#.&SY739F6<"ZN/9SC^K)")F1J0SF*V*LZ1@T/N[M[/GP0B&,_) +MO?*`5:OL4GX7T'A66VK`XW?J`,4)[=&;\_&&AZX8XOY/1^MU)YP^`!Q%N.OD +MDM3'.;]M4J#GWM*29(0@9Q3UFKZB\_G+FEH?G,Q4.N@]E=\)_8H +M\6FIP+\$%;Z[5T=-TQN#6B%X%IHA"P?+EAS\*YR!ZB-268^PF>)*L);Y;)_N-AKS^I9`N%Z3W+GGRA$@LO:7%!?CT&@YYS45N0)W6)6264V?$'P +MR=WU$85FK/7=S7&12G#JAD6WGT9JTD-7VI*IDFY2,KGZI]?H_XS.^QGBI-H$ +MKM`!V4]D"VV0\`CJ=Q,9AOI;=$^5;P=RAGL(#NJ9V\@<$B?04$ +M_=2N)5BJ_;. +M'[*4[K#$K@C\!2-CJ0@Y_`2!G>._M1!\=7(Y?/ +M@AI!,.,#)OF1%_NPTU8ZH\5#K*/7K8O@F_Z^F@@>%XG]/$<=N%LG#QK5QSUT +M0J0!$LJ7>]]F;7[DM0YW[-`=4W#N43GG^@%N6M8*W8ZJ&C"BVFC,UO-DQQKP +M)50F9"(YI-0+\3$78QZY0Y?XQ/`^4D4DM5NHH0:UI"?A$YZ7"1\[.;\L76.\ +M)O\70"2X8-"WE2=LJEX"B/))K]M=D0!1Y)WCS6?*=;Z)5 +MER&C[#4T^UO5CQ@/].@+)'9_W1D*0X$5QS(= +MPQ$?^"N$]X1]J+!1OA,L]'7=!YF$X&%R28FY#/0(5B7_'UQF'`XX5$@WV1EI +MXJ+P^$+9_EE=@C<*!1F76X[/\+G@-[\LZH)ZOF*>4=PI>GF)V33]RHEX7K#E +MAUR?-K(UZ_^#VWU7OX;_LNZKF+Y07K1F&>X-=#@?#BT3N[KC"VTG99$F75MW +MTU0U$^V!R*RO2`V=F2K\CLI%O]!!`%B/BRQ\\BW"H.<-I%5`?8?^!@IV1<8B +M3WV6Y6&HMM&V$B:$-.IP828*I4D3#-CV`$Z5^5'#[`3:#R%-B/\BK`=4?DQ^ +M(=6=57N@UW#FDU._7!Z99]2Z8[1HYK-B73=Z$J(R":[I\COHI$$:JQ`,44D+ +M_R[WP4/(6_^HS4<7P,^(&,+'&OIPDC/^#!UC+%H&!:RS:7/L=\/1A0^CAX]@ +M^#V"P4G.D_("P`'QL:13F>,TB_YCAOEW1B& +MT?.2@AY3X`M6Y_;4*!&9Y`J/XD,X)&0#O9/55-V3FFF*RW+)YV[]^/"?C#0R +M6!I1#>:/DD;#9E6]QI:;480Q@8MG?27LFYSV8:;&4?23NM)H-%Z`07HGI,#+ +M=S(JE!?\TJ*?Z3LXLXLL_]/3`G6T7E1`O+X4:K0$>#YCFP4`,OX[7NYK^HUP +MZZPF/IIE+/#8><)A?U2E=3+>E3V5I^7/[&?!T2G-I.6AY1CKK9`8%./"EA+IO-,"/` +M#6(B2J$:4:?T/D'8A98X734,&#FN[H#>;7]S#X/%18PNNM/H8+NLKOQP\G`] +MM8X@!>N"?0F1S551[0[[9X'X4>_,XS^C[5*7F(94Z0HODQSS&562'643VM_% +MWBK[G*]'/H3FVQ#T_Z=:4\[*+ON83WR'_*K'7"-@IX4C,II"#"04M$=O)JQ= +M(G\^?&)\.9OIE^FH,[@1KK5-?N=!H_1X&!S4631,$.J-BVXO]DG\DQP8P6FD +MH0]T3!MM5@\_\,U2R>ZCTZRKF8N)E0VJ&HA-D@Y> +M&DYFX@$3I*QUVR[+4K,6#[OVY/K(-DZW36OFN=\&<)(#DH2#JB9_`<4E(]7< +M-Z6SHRH4BQF>-K@OGM[[U9V.0?QII\:9J&;L)J^DT:DW+KE6KAE=_43Y;"7N +MC(3W4/Z'IUQ3M?=96JL](-CYY'X,N>G"86R&\>KE4Y;.@214B_+3>0%C42S/ +M?H#@CE#'3VDF?NWD8CL1U/KK':!GL2R9Y??(G2[R^A5K2Z +MS7/,B3T`&(;F:SGUE+\-1QU>7T07U^UJ]A1T.XACJ.-W^D!U%,HJ>LJZS;[? +M4"^XP@HN;B9]#C_]YX#;GHLZ-XT&)&R^9:QF@7@QB5@TX-3_W%#\A\C(C64R +M6>W?,S/7N4/2A1Z;C9K_*?85G]`I5RR!=D%+W;L#K)^O\!?X^?C"A]HZMF5F8%F?.W+44%B<(*N +M#9>S4KRCGS:K)-6'FBD$PMCKRKQ&!>\&&*/FD2S[#'ME*81*6Q%3%H1[5H?$ +M%USY-WSYSL@KN72@K;$]!I8E1>,K3T-V4Q^/6`ARIA?P#&*);/-_9H4DV/6$ +MI?K$]YU>3_YZ`C1G`6-E^,W+3:FVQ_\V[VPMUVQG/AJ>`-5Q"'7S5;&U9)SD +MK@?PCG+WSBLQ*'(A:S90GV3U,XA9L]/!G%2IT-CZ'AB/8DYCLTQHNJ.M#)C@ +M%0=BCHRKM6G+C?P]7UBZ58L^H,2[T"]UHKE*&CD!LKK4.DC52E"@JB)4+*Z: +M8Q^;B!EF,K>L/QDU#-\20!H)^>/E,ZTY<$^B<,X*")VN#6?[^UZ5DT_.4G0X +MC2`VS@)&IMB>W=E!`!PK+BY.;M:*S<5>X7>)\;$,NLHDAYV)OL/VE_*?^C:* +MQ)/%C/C"`B;_TC:4G&$>#4TR +M13:0N8XSM(#)?-+7J+,GV57+QZ)5ACA=J_NT:@+#?<"VL?)C2UT/OH7+#1S& +MM;8NL/=D5V?D9_EF"B.Z*::4N`XM8)Y+LR>!;"!H191R@;[$`J[R,]2GY7/@ +MHE:[0X7`!84M]1>7EC1Q77[VS0RL`IXMY!'2SX[-(=X-%#8EW=7EJ\_Q=FOI +M.9KK/8HDR1BTQ**K_"!W[9`BQ<#]^^^)3BY(^UA0^2"G+K@$'!/7/X[O]']H +MXA5>:5,#T>)UK6B,#=[;-<'/SW>;%8ZV/QH#<$NAW0S&`-CDS4BOG470SIAP +MM+UKEZ0?UP-VY5YL?>N_G1[ZCA9KAM<2K!<0M)M_@EDMB0")""NW!T@+J/L^ +M*S>:/P>\W;^^KX,-JE9KD![96B934_=K`Z!LM>W)BI[K:NHNE+$JMA):<(@> +MN!:[]+Y1:L4GS"6:,-\/AIKN,X&T_5'LG3/F6RK7MAR6_8*0(7R7J+.J8 +M6/$/(Y@61'KA-E8]PF-'44#W*=(NLT;$!0-KG,1+8=(`BX+:&=D7*GT4F7!* +M#VC11&%_ADHAK]T"=C!)F[:?=\6.L>6A11#Z9PQ=4Z%2.0_L26_PO1`77$F3&=9$ +MQOI&ZD3R=:]/B(@]/@<\84::"Z-6^+^ZC0,4%=SJ_RQF*-">I5%2E>.FJ)&T.OT>TM,H#)J^V46I@VQTUHHO=-"$GK,0I^ +M[37[85\+*#8A-1VQFF$[J42UDS@TDRYX&)_TJ'@4-#^>@XC-GQJQ%[HV*!'4 +MJ+9=/$3I9(`'G:(;C'3WF=$'I9X%L2G_89SK:$W@MY7<2.&F7XT)@(D..DYG +M]1!3JK"KC]NU]RV7^G;Y3'IWL1.QP/5]T#!U)2/,H]/=5?:&QY!#I9']'7/' +M\?#))?\`434)Z:!E43XX,JDW$[K;^`S:)B^$3+9IA5ZS&6;MG,]C%F8<27#MA&FM?<5$&(' +M"6PR*[VS*B<923W0\UK^(;B1`S?THIS0;Y&G*I_3>1JIMP9-U]6GI_UCSX6K +M%N8I?MJ.%$Y\3N]$#P/\F&Z9"Z`=MCYZ[FP3$A7^'MN@F]/^.&H:$; +M]FS\>L8,L('[34/Z"@6R^L[+2$7$;ZH$]=7 +MG<2D^=&V/^LTDX2`(?/1JH`=O%SUO06B#/M7%KI#NF4 +MVM#WM[5A.>/*,@6C_#@Q2T^B%BX!38@*^8ND9.0ED!^2:V1\1:W +M7/M2)!K5+#7&LY"/K.4;2:^)+A:*KM0?"K'3^Z9!=FDE5H4[__[?=Q'M0E-! +MO5K!MN9$XI&[_ZCCSPO;T-(+\../IV0 +M5NBB8:%3S&@(QL\JLV<"$@-SFON@4$U_:>M:#+V?)' +MQ%147.'`TZ3;KIS^//0FQU$7#EU^Y/]3L8`)S/,]YOT9SS4\G05S/CT%U1$H +MU0"<8IJFM9.FYPU@^ZG7X#0SNJ7&V7"_M]T;U5K_$*,@"6^,'FX7R'IJYGV0 +MM@'C6BH(^7K+&PKYTV>MO6>-+[H"?HL&^$!$JP.K!]NULIRP(MWQ"N.811U! +M`_3,W!#7&V+J=_/AG_%U,CU]I^+^1!Z=8=0@W;,P84$#P7JKG0(/VG&8&0Y= +MTUHK3N[?TW"\61BC#5Y3NQBW8KWGTY>N#?!HRKV'Z +MFN1LRP0'/2&B7UE8E=AAO,;OXH( +M$Y^U9RK(`29K-\#X,.^7A-.AZDP:A='\:Z-%=6KQWG%Q-ZBE6`:O$WO@J3L8 +MZS;==A=BHE84"`HQ]="FL<7V<)&<^C8!H9H;5F52634\&V]CA9@[H?$_+\=E +M21^.X=LAL0#%H$NK=?_EF.#7_VVH^KRK4_<==?B;+Z=RVN]$B;E^)HTN%;IA +MF2%4+S:2K@8Y^]%U\L!ZHNDVL?JUR78`ZVU-S/B)3!M+&N*TZIL5D:9 +M`UZW@S%5IU$*=YYEQDOCE?_6P+U\[1?P_>%^U]N=/TAM#R>133T!KBQLF1"K +MCJO#J;O(=O]M8YRJ7I?Z!GUT2A(W.P!I&.[=YGI;L;LP_A0O\>7PG7(G.>9\0X%/D[9D4GT]AD*^UO>_4JP.22FQN&\E/-!O;4E7/WPP*GH'A[J/)(R)`H(">I;_-J.<.J +M5`?!ZLU"AH4Y;;SP!_FB^]>><9^8B'&*49XWI,XWO2R"8^XO%)N)H,.=Y*;9 +M^@O$?":OZUY3D_VFZ<*+>>CF.MQ!7M`!3G$+#-R@N"1$"NB2#JUMW-[&6IYU +M*O24C]L,O=O6\8=1I20YU1?KA;5`VE4:-W>& +M?AZUNK+1Z2?AH^*((U)8+&K6.(_K'22!S+[4':0`Z!"Y*E9'BY4C*ZBH+"F8 +MW?>)Z];_J`OV8"J:MPE2C;`4$3)0=E0?YKP=LI6[PPJS[]^)/OY7\.]&F,9U +M*0#Z)DDS]$>60#[-C*ST%",N1*$SR&R>=`37/<0]9NVR55,EIUT40#8><*&G +MP]GY[J@-6*C_"&'I?&.UA"O8=1WA,Q^+34I-0)8'8YLPK9\R%[$;D')-V&=5 +MX+(91.RI\1]O'12L>;!-%,NC("2.Y7]%-;SHL3=D063C7<0T_T6W./3_^#+U +M"I)MXH5`PYE-51,B(-91XSTA'Q3I;@*863`%'G+ST9;3AMC8I)9^C\3F*14U +M:.6L'NHFX:>XBX0\HE4:1\$UG&NUZ$*J$!1QYA7>&^` +MDU1VB!B3^`3U+`T7/_0N9B0OI?\SR8++H?QIR(&YPALLN1Q/FO2-ML03.:X0 +MIYT3$G"'&9X0"7H2'11G;/X(KK;:7=?0*$9B9.>G8Q8L];%5WV"4$Q-U%(BM +MNOLU4?.V$5*T<9QW?A3)/@N# +MXH!)R!,V>)ICDF=$N>P[-R)2,/93D_!`%0:W`87X\](`>=+G!O1HDH,WN`YI +MC[9TMA,C6,13:*OELO^_WXSV!8CK$E[AE9.;D6A-J$=JR["[GQG^\G/N9(59 +MJ4VTV=S7I9="WS<\#8UWZSNA@"K>9P)+93[B7CUE7M7X:8"[3D)4G18='G:] +MJX+[F8JDL.O)99B8HH36S0O6<+'ZD0;9QW\$Z6;);XA>>X"`A.=W(,@'#(`@ +MP4YO1%^P;50'6P5 +M9@63N4\11OM5Q]V7S:%6Y; +M=-0L3G3>1\V3%-3X/YJ9N+RCF+85,P%JBD``^`&3NAX1JQ3?HL4<+#QOFMI` +M$.0!<"P6$`393G=%J_RW1!@#$LT]<,WOXAKEUYV(+\Y, +M(30VG*9!4*=:M)C>O4XP(H_S/77(&9_*_H1YAG`NJ<07,%/\4?J&M`I\PM?Z +MSJ*U&\GD]/C3L?UA!T!+&1G1!(OPS=G*M;40)%(E-C@Y/VU%O'S63"1!] +M"=+'/C',J"&\^,],M.X.K!7\GA<*7X=8#59HLZQH-O5'76`2DXC>[LL[2G0M +M5LJL;AR"$^(C@"\HUM`G%5':(5/F;.+=+-_IMLL+GMWS&N5B(,/L5$2?;#34 +M/^NZ8U)=X>=[\'@(=UT)(F3':9G;X]T$'Q3%`K^=\[ZE/;?:DB_0+M[`NJ2<18'"P!*H.F:^&7F%NF_KW"!(UEGQ;>VB=R+/]K\90/WT4;/-HEI5"E:HL%B0A\7B^ +M.[Z20U`=1=3R-2O[F\^*[;?EAK:76#/]`$[J)8Y2NZI:.,$CF<'1W79[TL?S +M#71(76[23/V4VT[A,":.,1_":`S_D-3>11+19[I>DE +MQS<_!WOT\6ZU9$&?9":Q"+D$NC7B8K2(S,)5S3/<>A]T%^7+1X#*BSLJX-QB +M)HR842HTYX+RA7F8%C>V.DW)!.R0F!>9*/UZ%-EPN=NKIRU3=>,0I9>[:&QG +MRF]!]3_8'^&E^2%'FT0OE!17*`Y'&:>W*I),=Z_DKN`)>EM(QW2\X5HTW,C/J)L`HVS"B"6R)]NB>V+50: +ML96=SSXC&JPSU.+1D[DF0<5E?9/.H, +M=;RK4$1A.UV78HF +M5:_E9GBS9!(:$`9V!K!Z7U6:]HO:\.0KCZ0GM3;(/#->W0J<7V^=]U++Q[(, +M;9,'O>]2]U^Y68"9IL>VL.A"C:/C@@PFL/LL=B*\A"8$@2L!+7!VOD3_E)>4 +M?3@]I@ +M#!;=BV&&``:J4\FJ"C3Y_Z_@$AVY[P>@3=SE+) +M>7\+VF\T%%GA&5Y;2DQPAKH;&7-HYHB)^NU*X&(%5"3:;LQ5'.L][2+M^3*F +MGTIL%K:*20-A]KAM\.S\Z[KC(P%N#G/J^)'M"2`?7!%I?XHFG+:-5^H,!F8X +M)]JH0'_$@<,3Z@*O-)*1AQ7COZUIJ)SAKDA!1JV_>"-._@5T[A1A!N@"YSXM9%0S#1Z6R;>2.7-;6D@1R0($ +M=(V]T3C+1Q)('/+]LSOH//D-]3SH838;&[[#(RQLKC[1QB7L-^Y=X,`=<0OQ +MJYA'SV'6[DKV01B*9(]Y9,0?8"2*] +M;<6_!WW($?NM20@A.)TJ&$O`6OT\I#&1GETL?ZX?(/RX26^&O5SQC2?<8-%[ +M4SS&6QBLMQ4=!8VA>4I"V?3A/G$J&G'3(>'1>("#'_V9JXPLG,MQKV9>`'?L +M"`/M#8*9Z+$XFP1+9/.AWM-">4+X0>:C]_KE^(D$LK["C_,&$J,6#A4@1Y^+ +M%R)8JUPS^-IGYC(L8::/!`X77:)RB'N?PO.?&BI5RFXQX\):/?%$TYS4TVPY +M,G?L$&L0X!"T>3O(L&*8L[9LEDF2>S(/17L4 +M<%89&G+N))LL8:DU>Z9TZ8+HAS>G:4!R;\%5BGV/V`'@X5OT,Z3/_*?+KPPH +MK^R_KPMOH!%*.LXZ2VJY>K).:H>DRI6(Z[#)@.+9XLY99O4WWX7@G8X7BO?Q +MSKPA%[4'/CI4?\*Z7K8[*>&:]CAD`WR>R*!^&/URA!AGB +M*2HY!PLIA"4U:'YI:*U']NRZ5[N*N`>'-"78'>S6S6%9%;G2*A/2IHB_?::4 +MKCQRZP8]37:&TS[LM%+RTH@E\FLBWF^^`XON'_B94K'E%V\1IB@'(/$D<;@+ +MXVYO^-`]GN`6:$X,INXFR'RFUFS@UL)A9:)`<7%,0\SQ(^Q%R`8FI]?\V3:! +ME]^1O-OS8!O;XCZM>3+.MI^%&`)5Z[3:."NE[NV<#M[+U7[`0T11_C4"/!S: +MOB(;PJ`"N06F6LVC0R>A(Q +M%)WXH6T`0Y]@;X/N>TCTL7^*V(:-24`Y?R- +M02TS@F(GM^@XR=(HDDO6NGPQA`MC+A@M>&`!$/[A(6>T5[P!!%0?X_RL;[A_ +M6ZU%$+#?O^"0^Q\1>\NM2Z+1C0S;DRS&3#A*P`D','GND9?O'*/KBD>RD=-S +MP4RB3I#O`&"UBQ_4*!`%H;28J,,H_ST"^'Z_1"X7B(*BB +MF%QS+P\*83@-U1DAA.&G^>]N[1/R?=^[#WY-@[G8]T5,`/RBAO+P.J46F834 +M_J:>X\_J=G#I('U"X5PJY_+E^_N7&P$1M8D>^Z=K4",R(7:R['H<,TQK[F^- +MZ.:'6/,1Y/-2?ZYIIY!SE*]]XYV92RJC%)G&=USD6^3R.SM)!4=8[F'$OL&* +M?LK+59S3>=D-7DKG4*/;P$0;!,-JF_\6C5:`6 +M!N^2FW$27F]F90,TC@#E6$""\!V-&9\.$?E='4PY1,S>'Y7L*`(GCKG_Y"SA +M'K@=F`%&\PO,Y,?X6[77X\1@E3KX0'7^F%=&KI18`Y)8TX(%3E($S[76W2]] +M"F;*@(>(#+R"2(T!BDTKZ)?9G5I4(>3Y+W@0LV1E%?V_9?EWOU*FSV7H[I*N +MJIU%0_)9AUY8QD+W7)^K$Q;T1P]-J;B9,BFE_:%N&NGW3_.+$JOX@,L[?!#/ +MXEV4WMFVH%$,(S_&D'O3TJ3P+"N,""`4UTT)WNIY=8M8EY`=VDZV6E%4#;J# +M_)6^11;NVJCB4ZP--:=S#9TH?;,UD&.4H+;K8)PW('`R0V+/2O"J"<$NY>Z1 +M=@DP2M!XWM2$S[E3R6+OB#2!'4ZJ8'T<"+BN$FZ?>:\H6V)EQ*S,;WG26WQ: +M<9O.TZ$F2?>?!2L/$(>VQ9#>>6GLL_5KW:T7YB]US4`)_YQB"JDGYGWFFRI@ +M9-VU$2G.56@+6EG+W>U@)1@[0%@(!ETB)NEL*7T-45LJ@+4DF)AF4N=JS)& +MXF_RIZ=[,%^*#YH-DU?3B>)RQA"D*B9Y"=/5`P=V6I%\H)8IBL6_E%:\F`]1"/ +M>E;('U0&&'`@=CTX9 +M[W[:E1X6ZPW0E2+I4-*8'ER)1P\$6\X?P)WD]2F*R[7'?L%9(/JG31,"2,H, +M)FJ#YU"Q.+A:^1"Z,.D%2>6$YP?&MY])XH*W5=ILL3Q]"^[J$;RGA06OQQ^K +M6*9*9L%XN"5.8Q-ZEQ57FQBSZ87*Q-"-:G3N$^6M,W/.P2#6YX%MY`/B4$A^ +MPS[:?J?O91NE>(BF4]5Y*IKFN%-MJ$'-N`S\!"AG0Y27@#--]VV.W^EM\H!? +M(W[DUF1=B[++=,4H[)SKKA,)LF",AAB5?]0[;A09:@/?J6%&QVLG:7VIB[?# +M2?\T5ZUK<<#[3]29-+I61@)(PT"&5G!>8UEG:I_;[6=`ILNVQ04/=!0D;%5N +MES2Q=>V*?)Q:0COFU80R`.Z7S+"X/UF/O=GSJ:"$C0(>E"5[75#3IO<['"MN +M(K+Q,9CTSP-<9&/J%X +M7U=!Q<7+K#VE0'^84PC&C=-KEFVXZ@J/&"-$]=5":'=LJ"T<&+G,;9'+Q@Y* +M6LJO644#3<$,L#]DHT+3!#&MHV[ +MA;EL,]O2$&J4'CQ7\)EFTI\T?C@&*T$C;84&?0NCT)R4;YJ`HMX0?X23)RI: +MWE-(=L3R&3]-<$G831U*-N*\KO"#?VF!05,"$*W_)`@K8AK]QL^,#/#CT5MN +M^)=SH+-_"*14`G3`O9D;GOVC3/`]9F>2%J<;TQR"H,R7GQC(VU%V.&Q*=K.( +M(@''%7@OO7V/TR[SMY+7G_P(W^*%-S=-TB(0V\M=]%T&Y2TJGLF +M+UT8-1OV4_=/F]C^RNL6(BSVYXZ?VCO:E9I8?.@TAJ$>*L/^A+3&7'P7[H74 +MC.9D)]9S5$"5=8U_&B>0U^\]2[1;H&F@DI#T%65:#M, +M=3^XM6.\:3_?Z^7/Y6J;TPE0[);GU`4OG'C5*(@_:7RF2-;&!27,WW>V=0!Y +M6F1HNAA#B*V^#Z.N50(P)X:"^=;^J28QNTUBWIE$"?"U6!,/6FO")),1\#PW +M=!_2^V-AS(L,<:^%DFY;C4I0#LT!_OZ(">Z!!#IK@OQ2\1?X1NXD_D\\?:_Q +MZ+2*E9-^82NJP.QR!T/5E#S2/L`*U@E$<5*AU>SSAU794Q5=1('T>D8^_,K- +MX@>(2YO$HPD;,[,%SKO9M;K'T2?#LN1QC-[Y45U=4?-=!&^AP.=`(A+P$.K# +M.Z;SB_8E/B>W@UL+@5P7;=:_"@BIF)84,R](!&%Y56GKA1IR]@CM+4J<+VZ" +MVG6D\%>%D(T\O!G#W@$@`/U:.PO.U2"%#^!.NQ:*PGU?$/>FTD/PP[M\33J< +M'$G!;W4HWHIN*-CP&7&6*)I6N97(\18G3"2T9@X&+6PTX7#RWSA3$$B7PA)Z +MI%1<,8N?;Z3$.,_MAC5+CW"8WL8W>E<*BZ"+,9'C+DN_(4W>,H8PW$0FIO]2 +MFB&D$EO=\THOTQ'9H[[1*6Y?!Z@JJ9%QZ>9ZW^$S8DIU!7T:ML#;`C[KQPVM +MMCR7]7B'V0#)IC#/M&.D)_X$;%]Y0!_&8-HN1X(*O8J=.ADA-)%X%:(9TL"= +M6?0"R!(3CZ>:5SUQR!7DRH71$QL&"CS%6^"EAR1KPB\GV60LY"2CJCUU6YQB +MRC.L#_S[3BF^E43D>A^X*`V@D'018Y[CZ9V-`D-%Q;_/&#B*RJ#PWAE6OWK# +MVHLI!MI!.7XC+8!&ZJ;LA(^9^R=_X6CW#\?RLX*:]JYUV4@Z? +M?.U=:0<;[RRP"V0*R*5,R*$SU!T][2*??F0?'-'OYJBL_9>G,;T8`*&9 +MO'X:(9OR-.MW<#T>4S[_+<-IKT8U8^IPIS>KJ$2P]+P^Y/[]:8&Y--K\BMW4 +M!-?GR6A&;?KU;O5<")$*?D0=F@"PCJ=.=]_J,W?8.V.NZUMTCKBOFI3&L]5M +ME.2]4<1R=V#5'[2!>M-"&,=_&$67K,4:K<0#\V'6E'=O?[+N1*&5\H\%XT+) +M;_*F#_]#IT[$W;^:9J%24LW;I:>>4\6X$R0B8U9MG\X[BN-VHG5@S2Y"9EU4 +M6KX:Q(IY62`F`4"3WQ,&R-(3J9)-NLU6?IBB(L0S&&4O__[&KY>RD.!L]?%U6E5I*XX35:/.0;/1R8]>UCWT +M_Z'I!1+:76QW;[/,/KZ[D:S.)NC.02N@A^9\F#Z63[0(]FYQN#HQB`JMU&I< +M'*6!N.)EIC`J-CW!Q4,%MJ\&],L!/(BM4]K$\!?G/&,P@AHIP#5IN_F^JRD, +MB^;)ET:A77NY;Q*09&Q&:RL^W4>Y[%L2*`1-_9TGTJ-6D']CVW9:@5Q>#\?S!8:L3E-F-U$X:&)X\Z>'(&XJPNYF0V.BBK +M"U<\*/K5Z-$ZT2>4V4&3!SA[[O)S9??L&5XP-I6M#2&MU0=7VZ$@MI+;F$(( +MOOH0VZWY5/]'A'9[!AFW7,&9WW8C^@IL<(63X>8D#'KU4*WYUP>3@&I"N7'F +MQT.I*+!22V2)]4?X0(=/$15\,WEO$ZB8]GJ +M$BXI#PNFBK`W@>/[F,CO>$%1&'W5C.[H>TWX[*R[S_FR68_2WA,/-68SRP$8!9$GR.SBW)/'?<,:Z=5 +M)+L_1;NS-L16$?@^W5/9R&$(6:ZGGJ6J`FI7NL''?H0?BK3.8K,3U1SM@Y]T$!H,KJ%R$<#2AF5N-U"`9 +M;DATB,&&!"GHIR>^26T3T=HA257.[ZA +ML$#:F6]Q@%.[/.BJX6:_0`DZ49E/\NMHUV:T]=*F;(#%@2[#'8\"?_7ZH];# +M-7(W`@5-D2V8FCD2P/P+3K5#&T"FZXK$I_C!7`/JER<2RB>7^.6#\'N/24E/ +M-W;7.U*F$3+^'5([RE1EA8^$L-998:5) +MOYX?<'C<>!66BEI5%((=%3P4`__<_A6&&*`,M2?@--4S3I%,U,J,9#T=O[Y> +M;W&:@G$9>#[J)_OA$R+(O3;U4 +MG&^-?-2YBR9K^/65U##[JY03%9#>!'H2/A74G!-$]$=;$>_UXZ9B.$5UIQ$D +M."_`<+H]-]S%Q4-!\\5<36!D6A:2.U"0$>GHI#%-]/70D8IDSCTD@&6<6'[8 +MT6Q?:A^3\;:"C;?T[ +MO);*M(52[A-'#N`V(6R&Q*UR*HVT46+Y>Y5PFJ@+Q_BV*Q?WD=1\[&O\`;5T +M`UJPS&K2R"2X%^F7GK^[XI>3XOT/_>FIS!&#-O?\U05-0\FED;5J!>JM)7LK +M8B?VCI(?AN3Q_B9>25@ +MEVINZT!=2109;C2YBP^H2WJC"(LM,UW<%8!XY5<6#F,]G5V +M+54/P2>R*U`_C))M,EMJ2HGHX1]CE?`0[@A,S8K'G-^_5)O+6FL0ZZI^HMMJ +MK=.7"Z@Z9&%Y&H)_[XI<]R1N6=+:TX;N(]5L"50ZB8^;(&_/3`'+#UL[]M3L +MYD%L8LCDO@US4JC53<,?_5-:1C1O`L0.`C4=#$!LD6:4L>C^PI&#T72 +M;%QLP-<>"2Z@[SL_J%'Y]Y$^H\<;_RAOE%FCX"6TL[*FFML_V6DW"DR/Y=*G +MT*\9JO7+YVJ8>/D#?4$\=#TO5JA:41R1FX##^VE:I073)-5H#?#^HAI9?SAH +M:@%NOHD"%`0CP)R+*O;VDTRK3:T/-C[Z`A2M=33EN<4F#V]R&LGPWSJ8)&]? +M=#VCP(.%@]_0("HS:XL`8Y4A,4U15K?-'?\ +MQX=NX0ES\$'6$L*+>RNG6O/:RI^:;Z3V\=26+MO<@BY(4^.`D\P +M`1+Z9_0RL4B!%C2EH4>@@.Q%0'48S[FAB3G]%:C^TPX$YL,!D#$GT^4].-Z? +MLMO;KQG6BRYBNE<&!&I8!E#M1K&D6O1N\Z2P-F5O]CEUOJEJC)(Q[3#:#J5W +M>'GRL16F4$J>9E`WDPNZ%]EQ35R_=>9O%EDFGB&$J9Y2W]K5:5M[_SN4._WP +MOI.'961B6;>YZO0]+6+6W-R&@V=9KN;T:,T7F^_B$.#P&JKP1\*-TH,:' +M4^RA*])JM9YH'HV.$?R`7.9M/^D3H$T("20I+$!B>Z\&G5.8BT$?72*ZI"4V +M`G*Q87%W7;>=G,:V6++,D^KR8C! +MR=,YY7BI2]]0-ID'6->U?=YMF#G9_K!\!'9+:_X7JBO9I/U)3WI\X2N,&=ND +M2LS.O*=@,YT6HQ2E2JIYM]%3[KVMM``,)[K-[JQN3GE@KR'1,%)VMVNJ>*;W +MD=(?`:0M:K0;#=)G(.*HC"?$5)US])!A/)XG7C86HO_.<>1D#/JCAT/G&7[F +M&53S)6Q8T.=!EM_I*XZ0E4P9+<=_SU^JZY8FH^_#3-<\MIZW3XI\;$Z +M,_A<<#>+L]TI,),_R,W_Q4A.`3'P-RZ,0J=((;T(:9?)HP>;%24&P+2]JXUS +M.(ZL$J'X$169M@4DOZUA-XT[DX>HZ-!'CJE6=`!!3?'IV69+X&E'[`1& +M<0[Z`FJ%J@_8U5N&6QUEF/5HVQ7`K,Y8$N@[G[B+'=!)V5G&?J$5TA3H(NPI)!N1^OG"$#M],_'I^HJ01R(GCTX.2)?>]'Q(1UM`6&=!@QV2H<4;<\ZX$+HF1GO)I^&SX/13GB` +MK%%M_:33*^>KA=*Q;.#MOQK/<)D0!S>ZVDU7BM2R#W@S3JZ24.O1),\DPG5CU*"7FL9=LY.LV<\J?ZN+<"CNR8,,->F,@X +M+L'GR`($X2$4[.2Y$#B?O45F>Q/P;Y!.UUGI4A1\ZX)I/U;'2[L%[7?6/=^, +MR+#^2GLMLZ?TA/81H-6@MDT4@BI\L^W'7-X>#6)&5<_7[>%/EEQQW4;S]M.? +MOM_/;G8WBQ7$]REQR:TN4V/KJR%@8\&I"^<739;LP'D,+JOCB;D^!UI9"F'3FC5] +MF\U&SH[,:PU_*D8839;BO)X6I;*B640;1>D]M&:*$OR#46MOR!_Y"K>V9FC%3Y%)@4?) +M@-21U*#P2-[IYR)A`NE>'?>L]K,3)2J":@W1/8*]BN-I)5RMNW,E9#)`P1,, +MZZ6%&R__[UH@DT![$5XB4^R+]SID34[^!8/=`UAZ8/;C"U8!X]Y(7P.HB^:H +MR/K\O.$R9[/O8,MY8.5M:]`;ASE>`N'`\I%>;A;S7U; +M9;.PY4S1/B^F43>V4>W++U;LD;C%L0*P^&]%H_VL-`&[F"O\)J0.Z@"@+L-G +M*!84*HKOT3L*=,9D38P_NU8QO1%,_(]T6+?ZT3GJ:?1I-ZY19+U%C$W+4AT< +M`Z<,.(_X:X=9.?0&]>O/=96;,XOVORZ\B?:BZR$;&GO9H0@@W.3&%.@)#;JU +MTQ'KO'40?)_B1(<+A7[=(Q'!?W%-!'/!E4Y5-W39+FBT<^]URB&`[&2I[24/ +M/RTKJ;U7J8T@6L6+PF5I+]^TLK%KN@+"D$_34$!5E$%#?ZX*PL`."_OI1`S# +M6^08&A,=*0LB$X[_8==1=G#)!\:UB1'UUF +M_(E526KW%Z3%CSO\*AK/\=K(U$/>1=;,/`&P##7#A*-%62.OYGEL4:/1PIN> +M,2N*$?$#>;%B@U`=!(S.&/QE?%\8[(NXD,\99164'[" +MTR*FG$<2XKLUKHND"G>5\!&!]OQ]S2#?,\?X>C^$6B8&1B@J-?ND80?GUUP! +MHE[HRUS;B,FWC3QUWZ'Y+W!LG%O=H[/:D"4(,Z%&Q0DU0:H6)(1)DR=G>C:@ +M:!(>14HZ,O*ULT@(E>IQ"OGZ)MGI3?*!.6P9[KV+O=U2;:L6$:PS@7AJ]B%& +MM5"34?S/!)*C0? +MAARK&Q(H#6-;=>(E-"@F:4IIE"^X#CI*G56P=@.WX;GZXD\RBH3K]J+B!"DU +M!M@W,$K1T/S"_#/7V@@&9/BI<6T0+-'=N*#95,0G7<;LR6&_+$6(WZ?1J7=S` +M5UGGWB3GO^1*8D8E'P#^H?81PWL>+VZ^R%O.OO5RV*4J<@>3?B64RMV@P86I +M_G1/+^?'HB6U;Y0E3<-;M(LNWO@?#_5Z38%+>&HL=@Y/ZL,^HV[%$DD0E4!N +M-#>:1ZUFB]:Z<].JZV)X1X;B-X71A]_:`!L9PW\(>R3/HA'TI*>AR'O2?_AL/7"@\XO4/COQ$8J47X3U%Q`(U'', +M_H63.`"29#Z7U-]<'#%+.B6M9Z?5$"!%`"PTD=>0\@X,\+!+;$9&5[]_BY<) +M8="0=K%O*'QB*%>U9&M*OB76G&(Q$JXL]D2_MM&K>:LMM;LGLIT8^7;<%^3, +M_[!)W]RN`Q1"-]%7D`^Y)#B2?NWQ%=("0MI4 +M80R8^R@[@(MKG6+S:))KY2M(U:FY^$(`4E';H96D8,SF6W*49:1BFLQ)Y<_5 +M+E&VZ#S0O^A:AZ].@:6CH+.`P;D49CQ:37B@I5M@C-$/@L.T_#%$C5OZ.^K- +MMPG]+L6KMS%O**3FCR(U'=+;2PI;WU$;98^R_`0:1'8;%_6B).T@=E<`%YK% +M8JO>:N0QE64TYOX/[L-E!?/J))7WHJ$*$4@CPAKWW_M1"0H\'#P, +MTZ@5O;,+A6.H[L&G4)<5.0GP-[X9WE5G.[NI@]W5]QH;PG@H3R@'!G&]UN'B +MNMX=^I`@[:_S0A$92@ESLJBT''#8C\4![:\!.H-5Q2_(+;W/A``Y$I.#8/SG'X+'`$#2'7#_OWDVYX$^Q/0&N?@KS`O,I""?KP>C"W&T +M78Q\*.A28@=@(1[`?ZGM@&B1@0F6[7JW!2N2S/8Q]U^EBHBG3>+)?A&^S@A@([!E9TT_`5,@EXITG +MES26=772%(1!K;N38&*A8):C)QWAX=-FH-04L%SUDP4[;L#9SG1B*;;]'=T68#0/IJ5S6S,VT]KB +M67?CYA,0ZG6SM:(,F3SC.UK,S"AJ)E=];Q%D5?\(`]!MY1M?2;WV(V@"Y<.PWY;:"/)(HP]ZK&^ +MN)9M1E_16D,$.70Y6??&^+CCG=96R\FZNG"SGT&A)V>%FB]3JU2&GR'=(31C +M>QT\?IPD&'^'=9]>]F0$=!03-8;!?!<'8)A=8>GI![&!8WT]Z8'W!-S1/W2P@(@-3,#G]^O\2]CXMZ4?`_^96AE:U*BC3 +MEIN!&(Z6L\N=\_+;GQ;!]5N[I?U47P=WF\0W?JVK=1]ZH9W@R?@W@>,"J?X9 +MI4PFXE$DDB$<>1J%P8'1$JWE+5N7LF*#0(EP%P^HV7+2J`H+DE/<8>];P#Q% +M$HULIS2W37KQ_G>L*%'L>`H$0')3B5-)J?S'JG9@#^>)(J])EI#;J1+L?W7W +M>`:/>CB_%51CT=]SGQB\-M>S/^/N2&1"^_J:[)P)AT(4AY(Y/X)4VCWX6W.M +M=!MGN[R7K84.>#2`2T3;MOT=.*>#5-8Y`SP4&\4J$LX!1JY"Y&ZOA3,;@=EU +MEAW4`1],P00<3QR*5R(Z*$E,`](2]:*,PMG-8?^8(FZ]R.+:US:-*26U2X:0 +M)+6@PI"B)!(*J)!Y:I5AJN\IN+9D#<%ZQ +MV=:9,L7[0S*!W,C(VFYPA:L75-%I*I"%8MS$@BNTD5`[%#,SYU4?EHSG6+Z# +MZ[O=#FXZ1S0YJ`G:KZ@`=?^LL[QBC_O@R=WZ9&CB$6Q)/'U,;=AZY@AM2/EK +M=)+V;_29:;NQ>5[A;..IRWCX4T6SGF^JN$^PST$8Y2,%W7I\P\W6B,)]9D)B +M?=/N,.["+S4X,`?I\B('"PH/XV305 +MT$0>+03L*TPYMM$>>M-)SM^!N%F>QLK@T%KPNX?\^*==5%>7:<@1KDO[2CFA1K`DIJW;P0 +MI];'S7L#V//"2@T)#0^:ORM"\YK]6T&O&9K;P1:SNW@2&_[8MAM*M@GVOTM: +M?0.7&)KQK>%1E##!R6$O"+0?!HQ94*W7X?7$W5U;N0RG##0K&@.HQ_&\! +M4LI#B)57K?C.Z8AEAUF4A03B/!YG7>[,MX$@:0XO:\- +M4PUK[;XT@R#)Y=Z*=C`4)SKPUV0+9NZE8_HL>PU;HUT$BGV=E[\06V%ZXAFK +ME$%[@@'D#K5SO]"?0$YO3%,$@X)8TP-EY>>_5 +MOC3TD$AK[UOE56P6+EMP_"_ZR=E5CQJI>Q+W6M\-' +M._KKF2<($0Y!U)SW7%0/PHKJ0Q_MC. +MJ=D\095/?"5'@Y-\QQ\@%N<48=%.GH8TOHU*MI.8-9O>ZN;LPU29J7(@74Z&&DD!G@F'\W0 +M7O]T_!"L^6^M--R`UL4?&[55WN\%#!&EN#)$](?9=)%&E,)X/3+!)Y.P!'0ZNG];U4^?_$D9? +M&:=+L7RV<&=D.@@ALIX)YD'`.+R7/;7$/Q1\IKQ_H72-<#D`0A)N%NF,;\A* +MW^,6F0CVD7*,.YESH^%P_=O9*MW!^7XO3\AG1M?>P'AWQ\IT>!4[N4_5DU!1 +M/^?5+-`R3S@G0_8-<0.>"F*\%2BQ@:5X3[N[,>RT%[UUQ8B'V^TP`$RXH0OZ +M>UO'28=O./Q&U-:VHLN`01+^%_[D(0OE&W/9H=V_S=H,$9Q:&Q!4(A3CXP84 +M,:XO2)1\/?()6SOJA^&215TB#"7<1-@&P7_\"UW."FB#V*Y,]J&6_8;GUK"3< +MK!-Z9,M)G\YXY:6JEOS+1:G]P$."?F@PD:L9K^7Z&J;<>9DF5A;U!V5^KWTE +MZ:O3!J`W^>?D#2Q#4B^#8HZ5`JQO;9%"'Q;6)(+OU)!HJ*\SIZ8]?83F7187:4*.X.:S^^!<&QL]H\L= +MM(&XXX$"WA$O\P8F/&(1/.*=;EJP9.]A>@7OU&G8WI#3(O60S0)"(AF_TX3+ +MD\T[Z-D%(,\ZI$0J220GF4T7RW*O;BJLKB1)-#73[](*1[N9H0"F4Y89ECY# +MJNGM$&\(,--$)JY:EW:=`"_VCR!74/H;9W2J&`!,3G\/;CM:*JGHF&?%-'E1 +M=2;86&OCG6E\2I:?-J/\=$'RZT-4/\6E^8[CD.+,)!M"KZ8H!`9LB$E-B?[< +M-2E5^-*C)1Q-1JJ;'?T51[%L0$_K;W[P!@P3SD_TTWGYCT<:TLIK564ME@H;C6,3XD!'9GP:R +MT;>O*C^R)R8K!T!]-4F"IL?NF+DYHEO;C,A@B_Q`!'KA\\5)D4>AW!FX!+[A +MG':0V^MX.N'J=YD$W07-ZI%D'.YG]F8U8CK&;E\OOSVY6TCZ&8"G7`5,!I*?*HU>6LSU'S4;.C&WZ%8SBY76 +MEAWY&O*I;3!('R]WXZ:41'Y\N;\#)P&I<#]QHBO'AGVT2CHD%]U64G=I]T./ +M5$;QAXV"G7*,^^46582'"+A69/XP1M?D;(0'P"^)](9EV,8M[`X7T!XYEK$M +MGT-:P:OV3:A7<<__BQ"9U1P$EL'CS0%36.MF"_^AA:(%TI]*@4&,+V!AU +MU)^S]GO64^^F&NV6;1A6K3G$F(WE"29^_FI?]%<=,S/2?-;J>K@IU +M!(N*Y:<"'H.Z?G%9K*Z'^,W?$GM6O,K>0UZ0.VR)L +M:VW)-82_QV+#7ZV%,XP=U`MR?6DH1BBN(-O1H;74D@` +M(7RF+;+OC_GJ/_TW\LN__<^PE^7ZD2(X1IWP&I%;#%^4=/VG_G6/@2@#,5N0 +M_[L/__0XC*K2/&G&2T.X\HI93; +MAJR!C?>((RV?Z:RE*VUP=Z,*Z9W2"D5#JL1*>?$U-C/ZWI?C +MN`TIZ&FY0&:>UMV;F["+00(X0]3+QZO6[0+QJJ>[]V>:[#*_L\=%J?&(862<"]ZR0 +M=AYVR!OS]Z&.NVV(B;7H>U#6?N6^H21>MKL\86<>"@]^?Q!(]?^8_FFB:YW! +M$L2]JII@M:O48,(^>J3]`9Y+YZ;U5B5,&WI:-;`V94L92M5XT&#M%\..OG[$(-0(6LK[P]K6('7A% +M%:8*T!.205!G_]MH\`]/4>7#K:YL/K)8[Q^H#I0_Z=5%T2?98/-C9*I(CN3D +MM*=.6D^+]VX2?S$`4M6IZ!FU7"4U.@E&GH[`"98=%`U;EW9"$:=PF!^H?A,+ +MPU^X\/5J4;C(4F6U^8OV^ULK@;62'1XK5U9VI:]+`-8`&>HA!C'B>I[?)T#$ +M>TD.$.E>:&!"NU,).SM],[D6%7@:PR.:4-BB\!":9P[PC`"HBR_L9,UOT%;^ +M.T5";LJ]R)3#H:T#SGT0/^>%/A1`/S0-!EVJ(UK[X3]ZK]3T;@;KGXVNB2Z[WZ^4:Y9L$TJM=D?'HKBZM4<&R4=!N3+9 +M9CXZP1"120#.U*3EC`,_-0!.79&]QKR@Q\.C)QI-M$I'+OR2D@E2`HZ_`/$/ +MQ?U8F=B;/$VVMDZ_H8:7J0H&4;$\?;N5US>FO0._.BZ:! +M5IGGG4&S$>&HX$0$FCI*?MX@&Q=FNI)WGV$)A!K6_II]TL'.:Q`#J)T<"=-> +M83XY5O;>%F/4DZO^Y[ROZESX5^#8 +M%0EV@+.1.#6RK[B&U)F*$KK^+2V8[?=2O)!>^T +M)F&0R>*3<+&G^I>,?!1RYW;?)D56>V80 +MV/&U4YZ_U4B2`-Z]P@1-B6`:HP94B"M3&K*FXRL]75^PC3Z*L@T-'8K4:&R6 +MKBM@76[R,>1NUSE12N*`*0+;:X],4[/G%R;1XL7$]W^&Y9_+3Y01$_B.;F3[ +M/(N4#\)W&8*Q_`)/H9$0U;Y0=PN&"=+3U1^-)_QFN3L3<837F+YJ2 +MROH'XY'[-;U>3];L2>2J7]J.ARG`6">M?\J_U%AJ_GT"R+>\KP%B)CTVO7)N +M].70\XY\#2"6(O[X7P+%D/?:7D.*XSELL"3^UR1_.!0*96"^>G0E%I!GM\8T +M`88T?[VPRU4R76^OS0T"MF=`P!L6>; +MFE):RO?NU.VQC0HD_)2E.\EU8\B=&D+;17.SLFNE515]-4P<1VSR3Z[@XI34 +M0GF(E53X'4V41$TL)7394+&"@%>STK`,7W3R5`>Y`/[&PB-%G:T?9SJ<^5YL +M8*#_VJ"N991L$)5;P]$NS2::;PGFV.?FOX\\*4D1Q3V4^^4R&6S)]GA1[':+ +M3V\[OQ@(!CPNOD#,NR)N2W9=H!@8G^"C0$4*4^)AL%CF8M/3L8U\G<0P +MD&UC,B<;S;^9TKP,SZ0(_Y5GO$[#"4QZI`%8_8D04T[Z\OT479X)9BJ&H*_" +M6>^^3'B#9HCPFI/BZQ7P4N9&74N@K_K],Z,X4T5EIY\S%6=R +ML7`HA':4?"?$=9W\3OM*$$.[%.LERD%&,GH!",(1%MJ*=L&V-5F?UFG=47;* +M0FY&.D_T/Z+CGOI;'#V39+; +M7)H&Z?2_"OF)1\K&O@]IAS'74:QNUGP:^R>N,BUQHZ9FR\'/.2""HDV+/C^B +M!C)KRE#*.S*_[9>NLY"M>1>G!V$\RL?2/\2`ALV"D0S=_J"93`,XOF'K0"W) +M2.2@ZJSR_B0OTS9665(N&7(X\A_#T&+X.7(?F31:E,E#)$!&<\0CA0D;UBCF +MLRFPV1DI?@ED/#P"Z&4L4AR67J/T.MA')(K'^^&R"5D06F*TJ(Y;Q[O9@5NE +M6"+E[ZA@PM+[PW5L^.1%;"'IZGHG(,I92\$9@S?\^FW<+N-))HF&/-Q^5XP' +M+\5:CJ4*8LO0Q9;V%Q5:SY<-^KIOZH[6F0=AQ-4N.4&D-__)( +MU^%-`,S)X1!Z)3*73\`]DR[&FV[70EA\?E46%1[&)0S\N4+8)^%Z1#EN +MFLH9H;)LED,6($2GJW/ED<\Q13_D$W/@\E)%Q#9%7$0MY$'"=<"D)I!**-M( +M6+TXKD_2C>G5?%DQ@_^2M,;&*56!%#K-K)-)]EJFXGH&)HNU;WUL/*S>[Z'4U3U%.?AS=?$$_6O@9N\N[&S@*$137X6'^& +MM3,OK7G>`7]/A;3\3X!W\%_4DGBGLFOM'4H5TQ\_/P1Y4+E[,U$\3 +M8-Y`^@27(K8(0PTU3A&I7F>?/@@@LJ;?)KLR>\N(^(OV/YG>DL6A>:TK2TZ^ +MS*E3:)EC:<&*'/(>U#SEBIGDQ1'3D(]E;VB2V_DW#0B+IVFG!Z\F--JM4>!G +M$P;*$6=>B!R6DZE2"XL$?W3<%L62;XO=TEJ1XI6`K[+3S`;-!^2SH\Q9DUY[=?U[FTWZ'J;3*=H_9?BA3:T?_B*P,*'\?X'\F` +MA<_@Y60'@'*VE;-P>H_%:OMRM0SDX18KA;#-_0-N"C"3\S"(T#X*;/O#O-- +ME?F6)P4#_E<.P!]0^B@JCEL]<@P8N-IY*^Y>:R^L155$0'Q6Q9RI/_%.R[FY +M"$-<55@'2^#AHS#9IK:>P'.P*>L5%`8J3MGWV +MC=1D+=N"SX>*'FFJY4U;(+"P'2NMS0+T*U`V+.<>9)V +M6"1B5TACU-?1EW')H\$=RH;;B9-?F];!8"TGH'UY<\T%_1WZO-RQU:@%A#-( +M]FV8^;'>O\(572^4*M#H\5F^FK)/YJ>JKNF+[;I:4SJ_30&!V#\MVK@'A36/ +MFNL2/8SZ]W`?^8ZID?[H/V".,\!ZCT7TP6WJKHOY/2^"JL_,6R:Q5N +M%`.QKN77-*UK=:;YR+M0*`0*N'>V]8/^;/[`$D'3%JQ%O!0RG[(3JI8H[&>B +MQ+L:[>3F/[NTA*XA_:O_)`0R+8_@0.Y`.BWV#;C<3:YD'Y?/*`]UP2 +M;@,%?H(^]H8%24X)PI\#*M'LKN6;LQ%]2++S5M.F<*(LZ;$HDWFKT/17.1DJ +M!J=$C5U[MSNA1V>;5AM582+)<&.^NPHW]QY+RK9/GFP]^#;L`88:JI>RU7N2U_0Y3 +M^?J/@$N +M;]2CUP_HV:3%^>M2BXM:@;<<(]ZM_6;W0JJA+9&)#S69L*"_NF!8_P/+T\[- +MG%@C:N3&(\`C71\(+#D]J#!GL@N'"E)1;?CQ`WI7CQXL^LZVH@.8JN'`X5?' +M=\0/_[IC9BU/G)68.8O8TXRCZ2J!%X$A)#4O-+W_QXI0"T?"Y`1!#Z+[XLR< +MU%^##\M*817A42S4!F/PK(DM*[JL1M;`96BA]BEG#OYJ6D\SN8L&719\,"RZ +MRU[F4%TT@(ER7^^0&'J(^M"D4Q;6\RK=7?%&3L.Y]5'D_TB4VE0++5MN0_WP%_S@`BX2WGD +MV$16G.B'=XVQ"G+'G('O"CN!I%.#ZCIX=\%'E_>W)8#1]_OX=/Q@ELBH=.M! +MPQ)G6B8L2:+ZP1T?X[/12KF"+G*%Q&L0?.YYI+EJNH13UP:Z;(=+Z7V_2$!! +M%H:Y8DDFECEK4:F!_*UCK\MU4M!BL[-WQ$&4>+%@OKXQNK)48(`.O&CD0"LZ +M2^'K)IXEM^VRRA(U,PV\34#5=_(!>'+KZ4+0?)%\"9[YBCKB_H\:ZGDT +M.>ZB*#ZUN*2(FR"XNY*X!0G8VS0.#@C$DQBC^$C*2X:,\"EWV!VW/N/<3L:1 +M*O;'\?I/"]X0,I:VU"VDTG'7#I?!$$%)5Z$+_\;O*N24-L"H7?S5U[PZWD8' +ML9B7`M$Q^`_P.A!2SLID;6$+[ZN2"4>(BSOG5I-`<`A:SF0IR`6$? +M3NE$3.H@?8N#Z\A7"[G$P8.^71HP1COS!+LR%YZ7DGPYA3D+G5UFZRY0)H+-U:["7ZX4^^@! +M/TSAP63<>,Q;7W^8A.)->C<6`RJET&:6QI%JRR)=2V8KG*]\KLKD$V6DQ7NP +MJRX=\`[[]^K&>ZP0YU9W2"(4],#7JVU9393T,,#%PRH//H.+*8CTO4B,)R'7 +M"D@!&NP,7>J\KY59]J3083XBR22!J@0,M'/L3+A.[HYVK!\X&EVF_H6!-FV5@2V4[HVP+:5;O&>D_*W/DXK%Y#AV +MGN&08Z89D-GSGH(_Q8[G?I#^(6Z,,$4W\BQ=LK[/`T'I3:CURX"[1@?*IQLC +M[QK9B(A-XW+-S"3D=Q8EI;#U/G?]G4?-&2#^8N2`U(\^I&N9P."??$'^ZU+Z +MEUU63.N7-1V&V:L74-`)KY7T]LGZR5C;H$7"!C/D4[8\4!^;GNE0SWIN_`2? +MLV\S$=F;>27RSTW!54KLN42IT\GT0F\(Y03'9-$5YCJ;=FKCN^X(A6H1W!:%H"`;7@-$J&]CE1FH_\EA_6(@5'>L+99Q/2NC,"VTY!Z(Q#1$S-UQ)\ +M8K8G16)R)9$X]#,.2]9X57<WV +M#H]W7G6%,R@=)HU_S:;35T0-Z@`1G`6[YKN.55U#*Y^!/%Q?K<9EA@*&_FLM)1BJ< +MQ@:HU%%@>1)-N!W'^7DM=D'GO;PG5O^,4E_Q0<;31S.?ZE\^#"1.O!.G5"65 +MV_R10[";T]P)J4SV$QAO_>?N*_:O3`R%*A=2J9-N:"),JD>AH$XP05$"LA$%OPSKDFT&YL0G"Q$#L:6$X +MJ(IV<8I3C#NMDU9QR&2?MZ5N!I+]_K3Z0MD*2PKN8[>VS:_>DN.<'KK$%OE&ERTS1L6'!6W +MK&4XA'8):?:"F42'J0K&D9+-"'C*:I5]XK'*F+='M2J`NUVCZW?#Y*."XUZN +MN!"VH77)X_PG#=B,DJ?N^TIQO1%V2JN?+E$!R`MSJ;7C1P/"F?+C;\U +M`[BN4=!5F`TMM+Y0`$)T'=23JT(`4U6$XIQ4SYHRA/O,PY/UA4['_$%AD\_N +M0(U.ZX\7SZ"9CL-:;H_BZ'*`P+%IMOK_?S-.DC<%ZI&7EP8)\4?W&3565R=I"EB[4/ +M#9+G7D,Z.CVR"0B"$ZM9Z&X0`6K0:WTN3[04Y*L:U`?2_>YQ7&Q9)C!C4ZX! +M^4KA76@.E_NIY`<'ZLU>1?+MSKC$XRIN*T[+VC8CA1S[L+F;'V\QG-: +M"D)LJ^'VF(-:!"P=N_-D9F)\O\&>Q?L-+WL^/O6^?[2\*\5+`B`RGATJESAF +MH)`Q7HSE';JOY*3LF+)344\TA9YF!A4GX`C.LXG5A;L$7*4A!0.9D/)X5/PN +MO'8DU`D5`QJQZH")AHPZ_!6J?F=-M&3B#HQ!2)6 +MF'PU9!'_V:0&D4N%YW4T4;'1)90'N1:OJ8'#U_[$`JY$S/"9+LF)%WY)]8V' +M8#0U=Z73:!^TK/'K%V6-:MK[C'B^(O\6U5M!3P`70Y%K&(S'?A9XN;K +M3Q))=98:V%VE:7Y3*_'R\=#A9A$.5NJ+$]!4(!CE'0I\.>F"4J7KFK +M_4Z`:%3"4!ZF8^RU62Y&7C.Y>!$]3Z?42H@"! +MK&BKC#W*]`K_(3-.%$K<+E@GWGO;$F#/U?46_8LIU^ZUV6"OUM04Z9$#Q2ME3)2'.-E,HJ>!0+8+4^=^06B5I#%G4YH/110Z8C?Y[C\@5F/\S< +MBX0G11ER,_=%U[Y(DX(A?S#I_*\IN9-5I`_>?;_PU].7ZC<3IP.5:^2Q3K\LEH4>LG\RH:+H@PT5CAJD?!$S +M9Q=V)L$D@]OF$(P?G2*YC`\RW@@C-]0%K:676LS])-N1K=DNM`U3)FZ*O6`- +M9%2U^QU$G-H]NYE$U@5SJ:,P?A%=HX4%YM9\''9,K`#1_U;0R^(?UE"+?WH3 +M!8H%F=-P>\EEZ18QV>MWJ"EZ]?R/D.>15LS8 +M)+(F%!EWAH^_JA!("@NTC-,B**+]X91JAV!UO\7C[Q`8O&E.6"*GFH.O6(1O +MZ=0D@VWG5I4P=BP?`\\`R\JJ,%(K$^)+GNWN37P,!15;[,>P'#O4\EKJCRD. +M"E*TJF&.ULP]KW!AZ=8G@>Z?"TL5HI6TF[E5W5FTBS\&"#'CVJI`-H?1*X+: +M]D/\S=ECGW"08AA+5/XYL(G3?S(:]*YD?0"(KP3:=U_:@8B;3)N +M'6J":-1]7<>;T)\.[U!R1] +M+>"J9U_HC[@7_S-%L@,K6!U4,SEJXPW1Z$M)_'J6"28YA)#YP%)^'>5`&<5T +MW*KPGCLD/!]FM!&H+CVA<;=3H1$N*<3/!S3=+(2V8&7B,2<_>^"1)?B44X3? +MEE9`Y$A"'*2UL+UU5Z@4J'5W&5SLTS,W&(Z\!6B[/M\][&.P!""4#Q*^64^P +MN@;X0?H^4-!SWP[E-4PP*70W]"%I-T1-("V>*!N;("%4DGI538.#?8$>T=DU +M=E*:/\]4R^\EK@$EC(6@_NCP,20RI=W"C$S2 +MS[R\)9#)",?##"@S4NS!P.>@4!@9Q"_$%,XQ-)&UAP'X4%6V,Q[I +M"P5*4;(`1G$$MRA*A>!<$=^[S+V>,7>T.P-"1J!Z!-3@B$ +M/^ZYY;*TJ#KH*T.R*"&)!J@F*[B`<8@,QWF)7E%QN/*M=75#/3#A2_C,])'2 +MKWWAFGGV;)OIRWQB`FQ5MI(X,IP\N5.=30,=$R@C:E;WFW\0J*(,A;>]PXC' +M?Q$?*G[:AO*3UXH@E`!#EMT$:%VER8'(_Y,;`-:VC&QYX0[7TN@++_I87SBO +MVU%$C54`T7G9[YY+:$%#_"FDVM:]JBC),Y^"7W!?FQ`4B^7@B0"1;.Q4QV[0 +MUD9VJ;:V1?<(O7BT`P,TWNP"^U@WQ70Q/1P_8.ITI<=/5TDQ(@6] +M\`/!WE[MWW<$@0_=.LM]_WW263&,GBD#TO$+A_XV0T2<2I>+*E.;:_\AO_YL +MA%&!NOC[KOS,V,ZP5&S'P1>DNRH#B?C+=-E8J&!4&Y+U%0<\HZ`S$JW[)!-$ +MLX.'N+KS2JA#2%='SG1DAH*;3$TU"T2B-B`V5^>ZTWUQ42F?ZA*@TCL)I?C/ +MHLXXZA.UVP:2V,4;/?V."'4R*LT]4F:3/FRQ@3R^)7:]OU4F$-$QJ3B`G[X3 +M2$*<6%^<^JZ/MTW09Y_ATR$!BTQ?^T[/%1J4G7JH&?WL9`LH?E^^\Y_::%M7 +M*KT#LK?[,%WB\B;T%'$+K1-0@7-2LFK%.YYHPH'.CXOKQ`"L@A%RO,!AANE2 +M;YB'VZQ$SK7])3A$<&S.!LF:74)`]7!JVNT#'54>]);+4^JP=6#0G_^:XL9/ +M3[@^J`=_/?9O?'Z7HV0!L/S@^H1Q9[8/!3XWQ.6!H-H +M[R4NEYA]G+!46@E!&CY)']KXE.*;HT_N`1]@#.%J"O_BUSJ1BD#@*I!!4_G( +MR5!'TXLHLXD]N?H.O6K##S.Y_G;R%F%1C<2`-, +MJU]A:YKM+@#R0:\K"MV^R>EMM@&CKD'J'!K@7,*NG1_!H_TWU8_R?I5R6!5` +M,#)K934)J2U<-T:]U@1Q/[V+@I-$X:@#3*P;H[$OPK;OX@9$*%U29[;??$-@ +M>TCJ%_AC=%N]?VTZ>4`ID#3YF\^LBF'HAG_,Y;=IW9'O +M42<16E#YX_RB>J(@LOX'L>O9&UBSQ_F72=>1)%[XQK(RC1&52`W +M>0\%4_TC(:XL6$ARZJ28:#.E>]BZL'?1EM>CN +MVG2-['X#F$XZI'@-!:= +MV#IV$G)8`-*GC@^)")TI^+?\A%^EXK6FQWQ`7F#_V2_$6`Z&1F&19[G$0&10 +MYV.>K`4%UL1X'V^M'$PP\7+?"O[X'AZP'8Z)W'BF+5XI^!RNRPE5\'T&\K[E +MC<25'.D):!>T9%E4MKL@A^E#DO7$%E+DYU"/GG4++ZJYY?L'NOVSN[O`KBK- +M"7#6C&9:YN*+;S-NPU+-^S`71.?/-H$'/D2(&]*"#MZDK,.T5@N'CK'4D\Z. +MYRX*S1`;.88&T@T$SM_6E37.;H'/OB9D8;-'J:>Z(G&+D&&0OHY0NG*!_3K-KBV#!_$`%NJ]LZJ +M6[36E:&K`S2?[W'&K?5.6X"_.>/80YGYT]"6UOTA(KIY$Y;3$]=?*&2M7?$EPK;3 +M9M*[_*\IB/C%-M923#C_-PZ4N06@'@2?ED:(XUX;FE,B"I96F`;[2HB.&0R. +MQ#R4H,@A&(->33*#RECKZ-F5OD;SN.XV1)[GT#KYK^^/5Q?CYQ>5&NS[9)"C +MKPCH0[F1OVO*3]60Q_/9V>PS3M^8D+"GN9=819/%JA"KCC?)H)B"K"W56P9[ +MF=..`9VZ4*3AF"L5>J'CTVPWCS1S-,TLR[DU:"=?WB!&1@P>+"[ZS,Z/*$C> +M5RF#`[S!@U.?Z2C!P,?(-YTO33_5C.7O/MKZB=$2\<`8D`7-Q0@/?3?!``]* +MVM;CA![67[0"52RV?BXY%/_/[COSOT3>&L9(*V[P4A=<1`]IH@7"ZX3G?3L9$CX)J_K53+E-()4J@7L0O4=M4J6)6YI\H:Y7X4R +M$!+TK!WI4]K&+%6@J$H'$63"#C91:90_&&:K'J;IXJ$$#R4*$T(C%\[=)@D; +MPOII0>EA"""3]^'JTJPI1#!!3@*SC)S,W?A3=_0VN:00#4<$3[6F,X%]ZW?7 +M36T`!SK#O5*A!B0-J_*?C%.9;,.#E^XF']F#@D$2BOSU-<0CZK+D)0;[*-#[LI9 +M:_!6]UGLPUGO*WXR5)6QNSI_WB[1;G5%CTVO)^>_^?4^CGKD2D/X]HQ^<)ZTOQ\NRP +MJN^_%<<]+-G+[610[%P-SS>4<,!CF:'.N^H"/3?2FE<0>[%BR%Z?3L%S^Z"] +MD/C@>IPR$1PIO0M#)BG8#?L4,E_#:>ATB::09[XYK:U[YHOUE&Z>5^M!TX<) +M8D_R*E'_^])`;C%3_O=7U!!IE)__QX;)J>W#Z`BF:6?B)A=?UY2V$!&<$E*7 +M\JN>7$DM[J-1:*40>$9IJJ.#MZP!LK2*\.;2&D??V`WLDDV>IEN%F?^,&()@ +M9;KC`J]87(7P65<"8]UYM_UDDZ2,XR,R5^8/Y,FB*4H1Q''FW@AXM2O4)Z<0"[LNPY?3XIUP*->` +M+F6O,M1BAMR<,70YIW7Y'LH&D16*@%6BNF?TE-9:I-LVQ^-0'(JL0"\XYX!+ +M6OT9R,2E.R,96<`,32.@-?YX!\Y4_T*?N0,Y,WR:MO<9JYD("D"-06!4+A!*SKA6;]0\[,'DL!;.:Q/]HPF:.$' +M*3D]B4:M+>@(+_3`UQJ9'7L5"O%\I,U!P6,6S_#@O-*`3;> +MT#MIW%,B(,;K58)K<-_BK4>=],3GR=U=MC!5&#Y?(FA7UE,X"]$N#C0WRS-Q +MOEN^3M[N]=:J'RVB)3[`RF\6"Q:&$HUK<4B,P.-JFN&++#TB +MDW#FN'Y8QX+_%TO.C9USPN=(G+VX6/#Z4:T2#P6X$JC]4.&@$<_[9VW?Q9?L +MUPT(3TJ?&L.I)KY]6QX=*5NHHWB3^MPKIBJV-`KMQ!S0CW+3Z3I1-!P9J.G* +M(%0ZKRA+`+G^MT,\XPWP@S`6)=GF,/T3(":-'R`XM&P,:4?_P4USQOXKAM/; +MOBG6

    \\`3[L6VCS#X +M"=JE+5/P=K?G'(WXI>>,CGZH$]]$1*ZBI4@'UQ+:$213LT?>D'1N^,A>YC7K +MO*CPQL:L96`LJKDLHZ0#?:7"P%>$Y$LJD`V+HK94!YO%JT>AZHU(1S +MXFY+@N'GAQ6+TJR`#.^?8:\0YA4XSE"-I(04?U>JDS4V[?C\)68F?NTR.+4E +M%;AKUR9B\.``]-=!3J&==2QD4J2"%<%9[5A_C#3&.604RXV+5MX<1HUURT<7 +MCC9GR:CQ_8#=FABQ&PRZRT5R(U(T!WL^>Y#MX7#!C;FT&*NDA]>:5&NEF.%T +M@7:5"_IV'NV<],@`[#VP`_DR#3^<:K%WTRKG"]:92D9IBV&K';KMO5=D_^G* +M("2CB*:SR+\.^;6Z(HH$[[&7E8E*B%\`)!.;G%N2?^[;D?G-Z\JN3,:@*LM7 +MFNQ6JRZ`0=L%"/I]>2866IW=UX$20YV2"6^>$]<&@D8O'HV$"Q6=SC%%,]O9 +M%-5.?5FUX5KI)Q\;GD?PL!]J2[XF1>";(95$QM[$$-U=8W5A+V(^.'$S;X(X +M("F5)O`;#=Y%Z1CLZE)_&1E`253,>YFI=TK=+0O>(;:T<$_$+E,J10N`A_<- +M")%BSOP4>NLJT[S?QK^*RL=WG&^)@OBTL6+KI^\(+V'*[96MV*G6,*I`_-MY$7)PN@#VE?/A!S^"6N'2QDDD5\3/?C0PV]>I +M0052D8UH7^D]V2EY_S2'FE=_[O_-$^TX!=5>MDPDN[]-)F=&VM/:-1J6,(Y2 +M_4O1,O2CW5_'\2'*T)F`['D/1BJ'LXE4L=T4%69&=XR-.HF2V2%ZB(>3<@`^ +MW7=I@;LM__IWK:!-!(/&"%YW%6\2,C8.!B@L:Q5?=JX^PY/>5W$1N%R@GYGK +M6!Z6;%4FIL"S,>?M>X4N#F2#@<-9;-<$>\]7`8;ROZ<._1;Y@.J/2=P__T]/ +M!UKBP9P38(6_*%(,!Y8UM1X%.X`$_\\W''16E"YBG7^..C"18^24$A0;.8S> +MV61Q-^00(@^N"ZTBLC(#397RSRK/>?U+?,/*[#]'@.!\?$::W+<4HT;`5!;# +MS$O_18&ECA6/#F--_&"ECFR9&@*FLJAOZ@P@H-[^X& +M)IV*ER-W)\Q*G![C\"+J.^LAO5AV\;S06F#6D1'_N>MO>#A_*V,@NFBIA@#3 +MN5S%U:LE1;`(VI61W?HQH\+F,WWMF#E78+$US99;I-J80H/%V-))@ZY\I_+^V<#%:JC-Q3+6JZ,1%%'#]-=(3,[5VP%J0:B) +M@!'<\04Z]'0?,S8PS4=.#X^N>_F/13P%+JC/*9%(*C%T)B>PJM!F9URK+93N +M_SIL)K0XGJ'E"9GBP_BO^)Q=?:?'W%<,_0BYHM5%*>MBG^A4)%/]O$ON6)Z< +M5A\D''7[$-)L.FO17AK5Z!6;\)186@+]KCFQL9\2#39&^)+X[C +M;76V7.X$L]ZA/5<^@GQ7>V26R+HHXE+".SSI`ZG`D*N)W/,N8"[\W*MG]_14 +M:-G#'L?O9QXP_SJ[U':O+Z5=N-')-?%@)$8%MYNW:1QQ+[9(0&3;`!$7U,P@ +M)^NQ^-+V:8?Z0344VE-EFB<7EA5NB("//$3UQT-G?U%'(("22X_V'2:/"70@ +MO,'#E[W`(N`1BO]R,Z/C#'EV#M>N +M;8R@)>N_,#J:6199'#1FNB-;AC#ZV?*,ON:'%'^$^2S]3&Y;"$J8-Q!:CZ*! +M6\OHS"GH8D#3:N"0#,M`ZX,T_1)[[G(JY+3W[$0FSYF.CTP\2TS3?415=*:I/M3\'BAKG`5*&Y6R%*E#6]+=8 +M:?.[02=XS5/-H"1P5.%&=7@0[-F$1"!BUSK4#Q7K":S#A;)655M,:&&G3;GL#+H%*Z$2N +M.@K'DI^'5?@C@0;D#?E@+X&:T`FJX\/CMK3+J17;1NWX6?%`AW_@*.>&=[+% +M+IJ=B0&#H2I&T%!A!5;ZU*I1!J[HY;XP[&?;4S8B_0QT[S%$S86U[S5D0)Z+ +M7\&0EG\L?&\G@.*$DF\KMQ(&2T!^:*D_`7S%/U,Z'5:+JV]B(N<`;$'W(FIW.XN/[M!AE]0JV9WOW716TO<4#I8+U[ZUI& +MZOP/297'JX!,5T&:TYG3K*2V.JV0'LGA*'7E\^AUSR.Q&RM>#<`H^,IBKV)@ +M"@H8E-DQV^I+.ZY0/>"=YGFC6G>F<'2,8-Y6HWB<.%2>(VBUJ->XEXK/A^>( +M7;0!1^S"HK!E[A44X37DC6"$SDV2^A\=%8UP6EP`,2B +MR`]Y:+XME8'PU?#UV1 +M_7SL<=OVL!UGL0-^<_6>TD3M@R'B7Q3*^5:7\'B"$$3GI#HZ)WY3'0>=Q^(=N!N&=8X +MD.&A3Z/D7@$U;,`,/Q7D94OWJ@3EJN\B#,']OAXYC8B)$#!@2=[DEJFCRMH. +MWO4,^SZ!]BTE`.9-P[HI\`K?"$^'-K]XK6B@A208$"G-8$(OL4`$[/M9$DGE +M;K*[8+'7HY07M^&?5?T\ZM^B\1'R&_7>@3(>,>4[DB^]2>F;*IG%(<ZYO>/B`F*69\]5V5`F2`BQ3];'JK+T#TZC@?[#8&[#GPB!9D?81 +M%SOU[@[K,)+L9/NW-Y^K#HQFT_S@&! +MK+=882G,:O&0#BXV+ZXDD#F(>98Q4*6"/-,ESQ' +MCM!01R02#J2!9J$\#>>?#'=:OD'.?^^$VO'"\_J-6OP'\^RF156EUO>6B'_^ +MM5$AX>Q63?IOUF:LD(-T0-T4;GG6/ZH1AK[=\6E2_XD7Q)8^\\06VR=`#H"@[Z2FQ;YE2-LRC]_H6- +MA93V%0>3LY_`;0F:]LVY,Z44GG$BHXSO7Z*R]/QT7HF4&I3:F;FWVG)#L;M( +MY2N!$J!$KVT+KAY?9E@@HS>BM^12S^>GWA*I4%A*?-7S=P<9KN.'TXJ#USQU +M/FJXJV"#[MWX5F$3J%?)P)6`5=V$%$Y0';7BSN?. +MX1EHX"M(1M249@[A8`E*IZ:K]NLB`+YWX#&<-4YQRX]\G!5ZQ>$!\W`8GVHIY>> +M*2QDF"[8-!'C?M)`[M+)\="_/^'"__-XX$JM-@5HMC'>+X:0>Z1X;_*PD/E2 +MD6$GK+WW.>"O]M'OK$4F<K*QS:MN),<53 +MK->Z(_ELQ>Q[USG-0$=%@FD3%%MEIB*\!9`%%N'EF8_J[NV.F-"'UPQQ`=I` +MAD5,C8$VM%PT\@WN/D**0^+P"CN;.4T%?4A,7JL/'@;;U^N4(=0D9&+\H)U_H_5\L5^:'>>(;$NY9M_`.._?$?69;2@::AU./% +M*,"D-L#^[*6BSL1YG+4)N5#"A#"$2KZBI,;D5WS@N_TD%>L54FW#,>(S\42$ +MF\M#\^)WOX=;X9?`)N(G:*ZI9:`>SD-#&?81"Y@/T0_QM)F.;#GOH_KBA]#`(X#B!X',AO8VGTF$\<3JO!3GO[C.1*@1B +M?/9N!FOL]HP_I8*[(AOEU$A_>M*N;WZT1$N+58.DI=Y?&H%-$Z(=814:$WXS +MNW7C<1]XV5V1GOIH,:WF9'9)0)M/\#YJ97GQF+D]?AC:AFBG(@D4QD2P$*Q&W=:R(+SJ`]?H]G"WLX:@6F[)H,NX4\BM5 +MK'.'M8ZHC@&'#.6X#R3G-_!QD]=G6WF)Y:XERYNCK^H@-KIQEK7)"HF79Q80 +MN8NHE*4-,D)))22ZA+4#,>A+):8A*.)W!6V0J>4X\1XMB1(QWEI=U@76[O?F +ML-8$.UT+7,/D.*T*P^O9C(>3'.NG@-`$`)Q1,GY"1]#X'Q9#(DVC)"GG)F+C +M$KY.LG*;@M>@`%8BC4'CDO<=T_X=Q+]YQ("4I7V-`7V%,K2GRE)#]33LWI_1 +M&Y.D@?/3GH7J\L[8H[;AD#-3)/:\1#@K::M%)E;\;Y'\J,-A-7H4)G +M]&6@(06M,Y\?C+U,@E#:1)VXU]Z9[-LFI@:UL'\/87C:!:J!Q)QFJO`,-X%% +M!ZW,H=<,;6C>`['Y]+.5J;314+K(=-P[PKRP*EB4Z+C3MO[DBL9+2JX:2QS0 +MZ5%TN:1-UGXZFA9B##C)L*FT`3.0"%E)S8()=$)ZJ"!U6;^MG.X)7*\OZ.^:OJPKI@G<)-%;<@HF5Q!F&N_$A(QDN2G":-E'%!.7R_)LN" +MQ`V[^1.'B'_I32S'K\G6J8>T]6-I:T[A"EMW17.0VKA:R\AT%+K_^7:DI(0/ +M9HC-H^5X$A$%ZKF)?9/PT.2=U7K/1RIOXFCEQFV2"76:DR@9_V,47,OI5QT& +M2H`-T41G]SVW.8T0$!DUW=CGHR`J,76LC*4,PB-5R1P$K +MH-[=$)1]8&3`LG71%G?W08H.0*,_M0)['R>0T==A2>:H5U+&7H^A8%!:!VZ$ +M=2C*)V;]0\GY1"60?GQ`'/"UKEE1-?W,500LZ1^^^-1YX"E)5Z6Z4NJ\OVL5 +M3TFZ!U?T,UI0SY,8AW-SQ?*;!H*.@@@(L^T*#O_&->Y1T?D\ +M>/U#OK]D'R9/\ZE3C^`Z/:2]7L[W2M'-9Z0P>-U_.,BK1[Z2BWIQ\%'-8D1W +MD^=4B`4I.:0`!9#.>K2#-1JL'[1O$PC1_?,FUQ?;3F53<"Q92Z@G)#PDX+]: +MAQ1D^UD>5"(U1?3AZDM^$4^TS8*+M.7_ZZV,,K=/&7D_12"M7DB("$_DT'\# +M^`T!QX$V?I[A5@'M4#]7HM$JW0=8]34UJSG<(TTJ`G8&EIF?C)Y!$,^`D"VI +M=YU_?<<\G>,0;K_"Y2H%UT""BV6>5?9[=14)R5](3TWH'PY+=87!`PXEL$5R +MXF?%S-\^6AO7!J)JER+-Q/9)W'63`=:KMV3H!YYND+$3VN*7I%B&(DX:*5C?_E9_:`!`9AF\)B[XSR*+DP=W!D$.,&0;-M;T\3O2#][_X\ATP +MLLESMM?MK.SEL#:,\]!*%`P8AF/8'_;D+7S4<($9ORJ8#UD88/^_!ZPV8W<7-+!PE[ +MFIBX#WVC5^DT&#/27B@E?`R#%VHU=FGADU)V46UT8#%JN;NY9D0S +MM:Q]VJ>&#Y@ZL_J0-GXD&BLFQLE.UQGS*823J^_LL*Q"'^RXY*^;-ZJ +MJYV6PG=]2$&3Q\C]T$JA#/,^8+B4^VS.\MF2D%)_UJ3/@7BV\CSOWK#^GA0= +M.LB*C#(23$P(6Z*%"9_\@#[LVCYO+!:3PYN[2,J?8T)G@.X$ZJ=)F[*]P,G9 +M@^D`:@K>?&Y^GG"FS"7S$8D +MKB[?Y:N\646@;;PE-#,0G&[\WK\:)3/K'*&O#/>CDD:!7:KFJ1R4*!6-,3H) +MI.4J>7WZ;!F(.#)M4]@Y3F,.XU;V1-]DQ3:[;5%4U\`N7(^N3W[YZ*::.*<3 +MY0ZI\0QGJGW)%VVL4`U(8?VF=9I0R:RH__?4L`GY5,S[A=ND4%8\# +M*-.W/*-\F)Q3OP^H(:.(DG@J#>H`(&+.V(]9K"IV5-!%CX_X/4[AL(P`'C2W +M($G<.9-B54L&>QUIWQ`D[JF-%-UD=<,GI@>,HS+>S2UIBUK29PL:\H[5V!UV +M1!9,Z1C1RE7%3Y68I)+8^=B;KYK)O8/R*[!P9;:3JA+.B;)K31%=TNZ>YLE2E@8DK*B)K$(-&,4:7405MO8\=GNX:7U\J)U=IYZ".\' +MOXTQ%G)C@2$K7SM*1@ATTUNN2(4DBF-=D5397MEM#/$-`BQ?5+K,T'K"UJ)P +M,\$K=C$O_`S;:C[@*Y>I\N76XWP&M43)CG;/^!H&]'0VV! +MZ&$[AI#2%5V"PJ-'1':`/=.3FH)U1OJFN#7(-:'K"YDR]A_UEOM[C6TIO%X2 +M_=Z[J4=DP9(Y)YV?F]Y@=B1(>$&K7BKP:;!-H("UT0GWG1;SG%?(ZRWRJ]"8 +MUYK6/*"=DRV$5HC;(1`YJ0%/Z*_3R*^53$E0.+O\D<4(L6C:(5$N1D6ORG0< +MM@P@]1I8.>BR`@N6(4_XY +M5W?$V"!0T$Y8\)L#HS"2:/;TRNFQ.,48OCF.%X=V'"%?G,03J)H(W\>RZEV] +M7\R\ZEK^,O^726%%FX3U/\8APF#GJTAV\C")G37SC"X(U>ZN27]!S35'YS<^ +MB)QT]B55Z"`"Z)TL%&P%S9TY#VI(@'^&-1"W.@IQ7/^Y;_C(5>0^BFPA#*6@ +M-NXJB!4;GN(;;1KQ!?YJG_IV`40GH=#('??3(2^G`6H[8Y3&)S*1\%>*7BZSEYLP2W]1>9!.8S]A8?V?@H=PY*X1FX<51M&>0&"CW.8 +M3?UW924^2_?`YYAO._-N!Y"XF6#HB28L)55A>#*9YOY*64-!P8'GO"NA&Z>V +M`%K"S@BJ9_LE+##/D4X&(X(CJ9U`@U+O#;]RO#:]D6ZK;G=%:@`$B^,R6,J= +M7^+/)2JI>ZG(<%`\!4XRJ;'#7NL2F1=&&=35"6XH;%-S4Z'E_=;ZU9C=(`L3 +MWUEUO%[Q!1G7Q;1E^,,^C3+8]4:)N9O`I,]L58)0+2QV9AK29\O9;9-ED=\7 +M'\8B/C0*#":NEL95JDX:26HR8#C'<-AN*Q +M&YY"[U>?7KV#\)B703:A+;(]"ER'&BW1'0C/>`;O3FN$1`*I`BB&]POQ-1`S +MIF>"%*!^L-_V35Y+MRQ;K^4P&?OF.2[FD$%@ +M<\0+_4EPFE6I8.!RG?O%9P7,.5`8-'4SR=-B.#&(V#IH84D[_;",>C4:ZB +M!L5[?P-Q$1+`U3D3TZ!E8$\F)QOTE,L;H=;;E]OE4W+@7&$9$-4"2U)&>`'9 +M'"IA&EMASXV0&8OV1Q9]6?8(A,^+<8=X^49ZYW1E$1<11%J\43?51$A&C/0H +M2W.-N<-?7IR`X6ZMF*?F:,2AHJYNH`<>869>Y$X,X%1\A]*JD7[`,N9U2&1# +MQWQ+W.>D]!S;D&KC%H(Z\Z+\K,:6P5A]JB9LYPN^*$;GB$'_PRMTL_'B@M]0 +MFE(DB[4V2U@3CB2K-#@85%1$?Z5F1S-9@U8(/>$(#R3Q&[Z^@W4.J/$E$6B\ +M)<$R5Y:93PB'28"12NGE6GB'WKLF3D;JWN_(-`\K);SHM7Z[:R)@(2.5:M\( +M_\PC?$184MK4^8_[8F.=S7FJZP"QB[PE7OZHV-J6/VB+P'CFBG@A9GU/:+#= +MWX[!:1@RF1)=1.'[>_UB^ORX8>>"KK?+S>_=5JU.'XWWL8G05K&35@L-\7#% +MOOZLA+U_")^8IW>@I+?A_]Q?\' +M^%22T#=/U`:E6)!;8<#X.Z"#A5`_PN*R#M!63$C89(@98QXN/EX,(-1=Y<;Y +M!7>F5)3&B6VM3:"Q&-(36H;^D'7$'VS,)[*..5A\T!Z%K^5M2J'SRI:1[N9A +M'N6ONW;4=@AWHCCG1\QB0^J3DO-B/8/8WY$9]:#4E3[ZWK*I=)`]@QXAZK0?"#G]D +M1"[=C/S+9\^(@NGKJE]`"F6/X"9?&)J)PB+V@Y/=<0NFBJ>&HUTX]31W/218?T2$)>NZ7=9/S10DI=`UQ[8_& +MJGD@\63-H$&O(W$#*;MJ%13-D0_16>?>;3`^RVV@AAG[D]J16$WJVN2CB1.6FQ%Y?)@6L3!6A9MZW\,I#W9FMY +M4._0?"V`-NM*;V+=-7W=L0;(_`L5O.1Y_^&8_4Y]$\B%44M?Z''@UXMJ38?_ +M2B0,^2:3`%%S)]%Y'=-A#;W!O@;$,E5W>JA"/S +M\/N&E]/XRTH,P'?ZE085_R[AA7@W^-^4= +MMM-1Q3CU'V%4'^?9;1?:'*!/I^),;AQZE!?A"A[P8WF?"OB,Z!S"H=\"%W3>A0::'/1=`NO11#<[&>5-MV-LJB3OJWP4[N]\HMJM! +M6_]^I)HLS*6'UQXSL)5'#0L!@G\[7]7!S$:X[%7NDNM_3_X!;+@?M";@*4:5 +MO_$EF)N*3`*)N9G9*J3%B]VP3%2>-CTJ]S*\&J@"4S7T"FTWS#7)<`R]N`.E&7>?;??$P=AV[R6\;0"FV=67QQE&'W_BU'!9L +MP#7'BD$$K$H8S7UPA-"=$C1FO=17=)ZC$B&F/S_5-QHKAZ[_DXE2;_`"2U!` +M`IBJ)*I=BI2\;S?%BI*W2RA@5><=>,+_R1@G\;Z!0@EPAJLBM876[YOKN+X\ +M"W<%C-[F@!>\4!0L$'3ZT^K5_K`BV"M=Z7)+6TB!/=#LTM0=2#JZ7'\?03C! +M1`1/)\3D%V94ZY,N9RZCN +M=J^QJ3O_N;5<2#$))@;/LREU0`WEURZC"E=D<2V!X5/0%F7JRJQ,@=`EL.,4 +M)LA.K0=G6(K<-5Z'$`RSIUMGI_@`IS.K,3JI_=17\(<3IQH3UDU]IP/!]VP[ +MF.*Z?3>``R.F[,,]^>_] +ME;UW"9]<9I&29"]M_,U4]\"QL?HYWG?%K=%NY[IJ@2"27P1?+"!;\AH)))C0 +MUN^%%"'6_9"W^#*3D(N_>0):CT?,6%":TUOT>C@$YWIDTZ]9F9[%$K+XXO0Z +M=RE`,%_05X'AO\VPN%"DP>++#K(3*2LOF+,LTF<,`V`)C-3=ZM'@K6^O&WBO +M8ZT@,`?0#+%A*ZBCHV/"V$L;M!CIE=.'UK13`\Y?AS6B<0NA?]V.NJ\?6_-B +MZ9(TSP/<7_C^H@N<>\QA,M.D,V()***F,PI`9?]Q8[L"IFW1=@R6KB9-7,$B +M@?%NMR)$*X@I#UG#Y5_)DJM,H=YYJQ$1I+*T4V.WY1R;*A0$%QKP/V^UGI#82:S>;H'UX9,3X/S1#1L/1'6-`3D +M+4C0DQ[H(6\`&44^\9KGNB93?2&9N('!K]_/5EJGF%#+@T=(V/8BJ?FOE\6_ +MO?]!!3CKDI<1F=<],(QGSWL;WE&K*6\:9;Q"%[!)HFJ<:1LC#P=[1]]%U(`` +MULHJ?),-P\5W6A"`[";EL$M3%*(*!JRYZ+L5Q#\TXP=[+`45\DI7V"!R&9P4 +M*=]+5IE#2^=$;BF1C[-PAS?'MA'[(45``N5IY=*[D6W2T)"%%%(^O'[9K@:0 +M-Z+W9B%I`BD8#M'PS.C!T*P<`1O&R%":\SS,W-,_QX?R_I,PI&8&K]0+K,W.A+!8MR#KF4!-DY75(346^5K]\2CAEXR=]QPI2(VW +MHFVJ6^+=Z3Y\NN%\7..QB5X<4P6&Y[ZB1)QWH$D]S4/;JW=@D5K!8:;X/5T-I//A!%Z+ZE;:3VVJ +M@_7,?O\&,9Q$`OOU`)5\=Q_-*6DZI`^8OFE;,BL&[B7[AP,8SH]F8S1.(L(= +M]J.2]P:*?IP3!>X(0H5:Q2<1&1:!\$\-]2^E2II]XQ8VG/+XVX&]OX@Q.\E\H8U)/J]6@<'XB +M<4P\\.'5J@]H"'"*SM^IGG#69"K\V68@JH6,BHL2/!LMFH4%ZI[*?<@H:^\\ +MGB6<;UG_O<9..FZ6<[9]&H;>FK$0_IL'9N_`-*MT9\K2P"OJ5!AMP(O"1%*. +M=3:JBB;AV\#"[S3B74#/9N'?V%G0W.*<.-WD9Y9E"/AJ""+J*']84TO*Z:C0 +M9L>?T6 +M,%A(]EX4NO')0V]]&X4VVF)FW,ZY"$[%8-72)O<.B4S/&7ZNC?%`XR3YH!O[ +M%TI>J!B".(+LIU//)E[3#BPVAFO9?ALFI[[#HJ>;DH/HKN,`H-=TY&-^?43, +MU60S\^0LIOI@)E&<61*WHRY(["D7=W_2O&H4^])9O@GYY#>'";*C2,IDO:RZ +M(>8<89SSZ[KE3N%*B$RPCTJ%99GWFY"^CM%'/84KK**6T-!Y[_E`ZW(\'Y[[ +MQ@=0F3\PKWD(&ZFFV,5'ZGFA$$6@KX"'RIF`%U4;?13"G%EC$W*.O%01(5+& +M68L.X&$1W^8*&OM4-S_101E<&:P$*W]J[M0X(Q*]S>U8\687I./BW67/29C( +MI-0VP5!NI8OGQRP"LO76^G9KP;FL&3;3LY_:]4;^9FFD*#1+&G7XVVT5#K22 +M;2SZ899"30$$5QYVNUX+!UUS;'4[?!:7>!XDOPQGX4LJHG=G%Z1$(>74:E[" +M]7736`/WTO@0V*YUK1CF=6-JM%^ST#(#,PB?58E4'5]P+U`3$RSJL$_8A2UG +M#*$,$1(-72:1;0PI$05F^8-E?SAW>>%S4E)V.KN4%F'U`1];C>T$_UGH<451 +MI4N\N--.O>R4M@6\E9+"8O3>B=`%6GAU"6*\EV:.L' +M'U(DBRV:]XYD%^6)!>/3-4/TK,?>O:5^4U]E5X6(X6[GTK_W*M"^;SQLCEF4 +M['AF[MGKSRCUJZ$+G&031199;3Y5Y)\@'"K].^&UMV)?#8N+1B:_/*E\*I>\ +MC4>HA,*N1ZL8.[S/##Q5DI:T/5L?K%'!W\#IQJ9GLBE1TL"X!``'X5GQ*.:)`H(:A^Q`ZXN$@TK4@C"_[2"P:4TK?J[U.&`;C_(XV>:"Y)E)PKX9!/ +MMACFC#.&3$N!U&U9,0QBL9V) +MA9-_"1:0J]8!6/R_@#\Z*9;;&!^O]Y`QD%L:!*F^)1*BZ&1&#*6N,V[4RW;V +M^J*1>B6D.&&GK\=G/2>:6^:`LEU-Q_]^X\M]@K)5"2K_\^I11.8MRYH^ +MA5Y^V@S-0W##69BAO?7^I2PRKK^&%!=6>!'O]GH1:.W%XC5%5T4OE=5AG2W. +M/[44./J10&6!NJ;45'#`69S2CCJX%_8O$A/_(A/=^,=?@4$]ECO@V!II@2.>IB8=&,)FQIO413K=Q&28U;H: +MB$%T`%GG>T[S=GC:"(=(M4JZ#/!9=%,[5<2".L!6G*E=;*'`96\W$]/WEI#`&1T +ME%AO`"W?NXA&]W:C[7A>R=V;H!(P;7JW&I=C"^2:Z7G.A&;D&Z0/A^W^Z,PV +M>+B*)^E=&WQ;Y>Z%_W'B!>S-#3ZV@X1Y:8F[NNY[XU$X7,&X7B$\94$/_:#D +M-825KUI%@QICM`]'7,=3(A=DL'519)9OF'Z#6&\)1,`E(:=8U6Z:6^BYF"Y +M^+5-50I#T!\YX3V+JK4&YGC2*__<+(-%XTX_K,BZ0F;FAL$[:L2(\-P7/,^B +MS#Z<.@6KP@]?_*%A'&43+6YL_'I1-0TAI/O'*[%_L,QG=6Q;W:KRCS!Y'U[1$\HWT:1Q\>2=37[_4 +M4HKUCB"@(O(47F7;2\F=9)%87]$/^F`A/N0@S!OHE*\>'0VC_*4$L4&0,3U? +M`%/MY@MT$>ECB-PV$ZMF#;RVF[2@'MM]DY"7K)\'\;1@V8^C'@?=E2R%RV^O +M54E0FX$XR^*-$(>RT2Z?W$5_N?V)JD,67SR/OLHIZ-*:O9>TZEXE,($51HFJ +MVYOUETN9ZIT*7\*L@Y'LJEGD0E,]NZH10DMUR51T@RKM3_]#CQ9HRL97^+AU?< +MQWBB57"\/)3:R:!1XX@V<-]%Y5_C=/42!:@,@4(K3P1;)Y4[4'9'#YO<3$0A +MU*FEAADFHWAUH)INZ348-O/8/U:TJQ[LA +M!BO"AFU,\/(%BF6VVD)[Q/5;`LZA6U!K3PKIY=/L+#'7^4R=[CVGOC0L(J4: +ME!';3LBO[+PL>CDE"J;(?L!BEO^04R/"CN8_F.'``9QJ56_$^RB)%]F$(<4^ +M.C%AO70!4B21Y9]>THKG7K6;MH5YQ_#S*K,4=\@3'GC:K$W6G0Z+F(PE>K_K +M`0R*"-[49Q)6X&G,J#,""Q=O`/:X#T88$'%ETJI-G*PUY(V2]&.QO;QI.BG> +M&;EB)ZRK0D,V.>E_9X>276V8@$=8ABH0F=GR#=\OT:&^J9H!>&6`ZB0-NO9$ +M_>2#D9\F3[9GI)49#3T7^J=G-7GF/_=BQSQUA!93P&^"NIOJC=.]/MJNR<8AJ!MQ,)Y#$FAKD@SSAK>`-T+ +M:MV]/^N4`0ERH(A,.7_Z:=0)\8H.[9,]>K"UF;^)`*0@7+^/".HH3[00;R"` +M2102RCA8S]KTZMX!+)/G0C2H=[<@3>[)AOQ'C@VAA`E[1N,GTOC[470UMLFA +M=D.S<%>3(3U0YYO+NUU!$SX,&(A^6OCRAUP?>:7;0X9O@\`1JHF#DZ2\BWKI +M`DZPYO=OG>1!B)O^&--B8NRNP+A#CRIAS8@I(UMXJE#3*'W_L.L5)B+ETD,$ +MGU-&,<6@>BD#\\4@-)O]E0ZT(7KW&$0UO4(AUOM-!V-0YXL1=E_\M1ZX3@DR +M+DZ#WZQQ>08.]K';ZXEDJI7X',)$_HS3+P7R[@ALL^ZX^=)X%'"B4G,ZJ+(* +M4E='XY56$HW216N^Y@EZXK.'?`*J>,K"(%AAGOJJ08;LCA63;[M6]DTS:'.^ +M"FVB`\Q%4"`:KB%C5*=;7\XR)G-Q"AFS?#BR;0OX@UF!0^W+J-/LNK/OMJ.% +MS!,()CD4@F>WOG-;6_D1+YD!L'Z!&"*)2]=>OZ!LZ77]R[!S(W"U`0VS]S]B +M(21H(H147%*6(FT8LE&NZY8(2K9%+;AT@U91,AU(FBSE$B +MVVXT+/.X^$XU:U0GW3\BTS-LZ?MEC)FDR?@EW;4]U<@.9C*41@!U*<33SZBP +MAX/C:>IH\-%BP*#"KY<7@'5+@C**`OEM76*Z)=`?N?ET/FY>(\:C0>S:>BHC +MW(SR;0G5"'T[(^ASZ4IY23&1^?_#7U]A5K^JAQ) +MZAH!W/@FW7A.EPJN:W5=B[\_Z5/OE#PLFI?<,I3@IYGMQ0[X.2L`%AC.S(5V +M.R*\%8JXN?[.Z0-4V"@&IL:$Z[A>-"_BLJ00EX,3OWK^CZ%W@?K3RW"%$%I0 +MJW%^L`\"9-4]W06`:6,,,TW<^D*4BF\5-M;;6%\OQO:)SJ)0W`QS7:KN;,$O +MF9'Z,AJP05.\ZKHX\<'>LZ!X^@.+?@[X17KN'D\,X$&C&\9C[[J%J&V/_'^; +M"P^*G/;ES`?,T9_1!EYDL`)3HVM:9:Q&?$POE'5H;-(_26AEETDL/`8\"WK% +M5(;$3,@VDF(XOF8--B4B8QY<-$K'[>V&NA<%(_.]1_`1G1%B]E+%4I+LUXR. +M58Q;A/G3(=#3PJ.N-7YI,^RL]!(T"NCN3.JOOMBI;BT$>+BR-&\U%> +MS,E^?K9WH,_?8N, +M>8N*9(XF,3SLJLJ&E[T4>MFV`4'C*COEZ!?[M2[=5SFJI76?Z!$&2`\&W\6` +MMNDA]OVH<2#WY^G)I_<21W[KYA9$/EV&U'K3U!O`R:`];K0*6;A,O1"`GZ?N +M*?S-/X"-7 +M6>RA1S:0>.JR$B5X^:F6X<4A2?7T3\)&VLA!&NTNJRR2`R2AXZ]YY]MNMTT' +M61@8H4KZFA'M("0IN(?('`E(ZBQS](FNV>YY^60JUL+`7NAKN)J`V8!3]4H' +MJ_AE.%_PL<7^ +MA,(0AQ<@/Y.335K`&V%E"/!APZ +MR28R1;3F,%Y2VP!^D"0-7:,S<-E.LEG57,KDB/J8DJPX5EI8U%@\1(IW(^TH +MPT&Z)>T^(3>'B79JDD"R8LJA`/G`IO7%SC$#`K\4JG746CE:/2Z^FB2/$=X;EK2CA7,V[]]=5C?-RZ)C02N2\8'V6"]P^ +M?"XT6MH!X%U1L;_74TP8Z?=Y?-"?I6GX@F)D*8;_:'HH*EUX#X>TO.1$S!R+ +MAFB3=B.N]PW2L?*+F"=('!;>C@O],Q2,Q,-(-FUG!E]1_&WORI&S)1URMWG- +M%_T)AQG._D_E&1X-!.FYM]R7ZQA"Z)+DL!I2?.E5(A$CVQ0W+0>"%GBC`5A, +MB-`QJ=[^`:5,:!NOKX +MC5L)63'TJN-\=H$@8]Y.#DFIL(/K)\JG8A#VU,NS7X)T4ARFD2D\MF=SB+S( +MI7&0$AC^LUV)H*@]!9I7>C6#!5Y0DAV9)HV>DM)0Y5?V/)[."Z$ZN.B"N^-\ +M[D3CY["C*D?7+X^_MUXP`_.89VQD6)E]_-93_UD2JA9, +M@(FWOGB-T8MET-A#8F,?3:06G9\:R@IL3(+;/-YD8L[OK0MA%^R,E\$!]"/&ZF)>F +M)%-[;S--?ENL=NH[D-`F?CK#$@*&8&GNZ@*OTG2W46[2WYH&>R`&39?:]0]( +MIIDD8?6S&OC:-AA@PS[1#&2*Y56V-63Y;WBKOMKIKGO2'H\T16BYV'O6R14ALWR[RKWR\L]! +M7RW+-7)2#+%?X/,2U1G\7-W0S%8(;\D(7#/?S0N;HSX9OLT_T4P5W&*62EY+ +M8?]#;^:K+]_2>+;*OT&TZ4^)Y_U".(0Q^9E> +M3,9M&,S+.<(F-IX#.Q2C8)S_K9'C'?@TK6I\^?U($T*3"SR +MY'Y[CCI`J]$V"GL(S<73>RRCV"E#EO3B.5`&6W%V8XB9;:OJ]HM)Z*$$?O$T +MV1;MT`F!-H!+HT7YBZT\H=,=GI2K=FW4DS]DWJ1&;F)=J738W2G9*N3)/]]# +M@="MQVR.#425'2UD'=G=/F:A&P`^G'M+7DI8?NG(#5XI5_%>]MO`6--ZD<1Q +M>-R9:G3I*8G]B8`F+#.MDR:J6V<[X!7='>X'GCM_;UU(WZ#4Z)TJLA%H+.TID.',\/0C5FP +M3$T?T&N@/\3UM9:H)`(_Y(_`D.N>`M0\JUC1Z?)WMT*<41[<>M)AM/X0&5Z2 +M>+H\A#G-$9)E>%X06Y70+?^LMAPHF8MC+S:A)_R6\T;2:'VJ\I8T0MDMWIP<.PY/-F[V?B)MT;?_5JLQ>H:#B@U6DATLQN[.-+(7]K)5F4?^[3FEV3>8[,I!%S#%GZOBX844*S +M1B:,ICV0FRG?H/IM4@"/2JHA[Q-]`8!2^ +M2<*R,8!:=@Z22$1QED'=UE)+,'&<"BTD5'^O-]`G.:<#86?:2(.54#Q-,.!Z +M.!B,BZ#EERZ8C[[KKT$JF6K38U31]PE-H^+CU'Y1&3DLMZI2V6/$_U'C:9:/ +M2)%*MU5WJM9U)5TVDVAKQF.&UOF@%P53BO25>I`4TP+;+Z(;(T1`,P@8GJVT+[-[>>A)->\B^"3)I.IUZ]Q`SD]8]*#CE\-'=K +MQ&(-1^0/?T6@_C,^+;B(+MDX9H6_EYT:>&AV@:>BKFB8P9C]#8@??,LYCA>' +M0MH#A=Q&YW=S1EN=ON$(!RE7G3]&PO%8S)9\)RJ.12:D6<`PI7H)=U=76_&H +M_NNJZ:EJ<#R-GZ2D$Q +MG#O\QFZT`GT&GZKXH<2?26"TI3Z/U$93N;$**DB&^<'D\B0]%7H&Y32P45;& +MX,&=DD]\S&+SA'`^KD$[.1%_/>3:NN5G9$Q`:,_%(S\C-S/,>#70%[R`-BX3 +M6K6TXDF0615/%==%$?C!I"Q4#-&9RB,Y19-+W8%V#,\QVO$+ZH93*D*?GL;H +MUP&Z&$<(O*6^S1JW9UX!L:,;Z`!K?2>R5FOGSB +M",\5]S[TP4;E&.E/?+1$((9CW8FKECW46S#<)@CB`J>1T0+H.4?>99[UZ"0= +M0R`@XJ)R?=_*L%!1KN/G*6HF3$N+4+LZM2TZVR<5!;EU.&ZM3$A"#HT+GVL, +MQ$F77R."23#2<_!=1MC:&9%M-E3,>Y8:%=)L59I#SDOP.LV!+$SM,\#LK6\W +M2)T$(2LJR$%#F&O6J&F3WM0HL7.K["`A0A+2TFS'A,!T,NB#XJ=T?_Q/**AD +M74]M0&Z[F]^DBM9_N>'>KY;73_.D-8??O/;L0"`_GFU.E7\&;L+V1*T`#'1+ +M5Q?AXJBHH\P3-:TBMM+VBUKUU#DPSNC9/,\"Z!\ZBJ4E*<@:J5/%[\YJ%C\@ +M:!5TPP7W+^6H98T3^^F]UP$I%1JQXS8W)YH4-#(<;`R933EMI`'[^ME7?5BT +MZ#((IYEO#J\+JLIHB\\A:BZP,7&V&?J'CS"`S +M>A+W3[K?YUX9[D%Y`#MPL-A&-#;)9;:&N[4/!Q./^XDO:+!=0J<>\MB1`;57 +M-">6KE-#AW3;FOXQO8)V4I6W.W_I\W"0;K/:-SK\`:R1O(_&AZ!]=KEB[8"N +M<94C]F;)"VL?\S/99O?.0Y/>)T8[*0HQ]$254GBJT]>T0UT>=IYZ*"/!.=OXCPQP<:4J>S_8H]0XSX4J'I(XO +M@DE(6(4583R9F)1T@Y-S8H_+)ZKFL@X7S5:?W;29QC*R=)U\(;E=CH`!C0X* +M$:&TG3G``_WFC(G_`54N>4,?<`06);86`P;MW0W +M-9FJ&R/N0?4*EN2\8<%<%''#!G=ZE8B)%8LRB+GM?XSQW_-`@&P=H&1C>G,% +M'Z^6LV+HC,*5_1VJBTMM[?3,I/1<_=VE00SLF:5Q$S%P$)P'M^3%MUJ6?>:C +MK.9S,*K+/KEJ^PK>#\)-X+]2[VO]DC(/E,+(X%-;KM@%O2;1D\1_H*P1?.C? +M[QC0?J:X+.Y!/QWG?FJ5L3X(06.F4./A7> +MO2";J4U">LK@Z_.O'G\&/M3HD/#O=[:<:)&F>RYJC%"&D=BBGA@XOMT:RMS; +M_:O%3$]J)\0ON%+S:UV>)`$U'VS_\/S0VHK@\WEA__JMQY)ENI&`4Y +MQ?&G90I_??_ZA$F\]\%]-^3_8LVPK^[;'-W:PL`\+8HI]+@8CN_,HS._^CGL +MM5R137LQ>1%-F)D>A"RX9A^)?RU#*8TPW]FB08>%O@E^;FB,+]DM4H_1XTNE +MJC;@$I05S!MP>*)YY>[V(@'*75U+(A040S$3CP;9C/?SZAJ^<]C[SLZA77H; +M/.[V]HW+^[/43D9H+%6)),+WGIV<0?;EBL)7!>QFCH;2NFIJQKA:QF7Y^Y)$ +MCE.`JD(<7F8$N=Q+AB%\; +M,$;`4,=K*+SM<4_&.*=7E_OK6M:WX9DXT-@+VY86WJ>T'N[+M:`+P09G149X +MNK%E>3:2=;PP.5MI:QSMO='/?0*)@)?"0X]-"Y(%WL>5;1)T4-<$X"MX!SX^ +M[&&W_B,+F0->:DFZV0]QB>?70WTYH=TY;8#!E=W+&J.U#,02P"?YGU%`T&X@ +M7SFH4&*$Y9@4(%436N@F/5&.QRE_<#3.@LW,AD++KC]"1?%&NI\A0\$%SZUI +MB)$'WXQP^]*S75S!RVZXG6O+WL.C_;`R/D]5'-Q.TS^I9R5N`\M^V/2O<,#<\' +M6R4-/`G*G-ZM&YEQ"NVH4"WZ.8V('\,NJ7Y\2.@Y@:SMQ1W@G#6:#9HE1`J] +M:V]17H,TV88Y76%&,HIS2H+3GM4LL!K)S'%6MO=TK9_$;<4(8><4[T)X#3=] +M+7F<2+0!!&3!+"C4=]#`FEQ$,W=R:"\UOTV%KY,%5SR3\0::HDQ,0=OG.5;T +MJ=_]-QIV&J\@-A/A-6Y6ISH*,2(N>9B("XQ'))/-,;@XK59A`P`R.8Z3)[F! +M-JQ/VP"!]1<5SQ];79[!.,@1&=[;ZW\/CJ8SM:#FO-[C*UF(6/UB!1&9MG": +MEGUR)RM.)A.VR(ME2IHM=.Q'.+D%^\B@I/L^W$\]NX]X?<4H\8^Y\#&?82XC +MY9:K+\PXT$6*#WYPO!?>5R^0T2MA6H7CLVZ\BGL^"47&W2EP<_/I_<_G-5J= +M)E/,5,W8E2-1LCS5-W5^2?8<_9R&^$\-%:]/!JY6SW>JT>2'.??@M_O$+.^+ +M?>:I='P-+U9>`,!-TS/*:>+PLTD%T#V!8)#J8M?3FOJ@ +MF9L:)NJ>BZ]:3]25$;,,$G7E`?J(EP1AR+5S)T`O_S*$8RJ6[134+7U_5&HU5]Z)B/2:!P+3$/47NX!C&-W/^`)D["RUP:G'\_WR4.(B +M9%TM@AR%Y441[206*2YF!3/R:85]+>DQ=AP:K,BBD6X[`[&_YB8D@KB8WE1@^7">B$N<3W.L=PBH[J\9K)`*Z%6;1^E+]5;$ +MB!_W0D,=$'E:2*-J9WNHKP;4FS5I.GQC3FFO.S5F+,">CI#WTS5)^?EQQDV_ +MR?^L'8X#,I^S>=W/YV[659[SL'J/[!`7NZRLIV9-A&>?UJ7V:WL:7M9'9MI/ +MGPM`J8'1?]R"9+0S2;O2N!KH7^*#9XX`0.365;,9YX+N\`+"TS\1E2KB]131 +M=4$?!(,#PCLZ+OHQ(YG'&)#?]ZN2ENLMHTN4F\03V$&K$4IUHG.DTR>-CK_/ZL0D +M?;/NNLV;VKM!E7GJZXU(RGO2BC)EG]?;$7WLXZ)%7.9W7C\$`&Q<@K-K%!K\ +M0Y]6S=ZB3IUXUHSB'#D607WME?VRC3?U;5:J$CV-%*$=U*.^'M(+1(G%&X/9 +M5T56YKH7G@6TCO/[,"S8-`_\50H/FEEE!E25EV]K4P`7$XD#RVC>W,/;X4)^HJ$ +MO):Y:2`I&K_=5S"75E6NJR:TA-W'34Z\G3J:L(:#L;WK&MJA/='S`=X)A#(L +MNR%"A804BUFCL=QFC]P2P5`SK!2*4G:BA9(*Z#=/&6(K\"@T6>@4B):DM2U" +M[7W80D8CD;518$+>%O$;I"!0QT6_V +M2&7O^J`+7C$5;$WBA_X;MW1Y3HFL/%3G.HRKI\4!SW`5K,MMD7I_-_)%AVN# +M4T<(LCQ(@4N*^+E%C>VT?`*?_8D5$S#R +M-\`%S.'G6"38#,=A#%.LU@HY%W)C,X2X64@F0P.YD,?VL05(+P*_ +M0>YALC))M>/[C8,]>%-[GJNC1C[$-A;D/@*`A.-7]X9K"XCN,+9^D__@IHB+ +M)\X.F27ZJ#=.@5SB%S.I+,+1L";] +M7SJ*D]-$**&)E'^08Q]WL&0.M>;!"GNE.6UD%JW +M9U-*UJBY5GY\'K76_(*_\/E.-*\1Q&_M@6E:#?`/X0"))&@1>7$=6V@;7S6& +M^\,4`QD#3[=?1Z`<+^H)*]<&`8TX<=PF'L./9[#MDWFA8QCAHL@ +M%?E1J.ZK*5O[/P+;?_HX@\)VMS0C7?)4Z_S)E3*I^D2!`E-WS&>IQ3:MA%3K +M#KWPTUW69`.`('*@C$7:_/_4UZR^+J&EJI\`;D4`2Q&;TWSJBX;#$1@X@N?# +MC&EBOSZDR("ZOH*;)PO5CU!H&=5-!33M+F)ZJM"&PL:W_/:B;[7SN?QAP(M- +M3&AXQ_MY332?_^TULX8DSN#KW36>*_1=E:U1^S[#4=%:%2^'#D`Y0\\^W?ZR +M/K?R?HUWZUN_[&FJ+J:EP[-F&K$]K)Y2%JGUYLQB^Z+YT_[+8>&$#(^4F/%4 +ML`X=?7)WODUDA]BOAOL\9D[*22FO+A4S_\7%^ZQ_`['@.IB^]:DE%)"`D9Y* +ME@9`5MGJ?S$J3JUQ!VH1U-^K&8>@E;)SETL%V+*^S;]*["9"9YO-"7LT:#ZA +MZ)8'DVH*[CCIT:XVL93)_@,#,KGPF5.3#R%"-6OV%[&W&K*H%9D>%&0HSX1' +MJMG-OD\>?(4U=%&R4!<37,N9RGEYT?A/)Z.T/DF]P;\F1^F\:N[L6;/"!8]: +M*U+UOC7FL[\LBC*2YT3N[7LQ_VFXTPZH7[`'I:)>_A_8V^4E'$ +M*^4N>4XCE?<,53@0G=SV2=U/2-FHKH3F$88ZPE,3`/HAQ!E\??\D0.9M-#G8$/9:Y$0G]\WG>I#8=,P#=R!/D.78:_/"GFK/YG`:`) +M7I@.TJ\4KR&*?WD<>U9;WS9'O(\#'>+KLG>6WSDVKQ?_!-/?5\+[:BR.;D`T +MDU",'08?$/AJ!P=<"`RC)$QQ&0DT:P$?D@A_FF%0YTA4VQ=8YH012>2(A?FZ +M'U7%S:]/O<[;GE1(25T8D]5X[!T/%SVC7RE(SMIN(2B&7)N'<4^ULS-'Z13.+ +M&D&!^-Q<1)2T.5/-))YZ?_@T]9WA?M)$BO,.TN=%Y5@-&+&8S/Y_)NX&>&F# +M?B'WBZN\]0^][`'#+0@\%K +M=JYMP,)M"\(<&EE[B_VA+@(J(P["11:XUM.N-#NJ@+LK4KZ-(YDU0V,?9@%Z +MQY8-U^`=`PQ_Q^W3:^!CAUV,'VE.QA_BD"Z[/:-: +MG_*=EZG99_@.9O@P_/N9UX[R``GL9V/'LX\ZAY5*/;GMZQJ1IT)+P=QJ%+RB +MGY'4=5-5(WH/?C0CF!.)ZZ'Q1`S4$\K6KK#C.,CWWG=2?L=[/RB?4VU3,2T9 +MHH`@I'=,CDA6;Q;$!F0!65S+*:.L?[4JWPN`P#9F>Q:ZJ=ZRHA2[XWPI*=3* +MF(<7O&!!=@YV8OS+Y81U$T`@VBD=GCP">>RY/-=(J;V#NJ'0EM9WVG4IA]W> +MRD*CD/"?+M"^'0LWK+N&[%:_6<0#?OK2?=_2^BEGT.N[!F)DX.3HXO51X`'$ +MW,<,'LSHP?L^1ZM7N^;07X_^QH&L*E]R;(HK!03XS#R)NN`A,@D]V^QU?X%< +M&B>`-F#8_(M+I9*<:^8)_0P\\#"+-:%7H_7X;R/\9>+D5J@)>1("=*`?+6M) +M&QFWPOEVA(D[-8.)_$E*IO<.XH_`I0/D^'V':]/(\>`QY_"<>MLCA[6#19&T +M,D*QSMP8ZR]"D7(#_O&13408?'$4+_!?LO#])U!NF*_EJ_XP"O0CGA*O'C52 +M!-=.1A9>"$ED(I].KGI3:'TBC_Y#7[62*;B@O8RKW0EB#7\RY[^.)"?']RC% +M^*?52$*!C*'K^GC\+$VH!)3*S\FL$$DP/Z+-?<"Q,ZV#RBICY.SR^5@$L3>C +MFDWJBXZAH@SJ=&1K\#K\$U'-6N&T]7CF<_P2O)T=#?"UG[%&.Q,+2HUDCZH53*+0#\/ +M"';.HM!KF[/&07Q#-#9R9E8/I' +MH^:A15@<#XDL!I0]6X0OQDH2(.Y]*5ZKQW)_921P$D.=?8!1X.UBL\ICPDO^ +M.'ZA7T[9.B:O['8M,>EK+$!A@%$Z@0C&.&;XF\9NV^-.AT.A2UX5>PZ3;D;. +MG5WMV&DLJ>*YRHJ-A5RI1C'UPD-K'06\##^;4U_FKAP,V%QX*BR%KXB=@L(3 +MK=2I_#&U#?:-;G,#,V&2%I0LPGZT02(S%>?QCC:'6HMT[W`Y`]L3,=[QT$MW +M!J9]?1?FN82OU'H1EYS2E_319M';RV]E+QY.P^'GSJ8#I=Y.=,1T@ +MWPEBXL9=Y.*Z##EPJ*8]3`W_O[)[@>5V7<<5!$#EPT9]DKE`Q`EL98KPCR36NA`V +M\R@T\(91^^6T6=GMGYP:+7=A* +M>KYS#P^R`%&WBUR[!]$:$=4RQ];'-?M&Z\Y!@EF^"NN +MNGJ+A^A>YT<(V@8DL>;6:%2;1[$$'E@GJSBB8ZW%$VWB8Y>.82BG"[P^8/_?N>'H +MAI(TJ3&S"M\!O:[?<_D1FA9(/V$ZNW9]=Y(5O+O6$H1..8AIXH%=`&<+O-28 +M72#;F1C8*?;A:4WUV"(O#TGHX=(2ZI@IL5*KI; +MF;,,B_)7C"1==H&^PD:&]N)BWU_A4*%=$(3WSK^=EOSYQ.W@84"DLGWKSQ/- +MO/^-HI>DWKL_M%1DE,0$FF.`;0/;<;L/$6MC.=ZQP3_9OGH$/ITLOX"&5`(8 +MW%=#W_.W6[>*>W&4*F1*>VNA:VGZD_[05\Y!_L_=1--]\MK=A]6(/'&Q`9;2 +M[670A3)B4D5D=7-&YZ)VA6\U<+&9M4 +M[[J.+!(EM@G#^IK(XTX5("W\UY$\OP`:N_!>0"'BYVF=`B>$["/^?S0>#91] +MT8&?3ZPY-B225]HKLTT>UUT*THLL +M,Z"`O%P"3)F;+X0-)TD/W.WTU`G<,>>S?Z.;7&./T!W=/FP__YF,\)Y4*Q%O +M)*+;PMC3Z3,T@6,M.HYGP_0L\8Z#J#K_A:I]K9>26>/W@ZB+0K0CYQ*QSB`* +MB)+YU8G7];+HA_(8W3/LRE*F>?7C:(KE8-_$/JMPT];!OQ^*AA?.C;HK&CA9 +M0R);ZO-34Q8&B3KT=C-HUCB$06T%@_0QCG1)2VS!S;UJ-Y:W30>A>VS1&[O& +M0V/(VQ=.T:[%T]J`S-G?PG']&&4QR^MYV=2J"&/.'9(5_;VDTDY!C=TG[D'17R18)MO['8N&LO$;"KN&)_KY$81L*[!0M" +ML7_\>05SP_(E$C*/'-6"83J4>E%%B*5G_C!9$!,\K@9%W-,8FM/L!)K1LYH? +M_.'%;B7&9O`N9=@T$T"#)LBI6L&5_#B#1`^7UI=IV/<2G%SA0$_Z@-D/AMNG +M3)M,OB`0FI/@CN,^F-0A\OG`/HTS3'O51(51^UJ_BGZ\Q*\ENIEV8V*PNZ/2 +M#8+!U576#FW?/-"5_?&/(\*O&%.8O70]/).X54;2RZTCHC6,OLB"AF_.,=<] +MVI\;_UJ]-(S*U2#)9.4HI!*MJ2`OM7(X4:^Z5(^DEB,)D +M(EAWQ-]E6?NH[JW[S6XIG[[8C]0T)^2O-RT5#V&>B[\/A$1,X7ZS!J&F%##$ +M6IWP,Q*X)SG.L7_\@2-3;U50-D-#] +MHQ^C/^%BL02(-1#'Z*5_:0Y4$'UZ53V!_MIV-"^Y%!>Q'''+WF+KB_^IP4RF +M6MCN"JU$AP]"-^$J0=F%<7FZ/WS019*''RR`CB)H@-6ZP#.HMU)7R3M2_BX$ +MIH3QU*B2BIZT,2`RZ"4*_,V'*8!>I0V.]?9L.=Z.P\S63V[XYP/N%%QEQ]HT +MV-/-:^X&+=6EA[Y3W^2;KR+?(:BU\?!CNM4M4\8(N!=8"@0LO1]'I/!68Y0KC)EP8J+^7P +MX/G<>)9ZF++?QC.@E`QWV44:?XD;,S7"4@RZ0ZR4WB-4>5?ZM>GSG3<^F7OV +M5IFT.$+D$8MF-B6I_6^J=JX:#!A.H;^T/U1P'C<.72PKB?"T^'KWJP.(&JOA +M:?)-/N^Y/M=<*'*]!A!?+"22F)!\QZA\L'1B@]'\#P"4SN3T,05JBYYB!S!J +M$Q_]=I@>O"KV)=S$9Q'4GH$V!4R'_)!K6WX9<_RLFK2!6=##EX@P!2`+K]9_ +MM3F01NDX%H3?MV25L4-_X"I,*3=:V37%YD)JH[@X+3!LZF*3A0@OR+ZT>*8N +MI675OT(-*90,<%E6?)I>M4W-:T"JM-)8HK^[.W./Q!'M'>>]7MEN%P`%W_V` +M>-3E2SCAI3^LRS=^9S$<1;D7V;[<)T(8N#D>A2:JGZ=3[L@;(?/,/?YBV)[!#JD7.7H.+QP:8"I9/9+$IN_(^VG4VX`-%X@=)_0R7JU#]GW2'L%B60S93K.1!Z(XA3Y +MX7ITUDL28:?96OXO`S?&F=Q!],/,_,#SSU!I]XT_TEH'%2SNXN\K@OB +MZ4`C45G=!B86$@'1J(/0!F!36DTKD=_"%*(U/C4),VCZO$PBM0C2][&HEU`# +MDP$#*%1(D^=+?[7%/.*Y02"AL1R]:+`L-XS#!U>W$ABQ#&@^*R.KGL7>&858 +M#Z*XS)-%#',:,R3!GJ:=ZG;\WX``Q`+H88/ +M(F1=8B6$33`$M`"_E\P1LLX,::&PG>X6--T):LE8%[/ZU6*ND[`;MBXEF0;R +MISG"F\_[:4^8Y4'<@'&R,AQ+X&E'D3DO+)\@C2^)/%#LDF"%S^#I/,I +MU8MA*,EG.Y10QF1Z.T7P52J$-C*VF1*@/?"OKZ9Q=A6X9V_F8N=3#S/A:5?I +M;?-PN=Q84RL%3U:\@G-=<-C+@4C*`LNK%K`#_G5YHKI>7N"]@MT=@&\\CB;H/W@-X;AK +M'[B[:E+JNZKX#B#L=RAK=5H+G[KW#HM=:S@%<#'DK8]-120+NB&%D8^[`4;3 +MG^01I6OAW!/[1(+S"R+]@=F6Q$]6@88T"):*DZ3#L4CN*&,T(F/RDV"Q'-,E +M:E_'7[POOB/&4B5D;*6\=>7NLCPC-ZSPV"5X1C;TNT +M:V!*O&O0>!V,1760CA0&G[?X<5],560N'Z&8!(M+<*00F""0U`-*^SA3E\22 +M:`JHX]ZN8XP1$ +MQ=3!]W/8@'(KIT@'R'4#)P?;AV"6\7_>84] +M9KAM=`4=4Y9F$F61\ +M)UKQ9&;'Z2Y:*_(C#4A&>XCG?=U[F$SE/`>O*5]5^4=6&\#NQL$G?_U@W[8' +MRN0*RB3R;VJ(G>22.>N&>4G/`SF\;O/D#JZ&1-U>?S!,PS&+Y<=J!B4]2>_/ +M\FQ&R.@&?0$Q."J=K`L0?<*_(]#T&U*^28U.Q1I%D;C#DWB:L?(L`+F/&4I +M-PDDP(=P"S1]PHZ7'^[HCW\)ND@H+"=!C'D3+SGI>9;3("XA?Y?1PG"F?BX: +M?E;$DG##DLAQ@4!NF=*:YO1%.N`$RSXAHVF,]_BFZLW'V%6_M9S(VAWR\.$W +MO)-2K[$,H9S&TD%6J^2H$_@\P0/:;@AT`TE%E<,=B#4,I(XEI`*CJT +M$*ZJ[E3)',STBV$A]-\YTYBB![NGL@=L`FJW3Z=:6>O[85J]\8P5K&+,--,[\`B()T+1`X9K@?&^6!N!F*MP+ +MOT8<7#(0U:$LHP`^:-":0IP<-F +M81"7WEP:W**10DH3IM,PO9^*>N"\Y+TX4,HUYNZ%E,VP72@925R9D9M=-Z\) +M$GB(XERX+25PT?J]X6>@##2;!R6M#<8<^HF7\D=&?:)Y*0,GXFDQVTB=7JWO +MY/CR1/U))12^LP[-%63'>Z.:XMD2LM^XNU5U=Q"C=FMP821N`)=CGPZ81+:: +ME07;IM29JJ1;07#W^Q02JH%"4%W(,:!\_)G"IJ#5A5X%8!K<:71#X[J09G6K9X`-3M!$V1CV6D:T5 +M.!S`*53G)HNY]2%"W.9]P@E)2\T)LN!Z2%O=A(EF9Q2D1F"H'.94U?R0@O_Q +M)Y?L$VJ1G03XDP#,--:!N1M>@RB]L,/T6?6;"&2\8L2XP+74VIW_.VFZS)QN +M7H>N4+)[L-I8%,$C*"I]CF<3RC48]KS#<'H\;!E*A<:_I*6@2X1I;,0/#UA= +M2)N^'`H(PY+PGO_W9*@H*FCJC508[<(J0(+*FPHCKBGYUV1:AW0!WL+3`VX5 +M%L71&K#WKON8?W-.2J+U6,X7!KD)%5@*"#.OG>03YD*%[D[#,S72XW3I_V96P*U,-2C2@>%WO5GC7O2UUD-^@.@LSSSF8 +MJS6:?V_G;UZ>BABW!!S[8@.MDR9ZS2;U(5AQS9&TZL3$,>)1V]4(P]@?G<>I +MI%GVU>$+V0Q3%:]8"OP#UZW5#'G&S=6KV\4T/AO31V\1J263P>F>R"E[;W>O<_N:( +M[DP19%L\Y;5&'V/=,KN1">GTJ+."&80_M_^LH:O-@W<6"A%$/3P0@>^_MP"E +M)T*_A,^YU2+'PQ7FZ"Y*NNN:CLZ!YK6'_/ELD_UX[M\DB`H<$;6.2&^E_K;Z +MY#K9\FI-OGP7&7:-0I3'!$*;+_:O\2&@])+U)RCO28+8>S)^SL@-K(PD,!H" +M]LT&_=&=,M)3MPM&]I0E;'NRYP3$2036\Y$ZN5T%W]"HNR@10N[.P0?\,QQF +M%^F=GZYT\:_>'2&`W#C7;7O;;1[V!WJ32@"3*I3Q][O./2P0ZC"N2P-FW5DC +M)U*(26K:5J)B8Y+XYXO&[!X2;R3^6+7^D;!GO^D3M+1"?0Y*T02ZV/QU\YNT +MZ/,PZ\W2CFI<"R;/S=X2V)`5FWS<^Z_]?7O(/^Z4LANYOC)O=">L4@2)O-SQ +ML!L`EQF"/@.UP""^7_7:/ZB=?9;$6+/66^MK._9-/Y[^*!NK.[UW[##V\:P- +M7;P=]-V0 +M;,'DRPM0!DDLICKDOQ_CET%:OV4&"PFK7N'6.I[W0'NAS4_#8T&FEW'#(*/P +M5D[O=9JC,,/2A/_T-QD!*NJF-N/KSFDC!(%PS#?!*7O9#KFS?]Y;'BL[S:DTT3 +MH4[&\&^"&A:@$EHI.)7MF,?L6`L16'4R%9^+P-0;N'=['XA!\5O"]3B,1&BIE:^@ +M:$^N1/C=Z1#2B$SP%RK15G1H"31MM]`NN7RB>'S70?+18:G35:#9$@`3*^`G +MX7H'D\;G\OBK6R\1J==Q`V.NU,JLU5$VB]9HN2IK*29YYY#%C>+Z\74W427) +MGLG8GIMI?C"?3AEL`[K9/&$493'?W[15^-CX_OC^'!K80&@PB1G!D-OIPCO0 +M%F?R8[@%+>4HFD%S]]PD;&U+,+E+'^EI^W&Y@Y^XJC`B>;I/R(D=]7\5DT0D +M1IJ7P>4JSO/+,EE?)NGL?;ZS^G58='G`+QV4NG/]9(Q"BMF":3T;@^/O=BBU +M7;]^1)H,!-J",Y#+6V7KU0.<7=6Y>)1/*\0!4X+\&)V_-*S5]*[N[$4>998MZFAZD3IOIMM\@\B% +MT8([7"3_O19;,4"4%FY,$`E1U^61Y,4O*N.5N]>J@D1D4+.4^1W01.[0O)IQ5HJ\#)B^]CT99C7)-"U'"`_ +MP432,U;#VH['PRET9O%9(@\#XG[!A_ZM0+G]0=G4BCWP/V6+@#`K&J.CDGW^ +MC^90Z_5L&N221C/J^)!ZUV2[9]MUHB'KC94F;&R-@%&]BAJH?$[*%';FIW40 +M7K!SO6$]@L*X72U'Z2A!`[5); +M(GVY]]8ZQ-^S>P&F^3&W7@Q51)(6:6ZMZS0N9Q7.M1WE>,CC*]MF).R?8*M( +M-A66E'LC2R2#V&)X@3-/H!&P!QRK=G'?1@9V?4_R(U,]_\!MV##['8S?>2J& +M;=QQ2^D,5JS)-HZ<<$%\<+8\=N5.:$>HS,!HK#`KD3_QVI.!$3*XO +M?M,?MRYFMCES$^SB*UWU$=[)K2I&71/[(=:9^D[*/2E@`[\R%U+N0WV4NWQE +M[8D*`>M:=3L`=VJ>9:C8?O1%UZJBZ:%!QU;*FZ5*TM8*HAX^1B?JU0.GAPF, +M"IB;RKS>F9DE)M3S)Z0+QO=IT2@N@,4VS[&VX*MPU2(IBPXCO89'/P$\OM?3 +MF%*%$WG'SW&:^@_E&WW].X@$M[Q1KPW\4^4*VL=JEFN(PFHKEH?$>6?KI.MP +M7"Q!;6`!P5%G#8KH`,"DK!6^PB^1I@4-YYK9K/ +M(Y2YG+A&B<%#?T:KR4F2<-.=D'\-K6A;FU(*+\9+L>MC_=9W[IIZ`1MIF2)]:,E&2<`9<>U'^>+8`*N +M]9`M=BL^-SQ&%HY`N9R%:5@^OWHGQB3S6_'(-2B +M?_6BRI=VNP1VEZAM7]'/K`"JP?2D1)B.?`@<8`H&/Z\%W@B> +ME$+X5SJW@#^+CHUJD"MIR'$&\QO**"3VS[$G23$ZF6FBWI],3^MF+.T/OE.N +M,8&9#,Z1OPYC)4)$`6ZCO&/"4$A9>6FMHF7G+Y2=MP\BJEVOK=?8XR^MS$)F +M<[$$';78[ERJ68KY]S@J"0+^MSC?WDM[[SY5+!46GLO8I4\F^GV_XH1BT3R_ +MX/-A+8M&_`GIW9SJ7#?YKP>]`)9[):U`=3`>$_E&]0[YBP\LH$EK*@V%L>L\ +M;>0FTO7(T8_S\YD#WMK"ANA_H['4H?6@0))Z3?6U` +MM*3;).\PXAVQ>THB4M)!0>K5T;A"CZ>Z0UY#+V%\""=&TN9.&/QIK]TXJ%># +M_@*-_+/X)M.#XL](?@II-W+K_U"02:NFO2)C*.F9RB86&\C?NS48+!LS$"@M +M)@">2B`J:2.="E+1I4$12F)O\TL8-0PNF6=O*/Q"OVD9)I3#Q,W^93@BQR?B +MYI7Y,^%.)%;RVPAJJ1%Z6EB$5C8MT`ON`K)83A##ZS):LRJB@/%47`A%18V@ +M5,K8PM=-MWA46,Y7QDJ[H8==/%,##XHOUKNU4@%*CDRLZJI9[D$@N0 +M`41`]]UD0!=*+ZZ5X'>K,3!T7C73/U)_.&XEHP.(V3Y>0;%17K%427'-;^[B +MS%;8[@>`(Z*1).%XYM4C6HDN2=M*79]7CV;1TR3ECZR8@M6_HFC\L0I)1]A) +MC;=WLL[>/P?`^MH':>AF>Q' +MHN+/7,Y#R'.(_$NX]@5U"+]IX3*E5SU>#LOFWT`,8-?O_6\K;S?4JG$4V]JT +M5E#A67D7?Y%YMAW`'*7O +M(&QJS70OIH'4V_@89<"(FY5S[A_(KF=+W1T&"N$>JMCU:*Q^/M#WUPGK)FQJ +M-ELB&`$(#MWO='%8XYA4_:WHX+&-+6DB`A"*7ANJ=3!4[?*T`W[74$,L75[& +MLT#259,X4T9./8]I;8`C]T(FI/1JG0,)&<;N@O"QQ"DE824;9;A*3NU]MDP[ +MQ/0?$G5&0$T&4-F-S6]YG\8[].B;)T3@1XI[)()O&F,U[!BT!LZ9$(M)#DGO +MW>PY/]MV%9J00EWD61J#[.O0-G+GC%*&5%IX3]_4+C*_SO1SBOCI";H0&`BR +MX*[XHP[L#MIUI4B&N7V` +M:J\@X71BWNFBCNM[L=N!77`I4;$5$AOGTD\H%NER@7)[XWIX>\+TMHO30W1` +MM,B;\DO@4XJ5>43IZF1[*`*K3^;H"6\;('7/V1AM&LHXW9] +MP>6%$/WA4@I7`8PJF!]G-;F]G;6MM3<42X';F:\6FWJL\:8!B=&W!G7VC+M/ +M1K]:066>:!?OQ*%)1F^?+M-2-!7;K9X`@YLJ*^!BR!]+``0_X[#@9[FWY2?) +M[M5$/#>^])C"?&?=H\;J3JRP52<,>>C<QV;Y%0C.=-&OZ@7O> +MAR7JDOZ4=NG'8<"A.XQX$=^J7@0\RF=1K[/TPDAH^G.K>J7#:&X][+M_]F<-)N98H0H8`_8>#,"JA9OM2SO9"H +M'#6-!935$P.!PZS'+PS]\CR`IZ3[.(@($0SVX`[F;+'N;-ID\6/U*P?3P24` +MF-$AYI4INC_](WQ=J3H(7_M'W>J8(/ZSA_"]P<31GFOI`-LQO$$:`CSSKR9V +MT4;-N?W_J5!QMX*FC6PIBK5/1>@X^((1?0^/?R1$MGO`B7^E[)7KO,A^U_`E +M-;PRB'7LQR3=[5_1A.9W\`0OD?V:%,IASL#=$L^[J\MM6>0K:FE2OS>Y#X10 +M\DGG-T"DV)^%^!@S4.:L@YQN[&RF3:SBVBP=1]ZUIT:33M\`*,2A +MU1MKCHMG#A1?B*Q.@\`!>UO0C5=B_$$'[]D9/N$$1];*J->JB$XVKM8PE25U +M#IH*09>V0K14VX$B]T5AZ*02WL`-8-+BH))J_Q_;P"_^];HQD2\UGMM6N<`% +M)$_Y@/GSV1C#=,[X[I&]J>P$%;94!*Q<16H:XN2E@Z9Y;'\:Z5;K-BCD.$,> +M5*]BU.?_,`>V&*]*V00>R<)T7IFIJWN/5^^%3E&(ZK0PCWTR-I3U9FD+4+E? +M+J<,PM/I/V&H)ND6D%8=78MHWO;4PG8Q%?4T2B_2=:?QV"@$8&MNI@C?`VXF +M:NU,6U@QV/QR.[[&N"*8W-+L!KTX$=_/ROZ2&73[%)138_H9]"IB`N7LJ^X/ +M`J@HCK-ZP.ABSH.QKH&-6-_CS`+1@"#;6F$ZFX+0T*RS@9Y.HOV[.UA/[LC# +M55]>H^:E9M76-%U#`F^>4SI5CZ/QI)@[\2="YBD<,R>3N>0/,0.QJY!R+ATU=4GAAMHHO85FUO$:C\.:6Z`4?!T[1.4EUUFKTG_J"] +MP[`N#ZE&SPA0O`HA@1$D\IS?&ZZH+U$+[GX#6XOD>Q@#]V%W)2YS_`%&@0%D +M(8Y8!G;7!6&NS8QK0TZ>PSPN*!)`*=:_$LB@C!N.`*7;D+,9)Q3$PV-VM6C' +M,Z.'$1DJ&SL0^R_R_+$_OWY=\ZO&+@\VU=HWYMBGP4;W+FDDT<\L\[W"!#]N +MTX9!YK4N,%\>J/.OR,X?GNW6])N#I_^K\#\.Y:ANX)FP4D7Y':%#2\0),3K+ +MT6LH!&T6(=(5\EY)BBZ%)ZU>S7T^K0+IF>8X+VB+6!C>@=/#^]URE"U?-A0* +M;]CH@R"*KA2JB[JWDG#86]*M^JT":O^6QWW43$MC\9CJWU"66=/S +M_3TUT;YOK.'LCFO>S2MBUXC0\9RMB+XPG+1)-*4CR+4U;[KWP5P0:3>$@U\( +MX\[C3"\TP`8L2,W(A+N\*_S5%Z%_#2&TH_DL@91VI^JT/J,?,_$(1LQ?GW0N +M[['>(_/"B)NJF>Q#7:X-JFNV=H*8>)[I1%;PSP'^ +M`@8*&L@[U3X;^@EJOAA%M)[,(1?RH<`2]%_V#BY"=I*P`8S%')SB!@^^-E(H +M\+ME.B&$:&Z37XBY72=WP975_3!!%@NQ);5R-0_#]3M:LQH)T5QD0?Q]Z<$;71P@?K^R,!OUCYG9[6L9U%^9(K5*<]YOT-@W +MW.(>&XA([,.MY#J63#E*XZDR9#1_8,KZT.M%[#'E]G$:]*GP`GI:NC20$HGF +MAJ^^XO./O.?EN;W0R!,WM-/0U8'UPT$1X"BE4QLWIMP518>`69?B0+K]^7JT +MO+'+@9=S/4P9/^O9JZ^X[L@>O>D:40-`<$0-J[O_&0QUMTS#CU`!>QY`X,+5 +MQQT%5!NUU[4&3VD9#T^%IVEL;EM89-L-"WB=? +MZG"JK`T*M4>N]B`6BYL3<(OM1;MM=^I/^-*_!??ZTN,+O\;+"(1UDW&[W]LP +MU:JRGMW+TK-&C\J$/!Y/D#4XP&2$O8F#*._V"R;Y4GG06Y92,>'ZLA?OR<%P +MQ7'Y)0E3B%V$7M$1[F5W0`##Y2PI)>IJ(8:52RK_$=]<`K6,+>L$5#\A[C]# +M8>>-W_:FV1NY!1EG\^;'RO_/=<5.1[_-&N:>S;E;3_#,1%(.7T(8L*%&;O0G +M?>'"6BVK"EB(C8;?MYCZ\B-#/RCI">HE0BHB_\#RG(L?Q70 +MSC@&X8-AL7IY/38Y_XX^XL"Z#WLW4C"U1)K%3FH3G-WC;L'H$G]AD?E8F9\* +MRD9\-E8F#'0XS1&S]5E<&1P%14V<+LFF!,4J@B6;E81`LSXYA496@YED(-9" +M]VPYM0RA\J:VD,@&]SU8IN9EMA7TID+:6`7H"$E%<@*H5>8X!Y +M=1'422$R]`DX^["!]^,4X&8(,H$!SZY0M_O#5!Z"'+C"*G8=?)QMEI@U992[ +M/YOW7(HD;^22FM'/7-@".A@UFR1X*T"%2U@KA[_EO8M^^6(K@=@,_U`7 +M/_@$?K"0RJR3BET,\W>TAJ7SUIZQ&+LGT#P`PF:GP'F.K'LAJ5)3NNV(*4A> +MC%^X0XVQ,.;#25#E\!_^*M8><9P,@`' +M\-"7OF"W?JT<&%5.)0_MQ[^DXP?D+#1R<\X?+;YO7XI,^`3V$UO&VZ\)=&-R +M_O*%H98,`,5Y3G[)7#.#]EF"#N]'&*>\Z6FN&'9 +M7V/M%;G?G*J,*Z,)C9BMC)$`=O2S!:2@U`DLR\%Z7\T4+_,6D>PPU_@5YG]+ +MO)7BY/?Y?S4[FW\XO8[GF%?S"K'_$Q8'/(6<)&JAO3X:NYQJ_8_&'Z"5U7Q% +MT59INXA'TZT7LPB->Y.NUI+&M+M;>^_'<,X?PJI!D^ +M-LK>4PHL^+%R/DX3QPA-S%S%@M7;MN#P-Y9#\?1;[MQ'O`6T[TJHBR0!=3;9 +M-9"AR6*GWL)KG%($O+E$(=I0O6>EXAI+WSMJ0,WA#']3LS<$8GW&>UPT +MBN.X6.S1YA=UC%;X(B\GRO))#XZ2*#''+?;1N#S#'AY?[Y_H5V4F.5!LQ1JD +MRPE\`PSBE+-M`08D;T!].E(ABG.CE@L'A&O?6JJ#3I?5:7;PM`B:,9).M/ +ML@?3X"[3YJK2C>F3-6SNI]FN8J!I=2FL(3?XYCO7'Z.S^%!_D +M8TD*3V6*HQP3[N2LFDHO>+@RU^J8GF*?"]:V!I?V@5/W#UY;E\, +M>T6`"OR<1;-'+JQCGK`'%#HFYL+]+:Y:R;TEIRCV(;LMGJ5EQ9A'D5@VQC>O +M%/,\`A$Q)-0H00,SP%`>/[$R3ZV7N.:P]1\NA!*2OW#9U5`\$YY,H:834HIQ +M9L;*:3#/C%A3O]E4^CL@.(A,^F*[S%I/RUA)!'07C*>2<60M$HP!Q%GWS>/8 +MX/HO=Y6#IB<:S<]8_&9D_8C&0Q+ +M)'DVI]5>V<_"S,`M$(8)#)I(I!\&(19SG)_GD@2/G#/9T +MH@O+:7(S(J=:]MI<'MBWEYHQW6($0U&P]T +M_J5_D'E5<;\[<_QFC-./U>UHB3Y!=$#<+)20V^1,CS%17G<:TI(%Q%@\N`HB5^`SD_UEZG&9_X&D_L^KLC^E.LNJ'"" +MM,;O3SYO9H.N,#`3K,+22Z)77;QM\PCI/ +MC^'6)0%(6$2Z+3[.N.!>U[^,7HH&VR0LGU +MR66'G!(@O?B#^W*8N6AI;-\Q&A_$88!RKS65N&$:7=]Z':#^=^%&64TMM.^9 +MO]XY;9=;AP4#UZG8,+LB$?]'4/A<>1T[R]?!TDO&M8_E5\-W(L=ZXPURZ2`Z +M!<"GHALCK$J!'MN6M2J8%2+F;7@IF-U$'#.%LW(30KOPU3?I2+$[Q2$?#3BG +M:.\O]L2&3ZUEN;Y/#/T#4I4GV\\L>!5\""D)HO[1+]/-!#%RB[AKA6<1]4EB +MGI(/1WVJM$9_&>QOF'92V0.V+]8X'D +M/^CF,:-V&8?\]>!!BG2*YIV"^WCZ`(U&V],:'Y^8@'#7Y%Y9& +M'@"N&+7"GRZ1+-@:'9RR.,#Z$(*+#6GH'4;SP\$VC`:^.*Q8?J;VV'/BJ"PI!C.IW$YZN6_(!3BG:4;SCKF`%4H9H,$JZGE5858B9BMH)2@0 +M(3\F!$U4;L0;57>0[_<\L$]^D^4^B*9S!G2E>($`1!8\,NW-33W!SH.`M+_Y +M39.#GG1*ILC),Q`Y^IP9,RW(=`\>4"&N6%4@DN"_,B%"M%63./8>GKO9-FZ. +M(H:R,U(PSJ>SX?%4#.4./\'>0^!D3#`*+W2_LCW2B#$FSBG;G`Q4HC92ZTL&K>5V!@&5Y1A9U33BUU!RMZ.[M)E:_?VEXK"E1>IFU? +MJE/@6S_UYX,T=DA7RC\#T,Y-'_",X&3KW]<$09-R?\JQIA5MD>:4>W?XC1UZ/K8:1[1@- +M5DC/.*:-@:P/2EQ65;W/ST>ZW36S^VQ5F+B^&_V/OT]S2?8#E9VL(BN])"=4 +M5579>].L8E2FQ1G0V=NY-6C0K5="M7R14O8T\#MC5B5$]%Z\19QM:-^M''&# +M7WN$WY<.H/SNA1J_?(*;TF>&--$S7(46KA<4P60A;2-VW$-@6`N7APL#79V9 +M9YE1"Y9U'KU(\*TF^M@=N:P87_1$5^Z +M/:M@CEWZ@Y5`$>G0&L6HNHWUZ;2$OJ5>BGK.NF8+8V'`FO8ZUTCB+.$29!]? +M&]*.ZG?"E#2)5UIZBI_9XH2>](-D!:=W19+,1I-_(-/-#2P^>4&U0?13P`S$ +M_W5+Y=V1N1LJNA/_T`^!T;W%?F+>XL.JV4G<)76!9*.0@Q.HU6%!/.%5#!3# +M4V$>)P>,40Z(,29AC,`"$O@;&;LG[EL"LNUXX:XVMT\K/H@3PH11L!U!XF(I +M*V?:O.`4$@WEZ=*<1CO3+KB:L1M2E"!6ZWX0ZOAJ(3+N +M@+E1>>BA(X7QYPUT.:R&_.:?6WXM)^D3G68/KF&F=EW$%"12`>LF:26L^Y0O +MTY)_H?NG,H(0@1']11W6%`@E%6BRSV485@YQ?@-@[O^:]CC`.]VX168@>@K: +M`EKL!Z!DX(\A2V#<75D<8-+?P&2XN2NH.UN!YEDUHZ387+GC!.O;&J0`Z7Z< +M21V.H1I\C\AY4*72&<#<#(VO&Y3]ERIM63>7J/ZE^/DZ93";:Y';2>OT=ULH'2 +MOMV7V]=IRP8PE+NI*>>UDL27E`7Z6!K)/5Q(;2B@\%R.\?>F:#1F`Z&_C\7RA3Q$9'(6(K,H.!`A1K+O/Q_<32.O%>X09[>(T:`EP*J&F"@7-#%TG1I;2 +MV[UY*G+;V2N@F!3)%$E7=^.7M@JW8_M8QCOK#B57E8D"^HO5086,Q*;K-Z7X?CJ45W%O<@XG9^N49O7R_&>6MFL,\BD->4ZS +MZAT*=M#3]5`O@>0B26ZI2FV5%;26G9FJ2WQF0@M@VQ_Y.?IB/MLWJUM_7SF_ +MF[##"S-QN)?70LH&57-WC`&@5H>X66SU>;/Z+LU.P*W59[!?5W#D2RVP&3U? +MNU\@JGM?5!']I&6;968N=A#9N=UC0AW[R5_0=BAYI\:7)I=RM.W7"DVT*27; +M^\Z\_*L8`!YA5)YS#+&97U;!_X6:MOPE%A;'8C]?%*[_O +M3"921;[BAKOG5%'@7M`;!18(_7%N;MCAS+]/%^''KVFS`AP'97@[!%`+9$CX +M!\=^81H52(_!A5E\`.'+>DM3[OAFI;^EKCG]HM._PIW?FH;J/&;.78?DO_5! +MLG_FS\87NJ["IAT*SG,%H +M/J,0X?\N4,W*./P%S>4)8_@0[,."71],G*V?GW^0=6GD^.O\[_^DRK+HYX'V +MTO,IS@'-NB5+Z92H3"YX#5"^3B1-Z.XO7O/XLM:\O_!5N;N\YDJ'%7 +M!S;BKW=S]15.93Z09:N4UAHZJI8Y*QK.HL?%QN">3Z_PA3?FYO^ +MP\;6H,C[^L@7PW!;EO!F)!6P4H_G4(9NO8S@[41HQ_;VO$X+8=&/`(!P*,(L +MS35`]Z7PP%-<01)F>@(.=8*'N^!ZHU>P((@1F2=Z$U.`;GP)DE<5R&&NT(O/ +M(%([+8M*O#RJ@'6\Q&ID32+KCOB;KQGIEM1@PA$+P=U0N_DT`/TUC;"4.Y*L +M;CDC)ZD[_Z+!1N,#=ET:F&XH?W]NG8;4>79,\KHF>5%L1U$>EZ+Z`O"7%W-/ +M_=_.)!"(;N`49,H%V-;VS2719#.,51O'3F,`SK^8M9V;+!W(\8AX";TR@A24 +MBYAW8,5T#F9IGLVLE-_TX9WAP"&V\PC7%L&+5X">2;O-08Q?+Z%/*A6'PF,, +MTCYQ(G8-0V4GD),F_//B<$.H;K0H-UEMJR>Y1=)5+B\[&P[S1,2_.LOEL@;D +M:OMU$[CG=5T64V[,MTG! +M#15:?'OH&L`JTB[R=/`5094%4Y7B89D&R*H`B7/WY$RV4.EB)`&4D\^G1@2/ +M\?/Z)^*M3`R[N_[ZPL?0L-G'CG]L(38,&#]L7QHLP8)R,BC"DSHXE;"F>"=1 +M?P&K(/7P#@DVH)VMD$(13O.IJ.\AF\.[%#MB<^`I]27H*3"P`&;X:I:FR7UH +M>NZXID?P3)!.'+IT*)>>-MD.U`J*3=#"T96"&9R2#&!7"MLI@?(&&*I2RI=/-=8@#/2.+LT^3TC"L"[$'"_S*(+KZ5:B +M.#F$OR:2GDKI"(VCLP@R9@F9A`T)AOG_&D+LEO<+:?5JK]I0<\?W@:L0KV7]"OO6-X-2#<` +MK?"8G1HI1/0BF!=!L`%S\!.0Y=3E6#>%QAR$I!Q+V^Q)Y?`1(X6YJHHI)85L+;J"?K"RS#]/#*6YR1 +MI2TG/;*6K8Y:'U1V1":(#M+8'$)'M4_?]:;E.^6B:ZY%)4DP\%J0^Z'E^ONC +M(/&"]AUP87%VOQ;LLH%@#<[_^*JG;T]USM\_=*,LE21W%^U,:F53)&BB=/R# +MI4B_W8&*UJ#HW5.>8ZT*Y*`I8W&3G.P\!\0P%%_,S#>',?``.\]`IFK![SO, +M](J=@[JVK7IO]HI1O,=(;]H>#FG"V6."*=V_@$K58,DJJ=_5<*MF`^OC8$>( +M03?B::_%*-R'I6&:$F2#]Q4H?2SL[S];A@>B+L)?]&.C`&G_X6"ZH:0]K^#J +M_QRJWYF*U[-:=$>*658BLW`A"?++`^J%)79P]>`W.54H3#H]1^`[:0%^"D,/ +MHQYB#K,+0S.3U]-.K5SN?`AV@R97;"OC@#H!EUS(5&"#OZN)N':&]O<[J`7D +MX7`E]LR_J-A1L*!\\\B%EI;VYWNT64+U9XG70?Y4V]HHIU\70'2$..K!KU2@ +MR^:ZCRL;9G\4R8N0*8;U'\VBZ^ETDV0+\<%5C.DCYS](K3^IO!'V.Q.^Y@)% +M[=I:78&L.9,2R?>AW(X6IC:(%C/3Z"71:O_GU3GO^E"A?S%\@C=&GW,:!*\) +M"P$>@9\-4C-ONN+>R&5IWXU:6B\5L6=[B%@TX3DF><8;6Y-/^Z$R0AA_V-M4 +M4J8!+4<,=O)"2/^J"UD41]Y=-\ZV"16!H`)&>(=!\\8(ZP5OLN\RQID?C992 +MQ7IZQ67#AE73Y?QK)"!30I`@NS&/H$];UC%;"C'C46#2V+E]W4N"\MX)&5(U8.M+T@(:K-I8;="SW_,/O",'[!]Y.1DW[Y+/`HDDH3" +M5S9%;6.`7-%@_D)B1<`/G3FC38-8GJJG@^4-"MO$@"A0.1UB0WW?Y9>1ATOW +M_L_N@G'G`P\&O%5;@.[^>]K&OU*&/^+!/ +MXJ'JZ1OX-E6.C[.];&V&4AD6\#F@F^%96"\A@%N2C.[C4*5/;T+Z^.#I69B* +MV'*N8L&LE"5%#.>,"E="J0%/D67\BG1?'[X!PEX:L]9]].4/*!HU`4>B&6>@S9QH["6$L1GQ5# +M2KQ9EE_BC&(M2,@G>@U%`K1>]0P>IV#B(HYS2<\-VB(7T2"'W0B\;+Q._T80W$*@$8SP`$9PC):JYN(:-0^UZ.MIQQ6&1,GT5E +MJXK_LXCM?HGC;@8"L%MBAN5O?EK,LQ<*,^/?J:/F`3DI=/B +MO`*KL`C>V!=)QYR/_EVS3UO/B5,]JY7(F5;GK5M43&O'MIR +MU_>E95-&81=&%Q>S7"Y0PMJW*--R_,]$-!HYNL,CB'KD9GPQWF2Z5#Z\TA*DF&`%B#-@.YGXGID2;I/8C8* +MLC/Y56_QJ\1$/H$+043E]/E,Q"&P6XY+I=2B&E9]MHQNP:.M@`28C\K]WQ="-:\6!3 +M73=AUI`N_J0@ZS4LD>?K>D/W2;>`/\TY;X!G.!GE=7=:M4JT;`G-/[%;Q6*CI@Y?^^_; +M8T/*P5UP#+_Q>]$;0?ON,(MH?PUCPL%[RZ$\DBEZ7#A>3T"*UV`R+*W:MAH/5I.3:`\`GMS@,J7+X+4XCW(Y:9L\S-HZ#N=KJ'1KTCGA +M][CN7:Z\.8!MFR3BV-[`G)R)IA2)C8=A,%VUR=G'?_//V(@5.2LWW)L +M<6#?(4:/=)FX3O/*V$?UM,NN23\V(_NR7UVSU+=&C*E'.;=\2'C2R*-S;C#: +M2)G=]MXT.))A36SK*,CJWO]?N,.`424492!2I$Q0V')JP5Q"$%-_H6`(,Z-<'H\J+Z$<[KE +MK<+<,!LFN[5,W3A0LS>](/F.!.'=#3(_Y;K),I%8F1!F!#'#7)O=$9N-@TM4 +M'"^8EH'#.OI%:2D[*3D:CF6)J@=A"R0TQ``P#L)KI$*17*P$X*9S4S0.# +MJXA!T`)2;#F49W'\I_YG&4X4>%>-+3`*C.NJ[CX=56@'Y:D7RIQ]D-FS;,9M +M`L5.=$F.29L#HMKONJ;FV+[N7`W<9S,73G8UE8Z;XM$\!U`*DI`4` +M)+4B$F4Q$;I=R/L"6JUA.Z?1$^$##AYMX*K,N5>P?SZ3K\!A[WZX=`;/:2S\ +MU:U%A>\#R/?9"/YR'>*/E^0+WGX^MQH4CC#F>%5\D]\L\?HF<>G+5JP%2-+]/**+TVA$;)064"92IW=> +M7HK#H)HE6C4G:P$;ZW<-"^EOJPI_YK#A?!#:"A]LFBWV1$3KQ%4-=]#R<7GP +M5/'^A3.%`4QZA5S`/+J;ZJC4!Z%QTEG1XNTC8TE]YH22.!X"*^;(R(_ZM4"6 +MS@1UD8U&[D:C`3Y\?*/B=TM,*.'_I^./;MJ07*<1OC+>'7L'H<74UT3#G#;@ +MCYP_])FE$565,#U<(Y+7_N_._KONMZHJM+B5CH$Y,L?0<>&!V?_$6<2WK#!CW'74 +MGK"QHKD@-&=6<,1>%::UL,S((.F2[Z?\]"'$IU=>,QI&9YN# +M1^KU"U5V/&S-X3?2)%M,W;T4UPL7SG?GT`0ML))4$#ZA+SBTARUBE^916 +M$#ZR#]L^SHS@63=S*WGH1'J_&S9`LI5]G!+6Q-2\6H_M;S0.&/]JODECP@?( +M"I1*$%=R=XEL.&M6EK4<@%9@:`BD_>8T58%O9$DPPU7M.\^Z*M:UU_ZYUNG: +M$`!UKX6=>K3(QZ*F>$W6R?ZO_.]M^(+_>226HP#(\EXQ']KVL]&G")$!7&X- +M<-C>:VNR$U\X.Z<"#]2QT[E#;>R=JG66QRYJ0:;QBU$/]EO8V[P>*,\E(X76 +MX-GGZZ7'[;/"JG@NV`Q[\0K**A=&?E%I^*#1,/_Z2-C^&-3-"H(70BLD4(@$ +M>QG%(`+CK>GW\.-/"#,'Q->)[<$X6F=S+2BU7&;Q(!($?X=B +MI2WNI,S4J4#*5_(#5^R-2XK,E^NN`&6A?;S'[BP$G(:S&T+T%3)@(6!V> +M.)6-0H$QG&\&9E*^/<6"9?@XH]BCN[9IU#]A_[HD@OJ6+$)T@&1)!C^5YII^ +M(8]2I@".&&,T&"_VV>[FS^&)2R+5.?28V:U!%U[G^82H7/93G9%S]=F[0#1D +MW4U+[#7G3\ZLU^`D^6M(GO`\X$(&)&#C40?=?2I)==M_/P)212&A:"Z3AQG^-"(JN#.IF;ER7X,*P +M.Y^4#4=X87SHXAT-LGUT5YT_D1F#:M(.B]QDT@W-K`1E/W76"%AF9^T`9Q4( +M:VF#NBXHD&@T+$E!C<9C2>`.Y7+2=$*%@!A@7'Y4+6O;L'7G=7]1IL&6QI5> +M"ZH*^Y+O+;1,\W8U5'>:JV71)/AX5J$E)BW[VB'G!T,F1#OLU1^C`1B%5Z@. +M\D'M,BRYK6W*'$DM.Z1A +M/]S6`18.XAN*Q-"O)OGKE*6(@Z6A^$';!EK?\Q755`+V'EW,>4NAB13K^%03 +MI/UHN4D.[N;C39'*#=X9(?/6/SC`7CJU@T"#K$"@8XA?CMWYOXAU-20M=%D@ +M%@<9XV0DEPH@I^;F&1Y(/P9`$;8UOL40=WUBZ6Z%P-#^@CR'@FVJ9G7OA;YZ +M;#98N66D'+[B@$?KP(KJ>:5B>0+]R-GM+(H"Q^0,;4/#R;V;7@@ZN]/;4CA6 +M.3UW\I\=.9R=V9Z0_"]%6OUM4N9@,8#K?W5^H?8'YF`=MZE(17@FX2T<&Y@Y +M-7@S>'ZMAG(80#U#TOE!79:/C6`ANFS[*ZXJ?Z77TT(R>(G<_`[6N>_W/'G^ +MBRR+=4?N$J5)**@BUV9L'CF[+Z;+QL(XQE;-T]^J08UP++O:)@X%@N2^+!,; +M9J=L%AJL!AO`6"F5E;C;L^?$3<#4%@(Z25I.:,'DJ7ZVV4#$33HO)(/-!^B6 +M)(CJUI_%)`RF;+UEPN*PE"D?%ST[Z\VJH/5V\LC@X._IS<8>>$ZL"/TMA1&F +M>VLPCHSZ^]\JPD__P"HF"1`]#V13S"1D?(1I4:8]KQ0P@EFH?4!LA?Q&K\9I%Q4%`A% +M,[=E75`*D,/YFE0EG8!!?[N"SC7VF,&%!%EBL^Y#+G'>X7\SMKL +M1+QD9+6-S8KN;.0!W/U0V=$_<3?RUA2[`BQFU1\;=7=?!)8O'>?JEOEX6+D9 +M-M:'C.&S^'+!!,S6=W9'QO^:F:4!?P$?RXW&)6FD74J),L@G<3VI5+;OI>*3 +M5K"62E&0@^=/0K@J'8>-VN617%XX\;31!Q4FW0MY@,)M$W46'WNJ6X%5E!'_ +M"@V*N3\91#N?MDW*J@3=(H%B39KM?#YRCPXPX_?72+%(WOCBQP1$#STM+V+7 +M3GM.`CNW'HS>4W&CS?VDE$DI.R)]R'_A4S9'&AJ+IT_`P_LO;?O([R=Y32KY +M\7_:'2H8\\E7WS=`I5&`%D-SEY-2LMN:)]MXO#IZT=DCZZ>VK>#+R:C`$':# +M4'MUV&(TA83!F2Q+,W^I0CF:F>I#8^NOKY9]E1!;5=8(,TE@H'#RCJ(4#<"1 +MJ[6F33GPJ4%R0)DP^9*XOUA%\T+(XK?F(QR`H6TVV6-?31M]!VYQ-.ET)'AI +M=*V2"4=P#H^!O8JT#QGK>L&!WW0JX3[DE',BYQ15< +MT#'-Q'&^5T9,M;V-%5:/:91W0'Q;4[]G_+GK'>3` +MC[^]9%_#K>^^TSF&OZMIWAMHV^[C^?!:0*G!0?G$S11HM;GV3/+S_ZO'O4]C +M\_5LN%XPX,V,_DF)-@>R$Z)VV9U3.IO-&E@W"*WF;$6XY'K9BJ.&24H;6,\C +MV>?&+W::@]G'_&\L&22PMR-A(AJ$PO*)Z&RA.82M5&6[IMT=KWKKO+=IB5OF +M"K@N8)UF3*2QO_5`W_2ID-?YQ-V7LH@H_[:+;4][&2M+:T]A(^-W +MAFPM4JUUT;E[:",;0M#N84Y(-9RN\1R(H=,QMD]9CZ5RKGN!J2:NR2^2(HC:`K=.3W\=W-#O5"+ +M*`5CIZ%<=3P.%L%D?OG\;Y#>XM'CN7)&`N]%,PKZ!7B5U\!$4$#OJIL+.L95 +M2Y3]E(N:ECYX$T8"VGEK)Q1!X:4M]Y-W\&=%BWR0DG,5;TC.#Z(9`FV=(PMY +M$%,5/0;$6M8*J)T,!Y6)CVD;7>-,HUIWS#TWF5/P7U=-3TF_3.U*6JNR.WT) +M;NLVYW2OI2QR5$:*W8>S?1=ZM.-RDO[<8!_SG:=">ZY_J@SL7ARVHE_W6/ER +M5%'Z)GIAUV\RT+-K"JP:)0!W@[3J25T_$3W'/2EFM&I_]=4\:A=VZ:W-V]T! +M@,__V\@#V2-TVE+4^&W$NK`)&Y>6G]SMZ9K(5LP_$/ZGSNPH9CH6S1MODF2' +M4E)JTB+IB@"(8NYL:@3M5`\;X=[K9DW7-:^3/Z*(0-E@8=RC[ZW:2W_5&&?DTGBBW%W\[Y32LO$2J"]D3G=[L9N'2\SK(S78E"I^- +MU:L*"7=,H,,-$=04J:71!!A71KXNE8&XZ<>`SMKI24+KO[&CK)3X1^EPDA)U +M!#JT(6%KA+:%N84*6B`JT+\`YA@NQ>'-J5GN +MP(@"7'XM$L)450DQH/X>@DZF@(RTH#J;[50J5=(]9NU4R1*+A7L3B5/H@`JK +MI_UP'.+.63+3(E75XN=FL8[# +M]WR):9VLJ&ATPH-G*6?JDQ^%APL8EP;8V7]T+#;R)V7B+EM1HI"E.1L8+CZ? +M(/;=P0N-`6Z'89F(Q(:T=CW\A_5?V?_3@"OC,(:?I]QQP[/[].5Z`UCF$%R/I;S: +M<$GT^T\_7HET,=$*V+*ZBGHVEA:1O.V(GF:+1*B,$EQW.//*QN5)6XM[)"=^ +M!E'*8!%_D%*"1K,$]HVK?T_4+PG6P7)J8K"+O/H.Y`C\]-I/@I,_;J8'C(\DE)[8SQL^$ +MS[$[GO-]5RP7N[^@R-U+=:2:.^_F6$E^PH(ZVOQL\C>#!']T`/TBN7PG\(\L +MBE@G"?HIH$G8I\I^)!7T(A\W$IJ!MBQ;)Q^VOAB4=ZXY(8E\C^+`DNV/+8A$ +MKQD^:R-3$`:-A#'F.WA;<<9'E=9M4S^TF+7Q5"KE"J+K`_FNM'#=?H_;L,'C +ML1S+BRW]I=@)&,MDC?7$#-B(_B"XPW%^]X.\I6Z*P6>)WQ0#0_YWINT78;[_ +MC6*2.5Q8J]L&/K4H]J,@+):0*C?"C46S[HA?.0+-*J]HY4-'PD3TK4[EK^U]= +MF/5?D(WASZIN5>46IBP%*OW)SZ@C7/=4B,,RR14.0\Y*U_"8"MS6%%!Y[PSG +MV,LM:9GM<9VNOD[7HF]@5Z/=,G3%L,3P<2630=:9"#78;3(9XKES'%Y( +M1=.ACJ9XLK'W*1^'2;F849U[!=>9E'#@S+AYSQ)]35&I/%W[^CI6PZ:J@#'M +M^HK7W=!OD=RSX^LT)I./M6&R?9:"]7-+OY,6DPN^DFB5T@YQ&V+E> +M)OL:Q[6Q.Z&+S>^W>(%J/.P1*0[NWO4>)IK#V.XSAWYLKZ^/]H-$/5OYZ1ZO +MY)_P2YZ_+AZFI9`AG(). +M\FI_GNO=O3#2&ZYG+47'OJ&&+5^J+#&EI6&>O0N!*R]C,@M5Z)*5D%%H,)', +M#T<'7]F%2^*R_,1$;PS'>*&X,==W3E-O%W>) +M+,#A%(C[;2CJURO!,U>NX6H#*IR3-;_C>Q"3;W:I#&^]QK[+:")L&:BL^_X]6&3/V,NF9 +ML26-XDASKVX^S:HR6<7NE<;K":*+DD#N13O8;P\OWE17<(S.*^W%C7HM\SW(*AGY^9BC0OVN_).32J +M8MJH(*HTWR_UB>G&3LBX(2=IBFZ;5N`3"DG`;CF4O2X\[OF:T$4S.QG"E2@_ +ML&DD-0\R53A+Y%18GR^4A*IR]#BIL&C#6SW?I-&/G7XT/&$M39;YR?-=3,FH +M-8"@$'@&IY7$:P!Y,]Z#$*9K1X)6IN[[9[$%;1%9R\.)X5"^V`3+',,;[7"\ +MOL2H1?;8)4_:T.`>A1H@I%8ASF@UWB=U55]CF27X^FL^97?J_SE[\<,V!.QB +M(*G_8F0]1RA@ME1<2=SV1[L;]\)CU[NU]BI[C\[(>$8HTM(XH/3%M>PZW?DP +M*25:`#BTUIO.L:/]I;."G_%@<^!`!F0*N<#VG_*D=Z06SU3%87YMM#1#3;F1 +M8VGE.](,P@?;.1S%@ACJY),AX&[9>FAXKT1,1)#Q-(TU/$WW;QWW]XX)\<$" +M[HK+(=G!DF+:TTO,\LBKIR+%`9#?_G6UK3A,5V]IW5F'^:66H,S7Y/VRV^SC +M_02[C8%ML05L)8_BO`QQCG?K2E_](0";E5G-:^Q?X_DA:'YGF8[;`)OI%Y:; +MT7_&7:BI!03?U)'_E.C,C=X%_4&4(/1DX_?N^LR4Y,9CWTMXUUM2P:CO]1)I +M8Y_DO["B0EEA1$%#,?U"3R!ITQ$,*K+'##J]97<-A(1Z9<4=\^7&LWXV4SE< +M8ECD`I>H8W$NDV@A.:P3P!J27AWH+1:X9K=BF51F[4,05K:35VKCUF`JI#4W +M6]YWHKJ8I154*R4".0=2Q@.@9?Z)2RKXT9$G4HV4[?:T(]YDEL,7PBKU_9ZG +MU>D(DIPV686U.]PC"LT:G(]PSF-B`Y62>=^)# +MEF'(,D!CC;TJ[[\:<.A@_I"B.H,>G(D5R/`<)2ZE^C*O.M1JU:;3SBSB%H2<#8Y-& +M\!*FM,`7Q@->J87-_FOM#5+FIU<.9B0OR9S(++HXAFELR#05*1,=4@3(X1M< +M$4E1K)F93,0:/W\W3<*_WJF^U;FL5JW.Z8K`"6R>JSX:;/`V"B<"$EU9OEA8$>I50 +M)O?V:13WWP3=F+H7#A?UFL=1Y=*SK@'!^EOAE%+,@F84VJ7E*'A`FGW;[V.& +MO.WU]!$Q@I:4A=M`=I8"A$#[!CQ-M[CVY,"+"P36E +MV'H*MHE+[XVB4--HN>Z4)2X.8D;H5YZY$/06DK=UV=TC&`<&XWC3-RP0=',? +MZ-/.6Q&;#-I`_::6.:PI^T;M4&_^H"7;QR,E>$N0%GV%#&+W\=`7U=S&<=S; +MA16F1GA*S4JOK]FT[LBG;,7N@`8J[UP2")Z0F1Y^0@H1;'JS,D>_T"GQ#,10 +M?IGQT7QUC';5H6DFFRMPG+TUXRA3:(V>=+J:)O1,]Z5!;C4KRV2")'URQEQ6 +M"DEM]>^,.LD$#>".2AW81A$9PCLMMH8;:X6%U7"K,_%\I7ID.H9>D&96@0X/JK +MD9;4;^=J6T%\"G(>:)##D7R&;$V4HY^-%,7?^DH5_Z[_E[00'5D\FK9_U'W` +MU5B!S;O*:S[;4FM1N;\*=L@1$(P9*&-O( +M[)1VH"*S3E3I\WJ?;GFYJHN=5]K\BN.P9H@V8:^Y!SG$[_LROW:SK[T%:\SE +MJ^HH-Y&W23G(2?P.GR$\.B"8N90GB.#/5KR(/"BG(Y:HZB/WG:R^U5%+=Y*W +M>GNHA4OKH0V?V0X(@U!U6*)IXET38IV\G,IJ=P"$;RB8SCN`Y#"SY +M4'7L,.VZO[U>A55816T:=&2U +M6F:2ZS-[[\G"APW&-3&DU"D4EV,F>/U0FDK$7+.FSVWO1'D!;$//PE^W<5IE +MIL'1;XX;/L>&3)%.PY-.JU-#5(=7LL43`FB<1,>?J(R4K48.3$N-&NEK-$E, +MIA=>M;CM(#]DQ%;U2T_Q,Q;3ZYX\=5,!L08OSOE;5J4]\/2UW\FZ;=M)/#^NU>O#>Y_$U669!G).Q$H^?X3UX:BGO_+"' +M%DN#"'Z%ZB=@N_HAP9F?/"-(Y_`GS#`?L8/7U.W3^40<2.#R: +MOL8L]C"+LE9GB4#;$O\96`L9LZ5%CSO(L4$X;JL%L>ONOWP#L@^#V'?N[I]! +M:<^3E9JP_!-2L2&8-89PW>S8J%`H.B9*<7,L?D\Q?VV+/Y!7:BUR<[\7J981@XY-39F&4+5X>D)NQJ1 +M0ZB&1G#C$&X\RD<;)#JLOKEX((TTPM+_S7,"/ZL2K7SZ`0I6ZC0;:;B1!E"R +M-5YMIB,9$F2`/-8\SD,D&)7:*;.ZY[SV1V/C-P(]WS3D-_RG]7O44@1S)8X] +M5H9G*"XG)^SAL:K=37&-`KL/Q`R#GGVE8FYJ16_K==J:PE$K4:KP!'@37Z0V +MT$!VB->H3F8)1B=/PVGE02).QIL.^;6Q;;[%:J%%H!OC('=S7%,Q4$4A#A0X +MN7-5*L&$Q+)^L)-:C=U'R(T_7#WFDQ9ZV>=!FIL23KMTE_;15'-"XUWBX?UO +ME$AX%5+G'-!1&\5V:3%58VK6YV3_S.&%;@N +M>1[$`3_>+[7SB'`_"_#BS#KO>!'W68(S:G0TQ9;"+WP>B!!TO8Z0?_%`9&=# +M;'C(3R!/H+X/+J0.1Z`F<9^9[9 +M;!OC_A'JP#5/_!"UQ'I%]#^^M>LVRQFW0;O4.8[2J$U]BI]=9C%']Q'CKQ&] +MQN_X^->YC8MB$.:/VTWA48ILBE3+%-3QR%O^S\NFQZ[2^V)7K[X2IVO`Y6GL +M)22@[8.WJE[*Z"\)-GKI""9#,HQ3`=K#NFLI\D+Z+;,5%('-`*E4D2<4]W,! +M`'1M.6H9%PT8BFO[B]*.5C3-9!:IK6E3G#WAN'DD3$U)@X56"S2JK)1"]&3$KM +M)@D,G_1'$X#3`#ZP./_Q<'5O3O,D!Q(PC@ORN)"Y;J[JL!6R5M1VPFY*DQQA +M<`LGYR;J\EH8O>#MC`?+M_#L-;"9<=K>CCZ6_;*Z=P3`,QZ\=63@0'FX$J7J +M4HU]\+9D#X)=;&EXGB@[@9?.E=Z_U_5>)##&K +M-SN0J2OP'"<+7AX?!@#CIN2C?BV\!'.Z)^U,/&5VM^-'1SDHDK!Q.\9T[X)* +M?:#_'HV8(^`!A"Q^:WXI!T#LXMH8-%/ +M`0P.)+G\"R%+*C_GY/TEH!Z$R,9_[C)B"!)!JY!4A;@%;($SUVP!%Q1`4IA5 +MADW@(J(\QG`+FHH!.\&J%M]E?KN*!WT4J9QQJU*4FAU=MC1G,XIN$`>#$Q:N +MI&5G9,5(+I(-UM]CN4-MYBPT61W%(].0M^PCENQ/KF"@#@8H;=Y9T[O+8?$7:W4H(R?;4CNS[7IUY^W=1YL4DE.I6'-$A<=1<$QSBAMU5<4Y8-6RD +M^L.-NZG1[B0[J*=E-EB8KQ^6@W%^$]W;K"WB\]J[_S5O%,:W#D,-9X@QET"3 +M,1S_BS#)[1!!F%[[Y\P9X1!3'SX=9DU$H@3=>F +MJVCP4!EA5DUZV_LF1SO"@9$W5.JJ0%PW90=]KX(36NF)%4C"V[$AN_Q.=%DM>U$VH9U +MM2S#N/A,V4*!F0?"%$=-T#NTFK'>\+Y9;-<^+&$S9K7P#B5ZQ)&)ZT&MK9>D +M-'#[;[,^/X,>\$DI29A<=3>>((S``',@!XEM<="*.JMNF;1).S8B7]XH,?O] +M%D^T5KGVIW2%"DO;CF;*T'QI$$ARJ.-K"AT'M_*'JXSE23&$QGB&OHRMWEY. +M[)EP!HP4T/:*`"-?4/4MJ<_FA)F4B4>-%>@@VJ9U7F5;J0UD?EL?]FY>A'UI +MX!/2AL=;UEES%KG`NI177RL!O[N(GB+:RP?4M(L>B@^,O9JXQ&S3W+G[L_.#FY"X9Y8SUK5HU/_5I(^!)&M`M.7\YKAXHM52UO$UPLRR3"L +MR573FVV&LU8_3-SG*Q-_C_LVVXK+*N.)OP]]O$3M(R01]4<%.62`&NUL5O=V +MD4HX!BWHCZ#P66-Y<)/Y>7R&8\&VDRT8@S3BO^SRM?1_07)ZRTIJ13`CQ*TO +M1+15/VH5""$TO_8>(`L1D2/>X9"^[(9X&'CGFYJUM2#KV +MV-QVPRGXOJ@!%!7L8;J-U;2Y>+`9!>IP(O7.S2U2SRO"__>W:.+&//AP-""0 +MMQUWO;'V.K39+E_#R#6;I_SOBFPCAX1^Z:D]3!_%A'V#R +M(11W'/DA#=4?T;.EDPK3U[FY]3\*0+Q[\1KJ'_X*"(GCFURS(8CA30RKLHM= +MB&,Z=QVN*=J'4I5`R>$FVL\S$:..,?L1V&30>_KH^_8UU1=WZ'6GG)\#[=MH +MI,[$1%7(C@A<\+]SMZNPI-&I0WM3>+\9:I!JUI)F +M!T2FIQD+VR6NBY5,+6SZ=$':39@1E)8*I_(R]&,5"?6(Y85@E$F3& +M^O[D8IRQ^MXNBL+3J@KZ&DGDH;5_G">1-TTBHL#F2P&!M_8GS%==50]S;+/J +M@&F0:7Z)ZIO.*S>YZ%JJ]%R0T:YYWA'>7.;*`.2EGZ_M'E78.B3B]O$W&H$+-[,1/O? +MVU=EU(ENDP@#M8E1M +M1T0&''=?`Q2)LX8D@O%6RR!: +M[EF%:@HR;:FI."@\1P&1->11X<6G:*;)VT227HIXXHF4S#3$@\"A-BP@:/A0 +M5*3[2R#VJ3;Y0*O(Z.:BDG]<^!VFK$="3>*;MLV'<-?`4:$[BVA5*G."K,+^ +M;G4_L4N=37*RXM#;<\#O@EY\`TP'CX^XTN,BU!)? +M[^CZN*Y+&4($$K7R0HBH`,DPCU6)C`TI]M&:>5VXD?XK$<9:SID:^ESVXS*Y +M1K]-+D!KF]1X/^LK8N"#I@>R:3/DJ@TB]FLL\-7-8[!MU_[C.@I!_>9:<&_I +MEPQW"[&FQ$:$&_/;M$ZRE].PDNQ%-\COO,C:VAS+2Q<73[F9WO3AW9.)SS%, +M?CQVV%CCLX*6VX#BO\+=C`CF>;N)],-W%']A7^MY<&]V$1WD63F^=0>DAJM< +M1.I.?UNE[SYK-;IL-RMM26R%7#NU)G4(G;N1\XAU[I&SS)AS^08/RWINB$PU +MHI1GCV1'E7$+._)CKM"7A`60FA*ZQ/9E11&'YJ)*4*9";\Y,/AS-;E`V#!8V`H";'0U[E9[FKBWE\L>:[9@S*!XJ.2)$/R:!K*& +M8L#_P/9R.SL@SW.H@.874QE1FL"-6YR\_@`*J.Y,R+#O%\VD+%39NR4;Q-#` +M8.`A?R7OYLJ4(R`CW3GR[-658T5[;*8%]Z]MB1H0V5BN[>FN+]9)OF9$[(&: +MW!HA03&?),#>VCQ'E`=7P#!2@,(<"GG8)AOX/DK:/[SO?T>\=,/DV7KF=6>1 +M8K1^,O8[7NR"<]#)&7)P19(>-Q"W_Y[U,&;FNR4R@&!*2`"!X[:-GX^1C_/K +MG2%RDM_K6=,3!GVX2S&PA#5=[JSS2ZWQBL'$19IR2*3P8 +MK;._38)53U%$(CN'ZR'AVGHC9SKF-/-Q("#9HO+(K77CD$WY*Y[G3'66!?S+ +M)66J^;5[-6]6BTF*=VLK)=L],V`IXI'F[U["K>BX?NZ8S*P'R)4 +MV@%7I_9YTQ=0/0DQ!5.,Q%U+"GA]"&[/@>J2!K8,L0\%%'R+`2(BY^2K+;4, +MPM&3KZ.BIH=YRM9FWC8@J]@].R93+(R`0PE3OC[\:]$R-A\N*L0C;[!)C>#& +M]-&C6<)>@H#P=^>F'9=R9=5`A1Z?./M:_I)NTPI$FLT_QTTY<"'YCIS +MT<+4QD\-/?A179RK9-UT8JN@OWOZS5P]B#>1B`2#[1L_Y&W,1D[[,PR3,0T. +MZ,C9<(H^*=[C<1,NOJ'T%5S/)<2BIE6NUL9*,]A#%\Z'BE%^9X-5CCVD]6!/ +M6N0U^\;^G[#O+M;%:+8=>G2SZ?A)#S0-K6CIS*8(;?#BT&R79ELI(WNW3#+Y +MS:>B<%;_1/;3B8*W%UU.`>'<'?7K\5RYQ*21?Y_N+\OKWH#LZRK6+HYEK4@8 +MJ#.\ZBA)R5Q[?&6R%G*UH2 +MU'^5_G;+RO`,B&`V71M=F*_XNM[^'+E.JK\'*CMP%]]B#3_Z2F/%9+2[]WP' +MCQX!_E$SYU'D01(Z,H^`GHTDOF7C!LD1VL[.6)D^]AP@9S[Z#B_X5M5,#S`I +MV1M!8/QCJ1E`M4]&^YKK+ELR&C?]7.B\0^*UG77[!DXEO:%F/MH)I-DHB-,L +M.P%B7,O-M,XX>I]NNXL\P89L6#DS2#I4SOS&LEUAZ/C(L9"I^S]14'2\MA$& +MY\OP`OQG;[Z*ERJ8I7)E>SA-U'V6X5H:C=\US?V>B?TYHEPF5V!COUKT`VNH +MP?<'+'\6D&8_E%W$22B\;\_#OA@L>:\=C3\)"O?L37XDG`X6V`0[E9@4X1*2 +M.AJ0E)T;6PT5JP/=WM[@W>D![<,20^T0C^UF4HO!_#W45@:@V=#XR5#3J5-] +MD0V6!,+'S>'J;)F:IN0%S)]AIT*!,25 +M_K]`^XK3*!@UXZ&GY#GFF)JMR1=WIO+O'ZFR:7*GR,K.9=ZGP/L=90,R4\3G +MZSY@0@Q\8+8`WI*DUM"P'JKC12\J7#XZR3G=,BF\G4:\Q]#9C?G)-0ZW`!9W +M)K-B&U%F>57]ZHG<@'%6!Q/U3;<1<6$=M)5D!,28'\K +MH_[)"G5MRC]9B^?^/RA"XB@&Q4T_<\8YT.M%3#QN_$0H0C(<:8\'CZ7,/FP_4!5C*WUKD9PS'H-:4$D:C)J_C>[$Y_2T@\JG0Y[?:.&F2IA +M*282<.(>4!T>:E@$F;L&*3F4)*E_^GA8_&SD*H`A@D;=H583YSZ)&I:04^S%X5-K0L?@1F1=WFRHN,CKB`(]V+'54,! +M0)&WC@P@!GL8OXL*?VU%"76JDJ2'`\DI4(%U0+"Y#&';J+MI\Q!@V +MF/[>GLD8/F0&@QQ'8LU/YC':NQ:+-];`O@(]X_H:@,ZTNZ>$R$E_6TQ0%$.) +MFF*<-*(_/-^52%-DO9N-Z5]$\HJZ8KL,P<;]9J>>=U:!LOPPCW&"*$;0%SYJ +M".O2M6%8&L:;M!6D(/?6-VJ2G6=93F*$$-#U+QNDTFW1P441HXJT8F)UX6R0 +M,I84!WT%$9;Z9%SQ!6=*E*[$Q]4GK"?W4@-MHX1KN156;W2Z[Y[\8M"^MO66 +M>L7&AT]V^$5U;9'\3<=/&0T,*HO8D>S$^51I:B\W1%3]W_7?P":Q;XOAP-!Y +MTZNZ3P)5\FABAYK6H"Q<-'+0W^^8Q8H#X^_\HL5,6,TJ'J8@1;LL%CYN$Y +MAG+O\LY.+?R&WC0=TH;VM\&%JG6U$)YW^'0@8=93302N:CV$CHVL3 +MU<9MDLD;,$$=@;;!S!8V*N;$=RG"D*98<4GWE+/?7/9]?1XFM^'2Q)Y*M7?" +M'=SWGXYKN'OA)9"F50&11'ICY1+;0I57D6P69K\'.IR.2FXDCF>Q6X7"O&W> +M\OKR`4ZO>LI\8N1=U6,FA+[J8#9V<=-< +MEWU@8LK/.R2#P'I:5H+KK0HS[F668%SMM'-++>D;1JX`F7"T,OFW'9?=/1GS +M*3KDHDN^8+P?I4B9\_6\MENE:LLNWQ)$`\F>IW\LXZPN#--UN&X_+0F^R;/Q4*'^^#WXFLXM2T1/4*.;1-KC(SE +M:9F7NNH(=3]^;AN$>TOVK^($=QCI,95,/LRFCTZA-D.(F0;*91G^6L6)W#^7 +M/>[0MU$U6/QDY_^NPXV.C0.A`B+FO8(XA3Y=^*5^>O1`84Q/HP+<9.E$%F,^>MO"'C>B+Y`^**J\M-RD +M(?@&3(MXMJ[7U'WVF0_@D=FP//H@.]#Z2H3&(M4EC=`QM>,`[2K^\R`]%_#] +M5C3,0:NQZ5Y&.JZ?=!@U=H+X-&LYQL*@?/&&\QAW(@T3AIYP7'(@E6_;R`6/ +MC-=VN%.-K1FX3C/@J>*')Q%R#H[Z"D-R +MTDL@%64U?V1L2L3T`'%G=F8Y`\)5#C6'V.3T\?_.@Y+8*.7<1.6A,GF#>HB1 +M6U&%EU_;)@2UEB$B.*Y,$!2NAXVL&&0)=>1+=VGQ!CJ]#8:@]'D- +M!+??J7D+0.M2!XZM@<%"S*#9HURMVG-$X;U8O,6[$WN>)STE/-YP`K\CK>K\&*CZDH""F_V""2Z6-)_WN]+5>`MJ(3&U+WKQXE0E-& +M!FL$5A!T#-?KC[B-?+WO4*&&XY[N$,+?N&J]9;0]X!"4,_NXD20OL\0`J&[0 +MM#P^X=?B6J-=$&HW4GVZ^]>A*=F;R13%E!21%;]EAJ)94,3NU@ +MF&(.1+\"14VA5">6\A.;UL/K@&Q4P$D5LI>9XVA2\@G?VY1[@_ +MG-@Z==M_?A5XL(\_"Z.7DC6"KQ!EO%*1$]SDJ@Z4+P4M";">#(\=([>T?">M +M-E@5ZM+_FNO1]U)Y_$]A1RX%Q4OW(N-:+34;GHR(-_'3X9 +M79$?&KOV.R-D@;6 +MX'39PO,4SE7GD"N#/_9WPX-'0\>T%^EZ[NJI_>=P+3@$%JGJRU(0WLX'A+A9 +MU;9GC_G_2S2V$J62XA`#]]G20XX\T1E!K5-]%/<8/+885.*%RWS%7!DF)Y,6 +M"PATZ$+*`K65.A%G?@@8GBX:9IP?*&#QS!VG*\86H +M+;&IZ/!H=3KPLK0[D%0A%C$OPZRP_K!*MQWKH@5#=VQ>IKT@>!`4FHU_G@Z: +M'WH:ES]/L*:Z"><`2T>H$:!%NJHUL]\V0K_VUUG+R/773LM3"O&2W3HB/H^W +M"L=F.S;:,R!\R%P2D5"(:X&A0S4`7&("9/9$C6+$?8VX[N>^@17`Z[V>/AJ.)+A45'5/? +M&38]%[D5H].*6Q!,`6;CA!E_D+E?O::KP9G*&$3%_HH^,IV6 +M`.S7Q.BG$R0Q&9V+LNAP3$&(8P<:16`XJY$B3TW"/80&:2DX'*,ITRSQ`J'"F +M$0:IM9361]F7G1@4OT3G#0/I8`J%-A.]6*%_+%37S5>R[(F.F]T[B]500$%\ +M/DR63V(I?:$VMD#'\8U)(H.#<1HU#&_L0^DK$LL2?ZL]A.W(1HX`4(G*QC4R +MD$67O$I_(US04JQ-;3SHAF+N:<7+R=_AL=HTNQ@'"7N_45-2J;_0.//]9X5) +MCFT4@RLJ^SL@V@*.P>=Y>U6F`L(#WZ"<%U3F +M5NWI1:*B5T8-0Z#DP)_WW-UI'4.O>S:5=9E5A$WFVG)KH419$N/+D[W(X_2= +MJU=AU,1%'\C[A7,[TD,$!!48^.\"?\#?76E,R'?B.H'I*AMI$[YG^4[5-1N2 +MR_4!<^V$W[>LD4R6&X<.92^1D`E?5T14#;&K&*F5,\";I^QC(H9='R\'[/'8 +MP2T*8WWI[^.0I>'7914(SY;D&@L=LU0H4"WR;+)H/.]T4?O;??>M3VL,T-RS +M@RN64G0G"BB#(%U;^VHU,.INB,9OS-C@_B=^,/.K=@M]BA8.U1PAXD"M1X[TJR/7?SJAJ`87,H>[W[J=D0PVRB=?7_-Q`'-O@W"Q@N;R;)?_*\ENN6= +M))LX@0ZGH@)8PX2$P(@J7]DKK5SM@D44J@-7?(MA(-,\#F#R3]`<4S_:G^*+/;$.C_#)/D%"]0)UE +M.)WN#@^EB27]&,,*W9$_"1F[-CQL=+F:SNT#5::9E/1,7@Q6.GWZ-+M@K1M1(EAS:7+'H.!8M16_OHL#> +MPHUE0[]9274>]3JA3B\068D)23="'NCFB=UZ8_Y"C;_5)#?GQ9%2-'H-CI12 +M&-*-`^NW?$-(43)A5:Z[=/&M=164Q!KM2Q;Y8$X?LF63M>Z_ZP=&2S%./@=%]O@]9,X72QS025J':6_L&D"E]@>#LG-MI>F +MH_I.].AI?F$J8_!4E$H*/J[.K*%%X)9`-\]AA#PP-,>1`4'RG>:@E:[0;T62 +MVO!DV$4,LLR'(I<(&>O!FYCD&W),9.\*OVU0[SN_1A.0YI`9X-MJV,["S0;(_Q4 +MJPT`PT/]ASI\,,`7M:F/9[];IBGGS/56J'Y)">`,C*GI-4G$PB_AU<\E.7X" +MJ`)+%YK'B#!S!QIR(N_#2"4GI#XNXN?Q4MM.@2JB^3H3-D:R_?N%4^BM.E.7 +M-RG/3^[7VA%7-7,X0Y]&HT]8[](A:2,9_.7P7>X=PS$.M>PPI,VOFS)':*>L/=""@S*E]@>[>'RTBVUDKUWRF3B_9<(#X+EE5)%33=E +MQ2Q\?U<[.^S3L%5#D&E4U3&#;O,JY_A>_. +MJQU(YV4]O(_(F\HLCDOB7BI=:OULT.^XM +M,*L6LY?'GWIV,ZVL8+D%1HGHM6H&^;Y7#>@83.7K3:H>',T>G0FD-'-NH'\W +MU[NNF.']P8OC5_]U5-8>#=88SA;^%^T=-5A:T92U,S?6X]^P_@&:GACXR)S5 +MTVI:AD,KN88YZR+BV^4$S#S@Q45DB=?IC55QG5SP'@AT6LNDW\)N'YB$H!TJ +MX#!:VM!YT'YKX$I?UX8E,RCZ_A)5@X28(?U5.OKG/_7)=U +MS5D[_`+>4H^\C?@)5RGD"^;*!2ZHOYD&;#ZU>CLYD3S*L&3FCOZRHC.9VJ!S +M*I)V9%NCWZ/HIYE7(F@O"X>1>S276R=V`-=5C@/^4(.?`9U:<,PUR."+$K)E2A(?.(/;/ZROIV&HKAKLD3@6J9\KB8X%71Z3^V)>1;('8( +M,NN;P&<(A:O;X?]V$^AQ_$"R$:]J,Y(RH"WT2TE'39[#U\M.J6GHBLD/9[ME +M=E0A9="8O-A1(8O[+_>6:/.GG&FKI2*:I:3=4-@V27D2'^_^B/6%&NOUX_ZK +M0J6J"X(D+CK["G@'H_CKN1GAQ062[4IIP1$[(PQ;!W')88ZKP_T'SO2HGRBB6/\U*U,BZ"*SO[1HOI+,#``GV#QG6C_TFSTPP%/["+DU],URY058E +MP*1[P?OFG8[^L6A)4C^*JQQ*3X>J@"3^03<)DMS]$?3K +MZ;OK$T[[@=IW@^FWV7(@.BQ<38,(E6PYRYVJ;/9NA=E)9Q7NGJC[BLE(#+I9L.F +M+GB*/4]@3D>I>Z1SV\S.].9IYYIC'1.,UHE10#XDD,41Q^NI?<3!*WJ^]7*R +MX_]224U"T^GCP>$D0$EJZ:\KQ2;-ZEM9I9@O,\ +MKKO3UVQV6L;%&66Z?MXO)[NCD]NOP5JG/09Z2[K_1*,>1JUR?1\DVO'+]UX7 +MBA[[B-Q1KJ[[\.*EPPV*AFA)S3$630R&JZ7MW.G +MRY/O]PN47YHA\41#(78(AS#=E9#[%XV?UZF8FC`3`!2+FOKM28H58J8@^1>X0_R-Z(P +MH#O>JVO6S),-)]&AG\*S^<7$C^]X:7W^6U/2WF;0UN-VD;V.HSIQV9@1Z.;) +M,S%C!)"]YH*%6M$D%Y%?'B?.O'U=<+Z)*`R8!1= +MD/*V;))4:G96RIABU=:'%)S0K6).EM_7H9\(C'A(-@%4@20:D&OFONWNOTX7 +M)PQ6/L`^PFPJ4%[38;^+LI:C6#,!"]4A#S3($]YC7&9O_>T\3ML?[FNPP>YJ +MY,+,].KF4W8Q^6^3>G)OSKV@,'-Z_M48Q:3"IT]MZR?%X*75?E%[;U`J]ZJ" +M)4VS5>379OR$YCB:V]H81YY$(.B*0$OMFTI#3P3!:W[D6F1P#K%8WL@D0-$M +MV]_(N"@7CWR,M4X%&?IT2$3]/DS#M3O_Z$C`O=`,$1#2L-10V?#8]ZE+2YZ- +M(AS?(+RAF*'D\M/(0Y_85V#'CY[&YKQ&@=H&J2.KJ,:L\@J1U&P-[6@P, +MS*NM=`X_#B61S7"(+G+TMFR79T3>_+#[V<]*:B!/H2Y6S=3M0W(TJ +M;EGCOD"P\Z0BQX*NF<*,;0S]6_2EW +M!-#ZG_>C9?SSJ`#I"8E:DPB):GS3A(6Z$/8).-]7]B)2-`62UO3CJ%:*[_)" +M,7&ZQ_].16*M\1)3YLPV.SD9DC4NE:_I_1_Z4JI2GT>2SD&Q%?;>1[L4#`I, +M``I>])JNAZ;Z#0_*O(1#,>GX^Z"W6%,IFFW/(7#[MJT$>\SD8-#RT/U*QVG) +M4=YU([8BH2#8Z*KG"A2\T/&ZW)1X1%Z`97&,1T>B45B>PP4)>O#>U[@P,W]S +M=_8GKFXZS9CH7RB.F`7$@5GKXYCOUQ/45&:0"IHM1RKD%&UX,!))]Q1QIK1( +M\2*+T![4O17'[*CM0@BW9$3%X#N2JOK0:[Y$>[>7$$&8 +M(S.*]M5BK"04D6*3U^\0]>^]9.BD&7QBSR]!MEEK93 +M_$>])W%1_/GKXHX@2;(2A.@>[#B`%0DSO#24[FR)%T(Y_6,[RGN07^`JI?[3 +MM&$N]FQ:B!I\#FT=TKH_*(S?H)14@I1UH=&5E@=]$+Q-Y""7-,\]QJP#\29A +MXCOD7*];?V;M]5P)$.K"KL*.@67[/D_T^6WG:;V4\,0_%QEUOS4%S^ET<<?N$Z3V[5MMA#GJW)9NF[4F%0*PG:@(VG;!W/+(`;WOTNU +M0[#(-RO*HYQ)X`3ACQ`=:M!$N9G`%H>1!OA9G(*\.`0Z)9]J^M-RGVL1]KU" +M`1.;P[-O2FE'I0B`%^.BQ7"!'5 +M@IXNI.0PR-[D:I2M";=CVAW7JQ3';9#H-C(N>8FVT[J%L\>!5:]*Q6WFP\0= +M\BFAZGEE<&1PBIPSBFHSMGYD>KNR?D*L:OL9@JS0[!-VWTHU4'%7- +MZ4'N]*PEA564JGW2X#:>CMGV(SJ'N[J2\)K:-$#L*(2DJ+;\$/G"GD!RPI\Z +MXS'O5[PBN'$NROPP,K6D$GEL('K-);V+OG53!H"57][,C$HCOAVX$UYY0[F2:4K6`7%T\R\U)!W%!Y5?@$:T-/WW+AXX"]LW[Z_`E +M.PT3]%\0_@\R7&*R`A5BD8X#J/I`M%^Y6VND?AE!*FMX@#*RZ#&[:G4O0RLB +M>G^.[#%D"TKXR'F@D&4;\1>89H(R=/7I%NW[/Z->2_"SPP)^UK^;9\]> +M,*QX829WSP?3K'`B.T\2\`>RP7`K+7_B8)>2B&B^ +MWKGH-$TD)YG%V>4+]@R;?F[-O>LC)]NE6I.^`Q;)N^$S//02*`K/_"997(DD[$/T]] +M+>US;",)PMU^`.Y0:WE9]=$4W)2_:U3`VV@HJ2Q78R`7\&9+JY<0IA,U>-.J +M)2L.#PX_AAJ>@7H'+3UYJ6!$;K][$6EZOW4:,#H[%P@U33$V&?7X.#K5M6H' +MPE0XK^S+[=6>"7QAC%7&4L@&++B##+M?;H1JG@;[ZFA;03B8,$8.%5;@$XZO +M#`8*&)^[SW0'@78T1"+@,_,*"R"9'"&T$)]TD*JI2:)G_W9.[=M+C>RQJ8+: +M?S!.84*!@\;?W.@@''"O>XM[N@B<-Q[^87."#*3W0\_;\&NDS=%`!`MFUOB] +MN3_*NE77X_EG;^%E\%N6'+BC\=*&MQ4`[(/G8PO5&J3A^H',&L/J`?K\I28= +M??@@+'*[^TDT#=67PX/*23`H,D?D47BM9AV<\M[L8CM!9FXA82I.E3X%TML, +MU;?;&=DH+.V2-1=F8;RLIOWVE4N<-G%Q;7Q)HN(3^I<2:Q)#FIFOW&K4?$4, +M!TAF[+W0(,(O/P^M+*^9J;)D]DG5_#U/@K_JU>1(PUF/YQ.I"%(AR;A2;$.P +M&:JI_N9H'"[F(>5VC'I!C@<2+OK&DI7\G+>W]95L1VH4!H4C$YO-/_Q$3Z^? +M(H+LB]3\NP[95FZ?X$#K$'WS\'1-:N<%MR!Q;,XGF&G03[ZD`?1'(6$X/D[A +M\J2>;F@B)53'-P^;8[483[W#""PK5T\1"2)];T.NV3L\G`;I6^T**IK'0T/D +MC_=UJN;DMR/_AOE/FQ[^H?\7SSM!DXP/U)+4EUZ`Z9(1?D$O"U[ACBBOP&4F +M]MO@Y81LZ`'Z#`(.^^FC'I`0&%G&IZ>V^R)ECZ=C'(PARXO],.*:M[L#/"<4 +M],Y8L/Z=]X1C%#/Y:@LP'@C8F<,S93<+@]&JZ9<:K-(NPRA`JP-8"ZS3WJ8U +MTW/UNA5NZG?DN$)",X;4ZH:C#@;2_CW.ZWWFL99FO^/D5)XT1>F.C)CA.^`, +M'V&#*"YMM\Y=CO2:0L@WHSY1'1.28MI366Y +MWR5?+D;<-47!E`'M7L$R_GJI]I(,LQ_=$QJVGX;$$T0A4#MV@L^WMZQP]"-D +M"W/7ZUZ0N*)P@@09V>K+-C\WWBZ3](^]4R/[)!"%]5Q\>VF_8UTG%J4XZ9HQ +MJVQM0%^%KU96/BVY)EFV`X'>,AP;F82B] +MG+4A`S&G!BU=*W39 +M2]N-/P6^:$KU:A*Z4*0.ST:P,'E'9N&_(\S'/"CH[R5"Y`]):O">%1`$H(*& +M)O$.3HQ`??F*E,:G"_3G3\.?VV,9C!>X^#^O&<.&U#1 +MA",70L3SB"B*C@,6!#Y3B<3_3O4]ZSQSU_5HYP>B8C2>2'H+T.1+YB0\Q0/_ +M=@,DB*-.J5,T#;ZR4MS2PVHA44-N<)'N*G@SU',"1[.\M82(<%LA`^EWE*6( +M0+Y/8K?[+$.$AX,")/[90<=[/XB],/XWB;SJL04;NR6(F2=%^\E(Q*U79SF\ +M-FBJ#"+NA9-U?%';U\:!GIU\IUO8H$_V)@7:B748S90J?$=E_=%L4Q2U4%J\ +M$WCW;YGWK;#Z#;N@UY$H87T+U$1A-5=/UM!%JH]Y5B(NLQ`<'Y5$^:=-99'. +M'@MC\0(/+M.M)?O7?8Y:!I+GLA^H([OJ\=WV8#J(=(-T:\_7G#`U; +MK^CJ&'3V\[2B`[_A,315E"3MB7E.Y:J(7E@3)HC-V($J;W.=&N^=!,2\QO+S +MA47#*=#0WO7`">S935N@&[G>$7;VB)Y]#,F]B@RKP.OW"BY#&2#>DM6"7]X9 +M[H63/BQEM^3[NGY&X^9P"%HTH2'S2ITF89!%MN`C$(BCQ`,*,R"J0`$F`A3Q +MZ4Q,,B<%79@RH:5I"1Z9,.@BUJ-(R84F_QM^-ECIGG8:XA)MY4YKAS36\DC/ +M:S>ZG,#YEM.9C\`T#:/+W`:ET5ZR_4#=Q\U$9ON./F;4%<.3?K]+.WG[I-Z1 +M[/I)LF)_0X8T8T'5]QMT3(.(C6L-VG*W0"'T&_J4AV]?RU<(:+BLV,]>GLII +M9ZW4L_#[8A^"&8M$^1DY^G39L:I40X$=0&H'P.A/)Z^]HK\'FW#LF[60#F^Q +MOYOF=O%L`GS$A0))I&-VH&S5M`84P;2S(%20B]#I0<8%5@PT[Q<$`3)([N*< +M3YA3?,*CZ]5910Y1[8W\P^MI:,`6=6FO*N'EZ<6,CW2`GUM-J(X^0+Z%I'"+ +M5`W^<:+)4N7CU:<$U(BI\2HD7-#*Q4:[%'BP,!O)3`!G/[!<518N5W29QW:3 +MC/%%\%%0'-"5XKPKE?P@JX#!P<(Y0@5A+:^4SC1O4)4Y\D!:OG$MCM;FGK*( +M@!LVG:Y"B["X/M#EN2(JJ9<^%SF@[+AT8ZYJ;1^Z[08^^'2"_@>B^OZ5WVIX +M*?OGH&52>H!`EB*?4OE=)8F`IX)",@;L)E$SQ(7ESQ298?4A>I:IUR +M"0S"HSB6@4UAA^']JSUI$B?*M$:['3:X9.I:EPP\=53(;FOT74A-.\LOUP"#V,6=?'U;[:,0; +M4O6*+1:5F*9KV_$-^(<-\XP@BH\=JF#YW]X*&O];0[PNE>1SB7]?4>%>U/&9 +M!H)'^\N25\X5P^+^(KWL4FSB-@%*C\A3'O#Y]/*.J(@8V#@76.!$Y=0J_V(\ +MH4("OV?,QCQ^:1::SP'J;NX?N-04-!Z:=DNR2>ISQXGN>G+7=$)D)YVX>E8) +MA7?LP[$MB2N9%;;*(V3[)X5QK:]2[#@1V=U<33P-%N^#Y5N/CLEE=]GZ,V)P +M2+V=!\?++D!NR&)P%I.\RVE7QY_;T7-A/&?[W^Z)3U6P=^?B!73^-HM50]3( +MPC-;SHZP4&\`QVI2S-.4=PWWKNLSW;UHVS$-GOFFM`P4AQW<=:5691V?`?U! +M6(C7Q$6V#.Z0^0>\>A^>B=&*XOPM[JNX+K?+?['G<1:Q(U990D+OM6=E#8)'_+N0R +M@GGX?'M-V;[LE>(D>\\_H/L;.- +MRR%H89TPM;0>F+?GLNIK;H'52G.B">GG3$$0HN9OH+CXP?BI$_.G3&UJ4ONS +M?$`9@N<_F.2JNV+PW/!*2%W*MTU0:!*8JH_81A[H4N[$R6S,%_%891WU@;V1C%[M7.HUFA*&UTW2EM +M?(21B+)-/1#1"@2,3H-Z*`%9\+R95#3-K!Y*%*4/@-@0Q\4>:)#4*A=E_Q>' +MO_>M?)\*%1FO.D[<_Z +MLNHMI4!58NXG#SUJ<$\UE:M5+_52HI`L[T6?E$N1L!8GS5M?/@$27P=L+N)\ +M60.2`4?W?VR_Y4!KYK?T*KMP"WUPIJDF':#]7]HDT2OUB.+%%IY6[8(2]/P_ +MQ:B6-+G"'W1RB-K^LRT5]S[!I$!17\TOKC+0J8ZA-S_^!X*R5LJHJK<@'[)'O0<#/K=S.EH65GEGD +MSMWQ3*F<83R%3T/]G&]*MSTH"'L8\'V4_.C#^P%GP?MN>HAVGFWD'#1?O?@X +M9QD@/OWP9MKEQHE98!D"*9N)T$FGVY?9CT9%YP#4AG/TR#DU7]^\)2!73*-A +M^.NH:>#C0DOD,V(2":PR4,WQ*P)OR:U!7@\F'*D1=:;X)COS6?JP_A]N`"!J +M(N;:<\8TO8WD7-.(>@B?JW6J,5WLMRKWB#")UAXB4$)##SBA&TR+%@4=5=CE +M9()ET;6S;U3EG-MRZ1;<@9M$B"08?M<5GO/Z:RP>+[*IZ7FF\$4FM@E0W7+/ +M-!B.19[(>^@E3^#!RY2@G00I#$?U'B_V4EIM:-S8W^)!I[^J:;\?-'OU02D] +M^553]MUR9TMI$.]?:ZKQ/3*(D0O9'P_PKMV+`5V96U5O$7_9AQF6T53UPW9$O.5'$:`HLN+Y(HK$Q0Y8E +M5%Y&VK4&TP(RIP>DNORAB373;>8[J=ON752XH_"[L&YD">2[$4<*H#,N=+E. +MN6D!",@6BOT,B5"7[=BAY>Z>X&5,D@="[/RKZ^YP3IS?T6^6^Y!I2:@$J`V$LWVB(%_GUEVA-8]"(PG\MG@?E,UI1< +M6_6)@Z,?L!Z_'S9ZGIR?10\I7RC=;/^@KS82)7FGRU`S6SW_GT]KO/C=QVFT +MB(05,ZW9#DZ5*.S8W,?HXN`EV'7-$F/(V]`",FZWM2.],)>K&@%[M +MQ6$$A[#?<+.>'IAD$B5M +ML,,-S+0B&>3/UTW//I!(&YNURK;!ZZ57H<1Y2+3Q +M112TD?F]5>DT!1I/#?PO->Y3-PV!U?JS3HD"M35(2Q'^R@H9PYG27G@Q6\VP +M=&/:;JT$J^-WMZ=#NEH0I9=I\T.<)1$%Z%/>P,B!W_I)>NKKD/"#BX@*&Z&H +M>%(P61JS7JZZH9T>&PL]1,2G'\U6EXJ>>HQ!#@F*&F7'II@1U)4/X&)T5GEU-L*9'OGMC7/U(M\/=/*M7OCJ\FZ,`!DH5"NJ7 +M\W"H>6V>,+,#A7*KSWTCT"T0\R&U)^_K0`2UY^"RX(Q/WB!2G[)V`:,_QAPV +M\%\0HCW!)ZR6:4:]^8(O]#WUZ8C]'KR';@;HZ9C_7.?` +MNK%%$2T,A9PM87Z,K7+>[-Q-P4]UER"%UA)M^WS["N'O0XY5W?%7A1%(_PA: +M`?SO1[YH7!T6&D5AQ'&V6P0WBG:T>I-\KQQJQRGW9"RY8#NE74*BX8YDIF$F +MLP+,NCJG:\3ZL\=5[D3JK9`JW/`P^9K3;CB0GFB-I2H9^BW3-:!"*/B]I*1N +MQD!W[EUDD1>[#H67'%HCB9Z#%#RB6#UTY$P0>G6MKP*]YZV#K!$O6N[ +M1C(`*RCH%9[K&MP%C?',AR(-"K\]^/[#SC%3W9ZM[YRO,^J)[RE;Z9;+H!O[ +MKD"64&>U"G3>;JM&D93D1'"^R^)!WFUS@U7=1%@L7X2*,!(&?GV8ZO5S_SXT +M\DN6Y7Y53&O>:B9D>\,J_"9'Y7FJ??+%@$Y\6.R#Q*Y6(9+H4*B"!,SVMQ1_]0E*?2'US^F/IB6$D#-XZ +M1["8BR$2+S]$RSR;W1A"8A'-)F#L,H4($RZ*A7$Q']?>UT_YPZ[PP7%>@\K) +MMKGCW@I]EK`WE"''XQFVWX,V/X7;2BU`ZMY4]'ZXS'M39$^$8=!#!,[5($I] +M^*W<'-J1*R5GU`FUE^!*(UM&08'J.5,.1V#X4/]RB;_X%HA%._7%+)DL;8/= +MWE?R4OALR31U2T>`+WHU<[:A)T/5J#=*'%Q3D,Z,-O1`@:0@5T`\O_C[4%@; +M5S^#+>URHRBZM"6:2PB:8/\)%MGRE8?"?JE)L3B25&/JI18,IM-HG0.&+F'TWE). +M-;TNI#R?!<8N'K](U9#2D7[@&M7SRB-BS!^<\1O5%79T4*M> +M#X*FN_RK@-L)F&FF`>02@R70_RJ.>1(O/:RZYJ>9@=EN@!4I>/[:!#!9<$PU +MFTB0`J;",KRF)]?TK;I?Q365(1:/GWH.0:YL6:B>NA3Q//9AZB(Y"66UH")3 +MHAOS,4MZEA7#[F:RF`,ALO])>:V^?TX3O9%)%?KC;;A*3;OIR<--33&^^14Q +MSI=M:TC-6X\=-GC$CIA1/NC]/O$P6->94TG8"Q58VS.^!E5LBA($-%$L_:Q& +M(-YQ\3,*Z:U&UP1_=-XK5'$2RWU44C_Z.>*TY=PR(1<:8UE`2^6\]UG`[DK\ +MDU?&J\%V-4W.AVI,X2L`9%=SWJTCJ+=/%6J?D%\L=5LFC1R_01[-_'UKO7Y$ +M1:24S84S<(?B:7O.*")+C1&NQ3'[Y(A-TD'Z`N"?:4?6K%)"_W+LXG1FQ#"T +M+RX^Y9&.,X+`KFD3!U&BW])6Q'L[E21DLXI[)B09 +MB\+5'W8^:**Q#Y'=+7%= +M_S$J20N^Y4Q-XAX$-N83J.HZDEDN>TGG[_#^@_RGPV`A_%I?Z-7_5DLZ9DCWO#FUQ\OU#&.3FPI1)_2--+_1,H8"!%]4#R +M#ZXMB8:#N1N,HZ/#T1"\[FR/(5?N=(#K5F85F3UXEI+`Y?,[VF1B&NQGB.%C +M8%Y-KLPSZ:;IZ.->+>9&6;F`2"T'@AQL8>-7J+.[VCF%<5"YPX\'(,R1W0GU +M?W58J,.#=,[O%3G,%<$,)_D6J&(6Y6$N!2R%@Y_,Q/9[CRK_@D$U%WUT;+.X +MG=\671!Y*[*6_FPE.L]67G".+8Y<62169F-X-H%L\C\3`!`S8[;T +MV4^.E7CUT+C9K^8.U3YK^%N=%69X>/J-[(.@)5&[Q_`6%)."[O4^$4"Z^K- +MVXV8$/M&7W`@I:EJF'RNQ&L%AR/S`>#\8($U!13(/2W>;H8)E:R"^_>OA[J: +M\)^JF?6!P-YC[EQ2%BW`-9UK!,]?10=QF2:/=-#7\4N7G$X55_6[D,>P8YQP +M"DO\C?H5UHE77A/MBQ=W>\50#_YU8_&3[`E']6E]]-0.CA.\(87G4$1(S5]W +MT284:JY3GC7-;_XS"/\S-7^=/!@1.D;@3RX7VAC_:O.X?9M9>7=408V*5^UQZF(WDR7"%]8/ITF9JU@?0#^!N]&-#QGK;45H^"R&P.%FV( +M"/\.PC(RE#"FG]3&;+]TXQE2'8YM"'!;+;2+5P!/8$`5>*T#FF>=YE(F!B%' +MK3#'I4FKLW]ZGB47[U+A2_,`N.2XLD7(.(6^.\#\&V98NETUC_R+GM7^!A(\\$`FF[EJC)T37%:2U`TLJ\ +M@7<>"'"0*?G73-5CX?%F=JEKV=7<)$*>$SA<'%C&I[9*F\?7$V\B2M6+-^3= +M_C).`%"3S=N\,@A_&7"\@BF78057^<0KL4I::*WCZ^]`?"30N6.7OOJK.F<2 +M6?*8*'4R>EW=]0;#:P33[0*0OZP_.1FU.NN1.@T@Y^TQJSL\7P'#K%-DX2:^ +M(_0U^BD3#:KK?!B`%78VF-M,4V.A>-U-54Q+Z-GK/C]87^;YS[>]&YA_##+8 +M=$".ZI\')GV#5J==*A+JC%EW.<@74`,V"I-E4(:%P)+&_PRADV-T0%.H)2T+ +MXW;*5*?)S +M!!K$R]_VU_EH#L6U+\M10UENVS=4CW)1G+(R+'.!-O<*WFRL0: +MN:N[K0\T::4O(N_\>T/)%U>:`;-/[M!94@%-!)30;#=DBBY7)Y:-=++MFPD]3`C#W5`.OVCK +M=O%Q/'A5K[P5P;?_YI*C'/^8`_PH.U'RGH]B^G>$WB_0;)OKP)>[D<:MTEK^ +M'I%J6H!R/T"(@7P,I&A80&S?#/=S/LQSGZ&&N,Y>88QEMQ>DF#YU';^S(F1F +M&E50X<[OY"?03LZ.BK&JF:IGU0BT$JY:W)V%F'O$]T`BCAX%]J4&%PG9@9)##44RM>0 +MQH!-9G?,5%Q"$2R39;H]Y1QFM6))H#`A3(.E&H/<1D>@N<@2G'GPY#-$K(HG%7/M\A^W]Z_ZS]*W2I^=:D2@$?:+V> +M3732)H/>CSJ>YJQK+\^LD/TULAX;1<2K[:/[\\P;I7/6#XX8N(,K!.'F`N$' +M1"1ASHY/XG]/]D`TM%/6VOY#"8`P*`N+PXM]FXP0O!O[)5.8'QVR6E`4%;1K +MR@<)NLBEN"934AZG"-HD,[T7`0EB=>^D"F04]:AS+C'8TRGH8MP0D0HU2_31 +M4Y1EU.+^.)Z2;#D3!:878Y7F+'>#CN6>9$P)XS&H#^,0L:KY+=I:D!(=ZIU] +M+>*C9VW,O7'(.65ZR@MK#3""F0ZR(CHDJ'M9;.L,@H7*-UQRJ3QN%;R;-"L_00^Q`3PY0E?="SRIVYFRMO[A'X&&1=4$;->RB?TH*H_F:C61I$?@[U +M-U^VM<6G1L/5<"CG^K.HL0S]6=72TK-@I`^LI?W-.>70=*Q9UFIS90N\WR60 +M$4QCPL$S9.85MG$DH`\A)V*H*HG(]4JCWGYWOD.G"J&3>LBN&M_/V_+NP.(% +M;Q^HS(32H[00F>=#C7T\..0)Z)GU6]]`?@7EX^_>@X4/\@?JYG6-HA>G;NJG +M2DP=$J+Q53G1M$B8(*V`>_CTG;&Q.KB[U8%!.[%;<),*@6R5TD$NO[+?+;K^8$E9 +M"2)]M57#$`]8=4Z=PYAS&@`,':T5VR\"INK+"O+$^M$_%SE&^ +M-E::L1<4U?S3I"A-F%RY?YYRH9@VL3M'_5&> +MJWZ9H*GMN8"9QY]L7T@5M*1`J7]9]A$_@N%>D'%R`U'/"VB]RHE+=TS[B-_` +M)>C2Q0BT$-@39R0*S>M\7G/BLD')%1&E.*D@+)KY=26,?LMI3!&K$L%1-F%K +M("=U+#^@\X&K28CQ^;46:ALKK]&J-1B8#61?:EUM_158K0?+HE3E[*I_GY;Y +M;5[]4&5\_[U92G/&!*%R0;1W1@@I%>^U([I4`/9M=D&UO^\;'F+;3FP5I#&[ +M<@0T+[RZ$%_U#U$,I[^N7%Y&`H@=DYZH.N<[M]![;(5G>)\YY;.%FITTR^XO +MTI!38]"8@>"`#W)HJ!^LC"2[P.:2>'8SR>ZQT3)F&*=+TCTWV0:5!4SEDT)* +M"W_L@"92U3@5TJSPRMX<<+_7.E>D85JHPHA_;5B:C2.GYDM_4.C#WW#ZG%%7 +M;5SWKOZ24B#C0$-Z87P]Y*[D=_^[61N^]=LW<.KNMH"U,)F2)]ZM$H7WEIJJ;S+3+UKL=73U6S?@B8#X7 +M;NL'-_=$P-3HVK=/,.M\,KGMR96Z`WUN[&09L)5QX^S7TQ\7=@%Q';0 +MI"R!2-.8MQG>G(?7B$IZ&`*YNZD.RH@^,S1H6?-ZR0P]!+/C5.RGM.@@..EA +MXSFPBO00'R6=8M1@GQ,4I!-GP+*$3!DNWL@$IVK']/L?!N0>@>XV>)4M!01& +MQ^F3-=[H;-^!/AX_DC/0($*H7;V:U"F^J_B:UT[C\8J"5N^Z[=#Z/7` +M9.8+5IA9#7[ZH50?/;\YT:A?#?U1I3WN;9O+DRM[2?W)4V%C"<+SH[R3KZ!H +M3VU-"^E@D/$)^7QB9A3G&Q_QWD+ZPS`,TAAXQ(^;IW2$D,*5729C +M'#!V3`94+`4IOW=O\NC\R%;)C48+.@:@Q!2/:0($%C4_WM6[S0E;(QW`%XBG +M.6%7C7I5&_WB@UUYOVT6M$O?QC.+QR0;9T][Y_*.JXC/!L*H[8LJ<9.0%,%ZE2Q8VCC$ +MHY84U[NKV)<<+VUN*'<_=^#<(9-N&:QN3\<\.SQP+'G@C='=O9USJD`?IC+)="L;P>!K*P9:F.=HFV266YV#L1E +MK;$(CS(HQQ1H.;!8)O_NGVLE[<7]OV\A#Z%^(T]S=7NS;:KY;Z(>),U\)\AT +M:C?M/J4O];9Z0_(76?"^<23G(#]EFJAV>#D'O&K^+W[X&4A&B'*A083`EWU7 +M:13OCW=L!-DR+,YV40S9%D_/QA982%?1UVK6(-!=?$QTO:Q*?Z'-/[$QK(9T +MK/K"$;NKFUE<'2R3;DX!63S>7&C(,SH:AW(I2U^/T>Y&=@_&;>,P?X5>$QFR +M)!I)WL^'4GQ?MG##,,&=Y7ND7<%Z!VW($YFZ:"U.;D>)XCTLV!Z/-=GUF15_ +M_32%MOW+E[('?>AYZ94_Z,EI;A*Y";3$0ZPO"X`_H0X\9IZ;.`A/]]*B,&Q2 +M;>2E>C_QNUM-,&I[8!G063 +M"#S*1>,U)<,)'/Y`;FU1;^K`@7[_@]E+&R22+5<8[4(?&.'L9G+E@S>6FI;Q +MPFHO;VQKS6%2<9CL5NEVD5F./J:C]DEB0.%+-H=7+B,W5,(-'$B(#Y!T(XMP +MX=#,&IBP?U2:@2'!P,*LKJ!+`KQ#("J6@'((YJKZU,:[^]';?Y8V_.J+-^YQ +M^[ZE3@W-UQ,.U=F2D60R[`_(//E1$]Q4N"3!]4'/";P[8<+QTKP52*0=L/S" +M:J^/05V!B>T/?>&$@&(/BSE3>7$FHI(*0]#E!VQ3S/<(H^15CG814.1J5%^B +M$8**G_5HX++S<96'5!4K9P\#V[*Q6,+1$E`P9FZ2T;$506;2*N91`2#696@J +MRR3XQ9H:]OZZ6VY+SP$S6MB]*9]58TI%19?Z7!X\SB*D6]Z"B@=MR0 +MGLG#*!?&[,^RK'4I02H+!?2!Q:F)2=$PN%";=,6'KM>V71II5R%+ +MD.H1=U:4RR+O:"!,AKS?U$L^5\7:3N[`D/QY"R%2M*G-4==&4.T`,BX*C&<; +M+5EJ97^SRI'K`NAT(BHWS=SK$C?8%L]2CL;$W#34<\:U>/4S-YVHIVP<)F2B +M\9/&U$!3P(#]CO:17&+!Y\YF0H+"S6$YYIN7?-G&<\RPSO:)A/N4;=_*(.O* +M+T=HQ#Q\,/15CRA6+XW*AM6T6L#W5&%EV*^K@-(XH3L]80WCEZZV:F/,K;QL +M.1PKC6W=O#!)O5+NP:2SLK(F;U<,F_,'=LC9=G]'4`R5ZT_?W`>'1Y!B$Z@VQ +M!E,)F$WD[L%/[V/*!RM8Q&+2I!/T.\=_+*6$CC=G/('=IS4KF?W5(O<3!RG$ +M,KG:@48].YD$.VJ6+:YY/Q:DW())/<($G-!&LPOTI!%?G7B0'Y1"GW3H@,R" +M,D.U+Q&WBG,``1:>B_07,V+,<13#=QVMO!9<6I5/Z+\DTOTTUT/F==+F1B`$ +MU;DRX/\$(K'[7&_RD>7]*Z,GZ&(3E_K/Y-)4JYXG`C.=977GU(TCB0!LH$=^ +M!''^!)&W"2AKC\?KJRRX-3-<_K??-`)N.3P8^:NI7SVL'^T(]^R6"K,U>'P# +M:S7L5/OL8;TN?19UUQ:[L47QM9S1!1A[Z![5N82J_$0*K#@C5E`!['ZQ\%FZ +M2ARXPNRN--[:2<:9M,3%8K/-U2<6P>9Q5/_G37VJ,37P#GX#[@V>Q`=4`?^M +MAZP6YX]!IQ]UE9JFL9A=D@2LU'9384V=&M7/G-;U3=J;N&)/43S+\_QS&,IB +M[O>N.6#K6'1MAS+,JVGF&7ZI6FEVIXU^J]X4HKFI\+P)3;:(T7!U4D3WENV< +M="0BV?I[7U?!VA^)G=VNYR;IC&05D<@L/'S*DF0JHHG@W\?A$%MBRX12)4'6 +MF)I9!\'L-*U"M)Z8MZ%?L'],WG@9%([9I#=PR)V8B>N2QERH7!+RTYID+7I/ +M!;?5-.3E(:?B?`CIQX8-ZYHORK^V-7+<#BAO4^2.CMQ'$SB0L0*N,'ZAE=D$ +M%[BFL8_*)SLFRT06R^WUV9'O1R,*0G#D;64/35`&FBQ>D"+4.3QU`3H%1LQ/ +MCPM=6PY>"Z^CJU8W`TQ67:\M'0^30&8$1G;\HY&O"_S]#$A?B-;A>L67GVY> +M*M*FQGUN:_>%K8Z5*&['#],A5L[%&:.N"3:]5H>^O+3:8)[DC)RSC&U3T:@J +MF3NDG=(N3Z5HAUY`7W:W$RX5=-\.%N#&YOP]%,"__52)UV.L_)BTQI'U!XSKS:7QI;D7KJA +MK+>PK_1539#+)^BZ;J?4=ZNI?=7&5X-O^B)EF=*Q,5RX_N/5\R(G]QE8R9D" +M?QWC\'7OW#O(2`,@5@39P=45U.+P]&TWS? +MKNP:?S+I3CH87+DP*6?6Q`"VLEW1*R++M^_';R.BLV+ZB\JT[DP[;4SWH:&O +M+[.*J>UX8S$4>Y]2"K@]%KR('8P/>4O6*XR6U*N2_`%$@,BLL)Z6J^!$QW[7 +M57-YVHJ^E2RF,H0/80XSK)DG6EV7>)QJ8SN04LG\10(B:#4\WF0"UZ&DX'/$ +M7O?'5_KW3\T#A4CLY9=V.2IE#4!8&S,?Q645CQ?BO/I$'N6^4]?#T3;#1D]I +M'4%=Z!\;XIH']!+RE,=^%#P,AQ7\$>7A#4-_PSXAF200+6?=R.J$P\L;P\'3 +M-S0,)[>1Y10WI.$Y]L`;FZ<8>9'WTW^'W#2E3$2[).-JGQ0YQDSL"69;K.G< +M+KCUR7Y&8HSUFL$YB$<$:G&/L6("TOR2CEBR:O:2N"%^SV1&>8^N?E*4F%&1 +M-MPMICW(%9=N3!3R.6`4%N@#(M1\*"IC;PYJQY)DRKX5-L%_Y%Y";TLX2:%/ +MBD:C4^:-5NL.^L[B1XB2D-/1$$2!6#OKD)V=-AG+6!CG#G6]Z#(RN*\@RB5- +M'X7\&4,3A]S&XW""8)<,Z"6]>)*!W,I2I*FBVTREW-2^K +MM&T;-1)_?28$"%6C(8C'OD;.5J=Q)KDY@T +MU('P,M39^O<(JXG@B&J=M=Z^FG9"@ZOH-'L46![E"YRT(S$&1(Q"?3B`N%KM7[N5Z +M^6B=5/H6?W`^;66A%,B7+G&\<)0:&`2-.YRA'@>AI-SE+-%39R+Z+%J[%>Z! +M0-=($.QBV[R]MF+(_?UCC5A=GYUOQ[B5.()TM?!)TR;_*L^!B?5HFMP/Q.BZ +M+Q?BO0QN\+&BRHRF$!FQYRK_F^%0920OZ[D,@*V#-N4 +M4LLYP;)^(.$_]XH]&L'A-TVY8%LR$`+#=P,U)<3*.,@S6_^65$>*58#GH+)Y +M\)JS&O7IHL^M'I5*,)7,Z&T40X2`J;C2`@-=KE-MTS':6[=%`[R;1D&_$(L> +M4):9[U8!8QT0$8.A0>./'9)`=5M#\D0I'-O?.?`>IPYNB>_NF?(MST]2%3^X +MS)"!]#3%ZRAD5L(OUL-"8NVLW)0BRX?O^D@OQ0&7.6;-SPS*B4Y>SK +M+C@L$$:%D#QE>JL3=,FY-9%%*4.CF..\ +MKKZ7G?N527[9'.H&6@:F30#N^L_/8[EE\@/A87\,3B%E>R@:_6Y92"P:(!=_)\3W] +MU%=VQRN\2_Y,"$X4`.?P!-_JT"\#;YLNV0(+H1]^+1;LYWDLV6'V.30MPBOP +M&J0=Q@E3'R`'9`>D=5N;B>D[N1KCFQZGG!^1.'S'I0&K(=G?_2^"!$-2K;W3 +MT5D,`9BO'VK)S.&/QG)L/)P,-*04K6-N_%;XGF9DZS72V3,"+=F!"]\*3[)D +M`!+`EW5:2@URN9WGAHJ(CCTBDC1/C`ANU'@4L)GWHEBW*QI.TE +M'+#Y_1C"Y6;F[;G7D_E7.%>,+'Q4OB>X?6Z@/?0H0DQH)V<.OWF%Z<;.H,L[ +M!<5DC*+!Q[]S3+5*JSJH\>[MEEY^^!H<[>L"[#B-JA;NA)7P=:KGHTN#!86@ +MC!8]+H^`E75L);I)(O>-+\DC8\%M*6]B=Y5-1ZJ&J*JM,/S>))B:^_D7CV'X +M08`^K/7Z#XSYZ/0=[T/Q*JW<="\8L#<.!Y25DN4L(YH+$+/S^.9/F.PWJ2@Z +MJL+>KB2X/_`=IO9KH>%"W0G`777QU&G9?N;;#\F-LU&6B"?.[\N(52$G]>,4 +M6V4NRKL#43W249GA_"(KX*'`KWNC3U%9@17@.6CRZQ"4N*Y2&.0_V4E.1*68 +M^DH1&:58<=5.555<5%[4I8M,*;3EH*T'P^S!\!&/SMWK>D?/H!\O$=T`,9%0 +MB&DL'O])WG,5'4W+`^YC^>^ZJHL@4S0C!U7,Q[GA=CMA>9W_$%!.W!#MG)Q4 +ME=E]K$&)NRF[2A;E]Q$YD=77XHY)7[^F59W)IG->F+(.%]46\H6G"-H9GX>W +MO7*A<`-,30MX\S,[SEJC>M&CGE7/LA2Y>B<9Q)6A=#;=X??/W/K3ED1K?YZX +MNGK)53T+N,H&K%]F:QKVRAJZOS'9Q$#>PF7U*DA!.C#UX-RQK8P851^NXG"O +M]9.Z/Z&8AAO*WM!5+%&!2.FB:;3P<:'W^*GKJ68:$,4C$K;[/D7++V**+7$A?X'-):#&\O<#X&-\+%3OL_I/@IW +M9;T=^>OO/3L%8<:S0TVDE';QZP#]B]6X-X.(F58PH%>G^VK=."BWJH;8[I\? +MPFEFRQ4'5!7'F*,>]"VS\]:DY)$3?VW1F_YA]`HF76S]-""JLY=)SXW58@)& +M\`"@J,_@H@4/#2/EP;8C*M$D!5!)A""$8.#.7`\R[[Y(8>2<)-"I%7L))!%& +M=OO9F?9%Y-6J"4GIK3O;GQ24_=&7P%9K!/8L"[,0 +MJ4'_+AKIAGG-V%K(17^5TN@V'L,MU1XMWHMS`(K;.8]B%F]L1V&=4W@>9#*8 +MZQ;!!R%9^K:3?H[_6`GEO[CW[R1#R5'U@@9H,9^9'6JL7-^+F%15QH?5&@L` +M=8G)U'`7&'@=YTZ2E0W.J^^<+=S13_EU,"HQR";.,]PQR$,%8Z1XYM:C6WKN +MHIZ%STB=XY8[8-B5P8`A09S:_4*!\81[1(IX8*OK(S$1Z"T.A$=%#F.ZG$=< +M$\.[=LJQ!FE2$>V`^/\9(Y:F5K*C90_2%"Y-@"Q>[>&=\3$WT.J73:N8IWOB +M*:;AIBW'7$Y;#QDPGWT(\A^UO@8OI0=;DZFK7^@8M"6W$5]H+?5Z^CXW!2W,WGDIUD +MA!98^&B_/6=^-HG` +MPOW;RN-N2?50%A9!MUVBF?Z3(;X]>_3FB33!2^QWWE$\>+[TB>XL!K9(DR!+ +MH"B7)1/C8!PUA^$RZ7TA2"9`(')1U`:I:TX\&]HP(X1D[OJ+4=O,08]X"]K8 +M8)D=U1!QWX7F_O28!LXCW'0N&Q#]EDY$2&.UF&PISD4_/O).PF;2035_"9`. +M.3P$\"F@:TYV;H2?E>V7R=WJG0P6?8T=%=\N`.^0<$XTEM->PIZBMY2^S#C. +MQ6]7"@Z^W^+G`YR$026^6^9C1Q>#]Z__H$B1/@T!$0T$F_$VX\8$I4'T@3(^ +M:H+X5G"Q?'YNQ-#6(/!!?E36B/=G?*YD@7C-TR4JUGQY4/L+OZ*:=3\93OS& +M:*&E)+JTFLTT9150UBF"@)DB%>M5@D4R?)"]%"^81M_R0,J;.`9<&%6JAP1" +MB4WG&JH+V.8.Q^@83FMVICB6G[/2_6,+#ZC6EDB&!?7T`Y\3O>?JA,B\$T,Y +MPMI1%3)@*"P+W.79-9*GE)U!UH+;K?G4[@Y[4Q.Q9!B>QFZ^Z!P6@F"WC/(: +M;*I+[\F4_/5Z7\E:Y1"(?8%++I:6/3/1SS.6=<4J:NSKE23-=B^Q +M8]$B?1&>T_0\B6Q`WA2>$&KDD4%,X!8%P#?)0,H'?=T^2BUCF!]+!'N8Z:Z; +M#2S(]`S_!GI5G@.\J2]X14E(EX.VR])/(LG"GW#U6&./V+BIOBI+?UM$,SN. +M#J3:K$1DZO=VV5)$>`UE?`?\-$8#I#T$#_V]Y\;IBW[A89?L_IKP2:86D6<[ +MOX[GOTECB<*ELYTD5'*[X]J3.C]H)`7V5&X]A07&N(`7>!D'#':F)Q48E[V@ +MRJR0#)3!=E2*FL/\`A>(W,<;1;EX+!3^'.3_L,U]H!+)B4^SC?BLQY +M_-6LBL_2B)5J2C6=(G*]('G-"RJA5!.YP"K%-P63=QI2%)/F&'Z(:_Y3Y0!? +MT'"5WF(`%>7E:G.JE"`,$J+M^_@MK5V87(-NSYX&N]VVE;T@,8Y4,/)(?V)N +M&UW9K-$P/1)YU0E;6:H.TF95VHTRECW"QOZ?7C)$Z+*!0-Y=D^`<9ZOAP&?%GJ-P +M?Y:Y/>[U<"[_>-$0DU#.YU?BOG(0>5.@34%L?L15P%W!`J4QE#IQ%1X;QAP/ +MAENL"WBBH!=(`J+B=,T'"`!4E$?\(-1%2>$-AV1.*H% +MSRM61Y2J=-)Z_)%Q]A,N7=:ROO4WA-TY&]1=5@K(%Y[:7&?X&8>CU2>3P#.Y +M^EOVU=+<$5"]Z+=3_:WLZ:FO$/FW\G:"1`6Z0P8E3<:G2:UT"SB."USG1V?[C]E/+0'%U7Y%/06+^",DK$$4EC6%]Y)[M_V&HQ!#A +M5>PYUL%'(H\"4@VJI31=#-; +M663X%_DY8518; +MZ67SAT,H+&`(N(VN.G3#VZPI&%TLUM5'KJ%3"KJBG=^N02[U)EIZ0:XI-(<- +MD2=L>=YL$4]%8?&+P&N=DI)IED'E>H2D+@6V0XLF\VXMD3[QKUD$\*KX3,/A +M47JXU%@7JW0#%#7\3))D?NJ,W2T)2^9V>&,G5#NSLZ=FSQ21;[ +MR&6FP0F#8[I#6+EN4O#4>]75<(?JPQF/&,D.9/SE-\#^Z$TDY)^I*[#H_[$6 +M;OFH+0*-9:$:II-PQ8,0W7:SDT(:J-W)(->BRQ?+(!/+>,@DJN5UB&DCRU4@ +M;UCE=S(A%SD#W\(-CD!9/\-_'C`*YL3PG`NC"+S:ACJZVH6J\UI7JQ)"F0ZS +MJQ;\_HY?DJ.D/XB<7M@\7TTWZT[=PJQ46^'[\!LT1Y,S%YW:\I-)OUAELYX? +M^$$)\HD;],PIMXU(:0# +M,4!R.P&[,*`Y:=B1F433%88JLI6Y_RLJIJ,CL92X6$2Y=RVDQ77PWRS6F75M +M"9#42]I3E),*7I14Z4J>KX2K^B'P-9.P<'6!:OUHA))U&$YR:Z:`XB-A +M8I5[>)U@COV@!\?W]PO'D$[+_/CPW@`!>H@*GU'\BH3"4B"_L4B*HZ)VX5&X +M8">=01KZX)B2RC,XK#G4"(#0^5(Y9P>WSVQ9VG^-,1#[P__E>P':U#=?5.,J +M5BY#QMPGP&3(Z&6N^7:F.JQPJ8*_L2<8$=G>JU`= +MQAIO]U$THS^F5C9]0M"HU'#^6VA$XK7WD]';M#(\33CZ:_T_<;19NZ!&)XP" +M16*I"+I@:_8#?9X/-N$>"V%GXPB3(@]SK=)CH_8&6+?KC*)\AY_G*4T_:4LY +M!*%89]DZA&4$RVBX5 +M*X;=%$-_@JD#9\K-+CVVH\.A-+XE#I.]U_K&NW]G[XN-38K1G%Z9-](PC1+M +MK\Y6RZZ.Q77]2CZV))-`)CU>1-HXUJ8JN\_LO<^J(SE`DC5)RDBV_W +M;]4`;4%^%Y@`(7Q+*^`&+,^Z"9OTNB\)@TL^KYKEI/6=G/])_SKAO`TQY*K%L\#R^G-[?$X-OGR@JU=S%\51@:#J@9]4 +MEN:.,UO$(3D<1GC5H:,D]4#=#-U%[U`RHD+)3W86PJ7;*'ERHRE\?N@:BEG0 +M0)T>4?QJ\"UC79%54X_X7*>8;2I277'UKXHG[\Q9R1-B7P=P7&.$*_U^V.W= +M-:&Y`+Z?@L1"QL4'(#3S[0DTQTN"@T"N16]SYM*DI.%)ZPUI(\Q4.V@(<1+. +M2#4\;CLWLTZ:O/3F^0BHVVL&U>6N5T2F5PZKVE;-?@MAC%^+#Y^`^_>!?SAW +M50CC8HMFX%*\+NB@S,XG]FT7G>MZF&'*=^0!.^>9NSWBD7RNJRKL[.T7)1#N +M\:LR`DS/7C8@++DAU*0[$E@5Y\[92&):&FDL0QM]9,C0N("`^1:EFK`T/LH5!^0)I9F +MBO`)#[8;?J[9IE!#'G+,#3=_I.-;'_E0TEG"*^+`527QTIK>7CF*;I.2`/MB +M]"O+)503$ZK%8Q!V89YP3:/-QT(0RZF9-G2BPDUO*_3G6_&_DN.0ZPGUQ!EN +M@-W:Q-K0EXRA/QJ7(V)B-#8:]`F3S0]7WQ'#'!@5?7<>)D0MR`3(]>NA@A%6 +MJ/4&\]8%H;B701'&/Q][45',,,!.&V+;5!1F@N%2`Z1%MS9VC\;#U*,+6R*" +M^1X-QPBLS1W.;L:O;]E\7]!HC>9'EZ:REV4A?7!0/-+PJBHIWI8F9 +MI?`L6I(?F>K6DJ'%T8Z&HA9SY:*Z=<-H9]KAX\PA'5!SFG`E>(V"D-QS'O'- +M5P^QL#O/?UAX9#))6:_NV-)UHG>)(#5$S&T6`3C$5'!B`F"]^*_1J773KR75 +M!^6FXBEXPAK32A21)63/,SNNE3W:WO%KK.FZ?,_F?E_6MIY3%0;+U07`^0P0P:%T$VJ:`2KZ(GRVK" +MV3N(W]?G(0'U\P'(O]2T<='T-6FY[Y`H">T+$SCQ_2TSA1'B6FW4OTB+YQA( +MV9T2=\AEYMX%D-MYVI8LH2"WR4$\*MNF,$WEV[:5_&_QM@H]\M'>N72,0MQ+ +M)TK&T%0?D_^"/)B>YVZU:>PKI_*STLC)BO%-!4IY^TTJM0@)@(UJ(/Y=Z&\6 +M0M9V(,#5<-LS/->CHH\;7[JB0'S*E,A!_D/I%HO]H%PFVAN,!/,!9D*["].C +MLULD9ID)2>M%'.FYS%L48GK<(QL,8"T\JLQP!RRQT]S+AN"H:9A\ +M9P1K622J:Y#ADJITT0"?K0 +M^@H9H"G3U8E@:WEK@3P;JL6%$"[T.OABA6Q8G5(/-/Q!5I/>S +M)H[='[84,KY']!-Q\EQS"9T$K])#VV!FM,&O%\NG6"'\@N]A1),GB8<$SK,0 +M"GVY%8T3=M$AZ9.E!Y$V\)%21^J7D>PDI]#*4AC:H2*D5HS6N+/#UK0+0S,6 +MN897=8E7%Z5:6&_CMKD?`D)8.%56US!BF`SP!C9U3Z?Y=X5H*R&\VFJG!J%) +M0_VW,,'8VJFP&;5@;'P.-UH6_$CL!?U+_X57+')NUDU'+?:,]"#J%F^U)2EV +MTZI,M;ENITLGP._S"WU#'R1;1'IN$)-7S\Q,9*LB0[!CA./Y[!-5!:F":`_' +MFLHT[071JR!6BCP?5.-!4SM=S9KH\I>,E"$NB@@%TLQ9HQ&`:C0CG56$.ITG +MRA5Y\YM"*I6=GAB#D'+>VEBGX1?K#AH7C)^9 +M,O;KP-\83#PBF_#O8G4W;G35#AY;B$*5#2\4);&W&8?MG2)`]@=J4M0)/@F: +M[W=G?&:"PX= +M4U@5^[_[R`^C&/>+:V>'?P][N-W_3]IIU7:*OUOJ92\W^-/1IDB`HS&GWOBF +M)$O+GPNDE_C(-'&NJKFK&',6F-#TXB)E?&9QB?_(FWLL3U048S:I+Y":85.1 +M8&XV-U6X4!M!WBEMX8WV`R?,V!M01/*%ENVL=JWAZN^7C?LR]K:,!^5K`F+@8DU-P[_G.A$X>@."SZ5P9 +M*G4)SX=5KF0;R!<`4WOZ#O[9EYN%,/9C-*#:L+L:9C".F;*5@F/J#B$ZGJ>9 +MMIK1+TCDLKL+2GPE;Y^\]BZR>M>BN'\-7I*UGW\+MN9`>+N2$4]*PW]^#%!G +M$%[%?N\EI<7:>-;P;XIV&;]GQ/>>?1G"K#E%RJJOB@@`.]U02.@$N\X_HCR& +MJ2;))W^#"C>'ICR5?/B(4_ND),CQ73)&<)I0052WU@%U/''(->=I+!MUL6&U +M5)I9O-IAF!2Q#]P7\$\EC: +M@/>K"HC;X`*]QC^5P"HG$5\B<'T0`ZHCRKJ375^GX80+-T0P`%N\/*ZX2T_F +M'GK*TG^CBN=MTHVY&4;Z=I\NQ;X*54SA];K\K6O-3C(&9S;'I$N;>)A>M.22 +MR>#B8O,J!I5%5TV3(EMU23K8V*:NOQ>$.BRB4W40BA:0,$4DA>,EW#$3.GZM?[_S7.LFOUM<@L)6Y-@;A3?!LD88IFE +ME7YJ"A$$JE\D-TIMLGY+H\3J_?()':W8<$]I#*0OF>KXTH1Q79!,WX^:%2[: +M%*F([+_<.LX,\]\@T]'GTVVU\-YX,]_)/,*E(>R_X%9V,3.^"9HB2EHK-%06-@TT#K7C`_UAU>J\NO!,5H4%#(N +M-SA5[O@=966E?0/ODVIX_%*-4',+YDR>,=5_75O)$6)Q9M0,E&UN1V(+LAH2 +M2/I+X=E$%?F0`K:L$2\DY*8"'6$Z,B\7V`)KMQ83>$GB@0`YOT9NIS2SK$T!LQKO$ZA$>['H+B2M:$]X!?9'Y=THE^D5N2S +MP9D+KWFR]PY[S5_NUJ>1]?4XTA.^[89)T3,N?T\5L0I?5#4$18'WZZ6XH4=% +M1TH>M@&25C(#&D*%CQSQB6HENJ\>(\OP"%IO*[4J_H1=F^SO;.C,>HO8D#9G +M@(N[AY3.-)9_BF@MK!>!B/V(YU\L_>&0LWI:F467[9,#\Q=EA?70\GFALWV5_!=POU[T[>,,3W$D1-._UJ^ECQ +M$^D;P*4$$)<;!"*_@+/',.+G4%*YLT[W/FJP)BT#H9V!UCC("`1144I$N4@Q +M&9.D7*GZ1F,XVH*)%BZ!\&7-6]#2S9(K9^WNT#PUO#+[G4S]YB'U-+$VM?+5NOS]U?-5654I*;O@7[`*B,:> +MGWJ5YA$T@1&"Y;7S-"C-WI`96_J=(OJN'#;+D7PK!]W0^M>A$-R]<1H< +MDW$IX_W8+[Z/`M:^G/X=*)#M/'>*R_+#JLY7\:62/^Y@@D87/.F5*2=KC0O" +MU^]Z<*N--_I>V'6@M!-##I/^JFUYC"]6,CUR^X-7VWL,7&1`-2>2/S5.6@V> +M7[W,;90#CY_>`RC7(9!>90KH?HBW/4#1\T0T)R(OSH)+JPF5Q(P6\!D.>G7" +MX/HBHC?.;J`<16=5@2+=%R7FVXNZ-%Z;!F)!UC",<^[$_R6PB..IK+$%B=*K +M#$-7/%33+Y=KO>QSNT>ODJ`\D0>#@*#ZN3KRU[@J&B3:6+SFN]GV:^CW0*Y" +M_0G@.F&T%(^S*:TE&H`J8!E;T.DD%)#.]%1N6A[UID]'498[HY+-K1CE=YU` +M+C"TIQ)E-:255:9';?OC:&E:B&A]H$Q89S!+Z_T.-[GTO%B%%XWIBA7'B;+@O\%M*1,7B%H.G*,0YR_7L#C9:[XOQ`B\PY$6D2S0:J +M4Y=C?/`MET3((>'CI%QLWZ1)`K:7H!7.;JB^$$;]V,>J4%/=P$]M@!57 +MX8#4>CE[!ZGAK#K0I-;,&D&M*/?,LW\N40*>TC%L]1.L)+(;C-,NZDOF`.;< +M-(&/['<_S%?0:^U\;8"5PYP"EC+=I^*%4OB+Q5,*8HC!;<.2"@GB3C=;>;_V +MGA.Q$H-.\S_@/ELYC7UN]LAZ>'XE.1!MG:$`6#SAZ/"@@!*LTE>8QVV(ZWJ( +M<7J$@J.=D*SMRV;E@N%M(.&@1RUEH)`MFP2&_KP1)SBJX55P:KUQN8VHF,[5 +MY^^`G8FY,>H"8E(IQNWCW?]"PJ_CS0:"=&=//GDVR@W,Z&`;<JCP_>%RUTV0QX]>]B=DEN/MP0'=OVM=N%CS'W-P>!^0;W-JE="3G9`IV' +M]E^91]2]8L%SN$#J\M#@/3LZ&-=MJWS,]K]*6]R?@9J2[KM9[7^::!9!L%P. +MKRX38H$<29@@0)K)M=XXY#Y8QA;R.2B*76/L"$N#V5>RK+[Z;FLUG2W6-Q4[,_]68GA +M.#*@?_1/9(F>TA-7?(C)Q$J872VY2.(2?RT(?N$Z$A$P+P`AE5^59+-!JC2[VGB2/9G2W9N +M&2M+C`(6BXXTL\T&A%LVH,/"-C$Z-;1>LO;73AATN`4K=R^`;Q!>4[EBM'-I +MMM/\2%$]@\)&30H5TI%#U:HXFI6-D(VJ=0_+AAB/RA_^>J+L%:M^S?]'4WWW +M"?A*2UF6.Z"%:$IBF$+E1?C<^YM-4[L*R;S`G(08)BW+7M&)T^9;,]G+: +M3IL;1CZWHV7%Y,-O2DKWL$QA^>=%#^(LJ]WK_#7<=K"ZROV-P":`SJ#S0;M[ +M9_!IT;T\`BR<><&FSX;HWM:-'36R<&19")6V%)`%$%(<`E=F9 +ME]L\F)Y3Q/\-M"P#^D& +M93@/D#WY1B"((>W_3+]*D7FS46G*$K2%+*J/*V*JP'ZP@B1O/8.X99<6<^G7 +M/L<#/KFP`Z3+&1AL+PJ0Y%;_8#S=2IXVUK:HH +M6M$\",%QD>.?=GM,3CVR,/8K%6CRGN1.IDJ(&0X+^BJ81TFC!KY:DR$(DC7M +MG1HUF*[^3SL6HT%7DO09MVZH8$RVI;?Z,D88<-YKBJ:+^P@%=+EU6L4SK8/_ +M5%$;X4HA*2V5[;6BA#$:D;-AXCEVY7(1H"52W34/RW'9!@JRC-C/E`KHVK'& +M=P>]N<3[Y]]FB1NAM5M2%`')=/>YE_GCTZ2RKA%Q9A*-?K8%J>T])L@0E'20 +M->`-!E"M@S,'TX/L1;$AW*9`CE8LF9U/)_^Q\$Y\$&QIVQ9PW_7(_N'9 +M.Y23+6OZU+^H+YH@RRTDP#OWD-T?=_"GF5Q3@EA-CK6HWT!F84^=6IXFB&"I +M0D:VP[[NR/E%FC3CA(E="=:K0F0&1D1`?87AJ\@I%E3_UM\^AIS:_GRNT370 +M-0&:Z[%LCJ1+"+CC<';<,Z5:V\Z#+T$"4AM5!;HS)QVZV%,"P1/C6F=-3$=3!&;?+1.] +M+SIH/-IHOE*H!-.Z1.8%Q6_!HVQJE@XBKC*,.,ZH6)!@,1\[$`E4GH/+'[P# +M,V@S]UC^RR@2Z92;$DCLP3KTITD[':290%::VA&ZR+NO5]N.R306>4=@AGK2 +M]BIEMF@T+%)XG['*C/GFP_E6^4@Q?H';$9G"&T)1(?333N)-P;/WT9K*K&-,#-H@[+QMEL/@,(:H4*@+_?*TV[(>@,&T1"]FS^2SJ-Q?TZ?:V+?0JR?J:;]A4 +M&WV=DQU/`K.C_0"6+$8<.TWM)-#U'\ZF,ZZ(A8SGO2V'7/:!)85`^`-RA2%9 +M_!`8`P.CMFN]66N=N1PA)RD!"8Z3%=:N@%S577@,"HCQEAD81Y.!>#? +MG%UY;QEN.L::6N1KRQ>%E!_9I*R\H9)3[!FO>HA158Y<.=]E9J_+"^<;I>YD +MHF:Q.P:?M3G-:PMZ*0#^-2F9CO<'%?P=]N9.':J>+,OCJR1=A+A8+ +M@X):_H:.CTM[I07]C.[BY'U?76"0-,8;2Z%F%,>[1E[(W),\@$O?W3TZL1T] +MBL'_C*<48@RN`5!YZAH?H"L`/3V@\/#/$OCE,593FP/!T1.1$YZIQ._`%"?+%>G/N_HU!:5U]VG+G154 +MWF*"SB0^.%MSIG%-'Q41BNJOW^,?N6P)C\FYERDX6(W3XO+Y3Q=SH1W6#3MN +M-W>HX,X;H6L!'*QQBF'%3O2Q7.LU=/"@P14"$=.1/5T3*-A4T]D#W#C:R,31_$Y1?D1J>F+>9;[R=^JFV`U@ZR,LB43;83:X3 +M.X410W)\RAX=[42W-O +M_AR$S@#8,73I#Z9)5&DFOID`+2P,/A2!6H))-]:M`\WC$/6$OA&)3B9.[O])1=^7/%\8UTZWF[5JZ3S_0!4 +M2/MW,>'9G^86OX$2-@(U99=&KC'K2#^F-^D3\R!G_F0>B7,U6^R#2H.SMLQ7 +M,4M3BT.^XFVTH(T1+*X]%1VK$P^G96Z]Y6(3(YW][N1%MA0D[]0*^E +M#3/J9;E4F1A4=36ZW%]H++5$U^![=>%'#E&F4?G%WV''VX3MB1I.C2^-*UI8 +M+\?L(;-[YJS40$]^)HW,%.F:X)NG(GU\!9E +M][+!RX<_S>0P7I)[H)39(MO+35>8++$A>?24K1]B*P/@,GE.==3[,-:Y",:C +MEF[Y;B`@\"G!R69_"72=%A$.*F9(H^!/`\,#&3W*B$_?LJS<#$X@FK>FIT9# +M4QG_7U;[R$4'DOCG4VZ02/\LF61N;5#-+)\F8T8PX=*UJHP@G^XRE;OP1$C# +M(:-A"3>JY'1]D3_/<`?<4BLD`0^(K3VA+K".8'8+DX'D1!&A9#,H+N,1"JZR +M%5T9U\D2-6<^%F;R%P1><,PE4@@481@8%[!;;0%AW6C3PB7Y9GPLE54U%ZG& +MEKAY]1#-&L3*8K'G6;T."0A*M#=&-6><-42)]+]=EK6R(#9+R#HYZQ; +MK&SV%.\/(\%A3P\`>T3_RR$V*6A*0F;3[-Q*T28H0\VEQMC.=C%%O):Q'H27 +MBL4,/B##7ACV55<=P5OT%ZZ0^W*8$40!`%H\JK4*T/K5V`%'_U:/I/=$,]/W +M%%[>)(WMHC(8G&WNE/G"-S_DI3E9ZGS[7->[=Q;;/#PKI5[OJ-X.UG:3#2*/ +M!R(X)D0R;.\)`T&^1#4C3@A]PJ.]],S/=->Y`26?T=%4QSWNF_#S6:TI1YT6E5/N.2*?9.9P*F($W;RX3;')B?J!L#R_H/%A*EY$T1&]O+>[QB`H6"K:2 +M,HGVK(FFH6I3)Y@EDODOPQ3`W09UF2-U)_$)%[0!E@@K-KV5GXC@J0C0DV%P-5=D9]"(`%50Y2>D^VPDH +MVYE[OKX,L`#ZXCRLR8X825:C6@BXRER14S'T(P1FF>:+(!Z@NP9&< +M0B,K_A=?GOY1Q&K/JOJ1>U@IM%54Q_FX\GH)5`J^2"L&"(G1'GM&L6*HN[4/:*W+33[T0UDABCW +MGI__X-1=OB7;OX[>I/S0=LD5=W8-6,<&^N-?S$T[#[^U.#AFD=5SD(RK"[F; +M(!#>"D;(+`A/(K6F[TG#?!CUQH&\$YH-I#B/GT\%_6[D^ +M>578<@B_`-0H3!IGLD\PF:T)+-J2R!Q^M_E(_:1IWO=3?<@+Z18+Y?)A9"0Y +M>6"D(0X>:\6OTC\ZD'$^LD(A(%-;08?&)Y^123S7>Z8^G@*(!V;YA.\]8 +M\8AN?^,?`/8"@^@HQP,[[2Q0KY9DFGS_<)7WG)YP]%LW!?4#VK*YKF3B6`$S +MDV:X;,1U+X.UY#IY&CJ1CD9/_4!8:G0GO'Q(>^KD4YZM.(>.:99"\)_=NR`% +MC(F:+R(F*/1&=Y@+(:\6>_M,KT<6AP.B5XW:_'Q4P"E,%V5O55+\^A7*4RG' +M8X.ER9H73.V%'H'(-KLX_0X^$M%LQA$-0GILQWW\CW$%$U"!*A<1^;0@*B"G +M>*\GH9QSQ<8L^8C7634<>9#7L1%=UQ(ZK)9Y9> +M:#/$:.G(H!X9/&_`UKS&L[PP-S[E:8O +MWM(+S89;]RI3P1$@B]TP&43K;/,DZG;-\$"K&-,UM3`?G#1H,`;U.*^O'9?Q +M,X_RT&Z[D@ED1_RR1TG1CPM\_8TMCY./T4`[ET;V2%@U:C$NLZ#I),\JN8Y(OL"OC:]Q]C[GL2:[ +M2.S`M8[>_4G-S8BW4;XE%G([HA[,YF*_P;F9_D2\]_LO*EDMP6RPEY1?P/,` +MQ*NP&B7BLC,_S7S#Y>\OHM=4WO-JHH$)AG+LG$\J8$XPZB/_!XIWWA$70]($$O`\""M>HH1O=L<.BH8=(Y>PA2'1/GS&FR +MS%$>Y`*=-3@:J9T661L_!@IQ(<28M,UR!E>CN"`@O-B"%"Q`QZ8P@=1K80LP8< +MX'R<%5`1R?-O51Z2IA-D&\56LV(7,>J"$[`9NTHV0\53.V&2_+<6$?DT,?R7 +MK^3[<(^/ZHZ.<54!$#+2C.E9"6K30OG[GC"K>6TK9*,!KQ3C65R$Z498IUP] +M10AD'=JW"F=/]#XL0IQ?MP?<&W8H@JY*LXM]9)5@F62_>,N`,[EB&-?B:W4A +M/P)_X_ZVCQ%U"=BH:>S)_`H'K(>G(JW6AGQ0\,0B-8CU,\^RRQY7#R.H:G.RL0:0&1JM^U]L/5)S,W*]V38JX(QO$D)W_9E4Z=[ +M#L`4^?Z\PK6E#6A"LPJ^I^;A">=5,2XL7N+6);B2ZLSR:^4(K*+^6TU%$$IJ +MA]<4&CV]XA8DT*`F@(9V]G6TU`R]LX?TRY.;!%%F8BD^WUPBF*$2EFE2HRU_ +M^K_9]-T$LH-OS&?<30!K'#P@KTI'A*0Q`H/NLO.F2E&CM=(B]&I +M"%Y[^-71*OA8/8A^[$5&P**;RD0-)IFLN&#N=?D@**PY-["H+?^N'G- +M1&&6WV^8XM#G#J^U+D?)IPT=?B9/^/%^YWSHBQ/,(L,C<56V[N$D*')M5?MM +MK0)UT0;D"G.9BUD2!).PX(2X':04++KR-D6+;^`HEX*?,L8LF\'DQ$PVBUZA +M7#VSOE`O91>#J)BZZ2A$=&6*W213%\]^Y'/]]MUA;M-S)";MP)JQ-BC?R.9.,/_!%T.199.8"I>5TD +MRRBG6'R+5,BK3_U&Q4P,46/\$JE@W*8QJ+.11 +M\YW@]_*SN!\/&@+6ZP$U.?I[W@N]:Z(0_(00G<'XD;T%%#+S-^ +MA&%?KK&"L`Z6,)YBR*RY#AN*_4Y!W!6LRS:3>_Y--"24139(HD]<7JI#UQC` +M'HKC3&K9'*Z:#?>L^G#&/UWSP>'AP(2# +MPD6A%60V^U)'8/'<:GM3ZVL=?1EUC(GN?`).$"D?F!3KBTP:SC)1I;Y*(-WE +MEC7L<)"$.F[_:"KS[UJ5Z110?Q+0`L>=/_L.Y%<&4@)D\R:/Z<^[%V?S9#R^ +M/T(/Y/)"FDV*4R/R"N_>AI9N2X-TT#A\=OI0)'>`QV[;E13!8[^BPCP5X&S% +M(X27O&(V#=[2T#/SY"SQFQ*_/A&_'"AB4-!E\3K)1/!4.VCW3W#K^A*Q' +M$VK=S3XY0.N^-QDDC;OPQ:\Y-!NQU85M^>,2RJYVB'#>/+@.M-H>ER2MCM%2 +MS*\`179I(K1RKZ%3N"06NFZI$F/9QR@H3KRZ9W4^"JK/&Z1W(G!'_VAX%,+. +MHB]Y_,X<3RKM)HQ*+ZD=9>QMK["F?U'(PC39L +MZL2TWOH;'#$14ZR(K`%?3=79J=,WO8&+:(QY4+T*O=2DK"UMITSZ[5\UN7G8Z:4%VM=IP4]]&Z1#H(U[4 +M66\@GP&/AN>$^@<)BF=)"[A.9K0QI<'$?+_K,`M#YTV]-O +M9J36R%3,JVWUJ)^:/W/SX"RR5]@2<`#.@C4!#IU.`NA^T:?!\;'"T4,BE?AJ +M#H%,4EHO4]"$W`?U4T9P4 +M+8/`O-E86=':H;+^>9B/]LW>RJKDU\AK;:`E\X#X!B7;01+O"3**=*2XD;X> +M^3+]@.@DM#.J"]/M9NKZNQ8237P,R]A77AOD67.-N']V+/DLTWA@@QJD=GH,,&0TDBHBX-S;(R=#KR&Y84!>@8!_<78>9"KRD +MQBCC4C;GXMI^,CQRCKC!Y-!Y($BE*P,0C/`RMX/0FZ[!-?=_Z2J44)=;5\VE]__S\@4HNGO\P,?Y?FK +MA1E(K%BI\0JNY0,=LHS.FL3L8136CT8%>I8^<*("M3.#-(@"\+C0LHX4NKJ% +MHB^KD0"?23@5+HH_VDWW'4IK%P>)MD=4K"S)]PHD&Q`MG[GPD&^5HY;:QHB3 +M>:<[!_$6[=,T#'&0(`#?Y,Q7D03.R&$Y'RA)Z8/F:J">NNQ#!'$Y.@+(ABQL +MV)]]8PE'5&'17H%MP4!%""KN=RA+T3T8_\8QFQF_>+4`_+6--#"F1J +M_JJJ[=P0ZFY(#P(L-\4.X1K;RW)-FA'V$#O>D<]U5;,&:9JZZJGW#M-)6VS' +M\T7U:VIN>[9;P.G,'%G%NM9!JT/VE.$47-?Y*-M5K:V$QQU+(P*?]LE-<9)- +M6,Z!KU3'XKT0?X\P2TG%2NFRD_G+;X4$*J%<$I>(?7._GR15D'._=ZK=!R;8 +MHOU2&$5(^2^IMO=-Q@DMZ%KG:+PE?Y/5RQUDU@43S&@&_R+@0[*+DHN\UF>0O_@>I\[XPV"']QXL +MY)(A_WBC6K-+D3A][HY%L(_<3)UQ^`/=FO@%S,PV.6+)P+05S^>D0IEJ&=W] +MF%AN(="IJM24/"RP_L<\MP03BQ9JWV70$OAAWL.U`X3'\`_0#F\.3I/>@OY* +ME/)(]G2402)6=JL4F-QG-Q+-X@+G!^*SZ3<-KJQ8+5;-VP2OK20S.3H"KG1R($L +ME+D_@6B-ZWY_>.^8K-]=R*/KW(-I(<0>QF@1$01UBX02' +M4I%)72,18'X[1I1^X/VB-_J3_H6>!GSX3F^N-I!*H1*5#!]58*68S/E1->&[ +M=#1KE"B>4Y0X&6=EOH\9OD\4E4Z'?F1E&"PQF59_?O>(0^R# +MVTFK]//.\7`W'9L'`>S9`)A4:ZUR/TY\*+FK3SU`%]FS26ATDE/:.JOHLA=> +MMCAJ!O_$4XK1RCA436WV_*"Y>L%G]5@'#^R0=P@C`MI_+&2 +MA"#P."1L*7KV:;0F`8[2C](_RJRTL4(W_EM"_41B.8AI)8BW4W+[ +MY)_EID%X&RF#;K#4V"H[H/#`K&BU[+H,5'NV`+60^>7VBB>2$&7,V$'W]DL= +M<04_E/*GQMP3"1V%;7+HK'-AP](L=XX+JJA5:US(;+H,9M4HS"]C^F&II6/D +M[\XZ1'BE'5DN[F>++GF,WTE9DO4#XQZXU+XE=K>#2_PGTYXI\1D),8HO,STMW3+J +MZL\5&U'&'\\/DLD<>H#-.=HS)LW +M1O7%RPB9&-$2[@;4.L,16)C&A;M'P\'NJTUFO9?\3(K#2+("80*S:R-#6>&? +M9;;')J&N,!EF1-:49MV08T-OW'K5$$!.S)EEK6`%:[!!&L8VB4\QW5`FGK;H +M;1S*A>S;U.VA\12OOJN.3U)A5C2O!HD'ZO>,>LQL6L6]X9,316D:Z^X?$B^8 +M.R>._/[5Q[X\PR+H\5,GUIL$N3,1U($ZNHHOYMDL-0MV\N>P*N+.!E^\L4R1 +M\[SP!TK>P+BL,BXR';!G^F*MLQ;?69XTU/>^BMN5-YF*SD#^0,G1>F50T6;/ +M:>",`G*POH=K040308T5F9.^@O:4*ED[IEJHCZ1']4F`:%$G=*?HS=HOQ#`. +MV%(0NQ^IIW_Q,0Z`3R%7@*<@'MABQ]0=+`GC7'C4SA'-*093_^&7C7< +M1Q/J3/+;#<@R73!DZ6@K":'=U@,-64>-\QQ9A]2I? +MC2ITCY84"F\T6J(7>[><8Y9;S&@+N:+M<.X@DJ^$U5=$CZ8P_.-YKS6N('8K +MIK\5^"_BZ"ZN8B.*[?AHJ=LH:#1L<(X!;&THH32XV3^\K>/WIK&Y;!RE'BI0 +MK'*-(;U_+-9Y/RIQ_=3S[Z@3:]\>F_5\%"5BQ@-0?T"R=:>B?8QMYX*237YM'' +M%L5>D.!:.4MO!/#0:H=7!PT]4!<0AT3#HA&2B5ZS53@JIDZ_B:]J#=V(3U\" +M!)U>_/46'\[!S03!(O;EII9^#-/KL^=R;V!1M&)$RQHSO5LW&,(@=3D>TTM!K..N_,119*1(E1D9;8S4"1XKY5'\0DJ[7?_V7%:G/45T8 +MA%'5&UBSXK+?STRN9ID=65F71O_9@E+8.@.ZCNY$J+8,YMBX&IM!\!P[/27, +MN7$8?A0#MHJW(W4@$?Q6_'<+^: +M1=80JD_O4@X\O(TJUF:_M"#S(=7M^;O'Y8U;F8$3-:&'W\G.%-;D3^%/-@P9 +M'!,)F$8+O)BC*C/SQ\J'K7W[ILJYC3?G,JC'&BYT3]_=MFGGK_A^,"(V!AE) +M+4IIDB7@RKY1NJD."7%UH%NE8'02<4/C1L%.F'I>7]XP&9F+PAYS2E-Z-M9I +MS`?8F-9IPT?RYK#'0)@`@'&3PR%G/43L=PV;XTFE7FB4F/2J)5FY(E53HN": +M05PAYR@+UF?<_S0_@^E0LA0EUW`(JHZ.M(&GY36"KH0+^3OS@JC7EB[UL'X0 +MHR_\L-G#79ZNJFE^0?L.0CI8_TUZ2("4V0;3/\$-N?D81$!:#`/^C#03V@5_"*V*Y%D7/(#6*$8E<[;[N%&6_6M-WHWNOVV&_]'7+[=LR9YI.C$/KG +M%M\!Z3OU)X'&=5(AAI,4>"0M*O[EJ@)9'\!)@;G&:!#V^5=5`1("@3VH&@6C +M[9OW,.@RZ00N5HH4'6$>$["F8?,50$=YCLX70V_9V]8BD/IC#D:\E'Y:5JP1H +MX:LB5MIP]9_E(D2S'*FJ.GJ31EXXD:T#8"&(ZMD^DO*6YLVX3760+7O`?SHN +M]XHEJCT!+;CJ2E;)1MZYVNQBY7^^'B4(I&&W!G4D`L7ZA^,A21W%_C&;9>/1 +MNC#DPD0;^'F3XDPXP"[6D$#+:!`S\B:I3-,[?&$:=%ZDRW\N5QT7%;Q?(S)O +M5ID?D0Q$+:GO="DY98'2N@@/"&?N5X +MQ+-R_8<%.=M4=E-]I-!W,/.\@^9SF8`!1[ +M1F5\7]U(A&/!=.!QO4D6833RF@D%Y=1[C9[7EW7`;M?:;TGU+ +M6NZXX52<73&T1+7;OWAU9^A3%*S75M=R&53?&OM"6!@EL3!'Z'9EO\E#MJXN.KA1.S\N9!O/44.O +M/J7OJ9$1:)7PDCYS)0FR]D7S>VQHK6"U5WS3V_,YW(S#1,O*_K'G1VL"ZV-Q +MMPASFJ5O&GNX04I-WJ9=`&$N=_]5WH&&G_Z-&%BYER2&6H24?[2M#6[RS=9> +M2@R\<:30CSR\S,A0<3_?FV91G%(HNKL24J@>TW0I6W"MM2!_$3Y[ +MN0=Z_H#NO`NG$1?2Q0M!9'>EZV:`/,7('AS(,=.B2XY? +M*VT9?CD2*$!4A$$T25CC`1`WQ*:^#QV0O4?MG3(9=-R^^N>$MC#42DJ#8A\J +MC.`^YA:3U\;%@&MHLZ0F<8/H.6,JZ`#5=,78CNAWRNME)LR@K6#BIN1?C-$G +M27.)-NI\1H#7UR8LYB0L'9IS.8UB]*K9N?'&N>>+XP-.4AXL?6/D<<.RO!P& +M/NT^#5>(R,HTYRS19BG(+MQ@[BO(H)6=2(X@#0[DM)^4[C)66&%*\9O[B/%P +MU)_?PC+K2'8$'TY,/(MG:L(I/\55_;\T>EZT'_3=&ECFCT?MH:9Z:8:&F+GW +M7:6YL*<_VZ>!"AE?1[,QXPYL9P%D;XJ=AH-;ID_Q%.%'X7B\.[G5F,059@H7 +MR%4[GWZ%U.0"9@\!P[]KB)Z_M) +MT]IC`XP0Y0U-AR;;WV]K#E"#F5$$.W]Y:#)??;J.CXA#4/\$+WEYL/N84^[R +M:O;UR4MVWYRZD1I1L_P(X%=1Z>Q-97YJ&L-MN9"M*&<;>-F9I"2`I==LWD5B +M43%@V`'XXX2YBWK?(>@DZ%X*X6I[A\X0+K5?43>&KFG>>R[NOG?Z>P;^/#=F +M^A1V*Z]9=0WSFHUO%/MYS-*\FE/1O7KUR10(][UQTVBS5_ME`W:.$^6RW@23 +MO63EHJ&\X\JHQ;YE=<1\DK9E.ZUT,A/OZR0]:2<;\O.JT`OOMH7`28"WS[%" +MM0TV$T/LI0=)NH]\YX+&ZLR>Q=T6:ETL9H1@"P.P/.&?4,.-8TIV@RL(3K]G/5D9\*Q?6O#Y7XH_M8+,/F4G&%Y%?I +M1!F4,IZ]I`3"8]`R\';)ZI/5&S769-NJ1S1PHN8E$M;O(:4]C;T +M5T/."2L#]+IZ+83'0XR,NZQ&TOP4OK&E1:PSD/?+-M1#S`8%O8?B;76P^@8P +M0PO_\6OE2"L5#*H*\GF]>-^1^AAS$5EH>;FY(;6D<8T^6DBR=$>XVK_K]LJ4 +M>OJDTF\Y7$IFEK%Z.H`P('6!;*E;GU4=QZ<3KJIGL!A5LD2RP*V!&:F".SXV +MZE/A<0HV'-H4"%(X)`#^"J7U'NVLIFG*9/%@AJ[;1Q\VXTD42$]2R;ZOAR]& +MNB$#R2^^DS/$0O!@NUO)GQ(-XC;9R_BX:XZ#:=C&@2_AV7J[4ZYB?3'L;O`= +MFT%3'I_C*KN5IFAT"02+X;QD$]4\H?.,$7Z)V;]\PC*IX#;D;EGZW$]$&-E> +MBK`"G:>(LA`2T4.YE!C;]4?EZ^R:DSO`)?K`5.NJ+<+1%--IJ+U61$>-#JY7 +M^U.5BSFX(1WI0<)(HS27[.85K8=!]U;0K$M&75.?J0GZD__4TP?E#_T`_5N( +MV3T_P:?9=I7IOI\V123T>ZES'&7*R\O`S-`WOPC]L#&Q?8$P%R2)8-(V1%N7 +M9^(XJ_GNN.A0[UPH).A-QW$B_7&VX*<':[M +M%:_WW"&3)/94X9Z^-'PCU"XHE,H4LNTOD0[A@5[!4<@8E8^6 +MPQ96\0.]]_VOP>3R)5)6@BH&&,/S794S.^V$-+@]A":C\[7P63E'S5.ZDMZG +MW!KHZVPZ+S:HYZ'@+W0G?G378)>TZ(CV#W##,5^6J@.IO':42.*Z)(JZA9I- +M,I'6.'U`%Q;IDY&!_ +M@&4X[:E2\=Z&TPR8MEK]3L.%-GDI*/1QQ9EGSH5&,RI>.0U(?Z0AY1 +MH::QWO^!B9@-/:WC^"T1?]`^68KU]OR0WQ5OD!EL;'O3]HE!#NRG\9!YH@`8 +M?+G*'58$>J$,1-(J#'4B\\GO;P*JH;?C?9$73*\CE00";]3$%`B8*@DVKV() +MD\SZ`B*$5NNK_>2_?P.2+HUZ>EF%[7A`X0\$80Q[-4_T +ML9N[S74I`18Q5#,H%\,T'A#%%!I$@H"3OX7?CDA1B +MO7C)M.G$5*=`J*\P55I&4`R/LT%Q>$A3M^@@'B3/8[@N +M'`#E4_(5G#TO9N0I,3L+[@'4]-F*\#:(Q(1\R.BQ='&D%KQ1R/46^Z84-OM% +M/K^'I<'H/IMDN)?YW3M2Y:-X>LXQ]V7+?6Q-&^X[6FJCZ@+C,68,='3$D_M[ +M)H/KYHDINM#]2F2ME?_%'^C;FJ=7`BE'KJ!N?I\/S'=X^22CWR9!6GKBZZY2 +M$]T#706X`L/,+:?@CYIO"4*GXWJK/B+]V0U;>(U9$]7)M"JS$#B!`O%)0_42 +MA&2)77-G[>(%KILXB](A\AK>SIHV&<3;4K<.$@>2U*&R=0I^V!+_=B>9,T$R +M.'*^$EC:T?'?U_BU/HMVCGJ/Q.?RULQYIW-'I&\[!VK)5^4%")4;3QY+F5R.3`SYH.'MH/UF +MM[";#TKML1R8LY4PXN2G.,I%6JS--7WVLJEE(1S=U7OY]0".Y.IPUP&H[8*8 +MU[C.$^CY$B'?\N^)*)6"7+P^XA68^MZ97C,EM(WX&A8R:X\KK\F@!IH^!I_@ +M<5<?TGF!H7\\(3M;3OD>.*:!M +MMT=A9\;)#>[I\\;9#":S@IW/0S0H[G%4>H%).<[40:Q(@_B/1+B4;A&(AY^%)@\ +MBI1%X_6FV@^BQ#2\D7"1*S-F@,YO[JI6)J5E`>I@'7N-&6G%[704)![1K+P) +MN?@7PYMO;_/,0F;RY:PE;?L(2BGN%-:"3/N%C%2YM44,R.K#\]VS::]XX[Y;+ +M?K6L.W+4]+9H_*\U'%QP8E5KQ2T`L>55G3W=5T1S,+59CXE39]]:PAN]O#<, +M-"TY734GH:-?VA3R=(IB=XRJC(Y^KN0QXCC]I/0A69?!$7PNBYH7+&7I(")$ +MJN +ME4/M#SX7V#B/N#7F\7$L'BDL'*S?V'^N7O3E<$(TN7`G(1J-!=VB(UU9*X$(,H7Q.E^Q7V?:Y`56=U\4Q +MV5=8I9U+,>`@#V?XH2E5:5GDT_S/@C(ISMZ"[YXN>,'MND^W]*W6A^.V2"H/ +MB?U71=;"'PWKM7>6N,YP3N+M.Z*BF++.X'!5\LN&R?26HQ,.%X;,T0@D^D'= +MXS^>J+7B'76N66J'VX09B7#`QF\S +MY_M[K#3:4ENLR6R:2W0N;+#*V%5>WKY7K`T/N:0Q.MK![>MI9D"S/@E$5'9# +M`<86'5%[!G6Y07*@DL/#]@B_=V]FA\5*+\]/=3:&0OZ2IZ\+G)Z3>EO/F60K +M2.`4?LL[F?CCBYW][:+J/G%RE8'9V^Q2D\\V:/6P/R[Y;ZH4P0531MDP3^") +M/%-5SX75S-?$NM8P0%1EK;0;$I_+\L)S3D)6?SV^72WMSA]);;!)ZL%MDIL\ +M^L+:";AJWWWSS?`VJ/]K4?95P@SC2_S@G6"USX/L9=L0[OLUAV]:^ +MS[$6`I>'Y$4&.^&[ODU<\ST%(YI==NS%E!>;(]K+S.RK^)`=/3.NY1QH^J@5F)T"7W>RP%O8NT/Q +M$C2=N?"D>C!),R>^0B15_G%DVQHG?=.[TK]-B5W +M2=X?3$JJ:]57-1_^D^8_E[P>XLJIR.//J?Z?8/K\CP\18`2F*ULY,R55S4OC +MMT,0M.I=E-C(ZMI4C=CZ=&):K[^`,V`AI@^WW/Q+`_44YP;>,;XJ6[K]77DR +M;;!;O#\$TP:@=_/1;ND[QZO8>JQ[,>?+V!BC38YQ)'0+_O=<"ZHWX+1K"(+M +MV#J!=!2(6L+7@Y\/A[UN1]7REQ*3IM.>+R/H]4;AE[;Z4U^:78S.9>B&RT)4 +M7K?>^+C[\\:(/H*U\8^'X`(OJ*/YCSEMNB60FQ1P$3?`EV5$5+&K6V&M?3S7 +M5Z1R![9Y]7:FW\:TEJ[^YXC_V;G`<(%_N]-Y+M(;'E\"RI,/]P+['KX@^5O3 +M^Q;#'RTS=0R[QSN++EI@%C?Y +M1B7K8[K7A54!],+ALVOH<=>3:/.##J!42R*LCW,X*@U%-)#)F#6_. +M:#Q3I`)DD+A%"JX4?GF?T8*=B<"RRZHX!Q+9:$0V-S1EU[G<+Y"/Y1)\06BH +M)?G\>57NOP-#=OKK*WIS93;]LGT:$2I\H4_NK2F,D`^,C$_"*!$5B)VU +M7-WMH(C]U0M:/(Y/%0/+U'X13H,F5PRXA$+H07=UN)FT0..Y;UNH,M_EL#JC +M.1GBX='&)I%N%4JPJVAQ>>5T4V&JZ6U_QN=%H\W3[Y7&,K6"83F^]/?F:B/&QK%_8]5KJBI(3@PQ +MF7_:V.U#ERTLMPF'(L21HME_IT9>NHQ$&&,2;$(CX*NLFX4LV$$15AJE6LUY +M>2),?V:.3:/![X/8JWXT9V^48?)IV`C[IVB1%%XII#"S5>.^:)"82#P#545M +MRG,B%K%#_R4B;H\EU)Z5(41AW?`ZXCK24)G+DL0QX_KLK<0-:`5;2OA"7'1, +MPM?D;70Q+B;T[TB:EE!E?!(#=(BM>=UTAAY)5$W)%RXBHZCZC[?/KZ,D@V]3 +ME$U^H#%K0)H>7F?Q/,/\*Y;^?QH&BCB[@B)3`:Y-*KRZ`]LN57J1+7$&1V;5 +M25=G>B+W2Q]5NR'J`Y(>-.\/UMWEU;(]Q@_IDRJLY<0WQ5NDSQ>3C-=MP==: +MJ+"(]P:^\>MMO#3L@'[-+!WW,?U*\M;&<*HNF%B_7&(57MO2;8)!HP-YXR/YSO7QS2OEI_1NJ)( +M@J"!'3,5\Q_FN[IC.XN=-*YM39\4E-O;G29TA\;VN<2)? +MDJ80$DELQU/56T&0(H7^\,.P0NW2.`JEI>51(!HJ.`[B"T?YD.VS89%ZGG=Z +MSP4?0=G4B8)HYT"UK$J>.[Z;_@I-MK%^.ME5$\,! +MZE-J118H#`BA;$)-VJ5ANI<0KHJVYK-F#+IJ@TR3?.(??>&:=[FAS#SU%FZ5=/](]M7Y^R1*]]!C[Q&*[RW.3%F.]YJV&J^07UU__ETIHLT%7,"%V@W5]9, +MB;8K719\A>2^6.OZPQ\1AQP!>&KL`P$#%%9JW>ZF)>L^XMK8<`?K=0H$HQ)] +M>Q!`0)I'4'0K>J/$2E-T+F"6DK5=[P7A6=V$3:V*^%_,2!FU*JW\(AAUC26W +MY.0URIDN`H5!T&*(AJ$96SN!#`S?MP(4V[#Y_&23-UL;Q(/&IYB]A2M>DG6K +M)+UKB$D7M0YA0%BC!IH:*;-^=]VR31O"6WC]OH4)(Y/*TGO*IT'\Z,;!I6VM +M@2O6J"+[Q=Z[ST)>Q%[3J"R@?K$>*YC+X)$-P'S+(<3.Z2S/VX?RD!6@V?5C +MT9/XSE3H[Q%&@7`@H=`FXS,F+S`QKM<&O1.92/+JH<6J%9HB+84S+!VB&W&T +MJ/N]$4\_C5#]=AJ"C#B/1;,DYL@%Y%MMV#`'`$XL8?G$JZM&G2O.#$QLKII_ +M-=^*'IY#E!*.(WKIVCW5F=^J6:I:@H@YOYDUESF#GK*%^G,IGL$$'7A66UMH +M*+X*0H[@4+MM;R^JWR(',X4LDCR<'"9ZMJ.S7538>-"XSZ0J9\V>ZU20P+S_ +MGJD"*YIA/('4JJZ[>$(P_9HC<$T[<\G12%H#GU]9J9HH8B:5M@?VOT>^HTLI +MDUI;O?PC"$2+=RIC=P[.H?28^**K#:_Z&&;[^1T4U=ESJ(WF2M;XDE7E[M>Y +MD6Y1YI#UDGND9,A?Q431:]>D".0(SG`!2]E,S%BOHT8D%4W*TN;#?3TRPR$B +MJTM9[HTIS_V04.M&*%%JS=`1,>X'CX6+6;9;60Y\O[&C"\$!N0ZP/F&M)$B` +MEV$B[&'['2/IG4#W4P"/RO_JF=]?@9#2"%FM%-;1>2F4L +M/8U>D!_`,FI:#U."Q8BI;\!-/&/X5/XI77O99'3K +MVSB\$ZP=8X'>3Q!`?@=TZERH08A92)&+GR,3IA"-%#\(I1]F"CN/4V[9HFTK +MU0A#PJW-X_5&4IN2>VEU\/*2&M>,1>;2B.7%Q@7F0;RRWQ#E,$;ZX(9++5-$/M:-S/M^`DN^:= +M_PY=@QEE*1TM+:]*909)9>E`M8'Z&V#FU+%E'R*8NZ.NMB1YP=DIL4E6+.J?T`I3/_^73NT"O*(-V?7+65@ +M\:HD24)RNKY*^5'=K3\F`OMBN#4LDM-.YZ&?)CZ4K[@;?ML#G$P8OWF,E +ML$*0H5R0!`B(78:?U)HEOA464Z]R+/"EJA8INP1P+==E4T_J[?O")#7ZN%', +MP#*YOG&WVDGZ[4*4_JF[`[:N\<3RZF=1?\&_`VOOT(CIG,.DXTWX>\J[SI;% +M/FS,^WB7-`T=_\C8=)(%7+EI(PY?"$]^OBZ+_D\&[>7!2`J*BXTU(+U[D-)L +MIL"!4L4M6WMRV-?*MLW54`2OPR+6Z']!K-2Y!4"#>OS%S"Q=E]PHA+P5_Q@J +M=KL#(Y2B^U5S?I/;2?]'Z"1[S[1U8(H0%S>IJ'3(Y$%;P-NN>)W+&+7J,45_ +MNT*62-NVEXIJI=+HNA +M!SO&.K:Y7M/1"^#06=)U0[,UQT!YU@FX9KP@33'8)`R@NJ][9(W;N_^=G`"@2ZMZN]N=$ +M)/R0\EZ#">O6']$BKB*2Q*2/TG+.QL]>)=TD)6_I'V3!UTT'X#:*R*,A]HD\ +MJ'DA-7%!TP`8,['5BI&\T04"Q.1RIEJJE1Q4A1>L4,P"-()NR@4#D1BP-9F> +MK$*A$2TCPDWP@VW!>E4]1]>%S7:<`(@/U4X>.]FG%3AV=\+0`X95_.K7\'0# +MR9LXAF0NLN2Y:<-F^*!XEL`=Y#[;O=H$CEZ[%LT:6=BK#.I-M^?@))@L?8#.<&^3B&`_MK(CB#?\QP(LH +M3FO9?K`,/R]I\S>_9]U7`(XG5W-0?!;9`($J>3(17GFX!=`C_7P[6LZYX!%$ +M=VT2]16J4VWF\6L>H2&`7?;-F8JG/MA;QY1MC=ZENE58DTS7C/C0JVBXBQZ2A5Y, +M?IH\,:%V>EC/QV._MTGO+M_XHUAG%V+""*V$,:ZD25UZ]HCE)M-GK1[R^8X% +M3LW_=]U^L>ZZ%X/Z3Z.]ZHVC?_;C409VPCXS%%&KBJCTE&JCMW,/Y=TVYSM= +M>&C:;/W(T4:&VC?,:YI0?M.`#]'AQ4GS11!?O]IP&GM1UQ..P4P[(U$TRL`R +MKFT<]2VRI92LTQNH?URUOO+$!'#1&>'OQ@#V__J3!L1?5W%UBJ\\*/>2:4$F7$$OV+"617Z&[U?2):REKKUJ7H;T@&=OX +MB^1*J,*KF8XN],`'#-``KJS[UBA6A57I%7T)A01O@>^2C!YY>XGUBH(=35E. +M*3SI$C3'A6HMYB?J\]L_N/M.W_')4RKQP<(X\(PJ097>&V(3E=\TW),$UXO> +ML'/=/@HACI+:"MKH<;@+N&*96D<_[UC@8./#^`-+;]'59R=%)1E:M17*\FN8 +M6!5\8)#5V&I"#WU1,"ZKP0J5&R678G;VV%AA:T+MY:)10=\NW(W5$#:E;2/S +M?\E<-ALJZ4D5.WP#.T(\A(?N@9VD9@2\VYRKHI@ +M2IQ7`,S+&\*.6AWKCTR\'-W"I5R&RF()X84=IM$=MZ&&^XYUEV._W6K2.ASL +MQ)Y%^$4J?@GMI1I"M+>.=FF_D)XS82/Q69?CNKAF&7YA04-'LS[:_5HX[<#, +MEE'0Z(01_;HO214.\N,.'')Z]3%T.4]+5&YVU5\V#<:36[PAKLW]!W`8"*NA +MF,]UBX'V7)0_?&-M2QJP#X)/J#=*9V!!SB<$S1!=XKMQ4,$GZF4N4VX(0ZZV +M+`"<6M[D(O_EB(@A4S32NT,D.@YV,6UZQ,%^@5#V%L4\9?)D*!NV<%E^$LD7 +M3%#N,3M!FM]/;R/BWJBK+TXEG$9[!8L,8KHP=-\\BQX:B@>P.$I?.0N2`70. +M2M*0L:RP!%J#O:S"H91UZL7%3W&3;(03;/6QU$=Q/S*4M58BRT>'"P@N/$!) +MJ;AL3VDT_JPAJEJ.G2O+W(9#4,(:F%FKQSCD[(Z?[)YVAL&*POOL]DZ[,F90,IEIU-=&&@1W;/Z35C +M5T+!WAXC35^C6,>:-U3@I@LET22IICN0P_+/)H;H?F/3K!R&UR2)56FD(S'( +MW)_&@?)"1[;+I,0RBR"\P.8GHCE:N27(3F6IBQ98:_R@J?#O5+]DA>'8"HOH +M82^D+@+)J_KQ[A)@O<;\-F(D*?WF&`Q9X\7LA"B>I*AYJ(.@E/5,6[1.C5`8 +M/%:RCBOH-V`14I!*_$FD!-CG=32.XWL>C];_WXES&3PC"Y6=&\7]_L;/;Q;3 +M<&\A"/Q]]RH:/1-;UUF%>R#VJG;>"]CKR%DE&XN5F/RMO13=XGI2"]J72G5B +M&W-T^WHEF>#RYKJ/$+(?3TT>IA*@0-=<[LO->$JFQ\,CQ/E@Q=18=_@ATS07 +M=44SU755!+G306R1V>`^7OIN&I&!3Z(ML3GHEU&@GX(1KON^?]TJ(LY?X-A2 +MTQW4H@$R;'R'K>38#6EMW'[=JC%./[NMRYW#[D\A8@'%\APVB*?D]R*]@^+P +M<4;!53=1^UX%92%Q!G&YS6R#8:<@OM"@_?FZ2Q:9*$KES\[4()!FT!*O$HS+ +M/8@?B5]@>Q3E<TV''*:%R`MHB"[N8E1ZRIF#F_!(FK*K +M;.JLN9G4OH+85&"9K&P5*<3>%D29B$)YGRS(Z7HW$':1*GU1]JT]B6D'M!3= +M@\2&SZ*W)340A&<:$D8F,:C5;&*!8=PS9A>*TE-+B?Q>-YMLIS&U@'S*;S8# +MV2CDN%M_H^MS.CA\:$`!2$U)A,2#I-4KJ>8$AIGQLAV"9A,^Y^SPXTKOY\V6 +MOUZ/&&OPO.$_`\-LTX]6:TIFYH0UID\\4#UOL+_YN_OKXRX3L9Z:PFC,;FV_ +M+W<<=+-Q&K;$^7&&(Y'-TE7[O(EW]"#@PO"J2C.CZ!S4VK9@6M=2X"D_L&L$FTS +M\&_.)RKA7N3OCPK_M/?A@0[DSM886N694&-KU_\T#.:$P&>_=SHZ-9L^(P/7 +M`W'+'J#=".J?J3_[,9<^9].K-:S=6Y=6:?#ZJ?LS31K5,RI`/G;.%O8:%4W8 +M6:0?V)(:"DYM#Q=OIH)BFG7:@/C9S4%TVB;TSF6AI9=2^7:67M?0L%>A^!7! +MN]F]9%XHFG7E,Q&@=3U>E\2O:P%C%L'`Z-A8]A/0!"JVQ8T%DO6L64FB]-=O +M:6Y\K!9QB%/(4U21`Q,(-0"D"RR[^S7I`EL0[EV6&U:7>;Z-`!&@#--DU>A] +M=$LR(!\.;9%[850>[M3F4X2-JMDJD,ORVD4>QO0DWQC]3]F6#8B<`"8VCBA4//'`>[Q;P*&&0W"M +MC8118'_ZB,XQ`#B(*`53Q:#W;%(;NDHV>S,&X&?,E8,@U'M%_,8X.@28X]]E +MIZ/:).>VR4AF:%.W!JK&7/<&U/!^!;NGKQCKSX,_^J*4]JE:.NY(5G[SQ-\O@20WS3+K?7:VN?N#@KQ +M9#:%J\S*F!;2.$#U^U2=>7;TC0U)A[FJ)2J\40W%!433[O_G`PT/,\E\_>?D +ML5ZRV]%*8.J;Q2RN>BZMC9Q_G+N"'L+A8PNS=L92'-;TZ6NF75EFL<^_>/J_ +M#3U(#%("[U!4%VY*,SDH7M5RY"@%2B1LG_!2(Z3/WGY2,2?47CG;SP\!SSB3 +M9"J"<]1[LPV@O>2&A&_5E\V*.$U^.H8]1('EOK5'+4/I[F:R::_$CP&'XW?A +M42M/R)M9_M7\/-E]&'#^K4LL:`2`AJ\4FJMUEH!/7:&R4E!7*E.7:RO +MG790HQX/GK%M2)W3'VSY0R-.D5RD>1J0XM0Q=_: +M%[11%?1M$F[G->+X=T8Y%3@SXPP@D8]Q)NW^*V+C?L=LDF<2@45T,-@U2`$_ +M6T_SJD'5XJ`&X-X_]LX:LN\>/N%3N/F!L-&!891.*;5="II5BP<83@=FZ=,( +M0T/%VI><_M^>:?FVTTJ4/YL5,B9!_,0Y^47+I\42ZU8=-;F$2FS;3I!KSY=&R_>D]X("&H(]OFH/-6RAL +MUKJCA7\!49A_=J0^XC0K6ZAUD=WY3N8E_W_9CSF26A-#]1E+B396PT,'5S?Q +M%M#),>4]F+2;G+:,K$\KC>S_IO'*+""RZG8GF<6YO0$D[-I,@:A+;K]>J(": +M+*ROURHN$?:`OV\CBNX/I&`-!`,(7&CYA\08X)3^X75%G'8_BE3G!V9D_Y*1 +M\_^[V,AD07\0+^`OVCQ9L&>&62/-/E6F>9@-"2P-I(U4Z#M*.5[Q&SH$M#+$ +M->63U!IX:U>9<,+#I_R1"D)+-L/SI%))6_*;C#I!=D]ORZKWDLT`PRG+RF7J +ML[T@Y:'%!2NPDS:$=+D3IQ,H28@24SK^PO.]K=-P+AX!)MTJM?!L1@6I]LV? +MX6R)4:G@#?ITFI3<+AH`2JBQU^]C_9WBT3Q(58@_>5[5>[M64IS6Q]:MMA`* +M,+W!*RWM6`#-S:Y3JZ3]:5%<;H'Y'M.X?6-`_U#$E%$2F0[L9]$)%_<.4W8> +ME"V5:XV??//&8&-M=*47K,Y`G?50=X4*+^N^B5Z5`LO5KM!B?V/@"ZV:X+/!39>&AWM,%J8BY-NO'3,`_J>,B4HT%QM\5LF\ +M#>O"6VV+F6_3T18G25[9D77\$`AV$;!:_D'T0R@P91VEVFU@XCM#NP8P+I7. +MOK('FCI(IE.`FP(:[V!JGYSQ\/TY6=],-!K/?Z&\A((4@(B@FNGIF_;'W`'G +M5T#FLP)&T6)\U#+NNX;^\$'$3A\@N#NV#)MU2!L9DE]J::LUL*(&`%E"3\3G +MJ`J9*$EUIG'HXP/,PW=!*C\OK'5-TB9Y)V7"36O_NX'0:WT2U:2;+V;'XL[1 +MTOX(ODW;MVD@CT/]2LV$Y[:'0U0N[T$@4T-GID>_*H-*@`;-H1U)3@-H/6]; +MLLN)V0V\.71QP+,4A[]AN$WTN!^9SQ!G/O$V/CP8D*$-CN=LK7XM#>7A_P'L +MD8'NN(Y&\XIJ`H`2R3_UE:V*C_TF/*XRB%`DVYX#?(!Q!:;!.J4=&U"==^?J5N);1O1J$OG*T@'D+X(K>/&4T!>0L*_B$ +M1[W#,+*>XK>$'$^$F1#5-_=+R5IFI6YA5T1.:'&'A:N8&(-1!$:MY%6910?O +MO-BIAO_"[/--(WLL2Q;`DIUZ-JPP*CEX8WHKE>D=!JMRX9*OR1[9+\ZL!`.J +M\+76$/Q\"^E]C$?DUDR99-6T4C,M?=?8N!BGTWK<_+(52),<\.'??+B'_KU._']](@NI*ZPHE7^YMRXRSTA+::L-P>MK +ME2:84F_F:Q$$JWT29_DM?\';9R(T6U[G,4%VG2D%JG2+'KKA>+;1JRO`V++B +MQ:A__A*3BX'4T??_Y-1B1/P6[.$,H&/-X*HM7[<'1^WH]229U#X2YT5Q'Q20 +M"TO`&]O6^IF]Q?7&T!Y8XDG%#@<]4]/3@#),8(%!G4O=!_,WH-T13V2D#+R% +MZ7.#GS/B(FP9_R1G+XI_9T&[G#^5[W`8&$W/QODP/^S%I(W>)G5`UY[T$T4E +MV$5LPV7%5_^Q38IUJ``*+\0^O/T5"(:Q +M<2-84@L6S:YBKK1JI_0;KC[!W]DF]/:5Z*`Y\A)GC*7),B,;&G@S0JKWGN]` +MCS6YZLF$@QT8$2[%3/];7KFHKW6@#6X-6>M,[=KG`][0/:T\./I2+'&'(,-& +MKA]_C**Y`L7=+XN%U+91"-0JE>8';?!//I?U*SKOI\Y);L7Q7[ZA+.="3TA1 +M[.R97V>)]<\V[L@D.3!4GQN7PI;(B(G]6_D&*XRLMHD?&JOJL-OYX3*BAP5F]:"XA:2^K``@ +MO8V,73N2Z_<=$IMX\-ADL`Z/;QLX]QGHGG8T/R$9G.DVJ)9@BK:R3IJ,4HF4 +M6"FWR$"H0ZGNOD":6A9A9GE6!#MLX($6Y,Z=\^Q@0A-E7;;^H#]Y +MOU:C;/YWZLM_N_%I,^MS44@AL8%Y)[G4' +M38D_V[9^0N"`3$86_@9YN-)\@WP]JJE^9R9K:HNN$N&WN@%B!V2+"F_EV^+% +M1F44X.#S))<.KQQ./>F+"X\(8#E^_9@5]+KD^!C*=B'Z57]]Q0PIVK +MH='.QAPS(8BL'\?M86'BZ#WM,_S!K1'\7?=+YJ]=*W6H)OP;A&2HP&S(XK(I +MRU`-^CQ"[WPXY?3JFA(,GM`QZ+WU$$G#>I,8H3VR#H;_BZ8Y!HQF]NVKUF)7 +M52VQ_\9[5D@W**-A^D!Z<2^P%G/LD`/*>??!A!T$CCXU%MOEW2D_W8'O,F/1 +M>Y*(6$TA`CQ5\M(YOQ+1WJ/J-MK)91WDS3C55ZT?5T;=W)(KZA2J2/MH/)`9 +M[YR>-?Q2=[C&1MXE$12-(A)K55]%*\NG0692@VYZ9$,%09#N.F=[OP-;BN"S +M6DH/#H49@O5B6._EU9B\:6&77/JM$C]>\=@!+E=R/_S](Y?`5A>JF\$_("0T +M>%2F]&V[H@31N>?>6AGV^>]%__`D"!9IVA,8BP81MXC`4#0T;2^14@ +M9R"D=K\$NT9`O/D"_QTXLK,G"TM+%K6HI![>?!>/@;?N#X#4U9G*/<#XN5QX +M-/4%>>M!L^#*?E2V'Z:3@;7#IDB0G[7\#Q[\5,](=H;+R:N<2=JMU>X_ +M#X`H(V"D5_W,WY\J6EEA0\K$S7ZXYC'J=B:BG.P0.5/4PXY.\6.'$BG2_62^ +MRIMF2V.M8$MON5L]HL^989-N>_QXLG?MQ*`/)7;Z?!(A,C?:,:$*Y5DY8M[S +M$,081A$U)6C5=[B/3CSNU/H_\6-$;7_$[=(7%4@+]-X6G(D[ +MG@TL=84L*.!74%`PEX011$#:3'T+FJ8;*.LUF!TC`2#=0*KZRNE1M*;BE_BI +M@6)GA22POY53FAB0L.RVX+<&8L_57&(QOXS+2* +M11Z?NFJOZNM*)'S$-F/-2`G)RMXJMH`9#/Q6J1[%>;137-6SOUBQ[>GG^ZLC?$6F[%<(YM>T%/_ +M6?[L6/7Z(;@HM9U. +M5%Z20,3"*H.QD9.E&SC=E---I?)CR^7(`-A^`TUNHF2-!<8OQFMKN$>NFM!5 +MTN`_3B#>QR?X)P6?!OQ<1YB7,^_D9,?@0E;S)LGZR@>A1,.XD31/>0W&5\`^ +M(8^SE*.,2&L<(*H!8E+<*(W[04')EG"0TW0C!5@6306G@BU=2.*5740J[@%) +M@^;'8IQ0/#H"4X@7_.^+N!]1-/5F,IZ.$!G<[`>S.3!L6YF3AQ" +M#)JED]HQ&R\KW;,#":HVQN(1FME8>5M"M+IB(+TB1AU(6+34-2*#H7QN>:2!88 +M/0AA47)OJ8L_6?&CZ9\F@_TF`69%1Z_U9=(B7_+6M+F@#C#E-ER`AF!^3QMTJF +M*CI6XAO:#IMU\['#-J=KL8\8R9K[6$G&(Z=4#VTW=BSF38W:ICU!%-6[Z:W3 +M_V'&_?ZJS3EWL]%ZB2BOWOP63M"J(F;O4M1\ZZ29-A78%I*ZT)=FPA3C'?<8 +M8EO0?S3T>2PD&KWE0G2%U14G:.V^7_F6]ZK)3ZP"P<7C//%Z57PKQ%H:CS#3:\:%F[ +M)"%NU&F=Z\KNS]E9JOZD'-ZVV?M5^-U^SF/G'&-0NU-.+IU3BJL39-2D>D!- +MO_%[Z+>M,D_"]G/CD)S769W?7\AHA(((L?HUOZR#T9&[5771^8\$2_[N,N)W +MIB<48CRK[8#5_`_AB*&D8L>BK?G#:0$*[HN@M`+W_?=9=U@TT;SPUX&LATJ) +MU+IPWN9V)CVPNYOGI89U?%IQLE31[C@?:CC88D?3:#HLHR<$F=Y/3')XV\X1 +MA9/RR/[\`^%3H,:;12L(EF*>A2;YH2N*\O.NHKZXW/P+5^P=3=M'TMCQ=*V! +MG98JU31SB=FO]&5%NEHFDPQI;6A&Y;O\%57U0=!L*T])JM?F+^[Q0(&%6V'= +MLX5"3B^6)E$4130S(M^CK@WNMGP+X-`N/I\^.TRSL2DO!WJ`TWJ^'M4_+$'< +M2391A01U\^1D[_C59MUUXA;%6EL<44UBS@(`KRD406T@'OR:ATC2M#8IIDZC +MI&:)G8&OY1RY5=>V&L2`DJTKBA:0#S4F5.W1`.Y7Q'!`O57CP24:8;V6Y**P +M?'./68O\ZWU#_?(E$/2(_/P_86*R2JTDT=A^7H]H((CL'6;U%$HI?.Z@UE[T +M'^;K>T(?$TL.-5O^MCQ^>N#O;&!&N#40S$@"OE8TWL2F$"0($K;7Q!.BJ#3O +M&H[!>B`-2\:8]&NF0Z2SF;\NEA;`2KXKPM^&OQ7\X;F@,X?9.CE4<-9F$ +M,O4(Y5]:>-^JDUL+JS'7"E7V]X]7$85E'8X6"JW\*MZ6;K"A2?H[`O3%'&K3 +MY$=R2K%BX2E-QKIR9+A\Y6F`::17I>.O3NB(,CO3?9KC +M5WU;:B6YB@HY4Y>B.E71G@E41516P<(H+[!ML#GUB'&$%3'8!O3@KDK=GCM^I2K.L.'(U61`WTU +M65E,4[,`=29T`UPFL\A0[O)9>S&6F(:RN*CIY9"]VS*J-#*X_7_M&#"JK2._ +M%UFFN-%E-F_'L9&ICO%QV6P=R79R]Q+<'_9_N)S&$J5S_0JI\"3(GA+>FN;1 +MSA*JD7H&6/(,'=^4-X/!+9-AE6M;-"86Q2[5"%1)]JH%1$_#JB%O6@#7EN.E +MV#C:D)[[/49`J39)/U!1]N@*:.(T7=_5^T6L& +MN%A2%:7;;?.5_[FP6L:;O.1/Y56%"2*;/!I/!=/-UAFU%1%A3$-B/9F'&>&; +M?8_0/EW1_;/%)23+0$Z]&MA7K.E0#>;^T3W),FVG0YR'".\U4*B*V\0? +MX1T<9]7M[\89V*;BI?^?\ZL5Y%!:;R95'SMY]J`[Z?M/U2H%`^=GG^/.'>V> +MMX*C9(`K4?N!RN'=C@*L)HK.9#4A>M;%8*4[,[8!M5&T>9(KD**C=TC;8_]>_-GY$UADN(3)*!&G[CE1N)$ +M0H`EH>);3(?23PNH#VBB[8,'45TCS>.V"? +M0C)*46I[-GO$D_XX7\!T'C_WYNEL>?K%AY1):!2Z010F>:!.:-C6XB.(S@"; +M9)$C)&JYR1?-EY7)X1SW6/VF@1'3B,`Y^NDPW"75 +M;*92-WSOX:MR(Y05*F_/X?=$&L*2,;2`1WKV"TO$M\G?0QS,KNQR]J!3.84V +M*]S<`M/TUM.&1%9J!9>'GE1K#W'T-6VIW=<8^6F:[5V8&=?'!CE +MW!*Y2Z(JJQ\461=\.KI^F((]S':;E<@*'OT[JQ2P);<.*@E1S0;B))!1VP&8 +M(BXM">$`LZB5_D-F63=5K.4-PM0Q=BZI%Q_K$=1B?X5@6"2O_C2!)^WH*J7M +MNY"VCK^B=)U8$MV/3?%%X]>`8,V[YPT1=(W!_]I[0R-`C(.\N/R*.IHC/?%[B]%7?.K;,H%NCKFP[LX4"'1+QMHWP1^G&(^;Z(_\/5:(FR6BHDL +M7U2=HY(4VB4A)D(F]@][Z0Q9_VON3@,5^L#1K3;3P2V=!`58TP+ONU*7$8=* +M*2O54!X$Y$H"@`;USL4H[1.*7GYY*9$S\A^J`/"AF<79=_0QW1M3E_Y90`CT +M,&?4V3@Q`6=Y5?K[N[(0$R:5B4XQ*H +M;C&6$VB3+_X;P4B/RRF^#V9I:Z];`AL\N-3`52E:G!L?D.?C.\O^/XJG/U!\ +M/&`-\:[+?JO[$$C\B`D0"W=(V>\(8!]9"UOCVMUF^2CLZDQ;^N!+#,(CMWUI +MCV7GZ`)*36!D:&EXT/]P(-'NA,P;;2T.[!@<3Q)S<9F8D;CI.U>M]]FD9P90 +M:V04X&BW^"99[-J2"+X(1K-E4B/?LZR;UPSP`Q!V`8&5'-UB +M@OO90IA(MGQ*6VP53@XZZ0SH`O$E;GR$Z*'X[^\WP5CV1X9H0GPE5BOYS;QWE[Z9;LV9)K8'"<&U&*($9T\96_^"O@GT]*.Z^O-L$` +MK]A;8M)@4$U`:^)!&TNO#X"5(<#"C4[OP+P<;]SO6U_/PMB9>\O7;/60-DT( +M+YZ736-67BI3N`S\P[L(F(K+9U@4EJV_KK2"/^W(KKBFJFW`]IQANG+'Q-[5 +M6%&6WN(I3QS!_G6OL!BK!51WS9+D6?ZJ*@V7M\W0MB\!?+3G(&?'OG?>Q2_= +MIOG'.(`-=V!#RB?&_#1WC'ZXY&^2?6(&6J'6N;E)Q%41SX]\L2P/04!W3>6[ +MDV:%ZY,0V,G@DZJKO@A8OU9#>09I29XCXEHNT+&W]-O[ND]0NDBNA3/1IH_Y +M&DYN8*^57=\'+X"K%/;`YHV],X`07!:;#X"D$\9=4$J@_834)M24?P"6`ZS6 +M?*%5?J:2#M]7(`A@CV;!1Q>N'L&6EH+;XVFMD<*?A/A?M)U?JF`A.P)/J!9] +M9L8HM"KTX`F"3@S:'[W\%VY__(!(R^%155#/WI#__V-G<4)*C7@84T.M!*2; +M$GA%BW.WVZASR8/34I/X1*;LG$_4T]J0<4)E+0MZ(C<0OF\C9@7%58$GV53S +M\17.U&#$MX$?K*7C-_N<$E5D^U#,E[>NH5_%TPR`DC:=)58VH#5+B;Z1\=IJ +M022H*Q-<.RV$MH0P%":.H%**L*C9L+HUO!;EX`0[P7/H)X`5$;G"A]"C?GTX +M8U(*'Q@2<*5_I:@!W&T.9NV(U4KI0U3B3"<;EIF80C_+,;.`RK_[#%7`$H"J +M,*F=3VEDMQ>I^8:&,F=NNEC!%N6;J&GI&"ZXA4\MRV*I6#0\C3&$CWY*_`R. +M.#R,P!OH3V@+-HZ="D_=D&)D';SO`7_0Q1EEI+%T%P-E<-.89X8L8'&R]#PP +M`[7-(PZHX,U5S&H6'UKCGY?;.H'\QE\/>:\^.P?^SS<=""K7ZJ&&U`>8R#YC +M(/3HKW*:]4&_ULYZK^?7>P!JI1YA\!^QPV9P+CCFNX0!.B6U)1BM:35=V:OQ +MD)GL:QY?7OLH_XYIOL$_/3F>GY'XDHQCIC"5!<(I(#I2$H:T"/5G>("5\6]Z +M`@:BE/6M50S@\(:C:IYPH;@<.YHTRYAAC$4>-)3SYE<5NQ[EY\(6?])87:.[ +M8VQQU0,M)F@KH2>E-T4%,]=_.R[DN)83D)@(V"M(X&(VS_YPBQ_>)#=>;RA286*SIC+!AZLI +M76NE,]V2(*WITOS@4;26U//7FBKJ\C;`H*CLSQ4YR13`P3'9?WM +MV!M-98DOF&1R\!)C\+PL)BW+A16Q<^^LT=*G[5T#QA^V[FF/,3F867O;_(Z- +MEF]LES[AX!..O&=QZ"KZ@/;T?M658G7CF9!:6F[H#[,_62DCD=?I4B;LTJP0 +M+65ZAZPI6XFR8-MIAKS`->)E@9]\JEIV+/)T'I;OY6+#BT!ZKP>0(U)2E\+1;P6AZ`"0^3[AZTAAJ^DS1M`\(O:M'%AT>!;=)=*8!,J+!%K8$`V->*G`!0U>45!],I2KW4`]`7'QH6.#H)GI9O +MQ*+%/F/,0_=<=A>Y%E'H*;I--L&0A5&5=%2>6A)!XY$(]&G5*JU\ACX0MN:L +M,#)2>1B33+^UPT5J0K5,`/Z+TDRE-8[:0!_W@-T_+G_+)"GVWLQD63T1SP/H +M>9-9^67A(>$*JQ^.<5N,PFNSZSG0HU_@0,;$*0@E$X!>7DVY&U!H<>PQ5-M=#PLRYT"P/CW3BUF=KG+JF +M@^[<&"<,DT?P[7-H'[-#TSRH./=O_*NG1W`WC$P%(ZPE[M\/R([_D9>6+R[+ +M%'3%.6%2]XY=YP*T6EWOB)XQ*+(0.:RH3W=<<*&OTUF"2E2+#_>I(+Z25*(E +M;3P(#9^(2G_4S0BP,%%A4D87/U$FTJ*5/G%9']+3TI)5*A7#$@R#5!]M4R4IDTP +M-.V&M0MKV%N>F,5SA.-".E;K\C^IFB@9/ZANJCCO2%/[_5+01]7HU* +M@20HTW2)$MUU&(D@W'@3FPF;3GR[1H3X)%6^,D!G>TGF$8MB#"$>Z4D*7HFK +MEA/A*T._N0**Z=^I==X41B^XRABV=PV;+\XHF]IZF1;SXI(#[L3@G]"YH^Q" +M=7>MV707,&@HE)WQMBV=OZ%?4!EQ+_YM;W/3>EBMM?J6*A&5H*4M$]Q"P[@Y +M"K%:5HBU-.=V<;9-CQ:@KFI5&Z^6Y(9)G^5#X[5'O +MRFZSYV[Q#2I^U@.#-&>6[4%Q7"O[1Z*FM(1!8PFE,JT1NJ@;);M"F/-_CUW; +M*/0WMZL9).,6DX.<@MM$:RDYDS5_:K]"AJ51/#@XON3=`<[5,'?\JVL#!ZK( +MF`+F\0V\'"R23GX/J6U$C*N+Q=KRL`3U.,.[N,_1C<*)C;7O"2>MV9.=VPJN +M@3G*"3S'H:BK.7/A]/3IN[-#4>,>-^S$Y8EU>Z\J-]YW3Q=-2'/W&RXSSG +M359E:WU6D&>Q92B2T!4MIJ[B-HELHMUUXA+-< +M4MR9'R\S,?@CLB1O[;>$'NJ(`XT%#NAY2%6_(EWTI0#'SG/KW=VEGY6F#WU7 +MT^.+XI5=;-6TD60N_!XU`T`#F/#T46(>E9D0!:J*"ZIMJX2J0'<[9`%U`12K +M\4P<^9N!+A(B6)L5^VLHX2DXQL72@FA2WD&Y$`]#Q=JTW9PL*/MLN]H39D#U +M_QG]'70I#]S%FE)>]+C]L-*W)MLR^LP+"#9?MA1G5^.!Q->>X1E6(5YH@`^C +M^`%#&AQ1B'?IK58DR=R.L6&N0=V;RG'>)]"/RR6`UQ#/9]])7SN(7HY!BWW4S70.3)VX>8E-:#L=.6U.E[QG137B'< +MW9TVVG&5->XHMWYIFB)XREPGN4R1RG1;Y/ASR#AN2T&V/W8!H_^.;>LGQ/+1 +M?$WSJ87D()&9F)X2(C8OUU[&L4Z_>`1A%=)SR,D;ZVP\5R-ZI(;8C6/\U+6I +M,EXEU2\UFTYHZX>,O,_.36H#T/7]4B^]Y"[#Y':`VDHUYUE,<2@\\6Q@E\!R +M[*QR*D2%/HN;<SY"-GGSFUYM$=#"<+Q7EM)-4I +MO*1S2KS#B7Y8-P9X/;/0X\>IACFIC!,R%6^9QZ'"FV8VX/T0)@QU0I=]65ZN +MT\YUJV8(1;B%X)9NBKR0#!F?<7[?7&;7$]&*.R^G=[WF[GU6G-POZ-3'%AGC +MGV:[_HHF6`AS#ZO8/F'=O5H+"0TFPO@`HWYU]R:-/^H1,R$=FR`.Y=_Q(GSE)S_II8&DJEYF%&";OK.]S6W9UEG&A]>2"PHA[= +M7KX#T)Z+/4'`2RWMR7PADB,]+L5S:HD1ZC+45!R/0-+@`*SZ2_Q:=G.1LP/U +M'4D@"V(C&=K&"NGZ*,W!42`L9J*)0H<6',9)$('O(9L?:=_B(@*7V:5O?$,6 +M3318H+EAPN#@%@%2D6.6D7_/82/9)HP2Y;@)K6 +MDM,`V7.N[@:6CZ583;NL[-'.??@%(,/U=*\@1*>@-:[G,\+AV?*_.MFNLN)( +MLMRL*3,_X5:T@YHN=F4U0@PI__P0KMI?%/%,N'Z9^+[AELI],#X>IX*2&`Z! +M^IT?N!RBQP3*AX2H@T9Q>DF?G5<$1X_/?WO7%E+U#?E(L9Z6'OR\1<+P($-!P:VHQN#0&DRL +M'W>?\!*F?,838"G?\J4$EMA6`^G8D[TX[I%)#):>.3,#[_,+\M*\;?NQD89* +MEA%!>>A'4@^&H*;D3=*0:=ZP;7*#DSBGH_$BY!6L^7&CH1VZ=P6ZR2$8#9%Q +MNE,9W7AD&A39MAF+^&9MY:]TWI_%"^%Z_UB@),U^U/BHE(!G*;>-)+A2Q(S) +MX]RI/=.)'*A2$QHT5B2=\4U3#V?2`]YBP(V/JN$&LPLQ/`T'%D_3 +ME<64)\8"!928J5-S7@2M`9J3*Y0$+1"5$<`^_I?R#7+?93;8V%D2N]30*H\& +MA+ALF*N(6=3+G[CZ](Y9D8W6S8*22AW=G$S'TSQ"U+CT'0`L4L&Y7M0^I3N0 +MA^20VJ]"QD1 +M1>3X,HRU5],Q[Y07J,^6*)M$$\0*Y\"A?E +M9058Y`V5)TAP^^OGJO-MSD)707?B5H +MJ*410FR+#7*IT=A*&&2X,\GJW9&4^-N1F"Y+G-$R,>7.;8]E7>B:0H!$@@[+ +MM:PROLP,8`4X&2@)K#R'S.5&EVH<;#@X2&`?6D0RH_$47`S/,?I?\ZW5/1;` +M3G!)#CS._GD&K<2%B5E9(ABM$7T)$'7I"0U;J1\(%4S.''HL,'\XA+Q0$-[5 +M<.!^5KHLECH..\>H!@457`-.>@C"\-1`M;2KOG.,3%_C4PS09X03!9)T6L^R +MR/A$BE5*],FVS;TFP,ENN=W;#&SBW5&A%IS,'BO1`=J='?[HCD3U;RIE@ETZ +M';@=I\FW7Z#&0B2C=.(S#G\$3=_"S'4!=X7W`Q(<8Q$(INUR +M>^=4?2S)&)@T&F*7I^$5W9*!=VK@HEEVO*5*0=^HW?Z +M5TN#(.JWJ[#D<;5XNN?/+M#2R-KO0YE/.YS?SE&G9@#%"S"SZ5'?0ZHH89_& +M?=O/,D^/D"/G@`'4KHWD_(/XP[A$B;]ACF\`9/[XH&1Z"=U5G9ZLXYQ6&!@8 +M=9+E)A3\]6IH4+?%`A!?>%VR_D6SD5_*_H(>8=HC[*V&>.)0B%6J=QB[';IO +M$"04.E']6[#Z&[=#EX9M>)-1,P!\-_2D(8CEEN$`/67^_.TM@M8"SSR-92'&*KZ_<(83`6>'7X7H^/)`LLID-']A$UYS1IQ-_RNW-@_J`.W+ +M(G+Q%:7U^/5]&:-VW4BK2TZ/U(`)JR73Y_TXA^#)8ZH2IT"(`(N77!ZS1^Z0 +M;]Y*I,7S.-WIKJO&L"W]&I$EV#4&R([Z9,OS3K!K?``'R>?(C)U/D""XW]E5 +MSU^=(=L(I)JR6*'O+JF]G?(EAPL5@F\0U,/U<`X8J;(D>R[(M-&U7'>B>P^I +M#3Z_KG!+77LWC#A9&J#"!5[&-=Z?S%UM!&$H"FJ:OFZ9^SL./3);)/0)KI"0 +M;L<];:QACH +MPR!'6N#_,>M_?-]EU9=FUR<&*Y,B+CL6YGAF)MW/J;,4:'\]N/^6CR-!U^,Z +MD^T@'PJDY9.3H(3"@*M[XZ[ESYJY6ES;"A`HC$EG(JPOQ?NS\Q$KP.D7^"V2 +M58)-E)D2<#B`IY=6X>DK@__^(FTC\/U":&T$RXUV=4N=8%U50)?)`!%NM95, +M_8U%D)-4@_8T'_%9$JX>%5A+`$@>*H<+A4*R:7LQ%\7];<@>W1[76:7[`(*5 +MS3$B#"H?HQ`L.9NPPX%<39'2E[HXZ^AWQ=F_I@_ZZ@'$@Y%L%R>94K%$]]PZ +MZ,)%@C9+(G9EHOREYI/6`1POYU<4<+F&FT3FH"YRSUDI*?1_L6L+XT\[5<6S +M,XN3JO^`V@0'D07'\B5$RDDQL1\=4,RNK7[N^6'(1+EM/'4#[MU)&-%(][6G +M&0PINIZ5U5E8OQW'V%!(RIHN1"G>).4^H1J+SI&\`ZI^YIYES6Z@6R2XK?T] +MX,)E]`N:BZ,/*748G#&/'OQTLR\MY.'[OF"';NKU17F?9"%^B_-5..:_NN4& +M]=ZSBV&[AGALJXSC?N"F&'!D,J_]WHI#^HH@2&KV18U%ZA1.-*P,LZ]4UX`T +M0#]Z`H8K.`1+D,$1*7'=7(!P*H5Y]\I^)&\FF.HF7*CF3G+'S^+OP]H,F/O4 +M,\#@7&6]58ITIJK@V_!(4;;`N^&'&DI/T&CK1HP5H;?3E/\(E,H8W+L]Z([9 +MKJHS^=,+3Z!Z$*0<[TK;=2)2TEU4"J-F'-';#LLCZE4D*Q:3D<7)OUF2R4C; +M"7?K.L/3&_%B1("$E499VA.ER'%*\#D^RR1F+*EU"$");1Z>^!1J?5_%@K*^ +M3`8.FVYB14/3*J5#12])XN`,->L1[N:4'>9\;'0(,I`G,$BC=+$K.S#7IM +MA^M=K$!GDS1J[EXMW/OU36GG5I9*14/N3[+8@5/J)OK8@72EH;>),"IU@]5%5J3,[I6X6P\4Z#/*D;3=]T#V5E<.2]]HFF;'S%'N5FIA4>PR8":GDXU9I=-0F86%_+D]9X +M=9,5-J$L/]HN.#I5%^&2%^B7Z8L@)/X\X$@5A>R<<4[>GOP9/-`*$@4Q3CY\ +MNDJLIO/S&E#WCS)"!]#5+5)PQ,_+'%^4UKJ0J9_)^X9BU=(IY9-*F-Z5Q=9E +M!5P10U;KF2FQ5_D4J1/%>OH5Q6DAS#E<'C;%5+7WL0X$<"3<,_%"L76>1#*( +M@7MKI0>I(*M)RJ'`!97[.7/"!H9_#5I*I-&*@D".N%K-0`W0>WVM'N^VK2&S +MT8P^A(IZF!,&Y\@O(F&K\L.)M"--K7F]\(/0Q8_Z%DQ,Z]>>J^[`ZDYW7RW_ +MULHP!+2['$8(!*S\G*7KMDJ\3R'%M8$:)M^1K`OP6X0U#+:8T&@0?2MK!/_4 +MPUWJE/#AH`U"X,=U-\?Z>,1B:R.\E2.^IW=T[MWB;+)\.H:?`XIH-GS\B$>N +MJS$#PHW/X5L^DDE7?C*@TA>&]-[Y9[3YRB9N9V*+)!(3`<]+HIU5#7LC>$-N +M*M]-Q5$5-PO3Y_'2%_DNS,J9C6I$1L(KZA,>5V9LAYWL+^)TJQ=<02*'/D)0 +M:^Y2OK+"T;LQ>E.A_+/[?K474K6Q>,'8UWT#-&^K,,*TQ"\ +MB9A.;][_Q7_-4B1#1Q*U$(:"59M8Y0\^S=G!-A1$6O'W3G)EO_T0[V7(;A#) +M)[UD2*8L49\6.8]-NB;QE$Y]4S5E!9BQH3[4#S+Z$O"7_KN-?4.[[EPO5!)Z[N+W70K=/CE4+6N&]-?AO`"M +M0KI_;W4D;/=A-(X"!&G6?#[WX1O[]7W/5OQ`?.L"BT +M1G("OH7P/Q8X$7IBV_K]Y$",YBSVG;8*1D1I$E0*8WM.L;$N*1T9#REHG3G^8GSNU'F\"BD1M9EL(^762, +M.CA2TV?:EFN#OQ.Y6.4JH3;62@3.65:9]F$W0YB?&H>X[G?CZ69LK=XM[5Z% +M+MM15<5AAD96T%M>K53$/Z9WCKEI2#+(0(UY=E+\4**KEF2H+@<=(0V1QR82?[PT\6'6A#%E4 +M;N`Z7RF']*T89?,CQJ!+G:J`];AQ6E.)>>X'W>,<+#3_VEH;S,G8[&9G(5!; +M\66U/>X*HN1S\P5R8W,`4;,JDX[I`I(W0>'@YPA],`BB?+M2?@FAL'F:LN'/ +M!Z1<@ZI?K=2U([?%E4T-92;HJ4<^&.>-^<)C:5T(R'55?Z%O$F<)$,B1/(&-1/"Q!'R0L +MX+W+6L],5?NJ'%X9SF68EP6H/$HP,Q?1Y7G,RGPCB\R-BSC63LBU:=Y]7;,XGSLOVZ] +MZB;A"&O>2O2\B\JQ9Z[WEH-DQRL1&@(KHU'FC[CZ."K)X'=;52#MCNFY6::9 +M-9X=R+"XADN7ZO_U(($P!^7W=!A-*@+ZC:I*H74$$5M&>[`LBS?H\49/$NFO +M+TW88"[%;;A`*@./BP5;4^8-LR9:2_/ME9E2P6*OS)F4'!H[D\/&G4&.8L=@ +M\"VCP-:Z*!/##SZ,9R,_`7&#!+E$5#QV=?O5A'![?V^H +M``C5OF8G_9'X%"!SI:,,/;7/+=W"K(*CO?ATYB;"F +M@I@-6#0-,(X85E:$%[=X'&LYT,2D3F/;9]A"'O-K42`VY74M\E/*@R&'L\^\ +M(8846$9_<,6EL;(**WB%=6)!-+^V#"Y6F<>Z<4`'P7\4(=NPE3:/&9<'-O1W"188*S8%;^YMMHM7!H +M7Q=&KUC?/6FVGPG#^[XJSN$-O=W/80];'-!`&IF$L3&D.XO8>%HA!#H/^Q)B +M2M.Q"1.MIB%),_([@+^"LNGO;@1`D1CF0.+ZCM]N!U8U-XV+>@=B9)-1U(_* +M6YC:$JQTG88X(_1S$64GS'G%&BU@S]U(1]CJ=_`5LN>Q*VS*+EPUKOP2$\TL +M5$;U'U\G"&UJU<'F875+/_Z"PICP5DOS#.POVOAR:#L5M@D6=I(-Y(9@_MM7 +MUU>D=$8030\24WN?XDV_R#KJ7_@1%#1BDJ/;,C/@ZZ$_BI^24QP$3(/629D7 +M1@9/*C?\]HXI;-=*:%'[MA"EX[I=`1DBA*NFN(D:L15[.6WRP(_&9IIC6IDB +M3X]8\*+\I1.#Y0"EZLD>KZN]\?/+?B6!%-9,="/;3(W%.OM>$@B:-6KOCM`S +M'.;"0`;X>S:>;@)0L#.[BDUD%@OR4OIB9;H'JD=T+G^'[9?-!'W(>I+5\X[P +M[W#U`BO_S0T@BX7G&5I1$&$%OTHDAW.Q+YPGT.M#WG*#[R5-O+=W,\8\MQ@! +M&R+!^\;_N>^HS,I>9[_KP12:\]G7A78JB=[S9:`<,O<7>?.UFE>P-O^BO*Y> +MF,>1-2[_,3!+_^P[SG(/'F1\6;4$?J*A"9:&O'<4["\]B,OR)P,T;MA8@OJ= +MP03>4X5[L;5+$]>I[@?F8TN:YFN']SGTIQ31/6[!E^IS[Z[/^AL,D7=X,ICD +MDBP)=37^?8<=X\?\QR+T4 +M8D`4:':X87#DL+!?*/_8*#UD3@J'&(@E2-^N]3GV]>^S^1J75UE/E$.1X=D' +M:/QBRJ.]PT0]Y";1\ICTV5#-+:%K*_%+Q+ABJ9WXV4GGN@,S[?U3P8Z/Q33M +MO<`NH5EIM`:*3:F-4GBDH*+=+'4-L\2Z^Z#5O99^7@_,?W%E(_XCI8+.JSS3:&<7:AO"Y +M3P(J?(!T>5<'0$P39!'[GXSJWQ9>J_#M@")&4'\2(;H@<;&M8R^A_5ESNH:^ +M!3Q$;J&[/?62)NS"H--=<5,Y,MV"E5\EOCK.;TP:9C1[0;[*]RPIG41YZ:N/ +M3W@"3LZ0:XB]#R;BPAMWW,HM;88^L_J/^/?L*I+[J0QQSZ'!T9+:%1F"WD"; +M%2N($-"]>S:,&2&,CG_$XIRO'OR'C7HIFNSI9>C2;O9>ZB#R\Y-,G +M"T%5J."K(:=>4PD3./=--;V]347'Q$M\2JS7\K2:*"$;%S-@#3UKAP;.XH9& +M77_P$`B-W,C*:TXWFO-8I/$%4:09.C)IP6S],)&7@%U\ +M]]&B)XKG#D&5WI<)1[Z3G]P6]:+WT'LPO<97_[WAO*6F=5? +M+%RE-;KI43],6\:PG70%6]ESG-/$)=A2KXJ5&,^U;WVNX?P%F3&H+TF4#I(#JYO +M#IU!1LU8[^TX2R(U?_%0LJ0'@/V&J^@RKQL__N:F@W[KL[C5V8M-_\5H%I.5 +M7BV@/__-Z9E^^FI>Q'\O#)(%>8.WPR$77"Q"Y;,QSZ;'G:Y.OCB.6A!?IG+& +M?H75%OY!P*(3?L>S`&'53"=RB&-"5L/V-\NG[J1FYOU8%A-W0C\M6W'V3ZF4 +M6Y6G!&6]<+5I^N]@_O&WXN&(KZ3(V7R!VVN8RXV#$V/.\P;C0#S3V[45VT./O?-_7NJ^9VX(%C*I6=#8G/2X]?.Z +M*0WHFA7MBL$F-WV0SBJMY&O8*3>"+;U20Z=AWT\+)!\2'Z;?'O$Q"<89\NIR +M25*];_]>VO]%XP+0:`2B\+%A9R[IF;+:A`H`]-#%`+(LD*&_S"(_9ZE5H9*& +MM0PEJE9O?]DEG2G0\1O/>WD1SE>HJUXVH$\3B88.?8(*-QN^4ZVOG2>!U?G% +MXA]67ID)K!>3,2GS^VG;!O +M;%>%S3GY7/I%4_I@#V5U!(LT+>K;.Z+AXJX2O>!#ST2VP?JJ.9G)*[U"Y@)" +M%POPD7QW14EQ?)=QTV;7])/SIA_BT)(``<_ZJ19IJYL6H!6//?]385/QD;*= +MTCT\"6ITO^1%Z[60QDF`H=#OZ=(2.41LILL;H$2NR;WBIQV^5@*B5/+:1WR0?5,B10OE59N>L4>ZPJ +M/'PO.J+05NNATJ/<%1[O=O/_:Z%/'"O<`)+(9X7[1.*^ER\7IN^)_<9@G4K[ +MZ'X&+;ILL''K%TSJ10V"%3YVW[":C#T-]\E`0N@@C4V+W![9C4">6B=UAHD) +M[2U"6?(<=J7C,'&F<3BR$%:2<(-,J>'B^X;3_:7P:3:+J7*@UX/Z84\*:96- +MK,OS"LF;&/GFDR?[\_*A]PLF@K9K*Q/Y92'WX@3!L)CH_TF=U]0&($:"D$\Y +M>S%_.GQD6Q)00AA&:[YU<=++-6M9DOV;$#&AK"&>H2!K%S"6;G!X#3_N8Q+* +M8%"HC5B#9U8+SZNX1U/%#.-JR0_%#[&XH6**B>#BR"C#=].[GPRB1BOOS"\? +M%P,HI]09Y*+<2/&C/'AU*7\P@9)T:PKQ;`&HSF`PC\,O=)SOEQMN6=SCU?B& +MGG[Z_J3Q'+F:WS"V3YD-&0`8RK,18DXZ7291-H$^^OR\2M14P0-&6ISVOQ'- +MI<;0DT=#E.RK#91!9O36?X%K;32F.4HQO3 +M^!R^?1`:W%&2P)^QYK%O5"XJD=@EDEHT,;WX>-9&I8EK'/2"&J"1V\OB1SX@ +MVYC`3H.96QX2K`$1W@0#;GXWJ#8&S010*#F_0[0J32SNOH'!!U:+E]A[W4VI +M[,[8;*=%E;9>!4U&2+BG!ZLWVYH'C.W88P0/^%A;S)@\6SY8 +MQJ\#\5"7?+(SXCT:X\(;R3,"P6BRY7YK\J?ZB;VL^8-G%0GN$]OKL-P$6QP- +M<8S#["(W?_X&^>_CAPO2]PH#W9 +MP$-3RZS?V<7-:&"G5--3_Z$QU\/J7-,B`&=9L.@V7>ZYQ2^3UA0MG?=+?F_L +MCBRU*YL:^ZVD@4M-2'MMK=7[SY!Q/H)GLORZHC7;*VRPM9,[2:3TFOJ.17>/ +M6[^T_=CUZF1>CS0?O#^)ALFD)OBX$(2;.#;NG?(\A"-%T"+EW\6EW,TGZNQC +M$@=F0L3^$#")YW%=R[WTZ&ZO`(V*D8S9=9;9@7S2O.Q#'!+KXLK,2`G!L7IN +MK[.(TI(VGCH$?S>AU[I*27^WG&^%U*_T<0^V$'ZM8O_Q.0K:[0_8A%V[Y/XP +M5.3U*/)L>8?&0=S=[I>`\E`3L*VJ-Q(C(-EM)6)[IE?B,U@857`%CDJD'!=2 +M+`KVF](NT<."3]*B86XW3/MFI,X+^_N2X05?JWM8*_GVK!9)V?-DJB\V#0FNN +M0425C+#+D@4&0H.9<"B=Y%:1]1]LE4^00^/?4,(DGM-'2P>8_^CPTKKIVX]3 +MVXI;J1;J8-^_.Q;#\@RH']32]P4\5-IJ0>*.@2#>G<-`%WW*(62SO#CR.&88"C +M`(*6G8U(>CQ\#FPN6+%);J*9#;UFMR=5^&5/RR[J!>>.=JDZ@SJ*\%9,J3O` +MC2)ADO?@5<+.V,G@J*TOOJ5UY..3THS+`,(Y!P/M!O.BUJOUTCP;X2*:_:IQ +M#^Z(/YJ0&C;#R(\V;MQ`B]#[,P=J,@2V-%>9):2VPMO%/XPI>_X_1;7X43,V35&F.$*106-P*1XKYVF[A>X:"PT51/O.3&)=X'\44]APA]GR_8(U(75M'04; +MR930)/'@IDBQ.SXW4`O5*L014*IH]9=F5=N9S."(57Y9AQD8-ZSABWK-8V,9 +MPAT\*`-S5+X.Y1OTWK7\.\$../0'?E(%[HK?.MWH]"32ZL:[X;!=@M']A8NI +MBK6TWQ<,BP:7MK`V0/@PTS&6O&+X1UZ>D9AB:6+]4\S*N1<+"4V/QUA"54"+ +M:#Y%_\#7FE^\2?\'((&;O"&<$6FU^[1WLU@+J'UO9B]C7]BP+/UR)2[U8#HK +M]`A7`_R#4VE`:F+RSN6"F167!VM^D3V6[Y+7Z]H$!,$H^&4\=#W;K8FC@L5$G[I;M^U)_V93!\.F$7,E&/WJ?3]OXYPM[JA-^ZV@B^YBQ? +M,I^"U'>"ZO49+6"X/F%BFEG[F)H&Y3-$#`TT`GFM>"RB,Q)![E?"_N$?ZVA# +M8]V&")?&>L.?2D60.47+9&;*T-:NE0HW!!X]S5H]"N)_#EY]9ZU)TF1G@Y#O +M^K1+6(N)=9G*D#PN8+P\`WU8/)BN#BAFD83!L,$\_ +M]+-[L3FOEB3^5VEOH=&\R0XATQ]]4\ZC#R?[8ON/)L,OYRR??+_?1$=W@,_L +M,"Z-:,C<@AZZI%A*:(F+P$OZ*Z7YL!WSV^=SK7--9M-^'+I3G3ES?)B`"KJ8 +M#+9L5%E>.VXCO-+*B??QZD!J3.A]_[D$HJ_&!NN/\BIB'TPK"^Y0F#4P4#J-]9\Q,[?M5W-%:-/A\ +M.U]==6H_V56C4HQ8)I')H``5UW<,@USEX)T,,\-H,D'&X7B#T6L$@I?Y.D`: +MQ#"/%M:C\_`1XD0F[&;!#+)7@1_:ZQ05Y%=#C^WVA@A)N@I/OF5B%G7.(N6Q +MJ3QOG>.;)>(ZL**/?_V];B[,[>CA9ON/!YUU]YN,#LSYB#(CZD$"TI9:A0L>2 +MT9+.5N(1*V\#17J,^&(ZIJ&_9U:LK[3$Q+"V[TF=>+3QR$K"?ZE'W0H +M,G0!T:@ESP,\.;9:9>R_H:[R;R>7WL]4_J-:^2"@ZOW>G>I +M7ZS'`#N!T^0GZ]@$&KNKU%*,*P;^#^7TS\#E`MU-B1A$97:_;-_,+I=N/8"` +MSR/@HD6M0/J.'FVY2?YAO,Q!K,Q+D&#:%,;7PL!_TU6)1 +M0+^D*.Q]C@DX!Z<,<#W;H>-_Z2+^'5[Y^>*U)5Y_I)6UL3^\!X@I:8;.Z +MN%3!=8MP>IKNBZH]$7K2_884 +M[RN,?,T8E3O98`!S6OLGJ@+,(NZ1BQ0PX^FN_V/:35SR*'O-='JM#P8I$)&? +M&.\.:_W+[-A)_9`9=.9.4NX!JJ6?%0^J4/.X[M#I$HE'`;^,CK&P0-XOG#]0 +ME/P:V__,7=63W``K#!D=I`5-@U2YON1#PUDR!H`,/TCW.-?QZ:E;QO3TD3P+ +MN%CQM:P>K(@6H97N3.G1-IM5Y:/.X(C(_6;47-[^JG_U-6!A_!W,\P0G>?T, +MK#OZI#&Q?R[Z=TGG/>;YVS")\X!P.ER+`,.>I@/#U)TRLA_W+>&R$4KRQJ0. +M8O3V'*N9%IDI502J2$//P`]>$A#6%K2B^>1I)W1L^_0)69PAYZ[C;Q71$ELL +M@X*'%]W7'+7>(SAK`S#RS:D8U'HRFU]%V027G]JBA\Y$XH&CC.N(5O6Q8\5* +MQ[K*2!<2;HSCD)HSD>.3UXU!57^8W;:#K*Z'/"E;[L&35RGC/9S$.?W3\^&# +M^765-8SL%'SG/`FP0`>,#4G=+61+L>-W4W@_QW8@C)%]K,)VJ#$]8=+4!):I +MXYLJG")6+FX*HS8AS#'?UQ8S@GY#;$*48T@Z:E$Y[DA6(YZ5Q&^F/354"AZ7 +M)PL*<[V#$7]'<`LH:T0DKZ9B<(12OVC)F#-UIV@[<8-6ID6\SQ>YO"F6,)P3 +MF/M&S16*C.4O>D@JI$'*7&[3K6=6YN6K'1QU(<4S,X(V1X['$@J^WP_ED",@ +M*&%T[U+\QU9VQ(/+QQM%>Y'`W0.THH*/6EHJX#+/>B"@48;Z?TX[Q6H['*?B +M:>KG@MYZ:5R+"5KJG?K3@';OF=3!F]8EF!ILV +MA*U5^VC4K^(]['ZM6JR'E;9>WT7!X_Q?[5VMMOA7ZK*;"_+#<&ZY*Z<6F()P +ME9L.BFSZ41FR7+&,F_S8Q`._,,1[^$5W3D/QHD^="3EM!-VJ?4M<10&G]!O7+,^O;G +M7G`%O&\OE8(A`A<6"7*0A^%*-MV[U4]YC`*XN17>>C$G#RX&UZIQ-1GJIPHF +MZL0<_V\-PC>P[(O#+&Z34WXEO4AT4G?F_WD#NXGSZHV=`4$&.8!!Y[9!69@?A\Y +M'0>)-*GV?N5?LD;)+&V5"%Q6.0(*7T43%`H;N7><6B[@(]E-T%BB$IJYQ^%> +M643[+UP5+NU0/RT]FY]]FSA2AQ3BP<-0S`R"T?X4824N!1*ZQ&,J#?4\G1)O +M[V=)"2B!B;5[PDD@J`\3X])!ZM.0,#Z5`+I`5^`''&P8X$W1]#KY-D;QE`"4F=,*(8AF4SK*Z\.[V( +MQ->V(Y"JA5>-9]#\,6.!_/77C!$=$=`-?DV[DV77/M2@(,1AX&43![;KSL43 +M4`C!-?LKC;A/JY+XT-)3^I>0YC28]I@;WZ&!F)8^K`MM>A8H>*RX?>0K@-Q2 +MZI%5[4XU;A;1A44[KX'&?LO=0UGC +M]'^16D;A#1SHO1"D5,!ZL8HL:1ZMTY2Q)6+<"4EPR*IORP"0=,7=JBJW'2/_ +M[HOF-U(K,IGW+A@D_Q5BMX=&\6EZ#'!,")B3ET.MW'YSQ0L]8^PD+=7S]O34 +M0]G8\)3DV?U/2\4N?"'R5`GV' +M&&9SIYPB:NX3IBFK1DRR=FDUJ@T'R8&*0D?1Q"=,V))C@@,8-.D\4+,<@*7M +MY=U-H!S+>M*IF^3KR90PA'Y+E_+\M6;;80H].4R$'W&T?2>WYBV3?D>D;WF" +M3K0)12/TXI4LF0$PI`:D*=C*6$T$TT*TGHIZ1W\5X'%+8#FYSHQ,J:M:0T-; +M(;.P:"ZQF5NYPCI_^V\!L!)Z]S\`(DR@;>2$C=J\JBMR'$Z&O9TUW];(FC7" +MG*7U(;/ER,6&DZJ2@C47A:N%%!!1F]`6Z?S*QX6_L3!(-00!."<.=,9K$LB&K-..7PT,D-_\`I3/1Q"=<*>[5X>NM:,A^[LQ@OR2&NI +M:?CX9;FU76)S.7UZ>21R(%N2Q^%5/*`>>J`+;?@,$#JN4:X(9!AY"E/O$,T` +M)&;/\&M)\LKAU[S!1Y-<:ZX$-W@D84HY+>6*)#25)A6-1)KGDV,7]B$HA]O- +MO5H_`5?^U<*!#"]*$0@9>9$<%,XB4.I]`0"FYG&!]M-)0WJ(_^L(B,`)S-Q4 +M?ZWC_,]V*@C(;Z$0_^.G.D%NM'N?''JO5BP*/F6:D[-:/5P]WO[->%P';4)% +MT?A"/C_,41P>W>E1?YP;VWR#]*<*&` +M#JF(2TPP)F+)G<1AE)T0`]+>[\-:'^=J?-"PT#\D2E6E(@R4"_ACH:@Z4YJ# +MX'ED+G]?)S0OR6Q\-HLF;8HUG/:DQ1IS\UI=QM'4H0TAP(1F.84'4/GP)U0M +MPC8W\>!%&HT.S5Z:#6;%#]5D;"..NJ,?NI:NM&CNOW\A557L_+0W+\5Z'=#B +MNP3LD/D!->4^H%.0NFB:\P6W@':^:`E_^EL88;[_79@;#ZPB>Z42CP=VP+]" +M4,7O'J/UZW]R;=3+#1Q9M*H,-%7ME'(8V'ZE5#B<*O-PU"R]=1%]'KVN8`H* +M+F@J/50#*F]DT^V!(K'61(7TG1ID\4\HH%9H8&190;;[?&8 +M_WT,1_@/I=`)7HE%TY0SP`[NE^!%K*%0;9,G<[1P.,[!1=YG:<8N$%X(&QV= +MKH0%%YOZ[&!\?&X>MJ[O2H4U="_7T4X$IT_]=6_I5%NX'UZ/D@BP5\@KR0X3 +MB`Y^8':%P*[`EREJX^B^5_ON+2DKMRK$>$\RKYA>O3QM2U,?AIRP9B^;4>:Q +M(<3!CP8/G\$93\:.:$+4DW/!=QOR7G+'=SX`(M.5S:1+X%!#S*9P?Q0S;B$% +M.::=W_69J.%6#&[6`R>._3G.1<..X>9\;4<]YV+*65WJ_U!,0!P8VL-%YO0' +M-?@M_DB!]2S>Z!<,%`PII_[U(1ESS[S'-8?L3HS""7!6@1*@ZK5<^)XF2LG= +MK\W,[#?Y8TZ1(EW&P0/1>L"G8Q-`[^:*G7ZZ+T`$Z$$[)(H.[%]W(=BDV@G+ +MYY=*4C(D<&5%<(2YLGB5.\"BK1A/JN%DPHC[R+@$ZIY>W4B-*S.U*&9A +MS23);300,O#98MXI57U3ES$U+OBCXH).-KW]_Z9;`PZ&_&6&= +M2*U1`Y+WSIFZY^49(S1]_808^67`J;5Q[`80YFF0'%@S.V*L]]0$UD?1SM^Z +M(S'(7]!`@;1M\J[ +M@_/1U/SC8[`KZ<#]DZ1K=G`K98L$R$YN6A?`I-Z0*@0\?G5G-Y^AZT:)!UACT'<*Z:K'6U/@:AB75DR*F4_+L58`+ +MP2GRAE#+^L:O>D72%WOMR(BC(.G-2ZJ=3/.HN>YL]77G#9Q%:NDG.G@-550E8^-BR4RE^.H,!\>++]KY +M,I)0J6=503YGU3,"R^03!<=9MEK9;W61E4#UUQ@I+R>0*)5:>;K:C2XH+>6H +MY*H-=.>77%;Z\,U>`H,[,]\@\M[P+*.0`.D:I>_%D11230'__C-L6[+8Q_N*:WM!DJVLH=0!IP]`@29*P,W^9 +M)$EV8P%`$8F:P<_)Y[;P68%7MR\HY2I=.5V?UDR-,ZT7R_M\I"'Q]55KC(/Q +MW@LL14%ZDI-G#7"&FE22((3GAC3C*?8"0AR>*>FL-&K.F\G^3ULXX:`1_BX +MMQ#+9-T]K;I.,1:DO6:U.'^=[/&)49ANH"DNCN6\;,N51AQEP$G"/]U@^&TQ +MZ#!:(S4EX'$!7!6B8!N7T7+_;K#"M-$3+_4G>Q5M6E*/;.M7L;BGN3@6S+2K +MDTE<.MB7(B$XT*:_(&3$UP!CB1>@91-[B38Z@K`2X?@DR]/B/>?:!J9&U* +MO[VTKKRC<.5.5#CQ44!#,US2E8\YPRSD&2DS7FT6$ROS=,M-OK9S"G#*R;#02;EQ>&(HZ1#/E$I,5 +M-;M1A`!=19<]P[?.:0Y":CV$_W;SK.?@A%FB@G]YO4PW91B&2I59\!6"]G&. +M[\JJ1HCC@0XE02QXNHY5TA+_\,!P2;L3:] +M0R8I!G6U\-&@BJS=-:_(4KP,9/P(]6%H48^GWN`&VTE%>=N.JTX1G&4H0`!4 +MW6Y7.HU\,6)`V!J"WN-2FC@2D,^WVW8&\^&,]AL.A'X?X>0AF^=U541@IJOU +M"`%Y,WW@$N>$5RNUI@>`9E%/:G.^^&Q>KG[F-=D=HQHH;/':D +M/4/@=Z[E`IG?Q7V+"LZ\RQ9#JS,AF0B)B3@J`H-\2FC.NPGMS87!@`4QCB-S +M*0VU;,MK]$K);]`U!\BCJ!P,:9-R_Z9?/PUF +M+&+/!EVO^K]PA3Y"O"7(2MR$V=8]R2MV7M=!B!]IP:=0OK:D'/%;13\^HMS_ +M-KK\M]-B3-OQ[4P&U!F[.C?K1E3J$^LYDA$W(Z$-^."9)3;Z&I!ZJC[MPE_[ +MZ-E,C,A2F'*+VU,KZMF\[&R.>R1=A7A45&/@Y&JTL-2YD?I*-)ZSX6@TVO9- +MW"E4"FB>;GF9^ZRL*_D5JK#&M=/V8AS-J)(Q9*`\S` +M_92I^;XV`)JS!2=C.I2(C*!!($_WSW8N%_W+J$D8=6OTWTV70LS1`G-S=J6; +M0B"9E@PMIX_L@IW5=RE:<'%,EEM-"O\TB#/G4#`U*``%DT-A:%<@_NRCR2D$ +MA!Q(3"``"K&F'7!.RX(J29(;1DA);:;Y%E/.)"5V&3/@XRG`F)T):*0))5WA +MDDN6JOJ-EZ=P6BG/TB15&:F8?$^8.8W98#-$0Y8L^?`>-1'T1Y8SJZ8>K]UN +M+W`MC&O;##E55SYJ3+FF>ZQ,U2G$0`&6,0N<#>H^4E$K%<4D,HYM>0!S)!D- +MS'Y=Z_-=(BM816')<0$O-1)%#/O)J&AU93%V--[G@G%EW\%IV?[C" +M!QXS)P[LQOAT>N&/H:>S%T%D"P07PVQ1SV@CIV`ZK[%#CC+F#P]ZU'LPGZ0L +M=762F-W2]P$-`:.@8!=*5+TX4^2QOQ[^5GF202?:%W3=^CJZM>?L/I +M35I/&#)V'X.&/SY +MEEJEYP7-P9[SW$";2I\06L]$P^>LW0M/Z'7;6>3S3)6B8*G06U?)O!^>Y1C@ +M>:PU@&8$&E1#3059'@>J9AGN3-J1MJ1/FZ^?ZN8FC]E%FS5J(T%(]6.9_#E> +M*.X??3B[5)`.4][\2Q*@9//)L')%M.$.?O)J"@$LHSMI+A,9F/O>J`A])H)C +M$%,2)G#B3O.G"4M:!6!!K8C'N](DIN%J>44,(+J'6`MA3-X+H[KJ7P(SNUV^K +MD[ET`NNR)/+C$@#O-[./T/R-52L(7^-CJN#8!Z%D#T"DAQ5=>EE2JK2HGSP% +M^?(*](%SN=)UX/>C6ME$W,05=E#6Z84Y*\5PET$2^JLX&-RAF$"W*D'Q;#Y. +M]M=KY-C0R1/9K+@?*_.!/WKF1)DR-=(E0KW1Q/>/C+SZ&^*^8+/FA^UV548!%W]H$T\KY,V/-B;$+>I +M,])*+;2+B+YA#C[WH^P.RH+3%AX\JP"#K(^@2;XBLCOCIG8>7)U`.G42JKPL +M]M9QI+4C294ZNU3``1A))C#E(M:"[78N+[Z=_RC_S-J"O@4%H;*7)UH+?!N& +M#U;6*/ZBX\,*%$`-PV_;(=A@P%2SZ,__RT,L%FCU2K56%B,J&?M+GR.BUTJ< +M#IW$`YCRU=]!%V'DNEINNBSG;6QJ)OY@MK3,?6Z<,G]];6@"FZ]/"PR.!^W5 +M[\0N9#JK[1&GO`"N#N.WT\$='EO7(0TJW,M/CV8=2"Y#WXF0N`AR(C^M8=U" +MIC__482F&#F64:OP5LR?*9"*XL&&'!%&NXP-9'`K8%F-;*)='N.K40VY)0S@ +M[:GN2#6[IE=S/S8,4;9=[C3P.NF]%IT:<.U`/@VQ?#XY_^]?CSVD'\8+THZA +M)*-Z3ZEI?'\AEKIIE\;;=#OM3]N>LG9&1B,]ZI"D8_GLHG_JDLPN\(;W/NJ* +M'[?Y=>A!114PM'),<<=27R<=9HP)KU +M2\"->:H7H;J75I1#R^5-NGLVTP]P^U$:Z&E.)JQ1`R#@')1\.[J'KNI6U5I' +M$AC'A9AW8K<,H!W:*5NO>&#I69N9Z%[F`JH_LJ+HAYR?S6Y_H55,*R,V$QJ= +M!!A-.;IGY[UBQ<9SI.[)L,<&]LC%":#4-OAP2J94\N/'JCLQI+#/;,*;PS,< +M4)$^3.=E]T1^HP%D]VGRZW)DNY$^^PKU(E.@*0]Y?UZ%G"O#7!K_5#,0.^;( +MX]6KW0XA(\[/_$J.1J582G14[0R\=ZQ]-Z.5VD_QI/.CL-P?P<.83;=3O%PP=Q<`6FI:1"AZMY/300BIG2.<$ +MQ*Y,81!,ZML6!/?T6-YWT%2V'A%4^JU7IE;^JP#OI08JLI]I(F8&WV4([KL9TPQ0:^ +M@1R!:_?^%HJE +M:X`X,%I80'5@Z=O6<6MB4%N +M>6IY:T;-[=`[U()MYFM"D)[R(,E&02DL#@6]\R.G5XN3.*O,IRWO)[-3(%-9 +M[]GGJP=R>]456T'_P?-?G^)T2G$1J-8A.D_[`31:Q55G5$`'?GCA-+M:(IMK +MO@6HHB.8_3YS),V+1,/E@]K3J\@H'F8L]%36!BQ2MB;\S9[=Z-, +M)&!-SQ.8U20AB27(/A3P"R*(73:YF!2A]=$P@9LH1<-9`9G +M2T*O+?@YF]!A6+BA)C#?0O3_N8J9K>1]GK2++7C66>"`'\/I*:C@"M%(X@#0 +M4#'=$]";G]YL41!+0(LNNZ5;._GE@*W*5Q`-*AJWF5N>&_^.:L03]T.\L*E.)3`AOK^ +MZA,?.KJX4DWTPZ/Q-IH(MG1?7"+0-&<.:9A>D]8-!!G(#"#Y3TG#7/*$7*GL +M@+,`\O38_''V19-I/@WECVJ8^.IT0I`%6:@E#DO!/J$KF*1/G0N^P)0_V\+Q +MNW1JSZE!!<6."4&\G0SA]9+1Z>S)W1&GV_M!5&PZ7?7MCO).$,)#;.4!_Q@N +M;\&!ON;]2(@KMCA\1,AE;<#?QBO91`ZL6DM)6K,!#*$7RO%=DW!'764[EQG` +M5>_+CG!O*\60K+T1NFKS5UX]PF'?[4YDMPKFBQY"B58P(G:0E\)]?IXFV$3< +MM^[2=YH1E>WMU@>&,-E9L58F>*[4#]4]PL_CRPB\XY\VH_.,R,+-4O9D5$4#.[8?WS>P$5DX +M[UG8[/==+)5ES;.7I)@7A&&WF:5BE&PYCJ76J)VB[?(RV>>FS*_$!\+PA8(L +MMXK9\ANPAY@:[,3PW<%4EM^VYVM!'4L;]0!.#+J<7AS5>-C/]B7($-::5<'K +MA")'R?EGQIRQR5N^!]I=H??L"=8P0NSA*E1R`]%;+2QF&7DW-(O/!-Z7<'(' +M$DXXZ?`.U5$MXKH\Q#&N0JV^S#L/_\*ZG-M_J(\O.NL8%`/;9SFT@]YPD%*7 +M&;>0]I>-VYVY9HG;M8'\25@L7O1#N6H^.C)\.#I2L,3C@F[LY\3!:3(X=O@9]4U;B@:_?>CLIC]+]]"$)W +M$XR7WD(*UDN87-:`^05(Q]KA[7TDV35GZX]$ML/+!Y0H22,[R?4<&3EE6CNK +MD=/RN;E@#J;`=.:-Z`Q@+FB%+[&B]LAG2'E6>O@!X3`T1;3QMZF?GS2G_4S? +M-%54]!R(-8Q26&&X70#(PS_=\:,19NML7NWBQ92.R++O)'\2Y79DE$CMH0)B +MRQR6X'/Y:$TV9-LCB_=41=ECMA6%$A9\VSI+NH;=N@#U$'O55[:8M$-I[^:4 +M[MZ>PT''2N3:(7\+'5#90_IG +M]JZBYM4G-V5"MLI.D51-+6&=Q2,.-R;;3J);ER$Z?G1W+;#EM8VGU_+W-QB$ +M]H@&/:+RC"KLPHNH2[57&0B634]:X8V'O4$3)W;?:D2N)\&W:/2/\R?(Y?!1 +MBDB_SV3;A+FPFUD,[QJ.%ZF\9;UOGB::7:Z)7#<8$#Z2\^[A*%Q+ +MJ'C717HP,SA##<.ZS'HMY<6.-+3`EB7U!T#HG$I3W6?0<^D6KI +M:0(JXS5,N@/G72CA4/P"MQ]U%LNF:!^0'B*@DE[D>^$DS\`I+;.\2U5P9WE$ +M+MUZ@5;^C@E*0O%:_A-_12Z&U'YS:43;4(6!#.USH7)%:CM!T'2^W'>+<=4% +MVZS"`[N0V)<0-J]N]7C![:\?-06E0S&G4D3IQ_[A1!IK.NV?[B:#W.SCX3&E +MB$C0@@))Y+*ZYV7O*(`/;]+$G1"\#ST]?!7^70\ZOU;B26O_7XZ&.H`V/7W1 +M%";=DMMX)C:&.SB>.'HT@\RV^LEGA^HF"1+4@]SLWA+239!W64H(0BO-3MQ< +M4%QO/\V\9`G)X1EQH&.A;-V2$E!OENFXQE=W$KB7OS/GWC]2=W-GG +M!ZB;P,[Y*R.48@-E4#53S49J&P:O\K'U_,Q'EN>H5]9WG,5E_RP&EO]A.V%$-QNWJXLO&2CD&FPP-Z]`4=^=4&\D\GC,CZ@S([8"/3U +MAA`0*[15G>MK@4'8D>?@P^MRP;`WF`HZQ[?"^PMN-J[,:[[Q#%=L_H+RK\,G +M(Y4`A[(C2$??.6M1U6=3Y=P4>D;=V_4II&X@)-`4QTHX410YD/Q0F*+9-$[, +MH%'4W$#/7."QI=A+I-;)Q8]$<2N,KTA/IM#&3&:<)X$U`Y'%7I`NORRD!@8E +MC-06FQ)&/=2TXBUE$U[+[7`(*Z>/._TTL-'@LAXA7`JWV?#X;XL<\&@/UGY0V9]-C.:86$P95#`=K5\SF/ +MZYGF`"6?Y!%*S-U!AL5>K$K';(7$$+WD3D&+Z3@CG;%$(:')K6QT#`&-[Y8? +M_\J8`H64)FE\ZP[>5+5$E`#8>=4SSQDC4P2\C7>XM:^-0MTE@1A]"?C7J],? +M*I1^EYBDR8GH%NIX5^0;`)3Z\LT5?"1*\'(^\F3=E1$#1OGFL$+KQ,H9=EZ, +M6O_4`]6C](*RM??E6/,86/:"WE&_SD4#(236/>0"=]1'K!52PLA-_BV[ +M'4R$[(%7X2R.HA.H_OBYM;,24CK<<70\6:C_>/349:[M[K0(WG,XV(<-0YJ];D$$NX$3\(%/]A\A3;/ +M+YY#FF\\)Q?J",\FH(=NJM-/Z,0.ETXA!P[SC7`&?$H&[H6HK/>@<%U7>\N_(:W#J\1)"K-*Z/@@%05FJUX%<_6-5"FQ1F-DT'FD=*4S['N0)D4FNRD=1:T3L?#.='N"R1I";-D. +M$U&R+/*(<4I.R]"MYIQWK_T;#C6E+J2=/*`29UK) +MXI'35RGF,3)FP:@7F@#"&CPT,K\6`YS[9_7;"&;8B=)T;Z'HLFGA2#YL7EGR +M(-"SZXFU,GB+\1.\7`"4LA55^YKIPIM^"FG1E?[J7JE=&152#5M=2#8BD%H" +MJ9G`A`BD&]W[8.,#U,)HO"4:EIY['CV@GNV+[2%/ADZ*@&;I-DYJ`'@B".)) +MYOHR][7UC92ZM6G=5EUT?6#+'".#^07&5$*5.$>6X#G:GHR4MR;FE2([AQS= +MHT\>?/[E&V@<(@1'8'1#ST-S/0_S7JI5TP-6"4N%0>YL0;9[W:N;BO%!-#5$ +M?8!E?H8K3EL5T8#/M/#W4"L6,W>#Q'^!%"=LT;L;>G2]B(#-C;P?^&WFYUTP +MIVM+'1,R%6-+*'59*UB9$NI>QHB#I+W?O9;N\L-`7?2T^X$>..P +MDDMTZHM380!Q8U`U%?Y3@`&]^`20W))@?ZI1L\+*S7%IB&CD'5WHZ"D&C^FU +MV1,<::YN>3J"HI$E^./[:APL7W;O`P$FE.-:'%^#2Q62:G]NX^+U%M1/5K5B6WFHNH[`)!<3$J++RH26PH>6YQ^ +MFZ$=/WR'/Z*_6_HN+Q!UV/DT!GUL_TU,,$;:M7Y1"JSQ+I@0'?5%@;/[MN%& +M,*D!>6#&WEV?R2P[=%MQ[A1-GTN)_<(D!X +MYQ?1P9&^ERCRGX%YH[XN&>G('Z)3YUHM=C[?6+?A;Z(P^T#=:V`S +MG^T=-5/UD7B?SMX4!)`<>]_*\YPTC>7B,]'E7ZJE4S`3YS\^138L\5%0)RGP +MZ=:Q"S$C@+DPN`UNI'M+EX2+]AY2$W[-]58PE+FB/KT:?3+XJW7Y+GU +M:_AR%-\<("7Y^_^('U:5]+PI63SX.&;F,-;T5/N_E>^"8KIXSRL8S>=Q&D'F +ML[H5A08E%CN%F$166?T&P(8&&VT(V]`VKVZVIM^>56,67F!.P07Y2FH*'4MF +M==[X;Z8STW,>AY)_L`D9Y%O\\Q+8`3!SU*E@6>.QQDNPF^8ZNMKZ2(AU7#GC +M2#9A!E<>#^:_3SV.=M6W`KL8%=4S/6SD27K$;NZ=0M^#))ZX;8%8#`PRJ.G^ +M(/.(Q(U7A22O:@.>SO3OJBJ9R\$>X,K$"4\K57M7U?KJ"\JU.N=PTEX41PGB"' +M[^DWQM)&::3[U-5J^-6&:U&B7;-P^QX;;9PU'<(2D!2P*DHI*)T9_!VNM,$T +M6`1IG#`AIKR2\9(GYUE=I8;$\=#2>\1;[X0&C-\N/X=8UYU?(<:]WS3CT% +M@V.6H_+1[EKD#-1[GUN6WFRRN:BRR35G.:E,-I^=R)7`.LO-.G55X9PE]BL> +MDJQB(`&L<^S#VHZ!]W7JCG=([UP4%2T_W!D@"),RJ$WHFGT(Z-%=E@KG9&P( +M>'@<.?>],/(756[94)<5NTJ9%G[F8P+S;`27B]3;0]C/[Z19/4ZOA_3 +M2$.!:2Q%L<:TE&'I-\I`GZ:%;[IN'O=LBR6M,]G0_[0J'Y@I+$QD.=_PKMU] +M\M0XEZ?WJ4J%TE6@V_T\D5_2W!HC%SY3';L_:-V$9KB:21#FR?S'+CU;"\7C +M*=J-'2`#]V\_:HURX>W/#" +M:X6K`FW9F5,GW./23,13/.%$CETW8I*[#D@$E&BB]%A5-)4`'?YGOKG$O7T. +MB,)L!<_&$@F,;)7KW4#4K-XA:AHY\D9/[._I/A&A;(*IK/`5A?SZX\[`I3U$ +M?_6,Y:?7AM0.'OU]/UM%BL)6Z#%@0_^=/O5[`\N)R(9,XKX@PDUG:?SL,7M` +M`'Q>$@AI3QD1[9P;4BW?LS"3AJDO>)D5G$:G,Y8`]\/7756-KQ<%S^Y/)W6# +M%4`&X1:;WR?K9G/GE#R>$G6U\`$L)M7:U].?"&@<,;\ +M[1X7)FL&*'3*?-#9=%2"K5(AM5Z+0W$OU_K>U("0=N;BB56?1:LQLB?HCN]2/:L1%!)_S4T2Z<6':4]S*U+#(WO/"QURC9$5 +M$OTB%2=0])1)>X9H_";'*.;CD'F"0T.CF4*BURL<00?P($2;G3(Z'1>FP_M) +MKKL4IHMBAOLOW7T5Y_/UD,*B6+!(%WR[[A<@=(('F=9*F!B!`_HN>O5^D"XU +M]DZ:"O]M".X,J`VL29Y3M5U-)@AL'"P5?Z!!&$+#XM5!D0P%P1)3H\I5R31Q +MDJ""@/UG5%#5V![>?XEX.4WT8P_9Z0R;\N3K,'B721K%V-)>\NR%4ITG@D=E +M[X,KA+MFI_VLHN3^R1].Y(8'IV<4:\ +M,7<[M])-DBNFY;=([C2QZG$--G^&8HZNXKW+&4.$GHI+"(QX;JA?IIBJJQVF +MAP5WCD%^CJMS/1W7W>*V;"_>?7;LD/7^43=3=X/X3RTO)!WT3V3>=(&K00PS +MY?U-%?+9-[4#4KJK^HXZQ@U,A)9]@*(R=5"S>02JIC:S26"R%;@XPPXOEB?G +ML8=0@_?+E!II+E%PZDDZ`/-3%!H0DD7C_X=C$9SS$7/F5M(0"]`[)G\,_&_A +MP6D!55=("4^'U>-AL>VD7#;K0)Q-='1^1;55K:\`P=7QSQ=9S.Q*E$#"44-B +MA'<[FTJ-2@7ZK(TE=S@,UQQ:Y\W7_(;NHR>`)H[^%(][U!P-!&B1%/VX1T\X=MYB*WR9#!90(HU=T6'6MM17[ +M^;#8^'4]!F-(7WCZ"&G$>&WL`X0]OS`,#YP\7S8Y5+ +M+]-2L2.Z:O!.QCB=$4[J`+SF1!HHBBKYR9Z2GV:`:W+9;PELO&TPV=Q^4O.. +MBQB,A\Z*B\!!K)`V'BE$Q`J-?2C>:A)+*^D\0V>>[B=]W^7]PU]\E?I\D%(\ +M7X/VI_TBU#4`=*?2+G!8)&;^ZBKWQ2+WACJ4KE)$(_)X_))4,?4PXE<[]5K2 +MG$O8H<+E8.Z%&M:A=/;&&>P91!P5'C)U.^>R59(YZ&>P5FFVAF$X\=OK=!KB +MP&KE&"YG2X]=8M*8,<1D2L_X0PZ^WNXXTG7<*P-S[YL\BR)'1.^J_7]5!>; +M[<(HJ7;S1Z7+C((''N[<_DM$'*[HLMT7;!J<-(\C$'8!F-_+ +M$^D^9RY?[)AH'N)PR3XHBHW`H#?VT5)W#6-G=1PFK^73D@5^;[]$U+]%^8\K +M>03)Q@4VA-?+LM8S4S7)V[P;SX@,5T?&%1"2DA?E_-R&-2D0`$7?W>'\7]XW +M6:QT".HGY^Y^GP[_0(71UTKC<@4).HILGT]$`JJ3[+!VWFPNM$:I0';@QYZX^30=4F<<8QLH4;0S3G;Q:>6^*S3R +M]L2!1/`)/:AA0HZNZ"2^OV7X6ZDQPYOYM<*7Z`*$@UT3K!T72GO?6D1=Y+#7 +M('6AS70.*09>8[>3Y_L_6&RG2('J;]U'\FKTL+Z,3PN-5X3$\T2BGP0%*L$L +MCFAH:9.Q/#VWZZ4UW0VPBH/6D,G2QZSN(P*?,XXVXB/F,E\?WQ#T3A@_*RF;]X>9E+QIYJX(7+.<4I3'-&'MQ]6XR^K:AV!`_'T1KDOZU8PRQRGK6 +MK.U0"MN=D%-VF_V@RC(G:K7JD/])%;KF,&]BU7L@V-)44QC,CIYA700JF'>[ +M9[BOGAOUA^M)!VZPPSZ:`C8(E*1A5W$GG&J59!L^\&@E<&Q2(5NW/>7L)Z/[F%\%D>`Z';; +M'J+>!8W!:)PD^@P`,1>`5RM&E*+560$DO%]N^JK%BS=>Y8./XI#!LZ[\/&KS +M&6@O4]Y#(*RN/-5!_O5_>R)5(<`'/(V2;ESF1_-+891&&^5Q8M(Y%818?<=, +MAW%U"L%17YO>.H?<"WQ0E+B%/$'"]L!MK'G>61H-TXQO1)J-)[W64R],`8SAM63&BQS"N%U)&<@Y/TL:ZG=(A/ +M<(G5B=9(6N`D84,A[ +MR9=7I->)A@'7B^IX`J5#?J8BG+O9(*/@WTZ1X+9.O%.'B?,OW5H_8;^:]Y,K;>RBJ8#LCCJ,@U*.F +MPF3R0?5"==@H,'TTY7&F\97@?2M/=Y*V)6G^?&\,&+FG#7\`OGJ#CE%<>23S +M<@\45K>A?4A(EY;)*<9_GR!EB,`BFJB/C9S[ +M="_$-9FUGMWE-+1E^X!$_W4\!H^#3%#Z2+#NA":B289T;/9KCH8N$J;$VB".A,+V1Z(?X/)5CY_Z;>/*$#=`S&*TH&45 +M#\3>3ARS,O.$!FW?JW-=3X)K>VUVMPF))J`_'1892L)E)1-4--KC.[#4:1`. +M"/A=PPHA7J%METG,]L-Z5++KF[9 +M]D.K:)PK*_.1'L4`-FR+%-G!>XYJ(Q9,IQ]X(:?NJJ+DE6!=:?R,=^+A_/W> +MHVE7T!L%8H0*`]0 +MN,`ZL>H[,HF]/WR.!YZX>L"G\OZ6[.@/E?,YJ/KZ8"(HA0P)!'\TH&U?G"OV +M/HAW%I\"*N#?I;"-'2W$*V-E3`3%DX0GQFTN3P*L"D8\>KJB>X&'/*`-XS0C +M+TC#H7RDX3!>KX=^U1!EAYA(Q3WC%`Y.1W@;X*%TZI"E>@V:H$ +MWG!)S!\81C"J/3-/JF5I8$M]-/0#MZ@(<2Z06)'C)9.S"DZZYWQP71VEME]? +M6>)FJ=G?HLFQ*&7ZO5%!S)]*9:X8$QQM>^_>0N8IE&;"#5&YZ@^/1IA];WEG +M6F][-DSL\XU"3+P(=5HZD=)C2_V?VNW%_0R+0'GDI_<:D_B^<8CO6Z^K_Q]F +M\+_$YGG2\-==`>`>6CH>?.*_B1XGXT69%IK")DN?^*9M;=&;7+5_=; +M/@&1R?P*`8NFJ6VX;/86#OHQ?P97=Y_@""SDE2JJ(W[YA1U\">]G/: +M&F^94)`.PA+=UHM4YY[R>7'A@R;4`Z9D1;=%??><4D0SZ;;=)0/`PYT@+\FG +M-2F7I7'A?U#I>,SU)S&-+"_=#6,29["]W+S<82WHGY&L?J?&C@BZ4.CA,7)4 +MZ#'WL@P`'!D)A+T=HJJ#(SE,:[^G=!);))""^$-CK'"5]I!?MBD3F*2P^QD. +M*1A&&2E@DWY'6C_R'-=]ILNB*?C,X):);4,4;PQWZ&M3=X"("[>WB9<)\&_S +MB;\A8H2+5+E9](R[T;>909%;UD]]^C%@-(.FR"ID:=-64N&M54^%HV'V=%Z; +M9RUD3GN*`U\\8MO\0!`0Z._2;NI^\*J1OKU)W6>I,E#RQBDZLGJ^O!%SU$<= +M15]J[#9($MJG1*VTRR&+#07-.U)-:KE#?=7]]M("U/8,HFY%;9@BG5BA +M_"30,MLPE]&/K-7H/;C+=\QQI/?\FO7P@^0!V67`,.U4+M9Q&/-2(+5K(V3U +M&77J;[P2<@^%%Y_O3!F%<'2(NH3W];5ANAV$&$*F6J\@FD$W9*.&DSGSM!Z_ +M@XYN#7\;9>;&.'N7>7J6%H0;FHB3_<8[@J@JD7``QWDH@+#@]T\QT[?VW;R@<* +M=SQNE(K',LH0@5\&XBI'I\9:%2BX34W4W.B'KL.BUP?^<]9S4!_W5B!^Y56X +M^]G=!(+MOL_A.->]#"@;XE-&"B9,(@&K9J>SWTM-<5V +M)9RLNWTSI,_?E\TB5->>DF9EP2BC!4H!C^J67'#KG<2:' +MML;O9%MW/6$B:X9QQ#\+07C3*283"(KC1E?UV6H)6Y>F@P']``I*TV8 +M7VE+S(4TV%[[W$&JU:#WJ]B]/P'J5H\X+:!B8J?6-B*XW!X;%]SEJZK*`/)B +MV`NSXICX.&M%)FZ7FTF%6T+`/NT-7,AZ328Q><'&Q-HY;_9O3RDVU*]=68/G +MSW="]P@)T!H;^K='BFO-4QERD^X(`2O0O"-9!VQ6*`G3'ZDZ;$GN.+O2>*`6 +MN%('MK@U,(Y+G.M:`V+[)X*/"CX_/"\G.V=H5MOEY9(FI==PU6^-7M,J"SX/ +M/:CW_=&0$""I_:P=Y7]3OD-^GZ0QJ].F:^,D7?=>[<`OX[16.PU:RNX#G71` +M8)Q?*`&WR:#4>ZE$I&9LN@.%BMB(_Y;+'4L34EN>R?MH,W0*BQ'^WU3*Y"*6 +M0$Q4LES`05>*G4B6D9:+V.TS$G\R]EO%M/:X)-XFE5$N$U?JLI=KNGV'#YY_C3F5J],7(,U"O+N[^] +M)??6^$I"Z&+'HR)Z_X2'4QJA+F$"O>%T>LE;5@Y^P>9Y"'&6E[/!()Y--P*F +M-Q@+I&,K`SZWPG)>T]F*PQ)K;#CMJEL<3RUJE3[13C5>V+V#HGA$I&7OBS/X +MV7S_5TPV7:/!CXE*SO2CUUF[T.O8E'?=.'"\UH>%0R9R:7V6OK"-L&HJZRRE +M=`ME,9?*^S>,&1ZNY/^\$0``;^K$\(/HSJ$5'3J30*2\'D^1D\I(;B>M+CX! +M"7:;/Q)>[I/Z2J*\)J.J^P@3J.;;=DP2?>[0?\XK;><5%M[_#1<#J&2<6!8* +MGDZYZSD^@#9#K1`[-8.1U4P,[E,3`F5,G[D2EZ^0!`,+(ID1D'.D++42;%O= +M*#[CV6+U-I98E[*/!QE^-]-L'F?@GM>!,5CEB0;J(*JZG!X.4;N.QZL^8("6 +MI8'"`;+,9V<1VJA>>#90[[%PKM)UF4]ED\BTA(D`+B2`*&`FB;J:V:$=.!MT +M[B6B=CIAJ:;NR/@_[3)5&1^A*@)-$,0[UF)!VM`HI8LTD=FFO)Z:]3),P/+, +M^:38(^&UR$O+/^:T%`?1PF0WY[BRVSJ)HJCI[24LNQ[-4!TY]]1P)3097;H" +MQJ/;K%<.))<,9]V=TOH$8'4^"]=K'^J=$,@FUIEKO.J@_DB@ZDP(&#+_L5:I +M'JH@+;D'#W4@Z$PXFN[2%OU]!E>)OC(\_49]W*0H"58*1%O?F?;T4*@8XMZV +M,O[3+4YI'M#@%LR@=#Y\)K8T7?)Y* +M<\0G"=[*LWP!VXKK^TG]NA:YZCE[$L2)B/;:BO:1C,+<#KQ& +M*"-O8=CZ@A-&>WL_[2@GH-9&H"BRWCJGN]_ +MFL@7G&1AZ/21T;\W!U-.,>I8!*HI09Z*F*^F`+A90:WQ)RHP6FG-DJ4LL#"V +M33L1C1S&US!:%:+,+X,:%DRLX%]4^-12W#C(1`CC(NA!1>NH%T&O6G;PN@SI +MG8]R-2W6-VE.5)$;47)81F8,:?B]Z[AG*TF:5Z(1F5`JJ`-`V:J<68U&"L<1 +M6PWIJ%X(")L[SOK#(7K5H?H?O\^F0$$S)\GVS-A]T75:`V"(UU8VVM"3#+Y" +M;67EX'M2*>4_:L+GVF29E"U>.[QXHW6G*1\Z]!6Z`WOJAG]E/+[UK;SCPGX_ +M+6D0Y.?$J`[#C6`0/.;&IFM%INH>9=U@Z!W28?\LH^<VS9WVL8AS(]!='5*@F+W<'NN+K):,((]824A+V[C6*!486#)QO8);645& +M;Q6U]AX)?O4KUE:>QV5@M34,8_\;%LEWW[50HM=')."CO5,OX_3#1-3.M*"5 +MA)3S@NJ;/$46DF)P"'HGQC4KLPI;PE>@?F3;1=5*QAM=KY+IU`Y^8(/0+@!% +M%JKJ+G`[\L=3/)4S]Y4-5MF*;WQ61ZK0<.$@T+-^WUDP%UQ=H=[G]L0<3QN= +M%RJ;&>4656TS_9M0!,Z_,;;?U:N&PFMM=3(HT%4-N&8$V[[(;UZ(:LJZKY/B +M<(R^&9CX*D9,VK!0$R5S+8. +ME/$3K%+E4Y.SN&`6#$F'(HR3','\L(()UCM\!\'GEC=9!T\N9R^936U9P3`\ +M3JM9@);C4UR#GVR_\8L@_9"XA`49Y'&6GJ$]Z0^6#(QXDU7BO4S!3!]1'/)2 +M'7PZ5+F1U>:VXIR*T9N*<;"M=W%SA@>)^P]92Z/D#U*@6@R0(0\#M76Y_5-: +MJ'U3YW4BWA/Y3IL[$-[0%,EHO(;6;<2KQSR\HDQL;;QQW69+_++@=M\IS(\% +MO/FZ>5CG/:^AUSG0(Z9K!^MM.6]8)&.#(7J=2']%4D9LHX-\M358(EU5*"'5 +M:0.B3I[,$$CNX1&'1`QY#TMQ>H9!I2$IUX%A.B80AK-I46)Y&^!U@MFSM3%\ +M$(@/[%ZA7,XO,]+X[HHE\4^.H+H4WV;+RZ1W@+,KU0O#7/1^6<4C4B"AYP?V +M?..?:F[K^'GB.]*XA_C/N['_/Y$4MBNLL3HG"?X>USEK40[C6H:H]7GNC^A +MFD3LVZ-\S2YE[>$05`6P5>_$"]>@&-$00G/XE;&P#I;%EPLQA'&)3H;-3[,Y +M9KP?`[_;(V6Z[\9B*F1JJY0YE"=_[T\+$7'K17KBSTQV.W?VNXB<(M]R,+:' +MJ^7`86#&;);A0=),AF$9P"0`,D.!$S8O/B;.A*8^N3NJ>'-W*,&J,'_=;VPE +M_99WMC=1EIV%;.(&4LTR.H:-%K_2$5D]LN_!:KP1>#G_\R38"/X%0<>R%GL?HAB.6._(+9"#/ +MY48OA.F%0 +M20W%3>U#RX3C##@S.W` +MI;'L8B]4-34""Z[00-RJ;LY[B-#Q4K/<4799QVKF;(_5_7LJ%7ZE]#PE:>O( +M%H]>/YB/IE`*"VUAD%J;?JE_JZ@#_\&61N3HC(@A=,NVRJPH2VPW$6.L%OA3 +M@-N;7RD#:8Y_)')QC^-I[1VM8 +M#>_+!I_E-E!G_A(SBVOO;EE;J5SV@VD2ZSVV_@;L9S(#FP^*V+KF.*F?VJSS +M^`8.=ZZ1KD +MT?\R1E8Z?FM+<'E/R0W(NZOO)$!+O"8;&U0C9V^F8:;'RAZA3=FU%_6;GKRO"-6$S]V2=W)@S2Q@IS-2DS119@*7^3&G +M-956<0M8X\==1*3K/%^FMRA,*ZGHS/R]JD#CE,,F^T52H/WH"UW%*<2D^=:M +MY2>.:@"F]V^='YO0J!&E%+7!1WV1.[V9`!^S_B![HH*/PA>PN^S/W4PCMYQ, +MU&9]PXJHYV<&2X%C"%)!=>RS^MI0VLK@YDKEO.2X4]B_)?6.*Y-> +M%>[`:=Y1TJ<'];>M1X246%"M&X]F^%66%1E*GQ==E.C?-8YDVP--#P+NA`(C +M_?UK95!M)SCO?F.;+&W'+98-F+=GV$CM/! +M_$+^)Z6&Q1#TU1:Z:RUJ'_!>1/U&-W%D$V5F*OL/#<6A-1C'P[.4ZC`*ZC%H9XAIJ/JO[6E&J-(Y;.-'8]U"^-W7`NF00N +MD3\6S"\JF1+_H"5HWU6UM=LVFG!$D>WJ946P+1:O7#<#"ZX$4[?_U@P7[ECG +MO]TA;E@;+Z`]=W1[^*OP[WC30S;9V[(-,?2]T#D+"OG/%E6%N^RA=/;PH9VK +M=DWUXY.Z=TTL +MOX"\6H.ZNA]-00K1E:L)WUB=)0E_XI]E^]1#_^[)RN[;^@$=93)+'X4_+[**KMU0_=<-N#(T1$/"_?P)F0SOYX#4D9=9`L'!-R3Y_P +MKSP,W3E\BC5'2UQJ8"$[C\@!\Q'1Z*NZKJ0C,P1Q!V6HDAV@AF)-\Q8\[9O+ +M58-%PAN0\4P#MFI<&[-]\$DLFY;MV*VB$>E4/30W$X=0[>WKHHAJJZJ(B@`O +M\[7^@"9,F?>J;OO?F.[?++B%`1H&-^^6*6613+XFD7)NQ7S8Y!#T3=>Y6Z.GP)W+'#V(^X`O.M];_[KR)9HK5^>B? +MS&AXM#7!VM*`AXD@<",$`Z%4]Y9&?XN3@X\?K]C\@#`(YS\)4MU*7;D>&AJ_ +M<9)RA%-!3EX",C!0N1A?6'-"675V[XP@;"?(24W`<-T]")27^JB!4$9"SI$( +M*#'Q'Q5\E/HRP6=$E`Z$\?$4\)43BWP_`DU8.,B3=ENE1[6HKMJ-UK8NZJ-I +M]FX9G"T/TR^(I%4'T\!#.!H +M2F%6#8MM)IE<@!@W"/RZHA*:"1U&BR+PYAC"'UV#F5=@.FUZ7R,!QGJ3\=42 +MKL2WZ>2.L&-+$*TXE1@,HFPO90QFT3`9O*.?&W:^+G/J"5H%^)71&O23'"%Y +M(R6@&MX6V'JS6U_0WJ4L?KY\7DS=\8Q_0+NX@8F46]9(GPJ4_O.&XQZ)Q4WF +M_K>!SF&&X#=JRH3^O15C!;H1U#@L=OM"\9>L%*GS>_N#$P>\ZL`7A'+B/3]X +MRTQ]$UD2R@+VD:;A;OJHFA8@R69F#!*)W[JJWA@.VI432F'$68!WIQBHN-(: +M^A-7"2,1?"!TMIS)8SF'GP(27C&U]\2O]W?.=)J"M8.Z/7/2&SUB=56HI\'J?Z)4LHAKLOMB+UM([VW'XXN>]PBP81BN#X6G+/J$2O;\7"JX\#2L +M?2\0^JA3&DA_(["AQ3>HZ/:4'HVTOOR2E0L#D^ZVNE*TES@[#QJ8Q$"H][Z< +M)M!2G:1=>H-S-*=BM)KRMNK"`L9GN<;0M92=O&/V`\B9!W\-`5V<5"9,3E:G +M90W"G15C_"""/PSI!".+46+?K73_^DC157U14`S08)#"H?]R2$,OOD"6H*BS +MX:7J$SEKD8:/S56*?U1"O(A\'ZX*K39F6_.\;)G"E?$:94I%)R#K&*#'"]QW +M-]=*_^3RIJ!]>G]H=EA-&-?X6&A>-ZWJFV=';=$6U#>,)_M#A+7\>&20>+EF +M*KT@&\$LVW,6.Y(2CM(SL,#T@D#0SOA])EI]_IN=73H:$C$)2T_CWS(5GP=_<`WOR`COS3N,:1>UUG2@0*@)OG +MH1#0X[;MY@6S$YR%=P6O[<+:#'<.M-"$+%H3;DK2WL^:V67FSWBIG"X<2Q$) +M#+]XL0>!LWP?3]D'`8Y,OB@=G*P'8-'M.ZHY;!;"XZ8*<9=BM(.Q[[H*W-QZW+)<,N*?I]A/Q2 +MFCUH_68X#`8UPK(#I+A?C=7/A.=S,_D'U^],T,/`O!MNXIZ4,_.##8H@G@>$ +MB+@'2*S:JE#.`WAB3GIN>F*4;6)FN@)=']O/@S%!(\3"B%D"4]"^`"]E;^E" +M%RPCQL>6:C3E'X5*X(H[>203Y3H^C#TFN]H]JU+F"-M3-^0=]>Y@)I(E\I6( +M9P5O\NEL['IW.`A7X8FD.=IBLP]A-K)_,/$YZ=:#1]9<"T(+Z*1"(U:^6IP$ +M'$2U0Y*L.8HONV)\01#[ED"FFL/NS1^S_A;_Q9$\&D=(EH+'LC1_$ +M8DE//:2`T,C7NOM<9&QCMN%9L^W`UGE>3'TVSN3I<@(%=(],3")_/1_&Y?I&J[0YT%76*[4]RDHCP5,G7F;:)5N,\`>F +MO*FPB"WYH9>!DZR`V1L=)6J5?0G\JW"`NZ,4"%2#C;&VE;R^-"W?S!C#8_AP*M]6'P46R.GL<[D3>YQ^6#"V3N@/F[T>[G +MQJQW18Y*.,:K3BZGT;X'Q:O_:?-\]['\UB^$PWSM=#OYR0YWW//7]*)>6WL)PO9:II.@#>-+7(CN:\! +MB,)94T;`R#I1D7H=OXN;?Q437Q+A0(1">Q0K$R$[+4'O'AZHZT6)E[>VYU]V +MQ&2^"T=W/-"[=)*UAK^F&=/OXK:EQF<;RJ(HS'71FPN/K3)2;W#49-GDFRSG=1MX +M`"X!K\I)@=(]Y=(1`17JUU`$YA3ZOCN$VHN?D1X@TDU_4TP1(.WIM)JIB.9# +M=C#\>%^HJH"0>ME5!,7/HVUQECB/BP[%M92,+0`94F9)YT,O$L8,#M6QGLF# +MK!K27U@0'JUY[>S&@'8+'/@IP!X6)"T@!]%.9&U"NE3C(F\9,$+\%KW^L)U@,G!#=B6NGJ=WD:Y)-PD-@O5P?Y*[9.F!C +M4U2(!:*Q0]^W+BA-_U3[)`;_>Y2'AQJ)*`[2?+*W(/@Y.&7681F[\.Z,#9@? +M$8>(+0?B$`;-T;0;,-ZRFJ\#EWP4V40PO"9M(+/N)7QWA@;=<4B!");@SBS+ +MH@!L!"#*P`$1EZ.$?\5&)&Z':_<$N@[E`)8A`H] +MFL3H:.FPQU]^W&]#,%,D4$VA7$(RA#HQ^QHD5)1-*DC?4+W2]OCJ($';_PLF +M*?K>JJOX9T6EX#46%CZ9=/)P)Y5D[(M.I*_3@RRR7R=WUS*\9RXHGJDJK!`O +MYL>.G#A>*>Z@.W'S*H,C!`(J?!1SA-KCR[)6P=#A=OYJQ/QU05._+N(7)^QL +MT1EM+7,KQQ-L3FAA3'EIS*W7@,YW1BX/_*7^9%\,!:1$"5$L&V+&VDHRZN-5 +MNK=Y/6?J=\T-EP(:)^`BOS6QFU[D)M):%:2R!$-[\`+$N[.?S*3&0H:*"X4RR6L\'T,B3W%K0>\PJ7DCS8GQRQ\''B) +MO1\6QC]Z+6*>\=D-_I0/\9N&*DBFSNAE-V*,C-*!90?(IMJ+[8]-`R.=?3#M9U5H_\$I'KS +M)=\B14'1]E:Q/H+(!;!5GPZ0ME^5&JF>NQ'5(S,S-*&;[0SJ7C5JG<%6D>P`NJ>3W+@?' +M`NFQ-ZB=3TS7)^]^=JLT7-^S'9D?\=X?O*V)K$P5?$1B_"5Q&V.S8,8`#)7/XLH9!2WM>7`W;O6>;(PU[K"_5\A(#0) +M2HP:7!K/95KL^6'9'HI%#!PR;)`L`4?"A71ZV)=58R#)+)P/3<%8.$;KV<,\J$YZX>)K,&_#(] +M+,E@VR9%D?0>$!:TN7#B5U@_DB:Y()`QWTOW2?'W)&=*NL^LW@QG'PBEC>D= +MIV3,>OP5MEQ8N5=0R9[AQ:/PE*'PZ)^.V$*G07N56> +M*_L@W@_*R*$O!'M&1B1]C-R?YE@._*2/.4A]PD.`M)3AV2^1]ZK(XU7-[XTF +M\!90V64#/NO.CO1%U\]O2@Q(\>6YD3&^UX(+DE2!DT\V*I^BZ!`9H^0:5U67 +MK2"AU/G2Z*BM;Q;1-1I*E3_,**V#&>#LVD8*!#*%P@U--&"KK4F19?(D?^XB +MJ2$J!H_]U^G"Y*).%*=EZ+3!']'$:>`=>F2E;48\:MT&$8PG7F#[-@8*9"%9 +M]69#OGD6WR1"<*N=$Z\$/:Q(HFK0(0 +M^4_*N%ZNZ;;)"5YK&\I(#P456;!VA/CG@G%\(1SG"^D_8KG-*U\KYGHI5 +MV+KTL_/)1ZI03.MKM*:-0G1GL-K[*H"/')A+`YF<-XB*S!^CZSFE5L)KJDC1 +M5>CG![]8&Y_6M5S:1HY.2I4!S\))G33PF&B@1"%6@2-'"?MCB=\>-XN2EZLB +MB2..4AD]@]]JQ^RF75&;Z[Q'[F4*9Z +MF[]/_FM*>#[+^::OC'.-J*3HNGD@Y/#(/6TE[WQ'F+130Q,*3K.4#T8FJ-($ +ME==(F/WI@D17]^];4*86R)NL*Y0%+@.$AM4./?,40O&82'SO1.+GT1!*1LK# +M%)P0H/B5\T?*IP=5.&`9?1+$-&^ZAOH$%AI:.D^W4/5XEI:>;"5*2P$@>-0J +M%AR+?1XB$Z\`)W"CV#=^%X!W)O%IH.<8Y4QUK%BB.^7R!3$`(U7MS[\"-B##Z\W13!%1FI80*6O`+Y%0.W3KB$97).GV`S?>1I,]:\/,;+S+5 +M[O$RA$;QQL>O0#&Q337O'N\7']Z>N9(V)%.!I./\"_T9UR>N[B*DZ$\8++&Y +M'=IB0"!/JR(=;QL:T[CK*BN$M^P<>+>7Q@^F*7[MYPAI0M' +M@0V3`+O:;K.HNEQA0V;CE.%K3>6$ +MZ9>8IX\`23_B4V79MY[HE\>6I"TZ&ETBW3U]X\?=.#1[^E8E7_RWR[C+_]1A +M8EWNL704SNS3%7)`0E=[+1!7VPK/QEOYAT`H9'QP(G7`GO&^L)HB:/)L)K,;,DZ\@-9^F +M/+:A8"J#%NE974D?$/@#:=UXHE[JS0G\HW?\3[F@&`$]&OI$HD1S1Q^G;'XF_9K<7$ZZB/3)E'-\ +MT#;\#)'+C#;=02I4$.!V`HP:=E)Z9>XK[N'>2^_[DQY=+,D7%H$5/=4^$U:. +M?B(O\:?'2*1J'4V6#7:V*G4PRE`L/@DY2^>X+`297Q"S?7MKA>2.6-,9J +MWXJ;Q=9V9#I?4\FOJ45O;0>CTSX'`,C@)Q^3L1*X\OD\7]PUY +M^9<(%W\:-[B*((%6JO1>R[=9MCJ<><`F?%*E:CLGT):%M5&!G@"=LLYDO]_Z +M3P9$3R]@/XO_5SL8,#J/H_9KE$HKBH4[E,WK]CUCPQ-NDBV*%D>M6[=0K&=Y +M4+KRB"Y3N/@H+T"E=^XTFLG<82&)B*8P]7C=@@_2 +M'3=O)UK\24A6@381NKB:#V$3%.,IJ-1DHNTM3F#G3PYY!0!$8"PZ%'4FS*>? +M%QMV?=^"?!F#%;OK;JALH-/@L`(&Z[L_?2I.6FD!C.9/0L'9R6/G>"L-!_.I18$ZL!A:S"'C0]9/=I&Q;8* +M)2VA:T;XIM2%P,7KT'),'-P8[&)-KHROME_05ZKEHO)YNAYV]D?5Z$<[8;C1 +M823JMW9BJX.U1#1`QAF034N3&(_`*W.=^1'7U`.(QRPALCCS[5%P+^TN-Z6K +MA'A[H^@*@7![\W=J9P%0\1'0:GN[_J1PFEO]5XRW9]0],K7NYU%&M54.D'Q/ +MH;0OJ,;:[[ED*GD\KPBJB4=_4?"C2[JP-X+IZ_,N(7F?FKZ);6% +MR>2PLQY]@8;$G0_.7XC6'$/F"JE"*5I_GN!V$E:-]M\)M+(3RP#56%$C'&B2 +M]#2(:DUOTHK`K:=TS5/*X@576]%(K8,FR=<$`[8;=IR5^/G%$M)MC,4?N_)2 +MA&R7N'2I<:0LV1E;FVJHZ+P'N[A0;>F]JU[9@>4]6FRY&;(D)/,+B?*AX#;; +MZWQ&97N]VPZ^+MRRZ,FDH8^6^9WI-64X/;1B40J\.=,]`"-P$\ +M/2F*>R%YJ^BYY._.<9W>Q%QBT@OUCR)S(NK`!7PO%A-/B1:``/_J3*J+W,P9 +M',L/I8EV]71D?VK=#?"'Z"?A'J7,E8?:;%2!1'M+(VE)CO"$65Q6!AC +MD9=2VI]!%T2VQ7JW6%D&QAH/B]5N]S,=K0M?CBH8]!13HDKLP9Z2OU7\C0VO +M*+O._A,$"P2PRC$DTCUJNAS[0K?41;(7O>DD*%']*DNWJ)?$^3:S]@WA$+J;VO+UUKB0N_LO2"^2LE%3JQW?58??TP<< +M,V/R11DFXJ]F"Z>,UD;\*]8;<`8/!F\B'2'80!_FHGHZ#A/G`F'T))@O*24. +M^3\22,W'_!:('&SM57/'[>2]CJQK:U2_S$=-?=`Q_;=UJ5S,0YM8Y)_<]X"R +MN%JH@%?Z]R&H1UHOAHR""K)D$^:K=H_Q[BXI';A4XJ_GH5[`<+"6:T'?%\W=;1NR;@G$L_MRF;MYM_3#PS=-T/07.)I*F8F8Y5M^7 +M&T/`K5FZ^;\@5'IN[@P3^K3"M$G!2;[0C\P%ZBX:P=QP\7RH=Y!@(J;N:JN% +M?X2`WXT:?;ID[D`J5B<7`Y_7O+^([<"ZN='"_8Y,ZEBS\&K_6@'TB(C100CK +M=NP=.J(%H\>#L=?\!0V>-)UV<_+_$[U.`NT](0J4B/Y#`LM0]>OI*!'LXFP&^AGVR(E3$-;A(KLZYNEMWR:\7P +MS6;LX40NKE3X$N7KHD]UPEG%PUKE45&&N=$X)6F<%G+G&LM]- +M-L)##R%16HP0_%X#,;Z6$P98`M!-ZD][L$J+RE2?<0N47-_2L\,T,MK)=HKQ +M`,'CZ@\%9:\O3GK0`DR$U[&3*[H/\:!"1X,T&=I6']L123&U^;U!.3F_H&B6 +M'DO-G\RD6.8Q&':$"PDO-]IM?+0)P<_R8>N\H>Y`#\VGK0JWWG+A`<3Z<5=Q +M2=UH>2FZ,SZT'5$N'Q2[-N#L=45'`HH]PJ]4K8KYS\>Y#0?1/>IVQ=;=%3 +M3,118:SRB#Z4_XBOBYI4=OV$+Y9^_SSUG>>?^BRP(E958\Q-46ZD44G_7R^I +MWW!\?=4P`F7-M0#!W;NI?Z'XQ5%[Y@,!T"#@LA$U.G)#)CTL*W'-F(GH*<0_ +MF\_CKEJ;*0K:*?4N<]KCOO_IV3:K/)R&8AF#>Q2AA?9! +M;VD6XQ-.)I&T&BG7B!!K-&,VF.KRIKL'W;0BULD;W5P)`G0T=NLS7Y9"]7]: +M)*S6&J]"=6S%/7S%^#4NP>[+B)'1?[P!O2Y`\="1(C.<5G7'!,K[6P942ZIZ +M'7&TV`WM/6@2[M17COY-BM,UK(EQQ4I +M-A)*/9?8QYHE1(+W,[7VW$7?H=.!UU_UB#@T:!36J[6V\DU9AGXK!]A??8CR9WB- +M(U7[H39_?XU+,:;-!6%L#K52D!4K"D-=#B0C*8QF$G>C-966U#=O[?_:&VG\ +M3][4GJY,]3#JQA@[PW(B'Q'$WK'!J)F+TA2,FH>P,1&R-8X[4#8RH*7I352W7^N&#TG)D8L/E= +MV%&0WIS\WB9L_(EY(`X3?ZU+3'8\[G^B1>X-%#^!96:P3D\:,[!QH:Q*VRG` +M-6&`[%SM\?:Y5L+9>=D**2+<,];.X]8!T967Z(0>GX^DU]58#L`M+>G9208] +M26<1%]YP_4DCM&7Q-[X6)IT3-Q?%"(,I.RB:LJ:>*"8:D_2,7A&P"Q?*C.[- +M5/F&ZP-US==(YWDH]`"JV$7C?>HA3S_>N51QIR[*5,$+22+EQ@PW\ZW47PJZI"-[$ +MNH00T#S3`P>*K,.GS'K]_OM\OM?8==[O9"]N!AI(!F\Z.[@JJT1];])Z4142 +MY1J8]<& +M[L>8402L>RDKLPL?'O]<`+>S%I7_<(+?V>_V@:2MI/*;5SO"FO^I$Y/R$AX/ +M(EU8O'4#IX0X,]%6_.2-J(ZU0O1=)LPK`A,U69OU0>:F1]9=8]POY(>(93&^ +MPYFG#:OB.*$T^;"YD,1P0,TP:PF8"$6TRTV5!FYY8L;.36,>GNKUD8"!JJ2R +MQ^0+%56(L9K*WG:LV%BZB`IV*:V-@5F&99[X*Q_X"QNPV&@BY"\^"_( +MA?\+T:QTL-B<6\=9/)IO@B:16+TOQ2Q24'G= +MZK&)U,HAW0`O&>R>"8L=RO]0J,>UMW5]CY7A*E=R9%?].@&F84H`H>ZS;PWM +M+F2XTU"+&I;"9LI,+AD,`T`$UT3"L&,>$WG//A5OO@?O5A1-4$>>RMQV/H>2 +M/XI+Q^L/"BDZKW4^SO!G*2M*5E1?B-`'5>I%'I+$N_T>/H!>$#J;&!"4!&!8 +MT;DK,\)O3AQ)A]?:4ACJ@I?<@&FW"-0/2]#(!1(]%SC;#C[NB^1Z'M(YL%DP5 +M/N^M*`97\=_@;E`^_QNAS$):YZ_+L%F!VM4_R)+*HU`HUKO9CR +M8U@>.`M@:>W9J55/+9\/6+M:(_OBU,UOXPIFA@`'"C@VETCQI9QD-)*7H5I_ +MJWZ`N3UP^LNV&N%]P'JI\QUU`*QT*MI_XH#,]4`P9FG*$&MHL4$(-$V8CQA[%2&_V\+;-1Q*K(<\NZ5^J$/Y9<>A!5RE"A5;R]B7WH?R;9?\NL00YMZ-F;&5D+;*#8 +M8.F:9/]UQ0?XP3LE,,6UKX@CP&Y5=%;2MY;(MLA,J'U9U8C?W@@8,J#YE?)' +M:$N%,;/7ZG$<['\+B7H`>)!3%EVR1:[#>V(*H-Z'F]$QU?EJCU[&UC.TU +MH(>=M3HJJ1T7ME9>"@#^:(=ACF=^X1NN3!64C];V>*^EXCQ+G^*N*_F*-`(&5YUBJ'/0X+J^!N'.9E +MO(\L??]C9!5R;.QTI;0Y.;>/_]"(7_'J&+L1\``O\##4H`=F>4EQ7Z[%@?:V +M45OKPFH/ZYLT5?[;J>YG,KD4VR`>WO;5,L_44+4Z/.&*+QL+.W.'EUR^QL"` +M4O&"9Y^$O&8/E<0!J^BRM=2N_2R1W6%H_\&;\F82CGE<5)(CH>CE8JV2WB9; +M9L/<`PE=52QI%"S*@'@G,5>5*8N-7 +M6T5>8Y]3-)F='92(HY1ZT30+*%JD++:!U6J-DCP/NT)ZOPW[R!8TTV73*":@ +M>J4Z)P4!9::YY$:Y`5$?!7PF,+$K5B1^&M_E3R$*6,W/?.,=]!QTB9[8+D22 +MX;MI!^\X?I%FK968(QW9[&*SLFJ0\5_AWL3N[14.@U4JF.%5V&=UL62+9WH*_AJW(99N5%/Z?&X*F]_B]G/P;&W<_A_ +MG!`6XORDKX&[T^^6..6>WK_Y=?E0XM"55W1\8/+:DZNZ4*?+XT94C'@$\O8@ +M@=<4=]WUO4^$3*`,!RO64+PK!#"?5LW*'_-9=8FCY0OA*=`-KD#\MYD=W]M< +ML/\-`DB!^42H2NDENP +MZE]'Y_UMJ#/9]VW!+DZ9+65YF@Q/CMR*8OR0D@HZ&/G9HH?IZ>2,X@K[T4WU +MH;N@HV]#!):V3U!GRU76^O5@1ZX@+50,V/`()1.#IA]Q1!?@4/6HT=S,*I&)KK@@(+NIR +M1P;WTV8;!$)Z\K2NF6[\(?2?.T0--W(<3P19&/%2'T8V9ZY830>F1:LV%DN9 +MG2.H)D:9Y"3L#;*%%/W +M8+ZKNKE'NM@`$:8@?!++`..Y]]0@)*D/T0?M<'`/GEGUU%D"#_'XP2_#60#X +M@/%>I>]UHO<'G#8O2K3-44M:"J_9!JRV([YH,6M5'_E/Z::*\)&/GAP2\IWA +M@MA\BF+`<]VHX%:S-4YXNS4&:H3P +M$7>?F!%]&D\$VK949,Z!I@MCV^=2;0/47D@R]M.>`3C/>`(7'4CVZ;HEW(P? +M(:2R^S_U4[94P/2/`-_MX7\0QRV=U^<7L9'E"A/)Q53UO]D[@\&8FW5P6*&N +M5M`3\#KGKD'6&74)^GM7(3@$;4EGL]CR8"R`C.Z6HEI0%Q`D-AX8$A8O(YQ7 +M2@62X[WE!7I'%V_$W90P?>)!X?(.$6=<4H,AV!&M]F1'#]$*OEZ=\F,5+V+J +MAT(['H\HT]#3^5X)X/D.)3\L+G;DMGTR"D@>*49=-N%X%S3\&$9MD"IWZ<># +MF-`S0O+RK\V*:\3TP_Q/&Y5U1O8T**6Y%:U.YJ]:ZQTF[[=!'5TXY)VS2S!\ +M0+-B@^7``C6`X?;/')H5]T.^MVP8)`NR"JX.(VR]_ND+?I)':YX[^,ATV62] +M2.5]WK61Z^=?FS%,T5>B/[OR-Z15">1+0)NR8L7?VT.XATU8G'"\H==D6A +M0]:3RC*LE&&*SB%6OAOW3%>#NW-P*D']756-%Q1Q;-@1GT8+Y@T-C53KI:P_ +M\:;C2N^F'/VBZ+MN%K2903#U=-4H$?@HP`8_%#/CVG)U[WIM,'`"A;;.W84G +M665N9MSX7@6`WEIY:][=:\'VD[$R72?*A/Y>JDI9_+GDD.AJ?.('#U!'X`HL3[<>8Q6%#%\ +MJ01'9!M-W4`V&($1J"SV/^_QI)(/!J/KY6D +MW0.)VR(38SE7-GTTD2UI?\)AI!)MS"B!*M.YGGW?<&>9VPYRE:=M9?"Q1P8" +M`I8%I\W'CTK<7R6/=C:C6@2Q=I'-83^_,:[IP8-N1(;D_:'K'6H7Q'%[0%!5\G +M:,`!J"8/,ZZ=I[[36O'5G8U:WH2SN(_J;Q-CGM\I0KO@"2=>2JIHGBS( +M\NB_()9PC=O\U^D?VC07&\IO=*3.=![0#!.1=3D++-#^L67LO^9&G>4$J:&( +MVI8=%OZT;P%=DW,Z.!Z'H1_#/LFR9P872X(V?E#9#NW_]^?3+V7B)X/*`\.C +MA2[!E9$)&;?BO'.*2UX.I'08N&*>4H'I84ANB94JM\U*C-N&RT9@;Y+J.YH/ +MP]`EEI^+HD1&MO#?@SK*H--!FNLA+9JMQ"71``A!3PR2B?A/+?FY.[.8`0+0 +M!S;T"JLVL>A((!57)D]>#GJ%$>I8>?<+CUA4Z4&P:8(ZSTRB[^3*%'BFNG$VC +ME`S?5%JBWEUV^[8,!^;_5B&FR5HYNB?,S5H)\L8:HI7]_8N*TL5@^JOYA1]3 +M6Q*KJEZO,&! +MG.G"OQ/!LE06VO5'VH8RC[$I,I#QB$Y6;'M$1R?Z3,?4Y8F"9EP=<;MI*@VF +M'S%*_0YD5,VO;]ZVD<%!1]QWJIEEM*+X$!"OW$"VT_7I>.U&__[!G'IN_]:* +M4I/&$7-8I00?%*45@,C&'K%M%67@ZKY0VE6/T)O+`J46RB#])"YES-C=V]NV +M-J]<7FXQ;R>V9RO.UV,&G=NAL^)7-DXE=J)\3CJ3HV/#\QF2L\"-0MG9\9)7 +MK:KX(7MKEDIW.+M-L=','>MI`_#&5M5M2(I98"A`BBNG!BDC0B[E;!73QF*,:/.NS)\+>;X,AN[AOO@[;/45KG#K? +M:YYJN[7E=TA&"=@&7,K:B+!P.MD)*V?2:9N-Y_;5O&9\;E]IJ534*!9RKS>\ +M4I_6$83IU9^*RKF[MB+#A=UG)WOO^JJ>)G78D["Q4P)5^>'C2K^&V$X<@V*1 +M4;M"PZ.0P456T^B6Z$WY;R`,L[]&!$K8@AV"/9KSY7Z6?<;.SC4**E=C**`6 +M"01]\&(@5Y-](=#[B_O/H?G;TRP^5.`IK +M/:]T^1AG3WE,$+8R$:41_P^N2S725*33(3P);X_^/@N(FHLK)"G4BM]H?<$M]ZKS?XSU"GM(2P&(PF'*7H+-M7X45K\_K;, +MAWU5QKD,?E\4]-/&,4(V1K'@O&B$-IX@5GGSS71D,8M$+(;W[P-F]\Z3ES,* +MN\3E/3HTBZN<-6LSF5_4>)(SSOZRD5:Q((PR-J'/F8?.D+?.UE&>DA:-$\P6 +M2F15O7Q^*!]UM0,DN`IEJ8_$C8#J\Y8I]2IPRV[2N["&7&DG)ZH]Z9HI!,$G +M:&_NR?P2UG?21*4+W`,IW6]&6^[AE@.VD,>IC9XZM]S*YE'NQ_CW2;F/P"R6 +MBH8%R@O+HT:+_IK'6S(/+^1Z#M*"N8-5`;X(R,]MO;XY@*2:#PF4\@:>&9V4 +M:%+_3B'M-]FXEY_>W3_6=$5"K^73JR&)0S'G"<,1`I_.:!-D1TS@"KT2I3L;$$--SO.EX1 +M1%K[G6-,7I2-3WZ@$"_I>1QI&-[V^7)]7/SU2(W(IE2#)?,]/*MWPJ^YIK=2 +ME34<6:\KEXF'!)4'BB?7,"(U%V_RB0!IDIK:ITJZ[")93>>3N[FQE6BV)OI< +MLOJCQGG:D"5JXAM%$B"Z8L(D-UXY@S,<17Y$W]CTBDF=H/8IC39><(SN"^5* +MM<6,55!'E8.:*@JX%?@8\;1MWY'-<:2`\>=,KK%B]J84/TE+5N1BLYHPU<+3P*4B$"PL(2PX=TVK/_4\\BXP(@__U+[8_0\0H450@7J&4_65U=`?_'%';((P][. +M+UPJI"BCBS36(JY58"TA'EZ^0JO7YQY +M[`,*:+DXY[3JQI50M+&#)%>94EM2<@)@N4#/FB)%3?#HQ/I/_ZO`+A/[ +M8;R'"`$EQ)J&#?J23\/_G=C;L@D\F#2K'8W:(U&:MV\V.J_:K/.K; +M'M08(%`5:3&XB>3F=.%W8UPT&A2]';L.&-6%D_[18KYG\ +M8!-V3H*<9"/2(XK!,31D>)HC.<^?TYY8W8&[_-C-!>C$ +MZ6>?*'H]>'J'F!K!*M:JS6^TZ>?@*+RLW8;=6[R+R<4AS\O! +M'4XQ6^HGJ0R=ZYW>GU1"NWW.$C'18NS"3Q>Q!+B7UH>L6&"C4#@?G/=R,?)Q +M=\W4+3&-!8=_Y7_P`CGB\VM(*8K-UB69(#$B6M"IS774FQ)_]W)8;M +MC1KO\4`/*8\6`N&@_(8JO,70ED1S/-`9BP_2W]O!M57#,O!5ZD'VW'Y1U0J\ +MC>FE?_I*SZ`8'0?K=#;4UT;*:XP+_-L3YR%]JW:_J0013R4J +M#X?`(T6T"T+0BL@PVFQJ$WIG/ELU;>Y(_!0E6&.NWNJPD\=/%QI0JU>7=U*_ +M=^B-U[3Q(BHGXZK'[=AU35"3EG0Q7CC`FU:WM[N:6!$^^\[V[XJ>JH>B*'1C +M=(7-14,2/V[14*^XE18T(+/^D?'WT]2>+N.A\6@$6@33Z6X7+F&KG\/#>ZD5 +MY+,*.IQ4/"C[0.3JR4T/DP5X@>7X?_33;R)A(4[^X'.4VQ$/UJ%CF+@2!KM,Z5@/Y`R:+/`+ABO""J+K:>$IZ)"'*; +M)]CI1MFAT),#'B,XJAS_)>L$P_E'C=I%.[T59W]^4&^8_37JW$^WD]7$0V'3 +M7Q=0W>Y&"A&7 +M/1L16B?.\B3>4_-XLC#9EL[N?$O%Q/1X2J6*K1'@$""=5=6;1+F.V5_64K&B +M?PM4.?`]K@]6@\!/LL"*\=6!SV<*ER@D?Z]5/UN`S<&:%O3NJ]=IP_ZXFZ>3 +MSTT8""OXD>5>!EAK(3R+-K)I[0UMW+@C%CHY]'1X8@4\.V;H/XA+, +MF2I"GZ9?S@L5G%ID1[RL,L@Y90043P%\B2W+LX:ONB.FON.+_!SSO6++J'FY +ML%6UZ<#.T>PATYJ%/@#C,NL\N0K3: +M?]EP%5D!$HYE=3SHJX[P>QSQTC?9/OA=W.T;BZ9#NJA]80R\0C:<.""0+404 +M7&`-"N":7V'<_E51//I!`/]Y*U-+9PGK?A3_*_`B&=??OB;K-I-F#U%[?\S@ +MT)*B/:H\1_3ST2Y>_)HZ1,OG)JP<\U)^KE_KM[IMS1FEA'"%W"$Y0[6H/?!! +M*V\6KQ.Z$5Y,4G'@Y>)J]N[!:.,RM@1$"5`"M6%3Z,WXH5W^P!KNK@=#.`]I +M'?/[!,;@&JA39Y<+Q!M#-)*9$:Y1NKJ__43]JM&K]2O1BW4;/[S$OC8ZNW-Y +M77%`S\'OA_[&C8_>EMKB9K3-'";9/5=!4.,K3O<17B9RQ"2AF)EMK.(P.BHQ3K,1DK%T+ +M-()W^A]=`[!'UBZKMA;"$3-G(J:WQ!Y))<%?3RK.BZ#0\+Q[(#LE%.^)!\% +MMR^Q.2BNG!R4JZMN\JD"CXD\3,07R"*J/+RHQ;.:-BSXVU;U$3D$E@(4ZXZPT_. +MK\#1HOPSRPXBE'Y@]:2[-)X%MB2S'W&-N[!XS^\XBO.4S#@?MAW5]8%_" +MQVXLERN+7[AA.];<@4Q!6[2C_BT68AYY'?U-#_T7(K;5MM7K0OB#L0A!81VL +MVU0@G6FY4T'G?$.DZ4>JS!H:$>E:.;^!"K=`.TFV!K_O&@ZCN/SH56*#[9BR +MR(!QE!(ADR@;X[-OS?WE[D6-2+`_#.9:K(L?KW_;#:2S$,2;[\L_2>UY^IW, +MT3V<]7$4,_44+#%YFS]8K7H0+2+1=LSO4[VQPO,87`H,?$O28@7>`-E0\<)C +MOVUI*KH;.VRC0$=IK3OGBSY:"J[IN5L7G2+@<>-D_=JJU)GE!>M6V8M!>CUS +M<9P&>_`9"D%*N/5:_$BG@?+[1@R\(-V)`J=[6N7](X^B.Q-W/:U*AO=YG].( +MLCS.QSO876)T"UYID.E6)AW0S^E5E/.3G4O05*\*,5=7)\K1E8R&`+&"&E&KPXQ<,8P4(BW0&?`4>R=O@( +M8*_HYAA:"^&-1!XO4- +M8>?[%*I1.=)]E]=`X$3,R*GMDZGA)SSN^I9"3\C"20JFJ'][,R05CP6VCL0W +MO8/YYK!8*,PFJO5^)JO7*OC$$`PP1?:5X('+M!/DO1C5*(:W%P-070\ER+M+ +MUAY(FB/9CP)24]4R^ZG_FIRAU])1HJ1\H?&<$&,I\YGX>T;*9LK/J2`"@&-.#$4U9IW'KX?;/*?BK^?[]5/+,$8I-O"W&%=9>?-XD\ +MCET!/D=,6X/H:]-4WJEH.8A((P5FNZ)#G^SBT>ZJ"%I$B'67RU1`*14`5>.) +MG&F>\;]+>,K]@B'^]$XL3E%@D^#8H-O+#Y_G^DQ%*9*66=G&.FIP/V*J:E:2 +MBE1"FF9+<]B@=RJJF[^_AT]5-CG_O+W4LC/IE9;)*$9U\W:*Z)&0O9Y'=B!? +M`8I0/`J.\S21J'\[IO*.V+*6[ZV=\'MYY.N/'FBHW#6QKH<3H(QB@SW'3&P8;AHYFAJVO4S8I\A+_2$0%P),$O +M'?HYYVTXI1>R/WAT#*6Q;;WM,QF.5#KJQ)VW(D53/G?3F0W_^_`=]<(?"O[C +M&X#9+02_%-Y`KZ!+!:XA/`5Q,2QD\(-K^\KM[+>AU$P=#0(Y=I!W=K5B<^RU +MO/L'02TJ^?RYI4_`AOOI-YZZUSGT-D-J5"?[KASGB/VM,R8VJANQ1#DZ2B!% +MRT[YSW^AJ2`4&"=V$F"MRN>ACQDB9Q.0"*$G$9A^<4,.IV0RX'X56PW;G^PF +MXRG@8%K1BW,N%(`XUJSL$*ZE"!V8_+^"&#?]G#GB813NTX`C$M&^_O;43W&P +M!DF7L@2?S9;9/',QW'@&SF'=YIF))!S6K)^Q%8$7;W\<*.`S]AWCU3T-.F7A +M-:20!-4Y^)L&M2);LNIKW`]0M0PZ31HN5JZ9X4L5!V6*6'?V#N$SB;_I-*Q2#EV*LG8$VR:05[9R./ +ML:X0X(V8GHJT6CSF:\_!\1"'G!K>IN5RE*N+$!$-1DKSJ;J]'7M8$XKNL!OH +M%S.F%*:C'OSN3:V0.7GRO-K6HT2NTT/<"'&-U[-1Q_R +M+#0IJ=4+\R6K$C<@8Z,_F3A='!&FG+&BYB'?YB=30?*A=B9QTU<8+^+(69Y+ +MWK,%OR@*S=2?+YU3A]?QIR_5I6BN$A2N&%0PH%A.K*XQ5=S*I@XB<.*'XNJ/ +M-(B+0CB+)3%#6N*ZQ(S;L^\(E?Q=I-F4KFLQJ8J(/T*89+XJB=#>IM<5^-KC^?D2D^;[;72+_3(I5'BAE<.1IZWIVDFH_*8K*^A>N59E=!8VYTN]111_I` +M>$/ZV-@)J1@I7A12;GW7$`#6LD8_@]NUR!B-X\/P/=A3?>,P/0/Q0<0/HADR +MAK/>FE),#M"AY/.E/=(8:@I?9R$@1G8ZP6/:S6.#+2*$TUQ[#8_S``?&J".\. +M?A6#&F1HPYS+5G@ZC5VEKG18!!64(DHW/07C,`L^56^\9N=DPAS!< +MF%;*=B^]H&),F&BXK>>RE9,^,DB9FA*16I5Y1J,'E-TPP("7]X_N:J)STCK< +M.`:@,3D?4V)OB\TB_O8JA*FVWJ3SHBT?1H=F7L>)E6UB@$W(7KX#=?D/%,YN +M`&O/C,U21756-_&__60>(PO_KF<4-E'E>>O_G2E-3&4>#QV``$!P?V^X4L-6 +M<`-#T?O3XD\^&HZV'XI2K%B`"Q/8D<>BC0X_%J3616=NI9VB%BYY-R:Q0Q@J +ME`Z((3_^@$C1#]514!$0STC'Z,0WMKPE=\??QRY0C4^)RXT-4R">);JN?70H +MN8^U`_F._Y=<6*3EM)V,3A4)^6O9HL=PP);/++HR"%O^?(Y&@Z\-0-;>1?57 +M("C5UM;4]8C#B+]YHA>>Y]^_!"46#E:JIETQH,FK\1'Q_T*_$M^\\[SWH\YH +MS&A]H06_!9-$WZ-&2@?K5KD4S1I8^^6IBH"P]E2G-W?A.[LH6ZG44E]HVC*( +MAGVO(D3.063>].*##P:@Y3"9;;A\0=SH^E-A76W?(`RK#Z;.K_'MS.S)#@YJ +M6`?&.=5G]XVB5Q)]SGMUB`RV3C\=G9;+43O5H@.H8[3^:"URZ$R%+WGMIZ+O +MOE;9EZRTZJOEQO2H2-Y#-&A941MS.W-.F@Z`_6W/+>WZD`4B\).-ZB/OWU@I +MQ1`'EJ9\#(2BNXC9P&?42CTE/3@>0Y>U*SN]?E9:*?[&$*8K`(5[B([;G9K2 +MQ)VD=B4?O"9,D_^D,V([/1T()*GF]W5K_9YATI`6M3W%E +M77^;U-=;/HFYI&(D=NX3H:U\0348["LB1SE+*#`3:V8VJ<80>)8S3H!*R/BC +M!NUQ%$-H%5'9=V9KY% +M8#NJ6Z)N34%)3\.W\F1<1Z5CR-^'PSJOE3R:,7PAT98BZ*]E]0YWFCD,4C&N +MNJI7M,8/^^9O-&FN?\.G;U2":4D+5^H]@^3I1>;[2-06 +M(_(9R,`HY@V"7'5GFO1-HV0:O_)@.[SEH.L75%+J4Y":K5JWIE+&++(+J +MRKD?./Y'F/*JDVP.V6+,)W +M6B!%(FH\RP!XV8`J"EF2WA[X6PQ5GJ:`]::,U[T,IM`.8C&)/*0+*ZJ':X(N +MHY)9WY/U-6VSD\ZJR!](V;)K2@.^Z:C-8!AE$@F?Q\&<4E<.[C3D`&"9BX1Q +M%@L1K!YO92BT\5H`(!53!QS()'R"[LS?YK9/&PQ1H&Z\T[3-K5*B,V+GT?S, +M[E<+]O9*)V0"[(R19,+LLDKW+Z.M[7K;G^3GP7B-9Y#Q2(FW@'^97O4*"TZU +M;-U0G1FS]CT)47`B?O;-@J1:NOR&<>''0FCUR8&.:E>"68_B`$3*N((.S]@% +M#X:7K'([0"K1&U,E!_?FUMV5%\%V=O+:.34/@ +MAPQ`I:TG3YQ&#.M>MC&&JLD,^KM7?\6;O.[@#,(FB5@659@*X;=U(/ZH&2RG +M#)'/2;.9&E3^@GFN:\?.?TA7AG#%A]VK]KPZJ36KO\KT+.,I!58PW>*H$R;1 +MD$I'V.8_$S?(G-@64*\Q\HC),&OP^/.F>YSXU>&EZ4!J\Y]X^W0&-0->\7OX$A6+M\(0Q7'?#NEWY$P5TV"DE:=Q'0U`*8IWL$'E.!==:8N63,JFS1U`/X"&K38^:&*[BK_.A-_"$M"'7(=CT>TH +MK]%=I"8(2_*JR0;Z:_L7?9F:F.6!5=(V6V@!8Z'$AFK7I*%*N+R\OI&Z%IV_ +M2V9F>2H2J075S^_4`8Y0%C8@>G7+,_I">0&;K\LMTZ9,1JB@D?3">Z8Y$%5F +M6$EA/Z56-GY@CO+/`7R\KZ9AP$CZIGI=:+M-B\VNJ?^A8*1K.R<+QI^K5MOP +M#B@$29U\HDX(;G!L-*`*^JV@V(F?-,6,*L35_2ZKQA$)DRC!32PC:WLE=1H8 +MW>3<,J62$RV<%/=>\<96BZO$CIAT-.!8;RN>TDC5^]/I66=TK4W<-X`.E[V@. +M#L5GM_W^RYJ3$.MUI>PY0$27LN]=,@8*.C`'X#W'G=6X6R,&+#D43[.],""H +M&?]Y#?9MD#.6O1[##ZVYJ&07F0P9$MY"[/S*@V57VJOO7IPH.X(N:NK^")._ +M[)]B/`\)^PLRMS"(CC!35/J-V,R80C-$:,F3\/;^&Y-)#@.(O$C(C4E/[1'] +M;^^^55(;(]G$1KXSW+=9]/.`"3N':P@SQY/:@0$:/L=5NH8R=7V-4Y=3\^H) +MT"/$\8@9)8E_@:<2$4G]^J;+#7ZJD-V;.I/V`ZH/':\R(O6]JI][9=BJLLC# +M3T+733_(4BCC.U.@@5J#MBY@FHIGOPH1-SB\W5;G.NTK%R$2N5GK,F>7;O`% +M`C,&?%3RWL<@PE[Q+@&2SU(4I#^1@]-$Y'GXCA]!=E4X`,?FA_FBAN17]U'. +M(&L$-&F9VZDUT?RWE7KGDOV5;LSRK^KCF^24G'N)A)!-&(+46VI&EH$J'<$X +M!?;7LQ+*6F107[7I`!P4L3CD)62`?TVYTVO@UE;8T+8P$4"0V^&UHB'A;_"B +MQW]/)F-QYAFD0%#D@7K^N%$I3-3)N@K#B/K2IH+&9YRGC*D+,=>#W+R_Y*@: +M:#1>>=C84*J`/O]8W/`-ZE)#*3B-@%T:]WVG'IA.9+.E[T_>;G*+7K'[B)2895_\!Y6EXU0MJS$2)B18KJ*E4\!UR?#G\%D-&)*J->I0>=[_.K +MON@A$WL2:H8(S*=]AY+D$5#1:Y'J:<;E(";T/H'4*OG7C@`'0/V&W39A\)[, +MG7V07.,C\=HZ?3MQ(/+ZUJ(EMI#8DLKVEN64S5=VQ?+APM\E.4PQ-K@0O;3T +MG;?PQ0+9^G>K*6U<)F#\>#L!;ABF2R9TMXV!(L6_U0\UR@VKJW^5];NX.5UT +M`B:71%LM*I$SM:G:=7."J.;W@S7HXJ_3CUZM*A66MT.`-XNV3KGA26"J_&WO +M/DR1DN?_T0#:?0%47-T879!FB&:4N/]YD.8@>`PR4ASL/T8@+\.$<9QI6;H/ +M@!_O]%*^>OYU+<@<'3QYT02_;GXCP%BKX!C)CAF/2HC3N<1?1?\E3\:QIWOM +MVVHN%:BQ%0F#%FJO'N4Z&??DB,(>3RDSIY5J3CH%BX4G^;IQ?;Y'ZEX-+H1K +M2[8["6T\;0NV*+HM+`4:(`0UR(/L]Z,0LA(-A&E_^+=;_!.7P[]EI6KDGQZ3 +MC3[-R;MJA'*@Y^L,"VH]7466SOX_?#/C]A6F?1)NCFM5$<&>2%H&"ZLSJX1G +MP?'H<1BWM_KPQ-QM".QRO^('=I82I;Y,C_O(T,)T\=BCUT16N-=7C'GAP6J:G,S'.H=:/1X;,^4G3Y?UP"1K29>[([+H2B2I\RVR&DVLZM&,IQ$2 +M;?=,\7=^@8G3]'#8*4]!V<5R1.*UTBG]`R01Z)BWF)_MP`#1QF@>7SA^FQKS +MJ8NOB:2]N.#:0]./>U@HV:BP[$UP3,UTK +MT'5)VOF9P\[].+H&%P6R-T/RUZ-Q='0;$X_:]A69]@B,"V-EK?#)(1F.QK@D +MK]A7I)-59D-?ZC_YA\]")+-#^>;L;?`AGMAVRL4) +M\7_EYR*1P-7Q[`R^,[$KYQ3(<7&S&DW7>S\+H#`"+1(YR9AW(V6=&G;\-;38X:[^Y4:]W6 +M\=)W$IR&;V%D&Y5(QTX@*9%",.B:>^,:L0/FP]>YMB^N>[JP>Q4E+)Z>F3AHEO)&= +M<+]ZOF6=K=-_M&+"7B]`T,\*>M]0Q>FMDMEB>A7?#><@7V]M#Q:P?PML.4(T +MM\?&%_E6W.H8RB.FWV#B'M&FE]A*#GU:&Q2G=5^S3?R.3+H)O%E7^S;K- +MO!Y?3B)@BZ`IH'O5B+Q^1VEGDOW2Q=DX5:8V5\ +MU%:3_^C&^%C)72(E[C*$T@NM$=#6PIV`_A^=>)DZ;;>^>%6B69\)E#-I5@<.;KZ5'(%HY^.5\ +ME+:]"9!"Q*".CL!R`5S'_K;'`PT8BN_IJ,-%A?&]O->\\Y6-4YY76K +MAWHE%S%)O/"[BJ%RXUGW=`E[^(%LC>I)]X]GY2AYGOA-T5!O7BEH2CD$^J:8 +M4P7L;%E`CV.$33JLT/ATC+N::K5@21X+_SRQL?4"`T+3\=%(IA2="(5B';WJ +MX'^Y@6%IT7P=/W?D@`)_1_L#)1.8W`X12D`:6/M)GZ<5-=@A;%13'4^\>^** +MNR!:!Z(8Y>BD4QU&)H6A@37S;D;S-S(?O6X8Q`%<;,&^C%"!L4ZHE9X +M8N!&Z9L]?1L#L*R3'F;>2"'EU[UA9>'-'@L/^/[G#Y*2)6&E]V5Q#J>?M$P1 +M&EFFT]V(@O1]H5'9Y#TF*A>@>V3HA8Q=++FZM_J0$91YL!H#HV?LA8_4SZEZ +M'9)10IJF]8\U'`-BZ\8GU3XPTMK*0Z7CPJO>M2 +MN_94M\GR1KE_G`#[].4<7BJUVA-GG@CB]9NE;,Q/Z9PF<'35SEG7*^WL#(+: +M5SX)/P!LZ[4^R6NG,TT@"DAQ8N:GUC1B.(/T(T$Y[:T$(&8C_&=6W"[0U6M` +MJ2,A\F60!IOK_D4)8IBT\)1BOW +M]E'/_H[+*W1#V#!]8;SJN&4E"[EZ:;:[I6*S)#+_X0*8%._=W*U_-5YK(]7Y +MB'2"!J=87R84O(N(`QY@D,53-LFUL>939-@PW,I>+!D5+1[&F)')BD)N>1>7W[O8/F+/ZH!WENQS:=&Q%3OV" +MQXH>Q9L02SLN:,KR",RHO3YI!@8B29/XF\)CBKG'36FA7++ +M6>J%<"\"2;%XP>W$5\7/Y::M@H]--O=@:]+0>X"TX`E0DMPLJ!#]B%CRS +MXV%-[XIUAU$CJ3K7DK.()2,@DHFZ_?`]^!V>.+A5R%*BU28W[+7&/P)#ULGC +MJZ*J@,''N-$T6WI7C&8"/^3@UE#X\M^X+]LVYS/J72$^UA)?_N*NI;7/@\+0 +M;-V%=$R:JV_ +MSR0R@DZKAJ'^7SR+C='']T#+`O0B=7!SZ,]/6O` +MLCL$=("2F@)871OSZ]#.LFX<^E!TP4H=_#2TL?VC2-EG:5A06Z\8M7_&$0\< +MVN&\O,@[+N$3#D7K]B&^$R.Q>3-4!GSDDQ_SV.@5L+.M3,,9D<=L<''29(4T +MXB<-B@B;@!(F@I=QM'943[F'R@<9/0-`\BP+2+M%J;X5D@9-4&KW_N^RHFNO +MTVC?*CL6C.4,-J<\O9Q>7T2#U8&%P;BLVE_M,78H$YN]7BMJ1.= +M1'0>-LFM_9#6_H5>BPOC,06@5':/8)U2E-@3+'[`$&F24Y3C7M):5FYN/"TG]#Q3T#UH>!_.$I:!#_7:A>6 +MP2XI$>#0LW48DS#(&6KK`!'08E.W9H^ON[+WT"Q;P +MIK$T"$:??_(]#MH*AR7Q@2(;H!M15@"DJ\,J5['K=N\`;LDZ;8,.2"H_9EZ3 +M+Q>4P]$&&8>1':4SXV?VIQEWQCG<>UF$V +M7IK.SWKWKWK+.`5#L`WZJ#$1&8*BQR*E88E\519B7IWW?_'\%2]BA;(FD;%" +MT@%86S4C*9DR\X><+X?;9G>!04K./F17[C@6GZML>ZVB`M'5L2L"CS[;ZA-W +M&T-E:\7FY;2T[,S)-KY-:L,]@Z2KBKCRPSR^Q]M@G(L4<%@2^M18`?=P`!6& +M/XU8'V1\FB5WZQ/Z&?EZO8IWP;[FC*NN+)'I:>S:Y-.!>I7?[W?3WVDD"8>S +M:T#\G"-P?%6VO#U&*P@0[&N&JZF78KR.T/FV2#;^<0A0[$$S80AI;6]F5^4D +M;0K8AY_Q9++U=6_2K.(EJ9+E$+5,=Z/IW$^]!FP`.(;'89VK;B.&ZD +M=R2=F)?/$K`HPP<>=,WY?/326G3ZF+@1/OXZE]B[TZ6M_$V191C$S/Y9YF&^ +M:DP90G;S"8!:2X@[K!"HDMH"R6ED_Y&B4(5(2FXH4);66+-`*M+?\T(,D_PW +M('@M1X^?6'=JU"'TA;*8ZQ6/-8-+'M#BK%&KN0L.=)['!I-(EF.R_QY1&?]_ +MI.OJNPB#U^'T7J+^,&.F#=T:V>"9]PD%4?0YW;3+A2P$L%_KATM"^MTH?%"; +MV(D&G>21W0IOLI'L?(`AI71K9KU +M'M,-ZY-XJ!YB_'4;$14#@CNRH*R-N=P^TC[`4VRIL_\]""P(FLBWI;X-XZ(A +M'GCA+Z^/T`U1/8M`\9(!CS5K,9='\;H!LA-CMJFI'`KKJI_P#]Q&Z;7=E0S: +MH8FU(K!,&(IYOO$5R\KU&2K[*G>C@(@C6=9_J7PYK57[C+X/\EIK9(D#_::*Z)S`< +M3R'\NI*1G$PC5A0U_(F@SJW382W'"N2S&*#;_V/_HNR#2+@^LU$4\H6YR3NK +M0)Y,.\P:!D]3A,J'EIZZ0H` +M1/?)=2M]P7^ZC,)HOR#XU;QB%H53M[M^+Y;X2&*)W?*D(?4R2]21M(RLK2G2 +M=(_FNJ8Q_)>E#CAITCAL/+[1B'0@D`V^+A#O"3DO +M;_951YY$N07:7,&JBO*WE,QDI<21X!Y!D(3H`=IFG)Q#!$ELBJQ)C`C![I]# +M=GN.3"9<;T]\EA>:)AV8=2Z/UEAXH^7KV4+/FW%CM'1C&`%P9@QM.MV3Z,1* +MN)G\-CO7X=?DJ,LIN;7HR+A8'<)*E:5@^E^FI.G63!)^#4HS9\_\4S_0C3U@ +M4Q$![(*VUC"@;C!UF3AKHYR2C$_>"ED-';90$`\\`Y1!H(X(JK172-+)WOD< +M^IDP-F+Z1>\!ZD9$RCR':GR`/0Q:J=V<`"L)\R;/1%G4@F(&L[;#>.O76PU2 +M65;J%-B/"C1']AU]5DX"^C=V4.J-D?F'X=ZQW\-0Y-*>'HH^$$G +M6WO1;!]F4:3"[HPV@GGJ`^:XV<\*ATSWC5/.B4S!D?0)8&8]*+?A^N@CN$`^ +MYFXTFKGW3(XR.!-QX_@9%3#^V[L6YD;FG[?YPJ-B]Q<\Z+]Z_^==D9.U6O0T +MW#;C-LL4#(&LV@GJ0=$&E]'JCQ5X61A2CJ7PK>TL+`75^`>@^,P:W?DV+Q-/ +M>.H8=&6/Y^S*UM'P#CU90J9BXEW6?U*J^KZ-#2?>8B4[YV:V!W40!^'!C;^Q^R0K_M;:PU']T_L^ +M$JIP+X+K8]3]ENC`XIVY%FSBW0&?/+C)LDXJ*(FI2B8SX(9NG6*]SB45F*0N +MR?%'%ET4Q)1O>P+9SVQ#IT%]C27.@S8#JX3NNTFJY/4)3X_WI\Q-<,ZED@X5 +MT8JDBXG$N)@M)T>8-(R^FGN?.F>M<:L=0L(A)RS%C+7'/+K(`:9D/?EWMB#B +M$+/Y69=#YU1I*:HV:MM5=B`/(!`C+=#-*'?=7KC//X^&T\@\+]<_\6[FO37B +MLEW&.@]<"JBT>WT!G8,'"W@*7=)==D!"GG+,?O?5U>/)EDW_S8@R9XNS^$_; +M.KL=IG!T$$")[1RN-7!I!?Q>CEU-2Z[]EK(F]&+"8FQ@6*::9(9QA+::X41U +M*H.JRY=26O0TG3Z\UBW#;L>$[CNG\5.=(24X1'#6PXKR$Z!\D;8&M*#*RA2Y +MB%/H+$"6V4$8BFW=6J4#`%Z[G/O]KL!)9>-@9Q_/S^]X0%;V +M[,.QT+0+SQZUTOM**N'G,]:PH(E$[%*#-]*';;L +M87[$(QD8LZ]4_\Y+XQ\?Q+;6!P/!TNEM2X_=%S@Z>RP>#UW7[1--W:_U*,G7 +M$7"Y_R"A;?@VI^(XD6WOM&W!<;,:8!@5I=BH6[N^Z$,=Y-A#,CJ*10[!VVTJ +MM]D$#LA=$C39TX;&<:*R&WU-].:M&37]WS8._'\\6^PH)^)F%'`.PXNRWR.8 +MT_G]N'E7$OE:I!;*UU]5*P8;9N%W0L8NYVJ;],$86=7!#25E%Y66[/)"8/D> +MLRJ_7:$;\$CBQM:I(=%6J3RNC74YM +M@8YD0%VM^)I\2K])O,PK#D/U$<9[*Q^1$/YU2/6J(C-I[X+Z)S#-3[CR>!@P*[;;W\0I:.^)T(!D%_941;O[P:1FBMY +M=2IF48ENW1;>>$$V6?H3,$YOC'8=$WGN&+R,"A19A0^2H%P`L3$U0-/L1OY@ +MZ)DI26/UG;TZ9N6LWX56U!8@2HQ9Q5'@?K'=S9!E]D4>U1U.]C#";A7MIG?% +M55=SMGH^/R(W!8W/Q,@S1=>L0'*KI.K(>\!(:-DOP;6OB_C.[H*OZ^_&'`I8 +M)]F]/J(BH)R:S7A/(N`0D70$+%!N,,_F$)L,!'_"L=\+B`65/ +M)XK:C2^K;8XL8LW0NN,RZKA6;/3DAE30LTD8(TF7[M"=_<%R'#A!S/N,'\D` +MO=?)3+/,E"AXU=C[[)G+[.WO/I\IP0.MXE1;ST?1W`:EE31]+H44/47Z=1R+ +MB8?^9KH2'3">5QSKCCK,M32HN^8Q_TA;&+:8]'M#%U=[J`)C0R`>G^62-!74 +M@@7/0S!X#$\P]#F,$ZJ\%(:^^#[^#3%J?U/#XB\2Z:H-SC@+0:G]Z_%"*\[L +MM9!)4FU#>:0\)]YU=P>.>TP3[`$=(H$_#K;JQK'@4&KNZ_ +M%92W:QS5Z<(<3D26;L0Z#6ST?68U=5<"<#L@S5F(0=IH0LU2%%;,-7H5(H': +M*>]3F):F:&CIU_F\0A<)QE +M0\@.((%HU0X+#-;])\`@21!F=DO(5I!,.<)ANQ->C,0N813+611T@.Z:@N9' +MCXTU3PB@"S`0;HU@@3">!7P8F)U+B\:#$U6MPYKUB51T"_#FN:QA)X58AS:_ +MAN(#Z(DBQPHH\(#V(*7T^P3"XQ@N5)6@OPSS,&MT,;ZT1A3K)0@(2K1[;SVM +M"NTMRR@[1;#`D!)M.UQ?!G1":\C7_"]E+QJ.1XP>S+!D]LJ3:/X<]4N$& +M0A_$$!/$A6;/50R>:"E^CRH8TD)PO5<&)*5]#*N^FRP1'93P/LN-<20"8EDJ)B1O6& +M"DH*D&@?T%W-N?366"KN%P&8MHA>IU>+A=HI:TNYMGH#QEQS/@]I2PT8D7JL +MY.Q1@,^SRL\:Q0?LF[66/B`=\<=53$:@R0,CHLDZ/";T*_="1;O.AM2;,([A +M'^R/UXQR.YY\RN>4N*"J_ZS,OU;_IF22H4J.+C6S#9[F&,SS:ASQ75>H?1LG,9F$!*-FW_6UJ5)-S);P(>,TX,J72_Q.?R$>TKE)E^%V87_)J +M72%R'O4_F5FR1Z[#-&C$8T#])L.5PM5JE!?AJ?YQEG#3 +MIJ+`,[&?7.SO@W$)[UPC/F$4W+*8;&UX+?+WXM4=/ZYOI^K_BNX7+<\A=SD: +MYMEU9.K,0]=99$WU-01^\%S*Z3#+.$DO2$7LK(E]KXDQSJ7H-9VJ#I6M"&40G7Y5= +MFZ`0-43%'2Q\IZO!15M>D;GX)@SBC&&5A/LI'V&JNL1*N/T^T=*>GX"EE,O/%%<`Y+8K->5G.+_`#2JL*D?L3 +M90*C%>PT*R1Y<]M;V3^AV,K4:\"`Q%D;)WV>U +MR0RSNLL3EI<.W%F2/N\@[FYE47L)%!N?6)["D3"\B72Y]XAB@T_0X7RH5\1 +MB`(WAGI\92&B7^":,FH:F3DQNX@;*H,?PP`[V=PC+Z@S.YYM8YBF(@76D4,/?YO[BJ6_L#@V:!,4C"`4=[B\/]\N-*@/C0+ZXK"^D-[" +MBR[C2,3SB\D> +MM]TU,'=!/#QIE]B6:'XK&N7R6!ZQ88$NX,-55]-%F;6&'O(#YW,; +M9,US8),<9_1P4/QCK]J+$VU^C0OMR:5`[F(J$<)_PK3S]@UH54EF47ZQJ?KTK3'T0NZ3KW!BINEKX&\B7YI>]PJ];B4?B +M)V*:%VP$+W++"#DN6`QK03X&-M)\26^!5;<=+/P)!.&-YXYM5U/8LN'ZM=P"?7YG6,H)C>-3K)"0,&*#F=:OT=`/2+; +MOE7.B1^]MBS**#:(;Y.NQ3]#KP]E5Y)2$#)D8BVDYZ+_Y/WY2A&DK7;>W/[! +M/1HTRY74=`7-0&`Y3C"T81#H'3<*$]$Z-W-#O"#_8OP%G@Q=PS(@0[664XP` +M;R0Z,DE0P-TH&](NC#'X%%%UFJV;D#6YSQJLT*=,JLD]*LXO3L_W!\/U_CJ` +M#0U"M#]_U8,4"($P`4*]J\EF==<@&"T9P=DF&!.NPE10\E#T@J9G.B'PB>49 +MSNV&`SHRWZ?K?3GAC<5/%'M##XO@^%]08@<4>&@=_0Z#Z-EBUZ9PU;OFK$RQ^.8#*U\ZM'([BP2&4.K)0@\HI_@UDZ +M!*[<9NN(;WR2@8A&A5)5Q>/PR9(8IT%SUQ(:X)J3G(!JU,*&Z,[U,E77URWN +MT0VDV)$N+?M?_"926J$]*@I$GD7V1DA>*!B5*IN^])I7)/:L2,FI*_,L+]Y;O+G-N5W,&M@% +MR[;CX7NWD\7_T"ISRKDO)Q9O13R#QPO.%(`4MAE2F-I;GU^WV%B$_ +M'KTID.]%^SY<\GT*!TPG8\I8(&][H;OS&GA%&"&GY'5#0V)54-Z1BA^:ILP\N=73=)')Y?WJTY]:RVD2SLA1MYO0E0E^XOT6BM< +MB.(SH7:S1PP`DS!T7;<2I("M6.`/O>^R_9^N>0!Q'SYB/[;"=.3HGB?$8(C5WD?HK@./]!GKKC%.UI8`J<]65/V?%C0/-$FTK*;>Z*#4,Y1`E(YI21!(.:.6NK1CA +M.OA[8X"C\OHGZ[]$<-"8EQO4`NR(FE\<:WED5SA*71+YK!9'S&7-M!$R*V[EPI2N;PREG(_L@V@$AM(-6)=%1C3D4!9"J';J[! +MQNM0NM+\O]47(`!RZ_LK\UR^!QJ_C>@@(TSEY@3A\J'OP6\)QZTW7R'_N^[) +M?+!K[?[4N@8@S?#?Y-%D9_X>3SKMS.F9?3@",,-\XO6YX>`"!P1)&@\M[O-! +M0D=JO89-UAG[FG_:WVR:0&J#4NZ8D;T2_;P5N!P?G-):XR6\>1K&K_GRA`P> +M]"*4+_!/=,=6J2@.5QMULPJW[#:J2+HWD346V;4T]UYJ*+&ANPENE><.9_Q^ +M)8B"E23K\)';ELK&0P>ZX*1FA&W_RHO(;T`*&L8TQ^'@>T=5?X03B#%N-"ED +M3;NJMYEAO5NF?V3S:2,F@2>JOR+^`0VPW>.A!S6@W]FSZ.+3(L"P8;T,&E/Y +MA%#)A2VX[<-N97XW`C?)U)]@KY[K5XF'@G%KZ#AN*")?U8H"9R2&DN]X:29+ +M@PZ.CDR;@725>='_ERY_%'E67Q+A^XI1#]H`;LS2V6FU8?T+4`;`3D>%H"R` +MN+;&C<:([RYBO;?<#H*ACZ1+IMR,&S1]9!3 +M'.=?WD`^K7/\EH^Q'\Z9M7)E\BAM<5#4,;-N#GT= +M+2\^GC1;EY5*4%D"FC8$_C\C!?@?.STH^U2!WSLKS'!ZS\N9HFM%>+BVMEPZ +MVB%*MAWDT.=OA:``!ARH`RN>G3*X$PWQ7@,6\;[<\U/6KCLW/_\-RR!VV>`8 +MU8GS&(R=EFDUL%AD(YDNVCQ[O:7\<%R&F4:IL@9:E;B/E*PM8:S"\&:T]$([[!'3@PZCR"5:I80X[_H +MQ:Y9+'1D0"<+GF>H%YWQW6SNL8O&=;4Y,B%%9GY1I?V'[HHM+-()K$ +MI9:LC1'QYKO".2+Z:*JVI5>J9"5)5>>CN16\C3*NK"#I7TFE.5<;3Q[9&F`9 +MQ2]A@@($AVPK&'<6&0V-[67_F`(-V?043T(..%2ZMHE[KU0.A7R=!\5%JV!KF\8X)X +M5"F7:--Y`AAS?8`X['WSV2;)/[Z%%D'*M(1&!'IOCC7G=6'MU>89X6.'8BA^R>J! +M%J2WOXXLMQZ0"'_\H^_"AP'/3Q +M"-8/_QW^ZNH3A2;"-62\/]`GRF<6U"=TN;V@-4AHTO9A8!B-\?JP8>+TH<*M +M"H`#IX)/JYFH'ITVX"&/,`>;2S*SB`US$3)@\"?8$ZA;;.+1DJ/+$N$[KH'= +M#&``4%P/GN@TP?"3&9LTHIDHM_4Y##2B%]6DZZ>VQ#!'.55S_,?.1GJPO1`F +M]$8,BR<%I\52):*/XE"9O*;$0[2H@\F9$ZK9H`QAE^\&@=74-1F!Y_WLRE+G)EP;E37&/(F&V*H,W+@V#09V +MHDUA#N'ZLJ'1WP[RZ'%8!?N^M80@5\@-,$H/R%ZNRBI[Y:(&YR5@#MM4+E_N +MDCJ*PTR4!?$RZ<<^YJ(J0NX#"T[^\1>1&#,)R00^]2"I?[LA\B$?L(&S_1B4'X$AQI)R +M6:":(#7X#9WG=/>?Q=NC(;P$V]9.Q9 +M3J@*7N":.6Y^%IG?E1QNE!ZL="6L$/W'L]\JC5_KB/ +MJY>3="5=-E+3S,7-\^42\8M29@E@!AGN(3DF11G?SO):<6M"/-1Z.AZY/M%Y +M1);D$-[;!\"/WWE/7;@$5D=#7:(&QR05VC*K +MZON00V_4*B"LG?6;N-Y+L<=`ZF_Z-"+B?9YF]7(QPM*1?IT"=:@!YLI'^V)^ +M`12]-K-`CD[",Y0(JH38E4WKP2VU3GY`///+]L`^/Y"L.8J%ZPKA!F7Q"->Y +M/18&ETAO(+'Z=.+L0Q@YEOMM`;'^9,=@;8=!*MMKF`;7Q&;1L38"],?<4KB< +M/G!GX4L/`U4,3Z=&^K\BR=7ASSI--1&5 +M\:IW-JPJ>'U&X1EM8=Y&-MG)>>U/HJ'I1@0!U4_\+4)1*H'/)%@S6O)2YE<&O7)(>B8Z4'WZJ'W):J4<*XQ"D(YA&05T><0!F +MPD)G,R2/`'Z6)@\?P4'N"I'")NNW.TNXHW,3W7_O99*QT?J1S7AH +M,"DI5UZ5W=?,VRFNOX$Z]ZW;9+>")[^PDS6O!*Z6"8I]`0W'ND`\V8N;_JK$ +M,*7(*K(3&R*/J-(FOS*?X_N870=$Z!J/3V#?/5`)8<^`JN(7.GH?RAE +M1)5E<;A#A5=A71=ZY0+RH7#A_9KW'^I((K +M8%].R18;.B,2@7'`2`@PPL=,U<-?(5F;.1:319LR_I`>=:#&,XV!%!!GU>J" +M4+T'IC/"BA@B@DD=U^X.$A/4:G="9T/VCF)W8YBQTR\K[#ZTAMK`6&*A6?*@ +M_G:$=0@Y*]&3XG&7@OI\YA@"XIZ1'E\,APBX0&1!QM'R*WXMW)=:RQ]XZ.'46#QM/L%JU7/Z8$L\/:#L1.N< +MS!P\%B2M[Y=D=R,N;9N#$$?JDT1RH$S!62MY*R88H'!P033W'DRK&H;;"S^? +MG`1&LV2Z#/FKN["((+[IH<*49''?>[C-$B1U)Z@BH;IA-?;$*1-8AU$"T20; +MR*U#[IO7/45MF[H)HN0'6WZ*U,4KXE"0\ZXO?'SX@ +MD6Z3"W*UH8AS%RVOL8>[UKCIO=0T39;XCA9/^1/Q30X! +M6PL=WVP?U9S<\2);0^-PWJ995I6>JJC0UU*!4G:-C#^#87.]0LD*59C$Y1G$ +MU=:RYD#K>IYMS**9_E]WDM+A*-5^=!#F+2Z(V%I#^T*"S=>%X"?$>.#+?+3C!I&ADEF1Z(CQ=\PY3SY>]NA/-B\/(3S$6J3:73MIG2"H*K] +M9LG1A1D"!)(?M`BI_`_P6;ZU0HS:GW^;=H?>[?]*+!V8A'#KP0MJ8.%KAUK* +MQZ%A/`BX;7>1&N5F`;0\DB0YOY+VFWY]LSX-M'C]KIV3GD.8262A.I*&5L,Z +M&+[,VWT\Y\M-,\XF!:<1+XUA9'"Q]BM/[EU?'\#;9SYP7<)$!!)2HMRU\*1A +M%YH<5+Q;X&`(;>EE(^AT?80WK(/X2;@$/$,:/C:VK*HW2UV&6RC4$8T0XZ1/ +M]K=]B9?^QTAC/8M3CZOER_,@O*F7"*TJC(&*5P?D";@$:_>[F,7P.R8FHO_K +MD,A)(/;OIXI^\*)QM,&MU9Y'=5!1`B6?HA]`4LB&?5 +M5%K($+Y067YQ-/3;@IS!^W\$UFBLY)+_H$G?`.0:'HPY:@-UP8^1$\LHH'/O +M5%Z\YA$H'6%C6DVW=HDBD:!7ED>CJ\*^E7<+OVU#)7>K<#[.2-#X="%YGCU*?,73^T@]GQI\"=Q@*C4>9J1VGG +M!="5QL>,@V^$%^G&>_XZ2LU^;!LHCOB$1MS[V8!6)8"-MDHSDANWJ122 +M$PCVKO-/H36'R=_=\`(>8:Z!/I[CY3E4I]JC7+DT%WWB:M45?`VS0\"0_;*V +M`4@B@^*?&"D%`-PI#[E.FZ=L/G@=P-?/,TQU6DPB;2I]D-^/,X!'TH:*PKM+ +M`QP>'O'^X?2K=@?U%Q%+,^UU?CT+00+.2O]M'EJ\!^$&D7-(8B.3_WWO.^#+ +M_-ERH78ZUTIQ1ABN@E#*,$7.S^DO9K0VOE1:F9W$0H$]12XU7I';LRUAK*A0 +M)^#&!=HQ)OO[/2,AM2@+3(;/^XG;"VJ>^AD\A;3\*L*I8?G`G[N2VN!C#U1! +M)`H;D09-Y,X?2C*T!$4GT7EB@8(@08K3S91Z;\]A2K@P&[PZM#DD#$86\2WB +M(Q&>'IDCW%%&'6>GY\[RJC@1Z8QEB!'A3)+N;._EP7+Y/2(7-;(,Z&Z_0GW` +M]VCA2LT""S>>A(N"&T6"\)H7*')=Y-^;G/![I0Z5]M#RX2BDSQ/OH?T@]S3/ +M0#Z88?VR0\3P=`FM0/BG]"!L`#/A=0E0MD5R?S5-VYEJ+[+T]-].3Z*>-#QN +M4N2_V!<,#W!EE1(D0+I.QU*3$Z6"L/,\V[LM6*S(6N:A)!@YD6!#%\4BB\\N*Y0N*F9DZ=DC-##BQ\SCQ\VS1W4"3RP +M13F`KPK7U:;:.1S/47/YC4U'2CV_=:]J'6,`15_PY6]$X"VRG#_?:_^^PV?P +MDN<7!L,0YY3H+*+BVT:!R:(_D5)K=]UW,@)D/,"FO=E;3;V>IZD@/:%I:S%H +M/J5Z\S1JWW=@P?OACH.YOV%ED2VYR-=>.GHFE6`X,_"WS"HU.4:J`HP.,N?* +M6#IR,7HI<\I#>3G.E+#[V&&/+IY4.4S>TPLT#IHM>1F",PAO%07HX6IRW+/7 +M&6$@Z'L.1Y`E?12IB4M86V3#$^^BW'O$4"DI?7^K%:LYRI][ +MERNJ$AGWT\>7*-ZI?.E5U97D!+0/I%KW/&5N\5`OSPCLF-Y&7`,DC^9"8[TK +M1Q":$2WRD34.7-&8[$N+RS'R]&NPNB`%"7D!RH?6PZ^_!Q]VC&[Y!%H3FRQT +M9>!NJ@0`)DROS%%=R5I7*'%P[Z)PY\%>B60X)"&#/KP&E]TTA\FL?@!-3Q,= +M!S"2?B;4V+@3@/:8PB=*[2+9+6#R5--?J9O5J69)F$J2.P'X);L.R,(DS*E) +MQ;^LU.RDE\I/-J92J4RAH;/.)$#M21<'C@!(J*5^3.6G@!YXO2U"W)X9L<>B +MJX'STE'\)ZL0W97VDH4%'92X-CV:`-/%9D\3*\G?5/3ICIB_D5A?Q=-(+]6N +M36!^[4;J8-2&_YI$^^3,P-'XQQ0.?&]2"@+D?D*`D8+![]?(N2YXJV-]Y08V +M>'[=BI+,]XLO6C:2(Y&9?='388SI&IMJM@E%$B1\9BNAEF6NR]`$O]'04+-7YM+HD[YL$25)Q!FA)XOXJ,4Y_3%FA\ +M//&:\G?1PAM!]L-22)#)8@CY>KH4ATXZR?=S`%B+F!3Z$V1-DUN'5!3\Y30% +MT?>OG\&UB^:I^?5O42N\B2V^FY:P@[<0\JD`EDW7O2V.1./=9LV?Z3DG_#Y0SS""E$'#QG*=+C[MP.42@NE8\7>FP`.GOG\F=N(&4K +M!+M[&FYGZ'"R8N#*"FHID-R$.Y;98J_(42O;DBMMCQMH,NF,[\Y* +M:$[*7WF,:'X,F05(T2@I.IUTA#!WX_D"=H:$^]ILE9Q#8CW0D1]^[0(8\8UF +M__<6*LJ0$GL+OVI9U,ZU@9%Z(O;52,H*U0?O),275=J=9")?B20ZZOX$9?_H +M3-%/U5$,$-"-_Z((U.1J`QY;8Q@\<4IOP[D:A5<2AW#FJXSQH5X$RL+DQF]^$8KZAEPUBU',`7M^L;WQ-72,. +MX9GZ/G&3Q9X5%QV^`@D6@+HQ_&W"B`X4+DX*)._9?]N4)G<_FBD&/)&8&\L^ +MU(#0Y,@(+B:*2;A?&5/FD70Z//4&9WT=P)P80J<`^=3Y`QT`1?X(^K!#>Q5L +MDR&XU1>#A3(2W9XD\L-"L,LBUGT-(P%7$WZYRA+.P%A"=;1S-1JZ5GX8*[SF +M>0'.A+SS]?J3>.S6*,&QN7V'CVLF<5F7 +MJRJID6V\D!&R)E*8T_M,XVO%699\!Z28HFN9;4:S)NEZ*63W1=`",$1P2+EF:(NYYR5![N5IG5K,)C +MKX77>`YR*UA:RCQU*.G_IHE&!]>-HDV=2?"/@FO<8M9%QXOLG2R\^Z6Q7W$( +M"C26N?Q__O]Q>:#(IL553#L55M,-G$U&\5\>(++AM/0W=2NBUQ_EW*52I%[, +M^\@PW/QIQ66FGSS9XW?15JT>!;0`;);"FE)'1Z_3K!TYW77BNZ@GWTG.,GN8 +MY8$$*&E+PV;<,@EXE.8S%W@R\$7D8M:_L_4`4S4JRN-8NS>V/`)MQ`4BVLM> +MI6I@`?2=9*L1!B7OFY#2MC4O(3G+Z2Z!?:F9X@ABR?V$!ID`0+5NY,H_@="Q\,+!.6JR5X?2T+K.C88<9D +MK!M$N%DJ9LCYW"\7'\VNP(,0'>6;Q0'?8J8DAAL!W-^=1L.OV=3`ZL!E90,` +M:C=ABBMBN>![5UMKO>`;`-=?%;+`I/G(@]"8I^X6Q:WA(^G2,#(CECF)?>=> +M6G+@IG78Z?=G%_]KU[-7D+27EVE=]AK/<`'@@`@(NUB3LNG$;*!Y6TP8D`;\ +M>H_=#2TJC*G38GWI/MTO%9/FZL6%LT*-U+XMZMR?GOLJ9RD!TM8I^LEE#)9[ +MM%`E02.`;FZN!XY:*LJ.5TZN>`+XE`M7[R>&HD_LGA."V70R?2.Z#L9KG;^@ +M"B+)$]C6Q4=IWO49Y)%S.^-Y[^DV2B'$UUW^EES$CW:U+?X@&P'L#P=A#1() +M-+1(77MU.R783802`;$*!_[M?+&24WZN5A!4%&\?-_I8>(46K3SG"C8+C/9_ +MX&?1O]?)ZOU`QQ-C6(C<^@ZC6LI)G5EQ,C]/!]"Q]/:7[NZE\&=F//$W:@I/ +M$?._D,ZV*]Y!C#C[$V.,HF%>9S!8Q1=FA9F))_CH@+M'_^DA&L_Q#N^] +M8$X?^WTEZ>U8VQZQ$[?9XR%=8WQ[!_C'2O998O*R]4JZK4ZEKUM?FQ3?[SDL +MQ+:6,K+(;0M^^Y0"H%9S1\?+9-/TQ@L%VED^Y%Q<^RK4\]B,B"[1IT>^9=!) +M,01X8`/&_AH]?13'W@EJ@GS7FQ7X8KM>4>29J*"_]H?\K7,L[O=,&ZHN4+'R +MI7)PS>1>`^I[/NM`FP4&J*71]R_F-2\A"J^P#;%Y>)Q66@_@:KJ@F@[6,H''5=3HD\]LF:B(EY58Y`UZJFM4*-&'=Z9`C>KG`M +M_Z4QC;'#;'>HB=+SWZLWBO%0M6[X/@OKK:TFT&TJBK*$U,TCD*9DSO +M/77-'R"Q#7-*PD/M="BV<\KX(5R9^-',9X`EKSYMF$JXTJ7:JD?BHV>GV3-VD!D,_9YD0E+H[3)P=SZ]M24(M*>+@3R-S0B)X?H9QQL0V21!7_M9:A +MSR2@JF';1^8T5)/>AWK.J^]'I]I0A7\2N>`"QJZ'0>/'/:];UMJR1N2&\$/^ +M'*52.M%OI=_39ZP(:V4ZVV#*N]/>V/71(LIFV>33FK:::TS93$2,PI$?S183 +M*6E^*K>RE@6"FEBOCC!HU,1_E=7":\/LT/5'V??#"B.C>>L_X6*E,QJG_R-3 +MG4&J[>BC53)2\_PP/\653-CIES$["5."2DA41;=M5I6,'VCU,K;#^4(;H6)6 +MY@>&J'VIX'MCN,[4?1PQ5C`+U1P%T7-R=690/H&[)5&WN+0PO&WM0+PKVK!D +M1\SW\%%87*TW89Y::!=H`VW[KQNKTG]_9H[`-O\Y!VPG+2P/;]I1+Y-=P]:' +MDFM!.\6-[+;B,4RSXC>*]D-%S/4NF:[)(Z\N)V1OG=/V=0PZX:S%BYT\+HE` +M;>1&A;"H9$.U805*G/[YC_6]']!D:WB4$'OHE%?R5M6F756M=*=IWW0YU2-W +MCLV"L0P-M:;`-NO((.]$EU\I*C;.@I@:]`W#T5/2<3%A-XVD],D!T/(LKV1R +M._+'?0=#?(X"INLHWE%_\7?G/NB,?K+["_3;8:#W8Y->&,@IF'_X9:('.%09 +MN8-L+LF*P%\AF1M>%>9=!.CN?P+9D"$X/9Z((D`T)]?[J<`<,S$2]F?ZJ4H8 +MKCG2UW89F8M4%4-L/8.^GG&]KX0__>[@`&NBZ3"9_S36BY$-)4U_GZ@J08B/ +MPN;T["LV1K:,!`3C_!9%8EQT%"V^+T.VASJJ"*[1^,D7MY0Z0E,\4?N^+_RG +MHA;/@087RE@?GP5X$A[[+&U/S+_,L##XWO"@]XO_^@DJTK$NBC!;-Q0L(:^^ +M`J>$X1^F5"2&ZB!@6'\#;"-,'ACZ:^Z(QVY+L*?#\L26-7:BXKT4S +MJUIBZ)RUU2T>/45,_Z!6;Q^#>*7@N2$H`#B=1VE)K*>>R`EUC]S3:\A9EE8% +MP$(?5CUQ.]ZC:BZ,?IC4`DSB/8^2DKD'4`G$#BU@K>;EI*H%;IP8>?0V&UCSE3:$3*84F()3\QNT)0&]F!0:.L?A5L-JU-*6@6TIAO-%]D9T+2C8Q +M:K=&:1L\K#O4(_ +M-MOB'O'W"1CO[XE!MO\$:*_[G$,CJ(>8%+:!.5>AY,J'WG%GO\(%F]\*BJ9* +M;8EQK8VG+#KU4$[7:^';?ZVE&/#8KFXKW4JJB`?IET8*+]MY3_6::D0D#%0V +M:DH*>`B^RR49'`&?*:B!U52=,O6_]IUYCEZ5*>\AY*._0:*6!HI%-2V952EG +M[#J8QS_=0[QMP$B30(\%9#"L,][W3-2B?UWZ3@N$1&$"9:O4W9CA8XG-+"?D +M=X0T2D-GCK/K@:JDS[;!,[R.J!NMT+6B^;B*P0CQDG3' +M]"[#O?I]9WNDX8`BJHYOP6,2#G$+0-JMTF5DHFN[>TU,2U'2*(O1@@>DSHG, +MEHQ6J<.G:[Y&J8#0!?'`Y_'L4%+"%%4ZS&MM[L><19QL1G=<^@`:V2/$W7,I]F8X.?:KC"1U%LJ])TUP$+SQ_%59 +M`3Y6A!8NO7E/U\>F0NXXSA+8CP$?&??9SQ.RZ8XA.(2>;].%?JPL_;;'&V`B +MJ]D@$^T$)*4$_#FU:V70!L;.B;I;^XN<#B*0$6&>X3&%\IZMMIP1RT>?>_Z$ +M,+#I\>3L>&]8&,Q;^KZDQSGWL)8*P=9TO=.4.['K#NE['':-Z=XL@F3:$&B; +M#BF\!2F+.J]BT$6"Q1D@&U1)1ZR!NVZQF3H]&'G1].G +M4%Q>Y-M!-10?1W<6XC:U59VT_NO>L'";_T!1#(H_Q/;3>I!8R"REXJF`0N65U'/Z+9 +M%NJTJXXSJ8?B0:)E5Q'UO/+UAQ9";-<9W/]YQT6,//3IWZLSQM;(>+_P=&EM +MCBA88U2IV=15?@!\-C)@P[DI(V9Q&WG7>096'Q&JU&@IHA]SG5GI2^K +MM*XC_J<^-H:'D#4M:6B&<$$TQ%`Q5^'1"ZRJ19UE7)/%8Z5*/'60\+QY[6(# +MZ[O>-3\AVSH)9-]VP_>0[V>9%W';\[?=)S-@>2Y=;)G\_$)WOT9TL+\QEP'% +MTF"YSGUO?]K?%CCY07#>IRX5'$3#,T>"'13K'[1.M)&CD1A)X>0,[[),D +M\6%DD&*IV.+@J*?;;*L[O2DPR*]#]X/=]J5R`Z]8F58N[Z71G/4I2M'#$0:# +MONK(D772G$,!/]L1D5&?4@:T9E:RM3ILH)4X&ZC#_[\(*LO)KQ]I0I45$];! +MW.Y?\`GTY,'RR67@'F9RVR=RLYYQ"RTTEU8X]+7&T$6;8U/W-?@D$GLV>N(D +MQ`CJABN!EO#+O-6OW6UGV+EG]!?0A4AB0&3UIZ\]X>,R+(K@?U.1I0TP4!?; +MF?5NX`S`[B1#K_M,Y?93O\!++E6X9VEN5.R(R,8W*3?/(1K,)/OT\BS+?G1!)]4<- +MG44"FVW;J?,@:L7ZH"/5,G:D)B];>RU*//STWF!;SS>,^>T7 +M^6--0\I38VP.STM`=YL3X:$)&,[)2SIT`=39J4ISBF5+Z2R=E[.F^1QG]#VF +M&/'RE$(M.CB&J\^0U$1J"1Q9#-13)01D+J:PP02ZL02T)2BEG'2J +M'M_)P2)I+8KS^LXYEHY?J/#@!4>+C7X%*1XR-7/4AN.T9PV)3KEMKMY]\B?J +M5)3\!:)#C*4AV9J_HN\!#(!@CUVQ8*XY38+T'EGEJEO1!04XL=N,E2TEFC0Y +M(S*U@XV$M7%2=&?'7X\1?/RCNHI++/3/Y"R^49"A.?L9?]TS_-#2DL39NN[W +M!=YJV42AQ"9E:5SZ46;B2!(!*)8?_W.[`CD(.&(,_4V>>4[\#<\SF8#L87QP +M_M,!F'0ITXC?)T]S)#:C6 +M:^G,J-K8C>C;,&KXSF3^\3_Z.]7_CS*&E$5Y&\6(,/[#N;1PW'^WU0B<]D@< +MDW7H\I>Q&2#'#B_,"B&;#%\7K-B.X7+-.IXWU-8!T2MLT6$HDBMM.396;$!C +M`(VOE./04,JBTDW"C*4>KXWD2.$WOAT9J+%D`0B^*YY^*)E#R6J_Z:O6V/6**8&"S`(O>1G +MVES!9?<_R@Z>C.0P#+2I%@&\63%S3J +M#6&/_`/IPC!29*I';=TU6_7`U%+*=V[_?K?`#^E.1!'.J(E37I7.=Q*LU7F( +MR:^V`"G,(_BXX<"&>1N!YP#7#[E2N19GW +M62/RS``+ER+"566$P>3AL,$.QQEVY1# +M6.X(/`Q_C">V3MJLW,TW&VV3,HDO_F6@KW8=(/57$CZ=:N(EM#G:;BJTXQ%' +M6N9+;NJ1^8W(19'NX9\BKZRN)25B"JA,B5+)Q$"4['88]R25Q-L\KZ8+(MM$ +M*RD'/P)@9I"G+5^(J5$:A!LRJ]K893H,EVYC>OKCXB17;`MVWQS)0D*">/R+ +M4_Q>+HYKH=="@,F$2'K\-U]B3U)[!MTZ3:6+T[@S5OIE#0'>3#H8@@?T*(F+ +MD5!@]8D?%T-JC_Q8JA0!G;7I3E\67*@>8,",Q#5$N6$)#I+(O8)>"SXC^;1: +M**W:R*[/0O[;]2H<41"PG7&<-[F9#HF,!Q97LQE&D4YMC3A[KJF@GW+LYGW,TB!Z6]QP9IZCAQ5 +M-?J1.)I!VA0S4.I#FR5N6Q/<PU[BXK?F +MYR=51C<6::M)*OB>.771V#Q#;@R>C+3L*O2!>,>[R$#C +M`0\]JH-MPE55PR2\?ACHJF:V35;W67'=I'XKU5N-H3J=RY(";'\EU8:&<[/B +M=`0V`Z1#$F(Z+&<;353)A=>S-XZ]:W:&Z5<_L>QN2FPH3J7B"+1'6KVNF/]/ +M*^U:=,IPY1YX0FW:>1G"1.T26>)\0:ODZM+@&<:=/&T\="WY +MU0N(44J/"O7!K";2>\-',2B7?L%<6-Y?R!;`D[& +M.1($4M%`BWP94>G4<7D'?^E^1O8=/?[@$DT0?OE`R<^A(L^@_)P%+J0&!E<[ +M*P*F&27V'(U(/Y.:^:AP.*ZG`7+(YJB007$F?!<)J*V.,5=MS,[UU)4O?X8]_/*:H3VJT +M]:BC%BM0?CLB>)JSA4U?25]T]Q(@GSX[`N!X7H/RS%/GY_JM4E7(;A,1(=-- +M)&7D[^S@-:K$#M40HU8Q+F)^Z`HK^G8BN.^GX_UH@@U88RWMLP\?;RDZ7=DO +M"YC(P5AE/;2XKI8!_Q:/IAD"X(&%1WEDV![]@F&W]43;?`&L.PO@\5K$-IWC +MUSO"+,EX/WT52>L_*05X)LR,UX61N$1I.^JS" +M*/+ZE8/SA>ZK9Z:"UR?FV?U,1+DVTZLXLT`CZ="&M1#F?W\GKS:[%_694O-M +MJ'6I(A3=.])YBV,[.Q@U_0PESF@$`:'--7[>,*QCZV?IA81`[>6W@RSC67P# +M#A=SKT'HA<+0@BX26)`"-591(@=NG*4K.D%CR+;S[GZ2""M>G[]IW.NHZ9S$2=@_[K7"LT1;3&O +MUF/0&L$M+"\V,M&T&,D#%)?YL::@[2MCZQ-_Y)%Z9.OA?WC:8HJ!:6,,;S&B +MG"K/O3=0KC/A]&!BE5)1K+`54KH!.2R5\[X%%@X/I.5`&!O,2-L$!CLW*=IZ +M.8[:WM;_U0%`KF(Q7!!4$]CH`M3'DM^-"JI@PX(UA92@SJNLJ:47I4E>XJR2 +MX"HS`Q=@N]#"SR+Z<#D`TG$T`>'GM/,LOAS&S>$%NGN%*@N\+-+BN,05'!=^ +MK2_M0O=0S5E`5Q6"YZ\Y78D7''+<_1FM3$)+8F1>35NZT\A&D-LNCW(QISC%8F.&`2/%3S4)R`)Z$S.597>W!.RWU!6 +M"^L?8.&*;K7^[)+IYS1',_Q@`SN^ZF3T->2UMD!W4B5F` +M_\WKDP;(EH<(]`\C"1=HN/S@M[B6+U:ISW8TD49+IZ?#"_C0ZPLL]@>:Z:FL]']7%+3^[#ZR +MN4[$HK'F.+T8$J0$QB<[Y@L.0[R$"/24X2@FV""PU/MHVAE=\K]*9+QPO=H, +M?Q?+8:^C]7MMOXCR\B,6B5SS00\DUF98QM@YU'[6N-&HID^,L!:B2`DU4..5 +M%&3*`ITZJ2T5O1]LH;/($Z"J`U3:G% +M;IUS@_W($5'!AB=1>HB514TL3ZS=/YLA<;U=V`8?,!-KQ#D< +MD*R#;+_S\Y]*_L&Y34!V*F[>V>;EFF&'<[JM7#][00H_L,^";+ +M`>87<-/5(+.9-X08J#5P_05RQTM':<@A\ZH\)+0Z![0<9K^UG14A??!?'=9O +M@F&PUA3_->C/!K+=T9&-'Y3@'6Y@_/M3+>B&&K#\%:6DT_DOO,PC6.?72OA$ +M+:8EXW!,%@Y&L#N>Q?-I5(#^+BW#)8=D*B5=4+ +M:")8#SZSS-26Z^?7KDHY8&ZL?SOMBW6T^W"+9&]`L@?ML32F6.UR1?<@Y1-Y +MRD::GLVXW69GN^W+\E[#7CNCGU5$V[+G8@008K#H$!8_\F")NM]T`,?U>N+C +M03BL)6*C0=UW/J$K":7Z==G8;.D +M*@NE\:2&WS#<8;%(4GGZH3V.>T$$-;:F%;(6LH89.0<:?7[=C"S*%4>4_'"M +MGE*0+:QL#!C=KF9`#`PND`X/%>7&>)&*4B!XL=!GWI*)90LP\2K!]3-7F^;+ +M%_TJS>E3HKDVUF-^[9FJ\%9IY.SS#I!OIR9F/X8:3S?@JBR/[XS)[?B,&\A: +M[=(_FJ#.JX5W4S?2T?1H`6LG[!14-OQ!4AH;S^AU^ +M)VMZ1"RCSY7@I^F`-ND"DHQ\:Q;VP$H_:@V%CH:(02M3L@!]@VH:64?RS0./ +MNN3K[TT>;7&Q"C+5O#+@Y<))S6G4R1M0-%69;#+;&9.@F_Y-ZU^ZV3T7;T9W +MGV7;D\.4,7;Z,!ZWA54:UP<]"V!LA5=JH3XUZD=7:E+6ZYS"\KE$HZPXE@MX +MT-,L0`6YL8^_R\=MF`-&1G]F+3&<]:`<1M>VL<)AP[#D3@_>G:KO>_CM[6Q\ +M_QE3G8@)//P7GA0G;H.OP:1?R=^'0-"63ZT>C]P':@X7BO]1QS%M_!(<87[* +M,7QM-34\Q9Z3GG;?GQ_AYI)528T4`-(WC,JZ4]2:JB?:WRLY;8.'O7-JN4+& +MR"!7;E`JTXL)`O\JF)7ZLB_ESUJX>HICUHS2T*"^H;JQ0F*+6;:7\H*Y;*+1 +M,\S[)7N2Y<4-Y7!6:1RMJI=P+K>][B>:<@(]$VO2M]**(92)![DCT73L973D +M^C>;"I(=XLH?BJU^[GI&%M!.[Y$\"`!PJZA-:F\N@:ZU5;JGOFRL2(A[AD0P +MZ3JDH0?H`3WYRF;7#R4T#FUF#2_9(!W*89-?3>V4@DHQHR`UE-=WIE92#@;8 +M2O%*X_^AC([&]115%:C5_A?^N\-[6-K'V.VWP(R>GX=.)==B4.,+6TOPK0'F +M+E>$5RN#@2_6(Y[;8;ZKY@Y_IV'*4[XJN^($)L]\9\-4&3Z +M4Z`SVEEI&F^':5-?4:^)#?]B)7/]ZO**2^U +M@_&L^<_F8F!!"X1TMP=/IW_U91P:L?]ER*IQ)(H^_<4AY<'PJ,V&0NSE8@>WK)(N>73_FW_J`8OT,K49U:58*MHJ4XW,_@X9:M^ +M0G"#AU^%2-">I.BX19[:D*"V*]!73AU02CY49KY4C%DOM!2_GX=Y@D5YW"R\ +M%*+_(]H[R13+#\!A[QUL9%"&Y-*GY\[OJF(2+>YX+&O-IY$\99[/\DCQ8TS+ +M/<6!6>:^2I$JK-J;F'"G'N^P!6(1,;JH+(X>U&Y`Z#NX]'D)K)-W5QC!30]6 +M2!O?C<6FD\N[])9VGJ,"N(5+O6H^>])G16:N,^$_"8EP)7U0#HCQ'-]Y,+JY +MX)(ZYQ<7\+7VU!B0E&]:?7D+ZW!H=1)RH;(ECG6Z58AU%.SX3\@SS+T +M/!$_D6HBV^R,6=$#[YT09DY6Z#=O +M8?KL&CT2R%B5O?1..65JS<+*C=;9UYLTD9G0)W,_WRF!73#GAH5*HU'?ALP( +M8A-P0F'-`IT;4LY!!*[4YV:?C]XV'2Q__Y,**.8CX3S3"A2@,V/FO61$$:/@;+D@:5:-4)O9!_L[Q9VTH*]E"4"0G=(S,W:+H1CQKD!O$NG1XH%R+EY^>T]@EQQPXE +M_K2$]1@6&1&3WE#C09)J@:Z^0KX!&P/4=!)#)P&D39*";JIDT`2AV9N8&Q89 +M.I$U)?0^Y)P;QTKP_6,W^D=>4D`9,>O[!YA:83.KEUZWH).-#16^^P6I+56% +M)XI-H-8$Z##3\2)F2E+MC02HQRZQU)D]/RJ:((4@!4.5D"Y-U[)`W8?%9-I?NY/^$0(%'--O\6N+/\FW +MZ@O;VR7219-;P``.(DT.M`,E^A+$':`/PN)'4ML,>"!W +M;`P_A:A!MD$@=8IF44J&>1;.T8'JD]9YM6Z+D!8_U#`_`L"XWB0ZD6%+6>2M +MF>;+]G-0OP,!+24F+O@K\83V6,40^_GK)#*Z_X:`9E5O2QLIJ^ITDY6FM*8+4`:5PGB#$RVFYQM3<4PAB-#R!% +M"*^C)"\?2FRK+O980"PTO4C`;LZ?%L'ZZX!2^X$_711?D],"T":V$6\/#YY +MW"UJQ2U!DUA"/Q!6.UT2Y%7EH<+--SPF%:N^K>9H)OK?7_#K3MQ`YG18P*5TH>^EJ_D=Q6%*1N=T^_N_6!3*A5)F3P`DM]P">L\#F:(4]AG/7\L? +MLO>J*Z.T3(:6PS%\61O%=Q-^LP$[GSRWLY$I\5ZS;(<%&=6=J)F,!%FH*QGM2+FJ^PG%!' +MGN20K"!&8>-]EAM/)%5SO;IK9\&WJ4\-KP#JHZ&@231SFR.W21R^,Z&)2ZHA +M+-VF)JO$L-N)+>O1=*S@W6ZZ\0#`!^GG.I;,QUF^S8*U0\A.[GU6E*9_[Q#C +M3^1B?C?*L8X)*[1&BEQWH/<%EAO2<]-!Q3++0_6ZVA\FO@AR +MI90Z$*1_BFBL+$762%4JGQO#3)/ZX9F_"3P3MTBF^@N-)])4`=>N]R/-GS:- +M(\F2LX.[(*^OA:IB=5R!P?W93N>B3U+/[4X*%6\X"K^^NMOP(^UM`GX27_8N +M<7\)"E`ISI13$CSM87)]ZJ7%KF^:=+@+K@R"4T9&;]JT/8*JKE=[!/@_!%L2 +M7/$#8^KAT%"O10E6?FBY^)DODJ;T+5"Y_TOZ*RU54M$*YYHP7 +M2^&@"LJ]9'(D9NT"YR+&!,R`X-@T/Y7!3AOLE0^X?C*`Z9FG_O;JZV53Z5?$ +M^>HTXJ+0GJM#Z4$$L?0"/P`:=)L6J5_]CROQ1M$+_-<\)@I@]6-W\%XA(M/C +MU(F3$T7ST\NL)&=OEBAQSF@IJ5Y^S)T?.G\65#<$B*<"##;:V;F13-8I36MP +M&5_--EOFJRIVM_>U;5#*:AX9YRW`9CN!9WE^^P(>4R-H?$"%$N^=R5D305UO +MA#2=(=E'%RWGJ,"7"5Q*P#G#9><8M$'^9%C=V40[QO0[97X/T3'5,&@Q3ZW( +M1>_7`]&0]=C%JEQ^[FX0&P&=_66CY(6H'E6NZD?LI&)*.H`^$DAVU=H=:O)? +M9SK&ZRIQ[9+HC\-=_\CP[\U;[`/2`9K(Z +MJ\,^1(?0,@/_8]QB`HG1E].+#XC=!5NMJ9F3FL-)($Z&5R!$;8IOF22<&85[EB'/LX&$7^>EP;X+09EGJ(-"$O1-^]$-Z$QT +MY<^KLHB#70"$IK),ZNN&4>2LS8AP!@9R\'D.3Y+^[DD%@]UXX%\F9UO6+6O= +MF]`A8B32VR+2,-S33G +MC=;Y6]S`@8C/62QF1D8[8&XAB6F]?DC>%[;6!S!3)_(H+W'F)]OV\%4>=7L" +MEB!CH:VJ0B+F6&B]@!YR'@LF34-ZP)ELK?H=9*9;:8I`L*(62305$7RO+#D" +MCVNK`+M1:9I.1Q(U2=%"T3UC^Z4QH;8!;W#">/@/"&,9UI2)O@+5M!1`C5V? +MQ6"[HC57E((1(<3_FHH44D!I8"1#EP`]7[KP9B+5?+$%RL..MT#ELQ)$%6C_ +MM)Z*B@N8)F-F-2;!Q$X[N:-1N&L3T)%]7!5.<("?WPI;;H]^T*=UER%Q-"?N +MV)1]ZP55R2D>"5.7*<0IA>.`4K>5"3X*MN?;<20.$-WA*#CU"6[W=N^CII_T +MO^N/I%51DG9H=6]>?]F"__ON;G>_=T=Z&/RR$P@LW&UDOSS9DQ/!*3U@6)(. +MW&D`[/*J2MXN[5V8OD9-Q),P7%V$\RBNEY.V*L>YYIT94JR/V^C-E,".F^9A +M_SS(Q"WX>]8Z][55K$U>$NK:8\4O*5BR7$8^="[^E`]PF-LK:-5=F)KML^XZ +M*Z;HN\^T)I-XK$CG3>R8?T+5BQ'>M9T'=/N43KD>G;QD:Q1F:KK.6CF@KS/V +M>=VX']+TW#I!PZP+!L8N`T0-WSS?PK\(<=\>/*4MJ$D1N=)N]A&0)>' +M@T4R)VSOY`P,3F,7ALFAT*(&OT?++9W +M/6]0O/=^;\LV4:L]MM6%!>2XTNG%6P@,X;S_;*4L.>@&:JE(<.D&33L77^,X +MX9HLZ9";K">%"..,>W&?[?@`MF>X"5%5/-7:Y<=4MD;T`S?CV;Z,&4NBP*^S9[N;M$ZE&>%6L]]('=5Q37W!;U2::J@ +M%-0Q::/*XIA1#J7^H[8=L#D3JD.MKQ%&+?E69M_!E&_0P5G?F!K'/F?@`\GF +MN_$-:RB-H5SG/M-)W\%P_Q"P#,?>9C@UZ*L\I!N2Q:6"SU4(1-IX_G6/8??` +M]1[9(F]DM\58@']7_NB]A2"6=,C&INSXTC;2'7T4B'M:_,!='WE]D*OK28T> +MQBK&4'*!L9,ZS$`,SW8AT8X'!8^<5#%(RXD0+5SJTB&>K0C5R=TTU][U-ORC +M3Q5Z2K)OA1*^C(,LC/6=24RIZ-5A/]EJB5>_UM?PM/&4-)RYZA85EH8;*R=` +MK*A"T-RH'4PB>Z=5[+^HT020E?]AS!1S"\I9L(SMF;G'Q;8];+QH[`W(OYZCX^:/[FJA$@7 +M0DNV:7/2!4^WLHFM=Y8RU@OGNM6PF=T3:FH!,$^?\,)Z!;C]M356?_ZON\^0 +MEI_/ZT!*FB+FK_@3CWGOI0%AR6-]A892PKA5\GNE?6A=5-*=WZGWK;V&$#.0 +M&&O<\':[M)T(IDD,)ES%AE0]H^T^5-7&OW3?54>BEO$IK[:*P=!X&1`*U4CZ +M`?6L!"U<&2&.]!>G:GSF=Z@`?4E-\(36U%$ZYR24HHH`;11IIT)PFF=(GL)]HHJZYG&`B/%D!N)EX^ +MGYI^/\ZYS`)(;SI:3P]_N21:-`&)#C4+?#&M?XRW@_^#NU"DTK&KIZ]@=ZD;V5PAJTS:Y-!^&6J"WK(_!C'2]!.Z/N$_GVS>KW/59/(Q8_+XJ)T7!5BCGNP_S;>#)J"9_VCT$+GAR)?:MFUEPWX)L+WEKRWUW)NC +MC@LD>;\">Z?..%'CBT4?P4(XA+K_[J1;][1$[:@^/ZL$.KSD"'QTHA-PM,S0 +MP1,DF&R@U$:2,%Z7]3=@T+CA'+L*-IA0=#8ORK$U1QJWTB*0'G`\%.[%+H]0 +M4RZZ9'[D%^,I`=@5"'0HJLNK\38W2_W9]4E.2`KY"F;%("_56G5EM5H=;UM( +M8%X:3:N321$:O@!/P)05'BV_90L:E4Y7]5W0ZX/35/B:L$,Z'M^_BMV+;X': +M>)&>\%B\N.N&*B6'_UP76'+"K??%6_8.`5LE?ZZ;,17-J5G:$R.<"=]+8E80 +M[["*MV.1IHGF/-[.&R:*Y4#`]KD%QCC^@\0:$1U@6[L0/]890=JG$A4#<$YX +MV<*@:V0;]0[S(^\<@^BR4G_C/_.`E&_EUGY3MT3S:2E?0773M#-3RANY*X-3 +M^PT\"&31H@8YWRW66EUR4DL>IT.=<(A1U"8X@?K6\T65ZN[#JL`S\?$>!O@A +MMW/6:`L$J>+KX(#(\;OE_421U1!`(R&'45WWZ,%R88\`:>,&[$\N@W8$L/E' +MZO!/D!4"`C5MUR?=&W#B/^$H&W8](HL@ZILJLG=<_TSCQCX8@/SD]TJV:=,X +MG`!*:7LS4Z\RFOMB;`UT] +MZH4IMP@,UD`?AS-F:`:]`WO--!(5K+U2YJKA_"#4I/K.JV_H9B+2,I??9RZI_L\8^=RP7);&G;J_YA5 +MC$+["FV92JK0NF[V0<')=DGB!,)M1+56C4)P>Z;>C+I +M+LP17YH6Y">[O^N(82U3"8*DDG^K'MQ!FJ>;/%WHOR2;>9'H&-K9]TQ`I[T< +MT:*W^$-9D8^^Z.P;I;>+H;/BQ*EI&]QWKYH1W87]SBVM>-">J_#U5\&Q([*UI3, +M69>$T!E\`>$B99JV_;79&<")I7+6#!%V52L%/!LX[UKSX=M:3Z&^:WD-\_S` +MQ$O2?:-\`R`;`1X5_RX^IH7M;@"02 +MS7NO.)8THMW`#<<&(6#FBL?043M<`.\O)PK5A>:YP5F__'XN$&C6JP%MX,`? +M=J\%%<>SJDO9);N%6AVSCZN'8DS#"%A%`4J]_HFN6SJ6G>\"*N>,WZE1 +MW9X;M[?;&A=R",V;0B\YC$[EFB2.1^*?\_37&03HF=A/PVHB]6!7&4WKU$2\ +M>=+B8L>K0I?'@_E>]-#S/N\3QHQUN`[:MTT.LW;H1F5C\U9_43`+Z`+MB;V] +M>Y!&:]6/^(IEHZS$[R;3B>\$72V$YM'`VE6^U\&>2GT-O:W]S_0,)Y,N^)^\ +M$&M-]QT]BK$MW.P1F!C,,`68$,+JB!:IWR\?P7A0%$CJ0^!JN@,7_FZ$V@'6 +MS^4U']Q"$#+"IQPO[=U#M`;L82X.RUFXV`==X>?EXJ"P[XK7>^8).9[\$W4B +M5^"4OK%S>+%\UZV)ZX]865PU?Z%O+PHCXNC"=-](43HEZ1V'4<@7JU["7=ZV +MQ<438A!XS4VE]DMX>Y>IU]T1(ANLRR1W^Y#3%"1Q1?BJ="_=HMMBI/Q5)U177G&K +M7#4C5PAGLO7,7+B?:P#7#R__*QVS%8Y\"1SJ`5U=1(^;CK/27\U`33W%D#K5 +ME8GEC?'X>?Y0GN"'.6MR8B)[*AML4Q,*?3)U+M3T5;!B+>,$?=,2.D4DI6:! +MXX!DN]9Q_.)2GD4W&4ZN>VAT-T3&]GTE/NZ=L,I[V%M,:]#GI=#N5&Z.C#AR +M759J#;X(ROC96'U):42A,^Q5TX;7"!&@=$W"A9Q]2NWWV5Q/*(Q98$2<6,YJ +M3VZE`WZ4/'15V_8QQY5XS<"\I8-A"`J^05T\WW9&MACY,?C7'-*``;84;"Q8 +M1^^:Y`^OGFHZ5A2T3>4EV>6C_2&-108LLP^8]/>I#P2BK,KQE$<-Q"AW?>VO +MA;I(`:=885:U50YZB#N,VQE[U4E.]J4DYPU8DLX%+G>^<>"RXFF45\5%:^ +MC55Q6+O\Y!2"]5IE&,XIVY<04P?[NECMV-N/#Y:8SL)WB6FJDI&U;%;3(^/T +M>R='0B7W)+Q"KP*L:Y$B3U]:ZG>I[\]B\#D+>BHX#H>VCT[P*"OGKQVBC"UO +M0GDDX0=_;SC$9TQA\MGX",, +M8MV%3N[X(K%LA7R[CY1?G`IX)L+([A8[:]NXBWBL)\!*;<*:+5:(^%`99D5; +MVKFPLVN$/&<=WI%P;D#G*EYQ.NVX6(!@-]DC*-BM^NZ$"6\M_D^YJ3".HC`H +MP>?@D\]36[/R7VLU+ND(1M*&GP?A:L3_>XG<,U6&R(0K:\/K"6N8+(S9%4CB +ME0=)5G_>I+R&&INY@6;P-_W%UQ!;U+9@(1#L,8\I?,?XM22#TR8QBD[7@%&F +MH,<6?_@%(J`-U>CTC?=X2Z.`F_'D77H<=LY.`03[0)MJ5FAM>*C;,]`O-W0[ +M-JS:*6GKTX=#.<;5W_^[[-'?X@OY]9?901&!?R2L)Y)Z/Z-P%'NIW:N]K27F +M\](Z?TC/FB319NJFL'`6_)SP\,RV35T;S*)`5VZ4]71#.2LA4CVMHG%5S3QE +M8[HI[Q\UGFBM?1AY1L_OZ\$"VK@$>5Y3R@_S8+H=]+5\>AZG#S?XZ]GUJ;+V +MY_"4%HUWAA&*M2"TN$Z.:7/Z_"\U[&U>)_!-MNRXR]N"2E[Q&F%\LUOK1')W +M\Y^E7=M\W_A54LR\:']+&O$@)_SN4=+EDH\(A9$_-4]?INI=-(AQ@C>-!W:J4-;/.2`<>M;9':<>\&AAE"#YX&^WYD@ +M<@0%9LCW]H^'6L=N<`7M8:MH6_*QE[^GJ#)45=B![+52&=,K=;4DR*6_AOTD +MY]UNJJH)4#TX%0*:8RKXV'&$G^>XVGC2?DVEW?['^E5@7G:"M82]"^\\C!"# +M-ZZ("'B^C2,H3"DKHX'N=7JG;NP7E%GQUVXKZQT)'6QB%\K0SFKT./KP%6LC +M@+[UZ/H2X/]#!K[\WV9'X8_I3OL&$LYSO$R>9"OSJ/'RU(2`:S\`]UMO][;8+:#@F^X$9QV_$\K*/J;NP]"NNI##"-8"]^/POT +M*7_!;-&4A`P;_%N=G:@80^QO,'[>0/]\/H#J:FH`WQ+H3L5CR7OICR!UL_E> +MT7#C:`W/"/;73,+9BGTWB4Y1]2_4@LS$VJ(I,5#+,FEZ[L71KE6XF;U\#U_0=BA)"JYV +M^B\/,73PM-\4NBA"D5TMO$Z7Q8$XVG'65KJ37PW@]URT%&GJG;%_ES:P8T\R +M&3E.UU_'J.+H3X-W=T*NY@DL1WZ9[)LA6F@)^8Y4<])7)"04ET=1^DT +MZ&3@I1PG9'H1V`0DYR6=YX?&B5ED>O<\W\&DY!F'&75K3VFT(^@0D$8/$2R8 +MY@0V9;_R_G$:A-A:",,CF=OR$VDHV-)/\9:H<)%@"@$SX6\J#A`]X4UH2_E7 +M2SFO=D]9V58-PNPA0WB6Z3/C,B(H`.#"QMYP8W]">,?(13CJM +M._6R/H[J +MAQ]5"_N41S8L=@8-Y4;[:]Z!5'\GS)9%2!KAB[Y"OZ)RB^S\607"[L\OT!7 +M,X-_6L."!2I6=]XJZ,:\`$.2DI;^[^J17=0JQS"C,%9Y)//BX)>8F_DW:XA0 +MJ.W)1QH'=L[3H>]6,Q>"U8C:1@^GQER,C8]IE(&==^5,4"O1KX2*BM7)R5?G +M*=GI9WYG))SS]PB[."62EF9N1MIXQ#=4. +M:\)\T+W""$%]+L+YY;G^4I!N#X#XWT,W+@\S(T00W"F%S0.:2>O19J<1W'K+ +MWZ@?E94=2HX`WFW_]$C13]5939$2641;!%_["(_:PPI4)$GM.L'P?62L+P&C +MH'N=^8!R>H2T?M)0LAG+.AT`C6.CPB6-!Q_,W#^".VM:N3N@L6!)R*>0:DI$ +M-Q8-&E%2L2`8*!WQRRB'Y4*#F7^6UMI1H=&+>9EG-KD_Z)0!Y97,XLW +M[2-']X7-([-0I[/D&UJE+!TS_E9N+B2A2WK?$)SN57.9J3Y%R[SRRI*,QZDKGBJ,H_YH6! +ME$F2^)FN82+/WJ.6R29$5'YR]QH1BT7@"@X19U1(>(5J^ITR$1R]H[-ZX?&X`[W\S"4WN,D@ +M=4=WB<-+X7OP#3CU@/6"ZY\,``\TPP,DONV0*UNHU`QP5T1V+36X:AQSG5YY +M2D!32R/*H$;2<9,_9#S`>.6--'+Q8NW#K$4I32ECHK55.01:OHTF)PW4K9!T +M[Q]#R#9AWR)+D+;8SR)`\"BJ*X*AQW-Y<^+]-0*'LEZFW*H;FQ1WPYLJZWU9]FV*+^R5^M4PT,!.2-:*/,9\D*;L.IJB!Q +M6MZ;7UHJI^^`+9:7A3M_]J*?\*B>>E,_7#C="R/H^_YR0*J&ZMT[]L_]O$$) +MC-=+GG$&`3?HI*Y:5$=GJ*:'CB#_\5D$PX +MC"KXP;Z5HT_H;`O8`EXWA%B7,#T<@(SE9*)A'([.!@G+?2&,7@?A'Y4>DUVV +M)&[H@*!C4%3L.2=O?BC+RJ`M78P[+Z`Y?;@D>E''MIZ/W2/[MVT.U6G%-:R; +M_9A_@+UG[5A`D-_S$;??ZSR6^![;UH)]@_L4[SU7C'BV.,M\J_VBM@Y1SS`4 +M"4\NEG+135&=6)FK@'G,9@$'/S(M:WHZKH!#E%4<)W"H.+X'7#1=&.0"%Z/^ +M#W,O;Y/H%P2:*BOCF/U?]7)MS6U"1*L,J6D&'E@&K"3?^L?7WP"PBIGP(-#9 +MUE,RXZH0V]4!5WV.+*,^VO97*D#2E'$<"Y3<*`ZE$<)MAH4/DFO7LI[\><2G +MQ_L=(2(X'ZWM1E8IGT9#ZSSNHGN*S5RV1X,#C!IA"5(*:/Y +MS;8S8:G`:A+:R+SMW"/*-&%1W%'0_7K1BZ9LN8*^TN\6=&<*)SF8*WXHF=^M3J0#-S%P57&W8"$*&:DIJ.MQ +MIAOCWG)-%5JD?+ESPL>#J_?/@W\@8.N;)->/K?MW?O@;[`$'2E)GC0>P8F*XSU2H>\LOQ;=?-D6UERYX\;S5LVUJIH6KT69I8+6?,(8 +MAF>?<:$IH.Q3(H/L=&54!)4S?:GC>\Z:\?83E'Z@&%V;:,[$6\4/`_SN@J,>H[I8=G@HPK-D)$)5PT +M\YGW7SE9$CG?/IO>R\1AM@6$4$,>.9;NFBPP6CX&'2U$M:WS:-37N:1J,3"L +M7:M",[\9+Z`FTA/,K_$@J?HKP_BX8R,*Q#9==_'.[?Z*Y6ES@P!:#'21.B.X +M_4I_/J?&!*/7\8>##38J?"F-:/X>0F_?S#&"?(;4;T\C^F%HP3R)3VJN*[F* +M!*7_VK-2=EBPFT%=X4=WXVD1XS[Q(NT00A`#MWT-[+D8?^&19X#M9KQTVO9" +M$J?W0D+IR'!DN88)->MN5#X3%<,X!?4D`@!3>_'Z<\<+6$8(;OBY="JB!Z)E +MH^A;E6G?V%>\2-1_P) +M[6:BB.O-TX)3FX-,4*0W&I-!VQCC/G4U.H +MRKY75M#K?_$?H?W8_<_[ +M&*^Z!U+_3-BX&?'[1-I88*OUA*!XJY^_H`B)[[56,K2D#J>9(=#!HY9MLO7S +MLLZ=#:1.4Q%I&%/YT6+0>TP>@^N#C_II2K@GYF7V3B+'&M=!NIW52^:@U;PR.SPADN' +MB",0;&T&3T<]*8>.27NV?Q3T?H5Q`S'C3/7J9I;XT#47K]BAXTP$:`M/%0.F +MH-*2?#JXY2"C4,=WL?XUG?V0W76N9+%]*^6EJTVMX>B`ST&K)D50>,B':8GF +ME8Y:T[4VK,#VY[XO=EG_E3:OJT.JT]&P7V%Q +M2F:^L%?8`V#I5U>MS,,^\1A=:V!TT##@"!BET^S0[7KJ:#18>1W19$"2`S.# +M\EUV"O8V`5-JAD=,^(E@/^73+0>%*J@-K;)..-."5)PO+.2+4=].:E.EJC;^ +M,"H/2&+DT",.W9E>_/^A7-O*IY;8#E_[4'U[0D$"/RNQ1W[C,2N;DD9[B%5G +MY^TURI4.M`W0F`-[!>"Q0U)K'EY\",*>Q.U#V.A07\FAV]6A]ISL,UV'R87L +M^A07AOS9.66'#_68X177PWWNE?,ZG;(ZPOFH5F[<0V;#S23FI0$2!>X&769A +MBXPGE:J8HDZ@>Y5,&N2"*\*A\%=<[^)6E45NW'`YPCKS'1F<=U'\Z>YBHV`> +MDK!ZNI[HRRL0H!CAYMRR.:=IEQN_3*:6T%S]-B;F-FB7G8J&L;?QP82G6=OE1F>G/GZ5JC\`\QNT#022P#K4?W +M.Y4/AF3>8%L"2B0/`P8?S74_9X_;3F:>BU"["^R_?+DV_B!#4]<;45P$!TD1 +MO];[S:%>/(I5@"14Y^'_9N5C(?J8%G/2[ZQ=WC\!-!6=R0C2%WZ&'&[A4GS\ +M*0[^^+C]B*VCO*[^&%P+8U8/!LCP/!B\X`*J@PA\$QMRSW5;]Y,(O:65 +MVCQ*MJ)IPW.=[T(P#TR2Y%-^H`3@_3Z4?['QW;ZU5[%"ZCIC$C8,>*]+CIZ> +M1)0JLJ&U,)NNF'^%L)>I,B@*/<[J9YE!>M.S``(,%[V`#\-,*6G"J&HW=95Q +M?N#OL\&BU(L959%BO7TY45]\%0#(9$,VN,:G>/$3\P`C<^SA7MTU**WLE%1W +MOYV<-_QEDOM"<(_S3=N+-V9*@^"`4JZPKXM='I#(L%\=:71DY$#E;.B>U(XJ +MW[R:/]_`H,S>*6_R_\4XZ(34T>H&'Q5G&\LL4E2ICK6W=Y9[=TH$RUZ?8;Q/ +M4ERXJTN*7ISW^BQ;DK(I\T,P?O4]8,X+*Z8`.">UQ'8D02HE(^PU\)Q8]`"G +ME0-O8H>71^*1!H@/!TRQND,-N)M0B^%^;\H*6G$QSH$-M%[^&>2@[3+N&S[5 +MM&7ET_J2@O^M85\"I'WL32-3GF\C57-/8X+9;2DT'#+`RZ\MBUKLX^[2`X7FO7(ZC7Q%)I. +M\O(ZN;4BN[4.*[C\TMG63$P86H_CR:4PP?X``84D6&#!@&N^3YS`=^L::5G8 +MU*=/I2SV1I(+`!=(L4Q0)@QN"W&`]AV.&A@HC7[$_PC7$D9DQU7B&:W7D&&+ +M[Z184H`?TFZ)91;GY/UM':;R(2Y'%9/]8M$;XC^'BHT;&>VR?;TZT'*/*.7[ +MZ-77>,[&2D7>H@4A84`AN-D9GG]RGN[-9\Z+8<.GUD7-K(<;D/;A+DQJ>L71 +M\[+9IBA^2N/@1NB6P0$WLK#/`&JV0]^99``B(L7%659I2^?#HV7K^"DAPA=I +M4RO2;UBO"D'4/4"1`K[JK)K,"3HI*V&YES8X4*FJP6UN],#?#]ZC]$SZ&%]* +M1SWR'<$"#>GB0'.VAR;P>0Q@O?)1C)V5[/"Q]!&0CXRR0OWM`,?:4D[0A[LL +M6S*1@)1EI+<)O^0&YL."_4E.C113HT1[7N;89&C&>V_!!->N6B0Z!"KH1F>* +M4N#E@[Z.S(! +M:O`3*[=PQ/J*CS"&.E*ZWYEYTXUH1RW5J"(;O_7^60^Y!K$;?\#**]520!KI +M`-BM/]U!*4_%&WLJA=8KS;*Q&U#ELQPO3^A88.>WGYOC_*7H^][-^ +MHKP"_,ETW@F\*D-25J?^'(6+6WUY+:25*J+SKN39\VF#=YOJ4)BUMRSD&G&3 +ML+]3T0S\C/-^RO&\+_,`PM$>/?%5O]<.:5Q$!JUM2?:KW-/+H>H\5ANB,QKV +MP0$HX4>4 +MEW"A_8U'6[/26\Z%O\`:6T^&3BF4A^"#FSS+G#::2=3AQ]N,FX*?[XV6.],V +M[N"]=OEHSD%CT\^_7>[(AUF^1/^Y^,DE?E*?IEP9LF:K_`C;;'@_@(-Q9J8O +MYL<\ML2$6?8#J6;-5\>3.X0:]N;V/RJ2.+>D*`^DO"[P]GQ`Y97'TX=!8\<_ +MOMD.=OB:@8+"0[KOXMITH'S6&G:Y:/1PA5=XFW"D'A'*IHMD7"NSGVX56VGL +M**?E-,>;VZ\%-"3%"2*U>8H'8]UA0-QXZ7=D/BR*CI28TX+C#&*5.Y7GVROO +M+M*TOS$"JRRSN7_O/JD:W_NDF\D:MK?''RYLLD.ETR=H"$#J;@'?L,I>X*E6 +MRBW7=U1IB4^*$KH&#R/+;?_E#__?D/I[+5F(:1Q5G..6MCX3TD@P3+-[DTU. +MV\-(=`$LJIT2J>_S&3@+7,?]6Z9EILKRD8,NJ5CI#IJ[)K^K-%D< +MH4/-98_V_M/<;<.I5JS2W@E\R4Z^@$X%NA=F:HM_YR-S)9("6:">;(2S#JRP +M9,KX,8&Z4D"RGDW0<5QRZE@D@'L0+B=AVW5CA`W^\GE%E_(@V!R]\BG'Z]_F +MT<_DDJ-\GOO"2O\T@DB+W@/00MEOX:TUQA738=5N*]7"1ZA_G3)1P7(Q2%\Z +M#=I4Z(9XF0?VO6R<)%RQ.+EJ,W$H'27*H*XLX?K"413*?7O7BMB_N[K+]!TX +M>$/=W7O/7(F*D52=?'*#P36XY=IFA2@1])GBD''<1*P>U4'=%,2W.[47%9SL +MVQX]%G>1><2H-\>PFQ(!+RX=Q^/8+8:%K+=Z`IIZ>WF^`0>AO)MH.]9'U%]F +M8)+;E<]\![YX(8Z9!&*S#Q:FBI7Q4Y14$A4F+GP:8'FE_G.@]QM2I\JY6_^= +MYH4M/+/64YZEKAABRZ7Z(2E6OCB=WP1TAF+Y?'T@#"N&F"_W4'2I/[5%?3^L#E'"9)^C3]Q +MC55CER_]R.E!Y,=98K^A3=B,(+ED2'OI?&GB$$2&/Y!#,)Q@CH]A:,SBB;[% +ME\&T@^!,,W:=!7=5(ZX-V3\MZ>A9A@KQT$C>MO:C[Y]$WI\&Y;,`=CT@#9J; +MK\=65$6"(S3_;D;Y7U]5KZ8D?7/*W)XU=#IG%XBRMA%O%3:B=!$-Y\$NY88@ +M:"=Q=K0[G4N:8UAQ*-.[)TMBVUP7K$'B+G3`\R1H%+9A`"$C,/D.O+M-3/7I +M]K9$$M4:>%C+BK^C(&SZ[MCE=3?'0_W<)R`L4?0VKT^L4>[4-0PG43P\%C/] +MG@A<]<5[5AN!<<9A2(>X`TFU?SZVAJZ>V[]-6O;:EI+F0LCUPHNS+R^'_3B" +MY>='S;=C#*U&-0@0(&M7B'1?<;T1YQ$)^A"+]Y]O_.)Y9].,?%/P@#);5\DG +M4H4Y"U*6!`]MKX;31Y?#_[LT]]^COR:_6Z4&S+CPP%,D[U>FJ;CL1&5KYY.O +M13"L@`],#;92H0*&0F2DQT(,ED +M2\BW=RTHS8:9N-GFO_U`UR-62@S&Z.&GF'#K%:V0W5>MZF60@`.P?>I7EHLF +MV'GRY$45.VN4++GROX'..P!2XPPD\^BP4Y;K;*T_0`=WQ8V]KP_/<7/LU;D(09=L#5T26+NJYT +M05FQMSA2BND0HUVL.H9;Z\^Z?-S]H.-)HOL=FR6&"XN;XTM:-60_-^?30S`7 +M!-QN[!@16G<*Q\*C>,OAT04\"NTZ5DQ=?8AO6B__R-.D]"F$5,3B?X/7.M[F +MXV;[CH6>>US2[LY05+BB0>)8+YR7[A#PX(I4RI7B!1Y$:/?_.H/A?)@:",*[ +M->ACN/5_]IVME$#[**8BK7GC;\?R^TX!X:D)(LL<)>%(*Y<'LCEE8,=M,L`1 +M98X8&HF@G1T'3BW-M&S_=]7GG(C+=T!`B8][O=?M9OQX(0'B^S8"0R(&0Z!$ +MR&-5E[N +MH@$Z[R\XF\I;8B,6YT'^NFN#H1_H!\)25Z1.<'9N +M\4!Q?E3[\SM%#H[;4U7+?V.N$HO/CFK2FCB]1N^9OE06+#I]?\+#T.,Z*:9] +MHW%7I,Z\724KU3[KDJ#J,DE./0^]0PF(U%T_Q!2YF*3H.8FH,#/F#A^M9J%0 +MWW"KEI+ZWS>[C-RGG@9[MKN#86H0AM6NE*HD\"G:S.)]S?(79W +MH71X54YJ_#U#@%?K@X^6?JL]])(1;>L4;)N%*6HGF)O-_;9/FA4":H"HZT8* +M*JD8"UH"I%F^/8@,O'A(Q7>%>!I?W\5S13XN%L8,+?Z\,>M[//70-ID6N-2: +M\5QN2<(B+WC]^`7S?>QR*^$8]:RA>WVE>2"@>Y'MR.ZT0T4W:(O@R*/E6EEY +M_B6_X?,*I"R]PZ3$(S8!A[2B[0$\5>1?WE#Y&7T^&]##'6'U:_4QD2PG<5CL +M3G&4K6-*15DF-/)Q0=)RLF9P/`R6(<%_8/HFG=TR?.]_ +M9#-NZWU:=AP[G"`)UVFM-]QN`FFGC0N@TRN0C=WW)]9T#N'#]R/YK`'?!RA$ +M^%$)VG=)+MF8L2L?N&TV*`YN![(-BVQ`VFO]ZDYBE>KW.D;\D&YHC#Q=DP(T +MM,I)P/"C#Y#,ZR+/M89%OL?UH!LOSP[5ZK=B;VWB#13N!VN$X7'922#5\MY@3R4DY*O)M0K_#R=0=B:@J(LT,.Q?^+OVU]"D]\S8&KVWJ-%C**.MQZ3ND8^'NGQ\#E;B+.4I`K0.II[!,NX=5V]/2U[\NA_:$ +M34C7B(%S$'L\7Z+N$BN"R?^G<^J?&0L*:O;GFL.F@^3(L@L')<@#V$F"FY:D +MF-,@;<_B,M!B8_Z#Y<#ULK#&_$.'K2*QA"T)6Q-O6X&W-,K@/DN]\'54,&SX +M;N)V_(UM8XCH+T6Z?(9NB$O:L?"V,]QMQJ:74*C$ +MW')5])E'S=CK2RVS9_)XD:+BPXI4OL +M#O])L.]-!9.CHWE80.*Q)BZ0),J$;I?K5^C%).?AY_WP9]G3'@";AUW)1Y/$ +M#F\LQ>,V"B/+F^%NY-GA%6>)*U4N:VC$P79CWT[<2@F@FQ+Q#N/C%ES@/D#7V(W0J<_-M[4"RYP\,$$ +MC9P?)[T5=FY:_!QRA5+08[#Y4M1PRXI4(3.D@'@1*K3=YN!B8C3@J""G(2Q3 +M^T:IGP%0%F:<4DI1E/5:D;..];=3/`N3I&IWG15O)=B?GR=6FW$F.]V8]]S= +M3IYP$O66URBI/$P$AL[UL]-AB-C84-[Z'J[PV[4WQLPPX*WQW_)G:*DAP/&/ +M#!39C+''V6B-0!MJ7A)T2&AVG( +MQO_^WX)B\_1H\U=6#ES8[G;./%!8#'+#H]X$"^C=8\`,45S7ZI*$(<'<_ROVZ1U_/ +M88PN(C#X-@YI6!,>U[$`92U6I@#QEZ^Z$],XN=Q2F=.L[REV;VO%ZQ"EC\NY +M-4J*@%:/3[JG.=$_%,6!M:[?P:/XA+KUL_NY#U%<*^#]>MVCUY4(A;@C[_J: +M]`,)_Y;UVL&@%=I98.F`Y;8\X:]SM9"*U?P',-Y9.^1NR_EV?K,;!<$+WB(A +M/G$=[>L5W-ZFI4!)S6R2+<+0[HL!WTDOP_0L*WX+`<4\9`JOH^@7'W.[H@U4R5;)YJ6@6+9(#T3UNL[\LG&J\'NS+G6T%.!&SD +MJK98G[K.KY^4O>%^#_+FH6"H;>D-*L9(DS#?J:I`@W+'"8ASE"SB^HDP7KQN")4VWX[L7RH0[7WE3(FW`DNXY2-:T:M]IG +MB>8*]RJ2K:*M5H^V.)H?J2&JR75*\CJ=?7FU6))S"S[%H]R/(;V-SVO..-+EZJ!A#D^W)^JN^!C3FBHXC2`XU*8Q78^." +M=BUM`1)\(X4TINM)M/._RLSIY839,?]]'6BQRB]"+,F^(^P?VO=1=Y^;3%,=1:=!,)&P;NH +MN4Y&U&B(WX"=IKWR%;->V==-O,&'+>E'(()CS!O`M/@7I"777J<*OV;3(XLW +MS!<_%).-PMO[.8C0`'JQ346U=6>I@+UCR0?L6Y1Z?=%E05K-I!+V&@=\%[&4 +M`/.Z06U!`%&FQ,)C*=CN%&P'QFF!7)QTI7?G\IJ[)%^')F?2+#V6T#2I=M!D +ML`;(6"S;C.+A-,$M82PTN"LIL@%USN#?-L!YW0#0/\];=#XJ"7/#GR\/I#*E +MP0.U,);PY6;+_Q/TBA&)%[$9%,!]33XZG$*>6,6I"&QL6E6_7%6L'V0LPAIT +M#*H*>_Y9(5.CD=`7]?5S5?N#JF>:A]&WQ/I=LDI>697TEI/B_&8AUZS4ZG0_ +M4&(W]X-X>6B1(U"M/K*408_0>\C3\?^!V(9DE:MU+![L,/AJU!VF)CBXX>H3 +M8_SMJ/N79D#"B,D716D,71!AH/ELL)"=\8*(1^H_2VYEFE8R(GK3-LW;-_R2 +MB=W^-R)=XHM58/7KKTP$D>V@@3$-7\ASFDNIC&OS6[=3_Q!5]W57N?8T!Q^87RFRH9W?6I:K&JR,E)OGNY+"U^IQVXV>)9_DE>K:Q,@2;ZM+?(*KE'%)!*:W&XXP8+G +MR/4MC$KRK;X.RT;#C'/JL2QKR\KOXP]8@\,$#%.V.16`TZEX%G)5LU0IP#$D +M=LV-2?*XW)?RVE&@'E=RA4&J5+GQ\815WIB.R('WJ*DUG=F]T;^6*A^,'R(C +M(-LU;B`M0(3$+`<4"S#>WQT+W!#[H)D?@1.W"/9YUA0YJ;MK +M#35B(,3B;GMCQEA[G22S%E!IA*;()1KHX<=SAD'%86@`V:29.R0"I@]WKA3L +MH(U?X*6ZPS0+G?W*&<*THX!I@MGH1F-$1<<(9?8.N58[]O%$./$;(9O7<=_6"\BEV`X0W)P9^-N2JE%QL)K)LW&4^D9C5.IL% +M=Y_Y0727^`\K],HSVQ>:S&LW_/56U+KTF\#*&(]6KP;N*NF\8-(R_U/)<,M< +MU:GI"=$=R2S1_=U6R[!U&TX_4[W\G&OG]$&N +M_MVVA5=/64':N__5))"Y0R*HYQ25>'`6 +M2P32:-:;._J_=!"F2%,:AJEJ0+,MW^".S;,*[L?9?C*H*+IN])?'ZWK09NI\=VC](<:M +MLE!TE6Z/@5,D1N%=3L.O&BS6PM'+SY)T>_@^8EA=,=_S` +MH3@WL*+JOXOUC":2SKE4J=L +M`4OEL8Y&97HV6AP"L)@A2J&`-_&NU852JU<@`4%0#_PV0-:[*,ES@OZ(EU/F +M@U7BKDNA@(!>VX3V'&2NTLZ?S&E\P0R9?8"<)58VO)`JHWC&0@; +M;15)>9ENTV"D$RF@QDB\V46;^K6-:#;G_"..8 +ME5IC^#-:>E]Z]+.W97Y-J*20E"0S9!5L,N0&OB#=IEZK(<,'W. +MLSY&R+(#EIB__U3V'L#C,.];2+3$Y$R@'UFV#`>ACB0O:W\H;4(%92]_86/S]G5YM$NG,LK +MV^_O\H2YJ),=KBJPA4,R-EXW:9Y[X/H^1D_2LPY03$3*S@3I6E1Z=A+:=])T +M]E>?*A`N%=:P>*,Q&:[M_*:IJ(LC`M?O%'U'8"C4SBDR<9P-SWJ1DZG2MPA$ +MD-Q(F+A89>!Z8HO+#<-4:R9CIH=P5:,U1HT"5_@Q*$G:;2"KDW9ICX$8EP#([#W@>[<6L$H_BB5:U#>RH(;K"SL^ +MRU5"911=Y<"F#?V^%=;#2ZU*=IAQ!A,O[Y04@=&@.ES\,_$;NN)RFO3^>Q)B +MV,02;<9KX1?8$OY`#X>05\16F!:Z"A\WU*L8%;#Z`CVP*'CKH_:W'7.-&+Y +M:&2T6+*F;VPOM&F+?5\^WE,B+@&HHYE>([/G,/"N$SKJ1*+>D9I@Y\#W*8\Z +MF)H)9\<&<*Z83E$U+]R!A(),0KN7:1,2`9)DH(<7WGO*3?@\?_1&PXFDH(.@ +M4429+;\4:>>VA^`IV#%PP0N84R9W/K^^23W0N3AC!C4T*M9T,')"4)_H=!E> +M=*P%&U<1]%-N62VY'G62,W&6,9`C=RO@AA)TH;R8&?4-%J@Y3=\MZJ8E$.5A +MF[+A(3ERTV`]YU\=4]#'.6+$K:))=`P%VRE+MLYJD%-B?B75?^]ETNQ$K%(< +M_<^BYL3S7\8W^NG9@;?[0-O2#4JF;.UV3?PE+K;1ADR-43>P%E_\V917%NNB +M>:YC42T4:1P*NPKP%Q)>GL#VK3-O!T]$(Z8W7)+KT3`1X:F?I4HI2$7P$AX[6!XZA>IZBH +MZU:H//WH2*D!AFH]/G=M::L\I+" +ML.32Q;Q=,ZZD_<7T.AD%P5M+YC5\HI`>=:Q2,7L&YR/=6$R'=]9_3U8N50\% +MHH$.T]7G6&8[2F7RSZ$V>V@2VK4]DBI3J6?X2I&"1W\I+M27=73U;THF54(: +M#([7.GKOC9GD46)GZ6(;'8KI/=/)'F!Y5O?WS-JJ=K>/M7OLH[54%KQIM*-# +M;AE*`2J#^>?$W#QBCUVP51CYL$MTKHNFR;VK.4NW@.5UO=+7DW3X_*AC]V93 +M[)FA-T#R7S,'T]Q@^!=W$U/,+1'54J#I/Z'Y1^=9^GS1]VWNM!S>;>82#A$5 +MW=V>0GG*^9B@#`I5F(3IW]Z%WL$&N'9#>G=<*6Q^5K<=/`1^[TZWKQ(:YGH= +M7\ER-V(XOY4P=4_/`"?K4`I15M$WS2O8""=++&DOMNXDSI)-E*$^_1DG[-0\ +M&*F3J5#&[5$:@E*/I9=_ +MI>\`^CUL&FR5\2^T_37&N9/=EJT@;N4#"HH1^JS$VRG8]EFKS07LJ@;26D14 +M9.5J;M?"$NM0G]K=>#K-,WO]YWD4?*A>X`65;_AHUEM2QW'_"!/%JF2.\ZC1 +M`">:OA!+7=1I$UWY&Y9R%N8<2*D1>'$WI5HB=#;X>XEWT-8(3T`VX):V#Y[> +M1.M??@V0F_+?E4\I/JR"`@>EVM'=`WX$QPK<_Z.?UG9)UN2#OL741`IDHCCN4WTD_1M!TS?WM':?HDV8P]W)NVMYG2$G[U$L"2MW +MNR/T/YK8)$-]@"KV<2+26`((BIC!W(3]UW6$FR?4_[C0-_/L=?OI\U27N@3% +MQ2NL(UWB"4.@LG`/;ETNGRSC>Y8R]EJB+`/%R[O31,_0%#*KZ4>E#"'CGXC> +MMMZ(Y>".$*/5W3+I4GL>JKA:MPVI5=9IVL#ZK1C!]?M)HS=Y/-0_O;NPB;<<2U*.18@ +M.%PA5_YV3&^8$W4?M=0M0!W28.)H-:OV,`0([2.NXG-5W?_6J?6$%P(O'7WF +M-\<[0PA=7GC=78+W'M!S('6'NQ6.@TGNP$?8X@^6(+F7HNS8%H.3F^ILD*6- +ME+FPJG%M?F_=AQ0V#0R#!6)E0MF-*WJ:T-)]Y&+/9A'%:"0QKLXD,LP8!\8Y +ME!_0B#U_4I21D:-49Z[W77D"VP4"(G7=GVU1N-7#<632'VXJ/1T&R2*C>Z![ +M'.<79$=/PFN=B\M6(GB6@\A^$R;YSRH/\]'54+>&W=;RD:(!/D]6L^.^\[3T +M.3S.4$*@-ISY,_^_8VOF2AS=>1=3"H!B=(;U##9OGS,=$7 +M/..[U!^NW-\#(]Z%6W&I9+K+?6<^[V[A=B,O,EEXPX:X@K8K;3#:.406);\" +MSA?")7YER;1')^(?3(2:H:7*(]WG^*-:F7ZLJE?=M3;:*3G:&F_\PF_$*3S) +MVTT9_R0($$#!@LZE#M_OJQ_'TID`#&PT5LE"W/'QJP2&Z:`*'S2J&12KIK?L +M_-[R\'\J)IB&!K;[R@6\-#S[!*3&VF<*><4M9U`$M6B%'/].0X0E%\B\RA<7`D#ZF'1Q#BVOZ->[A!`^#FRDNDRJ4*4YA+ +M>U:AT%!I:'FV0NS(@`HJ``U%4$IK"4THS6[M6GC,:`_*C3)*98'LE?HMHX:U +MZ#K+A'[.$8FCHS4UN++C_'(&Z#7+TU+KZ/,(NO!G043RI7O!(5C8^4;XV\V)?GB$2ISM-)<&1 +M#%IXS%A]4OI#!`N_^G5_H/HSV_\!M@`7+R[G$M5#>3(`-'1H]YK:$%L;+G&1 +MP>FVA*H>8O)8K%HGZ`>+^8I"I)XMIJ(`9Y;3PBR[G/V&)W64PS&NS_49_:&Y +M)6CS@VFFJU>7J)J9GM56WAQE5Z(*5D`@0.&\)8,_O$;.9;E.0X8I@?&('7** +MO\-([2LA"B1TAP:6)*@1*HI?!85UFPI,5&.YIW5^9?^=7Z^R;[KF3A^Q=EH\ +MMG(ZN\%W0,=7&7/QGF:/7UHIM#1@@FD-%UY)JUDIC4&^_O7UT+.[+HTD\OI8=/B=AX&D13.J#/!/87B@D4"U51RDM= +MG@XIN.0#DG25$). +M,UR\#!:4@)!Q4&+>TT6CDHEB.O_\A*&@K;$SX8OBMV;*I!,J)`,-FQCC<\IATE#8W?;)447TAV.>8D&:# +MTS69!SOK]:QIR5"5%QK!P$SK`HJUB++P%1&$U/V(8%.5)9R/:IK-R,UO)Q!^Z'^8/4!=DFV,QCU( +MB;3D&]L\*5`%3.;MGJ*<#]`H +M5.1..'!R[>R#\P#Z=/@'H!`D&GM&KP2WF&6#)'6H[*;[2TE;A0M!H6PHB40^ +M3*6U!'-'/*@B@:=LV4=63,P=_,?J0LUK(A1>,R8K%"OZ[1'G\GSHB^&M,^'5( +M\TH[LSRZD.60>:`Q+D=;N`\0&\T?@TK!1:X-RL+A]A,=\4#AR+S8@[;G7?0> +MIN&R&CI>>SO'QI7U)=P'C:TF_"V'8`Q\L(MLU<;LI>]KRSH3,[]9?@$3&L6* +M[9I=L%C0\Q,.H"KK>"M^+/O20W2_@1#MN4-Y4./?<#T*!._\)-C_$9Y=+3.V +MG!'^7\V`\L`/XP-3I[D:=9V2%%\'=*4H$CZ+&_3M2Y)9-J=L([O(S\+^R>W&NB\QP0@;DY(W^Z; +M.T4='348*V"6"`&`F1@#:^]\[B\E<-Y*#J6[P:R)K@-Z"+ZAKSZ+]4T3U\^\ +MA\WEA?17G!%&Y:F_UG\H\/=./XYYE!SRAA%K_Q;5W4:^[I$*DH; +M,.0I2VO"JS9"*$+":HCDFNBN!>KM^1G5[3Z*C*T=;I,(>?$-K**79M.O$OL' +M?DX+E-G@YI80$N*Q3^>))&QAUU7HB-908\XAS,\N7'#+W83$\T)7F/8IK$H/ +M8D2=VKF&%XT_$H4QN`,S_?(RV-3T-OWZ'V6(MCB?0C(R[OZXA\"\T[U#5.(X8_S_22B9[?)4$UYT/FC"YCZ/L2QUWXFJF +M#*ODE/5\?3:KH##.C91Z/7"\A]J4F&W4"!HA(N$@!]'"\,[RV>[XEV[L9+'? +M61A[(5/TKT]3O[&V)"4,*T378[]S?#Q#MWZ-66H6KG3J_,(F"#\//4B*"<%$ +M2!Y)]/D(P3VDZUM>8L:WSQ_3DF2:8-.Z,E(E1E29NO9A0AH$GSKSZ)%M3N-M8;8@(I2 +M:(385]C(62++!?*898B![P;VJW>H3XN817L7DUHU>.VPVH!#/ZK=WHSG_AQ,@%):HL)04`X4X%GM);8W5Q'/2M6'&7R:"CUO4JI1< +MSD+<*E4\*U5_Y!48,F8%%)8;=?KY"+9*BKFC[7S*J\UF:O/*9A_PB4X17-OY +MFV$J0!25;B]T,>KNXLV2WA`V*3HL7N3-3PZTD0ZP.Y\G70]L*&%QL'6U(:0T$1W5STH6V`U:P-7XZ+#32(=+BF_"==D1HZ,685I'>XEYU0\Q_ +MU4;JE50PFMP97"80L[?\P$R`*\&R!V0H9M0C$.Y>/0N*@@QG^75_X7G?1E8" +MV-^JPHB"WKX0KB%[,/F1RM$3A:.V?OC7W%W,YZ/]9(5G=#;%6T]X,@T>?F11 +MSF.D=CRU%VPJ9R42>FLRKJ96FZRH9J:R^C6_HJ<0MQ3C:`L08=>B_HKVQ;64 +MV3[!&(8).C>6T,9=6.F(AK$5!X872-;T7=_S7F9.=_3OP)#A/P,NZXET(Q#@ +M>:GF.#(Q`?=.KJ%9;$Q,$H5(KHVP"N=3`B8TNE`O`[%YTQ[?2 +MS,BKC1R.^9U8(_'-+"B\2P`54Q4#U9"]4>Z-B&V,BW*4K.=Z$A'=\"=3R\96DZON7\[W1PN2*+ +M2UGVR=<$[HBDM$3-:[UL +MGZ,#T;)M1C7;M;';;L&0IXXUD/YQU@:N[;]:M9S=TD>86KSVH$7&&3U&$?19 +M;!)P3M7V62==EL[/QHJ+^R]J(VZZY!B.BI(H6QGRDX\X3X>,H,X4U$\,BQ*+S56")`"\BKEQ*Q*-DU\P8`G%- +MJ5M(X8T\B^9URX*&N2K5[10_-AYNHQ?M/?*\@81.`'9!EL`V?7_[@9,5_Y=S^SD>/%J2JY?K\LF@XT3A,FT?7FS:6A$\% +M(W_\B27(MU'/2LTS8U^>&1*^C(2O:0Q;0Q^I(??(U#X`%E^@*LEN!Z!?7>G& +M&%1%1YO58XT.=@./T&,[5-AAE1YBPDI_/9#KV?_#IA-DD'X]=?D#NV?A&%,S +M+MJ$A*V.`U'AHQ!H]*#6BM5-CXUBH6B/"$^8A'6IIR6HH5WC;O/IY95;,^\B'T/QN-CD9LRG]Q%V%?GB1>O[V<;^X\2EK:$AYHT +M'`\]E-;[%1FFH"J7YSO5$Y?.3\/MC**U8`0"J`T3R.U[0S4D\DFKRK&\7;B5 +M78J#6K@$(?^+BC7PYM?:9)[(FC%1`-*E@46GZRRYPQ34W:]*X;VEMS__H$3! +MD]653965P_'/_'$?&ME;MA).H6L]\I>EY^+CW&-5!T?#O*VI]`?(+4#13OU) +ML:H'1+A%(_+*W^`AI_V`O/]=&4F.;C8K#ZHO"S]QS4\1(Z+*U)^-(JFATFQU +M=,%AJ0S>)G#R%XU)H%<)('VA#/>L7C02\ZV4W5*)$$#EG`DQT&,K?TP5B(/W +MOW>R=XX$M!E301$<82/TI,DQ(^P18/$N[]2*-F,(L5E!7E=M!)9HGI%OG=$Y +M];2`4JT[4E.BCFV:4F>?\@!?BU#O=B!FD5[Q[`HR=GSDWTPHQ'G*'BU4H0`/)IW$`'T<4_(EJN\A[$9W$ +M=C`)G:WIHJ0X[I.1_EB>?=T9 +M-[M^UF8L;7IJ)1>9Z"]&=%2!I=45-\8*B!\_V=#'E`;VD)Q>X)ZO88`0UUK6 +M3M(*R%DM!`-0'`,ERX0GMBA!['BL&PK)%RDHNZ'F;BTN%V_"Y;ZPM/*4C8[I +M:PDD1=C$#JPI:*?-_1E%!;1\6/%E]^!YH36[WF5K5LK\;'2]2!H&C)$^JDKC +M7=)0648#!%)&5WJQF8NMK\-4[&3MO26>Q[@YZR.BSNZWX[TCF1<\@V;KN_0F +MI50]3FYJGR&\U.Y`+&=N:-HY2;I`Q,QL3"`WB^3I<$'-H1Z0GO2?><68!.SR +MSWL8=1+;&0@`"?[BYIE]D'JB=C=$`-(?0:6*SS#.AB*,..;E0%VZZ^;7=-Y' +M&D'>/FX-7,&^CP\G1\D=YT3G2=5MJWF#\U]"\UU<'%)S+<3OF$,$?!92.F'O +M@&YM(>.?+,'+C^T#A-\*9K(_$5M3=8:BS(8>.FW])UIEY((3ZJFI>431FZ!I?H,D+W7YNQ!DEQ8:D!SR$,ITS#R +MOEY,55%++BNJ7'R;%T^U-(8LZ.YG=8)<,Z!DA$+%#Q/&`>6/1D%F*D.V +MCR6+5<`B09HQMV/AIGX2KY'P:U8PU/S[5*XZ51\:[-TDH#\63'9O"B_,V;F' +MDKF@9.Q1&BB/1S2[]O0CZH.)4JI9ER>.%=+*QM^_=GT]_JM078EK\JQ+?_*I +MN_;Q5^H[5B2!S+BC"3^U5U4UPACM)]8PW6UI12V4?-&R;!#`"#8H<>9W!G+Z +M5NK]_^HAS=72I6_ROC@^D7ND?^+&NI#5`B7%=F +M1/-FD[*(!++0"!T81NM;A'_$^C*[-PP.(:#$???(FZ?VYT<@*QEQ@,"6!CN1 +MKE6$J?^,\S#38J+R0EA*]!2WG#A572_@:\K`Q%ZN&FY)TSI4`TKK+TGO^1[$;B!5DVN&7 +M/U$K'?/GE\9C443[\"90MI0QX#XJ=IVT\PR9PY$NW]G'I#3UQR`K?&??SA[D.=I` +M[$`WX?@GSB%5#:$G:YQ^1O21T^%E=#D8S;,KLZ5LYL;Q_UFRU>E(2!'^ +M(=<\%A,JOLWGYX$\0XA63R\`";OP5!8/\0A"9I:94FG-OK`]`!,/H)*]]5$Y +MIS7'O/GDD1W#2A/$Z7@+\!?V,J%;_;DON>R4MQXZY?C.*MDAR.!$RVZTJ7,A +MM@UUU."4!#<:)#W_Z[QQ3\ZV.Y(HZ<9JL>0#%*W"0M.84;'?Y%4OJT.0,3VV +MR!W@KWXE]$Y)P7]!D2Q#93B6O-]`'L6U1Y4'Z:/BY"P:#8)<^*,(+B544P0" +M2V@`O)O>=&MR`M].(6D5D2L%0911/W4$37K;V6$0Z091/` +MS--6SN2.L&U8;%N_&%G=661I"^C/FA[BR$P%=*70B@'#<;_"S>V+UOO%FN2: +MX%WRJZ$#'*/R?X'_`*HH+6],%G_I)Q,+5X6QFW*J"`T]2B5KKP,"#TR"JOSN +MH.E^R)"5H[4>N$E!XSXU7[#;'1GS?JT#KZ+EGCC56\,:Y`=2^`^Q]:R4UK@X>O+"=T"!L+I +M'5UANA)EG[V''8(B7X)<&-:-_BU$^$^_RJ)CD%U.)`'8D"_*`=W4)E?P"-Q<76BX3*"CKABLK>DNIL6J +MA=@K&H5TR3D4=IZX=?B6&K:UV=OE3@_[NB8:'A]M%XH:+(-<&3F+"G0?4J2UYF'UZWUV +M:']0')6^-'C.`J=Z*_=_YYT;`'K%*A)VF4F_\;5[1%#FU^H>E-WII-:9/T'@ +MB6K>JG%Y48R)RMGFG2!XF;/%>(0^_]*8SX&P._"2E:59'2]LX/CE9)?).IUG:!71)8>[ +M.P(29E6(VN3,[XZC."/7]`SRS5`%?=0A+3)U(LJ[T.KL2(C*H)7:"F1\@PC` +M7)1#UW##Q\1/2:.RRCJM3H[FC.A!E.P5858#Q_+!0Y9];A^I:]&@`'$YF'[YV2HA3:7>1S?A4 +M4'A@P6U8`$WN\=+#93,LO,F_VFLSEZ&/WL&^8S\C_OE5@:K%!4^^V(=T9V:& +M?(33X#:9.J*L9^-I%2TBY(M4(EW8F:<$T%C3S'`<;&`!BA_RC+V=V1Y`XQ,, +MW)?1$%C^S/=P/R)KA4-&7>'Z-AKR?SU3V1>`*8LY,%7?LLCBG3\OWLH#G:8E +MJR:5+Q[^NY62\@LJYL7]CLY8CC=2:V44:9/=`*+\6!(9_;^!HJC;6^"ZK$Y< +M'$98V(X'<"5A#^CY76;)V;U^`H>=N"*-E%@N06]^'G>P_K+5!WK:'2G*^=Z! +MCSJ-6?"1J,@$#`+6L`3$+4-$E=[16)J+JR/IV-3.)>X6NP\]"L1,:#$^]Z!L]D!W["P`D=#%H74'PW9V8 +M\+IQ[8L'M&D#=LJE>H"R2W"_=RY;"=BNMJC()S1/V"^+!-!4*9DRF`.ZZ,SZ +MCAI)%28)U56A!U(;U@N"%0K@"LC(BGQR//LFDK3OI4\-Z`=AF-&=^@.7VJH! +M`MYS[,[T[`4:Q>[]+Y;1E\_PF"BMRVXRH+'72KA5M_O>*5U6Q*H9.1^=,=). +M3AZ$X&4G?-5KD16,:/[B-7*&V1,$V1IT!9Z:LN6IDO&+CR%6,3\*9W+P#>G: +M&HOM92&+J(O*Q,AUBJ=!;`W9(;L],5J[$=(A-!OT +M)=/N36=W616"V81VV:+0XIO"/_>_$<),IC*`/M73]`$2?#2^RVI'EI0[0Z+: +M_1F`S+RO?XNFAZ]_[L0JV>:8>+B.J@X9TF,UNRO;*5H(&F6FV\7S-@JH8_', +MO186RWGW9W1G:[P#7I8HC'*E_SDBPP!Y\R6BN5'O*55DSV+=K*5K"::H($8, +MP7_#&C7CJU,[M=2"<88U:!9W^9Z5D"M[)&(]M8R92\Y"RBK^-6Q#X,;U[/G$ +M>?:RFIOA6Q[B!:\!4K`C*PH2PG%'-)A]H,^(LQ=U3[/Z45Y6BOCV1,Z3;`; +MN!TVCW44M;+4Z_$Z[H)^,PT.LVFDNR=&OW\G">EU764&")[U9$X>+GS=P^GC +M386OUYB4I0B9DZWU,)T%;94.`_?&(XT]`0W1%YJF]:R<5-OR8B86:$F/SN`0 +M%0+J#33Y4XP^)>E,%2ABTP8)S/!7?DVUB0"_'GOAI,B!0H6FIP):\UE +M^WE?"AC,52+_E84_?Q=[9VN^8+,GEIVBR6J4SXI&`GZ=PD1HU9PE_&M-_\"* +MO9(>@2!AHM>(+M2^QP#$@$[0H5U#CVL*5F/B:R(0E60!F0!S\'I[2)/U_/<6 +MGZXBP1(C`HEO9#TBY2QRJEW65U\A(NDR6GL9::KD/Q^]^,TOKY#A_7K;'I%D +M>CNFB!2K`5_J"D9S1("FR5-8-Q`,+K%T#7RI*)L`_*B??_O3\;!*1U +MUA2M7`E0_A*@T9TL@B2^YZXB.9 +M)`;8BH-QJA8%N1Y&9\B:\>4W;JO+7=%0'@[YOF)J8`+IUZ*CK#+-Z1,*9O_Y +M]C&3F;2YVG_;716R>V<@XO#SC,T3,6N9D8XJ]5']-X/BUWP=3,?I&#`=S#G% +MO-`R"4SGIH.P@UDLYMR9SA&L_]C8M9FR[X5.$A$+9J4%6\@ACJFXVXGBB0") +M__$?#NH@6-TF`'EG!$:K(14J)$[`4*DBR;<_'JV@)ZRUC)3(0-_G`A4D!OTBUH>AR"G8(R8^C[-Q];OR)I3`E+5OS8#M8Y4#/G,:OFO])`KC443=OR9% +M7[Q$-&RFW\>)W\L@:1]O!-[.US&B:UY^>[LPY^3PX#`.ZK1I-Y9,'2B.PLGZ +MQ*?D@'DX+&NG>C>BJ@P +M*X9[1WH-YMZ9J?RYBE$-&`URJB5:F25=#Q^BYZH0M6%NC'2R^6=',AO'4E[3 +ML1>/\0?[ZA?FB^+\30KV2G?9"=/SE+`46V,L&=#IK@J*NFV9B&V%OL,"3`P% +MREHP@")IHY]_MH/,5Z[6WCV;[]_Y;7K'EQ6E6S)MHD)1T)$X^G)#+56]D>>V +MS*X(LXR7:TT=6NFBK"'#[F&S)H-D4TCM%*'FE$G,*11-\S6&5Z1OEH+Y;AX` +M8$&*N*#GA;*HNWH-Z/G/5_99DIOZ^GL0[&:GPE>8]5Z&5F-9YWN,*]0VHY5= +MKQ$:>/-]7R7O2[E*X`15TG90X'LN;8?YK0S(@/^OXBE:'/E?EG;E2PGN#EA` +M3XH8,;^<^-S=.PO=;21N$3'1@ +M[-\[?QRR-/W+ZA]D.H +MC;-=Q2;Z_E\KC$HZ)/7SD\M5A8ET:7S^1ZZ_8=ZMHWMIPT8#*],(V.0M-UVG +MK2=[.XD^#U9-%?FP%=^^M>7LWC4`M?=GTD]F/JQ\Z0*3/J<6+G1PRB;H,O7I8 +M/1@AV$VH.<'M;/H>@')X%1!UD;;#B0/?+4]IS=;$K-.$YNY2@.#^3&NZ6F'E +M(36Q,6L^+\QIWW1^>S*9#+@$Q1U%!3^<=+QR4%HX'>09/,UK@;3GB[(#M93J +MS+G7>(Z.1.WYO,L,173Q'Q!8C@^LM:?UQU]SR9_.DF%VNXQ=&%D\0!'I2,_&:QDNSEC1QON&<7VK9ZM= +M('`8#;01*?9AE,7JONS%&&>76S`V^:O6D*ZEVKKG@#%CR![A0.@*] +M5FD<6=T&QAG,F+P?5">-6%P7OT@'X=KX4MJ]H#XN5,>4'Y4SD7 +M3-E*GF;-(@RUA*8!CDX7?S*C38O7E\PC<(2D8>LM^'Z1!7)EE`^?)'NRR]%` +MA.Y*1`=53?W4O,+LSLR+2,N'0;YL`"#D/R8,R!P_S2\U(52)7W]*VU[@\:M8 +M/+[-$HZP^@/W?>[9MBU01N/@P<_V_"B,:">3/;#7\@0U7?M2;5GJ/AU2,X_, +M#K$^S)O=I=6,A[YJJ]@)Q6";N#TY"M:M9_3)21-#7$X\KTI6W"?9=&XM&KBH +M>Z,1`8GED)9.?":8Q5G;N1Y6$?N//R_\)!)*!YU_60VIH3@4YM,Y/H>-\<)C +M7:37;;JS3H+)#!G_\"JO!8,C,^>K"#\@YH(@<@G2?+P_"RS@@,UXH?%%!0V/ +M^%`P@;J8A?F`G-"-*XWQ+//,G<^F'5*R@!:X+KJ<@.6:IR$-?XC2K[#?X.G* +M56W3I>+(!'JRG3A^1G`U)&6S4_JW):"58S_<6U^1TU4Y(^4\):4<6.KXHC8Y +MG2_[E]\[@THX%*B8"#C6J>$KENM/%HLP-@;'=8=/NIE_O'GT-59&@V.CWBTG +M\F4_`?TOVVD^F'QZ;H,9\&.`)I%V;>7P(Q4=C;R$;*;]8_?Z:@Y..<6C]5V> +MN^0YFHMLT:[V!(<5RT5FU'_@UJH_Q^X2]\57))W@I12 +M;F>^B'<.4FXW>+F.#^]&.]PTE"\ +M:03W:1 +MLQ-*=`:49PXZE-!/[:VD5/B7<,3H56<@/8JV+MT>5HGSEP(R]I?7^';*&9XZ +M&>\)^)1.@LPF'DN06Y^/=5.1?0T`*0[KY=5-_KH^N+Y=/)\$*C]AFQA4J`'^ +MOV[L_N\6H\8R77-;VN"3*#'Q4O]>4G@#823Q"12]@:[6=-G7%YL9.Q9++$:F +MT#!,J1S-A'R"/Q&B&3FFP-&0=NB7V]%MEMDJ\E0HN4W1XLG=7MH0[B]4V-I* +M%G!WGK??QT1)*H#(Z:T+G,84-A*K,[(5`H@E[TB_V70/*]CZ%S_&=MU%B@[EL8[%J@1;.>K4E/DB/PJ_>T +ME/UT*8[A2:_C/_1LE%9"";X`5;SMFW;PDNEVV^*`U-7,R3\,7V!5#N22V.!) +MDHO5WEFNMQ/"I+X+]T`5+0%U5JH""!.T9BI^6#`9]@>$B.(-2@4QG*0,E8J@ +M?RG*5JTW_J2*S!%\=V[G\\L8/NM1SF^"@*M?M+ETDW\OH'0A'KQZ.G[T&>F/ +MC1.R8,KO*%',F#&3?G)^B2IC!ZO/*N+P91,!Z-R#_ +M4(,_\P:G]%?LJUQ!^]#@/_,1LHIJ+AK\0'EU)0#V1PQ($U3GD10`&+1(L/W+ +MN$A\0A#O6EZS/D8TQ5)"G^1RA;6;C="JXEQ.;5Q]K#KF_^,^-23=6DQQK2^M^+CUF[$WXW[4E0PFRB.? +M<+`P&7!VT_ME/#,3RVW/3/@Z@+FVEW]"R=/3VB_M.1-@A8MK:L0;*R60.OZT +M9-Z=E'!^J2ZQPN^&*C$Q1L-.J#(4:X%U1BU&PYQ^ZA%-MB8?:(S'FA@/4UBJ +M(CZ&YY&9;*91GZM__91&@`^?*:*UH@83",Z-.JJ$%B5L!TJ:S/L>X3^:8S\H2J6ACYVRY_ZFDG<&_@"_)+A(7ZD@8QTAS#UB3X1C$\OOL +MO$$R2O!P2H3H$,IYM!N45NP5^3'TQH,:N4&2`&"(1=!M6W#@!+-6R$GB$W*' +MGW3:D>[D>AO.=B)+2-,*5HQ*)?JQ60U%FP<-1YWM7B3W)"2ZG+:_N;M[,3SK +M+P],5K_68_.8TWH7)JT.MYP7H]&V,2G1PTA_#],1!NS9M;X=C.24@<^DJ5P/ +MHHMX98.RRA#7.<8SR;OJ!]>XEJ08!1G4;C\&ISIDUIGA7R&RQAMB@VETZ;M9E<:I&>`C +M7.\#0M8+?6""/Q+"5I%&*K'%TC'W_='3)`\K?^4CD61I3\87"<;@\>,DPB@X[D&8OA1YB*C&6B$&..>S'Q.GF\MKD0Z;1B/"M72T +M..9]SBAH<)@H",R\L_+XX^NE=:H!I>L_9#D)#HF=3=*!,=XGBEG.0(Z&YVNW +M8+9._JCD==5IL\9`S\J*'O-8L8T['3FL6/8YTR.O80ZS>5OK"U-- +M"OELM4+.KE,>MJ6M_\\AANF\M0S`<8(FFUK]E:Z6-50]:7W5S8V_R\0!HO_- +M-<_IGR@T,Y'FL\LL9&]5I/B)^Y`_80(4%B7A9@8"SC\J,)U^A7OT/A'(!YTMV4Z1:=)NG +M\/M7[CHFFN##/Y8-PZ+2#UQ6U?94BXN$#-3AF]N[@B?KG!^F?B'@RX/U)SKJ+7`HDT5!M7%X7S\TX&=OGC7>L +MED/8,9?&-5-BQX$L2I,BK=28SGWZ5@4#FYP<'5)C)Z3*R\Y2.B( +MWF5=8Y6BVWS/C)KN/G3(;>@=R(:%`4,3=QK;B<8D[/=&!R>L?Y7Z]Y)U8.'H6MRQTVDV +MGI&[B(DY5T54S^PM-[SDI)PS'!:""6[1WOZ\T/EDE-_.?2GQXV7T(O(`#UCI +M:$.ZYEOBFE>B?VYC7TF5]V#K7G[3[#0K+ZBBD,W#3<2Z-ID`A\$IA\!,9]/E +M&?X!:.E&]AA0I8C)=\.L!ABU003_.4_7(/D8*@T^%,1A-OP/4#`$,`]]WNT+ +M\ZE'N$,Y\M,_]G`+U#-<`IYR$Y.N$?541,C2L2,7EQU)"9#1K+7L\M/[>W>N +M#Z@PSXE*.V'%@*-!@J9]J_>`7^>$"H*7^T)9[8/EC=;1%>\%J3_PNUD&X(IK +M<#[K!H:FT0M*CH]XVN8<^SS/Q?@^U(BVBZ9N99,+`__Z0^BR;6S*\D-T8[]DVN>OG\Z7*`,5/#X.5>-,V5H*(R`75_TSZS +M/$_TN7(M&2T^:8N=L#ZVWJ$8A5DE?/O2'1$JMH].@QM*-]K&+=$TV]HI]'EQ +M0Y5?*+1S04+1"25APDO6C^S/)UXFUH^U_K9++EN^G3H_#F1N<7$(;L_E?(F2/R^M;EO2^_R+&-1:S'Y +M,YGMQ56K\\W-M11L0(]0":[?BI^H?_B,?F&;P^4@LNXDD3^&[DJP]A=NO98B +M@?:^X/&T0ACP>/7L25BX*5#>DH4&6F=G!H0"O'%KE)`+W7)!TVBW,CZX2IU! +MUYUYGN'IYR=^T=9^V"U0/H-5,O[_(2GI4AX$C[QZTO@`6M69"W;E06),8%YV1G&'Z]\Z?>JQ$`6*2&@IDRR>RWCQP`USQ2)JTY)+6 +M:8/1TT&-G_9PB._']4&]ODL/77-YEA6P[_;)&]C=2YN+HUCHA-N\$E=<",>" +M-N#CNT$^I0CD:O.[`/F=HOD+9T?'7_:TRA]KGD]@&63C494HG\Y[4\SQ(L5_ +M(C!\8:MUL"%BN:=WC?V?55<-DZ$T/`QH^[@4-8>46_W9?4")QX-4\QMD'X'6 +M&AJ!IWP!LZRWK-*@BBWS`2E-W(W+=G_LKC"QK2\J`$(+947IXN(-+(!2F1(Y`(.C[X@$\)2(+ +MO8Y;2)1B*I'+X.T=88Y6X[ON5"'NI6(OA73#9W)= +M(4B0,HRHA5P(*RU@V7IWN`4E42#)ITUH5*@/TF*60E8L>B?<`G@89/OA->%$ +M3\@$/V\;]+:?L96$K2)5CKR_'!6[@#!KJ4'&39G>#[1ZEL;3ZHO! +MP5$7-BI>')I,NVQFC@7=42#:B4+S\?YR'\9BY8:ET64P+*O1O;7O,YA%G.ZV +M.V"\)4G](G'Y>-&G54=9]QYBXON[SQJH4\!'_P-Y0^`SZ;)3^N9DWC[/VHU2 +MYD;?-S=IT(?9&+WW'\4(&2#^<%`]5IN]'P!,9VLIA2[B]:WSZ37$'] +MP.@1C)OV8`?/RYLS-MYJSFW#65>)>3?K3IZ8&(W1=EJTJQ$DT>RDM@>U;^F&8F@Z+RK$U,HWZ +MT0:9Y0408-+)-L&ZNYR>JVUR:ZPY%'Z_65SPSI:LE@U$R;+'3PC0)*>#]!0/ +MREX<:I0GX%?,>*>>7NYW.A%6BL]3]V=:`P(S_9KW:[PYJ4 +MG*+E+Z"W>5BSB%,T1(CC,_:9J+3<98$I'0?PU?!(!`JN^5H_@2O'$9_T\?=< +MSR+;APRAO#L-F>#H`9""O-3A,*VZ'^3L)09-CW,DH]YIV;OEN`GL6P<(U<^J%R)PH?&&+S"J\"&&8:^NM&]#K"7(F::1CU>I=B!:>:'^WLV'F:#,B7)3DIE:5)4V'6/>ZW,@:BGN5 +M,Q;;Y1Q<`I#Z-CMN]S-`J#XQ3^,[6[8@#W<>_.UW-M>/+$87P=Z-L[XOG"1/ +MYAW5IHN1L@%L)>:"6?A?,%)BO\JPO3AC0985[X=R%]9$Z7>B2CRL(-V6X/G@ +M`)_^:A#UERVPGC2$!\L7PE%NJQDVZ>N4R5I8AY$R:'Q-%CH91R?6V[`HIL!2S^>.8=F$[J&50/BH)&NW/'"V>FX]!Z*5:WS +M<&%70H.FT$'#XD?*!:(2[M@Q,LIN+OQ?G:-]/L(YZI@.CX30_=,4[I:U>FS' +M#:8*>"7IG3:H;YWKR#+B_SK5F426<.>(;$F1/J"-F&K'TC^$0[=.<[3104#& +MFJ/`*0.F!JO=U3]#6R@6R7*CB$G +MO,I\4<1B +MFR90GOXC^7T4'\'DI]U#MWV,D9<-F+>1SN!Q3(3^LZI69I^D.(&],=Z*3B11$VUXK00(0$@[5KKI0*5T)6![_98W$5'C\AO?_;E\>+=/&Y46 +M:CY#3P5H5R$F@!-'IYGO5=GA%$%V9\VK]^P)$SNN$0>^F?]?;6W<2%MV;2WC15_*!L_ +M6TK0C.6SU<=L'Z[>YM-M(>%&S7J55XH#NW9REF`YSW1"VJG!:*O==\!;W^6YF1UV-`L/U1A( +MS@>1'G,1YO:*X_R.'EG>Y+HF0M8-=]%R0E.=:>?D&5V7W30T'R;<%NL?W*?< +MDL3SF--=T%<XT>,0IF3H:N$Z_WYJPSO0VS3N(F']4@R2M!A^30TZ&>P%3&3 +M-N@ZX9LI:]B^`%N3=<4*!`NL;3I2\^E4\(8J3>C95H/O3C6)I[+98E:%>1E0 +ML"[S?--]7T],9$G]9CG&NT.>&[)>V2=O5.WV_U&VHDZMCSSRK'Q15-:.%`C@ +M18Z@<*EA%J8>LP7E_,T841?K,9DT[/A#KKJD@S`#+_$8LM:772T]Y]!6$H5' +M`"=_S?0W.W(05CZ.N+HX,8_[B.+@9[EM^ZH)U'+RN;TYU<`DJC"%=<47\9,P +MD.,>E$O4Z?S'JGZ8VG5$4L?SO08#(E%%_O!E=8OE],*$GXAHE`9'R+#F0QUK]YYY+1,K&=AYG$MG\7W0@Y$^6G'4_9RXJ<39ZJ-D-3&X55" +M<`].'I5ZV1?(/>+;<-JB/T3])18*T_M>+EJR1B4]Y[VM^6-%B"R^/E+_9X[. +M2Y>QD)V:)+UX51IY";BD^TA6UY]5G6< +MN)CSY[KSSU@?9$]]5Y.=#!8L#<`'V*:MZJ2.#?.H9V]))`K,\T.3H^;,C70` +M=ZS%H_:Y6,??M!\J0SPP#&<^; +M.O:2M>XF+Q?H)$3Q^$G4.\MEN*B"F2FD6D]+^SP,^+>RKJ7AG/_NSX>)_2!P +M+D`8"(D*%:)Z^.B4$1M:P%(/&6Q8U`KJ0[6=D]BXMZ./=1'\*^E +MV>S'W:\W@^CEL:%<6?X!>S([-86G/X5#QKIOC'O[YXR^\'9I>XXS7^&.7ZK/ +M'^58(?_O^LZFO.3PNWJ+A6]@506B+,!\>_94[Z#RM#N/QZLY=-E+0VH;/T>< +MNIRJ2WKWMORT6">MMH*W+).BI+O8U'E(N]6O@K:WY?$2>?9S]'7&Y+-,Q3S" +ML6NO)6`QO2_JO_Z)]`I52(]8?1G@3_/4OSTN]H_N.RVQA104?.+3]:;O'*"U_#N%)+97)B%*PW>Y98,,EG'TU77MK!P(#)"OOUU-&,R&>(Z$?*\\L6$EZ:9LG58Q>W +M)J`&;QZI$H:;$"B$5TY9(.QB/KX#9#9_+3[H7W[YT.QQX-65+LRP^K*6,A`) +M:);K1,F^D&?8;;CO\B@QZ/P>L"H]K6>/'F/WB"&-]#!1Q.F +M8N[RCXM7$+\C8;$-:R5,'JN5@6D0L&#M_,&_9PF3VCH\264?T6=FXG%HN.R6 +MXYOB4$Y_#1AA7 +M$KMK5>..X0^H5))^.?6D)8B`G\)G1$'/U*@4HN7]CBP?*A>_%J"A_,<2^3;2 +MLV^GY#UOOYN7OGS4#_#`3`FDI//.+[(BW6'#,0(GG/JY/PH9VMATDM-3?@[C<7S%1`60XP">*TNA$`J"1Y_I>Z1^!3>%&70?0_D="RY7FL/Y0E*F +MDXI3DH5]Z<(T'ZW'Q^LP/^7=R,4.3D(8ON65OD/O=IC%/:L]#_@OL\7#G0:( +MY\8P+GP(=->[_."-OS[@7[I8/*1XL2"OR6T3:MBN>_QGY_1A1GGP+4#^@+,M +M.#"#](X&"@YF+Q-R+MHP?-/\LCJ.FGDR'RQIP8LSF%Y^MR&$*#W?7Q('&TY# +M=85NFH5UK_DRFW`TW'("O5X&2UR.48I\& +M*/^*RLLN3'0MVCVX:ZF)F<#]CW?P/F!!4:"4^NW)7*(-/&8U/%3#`OW>V@U% +MUA-F_KFNA;HH9!'1:7*_PHCPLP8AT=!>;?.(F]M9/4:/*2,W]0E1[IJO@V4? +M+<+1UMA5(M7X<`E50((EKX4+R9^-NEXD3F,',..?J]JX?*'I9B#YL74N#TQ>9! +M^2?GR2Z[+J+D:L +MY0W]/4#`\C;RRDX+WD7$#XA73$_TWA1P?=7SYX\@;V8\"WY"/^`<8535-_ZQ4XV1 +MH'4C*O;$(C2HF]H/;O\;6WYQ@,;(7&CGGP11!0^3`0\5W=7-7JX'.%_$@*"8 +M6WD=Y=CSM=GQIIDW&99S/I?S<-#>>%^\P.]@NY1OY2FC:W04NS*NO86.;Q'] +MJ64>*(Q9P4%I!-T.3,)AV)=_R<)7<&?I,B;-I(N/Y",)8LUI%-UPY6:2IH>- +MJJS^`@#4SV/F$CMZ3Y.K&P680S0R5#M$A!M]4#_4U +MX1./FA\%_S='-'/0$+G@A+]+`=J?98EM<,C)$?0W_+W;;DT^*V-:S%20<3&/ +M"1@.9,\K+7)=0R3SVH32FY822"S(Y2?]1C]@OTI:AQV8"1JSI`,0>5YM$Z2E +MR>A\EOWB1.Z!9>(.8M:-*S>N@LX/9,T;DK*$:/';'L!UNI;:!>:T?B5U(G#9 +MRA[1M8=9WFF1$ZSG6A8,QV*!5&7?G>:PC/`,>490FOC?UBY@/`GVJ=`HSZ=L +M,UMFPV4/O(O$&/E<8F65CY*C&ZA79SN.!QT(9@50M583+EG4WGH9LA5 +M`6KF`Z(.@V@Z27V!PINZ$2=:1<9&B.^*XYQ8.?^$?.K?2QM\G'T,/_'I-(N@ +MIDD>\_ZF14M/DF4#!:ZRSI+N(=:I:-E^.!6DFVH\TNEX>(X4B_\C=AX4 +MQ7A0:@[=#MV#)@X_P1&W".<29H>SV0W1(D.[ZANOEJ-@?;KV(HXO1OSZ#J/F +M1\?PN`M_M:DPQPGS:_>CA.P`M>;&'0[O5N<@0P)7Q_(L1S`>(^C9(FLOQ,%/ +MB_QH4=!,X.Y\O-IA[(S6FC>F,A5$B/AQ&)'"C&UX3;*%S9J)QO?.4=%E3;=W +M"3?)E9>=)6Q$7E-)<-5#*P#JJ-&M)S43/H>AT"AS].Z03+`Z)`LV-&%ISA7\ +M!SS+RY,9I;V^"N8<6![9?R)L*!<@I2XN9^BH?M*@A.CQ+V!>PGJX"31(PM?B +MXI7"G&QQA7X/%748H`']_<#>G`EAQU^0QB-"M6E=?IXR;U*H5T"K81K(X@/7 +M^)?CC-.$V8C@!5X\+RZ>N#>HYX[>TE%0:+0$JMN!,7OL*0:=OT6`Q4,M:53X +M.5U;,_-U$)2@X;&!;NX][@'V.Z@XG'1+%Y1JV8. +M=X#9'@14A;HX='DM[GOJ/X):@EM-V-],,`=P<\EJ\!DP-UW'9X3'BYQK)B"P +M3:S68E_2,I%9Z<=8F)9YW.)^T,8PTQ<4N5BW7^+@HCT[>^2:$U_][2<,$\J9 +M1-_8-*?SZE#`$:SJ=8]*+6YE-ROO[PT)ECQ:./`2[LFZ[HO204G-1AS?^"2P +MO5#.[[I5VI))QJ\AE.3TP/ +MNVLZQ0'M;;99@HXRA88^BS=DQ1TQ/@O$&DD&`VANY* +MA=X['ZK`^E'SDX-RIUMD<'G)*^ENI=&O53M?_S_CLO3$H/V/11;/9&.OK*3- +M\](CU9I!\FNUPUV+VGJHC5R"F*0A0W'ZLKY)VT3*F4RGWSOUDRK(>*>6'Q=& +M0^3!*]CAOB^I::QZ)]L"IL[Z*!Q<_"WX^Z/`$:BAI4_I<$15V]YV +MP#+RR`%+PO7+$AT3QE%_7YP.20FQU+!2WVW)-%O)?@PW(2VE7*[%U/_R$4,< +MZG6"^CM0BL;F,N_5XJ?^9\'&TE+[/&V>Y\039%;09XH +MX8;R-'OH\5'!0'6ER_X"9'5\>F>Z`"F3G;>C+P:RH])U[P[4Q+8W!D3W\:!W +M(N>69L.D1^/FI@[6LFE.++!IJPLM+9,E'\0E[^M%14G\!XY2CH>P^_"'$SV +MB2CVJ"1.02ZN]MH/#/._S;]\Q%4I%B%F*R#5"->;_F[/`M0\J>^W8UL2:I/G +ME=,38OT^2!B>W(R:[S0,V,1ZJQG#CF+'VA1BS4\0X=?#>;:LZDYDY"@F#$3P+%9-D>0=(=Q.ZPW0CB)9POMX[BE($99/ +MONA#B15`]?L\.]5^#EBV1_U/:P;['0-#BUX.VJH#:1S1+/U#D3I,X,R4[BGA1$A&C(K04]-HJWJT&\.N$-KAH6XR:VDKPW36=R%? +M]!:Y_4M:<^L[P$).QEJ558@S(I?[T@$+5(+5OY)6]]!N+;I(83?*WP%Y\,0? +M0.,:WL1TK_8!,KF$MV,T!:1]8L#$T47+$@8VNQ!"LWUT\;.C +MR@0L4U;?-12KTNA4*S:!HF_(B4@#$)?^!60I3Y4=_\BV;8`(+>L#KTN.Y_Y8 +M25ON$'X)6!?_+`7)>*;[3^;$04>*89&"`L6X8?.IFNR\O=4%9T(9B"UZM*(4 +ME_@,;5NDR-Q3`>$,.Q-%WJ9;G7LHU^-#9GX51F#&/6E$&H^,:LSOVN?(>A3L +MI"7.TZ,86=8+R[=J*?^J*.%J=W+""/:MCQEL4DU^KB'?[TM=1=KXR"OF];'! +M)+C[B]@.LI&G#RA7SJE10YRK/Y1.I3A.NL@@"/=7@C8[X,A$_M;Z8I_6QV#> +M^/[XLB6KP9#X/I8YP9Y!UI=."8`K!`D+RIRKQ79`E&-?0@QTDE%4.&#UCN:X +MFW2_5,-.7]Q9L(REG2\\W)?@T4`0^$2OZ(4L)DXXG-6I0DD=9K=L&?]M<8^^ +MTKA=\G&RN6'3-%(RJHSH)Q:*\-VC6/S8'F9_!K6$0^WZV3@8;U:(_75U%*%Z +MAPCBH9;@>/6GVUEH=/XJG![HK/J1YJV'0M/]#'NCK4'*<6?YVQ7Z=9X!M>3?PRE4G\$ +M](EM<]TU$E,57_!5]M@A'#@T/SF6++J_'V4*(JS9+<*E9.?!2K+;[ES2]YP[ +M.$`7B!8^_;,75OFT'WW85DIA74VR8KPG/CABK#7"_[8:MOTF@E&_#+L$JM9` +M#9_CBA]GH=,+$,,#TWPS:?*`#A77/-?5*0*[66R!9UA8MJ:A6D4?K[+;>+BV +M"@4F_-WIF\:(8AR'UNNL1TF9\3D#ZP66^(%.-483DX6%A)1$70>!K^#+=N@^ +M2=NR3UU[6/U)C:K2W]!,B;-!L)1:Z6F`=3+;]V)VZ]2W95FHA-F;%'R^,R-@ +M$:9[]VY_[3XC[^#72#AT016I1'B^K5-OY6Q-UXI@_QQ,8E*D\B4G>)Q]#,#= +MVO5<&\J'BVZ.\TK=#D70O.?E.FD5+P:[MC&`XPL])\&PXI7^<0`YI1`E;9XN +MN,!/,MU?6>;!S23G$9#5`&,7N9M:=BA\T/`WS@U\N&0(777^D=^$X5@,M)A% +MVK=>Y;@*:(S/7VY`'P3NZ<(1',E)BR/G=G%#@Q-GH;E"T'M]I7.?AP.1'=8G +M`1]NKEG!'^RP:RI6U'L'M3A2$S@7=#^K8(G<3;T>X=E,\N!ZLG^'E)RU5^J< +MF`!*VX>YC*+BN08AJXN#=\H]^Q%^7&"TSH%UJB)J%:OELRZD!L8]QQQ*B4J_ +M%S"_VZQ,V$,GA[_9""96#3KSD74\/I/J34Y+VS6 +MVV2#S]?03&FW;'-%MK(]*:*(:.">6O?YNJ3&7?$+8I$8/^(5??#C.F22:-"ASKXT&#EX;9 +MA5PZ]'_L8FI9L"ZP<(":)3?%=!#--!$8DBH:?R)60.'QWAGJ"]F!EJK'I.S_ +M\D33W9E0$1&2XRC&/FD1"TY)7_KXZ^FJM)P_NO%0A4Y=G&O9&LM@R2KY"@/C +MF;0K(-W\$X4HKFV;[[W[OOKJ*^WE_4J-T7^IF1+#V/-;^M>=FW9FFEF%9?*X +MK5>EC]CJ''8S4#_LOP/Y+_VZU"=BW!=T!/3\19,6HZO^^WPV)>>18F`*83N' +MV40PX@?)Q%7674EDW*7G+)8-EJ4.:>C:NO&5BC=VS5:6<2UJB7F0?0F,"DDQ_6(XK@48350+C9[-=21UPUVNB54.1C%K4((L%(@:Z +ML2`,^_TVYCVCW4MY!W?:YV*)C]U$6('P?W41Q3$J]UG<\MB8%#NR\/#@']>. +MM*Q_2+:SF+3AL,Q&BUW_KNB@]6S<+9N51=(^KM'KW%L\V`T&VU,BW/T5!!N> +M51=<5AFQF0:TFJ^L-2A&N7JGK`[OI?N;98W_LFS#:[3:4'$@%[/)+XM(QV5* +MJY5+JIKX\``?_PIF.J1SJ^%`5,CFI?E +MJ>`B]6)39;72$*?GQOJ6"R1=6=>T`Y"&E?!',1_K;-[ +M"+P$2`:&KB+4YV>%"B%*Y0,Y>%7/E[Q=3$N&U#22?S2O_&A7!+(SW$(M%K9D +MC+PNQ&$^ZV_:>XP1#Y^VR8ZN>UQA[KP2_\EU80-NAJ8P,V8T:@4X9M+\%CP6 +MO5U=E4^*^6=<.0B#]$X6&Y.JIH&M12TO6U,[_9"5,NO;Z,-DA"K>!=*ALX;% +MLDQ`PPNB%=E""V0E[L[&R-]!F8&]N4)U<`N7AL.4Y>-985U&6RPA?&Y%3.M5 +M/5MBB+OPSU-0PF-T9!E=]H&P:C@-/QDT?8_!B\;UR"@TAIZM!UO;$3##S`_# +MUCKNI4W"&>F\^\Q[7[B^&2RQ`:X9SBW)?52O3#_NVIPO&15MN;!!U!T1VJJ+]?/3`KG +MB+LG"#&9(ND'@S@NN1LH`O_&*XXTN0C.E.#GT]>B#@;IA@8N$>Q%X:-O/#D# +M*^68#;K"A+HW@>K!A7%!(T8:KM]_DZ#6H(JL"Z567_=]%@P):WHM?P3?P2SE;"=";3,-_L@#T&# +MC?U4633F&UN"N:T+-#-2'6H#.\L1_OJ2]@LNN60&Y!*(22S.N4^TL#":8%H# +MLO[%#BC,?6^X(RIOH5ISRX?K.IR_X)J4OK>4`8G!K$"R#?<1>@Y^52HX`%3` +MM;G#9$7UJI7$,@DG7/HLDWDK4RW+Q?O2\0!?9(SN8Q=VBW&:]AC`(>O6\"SC +M8UC^%W18NO8S7!,HX7T:MJ3'7,N7R/(GL5;.]][O93*A5Q6'B?,)_US$@#=T +MYHA#^-.@@E3OV#>J3<4T,W,_@7`IGM$L4S20%V.REI-L;U>>@07\_Z`R/G]N4P0-K\#'[R3C]!I_FV)@7#LT__` +M;@M-X?_Y4>\4+'DU1/NAY_*`";MW:T1"1B$K^?J(G,3@QSNNYMA())%\OQXAS+#6B!I@J`L +M7Z'8WYSIU:-UC'F`7S%C_*3WWA;9MB-<9EE]%&H;;O-GM,^5[ML3R@4Q^4WB +MZE0N:8/U+A#:][24U?2R6&BXW3NR0=1CH:51DB//C40/^R2@H,,N(!S16L-1RIEUZ,U4`^&GWSNJ/Q +MJ4K29XPVUDYJ)YA!&6GZC&'*/XE3+M>6ZRY&HZDV/J72D,0>L.55VA4(L`;&L[K<0?C1GO!]U5%PYKS'L(;CS`RB=_^'<; +MSLZW('>M9@6VBVKA9V/,D&;MXW8$=1K)G,>C2>;PCO)V(?1YCBQ0G8C5QI)[B`E:R`,XXI.] +M&C5J>;9[JW$<::9BG@+0U%M;7:O!OOI]ZT]0Z!X]7U6'Q:"GW3.P2I)`;#:C +M!ZJ*I$;G`4J30=U0=[*XE[A/C2K-4KO>-+8I`)X*,`9$D8U2X&W5Q-D<^>'9 +MN1Z$R"RQ4&4:1TV0[>Y+8A93XV+;STT6B!A=KXXPS%=MQ='!A[XK$L^CWB1Z +MB?PS.JA8\^DI)FA%N]=10-85%0YPQ`D$%_Q1IR*A5`.@#%HI-`?>G%2T-15F +M%>7'R3?HT8W;E&K3U+PB%#"K$',(1EJ5'P.GSC4H:>ZV=W`P(\06#LN/QL+^ +M8=L8<#SXXFW/X(`XE#9E9M][_*A,[62BG03@`H,IDV]-S.W5;L\'1=A`BGSR +MA0;.:CTEKP=T?7_:O`&;).6/@5F^KNN'A)Q0S.HW=Q"-8\>[KLZ=+\0-?;^R +MY-:#'PF]2(+`-;Q"*,V?^:]6!T"]YF1;/9.XIM6P:-O-HV9T++LZ^5C +MK_TOX=$Q#U?C47=LH\F&VZ?:6QJ!_#CU/#*:\=BL_'`GL\3ZJ!:.U?`)-D1= +M.BBTO$7XR6*MIWVNLHQ"09@\SE/"/7WLTX7AB=>F'EHB!_.Z9)N +M1B^1<#"&H@/88KEDF:!Y!0^?SY#^`4[R-GSG8EQA?`ZPZ)FC]^RL_JR#8 +M@-0)>"@8GKB".,KJ$6!:^"I;J(Q*W=5H7?V+C@%#7?GC9!,LC6 +M_^-S8U;MK,*HIOK]$O70*R)K?&'I[$B_NQ)41>I$$OR6Z(B&ZAO;Y77KZ1*T +M;5,VK*3[Q?8`Y6WD02=!9ZYJ8']N."<#\&7-"HU.:J26PP<=X]9S#V1-ES:" +M?U5(&J\B'>E%$R>,7LMUCYQ+YMV`8;\7X@W)-&[>TC!MZQBIW7E5[+)ZE-W! +M"=N&L3(2#@':"YT':BRS`6N3F'3Z-(K[65AK*C&W>+53!PV%W8^M]=`N,8%( +MLTX$NP6L1^";.1,JW?4[R'/IO,<#DE^M;M-($BO=%6@*PKEGQ@Y'JJWE)+S" +MM)"Q%0WB0L<+5$U<%?U#?K=@\$C(F1A3>;R?B?^,;TCSM$]*\&HJ.8_&,.L5HG>;P\S'#%]M3GE6@,_-\7+ +MY%OI)>AEG/.V-?]IB,(_5B""?#"F`LB[^>`O!4[Y%S^$R-+$F9O +MI'YV?M<6G8_NQ_G4NX^H>PN_LFP\."X2=V(GWT7.R52@7/ +M63+&PC]*?UX;.#!_U,>"IC8'3!+8,0,:S(V$*^RT&,8RMDV_,=@D9B3!T:II +M6?M!]%YNA%W#=VBQRD-O2:,?DLI_(S,SL!YEJ(QKJ#^^.]'&T:]!*@DTE#F- +M!'B9"$X*BX&.*;@(\5MB42A5#BO04M^>[2(Q)DC^&_VY/OIPXY173[K4ETOZ +MH`@8;FP5G8D-IV4V5EGSX2P'S6H70)#+[L-9CGDV(+,!4IO0"I;?F$)>UX#L +M25L?<*)%V9:EE&PHSFN7S=)=9.0!N?`28B1U$\;7Y_P>]K-HL?4-U3":9-W; +M!8B`)A<.V`N?GMCNV7#I6Z"`X1[73/UJCC\!+WO!V3N'7 +M0#C>[_MXM0&\T.C'66NCE/])QN58IB1?UFDI[=\:C_I-FA,5(DM]N\-SX?0R +M%")*NQ-F3O/`X.MW'1=V#T&LN'A!;7Q#',O0L9&&K^=9%EH;78E4R!^6&'U_ +MF=-N!MWKCWET%\_C5L$W]@!!23/^J-(Y!,V<%I1V7`5BLP:=E6/OCL9=XC>D.K9KI0L=`/`- +MF0)6-HPO&]&S-3R$'=>($/.V#WYM_DT-:*$G-NV2O$G6'KP3&69<+RD*5^3NC(,E<_5J_:7KD,5 +MJ#P`W\5*ZG>Z2Q.5"8L7369\A]8 +M@0!IL.5C)@,;D8_7(;+=MP6"\G$XQM-[_>!M_Z?"WES:-,&W#:$*BWUQAVF\ +M>.;$4?MI_9UE[DV&,YF?J67AXVV1%"R.Q%EF!@`J,(+O?YW8:F$0U[39'>T8*WG^DN5QA)%RK:@N\GW!^.[RO!4ZE +MS/*!F6E2Q_('PTB6+'S]6Z(]?7HJD;`)Y$J\M1AE69\HD,BO+B"05SLM=BE* +MCE0_>+Z##$J]H*LD@."6S&J)X1,^W:=G^V`QT*N)50D/P.6:_`W@.]I';P#? +MK-)?#.53J?D#5;H0;E.#%\JHU[YC`9',CXXFJ*"D]'4^L0R@D,4Z[[*+95+? +M24I(W3J7ZT&D_F'V9[I1&F\2@%P&H37^@.%Z?RS#IOK\S>Z$DY)/U0]5@A.> +M#YCB+),U)^WNX4#A[R*EY0FE%2H!+JY]#D1:KV;(8.(X+<-K/`MEJ_1B&61A +MB6TS$\RRBBLXXP5#(9.RM_'[5MF"QY1A035JDNB= +M@^R!\!/KN1S,QIW?8M)=TLH+M49X=Q:K4&?PK/I)IA["'4&^1'O7PO5CPAGV +M":J;\#/`RPB_2`\`J-3Y006LB4D&")]`QSWS\KC*U`\[%".HJ47!IE++ +M55L,2PQ]C^$J0)X\\/9;!>@9AM];W6JE?FJ-+]Q!:B.]PA@_V"7X\DEUMET/ +M^$PH3[7B_N-8'R-!K'.A_P1E$W[+V&>N]@T^I@ZK07(P.0TH*"+PQ;?M_2@6 +M#+&%$S^37'VPD4D&O0\(I"W9JMOEJ#QD)$U,K+S<*<%8[W!A\I$!VI\9+.^S +MN\&Q$%Q,"$P':N_`M$5M1",N?Y>8\+XS@$$33\FUJ9*F#XK+(^-_*K +M0?DAN3/UB,O:3LI'?S9L;IA1TR;1;+`3I&7(4?#4!'N2%9*VD?0;(3CS6?46 +M/SK4\I:G&)-GO\)^#3JTDV`/4`@)C"K3#T=7F+^1;29&#O;CMC1A0/6'?.(V +M/"D`T,JA`9K_]4$1AMZ$VV+`>[E;'K(/><$L(2EBROKW/\R%S>(77_ +M']AV>^QD]#N%W1]4XL2TU2O,_7241U>\FNI.I-L!P'AB.YH]N?M`_RU7T6;J +M;IPZ&Y2HM5XA'&O)UKE$(3Z1.<()IURE%9I(%"/2)LN.3+"0JCD867ZR'-KB +M(V86^)I:;FB>;"QE/,V666QV2PP?:J$$U@R\,,B)[61\"*CPW8Y:P+/15.;U +M:&OYV845OPCOG4U7GHV+)0$>VTOV=?M]Z3ZFA=1#OG("IHKR.U\\,[8[/CGN +MD&C_&+NA))ZF]0T]]_$]3H2$RVP.CE*9'5V(*)=SN1AH>%(&7Q7\*D0M$+<< +M:[BX+T.U9WWZF)%WA0`2*V0B6IC7WF=^8]T:-E1E9\GX)2SG62*4VL=X-^!7 +MD419`SP)1#]BL$-IS6VHL-*>PX[NBK>[D%DN7W`UV'^KN2U'6P/S:P#AXS^& +M"SG7VTUX44IQ*I43?5B+BV*?)NHTV&H17T'`&&FK=<[(EKQ06^5664WGMR)=*;JJ226?SH!,)Y8[3+JQOUAD51/^^M0R4; +MX``K'ZQ!4A6C5%5,AMM!A5.S4L@(+I]9@U;A^9S1:)H.C)SO+JU&]^Z,T:&9-!*= +M5]&%V&9`K`TK"$3G,KE<+&3^6U1;<]HRD"Q#&&BPVI?25T`^V8.:UTTN,$I3Y5-P-M,JI57OC7`+%ITW58>EMV9=P_I#OX8 +M_LX1/\\ZZP,6#FBR: +M`XC)E`V7$/@;Q5=\%-T_($'4LVK.77Z9PFU%+*;UX=8O9J/F8*BM7BQ>M3JQ +M#-$AM&Q-(8.`3-<-P()YA7G4W%_/7Z"L047Q%=*:6!0;!XO8V\B*20L,0_'X +M[QB/-EE]A'`'4),`(O\)W%M'"\O'E!YVUJ6[37<')JLU5/^MX +MR?M8NBCA6_00;,PY#!@2;=%P/@_#]9<]]!:DH8,&8EJ=7FXE<=A=QI+"#-;3 +M>[.JB72TC$&(K`\U=1@'^)42P\B41^?#&0^]CF#IJ<8SB51P./B_+PB0\,AH +M8#F9I]L?>C6Z1U,,M*HL1(Q'!N)G=GD1KI-XS\KS?!*5/?7--!DA!E<(G7"5 +M&?6N67CC`4?SZYY*:C4ND0DB"84("1#<(*M3?Z[3.)6;[9Q)>MT0PQO234R( +M8WW'+7'!+HUU(*)OGD=O;H@&*MA;$*D;:F4%X!JAM)F@,,F(E*8=>1@C895Q +MBT=;R//YQ+CP/L[@TJ(\G92QB5QKR,=2Y]_2ZVQ7FKUA8>.QK]R_@3W$H0_]!O\2PBJ@H?_C`$H*W1?/>DK%T#4")Z[H40:D:P>F/-=^&@I;Z=J"6[`-,V&;SL'MRNU_R9#\A +M%+O!CG+>U6'7_WU_-S#/L:&@6[>U"Q/-V9TP,I85)ZH>ABAZ2>$W853I?SG) +M\'B^NKUU'+KZ"9JV"8"0(EV<)*%A29>(*FZHLIP7;#UCP%7%)A01[9^8T?QF +MRGN4P&>6[#/V&+=+K[E"Y0]N@(+^ZU,)'1KMH9:KZ<# +MRNM+!IE!;*,=C\O^\G-C@0RGS"DL7+8)3C4Q+!4(1K`\4I-^!<3$!O1#-[^: +ML`/\JNM=]Z;$+5_D>X%J3Y&N5O]^QB2I=HOA2/GR3\4ZN +M-[RO;53!3S-9+::U3F:2;K$A'#BHZP;Q(A4X1I*HU9TV?9)":2$.S:<4E9PE +M5F.5Z7(,-W5@JYNR^P46CD7K8+\RT[[\M9&[!N/RE?NIO&XMB<,EWDR!##!# +M>`;J*]=)1ELZ1K.R+(XDX9G?I#XDO_%D5A/N5D!VF#=4_P*44/&1X?!?6IO; +M)!![LE0N*[4OJS'[G,]$J[DH1[2M4G75+P.&-\,NJD49_G*T!RWX58#.'O8D +MW57+%^Z#%>*HE+=NVQ.+R)8D-ANL:V_#@5`3RE@'3'JY1([$1@5DL6_9>8]Z +M"F5QN5&84@/:40_KK_43[3Q7?HRM"]\&JOF_9:YX;F>1[9+X.5PR*/06E':]:@,?@?EFO+ +M];G#T!HRE)>M439&CG-?(T4Y9P7H-.5W0I+#6*WLJL':/3MWY%LP75\,V^TE +MAD">P#;_8)@!M_0OMN!%RH(`]IEJ'#]]TOUKG8\VN1SFJ]#0U)9^^U1U+5[. +MW_=IZZOG570(_;SOVD?#N,_:V`6JOWQ-+K3L!V_3W%DKFJ\_DNDDA\R@^[CN +M1H7E-S#DA9?QU"__"FFW;!XVDP3UGT]?-&>,43,N4U>A7Z^X_#"F0=RMX[H, +MBY,L;QES5W&#[5/6,6\:\1-H#[3(TBC1?0L4!M=DX-X%G)MW>2X^X +MMUJ5"L8OU[IMIAPTOT3C5E9-+F'??Z82[&4K4=+]Z'I*1<,<<545>!;D_U8X +MJ6D[45[>3Y@6@M04"S]SV0%'T[1OD.H:_GTDEH?T\&ROUJ=K`58S*3/$,&()<6"J+4J%2QVV4 +M'VB$*Z\LL(D-ES*X3BU?JIL$Y#]JHB&.7\"<+HVAAF3+26M:\#]<9TO!6TM[ +M$24=OG$`)M$CAA:NA3Q=RU_(1O"+\I#4$S<3\`(1]^/&F``D_[.[*'?TH-MB(0L#WW?N7'IV&5@DX/@R:)EW_S3SK? +MX-O?7DNN@'>GV=`7`X.+)O<7)=@E+_U4_B??[V*$3J`ERQ25($S +MA+1\L*2ZAQ2*[]1B>AA#F>($@0F/MFWBA.607M8^TX,]]/W[T8H:%8^.?%X; +MY3AU-(>28%P/X@;\AC&C^_5VJ2S7_Z1J +MQ^[''T<_PI#F*'$A-K*BSS9OVJO530:`^V"00@H[?.(??=5&3=EIN6B>E`36 +M,PQ.V*[6NA>3&S:O.L$DQ/3_(T)OXUE7PJF#_@R=)LZ87SZPF%;=,(L#N4H) +M2.(&7:38P\%[6:QII_1VYX4[>-#W0P"%9)]&QFD6=B<']YUQR<[.<#DFI=OM +M\RFP7FRSEL0\4A +MJ;SQ(%-ET+C[#N31^^8E0V0O=]--!S^3)%VG@[,H(=PP0F!MI[SDOC"0B/I0 +M5%4]DUX@*>+1&B[GH]_?#4!QRTD+Q%3GX"8"NFS^TU%SKV%#U+=+"W$R,X6X +MD]<-7N@_1WI^VB?[%^?FB44V#KV]MJ5?4DPK6_(PPG93FWL2]08]'O>,EQV0 +M^,Y9&P)[XAC_=:#PR',O86:`\`[0+%K[7,I2D47^JE@Q="QE8FX]U +M2Y@I&ESD=Z_=-+W;;YGR7>\@`&YFQVFWK)7PRE.H6`>-/K$&**QSM4?1+R0' +MB"W^[/I$^9$?DH+)G&P-B.P*Y,G+F71&P,Y#T9@7S),!I197QG#/#_'"A;WN +M/6@GL"5W[4PR)PYHNDN-?3/V0XYUU6G+\ +M=0DK5O$T6.[J7?G]PO<)Q63^601*'0]H5R?2Q=B\OU7!)QQZHI[483_'DGK[ +MSEKF-[M$5C.+3(W$'5HU(4?U,LL0AZP%0JC+ZB@J+;G9Y@;4%8#*C\O_L! +ME`I])RT5:-9T0(Q\N_/!I'`-5Q%B5Y#45*M9.3S@MM_MB^$I2B)C^B&NF2IH7#`B91V=/J +M2$NE5^0H*XV7%WF,W=LM_ET8YLBHI(24$&H5[N_+73?D9V[C'DVBR(@D0O2! +M$`0_$SB0KC],DX8`\'F$C*4?PE@I+#2SDZXR6>1W+_?LNOH7LI=\N8&6]%H) +M?H(7IK?CMJIP3:LK42D$KGU@CUGV#87WU3IF%SS#20E-!"CKTEVT&C:8%+NN +M0+1=U)RF">WW\\[>[BQUUK#G/.UF61IUJ-MF6GIGKK"XNL7MI=$#5T=-4=.^ +M'G/EL)\O*UV@#'CQ`MHX3USWQ)B`Q*WM7_-TSMJ15J5/?.?JI0;P51&'U*`A +MA$-=I+>E+ZUM(%=@\=2F';FIS^]!'-NZP8BD=KC[&S$R)/K$A$6,PW,M3:C3 +MXK,&NU,I).4L2DFK)C'")KRNPB_P_\%H$M&5D5RV4N54%$3G^LGC?+V8!E8S(?8]YH:.^'KZFM69;T^S3]\;0$[">'5Y +M4&F;)PKQNP125/A(3[:F][_ZZFBB,+M>^Z._:[CY8_`L`LDL:D!>4R)\+&`F +ML-2\0?WA9,B9`:O8D)&P;C22ILHAMO*U&'&0"?CW5VXNXBED*[T7:1!FFC)X +MDW'E;6HZU_(2<]A!KOKQY>S?IMWFH1A;P%V8)9+2QG7D_;\X*XDBKT19Q!DHD"M1%6[Q& +MNI7W+YBC^&Y5![>,3+@<_$;MENEQXH@%P%6_U0-DM(JD"W@#O2GF6AP8RBID +MA6J?M0KS*]6XV&U0W5W[W1QI9.>T]9H>^KIF>2I5/;TA@!&@4B=/N*9ZVWP` +MM/80Q>711[`)]&.\.X_D_.-ZPHX7&/X".P'8*.9.F4*STA-C;.F:S7C=*,JT +M1[^),("&+FY"2$`UOKK*-LT$`!Z#I'F+G+5"#`8B*$VQ@H/\ +M;2C,@=/NBFL8,O/#*CA5W:L-]<<5NQSPQ?^><>W\HLIWCM]U#L*3[FW^V)41 +M/EML<([^4`#3YE>!JYY.:3[-KJU2B=_$,9"<\'K'\7S!BX%U@SU!CI$'%R(X +MW43X@)54*E%8TER\+%*'.;Y2F%0YN&X4B\/LID?K +M]$T)J0LC]?Q7,G00![AU;6;S=18K.:8V3-98;H9K#?KYF6?-`L&:V>E/R+.B +M0KK@>INQ\WSZVU:N^+^U].6@FQ +MM)&<'4LIZA+1`X)_:E$0B(+`[E.NW(7(7*CQ +MZ#DD6+M>16C#93`Z[UI%DS]^*F00=_],R_IQLO>A8.\EOB1<,!I;>0;SN%X/ +MXAP5NU'XG/5HG6A6WG(E"MO)!P8PJ2[.$-$O0-]6,/2R[,&]5&9C727Z'NLU +M$^9OF,HD_!GHZG"X*CL[?-Z(^7(&F@WT.04TO[L>UPVY)N:5+^56;74R,>,N*.\-V[5."'NF=4(VP\47=?DD; +M7MT?/;SXQ$[,$RLQ>IM!B;E]7N&X5B,V])'_J?\Y+Y2$ZN-UZSE.]'FXQS2; +MFE"YBMG+2%V8&A"X:(M(KZ(+9:HBR'E^3LFE,NXPU.[A*N0_Y+(6,W +M':ZM6>Y752HD:303NO;0#BHEG.`NHRY3G!P8_82_'Z8H^H$?B1N6T6;_Q55`FRO$4;\ +ME=B8)\A<_W5S]52I`1T4XO;RE`&OZD=*W3A*=R20"IW$8!/F@38>)__%A[7" +MZ9=5[4-@C17A)AVC%'!IQ,JFYNNVG%2>%.]@=]H`B"ZM0UDN*9>`P$(P/C0H +MC'HYK':8?T-$`O5ST:PY.)"&^.KW"%T0`$SNAP69D!G7+_@$%[_N,8!=DPS_ +MSJSXB^.J2@DTO:#3X>U5A2Q7)ATC>CP05PC-15XC0J!10@F30$?-^5]EOCS1@TM8'5;)\I&4^G_9L3OG# +M`I.LZ8>(&YERRV4^D`]T[2JJBJI588?5O^:X_IZ<"X`#GF;[M9+V&$:RM=^S +MHKH'J9T`_"PCW`V,0ZY90*C21.U@TW/[5R[%@[V!6Y@`ES1,OSBA?!"QO3B& +MD>-RB5;.8Z,@$PG`C?C",C>J;B%I6SD=@3:A:8G#7>8G(6D#K<"PE!)Y`AK$ +MCL^`;S#4K8K52'/2#I#>^T&TLJ,BE^7W]!JJ,9L>23?1TT\*J.'0763!:4H)K?/4;^9XKJ!OMI?U_^/U"X>HQ1 +MC%;-XZTDY&Z^Z)9XH[M+?UT/AH!3%UJ\A@J5.B=*8&LE1B3\>"1G_RF?-VB@ +M>+`,M>?8T_:+*2J3*#K,`U62G@0>!J@_6>]<@D18[>Q_"$'DZ$I/`=)@<>5D +M9((%2['-]_I&8IV.2MBIW($\RR9,3/5Y)@@_#5;&B!!W3\TN)^63QF`)!CR=']&V/O&?J5(6.L1&LH>"-5D;&J]=-XO.\_(BGYQ1>!' +M_,E$,OV3)6WH]*IV?P8:ZN0:V8B#XO+P6XEM4F8:*U7H61BQJT9,6OJ%1O+8 +M=>>"_B@<1H"FZ//!!UMZ;,>._-A0&S0J+5J(:KIOYQG-R7N#ZQ@I)Q6)A6\G +MA_0'A(*1Y-TI[8E,%VIGF"R).42?MHJ-Z-F/BT:89\2,L%J" +MAA,-ETF?TCF-)PV*-S%[IA>'+XP;4F%51U9BFEG;^"4-NHC#"\TV-JWVK.(+\%6SN7EWMEX?B5":?HLG>`*E3)R'-K_]]/,`\`6(#,AI6?D8]053 +MSSA3OH(G\G4BAR!1Q0`7<+\!,K<<<'5YEJFMD:#K^[.5R#V'A,;$>I],N=P+ +M"-8L8L+!8)/\(!E=8Q\/3)1X",>NM_`#^30N"_X"8TH(>=C"C#H&YAR9H\Q$ +MRT-^/@$-.O:9'67";RU6UGS*YN/\I0VG/H#A^98+;WBCLE;>TX.A4AD"9HTH +M0/C`_0*>9RILUKYS%8<0+XX2E63?;&;L/,9)8F;YP$JWW>K3K%%/*J/@#L$` +MYT6\&%U.(F!:#R.0S632$[GZQ3K5N2"EQ*W&,`H*A@^+/.4VAE+-F;B4QD*C +M;XCWI3`IL>8,]&$*3^E<>OEX<,$(^K-G +M_O\8;.Z14H=^JYX?M8VRN-9*-(.SX_0:&"A>>S@0?[C+TQ-&3F"YJ^7^@O7/ +M1^0\L%^32];]]EV::N4O:%RE:7*]C#@",H/3_41C5T +M"$*KO@NJ'#-L0JD2I?V0OFS.4.43+5T5$KV1ZJ7[4B9^-/41O7\K/,)O:!H( +M4@RZ-XRZK\9;-M_@PAN_TI/[AM+ +M_5?X8V3HC$Q8GIFG6_5&ZXPMT\"G5,,3Y48OYL::#E/VNYQ9,I(`3#*%G5DX +MB?%9N](^;]Q$[A_QV:O^N@JUSR$<>"':7'(KML\\%'2;OKL&K6PML1S)7[E% +MPQR.@=V>SD"_AQSL9Y#8US\I0*SFB+MOW(^H$&(:L,[I;NNN;92:A2\>#9<6 +M)U>],4LZC=8:$W">Y](?`4U_K[!"?7)K*]+O2P:5%BF`=6-N6>8844K=\O<( +MM&;9RAH2KO=8[0OI!Y-F1W7M=5ECY\I9(FR]M.DOM2 +MQ:<=A#)2=>H251#*^?*];XRS2<.I3?3^DG6>BIMW3S\6%C!^$$;U?.R:!GME +M-B;0Z+:B69!Y<$_5>KB(7W'Y^(JU,`K>I"+HA^O04E5"W]WL;ZS_=2I40#,^ +MU_$*[9D<*]IW?TD]](''(!SJTJIOB2FXGNCV;YH`\)$'P[_$I/@Y;#*VBYMUV.`*@0ND&C?HG#L +MDH[=VI7(:.N6^9@#+%$V;QL_[,P4&1\7M*DL"JR`LL@ILQ-`8YFTU'8^E`93 +M\=]Y:'@I)U"G%^8H1HJBZ\,D0Z#;/ZO#I/EEN1*LK8:!9XED;9]%W"4\N\BJ +M08+\BQTQ`NO%<0D>19BB@XJ.`U*FT!-'T?D$/_U<$3%VJ.^D2F?"]]GZ<)0/ +M?:H`3IUBR/UGA-#R^@T10'#,6BM,\/T9+KT\@$VR/0/AF@D4C)^ +MIU`X,0`I`J8D&K;%8;=1%2'?:(]KLYUA["@"0^67\O5K`,E>'+-AU3.V*A8L-\9$RVC5,M<_J?D]@=W5I15SIX.3O^?O22\.01/(% +MLP)(#-BZ!+ZF<0'3@T%V]IKV?1%N46O%,Y:WPKZ\22J4S0`K-,AI)1=] +M07ZZP[`A&I>!?(C>J6%R3@#N&X(CAY96XVVF!%\=:JS.)MR^6T1"?-C?L0?_ +M\55*_7H`MU1$E!FON$#AW-;#^''%JI-WJ+UTX6^3T@79C(^PD9I;=C$<,.3R +M5>+1^G_//!W(=G'_7E;/K&WW@PZOMW,>U^ +M_&6#TKX+EFTE`"X^8]X@9;>DQ&URYFANMXQCDVLV\_D@"H=68NS73;4M@24_ +MW;=[<<>X.`[!'+K&0J!'*HS"1+J294H2/AAW.'$Z:QYTLB5*(Z<&U&0CVQIP +MGH/%AVO:S0Z8Y9&I4C*MN#R6.>5;Q#F.2C1`0;9SQP)?*\$SF!54`*/)@*#= +M1:9-C0O\[S_VS(%KX^X`WRIJ="A6"@`[$'@;4LYYQ&%R`U]8)REJW+^@5JZ; +MTDKT+NP4K[QBUU?R71^]R@36=PF]\Z8ZD.(>Y325^.%,Q4(_\$5)KU3*'T-H +M/X(>;QWSQ``>/G460Y8Y>P`])/?7^&N;"S3I1NMG�ZVI2,C,N,[FUQ6?[& +M%WY'2L"N9R;$#&E;*D.L*$*4:^9?ZMO6U2BO@;12">>?W!5S6T)6^[=]K#A0BRAKJ7J7/5Q*\C0P-@F8`3KND//3/^U&GUU1NN@-&9_=T_E)?4S +MF$PA)9*>#.-^5/G@_O9AZ5]6QPS+%T&_:M!V^N?+ +MM+=;[&WW+/9,06AQO)O=A$LU3.72*2D!A=TBSC:MJ3#^_AHEI+(4`_2Y]+MPQ&;&,L!\[MZU11GSQZKFXY( +M&U6NA:QVG"S0_U+>]4/H`46PZ@!4;B-#A(`94E,)L""[^,\Q_*UK^++5/SR@ +M,S?]"_5(JQMAG<&WBWKZFJ$0?#_63[>EN;-U=[#=J%MNNLDDYKN)5S)@532/ +M`U;[SS[[J*H%[]3<(ZFV2/6Z&Z3E.1L)^2ISXT/S'2F+4+YK$YY`C+,M6"(S +M@;,Q_AVG@[BE3$>IU3`OE:#B3=4Y1*ZM)ODP0JFG$K:QLK](;NF"-!'7)/G] +MC.+]-`J8:D?@_VA2_LMGN)L`*`=M_MU3;#2G/_NN7K:#WU:7DWR1EE\K3L3+ +M?I./G<(J'Z5((H]2Q;$WF=7XP'@V@`I-"^\NCP\1. +M(??+I%N6?2*`RG[%.S4_S)]6NGK.ILPS8&`IJ++2M"_16\5.NO:,YEN +M>L&KZ74*]/3GLNOC3&!X"- +M7)(KC`@;(A_E[TIE\[]=M@!1_68@[A*7\'Y(R`YQ>BA=')@_1X`GPY)*:8-! +MK(I=._1]](ZD6%/D.=$D.8/1X2[A.M/NL06(%^;)&W0V#1`[HM1I^C[*QBJ) +M6(@<<7&.QK*;BN%E:;BOI>.(^_3'N?29"=FV+2V%_^3,8$K+TWF;_S8&W^B& +M0\`ESO90]T+`6?(?Z>2Q]A%]"R_0I28E#M\OZLM]$@U96MTW#\O,SK(B\"_Q +M6N//XK`'O-=^\8@W,TH1:7CYA*]C!B"^H[:D689%C+#,9:`)@%A?\18;-^47@S%76SN7$F0%&F_G7RY4/Z>G!OWWI=UA(R[9GW9[U<)+N*_F +M9*">-X%;X,TT>"1^Q):?@HZ\>TC3Y>'$#)I0([D(-LI:&'()3^,TFE6V0K3_ +M@O+]\VZ33\DF#8L@XB@Q9/+6GC+F$TXP3!E#)\!$F?$ +MNG#3O9`MEE3YS`RQ/>_5^K)>"`V2CVO6/RA#+?8*2CJO(J6=@35=?+S4Z'.T +MH!4),&PMT6,7!-%+K;S&H@@U1M\A+-/_C1QZ;DE$D'+1Y"FN/(6!'V^]V33P +MC7^SEAX*:&MV">)!5]CZ&H6.NMD:]2%QK3F((UFA5-YI+W;J1KM?Z%0F[&>` +MV-U9]PQ`4+:HEM\7Z,FRRO4UG%^7NI&FQ,3RA\>)%B^<=:V'^P0:%RRH/N"S +M'85XT.Y!_H1CR9QDB*<%BRB4HH-/M*3EI[1-.)'^OT3&EJ:(R$H-\X#K,K^! +M>ASA%2I85%OC,_Y'5KIG'@'D-.=:OYSX<"#N;/7R8H0"^9ID%)L'6ZWWSGSD +MN"TREQ<=+?`P`4US)/RVT]8ATN/Q:C%RET:*RH3KW>DO)_@1I-0*+6L")L`? +M'VDGP-N[F3BAG&I^[5.L_T]79U'QEB7_[K>;!RTBE^Z9U\G*U\?.'^L/"[$# +M8*]R@6=U3`Y +MK$>?I#-=V^H\R^,6?*-1Z'2?D*'[JB3<1_B3KE"Y$']K8#,`-)9"6)F%YU)E=3[808.M32#XQ]5UU'] +M\=NNF$J!;-4?-2[>OGUH#2(JWZ=H%(V#/UN$FB"/L=-E4,+_;R1]_^Z%E./% +M(4Q0JW&^CNGF%;!\K(L=BH]P+ +MJ%G2H,;>:9'W63`+IH#@`Y*T'KHVH)C[6RCX;>K#E5TR5,["P"A:PWZC=C44 +M+A=@?^Q*G%3Y8#]D:.&O]&B4WRF52Z+W%RE@V(!)'Z#YP&]8WOK?8\K="E\; +M$RN.(->]%0@6U0TALAKP4CC,\\@[0;.8XG(>CL;`'.>R4,\WM<]9SUUG?+,# +MU1X2,-Y=4;OK2.]+O$G8V;D.Y5_IEI&T<6YX<"H!,PW%2>/0PSA*`C5.5F/2 +ML`$53Y(-Y?]\EE1G1/W(1-D*+&W&!X1SQVUJ\7GL#&G47'T-W_1Q8H[/"*L@4L< +M63HB^DDG-5&+$2_\`"%H)G'1NV?"-%)M1(:4I_?<@.C!T$:0K5VXB`VY8/YQ +M&"GNPNZ[UV#9"'W%89=HN?^P<+ZJ;QUWE1!)[1@.6>R&W9EQ1?^&*3G_I7$N +MW@!#4R:2_\?V(#@@0.6*,:SU7/A:IP[H7=&TXHM(AGV>`2CK?()U6ZT$=34: +ME3[BKA;N& +M&!9D=0A32]1;3[VB'"I,IKF+O7\4CR:) +M"J"9_/1#Y\',VW4'.7"8#5*T=+IDU[$7YBFH0GT7'Z\,3=WC&R6-+Z519$N* +M(WI'8GX2\YY$T:JHZ+AY`G3Z@3Z^A`,4#M6MRPXA*@JS24PW$AX\ZC837;2@ +MH$!'N5I>,7Q@>K",2,N-N@YZX:,&6]QE/EKG"CW@JE$S,Q),.AR!)V')0*8( +MG(D2F,:I14XU5O(>XRVF%1BT,Z@X=LYY+(ZQ@X9K=*C\',"G4H0]5.XX9\TU +M-"@!S=ECD!]]F<:>X>&.-P4`&K\7@296YI$1-+MNJ+0@31R(/\R9OO2+F0,TLT;!KV)600>] +ME[A9Y/6S4G>.&/M_/F[XI$G?B*&^S5Y=^)QJ30%O%WO=FO^E\SO/+FQ$1_$W3U3(M[MMDGE&-BNAT\VJ#8<&90/MD&)`?!.K'-!:CH?2L[^=NO'9,6;M5#@AU%Z7SC$ +M-=>;[7J3K::_9@;+DL;B.V?R8L7D"8R[[56CVRU(KF/BBXNY!=C_(>47-,^E +MH\4[OG$K@]KN-FM9A==$&3<9&RT?JWDMK<$KGU>(TG`7ION569YR-LD0D#\5 +M.3Y":A#)+#?`X#%;[!^<#K[J.E.5L4ZOJ[W1U+M_;H[^C7 +M&LM-QM^=6B;E!QH)O#1ZEX+)N;!]K89%8`X%;;OE.U"MO!B[7/.DAD488_V( +M1^1'S(3`QVG-4^01'^U"LH4(YRP/13Q44ADO2Z@_4`&$W(;D,"@8_HUJ/K/) +MA8@9P1F1A6JH%H2`Q7MU+,HDTGX]9'JH/>W;VMBZ,%_@%"V9]);D#?EOA6 +MTSTSW/TE%?W21D8,&?+5]TE\QI?8XM-@LCP?8%QL-6*/UU;F;@^9H5YCWZ\[ +MD6]H;',Q@IMY<"F)@#([MK'9GQ@/@E`=CF83D/WS(MM";'V#Y`573%).>C92K +M-B#A.LP6L^8[YV`*O+ +MX2J/`XDV'=71+I8`\X5C%H6)F#MET0F!1/E$.*PYXW>/1_4/PF7#-CH7?'[< +MXCT1@(L'2ZDGK8O,86:'SE^V&?NZ339#VCA?DOL_/&HX3B[BBNW3UCL+7NM* +MTQ61+?2O8;W?2->8]8F_ZZK`)&?<>\TP?@!.16#J6+E)?=Y:#U#F5\B/[K[& +MC)N6WL'45Q%=*YR.ITP5=SN7(+RW,2@)!1A.`A369:;+GDE@= +MF=WXB:@QF;V_D.*!T!I+B8TTJH,*[FLHADSE6(:XV1T9$;5-]PR!2*Q2:JT, +MU8"%/!O%X+-^!XBE]B8VT%L@8K7&_H(:T,^.>]RNO`>BVJG.6S?N4!]$X$82 +M)*CX14D*VM'.41_HQD@:4(ZC!)K;T/')KV?.XZRSLGE'A[PU7(J$(/8@(P/J%K;E)NCQ+C#DR] +MUC*Z9Z%18>G!LRN!?M>6>MQ`$1\LY@N*WU'PW=R.RW=?`AZ9;N +M6Y059*+-1IX-!FRSTE-4")KXP':X(&7ND>E`\-0C))GLC%'?:J-(-#/V<)@T +MJW=M3KKQ7M+UZA!B6CFB^Z<5,*C"J.;369RL5KJ9HE9!?E)U"?(]:R,ZYE\P +ME*J4'\4SG$V4OQ[F%@'U`"@C),H\\O9C)@C391)X?G4,Y:`?,5JV-^%UL4'" +M^HFQ)`0=H=C\;GF88)VJT0T6=M>#:X[SS+K. +MKZ=!S4%*$%;B/GY\O]`P^[M75\(4K`I>6H_HCY@Q(E2Y]5]'=#MS%=,QUE"S +MTK1_QICT]U.L@;454+5>\G*_-NITC1]$@V,*KUJ"*.O1K$7-B^_:."`^Y$QH +M9/(=/[T-HL^2>E_(5W@T#&-SY19L/%VSGA;GJZDOS&QU$K/S0$U7E"B?].M# +M6N)B@ND*W!P`*KK>1HFZ4I14C$*L]L?!NSU?T[;)R5C=!FG>SKT(-TZY'#6EO+QIKR0WI!.?_E)ZOSH +M!K#%D24=EXH%&S$,N#Z@SF>KQQ>V$#SH/M.YPE +MK:"CAR':OQ#19D+!7?C+X`P?'N9D)'Z[U3T!8H(E;I0.\\/,(SALV.T`A.:U +M*::Q.`47CH+>3F2LWXT!(.`IEUD,1.IEBJP])/Y@!N0/7\79:2"CHSQ3#NTN +MQ\ES4M:R.:=4UA(IHTUO@U0O\#DTH*;5/M:&SB41EK4@^YY+3=U,#7XZHJ@R +MFY'0\*=P,,7&]I5>IR^Q'+/AI+Y$SRA;@#!C+>IB&P5/_<-C:J0Y2.K3RJWIV7&-^O0BMS +MT,0H0EEY?,0%-!J(BT)!:8-W5A*RW4;FR/[QGK`\2)YJD59/&Q&/HH+34&1[1345"WE0@3V+?`L.G/VB`MFTNUN +M'V\=Q?!"[K]4S>'$\%8`MM@8S+28HT-!JTEIM5B4HSC)R^%%D/Q&P.DC)].I +MD"_CRSLF.T.E+'K15,T(Y6(E36GF=Z102"44Z7.JUZHCJO59`AK#@=CIU"%M +M5T>;+PS98I;#,[@N4FW:QAPV)'!ADE^8I?^],P>FK`<92 +M\G]Z!$9&TV&$DI-64-CEU^]'3)^A'8&B9#*2^,!L7^/3C662SDX9!F'J:`\' +MK:OSG1XM?S^Q+VD&AI*+Q)NLY42PI!PA83HJ!VNDW-94H2(GD`Q"1-X7"TI1 +M:CK+C].WAGS8J".?V>TOGT,UMCR6/;_Y(.G#5AHDPWX%2=2&OM$.(@BF\D?8 +M]GB*FHZ0JWKR7V`[XO7!$,`.C/*#.E](IH,`,6K.^(*L).L*J(?<-I>8/@!M +M;UKN4365)QT7?\HZ+KVO7#"NW.E?@JL&:(MUN-V;G^Q;*M3(&-;A +MDWT=^B`H0D,/E,Q"&:9$Y`4UT&@`8+H`AL*MH$?+QR=%\!P#B`V$;9IMQQJ@ +MF5XD/303*PJ=7[Q_G5BP![2?1Y[#9#$@'VQW3ZO-?8L,4!^=3N(J#LI+(NF* +MW^'FE[[VQEUOIW:77AJSE_.Z#O1=T,Q6"%2:5Q,6J9?_@:^2M]B+;`\I^S(T +M[AUT++0RP\^&)$W3U8P+0#1S^L?Q-\)E +M]<)3O3O@9+>K.(7[P=!'YHHGC"@_-EPFXK+Y;M$EUN,\AYUD9 +MD4"=P_SP(>Y=J#TDN[')FN7]4ZG>(Z+^9!8HGSK?,65G^$I*FS+@[N>K.^9\ +MYOA3AV"^1ATM[28'@@-G&$`,<#R45C@Q[[%8I38/MJ`WQ79.)]RYA07G?_9&HOVU$CR$]7IZJ2>JJ:#[G?I'2ZKF'_ +M0@D[N,L%Y7@0;GT:[;`R2Q/@>66O*Z*B0N&Q]%23+"M,Z"\>O';>,X>6;]DX +M34HP@RY<15K$JMD=5P<>:"/5PA_T$CE/+%;9KIR*#N:4\4;`)96:XO;1=<+7 +M!1NSEI7#S98_\!;DTB[D%9*3#S_LQB&)3'VD-^IF%GB*IT[2<8&'S)RD9>&P +M-I^WSPW$4P$OPSQ+VJW=0@K0/K@K$&Z#_;_P<>`!)771UXQDF/LPHLUY/ +MI0&E-;FE5`I$GWWS2Z`$,%-'UEU/,ZR)T*98)A0!"M$[*!P)/D]IZFZ5+.3B +MHN@2(X>&23VW0,25,P;H;AQRDQ&]#+!EGGJ[I:\!HUY4+_BP)WOXT"PV('$7 +MP%0IHE3H&PI[*5R%6R@FRB3B:`&F[M7GP421JG8)^C@_Q/H?7+N.'0SC?6D4 +MUB37!@^FHFJ7GI$&JX61/+^L_)>J[`&C8SNX*5-S@C +M_)4;JZH02X5OM;UQ@M3PJ)O'Z\KH=;M]_E@_RQB6Z=*4;M&SRB-UOH''$2^F +MM>YF*BYX&N\M7N0;B^[2KCW!H1ZF#(MA^/&!R.Q!H*F%^DFQ).G4\:C@L.;< +M?5_-I124UR+!**?/P$>D#!([$^3JZ5QIF46&&Y0M."0%JD@97Q-5-#3S@)H7-V*T>VAE1+(O=O6ND5VV!)F)UOP,<;A/QN1=XB8F +MG2Z"R]"_4^-2`5HBDJN%5CHT0-GQM`#SY]+5N'K&?6@25"OF>=4O(T"9;?K$ +MA3%=[9>GE\5XZDS0[GFC168?%2?!A\^Y&)+Z\X1_U=V*Y9E)SO\!&I&FL6+5 +M:V[@:_H]]$J!L,0X6W!C(Z&MV'#QMPWK6P[2ZM,?:X1,VB5)4>WR8B-YFL>: +MUNG>2I@8%ZG;`V2AA?8DC_D8T53^7.&-*@D%=8(:6X;U6LR%CL:96@ZRR3`X +MHQ9B^+OZ[AF4)`TF#BX.13+ZBHS5E]T3GSG2J-YPA2A1&GDTR,8I@BK&B-ZC)JSAJ3YP@ +M2"!2U*B$Y.\%KHVPN&-Y+(YOU2^NHKNS#4"9+,5K^[I=(.&.J11_4I?_&PYR +MJ3BS)/OQ'TB_-"X>"UZ*O60"YYH'`51P>^+SFWR-O2@`-JAA[2\\?F]ETX'Y +MW<990G50EA0D[PH#+C\^;49:';^.B*R)!O40E_+@8XK(7.M +M5%A)J2G*YEC12-\LGS&5W:G&0#+1Z%Y'R6%1?<%M3C.\'2&89'`8LX#)@H%W +MXR@C%J7#?P^++.,9P*5Q"Y^-=&OD35V]<(H0LV*EPEW>9>1MO%NZ;TMT-+-U +M5B.E[GF]"&!&,C^'[F_[]/CA1DK$=5"`&0%F;SE*":"ZL8R<<4A?<

    %W#\ +MX93?3S0%#0A\9JG[>,DQP!&129IL:[3V62.;)#E9^G\)-6",@@#_ +M#K0CS@@+FMPE3%O)1B8P,DZK5^/4\@/R('1\7]^HZ,C#5D->!@JT+Y+R."=` +M>(:-2&#\_9&9G0<[J1\:ALM?5@U"E\I%E-;1Y_$C38:1`O6Z&$RTI_[CB]@/ +M^67H(TDN2=NN+OBER$$U/&"GW)S;QD=QB"6A_!A@XU*5'2 +M4Z\+-E[68(34,A]*D2\.$X^ +MNQF+10D'M_Q8T-.N&J3QMZ59_/"P"F/K9G@J=,'/V):_4-IJ;TV-TH='D+WT +M@N+/HS5P;U3)%D2`[*XL.L6GXQ@J+H[?_$K^DP-&_O8F(6UW-PW^NZ#)Y=65 +M%<.>1#9QV#>M+S+`^"!LL']36>T0@T"%VNJ3.;&"X\"F@Q4BPT_T"^3^+W-U +M:DZL77XQ@9']12LL3]:^0!`_#B.LRZMR;ACD.\;$F<@MC +M*SR*%"B=(5Q@`Y[]6\P^V?WEP.=@._J>@#FR.GP8]4H;M/Y]QU#G29R+R\LQ +M25M31W9=C.<`WX@0'FX/UJV="3,LU/>$$Z8;>$ZGJ)HU+8(I1>9^:_,H"QN? +MXQY++0'K$0SR1''VQ432WMB&K.O@K@3L0J4DXN`6!(_MZU9$DC`=N^CN6M%\ +MNZ)9\9&&I1J:=QJVK[]@4@,IZ2CB&T:1*X00+^#YR)H?NB9>!9*7';&&)PC\ +MM5S^1-\GWI)*]/@S0J7PA?=$4.+4&=-T?1MZAUZ<<.M3\MAG%3H]B$J(/E+; +M9V#`#T6%`-?X+(X441Q#56@6J",-?A_1R:WRA5$%.N918O#).(NZ([D(2&E. +ME>;E4YZ+FRZ=6@,$,43C: +MK#0^&<[N%+I-$S_Z'97"?N6"`BV$72?WL:GB>5W?H.L:S3]%<2_W*A-S4+'7 +MGJ_LM]X)Q,8OSH>7;R<#LAOPKNEU-8,A@"O];^6(DC.0HO[QSDEY5;P*C#[1 +M]6&S_N99^?A%LC6?EWGTUYFA1Y/Q7P8(;=D;!UXAAHSO'G?/79T1N'*S%KAR +MA8,;%D;1!B49X?D>!(T<=&99>A/]EJ2?%8<2]AW;ZU5Y0H+DG_X^=95*J%G< +M?CD>C%B=Q+8.+/XI9RIM%RQ=33=_1J8]C[O!Z$7D'^:$C;YH[`.#2+%W7>8" +M;;@V34SWV*$7$)W>4E+V;D5KY[.M2^8\\BX1VGZU&(H2B$E;YGSH0`.< +MS:'`&=!&#Q,]O_\H^T8)&YW43*>\%\GT]MTOMA.\96J'Z*[L)>#GM1S,LMW[3'8`UPC^=J,RR%V">-TTQK3F8^_C\\,<48*" +M;%(<7W=-TL\I"K.G,5]8D3KSZR/GVBXZZN;TD\%`-8I<:+.KC91R:P[T5>9D +M?Y-CFK2-6$@!*!?Q_(MESCV$%Z'0*)Y2]B$I2!',+:M,,94N5M^=U*L'DN!5 +M#`JMIP(R+5_I-A**R+A&&,)]S!5$./"$/$52_0W7,Q6J;P!&UR,+4(,>.O'_ +M,`(?.6Z&,2S#8_#B3W,DLD-T52?6FM+6MQ:*1KX!7[-`AMBQ2A>/G(_B"X!3 +M8>O'MBK`](ON.8L"]F>/.\R,>NBE9=E^-WH(4[@U\4?-F'`B(?5]H"!I-HT> +MJ>`BL%4$9R[.5:JO.$U!2."JC."=>4:]2'S&L7V4'3T;5T`P:/S\[@X,*3\A +M_:OV\GN/3_2_0&PWA(VLKRKC++X8=DAQ^'\$<_"(/)RI;90.$;MO?3]F3\QV%S6!\UU +M)?4QU]PY_2(2@#F"R:?9^>/C@HT,I@O,EQY9,FYY'!/OP\+2P<\>H=1SA="M +MN_0B(%*SW/LYGD%T.17^-D,/C5''S1GS)*1EUO2I0ZQ6KZX9M:4-4UV#\K@&'9^053W\#>!])W2KO.=KA-]7Z8YV?(54P@>[\_$2D"O+H/J +MQJE^[3GJ/*VB.K:,0V0IY1E;'#]-7/V+^8II53-,[1'CT/1D5PK&T+3>=CY% +MGJPNRYXN,%G\]2"4K,V.!8X,MGF$AVC;@-B9:Y$9/.FEM(!&J4XO-/%>.!$)F0?M" +M\=.:5Z/-P)AB]?"J_PNJTP^JB*G><[M_\YM9A:C'*CBLX"J("REMJ*\^C`(, +MEMT)"3E"/%0HD)%N#\7RC6;\MFN1Y7\'=/*Z%HP]R6,8?%`'8\U(A:1>%R8H +MP5=BV>=D9G>,'&"P4L$X#W`TM=N+^'#XAB]%"P#I+:2J"]%`G!P#Y1^Q2)XG +M?Q:`D2.+HZ."^9[1L'YD%4:;C_ADS97(YYG/9+$=;<\8$"#N#RA +M6%Z]&VV,W0.8QG66E&+XH_G+?>X3N.K;E4;,*1:G':K'[,JO7!% +MZ03(QNV.4,%N00U,>N\;2($<:_U=7Z%F],\'%>%NIVV2(4VM9);!C3\AD`"Q%1A1W>"X$;YH]=HC`LYNIUU/1SJP\/0M5OU +M4:M=E?4R#DA7M-2Y[MP9-0#L_.,7O.&&$ZQM=_X:"@L\[4^X9,69+APO#-#_ +M3;0&E+9CP2X_C?*A$IN(N-\4S)MZ9%.BP5Q*\:#J#RW$'*&X?]BV!^\Z=4LG1$;%-HRP4>?,C%('="^TG.LR2#%DQU*4*W>0ZK>S;P&A +M?1]"MYL_J,\LV*9_F`0)!9>&D`6!)`E_\2X`UQ=G/MH"+B6FIPC4<(JQNX,) +MH1SB^=0H*JMK5#R+`M<=%ICK$?SSH*>2+*B_;OW]*3G,;"*7'>5PT3&O]W7! +M#],(2?UURA,4V'RM)QO-8U^FSJJCZ +M4[3;38OIRHKM(Y?\/\O(T*@7R3)Y]('9:]$U?HY#>)Q`T7-A9[J#+EB6B[); +MWYH-M*%H`/=_W;Z%\)0ZDC"@50B`"R;PA6DFZB&ZK0QM>@^RJ`NP5#3)02T> +M3J5XYKRB/-?H6&6G91]\S#*VES\/+PKO7SN$S?R^T!4UZ,71Q0VA'%F:U8HO +M-#2]&\M5R@=>,]F"E@KDH!#BLX9R6L9].]U=6_?F/SLH*YG`=()[`QE2RQR[ +M`G_?O`,EPO%=2G[8/H9-K9E&84-J8/E+?7E5C1;=\IZLRHPP>/P6IO +M*=Z_9I9_]&:H2B0GR*[:YS;M8605S"@"M#`G494I==!=F\T>SZ(&1NEPX.R?U +M20Q4QN)I,GHNA]G:R`X;*M.@9&1A4`@[@&(M:2!(\5HL+"G14+-MZD$9.5A/ +M<3\YG9ME=:_PK=&>_0Z0W4DF?.SW#;;<>X4%;/;20+E2[]M%HW4TD,<79E*B +M8\E)-(NMP^M(0L4MKS5IB."`T:T2_CW9M^_N],.]&HF'X(%;FUM`\=/BKCP^ +M-97(>E6G!GXYRWP;B$%)=]U'\$MH?#J4*J$H)+ZC@#"ZV1--)@ +MBHA(KCO-@^,6+9MV!#$]#!GY*27>7D=JV;-4#OC'"^;97G]+>94N?*!E,L!* +MG/A#YQ,7*-;-6`WA(Z[+Q4R0-Q)DU8,ZK+.%-B86VQU["9<0`^1T8B_+,=.) +M^.1%C1U6<-#BH@6$+]O=>)=AD!TU%";`"?966.-MFRPD?M#8HT68X!SGZ+5ZU)5]T[79_3P+Y*Y2;8K%JSX-+SK)5 +M[[ATBQYZ+%^-C7A>6-15E?#;#1C>!4374K/A'A<1(2R@0:_]A\T:]W<"T[). +MB'GL*NO%AOI8;@\4RR^P98U`(G?&*Y"#0?(#'1QP20FM`,<,UX7.A!`U3P[P +M9T2`16E6T]'^D5>Q>D-)RC!^P5E?IEEG,A.Z0;,,1&Z'#ZLS$"<@MC=PL``R +M^I9-L]!3/YSL`J!'UNW+4U+_.KDRP;`]DZU>T((Z=9"`A8\[3L%HCG^T2:_- +M[D1J[(>`7[R!GZ#A/(JUXTQD'+]LRQL&>!#^>.K:5/QHV[^AZ4Q&+%,6%^%7 +M^0`L4@["?R-1+_:B<1)+^WGN1":;L4(!NB/WQ@8$._@-V4#]S&`9$VG$U*'F@*A%@%1)H?(,?ZD:*%O2`AKLC]G#,TIPM +M&Y\R`]2."A290U:=Z$SL'UY7B#Z)3_;&PO,+6D.0]Q-]"A@T+W&#*786. +M"WPC2XNZ@%R$CX/])Q25UCOKC"!E*?$?>FSA2//=&[M^["Y%,_,ZL+,',UT5 +M0[\#7*$X[9UO.(HPYQ*V2DRM7KFGFF>87#NKK+U`;WW2D$TE78'H#84%D9NB +MKK)3,Z3DC?6L?^%4D@MF?V)CY"EO?LX+Z8N"5&Z9-]P6;XG0ZHV8_?T%KBTE +MXMO:G7S'?([2U#JV8U6.S4S-^/RVC'JW;?36NZ=?$+BHK"W0'[`\>S+8O-<" +MNA$M.8"\#JJHM4E35:J#/."9HXD8';)W4PF-;A7DR0J/`!"[-I3D^O/N+MV= +M+R=H)GM@/GQO-9F,#5QX2A"^+FZQFE1]-*XSF`1D=0E!*+4EJ<<<,5%`4[Z-:8>7LS.]PGW2%'LL&A&;(.N`G,> +M.?FC?$3X94#H0%RQ]DWGQY05^W<6Y(\303VWXJN^A\[5VZCNM?T^OBA)[H/4 +MCF,+K\P+WDAT-338_8/HXVDZ,/WFV![E +MK.546 +M$L\@\IG>[AIRGH2S*EV!I-SCFWB-H`Q8*E=U!)V#ODA$FF**]ETS2 +M+^@Y@4;K?K,$KJ-.$Y_A7VT9OW)/=;IRC9`&MEZZ\?":[(V7KQ($=;N7#!B& +MC+R<#?+L'9&2CKDR&U],*;K$6WLL^MI.5$"L-G$VDMR-B%8G5U4[W))NUI1T +M1#?BX%BE7M;K=),A[[%3JQ_-KB +M,#'3QH.CRK%=S?4#&<1Y2-(C;,J:M\>OCDMI?#HV8T6L.V^3Q-ZVD\"@(B_\QC8`6SE!BCDD=G#N3^0'L!>>#LWH0B2I +M=;=IGHO=+AO$"_+;CBZ3+A"%OX@1C-DS;&$F4F_Q+WM8QT +M+1S71<'\>.(>6X!A.\Z,J\$VE5$HU.N;?.7PS&0D1U(K!4_J;_1"1BYPDD$H +M006XAD'I;CLO*MK277M&PDD#)GN:KKIU*C2P%8_"V,\;FH/7V*]H?0GHRVW7 +M*OO@_+"-<&2BQ!2V.,"0$_17U8MCQ<2"S+;GTU;V@RL&U,()]9%4=U8SO]Y-D#K&@1D"A_19Z-)CCT"0]6MKH.Q07GT1@/H>@%>ZV8\;'6!;W3LVSVP"%V8:[; +MLO/@ET+]DO#(AF93T\#4E)Q<(N7=07*R[Z@RWS2MJG;$$EG`4LT>47MTHA:_[IEQ6QE/_QTL!V5R75O=0>?1UT?[EFJXD)2>HV[;"-: +M:L8>I1[HZ-;_R&]_BLR4DJ>%,&DUD4W@D^$!=?[I)D\P(M9,^*Y]*?@[BE:/ +MZ7R'*829\'KFX'N^5/<-6C[K?G_K$'8&)_AE8-D:QJ--$'6M?A8K"-:LTW.4 +M7G<]!M`_5U4ZD*;>(/Y_(:F9V&DWZ[)`G27_71KFK!UK>A0L7?#YK#6 +M",D(!W;@O+YQ)T#2*#?LR9R>8_U!4T8D6+IV!PR.O1%78.I16Z=AD`^%GR +MBS3JKY5ZR5>\:RJF6$P,/I9;34%9`').(XKT6+0Q\H?@_3$#$=ICC;SR?""P +M9HL'+\N+/X_,6;;31_T3N)]Q:QJF,)QQ*W\F2=6G,[]Q-E[0C?$_X_QWB<@> +M9B8WDG71](6;'B#K22B1R39VN_(0VU[R\)#0G/;;HYJOIM@\3$FO]!;890=Y +M!_O'+$S8%7)?YK=QCSFTM%1CV5!!B96]B]%RHI:AZ!Y[_3INN-S>9M(CJ510 +M^-6&58JUA/I;R(@/2:4\ZDDT6??6#RL08W]3&-@P/Z7%+.0N3!^$#3M'I7E@ +MOV1IS)V8\3&[R3ZXOW4F1@V44<078Z?&IPY?;.)W+=/HM>^ZI"?:*BS^FWY* +M.&?UTY6_'7AC^.Q.'.*R5Q8RC:[RU>?KU>+,\-8QDD*BU4F&@I$;8:GN]-:\ +M:[VBJ&=VU[S@!SHLR+N^C;_*J>SHIRC[3.$67%+Y&@]"ON;0.9S +M<:WV63(G3-PW-;>;E6'K6N/[';Q,./=KTZ5RFK'J_',A[J+Z']SX5[[LI?)+ +M[4V`3XCAG'=BK`D[\H?@B[^.PLL-W#.GP9C((!#K5OY70^/JE25RNL#A9":! +MS[:VBN@S+Y-P6!1>]'HJ4;@$-(4`*:(,MA3'!+DP@)_^2UJ&E-`T4Q;C5K5@ +MVMKTE0IME]1_,$Y$XA9'_`$A1RQ/:]3,(NH2 +MA+S!H2?!58Q''"=^$/`'3#^LKKYMU)\XX2O$ZBY_)P\PGT.*55\WOX"58IHU(\%U,&X_-*?\0^A,$8=#4"NNY%MR`?D/?A2X+ +M\@*IA']L%Z,;;M&U-K]^YJDA>8/)*0WQ^T49E_2%G3IJ2X2H#F[GTCZADK>D8%Y09U:!>F:\.&/3-)*960N,4K'?Y +M%&N"93'N)Q@->^H)*5-_J](+8F9DLKGMAULB?*8*I@YGC2VX\LWM';0Q>[:^ +ME +M(@X[@%]W4/IR#H#Y)9*,)P'G&^F-*S_F8,Q8ZT8K2$"#]U.\99T7@"/.%%D/ +MFW&W2RXGW"C;=8#H]M_Z%GRFH**4E#(!S%8P03<'=N]K5]WRYD]R#Q`E@:L/ +M4F>+,>^-5(+6-ET4M"!>=10E!71K@Y[ZL=]=^VS04ZI>3`>!S*X06$V40W^C +MS=3^!,7FB::@#74REFB=C0@GWT*2SF>SOR)?3]L4UMQ>2U1DOYU>"]9=\/L/ +M.^.VIZ3)-W![MFN]=-@&ID9KU?;K_SER;O"+OC4H6 +MEE9^Y*Y3KZK_B:QQ)D-Y3U2>/"OC#VJB5OF0G&XX=XBO=E3-"C_0E/TR2O[7 +M#&PA28+SF;&)34942\(HB+'7""VYU:??GM-.D.E@?P5*N4]LGT.6MC#,'JU, +M@8XV0YU`YE:G1-SM[".V1ZB2D)ZC]/=2`-D,.H(AAP=`?E6-G*$5N=O5",H3 +MZDQU$_Z"1L0#-(+`Z.];_`],ZZZSSTR3]!)V_:$G]*X\R89^V)4'S4_)B< +MP'8&D"&'1$/UGW!Y>\9._E[86CKOV]?NNS^_'B23E.`//:\,VE+QO7FV)&J_ +M!<1^LT^*;Z/FOR7*[,)K9NIO\G`F2Y!AQ:[I;_7L> +MCZB3UM%*',N$Q`,);!DS']V)2[NIIQK:.`W?KP8(_-M<8E([TZO;SK=*30X8 +MR+1=1J;U-IM'%\]DIG%K[U4(PL)RN<>I\KC2)[3.&/8,M$9165M/;GF%&;%G +M!*+"-][0MQW]8.#^"0965&;U%0P@&BY=-+;?,TJ+BEFO#,HV-`-&&'TT9UOW +MBK5H-(SK* +MF]1I-#X')/,?Q*N"J7\RWUE[>A\1D]2K0K!GLII=$8V2-!9[?1\L +MEP/F]`0,O.R5"MD')'U;5&SK>/F[ +M-+HF[;!-;#";HDD'<@-`%YDT14I+@O;QHILKEB?O+"(D[1`C&5K0]PCY\N<( +MJZ;V#.GU,D]%QS#=`^D5I*ONI1);#:<_SD;!:TH(1QRW\<[K^;PK!CQ%NMC% +M]-HGV;F4H5MOX_HUV_K>S5:18TV"YLZJ5.\M3%JX3[:H3^E8%>[(:[ZR?461 +M@*Y1)5S,FH61;FI`GB2$C)2_#&_2STRDCU^`IER%6ZK]R>Z^5G#T>L\.AF(2[M3(\G\`T1`O15`L%2;5E>;@1OZ +M,"/N>W=:!<<[J8ZQ:SA)APHH4-$X_.L/(:\:J'W\YNTZO>;>F#$P$E$'$CGV +M^(S+0I-D.K!**:NF'\J2-@T%[*'Y2\OGB5B[8ET:"/^]`]4OQWU4*1AQ41^N +M!J<.'2]PO1+`3%0:/GEDGK2X3`]WMGL2V=,1-X;/=SQ8=(-AL/$@DB4+<",P +MDN4=Z,KSWN[J(C`0*AYR8Z?)-MVMV]Y-)_Z+Z[LQ=5[0XC&Z"GK<"RKJ0DV; +M^:2J+K4\-OF3=M-/R'=2=WQWV6AN"/8]H` +MV@P81SK(#!G=OY)ON7Q1/)ESF+RJ\C.>U/:-;\@':L_$B##=2N,>R"=ZP\A\CK4&NHI]SP2(2\]3HE?Q0JH*];FW1N/#P\_:`[Z.T,Q&L-2+:J +M3'TNZ=+8P@S>,(\#,8*RPB'.[822>,]1][)&7(T7*S+DV)7=Z0$4\+YK>W2` +MM%;7N\:D4+?:>"URI.S%+K]#(N'\?$,F^MH2&I*9DGVW4O5L*&- +MSG?:;*&L.Q;'5+?%3E%O6N+F+9R#A+\YJX\[BL[7*,JH&-XZ9)EJ8];]$T)8 +MR\SN2;QF,HJM$5:3*HU`#%?,OVC<(F:9>0#GU6G5/2PV.P'Z4CFX\BC:E +MO*-M\34PXF*P@_/8X?99`]8\EHU^<9\.0Y!T]E&I#TV*KV0O8HF#*W)U0F<, +M`UJ+$2\)24+R_V>X!=[&7@R!>+4O(_3^4.20[K>8!`9 +MB//_Y<65BF:D'X'TL].O77*%-HZ=VF<'W"1%4\VWESPUR[,P-"G2`1C7+S\% +M_>&S5?-AT7*DR/!F'!#JZ$"W(I,\RE!/09G8:^B7N+%Y;B)"6YU-EDI(2$8T +MK_XRH7V.+HUQ$*"-5'$VHP]TU=$`4K3R`)39\$G$=,"_"&=T., +MG**)O\2W=!W8E!M4APZ#?AS@-V]?@JQLP2()$;/P/:99WW^>8^?[M`O8).QZ]:WQG&2=#^.I!J* +MR&^K?M^MA7D3XM'Z`.G!MBI^'Q'$:P/VC"@#S&DNO/_Q[[KAD60QYF,R&+)? +M69\L-B,PW*%L!)2!K."O[U598!>Q>Y;,$(O?#RZ":W1;6K27!?.?HG9TN.$R +MQM?Z?YA6;OW@4._YUM5G+ZGRME8]&CT*5ZCMUYNUPS.^Q7*X74MXXP1+Y_:? +M?[*?[+[KZ'Y!BG&0X>/SQ*C-UW?;P0EY49N/,&3>//%T%$]"(*ZC\#R+V8Z.OQWPH!=`#:P/WD#KX%"[H1T,>HHVF>-&U5O7M(9@;> +M4J*`M]]0A3#Y75G&XEI]T +MUD`HKY=8A#C@)HE*SDC)/>$5)#MQI+:HY/YB@<=/'1))\Y?]QJO$DT76KF]- +M@J$%K1*V]A(>,Z"RF`L#X5!7,>PBVB]BG'%QW-Z)LM\'J&38*%N#ITA#MO]* +MM\Z0@R`:_UQQ0CC]1G3Y[:(XIW&MTN/*)8*^ET\5SS\JLO%[67S;H@[CA+CU +MRQ4IQUXMD[MX`3)!7GBX%Q(U[^W!J&)%9MK7D&4DDKGAI90W?Y!!7_PP6!.% +M1HVDGJ("W\3N+(C1"/H>IUY7B!=1B4PWY=&-!/]U3,NBVRXJQ$3)=-HT5,;? +M%5#FR`34OPLUFV(J[O#:1TR#ONM"E!QGA*&_4<09@XM^U=SH:XFA$:6FH,=:JWN$OT8".+BZ5GU$OG>">6 +M%R$^EW6#VSKNO=G?=20V`A(%).?T7KY+@-Z@M0:C2U`>Y1\&77+KMA1F]\:K +M&V#C"/E174738MXXO@JNFJ\(H-ATA[_>ASG#XYY**H +M8GVE#J/LO\U0NZ#-[Q!FO39&FZ!4"O18(,&7PY6>R>Y0FDH^G/,Z$@8!,LVUR9$>58[E8KC +MR*`JF[-,E86#/"?^(B\(AHZEA$6>0!HOYP( +MQ3=\@#8#`MLTJ1[FD&=])%$U38"#LXGG1O7R';;KMA475N'5>1VR<3(TW.]_ +MOQ)C&I>)=O +M_LL!^I?)1`_J^.>G'@@^GN>/0K>P(1%-&EEG%10: +M]6F/&#P<]5`<,M4@$?6J,DA:R>)Y/"<.1/`*`,1W*H#Y^CZSBJ'$6CC,0QYI +MAA);2&2>)T\JE;0HZ[Y252]^9$%8$32%EB4QX"8VD7N4%N\_-H%H-^++079I +M\:C1@D+#LJ3.WFR$,8V[[7'P6:XT?>#^I"6%G.LXD![>/).O_?A'WF/+(WTT +M"CA`V(J5A,!,:Z@^/\M,Y;;PHHC<3&,;%./E+M7^"1G&A/J6%.:A\.0*9^?OO^#I0(S,+D.%F29D82;\Q,XLX05 +M08Q9LM3\D;DQ2^_4T\,CLE.X43:1NEM`92V=EKVXTCO'O*;\L:OI($+?ZY'B +M;PW'TECA:A%%$1]17V;.-K,/E;3"MF.R=*48GY"W$RAJUD=V7#:PM'0L<#[K +M^HNX@Y1CS89B7<&$\:\A.^-?..+"Z&LGO$'],-&S4?Z'))/I>G:T[RXG%^Q8 +MB2"E@@`+4;0E,#`8IN!?__C'%KY)AVH8?%54HE3HX%D5>B0-;#N7O!$1OWJ' +MGX]I:9BR^%%LJ!&#YK#%)GINO_F:)X\^.E.B*&]KT;BF;602TY']K0N!X2OF +MA@-)>\VHB]B:PN6@1%K,LT]E"H0&8E:COBC7$8FI.OW&]F`JCM<&.NP:F2O; +M8J!I<6&.GC=P#9K7)[:'-5OK@YTI2N.4-S[-M49Q)1ME&]=FA`EFS%-G]>=I +M=#F#3+*3VH0V$/Q#$;RKKIE[QMTNKMDT,-CVM?1@[F&/`85(OXV+-_6!5^GP +MFI-,J^1/`SFYI\?>+;ZKCJ_N%KT%N];F+2 +M^+)$[^#%V2GX!(4R_!EO*6,"VJ%?=;FIS5[8HS=>Y($/9KWG68Z-C(!D[\-F +MS22QY/XJGU)/7EZ2&+J0/]83J)&S[@[W;D]9S,9Z_]OVM4-)24WD1`9A'((P +MEZH$$%,H[UF*-/^,+3S;?X:VVY&0F/PE65^[4+/4I:%IK@'$D(G>ZNK0HUHZ +ME4`BYWFJU,^C(Y;IFDU7_&!/]%DW*&-/B&6 +MY9"^,YY0R^W+GN,*AO,+Z>5;_:8C1BOK.6E-BP"?&$1U]"&LC:^IA44&E/Q" +MJ(MBQ1B.*KD5!;P78*C&"[5*BMG6ROPEF\'+!7&ZVX;GH\Z/1A[CSX^^B&^; +MZ6D@M,?.N$5GF37BOOM22\K8S#1@&#G'LKPMQNDK_EYY(-U,3!#*/#$M +M&\!'*&+Z,2*L]!W9(T&^2EX<7+%L#!-5'@CIJ`&H*5@P'?4VN@,'Y8O.4`<` +MIQK6.:Q8RR"K&]?:]2P&$&$N6=EM59- +M"42]D5ER]/9[J153P%6\\S%59SFF+=[@,N):3_$S8A6(*:5$+Z;U%-Z/T7;*2I:3\XD?KC"'MLU#W[A=,%DKJL)L%0L5BRI4 +MD1Z\SSKLBWH?W=P2"OZW`22]O(VREV3CO#0H&6CR0?R)7,!8;I,[]X/CXS7N +M:DQB6C__[[&Z$&%L/;AZ\X"ZB*-^TIER4T]P7S6S6<9OF3U$=;)*,LL!+J,' +M99VC$PAEI)OF7^Q$;?_2%7X)N&Y9(B`'DB<E@O +M7.#T\PNO4`?]U&1<5Y0Z*2).[[(H8%;G@E@4AEM$E`GZZR^.`XRKD)AE1/(E +M'!]M$0-OUF@0:JL1OFO1)>3]@M3_]631D*)G"PJPP7Q'436^Q`>NU]+J*CR^ +M]1YAHTVT6540(B/Z6XAK(`-CS&KB?W;5/J+@!5FCFDGX +MB^*RW8`"?-)F)+&RHO8"WR,*6'*"AZ"^T:(QSUD33/X!Q +M'(!+$[Y[,*M/'GBC&$,0!CLXH/S(QL8``>$CN<;R/O\N8^_B_]:5Y2()BK4D +M+GXAY.X(X#LQ`;UYE28X=F^;"W^S0TBY=/,5WVOL*IZH;!VC$!U&2T$_,)[P/ +MB*'\U+(BK>R2>'AV`SA&'4M49MY1IC3MF-4Z*4?I72/&1%Q<(B-WY#,"8706 +ML1X7T&?*WP^U5*1"\HF&:XOPL,0WL*K-RHAEM@!_N`BEY4VQ9PY+25H*_O7G +M>L,"\2-1J=?4`^YY[])`R@+62!"#>[%Z@25/K:$>I1E7#Q^4N62K;IH3@K^< +MHC^81,M0`1_>I2VCFRF_=]AF,OUC.MP#7Q1K<*R-@81MA&8C5PVWZY4+_L". +M/X>A,]*0TC)]CH57O7'T^)(W^C7297$\CSZY +MEG_^@$41/=00#5$_PO2):0IOWNJ!R3+6OC1CU!;.)8ME`"];*(YQQ]SO^X+S +M>R.3"ZF.2/Z6#A8'>6;KU$Y@/WE_ +M_J`UX$W4]FNTK3BC#+`U'+8ZY.70'NZP0[>F#+N%;^(B(.J/@0]T4?EP363V +MU'P/FD>X7CJ/;7"=K*I=Q=8ETUJX)]^_K._',,GC+`-".'DI8QL8O14!L#_O +M;X)7T6[S.5#18=>,`.;0]9KEGC9GV_G3%84ENV?KVQQO=V-":"J,MPA**.L+ +MLC&`,]W6\M.1\P'%/:.8..9%U`4#=)?[YA;8.=^+%-8+?%VL+QL;-A&7W$9# +MB&X1[VUZ)W,U8NPOTOUTJV&!H-EX<04^C5T#6?;7P[%A[[!D42L16ZNSSCGS +MG]M]P'3.$.9/KRCP=#(OH9.'-FKB(3U*;C?G'PK`S]82M:KQ3D +M+7"2DEAD_JN"(*?2P(,O6?@N*HF/SPO<"`+6L]=%R+28/FRJ]YA_@S;;<`[:YZMT5MEVJ/C2Q2[SC(:,.I2>=OI%%4`7 +M*WP^8[*C>TV!=`%D3>0H6;QY%J*.S'=@D4>0'U:5`.6:H4-.TM9K! +M,A3IGYDKG%7K)PV#S/Y2^KT7_R(=V&5OP9)S@UOY[/6H5Q_*">+$7S(PNLSN +M-A'UCZ_3N#=/P:<)%)G9VKVNBB-74^LFJGEHHV0)`CSGVW0N"2<``]N!IES' +M!-P'U;5-2Z/MN7@,EW+%:O>@:+=C`4BXK\\>".P#(I,Z>FQP>S\:M5F=6_D= +M,1/IMJMT.#^?PB.WT6;W1704(M8/W%QO*8579QE[$6?4P)TH_I,IR[7C(@@D +MQ1&#SQPJ6A]13O`1#%9#AOK$.4;[$M6HMXUBI56V(GLJTFU$X6?);2"Y1SO@:A!L^OKP/B@A0Q1_Y6 +MY6K/P3O%:I"3GMN$T`0Q!AK'L+:[\-W328'_G&TX`-9NZ%G9LL/&&Z]%D#AL +MYN8O)050F&IY3K_EIJ5F#]RHKH$^?"TAQWIS"[BR@^GSWX+A&3Q6@KP]JX2W +M7N,Q)\BIV,#Z210R*6T\A-?P&#\K5D!D(1>[A6C2T6L5C@Z^(0DH1]\R7*^> +MH5547L[Q>'%;,?V&B^%B'+5#`O/G3J0HPI'/-,3>T/--6OU'#(,C%.19]R:\ +M_?UG1S3(GXW^TO=B2=`EJO7%38&*](5K'7:)(Q_](HCA1]#=0'!`"/V]\\E85@FK'*6"O/8G2JF/P!@ +MJ'9?11H-OU;767`;\E +MO_AA*+^/0!'&Y[@)@PI+&UV19Y5VZ&>`L;M=B#DO$\6:LEB$MD(A87J#D +M1Q$&^?7"1A-IK\:NX1'/JBO!/03;T]^)>FG^SA+U\_>\;%5YA_3E%:R\Z\L^ +MG=-A@*^S1U*T]T\X2@^R;;3S()G<\EAG53\0:3`0SIU-W_]U=!:E+(SJ*[FE +M-X+C#[H][.=4R\9]XI-E1X;B2Y,/.-U8%ID#3F>M\9Y$ +M>97[8\)P:/=>%C5@CQLF@IDL>$, +M:D5J&G`6MWU$&%41RZO3\T]KD>=>#13%L@?IWA9S!BN"C4M'/03:=928J/5B +MQVAGPR)!(J`:0)'@7SC`_DH6M.[Y*P3.KJ):$**ACI1_2@8(G$GB,@`0HXV` +MG#KZIB!]$^,JW);@IWOX(3QI5*#GJ'@KK]`XNRR0T=]LK+^S`MS7FFE66*C_ +M_:TVRN:8`EB-=EF-L::"60MH?V]CGJ'-9(:'F["NZZWEB_'6O4@S\_<4*\C] +MBPO`L]TL:!2.0L(^YH.MCFRASUE1G:+*'EO09PQ(CK$UDI'8/2#!MKY.-P[I'4>T@K)A +MWL^*WX+6*M,EA1=I^R7JEFX75!\EN6>?*(V+L\:6JJ6JV08F1U!0)N^T;0#H +MWY#S`>=3>ZB[0R;&#QSC+_>NPX:Y9.S7S'G!Q5DTK(N-+)A0WYB+VZCB!D@7 +M;9#)RE:[0,DAHU!83ROC(LZ]V;7BF68"Y3IEP7=2!:;6(@4K58JV<-[0%,K\1)^O!:.]Y53DOT^J'\@$W81,V&],^!+TA_]5&MAZ`# +M,O4Z'>X]&-X.Q`^=$,;WB:HP1LZ?TN,ZKJ*'4[)CA:X_>5ZH&]P>^H&JGB++ +MCB[YU1'6'_'X+Y_@PBF*5R%EL.'!NZ?N6\XMSM+0Q?(<\N+]5\Y/U-]I(?5_ +MU0DV*T8H$6;3C/9YQIO9YO$?9V!=F9:D@#=Z@!=YD+2HB;L!UNAJC$]SGK +M[;/F=[%_?I]@T\UH3P8"-RM6'MF(;Q%WKL@M8QXC&,\N,19K7QRLMJ"(*EA6 +M-GAHM5T4(WT9;4O4=?]J'W\:!;RA*FZ+C"#K4VUM`C9;^J[6[8)L=+1H=? +M!'2RB7H3&>=F+D#G>1>5AD;#4"WV`7\"A698*)MVLPU1USL@'KU)P.FAG;1_ +MG/N^'4?\[V8?TDF4?4)])$-J&F#$5:E1`_%%A6U'87&>M,'S$=("UY?5#H-` +MDSF$9&JCXMS3:0\(CO@4P*S"@=H99I"WFTK#"F!V+5[BSRWC`^PJU'C(X3KV +MW*Y2CZ'%!'19S;MQ0*@CRQ/X>3V'&R([_9#30_OD?JGJ@IT60GUFW.S>&9== +M0CW!EK6,.)$C(VDMAHG2Y2C+N7:"F4MQC01]V[7T!Y]I2I/L%BUJNL2'$@8? +MC*_CW!C`3?>FV%.$%2?.]??:S#8]4<[W'L>-]K0'+WT+4VQQ\>J2:W('D)+C +M0*YQ!C+_L,B6G9B/6I#R)1%+9W@!4H=*/A\TBI:H;&4VU*FFW#,&.HRD[`_< +M";5M3O)NH+5$9LH5QS_[2=/--/YN(`0&B*FQCSO/M=_2][!F'=MP\#66S;S5 +M:C"F_3C4_&RO)O_[]-,**W`'1U6.*Z4L3W$]S,Y='8ML^M68-->,?UU,WWC^E-U:FA;DH.6D&BBD`/75R_$I![I\E3V`*6 +M.XY*)U%+0`CZ%U&N;#_G[[:*5GC+PJ(1XCP!");;(BDY?KWOM3#X#_[O*[)? +M6B28K1LL2(Z&829$.9@DA.%0C>X#\=PCD/]-@FM-3CJV5I@2WW*]W"73-V"V +M/8[^LUCL6'4GETGO-DKJZ)ZK\3,(^.Q>JP6H^"<5]A].8-C9C9A-3^9-3UMB +MH&GAU3[!FED&XS2*QI8H(*A35N9%JL7:4LJG4Y"_#+>4<9T'Z,?*Y]I/[B.E +M/^7Q=F,UYY+(O/_]T7BQ5-\+J4)IM09(@$]=^S>8BH&JXA2?CJ(@3@]@TVI@ +MMP#04=<@U]HY@5Z80/H6]`/-B;GC(-=-.;1G7<(6%I*PL<^A7X7O;* +MU(W(*]?%HHC'=2I=/KHS_/SI+[./(+D\"WB]Z3H`TH>A[L,"BHI`OI&T!8A\ +M]U(Q.'8X^D>A#N9\.U";`5'IIM#EF,Y#T=*EM_9 +M*@GB4MR[0Q,V +MO@<]U?+ST?B5",2+\.I@Y3@\/'1<7]:>`M!EA/+/]XI7]B,"L +M%6=9.E!1"9EH5SR0Y4W=PD++16A`_S]A)YMK[#W6*@F0C7*;`:JY +MC@3:MQY?@9T0_=!\8V/L3:RK#8S(`3;MQ$%?^;W=;'"G=EU+7$T-K"SOC[XE +M-B,N\[/NG`E=*JR2O`R."??:ZNKV]:X\Z8RQ0:?HB6/.E[:57T_B6()O>KE7 +MWM0FJ3>XAA#DJI/^@\^87-X"05E37T')P'2S(7S\]7\SC?@YZJ<'/8D(WQ3M +MTJ@E&`GZDR$PU.)-3YE-767IZCYFU3W3,%I?B7-NEY88V]LL/8>8@7 +MSQO9(LU^IBM`N];E![5Q::3CE4/-"%3E*<5XFJ"T=;B?IC"A;<$^/@?E@=C[ +MS,34#A^I'H+9PIGX9^3"V3-E*MO"'Q:*#=G]%GGF::-HL*>7BA7\<[,Y2/1* +M6HY@U*@HW8:\.A9,1I&RC(^_UQ?C=/D/1)1X-N

    4RLF/)3X; +MX;#19,8N+0JO>&D)NNH^YTO\7;ZY"U000--NGS7.!Z\LS9F*V(XXN[#'2[FQ">\E/R`[(YCB+`HIU<_]. +MV^[K\0"R2J`HG-K2Y(Q8-:GQO$LM+!5%F0BRON!6*PLIN*T+Z]*.M0$6@9.5!RRU +M`PXE>H6T79*3IOJ<>J0Z;%#C.!`@N89!_\TR9;GRRWFB%@G_U">E=B,**:?, +M`L312SCT*INEJ(50U??R?,URMBWR:MV_8@CR``G)_[$`]T:@&LWL*+%JSWR0 +M1M0D^=SGUI=.1B>;P^UAK!*IM,+)Y03)DF48'3391P;HT@0MF4!3EZ]L]+%+ +ME8V)5X(,KH#"H42^`%Q!Z=1;H@[Q":Q80^3VX%D.I6:$;L<*K%7FL)JG+N,I +MJ_H#R09M0>V__L>PR^=D6Y_^T-ZUPDY_?64A:4B7ZSIL\!E0F_4>82>U9_,S +MO_K]0LKZ)P3Z2OHEP!L,\QN>%TRFWJ^1^=0WGE*_0IV=.$B0>]H^ZALYU81> +M:5W!IDRM9VW<3:X`VW1;PDPXLZN_-':4(ZK:?4/98FE:CL$,-_^QRC,UA6UG +MY5RCA8\4;A,7;OZ#;;SSVF([GOG8Z$.H:(_A;>4'(2V]'V,BC_VK2P\+;7!C +MG>R!9(N0^)+B7MV!TR'8EOXT)5B4JO<;Z`?M%K9J(0;`OK)B$C/F-\&VRLEH +MQIG4]/6R<82A/+X53GK[>?S4S=6/5"Z=M>%25QT`QH:2. +MB-\'Q)``FRS&YSL][-T_7I^;+[L?9K?E.7J-T*S1>`V^!6"\8O)\Z%CCWDC$ +MLSC9K=ZP>$<;2S(GV\:/?BM>ZGP0B;S3%*WA!/S&CXUP2_F#$9?^8O'H-H)K +M)*#/D8]@JT-`3*,WRC]UQAI6A7`5\B/7@?RA:QD+XY'H8G>SG%:F,;28P?C) +MA4F?36(!_+H,)V):5Z:LJ^\#3^AFO]AXJR,?/=/N"&]I*H`/.^SW_J*=CCFQ +MH#7BFI5H1I#&I36:L/D%*J?]LAH9+MP4(&,O_/*.;Y'JB?]^V9Z6+SZ7`->'"K(V$R`\\E/BBUGT-/9C +MCJ(KEDH!5&QL2)(]E'2E"A-8E61#5%P02H\T-V)HB'>C-`L<#@NPSN!D!A:4 +MRNV72R+<<;&$1#FH%ISP$!EQ#_XK'!BB_A66AV_=%.( +M;6:2TRI&",40<&9%>H*P2*!C^6>C2D\HNSBC?8J>BX(E4[,'VP_S:"WSAQ$_ +MZY%+UWDCL43>B4%4=JN&SF\,7L@A2]IADAZY.0$L^=BA)@3Z.!LR34:?JU.H +MKNQ_.]Y$PX@PA>P"-KQ(1F8:"YZD0<`B;W5_=8/O^6N9< +MMVV,[]Z8"FR-,RZGL<#NK:]BZKHQJ,#KL5X_@`;_>PZ#`@C"W67%D7AAF8BK +ME$]-++QZ0ZH)+9]R_24VJ&+'!+`#4%$K$M9R&5FQE/MX/^BZR=\[C57GYL-F +M!K1%^MFCI#IARY=[S[0(YG#_-E3`2E:RG5$ACU$+XK:R<)'-0`Y^JQ8J0!O3 +M6M[@B5/$SG[B()8^4B)YZO9_V-T`"=ZFI4V<^(H(>I]I3$FJJ:^>_KY/^0,5 +MOZ+>7B'3"<'/'7WE"ZTMDD@"?11GJ:&TYH0>@Q8L4A/Y8[B_=%%51;!WS`D* +M[*4'>M6Z.FAJG#XJ2>?J51'Y-,>'(+0(UK3U>BW+,Q@J#D'U9W(Y'$'UL!H0#6LE2NI:@;ST]G\.FU/U#8:P2=:LM-H\O +MJNI?;&:.LE#3,I@OKOOO%TT$X4;C`"9*B`O5%.*9RVI/Z>0\F1"\TQGZOI?1 +MXL][&4*XW`.Q)432PTYV=R5D(C%I\.]9H2P^1\AC:CGF,`($*Q[0.[4][YT +M_36Z0HY39Y.+OSV.:FU)PO]T<7JTG%5\^^OEJ85QS6+>M,7?Z]`,F3TKP +M9")#EMQH8]!N^:M3RZ=3D9>?A_=F(WEP`)%\ZV`$6^PRPP*JPX#L2XA"3M1.)";+9.BK07D]XWQR(]EN5#$MI7AT +MFEO=>XK"45R_WY,:K7&O,+62`-?/2/S2ZB5>E];T-85Y1MZ0+$M>8LNC'&I5 +MLJ\6D13/H-5TGHI%4?O\\1ZD'6T&,(,@!W\?:;/;.<:L3RM.9)[W:T;KJ@-15M2:4CJ3VDQ2U@KM;;(?SB6/[?)!0 +M+FR'JFPH+T3-7LQ9SZ'$5BO.LX"(4RJXJ!]*U=)NW.'_'2#S50Y[/[<# +M!PY4]*GB!OGU\K8FJ6('J3O!`I9I'&HTY/5A=,C=-J-CL>R-EP*,"H?&R\#L +M*9N#\/("9_V7X"\:5"<"CC),VRLVL.W,=HO$\7#LG@PH^*(.OUG+RRJ/%.#M +MKG;;T]JTG3HD5+(9OR:V"4?E"(;O9UM@4$51Q3O\C@DO/!F.2%4X[+QKTAW! +M)X!"\?UB7%6^1+9<"L8)BE_NPZ:H9A:,>-`M3CH7%`U-C8;)[(T4OC-IT4-%BW^W;BV122I'0JZIB- +MG&"[)'+3%:WE=0Y=MG_!;-"!2"?2'N&B4,LW":;*<;S)A?0[7OX)=E6"C"U0 +M^*D&-4#48*E\_*;;?7]5"M)-Y_7!.G`WSN1($UPSS7L8A_9O4S&^$GN'!8%' +MD-49W="R?-1+QOU[<0!#Z"\3[&4H`:$Z@H)>J%V_?-LY!3; +MNCM1$+=#R9;B$-@%KJ755B3V3G3&?W5^'_!F$#8S+UY([6%]E[?;)2K\/FJ< +MM"^6L(O`*`^#J0^E0`0WW(A8Y9!+,30PW3*@ +M(A%8WB3N/__2D9T+HDJD>OCO'>1?OU\,$BD$USE_](^2ZX6>N=3Z\OKE-+BJ +M^M2-8*"(PAEU?$@D0YUZ0?'*;PS&:2$BK(QZX+V;U3*YR!X$PG^[$I:NP.[> +ML-G_`@ZV[_7-OCJ4K^H;6?7M(N"/X7V5=TI0WTO&VIE[?+@ION(JA@[]T2;Y +M,S@&ACP\:L18-YJR_4;M$[*^81);9-B4[\#?T/\6O^@BCA2730QMENI:N>19 +MTGU-^4M$,0GH8RLI9A*('JAY9B_7')5&LT#PJX7$=X.E.!1]-ZZ*78!`)H6 +M$3RF*"O*"-PU&7"FZ9GBOID0YL\F5OT=N!>S"<$T7F\Q$[Q/V56#0A+ +M;8M'GPS.E=FELMK55$,@C%KU+?1+*\+M2TF>H*S"0_Z'CF)HJXV-P\RV#N:D +MI+1`^M,?GMA($$,2]_R^"*CAN,6KDA"%U_-*\]%P;A2HLF^4(D^/5Q\G2Z>W +M#53MTZK%Y+FE2]=,&_'WE[ZYO,)/`4E!D:Z`=!=.F#_I9F7*=;1^=H$&6V*! +MB5^^97[ZX^.$5ZS=#4?<[4X%NO"UWE-OWX6J_H64D(X["\QAC.Z!T?I83]5] +M7:X^.FZ-E"S;<068+N\TH%Y0C!$UM\C^:_W<_#\OCUF';@)'$GGXCLNRWXQC +M68A5NE'>1&#[KK=&O,:.%@QNNL):NE/'?3@#O]VZ-0/.UNAHIRW%DIPMF0#2 +M4=JOOX1RCXX*>(?)XQV"XD^#X8`*`5)ICK$^SB1[,;2#*S72^D4T.%QT1*5M +M;^@N6I[PJ.U70?64?L+]$M`W]E^'MM;LA$)S(*LEB4D%'+X!N(;`]7T:;5T +M0,T+CWS7BFV3J3G" +M*!3`"?DH7MH,W1'X.SUK'3.QT?=#M@!*ICO'(Z"E#=3=&ZZL1L%("OXM;BU^ +MM3?(3,^EE>K!R-##AP>P5J1!U"OE[V-'*GYP%8E5C3Y_< +M]D3#X+E2FP.N)!P\MQU70DU81@6S/H\Z8PNA#\D/JYI19L^$6#M+JW[;^9SR +M;\W?PX_M04!D"5,W`?/!JY_$&N^$W1-5[?M)'^+;6^8O)/5G\:9Z+";@+RJA +MAD5+=&P7D[/;'J7:D`L#ATN(G+)%JC6QUEODG@M=H+#4P)=$['JJW8STU?H# +M4I%O2H^#5*XN:-1Q5-.=C#G-1/CMFBE']1-AV2_E +M_%C$(*1HKF.2?8\`72))F^<'IX@@PU3$0A0!\U=L@NQFNG&(I65U_^/+0!\) +MCI-A]E9(;[M"7.]YORK.GRMN]K5;1Y03GO\K@_[78-=VZ(26)N^/$ +MH86`.O%,X#CS/AD,KBFC[13\+V9O.PU%Z)@%&$!8!'M3':P-(VIU%R&-!@2# +MSL!4ND]O>9-FH6F8"9_R$H]&YG-E]'B5PP7`/9?5UTW[+K?[&&4H_"C_\SI+ +MM(?!F*X,"#++=!_J!:9W37DD7THQ1/U +M$J[EBW?;@US'I[;LZ_:+G]B+D?S9IH_J"QI)F1S;"99N0^;8$Q +MGQI[0\#BP"@:2'R-4;RHLEQ"OG[Z.NY3?G]/$'=]6MEUNL2!]%Q$,TD0*NZ)5VW+-E +M.N3[&]E0ZPPW36U=Y#[[U5VS;%-?\$].:U+*Z^(:>H!8*1F6\E*L4_9L`'TZ +M;QNVG/2Q&.)?Y_>JN=@/(D.P*-/5>4LA;=UBJF4`RH%C,;'9[""[+_,Z%!PG +M>D5GV0UX"&M&3X^L^8667T,M"PR\(72N"5:R/'.O1EW[7`48(K*5D&:932HX +MP2PGP3<""U4ACKYK76HFQ74 +M(<(#6G6AFC`LN%VD!;S968F?O+!FNCD5-9U!4T8O\@_*_6J:$O!7;"H$`$R8&YAOGFE(@+$G-GB=O.K6CY +M!D7K]B9)99OBA$G[S8T2M3,L0`(VNJ$I2&(KR;8=K'W(['XU1+T!CH2XTVW6BTP<.>#B+ +M1O`X:PS)&.T_YBMW4)TPI?$AP'Z^7Q7)Y89DE*!63LXK=HP[#=B!0KQAVU1L +MV`A>69X'@Z45;HU8G(K6,O4[SU\?+E(]*R:_D$8J9(]S(J&8R]1WO5S$/YH+ +M`,%W)#<-'^MF+/QH,,,L!V(S<=G(8^=^HZ^8+V4#>SI-`!*;(8I"XV^C/O)P3>)>_?ZD::5X^BRHV'ZQ;["+@@/GBE52 +M`3>,Z^J@WH..+_("H]QDAUB^;ONJYMY9Y&&I/)YR',VU8WD%T-/]`2Y1B +M'D7=E5&SW6DAK+W:H6D7.48VMO_WYHY)^_(#_8G!\`]'_H7%D1*LY!>`E<>7 +MWL8:(1;6QDLIG[RL\'V7_9%O?.&^?TE>7?>5E_"5H&YS +M3!L/W401S2ND]'QPE@^S.LL1?8291%?PW*FFZTT8LXQ?K)S$U+8<2@K1P<(5 +M/G6B#OHR2[AMGM_IBX$_8N6Y]_`N_``.;XKT_]QW&1['U12O"X,O!A&]O/F]4KQ="Q\T=.DN<>I`K.K_6S +M2>J?W:UV/$F7DKUE^(&/#I614N*,^DPD"7J^F4>T>%#VIBO[J!)N +MXXXZ^WJ`+^2O'^*;B,&+V='YD"G;\_8JGV!ND$42H^V[Q5[B2`:-QH'`/$Y) +MONLR'$]>Y:D/=>GL)Q#S>F>E>KT$C +M:,):Y?;@`IY0G7L`WB+W4F42,V+G3W\>W?Z42VI&NOO7UXG%- +M![#0[V']!A2>3IVS0FQA-8M0,)<'_Q0(5>H-0#*BHWS$^W*92XOZW@:Z,D+X +M8@%J\4:/G2@JE,L$.J$X'/V)=D5C05!FGI]8RI*2WL2K6,YVG5JU_=<:C@84 +M*SAM?.61LJ!-S^Z!%FEOY:%0"([;KSM\ZETNEU.P2#9EL:^@I+,=<#E@&,%1 +M+L4TS9]02F';Z]:MVH!'$Q#D'D+E>-\?6O<2]#2(*!ZW+,]2`R%[0L")5@GO +MERP:MPO.16S5]_5>_QFL0ODO1?*Y")_(<_095)LAJ[1'$G57U;R*=*TA*\>U +MERJ`W?P8AF)"&+PZ$FP8,IYS)-RIIVT0EQB-`H7SG/,=SM7CZJLU3Y%B@P)F +MPVMK;6PU5Q]S?;/GQ?]S1M>ESX#)Q/!Z"I +M-DE%7&4KE*X'G,]VN7V!12X:P@1[5[Z%X=+$KR=-1=*B(,193+6AC*KMCY2J +MXPZV9E+`DD77/F?)L/X-R4!5_L%-B9 +M%>R'0X#T&7%``R/`+. +M,8!91\^=J1QN/T7'38SPC[]QGA``I(&':ELV=EGN2W5U]^^S_T+X#^SE@4@C +MM6\M&V=8)VR%3E/O`?XI_A8Z;_R)B1D]=KB&>/SR-#K42:O8*XARB9W+6OJY +ME;@DUM18(+>EJW3QB(3F`62D&8(B2]QP_7FTF89$*XMY@!I7/_.Q:UX$-"@( +M$--@]E!L_3A?PY8$%%EV2E3FA87DH**.@9#0!&MB@>HZ2QT;Q*=.;)F-?#/[ +M0TO"[7)!$LK;<'Z8PH.1D")2Y46##IO+_RT,#;_ +MYYQIRT,B$3TC%V&@E!`GMAXAWD-.#;^I-`A6\[T$^C[!?QO8%IBHFV;JZ[2L +M&X#2W"R08H9)`_GPH>V(%8>75^R\VB&Y)RH5X;2T_^)Y%N9+)\M0.YAX&:66 +M'X5S-J*`!G_EUJC@H>&S6@PO^N*_XT,5L5F3Z3P)N'2VL&IS9)&N2?PK=R?W +MGR7GCZBOD:U>!,R65`J#)?Y*MHQ7:?]F5N$;&[RQDR8">:H0`9"_G1@O[%L;EVBT6B4_"^M+AL5G"O?(3;`!UT="4F4'U#LM +M8./>N8U(S)Y\Z7RBVM)4&,[C[[ +M,$CN_EV(KLMTX[,>-3:5)DWGRV)OKW0QPS':A;QNV8I)=A5_!?DQLQW_BHA# +M:K$UBB],J#$':<8NO*A0PHB5P%Q!.Z`VQ;ZHAZT/WDJB475F&BHO+^%J\S#[ +MJ$L,7@B"E<8AGGL-K'EG*"K%&R[?CEX$<.%HXV"CMOC]G;:A>D+7'J>UM'$^-YC/F0_ +M`EI&\X"!HQJW*1DA-(CDKF!D[(;C#Q=N\.VX?:T#<$9TA?:.J].P%1,OLVB# +MS^D,JU:+N>3+)[2VRSE_DVM\2(B.B"M[W=!-/G^D,^`8+&=DO`,(EM>S\0-I +M&D]*-BP3/UT9P7$?HDF]'HQ4P#_]&`[OU9>R$W$VXZ%ZSB03J>5EVT1V4\6_ +M)57K<"P'Y,&:]Q*U`YR+H`8O%=J6%\IF-_IZ%WB*M0."ID!YR`O2Z-F5+YJ8 +MH;FC9G&R?7SN^^$=!.Q+[RI+SOO501/G"@;[FN-;>H`UV+_,J/4CC%,;D6)R +M/&^DGTSZG":7E99@RWBF$!!S!1EJ=WZ89#?\Z>_4EHD3ET="L8!0F0X1,++1 +MU]\\/9\STB`SO31$3=K^4&P62^F%TKK.>(2C,-(CQL?47I.5 +MJA<3!1YEBC;P_,;N>1;>,UOC9_83?NNP"7^!4RI,SP:3JZIDXFWMUSG# +MYU4AVPNQWHK./2F=J7NX:]*VH;?K.OT_OR=M&+ZL?4&/L"C%[;']/R`P%G;-#Z]:>:)%\WV!,P^AM#F+2HERQ?]=3AF +M`V1NFP"KG>)!;3UB0*F[^(IJKWN8R2&IUT9W,Z$K^^LYUJ?E^Y/AE%#8QA(& +M';ZM1&QFA*;):F*7UA."#U7+`=8ROJHF^@2(LPT)$C>UMCW;<"">)._HG_$P +M6*-O-%PI-K*CSDBEP3';OW&Y-/GTW8;^`;5&3J=W_>ZB#7ZFA[X^9R0/=1J! +MR[2YN3WJG8ZVVQA_/[290UN;-N->]3*@4R7KT$]0S5`KPF)PO+;!/4RK,SCZ +M*[I(F*?93\/,>-?A;$.':5+;@+T/D5!Q`2"D2%SLQ$D4_M<6$\M+Q>>,;7:Z +MXA(38D!(K/,HET&[!JJ%V0,7J800@+!ESWCEI_#)Y.TD#N-A5S" +M39@H_"W'P?_?2%&FF%"1$LU1Y",!X)CYKIN$TO/KLE+'#'>_8;J.)@@@(WX0C2B1''MPQ3&!)<'A55_33+>H8F/$NSALP_ +MO85%J''"B3QZCFZ!:BN=O>-.]&'%*-YHJL)1YXO?C0H%#35X4"=7UI/B_?>$ +M6IDDDM?5K;E[/D6`\_/S9UTV09[O9X^AKFY/(.]W>$K/#FK4^4,M^I?)M67C[E)_MN"^F87-IW1[FFX4PDIT +M&2`-+_P@UD(V[G\6S5WUJ6_B^GPF7G#KO9&`WZ`NAR0L@0M@LK<#\^\EM\]A +M)E8BJIG6H*Y='T1\?(\&2#JE(SU%JM=KUZ;RJIEDU@D6N4D\KE= +M(IWDB.'Y'5!A"I!]HF3NK$`G3?CLWC+V-H:#KS%SE4EJ#DB3%70ML6=VE-WJT<&"5WGIJ@L-8"7PX,;O.D%"##"(C$:/E +M:/\`R4P4]DIGE"`G?1VDOV+K_K[9?83DX-IX11L2"V%#*H94B$M\!N,\;;J%^/43 +M9?1YNV]FY[2DY`I-O#Q.CM4%QT-<>(99]U3(SL1<,HK"W^W0(ESR>.]XO6_L +MW4GW^P,P:`/__0YDGI-N+B[IJ0RM@W.=`R/@=>\:&,9]1S&F#%/-!\93B\FK +M*\,.6OGZ&II\3^1S3RASR49TL#RM_ +M+H697S`O,7H.&A7$:G7V.%T3>::L45Y%5!4!F8+P6H9U^G)_:`,P`14LOC"0 +MNV/!HEH/]S5>7+BE(I6B<)_H06`#"FS!Y!2\ +M6LV\JP45Q<&/6%1D-H$J..4F(OH:D!]497HUIJTTJ?WDZ(WY4=*[=<=Q-:3 +M#$?9RU5LQ/4+@)P[NMM]<:B;0=LFM(76=L3ML;PXX8D"0^!#YU5@I6V,D'<5 +MU^8Z3K2`8R3)W@/(L")B4K38.K$%1^ +M_'\0CC``^\0/RX?3KV4(XQ0.=G8Q,NWDGWI;@W2;IS<(N_\R;MTIL%WU_]KU +MH+6M:EM_#T/>VH@EK?$7;V*`T$(B'L%=@,%=8$[OT''@RV1>4D:&E?5*%1)( +M+BXKTU)MMH;EM!6H>B`]V,JBA^PIU_D#AIO/Y'NWP9K?@77)!+=2!9EM]B4[ +MEX0P5I2(O'DUC1C(D=.I-N?FB9OURA3)&B#^U]@LN98@GQB)$8I;I-_T+OA[ +M9!F3KGC!:>?J-5`1GI(K' +M^2O#_O+KGKH[CJ@/<$M/-%W80P$RI4K7FJ-"7&=A_"4"+J#86E3H-_Z-PSKT +M%\D)P\"5'[.B(X<)K^ZQ6KV]=E1,Y+J\+IBW#CN1GX")65E[$<9Y+E!+Z3O*BVB2'[_ +MZNC9*ZG,]94RF.))!,5=I6APWOC8B]Y%O4^;BF28&06;J*?J(O3R\BU\(;K] +M!\\""(45)O4LFU1LE^%J`I(Z"0I[T_*L2*)O`PD?Z")?"UV +MUMQ90*#79E."[L*=BM=\3[$UPASE@7M3SN!*N@>.V.&"0.GSFMAF>?]8&^-6,5=4:9I0KR);L^SREKUHZVF&+W +M]6%`$4ON<=]Y_5$#?R8K?I,9HI\4R^N_0!N*("3_@**)=+(NY(T=D6RR[BOR +MHLJY^Z%%;JZ+WNU_F_\I,_F8'@6Y_L.JE"0*[`,IAG@^DX7S#C-'IJT.*)-T +M6_$%P]=M:)LLS^"+>"%O?ZQ-T6_Y(>. +MC?VN@HJ.G!$)9C4.L8[H+KAH/^2]@&F-$I5'R?9?6P<2"G-IRYIC;&6?OV459-ARM#\G34],&8N;=QCQFF&F +MA$?2U:B0K^N:'G02!5EX]?@'+*'H@CAW_`%>XG^$>=*88`$`#<;8TK!SC#=N$O +M,\RNAP3.W@IFIEV3::LW;6'V=\$^GCF-'O?%4B5RXU)&QBB/TBG&81G.G'*G8+\JTC#]+7H/ +M=N?DE+CD![)>B9\DF+QF@1Z1!:$-5OZ#R@G[T12Z?Q&M/L/\]M&AK@V.36$, +M%OR8*Y/!I4UC?=NE@_Q9](O:47VK=0V(,.1*D'<#PG]DKW"V4$D"TE<=+*4I +ME-9F9H!!$2`8TAH7AH\$3"%1^_Y2TF(509F60(EXMNN654#S^>42% +M+UP'BG2K'MA?*%7BM'H:W@X(9O9GH"%^?_HL[E)R#6(]KDKQ#H4&:T89^$=ZYCNH;QYDS2S>+>^\CBHA._Q92&UASF +M%.]9.D/G\I2RY(,31K>^PB@S"P)C42)R3-$;:,8Q32#3L6; +MOR_5Z"-0]X2/(>K,::;UC_?DP/%U95J?21<];\*E1\R220UMZ@[K+`4E3T%9./3^J(Q'F7= +M'QU&\Z-U5H$'=%%AN8\M1%WU/"L;Q1*NK=/XOS2NFGKHD!OP?@\:BZ9$0`!# +M$E=C-!:3%FAAS^-;<#[T>06QKRKDE:N##<4(;V0L&H98O/!Q(?C8")PS@N>H +M(&K&"6`=;$1#W"+Z2*#$]'3+5I5TO?#)S'4VWI++_-\$*:-Q%N/TD8SLKJ$0 +M11OE<(0+D(+J(-O+)^SH03N>P$U$R3T1_0+__(.QO^?%NF3Q96`F'X?1P!O\NSI5'-_=I(.!]"ONKV(9%M'N=FK\E1L9=2$M[K:O$0Z-5;5>(.> +M-^)+@SST'OGA;U[ZH?1Q.DV^B&9-`;;A3ZP)_V1R<&""U,U1Y)6]EE.QK*U3 +M:BC!MI!AJK&)Q5^?C=!=##'1-4]$PU%8@H55#C-:5-2:,MVUAJ4(04JR\5D3HY(E_ +M97X/^F>:$.)-5^&_\/OV(NHDS0,XPZ&'*U[^(@L">F7RRN86=GC,M4SSU/+% +M7UL6@+;`L'N*SH,S_,43;:"=ZS+%X1)AL)BUVYREP?2%H`9H)@$&,3QT'"#L +M/E90M,R6K6HRQE'YX5]C=/L((T/N/>X%0Y3=[S%>ERD8V5@=G#[O6V[WYP5.H^XU3Y$=.I?]\].Z"F6,J*-4P3J^A$SF>- +M;E.5`OQZ'T&)X8[+6?.VBU=-LQ%&":5J#IY[`B2KVH%FOMS[0\B%!;]MD!`F +M.S3]YG>0P0L^Q0&T*9/&<^F"*S$<#SAS4@RN^!KDEUSF,^+*ZL':@(B+)"Q" +MTQ/SQ10,<9U8)4%.<&`MEAG$['I`=(*)7^OP-:0MW9JBH24AO0FC[)Q!D9;? +M!J_B.;28@0Y0IA$C-3)W4W_K8C:K=1M)+[TQ=@:*)F4Y%@1EY$LL2^K4KK:F +M6>*"@)ER"WKAP\25[2GM?S^_O3;Y;\)=\$ORUYG_D`%!QM\KVZ1+X`T8YLA. +MNJDQ*-5FL4O-ZKSGJ+1NJHN/"MJ'*%SPA(7G;00Z[-OQ_U[TX2`H>0/CJ%87 +M;M@P8WRGGOVSX_MY;]UZ#?E>L1&A@D"/=MNS$'"M +MJ3:DVW#/D-)(4BD>*CN\QD-O"LV@^2R+P[3)%M@%D]ACD$M/5Q">JH5"#;K, +MN5HAC!OP816N.%0U'K9X#7/+]28QZ&>QDJ\(`&?JBXK79,5-49_=( +M[CY":LXXASN`70P/"RB[_2-$;9H->!';M*!1%!6)Y\5F=A]T<$']!$"2!6EV +MR,+VL8"/-[@XP)F?IZ5V7HZ7%\!,$HR6/OU +MC4J$]_)<_>S?O^[X*4O$PB6"\9XC#74.U^?@<&O\7/;=*R-P@#]P%&@D0S`#2(AA89;MC=I,(22&:P%-Q55* +MI76C9^SOUR*WL;!>.=;6UH8C1`\*_'X.]R)77S#)I_CK6I&0*Z%@Y%O'O([, +M=%OZ/3B1N3L'5JTAO7FN2-B4^742B=R +ML.-X0^EC6"7<[*$J=):;46>=HE]?\4\0P2C<59,F:EH0H#KQ#[_B-T2SVU`' +M."P/+9[:+X__:^C#Z,:FW=Y?I4Q2FY7."TQ>"./4[A)";^?K:*(-,L&-CJXEIYP(1YU5P99R +M"25#6D#.T%@Y8L'K>BY;I"1I@$0\(_ZBJM*BF$9)Z+`@=,^CA:-<(2UYO].^ +MHH=[Z:['[+B5GRE"`-409T3L&Q/0`T-3J1<8RJW^$&-#=F,FS]H0N!7GJ9'E +MBY/X*8'W/=1A.DV]<5H[S9@%9,G'?RW76#AKD,@A_:'4V#?->8.EA&.A;&58 +M`8='AG4QP9PM86Q`&V&/&`;#@#WO>WN8#[*H+,BX2C:WIEK2P\<>I +MC50=A)HJ75K[C?^V_/YF"#:-BE[O7_%NG3)=`YEU/2^EB\36TCEJ\@ZP5**; +M&5.CL1$@-:9K[T)9908=SNOM#_N]'TTNE<\WM<'XB/[06P`Z2&OHCN)0;OM8 +M\(VB-?KIC5*]E'A*NOE@18VF/74;NA'0&EI+$%';GT@90/?$/!7EN[:<:ATB +M4%6@%:$.\C2+03BR&TG@KM2G,40_-F]FRQW<;#;WQPE9L_[RKT\\ODJG;XJV +M1BHG/[)#>FR8N\CU]ON3W3)G@Z5%D?19OS;=GVD.,DS'>WY<':KD1$7O0'%U +M#"OC#:PI?O(B=U'K2W<`/;+I4,+!<4%/Q+ +MCX,=C?N_^N6L[[="&.M7[%-O?+J[S?1))+348FB7J2U6AE*_;#-M; +MARJS[Y:^->EE`W=@]46!MZ')D@X*,+>@U\>(K.L"3@T;?T0`AW.;_*'UG+V< +MKF)8/#:KCBJY<`,^FU[W1K0V*R'XD%)*LYS0?:@OWP4LS +M/O1UN%52Q`&%='O(=!;-O>@-^,!@&@WW4E"K?LE3R,IMM32U_Y2HD$;^!+2W +MUKP:B=%143DU/4#9.%9Q:WR\RO@4#]U%L`Z#V=C^ZD;_3>DPXZ*_7+QD"ZR\ +MU^`5D;H*Y0J>:GSK8X>_RS9QM*1P70FC,RBJ&C3`T5+2T.+Y:D=8O@HZI-4` +M$'7*Z;FV5_FMMGN\]+1+B/P+8]O/"UU)K:Q:SDIOU)AE`S3+7XOGZZ@J0"ZQ +M#%!1_[ON5:(B199A;@+AU874BM<#L3N0I/)#\X:0VR##,*B7BFZR)V>A4T6U +M-4\4`P*5#)=*NU%Z3,D:N:MKYT,V(/4'5P#*]5CH0'ED3DL,$!L>8X"!FQ"R +M#?T@8O+'Q9,K<(^]7$0^"B6S%J6DW.P]#M\`G=VIG8)F34'*9!09I:4?\>'!(]Q/U$PV-4.T8HNK:9@+UHL2_0R,@DU^I`TT0H^FL%I_%63=(F?OSX(`C^LAT_I_Y*+]Z+7Y%5-^18U!M> +M9GS06&G/L"&(\;7!FLIGBYL6_^V$*;^3+GO +M#'7<6)I;$]$5KLA&]JOJ1>K[!0RO?VN)5`CE*C65K(_OEU-"A'36NG?F4XL8 +M5`8;_B";E<-:FO*HCZ!SYJB9N]%AF-$TK+>:Q=I0I_\D$PC.X$53`DZR0.@B +M/THPQ=PHD01^?@3`+=U5[<$TRFIH8+I+%X>;8Z,_;S,FY'IT@1??PS"H#$P1 +M1[ICU_/=+P5C[L=1Z!AYB?,N`@],-2JKPF85&ZG-U"3]M- +M*,LW#A/:E+!G?D"],YP06D3D:H!;#VO4MUMI1YU^E][Z"U\+A(A3DU>L,TE. +M8***(V)6?,H8RAA/1MR +M\<@7GIBIH'K$?A>\*'^?MZ"Z\:U_IJVKDV:DL.AW,-?Q`4Y6PYOJ+@ZWD[1^ +M3^*\JD,%Z>9Y1"KZU,N$*(QV4;,[JL[8Q090F.9Z\-<$W(F=_)4Z@EJC:#:[.[&7,-SI)LZ/K2] +MQ,LFI),`,.-L[YLS0OQN35R&^):CI8E5B^2<.)LA+_E/@;-#[P>[:=Y%"26] +M,!?Y0AUF`YI,NX4^-/K:B&,RZ7'VDLF./(MD +M2+"D//:]^97SZ$Q_Y#(^KL"^H?)#3@-BID!`*>,'!><7-D!R]E;EZ[IOX +MC@7.0<`AQB^='9V_?2,9G@79$]%7/Y@H4(*UVNA1BH4(IG6:T.LR(C![OO$K +MH'!=!CJB%8Q$''$`F&R0O?^Y[@-R=%F?KE5(EJ?=/I$F(LN%)![ +MA%6Z6V_)44K6!;1Z]*[E5&Z8"*FB+^.B4].'01#C`] +MUT24?MZ5Y4(OAG*/*?^,P"C!/IJJZV/Y>=0#)C`GE21]W?9.](O3;R]Y[4RG +MZ\N16MM?"M#-YX*<\0.018AL9S_1C!//+=J\.;S9T6"S\^>"+2-QBP;_?HLG +MST_XGU-^6I$0+;FO-'B4O_0L5^@*8OQ`2Y@_?=C7VIB%OZ!J5H$@9\GC?^MDVL168=I,7*7DQ^%;"5TT)=N6V9 +MJ*#UA/]GZIELMEXT;EMZ;*?X)%[QJ?1_OKGYDD+P=T64XMRB?'H1TWM%HWV$D:]GA5.5:PT=-)DP@N>==8C^LQ/.KLBR=R?="]?B@!@1Q +M/PG<-E$AU_GW$]6-]-4KI4_4;=L6]Q4FA*ZNAO^_-4WA\8@`9>W*M`T./.5D +MP@L^2.,,'*\SH?^"*:_*E=[SROF(!8)-N';UER=1-VQ-"#FVA#5P1F`G%/I#W=MJ8 +M)Y>1CPW3&+Q\H8$%$%T/TAUA)M]C:-T7DYN2TT*RTCA1V94QX(TL+M?B,F2F +MC0"_M9,U7P3<[DD@H%3MA):2Q/2X=+NA(G%@#4F;;$R3VIAH;'NQD,_$1"`, +M%B1+Q:5,\YAI:UHK=1R%M3^4:SYP<5Q,^[68-<=S<4V'&!`5\GW3JSBG^4BF +MA0&-(:TD$C;,_@A"#0:VY3&"T3U>(EY<67"^3%4Q+<BM)0J*2YRT%6=]C4]0R\]0 +MIB3SLHAX:RT66NYI[[^P[\&Z)BAGIX?=,[H386!V3JI/#FS_R.1V%\8P[,=V +MR;HW\<:#P;)-K+O.VO?L[*J7,V63LJ$')/RBGF$)SK")GR_GF8QA+-;O9":6 +M1*7^%YO:AN3TG%[DUWMA=_H%Y/^`3?-UVEE<,QK_)^-Q[`_6?4Z`:U?`.7'5?#]*D0_]5FKDCQ@)!\2<$V1X%TP$+-^ +M?HT++M$7&"'1/'VX6E83"E4V%?,Z6]9>S$JG*I;G^(&"[,Y-N/,YP)B";CVA +M`^Y9CR&*$C#JE5V^:.0V*@C?/`C.T./]@(*^^=$32!,$H#"CI+,=68MI3D$= +M+&0N@:5&XVY*P0Q'BTU$Q9.Q/6JE)E"D51,T'`4H=$EQ544X6:H\][FX*7.N +M#_2)K%;N:#'=3T8B*W/J)LCJ^YPT_^'Q8F>)9OP!HNS_Q=\9CE&3VB.LN +MEU:N3JP)@+:!I8#Y=Q?ENV73#&7!RMF=O(9JE'ZGL_\+#@/*N+L1SMS5J#+Z]\7 +MT6`-L:%$>U#<4U*YI_B2N=Q5P.5?`F:'`L(M2V&"V;(@2JOZU781*_`8<4@2 +M`5`6,[Y2S1U:Y2'#!]!%U)B;Z%7;3UJ5==>1AM/BY21CJ%CDYJ61PO%//`D* +M])VE60 +M\,*6CK9D@S_(P2MQ>.Q"8792;;7%ST +M*&YWTC`I($$*"1&*N-_C@QY+A@VK +M/'=K!^VN6KD'1ZW.(J8OF8BD-JQ=G97\^K^80M?K!97-.L&1UU<=)?'"B4>! +M`*Q:%%?X%#^@`I%QE8?6JPH3U]`?4HE"W^'.(PT+[#5A-R_0,F144R/&*&&L +M92D/XI@1:&OH@S@O(^\.YLPL"BM[<)H$'T=+VLM1(4^661I<7+S5N5(O'%4S +M-12P<7SY3>M,M+,S/4GA5@P+K`OPP)6CL7M@..2`0D_AKLE`JFI;1A/\/B3- +M;6Q`72WP6E*0P>]KKR/,@P_,)\?&::6Y7_T6E'LP2"C7`IR6"18%(W^4T(438KB&[Z%JZ?14FWJP4KK`2CRPQ7AN1 +M8@4K[\%O;@'J;=GC6FOAH'+?86'(PM?M^L(8F[Z&O$M'G0>JLN#(NFW3$>.] +MP$9UVH$""VK""S6?!;=TZ'UNZ1U\*;-7;U0R+9*<3+A?<'M%N@FU\=VAFISJ +M%"DC;^UG-,Z0@<`R-8;L([EDTF3_3N;2\WRVO^5/U(F4"H_-XKU(RV@QK5AF +MZ"*LORRE3..4!I*&PBO%S;!5B$4,FK>G7%9^Z;'C:H$\!(G<1!"RZ_@A+2'Q +M(76B1M`OUE.D*;,C6?`4TR_8`*=@)]7$X4GDJXLR^N(-$PW(34^YH(O&UG_] +M$FJ$VAS53W:`=*=AX-@NXM98X)N$(,(.*0;AQ3XN<^"8[KM;?,-(CRS767;. +MG,`E8[L];B_//:4PY5,MX1OI2N>].>_14'_>=95J=^P2V!S>T@?`=RF +MC-I760T8A20`W+6RGELC=B5BG$D"P,@)<6EOXIKDBU$46N6>TQ*R$+*55V/) +MG)0YD'\GQ7:.UHJJ8`]SKKC#S>>`N;%]QP:TOSV)7K.XEFB/3%4,(V$+S\.2RQZR +M9<;UDK;\T=_W)*.Y;6&)DV?52+BH\4YFXM1?4LT#U?(A]9+3>._0`G6#Q%?0 +MT@<(H-E"A[(N9D;R[FEH\W;UV%*5C9)D3#%XAZ8;X(C$@,G34788(U>U'(9U +MJCW^94W+=Z@^J?3;F_6R'O?SQ![RT)#CUFAL^[`?VUX_@YB'Y#+>-6J.X\Z--SP+(2LBG%E +M9J:A-']])5MS::)^P#"?\6N!FHF1K_.J8'F^[Q\,*9+G?"8AB4+*/_/:'(K2 +M=LLYG?`R!*=PX=VF62P2G$`)/Y,M;>'!ZG)X%UC6Y6@O,X*W!(&10E%X5D7XR'GV!N' +M=77/ZKA,*?H)7'KT'4X7"=0JX]#;+!:RFK*!32SRJP?DZ4@4W#.Z%^4'*2V; +M6V1K0%^LA\7QE3^J5(L)+ED)2:F\"4E8^'0NN(Y$41A)14<-YAW/_N*?`;GK +MP$Y7KE3K0AF8XE",+^''E>+=E;H,DBO[+;=09:\'6%V$*W.8F?JL,RB7WBZA +MZ37JD^V+JQBA!WOF`F%FVQ@[W',OQB=R)M@9F8&H`OF48X`;W;Z%FWIR>*W5 +M=&1S;$G,:V%@&[R9E_CRCSCB`S.@IG,\@27+J\\&QZ&^F6\6(9+<79 +M8&KU_G.O]7V$#1&9YBL4,P^-]((%9'IRP$SP:]496@]/+:R3OV>\I4`FBNL( +M#RO"38CIK$KE6"52.Y94=INZ#J"QV3JY+]2B`5[H/.-I1\R@Z'8,0]/,XPM<>\PHP:9M@$-;MZ>L-D5=JU']J:6J*M#!7Y6:%1<& +M`X-`<)X%R`X7!=$F*P>`GFP87R-I9-H:7^[X,P/-R;935$^I'^7B*K`0/\E! +M%HZC"V6=PE*F`?)RJ_V!_Y"90TW($'HV3FL"08:JN(4B)("DZJ7*/PL)E<8'LL'Q77C/K+"< +MHG4UEXO%&3?WU;`@L,B0Q>*?!R4YVZYM5H@A@#,%F]"49OZ&?@#]O(TL'N +MDK3O@!9(:Z+3S95.TV#@`SGD=E))3+XP>W' +MQR-L&DQ;89=(&VZ:)D@Y:$J=#GL;3&A!>W%*RO(G''+#Q"INEN4=3#Y@B'./ +MI3(YQNUZS69/$8``&'MA;DT=D&X>_J7-LT,B)-']/R-XC<7U6RVO8XGZSK9++8%;I;#(P0PZK$ +MSY!3.`QK!)\H7_?:2X)7#_TR3G< +M*4;^768#`3]VWRSA.L'[$=>ZTT[3V;F9?U+7_7\Q)2Q$0D_G)-OR.!AP-P/Z +M,WF_IG88R+3-MCI[E73=9#Q%_;V-/FL8P8GGE^$#YX$[8M[4V_NQ3SQO*`?` +M_R1X\?I7TK^0N$L>/&$S`\&=-0,# +M=%2(B/_OZTO-O]*Y>BN_^UO]F'$4?^M%@JT$4^[&(^L_93LM-C-1@(*2=;;P +MP'/,L\LJOB^)2PWV(Z&Y;!:E$H861$I9G:Z!A#<#%0(EH*^Y-'%B^D@?\R+5 +MODR31,LM+)]7^12##(!OPV:T!CMRUKPB^^N$$=&_\?[">=_M5UV'YVR? +MPS8X2U^';F_OVMO'D1];`EDQT2208=6P7[+`2'43@W`#3! +M'IG#E9VJ$A57TC#HG(HE#GB``M<;A/$F]9)\BHR!C"WU]Q$D*=$^GYC&_!@X +M`K8CLD.(ID_8,=H/8C0EHA)8_PGAY*NU443VTD#+OP0;W`\0 +M"A&?.2/ZV5JMB87CBK +MFM.=&S%]MH\ZJ3M6&*SZW@NF#@5_+_QJ5>`@1YT;V`TD;`>%=*+K`]?_:F\) +M]+XQ^&6"UE`\\4(\QGT?FIE!O)!6UI@ZQE/I`9,\GA+!U8;C/!%5-IBJ'F%H +MY'A*SC=94U`OE.1 +MI>XY-7L]?//*M4[5&P;O.,Q:-PG%$;GDPBV'TW)CQWJ"D'H*]FLP;T=+1PJT +M@S=6(\@%V"3_TTGJKU-O"_)\7)1;_'8T:T"6NHAUFE:_IHR+'/-O +MJ.^5Y1I$1/^N_^PZ10/QAL!X8OP>-3`8?>9X@,.XB#RT&"TP4(UF&;H'M;VN +MX00";FCD$T,#AO1_HLQ96(#VX$2$-6-!#0R%+%[/@05Y0:SBR7=T.UJN];+8 +MHTZ/OF=W*;EU.?OC&,#H&R8G]3V[6@"X35C\SQ42J(,W^%B#H`WNO9P\ +M0LA@PGO\EQFD:5/NKLVU@F63'[99C2JY?*,O.O[8`;#$HBA);08_ +MT$=TX%]PM]N.X@"_^R:N[FK"8)P[+]]XOZ_/(_"UU`7,0D*-N","]&=PBK/I.3I4=&*"\J\Q_9 +M:T9)U02][LR2^![=:]\T$/PU85J\RJUM*,]U=L"-]"")-_"H=%$D0209.HG% +M$C^J.7[K_.WC-US.P6%;6G41H7`!V+J,8'@8M(JC8;\T\(%[_Z'FB&Z3Y1NR +ME+WQ+Z(?US8G'-@6=-]AS9Z-[X>P?DK"'2%U]V?'>:1<)S4.[(RRXQ=R1A1( +M$"?H(+-B&(14!_4!#YPE3T]57E*M!\.2?,=S6<1C'K[H$/;'[P][ +M<@1H!H8I0J`F8'>@#Y?<3(%C29`5VCDT"K)4R:`R-7K:PFV\BS.\,H@*/A66 +M^$2KQ*T>DW]M$5ZE0]X5-HY34^[.@ZX6-M_^%1F> +M<8K=023M%N$NQ>>OUDG-UFMH1^!UT?&ZN2:1,T273Q]T/++)&F@(1Y5BJ\9/ +M3T%K:GFD_'<5=2P<96=6ZU8,Z3F`$Z>"Y\9082Y=3H='.TTV+=29*NS6^M?# +M'$:7TPZDFE#].YU7-/OZ-JQ(_P2>:S9"([8+4?$_F?5`-8 +M"5K?-),#S3%*2<$7ZB+6)R;>^\9]V7K#6]^=TFJ-.[=#%J:3"S67[":PMC0) +M&;J\25'C:P^H:PF)TP.TT/UZ6"M1>OCG+<19_61K+LAEP*FUJ#@UJ\<2BR%% +MN'#HJTY2/,S))H`[5&!-3HT<]OL(.?$2F'O#LXRAEB,4W#]9'J"`SB#!J +M(C`/'G:%)+Q@AL7F+&.F1,C(0A#E!"X9&V1+LK!O`>&S&_&WW;RZ#E%XI'`G +MC6DF"SQ/43,W@H?7Q^-GKE0G,H-;#C.-%C//MX2,R5PE4\%;S[E/`$E[C-5$ +MF%Q[!(1ZO8+-=0NH*-T++'/L\$7\5:`EO),6MK4\@\1M&I\T;]&PTF1$U7R? +M7>XO9"!+=@%T]LN)R<<&:R6XZLPIHRINK-E<7>2KG`%O"_PLXJ/CANH/*\93 +ML;R[O/!UWAHK>INY'LDJ$D=_EQ!E%6TT2H'`CUCUCP>Q8Q4>"`@(>2/_GBG` +MLW5(\LK5I+JHQ,0.2H;G%B+?O;(RW"YE`,&65T36(K[9F3HX1'Z-=&!%&=+, +MFH'GUI'\D$'R7X![LTW'\%?(#4_!C)UX%`5FIP:W0?>]*-.>WM:84[P\[F&R +M(KERS<2.QH$TO<6]]'_SP^FHVW%[9LR;_32I6"BGF,82DH2\(N*)21HR1>UE +MERGB_-:62G:MKP(MO,AC93(D:NS'J+T"H&J*@A +M5>$?.>>:%,)`:[LK?M;71!O;47AZEQ[\/:_U8+;LKGDCP!@@*5E[VV +MCHM+?#,G&=4-*W:XGT&R$[CNS6\%#S27."J9PV'N#G7,,>JB +MC6$D:9AIJ_%$=.P0F=#,";F@GJ_'_AG +MT>8$96=9^YZD.YS.-V60OQ`E!QR.HC`CYRX7WX=[A&R9I^?X",Q5G*&8Y']% +M*+H;$(35&?JPB/8>PLG:B2_FZA'/Z_LI/1.R$85F$M>W][QQQ.2CFEJ8[NC. +M)'9SUF%UJ@I39OM:5I5"S?+L4!;^(<"[9Q":W]U;1%^U^1P++,EOKG^`\.G= +MAENH9?)WT/%4N!WW(I)\N*D+?0N,;,MFLZYAME\[&X,&D\MO8/=BHQ>VA0A[ +M7-%&G:.+6U^=Z(O`*Z-9C%A]&23E)IJQ+]+8X?[='&TT@'3;UO`A;1`BJ>VWW]%P0'`BM:U=E]CE+3#FE0Y:BFR=QC_05, +M!=GQKZWC/FG.R#W"`OC]W+@PMOV,LR+BHIHJA$0[D/$ +M()^PR5P!6`;YL#&#(*'?Y7'&^HE:8^*Y[+1>2J,1N)^W@2VJ::Y%+OZNXFD/ +MKTK$K;D-=#ORE8O+:Y;[_8HH0\>"/8QIP>\A'2?WIQB9HM1=! +M13U=@$/6!@9`F=01J['4.&GI3-.A=S30%DAF3MZL&CA=QAUB(.Z0R9J]P"^7 +MTE(R5&C"\5%_)0$Z3DK\&@1*-R1L%]V%I&>J@?*2_BOYI1'MBX*[Y'GC3H&) +MG)8,)]L;?;1BDN]5^.N%[G64P%I7?,(\.8LXH%<\9[]8'W>(;('GO*?(,MW9!H*"CB.5*0_Q/O +M\BBU5?W(QDG,NC#L0'O6/6B2WX@*T+N[HMR=0$I1,FG8V"W=AROX3565]F27 +M8@-UE=_MB1`"1A2>K^'8-J%.W]TX("4D1$DL>7WS'TQ1J>4$KVL2P3L&M;,4 +MO1KFME_):LH(0&-13QDAZX=1\,P.]:\HDU""Z%G!*7U+VPE'4]M[#$QB1>IJ +M?%$4"'2_G2>/./C4@S,A?CR)S_D!H70<50P7A!+3B_@J-U:!U.AE^W6+/Z]* +M3F>29OG=-57M!1>Z$G%;W=V6/GXK?=^#`(6'?.#U^":@`<7%I= +M?RQHXCN7&FM=\6C,O:D#ODGM3I17T*"CGS#7N;9/+$PKAS`CX_M#I4ZMOX'N +MLR"\T7V3"8L8!)^0\X>LELVR5>;5;N"7!WBW4V3)0AYLRN/Q:C?X#NTZ7BJ4 +M/TZV:M9S][5M8=@%^A/1OU/=##A)),+5.@SM&ZR.96XRK<>/8TM)9I\CINF?/W,R!-5'M@V.FO.828?I$?VL>,XI8C +MX)D;<"EJY/JG[()?H;9R^?@5"MW&RFWH?1.8V.;L78(V+7[E*)^C35-8W4!J +M"I2(2H84XU4!X3^Z)BH3Y_7ZVMO8N''>L8H869CTU[ZJ+KWKHG'E.M8=OB?O +M7)9[:=!\&HYLV9T"1N\6EU]$C4D#$@A-Z#@6C7"-(_)M'W"\MSG!C"D9BQ0U +M7%;_X-7ABY)O5-8R.#T;NY-:\';XZ6W1>>J9$D^=JD&YRT1@4TMOR"$6-^MR +MDCM4Q1V==D7LKQ:7)C_@,:7!JQB`K:#\9O1/KF5<2P$U[_A.)AQ:EMN.MG,8 +MG<:A+_-5Q)5N8N_0[_O=W'HP32;'I-Y7@]00N:T5W(AM],0@>WRW4E%F`%3A +M:D,)#J/JY4Y*2QRQ<'[%)KQ_5KG:@65>;+LN%@.R80AX8TE?@.B;Z8&P&FA" +M/EV\=A9PWKO6=(EVYCU!0'EIG_,L_[TU7*8Y-\BYAD1$GB@_X0QOV-4>VE42 +M/3E(FH$&SL'RCUK*I>\=9=40K(/CF6/NC"Q.FB"1PEP/E*+).:HJYZZ9(ZD"PDYS_LIGN6^"/!(&*XPTEY+19[U/^/OB@R9(7&7/1$[@`Y2YY'ROMJF +M)+]:`J'O=M2/?;;G0I;>5(:?`;:<,L4H:4!]Y]>PD(-_CQ%!:9(F35_%UC8N +MK,#P^^UI*C]@]^&@/BC3+`+B?RA,".)'P*(/U+4(M!F^89DK0<8":^QL<@\M +M(2TS5C4V=#CQ:W/%C@C\DR)WIT,%_Q^Z*XKWIL>>!4[58-*C70W:(%?NK:@= +MC/=]1(+\=)KC5[^Q<-K-$HBWKG4Z)K#(';T3&`16G-CQ9&T4IVVPW)?4@IL< +M(25*[JZ&O$,GPA5$J[ZF-KW?V$>#,UHXZ$]>PJJ>LP+7JK>3Z@<7],';THV- +M!!Y2E7-J[=)9I$*ZXCAY`@0UL4E;+&J[2M8$MM-VMY35PKDU'1A(/`T0ZIKV +MF5:SK#%)\L]\$`%9=7J?XL#-GN*%SN<__"0PX`_88&HXB,MWD#LDNL +M@?F=3XO<4-'%.V[1&!<%5L+]M>&M<57#J:9"0M836BXBOBO>B/$@YW^0L8'* +M7ALY"N4>1NW_X*Y0^0,#M4%>"ST@BA1O:@5:G;D+@FLCL9;GA*$ZF!CW'XWS"#D8)T")J#\NJ"Q!Q,0DE +M"J?%)866+E+_"?NV7Q^41YGTX;D(UHF16W!3%&YS6EW%P-5V3CF8CIQL[]ZU +M*B]L89,=-91*L:JX'GBX.DX@<0`1R8[4-=7FC,LP`Z(2E\(D826=/^M$[< +M_4@+1W4K,W;'%3!(SC;3#Y>%OE<-XS9#!Z>"!N*/)ZV&@ +MH4_GH=';P8'4]?M^"`S,E<(<6QSH<.)RH*JODW?N>&W?@Q<2^W3C8-*W!#Y0 +M27E>I`;5VJ8LP5`BNQ,:\]=<'#]'$P@38L@@(DQ]R#4Q8W&J;\Q._P=C/I+J +M8']\HB0V<]^Y!DN@_Z36(=,EIGB+[-9*J+O=?$E50WAN,X"!EE-E-M%/X%_$ +M,OVU"<0/:K6'EA>SE#=YO4&WI`N;P?CR4_H^175#G]?BVVS<@W#RL3(-[^=]P +MW,'TI%FY+)L5IFS;2QR%_J;*S#T`D/;W*B,GJ6AD*A="1-2S[K:7$$<-[Q=` +MI=7PN0A;]^93"W^7K<0S&F*J)T/4MY=?0Q4#;-!SYGT8)IM?C6[_?+^5B^MJ +ML6YOSYC-;M^@&V!^_82I53AA5A_P\CO!F3S2I=G5@JT]_^T`9&G=O[WM:+__ +M!O>VUO?7`-_3>#EA,@77 +M,&A$V-MK>""LPJM]OW;XU^9P%+NZ&QCPX0*!)H6)P1D\>Z-->B8ID*_++E]K +MD2UGU3UGPWU3F:/!VM$%OX"_(NT6"%NR_I`C`1>(@`[H+>T18C<,)VTU,?Y#/(H-XM8&7!+'_S[QYP>HNU!/BE>\PQS1$J\7+^/OA;D\U>X&N9!%"' +M'-D[?T,3A'7#9PAH2!S*3G%O??-6,]FO57AK6KC4/O_XZEMWD68@4U.NIA4E +M4C$!%_>:0Y-OACCQ"@A=O[C7_2B:1XMQ$[M/4'9&^3,LX07:9YO6/XYGTT\S +M;+H%_V&JV'JV26W(4PR?*#9/TY4BRFSR.KH@M1R@/AO,^'I[3<,X=O)-/&)] +M\I'./@53#<)/<]25"(G>R:%L/4^"O9=71VMF%AX?G:[U#Q!HUKSH^)H2'Q*< +MYX)_.&N_!IR?O3ZMG7W0SB7KM:Q-KUY8CI47)#H-+Q@_SK<8D973"W>V[#>: +MBB%A3V?C*4'";@EN!;`B&2"0&Q??+UZN +MK[P',FC9GM)$H:)&J@5DWW`B@1E\\;VLM$BKTMZ!/YA>38B7_H7I<@X@[7%(K#C;%U(>8LQ[^-D6?K)W<:[B +M:3`03-'!@XU(D'BT\OP@O*2C?$3,R3Q(15&4HVG6I5X53J+51*7A7#FD5AZN8H^#U8A +M;D>&(F9N)9SBXI1VY-_F@U@$)$``[0KGAJ.0Q6>P"&C(6Y(D:O&),,``'<1, +M:6)L;M(4[C_6SL/P%VL8,M-FJ4#ZX7T%`H8IVE5(""0VA8I%H6[NY"^+IC)6 +MS=J42X8<4/[^/$_7YW)8!H4RXF2>&.A5`B]O4#9$]W'!3X_J=HCZV&3!;X$E +M,C^CQBLU&MY;AZ9"*4+`_:XQ$B&=Z66NGM_)RWT'ON=+(H)#;V2FC()`E"(# +MGV%#PVC5L+_L0L,&-:X??B&5)^R;#1Q-P>H=*[QC%]ZSVDA:7$1SB%;N$8?Y +MMUZ/T/:XTN$V(*R]EX^@L<:P?`Q`D7ZH:@L>,)B5IDO35I^)-_4<_>0TAQ-4 +M2]B"M+5AW=Y4J9?WT['>@LC;J2T_=S9Y^<)#"9-OT*3!PQ?VW3_`)[-@MNKL +MTU]#/!2V-*&_7_^#GN16R_Q'[%G__I%2XZL1UL["[EZ-T6H,@9"4/P#C]7;- +M1#A7N,89[(Q*[J057#6+7WSC()"?<0,FP&\CPQ+\_1O7X\1?YWW +M'$([QO).02S'3;IWRBY1K-H[`_,JI +M,$FDP,IPN[@BN)_:,U6UJH"+JXV:#/=4@)%,YNW*]"F6T6EX;AGT"Y]8($'E +MQ8L76033C-(JS$$Z@]-@U5&ZFW7N3H%`QC$5(\R%)6BZE,??AK'(*]YOG%#Y +MM_Y\Q_L3VFPGU;OT\(BBN_2P1CC"5R`<\5+@@P(@P +MG>9GODVYI_D2BYQPW)H/^3YUYR[SNKC_-A\D#_4NQJF-)CW6"NP>G)SAQ%LB +MY2:$W=`S+\I!V([*F;9Z0*?D?WR`Y:E"/:,.%U_5V(H],$!HK03#;MP,C$^Q +M+FK7>LX4/"TFZA>P:USKC6!F4:ZG4V"`E^*J.$8 +M6C1TP#CN.-\6K4W=8R4T);BW.6>NC3G5NJ__XPX+K>T;9OMV&[,+=T;*^U", +M0HJ\=BD<30!Z&!YWT-L,8QSV+$FS_,$5V+@YDL8C,9![R%CV==5K>=0\BJ9EP25ZBALK`XXCUE0L+*!GCT06KH5"<:5HK? +M\#(W-DT$6V&--:0=C9@F@C*:$LTSXFWB79SG8\'<1#:-3#&E]>K5K.O0R6\< +M:M'T45M08&4YLX*U;P]A`%I2]2H`KKB'(10\9]GQ/%@+/"_0]&5G/N&/E^]( +M#8\%6[NC%BFKR>$;%/>L@S6#NL]=T:AP!FJ%#4JC_?#!7[C'YPIM$J-_.VSI +MD63Q%%+S>[=/E._7Y8^1P)U4S_"I&,;V$P;W'-@\J]S:+*P$M9^W`3\M1(V\ +M9Z`KO[3%LIRD'N94Z4EMH1EM;'+BHJT@\97NU9Q#JZ@FV&@-$!H__P"?G.-^ +M(015S>7@>R@O"L<->"-KNG!1(D'D#K>5)RA]`;?O;PRI:V?[13U!X;FTV"6" +M%Y=-%K<-0*^MXA.8YE!<>G8\K.-J;A2G89)K<.[K=3Y;_*];=-&]$FYYA(): +M+_P>D&JM#(JES(X2NP'R)M`=I2LGL[F\ECC +M!1.0<1JHMBG4#^T`\"O)SS[?-0K=I?F,[(H0Z7JR],+O'C<"UM0T24I$KCTK +M"8F##+1BC9=9>B73M+XN^6_/E*Y\7I0)#OYP:&@@=Q'*(>@P:.!%`(P;9(#4 +MQAF\W=!O8W@G^F2^)L'.(VK263SRY?HRSG0?32WP%_!A!TY=G5%^_-&3[T.[ +ML?`8`0*C"&@R)2&C$LX5$FF6\(2/HF?A+)ZT+'JJ0W7]2FF" +MFZ-\MJ4>UA'^SGY[G*Y_Q.K&PXL3KYK2LPC/D'4]6K22:I]'#O-;XJT".>0^D8^9RJZ# +M*Y*Z"=D6)O:,-,H&*$MN[:%U!AGE0VM4HOLJ84J]H>3\`G12C12LV0%A<`3W +MEE!GA7+>1Q6U$9L=$J36XASYL1[X]2M/E@^X\"4*!$TYG2F26.+ +M`X::&\L2%I;[:.T!*2SD94DKI"$WFMV +M83.R43/R^(LU%`\:?H!HC)B0Z9/TXCL"KAA^KIL]-=?Y?%)__(!(C7V544$1 +M"X26X2\!@H/RN@)J+@Q#34F.%'/"Z/.[LMW!SV>3$#(2,Q'\)[!(20`>.HKE +M8I^@X=G/M4'#E^%B<,.:*`T(B=7H!3)L-:8U($>ZL.UI+]`4&\Y'SE^Z"&(@ +M1BPH#"^3*^IF@ZO(-5[_\HB8?KKO/_+?,8B,I9SCP$-+VMK!SOHU +M6F`4!4XXD([Q>)<*_S[FK13%N +M+,3YT3"IC'24&U+(X"WLZLEFK6I%D>&(25B7,VF8'$;Y`J/;[>/+8P>BEB6P +MN/I('J,F%J`HU#AG?E\*!$4?G"M_10;1349@=SIUF9)G:C5=P2`#0# +M0G5PVD.VY2WB<]=?@N_'?$HD92_1^;M5]5.K]<^-%9!JIJNO\(!D*RH%CVX1 +M!&E/&6MU.`!ZX%IA!V=0^#Z/[2&U=-1;39_8O]F91-=0TDS?LN?*TCQ'3&B0 +MF0LGM'&IH5G^H$T^.C+_<41W!6V7*2MA`U8&0$DLFX>BX(5_/W$6?G=>-#F9E'P?G.C+2;ZV5%X0%4\2\()TMFL@L3!,6Q[Y9,9\&I/I +M;R>;3B:^9G(>%9KR-TUD*S:])K+TQJU`3_K3T9O9^]>-:+#.=M5PGP[O]C@^ +MQW3K;1&T]6UAF_[!DWDHUD56IC@H]74Q%#[8$T#4YCFS.*,LB?10?!(I70*:#6!,1)V(&]L23=/NQG4'=S*KJUR?KZVV/DSG@8G +ML]FP"G((5/-5$M%Q'3.,A4LN&H625*\E?>$@"('4FCE"!DN$H;--$.Z+N6P+ +M@2+^IL_@DM8=HF+2:1C;+"NQJ>!+QL)G1ABC9Q9'H/=^WU/'-W[_\9FYEA`V +MVZ9#B4ZVKVZ8+]@4994$C=(USOL)FLYP*[SZ,<]"UF>DJ>..4B9U*<:0>K9' +MH:WD0%M$.[OM=A'[O5/LQPL0(*M_&RP@#)&(#DAQC4PJ-=&MFRK%9Y +M:"IU\\9,\+\QI5R810-.D%*DKGH1*)W'!3F%W9GI@N-[&Y<8ZXO>+ZMM+W.L +MD835AY;.5%I%Z314^K5^$\VP=_01?!F!ZO1X".-EY+*T5()&XI291RM\S5`= +MA_P0%X\+QV/_2SGS+C=XVI_;RHCJ&40??$GR7^YJ?B"'C>A]0M9>T8!UQUSF +M#;K^/6;/N.S\92[D'``28\D>*,VYYO1PX8))%ZEF&X*S=5V5PZ\*)E"-GGD/ +MXVFJ6WZ(4\\^DU.2?(@5M>R4852KRX6LAX$MO#:MB&G&.CDE)_W&Q3/A]BM$ +M0`'55^-`7/HQ:R??L^09_RR&PCS&OCAD$$?:5<0$.)=1$]=!V_G/+;%O,FKMI0\Z(+?7.B;\^EA8,4;[GI65X?G1CNRIP?NG$KL +M%J,%-8"$HBP/FS.L9BE"=MWA]GY/"TJSMH,]X=J1Q[I:H]/9_'G0G&TXJKVV +M6C*?>I!N8_9%6CNEKMZMN%V!J.(XYG"'BG!V\.LNF:7F&"H(=4[?YW&J4.2DO0@&\C+OR$B:_VF`GXXR9RRK;X$#99C\SRY-ADN8ASW['6)E^>7MB9#02 +M5':Q.9GQL&VDHM<7/2H:_*WO+RAE,V,7^Y"HLQ7HSL:)F=&&,L8UTP#8R7+% +MV+?TTU.5,`R9G([T8U?>^83U%_SJCLP%1_8H79%'IB)G4;#>C-OV-Z4P8S0- +M#+`Q"Z%*#A)WF?5QO4ZVR0.Q,8;%^NO&'I(*;@T#%RDGS,9.%U"ZC32[&Y-H +ME$PJ?YDIC=@LE'/,KBJ#97:-@S+\X@LD<1;\]Q)>@Q@8$,9T6*.X*W0549"& +M4H6^8L;\_`4G,X.^E/375#S8V><9AIC^LHD?\&DMJ9Z6EDK,#R!&+!'.ZZ/O +M1:=`A>V&5^G3W-6@^PG!PA6]>*%+^#L&[*&OJ<"F1+V(@['Q-+><*S=%N5F=,& +M%*TJ16M5"#_[>$BO_WO0N[_TW8-2M0U4\,'.-T\<4P]R_=.3E3C::>73^ +MS%D<@85GY(8/IRM2B+D75T#@N>D0@UROSZL(=C%=3_>:4*!O&-Z;-7^+_N`4 +M=J\03N4UWBI9*;'M&9-O:3G"Y!N4U_01[[ +M'9$KZ[AJE:L@K+\!R.$QM)LH!+`H:(HLK(+F2(-G/]]%H\7+V1G1D-=ILTPJ +M7W0O!(276MI)Z<6QRM)JM<2P:*UF5H":""A6[83MI?\K%;@HYB0,O**LVM5< +M*G&X^D^+VU<<'(:.F"X8B&`2Z?[6NV0H(2Y41&L^]7F7FJZOY6*8J;?"_!&2*-C(N0 +M:($,FI.Y(Z[\3=ZNBS3]%?518H&1WJW;O/A71'\)G%8(1E<,SM24PZ]1HU5) +M`[*#1EQ^JC2]HKM=EPW;=LBH*D&[H+F=2P9\_-`F*7DE6T9[S"UF/I8)SZZT*O^;;G55Z]<%-T/SMW:&Y\[-D3 +M*M,"M\824.W\0':_^UFMB)\#YX-BXO(QH6/%8Y_?RN62M1B>3@6BEO_7E"I% +MX\U@>1#IT#/UXP&B8BQ(EZ#&JL`3P55?E2[E3E[&J%;OX_T(=WM"XZ6(BP&2 +MBG!XNR,10:"T#)2GL4ZN?Y-EI1D0_&E6\SJ.>8Z*AE.J"=@BE*NI"W^1HZ3' +M8SQ^4/"9+IJWCD$F-)*NM$?8XE+6S;]3?UKR=%`'").T+/=6WL5K3QRM +M4<=LX-BO2K-"(S/V(VI@*$`%][J]/]D-;P6?/=2IOK453^X?9Q'1/.8K7JSY +M%MB][%QPUN-\,7NXV5AL75,WREN,TA)Z]E\%F9\_<&[*=?_!L6&"N6\!"A;, +M:1+IUE+'J2I_/XUD7V*^R_TET:4J-)]5.&PI$U.N)MRO-;-5'IM[!D4T,U3_ +MLYKP^AY9`QA9K9P_U/SQW2$I"86EAB[52W8F]7F.SP<,_ZU02&[L.5QQ=3B" +MG2;6,W%BO)AZ:@4J-F5URO=4;-_[,B0:VRUGU?^*!I7#%A,QP8`$,YQ2W.O4 +M:@@C;;<(1Z2,Z@X^KO<,C18:\.'L1O;^`B1P6)WG4IF'WUE;:R(80BGA);.I +M30+"TTC4!C$EHZ72'AE(GOXLV>V[FH?&:'.!ZTJM6,:&@NP6UPDJY+BZ7]#< +M4.7Y=@&NK8!OST^RN*HS^,)KC!Q\2*_JUDA/'6(%3C(+'QO\,)D4H\^+^JZB +MJ#.S-UU9PXKEH$_CR'&\J0&0)GJY0.D\C,F1?FICCLF=CRG'(/U-7Q-N)OKH +MYK/#_`RYJCTPF-!"8WB"]TI3KTWN0Z!GOV;G5%09MII,@)U-EMQ%T*$B@6J* +MJ'8ZLT%98O..@C^BEU-QY:OU>S$WF-B]MTS-C0\N84O=`Z;RDA(=3^/4M<+Y +M*"UBZW4P[33$@9UY1^HGB-41>MX6ST(\&SID47X$920+"*N!' +MA\_GURBA'=#T">%$6N1I[*`^U('OCO+C>/79IEH-ZSK]^TM?*J,S5.Z41X7_ +M802S)/PU-8?AL:+R,L4T+0<4FMT87=PTA21$"RK".V`&:T0'\A\,\U8F[`X" +M!6M_^I4]?O`@[:DL/"@%,AKDV)E>N="**%K#[$,)WB?RX#X48,W^7MK_9-X[ +M"0$UCLNMCXT\N6^'3J][J4?:S3^3MJL(""I6:2'G7[%,;LY"!2?W*MB`X;+/Z44 +M%F#BY=P>J'T(#:W2@L#[<_][E4;C@I;LE`N]TF;#=,H]F"1/8\\-`"9/YI.' +M.3P]AS1A0M%O5I;=C:5Z5XLYE0;&"8CL@/#-ONA2UO:]D,$O!DN]A\U+>L:B +M_N)=62_9UV3?>#4+QX#._JGI#2=T#_4@00J='/'='P15"]UD$O"50VUQ#,8Q +M2XT&8W=6(*/V2==H8\"X*(=#9@K'C-0?8I*U)%,&ETN68H"U'Z^D%XT^*4FN +MVT2E<^2@)VXVX[_$-T.%!VO/[:.@"]G>PJ$P>_]DN]3YN`95*!^',ULC$FD9 +M.18K4BB6BTUQX.[3,JO`2SLAB*<`S?CTW=E*-_'K`*3#0^^1?=KO(`3?TD&E +M/;(V\R=E;E2=L(#%&H8_U(3K?C!63&PO0Y"9[!2+O,ZS?A-X)I4LM@/ZQ=N? +M/<`R625PG/^?D8(KM7O'7U+2G"U.(J4ALSKDGD!"`H8RO;G(#L[HA.Y.ZK)7 +M/V&><+C'59A;_PGV<$URC`L8[LF2GVJ=EA'W8RFTK4L-VYVAALWCCOT@0Y4X +MMOAR6V:Y'#6$OP3:@S`2NM^6EQU0!.7+/D%-APBYG9:%61GVW^D`Q9YFT90X +MH(69=F1^IUTV!:KY#/,JB(2G\.P`!RU?_Y54EUJ#&[M.49S'>]Y%8UJ30;J, +MQ!E80!.\7F@U,(*XH1\<'7ON!YT0&-^?M_37:^)7B*-?9<)<)5AL\6G_H[`* +MD,SVA=:'_.3+L5)U9WO9BCC^4%0ZVE],L9`[S_J/U8^WH,_SC/-,OT";QKIUB98G.FT;6P0=!&$E07(98,31_@$ +MR>`,(G1$&.P6?_[Z.F,@=F))R3JZ0^P%$L*&YZ_'9S!?K9?1?A3/.4<,>\2[ +M'=YK6E#L:8\+7O1-7\9+PQ\W#9.`JC.$[;M]T(QW*1U]*0(^`1XUN"#4LXHG +M`RVM4WWEKVCX9S,')[L;>-S(41O4Y7-QN[4%!DLDJ0U4V&O`F]K+H):I&73! +M`P-1\^ISTD&=%X;MTIMZGLI16!AB=;`-NG,8FV^C06Q1_G=NTH']-=9V;F;C +M8#(G0!I;)Q)$H))B=C-XQ1VI:FI6?H!3Z7BSS'6RW@TE,8\=L.9_M$ +M.(=_!7Y:%%H:3?4G4XUD1C-<^ZQYT=Z_01L$F]D)8-?7)%+VK/FSV5D?%&L) +MXH53/Z[)\]&6C`DZ5NK6AG@@5YZZ+][ECSZ"OZ5;FLFL?1UMIQ9:1:['@A.7]#@M.3+EANT +M3FM3)>Y/,HRGL*>X*@^8[0=P!.1+R=J8F?\QS-J@&Q&][S4P,/,?)\;LQ2S/ +M#^8R7D#*)+X,<;OW\\Z@CLIX=!GK>]/;_,B6@E +M$0L0N%@J36QQ56%H,03;FC0M!O/DIM];XY?V;]%VNZ- +M,Y[V;>6S(M/WE)/B"!P5V_YH,B"U$-/S^.';UV6_C'MZ_0WQ5]:7C3%T$+^( +M9#=O4[ENXX6!R5#+PWYB?&&N4KT)[I,FV]>=0L3/-F7:2&5R76*:Q^^1Z@"H +M$E8.EN1#_8G_LK`'&;5;9R=^Q^7O9R_.'<$(>_%Z+0@3Z*VK3CJ,3R#5T)6G +MVVB$>V-L0R!UTY=A6E[IQ%BI<"E'N@.UT*;P:,%5>N&)$PNA7C'R/1CQC>#M +MO_Y(<./-]U66B6ICC9O*$@]GL*?@WR:"@9_4D)UC1!SH[R8XJN8U\SFB#>-\ +M#`5(B"L/!*#VKZ62\3'+/6S^8/UV,Q%!L`)\MB!M*NSC@>IU>NJD0EKG``$& +M$9HC+&N7%&W5JA$-,>WX2(*G5QV^-@K>[TCE>NR`8=ELAP&2,19):332>+K,\OIYU +M!M#(_U,2N#ZQ5%"VB.9:%G7$.![,(48YD^[FZX3%%PE<2<]X]]T,D%N4WH+B +M'A:A_(B%F875]*O`+>OF;3.UZR+U8*2(J7KO8< +MKG*)XO/JC][]7_ND=@][\%L0/1+ZEH_'UT9PX1I-W*5`?!N6+'IK$PW!D8.) +MOKST?SH#$W`PVI"P]HHC1_9]4H".R@L7DO^G;W +MO`<4"8+9FDHH0V@2VA&/Q)R*-V&7;;<5R.DTR)@DRTY\,76X#CN?G"60O8)YF"$2%7N'M\CP($/U6^R= +M4?_HOS^1$I*QY<+4Q:H1U>(T??N1[(Y^1F(Q`&VC!MP2$O4QT-;J:Q3>GT&6 +M!SO9#7MR,5DLOS)3]3JL@FK\K^VFO5U*^ZX*(LE*\).X;=]1`,T6T3TL-(>@ +MSDQ"Q)0M-NSQF/?4EMPS>Y\XV7&03M;;O:-H\74(J#KR#N-HAW5JFP'%V*L] +MXP>B(B5F;X++`&J9%8,VS+H1!("P)+@M[-W)!]9'Z.B6,\2%0"3(;L&[$V]9 +M-&D0G`>\];9B@:4?Z9VN[&J$'7N]+8/%@>MZ9Z-A>AA'6681.?Q8^&0'&QIW +MU_S3QNU`IS,]Q"7+.)$0Z^:12$:@0]F% +MV5)#N'\%*%RKIR=!_WG[L^O7E]1(@Q4?8HI;S;JJ^N-Q/O-W]T_23:V%&X$P +MXL-"3[@\/XZ],_U'Y=RZF6HMWN2V5^TT'`!VE;R3\"^!]&#&P6/?;E2?W:)$S4;A4&IC\J$*M+E48T3'&P+_"0#1^.O,[V +M+!D0-'5?C^-J%9F^JOL4WGM3=;I]'D`WH:(1L*3B+_8!%P!Q`IR?@8:!_W>N +M?RN$ODTT'#:-V#5L92>IAK/$$KHL!\0$N2Q7$;"D0U6(!C"I>#%U/4\+71] +M&3T-"5H$4VXA$BN%C]?QZB]RXL>"Y)C4H).[TLZ"-CPC\!^*=9*;8Z^FO'-< +MR4-#67]SC=,4N!1`<$M2X91X0,G]J[+<\H=BUIP8;SGY/SD_].BZO<'1CP8V +M-+\.39X=;;XE*"`DFDR&;36!T@*\Z"7Z!T3&*D!V@NLY+!SL(2`?<&"IG,): +M/:%9A'<*9E82OB>@;.O/0WYBX!:?0KNB.2*VS1G<4AWXYL)-S.+"]6 +MC[O32RMY1&IO`W'.+N]=`YZ`GL]GF_=/Q]Y^YH+#Q`J>;L9GK@?/GM*2]EEWMC,4VFZF#>U[FL=56B-I +M@&&0[.'D3'D-EY:&!,;=FC-_A2.50`V+LPB\+(=.0W.:=!DS-=]Z.;-!5RQ8 +MO.41WO_G.)26WY-Y3,JQ6`V$32(1.ED*&&I%CYXTR]$-Q`%9^-17 +MV?+MO6%$P/&[?@P/WA6PD==?L]A1:3\?^`M-6,93[XN-ZJ#9T39)K0!$T)@9 +M7`'O]B#&QXT*F'5CHLTI2P*[M<,VC^J8'YOT6'85B(X^G@E/FUN6&!HRC'KX +MC\5R2L!10H69*YL!?K\:57NTQ9 +M?U@R,GG=N&[>NB@D-]8SXW+NP'9XF++^P<1"X%W0:"I7<6S;S=88O.CYX=3% +MU]"&^$CXIC"7,*7ERV!Z0_)YT!4]^+6D%_!4=TL=#^0YM5/K<(^]>CO?&S\G +MC*YI2M%A@`"FXU4=H)4G:_J#JD795!+10U +M#2RO*##N3(!6+&=71'5XH5YKZR(3W;<] +M08DR^`2$;(=6!>*=/^+?;IGFCTKTV%%KTP%2H_=2G4"^"U0;59-U.S?8R^J6S].*>3)LR@,.(Y=B=MY:DL@2Z/H@:;*&2T_ +MQT-W69(Z=]2QV>GY_%M4Q0?X?64-+-2_7Q0H1OTLG9E7NW&F?5'<80;>INKR +M%9-::->G4!\>SZ.V>W-7-PP65E9X&MJ[S+&29IYK^(-A<_OY,:42W>6BMZ;F +M_VX,D'L.*#T2I)(RU'TJI::-\;_^:"'W>G^2SBU/1$B)V226S%)]=@=$]Y#> +MQCCA95_6^IA]BU"-F._:NO2#"`GK#F3GRU@N$P8!QGX.Z=<*6@=6[\SX +M3JH#"1G78HM+(QB2'8GQXA>P-#R:$^,O/;\.JZSYZ1W-9?:% +MHU%Q.)1+U5A3?1V"Q9$9:.V2@J^+T0$\&([TZCG56([J: +M6FC]:/!P0,\T^)3&WWS7EQE96X**W)JZ.6K(T1@0FVN+EX1KO/'VRO\4>]`' +M"7CO$RRT8/9_.V9HTS#=J`JB,1>2H<$=Y?Y@*XKMFPBV(Y/9WSB/$S5EL0J- +M7NUCT4<0+89\OXR>/\ESDF]VT%4\==3(>'KA9!4'DJLN#;'OF+,0LWOM)W#Q +MW':4N=/#F@*3CYT)RS))9'D7W[LP\W(.(B/,:)9G1F3XST@5-I%UD-+:@?CQ +MT''T]E7,4W>R@SB`/VG%&1C\NV2;\01"C)+.C?_&>M4F_C%)FI01;1@E>-:UY0 +M3JU1[LL[2/60B^^DC(#46HC6.`-F+_+45:1]#+`&1"N!;MR$R(TA!M'+8LJXU? +MF[F3RCF++Q5F\.F0-<>$KX1+^$XP)8*1N3_U&"5E[XTA6-)V^$7FXCG!%R6M +MM01295)I[GXSPXW#$74`7J1D&7[H\J(&0<(%(KB2,7O#HB[K^Y`F%P\P#*7G +MEB_\DM)]>[:UL007NZ33)!QFEA?MO:/.L+87>A5B/FB4G8W>+G[_$7[D6!K= +MB&FC9(NN$X&H)N"(HR_MI*J:`BB-(Q:C0+S0F37:6`B!Q1?=$UY!Q!B? +M0GN,`O7AJ?IR^>#BU#;O57X%)(5I>1VB,J'QP5^[SC>7(8J`)95JL*4EO%TJ +M9XZ'04'/+1-L@X[8XZ-_3&)WGN7QC[Z/+<`LY42VP$7=;K&N'N](+Z'ZSE`Z=;:A5/%P*98%(M$^ +MW4GQO%"=J8^>1>3?XY(%#\;$OTY)_P2U,@,T]8/%3\O-5Z-?"JPT;N8<+)YOP9;U?`]S(O?:EA[`Z8#.Y:$='>P[%T=O\.&(H.AJSH4-Y<2S>$OBW(IR`-5#,#%ALL4A7-$%/0'7O5TP$:W:CQ6 +M4HG^;ZO89?(I-S]N'"*(MP(@^R0=QL*"SNN<>P*[#H5J4S%SI.'73H.V9DSM +MCOH/;%[.("1O*YK=*`2\JUH##]POPO@ZJ[S_\C7Y=\BI_DGM65@@P]/.<;E) +M'1X=+>XH?Z#^'XQXG%<>8.,\X$3(,",IKV3X#C[U!"PK!G%Y"`=[\U@5YX3, +MLLY(5/F5&)`Y]+]4!P]79%9QF!>91=>\=3^=+,06.)T)2PD[(GF9"'K!1(A[=\CAOO@>^7>J409JHB]D"B(/ +MLV]YA_B@I%VT$3'K_DZ/&M(W63R:@PK][NE'Q=CGI$IN;4]G9`:*;/P7#^ZC +MN%NP:UJS<5I'RO9%X%^;*&B.1I,'GO1V6<%][,PRMZZN^$\<5V)UV7!3-?V6 +M#`[F,`X((M00"&7>TAKQ84>&/( +M6QF[GS1V%HTWXH*D_QDVC)(<3M(^R2;PL.'(U_E$=<_CHNGW`-51"QB2V6]B +M"0I@>HKN)9+\=2/Y-;>M@69H%UF&/,C>GSRH6T/'>1D;[B`EM)`VN`&$3A[7)(U +MLCL^8;O2#*+O5V?PD,E8?/)R$]I;>^00OP0_6[UF+@^7L-X.:YNU!E7`)%^. +M`^[[2$"#8-=;%9Z1TT,;'@0Z73*MY7!957O[%T+L5^)D88H+JT6>AA6'BXO) +M@'0G5\>0YC8#RQ=(?'0@1-"+1#B\/E+.!=)'/]-6Z1R3>8)4G7PH"7IHK7$02)DYZ](^HXN01K%.(P!S7VN!;.1!XQS&7S-7 +MPZ?0RA!*;;&;6I<$HI9%;@8L+7AQK'(V_P^J6ZAO1W,0=5H"MQ.OBORYV;^QJYC/,P8_IUL8W4TD/P!P]'V4"<"]KCR!Z!I>$\13V +M%7&HFF]LTY.?G[^QK[O:8@8*@=A%-,6V&2WK"A':!_<0(#TU +MZ4NL[B@HEC+I-QOLN("$RBCBMXHU9[/EL`'*L&$C>#!8)MB7,!@_UK*EN?^LQ*RA!R7?JZ#<'(JVJ.B^Q)E8IKA'<$3.JL]/I%/NL=:N!?/P0](AFP +MD8"]\[6-M$3_C:?-L^W'Z\\1)+UY0M#VZ&855BF`*UWT7*H`'7/U9.--ED'1 +M\BA9WT&/_'N2O*G@.F.DU6..NM9OLE@^(QFND93'OIZT*BT]HU-EL"J7['1&)EA25AK +MS$[15O\YA.,)=+#]N?U$\N>)35,S)Z66^@UJ@E"6HH!,<*^NO&$JZWNZS3=?T[M, +M",?@48B*!DL.@U6>1R;UD@X1V0XWE<+2L:6_P=A[A"M&SE3=I`J':18GF6'FMSS/*'E5_HE_K/-S"CH?C\5&0]2: +M(='4.^%W6KX?BKQ@)SPY!2C&,64M.KJH)FB*F-+,:4T-/LY>^2D<>I:F`-&B +M;3*``RP5;=:DOBMBY^GCD/2KHXQP124TT_>C-G?T>P]%$HD`P?+/3;;3'HTH +M"W:Z6EK8C4/M_O1.;@=FV`3$/*H6;4S40@0=L%ZD2T#A!`*[R6\-%Z_8J(D# +M3LO&$!ZODE4,Y/&UWVUVWOY0/&%CZTPS#,^TLB#L\Q>C5V75M?SP2*TU%A:( +MQ>*-!9/DTWJ\VC^'7()=J6R)VV,*[@7FX65I3C6I3[KVV39(>W*WU+;C%\^$ +ML/^,=$(H]#!UDEQ&2_%"CNZ'57(.2F/CV^]1Q*`Q,S,/D^!AA"KR]7ABI,[,CH^:UM18_&[#HY@2BL7](&BUQ2SW)'Z!;!Q: +MH%7_!$>5#6IE@X#OI4A,#W7;9&&O#0GAU$^+Y?[.IUR*T*;>W@5*Q9;LP6L5 +M8M;UV&(@PSF*>W[B6N\0P'=J**-`*T7)^*00!+7%D0RV[\&;QS&9(]#`+PA= +MUSZVJ1]U[4Y8/T3R:M'AQ*8=SPC=<.[DY5WV"#[[,OTS8:15B'[;YR'Y;OUD +MZ4M[ZV=(H=A`"QY%:!\K>)A\%_Y8UT1V+'[(5CQK35PXGV#HS&Y`*L(6L)4" +M(3;2ZT6U:45QI![!HM+!_/YVZWIOP?.MO<,;$V`PLLV*C3^V0X(6"(Y$.-@Q +MNZP_P0V,@*O0I^>Q>7_M0[1\4-02[5=%GLMQ=K!86G70\8 +MCJ)\L2VB,(CNFC-@F;)R+-_06!^R,I\'^)X.X`3:KH-:2&S^'*[/W% +MF"&87G;7TZ0G-#Q\[Z:TL:`[TJ9`*M!V!^+KCP"(_K. +MO4DX&W,5`%D!!V:XG;"RL5Q18M;.-)-'4I7.;$2+,X1`KW%]8?UY$A%+U>87 +MV:)3JO?F5>$W^/R\ST%\F;5HV#$+MMP'FJ7;_$5U<6V6MV9:AU91YE9)!BR? +M.`!I"&\:ES>*M6[;2(F-M5W +M&]&WB#H1>5#FX\'_#`)A>[>6^I:IBGZB^V>]NPAUQ,M]0$B-]1_D6;6L%]E` +MCBJ=BN/D$"],GZNBQ].1ZBZ1-NG5*R%]9_:="NL'/=ICM08Q1X<&1B^8,M0] +MR9)_+V0B?1W<*CO%)M-56^"T99ISXT%`RV"KR"`>C'8+(1IJIMC);WH^M?82 +M2F:1((20$T4:LA,`R@V\XSQZT^N!:2E?J)+Z`QULB>"W><8:9(=2+]6T^S%. +M+W%+T=]G<+8W/E.E>X`I$;$M-9UVZVUF>"0-*^']9Y=`7@<=R1F]G,2O@*\? +M[&,Y>.&#//\-0'O]G_^J4LH+XFM&>1Y,6TJ4G0.<`.'+B:G6++A2]S*8,(3% +M@O@3-)A+%F*S?THBC;U&:: +MZ5YV%B3_BF+!2K9?J((!S>U.=D*AJ[6LX.`]@ +ME*L13?E$"<94"(JT*W$*&0POSOBX;"LUEGK8O-Z)45I9#>3:JIB!A.*UOZ@^ +MHI+G?H&/;'E*9+L.R-M-6F=&9_AD_5&CU&:C4V+=90V8@8V255"1]+W[@6^A +MI>(,;![RQM'WTB$\WG@8>>Z;'_D/SE^U.R>0_ETW'(E +MDW`.><2*9;I>8D1()%#DL]9*MV&IUU9R.,XHZ`N[UY^A,A3.P'N(PQ6L>AB# +MEW36;-04!><%2NIP>\)B0_O!1U0P,R[TNYIR"S@XA%:A7?1[ZGF2@ATF\XLA +MIMVSO,BLEVBXC%U_N'@5/[5AZC4>QI@3F_=787'E-8_^>%VZC#_*SMKUS/() +M:XI42*JC&>NAB\AY_P&;1QB:`#>UAS$6+`%C0E4_J%U$[%/Z'=S2KP,WB+:, +M$(NF0D-JE`.(JX,/K3+-79=-C=9JX%J3R/"LAQSZTT(DB +M]/@1=/2?%&.DH>V5&'!?H;GNP@(%FKM(!SSZ7JZCUU9C^X\]VT'"& +MS3),#/:9KS9&7J4*LAY>S4B6LSG*?'$JO-E:>][J$G;FH+:\;G""S,/9/ER= +MJTW='2M%NC"YL+4;:<;2G]^<,,^$X<-'D#?IB&W8D0RW>/)_%NPB):-ESVX& +MQX!0V/:N;Q(508NGV=+9;;^:2W)?`LGA<04'G81!A@%VLG6L=V>Z@VZ5Q\\] +M!.-?G9!3-:OKS?1'O[`SW'/'H[[Q@UV'=?SIDZU_DA#G3E>&,&D$?/.K^HS9Z=:U8M!Y/4E?MT9F"7]_R2$B<)_2$E3^C1SP^2]2[Q3HAW@LC* +M9J4@D[)/!>=ICYE"_C63$"]>B_]??S=CF6$>^0/"EHK&\OL++FU'04Z=J2V5 +MOC[?W1QE@.P7$!G&OA*=$8=5EG`*9](2XK@#4^*LF3`:F)V'Q$'M>?$>7W6: +MN!)>%SO@._&^UJP<0,.&`(A@LT;/[.J/]L!0?=8G +M;S!Q64O+*$B$VJ:&U+R?-F_9C,SU$V9Y7U:K!'J[/_'A-(3?3@PG0'-U1D`_ +M69-XUF4$5[&TQ"/T@`B]S?DI/G;1O7A."%`Y0,-F97=,#,M7).\H@T09+:`E +M%`!J4MJ1NDBPI`4W5N.#>_"E;^3H3^1"S&O^NKO/\HV]!`QH#* +MGTH7"V-M;#0M@T-MN[`FBV9U@V)#5/TB@.H,#+,A\ODLS3==6NEWLG3=)9>6 +M%'6)341>V&&!CQ4@L4\A'`3A#;`"/<)V.CDH:P2'DN<'+\VYY?@+2)KB2+GK +MK0=?X[+@:'DQ(KZ)+??\8])HQS^(KE@-V5LO+/KD-6$#5Y*AL]$K!Z_?20(0 +MHQ0_*2`>-6*^M`TDE]\WU50#.3#:+V3AA-*!&8J@\F,2O_T3#VO^Z(%O= +MO13R_OKT%.#<90)4XQ!&[\[\T!P5ITO&/;I2A*2N62,!/,%-3!& +M7V0_MJL1J3/EDESZ?S:.P'.&W3.E,D$_Z>S!-.`I"-(GFR5^5'0^`YG3;^!5 +M2<*(9"5AX0UU$2D5$Q&2>N9V+F3D3$9ZD'O'^^Q#9((0Z#[5< +M7>4TGIR45K^WT/X-XSR+OG69OU52@/R`,V[D($ +MZJK:Y_R>?T?L5;5W>ZC(_W_5S4TP"K8UK.UJ8\QR:\0-XN>%'962``ILI)6& +M=X(2!30/^KO<2'!+*BH>I3UK+C&Y_BUJ33E +M_A:?1#88S;:N,)]^;VEH`*+7Y8M)S4ST'((;"P5U?+8-O+I>)GKK+L:4+6^B +M:?!G$3`/%Z@L@2#.@7'T#`!2;X>PO\LAG\9=]FS6P9!B-VH2W);@"]B.C8OV +M>V",*YO^UO!S"NSU;QH!C317R=L;ZM8?;`DQ_="YSNSHEK=J2]@28X\DVJ`/ +MKE\=IB%7YNZ5X8GQ84I:5;0^_;*9TQ>LH+MHUC_#_8JL=Y:@M9)SRU%42:C_ +M08^+`Z5I48`U^!STF!.\2QC$0T@#Y:-VY.7*W67582IO%H>X-T_]\M(9JE1' +M*I$Z27/I+[),/YTWR<5@5;`6X"C_O-_UW=M`@.1DQ0:+FJU&F?S!X43JW?I\?8M2I3B +MO4![V:=Y34DKX7WN8J[A/=L'P<4MTE%L:&8:\7#2"WZ-LM@/1D0;-DRX^J0Q +MI37KV2D7^IV'SPEYJF'G^QD5LMQ:X8&L_%EN+*O5>+%,I)?XR?9CGE_ +M3@VEW"\7#:%>V^A$$2^<;W5&&:0]5L63A/I,HWJ#E-UG +M`3/TG7**K&8<,&1?,_UMH$OUCX:L!]H\O70U$II559P[5-"4*1H]H,%0IU2L +M>QR08@)5",7>'8KYK,^^2&D4B,_HST]/[;]]9PV,/B5R4X!YYQ1(!Y/"5A5$ +M#XS$?W[II=\%GK/EFP]MPS`^$K>QDAO2]I=QZC@+ZI\QK'"RUOXIK]HIR)+_ +M9NV+@G$=EIK1>&H:$X\]UG0PX9>+[(#$G55M?"*KEN +M.9@=LM#&BJN-ZT'&Z@.8NL]UP;!GAJUMI[?O-K-N#8JQ-#S#:$4=JT!!8B-' +M6R<0*$/9KTNY3@*41V>]D7N_ANH1Q_)#4\KY7ZS(Z[OI9#ERN:;1[^[C.FZ' +MNL#KU4-0D*T(['4@[JF:_\2%H9=\!I-X9E=5KI514B`=*Q7<$P)FBHA'&']AMH'=@F5^ +MA&A0,[$&TL"-X_]\00G=$N5"0M5O\P%/E^^'/$[L,JWDF=D7%WP/]F-)5"ZE +MRF[7PGU*EYJ@!]C2=?P^XH`W3B2+O>XQ[:IB67B$Y6P8;FD)`:M_F)5U?>PG +MNGC@'K`Z*!RV=$5G!)8O7%63!F#Q7EV`M(50:#66\_?://U3NX@:B]F8XE,O +M\+'2N_V]J68DOG.5;7Y3)%Z@FF8%\_ +M9)M)NE3N"\?*?LO0+K9E]O0/,#6HGU3X+#*I5ONUA.@:!#H +M:@GL2(#@]5A4<;RDO$3YO9'FZ'CY^!J_W;6.349GI1:7*,&$,IQ-U;6J)[/!6:;??BX +M)9(,DRT\*N&\^.BKN[\7-EWUBUMZD,YEML73HOB>M>OOW@=08".EQ%IVP9@$ +MT[6;^BMM$,/6L#,DA/"0'_+?1LMKD-M5C)%J!$(15_FL-UDHUT1B`)B=!?'] +M*[&#/ZQ#BNN+(<8-<[W486'C= +M$2R"E,I-V\VF+<0N6SD>VHK\&CZ8;-%KZ`;+!54.JM(B%ITN]N]::->$IPZL +M6'R_F$@WI8'D0>\8G)$>7SC>Q+LE_ZVRCWC0PL(*+"Z-#&;LXI/;7[UDB&+> +MA->FEB6[!!,$(<_J]K/FU'4&.C&V@`]R$X'E&WI++S_1&O9%1)Y"/T#WZOW0 +M2%L"D'.[;IL8-G`"Y%QG?SK?;%G$KN6/Y$ZZ`N:F7L'T.<0[G\7;I%!("@D4 +M`M(B*>2&"^Z=RD*,:::XR0#@+*MR\\BV"CA`W27$7@$NF7CC8N\0JX%>GB6C +M;<%2K"-SQ[?3HJ9-6BC>;SE]7'*=ADT$MV>X7@COE-B%@OEC+&J-<622=S@5 +MFYHW04,41?R(Y@6=&#G4#!A1*3K,9"4:2BM%OP!D/]DO*KMIYO'F&1@CD<]F +M^+S8NEV[^Z4PC31WS;-:#C]7DM?2J@32Z/>6]$LZ<)5OW9@HS\9(@Y1L.=7P +M9N,MX!:_X^`>W0U]4FAD^J%-LHIE,5BGK^L +MZY*7#')Q2@$O&681D&?"Q>>ML.,.<+K5'J9_4C(3$0;(@A*W15SN$V%^?ZRU +M:.V'5#L1>)O!'7_T5@4T14^HL,MUI9HB83ABI!1=:XZ`L"__#!]<+K'% +MTNJV5LB$9S?Y9,$8`E3_J<:``&7RH.0RG=>90[.'3:]?#,;;(S77=]@K],7? +M'QZ17``[T"OQTP85_BQ:^)_=5M!A%2\F>N&TIXY +M8M^M(0;+.&YN=3E7:0JD=XCV1K%9>[$S,/?0DIH)%YC)K_LV!N<()X3+<.Y1 +MX*&A,V<06Z?M6F/JX'7_&;@Z^_1__T$C4_94`P-$*#1?]2HJ@ +M,TKY$E)R060>Q\0>I^T>!\2ZX8%1!'`Z6JA47P_'4Z$C4HOU">:=BJRT#F"]+S$G>JO::T&JGJ$8GZC@U]%IJI*J<*)%" +M[\3FL%GW;3QC.0A4N`I-H:#W&0?2-;$BT&!F]@W7!,$6Q.T$-'OP&@D2H!.; +M1]\=K90#1;@V39SEEK^;/_K/I];+T^)S.QUO%3[Z`Y#<7`*V2.DV*?'\?`8+ +M7=Q1(TDT;PR808\NL2.!XLU94:2?_$>Z&J+<=6B`'0`K/[>MI"!"$:;*29$F +MM9ZWW.2(90< +MFB:$6;]/91[$3QS`M9^;XEGP.+-"O;%AUD24P9L$>#_E%\,A/K +M1+KJ&@6::^B>`5'P>.L\$J;7JI4SQTRF"3\CU/)[PZQ8?9*;F-0A2/HDO +MOW0<9Y=BX,E1`3.-:YNLHJS0$BFE`%[LWHQ8[F43[90;:$]^MPNW_(D&;U>W +M):Q0"##,%J"1CG!F]+I22"-?>66]K4*&M@J,OBTLFH<<;.F45P!41ORB8[FW +M,AC''O$35MJ5R,<.N3$Y*E<\'Z8`3T:_CUS?[LLMA"-_E%W-(+LC.^W%Z@Z_ +MOJ!$ES7Z-_\4$5_-3A3';O`CBIC597ZE_N#8"R*MFW='/6PDO?I!39_J(:(L +M@CP77)(%VF9+9S@ICVDG2$XO.3(33A6)2IIZZ"Z)E/#X?S.MT7W<`T@#69;Q +M>(%Y>.^7;3&/OR.W-NO"[(L,78K9B5//1.^A4C#J\3,O5 +M6[J5=.PIA)Z!1DP^#AP;G`(&NK'C"25KX&:V[!,C#X7J1;$L-#/,124MKY$/ +MW=D`)*^7Q#L!C*^K(N_'//TI"K"7++(ET-"L&>PA!DK%47K'TFX5D/"=1=SR +M<=[D3BLL\=V>`GQ?6XQL,C%[9%T$8[O"0@S;)S.E#0-'%\$::N`,V?:>\3[K +M@0%J.K?A`T'3P8;L`QAB;E`Q2C@NV%WQ+HTQBI]].]K(Z8;UG@A,&?OKO(IL16L^JD- +M1G_2\K6(A9,)AE76U9/O4\;7/""E%%"H7*+^U`M\1%@G5^FVGLDK]JA=8X/% +M!N941.;J/2FU+3;M.^=>`9]'=G_D&LY.VY-0.%D_R#!HOB&;=K4,])PJ(@W+ +M6PW@A5VMCWWOGI9O=#`1_H//0MO&R]F#5U&RZ6.R1+Y&L&-FSQ%X2_Z6LT8A?GND6I2`4K/0@7]\69KU%?D'RIZD8X#T["IT[]_`"QDR0 +M!<"1F@*PGLTO%6QQ54,]:<-3HCT,#@#,%F[X)G\::`<=Y\O7>I#>`X`N><>3 +MEX4^ZU.N`5##1J,)707Y`PSC"%-X@<7!+Y\:F:"PRC!=ZCT7%1/=A`JW6@6F +M:AB@7"&AN4N`#&C>H\77>).,\'8)7T#/@\V?9<[)$LJ=`=*TE+#@\G$;D[.1 +MW&@QH%5VGX_.O'LAG2[)X`-4E"K,OL\`;A&5S:.QK;YB]GT%Y6;2:7'3H_%/ +MN/\J9Q]V#I:*"A!8;GR6L4YWM8HN)Y0O6QC?`>(NC1V'(8$#%E&@U*T07ID1 +M9A&G`^'-KSG]*QY4D6'7&*9)DN4PTDE'0H9D>3IO'TZKOK$A_G +M1OG'D;PUI1U\;"*H=@:AV;%B?'+\295)3LY#S_AJV$3[ +M#IN_>ZX7N+^I,>DR!>I+(!'Q:"?>#UYH%3B=H4(0AG)-K^W(QN157IN7&#D! +MOQ#6`Y5+PK,E.#@_.D7[<-C6Q+XY/?R%'W9."^]#-BE!`DT(C%&?G0JG_PM6 +M"\2[^Q7`;.$F=N!'07:.Q4W[+50L:,PMIU#H^[X]+R)@-,TP$,\+QE4CP/9[ +M[RP68>W`5(50.^O>Z4'DBNXL$$.;3)4]`BCL +MM7$2.$1'UQ$:XRG.Y)06X8Y/5PFR.6B<=KB7.8VXE2F3!?KHGI^1:57N??FF5C$"U0<;;@;K\:(2` +M0JZP(Z[H&?.(+G.=!LNR8W:G5P.X9`\G6Y\YS5!3"(A+@D?6N'?5['<16Z#8 +MS6,$BFA?I2]AQ+D=__7JSI.[02JHT/=I3TY!3SML/>-3@QO=:[^/.B&6I'-G +MM;HB9N^G_3O>!V\35$/%-SWJ5Z+/O"+?P]IB@&[#ST0#3+FZRC=-);$H4+5" +MN=(0G=H^=(8]#U;GEV#QXU6Y?\(IK^\E7*''I_`GNW%?L;F9?!P6A.[NP>>%XU`%20^M +MCT4`'ZSEYR>WGI_I)'4IO06.2"EK@A7)6LI]!<3J!>[Y'/.!Q +M9WH)U/:_A+5@'R>;#[_-QB6'I3H[F)E%DZ^_+X#7LYBMIB](7E;9 +M%%S@?^ZIO$^R&E#-=]P4K="JKWL$L0E2/Y7,AKA+N0J[NR&6ZR^'` +M=A1)[)/?(_M\8/V',\3Y*HDD[%:'>GCV6Z^WV*$$!=PH4/:+YXL;T._A;9N' +M)3;?@J1X?H0'M**[U%Y;X&65=:;W%L#,-F48QAZ?Q]W22DF9(G"!&$[%A>![3X`XKD(M-6\4,=3]1G5$,] +M=H60.3X]#/`&0KX0D3&7]1K<'84+,^2:4"6S$-TB3['67YA(6^(\0IJ,I$?8 +M:2/T"P5E+=Q1.:]>;&JGMA-5-NV:(`I^-S:RV"TJU2K^X@E.FK)Q)QM+?$.. +MBIS/X$.:6X@I#?A\'HOF0*>B>7[OD&KCY2A<'BF$/CD +M6TOJ<+U[/ZM/D_$F_W3;&C]' +MVU)T`&AI>CJ'B:J'VS5A;,SX!5A.!^VW#.J7F_O*\?_\@N=-DMP-&1Y^WX:/ +M$\A6!_^LV$O-#RM!]TNN4LY*^99?C/N,G2#(DS4_>EJ`[!\&CA\-KY(G2O!^ +M/3/L:FU0"KDQ68(WRT.>O]"_N@]G-VO0#P#4]O[ESV%3O\;H>\P')6Y7`I/Y +M;B/HKAZ]>73T^0!$OVDHP*>IZ\]TX%FY"'3V\,04-@-L,=#K22Q^/)NF=<:# +M(R-G>.EZ:\W_<9,QWJ2BO:<+L.`X(%W.UH&3'@9:W[!-V$?QMJ$Z<.3\ +M.HWJ0J1'Z?/9,&C2;T5?X!&C[XGZ(_J>OG@!L'S^)7*3BVFV+]$1A./?0.E] +M2,\Y&U!HEK+P([\?6O!Y>$PPXA,KYZU6#[>J02D+T?T3BC[4$B=F3_^'X!(( +MY(N35MD)G$IT;7.PW=IRFW^>S)(Q#!JF+^*OH0K5I'GT)?@(CW142PAB(GCL +M?]>/"`0?MLH^4,=`"<:E?YZ>B!Z9(U#XB+M2[`'$<6V$-+IN9($D-"-E@LEY +M=Z*Z\*%HY,#2)7DTP(YP9EN%114<+![*!TB9^%L2YS])+L(F.X$A?J[W +M*T)'JT3:H169;BC/%>GE3FD\CM^(@`=B&PP)>]#:DB[T<]1K>/&0#]6E$5*K +MKBX2+FK(V,W^_778X]NFIH"R-.R$;Y!/E=>,^,32F[>:+P(#$;OF+/TN`\:/ +M%>8L+JD6(.;0Y\'W^/2EU"F9<'LH0^@+^+KN(-Y"];:+KT4YGUO]J$!J&&*& +MK"DTCVGN;:'9I39.E-N"IH'''3$%61G'^X7]98I*ESV(BT,!4<>(IFK7U@_F#W&_DO* +M-G=?SP/.=D[LO+F*=WL#G2]CJ7HTMR\0+2Y@%;I0_ +MPHL$Q2]#(U:W*6Q#K\"^B(O7?P:"!'!LIK:#+O7M>%5C>OU/#&,N'1#0]E.P +MT,BI7!(Y4%B$'B'9-U?N_+-T?U5:T-"&W*NGH3:B&HX_L<321<5N,W'JK+J( +M?:(=>.?C?K4QNEIR08%:QQ,5$?5TY\]!A?NH(:BZEA]!',)+$#5H@(2OO]@< +MLH7C9$%^@<$4=O&GEM`ER7]`%"A/Q_4[RFW@Q=5+B9XVT&;A1&A/5JT6)JK +M`@YYGNF?D(M2.KEGVNH6'!EOZ^+\`>3K+9*X7=/-3=D"[]H2Z\Q78\:WVCLO +MV*ABMGG,9O1 +M;RJ7WO2I>)#`_3)%H/>((UU"&M)ML_C1JT(BZ0&STL8>Y0<6;E;ME.QES=RS +ME@Q';T`_KZ\5M.>^#N"=JTYB;SNJKLIVL]X;?,!LOC7JK%%F9Q^*RS`13>4Z +M).*8]9W&3(B`2,B9G,)PGX-7>J@;#K@3G`O?M7A_GBR8J06*4B +M-K.:5:MV*1'.S"9Y\^F2+HQ."'B=+R<^-AM>3U+!FEH1I#XSEG!/8I81]`85 +MH0_5YQ#*BH/'6":>S>4+^PHX?_BFR3#?.)-R>B6[PI*[A.RN[%#Y927 +M4O'8WKAN^M,YT8+8>8>BFLDF'%&_* +MPL.DUM +M!TLS1X7.]YGYO[N8SW]F=R$FW37W`LDC^+B+F^$\RH>[A:_PM6TC3C*;'&"X +M[\+H5)'#LQH^ZITO3.OUUWX>6`JA#@<`M%NQ4)OXL0=3?"YFJTN:P-2SO;H^ +MF`[>ZE\1X*$6YT:UNQ=`)=O!!ZX7'?.-(_3M(K`5V$B`:AS-1WGCN%XR.G!Y +MFH?NFFTN5#C08>JFN7I[[&GZ>9F0B5[8QY*78%=_N\V'V!^.*NK!(^#3A]JH +M$?6>?PM2/3'GL-]`8O@/,'<:QL/N5OS#]T7>XH"S]FV'![GHGA6AKZFRB9Z) +M5)N7$^FNY:[J\X%44GE^>*F-1Q6<>?OPX+VHG1)VCW,L6!9.&^%AG=60XH4T +M/9'H'J=].E@?]5G[[$C,/MB.EHQH:X1+8!B'U/RXT?N1)KSF7?V<6K6E$:0N +M_,N'DZXJ50`M?`CEJ@(6/@-&4!3X-86<4G,/A5&+HMI*74(T#S]@%T,P;0K[ +M#AQURW&INS/M27X+6<"&X>JBV8Y^VC("ME@@]%.TMVWQ>GZ6>5( +M;9+E$'[=$0/ZY%/"$`B`(=AB0^>(6H0Z'1O\LV8Q4%C1"'-&`Y!2J8C5ZVA7B[-QYH*6FZVJ +M09W9FE&,*Q5]U&88==0F>W^KP"[P4>#N((";,+^V6Y67;:PA_'6`T+E,Y*ID +M:ZO"6B,`ZR@67"LQY1YSG+!#''KRL;-R@8KM.*I2X2;Q:>8!$VF9]BV;*K^% +MO^^>LV]_4<.WM^;3(KID<=N6(;.HPDN$?KQ%Q%0(XMF +M8J['?+,S3)Q(@XP9@70M;.U3;2W$R',%`QPLNQLTR1#P,Q^ZS4\0_F!O($[P +MT:;+C3EOF.*#=+:\\?[6/C10N9XJMAH;87'6J8>V`B5I-QGN)UUF9D$N^<#4 +ML9RO8"483OIE,R>F-<`8)S\ZA]=1``$&S3AP$>@J/@,/9?'/-]C +MT`6N(*DD'+AC\I\O[3[^7 +M3/OIC>2.,Y]#LL4MB2M(P3)`ROLN_.68ODVL^D7N(UIF.]T=TU&D7AF:F$UY +M>&?6/?6!<->(&R5/;EKG<2V*TX1"&I.E^9)71O`7;P'/VLE@W/9VZB0WKZ@1 +MEH-Z["@4DD!)GQRY&,4EA)]"(M\O563>%FD8J#[$;DH;01L.(R(JIK$:$0`. +M)VZ=/:)T(/@0A;(OZ*M'PRU:=\)7BR_SE13U\&_-.V5;[P5CXTTCG\V38)?T +M#)!U.5YP]#/H8VO8$=_SLJ@M%MG=-?07'1<%N?+$Z2]"2(=O;<;46[+?<[0, +MHA\LEZE2+=S'53@&:VCQELWT\,K\8O65P+:F0WTMALX_.Z(0S`59:[?EV;_5 +MO\2N]LK(%?:S#D:?1Y>7)(YNT-=AKQR0_802P)8/=$T.I$._`5P:;%; +MPK%'=<'1[Z[#]'S:>(`<#BC&H@*U>UEF[Y3Z=5/N;!L!M$-81@X-0&A=L#I[ +MWB3OI[#69!DDG'AW:*63_73:5I,*_2.'CI(8FM^PK]'/*(9P++R1!#A6&-W3 +M=,\[F>!)-+>#FIP%*I+XE!C>XN?]7ES]/BDY28/45$*6&W*W^JGG&HGL?'^8 +M8/IJ;],\L\CBU'!A1W@U@:?D#8BN9(X=C*)I0^7\%=UHX7AI&F3BBI-9TMP4 +M%ET422,LK*&AI*KUQX@9OONAO;[:.8"`MOU\)OS2`?U]AQC%XE'$HZM4VZ:- +MQB<)&/X$5"^]"U]U7?-#!=;C1.ET2DIR3R!]F@VNJ,0-(BNK+(P1DY0@OSIL +M3/BZ56A^EK]NH7[4<"TP6R! +MOY^&I52F:B=ZV@A/<>JFK3T9L.S&/P/A6N9"!H\?K,:ES +M7S^@G@5.!G?*&SGA?R)X9)`6C^-N7Z_XR=I"/Z8@DAK1E)2W%:*MOLDY`8%^ +MBX[/\/#8Q02+4*Q][)D$7Y*EEHC:"/DO7B6_PAR%QXJ)FH3;:RX&E>F?"-717\A(>GOC<&$3LM +M,01Z3A+4B!65Q%J]A):C7Z]1?Q5SVK)*;5PG2D?B8$'-K]>B'#8H%0.DJQG% +MAA>8=2X)4WV#+P'&24-K7$;2O#HQ+<-$^'O0UI3J>-MILZL02=E&#\0!KNN= +M3M_0-7_UC\A[A+&G$LI)/BL]_PPF+)J,,[2\D.0L)!@2AE^(%+S*S?YAI=DR3XP9=[Q5:)8<*#'19=AON$%4H>/'G:-HY&S@QL@Q&51!YO#][= +MJ?.]KBZ0_E'E73PT0L"Y8WT[=BHK2I+C9VIGRFUYKG?T"@F[YP)X$)*S>0`3 +MR,SET3RP5LR7K)CL0W^5>\3UA-CI82*LFLE+G.J_D5YQV-/J;*9)' +M9,C4L'4J_X9=KV()8!&78']W^NZV!:2CL/B+]E_=:^(CPK\#$I'9 +M>4=YCQBC6WI/[40(OH'2>170][\M##+@&JML(-2G(P3?>.[T^9'Z!^T[%V.( +MRX.H/MY])B=17J=\7;X/46[G/+VHD*O'%)4]77+WF=G%A1C9SM +MYW*7B!`@KP!DUJ,^'K*.!@V'N'D^AMO^M;.EI=3)WJ1IKW"YAFF@3^)P2O.B +MT1V7"MC4&:M +M)(?H\?RSN6XCN=E[NWIKL.7)3\RV*8NIFQW!"*U601VM+S^;/*TX''U&#L!) +M!?,G7XLA3'W'_VFY[R*,!4KU/1VXOYG&6&>@!)_(4)G397OP)F'U=OO,?5$B +MV&VU<5'1H$"$Y./J5@,APZJCO95T\!F_YSRZ6_OIB1R3(?8#>-)'6]T`5.2? +M+(J<0O-]>&,:M$^+MEH2P7+CK-/DNA.]^?&(R2DBP'%7&0J2&^-:XW?!RY_- +MQ^H7DW*-/OBIWM3A,FW-;(3&6SY[@CU@N2VQ1,>_>JB-Z>F14/;5-HEOV-7> +M-N%%B1T2)L]N0-QT#8E]CE7]5'F(PU@\GCX#P3P/C7$33:#O(ECTR\K_ALN/ +M6>$W9(KF1A`=A%&"/=C-N&$XJ$I/[0^:TC9_"%7M#%BK[J3LLKZ>4-3T$P.4/B9BGJ@A;F'L$/?:_B\,%XADD9:'\T#JT^1,(2H2EV6V[@D` +MVD(.-D7Q:_5@M8X$;K'G#4^7&?Q\Q85J38*)ZXK+ZKF;KDG\_^3):O?"_LPQ +M5SW(+PI?RN39ELII1A)?*AY40LZ,0!`+=3DB4/5>&Y4Y"M;*06J'DV^\I1J) +MU(?!I='3KK$``);-WE]B4-D_Z+FLGWJ^(0T0,2;ZJZO>U%^-2IO;87BE##XRG;"2DG%20^$:4_1*29#)'+J,(-V?TRXX[](CV +MC"QR[R%S40+=2>+EKB3VD=)XLQB[%V+S;3O1=_$K**_/THDACX0 +M"]\:!":?*+<\_-4SLV=^."$*7":RN5R!H8S[Z,:VB??^_\TAX[5U8+L82X>' +M(V1C4U"W?.G&-O*H<_Y1-G;FO0Q`8SM&7K>-KY&Z,#U*>.'."Z1_.'0D-1\_ +M+.KC'T9_G+"[X&#?%'%&3GU([8^EQY<3OSRMKN[ML-Y",/=#B4BA58MK';.3 +M_G#%P>[AA9D,2A+Y$JA8EFIN*W'UXR.$3,M=$C00$'Q1=$0P&ZLH_E@`4,9` +M_QR`9L?*I]&X0F`J0LB^,\:V&S\5IESDZG.+(%)`7R-K;C5V2LOUB?+$S0_\ +M-;.&BR+U,LHBR'67:S&6--,+P\4&.^2]P>5N*&G(8XAF[X*SC\E2/Z]<&ZW] +MA``2V@.B?(&`$H*),G>7N;,"DP89$N]X?S:?$\6OG=/"9IE._B&;\JTO!^3 +MN$`CBYI"<8*\-(?UP_]!^>1'SZC$B1'TH[SBT'@I>HDJZZL?#2%\CE*%Q=VS +MM/,"N>\P9"I,Y)6:I[93;Z+H1;SKK3[!XJ,M:YIQR,.'B:*U.N@TF`>18L!4 +MM*D<=[0)71(@4O@]4VZDZ!XZ34/EY^!J,`V_&GZV&:\5H:X0WN>Y3X2R6GY_ +M]8T^SJ,,-?<38TLU[R+#JG\Q"UK.]VF^GH9%)@._+/F$^=WNIJ=AD!I*[,!XE@^;:=R1G#5[+$[(,6%?"S$O['&7*_`=+J&_5X9WGD6YK;N+0+!2% +MB?W\28@F1ENW0<2DR>]$(/WZESAG[-B%.C'"!:X[/WIV@0&%^0&:D$;,2@`^ +MFF.T:B?!W3+UT,OA']\'A?XF>ZB&<(,D,@O7%L=@)O=52Y)RU/ZMFVUD(X-; +M(UK?)_H\%AF'O?^7N2;2_MQV<&::9+1N7^>U+\M2D7UUD&3"S:513NZXS;_` +MFBI2",R4^19MI-I5'J3Q_-DG=`_*XFW6-1<`D?P5+\YD7MQX%$BEF`5428V& +M0.\5/;U8@.KMBX05L'315Z^-F>6'F'L(N<'TN3Y +MC+,^A7/?U(=!Q-U&F=-^5L.B%?=/HYB84[`J[^`\8@!OU4V:G*7T)`)T':]\ +M>:]^NV'I:\WNWT&T&;LG+'*,3Q*J5\70=G";YCEWOWF^0E[@W;]E'6]`%F +MQ1GYT%* +MI>-=@'&BS43C3*IH'"]?%KEI3!:"&#*_QG)4,CXEY]U8/V^I]WTMZ3Q,M;I+ +M^(7$L&M#Y$5\)G$KG9MEV[F@X_+FDDA3I$":)$*DZS?U=LPY.3#E"(S3X\`; +M[;-,\2R/'OJ4:$T^F!->OJ0/O8HYZ:C"5R]_^&-=$^ACHU7CK7J&&?BE2$5X +M\4B91@*J*EH:R*;MB@^C*H;7H^^@0Z=:P+TNU65R;V@[4L#?@<"=>83)CS_>]@2C:3/))XO)T(JP!(*3\2J!:6`F'082QL!Z^=FDR9:A/I9*+?"W*X6\:8+SNM3PAS[$:6MSSOK- +M;MQACGR]R"6$[^OS>;)50-5%J0Q`8.JQ!"!26M^M^:*8;X"FL=%&CN*^H4]T +MJ%MU-U38";FS5/E4!@#BML4=Z3+NP>!8N"RK-'`4W@:TF3&= +MY>:P]!BTXZW?`G#VU+%5"\"7*5Z1*^YL+M$:^2_/>YI>CRWP@T"H +MYVBR63#*3L(SVJIV*8$,.S'EISZ(//7TE!M-U1(+-;A5]-L87-%1:ZT06 +M@+^"7V.+'7>H(4F.S.)=7/>#2JK@S:Z3^F:=1& +MO<;8*/(9%K-V0(YI^Z5-P5_$PR+VR_EG`+GA?-E6*I`6?VQR[Y35V89O3-H7 +MG[W])ZLE9X9_N2'ZY_5U"_KV3AJYT:/%$;FLL=8(%=69)HV'+TFT;5I50Q]) +M^DG-_3@`1&*VW,V=59K_%'XWD7OW]?!E>)H18?"#+T178J\P>\=_$0K,!QQ7 +M#M&GRD+.(N9Y42_76-CA\+""/6WW;%CK?,9&A=.<.G?KK5./#R#,:*(4`R,H +M".AR&7?>>5_A0AUOUV>?AYSS.+7D\+HW]B/)Y>L86*` +M[(0VE$=#?B&5>[,=YX.0]BMO95MG=O5_4VR;Y^CCU_;.#C.5_\>+!&I1G0_W +M@"/$V!LJ'Q+A>]W\Z=D"(B[2601,!P*`9II09'8;N`G0@#:H<80GS%*<'^F? +MG367][94*4RD"G-OCT@*[AP\B38&^/1N!IU>OBH<+`&Q?/K'G/U9Y[@K5@FE +M24;*N&SC,LI0EO)O+QQ>+F*>%YR,?VSP4Z:\DQXLD--]3[;W&_^?33'%O"F8 +M+U/1RVHE%"#CL:OAGG(.($@V^FO-4FM:WY#__4\H8HK&DNJ6.(:E^*CU`UL8 +M*=YPVOX.0]SZ!CWV*XF+I5V\2VVD!9N.8Q:`9RWGWZJER%UGM6G(>V +M:B3_S,7`(O]TBYL)*>-X'A$&S-HN+O*7IG/7`\)>@\DJ>D@M7=KC$C@XLNY7 +MQ9"R0]7Q5A5Y<+`&_/0F<+G"B8WS>C-(Q!S9@K")*95[A+ +MXF)3B5J5DM(0I^#89HH4:U=0AJ":&J>F:N]EY0NKN,7+B]8=,-+4/!UDA;4I +M6CU+:YC:75'NF)C3N2C'+Y8JU?,-%@$I+-YODAJK'VJ3X9*&5!FDRT1\/,BF +M-YVOM=E^43O%ML"&XGT?8'!#@$RQF(C981D1^/BJP(+Q2L`L#:0#3$8EH8RA +MH=/>X9;A8?U^!]#;*+9%#M<.0!H;]*2;HE:J-R_<-\98??77EWB@_YCMP/1L +M-2E$O*_JNMSZM.CUP(TW-J@Q]SFZG-B[1M8T#WWT[9,N&Y8B=[R;F(_5*M,) +M2.S'Y.0[`S#D6F$B0T)NOAF:)@"R,4G,?0*P6=W@'<@=/1&[^(P3;HN+:% +M'F)34B()N7V?5&'GB1Y\,JE$2VJ!0ED=J=YJ(Q^@N*8>:HT*%G^H)7TG=CFQ +M_*+IX$_@N)I\(`LW;AZF*!5?&W_LMTMFG?0H^46U=3(NM\T&[?52HU82W(C[ +MD)LW0[N,+T2'*Z\9`00&>'OS",)U)%XN&H3-I,-Q$\^U$68PG(3SR361JW#F +M[&?*)_1^QS2-T$M65,@3=#EP$2XO"SA3("%GC\EN(IC"7[,AC%2U[7"-2DY8 +M_>-67-5P5V6I2O!AMN#^(*^.QE%DALZ-__E(Z,R&V""$'7I@(FT.02\.%*LZ +MQR>5XO?D((N^"YT/@W>Q%G"\4?>#4G"K>(J_]_XY&".147_K>KM4!HU(`96? +M0*EM`E2?N^(&GL\Y)QY/"XEK48>,REDA7J*'J2=B7C5JL%!:X";="V.=*GU2 +MUVZP9)#XG0YRE$75($,1\4VJD=]@40EG&:#55CY[-]V3#."E&C+G$2"4H)IKKBH'C2'5?=%D1V:%A`@;HFUG0 +M#!RYN6P=&8X-7>QB +MMKN23H"-#@R=#57]@9?>#-%_DZ +M4M\%SPZ"%JKS=X_8$MNP,IGP?C+-Z4=;4*(!:8LK,D#_L-M"=`"[L%EE,N;` +M\YJKCJ(/K%PS=?"5="@]+*H4P4X"9N#$6?+2@X`O,5]G(8565H4E2)Z:$G8_ +MHM_#P75EK<@YV:3_V+J2V6-9>W]]3'09+(JU:]70.A]DIC%\:]'5_+8>U[Y; +MI3=N/V"(3\R!;[4YMH`?'K@R;D,N(T@%L)UY7>8)='R>;4L"NI2\4I0Z>_#` +M"T5R]N&R4-0BX-1@",Y;>:\7;'2M),K!\3%;K +M`O>W\PSP%V#"V/$QW]L$-@.\'1-[E:^?`W2`/W?"HUL"15;@X3'/]%O:@,9H +ME(H,6S=!%V"V@'.HQIY";Y!:9\;U-"0B8MC(H/Y;6*:MV)4GQQF*D6H3^!RC +M[>RF5[-]H>QTR/GMOM:_:J(;&R@@[_EVS(T)VL+0>ZW,CNVFCN=,L=,;F=B" +M$>QNCL$\O_85=FOIVX1VHPA[6H[V_+(2,0V)"1^8''!W73L-ENVA2 +M]00N,5O37RR6"@,V.:919HLYJ;'[=^A"'/ZOCPCC].19`7"O6`Z[2S^J;]0< +M!QE0L(^R5K^=B/C8BETY;S?D`LP86">5HS((V3O*?L1KL6*I#(;03`WO(49O +MJSD<'0`K?A>KUG#QA#CJ`YK,[I:GQR8@#^GRN22\OV^V`PXRKSBS*ZZV@-B7 +M;,ZM;$"B1'`JF'C8)E5$LDB%\$0B#B_ZI7/T<@L.8(UAT`P#3=6(0#G5RBOZ'@-M)QCII(R65'#<(<5&Z +M*;!F]!-9";@;U.2@[(KI_;_2P8MLE+\"1QHS-0-"II7QFTOQ1W4C7ZM8[5_S +M^V<:+LUX=?0M:#R.7_NS2CYGCP7LMI7.Q/6Q9U!V$!VUO4Y'R5RPFQF7DN3E +MD?7977164-C8H$+Y0L`TQ-/:>Y&"E0X%U\4$N&5,%6&;-H4IG +MBG)+3+"%<<@R4IV&[8T`O4W085JN-2;K-#G,`'?WY[-R.KK0"M@6Q2&*]W=H +MR/\FRIDT=CVIO^'MK>I+W^*K@P[-<=-&K"@K1337OS?)%1`\ZW#W].AA;94. +MSP%S-IT[JMGA,,5W/>&EU>.5S719G-YF;N9J1CIY>U-@!5+Z,@/?CWFCP%$H +M5@_[E!^QS71O9,C.U/SN%S"=,,ZSO +MMX6Q!;Q&MX"0^OA!H4?P96C1NHT#^L/0$WJ\JCP&,@^RY'DM(!^!(@?;JA-^ +ML52Q,\)`)'\ZLI^N;KBN-[6PJ<(E"/0U\[G4KT% +M'",:^"0)Q^[LO7$T0SE)[,1BC)EWPMC +MHI9NO^'S;.=TX1(D2MAB:[*%]`0^F1^#V'-6I*>827N$;?6[!QP@UD]Q''UP +MA\:-!)QS@44]Z$R8FAC;W1/#W^)(+).2DI/50F7EL-T,"JOM('):("P!S_#D +M.LHXKJJ.=C_\/HP&:5.ES=!5Y3=5ADTISB@"&QR[%#X",;2PBDS4383.2>62 +M&K1F&=,G"<_@KZ/;1&0N8C$VQC.*KB[S)R,2344F%GG5D/%BB0.;%*IYI8>$ +M`>1%7XJZIH5Y'Z*O=<2E$$@XGKC1ITNWW*B+2FQ.DPD7W48T.;LUF[9JS8G3 +MH@C"*Y,D,#'#Q`OUN#T%F)B?=8KY;Q%";4Y@N6(B/])*#`;J\T&\A,1B`?1^ +MT[0_F&]^WX"%P5;<>Y$7%WN]R&E=$OA^-IRXC((`,:8I_6^O3!UE4B!.V +MH9C.2O*(9+-3+6*#]A5'V1`)1UIYWY#`?`LXO>=9)%W1:^M4KJQW-A<3>#=1 +M>M7JCFHN#@ATO4S6<57GT^3:FN_YV>ELUBFYL3;SYJR_'_7J>3K\AS9MC)J+^0UH]TB?784:MYI,YDTC/]:)N9\1Y,^@7$24Z:2X +MEVQ'U%J44(Y?XVJ2P0#@X\$&_@4[5O^DO4KV$?<6HB.<$3LWBZ"GD;8!KUW +M13F/+1IH)B5OHPV4(+3`@JLRA,\Z8G@5.DOTD&)N'I,?6PON^::.QZ!;H2&E +MV]GK2^^7'_97C\VCL,MQ35(*^4:5C2%Z:^HN3@PLJW%>T>NWO[!(.QELB5]! +MXX'Q'L+!,S*O+Y@='\T1NTR!<['BV*4MN/KB$RTN"*<1W:D2."]2LYJ:$IA! +M#EVE3*Q(T&YBK?LTMP!J/1=8R5/TFP#8-E,Y_RT#RL!NL+_FG8?#81OC0M50 +M)H.K=J\II7GHN(19W1)W*Z7IW/1T_H:,EN9:/8)[1J=K&A?5.C&`HXA.41:< +M61.IN5]2),0)..7$[M;)JJ@SLOJ&NPA'KI\*]1D5+*Y-225:9MB7O<56X3C409'3)=4Z;!N$@+1,X;(<@BJUF, +MN2'`A'\(U42#PTW-8I'0PYY4'3W/[H/3;?^)2X2O-M-/7*A415(X2G6"0@Q3 +M+%$.=_R;T(^=#&^FRN[?:)$!5BQ<,[CF2SPFX$;P>,-P!B9D^,T$D#@8UW,5 +M"_DYYQ,.>ZQ:I9@]AY7RX(J-?%"+K)B,M6K#2AR@#T./_%PJ/]U(\H;JA16G +MYM:'QBC#`Q%(N"[8ATG9=LT/V$(.S%2(5V5'BU[HUSA0*JEY,+'!I+1?B%@& +M?ZI`F%/#\_^:=V"W"F=*UNS"[9CU/L3VYT1._LMG&X$``_O_XB&#C-3J#.12 +M[.,AUT<$*^SPM..1'HAM%B7`)7M&+[WSAGQ[;+"CM4:K&OJQV1E5P]30@WX(6?(6/ +M?"H/-S+-O+`G%7`A)(+*S8$9+VG5FQ#%O0=JZU51W<*2"42WH&LISQ-)VX_D +M*X6N]8JM\$8-2RM!>>(]L\=8/1.!LV^38"'V@SIL/[#M,8-_<91$JL@MY>4: +MZ3O6R?PY$FW\EM@B?43K@-VI^_LDV?Y?]K_5#1O!M(H-,@X]=GN*1%I'`V.A +M%#LE36D14K()PH#I,%-2_N*>:E@>G3\B/F+E#$+9S]G%4+I.*[(INRK&Z5I4?S>U:3L"*H:78_&@[O):(='-=-S>34EQX%C%4FOG +M35,6MIS5,K+LRR@72MSOSAM6!):$8S]J&S$.=NO\'BB:(%?;R"]))\R(N;>B +M)V!*W&VN$Z+3ICP]3Z>2J0^_#?/^;Z:M3D@5O=2S&,"2(84/%TP*<-+H"3I5 +M^2@O_L!Y.4L<4&0GPGD*=TJ1T,=5H/^)_18G3M=XC\9 +M\AT#._O)W(%\V6+G,N(0W +M#V>=()#800SHWD&XF+EQCU#I2',[6JY<[E5@>MQL/&D-BW%#Z4Y[-R.+@#\V +MD?'Z\^0M38NT&/,HGP6TD]UP>Z&@S'ZIZX[X#N!L#?XV/LYSA3QL)ZZ(8%R8 +M-U6'U"QO4IB(6\J5T3O/SC@:"O/2B,I1AZDHQ)[PSZ*5<6]](;VNJ-)UE8[N +M>M`Q6]'G.1HAD9M$0G^>-]<2!W';;3@H(0A,!E.84$P(VHJ8&.-D9DQ2%B@O +M<%(?>%AZ[,%UTE;$!S*2W83H:8;RV4)XJDO5H!EL]:$!^< +M:O'A?>YIYJ@J]CWAO@^(CN]0M+V\\CGV.@OVS5W50)$"NR:2"A +M1H>@U//^?_FQ"IY]UNJ+GH<++R/:64M&KR+G6FIUVUK9E]*4M3"ARNU?:8]3L/65<<(^ +MB!H0^JZ\OP6PIPU_%HAY718N`*C7SNN3L:+/[*EVY?L^@825U9D<+JH%GGG! +M_V1>Y=(,:B=9(O2L=JF!$^5*FTL"^B!/Q'_JL4#.%F?D]];"+Q'7]%&5J+/MW-%/7M5H_!OV@J1]8]84\S#+L4.C +M%)MS,`$]4GKX)TXV`>U$\S+-58#B#.[GD2W4L&4>!\B5JS.P`;U%,4N2RSA! +M>-RNLY)+M`6#`EB1=?_&$YDH+L8:3TM[&DG%?DVX_ARF-_SKKR!=/!G6A4,# +M/#L4$FLS>M&)**+:J,\NU@&J*Q>SES0F&$%1'F8%,91ALXY3Z'A`&\XCK6/3 +MLO,TQW"SH=`!V"P,@Z'S_WN>-<4N5?(93F0W!P.(J4+='XA)E]4K^BJTK01E8>I%^:+E;./W>H;%6D'#T">"!X5``HJU8/E12*6L(6.O +MN#@H<8O59:WASH/2UC%-%8F'CO8J%'"VU>)$Y<0?4H['QJ!G^AX\L_;WUD.& +M'5T_G=2(8@@L!7P2!.JA)IP,`N*V)MAY]KT'BR\(P/N!:)5R;$?7@P. +MR,L`^3(2^CO0>B<=W/UL22NH.2;6Q_"4\W#BH1+?Q(WL#Z%>I^H4Y&5WM7^B +MBUA[$I@=WYX?>RQ.8D%E2WRTDN/6[/J"-AFZWWR\,E8^<5S;7!B]GYPMTA71 +MF@Z>B#5XQI3_X>\KN<_U!%ST$[P22QW99X(ZI"6"^G:<1F`6-C?R@:S0IM[R +MV&.URXRI7#4P>CR&N1"8&(V$+_BT(Q`2`E.?WNHI;UH4I?F1\1B+#[ +M.S,-AG,UBK!O&%2FR5+.6RLYNZ?5_#(R=\FA%\+)O[/YRH>A)`SX5&)DYP)[ +M.((?M?NTE_!O\<*BL(`\C'#[I,R]X>LD9LH=>O:CB(S6%[S1%FFX+:SSAVFG +MPM57K$&S!`4T=P_L2@EIHYH4:SF)Z$9*JBRT/UD3R25TE'PHA*53T2@#%WGRP@:D +MGY.S2_,S4;E?X,WS,B8\G[E%,&\*6 +M@U`[N6!J')8$9<'RR!WWH26Z@T;W0<>CXA\0DN5UU'D6^@N'E5JP!9R.]#C7 +MKMN-`(7(?>M&UI9DB6UDS?R#^7;)G5])W-8TO;X$EP--$= +M0)<,PKBJH&\BV&-V?9ZX>=$^6Y"UAKTO!2>X&Q'\ZR]-U[N;5=7:65R,-I,J +M5)L/\S_SV,(6^?B +M"B2D%LA`SRDIU?$JZ6R!O%Y;68+L%#AF<[MR\NVQV]D<$#[!NJC,*\4B7J1. +M*&B-'%<;'I:)TM"YIS$0DMWY/2C&B.G`49Q#R=TQY5]G_>SV'C3':9(6#XF< +M8=1(G.C60_Z$B&\_9[FFK(GY+Y:KM)-=[#Z!_(LS782>%A%QYU:^CNI-(-/M +M0;+#'ZZ8KXW=?`T_%V2U]W?])P#)2B03OT8@W6H+:#P-J7*=L1FFR/AN1G;61P#6J&X&,% +M$6S=14C<38_)@_'BH:E^FY#(0%\XY-?I)L84[JVK26UT)>VP2R#Z3Z1E9Z@4 +M#:FOA:^-GMYT<]LW]\QY+Z`M) +M]3RN0,`XS>'XO-"QAR[VVA/N;I1KME9:G$#F4I.B4`/=`!@G2&`N:#,,!AW# +M],;!=5A0$C6+C9$M%"D6\*HB7(Q"N(6R3= +MD96R\!PE<+9?]&V"._$'6*_#W(H(^)QP6".)>`-E^>TI +MPU6CJIY@;A\G&U\:ENPIKH(UXS3#RY8TTQ#!4B?=8\4W)&P-&"J,Z<3&-P!S +M-_[<0;HQIC#@(^4#5]`0M%J8X862K]89B-MV4IP;Z[^Q'>;Y5!!3HVGQ$6Y% +M,A1%=&(G:SFNJ%!9A-KM0GWY4]'6@EOOB#Q\C@$QL`XO.?4G".9>P:,CNMDZY*,'.X&,>)#B&IR2ILPYR'()>#1OA9WLC+XJ=, +M7_')PZZ"S5(#+YT&87K/^_<4;\0K3+[VV_P^V( +M-RO>D^X)3%0GZW$J^!5($DE(X=1:.LP-\9QU8HQ..EB`L&\>ZE/_PG0+A!GC +M^#]!,,$YU6RU_3*+'`/B%F.9[<]Z5ER0]CL(T&W1$TI>5WP<6[O%;8TX[%/J +M>R'Q1,=@Z/F$'N3\.^Y!DE/7`=%:@>E.4V";(3#X^&?8 +M@1*\IR%^`E##P;!4QL!G\8OFFO?%AJ]HXA0[8.<);4R]=59YHDS$L!]C;S!I +MQ[],A![XM,^UCS5)S,L:@\"=W;\EU0L]0*13"7Z*'&_OJRU5'`Y=158"]X2\ +MB45;'[Y<4'J)UL^5V3B[!="!G6+QTQE+E=_@&4*G98+&*J^>&"DJIV!&&&$3 +MT^S]95"3!=PN[>9A:*/PO5ZUE\:D=1$/]_+[8!K\VNZ[P7:#1QG3,]/`[RX9)).A\*[AK3*61-%%-?_;=>G`ISF3 +M^+8D!LQ9.$L\4'.<\2ZL6YCU2ME$BP*VM3YZQRCDN/`E*?Y2ON_I?LO_LXQ_]Y>`^Y>!2UMVA'" +M+M7)?9;.A%CQNL-+4::&_UJQ*P"PPW:>)I5*8)7^>6(\]!Q"^9YCE>>`9OG8 +M)X5E9'++N.-A41X$;]R98SEXT&=@/5 +M$W%[DJ21-IBD^"CQ4330W8#JJ,Q89!0A+ +M`07]Z6.D_.Z7VEF0(I0:0AO:-YP)J>S[OA=NP'32BYK"*AL=ZA=+"@3RO!KN +M^S2[`5$;.VMYT\AZ%*4GEH%UIW,KB:S;#\/Z1@@B2;M?IKHN+]E%?F:3A\EB +M9#ZV4W*B5TK.=B*V7;>]N\FH\\].P3-W[8=3JY3NCX0BZDA[<)A7I5MY]7XI +MYR7V_=.M5\9/<9?]ND!REXEH"YH/3*@AWAR5 +M:R@\PI^;.K+V_!<1#UPKT/L?ISC,)^T3"(A(PKFL-89Z\,4E/9J,<5RR_88U +ML8RV2_J%\11&JOJM6]SR(=U"+H)KF3/!>;86D"*D+7-_C[L_,JU>D"VY!^GX +MBFF!S6U6&^(G&![FH"$743K1(0C5%X).%64QWBJX5>GH(:_.B&2PHL[*_47W +M^"Q^Q%EZ=>Q8+RH(5&):%QS#`JKWKRMVU,J:*HSC8[X+,O:]N6H3(*&[$@Y5 +MOGK$18U[@NV7HH/;XR2_:KOOOJ_X,'W1$'9;Y`J:L?[6AMCI(^7Y4_X8*)4E +MI?-KB.V)3J*QXUB5?]>6K`=]G[!9[D>E]NS6KY?L$'=,0\`NIK<@%ONXAA/K6J&60??AX`[_:)D9X_6CH6+O3*1-M8MNE=^1*=UQF +M73]I:3M.B2OV`WM]BSWLKS/!K;O/L';@->):,E$="8U^3,06(@[@[_L2-QN!;BI9UAS3VSEB-/353HA@^;\Y0 +M)5+,#%*P-S^R*>VCP1\'-X=FZ>%:XWDR5**".81_PV/X=AP_>A)N +M$VJI@1S2#);$U6NES.>S:+*$Y;B<9*=VWM#-#,<*(L>?![ +M9#NQ-]:L%B"P,X^H)V>1;RKU\!994*3&`)JTL(*\GL`0_HL+$+A&-[K-%!1C +M+8,>&EXPGW?;^U5?QYM4?R';U![72EFLK;C/W=8'+RHWPY@!%,%J#=VEC/N= +MP*]'P_#'O$Y +M#TL<;8YZF*FDO!EC;(9`]^M6UF*(#IC@87EU\*KAW$OV?B'#O>T6C\7.[LV0 +MFG\3H.@ZAZ_=Y<'AW$-..D`G$L] +M26O__G3',:MQD+XWXI(?0=#8*0U/LX.-)$<^#=RV')0AF(;+[,F^")E#['G4 +MI1E-.6,P66^<(#)B/#8R_M)!-YM\:3OQQP^=1\A!BWHK"P;235?(ON6\WD9] +ML](+EK*36H356X*K@9;:TTP4W<74"^QDAIUN$ER/?D>E]$H[F=QUDV$Z2*5V +MS#ROY,Y`_X$E=\^@U/.!][1.CY$<35"Z#IYM,OJ+(=:-<-+06SS6*":(2Y_) +MS\_W=L.V8J(7=<\X95Y?3>+L`L+"K.KV^1&KA5)F*7-^[//D5<*PE2P4A+1$ +M7C!Z7G:T=+6-<[9,CW85OMSB/%ZY/3!DRBV0O1;_\+(@JA`);Y_#YV29<_21 +MI=$^1WQ.&K\ZN!D&:UD"YHT>NNN%XEDQ>J6]H]TURS66IOQ.Q^4AE!MVZ?XA +MV*!/C6[&RA#->5+&^U\ +M@7!:Q5:@PFY566,-^\/!5N`2;)[FXE*`ZMS3BC$,1;553\MTK][$DULF +MUOO`D\!Y$0#:9ST7D;Y +M\]I^1KD:O\3Y?K%2?I&R",F5"]/904FON2NFRSV9_)>YS<`Z!UYM`/OB6H!M +M0X.+6-#Q8`;$6]&M,Q40S0!XVN6RMP!%V4S/T+\=(&=*#D>OP2EO/H42T(>O +M2!WL86?9E\R13R_0CC(*LA*.L20,P5E:229_8G<&+'%DQKQCT82NXFY0*6FI +M6*0_9;I)GE6\4RF''\F2I0!A&=VF_VF*C&CA#,6X\T\RW>M>-X)D8FG``RWA +M86:C2RI)M@.LSD,[C:D1[MHQRJQ$\YM61!KN%!K)7&3^:,NQCGN(OE3#/0T&'E5S_5-W]!/4!^3'"0K'O)*JT7.@^=D?/RIL?7W5: +MRE+'YNC=3S5'`B24(9B$O+/D.V.Y+JY,T;8M^]<7$N4!_,JBJ%5$53(<6]T3 +MB!X:1ANU&)7;SIC[X!%_L^-WGP(7W@,5S3)< +MXP!5')5ZG/J8&5&LOW+"8]<@6;7M!049WWI^14>UK'M3R(*PF<;/20-0(8#K +M)M1I`EF3*Z^-/_5W3C4Z7R%?TC7@U>GA8@Q$QG#P=A1_A`-\TKWCOT) +M-*9MK%%[1^>$--_DI8^ERF]4?"?(N0S42WT3#[;\]NE6$4CNCM"\C' +MI#JM(0]DVVE^Q[`MA17:'S2N"R0F#1RH-/?JC8!S3_/-C1=V;X1)YO[BEQ=-X>EC+OP(59I6YEX8N2:Z +M#6['@AS<;>I:?VDH9O/^9?EM&ISI]F'D7O^35)YC-5:'=0Y0/W@44R3TS1F< +M-&)9B;0^10N((,ZY^"39$*Q(,]-VP6F;[KJOW\C^UGE9CD<#BM[G+[[_?&>4 +MMCWAAX+(U)FD*]UKW@K#K@'\<=.";M?Q;M/=']AIMK9$G>1J@_0\$(5]FG>G +M"(H8WBM2G.D]<$?OY"S_%@S^R]F0BP5"*K7[$4\?PH:%./#Y$U&0YOW!]!W. +MRE[Q?5&57I*Q?J]7F^S[64N1OVE,MQL:Z/%FN2X\5[&VM +MA$U?XZ'OD+Y"`_2HQ"A1I2("=0/$Y"5@XC/E`0EI(Q/I$!]A9I)N/KQR!:^4 +MG_^WZ]O1_%&5W'$,HN$\LV[B&RD:]5L[[I+V1!3N#!*-*(-GIB[N0J)WLMUK +M#WAV-LTVTS#YI,60 +MN%OPF;4?X8#_,JG5J*M++?.MAQ]&:_""#?')'E0'=APPUYP;"G,*1VNG8A0A +MFDPDE4/\JIVT:2&?(HJ_U&)O>/.G]$D\O'\G#2JFJ@8;X3RVT.HPGN'5W,8E +M*C[ST+_!X7U2XH%)(65M];:=LW%!`]=*BHNVJ/>/O/'4\T05B]"UDN8GE_43 +M3#'.X'7'&;!V?J:H<7K(XM(;^3ZD+5#VD,.=;D!9MO(&WE)5Q5V3#C&+>-G2 +MW]W+/&;%X)9A-"RR-D%.#%2_ON-+OJ6ZF>K+['T`G`I,=8BUF8/V`T7'V?0Q +M%+(/&0)7,W!$J[1=C-/[E'$E^J"@7OY9TX]'5?\4+F+1:NT^\#A:#&@BF1D$ +M>8\/.(]^/W8*KJ0M-2G:#>ZLHL%3L("")*9#T+=-<1H`M*E5[1.AACBRT57? +M8G'3;=5O)TJ;QX#"/1[Z_]0TU5#;N8P%*YL.W7^T]8.MDXDZ0W\R=^4L(Q&W +MM3F$0,)&)F][;Z!7W>P4/H&@>+\5U?;>$_5:<9`K?+32,1F7C?!AS:.CD5@+ +M@2@J5LC*Q#[K5S*/`F&!2TAL(X4+Q"V?[E(-5CE"HI,@'J%.>')8W9K2V>^W +M1C>\E^%G5VB+!.O9.L^3EI%!"@D1]?K>`T;$K3T:J@C)U4U@CAN6+LB7]OCQ +M\0"8>KE/()%FV\0];:Y$R<0#O34A>9SG.71&%F#3RY$N:6P +M"7]Q2"1EC5%].YGJA:=&3H-FR@\V+_R`&!5A\N=#)HG,#X90J+=JO +M&Z?[S@GJI-B0E,O+3L&-$YQ5C=Z%'K_R7RRPU*7 +M2NG-@?PUF:?$:9+;(^KW]ZE8:1,N[EXW^(7H^Z1]`7/)(\])CB2K+6I&D9W. +MUZW`HGHT!#8.F\%)`($[(3/V^;R\&0CV11;=A3$?+E>,[1<[JN!H8BHZK+OG +M8%T]CJ]FA$;@/%_-"2%0:1+_78>/K>G[;GS:)%0T,3='F1B+]1;Y1:^YD'J] +MZMNN'HL!D>Q8SU@`%;?Z)L?P^&(V!3P_L&>N0T@S`]8X+S5W@2:KJ$IW'!,M +M'=/DU1:CQ'_BW5#!!B?GZ`\]0F?S!;X_QE!F4T6C[Z?JJ6+ULQFCJV6EHR>Z +MI7HNN#KB>%38H0HG0(N3(SYO'-W6AT_VO2H1#\"1 +M,).ARX\8O1S]5.L\\50[CJSE(?O2&QH*+DPP9=YM`UK[@2]HN28+6C,&YN+] +ME,H0OTL')?U>`Z@#E3`N/X>&*63\\H2]BEJ=8PZJ&+V<4%Q+.R-Y\*)F@-QD +MV;OFH0;*EM%)0+9WRS:UR\J]R[*W7.A8_B9[*J3_()DB,E@B:YW8\EL=&7H, +M>-F!*,$OF<`;'8E-3UXH,)H/I[])2A;W^/DHMQ\:,8),>0;@CDP[3T0_GBXO +M8(4]ZWZ>T/TL;)VB(\PI]!158EA*T*"'JHV`0/W.8@OOS?SY@EH\]0M`HSD< +M^I*%SX["-\^V5)9!/E&DC+BG5QQBS(';O_9H+8:U./4MH@=57*1@>9OWW[BL +MF[8DK;G"DR+4L.W$,XLH.KA6GU$Y;L(7.X/(T=X5R646#2_>>U4V-`(1P[H, +M`O>_FJ5$/S;V\+!;*L$TP(CV<#4X@P=](^W@Z6@Z]@3XX'*#7SCD^FU]L:.L +M.$%>R2_6S77H&8MQ>UI2T>C&+WD$_0R;>NHI]",M&+BR@KCE-Q];=M"]1ZME +M@O0R2EF_VCGE&M)%+.$+B6K$=(#O1N<[@5M)>D9']>L%+,Q53,UU1+T+M++6 +M1O&"NMBZ?,J]H$3';J$B]+1;-9`)NG6>L$"KE.XPK`#V^P+Q.%_,X]#"JN'6 +ME:*7WDW/S#F4A&KI5N"K#J'!_CB-YQZ%/=H/QM$$YV"[(/,59[DIQB;YKG9E +M/ZM)9#>1Z`X;!*IB5L@*T::YG7VODQ[R/N27/:">3S')AK@\$B?A&S`!E8ML'*DU,Q6Y%=_3"7HU&2@O"Y +MK>+"HPDE`.53"!X#NZU@J$1?-3HQK]DAPU"=J@3I6J4M,N56A$BJ\E,M'AT# +M"I16)3J4/JAM#LI63E",5G!!PH-@&NWL^WWZ5B=]T',60#4ESNSS0OV7.Q9, +MYVJD`GJ&S@5U-5SS^IRQ>K_C*2'?-;,Z`,L@"Y[ +M4)A>N5L(_=-\JME_&*B>RP]@ZN,,7$@ZR?0>:68214.9TQGC10-27HH3SB"A +M7A2')&AS#G'ID/%7]/2EQRAU0Y+02;ALL(?$:^%_LX#\IY<'PE6B!GJY!G3X +MI>\ZT3(3IZ/[6R9\*4GBF%M_?"091YVZR!E?C>HUHN$SST2%2M)=ML'&7G]3 +M"8F;+_0(^Q7*X2E4MQ/.4=CX&#L5=W==OBAHC2(;>-9L63(9Q(N](+KN]5[X +MLO-,E.7V:S7OVXDW0P4<^MZX)K\?_:9!&/J<[A".+>;9NFYF.HD7&GO,S%_I +M>;PE37(UM<8&4RH>D)[+498\T;\BX9R<1^Z=%Q3[K9-VL_WKR?ONN)0H5,FU +M?9^P!TLQ%$I*W+T/0$6VT44K'P+(.IR'H%#P'&-]1P8>6O+`%(6T?5#SFM7# +M=V!66:,Y/@1'?1+WYJ,W%%:N\Q93)T35W)PNOW6N);HPRL"'#X:$@3?^*S8: +M**Z)W7[7LP+HE05NL]!.[4J18^,:`D%%3>S8?7'GTD([V+Z&+0SJ7,OZW*FV +M.#!]$=$#)$SQ6[Z=18F8_9):Y^>P&I-NW'/GX1"7GTNR7>]/`7D;53Q"'FUI +MBM'LWXW"49W&2E.J<5FC$;:1IHG%!)X^Y +M5'`+>#[Z]&^R7+@?RDF,HNF_0#1NL]!(Q_FQ6H5RC3V$7S-S1VS-MV37CHD8L,1J7OU$=T;!K6YUL4'# +MHZ'4+3+0BQ57!QHD?B[=_&H92B%C-@^F?6[\\%]J@/3V4;79\C"-#VY@\VK% +MSWU?;8`405L/X,AN?64$1?[$!)\S2N`2<[V +MRCXN\"E$585(V/Y8PLJR@;8;V58=+\[XJ1<.&A:#U@?9)$=U@X"F=:SI4ER1 +M8X=>,9.TS:*,YK]'S7[1!W(GK%C>Z\#A2?",2!(V[>.3H:P3A&M6(MNCF0!, +MQ8LE6?UQN-NI1`U5DP;67`6/3;;*K1\?.(D?#=Q5\J*^D)A00=6*>"73&.%# +M-[B65UNG!C2^^I"6?`Z\GQ/B.!O2V3R)X@IO1@0V9I>+!I#'4_5N#<%.;KA`>J!D0]D.?AVX9L=*5TX-E)5 +MB("[?P=G1D\;IMHG7'F^K_CX&0].*;?1"`Q>]4S_GKA_'B]]A)@IE0D8,<;( +MW;D;_K+!=6`NU!;2\,E3]!;7'16&[UF/%A[299TXVNR,;>RDX0LHQV**._^[ +M(U?Z1EI6L>$1]+UI+2HQN-OB:Y80][IJ1NVTGL:USEGMS8Q%9=(5=V7"1JFV +MP_T;^'.O%0E4=QH2^:QOEF.X1SI+"Y_BFKZ(-4$.I2)\XVD=YN&1!MG95UU; +M_(K*N&BHYYAIK+@CK(W@_AS@,B)@6@2##?[1I<3EXG,T->D@UK^,Y7LY#EZ9 +M^ZSF0.GXG'C%QI]-.:"?]-]35II['D15]=3VK2C,'XWL=.P1//-;"Y;JDWWA +M(#@DQ7^(^Z_SB/17+[_4U.RI-O4LUDOW^$B".=F],%A70+.!Y[KWAU7N_52- +M(AH5Y1((_$1,<1%_W%41"M2[8]@#"\_E^2A!T)(-OD0KM?QF0!..&J__7^)' +MU9Z=^6WZ3CH[F8?W,^-79)IDLM.ZHQPM'Z>Z +M3*HQ)&..C#YL%`$W=HYO$B)G%R.4*J(@@80R;KJ])[QA;>HN$RC+%@ORUCF` +MSHS:WW`3F13`]B;X$:_X#:&D$=OO$+%=Q1YM_1K/5"5X'0_`GK/Y%N;^MVM6 +M_MS2<*%[$=WP)5"PJ93!(Q-ATZB85R95C`(E:U*#^4MV:3$#C_@%.C=G]R-G +M7AMEO4G$P83A]DCC6QO.`$BZ\--X['P6H)F&U%J1\4H8U8OU74A[BN)SR8"J +MZM=PX+5_]&Y'&2[A4H)1^W[M%@QL=?34^[0>:(;VVI1YHF6Z +M)7(PVN.#VJGDZ3^W'(0I'@IU7V/WWG73Q@6"*H#E+@1I>],AO,#N:&SC'/SX +M>X4C1_+'5JII)+JB@Q$*YU6B)_`W<^AIZQ><\)\_2URX"VV4OD-!+&3$E+W+ +M'6\#%8YUYB%^UO8B(X`:@W^//P)-JYJ^?4.+5'XN#$FXNSL45?#P.'F$=.-J +M%B)[1!?$^@XR'Y?FMOUO\4BX69QX#7!>H*R\V@)AOJSI,85#(4;\38Y\!E77 +M]K)_/YCO8Y"4TIWP=>F1S/6^#OKN=[J;-UJRCH""I$T +M]@@T(QM=XK9/WB"KI+[`IS(WA1_!MO#BT%(V1#<3G/&6C-(`>?.W80!P?M^87>KBI%/`V8?"3Y/>7S060 +MBCI'?$I=$XU3/L7[^J\8BU,\I.B2KC7G4. +MD.HS^8?K+_ZLY)I<5+X(Y1=@36;+5+>Y0BI46>\6!"S1V=$7@F*AF!F553DI +MWJ<(&_>G0/2UOQ+#:*"J[Y8SF+3!S;)%:^`>_M5`WG9;O:ZNE/$:VH-(D6M* +MF_*?']6!NT?XC-4/%'&^I(236JA'`K?'*3^/Y^QC#&@ +M-A,^HAM[;W/39JV&2'+-D>I?Y4KIX[GV'JJ/I@&*14[GDTFD`O- +M&JER89X9Y!$2!"#0#&YJ.9L=>>&P[]4"@^ +MK((Z0TJG()Q,@)7?Y8]S>,`;E`I;IZ>\1^9LK0"G)E1H@9L)]-3;!EY/#_UL +M!)IR7IFRLKL$#GQ51AKG&]_QO!U'4NPR_%T_V)1O`G0-4]F%313BGZOA/-). +M/"&WU$L\;^"Z4)9''HPBY,T1_XQ.[3>8J@+P+V%,MK1X&`,?$O_^4MDEQ[`) +MI"'(3)>H9O%0,5H[UM6ZUOD/#U?6R:5EZ)1C95F,QDN6N83FOOD89+7+*B66]8\^P9;@*.$KPPEWNPTD*E?L&^+="`^1^1#-,=*%2'/\BB +MC]H1+(=A)8Y_Z(V+-UU#<,)Y]5F*4`H(07^N4V%SPIL[JR4M]6+FN3)?\<[3 +MU57+L0JT6BI!0]E&&5S(N^GE"8KHCH:FEB#R-)Y2[VXNT#QZ*)[^U&^UKLGL +M=]#FY2I1D!<'PQRZF^@@1T]6=YEA1I$"ZTAYSU+D0I;1.F+W%NI(G,0O +M\(B!_('LX7RZ=&/M#D=KUJV2XMZO*2Z.[V=4+V03*:3D3@M9N;'M^6%1#L&` +MTVW@D->5:M()2DE'J/A46SJ+WWS/5H#9P8@+`B,51FU6L%5$4-\V,&-:MEOE +M.&`\[UQN=?A;:E7Q2;VU^-EJR9>I#$#[E##RB)AC-K=*\`>$.GT%_?++6\HC +MHKRTWA'9$[E"'"Q[]%@;^J>I%KHES]?1\,6-E/9X`NB,47,8(K_L1,+3K+:C +MW:F8I"%?7`S!_="?&4F1LRJ@W*1B5$Y,C>W/<`IM8,?229>J;.[335AL6E_K +MX/ZLGF7IP>!/M;@3M&$[(:)VI_6CYH5/WLO:,8:WHMO-R79D5+\X,(V$*B@6 +M:0K,KZ[7EI2/PNQ:6+Z02Y +M&W?@P;\[IS^ +M7HQ(O8'A-I-T^RR_DA7F8T87PH1M23!CYK:KZ5CL'"(NBKRF]'E$94OUIBE' +M[^L/EBI,5"VS]`5N))Y%XJ:RJ\KW'W3ILE$:&MA/U_WF%'%%+Z^C9SW.'8,' +MEIRU+RC07+OP&MFETCP1\]^??#M(M@.?$U5.'C`IW:`A\I8A>+]JW:C8"\H1CL#(/5&5%EPA#,83#Q'.%Q;+9+ +MDO4EG`;AR8B96TE,1TAD@&HZ0J[?]Y1RV-A`:-,UT#972-WC#.D)SRYJDPB* +MB*,A47L2!_EK^U%"^@GD>_7^3F/IMF$UQQ0:*?>0;*H4MQ9>7$K"RITJI<4F +MUU8*$/`I#;*R.'(2#R^]74%K@1V(FJC^3!OZN6%N\XP%NZF>T(F3!$.FPS"E +M+1F)4(.)I/&4;))/)3Y(@_H!_.()'6FVET2$;(G59SJDZAI8W3;K=[?I-BE^5<840B@ZX!)3U?A]Q+YS&-*QF5;2%YX6Y.K/GZPJ5)Z' +MO+ENY^!CO!JK;(L9B[N59^88!=NP8[JBO"=;!5+=OT+">5=8(C1UI1X$CRNK +M30:WLE>E.`)GH#38,.SQ!>MN1A6ACQ6'7,*07O/-14N.:4=&?2^[)8IV^G[[ +M^!U[0L/@(=,]/>WM,<$^F305DX5AO0M$*,N;T]]ID!.4!9+1".JL\H+?>W%SJIG07I1 +MZD=?`)+$ILRAZO&LII%UB_[O65O5+<*#-ZV'/76DL?CYQ.F%J`76>Z!5)J>Q +M'W(_@X$;;\;PX==EE>FWEE9/66BDZ8@O/Y>O'R-`@7:S90 +M%,UYRD0B]P8B[4V[R1'2`MZT7@8Z[G3__(!X?W2@D$(`/W8``&I_```#35DU +M-&N7!S\=-1@`I($``$QI8F%R8VAI=F5!9&1I;F=497-T+F]D=,#,:Y<'/VN7 +M!S\0'4S93-$5U!$9E@-JRUB!JTU@=K$;5MK";6$FFDU@YJ\^QV:KDU,RV]S- +M$@@D`$Z&AXC\6%DV-#0L1^_`C4`B"?@B/G'%G>69]D$.4Z&K/*52&H9UWBC(\:4E."21^.2%M,+!O +M'/&G8G^"?V>TVBDH>CFGBK::BN[N;Q2+JA8G_H[B(R,N_>N=-$G'0K49YQ>: +MS-:A_C=3+L^45 +MCG-S;Z&'F]RT&SV,[%A$S9!G]EHG,G/XY%-09-(7O:_6LUDXN14M5$QAVK3] +M,16L%15#I'FE`Q5:`FDDRQ9&<4$4:;.A'?]Y="9I#S5M/4A#H6.CL@U3>7"L +M,\BMV[;-E$HFY,->6:*>3.V_B!<==UD1XQ?8)MQW:0AKZ*T^DXH1ZZE-YEZK\OJ/ +M!&=:1N%@=N-AJ^\)K>8^%Q_\*V,1<7L@F)HI^E1^!8>I1=[JBJ^)U3)LU(;OM=[-P%>;_M'2Q?&A1G\G\#D;9$,2T&'QE +M>Y:3*XN?BG:L+Y6KPYI*:J?*LB4-75CU;LJ!?CX:RVTJ'CVWF1XL[I$IQE?7 +M$C)=5&"]8.X.U;18&H-JG*FV]OU&KUW59Y;; +MZ=.>QM^`=J%13B:.QA6J'0AB,1>P5@51A?68@'#HYJOE4\7X*M%FI.14*'0Y +MD69=7'+@QA/H1#RT^DP"\-O?';-ZI(*LWP"OJ@UU+64+8Q50@\\JV\ +M#-HO=FLP;F-#1<['U`IJGV;Y8H)A\GUPZD<%NMR.(\U[1GE/!K[P@Z6LI'W- +MPCQ[9/E,/^#$7-5&7KU7I2\T\DT;9:3I-;*W5#1E3_GJH+ +MY-P%(5BQ4HE_UI%DR:$'!MZ+BLNU=P81-S^C8@!T?/?=@HWJ3;*5X-6'Q^>W:4.UR&H<>>0T=COA.J!6.SG.P[>"W+MRW08R!18@= +MKF,)74V:['S-A$=V91S4:9!<[USH)*W$VHC>2X8G56^.C2H'$7)RQ.? +MCV+K9\**"G%OVG\LP5#]":Y@+$FAK1&\[ALPS;2ROA1[".(L'H=W4]*#^F:+5S>,?ERA)>4RORLGAT75"OVU3;66AYQ?:/&>4'!R +MVM8B8L*C":K`PFWJLZGS[=5S?\Y7;JMEBS!+OF`@V@Z0M&5N+HUDP]S%`RXN +M"T9LG@818-"3PSC]4&''JMB]H43)@HV2=\=[S'_&UVKH[].->GW@6AWC]=OZ +M\[M"/7EYPFHT=L5DS+MH$]S!+TT/6^^>\U6FW/VJ_5I6\]`,@]V?3^5/_!&0 +MV72^X_=8O1MUOFE#4Y16+]I9)MK":0RZ;G69853GD%J$?0U_QH+F'UK1&>Z` +MXQIA`66L%UIVT_^>/^R)JY^SI2'T\*1R[VG^$*)5\TD +M-S`7.=::20@'C7>X%VUTN_3WPFFH3:4)P[,D[PSJ'K*<\PQDEGV&(.SP^[(= +MAS>1??[K6F^1NT`_IIV4:Z>5O-M_"+-Y;*25W3)5\_(\`_Z4-"[R3[G1T6WI +M0!8WP8'(K7`GNNZ)H9C+/&5)WW//PB&1\)[]EWQJ^![?IQXKX`:5\O>-)(EA +M.+(P+[P=U3WE"A?FCUM'-VNQ,'!!`_>G7K#,X?K\M*I]ZZ9]*#]<%W.>E\2` +M2-P[JU%:3/XN1XMX!KSQM*/:DJ//`.S78V2YN13T_V#Z=.,FTI"$0V0_<=1G +M)&_.>3@&Z=RZ*H;J3XL"'OYA +M\=J=G9;]3$6.B0Z%\11=@/@DB]I(2:F0S+8>IP,,O5%1\EOV)VCSN>=#GC`V9@P44J'OA[B;=D +MVK.\G@WPR)4K3HS/N.8LRWW(\ZXD:OPS&?GU^;H2R8<5RM.:[@80Y +M3*079AC9((1[SI@T\9D9XCP.MG[ZP*:/]4/ZRPG5D$X0/SN8&);!H,K=":87 +MZ6KUC"L2W2IX3D#)72L#Q(_/:-DJJ[J*!XG`1(WDTLDRQ0/I262;V892'R=E +M?:5P3'T#WKM3Q3MN9]WD(<*/]W:#!.DL"`/#0UWJ=>E,O-;[F`O$_L@7`)@N +M42+F5C2YIJ8()-F/7"+>G8*4"S45@$?&8N*KA_)5"&0)**:&%,0\^! +M3X7??'(OSE;O@CU)#@C#M*J&##D[E2[Z0&[HG*?G."S1U+%.+Y]YP^QYJ&ZS +M4+TUO.RWI,A!$WXJ$8X2]HE"PLDEFA>\0'UH[+N1_EWM.?"T_/$*6\566A=C +M^I/;5=`5T?`1Z)W.V[<+HPJN/V$;BV`KR&VE[?)00T!LJ%0@I2#'=5HE&,:Q +M8?>?#!FG"8MP:>@`P*%?F(JS%W;$N>RG(]#+/:=J<"[.QO.)2X$)L"\'S+S! +MS-_G*$\<2`WF_03/*SV3$*A#=KR7ZU6^OW-2F+.WA(-2/E98/D?P9Y-LAB""KP:NV2!0#31;;%8FD30MN +M[.%2);(VU@:4Z8I19)XM)F^G%B$)1$]5:`:2(3.2P-V@B=DY%,J+"$QG1"QY +M:!6TMLNGI.9D`AK@5`&3:F4X[06-#+#J8SBIZ),=?$>7F=DDN7HZ!D8;D,AN +M(NF+A$KJ.+!(B@MT%E(.IARD+:*I?C`.,V%&#(O"4"^EO/I.=9ZP*53%HPD; +MI(Y'HFIJ^?,6HI"EM=4@X4XCO5FUAT[1JVQKY;8*]`5,*IXF-(-6`ZB8)\T5F<>W";Z$I44"($ENOFD +M97D$IJW!=?2*KY\TYU+E'22[R^5W57(K83`%%@AWF8<[/J(E*FSV_UCEE-#D +MFU3QJ=FP@^._-N3:VU:#-&88U3J!0A-'O@V%[J6><'$&?/.@,_G&\;"5<,@- +M60*]O3SF@>R=*_`>M9XVFDWZG'!XU:YKNV)4N=PMFLQZ]$GY!<)";QH4^2(> +M+1[50G>-)_T".K-^*6'0*?Z>&/]6DSN$RAXK%0L,OLR;6B0-)HL1CCX3@)8H +MZZPB$1XU;EVA/'5'T20MC17;.:=SM0F +M-SZK@]^8''8@M,RGUNR.LOVPK`_D5ZM&7S2Y#:R< +M)NZJ(/.C;Q?[GD%I$85S#VO#'X_F(AS$>X-].,(>>NI<@C$&ED_.#YU;EAG< +M`*/8.#6?=JK]_S3P8J2^K95J';77=Y3U#35IY>)R6H_NOQCN=*=?#;@#GY"W8%R]/"5#%,)!/A +MI!1N3D./8$XW8D,BZE6^&K=[!Q8.JV.MBC7@2$5O:_Y'G?H%ALU-9+;NGXEL +M:$*'4$!\JR7-DM=F($IWF:6J"<^^ISL[0;[N"H9I'<1$VT$*%;(7KJE8K3%-"#TO[[_'&`GLS(,J +M@A[G?J):E'KR%)8=1URZG4!*M)>6OY%KJMUHG"\#4/AN,P=J6-H/7CJANAM" +M]*70Z-2A;XF?UW(R!MX3IHB!(060%,#]I^-AW*C1E$.=8UE$>(K+_F&-N<"* +M9]OIR(%."L&X5;]DJPP/#Y+:O*`JWMR6SL@=V4^0]V9L%V_,S.DWD2"Z86(? +MW-R(HY:WGL.:4=AQ)N\,E)_2W>\9?;8@5J39?1/E\U?)##N*!K-&2EUF%*?F +M7*D9,(MVA2%/6O#I3""L\4X[F2Z%E5>ZF'W6@7H1WPD+<*K#N9RI5D`3AZO= +M(3K")7(F[7IMAGX;HTSD6/IY^J)XG\<*QP.[JS"-JO9&!V9;@]!Z,.-0!GS. +M2=WW\7!WT+/\F9QQ$IX;&*JYPE:G]N6(H`G%:<.%4R9MNIBE6&GE))971;I1 +M)LL\=924/VJ%]7^,/7A7]K>-ZELC'X1;2NIGKFMZ<_15ZT%LYH>W?+Q!;9@MR_4^4-YD^`.M\,](DK9RS4*:T: +M_#-M/;E?9AEW'`"F8=G6A)HESZ`A7R%8.TA26^LUX@<%#3/2"W) +M2%SB#V^X.=G3#Y=[SG]SC`E'P=.Y<#VA$O$WX]9)$65$D/V$GQ4*!Q)*K`P+ +M(^HL328"/0(F`V"!7]Q4J[P1P,`@!RA<7K,M84$8]CE![EKW=);D4>HL[/TGLF5Z9IX: +MN9(G1$Y?RPEML\N"VZ%T&I#5Z\+5@J:2=66)OE[5%)58LVI4%?CNU'$Q20>L1HOZ!]*A\N>VU"Z4%48QEI_AI#,M"@L#_82CNH#&B@"J"G,8%4; +M'AZZU?:@0N>@PH7;;WD;=MMK'(=X'Q'W4BRMX?FPH&J=<((1Z0_8\CPOY@IZ +MWQ&612VI?I++#&'#P9:]S3]COX63C9[&/1'$Y#_MDX'YZL'*EA`VRU"*?.CF +MJ4D!1>5TUOZNYCE2K]!_3!?$"NYWLF\@^I#RV7X^NG9]=:7'+XR/= +MGTX_I\;006&6X4:[*:XE03QY>>#UGD](#P=:KSJU-?KT3R',0B/YEF"OEF#A +MJ%'2J,O2XHFT=/U*B5."I@'AKQJ/91;PY:?Y'.[>]- +MA%)JQ387E*T5'I]I#!>UG=J7JY,IO4MX%XA]A!.2\K#=?>H>Q-HZV@8I8(W* +MI(J"+2?9S=U.Z.KOI^YE*HM5$X%"^5[5D`,58*$IO`_585X5M)3C^P*K50W]HX:`@^>E]U0YV= +M7U2K]-9M8EE$:/G'A*'?C#C`%K^?OOMX^VY>7=Z\]CJS\5R6;O*M]*[0)R/9 +M@,YQB;O'GR,;IN#XOG4^#>A5'C%1K0V/-/;\58.ERB2"JNU`X=,5ZU`X6N'G +M`Y*\A.)`2"KP55WS$TH_P-H\.IMQP\$.[< +M-![;_+R[OZ3N;6&;IW'S']0*S\H%/1WW`=_;5+T+85@]D?1`=R.L$S4-W +M:`,9R!J4U'JW;8@$-C6U.3E4RP(J#&23@6M1JLL^`X@457*%47X)T.O3HHF' +MT*S$X&T[-P;X1G#B669WC=(-1`_Z\:PT#(^C\N.Z3(A"&%M.3E7+JGE-WN#4 +M5/KS3`O48(+#(=%M>>A90L[F/M)DB*B%EMT=3O&ECQ27WHO=J/VLVNS43M.L +M;3U?P3*GSFKKD@-4YDE2*XD:/+K)"LYQI]9+U6BD!;];RV +M3;<&$KRG(`(NJ+CXPZ%YG&EY`8%@_0*Z&GY$),=<;%QCL-W%'O'#\_4/K:XW.]9PO$2'M +M6$/#K9.?"QFD, +MVCX,:ODI^M4VELPUTFZ-&TW=QF3'@"KM.WVRU+Q-J@%'*7G)QZ1&ZW,H?Y=C +M'DJ`E0A+>"G6=,])"M>[6B(5O/`LO*Z(]G+Y`M+T*MD1/RGUT&(&F\1D?8Q- +M'A^K&G;P/.AS?Z?9]!D@)J>,&`OE=/SA[YG#S]RZ4>YK_#TR_7+9GXV7PX'_&?%_I4(V8,E%(+L +MB&*^J3U*.1=+;>K-W\`6T)(6AVH\?#'C\MO/U>S=&82^>C&$R6TJ&*PW!NWW +M'@*QM4"GV"&9B#P-1M-1H@EAREIC^%8+@_-)F*U.TDY^R*#6JLB(U:VDC\54 +M;5;CX['-%_T(4AXPXB#D0H2(?+B0,/>3O'`5ELT'.X19BDG9GJ6SP'ZB91%T +M3`VWSG("+W]X6ZWOR-@=]R$<&?@^9T!PU6A1/4IEM12^*J;IV\-.3=-'*^(W +MS(#%-^;M1'*S$O>2K37?[Z6`GJ[5V,OZ?2=B`]DJ3UZ#HI_"?3E,\%_PV<;B +MT@,!V[[[QS7S+37:*V>=[23PZ':U&-D#E^'-#,L+W#MXVY&K_(*]+MW +M7FGT9Y)MC&`M\B\^U,/(DX5K*TQ]NJDBS%$OR#AMG8)@U[8M@47@W1.0J!UZ +M8C[JY1VVUJB`DP5IT9-+/W/Q?P1B52F!"%Q;;^)#06:+)9?77KZ*P/MI<&1R +MT:UZ],2.U#ZGT-[:&V8]@67D5,"<4).:MM(L6"4`;FQ"U\R$0L>"G6%4;:;1 +MONR,Y_-K'$&PZ!R-WZG`.O](&3>9FT=W3,V';%3L.;.?M/!G7\S:9B6Q3I6! +MAX:U`DD7W8:Y7=Z7P%6<%LFOZ%`=9Z3U==\A0[LA$-ZPVY8L%NPVYL*CWH^0T&]G&71B#V>.9U +MP7?[@RC7GLD["2:2L_H_E/&#`XRL5"1+G?P5>8NLJW=+$'B.T<+=SYL+1H*U +ME&PN3P'/%ZX1,9;51N[P7D]FHQ9`R!OFK:?YKA +MFBX'LY.$TD[5*0P5(GA*R%Y^.Z+\.6GB3F=5?=W?U$ZAZF>B]PX<_!9`_:4E +MDZQP1F*'^:'L;R?J/T'DDJLQ91>#Z/(AIE-#.X8:7Y)=_28F(8IV1NHV/9(A +MXFN\68IA*WIZ@P=8[N3?1L;Q$1VT[T +M#"W+#Q5X+;MPA>,#V^T"N?$TKE5:\E[=CIIM3D +M."$^"S\:F(GE`V]E(\J[K(V4LD!-DPH#,?#$2ANMQAKQ@)#7N@!&0=T[IC$# +M1\OBQQ2@TO[RLQB-]F-GY@.O"7E])21%&/&>*S_@;8J4.9D#*P8%$&N`D*EJ +MW%9>;J&D&E\B\@HTNW?VMS*\9)`_> +MX1S(\!PT>0@_M%]0DWFONVD(B$WY==M(L1OB!N'Y",#V5\TR';S'"I-.V-DI +M^/+3<`N;%'=)P,"E=HNG9@L3.-O6I+LG/6M^33^]263=`TV?;-=M +M%P70JU4>*^,4S9Z8>.<.Z>LA^W9[]M)H=SWX]<_#I9?%R!:!$5T0;$Y6G80E +MR;1BW'N9HLL&1??0O+L@K=\=VDE_8'/@R7X>:#**YZ_:CL:G.S08HH0F"FRW +M(#&PG1L!W$R'A`7($D3_6;.H*KA+OYX'1:V>E%(DBP\9%6"<'(@=36-D#1P* +MXSZ)?/IEU>T7?L^4D9*6!`AT)WE36I>[)%.A<84J=O?M)2K/]X-U?1V,G%"# +MBXN7PR9&&TK'_5KC6(++](?4*Z,V(Q'^U:TIJ$ZC\M128OFY2E/H1 +MP-2NYK%LR7U0HVM>7"1"_R-6@1@@D>N602[4HW<2AG,K$!T[>B/4?2A*5`<[ +M[D[YNN1?5O#2)1Z8P<:$8L1$'T@KF"I\,[E?A.L"J)%J(W'5=/IP^5*4V]S`^9J^E5Z>(::?192_O^S,LJDQFDXQ<^N3Q +M,.QNR4H6C9;J*IQBSN<=S%18:)QP[P817["]:,T@P]C&W#U[;_\(9SM.-2?Y(X4_M*$D?4]Q,G?EDC?2%GNL=Y3Y1CH)MQ^PM +M=QPRLAN<&H_A(#/\._(;M1 +M)--@-0+TUWZ!*_F?."BP?`;7KG.DF'W9>36VMIM>ZU&RK&$>[+OFY4(^800? +MO9(]IISIJKFL\]&.>?O\Y\!N-,!%/P&&5MM+/;%@CMU/II%3NR1&"Z?57[1C +MC"%E(E98:9K8I1R"6E$HK&4^I&MP*VPF<"$;%CMWL\N.*H+<5/(M>3\`CC"M +MOWU[Z]B.(R&VP6=Z0ZK?[W2]%S)#K6KC07C>=>?S^3]Z!!&Z/;"^R2_>PK2@ +M"0E=^\,^+$H.S7ZJBWIH_,50;C!+5[KO#RN9145)OU'L!:(A8.0](*0^R;%Y +M75?#._&Y?O^Y9JFQKZ"^O86'FIXL;+>QLINRG."U,X=*9^FPD)S1$V*D&@&(LFLT#R\C8&/K@/*OJ0G:S2 +M)L'GQ#)8HV3$,IE0\KV26VB-G3Q7+F+O[1MZ*BOY!.*V,UT<>"5#BN"L3/L2 +MP+V/ZG/Z\&4D2*Q0]=4E1HZA%X_<>P9Y=?!10FRN1]WU>49,7`004%G%F][[ +M&JDVYYK6F*/7F+?@IKNXQ0^NA0A"`=W2[]@B[*9HHGF"&O(J1[5-:@18O=1M +M*XAX^A&$JK!/Z\05:+`6OM^IN/>%\M`UO"E'!XXJ&/;P@U#ZD42T7".+I2ET +M3<,[!I/`]<&I7Z-0ZOD(NF$_(DV+R_5+*?-!1XER8#(HG>#Q+A#XT +MSM7Q1`A@GP#OC^-TUEW!&`GQ\_`0_/F<;M]W[*%;X%^0&C`G)Q^)QZA?>(DL +M6ZEH&+O#RTK>KS#^$[@]K#5YVG@L/XJ?RZ[%8N`,*0*KI8S8CGG=23R,?*GR +MI'FOI_*_UC-PN03DS7HC+99(\.'[`:8&5B8&%=82@P8%U="M?]BNIX(8NHR,$@X^Q(@BT;*')5H,8#* +M#F0%_*\!<(@5B4!BCK_I_O8%^DUCT\,>K]$5!/TMJ7FMF8V)P<2YO86.@C:Q +MK@#`51'2XO&]C\G]7AP=A99"S9[FZ!T).NO5WRD=Y/7NA\R=$%/.R^S.L^W" +M[]@Z^O'CG'#E"QX)/&1$U%7RM*SSX9OT`I_()_+PHIZ/II9/EM(VE7=]/%/` +M\;J+-U2FV@APZT.[!.?B4(BH9;K\!I9T>@R7RRQD*,C5,U=IUQ!V.$0I:PB? +MI4ZAVXT[_#%WE^JNZNH2?D\NGC#MC;* +ME'G#*CU3!$XM_<:I?I\QOP#-[G>NYG(L[:)_K\NO=+B/[%4`Y5WP[S$U<:#A +M8I2OI$C[>[X]>,O>>R9.X3__;\AG]UP<79I8G`!T][J+*O%[1L)O>LN+Q1A7 +M&&=:<)R1).@`@,=W256Z$SQM"`DR&..^T51Z5JR:K6(BE(KTJSSI(%=1X(,* +M96+'MRC27LA)KM1#YVOHD46*FV91IW%%HF-"7<8]SS[^LW?.7S\N@?'V61C0 +M8O497Y`Y=!9-^0X+R"1Z3F;:4&%L#BS+3O<=GJE)3Q!JQSTX@@DPK?`_:T5XOMIC`I5AB-!EUD[&P= +MV8H-K'.TGDLP<3T@.6QH`O0%+[/7?I]X(5X%22NT7-I`Q2(K8HN&EU%-!44K +M>_B"=0-8Y!F[]Z-3=S9%;S#`E)J_'AJ_8#;GMB#@M6IL#7!4"A(L?H)8::R8 +MW/2CO-EVRG4JOAV':%!6;%+'8^/K1#X<6XYG5C2?YR.22=_?8V?1 +M1:;NJ(,'5QGG(%G*8P7V0)OC`IEE;\LQZ'GO?%EA_8BSA`PE%V]P\?+OGE-P +M%F.S._K"?3\.T;O>X#^<7;!=]4+Q4CO>^RK;:MX`_-ZM[.*V;ID-\1'Q#NBY +M%9+HQZX_[+\&3(2QYBBG(?;;7?F#-C?7P5W:^4!*-0&?" +MPAZB+\IMZ8*1^IRL4H7S57"R`@RN'/RVP,&8X`J[!E&H\!E?I>5/2)%4FT\0 +MCG@7&!Q&V1=N".7N44UA+_5T`GO?@U:MD7!-B[\W\?$:A4'F>TSJ8N718S)K.?M*R_^'9 +M9X1:[0(>&Q(%VO?:]Z!AOC;>P+'.;R+6+;.VD"W)4[M#G!\_N1[1RV3H]%Q3 +MW827,6SH.Y]S!,DOU*NG;;1(J +MY]S&`/+@P)4&U3C@I"C:($I)=*,_ODR7"L/G(,4J)8DUELM:%J8I`T.S@P_X +M[-?T&"'4VI6I-NFN:BX!QA(9EDS]$#NBL53/^'/Q_1Y&`#1A_[#9(H4%H+,O(H8GUG+XB5XV]X&K.V6" +M^&^'MJ)PTXAB\JKF:2)"BUOR[[[`]ABUR2?`R6K.%I(JO_`Y2)S;[DB2^"JH5;P@K'6C.ZTIR4-1_&Z'8Q>DJML0/LS21I +M4[=$#+]=(1$#FRR(\Z0/C5F>J/K&+EI>VEN*UH2GU'OY)J6;3PO'3LLEL8'R]2L]QR5EL1*'U5]5(8SFP>D>Q +M&/G(8=U&)@3[1P\*$;UR1=YZ,$](KI;WZ]/B\[K&%2\H)NK-.X.K<'KJ(;I! +MK/@O;Z^I`DDV]VE+T3)$>0@GH50EU>F;GF&SWR#.%!;C#*L*)YL2J@B5F6V" +ML.\O7"/E0S.[;2=:DF%8C`0(+&*=+LZNI2`V8)?-2"G:L#Z+8>6-E#&)3ATG +M]9/N$()]%)S&4<=*HIWE-JA#9G/![E1RJ[95DC?/-\+R6Y7!1-Q^$]`,55#) +M;W[S>VT,I-T'7ZO9^A=#MAHN0ZM1_6T*JCCM7O@T5_F## +MZXS;7^QK,!Q355;M+,[Z1]B#H2?\@N\KS2]V!$=*-1W2LA]0@X;6RL!#PSMHVCR2?#.GM:X$HLQMS'UKN:PY)S; +M2&P:=9VFY1$3Y7_Y2I@YT/'CZ&KSJ]&!&B>EBX_T=3_-?QU*K-APR#M4I>YM$/)CA'"%7QHY5< +MR%*LT,M/9=#Q4(<;$79R(,_GPU6IGG(2'&[\30U<*]J>Z3J6EE%?'[9:]IEL +M/;%LD@Y)D[O;ZS)G8UD5E>-GOHTFW92A&D<*7Q(H/M3Y][!!1;1;K0?:FH3W$-RG)M#IHH +MX-@]QKP@R',XWH/)OY!/28&9AIKN)W3G4V/DN#_U:D^;^+(6ZKFBX_ATV!HT +M<-J9%"?,>'PWG3:2]3);B8.>(2K<+5`'?8WDF!T?@-Y,WWH]XWM2R2NGG\(B +M6P),+AR8'EX"_V-2';5J!Q/-IC&M[@3:TBN][GL"VG@WP.V2NN[EQ#"9]7\/ +M=&`\N0;]P58/H7_WJ"^X=^2_NRYZ\"-%-C"@FQQ"W$7SX+E<0+6I!O8X$0PB +MKPK!3D>`CES@!RY$]M@CO>\^T'W6VW+#.MI);`4TGGEA961:2,N?4E;?SW>96UP]_XZ +M3>Z0$M!#ZA!9N%1DA0KFGZX^MYK6[:E]U%7&45AXVSN<,*CW(V9B2[U+T7GE +ME^5<:DQQ\#HFHHV$1161IB$*)E[SZMY=GE=TY_3304K-R;'$6<`%L728Q\>$ +MT'VIK/*W<],G,$9@6RN'X#Z('-B;W!F;&L](C$N,"(@8 +MFM@;&%F:V3]LIJ2*6G!$?GP8>-C&QLS`Q'7_?=E2W^<:0?HM;@=?YNOX8Y-[ +M6=?SW;)TUKW[]_A<6`Z_V[N0=?[I9U_67_\V+JT_>MH_^V5Q<6TZ+R]T_4+G +M0S+FQO9"\Q.?_LO_J]_TDL+!_XGFW[W-/])S]S+V)I8OYR5P_B)<8E_^D/\Z +ME_^73']Z_WTLV?J?^9?_E,_SKC^LL,C`P-"__/G_I+9&]A86G_BP@!"9EX#4 +MJ]]W2US9F)T(_XC_VWG^S]#+]#^E)^&F]>^YC'_%VK^>^$_^*T!JEP_KOBY; +M^E?TO_^5<`-89%[JX-+C^W86,R`4'9<`\"(^_U"/\LQ_<_IF6!O8OZ7!:`T2 +MQ'WX6,3$M,#C]8W4C$X.C7]$T/"__@GO\X/_D=G!Q`7?^#[M$']6_ZR^TL1: +MP-CE^]?BLP(O\VC-^/&3^WK8OL[$P./_[M6W_9`;?^6;?_<_6;67_5P8F9K_ +MW=.GYW8?]6ID9G)C_W;,#*`PWW<8F__S"FAR:&1$7_CQA8#K_BU9R=?QW^Q_ +MJ\_RTS$PLWY6:V3\ZN3?_3>'R'8'9@`44A\8GA?_QMO\H +M?S0UL0#%?D$^2F9?;V)-_S#LS+C,D4VMF=2#_:T7&UO;/Y=5^^&9@U&)R2>Q +MR9FG\[?L_]+S_\4#PO_]1NE__'E(??^P!\";C/E;`*67^?@Q_=4F7^%+[6O? +M>%P+W'_7]%S;^/(9.3$8/#!K^:7P/]J.AJ`#]P/^@#^XP"JT`F0_F1?_"?P' +MM0T%2=9?D>G:0%K_KOIT[-D +M!R@G(AB,B&*K4*3!D+L@@4UPH2KD<\0!1D261"&'IN%%2V +MN],/;Q!@?#Z=$R]VK19J;U:\-):).<4%Q<;3)Y0(QJYFP+,N9OTD6X4L7__O +MTD%R@A08=9[,.5[N-*&;YZ>3QRV>"EQDU-:UBV:T,*$\S^Y=[?765D,=OV\, +M^YV?"TTZX"28W<+3@Q0[12[>&;;!ESJ)M8,6N63:0QVPZ;6![U&B3//OWI +MH;-FGNY+'6/O+GO:JW[%B8.G+=R)BU^_'A4^ZU$!@P7>?7N_']_7(_+H1H7(*ZJVS+AZ\:A9L=G(_&9_;M7XVE35H'G33;HPVPE1,3,C$^!60 +M_N_G^4/SGU?>)KLMB/33ZSVXY)@P\;".^C5*C1T?BT='CN22YR_'/6WCFMS> +M?JV;-H8RKSIOK1\-$X:"26[PO6SS=,K;F +MXB53#@=.W.^2\9NLC[>EW"O9!`DBQ>32B%Y$<'/7'R8 +M@C1LU;9%]XU]ZWNSD..DAU%OC94Q8$5K:^4)'WG*I%$GN&ST:]&O9IIZ[+O0 +M(RDA,>7'L=9[\;P-+[YZB4+>F'0>;'/FU?/_'JW$O$Q]ST%[PBJ*'H=LB@H:G:]2T`E`"UV#!BK^?L'KQ[/SD +ML6_ETXO7^.KT@^MKK>;7T[>')Z)A/(+Z//7U3T?)RIQ".W3E>;X21BSW6@K! +M$!CNX@NMNLX@P`0CNWT8I)!)GW'-VG0Y^.NR1YR^2>!+<83XTR@<6+)%Z,D) +M3_]O/F?#&.`W@A#5#V,L9Q`&@`>4'WW+2TU2"']D^;<:C->K;.P!ISH#I4RJ +M[3R"3O9&O]\!UG`(L8,DMN](%L97Y$LA,GKQV#_ISA*`7(X]E" +M?I8-&>(+H;SVP!A4IYRD$)V&+:RP$.(@[$16%)BX0/NY=A4SDT?B0GN$&I]U +ME04A=-MD[;,,3^RVC`<-?_UA;7!/B\^?7GE`C#$+F(KYA#2%E/"@%S#[QQUE +M)US1/""<.*DG``W;8%__`USU!=ERVG$E!9)>#MLDIBG;N_7>`Z=\D07]Q(^) +M9![9?+C),7*(&+J;CP9_+V.(%.$@S-*##^\95'$4'M>%;`Z+=>G`X\\S(Q'HHT-IA'"4<91Q"YL6&:GA],&'MU5-"47I. +MC:P?MV6-S,'[YZ,U%,,:15F9<;->G"NT(S.KAMX4:!>U]ZI-N&C9IPD;JWY\VK-+[GRV,^Y +MJ<4[&S=KU'36^TLBZSOQ=0:7M,C9(DRH3FV1==[ZC_GOT)?`H0QM0.K!:=YZ +M\Y5?_BVG'$J2VA^^'S[EV?1DFGGIPV#`B>#,H`U[*5"V! +M6&#MJ*:>W=/3Q+;]5R(TC9]\^P`"(AX#'CRM1[K5L04'+Q/A+"Q>MGK?MO\0 +M7GWA"#[V?;LG`$+Y+&[8\>/)DV+87X&/7G6$HNQ39HX&?/G=L0EUHH!/=6PP +MN\_S?OCQ?*D!1QZZ+\7R94UB%F;[K^.J`&U56UIAVW92,_@7(O7L'N;N[TV- +M75\_=M1>\:I`+(K@V(P]X7I#[QU*W;C16<*5B[]::,2-*IXO?W[RX]]=-:+- +M@TU2C1;O']-9;<&;-<\1L!ER,:&W%)RVMS/D"5T]1@-+S#CF>VBF +M)$?Q$V:/H]V;ORUS"HOVI.F7)JNH*G/+X7;B%=5MK@?&,2$M*(J:0?.Q*`EN +M9,0D^LG;-/9_^4=BQU'/2`!>?0`'63S+J1=2T`@?L_KF))G$ZSY\U=DQY,Q( +MRF`F7,0)1: +MI5K)DS/-;=29BR);]N[!/^SASBL_/_M%'?*<;<8A>@"0UJO?Y(=-1RSZM>O9 +M/;%4.E`#RG;GQR9DQ8@"32&>VT`<60S]1M^WS66QJ``.EU"FS3W +MJNV\@DTR`B]LW#>W?[A%$!8KDEDY_+RB=-F3EP)JER"YO!'GAI[./Z8U25XD +MRU)OK0Z2[<`Y$;[?\-A&C,S0!_II@^/1@C_1$<0`=A)K>:X\8H7TK%LJE.F% +MH'`+7Z^XVM$F:4@8@?)[]*<0@GOB+/@@11,9?E1Y:%ZCV!N0`IX?Y_&DHIF' +MX/4^`)8VZHIAS0`!K"_\W;)C@CF:`DW6?.I2%)`3`K%BUO0`205%A8B&4D"3 +MKWK?@D>*/I&J"K?3F0HJ<]3Z]FNN%3K]RKJ_4ML=.\B'X%">G9N'UU+28Q)` +MP/9KM_!YQF3JVIPE'.)+DO_Y1@*$R4<`(/H?]0^\>,S;JT4G=Z8]8G>@S<7T +MYW.&CQV<9'%GD=XIN-T@'BPRRAAT$31%(I*I(Z"!UOS8PX=WO&S?(DS%"E:? +MS%JXAY*88Q-BUYKC2KV;-^+1GU*U9]-?FIC@;[QH3YGJLN^:^WE@L\\DU5QX +M<+%)>Z1>BM*-B*"L.0`*_5NR>@@#CQ-J_0!*[]\LRH0`@LJTZMT9B27\@"/[ +M[>G;<]&_@C[YI@'(OQ=J`"`_1`$/L*)$8"=8YX`RR39TX\H`C#[`)=\;GJ^-(T;9]-4!.ONO0OF$9'Q\!$KCUU^N +MI`8E\4O/6_"8OZWX4%0<(&(5>\_#K#QHT`1<$N4<;;H#:<\`0.N.@O0DX%WL +M)ZD9^9=3VD\PAW-^`F.SAR`(Y0*E+EC:4NF@>UM*=1(A.!['6JW=B<"`W:?$ +M!P&A&'?+F&0NKA:9E")I9N_7P[*I#&2K_$U.B3)AL!3KGN@5/U`$EN+D%T3Y@28O64 +M2WX^8*5!H^=/*`!]P`C,G+2UK_%6X,4Q +M:;;L'PH*6<-[(1$E[].]DMEWZ@];-QN$F!(P=`LZ(X1759:Q]2_P#'/JHMC(@\SS%R%X$L12`9TNA@3^08%)84M"JK/(4J:,UYSF7&.-\*-6+7 +MJ0\'M%YJJ@"B)<0&^\)B.WJ[$U(-,#C[(%9BL0_C`\:LZE%CQZ0 +M*'HI:9W8]ZPH??I^^7(DETU"\`L5U +M"50$4=FB<@!1,.V"U5*=-#+-;^@&&R,H31-ZR)00'-Z0Y74W0//CD68%R@+P +M-C!>/U*Y]H(7O+;DJ>ELT``.&6X7@#`#TN\]%GRQ8AHN`,"U`AZ(+)@#;9;) +MY%!2<<8$*I%^W-T"*86U4J8QK,.LI35?=0>>AA!TJ0"]"2.L,:*]<+^`1EL. +M`./KCL]LFP106EJBV`Y>@A33X0L<@?1*]P$^,4JC(UKK@L`9GS1JWTF2%^ET +M^.T8,;_9,*/3F(M@>L2!#SUT\!#";`?+L"VT#XE@5<84@DSA6V&>\5(B56;C +MLP)(QPQRW.L77.2&`F95N6M?PQE^"(6YF`%S@F6" +M'UPR>:71["'A +MZ^+/]2$7:*BG)UU5.&S?0R4^SH"=\OSGT`2-L"B@RP1B*:JN!JW"VF!(96;V +M``"F+^HP:`.$)>O`Q!3%Q,YJQ9_Z*RZ#$@F"C<&Z+YW[!8DP&F"X!/:'U!?' +MC=^%@K&7`$C`,>]R2;!7"9UDMO'V0/ +M:*$@C\$%X,25>,G^RUQ*'S`Y`5LM*F\RY\^1L0(P&:B@/,]0!!4Q8<(1A2Q8 +M2T!%3D2K1R!)HT9C5B"X6;:%G$*$G6P+R`K/A>SG8MDII0IRXJ@.C1-'01D$ +M?&433@WG#VM_3^?WHUDQKX0D75>'VT-]9/"?C;*3"2Z-RT+U7S[/5LZ[):_C +MS"_&&P(>B_N@B&2LO=O'_V^EJZ-F!$+^4#7!(O8P-/05T%`@J0,O\M!'+2@%+BJ.AUJC)X)H8Y]`Q%$5>/IBQ^&BSX4N/I +MA][V`,"9D"2L#,F!B%ED*3"8;WK;MN>M=$@VG`AE`=P)ZLIB`H#LDZP$_T)I +M;HZ5Z%V#MV3+SIRX0;"!XV\*HD#%3U300')$"7C%H[WSNA +MDN&`JR)T,;G"-`V=IQ&EX#N!S8EN5H!1)Q3Z$`:D91+H`5YU@W/4W3GT"^0E +MJ\J]4:?1H]L)M=9Z[=0#"1RK8\<:MCQ=;4\53OB_^DP8L`1(O0`Z4;W8]F;N/+?%/2WM[]+I^!=[]F3V@4-9SZ$E@G&YX-1!+?]@33(AE(=0 +M!A:R\TN>$FAT8`$[]7G,XSV%'1PKN2-UV3@5@S1JO[^"+18M67.`(X +M`%IA^D43)^^@=*Q?S3W"_#^(!7<)Y*OI%@P#!^+Z:^8G;COY7+J6L\BZ/.G= +M2$]LN!'R4D;KMT!0HAX2+F=B8FM!/UP!L+SBE^3@5$_?1`\0%I2&AX_L@@[KLM,LNBKF`3`HI&B)Z`'@69/-$ZXA1H( +MH"17S5'-&02[4"?CJJX]078FRYPGN(D:4MW:=/AQ53(#-*?891@$$NN-%/;I +M-A^->^RI1C1EZ= +MGV/+-G0(G1U?LD0%"MJ=@CY9$"/,F)P4&%\9+9,-<*F1)]&O* +MP>Q/WD!+2:,0NS(I,26'#3&EV/0$#YY)RAM%#58>( +M`>CK07"*L4<]$[%,HPK-62%0!PA)*HW*]0=<5&.QQ.9'H^<69LA)_&;?'?LX +M\/\UP:,X>PS'F;XI_YG]PT"N\L%3`FAKGU8-/6G.PPC^U;)@'^\"5I5M6+V# +M#+(&3FN[@_$#[(D.^[@@)V&M,_Q>->)18M4SU=?@ +MZ'8NG%87^@GV=>&[/3D=E9L2QV!LE7*693G'://EZU<1MVFF,M7]6]!JGYPI +M;.G2/S6R5*FGM0B@=REDJK;!RT.2=_^H2)%=F=F!F541%8L>EA)*2)52PZ(E +M)`DL>I42Q2632P*I70&2Q"@*"!#,(P@$R@1J=:#WPU[L9V^NCN>^HPX$EB$1 +MG/A__<_$RD30`$Q@-G.@SP&]-T09;=V/%P`;,3<\P4F[;3>(M5/0@479 +ME(&OJ2H"TMO'.-8-VI\@"181O47-OU',^.13!P4&)5BT9(9?((6.M=^)&_CV +M.@`#9%:&2#I&?-.^)*'TECOT,'>"W*C0)&4HY`T:UJHQ-`TZW?!_LL\%&T.! +MS[C$'G(-DH@-8.D)4'T%<4T@_+J*Y>)0%HUS"0?<^\=B";QK]-EQ)+)$J +M0(B2S:.@G^/>/H[25@Q=A[8IL1H>O%<&CCN+9&44C4([&RG^9@Y%5GQBMOPB +MC[5.\%9^GMV$O:GN_IH+-$V$>IMVK^VK;A$9:DH75\H<2%,^&&]%::<<.8\;!`U]:P +MI"_.&,>D8;*1,`B3N`<BF6A-T +M>'%4>H_*]8AB(,/SBPIK'870N)_D8#B/U8G/=<@-5Q)9SU4>P5"PO:FHF=4V +MTM;MM.?02/%0]K%F3=PXQ%'(XGW3_S\#+W2%4HL(B^=FU*?7H]/US%3VH'!4 +M$Z&]TMT=0JT^EC* +M%RW?@SUZ0*K.W&F5[RA]Z<`!24T@N]E-[]FRS33/1!M#C=*+(-`**]D.E"):`&-+`Y8A=:1LA3]+.:T:['=>Z`!(E. +M_3^Q"Z,<;+$MAB>SMZ/;+;82!&?+9MR_]OZFB4IBB5+-``$CNBL0=YX5``_6 +M:V2N51N&UN;F-\.[J][?6UKAK7H&JY;+I)#@S&ISZ5&TZ&G +M=J2XWEAEXI=;K6#$]!%IU0`%N;]%0L2@0NHE`RNW-\\MA +MORDA3G:W]N5LC4AHSI0"+[KDOF;W'*&&K[4R)RE3K/\^KD5`WS2@N^GTF]JL +MGIN)^<[^.:E]\B^A6*L5_2?#!OC#IO0';2IS]26ER(GKX\4:@$:"B_#R(M +M>_R(5!KMFW9LSRX]3K7T*H'2P%D^0B]R`TG<)[]6Y>\;+&43K"KV*@XB1@=& +M9TP>9K/$"\^L^W']I/"*/'Q.>^5^'+09`U54W;@!4@E'1?;U,[9M5$C@4MFD#KH16?85G,)P`L"MHUWN]3\\=P!>A:5*F^K?I\*OSXG@ +M(QH\Y0!Q?4&730I[/W)>">P\0O00Y#I/*7BY.G+A#@XZD*LDC3R"G>`\TX$M +M]'(.Y_D9V=661U@4QJ..E`8Y77;VMK-I_(WY$XC+9!8O;@KI6@FJ*#YZ=S>$ +M5!F(CZSYG>IP^Q%ASQ/D=SV$PK`%R/PG/$EWXKAF2&.$9'@85A:&8VZ`?C4@ +M\B*TU*Y8P\8KZ^#X=::I"#`24_)-L#\3S[1"QQU7PMD^T=I,EI#2CYHLG;1D +M!7HZ^"K]6K=/MNDJ6C6L8CL-4RXX)&Z;C*4^2&$>?;F&_70#T]SX=+O0G3IA +MC#0#9^VB(J1_0UJX&K,H9DO?1./!I*^(*>Y0V7X>XV85NPEGM>S0A&4>]7(F +M%):U*]

    X6^'9XY9^;UR_@U_E$D.\3E(5TG[ELX8$C)\`"ER])A[G`T9/OU +M[NHQ(.!;Z1^T!^EA?:;V^$#7'G@`Y@OF'W=MH+_X?+X<&B&]>4`&2@T$*8M> +MKJ%]3H$@SEZYRMD=,%B,Z#G`<7RQ6\6[\O0UNEY>")1]OS\)P3J`E +MK43)[XL8SEDB7H\!A[DU^EXZ9\F;#F>U9@PW6/JKMIR5_8>S,:!"81"560B1 +MT"#SH-70XZ$M]08_I\/UOQU4S(:A@HLF03K2AA.(.P=J2)A_UBFE=Z<+O$3& +MH]7'J16QGFE&)/^&^-'Y[H:X;2;)!'!9^X7*$FPN"/[ELD.5N((#6@(.46/P +MDM\*HP]#K](XRXC^]:XJ3V<,PL%;"EJTZ:EK!\C]GR)7L@1E6X>?)R*Q)`P` +M1/V1%0$8W7(#JXJ/44WVX4:_:4="!4'H*!1\B+`,X&/.? +M+#I-+(''@&E4AX'XC"%I:0*L&9[(W\B`'#H($`L&>PDV>[Q`@M688N1I4S:( +M^O3CB=D=NU0\5>1RCG*?")#UZ'MX"0T7`-Z>,`FP`LR=TSF(8IDV4HA.YR"# +MHT5;Q6-ELE?"C<.2`I=&F25.'Q(@H)@)Z=D@#%G80K(#N^=>4J+SK,_,'@,' +MNK(PC%96R2?PDV10!/Q,:?;YXYP(O&`]/#+2.JH>)L-P+X+'>6GVIHDZ0+^' +M!R.@OU`95Z]E97*GVQBB0N0$O$>BB)AH>>ESP0-10@W;1^+J1`8#)/N1*I,; +M$."-/6Z:&1/$'$9>+>^T$A,-"O@H?)\"A/B*]!0"D]"IU$O5M_I,@LVSLFM7 +MG0=44XIE`(;I&J%W"P[KS(-U:\+>4/MEB(6F\CU50`C'#PX2!5_#TO_")>\/ +M%YT/ME4O$'+>#ARDOX(/37&(D@HZXZ6*+]S+;6((.`"UQ[:A1[H2HTAHNQCE#6_SU=CW;M+OJKE'&;>R( +MW'ZK7"@@S.G"7!3`YNBA3&)11U_N**VHH%A]Q[U2JJ.E*S_6XD3QFQ&U.SHW +M*/-#YO*H=DK\>KAP&GYW.,$V56#O5CDY))Z,!;(3?J>(?H&PU&SJ,!-%#F1N +MC(W>4JO!%]D7WT2IFH:MI@>+%`8TMIKFRK<_97%ED:>%6-M>/R*G`7%_!E?/ +M?N!%ZDD?2I`MR\4TLR!]V>AN1<1*AWH9J,8`YH]@!S2!)O-NA6?E/KS/;!-7 +M>TUKGDSHMQ?[%11%]]2(8@XDE/X_&5"<0#K+P@'9?*6?$M7,D +MMMB$>MVK-,ZA-NA<2J(?F]H#QQEI:SG_4ESUOF[VWU$X#)ZDZ@EU="?Q'LA2 +MW1[?9U&5LKR*+F\R2)X$AT@MK&7A6-ZH6Z\02G%^S,4CPXK.\VZB\\3EM]2D +M;425?0!8Q361J_IJ<"(:RJM>M1P&:_]8YTBW6C)6Z76$19=X[^C +MCXUIIFMJNKS$_ZESD8B7NB1/W;;NQXB[BQIBH#-4(M,0CR0!0M9`R1]YQCU^ +M%)^,'WUAW*A9=:_;*L/U5AZ2TM&%_L:S`@/U@^.ZNJ#U`.'94:MIE,CB5RJ/!IK)_ +M;H="9*_J`5FH46(RM6-*BOZ+1/PAR7LIQ:+H;?(31STVS)G@\*/I3I?KMZ_8 +MG&FK[:.E`)#J1Y:C-^"VZX9<\U/1$U*YI63;$48,9 +MA@RM9JA?MSR3>[A(:U>7KX!SLHN%)8B$[W`I'`3!^.A%&2E'7IIK:\LR34UA +M>-`\I.VHRE#:^B'-IE(!. +MY-B>=Z<00F_Y.X.U'-8YT!B^5SLDS^*&22-N\'5V#@DC@`BZYVL^_VR_7G7- +M\=G$P3!Z%)#V'0Z#KGMT5\3UT0#NR>F>6C^GX3]8_% +M\5D]>+]TJND2*M(=Q1';Y<2%5<]EFPV22,]MLZ8JK&@76R)']KC4K-+QZUJB/+V`M;[&%&?7&8/H&:-#]39?S-Z"&-.^O[MPS#">NSJ:PI8A8\ +M>T<=A5ES**U_A:YR*_]?S`S";>^.U+UKW@*?_7-XT@7%9:6M"I73T$%/^@LU +M?EBK8*V.6(G22,(N&K/N4'8VF!I(\OZ0C0W#J*NXUR+*`N<`I=,?DHS,`P^UBOH"ZIDPW>:;]*FE/=M$B@%L2B1#D=W'';2AUP]-,>_VQKM>^G)3.` +M=HXX/T:T\H#.0)U8:53A^GOM1MRK#3!]A"]NM2X!K54/8)Q>V>,7&R_#?S9_ +M>!9Y=:3D`=)1&<6YLA6:]:TK1?#2/4K;B$GO9,3T9?49E\K\#,F]=^PD6[%+ +MYC_?7FO&JA](%1"2X`TZ+M7JZ>3/"86V@Q:,@LYY\.]H[G$J`/W/;"<@& +MP&R>#-8M9)D!TR&L/WK-L8'QIID4$RE04+^TU#BGE?,2/+CKUIEXYJ,7IIK( +MTI)P1(\JK0(AS;#-FK7UX.-(Q3&2GO&6>;F<5TQ1*/I>0BO>B9A,A)/[I-C- +M(^%9EIM4(R3(*PN^.\-2,M%<>]L."\'4AZZ@%!ZE#A(IK:>)"!N.-JPD+;M_ +M>HLMWFPJ+"0<]3KQPRP_E.VA55D.Q>U:#;W5FXT?H\,)B[QF.KDT +MZMO$HM0M(SMXL@2.N*U4E']8UKJK0C(9.=H +M[C5,U#2F#1_K'G2LULA/K^3T>XEMN5TU,G78()0G5\AQ7/;0FC%SMY/$9C+R +M'"L7>`#^CH=7[RPV.G`V)CCV[KS/L)ULM0P4RJH[RT]]<7S++5G5$,F6$T#7C]"U*YEB%9!&\ +MR6*1?-04UF#]V2:'V=&^:-"M@KKIQ=258=*.TV+SSTTD84I>N$#V)*[`%3A$ +M`([-0AK6S1.B2'@_CL@*!?*)_M_7)SWQ7][$XC(UT5,YU7FPX7!0YW +MF5?26<$.D`#,Z$E_>ZN64;*NDE*-=WK'0D>'3J0F#A1;]4!5R.5/M9 +M9)/*FZ#`,W49V5->!]^!A;;&.T'!&PE,/MTE:FX9T?>;`1WM7U_E6C5SQ`VW +MUEL_LE=#>(TCW1MT$Z5'[6U=3*W\B8#H((?WC''QX2_3<=S1O!OQYG)@`BW_ +M%\#\)V/SDYB]KX,P.#U.X*8/O_F4/G*_P:Y!>-R*]K#64VDP;[2U!J!(&YP& +MNAI)RTY$!^*5776EQ?'DN%B3CAIRBWML>%\PRT?$*@Q:OQ,O`1@SL^*7X)00 +M)4[[.''$5\TR*ENUX/`%(FGDR`/6C/!J;<`4';"A:(*J+K`\N*1$?""Q8+K6 +M)+E3YQGB+!&D@)@89IDDN4M)4QA3C@BD;"*UD4'6`56L,M#/T8RPAB0%PSJN +MC1Z`?*%+"J2Z$OKRDJ,N<@W(B[!&XB.CKCN5-GJP\(62R*5V'``#>9&QJD3) +M%%)J,/_8'5D$/HWTO_P;\)Q,73@?K)0S\?]FIN_G@F]L.%AAD0RS39"Q,]^Y +M4S".Z<:W2STS +MDW30U""R@%F<43L='I%@;.(+JJ3E_1'`+='1%O2IO:N@BAO3]N"URK,"2_QT +M9C(825B7:W*KDX"!_.R7QT49*A^9)$?0L)"7]OS42'!#_M\[SZ_"0JH-;, +MP+:(RX:N,CP8-Q/ON9\%&XD(5/B+MV>$X(JA7#E,143V$FP&*2\XAT3,8-,T +MU37XRC11>)^IU^W=HJ&!0?._^^\*F8V;HH,F?-\=%G".WLF3]:;^"0[_3.D, +MSD\KWBF5&+$AWZ.!S7.EH!^D3#>0RCQT%0JB#+_JFU!FU-9G"C=B.2S#X[Z"6 +M1CB87K%?VSHW^CPV#+;+MTU[YLUAZV@3C52J:.@T:.`4^8W-E&.Z2/5,')RG +M\CHN+//%BFPDUP8GRPYRMV;%X",XMC(9!2U<(X@5&QLXE;*)\>(1WMPW1=A! +MV\Y@4,9U%.\LW\JVRU8M+R3TUUK3"MFKUPU_SN.3*&7?;D_W3.(GF-&6V#G^ +M>SYW@?':)GI$UOD13P-4B+S%JV%T*BD\)=+B&ER$4AF9L/1T;#-O5V\X]H=-AP`!" +M+%LMQ?>4MV!/4]/%F!(4DZ.&GGRM^YD6WV +MD>3"+M\\';YUN&#M+=N[&KAFC:82ZRX0Y+HR7;\%@]UC#$%HDX%NET)Y.F[7 +MY``&@`&;XZKVWM2.)9AU6Z47X4QDRJ!.SE8N;N)L$I4E/G`I7$9*'8^=%*?$ +MM&[2L#+REK[Q0?CK<5G42NFA(VN\E7Y;/5>C3KHS,3ZJ5^O4KHV_6:LL0122 +MZSS/H@WL'M1@^^M.YZ%BDYAKX,'67\N2B[9:;#-3;*,JZC;T'5:-WOENN6W[ +M)HTMQ_#QKX\:/(DGG]V%OT.FOZF:%[P5831DE`[SU)?EIZC[`\;6<"NF#F&I +M"0D`61[0K^JP7(S04L^8-D:9HE:7M9Q&8`]:;6NQC3Z>LKIW\]"T@14>_Y8> +M_VKQO6((DGZCT7]J<%1U(:=\P2T&.Y'+;\=M$6J3))),-T&$?8I`ILD?#)X((Y` +M'.(8NNX*1S_<5?"RS,&O*PQN?EV37HWT3]GZ75*O+>3D\+UAQ6+[MHLK\)`) +MZN:%(_`2RM:`:K6F0/Q1'WZ)0E#;Y*KK%%JK;]N;Q7I]!.XT*.GJ]7UN7/<]DJ8]'Z@G&*J;9MVH4O+H8,E(4VV]D[[^?#-C;E*I=Y8&[ +MZM4.V4H?I";@1Q=O"J/EI)R<12LWRNR+.!5:3Q'PE +M:>-YMQ"#9K^>;&-'$,,W3HMP.^BR`;W$9V7XTP""=.%X)G#FZJ@YT&2:H'E1 +M"$\6./,=['<,KW3E+'8/U"W$9(F*\))P"$(DU<]YW)8YZB2 +M8'QS2)HT5C:3WR*7385<@1KPPVM%!\8[B43W*2Z^" +MM(Y(TV_&$OHB6&D:M(&!_!!?;%PQT5@3O>.-<.918QYDDGOU(ZHP7>\YZ<4' +M3-AT9CPD?$#VVTA:NM0KGN%^+.(_(>5JH'P:JLAQ+RTMCZIXYT;^&':E])![ +M&8V+IA).RZY,&30:"L&_EG!WIVI$BQE#K3K/+CP#?B']\!> +M];?.C1ZH9A!%N+\2=3'D$VZF/I2+,Z`+!MA81QFJECZN%J$%LQH>C1W&/F3, +M*)(SL)!?4#&_BQ?@DK:3,&-<,OQ1=WC`#RU$58`$;^='4?N^BB$B?KOT]7+C +M@RF88CYH9H?^4*TG#"0"25@FZ,\)_"HQLTW:_HE8_Z@]**#F?5?1,%SH*B+> +M*N:KN^86)LZ'S7\X@E+=;A#ED3/E'K6B498KUA,@!+000@-N.-WJ0Q-+:#"" +MP11`=7>&=*]LUKQ%'=\]'/>R&&JOKD'/(<#D)5-GXZTH#7\1#!VBVCV;@T$I+8E#&MH%I5- +M7ZYV`N"JC]9ZX,Z4PN3\#FIM-&A:I#&WE_`>%T/\-=9AD*]V]J>!7W4LD_5' +M=OJPLFS3(PGCU]VF\,6T'ZTE:PF,E)6,-R@<:QE[22A*_1I9&4[K4TRP+6Q#U.K'_LT3>=P\K'M^5XT"KW'*#!JJ9-3,A[`/<" +M=L>>X/%_Z!N,_;`D>F%B9D+2*?J.D$Z/D_!:P4;:X=A#12B^N"RIU&+\.;#F +M(PL-Q7&S770/3T%E]"RI3VD.*%\:,/TZS4Z\)0+-_`-L-RW2(4R(1Z&]>K22 +M,R\C)7BWS0BZMAI\`P([XL;C=-4260R+7G1J"+/]LB4^T_+F(GM#W=O=8O4I +M?#V_L!M.3'^'$T13E'ON,`Q@A=_RE;[:W?].)@_!6#)#!)>WFJ*_AAFG\@)! +MNYWK$(!\D^&1$-%)=8%13>D5%^)Q$6, +M97*#6N`C=[*P]][YWU>VNG_[AFV`7#>K!E![0Q9TKZN&S2W2\ERKSM3)$`C. +MX#D1@$%6P19Y9SI>LXO`W)L)-F`Z'PH6"`4'Q?AIS>3PG&2I^KD%([G6/+R5 +MU,XV=`Z/H:ZR^14J"=2R@VW?>$9WAO-W))%WJ2*"Q[2L6O"D.$XMW.K%NB(" +MO1*Y%4DE2*K&JY8!/,6,;M4KUKE:4C?4#\'6OZBC"*B]\QFR:^$91 +MN7B0&IC"AX_Q%.`)ORA2N22HJ+1Y)X:?'8[-`I\8L9T.@4WLBWI;(N+&P#:V8/&T,9P"PF^'%&1$+!^NN?%-#5C)F[TLD^Q +M'R"5M!\+RMI/KZPL6'O\WSR725\^!IS"7S3IXG=&Y[:.:C27'#-M*?[[B&>E +MU`35G$=([P9()77+J/UVRV/>OE<7_DA2"8MI:>:\56&(G=*,DFG:0#9[7$"' +M6OW9G9K;R'IY%YB[P"O?(4R]!;1D:1R!N3+F`YS@*%[`D?Z4THHJT#MI4M+' +M-*IH8R"7D.#:?0>5RJ&)ML!SU42L^4BEE:%:QM)A?P*VJT1*^BNML?%,N7KX +M?+JY(PAC$P(F/>(TU[<0)7??&3"52TV<%:E*%$);,GMG%0!%^R[-O]X*,BTY&H+LYPB?/0XS8IT]S6_X]@$$]TW`-:S(V/]$0S*L3>$<>GG#_K2Y"A-3,`72Q.IAB09O.D-1\)C +M:IK$7B`D$N%,7%G!%KV;UNTBB$+>``@-&6>5>RDD/+NV:IF%P[<";YI_DNG= +MOVYFBE(?'VC'`74(>.P;-$<#UFB7,SQ(1=YQV5AN9JYC8NTSLO0>KA(9ZD54 +MAL0Y10>HJ["FZPGX\O3MN2./&!$TD;AIJ7]Q&TXQ:*Q/$C7.OY=D33JK@J5J +MV=P5`G2(/T+"F09/TQI@].WT\%EH.+<\#72+9H;-J/Q*Q\/!N'U`8\1GSA." +M8)N]+SMD;^JG*PO.5T3\Y6*D#I;MIDX2&#+\%U`?:;),4F]!#VJ+U!Y:7(OW_Q*V(2R8G28_ +MYE,/`*IB&H4A-0;0\Q_#^'3P7;3YR1D3(^(V6)>/,G]>Z\&=<>=212#R`M_\ +M!U<'=\T7UT[#O6SU\-_(,W9*Q5F@T'%6](]LB9\!M^F!$1G!]XF.EY:8Z8=/ +MCWVO#KCV,X9KL"&GVOG&,-.8O@T4]9.N%([*+?#5*#2#I +M<8VMVSMZ^9<5![HCY5:!Q]L94O9']N'/E* +M!N`]Y'//[3[8B5NO9DJY,`P^7NGCU)BM(W`Y_H+GNG6//0S.&U)KT^EB^/#").\%/)R6_)=6'#UY_J^A=.UX=RM +M-H1XK;N]V890:M3-_ONNS]1R0P%#LK'W\$-#$3Q7:7:!J]!N]77SXKD;T:8" +M[B_4YPB$>U201WNY`"V$-^HENZ",`+XL$Z<2J#C3NJ,S8_25PZR@TPAQ()YN +MB8]Z**`'XN0;:N?XQJ9YI=74#(.](/O&N:MW8Q@*ZN5%`!#P=&PP@\-8`O6[ +ML>WVOWI`C#II!BY?%9^_S:CKG@%TL7XZ]:%6ZV>#FBH=Y70%K??_P+&H/RTB +MONP_DT6CMEG;#=A7;/;%0=]K*["O?@\[V':B41G:"*WYCDR$,RJ'& +M\/TYAG2,I5H6BP.>:956N^XZZ3ALIC4/('8:A?%?'P=";11^T-Y+Q#A>P@>1 +M+7GU7@&\NX\"96&.G!+2U]I#FLH@`?U',N2>T=@8UJNW7^U$X%.`^W(3)T[5 +MS-:K7R1-C&O-V;4HN-^Q`4:'"F;)KR$I>1CP`AQ%X/_F5SDTK&_][/=6L>$Y +M^U#(>"QZM5[&0TG('X",CJ$:#1W=&OW+X9\(*]CMHMP[7P6#L2=Y+.8U*Y.. +M/D3I"E(VB'A+#D/-34:.^^%SBH<3="_3K,$T8+AX.6_**\R>`"/#S>L$,V\# +M@=<%BRYM>Y6,_K?9<+ZOIQJ6\HODM[R$?B@FCD<3]20U\9V0"B9ET:IZ4)Y< +MH339O59.[7[4+N)T>2;?QRW:J;KC6,IM7(J$&V=]>;0H<9V"?HZ91T8?,'0O>09U=Q%YVM89#XO,L$: +MT9I>I6F!H;.WDQ4^@L!`UU2*45*GN,%<"(M:E6RT]4X/)=*1>N:@Z%'_35[^ +MIPO/*L.IB:1PH/QQ%]M_BV*6``Q^%H4+B*I&`BXR+3YV;2T>-,P=$3H;UZ.P +M4WL,LC.'5N?FON^I)%QA-TPE0G"?DJV]+M=5V=W)YV^UF;?YJ^DIRD*?KX"2 +M?\LV[&">P81#&4,('7_J`V6I[[I]7&J*I.X2XK,L+*22KBOXG0/A37=O3Q%0 +MP%1VL,W,:3C10^?[1X1.]\-`G2"CO'IKG@'I@(Q,0AIHV3;[H11SRI,N&@[,-?CJ,8AV)E(&4.1L9RP>^2YSW+&*L +MEF2^UY^)*GIE`"]8QK9H0'R#L&XDSD"%7>/VN/'(UYL3]$EQ8?@DT +M@&ZZ_MK]Q50"O:TD.3/]&&],FXLT+D8B/\R!G3;"R8VE40_A(^9D/]E-Q&5R +MU]*11!J-[?A\GZ'TDGT7JU.I%[QI+W:(4M#ZLIE41N+*VO^*W9[IE@=0F_1K +MC!5P(>19?6!_KXAWY1(W-CVYV%)X^0AL8%37!$7=%ZAT*@`I^+WO`?Q^M<;7 +M&^A"%]^73'>LGE-W6OWY1TO7IAS.D.F_F"=]JPQA-O`!B$NU1]F#)ZJ\ +M9CW$^2_72%4!8F`%&[]T=+AKJ2@277=\5 +MUN))UD-50Q=O=9-JR<(/W)]5[5_=%:CJZ9F5[7TSM`G!;&L&0'@Q)&)N3S3' +MVD70*Q"J;()Z]L\4PE3"Q,P2*-C`:=4P=UCIU?&X?5JWH=%@)<@13X$QN"3# +M!A7B&4]R2I=3)EU4[L.:(%XQ, +MF])DAIK(T>=LO0>XG5P"Z=ZEZZXIO*GLPKLW3@SHI!EGJ$RN_I-H&CD!.U8B +M8#7+R'(Q1B:BJM"*Y;L["[[@0BPW,"['JV[XSJS5RKW"BG;33^SB"^:Z#GAQ +MOJ."A/1\+`55MI;=91DC5#++-K4WVJ4S_L71_ +M_LX9?U$6C179:O>A7$`II!.2E-)JD=A@/X4YK_/)#/_N?W]B_DAO;F9I9_[T +M#)S_MMS$C1IC2`N+:^@\31?'>CNIER,CZ_GTIH3X +M!CEZ,CAD,:V=.KIVIGC(,_TRD +M:GF^.\ETP*WKAY>1/>\.;'KI=C;+0)3(2A35O73?"G_4:GIWZ&A^C2W[ +MYFH-UW+;D)7T7C6K'CX2]GR7/UNNB!F^H?K#G!U=N+6\!T3)R9>?7I.KKY+_ +M6!O9QX#;91.;(Q^H4JF#ROEL?*?6>A*_L\U?P%!O]DJ&,V[0B1TT_$.(_D._ +MD+I(7^@,E>F72RY544SR60\;'>FQB3SE4:CNP.!Y"L@\EH+,0GK55?\3!:^0 +MQ)0BX3;?.W6C+3'D.NL_N_$9H3XNGI_-5IR8J/*M7W_Q-X5]>'Y*G[$E%[,V +M/AS6YLO%2WW:5SHXA>%/=A6*O#&S#!44^L,112=F.UMZU:6GQJEPEF5E?L66 +MQ_N\:_)])!KN;2RW/!*#`J+4W=9`9\J>3?&Q(2%H(F2B$4E;KY2Z +MCN&1I!)_91Z,&DG*1P]IA?[XJ_Q`6%RW9%R!Y(!?HY^9$DO"PG-)%WK0'%^C +M5=)USWPS7]?PH_$Y(ILVDTZ5(<*E>H+<[Z(_!TCT^!G?@3KS`S@T+A%5/Y"DG+Z2/%BMR"XODJ(T*(]H#-^:+)*45 +MOCR"0Z/\+]?WB=FI!`,/\&8X&*+E3$G)A@K="-P0(,G@"E+?) +MU.*HBSI["NMGPCL@Z0]LN\8+,M3$,4C:F)Z,H.*5,5>EZ%+*T:1@6<7$1"3W +MP3_7R5FU?-WS?'CP,BD&ZW`BU@5MF(DW$V@]1`RT71AIH7Y#055.86ZWDO/HECM`JJ_J,8Z-6?!0^F8D.E*M.,[XW\'WNWS[-RSF)> +M@BF??_(>3-IL\BN,J215SR]W"\L3[#K:T':)A#`Q[:Z@$X*#;AYE@9=')O%` +M\39QUG>(TQ]H>)!(E+GAU!EP1 +M9]8>W$F[K_0-?.,^5%[6WW'OVH>_-%#'K4@XV +MF+]VGVR_\H2GNQ-[VD=!SD%=$VT:X&TP,E51[FB6>/#(AF'<1B.3"+@.E5 +MZG"I\B<6[8P[%]9X=.69*F.QAQ/)DI(3N5L&\S$WRJ8(L\(?X+HV5D<[V(9; +M>-LCFZF4"'TURI,8!>K,-B-<.[=6%IQ7;?LF'A7Q9GW.+2\PLK`A2*^-JP'M,@^HHI-ONKI[L%0*6Y3? +ME6&`_#PH*F"K_15D8?_IM22EA&-4Y32S?_%5[@'N+&34E.^.!J#ZIDKYR`N$ +M%DQ:EP3+5,*$95`D,R/[]EPN.;IS=!/':+V)U*[V7@\WOF(8P^(.QX%&R2BB +MPH4_3(#TK2%>RSLQ9U]KL,O40T^UFSP;E"X@;#,"V:"9K/JY#;M+8#3H8B:` +M+%U/E(%!I4V@5./8= +M+W?51B8@]=X_\DX>=8S!5?5`^D9B5C#MH>D7LI/9[:XF.IDJID%H5D +M!J5*=$;P=F7Y!>FH@M$'+T3[7DYHC=0UQJ=.]W?3@A$$33YV\8FJY6,GY]`Q +MM/BR./W19?`BO20<"R1C?SF2>^">[WF4SF*0EUK)1J7.^>?YF1U*+DP'??9N +M\:,RZ"X0VEPQ4Z+TB@K>J(I!7P,O;Z\%E-PID)YL?Y/)=H_F +M>?&"8/S6`)NE._#/(6%!4:)?TP+#!X*_F]U0_C^?]>ZNO\6?_'?7]U85!7_X +MU+^'NJ3_S:?W5@L%OT=*5_PK#__Q:OY*PF?H!(L_A6%O_SBO[J<0%/_K+BW] +MU7>/\6C^2G)7Z!]-?_^G+'_FS_^*4X_0/YS_-2HK_NY_\\V?_0.;C_O3;O_= +M[?IX_06W])_C-P_GNK^.9NG])_[F\?SW.2?T9FY?ZYP'^[=`/^D_OG$?[N5Y +M?_Y/_/Y(&GV"#Q#\_"'`/VF#O^.F>OS_/_\@Q#U[`$`'```` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_compress_best.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_compress_best.rar.uu new file mode 100644 index 0000000..22fde0f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_compress_best.rar.uu @@ -0,0 +1,274 @@ +begin 644 - +M4F%R(1H'`,^0J&?_1OUJ=Y7J9V45- +MIF0'97^*.^+__"SO/I(.MP.7!P7!DL#G$T\^K,^^=@6>9IU! +M]1L+14"5EZHLTQLNZE*M8V]_NS[5.(N7ZDV)#A@T%ZLGY1?TZ:KDIW%%#T%Z +M:I_-!OKZ+RD5=I2"AM"&%<F9T)4;8EZTP_]:ZQ\:ZL$ +M+8ZCW'*P$KI=7`JAW&B`X"L$74EEA\0F)4\,?$*=)^FMK.)('5=PI]2Q2Z^_730[/($"GS+O_!&9U!*C)X?'A@?Y*C896K8#TVO&DM$D2 +M2E7*N*(B3^,?S\OU5%]PRV!S7PKRSV"SOT!T,ZT,PL4R*@,RXD:/S2>+!)2O +M#+.:Z:,Q8_^.2Z6&R*2J+V7[\:22)H5L&)BIB?-HXT:'EJVWE_5G?, +M9\AF!,+P_UEW#5]\G0%G#)VXCP8-TS?AB&NAMH_.N5%/VO(#*WC.-;_ZGB5; +M*IK_;@LW5I.H!'+^BMQ[-+NO!WBBNN[D;Y4S@#^6HS$7/#O!UIN3`'9`$\5( +M)9:$%$A(@LT,;V4GJUA.@TBYDIMY.GL?09TH9A\)&P041M.E;WF>U>2&#?F/ +MWE'F,BO*ZHXRMFG.4]R\XF#HL38`X.\XZIB8X^4Z+=#]D0-G0JB%''.S*'*% +M8Z!;J`%`KA\Y&7/KZS6^;]PS16V'DY-JLE4>,SV/T*`LO0H#YW`)*`$IKHJJ +M"QZCA"SM7<&"Y@8P^"NJ%/LC/+9!MDH-[NF-@8B_Q:5_!6.\OY3$Z6*!7\LQ +M(QTK#:_"+C%[IC`35R0R1;7ZI,Y'=?$4 +M:=//'-XW24FT,WT.C$L@1QY_*;"^'_P\/Y.@EFU-O" +M'D4^K5<5GE]_U!6JBS;%JZAJ[\JLBO3XWR&CBN\!CPZ<-=8'E_AIA>6$9[C_ +MBEU3*RW\.[B7DNO_<%OK+?T)F12>Y(<55,;K=K"(G&R@ +M7H(+?[%\=>>(9Z@6TQE!(E&WM26(RN;K4PWW']QAM3&8-' +MBI_6V=>67EETJI58I/%^V'Y`)QVJ_-PMX]'D!@K=_+9>*F5IB.48.SQQ#>+S +MP;(Y4"(##2,,M0SQA@*5#))W!,>O-<\UI28HY\8FJHQ'H024"3S^?UK8"Z7/ +M=\K'0+LR"^RG,84.3AZ];N!L-GH#K04MI]9.=!?BB$Z]TC-BS^R'^![STM'0 +M-'25OTU"3,__$G[1Z2"`^20%[@MH"Q2?86#8@C1Z(*C]I:QL=F6) +M`;KY@H_,T5L"L:6B;=')"FI%Z_?\H?Q0*=F(',D@2=WK5_P7-S=2XP"?&(,C +M3_T.XL3CZ[K9Z%['FYSEQMM/8@ +MC?I",[7*J9#'<#$38ER^&CDX+%/!23F(@$9333&F/+`;A>+LC:<$\63EC95#B$MZIA(SH*0.J:-R]2?N3)]G +MK;TL0',."`?@?@LK@,.KHWH)O?^Q_#S;S(W+/=:ST\HC*W*[P;&6X:&X8EK) +M!CYW6-Z0<'CJ*)1CRWP%2QPT;C"_88ZV*0X([8Y\83!'!3.7?CWC;GD^2UFZ +M6UC*J+""K@"V8/"2,I303I'KH4C;_CD.[A$N)@7SJQ[`@#=F?>_')=IS!XMA +MQ..0&L#!;L(.%B@PL9+)-@(2E.J=[@][BYHA=^?S).>%M<`]TGO@R#.@+*40 +M.C:Y#]ZX&1/YFF7Z2>*IG8OFJV#FFM;\51V_79C4'[XBKA@(\G0!44;221&B +M/;''5VV2I?VH\)5KI3$%"2#0?AUSM(BS][#.V@HFBC:DVP1]/X(R\X;0E%:N +MRT"[#D``*IGFTL;GZ`<%\@NG#C(T!A2&3F9H`9<$@H-R[]/">I9P5\\V$6S@ +M\6&LO4USF:\\)IO\5SLB)[&#KV**6`Y%J'Z_.=ID2W[OUORZ#%,C@O>S=,9M +MV%(CMAP)/!ZEE7X%S9*TCCD8.YT*T;!Q^SOU1,L+SM#9?/,;8#AGKJ^&>TW+ +MOJ_PZIW\\;!NS]:K77N:KM;EE$"\F+=ZZFVJ7[FI4;-8BH`_0%+,TP>18F`> +M>C3RS]*C81!3K7S.^49,D#O"+V`:N-_`>9!QCTE#GBQR&#/FF+YT__RE!AL$3WT4U-0NFF.# +M\CT',T83SUZQ&Z[[Y=K9SLGGRDJ7G9M#?-6;F1,%:O*;F:56.:E]\JHWSJJ4 +MPQP4R%D<$*]@E8_?7=W>#)SMT01Q&1$.>!2YKF6$@%1](?_RA0FL>D"O'C_1 +MUB^1'83'4>8Y95+1L3Z4'8'P6?*9Y:J"H4.;3 +MIGS2J"[,S41\8^;Z\U2.%GI^L=FS/*!>?5:!O`7Z3OF(,#F+-D?)S@,%_Q7/EG\`;NF!1XU'VE$)*Y'@"8&Z_SES.X!! +MNU'"4$W9(%QFJCZ*D@PI9A57VGZ7X>^X=KV4WJWR=6Z1E>+R].WV">O68NY/ +M8L(`R&D:F1LU>Q!&==(8>(NVEA.([@?W9^J"07@OY[5*;?VOMHS&^D-Z=8:) +M,#87K9%[T.4=IAM^9:^=C;[3'9M%7]4T[=$T".LQV,DG[_'^&;V8ZA'.&X+> +MOXJ!';3$T;[L!=29I4WU]%M+5JZ(#?WL,D2#-J=H/'+%EPE_9M3J1<$VTAG] +MPX;@N5,:NC,_K0P*"H%3NB6?>&A'H;<47.VL43,@#&4PKY9\Y: +MW;:6'Z@#EYH#KYPHP3%P)!+'@G'3IN]D7G"ANL@B!?7V\"S&L&4Q].41A!40FOA1<;$W?A/*)?C9_-A?@K-5O]J[&U4I>), +M)58Y(JUFO@'/OKK(?G`T4LMH(W9AJX?SD5BB'`L0/>$KN,@NAD\F'#525+IK +M[EK(7K[WI,!=_&VN!=4$J-CG'Y+`M`=_$)S"+XG1P/;R#]+]L1G(=]<2RS[GU*A9"'@XZYSC_QN10%A)4F"1#0MDLQOB +M(FF[$EX-.G-%IL"R>^D'L&QN,;DGL`$WOBX/M7L^N:`I%A988+J./SL,0JKT +M04D(`-+9":HAZ5*5@N@7TU!5P$XG*WDP,^]PE55\4^%;)1WRE<4S7W?9R-(7 +M'D=Z`MK%P\X]4O=6TW&T=:2^8"\(D0C%K!Y#X+08([X!N:CD0`%FG1%H;(26 +M[+%(1Y$6$,8K+Q19:>#NJ5>F@0!`3&*X/X-SYY,H]2`9[95F\2*A.K"O19)L +M-((WX1C7+\,"C_O&Q3T#B89[/)-^"!.+APK^IR\D-H,QP;Y6E%P#OX)G+GCB +M]*9G2%Z>-P<56E`'6OJ9R\GV5:0R\0SS0%EB?]$;\(K?(G)#G,"H6U,%NDO1 +M/]T]UM`IG37ZW[(,_QBCF$/''KW"A(V=G@@W@-`E^_-W-R.XJM'S!>U_H8/- +M/BJ]GR;;5BY`TQ(XFX%Y=Q?#.N;8$SUGA!U['SG,(MZ +M"DJ!#T#@5/O%'.A]$)V4[ZF/=-B33C+IHFHXQ!#09]X]26N4Q11"G($O]S'?ST_P&^?6CP-)=``;)M?+Z3,GZI1-;E.@9BU@ +M.KI!/3G[+XW\,QO\RKBL]R'#REC_#0E:SN:"A?7[GQT?FQ1&I25+93T70E@?M-HYDJY&(!CB_!>)P<,YN.HH"<1EP]'JHG&D#, +MA._*]W/3/@A;,@L_N0NW^5*M[45V],^_;68V_GF],J="MSOD(6K@'@<-/ +M-[!E%QCDVTWHA`+']4U!5JK_F3_.U>R!DT6Z4F:Y9G3KM +MO`V5@/SE2&'*JD`18?T@"_RW5?>GEPN/H(J0_,UGLYUYPM6M6>#>X(")AJNB +M4J/_%ORC\FOX2;+2?P=R5"_.`G5F)4PD@H`/6K,%UY[_.J.QG02T)3K +M6ASJ70;13G6.EP)JRUG["E+`9^FP..Y.I$C\=5#LPP>.:IT7776=E',!QM#> +M;?Y([:G8%ZH]"6'[O":M?%N$CTWBX*^@-8363][.?N"AYP19U^X,8TAC4$OV +M8#]=(EUSOT`Y_3O:`Z_C'.S`2QQO_7UP+,59<4!\.X_C!)2F4H9J;D\_UYPV +M$X#VS5&/!>/L>+Z(_R96"G9)2J,W]G2-#;]B48;!%.+[#H`PY9#`O]#FY0E6 +MP4!G[X&?L\-)Y9=`,2:EGK>03ZCO%317A@%Y,I6\VJJHV#5<<&:`7G.KOLD0M>."GN1^:5+BK8,=9&1 +MNU+A+8ZN=2FTZC2$@5/3J5JDW4E_.-[(Z.*5,X%M&.2B_>LTQ/(L@>IO%G2O +M]VAXF5D=R)JT]WQ1LNHP>+-UU'[2C+6@?K28JFI':_2^,M!0*J4@VKI3U9L\ +MH/V@9D(]1YV2:F\==Q23"PV,*J=(0?`3[.\H<(Q=UOI2TTVF_(MBQ=>N;D78 +MEN.=960%?1'RP;FKMNKSH$'T%[]BR!3S\L5&8D'TTTD!A@1\9_3( +M9M!N`5QCNJ%VN(GKYK57YO70.]H[?2[XJ?>,FTENF:!WL:&[:E8E7 +MB-70,W54\6+37TL:S$4WJP,M-$.[HS=;[:S0N4)+B3".WU*1Q]48OM.!8]7* +MPPT9M``F84D^%&"M352>U(M6.!#E5_V*T?MY^XY9V]-V4="E.(LTG]ABY*3M +MN`AZ?;5AQZOZAIXU,D]19D@BBIQM:.IVNM+@$<'Q5CV_;+3SM&3877WTML/# +M5=N]D"`:QNY#O5+F#=*$V*^8`AR-DY:[FT8>UOA +M+:X'!VUK8ES23Y_10,7UAB'DQ*/@6#!*F7,5@2I@0J0.X0@_DI9C4$E-,_37 +MN^'W!8A(-A+(0R2C?=I];Y[<8:M"@S-()5QZ')N`KYPQS/%B3OK3L`Q-6&`I +MQ1!2OU!<\5!7KAJ-4:1+"2"2>8F?Q-:'"_G;D^Q?X3KS^0Y^QO'E.H1XS>X3'SV +MZ;1\IN[J?^T,MKS_'KO->#9M_M`:I;_^_M +MH&")7-%&):P%<`MLZC6-FH2Z>T@W[\2@\__'YX#-KR],)%@%3_]29?*@]-.[-I<9^[3=D!^JI:S-__CZG#FH'HU!W?#N\Q&O_=$!_L1?>4WB(Y*^PV +M">CGONWUA$&T[L\<,G*BT&GK&?T0G#+WN]'#LI01B?@[S*J/[D$F!C_8` +MCU47J9\%`3=6>BR&"61K:2Y^#;N,PIE@.<4;81#<'LN6H,_ULVI7]KF +M)]"7("7/*1,T(IM_VEC!]1\Q`\6)LXTO$JZ;KJHQ.C4D5?L*`&@)!5F,.GD( +M(TL+N,T]!@A2EZ6$H!N`AP01RS!2(2)J7U\/4S!CC&XZV:/FO,Z^^+6LUQD?@\+T>;(3/W%3.#V,*W7AA2C!M +M:9:D1G#EQ6XZ'UHQ.'1+II?@$ZS<+.>S@9'?KY9K54#X7:HH*BHE+%[)R``< +M\O7&XO'D"1O,Z#O%E>T+FGX#9*SA!%EJ$U2HV-QAO$M)V__:DM3^/G43`33V +M'.E7I*[!'PC=2[,H^]C%'E8^76XKW4@0-P,?W1\U>_J*MJ-4I@0/P[P`Y]2) +M:)]"@[:>_I(A-",```"_B&?VJ?_41/%T()`R`!D````9`````_'3_!$):O8^ +M%#`(`/^A``!T97-T;&EN:\`("6KV/@EJ]CY,:6)A%0P/&L'[WB2!U7< +M*?4L4NOOUTT.SR!`I\R[_P1F=02HR>'QX8'^2HV&5JV`]-KQI+1)$DI5RKBB +M(D_C'\_+]51?<,M@,F]PE+VS]2/>+LTL^)KU +MF2N[8ZO?.RN>$#S?0H]0YSYGBDJB]E^_&DDB:%;!B8J8GW*JO9*/%:M1X$FF +MP^&O`[RU:XM%UY]0#EF9\,:3">!<)ETSY)F5GC:.-&AY:MMY?U9WS&?(9@3" +M\/]9=PU??)T!9PR=N(\&#=,WX8AKH;:/SKE13]KR`RMXSC6_^IXE6RJ:_VX+ +M-U:3J`1R_HK<>S2[KP=XHKKNY&^5,X`_EJ,Q%SP[P=:;DP!V0!/%2"66A!1( +M2(+-#&]E)ZM83H-(N9*;>3I['T&=*&8?"1L$%$;3I6]YGM7DA@WYC]Y1YC(K +MRNJ.,K9ISE/HX0L +M[5W!@N8&,/@KJA3[(SRV0;9*#>[IC8&(O\6E?P5CO+^4Q.EB@5_+,2,=*PW' +MV6\5:'`GU$42X'+ML^24T+V!U"[7`*WU5Q]A$I;.G*JG3N>M(\%C1N33':_H +MHW*]Y@\[G\VP2BSYTEQL1Z8P$U +M-TE)M#',SS=QF:;,%!X>FAS*\$LTE:N;-E6JH>UCSZ1^*'21$RTA7<71W\*'6M7UH/$P-#82?]^*:&%&S?D\9SP=W8=U"D#*O8TJ'P +MI?QPA5Y[1`3&LES]V4]=\A6GM]#HQ+($<>?RFPOA_\/#^3H)9M3;PAY%/JU7 +M%9Y??]05JHLVQ:NH:N_*K(KT^-\AHXKO`8\.G#76!Y?X:87EA&>X_XI=4RLM +M_#NXEY+K_W!;ZRW]"9D4GN7+!"*$"@E$<G,@,C`8B[OV4TA+G:`EC40T>@O"I +MY@;Y\2/JDD=V1M![(CNP(_,E2-0U^CX,9BJE=-CP^H-4\+4&D]^J`VAH[`_" +MEO\Y>#/O3GZ<`Z:6=C5[_!MCXBCD:8T=_894T$+.WU/1Y`8*W?RV7BIE:8CE&#G*KAR=I-M!\(2S +MH1`)U-_43!QP@2?TY36!`,FTEU"+G+UR\DX'0Z_/'SUZY'L\<0WB\\&R.5`B +M`PTC#+4,\88"E0R2=P3'KS7/-:4F*.?&)JJ,1Z$$E`D\_G]:V`NESW?*QT"[ +M,@OLIS&%#DX>O6[@;#9Z`ZT%+:?63G07XHA.O=(S8L_LA_@>\]+1T#1TE;]' +M*1$!&)GM0DS/_Q)^T>D@@/DD!>X+:`L4GV%@V((T>B"H_:6L;'9EB0&Z^8*/ +MS-%;`K&EHFW1R0IJ1>OW_*'\4"G9B!S)($G=ZU?\%SA7*9M^EL80./SNR$4)E*K:0!TT,*59F65;WNQYN2Q. +MZ,L"-H?=(U3A>/=1R/Y!KMGFG!/%DY8V50XA+>J82,Z"D#JFC +MD'!XZBB48\M\!4L<-&XPOV&.MBD.".V.?&$P1P4SEWX]XVYY/DM9NEM8RJBP +M@JX`MF#PDC*4T$Z1ZZ%(V_XY#NX1+B8%\ZL>P(`W9GWOQR7:

    +8<3CD!K` +MP6["#A8H,+&2R38"$I3JG>X/>XN:(7?G\R3GA;7`/=)[X,@SH"RE$#HVN0_> +MN!D3^9IE^DGBJ9V+YJM@YIK6_%4=OUV8U!^^(JX8"/)T`5%&TDD1HCVQQU=M +MDJ7]J/"5:Z4Q!0D@T'X=<[2(L_>PSMH*)HHVI-L$?3^",O.&T)16KLM`NPY` +M`"J9YM+&Y^@'!?(+IPXR-`84ADYF:`&7!(*#Q@Z]BBE@.1:A^OSG:9$M^[];\N@Q3(X+WLW3&;=A2([8< +M"3P>I95^!NIMJE^YJ5&S6(J`/T!2S-,'D6)@'GHT\L_2 +MHV$04ZU\SOE')DN?ASL1NN^^7:V<[)Y\I*EYV;0WS5FYD3!6KRFYFE5CFI??*J-\ZJE,,<%,A9 +M'!"O8)6/WUW=W@R<[=$$<1D1#G@4N:YEA(!4?2'_\H4)K'I`KQX_T=8OD1V$ +MQU'F.652T;$^E!V!\%GRF>6J@J%#FTW+I/CY_;U,E7%R2F"W:/F]OYT`W/7T#4Z=_; +MLS/5@2B`\A(2,WZSA?974DF3$<^RA?!ACA!^T/=BR4X+!8F3^V075'/DF0UX +M9\E0VYNLUQJ.-$%SA9?S?8%ZQ#'_7KP% +M^D[YB#`YBS9'R-1]I1"2N1X`F!NO\YU2FW]K[:,QOI#>G6&B3`V%ZV1 +M>]#E':8;?F6OG8V^TQV;15_5-.W1-`CK,=C))^_Q_AF]F.H1SAN"WK^*@1VT +MQ-&^[`74F:5-]?1;2U:NB`W][#)$@S:G:#QRQ9<)?V;4ZD7!-M(9_<.&X+E3 +M&KHS/ZT,"@J!4[HEGW.#\NPS=&7V&Z>>=?0"-TW"#E7/V3CW_*1@*VI;B@^? +M21EF6?.^)_UN@CL82I]HIT<;:R<>@2+;+#RMMY6I*/U]FZGQINO=(L/3*#_E +M5U3,F\8F_^)ZI`^%#0TR`*7(=M'GAH1Z&W%%SMK%$S(`QE,*^6?.6MVVEA^H +M`Y>:`Z^<*,$Q<"02QX)QTZ;O9%YPH;K('*2`L;>F?*ZC0C^Z=G4^9(Z)%V9Q"G7_SY3!5I`B]/7H@7 +MU]O`LQK!E,?3E$805$)KX47&Q-WX3RB7XV?S87X*S5;_:NQM5*7B3"56.2*M +M9KX!S[ZZR'YP-%++:"-V8:N'\Y%8HAP+$#WA*[C(+H9/)APU4E2Z:^Y:R%Z^ +M]Z3`7?QMK@75!*C8YQ^2P+0'?Q"%Y#R%#PY?T$G""_TAOMOQHP89`J)7F\@W+<_BQ/#K!1_LAG]AD:E2F-"8 +M]9EGWWO2_;$9R'?7$LL^Y]2H60AX..N +M#3IS1:;`LGOI![!L;C&Y)[`!-[XN#[5[/KF@*1866&"ZCC\[#$*J]$%)"`#2 +MV0FJ(>E2E8+H%]-05@+: +MQ0^"T&".^`;FHY$`!9IT1:&R$ENRQ2$>1 +M%A#&*R\466G@[JE7IH$`0$QBN#^#<^>3*/4@&>V59O$BH3JPKT62;#2"-^$8 +MUR_#`H_[QL4]`XF&>SR3?@@3BX<*_J +MGC<'%5I0!UKZF7<7PSKFV!,]9X0=>Q\YS"+>G+V;#>"-"%-)1:#D=1.TV56\ +ML3$1T/BORY6(_1U4=%8([W3PHIR[N'6+5L.G:NJ`W=78>FS+G)>MXH:?N@U` +M&MJQ/P!F)D8/IFOA`*`51"H5&SFB:@@E2%,G)!O<[(BW%`Z+FD5DG@I*@0]` +MX%3[Q1SH?1"=E.^ICW38DTXRZ7,1T=&6/("@U*2!7J)J.,00T&7*=+9DO<0Z +M3W$.49(DMD':OZV[$'2VB+GR@7\@71JU(9?8F*!<3)&)*)@)8"[%UCD/\7O> +M/4EKE,440IR!+_!)AH")KL8J\Y1[0_LR4`I@JMCEH'M%T)8'[3:.7`6S#1:?%1# +M*>54`%8Z2P4#]S%B&_V61"Y,)("&PB4(`.?[C%?-J(?!-P_VKA:8H"G!Q2H] +M.,.F'`T0J5+ZRVZ85AWI*N1B`8XOP7B<'#.;CJ*`G$9U%=O3/OVUF-OYYO3*G0K<[Y"%JX!X'#3S>P91<8 +MY-M-Z(0"Q_5-057,XS7*28Y')2*J7JJ_YD_SM7L@9-%NE)FN69TZ[;P-E8#\ +MY4AARJI`$6'](`O\MU7WIY<+CZ"*D/S-9[.=><+5K5G@WN"`B8:KHE*C_Q;\ +MH_)G++W<[U"$K08NWP\U=SCFS"-;X;)SD4^*G#,CA('):_*S3*`"[MN"U\78 +MA]Y^<=^7K^$FRTG\'>_SJCL9T$M"4ZUHJ/0EA^[PFK7Q;A(]-XN"OH#6$UD_>SG[@H><$6=?N#&-(8U!+]F`_72)= +M<[]`.?T[V@.OXQSLP$L<;_U]<"S%67%`?#N/XP24IE*&:FY//]><-A.`]LU1 +MCP7C['B^B/\F5@IV24JC-_9TC0V_8E&&P13B^PZ`,.60P+_0YN4)5L%`9^^! +MG[/#2>670#$FI9ZWD$^H[Q4T5X8!>3*5O-JJJ-@U7'!G(I[[1".^J"/]&L'` +M?EZ/V4Y=41%=ZW]WF@%YSJW-2(I?"GK[)$+7C@I[D?FE2XJV#'61D;M2X2V. +MKG4IM.HTA(%3TZE:I-U)?SC>R.CBE3.!;1CDHOWK-,3R+('J;Q9TK_=H>)E9 +M'=DFIO'7<4DPL-C"JG2$'P$^SO*'",7=;Z4M--IOR+8L77KFY%V);CG'\H +M4(:WG65D!7T1\L&YJ[;J\Z!!]!>_8L@4\_+%1F)!]--)`88$?&?TR&;0;@%< +M8[JA=KB)Z^:U5^;UT#O:.WTN^*GWC)M);IF@=[&ANVG)0HN6WI6)5XC5T#-U +M5/%BTU]+&LQ%-ZL#+31#NZ,W6^VLT+E"2XDPCM]2D?N.6=O3=E'0I3B+-)_88N2D[;@(>GVU +M8<>K^H:>-3)/469((HJ<;6CJ=KK2X!'!\58]OVRT\[1DV%U]]+;#PU7;O9`@ +M&L;N0[U2Y@W2A-BOF`(W&&K0H,S2"5<>AR;@*^<,IOOFQ!U'L7^$Z\_D.?L;QY3J$>,WN$Q\]NFT?*;N +MZG_M#+:\_QZ[S7@V;?[0&J6__G*)]4W)`\_0^XZ/R3:#K@K6:\'O[:!@B5S1 +M1B6L!7`+;.HUC9J$NGM(-^_$H//_Q^>`S:\O3"18!4__4F7RH')EA?'O33NS +M:7&?NTW9`?JJ6LS?_X^IPYJ!Z-0=WP[O,1K_W1`?[$7WE-XB.2OL-@GHY[[M +M]81'*WAM.[/'#)RHM!IZQG]$)PR][O1P[*4$8GX.\RJC^Y!)@8_V`(]5%ZF? +M!0$W5GHLA@ED:VDN?@V[C,*97#R42-NTMYJN?T'&^9*DHBGSW7<>Q=B%,(O& +M;%V222=;"N<4?;@TEI_N7=;L5%TK7H#G%&V$0W![+EJ#/];-J5_:YB?0ER`E +MSRD3-"*;?]I8P?4?,0/%B;.-+Q*NFZZJ,3HU)%7["@!H"059C#IY""-+"[C- +M/08(4I>EA*`;@(<$$AKE?.DQ,&/UQ0/K.V5HX5`-"?VMV*WQP$G>?H1+KU,L +MQ3-+`GS.=>!$H2PGKS.OOBUK-<9'X/"]'FR$S]Q4S@]C"MUX84HP;6F6I$9P +MY<5N.A]:,3AT2Z:7X!.LW"SGLX&1WZ^6:U5`^%VJ*"HJ)2Q>R<@`'/+UQN+Q +MY`D;S.@[Q97M"YI^`V2LX019:A-4J-C<8;Q+2=O_VI+4_CYU$P$T]ASI5Z2N +MP1\(W4NS*/O8Q1Y6/EUN*]U($#<#']T?-7OZBK:C5*8$#\.\`.?4B6B?0H.V +MGOZ2(30C````OXAG]JG_U.L^=."0,0````````````,`````ZVGV/A0P!P#M +M00``=&5S=&1I61IMJ;G<[Z6"DBFSK*16$E +M-Q31OW?HQ-Y&TBESE5=DVFTW&]`WUZ-R-,JS5W=>+E5=6_BE?P@_5^Y56:"L +M($`^[S?PV_AZK/Z?'U_X_+T^W=]3_AKZVM^?C]70;=G;7Z/)8UW[, +ML%^:*>*2_!'DK<]_A]#WF/V'\;FUMXSP>;W;EG:'H6?C7W/_/EN_W\_A]7P] +M]G*FS7.1>%]GZY&GA^<^MQ3WH_*_;XH)9H9_/AGNU_Z>$D2SNV?;N>CS:R_E +MI5]^UT67']VK/PWG"9[8K4L/PNW8K<+_CL>-]_4^5^+YZOAZGM>K>W/ +MW-S;Q[V=?8V-?[]G[_+L_4\?W=*U^MZ7LVO?_7'__N\GW8\W\[V:E\[C9MJW +M-,GT?PKU^A\'_>"#AS-?Y?O9Z>&*_^3^O8_#\>C?_T/J^-/FKVI)YY+Q^W7_ +MICSV;'V/NL+*0F3R-`45O[_2(KOAK/S'\M]>W_C +MCZWI^F*>@R6'IS_]Q[>6X3;X:5<-6$^.]N=V*N8R]E')-@@MPKD& +MSV^Y]GN&?V;/^[GU>N45:R)$"Y>LJYGF]/PV_T?]H4`\_AAS+?+?HFV]W>"M +MMG>1?C8?]63-_?_9B`LB;M&\LES#;)]01=@87X^@((SKV^*+DHJBF?HUY7\P +MF9R*7]G[>>;!'#\W\$4(T1)=?F^O/RY6]+GXH)WY<.:K(M][*^_AO!)IP-R* +M[=Z3F.R;ESE%GIEO36']H8_I,F'AXND#1=`V'/FF6],F&*B@C>!U,F#'/\A4 +M$Q17^&A2',5@R#/E-!?N)]>5>7,I^I,^NX9^FPEI[(-!#US,3XLB!FB#CRH^ +M=#D_,Y1WTW;1#1CBS$`W?Q3>FU?SNS1<-^BJ*WE].PB4+R/QTF.K9H](-;6L(*$7SHKK/39S\,>93/IF;MDTN7L4(_;$FM#N/F))6Z:)6ITBGV9B +M;-$.;*BC(7[D(^P&LYC*BA4>[Q0N:$<-AD[EH3XT,8F'D>#9$-^X?1O4[;TB +M=O,UQ;Z:!HSL[@!#X-[#?OGYCW>"R,5P?&63AE@O!PO03M?LW&)F'-B:"*3*#B@"7DW(]@4I*ES +M.UFZMQ30S)F6@D8JS)@Z[H9CG:Q280H##<*<>$D8H:Z#ED5D(**77LQ +M)851WS^32G\O:6X/;N^BAU]&Y?/X>JYLZ7X:.$,5'&_@R^XCD9T%*148GS?R_7#EUY.%PS45/1:*+`@A&@8<2D@;YR1)*JDN'",GD +MN#]%1,?&F:/7G,W.;B_"JP4F:U&Y$5)\4<=*IDV#/0'BR&O\UFSUFXJ\O,9&]%`N! +M#')JJ=U*U\K\,/A!@&G_K19&<4]=7?XH6-6*D9QK#@T=O%@9<27=S,&]0CFM +M!;N1XO*UA_=QEV"W/6?EJ>+S=5/<'"7Z<[R +M$E_&Q&*=>#K!4^%@Z!_ADDN*Z2D9#\J=..O%T>$]##'R,8`*E!SNWT92'&ZD +M+\\9?.G*W7=2YV<,X8C?@7PA@M^\/\(@!(L8?CH;HOJ.FT-22];[R`?+84`C +M?2G92OU`O)F/$#KW%^5.CM[PS]\KZ"[;/'L_M;DP8F>*KP6+?Y;'X#U=IJ%F(GR"`_ +M!#M"*M^N$(@9[&C^-?SZ^G^B,.MI]0N0-E__I_QULC]*R-D39U?/7V.RT)ZU +M4BV?O\F2X@J`S$>-FP.&&>X&]&>7R?MQ0QX.IH2Q]0!?986K;27HIS!_'G:: +MMGOH]):D+[\@"7W`\=%F8K"Q^:--0SV.L#AW6'7MT!PL? +M82E6D0,,U`ALSPL!H$!/2C$F$)SQ?;,!A!J9=`1PU+,M&!$&XI. +MNTM1/8XH,"[%G#G1K/+%N#K'Y$K6H:*PK.8#6E!#*XJU4!%C2H.=F.$M)?&2 +MU]@:`FG+Y=1MK_TRRD71!+(E`PH+#<[G)D$]J(Z'^2WJ&)(Y.'$LEPJ"3];V +M/>C)3NQ$`9`!OD?R77W9LI0[Z.55^69K<;$H3EV +M?MBWE09(R03R^Q,XTI9.3K+PB9&P9@BJ"5@0` +M&NH*G0J_NXKV'A&&,S/!8+A^R]OI*G:29SF.4WTVX6;BG%OW'QKE2( +M^>P)-CT/02N:=$J#;S]PD,9)+2MAJ?I#,BID1V8`UCT5XOKS/!]0'^&ZX>&` +MJ@YRTT?PY6DN:`C1Y`4&=;5J!]>PL!(%9)N>4DJCF(H5S[9D)<$ZN9M*M\BJ +M"3YW1?2+`BXU9Y72"::*`U^^*U$DT6B5N3/SGRP_M_]N_%LAJPUO=]^YP6=S?LZG4T%JM@U_YZD1;6_FD1D5)?#@=B)O_SUNIB513J:D#_G;I7 +M@*4>`4*K4U=5_^&1O?\O;[=7RZ;U]P@,``^U-K>]7LW?[YI?A_:MU,1U/6=R +M*;,X4NIM`B:0HQP!PKF+U?^5ERH#['*1+82@=YP4P7>#&H#@_X6E2R.F1'(< +MR%9'&O0[&OL^37Z^G5_`2]O%G57Q@H^JF_/QP*"'U(&!Q8(> +MQT"X5=^CT.8]3'9K/E?=]_KUO=M>_=]86RL>[UK]-67)J_@;,[:B9)HA#M*S +MZN8_^C_RS9=Z"W+(P,Y3*)12BF:\.$O9PYB#0\P<7AM:<2M9?DW(D<^H#D29 +M@T!AN9AEKO]^)<(=2M>#.'Q6J'SO?9WQ0H?835R@HE%!H3@ZI`#Z]HSKI +MH.DL*4A>IW\VJG)HP<%T!.!IHT"U"A_=W +M_@83+:$3V9=<+0'FDRM9A97[VH?6J[BIO\Y)?:-USW^G$!"/31!TK/).VN&4 +M9A$TFH"!0!FH?L]1/FRCIJ=_*Z.C!?EJV'M^$IF;HMFA%JU,*/B0;0,*JL22/3Y6!PJ`=00P.(QH^S-$UG-35'9OV,6K)*8YH8YBQ9C +M54=:KU,.3.9.H9X`O6SP$V@>$"-JHO+*&D(BN8YXE?/CE*BZB5UFEC/RJ)J$ +M_O1(*)AGJ&>+#7N140C@JXZ?L!V=%,OS(:7DQTA\9Y%X*Z'1HYK[N94T;E%.T +M$HY(M9R%](CU62ZQ)J5#-:E:&6(@-3:N#J?"^\>10%=MSUU<+O620$15S2[1 +M"@6!=D4AM"8]N7$8J*&YF=2CK`AD>=#IUX:-P@SB5@5-=&M$34O6E&LQQM>Q +M.<($17Y3U.6=\0I+DQI@[T%RY5PI+H=RSQ:+M@L3(/DAF;,<'TCL`49@,1Y4 +M\,B2GR<3\C#-T5C:3E0:UE9@/KAG,9\_$SBTE6I[[/,CE8][=_MN>CU4.(]O +MCC0V_[@7;MRQ8!-PS(*"(H$STDXKU=8_@#HUIH`^8%GB@`>_#R +MA#6`CI+9<"$6U4FD?LDDA:,#/*J\')-RQJ]XG(/47!T*[Y,)`4[UW@5^5*TP +MC/P"KB,A4EMU*:[#Y8EP+*^^)!_P.UF3NVD]X/EIURBWAE3D4BP$*P[WG;`0 +M--5J!KAKO)"W;K9U8_Y?DJ`I/>!KRA)-)D?HG]/HZ4Y0:K!.TU?`X\5&X'5IV5K,JQUIJ:Q8XMZDVES4M=F5F.B>#DAT^:::B,:$.%&VDH=D%V&/$4$A^ +MDBLG^SQI355JCM'FDKV8Q%\H7.(T`2X;C[RIJ>9@6E:6T9;:&8;FCC"CE+61 +MKE'#HHZUC2\=/HL%'6!*C`M+`E_J7\=5BZKC44..J%N^FWWH0D&980UZ&\BZ +M=EQ7^*=G!.T=BEG)RV4>).(G^L:H!`SU65"X>&>1'X@@T`L\84OBO]6A'CY% +M@/O)_T?"IJ4JUPW%08R#H:S,,H,.4NSNJL2NB"C"K0?609[Y)UHC`Q_+EN8S +M-J:2/"/@9/CK+F]J%"^+'Y'`@KXN6E"@-\[V/RD)]OF``K"#O&"DYL#C&E," +M/,=OX6Q'66%[AFT>.`;BZ])-8-=@F9$T[>AG?Q#HO@X/CD6SZ_AO>YXT(UM$ +M9)\89:7O\R5[[^(XZO+)YT*U1-)P-T-JO?Y>ZA2T)J$E]A@2"V`UY^PI6$A= +MHXI*\G5-A]?=#E/EU?*W3'^JIK/J.B1)0JYV16&I`U/-N%Y(5])+YP+U5F%T +M@RO<+)2J]H%+2(`)'1P]18#BC2Q`",Y'1X%Q*>!I;-S&L1P+RLOL'RXD6H0' +MQ2H6)9R4AT\^(P2#V4A +M!^ZP8&WA[`+(\`KRS\6A%S6>Z^?SS(.,'(J6+(],-T(*1ZIE;X@HW0&1KS0L +MZ<85@DP+5;;_/0D+Y.6MT6&=!F4E]KX`U5[I-P58'O+HM>0\X%;Y5T-M.S]] +M+H&SH#2DE>:.B=@-Y)SQ26QZ&*&Z_7?56]7H.0!/V61XBQW?59EK]BXV)5[,N;LV]#P_;T'E,W0-;MB9H&![4H'3N +M_%](?M%,XCW\S-W,J>X\9UI35L3I(+*C[')+;&;X/7C5FA'B +M*[H\PNH-IZFV&5M+244Y/@C6V5A>2W$@YBFY8;#V]U[9H$W-#<-SSRI +MH^>31F\;V&:=*-0RV.7IY#^ZV"JLX13H,7<%&X`&=XX\P*6W"%`YN862'3QS +MBQJSMU[LN+$`4=4P,K:<<-5IVIM#MO;L#,$]]DO:RW'-'8H.)]HBV,.%"0YO +M'\QKERWD2;.M3#\%B+J!SGL(K5C.>(A;R<+)*1#Y8-#EMNK,=Z2WM$!2`")V2$"R!OLV(U3"]W]`!(:! +M#6<]@]?27!)6;<&:!03HSN5;YVY)C>I/1WYV.WAXD+W-&.W.Z`RMOX(VNKWN +M@6,]$?$YX:F)XA-6LW^&_N*!.>$9BED8S?4$*5406C'2'Q[[G#0DQ&G]4(;6 +M?T0>C0VM(7]RQX3?:+2)J:OE5/QDUQBOHMVO3)>DHK>TDZBVG+,Y'_X*:;'W +MS:*:7#E-BS!;P$T!%>,FC:%'?-_-,@NLZ&ZJRJ6*H-5C-*B"G"[+R*P\985O +M\=`H^7B&O\V6$W'\*&C6%0FJ55IE<*JD"O&D4Y"EH\Z-K&&F-_-OK`J=\WV9 +MGCJUVYK&XHT5H6!:N^D,*#M;:2]I\(P?3Q.W="@O%,*J([?E*)07*<*\+.WF%6VVB6W0UV,9AP +M6-7F^`.$1.K->EV0V?*2;6G7CS-`#4=5[6=9GI,H`@KN)+>*@N +M&KW6L]G&<33PNY!9G'K8O:3!#9=9BY@_P,XLMSOJT]P^X%AC)%]]7HC9#SZG +M37/@9OHNP2QXWC1V(-M8C`%.,_P0VXZ"+A9#J:]Z-`B"R6@577;36U(&SN'? +M-;"+'*>`DY^MT9H[296"#300JKFOIY%(U,@\^%/(M5;3GTQO4VV>/W;N>!OK +M:FJV]R4Z=*MBBJ+/%D/'G,>G#0R++M@SFB+F/#%>Z]$;&SLF\94M2Q`\MSF1 +MG\9FZ_0C(#A2QF:JET$0C9EJ&<*EH=6=%+8+Z\#_WJJADJ\#%W9CS1*9"L94 +M_6]CX4@\T9&>]FSVO-MVG;-"<*=7U/8VDI;.C8\GZGJ)$"!,*L0J04"VXE\R +MR[#FEKY#_M9\IMQ5H@]MA:EOOOP0EY&OEAV5=+NJS1C6QIT:ZGI&^N-;O +M=CIE*FNK\J93!#;$X`."6^@BX>(NEN4+;U!8N[H`UDJ"G:(&7`=1!CFD7W/O +M)]S!_1P.YDTGW55@XF#=T?5Z")ARQB7+VV +M&YWU`BG_Y`'"N0'CL_W[_>ZL!S^+(9.G^7YZ&Z9Y*=I-W6'NXO!A.>Y"Z1K\ +MMK%/#-I.F7-)'+!5QNU/3'7K+;479/L16X:1IYJGY\@]-."QGD4('I;6YS"3 +M2:$#I*ZA5O5(P76ZCNW01(2#J@H-;X\2]9F,_G2=6#7K;;R63\$`XJNW^+1?I+Z%,,AR*,R2:-6$?3 +MU-IZ[*-I&].AW+[B6S2)>&&J]S:>>UT%.0981-KV`<(.-"WHC=44R\W(O.!G +MIOJ:.1"S6^7"=AFT.NI38@<>\;,OFIZIDT,AY:;+8;1DE"^"N&R1,M(;2OU* +MK];K+9=B7%`(_T1+0M$=H7KN27_7A^GTQS(RI@/@?QV[#*?NU>=`R:. +MN4A1M!^S1F"<%^KD%Z#A-\O;T(C6=R1DR +M"T;#41I(#6I6]L$S"W6W3=]9MPW(VCG<"8TLWEKC+?1MF!3@-#>GHH16C3=H +ML47Q'H'TDR<3^3'TW)8E]PMJ.A#MR&-"P-IH(88*A9<(0R%[H[^?D*,5V&B9 +M'?S]+X<.8Q&$Y[(ER2<<+=EI./N8A/(#\.''7 +M5B92ZDY#)K"[50-EB*4KHO,<&.]1TSO09W)HG>57;VCI8=.8:6EON]'X9 +M525-&NC$TN\Z=4N34'77V!RAZ63P[4+.R2VI:OP2%NJDR_D:&7/E*BJ2 +M%EO;SUA]TQJ6'_;/20MN1LRIKO\"H6ZTH"JL'5N'ND<$O#.!G4_VMVIY4K+> +MD;RCZGV#>`M(Q91ZF7+M&A\BTGAU+N91$9ALO+[S`=%8\UJ/6V`2Y8#&^,M& +M8GTHZGC5*GU8!Y+V!26*0]"=!`<"B-4.DEI"Z%-IY=S`>K9UJ?X2HZ;4N9D_ +MAK(`0S(Z/W"EWA^D6`DRT/SLO5="QS/F\X1887E?@:J[-0;'&UQ-ETG.5 +MMTWZT->L7R^G3"R'B86E`:-A4P?N"?$?YZ11$5)\*ZYZ+44YLGW?5N_K(58Y +M)0"0XP)HO!^J<)W@3G>I^QE3>`H,>7FPUJ9MJ2Y%#3?J:_LWV6-L1I5N3>XR +M!GS>^JTH?G?%,X8'G*>'-T`VZP"T[(P?H`WH/44@AJ>]]W2JUFLA*&&X1C8A +M!A1:"'"M1R6^-YFE6UDI)7-O\$>RYK],SVA29)08;X7Z#HI%QX;MT?P&+I=: +ME&ZK53),FU"0+9'!B:FAO6@V*N.+BFI,'L%"N>EK%+K4C^E?T%(39% +M2\DB@]C_7<=2-K6CH+=@J`*:G%3V..;7<<$H9*8BVSN5C*NA2;2DI4L)P8K(D%07B=Q0P!IB+Z+SP3VA_'!E4%-=4YQ?FF,)UAK, +MO#V*^Q3-CW1)):*=.2(>.H:8*E2$$DRV&X+!.D,]/C7H+G((,\'#5P_@(X/! +MEO'B9;U'*C;*DUE3K;1O9,*5U]UM5DVXY,ZF010,,Q1I=7,[023J7VD1>5E7 +MVG3D(X`"/AL4:7Y6K3MKFC9HXK8NRX(W$6D<[HPDK.DAH\\1:MG\=^I,U5/, +M+(T22K%U8R^H!L6VR71C#:.,M+RO`X.[*?4).3^(D-JE5'0Q4$=5K?Y_L2'O +M)-T/=6^V\K;AR*Z\??@7L00(E"+'''E=:.8VM)50G#1"%]I`IZ*:ED6F2E0\ +M6JAW2LV+F?(.*Z3,ZGYY"#M&A'Q[-<0EM-)1C3?`O3#K4LG'#I&B$+AZ6QH" +M4$EW@_>Y(EAJC'2`S&-WVC[`J.T^"`#(_HSWH7AWMUFBN#$'_$N5_\(HI\SS +M2MN(/>:@9YAT()!+`+,;``"/3@```V.F!5XVL]H^'3,A`*2!``!T97-T9&ER +M7$QI8F%R8VAI=F5!9&1I;F=497-T+FAT;6R`S'*H[3YSJ.T^#!U1#,S1%\6= +MF]T/PH[-`V-[U)/P29F;F3P#KD;FQC9X>MJ;G<[Z6"DBFSK*16$E-Q31OW?H +MQ-Y&TBESE5=DVFTW&]`WUZ-R-,JS5W=>+E5=6_BE?P@_5^Y56:"L($`^[S?P +MV_AZK/Z?'U_X_+T^W=]3_AKZVM^?C]70;=G;7Z/)8UW[,L%^:*>*2 +M_!'DK<]_A]#WF/V'\;FUMXSP>;W;EG:'H6?C7W/_/EN_W\_A]7P]]G*FS7.1 +M>%]GZY&GA^<^MQ3WH_*_;XH)9H9_/AGNU_Z>$D2SNV?;N>CS:R_EI5]^UT67 +M']VK/PWG"9[8K4L/PNW8K<+_CL>-]_4^5^+YZOAZGM>K>W/W-S;Q[V= +M?8V-?[]G[_+L_4\?W=*U^MZ7LVO?_7'__N\GW8\W\[V:E\[C9MJW-,GT?PKU +M^A\'_>"#AS-?Y?O9Z>&*_^3^O8_#\>C?_T/J^-/FKVI)YY+Q^W7_ICSV;'V/ +MNL+*0F3R-`45O[_2(KOAK/S'\M]>W_CCZWI^F*> +M@R6'IS_]Q[>6X3;X:5<-6$^.]N=V*N8R]E')-@@MPKD&SV^Y]GN& +M?V;/^[GU>N45:R)$"Y>LJYGF]/PV_T?]H4`\_AAS+?+?HFV]W>"MMG>1?C8? +M]63-_?_9B`LB;M&\LES#;)]01=@87X^@((SKV^*+DHJBF?HUY7\PF9R*7]G[ +M>>;!'#\W\$4(T1)=?F^O/RY6]+GXH)WY<.:K(M][*^_AO!)IP-R*[=Z3F.R; +MESE%GIEO36']H8_I,F'AXND#1=`V'/FF6],F&*B@C>!U,F#'/\A4$Q17^&A2 +M',5@R#/E-!?N)]>5>7,I^I,^NX9^FPEI[(-!#US,3XLB!FB#CRH^=#D_,Y1W +MTW;1#1CBS$`W?Q3>FU?SNS1<-^BJ*WE].PB4+R/QTF.K9H](-;6L +M(*$7SHKK/39S\,>93/IF;MDTN7L4(_;$FM#N/F))6Z:)6ITBGV9B;-$.;*BC +M(7[D(^P&LYC*BA4>[Q0N:$<-AD[EH3XT,8F'D>#9$-^X?1O4[;TB=O,UQ;Z: +M!HSL[@!#X-[#?OGYCW>"R,5P?&63AE@O!PO03M?LW&)F'-B:"*3*#B@"7DW(]@4I*ES.UFZMQ30 +MS)F6@D8JS)@Z[H9CG:Q280H##<*<>$D8H:Z#ED5D(**77LQ)851WS^3 +M2G\O:6X/;N^BAU]&Y?/X>JYLZ7X:.$,5'&_@R^XCD9T%*148 +MGS?R_7#EUY.%PS45/1:*+`@A&@8<2D@;YR1)*JDN'",GDN#]%1,?& +MF:/7G +M,W.;B_"JP4F:U&Y$5)\4<=*IDV#/0'BR&O\UFSUFXJ\O,9&]%`N!#')JJ=U* +MU\K\,/A!@&G_K19&<4]=7?XH6-6*D9QK#@T=O%@9<27=S,&]0CFM!;N1XO*< +MOQ,V+I597=%5*XV'MJ.?B2!?VVARCU3,A8.AG$54X;[$=HX-*V"D)WW:RZ6J +M?B89CFR08V^J(1\,KS?8YVG>UA_=QEV"W/6?EJ>+S=5/<'"7Z<[R$E_&Q&*= +M>#K!4^%@Z!_ADDN*Z2D9#\J=..O%T>$]##'R,8`*E!SNWT92'&ZD+\\9?.G* +MW7=2YV<,X8C?@7PA@M^\/\(@!(L8?CH;HOJ.FT-22];[R`?+84`C?2G92OU` +MO)F/$#KW%^5.CM[PS]\KZ"[;/'L_M;DP8F>*KP6+?Y;'X#U=IJ%F(GR"`_!#M"*M^N +M$(@9[&C^-?SZ^G^B,.MI]0N0-E__I_QULC]*R-D39U?/7V.RT)ZU4BV?O\F2 +MX@J`S$>-FP.&&>X&]&>7R?MQ0QX.IH2Q]0!?986K;27HIS!_'G::MGOH]):D+[\@"7W`\=%F8K"Q^:--0SV.L#AW6'7MT!PL?82E6D0,, +MU`ALSPL!H$!/2C$F$)SQ?;,!A!J9=`1PU+,M&!$&XI.NTM1/8XH +M,"[%G#G1K/+%N#K'Y$K6H:*PK.8#6E!#*XJU4!%C2H.=F.$M)?&2U]@:`FG+ +MY=1MK_TRRD71!+(E`PH+#<[G)D$]J(Z'^2WJ&)(Y.'$LEPJ"3];V/>C)3NQ$ +M`9`!OD?R77W9LI0[Z.55^69K<;$H3EV?MBWE09( +MR03R^Q,XTI9.3K+PB9&P9@BJ"5@0`&NH*G0J_ +MNXKV'A&&,S/!8+A^R]OI*G:29SF.4WTVX6;BG%OW'QKE2(^>P)-CT/ +M02N:=$J#;S]PD,9)+2MAJ?I#,BID1V8`UCT5XOKS/!]0'^&ZX>&`J@YRTT?P +MY6DN:`C1Y`4&=;5J!]>PL!(%9)N>4DJCF(H5S[9D)<$ZN9M*M\BJ"3YW1?2+ +M`BXU9Y72"::*`U^^*U$DT6B5N3/SGRP_M_]N_%LAJPUO=]^YP6 +M=S?LZG4T%JM@U_YZD1;6_FD1D5)?#@=B)O_SUNIB513J:D#_G;I7@*4>`4*K +M4U=5_^&1O?\O;[=7RZ;U]P@,``^U-K>]7LW?[YI?A_:MU,1U/6=R*;,X4NIM +M`B:0HQP!PKF+U?^5ERH#['*1+82@=YP4P7>#&H#@_X6E2R.F1'(H^JF_/QP*"'U(&!Q8(>QT"X5=^C +MT.8]3'9K/E?=]_KUO=M>_=]86RL>[UK]-67)J_@;,[:B9)HA#M*SZN8_^C_R +MS9=Z"W+(P,Y3*)12BF:\.$O9PYB#0\P<7AM:<2M9?DW(D<^H#D29@T!AN +M9AEKO]^)<(=2M>#.'Q6J'SO?9WQ0H?835R@HE%!H3@ZI`#Z]HSKIH.DL*4A> +MIW\VJG)HP<%T!.!IHT"U"A_=W_@83+:$3 +MV9=<+0'FDRM9A97[VH?6J[BIO\Y)?:-USW^G$!"/31!TK/).VN&49A$TFH"! +M0!FH?L]1/FRCIJ=_*Z.C!?EJV'M^$IF;HMFA%JU,*/B0;0,*JL22/3Y6!PJ`=00P.(QH^S-$UG-35'9OV,6K)*8YH8YBQ9C54=:KU,. +M3.9.H9X`O6SP$V@>$"-JHO+*&D(BN8YXE?/CE*BZB5UFEC/RJ)J$_O1(*)AG +MJ&>+#7N140C@JXZ?L!V=%,OS(:7DQTA\9Y%X*Z'1HYK[N94T;E%.T$HY(M9R% +M](CU62ZQ)J5#-:E:&6(@-3:N#J?"^\>10%=MSUU<+O620$15S2[1"@6!=D4A +MM"8]N7$8J*&YF=2CK`AD>=#IUX:-P@SB5@5-=&M$34O6E&LQQM>Q.<($17Y3 +MU.6=\0I+DQI@[T%RY5PI+H=RSQ:+M@L3(/DAF;,<'TCL`49@,1Y4\,B2GR<3 +M\C#-T5C:3E0:UE9@/KAG,9\_$SBTE6I[[/,CE8][=_MN>CU4.(]OCC0V_[@7 +M;MRQ8!-PS(*"(H$STDXKU=8_@#HUIH`^8%GB@`>_#RA#6`CI+9 +M<"$6U4FD?LDDA:,#/*J\')-RQJ]XG(/47!T*[Y,)`4[UW@5^5*TPC/P"KB,A +M4EMU*:[#Y8EP+*^^)!_P.UF3NVD]X/EIURBWAE3D4BP$*P[WG;`0--5J!KAK +MO)"W;K9U8_Y?DJ`I/>!KRA)-)D?HG]/HZ4Y0:K!.TU?`X\5&X'5IV5K,J +MQUIJ:Q8XMZDVES4M=F5F.B>#DAT^:::B,:$.%&VDH=D%V&/$4$A^DBLG^SQI +M355JCM'FDKV8Q%\H7.(T`2X;C[RIJ>9@6E:6T9;:&8;FCC"CE+61KE'#HHZU +MC2\=/HL%'6!*C`M+`E_J7\=5BZKC44..J%N^FWWH0D&980UZ&\BZ=EQ7^*=G +M!.T=BEG)RV4>).(G^L:H!`SU65"X>&>1'X@@T`L\84OBO]6A'CY%@/O)_T?" +MIJ4JUPW%08R#H:S,,H,.4NSNJL2NB"C"K0?609[Y)UHC`Q_+EN8S-J:2/"/@ +M9/CK+F]J%"^+'Y'`@KXN6E"@-\[V/RD)]OF``K"#O&"DYL#C&E,"/,=OX6Q' +M66%[AFT>.`;BZ])-8-=@F9$T[>AG?Q#HO@X/CD6SZ_AO>YXT(UM$9)\89:7O +M\R5[[^(XZO+)YT*U1-)P-T-JO?Y>ZA2T)J$E]A@2"V`UY^PI6$A=HXI*\G5- +MA]?=#E/EU?*W3'^JIK/J.B1)0JYV16&I`U/-N%Y(5])+YP+U5F%T@RO<+)2J +M]H%+2(`)'1P]18#BC2Q`",Y'1X%Q*>!I;-S&L1P+RLOL'RXD6H0'Q2H6)9R4 +MAT\^(P2#V4A!^ZP8&WA +M[`+(\`KRS\6A%S6>Z^?SS(.,'(J6+(],-T(*1ZIE;X@HW0&1KS0LZ<85@DP+ +M5;;_/0D+Y.6MT6&=!F4E]KX`U5[I-P58'O+HM>0\X%;Y5T-M.S]]+H&SH#2D +ME>:.B=@-Y)SQ26QZ&*&Z_7?56]7H.0!/V61XBQW?59EK]BXV)5[,N;LV]#P_;T'E,W0-;MB9H&![4H'3N_%](?M%, +MXCW\S-W,J>X\9UI35L3I(+*C[')+;&;X/7C5FA'B*[H\PNH- +MIZFV&5M+244Y/@C6V5A>2W$@YBFY8;#V]U[9H$W-#<-SSRIH^>31F\; +MV&:=*-0RV.7IY#^ZV"JLX13H,7<%&X`&=XX\P*6W"%`YN862'3QSBQJSMU[L +MN+$`4=4P,K:<<-5IVIM#MO;L#,$]]DO:RW'-'8H.)]HBV,.%"0YO'\QKERWD +M2;.M3#\%B+J +M!SGL(K5C.>(A;R<+)*1#Y8-#EMNK,=Z2WM$!2`")V2$"R!OLV(U3"]W]`!(:!#6<]@]?2 +M7!)6;<&:!03HSN5;YVY)C>I/1WYV.WAXD+W-&.W.Z`RMOX(VNKWN@6,]$?$Y +MX:F)XA-6LW^&_N*!.>$9BED8S?4$*5406C'2'Q[[G#0DQ&G]4(;6?T0>C0VM +M(7]RQX3?:+2)J:OE5/QDUQBOHMVO3)>DHK>TDZBVG+,Y'_X*:;'WS:*:7#E- +MBS!;P$T!%>,FC:%'?-_-,@NLZ&ZJRJ6*H-5C-*B"G"[+R*P\985O\=`H^7B& +MO\V6$W'\*&C6%0FJ55IE<*JD"O&D4Y"EH\Z-K&&F-_-OK`J=\WV9GCJUVYK& +MXHT5H6!:N^D,*#M;:2]I\(P?3Q.W="@O%,*J([?E*)07*<*\+.WF%6VVB6W0UV,9AP6-7F^`.$ +M1.K->EV0V?*2;6G7CS-`#4=5[6=9GI,H`@KN)+>*@N&KW6L]G& +M<33PNY!9G'K8O:3!#9=9BY@_P,XLMSOJT]P^X%AC)%]]7HC9#SZG37/@9OHN +MP2QXWC1V(-M8C`%.,_P0VXZ"+A9#J:]Z-`B"R6@577;36U(&SN'?-;"+'*>` +MDY^MT9H[296"#300JKFOIY%(U,@\^%/(M5;3GTQO4VV>/W;N>!OK:FJV]R4Z +M=*MBBJ+/%D/'G,>G#0R++M@SFB+F/#%>Z]$;&SLF\94M2Q`\MSF1G\9FZ_0C +M(#A2QF:JET$0C9EJ&<*EH=6=%+8+Z\#_WJJADJ\#%W9CS1*9"L94_6]CX4@\ +MT9&>]FSVO-MVG;-"<*=7U/8VDI;.C8\GZGJ)$"!,*L0J04"VXE\RR[#FE +MKY#_M9\IMQ5H@]MA:EOOOP0EY&OEAV5=+NJS1C6QIT:ZGI&^N-;O=CIE*FNK +M\J93!#;$X`."6^@BX>(NEN4+;U!8N[H`UDJ"G:(&7`=1!CFD7W/O)]S!_1P. +MYDTGW55@XF#=T?5Z")ARQB7+VV&YWU`BG_ +MY`'"N0'CL_W[_>ZL!S^+(9.G^7YZ&Z9Y*=I-W6'NXO!A.>Y"Z1K\MK%/#-I. +MF7-)'+!5QNU/3'7K+;479/L16X:1IYJGY\@]-."QGD4('I;6YS"32:$#I*ZA +M5O5(P76ZCNW01(2#J@H-;X\2]9F,_G2=6#7K;;R63\$`XJNW^+1?I+Z%,,AR*,R2:-6$?3U-IZ[*-I +M&].AW+[B6S2)>&&J]S:>>UT%.0981-KV`<(.-"WHC=44R\W(O.!GIOJ:.1"S +M6^7"=AFT.NI38@<>\;,OFIZIDT,AY:;+8;1DE"^"N&R1,M(;2OU*K];K+9=B +M7%`(_T1+0M$=H7KN27_7A^GTQS(RI@/@?QV[#*?NU>=`R:.N4A1M!^S +M1F"<%^KD%Z#A-\O;T(C6=R1DR"T;#41I( +M#6I6]L$S"W6W3=]9MPW(VCG<"8TLWEKC+?1MF!3@-#>GHH16C3=HL47Q'H'T +MDR<3^3'TW)8E]PMJ.A#MR&-"P-IH(88*A9<(0R%[H[^?D*,5V&B9'?S]+X<.8Q&$Y[(ER2<<+=EI./N8A/(#\.''75B92ZDY# +M)K"[50-EB*4KHO,<&.]1TSO09W)HG>57;VCI8=.8:6EON]'X9525-&NC$ +MTN\Z=4N34'77V!RAZ63P[4+.R2VI:OP2%NJDR_D:&7/E*BJ2%EO;SUA] +MTQJ6'_;/20MN1LRIKO\"H6ZTH"JL'5N'ND<$O#.!G4_VMVIY4K+>D;RCZGV# +M>`M(Q91ZF7+M&A\BTGAU+N91$9ALO+[S`=%8\UJ/6V`2Y8#&^,M&8GTHZGC5 +M*GU8!Y+V!26*0]"=!`<"B-4.DEI"Z%-IY=S`>K9UJ?X2HZ;4N9D_AK(`0S(Z +M/W"EWA^D6`DRT/SLO5="QS/F\X1887E?@:J[-0;'&UQ-ETG.5MTWZT->L +M7R^G3"R'B86E`:-A4P?N"?$?YZ11$5)\*ZYZ+44YLGW?5N_K(58Y)0"0XP)H +MO!^J<)W@3G>I^QE3>`H,>7FPUJ9MJ2Y%#3?J:_LWV6-L1I5N3>XR!GS>^JTH +M?G?%,X8'G*>'-T`VZP"T[(P?H`WH/44@AJ>]]W2JUFLA*&&X1C8A!A1:"'"M +M1R6^-YFE6UDI)7-O\$>RYK],SVA29)08;X7Z#HI%QX;MT?P&+I=:E&ZK53), +MFU"0+9'!B:FAO6@V*N.+BFI,'L%"N>EK%+K4C^E?T%(39%2\DB@]C_ +M7<=2-K6CH+=@J`*:G%3V..;7<<$H9*8BVSN5C*NA2;2DI4L)P8K(D%07B=Q0P!IB+Z+SP3VA_'!E4%-=4YQ?FF,)UAK,O#V*^Q3- +MCW1)):*=.2(>.H:8*E2$$DRV&X+!.D,]/C7H+G((,\'#5P_@(X/!EO'B9;U' +M*C;*DUE3K;1O9,*5U]UM5DVXY,ZF010,,Q1I=7,[023J7VD1>5E7VG3D(X`" +M/AL4:7Y6K3MKFC9HXK8NRX(W$6D<[HPDK.DAH\\1:MG\=^I,U5/,+(T22K%U +M8R^H!L6VR71C#:.,M+RO`X.[*?4).3^(D-JE5'0Q4$=5K?Y_L2'O)-T/=6^V +M\K;AR*Z\??@7L00(E"+'''E=:.8VM)50G#1"%]I`IZ*:ED6F2E0\6JAW2LV+ +MF?(.*Z3,ZGYY"#M&A'Q[-<0EM-)1C3?`O3#K4LG'#I&B$+AZ6QH"4$EW@_>Y +M(EAJC'1/`[S9UA9,WT5`&I*2B-\5*XZ>SW"Y0.C)1^;.UK]$ +MXK@UJ)SH93P!`!P`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_encryption_header.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_encryption_header.c new file mode 100644 index 0000000..81965eb --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_encryption_header.c @@ -0,0 +1,71 @@ +/*- + * Copyright (c) 2013 Konrad Kleine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_read_format_rar_encryption_header) +{ + /* This file is password protected (encrypted) with AES-256. The headers + ARE encrypted. Password is "12345678". */ + const char *refname = "test_read_format_rar_encryption_header.rar"; + struct archive_entry *ae; + struct archive *a; + char buff[128]; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + assertEqualIntA(a, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW, archive_read_has_encrypted_entries(a)); + + /* Verify regular file but with encrypted headers + as a consequence, all meta information is invalid. */ + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); + + assertEqualInt(0, archive_entry_mode(ae)); + assertEqualString(NULL, archive_entry_pathname(ae)); + assertEqualInt(0, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_is_data_encrypted(ae)); + assertEqualInt(1, archive_entry_is_metadata_encrypted(ae)); + assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); + assertEqualInt(ARCHIVE_FATAL, archive_read_data(a, buff, sizeof(buff))); + + assertEqualInt(1, archive_file_count(a)); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_RAR, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_encryption_header.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_encryption_header.rar.uu new file mode 100644 index 0000000..5bd48d7 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_encryption_header.rar.uu @@ -0,0 +1,8 @@ +begin 664 test_read_format_rar_encryption_header.rar +M4F%R(1H'`,Z91EQMQ=@1S +M,[$:0Y\;'G8_C0D%2L":*;.B*LM0!,!.2!RBU?+`DTN9KXD\<4RGSC+#KCC:\R +M$)P&_/D2I'(4,7$^#2[\,Y"D.2T$@B1#J-Z$]R6_*($W7+!JH\,(XH,'C7FC +H@B,\$1>+CX-=`-%F3C6%I^,NJV2G7':,JF?4KS:6=TAK%$V=]2+N^@`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_encryption_partially.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_encryption_partially.c new file mode 100644 index 0000000..81256a9 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_encryption_partially.c @@ -0,0 +1,79 @@ +/*- + * Copyright (c) 2013 Konrad Kleine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_read_format_rar_encryption_partially) +{ + /* This file contains one file that is encrypted (foo.txt, password=12345678) + and one file that is not encrypted (bar.txt) The header is not encrypted + on this file. */ + const char *refname = "test_read_format_rar_encryption_partially.rar"; + struct archive_entry *ae; + struct archive *a; + char buff[128]; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + assertEqualIntA(a, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW, archive_read_has_encrypted_entries(a)); + + /* Verify encrypted file "foo.txt". */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0664), archive_entry_mode(ae)); + assertEqualString("foo.txt", archive_entry_pathname(ae)); + assertEqualInt(16, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_is_data_encrypted(ae)); + assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); + assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); + assertEqualInt(ARCHIVE_FATAL, archive_read_data(a, buff, sizeof(buff))); + + /* Verify unencrypted file "bar.txt". */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0664), archive_entry_mode(ae)); + assertEqualString("bar.txt", archive_entry_pathname(ae)); + assertEqualInt(16, archive_entry_size(ae)); + assertEqualInt(0, archive_entry_is_data_encrypted(ae)); + assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); + assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); + assertEqualInt(16, archive_read_data(a, buff, sizeof(buff))); + + assertEqualInt(2, archive_file_count(a)); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_RAR, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_encryption_partially.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_encryption_partially.rar.uu new file mode 100644 index 0000000..0c9727f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_encryption_partially.rar.uu @@ -0,0 +1,7 @@ +begin 664 test_read_format_rar_encryption_partially.rar +M4F%R(1H'`,^0'2>C_^E6-T51TBV:OLN/8KJ<5S5/Y4G6N&PG<5GX;P= +MF_YJK^@\`3\09C!T((`G`!P````0`````[[BD,VF3#%#'3,'`+2!``!B87(N +F='AT#!#)/HRW]%5!"GXA#4D)_]J&++4FP^?OH,0]>P!`!P`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_invalid1.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_invalid1.c new file mode 100644 index 0000000..61dea16 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_invalid1.c @@ -0,0 +1,44 @@ +/*- + * Copyright (c) 2003-2016 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_read_format_rar_invalid1) +{ + const char *refname = "test_read_format_rar_invalid1.rar"; + struct archive *a; + struct archive_entry *ae; + char *buff[100]; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buff, 99)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_invalid1.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_invalid1.rar.uu new file mode 100644 index 0000000..2380399 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_invalid1.rar.uu @@ -0,0 +1,5 @@ +begin 644 test_read_format_rar_invalid1.rar +M4F%R(1H'`,^0B$4= +2,P0`I($``'1EM#'TZD7E[>^E"B3)2K$2:-U +M5%)EX,^[Z/T)6TB:)CD1,U4E(I-+`,]6V+:-&:B>1$ +MSVZ_1\FQU\.SEQ<&;'GQY.#%O^;#M^+%ES69_ +MHXL^[K_Z?#!$V>[L_=W/I^?K5_-Q5_#M>BYO_I+GV]C]S[MCRV9 +MM&&7@GAMW)P9]?=Q;^/>X^4D&3Y&Q0BO#W_2,>[\.MAS1^;O7V_]_'ZWI_5C +MSZ#,MGIV'_:?M\MYIM^'3C\^]+W]G*NS5A/R[W<]V*O,9O\H\F;AQ;=E<@[/ +MM]S]GW#/]G9_ZN?:^O"*NM1(DUR^M5]1?CL8?KY,[_?6H"Y$[NC?+DW.+;@^LR+V)X7\OIF@CG7V_%C\FBK +M'FPZ-?+AYA.9S'E8=OGFX=ZS],/#CLGHC)NX?R\K?2\_BQ9\.7BYJN1> +M#!ROX.+?FDV,#N8]W=])YCN3>7/*+GIR[^;8P]J>/])R<7A\7I$]%Z!N+GSI +MEOIF:>*QXM[!,ZG)D\=A\D*"<>/@\.A2SF*X>0<_*;%P;E/KY5\N#15CV^7V>TB:%\F'>TF.UN:'EYO<6Y!'W\D];;7%,H8_TT5ZV#-SG\ +M6]S*<^G,WMP:7E[CLG^W'36D;C\TR9;M-05M.D:?9S$[.B'FRT4/-9FIF702-"LU,'IR>#GAF/.UQY.*:@-FY"W3"]!COP56VQQG.]T' +M,%Y"-OPPT:$S3T)0I=%1'G[R9/'!!F]2L\N#DF:_>C+>B;Q:AK_GV=GUFXM?+YIR-].@7AH8ZFJL]]*W! +M"_%I\,7#/3_[6/D:\I[?7?\5EK5E4C7FL/!T=O0P-7$P[NMP>#0CS6S+>YO< +M?S1E_';L7I59;^BM2N.Q@[6]G\5(%_MM#PCVIF9K!Z&>.%4[."U'='!L+85( +M5_W=:NEM3\3BS1FU(,=WJSA'V9<%WL>>Z=[;&'NRF[BV\^MARZGB^;U4]XO# +M#]//@H2<,KCB*=OS=853Y#!V+#X2U@"%*( +MSO;]'"0]Z^D+^DIP1IS6]=U+SL\6>;$>'%7PS8+P[\_\@0!2+'-^/0W4/J/3 +M=#63+ZWWP`?AL+%.-]EC957ZDUY.8^<[GK+8?Y<&UFX? +MFTP5J1,8$\];/O\/6O)TV.SU^O_/7Z_9U^Q_+9[/8V/CZ^Q\G7]._8P6D#U' +M#'E]#O0E"8`6:@F6'G-<1;^.MXN0K-$>/?ZVITKZ=,U'C]#YYUO/<'2Z:R2O +ML_;KK"WV>Y6%U/W/EN5[[.Q_'8_GS:8L.O?>&W>6WU^O\M,L\%VV^Q;^_*_0 +M7MV^/LMO)P\=OBU>#8V_E['\I^KVKD+6HGY!F'X@.U.*M_;BFB"WV.C^.O]' +M7Z?Z-Z;K;/U(<@=G#_XP_'K@.++ISC#L\_W/U3%=?^'7_G_+4MY.$GHWV_'./%ZV*C7M[#P4NEP +MW7OX3-X\?#PSPLU^^]W(BO8(>G_M8MR;@7>Q\$UI9N#X6BFUQN>^@`NA'QJX +MHN7SI#J^"&H\VW.59V_%:PGN7#,ZN")NO=VT+E3:&:KB.WT\'P=%DCTO=F+X +ML\6@&T*'CS7L_C+-W0]1W!SO3&/SU?X=BZ.%[H#1O$Z;6&CG1%M^*H!C+[1M +MWWG)?LR9?;02-:8(/]P('4'W<*5];/?I^J&I(??P`)PW@\>BSF*XK7YL]-69 +M]CU@@,V>'R]1MN']>662NB(+,Y0.:@MFY +M[G)D0>VB.I_YEW]#&3>R>'CK)<503'UX)=]&2GOQ$)F0F&^H_DW<-^;*J'?H +MY5K\N9KN71',-9+>'BE%3<>;5':@R4206"OL9KS2FS&3 +MUEX9S(W#S!0J#"N>@3?LI1&K*:AR<-M$VS8(SC?Q4`!UU!J="U_>\KW-X1Q; +MT3/$,%V?IBC5FM@Y>\%)4[I)G/-&4\%-N0S="<;ONCQURJB/L'#2;'T/8LM[ +M3LY4';Y^[(#&9,NE;#J?ULS45,QQLR8:S!CWX?7Q/!^H#_FW79X<4*@\Y=-' +M^'E;!?;F0R\.>KF;I5OJ*H4G +MSO1?KCX:+C:V"KI"FFH0'7[\>UCI-%T2MY.?GGRXG_WN_E=(:VFKS>X!!,/; +M[GV=W\.YX-GN=_9ZGJ:"ZMT&O_CU(BW6_SI$9G4E^+AOQ$\/^?6]3$U13U.I +MBP_1=I7P0E'P3H574ZO5P_XM?R+-S.0EVFT($TS48\$W"O,7U?^ZRZJ`_8Y3.6PRS'>>#3!=\ +M$K0'!_V6E89'ID49#S(:U'&OH>QU^S\G7]?3M?Q-+W>AG6KXR;E3+Q](EJOX +M]GJ/U4W\_'@J"'ZF*T.+BL]CH&\5>_H]FYCZDMQ6?-?N_A]G6^_M?AW?LFME +ML??]E?IU9=35_@NF=NI3).B$.Z5GVN8__)_^K-E[^+;RY+0SFF42QY9TS7P\ +M4/9YN8IM#YIN+YMK9YRMKTT9/@NIB<(IHV*M0HP]WO_C$)FZA$^S+MXM3'F +MP976M+-?ON0_6J[SJ;_GF3@N&Z\]_U<T85^75V,'?LA,UVB[="5JU-E'Q,SF6A+[8HN'%3SV4J +M'6"Z@8:JL3!'T^6T.%H!ZDX8'BB-'[,T5S.=351LW]S%U9)ICK@QUJQ<1JM' +M75P:8F"]NG@,W0/#,1MJB\VT-*<17F.P05^?'E+1=2E=9TL9_-43 +M5.?WT23HF'/5//*PU]S'HAGP.<]/X+Y!B_NY?6>#;XYUL?P:+?!BH&5J +M&)CZ<,L@^]9'+I`P\\HQ[GGU^Z$TPR[P2Y=0W)\*'9O;M8^UU8LM<9XO',M\ +M[&HP6KUL$\?HYYGYM&;DV/;I27I4B7XT?5O.G]B;L['FK\X#2^26J'QSY*\% +M=9T:.;AOYEIHW-%.Z"4>2-KG(KZ4#U;9=:";2H9UJ5LV6,N>Q7N$"@5_">L\,[\6@UKE9PQZ +M\V9GRL?>[O^O<^GZ]#E'M^]O4-O_>37;V\N/AG-PYJ"@ +MH%`Q/29YUZO6C\3'1UIH$_G,6?.@F^6SURC;XLM.12A@*=8=]YVQ-`V;5J" +MYPU[R0N[NW3JT?YP9-0%+!\%SRBDFE;'Z@_L>CTIRIM5S)W35\#QRS0ECS70 +MBXG=ND(=`'5*,M-;3@N!A4=G?!;*YYO63YI6=T[-Q1_W!QUEY:-P7UI[:UG/ +MDO\'P>R6HIO6L=;-IK%EY;VDVEYM5KLU68]$^+R6=/FG341CH0X:-M4H=F+= +MLWN.$$S?I45D_Z/&E7*K:CM1S26_S&47RLO<1I,)=/^F +MW[UDT@YJPAM^S?HNGLWE?\>>W@G=']]^"*$;=1&8/C9ETO?\U*]]_C/CJ^66"^ +M%:T39/!=H;JX/^,'J%+H34,%^TP,`MIC7L.Q4K3D+NCBJ5Y/5-A^ONB]3Y>K +M\UVF/^=4UGZCHFT63.+/2T`!+>1TP3+E*>!TMFYSUC/@7JLOVCY>.BU%`?&E0N==\Z;!494NP +M?3D6&?_-U[&5_W=N'!=N'HQ!M[<".H;UU!_9QS//,V/:]<"_]/W1SXEHD'V4 +MA!_>VC`[N'LF+(^"=>6PX^A%SK/=?I^G,A>8.HJ7.R/8ANS051ZIRM^*:C>@ +M.!KUP6>G&%<.3AK5;>#SZG(7Y/+K>BXL]!F63@N?`157O2=R=6!]Y=%UY#SP +M5;YJZ&[5^?OTN@=GH#2J2O.CJ#L3;RISQ5+8]FQ1=K^N^M6]<&+R3"?VV1Y1 +M8[WU6:M?LIR:LZL;\ONL]7[!7/IYZG6_=*OWV;\LT*>[\4C$'&@!F+0&]GD' +MWSE'XQG[^MHQ/?X]_>\T\X[4J^S+G=S=ZS +MP_OZ#Y37:!UO;$SH&!]J4(T[W\?ZV?O%.,1^'FN;W,J??'&==*:NU.F2=E1^ +MW,G&([D"A_<\Q_#0E>QO[A7^NW/_WRULV?IZ_H^\.2;K&;\'V2M7)>GR899I +M]>V:)S84]^V7MMMQSH[%F<3]XB['%Q4)%[>/])ZYO6\C!L]; +M3#\G8BWDLJB3HIGIO+VHH#V+HS8[,.CO"_]@4K0.]T/6@ +M<[!Q3K5EO/$67;+= +M@U5`P4WU2IW\A_IKVW+ABYW<45Z*.BXS.39ENEL)V!!,"=OS-]S8SU39@]_0 +M!!#H$-MY[#!P4EP8*UUP9T"@QHSW*M\]O)FB]2?1\&>UV]/Q4+WFRUVY[H#* +M[?XT;7J][T"[T=$?G.>14Q/BG-6V[_FW]XL5.>$MQ59&.+Z@LI51)VC'I#X^ +M^YQ<$F@:?ZH0W6P]$'I<&UTA?[UCPQ?:-Q$ZG5^:J?HDUYXK]:W:]FI>DLZW +MMDSU%M7K,YG__%IIL?OFT::7FY3M68AO"JYYIJ(-.%VKR*T_'#"O!X]`L_E\4]?\V7%%Q_3H:.M.H3:E5=,KAJJ0- +M>-(TY#2T>>C:QD4QO]+O6F5/?-]Q,\>K7;KF-YT:+:G8%M=]4,+,[7;I+VQX +M\G!7>>C7F,YON1/)S7\A0;7IP*\;'I>X%O`E9?98:L0_S;AX'6>RK2','P>O +MP#WO.\OP^+1GSN3)>3IK27^WM3YQ"T='63&I9`DX9&[C\.QXJU9?3GE&#]/$ +M[>Z%"O%,55$OWY31*%,XN'8ZOF_"9PH$ZVZ]AV1 +M=/E4FUL]>/,Z`&J-5]KG6M]*V@"3KN,.6(\\,^:81\[>*Q;D5>[:Y[/'&)T\ +M+O`+.,?6Q>Z3!%TNM:N9/_)LXVVYWZM/L6V?/][MSXKO +M6ZG5NOAJ++W09XHB\1X<>_Z]$;GL[DWQPI;2Q` +M^6\9E$_CFNU_0C4!PTL9G54NIHAGLS:LSS5+H=7/12W%P5X'_WJJAP5?!:N[ +MFCFB:9#6,K'UX)>0D'S9;&>^WL^UYMO:OV:%>*>KZL$KI*79Z-CR?VCJ)&*@ +M3#5B*I!H%MXZ^:LG+#W:?-+<$!_[F?--N*W"#[K"UAOOWX(3@HU]6'9JZ7=J +MS2UK:*='74^D;[>:WP>QTS2IKU?E9JF"GMC/,`Y.6^Q8_#XH=+>6:V^H+%[N +M@#K4J"GM$#5P'J(,O:1PWOO@^\0?Z.![UP\ZMR0X[JE[RQ]&//7W])_Z6-;! +M$N@8V\&[/I1&7=Q;=N*X\&[272M*L[1=QZN4BMTK%0PMXBV][56#Q6C=Z/J^@B:?+&4N7NZ&Y[Z@2I__),.%N8HX[/^_O^^]6`\ +M_RLAE?/]7Y]#=.?)IVE=NN;W>=X,4Y[F:Z45^7:X\]F;I.F77$CRXM7&[:>F +M.X-FZU%[9]C'MV:1I\53^/)/TZ<%CGR5"!]+:W/,)FR="!U2NH:MZTC!>MU' +M>[04$*@ZJ:@VWX^.O7)ZV@;MYZH]B=DGU$"EGDYM.Y8LOJ%F(DO[JK'O<>F> +M4NM+>_SG-`#O,G@FM-EBXZ/C\])U8.O6V\%+)^F@'CU=O\K1?LG!0IS9#R5&94FC:PC]/4VL +M&[EGM*+TZGW+[Q5LTC+X;-5[FZ>>UZ"G,S+3B;;_#/A!YZ%W\<75%FKS< +M#CIOM-'40M)W%FZ'74LW',X^_%F7YM/5,K@R'S:;+8NHR50ODZX;DQVV +MD-TK]35?K>M6R[*7%!./]C@M3M$>X+U[DE_[.+]?UEG(U4P1X,,MWX96'=U> +M>,SN[%?91M2]#1W,EE=)8O#'66IJ+STKQ=`V$3:'*3AXLO#'+18Z(/SVMY;> +M7E/?@RPHI#SJ9DZ.N:0H[@?N;>B"=-?KLFX_FG'UGY$:8P4;H +MBS.J2M>+=O=$-]'6=RHR9BVHL-2C24QK66[M@G,+NW73=^U=<-U&T>=R:8Z6 +M;S""[#,]L?B+4$NJ&^"[B +M^+QS+489X[(EY,GCLNV72NK*93?2=0R=87=5`[;$4TKHX+7 +M!E_J.G.]BYW,V._RJ]W:.JPZ>$4X-4F7^<4,O/REHJE0LW=O/K#[TQJ;3_W3 +MTEEUR-Q*FW_X%16ZTL4*K3=6\7ND<&'AG@MZG_$[2 +M,K*/:9M!T:TBG00+P42Y0[)ETA=(3;'+N<,=6SUM/\)4OFUAS-3^&LS +M`0YJ.C^Y"7?#^N/A@F;4_SV<&KH6/,_%YPSL,+YL.*Y5W-H-WMZY*TM5`:70J<7]Y.?$P^?5%$9U)^:NO/1M8\\63[WZ +MMW^LA6UR30"1>8$Z+P?U3A7^!.O]3]WH4WQ0@S!7FPZU,W:R;F.S3?J=?VN] +MFUMC>I5N8O<:@9^+WUK2A_/?BS7C`^>:>'-Z`;>L`NG9&(^B8WJ;U&D$.I[\ +M-_2M:S7`2BTW%&-H"#3HM$!PMK>R;?CP6Z5NK)5)7.[^"/MI1O5:K-29-U"/F4J9_5;WT1![O3RQ3D;F+]GZKR4_JX[S%.W,I9-^@6S>Q<=R:+NM!V +MJN7EQ8J3$=@HJYZK6*;[4F'I7]$)"ND5-^DBA@E_;^.TC:ZT="MV"T`4ZG%6 +M"67MKWG!-#)9H%MQN6UE7H4FV$E52Q2X"9WN]@NG8YA%*0W?8,5P)!J"\IW% +M#AFTQC_6O/!8.A_'!JJ"Q75//*_.FVTP$_'-.MFM;>'N/@M4SM>Z4DEL +M>>G)$8(U#I@J:D(4DR[3<0P3TAGL\K@Q;GDG!GQ>'5P_DR/,\'+?>X[;>H\M +M&V:DVVIUW4;W)Q4KK]]M6V;E_+5XGP=W*?J03J?Q$BZJ5:.IXK%O:K6_Y_N +M.A[X)O0]VM]M\K=R,BW<$>_BKV(*9$T(VN./FOM'6MK9-5"I_3D*;M'0C\?9UYPENFDHYZ;\%>F';67)X +M[.D:(H7)VY'T1*$-.0_>\F.L-6>YNFX^2>EOX_);D=:+-%TQ=6G2/J9!I_E3 +MG(>"ET[=CK?)AS1U#C4H;[6_S/J[WTVX?K?5^/;_K'YC^WX```````````````"]OP````O;\````````````O;\```"]O[V_7M^` +M+V_``<`%[?@````O;\`````````#@`7M^`````````````!>WX`````````` +M`````````````````````````9@``````'P`#``````!>WX````````````` +M``````````````````````7J_``%[?E[?@````"]OP`````````````````! +M>WX````O;\```````%[?E[?@`````````````%[?@````````7M^`%ZOP``` +M````````````````````````````````!X```````````````O;\```````` +M`````!>WX```````````````"]OP````O;\````````````O;\```"]O[V_7 +MM^`+V_``<`%[?@````O;\`````````#@`7M^`````````````!>WX``````` +M````````````````````````````9@``````'P`#``````!>WX`````````` +M`````````````````````````7J_``%[?E[?@````"]OP``````````````` +M``!>WX````O;\```````%[?E[?@`````````````%[?@````````7M^`%ZOP +M```````````````````````````````````!X```````````````O;\````` +M````````!>WX```````````````"]OP````O;\````````````O;\```"]O[ +MV_7M^`+V_``<`%[?@````O;\`````````#@`7M^`````````````!>WX```` +M````````%[?@``````!>WX`````````````!>K\``!>WX`````/````````` +M`````````"]OP```!>WX```````+V_+V_``````````7M^```"]OP``````` +M`+V_`"]7X````````````````````````````````````\`````````````` +M`7M^``````````````O;\```````````````!>WX````7M^````````````7 +MM^```!>W][?KV_`%[?@`.`"]OP````7M^`````````!P`+V_```````````` +M``O;\```````````````````````````````````,P``````#X`!@``````O +M;\```````````````````````````````````+U?@`"]OR]OP````!>WX``` +M```````````````O;\````7M^```````"]OR]OP`````````````"]OP```` +M````+V_`"]7X````````````````````````````````````\``````````` +M````7M^``````````````O;\```````````````!>WX````7M^`````````` +M``7M^```!>W][?KV_`%[?@`.`"]OP````7M^`````````!P`+V_````````` +M`````O;\```````````````````````````````````,P``````#X`!@```` +M``O;\```````````````````````````````````+U?@`"]OR]OP````!>WX +M``````````````````O;\````7M^```````"]OR]OP`````````````"]OP` +M```````+V_`"]7X````````````````````````````````````\```````` +M```````7M^``````````````O;\```````````````!>WX````7M^``````` +M`````7M^```!>W][?KV_`%[?@`.`"]OP````7M^`````````!P`+V_`````` +M````````O;\```````````````````````````````````,P``````#X`!@` +M`````O;\```````````````````````````````````+U?@`"]OR]OP````! +M>WX``````````````````O;\````7M^```````"]OR]OP`````````````"] +MOP````````+V_`"]7X````````````````````````````````````\````` +M``````````7M^``````````````O;\```````````````!>WX````7M^```` +M````````7M^```!>W][?KV_`%[?@`.`"]OP````7M^`````````!P`+V_``` +M```````````O;\```````````````````````````````````,P``````#X` +M!@``````O;\```````````````````````````````````+U?@`"]OR]OP`` +M``!>WX``````````````````O;\````7M^```````"]OR]OP```````````` +M`"]OP````````+V_`"]7X````````````````````````````````````\`` +M`````````````7M^``````````````O;\```````````````!>WX````7M^` +M```````````7M^```!>W][?KV_`%[?@`.`"]OP````7M^`````````!P`+V_ +M``````````````O;\```````````````````````````````````,P`````` +M#X`!@``````O;\```````````````````````````````````+U?@`"]OR]O +MP````!>WX``````````````````O;\````7M^```````"]OR]OP````````` +M````"]OP````````+V_`"]7X```````````````````````````````````` +M\```````````````7M^``````````````O;\```````````````!>WX````7 +MM^````````````7M^```!>W][?KV_`%[?@`.`"]OP````7M^`````````!P` +M+V_``````````````O;\```````````````````````````````````,P``` +M```#X`!@``````O;\```````````````````````````````````+U?@`"]O +MR]OP````!>WX``````````````````O;\````7M^```````"]OR]OP`````` +M```````"]OP````````+V_`"]7X````````````````````````````````` +M```\```````````````7M^``````````````O;\```````````````!>WX`` +M``7M^```````#^!$_L_$HKIR@3W\%I0\````+V_````O;^]OU[?@"]OP`'`! +M>WX````+V_``````````X`%[?@`````````````7M^`````````````````` +M`````````````````&8``````!X`!@``````O;\````````````````````` +M``````````````+U?@`"]OR]OP````!>WX``````````````````O;\````7 +MM^```````"]OR]OP`````````````"]OP````````+V_`"]7X``````````` +M`````````````````````````^```````````````+V_``````````````7M +M^````````````````O;\````+V_````````````+V_````O;^]OU[?@"]OP` +M'`!>WX````+V_``````````X`%[?@`````````````7M^``````````````` +M````````````````````&8``````!X`!@``````O;\`````````````````` +M`````````````````+U?@`"]OR]OP````!>WX``````````````````O;\`` +M``7M^```````"]OR]OP`````````````"]OP````````+V_`"]7X```````` +M````````````````````````````^```````````````+V_````````````` +M`7M^````````````````O;\````+V_````````````+V_````O;^]OU[?@"] +MOP`'`!>WX````+V_``````````X`%[?@`````````````7M^```````````` +M```````````````````````&8``````!X`!@``````O;\``````````````` +M````````````````````+U?@`"]OR]OP````!>WX``````````````````O; +M\````7M^```````"]OR]OP`````````````"]OP````````+V_`"]7X````` +M```````````````````````````````^```````````````+V_`````````` +M````7M^````````````````O;\````+V_````````````+V_````O;^]OU[? +M@"]OP`'`!>WX````+V_``````````X`%[?@`````````````7M^````````` +M``````````````````````````&8``````!X`!@``````O;\```````````` +M```````````````````````+U?@`"]OR]OP````!>WX````````````````` +M`O;\````7M^```````"]OR]OP`````````````"]OP````````+V_`"]7X`` +M``````````````````````````````````^```````````````+V_``````` +M```````7M^````````````````O;\````+V_````````````+V_````O;^]O +MU[?@"]OP`'`!>WX````+V_``````````X`%[?@`````````````7M^`````` +M`````````````````````````````&8``````!X`!@``````O;\````````` +M``````````````````````````+U?@`"]OR]OP````!>WX`````````````` +M````O;\````7M^```````"]OR]OP`````````````"]OP````````+V_`"]7 +MX````````````````````````````````````^```````````````+V_```` +M``````````7M^````````````````O;\````+V_````````````+V_````O; +M^]OU[?@"]OP`'`!>WX````+V_``````````X`%[?@`````````````7M^``` +M````````````````````````````````&8``````!X`!@``````O;\`````` +M`````````````````````````````+U?@`"]OR]OP````!>WX``````````` +M```````O;\````7M^```````"]OR]OP`````````````"]OP````````+V_` +M"]7X````````````````````````````````````^```````````````+V_` +M`````````````7M^````````````````O;\````+V_````````````+V_``` +M`O;^]OU[?@"]OP`'`!>WX````+V_``````````X`%[?@`````````````7M^ +M```````````````````````````````````&8``````!X`!@``````O;\``` +M````````````````````````````````+U?@`"]OR]OP````!>WX```````` +M``````````O;\````7M^```````"]OR]OP`````````````"]OP````````+ +MV_`"]7X````````````````````````````````````^```````````````+ +MV_``````````````7M^````````````````O;\````+V_````````````+V_ +M````O;^]OU[?@"]OP`'`!>WX````+V_``````````X`%[?@````````````` +M7M^```````````````````````````````````&8``````!X`!@``````O;\ +M```````````````````````````````````+U?@`"]OR]OP````!>WX````` +M`````````````O;\````7M^```````"]OR]OP`````````````"]OP`````` +M``+V_`"]7X````````````````````````````````````^````````````` +M``+V_``````````````7M^````````````````O;\````+V_```````````` +M+V_````O;^]OU[?@"]OP`'`!>WX````+V_``````````X`%[?@`````````` +M```7M^```````````````````````````````````&8``````!X`!@`````` +MO;\```````````````````````````````````+U?@`"]OR]OP````!>WX`` +M````````````````O;\````7M^```````"]OR]OP`````````````"]OP``` +M`````+V_`"]7X````````````````````````````````````^`````````` +M`````+V_``````````````7M^````````````````O;\````+V_````````` +M```+V_````O;^]OU[?@"]OP`'`!>WX```']'_`95WX```````````````````````````````````9 +M@``````'@`&``````"]OP```````````````````````````````````O5^` +M`+V_+V_`````%[?@`````````````````"]OP```!>WX```````+V_+V_``` +M```````````+V_`````````O;\`+U?@````````````````````````````` +M``````#X```````````````O;\`````````````!>WX```````````````"] +MOP````O;\````````````O;\```"]O[V_7M^`+V_``<`%[?@````O;\````` +M````#@`7M^`````````````!>WX````````````````````````````````` +M``9@``````'@`&``````"]OP```````````````````````````````````O +M5^``+V_+V_`````%[?@`````````````````"]OP```!>WX```````+V_+V_ +M``````````````+V_`````````O;\`+U?@`````````````````````````` +M`````````#X```````````````O;\`````````````!>WX`````````````` +M`"]OP````O;\````````````O;\```"]O[V_7M^`+V_``<`%[?@````O;\`` +M```````#@`7M^`````````````!>WX`````````````````````````````` +M`````9@``````'@`&``````"]OP````````````````````````````````` +M``O5^``+V_+V_`````%[?@`````````````````"]OP```!>WX```````+V_ +M+V_``````````````+V_`````````O;\`+U?@``````````````````````` +M````````````#X```````````````O;\`````````````!>WX``````````` +M````"]OP````O;\````````````O;\```"]O[V_7M^`+V_``<`%[?@````O; +M\`````````#@`7M^`````````````!>WX``````````````````````````` +M````````9@``````'@`&``````"]OP`````````````````````````````` +M`````O5^``+V_+V_`````%[?@`````````````````"]OP```!>WX``````` +M+V_+V_``````````````+V_`````````O;\`+U?@```````````````````` +M```````````````#X```````````````O;\`````````````!>WX```````` +M```````"]OP````O;\````````````O;\```"]O[V_7M^`+V_``<`%[?@``` +M`O;\`````````#@`7M^`````````````!>WX```````````````````````` +M```````````9@``````'@`&``````"]OP``````````````````````````` +M````````O5^``+V_+V_`````%[?@`````````````````"]OP```!>WX```` +M```+V_+V_``````````````+V_`````````O;\`+U?@````````````````` +M``````````````````#X```````````````O;\`````````````!>WX````` +M``````````"]OP````O;\````````````O;\```"]O[V_7M^`+V_``<`%[?@ +M````O;\`````````#@`7M^`````````````!>WX````````````````````` +M``````````````9@``````'@`&``````"]OP```````````````````````` +M```````````O5^``+V_+V_`````%[?@`````````````````"]OP```!>WX` +M``````+V_+V_``````````````+V_`````````O;\`+U?@`````````````` +M`````````````````````#X```````````````O;\`````````````!>WX`` +M`````````````"]OP````O;\````````````O;\```"]O[V_7M^`+V_``<`% +M[?@````O;\`````````#@`7M^`````````````!>WX`````````````````` +M`````````````````9@``````'@`&``````"]OP````````````````````` +M``````````````O5^``+V_+V_`````%[?@`````````````````"]OP```!> +MWX```````+V_+V_``````````````+V_`````````O;\`+U?@``````````` +M````````````````````````#X```````````````O;\`````````````!>W +MX```````````````"]OP````O;\````````````O;\```"]O[V_7M^`+V_`` +M<`%[?@````O;\`````````#@`7M^`````````````!>WX``````````````` +M````````````````````9@``````'@`&``````"]OP`````````````````` +M`````````````````O5^``+V_+V_`````%[?@`````````````````"]OP`` +M`!>WX```````+V_+V_``````````````+V_`````````O;\`+U?@```````` +M```````````````````````````#X```````````````O;\````````````` +M!>WX```````````````"]OP````O;\````````````O;\```"]O[V_7M^`+V +M_``<`%[?@````O;\`````````#@`7M^`````````````!>WX```````````` +M```````````````````````9@``````'@`&``````"]OP``````````````` +M````````````````````O5^``+V_+V_`````%[?@`````````````````"]O +MP```!>WX```````+V_+V_``````````````+V_`````````O;\`+U?@````` +M``````````````````````````````#X```````````````O;\`````````` +M```!>WX```````````````"]OP````O;\````````````O;\```"]O[V_7M^ +M`+V_``<`%[?@````O;\`````````#@`7M^``````'\!'_`95``8`````` +M+V_```````````````````````````````````"]7X``O;\O;\`````7M^`` +M````````````````+V_````%[?@```````O;\O;\``````````````O;\``` +M`````"]OP`O5^````````````````````````````````````/@````````` +M`````"]OP`````````````%[?@```````````````+V_````"]OP```````` +M```"]OP```+V_O;]>WX`O;\`!P`7M^````"]OP`````````.`!>WX``````` +M``````%[?@``````````````````````````````````!F```````>``8``` +M```+V_```````````````````````````````````"]7X``O;\O;\`````7M +M^``````````````````+V_````%[?@```````O;\O;\``````````````O;\ +M````````"]OP`O5^````````````````````````````````````/@`````` +M````````"]OP`````````````%[?@```````````````+V_````"]OP````` +M``````"]OP```+V_O;]>WX`O;\`!P`7M^````"]OP`````````.`!>WX```` +M`````````%[?@``````````````````````````````````!F```````>``8 +M``````+V_```````````````````````````````````"]7X``O;\O;\```` +M`7M^``````````````````+V_````%[?@```````O;\O;\`````````````` +MO;\````````"]OP`O5^````````````````````````````````````/@``` +M```````````"]OP`````````````%[?@```````````````+V_````"]OP`` +M`````````"]OP```+V_O;]>WX`O;\`!P`7M^````"]OP`````````.`!>WX` +M````````````%[?@``````````````````````````````````!F```````> +M``8``````+V_```````````````````````````````````"]7X``O;\O;\` +M````7M^``````````````````+V_````%[?@```````O;\O;\``````````` +M```O;\````````"]OP`O5^````````````````````````````````````/@ +M``````````````"]OP`````````````%[?@```````````````+V_````"]O +MP```````````"]OP```+V_O;]>WX`O;\`!P`7M^````"]OP`````````.`!> +MWX`````````````%[?@``````````````````````````````````!F````` +M``>``8``````+V_```````````````````````````````````"]7X``O;\O +M;\`````7M^``````````````````+V_````%[?@```````O;\O;\```````` +M``````O;\````````"]OP`O5^``````````````````````````````````` +M`/@``````````````"]OP`````````````%[?@```````````````+V_```` +M"]OP```````````"]OP```+V_O;]>WX`O;\`!P`7M^````"]OP`````````. +M`!>WX`````````````%[?@``````````````````````````````````!F`` +M`````>``8``````+V_```````````````````````````````````"]7X``O +M;\O;\`````7M^``````````````````+V_````%[?@```````O;\O;\````` +M`````````O;\````````"]OP`O5^```````````````````````````````` +M````/@``````````````"]OP`````````````%[?@```````````````+V_` +M```"]OP```````````"]OP```+V_O;]>WX`O;\`!P`7M^````"]OP``````` +M``.`!>WX`````````````%[?@``````````````````````````````````! +MF```````>``8``````+V_```````````````````````````````````"]7X +M``O;\O;\`````7M^``````````````````+V_````%[?@```````O;\O;\`` +M````````````O;\````````"]OP`O5^````````````````````````````` +M```````/@``````````````"]OP`````````````%[?@```````````````+ +MV_````"]OP```````````"]OP```+V_O;]>WX`O;\`!P`7M^````"]OP```` +M`````.`!>WX`````````````%[?@```````````````````````````````` +M``!F```````>``8``````+V_```````````````````````````````````" +M]7X``O;\O;\`````7M^``````````````````+V_````%[?@```````O;\O; +M\``````````````O;\````````"]OP`O5^`````````````````````````` +M``````````/@``````````````"]OP`````````````%[?@````````````` +M``+V_````"]OP```````````"]OP```+V_O;]>WX`O;\`!P`7M^````"]OP` +M````````.`!>WX`````````````%[?@````````````````````````````` +M`````!F```````>``8``````+V_````````````````````````````````` +M``"]7X``O;\O;\`````7M^``````````````````+V_````%[?@```````O; +M\O;\``````````````O;\````````"]OP`O5^``````````````````````` +M`````````````/@``````````````"]OP`````````````%[?@`````````` +M`````+V_````"]OP```````````"]OP```+V_O;]>WX`O;\`!P`7M^````"] +MOP`````````.`!>WX`````````````%[?@```````````#^`1_"\2RMN6#O^ +MAZ6/```````````````````````,P``````#@`&``````"]OP``````````` +M````````````````````````O5^``+V_+V_`````%[?@```````````````` +M`"]OP```!>WX```````+V_+V_``````````````+V_`````````O;\`+U?@` +J``````````````````````````````````#P```````*GZ#$/7L`0`<` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_multivolume.part0001.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_multivolume.part0001.rar.uu new file mode 100644 index 0000000..7378a9b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_multivolume.part0001.rar.uu @@ -0,0 +1,1337 @@ +begin 644 - +M4F%R(1H'`%IND``&I!9PX#@*>#,/AM$C\= +M-1T`I($``'!P;61?;'IS[/K1`L^BJ7QHH!,TI;W];?!5Z +MF=E%3:9D!V5_BCOB__PLW,UT8MG.V$Q7KSZ2#K<#EP<%P9+`YQ-//JS/OG8% +MGF:=0?4;"T5`E9>J+-,;+NI2K6-O?[L^U3B+E^I-B0X8-!>K)^47].FJY*=Q +M10]!>FJ?S0;Z^B\I%7:4@H;0AA7'(3P&:[\JU(8)'5$62(J&$W\)QVW45M^2 +M9P3SADC_"!&+;L,CD'5DHA4.Y/8103RTR=4"1_^^"?<=_K`2[*UD!5]5ELOO +MD904KH(C.D_I,E_*W4G%?:"JL3FS&'X'!M8\]_4N^GIF="5&V)>M,/_6NL?& +MG-!'+L%_B<.$R[@F\:]E.SEGZX8JG*P!=:4?BQID^?>^$K):ZA*;%AT&QG4H +M87NK!"V.H]QRL!*Z75P*H=QH@.`K!%U)98?$)B5/#'Q"G2?IK:SG--F<>%0P +M/&L'[WB2!U7<*?4L4NOOUTT.SR!`I\R[_P1F=02HR>'QX8'^2HV&5JV`]-KQ +MI+1)$DI5RKBB(D_C'\_+]51?<,M@,F]PE+VS +M]2/>+LTL^)KUF2N[8ZO?.RN>$#S?0H]0YSYGBDJB]E^_&DDB:%;!B8J8GW*J +MO9*/%:M1X$FFP^&O`[RU:XM%UY]0#EF9\,:3">!<)ETSY)F5GC:.-&AY:MMY +M?U9WS&?(9@3"\/]9=PU??)T!9PR=N(\&#=,WX8AKH;:/SKE13]KR`RMXSC6_ +M^IXE6RJ:_VX+-U:3J`1R_HK<>S2[KP=XHKKNY&^5,X`_EJ,Q%SP[P=:;DP!V +M0!/%2"66A!1(2(+-#&]E)ZM83H-(N9*;>3I['T&=*&8?"1L$%$;3I6]YGM7D +MA@WYC]Y1YC(KRNJ.,K9ISE/HX0L[5W!@N8&,/@KJA3[(SRV0;9*#>[IC8&(O\6E?P5CO+^4Q.EB +M@5_+,2,=*PW'V6\5:'`GU$42X'+ML^24T+V!U"[7`*WU5Q]A$I;.G*JG3N>M +M(\%C1N33':_HHW*]Y@\[G\VP2BSYTEQL1Z8P$U-TE)M#',SS=QF:;,%!X>FAS*\$LTE:N;-E6JH>UCSZ1^*'21$RTA7<71W\*'6M7UH/$P-#82?]^*:&%&S?D\9SP=W8 +M=U"D#*O8TJ'PI?QPA5Y[1`3&LES]V4]=\A6GM]#HQ+($<>?RFPOA_\/#^3H) +M9M3;PAY%/JU7%9Y??]05JHLVQ:NH:N_*K(KT^-\AHXKO`8\.G#76!Y?X:87E +MA&>X_XI=4RLM_#NXEY+K_W!;ZRW]"9D4GN7+!"*$"@E$<G,@,C`8B[OV4TA+G:`EC40T>@O"IY@;Y\2/JDD=V1M![(CNP(_,E2-0U^CX,9BJE=-CP^H-4\+4& +MD]^J`VAH[`_"EO\Y>#/O3GZ<`Z:6=C5[_!MCXBCD:8T=_894T$+.WU/1Y`8*W?RV7BIE:8CE&#G* +MKAR=I-M!\(2SH1`)U-_43!QP@2?TY36!`,FTEU"+G+UR\DX'0Z_/'SUZY'L\ +M<0WB\\&R.5`B`PTC#+4,\88"E0R2=P3'KS7/-:4F*.?&)JJ,1Z$$E`D\_G]: +MV`NESW?*QT"[,@OLIS&%#DX>O6[@;#9Z`ZT%+:?63G07XHA.O=(S8L_LA_@> +M\]+1T#1TE;]'*1$!&)GM0DS/_Q)^T>D@@/DD!>X+:`L4GV%@V((T>B"H_:6L +M;'9EB0&Z^8*/S-%;`K&EHFW1R0IJ1>OW_*'\4"G9B!S)($G=ZU?\%SA7*9M^EL80./SNR$4)E*K:0!TT,*59F65;WNQYN2Q.Z,L"-H?=(U3A>/=1R/Y!KMGFG!/%DY8V50XA+>J82,Z"D#JFCD'!XZBB48\M\!4L<-&XPOV&.MBD.".V.?&$P1P4SEWX]XVYY +M/DM9NEM8RJBP@JX`MF#PDC*4T$Z1ZZ%(V_XY#NX1+B8%\ZL>P(`W9GWOQR7: +M

    +8<3CD!K`P6["#A8H,+&2R38"$I3JG>X/>XN:(7?G\R3GA;7`/=)[X,@S +MH"RE$#HVN0_>N!D3^9IE^DGBJ9V+YJM@YIK6_%4=OUV8U!^^(JX8"/)T`5%& +MTDD1HCVQQU=MDJ7]J/"5:Z4Q!0D@T'X=<[2(L_>PSMH*)HHVI-L$?3^",O.& +MT)16KLM`NPY``"J9YM+&Y^@'!?(+IPXR-`84ADYF:`&7!(*#Q@Z]BBE@.1:A^OSG:9$M^[];\N@Q3(X+W +MLW3&;=A2([8<"3P>I95^!NIMJE^YJ5&S6(J`/T!2S-,' +MD6)@'GHT\L_2HV$04ZU\SOE')DN?ASL1NN^^7:V<[)Y\I*EYV;0WS5FYD3!6KRFYFE5CFI??*J +M-\ZJE,,<%,A9'!"O8)6/WUW=W@R<[=$$<1D1#G@4N:YEA(!4?2'_\H4)K'I` +MKQX_T=8OD1V$QU'F.652T;$^E!V!\%GRF>6J@J%#FTW+I/CY_;U,E7%R2F"W:/F]OY +MT`W/7T#4Z=_;LS/5@2B`\A(2,WZSA?974DF3$<^RA?!ACA!^T/=BR4X+!8F3 +M^V075'/DF0UX9\E0VYNLUQJ.-$%SA9?S +M?8%ZQ#'_7KP%^D[YB#`YBS9'R-1]I1"2N1X`F!NO\Y +MU2FW]K[:,QOI# +M>G6&B3`V%ZV1>]#E':8;?F6OG8V^TQV;15_5-.W1-`CK,=C))^_Q_AF]F.H1 +MSAN"WK^*@1VTQ-&^[`74F:5-]?1;2U:NB`W][#)$@S:G:#QRQ9<)?V;4ZD7! +M-M(9_<.&X+E3&KHS/ZT,"@J!4[HEGW.#\NPS=&7V&Z>>=?0"-TW"#E7/V3CW +M_*1@*VI;B@^?21EF6?.^)_UN@CL82I]HIT<;:R<>@2+;+#RMMY6I*/U]FZGQ +MINO=(L/3*#_E5U3,F\8F_^)ZI`^%#0TR`*7(=M'GAH1Z&W%%SMK%$S(`QE,* +M^6?.6MVVEA^H`Y>:`Z^<*,$Q<"02QX)QTZ;O9%YPH;K('*2`L;>F?*ZC0C^Z=G4^9(Z)%V9Q"G7_SY +M3!5I`B]/7H@7U]O`LQK!E,?3E$805$)KX47&Q-WX3RB7XV?S87X*S5;_:NQM +M5*7B3"56.2*M9KX!S[ZZR'YP-%++:"-V8:N'\Y%8HAP+$#WA*[C(+H9/)APU +M4E2Z:^Y:R%Z^]Z3`7?QMK@75!*C8YQ^2P+0'?Q"%Y#R%#PY?T$G""_TAOMOQHP89`J)7F\@W+<_BQ/#K!1_L +MAG]AD:E2F-"8]9EGWWO2_;$9R'?7$LL^Y]2H60AX..N#3IS1:;`LGOI![!L;C&Y)[`!-[XN#[5[/KF@*1866&"ZCC\[ +M#$*J]$%)"`#2V0FJ(>E2E8+H%]-05@+:Q0^"T&".^`;FHY$`!9IT1 +M:&R$ENRQ2$>1%A#&*R\466G@[JE7IH$`0$QBN#^#<^>3*/4@&>V59O$BH3JP +MKT62;#2"-^$8UR_#`H_[QL4]`XF&>SR3?@@3BX<*_JGC<'%5I0!UKZF7<7PSKFV!,]9X0=>Q\YS"+>G+V;#>"-"%-) +M1:#D=1.TV56\L3$1T/BORY6(_1U4=%8([W3PHIR[N'6+5L.G:NJ`W=78>FS+ +MG)>MXH:?N@U`&MJQ/P!F)D8/IFOA`*`51"H5&SFB:@@E2%,G)!O<[(BW%`Z+ +MFD5DG@I*@0]`X%3[Q1SH?1"=E.^ICW38DTXRZ7,1T=&6/("@U*2!7J)J.,00 +MT&7*=+9DO<0Z3W$.49(DMD':OZV[$'2VB+GR@7\@71JU(9?8F*!<3)&)*)@) +M8"[%UCD/\7O>/4EKE,440IR!+_!)AH")KL8J\Y1[0_LR4`I@JMCEH'M%T)8'[3: +M.7`6S#1:?%1#*>54`%8Z2P4#]S%B&_V61"Y,)("&PB4(`.?[C%?-J(?!-P_V +MKA:8H"G!Q2H].,.F'`T0J5+ZRVZ85AWI*N1B`8XOP7B<'#.;CJ*`G$9U%=O3/OVUF-OYYO3*G0K<[Y"%JX +M!X'#3S>P91<8Y-M-Z(0"Q_5-057,XS7*28Y')2*J7JJ_YD_SM7L@9-%NE)FN +M69TZ[;P-E8#\Y4AARJI`$6'](`O\MU7WIY<+CZ"*D/S-9[.=><+5K5G@WN"` +MB8:KHE*C_Q;\H_)G++W<[U"$K08NWP\U=SCFS"-;X;)SD4^*G#,CA('):_*S +M3*`"[MN"U\78A]Y^<=^7K^$FRTG\'>_SJCL9T +M$M"4ZUHJ/0EA^[PFK7Q;A(]-XN"OH#6$UD_>SG[@H><$6=?N#&-( +M8U!+]F`_72)=<[]`.?T[V@.OXQSLP$L<;_U]<"S%67%`?#N/XP24IE*&:FY/ +M/]><-A.`]LU1CP7C['B^B/\F5@IV24JC-_9TC0V_8E&&P13B^PZ`,.60P+_0 +MYN4)5L%`9^^!G[/#2>670#$FI9ZWD$^H[Q4T5X8!>3*5O-JJJ-@U7'!G(I[[ +M1".^J"/]&L'`?EZ/V4Y=41%=ZW]WF@%YSJW-2(I?"GK[)$+7C@I[D?FE2XJV +M#'61D;M2X2V.KG4IM.HTA(%3TZE:I-U)?SC>R.CBE3.!;1CDHOWK-,3R+('J +M;Q9TK_=H>)E9'=DFIO'7<4DPL-C"JG2$'P$^SO*'",7=;Z4M--IOR+8L77 +MKFY%V);CG'\H4(:WG65D!7T1\L&YJ[;J\Z!!]!>_8L@4\_+%1F)!]--)`88$ +M?&?TR&;0;@%<8[JA=KB)Z^:U5^;UT#O:.WTN^*GWC)M);IF@=[&ANVG)0HN6 +MWI6)5XC5T#-U5/%BTU]+&LQ%-ZL#+31#NZ,W6^VLT+E"2XDPCM]2D?N.6=O3=E'0I3B+-)_8 +M8N2D[;@(>GVU8<>K^H:>-3)/469((HJ<;6CJ=KK2X!'!\58]OVRT\[1DV%U] +M]+;#PU7;O9`@&L;N0[U2Y@W2A-BOF`(W&&K0H,S2"5<>AR;@*^<,IOOFQ!U'L7^$Z\_D.?L;QY3J$>,W +MN$Q\]NFT?*;NZG_M#+:\_QZ[S7@V;?[0&J6__G*)]4W)`\_0^XZ/R3:#K@K6 +M:\'O[:!@B5S11B6L!7`+;.HUC9J$NGM(-^_$H//_Q^>`S:\O3"18!4__4F7R +MH')EA?'O33NS:7&?NTW9`?JJ6LS?_X^IPYJ!Z-0=WP[O,1K_W1`?[$7WE-XB +M.2OL-@GHY[[M]81'*WAM.[/'#)RHM!IZQG]$)PR][O1P[*4$8GX.\RJC^Y!) +M@8_V`(]5%ZF?!0$W5GHLA@ED:VDN?@V[C,*97#R42-NTMYJN?T'&^9*DHBGS +MW7<>Q=B%,(O&;%V222=;"N<4?;@TEI_N7=;L5%TK7H#G%&V$0W![+EJ#/];- +MJ5_:YB?0ER`ESRD3-"*;?]I8P?4?,0/%B;.-+Q*NFZZJ,3HU)%7["@!H"059 +MC#IY""-+"[C-/08(4I>EA*`;@(<$$AKE?.DQ,&/UQ0/K.V5HX5`-"?VMV*WQ +MP$G>?H1+KU,LQ3-+`GS.=>!$H2PGKS.OOBUK-<9'X/"]'FR$S]Q4S@]C"MUX +M84HP;6F6I$9PY<5N.A]:,3AT2Z:7X!.LW"SGLX&1WZ^6:U5`^%VJ*"HJ)2Q> +MR<@`'/+UQN+QY`D;S.@[Q97M"YI^`V2LX019:A-4J-C<8;Q+2=O_VI+4_CYU +M$P$T]ASI5Z2NP1\(W4NS*/O8Q1Y6/EUN*]U($#<#']T?-7OZBK:C5*8$#\.\ +M`.?4B6B?0H.VGOEB?`0L$[CWO0RV;PQG[]YO4([OS^KUC!*VS;,:7,B@%/B- +ML,D]E.)F'Q)BX=J>QGX66+-A([-<4XT!"502XQSFA0'$.ZXX!39$L*F)I?UU_TX"L.M-<1SPH)CSO_O +MA8MW[+D&\>VQP,&#GUYN7_]:`O*R:X7CX8Z!!BVU2QBP<531RE'BN,(?(.K$ +M_/1ZJ6?\ZWC_%H$EZBK^[><0D/]$7S^D?T.:$(4@*$_V +MZ(`````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````8``````````````````*$OPP`Q?VO4_^?______________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_______________^@$?\B__K'_I_________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_________________________________________________________Z!' +M_(O_ZQ_Z?___________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________________________________^@3`'1%0R-%\6=F]S/A7.S +M5W8"T;9`[O=G2*&IP\3W2`(833>H2:8/`,[&-M/&Y!GWK4@ +M,-D75WT2#SF#E*Z5VOR5^KBL`````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````````````>K] +M7T\[_GZN?T/^/I_GT/4O.Q?SYW0Y_K]^YZGQ].4NQT.+`?0]2.AT80FY^38M +MC-UH&0]R&?>\/3Z/1^X4ZT^!N4Z4:9*:-$CN+!,AN>Z5('3INPWS_NJT>I`Q +MEA^_#-(OO7'F?`N31Z78C35VD7F4.&08ONMK'Z/IW^>?SOHYT6)%!7H['=ZO6]0\WN9L] +M'/S_R?R[&QY8,@B&!L_=C>&?P",_X=^*>'IUO9+ +M!I_[\_Z8<@.GXJ4\>CJ)&GB\`A!8TU=.$"I:?N=I]G]/<]'-T^M!=`D`XCE8 +M!JN7'E&K`DR"8\?V]-7J,5K7UQ5'<+]FEU.;$!Z4&1SM88*"?3W?+[\X)U>A +MH^#]#>$#56&'M?;J>.KMZ57@N-):N7[XVZ;1QQ;]1WA815)8\@RDMF"/+!(/T>IU? +MWK4OKS=:NG&%]=]*GRD($O%=%K]D%*E2C([A*)0WS=*OR3)?UZJ?1?%ZO+K] +MD&B@AY_W88M'73TMN!`>QOM7_-,4)_7>&W]L&3[?T^O_CYNE>^5_+W/_:R>8 +M&Z.WI9_@C:M]"Y\/W4G'3^Z+?@@J68M.)BZ/`ETX[^-^Z"[SJSX,)F&O/0HZ +M0PV66N,;O7>B\5ZX_>#AUFU*WVI\?&E]W:O[6[?0GQJ>MOWGAI^V)\"68D>& +M2/QE?L_#D"*?D5ZV<\L]1++_QO/P@DUZM6?[Q$%DXZ$[R\N0FZ([,@15!+0L +M!=9%K?M7= +MA:YU^7TJN7R`O'VY%71U(S)-WO;4&+1*YXM.65%X90P;)CC4=H$29N95RL +MRS#O),+>/5R.$9X*^/#N=GV$-TE:7,^."D3YWR48+\6.9(7^'M%":>`)GZ4R +M:N*>"^03M8ZJ74[FGT3>#9D960OE@UX%O&6._ZNJYLCB!,W-B\[)W7['!:PB +M\'XY%V/XRP=KA./R6^X<`T;BS9D,V"+I;FS-Y?XJ$K73X^QY*R2."*'P;UJO +M7E$H&N\X@/C%[1L5_;U7SR]WCO/9):4Y?(EI+>S$%V\]''EIWE6,$>6(O@+3 +ME[G#\?");LM@E?-3?CP*;D*S(U:ON4N?E<%T8)JF54U2VJU7FD,O@Z>QJR-2 +MZ]$'[.JA1.GM]KK]*3WMIN@Q8]9=O^N=OZ0OF$'83HEE&QW&8=Q9SC&7(HZ! +MT\56]-ARZ0CWLE=RG0:U[2V)E.'_K,KXFGKD,JPH2W)[CP\?_D'<+S8C_%+] +MEF32B&FU2Y,@:1B;SG3MZD%#;'BC"9%TM*_796%NG31&MW62'&8VV7G2&W*2 +M8_"I^'X>SX96^#80^^+?/@?3A_FU&%BKB"A6'M_R+O`W;3UFK8'X@2EPRF"B +MB.C*H#7`0[(C!G>Y?E@TZ^!XL9IZ9E*Z5Q"L),WOXAO=#HS/?P^GS03$?ROO +MBVREKR,\I>K(/.)^J/,R(!][,]7T6A38[L;5*M +MPVE56+MFK`W=K>U(0(/$!VRF)'4[YX]$*QA:#)'L^(WZY)E"Q)1K^B:IO3ZK +MA@.6L6=`"_YLZ(0Y&3%,0_)L67=S;-O4#B,0'6 +M)R[=^,ZP/SWX0 +M@&.8'L81\%H:KS8?+YM;=WC9+O^/@B!''YT.F5OPU\[;]SX+9M#%'>I]%&&W +MG1`U:.-"-[8';;(*FK?I\/LS.-T9XCHO61;2M@$\`6CG'QY4.\P!GUA3?ITK0 +MCW<&SL8L,37TB/+XZ90SU^_0EB>ZOK]_1MDA*F4]:`/,ZQR;5C2@1O+7Q/$52F4OGN\/,_'+"G,R[7/2I +ML$FBRTX>+,"R`D5>')8'I&,]:7?]56WD.)^0#G"0U,68W%CE(W]/6PQ0MZ). +MEB[;?2AL.OC$%1A/+!#J/''Z]?K%@_&YC/\*V^;9#_'SSHD]N\V0$ +MIHKP^J$Y6AY=(?^EEA[BZV[/+6@$A"3V*>`XXEYGQI+%"%?@DKWC,5,9XRBG +M(DCB3:DC7,O:X1##E0=;8G*N,KDE4="68,2VHU`0SLDRPH(H$Y%RN%;TG->M +M7CEJU'K(37^^OJ7O,S+C%JL8X<2NN"?]\NON0;:O0Y^=/?!#'GEP9VO@VX(# +MO7]M?X]1HA445@;>0V`BP8$E=-_:ZTAPQIY[9A\I2Q_=L9@>&,5(2KFQQ\4* +M*J.*B+AW*?*`5[E.3JD;5XL%UE<[5R+HJ*^O*J4MBU*7)5S4_#J\_&(UO +MF-HZ@43FIH#,4-FD4T6"!9<O"/P;L9Y0\$;5>\< +M;Q]KP2?\5:G'1*;2JR2L'T?#/L4Z- +MGC21?PUWK.CGG+[7ZT8.C)'8_7G=L6D8=%L9<$O#1RM>'TQU#I3K..2U.S!< +MG1N#^&'R6-J&&N&RG5WZN95X/S(V[ +M2D03%@"S:CD[T],"*J\LOZQ]K+%H3[(9Y<^Z0#>U9D`\NU,NSZ?:N?X/3?QI*:J(L6>($A+QV[!$AQ8)46R\6"NEJ5\U?;TP3K0" +MU=5=I'H=;4U\[\8:5_?#VZO-2-P(!N,YCV/$&*U=*H256[0JSR89H)LY4XPT +M5TM\KS63+<@_!J;63WE0P!Z//K2TON'^XDKUL3+KA +MDX)KB4#CP3?2";-\^G*COB>2.&;FO5]JT=/^7\KM#RYKM7V_K5^E%>[Z/*X. +MTR*_CYZ_0DJ@8/1(I2Q7S@SD>/^WD&=5=70Y2B]C4!5^7+IL)S&C;)5@>\6# +M5ET-3EI4?=W.`GG8I@F2(!!$:V,5]4?O:'3\5?+%^M66W]%&>O!"[MZMB$/D +MRR?VZ4"2L?S$[1D#@=M95,6MKTC\C&%[XM+Y[N">&]*BY9?3`;8O;M>-B?KQDWU&&LKY +MO*7BN&Z)?.1LJ9O&\SL.%4K;C4F@!9NMF:=/8UM.OVN_[WZR2-K._^\9OGE/ +M8Z4/D)G&82NF::OD)F;4KU#B?LB_ON7)G*2`48/P@BRROKP^*$_2R0G^YH=[ +ML9>R6.]N[.33"H=?,_CT.?FQ98>3V_Y09`[MO>)F+Y9DU7KK_H\=2!=E-_'L[\&W'RYVML>6W +M2B5XVTKCM8$=QWDW7T)C=H/2`M>F>1Z.EFT89XYM6]Y`.74[6+UO9V-#+L2* +MRG?O$G&H]`_8.C5?AT",*;PS'GFM70XN>WV4Q427^(`*\/X#CB^ +M$(`_Z;QM?B78W;%ULSQ]SP7'831UC7'T-)1'M@\&T\A :U"^,-";S5OB:6 +MG$,M^1P8+(5[>J-K6.5*L'$0+)C=0HM;#!4F--U/NZDV&E#R0UWL[7NQTR?( +MK-5,,P+(U-G9HX8/FZ7$?96E_ZGDBWBI,:/#Y=^S;#LY:>^CB6&-NY)Y7X[_!HZ6Z,D&]`WT!%WRJ<9];OD]9 +MY>24+=]B3T1H[A.%^F.1/,DM#4>!\9]0K>"FYBN[!+*PDPZ'TMGH"-NLKU?X +MK&8!'XW9[RE.P5>/,E6Z?%N:LC`<1CX,4F<@B!KO78!YO$IQ`''Q7JO"IX\? +MBBR#]:TMSQ5EEG7D[+^G+:=BG2QFL>/BO +M-QZJZ$.H`J_PPEC.-JXBK7]T=G#'\]ON_/CN":U"TF8LK:^LVXWN3E`F6;_# +MF@\C#/D]9LWKT#%HA\3BFCW4MIP#\!5<]$0Y$=*]?;JE'.^>7#5O5WUX9)44 +M:))UM76AT?_M55^=35MH +M8SBP1JTK'D6Y=#^?WQI>=*9C8FR=6JV)]+T%__'6]A[DT)F]% +MM.9/8%$580S)=?9\16F`[F7>"]22&A^BE$`:%]89YK8LMX4\?*>YWLG)25RK +M*.K)901`V]&IJZOJ1J_6GW!LR>I^"`[07J:]@%V?5BQJ?SP/;WQ=6$)VG)G> +M,CD;"*2]BO';UTABY)#56A_?JZ>CVO<+0[/9T^Y#1S1\ +M'1BO@_7G[F+:SX]=K^LYM7V:F+!8@8VWCQE9ON?5'U;4?[#8J%5Z%VJ6=4&'1J4HO;()4E6Z9]B#F&EOGA"Y]OY\)@Z$KQP\]L>4<',^O+3P:'OZ[N0-$59`T+&V[RU6]6;[V-V/2 +M\DOQI9RJV8A[VJ&3N-FHO1'WX^C$`6&2L/DNQK)5_WUI\QDNC?X],*1X0H=% +MT;6[0R[0Y+&X>-&5*QYNCCJ;63LCPVSZ%<=8_&<$7YI5O82X$^Z<##T4I_XS;/-5[M4JN)*<.,PUX=<@21*+8?\@!8`NJL$\VJOXQXJ9_D +M3.WKH>4UTR@[R57^/8HS5-09>'[^!EC_/B&H.[#.Q3A=.O\W-$D=K*48D@J19KZ-UX@W5I(05CF6[ +M[(CXM-/'Q^C,.*&X3^7'/##8'_F>E+Z+.!7!K[5XEI)C,E`)2K9=PC^3W!*> +M/=^JWKV#J"(QKCPP6:'6E9)Y.J(:%'W-59W0K-G+@+-9/@"A""&TDQUZZ*Z!(7K==%W;K&"$J@J +MALS;75>P>"E5\-;N4E/M +M0A%P9LKU*,B)FLB7(LC%+GP-Z^OAE/&,`'46Y6\TGV,SB'PST\;25YCUTI@) +M"8'KR_&OC2FE?A7ZGV6/IWY1];IKK:><9*`-O+^*CC4T2?\3C +M_M'7BFGLD;Y)8-WV+?F70"PKR_K2?DS;!F2K#Q)U^)[$X!XV5*%UYZ=7A]'N +MJRJW(KWG&Y:)'M=LW^%%XYMC7J/SQ2BQFE=9%4H:KU#/U&Z)XW&/F1DY^*&? +MKF)^:[Y;RQ8402:`0.G!SK912WR+3;6S1-%I+>%40ZT<0YQAHQO;* +M\@_]:\Z&\O@X6JRH!7L'0]=%F\#4G+=W3O;]?@ST(*H"J*!>=9,1I"NM^<5$ +M,?M3##_F0@61;>:`LF\VDL')];&<]T56:4]2!OY.9(`/*6V>1@]'8#"*GU77 +M;#NK:^GSZ[&-$_(WYR<(5I51ZVR&>0E=MYM$UWTOV5=5'&,CR +MBKOW;AR"NES,-/?Z>M505*><)/.8)UL,A0CY:\.+IC`GC%8_TJ5_HG*`HW#K&]2WB/L(8";`73ZE8Y;1D(J@(T,=])2H!$P7 +M0R:0/B15*(]<*@J1D[43+>O$MZ$A&')!G0?"`I/RWJEW*L#<#D!I$\V:\",/ +M[J!XYT&0)B+9L6#"$>!0#V` +M*;I#]B(J/TC[I-H4P\V$J3&_7VBB^Z,]'9,8PUO5QM2^Y5?P +M1\:_.IO%T4N"#U2-1H8Z]$6"3B%^+CQZ7CM4]>!+A*F1!\CK@_PCBB3,5V$W +MFK@M_W+2%)';;*J7&Y01`W``3(_X7]KVPYX0A2`H3^W1```````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````%`2_#`#%_:]3_Y________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________________________________________________________Z` +M1_R+_^L?^G__________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M________________________________________H$S/],17/Z59'_P````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````(``````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````'!,`9$53(T7Q5F;[,_%5R8N9`6#;(',YDX1 +M0Q.'4\P@"&$PSB$FF#V!OD8VT]MR#/_42!R0!DOIUT[>VQ[89(N+GPD'O6]7 +M5U=W5U===[_)5Z$7E>5T:I72NUXE?QTE8``````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````!ZOS?3SO^?JY_0_ +MX^G^?0]2\[%_/G=#G^OW[GJ?'TY2['0XL!]#U(Z'1A";GY-BV,W6@9#W(9][ +MP]/H]'[A3K3X&Y3I1IDIHT2.XL$R&Y[I4@=.F[#?/^ZK1ZD#&6'[\,TB^]<> +M9\"Y-'I=B--7:1>90X9!B^ZVMRLSBZ9H3>*UL(X9WO3T;88(NBWJ;FWYMCU: +M_`%SO[.K)IJ?V@]X?H^G?YY_.^CG18D4%>CL=WJ];U#S>YFST<_/_)_+L;'E +M@R"(8&S]S/W[H'VO3[-G[XE?]16`H7C7$6F?`7.ERJ_\NC3.&L[XU<8.@9'& +ML'1%!-IUL?&T8$DS.,.S_X.*MFY1YV-X9_`(S_AWXIX>G6]DL&G_OS_IAR`Z +M?BI3QZ.HD:>+P"$%C35TX0*EI^YVGV?T]ST4:L"3( +M)CQ_;TU>HQ6M?7%4=POV:74YL0'I09'.UA@H)]/=\OOS@G5Z&CX/T-X0-588 +M>U]NIXZNWI5>"XTEJY?OC;IM''%S(ZHSSRMS1_9,TNG9F9*F04#YUGBD(U/- +M>&+/_<==8H-%>N,41#3C!FNWYH_9"0.>;IUU'VT]?W7S>YV]+1\&G+.*[KK$ +M#3UQL@WJ0$J6U([]?U5-)YOU'>%A%4ECR#*2V8(\L$@_1ZG5_>M2^O-UJZ<8 +M7UWTJ?*0@2\5T6OV04J5*,CN$HE#?-TJ_),E_7JI]%\7J\NOV0:*"'G_=ABT +M==/2VX$![&^U?\TQ0G]=X;?VP9/M_3Z_^/FZ5[Y7\O<_]K)Y@;H[>EG^"-JW +MT+GP_=2<=/[HM^""I9BTXF+H\"73COXW[H+O.K/@PF8:\]"CI##99:XQN]=Z +M+Q7KC]X.'6;4K?:GQ\:7W=J_M;M]"?&IZV_>>&G[8GP)9B1X9(_&5^S\.0(I +M^17K9SRSU$LO_&\_""37JU9_O$063CH3O+RY";HCLR!%4$M"P%R2C.-H4T+? +MC(5%67(4L1#KH$O:A2=CZ)I=,W#/<=T<&R;OD^+GR7]R>;S\[^F=SHQ[7Y?2JY +M?("\?;D5='4C,DW>]M08M$KGBTY947AE#!LF.-1V@1)FYE7*S+,.\DPMX]7( +MX1G@KX\.YV?80W25IT4)IX`F?I3)JXIX+Y!.UCJ +MI=3N:?1-X-R+CMH^S0QQ>.!3VST>W\OZO1/ARI:U0G<^O;3?@AFLT3F^I]O8 +MV(QKO1N<6+Q&9-K=QA#.ND9M!7LK*_-MU6##8]^H@N)@J;S3BOVQ,LPCG>58 +M2+:*V35;YCEAI24B(J0M\Y2JU<8P+_FJF;]*S-YF1E9"^6#7@6\98[_JZKFR.($S42@:[SB`^, +M7M&Q7]O5?/+W>.\]DEI3E\B6DM[,07;ST<>6G>58P1Y8B^`M.7N:0R^#I[&K(U+KT0?LZJ%$Z> +MWVNOTI/>VFZ#%CUEV_ZYV_I"^80=A.B64;'<9AW%G.,9R5W*=!K7M+8F4X?^LROB:>N0RK"A+*,)D72TK]=E86Z=-$:W=9(<9C;9>=(;W_(N\#=M/6:M@?B!*7#*8**(Z,J@-_B&]T.C,]_#Z?-!,1_*^^+;*6O(SREZL +M@\XGZH\S(@'WLQS%ONS2;9EI`:]'J]Q($R)P>2I_(_!G;?HH[593:IE9]G0N +M7S-](4?7E>^>4@I>78H-U)&4K?"-R8TN"?![U?1:%-CNQM4JW#:558NV:L#= +MVM[4A`@\0';*8D=3OGCT0K&%H,D>SXC?KDF4+$E&OZ)JF]/JN&`Y9RTDR+%8 +M]^*4''I8+H\7)5ZQ9T`+_FSHA#D9,4Q#\FQ9=W-LV]0.(Q`=9P_H\#:E^/YF +M=;M#E_.?M8*%`9].H%QA'P6A +MJO-A\OFUMW>-DN_X^"($=$#5HXT(WM@ +M=ML@J:M^GP]S@I5F3)6[EI$<8?3D9#S8$P;-.DD>1K$W7P;>-/K4K#]U>BD`I:`94LW0A136V-35Q0\D*D4T-.9G4K\]6 +MS1LQRXX;IZS,XW1GB.B]9%M*V`3P!:.[P\S\D8SUI=_U5;>0XGY`.<)#4Q9C<6.4C?T];#%"WHDZ6+MM]*&PZ^, +M05&$\L$.H\(J=%/63*%6059 +MI5S;NN4@+*&;)3H3XYQ[U^L6#\;F,_PK;YMD/\?/.B3V[S9`2FBO#ZH3E:'E +MTA_Z66'N+K;L\M:`2$)/8IX#CB7F?&DL4(5^"2O>,Q4QGC**.6K4>LA-?[ +MZ^I>\S,N,6JQCAQ*ZX)_WRZ^Y!MJ]#GYT]\$,>>7!G:^#;@@.]?VU_CU&B%1 +M16!MY#8"+!@25TW]KK2'#&GGMF'RE+']VQF!X8Q4A*N;''Q0HJHXJ(N'9O^=R)+AZ\(_!NQGE#P1M5[QQO'VO!)_Q5IR +M'1JT;BWYEV@ON#"YHZ%6D3QO2/EJIZ<=$IM*K)*P?1\,^Q3HV>-)%_#7>LZ. +M>=VQ:1AT6QEP2\-'*UX?3'4.E.LXY+4[,%R=&X/X8?)8VH +M8:YR2\>?]/](B1SKD^/_1!`&*R=_?9X;*=7?JYE7@_,C;M*1!,6`+-J.3 +MO3TP(JKRR_K'VLL6A/LAGES[I`-[5F0#R[5R,D'<'5V7FO&[/DNM65XR[/I] +MJY_@]-_&DIJHBQ9X@2$O';L$2'%@E1;+Q8*Z6I7S5]O3!.M`+5U5VD>AUM37 +MSOQAI7]\/;J\U(W`@&XSF/8\08K5TJA)5;M"K/)AF@FSE3C#172WRO-9P%3( +M%W9*KVMY,MR#\&IM9/>5#`'H\^M+2^X?[B2O6Q,MS7E0A;A2;>E]NW%CUQV. +M7+EER,>/:W=G;V*-1B.2,#MO`)O[>S@U]+2[-66W]:PCNAZN&3@FN)0./!-] +M()LWSZ09U5U=#E*+V-0%7Y=BF"9(@$$1K8Q7U1^]H=/Q5\L7ZU9;?T49Z\$+NWJV(0^3+)_;I0)*Q_, +M3M&0.!VUE4Q:VO2/R,87OBTOGNX)X;TJ+EE],!MB]NUR,[$M7-\<\+Y#,;N]_M1K)GI77QKEBYM>4MI;7+,J#B?E7"&?@C-PLV15)1(A)GD)$8@P.MK)YXV)^O&3?48:ROF\I>*X;HE\Y& +MRIF\;S.PX52MN-2:`%FZV9IT]C6TZ_:[_O?K)(VL[_[QF^>4]CI0^0F<9A*Z +M9IJ^0F9M2O4.)^R+^^YNO^CQU(%V4W]RLQE88IE2.BPQ +MAKV,CR\8MSJNU7777A5*'O2[F\\/>IT9MX>SOP;3=?0F-V@]("UZ9Y'HZ6;1AGCFU;WD`Y=3M8O6]G8T,NQ(K*=^\2<:CT#] +M@Z-5^'0(PIO#,>>:U=#BY[?93%1)?X@`KQRVC3SHS%X_@..+X0@#_IO&U^)= +MC=L76S/'W/!<=A-'6-V#P;3R$8-EK4+XPT)O-6^)I:<0RWY'!@LA7 +MMZHVM8Y4JP<1`LF-U"BUL,%28TW4^[J38:4/)#7>SM>['3)\BLU4PS`LC4V= +MFCA@^;I<1]E:7_J>2+>*DQH\/EW[-S9EQ.TXS="/O>]BNW50:/>O+OQ.-JE0 +M`3%YL.SEI[Z.)88V[DGE?CO\&CI;HR0;T#?0$7?*IQGUN^3UGEY)0MWV)/1& +MCN$X7Z8Y$\R2T-1X'QGU"MX*;F*[L$LK"3#H?2V>@(VZRO5_BL9@$?C=GO*4 +M[!5X\R5;I\6YJR,!Q&/@Q29R"(&N]=@'F\2G$`J\*GCQ^*+(/UK2W/%6 +M65P'F=(FR7*_.?DKCM)DEZ=>3LOZY.4"99O\.:#R,,^3UFS> +MO0,6B'Q.*:/=2VG`/P%5ST1#D1TKU]NJ4<[YY<-6]7?7ADE11HDG6U=:'1_^ +MUS+C>IC^`2INA63>GEDM8_P[N/1; +MET/Y_?&EYTIF-B;)U:K8GTO05S`3*R`L,0%2$9*[SBV? +M!*ZO]N9R/A+ZMG>$V;_'R[?U7HS-EWC#[[MO:ULV2U+.DLLTV""@#FZ,$'.G +M=,/;L0_9^'0IV%K/Y0/%:^#FQRKI;\V#@V][_\=;V'N30F;T6TYD]@415A#, +MEU]GQ%:8#N9=X+U)(:'Z*40!H7UAGFMBRWA3Q\I[G>RIKV`79]6+&I_/`]O?%U80G:GB,BX@'\MT1.ND3\+D9RKS%4LC94+WR+O +M#I5%G-L=8]R*!I#5.V7#`,HCNP2_"#-G$GE4B69\7+GGUVOYNE_6D(71'WCB +M97ETLMT2"Y6BK*)9>L3>+.]%KG4)T^(G\+`A$[K'-B27U"2YM;=F1'6BV4KA +MCWJ=LQ8I`^%[V*\=O72&+DD-5:']^KIZ/:]PM#L]G3[D-'-'P=&*^#]>?N8M +MK/CUVOZSFU?9J8L%B!C9S?Y<:8[6A]GMO3T.GV>C]G;[?9^OM]JK?:ZV1LB/&5F^Y +M]4?5M1_L-BH57H7:I9U08=&I2B]L@E25;IGV(.8:6^>$+ES#DK\KE=G'6IM? +M8LV;4$.OB5MK?5`!1L]O:0T$GNQTV3].>,)]:3S@E6U9KDKAPNN5+9.2::]/ +MN:/;N:;5S,+0T)\0%=/2[&AW>KU*!SK=:J,@(2N"PW%9W!KB\T>WT[3%?)+Y +M[V_GPF#H2O%R8)_`P9'B__T&"X-I_\KV0>A("_D/:L>!3(?BJ2Y"RVW7$:-= +M2G^'Z",NLI#;QDHK&K(;<;_]?;H%)^9E2*BV.C;($ZV->]'M7_KNY`T15D#0L;;O+5;U9OO8W8]+R2_&EG*K9B' +MO:H9.XV:B]$??CZ,0!89*P^2[&LE7_?6GS&2Z-_CTPI'A"AT71M;M#+M#DL; +MAXT94K'FZ..IMS?4VM*[>-&8[B#UHSF.2)!7WRJLA$AJR#L;>/NJS\*9\JXP +M4:2'U)]W2EC2#[BP9%1GY)R*=CJ]/^^G"CHO5AO,[W4Z1*BZ?=]P.]V]/V3[.[H>Q='K>Z?5NF;D>W\K)STYV/HOPQOZDH@[MU;7`DDVF=L1+MBC0[>WK2J%+` +M!PK6QT>.I+5Z?'8Y5R\-6]78Y]K9`\U^8BL-RIT=/P)W=MUW`<`+7@7.J_M% +M?&GL*GT`9Y9.R/#;/H5QUC\9P1?FE6]A+@3[IP,/12G_AS*3.>)L-E>+_%NQ +M=[-L\U7NU2JXDIPXS#7AUR!)$HMA_R`%@"ZJP3S:J_C'BIG^1,[>NAY373*# +MO)5?X]BC-4U!EX?OX&6/\^(:@[L,[%.%TZ_QP]`!V<@\;EL@[&7&E +MD&AW(BSGW*'RLG2C+__M/40````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````?^TO(_HQ?VO4_^?__________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M___________^@$?\B__K'_I_____________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_____________________________________________________Z!'_(O_ +MZQ_Z?_______________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________________________________^@1_R+_^L?^G______________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M________________H$?\B__K'_I_________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_____________________________________________]"'A_UBY2R"4]W" +ML*RE:_OGG3#+\L@,>,PN7D[&4009/5G@?.;JM:BXCPHCK]VV[!W!8P +MYAI3ZHH(AMZ-VR@&&VJ'#SQX0QE)?R4N3VT'614`IIGL^R($79%MI#B-X4CY +M2<,-?%!I-[HQ#M]PYYZ?6SOAM+5LW +MF&<#GI93057E-9"T'5(%972#)X_X&MZ%%>,"#R0K[^%DUAQ_L=6WC_=;3^$B&IX@7 +M6#\FJ!/@DO,_:Q4&@$=1%+9L9'QX-`*25C]4+S1EM<'\+&/@+SZ!Z;8S%PZ; +M(==I$41B7WFK6VK3@'SRI+W`+B[X)G@4O0_W,7;CI_)#=I9$>48_/@*[!9_P6E;Z30VBMPXWC4A +MRUON:T2OHRGTI6-N1.9O4Q7!K2]V<9LB\ZOK`;O-+6./K\O;V>YL3U0;<@G] +MLA2,Q)]X^--?L#,";:,7QJQN4A;W5Z;,Q7 +M)^5/T,L?'O%IN1VBJHSYE"_F##3P-7AKO2*<+FA"Q7SX?[-K1*!"L]\N9+:. +M0,0/+O.NFOO8/98)R4T.=YUS'P05OYLC5UIA3#;.%]R3H86ZW$_$0R7#/%`, +MXN35/Z7_EIY(DISE:VN1+&?5:$\/OB?_.UY_;YHU]1>KOO^1>SO&=^G!C.=( +MELO]V=4)15`MSI")D`+9IQ_M4>U*+:4'_Z>[O6X((_Q"?<;ZJ5$<+9V6$EU40\:$&L%"BJB(8<0I[G_ +M!\`J./DJ`+W_1/'D9-O>\"'>)A+>%(A^RMG>^['D=3[P%6?=^<0A-E2XHAZ& +MM=M"/D&+NG;>+:_<_&(J-_X/$>`%(*^FHJEU.9*6OP.!?U:YX0_DSJ)4K>;9 +M<`K%R=FAF@5??,.T'?Q$9N9;%S:]GTXV!-OLL]NJ;\1'O+T/NS/BRH>?$*/D +M[P!,C_A?VNV'/"$*0%"?VZ(````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````````H!+\,`, +M7]KU/_G_____________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_____________________________________________________U95>P]` +/%`##I8[U```````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_multivolume.part0002.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_multivolume.part0002.rar.uu new file mode 100644 index 0000000..696ff56 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_multivolume.part0002.rar.uu @@ -0,0 +1,1337 @@ +begin 644 - +M4F%R(1H'`!EZD``&I!9PX#%Y:4IOAM$C\= +M-1T`I($``'!P;61?;'IS?$J_A%^K +M]7@Y2NE=K\E:7/38```````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````'J_/Z>=_S]7/Z'_'T_SZ'J7G8OY\[H +M<_U^_<]3X^G*78Z'%@/H>I'0Z,(3<_)L6QFZT#(>Y#/O>'I]'H_<*=:?`W*= +M*-,E-&B1W%@F0W/=*D#ITW8;Y_W5:/4@8RP_?AFD7WKCS/@7)H]+L1IJ[2+S +M*'#(,7W6UN5F<73-";Q6MA'#.]Z>C;#!%T6]3K7X`N=_9U9--3^T'O +M#]'T[_//YWTH>;W,V>CGY_Y/Y=C8\L&01#`V?N9^_=`^U +MZ?9L_?$K_J*P%"\:XBTSX"YTN57_ET:9PUG?&KC!T#(XU@Z(H)M.MCXVC`DF +M9QAV?_!Q5LW*/.QO#/X!&?\._%/#TZWLE@T_]^?],.0'3\5*>/1U$C3Q>`0@ +ML::NG"!4M/W.T^S^GN>CFZ?6@N@2`<1RL`U7+CRC5@29!,>/[>FKU&*UKZXJ +MCN%^S2ZG-B`]*#(YVL,%!/I[OE]^<$ZO0T?!^AO"!JK##VOMU/'5V]*KP7&D +MM7+]\;=-HXXN9'5&>>5N:/[)FET[,S)4R"@?.L\4A&IYKPQ9_[CKK%!HKUQB +MB(:<8,UV_-'[(2!SS=.NH^VGK^Z^;W.WI:/@TY9Q7==8@:>N-D&]2`E2VI'? +MK^JII/-^H[PL(JDL>0926S!'E@D'Z/4ZO[UJ7UYNM73C"^N^E3Y2$"7BNBU^ +MR"E2I1D=PE$H;YNE7Y)DOZ]5/HOB]7EU^R#100\_[L,6CKIZ6W`@/8WVK_FF +M*$_KO#;^V#)]OZ?7_Q\W2O?*_E[G_M9/,#=';TL_P1M6^A<^'[J3CI_=%OP0 +M5+,6G$Q='@2Z<=_&_=!=YU9\&$S#7GH4=(8;++7&-WKO1>*]6>HEE_XWG +MX02:]6K/]XB"R<="=Y>7(3=$=F0(J@EH6`N249QM"FA;\9"HJRY"EB(==`E[ +M4*3L?1-+IFX9[CNC@V3=\GQ;DZ96QH>C%MN4HE9"R03,]B.#?5\%/.LBUOVKNPM[@^$)19E-9HX1W=F7.%0/ +MS:+=WTNWQ[?%D&'W%BA>CT^2_N3S>?G?TSN=&/:_+Z57+Y`7C[V>CV_E_5Z)\.5+6J$[GU[:;\$,UFB(S)M; +MN,(9UTC-H*]E97YMNJP8;'OU$%Q,%3>:<5^V)EF$<[RK"1;16R:K?,=D[K]C@M81>#\<0'QB]HV*_MZKYY>[QWG +MLDM*>CCRT[RK&"/+$7P%IR]SA^/A$MV6P2OFIOQX%-R%9D:M +M7W*7/RN"Z,$U3*J:I;5:KS2&7P=/8U9&I=>B#]G50HG3V^UU^E)[VTW08L>L +MNW_7.W](7S"#L)T2RC8[C,.XLYQC+D4=`Z>*K>FPY=(1[V2NY3H-:]I;$RG# +M_UF5\33UR&584);D]QX>/_R#N%YL1_BE^RS)I1#3:I4O5D'G$_5'F9$`^]F.8 +MM]V:3;,M(#7H]7N)`F1.#R5/Y'X,[;]%':K*;5,K/LZ%R^9OI"CZ\KWSRD%+ +MR[%!NI(RE;X1N3&EP3X/>KZ+0IL=V-JE6X;2JK%VS5@;NUO:D($'B`[93$CJ +M=\\>B%8PM!DCV?$;]4'S=++['9N4X&O$Y=N_&=8'Y[\(0#',#V,(^"T-5YL/E\VMN[QLEW_ +M'P1`CC\Z'3*WX:^=M^Y\%LVABCO4^BC#;SH@:M'&A&]L#MMD%35OT^'N<%*L +MR9*W;`F#9ITDCR-8FZ^#;QI[C]X%!XD7Y#F]CJC'^^0,;#OR, +M[U:E8?NKT4@%+0#*EFZ$**:VQJ:N*'DA4BFAIS,ZE?GJV:-F.7'#=/69G&Z, +M\1T7K(MI6P">`+1SCX\J'>8`SZPIOTZ5H1[N#9V,6&)KZ1'E\=,H9Z_?H2Q/ +M=7U^_HVR0E3*>M`'F=8Y-JQI0(WEN3^?%=([E;=GW/@>2I!>_FP<`^U''F?CEA3F9=KGI4V"319:M+O +M^JK;R'$_(!SA(:F+,;BQRD;^GK88H6]$G2Q=MOI0V'7QB"HPGE@AU'CC].== +M>OD5NHF7YD$TK.H`)PSKM<"9?\@G+5NJ#,ME=_'G!"YSD;<;AE$;_G@T,]N: +M6](`V=`FY?E-&*;K4-JT%2M\YU[BC:3Q%3HIZR90JR"K-*N;=URD!90S9*=" +M?'./>OUBP?CW>;("4T5X?5"HT0J**P-O(;`18,"2NF_ +MM=:0X8T\]LP^4I8_NV,P/#&*D)5S8X^*%%5'%1%P[E/E`*]RG)U2-J\6"ZRN +M=JY%T5%?#!JWE5*6Q:E+DJYJ?AU>?C$:WS&T=0*)S4T!F*&S2*:+!`LN.<4D +M3H<7&1^;S-_SN1)"-JO>.-X^UX)/^*M.0Z-6C<6_,NT%]P87 +M-'0JTB>-Z1\M5/3CHE-I59)6#Z/AGV*=&SQI(OX:[UG1SSE]K]:,'1DCL?KS +MNV+2,.BV,N"7AHY6O#Z8ZATIUG'):G9@N3HW!_##Y+&U##7.27CS_I_I$2.= +MF!%5>67]8^UEB +MT)]D,\N?=(!O:LR`>7:N1D@[@ZNR\UXW9\EUJRO&79]/M7/\'IOXTE-5$6+/ +M$"0EX[=@B0XL$J+9>+!72U*^:OMZ8)UH!:NJNTCT.MJ:^=^,-*_OA[=7FI&X +M$`W&UO)EN0?@U- +MK)[RH8`]'GUI:7W#_<25ZV)EN:\J$+<*3;TOMVXL>N.QRYQ1 +MJ,1R1@=MX!-_;V<&OI:79JRV_K6$=T/5PR<$UQ*!QX)OI!-F^?3E1WQ/)'#- +MS7J^U:.G_+^5VAYQJ`J_+ETV$YC1MDJP/>+!JRZ&IRTJ/N[G`3SL4P3)$`@B-;& +M*^J/WM#I^*OEB_6K+;^BC/7@A=V]6Q"'R99/[=*!)6/YB=HR!P.VLJF+6UZ1 +M^1C"]\6E\]W!/#>E1!7CZ9V'"J5MQJ3 +M0`LW6S-.GL:VG7[7?][]9)&UG?_>,WSRGL=*'R$SC,)73--7R$S-J5ZAQ/V1 +M?WW+DSE)`*,'X01997UX?%"?I9(3_W=G)IA4.OF?QZ'/S8LL/ +M)[?\H,@=VWO$S%\LR:KUU_T>.I`NRF_N5F,K#%,J1T6&,->QD>7C%N=5VJZZ +MZ\*I0]Z7\@'+J=K%ZWL[&AEV)%93OWB3C4>@?L'1JOPZ!&%-X9CSS +M6KH<7/;[*8J)+_$`%>.6T:>=&8O'\!QQ?"$`?]-XVOQ+L;MBZV9X^YX+CL)H +MZQKCZ&DHCVP>#:>0C!LM:A?&&A-YJWQ-+3B&6_(X,%D*]O5&UK'*E6#B(%DQ +MNH46MA@J3&FZGW=2;#2AY(:[V=KW8Z9/D5FJF&8%D:FSLT<,'S=+B/LK2_]3 +MR1;Q4F-'A\N_9N;,N)VG&;H1][WL5VZJ#1[UY=^)QM4J`"8O-AV@;Z`B[Y5.,^MWR>L\O)*%N^Q)Z(T=PG"_3'(GF26AJ/ +M`^,^H5O!3/Q19!^M:6YXJRRN`\SI$V2Y7YS\E +M<=I,DO3KR=E_3EM.Q3I8S6/'Q.9N*P5/7FX]5="'4`5?X82QG&U<15K^Z.SA +MC^>WW?GQW!-:A:3,65M?6;<;W)R@3+-_AS0>1AGR>LV;UZ!BT0^)Q31[J6TX +M!^`JN>B(OMU2CG?/+AJWJ[Z\,DJ*-$DZVKK0Z/_VN9<;U,?P"5-T*R; +MT\LEK'^'=Q[C_A1[%C_@LS>&O*J_.IJVT,9Q8(U:5CR+<6SG">\*[[L0?/T?<3SX)75_MS.1\)?5L[P +MFS?X^7;^J]&9LN\8??=M[6MFR6I9TEEFFP04`P]R:$S>BVG,GL"B*L(9DNOL^(K3`=S+O!>I +M)#0_12B`-"^L,\UL66\*>/E/<[V3DI*Y5E'5DLH(@;>C4U=7U(U?K3[@V9/4 +M_!`=H+U->P"[/JQ8U/YX'M[XNK"$[3DSO&1R-A%).5$7Q!_$Y';T\1D7$`_E +MNB)UTB?A8JED;D<+DAPAN&+4#[5-U]'SS*A>^1=X=*HLYMCK'N10-(: +MIVRX8!E$=V"7X09LXD\JD2S/BY<\^NU_-TOZTA"Z(^\<3*\NEENB07*T591+ +M+UB;Q9WHM]3MF+%('PO>Q7C +MMZZ0QNU_6AT^ST?L[?;[/U]OM5;[73E4T^41=^;!/L1"OKHRR4 +MH+K@4KZ2SLKOW&WQC6#.^B-:[,5*;VR-D3E6/;QXRLWW/JCZMJ/]AL5"J]"[ +M5+.J##HU*47MD$J2K=,^Q!S#2WSPA<$JVK-I0.=;K51D!"5P6&XK.X-<7FCV^G:8KY)?/>W\^$P="5XN3!/X +M&#(\7_^@P7!M/_E>R#T)`7\A[5CP*9#\527(66VZXC1KJ4_P_01EUE(;>,E% +M8U9#;C?_K[=`I/S,J146QT;9`G6QKWH]J[EYMXRF"G,N5VPDP/8>>V/*.#F? +M7EIX-#W]=W(&B*L@:%C;=Y:K>K-][&['I>27XTLY5;,0][5#)W&S47HC[\?1 +MB`+#)6'R78UDJ_[ZT^8R71O\>F%(\(4.BZ-K=H9=HM&ZG3C^!8+G(M0@?))-OP^6W[._H]GJ:<*3) +M=&#H!T>UU_KR)473[ON!WNWI^R?9W=#V+H];W3ZMSF7P^*/_3?C&=BY+*B?% +M3TSG.Q]%^&-[D-JQ0HZ5P=N_D#W4E$'=NKER,[9$K4[.HLZL1A=T +M:G.8W,U*[\@+NI*PUQDSS:X$DFTSMB)=L4:';V]:50I8`.%:V.CQU):O3X[' +M*N7AJWJ['/M;('FOS$5AN5.CI^!.[MNNX#@!:\"YU7]HKXT]A4^@#/+)V1X; +M9]"N.L?C."+\TJWL)<"?=.!AZ*4_\.929SQ-ALKQ?XMV+O9MGFJ]VJ57$E.' +M&8:\.N0)(E%L/^0`L`756">;57\8\5,_R)G;UT/*:Z90=Y*K_'L49JFH,O#] +M_`RQ_GQ#4'=AG8IPNG7^.'H`.SD'CDR````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````Y?C_Q[O\?H[OZGR_P[GIYZ^E_ +M#YOX>G__+:2Q1_Q*=6?_1I\;_^NGE>L.A>"$BG>H5PH<%D4*^S`T'!>&1:+) +M"4O#P*AC8[^7\IS&7!O>S72H0ZD0SA*YNYG\/'#I(BP[V:2*1Q0[GKT:+:V. +M]*WYZ-^F:7M!0R>&RG3CF5FDO72W4\LTIFB;]$X]2:^LW/),H3'Q\R^;/%>W +MS?'QRC>"J+MHNHC0R%HR>:20#FF]Z96/AGJWGAY\87]Z$8?U^]P\DW9=,^YP +MZ;16UC9_>-[P38>$-MB'GYHV;L%PO)NQM+S=S4,.1G2BB7GXK9:B]K\HU>X$ +MH?BNB0B9IM4MK)'#*-LS5<4F&V&C8@_5/8R=GSW42Z(]'@OTWU)$YE<>WX>/ +MAX8_>7N[DV.75X(W?R29IG!D_VC6TMD)-TR0< +MG:]_14#F!"JMDGJ2ZJNY55Y_+E6[FK.A.IR-`,T['?@\SBO,N[56(X"GO:.> +M;AOFDST9.3!MH<66]EW789MP"BM<-^\'N.,&_$=2<#O)FJ^@?V/1G]5]2<#* +M7G-+\ZF\`\4`S:DJ^\X/ES[^]J0=KZZF,;NU;S?Z5:HO,\1U][8-9R]OW;F6 +MP8$M0]B271S@P^CLV[60$.@XU9"PQC._J$8,7"-:%IX]Q.S;+E%!&N7>AH:< +M$5RNK?WZ/LR.0(5.I4@7\_LUJRUHLO'"0!FU>+(0L9@97084^_GS^:+AG)X]H#&M1(#F]( +MWC[..'+0(+/HRS'D]QV)T4B.2>U^M1X.U2AA$Z&[S=XNI!2G#`?%=\,4L-7@ +M>XPW_+EQN7O&-AMZNGH$&I:8)W5L=TY(0]G&_R?1&'UD(_6@RX\E8`X[5W>W +M]/EF8O]]D>./=16BS<-5_F7'Y1D+9IE;`N)QT:8D&8[>K.E4-O8]1 +M?K::?EX\DJ"Q\6!1?1T>>ZRC).Z=CE,T'3HN2GAE(Q'!">%Y*:_RR+CSV +MZ@M1^]YVL_%[GSUA(R2D[)=`M)FT@Y)-F??ND_3Y[\G>'O^X%A.KR=Y +ME:9S&$GGY-/!Y_DQYM?+V]KYNW^^_4NK<'0(, +M6:"\,M^:T=\]:O^T_'R>7UE)YMYN#4>=4MJ/->[W+M;EK/RG3^W3.%?9[]#7 +M4O<^>P/<413]FF38[71HC3+RU]?M_//#-NVF^Y7^Y+8F;=KX^ZW<_GY*^+#P +M;6[\_<_E+U>];A:O$\I!VTSA>N3.?EQ!7V-7\=O^?;U_P;\B6VGL01`[NQ_U +MV/EV?6_[KUMZT[O9_GVNYTV1/KH!%W?X_-$Q6Z*VCY:Z`\F73*L5=?+\R5(5 +M^AD3:_4FPZ;!;9^"3#]R[T>>VT\2BI\L[AOC&B]JMVN_Q>W[)OSM7;_AV_\O +MY8!>:*,6^1^+],QGW%9XO+6V;MX[)*$5_/*RR#[\/?@Z]=!4^=::8E1311V% +MRF!#BWNNH`6H?QP7P:$Q(8=<#1R8"'K?=\M1$]ZR9G0@1-I$T1LX+]>?B]\9(V;OBT_`1`Z(?=DI7W,=_I_6!I+X?QP1X]B^)PI8_(/; +M:]Q#A\%=U]V3*MJ6PXH!IAF0;TC;,)_4^:80)[^-XR)WIO9*Z(;.RY;.ZCT3 +M34X)`;^7`)G!CJ;U5;_QWC172EQ5)6DA^I]KN8I@#C)'Y\TL_IF+YAP`2F?+J:F1&]L^.I?YQ<'.Q +MGW\_DY**7%."8^.[EOJJ4^I!8LAMT8'W*)(_KSZ:PS!2,3M/EOH!?3V-&(93Q1@]%>'('N10B'[ASSP(7E_+)&;-F[@P<5G16<]$X9 +M$C`X%NCG&WS1XZ85/CZ[%/J-^79*H.[NT;%V?BO"P['_B4;L9IM5*3!+D[3L +MW!!:^%X/H(?\AZ\ODR0"#[2YY/I(->I2G^:%![5NS8#7%`9,;<^B+JE`R>7> +MEK;V(<7GI)QFM"^J;$DOG?M?GFG3N'9NH20GEJ.`Z?/FW,TUHN?*TH$@S\?K +MK_SX/[V4-:[5Z.H(@FQ]7?^OP?=1Z&]CH9"[-C-?^_0.+?)_C,XS)I+\?GQG +M$]C_'Y.A::<4]CL9-C^=LJ[<\/T_V\'_;V2_?_GL]"T=#UL>!5=R.WA-/VW(@K["^S_S6'4X#Z7"9*V +M'%).\V[S+NWRDT.#_DLJP*//`HP'V(;,R&O[/<[?=^;M^[EVGXER]X8%UH6, +MD14XN36"A-7)J)A>CM=J%AFQ/_8S4LD9 +MEL4&Q;XT:A^F[X.N.=2/8GFZB%%5_TQY9$J9('W!JKKM84)DR%\"?UFIS#(F +MW,OKO+29,??;54.TUVIA(`J?ELM&2<77#.I3M'WMZV\'X??!IFS")Z>_<5]2 +M3S8V5V:WS3Y[4Z($%$`R*0+_3& +M^=6.G3=_F=OZ*5FX[.U=^$44(MDNN1*-:FD-5<-F0!4Z+CD(&ZS`PP:Q,7/? +MY;W<_V)&P/+!Z/I]HK"YTVJC1OP+704FTUIQJZH1='G]V;KS3?Y)T/"H;7WLW/# +MPQ+^MU<"T=21B_LYO9=O=Y)-L?;Y[=O)-&5HC$Q\.QRN-]Z*.6L1AY81FWLN +MCX2)ILQ]_#=?74B]R[[,U`28+FMTC(`+SV:&E:+,9M%^'8GO53 +M@OWCY>E$\5*(473SU#:(T7E6H1ZL)-IQN0*$K^<<92A6F3)E2%V8K0OY,\U3Z;I^F(S?)\L4:%EZ\A&3>KV8 +M_$0/3``,OWR\5*LWQ=6QV)NB:'_!E]$N&O/"=)NP0$A+:PA03]]:&GY"G<$B +M).]M=GK"Y!],0%M37/1F*OG`]$VTQ,7Z2*O(\AH]PYM>NKZ/1FI8:M]^4*\8 +MVS)U;*?AD66TTPC=X^*;Q2B+VYSY>$[T9MNA*=H/!C"GJVLY/+^[XNF"HGK6A];1>V+,07LUM+TQ1NS4 +M%CYYY0F3KL4US$8U#<,QVIL.S)X\L0LC)LU4*P?\%VE6!6PW:A])<'L,F'EE +MQ.C22)=Q:='60-8?,$:@OA#FI^^N*8A%,3+6F-S6FJ^UK7=/JB%4HG1:O;%* +MB=4_'1$NP=J,]QZ<+==VW\-)P]@F]P9>"8:?BQ`_YM-7$[S]R99TWMEO\DW1 +M/^M#4`R5]6K0NG"*TZ7W0`WYI`7YN'HL(^D5F]:'X@L+/,L`UY:0^Y4SI#9F +MEA$&Y8)G=$(FF2-C'3D_W.#/NSZ:,1C/Q1%H,(X,5-\RS:(7N!F^]10O[U+D +M;[H7EJ+4,7_78&$+:5%4]JE[24+M6U3;R>"V'[NJ +M,3/E[/T6RQ_[P6L^@2)X;4!J@&'#@:]]N04D@/2*Y<;]V$&%WH97VY]&G%[4 +MKRUG`$7/.I"7EEN++*T(`E7CI=*_)L\#6P;GBB)6J?+R6C>K1>`7)65#WX,<:ZF<_/)*_:IH\F[YKK%,52UCU]RP+ +M_Z;=*J_^/=@@76SS$@W=V$CJ!]<$?V1\SU+1FW/=07_Z?9#_$JD@],H0?H53 +M`[.>R4J,R;RVQFU#N=%[K\OR]B&(0Z8)=9Z9EP52)Y_CD`W=\6*5D9NPJM&8 +M\_#EI34W9_:XYT",S\-BP$-5Z47?Y=[K)(NCP\VZ#\T)#=[&OWWD@?%J)I4U +M7FL4&9IOXJ<,>R$HMG^FNL-:W83P1GH$=UT&:C?LF\U9-8WY^JKU?2`YZ]>I +MV?@WK]N7@K.H?5G4C!G&:`S$(#=/@$HU>BV?#SM%I_#DX-_TKS5>GOSP:/#E\GP\A\QK9!V??79J;`^]O",N_AF_/+\ +M*\XM'W>DT=3O3[8=G6MVKILA3MRSWVR<6COPE#]3Q'[N=+%;?@7O]-84'GK-B6*/6+1+#M7>'W89HDMS9=Z(GGXIY/TY]5;QX)2& +M[N9;X8YNG.)U(!5HN$7Y#B5K,2`-C=Q]9(FB%+\F+4TH)#O=SE#U<:=NZ9UB +M211ZU;J5F-07PXYJZ%EN)\*Y=KCXYW1BUC_K.A,5^XHN+_I+RJ@[V-Z +MSD7#CDVK*OXC+9YPU4I)[Y>?4>VW16.]9#VDT*3)IZ9";HZ`ZNQF(#YW.=7] +M?+M;M#7<",7M"^S:4STF9&.HM,6&=Z41G60DI,^O+Q5&[F!5BXWWN>S)6B*> +M'0LT]=3:=_J7Y=JL2X9/:[DAO11(N,MRXF4&73`DH?5\&GXY+5M=?Z<]*9*<-;5AV4)$U71",=Z/CUW&+(DT +M)I_11#=G8U4/2R-K>B_XH'AB.T;7)V.S]%.?H4UY6K\Z1:]HG&DLFWMGTT2V +ML4&S8^N:1GE>)N%C]='T4FF"*8<;DF._$?-5,NUD-V@2LX%4EFOCXL +MN%PT>'UIG%B:"+J]`R>S+CB(_I,-'9DT)L`5;U7#!I`T=I%^`W?%A\5H6,AF +M-_E;UI7IUS7<+/'1;MUA-Y,:+V?44--9]'H<_9Z>=4[YU +M1D*%\/LL.90.B]E1D.7?%TD_$*IT=%,:<$"3 +ME^[:\M&LO?CENGP9NG;JEX4=3%`1,<>4SY0U*^'U?"MH;1@=V0W[$+/"@^N.EI%0S)?Y(7&L.=]%GN1[D@AH4B^NAT;]3>?0 +MDUS[X6^H)@P)Y;I:NG!NYR08%BV4I2YNY^.INJQ7J&!%()+4O7&3:L.IDLNX +M=*W2TN/5,:.]>^:M +M6_/;AFI3S"(W/\=]?XIH<,X&9P:74N(9:,W,NF0)<]U=,P+>]Y.,M\N-T1/L5YX?%=RE]Y=W5@>3_U"BQ +M2F8>%HIR#;HT#)O54Y8H2S=$EB8)!EH<5PA\:ERS]M_2:.C+6DPVG3R="NQ6"+%U?@#Y)M!3WG`U+!T.# +M,64=C%\\;[P9_F0'Q1#SBZC]D0(GP]Z(^#-II[]^_\X&MBY+&,:N-V4E$<7C +MR;M;5R7>.:NE6]90B[FP>D5^./AF_#8DFF?43E*;$S3= +MYEJ]6B:5TXE[L;48,3?W,@TH;\NYR2N#629=:Z/1DP=NU\F.W>*T*+U7V*=0W3)00U/X\ +MDO3FXL:T&EUL+V0HN*:=5(`;=\W)27)Z0@;NZ: +M<>TZT5T5I:/;4L07U`3$*7]FK'O\EZ\I:$M\;\YF@.^Q.Z04W%$1T=2YX^K- +MH\V,6R/[Z`K>'/7QRA$*7S^#Y/OV.]_?P2@GZ7,?L9WX_.LE8.DMMW3@GZ7` +M/)A-_E&+]GX:49G\6>B9E-:-H:/OE-J[QRZW*B-.HJ0C2#2.+R9<(W-O?VNH +M!S+9:1S;@\\G(/+(O!FB*HM&SA])28DWV>3I\+6'YQ7=QZ-274K=QN2@'JTJ +M961D/HO@MBS&2HB^2;AN?-6$AM:74PCUO9I!=DXB@ETY_%]2A$>R+UU+E_Z^ +M/\_SY7EI]"%8\&QRSC-E;'CP\\8G:8K\LQU,1M&U:5,GDB66I`+RRKQZFV$+ +M:',3S\?%YX>T6:?!^FH^6[Q'+.L:?N%R(RQ=,>B(,ZFJUY/'BD0W]NB[E,4S)N1`:DQDI)K5_?#7L% +M\=HIN_6M$-TQT?:Y+F.<&\V(9?A,=G)3<"R-[$BA0%'/5NS.D)\HH(T3=/\; +M'WQ)9..X;-'2$=OGEE4^*G]ZG#%4J&L0A2P&[]OA]O,@&.U7:*I]_V]?C8BC +M'@K2<_9M2T#1>T-[K.OC%N97C"G<>>?S9;:+FN/XK1/R2WXQ;CTS9/"6>.*;L%,O_2&&7IYBS!2G? +M-IO/H;[O/4UW_LO29;1(W"J;CH%12*TH["-D2MX^J'P8*&;=93_L/;/RS;+> +ML'RW^A\FQ3Z"&3&NO5R]R&'S*$GI2EWHHD1P;9NI[U4.C9A]:R];N2NOBR0> +M^A6CMVY?@JGX6"Z<;`S5BI[T3D$#$BB6`.S\5Z+I'-L/=SSQ*V>S?0E3'MK! +M&:=#69($.B9(_OQR['6R$K7'5W5V$A8^Q^?T3@R[\H_9L"[HYS=_?L&128FX +M))Z8"WGKVR-?,S+A23JU]40-+&J_8Q +MY5HV:X1**[<3$VA$&DQ:(1PMS?S[OFNKE6S9*FJYVH(]S9[7[SVVR`FFJ#2U +MQ3X(R5,,>=.%XH5_;<"@56B:R;@DY3H`YO9^>OAO3WY=55P?9PK6-YLWL4IL +M_A#WT'![>GQ0SD;"7^+^N+E/^O)B$IW97EGX)HMF_DY+>0S&;\Z/X +M*[4HX-0`6&ZIZE3]YXSVHG.&W:\]&U[FTV'$NGEC$7?F2]H3)D)IR7Q1-YY( +MATC&DUB;1>N,WG:ZG[:[`2\_&1F?)Y,'/Y*YY;PLM/:Q[D3(`2X^EH7?Y*90L^+\6 +M-W0%CC5P9:B@9'R14RFLDAS*>3"KK1WZ_9K!>8HHT9^*AW6Q;S13I3>9(RNV +MF(5JCUXDX[N8_8B[IT1(LU*J]_SWPM_[?N2>]\7;J>[2.V^9N]&!>.Z/?R4F +M(*5RD7>_'-0VK+4V +MN=\DLK?Q^:N!T8LT13%V9R1]/`+Z5.>L[IQ3MW/D^;8GW*#@`;__[3HX```` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````/_E+Q/[,7]KU/_G_________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_____H!'_(O_ZQ_Z?___________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________________________________________^@1_R+_^L?^G__ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________H$?\B__K'_I_____________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_________Z!,`=$5#(T7Q9V;W,^%<[-7=@+1MD#N]V=(H:G#Q/=(`AA--ZA) +MI@\`SL8VT\;D&?>M2!R0!DOP\\./&QXPV1=7?1(/.9RZNKNZNKKQWGQ*OX1? +MJ_5X.4KI7=_DN>RP```````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````>KO]/._Y^KG]#_CZ?Y]#U+SL7\^=T.?Z_?N>I\?3E+L=#BP'T/ +M4CH=&$)N?DV+8S=:!D/EV(TU=I%YE#AD&+[K:W*S.+IFA-XK6 +MPCAG>]/1MA@BZ+>IN;?FV/5K\`7._LZLFFI_:#WA^CZ=_GG\[Z.=%B105Z.Q +MW>KUO4/-[F;/1S\_\G\NQL>6#((A@;/W,_?N@?:]/LV?OB5_U%8"A>-<1:9\ +M!E!D<[6&"@ +MGT]WR^_."=7H:/@_0WA`U5AA[7VZGCJ[>E5X+C26KE^^-NFT<<7,CJC//*W- +M']DS2Z=F9DJ9!0/G6>*0C4\UX8L_]QUUB@T5ZXQ1$-.,&:[?FC]D)`YYNG74 +M?;3U_=?-[G;TM'P:I`2I;4COU_54TGF_4=X6$526/(,I+ +M9@CRP2#]'J=7]ZU+Z\W6KIQA?7?2I\I"!+Q71:_9!2I4HR.X2B4-\W2K\DR7 +M]>JGT7Q>KRZ_9!HH(>?]V&+1UT]+;@0'L;[5_S3%"?UWAM_;!D^W]/K_X^;I +M7OE?R]S_VLGF!NCMZ6?X(VK?0N?#]U)QT_NBWX(*EF+3B8NCP)=.._C?N@N\ +MZL^#"9AKST*.D,-EEKC&[UWHO%>N/W@X=9M2M]J?'QI?=VK^UNWT)\:GK;]Y +MX:?MB?`EF)'ADC\97[/PY`BGY%>MG/+/42R_\;S\()->K5G^\1!9..A.\O+D +M)NB.S($502T+`7)*,XVA30M^,A459Q'!N;6ZY-6C.JLQ%/Y52F+3EE1>&4,&R8 +MXU':!$F;F5"OCP[G9]A#=)6ES/C@I$^=\E&"_%CF2%_ +MA[10FG@"9^E,FKBG@OD$[6.JEU.YI]$W@W(N.VC[-#'%XX%/;/1[?R_J]$^' +M*EK5"=SZ]M-^"&:S1.;ZGV]C8C&N]&YQ8O$9DVMW&$,ZZ1FT%>RLK\VW58,- +MCWZB"XF"IO-.*_;$RS".=Y5A(MHK9-5OF.6&E)2(BI"WSE*K5QC`O^9R67Y] +MC5FY)L.*-/U(/D;#*)DM75HT%ZJ9OTK,WF9&5D+Y8->!;QECO^K]7-D<0)FY +ML7G9.Z_8X+6$7@_'(NQ_&6#M<)Q^2WW#@&C<6;,AFP1=+M5Z\HE`UWG$!\8O:-BO[>J^>7N\=Y[)+2G+Y$M);V8@NWGHX\M +M.\JQ@CRQ%\!:!3]M-T&+'K+M_USM_2%\P@["=$LHV.X +MS#N+.<8RY%'0.GBJWIL.72$>]DKN4Z#6O:6Q,IP_]9E?$T]'C +M_\@[A>;$?XI?LLR:40TVJ7)D#2,3>L +MU;`_$"4N&4P441T95`:X"'9$8,[W+\L&G7P/%C-/3,I72N(5A)F]_$-[H=&9 +M[^'T^:"8C^5]\6V4M>1GE+U9!YQ/U1YF1`/O9CF+?=FDVS+2`UZ/5[B0)D3@ +M\E3^1^#.V_11VJRFU3*S[.A_"$`QS`]C"/@M#5>;#Y?-K;N\;)=_Q\$0(X_.ATRM^&OG;?N?! +M;-H8H[U/HHPV\Z(&K1QH1O;`[;9!4U;]/A[G!2K,F2MW+2(XP^G(R'FP)@V: +M=)(\C6)NO@V\:>X_>!0>)%^0YO8ZHQ_OD#&P[\C.]6I6'[J]%(!2T`RI9NA" +MBFML:FKBAY(5(IH:[@V=C%AB:^D1Y?'3*&>OWZ$L3W5]?OZ-LD)4RGK0!YG6.3 +M:L:4"-Y;D_GQ72.Y6W9]SX'DJ07OYL'`/M1W)6<2,?0QP#R^)XBJ4RE\]WAY +MGXY84YF7:YZ5-@DT66G#Q9@60$BKPY+`](QGK2[_JJV\AQ/R`XHVD\14Z*>LF4*L@JS2KFW==$GMWFR`E-%>'U0G*T/+I#_TLL/<76W9Y:T`D(2>Q3P''$O,^-)8H0K\ +M$E>\9BIC/&44Y$D<2;4D:YE[7"(8DYKUJ\/M>"3_BK3D.C5HW%OS+M!?<&%S1T*M(GC>D?+53TXZ)3:5 +M625@^CX9]BG1L\:2+^&N]9T<\Y?:_6C!T9(['Z\[MBTC#HMC+@EX:.5KP^F. +MH=*=9QR6IV8+DZ-P?PP^2QM0PUSDEX\_Z?Z1$CG7)\?^B"`Y"\,5D[^^SPV4 +MZN_5S*O!^9&W:4B"8L`6;4GI@157EE_6/M98M"?9#/+GW2`;VK,@'EVKD +M9(.X.KLO->-V?)=:LKQEV?3[5S_!Z;^-)351%BSQ`D)>.W8(D.+!*BV7BP5T +MM2OFK[>F"=:`6KJKM(]#K:FOG?C#2O[X>W5YJ1N!`-QG,>QX@Q6KI5"2JW:% +M6>3#-!-G*G&&BNEOE>:S@*F0+NR57M;R9;D'X-3:R>\J&`/1Y]:6E]P_W$E> +MMB9;FO*A"W"DV]+[=N+'KCLUN[.WL4:C$`3?V]G!KZ6EV +M:LMOZUA'=#U<,G!-<2@<>";Z039OGTY4=\3R1PS7-=J^W +M]:OTHKW?1Y7!VF17\?/7Z$E4#!Z)%*6*^<&D?D8PO?%I?/=P3PWI47++Z +M8#;%[=KD8Y.O:0K:=/8[%R58^">39H]V):N;XYX7R&8W=[_:C63/2NOC7+%S +M:\I;2VN694Y+0'@5X^I7P&OL7>#B?E7"&?@C-PLV15)1(A)GD)$8@P.MK)YX +MV)^O&3?48:ROF\I>*X;HE\Y&RIF\;S.PX52MN-2:`%FZV9IT]C6TZ_:[_O?K +M)(VL[_[QF^>4]CI0^0F<9A*Z9IJ^0F9M2O4.)^R+^^YN +MO^CQU(%V4W]RLQE88IE2.BPQAKV,CR\8MSJNU7777A5*'O2[F\\/>IT9MX>S +MOP;3=?0F-V@]("UZ9Y'HZ6;1AGCFU;WD`Y=3 +MM8O6]G8T,NQ(K*=^\2<:CT#]@Z-5^'0(PIO#,>>:U=#BY[?93%1)?X@`KQRV +MC3SHS%X_@..+X0@#_IO&U^)=C=L76S/'W/!<=A-'6-V#P;3R$8-EK +M4+XPT)O-6^)I:<0RWY'!@LA7MZHVM8Y4JP<1`LF-U"BUL,%28TW4^[J38:4/ +M)#7>SM>['3)\BLU4PS`LC4V=FCA@^;I<1]E:7_J>2+>*DQH\/EW[-S9EQ.TX +MS="/O>]BNW50:/>O+OQ.-JE0`3%YL.SEI[Z.)88V[DGE?CO\&CI;HR0;T#?0 +M$7?*IQGUN^3UGEY)0MWV)/1&CN$X7Z8Y$\R2T-1X'QGU"MX*;F*[L$LK"3#H +M?2V>@(VZRO5_BL9@$?C=GO*4[!5X\R5;I\6YJR,!Q&/@Q29R"(&N]=@'F\2G +M$`J\*GCQ^*+(/UK2W/%665P'F=(FR7*_.?DKCM)DEZ=>3LOZY.4"99O\.:#R,,^3UFS>O0,6B'Q.*:/=2VG`/P%5ST1#D1TKU]NJ4<[Y +MY<-6]7?7ADE11HDG6U=:'1_^US+C>IC^`2INA63>GEDM8_P[N/1;ET/Y_?&EYTIF-B;)U:K8GTO05S`3*R`L,0%2 +M$9*[SBV?!*ZO]N9R/A+ZMG>$V;_'R[?U7HS-EWC#[[MO +M:ULV2U+.DLLTV""@#FZ,$'.G=,/;L0_9^'0IV%K/Y0/%:^#FQRKI;\V#@V][ +M_\=;V'N30F;T6TYD]@415A#,EU]GQ%:8#N9=X+U)(:'Z*40!H7UAGFMBRWA3 +MQ\I[G>RIKV`79]6+&I_/` +M]O?%U80G:GB,BX@'\MT1.ND3\+D9RKS%4LC94+WR+O#I5%G-L=8]R*!I#5.V7#`,HCNP2_"#-G$GE4 +MB69\7+GGUVOYNE_6D(71'WCB97ETLMT2"Y6BK*)9>L3>+.]%KG4)T^(G\+`A +M$[K'-B27U"2YM;=F1'6BV4KACWJ=LQ8I`^%[V*\=O72&+DD-5:']^KIZ/:]P +MM#L]G3[D-'-'P=&*^#]>?N8MK/CUVOZSFU?9J8L%B!C9S?Y<:8[6A]GMO3T. +MGV>C]G;[?9^OM]JK?:ZV1LB/&5F^Y]4?5M1_L-BH57H7:I9U08=&I2B]L@E25;IGV +M(.8:6^>$+ES#DK\KE=G'6IM?8LV;4$.OB5MK?5`!1L]O:0T$GNQTV3].>,)] +M:3S@E6U9KDKAPNN5+9.2::]/N:/;N:;5S,+0T)\0%=/2[&AW>KU*!SK=:J,@ +M(2N"PW%9W!KB\T>WT[3%?)+Y[V_GPF#H2O%R8)_`P9'B__T&"X-I_\KV0>A( +M"_D/:L>!3(?BJ2Y"RVW7$:-=2G^'Z",NLI#;QDHK&K(;<;_]?;H%)^9E2*BV +M.C;($ZV->]'M7_KNY`T15D#0L;; +MO+5;U9OO8W8]+R2_&EG*K9B'O:H9.XV:B]$??CZ,0!89*P^2[&LE7_?6GS&2 +MZ-_CTPI'A"AT71M;M#+M#DL;AXT94K'FZ..IMS?4VM*[>-&8[B#UHSF.2)!7 +MWRJLA$AJR#L;>/NJS\*9\JXP4:2'U)]W2EC2#[BP9%1GY)R*=CJ]/^^G"CHO +M5AO,[W4Z1*BZ?=]P. +M]V]/V3[.[H>Q='K>Z?5NF;D>W\K)STYV/HOPQO< +MAM6*%'2N#MW\@>ZDH@[MU +M;7`DDVF=L1+MBC0[>WK2J%+`!PK6QT>.I+5Z?'8Y5R\-6]78Y]K9`\U^8BL- +MRIT=/P)W=MUW`<`+7@7.J_M%?&GL*GT`9Y9.R/#;/H5QUC\9P1?FE6]A+@3[ +MIP,/12G_AS*3.>)L-E>+_%NQ=[-L\U7NU2JXDIPXS#7AUR!)$HMA_R`%@"ZJ +MP3S:J_C'BIG^1,[>NAY373*#O)5?X]BC-4U!EX?OX&6/\^(:@[L,[%.%TZ_Q +MP]`!V<@\;EL@[&7&ED&AW(BSGW*'RLG2C+__M/40````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````#_V2\C^C%_:]3_Y____________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________________________________________________Z`1_R+ +M_^L?^G______________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________H$?\B__K'_I_____________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_________________Z!)#_4%IS_=3_\````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````$````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`!Q,(=41#,T1`!85O9S\*.C/!I9I1:2;N[&-B[`5MIBT,?1836;F[OB11)I) +M5B)-+34%IEX-^[V`4GT(E*.1T3,T512)P;F^.L,(DS43'5SOBOB7/\(/W/[] +MSD1P3SPF!'I,@``````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````.7XW\>[_'Z.[^I\O\.YZ>>OI?P^;^'I__RVDL4?\2G5G +M_T:?&__KIY7K#H7@A(IWJ%<*'!9%"OLP-!P7AD6BR0E+P\"H8V._E_*C?IFE[04,GALIT +MXYE9I+UTMU/+-*9HF_1./4FOK-SR3*$Q\?,OFSQ7M\WQ\F5CX9ZMYX>?&%_>A&']?O\$V'A#;8 +MAY^:-F[!<+R;L;2\W&/WE[NW#\"VZ13S4Z +M)=:V3Q#TU/+GI-CEU>"-W\DF:9P9/]HUM+9"3=,D')VO?T5`Y@0JK9)ZDNJK +MN55>?RY5NYJSH3JV#6/<3LVRY101KEWH:&G!%)MZ=CQ\GZ46;81TIWET&%/OY\_FBX9R>/:`QK42`YO2-X^SCART""SZ,LQY/<= +MB=%(CDGM?K4>#M4H81.AN\W>+J04IPP'Q7?#%+#5X'N,-_RY<;E[QC8;>KIZ +M!!J6F"=U;'=.2$/9QO\GT1A]9"/UH,N/)6`..U=WM_3Y9F+_?9'CCW45HLW# +M5?YEQW,@;`6'N49"V:96P+B<=&F)!F.WJSI5#;V/47ZVFGY>/)*@L?%@47T= +M'GNLHR3NG8Y3-!TZ'+]3GRB>+)PE;U"26?49/=@L;K[PEX?V2FO\LBX\]NH+4?O>=K/Q>Y\]82,D +MI.R70+29M(.239GW[I/W*1+WD^>_)WA[_N!83J\G>96F?Y,7.F +MUW>WV_\NUV^[VNY_+Q=WN;7R]O:^;M_OOU+JW!T"#%F@O#+?FM'?/6K_M/Q\ +MGE]92>;>;@U'G5+:CS7N]R[6Y:S\IT_MTSA7V>_0UU+W/GL#W%$4_9IDV.UT +M:(TR\M?7[?SSPS;MION5_N2V)FW:^/NMW/Y^2OBP\&UN_/W/Y2]7O6X6KQ/* +M0=M,X7KDSGY<05]C5_';_GV]?\&_(EMI[$$0.[L?]=CY=GUO^Z];>M.[V?Y] +MKN=-D3ZZ`1=W^/S1,5NBMH^6N@/)ETRK%77R_,E2%?H9$VOU)L.FP6V?@DP_ +M+RUMF[>.R2A%?SRLL@^_#WX.O705/G6FF)44T4=ALF9T($3:1-$7*>D-%"$=?3N^+5%(_=^.27QEDR"] +MZTV@X8_&&>/G>F3@B!^/)-IU:J"_U:B;$#85>RVGU'%[P=WK."_7GXO?&2-F +M[XM/P$0.B'W9*5]S'?Z?U@:2^'\<$>/8OB<*6/R#VVO<0X?!7=?=DRK:EL.* +M`:89D&](VS"?U/FF$">_C>,B=Z;V2NB&SLN6SNH]$TU."0&_EP"9P8ZF]56_ +M\=XT5W*Z(8%\ZC[&:UCV8_:+VW,O/7*'4,FO@'.<6`99O;Z<2@48FVBZ,8DT*HLE,P +M8$A:?WB![D4(A^X<\\"%Y?RR1FS9NX,'%9T5G/1.&1(P.!;HYQM\T>.F%3X^ +MNQ3ZC?EV2J#N[M&Q=GXKPL.Q_XE&[&:;52DP2Y.T[-P06OA>#Z"'_(>O+Y,D +M`@^TN>3Z2#7J4I_FA0>U;LV`UQ0&3&W/HBZI0,GEWI:V]B'%YZ2<9K0OJFQ) +M+YW[7YYIT[AV;J$D)Y:C@.GSYMS--:+GRM*!(,_'ZZ_\^#^]E#6NU>CJ"()L +M?5W_K\'W4>AO8Z&0NS8S7_OT#BWR?XS.,R:2_'Y\9Q/8_Q^3H6FG%/8[&38_ +MG;*NW'*.W)A5=CL]G8_Z>MON_T^S[.S]&N]?OP@820/NQWO#]/]O!_V]DOW_ +MY[/0M'0];'@57&!=:%C)$5.+DUG+5/QT^8^CS? +M[>-NB$/V,E4<7)EZ7(.*]?PTP@@=BA%.&SYVO!]WU_)]O>^[P?7(++:^WZZ? +M#AAT\W[=EG;L3P351#M:+[3$?^\O^HME\&24S_T1G+U1+-Q79*PV'(J5IS:) +M$+]VKO&E0R'-2I['@H35R:B87H[7:A89L3_V,U+)&9;%!L6^-&H?IN^#KCG4 +MCV)YNHA15?],>61*F2!]P:JZ[6%"9,A?`G]9JMO!^'WP:9LPB>GOW%?4D\V-E=FM\T^>W#]&KO) +MIO^I9^&R;K[;\*L#7CZ?:*P +MN=-JHT;\"UT%)M-:<:NJ$71Y_=FZ\W).4!90;+G\EEX#1J;PR2-L#O-6&E(X +MK[#KM-8=]C<.;=9O$SI)Y23;'V^>W;R31E:(Q,?#LBCEK$8>6$9M[+H^$B:;'+>[EJJ)]A)U. +M2]L65(9R>I<#C8;!8>M=*W\_/L?B$S;X3>UO(F,]'V<1)_:NAODT_>$:7\>6 +M)[XZ<]'%=EU8T[QXE>QN9@=S24?7&Y[2*>E2E,K"3:<;D"A*_G'&4H5IDR7-$12A*,D+W*3C1W/%Y=4FQ%&*83)\NB +MRQQ'I4A=F*T+^3/-4^FZ?IB,WR?+%&A9>O(7.6/;&:KK2H%3UU>9E.D_@_S[ +M_]/IYW)E;XEL:43.SFZKSR6X=$TH+SSA8+GADWJ]F/Q$#TP`#+]\O%2K-\75 +ML=B;HFA_P9?1+AKSPG2;L$!(2VL(4$_?6AI^0IW!(B3O;79ZPN0?3$!;4UST +M9BKYP/1-M,3%^DBKR/(:/<.;7KJ^CT9J6&K??E"O&-LR=6RGX9%EM-,(W>/B +MF\4HB]G+UFY/IEP-HPS!8@UUFXK35!Z(_SASX(*5WQ7S576EW5-_8]'6[E2& +MKE=VN;X%:[NYM%C1<+NVLN.:!U-C+2"TX;(84R9WQ55<]'N<^7A.]&;;H2G: +M#P8PIZMK.3R_N^+I@J)ZUH?6T7MBS$%[-;2],4;LU!8^>>4)DZ[%-/+$+(R;-5"L'_!=I5@5L-VH?27![#)AY9<3HTDB7<6G1UD#6'S!& +MH+X0YJ?OKBF(13$RUICG"W7 +M=M_#26D/N5,Z0V9I81!N6"9W1")IDC8QTY +M/]S@S[L^FC$8S\41:#".#%3?,LVB%[@9OO44+^]2Y&W-*^@BU1%`MY[N7=Z) +M]^&?@M&6F)V"QN;DQ":81BC^''8X[6`O>/1JNX"UK[5]VU37^_PD[J^:5V-%:YYL^W;(W9N +M_WNZ%Y:BU#%_UV!A"VE15/:I>TE"[5M4V\G@MA^[JC$SY>S]%LL?^\%K/H$B +M>&U`:H!APX&O?;D%)(#TBN7&_=A!A=Z&5]N?1IQ>U*\M9P!%SSJ0EY9;BRRM +M"`)5XZ72OR;/`UL&YXHB5JGR\EHWJT7@%R5G)QE[`!E^/RF>#SY9?YPZ8;%\ +MO2ZZ0GE0]^#'&NIG/SR2OVJ:/)N^:ZQ3%4M8]?Z_+\O8AB$.F"76>F9<%4B>?XY`-W?%BE9&;L*K1F//PY:4U-V?VN.=`C,_# +M8L!#5>E%W^7>ZR2+H\/-N@_-"0W>QK]]Y('Q:B:5-5YK%!F:;^*G#'LA*+9_ +MIKK#6MV$\$9Z!'==!FHW[)O-636-^?JJ]7T@.>O7J=GX-Z_;EX*SJ'U9U(P9 +MQF@,Q"`W3X!*-7HMGP\[1:?PY.#?]*\W+[Q:_[28_V%L^#?/U9N*L\^]:U'7 +ME7I[\\&CPY?)\/(?,:V0=GWUV:FP/O;PC+OX9OSR_"O.+1]WI-'4[T^V'9UK +M=JZ;(4[[Z/6")-H&;V_KY +M2A$N_R;'*[R)OVP;(F!9:KV%I2CB;Q[V$?(Z[JOA>B&U=?##-(7,P9'F%!YZ +MS8EBCUBT2P[5WA]V&:)+B)Y^*>3].?56\>"4AN[F6^&.;ISB=2`5:+A% +M^0XE:S$@#8WG,%I^7PA.V>D/?> +MWM6ZE9C4%\..:NA9;B?"N7:X^.=T8M8_ZSH3%?N'.F:UC?DH$6_&DMBZO,\] +M9>]2@.E)&;7=@D=U)T"42`L>@*>'J+B_Z2\JH.]C>LY%PXY-JRK^(RV><-5* +M2>^7GU'MMT5CO60]I-"DR:>F0FZ.@.KL9B`^=SG5_7R[6[0UW`C%[0OLVE,] +M)F1CJ+3%AG>E$9UD)*3/KR\51NY@58N-][GLR5HBGAT+-/74VG?ZE^7:K$N& +M3VNY(;T42+C+A7N)E!ETP)*'U +M?!I^.2U;77^G/2F2G#6U8=E"1-5T0C'>CX]=QBR)-":?T40W9V-5#TLC:WHO +M^*!X8CM&UR=CL_13GZ%->5J_.D6O:)QI+)M[9]-$MK%!G,O_R7LV/KFD9Y7B +M;A8_71]%)I@BF'&Y)COQ'S53+M9#=H$K.!5)9KX^++A<-'A]:9Q8F@BZO0,G +MLRXXB/Z3#1V9-";`%6]5PP:0-':1?@-WQ8?%:%C(9C?Y6]:5Z=3&BW)0!;375:#7?5-7MGU%#36?1Z'/V>GG5.^=49"A?#[+#F4#HO949#E +MWQ='-_6]9?=\?/G[7)SKUK%'4Q0$3''E,^4-2OA]7PK:&T8'=D-W*VB6X4).M<^P3(LOE36 +MUM-'>9J(-49K[WT_97TJL`31ETP18CSP+Y>:/NG1^.37NW,F[YK,[*;EWA"S +MPH/KCI:14,R7^2%QK#G?19[D>Y((:%(OKH=&_4WGT)-<^^%OJ"8,">6Z6KIP +M;N`T/*Q\=W+ +MJ.0?2ZGGO>3C+?+C=$3[%>>'Q77=U8'D_]0HL4IF'A:*<@VZ-`R;U5.6 +M*$LW1)8F"09:'%<(?&G`6L#]]>1";IC?4-V827=ABFSA3D2>9[TWW%3#WIB/@S::>_?O_.!K8N2QC&KC=E)1'%X\F[6U0,(EMS<-;TGOCCX9OPV))IGU$Y2FQ,TW>9:O5HFE=.)>[&W.N\" +M4W__&2.%O9(=V?Z9_2<+!ZMT4,L>_U/WU-4Z<]^DK:KD5WE&#$W]S(-*&_+N +MD(&[NFG'M.M%=%:6CVU+$%]0$ +MQ"E_9JQ[_)>O*6A+?&_.9H#OL3ND%-Q1$='4N>/JS:/-C%LC^^@*WASU\

    C4EU*W<;DH!ZM*F5D9#Z+X+8LQDJ(ODFX +M;GS5A(;6EU,(];V:079.(H)=.?Q?4H1'LB]=2Y?^OC_/\^5Y:?0A6/!LIMA"VAS$\_'Q>>'M%FGP?IJ +M/EN\7,?&9E@!2"G4MDYDN9FH[(?NC?@R=(/K>R<&3R1'+WARSK&G[A3QXI$-_;HNY3%,R;D0&I,9*2:U?WPU[!?':*;OUK1#=,='VN2YC +MG!O-B&7X3'9R4W`LC>Q(H4!1SU;LSI"?**"-$W3_&Q]\263CN&S1TA';YY95 +M/BI_>IPQ5*AK$(4L!N_;X?;S(!CM5VBJ??]O7XV(HQX*TG/V;4M`T7M#>ZSK +MXQ;F5XPIW'GG\V6VBYKC^*T3\DM^,6X],V3PG'R=/9.AKN@`=51G"LJ]IHZH;I]I='PU1EOXY'XJU2:;1TR9/*]V/=6")LTZ[AJCE +M4ZBGEG.3/1EYXE5SSYX'GCBF[!3+_TAAEZ>8LP4IWS:;SZ&^[SU-=_[+TF6T +M2-PJFXZ!44BM*.PC9$K>/JA\&"AFW64_[#VS\LVRWK!\M_H?)L4^@ADQKKU< +MO]5#HV8?6LO6[DKKXLD'OH5H[=N7X*I^%@NG&P, +MU8J>]$Y!`Q(HE@#L_%>BZ1S;#W<\\2MGLWT)4Q[:P1FG0UF2!#HF2/[\F`MYZ]LC7S,RX4DZ +MM?5$#2QJG)[0N.?8@\P$9-)^0.OMHW,VF()]_"@]_N<*U(DS02,0@FJ4'Z.X +M6-PG8Y3]WX`WR1P9=1]AT[_LS[T=5-U8D=/ZM[-1V-^;6YB-QIHS\8;">P]` +/%``FB51Y`0`````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_multivolume.part0003.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_multivolume.part0003.rar.uu new file mode 100644 index 0000000..91b7f28 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_multivolume.part0003.rar.uu @@ -0,0 +1,1337 @@ +begin 644 - +M4F%R(1H'`!EZ*%?VW`H%5HFLFX).4Z`.;V?GKX;T]^755<'V<*UC>;-[%*;/X0]]!P>WI\ +M4,Y&PE_B_KBY3_KR8A*=V5Y9^":+9OY.2W-%I:#J"YC[#9]&6)@HH1ZHV*<8 +MTFQK2]$+2^(@3/9+1"6W2O)L +M"JZC)MCDJG+%_;+=UEV.2(I,V[T@EI4_>>,]J)SAMVO/1M>YM-AQ+IY8Q%WYDO:$R9":>2(=(QI-8FT7K +MC-YVNI^VNP$O'+G7+LUC#W-PU`SJ5TG3!'3-Y$71F&\RIAPA-3+KMQ`A.LV> +MT\I=DWOQD9GR>3!S^2N>6\'-??Y*P]1Z)]:MSNVK3KLQO<_'-NOXQU:K;F)9 +MUV*]@/U`:IFZLT$S[=SKY$R`$N/I:%W^2F4+/B_%C=T!8XU<&6H +MH&1\D5,IK)()..[ +MF/V(NZ=$2+-2JO?\]\+?^W[DGO?%VZGNTCMOF;O1@7CNCW\E)B"E\79I]#\?;E*)GX0XO'&S/8K]`A_E[O +M:W-?VBQ++>W23#MSBS^;+K!B)WYOZGT*KTU5WI%WOQS4-JRU-KG?)+*W\?FK +M@=&+-$4Q=FH2:8/`,[&-M/&Y!GWK4@,-D75WT2#SF#E*Z5W?Y+GLL``````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````' +MJ[_3SO^?JY_0_X^G^?0]2\[%_/G=#G^OW[GJ?'TY2['0XL!]#U(Z'1A";GY- +MBV,W6@9#W(9][P]/H]'[A3K3X&Y3I1IDIHT2.XL$R&Y[I4@=.F[#?/^ZK1ZD +M#&6'[\,TB^]<>9\"Y-'I=B--7:1>90X9!B^ZVMRLSBZ9H3>*UL(X9WO3T;88 +M(NBWJ;FWYMCU:_`%SO[.K)IJ?V@]X?H^G?YY_.^CG18D4%>CL=WJ];U#S>YF +MST<_/_)_+L;'E@R"(8&S]S/W[H'VO3[-G[XE?]16`H7C7$6F?`7.ERJ_\NC3 +M.&L[XU<8.@9'&L'1%!-IUL?&T8$DS.,.S_X.*MFY1YV-X9_`(S_AWXIX>G6] +MDL&G_OS_IAR`Z?BI3QZ.HD:>+P"$%C35TX0*EI^YVGV?T]ST4:L"3()CQ_;TU>HQ6M?7%4=POV:74YL0'I09'.UA@H)]/=\OOS@G5 +MZ&CX/T-X0-588>U]NIXZNWI5>"XTEJY?OC;IM''%S(ZHSSRMS1_9,TNG9F9* +MF04#YUGBD(U/->&+/_<==8H-%>N,41#3C!FNWYH_9"0.>;IUU'VT]?W7S>YV +M]+1\&G+.*[KK$#3UQL@WJ0$J6U([]?U5-)YOU'>%A%4ECR#*2V8(\L$@_1ZG +M5_>M2^O-UJZ<87UWTJ?*0@2\5T6OV04J5*,CN$HE#?-TJ_),E_7JI]%\7J\N +MOV0:*"'G_=ABT==/2VX$![&^U?\TQ0G]=X;?VP9/M_3Z_^/FZ5[Y7\O<_]K) +MY@;H[>EG^"-JWT+GP_=2<=/[HM^""I9BTXF+H\"73COXW[H+O.K/@PF8:\]" +MCI##99:XQN]=Z+Q7KC]X.'6;4K?:GQ\:7W=J_M;M]"?&IZV_>>&G[8GP)9B1 +MX9(_&5^S\.0(I^17K9SRSU$LO_&\_""37JU9_O$063CH3O+RY";HCLR!%4$M +M"P%R2C.-H4T+?C(5%67(4L1#KH$O:A2=CZ)I=,W#/<=T<&R;OD^+GR7]R>;S\[ +M^F=SHQ[7Y?2JY?("\?;D5='4C,DW>]M08M$KGBTY947AE#!LF.-1V@1)FYE7 +M*S+,.\DPMX]7(X1G@KX\.YV?80W25IT4)IX`F?I +M3)JXIX+Y!.UCJI=3N:?1-X-R+CMH^S0QQ>.!3VST>W\OZO1/ARI:U0G<^O;3 +M?@AFLT3F^I]O8V(QKO1N<6+Q&9-K=QA#.ND9M!7LK*_-MU6##8]^H@N)@J;S +M3BOVQ,LPCG>582+:*V35;YCEAI24B(J0M\Y2JU<8P+_FJF;]*S-YF1E9"^6#7@6\98[_J_5S9'$"9N;%YV3NOV."U +MA%X/QR+L?QE@[7"O*)0-=YQ`?&+VC8K^WJOGE[O'>>R2TIR^1+26]F(+MYZ./+3O*L8(\L1?` +M6G+W.'X^$2W9;!*^:F_'@4W(5F1JU?!NVGK-6P/Q`E+AE, +M%%$=&50&N`AV1&#.]R_+!IU\#Q8S3TS*5TKB%829O?Q#>Z'1F>_A]/F@F(_E +M??%ME+7D9Y2]60><3]4>9D0#[V8YBWW9I-LRT@->CU>XD"9$X/)4_D?@SMOT +M4=JLIM4RL^SH7+YF^D*/KRO?/*04O+L4&ZDC*5OA&Y,:7!/@]ZOHM"FQW8VJ +M5;AM*JL7;-6!N[6]J0@0>(#ME,2.IWSQZ(5C"T&2/9\1OUR3*%B2C7]$U3>G +MU7#`_%*#CTL%T>+DJ]8LZ`%_S9T0AR,F*8A^38LN[FV;>H'$8@ +M.LX?T>!M2_'\S.MVAR_G/VL%"@,^G4"N=%Y0?-TLOL=FY3@:\3EV[\9U@?GO +MPA`,

    YP4JS)DK=RTB.,/IR,AYL"8-FG22/(UB;KX- +MO&GN/W@4'B1?D.;V.J,?[Y`QL._(SO5J5A^ZO12`4M`,J6;H0HIK;&IJXH>2 +M%2*:&G,SJ5^>K9HV8Y<<-T]9F<;HSQ'1>LBVE;`)X`M'./CRH=Y@#/K"F_3I +M6A'NX-G8Q88FOI$>7QTRAGK]^A+$]U?7[^C;)"5,IZT`>9UCDVK&E`C>6Y/Y +M\5TCN5MV?<^!Y*D%[^;!P#[4=R5G$C'T,<`\OB>(JE,I?/=X>9^.6%.9EVN> +ME38)-%EIP\68%D!(J\.2P/2,9ZTN_ZJMO(<3\@'.$AJ8LQN+'*1OZ>MABA;T +M2=+%VV^E#8=?&(*C">6"'4>./TYUUZ^16ZB9?F032LZ@`G#.NUP)E_R"<$+G.1MQN&41O^>#0SVYI;T@#9T";E^4T8INM0VK05*WSG7N*-I/ +M$5.BGK)E"K(*LTJYMW7*0%E#-DIT)\6M`)"$GL4\!QQ+S/C26*$*_!)7O&8J8SQE +M%.1)'$FU)&N9>UPB&'*@ZVQ.5<97)*HZ$LP8EM1J`AG9)EA010)R+E<*WI.: +M]:O'+5J/60FO]]?4O>9F7&+58QPXE=<$_[Y=?<@VU>AS\Z>^"&//+@SM?!MP +M0'>O[:_QZC1"HHK`V\AL!%@P)*Z;^UUI#AC3SVS#Y2EC^[8S`\,8J0E7-CCX +MH454<5$7#N4^4`KW*54I;%J4N2KFI^'5Y^,1 +MK?,;1U`HG-30&8H;-(IHL$"RXYQ21.AQ<9'YO,W_.Y$EP]>$?@W8SRAX(VJ] +MXXWC[7@D_XJTY#HU:-Q;\R[07W!A//^G^D1(YUR?'_H@@.0O#%9._OL\-E.KOUF_C24U418L\0)"7CMV")#BP2HMEXL%=+4KYJ^WI@G6 +M@%JZJ[2/0ZVIKYWXPTK^^'MU>:D;@0#<9S'L>(,5JZ50DJMVA5GDPS039RIQ +MAHKI;Y7FLX"ID"[LE5[6\F6Y!^#4VLGO*A@#T>?6EI?K[5HZ?\OY7:'ES7:OM_6K]**]WT>5 +MP=ID5_'SU^A)5`P>B12EBOG!G(\?]O(,ZJZNARE%[&H"K\N7383F-&V2K`]X +ML&K+H:G+2H^[NT.GXJ^6+]:LMOZ*,]>"%W;U;$( +M?)ED_MTH$E8_F)VC('`[:RJ8M;7I'Y&,+WQ:7SW<$\-Z5%RR^F`VQ>W:Y&.3 +MKVD*VG3V.Q%\AF-W>_VHUDSTKKXURQ/ISFG9V+O!Q/RKA#/P1FX6;(JDHD0DSR$B,08'6UD\\;$_7C)OJ,-9 +M7S>4O%<-T2^-YG8<*I6W&I-`"S=;,TZ>QK:=?M=_WOUDD;6=_]XS?/ +M*>QTH?(3.,PE=,TU?(3,VI7J'$_9%_?\3,7RS)JO77_1XZD"[*;^ +MY68RL,4RI'188PU[&1Y>,6YU7:KKKKPJE#WI=S>>'O4Z,V\/9WX-N/ESM;8\ +MMNE$KQMI7':P([CO)NOH3&[0>D!:],\CT=+-HPSQS:M[R`SL:&78 +MD5E._>).-1Z!^P=&J_#H$84WAF//-:NAQ<]OLIBHDO\0`5XY;1IYT9B\?P'' +M%\(0!_TWC:_$NQNV+K9GC[G@N.PFCK&N/H:2B/;!X-IY",&RUJ%\8:$WFK?$ +MTM.(9;\C@P60KV]4;6L'R[]FYLRXG:<9NA'WO>Q7;J +MH-'O7EWXG&U2H`)B\V'9RT]]'$L,;=R3ROQW^#1TMT9(-Z!OH"+OE4XSZW?) +MZSR\DH6[[$GHC1W"<+],9):&H\#XSZA6\%-S%=V"65A)AT/I;/0$;=97J +M_Q6,P"/QNSWE*=@J\>9*MT^+NP#S>)3B`./BO5>%3Q +MX_%%D'ZUI;GBK+*X#S.D39+E?G/R5QVDR2].O)V7].6T[%.EC-8\?$YFXK!4 +M]>;CU5T(=0!5_AA+&<;5Q%6O[H[.&/Y[?=^?'<$UJ%I,Q96U]9MQOKOKPR2 +MHHT23K:NM#H__:YEQO4Q_`)4W0K)O3RR6L?X=W'N/^%'L6/^"S-X:\JK\ZFK +M;0QG%@C5I6/(MRZ'\_OC2\Z4S&Q-DZM5L3Z7H*Y@)E9`6&("I",E=YQ;.<)[ +MPKONQ!\_1]Q//@E=7^W,Y'PE]6SO";-_CY=OZKT9FR[QA]]VWM:V;):EG266 +M:;!!0!S=&"#G3NF'MV(?L_#H4["UG\H'BM?!S8Y5TM^;!P;>]_^.M[#W)H3- +MZ+:P*(JPAF2Z^SXBM,!W,N\%ZDD-#]%*(`T+ZPSS6Q9;PIX^4]SO9.2DK +ME64=62R@B!MZ-35U?4C5^M/N#9D]3\$!V@O4U[`+L^K%C4_G@>WOBZL(3M.3 +M.\9'(V$4DY41?$'\3D=O3Q&1<0#^6Z(G72)^%R,Y5YBJ61N1PN2'"&X8M0/M +M4W7T?/,J%[Y%WATJBSFV.L>Y%`TAJG;+A@&41W8)?A!FSB3RJ1+,^+ESSZ[7 +M\W2_K2$+HC[QQ,KRZ66Z)!BUSJ$Z?$3^%@0B=UCFQ)+ZA) +M.WKI#%R2&JM#^_5T]'M>X6AV>SI]R&CF +MCX.C%?!^O/W,6UGQZ[7]9S:OLU,6"Q`QLYO\N-,=K0^SVWIZ'3[/1^SM]OL_ +M7V^U5OM=.533Y1%WYL$^Q$*^NC+)2@NN!2OI+.RN_<;?&-8,[Z(UKLQ4IO;( +MV1.58]O'C*S?<^J/JVH_V&Q4*KT+M4LZH,.C4I1>V02I*MTS[$',-+?/"%RY +MAR5^5RNSCK4VOL6;-J"'7Q*VUOJ@`HV>WM(:"3W8Z;)^G/&$^M)YP2K:LUR5 +MPX77*ELG)-->GW-'MW--JYF%H:$^("NGI=C0[O5ZE`YUNM5&0$)7!8;BL[@U +MQ>:/;Z=IBODE\][?SX3!T)7BY,$_@8,CQ?_Z#!<&T_^5[(/0D!?R'M6/`ID/ +MQ5)C +MVKN7FWC*8*6G@T/?UW<@:(JR!H6-MWEJMZLWWL;L +M>EY)?C2SE5LQ#WM4,G<;-1>B/OQ]&(`L,E8?)=C62K_OK3YC)=&_QZ84CPA0 +MZ+HVMVAEVAR6-P\:,J5CS=''4VYOJ;6E=O&C,=Q!ZT9S')$@K[Y560B0U9!V +M-O'W59^%,^5<8*-)#ZD^[I2QI!]Q8,BHS\DY%.QU>G_?3A1T7JPWF=[J=./X +M%@NIIPI,ET8.@'1[77^O(E1=/N^X'>[>G[)]G=T/ +M8NCUO=/JW.9?#XH_]-^,9V+DLJ)\5/3-R/;^5DYZ<['T7X8WN0VK%"CI7!V[ +M^0/=240=VZN7(SMD2M3LZBSJQ&%W1J&K>KL<^UL@>:_,16&Y4Z.GX$[NVZ +M[@.`%KP+G5?VBOC3V%3Z`,\LG9'AMGT*XZQ^,X(OS2K>PEP)]TX&'HI3_PYE +M)G/$V&RO%_BW8N]FV>:KW:I5<24X<9AKPZY`DB46P_Y`"P!=58)YM5?QCQ4S +M_(F=O70\IKIE!WDJO\>Q1FJ:@R\/W\#+'^?$-0=V&=BG"Z=?XX>@`[.0>-RV +M0=C+C2N8>KJLO2#0[D19S[E#Y63I1E__VGJ(```````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````!_[$O(_HQ?VO4_^?__________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M___^@$?\B__K'_I_____________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_____________________________________________Z!'_(O_ZQ_Z?___ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________________________^@1_R+_^L?^G______________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M________H$PAU1$,S1$`%A6]G/PHZ,\&EFE%I)N[L8V+L!6VF+0Q]%A-9N;N +M^)%$FDE6(DTM-46F7@W[O@!2?0B4HY'1,S15%(G!N;XZPPB3-1,=7.^*^)<_ +MP@_<_OW.1'!//"8$>DR````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``!R_'_CW?X_1W?U/E_AW/3SU]+^'S?P]/_^6TEBC_B4ZL_^C3XW_]=/*]8= +M"\$)%.]0KA0X+(H5]F!H."\,BT62$I>'@5#&QW\OY3F,N#>]FNE0AU(AG"5S +M=S/X>.'21%AWLTD4CBAW/7HT6UL=Z5OST;],TO:"AD\-E.G',K-)>NENIY9I +M3-$WZ)QZDU]9N>290F/CYE\V>*]OF^/CE&\%47;1=1&AD+1D\TD@'--[TRL? +M#/5O/#SXPO[T(P_K][AY)NRZ9]SATVBMK&S^\;W@FP\(;;$//S1LW8+A>3=C +M:7F[FH8QD[/GNHET1Z/!?IOJ2)S*X]OP\?#PQ^\O=VX?@6W2*>:G1+K6R>(>FIY<]) +ML9=VJL1P%/>T<\W#?-)GHR3-5]`_L>C/ZKZDX&4O.:7YU-X!XH!FU)5]YP?+GW][4@[7UU, +M8W=JWF_TJU1>9XCK[VP:SE[?NW,M@P):A[$DNCG!A]'9MVL@(=!QJR%AC&=_ +M4(P8N$:T+3Q[B=FV7**"-.$ +M@#-J\60A8S`RY)V*;Q-O3L>/CE@^>$N6G$T>.>*710.G)7=C:YCT_2BS;".E +M.\N@PI]_/G\T7#.3Q[0&-:B0'-Z1O'V<<.6@06?1EF/)[CL3HI$,;#;U=/0(-2TP3NK8[IR0 +MA[.-_D^B,/K(1^M!EQY*P!QVKN]OZ?+,Q?[[(\<>ZBM%FX:K_,N.YD#8"P]R +MC(6S3*V!<3CHTQ(,QV]6=*H;>QZB_6TT_+QY)4%CXL"B^CH\]UE&2=T['*9H +M.G0Y?J<^43Q9.$K>H22SZC)[L%C=?>$O#^SEW_QJ(!`%$8W>R>,7(7^M681K +M69W26]\GSWY.\/?]P+"=7D[S*TSF,)//R:>#S_)BYTVN[V^W_EVNWW>U +MW/Y>+N]S:^7M[7S=O]]^I=6X.@08LT%X9;\UH[YZU?]I^/D\OK*3S;S<&H\Z +MI;4>:]WN7:W+6?E.G]NF<*^SWZ&NI>Y\]@>XHBG[-,FQVNC1&F7EKZ_;^>>& +M;=M-]RO]R6Q,V[7Q]UNY_/R5\6'@VMWY^Y_*7J]ZW"U>)Y2#MIG"]S_/M=SILB?70"+N_Q +M^:)BMT5M'RUT!Y,NF58JZ^7YDJ0K]#(FU^I-ATV"VS\$F'[EWH\]MIXE%3Y9 +MW#?&-%[5;M=_B]OV3?G:NW_#M_Y?RP"\T48M\C\7Z9C/N*SQ>6MLW;QV24(K +M^>5ED'WX>_!UZZ"I\ZTTQ*BFBCL+E,"'%O==0`M0_C@O@T)B0PZX&CDP$/6^ +M[Y:B)[UDS.A`B;2)HBY3TAHH0CKZ=WQ:HI'[OQR2^,LF07O6FT'#'XPSQ\[T +MR<$0/QY)M.K507^K438@;"KV6T^HXO>#N]9P7Z\_%[XR1LW?%I^`B!T0^[)2 +MON8[_3^L#27P_C@CQ[%\3A2Q^0>VU[B'#X*[K[LF5;4MAQ0#3#,@WI&V83^I +M\TP@3W\;QD3O3>R5T0V=ERV=U'HFFIP2`W\N`3.#'4WJJW_CO&BNY71#`OG4 +M?8S6L>S'[1>VYEYZY0ZADU[EBH0J[,X11@\E+BJ2M)#]3[7%AV/_$HW8S3:J4F"7)VG9N""U\+P?00_Y#UY?)D@$'VESR?20:]2E +M/\T*#VK=FP&N*`R8VY]$75*!D\N]+6WL0XO/23C-:%]4V))?._:_/-.G<.S= +M0DA/+4>!1@/L0V9 +MD-?V>YV^[\W;]W+M/Q+E[PP+K0L9(BIQ;_;QMT0A^QDJCBY +M,O2Y!Q7K^&F$$#L4(IPV?.UX/N^OY/M[WW>#ZY!9;7V_73X<,.GF_;LL[=B> +M":J(=K1?:8C_WE_U%LO@R2F?^B,Y>J)9N*[)6&PY%2M.;1(A?NU=XTJ&0YJ5 +M/8\%":N343"]':[4+#-B?^QFI9(S+8H-BWQHU#]-WP=<Q/-U$**K_ICR +MR)4R0/N#577:PH3)D+X$_K-3F&1-N9?7>6DR8^^VJH=IKM3"0!4_+9:,DXNN +M&=2G:/O;UMX/P^^#3-F$3T]^XKZDGFQLKLUOFGSVX?HU=Y--_U+/PV3=?;?A +M5@:[ECDQ[*5LD\IT0(*(!D4@7^F-\ZL=.F[_,[?T4K-QV=J[\(HH1;)=_RWNY_L2-@>6#T?3[16%SIM5&C?@6N@I- +MIK3C5U0BZ//[LW7FY)R@+*#9<_DLO`:-3>&21M@=YJPTI'%?8==IK#OL;AS; +MK-XF=)/+DO[\\F_R3H>%0VOO9N>'AB7];JX%HZDC%_9S>R[>[R2;8^WSV[>2 +M:,K1&)CX=CE<;[T4/$KV-S,#N:2CZXW/:13TJ4ICF.KISXJPYR%8B*IZA@]C[^&Z^NI%[EWV9J` +MDP7-;I&0`7GLT-*T68S:+\.Q/>JG!?O'R]*)XJ40HNGGJ&T1HO*M0CU82;3C +M<@4)7\XXRE"M,F2YHB*4)1DA>Y2<:.YXO+JDV(HQ3"9/ET66.(]*D+LQ6A?R +M9YJGTW3],1F^3Y8HT++UY"YRQ[8S5=:5`J>NKS,ITG\'^??_I]/.Y,K?$MC2 +MB9V>2W#HFE!>><+!<\,F]7LQ^(@>F``9?OEXJ59OBZMCL3=$T/^#+Z)< +M->>$Z3=@@)"6UA"@G[ZT-/R%.X)$2=[:[/6%R#Z8@+:FN>C,5?.!Z)MIB8OT +MD5>1Y#1[AS:]=7T>C-2PU;[\H5XQMF3JV4_#(LMIIA&[Q\4WBE$7LY>LW)], +MN!M&&8+$&NLW%::H/1'^<.?!!2N^*^:JZTNZIO['HZW#&%/5M9R>7]W +MQ=,%1/6M#ZVB]L68@O9K:7IBC=FH+'SSRA,G78IKF(QJ&X9CM38=F3QY8A9& +M39JH5@_X+M*L"MANU#Z2X/89,/++B=&DD2[BTZ.L@:P^8(U!?"'-3]]<4Q"* +M8F6M,;FM-5]K6NZ?5$*I1.BU>V*5$ZI^.B)=@[49[CTX6Z[MOX:3A[!-[@R\ +M$PT_%B!_S::N)WG[DRSIO;+?Y)NB?]:&H!DKZM6A=.$5ITON@!OS2`OS98!KRTA]RIG2&S-+"(-RP3.Z(1-,D;&.G)_N<&?=GTT8C&? +MBB+081P8J;YEFT0O<#-]ZBA?WJ7(VYI7T$6J(H%O/=R[O1/OPS\%HRTQ.P6- +MS_89W^$B1>WM_W]:^+Z_ +MO\/VW0PC;,1F-\5_T3;WW^$G=7S2NQHK7/-GV[9&[-W^]W0O+46H8O^N +MP,(6TJ*I[5+VDH7:MJFWD\%L/W=48F?+V?HMEC_W@M9]`D3PVH#5`,.'`U[[ +M<@I)`>D5RXW[L(,+O0ROMSZ-.+VI7EK.`(N>=2$O++<665H0!*O'2Z5^39X& +MM@W/%$2M4^7DM&]6B\`N2LY.,O8`,OQ^4SP>?++_.'3#8OEZ772$\J'OP8XU +MU,Y^>25^U31Y-WS76*8JEK'K[E@7_TVZ55_\>[!`NMGF)!N[L)'4#ZX(_LCY +MGJ6C-N>Z@O_T^R'^)5)!Z90@_0JF!V<]DI49DWEMC-J'+7_:3'^PMGP;Y^K-Q5GGWK6HZ\J]/?G@T>'+Y/A +MY#YC6R#L^^NS4V!][>$9=_#-^>7X5YQ:/N])HZG>GVP[.M;M739"G;EGOMDX +MM'?A*'ZGB/WW]?*4(EW^38Y7>1-^ +MV#9$P++5>PM*4<3>/>PCY'7=5\+T0VKKX89I"YF#(\PH//6;$L4>L6B6':N\ +M/NPS1);FR[T1//Q3R?ISZJWCP2D-W[G*'JXT[=TSK$DBCTY@M/R^$)VSTA[[V]JW4K,:@OAQS5 +MT++<3X5R[7'QSNC%K'_6="8K]PYTS6L;\E`BWXTEL75YGGK+WJ4!TI(S:[L$ +MCNI.@2B0%CT!3P]1<7_27E5!WL;UG(N'')M65?Q&6SSAJI23WR\^H]MNBL=Z +MR'M)H4F33TR$W1T!U=C,0'SN7BJ-W,"K%QOO<]F2M$4\.A9IZZFT[_4OR[58EPR>UW)#>BB1<9;D +MY>*RMA*`()49ZEM][,99IRW=?X`BXYHAM7]A=PS5P:=(%57=H108R9U)M\_5 +MGT1&I/[?#IJ3>EXIW]Z74FYU1#*^K[YCKT*]Q,H,NF!)0^KX-/QR6K:Z_TYZ +M4R4X:VK#LH2)JNB$8[T?'KN,61)H33^BB&[.QJH>ED;6]%_Q0/#$=HVN3L=G +MZ*<_0IKRM7YTBU[1.-)9-O;/IHEM8H,YE_^2]FQ].BW;K";R8T6Y*`+::Z +MK0:[ZIJ]L^HH::SZ/0Y^ST\ZIWSJC(4+X?98M;C_]N])^(53HZ*8TX($G+]VUY:-9>_'+=/@S=.W5+PHZF*`B8X\I +MGRAJ5\/J^%;0VC`[LANY6SC\^UV?3T2W"A)UKGV"9%E\J:VMIH[S-1!JC-?> +M^G[*^E5@":,NF"+$>>!?+S1]TZ/QR:]VYDW?-9G93%!]<=+2*AF2_R +M0N-8<[Z+/N,FU8=3)9=PZYG:1V/BAP2>K'@EBF-DRU2#88(6$37W +MO%*&F1#_"TYZ-5N;_3EK6(;/E_=M3Y+>MV.S:-R9R=+2!1:)9\H(>A^8_OI9 +M&OGQN&^O)=DR\5NEI<>J8T=Z]\U:M^>W#-2GF$1N?X[Z_Q30X9P,S@TNI<0R +MT9N9=,@2Y[JZ9@6Y.&CA_ZTU0XO7;J&[HA]$SP&AY6/CNY=1R#Z74\][R<9; +MY<;HB?8KSP^*[E+[R[NK`\G_J%%BE,P\+13D&W1H&3>JIRQ0EFZ)+$P2#+0X +MKA#XTX"U@?OKR(3=,;ZANS"2[L,4V<*F^XJ8>]+EG[;^DT=&6M)AM. +MGDZ%=BL$6+J_`'R3:"GO.!J6#H<&8LH[&+YXWW@S_,@/BB'G%U'[(@1/A[T1 +M\&;33W[]_YP-;%R6,8U<;LI*(XO'DW:VKDN\D]\C) +M@[=KY,=N\5H47JOL4ZANF2@AJ?QY)>G-Q8UH-+K86YG4L;$8ZFW4,-:S/!>Y +M*.]LA1<4TZJ0`V[YN2DN3TA`W=TTX]IUHKHK2T>VI8@OJ`F(4O[-6/?Y+UY2 +MT);XWYS-`=]B=T@IN*(CHZESQ]6;1YL8MD?WT!6\.>OCE"(4OG\'R??L=[^_ +M@E!/TN8_8SOQ^=9*P=);;NG!/TN`>3";_*,7[/PTHS/XL]$S*:T;0T??*;5W +MCEUN5$:=14A&D&D<7DRX1N;>_M=0#F6RTCFW!YY.0>61>#-$51:-G#Z2DQ)O +ML\G3X6L/SBN[CT:DNI6[CS2"[)Q%!+IS^+ZE"(]D7KJ7+_U\?Y_GRO+3Z$*QX-CEG&;*V/'AYXQ.TQ7Y +M9CJ8C:-JTJ9/)$LM2`7EE7CU-L(6T.8GGX^+SP]HLT^#]-1\MWBYCXS,L`*0 +M4ZELG,ES,U'9#]T;\&3I!];V3@R>2(Y>\.6=8T_<+D1EBZ8]$09U-5KR>/%( +MAO[=%W*8IF3K=F=(3Y101HFZ?XV/OB2R<=PV:.D([?/+*I\5/[U.&*I4-8A +M"E@-W[?#[>9`,=JNT53[_MZ_&Q%&/!6DY^S:EH&B]H;W6=?&+$X^3I[)T-=T`#JJ,X5CEJ0,QRCI[7LGM?/`\\<4W8*9?^D,,O3S%F"E.^;3>?0WW>>IKO_9>DRVB1N%4W'0*BD5I1 +MV$;(E;Q]4/@P4,VZRG_8>V?EFV6]8/EO]#Y-BGT$,F-=>KE[D,/F4)/2E+O1 +M1(C@VS=3WJH=&S#ZUEZW[GGB5L]F^A*F/;6",TZ&LR0(=$R1_?CEV.MD)6N.KNKL)"Q] +MC\_HG!EWY1^S8%W1SF[^_8,BDQ-P23TP%O/7MD:^9F7"DG5KZH@:6-4Y/:%Q +MS[$'F`C)I/R!U]M&YFTQ!/OX4'O]SA6I$F:"1B$$U2@_1W"QN$['*?N_`&^2 +M.#+J/L.G?]F?>CJINK$CI_5O9J.QOS:W,1N--&?B-]:,H?U'QXJ4>>I7NI?1R/\8OR>]^QCRK1LUPB45VXF)M"(-)BT0CA;F_GW?-=7 +M*MFR5-5SM01[FSVOWGMMD!--4&EKBGP1DJ88\Z<+Q0K^VX%`JM$UDW!)RG0! +MS>S\]?#>GORZJK@^SA6L;S9O8I39_"'OH.#V]/BAG(V$O\7]<7*?]>3$)3NR +MO+/P31;-_)R6YHM+0=07,?8;/HRQ,%%"/5&Q3C&DV-:7HCD*RBIP344+N7SC +MMU]1`IE!*18+-`IP(57D$KG&-<(7DYQ0\\AF,WYT?P5VI1P:@`L-U3U*G[SQGM1.<-NUYZ-KW- +MIL.)=/+&(N_,E[0F3(33DOBB;SR1#I&-)K$VB]<9O.UU/VUV`EXY +MYN&H&=2NDZ8(Z9O(BZ,PWF5,.$)J9==N($)UFSVGE+LF]^,C,^3R8.?R5SRW +M@YK[_)6'J/1/K5N=VU:==F-[GXYMU_&.K5;UCW(F0`EQ]+0N_R4RA9\7XL;N@+'&K@RU%`R/DBIE-9)#F4\F%76COU +M^S6"\Q11HS\5#NMBWFBG2F\R1E=M,0K5'KQ)QW_DI,04KDYT:D./HU!O:U?RO83D,0BGM313Y@ +M:P*+>I2SWB[-/H?C[FJN](N]^.:AM66IM<[Y)96_C\U<#HQ9HBF+LSDCZ>`7TJ<]9 +MW3BG;N?)\VQ/N4'``W__VG1P```````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````/_E+Q/[,7]KU/_G_________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_____________H!'_(O_ZQ_Z?___________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________________________________________________^@1_R+ +M_^L?^G______________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________H$?\B__K'_I_____________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_________________Z!,`=$5#(T7Q9V;W,^%<[-7=@+1MD#N]V=(H:G#Q/=( +M`AA--ZA)I@\`SL8VT\;D&?>M2!R0!DOP\\./&QXPV1=7?1(/.9RZNKNZNKKQ +MWGQ*OX1?J_5X.4KI7=_DN>RP```````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````]7?Z>=_S]7/Z'_'T_SZ'J7 +MG8OY\[H<_U^_<]3X^G*78Z'%@/H>I'0Z,(3<_)L6QFZT#(>Y#/O>'I]'H_<* +M=:?`W*=*-,E-&B1W%@F0W/=*D#ITW8;Y_W5:/4@8RP_?AFD7WKCS/@7)H]+L +M1IJ[2+S*'#(,7W6UN5F<73-";Q6MA'#.]Z>C;#!%T6]3K7X`N=_9U9 +M--3^T'O#]'T[_//YWTH>;W,V>CGY_Y/Y=C8\L&01#`V?N +M9^_=`^UZ?9L_?$K_J*P%"\:XBTSX"YTN57_ET:9PUG?&KC!T#(XU@Z(H)M.M +MCXVC`DF9QAV?_!Q5LW*/.QO#/X!&?\._%/#TZWLE@T_]^?],.0'3\5*>/1U$ +MC3Q>`0@L::NG"!4M/W.T^S^GN>CFZ?6@N@2`<1RL`U7+CRC5@29!,>/[>FKU +M&*UKZXJCN%^S2ZG-B`]*#(YVL,%!/I[OE]^<$ZO0T?!^AO"!JK##VOMU/'5V +M]*KP7&DM7+]\;=-HXXN9'5&>>5N:/[)FET[,S)4R"@?.L\4A&IYKPQ9_[CKK +M%!HKUQBB(:<8,UV_-'[(2!SS=.NH^VGK^Z^;W.WI:/@TY9Q7==8@:>N-D&]2 +M`E2VI'?K^JII/-^H[PL(JDL>0926S!'E@D'Z/4ZO[UJ7UYNM73C"^N^E3Y2$ +M"7BNBU^R"E2I1D=PE$H;YNE7Y)DOZ]5/HOB]7EU^R#100\_[L,6CKIZ6W`@/ +M8WVK_FF*$_KO#;^V#)]OZ?7_Q\W2O?*_E[G_M9/,#=';TL_P1M6^A<^'[J3C +MI_=%OP05+,6G$Q='@2Z<=_&_=!=YU9\&$S#7GH4=(8;++7&-WKO1>*]6> +MHEE_XWGX02:]6K/]XB"R<="=Y>7(3=$=F0(J@EH6`N249QM"FA;\9"HJRY"E +MB(==`E[4*3L?1-+IFX9[CNC@V3=\GQ;DZ96QH>C%MN4HE9"R03,]B.#?5\%/.LBUOVKNPM[@^$)19E-9HX1W +M=F7.%0/S:+=WTNWQ[?%D&'W%BA>CT^2_N3S>?G?TSN=&/:_+Z57+Y`7C[V>CV_E_5Z)\.5+6J$[GU[:;\$,UFB(S)M;N,(9UTC-H*]E97YMNJP8;'OU$%Q,%3>:<5^V)EF$<[RK"1;16R:K? +M,7^*A*UT^/L>2LDC@BA\&]:KUY1*!KO.(#XQ>T;%?V]5 +M\\O=X[SV26E.7R):2WLQ!=O/1QY:=Y5C!'EB+X"TY>YP_'PB6[+8)7S4WX\" +MFY"LR-6K[E+GY7!=&":IE5-4MJM5YI#+X.GL:LC4NO1!^SJH43I[?:Z_2D][ +M:;H,6/67;_KG;^D+YA!V$Z)91L=QF'<6TMB93A_ZS*^)IZY#*L*$MR>X\/'_Y!W"\V(_Q2_99DTHAIM4N3(&D8F\YT[ +M>I!0VQXHPF1=+2OUV5A;ITT1K=UDAQF-MEYTAMRDF/PJ?A^'L^&5O@V$/OBW +MSX'TX?YM1A8JX@H5A[?\B[P-VT]9JV!^($I<,I@HHCHRJ`UP$.R(P9WN7Y8- +M.O@>+&:>F92NE<0K"3-[^(;W0Z,SW\/I\T$Q'\K[XMLI:\C/*7JR#SB?JCS, +MB`?>S',6^[-)MF6D!KT>KW$@3(G!Y*G\C\&=M^BCM5E-JF5GV="Y?,WTA1]> +M5[YY2"EY=B@W4D92M\(W)C2X)\'O5]%H4V.[&U2K<-I55B[9JP-W:WM2$"#Q +M`=LIB1U.^>/1"L86@R1[/B-^N290L24:_HFJ;T^JX8#EG+23(L5CWXI0<>E@ +MNCQV!VVR"IJWZ +M?#W."E69,E;N6D1QA].1D/-@3!LTZ21Y&L3=?!MXT]Q^\"@\2+\AS>QU1C_? +M(&-AWY&=ZM2L/W5Z*0"EH!E2S="%%-;8U-7%#R0J130TYF=2OSU;-&S'+CAN +MGK,SC=&>(Z+UD6TK8!/`%HYQ\>5#O,`9]84WZ=*T(]W!L[&+#$U](CR^.F4, +M]?OT)8GNKZ_?T;9(2IE/6@#S.LB3I8NVWTH;#KXQ!483RP0Z +MCQQ^G.NO7R*W43+\R":5G4`$X9UVN!,O^03EJW5!F6RN_CS@AW-+>D`;.@372'_I98>X +MNMNSRUH!(0D]BG@..)>9\:2Q0A7X)*]XS%3&>,HIR)(XDVI(US+VN$0PY4'6 +MV)RKC*Y)5'0EF#$MJ-0$,[),L*"*!.1>V8?*4L?W;&8'AC%2$JYLY3DZI& +MU>+!=97.U4/!&U7O'&\?:\$G_%6G(=&K1N+?F +M7:"^X,+FCH5:1/&](^6JGIQT2FTJLDK!]'PS[%.C9XTD7\-=ZSHYYR^U^M&# +MHR1V/UYW;%I&'1;&7!+PT#\R-NTI$$Q8`LVHY.]/3`BJO+ +M+^L?:RQ:$^R&>7/ND`WM69`/+M7(R0=P=79>:\;L^2ZU97C+L^GVKG^#TW\: +M2FJB+%GB!(2\=NP1(<6"5%LO%@KI:E?-7V],$ZT`M757:1Z'6U-?._&&E?WP +M]NKS4C<"`;C.8]CQ!BM72J$E5NT*L\F&:";.5.,-%=+?*\UG`5,@7=DJO:WD +MRW(/P:FUD]Y4,`>CSZTM+[A_N)*];$RW->5"%N%)MZ7V[<6/7'8YOT)*H&#T2*4L5 +M\X,Y'C_MY!G575T.4HO8U`5?ERZ;"K8A#Y,LG]NE`DK'\Q.T9`X';6 +M53%K:](_(QA>^+2^>[@GAO2HN67TP&V+V[7(QR=>TA6TZ>QV+DJQ\$\FS1[L +M2UE=?&N6+FUY2VEM0D1B#`ZVLGGC8GZ\9-]1AK*^;REXKANB7SD;*F;QO,[# +MA5*VXU)H`6;K9FG3V-;3K]KO^]^LDC:SO_O&;YY3V.E#Y"9QF$KIFFKY"9FU +M*]0XG[(O[[ER9RD@%&#\((LLKZ\/BA/TLD)_N:'>[&7LECO;NSDTPJ'7S/X] +M#GYL66'D]O^4&0.[;WB9B^69-5ZZ_Z/'4@793?W*S&5ABF5(Z+#&&O8R/+QB +MW.J[5===>%4H>]+N;SP]ZG1FWA[._!MQ\N=K;'EMTHE>-M*X[6!'<=Y-U]"8 +MW:#T@+7IGD>CI9M&&>.;5O>0#EU.UB];V=C0R[$BLIW[Q)QJ/0/V#HU7X=`C +M"F\,QYYK5T.+GM]E,5$E_B`"O'+:-/.C,7C^`XXOA"`/^F\;7XEV-VQ=;,\? +M<\%QV$T=8UQ]#241[8/!M/(1@V6M0OC#0F\U;XFEIQ#+?D<&"R%>WJC:UCE2 +MK!Q$"R8W4*+6PP5)C3=3[NI-AI0\D-=[.U[L=,GR*S53#,"R-39V:.&#YNEQ +M'V5I?^IY(MXJ3&CP^7?LW-F7$[3C-T(^][V*[=5!H]Z\N_$XVJ5`!,7FP[.6 +MGOHXEAC;N2>5^._P:.ENC)!O0-]`1=\JG&?6[Y/6>7DE"W?8D]$:.X3A?ICD +M3S)+0U'@?&?4*W@IN8KNP2RL),.A]+9Z`C;K*]7^*QF`1^-V>\I3L%7CS)5N +MGQ;FK(P'$8^#%)G((@:[UV`>;Q*<0!Q\5ZKPJ>/'XHL@_6M+<\5997`>9TB; +M)JNA#J`*O\,)8SC:N( +MJU_='9PQ_/;[OSX[@FM0M)F+*VOK-N-[DY0)EF_PYH/(PSY/6;-Z]`Q:(?$X +MIH]U+:<`_`57/1$.1'2O7VZI1SOGEPU;U=]>&25%&B2=;5UH='_[7,N-ZF/X +M!*FZ%9-Z>62UC_#NX]Q_PH]BQ_P69O#7E5?G4U;:&,XL$:M*QY%N70_G]\:7 +MG2F8V)LG5JMB?2]!7,!,K("PQ`5(1DKO.+9SA/>%=]V(/GZ/N)Y\$KJ_VYG( +M^$OJV=X39O\?+M_5>C,V7>,/ONV]K6S9+4LZ2RS38(*`.;HP0:V++>%/'RGN=[)R4E +M(R+B`?RW1$ZZ1/PN1G*O,52R-R.%R0X0W#%J!]JFZ^CYYE0O?(N\.E4652)9GQ?7:_FZ7]:0A=$?>.)E>72RW1( +M+E:*LHEEZQ-XL[T6N=0G3XB?PL"$3NLIVS%BD +M#X7O8KQV]=(8N20U5H?WZNGH]KW"T.SV=/N0TV]/0Z?9Z/V=OM]GZ^WVJM]KIRJ:?*(N_-@GV( +MA7UT99*4%UP*5])9V5W[C;XQK!G?1&M=F*E-[9&R)RK'MX\96;[GU1]6U'^P +MV*A5>A=JEG5!AT:E*+VR"5)5NF?8@YAI;YX0N7,.2ORN5V<=:FU]BS9M00Z^ +M)6VM]4`%&SV]I#02>['39/TYXPGUI/."5;5FN2N'"ZY4MDY)IKT^YH]NYIM7 +M,PM#0GQ`5T]+L:'=ZO4H'.MUJHR`A*X+#<5G<&N+S1[?3M,5\DOGO;^?"8.A +M*\7)@G\#!D>+__08+@VG_RO9!Z$@+^0]JQX%,A^*I+D++;=<1HUU*?X?H(RZ +MRD-O&2BL:LAMQO_U]N@4GYF5(J+8Z-L@3K8U[T>U=R\V\93!3F7*[828'L// +M;'E'!S/KRT\&A[^N[D#1%60-"QMN\M5O5F^]C=CTO)+\:6]JAD[C9J +M+T1]^/HQ`%ADK#Y+L:R5?]]:?,9+HW^/3"D>$*'1=&UNT,NT.2QN'C1E2L>; +MHXZFW-]3:TKMXT9CN(/6C.8Y(D%??*JR$2&K(.QMX^ZK/PIGRKC!1I(?4GW= +M*6-(/N+!D5&?DG(IV.KT_[Z<*.B]6&\SO=3IQ_`L%SD6H0/DDFWX?+;]G?T> +MSU-.%)DNC!T`Z/:Z_UY$J+I]WW`[W;T_9/L[NA[%T>M[I]6YS+X?%'_IOQC. +MQM*H4L`'"M;'1XZ +MDM7I\=CE7+PU;U=CGVMD#S7YB*PW*G1T_`G=VW7!PJ?0! +MGED[(\-L^A7'6/QG!%^:5;V$N!/NG`P]%*?^',I,YXFPV5XO\6[%WLVSS5>[ +M5*KB2G#C,->'7($D2BV'_(`6`+JK!/-JK^,>*F?Y$SMZZ'E-=,H.\E5_CV*, +MU34&7A^_@98_SXAJ#NPSL4X73K_'#T`'9R#QN6R#L9<:5S#U=5EZ0:'J&?_1OUJ=Y7J9V45-IF0'97^*.^+__"SO/I(.MP.7!P7! +MDL#G$T\^K,^^=@6>9IU!]1L+14"5EZHLTQLNZE*M8V]_NS[5.(N7ZDV)#A@T +M%ZLGY1?TZ:KDIW%%#T%Z:I_-!OKZ+RD5=I2"AM"&%<F9T +M)4;8EZTP_]:ZQ\:ZL$+8ZCW'*P$KI=7`JAW&B`X"L$74EEA\0F)4\,?$*= +M)^FMK.)('5=PI]2Q2Z^_730[/($"GS+O_!&9U!*C)X?'A +M@?Y*C896K8#TVO&DM$D22E7*N*(B3^,?S\OU5%]PRV!S7PKRSV"SOT!T,ZT, +MPL4R*@,RXD:/S2>+!)2O#+.:Z:,Q8_^.2Z6&R*2J+V7[\: +M22)H5L&)BIB?-HXT:'EJVWE_5G?,9\AF!,+P_UEW#5]\G0%G#)VXCP8-TS?AB&NAMH_. +MN5%/VO(#*WC.-;_ZGB5;*IK_;@LW5I.H!'+^BMQ[-+NO!WBBNN[D;Y4S@#^6 +MHS$7/#O!UIN3`'9`$\5()9:$%$A(@LT,;V4GJUA.@TBYDIMY.GL?09TH9A\) +M&P041M.E;WF>U>2&#?F/WE'F,BO*ZHXRMFG.4]R\XF#HL38`X.\XZIB8X^4Z +M+=#]D0-G0JB%''.S*'*%8Z!;J`%`KA\Y&7/KZS6^;]PS16V'DY-JLE4>,SV/ +MT*`LO0H#YW`)*`$IKHJJ"QZCA"SM7<&"Y@8P^"NJ%/LC/+9!MDH-[NF-@8B_ +MQ:5_!6.\OY3$Z6*!7\LQ(QTK#:_"+C%[ +MIC`35R0R1;7ZI,Y'=?$4:=//'-XW24FT,WT.C$L@1Q +MY_*;"^'_P\/Y.@EFU-O"'D4^K5<5GE]_U!6JBS;%JZAJ[\JLBO3XWR&CBN\! +MCPZ<-=8'E_AIA>6$9[C_BEU3*RW\.[B7DNO_<%OK+?T)F12>Y(<55,;K=K"(G&R@7H(+?[%\=>>(9Z@6TQE!(E&WM2 +M6(RN;K4PWW']QAM3&8-'BI_6V=>67EETJI58I/%^V'Y`)QVJ_-PMX]'D!@K= +M_+9>*F5IB.48.SQQ#>+SP;(Y4"(##2,,M0SQA@*5#))W!,>O-<\UI28HY\8F +MJHQ'H024"3S^?UK8"Z7/=\K'0+LR"^RG,84.3AZ];N!L-GH#K04MI]9.=!?B +MB$Z]TC-BS^R'^![STM'0-'25OTU"3,__$G[1Z2"`^20%[@MH"Q2? +M86#8@C1Z(*C]I:QL=F6)`;KY@H_,T5L"L:6B;=')"FI%Z_?\H?Q0*=F(',D@ +M2=WK5_P7-S=2XP"?&(,C3_T.XL3CZ[K9Z%['FYSEQMM/8@C?I",[7*J9#'<#$38ER^&CDX+%/!23F(@$9333&F +M/+`;A>+LC< +MN#ZSUEL'U^<.&%VP+^OO.!0"$M9%QK`Y8X%?_X)[D&NV>:<$\63EC95#B$MZ +MIA(SH*0.J:-R]2?N3)]GK;TL0',."`?@?@LK@,.KHWH)O?^Q_#S;S(W+/=:S +MT\HC*W*[P;&6X:&X8EK)!CYW6-Z0<'CJ*)1CRWP%2QPT;C"_88ZV*0X([8Y\ +M83!'!3.7?CWC;GD^2UFZ6UC*J+""K@"V8/"2,I303I'KH4C;_CD.[A$N)@7S +MJQ[`@#=F?>_')=IS!XMAQ..0&L#!;L(.%B@PL9+)-@(2E.J=[@][BYHA=^?S +M).>%M<`]TGO@R#.@+*40.C:Y#]ZX&1/YFF7Z2>*IG8OFJV#FFM;\51V_79C4 +M'[XBKA@(\G0!44;221&B/;''5VV2I?VH\)5KI3$%"2#0?AUSM(BS][#.V@HF +MBC:DVP1]/X(R\X;0E%:NRT"[#D``*IGFTL;GZ`<%\@NG#C(T!A2&3F9H`9<$ +M@H-R[]/">I9P5\\V$6S@\6&LO4USF:\\)IO\5SLB)[&#KV**6`Y%J'Z_.=ID +M2W[OUORZ#%,C@O>S=,9MV%(CMAP)/!ZEE7X%S9*TCCD8.YT*T;!Q^SOU1,L+ +MSM#9?/,;8#AGKJ^&>TW+OJ_PZIW\\;!NS]:K77N:KM;EE$"\F+=ZZFVJ7[FI +M4;-8BH`_0%+,TP>18F`>>C3RS]*C81!3K7S.^49,D#O"+V`:N-_`>9!QCTE#GBQR&#/FF+YT +M__RE!AL$3WT4U-0NFF.#\CT',T83SUZQ&Z[[Y=K9SLGGRDJ7G9M#?-6;F1,% +M:O*;F:56.:E]\JHWSJJ4PQP4R%D<$*]@E8_?7=W>#)SMT01Q&1$.>!2YKF6$ +M@%1](?_RA0FL>D"O'C_1UB^1'83'4>8Y95+1L3Z4'8'P6?*9Y:J"H4.;3IGS2J"[,S41\8^;Z\U2.%GI^L=FS/*!>?5:!O`7Z3OF(,#F+-D?)S@,%_Q7/EG\`;NF!1XU' +MVE$)*Y'@"8&Z_SES.X!!NU'"4$W9(%QFJCZ*D@PI9A57VGZ7X>^X=KV4WJWR +M=6Z1E>+R].WV">O68NY/8L(`R&D:F1LU>Q!&==(8>(NVEA.([@?W9^J"07@O +MY[5*;?VOMHS&^D-Z=8:),#87K9%[T.4=IAM^9:^=C;[3'9M%7]4T[=$T".LQ +MV,DG[_'^&;V8ZA'.&X+>OXJ!';3$T;[L!=29I4WU]%M+5JZ(#?WL,D2#-J=H +M/'+%EPE_9M3J1<$VTAG]PX;@N5,:NC,_K0P*"H%3NB6?P]` +/%`!8UZ=L`@`````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_multivolume.part0004.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_multivolume.part0004.rar.uu new file mode 100644 index 0000000..0bfad77 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_multivolume.part0004.rar.uu @@ -0,0 +1,208 @@ +begin 644 - +M4F%R(1H'`!EZ5J2C]?9NI\:;KW2+#TR@_Y5=4S)O&)O_B>J0/A0T-,@"ER';1YX:$ +M>AMQ1<[:Q1,R`,93"OEGSEK=MI8?J`.7F@.OG"C!,7`D$L>"<=.F[V1><*&Z +MR!RD@+&WIGW-?>ZZ^_[)-77?FF6P7=.]0P[ZG&Q:S^`6\IB_@_1WBNHT(_NG +M9U/F2.B1=F<0IU_\^4P5:0(O3UZ(%]?;P+,:P93'TY1&$%1":^%%QL3=^$\H +ME^-G\V%^"LU6_VKL;52EXDPE5CDBK6:^`<^^NLA^<#12RV@C=F&KA_.16*(< +M"Q`]X2NXR"Z&3R8<-5)4NFON6LA>OO>DP%W\;:X%U02HV.0\A0\.7]!)P@O](;[;\:,&&0*B +M5YO(-RW/XL3PZP4?[(9_89&I4IC0F/699]][TOVQ&#CK +MG./_&Y%`6$E28)$-"V2S&^(B:;L27@TZP;&XQN2>P`3>^+@^U +M>SZYH"D6%EA@NHX_.PQ"JO1!20@`TMD)JB'I4I6"Z!?34%7`3B3`S[W"5 +M57Q3X5LE'?*5Q3-?=]G(TA<>1WH"VL7#SCU2]U;3<;1UI+Y@+PB1",6L'D/@ +MM!@CO@&YJ.1``6:=$6ALA);LL4A'D180QBLO%%EIX.ZI5Z:!`$!,8K@_@W/G +MDRCU(!GME6;Q(J$ZL*]%DFPT@C?A&-.+TIF=(7IXW!Q5:4`=:^IG+R?95I#+Q#/-`66)_ +MT1OPBM\BO<*$C9V>"#>` +MT"7[\W$'7L? +M.*&G[H-0!K:L3\`9B9&#Z9KX0"@%40J%1LYHFH( +M)4A3)R0;W.R(MQ0.BYI%9)X*2H$/0.!4^\4JHQ!H:'=2VRCP1`%NG14 +MP<"#A;@MF=G$*%LRY%A-!VF)^Y!W3T/[,E` +M*8*K8Y:![1="6!^TVCEP%LPT6GQ40RGE5`!6.DL%`_JB<:0,R$[\KW<],]RQZ"%LR"S^Y"[?Y4JWM17;TS[]M9 +MC;^>;TRIT*W.^0A:N`>!PT\WL&47&.3;3>B$`L?U34%5S.,URDF.1R4BJEZJ +MO^9/\[5[(&31;I29KEF=.NV\#96`_.5(87"X^@BI#\ +MS6>SG7G"U:U9X-[@@(F&JZ)2H_\6_*/R9RR]W.]0A*T&+M\/-7?G'?EZ_A)LM)_!W)4+\X"=68E3"2 +M"@`]:LP77GO\ZH[&=!+0E.M:'.I=!M%.=8Z7`FK+6?L*4L!GZ;`X[DZD2/QU +M4.S#!XYJG1===9V4+@KZ`UA-9/ +MWLY^X*'G!%G7[@QC2&-02_9@/UTB77._0#G].]H#K^,<[,!+'&_]?7`LQ5EQ +M0'P[C^,$E*92AFIN3S_7G#83@/;-48\%X^QXOHC_)E8*=DE*HS?V=(T-OV)1 +MAL$4XOL.@##ED,"_T.;E"5;!0&?O@9^SPTGEET`Q)J6>MY!/J.\5-%>&`7DR +ME;S:JJC8-5QP9R*>^T0COJ@C_1K!P'Y>C]E.75$17>M_=YH!>Y'YI4N*M@QUD9&[4N$MCJYU*;3J-(2!4].I6J3=27\XWLCHXI4S +M@6T8Y*+]ZS3$\BR!ZF\6=*_W:'B961W(FK3W?%&RZC!XLW74?M*,M:!^M)BJ +M:D=K]+XRT%`JI2#:NE/5FSR@_:!F0CU'G9)J;QUW%),+#8PJITA!\!/L[RAP +MC%W6^E+33:;\BV+%UZYN1=B6XYQ_*%"&MYUE9`5]$?+!N:NVZO.@0?07OV+( +M%//RQ49B0?3320&&!'QG],AFT&X!7&.ZH7:XB>OFM5?F]=`[VCM]+OBI]XR; +M26Z9H'>QH;MIR4*+EMZ5B5>(U=`S=53Q8M-?2QK,13>K`RTT0[NC-UOMK-"Y +M0DN),([?4I''U1B^TX%CU3$H^!8,$J9[X?<%B$@V$LA#)*-]VGUOGMQAJT*#,T@E7'H< +MFX"OG#',\6).^M.P#$U88"G%$%*_4%SQ4%>N&HU1I$L)())YB9_$UH<+^=N3 +MYRR-IW4/+MT-Q^(B+XP2[3]2_K*=YS)`;8_;;H8V0[D04ZA'C-[A,?/;IM'RF[NI_[0RVO/\>N\UX-FW^T!JEO_YRB?5- +MR0//T/N.C\DV@ZX*UFO![^V@8(EC4'=\. +M[S$:_]T0'^Q%]Y3>(CDK[#8)Z.>^[?6$1RMX;3NSQPRL9_1"<,O>[T +M<.RE!&)^#O,JH_N028&/]@"/51>IGP4!-U9Z+(8)9&MI+GX-NXS"F5P\E$C; +MM+>:KG]!QOF2I*(I\]UW'L78A3"+QFQ=DDDG6PKG%'VX-):?[EW6[%1=*UZ` +MYQ1MA$-P>RY:@S_6S:E?VN8GT)<@)<\I$S0BFW_:6,'U'S$#Q8FSC2\2KINN +MJC$Z-215^PH`:`D%68PZ>0@C2PNXS3T&"%*7I82@&X"'!!'+,%(A(FI?7P]3 +M,&.,;CK9H^9SAI!%_..5#/M=O)1P&R5M7Z]:,-WH:Y7SI,3!C]<4#ZSME:.% +M0'-4/.3'C0G]K=BM\&%*,&UIEJ1&<.7%;CH?6C$X=$NFE^`3K-PLY[.!D=^O +MEFM50/A=JB@J*B4L7LG(`!SR]<;B\>0)&\SH.\65[0N:?@-DK.$$66H35*C8 +MW&&\2TG;_]J2U/X^=1,!-/8DKL$?"-U+LRC[V,4>5CY=;BO=2!`W`Q_= +M'S5[^HJVHU2F!`_#O`#GU(EHGT*#MI[^DB$T(P```+^(9_:I_]3K4'3`D#(` +M&0```!D````#\=/\$2J%$C\4,`@`_Z$``'1E'3`"+*!$C_3@1(_IQAS[Y;82LZ= +M4#-R:O8OE21=#P_TUX6[``"_B&?VJ?_44IATP)!+`/(6``"/3@```V.F!5ZR +M@1(_'34A`*2!``!T97-T9&ER7$QI8F%R8VAI=F5!9&1I;F=497-T+FAT;6S` +M"+*!$C_3@1(_IQ@[Y,&O-%WTZIVL0'K=[L^M$"SZ*I?&B@$S2EO?UM\%P_[# +M*[0L[1)9)\]U]*;T*VY-H-V?:#KQ512.@3PFR-]M+$AU5@KH[FU"*J*5<[>J +M&?_1OUJ=Y7J9V45-IF0'97^*.^+__"SO/I(.MP.7!P7!DL#G +M$T\^K,^^=@6>9IU!]1L+14"5EZHLTQLNZE*M8V]_NS[5.(N7ZDV)#A@T%ZLG +MY1?TZ:KDIW%%#T%Z:I_-!OKZ+RD5=I2"AM"&%<F9T)4;8 +MEZTP_]:ZQ\:ZL$+8ZCW'*P$KI=7`JAW&B`X"L$74EEA\0F)4\,?$*=)^FM +MK.)('5=PI]2Q2Z^_730[/($"GS+O_!&9U!*C)X?'A@?Y* +MC896K8#TVO&DM$D22E7*N*(B3^,?S\OU5%]PRV!S7PKRSV"SOT!T,ZT,PL4R +M*@,RXD:/S2>+!)2O#+.:Z:,Q8_^.2Z6&R*2J+V7[\:22)H +M5L&)BIB? +M-HXT:'EJVWE_5G?,9\AF!,+P_UEW#5]\G0%G#)VXCP8-TS?AB&NAMH_.N5%/ +MVO(#*WC.-;_ZGB5;*IK_;@LW5I.H!'+^BMQ[-+NO!WBBNN[D;Y4S@#^6HS$7 +M/#O!UIN3`'9`$\5()9:$%$A(@LT,;V4GJUA.@TBYDIMY.GL?09TH9A\)&P04 +M1M.E;WF>U>2&#?F/WE'F,BO*ZHXRMFG.4]R\XF#HL38`X.\XZIB8X^4Z+=#] +MD0-G0JB%''.S*'*%8Z!;J`%`KA\Y&7/KZS6^;]PS16V'DY-JLE4>,SV/T*`L +MO0H#YW`)*`$IKHJJ"QZCA"SM7<&"Y@8P^"NJ%/LC/+9!MDH-[NF-@8B_Q:5_ +M!6.\OY3$Z6*!7\LQ(QTK#:_"+C%[IC`3 +M5R0R1;7ZI,Y'=?$4:=//'-XW24FT,WT.C$L@1QY_*; +M"^'_P\/Y.@EFU-O"'D4^K5<5GE]_U!6JBS;%JZAJ[\JLBO3XWR&CBN\!CPZ< +M-=8'E_AIA>6$9[C_BEU3*RW\.[B7DNO_<%OK+?T)F12>Y(<55,;K=K"(G&R@7H(+?[%\=>>(9Z@6TQE!(E&WM26(RN +M;K4PWW']QAM3&8-'BI_6V=>67EETJI58I/%^V'Y`)QVJ_-PMX]'D!@K=_+9> +M*F5IB.48.SQQ#>+SP;(Y4"(##2,,M0SQA@*5#))W!,>O-<\UI28HY\8FJHQ' +MH024"3S^?UK8"Z7/=\K'0+LR"^RG,84.3AZ];N!L-GH#K04MI]9.=!?BB$Z] +MTC-BS^R'^![STM'0-'25OTU"3,__$G[1Z2"`^20%[@MH"Q2?86#8 +M@C1Z(*C]I:QL=F6)`;KY@H_,T5L"L:6B;=')"FI%Z_?\H?Q0*=F(',D@2=WK +M5_P7-S=2XP"?&(,C3_T.XL3CZ[K9Z%['FYSEQMM/8@C?I",[7*J9#'<#$38ER^&CDX+%/!23F(@$9333&F/+`; +MA>+LC:<$\63EC95#B$MZIA(S +MH*0.J:-R]2?N3)]GK;TL0',."`?@?@LK@,.KHWH)O?^Q_#S;S(W+/=:ST\HC +M*W*[P;&6X:&X8EK)!CYW6-Z0<'CJ*)1CRWP%2QPT;C"_88ZV*0X([8Y\83!' +M!3.7?CWC;GD^2UFZ6UC*J+""K@"V8/"2,I303I'KH4C;_CD.[A$N)@7SJQ[` +M@#=F?>_')=IS!XMAQ..0&L#!;L(.%B@PL9+)-@(2E.J=[@][BYHA=^?S).>% +MM<`]TGO@R#.@+*40.C:Y#]ZX&1/YFF7Z2>*IG8OFJV#FFM;\51V_79C4'[XB +MKA@(\G0!44;221&B/;''5VV2I?VH\)5KI3$%"2#0?AUSM(BS][#.V@HFBC:D +MVP1]/X(R\X;0E%:NRT"[#D``*IGFTL;GZ`<%\@NG#C(T!A2&3F9H`9<$@H-R +M[]/">I9P5\\V$6S@\6&LO4USF:\\)IO\5SLB)[&#KV**6`Y%J'Z_.=ID2W[O +MUORZ#%,C@O>S=,9MV%(CMAP)/!ZEE7X%S9*TCCD8.YT*T;!Q^SOU1,L+SM#9 +M?/,;8#AGKJ^&>TW+OJ_PZIW\\;!NS]:K77N:KM;EE$"\F+=ZZFVJ7[FI4;-8 +MBH`_0%+,TP>18F`>>C3RS]*C81!3K7S.^49,D#O"+V`:N-_`>9!QCTE#GBQR&#/FF+YT__RE +M!AL$3WT4U-0NFF.#\CT',T83SUZQ&Z[[Y=K9SLGGRDJ7G9M#?-6;F1,%:O*; +MF:56.:E]\JHWSJJ4PQP4R%D<$*]@E8_?7=W>#)SMT01Q&1$.>!2YKF6$@%1] +M(?_RA0FL>D"O'C_1UB^1'83'4>8Y95+1L3Z4'8'P6?*9Y:J"H4.;3IGS2J"[,S41\8^;Z\U2.%GI^L=FS/*!>?5:!O`7Z3OF(,#F+-D?)S@,%_Q7/EG\`;NF!1XU'VE$) +M*Y'@"8&Z_SES.X!!NU'"4$W9(%QFJCZ*D@PI9A57VGZ7X>^X=KV4WJWR=6Z1 +ME>+R].WV">O68NY/8L(`R&D:F1LU>Q!&==(8>(NVEA.([@?W9^J"07@OY[5* +M;?VOMHS&^D-Z=8:),#87K9%[T.4=IAM^9:^=C;[3'9M%7]4T[=$T".LQV,DG +M[_'^&;V8ZA'.&X+>OXJ!';3$T;[L!=29I4WU]%M+5JZ(#?WL,D2#-J=H/'+% +MEPE_9M3J1<$VTAG]PX;@N5,:NC,_K0P*"H%3NB6?>&A'H;<47. +MVL43,@#&4PKY9\Y:W;:6'Z@#EYH#KYPHP3%P)!+'@G'3IN]D7G"ANL@B!?7V\"S&L&4Q].41A!40FOA1<;$W?A/*)?C9_-A +M?@K-5O]J[&U4I>),)58Y(JUFO@'/OKK(?G`T4LMH(W9AJX?SD5BB'`L0/>$K +MN,@NAD\F'#525+IK[EK(7K[WI,!=_&VN!=4$J-CG'Y+`M`=_$)S"+XG1P/;R#]+]L1G(=]<2RS[GU*A9"'@XZYSC_QN1 +M0%A)4F"1#0MDLQOB(FF[$EX-.G-%IL"R>^D'L&QN,;DGL`$WOBX/M7L^N:`I +M%A988+J./SL,0JKT04D(`-+9":HAZ5*5@N@7TU!5P$XG*WDP,^]PE55\4^%; +M)1WRE<4S7W?9R-(7'D=Z`MK%P\X]4O=6TW&T=:2^8"\(D0C%K!Y#X+08([X! +MN:CD0`%FG1%H;(26[+%(1Y$6$,8K+Q19:>#NJ5>F@0!`3&*X/X-SYY,H]2`9 +M[95F\2*A.K"O19)L-((WX1C7+\,"C_O&Q3T#B89[/)-^"!.+APK^IR\D-H,Q +MP;Y6E%P#OX)G+GCB]*9G2%Z>-P<56E`'6OJ9R\GV5:0R\0SS0%EB?]$;\(K? +M(G)#G,"H6U,%NDO1/]T]UM`IG37ZW[(,_QBCF$/''KW"A(V=G@@W@-`E^_-W +M-R.XJM'S!>U_H8/-/BJ]GR;;5BY`TQ(XFX%Y=Q?#.N;8$SUGA!U['SG,(MZ< +MO9L-X(T(4TE%H.1U$[395;RQ,1'0^*_+E8C]'51T5@CO=/"BG+NX=8M6PZ=J +MZH#=U=AZ;,N"DJ!#T#@5/O%'.A]$)V4[ZF/=-B33C+IHFHXQ!#09]X]26N4Q11"G($O]S'?ST_P&^?6CP-)=``;)M?+ +MZ3,GZI1-;E.@9BU@.KI!/3G[+XW\,QO\RKBL]R'#REC_#0E:SN:"A?7[GQT? +MFQ1&I25+93T70E@?M-HYDJY&(!CB_!>)P<,YN. +MHH"<1EP]'JHG&D#,A._*]W/3/@A;,@L_N0NW^5*M[45V],^_;68V_GF], +MJ="MSOD(6K@'@<-/-[!E%QCDVTWHA`+']4U!5JK_F3_.U +M>R!DT6Z4F:Y9G3KMO`V5@/SE2&'*JD`18?T@"_RW5?>GEPN/H(J0_,UGLYUY +MPM6M6>#>X(")AJNB4J/_%ORC\FOX2;+2?P=R5"_.`G5F)4PD@H`/6K, +M%UY[_.J.QG02T)3K6ASJ70;13G6.EP)JRUG["E+`9^FP..Y.I$C\=5#LPP>. +M:IT7776=E',!QM#>;?Y([:G8%ZH]"6'[O":M?%N$CTWBX*^@-8363][.?N"A +MYP19U^X,8TAC4$OV8#]=(EUSOT`Y_3O:`Z_C'.S`2QQO_7UP+,59<4!\.X_C +M!)2F4H9J;D\_UYPV$X#VS5&/!>/L>+Z(_R96"G9)2J,W]G2-#;]B48;!%.+[ +M#H`PY9#`O]#FY0E6P4!G[X&?L\-)Y9=`,2:EGK>03ZCO%317A@%Y,I6\VJJH +MV#5<<&:`7G.KOLD0M>. +M"GN1^:5+BK8,=9&1NU+A+8ZN=2FTZC2$@5/3J5JDW4E_.-[(Z.*5,X%M&.2B +M_>LTQ/(L@>IO%G2O]VAXF5D=R)JT]WQ1LNHP>+-UU'[2C+6@?K28JFI':_2^ +M,M!0*J4@VKI3U9L\H/V@9D(]1YV2:F\==Q23"PV,*J=(0?`3[.\H<(Q=UOI2 +MTTVF_(MBQ=>N;D78EN.=960%?1'RP;FKMNKSH$'T%[]BR!3S\L5& +M8D'TTTD!A@1\9_3(9M!N`5QCNJ%VN(GKYK57YO70.]H[?2[XJ?>,FTENF:!W +ML:&[:E8E7B-70,W54\6+37TL:S$4WJP,M-$.[HS=;[:S0N4)+B3". +MWU*1Q]48OM.!8]7*PPT9M``F84D^%&"M352>U(M6.!#E5_V*T?MY^XY9V]-V +M4="E.(LTG]ABY*3MN`AZ?;5AQZOZAIXU,D]19D@BBIQM:.IVNM+@$<'Q5CV_ +M;+3SM&3877WTML/#5=N]D"`:QNY#O5+F#=*$V*^8`AR-DY:[FT8>UOA+:X'!VUK8ES23Y_10,7UAB'DQ*/@6#!*F7,5@2I@0J0. +MX0@_DI9C4$E-,_37N^'W!8A(-A+(0R2C?=I];Y[<8:M"@S-()5QZ')N`KYPQ +MS/%B3OK3L`Q-6&`IQ1!2OU!<\5!7KAJ-4:1+"2"2>8F?Q-:'"_G;D^Q?X3KS^0Y +M^QO'E.H1XS>X3'SVZ;1\IN[J?^T,MKS_'KO->#9M_M`:I;_^_MH&")7-%&):P%<`MLZC6-FH2Z>T@W[\2@\__'YX#-KR], +M)%@%3_]29?*@]-.[-I<9^[3=D!^JI:S-__CZG#FH'HU!W?#N\Q&O_= +M$!_L1?>4WB(Y*^PV">CGONWUA$&T[L\<,G*BT&GK&?T0G#+WN]'#LI01B +M?@[S*J/[D$F!C_8`CU47J9\%`3=6>BR&"61K:2Y^#;N,PIE@.<4;81# +M<'LN6H,_ULVI7]KF)]"7("7/*1,T(IM_VEC!]1\Q`\6)LXTO$JZ;KJHQ.C4D +M5?L*`&@)!5F,.GD((TL+N,T]!@A2EZ6$H!N`AP01RS!2(2)J7U\/4S!CC&XZ +MV:/FO,Z^^+6LUQD?@\+T>;(3/ +MW%3.#V,*W7AA2C!M:9:D1G#EQ6XZ'UHQ.'1+II?@$ZS<+.>S@9'?KY9K54#X +M7:HH*BHE+%[)R``<\O7&XO'D"1O,Z#O%E>T+FGX#9*SA!%EJ$U2HV-QAO$M) +MV__:DM3^/G43`33V'.E7I*[!'PC=2[,H^]C%'E8^76XKW4@0-P,?W1\U>_J* +MMJ-4I@0/P[P`Y]2):)]"@[:>_I(A-",```"_B&?VJ?_4NIQTX)`Q```````` +M`````P````"R@1(_%#`'`.U!``!T97-T9&ERP`BR@1(_LX$2/YN==."0-@`` +M``````````,`````MX$2/Q0P#`#M00``=&5S=&5M<'1Y9&ER@`BW@1(_N8$2 +5/RRE>PY`%`!/(RA<`P`````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_noeof.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_noeof.rar.uu new file mode 100644 index 0000000..7cf88e7 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_noeof.rar.uu @@ -0,0 +1,5 @@ +begin 644 - +M4F%R(1H'`,^0%0P +M/&L'[WB2!U7<*?4L4NOOUTT.SR!`I\R[_P1F=02HR>'QX8'^2HV&5JV`]-KQ +MI+1)$DI5RKBB(D_C'\_+]51?<,M@,F]PE+VS +M]2/>+LTL^)KUF2N[8ZO?.RN>$#S?0H]0YSYGBDJB]E^_&DDB:%;!B8J8GW*J +MO9*/%:M1X$FFP^&O`[RU:XM%UY]0#EF9\,:3">!<)ETSY)F5GC:.-&AY:MMY +M?U9WS&?(9@3"\/]9=PU??)T!9PR=N(\&#=,WX8AKH;:/SKE13]KR`RMXSC6_ +M^IXE6RJ:_VX+-U:3J`1R_HK<>S2[KP=XHKKNY&^5,X`_EJ,Q%SP[P=:;DP!V +M0!/%2"66A!1(2(+-#&]E)ZM83H-(N9*;>3I['T&=*&8?"1L$%$;3I6]YGM7D +MA@WYC]Y1YC(KRNJ.,K9ISE/HX0L[5W!@N8&,/@KJA3[(SRV0;9*#>[IC8&(O\6E?P5CO+^4Q.EB +M@5_+,2,=*PW'V6\5:'`GU$42X'+ML^24T+V!U"[7`*WU5Q]A$I;.G*JG3N>M +M(\%C1N33':_HHW*]Y@\[G\VP2BSYTEQL1Z8P$U-TE)M#',SS=QF:;,%!X>FAS*\$LTE:N;-E6JH>UCSZ1^*'21$RTA7<71W\*'6M7UH/$P-#82?]^*:&%&S?D\9SP=W8 +M=U"D#*O8TJ'PI?QPA5Y[1`3&LES]V4]=\A6GM]#HQ+($<>?RFPOA_\/#^3H) +M9M3;PAY%/JU7%9Y??]05JHLVQ:NH:N_*K(KT^-\AHXKO`8\.G#76!Y?X:87E +MA&>X_XI=4RLM_#NXEY+K_W!;ZRW]"9D4GN7+!"*$"@E$<G,@,C`8B[OV4TA+G:`EC40T>@O"IY@;Y\2/JDD=V1M![(CNP(_,E2-0U^CX,9BJE=-CP^H-4\+4& +MD]^J`VAH[`_"EO\Y>#/O3GZ<`Z:6=C5[_!MCXBCD:8T=_894T$+.WU/1Y`8*W?RV7BIE:8CE&#G* +MKAR=I-M!\(2SH1`)U-_43!QP@2?TY36!`,FTEU"+G+UR\DX'0Z_/'SUZY'L\ +M<0WB\\&R.5`B`PTC#+4,\88"E0R2=P3'KS7/-:4F*.?&)JJ,1Z$$E`D\_G]: +MV`NESW?*QT"[,@OLIS&%#DX>O6[@;#9Z`ZT%+:?63G07XHA.O=(S8L_LA_@> +M\]+1T#1TE;]'*1$!&)GM0DS/_Q)^T>D@@/DD!>X+:`L4GV%@V((T>B"H_:6L +M;'9EB0&Z^8*/S-%;`K&EHFW1R0IJ1>OW_*'\4"G9B!S)($G=ZU?\%SA7*9M^EL80./SNR$4)E*K:0!TT,*59F65;WNQYN2Q.Z,L"-H?=(U3A>/=1R/Y!KMGFG!/%DY8V50XA+>J82,Z"D#JFCD'!XZBB48\M\!4L<-&XPOV&.MBD.".V.?&$P1P4SEWX]XVYY +M/DM9NEM8RJBP@JX`MF#PDC*4T$Z1ZZ%(V_XY#NX1+B8%\ZL>P(`W9GWOQR7: +M

    +8<3CD!K`P6["#A8H,+&2R38"$I3JG>X/>XN:(7?G\R3GA;7`/=)[X,@S +MH"RE$#HVN0_>N!D3^9IE^DGBJ9V+YJM@YIK6_%4=OUV8U!^^(JX8"/)T`5%& +MTDD1HCVQQU=MDJ7]J/"5:Z4Q!0D@T'X=<[2(L_>PSMH*)HHVI-L$?3^",O.& +MT)16KLM`NPY``"J9YM+&Y^@'!?(+IPXR-`84ADYF:`&7!(*#Q@Z]BBE@.1:A^OSG:9$M^[];\N@Q3(X+W +MLW3&;=A2([8<"3P>I95^!NIMJE^YJ5&S6(J`/T!2S-,' +MD6)@'GHT\L_2HV$04ZU\SOE')DN?ASL1NN^^7:V<[)Y\I*EYV;0WS5FYD3!6KRFYFE5CFI??*J +M-\ZJE,,<%,A9'!"O8)6/WUW=W@R<[=$$<1D1#G@4N:YEA(!4?2'_\H4)K'I` +MKQX_T=8OD1V$QU'F.652T;$^E!V!\%GRF>6J@J%#FTW+I/CY_;U,E7%R2F"W:/F]OY +MT`W/7T#4Z=_;LS/5@2B`\A(2,WZSA?974DF3$<^RA?!ACA!^T/=BR4X+!8F3 +M^V075'/DF0UX9\E0VYNLUQJ.-$%SA9?S +M?8%ZQ#'_7KP%^D[YB#`YBS9'R-1]I1"2N1X`F!NO\Y +MU2FW]K[:,QOI# +M>G6&B3`V%ZV1>]#E':8;?F6OG8V^TQV;15_5-.W1-`CK,=C))^_Q_AF]F.H1 +MSAN"WK^*@1VTQ-&^[`74F:5-]?1;2U:NB`W][#)$@S:G:#QRQ9<)?V;4ZD7! +M-M(9_<.&X+E3&KHS/ZT,"@J!4[HEGW.#\NPS=&7V&Z>>=?0"-TW"#E7/V3CW +M_*1@*VI;B@^?21EF6?.^)_UN@CL82I]HIT<;:R<>@2+;+#RMMY6I*/U]FZGQ +MINO=(L/3*#_E5U3,F\8F_^)ZI`^%#0TR`*7(=M'GAH1Z&W%%SMK%$S(`QE,* +M^6?.6MVVEA^H`Y>:`Z^<*,$Q<"02QX)QTZ;O9%YPH;K('*2`L;>F?*ZC0C^Z=G4^9(Z)%V9Q"G7_SY +M3!5I`B]/7H@7U]O`LQK!E,?3E$805$)KX47&Q-WX3RB7XV?S87X*S5;_:NQM +M5*7B3"56.2*M9KX!S[ZZR'YP-%++:"-V8:N'\Y%8HAP+$#WA*[C(+H9/)APU +M4E2Z:^Y:R%Z^]Z3`7?QMK@75!*C8YQ^2P+0'?Q"%Y#R%#PY?T$G""_TAOMOQHP89`J)7F\@W+<_BQ/#K!1_L +MAG]AD:E2F-"8]9EGWWO2_;$9R'?7$LL^Y]2H60AX..N#3IS1:;`LGOI![!L;C&Y)[`!-[XN#[5[/KF@*1866&"ZCC\[ +M#$*J]$%)"`#2V0FJ(>E2E8+H%]-05@+:Q0^"T&".^`;FHY$`!9IT1 +M:&R$ENRQ2$>1%A#&*R\466G@[JE7IH$`0$QBN#^#<^>3*/4@&>V59O$BH3JP +MKT62;#2"-^$8UR_#`H_[QL4]`XF&>SR3?@@3BX<*_JGC<'%5I0!UKZF7<7PSKFV!,]9X0=>Q\YS"+>G+V;#>"-"%-) +M1:#D=1.TV56\L3$1T/BORY6(_1U4=%8([W3PHIR[N'6+5L.G:NJ`W=78>FS+ +MG)>MXH:?N@U`&MJQ/P!F)D8/IFOA`*`51"H5&SFB:@@E2%,G)!O<[(BW%`Z+ +MFD5DG@I*@0]`X%3[Q1SH?1"=E.^ICW38DTXRZ7,1T=&6/("@U*2!7J)J.,00 +MT&7*=+9DO<0Z3W$.49(DMD':OZV[$'2VB+GR@7\@71JU(9?8F*!<3)&)*)@) +M8"[%UCD/\7O>/4EKE,440IR!+_!)AH")KL8J\Y1[0_LR4`I@JMCEH'M%T)8'[3: +M.7`6S#1:?%1#*>54`%8Z2P4#]S%B&_V61"Y,)("&PB4(`.?[C%?-J(?!-P_V +MKA:8H"G!Q2H].,.F'`T0J5+ZRVZ85AWI*N1B`8XOP7B<'#.;CJ*`G$9U%=O3/OVUF-OYYO3*G0K<[Y"%JX +M!X'#3S>P91<8Y-M-Z(0"Q_5-057,XS7*28Y')2*J7JJ_YD_SM7L@9-%NE)FN +M69TZ[;P-E8#\Y4AARJI`$6'](`O\MU7WIY<+CZ"*D/S-9[.=><+5K5G@WN"` +MB8:KHE*C_Q;\H_)G++W<[U"$K08NWP\U=SCFS"-;X;)SD4^*G#,CA('):_*S +M3*`"[MN"U\78A]Y^<=^7K^$FRTG\'>_SJCL9T +M$M"4ZUHJ/0EA^[PFK7Q;A(]-XN"OH#6$UD_>SG[@H><$6=?N#&-( +M8U!+]F`_72)=<[]`.?T[V@.OXQSLP$L<;_U]<"S%67%`?#N/XP24IE*&:FY/ +M/]><-A.`]LU1CP7C['B^B/\F5@IV24JC-_9TC0V_8E&&P13B^PZ`,.60P+_0 +MYN4)5L%`9^^!G[/#2>670#$FI9ZWD$^H[Q4T5X8!>3*5O-JJJ-@U7'!G(I[[ +M1".^J"/]&L'`?EZ/V4Y=41%=ZW]WF@%YSJW-2(I?"GK[)$+7C@I[D?FE2XJV +M#'61D;M2X2V.KG4IM.HTA(%3TZE:I-U)?SC>R.CBE3.!;1CDHOWK-,3R+('J +M;Q9TK_=H>)E9'=DFIO'7<4DPL-C"JG2$'P$^SO*'",7=;Z4M--IOR+8L77 +MKFY%V);CG'\H4(:WG65D!7T1\L&YJ[;J\Z!!]!>_8L@4\_+%1F)!]--)`88$ +M?&?TR&;0;@%<8[JA=KB)Z^:U5^;UT#O:.WTN^*GWC)M);IF@=[&ANVG)0HN6 +MWI6)5XC5T#-U5/%BTU]+&LQ%-ZL#+31#NZ,W6^VLT+E"2XDPCM]2D?N.6=O3=E'0I3B+-)_8 +M8N2D[;@(>GVU8<>K^H:>-3)/469((HJ<;6CJ=KK2X!'!\58]OVRT\[1DV%U] +M]+;#PU7;O9`@&L;N0[U2Y@W2A-BOF`(W&&K0H,S2"5<>AR;@*^<,IOOFQ!U'L7^$Z\_D.?L;QY3J$>,W +MN$Q\]NFT?*;NZG_M#+:\_QZ[S7@V;?[0&J6__G*)]4W)`\_0^XZ/R3:#K@K6 +M:\'O[:!@B5S11B6L!7`+;.HUC9J$NGM(-^_$H//_Q^>`S:\O3"18!4__4F7R +MH')EA?'O33NS:7&?NTW9`?JJ6LS?_X^IPYJ!Z-0=WP[O,1K_W1`?[$7WE-XB +M.2OL-@GHY[[M]81'*WAM.[/'#)RHM!IZQG]$)PR][O1P[*4$8GX.\RJC^Y!) +M@8_V`(]5%ZF?!0$W5GHLA@ED:VDN?@V[C,*97#R42-NTMYJN?T'&^9*DHBGS +MW7<>Q=B%,(O&;%V222=;"N<4?;@TEI_N7=;L5%TK7H#G%&V$0W![+EJ#/];- +MJ5_:YB?0ER`ESRD3-"*;?]I8P?4?,0/%B;.-+Q*NFZZJ,3HU)%7["@!H"059 +MC#IY""-+"[C-/08(4I>EA*`;@(<$$AKE?.DQ,&/UQ0/K.V5HX5`-"?VMV*WQ +MP$G>?H1+KU,LQ3-+`GS.=>!$H2PGKS.OOBUK-<9'X/"]'FR$S]Q4S@]C"MUX +M84HP;6F6I$9PY<5N.A]:,3AT2Z:7X!.LW"SGLX&1WZ^6:U5`^%VJ*"HJ)2Q> +MR<@`'/+UQN+QY`D;S.@[Q97M"YI^`V2LX019:A-4J-C<8;Q+2=O_VI+4_CYU +M$P$T]ASI5Z2NP1\(W4NS*/O8Q1Y6/EUN*]U($#<#']T?-7OZBK:C5*8$#\.\ +M`.?4B6B?0H.VGOEB?`0L$[CWO0RV;PQG[]YO4([OS^KUC!*VS;,:7,B@%/B- +ML,D]E.)F'Q)BX=J>QGX66+-A([-<4XT!"502XQSFA0'$.ZXX!39$L*F)I?UU_TX"L.M-<1SPH)CSO_O +MA8MW[+D&\>VQP,&#GUYN7_]:`O*R:X7CX8Z!!BVU2QBP<531RE'BN,(?(.K$ +M_/1ZJ6?\ZWC_%H$EZBK^[><0D/]$7S^D?T.:$(4@*$_V +MZ(`````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````8``````````````````*$OPP`Q?VO4_^?______________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_______________^@$?\B__K'_I_________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_________________________________________________________Z!' +M_(O_ZQ_Z?___________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________________________________^@3`'1%0R-%\6=F]S/A7.S +M5W8"T;9`[O=G2*&IP\3W2`(833>H2:8/`,[&-M/&Y!GWK4@ +M,-D75WT2#SF#E*Z5VOR5^KBL`````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````````````>K] +M7T\[_GZN?T/^/I_GT/4O.Q?SYW0Y_K]^YZGQ].4NQT.+`?0]2.AT80FY^38M +MC-UH&0]R&?>\/3Z/1^X4ZT^!N4Z4:9*:-$CN+!,AN>Z5('3INPWS_NJT>I`Q +MEA^_#-(OO7'F?`N31Z78C35VD7F4.&08ONMK'Z/IW^>?SOHYT6)%!7H['=ZO6]0\WN9L] +M'/S_R?R[&QY8,@B&!L_=C>&?P",_X=^*>'IUO9+ +M!I_[\_Z8<@.GXJ4\>CJ)&GB\`A!8TU=.$"I:?N=I]G]/<]'-T^M!=`D`XCE8 +M!JN7'E&K`DR"8\?V]-7J,5K7UQ5'<+]FEU.;$!Z4&1SM88*"?3W?+[\X)U>A +MH^#]#>$#56&'M?;J>.KMZ57@N-):N7[XVZ;1QQ;]1WA815)8\@RDMF"/+!(/T>IU? +MWK4OKS=:NG&%]=]*GRD($O%=%K]D%*E2C([A*)0WS=*OR3)?UZJ?1?%ZO+K] +MD&B@AY_W88M'73TMN!`>QOM7_-,4)_7>&W]L&3[?T^O_CYNE>^5_+W/_:R>8 +M&Z.WI9_@C:M]"Y\/W4G'3^Z+?@@J68M.)BZ/`ETX[^-^Z"[SJSX,)F&O/0HZ +M0PV66N,;O7>B\5ZX_>#AUFU*WVI\?&E]W:O[6[?0GQJ>MOWGAI^V)\"68D>& +M2/QE?L_#D"*?D5ZV<\L]1++_QO/P@DUZM6?[Q$%DXZ$[R\N0FZ([,@15!+0L +M!=9%K?M7= +MA:YU^7TJN7R`O'VY%71U(S)-WO;4&+1*YXM.65%X90P;)CC4=H$29N95RL +MRS#O),+>/5R.$9X*^/#N=GV$-TE:7,^."D3YWR48+\6.9(7^'M%":>`)GZ4R +M:N*>"^03M8ZJ74[FGT3>#9D960OE@UX%O&6._ZNJYLCB!,W-B\[)W7['!:PB +M\'XY%V/XRP=KA./R6^X<`T;BS9D,V"+I;FS-Y?XJ$K73X^QY*R2."*'P;UJO +M7E$H&N\X@/C%[1L5_;U7SR]WCO/9):4Y?(EI+>S$%V\]''EIWE6,$>6(O@+3 +ME[G#\?");LM@E?-3?CP*;D*S(U:ON4N?E<%T8)JF54U2VJU7FD,O@Z>QJR-2 +MZ]$'[.JA1.GM]KK]*3WMIN@Q8]9=O^N=OZ0OF$'83HEE&QW&8=Q9SC&7(HZ! +MT\56]-ARZ0CWLE=RG0:U[2V)E.'_K,KXFGKD,JPH2W)[CP\?_D'<+S8C_%+] +MEF32B&FU2Y,@:1B;SG3MZD%#;'BC"9%TM*_796%NG31&MW62'&8VV7G2&W*2 +M8_"I^'X>SX96^#80^^+?/@?3A_FU&%BKB"A6'M_R+O`W;3UFK8'X@2EPRF"B +MB.C*H#7`0[(C!G>Y?E@TZ^!XL9IZ9E*Z5Q"L),WOXAO=#HS/?P^GS03$?ROO +MBVREKR,\I>K(/.)^J/,R(!][,]7T6A38[L;5*M +MPVE56+MFK`W=K>U(0(/$!VRF)'4[YX]$*QA:#)'L^(WZY)E"Q)1K^B:IO3ZK +MA@.6L6=`"_YLZ(0Y&3%,0_)L67=S;-O4#B,0'6 +M)R[=^,ZP/SWX0 +M@&.8'L81\%H:KS8?+YM;=WC9+O^/@B!''YT.F5OPU\[;]SX+9M#%'>I]%&&W +MG1`U:.-"-[8';;(*FK?I\/LS.-T9XCHO61;2M@$\`6CG'QY4.\P!GUA3?ITK0 +MCW<&SL8L,37TB/+XZ90SU^_0EB>ZOK]_1MDA*F4]:`/,ZQR;5C2@1O+7Q/$52F4OGN\/,_'+"G,R[7/2I +ML$FBRTX>+,"R`D5>')8'I&,]:7?]56WD.)^0#G"0U,68W%CE(W]/6PQ0MZ). +MEB[;?2AL.OC$%1A/+!#J/''Z]?K%@_&YC/\*V^;9#_'SSHD]N\V0$ +MIHKP^J$Y6AY=(?^EEA[BZV[/+6@$A"3V*>`XXEYGQI+%"%?@DKWC,5,9XRBG +M(DCB3:DC7,O:X1##E0=;8G*N,KDE4="68,2VHU`0SLDRPH(H$Y%RN%;TG->M +M7CEJU'K(37^^OJ7O,S+C%JL8X<2NN"?]\NON0;:O0Y^=/?!#'GEP9VO@VX(# +MO7]M?X]1HA445@;>0V`BP8$E=-_:ZTAPQIY[9A\I2Q_=L9@>&,5(2KFQQ\4* +M*J.*B+AW*?*`5[E.3JD;5XL%UE<[5R+HJ*^O*J4MBU*7)5S4_#J\_&(UO +MF-HZ@43FIH#,4-FD4T6"!9<O"/P;L9Y0\$;5>\< +M;Q]KP2?\5:G'1*;2JR2L'T?#/L4Z- +MGC21?PUWK.CGG+[7ZT8.C)'8_7G=L6D8=%L9<$O#1RM>'TQU#I3K..2U.S!< +MG1N#^&'R6-J&&N&RG5WZN95X/S(V[ +M2D03%@"S:CD[T],"*J\LOZQ]K+%H3[(9Y<^Z0#>U9D`\NU,NSZ?:N?X/3?QI*:J(L6>($A+QV[!$AQ8)46R\6"NEJ5\U?;TP3K0" +MU=5=I'H=;4U\[\8:5_?#VZO-2-P(!N,YCV/$&*U=*H256[0JSR89H)LY4XPT +M5TM\KS63+<@_!J;63WE0P!Z//K2TON'^XDKUL3+KA +MDX)KB4#CP3?2";-\^G*COB>2.&;FO5]JT=/^7\KM#RYKM7V_K5^E%>[Z/*X. +MTR*_CYZ_0DJ@8/1(I2Q7S@SD>/^WD&=5=70Y2B]C4!5^7+IL)S&C;)5@>\6# +M5ET-3EI4?=W.`GG8I@F2(!!$:V,5]4?O:'3\5?+%^M66W]%&>O!"[MZMB$/D +MRR?VZ4"2L?S$[1D#@=M95,6MKTC\C&%[XM+Y[N">&]*BY9?3`;8O;M>-B?KQDWU&&LKY +MO*7BN&Z)?.1LJ9O&\SL.%4K;C4F@!9NMF:=/8UM.OVN_[WZR2-K._^\9OGE/ +M8Z4/D)G&82NF::OD)F;4KU#B?LB_ON7)G*2`48/P@BRROKP^*$_2R0G^YH=[ +ML9>R6.]N[.33"H=?,_CT.?FQ98>3V_Y09`[MO>)F+Y9DU7KK_H\=2!=E-_'L[\&W'RYVML>6W +M2B5XVTKCM8$=QWDW7T)C=H/2`M>F>1Z.EFT89XYM6]Y`.74[6+UO9V-#+L2* +MRG?O$G&H]`_8.C5?AT",*;PS'GFM70XN>WV4Q427^(`*\/X#CB^ +M$(`_Z;QM?B78W;%ULSQ]SP7'831UC7'T-)1'M@\&T\A :U"^,-";S5OB:6 +MG$,M^1P8+(5[>J-K6.5*L'$0+)C=0HM;#!4F--U/NZDV&E#R0UWL[7NQTR?( +MK-5,,P+(U-G9HX8/FZ7$?96E_ZGDBWBI,:/#Y=^S;#LY:>^CB6&-NY)Y7X[_!HZ6Z,D&]`WT!%WRJ<9];OD]9 +MY>24+=]B3T1H[A.%^F.1/,DM#4>!\9]0K>"FYBN[!+*PDPZ'TMGH"-NLKU?X +MK&8!'XW9[RE.P5>/,E6Z?%N:LC`<1CX,4F<@B!KO78!YO$IQ`''Q7JO"IX\? +MBBR#]:TMSQ5EEG7D[+^G+:=BG2QFL>/BO +M-QZJZ$.H`J_PPEC.-JXBK7]T=G#'\]ON_/CN":U"TF8LK:^LVXWN3E`F6;_# +MF@\C#/D]9LWKT#%HA\3BFCW4MIP#\!5<]$0Y$=*]?;JE'.^>7#5O5WUX9)44 +M:))UM76AT?_M55^=35MH +M8SBP1JTK'D6Y=#^?WQI>=*9C8FR=6JV)]+T%__'6]A[DT)F]% +MM.9/8%$580S)=?9\16F`[F7>"]22&A^BE$`:%]89YK8LMX4\?*>YWLG)25RK +M*.K)901`V]&IJZOJ1J_6GW!LR>I^"`[07J:]@%V?5BQJ?SP/;WQ=6$)VG)G> +M,CD;"*2]BO';UTABY)#56A_?JZ>CVO<+0[/9T^Y#1S1\ +M'1BO@_7G[F+:SX]=K^LYM7V:F+!8@8VWCQE9ON?5'U;4?[#8J%5Z%VJ6=4&'1J4HO;()4E6Z9]B#F&EOGA"Y]OY\)@Z$KQP\]L>4<',^O+3P:'OZ[N0-$59`T+&V[RU6]6;[V-V/2 +M\DOQI9RJV8A[VJ&3N-FHO1'WX^C$`6&2L/DNQK)5_WUI\QDNC?X],*1X0H=% +MT;6[0R[0Y+&X>-&5*QYNCCJ;63LCPVSZ%<=8_&<$7YI5O82X$^Z<##T4I_XS;/-5[M4JN)*<.,PUX=<@21*+8?\@!8`NJL$\VJOXQXJ9_D +M3.WKH>4UTR@[R57^/8HS5-09>'[^!EC_/B&H.[#.Q3A=.O\W-$D=K*48D@J19KZ-UX@W5I(05CF6[ +M[(CXM-/'Q^C,.*&X3^7'/##8'_F>E+Z+.!7!K[5XEI)C,E`)2K9=PC^3W!*> +M/=^JWKV#J"(QKCPP6:'6E9)Y.J(:%'W-59W0K-G+@+-9/@"A""&TDQUZZ*Z!(7K==%W;K&"$J@J +MALS;75>P>"E5\-;N4E/M +M0A%P9LKU*,B)FLB7(LC%+GP-Z^OAE/&,`'46Y6\TGV,SB'PST\;25YCUTI@) +M"8'KR_&OC2FE?A7ZGV6/IWY1];IKK:><9*`-O+^*CC4T2?\3C +M_M'7BFGLD;Y)8-WV+?F70"PKR_K2?DS;!F2K#Q)U^)[$X!XV5*%UYZ=7A]'N +MJRJW(KWG&Y:)'M=LW^%%XYMC7J/SQ2BQFE=9%4H:KU#/U&Z)XW&/F1DY^*&? +MKF)^:[Y;RQ8402:`0.G!SK912WR+3;6S1-%I+>%40ZT<0YQAHQO;* +M\@_]:\Z&\O@X6JRH!7L'0]=%F\#4G+=W3O;]?@ST(*H"J*!>=9,1I"NM^<5$ +M,?M3##_F0@61;>:`LF\VDL')];&<]T56:4]2!OY.9(`/*6V>1@]'8#"*GU77 +M;#NK:^GSZ[&-$_(WYR<(5I51ZVR&>0E=MYM$UWTOV5=5'&,CR +MBKOW;AR"NES,-/?Z>M505*><)/.8)UL,A0CY:\.+IC`GC%8_TJ5_HG*`HW#K&]2WB/L(8";`73ZE8Y;1D(J@(T,=])2H!$P7 +M0R:0/B15*(]<*@J1D[43+>O$MZ$A&')!G0?"`I/RWJEW*L#<#D!I$\V:\",/ +M[J!XYT&0)B+9L6#"$>!0#V` +M*;I#]B(J/TC[I-H4P\V$J3&_7VBB^Z,]'9,8PUO5QM2^Y5?P +M1\:_.IO%T4N"#U2-1H8Z]$6"3B%^+CQZ7CM4]>!+A*F1!\CK@_PCBB3,5V$W +MFK@M_W+2%)';;*J7&Y01`W``3(_X7]KVPYX0A2`H3^W1```````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````%`2_#`#%_:]3_Y________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________________________________________________________Z` +M1_R+_^L?^G__________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M________________________________________H$S/],17/Z59'_P````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````(``````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````'!,`9$53(T7Q5F;[,_%5R8N9`6#;(',YDX1 +M0Q.'4\P@"&$PSB$FF#V!OD8VT]MR#/_42!R0!DOIUT[>VQ[89(N+GPD'O6]7 +M5U=W5U===[_)5Z$7E>5T:I72NUXE?QTE8``````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````!ZOS?3SO^?JY_0_ +MX^G^?0]2\[%_/G=#G^OW[GJ?'TY2['0XL!]#U(Z'1A";GY-BV,W6@9#W(9][ +MP]/H]'[A3K3X&Y3I1IDIHT2.XL$R&Y[I4@=.F[#?/^ZK1ZD#&6'[\,TB^]<> +M9\"Y-'I=B--7:1>90X9!B^ZVMRLSBZ9H3>*UL(X9WO3T;88(NBWJ;FWYMCU: +M_`%SO[.K)IJ?V@]X?H^G?YY_.^CG18D4%>CL=WJ];U#S>YFST<_/_)_+L;'E +M@R"(8&S]S/W[H'VO3[-G[XE?]16`H7C7$6F?`7.ERJ_\NC3.&L[XU<8.@9'& +ML'1%!-IUL?&T8$DS.,.S_X.*MFY1YV-X9_`(S_AWXIX>G6]DL&G_OS_IAR`Z +M?BI3QZ.HD:>+P"$%C35TX0*EI^YVGV?T]ST4:L"3( +M)CQ_;TU>HQ6M?7%4=POV:74YL0'I09'.UA@H)]/=\OOS@G5Z&CX/T-X0-588 +M>U]NIXZNWI5>"XTEJY?OC;IM''%S(ZHSSRMS1_9,TNG9F9*F04#YUGBD(U/- +M>&+/_<==8H-%>N,41#3C!FNWYH_9"0.>;IUU'VT]?W7S>YV]+1\&G+.*[KK$ +M#3UQL@WJ0$J6U([]?U5-)YOU'>%A%4ECR#*2V8(\L$@_1ZG5_>M2^O-UJZ<8 +M7UWTJ?*0@2\5T6OV04J5*,CN$HE#?-TJ_),E_7JI]%\7J\NOV0:*"'G_=ABT +M==/2VX$![&^U?\TQ0G]=X;?VP9/M_3Z_^/FZ5[Y7\O<_]K)Y@;H[>EG^"-JW +MT+GP_=2<=/[HM^""I9BTXF+H\"73COXW[H+O.K/@PF8:\]"CI##99:XQN]=Z +M+Q7KC]X.'6;4K?:GQ\:7W=J_M;M]"?&IZV_>>&G[8GP)9B1X9(_&5^S\.0(I +M^17K9SRSU$LO_&\_""37JU9_O$063CH3O+RY";HCLR!%4$M"P%R2C.-H4T+? +MC(5%67(4L1#KH$O:A2=CZ)I=,W#/<=T<&R;OD^+GR7]R>;S\[^F=SHQ[7Y?2JY +M?("\?;D5='4C,DW>]M08M$KGBTY947AE#!LF.-1V@1)FYE7*S+,.\DPMX]7( +MX1G@KX\.YV?80W25IT4)IX`F?I3)JXIX+Y!.UCJ +MI=3N:?1-X-R+CMH^S0QQ>.!3VST>W\OZO1/ARI:U0G<^O;3?@AFLT3F^I]O8 +MV(QKO1N<6+Q&9-K=QA#.ND9M!7LK*_-MU6##8]^H@N)@J;S3BOVQ,LPCG>58 +M2+:*V35;YCEAI24B(J0M\Y2JU<8P+_FJF;]*S-YF1E9"^6#7@6\98[_JZKFR.($S42@:[SB`^, +M7M&Q7]O5?/+W>.\]DEI3E\B6DM[,07;ST<>6G>58P1Y8B^`M.7N:0R^#I[&K(U+KT0?LZJ%$Z> +MWVNOTI/>VFZ#%CUEV_ZYV_I"^80=A.B64;'<9AW%G.,9R5W*=!K7M+8F4X?^LROB:>N0RK"A+*,)D72TK]=E86Z=-$:W=9(<9C;9>=(;W_(N\#=M/6:M@?B!*7#*8**(Z,J@-_B&]T.C,]_#Z?-!,1_*^^+;*6O(SREZL +M@\XGZH\S(@'WLQS%ONS2;9EI`:]'J]Q($R)P>2I_(_!G;?HH[593:IE9]G0N +M7S-](4?7E>^>4@I>78H-U)&4K?"-R8TN"?![U?1:%-CNQM4JW#:558NV:L#= +MVM[4A`@\0';*8D=3OGCT0K&%H,D>SXC?KDF4+$E&OZ)JF]/JN&`Y9RTDR+%8 +M]^*4''I8+H\7)5ZQ9T`+_FSHA#D9,4Q#\FQ9=W-LV]0.(Q`=9P_H\#:E^/YF +M=;M#E_.?M8*%`9].H%QA'P6A +MJO-A\OFUMW>-DN_X^"($=$#5HXT(WM@ +M=ML@J:M^GP]S@I5F3)6[EI$<8?3D9#S8$P;-.DD>1K$W7P;>-/K4K#]U>BD`I:`94LW0A136V-35Q0\D*D4T-.9G4K\]6 +MS1LQRXX;IZS,XW1GB.B]9%M*V`3P!:.[P\S\D8SUI=_U5;>0XGY`.<)#4Q9C<6.4C?T];#%"WHDZ6+MM]*&PZ^, +M05&$\L$.H\(J=%/63*%6059 +MI5S;NN4@+*&;)3H3XYQ[U^L6#\;F,_PK;YMD/\?/.B3V[S9`2FBO#ZH3E:'E +MTA_Z66'N+K;L\M:`2$)/8IX#CB7F?&DL4(5^"2O>,Q4QGC**.6K4>LA-?[ +MZ^I>\S,N,6JQCAQ*ZX)_WRZ^Y!MJ]#GYT]\$,>>7!G:^#;@@.]?VU_CU&B%1 +M16!MY#8"+!@25TW]KK2'#&GGMF'RE+']VQF!X8Q4A*N;''Q0HJHXJ(N'9O^=R)+AZ\(_!NQGE#P1M5[QQO'VO!)_Q5IR +M'1JT;BWYEV@ON#"YHZ%6D3QO2/EJIZ<=$IM*K)*P?1\,^Q3HV>-)%_#7>LZ. +M>=VQ:1AT6QEP2\-'*UX?3'4.E.LXY+4[,%R=&X/X8?)8VH +M8:YR2\>?]/](B1SKD^/_1!`&*R=_?9X;*=7?JYE7@_,C;M*1!,6`+-J.3 +MO3TP(JKRR_K'VLL6A/LAGES[I`-[5F0#R[5R,D'<'5V7FO&[/DNM65XR[/I] +MJY_@]-_&DIJHBQ9X@2$O';L$2'%@E1;+Q8*Z6I7S5]O3!.M`+5U5VD>AUM37 +MSOQAI7]\/;J\U(W`@&XSF/8\08K5TJA)5;M"K/)AF@FSE3C#172WRO-9P%3( +M%W9*KVMY,MR#\&IM9/>5#`'H\^M+2^X?[B2O6Q,MS7E0A;A2;>E]NW%CUQV. +M7+EER,>/:W=G;V*-1B.2,#MO`)O[>S@U]+2[-66W]:PCNAZN&3@FN)0./!-] +M()LWSZ09U5U=#E*+V-0%7Y=BF"9(@$$1K8Q7U1^]H=/Q5\L7ZU9;?T49Z\$+NWJV(0^3+)_;I0)*Q_, +M3M&0.!VUE4Q:VO2/R,87OBTOGNX)X;TJ+EE],!MB]NUR,[$M7-\<\+Y#,;N]_M1K)GI77QKEBYM>4MI;7+,J#B?E7"&?@C-PLV15)1(A)GD)$8@P.MK)YXV)^O&3?48:ROF\I>*X;HE\Y& +MRIF\;S.PX52MN-2:`%FZV9IT]C6TZ_:[_O?K)(VL[_[QF^>4]CI0^0F<9A*Z +M9IJ^0F9M2O4.)^R+^^YNO^CQU(%V4W]RLQE88IE2.BPQ +MAKV,CR\8MSJNU7777A5*'O2[F\\/>IT9MX>SOP;3=?0F-V@]("UZ9Y'HZ6;1AGCFU;WD`Y=3M8O6]G8T,NQ(K*=^\2<:CT#] +M@Z-5^'0(PIO#,>>:U=#BY[?93%1)?X@`KQRVC3SHS%X_@..+X0@#_IO&U^)= +MC=L76S/'W/!<=A-'6-V#P;3R$8-EK4+XPT)O-6^)I:<0RWY'!@LA7 +MMZHVM8Y4JP<1`LF-U"BUL,%28TW4^[J38:4/)#7>SM>['3)\BLU4PS`LC4V= +MFCA@^;I<1]E:7_J>2+>*DQH\/EW[-S9EQ.TXS="/O>]BNW50:/>O+OQ.-JE0 +M`3%YL.SEI[Z.)88V[DGE?CO\&CI;HR0;T#?0$7?*IQGUN^3UGEY)0MWV)/1& +MCN$X7Z8Y$\R2T-1X'QGU"MX*;F*[L$LK"3#H?2V>@(VZRO5_BL9@$?C=GO*4 +M[!5X\R5;I\6YJR,!Q&/@Q29R"(&N]=@'F\2G$`J\*GCQ^*+(/UK2W/%6 +M65P'F=(FR7*_.?DKCM)DEZ=>3LOZY.4"99O\.:#R,,^3UFS> +MO0,6B'Q.*:/=2VG`/P%5ST1#D1TKU]NJ4<[YY<-6]7?7ADE11HDG6U=:'1_^ +MUS+C>IC^`2INA63>GEDM8_P[N/1; +MET/Y_?&EYTIF-B;)U:K8GTO05S`3*R`L,0%2$9*[SBV? +M!*ZO]N9R/A+ZMG>$V;_'R[?U7HS-EWC#[[MO:ULV2U+.DLLTV""@#FZ,$'.G +M=,/;L0_9^'0IV%K/Y0/%:^#FQRKI;\V#@V][_\=;V'N30F;T6TYD]@415A#, +MEU]GQ%:8#N9=X+U)(:'Z*40!H7UAGFMBRWA3Q\I[G>RIKV`79]6+&I_/`]O?%U80G:GB,BX@'\MT1.ND3\+D9RKS%4LC94+WR+O +M#I5%G-L=8]R*!I#5.V7#`,HCNP2_"#-G$GE4B69\7+GGUVOYNE_6D(71'WCB +M97ETLMT2"Y6BK*)9>L3>+.]%KG4)T^(G\+`A$[K'-B27U"2YM;=F1'6BV4KA +MCWJ=LQ8I`^%[V*\=O72&+DD-5:']^KIZ/:]PM#L]G3[D-'-'P=&*^#]>?N8M +MK/CUVOZSFU?9J8L%B!C9S?Y<:8[6A]GMO3T.GV>C]G;[?9^OM]JK?:ZV1LB/&5F^Y +M]4?5M1_L-BH57H7:I9U08=&I2B]L@E25;IGV(.8:6^>$+ES#DK\KE=G'6IM? +M8LV;4$.OB5MK?5`!1L]O:0T$GNQTV3].>,)]:3S@E6U9KDKAPNN5+9.2::]/ +MN:/;N:;5S,+0T)\0%=/2[&AW>KU*!SK=:J,@(2N"PW%9W!KB\T>WT[3%?)+Y +M[V_GPF#H2O%R8)_`P9'B__T&"X-I_\KV0>A("_D/:L>!3(?BJ2Y"RVW7$:-= +M2G^'Z",NLI#;QDHK&K(;<;_]?;H%)^9E2*BV.C;($ZV->]'M7_KNY`T15D#0L;;O+5;U9OO8W8]+R2_&EG*K9B' +MO:H9.XV:B]$??CZ,0!89*P^2[&LE7_?6GS&2Z-_CTPI'A"AT71M;M#+M#DL; +MAXT94K'FZ..IMS?4VM*[>-&8[B#UHSF.2)!7WRJLA$AJR#L;>/NJS\*9\JXP +M4:2'U)]W2EC2#[BP9%1GY)R*=CJ]/^^G"CHO5AO,[W4Z1*BZ?=]P.]V]/V3[.[H>Q='K>Z?5NF;D>W\K)STYV/HOPQOZDH@[MU;7`DDVF=L1+MBC0[>WK2J%+` +M!PK6QT>.I+5Z?'8Y5R\-6]78Y]K9`\U^8BL-RIT=/P)W=MUW`<`+7@7.J_M% +M?&GL*GT`9Y9.R/#;/H5QUC\9P1?FE6]A+@3[IP,/12G_AS*3.>)L-E>+_%NQ +M=[-L\U7NU2JXDIPXS#7AUR!)$HMA_R`%@"ZJP3S:J_C'BIG^1,[>NAY373*# +MO)5?X]BC-4U!EX?OX&6/\^(:@[L,[%.%TZ_QP]`!V<@\;EL@[&7&E +MD&AW(BSGW*'RLG2C+__M/40````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````?^TO(_HQ?VO4_^?__________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M___________^@$?\B__K'_I_____________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_____________________________________________________Z!'_(O_ +MZQ_Z?_______________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________________________________^@1_R+_^L?^G______________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M________________H$?\B__K'_I_________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_____________________________________________]"'A_UBY2R"4]W" +ML*RE:_OGG3#+\L@,>,PN7D[&4009/5G@?.;JM:BXCPHCK]VV[!W!8P +MYAI3ZHH(AMZ-VR@&&VJ'#SQX0QE)?R4N3VT'614`IIGL^R($79%MI#B-X4CY +M2<,-?%!I-[HQ#M]PYYZ?6SOAM+5LW +MF&<#GI93057E-9"T'5(%972#)X_X&MZ%%>,"#R0K[^%DUAQ_L=6WC_=;3^$B&IX@7 +M6#\FJ!/@DO,_:Q4&@$=1%+9L9'QX-`*25C]4+S1EM<'\+&/@+SZ!Z;8S%PZ; +M(==I$41B7WFK6VK3@'SRI+W`+B[X)G@4O0_W,7;CI_)#=I9$>48_/@*[!9_P6E;Z30VBMPXWC4A +MRUON:T2OHRGTI6-N1.9O4Q7!K2]V<9LB\ZOK`;O-+6./K\O;V>YL3U0;<@G] +MLA2,Q)]X^--?L#,";:,7QJQN4A;W5Z;,Q7 +M)^5/T,L?'O%IN1VBJHSYE"_F##3P-7AKO2*<+FA"Q7SX?[-K1*!"L]\N9+:. +M0,0/+O.NFOO8/98)R4T.=YUS'P05OYLC5UIA3#;.%]R3H86ZW$_$0R7#/%`, +MXN35/Z7_EIY(DISE:VN1+&?5:$\/OB?_.UY_;YHU]1>KOO^1>SO&=^G!C.=( +MELO]V=4)15`MSI")D`+9IQ_M4>U*+:4'_Z>[O6X((_Q"?<;ZJ5$<+9V6$EU40\:$&L%"BJB(8<0I[G_ +M!\`J./DJ`+W_1/'D9-O>\"'>)A+>%(A^RMG>^['D=3[P%6?=^<0A-E2XHAZ& +MM=M"/D&+NG;>+:_<_&(J-_X/$>`%(*^FHJEU.9*6OP.!?U:YX0_DSJ)4K>;9 +M<`K%R=FAF@5??,.T'?Q$9N9;%S:]GTXV!-OLL]NJ;\1'O+T/NS/BRH>?$*/D +M[P!,C_A?VNV'/"$*0%"?VZ(````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````````H!+\,`, +M7]KU/_G_____________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_____________________________________H!'_(O_ZQ_Z?___________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________________^@1_R+_^L?^G______________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +MH$P!T14,C1?%G9O?$J_A%^K]7@Y2NE= +MK\E:7/38```````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````'J_/Z>=_S]7/Z'_'T_SZ'J7G8OY\[H<_U^_<]3 +MX^G*78Z'%@/H>I'0Z,(3<_)L6QFZT#(>Y#/O>'I]'H_<*=:?`W*=*-,E-&B1 +MW%@F0W/=*D#ITW8;Y_W5:/4@8RP_?AFD7WKCS/@7)H]+L1IJ[2+S*'#(,7W6 +MUN5F<73-";Q6MA'#.]Z>C;#!%T6]3K7X`N=_9U9--3^T'O#]'T[_// +MYWTH>;W,V>CGY_Y/Y=C8\L&01#`V?N9^_=`^UZ?9L_?$K +M_J*P%"\:XBTSX"YTN57_ET:9PUG?&KC!T#(XU@Z(H)M.MCXVC`DF9QAV?_!Q +M5LW*/.QO#/X!&?\._%/#TZWLE@T_]^?],.0'3\5*>/1U$C3Q>`0@L::NG"!4 +MM/W.T^S^GN>CFZ?6@N@2`<1RL`U7+CRC5@29!,>/[>FKU&*UKZXJCN%^S2ZG +M-B`]*#(YVL,%!/I[OE]^<$ZO0T?!^AO"!JK##VOMU/'5V]*KP7&DM7+]\;=- +MHXXN9'5&>>5N:/[)FET[,S)4R"@?.L\4A&IYKPQ9_[CKK%!HKUQBB(:<8,UV +M_-'[(2!SS=.NH^VGK^Z^;W.WI:/@TY9Q7==8@:>N-D&]2`E2VI'?K^JII/-^ +MH[PL(JDL>0926S!'E@D'Z/4ZO[UJ7UYNM73C"^N^E3Y2$"7BNBU^R"E2I1D= +MPE$H;YNE7Y)DOZ]5/HOB]7EU^R#100\_[L,6CKIZ6W`@/8WVK_FF*$_KO#;^ +MV#)]OZ?7_Q\W2O?*_E[G_M9/,#=';TL_P1M6^A<^'[J3CI_=%OP05+,6G$Q= +M'@2Z<=_&_=!=YU9\&$S#7GH4=(8;++7&-WKO1>*]6>HEE_XWGX02:]6K/ +M]XB"R<="=Y>7(3=$=F0(J@EH6`N249QM"FA;\9"HJRY"EB(==`E[4*3L?1-+ +MIFX9[CNC@V3=\GQ;DZ96QH>C%MN4HE9"R03,]B.#?5\%/.LBUOVKNPM[@^$)19E-9HX1W=F7.%0/S:+=WTNW +MQ[?%D&'W%BA>CT^2_N3S>?G?TSN=&/:_+Z57+Y`7C[V>CV_E_5Z)\.5+6J$[GU[:;\$,UFB(S)M;N,(9UTC- +MH*]E97YMNJP8;'OU$%Q,%3>:<5^V)EF$<[RK"1;16R:K?,=D[K]C@M81>#\<0'QB]HV*_MZKYY>[QWGLDM*>CCRT[RK&"/+$7P%IR]SA^/A$MV6P2OFIOQX%-R%9D:M7W*7/RN" +MZ,$U3*J:I;5:KS2&7P=/8U9&I=>B#]G50HG3V^UU^E)[VTW08L>LNW_7.W]( +M7S"#L)T2RC8[C,.XLYQC+D4=`Z>*K>FPY=(1[V2NY3H-:]I;$RG#_UF5\33U +MR&584);D]QX>/_R#N%YL1_BE^RS)I1#3:I4O5D'G$_5'F9$`^]F.8M]V:3;,M +M(#7H]7N)`F1.#R5/Y'X,[;]%':K*;5,K/LZ%R^9OI"CZ\KWSRD%+R[%!NI(R +ME;X1N3&EP3X/>KZ+0IL=V-JE6X;2JK%VS5@;NUO:D($'B`[93$CJ=\\>B%8P +MM!DCV?$;]4' +MS=++['9N4X&O$Y=N_&=8'Y[\(0#',#V,(^"T-5YL/E\VMN[QLEW_'P1`CC\Z +M'3*WX:^=M^Y\%LVABCO4^BC#;SH@:M'&A&]L#MMD%35OT^'N<%*LR9*W;`F#9ITDCR-8FZ^#;QI[C]X%!XD7Y#F]CJC'^^0,;#OR,[U:E8?NK +MT4@%+0#*EFZ$**:VQJ:N*'DA4BFAIS,ZE?GJV:-F.7'#=/69G&Z,\1T7K(MI +M6P">`+1SCX\J'>8`SZPIOTZ5H1[N#9V,6&)KZ1'E\=,H9Z_?H2Q/=7U^_HVR +M0E3*>M`'F=8Y-JQI0(WEN3^?%=([E;=GW/@>2I!>_FP<`^U''F?CEA3F9=KGI4V"319:M+O^JK;R'$_ +M(!SA(:F+,;BQRD;^GK88H6]$G2Q=MOI0V'7QB"HPGE@AU'CC].==>OD5NHF7 +MYD$TK.H`)PSKM<"9?\@G+5NJ#,ME=_'G!"YSD;<;AE$;_G@T,]N:6](`V=`F +MY?E-&*;K4-JT%2M\YU[BC:3Q%3HIZR90JR"K-*N;=URD!90S9*="?'./>OUB +MP?CW>;("4T5X?5"HT0J**P-O(;`18,"2NF_M=:0X8T\ +M]LP^4I8_NV,P/#&*D)5S8X^*%%5'%1%P[E/E`*]RG)U2-J\6"ZRN=JY%T5%? +M#!JWE5*6Q:E+DJYJ?AU>?C$:WS&T=0*)S4T!F*&S2*:+!`LN.<4D3H<7&1^; +MS-_SN1)"-JO>.-X^UX)/^*M.0Z-6C<6_,NT%]P87-'0JTB>- +MZ1\M5/3CHE-I59)6#Z/AGV*=&SQI(OX:[UG1SSE]K]:,'1DCL?KSNV+2,.BV +M,N"7AHY6O#Z8ZATIUG'):G9@N3HW!_##Y+&U##7.27CS_I_I$2.=F!%5>67]8^UEBT)]D,\N? +M=(!O:LR`>7:N1D@[@ZNR\UXW9\EUJRO&79]/M7/\'IOXTE-5$6+/$"0EX[=@ +MB0XL$J+9>+!72U*^:OMZ8)UH!:NJNTCT.MJ:^=^,-*_OA[=7FI&X$`W&UO)EN0?@U-K)[RH8`] +M'GUI:7W#_<25ZV)EN:\J$+<*3;TOMVXL>N.QRYQ1J,1R1@=M +MX!-_;V<&OI:79JRV_K6$=T/5PR<$UQ*!QX)OI!-F^?3E1WQ/)'#-S7J^U:.G +M_+^5VAYQJ`J_+ETV$YC1MDJP/>+!JRZ&IRTJ/N[G`3SL4P3)$`@B-;&*^J/WM#I +M^*OEB_6K+;^BC/7@A=V]6Q"'R99/[=*!)6/YB=HR!P.VLJF+6UZ1^1C"]\6E +M\]W!/#>E1!7CZ9V'"J5MQJ30`LW6S-. +MGL:VG7[7?][]9)&UG?_>,WSRGL=*'R$SC,)73--7R$S-J5ZAQ/V1?WW+DSE) +M`*,'X01997UX?%"?I9(3_W=G)IA4.OF?QZ'/S8LL/)[?\H,@= +MVWO$S%\LR:KUU_T>.I`NRF_N5F,K#%,J1T6&,->QD>7C%N=5VJZZZ\*I0]Z7 +M\@'+J=K%ZWL[&AEV)%93OWB3C4>@?L'1JOPZ!&%-X9CSS6KH<7/;[ +M*8J)+_$`%>.6T:>=&8O'\!QQ?"$`?]-XVOQ+L;MBZV9X^YX+CL)HZQKCZ&DH +MCVP>#:>0C!LM:A?&&A-YJWQ-+3B&6_(X,%D*]O5&UK'*E6#B(%DQNH46MA@J +M3&FZGW=2;#2AY(:[V=KW8Z9/D5FJF&8%D:FSLT<,'S=+B/LK2_]3R1;Q4F-' +MA\N_9N;,N)VG&;H1][WL5VZJ#1[UY=^)QM4J`"8O-AV@;Z`B[Y5.,^MWR>L\O)*%N^Q)Z(T=PG"_3'(GF26AJ/`^,^H5O! +M3/Q19!^M:6YXJRRN`\SI$V2Y7YS\E<=I,DO3K +MR=E_3EM.Q3I8S6/'Q.9N*P5/7FX]5="'4`5?X82QG&U<15K^Z.SAC^>WW?GQ +MW!-:A:3,65M?6;<;W)R@3+-_AS0>1AGR>LV;UZ!BT0^)Q31[J6TX!^`JN>B( +MOMU2CG?/+AJWJ[Z\,DJ*-$DZVKK0Z/_VN9<;U,?P"5-T*R;T\LEK'^' +M=Q[C_A1[%C_@LS>&O*J_.IJVT,9Q8(U:5CR+<6SG">\*[[L0?/T?<3SX)75_MS.1\)?5L[PFS?X^7;^ +MJ]&9LN\8??=M[6MFR6I9TEEFFP04`P]R:$S>BVG,GL"B*L(9DNOL^(K3`=S+O!>I)#0_12B` +M-"^L,\UL66\*>/E/<[V3DI*Y5E'5DLH(@;>C4U=7U(U?K3[@V9/4_!`=H+U- +M>P"[/JQ8U/YX'M[XNK"$[3DSO&1R-A%).5$7Q!_$Y';T\1D7$`_ENB)UTB?A +M8JED;D<+DAPAN&+4#[5-U]'SS*A>^1=X=*HLYMCK'N10-(:IVRX8!E$ +M=V"7X09LXD\JD2S/BY<\^NU_-TOZTA"Z(^\<3*\NEENB07*T591++UB;Q9WH +MM]3MF+%('PO>Q7CMZZ0QNU_6AT^ST?L[?;[/U]OM5;[73E4T^41=^;!/L1"OKHRR4H+K@4KZ2 +MSLKOW&WQC6#.^B-:[,5*;VR-D3E6/;QXRLWW/JCZMJ/]AL5"J]"[5+.J##HU +M*47MD$J2K=,^Q!S#2WSPA<$JVK-I0.=;K51D!"5P6&XK.X-<7FCV^G:8KY)?/>W\^$P="5XN3!/X&#(\7_^@ +MP7!M/_E>R#T)`7\A[5CP*9#\527(66VZXC1KJ4_P_01EUE(;>,E%8U9#;C?_ +MK[=`I/S,J146QT;9`G6QKWH]J[EYMXRF"G,N5VPDP/8>>V/*.#F?7EIX-#W] +M=W(&B*L@:%C;=Y:K>K-][&['I>27XTLY5;,0][5#)W&S47HC[\?1B`+#)6'R +M78UDJ_[ZT^8R71O\>F%(\(4.BZ-K=H9=HM&ZG3C^!8+G(M0@?))-OP^6W[._H]GJ:<*3)=&#H!T>U +MU_KR)473[ON!WNWI^R?9W=#V+H];W3ZMSF7P^*/_3?C&=BY+*B?%3TSG.Q]%^&-[D-JQ0HZ5P=N_D#W4E$'=NKER,[9$K4[.HLZL1A=T:G.8W,U* +M[\@+NI*PUQDSS:X$DFTSMB)=L4:';V]:50I8`.%:V.CQU):O3X['*N7AJWJ[ +M'/M;('FOS$5AN5.CI^!.[MNNX#@!:\"YU7]HKXT]A4^@#/+)V1X;9]"N.L?C +M."+\TJWL)<"?=.!AZ*4_\.929SQ-ALKQ?XMV+O9MGFJ]VJ57$E.'&8:\.N0) +M(E%L/^0`L`756">;57\8\5,_R)G;UT/*:Z90=Y*K_'L49JFH,O#]_`RQ_GQ# +M4'=AG8IPNG7^.'H`.SD'CDR````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````Y?C_Q[O\?H[OZGR_P[GIYZ^E_#YOX>G__ +M+:2Q1_Q*=6?_1I\;_^NGE>L.A>"$BG>H5PH<%D4*^S`T'!>&1:+)"4O#P*AC +M8[^7\IS&7!O>S72H0ZD0SA*YNYG\/'#I(BP[V:2*1Q0[GKT:+:V.]*WYZ-^F +M:7M!0R>&RG3CF5FDO72W4\LTIFB;]$X]2:^LW/),H3'Q\R^;/%>WS?'QRC>" +MJ+MHNHC0R%HR>:20#FF]Z96/AGJWGAY\87]Z$8?U^]P\DW9=,^YPZ;16UC9_ +M>-[P38>$-MB'GYHV;L%PO)NQM+S=S4,.1G2BB7GXK9:B]K\HU>X$H?BNB0B9 +MIM4MK)'#*-LS5<4F&V&C8@_5/8R=GSW42Z(]'@OTWU)$YE<>WX>/AX8_>7N[ +MDV.75X(W?R29IG!D_VC6TMD)-TR0;AOFDST9 +M.3!MH<66]EW789MP"BM<-^\'N.,&_$=2<#O)FJ^@?V/1G]5]2<#*7G-+\ZF\ +M`\4`S:DJ^\X/ES[^]J0=KZZF,;NU;S?Z5:HO,\1U][8-9R]OW;F6P8$M0]B2 +M71S@P^CLV[60$.@XU9"PQC._J$8,7"-:%IX]Q.S;+E%!&N7>AH:<$5RNK?WZ +M/LR.0(5.I4@7\_LUJRUHLO'"0!FU>+(0L9@97084^_GS^:+AG)X]H#&M1(#F](WC[..'+0 +M(+/HRS'D]QV)T4B.2>U^M1X.U2AA$Z&[S=XNI!2G#`?%=\,4L-7@>XPW_+EQ +MN7O&-AMZNGH$&I:8)W5L=TY(0]G&_R?1&'UD(_6@RX\E8`X[5W>W]/EF8O]] +MD>./=16BS<-5_F7'Y1D+9IE;`N)QT:8D&8[>K.E4-O8]1?K::?EX\ +MDJ"Q\6!1?1T>>ZRC).Z=CE,T'3HN2GAE(Q'!">%Y*:_RR+CSVZ@M1^]YV +ML_%[GSUA(R2D[)=`M)FT@Y)-F??ND_3Y[\G>'O^X%A.KR=YE:9S&$GG +MY-/!Y_DQYM?+V]KYNW^^_4NK<'0(,6:"\,M^: +MT=\]:O^T_'R>7UE)YMYN#4>=4MJ/->[W+M;EK/RG3^W3.%?9[]#74O<^>P/< +M413]FF38[71HC3+RU]?M_//#-NVF^Y7^Y+8F;=KX^ZW<_GY*^+#P;6[\_<_E +M+U>];A:O$\I!VTSA>N3.?EQ!7V-7\=O^?;U_P;\B6VGL01`[NQ_UV/EV?6_[ +MKUMZT[O9_GVNYTV1/KH!%W?X_-$Q6Z*VCY:Z`\F73*L5=?+\R5(5^AD3:_4F +MPZ;!;9^"3#]R[T>>VT\2BI\L[AOC&B]JMVN_Q>W[)OSM7;_AV_\OY8!>:*,6 +M^1^+],QGW%9XO+6V;MX[)*$5_/*RR#[\/?@Z]=!4^=::8E1311V%RF!#BWNN +MH`6H?QP7P:$Q(8=<#1R8"'K?=\M1$]ZR9G0@1-I$T1LX +M+]>?B]\9(V;OBT_`1`Z(?=DI7W,=_I_6!I+X?QP1X]B^)PI8_(/;:]Q#A\%= +MU]V3*MJ6PXH!IAF0;TC;,)_4^:80)[^-XR)WIO9*Z(;.RY;.ZCT334X)`;^7 +M`)G!CJ;U5;_QWC172 +MEQ5)6DA^I]KN8I@#C)'Y\TL_IF+YAP`2F?+J:F1&]L^.I?YQ<'.QGW\_DY** +M7%."8^.[EOJJ4^I!8LAMT8'W +M*)(_KSZ:PS!2,3M/EOH!?3V-&(93Q1@]%>'('N10B'[ASSP(7E_+)&;-F[@P<5G16<]$X9$C`X%NCG +M&WS1XZ85/CZ[%/J-^79*H.[NT;%V?BO"P['_B4;L9IM5*3!+D[3LW!!:^%X/ +MH(?\AZ\ODR0"#[2YY/I(->I2G^:%![5NS8#7%`9,;<^B+JE`R>7>EK;V(<7G +MI)QFM"^J;$DOG?M?GFG3N'9NH20GEJ.`Z?/FW,TUHN?*TH$@S\?KK_SX/[V4 +M-:[5Z.H(@FQ]7?^OP?=1Z&]CH9"[-C-?^_0.+?)_C,XS)I+\?GQG$]C_'Y.A +M::<4]CL9-C^=LJ[<\/T +M_V\'_;V2_?_GL]"T=#UL>!5=R.WA-/VW(@K["^S_S6'4X#Z7"9*V'%).\V[S +M+NWRDT.#_DLJP*//`HP'V(;,R&O[/<[?=^;M^[EVGXER]X8%UH6,D14XN36< +MM4_'3YCZ/-_MXVZ(0_8R51Q"A-7)J)A>CM=J%AFQ/_8S4LD9EL4&Q;XT +M:A^F[X.N.=2/8GFZB%%5_TQY9$J9('W!JKKM84)DR%\"?UFIS#(FW,OKO+29 +M,??;54.TUVIA(`J?ELM&2<77#.I3M'WMZV\'X??!IFS")Z>_<5]23S8V5V:W +MS3Y[4Z($%$`R*0+_3&^=6.G3=_ +MF=OZ*5FX[.U=^$44(MDNN1*-:FD-5<-F0!4Z+CD(&ZS`PP:Q,7/?Y;W<_V)& +MP/+!Z/I]HK"YTVJC1OP+704FTUIQJZH1='G]V;KS3?Y)T/"H;7WLW/#PQ+^MU<" +MT=21B_LYO9=O=Y)-L?;Y[=O)-&5HC$Q\.QRN-]Z*.6L1AY81FWLNCX2)ILQ]_#=?74B]R[[,U`28+FMTC(`+SV:&E:+,9M%^'8GO53@OWCY>E$ +M\5*(473SU#:(T7E6H1ZL)-IQN0*$K^<<92A6F3)E2%V8K0OY,\U3Z;I^F(S?)\L4:%EZ\A&3>KV8_$0/3``, +MOWR\5*LWQ=6QV)NB:'_!E]$N&O/"=)NP0$A+:PA03]]:&GY"G<$B).]M=GK" +MY!],0%M37/1F*OG`]$VTQ,7Z2*O(\AH]PYM>NKZ/1FI8:M]^4*\8VS)U;*?A +MD66TTPC=X^*;Q2B+VYSY +M>$[T9MNA*=H/!C"GJVLY/+^[XNF"HGK6A];1>V+,07LUM+TQ1NS4%CYYY0F3 +MKL4US$8U#<,QVIL.S)X\L0LC)LU4*P?\%VE6!6PW:A])<'L,F'EEQ.C22)=Q +M:='60-8?,$:@OA#FI^^N*8A%,3+6F-S6FJ^UK7=/JB%4HG1:O;%*B=4_'1$N +MP=J,]QZ<+==VW\-)P]@F]P9>"8:?BQ`_YM-7$[S]R99TWMEO\DW1/^M#4`R5 +M]6K0NG"*TZ7W0`WYI`7YN'HL(^D5F]:'X@L+/,L`UY:0^Y4SI#9FEA$&Y8)G +M=$(FF2-C'3D_W.#/NSZ:,1C/Q1%H,(X,5-\RS:(7N!F^]10O[U+D;[H7EJ+4,7_78&$+:5%4]JE[24+M6U3;R>"V'[NJ,3/E[/T6 +MRQ_[P6L^@2)X;4!J@&'#@:]]N04D@/2*Y<;]V$&%WH97VY]&G%[4KRUG`$7/ +M.I"7EEN++*T(`E7CI=*_)L\#6P;GBB)6J?+R6C>K1>`7)65#WX,<:ZF<_/)*_:IH\F[YKK%,52UCU]RP+_Z;=*J_^ +M/=@@76SS$@W=V$CJ!]<$?V1\SU+1FW/=07_Z?9#_$JD@],H0?H53`[.>R4J, +MR;RVQFU#N=%[K\OR]B&(0Z8)=9Z9EP52)Y_CD`W=\6*5D9NPJM&8\_#EI34W +M9_:XYT",S\-BP$-5Z47?Y=[K)(NCP\VZ#\T)#=[&OWWD@?%J)I4U7FL4&9IO +MXJ<,>R$HMG^FNL-:W83P1GH$=UT&:C?LF\U9-8WY^JKU?2`YZ]>IV?@WK]N7 +M@K.H?5G4C!G&:`S$(#=/@$HU>BV?#SM%I_#DX-_TKS5>GOSP:/#E\GP\A\QK9!V??79J;`^]O",N_AF_/+\*\XM'W>D +MT=3O3[8=G6MVKILA3MRSWVR<6COPE#]3Q'[N=+%;?@7O]-84'GK-B6*/6+1+#M7>'W89HDMS9=Z(GGXIY/TY]5;QX)2&[N9;X8YN +MG.)U(!5HN$7Y#B5K,2`-C=Q]9(FB%+\F+4TH)#O=SE#U<:=NZ9UB211ZU;J5F-07PXYJZ%EN)\*Y=KCXYW1BUC_K.A,5^XHN+_I+RJ@[V-ZSD7#CDVK +M*OXC+9YPU4I)[Y>?4>VW16.]9#VDT*3)IZ9";HZ`ZNQF(#YW.=7]?+M;M#7< +M",7M"^S:4STF9&.HM,6&=Z41G60DI,^O+Q5&[F!5BXWWN>S)6B*>'0LT]=3: +M=_J7Y=JL2X9/:[DAO11(N,MR +MXF4&73`DH?5\&GXY+5M=?Z<]*9*<-;5AV4)$U71",=Z/CUW&+(DT)I_11#=G +M8U4/2R-K>B_XH'AB.T;7)V.S]%.?H4UY6K\Z1:]HG&DLFWMGTT2VL4&S8^N:1GE>)N%C]='T4FF"*8<;DF._$?-5,NUD-V@2LX%4EFOCXLN%PT>'UI +MG%B:"+J]`R>S+CB(_I,-'9DT)L`5;U7#!I`T=I%^`W?%A\5H6,AF-_E;UI7I +MUS7<+/'1;MUA-Y,:+V?44--9]'H<_9Z>=4[YU1D*%\/LL +M.90.B]E1D.7?%TD_$*IT=%,:<$"3E^[:\M&L +MO?CENGP9NG;JEX4=3%`1,<>4SY0U*^'U?"MH;1@=V0W[$+/"@^N.EI%0S)?Y(7&L.=]%GN1[D@AH4B^NAT;]3>?0DUS[X6^H +M)@P)Y;I:NG!NYR08%BV4I2YNY^.INJQ7J&!%()+4O7&3:L.IDLNX=*W2TN/5,:.]>^:M6_/;AFI3 +MS"(W/\=]?XIH<,X&9P:74N(9:,W,NF0)<]U=,P+>]Y.,M\N-T1/L5YX?%=RE]Y=W5@>3_U"BQ2F8>%HIR +M#;HT#)O54Y8H2S=$EB8)!EH<5PA\:ERS]M_2:.C+6DPVG3R="NQ6"+%U?@#Y)M!3WG`U+!T.#,64=C%\\ +M;[P9_F0'Q1#SBZC]D0(GP]Z(^#-II[]^_\X&MBY+&,:N-V4E$<7CR;M;5R7> +M.:NE6]90B[FP>D5^./AF_#8DFF?43E*;$S3=YEJ]6B:5 +MTXE[L;48, +M3?W,@TH;\NYR2N#629=:Z/1DP=NU\F.W>*T*+U7V*=0W3)00U/X\DO3FXL:T +M&EUL+V0HN*:=5(`;=\W)27)Z0@;NZ:<>TZT5T5 +MI:/;4L07U`3$*7]FK'O\EZ\I:$M\;\YF@.^Q.Z04W%$1T=2YX^K-H\V,6R/[ +MZ`K>'/7QRA$*7S^#Y/OV.]_?P2@GZ7,?L9WX_.LE8.DMMW3@GZ7`/)A-_E&+ +M]GX:49G\6>B9E-:-H:/OE-J[QRZW*B-.HJ0C2#2.+R9<(W-O?VNH!S+9:1S; +M@\\G(/+(O!FB*HM&SA])28DWV>3I\+6'YQ7=QZ-274K=QN2@'JTJ961D/HO@ +MMBS&2HB^2;AN?-6$AM:74PCUO9I!=DXB@ETY_%]2A$>R+UU+E_Z^/\_SY7EI +M]"%8\&QRSC-E;'CP\\8G:8K\LQU,1M&U:5,GDB66I`+RRKQZFV$+:',3S\?% +MYX>T6:?!^FH^6[Q'+. +ML:?N%R(RQ=,>B(,ZFJUY/'BD0W]NB[E,4S)N1`:DQDI)K5_?#7L%\=HIN_6M +M$-TQT?:Y+F.<&\V(9?A,=G)3<"R-[$BA0%'/5NS.D)\HH(T3=/\;'WQ)9..X +M;-'2$=OGEE4^*G]ZG#%4J&L0A2P&[]OA]O,@&.U7:*I]_V]?C8BC'@K2<_9M +M2T#1>T-[K.OC%N97C"G<>>?S9;:+FN/XK1/R2WXQ;CTS9/"6>.*;L%,O_2&&7IYBS!2G?-IO/H;[O +M/4UW_LO29;1(W"J;CH%12*TH["-D2MX^J'P8*&;=93_L/;/RS;+>L'RW^A\F +MQ3Z"&3&NO5R]R&'S*$GI2EWHHD1P;9NI[U4.C9A]:R];N2NOBR0>^A6CMVY? +M@JGX6"Z<;`S5BI[T3D$#$BB6`.S\5Z+I'-L/=SSQ*V>S?0E3'MK!&:=#69($ +M.B9(_OQR['6R$K7'5W5V$A8^Q^?T3@R[\H_9L"[HYS=_?L&128FX))Z8"WGK +MVR-?,S+A23JU]40-+&J_8QY5HV:X1* +M*[<3$VA$&DQ:(1PMS?S[OFNKE6S9*FJYVH(]S9[7[SVVR`FFJ#2UQ3X(R5,, +M>=.%XH5_;<"@56B:R;@DY3H`YO9^>OAO3WY=55P?9PK6-YLWL4IL_A#WT'![ +M>GQ0SD;"7^+^N+E/^O)B$IW97EGX)HMF_DY+>0S&;\Z/X*[4HX-0` +M6&ZIZE3]YXSVHG.&W:\]&U[FTV'$NGEC$7?F2]H3)D)IR7Q1-YY(ATC&DUB; +M1>N,WG:ZG[:[`2\_&1F?)Y,'/Y*YY;PLM/:Q[D3(`2X^EH7?Y*90L^+\6-W0%CC5P +M9:B@9'R14RFLDAS*>3"KK1WZ_9K!>8HHT9^*AW6Q;S13I3>9(RNVF(5JCUXD +MX[N8_8B[IT1(LU*J]_SWPM_[?N2>]\7;J>[2.V^9N]&!>.Z/?R4F(*5RD7>_'-0VK+4VN=\DLK?Q +M^:N!T8LT13%V9R1]/`+Z5.>L[IQ3MW/D^;8GW*#@`;__[3HX```````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````/_E+Q/[,7]KU/_G_________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_________________________________________________________H!' +M_(O_ZQ_Z?___________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________________________________^@1_R+_^L?^G__________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________H$?\B__K'_I_____________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_Z!,`=$5#(T7Q9V;W,^%<[-7=@+1MD#N]V=(H:G#Q/=(`AA--ZA)I@\`SL8V +MT\;D&?>M2!R0!DOP\\./&QXPV1=7?1(/.9RZNKNZNKKQWGQ*OX1?J_5X.4KI +M7=_DN>RP```````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``>KO]/._Y^KG]#_CZ?Y]#U+SL7\^=T.?Z_?N>I\?3E+L=#BP'T/4CH=&$)N +M?DV+8S=:!D/EV(TU=I%YE#AD&+[K:W*S.+IFA-XK6PCAG>]/1 +MMA@BZ+>IN;?FV/5K\`7._LZLFFI_:#WA^CZ=_GG\[Z.=%B105Z.QW>KUO4/- +M[F;/1S\_\G\NQL>6#((A@;/W,_?N@?:]/LV?OB5_U%8"A>-<1:9\!E!D<[6&"@GT]WR^_. +M"=7H:/@_0WA`U5AA[7VZGCJ[>E5X+C26KE^^-NFT<<7,CJC//*W-']DS2Z=F +M9DJ9!0/G6>*0C4\UX8L_]QUUB@T5ZXQ1$-.,&:[?FC]D)`YYNG74?;3U_=?- +M[G;TM'P:I`2I;4COU_54TGF_4=X6$526/(,I+9@CRP2#] +M'J=7]ZU+Z\W6KIQA?7?2I\I"!+Q71:_9!2I4HR.X2B4-\W2K\DR7]>JGT7Q> +MKRZ_9!HH(>?]V&+1UT]+;@0'L;[5_S3%"?UWAM_;!D^W]/K_X^;I7OE?R]S_ +MVLGF!NCMZ6?X(VK?0N?#]U)QT_NBWX(*EF+3B8NCP)=.._C?N@N\ZL^#"9AK +MST*.D,-EEKC&[UWHO%>N/W@X=9M2M]J?'QI?=VK^UNWT)\:GK;]YX:?MB?`E +MF)'ADC\97[/PY`BGY%>MG/+/42R_\;S\()->K5G^\1!9..A.\O+D)NB.S($5 +M02T+`7)*,XVA30M^,A459Q'!N;6ZY-6C.JLQ%/Y52F+3EE1>&4,&R8XU':!$F; +MF5"OCP[G9]A#=)6ES/C@I$^=\E&"_%CF2%_A[10FG@" +M9^E,FKBG@OD$[6.JEU.YI]$W@W(N.VC[-#'%XX%/;/1[?R_J]$^'*EK5"=SZ +M]M-^"&:S1.;ZGV]C8C&N]&YQ8O$9DVMW&$,ZZ1FT%>RLK\VW58,-CWZB"XF" +MIO-.*_;$RS".=Y5A(MHK9-5OF.6&E)2(BI"WSE*K5QC`O^9R67Y]C5FY)L.* +M-/U(/D;#*)DM75HT%ZJ9OTK,WF9&5D+Y8->!;QECO^K]7-D<0)FYL7G9.Z_8 +MX+6$7@_'(NQ_&6#M<)Q^2WW#@&C<6;,AFP1=+M5Z\HE`UWG$!\8O:-BO[>J^>7N\=Y[)+2G+Y$M);V8@NWGHX\M.\JQ@CRQ +M%\!:!3]M-T&+'K+M_USM_2%\P@["=$LHV.XS#N+.<8R +MY%'0.GBJWIL.72$>]DKN4Z#6O:6Q,IP_]9E?$T]'C_\@[A>;$ +M?XI?LLR:40TVJ7)D#2,3>LU;`_$"4N +M&4P441T95`:X"'9$8,[W+\L&G7P/%C-/3,I72N(5A)F]_$-[H=&9[^'T^:"8 +MC^5]\6V4M>1GE+U9!YQ/U1YF1`/O9CF+?=FDVS+2`UZ/5[B0)D3@\E3^1^#. +MV_11VJRFU3*S[.A_"$`QS`]C"/@M#5>;#Y?-K;N\;)=_Q\$0(X_.ATRM^&OG;?N?!;-H8H[U/ +MHHPV\Z(&K1QH1O;`[;9!4U;]/A[G!2K,F2MW+2(XP^G(R'FP)@V:=)(\C6)N +MO@V\:>X_>!0>)%^0YO8ZHQ_OD#&P[\C.]6I6'[J]%(!2T`RI9NA"BFML:FKB +MAY(5(IH:[@V=C%AB:^D1Y?'3*&>OWZ$L3W5]?OZ-LD)4RGK0!YG6.3:L:4"-Y; +MD_GQ72.Y6W9]SX'DJ07OYL'`/M1W)6<2,?0QP#R^)XBJ4RE\]WAYGXY84YF7 +M:YZ5-@DT66G#Q9@60$BKPY+`](QGK2[_JJV\AQ/R`XH +MVD\14Z*>LF4*L@JS2KFW==$GM +MWFR`E-%>'U0G*T/+I#_TLL/<76W9Y:T`D(2>Q3P''$O,^-)8H0K\$E>\9BIC +M/&44Y$D<2;4D:YE[7"(8 +MDYKUJ\/M>"3_BK3D.C5HW%OS+M!?<&%S1T*M(GC>D?+53TXZ)3:5625@^CX9 +M]BG1L\:2+^&N]9T<\Y?:_6C!T9(['Z\[MBTC#HMC+@EX:.5KP^F.H=*=9QR6 +MIV8+DZ-P?PP^2QM0PUSDEX\_Z?Z1$CG7)\?^B"`Y"\,5D[^^SPV4ZN_5S*O! +M^9&W:4B"8L`6;4GI@157EE_6/M98M"?9#/+GW2`;VK,@'EVKD9(.X.KLO +M->-V?)=:LKQEV?3[5S_!Z;^-)351%BSQ`D)>.W8(D.+!*BV7BP5TM2OFK[>F +M"=:`6KJKM(]#K:FOG?C#2O[X>W5YJ1N!`-QG,>QX@Q6KI5"2JW:%6>3#-!-G +M*G&&BNEOE>:S@*F0+NR57M;R9;D'X-3:R>\J&`/1Y]:6E]P_W$E>MB9;FO*A +M"W"DV]+[=N+'KCLUN[.WL4:C$`3?V]G!KZ6EV:LMOZUA' +M=#U<,G!-<2@<>";Z039OGTY4=\3R1PS7-=J^W]:OTHKW? +M1Y7!VF17\?/7Z$E4#!Z)%*6*^<&D?D8PO?%I?/=P3PWI47++Z8#;%[=KD +M8Y.O:0K:=/8[%R58^">39H]V):N;XYX7R&8W=[_:C63/2NOC7+%S:\I;2VN6 +M94Y+0'@5X^I7P&OL7>#B?E7"&?@C-PLV15)1(A)GD)$8@P.MK)YXV)^O&3?4 +M8:ROF\I>*X;HE\Y&RIF\;S.PX52MN-2:`%FZV9IT]C6TZ_:[_O?K)(VL[_[Q +MF^>4]CI0^0F<9A*Z9IJ^0F9M2O4.)^R+^^YNO^CQU(%V +M4W]RLQE88IE2.BPQAKV,CR\8MSJNU7777A5*'O2[F\\/>IT9MX>SOP;3=?0F-V@]("UZ9Y'HZ6;1AGCFU;WD`Y=3M8O6]G8T +M,NQ(K*=^\2<:CT#]@Z-5^'0(PIO#,>>:U=#BY[?93%1)?X@`KQRVC3SHS%X_ +M@..+X0@#_IO&U^)=C=L76S/'W/!<=A-'6-V#P;3R$8-EK4+XPT)O- +M6^)I:<0RWY'!@LA7MZHVM8Y4JP<1`LF-U"BUL,%28TW4^[J38:4/)#7>SM>[ +M'3)\BLU4PS`LC4V=FCA@^;I<1]E:7_J>2+>*DQH\/EW[-S9EQ.TXS="/O>]B +MNW50:/>O+OQ.-JE0`3%YL.SEI[Z.)88V[DGE?CO\&CI;HR0;T#?0$7?*IQGU +MN^3UGEY)0MWV)/1&CN$X7Z8Y$\R2T-1X'QGU"MX*;F*[L$LK"3#H?2V>@(VZ +MRO5_BL9@$?C=GO*4[!5X\R5;I\6YJR,!Q&/@Q29R"(&N]=@'F\2G$`J\ +M*GCQ^*+(/UK2W/%665P'F=(FR7*_.?DKCM)DEZ=>3LOZY.4" +M99O\.:#R,,^3UFS>O0,6B'Q.*:/=2VG`/P%5ST1#D1TKU]NJ4<[YY<-6]7?7 +MADE11HDG6U=:'1_^US+C>IC^`2INA63>GEDM8_P[N/1;ET/Y_?&EYTIF-B;)U:K8GTO05S`3*R`L,0%2$9*[SBV< +MX3WA7?=B#Y^C[B>?!*ZO]N9R/A+ZMG>$V;_'R[?U7HS-EWC#[[MO:ULV2U+. +MDLLTV""@#FZ,$'.G=,/;L0_9^'0IV%K/Y0/%:^#FQRKI;\V#@V][_\=;V'N3 +M0F;T6TYD]@415A#,EU]GQ%:8#N9=X+U)(:'Z*40!H7UAGFMBRWA3Q\I[G>R< +ME)7*LHZLEE!$#;T:FKJ^I&K]:?<&S)ZGX(#M!>IKV`79]6+&I_/`]O?%U80G +M:GB,BX@'\MT1.ND3\+D9RKS%4LC94+WR+O#I5%G-L=8]R*!I#5.V7#`,HCNP2_"#-G$GE4B69\7+GG +MUVOYNE_6D(71'WCB97ETLMT2"Y6BK*)9>L3>+.]%KG4)T^(G\+`A$[K'-B27 +MU"2YM;=F1'6BV4KACWJ=LQ8I`^%[V*\=O72&+DD-5:']^KIZ/:]PM#L]G3[D +M-'-'P=&*^#]>?N8MK/CUVOZSFU?9J8L%B!C9S?Y<:8[6A]GMO3T.GV>C]G;[ +M?9^OM]JK?:ZV1LB/&5F^Y]4?5M1_L-BH57H7:I9U08=&I2B]L@E25;IGV(.8:6^>$ +M+ES#DK\KE=G'6IM?8LV;4$.OB5MK?5`!1L]O:0T$GNQTV3].>,)]:3S@E6U9 +MKDKAPNN5+9.2::]/N:/;N:;5S,+0T)\0%=/2[&AW>KU*!SK=:J,@(2N"PW%9 +MW!KB\T>WT[3%?)+Y[V_GPF#H2O%R8)_`P9'B__T&"X-I_\KV0>A("_D/:L>! +M3(?BJ2Y"RVW7$:-=2G^'Z",NLI#;QDHK&K(;<;_]?;H%)^9E2*BV.C;($ZV- +M>]'M7_KNY`T15D#0L;;O+5;U9OO +M8W8]+R2_&EG*K9B'O:H9.XV:B]$??CZ,0!89*P^2[&LE7_?6GS&2Z-_CTPI' +MA"AT71M;M#+M#DL;AXT94K'FZ..IMS?4VM*[>-&8[B#UHSF.2)!7WRJLA$AJ +MR#L;>/NJS\*9\JXP4:2'U)]W2EC2#[BP9%1GY)R*=CJ]/^^G"CHO5AO,[W4Z +M1*BZ?=]P.]V]/V3[. +M[H>Q='K>Z?5NF;D>W\K)STYV/HOPQOZDH@[MU;7`DDVF= +ML1+MBC0[>WK2J%+`!PK6QT>.I+5Z?'8Y5R\-6]78Y]K9`\U^8BL-RIT=/P)W +M=MUW`<`+7@7.J_M%?&GL*GT`9Y9.R/#;/H5QUC\9P1?FE6]A+@3[IP,/12G_ +MAS*3.>)L-E>+_%NQ=[-L\U7NU2JXDIPXS#7AUR!)$HMA_R`%@"ZJP3S:J_C' +MBIG^1,[>NAY373*#O)5?X]BC-4U!EX?OX&6/\^(:@[L,[%.%TZ_QP]`!V<@\ +M;EL@[&7&ED&AW(BSGW*'RLG2C+__M/40````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`#_V2\C^C%_:]3_Y____________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________________________________________Z`1_R+_^L?^G__ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________H$?\B__K'_I_____________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_________Z!)#_4%IS_=3_\````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````$````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````````!Q,(=41 +M#,T1`!85O9S\*.C/!I9I1:2;N[&-B[`5MIBT,?1836;F[OB11)I)5B)-+34% +MIEX-^[V`4GT(E*.1T3,T512)P;F^.L,(DS43'5SOBOB7/\(/W/[]SD1P3SPF +M!'I,@``````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````.7XW\>[_'Z.[^I\O\.YZ>>OI?P^;^'I__RVDL4?\2G5G_T:?&__K +MIY7K#H7@A(IWJ%<*'!9%"OLP-!P7AD6BR0E+P\"H8V._E_*C?IFE[04,GALITXYE9I+UT +MMU/+-*9HF_1./4FOK-SR3*$Q\?,OFSQ7M\WQ\F5CX9ZMYX>?&%_>A&']?O\$V'A#;8AY^:-F[! +M<+R;L;2\W&/WE[NW#\"VZ13S4Z)=:V3Q#T +MU/+GI-CEU>"-W\DF:9P9/]HUM+9"3=,D')VO?T5`Y@0JK9)ZDNJKN55>?RY5 +MNYJSH3JV#6/<3LVRY101KEWH:&G!%)MZ=CQ\GZ4 +M6;81TIWET&%/OY\_FBX9R>/:`QK42`YO2-X^SCART""SZ,LQY/<=B=%(CDGM +M?K4>#M4H81.AN\W>+J04IPP'Q7?#%+#5X'N,-_RY<;E[QC8;>KIZ!!J6F"=U +M;'=.2$/9QO\GT1A]9"/UH,N/)6`..U=WM_3Y9F+_?9'CCW45HLW#5?YEQW,@ +M;`6'N49"V:96P+B<=&F)!F.WJSI5#;V/47ZVFGY>/)*@L?%@47T='GNLHR3N +MG8Y3-!TZ'+]3GRB>+)PE;U"26?49/=@L;K[PEX?V2FO\LBX\]NH+4?O>=K/Q>Y\]82,DI.R70+29 +MM(.239GW[I/W*1+WD^>_)WA[_N!83J\G>96F?Y,7.FUW>WV_\N +MUV^[VNY_+Q=WN;7R]O:^;M_OOU+JW!T"#%F@O#+?FM'?/6K_M/Q\GE]92>;> +M;@U'G5+:CS7N]R[6Y:S\IT_MTSA7V>_0UU+W/GL#W%$4_9IDV.UT:(TR\M?7 +M[?SSPS;MION5_N2V)FW:^/NMW/Y^2OBP\&UN_/W/Y2]7O6X6KQ/*0=M,X7KD +MSGY<05]C5_';_GV]?\&_(EMI[$$0.[L?]=CY=GUO^Z];>M.[V?Y]KN=-D3ZZ +M`1=W^/S1,5NBMH^6N@/)ETRK%77R_,E2%?H9$VOU)L.FP6V?@DP_+RUMF[> +M.R2A%?SRLL@^_#WX.O705/G6FF)44T4=ALF9T($3:1-$7*>D-%"$=?3N^+5%(_=^.27QEDR"]ZTV@X8_& +M&>/G>F3@B!^/)-IU:J"_U:B;$#85>RVGU'%[P=WK."_7GXO?&2-F[XM/P$0. +MB'W9*5]S'?Z?U@:2^'\<$>/8OB<*6/R#VVO<0X?!7=?=DRK:EL.*`:89D&]( +MVS"?U/FF$">_C>,B=Z;V2NB&SLN6SNH]$TU."0&_EP"9P8ZF]56_\=XT5W*Z +M(8%\ZC[&:UCV8_:+VW,O/7*'4,FO@'.<6`99O;Z<2@48FVBZ,8DT*HLE,P8$A:?WB! +M[D4(A^X<\\"%Y?RR1FS9NX,'%9T5G/1.&1(P.!;HYQM\T>.F%3X^NQ3ZC?EV +M2J#N[M&Q=GXKPL.Q_XE&[&:;52DP2Y.T[-P06OA>#Z"'_(>O+Y,D`@^TN>3Z +M2#7J4I_FA0>U;LV`UQ0&3&W/HBZI0,GEWI:V]B'%YZ2<9K0OJFQ)+YW[7YYI +MT[AV;J$D)Y:C@.GSYMS--:+GRM*!(,_'ZZ_\^#^]E#6NU>CJ"()L?5W_K\'W +M4>AO8Z&0NS8S7_OT#BWR?XS.,R:2_'Y\9Q/8_Q^3H6FG%/8[&38_G;*NW'*. +MW)A5=CL]G8_Z>MON_T^S[.S]&N]?OP@820/NQWO#]/]O!_V]DOW_Y[/0M'0] +M;'@57&!=:%C)$5.+DUG+5/QT^8^CS?[>-NB$/V +M,E4<7)EZ7(.*]?PTP@@=BA%.&SYVO!]WU_)]O>^[P?7(++:^WZZ?#AAT\W[= +MEG;L3P351#M:+[3$?^\O^HME\&24S_T1G+U1+-Q79*PV'(J5IS:)$+]VKO&E +M0R'-2I['@H35R:B87H[7:A89L3_V,U+)&9;%!L6^-&H?IN^#KCG4CV)YNHA1 +M5?],>61*F2!]P:JZ[6%"9,A?`G]9JMO!^'WP:9LPB>GOW%?4D\V-E=FM\T^>W#]&KO)IO^I9^&R +M;K[;\*L#7CZ?:*PN=-JHT;\ +M"UT%)M-:<:NJ$71Y_=FZ\W).4!90;+G\EEX#1J;PR2-L#O-6&E(XK[#KM-8= +M]C<.;=9O$SI)Y23;'V +M^>W;R31E:(Q,?#LBCEK$8>6$9M[+H^$B:;'+>[EJJ)]A)U.2]L65(9R +M>I<#C8;!8>M=*W\_/L?B$S;X3>UO(F,]'V<1)_:NAODT_>$:7\>6)[XZ<]'% +M=EU8T[QXE>QN9@=S24?7&Y[2*>E2E, +MK"3:<;D"A*_G'&4H5IDR7-$12A*,D+W*3C1W/%Y=4FQ%&*83)\NBRQQ'I4A= +MF*T+^3/-4^FZ?IB,WR?+%&A9>O(7.6/;&:KK2H%3UU>9E.D_@_S[_]/IYW)E +M;XEL:43.SFZKSR6X=$TH+SSA8+GADWJ]F/Q$#TP`#+]\O%2K-\75L=B;HFA_ +MP9?1+AKSPG2;L$!(2VL(4$_?6AI^0IW!(B3O;79ZPN0?3$!;4UST9BKYP/1- +MM,3%^DBKR/(:/<.;7KJ^CT9J6&K??E"O&-LR=6RGX9%EM-,(W>/BF\4HB]G+ +MUFY/IEP-HPS!8@UUFXK35!Z(_SASX(*5WQ7S576EW5-_8]'6[E2&KE=VN;X% +M:[NYM%C1<+NVLN.:!U-C+2"TX;(84R9WQ55<]'N<^7A.]&;;H2G:#P8PIZMK +M.3R_N^+I@J)ZUH?6T7MBS$%[-;2],4;LU!8^>>4)DZ[%- +M/+$+(R;-5"L'_!=I5@5L-VH?27![#)AY9<3HTDB7<6G1UD#6'S!&H+X0YJ?O +MKBF(13$RUICG"W7=M_#26D/N5,Z0V9I81!N6"9W1")IDC8QTY/]S@S[L^ +MFC$8S\41:#".#%3?,LVB%[@9OO44+^]2Y&W-*^@BU1%`MY[N7=Z)]^&?@M&6 +MF)V"QN;DQ":81BC^''8X[6`O>/1JNX"UK[5]VU37^_PD[J^:5V-%:YYL^W;(W9N_WNZ%Y:B +MU#%_UV!A"VE15/:I>TE"[5M4V\G@MA^[JC$SY>S]%LL?^\%K/H$B>&U`:H!A +MPX&O?;D%)(#TBN7&_=A!A=Z&5]N?1IQ>U*\M9P!%SSJ0EY9;BRRM"`)5XZ72 +MOR;/`UL&YXHB5JGR\EHWJT7@%R5G)QE[`!E^/RF>#SY9?YPZ8;%\O2ZZ0GE0 +M]^#'&NIG/SR2OVJ:/)N^:ZQ3%4M8]?Z_+\O8A +MB$.F"76>F9<%4B>?XY`-W?%BE9&;L*K1F//PY:4U-V?VN.=`C,_#8L!#5>E% +MW^7>ZR2+H\/-N@_-"0W>QK]]Y('Q:B:5-5YK%!F:;^*G#'LA*+9_IKK#6MV$ +M\$9Z!'==!FHW[)O-636-^?JJ]7T@.>O7J=GX-Z_;EX*SJ'U9U(P9QF@,Q"`W +M3X!*-7HMGP\[1:?PY.#?]*\W+[Q:_[28_V%L^#?/U9N*L\^]:U'7E7I[\\&C +MPY?)\/(?,:V0=GWUV:FP/O;PC+OX9OSR_"O.+1]WI-'4[T^V'9UK=JZ;(4[< +ML]]LG%H[\)0_4\1^[G2Q6WX%[_37'_AWUXLOY>[Z/6")-H&;V_KY2A$N_R;' +M*[R)OVP;(F!9:KV%I2CB;Q[V$?(Z[JOA>B&U=?##-(7,P9'F%!YZS8EBCUBT +M2P[5WA]V&:)+B)Y^*>3].?56\>"4AN[F6^&.;ISB=2`5:+A%^0XE:S$@ +M#8WG,%I^7PA.V>D/?>WM6ZE9C4 +M%\..:NA9;B?"N7:X^.=T8M8_ZSH3%?N'.F:UC?DH$6_&DMBZO,\]9>]2@.E) +M&;7=@D=U)T"42`L>@*>'J+B_Z2\JH.]C>LY%PXY-JRK^(RV><-5*2>^7GU'M +MMT5CO60]I-"DR:>F0FZ.@.KL9B`^=SG5_7R[6[0UW`C%[0OLVE,])F1CJ+3% +MAG>E$9UD)*3/KR\51NY@58N-][GLR5HBGAT+-/74VG?ZE^7:K$N&3VNY(;T4 +M2+C+A7N)E!ETP)*'U?!I^.2U; +M77^G/2F2G#6U8=E"1-5T0C'>CX]=QBR)-":?T40W9V-5#TLC:WHO^*!X8CM& +MUR=CL_13GZ%->5J_.D6O:)QI+)M[9]-$MK%!G,O_R7LV/KFD9Y7B;A8_71]% +M)I@BF'&Y)COQ'S53+M9#=H$K.!5)9KX^++A<-'A]:9Q8F@BZO0,GLRXXB/Z3 +M#1V9-";`%6]5PP:0-':1?@-WQ8?%:%C(9C?Y6]:5Z=3&BW) +M0!;375:#7?5-7MGU%#36?1Z'/V>GG5.^=49"A?#[+#F4#HO949#EWQ='-_6] +M9?=\?/G[7)SKUK%'4Q0 +M$3''E,^4-2OA]7PK:&T8'=D-W*VB6X4).M<^P3(LOE36UM-'>9J( +M-49K[WT_97TJL`31ETP18CSP+Y>:/NG1^.37NW,F[YK,[*;EWA"SPH/KCI:1 +M4,R7^2%QK#G?19[D>Y((:%(OKH=&_4WGT)-<^^%OJ"8,">6Z6KIP;N`T/*Q\=W+J.0?2ZGG +MO>3C+?+C=$3[%>>'Q77=U8'D_]0HL4IF'A:*<@VZ-`R;U5.6*$LW1)8F +M"09:'%<(?&G`6L#]]>1";IC?4-V827=ABFSA3D2>9[TWW%3#WIB/@S::>_?O_.!K8N2QC&KC=E)1'%X\F[6U0,(EMS<-;TGOCCX9OPV))IGU$Y2FQ,TW>9:O5HFE=.)>[&W.N\"4W__&2.% +MO9(=V?Z9_2<+!ZMT4,L>_U/WU-4Z<]^DK:KD5WE&#$W]S(-*&_+ND(&[NFG'M.M%=%:6CVU+$%]0$Q"E_9JQ[ +M_)>O*6A+?&_.9H#OL3ND%-Q1$='4N>/JS:/-C%LC^^@*WASU\C4EU*W<;DH!ZM*F5D9#Z+X+8LQDJ(ODFX;GS5A(;6 +MEU,(];V:079.(H)=.?Q?4H1'LB]=2Y?^OC_/\^5Y:?0A6/!LIMA"VAS$\_'Q>>'M%FGP?IJ/EN\7,?& +M9E@!2"G4MDYDN9FH[(?NC?@R=(/K>R<&3R1'+WARSK&G[A3QXI$-_;HNY3%,R;D0&I,9*2:U?WPU[!?':*;OUK1#=,='VN2YCG!O-B&7X +M3'9R4W`LC>Q(H4!1SU;LSI"?**"-$W3_&Q]\263CN&S1TA';YY95/BI_>IPQ +M5*AK$(4L!N_;X?;S(!CM5VBJ??]O7XV(HQX*TG/V;4M`T7M#>ZSKXQ;F5XPI +MW'GG\V6VBYKC^*T3\DM^,6X],V3PG'R=/9.AKN@`=51G"LJ]IHZH;I]I='PU1EOXY'XJU2:;1TR9/*]V/=6")LTZ[AJCE4ZBGEG.3 +M/1EYXE5SSYX'GCBF[!3+_TAAEZ>8LP4IWS:;SZ&^[SU-=_[+TF6T2-PJFXZ! +M44BM*.PC9$K>/JA\&"AFW64_[#VS\LVRWK!\M_H?)L4^@ADQKKU]5#HV8?6LO6[DKKXLD'OH5H[=N7X*I^%@NG&P,U8J>]$Y! +M`Q(HE@#L_%>BZ1S;#W<\\2MGLWT)4Q[:P1FG0UF2!#HF2/[\F`MYZ]LC7S,RX4DZM?5$#2QJ +MG)[0N.?8@\P$9-)^0.OMHW,VF()]_"@]_N<*U(DS02,0@FJ4'Z.X6-PG8Y3] +MWX`WR1P9=1]AT[_LS[T=5-U8D=/ZM[-1V-^;6YB-QIHS\1OK1E#^H^/%2CSU +M*]SFZB-O0P7.9&(^"2;U+Z.1_C%^3WOV,>5:-FN$2BNW$Q-H1!I,6B$<+U^\]ML@)IJ@TM<4^",E3#'G3A>*%?VW`H%5HFLFX +M).4Z`.;V?GKX;T]^755<'V<*UC>;-[%*;/X0]]!P>WI\4,Y&PE_B_KBY3_KR +M8A*=V5Y9^":+9OY.2W-%I:#J"YC[#9]&6)@HH1ZHV*<8TFQK2]$+2^(@3/9+1"6W2O)L"JZC)MCDJG+%_;+= +MUEV.2(I,V[T@EI4_>>,]J)SAMVO +M/1M>YM-AQ+IY8Q%WYDO:$R9":>2(=(QI-8FT7KC-YVNI^VNP$O'+G7 +M+LUC#W-PU`SJ5TG3!'3-Y$71F&\RIAPA-3+KMQ`A.LV>T\I=DWOQD9GR>3!S +M^2N>6\'-??Y*P]1Z)]:MSNVK3KLQO<_'-NOXQU:K;F)9UV*]@/U`:IFZLT$S +M[=SKY$R`$N/I:%W^2F4+/B_%C=T!8XU<&6HH&1\D5,IK)()..[F/V(NZ=$2+-2JO?\ +M]\+?^W[DGO?%VZGNTCMOF;O1@7CNCW\E)B"E\79I]#\?;E*)GX0XO'&S/8K]`A_E[O:W-?VBQ++>W23#MS +MBS^;+K!B)WYOZGT*KTU5WI%WOQS4-JRU-KG?)+*W\?FK@=&+-$4Q=FH2:8/`,[& +M-M/&Y!GWK4@,-D75WT2#SF#E* +MZ5W?Y+GLL``````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````'J[_3SO^?JY_0_X^G +M^?0]2\[%_/G=#G^OW[GJ?'TY2['0XL!]#U(Z'1A";GY-BV,W6@9#W(9][P]/ +MH]'[A3K3X&Y3I1IDIHT2.XL$R&Y[I4@=.F[#?/^ZK1ZD#&6'[\,TB^]<>9\" +MY-'I=B--7:1>90X9!B^ZVMRLSBZ9H3>*UL(X9WO3T;88(NBWJ;FWYMCU:_`% +MSO[.K)IJ?V@]X?H^G?YY_.^CG18D4%>CL=WJ];U#S>YFST<_/_)_+L;'E@R" +M(8&S]S/W[H'VO3[-G[XE?]16`H7C7$6F?`7.ERJ_\NC3.&L[XU<8.@9'&L'1 +M%!-IUL?&T8$DS.,.S_X.*MFY1YV-X9_`(S_AWXIX>G6]DL&G_OS_IAR`Z?BI +M3QZ.HD:>+P"$%C35TX0*EI^YVGV?T]ST4:L"3()CQ +M_;TU>HQ6M?7%4=POV:74YL0'I09'.UA@H)]/=\OOS@G5Z&CX/T-X0-588>U] +MNIXZNWI5>"XTEJY?OC;IM''%S(ZHSSRMS1_9,TNG9F9*F04#YUGBD(U/->&+ +M/_<==8H-%>N,41#3C!FNWYH_9"0.>;IUU'VT]?W7S>YV]+1\&G+.*[KK$#3U +MQL@WJ0$J6U([]?U5-)YOU'>%A%4ECR#*2V8(\L$@_1ZG5_>M2^O-UJZ<87UW +MTJ?*0@2\5T6OV04J5*,CN$HE#?-TJ_),E_7JI]%\7J\NOV0:*"'G_=ABT==/ +M2VX$![&^U?\TQ0G]=X;?VP9/M_3Z_^/FZ5[Y7\O<_]K)Y@;H[>EG^"-JWT+G +MP_=2<=/[HM^""I9BTXF+H\"73COXW[H+O.K/@PF8:\]"CI##99:XQN]=Z+Q7 +MKC]X.'6;4K?:GQ\:7W=J_M;M]"?&IZV_>>&G[8GP)9B1X9(_&5^S\.0(I^17 +MK9SRSU$LO_&\_""37JU9_O$063CH3O+RY";HCLR!%4$M"P%R2C.-H4T+?C(5 +M%67(4L1#KH$O:A2=CZ)I=,W#/<=T<&R;OD^+GR7]R>;S\[^F=SHQ[7Y?2JY?(" +M\?;D5='4C,DW>]M08M$KGBTY947AE#!LF.-1V@1)FYE7*S+,.\DPMX]7(X1G +M@KX\.YV?80W25IT4)IX`F?I3)JXIX+Y!.UCJI=3 +MN:?1-X-R+CMH^S0QQ>.!3VST>W\OZO1/ARI:U0G<^O;3?@AFLT3F^I]O8V(Q +MKO1N<6+Q&9-K=QA#.ND9M!7LK*_-MU6##8]^H@N)@J;S3BOVQ,LPCG>582+: +M*V35;YCEAI24B(J0M\Y2JU<8P+_FJ +MF;]*S-YF1E9"^6#7@6\98[_J_5S9'$"9N;%YV3NOV."UA%X/QR+L?QE@[7"< +M?DM]PX!HW%FS(9L$72W-F;R_Q4)6NGQ]CR5DD<$4/@WK5>O*)0-=YQ`?&+VC +M8K^WJOGE[O'>>R2TIR^1+26]F(+MYZ./+3O*L8(\L1?`6G+W.'X^$2W9;!*^ +M:F_'@4W(5F1JU?!NVGK-6P/Q`E+AE,%%$=&50&N`AV1&#. +M]R_+!IU\#Q8S3TS*5TKB%829O?Q#>Z'1F>_A]/F@F(_E??%ME+7D9Y2]60>< +M3]4>9D0#[V8YBWW9I-LRT@->CU>XD"9$X/)4_D?@SMOT4=JLIM4RL^SH7+YF +M^D*/KRO?/*04O+L4&ZDC*5OA&Y,:7!/@]ZOHM"FQW8VJ5;AM*JL7;-6!N[6] +MJ0@0>(#ME,2.IWSQZ(5C"T&2/9\1OUR3*%B2C7]$U3>GU7#`_% +M*#CTL%T>+DJ]8LZ`%_S9T0AR,F*8A^38LN[FV;>H'$8@.LX?T>!M2_'\S.MV +MAR_G/VL%"@,^G4"N=%Y0?-TLOL=FY3@:\3EV[\9U@?GOPA`,

    YP4JS)DK=RTB.,/IR,AYL"8-FG22/(UB;KX-O&GN/W@4'B1?D.;V +M.J,?[Y`QL._(SO5J5A^ZO12`4M`,J6;H0HIK;&IJXH>2%2*:&G,SJ5^>K9HV +M8Y<<-T]9F<;HSQ'1>LBVE;`)X`M'./CRH=Y@#/K"F_3I6A'NX-G8Q88FOI$> +M7QTRAGK]^A+$]U?7[^C;)"5,IZT`>9UCDVK&E`C>6Y/Y\5TCN5MV?<^!Y*D% +M[^;!P#[4=R5G$C'T,<`\OB>(JE,I?/=X>9^.6%.9EVN>E38)-%EIP\68%D!( +MJ\.2P/2,9ZTN_ZJMO(<3\@'.$AJ8LQN+'*1OZ>MABA;T2=+%VV^E#8=?&(*C +M">6"'4>./TYUUZ^16ZB9?F032LZ@`G#.NUP)E_R"<$+G.1MQ +MN&41O^>#0SVYI;T@#9T";E^4T8INM0VK05*WSG7N*-I/$5.BGK)E"K(*LTJY +MMW7*0%E#-DIT)\6M`)"$GL4\!QQ+S/C26*$*_!)7O&8J8SQE%.1)'$FU)&N9>UPB +M&'*@ZVQ.5<97)*HZ$LP8EM1J`AG9)EA010)R+E<*WI.:]:O'+5J/60FO]]?4 +MO>9F7&+58QPXE=<$_[Y=?<@VU>AS\Z>^"&//+@SM?!MP0'>O[:_QZC1"HHK` +MV\AL!%@P)*Z;^UUI#AC3SVS#Y2EC^[8S`\,8J0E7-CCXH454<5$7#N4^4`KW +M*54I;%J4N2KFI^'5Y^,1K?,;1U`HG-30&8H; +M-(IHL$"RXYQ21.AQ<9'YO,W_.Y$EP]>$?@W8SRAX(VJ]XXWC[7@D_XJTY#HU +M:-Q;\R[07W!A//^G^D1(YUR?'_H@@.0O#%9._OL\-E.KOUF_C24U418L\0)"7CMV")#BP2HMEXL%=+4KYJ^WI@G6@%JZJ[2/0ZVIKYWX +MPTK^^'MU>:D;@0#<9S'L>(,5JZ50DJMVA5GDPS039RIQAHKI;Y7FLX"ID"[L +ME5[6\F6Y!^#4VLGO*A@#T>?6EI?K[5HZ?\OY7:'ES7:OM_6K]**]WT>5P=ID5_'SU^A)5`P> +MB12EBOG!G(\?]O(,ZJZNARE%[&H"K\N7383F-&V2K`]XL&K+H:G+2H^[NT.GXJ^6+]:LMOZ*,]>"%W;U;$(?)ED_MTH$E8_F)VC +M('`[:RJ8M;7I'Y&,+WQ:7SW<$\-Z5%RR^F`VQ>W:Y&.3KVD*VG3V.Q%\AF-W>_VHUDSTKKXURQ/ISFG9V+O! +MQ/RKA#/P1FX6;(JDHD0DSR$B,08'6UD\\;$_7C)OJ,-97S>4O%<-T2^-YG8<*I6W&I-`"S=;,TZ>QK:=?M=_WOUDD;6=_]XS?/*>QTH?(3.,PE=,TU +M?(3,VI7J'$_9%_?\3,7RS)JO77_1XZD"[*;^Y68RL,4RI'188PU[ +M&1Y>,6YU7:KKKKPJE#WI=S>>'O4Z,V\/9WX-N/ESM;8\MNE$KQMI7':P([CO +M)NOH3&[0>D!:],\CT=+-HPSQS:M[R`SL:&78D5E._>).-1Z!^P=& +MJ_#H$84WAF//-:NAQ<]OLIBHDO\0`5XY;1IYT9B\?P''%\(0!_TWC:_$NQNV +M+K9GC[G@N.PFCK&N/H:2B/;!X-IY",&RUJ%\8:$WFK?$TM.(9;\C@P60KV]4 +M;6L'R[]FYLRXG:<9NA'WO>Q7;JH-'O7EWXG&U2H`)B +M\V'9RT]]'$L,;=R3ROQW^#1TMT9(-Z!OH"+OE4XSZW?)ZSR\DH6[[$GHC1W" +M<+],9):&H\#XSZA6\%-S%=V"65A)AT/I;/0$;=97J_Q6,P"/QNSWE*=@J +M\>9*MT^+NP#S>)3B`./BO5>%3QX_%%D'ZUI;GBK+*X +M#S.D39+E?G/R5QVDR2].O)V7].6T[%.EC-8\?$YFXK!4]>;CU5T(=0!5_AA+ +M&<;5Q%6O[H[.&/Y[?=^?'<$UJ%I,Q96U]9MQOKOKPR2HHT23K:NM#H__:YE +MQO4Q_`)4W0K)O3RR6L?X=W'N/^%'L6/^"S-X:\JK\ZFK;0QG%@C5I6/(MRZ' +M\_OC2\Z4S&Q-DZM5L3Z7H*Y@)E9`6&("I",E=YQ;.<)[PKONQ!\_1]Q//@E= +M7^W,Y'PE]6SO";-_CY=OZKT9FR[QA]]VWM:V;):EG266:;!!0!S=&"#G3NF' +MMV(?L_#H4["UG\H'BM?!S8Y5TM^;!P;>]_^.M[#W)H3-Z+:P*(JPAF2Z^ +MSXBM,!W,N\%ZDD-#]%*(`T+ZPSS6Q9;PIX^4]SO9.2DKE64=62R@B!MZ-35U +M?4C5^M/N#9D]3\$!V@O4U[`+L^K%C4_G@>WOBZL(3M.3.\9'(V$4DY41?$'\ +M3D=O3Q&1<0#^6Z(G72)^%R,Y5YBJ61N1PN2'"&X8M0/M4W7T?/,J%[Y%WATJ +MBSFV.L>Y%`TAJG;+A@&41W8)?A!FSB3RJ1+,^+ESSZ[7\W2_K2$+HC[QQ,KR +MZ66Z)!BUSJ$Z?$3^%@0B=UCFQ)+ZA).WKI#%R2&JM#^_5T]'M>X6AV>SI]R&CFCX.C%?!^O/W,6UGQ +MZ[7]9S:OLU,6"Q`QLYO\N-,=K0^SVWIZ'3[/1^SM]OL_7V^U5OM=.533Y1%W +MYL$^Q$*^NC+)2@NN!2OI+.RN_<;?&-8,[Z(UKLQ4IO;(V1.58]O'C*S?<^J/ +MJVH_V&Q4*KT+M4LZH,.C4I1>V02I*MTS[$',-+?/"%RYAR5^5RNSCK4VOL6; +M-J"'7Q*VUOJ@`HV>WM(:"3W8Z;)^G/&$^M)YP2K:LUR5PX77*ELG)-->GW-' +MMW--JYF%H:$^("NGI=C0[O5ZE`YUNM5&0$)7!8;BL[@UQ>:/;Z=IBODE\][? +MSX3!T)7BY,$_@8,CQ?_Z#!<&T_^5[(/0D!?R'M6/`ID/Q5)CVKN7FWC*8*6G@T/?UW<@:(JR!H6-MWEJMZLWWL;L>EY)?C2SE5LQ#WM4 +M,G<;-1>B/OQ]&(`L,E8?)=C62K_OK3YC)=&_QZ84CPA0Z+HVMVAEVAR6-P\: +M,J5CS=''4VYOJ;6E=O&C,=Q!ZT9S')$@K[Y560B0U9!V-O'W59^%,^5<8*-) +M#ZD^[I2QI!]Q8,BHS\DY%.QU>G_?3A1T7JPWF=[J=./X%@NIIPI,ET8.@'1[77^O(E1=/N^X'>[>G[)]G=T/8NCUO=/JW.9?#XH_ +M]-^,9V+DLJ)\5/3-R/;^5DYZ<['T7X8WN0VK%"CI7!V[^0/=240=VZN7(SMD +M2M3LZBSJQ&%W1J&K>KL<^UL@>:_,16&Y4Z.GX$[NVZ[@.`%KP+G5?VBOC3 +MV%3Z`,\LG9'AMGT*XZQ^,X(OS2K>PEP)]TX&'HI3_PYE)G/$V&RO%_BW8N]F +MV>:KW:I5<24X<9AKPZY`DB46P_Y`"P!=58)YM5?QCQ4S_(F=O70\IKIE!WDJ +MO\>Q1FJ:@R\/W\#+'^?$-0=V&=BG"Z=?XX>@`[.0>-RV0=C+C2N8>KJLO2#0 +M[D19S[E#Y63I1E__VGJ(```````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``!_[$O(_HQ?VO4_^?__________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_______________________________________________^@$?\B__K'_I_ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_____________________________Z!'_(O_ZQ_Z?___________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________^@1_R+_^L?^G______________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________H$PAU1$, +MS1$`%A6]G/PHZ,\&EFE%I)N[L8V+L!6VF+0Q]%A-9N;N^)%$FDE6(DTM-46F +M7@W[O@!2?0B4HY'1,S15%(G!N;XZPPB3-1,=7.^*^)<_P@_<_OW.1'!//"8$ +M>DR````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````!R_'_CW?X_1W?U +M/E_AW/3SU]+^'S?P]/_^6TEBC_B4ZL_^C3XW_]=/*]8="\$)%.]0KA0X+(H5 +M]F!H."\,BT62$I>'@5#&QW\OY3F,N#>]FNE0AU(AG"5S=S/X>.'21%AWLTD4 +MCBAW/7HT6UL=Z5OST;],TO:"AD\-E.G',K-)>NENIY9I3-$WZ)QZDU]9N>29 +M0F/CYE\V>*]OF^/CE&\%47;1=1&AD+1D\TD@'--[TRL?#/5O/#SXPO[T(P_K +M][AY)NRZ9]SATVBMK&S^\;W@FP\(;;$//S1LW8+A>3=C:7F[FH8QD[/GNHET1Z/!?I +MOJ2)S*X]OP\?#PQ^\O=VX?@6W2*>:G1+K6R>(>FIY<])L9 +M=VJL1P%/>T<\W#?-)GHR3-5]` +M_L>C/ZKZDX&4O.:7YU-X!XH!FU)5]YP?+GW][4@[7UU,8W=JWF_TJU1>9XCK +M[VP:SE[?NW,M@P):A[$DNCG!A]'9MVL@(=!QJR%AC&=_4(P8N$:T+3Q[B=FV +M7**"-.$@#-J\60A8S`RY)V* +M;Q-O3L>/CE@^>$N6G$T>.>*710.G)7=C:YCT_2BS;".E.\N@PI]_/G\T7#.3 +MQ[0&-:B0'-Z1O'V<<.6@06?1EF/)[CL3HI$,;#;U=/0(-2TP3NK8[IR0A[.-_D^B,/K(1^M! +MEQY*P!QVKN]OZ?+,Q?[[(\<>ZBM%FX:K_,N.YD#8"P]RC(6S3*V!<3CHTQ(, +MQV]6=*H;>QZB_6TT_+QY)4%CXL"B^CH\]UE&2=T['*9H.G0Y?J<^43Q9.$K> +MH22SZC)[L%C=?>$O#^SEW_QJ(!`%$8W>R>,7(7^M681K69W26]\GSWY. +M\/?]P+"=7D[S*TSF,)//R:>#S_)BYTVN[V^W_EVNWW>UW/Y>+N]S:^7M[7S= +MO]]^I=6X.@08LT%X9;\UH[YZU?]I^/D\OK*3S;S<&H\ZI;4>:]WN7:W+6?E. +MG]NF<*^SWZ&NI>Y\]@>XHBG[-,FQVNC1&F7EKZ_;^>>&;=M-]RO]R6Q,V[7Q +M]UNY_/R5\6'@VMWY^Y_*7J]ZW"U>)Y2#MIG"]S_/M=SILB?70"+N_Q^:)BMT5M'RUT!Y,N +MF58JZ^7YDJ0K]#(FU^I-ATV"VS\$F'[EWH\]MIXE%3Y9W#?&-%[5;M=_B]OV +M3?G:NW_#M_Y?RP"\T48M\C\7Z9C/N*SQ>6MLW;QV24(K^>5ED'WX>_!UZZ"I +M\ZTTQ*BFBCL+E,"'%O==0`M0_C@O@T)B0PZX&CDP$/6^[Y:B)[UDS.A`B;2) +MHBY3TAHH0CKZ=WQ:HI'[OQR2^,LF07O6FT'#'XPSQ\[TR<$0/QY)M.K507^K +M438@;"KV6T^HXO>#N]9P7Z\_%[XR1LW?%I^`B!T0^[)2ON8[_3^L#27P_C@C +MQ[%\3A2Q^0>VU[B'#X*[K[LF5;4MAQ0#3#,@WI&V83^I\TP@3W\;QD3O3>R5 +MT0V=ERV=U'HFFIP2`W\N`3.#'4WJJW_CO&BNY71#`OG4?8S6L>S'[1>VYEYZ +MY0ZADU[EBH0J[,X11@\E+BJ2M)#]3[7%AV/_$HW8 +MS3:J4F"7)VG9N""U\+P?00_Y#UY?)D@$'VESR?20:]2E/\T*#VK=FP&N*`R8 +MVY]$75*!D\N]+6WL0XO/23C-:%]4V))?._:_/-.G<.S=0DA/+4>!1@/L0V9D-?V>YV^[\W;]W+M +M/Q+E[PP+K0L9(BIQ;_;QMT0A^QDJCBY,O2Y!Q7K^&F$$#L4 +M(IPV?.UX/N^OY/M[WW>#ZY!9;7V_73X<,.GF_;LL[=B>":J(=K1?:8C_WE_U +M%LO@R2F?^B,Y>J)9N*[)6&PY%2M.;1(A?NU=XTJ&0YJ5/8\%":N343"]':[4 +M+#-B?^QFI9(S+8H-BWQHU#]-WP=<Q/-U$**K_ICRR)4R0/N#577:PH3) +MD+X$_K-3F&1-N9?7>6DR8^^VJH=IKM3"0!4_+9:,DXNN&=2G:/O;UMX/P^^# +M3-F$3T]^XKZDGFQLKLUOFGSVX?HU=Y--_U+/PV3=?;?A5@:[ECDQ[*5LD\IT +M0(*(!D4@7^F-\ZL=.F[_,[?T4K-QV=J[\(HH1;)=_RWNY_L2-@>6#T?3[16%SIM5&C?@6N@I-IK3C5U0BZ//[LW7F +MY)R@+*#9<_DLO`:-3>&21M@=YJPTI'%?8==IK#OL;AS;K-XF=)/+DO[\\F_R +M3H>%0VOO9N>'AB7];JX%HZDC%_9S>R[>[R2;8^WSV[>2:,K1&)CX=CE<;[T4 +M/$KV-S,#N:2CZXW +M/:13TJ4ICF.KISXJPYR%8B*IZA@]C[^&Z^NI%[EWV9J`DP7-;I&0`7GLT-*T +M68S:+\.Q/>JG!?O'R]*)XJ40HNGGJ&T1HO*M0CU82;3C<@4)7\XXRE"M,F2Y +MHB*4)1DA>Y2<:.YXO+JDV(HQ3"9/ET66.(]*D+LQ6A?R9YJGTW3],1F^3Y8H +MT++UY"YRQ[8S5=:5`J>NKS,ITG\'^??_I]/.Y,K?$MC2B9V>2W#HFE!> +M><+!<\,F]7LQ^(@>F``9?OEXJ59OBZMCL3=$T/^#+Z)<->>$Z3=@@)"6UA"@ +MG[ZT-/R%.X)$2=[:[/6%R#Z8@+:FN>C,5?.!Z)MIB8OTD5>1Y#1[AS:]=7T> +MC-2PU;[\H5XQMF3JV4_#(LMIIA&[Q\4WBE$7LY>LW)],N!M&&8+$&NLW%::H +M/1'^<.?!!2N^*^:JZTNZIO['HZWV*5$ZI^.B)=@[49[CTX6Z[MOX:3A[!-[@R\$PT_%B!_S::N)WG[ +MDRSIO;+?Y)NB?]:&H!DKZM6A=.$5ITON@!OS2`OS98! +MKRTA]RIG2&S-+"(-RP3.Z(1-,D;&.G)_N<&?=GTT8C&?BB+081P8J;YEFT0O +M<#-]ZBA?WJ7(VYI7T$6J(H%O/=R[O1/OPS\%HRTQ.P6-S_89W^$B1>WM_W]:^+Z_O\/VW0PC;,1F-\5_T3;WW^$G=7S2NQHK7/-GV[9&[-W^]W0O+46H8O^NP,(6TJ*I[5+VDH7: +MMJFWD\%L/W=48F?+V?HMEC_W@M9]`D3PVH#5`,.'`U[[<@I)`>D5RXW[L(,+ +MO0ROMSZ-.+VI7EK.`(N>=2$O++<665H0!*O'2Z5^39X&M@W/%$2M4^7DM&]6 +MB\`N2LY.,O8`,OQ^4SP>?++_.'3#8OEZ772$\J'OP8XUU,Y^>25^U31Y-WS7 +M6*8JEK'K[E@7_TVZ55_\>[!`NMGF)!N[L)'4#ZX(_LCYGJ6C-N>Z@O_T^R'^ +M)5)!Z90@_0JF!V<]DI49DWEMC-J'+7_:3'^PMGP;Y^K-Q5GGWK6HZ\J]/?G@T>'+Y/AY#YC6R#L^^NS4V!] +M[>$9=_#-^>7X5YQ:/N])HZG>GVP[.M;M739"G;EGOMDXM'?A*'ZGB/WW]?*4(EW^38Y7>1-^V#9$P++5>PM*4<3> +M/>PCY'7=5\+T0VKKX89I"YF#(\PH//6;$L4>L6B6':N\/NPS1);FR[T1//Q3 +MR?ISZJWCP2D-W[ +MG*'JXT[=TSK$DBCTY@M/R^$)VSTA[[V]JW4K,:@OAQS5T++<3X5R[7'QSNC% +MK'_6="8K]PYTS6L;\E`BWXTEL75YGGK+WJ4!TI(S:[L$CNI.@2B0%CT!3P]1 +M<7_27E5!WL;UG(N'')M65?Q&6SSAJI23WR\^H]MNBL=ZR'M)H4F33TR$W1T! +MU=C,0'SN7BJ-W,"K +M%QOO<]F2M$4\.A9IZZFT[_4OR[58EPR>UW)#>BB1<9;DY>*RMA*`()49ZEM] +M[,99IRW=?X`BXYHAM7]A=PS5P:=(%57=H108R9U)M\_5GT1&I/[?#IJ3>EXI +MW]Z74FYU1#*^K[YCKT*]Q,H,NF!)0^KX-/QR6K:Z_TYZ4R4X:VK#LH2)JNB$ +M8[T?'KN,61)H33^BB&[.QJH>ED;6]%_Q0/#$=HVN3L=GZ*<_0IKRM7YTBU[1 +M.-)9-O;/IHEM8H,YE_^2]FQ].BW;K";R8T6Y*`+::ZK0:[ZIJ]L^HH::SZ +M/0Y^ST\ZIWSJC(4+X?98M;C_]N])^ +M(53HZ*8TX($G+]VUY:-9>_'+=/@S=.W5+PHZF*`B8X\IGRAJ5\/J^%;0VC`[ +MLANY6SC\^UV?3T2W"A)UKGV"9%E\J:VMIH[S-1!JC-?>^G[*^E5@":,NF"+$ +M>>!?+S1]TZ/QR:]VYDW?-9G93%!]<=+2*AF2_R0N-8<[Z+/N,FU8=3)9=PZYG:1V/BAP2>K'@EBF-DRU2#88(6$37WO%*&F1#_"TYZ-5N; +M_3EK6(;/E_=M3Y+>MV.S:-R9R=+2!1:)9\H(>A^8_OI9&OGQN&^O)=DR\5NE +MI<>J8T=Z]\U:M^>W#-2GF$1N?X[Z_Q30X9P,S@TNI<0RT9N9=,@2Y[JZ9@6Y +M.&CA_ZTU0XO7;J&[HA]$SP&AY6/CNY=1R#Z74\][R<9;Y<;HB?8KSP^*[E+[ +MR[NK`\G_J%%BE,P\+13D&W1H&3>JIRQ0EFZ)+$P2#+0XKA#XTX"U@?OKR(3= +M,;ZANS"2[L,4V<*F^XJ8>]+EG[;^DT=&6M)AM.GDZ%=BL$6+J_`'R3 +M:"GO.!J6#H<&8LH[&+YXWW@S_,@/BB'G%U'[(@1/A[T1\&;33W[]_YP-;%R6 +M,8U<;LI*(XO'DW:VKDN\D]\C)@[=KY,=N\5H47JOL +M4ZANF2@AJ?QY)>G-Q8UH-+K86YG4L;$8ZFW4,-:S/!>Y*.]LA1<4TZJ0`V[Y +MN2DN3TA`W=TTX]IUHKHK2T>VI8@OJ`F(4O[-6/?Y+UY2T);XWYS-`=]B=T@I +MN*(CHZESQ]6;1YL8MD?WT!6\.>OCE"(4OG\'R??L=[^_@E!/TN8_8SOQ^=9* +MP=);;NG!/TN`>3";_*,7[/PTHS/XL]$S*:T;0T??*;5WCEUN5$:=14A&D&D< +M7DRX1N;>_M=0#F6RTCFW!YY.0>61>#-$51:-G#Z2DQ)OL\G3X6L/SBN[CT:D +MNI6[CS2"[)Q%!+IS^+ZE +M"(]D7KJ7+_U\?Y_GRO+3Z$*QX-CEG&;*V/'AYXQ.TQ7Y9CJ8C:-JTJ9/)$LM +M2`7EE7CU-L(6T.8GGX^+SP]HLT^#]-1\MWBYCXS,L`*04ZELG,ES,U'9#]T; +M\&3I!];V3@R>2(Y>\.6=8T_<+D1EBZ8]$09U-5KR>/%(AO[=%W*8IF3K=F= +M(3Y101HFZ?XV/OB2R<=PV:.D([?/+*I\5/[U.&*I4-8A"E@-W[?#[>9`,=JN +MT53[_MZ_&Q%&/!6DY^S:EH&B]H;W6=?&+$X^3I[)T-=T`#JJ,X5CEJ0,QRCI[7LGM?/`\\<4W8*9?^ +MD,,O3S%F"E.^;3>?0WW>>IKO_9>DRVB1N%4W'0*BD5I1V$;(E;Q]4/@P4,VZ +MRG_8>V?EFV6]8/EO]#Y-BGT$,F-=>KE[D,/F4)/2E+O11(C@VS=3WJH=&S#Z +MUEZW[GGB +M5L]F^A*F/;6",TZ&LR0(=$R1_?CEV.MD)6N.KNKL)"Q]C\_HG!EWY1^S8%W1 +MSF[^_8,BDQ-P23TP%O/7MD:^9F7"DG5KZH@:6-4Y/:%QS[$'F`C)I/R!U]M& +MYFTQ!/OX4'O]SA6I$F:"1B$$U2@_1W"QN$['*?N_`&^2.#+J/L.G?]F?>CJI +MNK$CI_5O9J.QOS:W,1N--&?B-]:,H?U'QXJ4>>I7NI? +M1R/\8OR>]^QCRK1LUPB45VXF)M"(-)BT0CA;F_GW?-=7*MFR5-5SM01[FSVO +MWGMMD!--4&EKBGP1DJ88\Z<+Q0K^VX%`JM$UDW!)RG0!S>S\]?#>GORZJK@^ +MSA6L;S9O8I39_"'OH.#V]/BAG(V$O\7]<7*?]>3$)3NRO+/P31;-_)R6YHM+ +M0=07,?8;/HRQ,%%"/5&Q3C&DV-:7HCD*RBIP344+N7SCMU]1`IE!*18+-`IP +M(57D$KG&-<(7DY +MQ0\\AF,WYT?P5VI1P:@`L-U3U*G[SQGM1.<-NUYZ-KW-IL.)=/+&(N_,E[0F +M3(33DOBB;SR1#I&-)K$VB]<9O.UU/VUV`EXYYN&H&=2NDZ8(Z9O( +MBZ,PWF5,.$)J9==N($)UFSVGE+LF]^,C,^3R8.?R5SRW@YK[_)6'J/1/K5N= +MVU:==F-[GXYMU_&.K5;UCW(F0`EQ]+ +M0N_R4RA9\7XL;N@+'&K@RU%`R/DBIE-9)#F4\F%76COU^S6"\Q11HS\5#NMB +MWFBG2F\R1E=M,0K5'KQ)QW_DI,04KDYT:D./HU!O:U?RO83D,0BGM313Y@:P*+>I2SWB[-/H?C +M[FJN] +M(N]^.:AM66IM<[Y)96_C\U<#HQ9HBF+LSDCZ>`7TJ<]9W3BG;N?)\VQ/N4'` +M`W__VG1P```````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````/_E+Q/[,7]KU/_G_________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_________________________________________________________H!' +M_(O_ZQ_Z?___________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________________________________^@1_R+_^L?^G__________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________H$?\B__K'_I_____________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_Z!,`=$5#(T7Q9V;W,^%<[-7=@+1MD#N]V=(H:G#Q/=(`AA--ZA)I@\`SL8V +MT\;D&?>M2!R0!DOP\\./&QXPV1=7?1(/.9RZNKNZNKKQWGQ*OX1?J_5X.4KI +M7=_DN>RP```````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````]7?Z>=_S]7/Z'_'T_SZ'J7G8OY\[H<_U^_<]3X +M^G*78Z'%@/H>I'0Z,(3<_)L6QFZT#(>Y#/O>'I]'H_<*=:?`W*=*-,E-&B1W +M%@F0W/=*D#ITW8;Y_W5:/4@8RP_?AFD7WKCS/@7)H]+L1IJ[2+S*'#(,7W6U +MN5F<73-";Q6MA'#.]Z>C;#!%T6]3K7X`N=_9U9--3^T'O#]'T[_//Y +MWTH>;W,V>CGY_Y/Y=C8\L&01#`V?N9^_=`^UZ?9L_?$K_ +MJ*P%"\:XBTSX"YTN57_ET:9PUG?&KC!T#(XU@Z(H)M.MCXVC`DF9QAV?_!Q5 +MLW*/.QO#/X!&?\._%/#TZWLE@T_]^?],.0'3\5*>/1U$C3Q>`0@L::NG"!4M +M/W.T^S^GN>CFZ?6@N@2`<1RL`U7+CRC5@29!,>/[>FKU&*UKZXJCN%^S2ZG- +MB`]*#(YVL,%!/I[OE]^<$ZO0T?!^AO"!JK##VOMU/'5V]*KP7&DM7+]\;=-H +MXXN9'5&>>5N:/[)FET[,S)4R"@?.L\4A&IYKPQ9_[CKK%!HKUQBB(:<8,UV_ +M-'[(2!SS=.NH^VGK^Z^;W.WI:/@TY9Q7==8@:>N-D&]2`E2VI'?K^JII/-^H +M[PL(JDL>0926S!'E@D'Z/4ZO[UJ7UYNM73C"^N^E3Y2$"7BNBU^R"E2I1D=P +ME$H;YNE7Y)DOZ]5/HOB]7EU^R#100\_[L,6CKIZ6W`@/8WVK_FF*$_KO#;^V +M#)]OZ?7_Q\W2O?*_E[G_M9/,#=';TL_P1M6^A<^'[J3CI_=%OP05+,6G$Q=' +M@2Z<=_&_=!=YU9\&$S#7GH4=(8;++7&-WKO1>*]6>HEE_XWGX02:]6K/] +MXB"R<="=Y>7(3=$=F0(J@EH6`N249QM"FA;\9"HJRY"EB(==`E[4*3L?1-+I +MFX9[CNC@V3=\GQ;DZ96QH>C%MN4HE9"R03,]B.#?5\%/.LBUOVKNPM[@^$)19E-9HX1W=F7.%0/S:+=WTNWQ +M[?%D&'W%BA>CT^2_N3S>?G?TSN=&/:_+Z57+Y`7C[ +MV>CV_E_5Z)\.5+6J$[GU[:;\$,UFB(S)M;N,(9UTC-H +M*]E97YMNJP8;'OU$%Q,%3>:<5^V)EF$<[RK"1;16R:K?,7^*A*UT^/L>2LDC@BA\&]:KUY1*!KO.(#XQ>T;%?V]5\\O=X[SV26E.7R): +M2WLQ!=O/1QY:=Y5C!'EB+X"TY>YP_'PB6[+8)7S4WX\"FY"LR-6K[E+GY7!= +M&":IE5-4MJM5YI#+X.GL:LC4NO1!^SJH43I[?:Z_2D][:;H,6/67;_KG;^D+ +MYA!V$Z)91L=QF'<6TMB93A_ZS*^)IZY +M#*L*$MR>X\/'_Y!W"\V(_Q2_99DTHAIM4N3(&D8F\YT[>I!0VQXHPF1=+2OU +MV5A;ITT1K=UDAQF-MEYTAMRDF/PJ?A^'L^&5O@V$/OBWSX'TX?YM1A8JX@H5 +MA[?\B[P-VT]9JV!^($I<,I@HHCHRJ`UP$.R(P9WN7Y8-.O@>+&:>F92NE<0K +M"3-[^(;W0Z,SW\/I\T$Q'\K[XMLI:\C/*7JR#SB?JCS,B`?>S',6^[-)MF6D +M!KT>KW$@3(G!Y*G\C\&=M^BCM5E-JF5GV="Y?,WTA1]>5[YY2"EY=B@W4D92 +MM\(W)C2X)\'O5]%H4V.[&U2K<-I55B[9JP-W:WM2$"#Q`=LIB1U.^>/1"L86 +M@R1[/B-^N290L24:_HFJ;T^JX8#EG+23(L5CWXI0<>E@NCQV!VVR"IJWZ?#W."E69,E;N6D1Q +MA].1D/-@3!LTZ21Y&L3=?!MXT]Q^\"@\2+\AS>QU1C_?(&-AWY&=ZM2L/W5Z +M*0"EH!E2S="%%-;8U-7%#R0J130TYF=2OSU;-&S'+CANGK,SC=&>(Z+UD6TK +M8!/`%HYQ\>5#O,`9]84WZ=*T(]W!L[&+#$U](CR^.F4,]?OT)8GNKZ_?T;9( +M2IE/6@#S.LB3I8NVWTH;#KXQ!483RP0ZCQQ^G.NO7R*W43+\ +MR":5G4`$X9UVN!,O^03EJW5!F6RN_CS@AW-+>D`;.@3< +MORFC%-UJ&U:"I6^72'_I98>XNMNSRUH!(0D]BG@. +M.)>9\:2Q0A7X)*]XS%3&>,HIR)(XDVI(US+VN$0PY4'6V)RKC*Y)5'0EF#$M +MJ-0$,[),L*"*!.1> +MV8?*4L?W;&8'AC%2$JYLY3DZI&U>+!=97.U4/!&U7O'&\?:\$G_%6G(=&K1N+?F7:"^X,+FCH5:1/&] +M(^6JGIQT2FTJLDK!]'PS[%.C9XTD7\-=ZSHYYR^U^M&#HR1V/UYW;%I&'1;& +M7!+PT#\R-NTI$$Q8`LVHY.]/3`BJO++^L?:RQ:$^R&>7/N +MD`WM69`/+M7(R0=P=79>:\;L^2ZU97C+L^GVKG^#TW\:2FJB+%GB!(2\=NP1 +M(<6"5%LO%@KI:E?-7V],$ZT`M757:1Z'6U-?._&&E?WP]NKS4C<"`;C.8]CQ +M!BM72J$E5NT*L\F&:";.5.,-%=+?*\UG`5,@7=DJO:WDRW(/P:FUD]Y4,`>C +MSZTM+[A_N)*];$RW->5"%N%)MZ7V[<6/7'8YOT)*H&#T2*4L5\X,Y'C_MY!G575T. +M4HO8U`5?ERZ;"K8A#Y,LG]NE`DK'\Q.T9`X';653%K:](_(QA>^+2^ +M>[@GAO2HN67TP&V+V[7(QR=>TA6TZ>QV+DJQ\$\FS1[L2UE=?&N6+FUY2VEM +M0D1B#`ZVLGGC8GZ\9-]1AK*^;REXKANB7SD;*F;QO,[#A5*VXU)H`6;K9FG3 +MV-;3K]KO^]^LDC:SO_O&;YY3V.E#Y"9QF$KIFFKY"9FU*]0XG[(O[[ER9RD@ +M%&#\((LLKZ\/BA/TLD)_N:'>[&7LECO;NSDTPJ'7S/X]#GYL66'D]O^4&0.[ +M;WB9B^69-5ZZ_Z/'4@793?W*S&5ABF5(Z+#&&O8R/+QBW.J[5===>%4H>]+N +M;SP]ZG1FWA[._!MQ\N=K;'EMTHE>-M*X[6!'<=Y-U]"8W:#T@+7IGD>CI9M& +M&>.;5O>0#EU.UB];V=C0R[$BLIW[Q)QJ/0/V#HU7X=`C"F\,QYYK5T.+GM]E +M,5$E_B`"O'+:-/.C,7C^`XXOA"`/^F\;7XEV-VQ=;,\?<\%QV$T=8UQ]#241 +M[8/!M/(1@V6M0OC#0F\U;XFEIQ#+?D<&"R%>WJC:UCE2K!Q$"R8W4*+6PP5) +MC3=3[NI-AI0\D-=[.U[L=,GR*S53#,"R-39V:.&#YNEQ'V5I?^IY(MXJ3&CP +M^7?LW-F7$[3C-T(^][V*[=5!H]Z\N_$XVJ5`!,7FP[.6GOHXEAC;N2>5^._P +M:.ENC)!O0-]`1=\JG&?6[Y/6>7DE"W?8D]$:.X3A?ICD3S)+0U'@?&?4*W@I +MN8KNP2RL),.A]+9Z`C;K*]7^*QF`1^-V>\I3L%7CS)5NGQ;FK(P'$8^#%)G( +M(@:[UV`>;Q*<0!Q\5ZKPJ>/'XHL@_6M+<\5997`>9TB;)JNA#J`*O\,)8SC:N(JU_='9PQ_/;[OSX[ +M@FM0M)F+*VOK-N-[DY0)EF_PYH/(PSY/6;-Z]`Q:(?$XIH]U+:<`_`57/1$. +M1'2O7VZI1SOGEPU;U=]>&25%&B2=;5UH='_[7,N-ZF/X!*FZ%9-Z>62UC_#N +MX]Q_PH]BQ_P69O#7E5?G4U;:&,XL$:M*QY%N70_G]\:7G2F8V)LG5JMB?2]! +M7,!,K("PQ`5(1DKO.+9SA/>%=]V(/GZ/N)Y\$KJ_VYG(^$OJV=X39O\?+M_5 +M>C,V7>,/ONV]K6S9+4LZ2RS38(*`.;HP0Y-"9O1;3F3V!1%6$,R77V?$5I@.YEW@O4DAH?HI1`& +MA?6&>:V++>%/'RGN=[)R4E(R+B`?RW1$ZZ1/PN +M1G*O,52R-R.%R0X0W#%J!]JFZ^CYYE0O?(N\.E4652)9GQ?7:_FZ7]:0A=$?>.)E>72RW1(+E:*LHEEZQ-XL[T6 +MN=0G3XB?PL"$3NLIVS%BD#X7O8KQV]=(8N20U +M5H?WZNGH]KW"T.SV=/N0TV]/0Z?9Z/V=OM]GZ^WVJM]KIRJ:?*(N_-@GV(A7UT99*4%UP*5])9 +MV5W[C;XQK!G?1&M=F*E-[9&R)RK'MX\96;[GU1]6U'^PV*A5>A=JEG5!AT:E +M*+VR"5)5NF?8@YAI;YX0N7,.2ORN5V<=:FU]BS9M00Z^)6VM]4`%&SV]I#02 +M>['39/TYXPGUI/."5;5FN2N'"ZY4MDY)IKT^YH]NYIM7,PM#0GQ`5T]+L:'= +MZO4H'.MUJHR`A*X+#<5G<&N+S1[?3M,5\DOGO;^?"8.A*\7)@G\#!D>+__08 +M+@VG_RO9!Z$@+^0]JQX%,A^*I+D++;=<1HUU*?X?H(RZRD-O&2BL:LAMQO_U +M]N@4GYF5(J+8Z-L@3K8U[T>U=R\V\93!3F7*[828'L//;'E'!S/KRT\&A[^N +M[D#1%60-"QMN\M5O5F^]C=CTO)+\:6]JAD[C9J+T1]^/HQ`%ADK#Y+ +ML:R5?]]:?,9+HW^/3"D>$*'1=&UNT,NT.2QN'C1E2L>;HXZFW-]3:TKMXT9C +MN(/6C.8Y(D%??*JR$2&K(.QMX^ZK/PIGRKC!1I(?4GW=*6-(/N+!D5&?DG(I +MV.KT_[Z<*.B]6&\SO=3IQ_`L%SD6H0/DDFWX?+;]G?T>SU-.%)DNC!T`Z/:Z +M_UY$J+I]WW`[W;T_9/L[NA[%T>M[I]6YS+X?%'_IOQC.QM*H4L`'"M;'1XZDM7I\=CE7+PU;U=C +MGVMD#S7YB*PW*G1T_`G=VW7!PJ?0!GED[(\-L^A7'6/QG +M!%^:5;V$N!/NG`P]%*?^',I,YXFPV5XO\6[%WLVSS5>[5*KB2G#C,->'7($D +M2BV'_(`6`+JK!/-JK^,>*F?Y$SMZZ'E-=,H.\E5_CV*,U34&7A^_@98_SXAJ +M#NPSL4X73K_'#T`'9R#QN6R#L9<:5S#U=5EZ0:'````````````````````````````.:3$/7L`0`<` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_ppmd_use_after_free.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_ppmd_use_after_free.rar.uu new file mode 100644 index 0000000..1363386 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_ppmd_use_after_free.rar.uu @@ -0,0 +1,10 @@ +begin 644 test_read_format_rar_ppmd_use_after_free.rar +M4F%R(1H'``1G=$Q26`!W````>U!+`P0R`'#_J7\`+@TU'`#]`0`7__]"0D)" +M+W5NTQ26`!W=&@`[E!+ +M`P0Q`'#_(````"`@(+<@!/T`("`@("`@("`@("`@("`@("`@("`@("`@("`@ +M("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@ +M("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@(`1G=$Q26`!W```` +M>U!+`P0R`'#_J7\`+@TU'`#]`0`7__]"0D)"+W5NTQ26`!W=&@`[E!+`P0Q`'`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_ppmd_use_after_free2.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_ppmd_use_after_free2.rar.uu new file mode 100644 index 0000000..03c2ead --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_ppmd_use_after_free2.rar.uu @@ -0,0 +1,10 @@ +begin 664 test_read_format_rar_ppmd_use_after_free2.rar +M4F%R(1H'``1G=$Q24`!W````>U!+`P0Q`'#_J7\`+@TU'`#]`0`7__]"0D)" +M+W5N)B8F)F=I9`UD#1T+``!"`````````&%R(1H'``3_________`F@`H2`` +M``"`P\/#2\/#P\/#P\/#P\-3PP"`P\/#PYZ>AYZ>GI[#4\,`@,/#`L,@(""= +M("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@(/______ +M__\@("`@("`@("`@("`@("`@("`@("`@("`$9W1,4E``=P```'M02P,$,0!P +M_ZE_`"X--1P`_0$`%___0D)"0B]U;B8F)B9G:60-9`T="P``0@````````!A +0$```````````````````````````````````,`R`0`< +M```````````````````````````````````````````````````````````P +M`0#``@``````````````````````````````````+G1E>'0```"8&0$``!`` +M```:`0``!```````````````````(```8"YR9&%T80``%1P````P`0``'@`` +M`!X!`````````````````$```$`N9&%T80```"S_````4`$```(````\`0`` +M``````````````!```#`+D-25``````0`````%`"```"````/@$````````` +M````````0```0"YR$````!@`@``0@```$`!```````````````` +M`$```$`````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````(#Y0',6@/D@+5"08]]CWVH/8`(E$)!R)5"08"\!U&(M,)!B+1"04,]+W\8O8 +MBT0D$/?QB]/K08O8BTPD&(M4)!2+1"00T>O1V='JT=@+VW7T]_&+\/=D)!R+ +MR(M$)!CWY@/1<@X[5"04=PAR!SM$)!!V`4XSTHO&3W4']]KWV(/:`%M>7\(0 +M`,S,S,S,S%=653/_,^V+1"04"\!]%4=%BU0D$/?8]]J#V`")1"04B50D$(M$ +M)!P+P'T41XM4)!CWV/?:@]@`B40D'(E4)!@+P'4HBTPD&(M$)!0STO?QB]B+ +M1"00]_&+\(O#]V0D&(O(B\;W9"08`]'K1XO8BTPD&(M4)!2+1"00T>O1V='J +MT=@+VW7T]_&+\/=D)!R+R(M$)!CWY@/1<@X[5"04=PAR#SM$)!!V"4XK1"08 +M&U0D'#/;*T0D$!M4)!1->0?WVO?8@]H`B\J+TXO9B\B+QD]U!_?:]]B#V@!= +M7E_"$`#,48U,)`0KR!O`]]`CR(O$)0#P__\[R'(*B\%9E(L`B00DPRT`$``` +MA0#KZ<.+5"0$,L"`.E)U*X!Z`6%U)8!Z`G)U'X!Z`R%U&8!Z!!IU$X!Z!0=U +M#3A"!G4(B(&P<0``_L#"!`!J`/^QK'$``/^QJ'$``.AX2```PU97BWPD#(T$ +M/U"+\>@DF@``B0:%P'4.A?]T"KE\7D$`Z"@B``")?@2)?@A?B\9>P@0`5E>+ +M?"0,5XOQZ/69``")!H7`=0Z%_W0*N7Q>00#H^2$``(E^!(E^"%^+QE["!`#_ +M="0$@\$P4>C$G```]]@;P$#"!`"+1"0$5HOQ`48$BTX$BT8(.\AV+XO0P>H" +M5XU\`B`[SW8"B_F-!#]0_S;HR)D``(D&ASH#____XO.Z/)!``"+V(M%\(/`\%#_=>R+SNCN2```,_^)1?R% +MP`^.@0```(M%[`/'@#A2=4-0B\[H5_[__X3`=#>`OK!Q````=#:%_WXR@_L< +M?2V#??P??B>+1>PKPX/`'(`X4G42@'@!4W4,@'@"1G4&@'@#6'0(1SM]_'RM +MZRQJ`(T$'VH`4(F&O'$``.C%1@``@+ZP<0```'40:@>-AEA*``!0B\[H8$@` +M`#/`.8:\<0``=18Y1>P/A-,```#_=>SH:)@``.G&````.47L=`C_=>SH5I@` +M`(O.Z&8(``"+SNCF_?__9HN&PG$``&8[AKA*``!T(6I\Z""/``!0C888!``` +M4.AZJ@``65GH@?W__X!]"`!T>@^WCL!*``"*AL!*```D`8B&LG$``(K!P.@# +M)`&(AK%Q``"*P=#H)`&(AK-Q``"*P<#H`B0!@[[(2@```(B&M'$```^5P(B& +MM7$``(K!P.@&)`&(AK=Q``"*P<#H!R0!@+[,2@``)(B&N'$``'83:@&Y?%Y! +M`.@C'P``,L#I3@$``(3`=`WWP0`!``!U!3/)0>L",\F`OJA*````B(ZV<0`` +M=`B$P`^%[0```%:-3>#H+9\``(N&J'$``(N^H'$``(N>I'$``(E%^(N&K'$` +M`(E%_,:&MG$```#K58N&I$H``(/X>G57:-PR00"-AA!8``!0Z`2:``"%P'4' +MQH:S<0```?:&Z%<```%U%X"^LG$```!T%;@``0``9H6&P$H``'4'QH:V<0`` +M`8O.Z(7\__^+SNCW!@``A") +MOJ!Q``")GJ1Q``")AJQQ``#H<)X``("^LG$```!T"8"^MG$```!U(XU&%U"- +MAMUQ``!0Z,^8``"-AA@$``!0@<;>=0``5N@GF@``L`%;7U[)P@0`5FH!B_'H +M[=0``(M&!(L.BE0D"(A4"/]>P@0`BT0D!#M!"'8+*T$$4.C*U```ZP.)003" +M!`"+1"0$.T$(=@LK0010Z"+\___K`XE!!,($`%:+\3/)C88P#```B0B)2`2) +M2`B-CD0,``#H*M@``(V.:`P``.@?V```C8Z,#```Z!38``"-CK`,``#H"=@` +M`(O&7L-6_W0D"(OQZ!+\__^$P'4B:GCHAXP``%"!QA@$``!6Z.&G``!966H" +MN7Q>00#H1B```%["!`!6_W0D#(OQ_W0D#.A*0```A,!U!#+`ZRYJ`(O.Z,?[ +M__^$P'4?:GCH/(P``%"-AA@$``!0Z):G``!968O.Z%`]``#KT+`!7L((`%97 +MB_GH3.4``(MT)`S_=@2+S^@,____BT8$AP@0` +M58OL@^P,4XJ9!%@``%:+=0AJ`%:`XP'H>@T``(3`=0\'G`HU'`5"+SNA] +M_O__5_\V4^B>V```BP;&!`<`_S;H#)8``(OX5XO.Z%W^__^#?0P`=!6+30R- +M1?10Z$+___^+30Q7Z%S^__^%VW1'4^A>E```ZS^+70R%VW0X:@"+SN@+_O__ +MC46\G""`!35597B_'HMSL``(V.(`P``,<&X#)!`.BVD@``C8YH#@`` +MZ&:!``"-KI@3``"+S>BG7P``C;Y\2@``B\_H*=8``(V.T$H``.C6_?__C8[@ +M5P``Z,O]__^+1"04,]L[PW4"B\6)AI`3``"*@($M``"#CFA*``#_:AB(1A93 +MC8:X2@``4(B>L'$``(B>L7$``(B>LG$``(B>LW$``(B>M'$``(B>M7$``(B> +MMG$``(F>O'$``(D?B)ZW<0``B)ZX<0``B)YX2@``B)[`<0``B9Z@2@``B9Z@ +M<0``B9ZD<0``B9ZH<0``B9ZL<0``QX9P2@``!P```(F>=$H``.B8DP``:@U8 +M9HF&PDH``#/`7V:)AL)Q``!FB8;>=0``B9[(<0``B9[,<0``B9[0<0``B9[4 +M<0``B9[8<0``B)Y@#@``B)Z($P``B)[=<0``B)[!<0``B)[<<0``B)ZH2@`` +MQX:\2@``Z0P\``!6B_'HS/____9$)`@!=`=6Z*"8``!9B\9>P@0` +M58OL@^P85HOQ@+ZS<0```'4',L#I[@```%-6C4WHZ`2:``#VAL!*```"#X2( +M````BX:\<0``5VH`@\`4:@!0B\[H0$```(O.Z"<"``"+?0B+7P2%VW9.BP=3 +M4%")10C_%7@R00"+=0R%]G0YC4,!4(O.Z-K[__]J`(O/Z)S[__^-0P%0_S;_ +M=0CH!=8``%.+S^BA^____S;HR<((`%:+ +M\>C6/P``BXZD<0``.\I_(GP*BXZ@<0``.\AW%HN.K'$``#O*?"Y_"HN.J'$` +M`#O(=B)J9^@%B```4('&&`0``%;H7Z,``%E9:@&Y?%Y!`.B!&```7L.*@=A* +M```DX#/)/.`/E,&*P<.`N>1*```"=PWV@?1*```(=`0SP$##,\##BH'D2@`` +M/`)V'(J!V$H``#/2).`\X`^5PDJ#XO"#PB")D?1*``##@#WX34(``'0*N?A, +M0@#II=@``(M$)`1`P@0`5HOQ@+[P2@``%',5]H;T2@``$'0,N.````!F"8;8 +M2@``@+[D2@``!G(+R\9%_P'H2#\``(/X"'05B\OH#O[_ +M_SEUS.G(!P``QD7_`.MRBX.0$P``!1@H``!F.3!U,FB`````4(V#&`0``%"- +M0Q=0:@+H.1```(3`=1:+R^@W-P``:/\```"Y?%Y!`.C8&0``@+O,2@``)(VS +M(`P``!K`_L`/ML!0BX.0$P``:@!J`%<%&"@``%"+SN@=$0``B77D:@>-3XV#K$H``%"-3N-N[1*``!7C4W,B8.P2@``Z$1Y``"-L[9*``!6C4W,Z#5Y```/MPYF +M@_D'```BT7T`8.H<0``@Y.L<0```.D;!0``C;NX5P``C;.L2@``I:6EC;/`5P`` +M]@8"=`^-@\17``!0C4W,Z'MX``#V!@@/A.D$``"-@\A7``!0C4W,Z"1X``#I +MU00``(/X=(V#T$H``'0&C8/@5P``B_B-LZQ*``"EI8E%[(/`#%"-3R-1A!0C4W,B47XZ!YX``"-1A10C4W,Z+%W``"-1AA0C4W,Z`9X +M``"-1AQ0C4W,B47(Z/=W``"-1B!0C4W,Z(IW``"-1B%0C4W,Z'YW``"-1B)0 +MC4W,B47TZ)%W``"-1B10C4W,Z,1W``"X``$``(U^*&:%1@AT&E>-3)EMP, +M``#HQ>___XM-^(L)`\&)AN`,``"+1?0/MP`3U[__#P``B\^)EN0,``!F.\%S +M`P^W^%>-A83O__]0C4W,Z%AW``!H``0``(V-A.___XU&,%%0QH0]A.___P") +M1?CHL,D``(M&!(/X>@^%AP```(M%]`^W``^W?@HK^+@`!```@^\@9H5&"'0# +M@^\(A?\/C@T!``"-CC`,``!7Z)_U__]7_[8P#```C4W,Z.QV``!H[#)!`/]U +M^.B-C@``A<`/A=T```"+AC`,```/MD@+#[90"H/`",'A"`/*#[90`0^V`,'A +M"`/*P>$(`\B)BVA*``#IJP```(/X=`^%H@```+@``@``9H5&"`^$@P```(U- +MK.BJ$```C86$[___4.C"C```BTWT#[<)C;XP!```.\%U+6C_`P``5XV%A.__ +M_U#H\L\``&C_`P``_W7X5^@7SP``_W7X_W7XZ/+'``#K(6@`!```0"O(5U&- +MA`6$[___4(V%A.___U"-3:SH41```&:#/P!U%+C__0``9B%&".L),\!FB88P +M!```B\OH./K__[@`!```9H5&"'01:@B-ACP,``!0C4W,Z-YU``"+100#&@\!Q```!Z*L0``"`??\`=!5J`(U-S.B#=```]]!F.8.L2@`` +M=7+_=?CHF,<``%#H4L<``%!J:.CC?P``4(V#&`0``%#H/9L``(/$#.M*C;NX +M2@``C;.L2@``I:6-@\1*``!0C4W,I>AV-3?@``4%;H/IH``,:#>$H```'K-XN#K'$``#N#I'$``']0 +M?`Z+@ZAQ```[@Z!Q``!W0&CP,D$`:FCHI'X``%"-@Q@$``!0Z/Z9``"#Q`QJ +M`[E\7D$`QH/`<0```>@8#P``.7W,=`C_=R`0``@+X`6```)`^'I0$``#/;.9[L5P``=1#V +MANA7```"=0>P`>FF`0``C;YH#@``B\_HBW(``%>-C0R=_O_HN^P``%.-C0R= +M_O_HW?(``#E=#'4@_[;P5P``BTT(Z(/P____MO!7``"+10C_,(O/Z/MS```/ +MMX;H5P``J`1T38N.D!,``('!&"@``(E-_&8Y&0^$`0$``(J.`%@``(#Y)!K2 +M)0`$``#^P@^WP`^VTE+WV!O`4XV6'&0``"/"4/]U_`^VP5"+S^@^B9U0``C8T,G?[_Z$#P``#K*8V-#)W^_^@S\``` +MZ6[^__]H<`0``.@[?```4('&&`0``%;HE9<``%E9,L!?7EO)P@@`4U565XOQ +M,]OH/O7__XOXA?]T.8ML)!2#_7MT"8.^I$H``'MT)T/VPW]U!>A]Q0``.:ZD +M2@``=!V+SNB3ZO__B\[H!?7__XOXA?]URS/`7UY=6\($`(O'Z_565XOQZRR+ +MAJ1*``"#^'MT+(/X>G43_W0D#(V.X%<``.C)ZO__A,!U&XO.Z$GJ__^+SNB[ +M]/__B_B%_W7),\!?7L($`(O'Z_=5B^R!["P"``"-1?Q0_Q6L,4$`A``@V7P`(-E]`")1=R-A=3]__^)1>2+10R)1>A6C47<4,=%[$$` +M``#_%;`Q00"+\(7V=00RP.L?5_]U$%;_%;0Q00"+^(M%_(L(5E#_410SP(7_ +M#Y7`7U[)P@P`58OL@>Q8#```@WT4`%-65XVUJ/O__W0M_W44B\90Z-&'``"+ +MQE#HGX<``/]U%(VT1:K[__]6Z+F'``!6Z(F'``"-=$8":(4```#HMWH``%!6 +MZ)Z'``!6Z&Z'``"-=$8":/@R00!6Z(F'``!6Z%F'``!J6#/)9HE,1@)>5E&- +M1:A0Z!6$``"+10B)1:RA>%Y!`(E%L(V%J/O__XEUJ(MU$(E%M(M%#+\`!``` +M5HEUQ(E]R(E%V.CU4@``.\9U%E>-A:CS__]0Z-S^``"-A:CS__^)1=2`?1@` +MBQTX,$$`C46HQT7<#`@!`%!T"/\50#!!`.L"_].+^(7_=2K_%3PP00`]`C`` +M`'4;,\"`?1@`9HD&C46H4'0(_Q5`,$$`ZP+_TXOXA?]?7@^5P%O)PA0`58OL +M@>P("```4U97,]M3_W40Z,%2``"+30B)11#H<\$``+\`!```Z:P```"-A?S[ +M__]0Z(12``"+\`^^!E#H]DX``#A=#'0A.L-T!(@>ZRY3C87\^___4.C,40`` +M4.B93@``A,!U<>L5.L-T$6C\,D$`C87\^___4.C_A0``@+W\^___*HMU$'4S +M#[Z%_?O__U#HHDX``(3`=")75HV%^O?__U#&A?CW__\NQH7Y]___7.C?OP`` +MC;7X]____W48C87\^___5E-0Z`I2``!0Z,Y+``"$P'4?BTT(5XV%_/O__U#H +M9\(``(3`#X4\____7UY;R<(4`+`!Z_6+B0!/``#I`<$``(N)`$\``&@`!``` +M_W0D#/]T)`SH[<$``(3`#Y7`P@P`5HOQC4X0Z++1``"+SE[IJM$``%6+[%9J +M!?]U$(OQ_W4(_W4,_[;X3@``Z*O^__^$P'0$L`'K+3/).$T4="2+AOQ.```Y +M2"!T&6H%4?]U"(O._W4,4.B`_O__]M@:P/[`ZP(RP%Y=PA``58OL@^P,4U:+ +M=0A7C48P4(OYB44(Z+Z"``"[``0``#O#75OI']```%:+\>A-____B\Y>Z91+``!6 +M5XOQZ#S___\SP+^H````5\:&PS8```!FB8;4.@``B(;T0@``9HF&]$8``(B& +MP#8``(B&P38``.CUA0``687`=`F+R.B6OP``ZP(SP%>)AO1.``#HV84``%F% +MP'0)B\CH>K\``.L",\!7B8;X3@``Z+V%``!9A)A@1/``#HA84``%F%P'0)B\CH +M)K\``.L",\!?B88`3P``7L-6B_'HXDH``#/`B\Z)A@!/``")A@1/``")AOQ. +M``")AOA.``")AO1.``#H"____XO&7L-5B^Q=Z?J;```SR6H(B\%:J`%T"='H +M-2"#N.WK`M'H2G7NB02-P%%!`$&!^0`!``!\V<.#/<1100``=07HR/___XM, +M)`B+1"0$5HMT)!!7A?9V&_;!!W06#[81#[;X,]?!Z`@S!)7`44$`3D'KX8/^ +M"')_B_[![P,S`8/!"`^VT,'H"#,$E@(,P25P%%!`(O0#[;"BP2%P%%!`#-!_,'J"#/"#[;0P>@(,P25P%%!``^V +MT,'H"#,$E@(,P25P%%!`$]UAC/2A?9V +M&E,/MCP*#[;8,_O!Z`@S!+W`44$`0CO6C3MP``BT7\)?\_`(!Y!T@-`,#__T!U0FH76?]U&(U%T%"-A1C___^- +MM73___^-O1C___]0\Z7H0K@``(M%_(I-X)F!XO\_```#PHM5^,'X#HB,$"\" +M``"+^O]%_(%]_```!``/C%O_____=1B-1>10C85T____4.@!N```C9\?`@`` +M,_:+^XM$M>2#910`BTT4@T44"(O0T^J(%T>#?10@?.Q&@_X$?-ZA:%I!`/]U +M"&G`*@$```7@54$`4.C5?P``@WT,`*%H6D$`#Y7!:<`J`0``B(C@5D$`@/D! +M=1%J"/]U#(V`X59!`%#H>WP``*%H6D$`BDT8:<`J`0``:A"(B.E600!3C8#` +M54$`4.A8?```H6A:00"+??AIP"H!``!J$(''+P(``%<%T%5!`%#H-GP``*%H +M6D$`0(/@`Z-H6D$`BTWX,\`X11!7#Y3`4U#H-WH``%]>6\G"%`"+=11I]BH! +M``!J$(V&P%5!`%"-GQ\"``!3Z/![``!J$(V&T%5!`(''+P(``%!7Z-M[``#K +ML0^V1"0,4/]T)`S_="0,_Q5P,D$`4/\5=#)!`,(,``^V1"0,]]@;P(/@"5#_ +M="0,_W0D#/\5<#)!`%#_%6PR00#"#`!5B^R#?0PP="2!?0P0`0``=2B*12`D +M`0^VP%#_=1BYB%Y!`/]U".BU;P``ZPW_=0BYB%Y!`.A7;0``,L!=PAP`B\$S +MR8A(!(E("(E(#(E($,-5B^R#[`Q35HMU##/2B]F*#D(SP%>+?12)7?B(30\Y +M51`/AJT````[11@/@ZD```"#>P@`=0Z*##*(2P1"QT,("`````^V2P3!Z0:# +MZ0`/A/H```!)#X3/````20^$J````$EU7@^V##)"A,EY?(H<,H/A?T)!08A= +M_XE-](7)?C\[11AS.HM-"&8/O@P(9@^V??]F`\^__P```&8CSV8/MGT/NP`! +M``!F#Z_[9@//BWT4_TWT9HD,1T"#??0`?\&+7?C`8P0"@T,(_CM5$`^"4___ +M_SM%&'($BT482#/)9HD,1U]>6\G"%`!!0>L6.T48<]"+70AF#[X<&&:)'$>+ +M7?A)0(7)?^;KN68/MDPR`;L``0``9@^ORV8/MAPR9@/+9HD,1T!"0NN69@^V +M?0]F#[8,,KL``0``9@^O^V8#SXM]%&:)#$=`0NER____9@^V##)FB0Q'0$+I +M9?___S/`B0&)003&00@!B$$)B$$*PS+`P@@`:FOH!W```%#H/88``%G#58OL +MN``0``#H/-[___\5A#%!`(/X`W5Z5E>_``0``%>-A0#X__]0_W4,_W4(Z')' +M``"-A0#X__]0Z(5\``"+\(V%`/C__U#HOT\``(3`=1Z-A0#P__]05_\56#%! +M`(V%`/#__U#H67P``(UT!@&X!`$``%\[\%YV&5!HKP```.A[;P``4&@`,T$` +MZ->*``"#Q`S)P@@`BU0D!(O"2'0*2'04+?T```!U!8,Y`'4"B1'_003"!`"+ +M`87`=`6#^`%U[\C:_O__:@B+SNBI____7L-5B^R![``(``"`/6Q:00``5HOQ=3!H``0``(V% +M`/C__U#_=0S_=0CH5D8``(V%`/C__U!J=NBC;@``4&H`Z`**``"#Q`QJ`HO. +MZ%G___]>R<((`%6+[+@`$@``Z,?<__^`>0D`=7135F@`!```C84`^/__4/]U +M#/]U".@#1@``C84`^/__4&ITZ%!N``!0C84`[O__:``%``!0Z$!]``"#Q!#_ +M%80Q00!J-6I^B_#H*FX``%"-A0#N__]0_S7\P4$`_Q5H,D$`@_@$5@^4P_\5 +M@#%!`%Z*PUOK`C+`R<(,`%6+[('L``@``(`];%I!``!6B_%U,V@`!```C84` +M^/__4/]U#/]U".AV10``C84`^/__4&@$`@``Z,!M``!0:@#H'XD``(/$#&H" +MB\[H=O[__U[)P@@`58OLN``0``#HY-O__U:^``0``%:-A0#P__]0_W4,_W4( +MZ"9%``!6C84`^/__4/]U%/]U$.@310``C84`^/__4&IMZ&!M``!0C84`\/__ +M4.BZB```@\0,7LG"$`!5B^RX`!```.B(V___5E>^``0``%:-A0#P__]0_W4, +MB_G_=0CHQT0``%:-A0#X__]0_W44_W40Z+1$``"-A0#X__]0:F[H`6T``%"- +MA0#P__]0Z%N(``"#Q`S_=12+S_]U$.CE_/__7U[)PA``58OLN``0``#H&]O_ +M_U:^``0``%:-A0#P__]0_W4,_W4(Z%U$``!6C84`^/__4/]U%/]U$.A*1``` +MC84`^/__4&IUZ)=L``!0C84`\/__4.CQAP``@\0,7LG"$`!5B^RX`!```.B_ +MVO__5KX`!```5HV%`/#__U#_=0S_=0CH`40``%:-A0#X__]0_W44_W40Z.Y# +M``"-A0#X__]0:G3H.VP``%"-A0#P__]0Z)6'``"#Q`Q>R<(0`.GK_/__5O]T +M)`R+\?]T)`QJ`&H`Z"____]J`HO.Z,[\__]>P@@`5O]T)!2+\?]T)!3_="04 +M_W0D%.AF____:@6+SNBI_/__7L(0`/]T)`C_="0(:@!J`.@C_O__P@@`_W0D +M"/]T)`AJ`&H`Z&O^___""`!5B^R#[!13,]LX'6Y:00`/A90```"-1?Q0:B#& +M!6Y:00`!_Q5X,4$`4/\5"#!!`(7`='96BS4$,$$`5XU%\%!H-#-!`%/'1>P! +M````QT7X`@```/_6BSTD,$$`A%P'01_Q6$,4$` +MA6\G#5HOQC8X4#```Z&"V``"-CC@,``#H5;8``(V.7`P``.A*M@`` +MB\9>PU6+[+CD0```Z!S9___HTSL``(7`#X3I`0``BT405C/V.\9T%&8Y,'0/ +M4(V%_.___U#HEW<``.L4:`````&-A?SO__]0_W4,Z-JW``!F.;7\[___="EF +M.;7^[___=2!H7#-!`(V%_/?__U#H7G<``(V%_.___U"-A0#X___K#8V%_.__ +M_U"-A?SW__]0Z#QW``!35XV%_/?__U#H!'<``(VT1?SW__^+10B+N!1D``"+ +MF!!D``"-A?SW__]0T>_HX'8```/'/0($``!S%%=64^BMMP``,\!FB01^9H,^ +M.G01:@.Y?%Y!`.B*^O__Z0\!``"-1@)04.CD0P``C8TK__X3`=`N-C=SC +M___H<1H``(V-O-?__^C[&0``@'T3`'0T4U-65XV-O-?__^CN&P``A,!T(8V% +MK-/__U"-A:33__]0C86R<(,`%6+[(/L#.C3.0``A<`/A)L` +M``!35HMU"#/;4XU%]%"+SHE=](E=^(E=_.A0ZO__A,!T;.CM_/__:@=8.!UM +M6D$`=`-J#UC_=?10.5T0=`O_=1#_%1PP00#K"?]U#/\5(#!!`#O#=3C_=0SH +MT*\``%!HY`,``.A>:```4('&&`0``%;HN(,``+Y\7D$`@\0,B\[HM];__VH! +MB\[HT/C__SE=]'0(_W7TZ#UQ``!>6\G"#`!5B^R+10B`N'0M````5HMU#'0A +M:&@S00"-AA!8``!0Z/=S``"%P'4,_W44_W405N@:____:&0S00"-AA!8``!0 +MZ-9S``"%P'4,_W44_W405NCR_/__7EW"$`!65XOQZ"JS``"-?BB+S^A#7@`` +M@Z9,!0```#/`:/!B`0!FB89<$0``Z/EV``!9A+R.B6U@``ZP(SP&H` +MB\B)AD@%``#HL=P``%^+QE[#4U:+\8M,)!!7Z`H?``"+?"00,]N!QQ@H``") +MAO@$``")EOP$``")GE`%``")GE0%``!F.1]T$%>-AEP1``!0Z"1T``!F.1\/ +ME<"+SHB&7!(``(B>[@0``(B>71(``(B>7QX``,:&604```&(GEH%``"(GEL% +M``#HW[,``%]>6\((`%:+\5>+OD@%``"%_W0.B\_HS-H``%?H*G8``%EH``$` +M`&H`@<9<$0``5NA><```7U[#58OL@^P,5E=H```!`(U-].BFU?___W7XBWWT +MBTT(5^A-70``B_"%]G1'4XM=#(/^_W0],\`[11!\"'\$._-R`HOSBTT(5E?H +MAUX``(-]$`!\#'\$A=MR!BO>@UT0`/]U^(M-"%?H!UT``(OPA?9UOEN%_W0& +M5^A<;P``7U[)P@P`58OLN%@R``#H@M3__X-]$`!3BUT(BH/#-@``5HMU#%>+ +M^8A%\'4X@+_N!`````^$=0X``/]U\(U'*&H`4%;HL^8``(3`=1%J`;E\7D$` +MZ(GV___I40X``,:'7QX```"+AJ1*``")10B#^'0/A+$```"#^'9T!8/X>74' +MQH=?'@```8/X>G5&:&PS00"-AA!8``!0Z*)Q``"%P'4'QH=?'@```8"_71(` +M``!T:(V'7A8```^W"/?9&\DCR%&-AUX2``!05E/H5?W__XM%"(/X>W5"]H;` +M5P```0^$R@T``/]U\(U'*&H`4%;H".8``(3`#X11____:@#&AU\>````_[:D +M<0``B\[_MJ!Q``#H;1P``.L'B\[HV=/__[`!Z8D-``"`OU\>````QH==$@`` +M``^%]0C8;02@``4(O+Z&#L__^%P`^511.`?1,`=`V`?>\`=0?&AUD%```` +MN``"``!FA8;82@``=`WHH;,``,9%_P&$P'4$QD7_``^V1?_WV!O`C8]>%@`` +M(\&`??\`B47T=%*-A4CF__]0C88`3P``4.A$/@``:`````&-A4CB__]0C85( +MYO__4.A!L0``A,!T(XV%2.+__U#H3$,``(3`=!.-A4CB__]0C85H^O__4.B( +M;P``C85H^O__4%#H^3P``(O.Z!O<__^$P`^%O_[__[@`"```9H6&V$H``'1/ +MBX.D,@``@_@!=%R`?>\`=5:%P'4#B$43:@"-A4CF__]0C85H^O__4.@@1``` +MBXND,@``23O(=2MJ`8V%2.;__U"-A6CZ__]0Z`!$``#K&(O.Z)W;__^$P'4- +M@[ND,@```78$QD43`(O.Z+#;__^*AMA*``#0Z"0!B(?N!```QH?O!````(N& +MJ'$``"N&J%<``(N.K'$``!N.K%<``&H`45"+SNAM&@``@'T3`,9%#P#&10L` +MQD7K`'41BH:Q<0``B$7KA,`/A$H+``"`??!)_W7K#Y3`#[;`4`^V@^(M``!0 +MC85(YO__4(V%:/K__U#H97D``(3`#X1#"P``]H;82@``!'1;C8=<$0``9H,X +M`'5/:(````!0C85(YO__4(V%:/K__U!J`>C0[/__A,!U,&H`Z.!X``!9C85H +M^O__4.C^J0``4&ISZ(]B``!0Z,5X``!96<:'7AX```'IWPH``(V#$`0``(V/ +M7A(``%!1B4WXZ.AM``"#NT@M```$=3*`??!8=2QJ.NC)-P``A,!T(8M%^,9% +M"P'&``"`??!%=!>#NT@M```!=`Z-A6CZ___K$L9%"P#KXXV%:/K__U#H:CH` +M`%#_=?CHM6X``(M%^`^V`%#H7Z@``(!]"P"(1>IT1X"_7Q(``%]U(P^^AV`2 +M``!0Z$8W``"$P'02BD7J+$$\&7<)QH=?$@``.NL;BT7X@#A?=1.`OU\2``!? +M=0K&`%S&AU\2``!<@'W_``^$GP```(V#$`@``&:#.`!T#U"-AUX6``!0Z'YN +M``#K&&@````!C8=>%@``4(V#$`0``%#HO:X``(!]"P!T"3/`9HF'7A8``(!] +M\$5T$8.[2"T```%T"(V%2.;__^L,C85(YO__4.CM.0``4(V'7A8``%#HDFX` +M`(!]"P!T,&:#OV`6``!?=28/MX=B%@``4.A\-@``A,!T%6HZ6&:)AV`6``#K +M"3/`9HF'7A8``(!]ZP!U#?:&V$H```'&10L!=`3&10L`@+M$+0```'4)@+M% +M+0```'1K@'WP170&@'WP6'5?C8VHS?__Z+KU__]J`(V%J,W__U#_=?3_=?CH +M2B,``(3`="^-AA17``!0C8V\V?__Z$ZM``"$P'0F@+VXV?__`'095XV-O-G_ +M_^C5K```A,#K!X"[1"T```!T!,9%"P#VAMA*```$=!IF@[]<$0```'40:@&Y +M?%Y!`.CE\/__QD4+`(J&\$H``#PD=$$\'70]@+[Q2@``,'0TC85H^O__4.B. +MIP``4&ILZ!]@``!0C888!```4.AY>P``@\0,:@&Y?%Y!`,9%"P#HEO#__XV- +M2.[__^BS$```_[;T2@``Z#(:``"$P`^%,0,``(O.Z/+7__^$P`^$U`$``(!] +M"P`/A+H!``"`??!0#X2P`0``@'WP10^$I@$``(.[2"T```$/A)D!``"`?>L` +M#X6/`0``_X=,!0``@+OB+0````^%?`$``("[ART```#_MO1*```/E,`/ML!0 +M_W7T_W7XZ%P:``"%P`^$I0```/]U]/]U^.@Q&0``B$4+A,!T0_]U]/]U^.B4 +M&0``4.AQ&0``A,!U+O^V[$H``(U%"_^VM%<``/^VL%<``%#_LR0M``#_=?3_ +M=?AJ`%/H;@T``,9%"P!J`?]U]/]U^.B[&P``@+N'+0```/^V]$H```^4P`^V +MP%#_=?3_=?CHTQD``(7`=""`?0L`=".`NX``!0C888!```4.C_>0``@\0, +M_W7TN7Q>00#_=?CHAN[__[E\7D$`Z/#,__]J";E\7D$`Z`;O__^`OUT2```` +M=$2+@[0R``#WV!O`C8Y<5P``(\%0BX.P,@``]]@;P(V..%<``"/!4(N#K#(` +M`('&%%<``/?8&\`CQE#_=?3_=?CH%!L``+,!C8U([O__Z+D0``"*P^ET!@`` +MC8U([O__Z*<0``#IU/C__XJ#XBT``(3`=`J`?0L`=`3&10\!@'WP170*@'WP +M6`^%*@$``(!]"P`/A"8!``"$P`^%&`$``/^V[$H``(U%__^VM%<``/^VL%<` +M`%#_LR0M``"-A4CN____=?3_=?A04^CU"P``A,`/A>$```"(10LX1?\/A=L` +M``"-EUX6``!2_W7XC888!```C4X74%&Y?%Y!`.@;\/__:@FY?%Y!`.CQ[?__ +M_W7XZ((\``"$P`^%H````&A6!```Z$!=``!0C888!```4.B:>```65EH``0` +M`/]U^(V%2.+__U#HW*,``&H!_W7XZ*P\``!J`6H`_W7XZ,$9``#_MNQ*``"- +M1?__MK17``#_MK!7``!0_[,D+0``C85([O__:@#_=?A04^@U"P``A,!T!L9% +M"P'K:(V'7A8``%#_=?B-AA@$``!0C4874+E\7D$`Z&7O__^`?0L`=4.`OK%Q +M````=#!J`6H`:@"-A4CF__]0C85H^O__4,9%ZP'&10\!QD4+`>CZ<@``A,!U +M>C+;Z5'^__^`?0L`#X2*!```@'WK`'5C@'T/`'57@'WP4'11C8U([O__Z,L. +M``"$P'1"_W7XZ*6C``!0:`8$``#H,UP``%"-AA@$``!0Z(UW``"#Q`R-AUX6 +M``!0_W7XC888!```4(U&%U"Y?%Y!`.@$\/___X=,!0``_X=0!0``,\")AQ`% +M``")AQ0%``")AQ@%``")AQP%```XAK!Q```/E<"#CS@%``#_2(F'-`4``("^ +MY$H```!U/&B`````C85H____4(V'7!$``%#_%60R00!H@````(V%:/[__U"- +MA6C___]0Z-2H```SP&:)A6;____K$XV'7!$``%"-A6C^__]0Z%UH```/MX;8 +M2@``J`1T#`^VCO!*``")3?3K!(-E]`"`OO!*```DC4\H&M(E``0``/["#[?` +M#[;24O?8&\!J`(V6#%<``"/"4(V%:/[__U#_=?3H+%$``(N&J%<``(E'2(N& +MK%<``(E'3(V%2.[__U!6C4\HZ.I0``"*10^*3>N(1U&(3U*$P'5Q.(;`<0`` +M=6F+AJA7``"+CJQ7``"+EK17```/I,$+P>`+.\I\3'\(.X:P5P``=D*%TGPG +M?PR!OK!7````X?4%L",L#VAMA*```0 +M=0G&AUL%````ZRB`OO%*```P=!^#OK17````?!9_"8.^L%<```!V"X3`=`?& +MAUL%```!@'WK`,9%_P!U7X3`=5OVAMA*```$=!DXAUL%``!U$8V%:/K__U#H +MA:```%!J<.L/C85H^O__4.ATH```4&IQZ`59``!0C888!```4.A?=```@\0, +M:@.Y?%Y!`,9%_P'H?.G__^A5Q___@'T/``^%^0```(!]\%AT"H!]\$4/A>D` +M``#_MO1*``#H!!,``(3`#X76````.(-`+0``=`>#IO1*``#?@'W_`'08@+N` +M+0````^$M````(V-2.[__^CT"@``BY.T,@``]]H;THV&7%<``"/0BX.P,@`` +M]]@;P%*-ECA7```CPE"+@ZPR``#WV(V.%%<``!O`(\%0C8U([O__Z%0.``"- +MC4CN___H80D``(N+M#(``/?9&\F-AEQ7```CR%&+BZPR``#WV1O)C8845P`` +M(\A1C8U([O__Z(0*``"`NXL`#X5R\O__,L!?7EO)PA``58OLN("> +M``#HT,7__U97_W4(B_&-C8!A___H<O)4S/;,_\XG3+3__\/A*````"-A9=A__]0 +MC84`_/__4.A]8@``C8689?__4(V%`/3__U#HU6,``/:%0*S__Q!T#8"],-/_ +M_P!U!#+`ZP,SP$!0:``$``"-A0#T__]0C84`_/__4.C',P``C8U@W___Z*/K +M__]J`(V%8-___U"-A0#T__]0C84`_/__4.@K&0``A,!T$HN%8.O__P/XBX5D +MZ___$]CKD8V&*`4```$X$5@$BWT(C86`8?__4%>+SNCA[O__BH?#-@``6SQ4 +M=`0\274'QH?B+0```8V-@&'__^BOQ/__C8V`8?__Z%?/__^-30M14(V%@&'_ +M_U!7B\[HUN___X3`==V-C8!A___H>,S__U\SP%[)P@0`58OLN*05``#H0<3_ +M_U.+70A6B_'&AEX>````BH/#-@``5XV-7.K__XB&[`0``.C*ZO__OP`$``"- +MAEP)``!7C8Y+C5SV__^-AB@%```!"(N-8/;__Q%(!%?_=0B-AEP%``!0B\OHHMS__X3` +M=;>+BP!/``#H(IT``.MJC8,8*```4(V%_/[__U#H/6(``%.+SNBT_?__B47\ +MC87\_O__4(V#&"@``%#H'V(``(-]_`%TR6H`C85+C5SV__^-AB`%```!"(N-8/;__Q%(!%?_=0B-AEP%``!0B\OH +M%=S__X3`=8"#ODP%````=3*`N\,V``!)="DXAEX>``!U%6A#`P``Z+Y4``!0 +M_W4(Z!QP``!966H*N7Q>00#H/N7__U]>6\G"!`!5B^R![``,``!35E>+?0B[ +M]@,``(7_=`Y7Z!)?```[PP^''P$``(MU#(7V=`Y6Z#%A```[PP^'"@$``(-E +M"`"%_W0=@#\`=!A7Z'$O``")10B%P'4+5^C57@```\>)10B#90P`A?9T'V:# +M/@!T&5;H9R\``(E%#(7`=0Q6Z.-@``"-!$:)10PSP#/;QH4`_/__`&:)A0#T +M__]#A?]T)(`_`'0?_W4(BT4(4UL",L!?7EO) +MP@@`58OLN,`P``#HC\'__U-65XV-0,___^@PZ/__,_]7C85`S___4/]U"%?H +MP14``(3`#X1O`0``9CF]P-O__P^$8@$``(V%P-O__U"-A4#3__]0Z*4K``!0 +MZ!ZB``"%P`^$00$``(V%P-O__U#_=0CHB"L``%#H`:(``(7`#X4D`0``9HF% +M`/C__S/;O@`$``!F.;T`^/__=5Y6_W4(C84`^/__4.B1F0``4VB8,T$`5HV% +M`/C__U#H0"L``%#HDV$``(/$$(V%`/C__U!7Z%H,``"$P'0),\!FB84`^/__ +M@\-[@?L0)P``?*9F.;T`^/__#X2O````5O]U"(V%`/#__U#H,YD``(V%0-/_ +M_U#HZ2H``%"-A0#P__]0Z-PJ``!0Z!M?``"+-7`Q00"-A0#X__]0C84`\/__ +M4/_6A#C__]7 +MZ`H&``"*V(V%`/#__U"-A0#X__]0_]:$VW06C8W@X___Z/$"``"-C>#C___H +M:P,``(V-X./__^A5!```L`'K`C+`7UY;R<($`%6+[(M%'('L!`P``(7`=`/& +M``!35HMU%%>+?1!65\9%_P#H5@L``#/;0^F[`0``@'W_`'5E:``$``"-A?SS +M__]05E>(7?_H_B@``(V%_//__U#H^_W__X3`=#^%_W07@#\`=!)H`````5>- +MA?SS__]0Z$.>``"%]@^$90$``&:#/@`/A%L!``"-A?SS__]05NC]70``Z4D! +M``"+11C&1?\`@_@"#X1?`0``@_@#=1A65^A._/__A,`/A24!``"#91@`Z1P! +M``"+30B`N6@M````#X4;`0``.\,/A!,!``"%P'0)@_@$#X7W````,\!FB87\ +M\___5XV%_/O__U#H)5P``%;H=)8``%"-A?SS__]0Z'U=```SP#E%#`^4P%#_ +M=2B-A?SS____=23_=2!0C87\^___4.@7=@``#[[`4/\U`%!!`.@46P``B\LK +M#0!000`#P3O##X27````:@)9.\$/A*,```"#^`,/A*<```"#^`0/A*D```"# +M^`5U4HV%_/O__U#H;2@``(V-_/O__SO!B\%05W4&Z%HH``!0Z(5;``"%]G0] +MC87\\___4.B;*```C8W\\___.\&+P5!6#X7,_O__Z(0H``!0Z<'^__^#^`9U +M#VC_````N7Q>00#HF^/__U97Z),)``"$P`^%/?[__XM-#(7)=#Q35E?HQ0,` +M`(3`=#"*P^M3BT400#H?]____^&'`P``%Z*PUO#5HOQ@WX,`'0$,L!>PX-^!/]T!>AC +M____@'X3`'3KC888!```4(/&%U;HX@@``%[#58OL45-6B_&#RO\SVSE6!'4: +M.%X4=&V-AA@$``!0C4874+E\7D$`Z/C?__]7:@&-1?Q04_]V!(E=_/\5;#%! +M`(OX@___=23_%80Q00"%P'0:.%X4=#*-AA@$``!0@\875KE\7D$`Z+G?__^+ +M1?QJ`9E34E#H(KK__S/)`\<3T5]>6\G#B\+K^(/*_XO"Z_#_<03_%6@Q00!( +M]]@;P$##P@@`BT$$@_C_=0,RP,-0_Q5D,4$`@_@"=`B#^`-T`S/`PS/`0,.# +M>03_QP&P,T$`=!:`>1``=1"`>1(`=`7I[O[__^ED_O__PU6+[%%35HOQ,]M7 +MB9X8#```.%X6=`3&11`!QT7\````@#A=%'0'QT7\````P,=%%`$````X71!T +M!\=%%`,````SP#A>%0^5P$@E````"(OXZ.H=``"%P'0@BT4,.\-T&68Y&'04 +M4U=J`U/_=13_=?Q0_Q5<,4$`ZQ135VH#4_]U%/]U_/]U"/\58#%!`(OX@___ +M=17_%80Q00"#^`)U"L>&&`P```$```"#__\/E443B%X2B5X,B%X0.%T3=&.) +M?@2+?0P[^W0:5^@O60``C40``E!7C888!```4.B>5@``ZPDSP&:)AA@$```Y +M70AT&/]U".C15@``0%#_=0B-1A=0Z'A6``#K#V@````!C4874%?H-YD``/]V +M!(O.Z!O]__^*11-?7EO)PA``:@!J`/]T)!#_="00Z,3^__^$P'0$L`'K%/]T +M)`BY?%Y!`/]T)`CH".#__S+`P@@`58OL4U8SVU>+\3A=$'4(B5T0.%X6=`?' +M11`!````Z,$<``"+?0R%P'0?._MT&V8Y'W064U-J`E/_=1!H````P%?_%5PQ +M00#K%E-3:@)3_W40:````,#_=0C_%6`Q00")1@3&1A(!B5X,B%X0._MT#U>- +MAA@$``!0Z$]8``#K"3/`9HF&&`0``(U&%SE="'0+_W4(4.C(5@``ZPQH```` +M`5!7Z$R8``#_=@2+SN@P_/__,\"#?@3_7UX/E00!J"8O.Z(S;____=0R+SO]U".@AW___,L!> +M7<(,`%6+[%%65XOY@W\,`;X@3@``=1,Y=0QV`XEU#&KV_Q50,4$`B4<$:@"- +M1?Q0_W4,_W4(_W<$_Q54,4$`AL",MLX +M10MT"8U%]%#HLI,``(!]#P!T"XU%Y%"+S^BADP``A-MT"XU%[%"+SNB2DP`` +M#[9%"_?8&\"-3?0CP5`/ML/WV!O`C4WL(\%0#[9%#_?8&\"-3>0CP5"+1?S_ +M<`3_%70Q00!?7EO)P@P`58OL4?\%<%Y!`%;&1?\!,_:+AG!:00"%P'0MQD`4 +M`(N.<%I!`(!Y$@!T!^C`^O__ZP7H-/K__X3`=`F#IG!:00``ZP3&1?\`@\8$ +M@?X`!```00"*1?]>R<-6B_'H?OO___9$)`@!=`=6Z!I8``!9B\9> +MP@0`5O]T)!"+\?]T)!#_="00Z%#^__^$P'4:.$84=!6-AA@$``!0@\875KE\ +M7D$`Z)?:__]>P@P`5FH`_W0D$(OQ_W0D$.@<_O__A,!T%(O.Z.'Z__]J`&H` +M:@"+SNB@____7L((`%6+[(/L&%:+\5=6C4WHZ"I9``!J`FH`:@"+SNA\____ +MB\[H&OK__XU-Z(OPB_KH,5D``(O77XO&7LG#58OL48-]#`!6B_$/A/\```"+ +M1@R%P'052'0'2'4/:O3K`FKU_Q50,4$`B48$4XL=3#%!`%-1?Q0_W4,_W4(_W8$_]-(]]@:P/[`A,!UR<((`%6+[(/L#%-6,]N+ +M\5>)7?2)7?@X7A%T"^C4^/__B47TB57XOWQ>00#_=0R+SO]U".C\^___B47\ +M@_C_=4''AA@,```"````.%X4=#(X7A%U-SE>#'46C888!```4(U&%U"+S^B7 +MUO__A,!UO(V&&`0``%"#QA=6B\_H<]K__XM%_%]>6\G""`")7?PY70QV[K\` +M`@``,\F+PP-%]&H`$TWX45"+SNBB_?__BT4,*\,[QW("B\=0_W4(B\[H+1"0(AP`!```5XM]"(7_#X23 +M````@#\`#X2*````4U;&10L!B]^+\ROW@?X`!```?4*`.UQU,%97C84`_/__ +M4.@54```:@!J`6H`C84`_/__4,:$-0#\__\`Z#7___^%P'0$QD4+`%/HH+S_ +M_XO8@#L`=;*`?0P`7EMU)U?H!AT```^^`%#H>AD``(3`=11J`&H!:@!7Z/G^ +M__^%P'0$QD4+`(I%"^L",L!?R<((`%6+[('L``@``%-6BW4(,]L[\P^$C@`` +M`&8Y'@^$A0```,9%"P%7B_O1_X'_``0``'U!9H,\,UQU,5=6C84`^/__4.C+ +M4```,\!09HF$?0#X__]J`8V%`/C__U!J`.B#_O__AP@"```Z`84``"%P`^$ +M(0$``(M%$%,SVSO#=`C&1?X!.1AU`XA=_HM%%#O#=`C&1?T!.1AU`XA=_8M% +M&#O#=`C&1?\!.1AU`XA=_U>+?0Q7_W4(Z`#]__^)1?B#^/\/A-,```"H`0^$ +MRP```%-7_W4(QD4/`>@+_?__5F@`!```C87@]___4%?_=0CH'QH``%-H```` +M`FH#4VH#:````$"-A>#W__]0_Q5<,4$`B_"#_O]T?#A=_G0,BTT0C47@4.A: +MC```.%W]=`R+312-1>A0Z$F,```X7?]T#(M-&(U%\%#H.(P```^V1?[WV!O` +MC4W@(\%0#[9%__?8&\"-3?`CP5`/MD7]]]@;P(U-Z"/!4%;_%70Q00!6_Q5\ +M,4$`.%T/=`S_=?A7_W4(Z%7\__]>7UO)PA0`B%T/Z3O___]J`/]T)`S_="0, +MZ#?\___""`"+P8.(!`P``/\SR<8``&:)B``$``#&@``,```!PXN!!`P``(/X +M_W0'4/\5?#!!`,-65XM\)`R+\87_="57C88`!```4.A>3@``@#X`=0QH```` +M`597Z'2.``#&A@`,```!7U["!`!5C6PDF('L4`H``%-65^A&$@``OP````&% +MP`^$D`$``(M%>(7`=!5F@S@`=`]0C848]O__4.@'3@``ZQ!7C848]O__4/]U +M=.A.C@``BW5\@\O_C848_O__4#E=<'4[C848]O__4/\5C#!!`(E%<#O#=5+_ +M%80Q00"#^`)T#X/X`W0*@_@2=`4SP$#K`C/`B(:<%```Z:L"``#_=7#_%8@P +M00"%P'45B5UP_Q6$,4$`@_@2#Y7`B(:<%```.5UP#X2``@``C848]O__4(V> +M``0``%/H:DT``(V%1/[__U!3Z!@9``!0Z%=-``!75E/H=HT``&H!:@!J`/^U +M-/[__^C*K/__BXTX_O__,_\#P8F&``P``(N%&/[__XF&"`P``(U%3%"-AH`, +M```3UU")E@0,``#H"DT``(N%'/[__XF&@!0``(N%(/[__XF&A!0``(N%)/[_ +M_XF&B!0``(N%*/[__XF&C!0``(N%+/[__XF&D!0``(N%,/[__XF&E!0``(V% +M+/[__XV^%`P``%"+S^@MBP``C84<_O__4(V..`P``.@;BP``C84D_O__Z7L! +M``"+172%P'04@#@`=`]0C848^O__4.@-2P``ZQ!7C848^O__4/]U>.B-C``` +MBW5\@\O_C84H____4#E=<'4KC848^O__4/\5A#!!`(E%<#O#=4+_%80Q00"# +M^`(/A'S^__^#^`/I;?[___]U-A@`$``!05N@IC```:@%J`&H`_[5$____Z$NK__^+C4C___\SVP/!B88` +M#```BX4H____B88(#```5XV&@`P``%"-15@3TU")E@0,``#HXXL``(N%+/__ +M_XF&@!0``(N%,/___XF&A!0``(N%-/___XF&B!0``(N%./___XF&C!0``(N% +M//___XF&D!0``(N%0/___XF&E!0``(V%//___XV^%`P``%"+S^BMB0``C84L +M____4(V..`P``.B;B0``C84T____4(V.7`P``.B)B0``B\_HVH@``(F&#`P` +M`(.FF!0```"+17!?7EN#Q6C)PA``4U565XM\)!2+\3/;ZW-7C88`!```4%8X +MG@`,``!T#VK_Z(+\__^)A@0,``#K"_^V!`P``.AO_/__@_C_=$W_MP@,``") +MGY@4``#HW??__XB'$`P``%>(G@`,``#H[!4``(OH:+@S00!5Z())``"%P'0/ +M:+0S00!5Z'-)``"%P'4.B)^<%```.!YU@S+`ZP*P`5]>75O""`!5B^Q6_W4, +MBW40_W4(QH:<%````.AO$@``A,!T!#+`ZS16_W4,_W4(:O_HX?O__X/X_W3I +M4/\5?#!!`/^V"`P``(.FF!0```#H1_?__XB&$`P``+`!7EW"$`!65[\"@``` +M5XOQZ%1,``!95VH`4(E&".B"1@``7XO&7L/_<0CH+4P``%G#B]&+0@B+"@/( +M#[8!5@^V<0$/MDD"P>`("\;!X`@+P6H(62M*!%[3Z"7__P``PXM!!`-$)`2+ +MT,'J`P$1@^`'B4$$P@0`Z;;___]6B_&+1AC'!F`T00#'1@0D-$$`QT8(Z#-! +M`,=&#,PS00"%P'0*BPA0_U$(@V88`%[#BT0D!/]`$(M`$,($`+@"0`"`P@@` +M,\#""`!6BW0D"/]V$/\58#)!`(7`=0-`ZPN+1A"+3"0,B0$SP%[""`!J$/]T +M)`S_="0,Z*E,``"#Q`SWV!O`0,((`#/`P@0`58OL@^P04U:+=0B-1OPSVU>% +MP'0%C48$ZP(SP(M]#(D'BT40B1B-1?!0_W80_Q5<,D$`BT44BTWX4/]U&(E( +M"(M-_(D8B5@$B4@,_Q6@,D$`BT4+ +M"%#_401?7C/`6\G"&`"X`4``@,($`+@!0`"`P@P`N`%``(#""``SP,(,`(M$ +M)!B#"/^X!@`"@,(8`+@!0`"`PA``N`,``H#")`!5B^R#[!165XU%[%#_=0B+ +M^?\5N#)!`(UW&%9HZ#M!`&H%:@"-1>Q0_Q6P,D$`@SX`=$V+!HL(C54(4FBH +M.T$`4/\1AR<($`%6+[%%15HOQBT88A+\3/_.7X8=%N+1AB+"(U5_%)HJ#M!`%#_$87` +M?$:+1?R+"#E]"'0F4XU>'%/_=A175E=J^U#_42R+1?R+"%/_=A175E=J_U#_ +M42Q;ZPU7_W845U97:OU0_U$LBT7\BPA0_U$(7U[)P@0`58OL5HOQ@WX8`'0[ +M@WT(`'0UBT88BPB-50A2:*@[00!0_Q&%P'P@BT4(BPB-5AQ2_W84:@!6:@!J +M_%#_42R+10B+"%#_40A>7<($`%:+\8-^&`!U!#/`7L.+1AB+"%#_402+1AA> +MPXO!,\F)"(E(!(E("(E(#(E($(A(%,.`>10`=`;_);0R00##5HOQBT8$APXM)"(7)=!'_="0(_W0D"&H`:@#H6/[__\((`%6+ +M[(/L*%-6BS60,$$`,]M7B5WXB5W\_]:+?0B)1?2+!XU-^%%7_U!(AOY58OL45%6BW4(5U;H840``&O`#`4``@``4.B'0``` +MB_B)??B%_W4'B\;IN@```%-HL#1!`%?H840``%?H,40``(O8B\9F@S@`#X2) +M````:@1HH#1!`%;H-X<``(7`=3^-?@1F@S\-=2^+1?B-!%B)1?QF@WX&"G4? +M:)0T00#_=?SH%D0``(-%_`B+]XU^!(/#!&:#/PUTVHM]^$9&ZRT[=0AV(&:# +M/B!U&F:#?OX@=1-HA#1!`(T$7U#HW4,``(/#!NL(9HL&9HD$7T-&1F:#/@`/ +MA7?_____=0@SP&:)!%_HV3\``(O'6U]>R<($`%6+[(/L.%-6BS60,$$`5XE- +M^/_6B47\_]8K1?PSV[\0)P``ZU&+1?B+0`R+"(U5]%)0_Y'@````@WWT!'0\ +M4U-34XU%R%#_%4@R00"%P'0AC47(4/\54#)!`(U%R%#_%50R00!34U.-1129HE%Y(M%^(M`#&H" +M:C_'1>R6````BPA0_Y'8````7UY;R<.#;"0$!.F*^O__@VPD!`3IL_G__X-L +M)`0$Z8_Y__^#;"0$".F%^?__@VPD!`SI>_G__U6+[%:+=1"%]G4*N`-``(#I +MD0```%>+?0QHF#M!`%?HE?G__X7`=69HV#M!`%?HAOG__X7`=`R+10B%P'0[ +MC4@$ZSAHN#M!`%?H:_G__X7`=`R+10B%P'0@C4@(ZQUH^#M!`%?H4/G__X7` +M=!*+10B%P'0%C4@,ZP(SR8D.ZQ1HZ#M!`%?H+_G__X7`=`^+10B)!HL(4/]1 +M!#/`ZPB#)@"X`D``@%]>7<(,`%:+="0(_TX0BT80=1"+SNB+^/__5NAF1``` +M63/`7L($`%6+[(/L#%-7B_F+1PPSVXE]]#O##X0V`0``5E-34U-HZ#5!`(E= +M^(L(4/]1+(MU"%:+S^CW_/__5HA%"^B500``C80```(``%#HO#T``(OX._L/ +MA/<```"[V#5!`%-7Z)Q!``!H4#5!`%?H_D$``&@P-4$`5^CS00``9H,^((EU +M_'4-@T7\`HM%_&:#."!T\VH&4_]U_.AAO0```C40``E#HF3P``(E%_(7`#X14`0``5HO/Z*O[__^+??R(10L/MP9F +MA<`/A#((``(7`=2UF.09T1&H(:``V00!6Z&*"``!&1H7`=`AF +M@SX`=>?K'8/&#NL89H/X/G001D8/MP9FAR<($`(-L)`0,Z53\__^#;"0$!.GU_/__@VPD!`CIZ_S__X-L +M)`0,Z>'\__^#;"0$!.DL_/__@VPD!`CI(OS__U:+\3/`:A!0B484B488C48< +M4,<&8#1!`,=&!"0T00#'1@CH,T$`QT8,S#-!`,=&$`$```#H7#L``(O&7L-6 +M5XM\)`R+\6HLB7X$Z`M!``!9AB&]___BTX(:@'H[/?__XM.".@P^/__B_B%_W0G +MBP=3C5X,4V@(/$$`5_\0A@```"+!U?_4`A;_W80B\[H +M)?S__U]>P@0`58OLBT4,2%:+=0A7BWT4=$A(=#.#Z`-T$H/H?'5,_S=JZU;_ +M%3PR00#K/VKK5O\50#)!`(O/P>D040^WSU&+R.@S^/__ZR-JZU;_%4`R00"+ +MR.CR]___ZQ%JZU;_%4`R00!6B\CH!?___U?_=1#_=0Q6_Q5$,D$`7UY=PA`` +M58OL@^PP4U:+=0A7,_]H`'\``%>+V<=%T#````#'1=0H"```QT78A')``(E] +MW(E]X(EUY(E]Z/\5-#)!`(E%[(U%T%#'1?`&````B7WTQT7X4#9!`(E]_/\5 +M.#)!`%^),UY;R<($`%6+[(/L$%-6B_&`?A0`5W42:@#_%:PR00#_%3`P00#& +M1A0!BQUL,D$`:@#_=0S&1A4`_]/_=0B+SNA;____BT40B480C47P4/]U#/\5 +MG#)!`(L](#)!`&H"C47P4/]U#/_74&H`_Q4D,D$`BT8$AO?__XO84XO.Z&'[ +M__]3B_#H)C@``#OW=!!6_W4,_Q4P,D$`5N@2.```7UY;R<(,`%6+[(L-"%!! +M`('L%`$``(/Y_W4\C87L_O__4,>%[/[__Q0!``#_%9PP00"+C?S^__^+A?#^ +M__^+E?3^__^)#0A000"CH%Y!`(D5G%Y!`.L%H:!>00"#^0)U"\'@"`,%G%Y! +M`,G#N`$%``#)PX!\)`@`#[9$)`1U!U#_%9@R00#""`!5B^R`?1``_W4,_W4( +M=`?H63H``.L%Z!=U``!=P@P`58OL@'T4`/]U$/]U#/]U"'0'Z(LZ``#K!>AC +M=```7<(0`%6+[%-65XM]"(MU#`^V!O]U$%#HD?____]U$(K8#[8'4.B#____ +M1X3`#X3%````/"IT*CP_=!PZPW0?___X`^`'7HZ5C___\SP(3;#Y3`7UY;7<(,`%6+[('L +M``@``%.+70A65XM]$(O'P>@?)`&!Y___``"(11`/A!D!``!3Z)&*"T```,```#& +MAH0M```!QX:L,@``!````(F&T"T``(F&U"T``(F&V"T``(F&W"T``%[#5FC` +M-@``B_%J`%;HR30``(V.6"T``%[I-(0``%:+\3/)C898+0``B0B)2`2)2`B- +MCH@M``#H<78``(V.K"T``.AF=@``B\[H2/___XO&7L-6BW0D"%;HK3<``(7` +MC41&_G<"B\9>P@0`BT0D"(7`=!-F@S@`=`UH@#9!`%#H6#D``.L9@WPD!`!U +M!#/`ZQ1H=#9!`/]T)`CHR34``/?8&\#WV,((`(-\)`1<=`N#?"0$+W0$,\#K +M`S/`0,($`#/`@WPD!#H/E,#"!`!6BW0D"%;H,C<``(7`=A-F@WQ&_EQT"VB( +M-D$`5NBR-P``7L($`%:+="0,5XM\)`R%]G0>._=T&E?H_S8``#M$)!1R!S/` +M9HD&ZSY75N@5-P``9H,_`(O'="DSR5-F@S@O=15J7(7V=09:9HD0ZPF+T='Z +M6V:)'%9`0$%!9H,X`'7;6XO'A?9T`HO&7U["#`!5B^R![``$``!65XM]"(U% +M"%"-A0#\__]0O@`$``!65_\5H#!!`(7`=`T[QG,)C84`_/__4.L&.WT,=`E7 +M_W4,Z"-1@10Z+@V``"%P'0K5X/``E#HJC8``(7`=`U]>6\((`%6+[(M%#%97BWT4AP@P`@#WX34(``'0*N?A,0@#I"7D``.E_,@``@#WX34(``'0* +MN?A,0@#I&WD``.F3,@``5HMT)`B*!E0%1Z/*?__^+R(H!A,!UXH7_=`2+Q^L<@#X`=!6-?@&`/SIU#5;HSY___SO' +MC48"=`*+QE]>P@0`5HMT)`A6Z!`T``"+R.L.#[<$3E#HH/S__X3`=1E)>>]F +M@SX`=`IF@WX".HU&!'0"B\9>P@0`C41.`NOVBT0D!%:+\.L(4(OPZ'2?__^` +M.`!U\XO&7L($`%6+[('L``0``%:+=0B*!H3`=#2-3@(/OL!0Z$+\__^$P'0< +M@'G_+G46@#DN=1$/OD$!4.@I_/__A,!T`XUQ`HI!_T&$P'7/@#X`='!7B@:+ +M_H3`=`N`?@$Z=06-?@+K*#Q<=20X1@%U'VI`&*!XO/A,!T((K0#[["4.C&^___A,!T!8UY`>L%@/HN=0=! +MBA&$TG7B._YT!X`_`(OW=9)?@#XN=1"`?@$N=0J-1@*`.`!U`HOP@WT,`'0A +M:``$``!6C84`_/__4.C5;```C84`_/__4/]U#.B*,0``B\9>R<((`%6+[(M% +M"`^W"('L``@``%>+^&:%R70_#[?1C4@$#[?"4.@\^___A,!T'F:#>?XN=1=F +M@SDN=1$/MT$"4.@A^___A,!T`XUY!$$/MT']00^WT&:%P'7'9H,_`'1]5F:# +M/P"+]W0*9H-_`CIU`XUW!&:#/EQU*&:#?@)<=2%J7(U&!%#HH3,``(7`=!)J +M7(/``E#HDC,``(7`=`.-<`(/MP:+UF:%P'0E#[?(#[?!4.BO^O__A,!T!8UR +M`NL&9H/Y+G4*0D(/MPIFA+?"0,5T[HQOS__RO'._!\"E?HNOS__XOP +M*_=65XM\)!A7Z`\P``#&!#X`7U["#`!6BW0D$%>+?"0,5T[HY_S__RO'T?@[ +M\'P,5^C9_/__B_`K]]'^5E>+?"085^@\,0``,\!FB01W7U["#`!6BW0D"%;H +ML?S__XU.!#O!P@0`4XM<)`A65U/H +M:RX``(U\&/_K!3O[=@Y/#[X'4.A7:@``A,!T[@^^!XOWZP@[\W9"3@^^!E#H +M/FH``(3`=>[K%(H&/"YT+`^^P%#H*6H``(3`=0=.._-WZ.L8:BY3Z-C[__]0 +MZ*+[__^%P'0&.\9S`HO^B\=?7EO"!`!3BUPD"%974^@E,```C7Q#_NL&._MV +M#T]/#[<'4.C<:0``A,!T[0^W!XOWZPD[\W9'3DX/MP90Z,)I``"$P'7MZQ@/ +MMP9F@_@N="T/M\!0Z*II``"$P'4(3DX[\W?DZQAJ+E/HK_O__U#H*#$``(7` +M=`8[QG,"B_Z+QU]>6\($`%-55E>+?"04:CI;A?\/A.T```"`/P`/A.0```!7 +MZ.O]__^+\(7V=15HT#9!`%?H82\``%?HU/W__XOPZS*-;@&`?0``=!YHS#9! +M`%7HI&@``(7`=`]HR#9!`%7HE6@``(7`=0MH<#-!`%7H`BX``(!\)"``=4%7 +MZ(K^__^+\.L5Q@8P3COWB\;K#8U(_X`Y+G0-Q@`PB\'^`#@8=.WK$,8`0>L+:,0V00!7Z'$M +M``"+?"08A?\/A`L!``!F@S\`#X0!`0``5^@-_?__B_"%]G45:+@V00!7Z!PO +M``!7Z/;\__^+\.LSC6X"9H-]``!T'FBP-D$`5>C*<```AB[ +M<```AAR+@``@'PD(`!U45?H"?[__XOPZQEJ,%AFB09.3COW +MCUF/__B\B* +M`83`==XX!G02:-@V00!6Z)8K``"%P'4#0.L",\!>P@0`5E>+?"0,@#\`B_=T +M88!\)!``N-@V00!U!;C@-D$`#[X.45#H^"H``(7`=0LX1"00=`B`/B!S`\8& +M7XO&*\>#^`%^"(`^.G4#Q@9?@#X@=1$/OD8!4.AO]?__A,!T`\8&7U;H:IC_ +M_XOP@#X`=9]?7L((`%6+[('L``@``%:+=0AH``0``(V%`/C__U!6Z(;[__^- +MA0#X__]0:@#H[/3__X3`=`2P`>LL9H,^7'4'9H-^`EQT&%;HJ/;__X3`=!,/ +MMT8$4.@`]?__A,!T!3/`0.L",\!>R<($`%6+[%97:CO_=0@S_^BW]___B_"% +M]G04C48!4.C5+@``@'T0`(OX=`/&!@"#?0P`="IJ._]U#.BH+0``B_"%]G0: +MA?]U"XU&`E#H_&\``(OX@'T0`'0%,\!FB0:+QU]>7<(,`%:+\>@:XO__@V8, +M`(O&7L-6B_'_=@SH72X``%F+SE[I'^+__U:+\8-^#`!U#F@$``0`Z$XN``!9 +MB48,7L.+1"0(BTPD!(D!P@@`BU0D!(,Z`HM"#'4-BP`#0@@E__\#``-!#,($ +M`%97BWPD#(O/Z!_B__^+\"4`P```B\]TP@0`58OLBU4(N```!``[T',>BTD,`\HY +M30QT%"O".440@_*```7<(,`%:+="0,5O]T)`QJ_^@YJ/__ +M,]+WT#/).8$\4$$`=0@YL3A000!T#X/!#$*#^51RYS/`7L((`&O2#(N"0%!! +M`.OQBT0D"(M,)`29@^('`\+!^`,/MA0(0%8/MC0(C4P(`0^V00$/M@G!X`@+ +MP8M,)`S!Y@@+UL'@$`O"@^$'T^AJ(%DK3"00@\K_T^I>(\+"#`!5B^R+31"+ +MP9E6@^('`\*#X0=7B_"+P6H@62M-%(/*_]/JB\B+10C390S3XL'^`S/_`_#W +MTHH$/B+""D4,P6T,",'J"('*````_X@$/D>#_P1RXE]>7<(0`(M$)`16B_$! +M1@2+3@2+1@@[R'8QB]#!Z@)7C7P"(#O/=@*+^8O':\`H4/\VZ`LF``")!H7` +M=0JY?%Y!`.C;K?__B7X(7U["!`!7B_GH(N#__ZD`@```="6+3"0(@R$`P>@, +M@^`'B4$$C42'$(E!#&H$B\_HY-___^F6````5HMT)`R+SZD`P```=2Z`?"00 +M`,<&`0```'0/P>@&)?\```")1@1J"NLU:@+HKM___U?HD_W__XE&!.M9QP8" +M````J0`@``!U'<'H"H/@!X-F"`")1@2-1(<0B48,:@;H>]___^LOJ0`0``!U +M%,'H"8/@!XE&!(U$AQ")1@QJ!^L&@V8$`&H$Z%/?__]7Z#C]__^)1@A>7\(( +M`%6+[(M5"(/L4%:+\872#X[=!```@_H"4U(#/2B_N!^P#@`0`/@Y0$ +M``"%VWX@BT8,B@P00H#Y`G4,B@P00H#Y`G0#@,'@B`PX1SO3?."+1@PK^XFX +M',`#`(M&#(F8(,`#`.E7!```BTX@BT80BWX,,]N)1>2-%`F)CR#``P"!^0#@ +M`0`/@S0$```A70B%P`^.*00``(M]"#+``_GK$(M6#"H$&D.(!#H#?>2-%`D[ +M^GSL_T4(BT4(.T7D?-CI_`,``(M^((M&$(MV#(T,/HE]V(E%U(EU[(E-T(F^ +M(,`#`('_`.`!``^#T@,``#/;.\.)7?`/CL4#``#K!8M]V#/;:AQ3C46P4(E= +MW(E=X(E=](E=^(E=_(E=".@[)```BT7P@V7D`#O'Z3\!``"+1>"+5?R+R"M- +M](O[B]F+3>P/K],/M@F+]P^O=0@#\HM5^`^OT/]%[`/RBU7@#B4W,)?\````KP8M-Z(@$,0^^=8#5HE-X(E%W.CS*@`` +M`46PB\8K1?10Z.4J```!1;2+1?0#QE#HURH```%%N(O&*\-0Z,HJ```!1;R- +M!!Y0Z+XJ```!1<"+QBO'4.BQ*@```47$`_=6Z*8J```!10?=7:+ +M=;`S_S/)B7VP08U$C;"+$#O60J +M`8M-S/]%Y(-%Z`,/ML"(!`Z#Q@/_3?2)10AU@?]%^/]%[(-]^`,/C$K___^+ +M5?"+1="#PO[K#HI,&`$`#!@`3!@"@\`#.\)\[ND>`0``BT8,B44(BT8@/0#` +M`P`/@PH!``"#^!4/C`$!``"+7BB#P.O!ZP2%P`^.\````$C!Z`1`B474BT4( +M#[8`@^`?@^@0>&B*@(Q000"$P'1>@V7D``^VP&H2B47,7XM-Y#/`0-/@BTW, +MA<%T-VH$C4<84/]U"(O.Z/7Y__^#^`5U(FH45VH45_]U"(O.Z.#Y__\KPR7_ +M_P\`4/]U"(O.Z![Z____1>2#QRF#_V1^KX-%"!!#_TW4=8#K9HM&((M.#(MV +M*#T`P`,`/R`PNB%_WX]B@%!_T4(1CSH=`0Z +MPG4IBP&%P'T.C1P&A=M\$@4````!ZPD]`````7T$*\:)`8-%"`2#P02#Q@0Y +M?0A\PU];7LG"!`!5B^R#[`Q3BUT(5E>+^<=%_$!X?0&-0PA0B\^)7?CH^_?_ +M_XOPC4,84(O/Z.[W__^+"X/Y*`^'=@4``/\DC8.20`"`>P0`=`H/M@"(!NE? +M!0``BP")!NE6!0``BDL$A,ET!0^V-NL"BS:$R70%#[8`ZP*+`(O.*\AU!6H" +M6.L.._$;P/?8@>$```"`"\&)1S#I'`4``(M-^(I9!(3;=`4/MA;K`HL6A-MT +M!0^V`.L"BP"-#!"$VW0:@>'_````=!:+P22`#[;`]]@;P"4```"`ZQ"%R74% +M:@)8ZP>+P24```"`.\H;TO?:"]")5S"+1?B`>`0`=`>(#NFT!```B0[IK00` +M`(I+!(3)=`4/MA;K`HL6A,ET!0^V`.L"BP"+RBO(=05J`ECK$#O1&\"+T??8 +M@>(```"`"\*)1S"`>P0`Z[/V1S`"#X1F!```BS8[=0P/@VD$``#_3?R#??P` +M#XY@!```:_8H`W4(B][II?[___9',`+I`0$``(I+!(3)=`4/M@;K`HL&0(3) +M="@E_P```.L9)0```(#I\/[__XI+!(3)=`4/M@;K`HL&2(3)=`2(!NL"B0:% +MP'79Z;O^__^*2P2$R70%#[86ZP*+%H3)=`4/M@#K`HL`,\+K)XO!)0```(#I +M4/___XI+!(3)=`4/MA;K`HL6A,ET!0^V`.L"BP`CPHO(==7I%____XI+!(3) +M=`4/MA;K`HL6A,ET!0^V`.L"BP`+PNO:BDL$A,ET!0^V-NL"BS:$R70%#[8` +MZP*+`"/&Z6_____W1S````"`Z?#^___W1S````"`ZQSV1S`!Z=[^___V1S`# +MZ=7^___V1S`#ZP3V1S`!#X4Q`P``Z<;^__^#1RS\BQ:+1RR+3PPE__\#`(D4 +M".D3`P``BT,` +M``"`2=/BP>H?BTWX"].)5S"`>00`#X0:_?__Z0S]__^*2P2$R70%#[86ZP*+ +M%H3)=`4/M@CK`HL(B\+3Z(7`=05J`EOK"(O8@>,```"`2=/J@^(!Z[.*2P2$ +MR70%#[86ZP*+%H3)=`4/M@CK`HL(B\+3^.O(@'L$`'0%#[8&ZP*+!O?8B\@/ +MA'C]__\E`0``@(/(`>F`_?__BT +MBUCT``)X]``"V/0``\CT`` +M58]``&Z/0``EDD``DH]``*N/0`#VCT``+)!``$N00`!OD$``HY!``,F00`#5 +MD$``])!``/R00``'D4``.)%``%N10`"*D4``Z)%``&B20`!>DD``58OL4U:+ +M=0R+V8-C!`"#(P"X`(```%<[\',"B\:+?0A05_]S".@G&@``,\DRP$&(10L[ +M\78+,@0Y03O.@(:@B+RX@'Z,_2__^+10S_ +M10@Y`W+$Z?\```!J`8O.Z%OR__^+?A!K_R@#/HO+Z+_2__^+RZD`@```=0?! +MZ`QJ!.L(P>@*@^@8:@:)!^B)TO__BP?V@!!000`$=!V+R^B.TO__J0"`__\/ +MELC +M/8@```!\!RT(`0``ZQ*#^!!\!8/H".L(@_@(?`.#Z!`#1A")1PS_1A"+10PY +M`P^"]O[__VH!B\[H4?'__XM&$(U(`6O`*`,&B4X0C4@,B4@4C4@6UW"#`!5B^Q35HMU"%=J'(U&+(OY4(U'$%#HIQ<` +M`(M&&+L`(```B44(.\-R`XE="(-]"`!T%/]U"(M'#/]V%`4`P`,`4.A[%P`` +MBTT(BT8D*]D[PW("B\.%P'044(M'#/]V((V$"`#``P!0Z%47``"#9S``QTBT80AR<($`(M!%#M!$',0BQ&*!!"+ +M5"0$B`+_013K!XM$)`3&``#"!`"+012-4`$[41!S*(L1`\)F#[90`68/M@!6 +MO@`!``!F#Z_69@/0BT0D"&:)$(-!%`)>ZPF+3"0$,\!FB0'"!`"+012-4`,[ +M41!S,(L1`\(/ME`#5@^V<`+!X@@#U@^V<`$/M@#!X@@#UL'B"`/0BT0D"(D0 +M@T$4!%[K!XM$)`2#(`#"!`!6B_&+1A17BWPD$(U,./]7.TX02@`=%Z+02R%P'17BY$`!0``5HNQ +M!`4``%>+^@O^=!B)51"+D?@$```!50B+D?P$``")=10150S_=13_=1#_=0S_ +M=0C_L+17``#_L+!7``#_L?0$``#_L?`$``#HVB4``%]>7<(0`(M$)`2%P'0# +MB4$LBT0D"(7`=`.)03"#B<`$``#_P@@`58OLBT4,,])6#[P3_#X3P````4/]U_(O+Z-3!__^+^(M&.(7`=0:-@]!*``#V0`@"=!97_W7\ +MC9X0!0``_S/H%)/__XD#BUWTB\>9C8[H!````0$1400!??@!??PI?0PI1B"+ +M1B`95B0+1B1U)SB&Q@0``'0?#[:&Q`0``%!J`593Z"Z)``"$P'1]@WT,``^' +M.?___XM&+(7`="V+B*!Q``#_MM0$```#CN@$``"+@*1Q``#_MM`$```3ANP$ +M``!048O.Z,#]__^#__]T)X.^&`4```"+1?B+^'09J`]T!H/@\(/`$%#_=0B- +MCH`"``#H1Y/__^B440``B\=?7EO)P@@`@\C_Z_3&AL<$```!Z_)3BUPD"%:+ +M\8!^#`!7BWPD%(E>'(E^&'07.WX0=R)74_]V%.B-$0```7X4*7X0ZQ"`?BD` +M=0J+3C!74^B,O___C8;P!````3B#4`0`@'XJ`'415X'&#`4``%/_-NCFD?__ +MB0;H%5$``%]>6\((`(O!,\F)"(E(!(A($,/_,>B"$```PU6+[+@L-```Z*UU +M__]7:ES_=0B+^>A^%0``A<"-A=3K__]U)V@`!```4&H`_Q6H,$$`:ER-A=3K +M__]0Z(45``"%P`^$=0(``(/``O]U"%#H"A0``%:-C=3S___HS[?__S/V5FH! +MC874Z___4%:-C=3S___HO[G__X3`=1"-C=3S___HC;G__^DP`@``@TW\_\9% +M"P")=?A3@WW\_P^%#0$``(V-U//__^BBN/__B]AH`"```(V%U,O__U"-C=3S +M___HF+___XE%]#/V@\#P#XBJ````@+PUU,O__RIU(H"\-=7+__\J=1AJ"V@, +M-T$`C80UULO__U#HO1(``(7`='EF@[PUU,O__RIU*8V$-=C+__]F@WC^*G4; +MBTWT@\'@._%_$6H+:/`V00!0Z`D4``"%P'1!@+PUU,O__U)U)H"\-=7+__]A +M=1QJ!&CH-D$`C80UULO__U#H71(``(7`#X1,`0``BT7T1H/`\#OP#XYA____ +MZPG&10L!`_.)=?R+1?1J`(U$&/!J`%"-C=3S___H%;W___]%^(%]^(`````/ +M@O/^__^#??S_#X0!`0``BT7\F6H`4E"-C=3S___HZ+S__V@"``@`Z)P.``") +M!XV-U//__X7`#X3:````:```"`!0Z'>^__^`?0L`B4<$=`?1Z(E'!.LSC40` +M`E#H9PX``(OPA?8/A*4```"+1P2+#\8$"`"+1P1`4%;_-^B64@``_S?H60X` +M`(DWBT\$N```!``[R'<"B\&+#S/29HD403/),]LY3P1V7(L'#[<46$-FA=)T +M4&:#^EQU,0^W-%B#[B)T(X/N.G0:@^X2=!&#[@1T"$Y.=21J">L.:@WK"FH* +MZP9J7.L":B)#ZPYF@_H-=`9F@_H*=0-J#%IFB11(03M?!'*DBP7\G"!``SP#D!#Y7`PU:+,0^W!E=FASO__]0_W4(Z)U0``"- +MA>SO__]0QD7K`.@(#@``4(V%[.___U!7Z+Z-___WT%!H'#=!`(U%[&H*4.A9 +M$@``@\00C47L4(O+Z*/^__^%P'16C5@4:@Q3Z&(1``"%P'0(*\/1^(OPZP6^ +M_P```(M%$(U(_SOQ=@CWV!O`(\&+\(M]#(7V=@A64U?H)A```&HB,\!79HD$ +M=^A/$0``A6\G"%`!5B^R! +M[``$``!35E?_=0B-A0#\__]J`6@``@``4&@T-T$`Z)3^__]J*HV%`/S__U#H +MRA```(OX:F1;A?]T(8V%`/S__U#H25,``(MU#(/'`E>)!N@[4P``BTT0B0'K +M"HM-$(MU#(D9B1XY'G4(.1EU!#/`ZP,SP$!?7EO)P@P`58OL@>P`"```5E=J +M`(OY_Q6P,$$`:@6^0#=!`%90_Q6L,$$`A!'1H!]_P!T,X!] +M$`!U<@^O1?AH!@(``)EJ9%GW^0/&4(M%Q`^O1?29]_D#QU`SP%!04/]U"/\5 +MB#)!`(!]$`!U/V@`!```C86\]___4/]U"/\5C#)!`/]U#(M-\&H!:``$``"- +MA;SW__]04.@6_?__C86\]___4/]U"/\5,#)!`&H(_Q60,D$`:@7_=0@K\/\5 +ME#)!`(-E"`")11")1>SIV````(%]"``"```/C=,```!H``0``(V%O/?__U#_ +M=1#_%8PR00!F@[V\]___`'0J_W4,BTWP:@%H``0``(V%O/?__U!0Z)S\__^- +MA;SW__]0_W40_Q4P,D$`@'W_`'1FC47,4/]U$/_3BT78*T70:`0"``!`#Z]% +M^)EJ9%GW^5"+1=0K1`KQ@^O1?B9]_E0B\>9*\*+ +MR(M%S-'Y*\$K1=QJ9`^O1?19F??Y4&H`_W40_Q6(,D$`:@+_=1#_%90R00") +M11`[1>QT"_]%"(7`#X4@____7UY;R<(,`%;_="0(B_'HF_C__XO.Z*S]__]> +MP@0`H:A^00!`HZA^00"#^`AR!S/`HZA^00!35<'@"@6H7D$`5HOP,\"]B%Y! +M`%>+S6:)!N@<^___BQV$,D$`OP`"``"$P'425U;_="0<_S5X7D$`_].%P'4. +M5U;_="0<_S5T7D$`_]-J`&H`5U96B\WHB4(,P@P`58OL +M@^PH4U97:B#_=0B-1=A0B4WXZ/H(```SP&H$,\F)10@SVUJ#^`H/C]\````[ +MVGTBC72=V(EU_#O*?1F+??B--(&-?+<4BW7\`57\0T$[VJ5\Y3O*=09`B44( +M,\D[VGS#@_@*#X^B````QT7\L*Y!``^V=>6*1=@RAM"O00`/MG7FBI[0KT$` +M#[9UYS!=V8J>T*]!``^V=>0P7=J*GM"O00"+=?PR!C!=V_]%_&H#B$78C47< +M7S/VBEPP_#`<,$8[\GST`\)/=>TSVX-]"`I_.SO:?2"-1)W8.\I]&HMU"(M] +M^(TTL8U\MQ2+\$,#PD$[VJ5\Y#O*=07_10@SR3O:?,F#?0@*#XYE____7UY; +MR<($`%6+[(/L'%-65X/!)&H$B4W\QT7T"0```%\SP(M-_(UT!>2#P0*)??@/ +MME$!#[99_XJ4D+!^00`RE)BPAD$`#[99_C*4F+"*00`/MADRE)BP@D$``\^( +M%@/W_TWX=+^8V'M````%#_=0B-1?!0Z!S^__\/MD7PBP2%L)I!``^V3?TS!(VP +MED$`#[9-^C,$C;"200`/MDWW,P2-L(Y!`(MU#`^V3?&)!@^V1?2+!(6PFD$` +M,P2-L)9!``^V3?XS!(VPDD$`#[9-^S,$C;".00`/MDWUB48$#[9%^(L$A;": +M00`S!(VPED$`#[9-\C,$C;"200`/MDW_,P2-L(Y!``^V3?F)1@@/MD7\BP2% +ML)I!`#,$C;"600`/MDWV,P2-L))!``^V3?,S!(VPCD$`C9^D````B48,QT4( +M"````%-6C47P4.A&_?__#[9%\(L$A;":00`/MDW],P2-L)9!``^V3?HS!(VP +MDD$`#[9-]S,$C;".00`/MDWQB08/MD7TBP2%L)I!`#,$C;"600`/MDW^,P2- +ML))!``^V3?LS!(VPCD$`#[9-]8E&!`^V1?B+!(6PFD$`,P2-L)9!``^V3?(S +M!(VPDD$`#[9-_S,$C;".00`/MDWYB48(#[9%_(L$A;":00`S!(VPED$`#[9- +M]C,$C;"200`/MDWS,P2-L(Y!`(/K$/]-"(E&#`^%+O___XU')%!6C47P4.AQ +M_/__#[9%\(J`T*Y!`(@&#[9%_8J`T*Y!`(A&`0^V1?J*@-"N00"(1@(/MD7W +MBH#0KD$`B$8##[9%](J`T*Y!`(A&!`^V1?&*@-"N00"(1@4/MD7^BH#0KD$` +MB$8&#[9%^XJ`T*Y!`(A&!P^V1?B*@-"N00"(1@@/MD7UBH#0KD$`B$8)#[9% +M\HJ`T*Y!`(A&"@^V1?^*@-"N00"(1@L/MD7\BH#0KD$`B$8,#[9%^8J`T*Y! +M`(A�^V1?:*@-"N00"(1@X/MD7SBH#0KD$`@\<45U96B$8/Z)?[__]?7EO) +MP@@`58OL@>P$`P``4U8SP#/)0+X;`0``5XO0@.*`#[[2B(0-_/S__XB$#?O] +M__^(C`7\_O__0??:&](CUHT\`#/7,\*#^`%UT#/)7XO0@.*`#[[2]]H;THB! +ML*Y!`"/6`\`SPD&#^1YRXC/;B5W\ZP.+7?R$VW08#[;##[:$!?S^__^-C?O] +M__\KR`^V`>L",\"-#``SR`/),\@#R3/(`\DSP8O(P?D(,LB`\6.-!)T````` +MC9"PGD$`B(O0KT$`B$H!B`J(B+.B00"(B+"B00"(B+.F00"(B+*F00"(B+*J +M00"(B+&J00!T%0^VT0^VE!7\_O__#[:4%17]___K`C/2B)"SGD$`B)"RHD$` +MB)"QID$`B)"PJD$`A,ET%0^VR0^VC`W\_O__#[:,#?W\___K`C/)B(BRGD$` +MB(BQHD$`B(BPID$`B(BSJD$`#[;SB\[!X0,SSL'A`C/.`\F+T<'Z"#+1@/(% +M=#*+SL'A`S/.P>$",\X#R8O1P?H(#[;2#[;),]&#\@4/MHP5_/[__XV5^_W_ +M_RO1BAKK`C+;BTW\B)G0KD$`A-MT%0^VRP^VC`W\_O__#[:4#63]___K`C/2 +M#[;SB\[!X0*(D+*.00"(D+&200"(D+"600"(D+.:00"(D;)^00"(D;&"00"( +MD;"&00"(D;.*00"$VW02#[:4-?S^__\/MI05P_W__^L",]*(D+".00"(D+.2 +M00"(D+*600"(D+&:00"(D;!^00"(D;."00"(D;*&00"(D;&*00"$VW02#[:4 +M-?S^__\/MI05ZOW__^L",]*(D+&.00"(D+"200"(D+.600"(D+*:00"(D;%^ +M00"(D;""00"(D;.&00"(D;**00"$VW02#[:4-?S^__\/MI05V_W__^L",]+_ +M1?R!??P``0``B)"SCD$`B)"RDD$`B)"QED$`B)"PFD$`B)&S?D$`B)&R@D$` +MB)&QAD$`B)&PBD$`#XR/_?__7EO)PX`]T*]!``!6B_%U!>@,_?__B\9>PU6+ +M[(M%"(/L(%:+\5.)!C/`5XM]#(H<.(O(B]#!Z0*#X@-`C505X(@!0B\[H?/C__X,^`74'B\[HA?G__U[) +MP@P`58OL@^PD4U97BWT(B]F%_P^$E@```(MU#(7V#X:+````C4,$:A!0B44, +MC47<4.A,`0``P>X$B77\B74(A?9V5HMU$(U%[%!7B\OHL/G__XU%W%"-1>Q0 +M4.C<]___BP>)1=R+1P2)1>"+1PB)1>2+1PR)1>B+1>R)!HM%\(E&!(M%](E& +M"(M%^(E&#(/'$(/&$/]-"'6M:A"-1=Q0_W4,Z-L```"+1?S!X`3K`C/`7UY; +MR<(,`%6+[/]U"&H`_Q6X,$$`4/\5M#!!`%W"!`!5B^R#?0@`=!+_=0AJ`/\5 +MN#!!`%#_%;PP00!=P@0`58OL@WT(`'4*_W4,Z+?____K%?]U#/]U"&H`_Q6X +M,$$`4/\5P#!!`%W""`!5B^Q1:@&-10A0C44(4/\5>#)!``^V10A0_Q5\,D$` +MB47\:@&-1?Q0C47\4/\5@#)!`(M%_,G"!`!5B^Q1@V7\`.L'BT7\0(E%_(M% +M_#M%$',-BT4(`T7\BDT,B`CKY(M%",G"#`!5B^Q1@V7\`.L'BT7\0(E%_(M% +M_#M%$',2BT4(`T7\BTT,`TW\B@F(".O?BT4(R<(,`%6+[(M%$(M-$$F)31"% +MP'8ZBT4(#[8`BTT,#[8).\%]!8/(_^LGBT4(#[8`BTT,#[8).\%^!8/(_^L2 +MBT4(0(E%"(M%#$")10SKN#/`7<(,`%6+[%&+10@[10QS$/]U$/]U#/]U".AC +M____ZRB+11!(B47\ZP>+1?Q(B47\@WW\`'P2BT4(`T7\BTT,`TW\B@F(".OA +MBT4(R<(,`%6+[% ?P`BT4(#[X`BTT(08E-"(7`=`F+1?Q`B47\Z^:+1?S) +MP@0`58OLBT4(#[X`A+1?Q(B47\@WW\`'P8BT4(`T7\#[X`.T4, +M=0B+10@#1?SK!.O;,\#)P@@`58OL45 ?P`ZP>+1?Q`B47\BT4(`T7\#[X` +MABT4(#[X`ABT4(#[X`A?___UW""`!5B^R+10@/MP"+30P/ +MMPD[P74@BT4(#[<`AL$Z]SK!(-E[`!H?%Y!`&H,Z+[___]968E%^(-]^`!T#8M- +M^.CZ@/__B47HZP2#9>@`:(A>00!J%.B6____65F)1?2#??0`=`V+3?3H4>C_ +M_XE%Y.L$@V7D`&@XTT$`:`A/``#H:____UE9B47P@WWP`'0-BTWPZ)EY__^) +M1>#K!(-EX`#)PS/`PXM,)`R%R70CBD0D"`^VP&G``0$!`8O14U>+?"0,P>D" +M\ZN+RH/A`_.J7UN+1"0$PU6+[(-]$`!U!#/`7<.+30R+10C_31!T"HH0.A%U +M!$!!Z_$/M@`/M@DKP5W#BT0D!(7`?0+WV,/HX_[__S/`4%!04.C5+0``PU97 +MBWPD#(OQB\^)/NCSH/__B48(B58,BX<<#```B4807XO&7L($`(O!BPB+4!`[ +MD1P,``!U#6H`_W`,_W`(Z!RF___#58OL@^P<5C/V5E965HU%Y%#_%4@R00"% +MP'0A5E96C47D4/\53#)!`(U%Y%#_%5`R00"-1>10_Q54,D$`7LG#58OL@>PL +M`0``@SVP4$$``%-65[\`!```=3%J9(V%U/[__U!J#U?_%%]@^$HP````^W!F:%P`^$EP```(M]#(EU_,9%"P!J(EIF +M.\)U2(U.`F8Y$74A@'T+`'44.W7\=0\/MT8$9H/X+'0,9H7`=`>+\6:)%^LQ +MBET+A-MT!L9%"P#K#5)1Z*+[__^%P`^510LZ70MU%`^W!F:#^"QU!H!]"P!T +M%F:)!T='1D8/MP9FA6\G""`!5B^Q148U%^%#_%:PQ00"-1?Q0_W4,:@#_%:@Q +M00#_=0C_=?S_%;0Q00"+1?C_=?R+"%#_413)P@@`BT0D!&:#.`"+R'0X5@^W +M$6:#^EQU(`^W<0)F._)U#6I<6F:)$$!`@\$$ZQ%F@_YN=01J"NOK9HD00$!! +M06:#.0!UREXSR6:)",($`%6+[(/L*%-65S/_5_\5S#%!`(LU7#!!`%")1?C_ +MUO]U^(O8_]:)1?R-1=A0:AC_=0C_%4PP00"+1>`/KT4,F?=]W#M%$'T#B440 +M_W40_W4,_W7X_Q50,$$`_W4(BS54,$$`4XE%]/_6_W7TB44(_W7\_]9H(`#, +M`/]UX(E%\/]UW%=74_]U$/]U#%=7_W7\_Q58,$$`_W4(4__6_W7P_W7\_]:+ +M-60P00!3_];_=?S_UO]U^%?_%<@Q00"+1?1?7EO)P@P`@SU$(D(``'4G5FH` +M_Q7,,4$`B_"%]G07:EA6_Q5(,$$`5FH`HT0B0@#_%<@Q00!>H40B0@`/KT0D +M!&I@F5GW^<($`(,]2")"``!U)U9J`/\5S#%!`(OPA?9T%VI:5O\52#!!`%9J +M`*-((D(`_Q7(,4$`7J%((D(`#Z]$)`1J8)E9]_G"!`!J9.AS____@_A]?0]J +M9.BJ____@_A]?0,SP,,SP$##4XM<)`A65U/HZO?__XOX,\EJ`EJ-1P/WX@^0 +MP??9"\A1Z&?Z__]9B_!3C48"4.CN]___:B)89HE$?@)FB096,\!39HE$?@3H +MU??__U;H+OK__UE?7HO#6\($`%6+[(/L8%-65VIH_S4`PD$`_Q5P,D$`@#T4 +MTT$``(LUT#%!`(OXB7W\N[$```!U,HL-U+!!`.B=L?__:@57_Q5L,D$`:O]J +M`%-7_]9H-#=!`&H`:,(```!7_];&!13300`!OP#A]0575U/_=?S_UHU%H%!J +M`&@Z!```_W7\QT6@7````/_6,\!`@'T(`,9%N0")1:1T'(M-J('A____OPO( +MB4VHQT6TH````,=%I`$``$"-3:!14&A$!```_W7\_];_=0QJ`&C"````_W7\ +M_]975U/_=?S_UH!]"`!T'HM%J(/@_@T```!`B46HC46@4&H!:$0$``#_=?S_ +MUFA8-T$`:@!HP@```/]U_/_67UY;R<((`%6+[+@`&```Z`%8__^+10B%P'0F +M9H,X`'0FC4T,45"-A0#H__]0_Q7$,4$`C84`Z/__4&H!Z++^____!?C!00#) +MPU6+[+@`%```Z+]7__]H``0``(V%`/C__U#_=0S_=0CH`\'__X!]&`"-A0#X +M__]0=`1J9NL":F7H1NG__U"-A0#L__]H``8``%#H-OC__X/$$(V%`.S__U!J +M9?\U`,)!`/\5U#%!`.@V^O__,\`X!?+!00`/E,#)PA0`58UL))BX4!(``.A# +M5___4U>+?7`SVU-3:(`W00#_=7S_=7C_=717Z`AW__^$P'0(,\!`Z0L#``"+ +M170M$`$``%9T:4@/A?8"```/MT5X:@)>*\9T&(/H:G1-2'032'1#2'0\2'0U +M2`^%TP(``&H%7E-3:'$!``!J9E?_%>0Q00`[PW0'4/\5X#%!`%97_Q7<,4$` +M,\!`Z:<"``!J!NO0:@/KS&H$Z\@S]D;KQ&IL5_\5<#)!`%#_%=@Q00"^``0` +M`%;_=7R-A1CN__]0Z!XO``!64XV%&.[__U#HUKW__XV%&.[__U!J95>+/=0Q +M00#_UV@``0``:+0"``"-A1CV__]04XV%&.[__U#_%:0Q00!3_[48]O__:'`! +M``!J9O]U0P00"-15A0C45(4/\5X#!!`&HRC46`4%.-15A0:@)6 +M_Q7<,$$`:C*-1>104XU%6%!35O\5V#!!`(U%@%"-1>10:($```#H:>?__U!H +M;#=!`+L``@``C87,^/__4U#H4_;__X/$&(V%S/C__U!J:O]US\__\S +MVP/!$]-24.A?^/__:(````#H]^;__U"-A1S___]0:&`W00"[``(``(V%S/C_ +M_U-0Z-KU__^#Q!2-A+`00!0_Q6(,4$`C4584(U%4%#_%>`P00!J +M,HU%@%!J`(U%6%!J`E;_%=PP00!J,HU%Y%!J`(U%6%!J`%;_%=@P00"-18!0 +MC47D4&B!````Z$OF__]0:&PW00"-AS`00"+#>C`00!T!HO1"]!T16HRC94<____4E!1Z%OW +M__]H@````.CSY?__4(V%'/___U!H8#=!`(V%S/C__U-0Z-OT__^#Q!2-A@Q00!J`>O@_W44:F96_Q74,4$`,\!` +M7EW"$`!J`/]T)!#_="0,Z)7V__]0:`($``!J:O\U`,)!`/\5Y#%!`,(0`%6+ +M[+@`(```Z-92__^`/?+!00``=46+10QF@S@`=#Q6_Q6$,4$`B_"-11!0_W4, +MC84`X/__4/\5Q#%!`(V%`.#__U!H!#-!`.B(^O__65F%]G0'5O\5@#%!`%[) +MP_]T)"#_="0@_W0D(/]T)"#H:/___^A!]?__PB``58OLN&`>``#H7%+__U;H +MU2D``&C0-T$`:/L)0@#H@.___XL-+")"`&C\,D$`Z!,M``#_=0AH+!I"`.C. +M\/___W4(OCC300!J`(O.Z/-J__]J!%BC[`5"`*/H!4(`H^0%0@"@Y^@7X___4%?H"FC__X3`=#O_-5`B0@#K*FH` +M5_\5W#%!`.LH:``$``#_-5`B0@!J95?_%>@Q00!J`>O?B350(D(`5FIE5_\5 +MU#%!`#/`0%]>7<(0`%6+[+@`%```Z`51__^`?0A4=`^`?0A8=1#'10AY```` +MZP?'10@+`@``:``$``"-A0#X__]0_W40_W4,Z"VZ__^-A0#X__]0Z"6[__]0 +M_W4(Z'/B__]0C84`[/__:``&``!0Z&/Q__^#Q!"-A0#L__]0:@#H>/?__\G" +M#`!5B^R![`0(``"#9?P`4U:+=0A7ZP)&1@^W!E#HSB@``(3`=?$/MP9FA<`/ +MA&P!```S_S+;A-MU#0^WP%#HK2@``(3`=4N!__\#``!S0P^W!FHB668[P74E +MC48"9CD(=19F.4X$=02$VW0.9HF,??SW__^+\.L/A-L/E,/K"6:)A'W\]___ +M1T9&#[<&9H7`=:0SP/]%_(-]_`%FB81]_/?__P^$#X4.____:``$ +M``"-A0+X__]0:!+*00#K=L<%#,)!``(```#K"L<%#,)!``$```#&!1;300`! +MZ=G^__]H@````(V%`/C__U!H$M)!`.M!#[>%`/C__U#H0S$``(/X3`^%L/[_ +M_V:#O0+X__\`#X6B_O__Q@41PD$``>F6_O__:``$``"-A0#X__]0:!+"00#H +MG"<``.E[_O__7UY;R<($`%6+[+@`(```Z.9.__]3B]E7BWT(A=MT`\8#`(M% +M$(7`=`/&``"%_P^$H0````^W!V:%P`^$E0```%8S]C/)#[?`1T=F@_@]=16# +M?0P`=!N%]G47A=MT`\8#`8ORZQMF@_@-="AF@_@*="1FB0*+111"@\#^0CO( +M?PL/MP=!9H7`=;SK"HM%$,8``>L"1T>+70PSP&:)`H7;="]FB0.%]G0H:``0 +M``"-A0#@__]05O\5Z#!!`/]U%(V%`.#__U!3Z,PF```SP&:)!HO'7NL",\!? +M6\G"$`!5B^R#[!Q6BS7L,$$`5VH*_W4(_]:_`@$``.L9:@%J`&H`:@"-1>10 +M_Q5(,D$`:@K_=0C_UCO'=.-?7LG"!`!5B^R!["`(``!H``0``(V%X/?__U#H +M&V0``(`]%=-!``!U:VH&_S6<4$$`C87@]___4.@&N/__4.@\+P``A#W__]0Z`'L__\SR6H>9HF,1>+W__]1C47@4.B\Z/__:A18 +M9HE%\(V%X/?__XE%Z(U%X%#'1>0#````_Q6@,4$`R<-5B^RX!"```.A!3?__ +M4U9H```"`.CCY___B_"%]G4*N7Q>00#HZV___S/`9HD&,]OK;6:#/@!U"F:# +MO?S?__][=%UF@[W\W___?71WC87\W___4.APZ___`\,]^_\``'=BC87\W___ +M4%;H\>O__U;H5.O__XO8A=MV$8U$7OYF@S@@=0=+2$B%VW?S@'W_`'4.:%@W +M00"-!%Y0Z%/K__]H`!```(U%_U!J`/\W,\F-E?S?___HHOW__XD'A<`/A6__ +M__^+QEY;R<-3,]O&!?'!00`!.1T`PD$`=!9J?>@BWO__4&H"_S4`PD$`_Q74 +M,4$`H0#"00")'?3!00#&!?#!00`!.\-T2VH!4/\5;#)!`#D=)--!`'4(.!T4 +MTT$`=`@Y'?C!00!U(E-J`6@1`0``_S4`PD$`_Q70,4$`ZPQ3_Q7P,$$`Z-GN +M__\Y'0#"00!U[#@=",)!`%MT!>D0_O__P_]T)`16Z(?J__\SR68Y#G0GB\8/ +MMQ!F@_HZ=`QF@_I<=`9F@_HO=09J)5IFB1!!C01.9H,X`'7;P@0`58OL@>P( +M"```4S/;.!T0PD$`=&QF.1W8L$$`=&-6:-BP00"-M?CW___HE____XU%^%"- +M1?Q04V@&``(`4U-3:/0W00!H`0``@/\5$#!!`%Z%P'4L_W4(Z-#I__^-1``" +M4/]U"(V%^/?__VH!4U#_=?S_%10P00#_=?S_%1@P00!;R<($`%6+[+@,$``` +MZ"!+__^`/1#"00``#X2-````5O]U"(VU].___^@7____C47X4&H!:@!H]#=! +M`&@!``"`_Q4`,$$`7H7`=6&-1?Q0C87T]___4(U%]%!J`(V%].___U#_=?C' +M1?P`"```_Q4,,$$`APQ00!H'#A!`(V%Y/?__U#H]"H` +M`(7`=6%J\%?_%4`R00"#X!\\#G51:@!J`&AS`0``5__3B_"%]G0_C47D4&H8 +M5O\53#!!`/]U[.C\[___4/]UZ.BP[___4%;HY.[__U!J`&AR`0``5__3.S78 +MN$$`=`=6_Q5@,$$`:@)7_Q64,D$`B_@[??QT"_]%"(7_#X5/____7EM?R<($ +M`%:+="0(:B!6Z&#I__^%P'0:9H,^(G045N@TL/__9H,X(G0(5NCI[___ZP*+ +MQE["!`!5B^Q6BS7P,4$`@#WFP$$``(M%#*/HP$$`BT40H^S`00"+112CX,!! +M`'0%,\!`ZRF`/>?`00``=`5J`ECK&_]U"&BNND``_S4`PD$`:(`W00#_-71> +M00#_UDAT3TAT7DAT0DAU(_]U"&CZO4``_S4`PD$`:*`W00#_-71>00#_UH7` +M=(:P4NLP2'0.2+!.=2C&!>?`00`!ZQ_&!?+!00`!L$/K%,8%YL!!``%J`/]U +M"/\5U#!!`+!97EW"$`"P3NOW58OL@>P`"```4U:+=0Q7BWT(:``$``"-A0#X +M__]05E?HT['___]U&(V%`/C___]U%/]U$%#H!?___XK8A?9T$V:#/@!T#8V% +M`/C__U!6Z.[F__^%_W07@#\`=!)H`````5>-A0#X__]0Z/HF``!?7HK#6\G" +M&`!5B^R![``(``!F@ST2TD$``%9T$?]U&(MU%&@2TD$`5NF+````@WT(`J$` +MPD$`B_!U#5#_%?0Q00"%P'4",_9H``0``(V%`/C__U#_=1#_=0SH*['__V:# +M/?#`00``=3&-A0#X__]0:(.^0`!6:+0W00#_-71>00#_%?`Q00"%P'4/BW44 +M9HD&Q@7RP4$``>L.BW44:/#`00!6Z"OF__]F@SX`=!!H@````%9H$M)!`.A% +MYO__,\!F.09>#Y7`R<(4`%6+[('L``@``%9H``0``(V%`/C__U#_=0S_=0CH +MGK#__XV%`/C__U!H.\!``/\U`,)!`&C4-T$`_S5X7D$`_Q7P,4$`@WT(`(OP +M=!1H`````?]U"(V%`/C__U#HSR4``(-]#`!T#XV%`/C__U#_=0SHD^7__XO& +M7LG""`!5B^RX0!```.C;1O__4U:+\3/;9CD>#X0;`@``5NA`Y?__/?8#```/ +M@PH"``!7:CQ?5U.-1%P`^5P(3`#X2O````BS5L,D$`,MLX +M'0C"00!U!3A="'0VH0#"00"%P'074/\5]#%!`(7`=`QJ`/\U`,)!`/_6LP%H +MT`<``/]U^/\5^#%!`/]U^.CY]O___W7X_Q5\,4$`@WW\`'01:"PX00#_=?SH +MV"4``(7`=#"`/0C"00``=`V`?0@`=0=H6!L``.L4,\`X10@/E,!()>#\__\% +MZ`,``%#_%?`P00"$VW00@'T(`'0*:@'_-0#"00#_UE]>6\G"!`!5B^RXV%`! +M`.B>1/__@WT,``^$$`L``&@`$```C44/4(V%T,?__U#_=0R-3?^-E2AO___H +M@/7__XE%#(7`#X3D"@``4U97:@:[``0``(V%T,?__XVU**_^_U]64.@9Z/__ +M@<8`(```3W7P,_;_-+6X4$$`C84H;___4.@*)0``A`0``BSU$,4$`:@"-A2BK__]0_Q74,$$`@+TX +ML___``^$J````.@6IO__.\,/A)L```"-A=#O__]0C870]___4.@=K/__C870 +M[___4.APJO__C870]___4.BAX?__B_"#_@1R$(V%T.___U#HCN'__SOP=Q:- +MA=#'__]0:@#HW:G__X3`#X77````C84HJ___4.AHX?__,\EJ'F:)C$4JJ___ +M48U%T%#H(][__VH46&:)1>"-A2BK__^)1=B-1=!0QT74`P```/\5H#%!`(V% +M**O__U#_UX/X_W1JC84HJ___4/\5;#!!`(7`=5DS]NL!1E:-A2BK__]0:.PX +M00"-A=#O__]34.@QX___@\04C870[___4/_7@_C_==2-A=#O__]0C84HJ___ +M4/\5<#%!`(7`=!%J!&H`C870[___4/\5^#!!`&H`C84HI___4(V-R+O__^CF +ME?__A,`/A:C^__^-C__]F +M@[Q%SO?__UQT$6B(-D$`C870]___4.ABW___5NC%WO__B_B-A=#W__]0Z+?> +M__\#^('__P,``',<5HV%T/?__U#H-]___^L-5HV%T/?__U#HN][__VHBC870 +M]___4.@4X/__A`(`=04SR6:)"(V%T/?__U"_V+!!`%?HB][__U.- +MA=#W__]0Z*WT__]J9O]U"/\5<#)!`(OPC870]___4%;_%3`R00"+'=`Q00!7 +M:@!H0P$``%;_TXV%T/?__U!7Z-#>__^%P`^$Y@4``(V%T/?__U!J`&A#`0`` +M5O_3Z=`%``"#/0S"00`!#X3#!0``#[>%T,?__U#HKQ<``(3`=!0/MX70Q___ +M@^@PHPS"00#IG@4``,<%#,)!``(```#ICP4```^WA=#'__\KQW0K@^@P=!-( +M="-(#X5U!0``Q@7GP$$``>L'Q@7GP$$``,8%YL!!``#I604``,8%Y\!!``#& +M!>;`00`!Z48%```/MX70Q___4.C^V?__@_A&="2#^%5T$\8%Y3` +M00``Z1P%``#&!>3`00`!Z1`%``#&!>7`00`!Z00%``"#?1`$=2%H<#A!`(V% +MT,?__U#HS]W__X7`=`Q7C8W0Q___Z*CW___&!2C300`!Z=$$``"#?1`!#X6' +M`0``C870[___4%/_%?0P00"-A=#O__]0Z)VE__\S]E;_-9Q000"-A=#O__]0 +M:&`X00"-A=#G__]34.CVWO__BSU$,4$`ZR%&5O\UG%!!`(V%T.___U!H8#A! +M`(V%T.?__U-0Z,W>__^#Q!B-A=#G__]0_]>#^/]USHV%T.?__U!J9O]U"/\5 +MU#%!`#/_9CF]T,?__P^$,`0``(`]%M-!```/A2,$```SP&:)A=#[__]J+(V% +MT,?__U#HG=W__X7`=4WK(8TT"8V$-=+'__]0C870^___4.@BW/__,\!FB80UT,?__V8YO=#[ +M__]U)HV%**_^_U"-A=#'__]0Z/S;__^-A2C/_O]0C870^___4.CIV___C870 +MQ___4.@&XO__,\!FB870U___:B2-A=#[__]0C870Q___4/]U"/\5:#)!`(/X +M!@^$6P,``&H!_W4(Q@45TT$``<8%\L%!``'_%=PQ00`S_X-]$`GG_?__@WT0!@^%Q0(```^WA2BO_O]0Z'W7__^#Z%!T(X/H`W05 +M2'0)QT7X$````.L9QT7X!P```.L0QT7X"P```.L'QT7X`@```#/`9HF%*)?_ +M_V:)A=#G__^-A2C/_O]0C870[___4.B]VO__9H.]T.___R)U0XV%*L_^_U"- +MA=#O__]0Z*#:__]J(HV%TN___U#HS-O__SO'#X2R````,\EFB0B#P`)0C870 +MY___4.AUVO__Z9@```"-A=#O__]0Z)F'__^$P`^%A````#/;C;70[___9CF= +MT.___W1S#[<&9H/X('0&9H/X+W53#[?X,\!FB0:-A=#O__]0Z%V'__^$P'0X +MB]YF@_\O=19J+UAFB870Y___C48"4(V%TN?__^L/1D9F@SX@=/A6C870Y___ +M4.CQV?__9HD[ZP-FB3Y&1F:#/@!UEH7;=`4SP&:)`S/V9CFU*$___W03C84H +ME___4(V%*$___U#H+J/__XV%*(___U"-A=#O__]0Z!NC____=?B-A=#W__]0 +MZ(??__^-A=#W__]0Z"6B__]F.;4H[_[_=!^-A2CO_O]0C870]___4.C=V?__ +MC870]___4.C]H?__C870]___4(V%T+___U#H4=G__XV%*"___V8YM2@O__]U +M!HV%*,_^_U#H\:3__U"-A=#W__]0Z);9__^-A=#W__]0Z&JG__\[QG0/:%0X +M00!0Z$@;``"%P'01:%0X00"-A=#W__]0Z&;9__]J`8V%T/?__U#H"8C__XV% +M*(___U"-A2B?__]0Z-C8__^-A2B?__]0Z,NG__^-A=#G__]0Z+H1``!0C84H +ME___4.BM$0``4(V%*`___U#HH!$``%"-A2B?__]0Z),1``!0C870]___4(V% +M*(___U#H;$\``&8YM="___]T)6H`C870O___4&H%:``0``#_%9@Q00#K#8-] +M$`=U!\8%$,)!``%H`!```(U%#U"-A=#'__]0_W4,C4W_C94H;___Z)_J__^) +M10R%P`^%(O7__U]>6\G"#`"0\\U``.W/0`!^T$``G-!``'W20`"^TD``2=-` +M`'S30``UU4``;=5``'[50`!`V$``!]-``%6+[+CX?0``Z#XY__]3Z+<0```S +MVU.-C0B"___HW3____]U"(V-"(+__U/H:3[__XU%]%"-1>A0C8T(@O__B5WH +MB5WLB5WPB5WTB5WXB5W\Z&!!__^$P'0WBT7X5E>--`"+^(U&`E#HC=/__XM- +M#(D!.\-U!#/_ZQ`SR59FB0P&_W7T4.@ZU/__BT40B3A?7CE=]'0(_W7TZ'73 +M__\Y7>A;=`C_=>CH9]/__XV-"(+__^BW0/__R<(,`%6+[%-7BWT(,]M34VC4 +M.4$`_W44_W40_W4,5^A36/__A,`/A=P```"+10PM$`$``'0>2'4.#[=%$$@/ +MA+L```!(=`W__VIE5_\5<#)!`&@` +M``$`:@"+V&@U!```4__6:@__%0`R00!0:@!H0P0``%/_UFH#_S48TT$`5^@A +M\___@ST@TT$``%YT+%?_%?PQ00#_-2#300"+#="P00!3_S5T7D$`Z`R9____ +M-2#300#H7]+__^L):@%7_Q7<,4$`,\!`7UM=PA``58OLN%QI``#H=S?__U-6 +MBW4(,]M34VBX.D$`_W44_W40_W4,5N@\5___A,!T"#/`0.FM!P``BT4,+1`! +M``!7#X0"!0``2'4/#[=%$$AT;TAT/H/H970',\#IA`<``(V%Q/?__U!J9.C. +MR/__4%;H14W__X3`#X1D!P``C87$]___4&IF5O\5U#%!`.E/!P``B1T`PD$` +MQ@7RP4$``3D=],%!`'0,.1WXP4$`#X4N!P``4U;_%=PQ00#I(0<``&@`!``` +MC87$]___4&IF5O\5Z#%!`#@=\<%!`'09B1T`PD$`.!WPP4$`=`?&!?+!00`! +M:@'KOC@=\,%!`'0/,__&!?+!00`!1^G.`P``:FA6_Q5P,D$`B44,.1WXP4$` +M=2&+/=`Q00!J_U-HL0```%#_UV@T-T$`4VC"````_W4,_]?_=0S_%=@Q00`X +M'0C"00!T#&BF````Z-_'___K2XV%Q/?__U"-A<#O__]0Z+C4__^-A<#O__]0 +MZ'GL__^-A<#O__]0:*4```#HK#^`5U!,9%#P'H1)C__X7` +M='(X'1'"00!U:CA=$W1^_Q60,$$`4&A\.D$`C87$[___:``$``!0Z!+6__^# +MQ!"-C:3?___HP7?__S/_1U>-A<3O__]04XV-I-___^@->___B$43.L-U#_\5 +MA#%!`(/X!74$QD4/`8V-I-___^AN>?__ZP,S_T.1WXP4$`=18Y'2S300!U#FH$_S48TT$`4^@.[O__5U=6 +MZ%!2__^)'?3!00`Y'?C!00!^5S@=\L%!`'5/:GW&!?'!00`!Z$/$__]05U;_ +M%=0Q00"A?%Y!`(/X"74%C5AZZP\SVX/X`P^5PTN#XP6#PW]J,&I^Z!/$__]0 +M4^@,Q/__4%;_%6@R00#K"%=6_Q7<,4$`B\?IFP(``*'0Q +M00!6Z'CG__^+/7`R00!J:%;_UV@``$``4V@U!```4(E%%/\5T#%!`&@`!``` +MC87$[___4.@@2```:F96_]>)11"X$L)!`&8Y'1+"00!U!HV%Q.___U#_=1#_ +M%3`R00#_=1#H"4@``&@DTT$`:!C300!HX+A!`(@=%--!`.@V^/__.1TDTT$` +M=@YJ!_\U&--!`%;HP.S__S@=%--!``^%A````#/`OY8```!FB86DEO__B7T, +M.7T,=0@X'2C300!T-X%]#)<```!U"#@=*--!`'4F:.PY00"-A:26__]0Z##0 +M____=0SHS<+__U"-A:26__]0Z!O0____10R!?0R<````?K`Y'0S"00!U&XL- +MU+!!`(V%I);__U#_=13_-71>00#H1)+__XL]U#%!`#@=*--!`'4@:*L```#H +M><+__U!J:U;_UVBJ````Z&G"__]0:@%6_]1____ +M-1S300#H*LO__X,]#,)!``%T.%;_%?PQ00"#/0S"00`!="@X'1'"00!U(%-H +M;]E``%-HU#E!`/\U=%Y!`/\5\#%!`(7`#X2'^?__:@'_-1C300!6Z&GK__^# +M/0S"00`"=0I3_W40_Q5T,D$`.!T(PD$`=!)3:F=6Z(]/__]3:F96Z(9/__^A +M#,)!`#O#="0X'?+!00!U'%-J`6@1`0``5H/X`74(_Q70,4$`ZP;_%00R00`X +M'?#!00!T#6I]Z&'!__]0:@%6_]__\X +M'1'"00!T16@,.D$`4VH$_Q4,,4$`B47\.\-T)6@```(`4U-J!%#_%00Q00"+ +M\#OS=`A6:-PZ00#_UU;_%?PP00#_=?S_%7PQ00#K"%9HW#I!`/_7:``$``"^ +MX+A!`%93_Q6H,$$`5FC,.D$`_]=3_Q6P,$$`B_AJ9%>)/71>00")/7A>00#_ +M%0PR00!J9?\U>%Y!`*/D4``%:YB%Y!`.A' +MP/__C4W`Z#.'__^-3=SH*X?__VIDZ&_4__]J9(E%V.AEU/__4VA\VD``B47T +M4XU%P*/4L$$`:+@Z00"-1=Q7H]"P00#_%?`Q00"-3=R)'="P00")'=2P00#H +M]H;__XU-P.CNAO__C4WXZ%9%```X'0C"00!T!>A2X/__:``!``!3:/#`00#H +M:\G__SD=)--!`'8+_S48TT$`Z-3(____-=RX00"+-6`P00#_UJ'8N$$`.\-T +M`U#_UCD=?%Y!`'47.!WRP4$`=`]H_P```+E\7D$`Z"%0__^A+--!`,8%\L%! +M``$[PW0&4.BAW____Q6T,D$`_S5\7D$`_Q7(,$$`S%6+[(/L)(!]$`!35E=T +M$FI`_W4,NZ`H0@!3Z`3)___K`XM=#(`]F"A"``!U3#/)OEPB0@"-00&9:@5? +M]_^-00*)3OR)%IGW_XU!`X/&%(E6\)GW_XU!!(E6])GW_XE6^(7)=`-)ZP-J +M!%F!_IPH0@!\PL8%F"A"``&+=0AJ!5F-?=SSI;AD(D(`B5T0BW40BQ:+RL') +M"('A`/\`_\'""('B_P#_``O*B0Z+/R+?+W<@T40!(UTM=R) +M=0R+<`2-=+7<,_J)=?B+06#YP\S!+N#X0\S!(LS!M'`B0:+OR+?+WAZ]EN`3#!"0+_11"#PA2!^H0E0@!\A;F`)4(`QT40*````(E-#(M% +M$(U0_8/@#XTT@XU"^X/@#XL$@XUZ!8/G#S,$NX/B#S,$DS,&T<")!HM1_(MY +M"(LQBW2UW(U4E=R-?+W?B+202+3(W6UW"$`!5B^R#[!!6BW4(,\"+T(/B +M`VH#62O*P>$#@_@$&]+WVHM4EA33ZD"(5`7O@_@(_O__,]N)7?R+1?R+50S!X`*+##")#!#_1?R#??P% +M!(0@!`H^!(0@"#^`1R!S/`H^!(0@!6P>`+!>`H0@!H +M``0``(OP5O]T)!#HKP4``#/`9HF&_@<``(O&7L($`%:^Z$A"`%;_="0,_Q44 +M,D$`B\9>P@0`@V$,`(-A'`##BT0D!%:+\0%&!(M.!(M&"#O(=BR+T,'J`E>- +M?`(@.\]V`HOY5_\VZ#W!__^)!H7`=0JY?%Y!`.@-2?__B7X(7U["!`!6B_&# +M9@P`@V8<`.@<$0``C4X0Z!01``"#9B``@Z:D`````%[#58OL4XM="%97B_&% +MVW4%NS(W00"#?0P`=0?'10PT-T$`BWX$4^@VPO__0%"+SNAD____BP93`\=0 +MZ!7#____=0R+7A2-?A#H2,3__T!0B\_HM";__XL'_W4,C0184.A;Q/___T8@ +M7UY;7<((`%:+\8M&##M&!'-#BTX<.TX4Q,0@"#^#)^+(`]\L%!``!T'E97O_\```"^?%Y!`%>+SNC&1O__ +M5XO.Z`%*__]?7ND_Q___PV@`.T$`_Q6P,$$`AIFBT8(9HE%[F:+1@QFB47P9HM&$&:)1?)FBT849HE%]#/`9HE%]HU%^%"- +M1>A0_Q4<,4$`BW88`77X.77X7G,#_T7\_W4(C47X4/\5&#%!`,G"!`"+$8M$ +M)`0[$'4UBU$$.U`$=2V+40@[4`AU)8M1##M0#'4=BU$0.U`0=16+410[4!1U +M#8M)&#M(&'4%,\!`ZP(SP,($`(L!@^@\P>`$"T$$P>`%"T$(P>`%"T$,P>`& +M"T$0BTD4P>`%T>D+P<.+1"0$B]"#XA\#THE1%(-A&`"+T,'J!8/B/XE1$(O0 +MP>H+@^(?B5$,B]#!ZA"#XA^)40B+T,'J%<'H&8/B#P6\!P``B5$$B0'"!`"+ +M3"0$]L$#=2%6B\%J9)E>]_Y>A=)U#HO!F;F0`0``]_F%TG4%,\!`ZP(SP,($ +M`(O!@R``PU6+[(/L(%97C47X4/]U"(OQ_Q7D,$$`C47@4(U%^%#_%>`P00`/ +MMWWH#[=%Y@^W3>(/MU7@B7X,#[=]ZHE&"(E^$`^W?>Q(B48@,\")?A0/MWWD +M0(D6B4X$B7X<.\AV%+_L4$$`4XL?`5X@0(/'!#O!R<($`%6+[%%15C/V.3%U!C/`,]+K'HU%^%#HUOW__VH!5E;_=?SH +M+R#__XM-^#/V`\$3UE[)PU-6B_&+3"0,5^B_____B\Z+V(OZZ+3___\[UW\+ +M?`0[PW,%,\!`ZP(SP%]>6\($`%-6B_&+3"0,5^B/____B\Z+V(OZZ(3___\[ +MUWP+?P0[PW8%,\!`ZP(SP%]>6\($`%;_="0(B_'HQ/___X3`=1/_="0(B\[H +MK_W__X3`=00SP.L#,\!`7L($`%6+[(/L&%:-1>A0B_'_%2`Q00"-1?A0C47H +M4/\5'#%!`(U%^%"+SNA@_O__7LG#,L#"%`!5B^Q1BT4,4S/;4U/_=1#&1?\! +M4&K__W4(B!A34_\5E#!!`(7`=0.(7?^*1?];R<(,`(M$)`A3_W0D$#/)4&K_ +M_W0D%+,!45%FB0C_%20Q00"%P'4",MN*PUO"#`"+1"0(5C/V.70D$'8?BTPD +M"(H1B!1PBE$!B%1P`6:#.0!T"49!03MT)!!RY5["#`!5B^Q6,_8Y=1!V+8M- +M"(M5#"O15V8/MD$!OP`!``!F#Z_'9@^V.68#QV:)!`IT"$9!03MU$'+=7XM% +M#%Y=P@P`58OLBT40BU4(2%.)11"*`E97BWT,A,`/A!H!``!J/UX/MLA"B\&! +M^8`````/@L````"#X.`]P````'4CB@**V(#CP(#[@`^%ZP````^^P(/A'R/& +MP>$&"\%"Z9,```"+P8/@\#W@````=3:*`B3`/(`/A<````"*6@&*PR3`/(`/ +MA;$````/O@*#X0\CQL'A!@O!#[[+P>`&(\X+P4)"ZU&+P8/@^#WP````#X6& +M````B@(DP#R`=7Z*0@$DP#R`=76*6@**PR3`/(!U:@^^`H/A!R/&P>$&"\$/ +MODH!P>`&(\X+P0^^R\'@!B/."\&#P@/_31!X0#W__P``=BK_31!X-#W__Q`` +M=RV-B```___!Z0J!Z0`H``!FB0]')?\#``!'+0`D``!FB0>*`D='A,`/A>G^ +M__\SP&:)!U]>6UW"#`"P`<-5B^RX`!```.@5'___Z,R!__^%P'0>:O__=0QJ +M__]U"&@!$```:``$``#_%2@Q00!(2.LZ5KX`"```5HV%`/#__U#_=0CHH_W_ +M_U:-A0#X__]0_W4,Z)/]__^-A0#X__]0C84`\/__4.AR]O__7LG""`!5B^RX +M`!```.BC'O__5KX`"```5HV%`/#__U#_=0CH.XC__U:-A0#X__]0_W4,Z"N( +M__^-A0#X__]0C84`\/__4.@G]O__7LG""`!5B^SH&8'__X7`=%565_]U".C) +MO/__BW40.\9S#/]U".BZO/__B_CK`HO^_W4,Z*R\__\[QG,*_W4,Z*"\___K +M`HO&4/]U#%?_=0AH`1```&@`!```_Q4H,4$`2%](7NL+_W4,_W4(Z$G___]= +MP@P`58OL@^P@Z*:`__^%P'0+_W4(_Q68,D$`ZTE6BW4(,\!FB47B:@J-1?10 +MC47@4&:)=>#HB?S__X!]]#]U!(O&ZR'_=?3HK_7__XA%]&@````!C47@4(U% +M]%#HE/S__P^W1>!>R<($`(M4)`0SP.L29H/Y.7<5:\`*#[?)0HU$"-!"#[<* +M9H/Y,'/EP@0`58OL@^P45E>-1>Q0,_96B_G_%3`Q00"#?>P!#Y?`B(<``0`` +M5O\5+#%!`(7`#Y7`B`0^1H'^``$``'+H7U[)PXM$)`0/MA"`/`H`=`N`>`$` +M=`6#P`+K`4#"!`"+1"0$5NL7#[;R@#P.`'0$0$#K"@^^TCM4)`QT"4"*$(32 +M=>,SP%[""`!6BW0D"(H6,\"$TG0A5P^V^H`\#P!T!$9&ZPP/OM([5"00=0*+ +MQD:*%H32=>%?7L((`%:+\>A`____B\9>PXM$)`P/ME0(!(M$)`@/MD0(!"O" +M:](,`U0D!%8/MG0(*500#HLS[__S+`ZPZ-1##TB8=8`0``B1^P +M`5Y?6\($`%6+[%%14U97:)@```"+\6H`C8:X````4.@#M___BSZ+QYF#X@<# +MPL'X`VH,6S/2]_-J##/2BXZL````B8Y0`0``B]AKVU0K^XO'B47X7_?W:@PS +MTD!KP`R-/`B+1?@#R(F.7`$``%F+P_?Q:@1:4HF^5`$``(F^L````%EKP`P# +MQXF&M````#/`0(A$!@-`2G7X0(A$#@1!0$"#^0A\]$#K"(A$#@1!@\`#@_D, +M?/-`ZPB(1`X$08/`!(/Y)GSS,\G'1?S7____*77\B(ZJ````C48JQT7X@``` +M``^V5`X$BWW\,]L#^#O7#YS#`\N("$#_3?AUY5]>6\G#58OLBT4,4U:+\0^V +M7#`IBT40#[94,"F)70P[VG4%BT4(ZT2-C):X````5XLYA?]T)HM="&O`#(L7 +M4%-7B1'H#[;__XM%#(V$AK@```"+"(D+B1B+Q^L/4E/_=0B+SNC3_?__BT4( +M7UY;7<(,`%-55HMT)!"+AE`&```/M@"*A#!L"0``B(9N"@``5XUY`HM)"`^W +M"0^V%P^VE#)L"0``#[9?`0^VC#%K"```P>,%`].-C%'X!```BY9D!@``P?H: +M@^(@`\H/MI9M"@```\H/ML"-EG!*``#!:@@.BVH(`\B+0@0K`C/2]_6-#$X/ +MMQD[PW-&B;Y0!@``BD?$H```^W`0^WT(/" +M(,'Z!RO"9HD!QX:`2@```$````^W`8J.;`H``,'H"@^V@!0[00")AE@&``#' +MAE0&```!````#[8'B(PP;`8``(.F4`8```#&AFT*````7UY=6\($`&@``0`` +MQH%L"@```6H`@<%L!@``4>AOM/__PXV!>,H``(L0B9%\R@``C9%TR@``5HLR +MB3"-@7#*``"+"(D*BTPD"(D(7L($`%6+[%-6B[&,R@``B\8K10RZ__X_`%<[ +MP@^#L````#OR#X.H````BY$TS```BWT(`\(#U@/W:@B)L8S*``!>._YR/(O/ +MP>D#BAB(&HI8`8A:`8I8`HA:`HI8`XA:`XI8!(A:!(I8!8A:!8I8!HA:!HI8 +M!XA:!P/&`]8K_DEUR87_#X:"````B@B("H/_`79YBD@!B$H!@_\"=FZ*2`*( +M2@*#_P-V8XI(`XA*`X/_!'98BD@$B$H$@_\%=DV*2`6(2@6#_P9V0HI`!HA" +M!NLZ@WT(`'0TO___/P"+L33,``"+F8S*``#_30B+T"/7BA0RB!0>BY&,R@`` +M0$(CUX-]"`")D8S*``!UT5]>6UW""`!6B_&+CI3*``"+!E>+^2OX>00RP.MA +M/0!```!^'(7_?@V+3@A7`\%04>BTL___@R8`B;Z4R@``ZP*+^8M.#+@`@``` +M*\>#X/!0BT8(`\=0Z/2?__^%P'X&`8:4R@``BXZ4R@``@^D>B8Z8R@``,\F# +M^/\/E<&*P5]>PU:+\8N65,P``(N&1,P``#O0BXY`S```5XN^4,P``'\[?`0[ +M^7,U*\\;PC/_._A3BUPD%'P(?P0[V78"B]F+3@Q3_W0D%.CFH/__BT0D%`&& +M4,P``%L1OE3,``!?7L((`%6+[('L@````%.+71!6BW4,5VI`,_]7C47`4(D> +MZ#:R__\SR3O?=A6+10@/M@0!@^`/C42%P/\`03O++ +M30R+3(V\`PH#P/]%#(EZQ(E*!(/"!(-]#!!RTVI`4XU%@%#HYK'__XM]$#/2 +MA?]V(HM%"(H$`B0/=!,/ML"-1(6`BPB)E(Z(%```08D(0CO7 +M`\+#B\&*2`*`^0=S%/Y(`W4/9M$@L@/2XO[!B$@"B%`#PU6+[%%15HMU"%>- +M??BE9J6+=0R+?0BE9J6+?0R-=?BE9J5?7LG""`"+`87`=`90Z/FO___#5HOQ +M@3[B?P``?@7H.OW__XL.BT8(#[8$"$&)#E[#5HOQBP:%P'0)4.C+K___@R8` +M@V8$`(-F"`!>PXM$)`16B_$!1@2+3@2+1@@[R'8QB]#!Z@)7C7P"(#O/=@*+ +M^8O'P>`"4/\VZ*RO__^)!H7`=0JY?%Y!`.A\-___B7X(7U["!`"+1"0$5HOQ +M@V8$`(,F`(-."/]7:@2)1AA?BTX8Z%S___^+3@3!X0@+R$^)3@1UZE]>P@0` +M58OLBX&P````@^P0.X&T````=`/&``!35HU%\%>)1?B)1?2->02-D;@```#' +M1?PF````OO__``#K*(L"BQB)&HU=\(E8"(M=](E8!(M=](E#"(O>B47T9HD8 +M9@^V'V:)6`*#.@!UTX/"!$?_3?QU\HM5](U%\#O0#X30````ZRP/MW@"#[=: +M`@/[@?\```$`?2J+>`B+6`2)7P2+>`2+6`B)7PAFBT`"9@%"`@^W0@)KP`R+ +M_@/"9CDX=,2+4@2-1?`[T'7FZ8````"-0@2+&(/""(LZB5\$BP"+$HE0"`^W +M1@(]@````'XHC9!_____P>H'0HOZ:_^``\>+N4P!``")/HFQ3`$``('&``8` +M`$IUZ0^V?`$I#[94.00[T'0>#[9<.0-/B]`KTRO":\`,C921M````(L:`\:) +M&(D"C82YN````(L0B1:),(M5](U%\(OR.]`/A7#___]?7EO)PU:+\8"^J@`` +M``!7BWPD#'4?QH:J````_^B#_O__C8R^N````(L!AP@0`C9&T````BP([@;````!T!H/`](D"PXV1N````(,Z`'0'BP*+ +M"(D*PVH`Z-_^___#58OL4U:+=0Q7B_D/MEP^*0^V1#XJ.]AU!8M%".LNC48! +M4.A4____B44,A +M6UW""`!3B]F+3"0(@<&,2@``Z&O___^%P'0>5HMT)!17,\E!9HD(BTPD%(UX +M`J5FI5^)6`B)00)>6\(,`(O!,\F)B(Q*``")B$0&``")B$P&``")B$@&``## +M58OL@^P44U97OP`!``!7B_%J`(V&;`8``%#H?*S__XV>C$H``(O+Z$_U__^+ +MAF`&``"#^`Q\`VH,6(/)_RO(B8YH!@``B\OHW/[__XF&3`8``(F&1`8``(-@ +M"`"+AF`&``")AEP&``"+AD0&``!FB3B+AD0&``"Y`0$``&:)2`*_@````%>+ +MR^A&_O__BXY$!@``B4$$BX9$!@``BT`$B890!@``BX9H!@``,\F)AF0&``"( +MCFT*```SP(N61`8``(M2!(@,$(N61`8``(M2!,9$`@$!BY9$!@``BU($@V0" +M`@"#P`9!/0`&``!\S8-E_`"-AG`*``")1?"+7?R+1?"#PP*Y)#M!`(E%](M% +M](E%^,=%[`@````/MP&9]_NZ`$```"O0BT7X@T7X$/]-[&:)$'7D@T7T`D%! +M@?DT.T$`?,G_1?P!??`Y??Q\K3/2C4X#C4(":A!KP"A>QD'_`V:)0?W&`02# +MP01.=>]"@_H9?.!?7EO)PXM$)`135HOQ,]M#5XB>;`H``(F&8`8``.AK_O__ +M:@EJ!(V&;@@``%#&AFP(````QH9M"````NCHJO__:/4```!J!HV&=P@``%#H +MU:K__S/`B(0&;`<``$"#^`-\\XO0B_NY``$``.L/3XB4!FP'``!U!$.+^T)` +M.\%\[6I`:@"-AFP)``!0Z)BJ__]HP````&H(C8:L"0``4.B%JO__7\:&0@8` +M``=>6\($`%6+[(/L(%.+V0^W`XE%Z$B)1?R+10B+@%`&``!65^L,C7#Z5E#H +MG?G__XO&.T,$=>^+2P2`00$$C4L"9H,!!`^W$0^V<`$/M](KUHMU"(E5^#/2 +M.99R#P`:) +M5?`#UM'ZB%`!9@^VTF8!$8I0`3I0^W8UB_"-?>"EB]!FI8UR^HOZI8/J!F:E +MB57P.U,$=!"+5>"+=?#!Z@@Z5ON+UG?=C77@B_JE9J7_3?QUH$"`.`!UR-??"E9J6+5?#! +MZ@B*VM#K*M/1^(/X`8A5\7_JBT7HBU4(BW7L0-'X#[:$$+5*``"-A()$2P`` +MBSB)/HDPB8I0!@``C77PB_FE9J7K/HM%^(O0T?HKPF8!`8M-Z`^W`T'1^4#1 +M^#O(=!9048M-"/]S!('!C$H``.C:\O__B4,$BT,$BTT(B8%0!@``7UY;R<($ +M`%6+[('L"`$``(!]"`!3B]F+@U`&``"+BT0&``!6BW`"5XV]^/[__W42@WD( +M`(F%^/[__XV]_/[__W11BT4,A#QP2#>0@`=<[K`XM(`HV%^/[__SOX +M#X2%````BA9&B77Z#[`B%_W129H,_`70\BW<$.`YT'X/&!C@.=?F*1@$Z1OMR +M$(U&^E!6B47LZ,/V__^+=>R*1@&+3>`\P[@^A+``!SSCE5XG0\.47B=Q!64HO+Z./] +M__^)1>*%P'2T_XM*)1>R+@TP&```SR3N#1`8```^5P2F+W$L` +M`.L2BXM0!@``B4$"BX-$!@``B47BBX-$!@``#[9-X0^W,`^W>`(K^2O^B77T +MB[-,!@``1XE-Z(E]\(EU^#OP=1J+1>*)@T0&``")@TP&``!?7EO)PXMU^(M] +M\`^W!HE%_(/X`71:J`%U']'H4/]V!(V+C$H``.CC^/__B48$A<`/A`K___^+ +M1?S!X`.-3@(/MQ$/M]([PHM%_!O2P>`"0CE%]!O`0&8CT(M%_`/`9@/2.T7T +M&\#WV&8#T`^W`>M4:@&-BXQ*``#H#/C__X7`#X2[_O__BU7XC4X"B_&+^*5F +MI8E"!(I0`8#Z'G,'`M*(4`'K!,9``7AF#[9``8M]\(MU^&H#6CM5]!O2]]IF +M`Y-8!@``9@/0#[?"9HD1#[?0C4(&#Z]%Z`/7B_IK_P8#P#O'B57XB_IS&L'G +M`CO'&_]'.]`;P/?8C50'`0^W`8/``^LF:_\/.\<;_VO2#$<[PAO20@/ZBU7X +M:]().\(;P$"-5`<$#[R+QVO`!@-&!$>)2`**3>"("(A0 +M`6:)/HMV"(EU^#NS1`8```^%JO[__^F1_O__BT0D"%.+7"0(B8-0!@``@$`! +M!%>+^6:#1P($BD@!.DC[=B!6C7#Z5E#H$O3__XFS4`8``(!^`7Q>=@A3B\_H +M-OK__U];P@@`58OL#[=!`E-6BW4(B8:$2@``C9YP2@``BT,(,]+W +M6UW"!`"+AE`&```/M@"*A#!L"0``B(9N"@``B99\2@``#[8'BI9L"@``B)0P +M;`8```^W`8F&5`8``$B#IE`&````BI9L"@``@^\&2`^V#XB4,6P&``!UZHN& +MA$H``(F&@$H``.N6BT0D"%:+="0(B890!@``@$`!!&:#00($@'@!?'8&5NC/ +M^/__BX9H!@``_H9L"@``B89D!@``7L((`%6+[%$/MP&Z``$``%=F.\)T9E,/ +MM_B+10PSVU:+=0@YAE0&```/MI0&:P<```^?PXE]_&O_"XT$DP^W40*+20@/ +MMPDSVSO7#YS#*TW\,](Y30P/MHYN"@``#YS"C01#C01"`\&-/(:+S^C5\?__ +MB8:$2@``7EOK$XM%"(VX0`8``,>`A$H```$```"+QU_)P@@`58OL@>P(!``` +M4U:+=0A7B]D/MSLKOE0&``!75NA-____B47\C87X^___B44(BT,$@^@&@V7X +M`(J.;`H``(/`!@^V$#B,,FP&``!TZP^V4`&+3?@#RHM5"(-%"`1/B4WXB0)U +MTP&.A$H``(V^<$H``(M'"#/2]W<4,]*)10B)1PB+1P0K!_=U"(N6A$H``#O" +MB44(?`- +MOHQ*``"+S^C`Z?__:@&+S^C+Z?__:@*+SN@:]O__7U[#58OL45-65XM]"(OQ +MB\_HJ_#__XO8B5T(P>L%@.,!=%*+S^B7\/__B47\]D4(0'0,B\_HA_#__XM- +M#(D!5XV.<$H``.CY\/__A-MT18M%"(/@'T"+V(/[$'X&:]L#@^L@C8Z,2@`` +M@_L!=13H.^G__^L)@[Z,2@```'6O,L#K'8M%_$!0Z#;I__]3B\[HAO7__S/` +M.89$!@``#Y7`7UY;R<((`%:+\8N.1`8``(N6W$L``%<[RG8EB[[D2P``.\]W +M&V:#.0%T&XM!!#O"=@X[QW<*5NBY^___A,!U#(/(_U]>PU;HFNK__XN.?$H` +M`(V&>$H``(L0B_H/K_D!OG!*``"+OH!*```K^0^O^HDX@[Y0!@```'0W@[Y< +M!@```(N&4`8``%,/MA@/A;T```"+0`([AMQ+```/AJX```")ADP&``")AD0& +M``#IM````(N&<$H``(N.>$H``(T4"#/0@?H````!___XL/P:9X2@``",'A"`O!P:9P2@`` +M"(D'ZZB+AMQ+``"+CD0&``#_AEP&``"+20B)CD0&```[R`^&$____SN.Y$L` +M``^'!____P^W$3N65`8``'3,5NBU_/__Z>W^__^+SNAY]___@+YL"@```'4' +MB\[HK^K__XN&<$H``(N.>$H``(T4"#/0@?H````![__XL/P:9X2@``",'A"`O!P:9P2@`` +M"(D'ZZB+PUOI??[__U-65XOQZ%M8__^+5"00BYJ$````)?[_```[1)H$)3@3!ZP,!'BL$ +MNFH062O/T^@#1+I$.P)R`C/`BX2"B!0``%]>6\($`%-6B_%7C7X0B\_HF?W_ +M_XO8@_O_=0Z+S^C"_/__@Z8PS````%]>B\-;PU:+\8U.(.B![?__C4X4Z'GM +M__^+SE[I<>W__U97BWPD#(-_&`"+\79/BX90S```4XE'1(M'%/^V4,P``(/` +M)(V>`$P``%"+R^A%=?__BX90S```BY94S```L2#H:@#__U"+1Q2#P"A0B\OH +M(W7__U>+R^@*AO__6U]>P@0`BT0D!%97BWPD$(OQ._AT.\:&2LP```%S,HO( +M]]F!X?__/P!1BXXTS````\A1B\[HK.K__U?_MC3,``"+SNB>ZO__QH9)S``` +M`>L3BXXTS```*_@#R%=1B\[H@NK__U]>P@@`58OL@>RL`0``5HOQBX:4R@`` +M@^@9.09^#>CEZ?__A,`/A&`"``"+1@3WV(/@!U"+SNBZ5O__B\[HRE;__ZD` +M@```=!^-AOQ+``!05HU.$,>&,,P```$```#HG?O__^DC`@``4S/;B9XPS``` +MB9Y+SNAE5O__P>@,#[;`:@2+SHE%_.@\5O__BT7\@_@/=3B+SNA$5O__P>@, +M:@2+S@^V^.@>5O__A?]U!\9$'>@/ZQM'1^L,3X/[%',*QD0=Z`!#A?]_\$OK +M!(A$'>A#@_L4?)UJ%(V&/+$``%"-1>A0B\[HR^G__S/;BX:4R@``@^@%.09^ +M#XO.Z-OH__^$P`^$W0```(V&/+$``%"+SN@?_?__@_@0?1F*C#.\)@\<+:@>+SNAA5?__ZQA/@?N4`0``?6**A!U3_O__B(0=5/[_ +M_T.%_W_DZT%U$>A15?__B_C![PV#QP-J`^L/Z$!5__^+^,'O"8/'"VH'B\[H +M&%7__^L23X'[E`$``'T9QH0=5/[__P!#A?]_ZH'[E`$```^,&/___XL&.X:4 +MR@``QH9H3````7X$,L#KCK4___C4X0Z,GM__^- +MC@!,``#HMG'__XV.-$P``.C-4___,\F-AD!,``")"(E(!(E("(V&3$P``(D( +MB4@$B4@(C8983```B0B)2`2)2`B+1"0(B48,B8XTS```B(XXS```B(Y(S``` +MB(Y)S```B(Y*S```B\9>P@0`5E>+\>B84___,M*I`(```'0(BT8$L0%`ZPZ+ +MR(M&!,'I#K(!(LI`0(OXP>\#`3Z#X`>$R8E&!`^4P(B&:$P``(32=12$R70+ +MB\[HD/S__X3`=`4SP$#K`C/`7U[#5HOQC4X4Z)?[___V1"0(`70'5NA7G___ +M68O&7L($`%6+[(/L&(-E_`!35HOQBXZ0R@``BX:,R@``*\$E__\_`(.^4$P` +M``!7#X;-`@``BU7\B[Y,3```P>("BQPZB57XA=L/A*$"``"`>PP`=`G&0PP` +MZ9("``"+4P2+.XE5[(O7*]&!XO__/P")?>@[T`^#=0(``#O/=!A748O.Z'[[ +M__^+AHS*```KQXO/)?__/P"+5>P[T`^'?P(``(T$.B7__S\`B47L._AR,X7` +M="^X``!``"O'4(E%\(N&-,P```/'4(V.`$P``&H`Z`QQ____=>S_MC3,``#_ +M=?#K#(N&-,P``%(#QU!J`(V.`$P``.CGA-_O__BX9,3```@R0#`(M%_$`[AE!,```/@PT!``")1?3K`XM=^(N&3$P` +M`(M<`P2%VP^$\P```(M%Z#D##X7H````.7L$#X7?````@'L,``^%U0```%?_ +M=?"-C@!,``!J`.CE;___BT,0BXY`3```BSR!BT@__?__BX9,3```@R0#`(M%]#N&4$P```^"^/[__XM.#%?_=?#H287__XM- +M[(V&4,P```$XQH9*S````8-0!`"+AHS*```KP27__S\`_T7\BU7\.Y903``` +M#X(S_?___[:,R@``48O.Z/;X__^+AHS*``")AI#*``!?7EO)PXM5_.L8BX9, +M3```BP20A-CEA, +M``#HX^7__X.F9$P````S_SF^1$P``'8=BX9`3```BPRXAZ7;E__^+P3/)B0B)2`2)2`B)2!2)2!B) +M2!R)2"")2"2)2"B)2`R)2$R)2!##5HOQBX8TS```A3__XV.0$P``.C>Y/__ +MC8XT3```Z-].__^-C@!,``#HH6S__XV.G$H``.BWW?__B\Y>Z<%.__]3,]M6 +MB_$Y7"0,#X6I````5VH04XV&<,H``%"(GFA,``#H&)7__VB4`0``4XV&G,H` +M`%")GH#*``")GHC*``")GH3*``#H])3__[\T&0``5U.-AFQ,``!0Z.&4__]7 +M4XV&H&4``%#HTY3__U=3C8;4?@``4.C%E/__5U.-A@B8``!0Z+>4__]74XV& +M/+$``%#HJ93__XO.B9Z0R@``B9Z,R@``QX;\2P```@```(F>,,P``.@V_O__ +M7XE>!(D>B9Y0S```B9Y4S```B9Z4R@``B9Z8R@``7EO"!`"+1"0$5XOYA6W49N7Q>00#H +MHQO__^L-B8+^8VW +M-$P``(-F!`"#)@"X`(```#E%$(EU_'\#BT404/]U#/^W/$P``.@"E/__C8\` +M3```B4WTZ"MK___V10B`=!Y6Z&%K__^+V(E=^(7;=0F+S^A;_?__ZQ%+B5WX +MZPN+AV1,``")1?B+V(N'1$P``#O8=TD[GUQ,``!W03O8:F2)GV1,```/E$43 +MZ#B9__^+\%F%]G0*C4X4Z)#]___K`C/V@'T3`'1_@?L`!```=A:%]G0):@&+ +MSNB.^?__,L!?7EO)P@P`C9]`3```:@&+R^CKXO__:F3HZYC__UF)10R%P'00 +MC4@4Z$+]__^+10R)10SK!(-E#`"+AT1,``"+"XM5#(E4@?R+AT1,``!(:@"- +MCUA,``")1A#H./C__XM%#(-@"`#K$HN'0$P``(L$F(E>$/]`"(E%##/`B47P +MB47L.8=03```=C^-GTQ,``"+"XL,@8O0*U7PBP.)#)"+"XM%[(T,@8,Y`'4# +M_T7PBU7PA=)^`X,A`$")1>P[AU!,``!RRX72=1*-GTQ,``!J`8O+Z"GB__\S +MTD*+AU!,``"+"_]U_"O"B32!BT4,BT`(B48(Z/!I___V10A`B47P=`>!1?`" +M`0``BX>,R@```T7PN___/P`CP_9%""")!G09_W7\Z,!I__^+5?B)1@2+CUA, +M``")!)'K&XM%^#N'7$P``',+BX]83```BP2!ZP(SP(E&!(N'D,H``(N_C,H` +M`#O'=`XKQR/#.T7P=P4SP$#K`C/`:AQJ`(U>0%.(1@SHOI'___9%"!"+1@2) +M1E"+1@C'1DP`P`,`B494=#V+3?SH;TO__XM-_(OX:@?![PGH24O__X-E\`"+ +M3?`SP$#3X(7'=`K_=?SH'&G__XD#_T7P@\,$@WWP!WS>@'T3``^$CP```/]U +M_.C\:/__B_B)?1"!_P```0`/@P#^__^%_P^$^/W__U>-3>#HE/;^_S/;A?^+ +M?>!V*HM-_(L!@\`#/0"```!S.NCI2O__BTW\P>@(:@B(!!_HPDK__T,[71!R +MUHM=#(M-](U#%%#_=1!7Z,IV__^%_W0>5^A@D/__ZQ:%_P^$E?W__U?H4)#_ +M_^F*_?__BUT,BT,4B48@BT,DB48DBT,XC4C_B440@?G^'P``=QB-?C10B\_H +MUL[___]U$/]S-/\WZ,20__^#?BQ`P'````BT40_S"+3?3_=0SHUF?__X-%$`2#10P$_TWL +M=>/_=@2+3?2-1QQ0Z+IG__^+3?1J`(U'(%#HK&?___]V"(M-](U'+%#HG6?_ +M_VH0:@"#QS!7Z!.0___V10@(='F+1?R+"(/!`X'Y`(````^#M/S__U#HF6?_ +M_XOX@?_`'P``#X>@_/__BW8LC4=`._!S#XO'*\:#P$!0B\OH_LW__XLS@\9` +M,]N%_W8MBTW\BP&#P`,]`(````^#:?S__^A[2?__BTW\P>@(:@B(!#/H5$G_ +M_T,[WW+3L`'I2OS__U6+[(/L$%-65XOQZ`I)__^+^(M&!(/`",'O"(O(P>D# +M`0Z)??R+V(/C!X/G!T>)7@2#_P=U%(O.Z-U(__^+^,'O"(/'!XU#".L1@_\( +M=1N+SNC$2/__B_B-0Q"+R,'I`P,.@^`'B48$B0Y7C4WPZ'KT_O\SVX7_?D6+ +MAI3*``!(.09\$HO.Z-#;__^$P'4'C4?_.]A\38O.Z'U(__^+3?#!Z`B(!!F+ +M1@2#P`B+R,'I`P$.@^`'0SO?B48$?+M7_W7PB\[_=?SHM?K__X-]\`"*V'0( +M_W7PZ"V.__^*PU]>6\G#@WWP`'0(_W7PZ!B.__\RP.OI58OL@^P44U97B_F) +M??SH1O#__XOP@\O_B77X._-U!#+`ZWV#Y@=&@_X'=1"+S^@F\/__.\-TZ(UP +M!^LB@_X(=1V+S^@1\/__B_`[\W31B\_H!/#__SO#=,;!Y@@#\%:-3>SHD?/^ +M_XM][#/;A?9^%8M-_.CA[___@_C_="B(!!]#.]Y\ZXM-_%97_W7XZ/KY__^* +MV(7_=`97Z':-__^*PU]>6\G#A?\/A'+___]7Z&&-___I9____U6+[(/L#%-6 +M,]M7B_$Y'3Q.0@!U3(E=^#/_BQ2=:%%!`(72?C92C8?\34(`B\M3QT7\`0`` +M`--E_%")5?3H;)3__X/$#(M%^(D$O3A.0@`#1?Q'_TWTB47X=>I#@_L3M +M`P``@+Y(S`````^%@0,``(.^,,P```$/A><```"-3A#H#NS__XO8@_O_#X1J +M`P``.Y[\2P``#X6W````B\[H2.[__X7`=12+SNA'[___A,`/A3[____I3@,` +M`(/X_P^$10,``(/X`@^$/`,``(/X`W4)B\[HN?W__^O3@_@$=50S_\9%"P`S +MVX!]"P`/A1<#``"+SNCR[?__@_C_=0;&10L!ZQ(/ML"#^P-U!8E%].L%P><( +M`_A#@_L$?,R`?0L`#X7C`@``BT7T@\<"@\`@Z:\"``"#^`5U&HO.Z*OM__^# +M^/\/A,`"``!J`8/`!.F1`@``BX8TS```BXZ,R@``B!P(ZR:-AFQ,``!0B\[H +MX.S__[H``0``.\)]&HN.-,P``(N6C,H``(@$$?^&C,H``.E?_O__N0\!```[ +MP0^,'P$``"O!#[:X2%%!``^VF"Q100"#QP.)?0B%VW8EB\[H]$3__VH062O+ +MT^@#^(M&!`/#B\C!Z0,!#H/@!XE]"(E&!(V&H&4``%"+SNAC[/__#[:8_$U" +M`(L\A3A.0@!'A=L/AI4```"#^`E^;H/[!'8GB\[HH$3__VH462O+T^C!X`0# +M^(M&!(U$&/R+R,'I`P$.@^`'B48$BX9@S```AL)BU'\B1%(@^D$A<,H``.@6Z___#[:X2%%!``^V@"Q100!'1XE%"(7`=B2+SNA=0___:A!9 +M*TT(T^@#^(M&!`-%"(O(P>D#`0Z#X`>)1@13B9Z$R@``B;Z(R@``5^M>/1`! +M```/C6+\__\/MK@=4$$`#[:8%5!!`"T'`0``1X7;=B*+SN@&0___:A!9*\O3 +MZ`/XBT8$`\.+R,'I`P$.@^`'B48$5XO.Z.C4__]J`EB)OH3*``")AHC*``!7 +M4(O.Z/W4___I`_S__\:&6,P```#K%HU.$.C(Y___@Z8PS````(O.Z(+O__]? +M7EO)P@0`@WPD!!UT!X-\)`0D=0G_="0(Z!S[___""`#_="0(_W0D".@]IO__ +MA<`/E<#""`!5B^RX%!@``.B,[?[_4U:+=0B+AI`3``")1>R+AJ1*``!7B47X +M@_AZ=0N-CN!7``")3?SK#HV.T$H``(E-_(/X='4*]D$(`L9%"P%U!,9%"P"+ +M?0R%_W0_@'T+`'0Y@'D@%'(SBT$8@_C_="OWT#F'$`4``'0A@\$P4>@WQO__ +M4&IRZ,A^__]0C888!```4.@BFO__@\0,B\[HD##__XE%\(E5](7_=!*+SHV? +M^`0``.@X-O__`0,14P2+SNBX+___C4874(V%[/O__U#H`8K__XV&&`0``%"- +MA>SO__]0Z%F+___VAL!*```0=`V`OK!Q````=00RP.L#,\!`4+L`!```4XV% +M[.___U"-A>S[__]0Z$I;___&10\`Z:$```"%_W0.@Z<`!0```(.G!`4```"` +M?0\`=5Z-1A=0C87L]___4.B*B?__C888!```4(V%[.?__U#HXHK__VH!4XV% +M[.?__U"-A>SW__]0Z/!:__]J`&H`C87LY___4(V%[/?__U"+SL9%#P'HB##_ +M_X3`#X6&````BT7L@+AH+0````^%G@```(V%[.___U"-A>S[__]0Z#+^__^$ +MP`^$@P```&H`:@"-A>SO__]0C87L^___4(O.Z#PP__^$P`^$/O___VH!B\[H +MQO#^_X!]%%2-AA@$``!0C4874`^5P(T$A50```!0Z'V:__^`?0L`B\YT<_]U +M^.@2`?__ZVZ-A>SW__]0C87L^___4.BCB/__C87LY___4(V%[.___U#H^XG_ +M_^N>:G?H!'W__U"-A>SO__]0Z%Z8__]963/_5U>-AA@$``!0C4874(O.Z*8O +M__]7_W7TB\[_=?#H"S3__S+`Z9@```#H[?7^_X.^I$H``'1U*HO.Z/CT_O^+ +MAJAQ```KAJA7``"+CJQQ```;CJQ7``!J`%%0B\[HS#/__X7_=%J#??A[=0G& +MA\8$````ZR.+1?R*2`C0Z8#A`8B/Q@0``(N(V`P``(E/((N`W`P``(E')(O. +MZ/,S__^#I^@$````@Z?L!````(./$`4``/^)A]`$``")E]0$``"P`5]>6\G" +M$`!5B^Q14XU%_%!H>#M!`&H!,]M3:"@\00#_%;`R00"%P`^,C````(M%_/]U +M"(L(4/]14#E=%'0,BT7\_W44BPA0_U$<.5T8=`V+1?R+"%/_=1A0_U%$.5T< +M=`R+1?S_=1R+"%#_42PY71!T#(M%_/]U$(L(4/]1)(M%_(L(C54(4F@8/$$` +M4/\1A+?0AJ4(V%8/___U!7_Q7L,4$`AA?]T"6H05_\5O#%!`%_) +MP@0`58OL45%65XL].#%!`(OQ@V8$`(,F`&A<.T$`_]=H0#M!`(D&_]>)1@2- +M1?A0QT7X"````,=%_/\'``#_%2PP00!H*$]"`/\5K#%!`%^+QE[)PU:+\8L& +M5XL]/#%!`(7`=`-0_]>+=@2%]G0#5O_7H2A/0@"+"%#_40A?7L.Y?%Y!`.ED +M"___N8A>00#HV7+__VB$*4$`Z+2*__]9P[DXTT$`Z#8$__]HCBE!`.B>BO__ +M6<.Y^$Q"`.D4R___N8A>00#IL'+__[DXTT$`Z38#__\````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`$!*`0"F20$`ODD!`"Q*`0`:2@$`"$H!`/I)`0#F20$`TDD!`(Y)`0`````` +MU#\!`!$``(``````;$D!`$!)`0!820$``````!9)`0#R2`$`V$@!`,A(`0"Z +M2`$``$D!`"9)`0"N2`$``````%A!`0!F00$`=$$!`(A!`0"<00$`J$$!`+A! +M`0#*00$`VD$!`.Q!`0#\00$`$D(!`"!"`0`P0@$`1$(!`%A"`0!N0@$`?D(! +M`))"`0">0@$`L$(!`+Q"`0#*0@$`W$(!`.I"`0#\0@$`0D$!`"A#`0`Z0P$` +M3$,!`&1#`0!^0P$`FD,!`+!#`0"X0P$`R$,!`-9#`0#H0P$`^D,!``I$`0`@ +M1`$`-$0!`$Y$`0!@1`$`>D0!`))$`0"B1`$`N$0!`,I$`0#<1`$`Z$0!``!% +M`0`010$`+$$!`!9!`0``00$`]$`!`.1``0#80`$`&$`!`,I``0"\0`$`KD`! +M`)Y``0",0`$`@$`!`')``0!>0`$`4$`!`$!``0`P0`$`$$,!```````(``"` +M`````/!*`0#>2@$`RDH!`+A*`0":2@$`C$H!`'9*`0!>2@$``````/H_`0`` +M````3D0![`&8`;P!N`'0`+0!F`&$`;0!I`&P`>0`Z`"(`00!R`&D`80!L +M`"(`.P!F`&\`;@!T`"T`0!L`&4`/@``````/`!S`'0`>0!L`&4`/@```#P` +M+P!P`#X``````%,`:`!E`&P`;``N`$4`>`!P`&P`;P!R`&4`<@``````4@!A +M`'(`2`!T`&T`;`!#`&P`80!S`',`3@!A`&T`90``````*C\``%]?````````!E``````!)`&X``!T``````!4`&D`=`!L +M`&4```!0`&$`=`!H``````!3`&D`;`!E`&X`=```````3P!V`&4`<@!W`'(` +M:0!T`&4```!3`&4`=`!U`'````!4`&4`;0!P`$T`;P!D`&4``````$P`:0!C +M`&4`;@!S`&4```!0`'(`90!S`&4`=`!U`'```````%,`:`!O`'(`=`!C`'4` +M=```````4P!A`'8`90!0`&$`=`!H``````!5`'``9`!A`'0`90``````3`!) +M`$,`10!.`%,`10!$`$P`1P``````(````"(`)0!S`"(`"@`E`',```!R`'4` +M;@!A`',```!W`&D`;@!R`&$`<@!S`&8`>`!M`&$`<`!P`&D`;@!G`&8`:0!L +M`&4`+@!T`&T`<```````+0!E`&P`(``M`',`,@`@`"(`+0!D`"4``!?`&$`8P!C`&4``!N`&$`;0!E````5<`````:P!E`'(`;@!E`&P`,P`R```` +M```9#@D'!04$!`0#`P,"`@("W3P_'[]9\TBA9+Q:,F918$4`1`!)`%0````` +M`'(`:0!C`&@`90!D`#(`,``N`&0`;`!L``````!R`&D`8P!H`&4`9``S`#(` +M+@!D`&P`;```````^10"``````#`````````1H`CU7\'3AL0KBT(`"LNQQ,8 +M`0```````,````````!&$@$```````#`````````1A8!````````P``````` +M`$83`0```````,````````!&&0$```````#`````````1@``````````P``` +M`````$8`!`(``````,````````!&818,TZ_-T!&*/@#`3\GB;@L!```````` +MP````````$8!%`(``````,````````!&0#T!````````````[#\!`"PP`0#0 +M/@$````````````,0`$`O#$!`(`]`0```````````!Y%`0!L,`$`V#X!```` +M````````HD@!`,0Q`0!$L!`)`Q`0`` +M`````````````````````````$!*`0"F20$`ODD!`"Q*`0`:2@$`"$H!`/I) +M`0#F20$`TDD!`(Y)`0``````U#\!`!$``(``````;$D!`$!)`0!820$````` +M`!9)`0#R2`$`V$@!`,A(`0"Z2`$``$D!`"9)`0"N2`$``````%A!`0!F00$` +M=$$!`(A!`0"<00$`J$$!`+A!`0#*00$`VD$!`.Q!`0#\00$`$D(!`"!"`0`P +M0@$`1$(!`%A"`0!N0@$`?D(!`))"`0">0@$`L$(!`+Q"`0#*0@$`W$(!`.I" +M`0#\0@$`0D$!`"A#`0`Z0P$`3$,!`&1#`0!^0P$`FD,!`+!#`0"X0P$`R$,! +M`-9#`0#H0P$`^D,!``I$`0`@1`$`-$0!`$Y$`0!@1`$`>D0!`))$`0"B1`$` +MN$0!`,I$`0#<1`$`Z$0!``!%`0`010$`+$$!`!9!`0``00$`]$`!`.1``0#8 +M0`$`&$`!`,I``0"\0`$`KD`!`)Y``0",0`$`@$`!`')``0!>0`$`4$`!`$!` +M`0`P0`$`$$,!```````(``"``````/!*`0#>2@$`RDH!`+A*`0":2@$`C$H! +M`'9*`0!>2@$``````/H_`0``````3DP!);FET0V]M;6]N0V]N=')O;'-%>```0T]-0U1,,S(N9&QL``"D`%-( +M075T;T-O;7!L971E``!32$Q705!)+F1L;`"_`4=E=$-U7!E`(@`0W)E871E1FEL94$`CP!#!%-E=$9I;&5!='1R +M:6)U=&5S00``8013971&:6QE071T4$``($`0W)E871E1&ER +M96-T;W)Y5P``+@%&:6YD0VQO'1&:6QE5P`Y`49I;F1&:7)S=$9I;&57``"3 +M`D=E=%1I8VM#;W5N=```$057:61E0VAA71E`+,"1VQO8F%L +M06QL;V,`I`)'971697)S:6]N17A7`/@!1V5T1G5L;%!A=&A.86UE00``^P%' +M971&=6QL4&%T:$YA;657```4`D=E=$UO9'5L949I;&5.86UE5P``3@%&:6YD +M4F5S;W5R8V57`!@"1V5T36]D=6QE2&%N9&QE5P``RP)(96%P06QL;V,`2@)' +M9710%<`U@15;FUA +M<%9I97=/9D9I;&4`AP%'971#;VUM86YD3&EN95<`5P--87!6:65W3V9&:6QE +M`(P`0W)E871E1FEL94UA<'!I;F=7``!Y`T]P96Y&:6QE36%P<&EN9U<``%<$ +M4V5T16YV:7)O;FUE;G1687)I86)L95<`10)'97105<``#\#3&]A9$QI8G)A5)E +M8W0``!0!1V5T0VQI96YT4F5C=`"F`$1E'17```1`U5P9&%T95=I;F1O +M=P``;@!#%<`"0)-87!7:6YD;W=0;VEN=',`9`%'9710 +M87)E;G0`G`%'9717:6YD;W=296-T`#P`0VAA7-T96U-971R:6-S``"C`4=E=%=I;F1O=U1E>'17``#&`E-E +M=%=I;F1O=U!OP%' +M9713>7-#;VQO<@`V`E!O4$``*H"4V5T1FEL95-E8W5R:71Y5P``,`)296=#;&]S +M94ME>0!^`E)E9U-E=%9A;'5E17A7```Y`E)E9T-R96%T94ME>45X5P!N`E)E +M9U%U97)Y5F%L=65%>%<``&$"4F5G3W!E;DME>45X5P!!1%9!4$DS,BYD;&P` +M`-<`4TA'9710871H1G)O;4E$3&ES=%<``'L`4TA"%<`?P!32$-H86YG94YO=&EF>0``4TA%3$PS,BYD;&P`$`!# +M;T-R96%T94ENF4`;VQE,S(N9&QL`$],14%55#,R+F1L;``````````````````````-'>%- +M`````+A+`0`!``````````````````````````````!724Y205(N4T98``!2 +M4T13Y=F'&1/$=TB(PEFYXP9LD0$```!D.EQ0')A````#^):3<#````'0```'T'!@X&```` +ME0```,A=+!P$````V`````'GA;P%````*````&#%N48'````!`0&!@``!P<$ +M!```!`0``$@W00````````````,```#D-D$`````````````.4$`$#E!`!PY +M00`H.4$`-#E!`$0Y00!8.4$`9#E!`'@Y00"(.4$`G#E!`+`Y00#$.4$`'P`` +M`!P````?````'@```!\````>````'P```!\````>````'P```!X````?```` +M`@(#!`4&!@8`!`@0($"`P````````````0$!`0("`@(#`P,#!`0$!`4%!04` +M`0(#!`4&!P@*#`X0%!@<("@P.$!08'"`H,#@``````0````"`````@````(` +M```"`````@````(````"`````@````(````"`````@````(````"`````@`` +M``(````.``````````P````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````1"E!`$XI00!D*4$`>BE!```````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````8``@```$```(`# +M````6```@`4```"(``"`!@```,@``(`.``````$`@!@````8`0"````````` +M```````````!`&4````P`0"````````````````````$``$```!(`0"``@`` +M`&`!`(`#````>`$`@`0```"0`0"`````````````````!@```'0$`("H`0"` +M1`0`@,`!`(!>!`"`V`$`@#`$`(#P`0"`$@0`@`@"`(``!`"`(`(`@``````` +M````````````!0`'````.`(`@`@```!0`@"`"0```&@"`(`*````@`(`@`L` +M``"8`@"````````````````````!`&0```"P`@"````````````````````! +M``$```#(`@"````````````````````!``D$``#@`@`````````````````` +M```!``D$``#P`@`````````````````````!``D$`````P`````````````` +M```````!``D$```0`P`````````````````````!``D$```@`P`````````` +M```````````!``D$```P`P`````````````````````!``D$``!``P`````` +M```````````````!``D$``!0`P`````````````````````!``D$``!@`P`` +M```````````````````!``D$``!P`P`````````````````````!``D$``"` +M`P`````````````````````!``D$``"0`P`````````````````````!``D$ +M``"@`P`````````````````````!``D$``"P`P`````````````````````! +M``D$``#``P`````````````````````!``D$``#0`P`````````````````` +M```!``D$``#@`P`````````````````````!``D$``#P`P``\'8"`+8+```` +M`````````)!D`@`H`0````````````"X90(`:`4`````````````(&L"`.@" +M``````````````AN`@"H"`````````````"8BP(`A@(`````````````:(D" +M`#H!`````````````*B*`@#L```````````````XB`(`+@$````````````` +M`(4"`#@#`````````````*B"`@!2`@````````````#8DP(`+`(````````` +M````")8"`,X#`````````````-B9`@`2`@````````````#PFP(`"`,````` +M````````^)X"`'P!`````````````+!V`@`^```````````````@C@(`N`4` +M````````````"`!3`%0`00!2`%0`1`!,`$<`#@!2`$4`4`!,`$$`0P!%`$8` +M20!,`$4`1`!,`$<`"0!2`$4`3@!!`$T`10!$`$P`1P`,`$<`10!4`%``00!3 +M`%,`5P!/`%(`1``Q``H`3`!)`$,`10!.`%,`10!$`$P`1P`*`$$`4P!+`$X` +M10!8`%0`5@!/`$P`````````*````!`````@`````0`$``````#````````` +M```````0`````````````````(```(````"`@`"`````@`"``("```#`P,`` +M@("`````_P``_P```/__`/\```#_`/\`__\``/___P```````$`````'`P`' +MAP```']'8@]_)B`']RNJ3_^JH']P```/_P``!P<##____P!P?\=`___\0`?W +M3V8/_\9@?W````3T```'!P,``(```'!_!Q45%140!_=;W=W=W=!_E?\`UX?_`-)]_P#0 +M>?\`RFS_`,!C]`"U6N@`X-O9`![%Q0!:`I(`4P*-````4```@(``%A%-`!(. +M/P`K*RL`(D-3`'3-]P"U8P8`_\MY`"1'6`!>N.0`I^'U`/^=)0#_KS$`4#(` +M`*=8``!W?0`EF(``)]6``"(30``>L[U`-3X_0!4ILX` +M4!D``&6[Y`"!RNT`4X,!`.'UNP"/RAX``$,5`%FKTP!ANN8`D=<(`)O?%@"2 +MW````#81`$AP````N;D`>;$/`%J*``!2G<(`K.'U`%>GS@!8B```5X<``$)G +M````3AD`.82E`%JUW@!"A*4`0$!```Q*+@`A4FL`.7N<`"%*8P`````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````0$!&`$!`0$86)C9`0$!`0$ +M!"\G6RQ<7#!=7E]<7%Q1!"\G'5)35%4P5E=865I(!!H;'`U('4E*2TP]34Y/ +M4%$3%!4O!`0$!`1&'4<$!`0$!`T$)T$L-#M"0QT^/D1%.04$)QTZ*"PT.SP] +M/CL_0`0:&QP-,ATS+#0U-C4W.#WM[<`![>WM[ +M,````````+>WM[``M[>WNW,```````![>WMP`'M[>WNW,```````M[>WL`"W +MM[>[>W,``````'M[=W``=WM[>[>W,`````"WMP`````'M[M[>W@`````>WMP +M````>WM[M[>W`````+>WMP``![>WNWM[>P````![>WMP`'M[>WNWM[<````` +MM[>WMP>WM[>[>WM[`````'M[>WM[>WM[>[>WMP````!W=W=W=W=W=[MW>WL` +M`#@X.#@X.#@X.#A[>#>W```#@X.#@X.#@X.#AX.#>P```#@X.#@X.#@X.#@X +M.#<````#@X.#@X.#@X.#@X.#````"")G)$3,`571$3@X.#```(,B:B1,3`%5 +MU5$#@X.#``@X(FHD1,P!5=45$#@X.#"#@R)J)$S,`575$5$#@X.#"#@GNRQ[ +MN`>[=3@5$#@X,`"#(F)T1,Q\`/6P``$!P`````'\`8P!C`'``<`!_`'\``$M+ +M``!.7```46```%=H``!;:0``6VP``%]M``!5<```7W```%QX``!C<0``97$` +M`&-T``!E=0``9W8``&=W``!I=@``8'\``&)_``!K>P``;7L`*V]W`)L```"A +M````_P```,)0``#/7@``_U,L`.=]+0"03T\`_W!``!"`(``5@R4`7Y```%N6 +M"P!NJ24`,:-#`$#`7P!;SG,`3]YV`&K_:@#UD30`_YLX`/^P0`#_N58``&2" +M``!I@@``:H(``&^```!L@@``;H<``'&```!WA@``>H<``'.*``!TBP``I(``'^0``Q]F0!&>H4`D`"0`)8+F`"6 +M#9@`FQ6?`)P9GP"@$*``KR"O`+!*O@"W5,8`OU_0`,=RU@``@)```("8``"` +MGP``E98``(^@``";I```H+```*>S``"ML@``J;<``*R[``"TN@``L+\``+;# +M``"[P```NL<``+W$``#"R@``R<\``,W.``#*TP``S]``'L_5``#0T```UM<` +M`-C8``#7)RGK^_O[^_O[^_G)RWIZ>O[^_O[^_O[^GIZ_O[^_O[^_OYK:VMK:VMK:VMK:VIH:FIJ;X)T<6UX>GK^_O[^86%A86%A +M86%A86%A86%A86%A86%F?FQE46UU>/[^_O[^2DI*2DI*2DI*2DI*2DI*2DI* +M2F%I95%286UU_O[^_O[^)R'@(96 +M5%,0$Q(1%QHH1D3^_OX<)0@,,S4\`"LN,D``$EQ<8%9E?6(0$Q(7%QY$_O[^ +M_OX<"`PU-X@`*RPRB``27%^(5EICA&$0$A<;'O[^_O[^_OX(AXB(AP6'B(B' +M$H>(B(=95EAC?F,2'1PE1/[^_O[^_OX(AXB(AP6'B(B'$H>(B(=95A-C;A)! +M(R-!1/[^_O[^_OX(AXB(AP6'B(B'$H>(B(=7$Q-3$B`C(R`<'/[^_O[^_OX( +MAXB(AP6'B(B'$H>(B(=6$Q,2_O[^_O[^_O[^_O[^_OX(AXB(AP6'B(B'$H>( +MB(=6$Q+^_O[^_O[^_O[^_O[^_OX(AXB(AP6'B(B'$H>(B(<3$O[^_O[^_O[^ +M_O[^_O[^_OX(A_[^AP6'_OZ'$H?^_H<3_O[^_O[^\``#__```?_P``#_\``` +M?_```#_P```?\```#_````_P```/\```#_````_P```/\```#_````\````/ +M@```#\````_@```/X```!\````.````!`````(````'````#X```!_````/X +M```!_````/X``#__```__X``/__,8S\```$`!``0$!```0`$`"@!```!`!`0 +M```!``@`:`4```(`("`0``$`!`#H`@```P`@(````0`(`*@(```$````*``` +M`%T````N`0```0`$``(```!."P``$PL``!,+`````````````````````&8` +M*&8G`&````"`````@("``,#`P`#___\`____`/___P#___\`____`/___P#_ +M__\`____`/___P!=,P``73,``%TS``!=,P``73,``%TS``!=,P``73,``%TS +M``!=,P``73,``%TS``!=,P``73,``%TS``!=,P``73,``%TS``!=,P``73,` +M`%TS``!=,P``73,``%TS``!=,P``73,``%TS``!=,P``73,``%TS``!=,P`` +M73,``%TS``!=,P``73,``%TS``!=,P``73,``%TS``!=,P``73,``%TS``!= +M,P``73,``%TS``!=,P``73,``%TS``!=,P``73,``%TS``!=,P``73,``%TS +M``!=,P``73,``%TS``!=,P``13,$1!0S``!#,P=$$S,``$`S#400,P``/S,/ +M1`\S```\,Q-$#C,``#LS%40-,P``.#,91`PS```W,QM$"S,``#0S'T0*,P`` +M,S,A1`DS```P,R5$"#,``"\S)T0',P``+#,K1`8S```K,RU$!3,``"@S,40$ +M,P``)S,91`$T&40#,P``)#,;1`(S&D0",P``(S,91`4S&T0!,P``(#,;1`8S +M'$0``!\S&40),QQ$```<,QM$"C,<1```&S,91`TS'$0``!@S&T0.,QQ$```7 +M,QE$$3,<1```%#,;1!(S'$0``!,S&405,QQ$```0,QM$%C,<1```#S,91!DS +M'$0```PS&T0:,QQ$```+,QE$'3,<1```"#,;1!XS'$0````` +M`````%<`:0!N`%(`00!2`"```!T`'(`80!C`'0`:0!N +M`&<`(`!A`'(`8P!H`&D`=@!E````"`!-`%,`(`!3`&@`90!L`&P`(`!$`&P` +M9P`@`#(````."`!0``````8`"0`]`+H`;`#__X(``````````(`"4`````!+ +M`),`"`$(`&4`__^"`"8`1`!E`',`=`!I`&X`80!T`&D`;P!N`"``9@!O`&P` +M9`!E`'(``````$(`(5``````2P"=`,0`&`!F`/__A0````````````%0```` +M`!8!G``\``X`9P#__X``0@!R`&\`)@!W`',`90`N`"X`+@````````!$"*%0 +M`````$L`"0`(`8,`:`!2`&D`8P!H`$4`9`!I`'0`,@`P`%<````````````0 +M``!``````$L`I@`*`0$`:0#__X(````````````"4`````!+`*\`Q``(`&L` +M__^"`$D`;@!S`'0`80!L`&P`80!T`&D`;P!N`"``<`!R`&\`9P!R`&4``*T``````$,`;P!N`&8`:0!R`&T`(`!F`&D`;`!E`"`` +M<@!E`'``;`!A`&,`90````@`30!3`"``4P!H`&4`;`!L`"``1`!L`&<`(``R +M````!P``4``````$``(`U@"%`/____^``````````````E``````"P`,`,<` +M"`#_____@@!4`&@`90`@`&8`;P!L`&P`;P!W`&D`;@!G`"``9@!I`&P`90`@ +M`&$`;`!R`&4`80!D`'D`(`!E`'@`:0!S`'0``&4`__^!`````````````E``````"P`Y`,<`"`#_____@@!7`&\`=0!L +M`&0`(`!Y`&\`=0`@`&P`:0!K`&4`(`!T`&\`(`!R`&4`<`!L`&$`8P!E`"`` +M=`!H`&4`(`!E`'@`:0!S`'0`:0!N`&<`(`!F`&D`;`!E```````#``!0```` +M`!L`1@`2`!0`9@#__X(````````````"4``````V`$<`G``(`&@`__^"```` +M`````````E``````-@!1`)P`"`!J`/__@@````````````)0``````L`7P#' +M``@`_____X(`=P!I`'0`:``@`'0`:`!I`',`(`!O`&X`90`_``````````,` +M`%``````&P!L`!(`%`!G`/__@@````````````)0`````#8`;0"<``@`:0#_ +M_X(````````````"4``````V`'<`G``(`&L`__^"``````````$``5`````` +M#P"-`$``#0!L`/__@``F`%D`90!S`````````````5``````3P"-`$``#0!O +M`/__@`!9`&4`0!P`'0`90!D`"``9@!I`&P` +M90`Z``````"@`(%0``````8`&@"J``P`90#__X$``````````0`!4``````D +M`#``,@`.``$`__^``$\`2P````````````%0`````&``,``R``X``@#__X`` +M0P!A`&X`8P!E`&P``````````(`"4``````&`!``J@`(`&8`__^"```````` +M``````#`",J0``````4`&P`O`%L!X```````3`!I`&,`90!N`',`90````@` +M30!3`"``4P!H`&4`;`!L`"``1`!L`&<`(``R```````."`!0``````8`"0`] +M`+H`9@#__X(`````````1`@!4`````!+``D`"`&Z`&4`__^!`````````!`` +M`%````````#)`%T!`0#_____@@`````````!``%0`````-,`SP`\``X``0#_ +M_X``00!C`&,`90!P`'0````````````!4``````6`<\`/``.``(`__^``$0` +M90!C`&P`:0!N`&4```````````#``,B0``````<`.P!+`,(`BP``````3@!E +M`'@`=``@`'8`;P!L`'4`;0!E`"``:0!S`"``<@!E`'$`=0!I`'(`90!D```` +M"`!-`%,`(`!3`&@`90!L`&P`(`!$`&P`9P`@`#(```````<``%``````!@`$ +M`+8`:P#_____@`````````````)0``````T`$`"H`!``_____X(`60!O`'4` +M(`!N`&4`90!D`"``=`!O`"``:`!A`'8`90`@`'0`:`!E`"``9@!O`&P`;`!O +M`'<`:0!N`&<`(`!V`&\`;`!U`&T`90`@`'0`;P`@`&,`;P!N`'0`:0!N`'4` +M90`@`&4`>`!T`'(`80!C`'0`:0!O`&X`.@``````@`"!4``````-`#4`J``, +M`&4`__^!`````````````5``````@P`D`#(`#@!F`/__@``F`$(`<@!O`'<` +M65S +M(C\^#0H\87-S96UB;'D@>&UL;G,](G5R;CIS8VAE;6%S+6UI8W)O0T*("!V97)S:6]N/2(Q+C`N,"XP(@T*("!P3X-"CPO=')U3X-"B`@("`\87-S96UB;'E)9&5N=&ET>0T*("`@("`@ +M='EP93TB=VEN,S(B#0H@("`@("!N86UE/2)-:6-R;W-O9G0N5VEN9&]W&UL;G,](G5R;CIS8VAE;6%S+6UI8W)O2YV,2(^#0H@(#QA<'!L:6-A=&EO;CX-"B`@("`\(2TM +M5&AE($E$(&)E;&]W(&EN9&EC871ES,U,3,X8CEA+35D.38M-&9B9"TX93)D+6$R-#0P,C(U9CDS87TB+SX-"B`@ +M/"]A<'!L:6-A=&EO;CX-"CPO8V]M<&%T:6)I;&ET>3X-"CQA`!T`'(`80!C +M`'0`:0!N`&<`(``E`',`"P!3`&L`:0!P`'``:0!N`&<`(``E`',`&0!5`&X` +M90!X`'``90!C`'0`90!D`"``90!N`&0`(`!O`&8`(`!A`'(`8P!H`&D`=@!E +M`!\`5`!H`&4`(`!F`&D`;`!E`"``(@`E`',`(@`@`&@`90!A`&0`90!R`"`` +M:0!S`"``8P!O`'(`<@!U`'``=``E`%0`:`!E`"``80!R`&,`:`!I`'8`90`@ +M`&,`;P!M`&T`90!N`'0`(`!H`&4`80!D`&4`<@`@`&D`0`4`%4`;@!K`&X`;P!W`&X`(`!M`&4`=`!H`&\`9``@ +M`&D`;@`@`"4`0!T`&4`0`@`'0`:`!E`"``:0!N`',` +M=`!A`&P`;`!A`'0`:0!O`&X`"0!!`&P`;``@`&8`:0!L`&4`0`N`#P`+P!L`&D`/@`\`&(`<@`^`#P`8@!R`#X`.``\`&P`:0`^`$D` +M9@`@`'0`:`!E`"``9`!E`',`=`!I`&X`80!T`&D`;P!N`"``9@!O`&P`9`!E +M`'(`(`!D`&\`90!S`"``;@!O`'0`(`!E`'@`:0!S`'0`+``@`&D`=``@`'<` +M:0!L`&P`(`!B`&4`,@!C`'(`90!A`'0`90!D`"``80!U`'0`;P!M`&$`=`!I +M`&,`80!L`&P`>0`@`&(`90!F`&\`<@!E`"``90!X`'0`<@!A`&,`=`!I`&\` +M;@`N`#P`+P!L`&D`/@`\`"\`=0!L`#X`````````%@!4`&@`90`@`&$`<@!C +M`&@`:0!V`&4`(`!I`',`(`!C`&\`<@!R`'4`<`!T````````````'0!%`'@` +M=`!R`&$`8P!T`&D`;@!G`"``9@!I`&P`90!S`"``=`!O`"``)0!S`"``9@!O +M`&P`9`!E`'(`)`!%`'@`=`!R`&$`8P!T`&D`;@!G`"``9@!I`&P`90!S`"`` +M=`!O`"``=`!E`&T`<`!O`'(`80!R`'D`(`!F`&\`;`!D`&4`<@`````````' +M`$4`>`!T`'(`80!C`'0`$P!%`'@`=`!R`&$`8P!T`&D`;P!N`"``<`!R`&\` +M9P!R`&4``!C`&4`90!D`"``)0!D`"``8P!H`&$`<@!A`&,`=`!E +M`'(`'3POU/A"V-A$C_CG0963R<_1[*6=&5S="!T97AT(&9I;&4- +M"J/L=""00P!'`0``N0$```(WUUQ;QV$2/QTS$``@````=&5S='-H;W)T8W5T +M+FQN:[#_XWD7N&$2/[,"!)U3*3\I8@<)V1&0R]7`VWF-"-",24*"IU"$:&01 +MK>H6"P:E!#@11Y_B$[TA"'?P3O8]S9!^#-2"+:U(+2B**@T(-*+:@H-J-K0@ +MI[.G(=TDWWG@:&A^";N;N^&[N?(],I\W,PP,_8;F_"LT/L0D6P5KT0S#,W*Q +M$8G\W`QTZG:AWY"6T=4_GNV378/<@[G?R@F!C`W.^ZM4XY#Q]B`T,Y8PX9Z7KK6-?Q=AUE.[5KHYHQM/A\\*%BRTE)K$^HL1 +M'2POU/A"W5A +M$C_#FG^F3A<_M<$T=&5S="!T97AT(&9I;&4-"OLV=."0.@````````````(` +M````=6$2/Q0P!P`0````=&5S=&1I61I6$2/P/-8AM4*3]41RS$/7L`0`<` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_subblock.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_subblock.rar.uu new file mode 100644 index 0000000..5c55ca1 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_subblock.rar.uu @@ -0,0 +1,7 @@ +begin 644 - +M4F%R(1H'`,^0H5JAD)Q_9XLAN3)VO("$ +M4G0@D#(`%````!0````#0J+(OK=VVCX4,`@`I($``'1E."H>."I..#JP"(:&A@,(@P7*K5,*$PI##K,.:\HN6ME^F5M^.!A..# +ME>."H>."I..#J^60C6QO;F.#B"YT>'0`D/\0?^2Y_">#,#TN'-+$/7L`0`<` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_windows.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_windows.rar.uu new file mode 100644 index 0000000..05fa8db --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_windows.rar.uu @@ -0,0 +1,22 @@ +begin 644 - +M4F%R(1H'`,^0'3POU/A"W5A$C_#FG]U81(_PYI_=&5S +M="!T97AT(&9I;&4-"D."=""0.P`0````$`````+Q$M:7;&$2/Q0P"``@```` +M=&5S="YT>'2POU/A"V-A$C_CG09L81(_4^$+=&5S="!T97AT(&9I;&4-"H[- +M=""00P"Y`0``N0$```(WUUQ;QV$2/Q0P$``@````=&5S='-H;W)T8W5T+FQN +M:_#_XWD7N&$2/[,"!%U,%S^RB8E,`````10"``````#`````````1IL````@ +M````8[VJ;\%=S`'3/CJ#P5W,`5/_T7G!7````$0````,```!;L.$D$`````!#.EQ$;V-U;65N=',@86YD +M(%-E='1I;F=S7&]W;F5R7$1E'0```H`+@!<`'0`90!S +M`'0`+@!T`'@`=``G`$,`.@!<`$0`;P!C`'4`;0!E`&X`=`!S`"``80!N`&0` +M(`!3`&4`=`!T`&D`;@!G`',`7`!O`'<`;@!E`'(`7`!$`&4``1GM0(`"<.&<7\'E#X,!WD3;OM++F5PEDYM-U6H;/)X!&> +MU`@`)PX9Q0````#%`73@D#H````````````"`````'5A$C\4,`<`$````'1E +MF%Z897!E<&5P97!L*&PH;"AL*',`;AYN'F +MX>;B`B("(@(B`B(<@AR"'((<@C?B-^(WXC?B4L)2PE+"4L)N(FXB;B)N(HCB +MB.*(XHCBH\*CPJ/"H\BZQK3$>Z`M3P```96P=EB)(F#:0C*.B=E8YJH8[61W +MV+Z)DM;2)*Q8Z4V[T6O1*GO&@Y3UWQHV$QNX==:0U"G4XC@H"!]-(J(@'D/? +M@(SYTVUR+"E#9NEU?4F/)3&DAC2@Z%6S^G>N30VJGI%L62FLU1@^LI27SAJ\ +MAE7)"Z[IC/VMTH6><,,*6=1B_>=>!,RS3:UOL>+6(/[321O:>SY39A-MM;Q$AVID_52A79OI7GLR$& +MSF*I)!#&@`%Q#EY!`,.RR%*'&\:EF1QI5(J]X(-6,[J'"6>D\2[%OX:S*/?P46S?=U=PV5MOW^%-?Q +M"-,Z'1F[U]*D5IJX<+]WA,(L9NKCB>[D-C3H[!`U7VI[+9C9M9:A +M3'3YOJJE-5E\Z$7102[J,RG1VXIIC',\]YQ3C.:890?))T[97M[+-*8XQY&W +MIH_F5(+RXB"?$"!HHBA%2^8,)-!3&H29["AH7VT*^HIG\Y^_U;GAW,\!)WGV +M&],S7-,TY;['3(@ZG`VXB\VVM&^?"X!RVCO\T02FIP`U;[V.JPQGC64RBRT4 +MUY0&N\%%_CDP*E%B_.L)Q%IB\M:L5+[&I0_%2T.JE&DSJ\F.HTZ_HGFV49Y: +MC`"$AQ,D=<3^/R?B54&T*A&33@,V;Q7#IJ$==HB_(T7H(#)O*9>_":$02^K" +MF*F5#21OUT-KRQ]\L0"FP^9B'>[1/3**.N@"OB````7M\#3O$=.;64K*60;( +M,]2>I1YH\R)I$TL26+"'A#Q(8D+O!W@^'?#M86L+?5OJO77KL:6-2E)2DKC5 +MQHT4:*6!+"=3.IGX3\1=8NN9D,R$7"+A.DG2+C%R#&/"^9?*X#<"-<&M[Y5\L[_=_1,(F$):$K+4EJR-I&M(FD3/ +MDGR64K*=:6M(.$Q](FI95+*I%-(>I9E++I$-(4I9U+,I"](+I:=+1I!](`I; +M-+6I`E'RI;]+;H^U'CI==+FH]%'1I?=+TH[%&WIAU,$HX%&8IEE,?HTE%NIK +MU-)HO]$GIU=.(HHE"HJ(-/[H<4]LJX=3^H!L:'H>H[!FC6*`3@CA)3!E[+&6LWYN# +M1&I/L>\[9XD4HC0@A=+*4T@I(4.H%."=E9*L4XJ);BUECK,8*O]>"]F6LH8R +MQYJK4&@M&;ZWAM+;G2N@J)4JUMI[%61P#?J[-X,QY/7S^ +M!!A0XD6-'D294N9-G3Z%&E3J5:U>Q9M6[EV]?P8<6/)ES9]&G5KV;=V_AQY< +M^G7MW`%/B`"Y@?X"'Q```0!\T``'S@$_P``3_0(0T``R`!`,@&0````$#__X +M'_^!__@?@?_X'_^!^!__@?_X'X'_^!__@?@?_X'_^!^!__@?_X'X'_^!__@? +M@?_X'_^!^!__@?_X'X'_^!__@?@``"!__@?_^```@#YH``9`!R@\C(R&ZKFQ +ML]VG'6NK;7Y'YR_*2;6$.#`H3IT%@:D4DL9DAIUJ.-A"5-S[1?*=.G\Y*:'1 +M1KZ6E`1&3E36NH7)B!2(Z,%9;J:8I;R%A;D%KE3`J3R4O.]L0J^):=TM0O*. +M\2.HMA=FQ.2(#*``+0#__RQ`^FC6'9C\M-VY1W%.XY7!&\H5`"+,W&V_=W\^ +M_77O*T?R-^O4X)'`Z3U.Z1X5.M50:RX+XQ#';7;^I6W+O"/4^>9R1RG!Z1^: +M:>8FK#]*MUP\U+YH#IT%O_MOI9`M^L8R)"\'@`\Q$O@``4=AV`+M`SU9^H'X +M9ZFNQQ-0CUX*.""6+X'2R]-H;+96%JR-5HW)NY[/(B9T/2$Z,30K8-_0/9C+ +M-7:)?(99;O+XYLW$/Y(?+U8G^=LTGNZ:2Z'"G8R['JXC>ZW8VK#*5P[&]Y!7 +M(4XT+*1XM?)29BO)=9)?%%8T1___PX77'!5!9,V\L_>>[=7X1I8K?."<=)*) +MMQ(IE +M3*?-I+]6DJZ___G?+6HC]^T+#5G,/$>(M"IY_F>+.3THA1TWV#8R2@W:,SB% +M;4+BDGXR0^$/44-L-'" +M),O9S0>/PWNA#L#-&!*T9TSX?AZEJ&$LLL@]$`#L,&2TZA;RY*]+\74Q1=#P +ME9*X;4Y9E##F*M+0M5N0U#)+.2>*)+#6#3IAVY5R<69:&V"?__ +M]XEC]%^&4693BM$.(L;Y'RKS/)&2$@A$K(7BL)4:TA=:_V'/=C@T9I[K7UP? +M>S`:!,T9`N`;I41,6P[ +MJG&?KE50XF!\1TYPJE_`5R<0X#12A0_M]+_HOO(>:]EYCGFVN0=:U]ES/FDP +M4?@WZ+:X5(JC6VN%)2A&IG\->?E(Q'R.%.+<"\``@Q2/__^`RJ5L!E6DGZ?Z +M@J6*'B7N.GG>N`X):Y*6+>5DU'8EN%A,]=6C7U>%38)2D),4T4Z+@U4]2HB" +MI0`=!:($>Q@'\(1+`8$Q.`0!`7!4`!T%4(`N((JRA(0MD&/4=$I.X[3K1A+4 +M82-/$Y3=)%L5-2U;6A9UD7-H&07U@E365H$TBJ$G\B*0)9C-_:NI^@Z6R&YK +M6P/=-.QC3'___7922)<0Y5,>Q2VKBW36LFTSS.VZSGO.^+T/I`KYOX_<)1G` +MT+QG#T+P-'#QR7+D7O^^\7R6F#1QY*D)R8]L)M\>,%$Z>B]$$7Z,(\1*>+JN +MJ.+`V"_,"X\60HGD=Q'`[R0?$D8Q4^S_PW`CJ/2_+S.*WSNNFR#1N4S*YK

    KVVW5BL'"S3RI&ZR$\M4* +MK5<+$V&@H80`)A,%0F?C4/BJ@TJBT&G5HSD(MV>MU6GUHM%4DU0JE,L6(N%8 +MRF2+:D3:CV7C+:$#@+#4#EC;)0*`1B+,!&*Q_'Q,*A4%@M%0C%0G%HV +M%XQ&`Q$@I&`J$8F%HP$@D%@^(`V%(\(@X%1#)))(!')H^)Q8(8_&9'?__^OD +MT:L1&`T*B4ZF25ZK^1PJ,1N0-%`MJ&-U<-A[K@GM1Y.!7)=@L)!E4EL,L&UC +MK@LF$\`4$!88`05#@`#\9"DF#<2B\D%46!$:&0Z'0WG=:IDUL`WIA3JIA*E; +MK]C,=,-)F,QH-1Q.!F-MW.-O)!2M%!/1_/N!.2!O9I0>1Q!^QB2R2.PZ,1>% +M/___UB$XV>8$F+"4I'EB-+R$A(2)%E%8@*SPP'C^7(@P%)T,E&4^)A@QA3P8 +M*.C%&E7*!7V988%Y94SQ-8E,I*28F*P89+09/)!4H`!P*%0@2-0T +M3#@H9$!08'0X/$X=S.8\K&!D<2BM7,#Z-,L4HU"E.@1IU`8:5`(3YQ$-/FPYP +MZ;,)41Y.R4(U;___X8@5#U%6!PL`"0DF1@D/$0\+)FP[#B`]*!,I@Q\+#`>GIKO8,'6D`%BS)LV;O7L&/+GDV[MNW;N'/KWLV[M^_?P(,+'TZ\ +MN/'CR),K7\Z\N?/GT*-+GTZ]NO7KV+-KW\Z]N_?OX,.+'T^^O/GSZ-.K7\^^ +?O?OW\./+GT^_OOW[^//KW\^_O___``8HX(`$%FC@4``` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_tar_empty_with_gnulabel.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_tar_empty_with_gnulabel.c new file mode 100644 index 0000000..83f20bb --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_tar_empty_with_gnulabel.c @@ -0,0 +1,53 @@ +/*- + * Copyright (c) 2019 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * Tar archives with with just a GNU label (or ending with one) should + * be treated as valid (empty) archives + */ +DEFINE_TEST(test_read_format_tar_empty_with_gnulabel) +{ + char name[] = "test_read_format_tar_empty_with_gnulabel.tar"; + struct archive_entry *ae; + struct archive *a; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + extract_reference_file(name); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240)); + + /* Read first entry. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify that the format detection worked. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_tar_empty_with_gnulabel.tar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_tar_empty_with_gnulabel.tar.uu new file mode 100644 index 0000000..c5aa393 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_tar_empty_with_gnulabel.tar.uu @@ -0,0 +1,231 @@ +begin 664 test_read_format_tar_empty_with_gnulabel.tar +M;&%B96P````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`#$S-#8W-S,V,C`S`#`P,C8R,``@5@`````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +9```````````````````````````````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_tar_filename.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_tar_filename.c new file mode 100644 index 0000000..9ee8e81 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_tar_filename.c @@ -0,0 +1,394 @@ +/*- + * Copyright (c) 2011 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD"); + +#include + +/* + * The sample tar file was made in LANG=KOI8-R and it contains two + * files the charset of which are different. + * - the filename of first file is stored in BINARY mode. + * - the filename of second file is stored in UTF-8. + * + * Whenever hdrcharset option is specified, we will correctly read the + * filename of second file, which is stored in UTF-8 by default. + */ + +static void +test_read_format_tar_filename_KOI8R_CP866(const char *refname) +{ + struct archive *a; + struct archive_entry *ae; + + /* + * Read filename in ru_RU.CP866 with "hdrcharset=KOI8-R" option. + * We should correctly read two filenames. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia.866") && + NULL == setlocale(LC_ALL, "ru_RU.CP866")) { + skipping("ru_RU.CP866 locale not available on this system."); + return; + } + + /* Test if the platform can convert from UTF-8. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_tar(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=UTF-8")) { + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + skipping("This system cannot convert character-set" + " from UTF-8 to CP866."); + return; + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=KOI8-R")) { + skipping("This system cannot convert character-set" + " from KOI8-R to CP866."); + goto next_test; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular first file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\x8f\x90\x88\x82\x85\x92", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify regular second file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xaf\xe0\xa8\xa2\xa5\xe2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_COMPRESS, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE, + archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +next_test: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + + /* + * Read filename in ru_RU.CP866 without "hdrcharset=KOI8-R" option. + * The filename we can properly read is only second file. + */ + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* + * Verify regular first file. + * The filename is not translated to CP866 because hdrcharset + * attribute is BINARY and there is not way to know its charset. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + /* A filename is in KOI8-R. */ + assertEqualString("\xf0\xf2\xe9\xf7\xe5\xf4", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* + * Verify regular second file. + * The filename is translated from UTF-8 to CP866 + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xaf\xe0\xa8\xa2\xa5\xe2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_COMPRESS, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE, + archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +static void +test_read_format_tar_filename_KOI8R_UTF8(const char *refname) +{ + struct archive *a; + struct archive_entry *ae; + + /* + * Read filename in en_US.UTF-8 with "hdrcharset=KOI8-R" option. + * We should correctly read two filenames. + */ + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=KOI8-R")) { + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + skipping("This system cannot convert character-set" + " from KOI8-R to UTF-8."); + return; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\x9f\xd0\xa0\xd0\x98\xd0\x92\xd0\x95\xd0\xa2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\xbf\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify encryption status */ + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_COMPRESS, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE, + archive_format(a)); + + /* Verify encryption status */ + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Read filename in en_US.UTF-8 without "hdrcharset=KOI8-R" option. + * The filename we can properly read is only second file. + */ + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* + * Verify regular first file. + * The filename is not translated to UTF-8 because hdrcharset + * attribute is BINARY and there is not way to know its charset. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + /* A filename is in KOI8-R. */ + assertEqualString("\xf0\xf2\xe9\xf7\xe5\xf4", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + /* Verify encryption status */ + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* + * Verify regular second file. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\xbf\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_COMPRESS, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE, + archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +static void +test_read_format_tar_filename_KOI8R_CP1251(const char *refname) +{ + struct archive *a; + struct archive_entry *ae; + + /* + * Read filename in CP1251 with "hdrcharset=KOI8-R" option. + * We should correctly read two filenames. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia") && + NULL == setlocale(LC_ALL, "ru_RU.CP1251")) { + skipping("CP1251 locale not available on this system."); + return; + } + + /* Test if the platform can convert from UTF-8. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_tar(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=UTF-8")) { + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + skipping("This system cannot convert character-set" + " from UTF-8 to CP1251."); + return; + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=KOI8-R")) { + skipping("This system cannot convert character-set" + " from KOI8-R to CP1251."); + goto next_test; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular first file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xcf\xd0\xc8\xc2\xc5\xd2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify regular second file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xef\xf0\xe8\xe2\xe5\xf2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_COMPRESS, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE, + archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +next_test: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Read filename in CP1251 without "hdrcharset=KOI8-R" option. + * The filename we can properly read is only second file. + */ + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* + * Verify regular first file. + * The filename is not translated to CP1251 because hdrcharset + * attribute is BINARY and there is not way to know its charset. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + /* A filename is in KOI8-R. */ + assertEqualString("\xf0\xf2\xe9\xf7\xe5\xf4", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* + * Verify regular second file. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xef\xf0\xe8\xe2\xe5\xf2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_COMPRESS, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE, + archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + +DEFINE_TEST(test_read_format_tar_filename) +{ + const char *refname = "test_read_format_tar_filename_koi8r.tar.Z"; + + extract_reference_file(refname); + test_read_format_tar_filename_KOI8R_CP866(refname); + test_read_format_tar_filename_KOI8R_UTF8(refname); + test_read_format_tar_filename_KOI8R_CP1251(refname); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_tar_filename_koi8r.tar.Z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_tar_filename_koi8r.tar.Z.uu new file mode 100644 index 0000000..80b4568 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_tar_filename_koi8r.tar.Z.uu @@ -0,0 +1,14 @@ +begin 644 test_read_format_tar_filename_koi8r.tar.Z +M'YV04,+@05(F#)DR3.FQ9O7%@,[A`B[]L:6($5"-5D#Y>Z57;=ZM"&3 +M9N^?.'7RG/'81E`8MJ,77=KTJ<>KI;&3%L[2J_3OX%/+?AB^O/GSZ-.K7\\^ +M?,"!!0\FA"8MV;5BU-IO_QB2)6_?*O76G7`@%5?33SV)Q%-E-]`0U%#ZV4:= +M4U!I5Y:%9'$7'%<1=GC>67OU]1;AD$06:>212&)$GWWX)5D6;OW])J"4``K7$G$S'6A9 +M#3[MU!E-SSF)VH361355=F?NYYV&8K9)VGBTN2GGG'36:>>=>.:IYYY\]NGG +(GX`&*NB@%P$` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_tbz.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_tbz.c new file mode 100644 index 0000000..331955f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_tbz.c @@ -0,0 +1,62 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_tbz.c 201247 2009-12-30 05:59:21Z kientzle $"); + +static unsigned char archive[] = { +'B','Z','h','9','1','A','Y','&','S','Y',237,7,140,'W',0,0,27,251,144,208, +128,0,' ','@',1,'o',128,0,0,224,'"',30,0,0,'@',0,8,' ',0,'T','2',26,163,'&', +129,160,211,212,18,'I',169,234,13,168,26,6,150,'1',155,134,'p',8,173,3,183, +'J','S',26,20,'2',222,'b',240,160,'a','>',205,'f',29,170,227,'[',179,139, +'\'','L','o',211,':',178,'0',162,134,'*','>','8',24,153,230,147,'R','?',23, +'r','E','8','P',144,237,7,140,'W'}; + +DEFINE_TEST(test_read_format_tbz) +{ + struct archive_entry *ae; + struct archive *a; + int r; + + assert((a = archive_read_new()) != NULL); + r = archive_read_support_filter_bzip2(a); + if (r != ARCHIVE_OK) { + skipping("Bzip2 support"); + archive_read_free(a); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, archive, sizeof(archive))); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_file_count(a)); + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_BZIP2); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_tgz.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_tgz.c new file mode 100644 index 0000000..9fba896 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_tgz.c @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_tgz.c 191183 2009-04-17 01:06:31Z kientzle $"); + +static unsigned char archive[] = { +31,139,8,0,222,'C','p','C',0,3,211,'c',160,'=','0','0','0','0','7','5','U', +0,210,134,230,166,6,200,'4',28,'(',24,26,24,27,155,24,152,24,154,27,155,')', +24,24,26,152,154,25,'2','(',152,210,193,'m',12,165,197,'%',137,'E','@',167, +148,'d',230,226,'U','G','H',30,234,15,'8','=',10,'F',193,'(',24,5,131,28, +0,0,29,172,5,240,0,6,0,0}; + +DEFINE_TEST(test_read_format_tgz) +{ + struct archive_entry *ae; + struct archive *a; + int r; + + assert((a = archive_read_new()) != NULL); + assertEqualInt(ARCHIVE_OK, archive_read_support_filter_all(a)); + r = archive_read_support_filter_gzip(a); + if (r == ARCHIVE_WARN) { + skipping("gzip reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + assertEqualInt(ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualInt(ARCHIVE_OK, + archive_read_open_memory(a, archive, sizeof(archive))); + assertEqualInt(ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_file_count(a)); + assertEqualInt(archive_filter_code(a, 0), + ARCHIVE_FILTER_GZIP); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK,archive_read_free(a)); +} + + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_tlz.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_tlz.c new file mode 100644 index 0000000..7c7a143 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_tlz.c @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2009 Michihiro NAKAJIMA + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_tlz.c 201247 2009-12-30 05:59:21Z kientzle $"); + +static unsigned char archive[] = { + 93, 0, 0,128, 0,255,255,255,255,255,255,255,255, 0, 23, 0, + 51, 80, 24,164,204,238, 45, 77, 28,191, 13,144, 8, 10, 70, 5, +173,215, 47,132,237,145,162, 96, 6,131,168,152, 8,135,161,189, + 73,110,132, 27,195, 52,109,203, 22, 17,168,211, 18,181, 76, 93, +120, 88,154,155,244,141,193,206,170,224, 80,137,134, 67, 1, 9, +123,121,189, 74,137,197, 63,255,214, 55,119, 0 +}; + +DEFINE_TEST(test_read_format_tlz) +{ + struct archive_entry *ae; + struct archive *a; + int r; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + r = archive_read_support_filter_lzma(a); + if (r == ARCHIVE_WARN) { + skipping("lzma reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, archive, sizeof(archive))); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_file_count(a)); + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_LZMA); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_txz.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_txz.c new file mode 100644 index 0000000..c082d7e --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_txz.c @@ -0,0 +1,66 @@ +/*- + * Copyright (c) 2009 Michihiro NAKAJIMA + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_txz.c 191183 2009-04-17 01:06:31Z kientzle $"); + +static unsigned char archive[] = { +253, 55,122, 88, 90, 0, 0, 4,230,214,180, 70, 2, 0, 33, 1, + 22, 0, 0, 0,116, 47,229,163,224, 5,255, 0, 73, 93, 0, 23, + 0, 51, 80, 24,164,204,238, 45, 77, 28,191, 13,144, 8, 10, 70, + 5,173,215, 47,132,237,145,162, 96, 6,131,168,152, 8,135,161, +189, 73,110,132, 27,195, 52,109,203, 22, 17,168,211, 18,181, 76, + 93,120, 88,154,155,244,141,193,206,170,224, 80,137,134, 67, 1, + 9,123,121,188,247, 28,139, 0, 0, 0, 0, 0,112,184, 17, 5, +103, 16, 8, 73, 0, 1,101,128, 12, 0, 0, 0, 30, 69, 92, 96, +177,196,103,251, 2, 0, 0, 0, 0, 4, 89, 90 +}; + +DEFINE_TEST(test_read_format_txz) +{ + struct archive_entry *ae; + struct archive *a; + int r; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + r = archive_read_support_filter_xz(a); + if (r == ARCHIVE_WARN) { + skipping("xz reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, archive, sizeof(archive))); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_file_count(a)); + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_XZ); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_tz.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_tz.c new file mode 100644 index 0000000..4ba7bcb --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_tz.c @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_tz.c 189381 2009-03-05 00:31:48Z kientzle $"); + +static unsigned char archive[] = { +31,157,144,'.',0,8,28,'H',176,160,193,131,8,19,'*','\\',200,176,'!','B',24, +16,'o',212,168,1,2,0,196,24,18,'a','T',188,152,'q','#',196,143,' ','5',198, +128,'1','c',6,13,24,'4','0',206,176,1,2,198,200,26,'6','b',0,0,'Q',195,161, +205,155,'8','s',234,4,'P','g',14,157,'0','r',',',194,160,147,166,205,206, +132,'D',141,30,'=',24,'R',163,'P',144,21,151,'J',157,'J',181,170,213,171, +'X',179,'j',221,202,181,171,215,175,'`',195,138,29,'K',182,172,217,179,'h', +211,170,']',203,182,173,219,183,'g',1}; + +DEFINE_TEST(test_read_format_tz) +{ + struct archive_entry *ae; + struct archive *a; + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, archive, sizeof(archive))); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_file_count(a)); + failure("archive_filter_name(a, 0)=\"%s\"", + archive_filter_name(a, 0)); + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); + failure("archive_format_name(a)=\"%s\"", archive_format_name(a)); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_ustar_filename.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_ustar_filename.c new file mode 100644 index 0000000..5c2717c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_ustar_filename.c @@ -0,0 +1,547 @@ +/*- + * Copyright (c) 2011 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD"); + +#include + +static void +test_read_format_ustar_filename_eucJP_UTF8(const char *refname) +{ + struct archive *a; + struct archive_entry *ae; + + /* + * Read eucJP filename in en_US.UTF-8 with "hdrcharset=eucJP" option. + */ + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=eucJP")) { + skipping("This system cannot convert character-set" + " from eucJP to UTF-8."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xe6\xbc\xa2\xe5\xad\x97.txt", + archive_entry_pathname(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xe8\xa1\xa8.txt", archive_entry_pathname(ae)); + assertEqualInt(4, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_COMPRESS, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_TAR_USTAR, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +static void +test_read_format_ustar_filename_CP866_KOI8R(const char *refname) +{ + struct archive *a; + struct archive_entry *ae; + + /* + * Read CP866 filename in ru_RU.KOI8-R with "hdrcharset=CP866" option. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia.20866") && + NULL == setlocale(LC_ALL, "ru_RU.KOI8-R")) { + skipping("ru_RU.KOI8-R locale not available on this system."); + return; + } + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=CP866")) { + skipping("This system cannot convert character-set" + " from CP866 to KOI8-R."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xf0\xf2\xe9\xf7\xe5\xf4", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\xd2\xc9\xd7\xc5\xd4", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_COMPRESS, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_TAR_USTAR, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +static void +test_read_format_ustar_filename_CP866_UTF8(const char *refname) +{ + struct archive *a; + struct archive_entry *ae; + + /* + * Read CP866 filename in en_US.UTF-8 with "hdrcharset=CP866" option. + */ + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=CP866")) { + skipping("This system cannot convert character-set" + " from CP866 to UTF-8."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\x9f\xd0\xa0\xd0\x98\xd0\x92\xd0\x95\xd0\xa2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\xbf\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_COMPRESS, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_TAR_USTAR, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +static void +test_read_format_ustar_filename_KOI8R_CP866(const char *refname) +{ + struct archive *a; + struct archive_entry *ae; + + /* + * Read KOI8-R filename in ru_RU.CP866 with "hdrcharset=KOI8-R" option. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia.866") && + NULL == setlocale(LC_ALL, "ru_RU.CP866")) { + skipping("ru_RU.CP866 locale not available on this system."); + return; + } + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=KOI8-R")) { + skipping("This system cannot convert character-set" + " from KOI8-R to CP866."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xaf\xe0\xa8\xa2\xa5\xe2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\x8f\x90\x88\x82\x85\x92", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_COMPRESS, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_TAR_USTAR, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +static void +test_read_format_ustar_filename_KOI8R_UTF8(const char *refname) +{ + struct archive *a; + struct archive_entry *ae; + + /* + * Read KOI8-R filename in en_US.UTF-8 with "hdrcharset=KOI8-R" option. + */ + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=KOI8-R")) { + skipping("This system cannot convert character-set" + " from KOI8-R to UTF-8."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\xbf\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\x9f\xd0\xa0\xd0\x98\xd0\x92\xd0\x95\xd0\xa2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_COMPRESS, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_TAR_USTAR, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +static void +test_read_format_ustar_filename_eucJP_CP932(const char *refname) +{ + struct archive *a; + struct archive_entry *ae; + + /* + * Read eucJP filename in CP932/SJIS with "hdrcharset=eucJP" option. + */ + if (NULL == setlocale(LC_ALL, "Japanese_Japan") && + NULL == setlocale(LC_ALL, "ja_JP.SJIS")) { + skipping("CP932 locale not available on this system."); + return; + } + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=eucJP")) { + skipping("This system cannot convert character-set" + " from eucJP."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\x8a\xbf\x8e\x9a.txt", archive_entry_pathname(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\x95\x5c.txt", archive_entry_pathname(ae)); + assertEqualInt(4, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_COMPRESS, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_TAR_USTAR, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +static void +test_read_format_ustar_filename_CP866_CP1251(const char *refname) +{ + struct archive *a; + struct archive_entry *ae; + + /* + * Read CP866 filename in CP1251 with "hdrcharset=CP866" option. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia") && + NULL == setlocale(LC_ALL, "ru_RU.CP1251")) { + skipping("CP1251 locale not available on this system."); + return; + } + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=CP866")) { + skipping("This system cannot convert character-set" + " from CP866 to CP1251."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xcf\xd0\xc8\xc2\xc5\xd2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xef\xf0\xe8\xe2\xe5\xf2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_COMPRESS, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_TAR_USTAR, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +/* + * This test only for Windows platform because other archiver + * applications on Windows translate CP1251 filenames into CP866 + * filenames and store it in the ustar file and so we should read + * it by default on Windows. + */ +static void +test_read_format_ustar_filename_CP866_CP1251_win(const char *refname) +{ + struct archive *a; + struct archive_entry *ae; + + /* + * Read CP866 filename in CP1251 without "hdrcharset=CP866" option. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia")) { + skipping("Russian_Russia locale not available on this system."); + return; + } + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xcf\xd0\xc8\xc2\xc5\xd2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xef\xf0\xe8\xe2\xe5\xf2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_COMPRESS, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_TAR_USTAR, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +static void +test_read_format_ustar_filename_KOI8R_CP1251(const char *refname) +{ + struct archive *a; + struct archive_entry *ae; + + /* + * Read KOI8-R filename in CP1251 with "hdrcharset=KOI8-R" option. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia") && + NULL == setlocale(LC_ALL, "ru_RU.CP1251")) { + skipping("CP1251 locale not available on this system."); + return; + } + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=KOI8-R")) { + skipping("This system cannot convert character-set" + " from KOI8-R to CP1251."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xef\xf0\xe8\xe2\xe5\xf2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xcf\xd0\xc8\xc2\xc5\xd2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_COMPRESS, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_TAR_USTAR, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + +DEFINE_TEST(test_read_format_ustar_filename) +{ + const char *refname1 = "test_read_format_ustar_filename_eucjp.tar.Z"; + const char *refname2 = "test_read_format_ustar_filename_cp866.tar.Z"; + const char *refname3 = "test_read_format_ustar_filename_koi8r.tar.Z"; + + extract_reference_file(refname1); + test_read_format_ustar_filename_eucJP_UTF8(refname1); + test_read_format_ustar_filename_eucJP_CP932(refname1); + + extract_reference_file(refname2); + test_read_format_ustar_filename_CP866_KOI8R(refname2); + test_read_format_ustar_filename_CP866_UTF8(refname2); + test_read_format_ustar_filename_CP866_CP1251(refname2); + test_read_format_ustar_filename_CP866_CP1251_win(refname2); + + extract_reference_file(refname3); + test_read_format_ustar_filename_KOI8R_CP866(refname3); + test_read_format_ustar_filename_KOI8R_UTF8(refname3); + test_read_format_ustar_filename_KOI8R_CP1251(refname3); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_ustar_filename_cp866.tar.Z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_ustar_filename_cp866.tar.Z.uu new file mode 100644 index 0000000..359fc2b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_ustar_filename_cp866.tar.Z.uu @@ -0,0 +1,8 @@ +begin 644 test_read_format_ustar_filename_cp866.tar.Z +M'YV0CR`A$E1($H"#"!,J7,BPH<.'$"-*1`BCXHT:-4``J!CC8@R-'#V"K$BR +MI`T0,6+4H'%CA@R5,#[&?%E#!@`0,";JW,FSIT\`=>;0"2-G(XPQ=AM'4NVK-FS:-.J7!V2O)C1:,<:'_V*-!J5Y,F4*UO2C(DSA@P;CF_FS$OY8="A12LV';MY +K:^&I)*M6'DT::]>O84NK7LVZM>O7L&/+GDV[MNW;N'/KWLV[M^_?P(,K!``` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_ustar_filename_eucjp.tar.Z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_ustar_filename_eucjp.tar.Z.uu new file mode 100644 index 0000000..c6ab110 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_ustar_filename_eucjp.tar.Z.uu @@ -0,0 +1,9 @@ +begin 644 test_read_format_ustar_filename_eucjp.tar.Z +M'YV0M(+MTN>"#AXZ`!(J7,BPH<.'$"-*G$@1`(R+-FC0`&$11HP;-6)PO/@Q +MY,B+*%'&@`$B1HP:(6O(D"&3I4<9-V;$```"1L6?0(,*'0J@SAPZ8>1T'%.G +M#%&(3)T^=9CRXLF4'*=JWBBGXYTB0HE2!D7].J7M,L7(LJ,&SN6%"D8).&J53>ZA/ER9LV>,63`N.&S9]_+$HTB57HQ +M:EK/7Q%?19D5L^G37-FD.8JZM>O7L&/+GDV[MNW;N'/KWLV[M^_?P(,+'T[< +!(0`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_ustar_filename_koi8r.tar.Z.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_ustar_filename_koi8r.tar.Z.uu new file mode 100644 index 0000000..15e0d63 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_ustar_filename_koi8r.tar.Z.uu @@ -0,0 +1,8 @@ +begin 644 test_read_format_ustar_filename_koi8r.tar.Z +M'YV0T*0ENU:,&H"#"!,J7,BPH<.'$"-*1`BCXHT:-4``J!CC8@R-'#V"K$BR +MI`T0,6+4H'%CAHR*,T["B#'#(@`0,";JW,FSIT\`=>;0"2-G(XPQ=AM'4NVK-FS:-.J7O7L&/+GDV[MNW;N'/KWLV[M^^$ +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_warc.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_warc.c new file mode 100644 index 0000000..658ab8a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_warc.c @@ -0,0 +1,82 @@ +/*- + * Copyright (c) 2014 Sebastian Freundt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + + +DEFINE_TEST(test_read_format_warc) +{ + char buff[256U]; + const char reffile[] = "test_read_format_warc.warc"; + struct archive_entry *ae; + struct archive *a; + + extract_reference_file(reffile); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, reffile, 10240)); + + /* First Entry */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("sometest.txt", archive_entry_pathname(ae)); + assertEqualInt(1402399833, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_uid(ae)); + assertEqualInt(0, archive_entry_gid(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(65, archive_entry_size(ae)); + assertEqualInt(65, archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, "This is a sample text file for libarchive's WARC reader/writer.\n\n", 65); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Second Entry */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("moretest.txt", archive_entry_pathname(ae)); + assertEqualInt(1402399884, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_uid(ae)); + assertEqualInt(0, archive_entry_gid(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(76, archive_entry_size(ae)); + assertA(76 == archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, "The beauty is that WARC remains ASCII only iff all contents are ASCII only.\n", 76); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Test EOF */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_file_count(a)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_WARC, archive_format(a)); + + /* Verify closing and resource freeing */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_warc.warc.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_warc.warc.uu new file mode 100644 index 0000000..f89592b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_warc.warc.uu @@ -0,0 +1,23 @@ +begin 644 test_read_format_warc.warc +M5T%20R\Q+C`-"E=!4D,M5'EP93H@=V%R8VEN9F\-"E=!4D,M1&%T93H@,C`Q +M-"TP-BTQ,%0Q,3HS,3HS.%H-"DQA7!E.B!R97-O +M=7)C90T*5T%20RU487)G970M55)).B!F:6QE.B\O2!I +D9F8@86QL(&-O;G1E;G1S(&%R92!!4T-)22!O;FQY+@H-"@T* +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_xar.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_xar.c new file mode 100644 index 0000000..1c85245 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_xar.c @@ -0,0 +1,863 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2009 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +#define UID 1001 +#define UNAME "cue" +#define GID 1001 +#define GNAME "cue" + +/* Verify that a file records with hardlink. +#How to make +echo "hellohellohello" > f1 +chown $UNAME:$GNAME f1 +chmod 0644 f1 +ln f1 hardlink +chown $UNAME:$GNAME hardlink +chmod 0644 hardlink +env TZ=utc touch -afm -t 197001020000.01 f1 hardlink +xar -cf archive1.xar f1 hardlink +od -t x1 archive1.xar | sed -E -e 's/^0[0-9]+//;s/^ //;s/( )([0-9a-f]{2})/0x\2,/g;$ D' > archive1.xar.txt +*/ +static unsigned char archive1[] = { +0x78,0x61,0x72,0x21,0x00,0x1c,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xc6, +0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x70,0x00,0x00,0x00,0x01,0x78,0xda,0xc4,0x54, +0xc9,0x6e,0xdb,0x30,0x14,0xbc,0xe7,0x2b,0x08,0xdd,0x55,0xae,0xb6,0x45,0x83,0x56, +0xd0,0x4b,0xd1,0x7b,0xd3,0x4b,0x6f,0x34,0x17,0x89,0x88,0x36,0x48,0x54,0xe0,0xe4, +0xeb,0x4b,0x52,0x52,0x0c,0xa7,0x71,0x6f,0x45,0x01,0x01,0x1a,0x0e,0x87,0xa3,0xa7, +0xf7,0x06,0x14,0x8f,0x97,0xb6,0x01,0x2f,0x66,0x9c,0x5c,0xdf,0x9d,0x32,0xfc,0x05, +0x65,0xc0,0x74,0xaa,0xd7,0xae,0xab,0x4e,0xd9,0xcf,0xa7,0x6f,0x79,0x91,0x3d,0x96, +0x0f,0xe2,0x22,0xc7,0xf2,0x01,0x08,0xdf,0xab,0xf0,0x02,0x42,0x8d,0x46,0xfa,0x70, +0x22,0xf7,0xae,0x35,0x25,0x41,0x88,0xe7,0x98,0xe4,0x88,0x3c,0x61,0x7a,0xa4,0xe8, +0x48,0xb9,0x80,0xb7,0x92,0x74,0xa8,0x36,0xea,0x79,0x9a,0x5b,0x30,0xf9,0xd7,0xc6, +0x9c,0xb2,0xa9,0x96,0x38,0x8b,0x3b,0x40,0xf4,0xd6,0x4e,0xc6,0x97,0x48,0xc0,0x15, +0x25,0x76,0x72,0x6f,0xd1,0x5c,0xc0,0x04,0xa2,0x05,0xdc,0x3c,0xd2,0xca,0xba,0xc6, +0x00,0xa7,0x4f,0x19,0x59,0x6d,0xd4,0x9d,0x72,0xd8,0xaf,0x70,0x72,0xab,0x03,0x88, +0x36,0x41,0xcc,0x0f,0x28,0x47,0x38,0xca,0x10,0x3a,0xc6,0x07,0x07,0x59,0x7b,0x95, +0xc9,0x7b,0x3f,0x17,0x64,0xf2,0x2a,0xab,0xc6,0x7e,0x1e,0x4a,0x35,0x1b,0x01,0x17, +0xb8,0xb0,0x4e,0x97,0x18,0x21,0x1c,0xc8,0x80,0x12,0x35,0x4f,0x66,0x5c,0x74,0x09, +0x2d,0xdc,0xbb,0x6c,0xde,0x64,0x6d,0xaf,0x4d,0x89,0xf6,0x8c,0x85,0x62,0x22,0x4c, +0xa4,0x7f,0x1d,0x0c,0x68,0x5c,0xf7,0x1c,0x66,0x94,0x95,0xb5,0x1c,0x75,0x5c,0x08, +0x18,0xf9,0x45,0xd1,0xc9,0x50,0xd0,0x75,0x23,0x2d,0x53,0xcb,0x62,0x97,0x6e,0xdb, +0xb5,0x75,0x5d,0x4b,0x2f,0x13,0x02,0xa2,0x31,0x5d,0xe5,0xeb,0x92,0x50,0x01,0x57, +0xb8,0xf0,0xeb,0x38,0xc8,0xed,0x64,0xd6,0xd1,0xe0,0xfd,0x75,0x34,0x81,0xdb,0x72, +0xb3,0xcd,0x57,0x0e,0x43,0xe3,0x54,0x0a,0x01,0xbc,0xe4,0xd5,0x9b,0x1b,0x32,0xb8, +0x4a,0xe5,0xa8,0x6a,0xf7,0x62,0x74,0xfe,0x31,0x13,0x3f,0xbe,0x7f,0x0d,0xd5,0xd9, +0x82,0x52,0x4d,0xac,0x56,0x98,0x53,0xc6,0xa9,0x3c,0xb3,0x82,0x4b,0x2d,0x09,0xb5, +0x85,0x3d,0x70,0x6c,0xf7,0xc4,0x2a,0xba,0xe7,0x45,0x98,0xc3,0x47,0xa3,0xad,0x96, +0x8b,0x1f,0xa5,0xf2,0x77,0xbf,0xb0,0xd3,0x07,0x76,0x56,0x67,0x75,0xe0,0x9a,0x5a, +0x7e,0xb6,0x4c,0xda,0xe0,0xcd,0x8a,0xa2,0x40,0x86,0xed,0xc8,0x7e,0xc7,0xac,0x41, +0x8a,0x87,0x1c,0xff,0xe9,0xb4,0x34,0x0f,0xbe,0x77,0xef,0x9f,0xc4,0xee,0x73,0xd9, +0x7f,0x8c,0x5d,0x3f,0xba,0xca,0x75,0xb2,0xf9,0x4b,0xfa,0x2c,0xfe,0x24,0x77,0x41, +0x15,0x2f,0x0d,0x01,0xd3,0x15,0xf2,0x1b,0x00,0x00,0xff,0xff,0x03,0x00,0x88,0x32, +0x49,0x7b,0x67,0xbf,0xc6,0x01,0x29,0xf2,0x1c,0x40,0x05,0x3c,0x49,0x25,0x9f,0xab, +0x7c,0x8e,0xc5,0xa5,0x79,0xe0,0x78,0xda,0xca,0x48,0xcd,0xc9,0xc9,0xcf,0x80,0x13, +0x5c,0x00,0x00,0x00,0x00,0xff,0xff,0x03,0x00,0x37,0xf7,0x06,0x47 +}; + +static void verify0(struct archive *a, struct archive_entry *ae) +{ + const void *p; + size_t size; + int64_t offset; + + assert(archive_entry_filetype(ae) == AE_IFREG); + assertEqualInt(archive_entry_mode(ae) & 0777, 0644); + assertEqualInt(archive_entry_uid(ae), UID); + assertEqualInt(archive_entry_gid(ae), GID); + assertEqualString(archive_entry_uname(ae), UNAME); + assertEqualString(archive_entry_gname(ae), GNAME); + assertEqualString(archive_entry_pathname(ae), "f1"); + assert(archive_entry_hardlink(ae) == NULL); + assert(archive_entry_symlink(ae) == NULL); + assertEqualInt(archive_entry_mtime(ae), 86401); + assertEqualInt(archive_entry_size(ae), 16); + assertEqualInt(archive_read_data_block(a, &p, &size, &offset), 0); + assertEqualInt((int)size, 16); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "hellohellohello\n", 16); +} + +static void verify1(struct archive *a, struct archive_entry *ae) +{ + (void)a; /* UNUSED */ + /* A hardlink is not a symlink. */ + assert(archive_entry_filetype(ae) != AE_IFLNK); + /* Nor is it a directory. */ + assert(archive_entry_filetype(ae) != AE_IFDIR); + assertEqualInt(archive_entry_mode(ae) & 0777, 0644); + assertEqualInt(archive_entry_uid(ae), UID); + assertEqualInt(archive_entry_gid(ae), GID); + assertEqualString(archive_entry_uname(ae), UNAME); + assertEqualString(archive_entry_gname(ae), GNAME); + assertEqualString(archive_entry_pathname(ae), "hardlink"); + assertEqualString(archive_entry_hardlink(ae), "f1"); + assert(archive_entry_symlink(ae) == NULL); + assertEqualInt(archive_entry_mtime(ae), 86401); + assertEqualInt(archive_entry_nlink(ae), 2); +} + +/* Verify that symlinks are read correctly. +#How to make +echo "hellohellohello" > f1 +chown $UNAME:$GNAME f1 +chmod 0644 f1 +ln -s f1 symlink +chown $UNAME:$GNAME symlink +chmod 0644 symlink +env TZ=utc touch -afm -t 197001020000.01 f1 symlink +xar -cf archive2.xar f1 symlink +od -t x1 archive2.xar | sed -E -e 's/^0[0-9]+//;s/^ //;s/( )([0-9a-f]{2})/0x\2,/g;$ D' > archive2.xar.txt +*/ +static unsigned char archive2[] = { +0x78,0x61,0x72,0x21,0x00,0x1c,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xe8, +0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x84,0x00,0x00,0x00,0x01,0x78,0xda,0xb4,0x54, +0xcb,0x6e,0xa3,0x30,0x14,0xdd,0xf7,0x2b,0x90,0xf7,0x8c,0x1f,0x40,0x82,0x23,0xe3, +0xaa,0x9b,0x6a,0xf6,0xd3,0xd9,0xcc,0xce,0xf1,0x83,0x58,0xe5,0x25,0x70,0xaa,0xa4, +0x5f,0x3f,0xb6,0x09,0x4d,0xd3,0x30,0xdd,0x8d,0x84,0xc4,0xf5,0xf1,0xb9,0xc7,0x97, +0x7b,0x0f,0x66,0x8f,0xa7,0xb6,0x49,0xde,0xf4,0x38,0xd9,0xbe,0xab,0x00,0xfe,0x81, +0x40,0xa2,0x3b,0xd9,0x2b,0xdb,0xd5,0x15,0xf8,0xfd,0xf2,0x9c,0x96,0xe0,0x91,0x3f, +0xb0,0x93,0x18,0xf9,0x43,0xc2,0x5c,0x2f,0xfd,0x2b,0x61,0x72,0xd4,0xc2,0xf9,0x8c, +0xd4,0xd9,0x56,0x73,0x82,0x10,0x4d,0x31,0x49,0x11,0x79,0xc1,0xd9,0x2e,0x2b,0x76, +0xb8,0x60,0xf0,0x96,0x12,0x93,0x0e,0x5a,0xbe,0x4e,0xc7,0x36,0x99,0xdc,0xb9,0xd1, +0x15,0x98,0x0e,0x02,0x83,0xb0,0x93,0xb0,0xde,0x98,0x49,0x3b,0x8e,0x18,0xbc,0x44, +0x11,0x9d,0xec,0x7b,0x10,0x67,0x30,0x06,0x41,0x02,0x2e,0x1a,0x71,0x65,0x6c,0xa3, +0x13,0xab,0x2a,0x40,0x2e,0x32,0xf2,0xae,0x1c,0xb4,0xcb,0xd1,0x0e,0xd1,0x3f,0x3e, +0x73,0xa9,0x23,0x61,0xed,0x37,0xb4,0xf6,0x4a,0x13,0xdf,0xd0,0xc4,0x95,0x56,0x8f, +0xfd,0x71,0xe0,0xf2,0xa8,0x19,0x9c,0xc3,0x19,0xb5,0x8a,0x63,0x84,0xb0,0x07,0x7d, +0x14,0xa1,0xe3,0xa4,0xc7,0x99,0x17,0xa3,0x19,0xfb,0xa0,0x1d,0x17,0x5a,0xdb,0x2b, +0xcd,0xd1,0xb6,0xf0,0x3d,0x8c,0x61,0x04,0x1b,0xdb,0xbd,0x26,0xee,0x3c,0xf8,0xb6, +0x85,0xaf,0x06,0xdc,0xf8,0x94,0x00,0xce,0xdb,0x61,0x87,0x4f,0xe7,0x36,0x20,0x0c, +0xc6,0x55,0xc4,0x3b,0xd1,0x7e,0xc2,0xe3,0x2a,0xb6,0x31,0x68,0xdc,0xb6,0x70,0x99, +0x84,0x12,0x4e,0xc4,0xc8,0x9f,0xa9,0xbb,0xda,0x1d,0x38,0xc9,0xfc,0x49,0x73,0x38, +0xe3,0x97,0x11,0x91,0xdb,0x69,0x5d,0xc6,0x85,0x37,0xd7,0x71,0x79,0x6c,0xf1,0xd2, +0x32,0x73,0x31,0x0c,0x8d,0x95,0xd1,0x18,0xf0,0x94,0xd6,0xef,0x76,0x00,0xf0,0x42, +0x15,0xa3,0x3c,0xd8,0x37,0xad,0xd2,0xaf,0x3e,0xf9,0xf5,0xf3,0xc9,0x57,0x67,0xca, +0x2c,0x53,0xc4,0x28,0x89,0x69,0x96,0xd3,0x4c,0xec,0xf3,0x92,0x0a,0x25,0x48,0x66, +0x4a,0xb3,0xa5,0xd8,0x6c,0x88,0x91,0xd9,0x86,0x96,0x7e,0x36,0x5f,0x85,0x96,0x5a, +0x4e,0x6e,0x14,0xd2,0xfd,0xf3,0x84,0x42,0x6d,0xf3,0xbd,0xdc,0xcb,0x2d,0x55,0x99, +0xa1,0x7b,0x93,0x0b,0xe3,0xb5,0xf3,0xb2,0x2c,0x91,0xce,0x0b,0xb2,0x29,0x72,0xa3, +0x91,0xa4,0x94,0xc1,0x7b,0xa5,0xb9,0x79,0xf0,0xa3,0x7b,0x2b,0x56,0x9c,0xff,0x0c, +0xb2,0x66,0x45,0x4c,0xb7,0x28,0x45,0x38,0xd0,0x90,0x37,0x98,0x7f,0xf0,0x9a,0x15, +0xd7,0x69,0xff,0xdd,0x8a,0x9b,0x3c,0xff,0x6c,0xc5,0xe0,0xae,0x24,0x18,0xaa,0x02, +0xfd,0x68,0x6b,0xdb,0x89,0x06,0xf0,0x83,0x18,0xd5,0xaa,0xf9,0x82,0x4f,0xef,0x7c, +0xe7,0x59,0xe1,0x22,0x61,0x30,0x5e,0x2b,0x7f,0x01,0x00,0x00,0xff,0xff,0x03,0x00, +0x2b,0xab,0x4f,0xf9,0xbb,0xf7,0x90,0xb5,0x34,0x8f,0x7c,0xae,0x72,0xa0,0x80,0xd2, +0x69,0xc7,0xa2,0xe7,0x44,0x53,0xeb,0x75,0x78,0xda,0xca,0x48,0xcd,0xc9,0xc9,0xcf, +0x80,0x13,0x5c,0x00,0x00,0x00,0x00,0xff,0xff,0x03,0x00,0x37,0xf7,0x06,0x47 +}; + +static void verify2(struct archive *a, struct archive_entry *ae) +{ + (void)a; /* UNUSED */ + assertEqualInt(archive_entry_filetype(ae), AE_IFLNK); + assertEqualInt(archive_entry_mode(ae) & 0777, 0755); + assertEqualInt(archive_entry_uid(ae), UID); + assertEqualInt(archive_entry_gid(ae), GID); + assertEqualString(archive_entry_uname(ae), UNAME); + assertEqualString(archive_entry_gname(ae), GNAME); + assertEqualString(archive_entry_pathname(ae), "symlink"); + assertEqualString(archive_entry_symlink(ae), "f1"); + assert(archive_entry_hardlink(ae) == NULL); +} + +/* Character device node. +#How to make +mknod devchar c 0 30 +chown $UNAME:$GNAME devchar +chmod 0644 devchar +env TZ=utc touch -afm -t 197001020000.01 devchar +xar -cf archive3.xar devchar +od -t x1 archive3.xar | sed -E -e 's/^0[0-9]+//;s/^ //;s/( )([0-9a-f]{2})/0x\2,/g;$ D' > archive3.xar.txt +*/ +static unsigned char archive3[] = { +0x78,0x61,0x72,0x21,0x00,0x1c,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x38, +0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x3b,0x00,0x00,0x00,0x01,0x78,0xda,0x7c,0x92, +0x4d,0x6e,0xc3,0x20,0x10,0x85,0xf7,0x39,0x05,0xf2,0xde,0x05,0x9c,0x9f,0x36,0xd6, +0x84,0xec,0x7a,0x82,0x74,0xd3,0x1d,0xc2,0x93,0x98,0xd4,0x36,0x11,0xe0,0x28,0xe9, +0xe9,0x0b,0xe3,0xa4,0x69,0xa5,0xaa,0x92,0x25,0x1e,0x8f,0xef,0x8d,0x86,0xc1,0xb0, +0xbd,0xf4,0x1d,0x3b,0xa3,0x0f,0xd6,0x0d,0x9b,0x42,0x3e,0x89,0x82,0xe1,0x60,0x5c, +0x63,0x87,0xc3,0xa6,0x78,0xdb,0xbd,0x96,0x2f,0xc5,0x56,0xcd,0xe0,0xa2,0xbd,0x9a, +0x31,0x88,0xce,0xa4,0x85,0x81,0xf1,0xa8,0x63,0x4a,0x94,0xd1,0xf6,0xa8,0x2a,0x21, +0xd6,0xa5,0xac,0x4a,0x51,0xed,0xa4,0xa8,0xab,0x79,0x2d,0x57,0xc0,0x7f,0x23,0x14, +0x6a,0xd1,0x7c,0x84,0xb1,0x67,0x21,0x5e,0x3b,0xdc,0x14,0xa1,0xd5,0xb2,0xc8,0x27, +0x0c,0xdc,0x7e,0x1f,0x30,0x2a,0x01,0xfc,0xa6,0xc8,0x0d,0xf6,0x33,0x17,0x07,0x4e, +0x22,0x97,0xe0,0xf7,0x1a,0xb4,0xdb,0xdb,0x0e,0x99,0x6d,0x52,0xdb,0xb7,0x32,0xe6, +0xaf,0x76,0xaa,0x7a,0xb9,0x7c,0x4f,0xc9,0x7b,0x1f,0x0c,0x7a,0x92,0x72,0xfd,0x2c, +0x4a,0x21,0x33,0x26,0x44,0x9d,0x3f,0x99,0xb0,0xfe,0x81,0xe9,0x7f,0x30,0xfd,0xc0, +0x0e,0xde,0x8d,0x27,0x65,0x46,0x04,0x3e,0xc9,0xc9,0xb5,0x8d,0x92,0x42,0xc8,0x64, +0x26,0x45,0xd6,0x18,0xd0,0x4f,0x1c,0xa9,0xc9,0xfb,0xc6,0xc6,0x3b,0xd6,0xbb,0x06, +0x95,0x58,0x2d,0x16,0xa9,0x99,0x2c,0xc9,0x6c,0xf0,0x6c,0xcd,0xa4,0x13,0x61,0x07, +0xe7,0xd5,0x3c,0x0d,0x66,0x52,0x37,0x57,0x1f,0x93,0xce,0x26,0x09,0x8a,0xf1,0x1f, +0x39,0x88,0xd7,0x13,0x2a,0xd3,0x6a,0xaf,0x4d,0x44,0xcf,0xc2,0x09,0x8d,0xd5,0x1d, +0x70,0xf2,0x89,0x18,0x74,0xba,0x54,0x8a,0x64,0x08,0x38,0xed,0x68,0xea,0x79,0xd0, +0xf9,0xf9,0x39,0xbd,0x3f,0x70,0xfa,0x1b,0xbe,0x00,0x00,0x00,0xff,0xff,0x03,0x00, +0xab,0x43,0xa3,0xac,0x76,0x40,0x1e,0x8b,0x95,0x0d,0x28,0x79,0x79,0x43,0x49,0x4e, +0x16,0xa1,0x56,0x99,0x1f,0x83,0x77,0x41 +}; + +static void verify3(struct archive *a, struct archive_entry *ae) +{ + (void)a; /* UNUSED */ + assertEqualInt(archive_entry_filetype(ae), AE_IFCHR); + assertEqualInt(archive_entry_mode(ae) & 0777, 0644); + assertEqualInt(archive_entry_uid(ae), UID); + assertEqualInt(archive_entry_gid(ae), GID); + assertEqualString(archive_entry_uname(ae), UNAME); + assertEqualString(archive_entry_gname(ae), GNAME); + assertEqualString(archive_entry_pathname(ae), "devchar"); + assert(archive_entry_symlink(ae) == NULL); + assert(archive_entry_hardlink(ae) == NULL); + assertEqualInt(archive_entry_mtime(ae), 86401); +} + +/* Block device node. +#How to make +mknod devblock b 0 30 +chown $UNAME:$GNAME devblock +chmod 0644 devblock +env TZ=utc touch -afm -t 197001020000.01 devblock +xar -cf archive4.xar devblock +od -t x1 archive4.xar | sed -E -e 's/^0[0-9]+//;s/^ //;s/( )([0-9a-f]{2})/0x\2,/g;$ D' > archive4.xar.txt +*/ +static unsigned char archive4[] = { +0x78,0x61,0x72,0x21,0x00,0x1c,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x34, +0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x38,0x00,0x00,0x00,0x01,0x78,0xda,0x7c,0x92, +0xc1,0x6e,0xc2,0x30,0x0c,0x86,0xef,0x3c,0x45,0xd4,0x7b,0x17,0x07,0xd0,0x0a,0x95, +0x09,0xb7,0x3d,0x01,0xbb,0xec,0x96,0xa5,0x06,0x32,0xda,0xa6,0x6a,0x5a,0x04,0x7b, +0xfa,0x25,0x2e,0x8c,0x4d,0x9a,0x26,0x55,0xea,0x97,0x3f,0x9f,0x2d,0x37,0x29,0x6e, +0x2f,0x4d,0x2d,0xce,0xd4,0x07,0xe7,0xdb,0x4d,0xa6,0x9e,0x20,0x13,0xd4,0x5a,0x5f, +0xb9,0xf6,0xb0,0xc9,0x5e,0x77,0x2f,0xf9,0x2a,0xdb,0xea,0x19,0x5e,0x4c,0xaf,0x67, +0x02,0x07,0x6f,0xe3,0x4b,0xa0,0xed,0xc9,0x0c,0xb1,0x22,0x1f,0x5c,0x43,0x7a,0x0e, +0xb0,0xce,0xd5,0x3c,0x87,0xf9,0x4e,0x41,0xb9,0x58,0x95,0xaa,0x40,0xf9,0x5b,0xe1, +0xa2,0x23,0xd9,0x53,0x18,0x1b,0x11,0x86,0x6b,0x4d,0x9b,0x2c,0x1c,0x8d,0xca,0xd2, +0x8e,0x40,0xbf,0xdf,0x07,0x1a,0x34,0xa0,0xbc,0x11,0xa7,0xc1,0x7d,0xa6,0xe6,0x28, +0x19,0x52,0x0b,0x79,0xef,0xc1,0xab,0xbd,0xab,0x49,0xb8,0x2a,0x8e,0x7d,0x6b,0x63, +0xff,0x1e,0x07,0x8a,0xb7,0x58,0x79,0x9f,0x43,0x60,0xc3,0xa8,0xd6,0x05,0xe4,0xa0, +0x92,0x06,0x50,0xa6,0x47,0x45,0xad,0x79,0x68,0xe6,0x1f,0xcd,0x3c,0xb4,0x43,0xef, +0xc7,0x4e,0xdb,0x91,0x50,0x4e,0x38,0xa5,0xae,0xd2,0x0a,0x40,0xc5,0x30,0x12,0x47, +0x63,0xa0,0x7e,0xf2,0x98,0xa6,0xec,0x5b,0x1b,0xef,0x5a,0xe3,0x2b,0xd2,0xf0,0xbc, +0x5c,0xc6,0x61,0x12,0x72,0x58,0xd1,0xd9,0xd9,0x89,0xa3,0xe1,0x5a,0xdf,0xeb,0x45, +0x3c,0x98,0x89,0x6e,0xa9,0xf9,0x88,0x9c,0x42,0x06,0x2e,0x93,0x3f,0xea,0x70,0xb8, +0x76,0xa4,0xdf,0x6b,0x6f,0x4f,0x22,0x74,0x64,0x9d,0xa9,0x51,0x72,0xc6,0xbb,0xad, +0x89,0x1f,0x14,0x75,0x16,0x50,0xf2,0x92,0x8f,0x3c,0x9d,0x72,0xba,0x7b,0xc9,0x97, +0x8f,0x92,0x7f,0x85,0x2f,0x00,0x00,0x00,0xff,0xff,0x03,0x00,0xbe,0x66,0xa2,0x82, +0x3a,0x54,0xd3,0x61,0xaa,0x8e,0x30,0x4c,0xc8,0x36,0x3b,0x7a,0xa4,0xb9,0xef,0xfc, +0x7a,0x5d,0x21,0xde +}; + +static void verify4(struct archive *a, struct archive_entry *ae) +{ + (void)a; /* UNUSED */ + assertEqualInt(archive_entry_filetype(ae), AE_IFBLK); + assertEqualInt(archive_entry_mode(ae) & 0777, 0644); + assertEqualInt(archive_entry_uid(ae), UID); + assertEqualInt(archive_entry_gid(ae), GID); + assertEqualString(archive_entry_uname(ae), UNAME); + assertEqualString(archive_entry_gname(ae), GNAME); + assertEqualString(archive_entry_pathname(ae), "devblock"); + assert(archive_entry_symlink(ae) == NULL); + assert(archive_entry_hardlink(ae) == NULL); + assertEqualInt(archive_entry_mtime(ae), 86401); +} + +/* Directory. +#How to make +mkdir dir1 +chown $UNAME:$GNAME dir1 +chmod 0755 dir1 +env TZ=utc touch -afm -t 197001020000.01 dir1 +xar -cf archive5.xar dir1 +od -t x1 archive5.xar | sed -E -e 's/^0[0-9]+//;s/^ //;s/( )([0-9a-f]{2})/0x\2,/g;$ D' > archive5.xar.txt +*/ +static unsigned char archive5[] = { +0x78,0x61,0x72,0x21,0x00,0x1c,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x16, +0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xec,0x00,0x00,0x00,0x01,0x78,0xda,0x74,0x91, +0xc1,0x6e,0xc2,0x30,0x0c,0x86,0xef,0x3c,0x45,0xd4,0x7b,0x17,0xa7,0x83,0x31,0xaa, +0x34,0xdc,0xf6,0x04,0xec,0xb2,0x5b,0x95,0x1a,0x88,0x68,0x1a,0x94,0xa4,0x13,0xdd, +0xd3,0x2f,0x71,0xe9,0xd0,0xa4,0x4d,0xaa,0xd4,0x3f,0xbf,0x3f,0xff,0xb2,0x6c,0xb9, +0xbf,0xd9,0x9e,0x7d,0xa2,0x0f,0xc6,0x0d,0x4d,0x21,0x9e,0xa0,0x60,0x38,0x68,0xd7, +0x99,0xe1,0xd4,0x14,0xef,0x87,0xb7,0xf2,0xb5,0xd8,0xab,0x95,0xbc,0xb5,0x5e,0xad, +0x98,0x8c,0x4e,0xa7,0x1f,0x93,0xda,0x63,0x1b,0x53,0x47,0x19,0x8d,0x45,0x55,0x01, +0xec,0x4a,0x51,0x95,0x50,0x1d,0x04,0xd4,0x6b,0x51,0xaf,0x37,0x92,0xff,0x46,0xa8, +0xe9,0x8c,0xfa,0x12,0x46,0xcb,0x42,0x9c,0x7a,0x6c,0x8a,0x70,0x6e,0x45,0x91,0x2b, +0x4c,0xba,0xe3,0x31,0x60,0x54,0x20,0xf9,0x5d,0x91,0x1b,0xcc,0x57,0x0e,0x97,0x9c, +0x44,0x8e,0xe0,0x4b,0x06,0xbd,0x8e,0xa6,0x47,0x66,0xba,0x34,0xf6,0x3d,0x46,0xff, +0x3d,0xce,0x33,0x7c,0xa4,0xce,0x65,0x0e,0x26,0x2d,0x49,0xb1,0xdb,0x42,0x09,0x22, +0x63,0x00,0x75,0xfe,0x44,0xc2,0xec,0x03,0x6b,0xff,0x49,0x7b,0x49,0x58,0xfb,0xc0, +0x4e,0xde,0x8d,0x57,0xa5,0x47,0x94,0x7c,0x96,0xb3,0x6b,0x3a,0x25,0x00,0x44,0x32, +0x93,0x22,0x6b,0x0c,0xe8,0x67,0x8e,0xd4,0xec,0xfd,0x60,0xe3,0x82,0x59,0xd7,0xa1, +0x82,0xed,0x26,0xed,0x90,0x24,0x99,0x71,0xba,0xa2,0xea,0x8c,0x47,0x1d,0x9d,0x9f, +0x24,0xa7,0x37,0x55,0x86,0xd6,0x52,0x25,0x45,0x90,0xa4,0x35,0xe5,0xcd,0xe4,0x7b, +0x71,0x3a,0x98,0xe4,0x74,0xbe,0x6f,0x00,0x00,0x00,0xff,0xff,0x03,0x00,0x23,0x7a, +0x8c,0x2f,0x78,0xe9,0x69,0x28,0x93,0x14,0x72,0x68,0x8d,0xeb,0x42,0x7b,0xf6,0x0f, +0x70,0x64,0xa3,0xff,0xb9,0x35 +}; + +static void verify5(struct archive *a, struct archive_entry *ae) +{ + (void)a; /* UNUSED */ + assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); + assertEqualInt(archive_entry_mtime(ae), 86401); + assertEqualInt(archive_entry_mode(ae) & 0777, 0755); + assertEqualInt(archive_entry_uid(ae), UID); + assertEqualInt(archive_entry_gid(ae), GID); + assertEqualString(archive_entry_uname(ae), UNAME); + assertEqualString(archive_entry_gname(ae), GNAME); +} + +/* fifo +#How to make +mkfifo -m 0755 fifo +chown $UNAME:$GNAME fifo +env TZ=utc touch -afm -t 197001020000.01 fifo +xar -cf archive6.xar fifo +od -t x1 archive6.xar | sed -E -e 's/^0[0-9]+//;s/^ //;s/( )([0-9a-f]{2})/0x\2,/g;$ D' > archive6.xar.txt +*/ +static unsigned char archive6[] = { +0x78,0x61,0x72,0x21,0x00,0x1c,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0e, +0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xe7,0x00,0x00,0x00,0x01,0x78,0xda,0x7c,0x91, +0xc1,0x6e,0xc3,0x20,0x0c,0x86,0xef,0x7d,0x0a,0xc4,0x3d,0xc3,0x64,0xab,0xda,0x46, +0x94,0xde,0xf6,0x04,0xdd,0x65,0x37,0x44,0x9c,0x16,0x2d,0x84,0x2a,0x90,0xa9,0xdd, +0xd3,0x0f,0x9c,0x66,0xd5,0xa4,0x69,0x12,0x52,0xbe,0xfc,0x7c,0xb6,0x2c,0xac,0x0e, +0x57,0xdf,0xb3,0x4f,0x1c,0xa3,0x0b,0xc3,0x9e,0xcb,0x27,0xe0,0x0c,0x07,0x1b,0x5a, +0x37,0x9c,0xf6,0xfc,0xed,0xf8,0x5a,0x6d,0xf9,0x41,0xaf,0xd4,0xd5,0x8c,0x7a,0xc5, +0x54,0x0a,0x36,0x7f,0x98,0xb2,0x23,0x9a,0x94,0x2b,0xaa,0xe4,0x3c,0xea,0x1a,0x60, +0x57,0xc9,0xba,0x82,0xfa,0x28,0x65,0xf3,0x02,0x4d,0xbd,0x55,0xe2,0xb7,0x42,0x45, +0x67,0xb4,0x1f,0x71,0xf2,0x2c,0xa6,0x5b,0x8f,0x7b,0x1e,0xcf,0x46,0xf2,0x72,0xc3, +0x54,0xe8,0xba,0x88,0x49,0x83,0x12,0x77,0xa2,0x34,0xba,0xaf,0xd2,0x5c,0x09,0x82, +0xd2,0x42,0x2c,0x3d,0xe8,0xaf,0x73,0x3d,0x32,0xd7,0xe6,0xb1,0xef,0x6d,0xec,0xdf, +0xe3,0xc8,0xe7,0xf7,0x5c,0xb9,0xcc,0xc1,0x94,0x27,0x94,0xbb,0x0d,0x54,0x20,0x8b, +0x06,0xd0,0x94,0x23,0xb3,0xe6,0x1f,0x9a,0xf9,0x47,0x33,0x0f,0xed,0x34,0x86,0xe9, +0xa2,0xed,0x84,0x4a,0xcc,0x38,0xa7,0xae,0xd5,0x12,0x40,0xe6,0x30,0x13,0x45,0x53, +0xc4,0x71,0xf6,0x88,0xe6,0xec,0x47,0x9b,0x16,0xcd,0x87,0x16,0x35,0x6c,0xd6,0xeb, +0x3c,0x4c,0x41,0x0a,0xd3,0xed,0x82,0xba,0x73,0x5d,0x50,0x82,0x90,0xc2,0xc1,0xf8, +0x25,0x24,0xa4,0x17,0x2a,0x8f,0x52,0x56,0x25,0x68,0x57,0x4a,0xd0,0xe6,0xbe,0x01, +0x00,0x00,0xff,0xff,0x03,0x00,0x44,0x19,0x8a,0x2a,0x82,0xbc,0x8c,0xae,0x97,0xa7, +0x7d,0x65,0xa5,0x82,0xdb,0xaa,0xc2,0xcb,0xbe,0xf0,0x1f,0xd1,0xf9,0x56 +}; + +static void verify6(struct archive *a, struct archive_entry *ae) +{ + (void)a; /* UNUSED */ + assertEqualInt(archive_entry_filetype(ae), AE_IFIFO); + assertEqualInt(archive_entry_mode(ae) & 0777, 0755); + assertEqualInt(archive_entry_uid(ae), UID); + assertEqualInt(archive_entry_gid(ae), GID); + assertEqualString(archive_entry_uname(ae), UNAME); + assertEqualString(archive_entry_gname(ae), GNAME); + assertEqualString(archive_entry_pathname(ae), "fifo"); + assert(archive_entry_symlink(ae) == NULL); + assert(archive_entry_hardlink(ae) == NULL); + assertEqualInt(archive_entry_mtime(ae), 86401); +} + +/* Verify that a file records with directory name. +#How to make +mkdir dir1 +echo "hellohellohello" > dir1/f1 +chown $UNAME:$GNAME dir1/f1 +chmod 0644 dir1/f1 +env TZ=utc touch -afm -t 197001020000.01 dir1/f1 +xar -cf archive7.xar dir1/f1 +od -t x1 archive7.xar | sed -E -e 's/^0[0-9]+//;s/^ //;s/( )([0-9a-f]{2})/0x\2,/g;$ D' > archive7.xar.txt +*/ + +static unsigned char archive7[] = { +0x78,0x61,0x72,0x21,0x00,0x1c,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xbb, +0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x8a,0x00,0x00,0x00,0x01,0x78,0xda,0x7c,0x53, +0xc9,0x6e,0xdb,0x30,0x14,0xbc,0xe7,0x2b,0x04,0xdd,0x55,0x2e,0xa2,0x16,0x1a,0xb4, +0x82,0x5e,0x8a,0xdc,0x93,0x5e,0x7a,0xa3,0xb9,0xd8,0x44,0xb5,0x41,0xa2,0x02,0x3b, +0x5f,0x5f,0x92,0xa2,0x1c,0xbb,0x59,0x00,0x01,0x1a,0x3e,0xce,0x1b,0x0d,0x9f,0x86, +0xec,0xf1,0xdc,0xb5,0xc9,0xab,0x9a,0x66,0x33,0xf4,0xfb,0x14,0xfd,0x80,0x69,0xa2, +0x7a,0x31,0x48,0xd3,0x1f,0xf7,0xe9,0xef,0x97,0x5f,0x59,0x9d,0x3e,0x36,0x0f,0xec, +0xcc,0xa7,0xe6,0x21,0x61,0x76,0x10,0xee,0x95,0x30,0x31,0x29,0x6e,0x5d,0x47,0x66, +0x4d,0xa7,0x1a,0x0c,0x21,0xcd,0x10,0xce,0x20,0x7e,0x41,0x68,0x57,0xe0,0x5d,0x51, +0x31,0x70,0x4f,0x09,0x4d,0x27,0x25,0xfe,0xce,0x4b,0x97,0xcc,0xf6,0xd2,0xaa,0x7d, +0x3a,0x9f,0x38,0x4a,0xfd,0x4e,0xc2,0x06,0xad,0x67,0x65,0x1b,0xc8,0x40,0x44,0xa1, +0x3a,0x9b,0x37,0x2f,0xce,0x40,0x00,0x5e,0x02,0x6c,0x1a,0x61,0xa5,0x4d,0xab,0x12, +0x23,0x9d,0xed,0x28,0x63,0x2f,0xa3,0x6a,0xa4,0x99,0x94,0xb0,0xc3,0x74,0x61,0x20, +0xac,0xc3,0x4e,0xcf,0xbb,0xb0,0x83,0x18,0x08,0x30,0x14,0xaf,0xfd,0x78,0xed,0x4f, +0x98,0xe4,0x96,0xaf,0x30,0x61,0xad,0xea,0x8f,0xf6,0xd4,0xe0,0x9c,0x81,0x08,0xe3, +0x46,0xb4,0x88,0xef,0xdd,0x6e,0x7e,0x51,0xf9,0xee,0xd7,0x17,0xb7,0x69,0x6e,0xa7, +0xe6,0xe3,0xd8,0x1a,0x11,0x46,0x03,0xce,0xd9,0xf1,0xcd,0x8c,0x29,0xd8,0xb8,0x7c, +0x12,0x27,0xf3,0xaa,0x64,0xf6,0xff,0xa8,0x9e,0x9f,0x7e,0xba,0x33,0xea,0x3a,0xcf, +0x25,0xd6,0x52,0x20,0x9a,0x13,0x9a,0xf3,0x03,0xa9,0x29,0x97,0x1c,0xe7,0xba,0xd6, +0x15,0x45,0xba,0xc4,0x5a,0xe4,0x25,0xad,0x19,0xf8,0x20,0x74,0x75,0x73,0xb6,0x13, +0x17,0xf6,0xcb,0x4f,0x14,0xb2,0x22,0x07,0x71,0x10,0x15,0x95,0xb9,0xa6,0x07,0x4d, +0xb8,0x76,0xe2,0xa4,0xae,0x6b,0xa8,0x48,0x81,0xcb,0x82,0x68,0x05,0x05,0xa5,0x0c, +0x7c,0x54,0x8a,0x33,0x04,0xef,0x43,0x64,0xe2,0xf3,0x7c,0x90,0xfa,0x8f,0xfb,0x95, +0x5b,0x30,0x1c,0xaf,0x0b,0x18,0xd1,0x0a,0x66,0x10,0x79,0x1e,0x84,0x3b,0xff,0x20, +0xc7,0xeb,0x6e,0x78,0xfc,0x1b,0x1e,0xbf,0xe1,0x1d,0xa7,0x61,0x19,0x1b,0xb1,0x28, +0x06,0x56,0x18,0xcb,0x46,0x36,0x08,0x42,0x17,0x02,0x8f,0xd6,0xda,0x32,0xab,0x69, +0x65,0x06,0x14,0x8b,0x57,0xe2,0x72,0x25,0x76,0x83,0x54,0x0d,0x2c,0x09,0x71,0x96, +0x3c,0x5c,0xab,0x21,0x62,0x3e,0x48,0x37,0x69,0x8b,0x71,0xd3,0x77,0x61,0x03,0x9e, +0xb4,0x86,0x38,0x22,0xd7,0xe1,0xaf,0x13,0x03,0xe1,0x72,0xfd,0x03,0x00,0x00,0xff, +0xff,0x03,0x00,0x8d,0xb1,0x06,0x76,0xa6,0x7a,0xc3,0xbb,0x13,0x3d,0x45,0xe2,0x2b, +0x3b,0xd0,0x88,0xc7,0x58,0x7b,0xbd,0x30,0x9d,0x01,0x44,0x78,0xda,0xca,0x48,0xcd, +0xc9,0xc9,0xcf,0x80,0x13,0x5c,0x00,0x00,0x00,0x00,0xff,0xff,0x03,0x00,0x37,0xf7, +0x06,0x47 +}; + +static void verify7(struct archive *a, struct archive_entry *ae) +{ + (void)a; /* UNUSED */ + assert(archive_entry_filetype(ae) == AE_IFREG); + assertEqualInt(archive_entry_mode(ae) & 0777, 0644); + assertEqualInt(archive_entry_uid(ae), UID); + assertEqualInt(archive_entry_gid(ae), GID); + assertEqualString(archive_entry_uname(ae), UNAME); + assertEqualString(archive_entry_gname(ae), GNAME); + assertEqualString(archive_entry_pathname(ae), "dir1/f1"); + assert(archive_entry_hardlink(ae) == NULL); + assert(archive_entry_symlink(ae) == NULL); + assertEqualInt(archive_entry_mtime(ae), 86401); +} + +/* Verify that a file records with bzip2 compression +#How to make +echo "hellohellohello" > f1 +chown $UNAME:$GNAME f1 +chmod 0644 f1 +env TZ=utc touch -afm -t 197001020000.01 f1 +xar --compression bzip2 -cf archive8.xar f1 +od -t x1 archive8.xar | sed -E -e 's/^0[0-9]+//;s/^ //;s/( )([0-9a-f]{2})/0x\2,/g;$ D' > archive8.xar.txt +*/ + +static unsigned char archive8[] = { +0x78,0x61,0x72,0x21,0x00,0x1c,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xb1, +0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x42,0x00,0x00,0x00,0x01,0x78,0xda,0x7c,0x53, +0xcb,0x6e,0xdc,0x20,0x14,0xdd,0xe7,0x2b,0x90,0xf7,0x0e,0x60,0xe3,0x07,0x23,0x86, +0xa8,0x9b,0xa8,0xfb,0x4e,0x37,0xdd,0x61,0x1e,0x63,0x14,0xbf,0x64,0xe3,0x68,0x92, +0xaf,0x2f,0x60,0x3b,0xa3,0x34,0x6d,0x25,0x4b,0x3e,0x1c,0x0e,0xe7,0x5e,0xee,0xe5, +0xb2,0xa7,0x5b,0xdf,0x81,0x57,0x3d,0x2f,0x76,0x1c,0xce,0x09,0x7e,0x44,0x09,0xd0, +0x83,0x1c,0x95,0x1d,0xae,0xe7,0xe4,0xe7,0xe5,0x39,0xad,0x93,0x27,0xfe,0xc0,0x6e, +0x62,0xe6,0x0f,0x80,0xb9,0x51,0xfa,0x1f,0x60,0x72,0xd6,0xc2,0xf9,0x13,0xa9,0xb3, +0xbd,0xe6,0x19,0x42,0x34,0xc5,0x59,0x8a,0xc8,0x05,0xd1,0x13,0xc6,0x27,0x9c,0x33, +0xf8,0x59,0x12,0x0f,0xb5,0x5a,0xbe,0x2c,0x6b,0x0f,0x16,0xf7,0xd6,0xe9,0x73,0xb2, +0xb4,0x02,0x27,0x61,0x07,0xb0,0xd1,0x98,0x45,0x3b,0x8e,0x18,0xdc,0x51,0x64,0x17, +0xfb,0x1e,0xcc,0x19,0x8c,0x20,0x58,0xc0,0xc3,0x23,0xae,0x8c,0xed,0x34,0xb0,0xca, +0xa7,0xbd,0xdb,0x28,0xe1,0x44,0x44,0x80,0x75,0x7a,0xb8,0xba,0x96,0x13,0xc2,0xe0, +0x0e,0x37,0x7e,0xf7,0xcf,0x3e,0x87,0xda,0x63,0xe1,0xf2,0x1e,0xcb,0x73,0x47,0x21, +0x8e,0x84,0xc5,0x34,0x75,0x56,0xc6,0x5b,0xc1,0x5b,0xda,0xbc,0xdb,0x29,0x4b,0xe0, +0xae,0x15,0xb3,0x6c,0xed,0xab,0x56,0xe9,0x9f,0xb7,0xfc,0xf1,0xfd,0x9b,0x4f,0xcf, +0xe4,0xa4,0x28,0x4a,0x94,0xcb,0x3a,0xcf,0x9b,0x26,0x93,0xaa,0x92,0xba,0x29,0xa8, +0x2a,0x89,0x29,0xa8,0x50,0x22,0x97,0x45,0xa1,0x71,0xe5,0xeb,0xf6,0xc5,0xe8,0x48, +0xe6,0xe6,0x66,0x21,0xdd,0x3f,0x23,0x14,0xaa,0x22,0x8d,0x6c,0x64,0x45,0x55,0x6e, +0x68,0x63,0x88,0x30,0xa6,0x36,0xa4,0xae,0x6b,0xa4,0x49,0x91,0x95,0x05,0x31,0x1a, +0x49,0x4a,0x19,0xfc,0xea,0xb4,0x55,0x0f,0x7e,0x94,0x8f,0xc9,0xbf,0xf7,0x15,0xd5, +0xbf,0x7c,0x0b,0x8e,0x86,0x02,0xd6,0x47,0x88,0x69,0x85,0x52,0x84,0x53,0x94,0x5d, +0x10,0x3a,0x85,0x0f,0x7b,0x59,0x7f,0x97,0x89,0xff,0xc8,0xc4,0x5d,0x76,0x9d,0xc7, +0x75,0xe2,0x72,0xd5,0x0c,0x6e,0x70,0x63,0xad,0xe2,0x18,0x21,0xec,0x49,0x8f,0x22, +0xb5,0x2e,0x7a,0xde,0x74,0x11,0x6d,0xdc,0x87,0x6c,0x3d,0x64,0xfd,0xa8,0x34,0x47, +0x65,0x78,0x02,0x11,0x46,0xd2,0xbd,0x4d,0x1a,0x74,0x76,0x78,0x39,0x27,0xe3,0x6c, +0xaf,0x76,0x10,0x5d,0xc2,0x5b,0x31,0xab,0xc0,0x31,0x18,0xb6,0x37,0xe1,0x20,0x7c, +0x5e,0xc6,0xfb,0x45,0x10,0x1f,0x5f,0x78,0x6f,0x61,0x0a,0x60,0x1c,0x03,0x06,0xe3, +0x50,0xfc,0x06,0x00,0x00,0xff,0xff,0x03,0x00,0x19,0xcf,0xf5,0xc0,0xf9,0x65,0xe8, +0x78,0xc3,0xfa,0x5f,0x0a,0xf6,0x09,0x17,0xd8,0xb0,0x54,0xb9,0x02,0x8d,0x91,0x31, +0x9c,0x42,0x5a,0x68,0x39,0x31,0x41,0x59,0x26,0x53,0x59,0xc1,0x52,0x36,0xf7,0x00, +0x00,0x03,0x41,0x00,0x00,0x10,0x02,0x44,0xa0,0x00,0x21,0xb4,0x01,0x9a,0x0d,0x46, +0xa5,0x32,0x38,0xbb,0x92,0x29,0xc2,0x84,0x86,0x0a,0x91,0xb7,0xb8 +}; + +/* Verify that a file records with no compression +#How to make +echo "hellohellohello" > f1 +chown $UNAME:$GNAME f1 +chmod 0644 f1 +env TZ=utc touch -afm -t 197001020000.01 f1 +xar --compression none -cf archive9.xar f1 +od -t x1 archive9.xar | sed -E -e 's/^0[0-9]+//;s/^ //;s/( )([0-9a-f]{2})/0x\2,/g;$ D' > archive9.xar.txt +*/ + +static unsigned char archive9[] = { +0x78,0x61,0x72,0x21,0x00,0x1c,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x98, +0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x47,0x00,0x00,0x00,0x01,0x78,0xda,0xa4,0x53, +0x4d,0x6f,0xe3,0x20,0x14,0xbc,0xf7,0x57,0x20,0xee,0x5e,0xc0,0x25,0x89,0x1d,0x11, +0xaa,0x5e,0xaa,0xbd,0x6f,0xf6,0xb2,0x37,0x02,0x8f,0x18,0xc5,0x1f,0x11,0xc6,0x55, +0xba,0xbf,0x7e,0x01,0xdb,0xad,0xba,0x55,0x7b,0xa9,0x64,0xc9,0xe3,0x61,0xde,0x78, +0x78,0xf0,0xc4,0xc3,0xad,0x6b,0xd1,0x33,0xf8,0xd1,0x0d,0xfd,0x01,0xb3,0x1f,0x14, +0x23,0xe8,0xf5,0x60,0x5c,0x7f,0x3e,0xe0,0xdf,0xc7,0xa7,0xa2,0xc2,0x0f,0xf2,0x4e, +0xdc,0x94,0x97,0x77,0x48,0x84,0x41,0xc7,0x17,0x12,0xda,0x83,0x0a,0xb1,0xa2,0x08, +0xae,0x03,0x59,0x52,0x5a,0x17,0xac,0x2c,0x28,0x3f,0xd2,0x7a,0xcf,0xaa,0x3d,0xaf, +0x05,0x79,0x2f,0xc9,0x45,0x0d,0xe8,0xcb,0x38,0x75,0x68,0x0c,0x2f,0x2d,0x1c,0xf0, +0xd8,0x28,0x86,0xd3,0x0a,0x12,0x83,0xb5,0x23,0x04,0x49,0x05,0x59,0x50,0x66,0x47, +0xf7,0x37,0x99,0x0b,0x92,0x41,0xb2,0x20,0xab,0x47,0xfe,0xb2,0xae,0x05,0xe4,0x4c, +0x8c,0xbd,0xd8,0x18,0x15,0x54,0x46,0x48,0xb4,0xd0,0x9f,0x43,0x23,0xd9,0x56,0x90, +0x05,0xce,0xfc,0xba,0xb9,0x35,0x84,0xba,0x5e,0x5b,0xa7,0x73,0x52,0x32,0xe8,0x00, +0xa1,0x18,0x43,0x4c,0xde,0x61,0xb2,0x14,0x2c,0x81,0xca,0xf7,0xd9,0x96,0x70,0xc9, +0x7e,0x0d,0x17,0x39,0xe5,0x75,0xe3,0x9e,0xc1,0x14,0xff,0x6f,0xf5,0xd7,0xcf,0xc7, +0x98,0x71,0x63,0x76,0xfc,0xa4,0x4f,0x7a,0x57,0x9b,0x7b,0x5b,0x9f,0x2c,0x57,0xd6, +0x56,0x96,0x57,0x55,0x45,0x81,0x6f,0xca,0xed,0x86,0x5b,0xa0,0xba,0x8e,0xcd,0xfb, +0x60,0xb4,0xa6,0xbf,0x05,0xaf,0x62,0xca,0xef,0xff,0xe1,0xa3,0xd3,0xdc,0x42,0xf2, +0xda,0x43,0xa1,0x3f,0x39,0xdc,0xed,0x9f,0x78,0x0e,0xeb,0xa9,0x22,0xd1,0x65,0xc8, +0xea,0x1d,0x2d,0x28,0x2b,0x68,0x79,0xa4,0x74,0x9f,0x1e,0x16,0x65,0xdd,0x9b,0x4c, +0x7d,0x21,0x53,0x6f,0xb2,0xb3,0x1f,0xa6,0xab,0xd4,0x13,0x08,0x32,0xc3,0x99,0x75, +0x46,0x32,0x4a,0x59,0x24,0x23,0xca,0xd4,0x34,0x82,0x9f,0x75,0x19,0xcd,0xdc,0xab, +0x6c,0x5a,0x65,0xdd,0x60,0x40,0xd2,0x2d,0xe7,0x31,0x4c,0x82,0x99,0x0c,0x2f,0x57, +0x40,0xad,0xeb,0x2f,0x07,0x3c,0x78,0x77,0x76,0xbd,0x6a,0xb1,0x6c,0x94,0x37,0x89, +0x13,0x24,0x2d,0xcf,0xc2,0x5e,0xc5,0x5c,0x36,0xfa,0x65,0x90,0x6f,0x60,0xba,0x74, +0x69,0x14,0x48,0x9e,0x05,0x41,0xf2,0x64,0xfc,0x03,0x00,0x00,0xff,0xff,0x03,0x00, +0xee,0x8e,0xf8,0x75,0xa1,0xaf,0x74,0x71,0x3f,0x40,0x08,0xab,0x13,0x7d,0xc0,0x82, +0x3a,0x56,0xeb,0x4e,0x35,0xf1,0x35,0xb7,0x68,0x65,0x6c,0x6c,0x6f,0x68,0x65,0x6c, +0x6c,0x6f,0x68,0x65,0x6c,0x6c,0x6f,0x0a +}; + +/* Verify that a file records with md5 hashing algorithm +#How to make +echo "hellohellohello" > f1 +chown $UNAME:$GNAME f1 +chmod 0644 f1 +env TZ=utc touch -afm -t 197001020000.01 f1 +xar --toc-cksum md5 -cf archive10.xar f1 +od -t x1 archive10.xar | sed -E -e 's/^0[0-9]+//;s/^ //;s/( )([0-9a-f]{2})/0x\2,/g;$ D' > archive10.xar.txt +*/ + +static unsigned char archive10[] = { +0x78,0x61,0x72,0x21,0x00,0x1c,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xaf, +0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x40,0x00,0x00,0x00,0x02,0x78,0xda,0x7c,0x53, +0x4d,0x6f,0xdc,0x20,0x10,0xbd,0xe7,0x57,0x20,0xee,0x0e,0x60,0xb3,0xb6,0x59,0xb1, +0x44,0xbd,0x44,0xbd,0x77,0x7b,0xe9,0x8d,0xe5,0xc3,0x8b,0xe2,0x2f,0x61,0x1c,0x6d, +0xf2,0xeb,0x8b,0xb1,0x9d,0xb4,0x4d,0x52,0xc9,0x92,0x1f,0x8f,0xc7,0x9b,0x61,0x86, +0xe1,0x0f,0xb7,0xae,0x05,0xcf,0xc6,0x4f,0x6e,0xe8,0x4f,0x90,0xdc,0x63,0x08,0x4c, +0xaf,0x06,0xed,0xfa,0xe6,0x04,0x7f,0x9e,0x1f,0xb3,0x1a,0x3e,0x88,0x3b,0x7e,0x93, +0x5e,0xdc,0x01,0x1e,0x06,0x15,0x7f,0x80,0x2b,0x6f,0x64,0x88,0x27,0xb2,0xe0,0x3a, +0x23,0x72,0x8c,0x59,0x46,0xf2,0x0c,0xd3,0x33,0x66,0xc7,0x02,0x1f,0x69,0xcd,0xd1, +0xdf,0x92,0x74,0xe8,0x6a,0xd4,0xd3,0x34,0x77,0x60,0x0a,0x2f,0xad,0x39,0xc1,0x4e, +0x1f,0xe0,0xb2,0x01,0xf8,0x60,0xed,0x64,0x82,0xc0,0x1c,0x6d,0x28,0xb1,0x93,0x7b, +0x35,0x82,0x94,0x1c,0x25,0xb0,0x38,0xa0,0xdd,0x22,0xad,0xac,0x6b,0x0d,0x70,0x3a, +0x66,0xbd,0xd9,0x68,0x19,0x64,0x42,0x80,0xb7,0xa6,0x6f,0xc2,0x55,0xe4,0x05,0x47, +0x1b,0x5c,0xf9,0xcd,0x7f,0x71,0xfd,0x23,0xd4,0x27,0xb1,0x22,0xb7,0xd7,0x61,0xcf, +0x57,0x8e,0x63,0xeb,0x54,0xba,0x14,0xba,0x65,0xcd,0xab,0x1b,0x21,0xda,0xa4,0xd2, +0xab,0xab,0x7b,0x36,0x3a,0xfb,0xf7,0x8e,0x3f,0xbe,0x7f,0x8b,0xd9,0xd9,0xba,0x28, +0x74,0x6e,0xb5,0x22,0xac,0xa0,0xac,0x90,0x17,0x5a,0x33,0xa9,0x65,0x5e,0xd8,0xda, +0x56,0x8c,0xd8,0x32,0xb7,0xaa,0x28,0x59,0xac,0xda,0x07,0xa3,0x3d,0x97,0x5b,0xf0, +0x52,0x85,0x2f,0x23,0x1c,0x74,0x45,0x2f,0xea,0xa2,0x2a,0xa6,0x0b,0xcb,0x2e,0x96, +0x4a,0x1b,0xbd,0x69,0x5d,0xd7,0xd8,0xd0,0x43,0x5e,0x1e,0xa8,0x35,0x58,0x31,0xc6, +0xd1,0x47,0xa7,0xb5,0x78,0xe8,0xad,0x7a,0x5c,0x7d,0xd1,0xd5,0xea,0x57,0xec,0xc0, +0xde,0x4e,0xc0,0xbb,0x04,0x09,0xab,0x70,0x86,0x49,0x86,0xf3,0x33,0xc6,0xc7,0xe5, +0x23,0x51,0xd6,0xbd,0xcb,0xe4,0x7f,0x64,0xf2,0x5d,0xd6,0xf8,0x61,0x1e,0x85,0x9a, +0x0d,0x47,0x2b,0x5c,0x59,0xa7,0x05,0xc1,0x98,0x44,0x32,0xa2,0x44,0xcd,0x93,0xf1, +0xab,0x2e,0xa1,0x95,0x7b,0x93,0xcd,0xbb,0xac,0x1b,0xb4,0x11,0xb8,0xa4,0x34,0x26, +0xb3,0xc0,0x44,0x86,0x97,0xd1,0x80,0xd6,0xf5,0x4f,0x27,0x38,0x78,0xd7,0xb8,0x5e, +0xb6,0x50,0x5c,0xa5,0xd7,0x0b,0xc7,0xd1,0xb2,0xbd,0x0a,0x7b,0x19,0xf3,0xb2,0xd1, +0x2f,0x81,0xf4,0xf6,0x96,0xe7,0xb6,0xcc,0x00,0x4a,0x43,0xc0,0x51,0x1a,0x89,0xdf, +0x00,0x00,0x00,0xff,0xff,0x03,0x00,0x27,0xf8,0xf5,0x28,0x87,0x01,0xb1,0xb7,0x18, +0xe8,0x34,0x20,0x06,0x5c,0x66,0x9a,0x43,0x26,0xe7,0x94,0x78,0xda,0xca,0x48,0xcd, +0xc9,0xc9,0xcf,0x80,0x13,0x5c,0x00,0x00,0x00,0x00,0xff,0xff,0x03,0x00,0x37,0xf7, +0x06,0x47 +}; + +/* Verify that a file records with no hashing algorithm +#How to make +echo "hellohellohello" > f1 +chown $UNAME:$GNAME f1 +chmod 0644 f1 +env TZ=utc touch -afm -t 197001020000.01 f1 +xar --toc-cksum none -cf archive11.xar f1 +od -t x1 archive11.xar | sed -E -e 's/^0[0-9]+//;s/^ //;s/( )([0-9a-f]{2})/0x\2,/g;$ D' > archive11.xar.txt +*/ + +static unsigned char archive11[] = { +0x78,0x61,0x72,0x21,0x00,0x1c,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x98, +0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xef,0x00,0x00,0x00,0x00,0x78,0xda,0x7c,0x52, +0xcb,0x6e,0xeb,0x20,0x14,0xdc,0xf7,0x2b,0x10,0x7b,0x17,0xb0,0x89,0x63,0x22,0x42, +0x75,0x37,0x55,0xf7,0xcd,0xdd,0x74,0x47,0x78,0x38,0xa8,0x7e,0xc9,0xc6,0x55,0xda, +0xaf,0xbf,0x3c,0xe2,0x56,0x55,0xd5,0x2b,0x21,0x79,0x3c,0xcc,0x39,0x67,0x74,0x18, +0xfe,0x70,0xed,0x3b,0xf0,0x66,0xe6,0xc5,0x8d,0xc3,0x11,0x92,0x7b,0x0c,0x81,0x19, +0xd4,0xa8,0xdd,0xd0,0x1e,0xe1,0xdf,0xd3,0x63,0xd1,0xc0,0x07,0x71,0xc7,0xaf,0x72, +0x16,0x77,0x80,0xfb,0x51,0x85,0x0f,0xe0,0x6a,0x36,0xd2,0x87,0x8a,0xc2,0xbb,0xde, +0x88,0x12,0x63,0x56,0x90,0xb2,0xc0,0xf4,0x44,0xf0,0x81,0x54,0x07,0x5a,0x73,0xf4, +0x5d,0x12,0x8b,0xac,0xeb,0x0c,0x70,0x3a,0x4c,0x81,0xf1,0x1f,0x70,0x2d,0xbd,0x4c, +0x08,0xf0,0xce,0x0c,0xad,0xbf,0x88,0xb2,0xe2,0xe8,0x06,0x33,0x3f,0x5a,0xbb,0x18, +0x2f,0x30,0x47,0x37,0x94,0xe9,0xc5,0x7d,0x18,0x41,0xc2,0x94,0x04,0x32,0xb7,0xd9, +0x06,0x8b,0x7f,0xef,0xcc,0x11,0xca,0x69,0xea,0x9c,0x4a,0x1e,0xd0,0xb5,0x68,0x3f, +0xdc,0x04,0xd1,0x4d,0x2a,0x67,0x75,0x71,0x6f,0x46,0x17,0xea,0x62,0xd4,0xeb,0xb2, +0xf6,0x5b,0xcd,0xf3,0xd3,0x9f,0x60,0xce,0x36,0x55,0xa5,0x4b,0xab,0x15,0x61,0x15, +0x65,0x95,0x3c,0xd3,0x86,0x49,0x2d,0xcb,0xca,0x36,0x76,0xcf,0x88,0xad,0x4b,0xab, +0xaa,0x9a,0x35,0x1c,0xfd,0x68,0xb4,0x79,0xb9,0xfa,0x59,0x2a,0xff,0xeb,0x84,0x9d, +0xde,0xd3,0xb3,0x3a,0xab,0x3d,0xd3,0x95,0x65,0x67,0x4b,0xa5,0x0d,0xbd,0x69,0xd3, +0x34,0xd8,0xd0,0x5d,0x59,0xef,0xa8,0x35,0x58,0x31,0xc6,0xd1,0xcf,0x4e,0x79,0x77, +0xe8,0x73,0x79,0x5c,0xfd,0xf2,0x08,0xe4,0x25,0xbc,0xc2,0xb6,0x7d,0xc0,0xfb,0x04, +0x09,0xdb,0xe3,0x02,0x93,0x02,0x97,0x27,0x8c,0x0f,0xf1,0x44,0x59,0xff,0x25,0x93, +0xff,0x91,0xc9,0x2f,0x59,0x3b,0x8f,0xeb,0x24,0xd4,0x6a,0x38,0xca,0x30,0xb3,0x4e, +0x0b,0x82,0x31,0x09,0x64,0x40,0x89,0x5a,0x17,0x33,0x67,0x5d,0x42,0x99,0xfb,0x94, +0xad,0x9b,0xac,0x1f,0xb5,0x11,0xb8,0xa6,0x34,0x98,0x89,0x30,0x91,0xfe,0x7d,0x32, +0xa0,0x73,0xc3,0xeb,0x11,0x8e,0xb3,0x6b,0xdd,0x20,0x3b,0x28,0x2e,0x72,0xd6,0x91, +0xe3,0x28,0x5e,0x67,0xe1,0x20,0x83,0x2f,0x1b,0xfa,0x25,0x10,0xc3,0x86,0x62,0xda, +0x62,0x64,0x51,0xca,0x2c,0x47,0x29,0xc1,0xff,0x00,0x00,0x00,0xff,0xff,0x03,0x00, +0xf1,0x18,0xdc,0x71,0x78,0xda,0xca,0x48,0xcd,0xc9,0xc9,0xcf,0x80,0x13,0x5c,0x00, +0x00,0x00,0x00,0xff,0xff,0x03,0x00,0x37,0xf7,0x06,0x47 +}; + +/* Verify that a file which is missing timestamp information +has the corresponding timestamps unset. +#How to make e.g. + struct archive *a = archive_write_new(); + archive_write_set_format_xar(a); + archive_write_add_filter_none(a); + size_t used, buffsize = 1500; + char *buff = (char*) malloc(buffsize); + archive_write_open_memory(a, buff, buffsize, &used); + + struct archive_entry *ae = archive_entry_new(); + archive_entry_copy_pathname(ae, "file"); + archive_entry_set_size(ae, 8); + archive_write_header(a, ae); + archive_entry_free(ae); + archive_write_data(a, "12345678", 9); + archive_write_free(a); + + std::cout << std::string(buff, used); + free(buff); + +$./a.out > f12.xar +Verify toc has no mtime/atime sections +$ xar --dump-toc=- -f f12.xar +Dump contents +$ ./a.out | od -t x1 | sed -E -e 's/^0[0-9]+//;s/^ //;s/( )([0-9a-f]{2})/0x\2,/g;$ D' +*/ + +static unsigned char archive12[] = { +0x78,0x61,0x72,0x21,0x00,0x1c,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd1, +0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x56,0x00,0x00,0x00,0x01,0x78,0x9c,0x55,0x90, +0x41,0x8e,0xc2,0x30,0x0c,0x45,0xf7,0x9c,0x22,0xca,0xbe,0x38,0x2d,0x2c,0x10,0x72, +0xdb,0xdd,0x9c,0x00,0x0e,0x50,0xb5,0x6e,0x89,0x68,0x12,0xd4,0x84,0x11,0x70,0x7a, +0x62,0x17,0x46,0x9a,0x28,0x92,0xbf,0x5f,0xec,0xef,0xc8,0xd8,0x3e,0xdc,0xac,0x7e, +0x69,0x89,0x36,0xf8,0x5a,0x97,0x5b,0xa3,0x15,0xf9,0x3e,0x0c,0xd6,0x4f,0xb5,0x3e, +0x9f,0x7e,0x8a,0x83,0x6e,0x9b,0x0d,0x3e,0xba,0xa5,0xd9,0x28,0x4c,0xa1,0xcf,0x41, +0x61,0xbf,0x50,0x97,0x72,0x47,0x91,0xac,0xa3,0xa6,0x32,0xe5,0xa1,0x28,0x4d,0x61, +0xaa,0x53,0x65,0x8e,0xf9,0xee,0x77,0x08,0xff,0x4b,0xa4,0xe9,0x42,0xfd,0x35,0xde, +0x9d,0x8a,0xe9,0x39,0x53,0xad,0xe3,0xa5,0x2b,0x35,0xbf,0x28,0x0c,0xe3,0x18,0x29, +0x35,0x06,0xe1,0xa3,0x84,0x46,0xfb,0x62,0x73,0x04,0x11,0x6c,0x01,0x5f,0x0f,0xc9, +0x46,0x3b,0x93,0xb2,0x43,0xfe,0xf6,0xc7,0xc6,0x77,0x79,0x14,0x53,0x04,0x91,0x02, +0xd3,0xf3,0xf6,0x85,0x22,0x05,0x5a,0x1f,0x06,0xe2,0x79,0xab,0x10,0xe6,0x04,0xe5, +0x83,0xe0,0xfe,0xe0,0xdd,0x0e,0x5c,0xc6,0x41,0xf2,0x69,0xcd,0xa7,0x35,0x47,0x60, +0x63,0xde,0x0c,0xc8,0x6a,0x10,0x64,0x51,0x6f,0x2a,0x6b,0x63,0x9a,0x01,0x79,0x57, +0x93,0xd4,0x55,0xd4,0x06,0x1c,0x76,0x99,0x10,0x31,0x87,0x52,0x2b,0x16,0xff,0x5b, +0x36,0x78,0x9c,0x55,0x90,0x41,0x8e,0xc2,0x30,0x0c,0x45,0xf7,0x9c,0x22,0xca,0xbe, +0x38,0x2d,0x2c,0x10,0x72 +}; + +static void verify12(struct archive *a, struct archive_entry *ae) +{ + (void)a; /* UNUSED */ + assertEqualInt(archive_entry_mtime_is_set(ae), 0); + assertEqualInt(archive_entry_atime_is_set(ae), 0); + assertEqualInt(archive_entry_mtime(ae), 0); + assertEqualInt(archive_entry_atime(ae), 0); +} + + +/* +#How to make +echo "onetwothree" > f1 +echo "fourfivesize" > f2 +xar -cf archive13.xar f1 f2 +od -t x1 archive13.xar | sed -E -e 's/^0[0-9]+//' | sed -E -e 's/^ //' | sed -E -e 's/( )([0-9a-f]{2})/0x\2,/g;$ D' +*/ + +static unsigned char archive13[] = { +0x78,0x61,0x72,0x21,0x00,0x1c,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x31, +0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xaa,0x00,0x00,0x00,0x01,0x78,0xda,0xcc,0x95, +0xcb,0x8e,0x9b,0x30,0x14,0x86,0xf7,0x79,0x0a,0xc4,0x9e,0xe2,0x0b,0xbe,0x10,0x39, +0xcc,0xae,0x4f,0x30,0xdd,0x74,0x67,0xec,0x43,0x82,0x86,0x4b,0x04,0x24,0xcd,0xcc, +0xd3,0xd7,0x36,0x30,0x69,0x34,0xd3,0x51,0xda,0x4a,0xa3,0x8a,0x05,0xbf,0x8f,0x7f, +0x9f,0xe3,0x63,0x3e,0x64,0xf5,0x70,0x69,0x9b,0xe8,0x0c,0xc3,0x58,0xf7,0xdd,0x2e, +0xc6,0x5f,0x50,0x1c,0x41,0x67,0x7a,0x5b,0x77,0xfb,0x5d,0xfc,0xed,0xf1,0x6b,0x22, +0xe3,0x87,0x62,0xa3,0x2e,0x7a,0x28,0x36,0x91,0x9a,0x7a,0xe3,0x5e,0x91,0x32,0x03, +0xe8,0xc9,0xad,0x48,0xa6,0xba,0x85,0x82,0x20,0x2c,0x13,0x44,0x12,0xc2,0x1f,0x71, +0xbe,0xc5,0x68,0x4b,0xf3,0xef,0x2a,0xbd,0xf5,0x84,0x55,0x07,0x30,0x4f,0xe3,0xa9, +0x8d,0xc6,0xe9,0xb9,0x81,0x5d,0x3c,0x1e,0x34,0x8e,0xfd,0x4c,0xa4,0xfa,0xaa,0x1a, +0x61,0x2a,0x90,0x4a,0x17,0x15,0xa2,0x63,0xfd,0xe2,0xb3,0xab,0x34,0x08,0x9f,0x22, +0x5d,0x73,0x84,0x51,0x55,0x37,0x10,0xd5,0x76,0x17,0x93,0x25,0x8d,0xd5,0x93,0x0e, +0x2a,0x52,0x0d,0x74,0xfb,0xe9,0x10,0x56,0x2f,0x72,0x8e,0x2f,0xf9,0xb3,0xdb,0x52, +0x4b,0x2d,0x4c,0xae,0xb5,0x5c,0x6c,0x3d,0x89,0x75,0xc3,0xfa,0x78,0x6c,0x6a,0x13, +0xba,0x4a,0x2f,0xc9,0xfe,0xa5,0x3e,0xc6,0xe9,0x62,0xd5,0x83,0x39,0xd4,0x67,0xb0, +0xc9,0xfb,0x4d,0x66,0x92,0x96,0x58,0x70,0x4e,0x09,0xa3,0x02,0x73,0x28,0x05,0xa9, +0x20,0xe7,0xb9,0x34,0x98,0x94,0x0c,0x33,0x8c,0xa4,0xd5,0x22,0xd3,0x2a,0x7d,0x93, +0x68,0xdd,0xcb,0x65,0x1a,0xb4,0x99,0x7e,0x5b,0x81,0xcb,0x9c,0xba,0x22,0x3a,0x93, +0x40,0xb8,0x70,0x0f,0xd7,0x39,0x42,0x34,0x77,0xe9,0x89,0x28,0x2d,0xe7,0x6e,0x20, +0xb4,0xc1,0x2a,0x7d,0x9b,0x69,0x3e,0xbc,0xf4,0xf5,0xf4,0x7c,0x31,0xf2,0x0b,0x15, +0x8c,0x0b,0x21,0x08,0x47,0xd9,0xd2,0xae,0xd2,0xa6,0x59,0xfb,0x36,0x06,0xc6,0xb1, +0x38,0x8d,0x30,0x6c,0xb7,0xc3,0x8f,0x64,0xb3,0x1f,0xfa,0xd3,0xd1,0xc9,0x24,0xd9, +0xf4,0xd3,0x21,0x44,0x9d,0x74,0x7d,0xcd,0xc6,0xb9,0xd2,0xba,0x5e,0x99,0x77,0x00, +0x42,0x72,0x8b,0x99,0x07,0x68,0x05,0x27,0x52,0xed,0x07,0xb6,0xf6,0x6a,0xd3,0x1f, +0xd8,0xf4,0xd5,0xb6,0xaf,0x6d,0x81,0x11,0x72,0x04,0x78,0x15,0x42,0x7e,0xff,0x85, +0xee,0x26,0x78,0x52,0x69,0xd0,0x73,0xf4,0xd5,0x78,0x5a,0x8d,0x6d,0x6f,0xa1,0x40, +0x3c,0xcb,0x5c,0x61,0x2f,0x67,0xec,0xe0,0x5c,0x1b,0xe8,0x7a,0x57,0x9a,0x51,0x77, +0x8e,0xeb,0x30,0x4c,0xd6,0x9d,0xf7,0xe5,0x88,0xe5,0xc2,0xc3,0x38,0x0f,0xc3,0xcc, +0xf4,0x7c,0x84,0xc2,0x33,0xac,0xd2,0x20,0x43,0xb0,0xd3,0x6e,0x9b,0x95,0xe3,0x30, +0x88,0xc0,0xbc,0xb7,0xdc,0xf2,0x8e,0xff,0x98,0x77,0xf2,0xc9,0xbc,0x3b,0x98,0x31, +0x94,0x3c,0x67,0x8e,0xfb,0x8c,0x49,0xc0,0xd2,0x20,0xcc,0x40,0x0b,0x69,0x08,0x35, +0xbc,0x92,0xc2,0x7d,0x25,0x66,0xff,0x9e,0x77,0x60,0x19,0xa6,0xd6,0xd2,0x4c,0xd3, +0x8a,0x72,0x6b,0x44,0x25,0x01,0xa8,0x75,0xbf,0x81,0x81,0x32,0xd3,0xbc,0xd2,0xa2, +0xc4,0xc4,0xfe,0x13,0xef,0xf4,0xd3,0x78,0x47,0xf7,0xf1,0x8e,0xee,0xe3,0x1d,0xfd, +0x27,0xbc,0xe3,0xfc,0x5e,0xde,0xf1,0x3b,0xbc,0x3b,0x97,0xbf,0x6e,0x54,0x1a,0x2e, +0x9f,0x9f,0x00,0x00,0x00,0xff,0xff,0x03,0x00,0xe5,0xbe,0xed,0xcc,0x2a,0x10,0x73, +0x9e,0x84,0x13,0x2e,0x27,0xe1,0x8d,0x6f,0xf8,0x9e,0xae,0xd0,0x0a,0x8f,0x2a,0xca, +0xf7,0x78,0xda,0xcb,0xcf,0x4b,0x2d,0x29,0xcf,0x2f,0xc9,0x28,0x4a,0x4d,0xe5,0x02, +0x00,0x21,0x4c,0x04,0xbf,0x78,0xda,0x4b,0xcb,0x2f,0x2d,0x4a,0xcb,0x2c,0x4b,0x2d, +0xce,0xac,0xe0,0x02,0x00,0x20,0xfa,0x04,0xc5 +}; + +enum enc { + GZIP, + BZIP2 +}; + +static void verify(unsigned char *d, size_t s, + void (*f1)(struct archive *, struct archive_entry *), + void (*f2)(struct archive *, struct archive_entry *), + enum enc etype) +{ + struct archive_entry *ae; + struct archive *a; + unsigned char *buff; + int r; + + assert((a = archive_read_new()) != NULL); + switch (etype) { + case BZIP2: + /* This is only check whether bzip is supported or not. + * This filter won't be used this test. */ + if (ARCHIVE_OK != archive_read_support_filter_bzip2(a)) { + skipping("Unsupported bzip2"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + break; + case GZIP: + /* This gzip must be needed. archive_read_support_format_xar() + * will return a warning if gzip is unsupported. */ + break; + } + assertA(0 == archive_read_support_filter_all(a)); + r = archive_read_support_format_xar(a); + if (r == ARCHIVE_WARN) { + skipping("xar reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + assert((buff = malloc(100000)) != NULL); + if (buff == NULL) + return; + memcpy(buff, d, s); + memset(buff + s, 0, 2048); + + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_memory(a, buff, s + 1024)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_XAR); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + /* Verify the only entry. */ + f1(a, ae); + if (f2) { + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_XAR); + /* Verify the only entry. */ + f2(a, ae); + assertEqualInt(2, archive_file_count(a)); + } else { + assertEqualInt(1, archive_file_count(a)); + } + /* End of archive. */ + assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + free(buff); +} + +static void verifyB(unsigned char *d, size_t s) { + struct archive* a; + struct archive_entry *entry = NULL; + size_t buf_size; + unsigned char *buf; + + assert((a = archive_read_new()) != NULL); + + if(ARCHIVE_OK != archive_read_support_filter_gzip(a)) { + skipping("Unsupported gzip"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + + if(ARCHIVE_OK != archive_read_support_filter_bzip2(a)) { + skipping("Unsupported bzip2"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + + if(ARCHIVE_OK != archive_read_support_format_xar(a)) { + skipping("Unsupported xar"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + + assertA(0 == archive_read_open_memory(a, d, s)); + + // f1, content "onetwothree\n", size 12 bytes + assertA(0 == archive_read_next_header(a, &entry)); + buf_size = (size_t) archive_entry_size(entry); + assertA(buf_size == 12); + buf = (unsigned char*) malloc(buf_size); + assertA(NULL != buf); + assertA(buf_size == (size_t) archive_read_data(a, buf, buf_size)); + free(buf); + + // f2, content "fourfivesix\n", size 12 bytes + assertA(0 == archive_read_next_header(a, &entry)); + buf_size = (size_t) archive_entry_size(entry); + assertA(buf_size == 12); + buf = (unsigned char*) malloc(buf_size); + assertA(NULL != buf); + assertA(buf_size == (size_t) archive_read_data(a, buf, buf_size)); + free(buf); + + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_xar) +{ + verify(archive1, sizeof(archive1), verify0, verify1, GZIP); + verify(archive2, sizeof(archive2), verify0, verify2, GZIP); + verify(archive3, sizeof(archive3), verify3, NULL, GZIP); + verify(archive4, sizeof(archive4), verify4, NULL, GZIP); + verify(archive5, sizeof(archive5), verify5, NULL, GZIP); + verify(archive6, sizeof(archive6), verify6, NULL, GZIP); + verify(archive7, sizeof(archive7), verify7, NULL, GZIP); + verify(archive8, sizeof(archive8), verify0, NULL, BZIP2); + verify(archive9, sizeof(archive9), verify0, NULL, GZIP); + verify(archive10, sizeof(archive10), verify0, NULL, GZIP); + verify(archive11, sizeof(archive11), verify0, NULL, GZIP); + verify(archive12, sizeof(archive12), verify12, NULL, GZIP); + verifyB(archive13, sizeof(archive13)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip.c new file mode 100644 index 0000000..04f7e98 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip.c @@ -0,0 +1,918 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2011 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_zip.c 189482 2009-03-07 03:30:35Z kientzle $"); + +#define __LIBARCHIVE_BUILD +#include + +static +int extract_one(struct archive* a, struct archive_entry* ae, uint32_t crc) +{ + la_ssize_t fsize, bytes_read; + uint8_t* buf; + int ret = 1; + uint32_t computed_crc; + + fsize = (la_ssize_t) archive_entry_size(ae); + buf = malloc(fsize); + if(buf == NULL) + return 1; + + bytes_read = archive_read_data(a, buf, fsize); + if(bytes_read != fsize) { + assertEqualInt(bytes_read, fsize); + goto fn_exit; + } + + computed_crc = crc32(0, buf, fsize); + assertEqualInt(computed_crc, crc); + ret = 0; + +fn_exit: + free(buf); + return ret; +} + +static +int extract_one_using_blocks(struct archive* a, int block_size, uint32_t crc) +{ + uint8_t* buf; + int ret = 1; + uint32_t computed_crc = 0; + la_ssize_t bytes_read; + + buf = malloc(block_size); + if(buf == NULL) + return 1; + + while(1) { + bytes_read = archive_read_data(a, buf, block_size); + if(bytes_read == ARCHIVE_RETRY) + continue; + else if(bytes_read == 0) + break; + else if(bytes_read < 0) { + /* If we're here, it means the decompressor has failed + * to properly decode test file. */ + assertA(0); + ret = 1; + goto fn_exit; + } else { + /* ok */ + } + + computed_crc = crc32(computed_crc, buf, bytes_read); + } + + assertEqualInt(computed_crc, crc); + ret = 0; + +fn_exit: + free(buf); + return ret; +} + +/* + * The reference file for this has been manually tweaked so that: + * * file2 has length-at-end but file1 does not + * * file2 has an invalid CRC + */ +static void +verify_basic(struct archive *a, int seek_checks) +{ + struct archive_entry *ae; + char *buff[128]; + const void *pv; + size_t s; + int64_t o; + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 1.0 (uncompressed)", archive_format_name(a)); + assertEqualString("dir/", archive_entry_pathname(ae)); + assertEqualInt(1179604249, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + if (seek_checks) + assertEqualInt(AE_IFDIR | 0755, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertEqualIntA(a, ARCHIVE_EOF, + archive_read_data_block(a, &pv, &s, &o)); + assertEqualInt((int)s, 0); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 2.0 (deflation)", archive_format_name(a)); + assertEqualString("file1", archive_entry_pathname(ae)); + assertEqualInt(1179604289, archive_entry_mtime(ae)); + if (seek_checks) + assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); + assertEqualInt(18, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + failure("archive_read_data() returns number of bytes read"); + if (archive_zlib_version() != NULL) { + assertEqualInt(18, archive_read_data(a, buff, 19)); + assertEqualMem(buff, "hello\nhello\nhello\n", 18); + } else { + assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, 19)); + assertEqualString(archive_error_string(a), + "Unsupported ZIP compression method (8: deflation)"); + assert(archive_errno(a) != 0); + } + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 2.0 (deflation)", archive_format_name(a)); + assertEqualString("file2", archive_entry_pathname(ae)); + assertEqualInt(1179605932, archive_entry_mtime(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + if (seek_checks) { + assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); + } + assert(archive_entry_size_is_set(ae)); + assertEqualInt(18, archive_entry_size(ae)); + if (archive_zlib_version() != NULL) { + failure("file2 has a bad CRC, so read should fail and not change buff"); + memset(buff, 'a', 19); + assertEqualInt(ARCHIVE_WARN, archive_read_data(a, buff, 19)); + assertEqualMem(buff, "aaaaaaaaaaaaaaaaaaa", 19); + } else { + assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, 19)); + assertEqualString(archive_error_string(a), + "Unsupported ZIP compression method (8: deflation)"); + assert(archive_errno(a) != 0); + } + assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 2.0 (deflation)", archive_format_name(a)); + /* Verify the number of files read. */ + failure("the archive file has three files"); + assertEqualInt(3, archive_file_count(a)); + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +static void +test_basic(void) +{ + const char *refname = "test_read_format_zip.zip"; + struct archive *a; + char *p; + size_t s; + + extract_reference_file(refname); + + /* Verify with seeking reader. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); + verify_basic(a, 1); + + /* Verify with streaming reader. */ + p = slurpfile(&s, "%s", refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 31)); + verify_basic(a, 0); + free(p); +} + +/* + * Read Info-ZIP New Unix Extra Field 0x7875 "ux". + * Currently stores Unix UID/GID up to 32 bits. + */ +static void +verify_info_zip_ux(struct archive *a, int seek_checks) +{ + struct archive_entry *ae; + char *buff[128]; + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("file1", archive_entry_pathname(ae)); + assertEqualInt(1300668680, archive_entry_mtime(ae)); + assertEqualInt(18, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + if (seek_checks) + assertEqualInt(AE_IFREG | 0644, archive_entry_mode(ae)); + failure("zip reader should read Info-ZIP New Unix Extra Field"); + assertEqualInt(1001, archive_entry_uid(ae)); + assertEqualInt(1001, archive_entry_gid(ae)); + if (archive_zlib_version() != NULL) { + failure("archive_read_data() returns number of bytes read"); + assertEqualInt(18, archive_read_data(a, buff, 19)); + assertEqualMem(buff, "hello\nhello\nhello\n", 18); + } else { + assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, 19)); + assertEqualString(archive_error_string(a), + "Unsupported ZIP compression method (8: deflation)"); + assert(archive_errno(a) != 0); + } + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify the number of files read. */ + failure("the archive file has just one file"); + assertEqualInt(1, archive_file_count(a)); + + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +static void +test_info_zip_ux(void) +{ + const char *refname = "test_read_format_zip_ux.zip"; + struct archive *a; + char *p; + size_t s; + + extract_reference_file(refname); + + /* Verify with seeking reader. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); + verify_info_zip_ux(a, 1); + + /* Verify with streaming reader. */ + p = slurpfile(&s, "%s", refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 108)); + verify_info_zip_ux(a, 0); + free(p); +} + +/* + * Verify that test_read_extract correctly works with + * Zip entries that use length-at-end. + */ +static void +verify_extract_length_at_end(struct archive *a, int seek_checks) +{ + struct archive_entry *ae; + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + assertEqualString("hello.txt", archive_entry_pathname(ae)); + if (seek_checks) { + assertEqualInt(AE_IFREG | 0644, archive_entry_mode(ae)); + assert(archive_entry_size_is_set(ae)); + assertEqualInt(6, archive_entry_size(ae)); + } else { + assert(!archive_entry_size_is_set(ae)); + assertEqualInt(0, archive_entry_size(ae)); + } + + if (archive_zlib_version() != NULL) { + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract(a, ae, 0)); + assertFileContents("hello\x0A", 6, "hello.txt"); + } else { + assertEqualIntA(a, ARCHIVE_FAILED, archive_read_extract(a, ae, 0)); + assertEqualString(archive_error_string(a), + "Unsupported ZIP compression method (8: deflation)"); + assert(archive_errno(a) != 0); + } + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); +} + +static void +test_extract_length_at_end(void) +{ + const char *refname = "test_read_format_zip_length_at_end.zip"; + char *p; + size_t s; + struct archive *a; + + extract_reference_file(refname); + + /* Verify extraction with seeking reader. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); + verify_extract_length_at_end(a, 1); + + /* Verify extraction with streaming reader. */ + p = slurpfile(&s, "%s", refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 108)); + verify_extract_length_at_end(a, 0); + free(p); +} + +static void +test_symlink(void) +{ + const char *refname = "test_read_format_zip_symlink.zip"; + char *p; + size_t s; + struct archive *a; + struct archive_entry *ae; + + extract_reference_file(refname); + p = slurpfile(&s, "%s", refname); + + /* Symlinks can only be extracted with the seeking reader. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, s, 1)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("file", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("symlink", archive_entry_pathname(ae)); + assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualString("file", archive_entry_symlink(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + + free(p); +} + +DEFINE_TEST(test_read_format_zip) +{ + test_basic(); + test_info_zip_ux(); + test_extract_length_at_end(); + test_symlink(); +} + +DEFINE_TEST(test_read_format_zip_ppmd_one_file) +{ + const char *refname = "test_read_format_zip_ppmd8.zipx"; + struct archive *a; + struct archive_entry *ae; + + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 6.3 (ppmd-1)", archive_format_name(a)); + assertEqualString("vimrc", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one(a, ae, 0xBA8E3BAA)); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_ppmd_one_file_blockread) +{ + const char *refname = "test_read_format_zip_ppmd8.zipx"; + struct archive *a; + struct archive_entry *ae; + + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 6.3 (ppmd-1)", archive_format_name(a)); + assertEqualString("vimrc", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one_using_blocks(a, 13, 0xBA8E3BAA)); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_ppmd_multi) +{ + const char *refname = "test_read_format_zip_ppmd8_multi.zipx"; + struct archive *a; + struct archive_entry *ae; + + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 6.3 (ppmd-1)", archive_format_name(a)); + assertEqualString("smartd.conf", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one(a, ae, 0x8DD7379E)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 6.3 (ppmd-1)", archive_format_name(a)); + assertEqualString("ts.conf", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one(a, ae, 0x7AE59B31)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 6.3 (ppmd-1)", archive_format_name(a)); + assertEqualString("vimrc", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one(a, ae, 0xBA8E3BAA)); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_ppmd_multi_blockread) +{ + const char *refname = "test_read_format_zip_ppmd8_multi.zipx"; + struct archive *a; + struct archive_entry *ae; + + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 6.3 (ppmd-1)", archive_format_name(a)); + assertEqualString("smartd.conf", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one_using_blocks(a, 12, 0x8DD7379E)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 6.3 (ppmd-1)", archive_format_name(a)); + assertEqualString("ts.conf", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one_using_blocks(a, 13, 0x7AE59B31)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 6.3 (ppmd-1)", archive_format_name(a)); + assertEqualString("vimrc", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one_using_blocks(a, 14, 0xBA8E3BAA)); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_lzma_one_file) +{ + const char *refname = "test_read_format_zip_lzma.zipx"; + struct archive *a; + struct archive_entry *ae; + + assert((a = archive_read_new()) != NULL); + if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) { + skipping("lzma reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + extract_reference_file(refname); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 6.3 (lzma)", archive_format_name(a)); + assertEqualString("vimrc", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one(a, ae, 0xBA8E3BAA)); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_lzma_one_file_blockread) +{ + const char *refname = "test_read_format_zip_lzma.zipx"; + struct archive *a; + struct archive_entry *ae; + + assert((a = archive_read_new()) != NULL); + if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) { + skipping("lzma reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + extract_reference_file(refname); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 6.3 (lzma)", archive_format_name(a)); + assertEqualString("vimrc", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one_using_blocks(a, 13, 0xBA8E3BAA)); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_lzma_multi) +{ + const char *refname = "test_read_format_zip_lzma_multi.zipx"; + struct archive *a; + struct archive_entry *ae; + + assert((a = archive_read_new()) != NULL); + if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) { + skipping("lzma reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + extract_reference_file(refname); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 6.3 (lzma)", archive_format_name(a)); + assertEqualString("smartd.conf", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one(a, ae, 0x8DD7379E)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 6.3 (lzma)", archive_format_name(a)); + assertEqualString("ts.conf", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one(a, ae, 0x7AE59B31)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 6.3 (lzma)", archive_format_name(a)); + assertEqualString("vimrc", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one(a, ae, 0xBA8E3BAA)); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_lzma_multi_blockread) +{ + const char *refname = "test_read_format_zip_lzma_multi.zipx"; + struct archive *a; + struct archive_entry *ae; + + assert((a = archive_read_new()) != NULL); + if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) { + skipping("lzma reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + extract_reference_file(refname); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 6.3 (lzma)", archive_format_name(a)); + assertEqualString("smartd.conf", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one_using_blocks(a, 12, 0x8DD7379E)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 6.3 (lzma)", archive_format_name(a)); + assertEqualString("ts.conf", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one_using_blocks(a, 13, 0x7AE59B31)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 6.3 (lzma)", archive_format_name(a)); + assertEqualString("vimrc", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one_using_blocks(a, 14, 0xBA8E3BAA)); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); +} + + +DEFINE_TEST(test_read_format_zip_bzip2_one_file) +{ + const char *refname = "test_read_format_zip_bzip2.zipx"; + struct archive *a; + struct archive_entry *ae; + + assert((a = archive_read_new()) != NULL); + if (ARCHIVE_OK != archive_read_support_filter_bzip2(a)) { + skipping("bzip2 is not fully supported on this platform"); + archive_read_close(a); + return; + } + extract_reference_file(refname); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 4.6 (bzip)", archive_format_name(a)); + assertEqualString("vimrc", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one(a, ae, 0xBA8E3BAA)); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_bzip2_one_file_blockread) +{ + const char *refname = "test_read_format_zip_bzip2.zipx"; + struct archive *a; + struct archive_entry *ae; + + assert((a = archive_read_new()) != NULL); + if (ARCHIVE_OK != archive_read_support_filter_bzip2(a)) { + skipping("bzip2 is not fully supported on this platform"); + archive_read_close(a); + return; + } + extract_reference_file(refname); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 4.6 (bzip)", archive_format_name(a)); + assertEqualString("vimrc", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one_using_blocks(a, 13, 0xBA8E3BAA)); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_bzip2_multi) +{ + const char *refname = "test_read_format_zip_bzip2_multi.zipx"; + struct archive *a; + struct archive_entry *ae; + + assert((a = archive_read_new()) != NULL); + if (ARCHIVE_OK != archive_read_support_filter_bzip2(a)) { + skipping("bzip2 is not fully supported on this platform"); + archive_read_close(a); + return; + } + extract_reference_file(refname); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 4.6 (bzip)", archive_format_name(a)); + assertEqualString("smartd.conf", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one(a, ae, 0x8DD7379E)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 4.6 (bzip)", archive_format_name(a)); + assertEqualString("ts.conf", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one(a, ae, 0x7AE59B31)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 4.6 (bzip)", archive_format_name(a)); + assertEqualString("vimrc", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one(a, ae, 0xBA8E3BAA)); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_bzip2_multi_blockread) +{ + const char *refname = "test_read_format_zip_bzip2_multi.zipx"; + struct archive *a; + struct archive_entry *ae; + + assert((a = archive_read_new()) != NULL); + if (ARCHIVE_OK != archive_read_support_filter_bzip2(a)) { + skipping("bzip2 is not fully supported on this platform"); + archive_read_close(a); + return; + } + extract_reference_file(refname); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 4.6 (bzip)", archive_format_name(a)); + assertEqualString("smartd.conf", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one_using_blocks(a, 12, 0x8DD7379E)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 4.6 (bzip)", archive_format_name(a)); + assertEqualString("ts.conf", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one_using_blocks(a, 13, 0x7AE59B31)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 4.6 (bzip)", archive_format_name(a)); + assertEqualString("vimrc", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one_using_blocks(a, 14, 0xBA8E3BAA)); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_xz_multi) +{ + const char *refname = "test_read_format_zip_xz_multi.zipx"; + struct archive *a; + struct archive_entry *ae; + + assert((a = archive_read_new()) != NULL); + if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) { + skipping("lzma reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + extract_reference_file(refname); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 2.0 (xz)", archive_format_name(a)); + assertEqualString("bash.bashrc", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one(a, ae, 0xF751B8C9)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 2.0 (xz)", archive_format_name(a)); + assertEqualString("pacman.conf", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one(a, ae, 0xB20B7F88)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 2.0 (xz)", archive_format_name(a)); + assertEqualString("profile", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one(a, ae, 0x2329F054)); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_xz_multi_blockread) +{ + const char *refname = "test_read_format_zip_xz_multi.zipx"; + struct archive *a; + struct archive_entry *ae; + + assert((a = archive_read_new()) != NULL); + if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) { + skipping("lzma reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + extract_reference_file(refname); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 2.0 (xz)", archive_format_name(a)); + assertEqualString("bash.bashrc", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one_using_blocks(a, 12, 0xF751B8C9)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 2.0 (xz)", archive_format_name(a)); + assertEqualString("pacman.conf", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one_using_blocks(a, 13, 0xB20B7F88)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 2.0 (xz)", archive_format_name(a)); + assertEqualString("profile", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one_using_blocks(a, 14, 0x2329F054)); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_ppmd8_crash_1) +{ + const char *refname = "test_read_format_zip_ppmd8_crash_2.zipx"; + struct archive *a; + struct archive_entry *ae; + char buf[64]; + + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 100)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + + /* This file shouldn't be properly decompressed, because it's invalid. + * However, unpacker should return an error during unpacking. Without the + * proper fix, the unpacker was entering an unlimited loop. */ + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buf, 1)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_bz2_hang_on_invalid) +{ + const char *refname = "test_read_format_zip_bz2_hang.zip"; + struct archive *a; + struct archive_entry *ae; + char buf[8]; + + assert((a = archive_read_new()) != NULL); + if (ARCHIVE_OK != archive_read_support_filter_bzip2(a)) { + skipping("bzip2 is not fully supported on this platform"); + archive_read_close(a); + return; + } + extract_reference_file(refname); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + + /* The file `refname` is invalid in this case, so this call should fail. + * But it shouldn't crash. */ + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buf, 64)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_ppmd8_crash_2) +{ + const char *refname = "test_read_format_zip_ppmd8_crash_2.zipx"; + struct archive *a; + struct archive_entry *ae; + char buf[64]; + + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + + /* The file `refname` is invalid in this case, so this call should fail. + * But it shouldn't crash. */ + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buf, 64)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_lzma_alone_leak) +{ + const char *refname = "test_read_format_zip_lzma_alone_leak.zipx"; + struct archive *a; + struct archive_entry *ae; + char buf[64]; + + /* OSSFuzz #14470 sample file. */ + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + if(ARCHIVE_OK != archive_read_support_filter_lzma(a)) { + skipping("lzma reading is not fully supported on this platform"); + archive_read_close(a); + return; + } + + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + + /* Extraction of this file should fail, because the sample file is invalid. + * But it shouldn't crash. */ + assertEqualIntA(a, ARCHIVE_FAILED, archive_read_data(a, buf, sizeof(buf))); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + + /* Extraction of this file should fail, because the sample file is invalid. + * But it shouldn't crash. */ + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buf, sizeof(buf))); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + + /* This testcase shouldn't produce any memory leaks. When running test + * suite under Valgrind or ASan, the test runner won't return with + * exit code 0 in case if a memory leak. */ +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip.zip.uu new file mode 100644 index 0000000..4fb5348 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip.zip.uu @@ -0,0 +1,13 @@ +begin 644 test_read_format_zip.zip +M4$L#!`H`"````%EFLS8````````````````$`!4`9&ER+U54"0`#&55/1M19 +M_4A5>`0`Z`/H`U!+!P@```````````````!02P,$%`````@`;V:S-CHW9CT* +M````$@````4`%0!F:6QE,554"0`#055/1L!9_4A5>`0`Z`/H`\M(S`0`Z`/H`\M(S```4$L!`A<#%``(``@`;V:S-CHW9CT*````$@````4`#0`` +M`````0```.V!1P```&9I;&4Q550%``-!54]&57@``%!+`0(7`Q0`"``(`%IJ +MLS9X>'AX"@```!(````%``T```````$```#M@8D```!F:6QE,E54!0`#K%M/ +;1E5X``!02P4&``````,``P"_````VP`````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_7075_utf8_paths.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_7075_utf8_paths.c new file mode 100644 index 0000000..a0a510c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_7075_utf8_paths.c @@ -0,0 +1,102 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2011 Michihiro NAKAJIMA + * Copyright (c) 2019 Mike Frysinger + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +#include + +static void +verify(struct archive *a) { + struct archive_entry *ae; + const char *p; + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assert((p = archive_entry_pathname_utf8(ae)) != NULL); + assertEqualUTF8String(p, "File 1.txt"); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assert((p = archive_entry_pathname_utf8(ae)) != NULL); +#if defined(__APPLE__) + /* Compare NFD string. */ + assertEqualUTF8String(p, "File 2 - o\xCC\x88.txt"); +#else + /* Compare NFC string. */ + assertEqualUTF8String(p, "File 2 - \xC3\xB6.txt"); +#endif + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assert((p = archive_entry_pathname_utf8(ae)) != NULL); +#if defined(__APPLE__) + /* Compare NFD string. */ + assertEqualUTF8String(p, "File 3 - a\xCC\x88.txt"); +#else + /* Compare NFC string. */ + assertEqualUTF8String(p, "File 3 - \xC3\xA4.txt"); +#endif + + /* The CRC of the filename fails, so fall back to CDE. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assert((p = archive_entry_pathname_utf8(ae)) != NULL); + assertEqualUTF8String(p, "File 4 - xx.txt"); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); +} + +DEFINE_TEST(test_read_format_zip_utf8_paths) +{ + const char *refname = "test_read_format_zip_7075_utf8_paths.zip"; + struct archive *a; + char *p; + size_t s; + + extract_reference_file(refname); + + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } + + /* Verify with seeking reader. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); + verify(a); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + + /* Verify with streaming reader. */ + p = slurpfile(&s, "%s", refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 31)); + verify(a); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_free(a)); + free(p); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_7075_utf8_paths.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_7075_utf8_paths.zip.uu new file mode 100644 index 0000000..332f996 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_7075_utf8_paths.zip.uu @@ -0,0 +1,20 @@ +begin 644 test_read_format_zip_7075_utf8_paths.zip +M4$L#!!0````(`,$^9D5BZ95P"P````D````*````1FEL92`Q+G1X=`M)+2Y1 +M2,O,204`4$L#!!0````(`,$^9D5BZ95P"P````D````/`!@`1FEL92`R("T@ +M>'@N='AT=7`4``$NSPQQ1FEL92`R("T@P[8N='AT"TDM+E%(R\Q)!0!02P,$ +M%`````@`P3YF16+IE7`+````"0````\`&`!&:6QE(#,@+2!X>"YT>'1U'0+22TN44C+S$D%`%!+`P04````"`#!/F9% +M8NF5<`L````)````#P`8`$9I;&4@-"`M('AX+G1X='5P%``!G[AP'$9I;&4@ +M-"`M(,.E+G1X=`M)+2Y12,O,204`4$L!`A\`%`````@`P3YF16+IE7`+```` +M"0````H`)``````````@`````````$9I;&4@,2YT>'0*`"````````$`&``Q +M6UASCOG/`5^OQVV.^<\!7Z_';8[YSP%02P$"'P`4````"`#!/F9%8NF5<`L` +M```)````#@`\`````````"`````S````1FEL92`R("T@E"YT>'0*`"`````` +M``$`&``Q6UASCOG/`2M.B72.^<\!*TZ)=([YSP%U'102P$"'P`4````"`#!/F9%8NF5<`L````)````#@`\```````` +M`"````"#````1FEL92`S("T@A"YT>'0*`"````````$`&``Q6UASCOG/`5<$ +M&W>.^<\!5P0;=X[YSP%U'102P$"'P`4 +M````"`#!/F9%8NF5<`L````)````#@`\`````````"````#3````1FEL92`T +M("T@ABYT>'0*`"````````$`&``Q6UASCOG/`6#)ZG:.^<\!8,GJ=H[YSP%U +M'102P4&``````0`!`#$`0``(P$````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_bz2_hang.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_bz2_hang.zip.uu new file mode 100644 index 0000000..5193a77 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_bz2_hang.zip.uu @@ -0,0 +1,5 @@ +begin 644 test_read_format_zip_bz2_hang.zip +M4$L#!)LP,#`,,#`P,#`P,#`P,#`P,#`P,#`$`!P`,#`P,#`P"0`P,#`P,#`P +1,#!U>`L`8(0P,#`P,#`P,#`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_bzip2.zipx.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_bzip2.zipx.uu new file mode 100644 index 0000000..6d9884a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_bzip2.zipx.uu @@ -0,0 +1,19 @@ +begin 644 bzip2.zipx +M4$L#!"X#```,`#TQD4VJ.XZZ-`(``)`#```%````=FEME,ID:&U-'E`T&C1IIIZ +M@8&J>$9":`IZ@``'J:/2&#```````!@`2FB$T:31D9"F@8FC0`\H^:+Y;81F +M6OH?UN^\U&IFQOP9(.Z29 +MPY-_:/D\-$@RAM/2I>(FNV$2K!!&6I"Q+LXG0-YLG/4-JQE +M=%^\,6JL1H*""1!1W]4\/.E))/*(3J)$L1_D*SPD +MAZY)I5-#7@)=-5H06@2PP-)YSB5D!.3J63\EJ*\X%RMDE]>>,6XG5O@<^@:T +MT671Y,.:/=ICJ(=@\88>!>M^W)$;,QY(*`F*%Q2YZ^%TF$V^/85:V;L\W53/ +M?9[-IX&M.O38C\;C@Q';$E9[,C'?<#304$$9O&4U<2"$^;O(0X:)KR2UT?=.E*K!>,09(4\>BYUO&*8;D4 +MY=51BK5L/;$+WB"S8Z-?)M+GT/]^;,7$S'N0)))KF]$Z(GL[.L=F*G#!4NC) +M4)I$P%W)%.%"0YPC!DA02P$"/P,N`P``#``],9%-JCN.NC0"``"0`P``!0`D +M`````````""`I($`````=FEM-]>-Q`H``"L:```+````H'J-##(C0U&1)Y*>F +MF4:'E-&0:!H``-``)30B!0]3TFDVD])ZF(::`!Z@`T9#30,)"0@FBGD*9-IZ +MIZGE,F@9``-``&0'`````#````````)$00FC1,(TE/T:,HTVJ?J3/5-#,4]3 +MU#TADVAYI!A\^>RTQ(BD3$3I$[^,/; +MLS`?JD6R.G5Z9H!*U7PV]92S^P:OR\HL0A0_3>$BI8)(/R)[BOOLC2%8YJD( +MA.HIB.`H&#CG`1Q7XZ?+[_/^7_[H%_86(A9>\@A,_,XZ=,XL5W'7 +MHP4M+H9TD.>'-*H@_0+C17D%)P0)RW]IX%[$"C`LP1H=G0_&E!1":MS%AMXQ +M.;)R8XI%.5\07+:U'.MSO0WA +M_'JHZ5GH`I2IS+,0&673'.$+E#O<4'!QIOJ(=A]MS$!DF&L:[UWD`N@'J&ON +MK"9F:A.4,3W/HWR,FFXKDW_PF?19FN: +M8JZ13*&(2TCX35$",$])GPS2BLBY&_H+ZVL;>UD^#7W[$P11S-:X+;I&4P_2 +MY2FF=^Q>)*S'RAW&B*<0LART09,I)(!+E@9";HI&D+G>(HXB:0(%/23%!+S@ +M:NR/5*I%\9CK3:PVI^LQ +MG?A&-RQT6VZ[1QPG2Y9UVU<7W0N_@W]>`:ZV*-IMC1AC'"5PL)0>9PPF\/OD +MXXHMUZ\%[^LVOK%3L]),1F)*MOQ5)H +MBOICX8!01L:?$[E<$R]4`!$&F!"N^Z]2A2JH&\;#/"R\MG<`!XM)L2.#%FT@ +MI$"[T#%/63SY#K=LX#RSQ*%:^J%L1'HN2F*:.2LQ2X?"^Y^<9@U@PV(.4E%C +MNS^(@N"/+X8L:9,0T^E]7FZXBP#;&@K7#\.W[MOUG8-`-,<'O._DJ$2@7*?N +M#ZO8W/#Q7.=4KXGTY)7:1_NJ7-3FF\<6*$<^N]+-!C)W4+U60F$@>:,&%)NE +M6U9J0*F"F4!.R,Y`.G*"*P_*(P>-<7WV6=I7*E]98+HG":L0P4Y,?%RY^X[* +MDSY./:P;H^X)PU&L=#"2/IS$=1]X>MB:/!;68(&.EX`-X^"ZW_F;B,/8(F45 +M`_?U2XOBQ%&$HQ1YCTEC[_A42U:75Z>4-MI3.*/X>72/`C"+5Z>0B4C49O3A +M'N8'1IOJC95M$"-@1RC6(E"P.0[ZZ:;J?E0+#0?LP-6OA,=$^`?$]R)HW%K-',>W@ZBCI&CX:1\Q,YOY&7QLLV_J,<-^S+:AAO&'.A;*V +M3AQROQ<,BPB$?,M'!#1QR@/4P#TM5"<*D.$6U5>6NB0:@2#RD1AD +M(26E6M&U7;I&M?><,-FD48N@:,:2[U9AD#8DO`F8G`NH2VG:1>/.?`E4V(J^ +M#5)1$;.G/E?/U7S,RZJL\[5*#)Y+2^&5-1.L.G9B!:4)5`06C6IFT)6E9!%+ +M2NC400RE=1Y`*MU7P;V=>_94Q:13C>/8$;NI99OUE6QCKTH&-VKEJ+?SICS8UQ>&55 +MS!AN47T#J*?QEQ6,M2+`@9;Z#.*GM;18!J.<)J@Q;$1#.I*.KS4[,-,#$>-\ +M)PO&"I/*D7`.K'08;Q%TA8:$`G^HT8=;C3N5_4;IF)[F0N$3TDH*Q0-P<[42 +M,33G53,R)8(253>'`I(/(`C4Y$P=LZC+Z#,LC!<`8.=$0&& +MHL)>D\@AT(1A;6.-(URT`6J-@0P%Y020G3VP:QRCZPM[@QB;&[&]I'1L3HG6 +MHMV_<`9H[#0AJH/K\46RSPQC,;0Z:L!U8.MI-D=NTHM!=_;/K:@AM+BTH-:,C49$_(R)IC&^1Y +M[EI=1!L8O8:A+.F,:91'!%LGX.Y*[9W'8Q>2DN$BIBQ(Y()FJNVR"%T-;E6?@6^'&XMHR)AAWR$C9972+M#HSN- +M);+!>$HVAW9>(FP:U,1BUS180R6S:<$UD99OL@!``!4`P``!P```'1S+F-O;F9" +M6F@Y,4%9)E-9[2!3B0``35^``!1(A>=")0$"`+__W^!``=V;:TML-3U*>D]I +M3`F]4]-(T9`T:&@T8I`F(U'ZIZ@!H`>IZ&`````P``"4T4R9-3U`$T]$`,0: +M9KMEA9T)[OUF#<]_H_:R!%VW(Z5<8GI,92Q$\@_99'.V;0!9M_JQW(Q83@(> +MU(&RK]97O.4,(?9Q\O->C6^K@,2&/*Q^ +MQ&&;:95MR[%C&6KSOTJXV':CWZ0#H?FO+]L:K$L-@\J??66K"[C''`Q(05A5 +MAA`H<]68]Z8WD3,92%/*1-[+TH^&FHBX0;F(=TXT`&\A85\I0".^@K=W'6BV +M6W7I=FG(:-GP/>J!T.)K9&E&`70E\*O7<@B"XC8N],ESUC>J<#0$&LF`$Q"I +MPFSXM(AMXP]!B.B$A)+*A@FQI7N,888C3<<1)$V8APW#69B,^)R&)J6R?!9U +MVQ?F1G9TTEH&P"PV"U$F)!()!JGQ4/1670D)VLF!P-;I.\BHY"F((+!C$AZJ +MZ4L(AR$T$'4N]0NK3DSCOKGQ@9(O?$J:V8>5Q'*QHI5Q[SIJ>$D/XNY(IPH2 +M':0*<2!02P,$+@,```P`/3&13:H[CKHT`@``D`,```4```!V:6UR8T)::#DQ +M05DF4UGG",&2``!,7X``$'3GX%(B(Y<`O__?X4`",3M`&&IZ4RF1H;4T>4#0 +M:-&FFGJ!@:IX1D)H"GJ```>IH](8,```````&`!*:(31I-&1D*:!B:-`#RCY +MHOEMA&9:^A_6YQ\4L6YH5-&(7`A#+:]%S/&IQ$[W/8H;ZFA%01)[[S4:F;&_ +M!D@[I)G#ES0BEILMLL482*!*U'E=+=]T@I+>3,SRC1"`R6N_&W"N!*6`ETU6A!:!+#`TGG.)60$Y.I9/R6HKS@7*V27UYXQ;B=6 +M^!SZ!K319='DPYH]VF.HAV#QAAX%ZW[ +M2:!4(E-IS87%O<(M4.)02QAK:[^IR!Q:E(+-CHU\FTN?0_WYLQ<3,>Y`DDFN;T3HB>SLZQV8J +M<,%2Z,E0FD3`7-]>-Q`H``"L: +M```+`"0`````````(("D@0````!S;6%R=&0N8V]N9@H`(````````0`8`(#N +M7F'.E=0!`,YV<T*``!T`L``03U`0``!!0` +M``!02P$"'@,*``````"\>V9!ZECJ?1<````7````"``8```````!````[8$_ +M````8G5I;&0N`L``03U`0``!!0```!02P4&``````(` +M`@"9````F````"0`5&AIZW;_.Z31*H"X5"'0#D!!Z[ +MBD.;"\&2M2O8TO4XV[C)FEEI$MIAL&1)R*(X=%*;,XMAB[M*8\Z$';M1TFDT +M'*!QX<8B:3.'+]T`P#R/A8"XYNR.Q\(-`Q:D_@)>61JQ91P&@(=H1L`B*TY< +M._6LN"TE`.1P(RK(OF7'(\`XT5'!(^SDAS7LB_CUN[!'/DN,). +MA?AE%88KCZ_B,(U$QPY]T-DA&UJWP`0Y(7L1VXX;(_O$<@/!#@HR!PQZN)V$ +M\18EZ8U'%\:E.9WTSHU)122D>@W68J7WKN=:\1;(+^0P!-JF+\T0&G."K&F# +M=01DO7$8)JT2A^[U9Y-8+%+7@33=(>+RT['SEP4Q;`:XZF(XHQ=6C%,1+1IH! +M=TK4V`XIMDC]2.!ZLX(MZUX9S%Y;P8JWF0@!VHZYSP-0U"';K'G``:O,PG># +M,,Y).2$7H`1E5T-C-)ZP3)LL>_HR5HM*6A&_+3S`SL[ +M0W8UT7]B9^R4_2?[H0[_HQ[^U8E"^+&.\-,>A%=Z!'`Q>Q!.ZX#W^P"!ZGVN +M(V,TZT\NNKW^V1=NKT,&VB*(YW]4M/BMU?I291#S.Y=T#DL"9Q!,0$VA"-,8 +M&,E9!"$**3*^9&3OP.\V*@EN.X"0I8EL!:\9PY\)N- +MQX.,V=GS'9W\_+PN:-%":D'#GD+$N-6&-)`E5!ZQL\:%?MZ_,$9]??R838S1 +MY4W[0.\7#]J-9_./%?H82"O>*V=@7H]^NQ[/^N?ZX',]?-^?Z#F-GL")6>!O +MF("P!`D!JGO%XS)W36S)QK;3L9>=BH$[="N!KD2VTOX058A8TKO-,&JL.20D +M=U;L6@N/"[;F$$Y\=+0+%58LG\:+[R#(]/K]=`8FF6,`G04'C]P&*TPD1H4D +M"X``J"N"9`:<&*05X#:#L$X?R."7_UHE-`J+G#ICG];;?S#6%;=YYM5IZ%5\ +MIE%P0ZNULUV=-?9:Y9G>)G4(TKAT"&!:M%H@I"9N`B&#ADQCU"\<6E&@QS"5 +MR:>0JH:,@OW.19L9^.U"/)!AV96SM`3G`SEJXH)B-SS+.S=K*Z%<#])9F`<7 +M,SRE=)H"L?47H2.7@81JI=IFHJF_C0 +M[YY#;W.>.:";FL.KF\)?G@= +M8H*]C3C1Z8[&(Z/7'9@?QE.5B/<@3W`]BQPR)N[@/C:4[?:VJPUD[0'G#N16 +M$;=A@J&"XL&_,KT-*Y,0.M=P?-N3'JF9^,T?GX +MTU3J#9.JA(,RGN\P@XA.V9662._W2Z"CHU&6)2=!.CTGXT:[5]8=\W^ED)HZ +M-"6DRZ5KLPC4#@V^8$W>6778T;EY-9X:G\WI^'K2Z[<93^Q6XVK0G5V,)\/> +MU=7%H'LY/7M,F3L(0->\GE)DO/QD=D=3`VSWW!@7RLLLN(Y:&),@T:&J7,66 +M+SJR]!A?FKT>:DV]FCUSC#W(;/K[=-8?FOW/L_X(E\(4.[(%"AK]_M0\'PQR +M.JJ'K/1#O_>KB5_-.:ZQ*RC*1`))^8VJ<,816JN4B!8#5F(RA'0(`/1OI5Y" +MKB>4(*I?Q@,J6%G$PP@L&2#`U<6QZW":,"0!4G0GEV9_U'T_@/BFPA/&KNX4 +M%O#@2BW^YOSHB`<84(XR&#:7#8IM'MQ8TY%281+_[!$R9U#`0?:"U&"0D#/) +M[SK-)U%:@P$Z!25G"T%,2VJ7$M1YM;&IEEUL4DXQ>E-Q5XM"66REC^P6^F$, +M[I+1LLHAY'`/8%4=!.'!6XP'0>/9,]F$925EK! +MXI4"_BT5H^5./3O`> +MP7:'!J+*QM;C\-G8@K`.C)2TM%^B[=1&=!V(-(K"&,O&.\M+.2VQNHFW")\< +MQX['?']M#,Y-&4S1&C+-EF4ZD,Z2:1SN=-:=&3T-?F4()0(/^@-,5'<<`B9Y +M9:>`0%F6"-Y:5<_*(S@\T+L#RH$?\P<22.L0:!_IR1X!H4LN0>,,5$[^!"JY +M.]`Y@BRU?\@39*/2N0*)K_$%Q'N?,\#./^\-&&.%51#]PB'L]N$*8>I?907F +MO4_R#YP!4G^0>:-[_A'^H2+?K#HINS7!W'4*N)8WB_K)+R$SO<9^`&;C6 +M*4@#>()7J%.HCJ/B%]B4)[C[YZA<#/-8&,."@_Q8'MM>2GX"]R;6W'*@O)&6 +M27E5-:?Z=YZ%LE:#9CJK?%4F`W]',Q#LY/[D[R5A>KEBV1Z6&[776S$J2^/@>_\*''49;)(VO6&KD)4V5`'C4(`08?I^< +M+L4Q/LRE@(:E#14X/%=Q1*BR5`%L2:$YWZPY++.803)Y:AKCGGG9GU%^B@X] +M)3<$/@>7-DAIVG?FVKKCIL-MS]Q!R0"IK!I>05IO&A?]P11TCPEJ=W1)">FD +M.VS.?_GNYU^DI7#V7V(KCMW01DG?-2H]]0&]4SP>^3>':IK=@\WNRMC24L!@ +M\Q&*U&E_UGS*0)G:-/Z_H16@9Z<=:(5J7/P)*0JM[VR%?>A"P?QI//D58HV> +MP*L]"BVMC5<,7/4V3!G*PBRV"6-RNSK=*@NK6B=,!MHNVJ.+5NI9PCALH@V +M3@>/NU;\'I["7046-HO(V@1[2(G$L>(5`B7@Y!+Y`HN77F+0RSX\L'&YP/'- +M!M\IU#L8MUSM>_'4VB!H_];A=]E[F*($>_$B"RI*!:M&C*^">]Q.L@]@GHN" +M'W?+?5I$"-QD4L!IY5W@!I[ZVD]"H:2!"UK#%]6PL2%>T_,!+Z=V%JCWD-FT +M$9.WR0-/2AI82"Y-A9XL)V!NTM$3M>-MA.J`5Z5I*(OIO\9\?D@'24RN)+7K +M\0'8YRXJE^!=XY`'CKMLW-S4BWNPC]B*714A,.']9,P^-.=?H8,6X&Y:B,?. +M89H<21!8CV'P(E$9H/Q99YOKX.#*@_2-9P$A. +M\Z$H>-U@9->3AK/8-QZ@T7[_SU.@=<[Q/`]R1F$$;J(9GO?5!T.R'QE?#K5_ +M@`B2CR^#UPU0]3UIA`I6-T;5U59/#".AHYM`UPZ#NT?&IV"RT27Q%F,#IN#, +M6N'Y,R1V!*(;$/7HAC,T#(Z/`^I0#7_@\QNC)PWBVT&5 +M_,7UJ)?''E.15\0S&F4F"K\\'#L?3I6*4F5M8(P=,F/)JJ#-5E::NP'Z(=)+ +M&\\)*)S#'$*)R,&!/]$>[K>_U0P],V]=(@I>,#&USJ_$+`DT3E__N'FP%5!TRWIBBPAL7@\;K$ +M2(*W6E568<0#(;Q'>.50^[7KPPQR.F6YMR`'L,2:3@NDMC-\X*[?Z8?<3M:B +M-`!3P4,57U1_%;'O?>\QP+=5D,Y2%U]@[-]#/_'E*IV,@/`IDWL)EP6 +M!8"^$Q1D#,G8:YUH:$^QS3[FDG6"4FP>5"L#):ZVJ!Q4PZU!S)@@K@G +M&(#RL-!ZS'OF8/LMF0#*BT9B:'VHZM2,=I]."3Y7Y![]8'!O`B2ZT#9KRTV/ +M7#-$HJVZ6S+ED@>%"^AB7;/&/AF6-50*>$G +MU%4)]P&_=";-V`RO`6QIKHP42^ML%[$8KJ-Y7=J)VF,%R70_]MT_`[:Q63%LF$U +MH2IM68/1R?]T!K3@8_;[5=^\-L[-&5/G!G2ZB5<`#]I*A7C=(K##&&]!$N.A +M&UQ^`GQD-9Q^['7D14IFIR()??W9Z`1Q0P%F4Y/C[C%![D@2B:L5)-_4 +MV>6Y<.-D3?>&JDP?YMB!E"G'W+D5XZ[61[`&0R\E?X8P@(377?\R#[S6T4GN +MS$!@P?PXHO]7D?XT$S.X:4'5U34^/XZ0^E)?`#^+TS>OG\HB)8$`ZT,:.]7I +M@VKLEI'19.'Q3^O8NR7#:54(0P=E635R#.]RL25U/4%#!"?MPRCM(*-7@$6# +M7F&#-P%%"O87Q="ZS(8AV'?_D];1RJZ&_CR([WEI'FR+@0%9M,7FWW +MMC6G"`,JB;K+7H[L$X5PUOOIIR.1;(OKH128!!V0VYXEK^S[E'-@2,4J.K^D +M1%>X,=.Q*(O;PC<382=WP,9H-NQ^+@6.ZYT6:'CSN@91:8#O[T]K`)4&^'[U +MI@:PT_`C?!=*.N_W!J`DB@\@3IM)IN578]1FUZ5FQ1;>*T<%2`D(993PE/M9 +M<:#1I*0&8Q5>_\A!>K8(;U;65+U)4=](=,#0#K)D!Q,-#OR>!W/U_%O +MX42S0XIW&IG[%Z@ZM-97>G`UPW@W77DCXW0'&"=`4P8 +MBWWRJ-.^=V4OI:0Q!M/^;WIIJ.O_21J*_G/:U#>Q;GU6G(WMGE)!+3";F%#R +M24'G-PJOI9UCNK]*:0X6]_2)*XU]45@O8!J=P).7BJ0T./'CBT*>;"!R-M7Q +M[,P8]K6[]EN&&W!T#::XFW?9@U4QZ68'Z24ZP^Y_CR?XC16">3'M]W\=YY_@ +M*7O#J_QS@,?O^5?M8]*?3,83N)\;L=[,[@PKL_?6L/\4(,`N9=1?"]`<RT#G+T. +M-P'\Q5\R,9OB;8P!8>EHD);V&G]QM,)3&#T\(_E8Q2M(VV/Y +M"JFK&>O1H@UU$N8FS5!`N`7>X>%L)?,2';:7J<:3JO&D:J@.I*"G-.R1$CPI +MOH:.OXB3<&,S2*]]O"T/3[EYO@-XBZKV;Y?N,H1'`#S]6_0.D08X\,SL[)FV +M`D&$R`7?@6>CZ!+=>Y..?B.&<9B$SEZT*I8'J0PDX\$=/N3N.!XD6^0Q5*60 +MY>DZ$@F4MYAPQ4X:X8.<+;X$=K0U$366$%N?!$*-K7P-I>2KP&LY@9*&5,N4 +MP +M$D+N)N061.CA#1Q5;(O=I2XOD^.YAXGG__EO82`IP\1,X._K+/4#E@`X0;:` +MTPZ&!98J7=A;]&!A0+^@L&R;1_*7+W2G_`@W&CQ$+0K^W2LP#;9[":8413$' +MI;KP1G^G9'YN3-A+@'J;)>02@_$V>QF_A7B&8#%/TCAHYM(WX6^;_0U@_A:W +M6F]OY(V5>FHP@<@%Y,U)^U7[@7L?-%C:50$7C[E#S@;(-DBI%S'G4"*\$*R\ +MU/*DW`JR72X\%:"[^EN6W4""/QC)TIB&I582!`W!_#!(UL>.M<6@`X]C:H`/ +MF':\<,&8D3#?NJ6-?B02IDF$=]'![^!A`VZD)8G+8_JU:#5C.C>'Y^9XJ4U%M&,L$41ETR6"0U==(,#I-T878[Q!4*27^768X@9!K:A6UN'@ +MA@,NR*7+/0U(%7\K_) +MIVASQA:Y08`$*>H>&X9X$V9X"X*4-+-Q3#6`)MA+`(V#!B117K^4?_@%SHLY +MO\RLZNI&-U"8V?4)1\Q(`E"5=V9IZX'Y.YUKKXKM\><;B*1W%\WSX_95 +M\_`8V3<<.V_^SQO:-`*M:/&S\5UL?Q,G0(;7S<,SB\<_:8ZF\YUZ[:W!/`W@ +M&"),M69URX<:I/-.POOI-J>-L]D_1'#N5TX$O8^[G`*(Q,P)B50]5H*_$187>0*4W9="R) +MUIQ^*!1=4;=(:P`/8*HE(+\SM0I:I$?,!HA/>(Q*\@5HI"47W;0PU]S=6\]K +M32#*G$$+8OS$6Y:[JS)5_&FO8Z&58BE:=%G)N2.*2.HGOHA'?#(#R_6BO9SOPQO@ +M]-`)!8+:&V8#,)O-K0V+)XRLR1"X[116$'QBM*XKE,W6]%DJWK$IZ:=)YRNG +MRR8L>Q&S>ROA?]]B("S^%4$<20@^(I84")]P/F.0Y@-?+[)=Z,Z%@6Y7?2L( +MSA!@*K((>^ID2`4%E6C;2#[(P"<1ELZ$A(1A.'D,<&XI$AKH46O9Q?9-Y:W<('YWHGD*19'!Z7K92%([I8;=#&? +M[0=QU3D?J.5_%J*O,Q;_*U$Z)A_KE1C-TP +M_PQJK3K]_[-6J;'_=B3OY_+;]-D1GQC@Q=[)]%$=\->_<%& +M="!4@]?(5-^-$3#IXKH1/S?N?M[+@AC.6A>_SB4G2&[PYM_6?U)GNH%!G8TV +M=W,,IW'A=W<,^Z-)^+7)Z:7K6/]YLQMRODUQ=W:,XUO:U[L;8$ZCZ3KD[TTD +M.(23?G=;35U_H0]?M];_)RW0]/MYG]3Q[P']_S;_+9C)YG^C[[<*/TA5*/Z) +MM$I`W.9!BNUH?>%`FUW_!;41;#?_BT7W6AX2/WGYV*F3(-:9'SCQH<"LR.R[=O) +M@&2;-&CL$H7A;G<&N[2H%L`PE9YVD75#A(34L)$FE$DL/]U:8BE_M>/S_>'9 +M;7+E&`OR'\'/I]?'5X!)/.T?_PCD>\+K`D9K,)"BH1*;,CP2FA/\W`B^QF$I +MI@4V?:RN6UJUZ9)?XMZV[)K/7>#\59>?B4^47T):C)K12^@.XN57H3TKWF=` +M7_%"NSEEF@9F?Y/TL.*WE22@-/[?_5*S"O[J*6+-Y?G2P'1PVST[OZ%]E +M#=H?F@UM@7]6--D[>)$UNJ-/%>WV7SUWVM&GBG8'C3VG'7V2Y$Q:2Z&#+(#N +MU^$VD8+B"NRO4LFAM,GU^5'CQ:Z!,1GVZ%.QC6R"M$@?PN(N9+^;<2H:\399 +M,//;E&NSY]-HWZ.1,ZGRAGPJ=EKSIY)KL^?3:-^CD3.M\H:,!'9:@@25;?9\ +M&NU[-'*F9?%.`I*+(8\2D%T:OCB/A!?'-S=GQXR!VT%M('VWYAL;=#3M!2$7 +M=A'L,QV`>LN:,V8X'?CSXBY\:DX7_KRX"^^HTX4_9UWRT;9N&+CGEEY>'5^T +MVV=V3X5E+MA3VR';U,H^LJFVA]G51>UY%]T>NJV+^O`VNGUT7Q?UX7UT^^C& +MFCZB\UQ-D@['E`Y[0?/DACCN)>TN=8'HJZ*NFL%0O#24C/+,Z0"KE?:`-9A%]UA^)?`7^D/`+2U97("?0VA\M"1%'3$GT@>B>XKVWN!/3]:$2YU +M\`(LM+4`O$+)RW=I+(,N=&:5>6N/Y1/7J[8*;--E.?"\N+<4,)HK4+E197#E +MEY40Q.VR`GQ_3,GU\1UAM4/-=_(=8\73+?3244"SRL;`]RN=0];!$[+_"3@] +M/&&O"O-G,#>R[BZM5)H[H!;^)7QU?GZ\T<0V4 +M\)DX8*\P<;A>EX'%8R8>\-ZY50/_ZM8AK-H+I(4C$*-B+RHS:W+!0\_*)XU] +M:--^^,S\2Q:]M&PO`/+D:#68'B?A!@DB\H"7? +M1HMA77ZZ\(.$+*#%H*XO+[TN9U:X<\F^'5Y>_0:,\=PZR9]9.$?DB-U=>TU2 +MBNTMFR&G?_I-KY!JL9@^:_U_U,[BXC(^V%C,ZBR/T;4IGG!4%+(\Y];'B:7E +M<(+=E2=DDUWGTTPQF45SL%T]MKIBV-;%'QZVY7-'YI)J*W-JEXUJ>OZ10?_$ +MJ']B6).<1==O]7%M.N-<;W'='2^GGT=G)X<6BJ?$V"M@O +M7Z60P3,NF]]+]-N[7C*>T/X\*Z&B1Y=7UQ>PGM +M5;9)4LD74:&3PP_(^?0@:/<>`O7)"A*UI+4O@79^Z:66W2\5ST^\Y7-.L%\, +MZN+FS.<&:UG\)22!P?GQ%)OUOQA53HY@].)47A\*X=>JY84NB4SQ-7VG:)-_%LX1T#TGV0R*1JX\M`NKW\MA\,9[$FP"2D$ +M=5)GP[`S>`KNI]%@D&P%7)HO%1DE5=FI8,.5`;@&B-=44X\#;_L?>.ISX.U5 +M#AR%#!9#(UKH#6D.UMQ:"5JS2K8I`7B_F`8"W(D?"=2*#4O!??2$9ZIZ+`1X +ML%L-N6%Z?+"JPL`7AZ?=HZ\E($OV256I;"O&B>>\,<+UWTE?>:M5C, +M,GB?5IJ?5)U9"O-VA7VTY6N60*4+_?XW6($\X2XEL*LP5%-99R&\"R.))9O5'?+!QX*%7 +MG*V@5PR6ZA5GWGK%8*E><>:M5PP\N,J9/UL95%"%$HA"&#Q=D\]L0;K-VH`^ +M;Y5"91^?'TB>H@L3542J@/I.M/-C+P>4/F^5'$[K_?O?]_R<,OS21`ZF>7VB +M8JZ''YK7)-5ZJOKC,`^@%%M/P<77U2!QG%`N9+_7L/\^FZ=>,YS);L)9! +M73;-\]:-'QO\4A)\4H!U4:&;%Z?FOA2WE+$2V-O/=R>MX_/FE2^+M8_/^4+W +MM,F^R[UEYPG\O'G:.EP)?J404PK?2#)>-,/#!K2""::,SO.NY5YN6KB[@(U@!V&C/O=/WU?TF;1G*(%3 +M+73I7!7%J?Q!HKW7C#VL=V?^UKM!A?6N!**_&#E8 +M9L`[JS;@F"J_1%-$I*J1OWI@_CU +MN(9L..G/4.RF?$DTA[OC\ZN;WS1R\N[][:G?^I:;L,Z\35CO[-MZR\FF"%F^ +M))G?(?,"Z@W1OOGE`?82_S<^KP9;7A?SA8ZB-YX,1&O]+CJS\_?7-Y>?#GUN +MH58,7@CM^/S\\J./@><=04LF3TL)&T&\O/[-C[!)*>,E\_.CNU^X^O%"4+]Z +M^A"E@O)B4">M$R\W!I=A7@SJPD_+UU+.BV$A&MXGD/,=_'-^(28E>`VOG2=" +M.T$7BV9^<6;M,3Y[(06K%S,#>!?]]--W^A+R$L1&6)ZG+(]*VHN6>]6Z\K*I +MHACW0CB79UX^7GGP>-GZ")CG\ISRX(NGUVY]OFM?-3]Y11>_XR>HE\WRT]'2 +M22ZJSSP'T%9\]EFY*8&^:-4`Z*FL?\E6\G&!;\3E^KN +MBU;=/CX[/O0BU%*4?3&LFV,OJ_D76V=^"3B1MKT@FGKU"R&V3IN'>.["!ZO- +M4^I+3H-@7C3]+N`[?91]&41HP]O<7>[B+%WJ+O_P_$JW_L&3]SKQ[ +MOVS_;XY0G]?O1*>]>"[HLQ1DRS.V,WL9>BE([VP%>:%A\'W[P(J7RS,,2 +M6$>W7FDI)AQY"30..UX%WF)]>Z5`9L"\AT*V!"(_:^-WO*C*N%QL$=SV],4) +M4$^8WC@CSWWBA)O#OA1`D$=Y?/_(MYD7#A4%^7C_61!VM=(FZ_:BSWJ<"%XY58 +M>9RAZ(^[]ZWKFP_5V/BEZE7"?]:P[:OCP[N;CW<7[>,*;?=+]FC?GQWT[%?> +MU:=>4MEJ1T38(]]S:_Y9SZ\0&O2@#_\..EZ +MQ*P#=NORT#-N75XD?NQ%I5%8)=,^__7H^.,*DS:O'2^?]/GEK;>03X#];7G5 +M6.-OTLL]Z+Q\+5?-Z^:Y_UJ\+%4,U]=:)>\^L_W""[`8,E8`+0]@^^&,BHS^ +M&YT]6.TQM]LURZSLOV+R]N6C-MQ>+#+W5RYY[?;QL_1>PIQX? +M9:$+?WJ4BMB(^9%\@R1FR\Q!MYZVH"_V:=/%-A9-@/&,VEP>/N`?/5!)8N?A +M^>'7UV6I;!^K<]D*D$R6^0)8\KBTST+Y7>VE"_V$>**5P_CMJ]X5\+R03A^W +M7;3<3X?7-Y?G[_V@X8G%;WDL=XEL,Z.O4+BY<7? +MQ;`\]XO0PZO,S"?_.C/N\RK+)(%/K0LN"N +ML-'@?$B6OLJ\\*SDW7FO@Y>WG9="6XJ2(6<'X0TE+E%`*T(FE)@#2]9,A`O6 +M]=*V2S?7JT"5?WVJ[!7KQ:Q%2BU1.S_[O7T1>PE4SA=NO7CN!]1]2GL)8-1Q +MP(Q_O[SP*U*0?YE["70;B>F_(=E+WTM@G_\J66]SFT*\HIO@%53E(84*-B9Q +M;<0.5&Z90PQ)+:,_VC@\OLHO,Z:$T@.\23&-^E$NL@)9,EJ&TM1] +MO+C%F\C!QO[N[N[>[FY5_4AGC,7PO.I(FCA-N@K1/?T_ZD8\<7U`7E^\)"F/ +MB]&%`1Z)IE_Z,)2D@S!]*!R!A&.>7)Z=@=RUSYKM#R3Y&9/DW$$S*Y]U:BCI +M0UQD\H3G-.6--EKG-$D&04I?TYQ(!*<#"0<#2)R*LV+JJ3-&KC8=!H`,.^7%=#%LQ)FE_Y\W#Z\L%%V@2'+)B2D1N8E^] +MTS?I:UV>1XU.(>GSL^J%@2XN4>CKMGUWJ']?FH$N$#I`N#@.NX]A/X>(5\W# +M7YNGQ\&&^W3C_*&'O1Z=*L7(#/'W@1WT[]"\3J%`8 +M#'$)U\=7E]. +MQRF_2U:80>2WD_4>^T`W%]>YZ55W&`,1+<=][>"N/*!`I/GP4;97!6V0,E8D7J=0-Z$?_@Y5EQ?ULH^W`\DV==N45RGX,+ +MY^7EB=4#GB]E.$W26NGR.%)"/GF9%/U#\YASN9R0Q4CHION17N&99E`1G +M4=Q=+>"'>,,V#>_Q@K9Y/I#?`& +M4SR*V6Q]#O:W@Q8QKTG\79[S^2F^YSG?-<_.],7$]9_4ANY^27#UI=X,^NG% +M;6$$4^B436EFYX>%D:C;_$C9EV4C31\0-@AQ,C^>/O-9&$"",*]N/B"&\*Y] +M?-Z\N&D=MIW1*EJ4#9T?\,-5<)&,VM-D7!CSIGEQ='P^OZ[<]V7P^_S\TL!K +M81"0CR]PC=IW=\X@N>^S02KDC1(:7W$Y,WQ])@]C/F."\4FTI(`:[@;-JU9: +MP']]2U.17M=)Z^E#<$H(PV4NO-#SL!L0O_L<-';K!X7E'C6O42'TMGU\1U+E +M^]8-\EE7JCJ?ZO#?'RR7WJ)&SC6G@;4K#NYB4T7_TVS3L +MS&EI7.7K[O($I7,P9"FSGB;\WKTI(O0UEHIWN"*@O3+<9E3OUX,^7CX+]NIS +MJ:O9"]`&??(#X2AD5YF8;>L5UV?!>8A2B+R`*A$#1T(:Z.=B3_YROL]>P7P# +MB208)=-@/$F^QKW(&M/OHY`H)OT8?6=9!=(GY"+>;#G.8E5WO:6-\M6[1!0" +M/KZ@HTTF3-UI:S2H$K23GX3'4*-^BG;03 +MW92M58#"+ZB)H^EIU'T@*HMVT"/\VM[43T/2T&PE0WI/XLYX^FX70YT!%P_'TB14<5I:?9=<9Z5_)9(A& +M(D<5X(H:/@=07M?&?O"CVG=]KNX9T9+ED6T3'(0Q\QY/56VXSBR#*PR(4DLE +M`^:=&,_*X?**2J&6`[7V:)HT3``,WY@`S`_?XAZ);='WL#LE6:[Q0IG-/>O5 +M>,<^E*9.W3BFFU/Z5SCI&>DO1=G7;'Y!7`SDIG$;+_Y)L]S?^Q?.D@GC/V.6 +M+Y[_"V?)]*UTEC0)O`);-D7&*AN^SM*Y6RFHQX7'JY%,?9@EV`M_VZHX.R2) +MJA18YBQ<%20)1HLOUQ^9)W2X,JA%&C'[I]&(F<=U'@7NHOY3;O3,[TI[S_1? +M=ZMG?M?:>Z;_NIL]6WBU5Y_IJW_E1%\M(4'E_5MG"V@0G_JF@/P +M>#H1P"=1)]@]V"9QI+'WQC5T]Z*O)/^,D:A$H+ZQMD(#TBT_C:)[6!?NTFPVK@SZ"]I;,(INWN8P1CS3",2:\&=+8AI3NH^[%HT*$8TH,!8X0,ZHQY*N;*]?6CB-2]YPRBD=L4 +M5KZIXR`*29R4=ONFW4<28)-92J3Q.VW_,"*]3U]L/IE$T?OV4:%]VQC\]9$9 +MFLOO\3B0HD:,+E)XJ-#M.NG,TND(EEP9B1#B9=9Q??TB^1KLO:R8?:.335]: +MOC`M72#Y7]I#DI&ST5KM2YX>VD.G&T*5C())-C'V7'23R60VGC*6CF=3@6EW +MM:6]8+(+ASB5;'@Z*K,I$)EG_+XX;-<$"X]MQ5$JT'8-M(OH6\#>NQRS^?A8/>KI`TJ]51I<-:NQ7;.5N6-C*7;MAM^->.(49'?Z%FJGO +M9(RQ*",S&[`33&SO.<#?U]O1.-BU&W42?P_P>EDM?4N-H:NP60]?H2_)]=,) +M?8V5TW":KTYZP>-5RY<8[/#B<;#L$_+[]!63&'1O8BF +MA+.X-8]QFMQK]P/3_9(V3"=]!S!WNM=WYJQHR+O/GS];QV&J3A?ZLG$:CL=1B"<&W.UX3ON\_LMLY"#C=?/:8"E^:-@?FKT>=N6-1`76 +M]KX'R9@=C:PW8<-)IYLDCU%NA#W:<%`9F@WO(9O?O@>W-R>U5VJ*IJ6/)\&> +M7?IU=!_"<\;3N$/>_^86*'%"+*=+1Q%UC7]3G)&U&(87&*L(UEOA3X+=[$L8 +M"-N8$%`X`NGV3+`7.BS>G-=;.!X@>#I.'Y4PR)AIA,#GJ1IR^&(:'9-NYB`" +M!0\5`0!OMW`#\3M?:UC*:5W@7I-PE!H$S>Y#??V<#FC?`C@G#9LM->@M]G;S +M&@0Q@3*#CX>O=P@XXV)!=9F:SV#F^O;%\^W'F/KC +M$%)A9H+3NV^"P^9[$^@"@J'S&!QB0^3)]<>K0K +MA\!&W@G1SOM[8"QG@N.%,3U3H0TC,S6A6Z\,@.O(WE-C;'=<#3EZR#UW[;3G +MEPI)S3(]NUK@^5.P9T?\3"1490O\T+!K`4_X'S>6&+[5IV](A)Z"#C"94IZ. +M,=-,2I$ALJDI<>G1V4PS>FC0P%R-;L!A8O;M&P'RW``9_%!6GHV#'055D)8- +MTQ+\7^_T&^&6-5BRZ$_VS-9J,_XTPR>AYJ_<\[LF+MT9X/++320\SDY_1ZFM +M(^H036&2,NH*-+T(P"1"39*6#(5F[A[UP^Z3R[2)%@GEL??@B/?9B0@QX2!, +M?\]0(E"PRG#LYN&9TN/=W.EU6)+AIH1PQ%NBG'B!G#DNF_D4V-@.OLI[#CH. +MB/^Y_!"Z/6T*"<_P#[REZY?"&DHR0G<0\VT!VJF;;/#$4GL0X$&&@?'FD!32 +M?7RRS\">-&^:9P'=5['ZXVJP!P;4RS(*GM:!12@Z#\59_L$>O;!%YACT!SO- +M]<:E$%MQ>Q]FM)'U0K^K[`R)#A&G9Q3O$*E^9$M(FM]P(SF*1(_+5@3(U%B5 +M6H?HLJEF&_H4_HI'"?YBPX<02+:3"JC=#!VZ,]&\"*]1+]C271FT8>]96SD= +MR3?3&+0P?TM8&7J9'>V016XXN!0K'=QHU+^S05HZ/<\ZX?[=QXF5AOAWB[I- +M[9Z.P<65XMG,C"?1!13YI:O=,?BY^RR[-,?CO"<7%\XRZQ+)/=!$SI6=1]@,X^ +M8JL"3N@?.E+RK`!!KC0NBKZT0$(B(=@A/\&XSHVS3Y>IEP$FU/8 +M&/0C3X.FOE6`H&K"#MKR'W<:*LL.PWAT^JFD@Y1/(UP('PN<)@"(5+HT*KK( +M!1%4`Y&83&=C)A.IJM"\%[NO2Y;76+X\UC?DX$I`-)R#(]E`K@[:X?PYS*F3 +M]$D9_Q9.1BI]SF"G^?Z#V\L%,NV!+W(N=`E>"GMN%!N@*.#.]Q\.@JM&R@B> +MDP"$?M2%Z]H5?``B14$?3$V`J!&'`5R2&D'Z5K#1_T%?;\`]VT<^HS`ZNY/- +MKPFLK\33,XJ<)U1,GU#LJ[XNO.E%Q18ZN.]H!G,-7]1?OW:PD9ONVNT#2K1; +MIUP\3&PZS($P$5[6>?OC8;VD3QI]Y:`*#L];A(<@D=G'.^"*3'?W5>5T&\7I +M9MO7Z\6@HS0R(SB"XL0SK<^-NP,T*@?8+0Y@FX()$&X06X'>/Z+CGHWHP+=I +M6_`WW3[@(/X$/@';U]=ZD:,S&W>],1K$1B4WBD$ZBSGH87TMB\D,)$HKX@MH +M]6U5R0S3_=2\OEA?BT?BT>_BLJ6)9>$(;P<=T_F\%[]]/8EK'AW#")6-DW#TS[M71B;'! +MI*(.C41:@&$"(HR:A#D"E:.5XU0X#N*>`SGJQE:^K(*TU!^9"8!_&I!K6'?G+7-JCJ(/M?4^$^:>#QHN# +MER\=$0B-?@N[77&XLUN+*"$"/_2"86FD48#=LZ@`^PFD%6*CV'`B$\1M=@B@ +M71`+X[P@=]X\,]/FEX3.?^JNKSGJ$5*EP8=H-(D?4][Y`F!'6R"T(95@\1@? +MXOY##726V?B4=$YFJC>3&91<5GAQ%2#C?)A->MN`]/[O__%_Z.[]`OMV720# +M2Z^.2P0:\@Z7TZ0[7@A]))/'C +M<01Y0%@A%(CM];42X6H[B*9="<$@F5B$+)Z/DDA5"L5`062(G2T2793I=1B* +M=(N^+EYT=\R5Q4DC,TA(DHI]7Q%B.5';&H(U2#X$II#J,"/V2I.=.'W!X4!@ +ML]LK9!)K"V?3A+8IANGI2:H.C'KQU[A'-V)]365C)\AYB!40SL16RQ-UG*9@ +M)'%-69#2;FOB,&#SRJ?X,:85D&8+!\8#S<.%P`*\#E@7H4C0X)4:'=2TMI._ +MKF*)9HI6=EWG`.59INNZ&;(2[GHA5/'IXN2BR5=9LNMU`3.)[?8P62(%2[>' +M+6$)CGT<)9#9J;.<43S&S:ZY>(W-GWK`4D)(:4B$O+GS@B9+FUX_>:(2_VKN4UH1JZ68P8H'18>&!,)9L +M97,9-YQA"20RT>]W^(J$G?6U/IL5<#*J4CJ]V0(S0HA:9D*MLX,HF_LO8?CX +MF!"_BW$`HS?L=@KHV&&L-%0Q9T7D_A:5KJ(>49?3^)Y$N)C68.JG6:-\0??K:^CY+:3SY/4PMFH//4&+ +MK:VOI,DE=!!3DB.5,5AOJW'FL/RTS0PE308S,<=#C10%V.*@F2*S?T96]K*G +M*E7S8]ZIA/YCE_BFXD6+]34F^P_1@,0;Z*C$EB>A'@F?!F>!Q!"=(;)MS$9@ +M\J.-+?;DK3'*T#9([M@FA(89>!IQ8'-\CWQUT'"K7ICU+TDTZ0?M9$08W('K +M?)*ST,T9YQG'U1[(D`X601('BYC&#%:+3V&O@G0?.,KQXH:=O"5BMTB#6(.+ +M<)'9E42R831*9GV2YYB!DK83L?+%^$6,M@'7,LY-_`R[D) +MI(.<$,.&U@"[&HJ+1,3%65^0F*A85S;K>8?$`+:*5+'WY\YVQ.C*/M*$8+'_\B$B +M,80(\]QD#DG1&N%*=F,B(6]@].'*^(C=;IW>MJ\;@37)!ER^(LUV%Z7VUQU? +M4\8KGZ7,,G!\'#F2\A!>[^60D%P1Y`ZS5FY4QO?J&1+1PQIPR'<\D!(=! +M6O,8&"A!96E+\Y]<(&9[WA-;`A8%UW6H7H_VC'MQV!\EQ)UU4QK/%^%D+1\T6JQ%BC[BZ#PO1*RY9(^[;KT4MC;X!!Q6`G7U\POR@)Z\3U[G*;P:0WC +M5*WOD/.22=R/01FP_6P2BP?J_6>Q81(/8:!R+C`KL5;\$]7#2'\V"&J-5O-W +M%&Y/K2;"B:AI#!?MFV!-`[[&^F/]GCK2QM6327\'3"IRAU1@3$$['-_Q+65M +MUA[PS@YA4C+=@4M^YQ'&HA^#R`D>JPG=&D2VQQ'[BYF^OC'A9\3@O\;1MSK= +MDJ?99,`A:,]?#'M]/&U<1GM`T@T@TM@''Y_$QR3X$\$;P8[/3SB'$%!K(B-7<]VGKUE +M11@TL4M"[CUQ,A;0UM>"8$BSGTT$K(9>B,F9)/=83+VP%.#%"O:VS8O;L[,MW0/CCN$-M*9RC243]BD@L^"2W+S9++RM]S?[8"W& +M).N^%W9)4FD(O^<;S'HR$]F=36OP`0Y(9@WP9`J.@,-(2#690*ZB*Q!Q6)0A +M6YA`;934.&@3R5>"(9*A#V*BGJ3Y>1)F/9+\EF6>J6G/2?_D%>_OU3IP[,-! +M"3!QFKQ^\<*ZKCJ:E#5YDL@6`J4QM)VD]Z31N=FNO<6"6?[F9X?I/),9*VL3 +MJ%%TJD1O8IHVGQ.K`JWV)<8S@3[VJ#@A)ZA-@MH-\Y1()">3,E]L9Z)[>$W4 +MB\:HS8IHITMB\ZH)57TH7MTV[#82L6.$@#=9Z[QAD_-I$/J.>\V<:!@^&:.8 +M*U?]%'/RC?FG<_W`ES&M$KMH9E+V`N7*/9&+ +M6@:)9K,>VQC?8B^>6!\5ILTZ?2UF`IPP)1LD_;@K!EOI(S6Z;#@)6STENA"P +MQ([!IGE%OD8Y_WI>;SRW*/4VB'M$,F%69;<,?MTWZ:+LR0I%DF01!"2*HV]V +M..HF&,;?9V,PF\R.+1.&!!XG!Y..IBQ\_TQ>+L]S/$-_Q +M6[RR7E363IA+-O0^[:1 +M$T1@%1`"RQJ5O6`ZQ[?9'1>#CQ3T$>)M-U,E`F82=2>*!$,;/2H7:>=>S9R- +M9+NH6DD0B"6@+9+7)Y%#!\!A61\D%4KB9/GR&BHFX1A[Y3H^89<3\Y]OR"%7 +M1$/&(/@L")%89`[.AG`I+2V0S@*HCZ3=W#_EI`H8"XCG,3")C6().^S#US#- +M-/.]^NNZ/0'IB7T4EX38V5BT=Q3\S9HHZ;4?6]O6S(:*3"/Y(+QK""\P/*2; +MM9IZ3K>)X0(;MH0CA.K!EUY3)L02!X!4[YY1OJ%2CF>P##;OIY%6-)EQE'Q> +MD.)@?QH*5\_&"+!4FJ3#B&B/1!EPE(#VVV81"\01Z-(K[NOQ=[HK,?MP!CEE +M+(T&]S6C'VG>0-7AB,LN0RBU6 +MB@6P$;/H4$8FB(K#`D+:HP3BL80)21V0F;R#1&\V^/8 +M=:Y:I'%/V09;B<4JS^*B>5TU4M&78QL:@+N$L+O@XA**B--`)A4;R.N%/H?` +MY$C22.A>:>2&-1BH6@VP9EY[%?-Z79B6;9?1=&&:R`N*B]8PHV\%M9#NP+_3 +M_V?T__TV7!.0_&%%-:'_Z%"+Y8+%QO6E"O_\O%X5_%FV'8<*L82!T)'`=9.( +M+,"LC5^9ZCQ-U<"99CBX#-[O&V+9 +M-'Y?@?72P6'&X-F8RX:4Q!7I>E3:GY_F05#F*E30.'HWM`X;?0?RAM)'2J&Y +M8L$P3!_I1D]2<^J[5:?^O#">;2GC$A>S;5578*]P!2H;%DAO +MUNYZHYD)0.'&G7NAZ"7X$PP;[&(2[AS,-\0=+"H6,=DCO&HTTA)S= +MOT:35LLM8@PX4$*0V:8MJ-]!N!`1,H@#3^K@M;3CAC/_'6Z.1FKR,&8=1'$Y +M4MX;%R]%V``5C;[#IIVR,4SZ,7_>.WVOX6>-F_>ZSWLO2_=YWZ4=^7:'0HJ% +M?=^ +M!F=)OP:3]IJ;6XNI)6ED>[!22+<4TTB^D424:C6Z24+$:TBB2W[73E1]3!_C +M\=@)OKGT)F4?N68V?A80Z*PQASH(-"FW]]=;J5 +MPQ[=;E)6:8,EBY"%_59`?<@0V6XB&:LY>AD#=6=RF4DK*P7.C$O@VAV8*(MMU7L%Z_: +MAQCB+BF;J/VE4EQ#_,DZW88-TRS"QO']R')].>QJ&/5B`LZ;P<&OQYP*[]"H*\[S): +MM%-[QDO$\_"FGJL;L1X.;00>3E/"&':4W=OTQ36:A7&QB^P:]Q^F6D>K7A@" +MFUN#S`(:PA]8![&)+9D!2JR!M$5(M%XS>K.[37/`;RID#Q-6?299JY@>P +M5SB'JG8-R1@VD#N1%(+BJ!5E)"(+@HQO;L',]ET,6D:E8+W%2N0ZK\:+RO%R +M\\K:Y6-",CUJ_TU@](!,U11+.,E!$Y-B2JAK$YMP<]5$LF$"(F?IK>(@$N&39=L@E'&66FM>H5&RIZKH'%N?HD^ +MNY?)+PC:#C8U`@FVB2V5@-A\+M8G?E)11MVM&M51L)`*LV_;M1U.8WB7DT*\ +MK7'LS#A'\DM&?]?7-IO&6!_E3",PW!$KSJH$"%TB8MD'[C?JC9>D3HI43&,QR7)+XVG.HT+$;&1,#_=.1R[KPJ4#)LEX +M'&ER(P@Z[.3(UEB#Z]H.T"%VG$4H@T@DWT9L5>??9::[%J^1T5"K"7VM6:(E +M'(.CM^"^GEB[G*8E'52QT)-.( +M:?MH?0TR4#A*AJ'*@6Q,RD7=FL"6JI/?RV]%8\_=BGGB[L229-<2V<+)B`W$ +MXOCGB%X-$)&^6OG9"#X.%)BEB5JLKXE[P<4&>`));=%X1Z[!3%I.+E!3Y37P +M9TA9-&CR2,LPW)P(T0-7,S.A*C(S.-@8*)*W$(0J82$:0CUAAE2R=BD8V:&! +M'[=4U47D,[OTV-GH*#3*A;`Q49;X-.*RD^Q#9YLSY#P@5YJ`2CV);5\""3@N +M%393/A8KQ;0?$6F`>\74+%<&1,]ZMPKM&_FSSMJ=$&]YD/P*CJ9BS%-!3/&6 +MTT9"\2V#M7.P#U2\5$MRI1KQ#?=3P)6&>:-"#A"`LU@'QQZ]2TF8_:LF0.:D +M_I!]+F(_,GY#8#9-OOY:TU98;).!X#GM59H%=`!+'<^1RO7,?1>7U^PH4A*,@&/PEE:[38F +MU&1>1YP['L^TPH@5UY,14)*NQS"&5)[9YI&Q5Z&`-'*V>6YHI0IC$LHHCL+: +M*[>8-EQ[>KX=)W@F'`[<9?6SYIR3Q0C)FS4YC"27<"3!(#+Y.X^1D6SAQ)2G +M0^'ID:O!>H*8BDAH63MA(H`0%MTG?@!BDA90>6\4B0]"WZVMYD+%D`K+S:29DNH#_DE:%E)*> +MNL^M,CI-9HSKFD/Y:#*1R\UG#5=J6CO+?L($U$0I]\;D@-AD1=I?4RL_E^P\ +M/X0KY'##<@FNT=G+GT0C)\$Y]D-CP$M)3L@K+^Q%5>L>%_A=7[M(II9J,S2XWF),9GGVGZ>$;O"\;PG[F?A3=76)CW3!-#G?[KE-T +MQ0!.W)#$"9`UWF541I8D[,>(XVW2'&43=RS,^J3;=\+N(S$K9.!W88?IF6,I +M)R&DOC8*V_T\(\.3R-ZLB3EFE7YY/JD,\PM?F*F9J`A3L!NID=,P]- +MJLWUM&.]3^>1;IM/Z:RS;<(&-:^]_([0?`MT+FO(^^W0EIU<*H4;\:XA*?5< +M"GW)4"]=*<-E0^U<80!'K1"W&$%#'FFBZP2(5,>;NXX8P(1-; +MI&)4]0:#1)H'=;(:3JVSXR/)*L"8H7FX1RL0L=K.Q9^^A4^"42Q-A$3/!"]@ +M\"695?;MC./0WS%2T4+W;+90O"BT8>+[*&357+&3M% +MGMCD&9J\#\UICT>2BD(7CV<*[+1O*DGOG.^';D"],)3XRAR4YKO"ER>YOY>: +MCOU$P&.7H:'2]P"G-HRWU$6M5%RB.-C$N#;=3FMINHO/A3I1*SKH';=ZF!:* +M";_+Z9G+#N/U;"2'1/Q[2[>WDJ#NYK?7M@M:R/#@AT:B"8#)*<;XEL2#*>U# +M/TEZ>O@YH))CB$H?S`]5^R(D#4T8:+GS:K?3<-@*-WR9X[@XKM/6D;5)\%U0 +M?X1>(I@I\*V^MP?TUB)EUILFU)>?P4V2X!ZU)";\3ZY!-I[$7^FB]XLQJR63 +M/2A,UC:48/4!7*@VAI`U02=:38(BVY>IH?`VSB>.^DFP<3((AU'T%*4;B)DD +MKO$?_UL0.Y)RG,,HR\!E",K\MAS:UQGFXG+K+]T)YY7[81J^]G4,"TK",G,N&[?H/LP3'J;6V:H +MABH/%(:TS6&VV3W@1_(X;]-(?W3B6;J#9MB9JCPA1'D$Y1*AJ"7W-3/F,)P\ +MXI4_\9^8V94KFC2[O<+L['5Z3Y)B-[..*N8R1WH3X'6IZ^;AS5W[^/#V^OCN +MXO+H\H;^DYM-S+C80!^'E`S_U%X$3;,`,[=<39;9$41YXD=1:$MZ"+//UWHP +M3S-1(Q4(--]5<$-N$0FA6C1RKK6&?<`T/D05`MVK*L&KX\8S$8VKP`K +M;5':?#EPFSJ@R&LVZ>KX^IPG:;ZX_'1Q?+T=1%S=1%WM8F8PW+9]VY*:+6W0 +M%[@L-*9XOVKZCFZ0;]=D*<--%^=[N\&HMY$A*%X[Y>$E-:IK!393)"8(WHO4 +M,!.CDH3XB4F%%E/OU^5L-UA=IUY)G5J_E7"[R;WY8B,7'#V_D!?YA63M2FRC +MI`X;RX)Q"L/A;A^C2E62@/-H4B,=-C9%]27O0TI%EIAVYXO%`)!YOD^-O+!* +MLBA+4MG?609A!0\V6[W%2%$2KYDIE2"\D4T[FRBA0?0^$DM4SAAB`-(22#KK +MV)PXFH&0"?4DR?A;VW9J"&Z:Q#WA39R*L,.I"0C]@@L,'K!!DCR2X,J`-DWM +MV]RAAEP5C@MS??[\>7,K*\TE'SN#))QN*4KNEL?M[H;[^9-\73Q(W6MS@HX% +MCIUY@EFI92CL!T7M#2YYGIH\.XX8YQJI66:S^D.@_RH_:T,PLT^294D%62:O +M)AGEKJ6841F`C!B/OB8#/E-S0J+::`U45J@,%M0AO;-/M*N2&&<@?8>`C?.G +M,8&_B9:9EL+EJ:2,/64V/VN4UR#R;!N=!:LGO\)OYJY)%B/*%`>"FB=\'^/Q +MYI93ODI\!5G55N?AN<)$LF+-TH:E"%$2V9BGMJDLE%U.EF?BQ$BAF]J2U+(N +MNNCSTWI.(+E..JA+W>[&L\=UDSMO,\Y5!,$-%4N2>L6%+[_((6EC/D+"-GL_ +M&XYMA7U$[=7W;2A6:^?2%E67@('GIANL>NK+PP;BX3W7PE'1JU`GTP:^F)LA +M"`Y50L,4P@'7?1?Q%]7`V:#+PJ,8.N#N!$UD5E6SY\AY7>)S5NMI<4?VZ@>. +M])1O>#F;V^`[OU;V7\N"2XE$:8L^R-E$QF?/\7WO>C^&=0" +MNH8V/Z_UC%D-;@9,-D\<=+1N3!7$AE8TT@.*'$6`W.6,V6$[,)H6X?04_QO9P.ODLC +MI@`GUD_3#S3!1XNTNVD^%A,2#DZ'-F"48C&]YAFAOA<@WD08:*1^J4'SL +MC>PFJ[$^'X^9Z0'\FH`\>2Y38[U`+FCNW0PG0HWUM(;9'D:A@O$D^Q6;5QN7 +M2-T28L'IB'-5O3&I^<)R3%RT)N.N@0\E_.+XDU3U?XL_!S9D5:I7/TB(H-8D +MX*`@T!!-FFD]@YEZPDKU8T1W5,/U:#]F8S!1KCMX[;:EUZ777'"E8$#9!Y40S,*EFU+>;H1.4@:C="]==UHS9%K*/K@\^< +M&IEDO*47P=IF*UJJT?*%+>C\;#I^9L9A5@PE/@3Q0<9F*)HW\)H8A3SJF9J4 +M0&;B7+I'2UP:@?L%8E.)!1!,)E:%*E//E"G7HI+TJG4E\F65FS:GBB"WUOL_#'*H&QA<.16[9Z&H +MK#':L>ZP;X_34&,YTS<.%Y3J95P`4?S7RO:VQ>*%@:_"[\[):P4F5!.H<_DV +M(4D'!<\.GYZ>NO,6D!.KXCA70*0S]\K;7,$K4^NJ\Y27D4V=*AE#:EP!$(>G +MI72%AMS]WQ'`RR5I8.2PAEZ=659MZR$B'10%W8NK8IF-C2DY!U&NSF*Z)J%Z4FG?\5\2E&)A'^,4BWKE6.;4\7K#K\U(_%)_ +M-/L6C_;WZFDRFW3!O(A3CJ+ICNO@.7`*AOX>CW?H_Q?/2UPO1R&2B;G2;!#4 +MSG9J#W(5OFL^>O[^YBC)P9M2I8H5%"?13&2_1)B.J?9!-YHE`7$5!EJIU/RF +M&13G[[>*`]*G[BP-3J.XK]8T:V:!($#H-3`6*J=R7;9WW]-1/*B36M6)Z!8C +M\`MP=W;W=NA/;5X;QM.:4^D%GJ5))R(T'^T`5$:1]241]JT+TR8JROMVR7H# +M>A_2OGZ@JW9.HNMG9R9#^OP]-Q.H@8_39"S%0:&IK>=MLR".\F\-B%.3)#YQ +M'PUX=Q3J`U3FNA15Q/1^N8RO>?*"1$J6K/5_Z-\53$I7H#:0`HU'$!)%"6; +M^+B)7)0X6HN%N91:.WV.>'IE!M=[!HQE.JWO"6\''ZYJMY^W\1K.]V]$*;8# +MJ6;1MZ8M#BSHY2."_B]02P,$"@``````O'MF0>I8ZGT7````%P````@`'`!B +M=6EL9"YS:%54"0`#8ZZ84,8XFE!U>`L``03U`0``!!0````C(2]B:6XO`Q0````(`!*<9T$V32@KLU<``&H^`0`%`!@` +M``````$```"D@0````!F:6QE,%54!0`#Q#B:4'5X"P`!!/4!```$%````%!+ +M`0(>`PH``````+Q[9D'J6.I]%P```!<````(`!@```````$```#M@?)7``!B +M=6EL9"YS:%54!0`#8ZZ84'5X"P`!!/4!```$%````%!+!08``````@`"`)D` +M``!+6```M094:&ES(&ES(&$@FEP(&-O;6UE;G0N#0IA86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A#0IA86%A86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A +M86%A86%A86%A86%A86%A#0IA86%A86%A86%A86%A86%A86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A +M86%A#0IA86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A#0IA86%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A#0IA86%A86%A86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A +M86%A86%A86%A86%A#0IA86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A +M#0IA86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A#0IA86%A86%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A86%A#0IA86%A86%A86%A86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A +M86%A86%A86%A#0IA86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A#0IA +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A#0IA86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A#0IV#0IA86%A86%A86%A86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A +M86%A86%A86%A#0IA86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A#0IA +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A#0IA86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A#0IA86%A86%A86%A86%A86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A +M86%A86%A#0IA86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A#0IA86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A#0IA86%A86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A +/86%A86%A86%A86%A86%A +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_encryption_data.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_encryption_data.c new file mode 100644 index 0000000..b56d78e --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_encryption_data.c @@ -0,0 +1,79 @@ +/*- + * Copyright (c) 2013 Konrad Kleine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_read_format_zip_encryption_data) +{ + /* This file is password protected (encrypted). The headers + are NOT encrypted. Password is "12345678". */ + const char *refname = "test_read_format_zip_encryption_data.zip"; + struct archive_entry *ae; + struct archive *a; + char buff[128]; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + assertEqualIntA(a, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW, archive_read_has_encrypted_entries(a)); + + /* Verify encrypted file "bar.txt" */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0664), archive_entry_mode(ae)); + assertEqualString("bar.txt", archive_entry_pathname(ae)); + assertEqualInt(20, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_is_data_encrypted(ae)); + assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); + assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); + assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, sizeof(buff))); + + /* Verify encrypted file "foo.txt" */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0664), archive_entry_mode(ae)); + assertEqualString("foo.txt", archive_entry_pathname(ae)); + assertEqualInt(20, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_is_data_encrypted(ae)); + assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); + assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); + assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, sizeof(buff))); + + assertEqualInt(2, archive_file_count(a)); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_encryption_data.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_encryption_data.zip.uu new file mode 100644 index 0000000..d419e7d --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_encryption_data.zip.uu @@ -0,0 +1,25 @@ +begin 664 test_read_format_zip_encryption_data.zip +M4$L#!#,`00```*UI,4/H*IFA5@$``!0````'````8F%R+G1X=!``2#/PIQFT +M*F$4U*$#L8[-?B`!```#`!!F``$!`)``[SL/J;#"+JV#-X^_V7R?(/NINR^)*Z@-`+PM+G'_/G,@= +MOQI>T\*I"7FDH^[+/([/S3(S=2JR^B1VT7NV=\PU*ILZ(S-9P@#K>HTK<9$X +MG?3>):QUHT4^7JY*;B_X.,6FCSB0]-;K-:!W"\9#7%JT`````(``I>M3N%RW +MKHT3'HV+V7'\SG*),5W`7P-"J01^*X5F-K&;`\FXL%S[!!"J1 +M?4B:)(8&4)C/_^4!TF+`7W`%52=)VJ9U?3H,W@"9S8062TGSY_<:.\=X_SCC +M1?,I!IE@=&J39?KX5+0Y\Y`;^.[MR@]TB?WG-.D/]RONSJ(6 +MMAL3^^^V;)?](;*EA#%$TN]?2U!+`P0S`$$```"J:3%#_\P&4E8!```4```` +M!P```&9O;RYT>'00`(N/OW)U+.F;D#0D]']<[0I5,5G^P3D\Q/LN'ME\GR#[J;LOB2NH +M#7-Y7/%J"13'@"\+2YQ_SYS(';\:7M/"J0EYI*/NRSR.S\TR,W4JLOHD=M%[ +MMG?,-2J;.B,S6<(`ZWJ-*W&1.)WTWB6L=:-%/EZN2FXO^#C%IH\XD/36ZS6@ +M=PO&0UQ:M`````"``".OX15'_!K.OGAW6+M]C;[G8@26,FBSB&/46Q@#[301 +M`"51%C)3[11_TP#)7O_6`&/F?FGG]G9;W.L$";H2&[ +ML$PNS#NDG9Q@BFL$`&S?S3;,D#OS#% +MZ>O6I=M41I^&XX"JLTTKLW]*B=+>(C]+6]H**#DX_EJ;9BBY;,=02P$"0``S +M`$$```"M:3%#Z"J9H58!```4````!P`T```````!`"``````````8F%R+G1X +M=`H`(````````0`8`".@Q.V6L\X!(Z#$[9:SS@$CH,3MEK/.`1<`#``"`!!F +M``$!``````!02P$"0``S`$$```"J:3%#_\P&4E8!```4````!P`T```````! +M`"````![`0``9F]O+G1X=`H`(````````0`8`"4C6.F6L\X!)2-8Z9:SS@$E +M(UCIEK/.`1<`#``"`!!F``$!``````!02P4&``````(``@#2````]@(````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_encryption_header.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_encryption_header.c new file mode 100644 index 0000000..f40e1f5 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_encryption_header.c @@ -0,0 +1,71 @@ +/*- + * Copyright (c) 2013 Konrad Kleine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_read_format_zip_encryption_header) +{ + /* This file is password protected (encrypted) with AES-256. The headers + ARE encrypted. Password is "12345678". */ + const char *refname = "test_read_format_zip_encryption_header.zip"; + struct archive_entry *ae; + struct archive *a; + char buff[128]; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + assertEqualIntA(a, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW, archive_read_has_encrypted_entries(a)); + + /* Verify regular file but with encrypted headers + as a consequence, all meta information is invalid. */ + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); + + assertEqualInt(0, archive_entry_mode(ae)); + assertEqualString(NULL, archive_entry_pathname(ae)); + assertEqualInt(0, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_is_data_encrypted(ae)); + assertEqualInt(1, archive_entry_is_metadata_encrypted(ae)); + assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); + assertEqualInt(ARCHIVE_FATAL, archive_read_data(a, buff, sizeof(buff))); + + assertEqualInt(1, archive_file_count(a)); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_encryption_header.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_encryption_header.zip.uu new file mode 100644 index 0000000..8ba23d3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_encryption_header.zip.uu @@ -0,0 +1,32 @@ +begin 664 test_read_format_zip_encryption_header.zip +M4$L#!#,`02``````````````5@$````````!````,1``X3'*9,%K7_13)[I3 +MUO.*N2`!```#`!!F``$!`)``M'BJYI=VDZMXC4&]B1)Q%WJ/M`8VS +M%S*.0\5[MJ34[W"H8*AO==S@TG'S'J'3A;8C`````(``4-?ZX*L^`*0786KZ +ME7<\#%<[_`^#/MO"P\3FX5`^9`Q%(S:FDO98B*C`BC%'XQ0*X"FMO8[@3'S@ +MX(JO5(Q:8-&AM8(OPBY40\O!"%Z5'>I\/<_(AA-%)*TBI6YT6!WEM7L,-"W( +M/GE:7T.B39$3C.W)X2`A=KV-UB4C7I?6B-!F<"?VLE!+`P0S`$$@`````````````%8!`````````0```#(0 +M`%(U7N:0Z+,VS3SNJBRE_=`@`0```P`09@`!`0"0`+1XJN:7=I'+8EUNW[TZ +M9--K0QS.:Q+!FI.`8[!4$,6L*CF!QS:J1.BO`?`/13>YAU`IT$;$9 +M?;.\]/UPBB3_SV=KT;*]:?(9JYM:X+6&:R4J*4S0N)^KE,\XI>AO)H,GWNK> +M(U!O8D2<1=ZC[0&-LQ[:DU.]PJ&"H;W7CYF;:)G.8S3 +M%AT<])L+^"37+I@-S&ALBA\_10'AM,+6C"RP!FEV@VW1"2PDL->Q5HL*M[X( +M];^?-43F%4=UMP/U>83:C4K&OM*'&=DS[_V!*YK9X(6G9R,]GJ\\0`!A&@I%F4R!H=;RQSVWL,/D@ +M`0```P`09@`!`0"0`+1XJN:7=I'+8EUNW[TZ9--K0QS.:Q+!FI.`8[!4$,6L +M*CF!QS:J1.BO`?`/13>YAU`IT$;$9?;.\]/UPBB3_SV=KT;*]:?(9 +MJYM:X+6&:R4J*4S0N)^KE,\XI>AO)H,GWNK>(U!O8D2<1=ZC[0&-LQ[:DU.]PJ&"H;W7A2^EL1N!T3'%DP<< +MXY=DJB$8LS8KERBNN[I*X]M"?A\FYX"B`IP_XMQ-.*H3#`XY.,-K% +M0`Z%4:U*W#IM_DBOP-$^?R<8,!%#Z6F1`?;Z:=LG6@'C+#0I[]^+E$0'L5!+ +M!@9,`````````$``/@```````````````````````@````````"F`0`````` +M`.H"````````"`"F`0```````-(`````````$&8``0$``0`$``"$P.)02P8' +F`````)`$`````````0```%!+!08```````#__Z8!``#J`@`````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_encryption_partially.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_encryption_partially.c new file mode 100644 index 0000000..77af235 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_encryption_partially.c @@ -0,0 +1,79 @@ +/*- + * Copyright (c) 2013 Konrad Kleine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_read_format_zip_encryption_partially) +{ + /* This file contains one file that is encrypted (foo.txt, password=12345678) + and one file that is not encrypted (bar.txt) The header is not encrypted + on this file. */ + const char *refname = "test_read_format_zip_encryption_partially.zip"; + struct archive_entry *ae; + struct archive *a; + char buff[128]; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + assertEqualIntA(a, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW, archive_read_has_encrypted_entries(a)); + + /* Verify unencrypted file "bar.txt". */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0664), archive_entry_mode(ae)); + assertEqualString("bar.txt", archive_entry_pathname(ae)); + assertEqualInt(20, archive_entry_size(ae)); + assertEqualInt(0, archive_entry_is_data_encrypted(ae)); + assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); + assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); + assertEqualInt(20, archive_read_data(a, buff, sizeof(buff))); + + /* Verify encrypted file "foo.txt". */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0664), archive_entry_mode(ae)); + assertEqualString("foo.txt", archive_entry_pathname(ae)); + assertEqualInt(20, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_is_data_encrypted(ae)); + assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); + assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); + assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, sizeof(buff))); + + assertEqualInt(2, archive_file_count(a)); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_encryption_partially.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_encryption_partially.zip.uu new file mode 100644 index 0000000..ac19d31 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_encryption_partially.zip.uu @@ -0,0 +1,18 @@ +begin 664 test_read_format_zip_encryption_partially.zip +M4$L#!`H``````*UI,4/H*IFA%````!0````'````8F%R+G1X=")D871A(&]F +M(&)A'0B(`T*4$L#!#,`00```*II,4/_S`925@$``!0````'````9F]O +M+G1X=!``=Y31BJ>9'GG$*/<^F6_&OGLZO5E%/W5NJ591,`8BB:/5/7M)AK8/IJ0=@ +M`````(``QS1<"+$&V4,T_.3PQ&HBEXWEA;,\K(U'9+L4P +M=:(P%7DH*U7(2#M.IB;M\7X??Y!F]%PMN<#((2`+)9A+<(W[1K0X@&5:`QJV +MQ:NR:QT5U'+D!K^/_N*M>SJ-)-^@^N6]4VD&Z@L#X(!-7@-6#-G3WV`1:PL" +M!4FWNU]+#`:$,2UI5U`@#@BY.)#$HP6(2`PH``````"-=CTW$\L?V`@````(````! +M`!@```````$```"D@0````!A`````%54"0`#TE@57-M8%5P```0``````$L% +3!@`````!``$`1P```#T````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_filename.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_filename.c new file mode 100644 index 0000000..4dd2e8a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_filename.c @@ -0,0 +1,1224 @@ +/*- + * Copyright (c) 2011 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD"); + +#include + +DEFINE_TEST(test_read_format_zip_filename_CP932_eucJP) +{ + const char *refname = "test_read_format_zip_filename_cp932.zip"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read CP932 filename in ja_JP.eucJP with "hdrcharset=CP932" option. + */ + if (NULL == setlocale(LC_ALL, "ja_JP.eucJP")) { + skipping("ja_JP.eucJP locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=CP932")) { + skipping("This system cannot convert character-set" + " from CP932 to eucJP."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString( + "\xc9\xbd\xa4\xc0\xa4\xe8\x2f\xb0\xec\xcd\xf7\xc9\xbd\x2e\x74\x78\x74", + archive_entry_pathname(ae)); + assertEqualInt(5, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString( + "\xc9\xbd\xa4\xc0\xa4\xe8\x2f\xb4\xc1\xbb\xfa\x2e\x74\x78\x74", + archive_entry_pathname(ae)); + assertEqualInt(5, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_filename_CP932_UTF8) +{ + const char *refname = "test_read_format_zip_filename_cp932.zip"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read CP932 filename in en_US.UTF-8 with "hdrcharset=CP932" option. + */ + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=CP932")) { + skipping("This system cannot convert character-set" + " from CP932 to UTF-8."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); +#if defined(__APPLE__) + /* Compare NFD string. */ + assertEqualUTF8String( + "\xe8\xa1\xa8\xe3\x81\x9f\xe3\x82\x99\xe3\x82\x88\x2f" + "\xe4\xb8\x80\xe8\xa6\xa7\xe8\xa1\xa8\x2e\x74\x78\x74", + archive_entry_pathname(ae)); +#else + /* Compare NFC string. */ + assertEqualUTF8String( + "\xe8\xa1\xa8\xe3\x81\xa0\xe3\x82\x88\x2f" + "\xe4\xb8\x80\xe8\xa6\xa7\xe8\xa1\xa8\x2e\x74\x78\x74", + archive_entry_pathname(ae)); +#endif + assertEqualInt(5, archive_entry_size(ae)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); +#if defined(__APPLE__) + /* Compare NFD string. */ + assertEqualUTF8String( + "\xe8\xa1\xa8\xe3\x81\x9f\xe3\x82\x99\xe3\x82\x88\x2f" + "\xe6\xbc\xa2\xe5\xad\x97\x2e\x74\x78\x74", + archive_entry_pathname(ae)); +#else + /* Compare NFC string. */ + assertEqualUTF8String( + "\xe8\xa1\xa8\xe3\x81\xa0\xe3\x82\x88\x2f" + "\xe6\xbc\xa2\xe5\xad\x97\x2e\x74\x78\x74", + archive_entry_pathname(ae)); +#endif + assertEqualInt(5, archive_entry_size(ae)); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_filename_UTF8_eucJP) +{ + const char *refname = "test_read_format_zip_filename_utf8_jp.zip"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read UTF-8 filename in ja_JP.eucJP without charset option + * because the file name in the sample file is UTF-8 and + * Bit 11 of its general purpose bit flag is set. + */ + if (NULL == setlocale(LC_ALL, "ja_JP.eucJP")) { + skipping("ja_JP.eucJP locale not availablefilename_ on " + "this system."); + return; + } + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=UTF-8")) { + skipping("This system cannot convert character-set" + " from UTF-8 to eucJP."); + goto cleanup; + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify directory file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualString("\xc9\xbd\xa4\xc0\xa4\xe8\x2f", + archive_entry_pathname(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualString( + "\xc9\xbd\xa4\xc0\xa4\xe8\x2f\xb0\xec\xcd\xf7\xc9\xbd\x2e\x74\x78\x74", + archive_entry_pathname(ae)); + assertEqualInt(5, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualString( + "\xc9\xbd\xa4\xc0\xa4\xe8\x2f\xb4\xc1\xbb\xfa\x2e\x74\x78\x74", + archive_entry_pathname(ae)); + assertEqualInt(5, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_filename_UTF8_UTF8) +{ + const char *refname = "test_read_format_zip_filename_utf8_jp.zip"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read UTF-8 filename in en_US.UTF-8 without charset option + * because the file name in the sample file is UTF-8 and + * Bit 11 of its general purpose bit flag is set. + */ + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify directory file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); +#if defined(__APPLE__) + /* Compare NFD string. */ + assertEqualUTF8String( + "\xe8\xa1\xa8\xe3\x81\x9f\xe3\x82\x99\xe3\x82\x88\x2f", + archive_entry_pathname(ae)); +#else + /* Compare NFC string. */ + assertEqualUTF8String( + "\xe8\xa1\xa8\xe3\x81\xa0\xe3\x82\x88\x2f", + archive_entry_pathname(ae)); +#endif + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); +#if defined(__APPLE__) + /* Compare NFD string. */ + assertEqualUTF8String( + "\xe8\xa1\xa8\xe3\x81\x9f\xe3\x82\x99\xe3\x82\x88\x2f" + "\xe4\xb8\x80\xe8\xa6\xa7\xe8\xa1\xa8\x2e\x74\x78\x74", + archive_entry_pathname(ae)); +#else + /* Compare NFC string. */ + assertEqualUTF8String( + "\xe8\xa1\xa8\xe3\x81\xa0\xe3\x82\x88\x2f" + "\xe4\xb8\x80\xe8\xa6\xa7\xe8\xa1\xa8\x2e\x74\x78\x74", + archive_entry_pathname(ae)); +#endif + assertEqualInt(5, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); +#if defined(__APPLE__) + /* Compare NFD string. */ + assertEqualUTF8String( + "\xe8\xa1\xa8\xe3\x81\x9f\xe3\x82\x99\xe3\x82\x88\x2f" + "\xe6\xbc\xa2\xe5\xad\x97\x2e\x74\x78\x74", + archive_entry_pathname(ae)); +#else + /* Compare NFC string. */ + assertEqualUTF8String( + "\xe8\xa1\xa8\xe3\x81\xa0\xe3\x82\x88\x2f" + "\xe6\xbc\xa2\xe5\xad\x97\x2e\x74\x78\x74", + archive_entry_pathname(ae)); +#endif + assertEqualInt(5, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_filename_CP866_KOI8R) +{ + const char *refname = "test_read_format_zip_filename_cp866.zip"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read CP866 filename in ru_RU.KOI8-R with "hdrcharset=CP866" option. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia.20866") && + NULL == setlocale(LC_ALL, "ru_RU.KOI8-R")) { + skipping("ru_RU.KOI8-R locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=CP866")) { + skipping("This system cannot convert character-set" + " from CP866 to KOI8-R."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xf0\xf2\xe9\xf7\xe5\xf4", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\xd2\xc9\xd7\xc5\xd4", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_filename_CP866_UTF8) +{ + const char *refname = "test_read_format_zip_filename_cp866.zip"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read CP866 filename in en_US.UTF-8 with "hdrcharset=CP866" option. + */ + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=CP866")) { + skipping("This system cannot convert character-set" + " from CP866 to UTF-8."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\x9f\xd0\xa0\xd0\x98\xd0\x92\xd0\x95\xd0\xa2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\xbf\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_filename_KOI8R_CP866) +{ + const char *refname = "test_read_format_zip_filename_koi8r.zip"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read KOI8-R filename in ru_RU.CP866 with "hdrcharset=KOI8-R" option. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia.866") && + NULL == setlocale(LC_ALL, "ru_RU.CP866")) { + skipping("ru_RU.CP866 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=KOI8-R")) { + skipping("This system cannot convert character-set" + " from KOI8-R to CP866."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xaf\xe0\xa8\xa2\xa5\xe2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\x8f\x90\x88\x82\x85\x92", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_filename_KOI8R_UTF8) +{ + const char *refname = "test_read_format_zip_filename_koi8r.zip"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read KOI8-R filename in en_US.UTF-8 with "hdrcharset=KOI8-R" option. + */ + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=KOI8-R")) { + skipping("This system cannot convert character-set" + " from KOI8-R to UTF-8."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\xbf\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\x9f\xd0\xa0\xd0\x98\xd0\x92\xd0\x95\xd0\xa2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_filename_UTF8_KOI8R) +{ + const char *refname = "test_read_format_zip_filename_utf8_ru.zip"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read UTF-8 filename in ru_RU.KOI8-R with "hdrcharset=UTF-8" option. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia.20866") && + NULL == setlocale(LC_ALL, "ru_RU.KOI8-R")) { + skipping("ru_RU.KOI8-R locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=UTF-8")) { + skipping("This system cannot convert character-set" + " from UTF-8 to KOI8-R."); + goto cleanup; + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* Re-create a read archive object. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xf0\xf2\xe9\xf7\xe5\xf4", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\xd2\xc9\xd7\xc5\xd4", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_filename_UTF8_CP866) +{ + const char *refname = "test_read_format_zip_filename_utf8_ru.zip"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read UTF-8 filename in ru_RU.CP866 without charset option + * because the file name in the sample file is UTF-8 and + * Bit 11 of its general purpose bit flag is set. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia.866") && + NULL == setlocale(LC_ALL, "ru_RU.CP866")) { + skipping("ru_RU.CP866 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=UTF-8")) { + skipping("This system cannot convert character-set" + " from UTF-8 to CP866."); + goto cleanup; + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* Re-create a read archive object. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\x8f\x90\x88\x82\x85\x92", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xaf\xe0\xa8\xa2\xa5\xe2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_filename_UTF8_UTF8_ru) +{ + const char *refname = "test_read_format_zip_filename_utf8_ru.zip"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read UTF-8 filename in en_US.UTF-8 without charset option + * because the file name in the sample file is UTF-8 and + * Bit 11 of its general purpose bit flag is set. + */ + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\x9f\xd0\xa0\xd0\x98\xd0\x92\xd0\x95\xd0\xa2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\xbf\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_filename_CP932_CP932) +{ + const char *refname = "test_read_format_zip_filename_cp932.zip"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read CP932 filename in CP932/SJIS with "hdrcharset=CP932" option. + */ + if (NULL == setlocale(LC_ALL, "Japanese_Japan") && + NULL == setlocale(LC_ALL, "ja_JP.SJIS")) { + skipping("CP932 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=CP932")) { + skipping("This system cannot convert character-set" + " from CP932."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString( + "\x95\x5c\x82\xbe\x82\xe6\x2f\x88\xea\x97\x97\x95\x5c.txt", + archive_entry_pathname(ae)); + assertEqualInt(5, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString( + "\x95\x5c\x82\xbe\x82\xe6\x2f\x8a\xbf\x8e\x9a.txt", + archive_entry_pathname(ae)); + assertEqualInt(5, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_filename_UTF8_CP932) +{ + const char *refname = "test_read_format_zip_filename_utf8_jp.zip"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read UTF-8 filename in CP932/SJIS without charset option + * because the file name in the sample file is UTF-8 and + * Bit 11 of its general purpose bit flag is set. + */ + if (NULL == setlocale(LC_ALL, "Japanese_Japan") && + NULL == setlocale(LC_ALL, "ja_JP.SJIS")) { + skipping("CP932 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=UTF-8")) { + skipping("This system cannot convert character-set" + " from UTF-8 to CP932."); + goto cleanup; + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* Re-create a read archive object. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + assertEqualString( + "\x95\x5c\x82\xbe\x82\xe6\x2f", + archive_entry_pathname(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Verify directory file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualString( + "\x95\x5c\x82\xbe\x82\xe6\x2f\x88\xea\x97\x97\x95\x5c.txt", + archive_entry_pathname(ae)); + assertEqualInt(5, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualString( + "\x95\x5c\x82\xbe\x82\xe6\x2f\x8a\xbf\x8e\x9a.txt", + archive_entry_pathname(ae)); + assertEqualInt(5, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_filename_CP866_CP1251) +{ + const char *refname = "test_read_format_zip_filename_cp866.zip"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read CP866 filename in CP1251 with "hdrcharset=CP866" option. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia") && + NULL == setlocale(LC_ALL, "ru_RU.CP1251")) { + skipping("CP1251 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=CP866")) { + skipping("This system cannot convert character-set" + " from CP866 to CP1251."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xcf\xd0\xc8\xc2\xc5\xd2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xef\xf0\xe8\xe2\xe5\xf2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +/* + * This test only for Windows platform because other archiver + * applications on Windows translate CP1251 filenames into CP866 + * filenames and store it in the zip file and so we should read + * it by default on Windows. + */ +DEFINE_TEST(test_read_format_zip_filename_CP866_CP1251_win) +{ + const char *refname = "test_read_format_zip_filename_cp866.zip"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read CP866 filename in CP1251 without "hdrcharset=CP866" option. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia")) { + skipping("Russian_Russia locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xcf\xd0\xc8\xc2\xc5\xd2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xef\xf0\xe8\xe2\xe5\xf2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_filename_KOI8R_CP1251) +{ + const char *refname = "test_read_format_zip_filename_koi8r.zip"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read KOI8-R filename in CP1251 with "hdrcharset=KOI8-R" option. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia") && + NULL == setlocale(LC_ALL, "ru_RU.CP1251")) { + skipping("CP1251 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=KOI8-R")) { + skipping("This system cannot convert character-set" + " from KOI8-R to CP1251."); + goto cleanup; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xef\xf0\xe8\xe2\xe5\xf2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xcf\xd0\xc8\xc2\xc5\xd2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_filename_UTF8_CP1251) +{ + const char *refname = "test_read_format_zip_filename_utf8_ru.zip"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read UTF-8 filename in CP1251 without charset option + * because the file name in the sample file is UTF-8 and + * Bit 11 of its general purpose bit flag is set. + */ + if (NULL == setlocale(LC_ALL, "Russian_Russia") && + NULL == setlocale(LC_ALL, "ru_RU.CP1251")) { + skipping("CP1251 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=UTF-8")) { + skipping("This system cannot convert character-set" + " from UTF-8 to CP1251."); + goto cleanup; + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* Re-create a read archive object. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xcf\xd0\xc8\xc2\xc5\xd2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xef\xf0\xe8\xe2\xe5\xf2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +cleanup: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +/* + * The sample zip file was made in LANG=KOI8-R and it contains two + * files the charset of which are different. + * - the filename of first file is stored in KOI8-R. + * - the filename of second file is stored in UTF-8. + * + * Whenever hdrcharset option is specified, we will correctly read the + * filename of second file, which is stored in UTF-8. + */ + +DEFINE_TEST(test_read_format_zip_filename_KOI8R_UTF8_2) +{ + const char *refname = "test_read_format_zip_filename_utf8_ru2.zip"; + struct archive *a; + struct archive_entry *ae; + + /* + * Read filename in en_US.UTF-8 with "hdrcharset=KOI8-R" option. + */ + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (ARCHIVE_OK != archive_read_set_options(a, "hdrcharset=KOI8-R")) { + skipping("This system cannot convert character-set" + " from KOI8-R to UTF-8."); + goto next_test; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular first file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\x9f\xd0\xa0\xd0\x98\xd0\x92\xd0\x95\xd0\xa2", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* + * Verify regular second file. + * The filename is not translated because Bit 11 of its general + * purpose bit flag is set and so we know the conversion is unneeded. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\xbf\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); +next_test: + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Read filename in en_US.UTF-8 without "hdrcharset=KOI8-R" option. + * The filename we can properly read is only second file. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* + * Verify regular first file. + * The filename is not translated to UTF-8 because Bit 11 of + * its general purpose bit flag is *not* set and so there is + * not way to know its charset. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + /* A filename is in KOI8-R. */ + assertEqualString("\xf0\xf2\xe9\xf7\xe5\xf4", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Verify regular file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("\xd0\xbf\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82", + archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_filename_cp866.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_filename_cp866.zip.uu new file mode 100644 index 0000000..52c6770 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_filename_cp866.zip.uu @@ -0,0 +1,10 @@ +begin 644 test_read_format_zip_cp866.zip +M4$L#!`H``````%VEAS[,X8$4!@````8````&`!P`CY"(@H62550)``-!HYU- +M0:.=375X"P`!!.D#```$Z0,``/#RZ??E]%!+`P0*``````!=I8<^S.&!%`8` +M```&````!@`<`*_@J**EXE54"0`#0:.=34&CG4UU>`L``03I`P``!.D#``#P +M\NGWY?102P$"'@,*``````!=I8<^S.&!%`8````&````!@`8```````!```` +M[8$`````CY"(@H62550%``-!HYU-=7@+``$$Z0,```3I`P``4$L!`AX#"@`` +M````7:6'/LSA@10&````!@````8`&````````0```.V!1@```*_@J**EXE54 +L!0`#0:.=375X"P`!!.D#```$Z0,``%!+!08``````@`"`)@```",```````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_filename_cp932.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_filename_cp932.zip.uu new file mode 100644 index 0000000..90c22f2 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_filename_cp932.zip.uu @@ -0,0 +1,9 @@ +begin 644 test_read_format_zip_cp932.zip +M4$L#!`H``````/94=#Z"B='W!0````4````1````E5R"OH+F+XCJEY>57"YT +M>'1(96QL;U!+`P0*``````"W5'0^W)UO0@4````%````#P```)5<@KZ"YB^* +MOXZ:+G1X=&MA;FII4$L!`A0+"@``````]E1T/H*)T?<%````!0```!$````` +M`````0`@`````````)5<@KZ"YB^(ZI>7E5PN='AT4$L!`A0+"@``````MU1T +M/MR=;T(%````!0````\``````````0`@````-````)5<@KZ"YB^*OXZ:+G1X +7=%!+!08``````@`"`'P```!F```````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_filename_koi8r.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_filename_koi8r.zip.uu new file mode 100644 index 0000000..05c6695 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_filename_koi8r.zip.uu @@ -0,0 +1,10 @@ +begin 644 test_read_format_zip_koi8r.zip +M4$L#!`H``````+&CAS[,X8$4!@````8````&`!P`T-+)U\74550)``,>H)U- +M'J"=375X"P`!!.D#```$Z0,``/#RZ??E]%!+`P0*``````"QHX<^S.&!%`8` +M```&````!@`<`/#RZ??E]%54"0`#'J"=31Z@G4UU>`L``03I`P``!.D#``#P +M\NGWY?102P$"'@,*``````"QHX<^S.&!%`8````&````!@`8```````!```` +M[8$`````T-+)U\74550%``,>H)U-=7@+``$$Z0,```3I`P``4$L!`AX#"@`` +M````L:.'/LSA@10&````!@````8`&````````0```.V!1@```/#RZ??E]%54 +L!0`#'J"=375X"P`!!.D#```$Z0,``%!+!08``````@`"`)@```",```````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_filename_utf8_jp.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_filename_utf8_jp.zip.uu new file mode 100644 index 0000000..00c2af3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_filename_utf8_jp.zip.uu @@ -0,0 +1,15 @@ +begin 644 test_read_format_zip_utf8.zip +M4$L#!`H```@``,E4=#X````````````````*`!P`Z*&HXX&@XX*(+U54"0`# +MBEJ%3;[UBDUU>`L``03M`P``!`$"``!02P,$"@``"```]51T/H*)T?<%```` +M!0```!<`'`#HH:CC@:#C@H@OY+B`Z*:GZ*&H+G1X=%54"0`#WEJ%31KLBDUU +M>`L``03M`P``!`$"``!(96QL;U!+`P0*```(``"V5'0^W)UO0@4````%```` +M%``<`.BAJ..!H.."B"_FO*+EK9`L``03M`P``!`$" +M``!02P$"'@,*```(``#U5'0^@HG1]P4````%````%P`8```````!````[8%$ +M````Z*&HXX&@XX*(+^2X@.BFI^BAJ"YT>'155`4``]Y:A4UU>`L``03M`P`` +M!`$"``!02P$"'@,*```(``"V5'0^W)UO0@4````%````%``8```````!```` +M[8&:````Z*&HXX&@XX*(+^:\HN6MERYT>'155`4``VA:A4UU>`L``03M`P`` +;!`$"``!02P4&``````,``P`'`0``[0`````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_filename_utf8_ru.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_filename_utf8_ru.zip.uu new file mode 100644 index 0000000..9241776 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_filename_utf8_ru.zip.uu @@ -0,0 +1,11 @@ +begin 644 test_read_format_zip_utf8_ru.zip +M4$L#!`H```@``,NC/S[,X8$4!@````8````,`!P`T)_0H-"8T)+0E="B550) +M``-.G49-'J"=375X"P`!!.D#```$Z0,``/#RZ??E]%!+`P0*```(``!KI3\^ +MS.&!%`8````&````#``<`-"_T8#0N-"RT+71@E54"0`#6J!&31Z@G4UU>`L` +M`03I`P``!.D#``#P\NGWY?102P$"'@,*```(``#+HS\^S.&!%`8````&```` +M#``8```````!````[8$`````T)_0H-"8T)+0E="B550%``-.G49-=7@+``$$ +MZ0,```3I`P``4$L!`AX#"@``"```:Z4_/LSA@10&````!@````P`&``````` +M`0```.V!3````-"_T8#0N-"RT+71@E54!0`#6J!&375X"P`!!.D#```$Z0,` +7`%!+!08``````@`"`*0```"8```````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_filename_utf8_ru2.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_filename_utf8_ru2.zip.uu new file mode 100644 index 0000000..651f8b1 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_filename_utf8_ru2.zip.uu @@ -0,0 +1,11 @@ +begin 644 test_read_format_zip_utf8_ru2.zip +M4$L#!`H``````.:PCC[,X8$4!@````8````&`!P`\/+I]^7T550)``.`\:9- +MI6>G375X"P`!!.D#```$Z0,``/#RZ??E]%!+`P0*```(``!KI3\^S.&!%`8` +M```&````#``<`-"_T8#0N-"RT+71@E54"0`#6J!&357SIDUU>`L``03I`P`` +M!.D#``#P\NGWY?102P$"'@,*``````#FL(X^S.&!%`8````&````!@`8```` +M```!````[8$`````\/+I]^7T550%``.`\:9-=7@+``$$Z0,```3I`P``4$L! +M`AX#"@``"```:Z4_/LSA@10&````!@````P`&````````0```.V!1@```-"_ +MT8#0N-"RT+71@E54!0`#6J!&375X"P`!!.D#```$Z0,``%!+!08``````@`" ++`)X```"2```````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_high_compression.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_high_compression.c new file mode 100644 index 0000000..16cfbb1 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_high_compression.c @@ -0,0 +1,153 @@ +/*- + * Copyright (c) 2016 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD"); + +#include + + +/* + * Github Issue 748 reported problems with end-of-entry handling + * with highly-compressible data. This resulted in the end of the + * data being truncated (extracted as zero bytes). + */ + +/* + * Extract the specific test archive that was used to diagnose + * Issue 748: + */ +DEFINE_TEST(test_read_format_zip_high_compression) +{ + const char *refname = "test_read_format_zip_high_compression.zip"; + char *p; + size_t archive_size; + struct archive *a; + struct archive_entry *entry; + + const void *pv; + size_t s; + int64_t o; + + if (archive_zlib_version() == NULL) { + skipping("Zip compression test requires zlib"); + return; + } + + extract_reference_file(refname); + p = slurpfile(&archive_size, "%s", refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, archive_size, 16 * 1024)); + assertEqualInt(ARCHIVE_OK, archive_read_next_header(a, &entry)); + + assertEqualInt(ARCHIVE_OK, archive_read_data_block(a, &pv, &s, &o)); + assertEqualInt(262144, s); + assertEqualInt(0, o); + + assertEqualInt(ARCHIVE_OK, archive_read_data_block(a, &pv, &s, &o)); + assertEqualInt(160, s); + assertEqualInt(262144, o); + + assertEqualInt(ARCHIVE_EOF, archive_read_data_block(a, &pv, &s, &o)); + + assertEqualInt(ARCHIVE_OK, archive_free(a)); + free(p); +} + +/* + * Synthesize a lot of varying inputs that are highly compressible. + */ +DEFINE_TEST(test_read_format_zip_high_compression2) +{ + const size_t body_size = 1024 * 1024; + const size_t buff_size = 2 * 1024 * 1024; + char *body, *body_read, *buff; + int n; + + if (archive_zlib_version() == NULL) { + skipping("Zip compression test requires zlib"); + return; + } + + assert((body = malloc(body_size)) != NULL); + assert((body_read = malloc(body_size)) != NULL); + assert((buff = malloc(buff_size)) != NULL); + + /* Highly-compressible data: all bytes 255, except for a + * single 1 byte. + * The body is always 256k + 6 bytes long (the internal deflation + * buffer is exactly 256k). + */ + + for(n = 1024; n < (int)body_size; n += 1024) { + struct archive *a; + struct archive_entry *entry; + size_t used = 0; + const void *pv; + size_t s; + int64_t o; + + memset(body, 255, body_size); + body[n] = 1; + + /* Write an archive with a single entry of n bytes. */ + assert((a = archive_write_new()) != NULL); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualInt(ARCHIVE_OK, archive_write_open_memory(a, buff, buff_size, &used)); + + entry = archive_entry_new2(a); + archive_entry_set_pathname(entry, "test"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 262150); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(262150, archive_write_data(a, body, 262150)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Read back the entry and verify the contents. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, buff, used, 17)); + assertEqualInt(ARCHIVE_OK, archive_read_next_header(a, &entry)); + + assertEqualInt(ARCHIVE_OK, archive_read_data_block(a, &pv, &s, &o)); + assertEqualInt(262144, s); + assertEqualInt(0, o); + + assertEqualInt(ARCHIVE_OK, archive_read_data_block(a, &pv, &s, &o)); + assertEqualInt(6, s); + assertEqualInt(262144, o); + + assertEqualInt(ARCHIVE_EOF, archive_read_data_block(a, &pv, &s, &o)); + + assertEqualInt(ARCHIVE_OK, archive_free(a)); + } + + free(body); + free(body_read); + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_high_compression.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_high_compression.zip.uu new file mode 100644 index 0000000..0942880 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_high_compression.zip.uu @@ -0,0 +1,18 @@ +begin 644 test_read_format_zip_high_compression.zip +M4$L#!!0`"``(`*=Y]4@``````````*``!``(`"``8VAA +MD5>>))%7GB215W5X"P`!!/8!```$%````.W=06K#,!`%T&E)P8LL?*2XC@N% +M)#5QO>AM@9WDJ6!%\6$K/Q6T3LAX]N/GQ'Z9G&KA^*K1'S +M.`[GOIM*[TP_Q_>O0[G_:3X.Y\^^V/X2<>))%7=7@+``$$]@$```04````4$L%!@`````!``$`5@````L"```` +!```` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_jar.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_jar.c new file mode 100644 index 0000000..912e671 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_jar.c @@ -0,0 +1,59 @@ +/*- + * Copyright (c) 2016 Peter Wu + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * Issue 822: jar files have an empty External File Attributes field which + * is misinterpreted as regular file type due to OS MS-DOS. + */ + +DEFINE_TEST(test_read_format_zip_jar) +{ + const char *refname = "test_read_format_zip_jar.jar"; + char *p; + size_t s; + struct archive *a; + struct archive_entry *ae; + char data[16]; + + extract_reference_file(refname); + p = slurpfile(&s, "%s", refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip_seekable(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, s, 1)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("somedir/", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR | 0775, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualIntA(a, 0, archive_read_data(a, data, 16)); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + free(p); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_jar.jar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_jar.jar.uu new file mode 100644 index 0000000..0778c93 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_jar.jar.uu @@ -0,0 +1,6 @@ +begin 640 test_read_format_zip_jar.jar +M4$L#! H @ $AQETD ( 0 `Q0`"``(`,NJ,C\@,#HV"`````8````)`!@```````$```"D@0`` +M``!H96QL;RYT>'155`4``W[#=DYU>`L``03U`0``!!0```!02P4&``````$` +,`0!/````6P`````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_lzma.zipx.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_lzma.zipx.uu new file mode 100644 index 0000000..24fdc8e --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_lzma.zipx.uu @@ -0,0 +1,19 @@ +begin 644 lzma.zipx +M4$L#!#\#```.`#TQD4VJ.XZZ.0(``)`#```%````=FEM)82Q1PWAL +M+U`,N0L_$]^&650C/X$D6#4QFD$\A/"_![4!O/5O/!KH`WCQ*4?T2*]4P#/D +M0'9I?EZG=N69Z0V;H0I=CP*$?".I\ +MGMG/80.A'^W>R4J'S/CZ%P`8`>F=R>R&R$2T@EM#X)"OQH1?A7,`:4IU9WV! +M#2W*DXT',;.4YIN4A:-X)O=IREL201ZSOC=YSAU[C4-::/YV8\)%"L17+>VC +M%/'B]ZCQN$2(Q*9*\KJZ`Y131`]5C&G';@1S-QES_RZF!2OX45@58+??ES%( +MUJ<(\`11M$NO)HK#/MK-9RT"15.2I:IZN8VTM1_?$G\L#BH67]$S%[4 +M%C-$\Q<+./&HV](4,7)OL-@C^M0F"2O!0N$OHOW54H87^QLBQVH*D%A<#SI% +M/#+-5U(W';:KC)RE>0Y^5YI!RECQNR"R4.UW9IR!@:B!UB8?_D5$FT8YCJHJ +M2[2"-&-_D2BJ6#XK[6G=%K"%;'^-+0]FHCY4ER#`^-]>-A`H``"L:```+````?C+)VT(T,`U9;I1/'N)!6C.3M-O9LO]H<^=OZF\ +MXD\QEZIMP!JM4)W+(F]%N;U#&+F]WZ%S9>>]&^75:X)0Q-5>)IRT/%INC887 +ML0UF,PS8J@3;WGH95EW4\KBH,6ZK9,'![3$-(WL/C<[0.6%L9@]0;]_>&[A'#Q^##`6+*PM@YT+]E[B9 +M;QK38:)CO+S]4X2KF'=)BVO-GM+_#]PB0'*J89+$Q11IG\\+84M](58^RW.E +MGM3S6RH]#73P.KV0V,2=,/A!;G>2Y4R!!.4(0U+D<.'5V*%./ZZYD")=W4*4 +M\SL"IUJLN])WM`-&4L&!9&U_-1%%SPU0N4*.^L5&33"A5MZ;@8F+I^D7JB'K +ME&,P>"UI]NT;ZX`UU->]V$?KZV(DX&-6L>? +ME,(J<;DNA6/2.<9$>?-P]_!S8L3/2P@[C'H$FOA$WUOB>;X$)E7;K+7#X9M( +MM+H^AK#CML0LXTO#P#I)J_5"@O +MMGH9+OXD^P7AG@<%QGH<>FIWE]/>L)6Q2Q\CC=[?TCG262"1EO)'_W_C_K4< +M8.7YNR"3\9WTQ"0-!>^,M>WT.Y0A&3AK.4/YN5EW]"&HQ1=8Q-NHQABVH7$% +M24Q:J/<8%F1EI)-!HND&FP_;]E,JI$*AGE&]Y#FJ5R6<(UM;;>U?KU@OQ,M_ +MI/+:;0^0'8JA"==H5/;]Y10P&PS,1_M+D1I>`%>_Y\&F[_R/##784#0AQ1!O +M'8>IBY?;&;(VAOI$+Z[VMI>]WC!['W$&Z5/D+"6["[[.[P!/?9C/;CD66^J/OC) +MO0JXP'Y6]PGW8N@X(#-XXWMP"A%E$A8L+X>QIC[0P,UT0A!IYQ/#+>E60KX/ +M2JC'F-Z@_,-/$7+F5F$1\#^"CTSY;H2EAE,/8>F$^'5H!M2@D?2O@+NJ2&-O +M6IV-[<6F-JG0(,W-YJ%PJ<7T.F")'/+F_`F6B-HG436 +MJM-VK0?>9*R?K#]OHC90!]BCG'^D&%!JZ2T_&[RWV?0Z?T:#_\B`?:MRC$D5 +M1Z.)!/;3/=GT*T;DC/XLR;7S%VEP+U-M)-*V,1?M<377S9-`J]S4[OI4SR>V +M_?_H2WWH>\@*$V@`LZO?-'Z[4_4"T2R@=%! +M!\1]:4M((1B=ATAJ)23HE7>]=,7I#SK5'2OUZLX0LX*_67!+6S:*0UL)^GS6 +MM;$2!(-TY%4ME1>*'M)S'[0JP^&J%"-&A[C1YE;1:X_4Y&K9*2 +M'14NC*]O(JXNLX#M_(LDE6$G<0,+V/;44]-*^S%7G*.\$W&>2=9,EYB)/@XK +MX+E4?>NIP=*X]Z>3T,V?!"5:/M@X-H%DZEV,*9WIK;T_C18UC5$%^Z5PY8;USNB?S]`D-K2V2 +M-C#0-45C'YFF>#*$9JZ!$>%0;=VQ@LGY"J<.C.10"1'JL^B(VXPNK^]Q97E\`HX0MG2)F=>38R,IFGK\R +MVH!.V3_)_D,II8A=SL;X1!2D9E67=.$P+_D6&'X^1;4%:`ERV>!,''7<#=NE +MP')[\,A89G35\;ZN:IIY5DDSB$(8D$[G>7-L!(+(-7=LQ0Q3=S`L-)R9YT;S +M;%ZYVD%6)M=I]*QS>!3='"SB'E/4>J#EQ.&]0*U0H/Y1%DM].)E/UFD0?Q)B;_;;)-K_]6Z<)D_>^[=?49%4D4B@REC` +M,_KU,KX-N,44CL/:*^D>7X(;6_1&C;<;&`K3+4NY[=4%K2K:U"Q%T9)',7," +M+PC``PBBDVNY9V-LN'V')B4@4;OH(\/M%UBX$S."4_!;&=9W\L`!2O\!ANM5 +M8+""#5J&/M[2;M?47WN=0[4C*$7D#QB&`!*@5_0 +M9(5SZ7,Q"N?0W!\0WGQF,0JKH[G-(<6^PMJZV&VHQIT?VKJ^7^!EW?)`EC`$ +M0%,=?X0ME@T_&5UXJIJ9)5(<[=W]M#Y.$.96:_T8WM/H+"T_Q;QZN"`5DC&' +M.+(^")0XO=#&#@KVL2R9+.#F)P02=`6PT[21&>T*Q3Y2WVL><:PHB)R?*'+3 +M+,OK(7PNXHXMVFT"!)??8!H^I,&V +M8BOE(Z/VYY(5WLSG$.+8$;.A>]+PVB`WV,9M@YL='Q_<%2STU?_IG.I17G^L +M>#-=')K6T?C[^&,7Z)0!B[2-)2:&?*5, +M,;&-HI_/O(/V"4-:_E>0Z)=C=1/9HQJO$R:(&H@4RP"3%T[BOBZ`3_2>)K49 +M\ZL-26)MQ\%(>T0S5A4>EUCU[),JI"_/9<5)*6X\97`N:8YSR0%)@*#_'9'? +M/E=RFK"L&(#RS$S_0[?/!DW.`\FH$M\#"JSQ@*&C*W\`4$L#!#\#```.`(@X +MD4TQF^5ZO0$``%0#```'````=',N8V]N9A`"!0!=`"`````1B`2H,L'S88)4 +M*WW.8!PX^&C9J^P?<4.RSJ^WF7L-W#+OB4@(A-83?&.PVF@$.:VM<4\8K(_6 +M`CRI/@MR:,)C8$&U*MZKA\W'KCI%E2GDYYE/SB'*\S@5]NO,ZBF!;HY@ +M3Q=F"]@P02:6^LC>JT$T7BB(.:*G`I.?%/53CC#4I0N_ARFXFG`DZSI*$)UM +M1^X:IZ^^)T*5E,C6L<,L%=ASF-1:0CP6*FX_;?R;#]C:/ +M)C@@M]\FLU4*%H^>8VW4@@%D0U!02P,$/P,```X`/3&13:H[CKHY`@``D`,` +M``4```!V:6UR8Q`"!0!=`"`````1"`2HPGR1L@-2P5SX3!72_Z.U"NE"C>=! +MB(;_TY1PR.H(G3<^QXEA+%'#>&PO4`RY"S\3WX995",_@218-3&:03R$\+\' +MM0&\]6\\&N@#>/$I1_1(KU3`,^1`=FE^7J=VY9GI#9NA"EV-P&-RI:_YA-3= +M!E?#E$05TTLL[G6$<%[`H1\(ZGR>V<]A`Z$?[=[)2H?,^/H7`!@!Z9W)[(;( +M1+2"6T/@D*_&A%^%+WJ/&X1(C$IDKRNKH#E%-$#U6,:<=N +M!',W&7/_+J8%*_A16!5@M]^7,4C6IPCP!%&T2Z\FBL,^VLUG+0)%4Y*EJGJY +MAS2K)[;2U']\2?RP.*A9?T3,7M06,T3S%PLX\:C;TA0Q; +MZC0FI6JUP3:]D^3L->OKP>:G2P_FF8)V>\LVQ^;MC'-2N-,GXD"Z]PZI8A79+7ED*DB,K&N'OH,DT/C4$L!`C\# +M/P,```X`D3B139XWUXV$"@``*QH```L`)``````````@@*2!`````'-M87)T +M9"YC;VYF"@`@```````!`!@`@.Y>844/4!%`!C8!5C9V!B8/!-3%;P#U:(4(`"D!@#)Q`;`?%;(`;R +M&>49B`*.(2%!$!98QPP@;D=3PH@0%T[.S]5++"C(2=5+3,[1*TFM*`%**"H# +M.0J&7*7%J456;D#@"@2Z+D"@ZPP$NDY`H.L(!`9@X&QIY5Z:6EQB961@:)62 +MFE=I592:F,*57I1?6F#EZ.3LXNKFZ*0+HG1!/%TX%Z+=U,`J,24W,\_*`LC( +MR^LP```!\!``!02P$"%0,4``@`"``M:&-! +M)"I3#0H````(````!0`,``````````!`I($`````9FEL93-56`@`U?264!:7 +ME%!02P$"%0,*``````!7:&9!````````````````"0`,``````````!`_4%- +M````7U]-04-/4U@O55@(`.:+F%#FBYA04$L!`A4#%``(``@`+6AC0?@\%[ZS +M````'P$``!``#```````````0*2!A````%]?34%#3U-8+RY?9FEL93-56`@` +>U?264!:7E%!02P4&``````,``P#,````A0$````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_malformed.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_malformed.c new file mode 100644 index 0000000..f116064 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_malformed.c @@ -0,0 +1,62 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2011 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +static void +test_malformed1(void) +{ + const char *refname = "test_read_format_zip_malformed1.zip"; + struct archive *a; + struct archive_entry *ae; + char *p; + size_t s; + + extract_reference_file(refname); + + /* Verify with seeking reader. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + + /* Verify with streaming reader. */ + p = slurpfile(&s, "%s", refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 31)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + free(p); +} + +DEFINE_TEST(test_read_format_zip_malformed) +{ + test_malformed1(); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_malformed1.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_malformed1.zip.uu new file mode 100644 index 0000000..cbd21a8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_malformed1.zip.uu @@ -0,0 +1,5 @@ +begin 644 test_read_format_zip_malformed1.zip +M4$L#!#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`$`!P`,#`P,#`P"0`P,#`P,#`P +1,#!U>`L``80P,#`P,#`P,#`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_msdos.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_msdos.c new file mode 100644 index 0000000..1867204 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_msdos.c @@ -0,0 +1,116 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2011 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +/* + * Test archive contains the following entries with only MSDOS attributes: + * 'abc' -- zero-length file + * 'def' -- directory without trailing slash and without streaming extension + * 'def/foo' -- file in def + * 'ghi/' -- directory with trailing slash and without streaming extension + * 'jkl' -- directory without trailing slash and with streaming extension + * 'mno/' -- directory with trailing slash and streaming extension + * + * Seeking reader should identify all of these correctly using the + * central directory information. + * Streaming reader should correctly identify everything except 'def'; + * since the standard Zip local file header does not include any file + * type information, it will be mis-identified as a zero-length file. + */ + +static void verify(struct archive *a, int streaming) { + struct archive_entry *ae; + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("abc", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG | 0664, archive_entry_mode(ae)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + if (streaming) { + /* Streaming reader has no basis for making this a dir */ + assertEqualString("def", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG | 0664, archive_entry_mode(ae)); + } else { + /* Since 'def' is a dir, '/' should be added */ + assertEqualString("def/", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR | 0775, archive_entry_mode(ae)); + } + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("def/foo", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG | 0664, archive_entry_mode(ae)); + + /* Streaming reader can tell this is a dir because it ends in '/' */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ghi/", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR | 0775, archive_entry_mode(ae)); + + /* Streaming reader can tell this is a dir because it has xl + * extension */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + /* '/' gets added because this is a dir */ + assertEqualString("jkl/", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR | 0775, archive_entry_mode(ae)); + + /* Streaming reader can tell this is a dir because it ends in + * '/' and has xl extension */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("mno/", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR | 0775, archive_entry_mode(ae)); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); +} + +DEFINE_TEST(test_read_format_zip_msdos) +{ + const char *refname = "test_read_format_zip_msdos.zip"; + struct archive *a; + char *p; + size_t s; + + extract_reference_file(refname); + + /* Verify with seeking reader. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 17)); + verify(a, 0); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* Verify with streaming reader. */ + p = slurpfile(&s, "%s", refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 31)); + verify(a, 1); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + free(p); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_msdos.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_msdos.zip.uu new file mode 100644 index 0000000..4503d09 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_msdos.zip.uu @@ -0,0 +1,23 @@ +begin 644 test_read_format_zip_msdos.zip +M4$L#!`H``````!"2@D@````````````````#`!P`86)C550)``/P;@!7;'0` +M5W5X"P`!!/4!```$%````%!+`P0*``````#PE()(`````````````````P`< +M`&1E9E54"0`#4W0`5U-T`%=U>`L``03U`0``!!0```!02P,$"@``````[Y2" +M2`````````````````<`'`!D968O9F]O550)``-2=`!7;'0`5W5X"P`!!/4! +M```$%````%!+`P0*```````6DH)(````````````````!``<`&=H:2]55`D` +M`_QN`%?\;@!7=7@+``$$]0$```04````4$L#!`H``````!65@D@````````` +M```````#`"<`:FML550)``.9=`!7F70`5W5X"P`!!/4!```$%````'AL!P`% +M'@`0````4$L#!`H``````!:2@D@````````````````$`"4`;6YO+U54"0`# +M_&X`5_QN`%=U>`L``03U`0``!!0```!X;`4`!!````!02P$"'@`*```````0 +MDH)(`````````````````P`8````````````````````86)C550%``/P;@!7 +M=7@+``$$]0$```04````4$L!`AX`"@``````\)2"2`````````````````,` +M&``````````0````/0```&1E9E54!0`#4W0`5W5X"P`!!/4!```$%````%!+ +M`0(>``H``````.^4@D@````````````````'`!@``````````````'H```!D +M968O9F]O550%``-2=`!7=7@+``$$]0$```04````4$L!`AX`"@``````%I*" +M2`````````````````0`&``````````0````NP```&=H:2]55`4``_QN`%=U +M>`L``03U`0``!!0```!02P$"'@`*```````5E8)(`````````````````P`8 +M`````````!````#Y````:FML550%``.9=`!7=7@+``$$]0$```04````4$L! +M`AX`"@``````%I*"2`````````````````0`&``````````0````00$``&UN +M;R]55`4``_QN`%=U>`L``03U`0``!!0```!02P4&``````8`!@"\`0``B`$` +#```` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_nested.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_nested.c new file mode 100644 index 0000000..4418fc4 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_nested.c @@ -0,0 +1,87 @@ +/*- + * Copyright (c) 2003,2014 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_read_format_zip_nested) +{ + const char *refname = "test_read_format_zip_nested.zip"; + char *p, *inner; + size_t s, innerLength; + struct archive *a; + struct archive_entry *ae; + + extract_reference_file(refname); + p = slurpfile(&s, "%s", refname); + + /* Inspect outer Zip */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, s, 1)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("small.zip", archive_entry_pathname(ae)); + assertEqualInt(211, archive_entry_size(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Save contents of inner Zip. */ + innerLength = (size_t)archive_entry_size(ae); + inner = calloc(innerLength, 1); + assertEqualInt(innerLength, archive_read_data(a, inner, innerLength)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("file.txt", archive_entry_pathname(ae)); + assertEqualInt(53, archive_entry_size(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + /* Close outer Zip */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + + free(p); + + /* Inspect inner Zip. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, inner, innerLength, 1)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("another_file.txt", archive_entry_pathname(ae)); + assertEqualInt(29, archive_entry_size(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + + free(inner); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_nested.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_nested.zip.uu new file mode 100644 index 0000000..7b9e266 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_nested.zip.uu @@ -0,0 +1,16 @@ +begin 644 test_read_format_zip_nested.zip +M4$L#!`H``````(U`.D6]]'5ITP```-,````)`!P`FEP550)``-Y +MGR14>9\D5'5X"P`!!..5`@`$@A8``%!+`P0*``````"+0#I%N2<3PAT````= +M````$``<`&%N;W1H97)?9FEL92YT>'155`D``W:?)%1VGR14=7@+``$$XY4" +M``2"%@``3VYL>2!T:&ES(&9I;&4@:7,@9&ES<&QA>65D+@I02P$"'@,*```` +M``"+0#I%N2<3PAT````=````$``8```````!````H($`````86YO=&AE`L``03CE0(`!((6``!4:&4@>FEP(&%R8VAI=F4@ +M;65T861A=&$@:7,@;F]T(&1I`PH` +M`````(U`.D6]]'5ITP```-,````)`!@```````````"@@0````!S;6%L;"YZ +M:7!55`4``WF?)%1U>`L``03CE0(`!((6``!02P$"'@,*``````"90#I%^VUC +MDS4````U````"``8```````!````H($6`0``9FEL92YT>'155`4``Y*?)%1U +D>`L``03CE0(`!((6``!02P4&``````(``@"=````C0$````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_nofiletype.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_nofiletype.c new file mode 100644 index 0000000..b3260fa --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_nofiletype.c @@ -0,0 +1,66 @@ +/*- + * Copyright (c) 2013 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * Issue 332: Some epub files (which are really Zip archives) have + * nonsense in the "external file attributes" field. + */ + +DEFINE_TEST(test_read_format_zip_nofiletype) +{ + const char *refname = "test_read_format_zip_nofiletype.zip"; + char *p; + size_t s; + struct archive *a; + struct archive_entry *ae; + char data[16]; + + extract_reference_file(refname); + p = slurpfile(&s, "%s", refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip_seekable(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, s, 1)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("file1", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG | 0644, archive_entry_mode(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualIntA(a, 6, archive_read_data(a, data, 16)); + assertEqualMem(data, "file1\x0a", 6); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("dir2/", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR | 0755, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualIntA(a, 0, archive_read_data(a, data, 16)); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + free(p); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_nofiletype.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_nofiletype.zip.uu new file mode 100644 index 0000000..e05e9f0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_nofiletype.zip.uu @@ -0,0 +1,8 @@ +begin 644 test_read_format_zip_nofiletype.zip +M4$L#!`H``````$-$>$,$]RGB!@````8````%````9FEL93%F:6QE,0I02P,$ +M"@``````141X0P````````````````4```!D:7(R+U!+`0(>`PH``````$-$ +M>$,$]RGB!@````8````%``````````$```"D`0````!F:6QE,5!+`0(>`PH` +M`````$5$>$,````````````````%````````````$`#M`2D```!D:7(R+U!+ +4!08``````@`"`&8```!,```````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_padded.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_padded.c new file mode 100644 index 0000000..d8c694b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_padded.c @@ -0,0 +1,92 @@ +/*- + * Copyright (c) 2013 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +static void +verify_padded_archive(const char *refname) +{ + char *p; + size_t s; + struct archive *a; + struct archive_entry *ae; + + extract_reference_file(refname); + p = slurpfile(&s, "%s", refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip_seekable(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, s, 1)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("file0", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG | 0644, archive_entry_mode(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("file1", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG | 0644, archive_entry_mode(ae)); + assertEqualInt(6, archive_entry_size(ae)); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + + free(p); +} + +/* + * Read a zip file with padding in front. + * This is technically a malformed file, since the + * internal file offsets aren't adjusted to account + * for the added padding. Unfortunately, some SFX + * creators do almost exactly this: + */ +DEFINE_TEST(test_read_format_zip_padded1) +{ + const char *refname = "test_read_format_zip_padded1.zip"; + verify_padded_archive(refname); +} + +/* + * Read a zip file with padding at end. + * Small amounts of end padding should just be ignored by the reader. + * (If there's too much, the reader won't find the central directory.) + */ +DEFINE_TEST(test_read_format_zip_padded2) +{ + const char *refname = "test_read_format_zip_padded2.zip"; + verify_padded_archive(refname); +} + +/* + * Read a zip file with padding at front and end. + */ +DEFINE_TEST(test_read_format_zip_padded3) +{ + const char *refname = "test_read_format_zip_padded3.zip"; + verify_padded_archive(refname); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_padded1.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_padded1.zip.uu new file mode 100644 index 0000000..8cc3f41 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_padded1.zip.uu @@ -0,0 +1,12 @@ +begin 644 test_read_format_zip_padded1.zip +MBG[*5O,EN^?);45X-!:9?HM14B$W +MD5)U>`L``03U`0``!!0```!F:6QE,`I02P,$"@``````^'EW0P3W*>(&```` +M!@````4`'`!F:6QE,554"0`#)#>14B0WD5)U>`L``03U`0``!!0```!F:6QE +M,0I02P$"'@,*``````#W>7=#1<8R^P8````&````!0`8```````!````I($` +M````9FEL93!55`4``R$WD5)U>`L``03U`0``!!0```!02P$"'@,*``````#X +M>7=#!/`L``03U`0``!!0```!02P4&``````(``@"6````B@`````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_padded2.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_padded2.zip.uu new file mode 100644 index 0000000..3b57fe1 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_padded2.zip.uu @@ -0,0 +1,15 @@ +begin 644 test_read_format_zip_padded2.zip +M4$L#!`H``````/=Y=T-%QC+[!@````8````%`!P`9FEL93!55`D``R$WD5(A +M-Y%2=7@+``$$]0$```04````9FEL93`*4$L#!`H``````/AY=T,$]RGB!@`` +M``8````%`!P`9FEL93%55`D``R0WD5(D-Y%2=7@+``$$]0$```04````9FEL +M93$*4$L!`AX#"@``````]WEW0T7&,OL&````!@````4`&````````0```*2! +M`````&9I;&4P550%``,A-Y%2=7@+``$$]0$```04````4$L!`AX#"@`````` +M^'EW0P3W*>(&````!@````4`&````````0```*2!10```&9I;&4Q550%``,D +M-Y%2=7@+``$$]0$```04````4$L%!@`````"``(`E@```(H``````(.2J;)Q +M[PX@J`9,J[C2AH>N<8_.US0'*2[BOW;O(NTEX5WU&F@8Z'+:Q]HTV@/M"D"9 +MPM-+&=&VJIL(Z1VGT?_2.G?,\!@N+_"U8I!K>[,)F8(HA0[3P7N"0[A;4]3QYC6?U,X[!@NM% +MOQJNIW"H3++]CW52#?CS&A=VU8&T:-YPI'J&>3^,1.F=97>R\P]*YF).R*I0 +M2P,$"@``````]WEW0T7&,OL&````!@````4`'`!F:6QE,%54"0`#(3>14B$W +MD5)U>`L``03U`0``!!0```!F:6QE,`I02P,$"@``````^'EW0P3W*>(&```` +M!@````4`'`!F:6QE,554"0`#)#>14B0WD5)U>`L``03U`0``!!0```!F:6QE +M,0I02P$"'@,*``````#W>7=#1<8R^P8````&````!0`8```````!````I($` +M````9FEL93!55`4``R$WD5)U>`L``03U`0``!!0```!02P$"'@,*``````#X +M>7=#!/`L``03U`0``!!0```!02P4&``````(``@"6````B@``````D$,:4/1\ +MSHGT7I+41*.O21/O.+Z%^`_>)S-WGU>>J4G0Y?5'GJ1PMY->*=#3Y+U(_A)OCL1N.):>IH8%T>Y$?&=@(K; +M(+HD_4?R.6`$;@@+ +M12?TRT^S)&!1W*^J06(&KL+*+>]_YL$5K0Q:G9J,1!%[\Q"5;/MD-K-YJWEJ>3<8@F_*<(\B>K]4_(WC8#)`_QSG+`7`B&_11VIJ)@#(K)_I8R^=`VUO2_S,1C=1CAU>-*`]CC+&6Q;EE'#CG-W=^[,F,+UR-TE(9,G +M1_&$NYD`,5WY5QX7@%5XX-*7+7&#W'1#XF+"?6*U!H=B063.]NTA`1+&\J(K +M&U]DE8$ZYUU'UT\$!88I,6+(M/"=_+3@V5H+24 +MBA0>^0?[W07K"B%SQ&OA-R)S9W>DH,<4##E@?5YF:%K$?5U@W[IVG+2#8FC4'GT3-$L%_N,B$^)UY1GAD=.Z(HI#3[T"979&<`+ +M`S]9G+PI';5"==`18UE,>N"?>"_C"MSHX<[!&8$+A6U_7][TK*6.^\-O-UK! +M`)>[*.D1:1H!I,?PEIPW,NQ5CCX2NCY+%UH"T5X!O$&=6+X#"()33:]FPF:F +ME-O)\652#KD$^ZFBJ7K`55]R/A"OA"T7\R6K%B(2&6*/H0>*-:@< +MJ2V9^KJSL+P4A&$`4$L!`C\#/P,``&(`/3&13:H[CKK8`0``D`,```4`)``` +M```````@@*2!`````'9I;7)C"@`@```````!`!@``)=1P<:5U`&`PJ3,QI74 +?`0"74<'&E=0!4$L%!@`````!``$`5P```/L!```````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_ppmd8_crash_1.zipx.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_ppmd8_crash_1.zipx.uu new file mode 100644 index 0000000..fb6050f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_ppmd8_crash_1.zipx.uu @@ -0,0 +1,4 @@ +begin 644 test_read_format_zip_ppmd8_crash_1.zipx +K4$L'"(=02P,$\+N.O&*A>*\+."U``$H`````````@``````#````6(0````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_ppmd8_crash_2.zipx.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_ppmd8_crash_2.zipx.uu new file mode 100644 index 0000000..58de412 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_ppmd8_crash_2.zipx.uu @@ -0,0 +1,4 @@ +begin 644 test_read_format_zip_ppmd8_crash_2.zipx +L4$L'"(=02P,$\+N.O&*A>*\+.2U`@$H`````````@``````#```````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_ppmd8_multi.zipx.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_ppmd8_multi.zipx.uu new file mode 100644 index 0000000..6fadcea --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_ppmd8_multi.zipx.uu @@ -0,0 +1,84 @@ +begin 644 test_read_format_zip_ppmd8_multi.zipx +M4$L#!#\#``!B`)$XD4V>-]>-.0D``"L:```+````X%[[99#N5_N2Y@T-?"T%*8O@,-K>QSOR>-).,0-Q:=7)+:*Z&:B9' +M-YXDKOWK"T?"(.;F$3'A>TW+.W#W%Y0`:_5XI+35&4_L<0>95Q!XP,\T=VCM +MZB%S4G,4ED*-4T#5Y'BUCMS!0Z)0*50U=EQWM_F]2)<8#VF(432?^.!'O`I/ +MLP!A8AN1>8;MQ:S?/4-$K07X@["K?T]0<=84:OJ]Y$.D)3MNMK`U.(ORV3M& +MV`2EDVHT&D'F-=\,_"^;UGWW!=,KJI4^NZAF72$S=N.*PW!#ZJ?KQ0;$7E!] +MFC,:ST/]Y(,:K3SK7,%&A_%1`($9H@/\G.RN$J7BA?C\P"[U&[8MITK*`U5E +MVH'&CJ8?%1+H-H0=B*8]_(F;;/P`371(@?QN2T<4C52L;%S-XV),E4-V05&I +MA.V?U+HM63;JH=1]LJ_E"@JM?QH\6#NQ7I\I*%-!)LWB?U):O^--2R=1C):^ +M^@GFC0GETH%>LXD8_D*J'KS5[/M5+89M;6@3?]I.`M=;(S7*1?(?.9G!`S26 +M([JDK/(RCM%WYC`>G*L7:NJ!5TS[7MI^E[4/\RU9$&1XJ5#V;<'F^AX^R@P7< +M/2?UB;-2+I11]^X;,J\:,'^R=&8"@[EI0$J:":*LQ-F(IOSXC?1W>/;?4$P* +M;=V"OEY@S\%3'&F-^K0FME.]%1DTO*OP8.:M('3W)\S"1.@8# +M6Y1&@L+#!YVL]8.,[UP/\HMAR1"O!M/2?DY-8[N'P[T&2J7-V5%=XWMRQ,EM +M7TL^99!FXY0+B1^7K36"#!85"WXE,WFEU=B!+GX2$D<)MW>&A,8A9RPL]CR( +M!=1JX99-:5D;PM@S4(>?BKTFAQ>"%9\Q^Y\6T\ +MTS"*[M.TW7AE:#\(:M_JLJ#*-9-O,UW\T:PVW8G01OR!B59P=[:XNH0Y=OC9`KJ_%.>^)RW-,G^%%(U9HC957G/\@ +MW1\J*,JLX*CF*,-!'^O*E7=V#S8_#G`9YQ)#%,AJ8"-4B,OR8RW4@L)8F$JB +M.3QD;;M_L<:*T3B>8\OECY@*'6?[2VYXB3B!`<:65*HB/.^@;]\`IE)HTIG=_X:*3A'#M\P0L*]^ZFWC\UL`O;WL@#?"!(_]OZ4=B<\QL/ +MWD%/TL5[P\,^_3G\]WD-Q`?XU]K5LFW +MI6J$G\=W(Q+2_U&THGA'_6)`"WK=X74-OD_B%WJU+JH/A"K#JQ@)A<`>A6[H +MC2A>S7]ZV/H?/1KV&OR8B]IS\>Y:\5;B-:+E^V`:5_O[+(!,6LW0&[5(F4UH +MKM;R]_V\?PI6I+"7M1H%E':WL<1#J"O`>]S*UKS02ME,S7]X66@[B`_#?H$^) +MT&07IY[)18RK+`@#?UXT=8B=XC$J'SSJ>XP2RJ]>02[1J:R;0"M&L>KY(3*9QLH1N@K?LL%3J%O? +MR!>+JHS'L3_<*?;*81D1'/A-A"%%P..0%#Q32?L88\C'/'W?D +MG766\,!14W_TY,.;G,\C.+L1LR__7UR*_H!IE,1LZO,_+#?C[OW4+[4I`[7] +MZ;U%`5#@;6A5#JU]H+\E;^^LQBHQ$-T.P5.V/JS69'PI06.%#D4 +M%B.K!F(.G*6@/>[P-FU3-#%N.EY%W*]P_]<>?07:7 +MK&JYBO\0HXN^[/OA#_MP/QQG-+1?Z)7*WRL14*DMWL2795*UHMN/'POIN@Z= +M&&>Z/LT#HX00EWLZ%/G7)X<":!ST&P+Q0R)=V6!#D]TY1RYO!C&5&''Y<9UK +MK=LY46W;=`;(^L<>RMMG%(;??BF+AY,7=+H)6XSZ:2#^`W=RR7KIE>XQ/[_^ +M^$F4*967)DE3/^&\(7W?:EKRJ,PN@HOT:U_.!1-"7A-=LX\Y.=-37_355)/2H +M5V[LT(83$V*>?^YW7'6.SD=MYSM<`[M'IU]?H2ZU8\SLD+R-Q__8G +M2A&2#H5-J+*NQHQ&ZX$YO_(.OC\W[3B6WB#"MKV?*/<=(JBTKB`D_X'X+7"Q +MJ$B]N)L:OTXC':GK/!QYSR.,%%T3XI6(C(3&XZV`.ZLS=\O7>0 +M#N;$J[W)(Q.5<_I5G1K^FB10(.'.#Z!,B8Y'WX_=XOM8\+X/;Z\!"0HTWZG# +M[:0<%(2)`J>6>9=.B5&CWX.,@3RF>FN>'-0))N"!IY,\_?'B`DNYJ4'+!JK] +M\NX-@,,Y%)>#36Z7>CBBL=0S<@W(QRXPD3:VF-W)CS52HO!/T%NV[$0^B01. +MZH\`/9ZTF=$,",`0J\ANSPF&X.0O!?$8\^M%XSM$`D)W".C60(#6;('?*'.` +MTN9>^YI5M0P:-7MCSU2HCCU'`[!+^"9P9BH%1<=K_B#UZ3CDJWX+V\C^S$GD +M]M3M2VJY4''"]RN@>]D^K6B7ZGQG!<4'LZCK,BU]QH,1G(P$AB-W/G%7[.`! +M"P[DH--W#`"^#];7=H09``!02P,$/P,``&(`B#B133&;Y7IM`0``5`,```<` +M``!TCE(/-F<.B*/H_C$3G..AVGS/6(LHZG/Y[UI +MO1E2,[]ZU6`C\+WOIWU\>8)Z?4>]`A@"D*I3B52YGN&M&ME*-/]I!1,P.R@8#3-@,D#_'.`57C@TIL*(7/$:^$W(G-G=Z2@QQ0,.6!]7F9H +M6MRJ>G_FVK['10^FM,>V7UX1]76#?NG:?1,T2P7^XR(3XG7E&>& +M1T[HBBD-/O0)E=D9P`L#/UFL!57W(^$*^$+1?S):L6(A(9 +M8H^A!XHUJ!S!KSA%4.]<`XB*.5^_Q`%$6ON%MH"W>Z9/P^MG.I)@N0WI*EE+ +MX2HV+?E8)N&["2\:UYRI+9GZNK.PO!2$80!02P$"/P,_`P``8@"1.)%-GC?7 +MC3D)```K&@``"P`D`````````""`I($`````8FT!``!4`P``!P`D`````````""`I(%B"0``=',N8V]N9@H`(``````` +M`0`8``#P/%?.E=0!`,YV<5U`$`-+O[QI74`5!+!08``````P`#``T!``#O#``` +"```` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_sfx.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_sfx.c new file mode 100644 index 0000000..a33c1b8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_sfx.c @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * Read a zip file that is a SFX. + */ +DEFINE_TEST(test_read_format_zip_sfx) +{ + const char *refname = "test_read_format_zip_sfx"; + char *p; + size_t s; + struct archive *a; + struct archive_entry *ae; + + extract_reference_file(refname); + p = slurpfile(&s, "%s", refname); + + /* Symlinks can only be extracted with the seeking reader. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, s, 1)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("file0", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG | 0644, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("build.sh", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); + assertEqualInt(23, archive_entry_size(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + + free(p); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_sfx.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_sfx.uu new file mode 100644 index 0000000..aab730b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_sfx.uu @@ -0,0 +1,34 @@ +begin 644 test_read_format_zip_sfx +M!5@J$E]]1]?.)[Z/+RR:J';4YIJ7H0[7:BO"S8^VFB`_M_2)627VRG7%.)ZR +M->RL72GY3(0UJMJ0;.F=<-36\SK.=/A%FK!K4Z0URPF<&M#E<@RXT`A04/Z\ +M<^0G>R,X8]@8XDDNJY6M`)Q".-::"%RS&VR!DZ_:>D2?J2W="_+^EV*LRQR6=M7'6<;4-9>QC>@*<'9 +M/I<2W=CTNY/`P:EB;N!VD.N^;=8Z)1MJNOW`@8S9Z/X\U4^#H>WZQ>-61Y+W +M(K*N/]YP(XU?S7^FL2DM15A6H-!:D"W`W/DQN(2IZ12!O_3"Y6MC9` +MY#9LR=$B?G%0HZZ";I^LT<7@$6%T2#S-DG@K@LJ46)C>A`.T!2P@[Z5T;"DY +MVE@B9%DHX=,"ER*),3-%];VC5,B-`,WNYTNOA[U"LZQ4Q`Y(!"J2SO6JA4>?8[`$PN"E`@URA/B&/),005H.O-.^?T;PF])\WV?/ +M%K*51XKZU_[D_56VA6$UO(-5R6'0T/$S]`("I-`+&!&2>Z-*%PO"D_Q.E:G7<7=[ +MI<^0VIH=CZH9$9^5"W?CGNJ0Y<%R^I(R-M5;9#,.B4;R8['I*P^0%-3("7H( +M2-#V.4!`(<0=EP,>0S*H?-O[N6'JE`,U`V\<<;=F6L4RZW#1$[,1Z5/-28A? +M0/ATG:"NW/_TZ('?]7E=9D`5WR`OZN4>7-%DR,5[;$^A,E7QE#[U]F*VZR_H +M*XX#+B;Z9*0M(\<#->VZV)%.6&`@!."\7,,/[8,WDDMU +M2*@5[=A":;?D^<$^*U.UN^B%7M*2^A@`.N)^7"-?@!V9$W$_4[\R"WJ*,Z-$ +M8=9[;;447S.)EED+*4FGT[045[*=AI%;U(1L8 +M\[-R4%15\D,""]:=;;OVAJK.TY\J8A)G&JV9!ZECJ?1<````7````"``<`&)U:6QD+G-H +M550)``-CKIA0=SN\4'5X"P`!!/4!```$%````",A+V)I;B]S:`IE8VAO(")T +M97-T+B(*4$L!`AX#"@``````X8!F00````````````````4`&``````````` +M`*2!`````&9I;&4P550%``,6MYA0=7@+``$$]0$```04````4$L!`AX#"@`` +M````O'MF0>I8ZGT7````%P````@`&````````0```.V!/P```&)U:6QD+G-H +M550%``-CKIA0=7@+``$$]0$```04````4$L%!@`````"``(`F0```)@````D +E`%1H:7,@:7,@82!S86UP;&4@9FEL92!F;W(@:7-S=64@,C4W+@`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_symlink.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_symlink.zip.uu new file mode 100644 index 0000000..f573565 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_symlink.zip.uu @@ -0,0 +1,10 @@ +begin 644 test_read_format_zip_symlink.zip +M4$L#!`H``````-BDE3_!B>PO!0````4````$`!P`9FEL9554"0`#6+3R3G>T +M\DYU>`L``03U`0``!!0```!F:6QE"E!+`P0*``````#`PH``````-BDE3_!B>PO!0````4````$`!@```````$```"D@0`` +M``!F:6QE550%``-8M/).=7@+``$$]0$```04````4$L!`AX#"@``````W*25 +M/Q`VGXP$````!`````<`&````````````.VA0P```'-Y;6QI;FM55`4``V"T +G\DYU>`L``03U`0``!!0```!02P4&``````(``@"7````B``````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_traditional_encryption_data.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_traditional_encryption_data.c new file mode 100644 index 0000000..20e55bb --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_traditional_encryption_data.c @@ -0,0 +1,168 @@ +/*- + * Copyright (c) 2013 Konrad Kleine + * Copyright (c) 2014 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_read_format_zip_traditional_encryption_data) +{ + /* This file is password protected (Traditional PKWARE Encrypted). + The headers are NOT encrypted. Password is "12345678". */ + const char *refname = + "test_read_format_zip_traditional_encryption_data.zip"; + struct archive_entry *ae; + struct archive *a; + char buff[512]; + + /* Check if running system has cryptographic functionality. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + if (ARCHIVE_OK != archive_write_set_options(a, + "zip:encryption=traditional")) { + skipping("This system does not have cryptographic liberary"); + archive_write_free(a); + return; + } + archive_write_free(a); + + + extract_reference_file(refname); + + /* + * Extract a zip file without password. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + assertEqualIntA(a, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW, + archive_read_has_encrypted_entries(a)); + + /* Verify encrypted file "bar.txt" */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("bar.txt", archive_entry_pathname(ae)); + assertEqualInt(495, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_is_data_encrypted(ae)); + assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); + assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); + assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, sizeof(buff))); + + /* Verify encrypted file "foo.txt" */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("foo.txt", archive_entry_pathname(ae)); + assertEqualInt(495, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_is_data_encrypted(ae)); + assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); + assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); + assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, sizeof(buff))); + + assertEqualInt(2, archive_file_count(a)); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + + /* + * Extract a zip file with password. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + /* Pass three passphrases to decrypt a file content. */ + assertEqualIntA(a, ARCHIVE_OK, + archive_read_add_passphrase(a, "invalid_pass")); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_add_passphrase(a, "invalid_phrase")); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_add_passphrase(a, "12345678")); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + assertEqualIntA(a, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW, + archive_read_has_encrypted_entries(a)); + + /* Verify encrypted file "bar.txt" */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("bar.txt", archive_entry_pathname(ae)); + assertEqualInt(495, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_is_data_encrypted(ae)); + assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); + assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); + if (archive_zlib_version() != NULL) { + assertEqualInt(495, archive_read_data(a, buff, sizeof(buff))); + } else { + assertEqualInt(ARCHIVE_FAILED, + archive_read_data(a, buff, sizeof(buff))); + assertEqualString(archive_error_string(a), + "Unsupported ZIP compression method (8: deflation)"); + assert(archive_errno(a) != 0); + } + + /* Verify encrypted file "foo.txt" */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("foo.txt", archive_entry_pathname(ae)); + assertEqualInt(495, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_is_data_encrypted(ae)); + assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); + assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); + if (archive_zlib_version() != NULL) { + assertEqualInt(495, archive_read_data(a, buff, sizeof(buff))); + } else { + assertEqualInt(ARCHIVE_FAILED, + archive_read_data(a, buff, sizeof(buff))); + assertEqualString(archive_error_string(a), + "Unsupported ZIP compression method (8: deflation)"); + assert(archive_errno(a) != 0); + } + + assertEqualInt(2, archive_file_count(a)); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_traditional_encryption_data.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_traditional_encryption_data.zip.uu new file mode 100644 index 0000000..3e418b2 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_traditional_encryption_data.zip.uu @@ -0,0 +1,12 @@ +begin 644 test_read_format_zip_traditional_encryption_data.zip +M4$L#!!0`"0`(`,HT$$5'_=BD'0```.\!```'`!P`8F%R+G1X=%54"0`#S'WN +M4])][E-U>`L``03U`0``!!0```"E=VLFG3$F"T]Q^;J:A17F^=#3L<1CO8K; +MX-(?KU!+!PA'_=BD'0```.\!``!02P,$%``)``@`V#001>O'D[0=````[P$` +M``<`'`!F;V\N='AT550)``/H?>Y3Z'WN4W5X"P`!!/4!```$%````#O!PFX- +MNJG:A01W(N8M^T7N9=\_D!=4=?,$"6L\4$L'".O'D[0=````[P$``%!+`0(> +M`Q0`"0`(`,HT$$5'_=BD'0```.\!```'`!@```````$```"D@0````!B87(N +M='AT550%``/,?>Y3=7@+``$$]0$```04````4$L!`AX#%``)``@`V#001>O' +MD[0=````[P$```<`&````````0```*2!;@```&9O;RYT>'155`4``^A][E-U +D>`L``03U`0``!!0```!02P4&``````(``@":````W``````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_ux.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_ux.zip.uu new file mode 100644 index 0000000..7bfe796 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_ux.zip.uu @@ -0,0 +1,7 @@ +begin 644 test_read_format_zip_ux.zip +M4$L#!!0````(`&I.=3XZ-V8]"@```!(````%`!P`9FEL93%55`D``PBAADT4 +MH89-=7@+``$$Z0,```3I`P``RTC-R`Q0````(`&I.=3XZ +M-V8]"@```!(````%`!@```````$```"D@0````!F:6QE,554!0`#"*&&375X +C"P`!!.D#```$Z0,``%!+!08``````0`!`$L```!)```````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_winzip_aes.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_winzip_aes.c new file mode 100644 index 0000000..cc1e311 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_winzip_aes.c @@ -0,0 +1,152 @@ +/*- + * Copyright (c) 2013 Konrad Kleine + * Copyright (c) 2014 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +static void +test_winzip_aes(const char *refname, int need_libz) +{ + struct archive_entry *ae; + struct archive *a; + char buff[512]; + + /* Check if running system has cryptographic functionality. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + if (ARCHIVE_OK != archive_write_set_options(a, + "zip:encryption=aes256")) { + skipping("This system does not have cryptographic liberary"); + archive_write_free(a); + return; + } + archive_write_free(a); + + + extract_reference_file(refname); + + /* + * Extract a zip file without password. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + assertEqualIntA(a, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW, + archive_read_has_encrypted_entries(a)); + + /* Verify encrypted file "README" */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("README", archive_entry_pathname(ae)); + assertEqualInt(6818, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_is_data_encrypted(ae)); + assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); + assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); + assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, sizeof(buff))); + assertEqualInt(1, archive_file_count(a)); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + + /* + * Extract a zip file with password. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + /* Pass three passphrases to decrypt a file content. */ + assertEqualIntA(a, ARCHIVE_OK, + archive_read_add_passphrase(a, "invalid_pass")); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_add_passphrase(a, "invalid_phrase")); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_add_passphrase(a, "password")); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + assertEqualIntA(a, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW, + archive_read_has_encrypted_entries(a)); + + /* Verify encrypted file "README" */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + assertEqualString("README", archive_entry_pathname(ae)); + assertEqualInt(6818, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_is_data_encrypted(ae)); + assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); + assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); + if (!need_libz || archive_zlib_version() != NULL) { + assertEqualInt(512, archive_read_data(a, buff, sizeof(buff))); + } else { + assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, 19)); + assertEqualString(archive_error_string(a), + "Unsupported ZIP compression method (deflation)"); + assert(archive_errno(a) != 0); + } + + assertEqualInt(1, archive_file_count(a)); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_winzip_aes128) +{ + /* WinZip AES-128 encryption. */ + test_winzip_aes("test_read_format_zip_winzip_aes128.zip", 1); +} + +DEFINE_TEST(test_read_format_zip_winzip_aes256) +{ + /* WinZip AES-256 encryption. */ + test_winzip_aes("test_read_format_zip_winzip_aes256.zip", 1); +} + +DEFINE_TEST(test_read_format_zip_winzip_aes256_stored) +{ + /* WinZip AES-256 encryption with stored data. */ + test_winzip_aes("test_read_format_zip_winzip_aes256_stored.zip", 0); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_winzip_aes128.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_winzip_aes128.zip.uu new file mode 100644 index 0000000..d0f03a3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_winzip_aes128.zip.uu @@ -0,0 +1,66 @@ +begin 644 test_read_format_zip_winzip_aes128_encryption_data.zip +M4$L#!#,#`0!C`(RP#D4`````@0H``*(:```&``L`4D5!1$U%`9D'``(`044! +M"``>H87EHY!N6J#=V\<,#M>^H2IQID3@A--GSL+F%'R^%OKB.K(74CJ!,(%" +ML\O.^D'TO'!T<+"]"28FXP@QKAY]R+02!E!XE_6A-W&<$&SJ5W]K'SJ4>'C< +M?$@'%\!4L8>*E2K5B-8<[&G91%ZGYR#TGSS`?B00PF`2)_:"&O'6X:CZCFF! +M%LN3+RV8+Y:7FT;\[Z`8 +M#.*C"Y$E".**6.!H#\R79RP:B,[-8='=\./`9Z3YF]BYQN[ZTD.@T2SZT-A8 +M59C5?#Y?>`#F7G\NFB&V4MW!]*_J4CN%D2"IP$U5[:-]J%KH*^73=E]ZY&&_ +MH@"?_M)718\N(4$UDT]>3U'Y'_51#`T]QBA0@*F"5R:D"MDDPF5^,Z4N5:OH +M:&L^WBQ+/7QF6<>([\/MD199J8SO^V2=N!.2<@BHH@TZQ"\$MHH-&KF/J=MY +M5&`1-]@I8TUC(MU3P>1+A!EN@D?4?6O?L168`\4=(NM',IM@_*\S9Y)^7@R. +MD]PI:"D$H;)1V_N_P/(V4]&!C*#4N1WS=M2W:@OJNE +M@X^4UQ18U0=T;M8P&I[505T1@\8OBZJU1V+*78'SHF5W;Q_JVX\@E9"Y^I+S +M3O`YN"MKQK)H_EP@\&6"6\',T\BZX=]O&/R5IU>GQN-X&!]JD"*N]:\ZW@E< +MK9%4+86)S-B.Q\#AB]_FH4[BAJ$RVG#,\/)0!>)O-, +MJ*,\L)+13QE\5VV`B>.#3R9O&3('!,RVF`NW^\XOJBT['0#T/D]PX]]B.BZ^ +M`+DBP>[.SM-U?_(Y@:Q$@J0A_<8+%YWF+,]+BE88%#J+']@+":ZMMK0"J_?S +M63#:#=5\[SX0FK'AMM+%K)N\:>FJ?#),-EJ*J3FMKWNP:*,5$D\$MU?D_@"3 +MNKA?;'BJME"#\7.PX.,V)P=QJ(2!8 +M-("L@_W@%?TH4[V0?V:163N]'))S[M;-\I*XBZW['+(LU!8C]%]%&-MX3'3N +M(#^[<,$PR#R]A;'NY82IX95Q!B>F'ZML:;;:5X5@[X7W709-PSR:#/WKLZ7? +M**\XCDU3'O^C&C0M?+Y<\(U->?EDL9JF2AHV6]U9L/JGB8Y#T1JPP!]B]9_F2-7QX:GH@JT]3?YH6-G$L>6MOK](WK7$F/)I3K9DU:;LO`7+-8JA(?M9=;0.N? +M"'9;%TVW0.H-7M7A+O2200C5Q^Q,09=:(KP]*Q*UEW;?%1/9JIP;D@-:$]JE`.`6U'_)!X"%X/@,3_E#S< +MUW_8,*8/X%"Y0+Q(MPJ!Y:H(Q1R[X"@!.ONDDG&^LZ-0SB=UN25E1>9,(LW8 +M$\8K5(DX:++?=]SU4J]K\55,NSC;']1A+/J9C%0("NY +M0N=]F6EN^O:M_E96^"1"A9$SF]AU*Y,?@2]/ZKC +MY0OTS'9AG6;L.PY^QMI`#RZJ8U7"`2']I\5>?.$A;C@!4H;V*KB(YZ.ZS3LN%'T6]R68Q*Y$+^-)*X2 +MD*Z?V@2'1,U::-Y/.($&B2-=UOI`5[2CE@@T/H;@[Z'73^0(_1B)I+3+F +M<6CE>R;?1'C"L7>Y^5/<\FVV`<\E>?*!GQ(M8F.E,+FAH["QI2>;_T4#]8]? +MMACPPA;T0T[/.<,+JU"$"NBO*(JW_"D$=K$3K)R4H(-4Z&"TMLP$-`V'38G$ +MGNJKYC/]9MO*[3^M;07[[#M+@U98;,RP<%K?.5; +M5^!"?!:PEI>_*T3+M2(\V_PEHKQVAJ=6AEMCP"";"B.XP2\7@0>1SY@!W0\: +M>VY_6'V^*Y]=G^QMA/JFGW\M'7 +MSJ.3"7BX%C,0@V*0Y6%,8&K5PF*,195H"_-&"$C;PNQ',@!TQAI@K_0]3='< +M"5YE@'VL79"@ID!9N3!L:(".,SS%G$*72RMF'XUA\0\F9?-K])5\JQU4S&,, +M^;_$)Y]?[`.&-,'MH52B.,7N<24;^+Y0H-GEO#)>/+?N5&?P;"^SJMAC2A*\ +MYK7^8>W,L1!M)F*C.?;253MM"?Q[E(OG6;ZH.EHB]@LYPF[+<[!(& +MN\N=YDLSD.;+LF41\,^U0L_<$GZ!RB)ORA"ZU)N`#$FTL[I,5?2RR_VAB)ZA +M`7R/?*U[7XH<)T:S7Y*TL<1E^0LO4=NW()(46_)Y;WH"_A5F5-1$.I*C12"?[BI%-I:,6_9<.$W(V)J!L0AJ+//9H5":1Q>2HQ#J$ +M$D#]UA6EY1K=;`+2#+;SN(U(6^/L@29`!W8UX/!?@%M,3_;+4$L!`C\#,P,! +M`&,`C+`.10````"!"@``HAH```8`"P`````````@@*2!`````%)%041-10&9 +?!P`"`$%%`0@`4$L%!@`````!``$`/P```+`*```````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_winzip_aes256.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_winzip_aes256.zip.uu new file mode 100644 index 0000000..a45c8fb --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_winzip_aes256.zip.uu @@ -0,0 +1,66 @@ +begin 644 test_read_format_zip_winzip_aes256_encryption_data.zip +M4$L#!#,#`0!C`(RP#D4`````B0H``*(:```&``L`4D5!1$U%`9D'``(`044# +M"`#8+Z><':+DENQS9*!7Y*&!7BQK,UN]RF*'<':@;]N)O5>]A5>0[]C +M/4TU`"Y%KD,Q;V2W_NEI5;0-K#T.V%NY<)7![$L?;Q::E65L97^;(+=(2IFV +M*'V?"J/<$%EG^(,TPE7;:2^<$6IHLS:.DOJ1TANF&QL'Z>'ZY\:N^L@0VR[U +M(&+EC'2'.[8;UR0V(5169*2.:4?INQ>39^)88TBNQW?-GB3GU.U.%S\H^.0P +MYD+[R+-`^RY.XG((?EE<)XMHV2G=,5E,UK?R9:>FP4W2O(M8.D/P`W'HQ`K\ +M!JRK)[G8E%$_?=33Y8==ZY,D%4*7;1`=_G^+//Y$ +M2%I`YQ-RB$:L-;KU[W;V^4!`Z'SWP0>32#!#KM1.%WI/&D2]EM3IZRZ#@M"SML^ZB/,-1 +M6>-.Z,-C%)36I+!%R^QJ$W"&OKM$P>?77. +M\2][ST/5[OK@*I,ZS(XRI=PZPK!/^TV<=Q42TCAH`96R4C`"\D5J.,E-;,3S +M52BDWJ/'-B:_.J&-R[>]W$`6#W9VNCR#$WC-;P +M)/D[F[VO:O`7;O_%\.BN0N7Q5SQFS:1.S[V&6H +M\S(8:%*DO3UPD/*"(S#>G/1GR(M=JF9Z/@H"3]\4[G==.\O,Y4(0\DVY_V(< +MFP44+M$S4D$ABU@^K\D@2Q"3,=.ZR9CVZ*=#2`[YM)4$.T#L2SR:VXJ.M=3) +M!F2YHJ`U!GA;:^Y#WSX@6 +MT=(M?LQZ:E(=.$]\LML,'-U.Y&P-`FU4"4CF#C&%8PR+7(M? +MV7VE_;VA70@5%><_*-\D&Z;FN]1A"8W)&>Q!4O.X)65$<#5\[]FX!TND,&6\ +MH5#"C;\,^FZWQ"%FCT5$$282/OE!U[0VWK`3K,SO3/R:J_`9#CJ$O4FR,0MO7M7?OTI$?-)O6IB]@S:3G +MSRI(3B.4H06![4#@B3T^,J[EE].'7VK"&BC+5&DX^L(TG^:`*'YU#5[Z2Y2U +M%[A/-YQB%8R9-T@F]NI%`U3@&S@?+V#?OR8$[/SN4**;9-LXXV?T.J-8>??] +M'_0#/'F(I,WO106F(PQQ=EI-4,[L;`7'R)^`XJY8%G)--V/<.,+#&"A&U#8/ +M/!_J*I*6/L/';)&;1#D7Y/-3V1_SAVS)_']R-[&N<=\$6!$G(LWQ6I/9&U@S +M%PX.S]]<8(1R`[2@P^.?E`;#AC:36B%9VKS.DWB;D96Q@B5N1`JS+- +M$5@A"8/NH4RR`9L-W,1)^$M:%_0Z;]@!FI2^P)!HB$$T,D!L5T]3>E#U8+EX +MR7J68E#59VCL7$C^O\%,UU@F%1Z)@@XO?DL_9/AI'CAE_H:8)*8O.C)EZ)3J +M_/O[RV"G_\L6`_(&JC=%*M-,\SH*]X0NYF7C!@'AB1?)0%V-'&&S4L(JKU"R51LN+4O +MF*-J;GU!Q"-VMXQYE)W"!2'\CA:#TM'E!V=4LVPE;21ZFXE?`X4!\-%BE>G4HP_GR=?.,=RX1DDS@L;ANO.>(Y(XV.E?75/Z%\07)# +M29]G3LC#1*7;/U.>0:YMQ(&(;ZI/HD9`AP:,7"K[)BD1&QGOUY),VA_D`WV5 +M&=6QP3BO2EH;9R$>D9UNDK5&1<%Q$=T2H:[?6NS!#`$]JUJN)KDA+;\?OL`V +M/UL!FHQ[E:#KM',87??MLQ//57G:Y"X:W@Z7T0"/=O8UK\IOKJ#/H* +MRY3%(H^4QTON[C?(A[`)G'<.'#])^W7Q$:L.,S+Y#NH50*L.UK)!Y&=9T9ZK +M82&!G,EMJRAS893'@XN!N_2W7A$%.VW:8VBLC(.T?%T>%YO>TC761K*,=1;Y +M:3;0=K&-R_T0]E+,U-..&CB'G=L_7^62Z&7;`4^9XD_,QW +M)2R4!S5A]K1!D3!'M-J4_II&KMGZLJ=#$U,3'[!3T#W\Q6(,6YBG2NIJB/'9 +MOB*97C,5:,6E=>'TXQEFOT^<37@@?)!!+&%+SKZBYT\DC%2"@Z_]MSTYK@+U +MT*QLJS^\7=DWP@0FHR[.&@B47"0QM).3I)@<186J$T7`RZ<# +M^'P2JU?A("I4%VTDRLQUTRV_;Y&(2HMG/I>Z*5YR)B8M?U;S7H,3Q3M5#A'& +M&"[AV@.%,6YZ]Y6DG9)8`=2V'K#CTU#I\6=HL?\;/#VPC98#JBP9 +M`\VN+W02QK_,-`^I-Z0-K003Y[9NR__P1^,OQY[JHM_MA8Z5M&?HM.1TO98@ +MC/VHMV#85&XLFNN6VU2JXU'>=U/Y:"FI&&[=O?EU=`:WBO8+4%_R/BNRO(R: +MYJTK]U@)6&^QU>:;V)>YGKVVCR=?E,A.60O+AU3HYMXLT_OVE9QJJ-ASQE_$ +M:>T@FMZ\CHU#A]5$J%50$8!"B^S#K_LK5I[//X1DI%60QG4[2@7T7^I]F\Q0 +M2P$"/P,S`P$`8P",L`Y%`````(D*``"B&@``!@`+`````````""`I($````` +G4D5!1$U%`9D'``(`044#"`!02P4&``````$``0`_````N`H````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_winzip_aes256_large.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_winzip_aes256_large.zip.uu new file mode 100644 index 0000000..4d88757 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_winzip_aes256_large.zip.uu @@ -0,0 +1,2184 @@ +begin 644 test_read_format_zip_winzip_aes256_large.zip +M4$L#!#,#`0!C`/BN(T4`````)S,!`&LZ%@`(``L`36%K969I;&4!F0<``@!! +M10,(`!Q_XQ6]5"C+[)MCP!]MWAL_K6)/9Y"'\EPQ=F7!XFYN9YYD16+`R +MJ^*NG5F#7*H@[[VO`_0MDHU,"7]4\# +M4V86&0[_`ZJ9'B+#N:@B%://Z/EE2'W%JH/+#?NFF-/IFF_I0B*?&KDW"`+_ +MU!+4``!H=]K2;$[G)#.J8_8$L]DDDD?G)C(GU.LOQ\HII+_3O/DP?VA>FF#_ +MB$+[X4I09T2D\0$DJTZ%$V\&)=1N@6U&1NE$%D!1*T_2?8:H;5I!= +M+)?%:1:,Z/\B)W1CB +M\SS:GW1>DCY,DJJ8W`@Z^2U(`(X3@P?#Q.^=>8X=K%$HC;[BU$#4M;'\)?> +M3I?TVTZJR$YDVU#BV1AOJ,ZW:W\6ERA5>M6`E'MZJ1_@NTAY8Q= +M&>)Q/X&.M\"V0%?<,4]0`GT_P8%_6.PUZF5_5)--U-K9G/.IW>;S:HR&N\#O +MJR_:7ZV5[!Y'<5H>K[QD%0R#SN!8@38X(')*;:X8'?"Y7`V5B"W6R>9T1)Y^ +M;H1%A\SCW-S"V:A(4X\%R,.>)U)D!VD3?_*Y2SBNJ[,AUW[?E*=X:A!*I9)K +MZ*W:"=G%A>5=)?KM/,:T>`71!0"UX@LQ**F(4L'&Y+;[B.,8&(,\65U(Z[C= +MLO&Z>>9A24@AI+7&I45/";#8[6K<5E7M)WS#FA:J;E$-J9-EU']T:N6?A].[ +M6-8^PJ07O@FV"N$8D#UN0;%"_^Y#&!)/S`7%QK8GD.M0R*FP>/)]99''D;SU +MU6M:I3U"?+A6Q?)Z1,SB@RXK]4R(+2H6]<'<9S:4D8C[5]@P&?8HM^V?*;LS +M)"@-'+4^^XW@=@$QBZ*#T/WGIK5*9S#76[T`(B`7N7>_-_^^TH5A->%@MUO3 +M\;#'UVB_[[NE0]Y0Y$N=FMI1>CS^2/W48CR91UY.>`(MB$__A9,S2B^?O<&% +M=T9\^'#\`0.\^<:--^@_]C!=R="HN`4D7;D>EG,BR-KNV?V0;.V +M]-=57@XLF&X]CQC'I6VJCDSJJ;0IGI'BL<9W_=_FR,Q_Y,AYL/V8]K#.]5,>X +MS)YU)Q*Y`X6GAK'==Z6*> +M,G8CVZAQ6, +M?SK_;8Z96AGX@68V],.=_;'*5_B$D+_O+;J2GY#UM_W?DCIBHU`.=>^<]FM% +M5O\'SSPZR1#C:4GI5K/HT#B^\^Q2>&RXS!$0 +M!1U/L0(1R`V$QC">%"3=`1#=5P9WSL9#))4-V)US$MKA] +M(5"^Q#J&EH\:C2!&_*U3@T9%B%WB+@#5G/+PL\WE-WNA"79,O?$B'0Y(WD!R +MPXXT!!$@-%<;[%;&598OS711V>VH!)+[`D@03>LX;R4L58R,L^Y1ZC?>IN+' +M$B<+"DU&YQ&F%M":YPQ(*/--Q+RD_*X_,]],XT>L7HW8-VH]&S,=Q`)(-%2Q>NQ+/R$:<9ZB.D->UXJI.%J0;,:$= +M+[H-=0:9BCJ%]SQT=%I8VN;4G_;IK"![=SMIAV[1?QZ,W37 +M1$^:V`>V1QMO4HKY[EA,1PPJDWBEY88Y/;!],-^/S2\[3O"-5X0[_5TRS>^OGE%B:NKU5``\9 +M*J7JQF0E5;P;%GSHEZ]):Z1Q<`)4EBF\>H]5&_\&@&#]G#@$4ZT>GUFT"D]> +M/?LT?%^JD?S<>(..+UEHA#C(-7H;;[96H_\9@!K60L[N]`1>=V)52'IG%^H] +M9S(-@C:N)'\*OHDNWRPAWYL$^/KTA)49H5!67O, +M%H6U"#=#7*?I12ZO%8&][,=NR`3H5899ABAMEK<#Z*_O%T9".^VH'$KT#-#= +M.9)<8OLN%V<_>FN^._!OXTTMEKT3HW\8=Q,D,G@*910#]6%K#^KQBX(54YO\ +M-BB=U?KM0J">P;_>IOAN9!$G&AW0ZIC>+EK=UF(A;\"_58ZVEJMU`V9P'KP; +MLZ8M@X#0*Y3-RW\CU761+BBT<9[&.'[V`E_G8[=.UIAF),$9&T^`H<*T0K!/ +M9UR@J1^53GL.P(?6.UJ"L'+`DN!+]BR)5ASJ8D:<\=)-]!I[#[Z;9`&OD2`I +M1PJ8BIS5V59W_*.\;9S6,\S$VS':H?[HV=2ETH)/ +MRQ%)&JU3??RCTN)*GF>6]C`XH#TO'DZ]/&532K^BA#1RW6C-[< +M.W?3.BR:&02![+!I(]]*S3BO[BLBBON$KX2;Q2MQ<_(0X#S;F"8.1>BP\E.T +M0(.WH4:]L/JP!+'*B79$Z7-R_;2Q`SVCPD"GQW_S3UF,RF&D[DY0I7&8]L6M +M&-&BC.C]=*1.V5X:9Q68]HD`"+:0LH#]URN8[UAHR,9*D;@F_;[_B8U]N-7: +MC;A;JO6-,I1P<9A=;2?H5A$:XA8LJC+D\AJK2I`"D^BL9DD:\2=S23UH?Z+O +M1(I(Q?XEP4IZ+A9(&)=-2$N>D-MME2XF%;@+:V7^ND$4>KSIZ[PP3#,T``A(\^GS190"6D;Y3]2+@47L"FTD;Y9\-`W;&/130LQ@ +M`YY3Z[V6Y1*Z$'JZ8MX94VK\PL_/#SW9CR)_VHZ-S+BMJ$P +M8Z2CH3`W%E-,.XK#7A`!2=?5D4A]_JN2\`MO$+S$PF'$HDJB9%G$P_CY>OC: +M!>G\B[Z3038HM"$B[;+).K-Q$EM*V]LB*^R10]>XIN4WGZ3/VYW87CIVK,PB +M>K;"J#BW,DJTE\Y/^;F4OYJ/)M#Y=DU-K9)_%R_Q2ZXL2=UK(U.T:6K<\#YH +MC(`,<=@&L]()LOO37>-%GN)*T\\GV7^\MVMTH8IK^!8_OOK;`/YOB+^-!E5P +M3)%T:7]JFT?WNEL_=R,PF(?YE$W_ZAOX@U'Q,/18,4Y*A>7?IQ_97G1/G[Q +M3>A2,[J]0BQ"E49[C06!)(FY+HC4G1:?RR`O4%6M]K:7GNUJD/3R/]"\"!L0 +M*C:PI1P/B=Q!]Y!Y.5Y?O+ZIZQ-8D656E(I'`"6/::[2S:!.,["7ZOF-=W.7 +MVI[.95PYP.+L9\Q(-2`%!_FP$1O!-TI>)=U +M?/!#"=.^<8<`G,)/R3;&.V"9+!EGU9+KI&,LQ&/#!=SR)>[$B<_&R7#5E@:' +MG#%=H30%`N[MR6L$2"+,1Z5ZR?O%J^BFD[G&1G&K9O%#HF8,8Y)7NJ3VXE:; +M/1=1U,ZF9FOS@:[.VQ,O[IR-2ZX+9I0?]4UTU?Y@XJG+C;"C#]C)AE:%00-8Q%*> +MYZ= +ML7CT?9/!0W7VGO5'[*<_X9#53.JT96[XF72[[R!&#:P3!N53 +MH$U/EII?ZU4J.ZJEA=+#O$,M3>&?RADX:[AW=T63G7Y$?I=:W)FFBZETQ;U0 +M,"@_-?[&ZD3$4'J_G)Y\F'9"Z-9DZ*HWH)P:J:CC&$*:$?H$FC,;WONM'FJF +MOXKIK;NL"?6+=JSG5&K(P"4C]\CB#UW+_-=G^O?KNTDN_38!ZM&)=X1K+.1? +M\6HZ_Z%6)ERQZE;!;Y;HR&?-V1`13ONYE0F9I"ORBF!D59EE_Q.UKR*^?-WQ +MYT#R)),@-6'=>5?TA-$N,=C4)T;'KIH%DJBM^MYSX-)/&>\MVV.CS^]BF?FL +M%,%\?[!MV1.E"A^^(C$:YG0G8W"63:V)\;;7SVG@MXC^W"V9Z2]]Z;8I9JU@ +MM@QU9*L:@U\$U``^+OWWZ4?`:>_XH60XZX]1D*G9CCX004O\H3!QFED_C,,4 +MXCRJ07_8GN392ID^;2Z2U=8E`0WF]$JCU^"OX.9")=27D&$'=>4RR)SX."4R9TFC/Q.&21+F+/U]$C&6 +M-$0ST;2)VNW%-AQ4-3:I!WS59X])?P;_Z&]K16J^" +M%=]4'9M*&!GG-*;?!V,ZS$`(J@:Q/K-D=:]O7I@W>S6W5R$K)BRS`0C-HK+; +MNDA.[K2C1B6,)<<\:I<.%=M=1-AP`\2];7V9KJ!\7'QTH/3 +MFL(L0QRB':;>)@(Z%DP_->J)O8Q1K:A/@+FT./ +M1(E91I\-\@CY_W>@)Y8&K?5OGF1;+;6_="1&I(-JG/AG!87&UI$5COZ4B%:` +M_>(D#5M'MS`P/TM'TB['I&[JS*"$R,AT7%R-3?6X)+*@M"@9=S%3(HVNS'8Z +M@BP*/C*5U//O;@XQC;1&<0)O&N4&=).G)`SNY^"9'4N:K_QJE,M8^&W +MY%>ZC%RTBR-IVUY7IQ*H.4MW-H*,;$#Z=NUYTX/HPMAWSH?]G8_@?RQ^>5$9 +MB.D(`.W":Q8I;)+F5>:DLV_+KYEDF5#W3BZ`G[32,B'6/]7=&.`'>K@\2_U> +MVD;[Q4MG#ITLH;YH$&00P@!\2!2B>&BYF@,F-^LWY#A%5ZJ6"0VSM..+UFD_ +MOJ4J`/,O.."T9E;.LEO4E@X(BIV43!Z*J`DB/;9AU2!2CJO;H*RHXP8'\*8H +MM]NTT$_SY,>'F3!?)0%*^_2:J:.E,T/,U]&49`Y*3D.9J8D=!B\A?)*>]!"G"#LAT8XW[M)@F6GE5^7%&; +M(9L^.`(#"Z$>_7O81IW/:P>=:PS([@.`XIAK@@/MO\>;&Z```5CVM>&BQ->\ +M\;4)LV9IDW:L+572&+POE6R^YN-.$(:X;9F8\P'PMXO'5@:W`T93SL2&VN+@ +M=)#AFE?H2FW490WZSECX7F(.PD^CR1>.=W!+;',P;J,AY2 +M)"?$(S,2O9QXAN01:[.ML%/'$/"#F='DSQ!EL^/,8J-&U,?1,8Q<"!>2C;X( +MF@$M5V>\ATHGH;Y3-A+G+2[I>5M%;QD);Q+0[+JA'Q)%"&CTE?:M']&G0:_' +M%/GRG3,=/"Z[B9(G8%]#J>5OXO8\K)]DAH`&D*\B\62VOOQ\+,QY6'(#\VLM +M/HA`L3&4K\B_;\;*KZ;VII/)WC-ODA9`2T[$LJ^]F+='^Q1`=K)WT(&42%[%\Q]?? +MS_+>$3J6BWHO"Q7*)#3--M\,T,FRZV546EAD;GY``6N[U+$0$9RR_S9DH%I` +MK>:^74/*H1?);*I+4/_ +MS>FWTFD/%\>%_.PTPE''B%BDVT,)KPTPW,3/(UV;3, +M]_8Q20UR#[*,OO/O;6V,0H-W'!7]F@2/@L"[6BM.(ZH=.OHQ7B)^$P]T+JA" +M]02$SH0]FC)/`O[`,`E_-OZ0G$&#I1X>5!.\F"!^=EA^H2?!_:YO+^Y59 +MD>G-\=W([?2A2$`6_L%P^*F1[HM7^9;56.QHNB#;"J[$M\,%_IG'R0J_7L>C +M7'E/2W@4PK\INZ5*I"C8"O:0E%0T.%FP.GK*Q85FC*CV"*";31HZ5=GPRJ\! +M)^T33H`/=>4HWQ,&)G%CM4:&JVN8_9R4\'.X?T?'U,,8$^Q464+E$YS34>!. +M_J:%; +MH#&\VGE9Z:/A_&X+KQ7&9;5*CB)37%5/\IZ=XX-:"P*NY8XXADX6F56^!/6M +M(*/WC&[3J9\;T\4-X7L,(W.RPH<8_7.%:6D*GT5"Y(KD)%GM? +M"C35U\.&-@"=6J1E8\RL%\K($$2)(OTRDU`JXPS'5#&"<=&&L4X]QS*-.O2L +MP4(OSO]U1IDB0.(0V80A[0:8YD\K[39\)I4E1ITCT\Z83\*6']J6<=-6D4.C +M;H_XP!NJ>Z$,E"4J@\2$FR!$"+E*=@R59$>,PEO-5`5/Z,5$5>E(&SU0D30+ +M63[,W4CH5`G"['1?FI?4!$1"2K#\8SW/ON?C%VYV<^O'XF5#M^UV9O"POQE1 +M-H:%,+_^.QA[F+#T_%_NZU_CV%&D`>(R9MLQ+([)W$0ES7 +MP29?B%F-WBL$Z@IU@N%H$G$$0O'D'"+CM7'1_0N(/GS`'YDX*K_=GQE6E>00 +M4E5=;(E&QP;LL0KGBNJ$^NG<;*`YNQN-G(A?3$3PVK\K+"_JH5)C5#*"C>4> +M2%])*$[4C_?,&'=+;Q.50HWPWB4:5%433=I3V/2,WKS5W'KF+)$(A-/U,,Z^ +MQFV7N6,94KI7OE3-U8<]1:#ZCN6"_)YB#VPM'0KDUX^AJ3P_0UV?I(RDA32S +MW^,#LDY`!KD260&GO3R#/T@`&&=/[.7=M%Q::*7C::-B0MGM%V0&FXPJ_N7L<%4DDT4:J!QKKBEGHV\C)6 +MN_56.D7![NZLU\VHHP$6:'T5-O&>#^79=;V9B[4?N7:<9_4\L>I1[,M<2.(@ +M?)L/JC9G^_6M_I]DX4CE:*KBG]'JSTW<\TZR:.SZ2M/UCZOP#"*OVQ<^2^?- +M>3O"5=XQ#W!2(=*T,3R_KL>+K1=DC;_@(L;S<. +M$R!EQG+Y?3WX/-0+OXMN>VW[EX/4%=AYVM::*+$E13[:+(TK3<5.GJY4Y/6P +MMK;<%2&KA;AO')CK+$2(0#4PM!R8.`(GJW/T428W'RM7P#@_P%+YHJPGB(H1 +MN?4<;@AZ_\B*KDPX_U05%6C1Q1D\;?NA'-E<[>D!/G"K^9U)J6$,6@5;^:=# +M\QOG/WR&"X[\3A)4CK3MK[X[>)X.BA)4_3VI0\1F\:.75P$VFE8+E;K2$;G. +M;CK\%Q!A9Y;(CQC@/JZ+/S*WY5&B^XRF^MPK5_1['M3TOAO\\.,7BD=FYM9T +M(%;O&0"SD_$?C'-N#X\<;2ND$:)9>8XXN'5SF=R[S*9"(MW;_LS(]Y0T4%]E +MPW)X-#R6`:M@EQAA&B,.*Z_F8[Y0)5DCGZ;KCKO"$QWPV82*].=/#^-2GR7E +MM#A`AJQ->I$C:K/KNQ`_0$FC;\0\QLE\K8W.^_R(Z403'G&K`1W6SOL*![#8 +MOI.$:L`TQ\T5$OQE,H:`'+V$,9%(_KO=8I$)]I#=?;!)4 +M]I7@^&%Q$]7OP#?&L6+?F/?R(N&6E9Y]44)U6_HCI0ZD3EJ,\FH;D]33MP"!%`,B20)UF +M?3\W8M0[B+R=W$Y_DR&/7"68Y$2$+4$P'!#-8T$B;^]#QEDU[^:=:VIT`S.+ +M)$YQ&'CIIZO!TP^R[I?!XM)F4AF)2SDPLF(IXDFAQK'QC#)H772\'_'T%!\C +M^$7G@)\KB`3].9^8://!@94_DWM"T:VOC,%N.1I#S,T=UFC$\BW +MT)`OW95-:(*/QXBXIZFN%S/<'JP]]!NK*CSF`B"ABX1AF%;OK[(>-0H*I1`U +MOA3/0^5MBMGHW7ABZA@L:@%I`N=1(8,0:?B7I*C!2WHIGN4^5"3+ULZ/#AFL +M94CN'L-7>C1/9P4X#;LY+C#)F]E,QNVM]#IW]_H9?=Y!_R[35Z-->YQ^RZZ# +MN/IJ],N7IZH`2FT3);`?R=SY!*\ZH8-S*3L9&B6)7ANC8:X*?0*'+2Z;YDZ\ +M.P]QU9-.EP&)9:^'D:?VAB-\GN]!-&U62>PTF`6#Y!U=AM=>AK$E`7MI#P%/ +MJ[<36">Z&\!FA]U*6+2TNUJ<-5&J>D?SU<%E&W)I0),88"2<;.Y<"![O"_I? +M5:N<>HX*)P)>I#XUV9/97_WPZ>M9$.S@ +MV,WB;#M@7#:E[`$NP%I-;;O"V1_DKC*7H@+"#.@LM*6G!7`!09Q0\A03(HMB +ML,6*/#'>C6I5XO^+7:1V7X&>L>17VZL_*1E-J03NH[QWN4H(:O_52#_>BTYN +M[?UNU/J]?``HQ4$E?'*+Z.U7Q1UE5/1(`Y-;'RY!HMZ&J^$X].>6"JXIAAKP +MUU:EJ*&%@B4\SZP'6QLP]"=TQPG48*0'FI8+'5AM6#L^#+/#4.A>(?*'+*<( +MG.7I%+G&<`AX<9YI$`L%0&_!IHOD!_F&H2=F\L[W3Q)I'/89!2;U'?#OIQ6! +M(\O1EMW(1U9K?+4AP8.#_'Q6Y`\:K#^1,JU)HULEA=43#MO,J?7R_.9+TCC- +M)21=`0'=OKMS0P-LCD5,"2J9-,))F,+5$>3?XDB+Q)QZ6MZ%1EVM#FHN565G +M7[Y"(^27/BD9V$`F/Y9&1'SDT51]G]R\?\ED3%D/(9Q`\;6VSB$MGU_K?A&- +MUECQ'0^AA<`DCC`F#:IW_9:Z%A+/4#KC2%&DG4JI'**L%_I)R>,:^+'->FU6 +M[U",'YSS5E8M\F>EEDIZ!ZQK:2PAHZ,G=UQQ.A1=>.?%"W.A$4,7""$=]L>G +M4U.?+^V\6B;J*K*]R_MV&9[C.R\S#)G#&>0C;=6*$1.+U;=Z:*+`[UJTC?K> +M(%YL5RKX,ER-0%B+-];!!*IKWT +M-@NN_,CC7%#],<7BVTTO',C7RK,PBUM&#:OY1,XN(XP94HR/!3\;<1!<>9IV=)E5==:.V'HJJ#NXJU +M5;&B<7^NO[G;^F]5--!_Z.CC)?9=X4>@B9]]=O1<.=,Y(HE.M?B)J"[OI@(7 +M_%$8X_Z)QJH8IO$F74U34NL&^\@R?H9<`_.Q>"'UP)8<$:@.(^$T8NK((S\% +M+/\XWJ8IW\4;9M.=+I?@5]A/,##_8LK2=R>YQB?XI)/4%@H2E+4$XFG9'0.J8.^I7V +MQ&>>.3Z;N&3A6(`[!=\U?&2%##>1C?U_2[1X?JS=(GTY7>8$2@_#(R?6Q^$X +M6VL0;/S.-0_$Z$V3DNK]J--4-]!MNBL^813EQ74G#M<5>)W^5%Q.H%6>'`?` +M1"O^%''"[X>I$@>XERB\]`7A1A%UW[CF*"5X\,K(-3N?T^M3+I*_C?]NR^J# +M(G3PBFQNU>)?1VG'!>N&/116)FWH\C2/,+7P,1QL`>!>K%\1G8.P0T$4^?0$ +M`WNL2D&M=SR@^4Q2@L)DCIO"G:[0NGDS#L%Y"PB7EG&*&U-/F4;]//Z&8C(< +M1A]_6W#])3E,](#*>6>6`/EJ(*AVQ>)M#YX)0:^?YKL\6,D)>K]^0/2P9I.887C^%NKWB4LR4'T3*:\8$1IC:N1E* +MNI##WR(^['0?+)OL1@#-=TQ.A-.VR4%;.MI)&L@=]J_NAR$"A&9[*[_1F4F" +MAT_OG!B@-2_;RR0BEH[C_)8RRZH=U88R*DB^CKZ2J^T8X=(T1-3A7^A]9S@$ +M*B/9#;A&3=FQU_;E*:?%V=7@ +M7DJLV^!K8I;PH7@8I&3&IVGKCE"4AH/89_2+9(^Y[[5$V+&N)E4U]L,[7%TDUR:"U9=#@7JXBT +M?`#N,+<$R+7%PEC,S'D,VI5$,6FS%"0!`$K`2NK^.Y%M]V`R7,9?FL#&%WH: +M/S0#?AI<)SIC-$;(=YC**35:"ZBXU$AQC[U?@JGIE6.#3,BLM^<,L8!<:!J# +M((:H)]5(L23"3%4+4N$!N*%I858^MFR=M2\#(:?9)Z5&C60.("N_A&EH1!`6 +M6F?D`F]+YMZ?U`^I5?FBQ6Y_,L?!R#C4;$4*1!9]([L&;-[W9!'$NWP`NW'.[]?D9?2>)U4!5HH +ML8@()=3SAF +MG1Q4EE!U!VN&ILJ&J?*9K8U$;'/HV0F%SGU+-".]/0V\R)*_G209[4J3I)H# +M&8.JJ6N1!-4"EI>`JU%%S6[7:^FX<(45X'6U0;96;&1H*UPK6O9NP&>"*K-J +M\]678BZ!$'4`E6R"%IVCFY`1';^0H_*P]WW*-D\4!E>J_44%)$G2Z98A8L9G +M?D>&M[LQ'IM]%OL'R`5`V<5"_4_@@`P0L/:"U.N:RK<[,5XGX$=1X^GRZ4%O +MR7?Z$Z.!T4:4]%QPAD#3>]-9SL6NBT_"MEEWUP;D7OHZ[$>;T83@:6=V7_@R +MCZW)_)AB:BN\U+E1BQ`(3OO5A0X!MJW4,'OQQ(.:J&CVBZ]'X@62*GJ4 +M:H5D!!+R4$!?^:_G]0L$[O^@T#EIT-XNACE8?? +M*=^![>+6C#FQ0I]966J1,*EO1[CZAF9='NAI]`*383%,0I5U05FR0Q$G.%#Z +M)1Z!X$+H5^':E%]RX>%Z?#JOMOH\Q-J\&R_(:B:X\[""CV`%E-@IC1==,$^I +MCQU5/KIFDB5T,>_-Y4GTQ-!G9QNUBX +M!CN.ON/2D^!88650-I(2T]T.EC@@/GF`,+/YD/,L`EKM\9ZF!CT0![AE'L:CNFE)NE+[N +M`F>M:`NJ%(3*'MD"OMOG",-0-WQK3.(89):CE$J!+5:RGL/OSCAY]G7[_+`(S9MY7%8BI(8MZ9R-R& +M(YR`D1/Z+;;QY=5MOTS4H$#/*I_XH^D^AFXT@S1FIYW)5:FRHZ?^C#S!IPBE5O +M'6W.S:7JFL_*67Z^.L,8!_,U)P16##)]%2A+;8"S/-0PID@\FQ.\IZH4)<-' +M?[PAGT$6%5`4/Y4VI8.O6"9\0JG3,(.2\0:*8US#JL$*M!%(J&^VFP,7Z4T2 +MR2-4XIN6OO#*^/73CH>@$!Y[3$"@M0]Q,0YRXS/1M9VA[OR8K+:D-MHFI<5? +M9=S1F=.(_F8`ZJ2_Y/C$<5]5$VWLFK.40-?`\Q+XS=*_'&,+,9:9A(NQ%T"; +M/0D39!86#V$0P,&1YV;H7;,A0J?T)2!]>PSG%H6TO.5"A1CNA')+A#8&6 +MO[V^N)_LO48V/WJY8[4O^;&Z$?Z4DCT<#G+C"W!@RM_,3-:_!O?@":G7%KZ/ +MRVM%ERP#(%U_^GCU$JSS'A%1[.*_.MH8!]LSA$TL1J')L07J3^^5A]9!1RH& +M=$[0F43PYVH!]_Q=%&&>=P,PNA2#3Y5;C@)W\8<[:U#66P&*?8JRVPZ%>DM` +M!=/>:R&N(B(,>?RW +M!*M4AO'M^>;W=(Z>:1_6PZO?R.Q;2W"+Y+5_GWTT%'GUHN,%9G>8&Q*?10$< +MZZ#I>T1KH`P.8GS$PCD)>WF>*];$8W@XWL]>(64DQ8N$+K>99=C@^EM'@N?7 +M#6^^`[T?@BW@I%$B7H,!-^![_AO9&KZI6&&`@CC?@6;WN+EZ1! +M9#`WD514=^9@2@('MKJP[J`&WSSNCA9X$6^F/*P9Q*.E*EED_+'0A0K2^-<@ +M\F:T4,X5"[[Q\V4^S01/,L3TKF7;'H(6'KZ2WL.?^R$6LVQ"K$,9O)2U<7F] +M@VIJ:D0+9U,P)Y*H@W_'*PMYWVU>W8@U.Z>5JGF5,)I9C)LW2YVN&(B8]@]V +M;[-F5&9D5V'Y)O@RB-:N!B:1YFH%@RA;;YK2:VHS;VM9_W$^F)Y40^L?`NRL +M*=V@L*O#I?=I`H@NE:64;V%"B3\$R#]00L4 +M5.>=-^SNCS4WREOJ;3450]'#B+>U[)SF!M15Y(JWD\M%73RZLZI)EW+8=Y`.&_ +M;"CKOJ&OY.TY1@_0@C'F:(<[6).'ESBAW).J\\C'W9!/[H?E2NO1'9V;'=A^ +M5?@@PH8P7(I:AS,\//'\KA!8@BMS(XJQP(CH,X%F$H8]F-,((JUM6(%7IJ=' +MK%@^PY8HI'E86J/V?A(V+/'`--7O$4^ZZ/I0E:<%JKE]YB#)MIFRVCIU>B7= +M'\\\S;'S@`(J+U1U3;8?I">/W\R`39F%]8#]SE.!&^9Z6_D_=M1R-LLL!YL] +MI%EW!%Z^VTW"UX#"C,UU`KISSP8@FDQ,3`0AA!.`U-&%!:``=.J-*?LYAPW; +M[2L"N.FGU1;9$YY_IT(NO6Q6%`K.*`>%O3&^"T^K9Q&D1)C3KOKY750.^$PZ +M-!?$R!_Q20ZXJDD1@-EL?DR1`_WSW%*DILZ8`BH[* +MRNY1`G!G($O6'K\>1H5*!1V96&?0%.$="J*YECDE3=+KOD#UZ']\R)QP2O(S +MU%U#(-@\5]%_5!55=XK)[[8;2K#&\8MI+?$NL?AG@<$@K_G4$9,80I3F8K[' +MEDYC#HO]+!)1&7X0Z%I@@7\[JI.69)0*G`.`D)L7WN[$T_\2@KFVB,FOB*/; +M?2:&L_Q:=ZDP6I`Z1*N'<,L66ZFRB`.D.*5KX!(TAJA9BNS/0QMI2]A9$0*FD%Z9*4PRXQ&5>, +MV?IX28^O2NJT[PSPNEU<4TK6?+Z7LH&@XH9\Q+9IP6IY**8:TKB*9U;YV%B3 +ML.JYRM4/13X$&[OY(G6!%=;Z,4RZ;I:#P,JG'FJJ"#P;4P9,]2E2-K/8XG\# +M=/Q-QH7*2S-"$+I3PD?#;\FR^<$'-M_FK';=H[]YK-Y>4.541ZS]YFL+PJ;K +MSD>*)LD7OF1VF.9*<5W-"5\XH-U@)CMA9%7.O7>E0/VQ7P)UX$0``K*!;C6& +M*02W_M698YK8F])S]#.V/UCTVW)6[_=L+:2.K]`NR*`5A6+&(E6WO/7*K!?M,C&B3-[Z9=]\-738!&V8(MKW.P)YDC&UO'3R'"?3HA]Q4 +M`:O)\]174NF:>BCAT.M<@JLI(NW$_$5&0=;^!^SR=3H!CA*X.F36WTOM'"7^BZIIZ)$V+J74EFYCC:'U9T4Q&\MJ']=.&!+4;4.JD#K2D4)O4# +MO1T"3RI[[6.D>0[0Q1[;EKR97YGN$VN3\1V9D?K.`(`[UU#I/EQ`$5KD1$B+ +M^>B2?J!O%@5ZJ#R`/AKR0JG"7X[0*Z08&C';!-W8R:`3"_]X<,+'_CK;">L4 +M-GD6@"7*P+.7@16E`CQ+;G.!W(Y/?:!G1`5M:BNFEV%D=0=W:2N5#O$9UE%Q +M0_@S/;W7)"-#=L97XMVI72O\M>>!ATT!NR6A:=Y_P(KRYU,.GFX&&ZBMMC"R +M0L<&U:D:4^QK97`1$4;3S?6Q@YYWKL#0K1"R>7-9\J5P`BC//>[WT` +MX.QI+&)>D.6%IPXSD$\ST#:#A*<%IKZSK)B^L[QVA<:_V]C7%[CI@E?R)=2` +MEP=+&L]EDE:N4J)R4SQ@I6(TIV23*ZQ/,&4LXFDA#<$V#^A3E)/;NW)N5'\= +MNK3;@VL9+WCQR@Q=0@G9[.F68#3=M.V2I7%<@EWHM%R&;B08/=BC(\-XR:2H +MG@OH6G5?T%AE@Z/$.G&_QH031LZMI"F^!._7]X7X]"/]H/\M&3$>_2N%CX`,DQ:Y9$;FGJ>F"'<*"4[KM5;G';0IZV4CDS!BD5Q#(J6*UB2#_*%-ZI4.@^"`J[V;9L +MGK\U++*_:J:4#4SO9I6E\$;[#4#N`\-"\SJUV[)W'V8'LDU=?VUE +MO;[5NG'=@V``1*""G'&.G^3ZD,O#M,8\P)^0&`M^>HS>3\>=_6E""R--S*Q# +MD;)@3BK8QO$G7+Y@QG:T&N4X(NZ"+Q)@[W&J6X9T(RJ2VU=Q#!=`U8Y%\O8[ +M%>#V)1'_G\SONF#O1"5*F_-J%/ER5FK;9.YI=\(9B1PG5]14TCT`2#X14 +M]S&:S%,$56)G=7(S[[NI,&9;3!T&OG/`.9R'Y&L"'IF;I>"?1]>/H`G7-?7 +MHM#]W/'>TQ5FPO2'\G)X0K&O(P4+U8;*H"P71M"-5^*G]U-]N'\'<(NX$LD# +M]"H85,2?+(5U(JA=$:"G-J?QQV%4_3\F]5BA8_>(&J,/L$"/>.V%LW;-:7F" +M&GS\":?7ASSZPNT0=6Y6RA4*$0)"3>0P/)-AZ),E2E%0=V*+\C,W'"T__BGT +MF?:)^G^25@U>X@I"NH5L2U4$%`>&6KZCG>C% +MO/\&2<(]^*4/MWFU'E^::)*=WU)JW*TW)CZ1-3IAI6Y=\$!$H +M[#'G`@D@!RS&6VYPKP&A6&-29'LBN#NY\`7%/[40&`63G;,`@+,]=KF6=/-4 +MS-L,&6Q.?MB#57W9,*<$PE=OTKLY6;M_VKTYP29%B@)P8N;KF!07W]9UO]LO +M&LHYQABJ"*Q?-EA+O.C)>H^?.*=8Q\AN'JR,+U"C(^WAR+Q%S5R-8BYG/^DM +M]_Q1@SSQP6PDX8(.M]TLBL_KLC3VN1NV-^%E")'%IR2>?9W#5*E,0THQX)GN +M+[#%H)>-H@$I#:YV8...5F?*U'1?-\1*FL]48%F!0:DM&`SV"^WD0& +M$GZ9#J#I"J==$`RU73N8:>W!%5>;_,P&G$#L2V#`FRW>/1+"T:05GH]EIY/O +M"!:6FBEJC9;HR&;O6UG%>9M+.3J)TT=:$`IY`$($K3"2@M'#B*][K0DI<9PB*2%E; +M%O2\?%I.QH8HU8T/[$CMUE:[41Z<$B"S:E1?/RD7!#,/KDR.+@[4*7&`Q@-Q +ME8`49I>]1Z!:@;!4T![VB''$O;R_?-":%WBV/4JYKU*PF'F/UDXK4(4^].Q. +MA'P%U_,^`3Z).9#!&>SO?L?MB0^%]N&M'L8VG738"Y,G\UFEECH4?U!E.Q>%^]VA,R3XIFQ3R[ENQBPC%_ +M#Z^BI*!$<.0*`(8Q#M=(=&>DF1OGBB0;IS6J)S[G+6V_608"9N2SG:TJQ9(9 +MN">"3H1RE/;"P59B)#>7)..6<0.A#*7P$1.ER^B9DE^+U&Z;QQ-(P>U +MD51K8^=O>95BN6)C917X?LL:>"P3=-?@NXB`;T\7O%1\I'7K&X1N6;>5AFEY +M^V\%];=;ZM0[:10R\YU'9Q:*-2AAYHX]12#*@71?]EMKPH5!3I[J47@SIPL5>&_M_W&A +M#&S&P2-Z&:[N%O%ESSW3/0$8B(TX#]OB&C="V&=RA72I<6TD;-.69,7(F*.O23* +M)TC']<[3IUAR&^360Z5O@9].J3V!%6@?&:*=7NV# +MH.C76[S"W>&1@5TP:RF2@GK!;DI2I75,6!D391"I>(GC3.A/W0\C1JB=&F5E +MG\U:&BAL\M=?A[-5=#]_BT8R[[#W#9-=PO/'@)S7T1[[CVB#3=SQ%_Z_C4S07 +M0*$@'J'W7I*LY3G0*DQE:@RZ?M/#7.9G%MPDK;Y:)-R(69BHN3R07+XS(S6'@.)>V5%\^I0HWB[U-!Q>1UDCV +M>,OF(4QJD_^V7)(K*7RBMU`M:)WB^OFWR"9T/T[\4O^P[',KE108I==>*+I#4+#&/?I;F/2''^:!6X'2AAB +M],!0OOI7>ZOX3GS(LC#;*>`@/3@?%OQ8.3RK"MJ8J&,##/"QW/`CKV^,)3B@ +MHS(DX`WL1,^(3.&P+\``\%TXKE$832N1/1QIY^$+2259 +MZLL]++351G2P]"T#]BXGX&7#DEF%9EO%?GRW4?H\#J2:D;/X/T;OA?K#<+N/ +M\?_#3()<]OIU4IWG6]F+0_II6N7V1@!$A9DX'7!"/_X'X5F+!C!F.MKVL2*= +MQJQ])P;];+MIY'82XC,_B_N(,,VL7&?.G1RD9M0AM2M'?WMTBI7/K(`YZ[R*8 +MV5?ZH?*III(ZCX`RZ]L\B#.TY1!1Z:M='([C<;;X6L1/ZVQS`[F+G@5A4H?A +M<+:"$UT7-$*V!'"78OS0SJH9V;WS[?8<%;Z8*`=&ID]`B1!OZLA7BO.=N;G< +M@L#?49G<7[IVATBCOIOO2_].N[U)7QK6N*"`YGV'$O0B=69-6@'#QRK'<'*< +MFX'3'(9Y-;MR1P;(WV*A&.P@/N9Y/!UUN%/N@:[(L?;?,PT&U^QYI(+Q$?^.]'T^7%)J^/FFJ8^_)\]N[B<)U*`._?DN[_-W +M/,*T&;9DX!0X95]$5OH:/9^A^^.`(_1I92!X7Z'(O1Q:KPA5XYUTWEV*A@X9 +M)J.)=N%`60-^#@B-Q37Y5P44;Z,"ACMY-N::[TR:AJ>K_P7.AQ]>+2.F +MT&;):GF2>/'YICV(F:96PFF*T;YV61(4%3I*<.P)ZDX&7B?6"O#:ZPH!"%"G +M<0][F5\+&9F92Z<[[_>A#$JP/D=CP\NPX-@*[IC',M*/#Q92UA<&EM?P%62%"K@:O +MUC.X:4#VM!.=!20OW`R7H-L0`9D$&=&5-'K0;;T7V3F_))<`8@G5A#2WP)X3 +M8E<]5KFTCNO&W?*[[DZS8=#`UZ'T05$?=09`F[EA$&I&[E^KBP.=[PX]Z,3^ +M"^`7855-48NH%X_=RTK_J)EKO<-!J7H7N#AHMDO\W6])PF_$#H/A@HUO."O256 +M>J&\'JX]2SP.P`&SJ^].1S!`6#%$%:;QM9&-5NM.I)RDY=XN@OS4 +M]I7W$=E'ADA2)BH3$#ZUJC=;&?G+?U_1.1M#A:@P+ +M=U4UVTAXU`;1`QP#3=COA\E4*YLC[.X)AQD[4)P[/AXH*2PH+_G[VEPP?_9G +MLU3>QD&A>*HWM&6870;'&@Y?I=I[/"2'>947_&%+IB6.9=[Y.?J!@?-P?+)Z +M(3\,L?TM!?E@X$EL7QN3PWYP)/5#Q:8+(:+W&XE +MKUQ@AUP>R,707Z9'H4W88PLV5AE0?H1QOX$9"MC=#5$SBPG5=5#P5D:TA6S, +M\]QSRA/.(T/F?9=VPZ$8IN\A +MW=]^\Q+9(/^Q5VJDU;&.I90C`[@XBC5@+RN0YFO^6)V#T(O3/?I]6(Z'][9/ +MAZ%#<(=:)-)`=)-U\R"Q[LC1;P)5S4UQTE3/`D@_R.7*[`C"M)'&`=&1W& +M-X,3;6T&^&6#!2)]_\/2P5*(-"6=FM\/N&"G2T"&8(EBJ;I;473TKRCS+B6` +MF29!&4!D9`3<1%2KXZ,B\2G^P[R?"UQDUE,^DCHX*=3=@YHL>P?F][/U16!N28-/+,+>MKJ/[4U1>\ +MY(2,DQDV3/ZA=50S3XZ5[H#X2,N=8V/%^I7O01+O-==.D +MGIXCD^YM&.UPIS-P;OKJ#N!(6)/-`\FT\@!1ODCQYX>QULF?RGG5P^IX\H?- +M:X-RZRC=LBK.]31\WD!?$D=7+C1#)J=EWNJ>'6&A]/W2@\U+2>&I1)KK0T4L +M$RO?-.%DQ%">$J%H()B`(KG"F1`]7BZ2NUSR*KYUZZ>4!]/-@1S,Z)!-U;`N +MWHT:='/_'D!G7UXX;S,=VHHKUH)IZ]]]S"6`[6#D6K2_3@2NBX)U6RN6,)-- +ME:KT>$7]5;7D>K[I]P'3R7+12Q52S@KR`$6OT$@5]OXS.Q-`YPR3&:OIW"Q] +M&TE=XPV5R*JNFJ)\:0UM(^WVI%X@LA0/0P3 +MAX4[AW5<\7ADN&-5A68%M+\H=]P3SH\DIDI@P6R?5M!I7N`6+4SD(W>S]%>8 +M%A9T?U%0`/-;9A.F%QEGF+#@Y;1*P&&I0'/]N>KWLRJGU`2XW?V`RC?7T3974A99T*K7X +M@A\:2XW-2'J3N>&0(R&58$VUHZIS`D;SOTNQG\,R!/;^JS!&B>##=X^-J_M7 +M6(_$4V/4&[$."`,U4::^ISXB5AG"BR+.`K%GDD^"UB"D[12+J&`CPKW0X*H9 +M6'*5'D:;*-F=*#(W9-DY93WA\"F`*:^ +M)2?FW$?F4'!?#IOU_,$';.U\E4<7C*';V)L*&UC?G\S."FDR\FXE)SUN$QV8 +M?&J*L$_-[52\NGL^[J+:RLG=&$_DB27\ZU1E#::C?6-M.3')/?<+31#*77;-N"*051'` +M;^D!BBL53;!DM?[_.'5V^+Y8B>%+:^2/JG@N(GXA[=.*XQ:LR0!/%,S;>?3*_-GEC1%_S479PO8 +M[0H$Z^LW+98/R*_)0?#IGS9CR)V>]V+:C5HW-[N7^#6H-V*6P.;K/NN07"HH +MK)(_9LIEFW3!&\0R*L)2)JR-O'?1H`8;XOHAH?^`C1<608=]Q15?BI5?@D+OP%.:7Y?O +M[WHW/SXJ@3XCHWM5UBM?SS7)M-,=TPW70%+289=A2*.D-JTMOVIZ@^6?9S"^ +M1^C>8HBL$!*TC+@%_[88ZXD5`8@RG5;Y`-S9Y^(E)/SG3>=ZE0Q%Z:O#?SL/ +MOYJN-YG0!GV^WZ4<:'X4JNRLEUTO%YU#BN;>?D-%WI+TX;#1A6G'H:E@+>UB +M;HD^;<\,TIS9*@R6)5$H>8B&@X&ZM#K)$IA+A3P"%S8ZOXHR1MS9L[?TM?QP +MYA*URNH".]U#KLHCY6/W%_Q.1F*WBB.NI67_G+9M`*(UY*%0S)X<7',,I2C4 +M/0H39>)8TA[9L@SNS!&O8/8E&_P`\&GC-%K]19_QLW_4.I4U!)0#9\Y3O]V. +MKD\S>@_^VZ@R$_/?@ZC'/Q\QPW?AP`RW*=1K$^5::_L1':R3TUR1AYOX*H*8 +MTU%A70D08$>E(URTMH>>XC1[Y1,&UQ",UQQ",_Q&?KYAVBBO]5N@4%K[E5K- +M:M"6+07(Z-M1!\L4!.CIGBWT29YT_#H`47C[9F;3+52/0@M1X6&%PI;WO +M'Z*R%&[,8[/>4-[O/[A@'1YY?-HR9GI+3&TMQ+G-<8"_/!VBCQ=K&"LB"8(Y +MIR:LMN/_+GFH),XE987[#PAELYHRZAUCI'QP*`FL3%A+Y.D_]#J_0#$W?2O" +M-,D,T*)E1PHPJ'6L[@J0S!]S$_=:7^/N5C0]-,L7CT%K9ER;\M*7LGM<0>C$ +MYI4-]DZVJ!(\DU@[_8!J#+QXZXX9CYLVS>9_DTPH4+2K\`L +M"G3"F"BIX6_H[O[?"30_#>=A7)>MI78#U(_915Q?M.">P"C@<6!7B)5FH7J3 +MQVK4IMQ/M>C:)X)]>:/B!.`#RAW&%XPH#A%UQ8`HS2EMKR5EFTR\F]6@'1>D +ML%#+5_LDX<\[]\I470(>>BO&*[O>9A,+ID9[R,ZWD6Q\73C='KA"F!B0KN\K +MI`[+2N@B"^))+XQCU.=H=J4/!#M2,BG2\;T%H*QSE5W';VGN2C0*3L)PGF?2 +M=9$#R%ORF:J5R5N""55UKUPW^.W<>Q?0WJ=)!=>&9&P;59.XK%!SB/X96U83H7NW5TUQ^P0\`OXL +M%4(=CLFH0O)+=/.#8RM^&`/`K*K[JV?,O<7,'GON#VHFV>G:=?ZKN&!+V`;. +MCDDX;L34O^HINU803-)H,*$JA1EB5;96&JTNXZET2RC4I'HR%XW(SY;;$'6G +M-YA/K8NLBS`!UX8WDOXU.K+AU4IF#Q]AJI9U;15T9=-]6I14%`*$Y[B'?XND +M(PGUH[2\B[#,(V+?I9AZ([OJ')\%.SF/_=MB;QL::WC3R2BGD9-9V?JHO=R%F+5_N![;C_('!J!X[-F[B/T$3&F +ML0#B+)Z"$'D6!`T`=E\6)2\9V#>3L7=Z'52["_J>WFY[52_=QF;.D0T2A06M +MIL3$/:RGPV5PXB<,]*O9S52)V?);4%0KK=J]`.ZIY8!K[MFQCS6)NG[!F(X\`8I!A!=HS`*>*3#8BBXJ9*,@==;T)-1G=,T!^>^KVQ;W4IQRZK`HS#P3^J?"KQ)A.SH\92 +M&AT5]TH;%6X;U;A/`5IS`9(#WB^X4K26H6V!)P?266:@\X_PU/B:U.<\YH%N;]+4>SHG%+!"2_=5,SE*904%01(:* +M$+DF1/0X--YPF(LX"$/3D1(ZL"%V6S[>,@JIQK!D6B+8>X.HP[2%N[!M0L)\1F("6&7A#AC@([]IP*^JM0O=&21QOX[2PJL' +M>P`B,AGP?"N)NK3D-2S!P=AH/5%E;`DLO-2/_%<>O$ED\VK&BK\&]H\I#=72 +MMBE1ORYH_Z045LQ`J11%SN;Z1W2D)DNWFNY,Y13HAS@+;0.APLHF[&V[#K,$3C*"(/_)N +M)Y)OLMGP-^AUH+S;@L[``KYJ9O+T%@[^E*H9FW9C#A9GK(.O#SFJ(P%K;,O,-)&_>>G>]R$!"R8CD+ +MU(,P2O#8==$8\EMW4"8_I`XKIEL=>7CQ9\R1,6S]X/9X*(NCC/D1)>Q82&]O +M7`5(H_,8YO[L;!`>=M?;^:LFW6Q1+O?VI<-TTS1WH#\YRT^8;7^RT[+]+@I] +M4BBXT7M/;6L@^9U(?Q629\1EU?=D7]?;PGRV:`/5`45&A\@*>4``X7INY%/* +MZL0]4&?(6;33^W:H>D<9WSRA7?;YE6I6HLV'4+7,T+Y$>7`3XI*(;=,<;PS^ +MT5DM@HH;#)F,_(F9^87]_G@P%G8.;![OH*+9?>A#Z<49OB,1&;E@2]+$7.6S +M6<8?OAIULC,'NA/;K;MZ@>J(P6[IF6Q]2FFNT!(9@`PPI#+?RR-:XC249UF"V%-/"*CHD\K1 +MV+8\6NU6Z5-J]>5R45I57^Q3\1SB%6T<1XR%#'R#5I>?:8QL9;.5BH&Z*LZS +M;JAMM!`K\L:VIB:,_N9/T':@,5.*WX&FHHU1VY(=T%$)&'>V_,[>10K6<3]Z +MBT'PAL/LR\?A.33(75^CG(I_O7VW!EDOD!8H]0MX[5DS`GXC^UI25:N]G/P7 +MSQ)"1D3:3>C"8-\RQ)4OPE>8\P]-S/7[7RKS?:81(W&A4>^:89H`8!]297!4 +M+?U0<37-5ORSWLQ^I3CC[.U@T2H/]]GZ\AA.EIJ7L,$!0+>YWK,-7[VE^ +MT92ZD2'%;VS^SO=\WO?%LBB)4!:-JP*B"&W]TM[1, +M?[+C"W3VL*CJ++]JCKK]F`%S3C9;`M8&V,>!#OB`11])@J/1^_'RA#;0/9)( +ME#IO71OX,S*3/0NK9I^PR14')IBM)QQ<=Q)6+B%.$2KF[HW6?'1-WTN,5%E9 +MFJNVOT95T1!7<+=K'UJUQJ00;G%D5&^2\`:-0#4HMD4A0WU!&1VDD8,$:S$B7Y4H'J,"SX5?MS_5U>DL0;)8&UI.#\\FJ]+ +M(BR*KIL8?[#N']RZ+2A&1:Z8@CN`M3_2WG(VVH.)9I/4!&,@%]O;GMR)6_\[ +MK8H]IUW]X#J'=-&VL$-D0F0REFIOW''9]E-B@>RKREU!O^<.Y:MG_+D)P!]-;P=FHD5K]W*-%R +M5?;"6\*BQ"M+K3`B%DV+RRNCWR\=IXL=X54*X1!9H`X)7`;_Z,@.F(+$>N@U,V2IL?]Y9^,&5P^Z5/BEMW$(6T.("_^$?^C@_X_H,1%5X4F*@9OIEZWUP`-G7)08Z++3!W33O%:%0?!6TX8MS= +MC-9#S$VS>$K%`OTTX^2SL]CV_"&IF/=*B+6?Y$\E3A(.-,_Y=RD$C`0.HP&= +MLBJV"\IYB+1>=&]O6"#3>/+T:?Q9:0X7V'#U891UPK?OW5$9C5CV+='0GV<[ +MXEZ6)Q1O]T2F]\*DARKE9W1]4+Y28/[M9*FI]%E<*)793'_X*J0+=#"^Z`.' +M''HT;(L6VPR',DPK/_?EJQZ)CF0FYX6\G2J +M,`@P4:&E-V[:QD=/)A"J;,3'CW%@C=_=<#_LSL-#+I?5FC#\;OZF]8,U6`U` +MVHG81Z>3%*9-],@5RL_WGH?P[;F!RP]C380XW$N#(_ZNDQ$4,%_YFM>XO.@KNG&+IQ`"<.5'&?;^"QT)!*0-+( +M0V2@7\E3@&#[P0Y/N3NB#"I_&6P`[)I>_;_$S:R``NKT`A'?_BC](B='C@0)QTY?UEJ1C.;?^=;T]51M6+Y_2* +MJG/X\F3/W#W=%-86B2';*VMS#^*R@L2:&954V[6RSDX!Y0::12K>8CCK6,^" +M)I[F`)J2^VWH8T76?-TU[U\S*LB:F7\*$`]LV>MC=L>%_C54M$9PV-V3-AT/ +M4NS]F/M?>+:-T>+/-IYO2"Z(-;(+ST9B/=Z'M_V^X,V2-;Q01'H54R,*2-?Z +MZ#MC1`O]_=O$1S9YFP(6O8FXL8--)%:43EY.*1,#M_8.'(WB!;V[%;ADY/'1 +MS+Y$\KX$6DF[:9UO5=R=KGBA;1T(@Q`MVU'>6.\%5A+Q*3A+B3A7_.\1U_A/ +M3*T/*6:8V2W^)CZ9J"7DD?85!8+Y6'2RG^3TZBHC'+Q4ZRUZR.U(>V$R?BZ_ +M'OQ)QW0X+283$?"P;9W"\E)19DO9Y@U/X0+X`PKM[ +MMRE>.Y/N"(LW6J>3EN-H<"ANS,TPPXR5:?CYQ-5889AN8I5@/+IEOM\O)WJ6 +MG*=K\69DM3^<,B.%"^9\X`\!Q&UM>MU!X`3DIDLM'==W',*J_N0N#<8T^&40 +M#A[>-0V\CH<9MZZT;47:MOS+1NV)/QP9.UOW^9XE.`V>NE\ZN^OA!-DW!B<< +M6@.RY*&D-4)AC/Q8C#G(!QRQ$9>!XDSYEP$%2EB+5(*@&.W6/Z"HR`F$F'0^ +M7YH2"ZJTYX8X?8_D#(5EI`D[G9S2YP+$IMVU/SO4^C9]-JC`/,V?X>%90^#+ +MQF_S\'LY@YF)A[%:4^J\50.Y1*]'1C6)*^030"$@0^J/:'PO18Y*#=XR#:Y"YO;?8A#\V[U'WPM +M:QEX4(G;@3;#F%=C::/BY?@S+NVKAH+ZN5!Q@H5+MJ6:(,RIP&VN$_HM_"DM +MRU'ZOT)04I^Q),E+&O-*S)17A@S2LRLR$7\D4;++:[Q,9X!A,O*C5ZB(.!Z@ +MM9>TG`A3>$%WJG#-7O;4QK&7:B4(IZ82`3M\$B2Y/!_N0)G))VL:V'9 +M&YC%+P5!<\1(H8[>34*50"I56U&FE.%C(5$+5E8?=;LM\!2L-?;VV.BI +MQ)5=/2O`MGPW-V8&J_ID;9I+#601.YYQ^9XI +M("`5>(R%^+RW]I`2[S<41-1*0[E(G+>EB4J],?6"ERF<*7NT1B?4:YESNM&5 +M=X_@!^QN0!!$&J49BY3?SD/,K?@6FA0"+@1$#QM-GTK1/2CJ(0&F=J`GJGOZ +M>>ODW>3G!JOFA8%03[I:EZEF@RSD:%<$@9,_HJ?V#+\R%U[Q_= +MO>8]).LRRQS0="I@E]X\''E(PL)WSM;CRBU&K`;L\<)M5G;9"G\,8I> +M$CJ@)/5[0VZU;">)I88)M32E5PSFZ0<'E9BJNQO`^%XH6F6TL6^JW]M>CK^J +MDHZ^2A@I`];)/*'95($VK[,0/1@GK0\K6Q=M]5<^,LNLY\*#\D!Q,2*$\HI! +M9:A"Z`B_;,K.9V')H@Y"PT!8F,B4?\Q!]]NM=7V/N<.;7'!+UD1_`1TO-._! +M\22/F#N2AE`N$>H/$_2P=W!-_Q1//=GN(XF3'@"2,%Q&1C!5#2OD+'(QX'<& +M;SH.%N@BAM4Y[@0N=Q +M\ZJ!NL/"Z+P:.$OYK+:1GO3%XZ4/>P:A"<6=@5@N9DG_#<:P=\,*G.P@'7?" +M;UXJ)X.ZT?3>G@>I8Z$WIJ2PX'0IN0^>JVY4FP&?)YSGYG?3NRZ8[[TMMEU_$AK:".-F$SY*IOC1#?Z48"7V5HO9;@"(<((TNP&RD5U]'=FLE4FH0;O[CN\$3/05+ +M'!Q(6K!CWN*?<1%Y4_U^`;%*BJ,I/YLD^W3&+AL)W>@U=J5\%&=`/5J8(%%W +M2UZLG#Z/L\0LY>Y;WZ?0J>$/7*!M&J +M/\[)O*!F'\6I#2CCQS8XZG3&.?+((+5-3W7`ESEX69F$(VK)_:U-[O2`)RR/ +MK]W:SN3\E1?WU-B]^H2N%X''F7IH)RA;JV]LK;Q^4RO-'8J'_\_8>XI]7#31 +M]B7\>$$N"9U:]R$)_R&`N$(N66'V/CT?E3D)X\;QDA7-[)>K`>6U=2AU'#?I +MP^QC6DT$`*R%NOPD76,M:&/S%XN:9"2;^*U*J'+L(D_R/6IDF]%-(2N]K#$3 +M=?L=B$AS.S9F7(!@[@X7)&XXHDA1FMC*P2'+0RT1+]$M"B\9:00YLFHA&SY" +MSCX\4>VHOE!;@6DV'='+105`_\`U\$^5;#NH5-\.XXK.0@=Y"IN%Q +M0$Q(WL6;'>9E`UMN^7LVV&I'16TAW9R,&"C+0XGU>Y10&9%-\`SL=^IJ%`=NV=`\ZMDS%P$%*22V@5]$%NUJS[7JHY-H^%[ +MP%5B_NR7RL'PW*4NQU#+76B5+9ZB:1N+!(_5\>8L611/D8>+'757^+3!$."X +MD&O3^X<!!Z9Y#,DHO?RS=CT)M_EQVYUTB40)4GTLT,] +MU1S%88W%7*B^&1*(UKC7T_R-E"-YL9GON8)XV*_J8T3PSF*:U$J5&?`N.O59L+WDYR:1H`H=;W!$F[ +M\A`_RYK$PB_\;7-OE-=>H;=E9]__-*O;3G9"DBSU\D^T?E-)/@Y?#'FCB/FY +MZ'XR$!DM7G$ +M_EXZG#-I80"JN%C62SP=[H!8,.BO`\\'`42/J*XS(=ZRIYU55THO"1S4;9J# +M/3A2O)?0&8?<-_:#H(V98>9G`BH]2]]W^.;0*V_/I;GCF#2WQX8.>[S1^5%. +M$KDA"$'!V;]<0>9=AG03JD,JI-E-@"BU=*00;JT"5IX'O".^+;T:J\Y!"2\&OF2,2*M?GI:OQP^QZ8M'C@5+I`^`$,TYU-QN<&5ED;=X_68IP+7F +MAFX\+8N^H(F4E2_T#!%E+ETZV7U?M,O9)\G>9SN;A7C"W)7QMED3EB4?"3/>@?)]%#0)7899E'.#;4D#9& +MEL"7Y=6D/?GI<5.`*47Z$)+-I]-@UWZT3_9+5#NZW'9+$%[LF[)WA#]B4"KT +MZFZ3!6:C0C78O1Q<,8K[2/B];A5NEP]<#8?"@&,HNT3@+[L3GR!;@`Y>2A67 +MP*QER4/]JCA=!>X][-I$W$B*35:$<_1_9V%0@X18Y&6=<:_=:C,6X*YYM!V[ +M^A6=!=)>(9RU;*ZN5&@$H<-?J(:YDE*J%6U*__L#B#V[_*1R-R83L8((XC:B +MK=_J:[X-OD0]2A"OS.EP:S4]E^W!'?[R_<%`5-;V!CH2(06 +MWPF-U($<.?+9V[EZIV)J4L_TAW+3@UY8H`0+6R_[?2%D;!4"E/6A![@(7BSY +M/1\:,1XV3!)0$4R#CWP_I(POA@U3`$>XLBATMBRD835$OSB<&R&\OI]3EX=;J=$.% +M>]!:KC:PO*8&.4XD_U4!:T2(X$5U>I`AU(0.\F+MA:KTG+DJ'*U7\T_@)44M +MV"5K=FUW%3T+<4DXO)N`&/3^/=@6B2N6WE3OTX^ABC`7".J[Y@L60+<*&>)9 +M2O:Q@MZXU,D$U\4\AR@8&N`=WLDMM70D@EODNPXXXI+.8=>=3WGETN5[5\B6 +M9R3W7V5;#C/RG:9KTZWE#03?%_*GN-=DLTH><`EBP)07A1(9X0_PBZY%?YM& +M_S6Z;=Q5R!]N_3I>\7X^`ZP^74?G"U8[I:Y^DZ'[D_P1DD8`"CVA-R>:+'WS +M[O6*)OM1L=G;>N7$6&1?8>@;<7-J>:2K2YT!22L@AB@ZF<-?WTV.)SB7YOJ> +ME;4$`3C)GGCU-@H#,'!Q^B6@X,3X0-FTF,]Y4ME76!I"Y>N,L/`IF*W2O>.4 +M@5TFHWE\I^,?@:MH.@(F_HNE*X#1/@=M7CUU=KN0$M>TI?7>63DD5>Y/3<'O/2PP1B@^5#F +MJ?'M9.+&ZZ#Q[R+3CWEC2>:;_M^X3<'_D*I?"!3;K:<%Q*2`'8/X2$!^[08' +M)_,#[1!'>O_5+=*W/7:1']X/:Q_UU8PPRL;N&#-F==$9@'<4(`J"=?-8E^^Y +M!*#"F6Y!\D8MW=Y?N,2LFN&4GJW?R``&`,W,%C@(DDB*Q/`^$/0GFJ%5#D$0 +MGBNA;5;8>FV!^3FIOSC8UY\[TS;NK"9YG;###)06JS."\G]J]TFXK7*T\Q%& +M1&,DWFEN%94]Q6_7VUUK%.B+XR.LGWOT<]`U16(]?7*FF7$/@*DP`R^GDT"& +M(65%UH8>]XB6(K^AM'XUEX,;EL;)&R,?N9>;C_+]?D\]QJA,.HLJ9-,'J0@0 +MM2-H0(8"14\']<">"_I^_GJ*J67&X"'A1_=3O3MQD/<2*'=$5ZC%+U_B('%= +M6J4'*T75U67-I\U=E-6X^?6WLU/KI2JCY610&#&@BX(1#*J3`,V/02.'M0S' +MM<^._9^RG)1A,3XJ^"M<91P&'81GLSNSESJNV'@'RE%0UFC)O#"6H@"#^R%P +M&AQ/L9[,*6U`6]P>BQ^<$"VS58+U"]+O?;FZAUR!H<_5:9T31^I3Z36JZEDJ +M8V4N-+9+0:-,$LE=8WD\W2F4Z9?PRP[JB6GG14+P]DD^K;1R%#7E=>=9LT_TM7[,0MRFCRAL4@;.3F +M5D!8\`#D*.)M2O9KXX(^ZM'M^BX+$N"+1A0".=ZLPE^01?S<;7C:T'%W3MF4 +M?W4)&PJ@\Y\O*9#.LNUF(V>VK?R$=MMCEXQ +M!J(9EMV#I[9&\^?_'X^B_XMP!OI@VB*R8SS>F8>"LP:YPA\XMH1E^`6D@3_, +M8.,3HWLT@$+T(H:QD&__A\Q#*:MGLQ'==+NR`)MH]`61YN%Q_+/X^YSIZ?=N +M523ZB"5O96N$-R]"^G\8`ZBQ[XK0[+9A]%F0K#BA*#9K&RFWP>[V!^J3!S#D +M`CN1+/748:&H2@2%0/]*JJ](3F\)S@_:I&R+8U:US9D_^<_`C4DAK +M7J>=-FY(S_MS&T*`"_3*/$#C;O+K_/3-E]E?#A%!Z)""*<)9&P?4:W#9%LJ3 +M_:=3#5@JL`JL^].=7B4W2KJO*$:N99#CN1>65G"X!1:RZ9J2TC7750ADAW:\4"575].9^P3&%4\ER*PR-2= +M/T6NP!5)$`1FO6(Z`2&_X=_02OBBR'R[0*HY7,WA+WPPQNNP9Z?=Z_--0(&K +M86-\_$'E$E,R#9])`6Y\8-155OL-N%)-[$\@%KR&[)(>>X7Q%C=1PK,Z/]>H +M8*G.Q^OSA@NPTST,Z#.#ME="J;(@U,;K(:#62A[`!^(T--JY_EOYYL67Q(G9 +MR875B*:(\00>K(=L]8.F`7GE:3?>@L^2*M8MT$<[672B_EKW:0;A!^L&^Z-A +MBI;)NG33C=EP),Q.7@>+@O1XCM,(CR*5>2(H;$)X4"TFC#1Y-4 +MQO5\7[2+..$2:(@!/ES7LO,C*F>6$4`+7@10BY%ILXTEU0XY:!.I)[#=K^+C +M#"-]N-Z"PKBOA:QVY1P^RATM^4D_;7/]*K$B&TZ0#+[;'8:&<.CX8[$]*%$/ +MJ23-;B2`%C84)\?<0_;WY1X8/)KF$^0$50E).,NXZP,X\]]<_)>#US'`"ZUP +MCALXB\C#3B\Q;<6V66",RT#3&].N.>97D62NNJL>+]S()>QT@DJV8IA!_8-J +M7+E?I\\!^%)*"W7#\*@HU',]$#\A`:D@KJWRFYN;0H]."E&=:[0SUS7!M9M4 +M$_5*`^6M99-=MB58V4^C0F&^L1L,V]5R'^BGHV,.?+]/.M5Y4UEB*FJB':!H +MRJ33;Q^EJ?QZ8]=O/J/W`=&+Z4CJ`]9SA>IVRRM@O:9`G8W;I,4T:B4J>.'P +M#^_2S#B%5G6!%9+KVV]^'U9"?T"M(?P;Z^!&+]$B.*(/E,TKEA[ +M(!Z1MX][PDK6))5^S>L_=![D5N"M#P$J6BN]OHX!/H>@3WX)KJ5?.^HU'4D; +MJ#NJ];ML@'S4Z,HZ1=T!Q_J\'5C6\4,G$70JWW4SYI;_/WM>_CJZ3+>Z(;"+I!2OP +M/>A!5W]^OX?8)XEB2I0\MV+%?<97:;VMFA"&7M>GD+KA-)4HK/(?+KK*2`=QY:HPO6PQ5,/P'JR,[V,4UWQ65RL`-R7$ +M>D^.G\N'ZJ7FC6Q>K<48EO)_O`DIG5T5H3$R_3AMMGT-.-@)I4@6E84N2N&J +M/!!-G12\G9^4][6J3SE!R-X9M99>UG +MK$H/W>;1[\:T<],UAKA$6O:R]%D9$-V:@A3H8)N["X]BF6"I*[X8,22\HC(I +MS7LT_;',`D9TIZ&=S(X_@9!'.HB803U/$H3CGQ-,^FGCU\*E9\3Q&B@Q5OJL +M'H`W"6R6+^$_;?D(7C.Z]6<&0+'/X"!`EW8Z$_PC[#-:IP"['J#1KZ=SC0\-@R< +MQ\N!^M4HTCL8QWG0P@@"Y55V5V*&8HQGBS5EV4!GE*"ANB&K&O7&3B+VU:-) +M`W1,7DVO@%#9>UIQ\]CXK2'HEX3V``;"3D=Y3'O@/9`%?!94ERX5+[V,'F\#;Y&1GCTNF^3> +MCID3P?,?MS^F@+!SG">_!(KR;#A,2ZY,R8O47HGF#M_.".3`R\F0T:>48)S7KR4M'L!"E>*,07S!=I +ME.#Y*5W5KZ_U48#!L)#2]HE?2#BP.O+@Q[R%*P]I<&WC![9!;LM3>)Q^=X\J +MX*WXVV44AQC4C[*29\QEA$&<7C1+D%?FPXH$7KR2J4I,\AUG]74*2+4%^R?Q +M0B3XWAT<2FWY!;N,/4>RK(%7I8EO[@:K,[^W>4I=K'#ET<%L6KBW@9F/WK<8 +M:LO9**C^:)TC77"47.4\)!:*^/V0F#F\<-Z05<1JJZQ9YZAAAD[`!QN2^'0[ +MZ&X+^D'6%G#Q]W704R4!+FT2212DAG2MESI]/WZC5HYTS43UYY?VV1])B"^F +MX"1C^J;?MO<'S:*TL&!C)MAL1R^HED$])7.4*,3:MHIUK\"=G9K961\ +M1$`$5;V+:@:FG!_`I&1.%*FOIWNK,PP"AR,_5A^%M`_]5;\=8Z>K?`;>+LNS +M*U]@_$5"UE?!.HS(O6R74W?YAO?OWJ:7V]^)+SUGWQ<9=7R^+9'<%G'MJF!"1#/:LVA(T/?%F[;#VI$W%'Y)1@X. +M#N`>,H+_N4C,V@FXN\1NY&7L/ZH$1*1=#VC%LN*?SE_2F1+I2.!+K3D..P8- +M)Q"#?DTX.+[$8E#>V^E#V_[`!YAY+G%P(C>OHYKM+88.[I5#>BHXGNI$I?R# +M/]R,/[2^E5\,.@^6!''AMP#;/$BQ*@6XR.)K +MCE]^*#_\Z7CWG<,I'X21['[SX6J/ +M^S"ZO>,P:8.BN5[*)"W63O)'>4'KNKYC*1"HA&*QIJLK4Z9',!G56V6_$T/U +M;SD2_M=W!01&1.80Q7C]/^M:1$U1[ZE> +M-9R5_Q06;KK+,^:0GY0_+@<\J.8 +M[BMND!#V0C62/12#$5D5@+*^@@CL.%%UQ +M2!2Z[R,_A:27AY)P!%JB?4[,E1UHFD?TP\=S@%?[4&[L".E[+E<^K#<7&/`1 +M('Z]7B]M[W;+P3;UB#S2I&IFRB>=&LS9\2F$I@MPEK5^GY':!47OI]7/"D&L +M_(H,=8B"Q$O6!$/%K8QM\:RF86,`7RXP!3]'9&9*Q:_:Z54A"UB\S6(X&Q-V +M)JNAL678TB-[:Q0(A#T0H@=(%]3$5[&Z!=]D'A7G07%FQ""-6[T@Y"E\'EEB +MTE5B.EIISB2*3\:X'-A<0,E4-95TI+N:^Q_R6O%*+.$=:*"ID1(KP8RNIA&U +MINRA80TO`.5C!]R%X[%^W#H0$K_1SFD'Y'YEB;-ZJ%VF\7B14+-"3,",@?:3!Y,AX@` +M.;?Z`DXI0QM:$4$&F_%CL6N&QNT/EHL'1O<$QEW4&JB +M-E>/;5#HM$=:(06VC;XG@[S6G[Z2>4=@$I^F^9,VO[H!BTY<,M(H@H.YAK+- +MB58*B$=SUHKX8RYQ#44%A&TE,9$"799ID4?.*%D("?PN_^`E)2JE5,^R)_2? +MSG$-,=C3H(FF?TEG9+$[@.>!$>1O&Q*AB?)0 +M?GSU9DK8CCJ^]J5S0#4=CN2R9R)\C^0D%5X#6T:J'FMY"FX,OW%U#N2\J9MA +M)!..1$DG32(CA32G+/LH\]-Z8,/2P8"6F[.RD$Q7W7[@L7"1[_DI2A*L1V4& +MD:;$R19M`NEF8L=QT"`INQ(M>0F/[K5J\@,:]C-5TE(V7EMLTIU5S4*2A$/3 +M+*PHA&7K*!UV[(_`$>ZTM(U^FD!M'K>G-<@&]PLU**G.LL1#!W9]-'S[5TG? +M*RUS^WN2:QA+^;JB+2>6W9RLOB&D;O%-UR+E<[Y6E%1@=9 +M$TI8RG`.BT")CQWYN2G7B=,"BJHV6E;?55U)I>S,#!M>[YLL13]*9ETXY+DK +MQBU9?,8T+\28L+$UH6:B/E +M68I=L]-GQL7I"SS]?-(1:-&.`#OW57V^0.-?=/U3Q[&Q-#.N[*&C>V/H:!>& +M2XBE2=.Y]!V!1#&)5JIK2TU6Y5V_0"3MQ,)3HE\]OHR@$VFI_%P2U9W_2E=M +MSS"QQ4V:/A'S%'NOG;:B0'=A:QT;3GP0C_#G`YYR_U.]<**%J/!1-734/W6) +M$E;P/MB6Y$VL>(VUY24WAWR>6$MM\1&%$Z2#Y8MWF1))=_0?`3(Y\P'N,EFB +MTH^/?(*:+7X'(W:2UUE#BS%_FJW0GL#?[YIK;^-3UUWF+F#\,NUPE3J^H>5>(1U`2/;?-FI4 +M"?4DJQ=U9<^G%*,HZK#<@<2@EVK8N>^+2ZL!G&@IC?QSR=B*_5>/VVY\SKU& +M>H_-<3?/=*+DY"F#34BKS?[)[G7SAF=3Q&&$:A35S\9EI<7R!K6..5,E\+.W/K1IO38$5RD' +M4,:!;[GO?8.>K']"TL'5W^J\K?4`*"HV^G&5?7:,H.PJ+MV?["#_GC4KW<6U +M7,A1F\,%Y!"6(1FB*=ZZRF' +MQ[%%JSX45CI>Y!,K.U;7GSAL-]Z8F>#5P/IF_\FO,'*4"_XT"`:Z1A$!9)W" +MY:;0"IA$D%VBPR468')7T5V5G:YFQ-5OY,:@!B,`.`YXGG.*+Z[YP))Z`4N) +M@PJ!DC'KM!A2D42,'3Q*F4,;9)XVF!IC,)^>W;(H7\F\QG"7G7V6UIUS&%EZ +M"/=0UHE.&$AE!S,01FY33:RFQXQH8/\B5D^',OLKZYDAUB-5BYY@;`:>EQ!$ +MG<4QN+"C!(S4T7S("FTQ&U6;_>V4HDVY7&.$PZ%ZQ"O7.-TJ5*>%R_&4F;B* +MB5\TDXO0F\ET?^PW-_1ZBY5"X+6."$Y(9?F!=I.;P&T#G6M(F +M;OA1%OODQU?C`AK3^IXECL)_J7Z;H4B%,)O4\_C3_WF\=R8$N`_+*8SZZ;=J +M@3DU>'$9O?TD7C;X%27T5MYPI$8KO0T[.!(OBJ81`',\($^HQE^I`%866$U4O3OHC7(BOH$<$6E%IM=S;4=[SZ&R64;RUSF-2R7$'Y& +MNS>3N#`OL)R%+X?W0WG:,U4UKC6'XH3?0"]9F)SD8-I"6O73W;,/>;YQ+[K@ +M1FWA5=WF2F?L><@A>^.2?/$A4%9O`]RM8-1QCL< +M-U:Y?4Y&2UYIS_&HX!J&WGG6B+G(0B_S+!XA?4,M!5D0^`!2ZT.;!$+8](]VV".[5CS'F7!!!17H?MIT$;A#^V_U"8JE*P^K +MT*-5)'!'C`Z'$A;.D8EUG`QA;E1UC3Z+R)\1HKJ`[0?F_$H3-1"PJHL`D[IM +M]WW$??6T,NUJ/E3ZB*Z>MUKZT9S;QUF_(VH:6M1Q8CPL.K5FB>/%G%L"MHOK +M/>SD2R7A9L[:@U7M<6U/L1U5=U$^E;M+ +ML+X&7`S03W0B2'6.2R*379Z8IPPG+IX8)#[3M\TANE%JAZUG*1+5I2?I#1M+ +MQQ<3B]4_#YYS5;_UCY=?>,,ZW>B]]]U16G32?1$3X(KU.]LJG`=T/\T-A.Y''O%M+P\9F63Q\D2 +M63#;&8H[P%LE%#HB5A92%VD1L6:&T-!9'GTKOHCG-3E]<(5L8@RZ@7Y>#-0A +MIL-^.(]-:UD<58K2:DBL>EG8EA;C)K2(`RZ0H_HA/Y8*``>;0'RLZJ3L!I$" +M4,7H&R'D18*88+?^4X8.UD!/PLCAG!>ZPJF!3=)[T$\)DVEIP(#0Y6UEDY2N +MY+F5[_H*R=O>A!E*\-KI&B"Z@D3RO8?&'.3ZKQL?0&.3&BP)Q23]-*KA(AF# +MV^ONU:DYFC-.L^SU?'HG=>%+VM?$B0RS@9>I3F'/E&H+,VV@]^N&C^%@-JV8Y4 +MTBM:/9-?7HJUC5Y)A(RVIVZJ`5;]=)HQ`N#F!_L]")1AY?[*7."@G'Y(PH_. +MX:RB!@/EV0X2+"`1#F]9>[%R6X^D[*J_^&WHAFO*.^Z7B\@PSD-GM(2R_/..=NZE.S7O6EU\+WGYSIE +M/>22_PN@3!][;2 +M,7FHH^%J86#4YM6C;M[T/%#\>X:.R#5+0KAQ;"_D[`@YDZ"?IAC5F_R-E9(; +MXOX$^^LV_JD]R]+/SEO-L^K2-*S=HF!L+T)\U^"= +M:KP@8.&8L[N[TGO!]J$<'#.\/"[_9Q+=7TJ.<,__]MD?-$8*JO'^Z2^]O@84 +M;N.^L-[=9$5SC[G+=V>N'L9%X`P_)G".7[KZ2,9]+U_5 +M,J6>@%WOID4/!95>0$W;>M<HYF[ +M8'+H"9@64'H;O3Q?M6;0L*K9;;HZ(OXE7YA["9 +M^BWV/-CK\/#WR&G)6][P5:,;FP8HO5;I:)P50V)!"%WD1=J6?T8(3CI5`+D` +M1B>%AZ88_[/NORX2C#@QA9'71G'>5\/R@*#B/S2G4\^";E:S/XA%N,78VG!`P#%`PWO1.Z7KMGQ98C"KE#%G?*T.O%5:F\O +MY\H(TRY12BR#[ZG8/A+@K&>%IGFS&2((*9NW2Z5\0QQ[Q17'+TNUQFD9O.WN +M"\3V5-ZRQ=9$.D]/Q:WDROGJU=3&/D2/E6+].9%*OUV>/418RF_+-^`J__*: +M$("CV'C8W3) +M.B-JG#^SP>ZETD\E"&=2TJS/]HWG8%WRT;3?;DV%$A0^;O@GPD.%FIO5S2]F +M\=5;R59*_9=G+X)A4D!DP5!;CL:=F8!]4\DU>/6ZX3IGH-0=U#L!W%BRW`T +MM6.[D:72;DI??VF@5WKV[-T;N%GY)^$AD6C5(J'8'N +M@OMWG;YX`6^*HFP6.DF%[7>M/`#6[.KVTA5K02K3CMG=#&U#I\/RLLCSS=PRZNTJT(W$7H8OQRNB*#O= +M*BP!BYMQ+%'.-V*KM"W3\*JX0!!@A[W^M/<46.UU]A7%/I(LPU2P2`8>,C#8 +M'X-+E(@?YA(%TQEORW#6)Y+@VZ:ZE4/UT0)4R>OH>HS#][OE?.\*>18/@`_&6IR&0= +M&2E`M5(M,[GPJ,NXBN.;%#;?1L!$%29NE4?^F9#I?2)7.U1SY8:!C,,E*K?] +MQO=JVK+)KL9C>'HCBD"G +M9VRH5I,XCWRU`9N^][SMV+\?E( +M`CEA1#W,/#F2+9?"STNIJ+?<92#C\-"264'C%F[B9=C;8M6:^633V9?>E3(] +M*3\FI[:8R4KN#("OX,".U:8X#?G^%"M$7K8E[M*N'!CYD".2^=M7YCN2+3X% +MK8/RP"T7'9P>G&->]+_X69Q;*!F)S40.H?>!IZI7VU +MN6B=4.N[Z_X.`)X+P$MRJ8I,OHMAPG]V:F;O(NV*WQ3O)?H]9\,7D2OUB$*, +M-)R?4G2>2NLTXL[SU<4\"?%=0=@)#4D1M>H*$7>IB@&TW>Y_!?=Y6&ENNG1( +M)#7EJ,GF;=FHX^LU475!U\N80-DU%04/-P`5W9$_:>_EZ.=NP=[:*7`MY:%U +M>0&;G21S3AK,`[/[0R9M+'D`OYM9XVB!YCL@PB$32Z+`IO08,RH+J6-=&8`6 +MTZ9&`/_$3UCZ\%XZ^S1`K.?],S7,2@Y8[\2^;KH5P[X6A\>+-0"BA.C9 +MKZQW&0I`Z[6;]T9J587T-'\>UO`W14<5P=JX(2TU8FBF^"),J[!G"!0]I>@CR=G].ZEP)W:(B3:-5 +M2%-@AMZT`]7O#^\QMER8(+;V$'&E3$IAYTLSY]S;&7OJVX]5D@VI]16)3@_@P("F@!; +M/26UF_SW\6@#-'_C!C0:Y2LH]>^@.\7?X\K\N%X)V+3PM]#Y?SPJPJ@FH40J +M`[E&$2RMY!-G7RK\+&5`R*\F0RYE:O^R8SA;NCRITUG""OC*3-W?\7&4E!6YX$-3;^SOGO6"H2;&JV3') +M2]+4H!?`&J"/,!Q!J/1LG2\2%RMNU$:5[#GH0:VG)G'Y.1B9`([\3'G^`% +M)O8,(<#OQP9TI'M*W77@U0(PB<>^:((DBC.>>$XD+28:Z8R<;PE@3>:[9W7I +M/O-?7&PSKA>9Q5(#DB:%YVK`.[<'9JG5GM2&R->#,3;+CZC +MD$SDEKHOOFY$C(]-,OPLM5#GUF62S20@)DL1<1S'IN2)T9&R7&\_4,H4``*, +M2S/X@0%:"!6QNDB8>V9NHZKJVNCGY^6Q5+\R-"$Z-SK8$M$X?$?!AF_#,2[* +M43UX=2YP:@_>0!X^0`:=8I6,`0<<8BO<#W%W8K4!6C^H2OVP9EQ10WU$P3_Z +M&T)J[)_58'XYN+5#=EBD]S48M0Z+4!*S?K6'5V8BX?:X`%;-Z.C=R]#!W5HV +MK#Y9[>%@2=>K%TPTP-?/*CH"23'7*)7&?.J8U.;^-KKS+_CW5=)MYWR5R*,V +M7;FN__-00'P(5G)UN\G_@`*3<6%MTAU*AE0>&+W#3[9V\[5\4LU@*DK=&=<` +MOS`L]>&:I]$`@7YI02I_-OAK`IV>6](F1D5/`4S< +M6H;+?$,'&B-#DXIP?'=`M7[()[IZ4:?_S\-'OH^9/3;@^X;LD&OJ;1`/>(J) +M#L)*YX#3)-J&12$V.&.W+/`5;_%HZ"(_A]=L_NLMJ\1;80H8<-$.[$H[4P70 +MSRDM!"[RA?R*X-55!$IF*+"@PIG&MR/,AZ9:O?T_LA^J>T"18*=:3[I%T2=2 +M.KI!XVK)N7S4^1LHG']E2UNWA0_Z\;B8,U0AQ2,W>F8%PP"B>P,KK<>@>=B+ +M61N8O=1L.2I,57QD6TP:^@%PIAAK.@"N8DAH>05$R:KHXT;XE^6OF,TD0*9F +M_]K_I9F\[E.?'?U8!)FXO/\O:(#*,??\>T;I.*#_@)UB8S$6;MQPQ`J +M")$7Z-"DKDLQ2A:,-1/J_*?.3:2]P*#K!*(P[F`[2VRA_3QCRXT71-J>N@G\ +MBRN;EUWIGPY>X+%&\(NK==Y$`$P0C=`$ +M`BK1&2H6D[R^EG%1EZI+U06F5MV4N;G#)`1+X!HE-5H3IC@_MGM\7"9NTU1( +M]!C?:",=TDNG_R4'EGB.N^H%4H52?$=V'PM9#K`H?OH-M-JI1$RA^)O%X5Q+ +MB7;OMV55F$P3H_!?&&O[DGU.464.)TNN;8U;`J"'RA$`>PXD&'!YN@3\HZY: +MB7(C87<1RK<8/V0Q75U4`9G!CV9RD?O,,5<\S<8<*WM?P@;P'MY)VB0Y-;/Y +MJ#ZCOX$("`Q.+&X/DNFH56@FM!Q=T*!NZ%S?Y>E)RP3%WU^U"GALO&7P;*:O +MX!3R-$^[TME]_(3/3=Q]R'KE@*;6%'2-DN;\55WA!'0>AV^$4`]56">1E&E@ +M7VK4JJF3R9:DGS[+27)-9IUGM5TR,/B3MB?-1/_DTGLHXV3@78`RW!:$UPI$ +M`#YQ_W).@Q!80S*U)3RWK5B,9Y?FH;P9I$3'*)3ER2-,AXWQAJ_TINY(QV0( +M,`GJ3S-1]=#,ZY?5TOO+^<\2K9GV%9" +MSK6JA&CQD?W.I?:$-9X71*D1U66%$^3];8*@WAA9DRGK7KB4^8"5TUSI7G@: +M'A#T#(_JH%#X.6"(MK9/H44D/I%/IY*"A=BHBTTGD"H>9:/;X5)*[9.LOY&?6V%Q9PZ2W#9A4$-HPR4/<=U1S0'X,&2@QU_1K(@P#!>:7+.9KMKP`6B_IO?^^<843Q&Z=WTZLXJ59OI9 +M8,'+W:KR-)QB>J0%`K?!BBV([.[>^C?LKIOZ`4%_@QN9XWWHBG/R"3@W`TWL +M50>+0R'YA>E`@20N%EDJ25B*,-G!`G4K?;:<#2&+UBPOV"%Q@H2U=0!OD@'F +MY)M.A*!>\JOV$=-X&A+I>P6$?-Y-[BBC]4].7U1NOME)7`Z(:T_7XGN]FW9> +MJ.`-@WGS107\[1\A/O88`MJ%]#>BW(S,EU7$Z@0A`>0NG0?_=<2&\=UL=47\1M@"T6U!:! +MG^"YV7Q&-V;#Y^C)J>BRP0">:E[3WIMG'Z>@FM(Z5XM9EZJV;J^WCCO:4]ME +M#EK6KOS#TTCOCQ$I-P,-OD]W$]W)'`CI\;2O]M(AHDGB6X8B:P==0*U(5/ELR[GB*8C2=1%/ +M*,MYGV)$)(.X^4!YM;Z:?9AZ4QO?0`4)ZI>KIW/&F1/Y8]K:0R_0X$M?0E_R +M44)JUT^',>R>X$@ZW:G@YW-(MUNY`PZ[CULS!#H)SRW\02($2_D(;OEE;M?) +MCDCX=A?W13_JJBF&P^GQ#0%H^40-1@H(@?UH5CNUT57D%OV)EYCW71X2<,O; +M-.B'KJP7Y5)_N?/_BH=3Z\0Z<&UFW7GZ96!H9'HK-WOBS:+4T_9NE:P-H9& +MJC`#GN<9_SPDTTT7,B+Y]2*1B7)[*Q&IOBUR465!@<-#VO)A_O;W3Y*M#F]# +MCMX9CW%'HZU$WNSSZ8M+)UX0'VBNL;!8?*3()I4KLJL^GQTGBG`0`\R>1![< +M*`7_32)%(FMV#>.'6U8N)C[EY:SB:'/*X9N)CY')IDP2?]]SP'[5MJZN2^&V +M=*`397`2&:/6/JB:W%KF=Z>DP,17UM[:6Q!F'OM`?`!Z96^R=_LW2R#(4N(B=72D>UVAY0?^5DHV$7#@9T2<`>.IKY, +MT_-`3=_AY5DMQ#5(*\I#LYASLEC"'M/""ZL,($HLW!BG>R2:>2]KBO2'JO_] +ME&_E(Y!T#''([;K#V_Y0_:C%G*:,'=`^CK#CR&03K(QRHXM:":@2KMR<2.!3 +MQ/;OOR7Q'K4C!A_)%YSAH%'S@%]Z(+`ML$_+\/4.-#Z3W4/,52E]<"UEWD*Z +M+KPY;^L3J.Y^"-GUZ?*V+_%A*55RW!,'+U6U@9C7>^9Y?UQ/D+2E0;<3-%%W +M=UBQE(,HIO_LC-W&497+*FK"*#F&V6CC*.:4]N,-,,/'>*)'[7')^1^WZ$I/ +M2IO>>%!B6,?)R01,60]&4&WO]D-,81:`+%[C,:CRAGO&*Q]F:[12+69"I%\` +MW)MFR*<&%TP-PC3R+9Y98E,W?W\C_89%V`TI'V%T0^RAJ$G#DXMZLI]^*;GB +M&Z89-66!GAZM +M?"7&$S[3!5+`JCN;4L.X>O>V.7]:!H"'V%:OA"8RVO#*)N4L"=:5J`33CF(* +M0O[TJI-64L?A=<:`-;9A;GSSNA3'(HN^B>V'%SQ21MR#*#TU=I]/,(6I[CUH +MGC)W[2/[@(A@;"_P'BSIVQH8G]9HO?Q9QEV8^9NMA;]&,##0R,NY*H-M)']E +MN%#WC&_-%S/O/%.JAIIB8+;/PBPB<5R,JJ?6U,1TN]J5$FI^XSG4^S%KH#F& +M_4Y0%<:%7QO0Z(HJPP(5I>X6L]NGR'2:"QD#.+;9B57T\#4K4%D[O(\0_&JH +M,K,P]^*"93LQ\ +MD7R>^8B%IFR9!8]%^::A!D] +MB:!1#46ZY(&C&/U#Y-4AA]$X9/?EA_>QY%V/FV=S0!:UA_;JP]8/N"\>@I$B +M3T*6-HLNCWR7_7,_1?#17TBEK8B982EF)*#\9MTPZ9'3Z#L>Z$^T,:;!E)DU +M3GF<1X80/NBL-](G.6B#[RZG^U%'YD99/PO\/>DBIT0E(K?]0/HKS$ +MV_Q\_%21K@D&E0J9L;8YAKBZK3@]>@/)(WX,@-$)8FNE@%RL=PODGD]X=,#Y +M%M=;C.T(_#(`"'9%0Y>5UK4L?BQ(-'C+$K9X7&33^@)5Q--[U9N7Y$^;ID', +M=6"?A&V-&?QYT%#I53NR4N8[6^84&P&CZG(-.'H@6R;?>1,J`F&QI<.>XL\& +MJ$6MNX;-";!6CD1N36>>29=6WHP!$XQU[MT8T]C(Y$J>Z@?#O)]P#<]YM?KZ +M`[FY"RG7QE%^54HSXSK0S:H`\/%H!<0][?M:\LF$,VLJ;Y.TAY8!B@TVA&C< +MJV^W+WP>SK&X1)F\GRWIX<'H@O*31RZ"ZN?ZER%[:DZ(16002-_$"Q*?OLJ` +M`D>OT,X9U&T!2.C:"AJ8QE.K&2JWH!"._M&X=U`L_)RIT0*_M!?/W;"%%84M +M7\FNMJ-_K"4%@V-SVI:,)"2^%QF842SBXT9?^FR$7V^+Q:&.TSL&XB3$\N"K<3\XEO75%;F/;D%E?3M'?\![MCTLSDTSCESS5LNYVF! +M7L?4:[P%HOOZ'U:Z!Y0;V>RS:[4=X7(3;`:-S9A)_O?WWX>U!EYQ2M@//,8; +MG]Q[N1B?J6<$@Z*O"GJ'\G!Q]1@6[)*LO:LWF30R$(&==$:C/^HV%SC77A`E +M;]1L1@U]KX27^T4*"(WFZ3>&2/3DN9L(?+_I&[\YU+"JW:0%1*;78"+FF9I! +MQH]/TQ=B0*[R%>(J$^/+0"Q0.P_'[.'FO;JBS\/(%.ZL"3JA`8J_QC_Y#JY, +M:AV&20VJHO"R6X'BP-'9@'`C\;I8.K!&\/HSF1)2E9A6U'&CEP"$+2_Q]3KU +M13]5&K?$`V@_"8&X&)MJI(:,N6R(J;D(4/V`VYP!1.V!BCR/\+5,Z^L<37R. +M:4>*.HZ"SS+R;$_N4Q='&LZ1K%>P-JX#VU9XQ/B0DEMDF^&=K4#3H=T5.-\, +M+I5=6!^I&[N:=S+06G'T#NBLZ!X0\3:Z6G\8V8'DR/JMBHA*Y=V;F]M3@L?& +M&(7,9UJK>B'NGA7X3" +MS6PY8B'&?OHW63SVSH)O2D6"1>;FH&AUD<01#&1XZQQJ^<4.L5UHTT`#)@\: +M/^88QRLS=&0XR[]0]>TV;S;1LR]7_L,[N=C]T7\E<8`JJZ2Q@CP!B0]<'P]Y +M!#))S=`!U3XC)!S&<@S'XQ\\@%?:YS+OS`/^!Y^64S<G]59H\%G`56M+$86?)FK,;WR>-&+I&PN3F[\[DW=^2P5WQ+.U,`_5%926`% +MS"2,PN"YC-P<#^`P+Z#630QSU_DP+ZR$X^Q0F$*&;D,6B.EV4WAROEZ-(7F< +M9??(H^-[DLS4Y*_<1L?,I#"]&;OB.#J9J1C`=4"!Q/B%%KX.SRBS3-T8RXL) +MJFZZ)[?IUTUXC8[6B^=?_['Z&(8!2SDN3WD;`PVF\87)`[DRG5U8\1V[;Z$C +M[C315L]E^A>343Z6/=Y!,Z3R7?\CA.E2#+\Y( +M8O'JVJ�)XX%$&63-BFZ#3R4`N.#-F)8/1J;=I7CV8T&MT<(5:U%UD71<7? +MI6LYC.LJTT*;^K&("39@9[1.5_,Q&ID6S!7I*F(6$U6*U47N@Y\G6&MC[2KV +MEO;Q%+,YJ@YU0'B:GPYDFK`1F`3AIPC^E/573,@2#N.H^U9.!G#(R<&V5 +M13,B6VXY_:XAWO#A\L%""JPI*NM-N1MIR`F(/C=_ATZ=!=/]ND1K.H +M799IRRI:3C:A]B1/UD:[)UC/FB;J@K2:B)Q@6=3?=^NR]_R3'?'+3I[I.1_O +M\"^:,GDZM*2RXS*Z`\,YKZRKW4'\-84EPRHWFB*&/W<5=IK\7:C<-F&4J&PX +M.K9D<58#WQ;I8;OKW-+MF$L#1%+]0@0TCNCC`H^,)DFDT5[$?5-R%^3*D6V: +M7/40LNQ9YXD](*X+6_.VB92)NUI'Q0O29"ZQ:OV?7@*A>#W9KB>@TCBA:*PM1-LTOJ3OMVSG4"' +M)&PGU7UA`@KD'1C>0U76?G!4U9!C(4[()?!Q("7)G-U:N*C]DN332;0@SPBB +M4[-W.V^0\)YL1V"JBE&BM(4$63(D@H0UK4D@QLV[Y:<]#N?:K`D7KQXGH*#R +MJF;RKH]?A7:N$S9[3,+TF&S&$-I1O(-6JM4T>ZI4 +M6EQ4$B'X7D)EN6D*MF4]6K<=7"@4YX@-"21+K))0]E+Z1D[G";+@_$!$_ +MGH!GZ:1YT%A-J#Y>WT",#V,,0($NTW'Z3XC;;62=U"K)."PG!!P;GZPK^&HR +M4M/1^VW@$`K"9_T#%U'E/L!BZ80O93QLPF=_<&*I7A*+,75N`5\F>9(NGX*! +M)<(VHXDNRJQEUL_Z+$HIV*FSW0E\1H;.>2BP@QAE57TA>F*&O0X9"T3+)84Q/ +M&@GFH&8U'W';75+(1##*S[V5RV@J:BHD:@Q:X1<]@E8,*\A_^W+4&L#]U+=O +MVN`TNQ<8T./<63@Y4G?+_?WB^ +MW?0QJM]UHK=8;M:[CD4&-5+*9K>,M'BRCAI4\[M!W1TV6)#O3!]REGXUF5IB6+Z;#[LP)\M'7THEU!"N/GF39A>C +M92+!9QY%&OK8+&MB]+1]5Q?^APR?4]L6FEE69'O69\'>PX_&1N*8,F#('*E< +M+@S:#4=-:8-9YZ!NM[,&I&`7.F90`ZB8CY"\T +MFC?_9BZ\('.;!,_=Z'-KYSQ7@NR+<[,&YOQL0@D"UN=` +M.&WH!3`2[N^42F(=(/]$Z#U(.D26<]=U1WRA-%#KO",S`42C+'=51*DL:3-U +M09>WLV#'0CY%G-#^.$(V5A;_O>^2^3'>*N#-+@_PBSK!X&`LD)IZ+NX\R&`_ +M=N'(<480K=]T"1.-T"R?K"]*,+HS?II-&RN[!57;^6(VP:.%26QFB^A"/V2B +MK706CBRRVG`G!/396UP_>_C5SH2B-CD'(IVE1+:I8)B,=IWM!?];;AU4:JS/ +MP-B^%U70KE4;INT\4Z[[[)'ELCF0\@16RAM)/O1B)8'43%^Z@6QB+(G'OI6^ +MR7ZWM_,B;#^EXNHH?,GP86/]$#)^BTFZS2B'-%-?I^U=G".#E/H@V>(\6[*B +M2SF,XN@',]L(BG%;$=5>3G.F@?C<\^S$/4"0G":W8P]\QFGNN@MA^HCD2"TL7KFVVZR#);-9KRZLL+&+.7V_"Y/",ZOM33[$`+67M'\@PW!A4<:XX^;$ADCCR?^CG]6(UCKFBL+XQ)9G@5ZWM[XV/7 +MO9@LC2C+I]NJRK<)05!Y2R@Y*V.T&B?,7RK;QMY>?T-D(K&^2([&PN?3&F\"WG$ZXBT)W=W)2#(&D +MA/YYH/*2HC_17LX4:T$A-O_.\<$UOI$B!H+_O7(PC=`BA*1^HS7H@'LW)_?JSZR]KI^BR"&@JV +M_H:!6&R=`_^;X=N^19D7$(P[$1292=N4(2]..+?RYKG@&7.#`"_7]G!%_9!> +M2.0:&&P?5F21\R&6YFH[NL:_YN2EKP\X"<,$S+<-]D/3RY)%(0S][:'W(EHO +M5#<\!.8'#H0[C,M=\#:(>C_/DA(Y[);-?,Z]&YQT[Q7*Z1;#`,=8AL7ZS<<$ +M#H4=QJ[3J;/R!-#4].$VK\SY!Y++E\5,:[>D"3(\6Q(_E#6^.?Z=/OGWWV#] +M5F_NKFOB"1Q7NGH\VH?B;\PZH87L67R.';E'_2N$S]/56Z_!4J0U-R=JA?(XRL+SN@-2-]FEI!F +M?H]37@7B5BE'7JFN\0N7'!#%8MJU[R$-BL/;P"W*9.NDG0^'S+&HU\87RL'> +MRD15@"G)2[!C>?V#4Q(F38/<_M0,T$CY2>C;HC=JRL=L4K[]1#_>*;LG?.-" +MMYEHCY+CPE0>:XW2TY]=1@'T4AI'"_HC42SM#>K)Y)?*UZ/L>&BZD$C,RFW8 +MV-"6@>8-]S\SGQ3)"=%F@1"'`-0A(@O1QSV_U +MLLE\^B#`^`NEX%.>-DC#%^"6'2/_SS^<-)=)S]4HK3MWI`8"IZN?H$*6X>BZ +M`(9*$O)#S*,W7PQ3,J&#%+`34.1A:A,H^5],:EJ`=N#1A)=GXJ=Q5IL]YNM% +M<2&L=YI:1GR]:"XQU?&Y1/)>?2,^8++:93A/7H@>1A5^S6/N_%D;#0YD5W&\ +M%ZFO0R0]FV@8K@+$*`WR5V@%`4:`*Q=5.<\.WQZ-32@-&3DZC1^GI?8YXP\ +MHT9,::O*?4K^BOGWP$484IK-S)>Q?73$6X4_M4H%RGJ$3:+QY63_1YBY`5GW +MGOZ[1 +ME5JAG+RZ!]G(TJ8&P47^\2.?(+C!0+A3M0$&PV3'1K6W.RF62OBA;L"TT);2 +M+\VOV@&CL^A?595J]L@Q=YBYW/ZH<#`/'O)GVM7=JQ!U&(\`\\AUOC&]'30& +M+-VR]M*W#5M\H+4R/!&M)B/V&D31N;MH91F4AKLJ7W&,_@U: +MZ,>YA@:G/I,I_%>!*"32\LXD/U!\T>.#XGI2H8%IP3F>_]INU?#YWJ0C>\DO#3;N>*#[A'G$C*9<[8IER@ +MJFA-Q6GZ]"NXW6^QM)]T4?1S_`'#=NPN#CJ?XD!0/;2O3(P!)E\6*9;S0!G# +ML-;'N0!!=O7&M1"?`<6'"":VG*3"$XPDZYM8DD!N512)W85[#.!MKPH.K^.N +M#UZCU1NKES8\JKAJ8"(@;XJ!VB$09/?KOX@+H8A.#32,C0'+@2-\I:X;,S1% +M5+]FQAQ5DNFZ$,EBM>'=S$:?3JTE.`E+QK$S#WU48ZW4ZG1)Q,"AN0`%#G&` +M]^#)/$6A-]8NK>78CDD1;56/44]*IGUMRHL^E;XREL8]Q" +M!^&R@C"FW^@VS9'S6B<*00SC!C5T9YAFZB[9VACK")ZL[`Y91(DMZQ=,6;W_ +M$#Z9"ASU:?%MAQ(]Y"KT*W$\?"B+!63^J-:W+3U)P%(Z-TDM0X:1)!("G$^B +M+E\9NMF_E@\Q0Z&?K!(C"@U>V*N4@F@U^1<,9EKG\+`W5K6Z=6N4!BZ72N"' +M`<,0$"F@1=X#,9!*CE6/VL8;/,.='B9/W8[8_&MKG=IT`(#YP"J)PQ8/FO;+ +M\9!F(Q0P/8TY(]!0AZLERBD'V4][/ZSYE6(U_7F->8Z=I@DSL&56>DB8;YHQ +MG]^J+E-)))S@'+&LS.N31GM9-&OGD=VPAI9`V@P,^L'W(M*"U[,/K65#X_@P +M^DCWJLD,K-Z:7Z#@OAT349`$%,K-W"^YVCW*.\T%J(3E55':`P97T`;=Y9:P +M?,22RD$V`^]>_[\+;,Z8BZAP%S,$:UC&L*4X!XV0*FU\;*(*)PHBD$(D&GD> +MK%#+DV)E2%E4P)-V*9T"XLH>AG,.9SRSM&?7R$<58-\5C>!S11?H?7DK][/R +M%[N0W9@M[AI^GDJI7J28J1N#;B$7\\]O1X;$HF?QH*-!+W`:2-.BM2A]>M/Z +M/C[5`21/W1HY8Y+RZUX"'DB-*<,4YL]M0ST!"%=4<1Z""RF:"ZD/?`%G,6B- +M.=GJ.Q]]$3GVZ9J:>%*/(>P`(M6?+.>;,0SY%OD_P)I3KB-:]W)_01$,'2:"$MW*9FR*(TQMMB4MH?+T,>"E?V*+";8Y5"WKZE8^@I9?V^6(/KM +M_-8%2MM5>SG5'3C.L69>6ZN:6TGJ>6"MORQH;_@2?C,/8-:YT):922X'Q:1MBLJA, +M4\*F#X%]:$=C"YX5!_?'.A[R1>:^1MR"U+KCIEGP@>._JA(<%1:HL=OHZ6 +MHVBJ0QB@1)/+!(*5^U%2]?')%4LS+AF06QYY8TQBY8P1J30L2;G(&,A0\"*@ +M])V<5*K_>#9F^3=CX*P-BY=32N*.#M1L)>F@/B*-A'X$^+QZ[8";[C5<`;#U +MJM*UV2&!P=-';.AE/"YR8[9_J=>>#$;8$ +MS2"<7PB%[6,W_X*Z;]3N+H3GM:,,/B +MW:)32@0//IS*\5*KUD@<8+UED#RS#AWDX:EWU:;X&B0G)O05K%;7.H2JM!`H +M/YB,U,FTT'WI'S;@G;P/:S5D=3#BP*/?VS"*QHS$H(QL-'1:N&3N$0V,14R\ +MU1VS?XSPY&D\+79*_:!IG^8[NMZT,2Z72-O!99A(/H^H\+%DG&U1V,JO\0*H8W=YWQ;_2?%)&0IM]'Z'%Y5\LY;L +MH=Z>)5?K@L1Q"0L!C<733I#)NSRWKVP-!X+IV^-B*@SN^%4RJPTN3D+*'ZPC +MV7C%'+HF8)D_+Z#YJNHR;A)NRYC`W:[^^4@Z2Q]4NP.0=E2`N`)M*"%H[1%Q +ME-_8I0CKO#?['0V(_B:+D><%`*('*A"(F@VFD":'$30+^F#$!R'ZE"RZT&@< +MC\L^ADN,`+BQ9\1?>9(!O`K+36U2,]]`GDFO9Y9'.!9TO;#NJQ'9?E`=^#^[ +M'HR])H93N[[0Z])>C76&9UK<-F*3_IT^)_Y:K.364*@45>7+! +MB"J#4@NG9,*J%H?D`@'[U/2MW>C'683FSU1`3!V9I_.*PX0DUY'2\KSF!5=3 +MF`K]+C0096=O./3A/>@+9P'OM**M"+!XNZ3S3A[<.:D/H3)!64`47H_[@1,K +M^J9,T*\PM[O$7N-]!(M?^.Y)XP+3`H/4U!`P'\C`#$D&J`VT1!1GK^0S'-\G +MT4HG@/K%%@M1\VF>^G:^#H8+QU]2(-$`)D0$GKQ>HJ%N_F7.2!DL@.H@G:S' +M*=6,:&6'#K6&7)X,JAYHV*]]+4AFL!_@/#+/"2Q45!ULY:.B:EFJ6XY*[."6 +M)?W3O5%7#:D[GT)Y!^NGAJ'AIUWX12$+NK&358K3 +MOD(+?RZ\-D>LTQXCV\)0FCX#"BE:(Z]BM/[@&C4W[\`OUN_9"N'?VE<.9)>B +MQR)#Q;BPY6Q9._;R;^&S(B`!OIHH5$#`2A]@$]!*LX1JI)1MIE"12VCI\G>2 +M7P+R$H85V\35C,*8;I@1?HQE/+&PAFA[0-A**83?WZ):,(C65POTW;K-8-9J +M2H9.$7-M1?S^SE/^C?U0%RATSMESZ<,.NHC>Z +M#'HU440X@.ET$+T\I56RPX]\IZ#X.X:?LL.9X^\(*U\;T.J\D^U]BT,8E2SN +MXL"!;![W&*2?I';;I6QK@^S0\G]>8V@L4M]PEE=.N1K%M^3CMA#2?6D7GWZS +M;XVL;$/YV6O)G>;*A9>IP%G<>-AD^A9L1MR^\)NLV'`J#Y730K!D)Q.Y/PR? +MIKMQ5@-$HV*U,@!6T%,?!">/4O%)?4*(&?%GH$<2S-OAU+S)H1QB>+",)_); +M`49/!@O&<`6X3@0_00HSKCGJ0?>*56<*@&2[%?C/9,?\N2P=RZ7"K6O$:DJA +M!KPGK,%TLS218IW(YBBU)7-%U9INY/>#,C- +M7!4MR,LZ!D:`9L>EDM_URX]?5+S0^RW*6@*/%J*&WV:_R%!K^\_\'E%(J*2^ +M5+^FN`"T5,T_^_2JW*W5S>W7-QCT>%.YRB\+(^Z)/<-YHA%=BJVI +M(\QX]9R+8TLXDX+`A`\8P`D`_+OV!L'VZ9Q?+M*+^-\Z"2RY8J.1B6&=(I.O +M"HF<;9JO^A-@Q>(L]K:Q:7[P%N,U_QQDZ\8R-6*IWY(<.:+D]N^^+>>8^$)@ +MT,K@_O^>$N+P`$HN_7FY=B"0+H6X?SAE9Q^ +MT%<,?2$P[3EMXU8F;&H:`0H_^%R\,^XFC<";4#%D=%EK?IN?XYHR:49A/FU9 +M&IC0Y-;.&T[@#I5<;BXI]-P,L<1K=08RT#U=-,$HZ?9+N68C7*JL(KN^1_G% +M)#*-B""W#BY,=8Z$#1AA`//<[T5[:1N+$!U4=YQL]TH9V[05R^:JOA^B!=0J?PQR%GX6O.39^PRGP1AK<&#;C'DZ +M/`$[,74XBRF%O4;X,P>J8B`ZH->^ZWT:&/ +MY&CM4UQ(,9\5:H#XL3TC@Q%]#MH%F)V>.!KO'DN09-UO95FQ0ZOT?/Z$CQ,Z +M7S59XVV-4J8.VP7="N0:&\`CH5;Z%[]GA7VR>XC9K*1ARYD< +M%J.YK6LB:P1$04S"6)B+3>"G(N<:Y$.9(O_;>,G0'?LI&$:!-QD'/C1_S0,H +MZS41"0?TBP2T0Y1$_Z$^KNPT<,Q,"#F'5M)':!C^%\'*0]HOQ-]HAWXW9K?" +MPUA9UXG(M";5$>^V"#V+0QY"P>-BG6>O8(9:9!%`@6OL,L]V4R<(PB-`XJ75 +M;],6]HE$%X$J$764!FN]T<8PD?H<6FPC\_-Z``Q[AQ0/^F@?/R\U\A,0IO*? +M<_\\AZN0D),CJBK\RQ]%1X! +MZ8")6%#1C:$*8[CHMO5B?_2SM%W9@0;-[Z<+PN@-3;75;.>2@XP<97',;&_^N^$9$/D:"BI$N^GUO3?Q=V(M6H$ +M:_7T,2\1-R@6')O*QNA$<)-,6F*D9`XVZJ`^DP3@.*"L8MGS.YO[3EC(*D3< +MB#H6JOIA4.^DU^3Z##T&=WTL.7?`;8G,7=!":SAM44'8ZQQ?WC8>9+\X1J#W +M;QM3Y(!/J47C-2'A8N_J856.DOX^H86&&'WVNT6/\JJMQDWDO4 +MO95BB];Q9)Q!X>4'&.EF!7)G!^%@G/-_Y +M_\IQ\BU6R,#3&)(P4<:J"Z6< +MRZ5RD`HF[>%)'T`"""4P(>W@FL"HBQP`[/.S5L/6GYA/!EQUG=Q2NACB7;1^ +M%L"#TQ'AU0I`MD=^G"@:=*%RBFS1_2N5=4;2-=EQ0YK +M!IDX[[^)53L/5)#BT4OQ,<:[M*WNBS"\K#9,Y3%U]^9#'B-0*:"#)CA4D7$Q +MMO'>1?5D]D5MR;.IR*4VH9\O_=BLIZ^RURI\KSN_[^8RP=-`UAZ4:J/0K!8* +M>U(Z\D*!OK^6,T>"`Q81>Y\O.O9+^"D&-?>$2B]E.,![C87&YU06,2O5?-Z$ +M"2G=C9"[#O:-[W.RM`1L`YJ"1'_75U-FUWPS\EYOV'%K);8T2A\\UK_B&;J" +MUN%Y]B\VA8Y)0DS683AMWT+H?8/Z`E91(^5U4LO-"UGX4GQQTY<3=$X`JLEP +M6)$\&8K[/>^0 +MPQO-0'#]X/T?E;02KKG\)TN@/[1^:B65;,5KY/8XU[2+MJ`LQR/ +MG#D!/"\P:AQI==!;>G]O@ZI)HGYRF;\HI5*=QVP0E+%!OM=`N=CR;%F#!`N?5OH#+Z"+"6/QK;>-MTW +ML'%W65P'+BX8IH-7IW2Z.],+88ABUBZ\E29T/%-8+3@$HE(WB4:]^6^/ZTKVZ$(53^]*KDAMF">.(W/IRH1C+X9AT(&@.%3`J +MPAQWE_4WV%`"+S`X98$<9Y/,?*VB;-DJF.4#HP2"M3$TI"CM>FAR])6`?-GE +M`.X5R"UL\YW?WQCBQQ\%^SZI%:DY^Y8'($8H#E*+TN&T,"9-,PWE=XAH8`].VF;_O'40Y$<',Q`MU@IA@>LQ9(E\+\";:12D**@1Y;N@W*^/7PK: +MA@YAV(+PQJXD]I]/<00H7C($4JQ\%8SD=H`67$2=`?L9IO +M2FCI86'R0>HR)^!X8"K,J&0)J.&K68TR/_)*?]<1?UG:=C+V?MVIJNT=1P8% +M4Z;VFS#HQ;2RKA_:TT&^45DOS96M_MORDI[Y06C78=1^3BULT&,954`LJ&9& +M7A)U'[K\@A'5*C/"?ML(9M#^*M`G\0X"L`P/NA9QR?R3N5_\*.2V+C>3-,(8 +M2_N7/F::$\T-00V_\!1IP2P4!JYX;6`PA0L%ZMR_OFH.&Z64O+1LG5T]0QBZ +M@!1!3=_S<8BG%0R5WGQOB1LKO:Q.DNJS[H/96RZJ*#H%]H2B`,E4P65<_:X +M/B.;E(ED/"8Y)_;N$?G6@_?^_PW[>*_%847_H5B8,5TEMTO9K>>1L&?D00Z$ +MI`D]G!65:TD-X1EPGT7-3\#%^[J.6RIA41)-)O1/K0^V[\S6CNA>#3N,9*3I +M%'B0ZNO`M:O?6DUV6)Z\V/:F/;PFW0[=C!0K3"7,U.>2R,E]L;*;#N%Y`P]8KN7'L-9[;=8IE'0;%@C*@F;"@+E+"+<.MMJ#+>^=7WD*(?= +M9;*F+B'EE7_7"`8[T.'?Z:5>4^*4/>G;6LQXZK2VFR1PP][4H\%@(6-1[>@[ +MMND%RDU1*FC76ACK3#E5G\=L'84:X2VPBOFCO(AJP8)B1Y9P)*//VRR8O!:$ +M[C>N\8^..R/[I0+\JS0@]%X=&8H'-2@CDTVO6(A]<2^PWP-D6)_.?:$ZU>49 +MK>^,::@JZ@3A#0BTHU!1,HO%30C?78HJZ1*T9`<[\Z=UD?.Y\"FW$_=C!3DR +M_7^"-WHADPJLAUFY%?9E@=U"87,DQ)V$\Z/7BH@C0)X`DF_8'OW0">@'E-Z* +MMVC6``DO5OO]"B'W\-%;M7F`+=W&^(]Y\DC+C4H&PH0S3FA[78UP;3;)Q37TXHS2/R.KR`R>S#H:"2ZJ8+V;KE[*8]")(NG=^: +M0/S(M_PWS,.O9Q2\[XXD'/4<"*WFJ4F/EJ%`B@XG="&I.&IW[+YH1.L?4$&' +MMKQ_@@%'C'QSZP">SC0CK^#KNT8\\[T7#XIY`0D*T:KZF!OX$>$NQ;$LYL<( +M;UC#;QG#>PW$<^H[CNZA,UX+WJYB\%6SDS>MH'WEKUX>J66SR>'$NO`HQHC0 +M(X.TLKKC?IE\W3LHKY27"*O;_\%;MCM,!1,H#@^X="@U0I38N3G-* +M0A]V\^"45R8E?&!V[,)EP>9DK"9TG(-G0D38^1%N=I_GN#&=;M[+[+DW)9%D +M:MNJ[4-S#<=6JX0^YK86A%5I7KN8CSMQ9,2C8+@W! +MJ].8*R&R`7O;VTM/BS#Q3QD36E^X.**^;^[<)5J%:%CT[V<:)U%VQFE5%,2" +MA49^+?X6'$`%H]34^H4\/"7EZ<>9?P4/VH#6C__IBNPQ3XL//S-[CS_@R!"? +M$0)CD=282\U::342,+8=R@]`'L]?*4[*;/9J_04_:W)PKM*.[#9W:0;4_Q&\"V?^-@?BS^P +M$7H9H\Y%""GI@U&RF@V+C]AA:E(@D4VE;VP`O`:!"AT[2*I#G..`MN.TPIQ\ +M^O<;K:P;\5>PI7N2[D8T=,:G=6$AR[U"IGB`X=W75R@6 +M)_Q,.+:^_[6W%GH%5#S@2@XQN:D9-_K)[-VE9Q9#:HX>&/V7'R!?4(F31PK0 +M4'"$7NK(];*T\>^P0R/=5[T*GCA[#>,)=_G`7'OJ$;!_SV]#JZ=R^$A=(JN5\@`4,ZA?TLEST& +MYJ9/VNQ!OR!NH`L5W&KJLY&=VW/&DQGHV;G98FX4WLHL]'=83!0?$V+MTVVQ +M_@M(Y+&U1/96E+3HQ-`YW@H;7]9QM0%JG+VZUB*#9(6#%[!T$,OZ:T53',?3 +M`Z/R<&[-G;V)F#R;-GNX"&:I':;%"QMKQC=71>E +M!!S+@(QD+P,O45II>?%.;;RN''EY@$OMA_!J>:MH.^!;APS(6.A3('*]R!<26"U-:PQGB:GJXC]!$;E4@_P$RJ*4>OD358)6>AJ.Z3A&,+GV04E.K>:<$C5A:(1&'&7"#!U,6 +ME>1B$OG/W7KD+*>DI%?IQGJZFU;?BNM]-PC$EL[V)A92@)!%-8JAG+S%<54UI.L7NC4\/R?F3'7IMJ;UQ0920'/G7RNGWCYS'>D[!/ +M0XU\D[,]9.VRR*H8"&:5H)?`P5\"$SY/X67@K.%)7& +MF9>Q&NAQ"CU.N5+:\C)I.D>U0[09#@#?5:3)C=#1RZK9ZT0J%+VAV4HR^=WN +M&Y?=>?&X7\/2/+77RX1/6)DXC9CH9Y$W0>`B$3C1H%GY>XQ[U(*#.N^WB9&K +M)Z9CPRZ$$FI_L8F3]ZWFM%GGP>]3=H.F>WA+.X.$A07IK;)TP*,:EPV#\\$N +M[@.V]Q3A#N1B0*V'.6M:_>S)21.;;F%XN>"I2<1%+#._"D4"0(J79ML($J&0 +MG(T:GQ!01XOC9/.6H+,U.150N@[/0Y%47#;21'.Y)%L>7P93+ID+5>3NM"`I +M&E*1:VE!9]?*YE^?&Q6==#P;M>E=\],N_/D@%1 +MA>X$5C_BG.?3:VA!U3%O2=GJ>A'!A9.0?5];'RF\[N4#BI4M!'SA?=8='&^X +MD`M+\X/^2C.QI?)Y'E<.`6QU<9;,&\*""?O*0I:%#WI$6CU9:-LA(?N&4X,% +M-23H^SL,Q;9FQR[Z@6GL#XBZ*<0]%GST>@]?*?-MC,3[QESMY5MLUY;@Q*>I +M_T]9GX$'))$A%1ZZ5"PSFJ"4'9%:]*UHOP6C,N+_T-VY\8(G9?2"$$'X?N7W +M@R3GV9;CJ%(3?^JZB=Q9JO&>C]D*9:SYS=K>G%Q<5'YYE$?&Z366JCD+/6%_ +M-K9=]48U9L,2+ZHM75QY&UZ[_WG!$M/&/N$WD7)\2N,26Q+V2.I>\J4_ +MU?./B3AG1Z-41'K1"#9B\G5 +MX2/2#C6YY8AA=O\9Y=/ZNWF\'S&&?JIJ"HDJKW(WM"'E*2]_]LGS,Q97J?M- +MB<@IVPJ;?@?H7$3=/0(KE6BU=*0+' +M.V8D"HYH#;L9N0):(><0K8I*A\`@`N[7HJ2E]VIV(,D4C]O'N]^C-??*GXS6 +MTGZ`6OM#O;B;':_TR1Z2N.]"/$#;10,T8MU2#-MH3AI,C#I66&Y:$Y[K26,) +MK1"PQ82L^0=8`\*^G-RU?H7:?\R,-&)^(O=YW@/\,N^/S=NHX-$J'_KT]>% +M->-I4]"[>88B(H54%"$";=SYC,<5&=M]5R+E@X@5G/D)3-05K^*=4*@'$M_G +M][P$U"'--A.W[[(*YG +MOFM25.<"YJQRH)\6?3((IUCCLK;/[K6!],R5`E=HC?.#N)*U+5>"N/DZ8;1C +M^8)`$T!8ASN+'/,0KIBXO[]1O#FO(OW,J!DV_*$U"1!X0O&X\%AXF8AM#H:O +M0+OO#!'9'=QG(/P?2"D3[9S769`5=MZ4L"W[#JSR[)F\E((#$3'T:!(&>VSJ +M?SC?0^6VQ1<^2X>3DBKV.CZ=]\;Q`&UM,3PM]!;K>O2&V#G(71J_]#9.+GE` +MU5DF,:9^K%@,8D5C!LRWF5U=C>8_+/TK%6R!=UH9>1;!7N(^!N7O-$M_A807 +MTS1SZ-HZ%$Q+.$\LLU%"6X;'1QZ\ZU?G6>R;>;TKB0`Y<#\])7\MK1=8R?0( +MOE;\/*EY!\FEJ'Z>F^<8_0C71-5\@AL6ZBO$:6S#4CFL2\-]5[_QJ#]3%HPC +MP?EMXDK4X52AHJBIJ+.4''9L4TH#L*]+"J$+RR7<,GY4U@FZBW3,S'>O@V,Y +M<2.ZAW*5MG6E8*FGHBAAI9^W]F<$O88VZ+@+G+XH)2ETK=.`1%)+^*G[F9B& +M-H4*U?`.#3%I0`.[XFW!$/(EV"R&W>7]I36?'I]:^,-,BFZSJL;?$=%%E!BP +M+1+.[=)QG>;83HZ#XRBDM#G1_XE-)T%Q'2D+<;!.!6TF]S6^BD34L".\,9_R +M.4"R4R&)JB0)3C[EBD8(SPM#W-6.+F41R?Q=0`L5!H&_0(L6RPQ6KRD7/=ZX +M+T9X'Q]&,83-9ET<**8G>!7U3Q/=%_2NS::;9_;:@NK0"CQE*7UU:@9?5HQI +MG^K8,`Q]FVGEKU7)!#669G.W:)ET_4&64$RPX@9#9-\8%TIO>N&OM+_F$#OL''FD-]Q\U +M!E<0<$#T6EO4RTU\^<07HG0HC)#2-M0IB`\,>TBG#C@G;6.9+Q&)?/Y>3J+A +MG1JIPH]EBR/>1&P-K,WLKN@%K[17K<8WD,`%DL,_4\^P0N!SZKV+'6`L15>S +M$2,MZ,CR\2=W$L=([=HU$KEI__RH4TF>1[V4?",!?#N[=^ +M]XD:;OAX\1"*SV+:\MM&)9$\:2LSC`A6D\TQNFU1_77\9?DY$[M[_KOQ;-A$ +M:I"VR6]3%#]%3T!2UM^><#'@2[>90)0JT,PV"HW1>XDJ6#=8NLO[^3-0/I-4 +M'"2RRT&I;A.X%F-CG?>DA.O)6SZ;^-1PXQG'\%35A[;#-V[6><-5N3"3X4,B +MU2CGHY5H:.S\G.9JH4NI3\7Y`:G%GAF'E)/=@YYDO2>-@.8HR3T[1D206T7_ +M6+ZD'!1U(KOFY@'.)3`9*`/U,4[K`^$ZPM]V7SV8_Y7+$&6QHA?4DDI9,)?' +M/C.9J-\_4<2T@&]E.X&V2E$P_YJD(E08I$QH*QQ.?VTS^QV$;,WJ%-A=C6@9 +M-L^A8Y0M1!Y>9Q+>I\!F89.?4XGV$]VJ0?U*HE:G5@^'-%=/1^NO[3JT,ME" +M($&#LY+POLE2F!B8CT\:ZHM`G1*>'L4"%:R:.!CPNA>M)\T'!RV-S +M(QU'??_XE622!6?'*5G"F+>J'BT)F\7P$5YQ)*+OG@AI'!CV./\-V?YT.+O" +M1_1FO9J#1\8ISS+B1?]S@:1(<2XJJ%G$VCVN_H%@#C[76?Q,=, +MJ-(3/,31JE#Z9!@;:V9;96$H.5.Y>^`GBA/M%@D#%E4TN@96KS3R/C=C$]8W6M-,22C"T8-QM21W2->[2IT*WWK@":2,'M-]V)*F!7Z@$;7-2==._'`4&=HD'_^(Y:G#3# +M%;=P3H(M;'F%O`K50C3(TTIE'TGEO[DCHFLV366V10*;KX-KT.R,S(1&T.6E +MP9Q+A>-5Z!>_K3%B@$8*QG%+3!WH(5TY8S_EE4!ZDPS%+L'P$EY(R!YJ7,EVZ%?P5M&>P;\B1YB9;TXA%(TOB\*!,B56OC"!;>$_W"FQM7PT +M;K9$_XTL+OI(UUOVB +MN;\WCH$C'4[7>L.LQ7-@`JILK]+DKX]Q_\9-Z>H\F-2 +M5K#OQC)PDXGP5#X_]M0\H^#<]NYBG8=7$SZJ:16DMZA^P?.PX(.`LQTKPJOH +M23.=+K#ISR\O#L]PW^^`H=7;&UAWJ^%H)3!YG3KJ<$6D4(NQ%3@-B:N7?\K# +MBUSMV&5C9LSOT#-N1/G<'-W>"N[H$`@,B!"@CF,GD&7R3'[(!7`]/(EK*S6^ +M&R5!["@DP_N+OA`A!IBB(R-N7H<+)J&7O>?>\6NAE%^/S.U^S^2D1YWP +M;BN!#';-_+Y*289U`C_6G-^R2/NZ^!<'RRF%ZJ"SP<9N..*B@I\GD2W9&*0D +M?_;1"B;5J6;H=WS60E5&<"49BAM&PC6?=]I"O(E?Q(<1]/;?`+Z%E,^VUW:/ +M9]R#PI#;W/9'S!5%@>!,"VV'3NOI2J@)+?5C9M)=2BOPWTUL@(X($WJ^ +M9F/3@-+#C@5=%_[DQ5`(*,#]\EQM?.9G83P%X".-<$P+H]T$[:T*%W4-O;?I +MO=BE'>TH;O>@G'A%:\:^KB&5N;K-WI=KPNWYT%M]W@D!:7BE',G_A+KF'E!V +M)8#+IB*=2A*=Y7D@N4-0'-DAC/%URJA^RY]RF%;Y$T:^3$2-=A88(X(@\<4U +M/:ET%7=OY#17II89X$BM7T'&,XPN0X"^H5F"_UA#) +ML?$0I`#I!EA]3@]T]#BY<'/9=X%1GO3!SBFJ"X1!GS`I.(]F^ +MU?C7F$`$B`%^C$XBY(U;0>(@^I#^HAF)KTFW"T+EW!KC-T8+%YMA'M%"%00( +MD5FN^_ZYP])&K?#)#D]<[X\EFL^G/U\>Z<(IE`C^\O3MVO(&!+#`Y*EI/I6K6!FGM(1IM8LWLX/HB4D'H5F%KSRA[U8/>! +M-QZKMJV."%#=M?3[RG%N7>\?I-RYZ!9+G?D#$N^\.3KF_P\?,8\YNF%Z\X3P +MJO627@%OQK<`?.FV,:\\ZDP&=AW]'C",_AT/TW_#>H]^'CH*05UND=#+$#G# +M)=,_DJ[W-8![H/S35+/.(!>U4+*MVH\+T856=5WGQ&#IB:;<7*8YCZJY^QZ( +M.6PV8!W#0W%PCAO0X5.M+@S<8G/:FI2,5PM'@<.Z`R"XU6A;DCZI:CYAVBX_ +M&>.W"(SO,=$)K+Z85?_*[_EZ:M!IL>RQAUV`B&,/1T[WB0-K26MWYG.#OJZQ +MDX0=_I^P:]0!SMS_RI9&H#MI?2:L<:V:"V2JR%J=%\QM[66B::V$,7WNYSTG +M7`HI/`MZX.15YF(!J`Q3[_)X8P_QY=^J,V$">Z+S;S*Q;U"4 +M7BZQSEXEC)37T)";"H(J_7>G@"8&`Z%-WB8>KS5SDP`(J4^6^V[NH27J2$X- +MOOE8""4%8="I_`#8)"=:+++@S1NIJU*J"GF`!PQ2N&$[&@>#E"^O]XA#$BT: +M)!V.1M`M7NZ*EFTK$:`8(DOHI_"0H%5Z5]F'I>)=[J"&AQ9P?L0]!F*ST']G +M"I/4LF%8??-8>KOX'J$_I/J8NA\REY)*\]MX(A6+O<+3I\P[S'KJU?_54VO< +M2';J1U*ZF(;#"`2QU/SQ&X.^[>7T)B4M2+&BWM(8XV)R-9(C56?KG;J:JTYY +M9*6"LBO8/RLFD#'I(H?B-@%D,5B_Q39\R1!:!36KJ)8(SL:.C640(E74K&:G +MWY@+(+,>PI79X"BO0'E@/#>":\:85@JPCT^$FAL>O/(.Y76(7VK"& +M(M4.U5W>VITF&C[22E&*%[AB0HYM?.-"BL^2*D,_$M3I/O8\BSQ[DH8P!94M +M'@T5@F6R/I\6_G46GHUDXN1QZ6,["/U=(YJH&M[;EV2&)Q:A\XQ2=M^?776? +MVA$)U)_;!`#EH:! +MR>3#/'X`"F(R_*HWS,DS&M5A,S:CU+*:7.]2#UX1X83>`^VXNF%GY+#<@B5-\*0 +M[_H+4%&H87._I*?@]KKXEAQ2_/*P]]6.8E*7^-)J55.&>+JTIAY\B91%E>>R +MP"ZB0[IREKL(-0D1G[69=OO!(Z8$3T42&S5\-\&HGB,.I!B!9O60N`[&''ZH)I+-[@>R[5W>Z>3N.NH;TL(L@99[KJUI^?[ +MGHF?O6T&QX2%<3B(+VH()X@@+-OO,Z7:1Y@CG,Z81&7A:I[G0U;W$;P"VTL0 +MV;D!RFS?)J[E=W,+LH#($'Z/K3&5,=.0QXS=W`#56AGM%U*B;)#HA75UA4NB +M5UZ%(>S%+ECW5+-B34L/&<)AGK>^$/O"KIH.4(F]66:']DW?:?2!*KJ9)ZSZ +MF1U(&EM>A@"1&6(I8/KP/N2D`M@'8.-H*-NVTJ4G&OQ_=:%H+V84SO^PN:1& +MW(^:`OEH1P1O.G0[6EUG^GE`5;JO]I>]&W9.MI?\&'JEVK^E5S_Y[M6N[HX0 +M9ZQ'J=1/V_L9(M>1M6H-`4U^Z0W+MM`RGJP2B[R6$EPU/^RD!'HFGQW%5D^3 +MIFUJZW&W,2Y+B9OKP-WGM<+N%=LB.S5B'+/*_$Q+^F(=/O;]P5NON-]B0W\8 +M'U;HE((; +M%\/]G['%N0N6+`S'UUVS@.E(N.&MFTMOD.TQWC6@,+T%QJ2;M1=+$=G.+9#_ +M3VT\*K\IB$;(XAG:-_KY/P*-+`PY74$)GCU5ZW`@F/S/T!-'A29[^0;_8`M? +M'L?OKW=WNL3=G,9P7QVS_"U80^EJ))*'E^$H68WESN?J=LLKK8ZB/X9KWW4S +MJ00B9':DJ4(WR&^4'ZA/FO,"E\A"DT4F$OW3H+@GX3,)4-/C\L%N,'2/&076 +M$I&P)[>M$UY'TW-C**C71#+%+N\[NG;59?1SY!3_8TK(HW]<[H5+:PC:-FX, +M1^]XO,O5,D()%HB!LC'WAB^YPG6+$#`/U7<%5<2CVK*=#A@Y:^\8F#S4.4 +MG!%8KQM*M7LVJBG!<3H@N6HRZ[61:.285`I@0D]/S08#)_8Z]0G^;QY\T`6+ +M2%%4@?T2[.ZQ\I"]"61QF%1QMN2%1K'68/*1KXP%QZ!7\M-HC_519P_:Q^6Z +M"]7/F%S)K9C:EY`RURJ2/\<+S>7$3,]C*..UB%2+D"`R:JD_@, +M9J#57=,MP5/MQ(.TX\U)%9ZBC;TLE=3'Q__*RSB+" +MWT*`"#BC_?P*M*:IFLI/OH@P'$4$Y$\T[)/O(%\0\6-[4*J%T%-;OQ2W.`,_ +M:`,\_,]7]P)[]575C!3B"#<:)8LR?1LQD1@YC+!->^%?R7X'"TW=FV+NY_'? +M +M7%F*^OK.+"-)V>JY,@643.)F=8R**GB(3^\W@,DGL:C8;87T5SS'_U2"#HO/`.X5&);[-9.(V)]1&>NJ54Y4?UWYQ:";_:.%T7\KF*?"J +M+@@^%4TB&*SR:W)-T5#B304V11G%-QQ<><*RDS+'J/:FM1YOU\>`!U(4I9UM +MI5T7]150YJYL9(!,\^$J(D(PP9`P8!=GVWIL;E5`7Y<5)W03U1.6CX!&)WHT +M?8*[P5?[-,)YY,[?SQ59]BF$7MSF7E'6LJ1Z)]T>C:(Z6R]F+>]2_R5;ZS=C +MSQ"PO+A\52-A)M8RYJY:47QQ02+&(?K.DW0*^3)B%K!(N:T);!<5>,&\GRXP +M1]"'V!`%X3GWC>4P(D?D#$/U8OH5GZ_U".3 +MR*D6R&>`K)S&TWN11P[PS:3&@YI7HC[=8A_+7^='W=Y@I&FVUY)NU6X&-]U9 +MHS'L3P.S>N^\T'N2U"QOG`!)0S3J@&O/\+\L"C]-4'=G"T@)G>0#D1-9TFBQ +MP6-K1@2'RK,X(NQ^7O,`K6:VDE&>?`SMBN9!,'!N+R/@VM[9GJ50?9U$Z'$2((NJ7M%IRM(K13%=M@EW*0GU_>@!Z][,RR6+LC83"ME4GO/_D +M6/7QW]_]B(?=1_S:3.ZUDYCJ)._#H:Z$[53&FC^2'6@G0-00`Z>D@,?T`HS] +M&HFAX4+0;W0Y2]*BKJC[_%/BZ<8ASHD=ELG)S:54&C/`+8VDG>16X-Z9E;%; +M-:Z]H2]/V2Q[SSC,]-YS1PC((&=O'-O"B,\.^:GE%]=^4`8EF`HXM8$C"2:2-I&= +MWOWJ-'%?)8!96(N$=_9^]4.XE^S_KQ+!0!TEOM\C3GG+ +MRR+=Q;45L,+$6=Y#6\$54!;`NTDOMI>1I:+E=4G9)>Z4"Q`>-Y4(E#*YX-Z0 +M/$W4>296K'T/VYQM[[2"#W`&I`H[;.G.L'@(5[J@J +M&2'](:G14"\5!I96X:+ON&PC81K/)Y\IQ^``:VX2*E=RWY4+^;!W\"$:GKY8 +MOC`^W<+\#2?P'07L +M_F/W1N>>NO9!8)OP^5A<$/D\_9X2K^D43KF8_P@E7'6U6)E@(YZ_;8M1L%ZV +M:75`:*\4N8F8!4[*=G3+Q=.1`U`O+W>PM:M]"Q;K#?\_IXN&XOW*(4@D$ +M?DI1S_R2RA)8R@0OE-`AND6Q*64.\:PR1\VE34R.-;:;NJD=N`F6M[[(`_6[ +M@KX\H;J=A;Z.IGP-!8_BXD+[D0B[Z].G]T`=5:FP4;#,;:`:-:1@9"GP&"0R +MSCUHINYB((V,0,/(QZ37SW7]>)%;@]'[7>O8LWU[`M8^BJ5T!FM[1\-N_)^T=.@H5ENS\'<@4Q;J$*OB$L='#B(HQ&L$!R\S*4Z\\TNFO7=[X-F'<):47AN&_F13'D0)XG`!@G)"(A$YBK9<:KMD/ +MA^__4R+QF(3D:GHZ>]+S.5C_;D(?#-=Q02&YI.^MP1?7:4)K8V2V49S7EK^$ +MME%M$TRSU;"_^KS0ZF8)SZ:1BG<9^T()*S;X<6(B9[`E8MYK^[)7?KMN0$3GXY?7FOSWCPL^W69V/ZQ!Q +M_K:)_O-P9G!>8C.\2=:L'XA&C0]6_.N'Y(^*T?5J +MM+E,XH]JJO6+IMF8#3LP:G+11JEE'GBO91&SX?4*#8"%DE0K'PW$'HM4DT)Y +M2V*76Z2WMT:@?4Y2)%8>TF).NW4,F/GEO9V!5%_WGYTM^&I^6[FW;LYHF +M]*=^ROX=9YMQ80B4;2R[4J(6!=2-K07%8ZCTRX,Q*VT[F!T&`O +MW1BC5"?[FF':E5=`^:,^NIXXH9P^@S%_Z*2&T'38$5^X%` +MSERU/)$!7G/5:[Y\]>^&R-!5L)QU$//WNGJR@3:1Z%O(6H67S@KTZEF&,5M8 +MA3G.^B;P&RG8:!^P%T_#HW&/V$7YE&DX6^!U#KA5RQ&Q)D=E7=_]0ZG('-A7 +M%Q2B,*DR5?^?6:)6#62!YWR964M0:]@19K>66\I3Q +MAF3V\]G+'E_DT.G[8K1K[6+9>O/R?_(B9(D)[J>]/.JNRZA_PD06/>UMR)6^ +MRAM'YRX%A0Y:!+_INZV!8$S/[7@20G;O;]2DL']!R$D0[(DWJ,BXMC%DHC<7 +M3@W=)2KE0(7C_M'.L69J]X((;)'&C@E[;W8O(O9/UEBU,R\LR>&(D?CKW_FD +M#>`:^BD4DPC8PPDR[M530J_F]0^WMK^I*M;KPQ"Y56W4((&^-S_QMMZ&J0GM +M:?9R"B43S0$\(-RL>OTN^7R<[(ICV?):G)E:_7;>9TMFR^_OP-+2NVUGNBA] +M%!=L[R>0X[S-UQ*FCO:=TX=G[0"C?RB&R$:LEKG]\"BKD;B_3`&`L,=7LKUSQH%!^ +M5+'^A5_WG%Q;.&8*2SN"+]\EKU0QP+AIV#25E?E`>E_NQ9I8-A1X!92TX#S- +MM&0Y"%;`JUQ6-"<^JHUP3W=UE06D^"W7E@65D(@WJ-*>U^XVEQQFMOM+FIAC +M55OY['AEVI<4@TQ$5U]'6LU49A,?\QU_.N>IJ[L([)22VR@*8`AEW2]!&G+K +MQN(=='!Y1!;91O0;B)X&V&:_**O368I'(KG'UOAO"`-\"5#*+T)*_+,H3SU: +M$GQXD[(`*6(^QZ0HG-W%:MZ9+^$C!,5-5@"> +M1OI.;"/-A:`F#4T\<8_K]=I+QQ[[A)3)4^W&I1^8KRA3"S%_0Z&2>'4?,=LX +M*R)7%'["0D55B4CD5+0OO<+6`R&H%()V]`+BB:1=:^HSEEDB(P.S(!FRC[49 +MYM1".??6[7U\.%L$:2^_67D%E;O-G1H:C3^8YV.$W;&HLGMF/!%RTV?TU[,- +M:>**00NCEJ)W_P8M%QN-$';.I:/Z5I/JA:T_?8]+%?>7/("/]5:X_#D,;L?3 +MDTL9W0O@NCL#_:3+A/[^(&$6Z94I#L`YKZEICFYCJ<1K6YT^"4Z7W_P.TFEJ +MT7("SL>=A:9C']VZ5%P5NO'K\G%^/HNZ5%0PAWY"TJ.+GA/Z5TGA=#[Q3M'' +MX#N)=59+(41NTFG95^_?\M[)`^]1A_BP$U_/5G`%.T2/Q.S-AQ40+/#0^+NG +M)<<;S*10=F#;I!_C=M/.0AH_.SN3UJX-%=_I#R+)HHUC/O"'8:#GY_>+M?"RS/I"#;#$&F$S:.XYW@,T[.\2&_39!**HWR\-Y==RIH-+^(*`F*/ +M?)H6'8S71YQ1;DT<@_SB/TK+2O]-9@](')G.Z,(46(K6![ALM(9MZM>**:!T +M,;:O^X-_8C0+\6D?.'I1`KCYEYZD[R[,#=YLM`@!L-!W<_C2J#<2OBT('W7X +MRY-ABP77\+&Z[*>:?6"!\N08^-`7W[`,4DJR!R(][`Z3 +MMEX`E*P:/1X^1O&GK)XXA<3STA6WE33,*C3HY,[NL??[$+6SUQ'*5^Q\<(1P +M^QBRV?_O,4L["B^BBI;(Y[X05 +MJN1F$XZ*MIJ>]*K:C+Q&=30&OIU47W5Q0%3[IWX9JQNYS82=!T/>2OA$KG/( +M(GZ+.V=P1"HNQIN[9YC.IH7:;"M!68'JY9D.,M68^S2C3I][0>?R%`>M-SOI +MO@45#= +MCL"%NP@5C-H.?A&$U37AIKAP/'(\3D3^J5\X#!QM9R`NXE3N/GW*T1F8?=2Q +M/]+C`I2;AYT`%[@2-OA<2H!8D%_N]_R:(4+;MS,F`S&N[<\$,\7P7'U`T9XD +MY].\%)A"W/!C2HGGDL\D6EHY'Q;K9@/3-*ZQ69')<_#0?03:MAJ1^$%L\N7X%$9M?`LX&UE27NG;$<^! +M^F`,Q"5EE47V7R5")17\HCWW`=@-EGNTFDS>V:%#/!3NP2R()FN=T"O!YYH/A$1%:\-B9X.%O2AC)66BI6@DGMM=[1AY+\H_ +M1ZZ!'._\XVI7M`ZC?17B'W0=$+EGT4]OH%)-H*=B[F_:C[$AO4`T/Q'3$L^6 +MEO)JL8G%>D16DSLE5H-W-%N**!H>%,#ZRS\6*UK.W&)NH#">,9PTU<=31^/& +M79Z"-OFUY5V(V_"BO#)5)L;DE0T`A^#PY)/4U`?@KWCFAU='@NZ'>X<:=8>T +M#+G^J0.TLK!:S6\7!'*5RJR+-SW7PP$67$9/NNE=]QD#<5"G\XQI+GGI[:$3 +MFN#0JN?[R"T(,XY\`C.B1V4TK-0P0$S_AD76^K3P&X2$Q%Y^8W'B+K-*QUNT +M.>4U/R"W$-)P$0P%FBE_YW?\V?EU( +M\/EZM>I$_YT*FY`0QPF4Z@D@6WD*1]A +M-_Y_4'D>4H'F44-@,#R+M*D0$BLH"@7T[C[EXI4#$0X-\;&)LFMU"6QHI#MVPA@D5XH&5POIC$K#I7 +MU<(L-;-UDUACH5,`P#B:%*'H>B-;^PH7;43.BU_9Q/"G[L\[)Q>8%)Q`ZG;% +MC??84-`<<1OX`L +MFAA+Y'T@6R!I\A]K*]/U48G_S?&:CE23"[-S_/Y=K[@AD4&@/IZV>2_&^,P^ +M)(;(CC[9>PO0+1J7`S$#$LE1*YFS?8!`AE7Z[OWH;M:8,Z$K_*?JNJL.D86B +M?C$X!R%J1RZV]I9`0P3N17(1TA'M>JB/TF<`ZTPA0XB":QBG>TN995*JX$2E +MZ;RD5,L1MLZ+OD;610'T]5W[:A@I9\(?^O+5!'"A9B"9[&P(;J+HINZ)*7[4 +MPLG&H\'"=I'J+O0@5>R;:JR-/4#-./!GO\MN&.:CF,"R+@9U(-EM^C%_$A/_ +MPZFR.OPD<`Z4\G4N8M;!8LBEG1X:D]3EVI0F +MXO/7B/K +M2Z9[5%UU0&P_?IV9/A(8&V,L'U7V-II9 +M,)%"FZ`NU!,BJZF.!"]PP*-FPM<6Q,2[B40D"6/X?0LKL0E$0T0P1^E(=-1( +M^^$Y@6(M]+OOC)#1M-^(>[89RT==SC]]=P4`ZCG"+Z8>5W"BZ'>.S8Z3AS2Q +M)V]"\9L66Y"OX%T"NBZ@?5+^IZ$)`N.%4;A.3W(MAY$8R+CU05=E@-A.P0M- +M-N-8(K/R;S5ZLT2>:4\$.FQ^HO4I^L9PK5+:]D1SZ2&%-9TQS +M\@O,YW\D?VR"])KMK17_Q4X]8YVY'5REQ!M8F.3UR=JO`K3HR-[$PCD`->/P +MO?@CYE'_PQ;%4%1MHW3%-U'[PG8K,3:J@9!Z0B-^-%-(LXU.&U.,-I;/O[DM +M?:`0S@-UP5(BYN3)ZDLYA`?R!1(DW\?+!X2 +M#:*UXDDAW[XP]T[$Q$D_`^:^8M\>LR.;=?@D1\W/&VF9\_L.\+-EW.8M9_1H +M1CYL")K/6=[+FH$A-!6A'0<_B>;CDYY)\JYQ%_[L$R"P>D2)D8E5H;Z2*VK[ +MK8Q-Q?>C1OW0'PM=,R?C'*'P;'"N^']Z0$>4;KW)R8"UL7=0>C_>EQK54P/F +MT43=Q9DE6(XMVIK>4OZG]S-%`"4IE_I0Y\MFE"MK35Q`O;\$(3LVPN]8/+?= +MDN[C<%LE>UL<)B5PR;Y(BKY6#CZ$B?$NV!.,S+E[SRYMO>)UI`]#"C[K/]GX9*\(X&$F-%EJ`A/&DS +MM%X*N>51U4G#DZ"MH)]T=C\T%`+UA+)'L?5%XK/ +MR/(G<-AF/_"_''W17*)@(]:AK3&'V"G.W-_9?X^3!D'35O6M4C\F_H%=*DHU +M&WY4\E?]'M^4/P,BPIT/BZEZ6R)<1R*^]A.5B'%IT7JX.U@I5N53R02KF4+\ +M[.&Y6O8THB9:K=TV^P/M2_."/V>HTS8)^DBX0]8-LA@*I#HNFRNOQOTDCM^- +M:%,%UQ=O3?5"-ZC'BV-_I,8RF'0Y\Y8$XN*4TJMTE7B9O8:QN=\2*>55+NNZ +MT.)X)N"0I)RR8QNJERN%)P*W7ZZN%Z4*,S_7X#<.+Y6H;02F>=[V*#<`DX90 +M;RG$E*A.G7[V^J\OR4UJ*#_^WD=X!,)+LH/8Z-(PXTRA5^/<:J"LIB#DIRTB +MXA4>'-#@.YREG['LAA%=4WIWWFSE>.J%8]DW8#AHR5R"OR0;6!3`WY\\(9NA +M:,A#E`GZ]I?O1;L;HD,+]%/C0_QB6F/*,>8E:UB);(:_%ELYCV47\1Q\\-^> +M%P^7S#1_L_><8\#-:-]"'NINLP+H82#Q0ML^UBVS]'?WDWABTZD8V2?KIU+C +M\@*&%T(M4;<;M,/)4+[8XJK]K[U'\%^?A%$'E^@@+LW3'U0K`N.I.VHH+?"S +M=6)ZB*DJ>*N^UW0PAH87&*\C8'S^A\J`PS#S1[DN<"\%PK6A%U\!H^(MTN"] +M@T&"=E^%RRYL+[-Q3*:(2'.@U#Y?C$S#ATRR0K$&389\&O:1-%C#08:A +M:9-57ISI:PVI5+JX\\&O^"7XDM,H\#QSA-P^6#&V)F)?I>Y6IU.C;IE,;0#S#3 +M"G3?YNR@ZQJMCUV20N!L0PAJHF?DW7I,R$"WJUF6BDSE(`\K"HP"@5S.ORH= +M8S9HF`[1F\9`+Z%-4S"\;/@D2K>9OCF\Y,Z6*]&EUN0Y84L9+!9,=)MD8Q`6 +M*C2VT0_O<0)828ZWSOL:6N+L[OK70"O33&=RE$O=7,N>2XUK7!\WW$."S +MEYDQLQM;%*+.K@43PKFDC!*5JP!SVQBI7MNHSW35-C322$U3I-CO:O+ +MQ$=R6G6BQJ@DY)N]:.7+=_NQUFY'D.ES+VI9H3#:7ON:KH8_LN.NYJTP?K)Z +MIS1D00L)202IGUSCTCPQ13URFK;@VX#7GY:QPST0YL!`,@PTQJDX\XC;C&U@ +MJ^U>9V]L]M$$T(+",!;M0#!P!7Y_Q9_N>M-+#V_PC9?YS5,Y45JSOI,]-2L: +M-D+`:&?IA+W$!8?N!8MJ4D8TF0#L>ME3L4U +M\::Q^\RBQ6]IBDP/HAL<_VWT9V>$TE\HM4<6 +MB>YL)+":)/^K`75S<"<<2J(#!)2,5XL?''F?2=-ABK57D$^9N./1U22;5^/[ +M8MRQG?4B%XWD3XG.:XW2*X-7@2<2GT'A\UEQH5O-5L^YR59[RQ@ND7H,&+J1 +M@A58I1*H^MA5`8X]QVG<>4RU&:A[@"CM*?@$FO6+2D"Q0!3Y3O]$2BXZDO4O +MZ8J^,AB/&.%UY+F]UM)CJ"V-$M&B4LU(?.M"DEW/R54?<%2664"R1Q2O5\HW0:G\.,3%BE*%S0[*"V +M(QU5OD,"L(GQA&EK_97E3[+T:P<@=MNZU<-N&5/:H_V5\1_J_%`G''EZA7+% +MGR+U:X@58O3JC#-OQ!CK0"P$2OI7],1NP$U;9YC"%3U-9NUGAW@0OH,?5-#A_Q@SV]0T*0`*+5(0G]#V,G +M2(IUT9KW`89ZWJB]"\/H[6):H]4,.+6BG_B4P0D0*8_-Q`ESX6?:.[.L]64O +M!N+2)@H8T'1UY`WJP*4J@Q@D:Z]0P:DHZ@IX!975<[C]P@^_E**T7[^"\+#5 +MDA8":(F0\C642!@/[LESK*Z&STD$\@2LYB1$C!O48UEVV\$@]VI?O@-;$/;8\42#PZ-`RH`2%"G6>F('`8'(8V&_&:T(_K#>[I9O8RLU?%4S6AV12:UPV_=4UZ*!J +MPYG<7Q_0,->(0,N-'BWN'O3H@P;T-LSM3Z)(@B8PQ25$A'CFM+'Q+&N/+>;\ +M<(Y>]ZR[#N3;$0:C\SF`?WB'A_I:5N0PBY%=(.3H9B%/,31)AZP+>44"P@9E +MH^4R(B."_%UF4_U9OX?/'#[SL-_$`:_R`3*]3'O?0K$68O*].H=!+:^(2"Y/(E>2_Y1J'G +MCE-.:J+=<"7`W:3W5R4^,$8QKXVL/"_ET)PZ'@0SA!O9R%_R5`98.QF]XLFM +M6?0O6ES@(>NSNW6$ET#W[#QM]&VU5*,&L7?Y3WBATO\LX&5?-&!0T[& +MZYWQZMUFE6X0*9'=#ZEMI#;[@,C3`\G"N\;D3;!$5:`E^LWBW7'9H'#QS4"> +M+J=O6&*EJ&0%3<BF?MX%33D@8:K>,19?DB'(GN,V/O@ +MY4BNKT:9RM&8,[C<(;&9IS2/ZQ-)5AJL.$'84[WD_1U_M-@,F02\D?0O#R(M +MW&KT#I&:*(<0YK!;A/>5K\688VVE_R7]U0$2PB^*5"VFIR#>;)I%0N?]PJ,0 +M))`2J=__CL%T@\2`]LAR:KL."2TQR)2+[28M#6KV1;2+[RT><`Y#Y1%[8JBV +MWAV$8&](VEQE^CE1]P"#@&C1T9./B=L[14G;T'[1+!YXT-R$ +M$9K,LZAQ49UZS@<#K24)RG`.8?7I.J9%0OXL19!^MY#[?/^+8?C&JR#Y"=G( +M)!KU_4*."=4>S.^2F)TB!$6'!]<+4L.:;E=0=\<]\V;G2(GSY"$D56-`TT +MV#TT7<777*@\,:P+!S;2RQ/]57(@3`)2$4HOV[OAN><`]J]YQ^5-WP>S#+Q,#S@?$N_HGS^5O]_D"F>(O9BOX<)$E-'TI" +M_'&OHC;\Y:]F?+9[9,A\XCA?LSMKEZ]\%6X@"=M]D;\2KW,V'GDL!%7+6Y2& +MR5.9>^2>$#?>%03?!S^QK):1RWM0`^>Y%BW*[8_B[G!4U_1C.>UPQ&J:^KYY +MQ?TTD>8&>Y?I1PS<5KFJ3>].MWOMP\HIP&>Q?BEA6+Q"X/.':8E.OMY-LFG:T?(UJT>4 +MW@LC9,>`?[5S-5L[*Y\:?EMQ@)I&3>MOT^]G*S9E1;<],+A9$-W"PU' +MP(8-F!(5BO=T)@-GA,8:T8_L%I_!/>AX8K[7;*;81VPO"`-KDK-`G+'LFLOX +M)++&:^WN17SGCU]2,VO8\ZD\Y1R7I?0LRI>"(@YPFZ`2=8_B[KP_,&@X/9HL +M*+GGCQ2TW0TU<*,-;*V294,G;7*2Z5U8B?<$.UF8F@VUC5ND@5NY&"'"'.:( +M`O\H_)_27V86H'+_'1?>,+XE*^EF(-?UHL4DPL4!;MLV?`8K$NW0Q_0I9:U3 +M!NE&U;/G$7VTFQ74"*F:@X#<5=HA]^A:61FM,8HLD>,40'2!!<2X4IP+3EG& +M,G^K/7$-;)W=0.;#VOA::MYEHT!+@4F8SZ6C1N+D=9SF+(F+%RY.+(N)PL,; +M,ULB[N`"')`7E:FPP!I_WLARO1[PCLR_/$#ZA+5,X&/`9(=+'R@MZW/ +M6B+W9I3NW/E)6QLI*F.T')YJ\(;7/Y))9+)$G/1?FZ+57M"EIR@+%I%E@"%K +MIG",'/"5L5H]/+1BQ1"Y5V^FC?K@FCL&!&>Y#'9UV*UMDIP[=L$5\[XR7M,:&#HW2>2.][N#/&_>.(98YX6EI(6?D*SHTS3^M +MRR>/U);+`=E7\'BEA('H/DPP.MK[7@[*\^G%DG;?X0N\XWPA%]_KZY-=D2Q: +M^`>+A$I$T\B`.RH:Z$J_+L8)U*\N]G5E3!;V_U!\;E/@K;@_1M,*P:?6E#-X +M',6KMY?QQX6`SB$\'%<*^SI=WK`WAZ(YBL,]AY`.DCGKQWN1BP1>W!DMLE55 +M5:1ADE5+\$XP-CN+G3>YK1HT>4!!RK0$]QV>F%#ER?F1!)Z5S=:'?O)"K%WM +MFE6*#2")$R,-@#\P[T-:=.S1!)),9FB3-A@%.^=0;K5KL43A4`S\>VJYUP%J +MYL5]I:IK^O7XT^@[*^CR,=I>>>DD#5B2SIX/P?65'S1^(0B(D=.B(A@'*7^G +M!KYH0(]FINN@[$B\L?"GT$W0P]/OP6B?,VUX=8YR0(JZXQQ=\8T-$J=?+@]. +M('VZ4UQH9K"C+3V*XI@QE[L#?K^L6;&RL*TVF?[-I-+^R'TDK8T&L:1^G:UQ +M9%0HY5<]X\^!)ZN97NNH[[DR12FCK=>_).O3?!Y1>*"Z)(RM(((.V(C1',4] +M^]=X@J>D5D:=Z6KG1XL0\$JY[G;%^:^J18C#O1FHV5#?)?V@ARET*/.YKGPU +MND2Y64ANR/2+_,&COJKIHK\Q4SC6U`#I8L"?&=(OS)6I?718V0]"6;/X0#EV +M(+M@B9-:&70OS8RRRTV42N%I=^.Q8HD)_=`C53>;%1;_LVV`PKKCKHM/_6% +M(-#:=_\CL3B6RXF>B,"XCF1ZYBXN*WG66J4)T!%9LXQ<"UY:9PJO%:P8K.U% +M>!I9YWD/%<[_JZ088$9"(J:HICA9R\?+W=+#`^%`=R12"@QY'B&J:,%Z+U.4 +MLOMX"]RE?1.-WI.\V8`MJ[8BE<@SMI[]TL5X[2.`OGC`![&'A-6'1AK&IQ$F +MO8],B\QN+6S=(``J,%#0/[SLHGI23^IP2;=4JTW7>"\L95USR%#>?,BHJ.Y( +M:L:LI8?4ID-^"Z-`4OW@5G7M43`=U=D(8:%*NTC!&(K5%A.K<]/OA]U(!#O, +M*Q95_S&H987P3YQC^K&"^")Q>TF\7'OFX*'B#YS@SFD7KFVGT8&;-8&=F]'H +M;#[MAX,T]VU#>]HZ;OXP^;\I3?Q!_P9"@F]I:$](+8GUB"O2?XTV\Q-H^=D$ +M;LQQ\VX>/H<]J7).'5HV()LCE7F7T)\/%P).3[0!BH@;8K'I5CN7O@IY((<< +MX,A!S.@HKH[WO-D!&*Y#B[TE&8CIIT1=Z%%A>4?!1(+)FP^K3`G.'Z6GJFRM%,5*W8K-.!Z@3VZ`Z@ +ME_L<$?L`>2+V\LN8J/`'DIQ""8=?E5SO8QN())[GIP;7#-_@=K&L='C05CN/ +MW23,)ML=P90NA#*63F;,-C+*Q$@6SG_I\^HL7)3-K0.[2/1#CA02MX@'\+'' +MD*4W=.PS(:ST +M3<2!QH-\"YAV4^/MEOZWW4EP2N+&<_J\$2D'QS/GW0%WY1=5?8VH3?=<7 +MS4LC4F9YXLPN$&%D=`^?KDW7W*Q?!V=31@9SBN?`CT6WB,++W-,; +M/G`:1(##>6\C&A_)*2X,+;"2-QOWRNT:$$!+Y +MV6O])=W<+#S<2;<+<2)D#)%BYBG:2P$'*6T%FOUV[X+/KM,++(CML\]YS-*C +M<77SR[/8FNBU8)=4`9"J"DUAB%2$_:YE%55!5QVTI\T7UXX_9=$Q;--/K/L#JX.L,VN&3>%^E%JO0!*Q04"`F#LO%1LZ5-[\P!%_2IG?4'&)V(ST>T] +MG]9$8!3_:.,/]0!.$!6<[F$"1:PU>"NV(IKQB$M!6\>V-1=((H76#O,%4W"< +M;WUCI%MAVP.+E^_+T2)U)BVR@5$ +ML@):?1]06X-0A=Y7\(FIRR[NH^Y;4OD8G".>B?1#:J=35DEINUK\RE?XA6\Q`+D60O3GV*M*>4&F% +M"U_RE\'6,'6=%L=I-"@)J=VF4+GL`/;H-O7I]R5J',5W!RF`T97U"MMG>X83 +MB$W>BE=1EJ0]O3.49`\\QYO;/H-*->V3:!"-K3BOIKI444M144C(<20)H4JQ +M+(F9G/"4MD##F`=01H4]Z_PA^EWPD9M +M10VIAQZU*(#44PDQ;Y-"#<[J:/JQJBAX&(2#!4Y7VIKW0>W.P6N/)2&/<2S] +M00?-UMI>=VL?D[=7CM-UERTE;Y[4!3PW.\`_#J6V#2ER->$*+1#?+(72Q^ST +M,9QG)?*9B9"L=-;-B(;40=D358+?GR+T)5F'9:NRB92E:SE$("ACD*P/UZ#& +MNE,*D3#?8?]D44G9="!W':$^2-_9+Q"\^K3&V\L/Y")\>FDIW13?R?A6[G!E +MYI>I^YH2RYS'/\^Q8B8\R#:NQW[)A/:E7\9^96,S_-C8S/9U$Y% +M.`C(.*K?^V^JAZW-$OM:.#`IY^`=?ZV]VG`Z&?]RP/#SH:SW]*?_0=D_F)3* +M[8;G$LG,H]24N<%K1@E45>"3KW7UD%NUE^Z`5:RN7\;8L[$)>$IY%<)E^,HJ +M3-'\XW*7H#1SI%GU!P&2UT7K.9:5_IHICHA1-L(2>/MOVZ1*Y#69Y-2:'L?Z!59@;LK](UGF5U53KW%_%29X47E*KG +MA@J-JJ6/(%:9"%EV@$.<96HT)"=D&,[#.(+"BIDQB>E:7+<0KG!-_0.$6`Z/ +M]!GK8H]OURNFWU%[,`@4FV_JW2V9.]]I-IHCHF4Z$WAK&-9O71_*IA;;++W2 +M-!$A/)TA_W$NKCTM?+)@//XYR/VPX51T699)C_#9'1%>H_8S#]`Q,)!NGI;2 +MI35"V8`&E^%BP +MP_VJ5-48)G]DBO'B[-8%@3)@Q]2K9%4QJ"/,.++#R?RP\,!MT%H*%P)3+3M) +M&%XB^M2ZB?HG"YXQG2F:H8N38"O7`;78@WAQ!H3S-,*(IGB[_+_HTG]D=P[@ +MURDI^2VD5^$#LSX:RM*_`O):'NIT6`J),RZ/46`!>K>:?TL_4I`6&WTQ"XAC +M#'/M&_5Y#R.*V4(8C0.4WKIA4::VD=BC99M(+X?7XER4':$I^+*Y=Q`;]%E@^FS5XZ&6: +M)Y_8I?(:#%C)S7@SWWQ.H7"(Y+R[1Q1!%(,.<8T22IJKG.(1=L[DJ?*KIX5K +MCN]Q:S%/NCA"E]*;53QNKE.A`P#?3X#9PS:I@JFQ/POHZ%0+E("31"D6TOK8 +MWXUII;\O$/3?F'K0-C5@CB;(26:'1:0UI.JO&;L7X!S^:G?J:N,+`*F9WON@ +M6BTXGN^J%7.P8*D";J\N5H*QW:_P*4*K_&XF.UR-3 +M$CNO?V%\OU57M74S%G156DIC%PT#C(RQ]DN^K09/=DA[1$J1_S +MXM,@$0'147!GPV)F336#3L.?Z@L3%F92]14*PE7?*U5WTKGSMD`^2I6KRSCS +M@U/0ZKY]"ZDVWWV'/?"R1I+XLJNG@Z,F +MR)*/07TK;]2/W25&>I]%,4TC2PKC2:/NW27OF74S),OW8%.%$K#\Z&J.@4D) +M=8?8*K6U204I#.[%<`.F@P2::F:N43&=NCD48(OOCNJ/'M7<0,29.6`\H,OK +M0F%JSB,;O<'JMKT\@=@"V%()8U\`_D7:[WZPS"-(6=&6;VTB)GWE%3X@^W*4 +M:?)L]3-@1_@5W':+3WB%((YF#\(WHJ:QF*WGIU85%#]*`65EL#VHUNVWI!/PG'>==>\G?J4E? +MU8%/R?J,-3.LRL9V/K/@HQ`]\HSP!D+:JIK!=;(CQS'U_/CXI^&M,DVR;"A) +MC-+;7__Y#GF?H#$(WZ2V7:;@'/I&NE,?DQ,*]'K@+FSL&CYY#W"R)VBX+8%N +M7O>*#&TW"@@V``N/4E4@&OOCRF'JZSXCL0R$(.DA*W%ORR!!ODJ1$27TCV,. +M_?0:]A6]YDWC0!H5EGC\&$C"Y*Z^_;$<7&'GW-\?:M?/QI?#!^Z7$HKP!9/X +M]&WU>N^VB?P*B!+W:/.'\]_2>A9'?MM4PE(QG.[GM_!KK@S0I\[I*!9W=7Q6 +MFX$FW&$MM*5@L^]`H:P/-*\N*D?@ELW@Q'MD%J?%ZS=Q?3G,-"[[++)"+N;L +M'O`F\T$WI\;Y,F%-DCPKR,$>?*@9"H<1T(TX9GUIR%&+LP&!X98,B((H@(Z. +M*#9T/B:-1P[Q\]*P8&TG;S\E[4OPMWMU;];U@<%%U_Y-705,[MHEZ-;,%G_, +M4H`9%L]"CB@_J,844.P_2+:'MDK1I2N'X#DMYQU!/)?*+FP.AZ:).9=52E:O +MF.(9_9*!L7"5/1,V:M:.I +M$G-&(;R_PM?F<]'3Q\9UU1@<4Q?K+7O*6NZE55`U;QV@Y^5L3&YFU"%D7*HS +M#NP6'>4:T==MBU`$\OGVB8M-449\BW^A!!A$CV0)Q,-5!O!),YJ_KHV*VWI) +M+]^9["?^)<13RX%?97P&'RUKS^?<3L#PY2]AO`/1&M_4V\MI$T*=3K:@#E>C +M;9M0"Y`4\79K0J>Q%OE^4AD9]5$:[35;J!L&^9E,!W'I]@[EXA%7.ROA)*CE +M%QQ!S.I/1`;V3NZ0)C]L9HVD-ZIJ_$'?8IQA0<.07ZK;"=U+-J5;C^+/OCSF1^NU>!;1_=XZM'P2QGVWT +M;W1G:(V!C&J]8 +M`WBIY*UG;?BHYV4=LB&T6?'8@T3_Q!8LT+U;^[HF"2V&9UKLY>U(..+X,H5\ +M0#>!@!W?NDW8NDNMS2KR[F-H!FIA@>.N9UB]`>-@0UYV#DE\Q91#XZAV73_M +M_Y!/;.[-!J\W\MC4F2MIV1>;/W@"8=*UC7FT +M`"JY/S@MXPF^ON(W]Q<+!0SE`=FVF\>:J>DO"T<>J(NINOU]I'BQL#2OF.E+ +M![1;-"9_H"?\V=^G&8_+#>*CX%7>N0_/J\7\B5KETC>.-D%X8RY.L&G\-21! +M-?ZNV:)7O"5D+18_DR92`,9ZR%+`0\?Q?*\>%-DQ.W;I\++XV]`1?73ITJZJ +MP%+*K!U3YSNP7FH4)5N?CP7:K^VK+8S,GRO^C[T=(0$H')*WWT/YH)4BGVZ& +MWIN`^]T=#;#'.9%[<%.ZXUY)2&><5[D8PN\JZATVX#CD(;D5RJ+PCE4ABG3; +MLW<:._TY33P-.!B5WE;*9K`2K6=#O1;5^F/BO?[']LO\3MNU/<>:&ZPOA\K"]H20MKJ7OBLY10?3%O&JPE*B%^.AY +M[F%YYU,6E[S<;$G3+X.(6T$HIMJ`)TQIV4"<+'CPMXKB1S-E:,]W:3ZI/ZJ# +MTOW,%@'?Z@ULT@=AL/FPMC*LTXF)ER2IT9)(LG98@%6.&%G6PZRC20A+''6Z +MX0<\*!5]+B\S\'/SG`'2"Y+=X'?%<;"5B7R?GW-,P%>0#N_5];ZF;02%$!A"1$67.HV,"PN#8?I*)O3`2 +MK!#LA`3D!H?[8>23-VO@MS.CYBW1G4EL;64B2OV$]K].%?+EKMWF_J/W^"=& +M^WR8UI8R=AN[?1I\N.IQ3VWH9?N.Y49I:./&`F/QXE\P@_R5P"<[_)VF=U-] +MJ6`SIK4TW$T\@\6&KIM#(%*?!0SJ66+T,1:#Q6GY1/\6.5@'KA5M`/A.VTRK\(1C7[R+K*Z^YE$S+B_7F +M,HJ]ZYACM#3**&73;U$*]3*RL?OQ#[5H)(6Y.K'*:PO4C#8)=HK,0@Z`E@`S +M,;LI5F47KEMJ*-_,T]I3'(,0UOO,/H`7H=V%6>^HN&`T'3IM'?KKT44H,C,G +M[0Y:OZLO\-_0_UI:&$O;P99X.MTEX]%HW*`!:UZ4T/N=9&Y?@TD?.6%M6D.[ +M&6Z/B$)Q7-H+^,H%9+/;]!3(C?>KL3])G<89+7LJV'Y+[.@U[,9ID$/SK_:QG).P#-FLAF&\0X,%5\ +M3/:%_?&5Q*_O#8?EPZ,$R +M!!;W4@EN`.^;S:!QB4^47T>ULJK5`W!RVP7]:EQFK +MYMBLA!D16BI2;$PD\>@*?QPQ$`!/>\WEWIPT0FE.?U__`N,F`4S*\/,4\P:: +MN7DB^-;VS1XYTY*GT[[RCK4F!NI6@RX1]P>J7ID(%1^M#9\VRW+Q;":(^B7I +M7F*SUP&I(+&J71V#,/F0#U!Q234"4(VJTN>L;89,A<2D61W]DIWSVGSW![<# +M1(IZ(D/^%!<$:ER9MPWZ=K\:K!ANE=6`K_&OLA?@RH'GR2$,<0D%.VB*$6HK2"[/ +MOX.VVLLIOW\1,Y__4JQQ42O71\UZH\XV>X6^P/K\O33;W/#+F4#-4@L]P$D! +MW]P")>A$#!\8/O%.*/`CK4)*5`="=2JW"@SDIVN-]:Y'FP0?U$&>M++"#\`4 +M,Z7NSLNCW^)V5(X0JYK4>""*W3A+R'O\RKQ+<,NXQ.#-N*?MAM&0'XI-C/]_ +M'-&Z290]=J$I$LGJJ2Q.P?*@KZ@@8M14ME222$2.U`V*T6\=\_C(3'N+1.4' +MK>A_TE5PJ9UN#LH:'GABK&3QK^`HO';A]S>=1.7YYB&A0)G(3]`QGD/C6WDQ +M5K]D+#&.ZH+`&Z>9[Y8UZ!CYF.H(WA4:D,;*_M$C28<)`HJITK%*T'[$9S43 +M'L:$^?U1RO0W2!J)=]*W!LN)NT_)'W'P>ZUJP_&WT$2'.QZ<7?#E]Q.C#3:) +M!PSJM?K0Y]0$L>)^T1G^'0*D09'&C`M%NK>=`<4D8J(!V.*6$I)RA-W1H%,D +M@K'1T[@0T:.H]'0RU-5\X$T[UK`R_/Z#'Z.J:EVS:)+B$\@R]:A:IV"_'4`U +MSM^\<\N'2`VB36?+NL$G),'A,(^ +M]=N0Q\./$OHC<:Y.V\[F8P8J9@`_+J74%5'+%?H_XJH8_`M,4IC^(TZU?U(, +MD8>ZAESK>C*SA[%=JIE.=@X1J&-!?PVJ^Z!KJ%)'^:JW9;8H%2MB$%^$V+X? +M'6P(.TR.&9^[!2VV!U@$[(D//NU/NCV,)D'`ETV6N\;[=^$Y`@PO6#>E);>: +MQ(`B=2OM/73JQH"X_9STM^Q+@&+V&!4H+RSV0TB43$"&J&N;8G`+Z7YH_PK! +M\.X_"WEPU,Y;S*FM#W(R:06KWA'_2]&^[80Q2&@97H@6\2M8JX!ET:2I[_+) +M%^V-`K$-+E=T1D:@$XCB-"P+'2<;;,`%Z<2[6,"JPE%[0'G4-YC: +MU4=NDP;WW`#:IF?TNWXJ*-LNQT:&]02MN;FY\;LA)VDV0>&W$#.2*3[-B$7. +M,Z`GHN)ZJ@VU!T0:T<,SKSR7D^^/JZ`EA,Y5KG8#P]O%B"SO'5@'*A +M:_GPXA/:6^3/RI62]G'N.(;CJ5DZ#V2M]_0T!_CWM/U'V4,33YG##*31W89R +MG6%@_D\Y+H$AK3;G=8B*^GUO'!:+@`Q!I#S:]JC:JFGYZW'^=->&X,SHG@&J +MX$M;\11OQ)FL,M)'BTKW?R*!&/QU#0QKU[8JI_`#^@;ER\/R48]67BS7Y6O@ +MD8;;&I!UDS_JDXM(/9'WI-^ +MC*CIHVQ`KE"0N8I8`\((=9PQO%E*P0'>@U"#][?*+1:U&I?!`WRB#VR$J\** +MZER)GI6=&ZU')_U?BB3$0I'-?28WS-\XI@G>:`SXGVN"-Y>A*CMF!UPT'LI8 +MT5TM")Y%^U0RVCE],]2O+B`4IMP.`561T52P--3M"IL:+'5E_DKF'D#(U@*E +M"U](2:@`GR#-``[L7!W?`[JFV>T0P6[:>6RH]K,'PC"D#O5L[SC*21TI +MGF&R/CI4$_#-]_%SQF2.8\L1#%0?$FWQNNH8O4@/2?`Y0\8?;J*ZL0)1OVYL +M1#*V9+^CE%Z'7:83.*'&^5-[%%7U\-A6@UJSO^L00C)!:>/,/C)?F57AS>EV +MMO0ME-2@:O8+CMP.WV.LY4S-%T3IUB,2ZB'[ME2>B&]XAYS-TS`QZV84(`0Q +MBK5V5BFQ.CAB>X,@%*<56[7S&2O2W)<&A,A3)WS]-Y)-C'ZB&]E*[F0U)4\- +M18!(OU63_^O*SI]3N$%1O,%KG`1M4(6TU36=!69U,LH\]6I468]R4ZAX/QWJ +MCCG")/BSSXR7`X]1!3(_?C8;'AWE+XV:^@-[9E:2] +M@=O*LX8R9@J2_$7LASH\4Z#U7HNS"PN8[I%3CP%&!6[QKH9+UYG*..A3SA'M;)(AM<@%TI!"O% +M;S1UA<%H4LJ-/'(ZV@5^)7->$#H3!Q:5B3A=RN,X+=R5^WX^E7/8Q>#OHFJS +M8KG)=H)JDI[KJX2IM17L&-\A[RDYE8=/E!P?211F1/AH87!FBJ]A7ETO?*;[ +M%0FB>A7_6?;;#?;K_1W,\)3%(.R&(DV$)VD@'+3/A]DNGT:Z-!=P&\=.FH+K +MPAJ%,K"HE49F_L>KYAN?*ZDNT"5X@%.MA+!?OE0Q;L)4CRTL$!E/8E#_9HTK +M1&\[2`3':DL6R#WB_*2(/J7]Q3688]8OA&UR47,3E +M?@M<*@EQ`RH_%!#)9=D3?9X4>?:]_QA$_&TT/&HM'?4MX.SW(WP14QOWWW36 +M5]8;S&&2BJG\8"SZ#!6WL,"MK6D?L'ZJS$+`CG%6,88FYKI`NU/>BL<@1@M? +M.Z%W8K]`O@NLD%S&PTL%3P/0GNB\BDDEN;)5E?TL@A%,Z@R&'G",`=2T@GHK +MZ<'2UKD]']VSS\_G#-W18[;EES)LG`_^U`F$K!<4/'?*FOPZ@E_LQOKNW=V# +M^G(RTXR@W/6=P7Z!]PDRA17F\&DE& +M#'(]2`J"3I8O(9KRSM?66HOETP!154"_"GD#0KK6#M-M+(:M!)WQSHF`*U/X +M))?+6IS0?AH%9G?D7!:T79:LK<^KTQ^YSJ];;Y:_U=LSZ5_@#3#@(O'R5]\A +M:$K?4U:;:GU3R-LL?.8/`TF*X6\NZUR,FH9ZI<$;A9!X%_6EF1M+=&EC[_'6SI*P-8UJ?"*J9ME,6^B3,S$R&DNV=T +MW0]@A:ONO40BG-G:U_7M@?+O*"@"V.E$RE\0TJA*'E5E0CE=QV^M8!-X9"_; +M@4J;U--"8J9LI9>$I7"]@O0G%AEO,Z?8>T"-C\*4*B=N5#'G[@)FXL1TFB1< +M#T9[9:+^IRF&R6NM?$P4.4"OO_'O,=$9Z4V`5G2_<.V?"L92U0`F:QM:?7FP +M!^'%/'M.X9E3M/*N:BU"A^B.:NRQ_8\0.:AD-^!RAW+@&AB^:OA9WX]/[OQ] +MF&23]\Z'Y@&.0W??#OEYE91),-7H*%7+;[#I)5@#;;#\,&>3$\X#-VQ9GKV4@+9O0%1JE-2+9N +M(ZKE7JPIN3^3\4:J[D(HQ"COA;&MXE7*!]3+["5^IY-]X]TNZ*Y-]+O*\`,%$Q#LLTSA(*2!^RS*^I@#7M@ +MS>!4"1T$9+`G%HA[KM7:K6>AK47L2[7MPX2(30V=KNR3Z$,F4>B?;+6D&LBW +MF3P%$GL\0+.:I2F.X>=CTCF3"=CZ+J>@`7-;\`/4?&[YM.J'1M^OYODG'(&! +MCQF85J?5HVH$@],(HDL8L+1#N<$2*HT7)[LCIP@.VR[O('7'^SI0;%Z3B"8$ +MI@T"U%_0#LGTL2,^466X0TT)ZSWI7*2"YL/H/\=B,,O>^A?'[<*A9.X>.B0+=(#@V'(E?F*L=`O:H.&K% +M"4=(].#;'5A-ORQ>0`A.GM!"?Y%02P,$,P,!`&,`C+`.10````!J*@``K7(` +M``0`"P!.15=3`9D'``(`044#"``Y+PUL0H:'H6%+_WK5A(0@'S.R`@BTB^H! +ME=_0_2$!MWR*L_4FZSM/-"& +MN@)49@\G=4 +M2FS3?77_M/D86Q$@5KG7MM&CX-"Q!N@PY*-H&U&_8&B*-0GDYULR;06R/7F$ +M]_=T.\K-?"ZZM75UK`Z +M<5)"\%S:MJXW'Z5OHSVHZA"-1/$13RDD[[<1634#-]^V[U4EK^P(,SR?/#GZ +M"0C3T;$9UV5D9"UU"SY_]2S:5,^+U)Y1F[-`A?+&\D726&`4U';G"X=$X\3)A%U5+8"F3?,J9]>0#*I=9EP(8K-"=H9CB +M#V'/D.3NB0LGK%H-LJX-Z[^GG#ENG/@8K>1O +MXJN#XEX')D'P/O3Y9],EE4`GX_&F3O*'X$L=)96J5$;0EI=BQLEE8^;)"H5Q +M3&-425D$_<=ZS1Z#/]O6J6.G_>XB%<:=ES?\T[#Y!^>L*"N0IJ<;JK69ZLN-&R-0BLA(FQ/S#;7*77+&>.J@$4E6UB6_MK +M[L:")0`HD[G44%KV1)H8EC-DMV@J601;V#D#Q.X<)7HXBP]#%N!K62O&)>9' +M,)@P0X9G3T_@1U%UJ`&B2$@OJ;B<-?T5`)#1?[JRR$VEB0Y-WO\>;TZJ\.\$ +M[`*`JP#$NTX=_4R@0U,EOQ6RSMXV@\LH;9AEN:6:]&T+ +MR!2,#:-3:VCO6*=.P^W& +M1L-6I7Z<<=K%CUZ#5[$S,>/3Q.Y2&%?9!M +M(/#?:_*T<[R/.6=R>\P#?QH +MR+6['-"L/IQN4]HY7@[$&36B'"M:CQO]9?=D7T)!%;#&9<;4@!EQS7K7;RD_ +M'Y*+WD=H=TG=[([YNG\H,A5V)EQBI$\K +M>6:F)43@*D_[]2P8:`2B;S05`";T_1]^E('7-]##NU8C.WAV7ZE.UIF7OF=$ +M$-0`)_X^&!3-%T03BR60[\%\(.AE=6%\#6UWE*A_D*0]SY71$E0GHY?IQ@0-7TN/OR!65V +MOG=0H#1MXL'/Z.B@T>L9U@SQO*5[T488=I,ACIE;:VR:+F`9[+_Q("8"GECA +M3P$VH9I+%HZ>F4/G$^YK%&'(VDQZZ"]#^*^73EAIVJY@[.T7C-/\MM=0I=:] +M_44%^$TJ22E=$GM7 +M!B[6W+6-7"^LY>N^2`D2`%9&T6;NSL@J8=4P17.'V$4/M!IW`X4]5N_,U39N +MW>%E`N?3KR*Q>8FDW$AD*K8"(46_M@CY%A\W?8MFX;S%0W*1AM0B +M_^2J$?0=2?H;;7\Q&':7$36O?R4`"T,6$L+=(3J04_)P?TEHM1@FZ/+O/`BJ +M-2NK4-V,*/7)#6H/F\BSHP4J3X +MH$J3P]-K2'\J_&2\"7'!.1WIFT9-%S3>;X'4V*IN;'*8]F%?9@]HL!,.7]"/ +MF`KMAS!Q[?T&RP\/L32S8S+HA8>VS5*GG,PLK!VP.O:C$)LO:V#5.L7_CK*E +MM+\*OSIQA"92VM)-L]2*OB[M0`%/+F917*`0H#+TTLQQAWJNE4HL7WD[[49% +MB=Y\;73M%7SMY"\51%>R5CW$\%86^*LX36#,JVM.ARU$QHYE%\"8'K8@N7T> +M5&G'O&5%6)DALL_S8N1&#%+C\,>Z=-'YW(0(.U81.6O@*OQ.[.`N_=-]==4H +MU^08!IISTRV8I#=`F,H=*2XV8(+C@<"X\"7'"XGWM[54UV2TW_J3\LC`K +M^X5`^))X)EEB,)OT.-XEU6Q!A,&/[4CQD9_4<.?U94FE0?SNY/TN+O$/Z]-' +M*K3L39ORTOQ>8MO-YI=SGARE6R]N#O0>&?%`Y0>QDG`O +M8F4.$EI9I!-=Z-1Y)EL.V"4[31HPDC70MO`*W.[A(C@;J&GCUOS/2=TT+N^C +MP*OY;OO%+SL!5H2%H(XV<$83%DA_V\AU,':\UUF.8--PZL^`5<)\GFU5T#I* +MYD#;>BA8X?L';^W6^F1%"HL+$@DS)27W*OO*\W"D<,V84.).!!U;#[Z48V_P +M666#F(QDAXN+!*R39!5;G2T4=BP'>115^@F$F'B9Q\(G.^&5.+AK +M0V!@.Q)Y&ETUCD,Z@U^&6]`USDIK9BLTM!QB680IYI;\,7Y,06VW>#E,?%2I +M&L)FQ4(^L63W*;(^6LSZYCG#`54ZC.3KX$_'M;2":AC[J/O1U"!4,=%*P=GE +M%X`OH,_1\_.\O473"BO?`\[@H&";R>E1-5MFE@<^G]II5UF90=O!R&8C(>OR +MSO:2NF*4U12[9:Y-%A7F>)@#O[EOT0]#2BK'1X=E>'\9PFHD$_I_8=NGU:EW-)6,B +M2--'A\YJV0C"`!S.2'@K1D@8W8UD[<_ +M!4W81HB?)C`%,+AE5G_O\2G*%\DOHH331!F?9F/-"='O=S$\NWM)-6 +MW$OG[Q2&@9+#)TBXX'V]WG@C(G&6G'-O)H2NJ"_=P]E8C8 +M\A*7,,33MT;_?NI"I6!$S-?%R@PQ53''M'C2#&L,\32HV(X^U=R#NMX>J6>) +M?Z%U8?)?I0_Q*)^:N[7O?)+_C@X-/6,29+!ZV',6W/"J_L+B[WVDD[5-(U06I2 +MIMB1QS6`TLP&#D27:[^82+M/OSFA%P(,@W'1TR\G;^=>"DA1_AHS'.3 +M2TI:"G"*8G5&NC8NVS+8Y]\]X:D9VMRJN\G +M`62:>RH0"`2Y9ZDN,U+COF$R6G#']IG9#F+3:-WW@-ZWZQ,Q!OH9O#<7F)][ +MLA5S/!E%]W#7S/E?.<1L+M3D(?8GN6OY-*Z6`+AS`^,KLY'QA993\K7H_)@- +MF@!R`\[KZ<633M@ED+MK[QM14VS'JW@>`:76-4N[QMFH#CK)<\V%$^,%VA&[ +M*4H%B]5,HUMQ`/1WRL`1I#"V:$D"X +MQ+:"DRU./.]T8+B#0*$:W=$X'2MZT3<-(QAO94(G$-&\M+6!J\3AUZT!B`GK +MN=KM-M$9KHDG,&RV0Q=`A71K;')^SX?1;PQ,(CY2MH=RQ(0I0K*^/$3F!XJ( +M^IH7`\5F7C,"9S\35IRO!CF9'=UQ_,0N"],=4+5;S/?^*$]+YS*8*9Q$+H]V +M]KRM`C05I:)/_36Y]J$69?>;N!B`$LWIC!$K),9>>#+.:!.2IL!7AE+7<.GQ +MH3(8%E9X\+DQQA\MG'`9I$6@G7==:W80H$@E0E-`NZ`E\X*`EK?(LU[&$\L> +M6\;K%&X43K6""\(2W.P%(056>NT^#]A157Q@J)YCS6.E^377$*48K>_/9$^& +M^QW@:`&3Z\!WHZS@;01:P^_&QK&L'=(\\F-@3LK7,K.9[4D,/(!Z` +M([LV+`+5GZZA!&:^`&L46!XD(N!N@)0FT9:"7"J1)#KL +MVL]:V`6H0YP5M;[3J=]J,W3`A?];HGFY=H/NBV?1;.%!6P_BX@E(',K@#@`M:9&)&$J*,KO$>#1DJJG9\WD +MP.L_GV-6?(W8_VX#'(,G;$_`/D8Y:XSVIXKK'K;&]]H#^C=&>B\S\F\Z\C,% +MOIAA+7YUJA!@K%OL0+D+FV/FPL+<'952F'+!?P__FJ2Z4*ZPAS(I&>"6[R3& +M/':PPTQRT.B2^YO,FA--2`M=DW`DPD[VCXC#M1TE4N<#>FP=,\DD?--'IYT1 +M8HR<$C.VJK6=LJK<7'N7R$I!FFW.JJFX$ZR0LU@NR?LDWNFB]KJ%X9%%"6,] +M-.T=7)Z-\4A<(;C46`^^RC6B\]0BPW;]*PK"8^[^($,XC0.-!EO!"1AX67&* +MQLZ,X450TZAVSB&E=ZO3OLVC%LZ-H"B+B-6$/OQ0$.K%+Y\,2_`VPFQ+YLA$N\IE)A_3*T/6_"5?^)-*6E:RR?!(?@!`W1<:)NXH,1AG +MZU?/>BVK?F4K73L]2#*S=ED3AXYZ[I<4*!&[?L@X+>DU\_"?I<#GEBMLTN]# +M3;]%.= +ME#?_U%18/*CHR5D\W&L'"6,YLJ`LEQ4=`9SS0S:C'0T +MT42)W*UD),*RIQF9I-"D%'V6FL%__?W`T>Q76J5R\7%G([WA4%RC_?3KR9)G +MW.C+Z(;)*D>`I-'6M!T*$9D@O&:>9IA.3IIPS89'FP/'BPSA1IO/E:_:%/2- +MVRU\+0:^OJ"3K4=$5K)#?EZ`PHK&_-`0`1W!!=H11GC]YP=,TL%]AJKL%7^3 +MQ+Z58FU;Y,*P-%-=-W@^!]%E:/M<@7349@P%^1S`4$ZF)3ERYD!$-!>"$,JDF'9<8IG9@_.K/Q6(NT +M%E?;R&O4*2R_*++]#G,&O3-"WO:.'5Z'NXRTU-:%I[O%(*-E&'>X#>B/5!4D\"!`,:>S$\O16PIU`>]D#X$ +MN25EV%0CDG0@7MK1`!2A1\AJ'7)&M'UFE`$AXHIJ5\EPVH19-RW^-JRAO._&IQA]:Z&F@J.L'2KU02*"I9L+WB0I%AX7X-I5Y3N1N,S05_^PG+ASS:&=KT:*OE%T'_;UHJR( +ME`3:8HV> +M+[W:F>RS(3D/)#8:1J4-]/M63)LWJ)>8.= +M%&!&XN'DF^7"G9D.6/V^Z1.(P33917AVCY%WZ!;QO`B`_U=SDF7.,"->AN04 +M#0K"1^#WB`ALYQ+0R*I`3F/OSMYO*;KUGL#GH);C.8_[T(T=2*%"G,[ZE]5D +M0(3N_+2G`I?_TG@BJFPVYTF;AFJ_"!GEDX'QTA#$E-;,K:3[K)VPNJ^4!'$' +M]E$81+('&O)&56T:'*A[[XHC-R:[<8`8"KK#ZW-K+WD)@NN]\2(J8-9G0MC. +M[UL-6)WSF`&F],<>@^@P*/4S9"Z9#OV`G\)#9;#QUAW(IBE-3@S';KJ[8Q>- +M4X<#L1PBC1LY;*V-(#.5[#)]FXK_!`'$1`95L_S$U]SG7[[P/3U$K7BD$0NAU&3_P_!#[`13]:&Z'R#O/CWF1([[Z+C!P77R7]F'< +M$$9ZU&`I&W96&PJ:Z"D(`C^6X.>AD0T^0*KFUEB8TBJ;PS_&C9#9'D0`L0Q! +M6[])RH>I3DEQ/>.;L9DGL!/D' +M?2PEN/>%9FUT@4HRM^L5'U!:K7H++MT62NAEB>WS]V1;XP<0E7`B%RL5J[8# +M!'7`D/Y$0/=Q:%#)"HQE'Z3MG7`T:23=M9N'8M2O)[#E#0FUY$KOC^T;3'_C +MU,.JD1F(-G+%VN:"ACDR5V=JG20NH94ENTJQ`Z:E3/];WS" +M.4"#?NCXKSXTWQB;Z(JH"Z1M+ADD#N73"B^C`WT!`Y0$#STS=8>_0#Q*W*2Q +M-L5N5H<%?_=HYOWK)_A@X-,I5-G9UXZM/M( +M0-F!S>:0"!G\1J$+-F0=QQ1;W3=A*`SG-$&>+]4R]W5G#R?O"H_OCI,HOS/] +MXO#EF@VSY[)W3>S@FPB)G)]&1Z/Z7:P+6RHVEQWQS52Q7!49;D6LRC.]#:/K +M&[6XX"AU+WW$&_N=/59F5+N],9:*4VFO1244:SHQ]F*7YCP!\@:56P4\#<=^=S +M`ASB]7,J;.,TXKCQJB>'&R8]&B\<+-KN\V,$9+"478<=PL2$(SX$]""O.>-? +MQ#:?%#-O=('FU*^AD\12E@(-QF?KSQFH)7W4A6BU9"J8812T;2Q<5(=`K)HJ +M6.8;3^&PB+Y+BGR,Q3<#:2\S5A;:JZ:F2=+TKLU4"#\=V,ATY<+ +MVL>UHU>76..;Z.%B-3)4?193#L8`K;OQQL"<"H6E)6R4@A=#UL0]"#ES8N+E +M:/`GATG]N11P8[_OD$`3#M7B`PCF:C]6]\K$*661#ZIU;Z@C2Z5S9:L2050.MR4C-3.X`T%NSY"$OH/+-&[BY96R_^K8TR[^<< +M<<2=KZN>N36,KAT*Q3!!5D%2&!5+KQW"` +MNDO@)6G2'PC"&F2X]`^P0RP@;1@\#OS!BGYI7+DTH/=LYH"\/(C5CRT3@U5I +MRU+B`=TM[S^C?>;A<+;=6T10;1R=0VB@?U.Z@IN3)-B%7,AAM'7Q$[M@FCDD +M;N6Q.Y4F!N3>";*LG!(95+^X"Y.-HA'1;Y0TKJ!'P&ZP:MW7MGYH6*3M3\KI +MC^20^)_P^JA-]CY_\+*SD"_:F/Y6P>`J46'LM[;7A?2"%=R=W=3EIJSY.`V` +M=-+*1[C7"\`GS5]5"I962M:$%$2!;+/_8O!&5.I?N[ +M\)M_(9Y$MT/<_!*+%5<*5UGH1$1-""F,Y+`]&?@0`39@&B4D%.D_US2I^;]_U)TT9ZI(2/&4A4 +MY1'!KV`00V>6*R<=JBS(NDODP<%^/'.U9#J!1/`8#"E!X]&B +M%C`*7*7,'4>U8B+*!N*`:3();\V1E9799I5ER"J:B=E]F"8C[57;!S';BZ^E +M4=`08I-7O#KA30H=2L>R<\I.]Y_;1+=,2U1-3Y8%6J;N@5FH6_(KWX.X)!C<2R(5K%Z].54V+! +MU0]J8>8HFH8^8/8QX'A&#`;4%%N[/KSUYD%G1L>Q?>>4"!Y-GK!7@B8#?7C/W@S5&0RZ4*I].M'/[_5PQGU?'6_O^9^'%J4V]R\- +M)MK38G<\,6X_8NR2'6G3N/Z2*YP#?LWA;6.AX1#^UT:!X$""VB6MV@;$&XVX +M^^3[](CI7**_8/=8*4[Y#<@G>G5\T0$PQO4V$S8_R%G +M0J_]O)QB9N5L^)[C,'H-)7*G5VWX1F@3`A,R;IEQ]&D_&$6^%5 +M4&VW!=2SH.B'9`0$O)$ +MC;PUZ]C!>]HK7BYZ@TZOG6Y>^&]8<&_E1-8GM;I^B1;==CDR:T.[<.NH`@N> +MT1C*_6IR5R"6&RN-FL_=5[5+^)ZCOGH@Q-GNWW55E35C9_;0[C;I=HK*%1^> +MX%=0DN&')JNJV#OR=:>QE46^:.KMRN_SI4"\H+'(V2@".0IG8/Y7N=@^2C!H +M1N\#6;/C/.SQYJH"^?&A)RW_R#V[Z9*5*:-#8B;[T$Z0G1Q>D:LY?@X*V%!# +M6WY4)D0\MF)POEDFZ_&5M?L]Y\@GG&2*=933"0J%,6@:L$)ETC"&Z+0Y4E*0 +M%L*BR[^:`;03[%*4-TDQYA`HY(R0;OI/A)R53V8//_R[]/[$3YR,2)RV@-09 +MD^9CVU+,^T]\5502O7^Q2;9]^4;JSE^!RR^(D\XHE&Y4)L.1E6("I\F\.Y.2L>#9Z#^?9CZ`=HB!O<`-?9U)!2%CM@ +M>&<:ICZ#,7>8HY[5U,A1P12'Z!=:=):,N([N_42.HQ.TN4Q(VYCJ??_0..-` +MV'11;>,!^GQB_F)$H10;E='^/=9R]X3=>)&IH(@I\P#S,15#:W=';XR*[)"_ +MS2Y3?KZ;"UFPJP*5EQB^#NXM)8[%3^+8'*E8[&$V!)8)B]S_(QZ>RP9XE!`R +M0`IXG?IC/^O=EC+.ZB/"@IK6/B+.L0E1F^#MA@?U>E-)X"4_]%X-:2)6.KM'EA,;MW0R!?++)>-1_LTT+`"ME1##1%@C*`WV;YC^+[#V*/; +MA)9/^2:%8+`PY!HS<"Z<>(@1QZJ]K"W80F0@:PCD[2]]H//NM6">NMPXT?\! +M0\+=`:Y"AG>*M>?:&[X[O\&8^IQ;[A.9PS0DN0'6%4J5>4%Y/,Z+:9%`S% +M^N)%JX6HSY)RV\&]4#$880*"TJH',C;&/QP5%XQ,\-29WD15C'S?;,5Q1I`9 +M0-;^M]&LJ;7.X)D.A./A%WAIC]$Z%5$N4&=UF'*M+I#+DC&K^CN9;F_-=%T<3<438;8 +M^&M&@>%#"R)6$^E&VSHU[87(83NL"%I7FLCQEV5ONZSE +M],>I4@?85G!V7R+K@ZLA7-69S88REA=LS\#.D!LJ,&WL0.2A>K[!*OW03Z&_ +M2T2KHY#%,A96;@U3B8.#7;<`Q2CT.FES!=0@NU`'5&;C# +M.NM*Q)-5DPC:6`5A+CU5%.8L(45)EBT,JXAIR90^0+LJ,Q'%S46<$"(9GAEX +MFZTFU]1A=HV!B(^A^`$G90V;QO"DK?YJPJC=%TTYMGT' +M^A]X''%])$/9X=)07M--103,8ND@)R]IB_5_?]!2"_6U^!I`3_76&)^U,UG& +M2G1B;5X>*3RO(X@:[H48D\:"])HS6;2CY>>3`AS00V<*O"5]J4R!W_/A5//= +MYN1=*ECU#]]H"X:6FWA]%K48#3$CBF@N[6V^U9Y"5F,3G\$_NF@.+$[S$$LC +M9#`]4XY0^HH(^-&\JL53[EN0T5^SJW/F,[;?R%CV=TU^)RN;@PP)J*''JO=^ +M&+\5[\"\7NTB`.`%DQN11GLHD)@ +M6'467J?ZB6D[:X;#0BT'\-Z"U3%Z**C%X()\X@_C6WS;*O.G7^OCIM_J1L#; +M:30GLHO?AC.'&&%G.7'L'P(HNKOF=N1&,'CHM5(\<]K"#RV=)#HN=D6F.7Q\ +MJT:AR@T(62ESL';63^E$EV747`+:[H'7$5THB^G2W\(@QSB$O7S4F"N>>^7N +M(4QMT$2UNKY>+@M(J/BXMA1QHY'HUM0RR3<4,/DH1C*UKL#.`E2`0T>=N34?)E!;2=T^!`\00AL +M*CUU1L([CP.PL7OPMQ+_.N+A2@A#LZN*R>0BR']Z=/WH'[U_]EY#"9SXH3-` +MTM4%9+UB5^JS$H9GFTTVH;:JA1_]#$D)UB2OE-)B2K.F1XJ0`EN.C!#X,YNO/@>?_9.\=#;HB4$3$ +M.IJY2=X[NN\'X95@'PFF8L91NP/8W`+#W:RLU[O<3U60#5D(.D8'_7C\YL1Z +M%XZ$KU-?WI?5%S,_T*-U(IFV2Z%J4^J2BX$%#FE0I`*>&5QFD5*/]A7-GUN> +M?."&,NYW4DO>>('];->E\%2$-Q%83*)N`HG*AB6=]?4NN;R\\Z0/\C<)E=>L +M!0[B32?S/UXC4`1%F8*ZS;']O[_+/]06;K/G.-OHC@T\$ZKNC$M46@!82AQ' +M840N7P:.WU1M\WGS'B`&X;[U]Y1U#@(F#M0??!.H6R:W$IQPK_REXE=E^D4] +MF-T0>7&S/PY0DS9*U^QSM5""BFNM+SD2XE`IS05?TLA@*3]!;W44LBEWHXJE +MUDZ)F?[#V\AL%?+V8',..&"!A:!Y%AH'9W1H6#N(AR)[A;[L:.T9@BU[G1/O +M;EHB +M:<[:_0LPENIQ)44TWYRMU98)K:KKXY4LX +M4UR](55WFOZFV^JT-&J&$3=6Q'49U(F1*Z>P`7?@^%3QH]$0>\?GFN>"I +MC!JQE[KW"#D"0K[M-V^%`VD)B^6SJPPB2QN)^'T$-Q"X8BJY=>R8W+K=YC_# +M!T7IQF1])M@U=Z6#@.IW6]S`J;M=(<$H4%A#&JM69:$<)&LU(;4G_IQ[Q*$M +MUFFAJP$";WW8><0&-_+JY0N2.FJ/VM/_9`S/@3/P+LD;V_TS_Y+`>@DS)P:1 +M?J-B"![HB_H'3G.KS?HV^RSN/F5OD5N:1'GM6C#>3%"+?VX8!GRRQ0(NQ?2T +MG+#5%`XK23E:&:5:-`:R7YM//'\SK1NQ_)7`)?KC3?L_$L_O80H6<06?5)Z- +M%$@9>"50@T6/%IW[QYTN93*J6L/W06C5!HY_-![TLGZ2>X6!T/\U*KZ=FQ$7 +M(L;>%KW1G6?"T+$.N((>F>79#5C[,;8]HK%;-\/P;\:J+,3N>S$O.0'A4>3L +MUAQ8\USS87%NZ\1,&M)HLZR +M,*(/YH)E/J\VXJLW\)G6J@1#YD- +MH7VSJ8Y=5(9!H.-!,Z&ZOV^FV1P#QV;NP(16=MNT>K=W#[T$IOQ\,H(/F58. +M6,4RG3O<! +M.0<)!N(-Z1T'(TDUC_JZ#.IGN!5$-74RMOR1*-]"* +M"Z^<6^T]1.SE?9:E*N_2Q9,SGMNC"A=L#42VG0W5N$0F$U/E([$"^3%YC,9+ +MI;0DA3^J][T4`/?2_KE-"=\HA%@P_3EQQUAU4Q&`JFNL6&\DXUF>X&5M3<\5 +M.-HW>X?I'61]T3S40I:Y3H_.%;6H"@ZWJ+"+KJ>(QBZ6_AH,C]0OJ465ZSIKL+3B)];$]0&Y +M!;HUD"PO9BAP;!4`UB+&<=E8V&$K/-6&U30D@FS#291YZ:@MW`U>0N?Q&P4' +ML\--&.U5@KM`&"&VEGK%9)0Y9/`6*J%I5IKP09%KZIV=T#6;^?S$ISI%Z575 +M&(N'OQ^16HI[T!B6G-@T3BY3!`]Z3"K-#2(*B)"CC+Q"N;%2^C9?DOC@<5FF +MZQ$E-@_$;WAE1SL[`)K/E80Q_PT2#9*+]8I(B0IK+2/4:_N(%AVL=7*"V:)# +M]SOHW>[QSTC/W?)["XM%/3?OD(H +M&T$4\ZD)Q`S%?Y=?V3BF*^"Z.^$$[Y?0<.K8SW5-"X>4SS]U>?/P)V[,#7^M +M?/P56NC;])5.7P5;;!."O,"B+RTAH5S_X:O2VBB)FUDE[+]^"RO[(K2+K_7S +M>S?.X2Q7*#=IZW$_08(Y^RS^4, +MO<4%NWXSOPZ!92^H.2,5DVT"`3[^11BM.3UH5#QW&IU3AIK[;U=+GVO^ +MFPU.\$DD8XHH.[;#E8OHMKFX4!FD#`IS&0Y:?&5JLNRISI"`"BN7V7M?1ZG*,AB04VF9D5O;:JYJR7!:D04`833-N+K\0(JUAH+_MNNPKN)/'RBFT"^#97 +MFT+-J;'1"7-&D^))H,\CD#3!V:#06%-)?33@\TPY/J%TRI6XHP,!^Z2VU?.^ +M/E738'J.`+$%D-Z"`-ECE4SL#QZA.+6LYBNM98!D%70M?Y"I.A2M6Z"]N]KUI_&/""S9,:!T>!Q +MI#K91V>#'&8>S9P(0Q-J399?:9`'SX"WA+=M$4+0,:J)B4$SW8:8&Z.3S/L, +MDF'.5A`%S@C*17:L*"8NQC5^;*/*_A((5$;HPL]``]ADUEPN^A1S=)K=0"PA +MW*TCA"5PA.A:F2R3L8.37"Q=H(+P/&R=%>L+%FV'+J('>[MW5`$D$)X++2X# +MMKJCN&.=E_^RFRK64?X>[5#'.1BZSR6EQ0_-;*1]U1V&DH0AEP)?3E +M]5+DS=V:M+)QN$262-QJ_BQ)W)#3@5UE4T.81/O`W'8>7#>JU5P1=,];]H1_ +MN)(=G>UA])BQ2TZ\0ZI`+0 +ML#HQ:9:'1Q7$K4GMEB/+@!+PWOA_$ELG47=?CC[8#QM3[9G@LNH9T3I^>=N% +M8+V32"*G=!)HEGQ.L^&\"E<)]@^_]Z!.B6G9F<'B#,CO>9,^.)+`S^M51>59 +M)U)1BHZJ7IXRK7O2!WRSRX&1BXZ@>"^H;%VK1-7IT[B&C;,\;EARAQ-H_%4H +ML3XJ"BV5:N.01R)NB(BXXKQW!B4PXZT9/&7S&A$WC351'0@Q]8F5WD[!<,/" +MF'9%Z.MNY7'K%\QO.F5*T":>ZRL>RM\@!X>J[C`%##8=OV#QSWBH(WF,B].4 +MT0:TE^@,;^,\039<`ZA5B>:3`,PE"8>U"]7M@RQWY7:ZY-.V`,BAIS;FM3W? +M/OIP0/Y;TJ"GA"X3I2LH.@F?`VU$V)XXV";+$B(C03R!DWGQ]=A@C=3SOG7@ +M)_TYK:KFQ^+XI@L7GZ8L.9":5)'R%TR^[>&)_E^MGU@T@`1SP5(90-8V-7;- +MBJ9X8\RSDQSSCJ39J-7\F4 +MX31'%$E"\I1XJ7:<%)@8WK=AAWPVIK)8S!P8_B838*RI_;&!+G*A;F)1",R5 +MW=0W/5MJ[5-@HRH\NL."]?1\5#5+XT,1A$3=8]`">[\FXPC$:Q[(.Y;#,E$[ +M@/XU;."!XO%JXLAUP;4M`@OS6!4Z?,T6Q];8VCUMR7Y)MVI%(>Z+L\)!"1O* +M)H24V"Q((Y\4LBK`9CF!.=7>Z^WCS:EQC)JR[!6%1`Q+47F"&P3A$`9:I`WT +M=.U8^6VITR<[P:5ITU3R1[#^1E4H2EF8$B=K"Z##-_-4J!QV&Q63]0DDB?"^ +M\9&*3T?&J@N;2Q`F^99HP,E)*R,@)](7D'BM*FR-?2-[\O_)'PD +M47,2/@!I$L,V5J,'XCT/3T<\MYE/KR;0)/#3CLD!,S')RG-Y2-[5FH6)L=\! +M8NK.$7]NI#DC0"S\6YC@&\9)N?\W>.E*@$@6TT-C5/!V#**.!EXQSKSC4RNC +M\-K>_/^?]2V0ES9B%K;_V3D_XAVO4/Y00.RP2Y900N])1$!D]^36 +M2F+6I^&=%_Z#FHV[_C.KKQ<@=4Y',-A1S]\E;$#62)O#C;*2(CN.XP,O/YJ,2\_./9X@]\UX<(^D>*F0+ +ML21Q;W-,#@Z*8=G-FUHY_I[+[H^P)ISYC92RFP4`H.\G3.O*\F@*\ZJX%2VE +MI*;<*@FGTWX%)X6T4XSE7G90[KLJ1]K!X0!CK_(0DU]>@[FW`'RVBKK,C:B4 +M'L+6"SQ:;#0SF`@TR3H^U-#3>,33_2Y335TDPG@A!S4#P +M8*;;\MV8>7P,.3B`.O\<=]J./E'0.WE_VX7779>880"@4YNK&X;'-RX$?]1A +MV1#=BK0<*>EZ$%32>K0'&F3VD38"QS:F!-U8]@OW'_F:PC'R5-RGXH`^#!IZ +M;?<&%DQH3(VKK6=:;;`E0RT9R\"IJ>"1BRTE`"JK>_%?[6NVPO4SM9DF,!>. +M=V',SK\>I2*H_RP8S?T$J)A6X-KQ6.%5_@D<@,)+Q0LE2M)"3VNN@71,OQM/ +M/-J.L;RLK8IR&"8-P&U9HV0PP3!)BS6A-3K^>TFBM-V?2]>8EI"0\&C!Y?_! +MTH@%K6:.M<>8BT&#[Z0Y*3KP0S7N-N!^J4D0_:U+9'04C_*@W[$7?=>5ZG=R +MXM/1%<4!^9?'"/*MMZPGV]IQ2F"EAP.ZXM&!JXMN;RRN.\7,FLQ:^`!2ZGJ2 +M0DX9"T2<%JDIST3'@@N'"45SHFW:F!Z<(3<067ZVO)@NG?'^D[Q%@3;5\_#! +M00!S'%4TL#^(SR'JA@[\Z0!2?Q- +M/6V+V#"U['H"TTL+02RTYKOXPE:`2I`%UT([+WMCD76`?`D[^M'Y-6+.8:T` +MLI8^`V&K;+.A?+IU!EG4+`:8(U,)%SNK6\X4_/VII06/<(&%_Z'+15DWP!6) +M$"C@.T4M#//>@DY8OZF^JA8WG^\;;\8/8RK0$/+5=C>9F!>#I=2!0X\8@W!DD!4FH0 +MPNKTJ;I(IT[_7I2#WAF#!8]O>9NHU8EK]5IIB;/-8@8'+IF\/S;SDM)*SPMS +M?K\5ATC+3(0H$*"'`;R7DO):*>]18LBX +MNA-M,*G6^WM8MY\6ZH^N%*QMW%P*^O_6&4"'K@"CW&E%H7CQ +M='Y2+!5F=BQVDM!TQF.;T00"/XI6U2@)QSR`"A+DX8@L^S#';MX5@2.5`9!0 +MT/.5C +M?)OF[/#D_Q^*(AQ.VSP\B*;IM2/E:R#"\L2%A/F2TK^J'QQ:<:3!?#3\N^^) +M#=,Z@C!I")JYA3#9HD[A(""X04M@EW%&PM`@T#"64JWQR!7\84GT/XF8Y^86 +M-*VCG>]8E^2C$=PR%VFTZ63;=\^M>Y*#R*[J5\Q'Y$^'/A9!SG.S<)E(=AQ= +MFT;O07NH54:9($,$%A*H/_2',1 +M9*V=(TR^E>+;X^L5"0'FNRE@E5[-E:*AM>D/99QWYDH +M*=+ZPZPGR-,KAH9P>R2JK!&K[3%P7ITZ?>CB-37"Y/!*%Z:/;QF/D`\^9(T= +M+U3])PBEWXX?(T%@/8Y)L;UB)P8?1^(Q(Q'RXE\U#(CF% +M,SP"%'L!AMAUP,7MVD$OOZ?MQ>#WC[X%DL1IOJM?JORSJ]-W"I.>"QW1600` +MP@$L4W"1RU<]VQP\A(R,O1>"UDN@<\A3%THBEUY'1FO/$N1#*`T,JLY,JA(] +MOA10OT&S#(IM7=G>2@5^U:]RKO7K35.N/+[&<^J''(DBZGS_^6R>J8N[L-\P +M=^GZ?__5[U_`O(JAT>DFNXB?F&,AK[V>)55H@8$551O#LM)?&A*(DSVF33[V&8X)T-V"M +M5V39OP:H[-I(-UF!7BP+<++5@C7RB0.5]Y9/]#56G^\`1B;H4RA=!^#[E#SL +M#(``NBVPI\6TO[]K_9B(]2F(_DW:X_4(.:64KJH34>Y].VOU"CMOH(K\Z\UX +MUC.2P,4$(,'O4PQ:#*(DC,OCR\8OD?_DQ_ZS-7DM_7O";7!.F.=(5)@O9.H_ +MBF=%=E+;VN%COM1A4\_P-5=0^=FNG6'Z?1XR^2S(!7!$JF@<3\RB)%$0,9HD +M9V,RXG%`H[7@C]BZ;S45GD('?#6>%3E,@C6#,#KM<4[VWU=ALO +MCN/WRG*&0F5&^`"^*@<0==U.[I7D?'6$*W451MR/`C%DMY`GZ4$IN?*$$)]ME"/SX+_XA\/FL+#/F@( +M[K*#3E9Y'[P%*H5Y0,'1>\(>$%7-6U+"ZMS$>P12LI:FN2.E2-EC_ZV':.0L +MW"/!8"ARTH;ZTET9&VL(@AQ:5%" +MV0@XB&\$?&8U?[3/NF8_"X%],H2AS_2S`D2`)=#A:57W\2_HED*1>NAXU(ZI +M-9AVD,,3&,_\/`;.46KURN&U07$%U9NQEUP)/=]YPGB_JN]5/RN'H_@2"N?N +M(PH?I`7229)\R_C)9[CR9(0H,"GN-+$[1?*"L5D%\/$7:NG/."M8/;BC^"^' +M4#'!V(7W`PFQV01OO'P52,22F +M7*?L,FN'9C_KPW#"`6XH?^\#XAA^;=EO#Z+[AI_;%TSLY3JGD&OB*-A:97-+7S>5*+Q>6A8PZ]?-](W$<$DOMQ60H;F29 +M(<4D+0BFL)I;9(RO6[UF`.N,;Q%[2/GZ1L*33N_A7&=."_)SGNE?2!J="TYG +M_]B9L5M=/<&P!98)$0.=IW_ARB,"G@;=_V''M3FM'@XJ.](=QKM+`_Q)`L#L +MN6V@+M#]Q\8DG3=8YG+>0!IK'$C% +MKC5"6T+)BA#Z+E^%`A3_QL>G&B)'A,@Q*FKV&WQS1&@J.97H&;< +MKIM%RD*D1@;YMP?2A$T9>ES6&\-U&H+E!%H\LUBXZ[LGOAJ4/N]IP1.^!_04 +MQ4+ZSZOBQ_5H"'E=M(3>I=X066TWF=B"DB,AT]R4U?4_"J_?DG^HM5XY:ERX +M``HJ@D"G^S_/2REEO]S>,VP1$W2S_88B+^ZF$0Z"`0LEU19$.0^]O;7JAM'5 +M('*2@:`&1";PY'+(F!UL(EKK,XZWN.FY*CC@+R;H)U^T<`#!>7C*O(O', +M8E.K5L6:X.S?!JNVB3I*>&W"&96(+,O_O-$5Q@^N`),\.HJMG9,`U4:+-1O' +MF.:']F`X$)#=H[/$&P>*N8$$0?`/[Q[/C6VXBVL/U=$^BYIO+X24?)\7"CV/ +M'JV"D,[1207PN*%I/!R'T)&<>*,7ZJ?8,>O,B-R?G-O]C135"A*Q`-85P'8# +M<5,)X:<$/#&V3*W`Y1SMPDRH\N/##R+#WJ#DUOAD&]6E9[#^,O0#V':#!T)= +MW=^(GMY8/]*+J56I,0A?$7ZLQ8QFUMQ09?/.JWE;SA!A?'^-W6,,\U$'7'YV +MI(PA=.TQM9(WFM)2&AF1)O=/4;B6QRS\;14VNEJ#9TX?S,:2W0="CN\CZ)?E +M86T^<3@5:'AGS5'P4_U12QWJ'SV%T$,P6MX1-;?0@5S,&ZXE:'M-=E@%L4$4 +MP2SGS>5=.61\5JI=#MY&VMTK9SR!.KQ%6\%8KBI2CJ=Y8#CA*HVQ^MYRAX%F +MJ#;JZABX'ME_7&V"?:U;LH-[R%$!WQX>V(R:[5P;N3YE=4T"LQ'$/7]"WO0R +M68I,#USF\9''8\ZUHS*F\)D":Z^U)GT%V>49"4AC;5U5Z3J2K+6,3."$G:RG +MN"^!XUMY9JKN-4$=RST8JZWYOI-97)&("7/-&B;3#(8;F&615JX,OPJ]JUOQ +MY]X9A3<_I0):T$;D[XU59]?+5E1&'^+4`:BD[+K$O=8XI40*VJP1P1#^:O;H +MET[YP-+^LX]AU]MA4/V1SLR!TBK`W`(S\"TT1Z)6:)T?O&U,`98$AF.!HYC! +M&^09LQA&!>'>X%SA&:HM0TYLKGS&E]DV&0KE#,.42!E-5V!F$O!J$G;U,B5R +M-$:.8GVUO0T"0'F"'%(#3.X%ZX\\WNXJG9#AQ-O-@<#XS"Y[F';6%J9*C;5E +M!9Z'R$?LOX(T_4S__0$9C\Y92.J3).DPE>07.FDD>;_T/A<)%'#<+Q9H+BNG +M($BQ!WRMW>N^_B1)7'_3(^48-K5%]/9I!;2G\$+?7.#V2]'T0A7#;_Z0E>!6*LB +MBIE`;8[3G6A_+@@>?>@D%AU#MSN3HZ.*J5CQIYVB=8%/?2YS8(=].(_#Z-M,ZY= +MM<9[AG<=)()#@719BYHH)2)>] +M[Q[H9Z.@-I,B/N(7;]TVJ4IGTL,/#0W, +MU=BBMHDFK$C!&WIHQM$SQ]Y-1.D\$=*=&"G8+M.AN)H&I#IS>+?%:%AZ1)?- +M\GX-4_<]`'']:HQ4'U[M%&_GK46`#:NJ^5'0$]%1FCK]K_\66E!=$-_,0H>* +M.:5_,.S24**\FSQ@7MK,W[!;4$RAG;I(Y/D`RF@>2"X3$VP$E5N@SIZRHURI +M.U>$8D"/?D=>G-K]FDO._#O#%U9\.7?RX/3;WPE2=OU3F9!R"5[/B08UM)PC +M*]2N/L5`@[-8\143^L5:+1Q +MR,52'ULAEWY^Z5528*HO^\M*%U$*E]G3M8@LAQW73M-P_8>8;M]R^]97OJ3GL-;TA& +MHO]*;K'#:7LO6[[:">^7U7U4BB#"2HM^>V2&CW0>UIP5+?ZO`]D1+JR+56LE6Q"-6K)PVT/@P()BC:_P_J]K7F!&/%*C606ZU/U,!`;)N^;]9:J:OGM570$EE4\#6&:3^T]7S!U: +M^[E4%+T-W:AN(JDQVCI<.DE&!E;$$.?T,!N*ED51=(_RW950<&\X.VM8[*&W +M_;&ZJEBEK'TRN#VUO%;)H#(N/D_;N`>D+E[WI99'UC-RO5?XL$55]8?D0H&$ +M*8.F":L&T#9;UME%2E7V>97_@%^[BV8&635*^LH56LAZF)_ +MX2X['`.;M.'2/[YA$RX5$[FQ;0/NE[$<_.JY_-/=F'A:I`Y?[J,FI(HM9AO+ +ME:U?A/N5<'=S=]F6PMLKH!J\;!:0\7Y/^A+=0Y#KE&T1$6`FH*@'<,WE/1&( +MJK_"D.C>^']CM+<3)!!8!+\?G-IXLQ!R?(D[E@&O1CJ(1+7%W-0=U-A0(/T% +M_TM[/]FC,S.)+$"V]95*B!HZ4A,E5*N-#F=*^.,BB*08OL?G`DJ]SC@+KF-X +MP+#*>6,W7D)#5@[+G9JV*7)G[+H!A2O9X1[6)RA4&";8B>NE +M":T&>:$7A-,1%QN/<[S$IJJ%^DK[BVF]+,*<4IM4PN#+$RHA_;CG6.G8;-L# +M6OFZY'!"&.F;#67!J+B1P#%(HH=]CO*"?4D.]HH*[M2/RJA7%XA%X5 +M'TDY9EVV@I?@.2I@0A%&,(BG1)EBN7[YT-N))TP,=G9\F8P-;S2S&.?XRU!+ +M`0(_`S,#`0!C`/BN(T4`````)S,!`&LZ%@`(``L`````````(("D@0````!- +M86ME9FEL90&9!P`"`$%%`P@`4$L!`C\#,P,!`&,`C+`.10````!J*@``K7(` +M``0`"P`````````@@*2!6#,!`$Y%5U,!F0<``@!!10,(`%!+`0(_`S,#`0!C +M`(RP#D4`````B0H``*(:```&``L`````````(("D@>]=`0!214%$344!F0<` +M`@!!10,(`%!+`0(_`S,#`0!C`*>+#D4`````3!4``)M_```(``L````````` +M(("D@:=H`0!C;VYF:6!R(9&J6OW+%/X2D%.HLH/4@[H=,;4@&P$:E>NK#GQM>2SUV&GDS9/G@ +M#J5^X(O,+,<&,^D*&]*S\[._['H;H(Q_@TY#%3(7ISR#T4<+FKD +M-'UE@M9HUNOF^9MZR#O0-#3>B]`@TJ]>?X)52Y;GS"R3N$GK%N3U>*,.QPGC +M;.A^EBBCJ^;J2`$0=15"S/(-HTY$S,RP&`]-F).(Y6:IZW +M7Q$X7=3@$DJXHXHW.R,6AA('+_8!`0MPO*EN3=90VQ[;;:4#)FB%;O@;==TN +MUIODRIYX5A?)/*":="9HP.[TN_G`P57[R16<\9W2T3#$S$&_&>/BHK[17P\B +ME_6B>`J^8YK:0!*/65&B<]:)W`8[46&N&0FRD2<\-9VR.)+Y<4ZF6?;WRP30 +MYG7\7`5:2OPD'DHO866#4U/#@$1D(W-]H[0%?*2 +MH>)PD!IL'/X;6!J+W-(785MSV)I?B_: +M:&_ONZ)K#.-?;ABX?DD9K5E(0\*^QLEGN44VF@^7@47AQ/I1SF^KRMC#QWU$ +MXA=^RQ5-2J2;_AY:JKS-?)>L;&_A9R>M?$Y6=^A:%K+$7%E>X:2JUDX397!U +M8$CA([")9K[.MGT#&Y+.VX`K5Q8HR(&-K;ANB!,ND,+3JJJY;S$&CQ2(;#4U +MC>8"_W'[2%A;H69FAB3R;]**#["CIEV]VW,`\J[A-E%`A42,$LNF(_U%QX8>^^BOOKHG#S.;IH+\7S+?2H_E,6WE?CJ\ +MEZY4F2&QH,(.K*8\CYYJA/Z;O,C6EYZ6X!-/=ZN;9,KDV>@G93A*\*@X:KH` +M%$;5M_5&QWJNWC;602%0(F>BETMY+)MSI>$+;GG\1KV<03_G2!(%T]8-/=9; +MUC`8Y^B;A@/Q),\*+H;M8OV,Q;8NOPY50W2#)50`VP836D>R0Z';AS%]"V5*(5BAV+P$>6*W5TE._HB.O[%H1YF#]&4$`](9Y +MP@5P\G.*V1]^2)$A$'TZW[W?AN$E\7''X7N=!U!")BU6T9\=?$1YO2*!^D&^_R6% +M]FKV"\514HQY9!\#<"1NDS85\KC0V*#LONDTV%*A)!;&>)F#8.#4!-*HT$B),T8-\-WO,W +MLM\Q&O['(&M1=-DG4O068^=J#\)^33.JJ\5R@:S;+;N_*:VM2QC3TH5X#EQ. +M_O=Y`=0,&%^>,P/,'N%8'5%TO2K3%GPLY@;G@MCBMW^R&JQ*U=XXEGPS`OTV?!3I];X)ZX(=AF+G7IPQ*\!M=KEO;0;HP"0TP9MY@7B-RN?H,>%1LE&U6A/[`]3C.0_KV]$+*2O(&$>V%4-3<=]G,%O +M!`JBSY93:XW8Z9AA+!L^IO#!]+ZR63)?MH9N)HFY? +M-.?$SZ68*UXULE*OHO>MAL:$7TSY3",VS:4;NHSVWQ?D;<[XQN]$:(+Z#)BI +M6:@7XQM-VSI3N@$=^WT%^YWOEVWC'J0T&D^C'2QO"^;.Q"5E%7&*;8BUHKIN +MCSX:051L^"5D=E.GBR3BSZRMOD-U1$3[P=.-K*OJ#OV3WU!1@9R!"#6L#]A< +MF.Q/J!!\VL`;'VMQ5I-XU$S+>IS)"I/T-XB67"!Y7>]@1ZYU!:_[D'N,.WM=E`G3)K@D5LIJ])3 +M<6;R)I99QA=[&)$-DDDUB9N<)S"B:V4A!3[)4=UYP3Q+C*9'UG)FQ3V[YJ6+ +MME<:)`J!8[&2!?M12?JZY#O&Y3&_/G4Z,IW%G\072[-*`.PMYTDWM^X*UBL49-"!.X=)2'MO(:X0$W__\80X8E:"L]*F$COJ=L][03;IC, +M\:_Z4]@\G"I9`>Y@'L+[ZJ*U,LX?]?4N0F'G_/^%0J5K7;G`4`]2D/ASCFR; +M[I:DJX1O)/9=-*OKS8G50PE$YKR#\G[XA"0]K5R4[#U\H+:7/NM,#$T9.G:? +M#E#UFQ_]";#E=:]DAU<)M#QLS[HN')L'HNO.51+V#36F%YJ5#[^@];DYA1UG +MY.&+\XG3*@3[9Q8G=#$S95)E:5`4Y#JX,\RM8M4;R5;$B+Z"P0CT]+H',L^J(-BWG^4=I)QD +MIU2_?ED:=W'K$]E`E/9]*S%V+5IFKRRY8S1W&7K7N6-!H?2E/B&J5PR%:?MK +M=331,'0Z!H+:W'F!RA0U5N<45+;!4&X8JIVF`;^$4UJT^P;<[4CUE!%7LHB3 +M;:U##\:5\2V`^E1.!E!^"J>(`A=R9WF1SNRH^#TI#F$.N%V-U(A+]<,#R[#D +M9?2@!B==^V+J+-V`%[JWR.(9RR`U6?"D7D:F:)_;11RW8%M):(&?4$'8?Z;V +M^6$Y)TR3AJ%IA$PE@5$T]U1!//6D<[QX%&3L2KK+B3)9WYSDP:DQ";XLB%BP +M):?)VIG.0U-NH:P$0,WVALS*B6\]UUI6]Q<&"V_N_&&'=AW%HL +MR4E([I&V[`\[$+9S!4RZ%D+NELG/2T.0-7@4OBFWW3UK^\=WHFF?E+/,,'.` +MG",(1S.#R\`URH#JB&A%;1@'-P.[Q7J![QLLE8G%,=E^JYX5N&UBZ%G0$-($ +M`R%<+YPOA:EC6#8)U]\WRH($6$R=,]88\Q8/EK#$&G-R86@5//LO%U6@0-JW^+5O*B_Z!?I=WT#=K-"F$W +M/1;Q\'$3:H5KTCILI4.9'Y>GY]I#J;@A$%@0!0W5MQ.[O;AQ&BFQ_3(UK>9]BSWQ5IDDKJ=:X +M!!![8:'7:`>#N(AK`]X^-DO:M5MT4FW)R7H@.=\A5W82=E'K\Z]?AL?6CJWJ +MU7WT?V/9)\O%0 +MFYH]"*$OI7+6VQV'J)55UH5^V#M0L*-G%/LU64R^ARM%F&T?R'WL?8(F9NGW +MG/&"&&Q2GQ[2!/*<"UJ"JHGS_LDGBTA^;89WDT^W.&0--BH]TNXRHF*W_`8; +MU)Q8#][%\Q&X_'"@I_PW^>JEC/Z6I'X$DYC5S^"%,I0RND-<=JHD7B02Q5Y5 +MV1N,6:':N*IW7"$1+_<,<]E+GT:L@X75DA$JV?N6SY^]8!H=4Q<]/E&81<@' +MIH?HN\=`N\,-17_+2E;D6/C#;I3#UE/)MLD3Y@$JJU+Z>SY(_7&]"K5R.V<' +M<*B(2(5"@VIJ*JN<7'OHOG0_(&G*_N*A,1N@N478HU^UPAU-'Q;:TB6K5RW9 +MNYD`-G5O'S(0*>-&4N)$9V'\UR;X:0#`3Y?]"N>2=I9>A!CH$NQ.2VOQ8R +M"T51RL`LP3W"^@3I%QF-L*J>BVLHS.C>=!A\LSXDN$NOJ^3AGJ6?M;\:04@` +M$PK^Y[Z\*0$9?I +M*(>$AA=G%3#&S\1/]P>FJA`-K%S\#YN$9LJ;W#>SL?UI9Q[*X=O"8,#VW40( +MO4$,EE,!,+R!R'AM-:R/*)/4MA*CLHQ?)8^/5(TYC5K?LO$Y7'T``%+;ZS_7 +M5V4M_]Z>$*[2<.T\%K?B[!B=QY62F\*UVIU.9,!]!U6(F=(NU/>G:DA?L:DL +MNW1J)??.!-H/QR=+P;NUP57X,UQK="_S+$!O.KZCZ"N:\3W/K +M?I:YY\5:EZ+(\)Q)S!CFWP/&582L#`W5!>'EP&V#&AY.LF+-$VM4@J\;\N2K +MK-%:1>,#G,W!U8%((A>Q@R1RPZ)3_8WAADXS.-@Z;[A''J`B3'G]1>%RKIE, +M7G+?@WLK5`Y#U:U^7(_`L3YI2QS2\?9 +M_WA62*X<,CAX:!+GGH$&&]J"6Z.##467^XRJ!?E"*&Z^9\M&DX7\9_ +MRBCV#7E43O'_\UHJ]P=-*]KD0/&VB9NM*D[BU[:7VYX@)53KN2JRG>Z'^CA/ +M+*?JTM)!2L^2S&`B!;QOGN%*[$PK/,@LM`"5DC;C"`+.-R>*MF'C]R\F1H/*?A;O]+2CR[R^3?7>7/?1V%.QVDN\1]7YM(/03F@PB6--%"X]:NG. +M2*&QWAYYY]!9/W!EX(,L'N\#'9<4R_J?JX+"YX@2KKF3J +MQ#[_YJ>QYM,/UOZ-O2"=/\?1$O^"!%1IN6I&B0[9TPIA.KKHT0:5L`(OM;_*[+-S]\&8=;DO60ZV3S6/9(OZC#C0@`WLZBY/ +M7I+J9_!XC0A#7$I?Y60(.;BJW3[E;[!*G(5]Q?1]*Y^JOQ6B73IRF5;=G#K: +M.OU]5QVW!NN3)'(&6^0&NH^#/G'EO2=CEB5`!U&LM']9+QI^>6=0_]"C=E7W +MPUNAT'&-4/TL%$1'_]7,O&)J%SSA46@^-Q$T`%X,;3TL#]TE^5>.K^`(@P_! +MCXOA"?%L^RF$KEQWY*#T+M(%DD6"[14E8%>_93KV4/27!I*^5507.GF/]4"U +M2V[\B5"PSN+%6^]VS0LW[KTC1CBX!.$L]$=O&GNWZ3O`Y+-J*@"/Z)HV6:*JBIWUK2,\M^,_6^N$[:Y-]=8> +M`ALIRF@IB57=6@_+%"S#YCZS5@`*.T*.FK+WQ:D.;3=RD7S")L#6(.4,XK10'./2QS#=Q4A-:Z1IE.;G +M,%YN)B0<0SIM148!I1ES9*O3CG>R@L0,*>0VBQ>#3V0ALU$\*@L"%4!AY7I[ +M`NP:"5X)$HDSN<&1LE%39K302=P"T`F91!*Y:I](D`].-'[R0?@N"1U6:>3K +MMM,S4$EFRBPP]R8:;Q"RR[!3VG$J*PZZ(:#MH%9B-KH3"\J!^:SLQC9X\,>X +M(SMO=(;;R2A2'4L8K8O)3$*;`,DO9KYHV]*V:A+>A\CJQA5>6JV?^K?]+(@2 +M*QP<,A3"X8K050>U,4D1:X%;N)1L_W(0")]F5:EM3J#L^$LHI+&_243.PST= +M<=<_L]Z_*-X?S04H(GP)FG_2??Y:?-S(=N"CJ(@&G4A4N)`U$:_&_^K.O-\\JV@]6"A9H.:7G5WW0FOR-' +M#?R7YD]EG7\81+LR:=H2.%@%-(J[K&T\.YF1"^:E8L%E!_N+3+RR&E=M!`4= +MG6--\@]9)[^ZC]"@B4O";_']UIS5&`9"I!YLJD-ED[HL!U[%Q"Y>SD5BYT\` +MR(J>4SI>2(I*MH&$?"*\(+J(M`3X7\YO(Z,CLO1^36R+G=L,.B69E;#2PS>$ +MDHLU-M\!#,JII-DHM%JW%'8JTB9))6CH>V:U298/E*,O<"_=?]W;(T3/@[R5 +M*!SR=:!'(@=I?-G!F8!?VPP?LQ*5;\5-#\*BKV3*@Y3G2'T6?CA6,5$V>B&7 +M\@6F'A[7^43YY!YSQ9TG3Z_J3X7<15)ZY?QQ`KI<"[E9QT_20!WFJJ_OP<&KSVT3FA,@<`.-6*S1&>_2)ZH8;]N +M83/;=V[ +M?'&*](J#)IL.,":+V\BEU;&Z##^2'KRF-/ID=853@9"BC[N.^.JW(JJG6=K& +M/K1B:]XE\`$."8$HK2#*\4^<1XUP22[]-T!0Y&U7._+NE5T:;XQ\WM26?,.@ +M";QFXC3@X"VQA#FD(%1]PIC^([AC9?-T]O.BR\H*7N%)W\G8!WAD$=X1W#@A +M[+?0[6[3H7BIM"(UGS'5V@B,!*C@/H?F)!B":J`[1[\-&\33WN(`/)994LQR +M,]6F_<<=!+[\W")`@FH6O@K+8&Q79I6/ +M1E8A/65;.7IQP,I3^#8$=#_7$NL_7;)/C2X;F;3U6-U52A73Z&OY&QL=--L/ +MTT*1Y'UMZI![[ZP6YXQ\(KF,%GGRNDSN-GT(X/@CM&%''4B'9-/[ +M:7(4%V+8B_I_G@XO!1Q5:DW$I?&QI\P`@RU$KVES`B^>,QU?S).4?X1@(0[2?]C_##22\J`G86//K[JRGGH+"Y)HLA%4_9V== +M5P(C0&F8,O.R)P>54%T76]#>@LXO63MZ001?L+'O!K>5XS>K]:T:[@>,B:;IB2F*GGO8&\R#"$?)HPC+#D'AN$-BB4DCN*:APG]7"W%3B*5"(U2T4X= +M@9C.@/8;.JZHG[SVJT15QY!L.)V[L,D%N(/,7EV<6T2M8]4DBT%,R/89LA8U +M>U\)64S)#*.)'0[!#/\9.6^W_>#"!B@NBL?7JZ1.$I"VID$2&TI'0Z@\P'\G +M6SR9!0NU^`IV_ID8U%=3*(^+"4T1X((6_FBQC)9$PFBUL]<1,]S!+>#PJ[%H<2H0"6A +MIYB7=GGPH!_8+Q:$I09*"\)&%HUP2'X^1_;,\T5=!'^A#5>U*#)2^Z>L/*E5 +M%Y=SZRY&`Q_\(3_!//$I\E.SDZXL)WCSE7*0<#ZW/W*WM?^3CV,,)YEK01]T +MT,<7Y)@5O0':C!S_0^WG/9:,_0!\NG>*V2&:&Y6HU["3TUJ[%2F5'QVDJ49T +MXGT,!*J&0,&"B11L_MOP3I7+N6GR9P(1N,#/>TI'$'P9K@^7G77Y&\%&7G#U +M.(1KPE@G:PEDVEKT='HZIP\2CZXN#7@$BKO\_/`A&S$A2;^3%0VJ0B<>6Z7* +M'(W4;J5SB-RW4&#Z`/N2.@8_6$ +M@.Y1A%M"F_0Y9)K*3PGD$TRK,@"9C'8J9SEZHM`Y$LI/?PG%_42+$3TP@+I` +M+:FR6X1[JU^A\'RX,7__;W>6RC#^PQ8?M\"W+\9N+5D6E<,I6YVTKS#\$JVA +MZ;K0DY^(!*H9_',HH[YJO:)!+$6'J^.N'A`#`W;24DHV[N/$M_I"<*S-?4"H#MX!C`%KOF),."`K?#U%$R3O$^-3L$B +M4!;(W2EW.X`!YA8N;NJ=9MQ+0L:V/,NE<$C'^^VK:'5:ISTE3397ZF]A-RNV +M_0['T/F3^RM,C)6LKU.-W*KX4K%_0E/L1N*_EGPJ.$1^?N[5CQ%1QVWW7=PQ +MRBO*[C$);8)1VXE3/D#0,<6UN<]Z2^" +MDK"/$_T4Y*0'L%^0ZU9V*83*/A7Q58HO'/N:&4-[4C;Z"VG4F*YB&&-DUJDN>P.WW_W/(C8EWN-?5&H` +ME(KXMK!7NU+"*$'9`APUBFPA)L:VI),V)&P9=E5XX@LEL0`6F[B]V<#9XN[& +MRCL*9L(.?C[(@XE%VY>?B<'!&6!:!_F-/_H10MNL_AK01%_7!^2_ +MK-;P"DF0A;4'A4:'>AL55U%9:8*0`4^?W8+9DT"V0RD8LG/39(VE@V_M&V+K +MAMS@CU$V!O(Z>CG.!!.(;UXV'W%\:.5'^#G(S+5'+V!>C07US+?DIUL/62Z: +M&B4VHH.FA1S9(^$W)M3*NTHC:"FCSF;3$8P4Z@>L4)!K1Y*\<:F0-]$9L=HB +MY)E#TDD5?I!S4M5OOCCC'R/!D.`9%'K&$F[4E5VH"YP$-,%9!F'3#+:9192$ +M+UB^3S-M%M@;228EH`````````&9"<41``!4)ENHJ``*_`(``````%E:4$L# +M!!0```!?`$DZ/4N(?PNR0`4```8*```+````<&%C;6%N+F-O;F;]-WI86@`` +M`/\2V4$"`"$!`````#[C.DH'JHS8W0 +M#?$V8!+]F!+4KI<$@5HR#OF&_!+?L]N#167^N/Z\RR?GT6KQ]?CNM8>==$!O +M=?@QVU.*S@O@?_!ZYES=OXHQYJ$K_DR%MMLC^2[U):T3="8KH6E\^#TM[(#:A4]+,_]N-'V@&OOT`,J)*`1$6H.A\AQ<:=18H%@ +ML;39WZ/[&[?/?SG0:`)Z@@QK2DRGY04F&/;-K*Z2%^"N_BP_F6O6MO(I/U.T +M,L^0$-SQ!\_E:AA7X(VUV.Y`_]<]=`A6(D?^?S$N7OB; +MT(0U)^NL7%.Y4Y=[UNW8JWFUU2Z%N5G/Z:2V?%%%6/';]$%?%<3`>;=\3"TZ +MOQH>DR`T^1`8>\&>-+PCS8;)$M]WJ2O3&-M5NR) +M$WG>P*D3/:ZM,!QAAXTJ^?^DMH4:%0+):![`U`''+%K.;9,DM-OWB^)49!83 +MO-XVJ-N?)]_]87HXQ6(V0%4!R+DSR&(F=2*,KFTT2V$[`UZVVMLSI3T^B.%" +M3D->'YYCN2Z9EC%"/S^=W%139%7:"`%-3":\73B.TK]C)8:O)4=W6=.WU7J2 +M@Y#"B90[N&9_-Z@-5-#!_EI#N]D^NX!(OD[^I4G/L<]:Y&KD/P[5G?Q)6SR. +MDWT*.9G^KK"3^&1]@*+P6$#\Z4SCR,)E-_G'AVC:U4C%35O[,9B\$>QS9A// +M4-6)6TL?R;D":$KYVE+4" +M&J><3=ZH:XM&"9ZG5-4HEZVM9YO'8X@P#G1HSFI) +M2W.U-!_N1K4*.N#AAUV?:`+5)2Q\ST04<\TLD-92B`V7$2.54`>G]G_GE!`] +M_IBNF"]3MS#G]1S*N!MZE$UQX#1ICZMB[T'>_#A&8:3CP,B^UU\D$[3QNZ\P +M=]=4'BLWD`?H@Z@Z1;^A03I/VJ2$9]*>-&-,(=@TI22.6-'S#KS*+AT&AY64ZN7$Q'B,&TN<$OCO2W@';2/5 +MEKGSV4@OF10@NP4EBO7\Z_Z/ET#+&R::*OH_-<8/2\VF!^Y["EA#=>3&>K=? +M3^N#$@0V@=Y#K\T!ZU-B?E02#N6U>="G!A6&D?[?!.55MDR7@#`#^[T2I%,A +M+@+0O`/8^4,FN!XRSE;S@C93NICEP.5CEB_787X1B`&3L2FW@E,@?%HW,)36 +M&;CMA--B'7O,LRD\RJ3&]S+/5/3#/?F.Y/5_]51?5DUT3'R5UY.+M +M3HA.NI":EB`FI,"L@%9/?/J.E'FE+AIF8,A&N_G:M,4%DNJM5&/OK\3N="=5 +MYWM9VORAD0```9P*AA0```_X7#"H``K\`@``````65I02P,$%````%\`2J/! +M2E3P*2/$"0``R1D```<```!P`!&(!PA/3V#P('SF^\W3.1N]J/".J]^]]U@ZBN`&LJSNNZ7/6,;7A:'$J$`EH:>8EW9Y\*`?V"\6A*4&2@O" +M1A:-<$A^/D?VS/-%701_H0U7M2@R4ONGK#RI51>7<^LN1@,?_"$_P3SQ*?)3 +MLY.N+"=X\Y5RD'`^MS]RM[7_DX]C#">9:T$?=-#'%^28%;T!VHP<_T/MYSV6 +MC/T`?+IWBMDAFAN5J->PD]-:NQ4IE1\=I*E&=.)]#`2JAD#!@HD4;/[;\$Z5 +MR[EI\F<"$;C`SWM*1Q!\&:X/EYUU^1O!1EYP]3B$:\)8)VL)9-I:]'1Z.J-8JFWEH.CT0J&T-]!<(2-ZX3@)RN\J +MD0J4H/6N:=KFT$;\&+`]@#Q%F@SF+-%(65*CB7!$HAZK&W*TS\4$TS&_-!XUFUI$7*A-;',>)+^5/P,ZD`[HWR.A9G^#C +M-6KTNK(S\@+HL$6:2FA5[-R2LQ[3WK4@G[G^^#%XET%6G82[QS;7(S,^%>P. +MYKA-5S)0G[)N+EKS^1K@1W;SU#4':SY-Q*(HA+6WR\"M,7!$$QQVKNVE\P[0 +MBBWM8'\!):GY@^BZZ/>2OU-EQ9/907=8"CMA,Y1-O?0VM$[ +M,QLUL^VK@(FD@-<=6)L`J(Q]$R2&TIS@=/S2CA0:)DA&H\H`$K>#+BZ#L5!& +M]8O1Y2#,@L6`*Z_D^1@3[G%I48$DK(:8@ZH;WXDD0/L?(I^Z'Y4Y+\D8XG`( +MSAG!!38.H:+L%5M[]Y^`-CTFJ#CX<7/IC$#M`L)E=Z68`.Z15.!\)150B=YZ +M<&XZF>5(BYL_(:&P;,V^D';WU2KR?A0+4-E:0%O1F9`\";RR09,+G:>77.C7 +M]KV`K:4D9*B)Q7-\>:1&]N#JUDJ(<;NGJG2;_\!+&29%3S'E+/YN\/.CP_`+ +M2C&6BOI"R]9V%EB^`F/J&*.2?`KS5D\7+CM*1],_W<7&0.MI\<*%EQY7Q@SQ +M]J35[E'P\:C"YF9--<<]IB4/#I9@9S3^CAVB3]UU"M=C#6^!]'`R!N<"BA3D +MN!$ISF;-DTGCY>18H,[#4UN),"U;=7J/F]7_C]K`/LRZ> +ML--U<[]+X!IV+&GCQ]@_E!=D2Y1SD_+@R,2:B,26E+GCGX,S56]3OA<@OBVL +MP`N1,^ZJXI1U"XKCE:I(CGLU!K\^_VU7+TJ2/;81PC?GHW(SPC^[!L2+DA`2 +MY\B!@>P$N?Z%:.G%!3DJDM;N*"DN*/0 +M.&`?D?G/MZ-/H^LA*3<3>4'L">#EY&"!H9TB4M/1;]:<*%/-*%*ZZ2,FF"T` +M1-VLYD+N +M@QH1*4'INB@E6X<9,1=\T'`K<_PIF!F*CV&59B&:2$-.E\%OM2!\T"\X#?W) +M_\E.2DS4TN&FVR:GZQ#7+A4-!3L*KI`(NX#-0JA_OH3'J@OJ/G'C\>/BB@8\ +MO9AR=;IRPX06AZX1'^R/RE>AE,'6#4](`V?FM0=BN]-3P7I*Y1N1VF>PL"IJ +MGF]0@PM>JH[PYGC*F^0"*N9OI-E(9C^LSD&NHWHEQ=_$X4]3I1L][E,)5C%OKU.]ZXIDSD]%)$8-'2>$@08,C&F")$0X!^:[H:2 +M77[$CGQ]J0)I&=%/9U>ZZ!2Y93+,3^<38JQEC-]%YBW9?`S,U]*_N)5*MF1; +M6\2$>DXDY!G'+D3!)U47?ELRTEI9>)&;2]..PL(AM-=O/69L[N:Y:FYU$4OV +M^,N@H"C'ZH#0&TGK?'HWAY=!0Y!^[6!S_P:>A)^@YZ;N82NGABF]X@0;_,-? +M>;?A^0=`'34QXH8VW08:$;&O]MLZDV-KC!/$@J-K$9[N0&GOS+2GI;?LN)L!M0MJD)X0D:^^ +M)C-S@Y6IMQ)#AE,[..:E&_PK.Y=^1&=;H[0VN#H>-LQAW3+GYKV6I=X6B3=8 +M.@Q5EULK;>80C>Q2*R&+D7DQ0E3,-2X+C]$9NN9R62RYTV[PC,4H>F[\5?A# +ML..XN!<+40H+7WGS&4<3H)3#?4%;XFXM&K'OQ*Z'L*"N<J@/Y%[H1GLJ4SH:YM^-V'+5CKLSP:+]J--=`-B,9Z+53^H2Q]->KE@3ZYY +M\OZ`-KB^'V-<@\MC.J++G-TJ>RS-M>)-3OU&NT5CLUM2@\\A+I;`GDR'T11U +MAW1H\ZECZZD*=!@DMO3,60R-`\W7_X6C,8FB3C-2V +M(@S*@2LK1T%!';G7&%\&D>=1/;=64G$92-FPMB(<+37:DLED52:_VFEY47*O +M3ZKVJ;/.\O<_2Z?IB'U9W2:6S6_,X$F=(#VZO.@V-4CY<68\B@A`UKG0$AR1 +MC3-VV!4W/,85QD39F&!67\SGM$KS:=TRN]$V"EC=+O7\PN8.A__Z)$@0>8,] +M!NHPA*?U=-A#U>OEK!#NG,RB2Y@@`5JNHJR0;9A'3FP'V/.UYMG+D*L*">.% +MKY&BW>NHE92\QT;V$D8_X^)[*WA-4GBAS.]:Q0"SGL>J*KNDX)76,LF["/13 +M[SM72F%\\//WRT1^2GJA553G>V*&$Z9ZK.*:"0K;06@IC_N`Z$&Z4?!2=`CN071_Z=#```````!G1/),P``5\:%:*@`"OP"```` +M``!96E!+`0(4`!0```!?`$JCP4K)N%'WP`0``,4(```+`"0```````$`(``` +M``````!B87-H+F)A$,`````__________\!`!0`+0$`$``````````````` +M````````2\O,237@`@!02P<(1<8R^P@`````````!@````````!02P$"'@,M +M``@`"`!/>7A#1<8R^P@````&`````0`````````!````L($`````+5!+!08` +1`````0`!`"\```!3```````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_zip64b.zip.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_zip64b.zip.uu new file mode 100644 index 0000000..99bef74 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_zip_zip64b.zip.uu @@ -0,0 +1,7 @@ +begin 644 test_read_format_zip_zip64b.zip +M4$L#!"T`"``(`$]Y>$,`````_____P8````!``P`+0$`"````````````$O+ +MS$DUX`(`4$L'"$7&,OL(``````````8`````````4$L!`AX#+0`(``@`3WEX +M0T7&,OL(````!@````$``````````0```+"!`````"U02P4&``````$``0`O +)````2P`````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_large.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_large.c new file mode 100644 index 0000000..6966ccb --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_large.c @@ -0,0 +1,94 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_large.c 201247 2009-12-30 05:59:21Z kientzle $"); + +static unsigned char testdata[10 * 1024 * 1024]; +static unsigned char testdatacopy[10 * 1024 * 1024]; +static unsigned char buff[11 * 1024 * 1024]; + +#if defined(_WIN32) && !defined(__CYGWIN__) +#define open _open +#define close _close +#endif + +/* Check correct behavior on large reads. */ +DEFINE_TEST(test_read_large) +{ + unsigned int i; + int tmpfilefd; + char tmpfilename[] = "test-read_large.XXXXXX"; + size_t used; + struct archive *a; + struct archive_entry *entry; + FILE *f; + + for (i = 0; i < sizeof(testdata); i++) + testdata[i] = (unsigned char)(rand()); + + assert(NULL != (a = archive_write_new())); + assertA(0 == archive_write_set_format_ustar(a)); + assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used)); + assert(NULL != (entry = archive_entry_new())); + archive_entry_set_size(entry, sizeof(testdata)); + archive_entry_set_mode(entry, S_IFREG | 0777); + archive_entry_set_pathname(entry, "test"); + assertA(0 == archive_write_header(a, entry)); + archive_entry_free(entry); + assertA((int)sizeof(testdata) == archive_write_data(a, testdata, sizeof(testdata))); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert(NULL != (a = archive_read_new())); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_open_memory(a, buff, sizeof(buff))); + assertA(0 == archive_read_next_header(a, &entry)); + assertEqualIntA(a, sizeof(testdatacopy), + archive_read_data(a, testdatacopy, sizeof(testdatacopy))); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + assertEqualMem(testdata, testdatacopy, sizeof(testdata)); + + + assert(NULL != (a = archive_read_new())); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_open_memory(a, buff, sizeof(buff))); + assertA(0 == archive_read_next_header(a, &entry)); +#if defined(__BORLANDC__) + tmpfilefd = open(tmpfilename, O_WRONLY | O_CREAT | O_BINARY); +#else + tmpfilefd = open(tmpfilename, O_WRONLY | O_CREAT | O_BINARY, 0755); +#endif + assert(0 < tmpfilefd); + assertA(0 == archive_read_data_into_fd(a, tmpfilefd)); + close(tmpfilefd); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + f = fopen(tmpfilename, "rb"); + assertEqualInt(sizeof(testdatacopy), + fread(testdatacopy, 1, sizeof(testdatacopy), f)); + fclose(f); + assertEqualMem(testdata, testdatacopy, sizeof(testdata)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_large_splitted_rar_aa.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_large_splitted_rar_aa.uu new file mode 100644 index 0000000..a6c3b3c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_large_splitted_rar_aa.uu @@ -0,0 +1,892 @@ +begin 644 - +M4F%R(1H'`,^0%0P +M/&L'[WB2!U7<*?4L4NOOUTT.SR!`I\R[_P1F=02HR>'QX8'^2HV&5JV`]-KQ +MI+1)$DI5RKBB(D_C'\_+]51?<,M@,F]PE+VS +M]2/>+LTL^)KUF2N[8ZO?.RN>$#S?0H]0YSYGBDJB]E^_&DDB:%;!B8J8GW*J +MO9*/%:M1X$FFP^&O`[RU:XM%UY]0#EF9\,:3">!<)ETSY)F5GC:.-&AY:MMY +M?U9WS&?(9@3"\/]9=PU??)T!9PR=N(\&#=,WX8AKH;:/SKE13]KR`RMXSC6_ +M^IXE6RJ:_VX+-U:3J`1R_HK<>S2[KP=XHKKNY&^5,X`_EJ,Q%SP[P=:;DP!V +M0!/%2"66A!1(2(+-#&]E)ZM83H-(N9*;>3I['T&=*&8?"1L$%$;3I6]YGM7D +MA@WYC]Y1YC(KRNJ.,K9ISE/HX0L[5W!@N8&,/@KJA3[(SRV0;9*#>[IC8&(O\6E?P5CO+^4Q.EB +M@5_+,2,=*PW'V6\5:'`GU$42X'+ML^24T+V!U"[7`*WU5Q]A$I;.G*JG3N>M +M(\%C1N33':_HHW*]Y@\[G\VP2BSYTEQL1Z8P$U-TE)M#',SS=QF:;,%!X>FAS*\$LTE:N;-E6JH>UCSZ1^*'21$RTA7<71W\*'6M7UH/$P-#82?]^*:&%&S?D\9SP=W8 +M=U"D#*O8TJ'PI?QPA5Y[1`3&LES]V4]=\A6GM]#HQ+($<>?RFPOA_\/#^3H) +M9M3;PAY%/JU7%9Y??]05JHLVQ:NH:N_*K(KT^-\AHXKO`8\.G#76!Y?X:87E +MA&>X_XI=4RLM_#NXEY+K_W!;ZRW]"9D4GN7+!"*$"@E$<G,@,C`8B[OV4TA+G:`EC40T>@O"IY@;Y\2/JDD=V1M![(CNP(_,E2-0U^CX,9BJE=-CP^H-4\+4& +MD]^J`VAH[`_"EO\Y>#/O3GZ<`Z:6=C5[_!MCXBCD:8T=_894T$+.WU/1Y`8*W?RV7BIE:8CE&#G* +MKAR=I-M!\(2SH1`)U-_43!QP@2?TY36!`,FTEU"+G+UR\DX'0Z_/'SUZY'L\ +M<0WB\\&R.5`B`PTC#+4,\88"E0R2=P3'KS7/-:4F*.?&)JJ,1Z$$E`D\_G]: +MV`NESW?*QT"[,@OLIS&%#DX>O6[@;#9Z`ZT%+:?63G07XHA.O=(S8L_LA_@> +M\]+1T#1TE;]'*1$!&)GM0DS/_Q)^T>D@@/DD!>X+:`L4GV%@V((T>B"H_:6L +M;'9EB0&Z^8*/S-%;`K&EHFW1R0IJ1>OW_*'\4"G9B!S)($G=ZU?\%SA7*9M^EL80./SNR$4)E*K:0!TT,*59F65;WNQYN2Q.Z,L"-H?=(U3A>/=1R/Y!KMGFG!/%DY8V50XA+>J82,Z"D#JFCD'!XZBB48\M\!4L<-&XPOV&.MBD.".V.?&$P1P4SEWX]XVYY +M/DM9NEM8RJBP@JX`MF#PDC*4T$Z1ZZ%(V_XY#NX1+B8%\ZL>P(`W9GWOQR7: +M

    +8<3CD!K`P6["#A8H,+&2R38"$I3JG>X/>XN:(7?G\R3GA;7`/=)[X,@S +MH"RE$#HVN0_>N!D3^9IE^DGBJ9V+YJM@YIK6_%4=OUV8U!^^(JX8"/)T`5%& +MTDD1HCVQQU=MDJ7]J/"5:Z4Q!0D@T'X=<[2(L_>PSMH*)HHVI-L$?3^",O.& +MT)16KLM`NPY``"J9YM+&Y^@'!?(+IPXR-`84ADYF:`&7!(*#Q@Z]BBE@.1:A^OSG:9$M^[];\N@Q3(X+W +MLW3&;=A2([8<"3P>I95^!NIMJE^YJ5&S6(J`/T!2S-,' +MD6)@'GHT\L_2HV$04ZU\SOE')DN?ASL1NN^^7:V<[)Y\I*EYV;0WS5FYD3!6KRFYFE5CFI??*J +M-\ZJE,,<%,A9'!"O8)6/WUW=W@R<[=$$<1D1#G@4N:YEA(!4?2'_\H4)K'I` +MKQX_T=8OD1V$QU'F.652T;$^E!V!\%GRF>6J@J%#FTW+I/CY_;U,E7%R2F"W:/F]OY +MT`W/7T#4Z=_;LS/5@2B`\A(2,WZSA?974DF3$<^RA?!ACA!^T/=BR4X+!8F3 +M^V075'/DF0UX9\E0VYNLUQJ.-$%SA9?S +M?8%ZQ#'_7KP%^D[YB#`YBS9'R-1]I1"2N1X`F!NO\Y +MU2FW]K[:,QOI# +M>G6&B3`V%ZV1>]#E':8;?F6OG8V^TQV;15_5-.W1-`CK,=C))^_Q_AF]F.H1 +MSAN"WK^*@1VTQ-&^[`74F:5-]?1;2U:NB`W][#)$@S:G:#QRQ9<)?V;4ZD7! +M-M(9_<.&X+E3&KHS/ZT,"@J!4[HEGW.#\NPS=&7V&Z>>=?0"-TW"#E7/V3CW +M_*1@*VI;B@^?21EF6?.^)_UN@CL82I]HIT<;:R<>@2+;+#RMMY6I*/U]FZGQ +MINO=(L/3*#_E5U3,F\8F_^)ZI`^%#0TR`*7(=M'GAH1Z&W%%SMK%$S(`QE,* +M^6?.6MVVEA^H`Y>:`Z^<*,$Q<"02QX)QTZ;O9%YPH;K('*2`L;>F?*ZC0C^Z=G4^9(Z)%V9Q"G7_SY +M3!5I`B]/7H@7U]O`LQK!E,?3E$805$)KX47&Q-WX3RB7XV?S87X*S5;_:NQM +M5*7B3"56.2*M9KX!S[ZZR'YP-%++:"-V8:N'\Y%8HAP+$#WA*[C(+H9/)APU +M4E2Z:^Y:R%Z^]Z3`7?QMK@75!*C8YQ^2P+0'?Q"%Y#R%#PY?T$G""_TAOMOQHP89`J)7F\@W+<_BQ/#K!1_L +MAG]AD:E2F-"8]9EGWWO2_;$9R'?7$LL^Y]2H60AX..N#3IS1:;`LGOI![!L;C&Y)[`!-[XN#[5[/KF@*1866&"ZCC\[ +M#$*J]$%)"`#2V0FJ(>E2E8+H%]-05@+:Q0^"T&".^`;FHY$`!9IT1 +M:&R$ENRQ2$>1%A#&*R\466G@[JE7IH$`0$QBN#^#<^>3*/4@&>V59O$BH3JP +MKT62;#2"-^$8UR_#`H_[QL4]`XF&>SR3?@@3BX<*_JGC<'%5I0!UKZF7<7PSKFV!,]9X0=>Q\YS"+>G+V;#>"-"%-) +M1:#D=1.TV56\L3$1T/BORY6(_1U4=%8([W3PHIR[N'6+5L.G:NJ`W=78>FS+ +MG)>MXH:?N@U`&MJQ/P!F)D8/IFOA`*`51"H5&SFB:@@E2%,G)!O<[(BW%`Z+ +MFD5DG@I*@0]`X%3[Q1SH?1"=E.^ICW38DTXRZ7,1T=&6/("@U*2!7J)J.,00 +MT&7*=+9DO<0Z3W$.49(DMD':OZV[$'2VB+GR@7\@71JU(9?8F*!<3)&)*)@) +M8"[%UCD/\7O>/4EKE,440IR!+_!)AH")KL8J\Y1[0_LR4`I@JMCEH'M%T)8'[3: +M.7`6S#1:?%1#*>54`%8Z2P4#]S%B&_V61"Y,)("&PB4(`.?[C%?-J(?!-P_V +MKA:8H"G!Q2H].,.F'`T0J5+ZRVZ85AWI*N1B`8XOP7B<'#.;CJ*`G$9U%=O3/OVUF-OYYO3*G0K<[Y"%JX +M!X'#3S>P91<8Y-M-Z(0"Q_5-057,XS7*28Y')2*J7JJ_YD_SM7L@9-%NE)FN +M69TZ[;P-E8#\Y4AARJI`$6'](`O\MU7WIY<+CZ"*D/S-9[.=><+5K5G@WN"` +MB8:KHE*C_Q;\H_)G++W<[U"$K08NWP\U=SCFS"-;X;)SD4^*G#,CA('):_*S +M3*`"[MN"U\78A]Y^<=^7K^$FRTG\'>_SJCL9T +M$M"4ZUHJ/0EA^[PFK7Q;A(]-XN"OH#6$UD_>SG[@H><$6=?N#&-( +M8U!+]F`_72)=<[]`.?T[V@.OXQSLP$L<;_U]<"S%67%`?#N/XP24IE*&:FY/ +M/]><-A.`]LU1CP7C['B^B/\F5@IV24JC-_9TC0V_8E&&P13B^PZ`,.60P+_0 +MYN4)5L%`9^^!G[/#2>670#$FI9ZWD$^H[Q4T5X8!>3*5O-JJJ-@U7'!G(I[[ +M1".^J"/]&L'`?EZ/V4Y=41%=ZW]WF@%YSJW-2(I?"GK[)$+7C@I[D?FE2XJV +M#'61D;M2X2V.KG4IM.HTA(%3TZE:I-U)?SC>R.CBE3.!;1CDHOWK-,3R+('J +M;Q9TK_=H>)E9'=DFIO'7<4DPL-C"JG2$'P$^SO*'",7=;Z4M--IOR+8L77 +MKFY%V);CG'\H4(:WG65D!7T1\L&YJ[;J\Z!!]!>_8L@4\_+%1F)!]--)`88$ +M?&?TR&;0;@%<8[JA=KB)Z^:U5^;UT#O:.WTN^*GWC)M);IF@=[&ANVG)0HN6 +MWI6)5XC5T#-U5/%BTU]+&LQ%-ZL#+31#NZ,W6^VLT+E"2XDPCM]2D?N.6=O3=E'0I3B+-)_8 +M8N2D[;@(>GVU8<>K^H:>-3)/469((HJ<;6CJ=KK2X!'!\58]OVRT\[1DV%U] +M]+;#PU7;O9`@&L;N0[U2Y@W2A-BOF`(W&&K0H,S2"5<>AR;@*^<,IOOFQ!U'L7^$Z\_D.?L;QY3J$>,W +MN$Q\]NFT?*;NZG_M#+:\_QZ[S7@V;?[0&J6__G*)]4W)`\_0^XZ/R3:#K@K6 +M:\'O[:!@B5S11B6L!7`+;.HUC9J$NGM(-^_$H//_Q^>`S:\O3"18!4__4F7R +MH')EA?'O33NS:7&?NTW9`?JJ6LS?_X^IPYJ!Z-0=WP[O,1K_W1`?[$7WE-XB +M.2OL-@GHY[[M]81'*WAM.[/'#)RHM!IZQG]$)PR][O1P[*4$8GX.\RJC^Y!) +M@8_V`(]5%ZF?!0$W5GHLA@ED:VDN?@V[C,*97#R42-NTMYJN?T'&^9*DHBGS +MW7<>Q=B%,(O&;%V222=;"N<4?;@TEI_N7=;L5%TK7H#G%&V$0W![+EJ#/];- +MJ5_:YB?0ER`ESRD3-"*;?]I8P?4?,0/%B;.-+Q*NFZZJ,3HU)%7["@!H"059 +MC#IY""-+"[C-/08(4I>EA*`;@(<$$AKE?.DQ,&/UQ0/K.V5HX5`-"?VMV*WQ +MP$G>?H1+KU,LQ3-+`GS.=>!$H2PGKS.OOBUK-<9'X/"]'FR$S]Q4S@]C"MUX +M84HP;6F6I$9PY<5N.A]:,3AT2Z:7X!.LW"SGLX&1WZ^6:U5`^%VJ*"HJ)2Q> +MR<@`'/+UQN+QY`D;S.@[Q97M"YI^`V2LX019:A-4J-C<8;Q+2=O_VI+4_CYU +M$P$T]ASI5Z2NP1\(W4NS*/O8Q1Y6/EUN*]U($#<#']T?-7OZBK:C5*8$#\.\ +M`.?4B6B?0H.VGOEB?`0L$[CWO0RV;PQG[]YO4([OS^KUC!*VS;,:7,B@%/B- +ML,D]E.)F'Q)BX=J>QGX66+-A([-<4XT!"502XQSFA0'$.ZXX!39$L*F)I?UU_TX"L.M-<1SPH)CSO_O +MA8MW[+D&\>VQP,&#GUYN7_]:`O*R:X7CX8Z!!BVU2QBP<531RE'BN,(?(.K$ +M_/1ZJ6?\ZWC_%H$EZBK^[><0D/]$7S^D?T.:$(4@*$_V +MZ(`````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````8``````````````````*$OPP`Q?VO4_^?______________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_______________^@$?\B__K'_I_________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_________________________________________________________Z!' +M_(O_ZQ_Z?___________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________________________________^@3`'1%0R-%\6=F]S/A7.S +M5W8"T;9`[O=G2*&IP\3W2`(833>H2:8/`,[&-M/&Y!GWK4@ +M,-D75WT2#SF#E*Z5VOR5^KBL`````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````````````>K] +M7T\[_GZN?T/^/I_GT/4O.Q?SYW0Y_K]^YZGQ].4NQT.+`?0]2.AT80FY^38M +MC-UH&0]R&?>\/3Z/1^X4ZT^!N4Z4:9*:-$CN+!,AN>Z5('3INPWS_NJT>I`Q +MEA^_#-(OO7'F?`N31Z78C35VD7F4.&08ONMK'Z/IW^>?SOHYT6)%!7H['=ZO6]0\WN9L] +M'/S_R?R[&QY8,@B&!L_=C>&?P",_X=^*>'IUO9+ +M!I_[\_Z8<@.GXJ4\>CJ)&GB\`A!8TU=.$"I:?N=I]G]/<]'-T^M!=`D`XCE8 +M!JN7'E&K`DR"8\?V]-7J,5K7UQ5'<+]FEU.;$!Z4&1SM88*"?3W?+[\X)U>A +MH^#]#>$#56&'M?;J>.KMZ57@N-):N7[XVZ;1QQ;]1WA815)8\@RDMF"/+!(/T>IU? +MWK4OKS=:NG&%]=]*GRD($O%=%K]D%*E2C([A*)0WS=*OR3)?UZJ?1?%ZO+K] +MD&B@AY_W88M'73TMN!`>QOM7_-,4)_7>&W]L&3[?T^O_CYNE>^5_+W/_:R>8 +M&Z.WI9_@C:M]"Y\/W4G'3^Z+?@@J68M.)BZ/`ETX[^-^Z"[SJSX,)F&O/0HZ +M0PV66N,;O7>B\5ZX_>#AUFU*WVI\?&E]W:O[6[?0GQJ>MOWGAI^V)\"68D>& +M2/QE?L_#D"*?D5ZV<\L]1++_QO/P@DUZM6?[Q$%DXZ$[R\N0FZ([,@15!+0L +M!=9%K?M7= +MA:YU^7TJN7R`O'VY%71U(S)-WO;4&+1*YXM.65%X90P;)CC4=H$29N95RL +MRS#O),+>/5R.$9X*^/#N=GV$-TE:7,^."D3YWR48+\6.9(7^'M%":>`)GZ4R +M:N*>"^03M8ZJ74[FGT3>#9D960OE@UX%O&6._ZNJYLCB!,W-B\[)W7['!:PB +M\'XY%V/XRP=KA./R6^X<`T;BS9D,V"+I;FS-Y?XJ$K73X^QY*R2."*'P;UJO +M7E$H&N\X@/C%[1L5_;U7SR]WCO/9):4Y?(EI+>S$%V\]''EIWE6,$>6(O@+3 +ME[G#\?");LM@E?-3?CP*;D*S(U:ON4N?E<%T8)JF54U2VJU7FD,O@Z>QJR-2 +MZ]$'[.JA1.GM]KK]*3WMIN@Q8]9=O^N=OZ0OF$'83HEE&QW&8=Q9SC&7(HZ! +MT\56]-ARZ0CWLE=RG0:U[2V)E.'_K,KXFGKD,JPH2W)[CP\?_D'<+S8C_%+] +MEF32B&FU2Y,@:1B;SG3MZD%#;'BC"9%TM*_796%NG31&MW62'&8VV7G2&W*2 +M8_"I^'X>SX96^#80^^+?/@?3A_FU&%BKB"A6'M_R+O`W;3UFK8'X@2EPRF"B +MB.C*H#7`0[(C!G>Y?E@TZ^!XL9IZ9E*Z5Q"L),WOXAO=#HS/?P^GS03$?ROO +MBVREKR,\I>K(/.)^J/,R(!][,]7T6A38[L;5*M +MPVE56+MFK`W=K>U(0(/$!VRF)'4[YX]$*QA:#)'L^(WZY)E"Q)1K^B:IO3ZK +MA@.6L6=`"_YLZ(0Y&3%,0_)L67=S;-O4#B,0'6 +M)R[=^,ZP/SWX0 +M@&.8'L81\%H:KS8?+YM;=WC9+O^/@B!''YT.F5OPU\[;]SX+9M#%'>I]%&&W +MG1`U:.-"-[8';;(*FK?I\/LS.-T9XCHO61;2M@$\`6CG'QY4.\P!GUA3?ITK0 +MCW<&SL8L,37TB/+XZ90SU^_0EB>ZOK]_1MDA*F4]:`/,ZQR;5C2@1O+7Q/$52F4OGN\/,_'+"G,R[7/2I +ML$FBRTX>+,"R`D5>')8'I&,]:7?]56WD.)^0#G"0U,68W%CE(W]/6PQ0MZ). +MEB[;?2AL.OC$%1A/+!#J/''Z]?K%@_&YC/\*V^;9#_'SSHD]N\V0$ +MIHKP^J$Y6AY=(?^EEA[BZV[/+6@$A"3V*>`XXEYGQI+%"%?@DKWC,5,9XRBG +M(DCB3:DC7,O:X1##E0=;8G*N,KDE4="68,2VHU`0SLDRPH(H$Y%RN%;TG->M +M7CEJU'K(37^^OJ7O,S+C%JL8X<2NN"?]\NON0;:O0Y^=/?!#'GEP9VO@VX(# +MO7]M?X]1HA445@;>0V`BP8$E=-_:ZTAPQIY[9A\I2Q_=L9@>&,5(2KFQQ\4* +M*J.*B+AW*?*`5[E.3JD;5XL%UE<[5R+HJ*^O*J4MBU*7)5S4_#J\_&(UO +MF-HZ@43FIH#,4-FD4T6"!9<O"/P;L9Y0\$;5>\< +M;Q]KP2?\5:G'1*;2JR2L'T?#/L4Z- +MGC21?PUWK.CGG+[7ZT8.C)'8_7G=L6D8=%L9<$O#1RM>'TQU#I3K..2U.S!< +MG1N#^&'R6-J&&N&RG5WZN95X/S(V[ +M2D03%@"S:CD[T],"*J\LOZQ]K+%H3[(9Y<^Z0#>U9D`\NU,NSZ?:N?X/3?QI*:J(L6>($A+QV[!$AQ8)46R\6"NEJ5\U?;TP3K0" +MU=5=I'H=;4U\[\8:5_?#VZO-2-P(!N,YCV/$&*U=*H256[0JSR89H)LY4XPT +M5TM\KS63+<@_!J;63WE0P!Z//K2TON'^XDKUL3+KA +MDX)KB4#CP3?2";-\^G*COB>2.&;FO5]JT=/^7\KM#RYKM7V_K5^E%>[Z/*X. +MTR*_CYZ_0DJ@8/1(I2Q7S@SD>/^WD&=5=70Y2B]C4!5^7+IL)S&C;)5@>\6# +M5ET-3EI4?=W.`GG8I@F2(!!$:V,5]4?O:'3\5?+%^M66W]%&>O!"[MZMB$/D +MRR?VZ4"2L?S$[1D#@=M95,6MKTC\C&%[XM+Y[N">&]*BY9?3`;8O;M>-B?KQDWU&&LKY +MO*7BN&Z)?.1LJ9O&\SL.%4K;C4F@!9NMF:=/8UM.OVN_[WZR2-K._^\9OGE/ +M8Z4/D)G&82NF::OD)F;4KU#B?LB_ON7)G*2`48/P@BRROKP^*$_2R0G^YH=[ +ML9>R6.]N[.33"H=?,_CT.?FQ98>3V_Y09`[MO>)F+Y9DU7KK_H\=2!=E-_'L[\&W'RYVML>6W +M2B5XVTKCM8$=QWDW7T)C=H/2`M>F>1Z.EFT89XYM6]Y`.74[6+UO9V-#+L2* +MRG?O$G&H]`_8.C5?AT",*;PS'GFM70XN>WV4Q427^(`*\/X#CB^ +M$(`_Z;QM?B78W;%ULSQ]SP7'831UC7'T-)1'M@\&T\A :U"^,-";S5OB:6 +MG$,M^1P8+(5[>J-K6.5*L'$0+)C=0HM;#!4F--U/NZDV&E#R0UWL[7NQTR?( +MK-5,,P+(U-G9HX8/FZ7$?96E_ZGDBWBI,:/#Y=^S;#LY:>^CB6&-NY)Y7X[_!HZ6Z,D&]`WT!%WRJ<9];OD]9 +MY>24+=]B3T1H[A.%^F.1/,DM#4>!\9]0K>"FYBN[!+*PDPZ'TMGH"-NLKU?X +MK&8!'XW9[RE.P5>/,E6Z?%N:LC`<1CX,4F<@B!KO78!YO$IQ`''Q7JO"IX\? +MBBR#]:TMSQ5EEG7D[+^G+:=BG2QFL>/BO +M-QZJZ$.H`J_PPEC.-JXBK7]T=G#'\]ON_/CN":U"TF8LK:^LVXWN3E`F6;_# +MF@\C#/D]9LWKT#%HA\3BFCW4MIP#\!5<]$0Y$=*]?;JE'.^>7#5O5WUX9)44 +M:))UM76AT?_M55^=35MH +M8SBP1JTK'D6Y=#^?WQI>=*9C8FR=6JV)]+T%__'6]A[DT)F]% +MM.9/8%$580S)=?9\16F`[F7>"]22&A^BE$`:%]89YK8LMX4\?*>YWLG)25RK +M*.K)901`V]&IJZOJ1J_6GW!LR>I^"`[07J:]@%V?5BQJ?SP/;WQ=6$)VG)G> +M,CD;"*2]BO';UTABY)#56A_?JZ>CVO<+0[/9T^Y#1S1\ +M'1BO@_7G[F+:SX]=K^LYM7V:F+!8@8VWCQE9ON?5'U;4?[#8J%5Z%VJ6=4&'1J4HO;()4E6Z9]B#F&EOGA"Y]OY\)@Z$KQP\]L>4<',^O+3P:'OZ[N0-$59`T+&V[RU6]6;[V-V/2 +M\DOQI9RJV8A[VJ&3N-FHO1'WX^C$`6&2L/DNQK)5_WUI\QDNC?X],*1X0H=% +MT;6[0R[0Y+&X>-&5*QYNCCJ;63LCPVSZ%<=8_&<$7YI5O82X$^Z<##T4I_XS;/-5[M4JN)*<.,PUX=<@21*+8?\@!8`NJL$\VJOXQXJ9_D +M3.WKH>4UTR@[R57^/8HS5-09>'[^!EC_/B&H.[#.Q3A=.O\W-$D=K*48D@J19KZ-UX@W5I(05CF6[ +M[(CXM-/'Q^C,.*&X3^7'/##8'_F>E+Z+.!7!K[5XEI)C,E`)2K9=PC^3W!*> +M/=^JWKV#J"(QKCPP6:'6E9)Y.J(:%'W-59W0K-G+@+-9/@"A""&TDQUZZ*Z!(7K==%W;K&"$J@J +MALS;75>P>"E5\-;N4E/M +M0A%P9LKU*,B)FLB7(LC%+GP-Z^OAE/&,`'46Y6\TGV,SB'PST\;25YCUTI@) +M"8'KR_&OC2FE?A7ZGV6/IWY1];IKK:><9*`-O+^*CC4T2?\3C +M_M'7BFGLD;Y)8-WV+?F70"PKR_K2?DS;!F2K#Q)U^)[$X!XV5*%UYZ=7A]'N +MJRJW(KWG&Y:)'M=LW^%%XYMC7J/SQ2BQFE=9%4H:KU#/U&Z)XW&/F1DY^*&? +MKF)^:[Y;RQ8402:`0.G!SK912WR+3;6S1-%I+>%40ZT<0YQAHQO;* +M\@_]:\Z&\O@X6JRH!7L'0]=%F\#4G+=W3O;]?@ST(*H"J*!>=9,1I"NM^<5$ +M,?M3##_F0@61;>:`LF\VDL')];&<]T56:4]2!OY.9(`/*6V>1@]'8#"*GU77 +M;#NK:^GSZ[&-$_(WYR<(5I51ZVR&>0E=MYM$UWTOV5=5'&,CR +MBKOW;AR"NES,-/?Z>M505*><)/.8)UL,A0CY:\.+IC`GC%8_TJ5_HG*`HW#K&]2WB/L(8";`73ZE8Y;1D(J@(T,=])2H!$P7 +M0R:0/B15*(]<*@J1D[43+>O$MZ$A&')!G0?"`I/RWJEW*L#<#D!I$\V:\",/ +M[J!XYT&0)B+9L6#"$>!0#V` +M*;I#]B(J/TC[I-H4P\V$J3&_7VBB^Z,]'9,8PUO5QM2^Y5?P +M1\:_.IO%T4N"#U2-1H8Z]$6"3B%^+CQZ7CM4]>!+A*F1!\CK@_PCBB3,5V$W +MFK@M_W+2%)';;*J7&Y01`W``3(_X7]KVPYX0A2`H3^W1```````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````%`2_#`#%_:]3_Y________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________________________________________________________Z` +M1_R+_^L?^G__________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M________________________________________H$S/],17/Z59'_P````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````(``````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +H```````````````````````````````````````````````````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_large_splitted_rar_ab.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_large_splitted_rar_ab.uu new file mode 100644 index 0000000..4386978 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_large_splitted_rar_ab.uu @@ -0,0 +1,892 @@ +begin 644 - +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````<$P!D15,C1?%69OLS\57)BYD!8-L +M@];U=75W=75UUWO\E7H1>5Y71JE=*[7B5_'25@```````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````````````````````'J_-]/._ +MY^KG]#_CZ?Y]#U+SL7\^=T.?Z_?N>I\?3E+L=#BP'T/4CH=&$)N?DV+8S=:! +MD/EV(TU=I%YE#AD&+[K:W*S.+IFA-XK6PCAG>]/1MA@BZ+>IN +M;?FV/5K\`7._LZLFFI_:#WA^CZ=_GG\[Z.=%B105Z.QW>KUO4/-[F;/1S\_\ +MG\NQL>6#((A@;/W,_?N@?:]/LV?OB5_U%8"A>-<1:9\!E!D<[6&"@GT]WR^_."=7H:/@_0 +MWA`U5AA[7VZGCJ[>E5X+C26KE^^-NFT<<7,CJC//*W-']DS2Z=F9DJ9!0/G6 +M>*0C4\UX8L_]QUUB@T5ZXQ1$-.,&:[?FC]D)`YYNG74?;3U_=?-[G;TM'P:< +MLXKNNL0-/7&R#>I`2I;4COU_54TGF_4=X6$526/(,I+9@CRP2#]'J=7]ZU+Z +M\W6KIQA?7?2I\I"!+Q71:_9!2I4HR.X2B4-\W2K\DR7]>JGT7Q>KRZ_9!HH( +M>?]V&+1UT]+;@0'L;[5_S3%"?UWAM_;!D^W]/K_X^;I7OE?R]S_VLGF!NCMZ +M6?X(VK?0N?#]U)QT_NBWX(*EF+3B8NCP)=.._C?N@N\ZL^#"9AKST*.D,-EE +MKC&[UWHO%>N/W@X=9M2M]J?'QI?=VK^UNWT)\:GK;]YX:?MB?`EF)'ADC\97 +M[/PY`BGY%>MG/+/42R_\;S\()->K5G^\1!9..A.\O+D)NB.S($502T+`7)*, +MXVA30M^,A459Q'!N;6ZY-6C.JLQ%/Y52F+3EE1>&4,&R8XU':!$F;F5"OCP[G9]A#=)6ES/C@I$^=\E&"_%CF2%_A[10FG@"9^E,FKBG@ +MOD$[6.JEU.YI]$W@W(N.VC[-#'%XX%/;/1[?R_J]$^'*EK5"=SZ]M-^"&:S1 +M.;ZGV]C8C&N]&YQ8O$9DVMW&$,ZZ1FT%>RLK\VW58,-CWZB"XF"IO-.*_;$R +MS".=Y5A(MHK9-5OF.6&E)2(BI"WSE*K5QC`O^9R67Y]C5FY)L.*-/U(/D;#* +M)DM75HT%ZJ9OTK,WF9&5D+Y8->!;QECO^KJN;(X@3-S8O.R=U^QP6L(O!^.1 +M=C^,L':X3C\EON'`-&XLV9#-@BZ6YLS>7^*A*UT^/L>2LDC@BA\&]:KUY1*! +MKO.(#XQ>T;%?V]5\\O=X[SV26E.7R):2WLQ!=O/1QY:=Y5C!'EB+X"TY>YP_ +M'PB6[+8)7S4WX\"FY"LR-6K[E+GY7!=&":IE5-4MJM5YI#+X.GL:LC4NO1!^ +MSJH43I[?:Z_2D][:;H,6/67;_KG;^D+YA!V$Z)91L=QF'<6TMB93A_ZS*^)IZY#*L*$MR>X\/'_Y!W"\V(_Q2_99DTH +MAIM4N3(&D8F\YT[>I!0VQXHPF1=+2OUV5A;ITT1K=UDAQF-MEYTAMRDF/PJ? +MA^'L^&5O@V$/OBWSX'TX?YM1A8JX@H5A[?\B[P-VT]9JV!^($I<,I@HHCHRJ +M`UP$.R(P9WN7Y8-.O@>+&:>F92NE<0K"3-[^(;W0Z,SW\/I\T$Q'\K[XMLI: +M\C/*7JR#SB?JCS,B`?>S',6^[-)MF6D!KT>KW$@3(G!Y*G\C\&=M^BCM5E-J +MF5GV="Y?,WTA1]>5[YY2"EY=B@W4D92M\(W)C2X)\'O5]%H4V.[&U2K<-I55 +MB[9JP-W:WM2$"#Q`=LIB1U.^>/1"L86@R1[/B-^N290L24:_HFJ;T^JX8#EG +M+23(L5CWXI0<>E@NCQV!VVR"IJWZ?#W."E69,E;N6D1QA].1D/-@3!LTZ21Y&L3=?!MXT]Q^\ +M"@\2+\AS>QU1C_?(&-AWY&=ZM2L/W5Z*0"EH!E2S="%%-;8U-7%#R0J130TY +MF=2OSU;-&S'+CANGK,SC=&>(Z+UD6TK8!/`%HYQ\>5#O,`9]84WZ=*T(]W!L +M[&+#$U](CR^.F4,]?OT)8GNKZ_?T;9(2IE/6@#S.LB3I8NVW +MTH;#KXQ!483RP0ZCQQ^G.NO7R*W43+\R":5G4`$X9UVN!,O^03EJW5!F6RN_ +MCS@AW-+>D`;.@372'_I98>XNMNSRUH!(0D]BG@..)>9\:2Q0A7X)*]XS%3&>,HIR)(XD +MVI(US+VN$0PY4'6V)RKC*Y)5'0EF#$MJ-0$,[),L*"*!.1>V8?*4L?W;&8'AC%2$JYLY3DZI&U>+!=97.U4/!&U7O'&\?:\ +M$G_%6G(=&K1N+?F7:"^X,+FCH5:1/&](^6JGIQT2FTJLDK!]'PS[%.C9XTD7 +M\-=ZSHYYR^U^M&#HR1V/UYW;%I&'1;&7!+PT#\R-NTI$$Q +M8`LVHY.]/3`BJO++^L?:RQ:$^R&>7/ND`WM69`/+M7(R0=P=79>:\;L^2ZU9 +M7C+L^GVKG^#TW\:2FJB+%GB!(2\=NP1(<6"5%LO%@KI:E?-7V],$ZT`M757: +M1Z'6U-?._&&E?WP]NKS4C<"`;C.8]CQ!BM72J$E5NT*L\F&:";.5.,-%=+?* +M\UG`5,@7=DJO:WDRW(/P:FUD]Y4,`>CSZTM+[A_N)*];$RW->5"%N%)MZ7V[ +M<6/7'8YOT)*H&#T2*4L5\X,Y'C_MY!G575T.4HO8U`5?ERZ;"K8A#Y,LG]N +ME`DK'\Q.T9`X';653%K:](_(QA>^+2^>[@GAO2HN67TP&V+V[7(QR=>TA6TZ +M>QV+DJQ\$\FS1[L2UE=?&N6+FUY2VEM0D1B#`ZVLGGC8GZ\9-]1AK*^;REXK +MANB7SD;*F;QO,[#A5*VXU)H`6;K9FG3V-;3K]KO^]^LDC:SO_O&;YY3V.E#Y +M"9QF$KIFFKY"9FU*]0XG[(O[[ER9RD@%&#\((LLKZ\/BA/TLD)_N:'>[&7LE +MCO;NSDTPJ'7S/X]#GYL66'D]O^4&0.[;WB9B^69-5ZZ_Z/'4@793?W*S&5AB +MF5(Z+#&&O8R/+QBW.J[5===>%4H>]+N;SP]ZG1FWA[._!MQ\N=K;'EMTHE>- +MM*X[6!'<=Y-U]"8W:#T@+7IGD>CI9M&&>.;5O>0#EU.UB];V=C0R[$BLIW[Q +M)QJ/0/V#HU7X=`C"F\,QYYK5T.+GM]E,5$E_B`"O'+:-/.C,7C^`XXOA"`/^ +MF\;7XEV-VQ=;,\?<\%QV$T=8UQ]#241[8/!M/(1@V6M0OC#0F\U;XFEIQ#+? +MD<&"R%>WJC:UCE2K!Q$"R8W4*+6PP5)C3=3[NI-AI0\D-=[.U[L=,GR*S53# +M,"R-39V:.&#YNEQ'V5I?^IY(MXJ3&CP^7?LW-F7$[3C-T(^][V*[=5!H]Z\N +M_$XVJ5`!,7FP[.6GOHXEAC;N2>5^._P:.ENC)!O0-]`1=\JG&?6[Y/6>7DE" +MW?8D]$:.X3A?ICD3S)+0U'@?&?4*W@IN8KNP2RL),.A]+9Z`C;K*]7^*QF`1 +M^-V>\I3L%7CS)5NGQ;FK(P'$8^#%)G((@:[UV`>;Q*<0!Q\5ZKPJ>/'XHL@_ +M6M+<\5997`>9TB;)JN +MA#J`*O\,)8SC:N(JU_='9PQ_/;[OSX[@FM0M)F+*VOK-N-[DY0)EF_PYH/(P +MSY/6;-Z]`Q:(?$XIH]U+:<`_`57/1$.1'2O7VZI1SOGEPU;U=]>&25%&B2=; +M5UH='_[7,N-ZF/X!*FZ%9-Z>62UC_#NX]Q_PH]BQ_P69O#7E5?G4U;:&,XL$ +M:M*QY%N70_G]\:7G2F8V)LG5JMB?2]!7,!,K("PQ`5(1DKO.+9SA/>%=]V(/ +MGZ/N)Y\$KJ_VYG(^$OJV=X39O\?+M_5>C,V7>,/ONV]K6S9+4LZ2RS38(*`. +M;HP0Y-"9O1;3F3V +M!1%6$,R77V?$5I@.YEW@O4DAH?HI1`&A?6&>:V++>%/'RGN=[)R4E(R+B`?RW1$ZZ1/PN1G*O,52R-R.%R0X0W#%J!]JFZ^CYY +ME0O?(N\.E4652)9GQ?7:_FZ7]:0 +MA=$?>.)E>72RW1(+E:*LHEEZQ-XL[T6N=0G3XB?PL"$3NLIVS%BD#X7O8KQV]=(8N20U5H?WZNGH]KW"T.SV=/N0TV]/0Z?9Z/V=OM]GZ^WVJM] +MKIRJ:?*(N_-@GV(A7UT99*4%UP*5])9V5W[C;XQK!G?1&M=F*E-[9&R)RK'M +MX\96;[GU1]6U'^PV*A5>A=JEG5!AT:E*+VR"5)5NF?8@YAI;YX0N7,.2ORN5 +MV<=:FU]BS9M00Z^)6VM]4`%&SV]I#02>['39/TYXPGUI/."5;5FN2N'"ZY4M +MDY)IKT^YH]NYIM7,PM#0GQ`5T]+L:'=ZO4H'.MUJHR`A*X+#<5G<&N+S1[?3 +MM,5\DOGO;^?"8.A*\7)@G\#!D>+__08+@VG_RO9!Z$@+^0]JQX%,A^*I+D++ +M;=<1HUU*?X?H(RZRD-O&2BL:LAMQO_U]N@4GYF5(J+8Z-L@3K8U[T>U=R\V\ +M93!3F7*[828'L//;'E'!S/KRT\&A[^N[D#1%60-"QMN\M5O5F^]C=CTO)+\: +M6]JAD[C9J+T1]^/HQ`%ADK#Y+L:R5?]]:?,9+HW^/3"D>$*'1=&UNT +M,NT.2QN'C1E2L>;HXZFW-]3:TKMXT9CN(/6C.8Y(D%??*JR$2&K(.QMX^ZK/ +MPIGRKC!1I(?4GW=*6-(/N+!D5&?DG(IV.KT_[Z<*.B]6&\SO=3IQ_`L%SD6H +M0/DDFWX?+;]G?T>SU-.%)DNC!T`Z/:Z_UY$J+I]WW`[W;T_9/L[NA[%T>M[I +M]6YS+X?%'_IOQC.QM*H4L`'"M;'1XZDM7I\=CE7+PU;U=CGVMD#S7YB*PW*G1T_`G=VW7 +M!PJ?0!GED[(\-L^A7'6/QG!%^:5;V$N!/NG`P]%*?^',I,YXFPV +M5XO\6[%WLVSS5>[5*KB2G#C,->'7($D2BV'_(`6`+JK!/-JK^,>*F?Y$SMZZ +M'E-=,H.\E5_CV*,U34&7A^_@98_SXAJ#NPSL4X73K_'#T`'9R#QN6R#L9<:5 +MS#U=5EZ0:''_6+E +M+()3W<*PK*5K^^>=,,ORR`QXS"Y>3L91!!D]6>!\YNJUJ+B/"B.OW;9S0PY- +M[L'<%C#F&E/JB@B&WHW;*`8;:HS[(@1=D6VD +M.(WA2/E)PPU\4&DWNC$-S1*M!@9RNMO!$E8(8PG`/TI.T!;DYUZWW#GGI];. +M^&TM6S>89P.>EE-!5>4UD+0=4@5E=(,GC_@:WH45RH*Z^GG^_6M*!D+I<>`C +M[7(;3L,O#V0T3]>=1R1C=I=NREUG:Y&'*@99):YR$62SH0=V?^K"I=,1:66T +MGW_Z!J/L2=IG2'>;.8I!N8RVA_(VK^<.U-YXP(/)"OOX636''^QU;>/]UM/X +M2(:GB!=8/R:H$^"2\S]K%0:`1U$4MFQD?'@T`I)6/U0O-&6UP?PL8^`O/H'I +MMC,7#ILAUVD11&)?>:M;:M.`?/*DO<`N+O@F>!2]#_-2'+6^YK1*^C*?2E8VY$YF]3%<&M+W9QFR+SJ^L!N\TM8X^OR]O9[FQ/ +M5!MR"?VR%)SK0`HFMR,+F;N/EV.*Z6/:<9)XS$GWCXTU^P,P)MHQ?&K&Y2%O +M=7ILS%\6FY':*JC/F4+^8,-/`U>&N](IPN:$+%?/A_LVM$H$*S +MWRYDMHY`Q`\N\ZZ:^]@]E@G)30YWG7,?!!6_FR-76F%,-LX7W).AA;K<3\1# +M)<,\4`SBY-4_I?^6GDB2G.5K:Y$L9]5H3P^^)_\[7G]OFC7U%ZN^_Y%[.\9W +MZ<&,YTB6R_W9U0E%4"W.D(F0`MFG'^U1[4HMI0?_IYS/(R6AB._6`_8]2E3@ +MVK\FWLQ+$Y&<=MR7LHXJF@O9D8*`K!GFU#CA?Y\8^`&'KKKR?5&3J,8SZLF. +MW:9TU>%-C&(J2X&4V/Y-51[N];@@C_$)]QOJI41PMG982751#QH0:P4**J(A +MAQ"GN?\'P"HX^2H`O?]$\>1DV][P(=XF$MX4B'[*V=[[L>1U/O`59]WYQ"$V +M5+BB'H:UVT(^08NZ=MXMK]S\8BHW_@\1X`4@KZ:BJ74YDI:_`X%_5KGA#^3. +MHE2MYMEP"L7)V:&:!5]\P[0=_$1FYEL7-KV?3C8$V^RSVZIOQ$>\O0^[,^+* +MAY\0H^3O`$R/^%_:[8<\(0I`4)_;H@`````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````" +M@$OPP`Q?VO4_^?______________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M___________________________________________^@$?\B__K'_I_____ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_________________________Z!'_(O_ZQ_Z?_______________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______^@3`'1%0R-%\6=F]S/A7.S5W8"T;9`[O=G2*&IP\3W2`(833>H2:8/ +M`,[&-M/&Y!GWK4@,-D75WT2#SF#E*Z5VOR5I<]-@````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````>K\_IYW_/U<_H?\?3_/H>I>=B_GSNAS +M_7[]SU/CZGT>C]PIUI\#N/,^!\/ +MT?3O\\_G?1SHL2*"O1V.[U>MZAYOR6#3_WY_TPY`=/Q4IX]'42-/%X!""Q +MIJZ<(%2T_<[3[/Z>YZ.;I]:"Z!(!Q'*P#5O[KYO<[>EH^#3EG%=UUB!IZXV0;U("5+:D=^O +MZJFD\WZCO"PBJ2QY!E);,$>6"0?H]3J_O6I?7FZU=.,+Z[Z5/E(0)>*Z+7[( +M*5*E&1W"42AOFZ5?DF2_KU4^B^+U>77[(-%!#S_NPQ:.NGI;<"`]C?:O^:8H +M3^N\-O[8,GV_I]?_'S=*]\K^7N?^UD\P-T=O2S_!&U;Z%SX?NI..G]T6_!!4 +MLQ:<3%T>!+IQW\;]T%WG5GP83,->>A1TAALLM<8W>N]%XKUQ^\'#K-J5OM3X +M^-+[NU?VMV^A/C4];?O/#3]L3X$LQ(\,D?C*_9^'($4_(KULYY9ZB67_C>?A +M!)KU:L_WB(+)QT)WEY/MR*NCJ1F2;O> +MVH,6B5SQ:286\>KD<(SP5\>'<[/L(;I*T +MN9\<%(GSODHP7XL_407$P5-YIQ7[8F681SO*L)%M%;)JM\QRPTI*1$ +M5(6^,L=_U=5S9'$"9N;%YV3NOV."UA%X/QR+L?QE@[7"O*)0-=YQ`?&+VC8K^WJOGE[O'>>R +M2TIR^1+26]F(+MYZ./+3O*L8(\L1?`6G+W.'X^$2W9;!*^:F_'@4W(5F1JU? +M!NVGK-6P/Q`E+AE,%%$=&50&N`AV1&#.]R_+!IU\#Q8S3T +MS*5TKB%829O?Q#>Z'1F>_A]/F@F(_E??%ME+7D9Y2]60><3]4>9D0#[V8YBW +MW9I-LRT@->CU>XD"9$X/)4_D?@SMOT4=JLIM4RL^SH7+YF^D*/KRO?/*04O+ +ML4&ZDC*5OA&Y,:7!/@]ZOHM"FQW8VJ5;AM*JL7;-6!N[6]J0@0>(#ME,2.IW +MSQZ(5C"T&2/9\1OUR3*%B2C7]$U3>GU7#`_%*#CTL%T>+DJ]8L +MZ`%_S9T0AR,F*8A^38LN[FV;>H'$8@.LX?T>!M2_'\S.MVAR_G/VL%"@,^G4 +M"N=%Y0?-TLOL=FY3@:\3EV[\9U@?GOPA`,

    YP4JS) +MDK=RTB.,/IR,AYL"8-FG22/(UB;KX-O&GN/W@4'B1?D.;V.J,?[Y`QL._(SO +M5J5A^ZO12`4M`,J6;H0HIK;&IJXH>2%2*:&G,SJ5^>K9HV8Y<<-T]9F<;HSQ +M'1>LBVE;`)X`M'./CRH=Y@#/K"F_3I6A'NX-G8Q88FOI$>7QTRAGK]^A+$]U +M?7[^C;)"5,IZT`>9UCDVK&E`C>6Y/Y\5TCN5MV?<^!Y*D%[^;!P#[4=R5G$C +M'T,<`\OB>(JE,I?/=X>9^.6%.9EVN>E38)-%EIP\68%D!(J\.2P/2,9ZTN_Z +MJMO(<3\@'.$AJ8LQN+'*1OZ>MABA;T2=+%VV^E#8=?&(*C">6"'4>./TYUUZ +M^16ZB9?F032LZ@`G#.NUP)E_R"<$+G.1MQN&41O^>#0SVYI; +MT@#9T";E^4T8INM0VK05*WSG7N*-I/$5.BGK)E"K(*LTJYMW7*0%E#-DIT)\ +M6M`) +M"$GL4\!QQ+S/C26*$*_!)7O&8J8SQE%.1)'$FU)&N9>UPB&'*@ZVQ.5<97)* +MHZ$LP8EM1J`AG9)EA010)R+E<*WI.:]:O'+5J/60FO]]?4O>9F7&+58QPXE= +M<$_[Y=?<@VU>AS\Z>^"&//+@SM?!MP0'>O[:_QZC1"HHK`V\AL!%@P)*Z;^U +MUI#AC3SVS#Y2EC^[8S`\,8J0E7-CCXH454<5$7#N4^4`KW*54I;%J4N2KFI^'5Y^,1K?,;1U`HG-30&8H;-(IHL$"RXYQ21. +MAQ<9'YO,W_.Y$EP]>$?@W8SRAX(VJ]XXWC[7@D_XJTY#HU:-Q;\R[07W!A//^G^D1(YUR +M?'_H@@.0O#%9._OL\-E.KOUF_C24U418L\0 +M)"7CMV")#BP2HMEXL%=+4KYJ^WI@G6@%JZJ[2/0ZVIKYWXPTK^^'MU>:D;@0 +M#<9S'L>(,5JZ50DJMVA5GDPS039RIQAHKI;Y7FLX"ID"[LE5[6\F6Y!^#4VL +MGO*A@#T>?6EI?K[5HZ?\OY7:'ES7:OM_6K]**]WT>5P=ID5_'SU^A)5`P>B12EBOG!G(\?]O +M(,ZJZNARE%[&H"K\N7383F-&V2K`]XL&K+H:G+2H^[NT.GXJ^6+]:LMOZ*,]>"%W;U;$(?)ED_MTH$E8_F)VC('`[:RJ8M;7I'Y +M&,+WQ:7SW<$\-Z5%RR^F`VQ>W:Y&.3KVD*VG3V.Q%\ +MAF-W>_VHUDSTKKXURQ/ISFG9V+O!Q/RKA#/P1FX6;( +MJDHD0DSR$B,08'6UD\\;$_7C)OJ,-97S>4O%<-T2^-YG8<*I6W&I-` +M"S=;,TZ>QK:=?M=_WOUDD;6=_]XS?/*>QTH?(3.,PE=,TU?(3,VI7J'$_9%_ +M?\3,7RS)JO77_1XZD"[*;^Y68RL,4RI'188PU[&1Y>,6YU7:KKKK +MPJE#WI=S>>'O4Z,V\/9WX-N/ESM;8\MNE$KQMI7':P([CO)NOH3&[0>D!:], +M\CT=+-HPSQS:M[R`SL:&78D5E._>).-1Z!^P=&J_#H$84WAF//-: +MNAQ<]OLIBHDO\0`5XY;1IYT9B\?P''%\(0!_TWC:_$NQNV+K9GC[G@N.PFCK +M&N/H:2B/;!X-IY",&RUJ%\8:$WFK?$TM.(9;\C@P60KV]4;6L'R[]FYLRXG:<9NA'WO>Q7;JH-'O7EWXG&U2H`)B\V'9RT]]'$L,;= +MR3ROQW^#1TMT9(-Z!OH"+OE4XSZW?)ZSR\DH6[[$GHC1W"<+],9):&H\# +MXSZA6\%-S%=V"65A)AT/I;/0$;=97J_Q6,P"/QNSWE*=@J\>9*MT^+NP#S>)3B`./BO5>%3QX_%%D'ZUI;GBK+*X#S.D39+E?G/R5Q +MVDR2].O)V7].6T[%.EC-8\?$YFXK!4]>;CU5T(=0!5_AA+&<;5Q%6O[H[.&/ +MY[?=^?'<$UJ%I,Q96U]9MQOKOKPR2HHT23K:NM#H__:YEQO4Q_`)4W0K)O3 +MRR6L?X=W'N/^%'L6/^"S-X:\JK\ZFK;0QG%@C5I6/(MRZ'\_OC2\Z4S&Q-DZ +MM5L3Z7H*Y@)E9`6&("I",E=YQ;.<)[PKONQ!\_1]Q//@E=7^W,Y'PE]6SO"; +M-_CY=OZKT9FR[QA]]VWM:V;):EG266:;!!0!S=&"#G3NF'MV(?L_#H4["UG\ +MH'BM?!S8Y5TM^;!P;>]_^.M[#W)H3-Z+:P*(JPAF2Z^SXBM,!W,N\%ZDD +M-#]%*(`T+ZPSS6Q9;PIX^4]SO9.2DKE64=62R@B!MZ-35U?4C5^M/N#9D]3\ +M$!V@O4U[`+L^K%C4_G@>WOBZL(3M.3.\9'(V$4DY41?$'\3D=O3Q&1<0#^6Z +M(G72)^%R,Y5YBJ61N1PN2'"&X8M0/M4W7T?/,J%[Y%WATJBSFV.L>Y%`TAJG +M;+A@&41W8)?A!FSB3RJ1+,^+ESSZ[7\W2_K2$+HC[QQ,KRZ66Z)!BUSJ$Z?$3^%@0B=UCFQ)+ZA).W +MKI#%R2&JM#^_5T]'M>X6AV>SI]R&CFCX.C%?!^O/W,6UGQZ[7]9S:OLU,6"Q +M`QLYO\N-,=K0^SVWIZ'3[/1^SM]OL_7V^U5OM=.533Y1%WYL$^Q$*^NC+)2@ +MNN!2OI+.RN_<;?&-8,[Z(UKLQ4IO;(V1.58]O'C*S?<^J/JVH_V&Q4*KT+M4 +MLZH,.C4I1>V02I*MTS[$',-+?/"%RYAR5^5RNSCK4VOL6;-J"'7Q*VUOJ@`H +MV>WM(:"3W8Z;)^G/&$^M)YP2K:LUR5PX77*ELG)-->GW-'MW--JYF%H:$^(" +MNGI=C0[O5ZE`YUNM5&0$)7!8;BL[@UQ>:/;Z=IBODE\][?SX3!T)7BY,$_@8 +M,CQ?_Z#!<&T_^5[(/0D!?R'M6/`ID/Q5)CVKN7FWC*8* +M6G@T/?UW<@:(JR!H6-MWEJMZLWWL;L>EY)?C2SE5LQ#WM4,G<;-1>B/OQ]&( +M`L,E8?)=C62K_OK3YC)=&_QZ84CPA0Z+HVMVAEVAR6-P\:,J5CS=''4VYOJ; +M6E=O&C,=Q!ZT9S')$@K[Y560B0U9!V-O'W59^%,^5<8*-)#ZD^[I2QI!]Q8, +MBHS\DY%.QU>G_?3A1T7JPWF=[J=./X%@NIIPI,ET +M8.@'1[77^O(E1=/N^X'>[>G[)]G=T/8NCUO=/JW.9?#XH_]-^,9V+DLJ)\5/ +M3-R/;^5DYZ<['T7X8WN0VK%"CI7!V[^0/=240=VZN7(SMD2M3LZBSJQ&%W1J +M&K>KL<^UL@>:_,16&Y4Z.GX$[NVZ[@.`%KP+G5?VBOC3V%3Z`,\LG9'AMG +MT*XZQ^,X(OS2K>PEP)]TX&'HI3_PYE)G/$V&RO%_BW8N]FV>:KW:I5<24X<9 +MAKPZY`DB46P_Y`"P!=58)YM5?QCQ4S_(F=O70\IKIE!WDJO\>Q1FJ:@R\/W\ +M#+'^?$-0=V&=BG"Z=?XX>@`[.0>-RV0=C+C2N8>KJLO2#0[D19S[E#Y63I1E +M__VGJ(`````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````#_V`2\C^C%_:]3_Y____________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________________________________________________Z`1_R+ +M_^L?^G______________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________H$?\B__K'_I_____________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_________________Z!'_(O_ZQ_Z?_______________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +H_____________________________________________________P`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_large_splitted_rar_ac.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_large_splitted_rar_ac.uu new file mode 100644 index 0000000..0ceeae1 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_large_splitted_rar_ac.uu @@ -0,0 +1,892 @@ +begin 644 - +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_____Z!,(=41#,T1`!85O9S\*.C/!I9I1:2;N[&-B[`5MIBT,?1836;F[OB1 +M1)I)5B)-+35%IEX-^[X`4GT(E*.1T3,T512)P;F^.L,(DS43'5SOBOB7/\(/ +MW/[]SD1P3SPF!'I,@``````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````````.7X_\>[_'Z.[^I\O\.YZ +M>>OI?P^;^'I__RVDL4?\2G5G_T:?&__KIY7K#H7@A(IWJ%<*'!9%"OLP-!P7 +MAD6BR0E+P\"H8V._E_*C?IFE[04,GALITXYE9I+UTMU/+-*9HF_1./4FOK-SR3*$Q\?,O +MFSQ7M\WQ\F5CX9ZMYX>?&%_>A&']?O\$V'A#;8AY^:-F[!<+R;L;2\W&/WE[NW#\"VZ13S4Z)=:V3Q#TU/+GI-CEU>"-W\DF:9P9/]HUM+9" +M3=,D')VO?T5`Y@0JK9)ZDNJKN55>?RY5NYJSH3JV#6/<3LVRY101KE +MWH:&G!%)MZ=C +MQ\GZ46;81TIWET&%/OY\_FBX9R>/:`QK4 +M2`YO2-X^SCART""SZ,LQY/<=B=%(CDGM?K4>#M4H81.AN\W>+J04IPP'Q7?# +M%+#5X'N,-_RY<;E[QC8;>KIZ!!J6F"=U;'=.2$/9QO\GT1A]9"/UH,N/)6`. +M.U=WM_3Y9F+_?9'CCW45HLW#5?YEQW,@;`6'N49"V:96P+B<=&F)!F.WJSI5 +M#;V/47ZVFGY>/)*@L?%@47T='GNLHR3NG8Y3-!TZ'+]3GRB>+)PE;U"26?49 +M/=@L;K[PEX?V2FO\ +MLBX\]NH+4?O>=K/Q>Y\]82,DI.R70+29M(.239GW[I/W*1+WD^>_)WA[_N!8 +M3J\G>96F?Y,7.FUW>WV_\NUV^[VNY_+Q=WN;7R]O:^;M_OOU+J +MW!T"#%F@O#+?FM'?/6K_M/Q\GE]92>;>;@U'G5+:CS7N]R[6Y:S\IT_MTSA7 +MV>_0UU+W/GL#W%$4_9IDV.UT:(TR\M?7[?SSPS;MION5_N2V)FW:^/NMW/Y^ +M2OBP\&UN_/W/Y2]7O6X6KQ/*0=M,X7KDSGY<05]C5_';_GV]?\&_(EMI[$$0 +M.[L?]=CY=GUO^Z];>M.[V?Y]KN=-D3ZZ`1=W^/S1,5NBMH^6N@/)ETRK%77R +M_,E2%?H9$VOU)L.FP6V?@DP_+RUMF[>.R2A%?SRLL@^_#WX.O705/G6FF)4 +M4T4=ALF9T($3:1-$7*>D- +M%"$=?3N^+5%(_=^.27QEDR"]ZTV@X8_&&>/G>F3@B!^/)-IU:J"_U:B;$#85 +M>RVGU'%[P=WK."_7GXO?&2-F[XM/P$0.B'W9*5]S'?Z?U@:2^'\<$>/8OB<* +M6/R#VVO<0X?!7=?=DRK:EL.*`:89D&](VS"?U/FF$">_C>,B=Z;V2NB&SLN6 +MSNH]$TU."0&_EP"9P8ZF]56_\=XT5W*Z(8%\ZC[&:UCV8_:+VW,O/7*'4,FO +M@'.<6` +M99O;Z<2@48FVBZ,8DT*HLE,P8$A:?WB![D4(A^X<\\"%Y?RR1FS9NX,'%9T5 +MG/1.&1(P.!;HYQM\T>.F%3X^NQ3ZC?EV2J#N[M&Q=GXKPL.Q_XE&[&:;52DP +M2Y.T[-P06OA>#Z"'_(>O+Y,D`@^TN>3Z2#7J4I_FA0>U;LV`UQ0&3&W/HBZI +M0,GEWI:V]B'%YZ2<9K0OJFQ)+YW[7YYIT[AV;J$D)Y:C@.GSYMS--:+GRM*! +M(,_'ZZ_\^#^]E#6NU>CJ"()L?5W_K\'W4>AO8Z&0NS8S7_OT#BWR?XS.,R:2 +M_'Y\9Q/8_Q^3H6FG%/8[&38_G;*NW'*.W)A5=CL]G8_Z>MON_T^S[.S]&N]? +MOP@820/NQWO#]/]O!_V]DOW_Y[/0M'0];'@57& +M!=:%C)$5.+DUG+5/QT^8^CS?[>-NB$/V,E4<7)EZ7(.*]?PTP@@=BA%.&SYV +MO!]WU_)]O>^[P?7(++:^WZZ?#AAT\W[=EG;L3P351#M:+[3$?^\O^HME\&24 +MS_T1G+U1+-Q79*PV'(J5IS:)$+]VKO&E0R'-2I['@H35R:B87H[7:A89L3_V +M,U+)&9;%!L6^-&H?IN^#KCG4CV)YNHA15?],>61*F2!]P:JZ[6%"9,A?`G]9 +MJMO!^'WP:9LPB>G +MOW%?4D\V-E=FM\T^>W#]&KO)IO^I9^&R;K[;\*L#7CZ?:*PN=-JHT;\"UT%)M-:<:NJ$71Y_=FZ\W).4!90 +M;+G\EEX#1J;PR2-L#O-6&E(XK[#KM-8=]C<.;=9O$SI)Y23;'V^>W;R31E:(Q,?#LBCEK$8>6 +M$9M[+H^$B:;'+>[EJJ)]A)U.2]L65(9R>I<#C8;!8>M=*W\_/L?B$S;X3>UO +M(F,]'V<1)_:NAODT_>$:7\>6)[XZ<]'%=EU8T[QXE>QN9@=S24?7&Y[2*>E2 +ME,K"3:<;D"A*_G'&4H5IDR7-$12A*, +MD+W*3C1W/%Y=4FQ%&*83)\NBRQQ'I4A=F*T+^3/-4^FZ?IB,WR?+%&A9>O(7 +M.6/;&:KK2H%3UU>9E.D_@_S[_]/IYW)E;XEL:43.SFZKSR6X=$TH+SSA8+GA +MDWJ]F/Q$#TP`#+]\O%2K-\75L=B;HFA_P9?1+AKSPG2;L$!(2VL(4$_?6AI^ +M0IW!(B3O;79ZPN0?3$!;4UST9BKYP/1-M,3%^DBKR/(:/<.;7KJ^CT9J6&K? +M?E"O&-LR=6RGX9%EM-,(W>/BF\4HB]G+UFY/IEP-HPS!8@UUFXK35!Z(_SAS +MX(*5WQ7S576EW5-_8]'6[E2&KE=VN;X%:[NYM%C1<+NVLN.:!U-C+2"TX;(8 +M4R9WQ55<]'N<^7A.]&;;H2G:#P8PIZMK.3R_N^+I@J)ZUH?6T7MBS$%[-;2] +M,4;LU!8^>>4)DZ[%-/+$+(R;-5"L'_!=I5@5L-VH?27![ +M#)AY9<3HTDB7<6G1UD#6'S!&H+X0YJ?OKBF(13$RUICG"W7=M_#26D/N5 +M,Z0V9I81!N6"9W1")IDC8QTY/]S@S[L^FC$8S\41:#".#%3?,LVB%[@9OO44 +M+^]2Y&W-*^@BU1%`MY[N7=Z)]^&?@M&6F)V"QN;DQ":81BC^''8X[6`O>/1J +MNX"UK[5]VU37^_PD[J^:5V-%:YYL^W;(W9N_WNZ%Y:BU#%_UV!A"VE15/:I>TE"[5M4V\G@ +MMA^[JC$SY>S]%LL?^\%K/H$B>&U`:H!APX&O?;D%)(#TBN7&_=A!A=Z&5]N? +M1IQ>U*\M9P!%SSJ0EY9;BRRM"`)5XZ72OR;/`UL&YXHB5JGR\EHWJT7@%R5G +M)QE[`!E^/RF>#SY9?YPZ8;%\O2ZZ0GE0]^#'&NIG/SR2OVJ:/)N^:ZQ3%4M8 +M]?Z_+\O8AB$.F"76>F9<%4B>?XY`-W?%BE9&; +ML*K1F//PY:4U-V?VN.=`C,_#8L!#5>E%W^7>ZR2+H\/-N@_-"0W>QK]]Y('Q +M:B:5-5YK%!F:;^*G#'LA*+9_IKK#6MV$\$9Z!'==!FHW[)O-636-^?JJ]7T@ +M.>O7J=GX-Z_;EX*SJ'U9U(P9QF@,Q"`W3X!*-7HMGP\[1:?PY.#?]*\W+[Q: +M_[28_V%L^#?/U9N*L\^]:U'7E7I[\\&CPY?)\/(?,:V0=GWUV:FP/O;PC+OX +M9OSR_"O.+1]WI-'4[T^V'9UK=JZ;(4[[Z/6")-H&;V_KY2A$N_R;'*[R)OVP;(F!9:KV%I2CB;Q[V$?(Z +M[JOA>B&U=?##-(7,P9'F%!YZS8EBCUBT2P[5WA]V&:)+B)Y^*>3].?56 +M\>"4AN[F6^&.;ISB=2`5:+A%^0XE:S$@#8WG,%I^7PA.V>D/?>WM6ZE9C4%\..:NA9;B?"N7:X^.=T8M8_ZSH3 +M%?N'.F:UC?DH$6_&DMBZO,\]9>]2@.E)&;7=@D=U)T"42`L>@*>'J+B_Z2\J +MH.]C>LY%PXY-JRK^(RV><-5*2>^7GU'MMT5CO60]I-"DR:>F0FZ.@.KL9B`^ +M=SG5_7R[6[0UW`C%[0OLVE,])F1CJ+3%AG>E$9UD)*3/KR\51NY@58N-][GL +MR5HBGAT+-/74VG?ZE^7:K$N&3VNY(;T42+C+A7N)E!ETP)*'U?!I^.2U;77^G/2F2G#6U8=E"1-5T0C'>CX]= +MQBR)-":?T40W9V-5#TLC:WHO^*!X8CM&UR=CL_13GZ%->5J_.D6O:)QI+)M[ +M9]-$MK%!G,O_R7LV/KFD9Y7B;A8_71]%)I@BF'&Y)COQ'S53+M9#=H$K.!5) +M9KX^++A<-'A]:9Q8F@BZO0,GLRXXB/Z3#1V9-";`%6]5PP:0-':1?@-WQ8?% +M:%C(9C?Y6]:5Z=3&BW)0!;375:#7?5-7MGU%#36?1Z'/V>G +MG5.^=49"A?#[+#F4#HO949#EWQ='-_6]9?=\?/G[7)SKUK%'4Q0$3''E,^4-2OA]7PK:&T8'=D-W*V< +M?GVNSZ>B6X4).M<^P3(LOE36UM-'>9J(-49K[WT_97TJL`31ETP18CSP+Y>: +M/NG1^.37NW,F[YK,[*;EWA"SPH/KCI:14,R7^2%QK#G?19[D>Y((:%(OKH=& +M_4WGT)-<^^%OJ"8,">6Z6KIP;N`T/*Q\=W+J.0?2ZGGO>3C+?+C=$3[%>>'Q77=U8'D +M_]0HL4IF'A:*<@VZ-`R;U5.6*$LW1)8F"09:'%<(?&G`6L#]]>1";IC?4-V8 +M27=ABFSA3D2>9[TWW%3#WIB/@S::>_?O_.!K8N2QC&KC=E +M)1'%X\F[6U0,(EMS<-;TGOCCX9OPV))IGU$Y2 +MFQ,TW>9:O5HFE=.)>[&W.N\"4W__&2.%O9(=V?Z9_2<+!ZMT4,L>_U/WU-4Z +M<]^DK:KD5WE&#$W]S(-*&_+ND +M(&[NFG'M.M%=%:6CVU+$%]0$Q"E_9JQ[_)>O*6A+?&_.9H#OL3ND%-Q1$='4 +MN>/JS:/-C%LC^^@*WASU\C4EU*W<;D +MH!ZM*F5D9#Z+X+8LQDJ(ODFX;GS5A(;6EU,(];V:079.(H)=.?Q?4H1'LB]= +M2Y?^OC_/\^5Y:?0A6/!LIMA"VAS$\_'Q>>'M%FGP?IJ/EN\7,?&9E@!2"G4MDYDN9FH[(?NC?@R=(/K +M>R<&3R1'+WARSK&G[A3QXI$-_;HNY3%,R;D0&I,9*2:U? +MWPU[!?':*;OUK1#=,='VN2YCG!O-B&7X3'9R4W`LC>Q(H4!1SU;LSI"?**"- +M$W3_&Q]\263CN&S1TA';YY95/BI_>IPQ5*AK$(4L!N_;X?;S(!CM5VBJ??]O +M7XV(HQX*TG/V;4M`T7M#>ZSKXQ;F5XPIW'GG\V6VBYKC^*T3\DM^,6X],V3P +MG'R=/9.AKN@`=51G"LJ]IHZH;I]I='PU1EOXY'XJU +M2:;1TR9/*]V/=6")LTZ[AJCE4ZBGEG.3/1EYXE5SSYX'GCBF[!3+_TAAEZ>8 +MLP4IWS:;SZ&^[SU-=_[+TF6T2-PJFXZ!44BM*.PC9$K>/JA\&"AFW64_[#VS +M\LVRWK!\M_H?)L4^@ADQKKU]5#HV8?6LO6[DK +MKXLD'OH5H[=N7X*I^%@NG&P,U8J>]$Y!`Q(HE@#L_%>BZ1S;#W<\\2MGLWT) +M4Q[:P1FG0UF2!#HF2/[\F`MYZ]LC7S,RX4DZM?5$#2QJG)[0N.?8@\P$9-)^0.OMHW,VF()] +M_"@]_N<*U(DS02,0@FJ4'Z.X6-PG8Y3]WX`WR1P9=1]AT[_LS[T=5-U8D=/Z +MM[-1V-^;6YB-QIHS\1OK1E#^H^/%2CSU*]SFZB-O0P7.9&(^"2;U+Z.1_C%^ +M3WOV,>5:-FN$2BNW$Q-H1!I,6B$<+U^\]ML@) +MIJ@TM<4^",E3#'G3A>*%?VW`H%5HFLFX).4Z`.;V?GKX;T]^755<'V<*UC>; +M-[%*;/X0]]!P>WI\4,Y&PE_B_KBY3_KR8A*=V5Y9^":+9OY.2W-%I:#J"YC[ +M#9]&6)@HH1ZHV*<8TFQK2]$+ +M2^(@3/9+1"6W2O)L"JZC)MCDJG+%_;+=UEV.2(I,V[T@EI4_>>,]J)SAMVO/1M>YM-AQ+IY8Q%WYDO:$R9":>2(=(QI-8FT7KC-YVNI^VNP$O'+G7+LUC#W-PU`SJ5TG3!'3-Y$71F&\R +MIAPA-3+KMQ`A.LV>T\I=DWOQD9GR>3!S^2N>6\'-??Y*P]1Z)]:MSNVK3KLQ +MO<_'-NOXQU:K;F)9UV*]@/U`:IFZLT$S[=SKY$R`$N/I:%W^2F4 +M+/B_%C=T!8XU<&6HH&1\D5,IK)()..[F/V(NZ=$2+-2JO?\]\+?^W[DGO?%VZGNTCMOF;O1@7CN +MCW\E)B"E\79I]#\?;E*)GX +M0XO'&S/8K]`A_E[O:W-?VBQ++>W23#MSBS^;+K!B)WYOZGT*KTU5WI%WOQS4 +M-JRU-KG?)+*W\?FK@=&+-$4Q=FH2:8/`,[&-M/&Y!GWK4@,-D75WT2#SF#E*Z5W?Y+GLL``````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````'J[_3SO^?JY_0_X^G^?0]2\[%_/G=#G^OW[GJ?'TY2['0 +MXL!]#U(Z'1A";GY-BV,W6@9#W(9][P]/H]'[A3K3X&Y3I1IDIHT2.XL$R&Y[ +MI4@=.F[#?/^ZK1ZD#&6'[\,TB^]<>9\"Y-'I=B--7:1>90X9!B^ZVMRLSBZ9 +MH3>*UL(X9WO3T;88(NBWJ;FWYMCU:_`%SO[.K)IJ?V@]X?H^G?YY_.^CG18D +M4%>CL=WJ];U#S>YFST<_/_)_+L;'E@R"(8&S]S/W[H'VO3[-G[XE?]16`H7C +M7$6F?`7.ERJ_\NC3.&L[XU<8.@9'&L'1%!-IUL?&T8$DS.,.S_X.*MFY1YV- +MX9_`(S_AWXIX>G6]DL&G_OS_IAR`Z?BI3QZ.HD:>+P"$%C35TX0*EI^YVGV? +MT]ST4:L"3()CQ_;TU>HQ6M?7%4=POV:74YL0'I09' +M.UA@H)]/=\OOS@G5Z&CX/T-X0-588>U]NIXZNWI5>"XTEJY?OC;IM''%S(ZH +MSSRMS1_9,TNG9F9*F04#YUGBD(U/->&+/_<==8H-%>N,41#3C!FNWYH_9"0. +M>;IUU'VT]?W7S>YV]+1\&G+.*[KK$#3UQL@WJ0$J6U([]?U5-)YOU'>%A%4E +MCR#*2V8(\L$@_1ZG5_>M2^O-UJZ<87UWTJ?*0@2\5T6OV04J5*,CN$HE#?-T +MJ_),E_7JI]%\7J\NOV0:*"'G_=ABT==/2VX$![&^U?\TQ0G]=X;?VP9/M_3Z +M_^/FZ5[Y7\O<_]K)Y@;H[>EG^"-JWT+GP_=2<=/[HM^""I9BTXF+H\"73COX +MW[H+O.K/@PF8:\]"CI##99:XQN]=Z+Q7KC]X.'6;4K?:GQ\:7W=J_M;M]"?& +MIZV_>>&G[8GP)9B1X9(_&5^S\.0(I^17K9SRSU$LO_&\_""37JU9_O$063CH +M3O+RY";HCLR!%4$M"P%R2C.-H4T+?C(5%67(4L1#KH$O:A2=CZ)I=,W#/<=T +M<&R;OD^+GR7]R>;S\[^F=SHQ[7Y?2JY?("\?;D5='4C,DW>]M08M$KGBTY947A +ME#!LF.-1V@1)FYE7*S+,.\DPMX]7(X1G@KX\.YV?80W25IT4)IX`F?I3)JXIX+Y!.UCJI=3N:?1-X-R+CMH^S0QQ>.!3VST>W\O +MZO1/ARI:U0G<^O;3?@AFLT3F^I]O8V(QKO1N<6+Q&9-K=QA#.ND9M!7LK*_- +MMU6##8]^H@N)@J;S3BOVQ,LPCG>582+:*V35;YCEAI24B(J0M\Y2JU<8P+_F +MJF;]*S-YF1E9"^6#7@6\98[_J_5S9 +M'$"9N;%YV3NOV."UA%X/QR+L?QE@[7"O*)0-=YQ`?&+VC8K^WJOGE[O'>>R2TIR^1+26]F(+M +MYZ./+3O*L8(\L1?`6G+W.'X^$2W9;!*^:F_'@4W(5F1JU? +M!NVGK-6P/Q`E+AE,%%$=&50&N`AV1&#.]R_+!IU\#Q8S3TS*5TKB%829O?Q# +M>Z'1F>_A]/F@F(_E??%ME+7D9Y2]60><3]4>9D0#[V8YBWW9I-LRT@->CU>X +MD"9$X/)4_D?@SMOT4=JLIM4RL^SH7+YF^D*/KRO?/*04O+L4&ZDC*5OA&Y,: +M7!/@]ZOHM"FQW8VJ5;AM*JL7;-6!N[6]J0@0>(#ME,2.IWSQZ(5C"T&2/9\1 +MOUR3*%B2C7]$U3>GU7#`_%*#CTL%T>+DJ]8LZ`%_S9T0AR,F*8 +MA^38LN[FV;>H'$8@.LX?T>!M2_'\S.MVAR_G/VL%"@,^G4"N=%Y0?-TLOL=F +MY3@:\3EV[\9U@?GOPA`,

    YP4JS)DK=RTB.,/IR,AY +ML"8-FG22/(UB;KX-O&GN/W@4'B1?D.;V.J,?[Y`QL._(SO5J5A^ZO12`4M`, +MJ6;H0HIK;&IJXH>2%2*:&G,SJ5^>K9HV8Y<<-T]9F<;HSQ'1>LBVE;`)X`M' +M./CRH=Y@#/K"F_3I6A'NX-G8Q88FOI$>7QTRAGK]^A+$]U?7[^C;)"5,IZT` +M>9UCDVK&E`C>6Y/Y\5TCN5MV?<^!Y*D%[^;!P#[4=R5G$C'T,<`\OB>(JE,I +M?/=X>9^.6%.9EVN>E38)-%EIP\68%D!(J\.2P/2,9ZTN_ZJMO(<3\@'.$AJ8 +MLQN+'*1OZ>MABA;T2=+%VV^E#8=?&(*C">6"'4>./TYUUZ^16ZB9?F032LZ@ +M`G#.NUP)E_R"<$+G.1MQN&41O^>#0SVYI;T@#9T";E^4T8IN +MM0VK05*WSG7N*-I/$5.BGK)E"K(*LTJYMW7*0%E#-DIT)\6M`)"$GL4\!QQ+S/C2 +M6*$*_!)7O&8J8SQE%.1)'$FU)&N9>UPB&'*@ZVQ.5<97)*HZ$LP8EM1J`AG9 +M)EA010)R+E<*WI.:]:O'+5J/60FO]]?4O>9F7&+58QPXE=<$_[Y=?<@VU>AS +M\Z>^"&//+@SM?!MP0'>O[:_QZC1"HHK`V\AL!%@P)*Z;^UUI#AC3SVS#Y2EC +M^[8S`\,8J0E7-CCXH454<5$7#N4^4`KW*54I +M;%J4N2KFI^'5Y^,1K?,;1U`HG-30&8H;-(IHL$"RXYQ21.AQ<9'YO,W_.Y$E +MP]>$?@W8SRAX(VJ]XXWC[7@D_XJTY#HU:-Q;\R[07W!A//^G^D1(YUR?'_H@@.0O#%9._ +MOL\-E.KOUF_C24U418L\0)"7CMV")#BP2HM +MEXL%=+4KYJ^WI@G6@%JZJ[2/0ZVIKYWXPTK^^'MU>:D;@0#<9S'L>(,5JZ50 +MDJMVA5GDPS039RIQAHKI;Y7FLX"ID"[LE5[6\F6Y!^#4VLGO*A@#T>?6EI?< +M/]Q)7K8F6YKRH0MPI-O2^W;BQZX['+ERRY&/'M;NSM[%&HQ')&!VW@$W]O9P +M:^EI=FK+;^M81W0]7#)P37$H''@F^D$V;Y].5'?$\D<,W->K[5HZ?\OY7:'E +MS7:OM_6K]**]WT>5P=ID5_'SU^A)5`P>B12EBOG!G(\?]O(,ZJZNARE%[&H" +MK\N7383F-&V2K`]XL&K+H:G+2H^[NT.GXJ^6+]: +MLMOZ*,]>"%W;U;$(?)ED_MTH$E8_F)VC('`[:RJ8M;7I'Y&,+WQ:7SW<$\-Z +M5%RR^F`VQ>W:Y&.3KVD*VG3V.Q%\AF-W>_VHUDSTKK +MXURQ/J5\!K[%W@XGY5PAGX(S<+-D5242(29Y"1&(,# +MK:R>>-B?KQDWU&&LKYO*7BN&Z)?.1LJ9O&\SL.%4K;C4F@!9NMF:=/8UM.OV +MN_[WZR2-K._^\9OGE/8Z4/D)G&82NF::OD)F;4KU#B?LB_ON7)G*2`48/P@B +MRROKP^*$_2R0G^YH=[L9>R6.]N[.33"H=?,_CT.?FQ98>3V_Y09`[MO>)F+Y +M9DU7KK_H\=2!=E-_'L[\&W'RYVML>6W2B5XVTKCM8$=QWDW7T)C=H/2`M>F>1Z.EFT89XYM6] +MY`.74[6+UO9V-#+L2*RG?O$G&H]`_8.C5?AT",*;PS'GFM70XN>WV4Q427^( +M`*\/X#CB^$(`_Z;QM?B78W;%ULSQ]SP7'831UC7'T-)1'M@\&T\ +MA :U"^,-";S5OB:6G$,M^1P8+(5[>J-K6.5*L'$0+)C=0HM;#!4F--U/NZ +MDV&E#R0UWL[7NQTR?(K-5,,P+(U-G9HX8/FZ7$?96E_ZGDBWBI,:/#Y=^S;#LY:>^CB6&-NY)Y7X[_!HZ6Z,D +M&]`WT!%WRJ<9];OD]9Y>24+=]B3T1H[A.%^F.1/,DM#4>!\9]0K>"FYBN[!+ +M*PDPZ'TMGH"-NLKU?XK&8!'XW9[RE.P5>/,E6Z?%N:LC`<1CX,4F<@B!KO78 +M!YO$IQ`''Q7JO"IX\?BBR#]:TMSQ5EEG7D[+^G+: +M=BG2QFL>/BO-QZJZ$.H`J_PPEC.-JXBK7]T=G#'\]ON_/CN":U"TF +M8LK:^LVXWN3E`F6;_#F@\C#/D]9LWKT#%HA\3BFCW4MIP#\!5<]$0Y$=*]?; +MJE'.^>7#5O5WUX9)44:))UM76AT?_M55^=35MH8SBP1JTK'D6Y=#^?WQI>=*9C8FR=6JV)]+T%__'6]A[DT)F]%M.9/8%$580S)=?9\16F`[F7>"]22&A^BE$`:%]89YK +M8LMX4\?*>YWLG)25RK*.K)901`V]&IJZOJ1J_6GW!LR>I^"`[07J:]@%V?5B +MQJ?SP/;WQ=6$)VG)G>,CD;"*2]BO';UTABY)#56A_?JZ +M>CVO<+0[/9T^Y#1S1\'1BO@_7G[F+:SX]=K^LYM7V:F+!8@8VWCQE9ON?5'U;4?[#8J%5Z%VJ6=4&'1J4HO;()4 +ME6Z9]B#F&EOGA"Y]OY\)@Z$KQP\]L>4<',^O+3P:'OZ[N0-$59 +M`T+&V[RU6]6;[V-V/2\DOQI9RJV8A[VJ&3N-FHO1'WX^C$`6&2L/DNQK)5_W +MUI\QDNC?X],*1X0H=%T;6[0R[0Y+&X>-&5*QYNCCJ;63LCPVSZ%<=8_&<$7YI5O +M82X$^Z<##T4I_XS;/-5[M4JN)*<.,PUX=<@21*+8?\@ +M!8`NJL$\VJOXQXJ9_D3.WKH>4UTR@[R57^/8HS5-09>'[^!EC_/B&H.[#.Q3 +MA=.O\#?N]@%)]")2CD=$S-%44B<&YOCK#"),U$QU<[XKXES_" +M#]S^_GGKZ7\/F_AZ?_\MI+%' +M_$IU9_]&GQO_ZZ>5ZPZ%X(2*=ZA7"AP610K[,#0<%X9%HLD)2\/`J&-COY?R +MG,9<&][-=*A#J1#.$KF[F?P\<.DB+#O9I(I'%#N>O1HMK8[TK?GHWZ9I>T%# +M)X;*=..96:2]=+=3RS2F:)OT3CU)KZS<\DRA,?'S+YL\5[?-\?'*-X*HNVBZ +MB-#(6C)YI)`.:;WIE8^&>K>>'GQA?WH1A_7[W#R3=ETS[G#IM%;6-G]XWO!- +MAX0VV(>?FC9NP7"\F[&TO-W-0PY&=**)>?BMEJ+VORC5[@2A^*Z)")FFU2VL +MD<,HVS-5Q28;8:-B#]4]C)V?/=1+HCT>"_3?4D3F5Q[?AX^'AC]Y>[MP_`MN +MD4\U.B76MD\0]-3RYZ38Y=7@C=_))FF<&3_:-;2V0DW3)!R=KW]%0.8$*JV2 +M>I+JJ[E57G\N5;N:LZ$ZG(T`S3L=^#S.*\R[M58C@*>]HYYN&^:3/1DY,&VA +MQ9;V7==AFW`**UPW[P>XXP;\1U)P.\F:KZ!_8]&?U7U)P,I>G8\?'+!\\)/LXX3W'8G12(Y)[7ZU'@[5*&$3H;O-WBZD%*<,!\5WPQ2PU>![C#?\N7&Y>\8V +M&WJZ>@0:EI@G=6QW3DA#V<;_)]$8?60C]:#+CR5@#CM7=[?T^69B_WV1XX]U +M%:+-PU7^9<=S(&P%A[E&0MFF5L"XG'1IB09CMZLZ50V]CU%^MII^7CR2H+'Q +M8%%]'1Y[K*,D[IV.4S0=.AR_4Y\HGBR<)6]0DEGU&3W8+&Z^\)>']G+O_C40 +M"`*(QN]D\8N0O]:LPC6LSNDMZY*>&4C$<$)X7DIK_+(N//;J"U'[WG:S\7N? +M/6$C)*3LET"TF;2#DDV9]^Z3]RD2]Y/GOR=X>_[@6$ZO)WF5IG,82>?DT\'G +M^3%SIM=WM]O_+M=ON]KN?R\7=[FU\O;VOF[?[[]2ZMP=`@Q9H+PRWYK1WSUJ +M_[3\?)Y?64GFWFX-1YU2VH\U[OQ!$#N['_78^79];_NO6WK3 +MN]G^?:[G39$^N@$7=_C\T3%;HK:/EKH#R9=,JQ5U\OS)4A7Z&1-K]2;#IL%M +MGX),/W+O1Y[;3Q**GRSN&^,:+VJW:[_%[?LF_.U=O^';_R_E@%YHHQ;Y'XOT +MS&?<5GB\M;9NWCLDH17\\K+(/OP]^#KUT%3YUIIB5%-%'87*8$.+>ZZ@!:A_ +M'!?!H3$AAUP-')@(>M]WRU$3WK)F="!$VD31%RGI#10A'7T[OBU12/W?CDE\ +M99,@O>M-H.&/QAGCYWIDX(@?CR3:=6J@O]6HFQ`V%7LMI]1Q>\'=ZS@OUY^+ +MWQDC9N^+3\!$#HA]V2E?F]DKHAL[+EL[J/1--3@D!OY<`F<&. +MIO55O_'>-%=RNB&!?.H^QFM8]F/VB]MS+SURAU#)KW+%0A5V9PBC!Y*7%4E: +M2'ZGVNYBF`.,D?GS2S^F8OF'`!*9\NIJ9$;VSXZE_G%P<[&??S^3DHI<4X)C +MX[N6^JI3ZD%BR&US3+R>/8QK95$=^9%6L$M=^QQS8HI;P44G21[1@?Y%"(?N'//`A>7\LD9LV;N#!Q6=%9ST3AD2,#@6Z.<;?-'C +MIA4^/KL4^HWY=DJ@[N[1L79^*\+#L?^)1NQFFU4I,$N3M.S<$%KX7@^@A_R' +MKR^3)`(/M+GD^D@UZE*?YH4'M6[-@-<4!DQMSZ(NJ4#)Y=Z6MO8AQ>>DG&:T +M+ZIL22^=^U^>:=.X=FZA)">6HX#I\^;ST+1T/6QX%5W([>$T_;ER#BO7\-,(('8H13AL^=KP?=]?R?;WON\'UR"RV +MOM^NGPX8=/-^W99V[$\$U40[6B^TQ'_O+_J+9?!DE,_]$9R]42S<5V2L-AR* +ME:QX*$U;J(457_3'ED2ID@?<&JNNUA0F3(7P)_6:G,,B;WK;P?A]\&F;,(GI[]Q7U)/-C979K?-/GMP +M_1J[R:;_J6?ALFZ^V_"K`UW+')CV4K9)Y3H@040#(I`O],;YU8Z=-W^9V_HI +M6;CL[5WX110BV2ZY$HUJ:0U5PV9`%3HN.0@;K,##!K$Q<]_EO=S_8D;`\L'H +M^GVBL+G3:J-&_`M=!2;36G&KJA%T>?W9NO-R3E`64&RY_)9>`T:F\,DC;`[S +M5AI2.*^PZ[36'?8W#FW6;Q,Z2>7)?WYY-_DG0\*AM?>S<\/#$OZW5P+1U)&+ +M^SF]EV]WDDVQ]OGMV\DT96B,3'P['*XWWHHY:Q&'EA&;>RZ/A(FFQRWNY:JB +M?82=3DO;%E2&^.G/1Q79=6-.\>)7L;F8'TBGI4I3',=73GQ5ASD*Q$53U +M#!['W\-U]=2+W+OLS4!)@N:W2,@`O/9H:5HLQFT7X=B>]5."_>/EZ43Q4HA1 +M=//4-HC1>5:A'JPDVG&Y`H2OYQQE*%:9,ES1$4H2C)"]RDXT=SQ>75)L11BF +M$R?+HLL<1Z5(79BM"_DSS5/INGZ8C-\GRQ1H67KR%SECVQFJZTJ!4]=7F93I +M/X/\^__3Z>=R96^);&E$SLYNJ\\EN'1-*"\\X6"YX9-ZO9C\1`],``R_?+Q4 +MJS?%U;'8FZ)H?\&7T2X:\\)TF[!`2$MK"%!/WUH:?D*=P2(D[VUV>L+D'TQ` +M6U-<]&8J^<#T3;3$Q?I(J\CR&CW#FUZZOH]&:EAJWWY0KQC;,G5LI^&19;33 +M"-WCXIO%*(O9R]9N3Z9<#:,,P6(-=9N*TU0>B/\X<^""E=\5\U5UI=U3?V/1 +MUNY4AJY7=KF^!6N[N;18T7"[MK+CF@=38RT@M.&R&%,F=\557/1[G/EX3O1F +MVZ$IV@\&,*>K:SD\O[OBZ8*B>M:'UM%[8LQ!>S6TO3%&[-06/GGE"9.NQ37, +M1C4-PS':FP[,GCRQ"R,FS50K!_P7:58%;#=J'TEP>PR8>67$Z-)(EW%IT=9` +MUA\P1J"^$.:G[ZXIB$4Q,M:8W-::K[6M=T^J(52B=%J]L4J)U3\=$2[!VHSW +M'IPMUW;?PTG#V";W!EX)AI^+$#_FTU<3O/W)EG3>V6_R3=$_ZT-0#)7U:M"Z +M<(K3I?=`#?FD!?FX>BPCZ16;UH?B"PL\RP#7EI#[E3.D-F:6$0;E@F=T0B:9 +M(V,=.3_X&;[U%"_O4N1MS2OH(M410+>> +M[EW>B??AGX+1EIB=@L;FY,0FF$8H_AQV..U@+WCT:KN`M:^U?=M4UW)HJ*\K_HFWOO\).ZOFE=C16N>;/M +MVR-V;O][NA>6HM0Q?]=@80MI453VJ7M)0NU;5-O)X+8?NZHQ,^7L_1;+'_O! +M:SZ!(GAM0&J`8<.!KWVY!22`](KEQOW8087>AE?;GT:<7M2O+6<`1<\ZD)>6 +M6XLLK0@"5>.ETK\FSP-;!N>*(E:I\O):-ZM%X!P`9?C\IG@\^67^< +M.F&Q?+TNND)Y4/?@QQKJ9S\\DK]JFCR;OFNL4Q5+6/7W+`O_IMTJK_X]V"!= +M;/,2#=W82.H'UP1_9'S/4M&;<]U!?_I]D/\2J2#TRA!^A5,#LY[)2HS)O+;& +M;4.YT7NOR_+V(8A#I@EUGIF7!5(GG^.0#=WQ8I61F["JT9CS\.6E-3=G]KCG +M0(S/PV+`0U7I1=_EWNLDBZ/#S;H/S0D-WL:_?>2!\6HFE35>:Q09FF_BIPQ[ +M(2BV?Z:ZPUK=A/!&>@1W709J-^R;S5DUC?GZJO5](#GKUZG9^#>OVY>"LZA] +M6=2,&<9H#,0@-T^`2C5Z+9\/.T6G\.3@W_2O-R^\6O^TF/]A;/@WS]6;BK// +MO6M1UY5Z>_/!H\.7R?#R'S&MD'9]]=FIL#[V\(R[^&;\\OPKSBT?=Z31U.]/ +MMAV=:W:NFR%.W+/?;)Q:._"4/U/$?NYTL5M^!>_TUQ_X=]>++^7N^CU@B3:! +MF]OZ^4H1+O\FQRN\B;]L&R)@66J]A:4HXF\>]A'R.NZKX7HAM77PPS2%S,&1 +MYA0>>LV)8H]8M$L.U=X?=AFB2W-EWHB>?BGD_3GU5O'@E(;NYEOACFZT+ +M[-I3/29D8ZBTQ89WI1&=9"2DSZ\O%4;N8%6+C?>Y[,E:(IX="S3UU-IW^I?E +MVJQ+AD]KN2&]%$BXRW)R\5E;"4`02HSU+;[V8RS3ENZ_P!%QS1#:O["[AFK@ +MTZ0*JN[0B@QDSJ3;Y^K/HB-2?V^'34F]+Q3O[TNI-SJB&5]7WS'7H5[B909= +M,"2A]7P:?CDM6UU_ISTIDIPUM6'90D35=$(QWH^/7<8LB30FG]%$-V=C50]+ +M(VMZ+_B@>&([1MV?31+:Q09S+_\E[-CZY +MI&>5XFX6/UT?12:8(IAQN28[\1\U4R[60W:!*S@526:^/BRX7#1X?6F<6)H( +MNKT#)[,N.(C^DPT=F30FP!5O5<,&D#1VD7X#=\6'Q6A8R&8W^5O6E>G7-=PL +M\=%NW6$WDQHMR4`6TUU6@UWU35[9]10TUGT>AS]GIYU3OG5&0H7P^RPYE`Z+ +MV5&0Y=\71S?UO67W?'SY^URY'N2"&A2+ZZ'1OU-Y]"37/OA;Z@F#`GE +MNEJZ<&[G)!@6+92E+F[GXZFZK%>H8$4@DM2]<9-JPZF2R[AUS.TCL?%#@D]6 +M/!+%,;)EJD&PP0L(FOO>*4-,B'^%IST:K2[)EXK=+2X]4QH[U[YJU;\]N&:E/,(C<_ +MQWU_BFAPS@9G!I=2XAEHSNW4-W1#Z)G@-#R +ML?'=RZCD'TNIY[WDXRWRXW1$^Q7GA\5W*7WEW=6!Y/_4*+%*9AX6BG(-NC0, +MF]53EBA+-T26)@D&6AQ7"'QIP%K`_?7D0FZ8WU#=F$EW88ILX4Y$GF>]-]Q4 +MP]Z7+/VW])HZ,M:3#:=/)T*[%8(L75^`/DFT%/><#4L'0X,Q91V,7SQOO!G^ +M9`?%$/.+J/V1`B?#WHCX,VFGOW[_S@:V+DL8QJXW9241Q>/)NUM7)=XYJZ5; +MUE"+N;!Z15RKBGD#");K=%#+'O]3]]35.G/?I*VJY%=Y1@Q-_"]R4=[9"BXIIU4@!MWS_R7KREH2WQOSF:`[[$[I!3<41'1U+GCZLVCS8Q;(_OH"MX< +M]?'*$0I?/X/D^_8[W]_!*"?IK2IE9&0^B^"V+,9* +MB+Y)N&Y\U82&UI=3"/6]FD%V3B*"73G\7U*$1[(O74N7_KX_S_/E>6GT(5CP +M;'+.,V5L>/#SQB=IBORS'4Q&T;5I4R>2)9:D`O+*O'J;80MH*1#?VZ+N4Q3,FY$!J3&2DFM7]\->P7QVBF[]:T0W3'1 +M]KDN8YP;S8AE^$QV653XJ?WJ<,52H:Q"%+`;OV^'V\R`8[5=HJGW_;U^-B*,>"M)S]FU+0-%[ +M0WNLZ^,6YE>,*=QYY_-EMHN:X_BM$_)+?C%N/3-D\)Q\G3V3H:[H`'549PK' +M+4@9CE'3VO9/:YHS8WJO::.J&Z?:71\-49;^.1^*M4FFT=,F3RO=CW5@B;-. +MNX:HY5.HIY9SDST9>>)5<\^>!YXXINP4R_](89>GF+,%*=\VF\^AON\]37?^ +MR])EM$C<*IN.@5%(K2CL(V1*WCZH?!@H9MUE/^P]L_+-LMZP?+?Z'R;%/H(9 +M,:Z]7+W(8?,H2>E*7>BB1'!MFZGO50Z-F'UK+UNY*Z^+)![Z%:.W;E^"J?A8 +M+IQL#-6*GO1.00,2*)8`[/Q7HNDVL$9IT-9D@0Z)DC^ +M_'+L=;(2M<=7=782%C['Y_1.#+ORC]FP+NCG-W]^P9%)B;@DGI@+>>O;(U\S +M,N%).K7U1`TL:IR>T+CGV(/,!&32?D#K[:-S-IB"??PH/?[G"M2),T$C$()J +ME!^CN%C<)V.4_=^`-\D<&74?8=._[,^]'53=6)'3^K>S4=C?FUN8C<::,_$; +MZT90_J/CQ4H\]2OQ2FS^$/?0<``` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_large_splitted_rar_ad.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_large_splitted_rar_ad.uu new file mode 100644 index 0000000..f736f13 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_large_splitted_rar_ad.uu @@ -0,0 +1,892 @@ +begin 644 - +M>WI\4,Y&PE_B_KBY3_KR8A*=V5Y9^":+9OY.2W-%I:#J"YC[#9]&6)@HH1ZH +MV*<8TFQK2]$+2^(@3/9+1"6W +M2O)L"JZC)MCDJG+%_;+=UEV.2(I,V[T@EI4_>>,]J)SAMVO/1M>YM-AQ+IY8Q%WYDO:$R9":>2(=(QI-8 +MFT7KC-YVNI^VNP$O'+G7+LUC#W-PU`SJ5TG3!'3-Y$71F&\RIAPA-3+KMQ`A +M.LV>T\I=DWOQD9GR>3!S^2N>6\'-??Y*P]1Z)]:MSNVK3KLQO<_'-NOXQU:K +M;F)9UV*]@/U`:IFZLT$S[=SKY$R`$N/I:%W^2F4+/B_%C=T!8XU +M<&6HH&1\D5,IK)( +M)..[F/V(NZ=$2+-2JO?\]\+?^W[DGO?%VZGNTCMOF;O1@7CNCW\E)B"E\79I]#\?;E*)GX0XO'&S/8K]`A +M_E[O:W-?VBQ++>W23#MSBS^;+K!B)WYOZGT*KTU5WI%WOQS4-JRU-KG?)+*W +M\?FK@=&+-$4Q=FH2:8/`,[&-M/&Y!GWK4@,-D75WT2#SF#E*Z5W?Y+GLL``````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```'J[_3SO^?JY_0_X^G^?0]2\[%_/G=#G^OW[GJ?'TY2['0XL!]#U(Z'1A" +M;GY-BV,W6@9#W(9][P]/H]'[A3K3X&Y3I1IDIHT2.XL$R&Y[I4@=.F[#?/^Z +MK1ZD#&6'[\,TB^]<>9\"Y-'I=B--7:1>90X9!B^ZVMRLSBZ9H3>*UL(X9WO3 +MT;88(NBWJ;FWYMCU:_`%SO[.K)IJ?V@]X?H^G?YY_.^CG18D4%>CL=WJ];U# +MS>YFST<_/_)_+L;'E@R"(8&S]S/W[H'VO3[-G[XE?]16`H7C7$6F?`7.ERJ_ +M\NC3.&L[XU<8.@9'&L'1%!-IUL?&T8$DS.,.S_X.*MFY1YV-X9_`(S_AWXIX +M>G6]DL&G_OS_IAR`Z?BI3QZ.HD:>+P"$%C35TX0*EI^YVGV?T]ST4:L"3()CQ_;TU>HQ6M?7%4=POV:74YL0'I09'.UA@H)]/=\OO +MS@G5Z&CX/T-X0-588>U]NIXZNWI5>"XTEJY?OC;IM''%S(ZHSSRMS1_9,TNG +M9F9*F04#YUGBD(U/->&+/_<==8H-%>N,41#3C!FNWYH_9"0.>;IUU'VT]?W7 +MS>YV]+1\&G+.*[KK$#3UQL@WJ0$J6U([]?U5-)YOU'>%A%4ECR#*2V8(\L$@ +M_1ZG5_>M2^O-UJZ<87UWTJ?*0@2\5T6OV04J5*,CN$HE#?-TJ_),E_7JI]%\ +M7J\NOV0:*"'G_=ABT==/2VX$![&^U?\TQ0G]=X;?VP9/M_3Z_^/FZ5[Y7\O< +M_]K)Y@;H[>EG^"-JWT+GP_=2<=/[HM^""I9BTXF+H\"73COXW[H+O.K/@PF8 +M:\]"CI##99:XQN]=Z+Q7KC]X.'6;4K?:GQ\:7W=J_M;M]"?&IZV_>>&G[8GP +M)9B1X9(_&5^S\.0(I^17K9SRSU$LO_&\_""37JU9_O$063CH3O+RY";HCLR! +M%4$M"P%R2C.-H4T+?C(5%67(4L1#KH$O:A2=CZ)I=,W#/<=T<&R;OD^+GR7]R> +M;S\[^F=SHQ[7Y?2JY?("\?;D5='4C,DW>]M08M$KGBTY947AE#!LF.-1V@1) +MFYE7*S+,.\DPMX]7(X1G@KX\.YV?80W25IT4)IX +M`F?I3)JXIX+Y!.UCJI=3N:?1-X-R+CMH^S0QQ>.!3VST>W\OZO1/ARI:U0G< +M^O;3?@AFLT3F^I]O8V(QKO1N<6+Q&9-K=QA#.ND9M!7LK*_-MU6##8]^H@N) +M@J;S3BOVQ,LPCG>582+:*V35;YCEAI24B(J0M\Y2JU<8P+_FJF;]*S-YF1E9"^6#7@6\98[_J_5S9'$"9N;%YV3NO +MV."UA%X/QR+L?QE@[7"O*)0-=YQ`?&+VC8K^WJOGE[O'>>R2TIR^1+26]F(+MYZ./+3O*L8(\ +ML1?`6G+W.'X^$2W9;!*^:F_'@4W(5F1JU?!NVGK-6P/Q`E +M+AE,%%$=&50&N`AV1&#.]R_+!IU\#Q8S3TS*5TKB%829O?Q#>Z'1F>_A]/F@ +MF(_E??%ME+7D9Y2]60><3]4>9D0#[V8YBWW9I-LRT@->CU>XD"9$X/)4_D?@ +MSMOT4=JLIM4RL^SH7+YF^D*/KRO?/*04O+L4&ZDC*5OA&Y,:7!/@]ZOHM"FQ +MW8VJ5;AM*JL7;-6!N[6]J0@0>(#ME,2.IWSQZ(5C"T&2/9\1OUR3*%B2C7]$ +MU3>GU7#`_%*#CTL%T>+DJ]8LZ`%_S9T0AR,F*8A^38LN[FV;>H +M'$8@.LX?T>!M2_'\S.MVAR_G/VL%"@,^G4"N=%Y0?-TLOL=FY3@:\3EV[\9U +M@?GOPA`,

    YP4JS)DK=RTB.,/IR,AYL"8-FG22/(UB +M;KX-O&GN/W@4'B1?D.;V.J,?[Y`QL._(SO5J5A^ZO12`4M`,J6;H0HIK;&IJ +MXH>2%2*:&G,SJ5^>K9HV8Y<<-T]9F<;HSQ'1>LBVE;`)X`M'./CRH=Y@#/K" +MF_3I6A'NX-G8Q88FOI$>7QTRAGK]^A+$]U?7[^C;)"5,IZT`>9UCDVK&E`C> +M6Y/Y\5TCN5MV?<^!Y*D%[^;!P#[4=R5G$C'T,<`\OB>(JE,I?/=X>9^.6%.9 +MEVN>E38)-%EIP\68%D!(J\.2P/2,9ZTN_ZJMO(<3\@'.$AJ8LQN+'*1OZ>MA +MBA;T2=+%VV^E#8=?&(*C">6"'4>./TYUUZ^16ZB9?F032LZ@`G#.NUP)E_R" +M<$+G.1MQN&41O^>#0SVYI;T@#9T";E^4T8INM0VK05*WSG7N +M*-I/$5.BGK)E"K(*LTJYMW7*0%E#-DIT)\6M`)"$GL4\!QQ+S/C26*$*_!)7O&8J +M8SQE%.1)'$FU)&N9>UPB&'*@ZVQ.5<97)*HZ$LP8EM1J`AG9)EA010)R+E<* +MWI.:]:O'+5J/60FO]]?4O>9F7&+58QPXE=<$_[Y=?<@VU>AS\Z>^"&//+@SM +M?!MP0'>O[:_QZC1"HHK`V\AL!%@P)*Z;^UUI#AC3SVS#Y2EC^[8S`\,8J0E7 +M-CCXH454<5$7#N4^4`KW*54I;%J4N2KFI^'5 +MY^,1K?,;1U`HG-30&8H;-(IHL$"RXYQ21.AQ<9'YO,W_.Y$EP]>$?@W8SRAX +M(VJ]XXWC[7@D_XJTY#HU:-Q;\R[07W!A//^G^D1(YUR?'_H@@.0O#%9._OL\-E.KOUF_C24U418L\0)"7CMV")#BP2HMEXL%=+4KYJ^W +MI@G6@%JZJ[2/0ZVIKYWXPTK^^'MU>:D;@0#<9S'L>(,5JZ50DJMVA5GDPS03 +M9RIQAHKI;Y7FLX"ID"[LE5[6\F6Y!^#4VLGO*A@#T>?6EI?K[5HZ?\OY7:'ES7:OM_6K]**] +MWT>5P=ID5_'SU^A)5`P>B12EBOG!G(\?]O(,ZJZNARE%[&H"K\N7383F-&V2 +MK`]XL&K+H:G+2H^[NT.GXJ^6+]:LMOZ*,]>"%W; +MU;$(?)ED_MTH$E8_F)VC('`[:RJ8M;7I'Y&,+WQ:7SW<$\-Z5%RR^F`VQ>W: +MY&.3KVD*VG3V.Q%\AF-W>_VHUDSTKKXURQ/ISFG9V+O!Q/RKA#/P1FX6;(JDHD0DSR$B,08'6UD\\;$_7C)O +MJ,-97S>4O%<-T2^-YG8<*I6W&I-`"S=;,TZ>QK:=?M=_WOUDD;6=_] +MXS?/*>QTH?(3.,PE=,TU?(3,VI7J'$_9%_?\3,7RS)JO77_1XZD" +M[*;^Y68RL,4RI'188PU[&1Y>,6YU7:KKKKPJE#WI=S>>'O4Z,V\/9WX-N/ES +MM;8\MNE$KQMI7':P([CO)NOH3&[0>D!:],\CT=+-HPSQS:M[R`SL +M:&78D5E._>).-1Z!^P=&J_#H$84WAF//-:NAQ<]OLIBHDO\0`5XY;1IYT9B\ +M?P''%\(0!_TWC:_$NQNV+K9GC[G@N.PFCK&N/H:2B/;!X-IY",&RUJ%\8:$W +MFK?$TM.(9;\C@P60KV]4;6L'R[]FYLRXG:<9NA'WO> +MQ7;JH-'O7EWXG&U2H`)B\V'9RT]]'$L,;=R3ROQW^#1TMT9(-Z!OH"+OE4XS +MZW?)ZSR\DH6[[$GHC1W"<+],9):&H\#XSZA6\%-S%=V"65A)AT/I;/0$; +M=97J_Q6,P"/QNSWE*=@J\>9*MT^+NP#S>)3B`./BO5 +M>%3QX_%%D'ZUI;GBK+*X#S.D39+E?G/R5QVDR2].O)V7].6T[%.EC-8\?$YF +MXK!4]>;CU5T(=0!5_AA+&<;5Q%6O[H[.&/Y[?=^?'<$UJ%I,Q96U]9MQOKO +MKPR2HHT23K:NM#H__:YEQO4Q_`)4W0K)O3RR6L?X=W'N/^%'L6/^"S-X:\JK +M\ZFK;0QG%@C5I6/(MRZ'\_OC2\Z4S&Q-DZM5L3Z7H*Y@)E9`6&("I",E=YQ; +M.<)[PKONQ!\_1]Q//@E=7^W,Y'PE]6SO";-_CY=OZKT9FR[QA]]VWM:V;):E +MG266:;!!0!S=&"#G3NF'MV(?L_#H4["UG\H'BM?!S8Y5TM^;!P;>]_^.M[#W +M)H3-Z+:P*(JPAF2Z^SXBM,!W,N\%ZDD-#]%*(`T+ZPSS6Q9;PIX^4]SO9 +M.2DKE64=62R@B!MZ-35U?4C5^M/N#9D]3\$!V@O4U[`+L^K%C4_G@>WOBZL( +M3M.3.\9'(V$4DY41?$'\3D=O3Q&1<0#^6Z(G72)^%R,Y5YBJ61N1PN2'"&X8 +MM0/M4W7T?/,J%[Y%WATJBSFV.L>Y%`TAJG;+A@&41W8)?A!FSB3RJ1+,^+ES +MSZ[7\W2_K2$+HC[QQ,KRZ66Z)!BUSJ$Z?$3^%@0B=UCFQ) +M+ZA).WKI#%R2&JM#^_5T]'M>X6AV>SI] +MR&CFCX.C%?!^O/W,6UGQZ[7]9S:OLU,6"Q`QLYO\N-,=K0^SVWIZ'3[/1^SM +M]OL_7V^U5OM=.533Y1%WYL$^Q$*^NC+)2@NN!2OI+.RN_<;?&-8,[Z(UKLQ4 +MIO;(V1.58]O'C*S?<^J/JVH_V&Q4*KT+M4LZH,.C4I1>V02I*MTS[$',-+?/ +M"%RYAR5^5RNSCK4VOL6;-J"'7Q*VUOJ@`HV>WM(:"3W8Z;)^G/&$^M)YP2K: +MLUR5PX77*ELG)-->GW-'MW--JYF%H:$^("NGI=C0[O5ZE`YUNM5&0$)7!8;B +ML[@UQ>:/;Z=IBODE\][?SX3!T)7BY,$_@8,CQ?_Z#!<&T_^5[(/0D!?R'M6/ +M`ID/Q5)CVKN7FWC*8*6G@T/?UW<@:(JR!H6-MWEJMZLW +MWL;L>EY)?C2SE5LQ#WM4,G<;-1>B/OQ]&(`L,E8?)=C62K_OK3YC)=&_QZ84 +MCPA0Z+HVMVAEVAR6-P\:,J5CS=''4VYOJ;6E=O&C,=Q!ZT9S')$@K[Y560B0 +MU9!V-O'W59^%,^5<8*-)#ZD^[I2QI!]Q8,BHS\DY%.QU>G_?3A1T7JPWF=[J +M=./X%@NIIPI,ET8.@'1[77^O(E1=/N^X'>[>G[)] +MG=T/8NCUO=/JW.9?#XH_]-^,9V+DLJ)\5/3-R/;^5DYZ<['T7X8WN0VK%"CI +M7!V[^0/=240=VZN7(SMD2M3LZBSJQ&%W1J&K>KL<^UL@>:_,16&Y4Z.GX$ +M[NVZ[@.`%KP+G5?VBOC3V%3Z`,\LG9'AMGT*XZQ^,X(OS2K>PEP)]TX&'HI3 +M_PYE)G/$V&RO%_BW8N]FV>:KW:I5<24X<9AKPZY`DB46P_Y`"P!=58)YM5?Q +MCQ4S_(F=O70\IKIE!WDJO\>Q1FJ:@R\/W\#+'^?$-0=V&=BG"Z=?XX>@`[.0 +M>-RV0=C+C2N8>KJLO2#0[D19S[E#Y63I1E__VGJ(```````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````!_[$O(_HQ?VO4_^?______________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_______^@$?\B__K'_I_________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_________________________________________________Z!'_(O_ZQ_Z +M?___________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M______________________________^@1_R+_^L?^G__________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________H$PAU1$,S1$`%A6]G/PHZ,\&EFE%I)N[L8V+L!6VF+0Q]%A- +M9N;N^)%$FDE6(DTM-46F7@W[O@!2?0B4HY'1,S15%(G!N;XZPPB3-1,=7.^* +M^)<_P@_<_OW.1'!//"8$>DR````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````!R_'_CW?X_1W?U/E_AW/3SU]+^'S?P]/_^6TEBC_B4ZL_^C3XW_]=/ +M*]8="\$)%.]0KA0X+(H5]F!H."\,BT62$I>'@5#&QW\OY3F,N#>]FNE0AU(A +MG"5S=S/X>.'21%AWLTD4CBAW/7HT6UL=Z5OST;],TO:"AD\-E.G',K-)>NEN +MIY9I3-$WZ)QZDU]9N>290F/CYE\V>*]OF^/CE&\%47;1=1&AD+1D\TD@'--[ +MTRL?#/5O/#SXPO[T(P_K][AY)NRZ9]SATVBMK&S^\;W@FP\(;;$//S1LW8+A +M>3=C:7F[FH8QD[/GNHET1Z/!?IOJ2)S*X]OP\?#PQ^\O=VX?@6W2*>:G1+K6R>(>FI +MY<])L.$@#-J\60A8S`RY)V*;Q-O3L>/CE@^>$N6G$T>.>*710.G)7=C:YCT_2BS +M;".E.\N@PI]_/G\T7#.3Q[0&-:B0'-Z1O'V<<.6@06?1EF/)[CL3HI$,;#;U=/0(-2TP3NK8 +M[IR0A[.-_D^B,/K(1^M!EQY*P!QVKN]OZ?+,Q?[[(\<>ZBM%FX:K_,N.YD#8 +M"P]RC(6S3*V!<3CHTQ(,QV]6=*H;>QZB_6TT_+QY)4%CXL"B^CH\]UE&2=T[ +M'*9H.G0Y?J<^43Q9.$K>H22SZC)[L%C=?>$O#^SEW_QJ(!`%$8W>R>,7(7^M +M681K69W26]\GSWY.\/?]P+"=7D[S*TSF,)//R:>#S_)BYTVN[V^W_EVN +MWW>UW/Y>+N]S:^7M[7S=O]]^I=6X.@08LT%X9;\UH[YZU?]I^/D\OK*3S;S< +M&H\ZI;4>:]WN7:W+6?E.G]NF<*^SWZ&NI>Y\]@>XHBG[-,FQVNC1&F7EKZ_; +M^>>&;=M-]RO]R6Q,V[7Q]UNY_/R5\6'@VMWY^Y_*7J]ZW"U>)Y2#MIG"]S_/M=SILB?70" +M+N_Q^:)BMT5M'RUT!Y,NF58JZ^7YDJ0K]#(FU^I-ATV"VS\$F'[EWH\]MIXE +M%3Y9W#?&-%[5;M=_B]OV3?G:NW_#M_Y?RP"\T48M\C\7Z9C/N*SQ>6MLW;QV +M24(K^>5ED'WX>_!UZZ"I\ZTTQ*BFBCL+E,"'%O==0`M0_C@O@T)B0PZX&CDP +M$/6^[Y:B)[UDS.A`B;2)HBY3TAHH0CKZ=WQ:HI'[OQR2^,LF07O6FT'#'XPS +MQ\[TR<$0/QY)M.K507^K438@;"KV6T^HXO>#N]9P7Z\_%[XR1LW?%I^`B!T0 +M^[)2ON8[_3^L#27P_C@CQ[%\3A2Q^0>VU[B'#X*[K[LF5;4MAQ0#3#,@WI&V +M83^I\TP@3W\;QD3O3>R5T0V=ERV=U'HFFIP2`W\N`3.#'4WJJW_CO&BNY71# +M`OG4?8S6L>S'[1>VYEYZY0ZADU[EBH0J[,X11@\E+BJ2M)#]3[7%AV/_$HW8S3:J4F"7)VG9N""U\+P?00_Y#UY?)D@$'VESR?20 +M:]2E/\T*#VK=FP&N*`R8VY]$75*!D\N]+6WL0XO/23C-:%]4V))?._:_/-.G +M<.S=0DA/+4>!1@/ +ML0V9D-?V>YV^[\W;]W+M/Q+E[PP+K0L9(BIQ;_;QMT0A^QD +MJCBY,O2Y!Q7K^&F$$#L4(IPV?.UX/N^OY/M[WW>#ZY!9;7V_73X<,.GF_;LL +M[=B>":J(=K1?:8C_WE_U%LO@R2F?^B,Y>J)9N*[)6&PY%2M.;1(A?NU=XTJ& +M0YJ5/8\%":N343"]':[4+#-B?^QFI9(S+8H-BWQHU#]-WP=<Q/-U$**K +M_ICRR)4R0/N#577:PH3)D+X$_K-3F&1-N9?7>6DR8^^VJH=IKM3"0!4_+9:, +MDXNN&=2G:/O;UMX/P^^#3-F$3T]^XKZDGFQLKLUOFGSVX?HU=Y--_U+/PV3= +M?;?A5@:[ECDQ[*5LD\IT0(*(!D4@7^F-\ZL=.F[_,[?T4K-QV=J[\(HH1;)= +M_RWNY_L2-@>6#T?3[16%SIM5&C?@6 +MN@I-IK3C5U0BZ//[LW7FY)R@+*#9<_DLO`:-3>&21M@=YJPTI'%?8==IK#OL +M;AS;K-XF=)/+DO[\\F_R3H>%0VOO9N>'AB7];JX%HZDC%_9S>R[>[R2;8^WS +MV[>2:,K1&)CX=CE<;[T4/$KV-S,#N:2CZXW/:13TJ4ICF.KISXJPYR%8B*IZA@]C[^&Z^NI%[EW +MV9J`DP7-;I&0`7GLT-*T68S:+\.Q/>JG!?O'R]*)XJ40HNGGJ&T1HO*M0CU8 +M2;3C<@4)7\XXRE"M,F2YHB*4)1DA>Y2<:.YXO+JDV(HQ3"9/ET66.(]*D+LQ +M6A?R9YJGTW3],1F^3Y8HT++UY"YRQ[8S5=:5`J>NKS,ITG\'^??_I]/.Y,K? +M$MC2B9V>2W#HFE!>><+!<\,F]7LQ^(@>F``9?OEXJ59OBZMCL3=$T/^# +M+Z)<->>$Z3=@@)"6UA"@G[ZT-/R%.X)$2=[:[/6%R#Z8@+:FN>C,5?.!Z)MI +MB8OTD5>1Y#1[AS:]=7T>C-2PU;[\H5XQMF3JV4_#(LMIIA&[Q\4WBE$7LY>L +MW)],N!M&&8+$&NLW%::H/1'^<.?!!2N^*^:JZTNZIO['HZW#&%/5M9R +M>7]WQ=,%1/6M#ZVB]L68@O9K:7IBC=FH+'SSRA,G78IKF(QJ&X9CM38=F3QY +M8A9&39JH5@_X+M*L"MANU#Z2X/89,/++B=&DD2[BTZ.L@:P^8(U!?"'-3]]< +M4Q"*8F6M,;FM-5]K6NZ?5$*I1.BU>V*5$ZI^.B)=@[49[CTX6Z[MOX:3A[!- +M[@R\$PT_%B!_S::N)WG[DRSIO;+?Y)NB?]:&H!DKZM6A=.$5ITON@!OS2`OS +M98!KRTA]RIG2&S-+"(-RP3.Z(1-,D;&.G)_N<&?=GTT +M8C&?BB+081P8J;YEFT0O<#-]ZBA?WJ7(VYI7T$6J(H%O/=R[O1/OPS\%HRTQ +M.P6-S_89W^$B1>WM_W]: +M^+Z_O\/VW0PC;,1F-\5_T3;WW^$G=7S2NQHK7/-GV[9&[-W^]W0O+46H +M8O^NP,(6TJ*I[5+VDH7:MJFWD\%L/W=48F?+V?HMEC_W@M9]`D3PVH#5`,.' +M`U[[<@I)`>D5RXW[L(,+O0ROMSZ-.+VI7EK.`(N>=2$O++<665H0!*O'2Z5^ +M39X&M@W/%$2M4^7DM&]6B\`N2LY.,O8`,OQ^4SP>?++_.'3#8OEZ772$\J'O +MP8XUU,Y^>25^U31Y-WS76*8JEK'K[E@7_TVZ55_\>[!`NMGF)!N[L)'4#ZX( +M_LCYGJ6C-N>Z@O_T^R'^)5)!Z90@_0JF!V<]DI49DWEMC-J'+7_:3'^PMGP;Y^K-Q5GGWK6HZ\J]/?G@T>' +M+Y/AY#YC6R#L^^NS4V!][>$9=_#-^>7X5YQ:/N])HZG>GVP[.M;M739"G;EG +MOMDXM'?A*'ZGB/WW]?*4(EW^38Y7 +M>1-^V#9$P++5>PM*4<3>/>PCY'7=5\+T0VKKX89I"YF#(\PH//6;$L4>L6B6 +M':N\/NPS1);FR[T1//Q3R?ISZJWCP2D-W[G*'JXT[=TSK$DBCTY@M/R^$)VSTA[[V]JW4K,:@O +MAQS5T++<3X5R[7'QSNC%K'_6="8K]PYTS6L;\E`BWXTEL75YGGK+WJ4!TI(S +M:[L$CNI.@2B0%CT!3P]1<7_27E5!WL;UG(N'')M65?Q&6SSAJI23WR\^H]MN +MBL=ZR'M)H4F33TR$W1T!U=C,0'SN7BJ-W,"K%QOO<]F2M$4\.A9IZZFT[_4OR[58EPR>UW)#>BB1 +M<9;DY>*RMA*`()49ZEM][,99IRW=?X`BXYHAM7]A=PS5P:=(%57=H108R9U) +MM\_5GT1&I/[?#IJ3>EXIW]Z74FYU1#*^K[YCKT*]Q,H,NF!)0^KX-/QR6K:Z +M_TYZ4R4X:VK#LH2)JNB$8[T?'KN,61)H33^BB&[.QJH>ED;6]%_Q0/#$=HVN +M3L=GZ*<_0IKRM7YTBU[1.-)9-O;/IHEM8H,YE_^2]FQ].BW;K";R8T6Y*` +M+::ZK0:[ZIJ]L^HH::SZ/0Y^ST\ZIWSJC(4+X?98M;C_]N])^(53HZ*8TX($G+]VUY:-9>_'+=/@S=.W5+PHZF*`B +M8X\IGRAJ5\/J^%;0VC`[LANY6SC\^UV?3T2W"A)UKGV"9%E\J:VMIH[S-1!J +MC-?>^G[*^E5@":,NF"+$>>!?+S1]TZ/QR:]VYDW?-9G93%!]<=+2*A +MF2_R0N-8<[Z+/N,FU8=3)9=PZYG:1V/BAP2>K'@EBF-DRU2#88(6 +M$37WO%*&F1#_"TYZ-5N;_3EK6(;/E_=M3Y+>MV.S:-R9R=+2!1:)9\H(>A^8 +M_OI9&OGQN&^O)=DR\5NEI<>J8T=Z]\U:M^>W#-2GF$1N?X[Z_Q30X9P,S@TN +MI<0RT9N9=,@2Y[JZ9@6Y.&CA_ZTU0XO7;J&[HA]$SP&AY6/CNY=1R#Z74\][ +MR<9;Y<;HB?8KSP^*[E+[R[NK`\G_J%%BE,P\+13D&W1H&3>JIRQ0EFZ)+$P2 +M#+0XKA#XTX"U@?OKR(3=,;ZANS"2[L,4V<*F^XJ8>]+EG[;^DT=&6M +M)AM.GDZ%=BL$6+J_`'R3:"GO.!J6#H<&8LH[&+YXWW@S_,@/BB'G%U'[(@1/ +MA[T1\&;33W[]_YP-;%R6,8U<;LI*(XO'DW:VKDN\D]\C)@[=KY,=N\5H47JOL4ZANF2@AJ?QY)>G-Q8UH-+K86YG4L;$8ZFW4,-:S +M/!>Y*.]LA1<4TZJ0`V[YN2DN3TA`W=TTX]IUHKHK2T>VI8@OJ`F(4O[-6/?Y +M+UY2T);XWYS-`=]B=T@IN*(CHZESQ]6;1YL8MD?WT!6\.>OCE"(4OG\'R??L +M=[^_@E!/TN8_8SOQ^=9*P=);;NG!/TN`>3";_*,7[/PTHS/XL]$S*:T;0T?? +M*;5WCEUN5$:=14A&D&D<7DRX1N;>_M=0#F6RTCFW!YY.0>61>#-$51:-G#Z2 +MDQ)OL\G3X6L/SBN[CT:DNI6[CS2"[)Q%!+IS^+ZE"(]D7KJ7+_U\?Y_GRO+3Z$*QX-CEG&;*V/'AYXQ. +MTQ7Y9CJ8C:-JTJ9/)$LM2`7EE7CU-L(6T.8GGX^+SP]HLT^#]-1\MWBYCXS, +ML`*04ZELG,ES,U'9#]T;\&3I!];V3@R>2(Y>\.6=8T_<+D1EBZ8]$09U-5KR +M>/%(AO[=%W*8IF3K=F=(3Y101HFZ?XV/OB2R<=PV:.D([?/+*I\5/[U.&*I +M4-8A"E@-W[?#[>9`,=JNT53[_MZ_&Q%&/!6DY^S:EH&B]H;W6=?&+$X^3I[)T-=T`#JJ,X5CEJ0,QRCI[7LGM?/`\\<4W8*9?^D,,O3S%F"E.^;3>?0WW>>IKO_9>DRVB1N%4W'0*B +MD5I1V$;(E;Q]4/@P4,VZRG_8>V?EFV6]8/EO]#Y-BGT$,F-=>KE[D,/F4)/2 +ME+O11(C@VS=3WJH=&S#ZUEZW[GGB5L]F^A*F/;6",TZ&LR0(=$R1_?CEV.MD)6N.KNKL +M)"Q]C\_HG!EWY1^S8%W1SF[^_8,BDQ-P23TP%O/7MD:^9F7"DG5KZH@:6-4Y +M/:%QS[$'F`C)I/R!U]M&YFTQ!/OX4'O]SA6I$F:"1B$$U2@_1W"QN$['*?N_ +M`&^2.#+J/L.G?]F?>CJINK$CI_5O9J.QOS:W,1N--&?B-]:,H?U'QXJ4>>I7 +MNI?1R/\8OR>]^QCRK1LUPB45VXF)M"(-)BT0CA;F_GW +M?-=7*MFR5-5SM01[FSVOWGMMD!--4&EKBGP1DJ88\Z<+Q0K^VX%`JM$UDW!) +MRG0!S>S\]?#>GORZJK@^SA6L;S9O8I39_"'OH.#V]/BAG(V$O\7]<7*?]>3$ +M)3NRO+/P31;-_)R6YHM+0=07,?8;/HRQ,%%"/5&Q3C&DV-:7HCD*RBIP344+ +MN7SCMU]1`IE!*18+-`IP(57D$KG&-<(7DYQ0\\AF,WYT?P5VI1P:@`L-U3U*G[SQGM1.<-NUYZ +M-KW-IL.)=/+&(N_,E[0F3(33DOBB;SR1#I&-)K$VB]<9O.UU/VUV`EXYYN&H&=2NDZ8(Z9O(BZ,PWF5,.$)J9==N($)UFSVGE+LF]^,C,^3R8.?R +M5SRW@YK[_)6'J/1/K5N=VU:==F-[GXYMU_&.K5;UCW(F0`EQ]+0N_R4RA9\7XL;N@+'&K@RU%`R/DBIE-9)#F4\F%7 +M6COU^S6"\Q11HS\5#NMBWFBG2F\R1E=M,0K5'KQ)QW_DI,04KDYT:D./HU!O:U?RO83D,0BGM3 +M13Y@:P*+>I2SWB[-/H?C[FJN](N]^.:AM66IM<[Y)96_C\U<#HQ9HBF+LSDCZ>`7T +MJ<]9W3BG;N?)\VQ/N4'``W__VG1P```````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````/_E+Q/[,7]KU/_G_____________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_________________H!'_(O_ZQ_Z?_______________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________________________________________________________^@ +M1_R+_^L?^G__________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M________________________________________H$?\B__K'_I_________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +H_____________________________________________________P`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_large_splitted_rar_ae.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_large_splitted_rar_ae.uu new file mode 100644 index 0000000..9f463a4 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_large_splitted_rar_ae.uu @@ -0,0 +1,375 @@ +begin 644 - +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________H$P!T14,C1?%G9O?$J_A%^K]7@Y2NE=W^2Y[+`````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````````````````#U=_IYW_/U<_ +MH?\?3_/H>I>=B_GSNAS_7[]SU/CZGT>C]PIUI\# +MN/,^!\/T?3O\\_G?1SHL2*"O1V.[U>MZAYOR6#3_WY_TPY +M`=/Q4IX]'42-/%X!""QIJZ<(%2T_<[3[/Z>YZ.;I]:"Z!(!Q'*P#5O[KYO<[>EH^#3EG%=U +MUB!IZXV0;U("5+:D=^OZJFD\WZCO"PBJ2QY!E);,$>6"0?H]3J_O6I?7FZU= +M.,+Z[Z5/E(0)>*Z+7[(*5*E&1W"42AOFZ5?DF2_KU4^B^+U>77[(-%!#S_NP +MQ:.NGI;<"`]C?:O^:8H3^N\-O[8,GV_I]?_'S=*]\K^7N?^UD\P-T=O2S_!& +MU;Z%SX?NI..G]T6_!!4LQ:<3%T>!+IQW\;]T%WG5GP83,->>A1TAALLM<8W> +MN]%XKUQ^\'#K-J5OM3X^-+[NU?VMV^A/C4];?O/#3]L3X$LQ(\,D?C*_9^'( +M$4_(KULYY9ZB67_C>?A!)KU:L_WB(+)QT)WEY/MR*NCJ1F2;O>VH,6B5SQ:286\> +MKD<(SP5\>'<[/L(;I*TN9\<%(GSODHP7XL_407$P5-YIQ7[8F681SO +M*L)%M%;)JM\QRPTI*1$5(6^,L=_U?JYLCB!,W-B\[)W7['!:PB\'XY%V/XR +MP=KA./R6^X<`T;BS9D,V"+I;FS-Y?XJ$K73X^QY*R2."*'P;UJO7E$H&N\X@ +M/C%[1L5_;U7SR]WCO/9):4Y?(EI+>S$%V\]''EIWE6,$>6(O@+3E[G#\?"); +MLM@E?-3?CP*;D*S(U:ON4N?E<%T8)JF54U2VJU7FD,O@Z>QJR-2Z]$'[.JA1 +M.GM]KK]*3WMIN@Q8]9=O^N=OZ0OF$'83HEE&QW&8=Q9SC&7(HZ!T\56]-ARZ +M0CWLE=RG0:U[2V)E.'_K,KXFGKD,JPH2W)[CP\?_D'<+S8C_%+]EF32B&FU2 +MY,@:1B;SG3MZD%#;'BC"9%TM*_796%NG31&MW62'&8VV7G2&W*28_"I^'X>S +MX96^#80^^+?/@?3A_FU&%BKB"A6'M_R+O`W;3UFK8'X@2EPRF"BB.C*H#7`0 +M[(C!G>Y?E@TZ^!XL9IZ9E*Z5Q"L),WOXAO=#HS/?P^GS03$?ROOBVREKR,\I +M>K(/.)^J/,R(!][,]7T6A38[L;5*MPVE56+MFK +M`W=K>U(0(/$!VRF)'4[YX]$*QA:#)'L^(WZY)E"Q)1K^B:IO3ZKA@.6L6=`"_YLZ(0Y&3%,0_)L67=S;-O4#B,0'6)R[=^,ZP/SWX0@&.8'L81\ +M%H:KS8?+YM;=WC9+O^/@B!''YT.F5OPU\[;]SX+9M#%'>I]%&&WG1`U:.-"- +M[8';;(*FK?I\/LS.-T9XCHO61;2M@$\`6CG'QY4.\P!GUA3?ITK0CW<&SL8L, +M37TB/+XZ90SU^_0EB>ZOK]_1MDA*F4]:`/,ZQR;5C2@1O+7Q/$52F4OGN\/,_'+"G,R[7/2IL$FBRTX>+ +M,"R`D5>')8'I&,]:7?]56WD.)^0#G"0U,68W%CE(W]/6PQ0MZ).EB[;?2AL. +MOC$%1A/+!#J/''Z]?K%@_&YC/\*V^;9#_'SSHD]N\V0$IHKP^J$Y6 +MAY=(?^EEA[BZV[/+6@$A"3V*>`XXEYGQI+%"%?@DKWC,5,9XRBG(DCB3:DC7 +M,O:X1##E0=;8G*N,KDE4="68,2VHU`0SLDRPH(H$Y%RN%;TG->M7CEJU'K(3 +M7^^OJ7O,S+C%JL8X<2NN"?]\NON0;:O0Y^=/?!#'GEP9VO@VX(#O7]M?X]1H +MA445@;>0V`BP8$E=-_:ZTAPQIY[9A\I2Q_=L9@>&,5(2KFQQ\4**J.*B+AW* +M?*`5[E.3JD;5XL%UE<[5R+HJ*^O*J4MBU*7)5S4_#J\_&(UOF-HZ@43FI +MH#,4-FD4T6"!9<O"/P;L9Y0\$;5>\<;Q]KP2?\5 +M:G'1*;2JR2L'T?#/L4Z-GC21?PUWK +M.CGG+[7ZT8.C)'8_7G=L6D8=%L9<$O#1RM>'TQU#I3K..2U.S!&RG5WZN95X/S(V[2D03%@"S: +MCD[T],"*J\LOZQ]K+%H3[(9Y<^Z0#>U9D`\NU,NS +MZ?:N?X/3?QI*:J(L6>($A+QV[!$AQ8)46R\6"NEJ5\U?;TP3K0"U=5=I'H=; +M4U\[\8:5_?#VZO-2-P(!N,YCV/$&*U=*H256[0JSR89H)LY4XPT5TM\KS63+<@_!J;63WE0P!Z//K2TON'^XDKUL3+KADX)KB4#CP +M3?2";-\^G*COB>2.&;FO5]JT=/^7\KM#RYKM7V_K5^E%>[Z/*X.TR*_CYZ_0 +MDJ@8/1(I2Q7S@SD>/^WD&=5=70Y2B]C4!5^7+IL)S&C;)5@>\6#5ET-3EI4? +M=W.`GG8I@F2(!!$:V,5]4?O:'3\5?+%^M66W]%&>O!"[MZMB$/DRR?VZ4"2L +M?S$[1D#@=M95,6MKTC\C&%[XM+Y[N">&]*BY9?3`;8O;M>-B?KQDWU&&LKYO*7BN&Z)? +M.1LJ9O&\SL.%4K;C4F@!9NMF:=/8UM.OVN_[WZR2-K._^\9OGE/8Z4/D)G&8 +M2NF::OD)F;4KU#B?LB_ON7)G*2`48/P@BRROKP^*$_2R0G^YH=[L9>R6.]N[ +M.33"H=?,_CT.?FQ98>3V_Y09`[MO>)F+Y9DU7KK_H\=2!=E-_'L[\&W'RYVML>6W2B5XVTKCM +M8$=QWDW7T)C=H/2`M>F>1Z.EFT89XYM6]Y`.74[6+UO9V-#+L2*RG?O$G&H] +M`_8.C5?AT",*;PS'GFM70XN>WV4Q427^(`*\/X#CB^$(`_Z;QM? +MB78W;%ULSQ]SP7'831UC7'T-)1'M@\&T\A :U"^,-";S5OB:6G$,M^1P8+ +M(5[>J-K6.5*L'$0+)C=0HM;#!4F--U/NZDV&E#R0UWL[7NQTR?(K-5,,P+(U +M-G9HX8/FZ7$?96E_ZGDBWBI,:/#Y=^S;#LY:>^CB6&-NY)Y7X[_!HZ6Z,D&]`WT!%WRJ<9];OD]9Y>24+=]B3 +MT1H[A.%^F.1/,DM#4>!\9]0K>"FYBN[!+*PDPZ'TMGH"-NLKU?XK&8!'XW9[ +MRE.P5>/,E6Z?%N:LC`<1CX,4F<@B!KO78!YO$IQ`''Q7JO"IX\?BBR#]:TMS +MQ5EEG7D[+^G+:=BG2QFL>/BO-QZJZ$.H` +MJ_PPEC.-JXBK7]T=G#'\]ON_/CN":U"TF8LK:^LVXWN3E`F6;_#F@\C#/D]9 +MLWKT#%HA\3BFCW4MIP#\!5<]$0Y$=*]?;JE'.^>7#5O5WUX9)44:))UM76AT +M?_M55^=35MH8SBP1JTK' +MD6Y=#^?WQI>=*9C8FR=6JV)]+T%__'6]A[DT)F]%M.9/8%$58 +M0S)=?9\16F`[F7>"]22&A^BE$`:%]89YK8LMX4\?*>YWLG)25RK*.K)901`V +M]&IJZOJ1J_6GW!LR>I^"`[07J:]@%V?5BQJ?SP/;WQ=6$)VG)G>,CD;"*2]BO';UTABY)#56A_?JZ>CVO<+0[/9T^Y#1S1\'1BO@_7G[ +MF+:SX]=K^LYM7V:F+!8@8VWCQE9 +MON?5'U;4?[#8J%5Z%VJ6=4&'1J4HO;()4E6Z9]B#F&EOGA"Y]OY\)@Z$KQP\]L>4<',^O+3P:'OZ[N0-$59`T+&V[RU6]6;[V-V/2\DOQI9RJV +M8A[VJ&3N-FHO1'WX^C$`6&2L/DNQK)5_WUI\QDNC?X],*1X0H=%T;6[0R[0Y +M+&X>-&5*QYNCCJ;63LCPVSZ%<=8_&<$7YI5O82X$^Z<##T4I_XS;/-5[M4JN)*<.,PUX=<@21*+8?\@!8`NJL$\VJOXQXJ9_D3.WKH>4UT +MR@[R57^/8HS5-09>'[^!EC_/B&H.[#.Q3A=.O\P!`!P`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_pax_schily_xattr.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_pax_schily_xattr.c new file mode 100644 index 0000000..7554f6d --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_pax_schily_xattr.c @@ -0,0 +1,70 @@ +/*- + * Copyright (c) 2016 IBM Corporation + * Copyright (c) 2003-2007 Tim Kientzle + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This test case's code has been derived from test_entry.c + */ +#include "test.h" + +DEFINE_TEST(test_schily_xattr_pax) +{ + struct archive *a; + struct archive_entry *ae; + const char *refname = "test_read_pax_schily_xattr.tar"; + const char *xname; /* For xattr tests. */ + const void *xval; /* For xattr tests. */ + size_t xsize; /* For xattr tests. */ + const char *string, *array; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + + extract_reference_file(refname); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + assertEqualInt(ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_xattr_count(ae)); + assertEqualInt(2, archive_entry_xattr_reset(ae)); + + assertEqualInt(0, archive_entry_xattr_next(ae, &xname, &xval, &xsize)); + assertEqualString(xname, "security.selinux"); + string = "system_u:object_r:unlabeled_t:s0"; + assertEqualString(xval, string); + /* the xattr's value also contains the terminating \0 */ + assertEqualInt((int)xsize, strlen(string) + 1); + + assertEqualInt(0, archive_entry_xattr_next(ae, &xname, &xval, &xsize)); + assertEqualString(xname, "security.ima"); + assertEqualInt((int)xsize, 265); + /* we only compare the first 12 bytes */ + array = "\x03\x02\x04\xb0\xe9\xd6\x79\x01\x00\x2b\xad\x1e"; + assertEqualMem(xval, array, 12); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_pax_schily_xattr.tar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_pax_schily_xattr.tar.uu new file mode 100644 index 0000000..52f7a8f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_pax_schily_xattr.tar.uu @@ -0,0 +1,231 @@ +begin 644 test_schily_xattr_pax.tar +M+B]087A(96%D97)S+C$U,C4O8V]N9F9I;&5S```````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````#`P,#`V-#0`,#`P,#`P,``P,#`P,#`P`#`P,#`P,#`P-C0W +M`#$R-S$R,C$P-3`V`#`Q,C4V-@`@>``````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````!UW6X5O?Y6: +M9^':P2MZR[4)$@W?)B6GX0U@<,0M%6YNMO%OG+IS%/.< +M,"A(N&S.F9]=!*5=\).X."2$GUGJ,0C:@+G#$M_E8UQP,LU-G(8IKW^K^<8* +M*3_.N0'%8.^$8S$`D9XOF+DK<<)U34U'_"O5/22YS96QI;G5X +M/7-Y61I`P!#2DTAT@```$*((<0`````__\#`$-*32'2```` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_truncated.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_truncated.c new file mode 100644 index 0000000..3991ab2 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_truncated.c @@ -0,0 +1,135 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/lib/libarchive/test/test_read_truncated.c,v 1.4 2008/09/01 05:38:33 kientzle Exp $"); + +static char buff[1000000]; +static char buff2[100000]; + +DEFINE_TEST(test_read_truncated) +{ + struct archive_entry *ae; + struct archive *a; + unsigned int i; + size_t used; + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used)); + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file"); + archive_entry_set_mode(ae, S_IFREG | 0755); + for (i = 0; i < sizeof(buff2); i++) + buff2[i] = (unsigned char)rand(); + archive_entry_set_size(ae, sizeof(buff2)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, sizeof(buff2), archive_write_data(a, buff2, sizeof(buff2))); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Now, read back a truncated version of the archive and + * verify that we get an appropriate error. */ + for (i = 1; i < used + 100; i += 100) { + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + if (i < 512) { + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_open_memory(a, buff, i)); + goto wrap_up; + } else { + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, i)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + + if (i < 512 + sizeof(buff2)) { + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buff2, sizeof(buff2))); + goto wrap_up; + } else { + assertEqualIntA(a, sizeof(buff2), archive_read_data(a, buff2, sizeof(buff2))); + } + + /* Verify the end of the archive. */ + /* Archive must be long enough to capture a 512-byte + * block of zeroes after the entry. (POSIX requires a + * second block of zeros to be written but libarchive + * does not return an error if it can't consume + * it.) */ + if (i < 512 + 512*((sizeof(buff2) + 511)/512) + 512) { + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); + } else { + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + } + wrap_up: + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + } + + + + /* Same as above, except skip the body instead of reading it. */ + for (i = 1; i < used + 100; i += 100) { + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + if (i < 512) { + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_open_memory(a, buff, i)); + goto wrap_up2; + } else { + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, i)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + + if (i < 512 + 512*((sizeof(buff2)+511)/512)) { + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data_skip(a)); + goto wrap_up2; + } else { + assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a)); + } + + /* Verify the end of the archive. */ + /* Archive must be long enough to capture a 512-byte + * block of zeroes after the entry. (POSIX requires a + * second block of zeros to be written but libarchive + * does not return an error if it can't consume + * it.) */ + if (i < 512 + 512*((sizeof(buff2) + 511)/512) + 512) { + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); + } else { + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + } + wrap_up2: + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + } +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_truncated_filter.c b/dependencies/libarchive-3.4.2/libarchive/test/test_read_truncated_filter.c new file mode 100644 index 0000000..632638d --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_truncated_filter.c @@ -0,0 +1,173 @@ +/*- + * Copyright (c) 2007-2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * Check that we generate an error message when reading a truncated + * gzip, bzip2, compress, xz, lzma, or lzip file. + */ + +static void +test_truncation(const char *compression, + int (*set_compression)(struct archive *), int can_prog) +{ + struct archive_entry *ae; + struct archive* a; + char path[16]; + char *buff, *data; + size_t buffsize, datasize, used1; + int i, j, r, use_prog; + + buffsize = 2000000; + assert(NULL != (buff = (char *)malloc(buffsize))); + if (buff == NULL) + return; + + datasize = 10000; + assert(NULL != (data = (char *)malloc(datasize))); + if (data == NULL) { + free(buff); + return; + } + memset(data, 0, datasize); + + /* + * Write a bunch of files with semi-random data. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_add_filter_compress(a)); + r = (*set_compression)(a); + if (r != ARCHIVE_OK && !can_prog) { + skipping("%s writing not supported on this platform", + compression); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); + free(data); + return; + } + use_prog = (r == ARCHIVE_WARN && can_prog); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used1)); + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_size(ae, datasize); + for (i = 0; i < 100; i++) { + sprintf(path, "%s%d", compression, i); + archive_entry_copy_pathname(ae, path); + failure("%s", path); + if (!assertEqualIntA(a, ARCHIVE_OK, + archive_write_header(a, ae))) { + archive_write_free(a); + free(data); + free(buff); + return; + } + for (j = 0; j < (int)datasize; ++j) { + data[j] = (char)(rand() % 256); + } + failure("%s", path); + if (!assertEqualIntA(a, datasize, + archive_write_data(a, data, datasize))) { + archive_write_free(a); + free(data); + free(buff); + return; + } + } + archive_entry_free(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used1 - used1/64)); + for (i = 0; i < 100; i++) { + if (ARCHIVE_OK != archive_read_next_header(a, &ae)) { + failure("Should have non-NULL error message for %s", + compression); + assert(NULL != archive_error_string(a)); + break; + } + sprintf(path, "%s%d", compression, i); + assertEqualString(path, archive_entry_pathname(ae)); + if (datasize != (size_t)archive_read_data(a, data, datasize)) { + failure("Should have non-NULL error message for %s", + compression); + assert(NULL != archive_error_string(a)); + break; + } + } + assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, + archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + free(data); + free(buff); +} + +DEFINE_TEST(test_read_truncated_filter_bzip2) +{ + test_truncation("bzip2", archive_write_add_filter_bzip2, canBzip2()); +} + +DEFINE_TEST(test_read_truncated_filter_compress) +{ + test_truncation("compress", archive_write_add_filter_compress, 0); +} + +DEFINE_TEST(test_read_truncated_filter_gzip) +{ + test_truncation("gzip", archive_write_add_filter_gzip, canGzip()); +} + +DEFINE_TEST(test_read_truncated_filter_lzip) +{ + test_truncation("lzip", archive_write_add_filter_lzip, 0); +} + +DEFINE_TEST(test_read_truncated_filter_lzma) +{ + test_truncation("lzma", archive_write_add_filter_lzma, 0); +} + +DEFINE_TEST(test_read_truncated_filter_lzop) +{ + test_truncation("lzop", archive_write_add_filter_lzop, canLzop()); +} + +DEFINE_TEST(test_read_truncated_filter_xz) +{ + test_truncation("xz", archive_write_add_filter_xz, 0); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_sparse_basic.c b/dependencies/libarchive-3.4.2/libarchive/test/test_sparse_basic.c new file mode 100644 index 0000000..0fbb7f7 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_sparse_basic.c @@ -0,0 +1,662 @@ +/*- + * Copyright (c) 2010-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_LINUX_TYPES_H +#include +#endif +#ifdef HAVE_LINUX_FIEMAP_H +#include +#endif +#ifdef HAVE_LINUX_FS_H +#include +#endif + +/* The logic to compare sparse file data read from disk with the + * specification is a little involved. Set to 1 to have the progress + * dumped. */ +#define DEBUG 0 + +/* + * NOTE: On FreeBSD and Solaris, this test needs ZFS. + * You may perform this test as + * 'TMPDIR= libarchive_test'. + */ + +struct sparse { + enum { DATA, HOLE, END } type; + size_t size; +}; + +static void create_sparse_file(const char *, const struct sparse *); + +#if defined(__APPLE__) +/* On APFS holes need to be at least 4096x4097 bytes */ +#define MIN_HOLE 16781312 +#else +/* Elsewhere we work with 4096*10 bytes */ +#define MIN_HOLE 409600 +#endif + +#if defined(_WIN32) && !defined(__CYGWIN__) +#include +/* + * Create a sparse file on Windows. + */ + +#if !defined(PATH_MAX) +#define PATH_MAX MAX_PATH +#endif +#if !defined(__BORLANDC__) +#define getcwd _getcwd +#endif + +static int +is_sparse_supported(const char *path) +{ + char root[MAX_PATH+1]; + char vol[MAX_PATH+1]; + char sys[MAX_PATH+1]; + DWORD flags; + BOOL r; + + strncpy(root, path, sizeof(root)-1); + if (((root[0] >= 'c' && root[0] <= 'z') || + (root[0] >= 'C' && root[0] <= 'Z')) && + root[1] == ':' && + (root[2] == '\\' || root[2] == '/')) + root[3] = '\0'; + else + return (0); + assertEqualInt((r = GetVolumeInformation(root, vol, + sizeof(vol), NULL, NULL, &flags, sys, sizeof(sys))), 1); + return (r != 0 && (flags & FILE_SUPPORTS_SPARSE_FILES) != 0); +} + +static void +create_sparse_file(const char *path, const struct sparse *s) +{ + char buff[1024]; + HANDLE handle; + DWORD dmy; + + memset(buff, ' ', sizeof(buff)); + + handle = CreateFileA(path, GENERIC_WRITE, 0, + NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, + NULL); + assert(handle != INVALID_HANDLE_VALUE); + assert(DeviceIoControl(handle, FSCTL_SET_SPARSE, NULL, 0, + NULL, 0, &dmy, NULL) != 0); + + uint64_t offsetSoFar = 0; + + while (s->type != END) { + if (s->type == HOLE) { + LARGE_INTEGER fileOffset, beyondOffset, distanceToMove; + fileOffset.QuadPart = offsetSoFar; + beyondOffset.QuadPart = offsetSoFar + s->size; + distanceToMove.QuadPart = s->size; + + FILE_ZERO_DATA_INFORMATION zeroInformation; + zeroInformation.FileOffset = fileOffset; + zeroInformation.BeyondFinalZero = beyondOffset; + + DWORD bytesReturned; + assert(SetFilePointerEx(handle, distanceToMove, + NULL, FILE_CURRENT) != 0); + assert(SetEndOfFile(handle) != 0); + assert(DeviceIoControl(handle, FSCTL_SET_ZERO_DATA, &zeroInformation, + sizeof(FILE_ZERO_DATA_INFORMATION), NULL, 0, &bytesReturned, NULL) != 0); + } else { + DWORD w, wr; + size_t size; + + size = s->size; + while (size) { + if (size > sizeof(buff)) + w = sizeof(buff); + else + w = (DWORD)size; + assert(WriteFile(handle, buff, w, &wr, NULL) != 0); + size -= wr; + } + } + offsetSoFar += s->size; + s++; + } + assertEqualInt(CloseHandle(handle), 1); +} + +#else + +#if defined(HAVE_LINUX_FIEMAP_H) +/* + * FIEMAP, which can detect 'hole' of a sparse file, has + * been supported from 2.6.28 + */ + +static int +is_sparse_supported_fiemap(const char *path) +{ + const struct sparse sparse_file[] = { + /* This hole size is too small to create a sparse + * files for almost filesystem. */ + { HOLE, 1024 }, { DATA, 10240 }, + { END, 0 } + }; + int fd, r; + struct fiemap *fm; + char buff[1024]; + const char *testfile = "can_sparse"; + + (void)path; /* UNUSED */ + memset(buff, 0, sizeof(buff)); + create_sparse_file(testfile, sparse_file); + fd = open(testfile, O_RDWR); + if (fd < 0) + return (0); + fm = (struct fiemap *)buff; + fm->fm_start = 0; + fm->fm_length = ~0ULL;; + fm->fm_flags = FIEMAP_FLAG_SYNC; + fm->fm_extent_count = (sizeof(buff) - sizeof(*fm))/ + sizeof(struct fiemap_extent); + r = ioctl(fd, FS_IOC_FIEMAP, fm); + close(fd); + unlink(testfile); + return (r >= 0); +} + +#if !defined(SEEK_HOLE) || !defined(SEEK_DATA) +static int +is_sparse_supported(const char *path) +{ + return is_sparse_supported_fiemap(path); +} +#endif +#endif + +#if defined(_PC_MIN_HOLE_SIZE) + +/* + * FreeBSD and Solaris can detect 'hole' of a sparse file + * through lseek(HOLE) on ZFS. (UFS does not support yet) + */ + +static int +is_sparse_supported(const char *path) +{ + return (pathconf(path, _PC_MIN_HOLE_SIZE) > 0); +} + +#elif defined(SEEK_HOLE) && defined(SEEK_DATA) + +static int +is_sparse_supported(const char *path) +{ + const struct sparse sparse_file[] = { + /* This hole size is too small to create a sparse + * files for almost filesystem. */ + { HOLE, 1024 }, { DATA, 10240 }, + { END, 0 } + }; + int fd, r; + const char *testfile = "can_sparse"; + + (void)path; /* UNUSED */ + create_sparse_file(testfile, sparse_file); + fd = open(testfile, O_RDWR); + if (fd < 0) + return (0); + r = lseek(fd, 0, SEEK_HOLE); + close(fd); + unlink(testfile); +#if defined(HAVE_LINUX_FIEMAP_H) + if (r < 0) + return (is_sparse_supported_fiemap(path)); +#endif + return (r >= 0); +} + +#elif !defined(HAVE_LINUX_FIEMAP_H) + +/* + * Other system may do not have the API such as lseek(HOLE), + * which detect 'hole' of a sparse file. + */ + +static int +is_sparse_supported(const char *path) +{ + (void)path; /* UNUSED */ + return (0); +} + +#endif + +/* + * Create a sparse file on POSIX like system. + */ + +static void +create_sparse_file(const char *path, const struct sparse *s) +{ + char buff[1024]; + int fd; + uint64_t total_size = 0; + const struct sparse *cur = s; + + memset(buff, ' ', sizeof(buff)); + assert((fd = open(path, O_CREAT | O_WRONLY, 0600)) != -1); + + /* Handle holes at the end by extending the file */ + while (cur->type != END) { + total_size += cur->size; + ++cur; + } + assert(ftruncate(fd, total_size) != -1); + + while (s->type != END) { + if (s->type == HOLE) { + assert(lseek(fd, s->size, SEEK_CUR) != (off_t)-1); + } else { + size_t w, size; + + size = s->size; + while (size) { + if (size > sizeof(buff)) + w = sizeof(buff); + else + w = size; + assert(write(fd, buff, w) != (ssize_t)-1); + size -= w; + } + } + s++; + } + close(fd); +} + +#endif + +/* + * Sparse test with directory traversals. + */ +static void +verify_sparse_file(struct archive *a, const char *path, + const struct sparse *sparse, int expected_holes) +{ + struct archive_entry *ae; + const void *buff; + size_t bytes_read; + int64_t offset, expected_offset, last_offset; + int holes_seen = 0; + + create_sparse_file(path, sparse); + assert((ae = archive_entry_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, path)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae)); + + expected_offset = 0; + last_offset = 0; + while (ARCHIVE_OK == archive_read_data_block(a, &buff, &bytes_read, + &offset)) { + const char *start = buff; +#if DEBUG + fprintf(stderr, "%s: bytes_read=%d offset=%d\n", path, (int)bytes_read, (int)offset); +#endif + if (offset > last_offset) { + ++holes_seen; + } + /* Blocks entirely before the data we just read. */ + while (expected_offset + (int64_t)sparse->size < offset) { +#if DEBUG + fprintf(stderr, " skipping expected_offset=%d, size=%d\n", (int)expected_offset, (int)sparse->size); +#endif + /* Must be holes. */ + assert(sparse->type == HOLE); + expected_offset += sparse->size; + ++sparse; + } + /* Block that overlaps beginning of data */ + if (expected_offset < offset + && expected_offset + (int64_t)sparse->size <= offset + (int64_t)bytes_read) { + const char *end = (const char *)buff + (expected_offset - offset) + (size_t)sparse->size; +#if DEBUG + fprintf(stderr, " overlapping hole expected_offset=%d, size=%d\n", (int)expected_offset, (int)sparse->size); +#endif + /* Must be a hole, overlap must be filled with '\0' */ + if (assert(sparse->type == HOLE)) { + assertMemoryFilledWith(start, end - start, '\0'); + } + start = end; + expected_offset += sparse->size; + ++sparse; + } + /* Blocks completely contained in data we just read. */ + while (expected_offset + (int64_t)sparse->size <= offset + (int64_t)bytes_read) { + const char *end = (const char *)buff + (expected_offset - offset) + (size_t)sparse->size; + if (sparse->type == HOLE) { +#if DEBUG + fprintf(stderr, " contained hole expected_offset=%d, size=%d\n", (int)expected_offset, (int)sparse->size); +#endif + + /* verify data corresponding to hole is '\0' */ + if (end > (const char *)buff + bytes_read) { + end = (const char *)buff + bytes_read; + } + assertMemoryFilledWith(start, end - start, '\0'); + start = end; + expected_offset += sparse->size; + ++sparse; + } else if (sparse->type == DATA) { +#if DEBUG + fprintf(stderr, " contained data expected_offset=%d, size=%d\n", (int)expected_offset, (int)sparse->size); +#endif + /* verify data corresponding to hole is ' ' */ + if (assert(expected_offset + sparse->size <= offset + bytes_read)) { + assert(start == (const char *)buff + (size_t)(expected_offset - offset)); + assertMemoryFilledWith(start, end - start, ' '); + } + start = end; + expected_offset += sparse->size; + ++sparse; + } else { + break; + } + } + /* Block that overlaps end of data */ + if (expected_offset < offset + (int64_t)bytes_read) { + const char *end = (const char *)buff + bytes_read; +#if DEBUG + fprintf(stderr, " trailing overlap expected_offset=%d, size=%d\n", (int)expected_offset, (int)sparse->size); +#endif + /* Must be a hole, overlap must be filled with '\0' */ + if (assert(sparse->type == HOLE)) { + assertMemoryFilledWith(start, end - start, '\0'); + } + } + last_offset = offset + bytes_read; + } + /* Count a hole at EOF? */ + if (last_offset < archive_entry_size(ae)) { + ++holes_seen; + } + + /* Verify blocks after last read */ + while (sparse->type == HOLE) { + expected_offset += sparse->size; + ++sparse; + } + assert(sparse->type == END); + assertEqualInt(expected_offset, archive_entry_size(ae)); + + failure("%s", path); + assertEqualInt(holes_seen, expected_holes); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + archive_entry_free(ae); +} + +#if defined(_WIN32) && !defined(__CYGWIN__) +#define close _close +#define open _open +#endif + +/* + * Sparse test without directory traversals. + */ +static void +verify_sparse_file2(struct archive *a, const char *path, + const struct sparse *sparse, int blocks, int preopen) +{ + struct archive_entry *ae; + int fd; + + (void)sparse; /* UNUSED */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_pathname(ae, path); + if (preopen) + fd = open(path, O_RDONLY | O_BINARY); + else + fd = -1; + assertEqualIntA(a, ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, fd, NULL)); + if (fd >= 0) + close(fd); + /* Verify the number of holes only, not its offset nor its + * length because those alignments are deeply dependence on + * its filesystem. */ + failure("%s", path); + assertEqualInt(blocks, archive_entry_sparse_count(ae)); + archive_entry_free(ae); +} + +static void +test_sparse_whole_file_data(void) +{ + struct archive_entry *ae; + int64_t offset; + int i; + + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_size(ae, 1024*10); + + /* + * Add sparse block data up to the file size. + */ + offset = 0; + for (i = 0; i < 10; i++) { + archive_entry_sparse_add_entry(ae, offset, 1024); + offset += 1024; + } + + failure("There should be no sparse"); + assertEqualInt(0, archive_entry_sparse_count(ae)); + archive_entry_free(ae); +} + +DEFINE_TEST(test_sparse_basic) +{ + char *cwd; + struct archive *a; + const char *skip_sparse_tests; + /* + * The alignment of the hole of sparse files deeply depends + * on filesystem. In my experience, sparse_file2 test with + * 204800 bytes hole size did not pass on ZFS and the result + * of that test seemed the size was too small, thus you should + * keep a hole size more than 409600 bytes to pass this test + * on all platform. + */ + const struct sparse sparse_file0[] = { + // 0 // 1024 + { DATA, 1024 }, { HOLE, MIN_HOLE + 1638400 }, + // 2049024 // 2051072 + { DATA, 2048 }, { HOLE, MIN_HOLE + 1638400 }, + // 4099072 // 4103168 + { DATA, 4096 }, { HOLE, MIN_HOLE + 20070400 }, + // 24583168 // 24591360 + { DATA, 8192 }, { HOLE, MIN_HOLE + 204390400 }, + // 229391360 // 229391361 + { DATA, 1 }, { END, 0 } + }; + const struct sparse sparse_file1[] = { + { HOLE, MIN_HOLE }, { DATA, 1 }, + { HOLE, MIN_HOLE }, { DATA, 1 }, + { HOLE, MIN_HOLE }, { END, 0 } + }; + const struct sparse sparse_file2[] = { + { HOLE, MIN_HOLE }, { DATA, 1024 }, + { HOLE, MIN_HOLE + 409600 * 1 }, { DATA, 1024 }, + { HOLE, MIN_HOLE + 409600 * 2 }, { DATA, 1024 }, + { HOLE, MIN_HOLE + 409600 * 3 }, { DATA, 1024 }, + { HOLE, MIN_HOLE + 409600 * 4 }, { DATA, 1024 }, + { HOLE, MIN_HOLE + 409600 * 5 }, { DATA, 1024 }, + { HOLE, MIN_HOLE + 409600 * 6 }, { DATA, 1024 }, + { HOLE, MIN_HOLE + 409600 * 7 }, { DATA, 1024 }, + { HOLE, MIN_HOLE + 409600 * 8 }, { DATA, 1024 }, + { HOLE, MIN_HOLE + 409600 * 9}, { DATA, 1024 },/* 10 */ + { HOLE, MIN_HOLE }, { DATA, 1024 * 1 }, + { HOLE, MIN_HOLE + 409600 * 1 }, { DATA, 1024 * 2 }, + { HOLE, MIN_HOLE + 409600 * 2 }, { DATA, 1024 * 3 }, + { HOLE, MIN_HOLE + 409600 * 3 }, { DATA, 1024 * 4 }, + { HOLE, MIN_HOLE + 409600 * 4 }, { DATA, 1024 * 5 }, + { HOLE, MIN_HOLE + 409600 * 5 }, { DATA, 1024 * 6 }, + { HOLE, MIN_HOLE + 409600 * 6 }, { DATA, 1024 * 7 }, + { HOLE, MIN_HOLE + 409600 * 7 }, { DATA, 1024 * 8 }, + { HOLE, MIN_HOLE + 409600 * 8 }, { DATA, 1024 * 9 }, + { HOLE, MIN_HOLE + 409600 * 9}, { DATA, 1024 * 10},/* 20 */ + { END, 0 } + }; + const struct sparse sparse_file3[] = { + /* This hole size is too small to create a sparse file */ + { HOLE, 1 }, { DATA, 10240 }, + { HOLE, 1 }, { DATA, 10240 }, + { HOLE, 1 }, { DATA, 10240 }, + { END, 0 } + }; + const struct sparse sparse_file4[] = { + { DATA, 4096 }, { HOLE, 0xc0000000 }, + /* This hole overflows the offset if stored in 32 bits. */ + { DATA, 4096 }, { HOLE, 0x50000000 }, + { END, 0 } + }; + + /* + * Test for the case that sparse data indicates just the whole file + * data. + */ + test_sparse_whole_file_data(); + + skip_sparse_tests = getenv("SKIP_TEST_SPARSE"); + if (skip_sparse_tests != NULL) { + skipping("Skipping sparse tests due to SKIP_TEST_SPARSE " + "environment variable"); + return; + } + + /* Check if the filesystem where CWD on can + * report the number of the holes of a sparse file. */ +#ifdef PATH_MAX + cwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */ +#else + cwd = getcwd(NULL, 0); +#endif + if (!assert(cwd != NULL)) + return; + if (!is_sparse_supported(cwd)) { + free(cwd); + skipping("This filesystem or platform do not support " + "the reporting of the holes of a sparse file through " + "API such as lseek(HOLE)"); + return; + } + + /* + * Get sparse data through directory traversals. + */ + assert((a = archive_read_disk_new()) != NULL); + + verify_sparse_file(a, "file0", sparse_file0, 4); + verify_sparse_file(a, "file1", sparse_file1, 3); + verify_sparse_file(a, "file2", sparse_file2, 20); + /* Encoded non sparse; expect a data block but no sparse entries. */ + verify_sparse_file(a, "file3", sparse_file3, 0); + verify_sparse_file(a, "file4", sparse_file4, 2); + + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Get sparse data through archive_read_disk_entry_from_file(). + */ + assert((a = archive_read_disk_new()) != NULL); + + verify_sparse_file2(a, "file0", sparse_file0, 5, 0); + verify_sparse_file2(a, "file0", sparse_file0, 5, 1); + + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + free(cwd); +} + +DEFINE_TEST(test_fully_sparse_files) +{ + char *cwd; + struct archive *a; + const char *skip_sparse_tests; + + const struct sparse sparse_file[] = { + { HOLE, MIN_HOLE }, { END, 0 } + }; + + skip_sparse_tests = getenv("SKIP_TEST_SPARSE"); + if (skip_sparse_tests != NULL) { + skipping("Skipping sparse tests due to SKIP_TEST_SPARSE " + "environment variable"); + return; + } + + /* Check if the filesystem where CWD on can + * report the number of the holes of a sparse file. */ +#ifdef PATH_MAX + cwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */ +#else + cwd = getcwd(NULL, 0); +#endif + if (!assert(cwd != NULL)) + return; + if (!is_sparse_supported(cwd)) { + free(cwd); + skipping("This filesystem or platform do not support " + "the reporting of the holes of a sparse file through " + "API such as lseek(HOLE)"); + return; + } + + assert((a = archive_read_disk_new()) != NULL); + + /* Fully sparse files are encoded with a zero-length "data" block. */ + verify_sparse_file(a, "file0", sparse_file, 1); + + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + free(cwd); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_splitted_rar_seek_support_aa.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_splitted_rar_seek_support_aa.uu new file mode 100644 index 0000000..0344d2c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_splitted_rar_seek_support_aa.uu @@ -0,0 +1,159 @@ +begin 644 - +M4F%R(1H'`,^0R!M87)G:6XZ(#`N-SEI;B!]"@D)4"![(&UAR!M87)G:6XM8F]T=&]M.B`P+C`X:6X@?0H)"4@Q+G=ER!F;VYT+69A;6EL>3H@(DQI8F5R871I;VX@4V5R:68B+"!S97)I9B!] +M"@D)2#$N8VIK('L@9F]N="UF86UI;'DZ(")":71S=')E86T@5F5R82!386YS +M(B!]"@D)2#$N8W1L('L@9F]N="UF86UI;'DZ(")&R!F;VYT+69A;6EL>3H@(D)I='-TR!F;VYT+69A;6EL>3H@(D9R965386YS(B!]"@D)5%0N8VIK('L@ +M9F]N="UF86UI;'DZ(")":71S=')E86T@5F5R82!386YS(BP@;6]N;W-P86-E +M('T*"2TM/@H)/"]35%E,13X*/"](14%$/@H\0D]$62!,04Y'/2)E;BU54R(@ +M1$E2/2),5%(B/@H\2#$@0TQ!4U,](G=E2X@"CPO4#X*/%`^06YY('-I9VYI9FEC86YT(&-H +M86YG92!T;R!L:6)A2!N97<@=&5S=',@;W(@8VAA;F=E +M&ES=&EN9R!T97-T0H):&]L9&EN9R!T:&4@ +M)G%U;W0[6]U +M)VQL(&YE960@=&\@2!T:&4*/%14($-,05-3/2)W97-T97)N(CXM +M2!S:&]U;&0@ +M8F4@=7-A8FQE(&9O2!F&5C=71A8FQE(&)E +M:6YG(&5X97)C:7-E9"X@"@D\+U`^"@D\3$D^/%`^0F%S:6,@=F5R2(^/"]!/D)A2!T:&%T(&EL;&5G86P@&-E2!W:71H('9A'1R +M86-T7W)E9F5R96YC95]F:6QE*&YA;64I.PHF;F)S<#L@)FYB'1?:&5A9&5R*&$L("9A;7`[864I*3L* +M)FYB5]P871H +M;F%M92AA92DI.SPO4%)%/CQ0/@I4:&4@/%14($-,05-3/2)W97-T97)N(CYA +M2!D969A=6QT+`IT:&5Y(')E<&]R="!T:&4@9F%I;'5R +M92!A;F0@6-L92!O9@IA('1E0IA;F0@87,@82!L +M86)E;"!T:&%T(&-A;B!B92!U2X@"@D\+U`^"@D\3$D^/%`@4U193$4](FUA2!D:7)E8W1O2!A2!O<&5N(&9I;&4@9&5S8W)I<'1O2!W:6QL(&)E +M(')E;6]V960@9F]R('EO=2X@"@D\+U`^"@D\3$D^/%`^5&AE(&-U2X@"@D\+U`^"@D\3$D^/%`@4U193$4](FUA +MPHC:68@7U]03$%41D]230HF;F)S<#L@ +M)FYB"@I(&9U;F-T:6]N +M2!I;F-O;7!L971E(&QI +M'1&:6QE0V]N=&5N=',\+U14/B`*"3PO4#X*/"]53#X*/$@Q($-, +M05-3/2)W97-T97)N(CX\02!.04U%/2)2969E6]U(&YE960@82!R969E'1R86-T7W)E9F5R96YC95]F:6QE*"9Q=6]T +M.W1E"UE;F-O9&5D(&%R'1R86-T7W)E +M9F5R96YC95]F:6QE*"D\+U14/B!W87,@861D960@86YD(&ES"FYO="!R96-O +M;6UE;F1E9"!F;W(@;F5W(&-O9&4N(`H\+U`^"CQ(,2!#3$%34STB=V5S=&5R +M;B(^/$$@3D%-13TB1&]S7V%N9%]$;VYT6]U6]U2!R=6X* +M"6%L;"!O9B!T:&4@=&5S=',N(`H)/"]0/@H)/$Q)/CQ0(%-464Q%/2)M87)G +M:6XM8F]T=&]M.B`P:6XB/D1/3B=4(')E;'D@;VX@/%14($-,05-3/2)W97-T +997)N(CY(059%7SPO5%0^"@EM86-R;W,@9@`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_splitted_rar_seek_support_ac.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_splitted_rar_seek_support_ac.uu new file mode 100644 index 0000000..ee9f78c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_splitted_rar_seek_support_ac.uu @@ -0,0 +1,141 @@ +begin 644 - +M2!A9&1I;F<@:G5S="!A(&-O=7!L92!O9B!A&ES=&EN9R!T97-T(&EN&%M<&QE'1R86-T7W)E9F5R96YC +M95]F:6QE*"D\+U14/@IT;R!D96-O9&4@82!U=65N8V]D960@:6YP=70@9FEL +M92P@=&AE;B!O<&5N('1H870@9FEL92!W:71H(&QI8F%R8VAI=F4*86YD('9E +M2!T:&4@0IF965D(&%R8VAI=F4@96YT2!A9V%I;B!T;R!R96%D('1H +M92!D871A(&)A8VL@86YD('9E2!T:&%T"FET(&ES('1H92!S86UE+B`* +M/"]0/@H\2#(@0TQ!4U,](G=E2!T:&%T('1H92!A2X*5&AE2!T6EN9R!F:6QE2!T +M:6UE2!T;PIA=F]I9"!UGH@=&5S=&5R/"](,CX*/%`^5&AE(&9U>GH@=&5S=&5R(&ES(&]N92!O +M9B!T:&4@9F5W('1E2!A8F]R +M=',@=&AE(&5N=&ER92!PGH@9F%I;'5R92!C +M875S97,@82!CFEP(&]R(&)Z:7`R"F-O;7!R97-S:6]N('=O +M;B=T(&AE;'`[(&%L=&AO=6=H('-M86QL97(L('1H92!O=71P=70@:7,@F5R;R!B>71E0IE9F9E8W1I=F4L(&-O;7!R97-S:6YG(&$@F5N(&5N=')I97,@9&]W;B!T;PIJ=7-T(&$@9F5W +M(&MI;&]B>71E2!T:&%T(&QI8F%R8VAI=F4@8V]R +M0IC87-EF5R;R!B;&]C:W,@8V%N('1A:V4*<75I=&4@82!W:&EL92P@F%T +M:6]N.@I,:6)A29Q=6]T.R!Z97)O+6-O +M<'DN(%=H96X@>6]U(&=I=F4@:70@82!L87)G90IB;&]C:R!T;R!W2!B;V1Y+"!I="!W:6QL('!A2!L87)G92!F:6QE('-I>F5S("AT87(@9FEL97,*2D@86YD(&EN=&5G97(@;W9E2D@:6X@82!T97-T('1H870@ 0) { + for (i = 0; i < dlen; i++) + *p++ = 'a'; + *p++ = '/'; + } + for (i = 0; i < flen; i++) + *p++ = 'b'; + *p = '\0'; + + strcpy(dirname, filename); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_pax_restricted(a)); + assertA(0 == archive_write_add_filter_none(a)); + assertA(0 == archive_write_set_bytes_per_block(a,0)); + assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used)); + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, filename); + archive_entry_set_mode(ae, S_IFREG | 0755); + failure("Pathname %d/%d", dlen, flen); + assertA(0 == archive_write_header(a, ae)); + archive_entry_free(ae); + + /* + * Write a dir to it (without trailing '/'). + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, dirname); + archive_entry_set_mode(ae, S_IFDIR | 0755); + failure("Dirname %d/%d", dlen, flen); + assertA(0 == archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Tar adds a '/' to directory names. */ + strcat(dirname, "/"); + + /* + * Write a dir to it (with trailing '/'). + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, dirname); + archive_entry_set_mode(ae, S_IFDIR | 0755); + failure("Dirname %d/%d", dlen, flen); + assertA(0 == archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Now, read the data back. + */ + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_open_memory(a, buff, used)); + + /* Read the file and check the filename. */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString(filename, archive_entry_pathname(ae)); + assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae)); + + /* + * Read the two dirs and check the names. + * + * Both dirs should read back with the same name, since + * tar should add a trailing '/' to any dir that doesn't + * already have one. We only report the first such failure + * here. + */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString(dirname, archive_entry_pathname(ae)); + assert((S_IFDIR | 0755) == archive_entry_mode(ae)); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString(dirname, archive_entry_pathname(ae)); + assert((S_IFDIR | 0755) == archive_entry_mode(ae)); + + /* Verify the end of the archive. */ + assert(1 == archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_tar_filenames) +{ + int dlen, flen; + + /* Repeat the following for a variety of dir/file lengths. */ + for (dlen = 45; dlen < 55; dlen++) { + for (flen = 45; flen < 55; flen++) { + test_filename(NULL, dlen, flen); + test_filename("/", dlen, flen); + } + } + + for (dlen = 0; dlen < 140; dlen += 10) { + for (flen = 98; flen < 102; flen++) { + test_filename(NULL, dlen, flen); + test_filename("/", dlen, flen); + } + } + + for (dlen = 140; dlen < 160; dlen++) { + for (flen = 95; flen < 105; flen++) { + test_filename(NULL, dlen, flen); + test_filename("/", dlen, flen); + } + } +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_tar_large.c b/dependencies/libarchive-3.4.2/libarchive/test/test_tar_large.c new file mode 100644 index 0000000..626f9f0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_tar_large.c @@ -0,0 +1,289 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_tar_large.c 201247 2009-12-30 05:59:21Z kientzle $"); + +#include +#include +#include + +/* + * This is a somewhat tricky test that verifies the ability to + * write and read very large entries to tar archives. It + * writes entries from 2GB up to 1TB to an archive in memory. + * The memory storage here carefully avoids actually storing + * any part of the file bodies, so it runs very quickly and requires + * very little memory. If you're willing to wait a few minutes, + * you should be able to exercise petabyte entries with this code. + */ + +/* + * Each file is built up by duplicating the following block. + */ +static size_t filedatasize; +static void *filedata; + +/* + * We store the archive as blocks of data generated by libarchive, + * each possibly followed by bytes of file data. + */ +struct memblock { + struct memblock *next; + size_t size; + void *buff; + int64_t filebytes; +}; + +/* + * The total memory store is just a list of memblocks plus + * some accounting overhead. + */ +struct memdata { + int64_t filebytes; + void *buff; + struct memblock *first; + struct memblock *last; +}; + +/* The following size definitions simplify things below. */ +#define KB ((int64_t)1024) +#define MB ((int64_t)1024 * KB) +#define GB ((int64_t)1024 * MB) +#define TB ((int64_t)1024 * GB) + +static int64_t memory_read_skip(struct archive *, void *, int64_t request); +static ssize_t memory_read(struct archive *, void *, const void **buff); +static ssize_t memory_write(struct archive *, void *, const void *, size_t); + + +static ssize_t +memory_write(struct archive *a, void *_private, const void *buff, size_t size) +{ + struct memdata *private = _private; + struct memblock *block; + + (void)a; + + /* + * Since libarchive tries to behave in a zero-copy manner, if + * you give a pointer to filedata to the library, a pointer + * into that data will (usually) pop out here. This way, we + * can tell the difference between filedata and library header + * and metadata. + */ + if ((const char *)filedata <= (const char *)buff + && (const char *)buff < (const char *)filedata + filedatasize) { + /* We don't need to store a block of file data. */ + private->last->filebytes += (int64_t)size; + } else { + /* Yes, we're assuming the very first write is metadata. */ + /* It's header or metadata, copy and save it. */ + block = (struct memblock *)malloc(sizeof(*block)); + memset(block, 0, sizeof(*block)); + block->size = size; + block->buff = malloc(size); + memcpy(block->buff, buff, size); + if (private->last == NULL) { + private->first = private->last = block; + } else { + private->last->next = block; + private->last = block; + } + block->next = NULL; + } + return ((long)size); +} + +static ssize_t +memory_read(struct archive *a, void *_private, const void **buff) +{ + struct memdata *private = _private; + struct memblock *block; + ssize_t size; + + (void)a; + + free(private->buff); + private->buff = NULL; + if (private->first == NULL) { + private->last = NULL; + return (ARCHIVE_EOF); + } + if (private->filebytes > 0) { + /* + * We're returning file bytes, simulate it by + * passing blocks from the template data. + */ + if (private->filebytes > (int64_t)filedatasize) + size = (ssize_t)filedatasize; + else + size = (ssize_t)private->filebytes; + private->filebytes -= size; + *buff = filedata; + } else { + /* + * We need to get some real data to return. + */ + block = private->first; + private->first = block->next; + size = (ssize_t)block->size; + if (block->buff != NULL) { + private->buff = block->buff; + *buff = block->buff; + } else { + private->buff = NULL; + *buff = filedata; + } + private->filebytes = block->filebytes; + free(block); + } + return (size); +} + + +static int64_t +memory_read_skip(struct archive *a, void *_private, int64_t skip) +{ + struct memdata *private = _private; + + (void)a; + + if (private->first == NULL) { + private->last = NULL; + return (0); + } + if (private->filebytes > 0) { + if (private->filebytes < skip) + skip = (off_t)private->filebytes; + private->filebytes -= skip; + } else { + skip = 0; + } + return (skip); +} + +DEFINE_TEST(test_tar_large) +{ + /* The sizes of the entries we're going to generate. */ + static int64_t tests[] = { + /* Test for 32-bit signed overflow. */ + 2 * GB - 1, 2 * GB, 2 * GB + 1, + /* Test for 32-bit unsigned overflow. */ + 4 * GB - 1, 4 * GB, 4 * GB + 1, + /* 8GB is the "official" max for ustar. */ + 8 * GB - 1, 8 * GB, 8 * GB + 1, + /* Bend ustar a tad and you can get 64GB (12 octal digits). */ + 64 * GB - 1, 64 * GB, + /* And larger entries that require non-ustar extensions. */ + 256 * GB, 1 * TB, 0 }; + int i; + char namebuff[64]; + struct memdata memdata; + struct archive_entry *ae; + struct archive *a; + int64_t filesize; + size_t writesize; + + filedatasize = (size_t)(1 * MB); + filedata = malloc(filedatasize); + memset(filedata, 0xAA, filedatasize); + memset(&memdata, 0, sizeof(memdata)); + + /* + * Open an archive for writing. + */ + a = archive_write_new(); + archive_write_set_format_pax_restricted(a); + archive_write_set_bytes_per_block(a, 0); /* No buffering. */ + archive_write_open(a, &memdata, NULL, memory_write, NULL); + + /* + * Write a series of large files to it. + */ + for (i = 0; tests[i] != 0; i++) { + assert((ae = archive_entry_new()) != NULL); + sprintf(namebuff, "file_%d", i); + archive_entry_copy_pathname(ae, namebuff); + archive_entry_set_mode(ae, S_IFREG | 0755); + filesize = tests[i]; + + archive_entry_set_size(ae, filesize); + + assertA(0 == archive_write_header(a, ae)); + archive_entry_free(ae); + + /* + * Write the actual data to the archive. + */ + while (filesize > 0) { + writesize = filedatasize; + if ((int64_t)writesize > filesize) + writesize = (size_t)filesize; + assertA((int)writesize + == archive_write_data(a, filedata, writesize)); + filesize -= writesize; + } + } + + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "lastfile"); + archive_entry_set_mode(ae, S_IFREG | 0755); + assertA(0 == archive_write_header(a, ae)); + archive_entry_free(ae); + + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Open the same archive for reading. + */ + a = archive_read_new(); + archive_read_support_format_tar(a); + archive_read_open2(a, &memdata, NULL, + memory_read, memory_read_skip, NULL); + + /* + * Read entries back. + */ + for (i = 0; tests[i] > 0; i++) { + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + sprintf(namebuff, "file_%d", i); + assertEqualString(namebuff, archive_entry_pathname(ae)); + assert(tests[i] == archive_entry_size(ae)); + } + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualString("lastfile", archive_entry_pathname(ae)); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + free(memdata.buff); + free(filedata); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_ustar_filename_encoding.c b/dependencies/libarchive-3.4.2/libarchive/test/test_ustar_filename_encoding.c new file mode 100644 index 0000000..5e4fba7 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_ustar_filename_encoding.c @@ -0,0 +1,393 @@ +/*- + * Copyright (c) 2011 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +#include + +DEFINE_TEST(test_ustar_filename_encoding_UTF8_CP866) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } + + /* + * Verify that UTF-8 filenames are correctly translated into CP866 + * and stored with hdrcharset=CP866 option. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_ustar(a)); + if (archive_write_set_options(a, "hdrcharset=CP866") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from UTF-8 to CP866."); + archive_write_free(a); + return; + } + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set a UTF-8 filename. */ + archive_entry_set_pathname(entry, "\xD0\xBF\xD1\x80\xD0\xB8"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Above three characters in UTF-8 should translate to the following + * three characters in CP866. */ + assertEqualMem(buff, "\xAF\xE0\xA8", 3); +} + +DEFINE_TEST(test_ustar_filename_encoding_KOI8R_UTF8) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "ru_RU.KOI8-R")) { + skipping("KOI8-R locale not available on this system."); + return; + } + + /* + * Verify that KOI8-R filenames are correctly translated into UTF-8 + * and stored with hdrcharset=UTF-8 option. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_ustar(a)); + if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from KOI8-R to UTF-8."); + archive_write_free(a); + return; + } + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set a KOI8-R filename. */ + archive_entry_set_pathname(entry, "\xD0\xD2\xC9"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Above three characters in KOI8-R should translate to the following + * three characters (two bytes each) in UTF-8. */ + assertEqualMem(buff, "\xD0\xBF\xD1\x80\xD0\xB8", 6); +} + +DEFINE_TEST(test_ustar_filename_encoding_KOI8R_CP866) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "ru_RU.KOI8-R")) { + skipping("KOI8-R locale not available on this system."); + return; + } + + /* + * Verify that KOI8-R filenames are correctly translated into CP866 + * and stored with hdrcharset=CP866 option. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_ustar(a)); + if (archive_write_set_options(a, "hdrcharset=CP866") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from KOI8-R to CP866."); + archive_write_free(a); + return; + } + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set a KOI8-R filename. */ + archive_entry_set_pathname(entry, "\xD0\xD2\xC9"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Above three characters in KOI8-R should translate to the following + * three characters in CP866. */ + assertEqualMem(buff, "\xAF\xE0\xA8", 3); +} + +DEFINE_TEST(test_ustar_filename_encoding_CP1251_UTF8) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "Russian_Russia") && + NULL == setlocale(LC_ALL, "ru_RU.CP1251")) { + skipping("KOI8-R locale not available on this system."); + return; + } + + /* + * Verify that CP1251 filenames are correctly translated into UTF-8 + * and stored with hdrcharset=UTF-8 option. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_ustar(a)); + if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from KOI8-R to UTF-8."); + archive_write_free(a); + return; + } + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set a KOI8-R filename. */ + archive_entry_set_pathname(entry, "\xEF\xF0\xE8"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Above three characters in CP1251 should translate to the following + * three characters (two bytes each) in UTF-8. */ + assertEqualMem(buff, "\xD0\xBF\xD1\x80\xD0\xB8", 6); +} + +/* + * Do not translate CP1251 into CP866 if non Windows platform. + */ +DEFINE_TEST(test_ustar_filename_encoding_ru_RU_CP1251) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "ru_RU.CP1251")) { + skipping("KOI8-R locale not available on this system."); + return; + } + + /* + * Verify that CP1251 filenames are not translated into any + * other character-set, in particular, CP866. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set a KOI8-R filename. */ + archive_entry_set_pathname(entry, "\xEF\xF0\xE8"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Above three characters in CP1251 should not translate to + * any other character-set. */ + assertEqualMem(buff, "\xEF\xF0\xE8", 3); +} + +/* + * Other archiver applications on Windows translate CP1251 filenames + * into CP866 filenames and store it in the ustar file. + * Test above behavior works well. + */ +DEFINE_TEST(test_ustar_filename_encoding_Russian_Russia) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "Russian_Russia")) { + skipping("Russian_Russia locale not available on this system."); + return; + } + + /* + * Verify that Russian_Russia(CP1251) filenames are correctly translated + * to CP866. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set a CP1251 filename. */ + archive_entry_set_pathname(entry, "\xEF\xF0\xE8"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Above three characters in CP1251 should translate to the following + * three characters in CP866. */ + assertEqualMem(buff, "\xAF\xE0\xA8", 3); +} + +DEFINE_TEST(test_ustar_filename_encoding_EUCJP_UTF8) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "ja_JP.eucJP")) { + skipping("eucJP locale not available on this system."); + return; + } + + /* + * Verify that EUC-JP filenames are correctly translated to UTF-8. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_ustar(a)); + if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from eucJP to UTF-8."); + archive_write_free(a); + return; + } + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set an EUC-JP filename. */ + archive_entry_set_pathname(entry, "\xC9\xBD.txt"); + /* Check the Unicode version. */ + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Check UTF-8 version. */ + assertEqualMem(buff, "\xE8\xA1\xA8.txt", 7); +} + +DEFINE_TEST(test_ustar_filename_encoding_EUCJP_CP932) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "ja_JP.eucJP")) { + skipping("eucJP locale not available on this system."); + return; + } + + /* + * Verify that EUC-JP filenames are correctly translated to CP932. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_ustar(a)); + if (archive_write_set_options(a, "hdrcharset=CP932") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from eucJP to CP932."); + archive_write_free(a); + return; + } + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set an EUC-JP filename. */ + archive_entry_set_pathname(entry, "\xC9\xBD.txt"); + /* Check the Unicode version. */ + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Check CP932 version. */ + assertEqualMem(buff, "\x95\x5C.txt", 6); +} + +DEFINE_TEST(test_ustar_filename_encoding_CP932_UTF8) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "Japanese_Japan") && + NULL == setlocale(LC_ALL, "ja_JP.SJIS")) { + skipping("CP932/SJIS locale not available on this system."); + return; + } + + /* + * Verify that CP932/SJIS filenames are correctly translated to UTF-8. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_ustar(a)); + if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from CP932/SJIS to UTF-8."); + archive_write_free(a); + return; + } + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set a CP932/SJIS filename. */ + archive_entry_set_pathname(entry, "\x95\x5C.txt"); + /* Check the Unicode version. */ + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Check UTF-8 version. */ + assertEqualMem(buff, "\xE8\xA1\xA8.txt", 7); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_ustar_filenames.c b/dependencies/libarchive-3.4.2/libarchive/test/test_ustar_filenames.c new file mode 100644 index 0000000..1a4b4e1 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_ustar_filenames.c @@ -0,0 +1,183 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_ustar_filenames.c 189308 2009-03-03 17:02:51Z kientzle $"); + +/* + * Exercise various lengths of filenames in ustar archives. + */ + +static void +test_filename(const char *prefix, int dlen, int flen) +{ + char buff[8192]; + char filename[400]; + char dirname[400]; + struct archive_entry *ae; + struct archive *a; + size_t used; + int separator = 0; + int i = 0; + + if (prefix != NULL) { + strcpy(filename, prefix); + i = (int)strlen(prefix); + } + if (dlen > 0) { + for (; i < dlen; i++) + filename[i] = 'a'; + filename[i++] = '/'; + separator = 1; + } + for (; i < dlen + flen + separator; i++) + filename[i] = 'b'; + filename[i] = '\0'; + + strcpy(dirname, filename); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_ustar(a)); + assertA(0 == archive_write_add_filter_none(a)); + assertA(0 == archive_write_set_bytes_per_block(a,0)); + assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used)); + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, filename); + archive_entry_set_mode(ae, S_IFREG | 0755); + failure("dlen=%d, flen=%d", dlen, flen); + if (flen > 100) { + assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae)); + } else { + assertEqualIntA(a, 0, archive_write_header(a, ae)); + } + archive_entry_free(ae); + + /* + * Write a dir to it (without trailing '/'). + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, dirname); + archive_entry_set_mode(ae, S_IFDIR | 0755); + failure("dlen=%d, flen=%d", dlen, flen); + if (flen >= 100) { + assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae)); + } else { + assertEqualIntA(a, 0, archive_write_header(a, ae)); + } + archive_entry_free(ae); + + /* Tar adds a '/' to directory names. */ + strcat(dirname, "/"); + + /* + * Write a dir to it (with trailing '/'). + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, dirname); + archive_entry_set_mode(ae, S_IFDIR | 0755); + failure("dlen=%d, flen=%d", dlen, flen); + if (flen >= 100) { + assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae)); + } else { + assertEqualIntA(a, 0, archive_write_header(a, ae)); + } + archive_entry_free(ae); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Now, read the data back. + */ + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_open_memory(a, buff, used)); + + if (flen <= 100) { + /* Read the file and check the filename. */ + assertA(0 == archive_read_next_header(a, &ae)); + failure("dlen=%d, flen=%d", dlen, flen); + assertEqualString(filename, archive_entry_pathname(ae)); + assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae)); + } + + /* + * Read the two dirs and check the names. + * + * Both dirs should read back with the same name, since + * tar should add a trailing '/' to any dir that doesn't + * already have one. + */ + if (flen <= 99) { + assertA(0 == archive_read_next_header(a, &ae)); + assert((S_IFDIR | 0755) == archive_entry_mode(ae)); + failure("dlen=%d, flen=%d", dlen, flen); + assertEqualString(dirname, archive_entry_pathname(ae)); + } + + if (flen <= 99) { + assertA(0 == archive_read_next_header(a, &ae)); + assert((S_IFDIR | 0755) == archive_entry_mode(ae)); + assertEqualString(dirname, archive_entry_pathname(ae)); + } + + /* Verify the end of the archive. */ + failure("This fails if entries were written that should not have been written. dlen=%d, flen=%d", dlen, flen); + assertEqualInt(1, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_ustar_filenames) +{ + int dlen, flen; + + /* Try a bunch of different file/dir lengths that add up + * to just a little less or a little more than 100 bytes. + * This exercises the code that splits paths between ustar + * filename and prefix fields. + */ + for (dlen = 5; dlen < 70; dlen += 5) { + for (flen = 100 - dlen - 5; flen < 100 - dlen + 5; flen++) { + test_filename(NULL, dlen, flen); + test_filename("/", dlen, flen); + } + } + + /* Probe the 100-char limit for paths with no '/'. */ + for (flen = 90; flen < 110; flen++) { + test_filename(NULL, 0, flen); + test_filename("/", dlen, flen); + } + + /* XXXX TODO Probe the 100-char limit with a dir prefix. */ + /* XXXX TODO Probe the 255-char total limit. */ +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_warn_missing_hardlink_target.c b/dependencies/libarchive-3.4.2/libarchive/test/test_warn_missing_hardlink_target.c new file mode 100644 index 0000000..d7fa5eb --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_warn_missing_hardlink_target.c @@ -0,0 +1,45 @@ +/*- + * Copyright (c) 2015 Graham Percival + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_warn_missing_hardlink_target) +{ + struct archive *a; + struct archive_entry *ae; + + assert(NULL != (a = archive_write_disk_new())); + assert(NULL != (ae = archive_entry_new())); + + archive_entry_set_pathname(ae, "hardlink-name"); + archive_entry_set_hardlink(ae, "hardlink-target"); + + assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae)); + assertEqualInt(ENOENT, archive_errno(a)); + assertEqualString("Hard-link target 'hardlink-target' does not exist.", + archive_error_string(a)); + + archive_entry_free(ae); + archive_free(a); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk.c new file mode 100644 index 0000000..e38dbc7 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk.c @@ -0,0 +1,349 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_disk.c 201247 2009-12-30 05:59:21Z kientzle $"); + +#define UMASK 022 +/* + * When comparing mode values, ignore high-order bits + * that are set on some OSes. This should cover the bits + * we're interested in (standard mode bits + file type bits) + * while ignoring extra markers such as Haiku/BeOS index + * flags. + */ +#define MODE_MASK 0777777 + +static void create(struct archive_entry *ae, const char *msg) +{ + struct archive *ad; + struct stat st; + + /* Write the entry to disk. */ + assert((ad = archive_write_disk_new()) != NULL); + failure("%s", msg); + assertEqualIntA(ad, 0, archive_write_header(ad, ae)); + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + assertEqualInt(0, archive_write_free(ad)); + + /* Test the entries on disk. */ + assert(0 == stat(archive_entry_pathname(ae), &st)); + failure("%s", msg); + +#if !defined(_WIN32) || defined(__CYGWIN__) + /* When verifying a dir, ignore the S_ISGID bit, as some systems set + * that automatically. */ + if (archive_entry_filetype(ae) == AE_IFDIR) + st.st_mode &= ~S_ISGID; + assertEqualInt(st.st_mode & MODE_MASK, + archive_entry_mode(ae) & ~UMASK & MODE_MASK); +#endif +} + +static void create_reg_file(struct archive_entry *ae, const char *msg) +{ + static const char data[]="abcdefghijklmnopqrstuvwxyz"; + struct archive *ad; + + /* Write the entry to disk. */ + assert((ad = archive_write_disk_new()) != NULL); + archive_write_disk_set_options(ad, ARCHIVE_EXTRACT_TIME); + failure("%s", msg); + /* + * A touchy API design issue: archive_write_data() does (as of + * 2.4.12) enforce the entry size as a limit on the data + * written to the file. This was not enforced prior to + * 2.4.12. The change was prompted by the refined + * hardlink-restore semantics introduced at that time. In + * short, libarchive needs to know whether a "hardlink entry" + * is going to overwrite the contents so that it can know + * whether or not to open the file for writing. This implies + * that there is a fundamental semantic difference between an + * entry with a zero size and one with a non-zero size in the + * case of hardlinks and treating the hardlink case + * differently from the regular file case is just asking for + * trouble. So, a zero size must always mean that no data + * will be accepted, which is consistent with the file size in + * the entry being a maximum size. + */ + archive_entry_set_size(ae, sizeof(data)); + archive_entry_set_mtime(ae, 123456789, 0); + assertEqualIntA(ad, 0, archive_write_header(ad, ae)); + assertEqualInt(sizeof(data), archive_write_data(ad, data, sizeof(data))); + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + assertEqualInt(0, archive_write_free(ad)); + + /* Test the entries on disk. */ + assertIsReg(archive_entry_pathname(ae), archive_entry_mode(ae) & 0777); + assertFileSize(archive_entry_pathname(ae), sizeof(data)); + /* test_write_disk_times has more detailed tests of this area. */ + assertFileMtime(archive_entry_pathname(ae), 123456789, 0); + failure("No atime given, so atime should get set to current time"); + assertFileAtimeRecent(archive_entry_pathname(ae)); +} + +static void create_reg_file2(struct archive_entry *ae, const char *msg) +{ + const int datasize = 100000; + char *data; + struct archive *ad; + int i; + + data = malloc(datasize); + for (i = 0; i < datasize; i++) + data[i] = (char)(i % 256); + + /* Write the entry to disk. */ + assert((ad = archive_write_disk_new()) != NULL); + failure("%s", msg); + /* + * See above for an explanation why this next call + * is necessary. + */ + archive_entry_set_size(ae, datasize); + assertEqualIntA(ad, 0, archive_write_header(ad, ae)); + for (i = 0; i < datasize - 999; i += 1000) { + assertEqualIntA(ad, ARCHIVE_OK, + archive_write_data_block(ad, data + i, 1000, i)); + } + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + assertEqualInt(0, archive_write_free(ad)); + + /* Test the entries on disk. */ + assertIsReg(archive_entry_pathname(ae), archive_entry_mode(ae) & 0777); + assertFileSize(archive_entry_pathname(ae), i); + assertFileContents(data, datasize, archive_entry_pathname(ae)); + free(data); +} + +static void create_reg_file3(struct archive_entry *ae, const char *msg) +{ + static const char data[]="abcdefghijklmnopqrstuvwxyz"; + struct archive *ad; + struct stat st; + + /* Write the entry to disk. */ + assert((ad = archive_write_disk_new()) != NULL); + failure("%s", msg); + /* Set the size smaller than the data and verify the truncation. */ + archive_entry_set_size(ae, 5); + assertEqualIntA(ad, 0, archive_write_header(ad, ae)); + assertEqualInt(5, archive_write_data(ad, data, sizeof(data))); + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + assertEqualInt(0, archive_write_free(ad)); + + /* Test the entry on disk. */ + assert(0 == stat(archive_entry_pathname(ae), &st)); + failure("st.st_mode=%o archive_entry_mode(ae)=%o", + st.st_mode, archive_entry_mode(ae)); +#if !defined(_WIN32) || defined(__CYGWIN__) + assertEqualInt(st.st_mode, (archive_entry_mode(ae) & ~UMASK)); +#endif + assertEqualInt(st.st_size, 5); +} + + +static void create_reg_file4(struct archive_entry *ae, const char *msg) +{ + static const char data[]="abcdefghijklmnopqrstuvwxyz"; + struct archive *ad; + struct stat st; + + /* Write the entry to disk. */ + assert((ad = archive_write_disk_new()) != NULL); + /* Leave the size unset. The data should not be truncated. */ + assertEqualIntA(ad, 0, archive_write_header(ad, ae)); + assertEqualInt(ARCHIVE_OK, + archive_write_data_block(ad, data, sizeof(data), 0)); + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + assertEqualInt(0, archive_write_free(ad)); + + /* Test the entry on disk. */ + assert(0 == stat(archive_entry_pathname(ae), &st)); + failure("st.st_mode=%o archive_entry_mode(ae)=%o", + st.st_mode, archive_entry_mode(ae)); +#if !defined(_WIN32) || defined(__CYGWIN__) + assertEqualInt(st.st_mode, (archive_entry_mode(ae) & ~UMASK)); +#endif + failure("%s", msg); + assertEqualInt(st.st_size, sizeof(data)); +} + +#if defined(_WIN32) && !defined(__CYGWIN__) +static void create_reg_file_win(struct archive_entry *ae, const char *msg) +{ + static const char data[]="abcdefghijklmnopqrstuvwxyz"; + struct archive *ad; + struct _stat st; + wchar_t *p, *fname; + size_t l; + + /* Write the entry to disk. */ + assert((ad = archive_write_disk_new()) != NULL); + archive_write_disk_set_options(ad, ARCHIVE_EXTRACT_TIME); + failure("%s", msg); + archive_entry_set_size(ae, sizeof(data)); + archive_entry_set_mtime(ae, 123456789, 0); + assertEqualIntA(ad, 0, archive_write_header(ad, ae)); + assertEqualInt(sizeof(data), archive_write_data(ad, data, sizeof(data))); + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + assertEqualInt(0, archive_write_free(ad)); + + /* Test the entries on disk. */ + l = wcslen(archive_entry_pathname_w(ae)); + fname = malloc((l + 1) * sizeof(wchar_t)); + assert(NULL != fname); + wcscpy(fname, archive_entry_pathname_w(ae)); + p = fname; + /* Skip leading drive letter from archives created + * on Windows. */ + if (((p[0] >= L'a' && p[0] <= L'z') || + (p[0] >= L'A' && p[0] <= L'Z')) && + p[1] == L':' && p[2] == L'\\') { + p += 3; + } + /* Replace unusable characters in Windows to '_' */ + for (; *p != L'\0'; p++) + if (*p == L':' || *p == L'*' || *p == L'?' || + *p == L'"' || *p == L'<' || *p == L'>' || *p == L'|') + *p = '_'; + assert(0 == _wstat(fname, &st)); + failure("st.st_mode=%o archive_entry_mode(ae)=%o", + st.st_mode, archive_entry_mode(ae)); + assertEqualInt(st.st_size, sizeof(data)); + free(fname); +} +#endif /* _WIN32 && !__CYGWIN__ */ + +DEFINE_TEST(test_write_disk) +{ + struct archive_entry *ae; +#if defined(_WIN32) && !defined(__CYGWIN__) + wchar_t *fullpath; + DWORD l; +#endif + + /* Force the umask to something predictable. */ + assertUmask(UMASK); + + /* A regular file. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file"); + archive_entry_set_mode(ae, S_IFREG | 0755); + create_reg_file(ae, "Test creating a regular file"); + archive_entry_free(ae); + + /* Another regular file. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file2"); + archive_entry_set_mode(ae, S_IFREG | 0755); + create_reg_file2(ae, "Test creating another regular file"); + archive_entry_free(ae); + + /* A regular file with a size restriction */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file3"); + archive_entry_set_mode(ae, S_IFREG | 0755); + create_reg_file3(ae, "Regular file with size restriction"); + archive_entry_free(ae); + + /* A regular file with an unspecified size */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file3"); + archive_entry_set_mode(ae, S_IFREG | 0755); + create_reg_file4(ae, "Regular file with unspecified size"); + archive_entry_free(ae); + + /* A regular file over an existing file */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file"); + archive_entry_set_mode(ae, S_IFREG | 0724); + create(ae, "Test creating a file over an existing file."); + archive_entry_free(ae); + + /* A directory. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "dir"); + archive_entry_set_mode(ae, S_IFDIR | 0555); + create(ae, "Test creating a regular dir."); + archive_entry_free(ae); + + /* A directory over an existing file. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file"); + archive_entry_set_mode(ae, S_IFDIR | 0742); + create(ae, "Test creating a dir over an existing file."); + archive_entry_free(ae); + + /* A file over an existing dir. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file"); + archive_entry_set_mode(ae, S_IFREG | 0744); + create(ae, "Test creating a file over an existing dir."); + archive_entry_free(ae); + +#if defined(_WIN32) && !defined(__CYGWIN__) + /* A file with unusable characters in its file name. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname_w(ae, L"f:i*l?e\"fl|e"); + archive_entry_set_mode(ae, S_IFREG | 0755); + create_reg_file_win(ae, "Test creating a regular file" + " with unusable characters in its file name"); + archive_entry_free(ae); + + /* A file with unusable characters in its directory name. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname_w(ae, L"d:i*r?e\"co|ry/file1"); + archive_entry_set_mode(ae, S_IFREG | 0755); + create_reg_file_win(ae, "Test creating a regular file" + " with unusable characters in its file name"); + archive_entry_free(ae); + + /* A full-path file with unusable characters in its file name. */ + assert((l = GetCurrentDirectoryW(0, NULL)) != 0); + assert((fullpath = malloc((l + 20) * sizeof(wchar_t))) != NULL); + assert((l = GetCurrentDirectoryW(l, fullpath)) != 0); + wcscat(fullpath, L"\\f:i*l?e\"fl|e"); + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname_w(ae, fullpath); + archive_entry_set_mode(ae, S_IFREG | 0755); + create_reg_file_win(ae, "Test creating a regular file" + " with unusable characters in its file name"); + archive_entry_free(ae); + free(fullpath); + + /* A full-path file with unusable characters in its directory name. */ + assert((l = GetCurrentDirectoryW(0, NULL)) != 0); + assert((fullpath = malloc((l + 30) * sizeof(wchar_t))) != NULL); + assert((l = GetCurrentDirectoryW(l, fullpath)) != 0); + wcscat(fullpath, L"\\d:i*r?e\"co|ry/file1"); + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname_w(ae, fullpath); + archive_entry_set_mode(ae, S_IFREG | 0755); + create_reg_file_win(ae, "Test creating a regular file" + " with unusable characters in its file name"); + archive_entry_free(ae); + free(fullpath); +#endif /* _WIN32 && !__CYGWIN__ */ +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_appledouble.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_appledouble.c new file mode 100644 index 0000000..706794a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_appledouble.c @@ -0,0 +1,239 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_SYS_ACL_H +#include +#endif +#ifdef HAVE_SYS_XATTR_H +#include +#endif + +#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_SYS_XATTR_H)\ + && defined(HAVE_ZLIB_H) + +// +// The test ACL used here is sometimes assigned to the 'Guest' user +// This changes the text and breaks the test. This function simply +// strips the 'Guest' information from the string to help ensure +// consistent results on different machines. +// +static char _acl_temp[256]; +static const char * +clean_acl(const char *acl) { + char *p, *q; + if (strlen(acl) >= sizeof(_acl_temp)) + return acl; + + strcpy(_acl_temp, acl); + p = strstr(_acl_temp, ":Guest:"); + if (p != NULL) { + fprintf(stderr, "Shortening: %s\n", p + 1); + memmove(p + 1, p + 6, strlen(p + 6) + 1); + q = strstr(p + 2, ":"); + fprintf(stderr, "Shortening: %s\n", q); + memmove(p + 2, q, strlen(q) + 1); + return _acl_temp; + } + return _acl_temp; +} + +static int +has_xattr(const char *filename, const char *xattrname) +{ + char *nl, *nlp; + ssize_t r; + int exisiting; + + r = listxattr(filename, NULL, 0, XATTR_SHOWCOMPRESSION); + if (r < 0) + return (0); + if (r == 0) + return (0); + + assert((nl = malloc(r)) != NULL); + if (nl == NULL) + return (0); + + r = listxattr(filename, nl, r, XATTR_SHOWCOMPRESSION); + if (r < 0) { + free(nl); + return (0); + } + + exisiting = 0; + for (nlp = nl; nlp < nl + r; nlp += strlen(nlp) + 1) { + if (strcmp(nlp, xattrname) == 0) { + exisiting = 1; + break; + } + } + free(nl); + return (exisiting); +} + +#endif + +/* + * Exercise HFS+ Compression. + */ +DEFINE_TEST(test_write_disk_appledouble) +{ +#if !defined(__APPLE__) || !defined(UF_COMPRESSED) || !defined(HAVE_SYS_XATTR_H)\ + || !defined(HAVE_ZLIB_H) + skipping("MacOS-specific AppleDouble test"); +#else + const char *refname = "test_write_disk_appledouble.cpio.gz"; + struct archive *ad, *a; + struct archive_entry *ae; + struct stat st; + acl_t acl; + + extract_reference_file(refname); + + /* + * Extract an archive to disk with HFS+ Compression. + */ + assert((ad = archive_write_disk_new()) != NULL); + assertEqualIntA(ad, ARCHIVE_OK, + archive_write_disk_set_standard_lookup(ad)); + assertEqualIntA(ad, ARCHIVE_OK, + archive_write_disk_set_options(ad, + ARCHIVE_EXTRACT_TIME | + ARCHIVE_EXTRACT_SECURE_SYMLINKS | + ARCHIVE_EXTRACT_SECURE_NODOTDOT | + ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, + refname, 512 * 20)); + + assertMakeDir("hfscmp", 0755); + assertChdir("hfscmp"); + + /* Skip "." */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(".", archive_entry_pathname(ae)); + /* Extract file3. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("./file3", archive_entry_pathname(ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); + /* Extract ._file3 which will be merged into file3 as metadata. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("./._file3", archive_entry_pathname(ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + + /* Test file3. */ + assertEqualInt(0, stat("file3", &st)); + assertEqualInt(UF_COMPRESSED, st.st_flags & UF_COMPRESSED); + assertFileSize("file3", 8); + failure("'%s' should not have Resource Fork", "file3"); + assertEqualInt(0, has_xattr("file3", "com.apple.ResourceFork")); + failure("'%s' should have decompfs xattr", "file3"); + assertEqualInt(1, has_xattr("file3", "com.apple.decmpfs")); + assert(NULL != (acl = acl_get_file("file3", ACL_TYPE_EXTENDED))); + assertEqualString(clean_acl(acl_to_text(acl, NULL)), + "!#acl 1\n" + "user:FFFFEEEE-DDDD-CCCC-BBBB-AAAA000000C9:::deny:read\n" + "group:ABCDEFAB-CDEF-ABCD-EFAB-CDEF00000050:admin:80:allow:write\n" + ); + if (acl) acl_free(acl); + /* Test ._file3. */ + failure("'file3' should be merged and removed"); + assertFileNotExists("._file3"); + + assertChdir(".."); + + /* + * Extract an archive to disk without HFS+ Compression. + */ + assert((ad = archive_write_disk_new()) != NULL); + assertEqualIntA(ad, ARCHIVE_OK, + archive_write_disk_set_standard_lookup(ad)); + assertEqualIntA(ad, ARCHIVE_OK, + archive_write_disk_set_options(ad, + ARCHIVE_EXTRACT_TIME | + ARCHIVE_EXTRACT_SECURE_SYMLINKS | + ARCHIVE_EXTRACT_SECURE_NODOTDOT)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, + refname, 512 * 20)); + + assertMakeDir("nocmp", 0755); + assertChdir("nocmp"); + + /* Skip "." */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(".", archive_entry_pathname(ae)); + /* Extract file3. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("./file3", archive_entry_pathname(ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); + /* Extract ._file3 which will be merged into file3 as metadata. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("./._file3", archive_entry_pathname(ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + + /* Test file3. */ + assertEqualInt(0, stat("file3", &st)); + assertEqualInt(0, st.st_flags & UF_COMPRESSED); + assertFileSize("file3", 8); + failure("'%s' should not have Resource Fork", "file3"); + assertEqualInt(0, has_xattr("file3", "com.apple.ResourceFork")); + failure("'%s' should not have decmpfs", "file3"); + assertEqualInt(0, has_xattr("file3", "com.apple.decmpfs")); + assert(NULL != (acl = acl_get_file("file3", ACL_TYPE_EXTENDED))); + assertEqualString(clean_acl(acl_to_text(acl, NULL)), + "!#acl 1\n" + "user:FFFFEEEE-DDDD-CCCC-BBBB-AAAA000000C9:::deny:read\n" + "group:ABCDEFAB-CDEF-ABCD-EFAB-CDEF00000050:admin:80:allow:write\n" + ); + if (acl) acl_free(acl); + /* Test ._file3. */ + failure("'file3' should be merged and removed"); + assertFileNotExists("._file3"); + + assertChdir(".."); + + assertEqualFile("hfscmp/file3", "nocmp/file3"); +#endif +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_appledouble.cpio.gz.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_appledouble.cpio.gz.uu new file mode 100644 index 0000000..f2797d9 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_appledouble.cpio.gz.uu @@ -0,0 +1,12 @@ +begin 644 test_write_disk_appledouble.cpio.gz +M'XL("#N]E5```W1E^_VO?/X52A[:CCZ".9<'JV.U, +MN6AG9G6;C%-A,2X*7 +M)%6SN;;CS7_GO;VI,!TR)L^=.SH^/T%'"-W'B?[PJ#_IW[0U=`K!(3XA0(\N +MT$&X411VV:;C`^)]<&3T4S]+B@6)RS)7)$YR4JO7&C:,2Q`ZTYJ5JN04"``\ +M`;`/8`_`+M!]DW\M;QJUJB6G3*9J^28K%:?:O"J:4KJ>/PFFKH?;!;<*;V77 +M;E$9IXML*:\@R?-B+==55BMM]T%-NA^VO]H_'H7N[5T0&H9QV&_\YP_X`B-U +&WD<`!``` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_failures.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_failures.c new file mode 100644 index 0000000..c563ce1 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_failures.c @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_disk_failures.c 201247 2009-12-30 05:59:21Z kientzle $"); + +DEFINE_TEST(test_write_disk_failures) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + skipping("archive_write_disk interface"); +#else + struct archive_entry *ae; + struct archive *a; + int fd; + + /* Force the umask to something predictable. */ + assertUmask(022); + + /* A directory that we can't write to. */ + assertMakeDir("dir", 0555); + + /* Can we? */ + fd = open("dir/testfile", O_WRONLY | O_CREAT | O_BINARY, 0777); + if (fd >= 0) { + /* Apparently, we can, so the test below won't work. */ + close(fd); + skipping("Can't test writing to non-writable directory"); + return; + } + + /* Try to extract a regular file into the directory above. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "dir/file"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 8); + assert((a = archive_write_disk_new()) != NULL); + archive_write_disk_set_options(a, ARCHIVE_EXTRACT_TIME); + archive_entry_set_mtime(ae, 123456789, 0); + assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae)); + assertEqualIntA(a, 0, archive_write_finish_entry(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + archive_entry_free(ae); +#endif +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_hardlink.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_hardlink.c new file mode 100644 index 0000000..f80821c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_hardlink.c @@ -0,0 +1,215 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_disk_hardlink.c 201247 2009-12-30 05:59:21Z kientzle $"); + +#if defined(_WIN32) && !defined(__CYGWIN__) +/* Execution bits, Group members bits and others bits do not work. */ +#define UMASK 0177 +#define E_MASK (~0177) +#else +#define UMASK 022 +#define E_MASK (~0) +#endif + +/* + * Exercise hardlink recreation. + * + * File permissions are chosen so that the authoritative entry + * has the correct permission and the non-authoritative versions + * are just writeable files. + */ +DEFINE_TEST(test_write_disk_hardlink) +{ +#if defined(__HAIKU__) + skipping("archive_write_disk_hardlink; hardlinks are not supported on bfs"); +#else + static const char data[]="abcdefghijklmnopqrstuvwxyz"; + struct archive *ad; + struct archive_entry *ae; + int r; + + /* Force the umask to something predictable. */ + assertUmask(UMASK); + + /* Write entries to disk. */ + assert((ad = archive_write_disk_new()) != NULL); + + /* + * First, use a tar-like approach; a regular file, then + * a separate "hardlink" entry. + */ + + /* Regular file. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "link1a"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, sizeof(data)); + assertEqualIntA(ad, 0, archive_write_header(ad, ae)); + assertEqualInt(sizeof(data), + archive_write_data(ad, data, sizeof(data))); + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + archive_entry_free(ae); + + /* Link. Size of zero means this doesn't carry data. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "link1b"); + archive_entry_set_mode(ae, S_IFREG | 0642); + archive_entry_set_size(ae, 0); + archive_entry_copy_hardlink(ae, "link1a"); + assertEqualIntA(ad, 0, r = archive_write_header(ad, ae)); + if (r >= ARCHIVE_WARN) { + assertEqualInt(ARCHIVE_WARN, + archive_write_data(ad, data, sizeof(data))); + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + } + archive_entry_free(ae); + + /* + * Repeat tar approach test, but use unset to mark the + * hardlink as having no data. + */ + + /* Regular file. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "link2a"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, sizeof(data)); + assertEqualIntA(ad, 0, archive_write_header(ad, ae)); + assertEqualInt(sizeof(data), + archive_write_data(ad, data, sizeof(data))); + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + archive_entry_free(ae); + + /* Link. Unset size means this doesn't carry data. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "link2b"); + archive_entry_set_mode(ae, S_IFREG | 0642); + archive_entry_unset_size(ae); + archive_entry_copy_hardlink(ae, "link2a"); + assertEqualIntA(ad, 0, r = archive_write_header(ad, ae)); + if (r >= ARCHIVE_WARN) { + assertEqualInt(ARCHIVE_WARN, + archive_write_data(ad, data, sizeof(data))); + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + } + archive_entry_free(ae); + + /* + * Second, try an old-cpio-like approach; a regular file, then + * another identical one (which has been marked hardlink). + */ + + /* Regular file. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "link3a"); + archive_entry_set_mode(ae, S_IFREG | 0600); + archive_entry_set_size(ae, sizeof(data)); + assertEqualIntA(ad, 0, archive_write_header(ad, ae)); + assertEqualInt(sizeof(data), archive_write_data(ad, data, sizeof(data))); + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + archive_entry_free(ae); + + /* Link. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "link3b"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, sizeof(data)); + archive_entry_copy_hardlink(ae, "link3a"); + assertEqualIntA(ad, 0, r = archive_write_header(ad, ae)); + if (r > ARCHIVE_WARN) { + assertEqualInt(sizeof(data), + archive_write_data(ad, data, sizeof(data))); + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + } + archive_entry_free(ae); + + /* + * Finally, try a new-cpio-like approach, where the initial + * regular file is empty and the hardlink has the data. + */ + + /* Regular file. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "link4a"); + archive_entry_set_mode(ae, S_IFREG | 0600); + archive_entry_set_size(ae, 0); + assertEqualIntA(ad, 0, archive_write_header(ad, ae)); + assertEqualInt(ARCHIVE_WARN, archive_write_data(ad, data, 1)); + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + archive_entry_free(ae); + + /* Link. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "link4b"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, sizeof(data)); + archive_entry_copy_hardlink(ae, "link4a"); + assertEqualIntA(ad, 0, r = archive_write_header(ad, ae)); + if (r > ARCHIVE_FAILED) { + assertEqualInt(sizeof(data), + archive_write_data(ad, data, sizeof(data))); + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + } + archive_entry_free(ae); + assertEqualInt(0, archive_write_free(ad)); + + /* Test the entries on disk. */ + + /* Test #1 */ + /* If the hardlink was successfully created and the archive + * doesn't carry data for it, we consider it to be + * non-authoritative for meta data as well. This is consistent + * with GNU tar and BSD pax. */ + assertIsReg("link1a", 0755 & ~UMASK); + assertFileSize("link1a", sizeof(data)); + assertFileNLinks("link1a", 2); + assertIsHardlink("link1a", "link1b"); + + /* Test #2: Should produce identical results to test #1 */ + /* Note that marking a hardlink with size = 0 is treated the + * same as having an unset size. This is partly for backwards + * compatibility (we used to not have unset tracking, so + * relied on size == 0) and partly to match the model used by + * common file formats that store a size of zero for + * hardlinks. */ + assertIsReg("link2a", 0755 & ~UMASK); + assertFileSize("link2a", sizeof(data)); + assertFileNLinks("link2a", 2); + assertIsHardlink("link2a", "link2b"); + + /* Test #3 */ + assertIsReg("link3a", 0755 & ~UMASK); + assertFileSize("link3a", sizeof(data)); + assertFileNLinks("link3a", 2); + assertIsHardlink("link3a", "link3b"); + + /* Test #4 */ + assertIsReg("link4a", 0755 & ~UMASK); + assertFileNLinks("link4a", 2); + assertFileSize("link4a", sizeof(data)); + assertIsHardlink("link4a", "link4b"); +#endif +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_hfs_compression.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_hfs_compression.c new file mode 100644 index 0000000..2960fe2 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_hfs_compression.c @@ -0,0 +1,278 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_SYS_XATTR_H +#include +#endif + +#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_SYS_XATTR_H)\ + && defined(HAVE_ZLIB_H) +static int +has_xattr(const char *filename, const char *xattrname) +{ + char *nl, *nlp; + ssize_t r; + int exisiting; + + r = listxattr(filename, NULL, 0, XATTR_SHOWCOMPRESSION); + if (r < 0) + return (0); + if (r == 0) + return (0); + + assert((nl = malloc(r)) != NULL); + if (nl == NULL) + return (0); + + r = listxattr(filename, nl, r, XATTR_SHOWCOMPRESSION); + if (r < 0) { + free(nl); + return (0); + } + + exisiting = 0; + for (nlp = nl; nlp < nl + r; nlp += strlen(nlp) + 1) { + if (strcmp(nlp, xattrname) == 0) { + exisiting = 1; + break; + } + } + free(nl); + return (exisiting); +} +static int +get_rsrc_footer(const char *filename, char *buff, size_t s) +{ + ssize_t r; + + r = getxattr(filename, "com.apple.ResourceFork", NULL, 0, 0, + XATTR_SHOWCOMPRESSION); + if (r < (ssize_t)s) + return (-1); + r = getxattr(filename, "com.apple.ResourceFork", buff, s, + r - s, XATTR_SHOWCOMPRESSION); + if (r < (ssize_t)s) + return (-1); + return (0); +} + +#endif + +/* + * Exercise HFS+ Compression. + */ +DEFINE_TEST(test_write_disk_hfs_compression) +{ +#if !defined(__APPLE__) || !defined(UF_COMPRESSED) || !defined(HAVE_SYS_XATTR_H)\ + || !defined(HAVE_ZLIB_H) + skipping("MacOS-specific HFS+ Compression test"); +#else + const char *refname = "test_write_disk_hfs_compression.tgz"; + struct archive *ad, *a; + struct archive_entry *ae; + struct stat st; + char rsrc[50]; + static const char rsrc_footer[50] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1c, 0x00, 0x32, 0x00, 0x00, 'c', 'm', + 'p', 'f', 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 + }; + + extract_reference_file(refname); + + /* + * Extract an archive to disk with HFS+ Compression. + */ + assert((ad = archive_write_disk_new()) != NULL); + assertEqualIntA(ad, ARCHIVE_OK, + archive_write_disk_set_standard_lookup(ad)); + assertEqualIntA(ad, ARCHIVE_OK, + archive_write_disk_set_options(ad, + ARCHIVE_EXTRACT_TIME | + ARCHIVE_EXTRACT_SECURE_SYMLINKS | + ARCHIVE_EXTRACT_SECURE_NODOTDOT | + ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, + refname, 512 * 20)); + + assertMakeDir("hfscmp", 0755); + assertChdir("hfscmp"); + + /* Extract file1. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); + /* Extract README. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); + /* Extract NEWS. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); + /* Extract Makefile. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + + /* Test file1. */ + assertEqualInt(0, stat("file1", &st)); + assertEqualInt(UF_COMPRESSED, st.st_flags & UF_COMPRESSED); + assertFileSize("file1", 8); + failure("'%s' should not have Resource Fork", "file1"); + assertEqualInt(0, has_xattr("file1", "com.apple.ResourceFork")); + failure("'%s' should have decompfs xattr", "file1"); + assertEqualInt(1, has_xattr("file1", "com.apple.decmpfs")); + + /* Test README. */ + assertEqualInt(0, stat("README", &st)); + assertEqualInt(UF_COMPRESSED, st.st_flags & UF_COMPRESSED); + assertFileSize("README", 6586); + failure("'%s' should not have Resource Fork", "README"); + assertEqualInt(0, has_xattr("README", "com.apple.ResourceFork")); + failure("'%s' should have decompfs xattr", "README"); + assertEqualInt(1, has_xattr("README", "com.apple.decmpfs")); + + /* Test NEWS. */ + assertEqualInt(0, stat("NEWS", &st)); + assertEqualInt(UF_COMPRESSED, st.st_flags & UF_COMPRESSED); + assertFileSize("NEWS", 28438); + failure("'%s' should have Resource Fork", "NEWS"); + assertEqualInt(1, has_xattr("NEWS", "com.apple.ResourceFork")); + failure("'%s' should have decompfs xattr", "NEWS"); + assertEqualInt(1, has_xattr("NEWS", "com.apple.decmpfs")); + assertEqualInt(0, get_rsrc_footer("NEWS", rsrc, sizeof(rsrc))); + failure("Resource Fork should have consistent 50 bytes data"); + assertEqualMem(rsrc_footer, rsrc, sizeof(rsrc)); + + /* Test Makefile. */ + assertEqualInt(0, stat("Makefile", &st)); + assertEqualInt(UF_COMPRESSED, st.st_flags & UF_COMPRESSED); + assertFileSize("Makefile", 1264000); + failure("'%s' should have Resource Fork", "Makefile"); + assertEqualInt(1, has_xattr("Makefile", "com.apple.ResourceFork")); + failure("'%s' should have decompfs xattr", "Makefile"); + assertEqualInt(1, has_xattr("Makefile", "com.apple.decmpfs")); + assertEqualInt(0, get_rsrc_footer("Makefile", rsrc, sizeof(rsrc))); + failure("Resource Fork should have consistent 50 bytes data"); + assertEqualMem(rsrc_footer, rsrc, sizeof(rsrc)); + + assertChdir(".."); + + /* + * Extract an archive to disk without HFS+ Compression. + */ + assert((ad = archive_write_disk_new()) != NULL); + assertEqualIntA(ad, ARCHIVE_OK, + archive_write_disk_set_standard_lookup(ad)); + assertEqualIntA(ad, ARCHIVE_OK, + archive_write_disk_set_options(ad, + ARCHIVE_EXTRACT_TIME | + ARCHIVE_EXTRACT_SECURE_SYMLINKS | + ARCHIVE_EXTRACT_SECURE_NODOTDOT)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, + refname, 512 * 20)); + + assertMakeDir("nocmp", 0755); + assertChdir("nocmp"); + + /* Extract file1. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); + /* Extract README. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); + /* Extract NEWS. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); + /* Extract Makefile. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + + /* Test file1. */ + assertEqualInt(0, stat("file1", &st)); + assertEqualInt(0, st.st_flags & UF_COMPRESSED); + assertFileSize("file1", 8); + failure("'%s' should not have Resource Fork", "file1"); + assertEqualInt(0, has_xattr("file1", "com.apple.ResourceFork")); + failure("'%s' should not have decmpfs", "file1"); + assertEqualInt(0, has_xattr("file1", "com.apple.decmpfs")); + + /* Test README. */ + assertEqualInt(0, stat("README", &st)); + assertEqualInt(0, st.st_flags & UF_COMPRESSED); + assertFileSize("README", 6586); + failure("'%s' should not have Resource Fork", "README"); + assertEqualInt(0, has_xattr("README", "com.apple.ResourceFork")); + failure("'%s' should not have decmpfs", "README"); + assertEqualInt(0, has_xattr("README", "com.apple.decmpfs")); + + /* Test NEWS. */ + assertEqualInt(0, stat("NEWS", &st)); + assertEqualInt(0, st.st_flags & UF_COMPRESSED); + assertFileSize("NEWS", 28438); + failure("'%s' should not have Resource Fork", "NEWS"); + assertEqualInt(0, has_xattr("NEWS", "com.apple.ResourceFork")); + failure("'%s' should not have decmpfs", "NEWS"); + assertEqualInt(0, has_xattr("NEWS", "com.apple.decmpfs")); + + /* Test Makefile. */ + assertEqualInt(0, stat("Makefile", &st)); + assertEqualInt(0, st.st_flags & UF_COMPRESSED); + assertFileSize("Makefile", 1264000); + failure("'%s' should not have Resource Fork", "Makefile"); + assertEqualInt(0, has_xattr("Makefile", "com.apple.ResourceFork")); + failure("'%s' should not have decmpfs", "Makefile"); + assertEqualInt(0, has_xattr("Makefile", "com.apple.decmpfs")); + + assertChdir(".."); + + assertEqualFile("hfscmp/file1", "nocmp/file1"); + assertEqualFile("hfscmp/README", "nocmp/README"); + assertEqualFile("hfscmp/NEWS", "nocmp/NEWS"); + assertEqualFile("hfscmp/Makefile", "nocmp/Makefile"); +#endif +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_hfs_compression.tgz.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_hfs_compression.tgz.uu new file mode 100644 index 0000000..35e26ae --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_hfs_compression.tgz.uu @@ -0,0 +1,1800 @@ +begin 644 test_write_disk_hfs_compression.tgz +M'XL(`,'#B5```^R]ZWK;1K(HNO^*3X%1O$=2EDA=;2?RSEI#2[+-1+9+]4.?'>8']8J_SYZ)30!5U?>Z=77U +MV/6FG+:-\_>\=/GN^;^WM/3\X@/5_>'!(Z__P^9?U_SG^\/A;XR"T/'=@ +MA\.I^]ZQ!@M_Y#F=5NO_63A1[`9^]%^6U8LB>/JOEF597UO3.)X?[>PD.)V) +M&T\7@\XPF.U8;F3%4\>:!C.'2`?^)'#]":):>CDCY[WC!?.9X\?;ENL/O<4( +MP*Q1,%S@.QN+WK9L?R0Q_3N@'!!QCWCFA9<=,731I&(R@,4$P@0[`QLRU1NX09K2#!:EBHL5@ +MYE(QCC^U_:<=:)GC;UMQS;"B=8;D\VYHO/`]J^2_L9.N]:UNOW?@-]&%2 +MGP@JI'6L5A/M)Y*)6JW;*73["&H6NH,%]IP81M&Q#H_)./"\X`/V%A"%;8VALNVQ8\>+T!E9&PC`S:4_,&2>+7IPL'"]&*:.5B\N +M83AW@Z0(?$J5,7+'8R=$&JX?.^$8*,)X:,4X401?7=OS'HA.9.-$7?A#[#;; +M<^,'+LFYMV:(T64Q"I8-'8;GL13X,PLC[`%(/!?;#^)==[ +M!^<3]MJ\[>$BA3X-G6$75S_W+EX#[`?9H4-85*.`JP?M$H"]BYO;[MD9 +M`$(M8A@2+A0?P@4-H0`4S*U-N%0IU9%C=P(3$#[)WTPC&H;N''A1Y#BJ&%P` +M(P>:[$G>C4 +MEWF=;4,E83Z,>&2=UH:J^X:HK.AFK!)2Z]@SX)A#+QC:7F=VN)TTMF,/Y6QH +M,TV8,Z*>:=:Q#>L.UH;O.",N&U@LC;H31JGR7%^6T9G"0VL-NMN!66W'T#)9 +M]:3'N=*MUNN%.\(F6R(J`'K?S:8H;2V8,E!?3E%!3+!7\R +M@%R9`@491#D.0NA(VLH[L";(VI"[!^^=\+WK?)"(DD':R'(^3`.<75]+9MA' +MEMDYV%;/R#:=S(L^=/H=O649IV.+;UBQ]]A7/`>A9V!D2=Q%*#E`WD0T\[!* +MB$9D!)]VK.Y5+]*K!1T=/@!1,:$):YW7C0FS;L%$0$YH#3T[,F@04P4V&265 +M@V%"!@G=BTL;IMS4!2.?@#B\,)]#3;ISKWL@?!@OAC1/QB'H"` +MA5DEM0U1M*ZP3.UPU(Z#-C%_V;5$!@G,0*,(?:J.K(+U'CBX[:.V@@QA9OL+ +MZ)BY/7$(#TK!A2]J.9(,8@,Z8D-C#K#:;,M?S`:@Q<"D3,2>[+I6ZV?@HM$T +M6,`BAP$+:(80K6$P)Q$"DHB[%LI8E[-^NLX5!883!8MPB.`C1TVS*"4`\?TL +M"!W%)BWKBH6-Y\2PUEIW?O!!="M*&2<,4>J@8C@#C0H9-K%[[#ZH\_$BQ%9X +M#]OF.EO$`8[0D,0V%`6]$%$]L5%I<31&6))!7UNO+]Y2IW.W6)O)P.$7+Q", +MV`WPF4"YA +M%'Y\3F":SO2U=75YTWMGD26B/<_M>UXS+"4%90T@&,9.W`Y"%SH+V0(,*-?L +MQ^M#JWMSW.LE[\HQ7KH^]C#-T,V!.VE#>UQD>6@5Q+'GB!?B.H-Y`Y/O`?L7=VY"G;O#,(B"<6P==U_JL&=OND3\[)$<>213'J0L2>;MP!GC2G+>V]Z"U4%2U(1>3D4MD.L'..%H.M([5B2H"Z^O +MSH'YVW/@J_1I\A&:*WL/.I]>#N#E?N:M?-XY^^6GS$?OX\R&U0&(O"3N/QH@ +M1IM1<1O"LHR=9("!P>2V6#"KH^66PCJ4#[,!)O9HG>#XVS9(9'"6I16)2L3:/1IF+'!@()K/6VB0[.<4O<'UO6TX\W.JH56YR +MG+IK=MUW/@S7DY?1-,TI_IP5(Q=\^2(R5\!/4T=,`=U$W!9J2K0`TPXGR8!X +M*HPL5%)9(>DI8D[[SSJI+X+8B1*-(%G4V"!KZ;3*$47=PQR#R2#%!2QPJ&U#^4[%9Q4"]5X!W0P7VCW3B*2N6!T\ +M."3G!J0BH0"V!Q[Q>M0[Z3?IQ=P'0IL`>,>&12F+(T53D`#1[\RQIGZL>LBF +M_T#B(V\+_+3;YR?WSI5JO?`N34'/@'9SHPT+&GOJTJ>:;J>[0#:&RO,^V`^1 +MX-?0;8;6P61Z&ZB?Q6CEQ-S/:-G/W(^@&:$9,V3M80[3EXPI:$]O3`K.*/`W +M:*RQUN[0!1T'&OX^N'/0&T1-)553^$>LS6B!W149<\,FI30!UAL32):S!>II +M;'W`\JP)B%[T$9$B229LS]<(`*16.[UJP.%H(#5@Q$X5.'+T%Z*FVT21RT!BU$3:+D)E7:T&`KO5H2#`.R# +MQP&'K(VEHGF`*HY+8H@&P'_OAH'/JN\'FFTT/VF@-P-:^8P46)3OT.U40-&]VG)&]-K"'=[A^QL!;L2_F8%.99,&`06D)L]"* +MW1FM"52K9_:KVIG26,=3/&(+7U0$%SHV/6_"=SU1/0F-9%T`=+QQMBEV,<[ +MV$J`!6HTCV2/2Y]>)(>$A`Z-"ORKW-`N-Q]&!WDK>B':,V>&)M9@@3:5Q3H" +MF]3Y-Q/'FD4',XLM;S +M5==U,7$1!5N8M2"WL0@8U3G6\(.4NJAR@OG]`+/A_N[1\5;,U9Z+V9 +M!A&I0[&Q256Z#=@J(KX1I;;@0+\DURQ2IYTWZQAWX?0B:F_+E11J[!.*0K4R +M7X?!8HY\]L096ON'1&+/Z)2#SFYG'Q#)N35BN`,))S=EQNX],).9$T[00D>) +M\@J$/AA;*?B;AQGIB5*W@[J@386,"7O;,, +M@]5$?TF[(-Q`T#1_`MD)B@UWT-Y!05?NVJFNW%4=]G8^0H<#VN_.J"W5+E`6 +M29$%[01U:98EJ9WW@\Y]Z\:96[NJHUZY]R06VM$+81'KW@7>%`QX0P#=T#BE +M=B(UM091[,8+WA/K+B;6WC?_?NG28V64^!CV#.(BMAVY,\-"!WT6%EH^6K=\VMQNW]>^&,)(-PAAWN6(,0;"VCA'WH<.0R +MZ)/#K@#=!D7VV]M7[6_0DA_ACE=W'EK[JNG7SMA&!SQ5HX]*V^86;WG@QB[8 +M64.VUL$,`8J>T\9M6IB>9%F\T$U]%.F!-TJVJ2,T]H3SCHO=VU>K$.RRF#04 +MP1BXS,@!ZPS;Q@XF7)AB_N+*]!RUMR;H[:96H-A8"7`S%M@QT@6V[$=R@B;K +MH=,ZAP$Z4`3.T5'Y(0CO6)\"B]67KGVT[TC''*O=*GL`+=[<(AH)-\-!PX*A +M=[3AFJ$VRHWDJO$DM\Y?'M\DKC^2YLVVE"`QDHN9K%)"$)S-A=+4SFXCK_=3?6`-AN2Q4QB-NFY5\0ZL9NZ +MO7?;UNWUVV>'[%`+4)FV<#L8!R%B8<9S>O>(W.UB,=.'7?GA[$UW!YWN:J5[ +MUNZ!_"@"*50D1A(^@0LHO86J;9@!"#)AVV.>\JTD>([SS4VM!V2*0HXP2W$' +M;,MI_&B7!\&S0=B'PE@D?X*/&VP/:G^?#"Q9->9;WT@"UXY:IU"1H75YH[N< +M#7Y(F+NJVMFFHJ:FA)YJ+<[S!VM?E8B>6J%;X(<]U1:4"?]]JYCA"^425$1`XE$73+2BM0 +M6GKL+1;%[4E(E/]B31^QM&Q/W!'^3193N[V@IP4^,3?_1A^_:Y#2`P\7/Z]$ +MF,?)Z.\(;JNI.L!3B*6`6@)!)-;X)!T=R;V\"&])4"<1ZV#$^IG +M*,RA'5RP-H4()_Y[YOJ+>YY54F+CID-'9P=B]#B>@T!Q_\[#V:M)._*9(8V' +M)-*"EO*^-AT]D'^Z/$1G&G0**,_`@D`+F;D1NBLPK,-S:;7@M)LXOA.B0=N2 +MH5SHY.=M'R#A#N\>K.[U\9O>CZ?]5]W;[ID%ZQ5Y0SS%I6&]=R/A/1""@JKU +M5$TH&`\Q9^F#&GH6BR0QX"^QA\Z2$=567+W3!71D)X5WE8PA\"&0]#3%V<&! +M;L3(['"UZT+,E4(S4@2)&_OQL\-^K#/=8#SNQ]MH3_4IR#'`?V`ZXC_LQ8.? +M3&HWF0X<\$#^>AAJW8]%C%>MLQLAZ93?S5PE9`P]3X9V1BHW.J;$K-3FQE[G +MGL-%".DP0<+U-W8#I0W1=S5UN]+1I^V0*X;I/;`M("8_HZH>ZP$_F9#NTIUC +MW36VAPM'9X8CLCTY/DF.+SL06]_#J!_LI3N$]K+;/[92K3$TOV\ZNXD*CV22 +M=8QKB7299"5@E3:X#2X01AA'Z7904;*0H\)+&A3)>H$,W`B41)MCQ +MP^2#Z[<(..E$HUK/.]_N[B?&A;498WRH>*1J0-6W4A2$F;"#L/17_X/0`J%0 +MX$JO?\I!$-X[('R7DC06DH@89:\`A1<(3S5D$F&\F!.;B(0)37VQ^VU.\_:J +MFT?V!@]<#HD];>!`-^"E@W`X_FA^6(-@`L;X!SOTA?8)"L["O_](\+R`)#S. +M%QX76`3/63SOI0%PIW#G_J,VP85%2A/+TN@VN8R*[JR>[[`"39&&1ZPI%-1D7\:>[.<<^+9-.S@B[4 +MYKYF&60`GW6^_5:;C02ZJ[H/I\1-[_55[^I4^'1(`F%%J%GG-S\>=W)P(MPZ +M`3D)JASJUL7ST#;V\?HX5[BZN]\45GUN89%+H_M2]OFBM42@9$!U2.'J@1#AY +MW4?V/,8*^`YN+T/QG9SF39QX_N'K/KNHX&$2XD-2+$>)X71L1_;8B1]83TD6 +M`MI\ANH*W#3NLW39W]R2H1M0R04YF/:?_L_6&L67.6/0&5T1X<9R3-3_!<_[ +MEQA5!RLM1,M)E+LOR[TZ>25],!&;0[Z(N`/2/FV94*"\BK?3(V*)F*1T;O^& +MNR?"])5:H6`AK(*!=G0,9A0N\Y^`(R(!D$0[^430*43;"8RK]E!G081[&4#K +M''K$G;IA8%UT?^A^WSOO5M#[$90TF.4W\6+D*OVZB-):UY,+`OL!-R<[FOXE +M%^V),\#N?0F,^:NG>\^>/G^NJ4`(]+,]'(JX!HR2`4XH(HAEI/$+BQQCI"J@ +M_T1N0$&W`9L`:;,#!%6#2!FG!NGUIII)&!%9IK6OZX]@4D76&\CY% +M6+,68-J`25!>QAMW,FTCGR4Q'H/-24+U-ER@D4L&+RX%U''>+,+1-E)Z^=O_ +M^?]@[7V/_NT.:P:*7YWF*#1RV(2KF(/.2.V'`5DC5IH$-S'!A*MA>S*V((?Q +M]G%9]%'<@/J!89C2UJ>HI=9:CG)%L4S(&FA#7.S28GUDI#0;A2(PI+5&,0H< +MVY+8=5@4V!83T7BVW;&NI$Y*G8&0I-KWWJ%P$_:M.:-..DRAM19JN"CAD,$F +MJU><%\$84R-2E/;DU69H:TWHQC(L=H";UM`"F#.NLO+8'(U-G<"U-DIE@''R)WC +MRBZL2:;6*:&J:2,$]S07[BGHCD]M$U3H+7F@ARE0H4[F@1YHH.3,_[80=#\- +MFM^FIZ:>FP*]07V9?"*ATY;*+[)@:6J8_2-V&)Y+='T9R35S1%J`J4V$L!YH +ME?RV`+UF;0@L#^8SK0D1_@'K9^#&J$AX#VU47$0 +M20X[G(`%8\"-Q@U@;5T.8RF(H'L$JV+6:.AC+'H8?D^-<4^>3:#&V5.J*&W8 +M'^%""&/I[Q*\QA:>;B+#'AA1+!WP$IYL(>82:4BQ+J`RP?<^O@)EI[7&!TQP +M9(1)J6&3!P;#(;S$A=JA#:*D[M_;]MU=`/+.Q0'PCSAL5)[>R#M%1_AJ*ETY +M(^`NK]TQJ'`NM,$-XRE*.N64,\'/W3LOB*P?[=]\^XBL(GW+$FQ]>``)H>PC4#?IAI6;5A!1V]N0?U?H5X.`\UA;#-8.[2/44T` +M^P-W@\:M-1EP8E%[:+8*##&":K;VWH,E%\!`Q*!'"L&@=EOE9@[I3]LD4**` +M`PM%_#<9P&H.&J=X:++2+GLDM&J,*P?"%*R%O40K%2P'4`*)[4\=#]0;M%%! +M+.,N``T)C08%U[FH.J/*MK[P4$/)$I/RRCQ!@N[QN2LYCV% +M_0+6_50SCLL!!Z8G8C?-@\B"<\2Y3K(+'#]83$"?(P$*UH[#858XOT#0[N'6 +M,HX;[S/L9EA:;VS95MOC(%-RM["I??KNY/3';=YW4.>DA".2?1K?9FC9B3U, +M8>U**P8!-*`-2U)KJ1WLTV-*3PTEAL_%8J]RM!KK7(/%A"Y]F_XZ#*B77"1%CW8OR+$^?K-,(CC=76<5AZ%DD@S<1R2(MPET@\.M/X7!]I#-59'#2P*HATY\D3O +M0AZY-6N()I=^O@O8>QLUS4`$6.-VS$3P71FG"/K<&(,RMU5!275.;%"!T0EL +M3ST,>V&G*^V1!D!+G#7!DY$4^FE6YA@,+1^7Y-`%%G*$3I_>Q:M+C"*$GV]O +MKOQ=-U+6VO*9&5&Q&)#!P^BAQ)9"6'@]/(T$P.0N#@9-7+ +MEA&_^F"C[X+#/J/Y@D-PB*1RCZ$`!:JD;;')$>E$9/>\!+&$L\BZ[J#I=:?& +M>.3:$S\`Z2PZ9>^P;$ZV(R/LPMB+%AYKIG)01H76%;,MG?4)U,I%H5:#QL31 +M2]A:DU^$"$C.#,Z=4!W&(STO"-V)BYR!#DZC(\CUQ.X_J0VA.T,'E;:`R8A5 +MZA^;'E+[4T%0:]`:#":&D9>6"&5JB%SZ3-:L&>&<'9E(0[^"6_,X=.HL^>GKZA#;S+3X;3G].:+^8 +M^.N1##\#`8]G?SNP2AX6H41@QF +M;.`)LPS8,_NRA2@9AG8$*Q0)*1;>GN?Q/B2)8+@E,+?OCZQ34/Q#>09JY(84 +M06$Y9!M;&SL;+\@01IXX!"5W#)*,SZ^N6=8,:K\(7?W4$[N<07-WV=6+G@(0 +M#E/:;1V[CC>B!D&?IQM];H=W0A5A#46$5'#(M!-3/>SA<$'[0JH.Z(H#L(4; +M3;%`/'J1H&ZN@Q+"<1<^!9*@P;-Y\?;L;$OT@=R.H0Y4KG(9^$OBDTDFP25& +MO@X&*T-1.`041@*F +M28AZ%2P!A\*B)-O""K3]H(V:Z]CUY1&*`>84(&8B=I*R]829=0?Z&VU),.]D +MUQXR(V9_W.*#_?8`-_9Q@Q+)N%&`Q[QD7PTX=`/&B"-;.+4%'9D/1G1("ZT@ +MU6LOL,&D?R,;P/$,%F2LA13W/'"`W[AX/@7'B4P!>:Q,!/JHH>+X]79HM6]% +MO+K(5@"6$]0H#2>C>ZA-;8S5M]J+]+0332+WJCKEG%ZZ-^BWX8@=J00<)="F +M8W,8B'03N*Y)$F'V#WEN4-.KOG+'""R?>1BP^9I!IP56Y;`0(V:3X@:*M*== +M0WO2`24'H0`1!Z<`A0R)PM]=N3N0U+2'DPAX&86[@[&#%7+' +M#QQB)Y*Y4#8/GVP+R?)::[C0R"))^"''!$U<)TJ7PKYEX4)0SK:L.,W@H5S& +M:N7X11.7<'$';+# +MEG$B<=!2A).0UY.C"Y$6^S'(-2\FWUZ^_#KL[!VJ*?7"GP/GYB+Z9K>9!,?&W?XANUZXK":9OF$E9FFVNV;5%T,=:.:@)*!#()1\;2 +M86U4.!U6!GW2RK6[/AV%(G1Q/7&?\^C?O+UI8_F=5&U0I:?R,*G&%%D!A]F* +ML(YO=#AY3(99K'%0=QNU->L'V[5^`N::POT[3\U_H'I%B:GFJ$@+3Q+'MXQ` +MF1DZ8H\G\72BLVQ=K+=U0Q%!KX`Z03I,%IBHXXMDC;/#!^=6))BWZDRA$9"0 +MZ&A1)%BTM*.,2#M]:1H^DNVT:<5!((J!]D!?#QV-#Z"$)7L03"B.D]6/@G8DCNTVV+G=!L$+LZ&+98(MMC!9ZR8&#''`SP.CML3(D:`M-(@FCEXMI;/>B!Y@;=-*A8R1YPN +MHW2_GM[#6G%I#\>2`N9!C8TF4F&UZ.:6 +M*$GNQB03@C@S],SF3Z05,V&I9L&@^#*(BL(";.BC`-5C#A-$+8S86F>+-UC$ +M(GB>G<1:R(P)B,&[(Y&4#+5%CGM*.EAI+,IXYBV:;XM*2N_E*$!),2S.R!SK7['/#`M2GJS>>:4JIMPV4!GZ7VX-3(FN%JZ+?L##%``S7P +MR%JG,-ZA]3O'\]ZOLV=3[OLRK>?:'*89O$"7%L9V9.**1'N$MI^MYE,K;ZM0 +MD,:AUT/K*'<7LC?@T)'@T)17;&9'=WS,5997-.J'J?(4'&]9R7QI<@ZVVWA& +M9N`Y[7O4-7ANJ7?VT(/!3EQ]-_9LX;G6S2*`CG#\JKH<%-4EF3YG]AS^6@". +M[PKVR4H%[B927A*V-*$*^7!8A=]*2&3$TR%A)-TD[G)S9^!=I^@H8GD8<8+$![>Y[$ +MT9F+[+:B);"?6@*%@"G6F\"=L_!$-6<;]VHG4ZH33N!1,,2#X1C3S!I4)#A+ +M:TW%.4,%<0.RD.=KC-B$XW(EPT=U/9D[PG(!*G1PIY-"O:2L(`M?SP)B+T2( +M/XHD<51Y`':7[XL0^X +MQ6'2I3D""9>'=.M@%)>FY1WI\Y*5#>2BSCWZM"-RAC$>R>?]UR]%^-G>[4O1 +MS_O/<_OY0.<=)MPQLV*1"\!7<75),CPZM8Z=]:SQT)?,->6 +MV2_0O^V5,!^C.W<^UX+OS1Q-:,,Z]S8*.K0\500\3+?#UZBS"/^6YF>A8IZF +MBY'N0&T*;?[G-Z^WC-DCNAN,5>A@/D5(RG[/PM2?KNGG1P>!/.\AX^)E2CZJ +M@UI-/:'3R/@OQ!3Z!"S]>#CEM"@B^1[RN!=6#]3*8"YS#[R'3N%M5I$\-Q*) +M57!_26;2$]H<)C_DJ2P"4;)3^="QJYHQ< +M($Z=0<&OIY>O9(*..'Q`ZE0MBZN*P./L+RCF=X2X5\<7UZ`6R`91!UL2!Q1[`Z&+\*#UFK2;]6[*$+\M +MT,DMSNM"$W-;N`64CS"2"4AD\`%Z43$6SW>'\F`0MQ/8D=;:6)QUEDXU( +M]8F3K6`Y#OM%X["?&H4:]$C@S)B2QHPZ.+&D')*8F>\)!#PKE$5.8NNI@$ZYQ38EN24U`I4&/5FWJ*9B"GIL.0?`8I?TI2]K._41['?,SMK2 +M`W+2H[*O&VAT-C_'GMU/]!<,VK8V1002^B:V9$([=)^S]PGC9,5_A7B#4AD3N,=I"@\985"(713H1',:7')#E;ZL;&C@HP +M,U^Z'L8:X@!S0E'J@#"8SQUQN!$9NLBX54ZPL*G%0B+^8B^A; +MLX>W=6%*.RZ@C>P,^*01\7:_M88ZD.T',UOH@>1,,J)N96!+T4S:EF8W^[.?E#2'!@13%-X*4-5N&:XP49$\?`6 +M!J%R6(@(H0Y)(.6T_0.?*H""[[:$J8N1S[2E1YN-FD$CI!!VC),@SI6%16LS-'48:X+HB;F:D`1%CO5LT[??, +ML4[@7H%LF?+Y"HJFHIDG%#$Q;^G8B,U[RRC:*=@'33R,B>),EASQC=M/T,Z1 +MPQUE4X``)3[FPK&/_A?FDO]/<0#2T/IMVG-A_Y'<-\29#97O?"N.K9#:Q@7A +MSNFHT"T@"E#<\1R/,!_[").D!"'**!Q+9=VZD<.R#B2W.U]X9B9=F*TX)6%Y +MS%S4RA/?/)[8*S!`]@S?/`$JK4*ZA!*.(VCMYWM,]W1_N@E'!SP#"@<>DOG9 +MUL9)S0@^-RO/,()>0I$$F#&>S^_<.5*SI=MU*+D@[O3PTB`[@5U%H+2LO2(F +M@"$LHI]F>!IN0>[K^9\)I[CO@OACN0CQ: +M'8'%H]?V\/+&>B=*R&>P>X:N9\"=>C"^/N=+@K;3`0*8+^;\I$+)<23\<2R) +M(I&Y(DH=Z5%9+)()^J*U9I)T^20@;3XMF$VGYC\?J\(C)2.Q?:Z,T3A8T%P7 +M9RCOY$GD?/?9GJXUK9TEG[`"PD7)ZT:>`5&'%:%_Z>2&>V\>=LX6H2LY!)BO +MP>T-]LV1V#,T.,U_J%^"81HOM(LJO'N83P&8PT40*ZY-TD0.!0\$*DET7Y!9 +MHK%SN4Z23,KLOC@>SO0K5$O +M.Z-M<0C[SJ%XF\C@;+P=BVY]L.TQYRH(*SR!/T0_S$@.2SX+`?-U+]7=APD; +M#AVULD(YS$+?H6`(Y`-5Y%/<+E<')B>P3[&FE#.'_9@;.QLXO3!,#SHCR9-J +M7-[`1/,-.+`)4PPR`3PW#]7A>0:5L%@S$^CFH21`-_%CFM0XV]Q(WL(S@?&( +MU)T\T6*P+<,&Q;GV_#4"]4WQN020^EOC+3O&40H]XEV$I'2,(_0Y13W7M0Q= +M#-T8B0$TL\94?&E*YL58:8EU\LI]:I9K:K+"KXMY@OAPA6=/),7"EARF*"K) +M*WW_8-9B"I>!QV>01*31(A(W0.`WD?F>U$*A_)V&ORJ\)BVF('(]>`"Z(4-APAHN+@=HV5+EW*I-+J_`6W +M'O$B!Q>K-1$+T3.!P^I[HPC-+98;^,69K9JA)6V+?"^ +M$ED"K,F"=C(TSSJBBTS#>.<7764P>"^OV>&M-GDH0$:1-F$#/^-YX?(% +M=MQO9Q3G3I<3V;Z9*(HK"S.$/*^VF=%"S(O=?-T"YL6>.2\2P*XPRVEVLCZQ +M2354UQSQF7;M9@*J*]Y +M].1B1^?UPN=!`OF]);JWD*'NFMVKX*P>GO#`*8H;B4",1]'%MZ`>Q-`/DR`8 +MB<$WB/(90\ST0?)06%\P26T9!IJ_>;4[V-/$"@$^-R0N#M?KWHGR2=!:$/L1 +M8A&AFP+?RMM*87J+)&5J-XVY[Y3,W,`:8RZ)D'Y2#K)YZ+Z'A3Y)QZSF5/9I +MJK(*D(/5/=Q"53&$9`EJT6H<%'ES&4D.K^)\7&<26.NO/'OF.`].M(XQDR`U +M_L__RQ/;X72<,R05%& +M%*2#'OVY;?3:TUP#05'9$X=%/2&L_:1J6"VE"''-*&^?-YS.@M'FEBPJ7[V' +MHO(#A5';IC#;9!U@"G@^MRFU/QCQY+B#.&$GL_+8J,IC4"XPBG8P;LLR9W9X +M!ZQ51+W(VN4;FE"[_53MU')Z"9KB,/&.BIE+$NG(ZI^^N[WN'M_V;TZ/WUZ? +M]B\N3RYOX?^\LD$8IP%N?CX_ZUW\P"?\([40U*603B+5N)D#GBCH,Z-SHB,, +MLS=S/+RIXO3ZVT]S3^43&X&*6UOWO8X +M9\L-\A?>3%"\7H>*YZ-1R?V-,DF, +M9;U,W[!!MW2@2P4:TYET>&S7R5P'K*`#T"\XW"X:9%$U7+O99#%(2%XA*YR\ +MZ)7DF\#X.I.(#3STV8I5C$>4>-=,IDI@V4BNG4U,H0'\WF%/E.$,D02A":"= +M#=29.*@!LPFQD\3E;VVKJF%P4T@WH6+T(!V7H*,)=">(.]K!'3`O".Y`<25" +MFS+WK3&H-F6%H\1<[]Z]V]Q*4G/QX\`+['A+3,G=_+C=7?O`',EOTP,I^EJ. +MH.:!H\T\>:V=%"BT#XJY-RCE>23/V=E\6Q*8<,G)9K$?@O:OD&=TW[*X!BG2 +M#A4D)WG%(2-C6;(;E0APB7BYDD=C*D>(31N1`Y4,*CD+.JB]TY[H4&AB=`+I +M'A5L''\H$^=O(-),<^+RB(^,/20^/^64%T'D23=J#18[^07[9GJ;N#%L3,G+ +M8T@YO7/GFUM:^BIULZ`(N4N._Z4KDB1K9AC2(MA()&>>\$TEH>P\LE03+48* +MT80O27C6V18]?-TQ%)+K8(!YJ6^&[H*N?S)/G*NK5J4G2>R*LUQ^9DS2O6R$ +MA`)[N9C-589]C-KK'*A0K-[.I4JJS@$#AQ(-O7K:'3:OP*;1/1P%6*D\F2KP +M1:X,GN!H2J@[Q?DF;E)_,1LX.71)>61'!VYW(D\D4=56XTCGNGC/67A/TSVR +MWWFJ:4\FX.4BIIPWW9<]>=5V-K70[@M+774K+IT55Y\-G"F>^/S*'8^<\0:: +M!;`,U?D\N@6-G=[HLGF@H*.6=%VH`T!<;B=5,Y5>-6FJ:W+V'>'31"UX0\LH*47'"%&-MW(P5I^78;0)3=X)!3^Z81P?? +M10YQ@%=JGV9BB0,^(DF[?LQ'S82`@M/I7B5A%+/KU12$XKX`>5&12(2B)N,Z +M+NSU9"4+9[T9CYG8`72;`-TR(*I&=@$O4./>#"U"C>RT/=D]-(52SI/D*W9> +M>YZC=7.(!1U'S&3UYAONTHGEB+F(G(R[DCX:X71#/!TAQK\]%;+*V:NG'"(H +M!;NJ0C.H[QYG+<#WHC\4GUUSJ +MS=OS\^YU[_1&>)>^+5IC*2^"")!YE@[,RFFU2N:H1>5@U"Y=V-629I-#-KJM +M+H@BG["4+2,'O6TJHZ5P6CY3"9TWXOF&+(=$\0>Z>Q&8#Y[8M-GRQGD-@B(F +M#U$DCP22$*?4/2+%I52XGV%L*H@`O)\+F4$JR]2&$,IM)^=X54LP^;S,S9OJ +M=F?VZ[71Y=+92I=][03AQ/8I'9F>AA-TO"%N%Q_IEVCBN#ITL_?DHYP<8AL8 +MI7+$?L]44EGIM"/;X4`-I^3&/*9'FA3D[&64`)'WKX78VV:/%Q9\9=]K(R\R +M,&$V@0ZE;V.6]#2ULT.C)T9=NPM(BU71-E>022?;*R^,A%*=#9RIA@; +M1$;F)NTX4@B-?!D&H(>1MJ[DH#CP2PG:]B5M#-.BR[I%`@294%3,VA!':?"MI'.LAI,;Q--$;-)2HBKJ"^)K'*K'F?:U_4N@DD[L(S?%G%'^ +M+-/R>!W1;3,$??X'FJ)0S]Q9WOP'_/#G.V +M7DYL/$Q,F68MJWVVTY[R4K@7Y]'-]6MPDJ='N485&2C:03/6_0(6.C+;!ZQH +MT@1XJ]`2F4KE-W&"XOSE5KI`>!HN(NNUXTZ$-TVY67QYZ:OP4&F9ZY*^NX]\ +MU^N`635P8!5CX!?2W=G=WX&_!7A[YL9M+=,+[BR%`P>FN;_#=\Y*CBQN$J&] +M=1;:P$6IWR[);D#L8^C7-[#4SD%U?:?59`;/]T9-T`R\BX,Y)P=%2ZUE^F;I +M&E?Z+0+BA$L2GPA'!+QK!O53S+CC<#0`#`/&FVEAZ%+(D)*)*J^Z\Z3]P?;N +MC$,$DO%14MIGDKA,QJ$1)0QR,;V0T:.Z)2+RFW/U#H4DQ%#1MLK^[YA9Q3AY +M`>8&$E1M#XU$-K)!CLO(18ZC5;/0.%*KJD\13]_(PL4Z4[=[W@0>1M!L6V^N +MVF_?;>-M./_M/_UR_^/G^/-5UU]N#_ +M(AUQK/-P$)Q?QNHP+^LM[%=+EP![.6@OT7&;8L8"["$<8PLP'J% +M1BO%ZB`5T'*Q)10@I5=:7M8<";07*HM9'B6@P'E<,70`Q`X&NB7AJY1K9TXN +MAAV*Z8BDCNC&6`=B;'0(GOV0^JWON/',>RH_VXO3FQGIU>6UU`?^J>WW;.WY[UKVVKMY>@Q)V"HWC/_.[ +M"9XP`>%F?6<]V12_M[1L;@@BT_@+J.0Q#0A/$HA_Y@`X]\Y0`Q*/!J`]Z_>' +M(X`X/KGJWK[Y;OW)DW__V*^HKWVWA^??VS`(>J4->75^^ONZ>YP#K4#?'U[VK +MVSR@WL7-;??LK/_FM(N&,$+(5UB)K1;=^(9Z/WT3$ZJOWO91M]MJ75Q>GW?/ +M^@(50(]:5]>GYO/ES:WQ0N"\O4ACI=X@GOF*M'VH`Q[QC.&->_#-L[9(0=L6 +M\?_?=G9;>$]M#;"!Z\M^O*%6XB">OCL]?7?;W]LRG_>W6K1!IB.D3A(_V638 +M%.;!EO5K:\UX=;C5NCV]N6U$(TW@*WSDM#[]/2#T:^LK[6CSCK$U07D5^H/I +MV.T,U];6"D"36P/$K4%EP!)DNE8-,RR#41M#9:5RAF\T7C6PEM$'^Z(/UC"C +MA,C1EU2RZ$N*R($D0KD>*"%-BD;V`Y"(%H*'=%HG/9BUQY?GYY<7\'P-J^O\ +M5(R=$G_]D3./MA*N)!;AC9@H4#W,QD@C$X\NKGWL7KRVY$LEI!O!,$S4$A-V1T4V9UTE`8BX6?0[1 +M7"Q`A=[-080^Q!+3.(+-M:-I#HX78U:73I0I29S):8&=?WD,O.G\D/B!WA_V +MD"[P[,P.B=>+Q_[LD$83P(LZ/6D.\8\H'N$65Q]W!8!8)1;=[5D'T+/[=*-< +M+5AWT/9&M2$QM5!-6%!&QNY]36CTXM0"C87U6`\X6DS`.*P%*C:+Z@'_[V`0 +M!1B^G0N>:+?VL)5=[TK`I&8.\H'CRXM7O=<8E'%R>G5Z<7)Z<=P[E>P@F9-; +M1):!^\AHCL].NQ=]W*]"42*72VS'%&Q(3T,\<2(?O&`"-#4]''>&_,#$%"]; +MLSNQEC#\.:M"C%JB(DJ#D`Q(?C!K5\J!3)0?25$2B-3F]\@>^O;HMS[?;_6= +MQ;V.JNW\NW_2A7SKBA6N6[];N-VQ$?W>@?]--O[YPJ2"E<7PIB=/Z%SBK^0# +M2#CIUUO66!%],I?DUJ/?__O)$ZW@G=]_7__GBQ<"G[``7+QP(GO(Q1)LGP6$ +MI(LE,]4V'C3Z_;\[7P,U65'9T3/['G`.=^FE'PR@SH*:[`8LJ5Y7[/S]'YV_ +M0_U__?7KW_^Q\RO\^>L.]$R&M"!*^[/8.4^><#:/46`E/4*7PCI)"Z!K,CVC +M4T82:@%D&[+UHKI,RRB7VLUC8J5*MGY_L;YA[5B=KW_=V?E+A#_@OYT75K3] +MZR:^W=KY^W_O_./K)T^V?]W;WA#$8)W]],.6M?'R]'7OPOHW[RW]?;VS_@^H +M]_JZ]8=Z]^3)/K[3'M;A?T^>[,F)X(ZMS?_X#U\`RE9K8[JU)2`M($IIT@&= +MSFI*DB\LB6[MOC#+I;K\(0@`K\!Z0;]MXOQRQ6T06X(JO)-4X><_K#\V:%#T +M(9$=N?'DR5\N7I3_%>W\ZN]8,&NT`B^)[WK+65QK9MO +M!WA3$[X%_F=\F-G^7@X\O#XH1'B:@Z"X4#Z69BRNM\YNSWHOKVE_4-I_?>T= +MLF\_P"8:;ZGA.C-'';VE*?L@K?7/:G&8.$S'1+NY?'M]#!]1`!@&A-*I0<)T +MAMBJ_&]]#$^U8\QFG`_#BLK,GKA#H),',,-]::>P$/&]NJ!P>+#?F>8607=" +M%Y=`GRL+P`U.V\\O09Y6+<*D,]AE7]FJ0J%93L7,/E$%2[?$5Q1:SD5:-`HCGA2VAK]7M*"L@'!12AT_Y*&#S%R.10\".;3SH&/3'59`Y +M%P[6P*!D(G7@*KHF@02=HD^AYW8XZG/@9#E]&4!:"H0Q.Y5]P$"5#5=@Z$6K +M`6`M?H'NZ9J39GQ`NQY`?G=")[R2S3"D&%*C9`F(933#*,I@M>X".]C +MT`P!-^,;(?U.50$KS>"+!6T>^`"E>8F, +MR\,9VB7\-@\>$]LU0:!H_T88XO:.1CC>U&X$S[FDFF"$#0"+A?L6?`R +MJ9Z!+A7I&>@J>9Y!6"R:#FZ)?&987&#BT%A=P'(IGH$NX;H9V'IS44,H%:ZY +MT'W,?%H?I4JT9A#*Y60&?&Y7L4P-&`->ZT-3>%-]\/?/&X%/_$4C^#+IFP&N +M-\&*+!IV\O5E9D##`M:WE/,%E@91XD'2]]8K+5.U9US4)+G9G"NFJY!SMM*+ +MFZ3M7Z./D?SG]FRN')$>IPGHCX)X2W[DO7)QBHZB#JR:80=>4`29[9QBV!H0 +MV3[(`N?U@A=@-R1`Z&F]?/G]Z7$J2L-PLA+I*@]J,9#PHGI!B0.T$)L=E.6? +M-0]E!:#IHJP`%H[%*J@:Q4K78@48^Q8+@:1_,;\CV:]7B"QY1SYRXA@L),!N +MO7ST<%",1ZZWTJ^F[ZT"-,_Y5@.%65\-P#P%O!Q->M7*H:2:7@>JNDVFFEX# +M5JCIY9"ZC*F`S+K-&B&P2MT(1:G5C;!8M6Z&TAC#:UX(J=F-,$C5;H0AU>U& +M2.@_:X2P6#2#!PV])KRF?#?":#`;E<;>"%YZT1HAH1NM&0*J^HTPV)'6"$6J +M^XV0T)76"(%MA$8H8=-!06]:(X2X:0GW31%*9Z[PFE5\5[ZP0CCRA^6+9>D- +M*\1ECUCYY\0E5@>N0LY6>+HJ\"IE:-K751>P7(IFO5T5H)HCJS:DYLEJ@"/< +M!PTPR@5OL3.K/DJ%R,UW9]4'KQ"V^0ZM^N#E8K;0I54?0_FTZJ.4BN.3/3GJUFX.S:JH]3*>P*G%OUX=&[51^:W%OUP=F_51^>'5SU +MX86'JSY"J4#,]7'5@"XT0+*>+`!A)XYRU6RE8L\2UP8!YG[<:G7/^S_VO21R +M\ST\])]L_KC%<6GTF/X(.">GK[IOSV[Q[-/+RYO>[<\Z_"X@M-L1"I_+=\3&_$Q"OSKJO99RT^:K=1L?"=Y3"]\GF +M\?'9B:!V+`#@I8Z=JLF)@E(_V]"I?]-K/!:5?MD].>$XY#:=BU''C_3/^_P9&4ON]P.%;AYA +MTF$.$QHI(.,`EGXBB_$E4BKJD8_AJ#!$=2K'^$V[:LF!'2V$*^=X3\Z[H>GO +MW)?^3H(4%6L;&$\VL7]%VV75DR$Q$47M%8ZJK4Y:^VPNZ?VM5K8``DF]3N#^ +MS/6EZE"XLO3&X92B*T50B8]V])G33M[G=S=]3W5)0CC3RTRT>##HPE\#ELX0 +MU0&DFNS6!QU@?L_ZX$WJS/>SL$..581?EL0;?-Q?$A/TWV4QET7TEB[26QYQ +M9B^-&BR)>=^@MD+K(!6Q-M*$GCFG1WTL5EF:+`&!\;*_P)1[C?&.E\3[?DF\ +MLR7Q?ED2K\',$AB)]=P4L\'L$!BCQACCQAAL1#?%PLM5&B-YS3&6JEPSCJ&0 +M@N8ES1IC-%_LB^88BR5GJ#R\V12O";<4*`^-,9J4@7=3]GE3M382WH,43^FZ +M>-RCA_\OAQMBXDZ]X)8.7Z1;ZM]2&*EC388%TO%LJ=6CN9!2ZI/S^:#&:P^D +MQVN']S5%'M\F9@`]879E'`"PF3G^`=^*J[^4R +M5F2S)D@N&)'?K0N88WX4`V-D25U8VGX3+L.Z*$*[Q;>_+(.4,5/JH65LE)IH +M2V%EK).::$MBI;6,NGC!,FAI&5N,56B/%*-DU;EBV#++H!+KS5)8N59!)=;E +M4EBW2V&]70KKW5)8M6>=M%B:PN=;.)5XSCV=\FZ(-7%'?;JUC2HQ/FM +M(?Q=4WC'F>.ZP\T#2J7=##W'VJG&:<"%"BV=2I3:LE'"4Q]@&MVFB,%H,6M: +M.TIIODQI_VH(WW2E-IT`F&YHL<1:R#?X*M'JBY1\$ZP8?DYW$OJUVT^A)WU, +MQXCQH76QHGCDUI:EG!V%SH;YF#6[-A[?%8;QW'51$%`7U)>O/^2\N)+R@OC^Y>4%^[[+RDOOJ2\^)+RHA+C2\J+ +MVA'[7U)>5,;J?TEY40/C2\J+LMC]+RDOOJ2\^)+R(A?C2\J+`H0O*2^^I+SX +MDO+B2\J+(FG9*.6%OEV?_!31'[F?C.J18Y3VX-.ET9<<(S8-@G]E1*#Z0BY+ +M,80\4GO9994/[8^CPPI0`5+X/6]9IB"JJR0&R)Z[?7&#=PWHH>?889\N\JT# +M7>"2S8',]ZQF`8O<=EE(WS8*2="8^HBX\7M_2D=EBFP+&L@YIEF!6C8 +MPJQV6`!,+)^9$S/S1H@L*YHC+HM1N\^%(5D#'(G77>O*YJP'B'=OR&VM:AQ- +M!#<3D0.78,1FHF9U5C3-`(!OUW+D9-K2V4@2(B9`SI> +M#5;%X"7NF7S04EFE`^9M>A1"UEE$!@JZ9>QQJ7C-P`^*+,]"\/XO31$&C5I` +M&!_+-(E'K*[E[FM6 +M859H7<5(RY0VK#W=JJPR'7:B2]HF.+5GV40%RC>`KU31=`PW"FKW#<(29^[S +MA)&RSA!`?#(!LCA769;X(B[#FG3-5)889ALQ8! +M?*E7)`ON.Q\:%P'_GP7OF[3C(_PWCAH4E+?!70C9=$WE>_GS85%?K%_MO%WS +M(L@RIXP.66Z3IB"%M=*P0Y;@2_&@+D^*:W.OV*L-65NZQ74!:<.E:2_D[8OD +M0]:77BBRZE:CEDV"4S@.%_[0CJO7K`IKJ("K35`!%FV')_`LB,0QOF(P?9S* +M='V2A14=9(YZ&343LH[IF.SMU`*2IG)9)33H&LX2#;H@^B(7=NZ$LYJ5B)QA +MN26DPU:I&3HL'P*H!XP;#=7UK8RQ*$*H<#`:P(7A$@7P%4IM!I;;BIGLZV)5 +M6=TF<"/84BTS!5MJSANPU5:Y`5X855$`7RHX!&0M2]R`+14#!F2%(SH#6VE@ +M9#%R8R3*$,H-.0.^('"@`+HH_J(G43=)I!IB-A>/U=FZ6%7J +M9A:X;^,][8O8J=IQS4$=>G94+C^+D?JN/RJWTW)PQV//GC3KC+X/9K8#\L". +M2S?/&D1\]5(*0'S]4@%"N +M]:9!F[6W`=-%>=B4-LX\*:3+M=SJL-`T[$>^#5ZGWX]@@I>-G*[L:SJEF9?E +MF7ED,/G)AQKE0SJT23\.:5P?4T0@&_/4F,3RB-E`J-HT\B*DC&0EJB>?U^M) +MW.4T#I/6P-$/8#;&S4N$6`>/PX*:HO%>Y5)8VOG)Y?#-S7ET*6^_XK("_=C6:TP/(DA&:P%`$]#FHY +M`MGCGH]!AQT>CT%)>4,>@UA._IEE*3T6H9S\,D%#[29,)MSL>@$S]2?>X?BWTX?1'H9*3&7@9 +M4LLJG`6'W%^23>&=N72Q683U5=A +MU/8.YF)3&_).SZ]&A8[,+T=B!=0R%E&!N7RKQ1O]X/[R5/0#_2M0J=C?JT&A +M?*>OFD#5/E(U!3UAP*I4LEF'ER!""0:6)U*]9U5-(Y.0X/%(51J02Y.LL@IK +M$LY/;+`BT6S"@T7@)[@87E:18D?'H7B(TVH3**(QR.US)02B26:(QH))Y9&+S4K +M*[$G989%-7:9,5")[:V(G;XWHQEVB0^H$AL38RR-G$V8L32I="*-E0EI"3:6 +MIF4DWEB:BCKEOC2%$C]6)>YR,U-/[+$$=FD0705>92A9"7XJ04AS"D;BD"70 +M,:%(<[3"1"/-2=6+(2S&-Q*3+(N^3,]7[^K4P%U2=\]/?-*<3CHARK(4\%C< +M"KCY"516(5@W/J^"5E5,7`5Z)A'+\G2J-X3JT2C?QZE)8SD!7I7H936*5;LY +MC:AHB6%6H[>"*,TDDEF-Q%*Z9CKQS,H45F%Z^8EJ'H'.H*E7N)!,^G;0Y0D- +M'J6'9"*<1R*5OEAT>4I+VA_%"74>B=92BFMQ`IY'H(7G.1^!3"IASV-17-(* +MK4CP\T@$ARLOQV6]EL6)@AZ!ULJK,$DL]`ATEC99LXF(5J=A)"A:G9Q,7+0R +M)2VAT6/1HD1'CT4L7%4YR$N,M#+%,.?B["7I++6;4YQ@Z3%HJ<1+*Q/3$C*M +M1JLL=+DVA61+?5HR(1/JU$IBY^N2V&9S:ITXJB5*:032JU.\+%(#5:5 +M:?'*4C%.WV3?G,+*VF.\*H%4XJO5B)7%+-6CL+IV:"306I+42KXM,^'6LD1D +M(JXE\5>N0"9Q5W,Z1D*OYNAF:J[E\)<=R'1BL%4IK.)RU1*)K8*<)!A;B!$92N1$`G,5J.QK#F3D_!L)2*<"&U9$K7/6=0EM.1&>7Y"M17I +M+.ET*$O`MB*U9;WJV81M*]-8RJK/)GA;D<;RWOC\A'`KTEE*,?HS$MHMR*5JK,9S>Q22,B'?8Q*3B?H>A:9(X/G%R>G%<>\T.7.FO^SO;;5. +M3E]UWY[=]GL7QV=O3PBPW>NT1LX$PY$;;NT,%JXW +MVK$7<8"WXNX(>#HU![^Q>5%_9C\,'"`A7]#7V7MX`W^UQZWCR_.KWMDI%7)\ +MC"5`;6[$OT:M\)W^NWO>/[ZZ>G76?7U#_0[XZI&_J@?QJW5VJQ=WUGMY>WEY +M)J!_['OQEM5NQ_;DN^-C?B<@]#+,5^TVADE^A\V&QJ6:0/"-6J$W@;!S6T&5 +MA2K*X7P/#_TGFS]N\8%%>DQ_!!Q9DQ]/KU]>WO1N?];A=P'A;\YP&ECKE@6T +MX<^Z]>1O+[@P.];HP<+4"X/'],?2P@"""FL='Y^=R&%OG?4N?GCD04&'!5$_ +M.RF:$*J3ST[4)_6S'4`'R,X6597]=7:2ZG!XD06HZ'2`274[E*)W^^O3"XTH +M/!F%XG/FG(0CL5QW;F5KZ/H**4XD8P@50K=-2BU@@T +MK44IK+QFI2JK?V;LULSV]X#34M/@-S%=?(` +MOZ-X]!V-YBM@SEP4C2VPZ_/+BRWYJ'7>[>F[WL6K2_H-$O.Z*[ILY`(MT0%7 +MW>,?NJ]/M]JP;*"V/:#40OFEPXC?O$1"!_>OM>^_MBSKWW3LV_J+U1Y9ZPG" +M.GVTK-]_!X@Q&#SFQW;\,'>L$:*A']AJ[^_N6FWGWAE:PRGP)VOQ'Q^L?_]A +M;;S8$(3HSU__:B'P.#2HO;#^@/_S=.]>'[_I_2@Z24)T4`N=?&R]_J5WU3^] +M^!$E>'L`U:;^6/BN#PJOYW$28`]>D2P&**IX1]1V#'7%+$Z$A$>+_;H(W>.S +MR^/N&=;IWZ0J_&'M3(.9LS-<.#OS,,##EYHBE-8<9BYH4_X$ZAPN?,L>>L'0 +M]MI[G;T]8(2WW>O'H0M]U,KCCT!]MT6%(`!WKY0R?3%QX./>_A&,X1&`8M_; +M4:O[]O;R^/+BU2.U6KPFLKR^'H\PGS`ETN?='TX?C_#,OG/$0/V$`MRW/]RU +M7MZ<'%_U+F7?]6]NKWL7K^'K06>W`WUH(P0,:PD`J3>3X1!^@+9Z?GERRCHD +M279X?]!B$8X3'>ISN=\"S8E1K/9I2ZI1I,GN+*)PAZ;4CN!?N2^QW?]U_`Z^O3GHX_BJ=?+V_.IE#R=7Z_3XS67_6/W"=VV??]_2V]?7 +MI]A`JMK`]7M?+>MWH7-[?=LS/]O>`25GLHO_:E +M5/BW>/&'U9Y9SPX/%<#5]>7KZ^ZY`:,^WAQ?]ZYN"[[!F%_IZ)NB^'XT!>4+ +MAC%JD=:EJN>-6D(YP];"`I5K54ZCB[?G+VG5'.SN[L(TRH/)3C4`ZL'P_2B+ +MXG&'R8#_N7@.MA,%5OLG;[L=HMN-?IJ02`-,,%DOFA<>;ES`/X./,*.\CY;5 +M/C.1X"U/-_B8\XU*AG]G@.GY3AQ[3DLPI:Q%1NN4A#T@TS0[ZUU=4G6@R9A5 +MWJ?^O-4:6USF=;IUMUK[D'^@Y'T<'H+\P_7'`6HDO5>G(-]$`X]:YS_`0NKC +MQ$U1$/.D'4UIFHQ:%^?Z-/%!?KZ$=ZUY`4 +MOKJ\/M=89>NZ>P$C#;]"V\>!OSDU%F#DC.#5;5^(D!:-/@+0QVF+EC0\XQ'R +M>2NG&N_.S_8%JS17&Q+`Q=!FS;-E#R(UIQ&R9'X1+'LDZD#JJZ4N?$WJP_XP +M[DL]@I^4&.-'C=^CNBFET7>6E#)D$H"LQA/XHP"M[@Z](R^S1`,]AA8?J49_ +M@#H9@!X&^N(3^`#U7">@A9\"NP>@%O2S4'S_C:IH?QXZ8_?^#^S_%O4*UN7@ +MFV?MA7_G!Q_\MCC&^6UGE[_W;<^U40\4C\/Y0J"(%P$IB6FL]XX_"K!<0;>E +M#4&GAZ*.L+KJXG=8H&.9A[<#[G2?_3JT<(/;>5>"$ +M^4=+ZP.=?FL:1'%)3^#GI"/H2>L'>DYW`[W,],(TGGGI.HFID&ZRG"'(+'-; +M35PT$:'+LN>$N:(O,7>R(&>`__!=T7=\;M'2=G(KRY\8`F^\R#3W/2PAME^S +MR/"^-;N#GWWV39H"L$I8!-#C>A<3%Y*].Q^-T^.AID?"KEKR3%T,?#)"9S4E +M]4/.MWT/_VO-HS25J&CEX8<6S>=1;D>@#%'\I].*'B)L5AK*B8>M&$/)M'FI +MNB69X:T4]^NT#/;6409"__+J%G@W"@5HGN-.?"M:X&QHBT0ZTN+K=\\313LE +MJ%NMKUI?63]-[=B*`_YFP9!:8DC@*\R4/BD7U]UK=E`G$[/CV2T_0-A"D/Z8 +MH*0/PTJYKI1O(W$WI5Z1+R=Q@;Q\VSO3_4E93WX4=Z9H1QK/2$5_T;H%/>8& +MS?#>]27H(1>WZ9IE`+0J%GVCNF8_0@]WO0_V0Z1U,/DK!@&HJDR37@H28+A: +M>#C5`J&Q078^FO@;Y%LX?G-Z_(.0SV^O3_MJ9-N.;P\\IRW(Z<](L\5NFGYB +MDOU$9L1/O(^C?K0IG,V-'Z#2MU/'PN1'%F8>L]S(@HD^#-/%BJ;N?(Y*HZ8BA0X(RLB).D"L%R.%A9_0,/$Q5O2N`[;9CWH=*=4. +M_HM'HN'?A;\`#0=^P'(XP`]'A&\'-I1W/[7`MB`4`=."V3.YC?"&?#[W2WJ&*KK\0F/P*UCG6 +M;(V?@-N)7\Z]/9M[3L1/QN37O'69;^0#S0"(E:&_7\LX5O.P:,WDHB5>7-UY +MR(-P2O,A7*##"R:N1;VRF,,W6B1GI]T+Z:;,W>Y#'L#M3G$*T3<9?L'%GB5S +MF]TUT;85!8MPZ&Q;P-\["-1*.6!-)B4YYS3GI4@(,M5W"!/7=RX=2@*3OAM. +M^P9RQ7V/2?NF!3#ZG6/#O`)DXL&B0L3WZH+"X<%^?K-%9L+"$NAS90&@N+FP +M,DHZMJ@`T>UE7[5+RTJII!*+5,"2AE51<'6SM?O,RLNK47V95*8NI-J#$[H6P.NHFO*+R(KI2^3JY0" +MR?P\-8`J&VYFW:D&+;@JU`"LU3]ZDKM2:CFW@#6!S[_>O`RC\([S,J1)[C7D +MI1A-$?)O.B_%R+N6O`R!+A%H@E!TF7D9#F8S:`*_6#0"S[D`/1]<"V)O@E!_ +M`JH(]R;@\G:J)CB8AJ81?-X=[64(^;<0EV$4W8Q>AH-'K9O`Y]\[7H81-AP, +M/*/L$%D5-RB5EU`EK],W(M6$*Y78U;=[FY#U +M.D"[[ZB<7.Z]1O51Q!TG]1%*A7SQ?42U,_[]0K6ARP5[_GU!M:%+17KA +M_3^U$=1IM-H8)?(Y$B9T]:P@+-W +MRJ2Q-0A`Y;A/>PZ\?83!]ZVOK+8?M!?^R!F[OC.R9G9X%UDQ>H(U=_DK;N,6(T92YX?(;:7)]5YV3SAL.HD[H?:>V_[[IY +M,TC#U?9SRGQJ!\*=6NA)0BVC$@A]:NZ8J96ZRNQX&E5#T9'_*BCRE576C.X/ +M*8$BETO%=\[*4`6D3_WBNI->6$**M;\J@,H:95=CMDK$I)^N98DD/[F(PL_H +MB7)"'Y/R9LDG/]O,/B(NS(1BOIQ7"V1C3]&K;W5'(U+(;4]?RQQ+6['-H]4U +MO=^3UVNN/PH^`.8U&M]/.=#)']#&R*1Y3O.B+?Y<*>1-CR%\A.U:%N'KN+2MC>@ +MULG[G>0G<^O\3V)G!HK5FJN715]3W\PRB\Y2K,F-L6QEM_)F%.X6T5U?PZ*O +M62=?/AS^Q5M115]S[_<:U@.GV[A*2DZN[!I6U8`4F4J@I'K%<*+[]2NWRIHC +MP/6[M>J`R[VL&C61FU(U0-6>1PU8_0JL&C76[KJJ#4U"J0:TMD]2#9RYIFH) +MG,1,7Q95V>3U".3?+U43.7N/U!*(Y-ZJA\;W0M7MUNR%/36+R=[+TP!1831% +MB>KCB"N::L`G=S'5`1;.NQIK-'N]4G47%5VCU`BSX;!DKD6JT0TYAE0ACKCG +MJ)3!&U<:E76N?GE1#3BZIJ@.'%F-U7!>;;B970\NJ$4/+PZJ`9:](JAD+`ON +M`JJ/H5WZ4SSZ>9?[5!>AKAZHT6CT4U5#50VJCC'=[O6`O4;`51RRZF:6 +MBJY)^]/K%92]:J5>,3I?*X?7W>65K4^\Y35!:2.Z/JRQM&KAJ"M.FB`,W%+E +MH^#2DJ88@V:MD->0-,69?&R,(K2+ACBD:33"N6]6M1KV4N[-'TW*2%WQT:"D +MY"J/99"6*6U8?]))BZ\6L'G91KU*R4LUFA0AE=/:"$K)JX7"]V$T`#8NOJC7 +M;/V"B_HE:3=9U"Y&O[&B*5)8:E)674%1NS1QU43]HOA.B4;P\O*()I52ET34 +M1M(N@ZB'0Y%(->68<;U#S<:+'=EZP/+"AIK@80-YS0Z@>K!5)F_%O0KU.C[% +MJNKA#,HMM?25"+5AO0:P%=9BZD*#NJ"IJPOJ]>%]@X%JH@<:UPY4C4U-H\:\ +M2:"*J(I.JZ1KT*P)JB*;BA&,?/]EE,W<^E60U9V5SM9?'[:6,:IMK)91SDNU +M7XMJ+1]--GE^/6#>,J]9;Y$/OQ[E:@4E)\-]/6A.95]=Z6P075T,Z?.L!9U$ +MQ-5$F%38VF6)Y8O96$X"^;IE>,V`RU75;.[WNL`U#/[\;.YU$2H$339!>S7A +M6F9^-N=Z7<):%UP%W36#YTSGE1,^+Z-Y0Z0:2D)9 +MAO*:6)6*:V7*\28%J=3BRR#)%.+#!J@B4WBCXHR,X(TPTYF_Z]541C74`M92 +M>=<=M"H]OR`[=P/RM>5J)M]V$PP1/%H3HTII+LB579=\E9Y=D/ZZ`?ETGNNJ +MF9@*]"D'+DY<75Q,?H+J82L3[F2DVC/S0R>@F4^LZF+8D_IDY##3*V2U3[1$ +M;C>WW=O><6X*A735SD[R`E`UJ+Q$'5I1^+E/1_V_^^=P9":_?D$YJ^8?1O_, +M5/?L^I?>U7<7EYQ((U.KDF@^ZGZ9*Z!H9&1L%*Z/Q:(T0$H4FXTYB._CSB^$ +M782K[[WW]SIHI5-AM>#W:\.3X-_KD$92!YX\CWM)VZO`<1H#^*1>;0A\OS:X +M)ZA[#<#W&X#/[$;4`;PA]8,&X,%<]#O\K(^RWQSEH!'*S!ZVN5Z_U(;?;P"? +M#9Y(<"M0TS$4`H4.OT/J^8)M`'C:`/&T$_;03]K!'T\\[]/"J'QA`.Z#O +MU`'S/DXKP/*C(ZJF1XCYMG`3YSW8#X"H=N`I_+V#^_![G9"(Y(G!NC3V'X'& +MP2/0.'P$&D\?@<:SIC0PPY6@8`Q*[8%-$]A?E\FHS>#-LRP=RXW.5::D[7 +MIGC+]=!R6)C"JS$2'PAVAWS>O?Y@@"2J,J;3<7][B6I9%V6_.N,FA!#$UTSTVNB`)-<`HDC +M!#7,9HB4(<4)M?HVQ*<8R&61PV!X%[JCB=.<@A$?VA@[I^#FN!@ON7S)N$.^ +M"KH*I)0TZI*0(;+-6RYVFYLAZA&60C`+EU-=;#[ONJL\5Y! +M,UQT585--&CT?H&F:84W1FNMY'+-T# +M3A0M18#=?N3JV]W=E?[&%4CLKT[B8'42APU)^($3C!L//^6'IA'0]G.;%1R- +M[SO.?8-U24B+`0UYXPHO?)="Y)KBR70TS?`^=&A1-5"B%$YMC)SX^`9:\ZK: +M?BI`>`F+)1UBW-QD25%8HA7H?J_<'RN*7Q>-%OA+8*,2LBPV-W99;&EAKX0? +M+I:OOC30&^(#]B2>XNW=CC]JBBR#J^6`U\5;W-><(Q2"#^:;Y\88DX?LP[:K +MB\I#&RR'-EP.;;0<6@VU**\SFF#4<;WE=4$3C%$YA@$<.]9!WIXRPZ_[`SUAZGVD+IW`S\DE\_0$]0] +MIL!()Q:OL#7B)R@_D^UNREB>G5Z<7)Z<7QSG7FV5O +M,OM*8'ET%YP[I'L6,Z_:_$M!#X<9:.U53O"DA)+QD>6U2H5/"MSEPCX-VLF= +M9[*Z6[EAG:JVR?59J4Y1,.G82FTV[-&DU6:$D1(QY_U0OL_F/Z0)D\H)VU+C +MH>4O;65?Z552*#)WH8:BO>(W+6UM4"1ILA:(=Z7R#M*[_,2"ZEHJ+:.@\1[_ +M$CD",^_[NP(C\R$Y5Y?SD?91"[ZQ+JT.)^1!<*H2TIU_J0$C#MQ60&'`2`VH +M.D!>+5)>/:`D2U095%"#UGU1@4+)DH=T +MU`$ZJP-T60?HM@[0VSI`[^H`V>6?!Q6?]7.!A5#./66)+2.LP$185$X$_>!B,50A^Q#?BS[/[1BS*Q?5E&X? +MH8TCF7PT!RB*1R*;7^['D,)L9O/`=_RX8)H)LQ,3:A44DN1@S/VL5(&6(6DU +MW0=0EE9_]>S9R6D55FL9]WL:A>]QQ-(_W>4#&*;J75\/.^O;PY +MN>U>:\=F5'VU@S.,_V3S]-TI*&Y;`JGNL1O9;J,9>0H@C:>XJ[=(6B;.JW(0 +M5"QX$[@8AN-0*V`^5I?EU:!#QS>L*IB978-04`ESGU^?(M8ON[00HPQ$LA!Q +M@H2=304@!]4@A\4@)C/*K9%I`:BLX/)*Y6)#E4)3$L6<;GY-[$Y^Y`M'DM\T +M2=6C;K@:-N;!EBJ@N9%):"DK,_U.-S/I6\K.3+\K,#0)+&MI"MO2K&O&TB3D +M1S,UC1H7VIJBPH:Q:?1-`I7F-C1JXJ,P.).!-.S-[.NA>IVU-QDZU^`TKC#' +MD2FX7R,'U*QM0BTE(M+OY*7?^A+0[-'D9N7Z!JFY+M:,U[0`S=3WR7O\*TEF +M;[[7#=74EY2EFOIJ5"3[6=I7U-!?:D%)<[0"3-JC56"UH+QZQ+R:4(E-6@X7 +MU`&[+RHTSRQ-@4QX%=/)J2(8(5]V*[Z_3%EX^5!I*S+[J.+[N.*[:7+FPR2^AD(0K^I[C6(,8[(()*BB,JOX7C4K +M%U7?%W6&S;!<"J$T`RX?X*'B>S$^WC+15YD@\D#F=A3%TS!83*;]41"/@KB@ +M23I@Z&#+'&%R)<+DS[*Y2,'+&EVJ!856EU'[(OTG$;I"%\U*WO0'4^+*IR+[ +MK/`CV%K'5[W+:@L-*1@F&J+5M=%4-YG-R=6;:#Z(Y`>%\H/CRF6401D,6VI5 +M4.+,8!54'2"O%BFO'A!9;-5@00VH^X(2=4$*RV[J"< +M(X8MKPK8OA]$#S-1X?KP7.WZ\*+R]1%*FI!(RWERNJ10P%3"Q+5@(F"ZBSB_ +M_R70^R*HM-$+5L01+/27;WMGMTJ#M]@J`6L$N.!Y]X=3-*NZYWW\R9P0+^AJ +MV[-6JW/S]M6KWKO3FR/MIP6F;\<+K`[^?_!;RYZUV]"?H1--CUIK?SMJ/=F4 +MG!BK0\?%7/_(LG+>VS-+F,A0B;2`L`5G6UT^>P+NOM^2S93G#:6!M6,3Z1$6LO_X5V_[V]I+[H8V7 +MQSGNQ-]XD>")HD9;-?`0:PT^.O=N;.UJ1.C%W@OQQHGL(?TMR[?`N#J][)'T=YXX9CDA:O/*O0WEY$,'QB +MG/XK&92O#9!D:$3;GVS>O#D].]NR.B:M9"R*(&2W9DAF!25W:#X9Z\G?Q&## +MS"%_&)C>#P-G*ZG!(Q'D"M,L:+5*._+(2NDVTY61'Z;MS>&1VD+9T1! +MG7"Q#J?.\$Z6G"%]5+@F2Y<"5F<+:':/SRZ/NV?]\\,M1>L'0]OJSPVI2 +MC+Z5_.QWSX6&ED_LJ-62+.W(HH27[>D>S$!WS+<,_L5JCV$H7N"%C6(JAC-\ +M)V%?R$62SPT-,,>#:7WTPAJ[K9;\H"\169,Z2\2L!3#R9K-+\?'GHQ`X?YM!9142G-(; +M(H_*>RDU_4M)0:,;]R$T1+C;VD"+7)G7W>L>BCFZ![*OO4*A]&3S`FP&F).] +M"UAW0)$OHK3:'ZUU=5WFNO7[[SB;?CCI7?>OMO#+"2C?\+25P``QU)R_V\B6 +M`_R&B?IIHH3Q@L/'HG@??J*49!GY!%\EIGQ*&LDX5)M_"QQDMNOH">;;A<4*$D]B$:FOXKG=QDN5OA.=#Y]EAR8_ +M@;-=]Z[ZB+!ER;INY/3EQKI:P9^C"KG#237XH]5:^`7S29\\;R^2Z;/2+"@< +M?5[AO.=*BV#ED5(-$\PS;R!VGCP9KS88Z5+R^AI+65?3$Y@_,:%,=[?-A6GT +M+74CEY"[S$O&I+#+H6K?K?^3NA@6E/6[%>%%W*`#1;_O_/V_=_X!&NGOOV_\ +M4W8/U0Z6$Z"M6W_Y#G_.J5I(I_-"'S"NZ*\`\6_X^,=.%/11`M)]?;^N2X*R +MPW*`LKWE!]C/Q1W&WXO[+.>[UFTY7__O[SDM/%@H=6Y(,FZ+U[9B]UIP+)A# +MUG]:Q9@F45#A<*+7)I^@Y!540$TO4CJV,-6=%QR55#1UAKH1==(V^WQ`\!.6 +M(K:`/F$)?`7PIRN`KR3\Q/0YTPW=9_^I2S*O&OS4I8D6OD)2Y%787^Z$F9T8_6GHR^OQ?UT)23W;G_",N:ST?-/2#\*CC +MTY+G>T%=/P[P'M-/75;>Q9]89H;R)RB78OTG%"NOE?K\)6,BO,]? +MZF+Q)Q1Z__&S%IJDWOP3BOWO]GU+JIY<_?'O4 +M)[1WQ/54$9W$&G_"@BAMQZ2=EG?)W7OZ.5\6O].JJ1/[.#)7G;XJI4RYG\.EE"WT3RCSD]2ILS/X$;*E/EY +M?$B98M5IM,]_5ERX[CS_=G\ +M*R9T)Y:D0Z0>ER''6LL(2T/:%'RMSE[BK+;&4Z<&/=9/:T\\X[G.6TR +MV.T<9R\&.RT^7SKS+HL/K\^]S^KAL9EW6GUF?>:=/AXO"^QU^O,S@UW.B?KI +MKDO7'?DVI^F/UI6["N]>/1QFN;>D>0/+A"UR^CUT9SFFVYF:")/MY=-D6S\N +MT\PMV6Z^^?W77[[XMKS37_]!>U#M6?$DV._^N/GWS8L7+[_XN+_MRS_\Z7]^ +M_.R3K+A'[EG[``!\7\7KC;[XHG[:X-_4,1[:S\URT0GQ2OD=;7W3`!?>E9^U/?+3W$J>2^A\GW,)(3#X`4 +MK)(.Z[.?:LUC0'>'XY__]9M_^=??_;%\IJSX8&'SW^X'RFY;[UP/E#7;*,]? +M:#O1GR-2/8X_1U0]05$\D%$]'U8\!/'LK\76Q>,9'YY_T;YBXOGS7_SBP^JG +MMZ\.R?Y9L?`W?Z=?E8[T)]&*'2O_V3Q\63Z>UN[RMCOMWX=/I74C*1X4.?WV +M_/-/__X7/__Y;X^_??5A_>S(IW__UT__^F'E_EF]V;7=L#?^WS[_*,^VQW,A +M`SXN?GS>_=Y,KISWGWY;_-_YY_]Q_/FSGS_6O]P2Z'_=OGOU7-:C_^VSW^?/G_^]OBPA]5&ZQ +M^\_B@99??7S[J;RT\NQGNY_]_-FNMM]IUN4C?A\]?_[K9Y]_?HOD9Q_7>RVW +M:O_U9\7S7L]_U3[!7(:R]?YP\WX;P;.?_:+8ZK.?5YO^5[.+6Y$4D[DEQT>[ +M(CM*KQ^KQKN?=[OZKV$.Y.].^V+LU4;=$S_=XXG- +M_.LOR@W:M2]LE8<12[_JPXC*0V[-,WQU)11O4_F8]E3:X!'!QF?Q4&`Y!/UQ +MN+K(RI&WS\,]FWM()DK4T;[%JWPCP?/BS0KUZ,HUK\I(J1 +M?OZ74?YH['G6/ASVZE:$_\==RRT`*@0,*OLORO.MQ^;YUBY"O^Q>S_"S9Q\5 +M+P`PK?2'Q4/&Y6-D/^O"7S\4>C,Q\KHU:2R:9_-Z$7?'=FS([:"JN/Y'\T1W +M]8=!(B@+5H>H[[<<#G3!C)WB+_#Q-2$I'R$S!:5ZMFQU82E?^3(N*\L7/E8: +MTK1UXP*F4?6-=;3VIHB=-+X8MI&G]DHB^E[YF;5^"6FK7T3V4+S;K=&KW+C5'#G0; +MUNMOM]2=PE+,9&+:D2W.RD;JB\L^Z?ZN+F93U.;Q#WZ%)$ZU.^%$+U_K!*C- +M\H5M2EF:[#2/B+K7+0Q[<<]`"U'Y9MA^?$P#;H-$VT^Y@K^<;4_5&VI[.6;? +M(W=WAD2;=H>]E^@NL]_B%8'+[+EX[>!">UYJQ\EB4TZ6V_'3=K%=IPOM^3IC +MM-771<^V4^T%U+/MM7VE]=Q[;%Z2/?=^7RRTWZ\7VN_+A?;[PT+[G9&,@Q>B +MS[WG&>G4OK5][CT^S+['ZK[*N?=:OJM^[ITF\^]QD>#.JYC4=_[/O=.GV?NAR&X=1R^??Q,]BZ4_.M%\`=]4]D;[/^3/JGF+=9GFZ_(?U)_2EI9<[UW/NBYS]VGVK7ZZ[XB[VT51>&:U.%L5+;9N_V"U/*YT*G +MO9[3?C[27?[%9DKEFZQ4=W"NZ`;#73C'KD:K?ZW%-M0F3RC[*"/[RUGV,KC& +M,MF>BON99]E1^1:/^BF-?D+;]LG;H?*Q^<%EG.EW:;B",_U.#1=O9MCI`OLT +M7+*98:>+['-XVF&.O0ZNT4R_T^$!XS3['+DT,\T.^^?E)F/L^/6):297[_.K +M!?9IN2XQZ3Z_66"?WRZPS^\6V.?W"^QS)K@VUWGFW9OMJM*D>]U?[Y/+S/M\ +M/.PVC^63W;/NU70A8M(]OIYU;V_FW=M^?RJ:9HWKFFR6V*F/\ZZMWE5P+RPN=RZU67V +M;F6[`#GI3N/@\^SSG._V)$^MN +MN,>LU;?[BGL6T^/^F,\4T_.[I_*K3;=MY]FAX2K\9"&U7#)A[$O9A>D*2KG7 +MX86.\L^CUU+`5TE=>^E=4U%>[*`\P%Y&J/F/XBVBO967?26%;RS+K"!9>BN;S=PL.H?HR +MWB(#:#Z:M\C.JR_1+;+KYG58B^R\^PK?,KLO/]"WR*ZSP>C.8ZJWUW@RG?9^]-R,R7JM;<#A>C<9X]6O!X1BN5"TW +MFO*-^MZ,IGG7OC<#*C[CZ,U@+H/GNI8;R_#2QQ)C4=[L[\UH/.F<[0<(O!E+ +M\T%);P94?&?2G\&<#@N=.+9_E=*;X31?7?!F0,4W++T9C/&Q@^6&D_D$G>)# +MF-X,)O?!K-8!Z\_LKG@OMOO;RXRAOZ#DO/MN?EJYR(['SS/.?.N-^VW +M/I<>PX*GB1U?"%UP3(N>INU_4]2'02QWHG;X)=(%AZ%\I-2+4=@?@EAJ//4G +MZ#P9S7+GC>T?0?5C.`N>,39_,M6/H2QXKMC\@54_AK+<66+KYUC]&(WMMO.% +MAK/46=G!=UV]&,6")X9-7X+U8R`>=.C^MV/]&8KQL?F%QK/H.4_+!VC]&$OQ +M75H_1E)^KM:/H51?L?5C+-7';?T82_W-6S\&L]@Y5^,7R2+W/`V_J;OT +M$Q/EYW87ODW3\$S5C!FQZ,Z'W^]=+!^G&T#Y%%GUVKS^`+J?!H\*=D:&_6J_ +M`B9N>C[/^@W=Y]L'FZ*\NZ\JS#\JS%QN<"@C@_GS_P8D3\C&=?=4WX8/;DV\Y@@#T3./*12C-PGZ?GVX]O#O4?!ZH\,O=Z?S]\`_;F'8WC +M_H1Y!_,X?B%SYL&,7T&<=S")7X,9OOMXP<&,WD0X[V">MF,WU\P[EM/VNE%^ +M_[4'I[;KD9W39)L=SN570\:?$%EF7$7DG&^WFW=H1:A>;;/BU/+@M>Z+#>IR +MV>T=]X;..Z#1NT/G'8H7O*X^VN5Z%&RNP3A>WSGG,`"O;IQK.->\>(5C5A676OWKPIPDR>C14`K#_7V>WMIIGFV+LXS; +MX3UV2XX/_K[2.8?F?D?GG*,I`E,^_78]G/.]#RV_&1;D(HS?GP>/3D5CMU>/X<[E>C`CT"N<"(?#B' +MK8YG_"UPRPS((PFJC:QX1'+[X,,ED<&P[A:^Q]XZJN'GV3T9UYV/V54.;/AQ +M>4]&-OP8O"<#\^,"F&5H/EP.,P[-AQ/B@X%YC/YTY\'UN\&HSC]EGU6W#3A> +MU[SH`/VX7FX?F\>QN_>MA7IRI[`ZI$?U#+R'0_.M*Z.K## +M.?6M"HLAE2=1BG.&'IV;ZT9W3;/L]D_O!O8Z30[[W#^=W0VM^!ZPKV/+/#N! +MT8VLOI5Y[\$UO=X`L\S+;+L-RX<'T(:C.N[?^AJPV_^>TI\\S+'WM_]_./L7 +MMO%O!2PS($^EHNLM8PL,J;@$[UU*C7]B89$!>?!LHCH@+VZ5[PVHON'0S]+S +M]_@QO_/LV#'W[6`V3WP;D&]G5G//QE.^K='3>AM_2>$"`_+NS&EQNM2SM?/I +M1KQ",N79Y7B_S;TY3"A>&>7'HZ#E<'P+3SL>]^J0/+F>I@[IW9-WZ5V\ND`^/;RA#`^/./0?"S(9FS^7$PP#J^ZL\:SP7ERK\AP3)OMW3E- +M+OG>D_?3&T9XGVS/7IQ7MX]M:\/VVS;>[# +MVW\-`_SQDM:7F7PDGA>?N-%&5'QBTLO>Y9\TROV-E&?GH)6!N;X;NM2X7-\0 +M76)<7MP9TQ^1ERGOWXF+XI2OIY$JFG9S\MZ+6U2J`7KUPG*]': +MG&]*QP.PJO>$S7W303F,YQ]]^?V7U:Z>?]3[;5.,XL6W__:QX:>;^R__],67 +M?WKQAR]OOW_P=_^4/3W[Y.&9S?L'?_?\H]_]$K/>?*N^%S=\9-B96]1_,T;S/\"JMQVVKE'?LN%U`ST#\%ZMJZ +MC-8OD=OW[I@"V:#G45K5KVJK3M_]P#'6'K#`FS]F[UGF+.N$M_.$::U>!:/8 +M6XL"8G[%#KYN>OHY:)#E8_G?U>NCD:;5IS;0A52;_7YS.9W4.R(QQB\XQE]S +MC%]RC'_@&&,3LC8SW.J!,K:[AW-#+VWXONRF]Y)$I#E:7L^YZ^R +M]/+X:K-+\UV*75+50;8O@FP:@J++&S&K?9S#M6&2CFUQ_VI__V;SM'TT2C>' +M@<.U5=N-;.QPV?MF,F#;<8>]CQ^X-P6XNVF%T[O-W:N'`\*Q8@3>Q>UPS)1R +M`"/(+BROL,<:0G;5/T<)M@`Y1T8)'*#!MRK@)A#WU^+[$QCGE<&XZ\%'OB$; +MC[OL?>79O>FXN\'GZ2`;C[LT?(L:MKG#[>EI]P]`E^6FX^ZR.YBOVW8.1_NM +M25S:MG0[J]ZX?SCFJ?;5!IP99#>C+X>GF4-W6SRF=\7NK#*"[J(X?WB#RW&W +MS7:#1SKH+J"[MY]>`ID!=C-X@S[8`N!\\-$0L`78.2[=.AO,#O1+ST@[Z([Z +MY\Y15H"=&#\CBK*"[*3ZN'%SC^PV`6I>FS%^E[UG+6CF^-T.'Z<@>\#OW':B +M`&5.V"UOK[2=VDXTH,P)NS6?:L!8XW=:?$J$OM/2&K_3P4,`5`?X76LOE:48 +MXW=Y,9V;@=OB=V@\LP*WQ>S0]%@`R1J_4R+X.V/"+H''719;_`[OBH-SZ*'D +MF`/\KK6O4%",";LT7Q'%6.-WVKL%@V:.W^W@KGFJ`_RNM=?_48SQN^S=&DTS +MQ^\VXQ1L1JI8[;US%&/\+G/.+'/2+*^<75Y)NV2U&'>'.>>9=GL,8%N(P\WY +M=/M';KHZY[89W\$E/P`;8+GEN+.?#EE^V0+]-1N/NT2=5X"=3>A]&=F]*<#= +M9KL;OF,(987;R>AE99P]=L?O-O"S#%9K[$[AQ\H66^0.<4?)=G/D;A''QQ9; +M[`X9^R/L#G%,;+'%[A!\-&PV1>X.?AQL-D7N#G4$;+5&[G3D8C_*'+E;Z.&H +MR1"RJ_)T-/C2=\\&O`/$A8"!%7@GY$L!#A_@`>":]M`.LB/4&7O=!.X>?,Z^ +M;X3:!;:?8D[;C]SSCC.#[*9(FDHK8_:B6.%V@CAC9#9%[@YZN&(R1.Z*H+(, +MULB=PL^("7NK31%[J[W0"'!%KG#WI."!%OD#L&G8XR6R)W1R8T!-^HR\M#,O)M: +M5]Z&`])SP\W=;D$"RF1@=MW]:W5_:/,?3KEK,P3?UVEU`+E[TVH,N$_39@NX +M)7/4%'K[)<")^];!<2>(6RC''4%ND'1X8$X%=+/CN`O`#8TV!Z#;%FW&@%O_ +M;*8@.MF,@;<=6LW=MQ?:3%VW$EKMG'<.CEDB;A,<=X.^#=#M#M`%W$[01^UN +MEZ`V,NH&=-/=J`?0<3K``V^9$,?:;C^0`^E1+V!I,NX%>0L;QAG@A#O&'>QT +M.L8CX$PYRIVH-\!I;I0[YTELC#?W.6J,-]`I:(Q#YZU5&&>NFZ8POEPGH&&^ +MH">N,-Z$*A]VD@OC"W3C$<:A\W8BE#/GZ2Z,-\`=0!AWH!-&&(?.^W4PS@!G +MEC#NG'?8X)PY[IW!.'.>@L$XQV%)L/]QTG-DO0[24V +M8Y86!MPR,FH*OCT$Z@5Z_P?<'^2"`]P;73X2;\4`NV,(1\+=$V!7#,E(N.D! +M[(HN%FDW*X"]P>Y"`+NCBCO,O0,`'XP3"9SK_P"??'SRS@2@KLH#G7"!QSX9 +M@+MJ#O7".+I`7_(&.Q+H+Z@KU2A7@*O08'^0B\M@9ZRC`,KU8+`OYZ5>L"?W +M=5RP*\`U6K`OP.57L"^R\,=?-G5[(IUX1%[S'#,'=9+RG39]+Y:W#+K,<"=N +MC2[*%^K<&OSFX59!=^?=YOAP_DS"3QG+7SF* +M]MM<^\@BS57QQLULL\^RU%%U`%>0R]0`-X`+UFXOH,N4;C?E1W?]L/7O@MY-5Y.A#HLXBJXY0&T%/9SJN&6/5B +M.:^52!#V.HD[F?2ISXER?17#$ND7D'.K4"^;^_1H?S4BRJ$B(R7S;J!.I=U. +MXX^<>G>WC*/SNGK'+^34J-.'^_#7Z>+1>73C=N$\&'&Z2"1<&%_*BG/A.E_J +M=/&T=9P_<'JXR?"-\ONOR:*\]G=.DVUV.)=^(3?X@1T67S%QGNMT>BN\W`[\ +M=_KGPDFN+I?=WGTJV.G&=0K8Z8"1RZ7T@5QE&G'AOK'580R["W/$R34O[L%L +MCFVI;MK+/I`-X[AW@ +M@'-<4N!,;&FZ^TIO:'LDCZF]X9+MH/@,RNW8*KT58YYM"_6W3OAG._I9=XX`U[7A3D"7(D%.F+(BKZ?[A#\ULKIQ]ZJ6]#U +M6)2KS?GP>&2=PE.=JLOX\=XZ-[NY*)6NC-^[(?NS_CY'KH[SJ&6Q2']P,OHD"[`!^[$RT+[ +MBCO3U_FG[+/J-(#[9F>L6\XQN=VC^#CO94J9=<98=?2H*GXQAS(57+J2*K9' +MTT=;Z>X.9_,7TDB.2HE3Z$NV(NQ\7M,LN_U3R-WK-#GLG-$OSPU]'?=O90=W^]]3^I-8[-[?_O_A+#5$ +MYW,!8#>B``7,$?L]-??I1FBL2`H-A7PQ47$$>>0`Y.NVS)XFYG??WC).BJB/6D9OJZ-V34+"+ +M>_:8,<(]T@;UQKG/0O,$>P`-Z(QS@F;@J`I^OGV2<0,+YVMREQF\9TQW*+6KCD7N@8'1:G;<1<G=/D +MDN]9]_(;_-XGVS-#Q]L];@[''>,TL<'QPT.R?11F^FU[;YO3[B@UN +M?[RD]4&67(8R'@'2_!2/\@E6HQ3$APQ1W@N46$-\"3BT!OC#,X?3^" +M"R`E4`H!+3JJHN2;@P7&21GDP^4N1\7`BIO?E9%MSC=`> +M"7W8;Y+M)WO'-2JKD?$=M\:MBV?WRK-3CM-13F-EE[?:^L7=>7?[QR?5/PR> +M!]N,//2J;&M_VE#=Z#:DO%S#O:G]*5M:WK>I;'&^W)T=3BQOZU&VL-VU7&Q2 +M)E$=@C*!+(_P&KU;V\X:VBV*-_&B#*IK)38!-F)7W3=9$MITR1QF +M:;Z2!;-]S$Q'B$!;NFG"V*WQ.@O4U'CF`&IL.N:$V1J/P^VF=?NP'$G:[5[M +M$U,;M!M4#S]M7FPNIY.1AT[3K^BF+^FFW]!-OZ6;?D==KA6WAB5PYB/-WMM$R3'6._/U*,2`P@ +MI/8'96=_.-QN,W(<4OQC^[, +MRK\[C?1=`6S,U[E[=A_L#N>\>*?+\9,BP#>H_F/KZ^\_S;=WG]Y_\,'A6':D +M9\6X?_'\HR^^_/,7?_C7CYN9M$=6?TZ=6Q:7&V";M<%T;E[-SC:(XL9;UQV-4'*UY>_KPP6J_0NF_==,^Y=,^Q^8 +M]H2,'1P#43T0LJVVW)$M'\B6U>$3U;H\X4`U3NB6K$'3B*8>%E&-G\B6=`A= +MZ)879B4T8I1J3Z%^;?J.;$G99_'>O$UU^0]M?-J>S_FK++T\OMKLTOSV/YZ/ +M;%^$71N(<@6G\]*([.*U+7].@!NKW_B#&S5Z$&Q0O1H1O'WUFA/O]0(;=.^( +MA)N4W\L#;Y[=(;8MKM.AMM:_A8@LPP=#T=GJ"F_;@&V7:O+T$ +M9]6\.8=BA0^O_IX<@FU]UP#.4GT_'M)R^!TZEH/JSFV6B_:6;9:76B^S7+`] +M)/Q!5#J6XZ'\#`C+0W/;-,M)\1H"EH/+A6=?J%2:O7)S-Y??O=-+!=>?<5>.OF^VA@`[2&JN[UPFVN?ON,;*F>JZ/[J+]! +MP_"`DR;V;YG172!%B?F;971SI!PQ?YN,;HX3(M9OD-$]="?*R"XP(J+W?3&* +M'?)`S?$=,8H?&F;P1UW];X11#2F0(!UX#;[_1;9$*DO3=[[HQD2N]K_GQ3.O +M+_Z1?=0/S=$=H-6@Y?M<=/OB,1ZZ=?D=+KIY]0P+W;YZ:H5NCQ*`QN]J$:S! +M)TR&W\]"F8`)VK^CIOF/LGD0;;4+`50?P_M$7W5@&.M7D3@^ZE. +MUK/\]"XQL'R=!Q>T*$[XD@6A<7/JBFY740AG'OL@C+D_$J"=MCC7ZV'Z,R9WLUW,^(]]1>8>$X::4_ +MWPE[X7J'!6Q7S4$"QY&F/5B.#-=N!/W5YTL$/79G4`2=#FZ,XGN4=CBX#8KO +ML7=W$]MA=6Y&T&%[MD;09WD)2=#?Y2+J3K\-BN%./2L@Z%`.$-UY!T%W[<4I +M09_EM2I)?[TG#-@.ZRM9@A[;4QF"/LOK7(+^ZI,E@AXSX60L+XH)^LN%QW<5 +M]L=A37-!C67>75\CNJDNMQ&-VZMO1'NN^JZOS7&LM4MU0H[,=]DS738GG,4< +MLG3JR&4^*8\\A6JY""CEC:=-+9<(I;RQ5*G]`J*40].-]SR/#`G9O]K(=\,[ +MX>&Z%LEW*P)=]NF*P85+&3\"C)0X8S&\RBGDB'=X8[P&*N5+ID,-KI!*>AL\ +M+;)5R5EU[E?)67XJ5!CO1;T'P_J.^B\*@%L"STP[O)3/IMU$0_/UY\WQX?R9D*LRM+^R +MU2[4F\"`[#4/]L"?2OV7[>FP>=A77UOE>RO>KY%M]EF6VHH3Y6WT:C_*T]AU +M?XRC\:NZ&$_EU=7J.5`Q;^4K:J2<%1\%$'#FNI*,\54RYCY)S[@?M%YW+J];IW>O]?4Z$_]#Y<7\M7A%8O+QT]/PPR[']!"?: +M;1%AVPD8M+-2'U2-M>KLHHXKX2'O>"J/8CE5G^X5<%<,3JK7C)XYQCO:W*=' +MP[L,B#X5O2J +M[$=#""^)D)M[3P'PDGQT3[E]U]SC@1JE^VHM@ER-'+#QCC6U]CE:[0OGF#I +MN^I.$MSD`>OL@.IY_"(VT=OF?'@\>1:X585RRMKCJRWUI( +M\"0!8I;"ZTU\>+.'P3C2"IF0> +M]UE\LHX"C3Y9PG_@<8JB*;[C*>CN_%/V676Z8N3N=;IGYED#N],I1GLO5N[< +ML^*JKT?U2$/2IUB5/[:?1!+TQSYGH7H\G%.QM2U\ETVS[/9/ +M.8^OT^2PSP5;1.>S^/B%N--,2OQT+NOS[7O.H6S/=2CLJ[&:57T7X3(M:3G'I6OZO+ +M=2ERSK-`6)Y=CO?;G-]3BCO?F)>32S]B`VH=C3_Q!/%7">'A-Y20;M0\YYSK +M*[4^,P'TJI,X(:][Y,RO>WY#Q$ES*49F2!(72Q5OHX^Z('V=]MF3T"3/^WO> +MF5[5%_P:,X<3RRB_3%/*@U\56N1;Y_$ +MO'*O^NC.1'VQSM+T?+$N1VF^^%>--'>.!Q_1_EC"M?8DQM_.(WJ;G.7IIQSE4:?HLO<.!4X3#'Z +MK4XW27GEGLX9.MML[\YI\\^`&WP\/R?91 +M=K$VQ_0F+6]Z<)NS;@XW>/[QDM;'>J*9RWLD3'-5/`0J6ZZ"Q,LG&)N4\E<\ +MCCWZ2G(X]O`KVB'OK%/?E>QZ"(J>0J]+CZT@0W.0PCN+!'VQ`=Q7,;SBX09E +M?)OS#6"+$\8/^PWR?:3?69[,;;#L'B$LSQ5UOMP1_%U^%!4O-VMV&67_2\+8-SX_Y[9HT;G2]W9[>K_@NC +MC!L-[A`OMNKE0!V7IJK$UU76<@Q4"F]6?! +MB[_^P#'N78?#FO<^#H\V9UDGO)TG3&O]7`3>/N687]&#KQM&_T@48MK_OC7$ +MQOX)=H3U5RQKP^?7$=;?L*R_95E_Q[+^GF6-SNKFD_%4.]/97X3]_EJ:$*T? +M#[O-8_^H!V/?/U>*L'U-M'M#M=OO3T7][ZMK30.-`70S.#V,L250T_+)>80I +M6C,T=F6L\E=;LH-T=WFBCCI-=KR]_TBTHY*#FE"76PU>H.E^.,,>WTMH0 +M;7?:YOD^.Z+C5+Z[M;QGL7]N#6)]SG<'M-8H'OD_E8=MZ7%_S-%#KJ\V%L]T +M84T-[QB`F)D.G(J_%P699;0.ST'<+,S!?\&],//KW_-/W'#_[N +M^4>_^^/FWS9HFGQ_3 +MV>4BK_>JY&^^?_#[[_]YIN7Q9[+/R;Y;4>?Y-O'SU^\ +MJ/Y6;_'/+W_W+_]6;*;_]R>?%`^W?UX,^2;IRLD4&WWQY3__6_W/WWWW\MO- +M'_[TXN5W7WQ9_DW]]_[`-R_^_.=V3^J_WP;RHONAV?EM<4&!T-8?=7JN2Q'8 +MCOY2\/79)P_//C2$_L-G?_WKLS*I/WS^T3F[OS6GCW_QX5_&%FF;?]PE)'KD +MZ#.1UK0VSJ;)P4']=&33TP-#@H?H`0Z2W8ULB +M:$L#2@CS8M+@TI\9^:H%$#:]V0*AHX?R;_#Q)?<^*`Y^FH.@]BK2C3[EWYO_ +M[@$'%ZSF"`N-!?/0M/HO-QDO)?/[YNTOAX=GMBC^]EG^:G]\IA\& +M#K;9)^=];YLNZ(.M'PY_\;\N[EX'7AD++6ROHHH;;=M64?R'#Y54#@I41,66 +MM@JJO/3Y4\YQ%#YZ%$`%T`QC['=WZM=#,^=].9M`4YZW$J:,[1J`5SD+1+\S +M:\ULJ`(V`H9F`P`5FDW1K)\KU8/E^P(+.*R0]MJ)RO;VCY[42S=(:-6T%B/5 +MHW@U$*>+@8L\AFA!"T0;)F0[4,&H0[<63C?[<,MG@A4@JL2 +M*ZJ40(\C2]L0AB[-A-*#O"BQD'N4;PGP@7*MW79!_];,E*V4'T2*M?2'KEC( +ML+7"1=W"T%4P:#\=+BUQLB#3%56M*M$3P-ZT8:U3ZZ2:6H4$:9F2)237T;CQ+6;F9MLX$7]%)=>,J2]B]S-`5=#7C2 +M2TVT^A\9)$`]ZQ9F]=SW.MOEI^'@(-MQ3[CWIAM6I4VW;F/5,,W%*?%Z`!U/ +M$BK"_PM67E12:%W+OQ6O:K#8JSZN\I'2IB>5/Y=_6;H*;0,=5F&YI24;2YM> +M'5H]]QBGQ&*,*JM+9R +MUFGKW43$)B9.)@Z"AZLY9;#0;6%UUTW`47E-&**H/.$U=561WNN\KR-LO\-6 +MDIUX;>@=S%.V`U)/L:!W/G^J,)(.Z%%&C-9P]2J?83>L_NYI)=>#)M1R90FK +MYV8O5I+6,8+1M!]00GUV@\=LCZC3=D*06JW#$T^U3K/>D.HS=-$0ZH_430D5 +MZ&!HLRP0CG;;8EC:63$[K)<5'%/']3-C1AG0O^K7.?'E>H=KX`0*6*Z`./=D +M93/H>M-8:`G5/+CB`;9`5+3M*H@K5/'4])2K#ZM,0W\.I39)/9I8G0[J0JY@ +MF;?&D!=^'3/L^HZI:_N=0:.,:-XX6O[Y!T,3[VW@*2_ZTR!`H^<"QH[!?JV( +M[\<11GIK]`DX,$R09(B`PW#2$$;T@QH/*&9/%U3M&V1"F-5/$@TB]>]H`(-5 +MA?0!@Q&F'1C,F;HB6)#$I#G"S3PXDXI7USL42;%)"%0JI\*E4N&$P*5JW[!6 +M4\:3T&ST=>!"I9DHT90*EGKR:+24`8X4+?,E#Y(++K42%!GXBH7#!DSOJ-88 +MW3T:,W+_:!Q(:I<0,1.MA@DR$^',*KZCX]`RQ28A$*N<"I=7A1,"KZI]P]I1 +M&4]".]+7@0N99J)$4RIDZLFC(5,&.%+$S)<\2"ZXM$Q09.!K&0X;,!VD6F-T +M!VG,R!VD<2"I94+$3+1:)LA,1##++64"X96$D*&Q"M&)B(U(5,30X<)@"Q$M +M$0N8>;(&1P*G>`F'!0+2A4P#5+N@=0MNLYA`M03&E7@52V@9"&=4XC[SD@1R +M?)5(G'E):$=7">+@.2$>/">B9UX2^B%1PC@D2HB'1$G$9U[F2QXD%USB)2@R +M\.4+APV8]I'0CG<3[O%N,L&9EQ`Q$ZV."3(3$"4A9&BL0G0B8B,2 +M%3%TN##80D1+Q`)FGJS!D<`I7L)A@8!T(=,`U2YHW8+;+"90+8%Q)5[%$EH& +M8ACUM'7KE=LV85"JF`R?4CX=VH"*FI!ZD+0:?,?5DJ;9TSE0!()"F +M"'.TI)DQA["4<&N9H#@AH6>6KP#6F*^FL\A5^M>!*NUIPE;S&="6?"[[2SP5?:>>"K_%>8YHI:W`D<(F7 +M@%C`ERYT&F#:Q95TAO_*/,-_E;_&%!I7HE4LP67@**,>TNQIFV^.^[>F-[^K +MOWI*)FT"!":I]C`>Z7NT]A@M=K#^8@XW@1S]2>&M$,3H311""RV$\7!BKLR` +M5[1!<816TR2EP:QJ!]_U!82PO6^!X7K?EJDJ@F)#3"HBK`P;9Y +M039H/WO*&'T*!,1H#F",Z>W3VB#T^,$ZA"7F!$`,)D8P0R"B/UD((_1`QH.( +M&1,$4=\&$1%>A9-D!+O&'9COK2.$\P,3#.@'QDPM$1PJ8M(3X67:*'/24WY( +MC\;/L;8_>4J:;N@$QK3&,+XH^[*VARY>L-9@B"\!!MI$D"8("*B3@P"@"U@\ +MI3]Q$@#KU*`+PJE4DAX@UZJ#SLI:0EWM,O=[_3((PX_>; +MR^FTS^P=OMG`;WJTTZ`3I'&!XDBW7Q?TVSBBT#^,/AT+Z@1)AGA$*)-&@*(- +M:G2PF"]=4+5O5PV!53]'0?#J']8#NE5%=`+5B-`/5',9?1$>2"+4'0%F'H1) +M+UQZY$401'K!UR,O*#QZ`6XP+T@-9AA].D9>4#'R@HR1%R2,O(A6C\R7+JC: +MM^N1P*J?HT=X]0_K"B\H7>$%KRN\$- +M_<.ZPM>4KO`UKRM\+:Y'P@-)A'HDP,R#,.FE2X^\#()(+_EZY"6%1R_!#>8E +MJ<$,HT_'R$LJ1EZ2,?*2A)&7T>J1^=(%5?MV/1)8]7/T"*_^85WA):4KO.1U +MA9?B>B0\D$2H1P+,/`B3?G#ID1^"(-(/?#WR`X5'/X`;S`^D!C.,/ATC/U`Q +M\@,9(S^0,/)#M'IDOG1!U;Y=CP16_1P]PJM_6%?X@=(5?N!UA1_$]4AX((E0 +MCP28>1`FF5[(WO[D-X5HKU]OC5'<&7U1=A:>U_N$?9\CS,)PHR[WWRV +M/]ZGN[V]QW>;^$T092ITCG1.4#Q1]^W"OQ)/5!LPK0,=$OI$B:9X:&B31\!# +M"7!T")D[>9!V]_\)P8#YS>_H#CQ0,`ZP](K#^(]/8' +M?+$_$(K]`5GL#Q'V]JF2`%BG]MX>0*5R>CN^5F%$?L`1^8%*Y`?!WNYON4?8 +MVSW.)`@S'K/WAY.]OU<_^TV.>@IT=E0.4/QH]NE"?1T_%.[[,:>#H)L8P0P/ +MA':R""C4@8P."W,D"**^[;H@H`KGZ`-ZC#XT +M$T7@H0IA=&R8/#/@%6T7$<'4-$="4*L:AO5Z`1%4;RT(4&]M9=1#&&R(4#D$ +MDF$0QB1VR9!XSI:$(Q82'%,20#-(D)T@$1$("9X`":'\$V3M)Q&*@JF2`%BG +M=B$00*5R)`"^5F%H3G!<3JA03@1[OK_E'F&?]SB30,P8O\J0!'`.,N%>94CP +M9R`3X$GDA'`2N1]S!@AHIPX3XJG#A'#J,(GT*L,<"8*H[Q%=$$Z%L_0!N<:! +M=,>?^TTXYWX3X:L,X:`B1@T13J:!F//^:>3%1^6OGO.FG``#-H4]CC75'IW= +MHHP=KEGHX680HID4WHK`AWJB&#R4(8R/#5-G!KRB1T1$*#7-DA#$J@9BO5I` +M#-4;"PK4&ULA]1`$&V)4#F%D&(PQZ=B)B.)7WPF3\DY#%/9(OJ2@8\PR=LC> +MD`J=@F@FA;>BD"%%'U24(8R0"Q-G!KRBQU1#(#7-4PVTJH8R/<4>"S86)*:G +MHN<<@F!#E*HAB`R#,.;)+AF>/&?+$T\`1X(I3_ +M$[+VGR(4!5,E`;!.[4(@@$KE2`!\K<+0_(3C\A,5RD^"/=_?GGM.C)S3VW,<+W(`UG,DUG.1WI[CBSTG%'N.+/8\PMX^51(`Z]3>VP.H +M5$YOQ]9Q*$&1=[;[]X3HP+I[=?<+RX`+!^ +M06+](M+;+_ABOQ"*_8(L]DN$O7VJ)`#6J;VW!U"IG-Z.KU48D2\X(E^H1+X( +M]G9_RSW"WNYQ)H&8<7%]&*G=PG-^7/B?16I]X%AR`7_7IHLEK@$,EX!!APOU +M4R6M)8$5%]*'2KK0QL>-.;,&1X(1$1$:"UB2@DD#8%NX4+X]HUE1FL1%_!M( +M87(E1D429@9"&/73/CO?_FD7*\T&?O.IG08=3HT+%)NZ_;I:3AM'5,<91I^. +M$W6")$,\3)1)(UC2!C4ZD,R7+JC:M\N3P*J?(TYX]0]K#-VJ(OJ":D1H"ZJY +MC"X)#R01:I(`,P_"I.M[NQ2Y_>8WAXK!TP%TLT:QI]R;JX\4,4.U$"W(=$;4 +MD\':X,E031`!A2)LT=%@PER`5JU=1`11MQSI0*E<&+;+)4,0N]Z>`.O:4D8A +M^%W]$:H!SS,*PI!W]L;_SG-^O..T_7;TS8[&^]U5'[UE1OJ!"C@4.R! +M[-#V:*>\&CL@Z(WAIA"@-RF\%88#^D1!*%!#&!$+9LH,>$6;A$!@-4V3`[RJ +M=J%<6T`0S7L6**#W;+GJ("0V1*44@LJP4<:*012$RA"V,!"B":$#=PF,[D&I);4&J#T%U%#R38E5(X6?H!_DV*R9Y +M^\Q>M0'U]2=84*SUQ5^/2=8"U/6%KW7P[SM]4]RYO8)HX7,2)+>%J/$Z&UK +M[5V+Y_L"G40NXV=?0[5.[I]VR>&X;_#>_.?2==(.RUTFS:;&.NG\Z%AIYSG" +ME6$LW$FO#F9T`U?:*P,TY'T[K0#37F9)C#G=]WC8`]6^+UX\V0$`)J=N;ZTCWV".0 +M-OEJZX:D+O6RNV,-59[T)E5 +MS6V$5;W)N^NA'8#]5U?^-X,RY'TUB0"SG17]868VG<&CW(1T`E=VFBA0!\E: +M_>WOSJIOM\01?HZ,#I+@LZ^96@?GR]VY/5BH_F/I.JB'Y"Z#:D-C'30^=%#4 +M\QLA13\"[K3N!C'RLRNQVX$9,KN>2H")S5T$0YXVP/8J4R'(=N>J"0!-K*P$ +MZ#9P(J#;%,?MN1(\2'8OLG9J75SR0]+@N_SWI6NB&I"[(,KMC/50>]"I4#,B1U-8D`,YH5_6%F-L#V*#O8U4^O@;7;(V^NQU7\L70?UD-QE4&UHK(/&APZ*>GXC +MI.A'P)W6W2!&?G8E=CLP0V;74PDPL;F+8,C3!MA>92H$V>Y<-0&@B965`-T& +M3@1TF^*X/5>"!\GN1=9N>.?9YNWAN$O?GO7[)MN_+ETG_4%"[T9K+4;N2E.\ +MFN[EZV+@O*?/$"[H?6?:0"';P>Y#4P=OO1^M"T"`]3/A&HY5B7Z?IK=U`K]O +M$U$ZC94.[O]*/.@NQ4WN;`!^7S`<4!RKG9I'O0H?QS +MV=6ZC90?)`J6]@P38-!Z[7;;]W-V8*G4,&`O"C'-,;)!TQ%1O2:1P\=L/UJC +MMBFU9>J.T"+%2GWJ9XD5AU1@V3'#J\%^!YVJ"@9:C6SM]:` +MRWBAKCMA(?N7-*5F;IXY;,?\M#TUX3A*%*D +M*DQ'$&J`K0Y>.BFRNQG.(OM>Y4_\FS6FP&BJG% +MVL91C:UG`^N:6+AH-X@9IK248<*V!)57-_31`FMF'WZ!B:[C>+5HGL%U +M+US%6&'6AGL<9\IF,*`I!M0^YD6QQ=#/?$F"D4J]VYX/]\/>5OW9QWJM!XRN +MV,H.4K7-'FR,K&,#XF0_CN@R[(8-WQI>CNU4W"591R62HIQBC=U5-NR)WM<9 +MH3>B*VT^%6HT_=/#)!FI]/OT]&[83LN_^ECEU7#1 +M)5Z:02J\]F_#;!47$&5[(4379SMD\,;PZFRFX2[.*AZ15*;XXCKK:MA`/:\L +M0OM$UM8X%^LU`&"QW1)!Q=:&U3E]JLQHNJ9GR3%2V?NG4_YN\Y1G^_VP<:H_ +M^ECEVN#1I:Y:0RI>WYN-NUK,0/@U1QE=R/WI8&W@9=V;HKNZMM.:C:)31J5O6.DUE?-`"@^P8(3O=-6;T\%`1$T^<#2JHQDESS;'N?;XJ_ +M_F!0`=K/7K)$GP">)9H]B":]/5KYK\<.U@$L\<;C8#`MO!4""?VI`J"@1S$6 +M*,R8&_"J-BB$T.J:HA*XE>V`>F\)(5@?F&#`/C#FZ87``!&/;@@OR8"DN7O_ +MZW$%46S@.VO*2;!84WC`TJ;:*Z1;E#%$]PL]\BQ8--.CV-&`44\9AXPRHA$B +M8YY,P53\N+H(IN:9"H-<]?`&4"THL@4T1L0FT)B+:8V0\!&EY@@LZ8`D>LS> +MCVN/8@/?.51.@D6AP@.60M5>(1VEC"&ZH^B19\&CF1[%C@:/>LHX>)01C1`= +M\V0*IN+'M4!:D&1;:`Q(K:!QEQ,>X2$CRBU1V!)!R612WH$ +M0"&V\"`0"-Q,2+U$3G00H4%F!@49D0J.Z5,$4>,.L1%&E7.E!JW.$3>3.;"3$0Y.$ +M?&B24`Y-DDC/;,R3*9B*'Q<;P=0\4VZ0JQ[>`Q+*06;".\A,I,]LA(2/*'5' +M8$D')9%+>@1`(;;P(!`(W$Q(O41.=!"A068&!1F1"H[I4P11XPZQ$4:5$_>XII,-ESRHIT@RI/*CFC:6($5D^B.H +MI`.2Z.JXYG+U_VSLE7O-Y8H_%WN%GE"_4DZH7\6NN5QIYU"OU'.H5\(YU&N< +MUUQF2!%$C8^+C4"JG"DUB'4.9_Z5E@;>!(Z$W1 +MS0,MH\W&D#U82`'>##0+S!FN6 +M&@B1%]&HAD"3S4V>KQSJXBO_N?,55UU\A:?.5]#6\16E=0R#3J7%5S1:?$6E +MQ5<$6GP5I[J8*T40-6Y5%R%5.5U=<.H$FCQ,DYU,5>* +M(&K.I\"VT= +MWU):QS#H5%I\2Z/%MU1:?$N@Q;=QJHNY4@11XU9U$5*5T]4%I\Y!P/^6`/QO +M6<#_5EA=!,6+V-1%:,GF)L]W#G7QG?_<^8ZK+K[#4^<[:.OXCM(ZAD>N([ +M&BV^H]+B.P(MOHM37;YWJ(OO_>?.]UQU\3V>.M]#6\?WE-8Q##J5%M_3:/$]E1;?$VCQ +M?9SJ8JX40=2X55V$5.5T=<&IP3!UV<,&V!]0T,;0HH`W3=`]].W\4IKDJ?9N%!]6C5 +M`+Y7)+WO8VL2A%_@YP&TK?'(%?@6A<]5'5L']S5YW&2XLW;J.Y^Y<$?OU'<8 +M*MRY@7V'`_:=0*>^P];T';ZF[U`U?1=;IYYFX4'U:.W4OE5G5LG=K7Y`&0X3>?[8_WZ6YO[]CM%CYSHIL&F1:M"PPUE/VZ +MP-[%$05X0_C)+-"F2#+$LT&=-IP175PC(\6L"8.J?[M""(P`#,7`9`"L"2CK +MBF@&FA6A*6CV(LHB1)I$ISP"33XWF?;7^^0RHDN:WSUF4CL%*H\:!P@:=?MT +MM)'05VWPR%>M)=1&4+R(366$EFQN\CP>=IO'X_;)KB^Z+3QFCS(-*GLZ%PCZ +MJ/MU-!$ECI@V8@H_E1WZ%$F&:'YHTP831(EK7`29-V%0]6_5'J$1@*X_N`P` +MM05U7>&-0;?"MP;=7D*)!$F3V!1)J,D'(%/V_F#X8I7VJ\\\JH9/)E%ICJ%0 +MO3]74ZGBAFHHO5"3>=%."6V$YT0S33@CJOA%1H?)DP)4FRVNK.GCM,T]>TU7!:PQ%7KO!_QH' +M_=<"*N`UMMY?XVO]-:K.7\?6]:=9>%`]6KN\[Q5)[^[8F@2!]S4*NJ^)P'TM +MULF]K.K8.K>OR>,FPQMKIW[C,Q?>T#OU&PP5WKB!_08'[#<"G?H-MJ;?X&OZ +M#:JFW\36J:=9>%`]6CNU[Q5)[]38F@3!]@T*MF^(L'TCUJF]K.K8.K6OR0,@ +MPWY_VASW;_?9YN&0[,_VQMW?T&=J#"9%1DC?$X8HPU&XV#^(,:H5V%>(#`_3 +M]#GV>+080@(GS6`%(L/.\AE&(8Q=B@3-&(90$:4,K!,-$P'1F$S&A#YE6+#5G1Z*<*D=9,P&;W#(?']NFC"N\,AP5X536`7LQ/\Q>Q^J*F<22C7,Q/: +M]A$]`Z'((@0FYH( +M);D`9'G_9'_98_FCSU0I!T]&2F&-(4JU-U#[`=P3$IP'\3RHW28Y6`7#T +MF2!'>NL_8LAQ=&/^B&/\4:#='[&%?L17^1%5XL?86OPT"P^J1VM;][TBZ0T= +M6Y,@ZAY1R#T2>7L4Z^!>5G5L7=O7Y`&0H;P3('^U'6G9W28^DT*9"!D8G0\, +M.=0]N^BNQ!*%>=,:D)&@3Y-FB8>$-G4X+93H1@:-N?,&1P.[8`B.!PP)P28" +MK"^HRXMH$+H9H5/H#D3T1JAPB4Z3!)R$`%*EN\N3_3I#_;//?*HG0"9398^A +M4K-'5Z^I8X?J,_UXD_'130MOA<=&.U4X,NHH1@:+.7(#7M5V[1%,73,T![FR +M89AOEA"!^,Z$@/?.6$1?A`*(Z/1$0$GF)DV:[%SG/91-/.:-.A$J<10?".IH +M>W;T#366F-YA7`,J.GK3I%FB$:)/'8P1-;IQ@63VO,'1P*H]PN,!78/PB0!J +M$]KRPEM%SPS?+GH.)'1)L'")3:>$G(1N4OUHE2L_^DRE'^GBY$<,@7YTMY0? +M<9WD1P'A\2,6"3_B2?`C"@`_QB8JIEEX4#U:!8/O%4F7!]B:!''X1Q1^?R12 +M]T>QCN]E5>9N%!]6CMU+Y7)+U38VL2!-L,!=N,"-M,K%-[6=6Q=6I?D\=-!OM+ +M([U^@QOCM9"H-[0!7LN'?`^?Q*L=T2]%([P%#??:L^A>SSC-PH/JT=JI?:]( +M>J?&UB0(MKA7S%'?*2?WYD,OJSJV3NUK\KC)<#GL-I?1KS]W6WC,"64:5%IT +M+A#44/?K`+L21PS@3>&GLD"?(LD0S09MVF!&*'&-BQ3S)@RJ_JT*(30"T!4# +MEP&@)J"N*[P9Z%;XIJ#;2RB+(&D2F_((-?D`9+KLC_?I;D28-!OX3*5V$F0D +M-1XP1.KVZNHQ;0Q1+688>3)$U.E1[/`(4:8,)T@;T+D6"JGF& +M$&%5/:P3=`N*:`2J$:$/J.8B&B0T?$2G/P),.C>)KN^MJN/VD\?L*09.9<[- +M%D&;!QD`U-3``BFC%5?B3K3^L.JT*P?_ZI*L" +M?(6"H%PN$QS']>9X$->&$GW?VR*/K;_[G$1N4MC;N->48#1Q%"$`"$<27**! +MHTN;4-FXPHZN>4^S\*!ZM#9NWRN2WK:Q-0GB+0ZW5-K*=6POJSJV;NUK\HR0 +MX;3-\WUV--PQV/[B(Q>Z8:.IT)I"J*#LQP;L+DX@8!O"BJYI;0HH`WA-J]-R +MUW07IT@J>M*%!]7CL%,'4I&$3DVLR7'8*NL#@*VV-0*VFAVK4_M&8;Y+T^'BS>F7HU_KO7C*B-P4\)W0'(%KT]VG%>2]^,*C;@HZO_N'4 +M"&8($@RF"^!!+Y:Q,&'>%$'4N$$#A%?E%#W`KW,'WOLK"8'\T`:#^J$U3RT$ +MR(MX5$28R39"GG.^.Z1#45']V4?*U`-&HZ6R@Q"EV8.M&]2Q`36!?AS1Y=X- +M&[XUO+C;J;AKNHY*)(4\Q1J[JVS8UKVO,T(31U?:.$6;I0#`L]L4P]\?<<'Y]L(6?U=^?!@$#/1D'20"2%!!A@(O]@W4%M0&# +M%:HC&.R9"B)![VU +M18.`NV>`87;/E*<5`D%`/+H@G*0:()\T("=X>CKOTK>$"0?.#CQQH!XVF0&,) +MH4"W%QN9VQB!R#R,*+J(U>%CMH<7L3(E=Q&W$8JDA*=;<4@%#GMQ$#5(Z,6D +M*AS':KK&O91Q-+_8X:3ZX!7B;W;\Z_+3_1?>OU=B;_]C> +M)T5#5K94?V'1H+=+/!&@P]>@H!AU:3YFWI$!O+\.V;:X69CM#+-6WZ2IH(W& +M*MT^O:;4H3&;M]IYJ;=T,H#KMFCC05=NKZ'/4+M]2EO7S(CID:U'.3UB9^WN +M,57_W-U^QOKW,J$@!+E_M;]_LWG:/A[N+0I`W<)[GFC3H5-%=8.BB[[_T::@ +MQ17>',S+06=&?ZID8R1#>M-'L$2+<8Q$F3N)T)RP*(YP2<%1(#*L`#00?:VA +MC:1OA6TH?7L9I1(X=>)4,N$F)(A@3[OD<-S;5$[]J__<:J;!(%;M`D>K=K_C +M#:F)(Z(9#4+/X(HR-9(AEB?==#$L:6(9)45F2!14O=O42G`5SU(IK)J'-(-V +M/<&-0+%`-P'%5DB1A$6.2!5(,`D'(E#V[I2G-L%1_>@_?>I),-!3><"1I]GK +M>`^I8XAH(?VH,X#138MBA\5%.U4,+>HH1HF*J3,$4^$VB1%8C;,$!J/*(;1O +M%A(,^\X`S?K.5$A;A(.*2'5%$(D&(<[^F&?O+)*B^LU[VM13H*.F*_H!IQ.BFQ+!#,F'=IH(/-3QBY$-TZ8&HJ8M(B*LJN9("'I=`[C> +MK"`4Z]WV6*IWEC+J(1`VQ*D<_$\P,&$V]^GIW>:<;_,Q_:!L%09SU&DQV:.X +MPE-(&X>[F:AQ1K85XQ(Q^=*;.LL!A3EZ.+#T46,?+8462C`27\:T3-"$8>L; +M,<9`6Y*6!ZCFU+,DM:F>#T%%%`^Q(E9.420LG(#E2RFR_3E-?MIGHRI+WS(0 +M#O:FQR6A[HY`P_YX`$VQ%W=L8[0M&Y=EPU"PG9"8-@@/FFN]-8F7;,LG'YE+ +MH^HL!C+Q59HTF\#-KY\CN`8XM*8UP:$?2>46+>UB5G(Q)C2U2XYK/HH9K>LH#B3U4]`0BEDCA9J8"**Y+A^&=%Y? +MYJ(A]5P^_$H.[2*.\`5"SIEV^DEV\OGUV"\&SI0]6#*,*YW@V""@H8QTN>^9((S8E1'10B*?@:B,L*<'MIUAK7 +M7#HK6FOI["653[#4B5GQA)B0$((][O/=-K>="6I^]9Y;[33HQ&IT +M(;5QA#>C8>CI7%&G1C)$\D29+H(E;2QCI,@O+'JC^LU[]M13H'.G//H!IY.BFQ+!#$F)=IH(1M3QBY$/TZ8&HJ8MFB*LJN;H"7I=`]#> +MK"`4[-WV6*QWEC(J(A`VQ*D>_$\P"&'24WY(CV>+;FA^]9XQ[33HC&ET2;1QA+>)8>CIG%"G1C)$LD*9+H(6;2QCI,4<2B."9,&'$W"YP&@ +M3:BK"VT4N@VV5>C6,NHD4*[$J5+"2T`0H4Y/NW^P*97R-_^Y5$V!0:32`8Y& +M]3['6TP5/T1[Z06<08YV2@0S+#&::6)H4<4O2DY,FAJ(FK8ICJ"JFJ4TR'4- +M`7R]@F"XM]NCP=Y:"JF*,-@0J8KP/L$@A,GN+)+A]H/W9"D&3X?*S1I%E')O +MH[V@B!F\$6@1ID.@G@;6!EG^U=00M5]$*\:RGR0+H)5J$0*AU"I'`E"J%<#F +MYQ]WL]$`A%CO]W9NGOQD__,*"?`8$9ACZ-&M<=Q +MOI>Q0Q!>CS6C])OIX*VPY5]/$0.`,G)1`F"ZG(!7L:WS!U3'K.Y/K&0(N*NE +M`Z.[V1P-[\902`?X#X-(]8#7B04ERF:WS;>;PS%/-P]C(D'?+@C2]*;&@X[N +M#$V@_EB<3:07;UQ'L2T6CS+#$#!=$/@S"`L21KUUB)5+RZ8;D3TCTB9\^G!% +MCRQ_@%VKGQ68%C:TI?2SH1#UGZM'DX)+8W +M=-BW#X27QJERJ6ER2J"G>6R`MFI<#VQ['5]4+@5M(1)R1:*B)6QH.AK7+5Y& +M^IBF3-:-JL+8:,=7B5/R#MQTS=F$:[XV'[0F;/,FJ297Q]&8U>::"@!'Z%-Z +M/ER=&K3:*B`6U].2X&_EBDC=9AS`IEW'F=*J^TLDP;]NZBP'9-:UX2`1KHY] +MW%2;/\%(?''JOE`)(Z/Q)!B#:F=-'N";6&=);UV=#VG%%@6Q8E=BH2PTKF?<'/4YA048Z=2,,5)21D].S4E4ZS9G&KZ1V_S0V[K- +MH[0J736#8U>S:RT0,.'WUSS;WMN^L:YM$@:]VPDQ4=WXP9.Y&X&[V[>Q13;W +MX9HP4:A.EVY-`9T2`BS7VDA'"[%Y]D?'8QG-)F'PK)T0DV:-'SS-NA&X>U<;6V3O +M&JX)$T'J=.G6%`0I(<`BJ(UTM`":-Y?PU!C308%R@ZV#!,@!;3?=DJ/:C6I& +M:C>J`T$=%#:$(M9!P28FDFB.1Q^ZC4)BFL1##ITG*M6@]XDK,2;U,=$'%_1I +M<^SI4"+>3ZM$/7(LS9M9%**X55*03!%22FRJX)H2X49IW9#1F"9X)B`.1$6O +MG0).5#SQCMLGF(XJ-PR,>]7DI,A7>F/0KQX-HOM5,:=VP-Z*2<&K#0/7!PMB +M36C((*M6(WZ4+91U5!*!]%>X+)+383(T0K>Y.CEHK:XUYK6[ULT4VBPJO*U! +MJ\62R#AB/NV?TNR=4[G5FP7$RF9B$IRL?1$IV8X$V#N;6%,ZYV"=)'"F3)_G +M@8RR+B0DD#4K$#?$%LDS&FVR^49C39C^BMPWK#UER!QH&U,3P=4&^N;DMI8WXF@ +M_HH+8!'KKV@2%T[$R^F49GEQ!BW?9YMMDHS*L.'6@=#1,$TN(H%J2!FS:EQ#PE,)?/?^`U\?ZBRE*S"Y&0*P%RMF%CLK->M[6PTX\T9;(.H3?#IYVTYI3E +M';$--]G$:<2=#XE6W'F;3GVN@*/K4:%Q%P"5T,5*9OOS^+5FBTF0E.XF+(OI +MUB^;U,H(T5V_6QM>XS>LL2Q:M7#)>1,`K!I")F.[E5P+9#W+73X5$=(U%BY* +M"]@IR$CLXDJ*<1JYYD:BEVL.I].S*X/N>K3M>@J#2O3'[":7$2*WVCY(DM=3 +ME85XY91-\&9L:'%0KP=/&?0759:N78B$7`EPM0T;$ZKUNJV%IWZD*9-U".D: +M/NVD1:LL[XA=N,_`R<;^+B4Y!PU,XKT'A%^^X,NC-N +M<*Y([*NLY]^I"F3=0CY&3[MI`6H+.^(G3@1./F3B)[\268X^[D"CJY'B<9= +M`&1"OT]18K38/$PZEQ,51G/ADT_F:F3X#E^N!;/!Z^LIC,\F/#*>).!9AXS+ +MSG+%5@/.Y?.31S>,_`R<;^+B4Y!PU,Y;I1&K\38N1/INXVQ"W1DW.%>D.:-- +M?"J1C^EQ]"LTILV#Y'$U45D:ES[9-*Y'AN[GU5KP^GEO/66QV89'QI,`-IN0 +M,;%9K=A:H.E!?O+HAM";H?--6F]*$H[8=NLTXK3=UH5$VVV=3:O1F +MO(E/)?(I2Q^S[1-"!U^N+RR+%5#)>9, +M@*A*^)A0;==P+53U*6G9'$2(TSA(*"U1Y5E([-==;G%:MNI%HFNK_J93K"NB +M['K4ZSH*@DKP[(11L<7607*[G*8LL0N7;%I7XT(+@'(=>,U?7TI9CC:A$7$D +MP,\Z7$QVEFNU%FHNG9@LGB'4:-A$DU:A/;/*6HT+W[&(->"U;6T590-9AD?`C +M@,-@^1M,4E9VMX\LFE;C@K=H8LUX'5H;15EP5B'1<*/ +M`!BK4#'!6*S26K"X:$9R"(;0C"$S3%HS2E&,V$K+Q.&TTMJ!1"NM74VG&2-% +MXWHT8WR)CB=NFCUM\\T_0%]XI&P>&'/5B4HQ5_')H*XV,D2O5M>"VJV-ZRF% +MR5YX9#RQ4*F'C`Q+=<7BAZ4W^RYX3;?G +M;`I]N0IPKD%GQI[X5"*7W[@'X[C\CGR(-"ZG*8OBPB6;Q-6XT*V\7`=>)]>7 +M4I:736A$'`G0L@X7$Y;E6JV%E$LG)HMG"($9-M&DY:4_>;>[3'>QEE[I%D.1MIRL+W\8MF\#=^-"MNUT77O\>+J\L.]50B3D3H*@2 +M/B9*VS5<"TU]2EHV!Q'R,PX22@M1>182.W676YQVK7J1Z-FJO^D4ZHHHNQ[5 +MNHZ"H!+\?GN'4+'%UD%RNYRF++$+EVQ:5^-""X!R'7C-7U]*68XVH1%Q),#/ +M.EQ,=I9KM19J+IV8+)XAU&C81)-6H7),(S;;*G\XC;;Q(-%D&U_3* +MA1EGPI,)?#JD&$E9;!XF@O"Z>G]19>G9A4C( +ME0`_V[`Q`5JOVUKXZ4>:,EF'D)_ATTY:@,KRCMB)FVSBM.+.AT0O[KQ-IT)7 +MP-'U*-&X"X!*Z,,Y_>^_^UT91G=N&53NAL?NN&WZ\)K^OM@@56VP=)+?+:!U_SU +MI93E:!,:$4<"_*S#Q61GN59KH>;2B;;'/#-?;1\D@^NIRC*X=M.O6Y`HZN1X7&70!40F>H%W]FH;XU+Y-_]64;R7H^Y;6N-_R&_?;"17E6RE. +MOI7AY%L13KY=DZ)<-C%9/$,IRI"))J\HI9A&;K!OV0WVK6"#?3NYHHR6E&M2 +ME#$F/)7`.>H<91[J$7TN?XXRESB>SVFG@G+^J:!\PG.4N=21=RYSY)V+''GG +M:SI'N71BLGB&4)1A$TU:44W[NN$BO(JQO(IR\KDE1+IV8+)XA%&78 +M1)-6E'),(S;8*[O!7@4;['5R11DQ*=>C*.-,>"J!WQ]."$59;!TD?\MIRM*W +M<,FF;S4N=.,NUX'7N/6EE.5D$QH11P*(90E&&331I +M12G'-&*#K?*'TV`;#Q(-MO$UG:*,F)3K491Q)CR$P.<\.QP?+0*R_M%[NC:3 +MH*.T]H`B9[O7T1[;Q!#>4@=1IP-+F1;%#HFC;JH(^C11C!$UDV<(IL(MDBJT +M&N<()DZ5`[I#NY#09J`88-FOF,IHFX!0$: +M;=4$Z#PK[5$4J_JV,&[52_6=+2TT\%;(3'23!$!CRIR,0)CPIR`5[%% +MK814QQQE0JUD`-SKI8,BO=T<"_+64$9G!`"#./6#WXD%(ZJTTZ!CI7&!(DNWW]&6T,81WA6&H:?S09T:R1!)"66Z"%"TL8R1%',D"JK> +M+2(BO(KG2`E>S0.XWZTG%/VJ!9;^JJV,L@B,''&JC'`2#D*@M]DAMWTUH/K- +M>_;44Z!SIW*`HDZSS]'V4<3HIL2P0Q)B7::"$;4\8N1#].F!J*F +M+9HBK*KFZ`EZ70/0WJP@%.S=]EBL=Y8R*B(0-L2I'OQ/,#!A-KO#^V\[ +M7=';*`SB*)-B@J?SA">0.@IW'U%BC&PHIM5A@D6?-L>>@AHM%%CF*%&/%CU+ +M9!:%*&/B)6"FL.6,$%6@_4=-`%0CT@U)'4EW(:A]XD!4Q/HH^$1%$N^4G@]7 +MMXJJ-@N)>?7$1)A7^:)2KQD)M.?5L29UO?XZB>"JFS[/`QU9;4AHT*I7(')H +M+9%G--JX%5:PO!%262+$P36P)AT(+:PS932QSHFXWHH%8-'KK@@2%TG$\S[? +MG//M<;?-=ILD3=]<;"_=<1B%Q$KCI$6X:?),I:AYE-#N:EPC4J\=7VT10-K" +M)NF/#D]+*&DH-:YJY%CU.Y,EB.E6E%$R4TAM3DY-7$,W)QRAO=L<,9J]S:6X +M9ET[DJ/7NBLN%#CQT]/^N'G8C4KB9IM`:-Y.B8ONQA&!U-T8`"*@C2^VYP\7 +MADM&=M;N5Q;4JUHW4E +MU8.D6@N>23$KK9`3%$NX0S)Z-[VR55",*Z!Q+$])"@&::N0+P`6RS/:+09E6-A\X8OQN2(`^YD6CK@ +M&EG/E-;'>DXD=5A4`(M9@\62N!0B;NY^\]G^>)_NQB]_&@V"8Z0Z63E6*EY9 +MU-1&A^JDZIK0>ZIQ9>4@V`N3E"\F&/70,1"IKMX:4.E5MG+)!U2%L;!/4BE. +M03]"$]:2BMJ.>TZXC;GG;AIMN2*LKD.#KJ,0:,1^MW'>J&?8/$!6-Q.5Y'3M +MDTGI=F3(GM^L!:?C#]93$J-*>&0\L1':A8P%T&;%U@%/+_*31S>P&@V?;[)* +M5)9PI.;;IA&]]2HN^(U7<3:5_HP>G&O1G3$G/HW([P^G7X/59KEQ@"RN)BG) +MX=(CD\+UJ)!=O%H#3@_OK:(D*-NP2/AA0[()%0N1U2JM`X\+9R2'8&!%&3;# +M9-6D',5(#;5.''H[;1WPFVGK:BH-&2T:UZ(=8TQT$G&+IO@Z$H4:/0%0"+T8W93M%`I6FT< +M'IGK20I"N?+((W(S*EQ?K]>`T=3[JR@(S"XL$GZXJ&Q#Q>%DO4JK0.32&C'*!.=1ER,9`R4MN*" +M48"TI.;,[LW3B44A((KP4`*'*Q**2Z8B@UE@D1@RM60EHA2W2'V3VS;ENN;4 +MZC!*%JY%&<:6X"3")I@SB4F@1^&)^)G$1.`8/"&=MTG8YVWZJR@(Q$3H<#D1 +M.5Q.)`Z7DQ6=25PZ(SD$@XK$P!DF*A,%*4;IHPGW!$LB=X(EF?I,8KQH7(E> +MC#+1:<1]G\(E8[%M@+0MIRB)VL(AD[35F)#-N8P_IS?K"RA)Q"8D`F[8/*S# +MQ,)AN3[K8.&2J*0L%J?57!PT51D,`NJ"H.FEJ@J%.,6I6G6&4-NFJT]NVFVGB92A7&R<"6J +M,+H$)Q'VE*6/V?8)*@R;S<.C;#M1022L@XG&Q7;!6@]",_>72#2L@(^"8J)(4)1^FV71J1&Z[J@MUS56<3ZD;NI"@*Y=K'F;2(6N +M@Z,K4:+1%P")T-?W4!UZVS(\)A?3$V3QS1V/PN5X<(V\B#NCA6O+)LC&.A1L +M)UP>5N'AD+!8DU40<*'D(W,)JAF#)9.H3A1A$Z4UECE";HJU-;L=UGXF4H)Q +MT6XEBB^:A(83]+S/-P]I]K3-1V6=LED@Y%0GQH6FXHM`3&TD@&ZJQAK;2HWK +MQ,5:;_H\#R2@Z2%!TTQ=@7A!MEB>T6@S*M;"Y@U?ILD1!]S/M'3`-;.>*:V3 +M]9Q(ZK*H`!:S%HLE<2E$W/R#Z[4U_6V#(V,]13DX5@Y9A&S&A&J8=?SI7;._ +M@'*$ZT(BX(;)NC9,#.#5Z[,&YBV;B@QF`:56XOI"7+UYHY'U7(\N`9LR2J(MU#RD;D$U7W!DDE4\XFPB=(.RQPA-\/:FMT* +M:S\3*;VX:+<2A1=-0I,(>O=N<]P^C3_68=@\/)*V$Q6$:>.31]1N9+BNVZX% +MH_4.UU,0AVIX9#QQP:B$C$/'=L56`4@_\I-'-ZA(C(!OHG)1F'"4/MNE$;G9 +MJB[8'5=U-I&.C!^<*]&642<^BB$*-+<#)A-\?]VWN,-*P,PB1M/5EAV%9>^<1M1H?O +MT?6:,!MU?V6%8=F%2:O#I2[9RR8<1F!&P3UQJ"M./VI.; +MI&(UYLZ)2'?NW$VH0=>!U17ITN@+@43LPSG][[_YS2^A2K79/#Q6MQ,5Y'3C +MDT?I;F2XGM^N!:/C#]=3$*-J>&0\<1&JA(P#T';%5@%//_*31S>H&HV`;Z)* +M5)APE.;;I1&Y]:HNV(U7=3:1_HP?G"O1G5$G/HG(3WFV!]^?66T<'HOK20IR +MN/+(HW`S*EP7K]>`T_E>B_J!*;1-3S*_B;>LIMPR-J-45! +MH)8.>42MQX1KO%7\&9VWMX""!&Q#(N"&R\`F3!P(5NNS"@8NFHH,9D%E8-#4 +M$A6"8MRB=,PZ8\@ML[5G]\S6TT1J,$X6KD011I?@),)>SCE<%E8;AT?8>I*" +M@*T\\@C;C`K7C^LU8#3D_BH*`K$+BX0?+A+;4'&86*_2*I"X=$9R"`85B8$S +M3%0F"E*,TD>;Q"$WTLX!NY-VKB;2BO&B<25Z,-*Y$,T:9Z"3B/AXO"-%8;QT><9MI +M"@*W=LDC;CLN7)MNUH'1IP=+*)R>(95$(& +M3S11$2G*-$IW;?.'W%X5#^S^JOB:2$G&3 +MV<2]$CKUE=FFKU.)QZL(#Z\",+SR27A=C6!<+@?IE(**Q(`Y)2H/A4A%Z9-7 +M7I.\2G7(Z[1Z,#[XK40#1I78)**6']V&\;3\MG5P/"TG*$C3YA/S]*2K1H3K +MN?7'Y,D]5U\[0?0UX>![X:*O#A$'?>7*K`)\R^4@G5)0W1VS,V>VQ<321[HL/?BO1?5$E-HZHZ2D_I,>S4_0UVP5$TG9J$A!MG!$) +MVHT%V&3;>%,Z['"Q)"BGAH#I@LPW)2PDN+7K$#?7EDHW(GN<4BYD^LB(."G^ +MH+I'O +MWO+0,!4\!8=.0/0S[=O8!@WQ=+>_L47`4\D\1:(ID$+&:0/H8XAK3,R9/VV0 +M+.BII+!I0%%%G=YN[5P\%R)JF_E;>LLDZ+?A37=X4ZAAN.8_20?A!G^`&]?8GH1UNFJ;,< +M((^T#.%`'&<-8A\3E7Q(,!)?+&>+PB<,YTR1+&,`!]G#/(`>8ILLL0?8)A\R +MYXZ*7!:@;R""8P<<2J3F1=QQE\$&Z[9%Q)&5: +MC2AQY4/644DT>C-W^"SBW\XM2R/P_;#$0VR+,>V.V(G.$D6,MTCU6)2)#+V? +MTRS:3%MX2TCC='AW=**(:-Z_\W9=1&\<7P[>'9EH2)F,"7=EXK!DC'%,-%HJ +MB="<&+GS.TQ2<._^YK,">`,NO,W8K"@WXX#] +M/]A$4H].BI\'PW_:'HZ])80QV]`_C"VP#(PM#)(9QR@QS#$E,88!291COZ/BR6$H1&&)2 +M',%3A*Q$1#GB:C"&E0]3S8/V7Y_ +M=]Y5[\7YU=ZDEJS;^LT[^Q2)U+,ZA--O9$SVUF>//[`%`A:02++1D`BXP9!M +M+$Q0PMG7)SK.>9>*#&:9U%ETU"*KM4FYY6J.(QD#:I*C]JAF.>I)0-6MAX41 +MJKY5)#B>L,>'\V<@25AN&!A9J\E)0;7TQB!J/1I$[ZUB3FV\O163@EX;!JX/ +M%NZ:T)!95ZU&_)A;*.NH)`()O7!9)"?Q9&B$[GUUR>*<8]!Z@;4\@W +MI,C?$\6\_L^Z[L^YWK^">Y[F3BD"0\:53J`4$5`\`AR!-Q[BK1S\6SBFNC"9%K8H"3E`@X>J_;$^'S<-^FU^R$;5DV#8$WIFFR**>P2&6?L8QN5J?*?ZH +M%CBZ@"R264(BX`9/-G.8<(0SK4^DG/,H%1G,LJNSB*C%5&L3<0O6'(T9@VB2 +M%GM"L[1X$E-U:V!AM*HO\@3'$?8^V6^SS3[+TLRI"M5M`^*K-D4)NJH.B735 +MQP1LQ5K\*:W8O(`2).R'1,`-F82],)%(J*U/W!ST(149S'*JPABH):,*I;F% +M:IIZQN";9M^>WC3[GJ158=0LC%T5QIK@2,(^[9+#T7V>L-DN)*XV4Q,A:NV, +M2M-V+-"VV\2;U'('BR5".R4$3!=TRG5AH1&N68?(V;90NA'9XU9V`=-'2-$) +M\0?7Z-JL(#0YQ9;1X!0OXNHM)IY%K]8B26`D(;-WISQUB[-JLY#H6$],!(V5 +M+RH9FY%`.V4=:U*C[*^3",:ZZ?,\T"'6AH3&L'H%(@?8$GE&HXU;C@7+&R$Q +M)D(<7"=KTH'0R#I31A_KG(CKL%@`%KT&BR!Q<41\W.>[;>X^.]9L%Q`1VZE) +M`+%Q1B1B-Q9@F.P\62H)@:`J8+,L>4L)!`UJY#W!Q;*MV([''*L9#I +M(R/(I/B#ZFQ=5N!;FVI+[VVJ%VE5%A7/8E=FL20PCI!/V_S^U29]>]R[[VA3 +MMPV(D]H4)4BI.B324A\3L(5J\:>T4?,"2I"N'Q(!-V3B]<)$HIZV/G%SSX=4 +M9##+J>QBH):,PI/F%JI1ZAF#;Y9]>WK#['N25GU1LS!V%1AK@E,(>]KFKX"B +ML-PT.+I6$Y1#:^F/1=9Z1*@N7,6>WH1[:R>'P#8&@^^%B;XF1`ST52NS!O`M +MF(-T2@%U7\BZ4;FM:-@GFZ:%@.R$33PL/"7C*FL1- +MNV63C\PEI]`+G4PR,D^23:A>J.8(OA7JUO1.J/N15GA1TBYV=1=;0N,(FNVW +MN\U]DIYO/[X]W+O/ZPT,`J+I<+(22!UX)9+5,#I@_QVN":4-CZRL!!R-89+R +M14:E*70D8@Y7+VYL>IBM7/(Y)61<[),1E-/1#]6-#4F%;\I&)_3>;'0GK3E7 +MA]78]>B:"H%'[$UZVA\W#SNT9FT-`^9W-_DI*-YZ%Z*Y,EJB2NC63$(M&#)@ +M"AAK893V*09G-;0BD.Y6>UVH]CC+I4B+ULAQL78:S3P=;5G204E&OH30G,E) +M"+.LS#[QUM(";L'\T^9+M(-W*>IFG7 +M4E#9#/-C0NRKX9W&LW0+4$(NV0C:C%AE,PBC'F3I357]$?)[TB.`B0DN(6*Z +MM!63,JI+<4&C.I_I^.!OC6*8>.MN%7\K/-+QQ-,ER0^G9+_9;?/MILK,,^Q8 +MPFP:6A^R!$"L`YG]<[J/;<08K619.[).*Z\%6$-,Q[]EY5<` +M_I!R7H["L&."J#DL>"PP&XGQ4L26FD098G?'E"!VQY/H_K_!WI177[MWVVV3^=\G&3]7GGA,#M"MGV+5]>%4-ML0T6%9K\P*`+ED#M(I!5.C07-*4'F*D0K?/)M4 +M(;;,SIS9*#M'D^C(&.&W"GT866(3B'K>Y\6]R?E-0::G_)`>81IP:!8:9PT3 +M%R/NT#>'OJ:18OJU8:W(O7MLW<5P:@Z?K$<>9HTAI2/7L,(K@*_O>2U#4YA6 +MC9*G@AIV!7#=#RD3U_H*KP76'N>U +M#$T1^CHVGDKKZRF)2I0)O?3CR(2!*PF9,'`ZG;Y>.;#7HZ_76SC$CH`5U@%W +M@$FDM!#QR2)#1%U,*Y<%L2O&6RG0KDP2>Y*F3-;!96\$M!,6NL*\HW5HB=8L +MVY/G4+%KX.AJE&KD!<`B-/"];*I!N(26?`>;ZE6&T-AW3VEK(M#L)WFW6C], +M4KZD<,I\H8ZV>JO"J0_9RB4?5IP&SKY)Y*D@_3C]F?$"IKX3L0X]X5O,UH35 +ME>G4J`N!0NS+Z91F.5"GUAL'Q^EFDG*$KCVRZ-R."M7IFS6@=_G!*LJ!4PF+ +MA!\F,+M0,6#9K-(:,+EX1G((!M2;H3-,4F=*4HS05MO$H;94Q0&WG2JNIM&4 +M$:-Q'1HRSD3'$;=0G?LL2S.G8.RV#(BTRO0D(-NY(Q)6'0^P)2MQI_1CT[)) +M,%`/!=L)F7Y:>$CH4]8D;NHMFWQD+CEE8.ADDA&`DFQ"=40U1_#M4+>F]T+= +MC[3BBY)VL:N\V!(:2=`\.QP?W;*NVBPD@T6CC%FO!\D9(IHD0!]?/FG0@-+/.E-') +M.B?BNBP6@$6OQ2)(7`H1-_?I\:=]=H8\R3*T"(Z2VG3E<*FZ99%3'Q^JG6KK +M0N^LYN658V$_5&+.F(3LA8\!2VT-UT!-WY*6S4&@2(R'A)+2<1H6$OJRGEO4 +M%MWWPNW6?7_3*,Z5478=ZG0]!8$C^-OLD.]-+XER4-QF%Q#+K5.7X+G-.9'J +M]K$")8-UO2C"P;WX$C0>"Z&P2S*91\)*XK-UG>-F="CI+<16IT:.F:XR>GDN +MOJ*D@CT+\8)AS!==-HQYE5;3?^/WBMXU^K<"8JIOU`M';79A]@?Y5X[:G/.[ +M`^WEC-;U8LJ3"5\[.A9"89<2]!9YD9UUG5?#;J_36XBM&/4='5W%U?>D?*6* +M!_:K%,=\B8B'R=]"^C=^K^A-I'\K()[Z1LOND#O"-$);J@/0M8>,Z)A83$M2 +M6`Z_8MQ=FV#V)ENYY$.(XAC8)RV#I>E'[-LB#5NX4\^B<5>"U?7HV/@+@4=L +M]\M*AQ8!$UOH=:5#MT+$1KP"TK`N$AI`^I6EYE").1.C*_WU>H8U7!==_4A: +M-@?1TC5T$DXC7B59R.K:M-UIWF"Z2LJN3<7&7A`P@M]M=YN'G56V +MUC\'0.9F(AP(USZ0Q&WW[.C:32PQ+7H0?P[>E.G1+-'@ZJ:,HE03T3B!-$N^ +MX*K?*M;"JW^>#.,1`-1/VF6%-P_%!-\I%&,IG10<2&+5-B$E'HQ(1S1\^J%`(4B/ +M>IP86BBS*$2Q*IVPF<)3/7)4`36B7@+`V]'`$-^4!BZD-%$TB(I5*\60J"CB +MW9\.J4M"E=N$0[MJ2@*H*QW12%>/`=;DJO@2>EQO803(U$Z984[E4A,&"I:J +M>$?-I%E3BL`0EV@*DB(BDHG-$4P?JE<>W89:.W(7:CT(JZ6PF12Y4@HV05&$ +M>\RW]B^QJ-N$P[=J2@)T*QW1Z%:/`=;2JO@26EIO802(U$Z984XE4A,&"I&J +M>$?-HUE3BL`0ETH*DB(B*HG-$4P3JE<>W81:.W(3:CT(JZ2PF12Y2@HV07&$ +M>W\X.552L4U`?"NG)$&WPA&1;M48@"VMC"^EI>D+(T&D9LH,S9E2!(8X55*(%)%125R.H)I0M?+X)M38T9M0XT%:)07-I-A54J@)BB)< +M`E!)25A\2Z144D*G6X)I:0FUI27B*BGA$2GA$"EA$"F)7R7-FE($AKA44I`4 +M$5%);(Y@FE!";$()NPDE$ZFDL)D4N4H*-D&1A'O:NE72;9N0^%9,281N-T=4 +MNI5C@+:T(KZDEJ8MC`B1ZBDSS.E$JL)`(U(1[\AY-&-*$1CB5DD!4D1()3$Y +M@FM"Y!<4AK646`J=2XII1\#II@# +M_Y1ZX)^*GTM*><=M*>>X+64*B> +ML@_5TXG.)87,I.A54J`)BB+)9**3<*A6SDA`;05?FADJT8`ZV9E;`G- +M3%\3`10UTZ5;4T%4AX#"H3+244-HOES"4\,EBP+DAH@H8I(#TW&J)4U&CT,5NYY',IN\C8)Z+Z)J0?IO&: +MD@K=ALU.R$W9[$Y8.ZX/JY%KSE45`HK8YS399H?S)M]FF^U]XE*J_/;UU,`HZ;PR'BB(M00,@I`!RL6-3S]RD\>W5QJ +M-"*^B2C1B0B':;[#-$*W7I,+%T>&-RRO(TEZHQ)QQB:J'CP-5=0U7057/ +MDI;-0:@XC8:$HA)U$A92^K666^26W?/"[MH]?Q,IUG51=B7J=34%@2)X(8-? +M;;-=>A%5DW"R,7"U& +MF^`HPEXNN_U]NG.>U6RW"X>KW=0$B-HZH]%4&0NL[7;Q)K1Y68M]137U(O_MD#WAO&.2\89[Q?//Y/'LR7 +M2WAJN(1/@-P0D3Y,;M]DA +MMU^+4[<)@&C:E#A`4QTAB::/P='`M/AB.IAY83@DZD^988YF42\,*!AI\8Z3 +M14ND%($A5ED4,D5XPDB*(Z`.I*\\O`7U[?`]J.]!2AU%P:18%5+H"0HDW#'/ +MWMGU4?EK"$RKIL%B6>D"2[%ZOZZF5<41U:YZH6=QIIT:R1#/EF:Z.*I4L8R4 +M)I,G"JK>[5HFL(IGZA=&S<-:0KV>B&;06A#:0&LKIE!"(D>T2B20A$,0:'/. +MLZ>QNZ3UK4+A43.`-)PNSNC&8U@B-F^TJ;,&-2\@#9H#1+8J/2?(@JI%B(%;6"BB!A@02\ +MYML\SS8/V7Y_=][9-59ONQ`8V)\:BX$]9U@*#L;B:H7]>*.:H76Q6/0RA(#I +M`D^P85AP#.NO0Z0,6SC=B.RQZZ\(Z,/48,+\@;6U058@&IO!EM#:#%[$U%B, +M/(M6E466P#!"/AR2?)]M[M/+,;=*,VVC`,BH3XH#1IQHFJAS*(0Q2JXPF8*3VK)4074HWH)`&]0`T-\ +M=QJXD-)6T2`J5CT50Z("B7=Y;W^0O_PQ!+Z5DV!1K?"`I5FU5U<'*V.(ZEQZ +MU%F@::9%L<.#I9XJ#BAE%"/%R+09@JEPNY8)JL:9VH5/OC397LC]NG_69_O$]WA^.C56=8#0+@DGVR +M'%)9O2+I-3(Z1U>RKPFF4P%6E@.MT3!)^4+#;2QT*.#95R].!'J%)'!_'(XVWHLSIG?;EHC#P>'460[0Q!N$`X6Y7NSC +M)-MR"4;BBU4&ADX8GN"39`RHH_7S`-[&AI;XWC7T(:7_?G#YO=@*,=\WK!Q0B(;X(&O-I[X7B;U/*$Z1:(ID3GXYVS:N,;, +MF>G3!LD"A_`)BP820IHQQS*29*XG0 +MG'!HF?!((:%G>*Q`M)1JK;%-I;&BMI7&7E;9!$J=N!5.>`F))%AQ"Y);[91; +MA<2Q:EHB)"M=46E6CP/:N*HXDYI7;XE$>-1.G>6`SJ4F'#0V5;&/G$ZS)QB) +M+VZ5%"AAA-22`&-P3:K.`T*C:BT9S:KU(:Z@8B!6](HJ\(2%$?"TO2(>)#1O +M'0`/+=/D4-'L$DE'V[@-5PH_EG6*DX*^I>8 +M+)Y9E5UL1.,IO2F9!FJDMOR!-U2[!WQCM?N24H2K(F6LBG$M"0\C<+;?[C:[ +M;;[=)-OLT7[6KK]=`,P=3(W#VKXS)&6'8W&TYD&\,4W9OE@<^IE"P'2!)IXA +M+"C6#=8A3L8MG6Y$]EAU7PSTX6D]:?Z`VMTP*^"-SF2+;W$F+U)J+DJ>Q:K: +M8DM@#"$/YS<.759L$0P3R^GP65BX(5&PVC^H(99QQ;="?3GXC&JF2C8F +M/H%(98QC)M'_W][9-[=Q'.O^_FM^B@T/*WJ)2%J6%5?(4FX467%4L667).?F +MQ+(A$%Q".,);@*4(R?+Y['=>=V=V%\1,=Z^`F9$KL4EPIC'3W?M['NPN@(_5 +M1-ZR4#AQ?19#?`'ZQF$VN?U?J^AE!J4!CNS3XKX<%D[^Y/F>[ +MT:@+S&FL+R\-B]M2118,0>"6]`'AVZAA[-3=Q:9%<]#!%,=%0BHKW!T+/76\ +MV5L0"6^+@E'OMGCTCC=!RL;O;M,Z(#P(GJ^8$QZL_YYS:U`HE"XWA<:RC@0A +M<;4*%TTO<^PMX\WJH$%H;ALS'X8[(Q7^A"NS'C'2/GYG08ARO0T,EBD$9H^$ +M*NX*5C6`IVB9$X$Z988@]6HQ("IJWQ5XHWH0CWNOWG0VS5>C99%/-YBIQNA0 +M"-C<)AJ$C9`0(K:LRT46FW7PUL=K2HGF6VMJ2`+!B->6+G_T-6L5,0%WJC%1 +M/+O>RD5$-`)SUQ'3W%6TI7\\Y;0U`E!76V.1.L%42!FU6TR@X?T(7.2+WG#Q +M?C3?Z":KD0%QU]@>!7&K<$#:FNMQ%&DC[Q"!;BL;!0OM5*"#@!EHI0?$/Z,F +M<9-ON\T'YM)&5Q@ZF6C<("6;O$31[!%_0;1GP\70CD/M_**D7>Q.+[:&]B?H +MV-G9C4/DYYC6V8VQ]!S[B^L8)Z[ULE&Q;DS!NC&>=6,TZ\:I.+OM-1^82T[. +M+F0RT3D[*C9Y"^$8)81C(B$<=^KLHJ-="LXNIH8&$/3]S-'8\8&AT5-LC@R= +M/!J&G'(U/KHJ<@Z65;MB9)#3:<#&P"%.I09..%&-!/"VG:Z#DLC-R@7+(D(C +M1T(C?]63S0$4/3T9J7DZ3"<>+B:\)>'?(FED&#%[D\MQ,9J/\]Z\OR@V?&#. +M-?,"I&ECZY1HK0='DK:Y5D]!;M0+H\_KBT])T;84$H=$,[8EK2CD-NJ7BPV?L[AV5IC,-;=-S%XC-)["UCK]Q=NL$U+&6TM.S--:ZD@# +M4C#63B>6MF9MDZ'NCC8T"3]]O&I4!"7WKYTQ%"KY5M^AQ+\6B<0&U&)VZ'C3 +M)71"SCC)`\9?`2XOS_/![-S-.)>#`Z-]M4DJQ)<1$60W5N7A(:H:0*U#2Q6I +M`&NEA2(."J=FJL`4K:H4/SIWH",Q!'.RKN$SC,ZHTE+,6V6-QH&)JQ4`IZE6 +MJ"Z\9]1H3,%7QMKH/L2=+2;]HO?5YK>G&P.#X:RY.3QAC6@@NEJK<5)C,^?^ +M2MQ:,3S\:FG`Q@!"STX-`'AF-6)&W5:[#DJB#;XO=!91^#U*&GG(G]4`7BA]A'[S,8;9S<69B\H7-F>.)XBYEH!YB4J:DX +M(5-!NO!C40`L!1\6>N/Z$W'0/W,R8'Q<8$046Z,"(@^&(*)!(SS5]I +MC?X!RJP5`:FQ5JQ.G&;LI$S"74;<\$`"GXVF[H:2#PZ1OF*3I.CE$;'DE:OR +MU6Q1`Y1DVU4D!:1."T48=8T5C,KXQPD:'$[?W;R_7R(8'RER^46KFLI@$U!4K`V@U +MKP56K:UZ4F-2I866^]/'-V\'&78?*-WE72$`PNN:".< +MY*H0-**K@G7I+Z,&9TH^,];&1Q#YS/$&36-\J$0^H[P]TPA*0>0SW]O=S'J@ +M5?VLDULS:RDB"D7#SS/D#41FW1+BYPZT*9)U?O8S<-IU8$`)>0=7XC/$36BU +M&$1:?-;AO9BI<#0I)QKQ`8`A]/LO/.THFQ`LH?EFZ0'-HI(06JP.I/6\)GBQ +MMRI+#U.5)JI81#B5J2/@*:]>2CC=B6[%DL_3G(;.OB[L*27]$/HLF@HKT"H( +ME4*K<-UZU`2PFI9/C?M`0!![^-[/JK+QH=*:;Y40?78]%-2#E6,8C4 +M6$7KU)7&SM&D'&G$!P""T&/7+Y.Q9X3*Z#'IU\O882DH/?;^ZH]:7="2/^[F +M*VB:J2(+1L/5,?;K&VHU3(BL.].T:`[Z>=4(2-B!7R5F(5RRQYBO"VE&(9+M +M<9??A),<99-RL`D<$"B"3_J^3I;-")???+L=T)N%I:&W6!_,%/"Z$)@"J[P= +M,%:EBBP8%6-E^B@8RVN8%&%WI&G1'/1ULL&3L!,G2\I"C'"+WD(+MXI")MPJ +M7L=.-@W*)N9DHS\@$`1?>=XAL`KWFMFJBSL$5C17S%;02Z\KBDNOJT[O$%C1 +M7=E:45W96A%=V5JE=8?`#K0IDG5^7C5PVG7@4PEY!Y?D%<$%TA7I!=+51[A# +M(':.)N5*(SX`@(3V^S(F:T:(C.[@ZYBLL%A*`[_BQJX+2O*[_$JF1JK(@N&Y +M2O/U(78-$R'K3C4MFH/N7C42$A+[U0Y8")-L_-?2-*(0R';WW]"4&F63<;") +M'!!`@L_.!^XFE@\.D=IBDZ2XYA&QI):K\M5^40.4[-M5)`6H3@M%'#PV5:IP +MQ!152@25V^U(#,'<[6?0#",VG604@RFK;!R$J.H`!'JJ0W7F+6-%8S(^,L)& +M!Q)W^7;Q9>_L_6C^16\QG[C;Q]J\$"EQMIA6'X7J=$^'QCK8-&EV(L`DML0@< +M0TO4SESR)WXGY*@3/X`P"C'T^GB":DJPJC"D_X""*BZ)$@QA[_8V:H,W(+4: +MTZ.Y3!==-"(@ZQ02L'B8T@<5[%KOXJGH:9ECX&(71IF:C`AU'Z+?H&V'H=+T +M,F"W?C@AZ*;E?=,X,+!$!YQD+J<%S?6N3C&7L@8-0A`'_!E\?)1@$^@WBY6;)V3\@^`[Q:G40IS%`?Q-]L[+D$!X0?>FW +MCD4#W@'%%W^7U4L(M;O1K5CR^;G@X-G7@?,EI1]'59PN +M'&%TM$O!]<74T/X$'1;]A=\G:=DS`N-I;;M45+7#(NA:7Y^'"-?J`A7C=>6E +M8F0S563!4,QLI`_,SEH-XR?H[C4MFH-.CC(F$M(YS*Y8Z"W0]=Z""74S"DZP +MF_&Z<*+)438%IYK2`0$D^-#MVPGTV!"9/23\5@(=$$MIWR^"+_./$OQA%]]" +M8*:$(`R>ELCOU"[KDP@?M]B*"&:Y^\V`J47L,8FX!9-1Q%>NF_,)I'/8W3<) +M1,O"9-QB9`T.)*SSMZ]6HT-D+.VWKE8AL93U_^)*HPXH6>[H6U;MU)`$PK,1 +M_9U_1JT2H>/6&Q/%,W?/&#C1B'TC(=-@THKZ@D@[`H&\=OI-J=&3,ADG&6G# +M`PF\G/<72X_KY6I\B`S66R5EL`J*I7"Y-E\)U_5`B7BCJ*34-%)$%`I/SBIM +M.';JNB7"SAUI4R3KW/UF!+0C]IS$O(/)<-E-""$V8A!(L1&M,_>9`D>3<:&1 +M'P#^A!XM9XYO'YCR$7.4=*N'ULE&QL4H%.@B*AV5Z +MP"14-8F?@-MK/C"7G#QCR&2B\XE4;/*61MTC,%&L9N/DL(K3A1.,CG8I.+Z8 +M&AI&T,GEN!CU\E613PMGDV=-"I"J]J8I\6I%1I*VMDI/3;9KA)'G-=6F!&=EDD9R*[TWQ0($1?S5;+-A_G>VQ'A\@YF?OOW#UH\:,\!AM;I>0T498'*6M]?D) +MOED7A.2WEI>0J;54D07#-1H2DOK53E@(D6RK +MM\"B78N"ENU:O(Z<:UJ43<3!)G-`8`@^GDV'GE963`F6X'+#]``7<4D(KE8( +M<@:R-GAK4*LQ/6K+=-%%(X*M3B$!;64E4X+M#O4NGHJ>QC8&+G9A;:G)B-!R +MU6)8,2_#4*EY&;!;?YL0=-/RN&D<&!BB+Q:>+I=-");E?+/T'&=122@N5@=R +M"+PF>']@598>LBI-5+&(`"M31X!77KV4T+H3W8HEGZ>3#9U]7;A82OHAA%HT +M%5:F51`JD5;ANO6N"6`U+<\:]X&`(?;;?+$8%2V]CZ_0(KX*3 +MD-Q<*\@@&/7"^X2VXM-3V$XA<4@B)EMI)4"S4>>4^+R[[4W$5D]3'!==N[#( +MW?$5X1/,+L3:!3L6E6NPHW;KHA/G=UH..]T#"*00BX7/?;UJ='A:H+=)R'\5 +M$D?].;JD:0Y"VW2PM?'19- +MX&I]WM)=U@6GW\WRTK+33!59,`**&NE#HK2L82HTW:6F17/0PW[&04)J(TK/ +M0J!25[V%D6LS"H5FF_&Z_?]BZ7/&UI@1'LW- +M[1*BW`B+([FU/C^;8-8%X1):RTO(VEJJR()A26NG#P-:LX9)4';'FA;-05=C +M&PT)26UM)RR$:+?56V#IKD5!*W.-BW*)N)FDSD@_`D^?MUW\J]\7&"L +M%ENCXC,/AJ"R7(N'Q(M\0X7=+A85'74*D"%0)%1I`?-/U"%^YFVCW8#LI6 +M+/E<36(D[".UC1W0#Z+#9E.!!=D.@E9F.UQ''C,=K";B0Y,X$/R)/2D6N9M) +ME2,#([3:'A6893@$D?5Z/*1=Y1VJZ?6R43&R2@4Z"(J*97K`.%0UB9^"VVL^ +M,)><+&3(9*(SC51L\E9'W2,P6:QFX_2PBM.%(XR.=BFXOI@:VI^@\_[*^3Y' +M/38PAI9;I&*H#HB@:+4F#YDM\P\5VF8!J'H>.4KEU<8N;SJQ)U=X6EVA:79%9)F5VFXLX_?;D#V.+JS,.E#Z<[P +M_`&(VQ5"W*Y(Q.VJ0W<6"<_2<&?A-[`_(0O'*]>"\IS9P7NM6OA>S*C +MP)S,*#HY=U;@7VL6V->:!?*U9I'&N;-MM!N0/4[N+%3ZT+DS"OYXBUN!./50 +MD)QZ*#H\=Q8-SU)P9S$T,(B0O7PR+][YO?>V95IX]&QLG!"E]=@XLC97ZJ>\ +MC5HAA'A]W0FQV98^VHA8J+:D%,/81H63`.YN]S4-35WM9X0\)36G'1,5HOS- +M]@,;@;90:%_0%K0CG_L)V(EXY*0/')@B>#OKD#6@&S=-17VXTZ#Q&!V[9DK\ +MTH&7#+FIN>,=ZE8L^9Q=M8I%14:4`&0+'0)D6./IX'1+@ +MW1;:#<@>-Y,8*'T(+2$!?_QU3W0%4.[47*3*J2B=N+Q8>):$@XN@@0&$'#JZ +MLV%X?!Q2NK,ACHY#7[D<8N1RV(D[&^)I-L32;(BDV3`-=[:%=@.RQ\V=!4H? +M0G=&P!]_<1LBQ&U((F[##MU9+#Q+PIU%T,``0HX=W=DX/#Z.*=W9&$?'L:]< +MCC%R.>[$G8WQ-!MC:39&TFR/FS@*E#Z$[(^"/O[B-$>(V)A&W +M<8?N+!:>)>'.(FA@`"%7CNYL%1X?5Y3N;(6CX\I7+E<8N5QUXLY6>)JML#1; +M(6FV2L.=;:'=@.QQ!TH?0G1'PQU_<5@AQ6Y&(VZI#=Q8+SY)P9Q$T,("0 +MCN8L/#I26C,<&7V5$B.4G=@R/,6P$$,R+`U+]K'[#$8;-SL6)&\(S1B:./Y* +MAA`R$AWKT(?%`+`D/%C@C>M/Q,NE][M4:U,"XV1]PU3$K,5%T+.Q0@]-K=<& +MJJ]K:TR%Q)9TT45#H;*90C`VZY6,'Z`[V;MX*CIYQKBX2.$K`+'YHD=%/PK:D=&/Y$7SE^$O4JO,^"75%^$O4*]TFP*]^/!EYA +M/AIXUAOM!F2/DX4,E3YT9I&"/][JMT)\ +MD.^*Y(-\5QU^$G4T/$O!R<70P/Z$?#^:.[DS/BXP/HJM4=&1!T/04:[%0RY% +MOJ%R:1>+BF8Z!<@0*)JIM(!I)NH0/\NVT6Y`]CBYLU#I0^?.*/CC+6ZR*V#B +MIN?BQ$U'Z<*=1<.S%-Q9#`T,(J3?%6)K0GC$[.#JL!451U#@U36[)@B1[?*J +M<"--5+&P>*2Y-&%7+PE<[E*W8LGG:A(C81^I;>R`?A`=QE_B:@1!*W/WUWV3 +MPFHB/C2)`\&#V./^8KC!G&)H>[,.F2>TI1-0TH/E4`4M\5 +M,H2B]D^!-J8'T>;]5:]87$X'_2(_O]X/V4-#X5MM@VC*V?$@M*NOR$7C:KGW +MUKIUM4.CJYD.?!08RAHI\D=:K3(1@VT7>A!.J>O]5Q2<(O!CY*1RE\%ZJWC* +M87,Z4!:;@4A]6\SPB]K71=K8/D2=+4?%:#;=8/GTJ&`H6FX+CT\="D3.:AU. +MTEKFV5]5FR7"<\W<.BH`D&9&.@`@*W,?,\&VT6`@OFPP:^$2AL*BT3#&0[^J +M/O"5+G,F5+7,&+1.+!)BQ>VZPF]8#P(ZGE4+[Y4JY=DTW.M3WS,8F+,7G9P] +MP[]XQ+YP1+YH3.-LV;;Z#$:;ZPU7T+PAL%QDQ''7,,0)`Y*3!1V>`8L)8%%[ +MKT@:%T)$?I]8D6_X/(_&Z.#H6&Z3#I$Z)(J4U;J\I+.L`UQ!FZ6DXYV9&I)` +M2/H9Z4)`L*Q5"B3 +M4QT,Z!K;QLSWQEH]%5XTL[,>)\*VU%D0HJRUY5H398\*@'BU;6&`9X?R)%Y]'1ODKI9G +M'[U;5R(,IYI;1P7P)E4C'5ZHJN4^3E)MK\%`?%EKJ4(G#,Y443+&2:WJ?>`N +M5\V9_GK5C$'EK*(B5JSN*I:&=2?@]1]L48T(A'L$'VM1A0'0SO&#"(R\^@H= +MY4=:V%L%3P:Q"/96N=4DAD@+OCK"LUV`[)GK8>*@3XX/T7-'R^6CY9JT!-88$0&%S0QCL&G$\ +M26NM8(-*F[GU$>;6FF!05]LN?+8WT.P4>#',S'21/C;56+EQNX`P; +M#3F<5,DJN;L0U:;Y:T\M`)7?"AY"L7JGD!O3EVB]B_YH?+FXYKIIV]B@"&=L +MD09T54`P\C/K$S;ONMB&"6@QT+ +MGUI4!HV66Y[*:'8,1"+M^1BMM"/1N[F(61B_XXNSP;T)^[J_.!^/IBZGR:JQ +M8?&UVB(17X"K/,.E-]&V8C89Z0"'03#O2H]4.KIFD1/O"TV +M'YA++KXO:#*1>3XR-OG*8=DC(#$T9J.DT(C3@=.+CW8).+RH&MJ;H/-\,7&Z +M!"P'AD5/M3DB=,IH<'+JU;CKJLHY4%;K%2."7)4&;`P,XLK40`FGJA$]WK;5 +M=5`2N5BY@%E$9N2(:.2K>KHY0*)7349I7A6F`P\7%]X2\&_1-+(W,9?YX'*Q +M_G/>FB/#(J;>'A$P53@X,@IUZ/A[BJO$/%M5XV*M95J4`'0;&N3`^8=:HF\9-N +M>\T'YI*3LPN93'3.CHI-WD*H>P0FA-5LG!!6<;IP=M'1+@5G%U-#^Q/TW<3U +M[15Z:&`$U1ND`JB*AR!HN2(/A=6YATILHW94R#/2@8^"@EZ5(C#U=&7BA]Y6 +M>Q!.*2>C%S:GZ*P>':F\M;%L%9@X&M-QZF@$ZL+O10F_%#Q?;(WM3=1B=-U7 +M5#0&AL52M3DBCLIH<(KJU;@KK'XV8H(HVK(R)XUMUL)?::^I)QZ#K>FAB01$ +M8EO*`&!L5BQF..Y8?^+HML$5QL0W"H?8%>$\1+:EC7REMC4$5'!;@]'ZQX3` +M&;>O3*/Q(41^/YI_X>@UQ=#@."PW2$=@$0]%7[4B+^V6N8?K=JUV=&@LTX&/ +M@D2B3A$"A[(R*8!PBST(IY2C9PR94Y1>D8I4`*E4K0*5R7(Z5B++0-WXP@CA +MEX8/C*NQ`43E!5ODRTT7BNNC0Z-JM4TRK)8A,60UUN4CP54=P"K<4DHR'EJI +M(0F$HZ*9+C@8JUHE0,:=:$P4S]Q,8@1$([2*Q$SSUU6C?X#2:D5`JJL5JQ/G +M&#LIDW"1$3<\@,!#9DG=W*08&1IWY?;(B"O"86BKUN,CTC+O8(&NE8V,A64J +MT$%P#-3I@?-/UB0!\FVM^6=C45_XN'QC#DA,M7<,BE;CGJ)U&'$_->B;"U1UL80)&NOO-B"A)[$$[XB1,QJU.0PAZ+0Z!M-.S*$ +M5NG`1\$!LTP1G).J,@G`<9L]"*>4F_T,FE.$9I.,5/[*J5L%*)C5=*1.5H$Z +M\8\QPB\);QA98T.(ZF[[@J0IL>E#DQ0@MTBU[[B:6@002=]5V?'1H;'3[X]0GJR +M<#AZBO7XB2O/.T)$V2(-V6F@_,)5=G%RR92)T= +M"9L@0BAZ!"R$:C9:"%6 +M^9\VF>%.F\PZ.F@3\\9<[ +MT15`H5-SD1*GHG3BYF+A61*N+8(&]B+D;#'I%[VO'-ZQ:XP,AY'F]@@8:82# +M4=):CYMPFGD'2&=KV0C85DL%.@B4;W9Z((0S:Q(UX;;\1;!VFRP#-;B$#NY.&D7N:.+KJ$!!.TOW'P=&Q<:._G6R+C)@F&H +M*=;B(ZD\WV!!M8I%1C>5`F0('-ED6N!]R\6Z#T(?1M!/SQ +MESC1%4"!4W.1\J:B=.+68N%9$BXM@@8&$'(P'\W<_)D8&1HCY?;(&"G"82BI +MUN,CG#+O8.FLE8V,;64JT$%P?-/I@1-.UB0!PFVM^@B:F@@07OY9%Z\<_=W:GR(+-5;)>6I"HJE +M:KDV7^G5]4`)<*.HI%0T4D04"D_(*FTX3NJZ)<+*'6E3).OU@(G\+5ZTN*S3`]-)`)XZI0AV2DKE@HX=Z`_<73SL)^A\XW:?%(2 +M#JB\JHTPPEN&H-#=,EAWOC-R<*;C.>-M?"B19^<^=I./#I+&8INT*.8AT226 +MZ_*6>1C,L(E&;2_IF`;4 +M6-D_&(G5$2@45L?JSEE&3,IT7&6<#0\@\'!Z6;B^ET6-#8V]>HMDW%4!,=0M +MU^0CUSK_8+%N%)",C$9*",+@J%BE"+CE5D0PR\TS!DXM0K](R"U_ +MZ2P[!BB#0"%MND@RP +M.B*&L-6J?/2XK`%8D)M5)`.BF1:*.#@D&JF",[&L4@)(W'Y'8@CF9A*#9QBA +M322EF+^.5HT#%%(S`%))S5"=>,68T9B$7XRTT>'$[9W-9H67<90S`B6OVBXU +M?&58`@+K]0&D6]4%J]_U\E*SLTH563`2BI;I0Z-4U3`=FNY.TZ(YZ&4_8R`A +MO1&E9B%8J75OX>2ZBD*CV56\+AUJ,I1-R;6F<$`@".[Q-G-[2J@$IWZSN1V7 +M@N"0]_+6:H.V!IV]\;R9+KIH-+`E>.=DK9()P7:7>A=/13]C&P47.["VY&2$ +M:SGR[;G-,$1JWO&[U%.$;E(>-Y$#`T'TB]$XG_8G&[^5>LVL4*E>;9L9J +M@V0(E_$PY-8K\G$%*O=@,U"O'1E"JW3@H^"`6:8(SDE5F03@N,T>A%/*S7X& +MS2E"LTE&*G_EU*T"%,QJ.E(GJT"=^,<8X9>$-XRLL:%$[?7/EK/Q)7MTWB]> +M>[C`VL0@65O?/"UW:]'1%&ZLUENYZS7#Z?C:#J"%:TL:J6,2@+>96B2&Z]5. +M!6&B;5!Q\6K0K5"?U]2U@;I2)HU)D:TF2ZZ:!18 +M-E*(!7)9R61`O%N]BZ>BCX..A(ODKKD#,D(%OFHQE+2;84A$W0S8H2]."[H) +M^=]D#@PLT7NCZ7D^=?STL=:90=.]W'XWB-?AR4A?K1=L)\JZT;B*9AMTPV@S +ME>1!"8EMI)<(W&7-4Z/W+C<[&7+K%*J+!X=2C7YV]2=%V0YJ11 +M7F)&&ZDB"T;!Y"I]6!;K&B9#X!UJ6C0'?1QT%"0D=\SD+(0*>ME;*"$WHI`( +MN!&O0R><#F43EDSXJ!=A;4HQE>Z/RR<`]C)ZGH["/58^4 +MP^2&_2.0&.HZFJV),AYMX4B\1UO@#OW[)]B?I_8YRI\.+.QG*\_[*S<7SP>& +MIA5B)B)R#?8==,3+8ZC1@8^!`JE(#QZ:H1@*(W$[704GD +MYF2#91&A2R6AD;]0RN8`RJ*>C!1!':83+QD3WI+P@)$T,H"8R]?]A<_7)QOC +M0Z.GN54RA!I!,22UUN8CM&8]P'K;6E0R&M921!0*QT8[;7!$FG5+@),[U*9( +MUKF9Q$AH1V@9.^"=O^Y:W024WUH,I`K7HG7B*E/A:!*.,X$#`$#HHN]X0RX? +M&!J1Q>;(0,RC80@L5^.CX2+G8/&V*T8&19T&;`P]OI.BB) +MW$QBL"PBM(4D-/+70=D<0`'4DY'*I\-TXOEBPEL2OBZ21H81T^=$8A'L*^NB +M@].(!*2DI/(T5$H?#\K-*&`ZBN6R+\W)$V1;+.W7Y&0#MB +M`TK,.Y@2E]V$D&(C!H$6&]$Z3%)]5>F@BX>%9I@S'3E6Q1,"Y"_V)HYN[_0R>;\3F +MDY1P,.75;800WBH$@>Y6P3KSG;&#,QG/&7'C`XG\]BLOORF'A\ACM5%2&LN8 +M6!KKE?GJN:H%2L_K]23%9I4>FDAX;)8IPV%352P1:.Y"?^+HYNXW@^<;L=\D +M)1Q,=G4;(62W"D$@NU6PSOQF[.!,QF]&W/@`(J]8J0`:O2-WE"DG=E;=B +MKU!:O>K&1:X(,+A"`W"%1=\J$;>XG:Z#DLC-%0;+(D(G2$(C?Q%<8>1O12-\ +MJRZ]7DQX2\+31=+(,&+ZO#.G&AX@.\G?F5/%1%(4],X'HQ88I>WNG3EV>F@B +MH9%(<8.Y4;$TX+@3_8FCF[,K#)]OM`Z1EG`@D<6^0<$.@1?+V8\):$IXND +MD6'$]#E76`T/D)WDYPJKF$B*@L[%&+7`*&UWYPKM]-!$0B.1XB6O4;$TX+@3 +M_8FCF[,K#)]OM`Z1EG`@D<6>,K%#X`6WZW.%*8`S%5\9<^,#B3R=]7@=%_ER +M.9I-W8UG;5Z(A*YOG134M>!88C?6ZBO^]7JA7,#:XI-2MR6%Q"'Q'&ZF%0?D +M>IT3X?*.MS<16]UM;X1T)3;"'?,5YA`:78BP"BVQ"#Q#2]3.7/,G?B?DK!,_ +M@'P48C;/I[U)/IDM-IWH-4<&HP'6]O#,-\.!*&^OQ\E86'GWMQ+M9<.SM9X* +M=!`@/VOI`1#3JDG,A-QV\X&YM,&KAD\F"C]*RR8/R;1[Q%LW6\9Q='QQ$W>O6ZB31 +MU]3+7[!=BH^GZ?4I)`X)).VU:05P]YHZQ\S@<-J;B*T;O&K<=*7PL1^/KQZ6 +MX+HN]#4(U\>"VH7KH]*ZX4_\KO51H@1/[`!R4P@>YV(TSJ?]2=[+IX/9^6@Z +M7.NYVT<'H`5KMHGA?WM(3^JO6]<&L[&F#CX68U,I,=Q=GQJ20-Z,79LN+[*N +MJ56<--V]QD3Q;*W/C8UH.$_;)=.JD*>['UVN)CP_=T^&L_V]EK_N+C(CMA#RZS'_UT]:*Q! +M_MUX8.W0WD5S-'],3M@['RV+-2M4#V2#V?1B-#P:%WNCZ;+HC\>'D_[T[@E+ +M%?MO[[N'3Y_?VOOL+PO[BX;??LL=D*=]G^V+D79['?:YL +M!S>_^P?KWMX/M_B?6/>]X+UL#&+AQFQ=#V[PNHH@TT:0?#4JLL]/6:=_]FMV +M,5MDHVS$&N"`3SS-SF=2/_L5^6=W[YZ9>[/__T^>&?U(KOW+USNKHAGX3_PR76Z3`;_/!M-M>Q?)8;^Z/#CXORJ4*E[9;"Y= +MF?'#@:LAST*/#[LEDUS+X;)*7758B74NQ5)^W9`4-;8])]+4C1[P^^/2AU]V!]TH\YW655W6_F0W. +MUQ0Y^_WO,T'V_:JJMW3EV:PU)=:S]"1>6Z.P][R%X)Z+$-S;(`3W=D,([@4E +M!/>L?KR7K!#<0PK!O0B%X!Y0".YY"L$];R%H/=2W)@2M1_PF(:`[\'!"<`\D +M!/>3@CN@X3@_F8AF+\9RO-%O%FX(I0/R/;9J`OE +M^(WB8(\LVZ;QE'8?->,K1*G#,>J2G'MI\T*@)&P\9 +M)%[6W/$&%ML.5[J4]>F=./Q4BOUQ@,&7)@M'B]F+CV. +M%FLSC6-E[\G7_,#0>6`_/O_^QV>/Y(6K;Y\\_X'_]\7#;Y[W_O;DV\?\B-$I +M-,89LUNF2!%GM?K/92Y35W<32JCMYA[IYE:)':D6E[^632[^4+:Y:2D.;C[\ +M?_]@'O57V<(_'1Q\_C/SOG=/LRD;Q3]Y1?[V6V44'C_]FHD\6\=-/>16)@W0 +M3;%F$>A6-E^,ID4V$C;L-U76R9L1*_?%DZ_94N5>]XK^<'F2\4SL[?%_GV1K +M,JTN!+T^XFF1J?OZ\0]L,8^?/GK"![#XGUDYU9GFKQ"*;"56\#I?L/S.K\[E +M@JZKD_V$R=9L^7IT48B?RFT(ZC\6F7CX[)OGMPX.;NMZZKV=F"^-C*-9C>*' +MLTK3249@O]1' +MJCR6?Q_RCLH.1^S/WQ@+8`7AS[1O7E\7O5=>7.>#,T9A,2O[YIG\S_/__H[] +MF]]^D/'A>WN#U_G@S>$+II+"&(H?N$&XZ+/7R[Y +M#\LWH_D#J=5RU0_*-F"]L9K/%D4F?S5/;'K%V+/A?I3ED*SPZ+D\[Y&/K/)D]SAC%W21[9(V?%,^G +M]M1[_/2?3YY]__2[QT]?<#/W*QO]FQFY;&R>TU2M@^WV\YYO9/+[.7G_TLPLL?;TMFR/KHZ.*W*OYGJJ[Z +MS_)7X^^L"@S7B_S\E+G>Y8-__?#P^7-C9:?&S^KYY(SA8BIG7#,A7_8'+>EG +M7I85.L^^^NJCIDGT.AVI1X@NO3X)G8:P+6TE2I5B8/.?T4_)=& +M2L2SG(TOY;,\_\>3'\J_&CVK7P7]RL;_QE>U9#\OB_/?3N21L&_PNZ;8^Z(4 +M^\S1_X?3VBP8__ORP3[_3W5V[R&KX;[^U=R-,7I9&\[^E>F'RE4;"Y#)E6NH +M.0=CE*AIZZ`L.^M/ISD_J`_8<\GF8AOG2\GX`<."KZE`>WR="/[()4^\^D%I +M9/WAI060:U=SEK_NOV6-U%]RI.:#@OU\4_=K^8A,"8]\:[]9;W,'YOKY3C?F +M1S7R["*S%Z9JX)"FZFETFD2*EP_X?U2&C$>NRE&M,\>HS0 +M-]7!+>9WPS2TNI[?6I;MUYC*[8A:A9:Z17?$,KS0.5)A]?F5ID!T.7F6' +MX[SZLTI$]=H97>3<$K0FKCR@>>JX[3%.0OSP\-$_'G[SN/?7 +M'[]Y]OB'[Y^]N+5O)T['_8&YH&6N?LT*[DI;Y[9N7']8X(V:WN7'>O^J*#UF]4YJCRT1^ +MR&JYK9^!$\MAH0H[3'/C_&00W]0)!X-TO,Q9<;OZ]9/G+_3YF/*]\.<%;)?Y.PY1US/AOD-M;WLS\?G^=OCZ>5XW-9/ +M^6(Q8WF]F%U.SS,>F,]=\I>417\T'4V'?$[V\M5DM%SRW_0";O"#;MP?Y).< +MO1`K\E5QLI_]^?=?G%I+/AQ#5RT/E!O+XU^.,_W/\0WK&=390OD/BW8Q6O'% +M3NYDZM1H^;QWV+-.9EPFV"87N?&T>;7GT_UKHK^;CP8LXCN>B?X;/FLD$I0O +M#L4KL1O9U8@]H7H:OHI:-'Z2\ZYYN)Z4_6,TNGIM),/T5->7I^7%V4W]H#C< +M)F_8C]:C[*"0';HL%L(XRO;3;;M?)?:GGX]^^N7@X.7+VS\?OV3__/YXJ%]( +MS^:M,8P7JTYQ]-%9';(W-![97WK&"65Q_;[UG#+_2\OE4O8B8/F!/:NQSN,/ +M'TZ+_8K1Y1A[.\I.;XY?'Q[\Y/V1H^5`5BS[:\<_S3+\?R2NP-_\V)JK,LM?&:OM'^M[&,R+U,;F +M7C7Y:/6PGE]W11>C:>NX[)`=B&SIV>^RPWG.3WI\]?GG[&E7^2`;O)[,SK/+ +M/RRN5MFOOV4OJY=7;9@^M\Y?B91I"\+VG?WN069DQU[<@&'M8OZL&_B/ +MQ^J\&_]1G7:3MH`=H2KJ`T6>"GS&'ZH'2ZX'L#PM5$/Y&);&"WS4#?/GEETP(1],WR^RN +M5=#^'Q8.LVM=X#:)/Z68Q"^""3'L+5_+=U1-=`@91>9!QCY\)OYFZ8E(Z?#] +M:'ZB\\X$HK^0Y_[TL.JT)OL3OX[ZS;^?_,#^SO_#3Y'=RG@$_O1_KB8=L;%' +MP_?K1$\^\QF;]X774XL9V>&?VI[M[/T7US_=^/VD[_5L?,*:)^-_NO[95N^] +MGFOUONUI5ALRR,;\V^MI].<9M#W9OZ]_KN7K_L)X+OYK9CR38U_P:1L;P^Y( +M=0;<",+^OO>9"+[X3^UQX]=KGT/BA!T['[WU_RM[P1TQ&S7,B^R267@2Z9L^6?[9NQ$/F416+\'5[V%_UID><\2+\H +M(RU&9Y=\,/?ERWQ\<:AL/]/RLW?,X[[ACK\_G;'Q"Q:)K8(_]9&\`,&O(LC$ +M*..DG%[OX;-'?W_R3^[VE'VZK;9[6\%]38;.!UDC0^5=&B('MY@U*N.Q8UD' +M5(=\,P`;W@U0N@1J#:'23G@Y[6.WY?CWU9SGXJ=5W.\JZ__/3+R>865B9%3:6A3[/M?$X^/7%=_S=TH?'Q63^VW%_PA)]>,#^.=XO +M)X@GOCJ7]R64C[8O2.Y%CSDZ.M8';^NQ,:4C4&_*7XA[&=^+*N2GV)^5U-O/\C*':I^MO>Q>W>O"7 +M;[=J9V/NOA;_5B>VQ<]S\>^5(.O!P?R&^F%U8Z]927G7H@;C#;F99DO<$C>V +MZQ?JKUJ'\06KFT3DJ?NQ/+%_5S6+Z!.9L\?/GGW_[$3>4I*-\XLBZU\4^:)J +M\I/][-1L5NLD;7F?8>/TA7GZ\*8LLAJ;+2_G_,2X<4U"OHJWGV?3QJS!97/S +M$XY[=G.=5,W&,JR77WT$Q8WL07:4F>NW,E/KU$%_FLVFXW?\VE)VL9A-2NLI +MY*M,EEQ1IN^0^NPO9KFJ>.VEXN?_R^9?7RG6G%(SV3;R03%;O%/%*Y^C5KSK +MGMT<9Z=3WBO3GYSP&Q/8?]>?MCB0E>[]\.S[;YX]_.[YK?5#C1MP]E29#F[^ +M]<H-XFO>+KCFS2/7W2*_]H;@UK/HND4LK+I'_G9F2JW_#?SK^?]HE_]E?_&_UJ!J6(4?WRO^KEJU+]L6HQZ +MSL:S[%EDM@R8N41Q-OUD_9[UG>ZJD?C9.OW0\Q?/V*L4]0=][JXZ3^4RQ7Z< +M/^6#PZ4,]$K7D]\NR?]\ZX9Q\58"I;8X_HKI@1C+'WA03=Q_I==E??*.N((T +M&ISH#]NI?J_NS2L?TZF:#A]_J+E[SK`D7CWHG$E +MYT.V+K"@\L;PYJCR%,I@/IH9GW0E55EAWB"5'K?^;XU:-H6L&\`^I8D9RO'2) +M9@ZN#S&:5[QBY3W9TK*UO^WMU:^]&D?:7^31+4Z>#6:3"3])-N)7\8I\RK`O +MC&TU?16.'[U3_HQ0XS5(X+%M<=4$L1E3/W96X9<9]8' +M=*&R):#_3U1^NZ +MH\T^7EIZO[6%R^UH.[5G;K8JCY$#?LZ.^ZX&\H53*!]\?6Z8TK(`QB.S0=_\ +M7=ZD??YV=,+/ML@2B/\R=7E=3)CV\W^+Q]4/)URR+V9S5Q +MKSR%_;:Q\F%^.P1;?NN;,8UH?'7&+Y8)*5=;,QK5#+.C-[C+0[EE\S?KR0_YN/,5\:0Q>VF.7 +MUM#R!4>3-NTX`AZ%U%\=Q_[*83;XL\J-!GSUQP`=K2V9L7#5SIPY6ZR,5 +M68IK]+-_M_^N`=#B#.L@58?]WI[H&]TO99_P_E!]H?O!-/BFW3>/G75O`N7/ +M7OVM)@36!R9D:]YW7?M*O`\1+$74V6+=U>1*RVESY +MHWA!P>;^\/?OG_ZW>D>5>B\+GZ%&]R>'AXO\8I$O7UNQQMMLMV(W?! +M;UKD75E=GC#QN8:>%B1K!5U+3VN2#=#-8+1GUX"[]U]9_U;V2*1H=EEDR]DD +M9_.G>2Y>N8B7(_SUC#[A.;1I[M'P[K0U>._;& +M[?^]L7G,$85R>3^K:T'5W\35 +M0'[3L3J/WY@K'-,U`<2`]BC<<#5FL@?7CVY_,OV7]GG"/S;F\$>O&=_^1.6? +M:C/%+3-YML_/ZA^]WI?WR/S/)1O''UF*@V-V(>Y\46\@8G'YC2ZCJ?DW^ +MY?-C^VSV-C]J^08%OM[J+#Z_EZ:HN?36SPEGW9Y]D'?9?_WX;T^>/A9OALS^ +MW/)YZ?P9]O;*XKD\93GX^N>JQ=S;JRKG\BS5Z.N?IAY55#MG57N;+_C7[BRS +MG^X=W?_3G7M'?[QWBY?RFZ<_RN8H9N+-4.JMR;S0;_N+4?]L+&O\/;^SZ6JT +MS'DIWRV+?,+2-V$%O\EA^?S=\I\96S1_DU%Q2YP&.LM9K(%`\M'>T=/O'_^+ + +#endif +#ifdef HAVE_SYS_XATTR_H +#include +#endif + + +#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_SYS_XATTR_H)\ + && defined(HAVE_ZLIB_H) +// +// The test ACL used here is sometimes assigned to the 'Guest' user +// This changes the text and breaks the test. This function simply +// strips the 'Guest' information from the string to help ensure +// consistent results on different machines. +// +static char _acl_temp[256]; +static const char * +clean_acl(const char *acl) { + char *p, *q; + if (strlen(acl) >= sizeof(_acl_temp)) + return acl; + + strcpy(_acl_temp, acl); + p = strstr(_acl_temp, ":Guest:"); + if (p != NULL) { + fprintf(stderr, "Shortening: %s\n", p + 1); + memmove(p + 1, p + 6, strlen(p + 6) + 1); + q = strstr(p + 2, ":"); + fprintf(stderr, "Shortening: %s\n", q); + memmove(p + 2, q, strlen(q) + 1); + return _acl_temp; + } + return _acl_temp; +} + +static int +has_xattr(const char *filename, const char *xattrname) +{ + char *nl, *nlp; + ssize_t r; + int exisiting; + + r = listxattr(filename, NULL, 0, XATTR_SHOWCOMPRESSION); + if (r < 0) + return (0); + if (r == 0) + return (0); + + assert((nl = malloc(r)) != NULL); + if (nl == NULL) + return (0); + + r = listxattr(filename, nl, r, XATTR_SHOWCOMPRESSION); + if (r < 0) { + free(nl); + return (0); + } + + exisiting = 0; + for (nlp = nl; nlp < nl + r; nlp += strlen(nlp) + 1) { + if (strcmp(nlp, xattrname) == 0) { + exisiting = 1; + break; + } + } + free(nl); + return (exisiting); +} + +#endif + +/* + * Exercise HFS+ Compression. + */ +DEFINE_TEST(test_write_disk_mac_metadata) +{ +#if !defined(__APPLE__) || !defined(UF_COMPRESSED) || !defined(HAVE_SYS_XATTR_H)\ + || !defined(HAVE_ZLIB_H) + skipping("MacOS-specific Mac Metadata test"); +#else + const char *refname = "test_write_disk_mac_metadata.tar.gz"; + struct archive *ad, *a; + struct archive_entry *ae; + struct stat st; + acl_t acl; + + extract_reference_file(refname); + + /* + * Extract an archive to disk with HFS+ Compression. + */ + assert((ad = archive_write_disk_new()) != NULL); + assertEqualIntA(ad, ARCHIVE_OK, + archive_write_disk_set_standard_lookup(ad)); + assertEqualIntA(ad, ARCHIVE_OK, + archive_write_disk_set_options(ad, + ARCHIVE_EXTRACT_TIME | + ARCHIVE_EXTRACT_SECURE_SYMLINKS | + ARCHIVE_EXTRACT_SECURE_NODOTDOT | + ARCHIVE_EXTRACT_MAC_METADATA)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, + refname, 512 * 20)); + + assertMakeDir("hfscmp", 0755); + assertChdir("hfscmp"); + + /* Extract file3. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("file3", archive_entry_pathname(ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + + /* Test file3. */ + assertEqualInt(0, stat("file3", &st)); + assertEqualInt(UF_COMPRESSED, st.st_flags & UF_COMPRESSED); + assertFileSize("file3", 8); + failure("'%s' should not have Resource Fork", "file3"); + assertEqualInt(0, has_xattr("file3", "com.apple.ResourceFork")); + failure("'%s' should have decompfs xattr", "file3"); + assertEqualInt(1, has_xattr("file3", "com.apple.decmpfs")); + assert(NULL != (acl = acl_get_file("file3", ACL_TYPE_EXTENDED))); + assertEqualString(clean_acl(acl_to_text(acl, NULL)), + "!#acl 1\n" + "user:FFFFEEEE-DDDD-CCCC-BBBB-AAAA000000C9:::deny:read\n" + "group:ABCDEFAB-CDEF-ABCD-EFAB-CDEF00000050:admin:80:allow:write\n" + ); + if (acl) acl_free(acl); + + assertChdir(".."); + + /* + * Extract an archive to disk without HFS+ Compression. + */ + assert((ad = archive_write_disk_new()) != NULL); + assertEqualIntA(ad, ARCHIVE_OK, + archive_write_disk_set_standard_lookup(ad)); + assertEqualIntA(ad, ARCHIVE_OK, + archive_write_disk_set_options(ad, + ARCHIVE_EXTRACT_TIME | + ARCHIVE_EXTRACT_SECURE_SYMLINKS | + ARCHIVE_EXTRACT_SECURE_NODOTDOT | + ARCHIVE_EXTRACT_MAC_METADATA | + ARCHIVE_EXTRACT_NO_HFS_COMPRESSION)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, + refname, 512 * 20)); + + assertMakeDir("nocmp", 0755); + assertChdir("nocmp"); + + /* Extract file3. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("file3", archive_entry_pathname(ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + + /* Test file3. */ + assertEqualInt(0, stat("file3", &st)); + assertEqualInt(0, st.st_flags & UF_COMPRESSED); + assertFileSize("file3", 8); + failure("'%s' should not have Resource Fork", "file3"); + assertEqualInt(0, has_xattr("file3", "com.apple.ResourceFork")); + failure("'%s' should not have decmpfs", "file3"); + assertEqualInt(0, has_xattr("file3", "com.apple.decmpfs")); + assert(NULL != (acl = acl_get_file("file3", ACL_TYPE_EXTENDED))); + assertEqualString(clean_acl(acl_to_text(acl, NULL)), + "!#acl 1\n" + "user:FFFFEEEE-DDDD-CCCC-BBBB-AAAA000000C9:::deny:read\n" + "group:ABCDEFAB-CDEF-ABCD-EFAB-CDEF00000050:admin:80:allow:write\n" + ); + if (acl) acl_free(acl); + + assertChdir(".."); + + assertEqualFile("hfscmp/file3", "nocmp/file3"); +#endif +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_mac_metadata.tar.gz.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_mac_metadata.tar.gz.uu new file mode 100644 index 0000000..216b6ef --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_mac_metadata.tar.gz.uu @@ -0,0 +1,14 @@ +begin 644 test_write_disk_mac_metadata.tar.gz +M'XL(")$=EU```W1ED^J[X=\E-1`VU$L +MDD1X!Z"E_TCQM_]^_6."M_1/+&R5]_]OP%]<3_BC4ITE)24E!\8G]#K>=@`0 +"```` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_no_hfs_compression.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_no_hfs_compression.c new file mode 100644 index 0000000..b7210e2 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_no_hfs_compression.c @@ -0,0 +1,231 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_SYS_XATTR_H +#include +#endif + +#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_SYS_XATTR_H)\ + && defined(HAVE_ZLIB_H) +static int +has_xattr(const char *filename, const char *xattrname) +{ + char *nl, *nlp; + ssize_t r; + int exisiting; + + r = listxattr(filename, NULL, 0, XATTR_SHOWCOMPRESSION); + if (r < 0) + return (0); + if (r == 0) + return (0); + + assert((nl = malloc(r)) != NULL); + if (nl == NULL) + return (0); + + r = listxattr(filename, nl, r, XATTR_SHOWCOMPRESSION); + if (r < 0) { + free(nl); + return (0); + } + + exisiting = 0; + for (nlp = nl; nlp < nl + r; nlp += strlen(nlp) + 1) { + if (strcmp(nlp, xattrname) == 0) { + exisiting = 1; + break; + } + } + free(nl); + return (exisiting); +} +#endif + +/* + * Exercise HFS+ Compression. + */ +DEFINE_TEST(test_write_disk_no_hfs_compression) +{ +#if !defined(__APPLE__) || !defined(UF_COMPRESSED) || !defined(HAVE_SYS_XATTR_H)\ + || !defined(HAVE_ZLIB_H) + skipping("MacOS-specific HFS+ Compression test"); +#else + const char *refname = "test_write_disk_no_hfs_compression.tgz"; + struct archive *ad, *a; + struct archive_entry *ae; + struct stat st; + + extract_reference_file(refname); + + /* + * Extract an archive to disk with HFS+ Compression + * the file was compressed. + */ + assert((ad = archive_write_disk_new()) != NULL); + assertEqualIntA(ad, ARCHIVE_OK, + archive_write_disk_set_standard_lookup(ad)); + assertEqualIntA(ad, ARCHIVE_OK, + archive_write_disk_set_options(ad, + ARCHIVE_EXTRACT_TIME | + ARCHIVE_EXTRACT_SECURE_SYMLINKS | + ARCHIVE_EXTRACT_SECURE_NODOTDOT)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, + refname, 512 * 20)); + + assertMakeDir("hfscmp", 0755); + assertChdir("hfscmp"); + + /* Extract file1. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); + /* Extract README. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); + /* Extract NEWS. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); + /* Extract Makefile. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + + /* Test file1. */ + assertEqualInt(0, stat("file1", &st)); + assertEqualInt(0, st.st_flags & UF_COMPRESSED); + assertFileSize("file1", 8); + assertEqualInt(0, has_xattr("file1", "com.apple.ResourceFork")); + assertEqualInt(0, has_xattr("file1", "com.apple.decmpfs")); + + /* Test README. */ + assertEqualInt(0, stat("README", &st)); + assertEqualInt(UF_COMPRESSED, st.st_flags & UF_COMPRESSED); + assertFileSize("README", 6586); + assertEqualInt(0, has_xattr("README", "com.apple.ResourceFork")); + assertEqualInt(1, has_xattr("README", "com.apple.decmpfs")); + + /* Test NEWS. */ + assertEqualInt(0, stat("NEWS", &st)); + assertEqualInt(0, st.st_flags & UF_COMPRESSED); + assertFileSize("NEWS", 28438); + assertEqualInt(0, has_xattr("NEWS", "com.apple.ResourceFork")); + assertEqualInt(0, has_xattr("NEWS", "com.apple.decmpfs")); + + /* Test Makefile. */ + assertEqualInt(0, stat("Makefile", &st)); + assertEqualInt(UF_COMPRESSED, st.st_flags & UF_COMPRESSED); + assertFileSize("Makefile", 1238119); + assertEqualInt(1, has_xattr("Makefile", "com.apple.ResourceFork")); + assertEqualInt(1, has_xattr("Makefile", "com.apple.decmpfs")); + + assertChdir(".."); + + /* + * Extract an archive to disk without HFS+ Compression. + */ + assert((ad = archive_write_disk_new()) != NULL); + assertEqualIntA(ad, ARCHIVE_OK, + archive_write_disk_set_standard_lookup(ad)); + assertEqualIntA(ad, ARCHIVE_OK, + archive_write_disk_set_options(ad, + ARCHIVE_EXTRACT_TIME | + ARCHIVE_EXTRACT_SECURE_SYMLINKS | + ARCHIVE_EXTRACT_SECURE_NODOTDOT | + ARCHIVE_EXTRACT_NO_HFS_COMPRESSION)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, + refname, 512 * 20)); + + assertMakeDir("nocmp", 0755); + assertChdir("nocmp"); + + /* Extract file1. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); + /* Extract README. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); + /* Extract NEWS. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); + /* Extract Makefile. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + + /* Test file1. */ + assertEqualInt(0, stat("file1", &st)); + assertEqualInt(0, st.st_flags & UF_COMPRESSED); + assertFileSize("file1", 8); + assertEqualInt(0, has_xattr("file1", "com.apple.ResourceFork")); + assertEqualInt(0, has_xattr("file1", "com.apple.decmpfs")); + + /* Test README. */ + assertEqualInt(0, stat("README", &st)); + assertEqualInt(0, st.st_flags & UF_COMPRESSED); + assertFileSize("README", 6586); + assertEqualInt(0, has_xattr("README", "com.apple.ResourceFork")); + assertEqualInt(0, has_xattr("README", "com.apple.decmpfs")); + + /* Test NEWS. */ + assertEqualInt(0, stat("NEWS", &st)); + assertEqualInt(0, st.st_flags & UF_COMPRESSED); + assertFileSize("NEWS", 28438); + assertEqualInt(0, has_xattr("NEWS", "com.apple.ResourceFork")); + assertEqualInt(0, has_xattr("NEWS", "com.apple.decmpfs")); + + /* Test Makefile. */ + assertEqualInt(0, stat("Makefile", &st)); + assertEqualInt(0, st.st_flags & UF_COMPRESSED); + assertFileSize("Makefile", 1238119); + assertEqualInt(0, has_xattr("Makefile", "com.apple.ResourceFork")); + assertEqualInt(0, has_xattr("Makefile", "com.apple.decmpfs")); + + assertChdir(".."); + + assertEqualFile("hfscmp/file1", "nocmp/file1"); + assertEqualFile("hfscmp/README", "nocmp/README"); + assertEqualFile("hfscmp/NEWS", "nocmp/NEWS"); + assertEqualFile("hfscmp/Makefile", "nocmp/Makefile"); +#endif +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_no_hfs_compression.tgz.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_no_hfs_compression.tgz.uu new file mode 100644 index 0000000..8db2825 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_no_hfs_compression.tgz.uu @@ -0,0 +1,1765 @@ +begin 644 test_write_disk_no_hfs_compression.tgz +M'XL(`/2=D%```^R]^W[;1I(PNO^*3X%5?$9B5J1$2I9MZ3$ +MR6:&"Y(@B0@$.`!H24[R4N>/\P+?BYVZ=#<:=X#4[)SOM_9,;`*HJK[7K:NK +M)[9C=?[E'_MG;V_O\.#`P']?';ZD?_>Z_,Q_.GM&I[MW<-#I'!Z\.C3V.IU7 +MG8-_,?;^P?6B/\L@-'VHRFAI%<(!V&12\)U;8JA__P_Y8PY'8VLR;?RSZ_'U +MSS_GS[7Y^,$RQY:_>W/6.[TX^T>44;;^.R^[:OV_W'\%ZW__L/OJ7XS'?T1E +MDG_^AZ__[IXQ"NVY]5UG_R7T_L&KEYT&O#.C=YW7;UZ]:>R_-L[[;WLW)Q_Z +M/YRU1[X%$)ZK0;U\<_BJT7UMW`+$^4_MR<0QI\%W(V^^\*T@L,9?./J/AF$8WQJS,%P<[>Y&..VI'K8[151#+V=L?;8<;S&WW'#'L-V1LQP#F#'V1DM\1SQFQS#=L<1T +M[X&R1\0U,G/3=A#/L8,P:',%[SS#MQ:>'P(ZU`>JOF,L`XM0Z=$(?7-T;_G` +MZYBZ:-+(&T-C/&\*'8"-66B-W"7,8!<+4L4$R^'`_86\F;/A;H&1]R6B.015`Z>?--_HO$# +M=D\#`R-A//AVB+^A',N7_L"0.:;HP>'2=D*8.EJ]N(31PO:B(O`I4<;8GDPL'VG8 +M;FCY$Z`(XZ$5@Q()A)?I.$]$)S!QHB[=$7:;Z=CA$Y=D/9IS&+G@R+C%J1S, +M`4.^E$5BMYJA\>0M81Y"=]G01S#1H)WM.)%=Z"R;>L>DOC='(1:,I,;6'-88 +M3$CJ69RFWD1KMB`T`H$+8WMD&#^8ONTM`\,.+2@_$/,-:CC$]MC^V%B8?FA; +MP;'6:#$%D0H6C>TVE^',\P/C`:88#.Z3\7>YWMLXG[#7%BT'%RGTJ6^-0@\F +M!!&PW>1TLEV8*7-:LM`)V&E.8%&-/:X>M$L`]B]O[WKGYP`(M0AA2+A0?/"7-(0"4#"W +M%N%2I51'3NPI3$#X)'\SC6#DVPO@18%EJ6)P`8PM:+(C>HTZBA`I[[,ZFP3*@GS8R'3:\X.=J+%M[LHSV#!X:&]#=%LQJ,X26R:I'/+^TQ-MDXU9F] +M'%'98*A6\!0`/6CEMP8SE'8'EA30EU-0+!?\R0!R90H49!#%.`BA(VDK;]^8 +M(FM#[NY]MOS/MO4@$26#-)'E/,P\G%W?2F8X0);9WM]1S\@VK=2+`73Z/;UE +M&:=CBV]8L<_85SP'H6=@9$G=3_0JP4=[3\! +M43&A"6N3UTT<9M.`B8"]2=605C,_`P4T7M15D"'/374+'+,RI17A0"BY\4] +M!]&M*&4LWT>I@XKA'#0J9-C$[K'[H,XG2Q];X3SMQ-?9,O1PA$8DMJ$HZ(6` +MZHF-2HJC"<*2#/K6>'_YD3J=N\78C@8.OSB>8,0N:`$PK/2,JJ8A7F`1`0C4 +M@.=>T"2BMQY,"N!/;X"SA):+PY1=1N_D7*!F(^\9EA*"LH:@#<*K;#E^39T%K(%&%"NV0\W!T;O]J3?C]X58[RU7>QA +MFJ';0WO:@O;8R/+0*@A#QQ(ON!G]VZLWAX=[QLEIZ^;JPK#G-&VW24I["U:A +MC!MO=._;8Z@W$/F+Y]@P$ZBC:+B9T,_]:]41`A]T,.4R0,S-L35!4;)I:.^1 +M0=ER''`(<83>WIX:6ZANQKIVBQ;_EMYYKUH_VXLXU(4]\KW`FX3&2>^M#GO^ +MH4?$SW_^$,>XZ=W$7WS27]"B5O,6UYT^76$XQP[)E"@\ZGET-X +MV4V]E<^[YS__F/KH?)F;L#H`D9?$XY<82*S-J+B1D\B*!A@83&:+!;,Z6FTI +M;$+Y,!M@8H\W"8Z_[8!$MD.886C9ENM\CC'J;IF-UWK8;09O0QF24[QSUDQ_"!-/;EU`[E=Y`56030*P$LLAML3IX<$C.#4E%0@%L#AWB]:AWTF_2B[D/ +MA#8!\)8)BU(61XJF(`&BWUI@3=U0]9!)_X'$1][FN4FWSX_VO2W5>N%=FH&> +M`>WF1L8X#%Z,FT'(3*NUX.1+>K0`'`=@'CP,.60M+1?,`51R;Q!`-@/O9]CV7 +M5=\'FFTT/^H+2A'EN%B&4;\Q1O^"@"M +M('S"^;``3%K'R)^YY5"'F8FN6&#L-AH'LJ+,`,@`!$O/5;4SI+$.IGC`ECXH +M"#9T[.:?!>YF)'JCFDBZ`&DY$^Q2[.-=;"7``C6:1[+'I4\OD$-"0H=&!?Y5 +M;FB;FP^C@[P5O1"MN35'$VNX1)O*8!V!36KN<6!MV%6A6CT/=C"+<2ZRB(41 +MC=BJ+C3^P@`%*^D)+4=T2&Q2!Z%FL;.)^@3P*7-A#I$`S7K9!:K!;-Y383K7 +MIV%!AFI#$6A7"NF/E6"A0!T@>#7V&B*!W!V;(38+#;ZCJ+=8>Z*%RW.=;$T$ +MA0$3W833T1R/5=]HBA8)'F$)3VP?UKWT()OD*/+8RXRNI*C,R%8EMSJ*"1P; +M]FW$%@'W`\YNJI(:2FV((O[[`":WZ`6M$Y7FA](XN*>U(L9PY+F?+==&+TML +M_,BL-^\MGKC`P*P1>Y-Q/'FD4',X,C:S5==-,7$1!5N8MB!WL`@8U076\$%* +M750YP?Q^@MGP//L_Z)U]'DKY?XKW_PY?'70/H_V_`XK_>=DY_+K_]]_QYYTU +M-/9>[AC=O4[W*&=KSD#OS3-. +M6B.C>T`D.K%.V6_OM;N`2,ZM,4(E$2L*U7$2*:+)^-[JN&4?49\E!"ZD3B7VYIWTN5!N8@50_A +MX=&>HS`#H1)5C&P-U"J6I"'3]@C35+W:%UC1-F)4_%9T2 +M[)K`LN[C="25P+A]]\F(&:QQ]+>T"\(-!$WS1Y"=H-AP!W7V<[IRSTQTY9[J +ML(^+,3HH2[,L2>R\[[Q=X4]#C#0%T0^.4V@W4U!H&H1TN>4^LMYP:G=XYXVB;.D!C +M3SCON-A.5ZU"L,M"TE`$8^`R`PNL,VP;.YAP88KYBRO3L=3>FJ"WEUB!8F/% +MP\U88,=(%]BR&\@)&JV'=N,"!FA?$;A`1^6#Y]^S/@46JRM=^VC?D8XY4;M5 +MYA!:O-TD&A$WPT'#@J%WM.&:HS;*C>2J\20W+MZ>W$:N-R+549SN"M;7S%RB +MF:MS#^A)L944F1.BJ"2%.Q1'6C\$M'MAC7F#8S@*D%M!6X(=60(ID[*WT%?K +M[1+'!RR_15KAQ`9\VHVUJ+2]-]$T&GE3%PU6\KAI+EQT-K'?A=5D5.W)(<`4 +M(C8#1H.-*JKH(^B`4%7AHVO3IHTV%*"QDHM9;!*"T)POQ-)4#JZ3-WN)'M!F +M0[282.6"=V4Z__:<>XN_EX>,`.-0^5:0.W@W$0`A9F/*?WCLC=+A8S +M?=B3'\X_]';1Z:Y6NF/L[SP(C@G"WA?&(OD37-Q@>U+[^V1@R:HQWWHM +M"=Q8:IU"14;&U:WNFJ%;H$?.JHM +M*!/^=J>8X;%R"=D4B$-L2LATWG-36@H7$55-,)>Q<*0)?BBG@5P:(S`NGQ;( +MQ,1R(B('D@BZ9:45*"T]]A:+XCH2$N6_6--'+"U;4WN,?Y/%U&HMZ6F)3\S- +M7^OC=P-2>NC@XN>5"/,X&OU=P6TU50=X"K$4,`N9J;Y2,PD]@6!R"QR2[M;4 +M'#TEMP2(\ZAU<$K]#(59M(,+UJ80X<1_SVUW^]@$2]NC^R1#QPX-WO;O>N0'K%7E#.,.E87RV +M`^$]$(*"JO5232@8#S%GZ8,:>A:+)#'@+[&'SI(1U59X6K7A9@KA68D"!(W=L/#@T&H,UUO,AF$.VA/#2C(T<-_ +M8#KB/^S%@Y],:B^:#ASP0/YZ&&K=CT6,5ZVS6R'IE-\MODK(&'H5#>V<5&YT +M3(E9JJ1I0]6:"@C`3=A&6 +M_AH\""T0"@6N]/['#`3AO0/"]PE)8R")@%$Z.2B\0'BJ(9/PP^6"V$0@3&CJ +MB[TW&/[`T>N`P2'6W@0#?@I8-P./YH?AA#;PK&^(/INT+[!`5GZ3Y^ +M(7A>0!(>YPN/"RR"5RR>.TD`W"GE,$U3&1/]63OLP>2;`(R/>+(<49%_&EA+W#/ +MBV3384X7:G-?LPQ2@(?M-V^TV4B@>ZK[<$K<]M]?]Z_/A$^')!!6A)IUI&W3<>VR)`A28X.JW% +M5BF'`>H%='(+V$L6H$`_4H3M',0*VOTN#/?2I^O-C:B#3'>KP5E'1>@LK>%22:%[H^]F\O&!H62`=$1 +MA:-[2H23UWUL+D*L@&OA]C(4W\YHWM0*%P_?#MA%!0]3'Q^B8CE*#*=C*S`G +M5OC$>DJT$-#FBZFNP$W#`4N7[G93AFY`)9?D8.J^_+\:&Q1?9DU`9[1%A!O+ +M,5'_8Y[W;S&J#E::CY:3*+VO__O_A;7W%_1OMUDS4/SJ+$.AD<,F7,4<=$9J/PS(!K'2*+B)"49<#=N3 +ML@4YC'>`RV*`X@;4#PS#E+8^12TU-C*4*XIE0M9`&^)BEQ;K(R.EV2@4@2&- +M#8I1X-B6R*[#HL"VF(K&L^V.=25U4NH,A"35OL\6A9NP;\T:MY-A"HT-7\-% +M"8<,-EJ]XKP(QIC&(D5I3UYMAC8VA&XLPV*'N&D-+8`Y8RLKC\UQJ$(\.IUC +M4!H;O&%`[A4]""60\2>108\*O"BPS4H13X/7PND@7&N[\>7*GFCB:%G+-44H +M+C+UK9LY&>'Z+H0P?$8XMG:(>H2#A/+51R#L;!\`]XK!1>7HCZQ0= +MX:NI=&V-@;N\MR>@PMG0!ML/9RCIE%,N#GYAWSM>8/Q@_NJ:1V05Z5N6.(-A +M=#GXP>BCXP?JCJ%!P&Y(7\/H'S_FH"%[5H`R1XKY +M!,:#Y3B@-I+(XB!,UPN-)PLP.81M#/HVU;!LPPHZ>KL)]7^'>CD,-(>QS6'M +MT#Y&.0'L#]P-FC0V9,")0>VAV2HPQ`BJV=K_#):TD>1!:<)#3,G=PJ;VV:?3LQ]V>-]!G9,2CDCV:;Q) +MT3(C>YC"VI56#`)H2!N6I-92.]BGQY1>QI08/A>+O11*(LW%<4B*<)=(WUO0^I\M:`_56!TU,"B( +M=FS)$[U+>>0V7D,TN?3S7<#>6ZAI>B+`&K=CIH+ORCA%T.C*30SWAE3L#0PL:&_")$0'1F<&'YZC`>Z7F>;T]MY`QT/: +MGC_=12$5.P,@B,FS)$,?YCY9LVJ`=W=A)GGA+F[)[]ZCL^B+HZ=/:#'?XK/A +M].>4]HN)OQ[)\#,0\'CVMPVKY&GI.Q2"=G`X'T_%:.9:%OL:0]N(YUBX%3Y0 +M)>IIQ&#&>HXPRX`]LR];B)*1;P:P0I&08N&M11;O0Y((AEL""_/QR#@#Q=^7 +M9Z#&MD\1%(9%MK&QM;MU3(8P\L01*+D3D&1\?G7#,.90^Z5OZZ>>V.4,FKO- +MKE[T%(!PF-%NZ\2VG#$U"/H\V>@+T[\7J@AK*"*D@D.FK9#J88Y&2]H74G5` +M5QR`+>U@A@7BT8L(=7L3E!".NW`ID`0-GNW+C^?G3=$'1UAK?\FZ.[G6<`_0L3!8&8K" +M(:`P$C!-?-2K8`E8%!8EV196H.5Z+=1<)[8KCU`,,:<`,1.QDY2N)\RL>]#? +M:$N">2>[]I`9,?OC%N]W6T/\Y)]->30#1@CCFSAU!9T9-X; +MTR$MM()4KQUC@TG_1C:`X^DMR5CS*>YY:`&_L?%\"HX3F0+R6)D(]%%#Q?'K +M+=]HW8EX=9&M`"PGJ%$23D;W4)M:&*MOM);):2>:1.Y5=W%M"<=4'(0"A"Q<`I0R)`X]R%4XT@V$-=&Y0GL4V(9(IC'&8MC[&(W +M''2DOZ!Q9(ISPLQ!I!N#S[(V-F3AH-K".V"=:,A3^+LM=P>BFO9Q$@$OHW!W +M,':P0O;DB4/L1#(7RN;ADFTA65YC`Q<:6201/^28H*EM!(Q]\43V*`MMLNE;-C%@CSB9 +MXTWM$3ML&2<0!RU%.`EY/3FZ$&FQ'X-<\V+R=;+EUT&[/T6Z8K$F2"H(LBJ)O=BGJQIC;C\L%"IO(C\T51@W.QO@^]$;!8A+9 +M7BP1@TG#T^9]_,A>3-9R/YKXVK[%:[7KBL)IA^825F:':[9C4'0QUHYJ`DH$ +M,@E+QM)A;50X'58&?=+*M;LY&_LB='$SU$;5"EI_(PJ<8, +M60&'V8JPCMFG]%]8H24RU0D1:> +M)(YO&8,R,[+$'D_DZ41GV:98;YLQ102]`NH$Z2A:8**.Q]$:9XDD"L3TRV-A2)DN5&&+!G")7AI@G4F2/T`ULWD +M*:95H+,`9!X1X]@HTK#E^4EEF7?;;]IJ!!@3^Y&W)-C/1JJ]9N!OM]A(;WUI +M[B@W&XAT+0\*[L[C+C`E=VBUQ,[I#@AWNXF9@7)&B8/_/>!PX2U8M,>CA,SQO#\8$O:1^+<0-[@\)9=-*&$GTL*F"Y)64W,M1@)+@ +M'DS8/7EVDU/,/=AC=I"W$S@G.),M/D9B8\ZVN,-`F-64ZZ>A11=GU.M-HEH* +M+N+I+#3G?*`\[@V3]I;1,F$-_!W^.X?_)CNX-8&:/WI19>@_(K1L7F"VW/H2 +M!G^Z7J\3^UD*CD*%2,-()C;@(UDLVKY8OM>BP\,O-5YI2JFW#I0$/$WMP:F3CX6KHMVR/ +M,$`#-?#`V*0PWI'Q.\?S/FZR9U/N^S*M5]HX2VGZ[F +M2R-KJU"0QJ'70^LH=Q>R-^#0@>#0E%=L;@;W?,Q5EI)\A0<;UG)?&ER +M#K9:>$9FZ%BM1]0U>&ZI=^;(@<&.7'VWYGSIV,;MTH..L-RRNNSGU26:/N?F +M`OY:`HYK"_;)2@7N)E)>$K8T9RA(-/(CW$5&M8IG*^ZM"'8S7&+20#W2N+&Q +M"?)\BEE`0G1-;!J419A.QHD"Q"YZ5$.F)AD+B29II_,3&[\"K1NAX4GD$08+ +MT-Z>(W%TYB*[+6\)=!-+(![71&=<()//9&>#`<8YI9 +M@PH$9VELJ#AGJ"!N0.;R?(T1Q^&X7,GP45V/YHZP7(`*'=QI)U"O*"O(TM6S +M@)A+$>*/(DD<51Z"W>6Z(H225#BO`M`RHB6-*LYUX(4B#'&Q'#K"O8:$ +MM3,.AHC0Y8!^#!?A<.XMW"R9MM"EO:&?K<6J>8&E,,@HA%6*U?`>0",2"1\6 +MO@?,:PZJ2[S7W@GS,;BW%PLM^#Z>HPEM6.O11$&'EJ>*@(?I=O`>=1;AW]+\ +M+%3,RV0QTAVH3:'M?W_]OAF;/:*[P5B%#N93A*3L]PU,_6G'_?SH()#G/61< +MO$S)1W50JZDO=!H9_X680I^`I1^.9IP6123?0QYW;/1!K?06,O?`9^@4WF85 +MR7,#D5@%]Y=D)CVAS6'R0Y[*(A`E/94/XE-Y[V4TE7&+:$E6CJBLY+HA+T9, +M<)E`(EE&:1AEM.6.4/MY5^V#C>HN&)LP:%&J3MI/5LD^99AFDC8.WY?HK"^% +M70X(GT""?\&:\PGH[5\<4- +MJ(7<8F?=E=)OH@-M*N)$HB*PR0=3!EL@!Q=Y`Z"(\:+TA[6:] +MFU+$[W)T4C#&0"$AE\@%Y4C,5S[9$\&$2M,J>A.4V5) +M1]ED`U)]PF@K6(Y#-V\D5P\9B0R([:/S*D'1"9FNP)!SW(ET=,8>JJ@TVX +M`64YQ[G?:G5=@<>!&[2/\*\2:D,AM1MN/T'C+"H3">#?`HYC28Q*=+;7# +MV(X*,#-7NAXF&N(0**AU6+^VE),*TH71-FU?.67$\>27N:,V6%\S!*",&'4:?8; +M\Y>=I!;>V(AO(,1IROUC-*0T3ZF,\SWYX98VUMLJ)UVVM!-?=>MK4\-68P$B$NV;RXJ\OJ +M.%S6R3FT3S4570M/VZ'$6*B#@Y(LO+`B\%TX5TRQLJC$02'N +M +M%9VNWA5IYJ[%DD3+$D\+>Y2G<8,W_BFB5P2(,.Y,9&T1BH]&!=W2P"T:&[R] +MH,\&W`D$LT7$.Z(%A%9.+%!3Z&LHGU'+POQV]^:3DN;`B&":PDL9JL(UPPTV +M(HJ'MS`(E<-"1`BU3P(IH^T/?*H`"KYO"E,7(Y]I2X\V&S6#1D@A[!@K.OB$ +M5JG80R>?,^IY.+D"#[G4$_OV.9"`XE+19TK#HK28VWN,-,!U1=PLE@9$C/5> +MWK3OQ,"_N/Y+XASFRH?/N-.+9" +M:AL7A#NGXURW@"A`<<<+/,JU)5+BX]'W+6JS-M@\TS".G;*U6"`VA?[JTP%K +MD0Q?CX?$F6V.9B*`G9DU>L!<["-,DN+Y**-P+)5U:P<6RSJ0W/9BZ<0SZ<)L +MQ2D)RV-NHU8>^>;QQ%Z.`=*)^>8)4&D5TB44<1Q!JYOM,>WH_O0X'!WP]"@< +M>$3F9TL;)S4C^-RL/,,(>@E%$F#&>#Z_'T]QWP'TQ +MW(5XM#H"BT>OS='5K?%)E)#-8#LQ72\&=^;`^+J<+PG:3@<(8+[$YR<52HXC +MX8]C212(S!5!XDB/RF(13=#CQD:2]/(F>[SSJZUK1Q'GW""@@7):\;>09$'5:$_J63&_9C_+!SN@A= +MR2'`;`VN,^S&1Z(3T^`T_Z%^"4;<>*%=5.'=PWP*P!PNO5!Q;9(FB6Q]L>\RY"L(*3^"/T`\SEL.2S4+`?.TD +MNOL@8L.^I5:6+X=9Z#L4#(%\H(Q\@MMEZL#D!'8IUI1RYK`? +MPC.%\0C4G3S!.T&<4 +M]4K7,G0Q=!M+#*"9-7'%EZ9D5HR5EE@GJ]R7\7+CFJSPZV*>(#Y`F=Y)'*]MC0'$X@O2W5 +M;Z5I<`)@OH-/!2*`]C6ER@CFC<,'D<.+E9K@6.1\<)#J[B1`8XOU-FYA:JM& +M6&D[`N\;D27`F"YI)T/SK".ZR#2,=W[150;#S_*:'=YJDX<2A,RV\<(94'F@ +M3(Q=3/;-CY&G76U."I_GD3SD)A)OBF-%/'L\E;L](&;&7K5O`O.C$YT4$V!-F +M.VJ8;JFB,^TZ[=3$`UQ=DI?=!B;L?V?F`%M!-%\5Z9-J5IK=#B\283 +MSNDX]9@\]C):J/`>R0D?QC&@""\5)I@'"Q?+5/;G8T7F]='F00'XW1??F,M2]>/O-H;=C2Q0H"O8A(7A^M]_U3Y +M)&@MB/T(L8C038%OY6VE,+U%DC*UF\;<=T9FKF=,,)>$3S\I!]G"MS_#0I\F +M8U8S*OLR45D%R,'J#FZAJAA"L@2U:#4.BKR]"B2'5W$^MC7UC,UWCCFWK"8`I[/;4KM#T8\.NX@3MC)K#PFJO(8E`N,HN5- +M6K+,N>G?`VL542^R=MF&)M2NFZB=6DYO05,<1=Y1,7-)(AT9@[-/=S>]D[O! +M[=G)QYNSP>75Z=4=_)]7-@CC),#M3Q?G_M)*@3BO"O/#5Y%H(2*I)$I:!'V@:YQO$I%]E6>XC74 +MXQD),!7/2.X5G)4J*6T\';@Z.B`FK^RDZ[.;"ZJD?''UX^79S8Z>YA]*)C># +ME+:W'_N*YZ-1 +MT?V-,DF,8;Q-WK!!MW2@2P4:TYZV>6PWR5P'+*\-T,<<;N=/Y(O-6'!TNB&' +M\89$J)@S +M1!*$)H!V-E1GXJ`&S";$3A*7W]Q15[R+.V". +MY]V#XDJ$MF7NV]B@FI05CA)S??KT:;L9I>;BQZ'CF6%33,F][+C=/7,_/I)O +MD@,I^EJ.H.:!H\T\>:V=%"BT#XJY-RCE>2#/V9E\6Q*8<-')9K$?@O:OD&=T +MW[*X!BG0#A5$)WG%(:/8LF0W*A'@$O%R)8?&5(X0FS8B!RH95'(6M%%[ISW1 +MD=#$Z`32(RK8./Y0)LY?3Z29YL3E`1\9>XI\?LHI+X+(HV[4&BQV\G/VS?0V +M<6/8F)*7QY!R>F\OMIM:^BIULZ`(N8N._R4K$B5K9AC2(MA()&>>\$U%H>P\ +MLE03+48*T80O27C6V18]>-^.*20WWA#S4M^.["5=_Q0_<:ZN6I6>)+$KSG+Y +M,#9).^D("07V=CE?J`S[&+77WE>A6/W=*Y54G0,&#B0:>O6T.VS>@4VC>SAR +ML!)Y,E7@BUP9/,'1E%!WBO--W*3^8C9P +ML_">)GNDVWZI:4]QP*ME2#EO>F_[\JKM=&JAO6-#774K+IT55Y\-K1F>^/S& +MGHRMR1::!;`,U?D\N@6-G=[HLGFBH*.&=%VH`T!<;CM1,Y5>-6JJ'>?LN\*G +MB5KP=I-O_`)E`=4RWMM'.XF9M;I0EK>0LLKR47'"%&,MW(P5I^78;0)3=XI! +M3_:$1P??!19Q@'=JGV9JB`,^(DF[?LQ'S02/@M/I7B5A%+/K-2X(Q7T!\J(B +MD0A%3<9-7-B;T4H6SOIX/&9D!]!M`G3+@*@:V06\0&/W9F@1:F2G=63WT!1* +M.$^BK]AYK46&ULTA%G0<,975FV^X2R:6(^8B<8B@R$E`04'(0\2AF?X6NJE],JKO+6LAP_6@/Y8+%**4;Y!/W-!^!L8_ +MGI^>W7"IMQ\O+GHW_;-;X5UZD[?&$EX$$2!SF`S,RFBU2N:H1>5@U"Y=V-60 +M9I-%-KJI+H@BG["4+6,+O6TJHZ5P6AZJA,Y;X6)+ED.B^('N7@3F@R5O=[LQ^O1:Z7-K-9-DWEN=/39?2D>EI.$''&^%V\9%^B2:.JT4W>T^_ +MR,DAMH%1*@?L]TPDE95..[(=]M5P2F[,8WJD24'.7D8)$'G_6HB]'?9X8<'7 +MYJ,V\B(#$V83:%/Z-F9)+Q,[.S1Z8M2UNX"T6!5M"5S70V? +MXCJRS%/%97".*R1$X6D!+*$YH?\=`W@I)0TZ.92C5]0LRK8UL\`&Q83NR5:1 +MSD;.E-@&42QSDW8)J(35I*5$5]07R-0_4XT[ZV?PE4DHE] +MY*:8-95H>KR.Z;8;CEZ;N\L%V][MMOG,/>AHDI6N%N_H&STLM8>C/]F(7 +M_CL\R-AZ.37Q,#%EFC6,UOEN:\9+X5&<1X^OWQ@G>7F4:521@:(=-&/=SV.A +M([-]P(HF38"W"@V1J51^$RRJ\:0H&HZ:"2RD0UR7$8N7P`3K%C<#:+J7)M46#!.!X1],^^E>^_[P](+-X?VY5' +M#YZ_C.+['_?V.J!^JOL?#_>-O<[!P=[AOQB/SU^5])__X?<_=O>,$:I_WW7V +M,:/WP:M7G0:\,_5WW3>O&ONOC?/^6['QUN9[W?%`D(3J'!YT7S6ZKXU;@#C_ +MJ3VADYO?10;(_Z`U]7_2GW_'W<[!J\3Z[QX<=K_>__K?\>>; +MZ,@9J.-\AU,H;`@9A=EI=S#XG].11P?4V@T-V<#-0H$;!\2=)"VH">SO;T`+ +M7SSQ4;7MDR98W6\.6GA=*RD`(+HG(8IJXQTZEXC/[*`M2I@4QZC3EG>J!P+K +M6"4;S"($%#C=,D;X@':(\:A1E#FEQ%J0)W"70J\":G`&G!XJ]M_WS_MU/V.AW_;O+L]M;X]W5 +MC=$#_.O>S5W_Y.-Y[\:X_G@#MM(9-([_F//!`&?.8.P_X4GQ[XQ?0-7ZC?X& +MA0N^PH?O7.]8O*']YA^^_;W5`NI:6>*+"V_URG#@?`+."LR1_F8,IIX"T3^2 +MUYHK`@1A@(@D?ONCL;B?XC$^L"#@_8MM\;NII:+%[_]?/MA\,/9S6W_ZO+?VG^\V,8/ +M@]LSF)F]NZN;YJ;QIS\9HW%#W'0W"&:#T]Y=3]17OFMBDI'6W``1I4->WUR] +MOX%)D0;6H6Y/;OK7=UE`_##60^]C0@A7V$EF@VZ5A.=*_1-L(.! +M>CM``[K9N+RZN>B=#P0J@!XUKF_.XL]7MW>Q%P+GXV42*_$&\>*OR*4"=7Q].#@\:)F8*+@U-OT'V^W0&9$&7@=>"7!HN[(O;ZFE.)!GG\[./MT- +M.LWX<[?9H$@$'2&1LN'%-L,F,/=Q06[$7ATT&W=GMW>U:"0)?(./G#]MT"$V +M]HV60V(WM@=,"6P&P]G$;H\V-C9R0*/K6<3U;$7`$F2V40XS*H)1._!%I?)5 +M"N@EU,`:L3[HBC[8P-0](AEJ5,F\+PDB^Y(()=6AS%\)&ND/0")8"C[2;ISV +M8>:>7%U<7%W"\PVLL(LS,79*SQB,K470C#B36(BW8J($/G,8_X8<7VZ&W&,@OM'1V46="F%T9[TG8A7!1S'958!_]:U6!H=M*0:&KL+ZE +M<(+%M8+RTIT0DVBU*T#*,Y$Y<"`@N"6:,&@O1FID=(PH]R@($(*+KD?`K-D*+(Z6F$1PGE@^/AVM$,+-SR +M=[TXIGC9F-^+R8;G6M)JR[@A*J*T%LGPY(=X[0J7:!SE!U+.!"*U^3.NGX$Y +M_G7`%Q=^9W"OHS&T^.Z_6)]7K'<35'7<&]7FBB+Y82'*;P>]_>_%"*WCW]]\W_TOIS(0%X.(%J=!4+,$.6"!)NE@R +M4VWA"=+?_];^%JC)BLJ.GIN/@'.P1R]=;PAU%M1D-V!)U;IB]S__VOY/J/\O +MOWS[^U]W?X$_?]J%GDF1%D0I\(9M%$[3!.9)U"-TV[<5M0"Z)M4S.F4DH19` +MNB'-X_(RC5BYU&X>$R-1LO'[\>:6L6NTO_UE=_=?`_P!_^T>&\'.+]OXMKG[ +MGW_;_>NW+U[L_-+9V1+$8)W]^'W3V'I[]KY_"?8G!0W\YV9[\Z]0[\U-XP_U +M[L6++K[3'C;A?R]>=.1$L"?&]K_]FRL`9:NU,6U&)N%O?/\%H-,A?$GRV)#H +MQMYQO%RJRQ^"`/`*K!?TVS;.+UM<\],45.&=I`H__VK\L46#H@^)[,BM%R_^ +M]?*X^*]@]Q=WUX!9HPU`)IX"I.*6KFP[586O&>3EP'8^69BM+SC,!+$I6@2L0UV'E8;(+80#:RJU@0'D(-B +M-IN;,4-9Z(KCIEX4X4@4*$;:P]I`"ZX)2_$43(O3_DU3&;6;\;=#O'$0WP*[ +MCWV8FVXG`QY>[^R!]@ZEE>MA$V-O +MJ>&Z[$(3J*'94B"]]<^*%\1QF$X<[?;JX\T)?$1Y%[//E,D"`K4]PE9E?QO@ +M,0LSQ*S\V3"LN,S-J3T".ED`ODET.?2 +M`C!0QW2S2Y!9%_(P*9=(T5[:R%-?2BG'D9=!*=V$_')9"_SQ2T5PCJ-\5;U35>!E/?A\09L%/D1I7B#CLG!& +M9@&_S8+'!*UU$.C46BT,<0M5+1QG9M:"YYR(=3#\FH/AFP^UX,.:]!]KPA?- +M5;Y&+5NK$-_R&#)_)L:'%_AA#ID2T("LV$EV:7AI<6XU/]L^YA?*QJ0MCEQ4 +M;0.DR+#0P(HEN@Y8(K(TT#HR/3HK4B2O=:@B@9V`*Y38&FR)R&;(:AU@CL>" +MS9:0BP`'P\,#RRUD:6F4IT&%QND(A4(^!5XJX5,8Q>(]#5X+NEBPI\&+I'H* +MNE"DIZ#+Y'D*8;FL.[@%\IEA<8&)P\]5`8NE>`JZ@.NF8*O-10VA4+AF0@\P +M@W=UE#+1FD(HEI,I\(59QC(U8#RX41V:PO2J@W]^50M\ZBYKP1=)WQ1PM0F6 +M9]&PDV\@,]S&+&!]QSY;8&D0!1XD/72AU#)56_)Y39)[^9EBN@PY(U(AOTE: +M>`!%,N%V@3E?*$>DP^EN!F,O;,J/'(H@3H-34(=1,:K#\?(@TYV3#UL!(MT' +M:>"L7G`\[(8("#VM5V__%$=K\`!FHO-#LKBSYJ' +ML@0P[J(L`1:.Q3*H"L5*UV()&/L64'9P58<7 +M'J[J"(4",=/'50$ZUP!)>[(`A)TXRE733,2>1:X-`LS\V&ST+@8_#)PH4/4S +M/`Q>;/_0Y+@T>DQ^!)S3LW>]C^=W>+SL[=5M_^XG'7X/$%JM`(5+&+U%7U*B +MBIADE8B?]]_>75V=8Z2=J%`3*(3F]+N3$WXG(.C*EC)VIRJJ#4SQ9T\9_U&D]$I=_V3D\Y2#OU,5)!B>H(5.PW[;%%IZ.T@*Z,LU09[T9Q +M[V=7>C\)4E2L%<-XL8W]*]HNJQX-21Q1U%[AJ-KJI+7/\07>;3;2!1!(XG4$ +M]\]<7ZH.N2M+;QQ.*;HH"U7Z8%>?.:WH?79WT_=$ET2$4[W,1/,'@ZZQC\'2 +M":,J@%23O>J@0\Q:71V\3IWYUC%VS['"\/.*>,,OW14Q01M>%7-51&?E(IW5 +M$>?FRJC>BIB/-6HK=!!2&"LC3>F9,U55QV(%ILX2$!AO!TM,)%L;[V1%O+^L +MB'>^(M[/*^+5F%D"([*EZV+6F!T"8UP;8U(;@TWJNEAX95AM)*<^QDJ5J\L%-W3X/-U2_Y;`2!QRBED@;<>46CV:"PFE/DJ&`&J\ +M]D!ZO)8I05/D\6UD!M"32+:&%C1'0^!;<>H!?P;+81"*WR*"$G]J(9%9Z1J, +MS$P-,?O@0-H'$6@K@9%46/%;U,,IO/B(:I_3JI_^4>^!/`K4(9GHW#]Y>-1C +MF7C<@3&\N.Y]0!,EWF0YJ;2W"NJ?;*Y0%2I9*R]3UHJTA8N,%0F3:ZN\5'TO +ME[$BFS9!,L&(_%Y5P`SS(Q\8XTRJPM)FG'`@5D41VBV^_7D5I)294@TM9:-4 +M1%L)*V6=5$1;$2NI953%\U9!2\K8?*Q<>R0?):W.Y<,660:E6!]6PLJT"DJQ +MKE;"NEL)Z^-*6)]6PJH\ZZ3%4A<^V\(IQ;,>ZWO->'KKM2Z$P"3$2U76`O9!E\I6G61DFV"Y<,OZ*9=MW+[*1!E +M@-E+,5JT*E80CNW*LI13P]!),1?O@JB,QS=@8G1W591,,SH?/&W+%"BS&9_B +M\.>GM'M&"C;\2J6_(*"O"3`^?TV`\34!1NS[UP08]N>O"3"^)L#XF@"C%.-K +M`HS*\?M?$V"41NY_38!1`>-K`HRB2/ZO"3"^)L#XF@`C$^-K`HP?ID#H'YT@GQVB1VRHG0F*K(KO6(P0)X6";'LJR` +MF&6:Y:!A"]/:80XPL7QF3LS,:R&RK*B/N"I&Y3X7AF0%<"1>=:TKF[,:(%X\ +M(K>URG$T$5QS/%+">P7,E5&*AF0((U&X2CF4/\>>28%EJIHIJ&F64I2&RE)P +M4E!.1:AYVI.3`95AQZ2@YF9:-4X!@6S4=R>[19)2H`1\MS9%165Y$W(1L*R< +M#:T4#A('!7E,%_F40B^78RO3EDI!9MA0*9CBD>+@OVQ_BP:5N3.9^)Z[+:?! +M/8:X*:?TWWQ(9:$OW2)F-5E^*>H"M@245!N0C5K,J8JW1B,X%I>F[13K3N4" +M.=_?DP%3(IMQ3M9I;+2?!G-Z6D1960Q58#"\`10!T*WQ"DCD]*93Q`ZK;]8E +M$C12LH#;%&I7.F:>!Z<0 +M>A#84[?,'-#Q*K`J!B]PSV2#%LHJ'3!KTR,7LLHBBJ&@6\:<%(K7%/PPS_+, +M!1_\7!=A6*L%A/&E2)/(1)D6\=9,C!*](`>G4$O(Q"D4?"F,50;=&Q?I&RGP +MX+-_P.I:YKYF&6:)UI6/M$IIH\K3KP +M`Z]RWR`L<>8!WT]>`^W1\T&#K,I3`/)7S[&ML,82CG`P#+(VDE^5^48HPIZS +MBE2=!*;OUVL1P!=Z1=+@KO50NPCX_]S[7*<=7^"_25"CH*P-[ES(NFLJV\N? +M#8OZ8O5J9^V:YT$6.65TR&*;-`$IK)6:';("7PJ'57E26)E[A4YER,K2+:P* +M2!LN=7LA:U\D&[*Z]$*15;4:E6P2G,*AOW1'9EB^9E580PE<98(*,&\[/()G +M022.\>6#Z>-4I.N3+"SIH/BH%U&+0U8Q':.]G4I`TE0NJH0&7<%9HD,#]Y5[ +M^<6CJR'EA&QDPBXL?UZQYH$U*C:?=-@RW42'Y9,#U8!Q=Z*\OJ6!&7D()5[) +M&'!NC$4.?(DFG(+EMF(R_*I89:9Z'+@6;*%JFH`M]`'$8,M-^1AX;BA&#GRA +MM!&0E=$&^1`YP5M%(,/AIY7 +M9&!DXM3J)HE4039GXK$.7!6K3$=-`P_,8>`YR]`JVZ;-0!TY9E`L=/.1!K8[ +M+C;N,G`G$\>$*M*M*3@TC.^2H`"$[Z"@'H5A53H+6:V\-IHORL"YMG'EUE*>B6-(D+)+' +M'5&-_B"`"5XTO#4:@329T2?@PX[/)Z#DO*&/`>QC*0UJU)Z+D(9 +M26=6I93**[,B(3KX\AR$I!OF.6CAKNUST%DNGX5,,G=+;3*:?^@Y"*V_<)43 +MZCG(R+.XST$+PU6>AG;>@Y:N$7Z''0RTAJN2,E_ILF$ +M>Z//02=\IOH\/A.=5=:^B!M?#4T=/JZ+GDB26@U)GE>NBY>1=[6>[;^*Y9TZ +M^KP&@>=0C>/GG]?!7D6_S3HOO0:-%37VDR?:GX5*1CKA54BMJG#FG(Q?FPQNJ:U-A$[2KTV%M[O6)L.; +M8&N3$7OD:]-915?-/,&_.I&Z_JGTJ?X89CRG_&%\;^9U/'-]DG3T*;ZWDX#+ +MS6#_*GEIV>MD8VA7+EEL.KM]&49E[V`F-K4AZ\C]>E3HG/UJ)-9`+6(1)9BK +MMUJ\T4_[KTY%SP*P!I62_;T*%(IW^LH)E.TCE5/0LPRL2R6=JG@%(I258'4B +MY7M6Y31260R>CU2I`;DRR3*KL"+A[&P(:Q)-9TEX1H)%SJB*Y#BKPII$TJ?[ +MGX-@[-#_,Q!\;DIKSPV9S6%U,E&6AS5H%'OQJA+0LT*L3BLO6\2S4'RF"97* +M+O%\I%:94B(;17W$6):*E=$+S/93-9%7V5GB_? +MU:F`NZ+NGITMI3Z=9!:552G@6;HU<+.SKJQ#L&I\7@FMLIBX$O14]I;5Z91O +M"%6C4;R/4Y'&:@*\+#O,>A3+=G-J4=&RR:Q';PU1FLH^LQZ)E73-9+::M2FL +MP_2RL]L\`YUA7:]P+IGDE:*K$QH^2P_)[#G/1"IY&^GJE%:T/_*S\#P3K944 +MU_RL/<]`"\]S/@.91):?YZ*XHA5:DA7HF0B.UEZ.JWHM\[,+/0.MM5=AE(WH +M&>BL;+*FLQ>M3R.6U6A]4@*YO2VA3]C-NV +M5Z2STFY.?E:FYZ"ELC6M34S+XK0>K:+0YV5*,ALT2M1Z4H?KHJ +MA54VJY+9IM:FD,Q"M3[!YR(U7%>FA6M+1M0CP]GTGHG6LPQ;*OO>,]$36?G6I+:J#Z$TB]^SD)39_9Z3F,SZ +M]RPT13;`9Z$5RQ+X+!23V0/7)+K:^8:\;(-K4GH&SA,^8UW6U613V0R?@5#Q +M`:^*A%9S<>1D15R3T#,H!5$6Q6<@E,BNN"K%]4Y/E65CK$\Q.TNCHM-(("7/ +MH.5\3N.=GEV?79Z>79[TSZ(#;/K+0:?9Z%T,?AA#%]L_-/DP'3XE +M/@'\Z=F[WL?SN\$/9S=OKV[[=S]IT'L`/C&=P%)O.O#FB(MY?W:I48.G6%'X +MG/I<6!R"8(%_MD8SS]@T#"P`_VP:+_Y\K`%A';@*9J@5`=-,KP`\)C\6%@\0 +M5'KT2.5(A/[ER?G'4^KZ5K_=&%L+G#Q4PNV'L_-S/$$8>C"M_-'8]IN[PZ7M +MC'?-9>CA3<>[`IZ(PV^<,,%@;CX-+2`A7]#7^6=X`W^U)HV3JXOK_OD9%7)R +M@B5`;6[%O[%:X3O]-[3TY/KZW7GO_2W-9,!7C_Q5/8A?C?,[O;CS_MN[JZMS +M`?W#P`F;1JL5FM/O3D[XG8#0RXB_:K4PBO4[;#8T+M$$@J_5"KT)A)W9"JHL +M5#$:^9.3V+2`Q^3'PFD!$+%)";13DQ)@:*Z%EX_+FZMT[>.WZWF32N.A=WDJ8`3[` +MT/;N>O1J<3\5M]/CJV;CPUGO].R&P6UWY"S'UD"\:S;.[F!IP2<+%G30.!%/ +M(WZZ/;FZ1GXZ"D:@MN#*NSD[^7ASV__A;'#7NWE_1GJ`^(I='X:88,WQ_&`P +M7L[G3Z+?YU/W.\.WQM\94Q]^.?@X=);PES_]S@C"\7?<9S1ZB$Y#&WSG>@FJ +M:LHF"^*9_0[8/[>3YCD(A(NKRZ9\U";2W=DG''KZ#5K.34],G[$-E1&]?]T[ +M^;[W_JS9`KX"7=4'2@V4D#J,^,WSSK6 +MG',3,%)C7XU6^+2PC+'QKT8+??=&J[NW9[2L1VMDC&;`2XWEOST8O_UA;!UO +M"1J&\:<_&0CI3^*DY.???S=^,P+'LA;&RQS88^,/,7=AZAM'QU`Q:MC"HWVS +M1.MX(.*O!8/IW9Q\@#ER&^NC-MHGTR^-]S_WKP=GES^@)M(:0M\P3C2?$*&% +M/F0:CJ4KUATGH7;@%2D;J-IAO[5%9TV@JS"+&*LHQ8A__=+>_1U6E6]-[,?F[N];\&GJ0S>V/AM;N*(F'JU2^.O%BRVJ,YZL=ZO6 +MMW=R?G72.\=J_4:JV!_&[L<`F,ON:&GM+GP/#Q]KNGM2-9O;8`"X4^A,8'J& +M.7*\D>FT.NU.%Q8L]"H2?O$;_`"9[?_1R!*!`++7($C3;XC!DU)]("8_?.QT +MCV`>'@$H#I,9-'H?[ZY.KB[?/5?=Q6NBRQSJ&2GS06FB?='[_NP9*<_->TMT +M^(^H,YD/]XVWMZA/4_'0WBUUP"MD\D8K;.&5$'A#9@! +MN\O`WQ42`1O\.'>`Q$_OKWMW'P8_HE``/0@M"*)X^J$'LP*'N_]^\`%>7Z/@ +M_,YH0Y6"QNGY.->G5\'3'-.;-$X_7ER_[>-<:IR= +M?+@:8`M_&?'OZ.T=_7I_7U]Q9X^S3&;!L!'F7#?*ND?6^T;^\ +MO>N=G^OOQ?HW6B/Y=2"EZ&_BQ1]&:VX<'APH@.N;J_W+3O[[+ +M^08#?*VC2X5B$,Q`MX7Q"1JDU%+U'.?SO`6CUCIH=W%LD/?OPO.N??CZL&4N +M%H[5&IO^@^UV.KL`T^[L.N.&4)6Q\O,-L< +MG%U4+3%/$H8GK3)BI-!:FD#G_>LKNM-@`02A9OC;I5ZZRZK374FM'*^!ZQ[E +M_C.M?5SWR/Y1&^N_.T,AQDT[:EQ\#T63)R-!02J1P8R&?-RXO-!GI#N'%V>G +M?9Q#[MP:VV$#FP'+!EYXPU]!V5DTV#6#+QI7HD2/>HR>#@^H!D)]B5T*(5\. +MWG[$)7)U#7,8J`F-,$5SC(#9[5()5%\LE1&JTA\-1N%`:@+\I,00/VHL'#4M(3[@ +M4?RBMZ#_H!MQ,/;0P]6F=[0_(=%`%8GK):#7>J`2@3[Z`AZAKIL$MW33D(\` +MUX`>%VKH;\@:!ZR>_8$CT:#>@4^/KP\'AP=Q9ME%5LD0`].Q3=3+Q.-HL51( +MXI6'GS,P/UONV,/2B79#&XYV`\^/RJKA;]_S4/_]HZ$]T$=99=PFL1IC;Y2% +MM0OO=U_\EEA!0.RSK<`)\X^&U@\Z_<8,U/?"WD"`J#/H*=87]";=%?0ZT1.S +M<.XDZR4F1K+9=TIFS!MF$$+)YW_&Y0;JUE5E; +M_L00*'%2[?T,*XHM^C0RO&_,[^'G@%VR0GPT&Q[TIMY]NLK66(PGR;Y6P\]* +M!%:F(0]QAL`/`]S0H"R2R.%V'N%_C460I!+DK2[\T*#Y.LYL(\H*Q6K:C>`I +MP!%(0EGAJ!%B[*(VZQ17BV9P(\'IVHT8)VLK57YP=7T'/!J9/S3/LJ>N$2QQ +MH%LB/,#(W0XV\&C)8A9@]\A4DP("WCIG?# +MFQC1G&L[9L/U$#879#`A*.FP,1)N0^7(B5Q]B5?D1XO\/6\_]L]U7UYZMR<( +MVS,#",6>D8K^HG$'BLLM&N3]FRO0/2[ODC5+`6A5S/M&=4U_A![N.0_F4Z!U +M,+E'AEXX,Y@FO10DP,@T\#2T`;)ABRQK-*JWR&-P\N'LY'LAAS_>G`W4R+8L +MUQP"CQ/D]&>DV6"WT""RE7XD&^!'WNM3/UH4\FB'3U#INYEE8+8M`U/=&79@ +MP$2?6RXL`,-;0NV?P"Z;F$LG1$=B,+,7"]02-57(MT`D!E;0!F+]$"DLW8A& +M'!^#D^_;8&#]H->10P]]#`&\ +M')E!V/K[$MB`.PG'R[>$2 +M([P!+O*OH;'7V#BY`+7Y'&""=O@8;FQLP+MH*4XMMQW,M)=#T'BEKS7^A;PL +M]$I[ASJY_D)@\BM8YUBS#7X";B=^68_F'*17P$^QR:]Y!U/?R/^<`A`K0W^_ +MD7)J9V'1FLE$BSSHNK.2!^&,YH._1!<33%R#>F6Y@&^T2,[/>I?2+9JY)8P\ +M@-N=X!2B;U+\@HL]C^8V.U:"'2/PEO[(VC&`O[<1J)'P-L>9E.285(KZ7%^2/]KO9 +MS1:I,'-+H,^E!8!*9L/**.C8O`)$MQ=]U6[)*Z22R&13`DO*4TG!Y#S-4SEHSMVT,T&A\8[1<4^=3VA3LUUY.$6D8I$/K4[`E3*W25F>$L*(>BM!!E +M4.0K*ZT975A3`$4NEY+OG`:D#$B?^OEU)[VP@!1K?V4`I35*K\9TE8A)O]Q( +M$XE^OEP +MHOOU.]Z*FB/`]15>W6]`U1%8M) +M7P15`U%AU$4)JN.(.\$JP$>7?U4!%LZ["FLT?9]7>1?EW=M5"[/FL*3NX:K0 +M#1F&5"Z.N%BKD,''[M`JZES]MJP*<'0O5A4XLAK+X9S*<'.S&IQ7B1[>5%4! +M+'TG5<%8YEP^51U#NV4J?_2S;I,J+T+==5&AT>BG*HCYD]G5'!0U/WFM41#PRQ"M!9=]5E+^6"F(FBG%4M$)9K5*W#)5U3-SM7@W8 +MJ05F[?:H5H_.U8GC=75[:^LA;7A&4-J*KP\:65B4< +M=:=.'82A7:A\Y-R24Q=C6*\5\MZ;NCC3+[51A'91$XRKQJ +MIDX9B3ME:I04W1VS"M(JI8VJ3SII\54"CM_N4JU2\A:7.D5(Y;0R@E+R*J'P +M!2PU@&,WK51KMGZC2O62M*M3*A>C7Y%2%\DO-"G+[CRI7)JXVZ1Z47R)22UX +M>5M)G4JI6TDJ(VFWCU3#H4BDBG(L=I](Q<:+'=EJP/*&D(K@?@UYS0Z@:K!E +M)F_)11[5.C[!JJKA#(LMM>0=')5AG1JP)=9BX@:-JJ")NS*J]>%CC8&JHP?& +M[KDH&YN*1DW\ZHHRHBHZK91NC&9%4!79E(\0NV"BB'+\,H!B_39]J4!5 +MX`I>@NQK`JHBE$BG=.;_O=]4\R\RXDJW9^FA6UJD%E9??0BL+/ +M`\H/\-U_C<;Q'.#'E-9J\3#^KU1USV]^[E]_=WG%V3=2M2H(`:3NEPD&\D9& +M!E3A^E@N"Z.J1+'I0(7P,6S_3-AYN/J&_:#31M.>"JL$WZT,3X*_TR:-I`H\ +MN2L[4=O+P'$:`_BT6FT(O%L9W!'4G1K@W1K@<[,6=0"O27V_!KBW$/T./ZNC +M=.NC[-="F9NC%M?KY\KPW1KPZ8B+"+<$-1EX(2=M1;0H^@(Z'A<\%5H?N5L9 +M68_AT!99"=;C%X1]_%+"C*(P#0!'@5JE]WG%U('>KP5]4`OZ92WHPUK0K]J/ +MBZ`8&N,^H.]P2^3GDL[F$!%S6`7,^3(K`=CU +ML.,C5`^71D@U>17<[LJXW37*[:Y0[DKS8J5UL^)<6'6IC2T'HQ=76FP1;OWZ +M\L:R`*P['-&N=.UR5VMI?+K6Q5NMAU;#PKQ?M9'X%+$]XD/RU0<#)%&9,9T, +M%NQ$JF55E&Y]E/WZ*$I)'2W>[*LB*V'KP8/2&5$942OW]>&A(E`?WUJ.?EVL +M@7_OV:_]-?"7X>3U8*T:$`5_69]"(D`0_ZN-K@+^:F#'@O+$`"H3OSX!'L$U +M"/`0UB<@706#SKXTS5;`?;4.+A_AW-L3-/(MD'(:G?5I=)ZA'IV]P1RLW8EM +MC>L00Q-=,],KH@"37`&)PPHUS'J(E%;%\K7ZUL2GP,E5D7UO=._;XZE5GT(L +MJ+0V=D;!]7$QR'+UDG&'?!UT%7TI:50E(>-JZ[=<[#;70]3#,H5@%BZGJMA\ +M2'9/>:KJX756Q.NNB+=?&\^916VK@72X"M*K^D@/=CC[%;.NUVD7AQKPWY5+ +MDUORG&NOKV]/>EO7(-$=WT2^^N3.*A)PO4L +M;U)[^"FI-(V`MI];K^!@\MBV'FNL2T):#FG(:U=XZ=H4(E<73^:PJ8?WT*9% +M54.)4CB5,3*"ZFMHS>MJ^XFHXA4LEF1<W@+$X@$N.#(AHXDR4%.W_61"W9SU3B_.Q-4R)]Y\ +M[KD&2E3*_Q@!&Q/?<\$:'@?&-KK$=O!VJV8\J]DD<5-,K#3XNFOY&8&4\L,L +MZX-C3O2K,+(@\-X7GVRC5*QB\ONLD:YNI0A#D=U-7&LE+]L9>Z-`NW)'7#(4 +MM1]O]>&7[9'^,-,>$O=\X(?HLAMZ@KJ'%%-IA>(5MD;\!+TI$/ES\5&DY,:? +M,L=V+(UHMREK>7IV?79Y>G9YDG&=6OKFM&\$ED-WS]DCNKDQ]:K%OQ3T:)2" +MUEYEQ%U**!E:65RK1.2EP%TM8C1&.[IC35:WF1D1JFH;7=>5Z!0%DPS+U&9# +MAR:M-B-B*1@SWH_D^W2^19HPB1RT#34>6K[41OJ57B6%(G,E:BC:*W[3T-8& +M!:%&:X&X5R+/(;W+3F2HKL'2,AC&WN-?(B=AZOU@3V"D/D3G^#(^TA9LSC=6 +MP]6YABP(3HU":O?/%6#$`=\2*(PUJ0!5!LPK4.AG +M\GQ/!L3,3\IQQ%5)_+Z92,N6"XL]+F`C+ +MTHF@GWG,A\IE'^)[WN>%&6(VY[R:TFTGM.4P=M9)59 +M[&==9*K7/4/32+Z/J1AYM^!J^%G?WMZ>WO5NM!,WJK[:F1O&?[%]]ND,%+>F +M0*IZ8D>V.]:,+`60QE/<#9PG+2._5S$(*A:\?YP/PR&L)3!?RLMR*M"ADQ]& +M&<1+]IDJI'W7"-V9C[355`?2.3T!)69O*= +M;F;2MX2=F7R78V@26-K2%+9EO*XI2Y.0G\W4C-4XU]84%8X9F[&^B:"2W(9& +M37P4!FFX\CDW.>1`1JO;40M(2*2[^0EX_H2 +MT.S1Z";GZ@9I?%ULQ%[3`HRGVH_>XU]1\OSX>]U037Q)6*J)K[&*I#]+^XH: +M^G,E*&F.EH!)>[0,K!*44XV84Q$JLDF+X;PJ8(]YA6:9I0F0*:]B.G25!R/D +MRU[)][<)"R\;*FGE9D/]I1)4TL[-AOJY$I19\CUE7&:#Y7:T^#XN^3XI^1XW +M.;-A(E]#+HA3]KU",3%C,@_$*Z,R+_E>-BN79=^7588M9KGD0FD&7#;`4\GW +M?'R\U6*@DDAD@2S,(`AGOK>Q0!_,B?$"\%:YKS1:-]^?/>N_^GL]DC[:8#I +MVW8\HXW_'_[:,.>M%O2G;P6S(P,K@*Z$QL:?CQHOMB5+EJ_;MGMD&!GOS;DA +M;&6NW=*W!F-K$32!$&ZWPV^\XNW%?QR#R8YC91@C,[",K4RD+80E(,/X]L4+ +M>/=M4SX;AC6:><:603Q05,3XTY^P$S[>77&'M/#6.LN>NEO'$9XH:MRL@(=8 +M&_#1>K1#8T\C0B\ZQ^*-%9@C^CGV7(M^Z)73&'1^0;(+N:9Z'1/H5&`QC4;[ +M^N;LI'_U\58;2?GC*&O<<$R2RP"&3XS3?T2#\FT,)!H:T?87V['C/"8_(@?/Q-N9::N*,R*D3KMK1S!K=RY)3I(]RUV3A +M4L#J-(%F[^3\ZJ1W/K@X:"I*_Q][[]HDN7&E:7YN_HH<;EF3;%.1DD8FV8C# +MM9&*[";9)5&F)GNX[$LH,B.R*EC(0!*!8$55L__[!N[N@#MP;@#\0MN>%2L# +M?N!^_/CSOKAO[Y+T;IML'GXS':IJ_D'WGYL__*FV:N9@OW_GG89MO[\I7YKY +M].6OKA5XN*\^;_@_;I[>7Z?BX^)+D<>;[*'X9[/9QS?[Y%JGO__XYOY@;6+C +MI3'(.\U?U873]`^RW\$(M4,?_[9'S[][*\? +M7&>OW\<\/=^]O";LG7>*+W$6W_\[/GVYRWY_=>G5IDT7NC:C'ZS\_7B6>HMB +M--1UT.@<7@=2GXU[>HU5GNG\ZQ_^^D6A@N5G*3?*GPJI>O+^GZ^'%-=*_>+/ +MU]5XC7C]6^&//WEON/D5)F6)/3W>O-M^V?/=FY]^NBE;?%S=)';*?WW]ST(" +M*P%\4ORI$\&F3HLJ??)8EVG-J*KQNU637Q>_O]O(3ENENOA4H=[>-&W*WOQ7 +MW:8@Z;O%$OCG3[_XZ^8O'Q3:^^GUF.+ZKP_:_K_7[$+9[EW#=F7D6@M[\>MO +M(M>KK/Y7O=#:7^M_/WU:?`KJDWJ.KC\W>>_^\XK%OW[QETW1X(.;)A<375^B +M"\:LE#WX[W?>.1\M9:?6V#=_%JHR:W55(*BNW)9KA3U3[;S#28&1.BK6=WIT^^9LI]V6" +MR^5<=.WFI\X]GO:[F_=./_WGO_WG1_]Q-;8_??C3QS>GGSYJ_EG^Z_J_'YW2 +M32&-Y1<$?WI/BY!FU^&<_S98[]?>#)9[/;8G_U7\^M_UC!C^^-]-^HYID7A[ +M!JO?[4DT_*[DT?!K@*E4;D.N/>,A*\7R@VKUMUQ5;L*]'FW=_+\W]I9ZT*M# +M+)8".'S7Q+0C2S1UE\T)M.)M?$GZ^Y&.]A[S1D4OS>RF>H9QQKW4EYIFW$/U +M:>/Y=E!]:G'F^-7+>`H?-?N>]$\HSKVW^C7,L^]FBS^7XFN<,^ZE +M^<3W?'MX*+_$/5_\YG._\^VA^Y[XC/MX?-C];L;XV>VL'[=[KC;9KOF$S@+C+*Y8#/S$)MO +M^2ZRFZ9`EMA1>;_S$CNKW]8_\Z[43[;/O:OZT86= +M7MXNNM/N[:`K['9I.6C?9KK\3F^+DPR[95=M^]+3-?9:WD&T^&ZKCRHMO]_F +MXW'+[[GX^O'R>ZV>IEY^O]DJB[=X_=/R>\U7&>MEE;W.KS_5!ZYF/-ZIOZ!U +M*I_XNI]Q1^7K0>8+_^,AR\_;.?=0O=1DYOC5"9=YK^*HGRB>^1R2]H'CI4\B +M*=\3G/7TCKJ?><_O]/8T\PF>X?<8Y][7=M=^(7VY72G/!"U1C^J.WVS:*5QR +MMPN<6!KL=*&S2H/]+G%*:;C3%?:YQ,FDX4[G/Y,TV.<"IY$&^USF'-)@M^U3 +M;POOMSZ;,^?>"CM0N>@%=[7$&:/!/K?SBYFRMR4U1=GM`B=.C/NLGHI>>,?+ +MG#89[':)LQ>#G19?6%UXE\6WX9?>9_60VL([K;X$O_!.7QS/*^QU_O,S@UTN +MB?KYKDO7BGP=T_Q'Z\I=A;!CM#W_:_.OFV;/G +MGW[0C_?\BS__\P'^*5RU]^FG]S,*_J.,J7L;<&[7U7NSK +MMH.;L`WM!]&Q]WQKK2Q[G)ZQZC73RK^NB7A:O-):KPW#`/3R8.U/?<_U$+F2 +M^QX6Z/U(3=S#RM2T6;]2J]K$[KI?D'XU_^^M4__?4/?RJ?^HA-VU;_=FCZT^[X;-'[0-LQ^:ILW?5I]@FGCJK8TX^=:;N6WGJK'[^S?K@ +MR+5'C_5S<]WC(]6#(Q^U+]AX\N2CC^KG0EZ_/"3[FZ+4KO$>?U4&TI_0*SJ@ +M_+-Y^*T<<+O+Z^ZT_QX^K=?UY.G^YKW'CT^_^/`?/OK%+SX^?OSRO?)/IY\^ +M_(>?/OSIO2K\3;W9I=VPU_^/G[R?9]OCJ3`G'Q0_/NE^;P97COO/'Q?_W^D7 +M_W[\Q<_^W=#]_]CYM/;MXMDG== +M+LV_?W7SWU6G_NMF]\F3)__SXR)#[Y=;[/[CYG]<-_C@^E-YP>?FW=V[O[C9 +MU>UW6NORT87U:;_W>SBNMZ*P5R+X_U=41UEU`_4QKM?=+OZ[V$-Y&\>]T7? +MJXVZQ^JZQS:O,WS]_=UKES^LJ_[ZST_J*2_^\Z-R@W;NB[;*DT9E7/51(V7! +M-,\>UJNQ>)?,![2GZ0:/-C8QBX<9RRX8%V79\W9EWBS=)=/ZK[/=0.!)\3J) +MNG?EG%?+7'W\4D7AY+.7:/B5/1UY<.W=/GNJQ]:*Q?SRN@C_K#:QV!VPS]LGLGQ;LW[Q=O/3#BMWB&NGR6[=TN_?7#K-_/`>O6'02$H$U:GJ!^W[`YTPHQ*\3=X_YJ4E`^VF9)2 +M/?$675K*%]Z,&]GR=9>5:S5MW82`N6)]8SVLS1>J;^I\VCPS^.3]PHY=A_Q[ +M8Z_*]8()6YS6G"%F>P3'C]U_&]GOE9>S*M;4]%KS5FWR-W=X9"FW>'O1<,K[/?XO6)Z^RY>"7C2GM> +M:\?):D-.UMOQPW:U7:VQ>(+[T?I^M +MM-\O5]KO\Y7V^]U*^UV0C(.7Q2^]YP7IU+[1?ND]WB^^Q^I>T*7W6K['?^F= +M)LOO<97D+NN8U.\A++W3A\7WN+Q9.2^_Q_-*A&\^5;'T?I=TV^WG-);>XY)C +M5#[YL=A.#1\1667?S7=)1'>N[M)X5KOLAN'4YOU!]L_"[W-FI/.PVWK]L#SV>JV6DSK&>SV$]Q/ZR]Q*[-JZ$YYEAH: +MT7"ZD!U2_3:]8-SR'66"\4[GVY-H!\L':07C5<^U"@;L?3*>&[GW0=2:!,4> +M]'57_,6Z^H<_JNM>C6^XME4T5A:^>=?V"UO*IUCGO1[4?IISF@W%9@H63*W4 +M<'#HZ`V&NYCLNYJM_K4:6U>;(J+LH\SL+Q?9R^`:S6Q[*N[A7F1'Y9M+ZB=3 +M^@5MVR=OA_6IX^*O@\M`\^_2<`5H_IT:+OXLL-,5]FFXY+/`3E?9Y_"TQ1)[ +M'5SCF7^GPP/.>?8YY^J8SG8Y +M;YZ]/6[S?)\=%ZJ:\B''39(>7Q2/NR^SSU.^TY]GL>Z&>\Q:?=&PN.Z/ +M^4(Y/;UY*+]4==UVF1T:KN+/EE++]13&OI1=F"ZOE'L=7N@H_SQZH<6P1>]J +M"_@BZU0_>E==E-==*,_BESEL_E&\6[57&[(OZK#M6/UXWCH=,#^SL=#.JT_N +MK;+OZFM\Z^U:^5#?BIW0O^&W8D=.QKME%NW!RE/1?!1PQ2Y4WPM#YCW]:_=@W?K4W^V_F1\:K>2MVQZG>&*^/K=@=P[6L]7I3?F?`F=XT +M7R!PID/%QRV=ZGT97AQ9HR_*]PZYW)Z;;YFNLO/!XZ`+[WK3?@%U[3ZL>)IX +MXKNI*_9IU=.T_2^MNM")]4[4#K_/NF(WE$^W.M$+^V,2:_6G_C"?([U9[[RQ +M_=.P;G1GQ3/&Y@_)NM&5%<\5FS\[ZT97UCM+;/U(K1N]L=V8OE)WUCHK._C: +MK1.]6/'$L.G[N&YTQ`&%[G]1UYVN&!^L7ZD_JY[SM'R6UXV^%%_K=:,GY4=\ +MW>A*]6U?-_I2??+7C;[47P)VHS.KG7,U?C=XY9ZL.7; +M-`U/72U8$:ON?/A5X]7J<;X.E$^152_6ZW>@^VGP,&'7R+!?[5?`P$U/\%F_ +M&EQN/?A:L#&&81^6WHSOK6MGW2]TE/T4]U_PUYLVV[.- +M)9O[JZ.\/>TJ#/]JS%RNT*GC_>DW;O3(G9Z,^^XE.^),Q=1_V3X>-O?[;7[. +M'.I4\='/;+//LG3,="[=J`VP#U[7[M_XK8QK]*ZHOK'K +MZVOTJ3S'51U45R>87.Q?=0[.V?XYWC'7(%+?R^I.KXI4.>;[)^^S7:4_F[OT +M:/E&U7I=4\[5N\FQP<4$=SOH>L\<0-GME6`N>-SJT\&3]^PMVYN)^Q.6[O/A]M4Z=S[O]Q+VA +MRW9H].[09;OB!*^KSWI-/0JV5&E53O-L6YQEW`[OL5NS +M?_#WE2[9M>EW="[9FR(QY=-OE\,IW[L@^4VW(`]QKM"EJ0.X?[5:]`CT"NT",7SF&K_1E_ +M"]PZ'7+(@FH]*QZ1W-Z[<$EDT*W;E>^QM_9J^`%W1_IUZV)UE1T;?G[>D9X- +M/Q?O2,?;N^;P[F[SZ[ZUKQQ6!7^Y8Y=@*CZUE] +M*_/>@6MZO0YFF9/5=NV6"P^@#7MUW+]V-6'7_WM(?W2PQMY>_]_]R;VTC7\K +M8)T..6H5I]XRMD*7BDOPSI74^"<65NF0`\\FJAURXE;Y7H?J&P[=7'KN'C_F +MMXX=.^:N'#@Y<=%)I[<"] +M6N7):S=6O*YD#N1&[Y!#=TUWKQIUJ2_-\P@.S)S2*7<>YE,[=7]J/^/BA)0H +M?9O\9M;R77K<9P]N5=5I?^?$;:-JEQRYUJ=VZ*N>,[6$^/;6*OUR +MXPT:6I\`7[]:HUMNW)0SZ%)5[D4$QSKGR-,=>I]<[)(+]Y7TNN3"0S!:EYQY +MR$3K%>"+7FMTRX43JG6'7'JP1.N2"^[6Y35,'[A$T=LW%!=GTS9T+'<;N57?].-8Y1^YC +M&?9IL[T]I-L=T +M<]H_;K-M[L*;B0T=_.&$Y_?T7I4?/[22>URSQKE[F;*L7/02L>F +MOFFZ5K^FOF^Z1K^GXP!8U?O5EKXAHNS&D_<_^_:S:E=/WN_]MBEZ\>SK?_G`\-,U_&=_ +M_O2S/S_[XK/R]VN(O_YA,[[5.W_W?[*'FZ?W-[8^O/-W3][_PY\V_[IY]NSY +MIQ\\>?_Y%W_^9]/.1_KU_-,_?/II\LJ3-\4']XY/B_F_ +MYOKW[_S=TZH?_]!ENOU;<5;I(^L/97)-ORH3,/ESDIK^#@B]N9^*7FVA[.`J +MA\8FQ=^M>RPS67U!5OWYG=WAE%M3F6]O/[Q[YYW#\2XY[_95NKHRO#WMBK\\ +M;;XR^)=TTM':E)^*Q30HD_A+?)/JOCIT,\J8 +MRH;U:_VJTZG?,=L7S^/P(KS(WG(C<`,D["XD_``/6W:(X?+!1;@01E'[D_)R +M`;KQB_+?U8O(\:VK[[90EES=\H^;\^/C/B.W?\9L_R6S_7-F^^^8[0D56[?L +M;MBA1B!46]UR1VYY3VY9O1Z4VOKE/J$W3N@M69VF$:UMG-+W_$!N28?0F=[R +MS%P)S5?3J.TIU*^;OB&WI.RS^.[QICI!AF[\N#V=\I=9>G[Q]>[N]>;1ZV+PI?"&[4^$%P@^ISV^#MJ\]B +MX#:_:OOCF\WMR_L#J>'U$#;'-M0_-(!L7)]_Q;8B=+/YK@>RV:7X!@>\4?,) +M!&W1?P88W>7S8_0Z^>7:+V':_W>&VKMZU?SCF:?&]!F13 +MTZO>"2&*!^@NE(;%.;%KK1YWVVS7/*9`"-,>?*.:-F^3Q[5JOHQ!:85/K_[- +M"4+;^CPHKJ7Z#4IDR^ISM\V=B=L$(3*F`-7]ZJP0[>WEK"BU7V:%8$=(^)VH +M?"PG0O'%`UZ$YN9>5I#BE92L`.!L4*4-U;Q@J1<8NB>-T/*T#.[<&% +M&P"U,NNOER.WOQK[Z__D]_!VQ=40^-8_'K+\O$4T0'NHZMN(N,TWVUW[%@%R +M2_5<'3W&FPW.4@TCX*S)H#W>EPQ"($W)L#VO.=*.#-NCO,B@.BC!P"8R*41UY1)V_4QZYQ!VK:X]&,(S4E#@TS^*,NM1GJL*O7D`()TH%7 +MU;1(O[J&DMT<9P$%KXNH!GS"IT7_=&QC(:A,P0?NW>S7_ +M*,6#V%:[$$"-,;Q/!->^ODQ`;%Y?->"T5B\B\.-4)^M9<7J7&%BQ3H,+6I0@ +M_#&UUR-84>K+$\08[=4*8OOZP@*Q=4L48GOET@8U0G6E@]BZN/!!;5I>!V$T +M[ET6844R7B5A1ZS1SXYC=.;LJ(;[&?&1VBLLG""M]><'84]<[["`':HY2.`$ +MTKP'*Y#AVHU@O/I\B6#$[@R*8-#!C5'\B-(!![=!\2/V[FYB!ZS.S0@&;,_6 +M",8L+R$)QCN?19U+,%Y]LD0P8B9Z[[KJ_-<5IKE^J$`IGOLF>&;$XXBP5D^=21RWQ2$7D.U7(1 +M4"H:SYM:+A%*16.Y4OL%1*F`IAOO>1$9%K)_M9$?AG?"8^I:)#^L"'39IRL& +M%RYEX@@P4N*,Q?`JIU`@WN&-\1JH5"P9A1I<(96,-GA:DA>RN7XJ%8][#&*[ +MNBH5KKS8*A6LNO8J%:V^%"L5KKXR*Q6.<]AAOF[+#D8]E6JXJLN(,*Y%O0?# +M^H'Z+PJ`MP2>F9Z(4CZ;=C4-F_OK*KL][3;'^]-OA$*5J?V5;>U"HPETR+[F +MP1'X0ZG_LGT\;.[WV[SX@`4_6O%^C6RSS[+4MCA1T4:O]J,BC5WWQP0:OZJ+ +MB51>7:V>`Q6+5KY\4RI8\;$`@6!35Y(QL4K&W"7IZ?KCZ\.=1/?Z(2=,N$#H +M<4>-WL'#.;E];_VV>CY859@^PE.=-@B +MP[83,.A@I3^HA+52=M'`E?&0#SQ71+&:JD_W"H0K.B>E-:-GCO&!-G?IT?`N +M`V),Q:\*U^/`"<\0>;:0G)*\+3Z[RJ%\]:*?T5.^B#`CQ^6(*"_L1UB8*/:C +M(4241"C*@^UZ'RJ*]50P(LK#UG:>`Q&D^(BM\ONO.4<"=J +MSZRRPW!F:NJ*`RH&\]BH@*#D9'4W!%"?N]4`OO:[9/-L6 +M3G.;<.P0]FYE<,SQ^WC!88JNE-=@+X=3OF!QI@LXS^(.,>B*;X.*!CN]&/VF^ITQ1E-<#6^4+X3)!/Q<$K%YK:(53JGPL5*F,XN["7-LNO_RD7\ +M/DT.^UQ0(KJ82R/M^^YQS*]B)GF6Q&K_%85RV'X8[[U^)= +MO/[?0_JC9!ZKKVD*=M3^&`@ADC1SQVX1P\8JSF?(IBK1J)=\VB +M%ZD^FRH\H3/H=2P4J[V:4GD7[38C82'+N6?TJ%S>D +MR#G/`F%Y=C[>;7.^IA1WOC$O)Y=QQ#K4!AI_X@D2KS+"PV\H(<.H=\T\=J+.ZQJ1KKS8/5>,%FSB,4AT/.:9JD&L +M:BZ*#U1*1>5>2M*#B<9BG?KIQ6)=X])B\2]%:>$FGJ9$QV.Y8>W3N4J-%I!W=EZ+-_K,&SK:^!-OU'";VS3EG``UQA2= +MYB:HP+&/,6YU#DLJ*O<&XXYU< +M-\2^OT^V+V0GJ_AD^6E_]8/;G'7'N2'R#^>T/H`4K5S>+8\[2D@&-/U*(#\DYE]4/)SH>@Z2G\NG3?"C)('ES+/$5;Q2JZ +M5SPQH?1O<[H"C%/9ZAG&B5,ZQ2?=C='N]YMD^W2?V=ZV/=&P>"ZT//_6^QI( +M\67XKMGM:7?]P]/J?]0.CFQF>G[:N+GAZ53S=M=NEI\)O4[#Y,;]E]<:-SJ= +M;T_3H?IOH3)N-+CMO-BJ5P-U7LKY[S\?/K%Y62Z_Q#88G`"%-"K>AXUM4UTL +M&E@Q4-/Z6^/%7[_C-.Y=W,,V[WUQ'MV#;IYSF%W3G:\'H +M'XE"FO8_F@UI8_^N.Z+UYZS6AF^Z(UI_Q6K]-:OU-ZS6W[):HZNZ^0X]M9WI +M["^B_?Y2-B&V?G'8;5[TCWHP[?OG2A%MOR>V>T5MM]\_%NM_7UW`&G@,8)C! +MZ6%,6P(U+=^Q1S1%>X:F79FK_.66'"#=G1^HO4Z3'6_O/Q#;4 +M&6O0=+XM>RW`+23M\AK)GY +M+H*FZ3L?WGV8_OZ=OWOR_A_^M/G7S;-G'^SVC]<#D/TG?]O?O4QOGOR?FY]N +M3OO=S7NGG_[M/S_ZCW]X\N2G+O;?__3QZ:=__S"]_O&G]_[V\;\7<9Y]]:>_ +M?/'\LP]NGO[IZZ+YTS]]>OU_?[G^OW^\>?*DCO[AUX_IS=.[FZ?E'I[\[YN_ +M__NR\?9ALWGX\8/>AMV_KCW^?Y2^GM)S=K?_Y+TG__N]F^K5+]?__C_O%9HFGQS3FW^_-JBZ^TG;[YMK+Y]=__M/7WWZ6?&/:_2BT#XH-VZC7^'Y@3J< +MKK=5UFZ_9^?M]GMFYOYV;?7__=-?_O#UYYO_^\%-D8>_^91*0_?+W";LDDRT +MFGS^];Q5F>!R^69_8B=3'9):F?HI).,9IVMV>V>:BK_>J1F_QO_BCU]_]=7S +MHAOE'Y/\NJ.G^?;%)\^>57^KM_C'YW_XIW\I-M/__?1I\23])T7_KU:O'%FQ +MT:>?_>._U/_[AV^>?[WYXL_/GG_SZ6?EW]3_[G=\\^PO?VGWI/[WM2//NA^: +MG5\G&90(K0Y0I^VZ4H'MZ&\%=V^>WM^\9TC]>S<__713%O=[3]X_97=7T?K@ +MH_?^-C9)V_R#KC#1/4>?H325MW$@3;V#LB*\)+PNV15J:0H6ZEGF(3347R.# +MAYX8&D34&&"8]'9L*P1M:D`%89Y,&F3Z(R-?U9B&3F^@0/CH6?P90C@(+52# +M[Q0'2L\VNT +MOQWN;VQ9_/@F?[D_WNB'B8-M]LEIW]NF2_I@Z_O#WYQ>'[??A[1"5IK@WLHJ +M;M!MI:/XAPLKJNP4:#$56]I64A6ESZ%RC*,0TK,`6@A--\9^'UT"=:_,]5\. +M)(32Y\V(J7([07"J=H%2,%F]9D94"1L!1+,!@`[-IFCV+U#R8?!^A8D;H<3!'(D"WH0M&Z"=EN:N&HO;8NH&[@ +M@2RC&69R;*5HVN+N6H%K#6ZU6)&E)'H<7=J&,(1I32B:M/92"T:S7"N$=Y1K +M^+8;!:[BIFRE_""R:,MXZ)4+Z;:V@%&W1G0K&;2?#IN6/%G0.955;76B!X"] +M&<2T7JWC:=8L)#\.+%U"D:TW_:`U6-1TMJ; +M6677WX7MA"K/N;3=JR#-65<=GO52%8T#(YT$N&J]A=E5]Z,N=OEJV#G(=HP3 +M];V1>KSBYIN_L54QS\4M\74!.MXDK`SW+WBMO:*\5C'W9KY:B\5>]7Z5C[(V +M&E7^7/YE[=5HZ^AP-99;6JJR;--;C];(/=8IN1BCG2EEP]4%ZB1LR[$5IO59 +M6V.V4?N^QF:K +MP&Y6SB@+^E<-NR"N7">9ZCB!!I8K)Y-[LC(:=)UJ++6$53VX4@)N`5O9MJLG +M4UD*=&W/606P%6K0:U_6*$FSB:MT@KZ0*U_FK3$$AE\']7:=!ZOB;E?2*"N: +M-Z66?_[.(.J]#1SE1G\8!'CT0L`8,MBO%?7]/,*(;\T^`0N&`9(:PB`Q'"^$ +M%?U\!@J,Q>!"Y=FH,2F!,#4XT8C +MILQM#(A9KHB0?)AR+UX1@N]@.(S`:$@UQV@5:9J1=:0)(.EE/,--')[&RXJ$ +MLZOX/M"$MRDV\8%$23/C#Q,$K`R9"BC9 +MH*D&5S1F<#'^\"42!^-;)<)9E4R?F4D\.>Y*),[,)+2CK@1Q4)T0#ZH3T3,S +M"?U0*:$=*B7$0Z4DEC,SRQ41D@]39L8K0O#M#(<1&!E):,?!"?DII##-\ +M`'4LGR2=&O]\+6V@Q*8DY`R_"PK.;1RX6:J(D'R8MCH>$4+"Z-`9@1.3\:_( +M3C1C2`GDT\%!XR86?^-A1<+9=9F\)G7QX_SS1>":U(5T]OD"OZIPH5U5N$A> +MD[J0SQE?2.>,+[1SQI=(KDDM5#TX(DR9&8^8P+VP8'XMK9)SH.YNB5'^N\CY-C?8".UG1UFC#X&`&BT`C#6]?5J% +M0L\?3"DL.2>`8C`P0C,8*OKCA+!"SV&@J%BP4!#KW&`J_%OI)%O!7NL3N._- +M(X3W@R88X`\:,[V%3\@(UE_X5W&C[$D?\T-Z-'YNMOW)4>)T72>PIFT,XXRR +M+ZM,=/F"280AOP0H:`-!-H'!0!T7!`1=K@)%P,S%`%RO!I_@SXHE^0/RFIV@ +MM#)7$$)KFV/HK#5D>@&7EWVPVN]^14'8\ +M.CP3]R=>`25T?^)A!4+8].64/_G2"S)]R?4W#RG(23YW'X +MD^7*!L4`NS_QC`(2[./S)W:41[77S;&,6? +MT1=Z=_E"B0CS5?#:0)!-4&``OW&YRU78*)BK&(#KU>XB/%BQ'.>`7[,P5D/? +M?:UM3N"SR#O875[VH7L`ARL*PH[;W_YF?[Q+=WN[YG>;N$T292ATGG1!4%Q1 +M]STE`TH^47)@F@XQ/"0$QW/P&0%3 +M#'6.$KL)$P5S$`UZO=8WBP8CF>`K]F8<2&OM=1VYQ` +M:)%WA[J\[$/W`@Y7%(0=.[O6[QPGQXZC]3L<-W8`O.^0>-^):/T.O^AWN$6_ +M0R[Z7>A:/UK7>L]6+$O61B9=S@R[ZADW@EJO9/+/G2M=[BB(.RX +MMVO]O>/DN.=H_3V.&_<`O-\C\7XOHO7W^$5_CUOT]\A%?Q^ZUL]5#,#U:M=Z +M#U8L1^OQ:Q9&YGL^I9+X7U'HGEWWH6N]P14'8\2)[>WBTZWWUL]L$J8=` +M9T@5`,619I]3R*_SA\)^/^=T('0#(S1#@:$=)P(.=0[#QL,2A8)8YW:?X-%* +MY_@%^EJ'4;Z91P3INR8$VG>-93R$%\@(W5-X5'$0]KS<)R,6H_S5;>Y4`Z!# +MIVR/8DZ]QRG5J'*'$HU>NNFD:`>%;X7B1#-&!":J[(7-B-DK!+ZR[:;"F[7- +ML134U0W#>SV!"+JW+0AP;]O*N`GG&1&ZD_"DTB"L2>P6(G&<,0G'/"0XMB0` +M44B0BI"(&(8$3X($AX$$R8`D=),P5S$`UZO=&'BP8CF6`+]F88A.<'Q.J'!. +M!#V`D\L^=-UWN*)`[!B_*I%X<*XRX5Z52/!G*A/@R>:$<+*YGW,&$&BG&!/\ +M*<:$<(HQB>&JQ!*%@ECG(S[!GY7.\@ODM0ZD//X<<<(Y1YP(7Y7P`AG!>PI_ +M*@[$GK( +MP429O<`9,7>%P%?VB*GP96VS+`5Q=0/Q7DT@ANY-"PK8B/%G;/!=!6]U0MJ?88\2F!8GMJ>@Y"=<9$;Z+\*+2(*QYL%N( +M!\<9\\`Q#P\XMCP`1.$!J0@/(H;A`4^"!QP&'I`,>`C=),Q5#,#U:C<&'JQ8 +MCB7`KUD8HA]P?'Z@POE!T`,XN>Q#UWV'*PK"CMRN];GCY,@Y6I_CN)$#\)XC +M\9Z+:'V.7_0Y;M'GR$6?AZ[UOR:A9$YQY$YIY(Y%]1Z +M)Y=]Z%KO<$5!V'&V:_W9<7*<.5I_QG'C#,#[&8GWLXC6G_&+_HQ;]&?DHC^' +MKO5S%0-PO=JUWH,5R]%Z_)J%D?F,(_.92N:SH-8[N>Q#UWJ'*PK$CO/4AY[: +M+1SGR)G_F:;I$8!CEGA<0`F$-VL(O1!;420![6YC$_Q"BBA>Q0/*Q#"ILM;NS6Y +M_N8VCXK.TT%T;8UB4+FW*3TIOM"="N6\HX!FXI?\&N?+?A"[_Z_.`/]>,V.QGOG51^=94?Z@`H`%':`QFB[=%.>S5W0.`;TTTA06]0 +M^%9`'NAC!"%!S5ZH3%BH0N`KVV0,/%O;-'O`6]U32-7[S<[-+\^G\&,V'8R%'NF(9#@(\A#(Q!QOU; +M9<245YB:C,X(`2F6`9,;PP!C'C^$,Z8\!PJ;54L*S0Z#7?&;'B3S(LJ/"8$Q +MSCA$9RP-,7)C"<'T-R'`*%CO$TZ%@MF6[8M;+TUG64Q;><"V=D!,M#5Q\&SK +M>@!2LC:W>"D;3@N32.J@Z:WQ3%)R@(52F^T(F+1&9>%),F&3?&0)VR@)T`0A +M1-W$8Y5(;4F5(C6&H%ORF4U1.";_*_6=?)L5@[S^S]/J?PI?U/V1S:QK##RM +M#)W2:%3\KBT#9ZLC8[Y9UJ?>K67^&L:R[OO#S +M.L.GI^0*[I-&2YF1*+TM1LG1V]:J96O6_=K*(E?YB\^ENE[N +M'G;)X;AO<-_\<^WUTG9K>KDTFQK72Q='QTL[SA&^#',Q7?QJ9T8W&"E_I6^& +M^F]'Y'OYRTR-L98;^#M7S1#\P^K9!(TN2L(ZM]67T=:!P%+2=W>O)[TB#T2:6,?PY$Y28!UTN_@]%9C +M*Z;77].RT<;K_;!E2_!5)YUEU1 +M`:B1:W.OKL?K[[M&FFABZ,"HQS="C'X&ILN[Z\3( +MSR,%WO;)4.'U*'PO<.YD&.JU`;A3%0M!^'3-FD#0Y,I*@FZ#211TF^(XOD"A +M^\_R5>9071_G_)`T."__>^VU475H>F&4VQG711U!IT=.70^OLT/>7M^M_K'V>JB[-+T-LG0X77H_"]P+F38:C7!N!.52P$X=,U:P)!DRLK";H-)E'0;8KC^`*% +M[C_+5YG#X1UNF]>'XRY]?=+OTVS_NO9ZZ7<2>M=;VV+D[CP2X'D_<. +M&M(%O;]-ZRADN\G[W=1^6^][Z\;N^SJ:<2['5HM^7ZBSZP5^GRANQ=CO-512 +M/7'/H;8E\-Y#K0WE?M+5UYO_RN5L+;Q3/I]0',"%G.8`YD5%];2*[C]G>ME9MHVF7ZW1R +MUE^TU*>/UIAYR$HL%=2_M=A7U+E6XX"JEHDQ@]6Z\3A;K6UEKDX^>8560[QEYI:U7]R;$TV'<6LR;K-Q*IL +M(QN8U^1BBGJ#G&&6F-)-V)93RZSK]>A":P8>V$(3G<_Q5:,IF=OK!J=FN)5C +MA5J;[G&L*9O!P*8TH.K:VHLN.'USI1A&5NSM]G2X&VI=]6<7UVW=8?3*K=I! +M5F^S!QLKZ]R`>-G/(WHY=MV&;PU:ENTHII=FG9`0%^<<L6-8[*9"@`JNTT1N.P:L?33H04;IIXZ6"PC*_XN?7PSE-?RKRZN]JJ[Z*5> +M-H.L]#J^#;=57D"T[:40O4[;+H,W!JW29@33B[1*18@K5'R2)]?74%`=7V$$ +M.46NL7$^UG,`P&.[)8*.;1N6DCJR0L-44<>*9&2%[Q\>\S>;ASS;[X="JO[H +MXFK7.H]>\FIKR,K7]V;CKY8S$(;-648OZ/YPL&U`R[LWNNE5KB4MQ*6^3%5` +M5_!0JKU:PP3A9JWB<4+KDP8`=;\!@M?]IBQM]P`%8>J^1\4U1I1+GFWO\DWQ +MU^\,KD#[V4FFZ`/`,T5K#Z)*;X]6'=!S!U,"2[[Q6!@,"]\*AH;^*`%PT!,8 +M)!P6K!'XZC8X!M_6-\4U<%?X!-Q[4PC!^Z`)!O"#QCS_X`\H`O41_A4;D#BW +M;W\][BB*#5QG3CD(%G.*"%CJ5'N%J$:90[1NZ)EG0:,9'J4=&ASU:''H*),9 +M.CJ6J1C,RA]W&]ZL?:;C(*]^N!!4$XJ4@J8140R:YF+>PQ.,A.]!/"L^()%> +M9&_'O4BQ@>L\*@?!HE$1`4NC:J\092ESB%86/?,LB#3#H[1#0Z0>+0XB93)# +M1\@R%8-9^>->Q)NUS_0BY-4/EX-J0I%RT#0BRD'37,R+>(*1\+V(9\4')=*4 +M%?&`1FPC0B`16%1(FB)G0HCPH+"#@HX8#,C\I8)8ZQ/FPX_5SK4>M/6.8#\% +M_3SR2[L.][D1@>/PI^B`!$JFSGPD'AS]).PS'PGAV"',QS(5@UGYX^;#F[7/M!_DU0_7@H1R\)GP#CX3Z3,?GF`D +M?!_B6?%!B31E13R@$=N($$@$%A62ILB9$"(\*.R@H",&`S)_J2#6^H3Y\&.U +M0N5^ +M86)2Y)$@)UKZF0RIATAJ2.!(-6(L28J4AD^2A0H'Q8$I+^(-"=A^A,P"C#R4 +M\XH6B+H562+J]H+.Q!NJQ.!0O"M",*'2*:.2>D"GE&U34@*94K#6I"2I2>4L +M2DID24I!24HA21J#/5FB8C`K?\J:>++VV<:$N/HQBI!2!"'EZ4$J[4F\P$@, +M?L2KX@,2Z3)QC>;B_EG;"_<:S05_SO8"/?%^H9QXOXA=H[G0SK5>".=:+X1S +MK9<(KM$L4"J(M3YN/CQ9[4SK05SO<"-\Q^%1T8T0 +MZ#[-'K;YYKA_;?A>AOJCB^31.H^&CMH:0AQ];S;-T'(&$@QSEM&`Z`\'VP:$ +MAM[HIKF@)2U$)"Q3%=`5/#007JUA@G5@K>)Q?NN3!H!WOP&"W/VF+*_@`0K" +M]`<>%=<(45[ND\>A&2C_ZB)!JNZBP5$V@Q"CCF]#>Y47$--[*42OZ[;+X(U! +M*[D9P?02KE(1XLH5G^3)]364:L=7&$&'I8WY(CYMGF_/CXSX;:FGO=Q?7?'\(Z+7?"P"AP&"?-ASW\P<" +MLS7IZ%5N&!JA&6CE#T><2-,%^%IT4T3Z/,)M_&Y^_SYG.LV/L?3YW.HA'Q.D9!ATJG4 +M^)Q&C<\)U/B<0(W/(W`;2Y4*8JU;W89/JYWN-CCK'03^SPG@_YP%_L^%W88O +MW`C:;?A6=-,$>C[A-IZ[SY_G7+?Q'$^?YU`)>4Z1D&'2J=1X3J/&BF"?35 +MA-OXRGW^?,5U&U_AZ?,55$*^HDC(,.E4:GQ%H\97!&I\1:#&5Q&XC:5*!;'6 +MK6[#I]5.=QN<]0X"_U<$\'_%`O]7PF[#%VX$[39\*[II`GT]X3:^=I\_7W/= +MQM=X^GP-E9"O*1(R3#J5&E_3J/$U@1I?$ZCQ=01N8ZE20:QUJ]OP:;73W09G +MO8/`_S4!_%^SP/^UL-OPA1M!NPW?BFZ:0-],N(UOW.?/-URW\0V>/M]`)>0; +MBH0,DTZEQC2!]0T/;0BH!ICU#WRK?I>B +M@%?\/`4`6I=63^#ZRJ3[`.S:!&$8^%D#;6L\>@6^I>'HZ@Y:T5TMHFE"W%J5 +M^]9E/MS2E?L60X?;:7#?XL!]*Z#HM7T;M'+/4P"@=6E5;M=7 +M)EVYL6L3!-U;%'1OB="]%5-NUU9WT,KM:A$!"/';W^R/=^EN;U?P=@N7>=$- +M@TR--@2&'LI^IP#?Y1$%>D/ZR4S0ADAJB&*$.F(X*[J4ADR,10L'Q0&[8_", +M!`P'P60!3`R4>46(@M:*(`Y:>Q&GX1E5PG8BGA;A-*'VE[OD/.)3FM\=9E,[ +M!"J7F@`(*G7[G)"9-G\8D1DFG4H1=6B$9AB"*",%\Z--8\#L6*I4$&O=ZD5\ +M6NUT'\)9[R#\=S,)A[_:!H]^M;6$^_"%&T&[#M^*;II`+PZ[S8OC]L'N-[HM +M'&:0,@PJ@[H0"`JI^YT0$R6/&#DQI9_*$'V(I(88CF@C!I-$26G`)%FV<%`< +ML'H1WTA`]R-<%H#D09U7N$#HK?`2H;>7<":^425HA^)K$0((E;T]&+[`I?WJ +M,I>J[I.)5#;'T*C>WY2X5'E#"4LOU61NM$-"-T+QHADAG!55ZD*FQ.S%`5[/ +M=K?AR8IFN`SBFH:!O9X[!-3;%@2@MVU%'(7C9`C;07A29-.$^=[J%KYWF2O? +MTUW"]QB:?#\M`-_CX/^]@"OX'KONOT>M^>]1Z_W[H%W`/`4`6I=6U7=]9=+5 +M'KLV00#^'@7?[XG@_5Y,V5U;W4$KN:M%-$V(5U;E?N4R'U[1E?L5A@ZOIL'] +M"@?N5P+*_0J[ME^AUO8KU-I^%;1RSU,`H'5I56[75R9=N;%K$P3=5RCHOB)" +M]Y68+"$"(_?YQ<]R_WF>;^T.R/]F%O+^AR_08#(J,DGXD#%F& +MO9C2@$&.49)@GR$R1$S#Y[1'(<:0#3AQ!LD/&3_K5QJ%-'9KXC5K&,9%E#8P +M11H6`D*@3(T)>F4*(^*!`L)7V/XIP.*=)F(R>H=$XOKUU(1WAT2"O9J:P"Z" +M)_B+X/U44WF34*Z#)NCKH`GZ.F@2_!T2\Q<'>#U;;8TO*YIN8*AK&D3[!'WQ +M.F%R\V2T%*TQ9*GV-J4'9.S:!-'WB$+ODYZBO))+%.Y-"Q=/S@JV`V$=UQ@6`HV&6#ZH$XO0BCT9@3%T`.(^`\/(1.V1_&X&`'$2G?G +M!_MUB?IGESE5#X!,J*H]AD[-'JBH$Q@R +M-):H$?CJMGL1;]8WPX.05S@,]\T4(E#?-2%@OFLLXC<\`$78_L*C8ILF3IKL +MILZ+*)LXS!UU(%3R*#$0]-'V/*$?:BXQ&F*<`RI">L.DM<2@1!\U&"=J8@,& +MRN+U@Z."U8OXQP6Z)^&3`207VO3"):/7#"\;O0`2/L5'R`3M6WPNQFEB_6"U +M+S^X3*6XEZS.C:Z@Y:N5TMHFE" +MG`^[S7GT:]?=%@[S0AD&E1I="`0]U/U.`%[)(P;TIO13F:`/D=00PPAMQ&!6 +M*"D-F!C+%@Z*`U;'X!L)Z`Z"RP*0&*CS"A<%O15>'/3V$D[#-ZH$[41\+4(` +MH<[[XUVZ&S$JS08NTZD=!!E-300,F;J]3FE-FT.4U`PS3X:).CQ*.Q1*E-'" +M2=(F,V2,+%K7V&,6&M?I@B=!.*$`2U$4$/U.8BGL0CC(3M1SPL +MOFDB7=Y:71*XQJ:+FEHJ$>!JX%!@?5J,`@ +M*!(5,`!FJP/8*K4Z!O?7*=TEX%:%@Q11Y$"@'(DR24$';W$<2L@`0-?K[M&*]ES\8W&U)QU-@.#1",Q@1!B,%<*&7QB#9L&RI(-:ZP1/XM]HI +M_H"_WB_N!&HJ_"SZ$8(=,IWAW1H,JH_NTB;NL-H +MQ%3M(&1I]F!3A3HW(#'HYQ&][+MNP[<&+?)V%--KNTY(B`MZCKF>7FU#F7=^ +MO1%$';WBQFG:3`4`HMVF"'9VC5@Z[=""#5.#'2R6T16?'1XW14[3X_Z8&\[' +M#[9PDP+]81!PT`L!(\-@OW94]_,(I+8U_82U;Q@BJ2&0",,10^#03VF8E%BA +M<%`<,)D`+TE`L@8B+)C2@,&\@N3`T`JE#(;V3$?A)55"=1]>%^$8H=X\)(?C +MJ\TUG,&D*#\Z226U\W@<*:U!)-+V9M45-6PP5[XM(8IIH*SBB]`B5T8S +MO<#;Y(2XM.>;>DU3B.VFYB`)A5-T8@5FW&TFX'EW.86NUP +M\8P0X?7AN$M?&RXH-#^XR(.VTV@:-"TA-.CV8B-TFR,0H8<912]FM?N8[4&+ +M61G-]&)NDQ/B4IYOYB$K<:C-7JQ%@C:35N,X7KN)`>!5W1B!5[492YL=7,YA +M:K/#Q?/.-=O;[.[EX4<(\/XZ=-OR9F'W9)JU=4X:"KJ19<7;1]8L>6BZ5ESUO!)0 +M=:]7<$_@%UC#?5I;Y\R(ZY&M1WD]TLZJ]H%08%7U7Y`#3A86A"1W+_=WKS8/ +MVQ>'.XLC4+=PGBO:<.AT4<.@**/O?U0+$L7$YH7%@?B+S$XCD2&&0`AT><:*BC]5EAAZ;>7<2[^TB<"9^-O88)( +M]K!+#L>]S?74O[K/KV88#'+5(7#4:O<[+DQ-'A&B-$@]@R_*T$@-$5SI1HIA +M2I/&\&FR0,&@UKW-O7BW\EFNA;7V(:+0SB=8$)06:#%0V@HY%&\($H,C\:;P +M0"3*WCSFJ) +MH4:=P/"1,7>E8%:ZS7)XMM99AH.QVB'4;R82#/VN`9KY75,AK^$%,F+P&5X4 +M'(0\^V.>O;%8C.HWYZE3#X&.G"H`BCC-/D=%H\X?7#/Z":>3HAL2H1F<$^T( +M$9BH4Q<\(^8M$<3:MI@*OU8WQU+0US>`[\T,0O'>;8^E>]=2QDVXSX@(G(3[ +MA08FS>8N?7RS.>7;?,Q/*%OYP1YU6$P&*:'P--+Z,2TJ:IZ1\F*<(B9G>D-G +M!4"R1\\$ED)JVN.@T4J%1N+,F+?QFC1LOR/&&J@T:76`$JE>2Y)<]6((.J0@ +MR!6+DPJB<.$D+%^*D>U/:?+C/AMU7?J6GO"P-SPN$?5P!"KV^P,0QU[>L0)I +MFS8NTX:I8`?!LFV0&33?>M,1">'6+T(RGT;=6@B$XKLV:4:!1;!?(S@A'+:F +MB>$PCJ23"Y%ZT3B[$`L;3M+3XS8[V6Y&UC;QA)S-@+C`K.,02-GV`*"@36ZQ +MTCF8$R["E.'26V.AU8T>3:LFR9%`:M&:PM-CU(#YR0^^Y>(3!*Q%[93C1$AI +M1E,?)8"DG_(51M%X)E\+%$&VJ/JJ+APM5$980X\['.T8(N!X6)>""0KFLPKRB,LM50-]P$X_'\:P@,>3* +M'M+=Q$F?>AMOZ%4/B8^O*A")8$T?0")5YQ>O4_V)X1.H&S*C.9Y#;08(**I3 +M'0V+EBTM`DLFC)"?-)&P0WR>(#2HF7FL#'7MJ$K419!U1_ZR*2*GY&^APDEW +MV>;Y^+U0U1:>,*X>#I=O51@"W9K]`P2MSBM6SOK3P651-U1R8RR'VI&C*52G +M-Q("+5=,:%Z,^B(?B<'W1%QF@&6FF6N&L?(`K=?$(%06V!%0.UK8Q#\8<@$3@2?PH/ +M0J*';7[WTN(_JM^<9U`]!#I_J@`H^C3[')61.G]P$>DGG$Z,;DB$9G!:M"-$ +ML*).7?"->TPZ*QI0J!HT^UW5"S:/,+E8IAZ.B_4H9$:PIFA +MC!1!C3:-P5-CB8)!K7N+Q_!OY7-\!F_M`R2@FT^H"*@ML#*@MI5Q'/X0)`+G +MX4_A04CTN,U?CIW+Z'YWGD7*4.@LZH*@:*3N>U1:E'S"Q<4T"72:Z$,D-H43 +M11LQ@BE*2H-GRG+E@V2"Q9_X206.1^%S`2`7ZNQ"!4-O@Y4,O;6,6_&/+Q&X +M%O\*$42JQX?=[VS.I?S-?3Y50V"0J0R`HU*]SW&IJ?*'D)E>PAD$:8=$:(8@ +M1S-"##6JU(7/BUE+!+&V;0[$J]7-#I=K:Q19RKV-:D*1,[@@:!FFPZ`>!K8-'`/5 +MJ!`,*!(5_/*?I1J@*]9B#'Q9LQQ+0%FU`$:7DP4%=+TQELYU,QD/X.:RCT#W +MW2PH$#GVVYU-[8N?W&='.0`&.XKV.'I4>QSG?)D[!.GU7#,0T`P'WPJ!@7IT +M&!"420L?!//5!GPUVYR`1^N9Y0:(*QH"\&KJP`AO-D=#O&DHY`ND/CP4M-K*(R;7PY+@S^%$EPL!LZ*P"%>6TF2*2KTQX1W98O-!)G)GV@KZ21\7P2K$') +M6E,'>#'K6M(EK(LA[>!\)U=4SLSWPL61\+3/B\]1'7?;;+=)TO35^7'2?YG: +M>,1(XY`E>&D*3*2GN8]`.37.#T5L@0:2GC+^?F)4K"S96&%W1;'+J\VR)*N]1861R5NXUUH8!)O[_DV?;. +M]@UY;1,_*-X.B(GL)@Z>T%T/IE6_S2U2Y(=SPD2B.EQZ:R3PE-%C^=8F.0Z8 +M+5M3>'J,V4)/^<$V?0($@2I5-^4H85*;D71(#2#HS[R%42S>RML"!9,M?=P? +M)Q[S:#;Q@VOM@)A4:^+@J=;U8%K#VMPB-6PX)TP4J<.EMT:B2!D]%D5MDN,` +MT;(UA:?'F"_RE!]L7R1`$*CL=%..DAVU&4EVU`""OLA;&,7BB[PM4"39)AZE +MZ#;RB6T2#TUTD:AT@]YOKN28I&>B#T+HP^:T)\&)>%^NDO"8\+1LA5'(,NV: +MO&2+D'-BTP4G3H0;KO6&#(&:X1D#[U$5EY?RN&#QY#MN'V"^JMS0,_Y5@Y,B +M8!F-0<&Z-P@5K').5<+>C$E!K$T#-P859DU6R$"K)B(RI*U4?50B@?R8OTR2 +M\V4R5$++75T<-,EK&_-DKPTSAU<+!7/1>;=0"AI'SH?]0YJ]F71R]68>,;,9 +MF`0OZUA$6K8]`6IHDVN*@@[F20)KRO!Y$2A(Z[)!`EJ3_(A@MDJ]T:@SZ=;\ +MY8Z,4Y,A#TK4VG+`2YK2E"YH2A!I?Q8"R*+R92$4,)B,Q4WR[2>:[5Q4-_.# +MB]K`F%148^&IJ/=D6A^U7"/UT3Q/3(SUA\^+@,18+QM8C&G)CP-BZ]4;C3IC +M?LQS[K#]F"!YH'*FEP-*SOI-27+6#R+HQX(!62Q^+)@"AI/Q_/B89GEQABW? +M9YMMDHS:LN'6GE#2,$PN*HTE-?SP1/S_J3*TK-+D5`H'D'; +MC#$96D]9E`QUHUR9S$/X3_^I)^U!9;E'E..FFCB"W,60D.0NVGQN-&R>1NI* +MPUX(5%(7TYKM3^/7IBU-O*1U-V!97+=QV<16>HA6_VYN>`;`,,>RB-72)1>- +M!UHU>TS6=I,8)6P=JV$^'1%6-A0^2AO:.0A)5'.EQ#B"KH61T'0MX'S^-A[X +M1NIUXUD@5+*_R*[V&6%ZJ^V])'H]5%F85T'9)&_ZAC8)]7SP'$)_4F4IVZ5( +M*!2/KVW&F'"MIRQ*KKI1KDSF(:RL_]23-K&RW".J<$S>C@J2C*K"``(OJ[P(^-%B`QNI!@UT`5#(GR+.CB;_G"9(YSHXF,F<) +M$NKIID3B=%-_4F4IFL@=S2<"1_.)T-%\$O'943?*ET1% +M3@1."B6B)X62!ERH,*(+F+R"5WU#*_T +MY5PPA5Z?3V&,-NF1B<2$:)TM+D/+R8H3H.O7*8]R&#OJ.>?$S:@@Z:@*7)41 +M2X";$"+ZVP2;T8<&"]!8/6BP"X!*YF-Z'/U*CFES+[E<#526RF5,-I7KGJ%U +MO9H+GJ[WYE,6GVUZ9"+Q\-EDBXG/:K*BA*<#=$!6U:>$GG=KBR>&["L@G= +M]0\M\^V\\)1^.+VR3%53)1:,1U8E282 +M=;NK+8YTJU$DU%N--Y^#C8.VD;K9.!8&E>39(\;5%EM[R>]RF++D+D*RJ5WU +M"VT$RGG@F0!]*F5YVJ1&)!"/HW6FF`PMIRE*>JY=H"RN(=RIWV23=J5R;".* +M;E4_',%M(DB(;1-K/@<:)C$C=9QA%CZ5Q.-_:2PL4@91%\C<@F<-DK +MM'87<\"3;FT694%9IT4B#@^359:8E"PF*$I$KEJ9')(A+*7/+),VE%(T(ZIJ +M63@<4:T#2&AJ'6H^+QD>(B/UD>$5/)6\E[<(#WG=V$ON%H.4I>XU(INZ9:_0 +M2EW,`4^IM5F4!62=%HDX/$!666("LIB@*/&X:F5R2(;PD#ZS3-I#2M&,**EE +MX7`DM0X@(:EUJ/D\9'B(C-1#AE?P>/*FV<,VW_P.^H(E97//V*L.5(J]2DP& +M?;6>(31;G0NJ:AOG4PJ7O?3(1*(B4\\6&9KJ9$4&36?JE$ +M=&CAU4C@3MY>9`($SDG9G +M;.G.YK.6F1`G,RXF,PE*9K':RC4KDT,RC*7TF&7BAE*(9E15S;BBFLEI:C:W +MEPP.D;'ZR.`*GDK>VS>;NW0'>]FFWL)+`K?#E85P$Y9-XJY_:`EOYX6GX\/I +ME66HFBJQ8#R:*IEC(K6=OBBIZE+QLGF(L*-A$%':F,HSD:C876UQ9%N-(J'= +M:KSY'&L(EQML;67_"Z'*4ON(B2;VE6_T$:@G`>>"="G +M4I:G36I$`O$X6F>*R=!RFJ*DY]H%RN(:PIWZ339I5RK'-J+H5O7#$=PF@H38 +M-K'F!4OYX(IX_I\ +M"F.S28],)"8XZVQQR5E.5IS@7+].>93#&$[/.2=N.05)1]7>JHQ8XMN$$%'? +M)MB,OC-8@,;J/8-=`%0R[Q\>\S<(`UIM[R69ZZ'*@KD*RB9STS>TN-?SP5/W +M_J3*4K1+D5`H'D?;C#%!6D]9E!QUHUR9S$/84?^I)VU(9;E'5.2FFCB2W,60 +MT.0NVGRN-&R>1NI,PUX(5%(?3NG_^NUO?XGPITT++UG=#E>6U4U8-JV[_J&% +MOYT7GO0/IU>6K6JJQ(+Q^*IDCDG8=OJB)*Q+QU +MQ1%O-8J$?*OQYG.R<=`V4D<;Q\*@DCQYN46XVF)K+_E=#E.6W$5(-K6K?J&- +M0#D//!.@3Z4L3YO4B`3B<;3.%).AY31%2<^U"Y3%-80[]9MLTJY4CFU$T:WJ +MAR.X300)L6UBS>=`PR1FI(XSS,*GDO@AS_:89_*K[;UD<3U461970=DT;OJ& +MEO)Z/GABWI]467IV*1(*Q2-HFS$F0^LIBY*A;I0KDWD(_^D_]:0]J"SWB'+< +M5!-'D+L8$I+<19O/C8;-TTA=:=@+@4KJ#/7BTS23>UI?17O&8 +M\=_QF,WX^M%,ZN5Z&?OM>IG(Z_6R:%]!NG:!LKB&\)]^DTW:>\JQC2BW&?O5 +MC)G@NQFSV=]&&B8Q(W6:818^G<2O40[SM:\?E:A)>OHW68ZQ8HBVLHA^DSV>0=IA3;R$+[FBVTKP6%]O7L#C-$ +M8D;K,$,L?"J)<]0YS-S7(_U<_AQF+G&7\4T3YC.8=YD:#PA2;@%[Z`7V9TF!\GAH1#N14%%0&F`U0&DJXW7\0$8$/L6/@H.39W-ZO/Y/?C_J-=J- +M/.%0-R@NC=I(!"HIO0`H3)=CK-(89H<+&FW8G/98\*A90`.H2W@D&%JAPBAD +M&?4V_K*%[W5DZ`*6(J4`<)*D-:1)DQ9"TA/YCJIH/)/O!0LAWSD_)!8G5?[D +M/..J`="Y5K9'T:S>XZA^5;F#JU8OUW3$M,/!MX+CI!D=`B)5TH('QXRU`5_- +M%O?BTWKF.!7JB@9`OIXZ*-K;S;%`;QO*^`ZWH1"!GW"[P"!D^?&0Y>>MS2HT +MOSI/EW88=+PT(5"$Z?8[*@UM'N'J,$P]G1/JT$@-X;101HH`1IO&X(FQ1,&@ +MUKW%5/BW\CG6@K?V`?SOYA,J`6H+K`JH;66`IT_50`4?9I]CLI(G3^XB/033B=&-R1",S@MVA$B6%&G+GA.S%LB +MB+5M\1A^K6Z.OZ"O;P#BFQF$`K[;'HOWKJ6,JW"?$1&X"?<+#4R:S>YP>K79 +MWME.9_0V\H,\RJ"8`.HBX4FD]F):3Y0<(X7%-#M,P.C#YK1'(D?+`I8]2L+C +M0-`:%48ARYB9\9@M;'LC1!>H#JD%@!(DO2%)F?00@E[(>U3%XI>\+U@D^1[3 +MT^$R[:JJS7QB7STP$?95L:CT:WH"U;XZUR3UZ\^3"+:ZX?,BD-#59H,&KSKY +M,<%KC7JC46?:<7G+'2'7)4(>G)`UY4"0LJXI0\RZ(.+^*P"0Q>7#`BA@)!E/ +M^WQSRK?'W3;;;9(T?76VO?1GHI%/S#0.6H2?ILA4FII["559XQR1-'=\MD5` +M:4N;9#P21"U9I"'5.*$QX=7MBI8@Y[3##)*=0NYS=GKBA-U<<`29MP5BB+XM +MI+B'C1C-<7G?B!<,G/SIX_ZXN=^-6N1F&T^HW@Z)B_`F$('871\`9J#-+U;[ +MAQ/#):0Z9$9S+/^4#*!QUZ8Z$K8M75H$EHR:1E]IPK>$$CP!ZU?&93-,[+YT+%DNZ0C-Z=KVSE%>O*8V +MFACR#LMOX/1ARKO),%LC=M +M8DQK4\$.0F9;DQDZWZKIB(UPJQ4AF4\PM^8QH01=FQ"C\")8UPA1"-O63#%L +MX\SBY`*B7GS.+J#"1I+T8?^09F^F?5Z]G4\,;88FPL\Z&)6>;5^@TMKDFR2L +M@\D2H9R2`F8($N&ZC-#XUDQ!3&Q;J>R(#)KV8O7R?C9HU93-/**D.C(M()1:!D%I/`(JI +MYAHKF,9YXN*L-WQ>!"S,]&R@6:8F/Q*0K59O-.J,VC._N<,W9W+D`2N:5@XX +M0>LUI>E9+XBD+PL%9-%XLE`*F$+&S>UO?[,_WJ6[\L5(=K!PSE:@L +M>FJ]0RFJ.B=T;37.K!P,>VF2BD4'I)XU!BK5B8L.F4Y5+9>`0)<8"@,EG>,< +M%"2(L5945%GN!>$*="_NV9TCM;^:"H_R#^93$J9(>F4@I$G?(H!W:G_G-.UIG* +MDHXDPFT9T258"<$78"787'XT9(!&Z4-#7@`T,K\]//X:[#[+C3UD,L2")Y&WF,=L?SI!;62[O7_T[88J +MB-\V*(_`2M]PPMW-!T.[#9,J2$TM14*A&.Q4,\;!9S=E\?'3F7)E,@]J.(.@ +MGJCM%.<>18N5:B++L1:#K!S#9+'%[6$Q0?*M>N3`[)H(;3 +MDI=<0,I0%R2 +M2+,U>C[S*`1&+AIIP3[PDDKG/-`:)R!C]8Y`%3R/O +MVQ1N(8MM/:1N.41)Y!8!F<2M^H04Z3+_'(W6)U"2C$U*!,)PN%AGB(7%-L-41!RI8!>92M^X23Y"K_#$GN3:`@$=N4"(1A$+')$(>(U=3$ +MQ\-52Y+!+JA+])I>HBY1C%\4\:PKABR>;7NV>+:19G*)P3$Q1I<87*&32/N8 +MI2^R[0/4*#:;^T?;=J""N&UB\HC;]0RGT.U<,$1Z.)^"F%33(Q.)`4LE6QQ> +MMI,5'S#=J%,>Y:"6,@#.B1I+8=)15+Z-5L6ZS@S.<-@J!>C`PRFL.$D +M/>WSS7V:/6SS49NG;.8)0=6!<>&IQ"*04^L)0%757&,EU3A/7+SUAL^+@`6; +MG@TTU=3D1P*TU>J-1IU1\^8W=_BV38X\8%W3R@$G:KVF-$7K!9'T::&`+!IO +M%DH!4\BX^=W4:W+ZVWI'R'J( +MFR$&^.JIB8Y]ZY8D@UU`:^Y:"F,0#.B=I'8=)1]+8K([+HJB'8RJL&F\E7!@W0 +M&+UFT`N`1.:[QT,*-9_EMOX1N1JB((S+@#P2UWW""7F5?X:*]R90D)1M2@3" +M,!C99(@#R&IJXF/CJB7)8!?44GI-+U$S*<8OBHK6%4.6T+8]6S_;2#.YQ^"8 +M&*-C#*[0R:3='/>O[S!6L6K@)W'KP0I#MXK*)V_3.[Q6UW/"%.S^S`I#LTN3 +M5"PF/MNL<1E:3UR<&'6E:KD$Q!C.`!@H;CV%*4C5YJ:H6`+=!1%1Z2[+S&ZE.#7Q`D;^,;L=J""OFY@\6G<]PVE_.Q<,Y1_. +MIR!.U?3(1&*@5,D6!Z3M9,4'43?JE$31N>H53\WH.&%K> +MGT5!8'9ID8C#@&6;)0XJZPF*#Y-K5R:'9%"'Z3G+1-VE(,THPMH4#EE6NP!L +M4>U"S>0I@T1DC%XRR((GD?=Q>X$ZR&)3_YA;#E"0MT4\'FVK'N'TN7\#<#E=OZ1]9JB()@+0/RR%KW"2?`5?X9"MR; +M0$$2MBD1",-@89,A#@RKJ8F/A:N6)(-=4%OH-;U$C:$8ORC*65<,63K;]FSM +M;"/-Y`Z#8V*,#C&X0B>1]GS*X3:QVM@_TM:#%`1M%9%'VJ97.%VNYX`AS/U9 +M%`1CEQ:).`PTMEGBL+&>H/C0N'9ELTS4-@K2C**G3>&0!;4+P%;4 +M+M1,WC%(1,;H'X,L>!)Y?_P=PD-6&_O'W7J0@M2M(O*HV_0*I]3U'#"4NC^+ +M@H#LTB(1AP'(-DL<0-83%!\>UZY,#LF@'M)SEHEZ2$&:422U*1RRI'8!V)+: +MA9K)0P:)R!@]9)`%3R+OB^,982+KK?TC;S-,0?#6(7GD;?N%D^MF'AAZ/9A* +M04XJJ1$)Q"!EERD.*IMIBH^4#A0HBVM02^D]V41-I2C;*"K;U@]99I4(;)U5 +M8LWD+(,E9HSN,MC")Y'X`K>7%R\)?!$VEA2\$Q;XPY?HREYF\B'#QPH/B +MA4_$2YP&?Q@4!&/TA$$5.(FL +MY4?#85PMO\WM'5?+`0I2M8C'HVK5(YSV5M]%IVNO/G>""&S2P8_"0&"='0X" +MRTF)#X#KU2*=5E`?Z#&O1'V@$+$H,EF5"EDFF^9LF6P"S>0#@X)@C#XPJ`+' +MD35]S`_I\31I`IOM/")J.S0)F#;!B"3M^@(4VS;?%*4=3I8$[=04,$-0.*=D +MA`2Y=@HBXMM:94=DT*2U\YE",J9.BD,HM>NJ`B]U:ENZSJE1I%U<*%R+RKF% +M4LACI+P_)/D^*SS>J\UC>CKT7V4X_-U9+AJ&@J?A,`B(@J9]&^70D,]I&1R; +M!#R=S$,D-IVFD7'$``H94AHL>Y8O'R03>J[);RI07)(<%T;$Q#2[4R)B;@,5 +M#W-KGOOQER\!NQM_"Q%RG+<_YMF;S5WZ^&9S^_+^8#G3U-_*6699AT4_NNN' +M0AW;#?LQ>J@_R#/\0-\^1?2C,-/060'@1V"&3"".OP9I#Y9.+A0:B3.6LTG^ +MDX9S)DF6-8"#[V$=0`^]32VQ!]ZF&#+GC\(A5\#.*KS"A9`PVV]WF]WA]&KS +M^G#&VSG/0L/0Z"P8.07,$'"2&3." +M8)EA"H)GV?IE1V20Q8^%02&.)Y/G$$#>3%4!%3AS6ZS$F:/(N+/PN!:!2PNO +MD$'W08QZ-&^8*.#'2/0#BB!!^B1]%IE">/;0B!./?UJB8%#KWG;7DW/`[,0$GC`P;ND\GP^"X-V+2C]6,O0'< +MFTL]?!^=,>[-D[SC*T,,[.V3C",LTT2$CRT7JH]*I-&;P_UG$O_V<%DJ@>^K +M)1YZ6QK3[JR=Z2Q2F)B+P9\%6=#0^T+-)LZTA;.D-`Z'=V]HO0 +MR/'IX-W9B8:5J3'N[DX1\9@!OY(7+C:T5 +MY69>.+QF>P9C +M]E7;I[9MLHRPMF\\RFA[,ZMG" ^^X'O"TH]:BE^'G0_8?MX=@[MU%N5_[= +MF>.3D:[;CDG*)O;:+QL;CT3&]F4\S%3R-7UP:4JN[0@!.@1DD^FC`6U$AF.` +MD13YO%'GKIK2!G`GQ%-$F*\N;9]'%_W#SL']+LC4G9!]NXS8_AD(@D&02"4\70![L$#/,+E(.1 +MB2&2PSAD1G,@44P9@-)EF.JP.;-::1%88G(@WM.$[$Q$>3(E-(:9!XF.L1U* +M@(P1!%Q-$&P*W04%4:B3I"NSM[U+-O?9?G][VE7OY?G5WN2>K-NZS3W[$(GT +MLP:$4W"D3W8)M.1(Q8#$$;8: +MG!1[!\NSN!;%[KACW*J!N:"'?R")_3Q7SO@'J_0*<^P1BNV=JZ=(B +ML&3<^7A*$P$'),`3N``1;P'AW_HQU[U-/K,I'I?D<:$"25?_9?MXV-SOM_DY +M&W%/AFU]X)YIB"SZ&0)B*6CLTY0$FO*/DL+1"601S9(2@3`HPIDSA".=:6IB +MX)U#)T)HFF)).;R`F=B'"XP\$+'D?8N +MV6^SS3[+TFS2):K;>L19;8@2E%4#$BFK]PDHR5K^*9)LGD`)(O93(A"&0L1> +MADA$U*8F(AZZ4)(,=DVZQ!#H)>,2I?F%$D^]8O#BV6]/%\]^)&F7&"H3HW*) +MH18ZDK0/N^1PG#Z/V&SG$U^;H8F0M0Y&I6K;%ZC\-ODF2>]@LD2HIZ2`&8)$ +MNRXC--(U4Q`3XU8J.R*#IIV>QQ02^4PA&8,FQ2&4PG55@9:D.4(*8:D$A-O4]`*=7R3Y%3 +M\P1*$*^?$H$P%/+U,D2BGS8U$?'/A9)DL&O2Z85`+QG')\TOE&#J%8,7S7Y[ +MNG#V(TF[P%"9&)4K#+70*:1]W.8O@2:QW-0[RE8#E$-L&8]%V+I'*#6NE1U15AB>!U"X&1F)2!I3)-4+`HR35DCD7,X<1'AT\&JY1)PTE*&Q4`9 +M@SD?!5&J;"@JO#@;@]`UVAA.VH/&A->H_&E,"X)'[DWZN#]N[G=H#]LV])CC +MW>#GH'D;78CJ2F^);J&;,PG78*B`.:"LI5$ZI@2DU:R*P+J;Z(B1[7"U2Q$7 +M[9G#8NX\'GH^ZK(LA%*,?"NA!9.S%%K8N;UVS%B/VHO'O*!$E..0[(];P-VF +M$\W]UY`V$3/J2+,/637I>L[S-NU<"CJ<87W,B'\UO?-$%I0")=N2@M`6P\^B +MX,>ZD*4X]2@@0([/>D0P,\DES$Q7MF*61@TI;FS4X`L=+_PL&%K-_2P9/R]` +M\AW+9="'HD*W'&,]DF3NR +M7YJJ!3%)L*=3/BI9"JS9I7?V,_:@7&$%9COM+OGEY_:]]MMD_/.9O8!Y_V,PW +M/3$,7$Q)AK$Y*F+J*<;7&.:*[&G&YET,Z^;TR48DX]R833K*#9,;&\1=KV\9 +MJL*\>I!<%?3HLY,5;QU,Y4>T#>903,M@#CJ+'X\6@9]&#(K*4&E2]I+J0L13JM8.[4:UX).E$Q8N%%M"D5HG1VS9F"V06:Q5<&!L'X_&)@!4X@ZVF? +M%_WL9,5;`5/Y$6V!.133(IB#SN*' +M(P=W?/XY\@5$588T>]CF>+^M-?-2%_2!RZJ"%INM"KV>HOV(/E<\/V*9=UEL +M#](G&Y&'[7XVF=C6)S=*:#M8>S2EEI!H66U>PM4&SM,XG6O@"X%%:N![X-0&_I):\IUO +M:E094F/?<:7-B8#HS_(NMWZ:I&()8)7YXAYMXN+%J@M5RR4@UJQZSL!9[*H@ +M!3DZS7C14S^(F%+/^-:T2/`:LV\->D%0R'U^?$RS'.A;ZXV]XW4S2#E2UQ%9 +ME&Y[A5+\9@[H:C^813F`*FF1B$,'9Y1MW"A^RQ+LTD#V6WI$7&5X4G` +MM@M')*W:'Z`T*WFGZ+)IVB18J*>"'81"02TS)`0JTQ$1_=8M0C*?)FVA[X22 +M,822C$(IHUHC>%G46],U48\C[0!#HUY4KB^TPD:2-,\.QQ?3-J_:S">"U@,3 +M@6<5BTK.IB=05:US39+4_CR)X*T;/B\""6QM-FA4JY,?$]#6J#<:=:;-F[?< +M$;)M(N3!Z5I3#@11ZYHR%*T+(N[3`@!97-XL@`*FD'%SEQY_W& +MT5(;KAPVU;`L@NK]0\FJ-B]TA35/KQP3^ZD2"T8G92]S#&AJTQ<=/5TK7C8/ +M@:8Q'")*6LEYF$C09[VVJ%+=C\)5[7Z\>1QH/+2-T*W&LS!P)'^='?*]Z:54 +M$S2WM?.(Z=:A2W#=%IQ(=WM?@=;!.E\4`S$]^1)4'DNA<$@*H4*-PU@LNGT8BRKMKG_F>(1/L/^\D)AN +M'/7"4UL[/W5"_I6GMN!\E:"]%-(Z7TR;,N-K3\=2*!R227&1%^A9ISA.ACM= +MYD*,Q;CQX"@K[L9GY2S51+!?X3@62\1$S/X6U)\Y'K<;CWHA494";<-]5H9Y +MC+>4$M`]B(SYF-E<2])8!,-B_(W:0#M3M5P"(DQR"`R4ML72%"3JMXAP"ROV +M(IXW?+Q&ZFO#7Q`\XV]SNKC:U_]H#0S4`X,*YC(,G;[GE"O9M<8J1ZD'\.YI3AT5IB +M`-:-%D6K)ID1@&F1NL%1P&K>_.,`SY;Q2`#2E79:X2*B-,$KAM)8RC?Y!)0H +MO(Y/!0@C4S$!VVO;MX?'7UM=BK:1!XS2!\7AE!8)2:M>+R942,\Q1HLLL\,! +MSV#8G/88"/6S@$*1GO`(<+12A5'(8G4^?K.%YX+DZ`(2I%X!P&5IT!`O3H,0 +M4AXI!%1%X9U"*%@4^>X>#^F4I2JW\8=ZU9`$D%<&HA&O[@-,[*K\$K2N-S$" +MA&J'S&A.X%.3`0J>JE3'PZ9%2XO`DBD3Y25-1"P4FR<8/:IG'BU';3NR&K41 +MA-V3MVR*R3EY6Z@HTKW(M_8OQ:C;^,.Y:D@"E"L#T2A7]P$F;55^"=+6FQ@! +M,K5#9C0GD*G)`(5,5:KCX=*BI45@R91K\I(F(JZ)S1.,&-4SCQ:CMAU9C-H( +MPJ[)6S;%Y)J\+50'B==4[&-1YPKAR1!N2(0D7)5'X#25N:7(FWZQ$B0 +MJ1DRHSF%3'4&2&0J4QT1EY8L+0)+)EV3CS21<4UABU$20 +M=DV^LBDJU^1KH:)(EP!<4^(7YQ(IUY30*9=@I"VA2ELB[IH2'ID2(ID2!IF2 +MR%S3HJ5%8,F4:_*2)B*NB1J2XG'"Z-[%S3@J5%8,FT:_*0 +M)D*NBF@"D>O04'I5)C@=&R]44GAY3-LE#?HB8 +M)"9!,,I333E:>)IF9-UI`@C[(R]A%),W\K)`461[W%XVRN^_ODRYI&$#?YAG +M&*P`_X91:30T]0ZFA(8Y(>CBV,P*P,Z<)JE8!!`:LT;!HF'BXD&DBU7+)>"4 +MTPN,@2(N<$8*8@385%1H.38'(8NS.9RPEXP*KS%YT*@6!(K%A&:$EV!2"+,"F8,)^-`J`QN1#HU@` +M)#(7=O;TN,U.>Z@%55KX1V=UN()X5L+R"*WU#R?SZKPPE-XXO8),[:5*+!B# +MK'KF.'!5IR\^NCI6O&P>0LUJ,$04M:RS,)&BVUIMD:6[%X6MWKUX,SG8:&@; +MHYN-9F&@2%[8XI?;;)<[7;^\+4;F@!9VV`TJBI]@0J4AO/$1:J)C0O)CR5-X10\1'L9B!D9QRKM%B4[4>?F!R1=X6)(AG@XPQ^O4U=ZM,,]#>I8]Z>3WUYOOAG&7AO/B>^ +M^)SQWO/(/LFP7$WAZ3%EA#SDAX@58A($HSG$%]RSWV\_TW<8O(113)[(RP*% +MD6W_\)B_V;S.#KG]VIVZC0=DTX;$`9L:"$DVO0\30J;E%Z-DYHGA$*D_9$9S +M#)-Z&4!!24MU!$Q:H[0(++':))]IPC-*4CP!*9$^\W`IZK?#:U$_@I1;\IU- +M43@FWPL52+ICGKVQ^Z7R5Q_85@V#Q;0R!)9F]7ZGQ*O*(TJV>JEG\:8=&JDA +MBC'-2'%TJ=(8`U5F+QC4NK=[&\]6/M//,-8^3!KJ^42(0MN"(`=M6S''X@E! +MXG`FGA0>@D2;4YX]C-UUK6_E"Y>Z8;'IU(:B4$KI!T1XNCRC!<@P16SN:$-G +M!4!S2,T$GD==VF.ATBJ%1N+,N//QF#0"3DB(-7"!4NH`*51:2Z)@:3%$'5,` +MY(K'4050N$`27O)MGF>;^VR_OSWM[)ZKMYT/+.P/C<7"7C`L#0=]F9+$?KY1 +MHFB=+!;%#"E@AD"1;)@1',OZ4Q`#RU8N.R*#['XL``HQ/9DPAV#R-J@*A,`9 +MVA(DSA!%S)T%QK4X7%I@A0PCY?TAR??9YBX]'W.K5=,V\H"0^J`X<-0B(@ZY^%E#`;)6JC`*6:P&S&^V\*R7'%U` +M6M4K`+A0#1KB56H00LIKA8"J*/Q5"`4+)-_YK?W%`>6//G"N'`2+;D4$+-6J +MO4XI69E#E(+I66!`/"@Y&GA?'<_$VRJM+V1^W#_O-_GB7[@[' +M%U;?86W@`9_L@^40RQH52;&1WDVHDWU.,(H%F%D.O$;3)!4+`[FQK*'`9Y^X +M"%#H<-5R"6CU8V$RD.?;YJ<@2&Y'B@HNP:-!\+(\&D[*&\:(URB\9HP+`D;N +MXO7IFVQ_2I,?]YG5L.I;>4#HWK`X4-9#(4G<[\>$G/?RC-%PVQ1Q>#@<.BL` +MAGR#3*!PUTM[!(1;K]!(G+':0M])PS.`DJP!*5N_#N!R-FR)U[!A#"DG%PJY +MHG!GH10NC(3IX_ZXN=\>DG-F?PA2V\@#"NJ#XB!0BX0D8*\7$QJHYQ@C@9;9 +MX0!K,&Q.>PRN^EE`T4I/>`2H6JG"*&2Q6BR_V<(S6')T`:E4KP#@(C5HB->H +M00@I;Q4"JJ+P52$4+(9\]N<;F]^]H1WS><8F"(EP@`?)VGSB-4WJ>45UB,2F +M>/;@G]]I4QH-;^8O'R03)HR07U20L#]T+B`T!/?XE=J&JARRSPWZQI>('(T_ +MA8@AU2&9.AU4;.$-J\KA\%E5A"'1JMH_2(C*O.*E2)\./FN:H9(;XWE3CYQ` +MG#*]T1!GJ6)"\V+"V_A'#`E_PV,&0EJJN<:*2].**B]->UFGXQ]](G(\_A4F +MDF3%+4S3[J?>5<,2(5H9BDJUNA]0`:OR3!*QWA2)<*D=.BL`B4]-)FB, +MJM(>$Z46+S029Z9=DZ>D$7)/`JS!B55=!P3!:ELR1*N-(>ZH/"=77`[+\\*% +MD?!Q>T$\J&C>V@,N6H;)H:,Y))*2MGY-"*9E'C#".365'-[94R,2",,_:Z90 +M'+1,4P0T=*]`65RS.KW0R,9S?G.R#22HMOJ!"ZL]`EY@[;&D'&(LQ(S"0<92 +M^#`29_OM;K/;YMM-LLU>V,_J];?S@+V#H7&8VP^&I.VP+Q,2/<@W1ISMD\6A +MH"D%S!`8\ADR@F+>8`HB8-W:94=DD-4'AD`AGO>3YA!(]H95`1<\4UN\U)FB +M2+F[T+@6A8L+K9`QI#R<7DWXM&(+;]A8#H?/Q"(,B8;5_D'"6.85+XGZ=/!9 +MU0R5W!C/IWKD!#*5Z8V&2$L5$YH7$Y[*/V)(^"@>,Q"24\TU5FR:5E29:=K+ +M.B7_Z!.1(_*O,)$DN_[_LFL1I-F;39YM?]QGIVURFK9#YF8^$<\R1?!H3U]LA%)X+1FDT93R^3&!%@?ZEN&JM.F,5BN"MG+ +M1#XF(O5\6%L4*3=%X:BX*9Z\`XZ+MI&YW;@6!H+D^\O5&=_9O]NN +M;>0+K=M!L?'<1*(0N>L%1-O;'*/E?#@[;""JP^:T1V-/R0*>=&W"8T';\A5& +M(HBL>'>5ZP"/(57NPZ',J1$)A":?*5-X +M!`ZG*182.E6@+*Z-6[N`R"9@]F9B&UQ-#?6#E%5C!**^&F.).L,(B!F/>XR@ +M\'$DSO?9YD7V]O`XZ2Z[+3WBKS(\"?)VX8C45?L#%&LE[Q2A-DV;!!/U5+"# +M4%BH98;$064Z(B+@ND5(YM.D2_2=4#+N4))1*'%4:P0OC'IKNBCJ<:2=8&C4 +MB\KYA5;8>)(F8*>7^,C11-;I)5R*)GB137@BVY\V*>8E$LQ+6,Q+V,Q+HG1Z +MZQ4AF4\@I^2)*>?&*1?F +M:B]UH@&9K-4SR:6N.JUQTM?1PA;A*,:[!D52<3\[&TNITJ_5' +MS!D=<)2DCM4I1[EP\$IP/N_V=^D.9J3;C3VC?C=(*=2W$1F$5WJ%\!+='%`M +MA&$6I4"KI44B#A6K:I;(-.TF*#*$.E"9')*!K*S_+),SKK(T0ZNM4C@TD=4" +M\+15"S6'%PT5D='YS%`+'D/>-'O8YIO?33_^KFSH#6_5P?%)JT0C45;K#4B5 +MU9SC%=DX8WP(]M+`C8&'GYX5`OC4B8@&>:M6'Y5($S[0=R9)^#])*B%D4"L. +MK`3V&E/EKQ=&UNN%A;F(O%U8!8TGYS8#.;GK9IXQLQB8%"^OL1BT+'N"T-`B +MUU0%U>9)"FOU\'D1J$BKLD$&6I'\R&"V>+W1J`-R:WYR1\ZI\QC51YG!I(7`M.J<60B&32%E<5]T?MP]3=]09&OA'3F6P@@#MHO)(JO8. +MI['*G##$UC2S@E#4TR05BX%)+6L<7BH3%Q\V7:I:+@&AIC$0!HK:R!DH2-%C +MM:C(PJP'82NT'FXFSQD%7F/TI5$L"`*Y'P_I9GM_2&'&M=W:-V)WPQ2#=1N2 +M0VJE7QC9[^:!K/F&J13CJ)8:D4!D@JJ9HN.SFZ;8R.E$@;*X!K.C`9!-T(@* +MLPVON$K]$.56B\#46BW6+,XS8&+&YS8#+GPBB6\/1[C!+#;VD<+E($417$3D +M$KCJ%5:[RSE@2;<^BZ*@;-(B$8>%R3I+/$J6$Q0C(M>M3`[)X);2:Y8)&THQ +MFM%4M2H$32[F`NN:FOS*8W+.CTRD;C(K++%AF8Q69%"<_4ZY5$.Y3#]YIR\RY0C +M'5EXRS+B26\=0D9\ZV!S^LU0`1JM[PQU`3#(?`N\P5/9WEWJD$E2#S +M+?8VN?^_O;/O;B)']O_OW\FKZ,WF;`A+D@&&G;/AL'=8AF4Y,P,<8/:W=V'& +M.';'\<5/XW:(8>"^]JO'EM3==B15-;8D.+L3/TC54E7I4]]6MVT]'N#J?MK* +MK9T5%R&9`G/T%'CCD1ZR5#FZ!>D*9)Z;'`V<>BT(4D3N^5?D4\#-:Q4;2#7Y +MM,5[.1/@:;K*-.*%`"'UAUN.\I1T");4=++XH"9644C-1N=5\VE,X$7?B"P^ +M5(6;L&S!LO6N!<$@-R##V[2E;0/E=ITJNC()D8QB,W&YB,`:#S`]=\(*CI5 +MA8N03(&9RCT&1RH-6:H\W8)T!3+/3:P&3KT6I"HB]_SK,LLF8%D6-I"JLK#6 +MJDJ-F*?I*M2(%P*`U"/;'[LQ>X3*ZA'JS]^89C%H/7+^29)*7,"E?]3.3^34 +M785F#,S7$?1G)2KA2Y6P6Y.\8!ZZ:=<(B-B"?D5FHG_I'D%^QJ1N!:E\C]K\ +MI9Z4:)NNHDU@88!(/NZZ*EO2(UR.T^FV0'%B%H?B;'Q^XH#&!4$<&.%M@;7" +M56C&$%C+/8?!6AJ^=$F[)B*TH6U0F0@HXRRUP`1=6T`JXL->R +MLHV>MBDKV^@7!H#D2\<["I;A7EM;MG%'P1+GRMK2]Q+M$N,2[;+5.PJ6>%?` +ME@A7P)9(5\"6"=]1L`7I"F2>FW8-G'HMZ%9$[OF7YB7"A=0EZH74Y6>XHR!B +MGJ:K4B->")ZD=ONQ**-'B*QNX>>B#+-06GO^](X9%U#I;_,GHVJN0C,&XBO. +MSYJ8X4N1L%N5O&`>VFO72(B(K%];8*)?Z8;_7$[-"D+Y;O\7I!*B;9J*-I&% +MX4GR:;]G+VIIXQ#IS2:)BFUJ$4IL/BI7#K*"!/> +MD[S%N_DWG=,/P]FMSGPVMI>3E7XATK@Z=50L5XQ#"5T;JVN!K\8+5.M7!A^5 +MM@TN1#8)8G#=HS`<5T.<(I>W/,V1&&LO=".D+++\;9FS?AJAEH4`N=!@"T$Y +M-%AM334GSO$T%7;B"PE2*09.7W^@N@1;'0;X7X"@[*)4A('?I\BUV,"%2"7& +M^(@NW85G#0YFZ3T$)@^2_2*$;C2-AKE(3MS*E8X6J+U[6?#?;@6 +MA@ILTI+1N1]9"">BFBH-G8`M*&)6"_L6[)WYT'E2VI1&D@BW- +MM:IU(\=KNIHV\@7A3NY\/%N\MQ*MO&5@I!;3PP(T-P<@LQR/0XD7?O>M[=6P +M8;%2N0)LQ)>.I6>\L2C"D1@--Y>$WGRRDI0A$PI/1&(QRKE*RASQ*X^J-ZPN +M*CMM*,28J)><"HPIL=U).EATYV[?W&7V"(RKE>EBT=4T"Z!L=7P.Q;@2%]^B +MO"J\6*RLNPK-F"\[:Y[S9F@E?(F1=/N2%\Q#*X49$Q'Q%&=;3'0NU-7<\BO8 +M=2NPPEVWUX8R38FVR2G7E!:&)\D'=K^6(-N&R.X!XJ\D2(-06KO^@'WI?U#A +M'[3QJPBZ2Q#,@*@)_"WP,C0IR)H3B5]^Y13P4_%Z?X02 +M.FCOEPUB9&*:ZC&R1/)BUIT7#M?71?L062RGBLIB811*XW)LKJ5@S.@5(5W/2F)@U+`.)6QFE8VTV8P0I +MTRNBC0G0FMLP[4&P6O4BB+!F0!-$[99F-`8YK>5H7.S$%:GMT=.KPE<2SK_8 +MUPS!ZW[-9%O:-D4T)ZF#4UPP?N1?3N=S\M=:+LOV`=*^G"HFYJ51(.'5V!R% +M1!D/B(:H!Q63NKJ+D$Q!6*MY#(39,F0)\G5;TA7(/&NA&P/U<.4M-O>\:K3* +M)O_RK-N`5V;=6ELJ-G:>)JE88U\(7J3^G^EHF"\ZIQ]NV>I3K4=XK-:GB\AJ +MS2R,UL;XW`J_'A=`Z6\,+R);*ZY",P;@J^DY"&'U\*5'V"U+7C`/;;5K-$1$ +MU:^M,-&G=!NYY5V\*U;`Y;MBKR4EFPQM4U2TR2P,",E'T\G`4=JR+L&2G$\8 +M'^3,+@K)Q0B]%`*/#5PB5&*,C]S277C6X-"5WD.@+@]BLM#=HAR&T]%1Z,;` +MQS:D+C8A`35=I!BTJ)=FL*IZ:;!=O9L&?!/6O&DL$`C9YW-'U4LZ!,MT.EE\ +MGA.K*#1GH_-2"C0F<)U@1!8?ML)-6+;@H.5>0\`L#5RRB-V*K(42T%'9AL[` +M-E0M)@4!!9LE%;1<"R-8Q5J8:U?+QHW7A#5LW`L"0NYW^;P83B=YWU'"JG[! +M4ER;.C[*E7$4HNMC]1(*6KS@>J$I^/@T-EV(;!+.9L.C"(C60IPLI[A5#98-K"4@^FU795=;H<3UAQI[N0O"K%?.YR7[!H +M'5Y-D--$K`/")(S^Y;C<1(>,`T!JU$*)R%_--2B&`*Q5GH(05H8I/:IN08*" +MN&:K>X,G&ZK&166;3QDN\\>[^&H6P"57L]628HV6F"DJT6@3WY?$/;L?-2@; +M!TGA'N+/&906P03N.7XSO(H!K'3WVO@)`\,M&'9@F.S!OFE;!2A)1&XT,R$D +M`R*U#%^25-VFY`7S +MT$&.QD%$;&&*ST3/BJUR"U*V=2L8M5NWUYYB38.VB:K8-!:&+\G)_\;3=_8W +MPNI=@B2YFC`NR$N[8))K(W16""HV,(G0$&-V0C<:(J+*W%:8Z%/#C=SR+N$5*^`*7K'7DL)-AK8IJMMD%H8[ +MR4?G72L]2]L%QFPV-2Q.4V,`.O.Q.)1ZYF_?`F\&"XN2T@5`$[Y$%![QYB`+ +M06+LVT3:>3+(2D.&2B$\O8C!(><2R+/"K_#)OK!R)ZVTH?YBX%IRJBZ&1/8B +M9>=L.,HGW;'=)Y2,#N&14YLL(D"551A)]=&YU5@M)H!BVQ191"B:;L*R!<"D +MX34(+[7`I8?-;ZTGE79A-(^`*;9IK27,F@=<4 +M=6D2"\*=W./%/+<3K;QE8*06T\,"-#<'(+,W5L&&Q4KD";,27 +MCJ5GO+$HPI$8#3>7A-Y\LI*4(1,*3T1B,L+BH[;2C$F*B7 +MG`J,*;'=23KK+JWODY1M`V-I.44LEDJ#`)JJ,3F4V]+_O@6W'D`L`NHN03#C +M2T'-0]X<+$.3&`,UA8U),N`)KP +MI9WPB#?I6`@28]PFTLZ3059*+U0*X2D\#`XY%SR>%7[%3O:%%3III0TU%P/7 +MDE-O,22R#RDO+=7:97B#+)4:V%2"%.MP3GD4>0N`47N$J7(7;:HUL+G6H)J+?Q$=B?EPG)O +M;1'>6>T">+<[ +MOW&H:BM'(^0JJEAMF:P^"J">?MZ"H,D46!\T&6U)]R8-[A0U<](+R*\R."OM +MD&M!.^H:B_[^B@-':[2LHC$QC`)@-/0FK9:W*&NA!+16Q7$P$%<)XU/0JWBC +ME&WD@OU9M&X*>$U2TZ:P(#S(??K!3K*2=J%1FDX-# +M&\%"HZ-P`="$-PNY1_P12$.0&O#+(3C8%2"%$B(G#(O?ZQK/`L>Z(O +ML-H)*ZVHO@BXEIZBBR"1/4@YL%1K@_`X.N97,`*9N#5M3:`$ZU +M`8!J`R#5!@FJM0VDG2>#[-1:H!1"5&L(''(O<@-`D1N@%+E!BVHM`JZEI]8B +M2&0/4HXLU=HH/$Z.,-7:"$;)D6O9'$'*YJ@5M3:"4VT$H-H(2+51@FIM`VGG +MR2`[M18HA1#5&@*'W(O<"%#D1BA%;M2B6HN`:^FIM0@2V8.42TNUM@R/DTM, +MM;:$47+I6C:7D+*Y;$6M+>%46P*HM@12;9F@6MM`VGDRR$ZM!4HA1+6&P"'W +M(K<$%+DE2I%;MJC6(N!:>FHM@D3V(*6E6`N/DIA2#49(UXH)*9BMR#0XS0`P +M`[(L08GVN?/-CSIV\BQ([B"*,S!YW"L:H*"AU+,6=5G@($M/DP6>P.YDO"B< +M/P5;Z1(8+ZL3QB)GQ2Z`HK41.M36:FQ\Z^S*&&.AL<%=>-9\D5GWGC<^JT%, +M#*1;F<-P.EIIR+CXB*`;9)?`;Y!= +M)OC-V)M(.T\&64G*4"F$)QXQ..1`+Q1>HGRA\++%;\:.@6O)*;L8$MF= +ME!^&,RNU1ML%QDDV-2Q*4F,`2O*Q.)1-YF_?LFD&"XMJT@5`$[Y4$Q[QIAH+ +M06),VT3:>3+(2JV%2B$\M8;!(>.1LX6JR815&4L^K<&9,`,6VS:O(-3=AV0)@$N<2AAFX]+"Y35D+ +M):"M:(R$@:@RL@4*^M1C^*6PFA%PA6[_.G$J>$U1ER:Q(!S(/>K.!U>H5=XD +M%#:+"8%9S.WXT%>.P*9^"]\Z5^QJ3,#H4]/U[^V,MW+V[D`33DX%8)\SI]SI +ML5[I!!%7CL"JQI9_=JVL]1'"^Z5,'&7"G +MFN8)#Z"5;D^&9)M(-"_.7"'>PB4-AF3#88U#'5-YX%K"])Z^U4NW@:O,PB=7 +M0BHL_,1U(*'EKEMX9["8NVVP\U;7G0W(KD8KNVOPDTK`"27P9#+!W;1-Y9L? +M==8+L*"Y@R#!T,AC7\L`&PDHFP@M[I!%`K)TM%@D">Q#1GJ?V2*_XOM#:JV# +MHV0Y33Q42I,@8JIQ.970,@[^E;0>2CSNZ:Y!,>1/0914U7^^)96W0*TPNJVVE&*\1(S0149;^+;D;B8=>=%WCGM +M%L/>2F%I-`J`NN:D(*@U+#D2MC***VJRZ6.74KPB.A#@U:8-Z>^"MZH7G*AF +M.CP!E&THPWS(LE+:A9%@1\IBE'\E7'<479J_C9I>ZM"A&$5_6I@PRX$*OF +M"2=D5=R>`+$VEVA>G%DIL4(G#4QD8;+&JFI5\\"^;-5[NM>MN@TLI14+N9)0 +M6[$DKCT)UW^1AFH1"/\0OD9#F?&@GN47'FA^=2UXF%^A84[5N[,KD_P^LJZY +M-Q$2?;YDJQASI5A_+%:6LYF^7@K8Z6!!*-;D`:,*%6`T><>)6 +M+00)L&O3:>?)H)6:*@8*P?05-H>L2EH]*^P+6U-?]_+69`5+?<7&M21466R) +M[$/*3C[I3?O#R/951$$7UL3F55RT>_F6V*:AX-#1=A&3* +MGXZ&QP"4U$*6'"NW)UV!S+-4B7%0#U,UXG//H_CJV>1;A$T;T&)L6FM'7<;/ +MTP359_P+P8[4E_/A(N_TA\7;E8)4:Q(`C?4)0?"KV7$DKC&"*ZJU[EN7`MT8 +M$PCR*M/U[^T"-G/V3BS3G9P`O#Y[3KG38Z6T"YH*]DZ9]WAZ&*^YCIK4]N@2*=-$0=XRJ`W^?0Q61<\ +MS?]^E:\I@#@D,UV"8,:/;8:'/"&GA28IUFT^)0'LLI!GX=,+2[#A\LNQ0NH9 +MXU,JS?Z0FFE:PE=W<3(Q,0489Z([D_:\.^^/AA.;;335-BS.JBDB4;8TZ$]9 +M;4SV)5GYW[,D-P00B8B&2Q#,>!)1]Y`O$55HTN+AQE,2P"X;E1@\O=!4(BJ_ +M7(NGEC%>Q=/H#RJ>AJ465&*43$Q-)4:9Z.ZD/2LZ-(9$:A;K?N!J39?`J%N= +M,!9Z*W8!!*Z-T*%J5V/C6[Q7QA@+H0WNPK/F"]2Z][RY6@UB8G#=RAR&T]%* +MCL;%1SQQVAXAG2MX+<7\"GF#&5@];S#8AGY-#;[):=O4%H@SV4?3Z=N+F8W< +M%2W#HKB<'A*ZA3E_8I?CL9U;\6-B1V:JX`&_$DI?*,+R!E.-*BX@:3 +MT)M/-H(S:$*AR4LT1KG6RC)'O$JDUAM4&34[+2C&J*B7FAJ,*K&=23K+YV.K +M6R5YP[`H*B:'A%!NS9^@,BQRRNDA@5.8\R=G.1[[DBK][EE3:V%#8IWF"K`13]HIS_CB3H8C +M+=IM,`F]^60C[8(F%)JX0V.4:S4L<\2K'&J]0?50L]."PHN*>JFIO*@2VYVD +M[)?/K)0>;QD81\7TL"C*S0$H*L?C4&2%WWV+;#5L6,Q3K@`;\65>Z1EOYHEP +M)$:\S26A-Y^LE%[(A,)3>EB,2 +MOA_;?DQ9-@V,I'*"6"`5]@`D+4?D4&FE[WU+;2UV6.C3W`&WX@L_Y1UO^LF@ +M)`:_C>:B/ZVLA%_8O,*3?GC$5H["NN\+EGO:U&#`EZR@U0&Y[`*[WBBSL1 +MB+10MZGL\R62C=(+F$EH*@^)2JX%4":'5_E3G4'%3YEI0=M%@[G4-%TT">U" +MSK/A:)'/.Z=_^8;]`,A5EW!KS8-A:'VB<([6;'K1M&%D5K6V'@OWBKLFGG`< +M-KH'QY([&IN\Y0'(>K"2@>26Y2F,HQ)@XAZ$8VR*=0[%M2"/7DMMHPK?P +M-AK#U9-I`#0AG9G&`O`A\X?A[):E]F1-@^,QGR`>B9D]$(7%B)QJ./>]?_VN +MQ`X/D:4[X%;\T2B]`\`B#TIR0-Q@+OK3RE)#ALPK3.V(12R/DBE2Q;=K"N!+<@ZSRRP+MI .C2ZJFFBX;4T"2&L-BZ74JSBX%V- +M&T*)QD7#-2B&O.FH>\H?D"I,J1%R*Q(4Q#4[T1@!V1"E(S+;W.NKEC^>)=:P +M`*RRAJU6E&3$Q$Q/54:<^!XD'A"):J9@Y"73$>EV+-_>Y= +MJ"MA0V-BZ0JP$6\62L_XU)4GYGY*([=M!\6I\0V:I/&96QFF$H;8TQNI9E +M/3Z@`MT8:%1R5ER&:`Y$4].#,*[JH4R1KUN8R@BLM->?$=$269.VQ$N_A.!R1"[J +M0/C>6Q148X>&4N4.N!5O<);>\>>E"$IJD-QD+OK3RDZ.!LTK1/&)1BSW"BI3 +MQ;-PJN[`>JD,M:(G(X-@>EHQL@3W(:N]#`R2JL@B$$Q4C[(+K+IM"4`4],'( +M!P=?FN)O4TGHS2=+X1@3"/AB,]XFTH +M";WY9*OT@B44JM)#891/060YXET016]P011V6E)ZT5`O1:4736)[D71JO:8J[IS>%GB]/W;=3IK#ME&E+>WI3C+/;*>CL=@H^NYTFN:>WH23TYI.M +MT@N64*A*#X51/@5Q"MKZF")M?4Q;W=.+AGHI*KUH$MN#I+/Y=##OCNW$GFP< +M&DW+2:+A5%J$$%6-RJ7FEC'P+KOU***!4'<+AAUO'&I>\B=B&:#4D+CYS(20 +MS$X6!L\R1'&(2C/W2JH2Q[.8Z@:`]50WU8I6C!21Z>G&2!/>@[P7%RX_^5*V +M#HV\:IIHX"U-0LBKC-?KAE"B<=)P#8HA;U+JGO)'I0I3:J3)EQ_LM"5I +M%QI[Z=30F$N,06C+QN)2HJF_O8NS$2PT"@H7`$UXDX][Q)]Y-`2IL6X#:>?) +M(#L=&"B%$+4?`H?\>);0Q;`B,J[@";,2#=B6.GM70XK=I"577342TGA19?8'B3M +MSNUT'FD7&D/IU-#X28Q!Z,G&XE):J;^]"ZL1+#3*"1<`37@3CGO$GV\T!*FQ +M;0-IY\D@.RT7*(40=1P"A]Q+'1(GM2=). +M/IXMWMOK/=$^1*;*J:)R51B%TK4):4%'IJ+D(R12(E,IC,%[* +MD*7(S"U)5R#S[#5D!-1#UI/(W/,KP64V`0JQ9@.A'&O66E.;D?,T314:^4+P +M)?4DO^PYB%/6/$A*\XGB(IK9!!-:C,RYTO-8P`I])9ZX&"W=@V,)!E'I+2!# +M>;"2!.@6Y"F,<@YR-'3.88M13-)Y5F"11I`"7)K`J+^EL?9T:+P`352#QKL` +M?,D\[;O(3]HZ2"JS:>(BF9H$$YF/R[FDLSC`*KH92EQN2M>@&()14W@*"$T6 +MIB2)N>D$!7'-07"&339LN8G'-L]:R_,'4FJE!8Q**VVUIS3C)&:B*C/.Q/<@ +M\6!RL;#];(QH&QJ#Y131^"L,0NA;CLFE;$O_>Q?M6@#1"*FY!,&,-QV5A_S9 +M*$.3&AQ$8_`L0Y2-J#1SKZA +M&8/2M/0<&*DB?(E2=7N2%\Q#)SD:`Q'QA2DV$[TKMLPM6-E65G!JM[+7IF)- +M@;;)JM@4%@:`Y`X?8S>[A$IR[`^SFW8Q2.[S&>%*;,`2H;4/MM?=A6<-#%V$ +M3V16@I@J=+VD:@_#:.'TDA(H36$4TA!R=QX;K4`V" +MJ:Q[$@YF%=94R;R5B8W"43>1'!%)6Y#*+;'47P]H>0>4!(8E)%5@V&Q5.2=( +MZG15=((+!U`)/I`'9X6;GA9]0JT!&,>A?CM%';LCX@,5&+=#H9-9< +MAF@.3&7E03B392A3Y?&6I3("*]TTIB@F@HY_8@!)HJ`:.S24 +M*G?`K7B#L_2./R]%4%*#Y"9ST9]6=G(T:%XABD\T8KE74)DJGH53=0?62V6H +M%3T9&033TXJ1);@O63O=TV(ZNB"OSKJ+Q6(XVJ@DT3SUF<[%G$=E&V,S,56O6U3UU,P +MU)(1(A\:C&&(B0:S[6GG+UA/5'-_65#>E:,WZA;%T/+G"\PN8=:*KAR&T]%%44?"1W05 +MW0(A?0N]2C%0B=?-H!1WW6"+.CD9^*:JAY-9(%"R=X:3?CZQ_+:SQIY!4[Z< +M?CNHE^;1B*_&ZRTKRKCAJ(MZ&K3#:MV5Z$9QR*UY%@G@9;B3IO@V)ST:?ST$ +M=EP$;DMNM\=@H+90.8DA,71KF$I#M]N^(D^;\HFK];07EG6G\0S +M>H19-^1TD:N%,`NO$N7XW,6*C`M0I-3"B\QJS55HQH!L5IZ#,EF&+TT2;U'R +M@GGHHJBC("*Z@D9GHF]A+W,+5-`U*RB%7+/7HC).@K:I*M\D%H8WR2?33I'/ +MNO/N8FKY^[\-_<)DNCEU9*X;QN%TKXS573J8\0(*B!7!1Z9RS87()H&$KGH4 +MRFDSQ&FR>JO3'(FQ+IHY.LJBZ^=6.>LK&2I9"!(.-5LH\J%FM45UG33'4U7= +M22\D[TKQV\5TD?<=OTJYN6N8U:+F`.1R4;4/KQCU$;NKEEKL@,)E=2X@H[W) +MG?A6@8!O\"Z4\;6@IPGY,'(?C\8NTCU2'J,+^,]`9%_U44]-D`!I,H>B09H, +MMZCGOT`_V>]Q_K+`H-_M/.LN[50];1A:S6"30ZL/U!JD&O#1N"@2YG-O_6%& +M#`VZT@U0&]Y`%5[QQR<+1&JHW$SV^1+)3MD&RR1$U8I")?>"R9/#LSS*SL!B +M*,VTHBTCP5QZFC"2A/8@9W'>G;O\W+/6/C2*ZE-%0ZEF%$)48VPN!5>/AW?= +M;0PJ&A4K+D(RYRF+]O<4 +M(P=HDCHSY@7@2>9BUIT7EA])TMJ'2&8Y550P"Z-0,I=CO1R-@'K(@A29>WX5NI+XH7*YWB^8A4EI,%!71W":4T')DKI5>Q`)4Z*OQ1,6H +M<@^.)1!$2V_!&"J"E2)`MR%/892SEZ/!W`L@?!9>@N&3Q&L%.&Y#7D*HYR]_@R><\CZ$Y5T?N57IA&@_"H3".57&6M- +M?T8,T#3U9\0+P(/,2UOEN0R0Q4M4M;D$TG?I7+F7H)J];$=5+A%PN(2`<`E% +MX#)%];B9[/,EDIU*#)9)B,H0A4KNQ7`)*8-+G`*X;%/[18*Y]#1>)`GM1TZ7 +M3_JHY@$R%/V3/LHFD*9>GZ#08@&IN.U]TL=T#XXE"!HQ;E37@I4@)+MC_I$SE`D]29,2\`#S)_&,[LE"=M&!J+ +MV>30&$RM0>C+1^-2N9G/O6NV&3$T*$HW0&UX@U!XQ1^!+!"IH6\SV>=+)#N5 +M&"R3$)4A"I7XFJ>8`,1=]+ +M5#:!-/7:H]%B`:FX[>TEFN[!L01!(\:IL!:L!"&Y%7D*HYRU2@R?<[B*$9=T +M7L46NI5BFH`7WK;W$B,':)(Z,^8%X$GFR;1#@SK/BV(XG=@+T4J_$$E=G3HJ +ML"O&H>2NC=55!%3C!5(#*X./2M\&%R*;!/&X[E$8F*LA3I'/6Y[F2(RUE\$1 +M4A99&+?,63^E4,M"@&1HL(6@'1JLMJ:B$^=XFDH[\87D4BFFLWS2&>?CZ?RJ +MC6"]93"UP)@>G/VZ.2_:F^.Q$AB&W]TE17/8X(RMN@)LQ)VC%<]XD-,(1S*D +MW'02>O/I"NT:/J$P]"DNHQQ*IYDCKL6RVMNW/%;MX"K+^*B7D$*,+[%=2$H% +M8Y$O=,78*1;3^57?VKZZ7S",73-U.&]7&_>B[[JQ6I7J-?%R+]PVP8=3=;T+ +MD4VZ$W>M1SWXNR;$R;`XG#1'8NP5VC5NRF+HVL_'60=IL"X+787">EN^LF&] +M55QU_(7C*H6^D#RYA617*:B=L^$HGW3'>2>?]*;]X62P4H,WMPZ@)JR8)J0. +M-)MTI/^J<5TA.E;$P45J7!5*"']7NP;%D`MK5WK*B;`KPI0`5;APW)W?K\I_L_DO1Z\?+^CS_2UT;$^,U[^\0?KW>^HD]NW=O7>O'7><`GV2Y[ +MYR;U]BY]/L?/,-*XM[>\PD_W/KC6A'B^9RN,B^9O98PUTRNI]^(.NE +M\XR%D:3X2[IZU#'V=UEKK=EN4[/=TOI-UO[W[&PZSX;9<"('E,PR*_(^-;5__/KHYJONX8=? +MKN_M'<^X%\^&[,\GTNSRG*1D-L^[_6S&+#(#VM+:VYN)4?3OB;3OW]M5N;Y+ +M\_=R.ORZ8Q[CXWO(WW$QI9G^Y.[Q8VCZ\?W'W"7\YN#.CKO\M<(U/3/$&7:7;:)5.E25QW"YD3?7/5F7JA0YL=<"=7?%@HU_%T +M^B#'6;"A_'Z%4T3;M6NRR1FRWQ6+E#GADS;]3SL[%Q.#6SJK?GY2H16#52.1 +M3,BPP=Q[4Z/!"AC0E*RQ3^^Z8NE_Y.Y8M_`_23"P]<.77GL+[PUW[7!^KSF` +M=T46E3YG];'HG,VGXPYMH=>0VRW5D-N?H8;XAMP.L8;<-E+Y=K(U +MY#:PAMR.L(;<]JPAMQUKR&WG&G)[JVI(;>';U!"\A;>ZAMQVKR%W6JHA=SY# +M#;EC5T/N;'$-N1-B#;ECI/*=9&O('6`-N1-A#;GC64/N.-:0.\XUY,Y6U9#: +MPK>I(7@+;W4-N>-80V9O!WR#B\:7%I/R!1[Q-26%'KO2VHQ:^689.@&$1B8; +M2+ZB>AB6RW1=543JX]`JB5BE-`MFE02J`EL`UP_9"M.N"]QE":]RC,4J7N$E +MR3,Z>'T1FXESQ6H&)(I8XDWQ$5ID5J[2<@%^_)6LP(\?5ZT3TTOVBV4XZ8TN +M^OD_'][__N'S%W2UB%D&\2[Z:M'L7KE6JF,(>Z5P/Z]8*\UN +M6=7U:B^M6BF5K+ERJ?@F21LK1??1U>MDY_'W=%'(@9.'+Y[^_/P!O[[VX^,7 +MS^C?E_C\X_&/#^EJD7/6VFF]&[KP:DN&\-M%SN=:+?NBHIK9.)39*#PQ +M%#G)GY99R=XH\U*O_7O7[O__'\BZ^IWGW*N]O:]_(2*5K(P):46_8(8_^Z0J +M^L,GWQ,=1L9Q338YR+A2N<;&S`P=9+/Y<++(ADPO?1)Q&+\=DOB#)7/ +M=6?1'10G&?7$S@[][TFVPM/B>M7Y$74+=]WW#Y^1P3Q\\N`Q;4#L?V7X5'J: +M2OE%MF0C.,_GQ+^SR_Z;\JQQ59S,`R8;L^)\>+8P:4U%^;6'S!/WGS]Z<;"W +M=UW&4\[M1#^'T1@O6M$5+ARWM\?&0Q;=\JX)W+V]/V:'`Z:)54V@TV>'/I`/ +M]"O8Y@O:$)4KR""^VRWS3Z):.]\"VJ]8EM5EN-/CJ?Z`Y?J#UG+]2TI?F=): +M%C_0LU@FI]SV$6\?R`?&O1+&"P\:,J%$W,XC%FP)'UYM>GW:;S&==4XOAJ,^ +M]0_=D:)D*K>GJBV%'\OW!S2CLL,A>?N1-@`2$'JDW9V=7M&;SO*3C/\]8BX1 +MT_]#=E@8K^NS?O'@Z;.'!]GA:7;XFY@N>TG-5W]*!F`8DF_SX+4>F6A),U"VHX]7+AZKE2`:\7SOT8T;)>)V:?HP;[QZ_?KXE^LD +M2?_KA#\\R`JJ)?2V=T4ZR_?(6Q>G/-UE(]$F+[J]E3LF#5)SN&N"3^A)99^U +MJ/%+RDXZ&KV-MF^3_>UOU>0[-N.A;B!AU"JC1M,L(_6;Y5OVZ#G_\^*_?R+_ +MI??79+1Y-<;3BX5\.)SHSV93_9E,A?.\]_;P)=%J[%2$/:`Z\JQ+WN_?(]6` +M:#3Z9TE?80]FW:*@#XJWP]D]OH7"77^OC`$ATG(VG2\R_ERK_N4QLGVQ9TM7 +MW8*4I-YT-)T7!S:G*C2D"_+V5;`\(A%9T'?Y.009X=%QN2M%\EK?1C7;::WH +M28>1A<9I!SN>F%/GX9-_/7[^],E/#Y^\I)K_=]+Z$[/,ES5O](_O.\\?$F'\ +M\,'+`S/E,N;K-\1U<]*;/,[^G-U\]S9<.,?;O?]Q__&-'.%*M(/KO^JO7 +MV>NO?F&'Y0^O\PK&XR:MLV?*_E_]^=O_% +M"VUD=[7'XGB\QV`^X3W6="B7JAD6PHIZ,+?I07/SQ^5KZKY;*DV>^D_2+>+OVC-H7ODQCN-A%5 +M:UU4FI/_9!7`&@/@SN5CJ.A8K16+:6.C+#OM3B8Y7>Q[Y%@\N@J,U["_+XFLS7\A7N +M$FKY8+<>;WT&^OCI3*_TCTCDZ5EF#DS$P,)-ZC#23V6-=U:- +MI4].@"?3A7!6S5<,@1<3S5O\.$V^4D*Z6YR3$;%K3/3XLBU==3.RT,NBK>9<=X4TI +M;KB977I!LI<=]MYDAZ-=O[^\Z/G#Y\]??[RH*+@I-UG1%D5N7B:+>@Y4F/?QJGS7L"9 +M"R,K4JFTQI_OBIVUXOCH^-[QX(T3YBCG=UG5;4*K>'?>$(0*^?E0!/QWF]OP +MR5?::!<25=9\K'85;ZWN6[J]UI6_LWYDC:-?X3UZJD!==$+IPJ4XD6U4"W__ +M^,5+N<58[JO*"WY7*%36O'$7M:Y272[A5\]:^MH>>?7R?CDKOF%;321MY'1E +M"?,#XM]LOWN:G>>CV:UQ=Y(-"[)T?KL8DJRABV>0DZ!W%SDYYI`6Q4&^+Z:7 +M_>VXG[\[GER,1DVG4OE\/B5^/9M>3/H9-4S[%G279-$=3H:3`>V3[8^'14&? +MR./OTX4[ZO;R<3XAJS=?+DYVL[_]Z=9=8\2'(]]!\\6V7QS_>IS)?\?[QA'$ +M%0'^CU@[&R[I6,$I+#9GC/-<.FZLIW]U=8_W];-@C%M\3 +M1W3?TDY#YIY\?LA.$/>SRR$YGC@*'43%F+K2DAD98*:Y..WB9CHBYP_D7DV? +MXE6^R-;@^"UY:+Q*E@3/SV(Q9]I3GB[+,_72KZ]^.7KUZ][>Z]?7?SE^3?[] +MZ7@@=X:FLT8;VNZ+E1VY-M6"W9>$)>]TM$L:[,Z1QJL:])V&"_7D/*+X2(ZJ +MC?/XX\>[BUV%^;*-.9WCC]5S?MKMC=H"(0NU'%UY:G+]^/J!?EE-U8:R[2X? +MX%?T\,PUQZ^/C__0OTO&\%$%B!RMN''\ZM=C?@_`OMZ)EL'#BS=-&R7*0>J` +M*^X[8DU);LBX0VN3=U +M.AHY?%S>ZF,*J[/AI+%==DC6(1DZW;>;Y71WY=NOOR:'7>:]K'<^GO:SBS_/ +M+Y?9[Y^RU^H,K0G2?6-#EKE,JA@R[^P/]S+-.^;@>H1J9[/G=0/:@&F8YM5+ +MK"W/K1Q7&3>+$55/\'CYJ@].-"'=Z6%F*P[2T-PXFK;YQNX*O/_#0[&13!^* +MC50N"L@*%5;O"?(H\&EOJ!=+KAR>3Z=O=[XZU"0I92J5-AWBQIQ>8^'MR?"J +MT6@*PYT[;(G60G%C,/WS7`2$?D"0C>`/=0/??/,-J8/#R=LBNVD$M/OGN47O +M2A;8=:*'9)WH55Y^/;'?_V4,2--0SC]<,MB#"-7%XS$C,D@?J1N +M>/KL)1M']?`C&P\L/S@=^]__H8>C\^>/#@_S3]GR0]/LES:')PW_XS0`^=TD +M34?\C\4!B_/N7#L@?9IIA[-,,-K-+L/,X(J->\T2>7_G*W:$^6^5U[6G5Q^( +M$XHLQY/5`.2"J?/R_O-'#^D&Z0J+]_:_.]E??\0_9B^IKB9.'^2+[((HUGG! +M-"\;"J,W%<1$%A&IT\W^Q:Y=\,NC%T0?TZ_RSHB)?$(L$8P/+KKS[F21Y]1( +M=U%:F@]/+VACJNZ+?'1V*,X=B"0X?4^D\EMZWM"=3$G[.;%$1D$/?<0OK]#K +M'-SU0G\)P=BY__S!/Q__BXI&H<*N"V!<%S5B10KT>UF-,>7M1LP']%)4:8^L +M?FE0$*)N@+198V%4CFBT8@"C=0-8EMWI`JUW7J[K_!_9]V*B+[GJBEMA0:P/ +M)X>*/AF]=8$M2V&+-%5C,9<%6R6L&=6T),QEL3F\-%:/+*[FJ_PD1U,97+L; +MK]`B)_M7K2K%5[5@WF_<[W5DK:1WI9G7J,U#B8O4AN[]]=6O)_3R*+](>N.8 +MR%_N#M*6F.[G4K3L_?[R)_IU!X?'B_'LTW%W3#Q\N$?^':O/9+`#7_;Y33KE +MJ\T#XG.1;8Z.CN4*SK/#0W$%\.B(/";I0;0/'4%EJJ5@8RBBJ^_!/Q\^^*'S +MX.F3?SQ^]//SAQU=FV6"4.O:L,&NT7=KWN^_&U[9AE'CRE9R%\"RG9W1\@:Y +MJR="(E2V9L8[(@%6N9^?7E5[E07?S7U4E0WP?2ROK=U1_L8/=(T=/$@\JN +MS\US]E^Q!\\>S]A_EXS">WNS??%@N;]3#R>]/U>>%^[SJ=2SXF!?^Y`-_\:J +MA\^?/WU^0H32>[8?.J47:+*][[++X>*<*)N,W7FE?=Z##F"U=;4QJ)T=?])N +MNZ"$]QA>KSNA%X]ZYW19#R?LBHK/(/B5%CZ4AOXT5.*^,GY]9?2&;]J+^;/1 +M\6P1`^-[::/\;)%USQ;Y7*WQD]WLKKY6C4WP\E;EV@:1OC][C>>X:)L5%S-Z +M(4*[<,3W2_G%YZI +M+%02P6PZ&;UG^45OO2Y5.2ORI;/XB#)Y4Z5(ZC=\5LK>5:%:&RFR++FR(-/( +M>XOI_+T(7GF,2O#6'5UO9[J3W^C4'9_0NT?(WW7G1=SLL^=/'SV__].+@]5- +MM;NG=D28]J[]_>?'/[[LR/O@KNI,1L('=)+]U'V;LY.EO6L_OOSQ\=^?WW_^ +MF-])5PXE$U>@**KYIW#477:OV=TD_)[3\M,FI\.)['PBRR;]FB+M`#NR,=VZ +M/N'[P'QEFY]7(+WXUI7Q*CE`PZOJ.S]6?%!\Q6?_UGV8:.6')QH_QBBW(8W/ +MJ.SQ(BKW!B4<'((F74C")A_2_2_E6_I,?[??7735N_09?5>!23&*OKZC'JM$ +M_>ZJP8ACUHZR8]0D0W_J0V37*TZ,6\[IC9POGS]F]VPJI*P:A_RXB\@TNF$J +M7V)6Y!L'I5Y2FX4VGOY[C[6D+]Q3;M\U +M9D78JW\1&KNN..R=R+M]U7-U)VGYFMRAYG=@L[.HSH,?']Y_(NY"9ZM$;D0U +MO"\-'+&/4VL7^#YFJPRS4G*E>;V5NHEU-IQJ7T`HQ<&<^&(\JS5;\V;EFPQM +MVC:WT+X@[FIS1N,KFUB.L=[CJG;TR^E<[/+VS:T6W;F%+=YJ]7N64]6:KFA` +MOS.0Z/Y186--;UQMHB4OVV6@.=F0LI7W=G:JE^2UE?8=USAL,[0W'8_IIN>0 +M7MQ=Y!-2J]AYB.I>4(%_0V:,S++F3&A2J7C"DM\"(#6#/E(OJ8I"/E1`5I`*J\))["K +MV_*K$#6-D1G?CRB>3::4<7HKTEOG'!V.4H%*$+*J6&Z>T\`*L)3!,K$RKW*E +M"1&-"WWU:EVUVLSUTI#[C2E<3D=JP!U]LBH\F@_H/BP5BS7D,WE3OGC>UY1T +M&0#ME6FOJS]G'RG8Z;\;GM`=,AX"]I=4E_/%F`@6^E_VNGAP0G7&V93JB[.I +MD!WLP)$.&W_CY<,T:'9WVQ%!.Y6@KZDCUT#/Z"DE\ +MR*>L/S,.IKM`3HR[0CTS.M1=,Z:IK7^[GO[DMO[DCNHTZY^I3N2)<0S^7#O$ +MK-`:%V;;PFA:GB75.7=2NQG)8QD:-_<<=R\6T_$WB_RHUR4'#GBQ-GC&Q%7= +M=V*Q&M]P2UQU99ZD:S$[/73?/I;?,I625'5.ZS\R>Q@R_3NMPX +M5I,K'[*S(-+WV3^?/OEO\60:<: +M*CZ"5Y90&4R+@EKVJ==4855]EB]CGXW-C,O$LF;P6R"R\F8,=:=+5MZ=D)57 +MSK/RHGW9?_DADQ>ZL_*ZJUH*#?7+J%9RRE?5+Z-34PFK[GB)W639L7+E@UX+ +MXG6#53=9XEA%DV5-JTM-Z=-45&C5T\N9J()ZZ:J4,>.47N]:/<5GPZQ4(;W] +MBOHJ)F34(KU;);9J6ZZ*0#=@5?#8Q6`KJ2 +MKT8G$[%7H]/L74'RSA^S[D'V@+F(?I"TF(YSTG^2Y^SN8\[S`O2 +MY91TF8Y&Y!6&T?ZT=T'OY&9W?;#F_.?=Z7T?U2L[_,X-1A]R>B0?G-\]N!?+^3M:6^N:GM4O)M4&J]LNW_]?_>O;D,_6&O3K#>=Y[1=[<:? +MX^O'VNZO]JIZG1#>N+>`>))>:SLF&7-,BM'%C-`E/RK.C>^CIV34OQ*?E"[U +MS)1?Q^IK]?^7/'Q5V7DHA_>+N,*GWF/7>.G=ZN+R1*TOTU1K#+`&S5:H)*OU +M)"^N;MU\,/E."M*.O +M%&QQ3,_8O4[BPVO$+KVU:3C1W^._JU$<$7-_IR?^]#HA63HLE&1-\<\.S.;3 +M=\,^N]>JZ$Z&B_=<;F33B2Z$F;05^P!T;9].W^5'#3]]0\>K+D[0NZ<6%1W? +M^,,.)-NSC_S3&=\__,?C)P_9!W&SOS7\P`4]PLY.&3R;0Y:-UQ^K8G-G1T7. +MYBBJ]?K#5*VR:.B_;Y;#(:2C?%XM\3-PW)@&_1F'YXGWQKXP,FG[` +M;7'`-HI. 0); + + /* See what GID it ended up with. This is our "valid" GID. */ + assert(fstat(fd, &st) == 0); + _default_gid = st.st_gid; + + /* Find a GID for which fchown() fails. This is our "invalid" GID. */ + _invalid_gid = -1; + /* This loop stops when we wrap the gid or examine 10,000 gids. */ + for (gid = 1, n = 1; gid == n && n < 10000 ; n++, gid++) { + if (fchown(fd, uid, gid) != 0) { + _invalid_gid = gid; + break; + } + } + + /* + * Find a GID for which fchown() succeeds, but which isn't the + * default. This is the "alternate" gid. + */ + _alt_gid = -1; + for (gid = 0, n = 0; gid == n && n < 10000 ; n++, gid++) { + /* _alt_gid must be different than _default_gid */ + if (gid == (gid_t)_default_gid) + continue; + if (fchown(fd, uid, gid) == 0) { + _alt_gid = gid; + break; + } + } + close(fd); +} + +static int +altgid(void) +{ + searchgid(); + return (_alt_gid); +} + +static int +invalidgid(void) +{ + searchgid(); + return (_invalid_gid); +} + +static int +defaultgid(void) +{ + searchgid(); + return (_default_gid); +} +#endif + +/* + * Exercise permission and ownership restores. + * In particular, try to exercise a bunch of border cases related + * to files/dirs that already exist, SUID/SGID bits, etc. + */ + +DEFINE_TEST(test_write_disk_perms) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + skipping("archive_write_disk interface"); +#else + struct archive *a; + struct archive_entry *ae; + struct stat st; + uid_t original_uid; + uid_t try_to_change_uid; + + assertUmask(UMASK); + + /* + * Set ownership of the current directory to the group of this + * process. Otherwise, the SGID tests below fail if the + * /tmp directory is owned by a group to which we don't belong + * and we're on a system where group ownership is inherited. + * (Because we're not allowed to SGID files with defaultgid().) + */ + assertEqualInt(0, chown(".", getuid(), getgid())); + + /* Create an archive_write_disk object. */ + assert((a = archive_write_disk_new()) != NULL); + + /* Write a regular file to it. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file_0755"); + archive_entry_set_mode(ae, S_IFREG | 0777); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a)); + archive_entry_free(ae); + + /* Write a regular file, then write over it. */ + /* For files, the perms should get updated. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file_overwrite_0144"); + archive_entry_set_mode(ae, S_IFREG | 0777); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a)); + /* Check that file was created with different perms. */ + assertEqualInt(0, stat("file_overwrite_0144", &st)); + failure("file_overwrite_0144: st.st_mode=%o", st.st_mode); + assert((st.st_mode & 07777) != 0144); + /* Overwrite, this should change the perms. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file_overwrite_0144"); + archive_entry_set_mode(ae, S_IFREG | 0144); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a)); + + /* Write a regular dir. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "dir_0514"); + archive_entry_set_mode(ae, S_IFDIR | 0514); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a)); + + /* Overwrite an existing dir. */ + /* For dir, the first perms should get left. */ + assertMakeDir("dir_overwrite_0744", 0744); + /* Check original perms. */ + assertEqualInt(0, stat("dir_overwrite_0744", &st)); + failure("dir_overwrite_0744: st.st_mode=%o", st.st_mode); + assertEqualInt(st.st_mode & 0777, 0744); + /* Overwrite shouldn't edit perms. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "dir_overwrite_0744"); + archive_entry_set_mode(ae, S_IFDIR | 0777); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a)); + /* Make sure they're unchanged. */ + assertEqualInt(0, stat("dir_overwrite_0744", &st)); + failure("dir_overwrite_0744: st.st_mode=%o", st.st_mode); + assertEqualInt(st.st_mode & 0777, 0744); + + /* For dir, the owner should get left when not overwriting. */ + assertMakeDir("dir_owner", 0744); + + if (getuid() == 0) { + original_uid = getuid() + 1; + try_to_change_uid = getuid(); + assertEqualInt(0, chown("dir_owner", original_uid, getgid())); + } else { + original_uid = getuid(); + try_to_change_uid = getuid() + 1; + } + + /* Check original owner. */ + assertEqualInt(0, stat("dir_owner", &st)); + failure("dir_owner: st.st_uid=%d", st.st_uid); + assertEqualInt(st.st_uid, original_uid); + /* Shouldn't try to edit the owner when no overwrite option is set. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "dir_owner"); + archive_entry_set_mode(ae, S_IFDIR | 0744); + archive_entry_set_uid(ae, try_to_change_uid); + archive_write_disk_set_options(a, + ARCHIVE_EXTRACT_OWNER | ARCHIVE_EXTRACT_NO_OVERWRITE); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a)); + /* Make sure they're unchanged. */ + assertEqualInt(0, stat("dir_owner", &st)); + failure("dir_owner: st.st_uid=%d", st.st_uid); + assertEqualInt(st.st_uid, original_uid); + + /* Write a regular file with SUID bit, but don't use _EXTRACT_PERM. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file_no_suid"); + archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0777); + archive_write_disk_set_options(a, 0); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a)); + + /* Write a regular file with ARCHIVE_EXTRACT_PERM. */ + assert(archive_entry_clear(ae) != NULL); + archive_entry_copy_pathname(ae, "file_0777"); + archive_entry_set_mode(ae, S_IFREG | 0777); + archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a)); + + /* Write a regular file with ARCHIVE_EXTRACT_PERM & SUID bit */ + assert(archive_entry_clear(ae) != NULL); + archive_entry_copy_pathname(ae, "file_4742"); + archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0742); + archive_entry_set_uid(ae, getuid()); + archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a)); + + /* + * Write a regular file with ARCHIVE_EXTRACT_PERM & SUID bit, + * but wrong uid. POSIX says you shouldn't restore SUID bit + * unless the UID could be restored. + */ + assert(archive_entry_clear(ae) != NULL); + archive_entry_copy_pathname(ae, "file_bad_suid"); + archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0742); + archive_entry_set_uid(ae, getuid() + 1); + archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM); + assertA(0 == archive_write_header(a, ae)); + /* + * Because we didn't ask for owner, the failure to + * restore SUID shouldn't return a failure. + * We check below to make sure SUID really wasn't set. + * See more detailed comments below. + */ + failure("Opportunistic SUID failure shouldn't return error."); + assertEqualInt(0, archive_write_finish_entry(a)); + + if (getuid() != 0) { + assert(archive_entry_clear(ae) != NULL); + archive_entry_copy_pathname(ae, "file_bad_suid2"); + archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0742); + archive_entry_set_uid(ae, getuid() + 1); + archive_write_disk_set_options(a, + ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_OWNER); + assertA(0 == archive_write_header(a, ae)); + /* Owner change should fail here. */ + failure("Non-opportunistic SUID failure should return error."); + assertEqualInt(ARCHIVE_WARN, archive_write_finish_entry(a)); + } + + /* Write a regular file with ARCHIVE_EXTRACT_PERM & SGID bit */ + assert(archive_entry_clear(ae) != NULL); + archive_entry_copy_pathname(ae, "file_perm_sgid"); + archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742); + archive_entry_set_gid(ae, defaultgid()); + archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + failure("Setting SGID bit should succeed here."); + assertEqualIntA(a, 0, archive_write_finish_entry(a)); + + if (altgid() == -1) { + /* + * Current user must belong to at least two groups or + * else we can't test setting the GID to another group. + */ + skipping("Current user can't test gid restore: must belong to more than one group."); + } else { + /* + * Write a regular file with ARCHIVE_EXTRACT_PERM & SGID bit + * but without ARCHIVE_EXTRACT_OWNER. + */ + /* + * This is a weird case: The user has asked for permissions to + * be restored but not asked for ownership to be restored. As + * a result, the default file creation will create a file with + * the wrong group. There are several possible behaviors for + * libarchive in this scenario: + * = Set the SGID bit. It is wrong and a security hole to + * set SGID with the wrong group. Even POSIX thinks so. + * = Implicitly set the group. I don't like this. + * = drop the SGID bit and warn (the old libarchive behavior) + * = drop the SGID bit and don't warn (the current libarchive + * behavior). + * The current behavior sees SGID/SUID restore when you + * don't ask for owner restore as an "opportunistic" + * action. That is, libarchive should do it if it can, + * but if it can't, it's not an error. + */ + assert(archive_entry_clear(ae) != NULL); + archive_entry_copy_pathname(ae, "file_alt_sgid"); + archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742); + archive_entry_set_uid(ae, getuid()); + archive_entry_set_gid(ae, altgid()); + archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + failure("Setting SGID bit should fail because of group mismatch but the failure should be silent because we didn't ask for the group to be set."); + assertEqualIntA(a, 0, archive_write_finish_entry(a)); + + /* + * As above, but add _EXTRACT_OWNER to verify that it + * does succeed. + */ + assert(archive_entry_clear(ae) != NULL); + archive_entry_copy_pathname(ae, "file_alt_sgid_owner"); + archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742); + archive_entry_set_uid(ae, getuid()); + archive_entry_set_gid(ae, altgid()); + archive_write_disk_set_options(a, + ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_OWNER); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + failure("Setting SGID bit should succeed here."); + assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a)); + } + + /* + * Write a regular file with ARCHIVE_EXTRACT_PERM & SGID bit, + * but wrong GID. POSIX says you shouldn't restore SGID bit + * unless the GID could be restored. + */ + if (invalidgid() == -1) { + /* This test always fails for root. */ + printf("Running as root: Can't test SGID failures.\n"); + } else { + assert(archive_entry_clear(ae) != NULL); + archive_entry_copy_pathname(ae, "file_bad_sgid"); + archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742); + archive_entry_set_gid(ae, invalidgid()); + archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM); + assertA(0 == archive_write_header(a, ae)); + failure("This SGID restore should fail without an error."); + assertEqualIntA(a, 0, archive_write_finish_entry(a)); + + assert(archive_entry_clear(ae) != NULL); + archive_entry_copy_pathname(ae, "file_bad_sgid2"); + archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742); + archive_entry_set_gid(ae, invalidgid()); + archive_write_disk_set_options(a, + ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_OWNER); + assertA(0 == archive_write_header(a, ae)); + failure("This SGID restore should fail with an error."); + assertEqualIntA(a, ARCHIVE_WARN, archive_write_finish_entry(a)); + } + + /* Set ownership should fail if we're not root. */ + if (getuid() == 0) { + printf("Running as root: Can't test setuid failures.\n"); + } else { + assert(archive_entry_clear(ae) != NULL); + archive_entry_copy_pathname(ae, "file_bad_owner"); + archive_entry_set_mode(ae, S_IFREG | 0744); + archive_entry_set_uid(ae, getuid() + 1); + archive_write_disk_set_options(a, ARCHIVE_EXTRACT_OWNER); + assertA(0 == archive_write_header(a, ae)); + assertEqualIntA(a,ARCHIVE_WARN,archive_write_finish_entry(a)); + } + + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + archive_entry_free(ae); + + /* Test the entries on disk. */ + assertEqualInt(0, stat("file_0755", &st)); + failure("file_0755: st.st_mode=%o", st.st_mode); + assertEqualInt(st.st_mode & 07777, 0755); + + assertEqualInt(0, stat("file_overwrite_0144", &st)); + failure("file_overwrite_0144: st.st_mode=%o", st.st_mode); + assertEqualInt(st.st_mode & 07777, 0144); + + assertEqualInt(0, stat("dir_0514", &st)); + failure("dir_0514: st.st_mode=%o", st.st_mode); + assertEqualInt(st.st_mode & 07777, 0514); + + assertEqualInt(0, stat("dir_overwrite_0744", &st)); + failure("dir_overwrite_0744: st.st_mode=%o", st.st_mode); + assertEqualInt(st.st_mode & 0777, 0744); + + assertEqualInt(0, stat("file_no_suid", &st)); + failure("file_0755: st.st_mode=%o", st.st_mode); + assertEqualInt(st.st_mode & 07777, 0755); + + assertEqualInt(0, stat("file_0777", &st)); + failure("file_0777: st.st_mode=%o", st.st_mode); + assertEqualInt(st.st_mode & 07777, 0777); + + /* SUID bit should get set here. */ + assertEqualInt(0, stat("file_4742", &st)); + failure("file_4742: st.st_mode=%o", st.st_mode); + assertEqualInt(st.st_mode & 07777, S_ISUID | 0742); + + /* SUID bit should NOT have been set here. */ + assertEqualInt(0, stat("file_bad_suid", &st)); + failure("file_bad_suid: st.st_mode=%o", st.st_mode); + assertEqualInt(st.st_mode & 07777, 0742); + + /* Some things don't fail if you're root, so suppress this. */ + if (getuid() != 0) { + /* SUID bit should NOT have been set here. */ + assertEqualInt(0, stat("file_bad_suid2", &st)); + failure("file_bad_suid2: st.st_mode=%o", st.st_mode); + assertEqualInt(st.st_mode & 07777, 0742); + } + + /* SGID should be set here. */ + assertEqualInt(0, stat("file_perm_sgid", &st)); + failure("file_perm_sgid: st.st_mode=%o", st.st_mode); + assertEqualInt(st.st_mode & 07777, S_ISGID | 0742); + + if (altgid() != -1) { + /* SGID should not be set here. */ + assertEqualInt(0, stat("file_alt_sgid", &st)); + failure("file_alt_sgid: st.st_mode=%o", st.st_mode); + assertEqualInt(st.st_mode & 07777, 0742); + + /* SGID should be set here. */ + assertEqualInt(0, stat("file_alt_sgid_owner", &st)); + failure("file_alt_sgid: st.st_mode=%o", st.st_mode); + assertEqualInt(st.st_mode & 07777, S_ISGID | 0742); + } + + if (invalidgid() != -1) { + /* SGID should NOT be set here. */ + assertEqualInt(0, stat("file_bad_sgid", &st)); + failure("file_bad_sgid: st.st_mode=%o", st.st_mode); + assertEqualInt(st.st_mode & 07777, 0742); + /* SGID should NOT be set here. */ + assertEqualInt(0, stat("file_bad_sgid2", &st)); + failure("file_bad_sgid2: st.st_mode=%o", st.st_mode); + assertEqualInt(st.st_mode & 07777, 0742); + } + + if (getuid() != 0) { + assertEqualInt(0, stat("file_bad_owner", &st)); + failure("file_bad_owner: st.st_mode=%o", st.st_mode); + assertEqualInt(st.st_mode & 07777, 0744); + failure("file_bad_owner: st.st_uid=%d getuid()=%d", + st.st_uid, getuid()); + /* The entry had getuid()+1, but because we're + * not root, we should not have been able to set that. */ + assertEqualInt(st.st_uid, getuid()); + } +#endif +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_secure.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_secure.c new file mode 100644 index 0000000..7cd66c4 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_secure.c @@ -0,0 +1,281 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_disk_secure.c 201247 2009-12-30 05:59:21Z kientzle $"); + +#define UMASK 022 + +/* + * Exercise security checks that should prevent certain + * writes. + */ + +DEFINE_TEST(test_write_disk_secure) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + skipping("archive_write_disk security checks not supported on Windows"); +#else + struct archive *a; + struct archive_entry *ae; + struct stat st; + + /* Start with a known umask. */ + assertUmask(UMASK); + + /* Create an archive_write_disk object. */ + assert((a = archive_write_disk_new()) != NULL); + + /* Write a regular dir to it. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "dir"); + archive_entry_set_mode(ae, S_IFDIR | 0777); + assert(0 == archive_write_header(a, ae)); + archive_entry_free(ae); + assert(0 == archive_write_finish_entry(a)); + + /* Write a symlink to the dir above. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "link_to_dir"); + archive_entry_set_mode(ae, S_IFLNK | 0777); + archive_entry_set_symlink(ae, "dir"); + archive_write_disk_set_options(a, 0); + assert(0 == archive_write_header(a, ae)); + assert(0 == archive_write_finish_entry(a)); + + /* + * Without security checks, we should be able to + * extract a file through the link. + */ + assert(archive_entry_clear(ae) != NULL); + archive_entry_copy_pathname(ae, "link_to_dir/filea"); + archive_entry_set_mode(ae, S_IFREG | 0777); + assert(0 == archive_write_header(a, ae)); + assert(0 == archive_write_finish_entry(a)); + + /* But with security checks enabled, this should fail. */ + assert(archive_entry_clear(ae) != NULL); + archive_entry_copy_pathname(ae, "link_to_dir/fileb"); + archive_entry_set_mode(ae, S_IFREG | 0777); + archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_SYMLINKS); + failure("Extracting a file through a symlink should fail here."); + assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae)); + archive_entry_free(ae); + assert(0 == archive_write_finish_entry(a)); + + /* Write an absolute symlink to /tmp. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "/tmp/libarchive_test-test_write_disk_secure-absolute_symlink"); + archive_entry_set_mode(ae, S_IFLNK | 0777); + archive_entry_set_symlink(ae, "/tmp"); + archive_write_disk_set_options(a, 0); + assert(0 == archive_write_header(a, ae)); + assert(0 == archive_write_finish_entry(a)); + + /* With security checks enabled, this should fail. */ + assert(archive_entry_clear(ae) != NULL); + archive_entry_copy_pathname(ae, "/tmp/libarchive_test-test_write_disk_secure-absolute_symlink/libarchive_test-test_write_disk_secure-absolute_symlink_path.tmp"); + archive_entry_set_mode(ae, S_IFREG | 0777); + archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_SYMLINKS); + failure("Extracting a file through an absolute symlink should fail here."); + assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae)); + archive_entry_free(ae); + assertFileNotExists("/tmp/libarchive_test-test_write_disk_secure-absolute_symlink/libarchive_test-test_write_disk_secure-absolute_symlink_path.tmp"); + assert(0 == unlink("/tmp/libarchive_test-test_write_disk_secure-absolute_symlink")); + unlink("/tmp/libarchive_test-test_write_disk_secure-absolute_symlink_path.tmp"); + + /* Create another link. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "link_to_dir2"); + archive_entry_set_mode(ae, S_IFLNK | 0777); + archive_entry_set_symlink(ae, "dir"); + archive_write_disk_set_options(a, 0); + assert(0 == archive_write_header(a, ae)); + assert(0 == archive_write_finish_entry(a)); + + /* + * With symlink check and unlink option, it should remove + * the link and create the dir. + */ + assert(archive_entry_clear(ae) != NULL); + archive_entry_copy_pathname(ae, "link_to_dir2/filec"); + archive_entry_set_mode(ae, S_IFREG | 0777); + archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_SYMLINKS | ARCHIVE_EXTRACT_UNLINK); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assert(0 == archive_write_finish_entry(a)); + + /* Create a nested symlink. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "dir/nested_link_to_dir"); + archive_entry_set_mode(ae, S_IFLNK | 0777); + archive_entry_set_symlink(ae, "../dir"); + archive_write_disk_set_options(a, 0); + assert(0 == archive_write_header(a, ae)); + assert(0 == archive_write_finish_entry(a)); + + /* But with security checks enabled, this should fail. */ + assert(archive_entry_clear(ae) != NULL); + archive_entry_copy_pathname(ae, "dir/nested_link_to_dir/filed"); + archive_entry_set_mode(ae, S_IFREG | 0777); + archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_SYMLINKS); + failure("Extracting a file through a symlink should fail here."); + assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae)); + archive_entry_free(ae); + assert(0 == archive_write_finish_entry(a)); + + /* + * Without security checks, extracting a dir over a link to a + * dir should follow the link. + */ + /* Create a symlink to a dir. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "link_to_dir3"); + archive_entry_set_mode(ae, S_IFLNK | 0777); + archive_entry_set_symlink(ae, "dir"); + archive_write_disk_set_options(a, 0); + assert(0 == archive_write_header(a, ae)); + assert(0 == archive_write_finish_entry(a)); + /* Extract a dir whose name matches the symlink. */ + assert(archive_entry_clear(ae) != NULL); + archive_entry_copy_pathname(ae, "link_to_dir3"); + archive_entry_set_mode(ae, S_IFDIR | 0777); + assert(0 == archive_write_header(a, ae)); + assert(0 == archive_write_finish_entry(a)); + /* Verify link was followed. */ + assertEqualInt(0, lstat("link_to_dir3", &st)); + assert(S_ISLNK(st.st_mode)); + archive_entry_free(ae); + + /* + * As above, but a broken link, so the link should get replaced. + */ + /* Create a symlink to a dir. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "link_to_dir4"); + archive_entry_set_mode(ae, S_IFLNK | 0777); + archive_entry_set_symlink(ae, "nonexistent_dir"); + archive_write_disk_set_options(a, 0); + assert(0 == archive_write_header(a, ae)); + assert(0 == archive_write_finish_entry(a)); + /* Extract a dir whose name matches the symlink. */ + assert(archive_entry_clear(ae) != NULL); + archive_entry_copy_pathname(ae, "link_to_dir4"); + archive_entry_set_mode(ae, S_IFDIR | 0777); + assert(0 == archive_write_header(a, ae)); + assert(0 == archive_write_finish_entry(a)); + /* Verify link was replaced. */ + assertEqualInt(0, lstat("link_to_dir4", &st)); + assert(S_ISDIR(st.st_mode)); + archive_entry_free(ae); + + /* + * As above, but a link to a non-dir, so the link should get replaced. + */ + /* Create a regular file and a symlink to it */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "non_dir"); + archive_entry_set_mode(ae, S_IFREG | 0777); + archive_write_disk_set_options(a, 0); + assert(0 == archive_write_header(a, ae)); + assert(0 == archive_write_finish_entry(a)); + /* Create symlink to the file. */ + archive_entry_copy_pathname(ae, "link_to_dir5"); + archive_entry_set_mode(ae, S_IFLNK | 0777); + archive_entry_set_symlink(ae, "non_dir"); + archive_write_disk_set_options(a, 0); + assert(0 == archive_write_header(a, ae)); + assert(0 == archive_write_finish_entry(a)); + /* Extract a dir whose name matches the symlink. */ + assert(archive_entry_clear(ae) != NULL); + archive_entry_copy_pathname(ae, "link_to_dir5"); + archive_entry_set_mode(ae, S_IFDIR | 0777); + assert(0 == archive_write_header(a, ae)); + assert(0 == archive_write_finish_entry(a)); + /* Verify link was replaced. */ + assertEqualInt(0, lstat("link_to_dir5", &st)); + assert(S_ISDIR(st.st_mode)); + archive_entry_free(ae); + + /* + * Without security checks, we should be able to + * extract an absolute path. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "/tmp/libarchive_test-test_write_disk_secure-absolute_path.tmp"); + archive_entry_set_mode(ae, S_IFREG | 0777); + assert(0 == archive_write_header(a, ae)); + assert(0 == archive_write_finish_entry(a)); + assertFileExists("/tmp/libarchive_test-test_write_disk_secure-absolute_path.tmp"); + assert(0 == unlink("/tmp/libarchive_test-test_write_disk_secure-absolute_path.tmp")); + + /* But with security checks enabled, this should fail. */ + assert(archive_entry_clear(ae) != NULL); + archive_entry_copy_pathname(ae, "/tmp/libarchive_test-test_write_disk_secure-absolute_path.tmp"); + archive_entry_set_mode(ae, S_IFREG | 0777); + archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS); + failure("Extracting an absolute path should fail here."); + assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae)); + archive_entry_free(ae); + assert(0 == archive_write_finish_entry(a)); + assertFileNotExists("/tmp/libarchive_test-test_write_disk_secure-absolute_path.tmp"); + + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Test the entries on disk. */ + assert(0 == lstat("dir", &st)); + failure("dir: st.st_mode=%o", st.st_mode); + assert((st.st_mode & 0777) == 0755); + + assert(0 == lstat("link_to_dir", &st)); + failure("link_to_dir: st.st_mode=%o", st.st_mode); + assert(S_ISLNK(st.st_mode)); +#if HAVE_LCHMOD + /* Systems that lack lchmod() can't set symlink perms, so skip this. */ + failure("link_to_dir: st.st_mode=%o", st.st_mode); + assert((st.st_mode & 07777) == 0755); +#endif + + assert(0 == lstat("dir/filea", &st)); + failure("dir/filea: st.st_mode=%o", st.st_mode); + assert((st.st_mode & 07777) == 0755); + + failure("dir/fileb: This file should not have been created"); + assert(0 != lstat("dir/fileb", &st)); + + assert(0 == lstat("link_to_dir2", &st)); + failure("link_to_dir2 should have been re-created as a true dir"); + assert(S_ISDIR(st.st_mode)); + failure("link_to_dir2: Implicit dir creation should obey umask, but st.st_mode=%o", st.st_mode); + assert((st.st_mode & 0777) == 0755); + + assert(0 == lstat("link_to_dir2/filec", &st)); + assert(S_ISREG(st.st_mode)); + failure("link_to_dir2/filec: st.st_mode=%o", st.st_mode); + assert((st.st_mode & 07777) == 0755); + + failure("dir/filed: This file should not have been created"); + assert(0 != lstat("dir/filed", &st)); +#endif +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_secure744.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_secure744.c new file mode 100644 index 0000000..08c725e --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_secure744.c @@ -0,0 +1,95 @@ +/*- + * Copyright (c) 2003-2007,2016 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +#define UMASK 022 + +/* + * Github Issue #744 describes a bug in the sandboxing code that + * causes very long pathnames to not get checked for symlinks. + */ + +DEFINE_TEST(test_write_disk_secure744) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + skipping("archive_write_disk security checks not supported on Windows"); +#else + struct archive *a; + struct archive_entry *ae; + size_t buff_size = 8192; + char *buff = malloc(buff_size); + char *p = buff; + int n = 0; + int t; + + assert(buff != NULL); + + /* Start with a known umask. */ + assertUmask(UMASK); + + /* Create an archive_write_disk object. */ + assert((a = archive_write_disk_new()) != NULL); + archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_SYMLINKS); + + while (p + 500 < buff + buff_size) { + memset(p, 'x', 100); + p += 100; + p[0] = '\0'; + + buff[0] = ((n / 1000) % 10) + '0'; + buff[1] = ((n / 100) % 10)+ '0'; + buff[2] = ((n / 10) % 10)+ '0'; + buff[3] = ((n / 1) % 10)+ '0'; + buff[4] = '_'; + ++n; + + /* Create a symlink pointing to the testworkdir */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, buff); + archive_entry_set_mode(ae, S_IFREG | 0777); + archive_entry_copy_symlink(ae, testworkdir); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + *p++ = '/'; + sprintf(p, "target%d", n); + + /* Try to create a file through the symlink, should fail. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, buff); + archive_entry_set_mode(ae, S_IFDIR | 0777); + + t = archive_write_header(a, ae); + archive_entry_free(ae); + failure("Attempt to create target%d via %d-character symlink should have failed", n, (int)strlen(buff)); + if(!assertEqualInt(ARCHIVE_FAILED, t)) { + break; + } + } + archive_free(a); + free(buff); +#endif +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_secure745.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_secure745.c new file mode 100644 index 0000000..870b064 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_secure745.c @@ -0,0 +1,79 @@ +/*- + * Copyright (c) 2003-2007,2016 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +#define UMASK 022 + +/* + * Github Issue #745 describes a bug in the sandboxing code that + * allows one to use a symlink to edit the permissions on a file or + * directory outside of the sandbox. + */ + +DEFINE_TEST(test_write_disk_secure745) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + skipping("archive_write_disk security checks not supported on Windows"); +#else + struct archive *a; + struct archive_entry *ae; + + /* Start with a known umask. */ + assertUmask(UMASK); + + /* Create an archive_write_disk object. */ + assert((a = archive_write_disk_new()) != NULL); + archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_SYMLINKS); + + /* The target dir: The one we're going to try to change permission on */ + assertMakeDir("target", 0700); + + /* The sandbox dir we're going to run inside of. */ + assertMakeDir("sandbox", 0700); + assertChdir("sandbox"); + + /* Create a symlink pointing to the target directory */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "sym"); + archive_entry_set_mode(ae, AE_IFLNK | 0777); + archive_entry_copy_symlink(ae, "../target"); + assert(0 == archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Try to alter the target dir through the symlink; this should fail. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "sym"); + archive_entry_set_mode(ae, S_IFDIR | 0777); + assert(0 == archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Permission of target dir should not have changed. */ + assertFileMode("../target", 0700); + + assert(0 == archive_write_close(a)); + archive_write_free(a); +#endif +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_secure746.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_secure746.c new file mode 100644 index 0000000..5ce1fd9 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_secure746.c @@ -0,0 +1,132 @@ +/*- + * Copyright (c) 2003-2007,2016 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +#define UMASK 022 + +/* + * Github Issue #746 describes a problem in which hardlink targets are + * not adequately checked and can be used to modify entries outside of + * the sandbox. + */ + +/* + * Verify that ARCHIVE_EXTRACT_SECURE_NODOTDOT disallows '..' in hardlink + * targets. + */ +DEFINE_TEST(test_write_disk_secure746a) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + skipping("archive_write_disk security checks not supported on Windows"); +#else + struct archive *a; + struct archive_entry *ae; + + /* Start with a known umask. */ + assertUmask(UMASK); + + /* The target directory we're going to try to affect. */ + assertMakeDir("target", 0700); + assertMakeFile("target/foo", 0700, "unmodified"); + + /* The sandbox dir we're going to work within. */ + assertMakeDir("sandbox", 0700); + assertChdir("sandbox"); + + /* Create an archive_write_disk object. */ + assert((a = archive_write_disk_new()) != NULL); + archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_NODOTDOT); + + /* Attempt to hardlink to the target directory. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "bar"); + archive_entry_set_mode(ae, AE_IFREG | 0777); + archive_entry_set_size(ae, 8); + archive_entry_copy_hardlink(ae, "../target/foo"); + assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae)); + assertEqualInt(ARCHIVE_FATAL, archive_write_data(a, "modified", 8)); + archive_entry_free(ae); + + /* Verify that target file contents are unchanged. */ + assertTextFileContents("unmodified", "../target/foo"); + + assertEqualIntA(a, ARCHIVE_FATAL, archive_write_close(a)); + archive_write_free(a); +#endif +} + +/* + * Verify that ARCHIVE_EXTRACT_SECURE_NOSYMLINK disallows symlinks in hardlink + * targets. + */ +DEFINE_TEST(test_write_disk_secure746b) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + skipping("archive_write_disk security checks not supported on Windows"); +#else + struct archive *a; + struct archive_entry *ae; + + /* Start with a known umask. */ + assertUmask(UMASK); + + /* The target directory we're going to try to affect. */ + assertMakeDir("target", 0700); + assertMakeFile("target/foo", 0700, "unmodified"); + + /* The sandbox dir we're going to work within. */ + assertMakeDir("sandbox", 0700); + assertChdir("sandbox"); + + /* Create an archive_write_disk object. */ + assert((a = archive_write_disk_new()) != NULL); + archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_SYMLINKS); + + /* Create a symlink to the target directory. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "symlink"); + archive_entry_set_mode(ae, AE_IFLNK | 0777); + archive_entry_copy_symlink(ae, "../target"); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Attempt to hardlink to the target directory via the symlink. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "bar"); + archive_entry_set_mode(ae, AE_IFREG | 0777); + archive_entry_set_size(ae, 8); + archive_entry_copy_hardlink(ae, "symlink/foo"); + assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae)); + assertEqualIntA(a, ARCHIVE_FATAL, archive_write_data(a, "modified", 8)); + archive_entry_free(ae); + + /* Verify that target file contents are unchanged. */ + assertTextFileContents("unmodified", "../target/foo"); + + assertEqualIntA(a, ARCHIVE_FATAL, archive_write_close(a)); + archive_write_free(a); +#endif +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_sparse.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_sparse.c new file mode 100644 index 0000000..36ecf32 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_sparse.c @@ -0,0 +1,290 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_disk_sparse.c 201247 2009-12-30 05:59:21Z kientzle $"); + +/* + * Write a file using archive_write_data call, read the file + * back and verify the contents. The data written includes large + * blocks of nulls, so it should exercise the sparsification logic + * if ARCHIVE_EXTRACT_SPARSE is enabled. + */ +static void +verify_write_data(struct archive *a, int sparse) +{ + static const char data[]="abcdefghijklmnopqrstuvwxyz"; + struct stat st; + struct archive_entry *ae; + size_t buff_size = 64 * 1024; + char *buff, *p; + const char *msg = sparse ? "sparse" : "non-sparse"; + FILE *f; + + buff = malloc(buff_size); + assert(buff != NULL); + if (buff == NULL) + return; + + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_size(ae, 8 * buff_size); + archive_entry_set_pathname(ae, "test_write_data"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + assertEqualIntA(a, 0, archive_write_header(a, ae)); + + /* Use archive_write_data() to write three relatively sparse blocks. */ + + /* First has non-null data at beginning. */ + memset(buff, 0, buff_size); + memcpy(buff, data, sizeof(data)); + failure("%s", msg); + assertEqualInt(buff_size, archive_write_data(a, buff, buff_size)); + + /* Second has non-null data in the middle. */ + memset(buff, 0, buff_size); + memcpy(buff + buff_size / 2 - 3, data, sizeof(data)); + failure("%s", msg); + assertEqualInt(buff_size, archive_write_data(a, buff, buff_size)); + + /* Third has non-null data at the end. */ + memset(buff, 0, buff_size); + memcpy(buff + buff_size - sizeof(data), data, sizeof(data)); + failure("%s", msg); + assertEqualInt(buff_size, archive_write_data(a, buff, buff_size)); + + failure("%s", msg); + assertEqualIntA(a, 0, archive_write_finish_entry(a)); + + /* Test the entry on disk. */ + assert(0 == stat(archive_entry_pathname(ae), &st)); + assertEqualInt(st.st_size, 8 * buff_size); + f = fopen(archive_entry_pathname(ae), "rb"); + assert(f != NULL); + if (f == NULL) { + free(buff); + return; + } + + /* Check first block. */ + assertEqualInt(buff_size, fread(buff, 1, buff_size, f)); + failure("%s", msg); + assertEqualMem(buff, data, sizeof(data)); + for (p = buff + sizeof(data); p < buff + buff_size; ++p) { + failure("offset: %d, %s", (int)(p - buff), msg); + if (!assertEqualInt(0, *p)) + break; + } + + /* Check second block. */ + assertEqualInt(buff_size, fread(buff, 1, buff_size, f)); + for (p = buff; p < buff + buff_size; ++p) { + failure("offset: %d, %s", (int)(p - buff), msg); + if (p == buff + buff_size / 2 - 3) { + assertEqualMem(p, data, sizeof(data)); + p += sizeof(data); + } else if (!assertEqualInt(0, *p)) + break; + } + + /* Check third block. */ + assertEqualInt(buff_size, fread(buff, 1, buff_size, f)); + for (p = buff; p < buff + buff_size - sizeof(data); ++p) { + failure("offset: %d, %s", (int)(p - buff), msg); + if (!assertEqualInt(0, *p)) + break; + } + failure("%s", msg); + assertEqualMem(buff + buff_size - sizeof(data), data, sizeof(data)); + + /* XXX more XXX */ + + assertEqualInt(0, fclose(f)); + archive_entry_free(ae); + free(buff); +} + +/* + * As above, but using the archive_write_data_block() call. + */ +static void +verify_write_data_block(struct archive *a, int sparse) +{ + static const char data[]="abcdefghijklmnopqrstuvwxyz"; + struct stat st; + struct archive_entry *ae; + size_t buff_size = 64 * 1024; + char *buff, *p; + const char *msg = sparse ? "sparse" : "non-sparse"; + FILE *f; + + buff = malloc(buff_size); + assert(buff != NULL); + if (buff == NULL) + return; + + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_size(ae, 8 * buff_size); + archive_entry_set_pathname(ae, "test_write_data_block"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + assertEqualIntA(a, 0, archive_write_header(a, ae)); + + /* Use archive_write_data_block() to write three + relatively sparse blocks. */ + + /* First has non-null data at beginning. */ + memset(buff, 0, buff_size); + memcpy(buff, data, sizeof(data)); + failure("%s", msg); + assertEqualInt(ARCHIVE_OK, + archive_write_data_block(a, buff, buff_size, 100)); + + /* Second has non-null data in the middle. */ + memset(buff, 0, buff_size); + memcpy(buff + buff_size / 2 - 3, data, sizeof(data)); + failure("%s", msg); + assertEqualInt(ARCHIVE_OK, + archive_write_data_block(a, buff, buff_size, buff_size + 200)); + + /* Third has non-null data at the end. */ + memset(buff, 0, buff_size); + memcpy(buff + buff_size - sizeof(data), data, sizeof(data)); + failure("%s", msg); + assertEqualInt(ARCHIVE_OK, + archive_write_data_block(a, buff, buff_size, buff_size * 2 + 300)); + + failure("%s", msg); + assertEqualIntA(a, 0, archive_write_finish_entry(a)); + + /* Test the entry on disk. */ + assert(0 == stat(archive_entry_pathname(ae), &st)); + assertEqualInt(st.st_size, 8 * buff_size); + f = fopen(archive_entry_pathname(ae), "rb"); + assert(f != NULL); + if (f == NULL) { + free(buff); + return; + } + + /* Check 100-byte gap at beginning */ + assertEqualInt(100, fread(buff, 1, 100, f)); + failure("%s", msg); + for (p = buff; p < buff + 100; ++p) { + failure("offset: %d, %s", (int)(p - buff), msg); + if (!assertEqualInt(0, *p)) + break; + } + + /* Check first block. */ + assertEqualInt(buff_size, fread(buff, 1, buff_size, f)); + failure("%s", msg); + assertEqualMem(buff, data, sizeof(data)); + for (p = buff + sizeof(data); p < buff + buff_size; ++p) { + failure("offset: %d, %s", (int)(p - buff), msg); + if (!assertEqualInt(0, *p)) + break; + } + + /* Check 100-byte gap */ + assertEqualInt(100, fread(buff, 1, 100, f)); + failure("%s", msg); + for (p = buff; p < buff + 100; ++p) { + failure("offset: %d, %s", (int)(p - buff), msg); + if (!assertEqualInt(0, *p)) + break; + } + + /* Check second block. */ + assertEqualInt(buff_size, fread(buff, 1, buff_size, f)); + for (p = buff; p < buff + buff_size; ++p) { + failure("offset: %d, %s", (int)(p - buff), msg); + if (p == buff + buff_size / 2 - 3) { + assertEqualMem(p, data, sizeof(data)); + p += sizeof(data); + } else if (!assertEqualInt(0, *p)) + break; + } + + /* Check 100-byte gap */ + assertEqualInt(100, fread(buff, 1, 100, f)); + failure("%s", msg); + for (p = buff; p < buff + 100; ++p) { + failure("offset: %d, %s", (int)(p - buff), msg); + if (!assertEqualInt(0, *p)) + break; + } + + /* Check third block. */ + assertEqualInt(buff_size, fread(buff, 1, buff_size, f)); + for (p = buff; p < buff + buff_size - sizeof(data); ++p) { + failure("offset: %d, %s", (int)(p - buff), msg); + if (!assertEqualInt(0, *p)) + break; + } + failure("%s", msg); + assertEqualMem(buff + buff_size - sizeof(data), data, sizeof(data)); + + /* Check another block size beyond last we wrote. */ + assertEqualInt(buff_size, fread(buff, 1, buff_size, f)); + failure("%s", msg); + for (p = buff; p < buff + buff_size; ++p) { + failure("offset: %d, %s", (int)(p - buff), msg); + if (!assertEqualInt(0, *p)) + break; + } + + + /* XXX more XXX */ + + assertEqualInt(0, fclose(f)); + free(buff); + archive_entry_free(ae); +} + +DEFINE_TEST(test_write_disk_sparse) +{ + struct archive *ad; + + + /* + * The return values, etc, of the write data functions + * shouldn't change regardless of whether we've requested + * sparsification. (The performance and pattern of actual + * write calls to the disk should vary, of course, but the + * client program shouldn't see any difference.) + */ + assert((ad = archive_write_disk_new()) != NULL); + archive_write_disk_set_options(ad, 0); + verify_write_data(ad, 0); + verify_write_data_block(ad, 0); + assertEqualInt(0, archive_write_free(ad)); + + assert((ad = archive_write_disk_new()) != NULL); + archive_write_disk_set_options(ad, ARCHIVE_EXTRACT_SPARSE); + verify_write_data(ad, 1); + verify_write_data_block(ad, 1); + assertEqualInt(0, archive_write_free(ad)); + +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_symlink.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_symlink.c new file mode 100644 index 0000000..aeadfee --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_symlink.c @@ -0,0 +1,269 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_disk_symlink.c 201247 2009-12-30 05:59:21Z kientzle $"); + +/* + * Exercise symlink recreation. + */ +DEFINE_TEST(test_write_disk_symlink) +{ + static const char data[]="abcdefghijklmnopqrstuvwxyz"; + struct archive *ad; + struct archive_entry *ae; + int r; + + if (!canSymlink()) { + skipping("Symlinks not supported"); + return; + } + + /* Write entries to disk. */ + assert((ad = archive_write_disk_new()) != NULL); + + /* + * First, create a regular file then a symlink to that file. + */ + + /* Regular file: link1a */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "link1a"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + archive_entry_set_size(ae, sizeof(data)); + assertEqualIntA(ad, 0, archive_write_header(ad, ae)); + assertEqualInt(sizeof(data), + archive_write_data(ad, data, sizeof(data))); + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + archive_entry_free(ae); + + /* Symbolic Link: link1b -> link1a */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "link1b"); + archive_entry_set_mode(ae, AE_IFLNK | 0642); + archive_entry_set_size(ae, 0); + archive_entry_copy_symlink(ae, "link1a"); + assertEqualIntA(ad, 0, r = archive_write_header(ad, ae)); + if (r >= ARCHIVE_WARN) + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + archive_entry_free(ae); + + /* + * We should be able to do this in the other order as well, + * of course. + */ + + /* Symbolic link: link2b -> link2a */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "link2b"); + archive_entry_set_mode(ae, AE_IFLNK | 0642); + archive_entry_unset_size(ae); + archive_entry_copy_symlink(ae, "link2a"); + assertEqualIntA(ad, 0, r = archive_write_header(ad, ae)); + if (r >= ARCHIVE_WARN) { + assertEqualInt(ARCHIVE_WARN, + archive_write_data(ad, data, sizeof(data))); + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + } + archive_entry_free(ae); + + /* File: link2a */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "link2a"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + archive_entry_set_size(ae, sizeof(data)); + assertEqualIntA(ad, 0, archive_write_header(ad, ae)); + assertEqualInt(sizeof(data), + archive_write_data(ad, data, sizeof(data))); + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + archive_entry_free(ae); + + /* Symbolic link: dot -> . */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "dot"); + archive_entry_set_mode(ae, AE_IFLNK | 0642); + archive_entry_unset_size(ae); + archive_entry_copy_symlink(ae, "."); + assertEqualIntA(ad, 0, r = archive_write_header(ad, ae)); + if (r >= ARCHIVE_WARN) + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + archive_entry_free(ae); + + /* Symbolic link: dotdot -> .. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "dotdot"); + archive_entry_set_mode(ae, AE_IFLNK | 0642); + archive_entry_unset_size(ae); + archive_entry_copy_symlink(ae, ".."); + assertEqualIntA(ad, 0, r = archive_write_header(ad, ae)); + if (r >= ARCHIVE_WARN) + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + archive_entry_free(ae); + + /* Symbolic link: slash -> / */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "slash"); + archive_entry_set_mode(ae, AE_IFLNK | 0642); + archive_entry_unset_size(ae); + archive_entry_copy_symlink(ae, "/"); + assertEqualIntA(ad, 0, r = archive_write_header(ad, ae)); + if (r >= ARCHIVE_WARN) + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + archive_entry_free(ae); + + /* Symbolic link: sldot -> /. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "sldot"); + archive_entry_set_mode(ae, AE_IFLNK | 0642); + archive_entry_unset_size(ae); + archive_entry_copy_symlink(ae, "/."); + assertEqualIntA(ad, 0, r = archive_write_header(ad, ae)); + if (r >= ARCHIVE_WARN) + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + archive_entry_free(ae); + + /* Symbolic link: sldotdot -> /.. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "sldotdot"); + archive_entry_set_mode(ae, AE_IFLNK | 0642); + archive_entry_unset_size(ae); + archive_entry_copy_symlink(ae, "/.."); + assertEqualIntA(ad, 0, r = archive_write_header(ad, ae)); + if (r >= ARCHIVE_WARN) + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + archive_entry_free(ae); + + /* Dir: d1 */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "d1"); + archive_entry_set_mode(ae, AE_IFDIR | 0777); + archive_entry_unset_size(ae); + assertEqualIntA(ad, 0, r = archive_write_header(ad, ae)); + if (r >= ARCHIVE_WARN) + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + archive_entry_free(ae); + + /* Symbolic link: d1nosl -> d1 */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "d1nosl"); + archive_entry_set_mode(ae, AE_IFLNK | 0642); + archive_entry_unset_size(ae); + archive_entry_copy_symlink(ae, "d1"); + assertEqualIntA(ad, 0, r = archive_write_header(ad, ae)); + if (r >= ARCHIVE_WARN) + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + archive_entry_free(ae); + + /* Symbolic link: d1slash -> d1/ */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "d1slash"); + archive_entry_set_mode(ae, AE_IFLNK | 0642); + archive_entry_unset_size(ae); + archive_entry_copy_symlink(ae, "d1/"); + assertEqualIntA(ad, 0, r = archive_write_header(ad, ae)); + if (r >= ARCHIVE_WARN) + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + archive_entry_free(ae); + + /* Symbolic link: d1sldot -> d1/. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "d1sldot"); + archive_entry_set_mode(ae, AE_IFLNK | 0642); + archive_entry_unset_size(ae); + archive_entry_copy_symlink(ae, "d1/."); + assertEqualIntA(ad, 0, r = archive_write_header(ad, ae)); + if (r >= ARCHIVE_WARN) + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + archive_entry_free(ae); + + /* Symbolic link: d1slddot -> d1/.. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "d1slddot"); + archive_entry_set_mode(ae, AE_IFLNK | 0642); + archive_entry_unset_size(ae); + archive_entry_copy_symlink(ae, "d1/.."); + assertEqualIntA(ad, 0, r = archive_write_header(ad, ae)); + if (r >= ARCHIVE_WARN) + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + archive_entry_free(ae); + + /* Symbolic link: d1dir -> d1 */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "d1dir"); + archive_entry_set_mode(ae, AE_IFLNK | 0642); + archive_entry_set_symlink_type(ae, AE_SYMLINK_TYPE_DIRECTORY); + archive_entry_unset_size(ae); + archive_entry_copy_symlink(ae, "d1"); + assertEqualIntA(ad, 0, r = archive_write_header(ad, ae)); + if (r >= ARCHIVE_WARN) + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + archive_entry_free(ae); + + /* Symbolic link: d1file -> d1 */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "d1file"); + archive_entry_set_mode(ae, AE_IFLNK | 0642); + archive_entry_set_symlink_type(ae, AE_SYMLINK_TYPE_FILE); + archive_entry_unset_size(ae); + archive_entry_copy_symlink(ae, "d1"); + assertEqualIntA(ad, 0, r = archive_write_header(ad, ae)); + if (r >= ARCHIVE_WARN) + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + archive_entry_free(ae); + + assertEqualInt(ARCHIVE_OK, archive_write_free(ad)); + + /* Test the entries on disk. */ + + /* Test #1 */ + assertIsReg("link1a", -1); + assertFileSize("link1a", sizeof(data)); + assertFileNLinks("link1a", 1); + assertIsSymlink("link1b", "link1a", 0); + + /* Test #2: Should produce identical results to test #1 */ + assertIsReg("link2a", -1); + assertFileSize("link2a", sizeof(data)); + assertFileNLinks("link2a", 1); + assertIsSymlink("link2b", "link2a", 0); + + /* Test #3: Special symlinks */ + assertIsSymlink("dot", ".", 1); + assertIsSymlink("dotdot", "..", 1); + assertIsSymlink("slash", "/", 1); + assertIsSymlink("sldot", "/.", 1); + assertIsSymlink("sldotdot", "/..", 1); + + /* Test #4: Directory symlink mixed with . and .. */ + assertIsDir("d1", -1); + /* On Windows, d1nosl should be a file symlink */ + assertIsSymlink("d1nosl", "d1", 0); + assertIsSymlink("d1slash", "d1/", 1); + assertIsSymlink("d1sldot", "d1/.", 1); + assertIsSymlink("d1slddot", "d1/..", 1); + + /* Test #5: symlink_type is set */ + assertIsSymlink("d1dir", "d1", 1); + assertIsSymlink("d1file", "d1", 0); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_times.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_times.c new file mode 100644 index 0000000..568d04c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_disk_times.c @@ -0,0 +1,167 @@ +/*- + * Copyright (c) 2003-2008 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_disk_times.c 201247 2009-12-30 05:59:21Z kientzle $"); + +/* + * Exercise time restores in archive_write_disk(), including + * correct handling of omitted time values. + * On FreeBSD, we also test birthtime and high-res time restores. + */ + +DEFINE_TEST(test_write_disk_times) +{ + struct archive *a; + struct archive_entry *ae; + + /* Create an archive_write_disk object. */ + assert((a = archive_write_disk_new()) != NULL); + assertEqualInt(ARCHIVE_OK, + archive_write_disk_set_options(a, ARCHIVE_EXTRACT_TIME)); + + /* + * Easy case: mtime and atime both specified. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file1"); + archive_entry_set_mode(ae, S_IFREG | 0777); + archive_entry_set_atime(ae, 123456, 0); + archive_entry_set_mtime(ae, 234567, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + assertEqualInt(ARCHIVE_OK, archive_write_finish_entry(a)); + archive_entry_free(ae); + /* Verify */ + assertFileAtime("file1", 123456, 0); + assertFileMtime("file1", 234567, 0); + + /* + * mtime specified, but not atime + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file2"); + archive_entry_set_mode(ae, S_IFREG | 0777); + archive_entry_set_mtime(ae, 234567, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + assertEqualInt(ARCHIVE_OK, archive_write_finish_entry(a)); + archive_entry_free(ae); + assertFileMtime("file2", 234567, 0); + assertFileAtimeRecent("file2"); + + /* + * atime specified, but not mtime + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file3"); + archive_entry_set_mode(ae, S_IFREG | 0777); + archive_entry_set_atime(ae, 345678, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + assertEqualInt(ARCHIVE_OK, archive_write_finish_entry(a)); + archive_entry_free(ae); + /* Verify: Current mtime and atime as specified. */ + assertFileAtime("file3", 345678, 0); + assertFileMtimeRecent("file3"); + + /* + * Neither atime nor mtime specified. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file4"); + archive_entry_set_mode(ae, S_IFREG | 0777); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + assertEqualInt(ARCHIVE_OK, archive_write_finish_entry(a)); + archive_entry_free(ae); + /* Verify: Current mtime and atime. */ + assertFileAtimeRecent("file4"); + assertFileMtimeRecent("file4"); + +#if defined(__FreeBSD__) + /* + * High-res mtime and atime on FreeBSD. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file10"); + archive_entry_set_mode(ae, S_IFREG | 0777); + archive_entry_set_atime(ae, 1234567, 23456); + archive_entry_set_mtime(ae, 2345678, 4567); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + assertEqualInt(ARCHIVE_OK, archive_write_finish_entry(a)); + archive_entry_free(ae); + /* Verify */ + assertFileMtime("file10", 2345678, 4567); + assertFileAtime("file10", 1234567, 23456); + + /* + * Birthtime, mtime and atime on FreeBSD + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file11"); + archive_entry_set_mode(ae, S_IFREG | 0777); + archive_entry_set_atime(ae, 1234567, 23456); + archive_entry_set_birthtime(ae, 3456789, 12345); + /* mtime must be later than birthtime! */ + archive_entry_set_mtime(ae, 12345678, 4567); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + assertEqualInt(ARCHIVE_OK, archive_write_finish_entry(a)); + archive_entry_free(ae); + /* Verify */ + assertFileAtime("file11", 1234567, 23456); + assertFileBirthtime("file11", 3456789, 12345); + assertFileMtime("file11", 12345678, 4567); + + /* + * Birthtime only on FreeBSD. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file12"); + archive_entry_set_mode(ae, S_IFREG | 0777); + archive_entry_set_birthtime(ae, 3456789, 12345); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + assertEqualInt(ARCHIVE_OK, archive_write_finish_entry(a)); + archive_entry_free(ae); + /* Verify */ + assertFileAtimeRecent("file12"); + assertFileBirthtime("file12", 3456789, 12345); + assertFileMtimeRecent("file12"); + + /* + * mtime only on FreeBSD. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file13"); + archive_entry_set_mode(ae, S_IFREG | 0777); + archive_entry_set_mtime(ae, 4567890, 23456); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + assertEqualInt(ARCHIVE_OK, archive_write_finish_entry(a)); + archive_entry_free(ae); + /* Verify */ + assertFileAtimeRecent("file13"); + assertFileBirthtime("file13", 4567890, 23456); + assertFileMtime("file13", 4567890, 23456); +#else + skipping("Platform-specific time restore tests"); +#endif + + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_b64encode.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_b64encode.c new file mode 100644 index 0000000..665087b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_b64encode.c @@ -0,0 +1,173 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * A basic exercise of b64encode reading and writing. + */ + +DEFINE_TEST(test_write_filter_b64encode) +{ + struct archive_entry *ae; + struct archive* a; + char *buff, *data; + size_t buffsize, datasize; + char path[16]; + size_t used1, used2; + int i; + + buffsize = 2000000; + assert(NULL != (buff = (char *)malloc(buffsize))); + + datasize = 10000; + assert(NULL != (data = (char *)malloc(datasize))); + memset(data, 0, datasize); + + /* + * Write a 100 files and read them all back. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_b64encode(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualInt(ARCHIVE_FILTER_UU, archive_filter_code(a, 0)); + assertEqualString("b64encode", archive_filter_name(a, 0)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used1)); + for (i = 0; i < 99; i++) { + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_size(ae, datasize); + sprintf(path, "file%03d", i); + archive_entry_copy_pathname(ae, path); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertA(datasize + == (size_t)archive_write_data(a, data, datasize)); + archive_entry_free(ae); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used1)); + for (i = 0; i < 99; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualIntA(a, 0, archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualInt(ARCHIVE_FILTER_UU, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Repeat the cycle again, this time setting name and mode + * options. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_b64encode(a)); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_filter_option(a, NULL, "nonexistent-option", "0")); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_filter_option(a, NULL, "compression-level", "abc")); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_filter_option(a, NULL, "compression-level", "99")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_filter_option(a, NULL, "name", "test.tar")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_filter_option(a, NULL, "mode", "0640")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used2)); + for (i = 0; i < 99; i++) { + sprintf(path, "file%03d", i); + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, path); + archive_entry_set_size(ae, datasize); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertA(datasize == (size_t)archive_write_data(a, data, datasize)); + archive_entry_free(ae); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used2)); + for (i = 0; i < 99; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(0, archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualInt(ARCHIVE_FILTER_UU, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Test various premature shutdown scenarios to make sure we + * don't crash or leak memory. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_b64encode(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_b64encode(a)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_b64encode(a)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_b64encode(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used2)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Clean up. + */ + free(data); + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_bzip2.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_bzip2.c new file mode 100644 index 0000000..4f32d28 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_bzip2.c @@ -0,0 +1,276 @@ +/*- + * Copyright (c) 2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_compress_bzip2.c 191183 2009-04-17 01:06:31Z kientzle $"); + +/* + * A basic exercise of bzip2 reading and writing. + * + * TODO: Add a reference file and make sure we can decompress that. + */ + +DEFINE_TEST(test_write_filter_bzip2) +{ + struct archive_entry *ae; + struct archive* a; + char *buff, *data; + size_t buffsize, datasize; + char path[16]; + size_t used1, used2; + int i, r, use_prog; + + buffsize = 2000000; + assert(NULL != (buff = (char *)malloc(buffsize))); + if (buff == NULL) + return; + + datasize = 10000; + assert(NULL != (data = (char *)malloc(datasize))); + if (data == NULL) { + free(buff); + return; + } + memset(data, 0, datasize); + + /* + * Write a 100 files and read them all back. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + r = archive_write_add_filter_bzip2(a); + use_prog = (r == ARCHIVE_WARN && canBzip2()); + if (r != ARCHIVE_OK && !use_prog) { + skipping("bzip2 writing not supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); + free(data); + return; + } + + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualInt(ARCHIVE_FILTER_BZIP2, archive_filter_code(a, 0)); + assertEqualString("bzip2", archive_filter_name(a, 0)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used1)); + assertEqualInt(ARCHIVE_FILTER_BZIP2, archive_filter_code(a, 0)); + assertEqualString("bzip2", archive_filter_name(a, 0)); + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_size(ae, datasize); + for (i = 0; i < 999; i++) { + sprintf(path, "file%03d", i); + archive_entry_copy_pathname(ae, path); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertA(datasize + == (size_t)archive_write_data(a, data, datasize)); + } + archive_entry_free(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used1)); + for (i = 0; i < 999; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(0, archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Repeat the cycle again, this time setting some compression + * options. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + if (use_prog) + assertEqualIntA(a, ARCHIVE_WARN, + archive_write_add_filter_bzip2(a)); + else + assertEqualIntA(a, ARCHIVE_OK, + archive_write_add_filter_bzip2(a)); + assertEqualIntA(a, ARCHIVE_FAILED, archive_write_set_filter_option(a, + NULL, "nonexistent-option", "0")); + assertEqualIntA(a, ARCHIVE_FAILED, archive_write_set_filter_option(a, + NULL, "compression-level", "abc")); + assertEqualIntA(a, ARCHIVE_FAILED, archive_write_set_filter_option(a, + NULL, "compression-level", "99")); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_filter_option(a, + NULL, "compression-level", "9")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used2)); + for (i = 0; i < 999; i++) { + sprintf(path, "file%03d", i); + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, path); + archive_entry_set_size(ae, datasize); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertA(datasize == (size_t)archive_write_data(a, data, + datasize)); + archive_entry_free(ae); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Curiously, this test fails; the test data above compresses + * better at default compression than at level 9. */ + /* + failure("compression-level=9 wrote %d bytes, default wrote %d bytes", + (int)used2, (int)used1); + assert(used2 < used1); + */ + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used2)); + for (i = 0; i < 999; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(0, archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Repeat again, with much lower compression. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + if (use_prog) + assertEqualIntA(a, ARCHIVE_WARN, + archive_write_add_filter_bzip2(a)); + else + assertEqualIntA(a, ARCHIVE_OK, + archive_write_add_filter_bzip2(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_filter_option(a, + NULL, "compression-level", "1")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used2)); + for (i = 0; i < 999; i++) { + sprintf(path, "file%03d", i); + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, path); + archive_entry_set_size(ae, datasize); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + failure("Writing file %s", path); + assertEqualIntA(a, datasize, + (size_t)archive_write_data(a, data, datasize)); + archive_entry_free(ae); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Level 0 really does result in larger data. */ + failure("Compression-level=0 wrote %d bytes; default wrote %d bytes", + (int)used2, (int)used1); + assert(used2 > used1); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used2)); + for (i = 0; i < 999; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(0, archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Test various premature shutdown scenarios to make sure we + * don't crash or leak memory. + */ + assert((a = archive_write_new()) != NULL); + if (use_prog) + assertEqualIntA(a, ARCHIVE_WARN, + archive_write_add_filter_bzip2(a)); + else + assertEqualIntA(a, ARCHIVE_OK, + archive_write_add_filter_bzip2(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + if (use_prog) + assertEqualIntA(a, ARCHIVE_WARN, + archive_write_add_filter_bzip2(a)); + else + assertEqualIntA(a, ARCHIVE_OK, + archive_write_add_filter_bzip2(a)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + if (use_prog) + assertEqualIntA(a, ARCHIVE_WARN, + archive_write_add_filter_bzip2(a)); + else + assertEqualIntA(a, ARCHIVE_OK, + archive_write_add_filter_bzip2(a)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + if (use_prog) + assertEqualIntA(a, ARCHIVE_WARN, + archive_write_add_filter_bzip2(a)); + else + assertEqualIntA(a, ARCHIVE_OK, + archive_write_add_filter_bzip2(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used2)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Clean up. + */ + free(data); + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_compress.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_compress.c new file mode 100644 index 0000000..1b8910e --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_compress.c @@ -0,0 +1,97 @@ +/*- + * Copyright (c) 2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_compress.c 189308 2009-03-03 17:02:51Z kientzle $"); + +/* + * A basic exercise of compress reading and writing. + * + * TODO: Add a reference file and make sure we can decompress that. + */ + +DEFINE_TEST(test_write_filter_compress) +{ + struct archive_entry *ae; + struct archive* a; + char *buff, *data; + size_t buffsize, datasize; + char path[16]; + size_t used; + int i; + + buffsize = 1000000; + assert(NULL != (buff = (char *)malloc(buffsize))); + + datasize = 10000; + assert(NULL != (data = (char *)malloc(datasize))); + memset(data, 0, datasize); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_add_filter_compress(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, path); + archive_entry_set_size(ae, datasize); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertEqualInt(datasize, + archive_write_data(a, data, datasize)); + archive_entry_free(ae); + } + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Now, read the data back. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + + + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(0, archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + free(data); + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_gzip.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_gzip.c new file mode 100644 index 0000000..935fb51 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_gzip.c @@ -0,0 +1,298 @@ +/*- + * Copyright (c) 2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_compress_gzip.c 191183 2009-04-17 01:06:31Z kientzle $"); + +/* + * A basic exercise of gzip reading and writing. + * + * TODO: Add a reference file and make sure we can decompress that. + */ + +DEFINE_TEST(test_write_filter_gzip) +{ + struct archive_entry *ae; + struct archive* a; + char *buff, *data; + size_t buffsize, datasize; + unsigned char *rbuff; + char path[16]; + size_t used1, used2; + int i, r, use_prog = 0; + + buffsize = 2000000; + assert(NULL != (buff = (char *)malloc(buffsize))); + if (buff == NULL) + return; + + datasize = 10000; + assert(NULL != (data = (char *)malloc(datasize))); + if (data == NULL) { + free(buff); + return; + } + memset(data, 0, datasize); + + /* + * Write a 100 files and read them all back. + * Use default compression level (6). + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + r = archive_write_add_filter_gzip(a); + if (r != ARCHIVE_OK) { + if (canGzip() && r == ARCHIVE_WARN) + use_prog = 1; + else { + skipping("gzip writing not supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); + free(data); + return; + } + } + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualInt(ARCHIVE_FILTER_GZIP, archive_filter_code(a, 0)); + assertEqualString("gzip", archive_filter_name(a, 0)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used1)); + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_size(ae, datasize); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + archive_entry_copy_pathname(ae, path); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertA(datasize + == (size_t)archive_write_data(a, data, datasize)); + } + archive_entry_free(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Basic gzip header tests */ + rbuff = (unsigned char *)buff; + assertEqualInt(rbuff[0], 0x1f); + assertEqualInt(rbuff[1], 0x8b); + assertEqualInt(rbuff[2], 0x08); + assertEqualInt(rbuff[3], 0x00); + assertEqualInt(rbuff[8], 0); /* RFC 1952 flag for compression level 6 */ + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + r = archive_read_support_filter_gzip(a); + if (r == ARCHIVE_WARN) { + skipping("Can't verify gzip writing by reading back;" + " gzip reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used1)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Repeat the cycle again, this time setting some compression + * options. Compression level is 9. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, + archive_write_add_filter_gzip(a)); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_options(a, "gzip:nonexistent-option=0")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "gzip:compression-level=1")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_filter_option(a, NULL, "compression-level", "9")); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_filter_option(a, NULL, "compression-level", "abc")); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_filter_option(a, NULL, "compression-level", "99")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "gzip:compression-level=9")); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, path); + archive_entry_set_size(ae, datasize); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertA(datasize == (size_t)archive_write_data(a, data, datasize)); + archive_entry_free(ae); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Basic gzip header tests */ + rbuff = (unsigned char *)buff; + assertEqualInt(rbuff[0], 0x1f); + assertEqualInt(rbuff[1], 0x8b); + assertEqualInt(rbuff[2], 0x08); + assertEqualInt(rbuff[3], 0x00); + assertEqualInt(rbuff[8], 2); /* RFC 1952 flag for compression level 9 */ + + /* Curiously, this test fails; the test data above compresses + * better at default compression than at level 9. */ + /* + failure("compression-level=9 wrote %d bytes, default wrote %d bytes", + (int)used2, (int)used1); + assert(used2 < used1); + */ + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + r = archive_read_support_filter_gzip(a); + if (r != ARCHIVE_OK && !use_prog) { + skipping("gzip reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used2)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Repeat again, with compression level 1 + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, + archive_write_add_filter_gzip(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_filter_option(a, NULL, "compression-level", "1")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used2)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, path); + archive_entry_set_size(ae, datasize); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + failure("Writing file %s", path); + assertEqualIntA(a, datasize, + (size_t)archive_write_data(a, data, datasize)); + archive_entry_free(ae); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Level 1 really does result in larger data. */ + failure("Compression-level=1 wrote %d bytes; default wrote %d bytes", + (int)used2, (int)used1); + assert(used2 > used1); + + /* Basic gzip header tests */ + rbuff = (unsigned char *)buff; + assertEqualInt(rbuff[0], 0x1f); + assertEqualInt(rbuff[1], 0x8b); + assertEqualInt(rbuff[2], 0x08); + assertEqualInt(rbuff[3], 0x00); + assertEqualInt(rbuff[8], 4); /* RFC 1952 flag for compression level 1 */ + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + r = archive_read_support_filter_gzip(a); + if (r == ARCHIVE_WARN) { + skipping("gzip reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used2)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Test various premature shutdown scenarios to make sure we + * don't crash or leak memory. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, + archive_write_add_filter_gzip(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, + archive_write_add_filter_gzip(a)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, + archive_write_add_filter_gzip(a)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, + archive_write_add_filter_gzip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Clean up. + */ + free(data); + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_gzip_timestamp.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_gzip_timestamp.c new file mode 100644 index 0000000..23b11db --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_gzip_timestamp.c @@ -0,0 +1,118 @@ +/*- + * Copyright (c) 2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_write_filter_gzip_timestamp) +{ + struct archive_entry *ae; + struct archive* a; + char *buff, *data; + size_t buffsize, datasize; + size_t used1; + int r, use_prog = 0; + + buffsize = 10000; + assert(NULL != (buff = (char *)malloc(buffsize))); + if (buff == NULL) + return; + + datasize = 10000; + assert(NULL != (data = (char *)malloc(datasize))); + if (data == NULL) { + free(buff); + return; + } + memset(data, 0, datasize); + + /* Test1: set "gzip:timestamp" option. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + r = archive_write_add_filter_gzip(a); + if (r != ARCHIVE_OK) { + if (canGzip() && r == ARCHIVE_WARN) + use_prog = 1; + else { + skipping("gzip writing not supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); + free(data); + return; + } + } + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "gzip:timestamp")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualInt(ARCHIVE_FILTER_GZIP, archive_filter_code(a, 0)); + assertEqualString("gzip", archive_filter_name(a, 0)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used1)); + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_size(ae, datasize); + archive_entry_copy_pathname(ae, "file"); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertEqualIntA(a, datasize, archive_write_data(a, data, datasize)); + archive_entry_free(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + failure("Timestamp should be recorded"); + assert(memcmp(buff + 4, "\x00\x00\x00\x00", 4) != 0); + + /* Test2: set "gzip:!timestamp" option. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, + archive_write_add_filter_gzip(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "gzip:!timestamp")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualInt(ARCHIVE_FILTER_GZIP, archive_filter_code(a, 0)); + assertEqualString("gzip", archive_filter_name(a, 0)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used1)); + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_size(ae, datasize); + archive_entry_copy_pathname(ae, "file"); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertEqualIntA(a, datasize, archive_write_data(a, data, datasize)); + archive_entry_free(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + failure("Timestamp should not be recorded"); + assertEqualMem(buff + 4, "\x00\x00\x00\x00", 4); + + /* + * Clean up. + */ + free(data); + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_lrzip.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_lrzip.c new file mode 100644 index 0000000..f28c835 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_lrzip.c @@ -0,0 +1,131 @@ +/*- + * Copyright (c) 2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" + +/* + * A basic exercise of lrzip reading and writing. + */ + +DEFINE_TEST(test_write_filter_lrzip) +{ + struct archive_entry *ae; + struct archive* a; + char *buff, *data; + size_t buffsize, datasize; + char path[16]; + size_t used1, used2; + int i; + + if (!canLrzip()) { + skipping("lrzip command-line program not found"); + return; + } + + buffsize = 2000000; + assert(NULL != (buff = (char *)malloc(buffsize))); + + datasize = 10000; + assert(NULL != (data = (char *)malloc(datasize))); + memset(data, 0, datasize); + + /* + * Write 100 files and read them all back. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_gnutar(a)); + assertEqualIntA(a, ARCHIVE_WARN, archive_write_add_filter_lrzip(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualInt(ARCHIVE_FILTER_LRZIP, archive_filter_code(a, 0)); + assertEqualString("lrzip", archive_filter_name(a, 0)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used1)); + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_size(ae, datasize); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + archive_entry_copy_pathname(ae, path); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertA(datasize + == (size_t)archive_write_data(a, data, datasize)); + } + archive_entry_free(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_WARN, archive_read_support_filter_lrzip(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used1)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualInt(ARCHIVE_FILTER_LRZIP, archive_filter_code(a, 0)); + assertEqualString("lrzip", archive_filter_name(a, 0)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Test various premature shutdown scenarios to make sure we + * don't crash or leak memory. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_WARN, archive_write_add_filter_lrzip(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_WARN, archive_write_add_filter_lrzip(a)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_WARN, archive_write_add_filter_lrzip(a)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_WARN, archive_write_add_filter_lrzip(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used2)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Clean up. + */ + free(data); + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_lz4.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_lz4.c new file mode 100644 index 0000000..4f2135a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_lz4.c @@ -0,0 +1,411 @@ +/*- + * Copyright (c) 2014 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * A basic exercise of lz4 reading and writing. + */ + +DEFINE_TEST(test_write_filter_lz4) +{ + struct archive_entry *ae; + struct archive* a; + char *buff, *data; + size_t buffsize, datasize; + char path[16]; + size_t used1, used2; + int i, r, use_prog = 0, filecount; + + assert((a = archive_write_new()) != NULL); + r = archive_write_add_filter_lz4(a); + if (archive_liblz4_version() == NULL) { + if (!canLz4()) { + skipping("lz4 writing not supported on this platform"); + assertEqualInt(ARCHIVE_WARN, r); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + return; + } else { + assertEqualInt(ARCHIVE_WARN, r); + use_prog = 1; + } + } else { + assertEqualInt(ARCHIVE_OK, r); + } + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + buffsize = 2000000; + assert(NULL != (buff = (char *)malloc(buffsize))); + + datasize = 10000; + assert(NULL != (data = (char *)calloc(1, datasize))); + filecount = 10; + + /* + * Write a filecount files and read them all back. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, + archive_write_add_filter_lz4(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 1024)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_in_last_block(a, 1024)); + assertEqualInt(ARCHIVE_FILTER_LZ4, archive_filter_code(a, 0)); + assertEqualString("lz4", archive_filter_name(a, 0)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used1)); + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_size(ae, datasize); + for (i = 0; i < filecount; i++) { + sprintf(path, "file%03d", i); + archive_entry_copy_pathname(ae, path); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertA(datasize + == (size_t)archive_write_data(a, data, datasize)); + } + archive_entry_free(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + r = archive_read_support_filter_lz4(a); + if (r == ARCHIVE_WARN) { + skipping("Can't verify lz4 writing by reading back;" + " lz4 reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used1)); + for (i = 0; i < filecount; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Repeat the cycle again, this time setting some compression + * options. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, + archive_write_add_filter_lz4(a)); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_options(a, "lz4:nonexistent-option=0")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "lz4:compression-level=1")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_filter_option(a, NULL, "compression-level", "9")); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_filter_option(a, NULL, "compression-level", "abc")); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_filter_option(a, NULL, "compression-level", "99")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "lz4:compression-level=9")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used2)); + for (i = 0; i < filecount; i++) { + sprintf(path, "file%03d", i); + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, path); + archive_entry_set_size(ae, datasize); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertA(datasize == (size_t)archive_write_data( + a, data, datasize)); + archive_entry_free(ae); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + failure("compression-level=9 wrote %d bytes, default wrote %d bytes", + (int)used2, (int)used1); + assert(used2 < used1); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + r = archive_read_support_filter_lz4(a); + if (r != ARCHIVE_OK && !use_prog) { + skipping("lz4 reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used2)); + for (i = 0; i < filecount; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Repeat again, with much lower compression. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, + archive_write_add_filter_lz4(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_filter_option(a, NULL, "compression-level", "1")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used2)); + for (i = 0; i < filecount; i++) { + sprintf(path, "file%03d", i); + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, path); + archive_entry_set_size(ae, datasize); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + failure("Writing file %s", path); + assertEqualIntA(a, datasize, + (size_t)archive_write_data(a, data, datasize)); + archive_entry_free(ae); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + +#if 0 + failure("Compression-level=1 wrote %d bytes; default wrote %d bytes", + (int)used2, (int)used1); + assert(used2 > used1); +#endif + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + r = archive_read_support_filter_lz4(a); + if (r == ARCHIVE_WARN) { + skipping("lz4 reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used2)); + for (i = 0; i < filecount; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Test various premature shutdown scenarios to make sure we + * don't crash or leak memory. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, + archive_write_add_filter_lz4(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, + archive_write_add_filter_lz4(a)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, + archive_write_add_filter_lz4(a)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, + archive_write_add_filter_lz4(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used2)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Clean up. + */ + free(data); + free(buff); +} + +static void +test_options(const char *options) +{ + struct archive_entry *ae; + struct archive* a; + char *buff, *data; + size_t buffsize, datasize; + char path[16]; + size_t used1; + int i, r, use_prog = 0, filecount; + + assert((a = archive_write_new()) != NULL); + r = archive_write_add_filter_lz4(a); + if (archive_liblz4_version() == NULL) { + if (!canLz4()) { + skipping("lz4 writing not supported on this platform"); + assertEqualInt(ARCHIVE_WARN, r); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + return; + } else { + assertEqualInt(ARCHIVE_WARN, r); + use_prog = 1; + } + } else { + assertEqualInt(ARCHIVE_OK, r); + } + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + buffsize = 2000000; + assert(NULL != (buff = (char *)malloc(buffsize))); + + datasize = 10000; + assert(NULL != (data = (char *)calloc(1, datasize))); + filecount = 10; + + /* + * Write a filecount files and read them all back. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, + archive_write_add_filter_lz4(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, options)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 1024)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_in_last_block(a, 1024)); + assertEqualInt(ARCHIVE_FILTER_LZ4, archive_filter_code(a, 0)); + assertEqualString("lz4", archive_filter_name(a, 0)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used1)); + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_size(ae, datasize); + for (i = 0; i < filecount; i++) { + sprintf(path, "file%03d", i); + archive_entry_copy_pathname(ae, path); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertA(datasize + == (size_t)archive_write_data(a, data, datasize)); + } + archive_entry_free(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + r = archive_read_support_filter_lz4(a); + if (r == ARCHIVE_WARN) { + skipping("Can't verify lz4 writing by reading back;" + " lz4 reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used1)); + for (i = 0; i < filecount; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Clean up. + */ + free(data); + free(buff); +} + +DEFINE_TEST(test_write_filter_lz4_disable_stream_checksum) +{ + test_options("lz4:!stream-checksum"); +} + +DEFINE_TEST(test_write_filter_lz4_enable_block_checksum) +{ + test_options("lz4:block-checksum"); +} + +DEFINE_TEST(test_write_filter_lz4_block_size_4) +{ + test_options("lz4:block-size=4"); +} + +DEFINE_TEST(test_write_filter_lz4_block_size_5) +{ + test_options("lz4:block-size=5"); +} + +DEFINE_TEST(test_write_filter_lz4_block_size_6) +{ + test_options("lz4:block-size=6"); +} + +DEFINE_TEST(test_write_filter_lz4_block_dependence) +{ + test_options("lz4:block-dependence"); +} + +/* + * TODO: Figure out how to correctly handle this. + * + * This option simply fails on some versions of the LZ4 libraries. + */ +/* +XXXDEFINE_TEST(test_write_filter_lz4_block_dependence_hc) +{ + test_options("lz4:block-dependence,lz4:compression-level=9"); +} +*/ diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_lzip.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_lzip.c new file mode 100644 index 0000000..145a308 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_lzip.c @@ -0,0 +1,255 @@ +/*- + * Copyright (c) 2010 Michihiro NAKAJIMA + * Copyright (c) 2007-2009 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * A basic exercise of lzip reading and writing. + * + */ + +DEFINE_TEST(test_write_filter_lzip) +{ + struct archive_entry *ae; + struct archive* a; + char *buff, *data; + size_t buffsize, datasize; + char path[16]; + size_t used1, used2; + int i, r; + + buffsize = 2000000; + assert(NULL != (buff = (char *)malloc(buffsize))); + if (buff == NULL) + return; + + datasize = 10000; + assert(NULL != (data = (char *)malloc(datasize))); + if (data == NULL) { + free(buff); + return; + } + memset(data, 0, datasize); + + /* + * Write a 100 files and read them all back. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + r = archive_write_add_filter_lzip(a); + if (r == ARCHIVE_FATAL) { + skipping("lzip writing not supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); + free(data); + return; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualInt(ARCHIVE_FILTER_LZIP, archive_filter_code(a, 0)); + assertEqualString("lzip", archive_filter_name(a, 0)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used1)); + assertEqualInt(ARCHIVE_FILTER_LZIP, archive_filter_code(a, 0)); + assertEqualString("lzip", archive_filter_name(a, 0)); + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_size(ae, datasize); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + archive_entry_copy_pathname(ae, path); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertA(datasize + == (size_t)archive_write_data(a, data, datasize)); + } + archive_entry_free(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + r = archive_read_support_filter_lzip(a); + if (r == ARCHIVE_WARN) { + skipping("Can't verify lzip writing by reading back;" + " lzip reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used1)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Repeat the cycle again, this time setting some compression + * options. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_lzip(a)); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_filter_option(a, NULL, "nonexistent-option", "0")); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_filter_option(a, NULL, "compression-level", "abc")); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_filter_option(a, NULL, "compression-level", "99")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_filter_option(a, NULL, "compression-level", "9")); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, path); + archive_entry_set_size(ae, datasize); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertA(datasize == (size_t)archive_write_data(a, data, datasize)); + archive_entry_free(ae); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + r = archive_read_support_filter_lzip(a); + if (r == ARCHIVE_WARN) { + skipping("lzip reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used2)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + failure("Trying to read %s", path); + if (!assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Repeat again, with much lower compression. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_lzip(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_filter_option(a, NULL, "compression-level", "0")); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, path); + archive_entry_set_size(ae, datasize); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + failure("Writing file %s", path); + assertEqualIntA(a, datasize, + (size_t)archive_write_data(a, data, datasize)); + archive_entry_free(ae); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Level 0 really does result in larger data. */ + failure("Compression-level=0 wrote %d bytes; default wrote %d bytes", + (int)used2, (int)used1); + assert(used2 > used1); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + r = archive_read_support_filter_lzip(a); + if (r == ARCHIVE_WARN) { + skipping("lzip reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used2)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Test various premature shutdown scenarios to make sure we + * don't crash or leak memory. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_lzip(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_lzip(a)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_lzip(a)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_lzip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Clean up. + */ + free(data); + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_lzma.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_lzma.c new file mode 100644 index 0000000..68e4898 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_lzma.c @@ -0,0 +1,259 @@ +/*- + * Copyright (c) 2007-2009 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_compress_lzma.c 191183 2009-04-17 01:06:31Z kientzle $"); + +/* + * A basic exercise of lzma reading and writing. + * + */ + +DEFINE_TEST(test_write_filter_lzma) +{ + struct archive_entry *ae; + struct archive* a; + char *buff, *data; + size_t buffsize, datasize; + char path[16]; + size_t used1, used2; + int i, r; + + buffsize = 2000000; + assert(NULL != (buff = (char *)malloc(buffsize))); + if (buff == NULL) + return; + + datasize = 10000; + assert(NULL != (data = (char *)malloc(datasize))); + if (data == NULL) { + free(buff); + return; + } + memset(data, 0, datasize); + + /* + * Write a 100 files and read them all back. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + r = archive_write_add_filter_lzma(a); + if (r == ARCHIVE_FATAL) { + skipping("lzma writing not supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); + free(data); + return; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualInt(ARCHIVE_FILTER_LZMA, archive_filter_code(a, 0)); + assertEqualString("lzma", archive_filter_name(a, 0)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used1)); + assertEqualInt(ARCHIVE_FILTER_LZMA, archive_filter_code(a, 0)); + assertEqualString("lzma", archive_filter_name(a, 0)); + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_size(ae, datasize); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + archive_entry_copy_pathname(ae, path); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertA(datasize + == (size_t)archive_write_data(a, data, datasize)); + } + archive_entry_free(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + r = archive_read_support_filter_lzma(a); + if (r == ARCHIVE_WARN) { + skipping("Can't verify lzma writing by reading back;" + " lzma reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used1)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Repeat the cycle again, this time setting some compression + * options. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_lzma(a)); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_filter_option(a, NULL, "nonexistent-option", "0")); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_filter_option(a, NULL, "compression-level", "abc")); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_filter_option(a, NULL, "compression-level", "99")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_filter_option(a, NULL, "compression-level", "9")); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, path); + archive_entry_set_size(ae, datasize); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertA(datasize == (size_t)archive_write_data(a, data, datasize)); + archive_entry_free(ae); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + r = archive_read_support_filter_lzma(a); + if (r == ARCHIVE_WARN) { + skipping("lzma reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used2)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + failure("Trying to read %s", path); + if (!assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Repeat again, with much lower compression. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_lzma(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_filter_option(a, NULL, "compression-level", "0")); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, path); + archive_entry_set_size(ae, datasize); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + failure("Writing file %s", path); + assertEqualIntA(a, datasize, + (size_t)archive_write_data(a, data, datasize)); + archive_entry_free(ae); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* It would be nice to assert that compression-level=0 produced + * consistently larger/smaller results than the default compression, + * but the results here vary a lot depending on the version of liblzma + * being used. */ + /* + failure("Compression-level=0 wrote %d bytes; default wrote %d bytes", + (int)used2, (int)used1); + assert(used2 > used1); + */ + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + r = archive_read_support_filter_lzma(a); + if (r == ARCHIVE_WARN) { + skipping("lzma reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used2)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Test various premature shutdown scenarios to make sure we + * don't crash or leak memory. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_lzma(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_lzma(a)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_lzma(a)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_lzma(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Clean up. + */ + free(data); + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_lzop.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_lzop.c new file mode 100644 index 0000000..92db7bf --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_lzop.c @@ -0,0 +1,268 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * A basic exercise of lzop reading and writing. + */ + +DEFINE_TEST(test_write_filter_lzop) +{ + struct archive_entry *ae; + struct archive* a; + char *buff, *data; + size_t buffsize, datasize; + char path[16]; + size_t used1, used2; + int i, r, use_prog = 0, filecount; + + assert((a = archive_write_new()) != NULL); + r = archive_write_add_filter_lzop(a); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + if (r != ARCHIVE_OK) { + if (canLzop() && r == ARCHIVE_WARN) + use_prog = 1; + else { + skipping("lzop writing not supported on this platform"); + return; + } + } + + buffsize = 2000000; + assert(NULL != (buff = (char *)malloc(buffsize))); + + datasize = 10000; + assert(NULL != (data = (char *)calloc(1, datasize))); + filecount = 10; + + /* + * Write a filecount files and read them all back. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, + archive_write_add_filter_lzop(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 1024)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_in_last_block(a, 1024)); + assertEqualInt(ARCHIVE_FILTER_LZOP, archive_filter_code(a, 0)); + assertEqualString("lzop", archive_filter_name(a, 0)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used1)); + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_size(ae, datasize); + for (i = 0; i < filecount; i++) { + sprintf(path, "file%03d", i); + archive_entry_copy_pathname(ae, path); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertA(datasize + == (size_t)archive_write_data(a, data, datasize)); + } + archive_entry_free(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + r = archive_read_support_filter_lzop(a); + if (r == ARCHIVE_WARN && !use_prog) { + skipping("Can't verify lzop writing by reading back;" + " lzop reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used1)); + for (i = 0; i < filecount; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Repeat the cycle again, this time setting some compression + * options. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, + archive_write_add_filter_lzop(a)); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_options(a, "lzop:nonexistent-option=0")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "lzop:compression-level=1")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_filter_option(a, NULL, "compression-level", "9")); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_filter_option(a, NULL, "compression-level", "abc")); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_filter_option(a, NULL, "compression-level", "99")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "lzop:compression-level=9")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used2)); + for (i = 0; i < filecount; i++) { + sprintf(path, "file%03d", i); + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, path); + archive_entry_set_size(ae, datasize); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertA(datasize == (size_t)archive_write_data( + a, data, datasize)); + archive_entry_free(ae); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + failure("compression-level=9 wrote %d bytes, default wrote %d bytes", + (int)used2, (int)used1); + assert(used2 < used1); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + r = archive_read_support_filter_lzop(a); + if (r != ARCHIVE_OK && !use_prog) { + skipping("lzop reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used2)); + for (i = 0; i < filecount; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Repeat again, with much lower compression. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, + archive_write_add_filter_lzop(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_filter_option(a, NULL, "compression-level", "1")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used2)); + for (i = 0; i < filecount; i++) { + sprintf(path, "file%03d", i); + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, path); + archive_entry_set_size(ae, datasize); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + failure("Writing file %s", path); + assertEqualIntA(a, datasize, + (size_t)archive_write_data(a, data, datasize)); + archive_entry_free(ae); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + +#if 0 + failure("Compression-level=1 wrote %d bytes; default wrote %d bytes", + (int)used2, (int)used1); + assert(used2 > used1); +#endif + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + r = archive_read_support_filter_lzop(a); + if (r == ARCHIVE_WARN && !use_prog) { + skipping("lzop reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used2)); + for (i = 0; i < filecount; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Test various premature shutdown scenarios to make sure we + * don't crash or leak memory. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, + archive_write_add_filter_lzop(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, + archive_write_add_filter_lzop(a)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, + archive_write_add_filter_lzop(a)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, + archive_write_add_filter_lzop(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used2)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Clean up. + */ + free(data); + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_program.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_program.c new file mode 100644 index 0000000..9fe264c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_program.c @@ -0,0 +1,124 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_compress_program.c 201247 2009-12-30 05:59:21Z kientzle $"); + +static char buff[1000000]; +static char buff2[64]; + +DEFINE_TEST(test_write_filter_program) +{ + struct archive_entry *ae; + struct archive *a; + size_t used; + int blocksize = 1024; + int r; + + if (!canGzip()) { + skipping("Cannot run 'gzip'"); + return; + } + /* NOTE: Setting blocksize=1024 will cause gunzip failure because + * it add extra bytes that gunzip ignores with its warning and + * exit code 1. So we should set blocksize=1 in order not to + * yield the extra bytes when using gunzip. */ + assert((a = archive_read_new()) != NULL); + r = archive_read_support_filter_gzip(a); + if (r != ARCHIVE_OK && canGzip()) + blocksize = 1; + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* Create a new archive in memory. */ + /* Write it through an external "gzip" program. */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_ustar(a)); + r = archive_write_add_filter_program(a, "gzip -6"); + if (r == ARCHIVE_FATAL) { + skipping("Write compression via external " + "program unsupported on this platform"); + archive_write_free(a); + return; + } + assertA(0 == archive_write_set_bytes_per_block(a, blocksize)); + assertA(0 == archive_write_set_bytes_in_last_block(a, blocksize)); + assertA(blocksize == archive_write_get_bytes_in_last_block(a)); + assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used)); + assertA(blocksize == archive_write_get_bytes_in_last_block(a)); + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + archive_entry_copy_pathname(ae, "file"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 8); + + assertA(0 == archive_write_header(a, ae)); + archive_entry_free(ae); + assertA(8 == archive_write_data(a, "12345678", 9)); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Now, read the data back through the built-in gzip support. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + r = archive_read_support_filter_gzip(a); + /* The compression_gzip() handler will fall back to gunzip + * automatically, but if we know gunzip isn't available, then + * skip the rest. */ + if (r != ARCHIVE_OK && !canGzip()) { + skipping("No libz and no gunzip program, " + "unable to verify gzip compression"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + + if (!assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae))) { + archive_read_free(a); + return; + } + + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file", archive_entry_pathname(ae)); + assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "12345678", 8); + + /* Verify the end of the archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_uuencode.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_uuencode.c new file mode 100644 index 0000000..57a4b49 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_uuencode.c @@ -0,0 +1,173 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * A basic exercise of uuencode reading and writing. + */ + +DEFINE_TEST(test_write_filter_uuencode) +{ + struct archive_entry *ae; + struct archive* a; + char *buff, *data; + size_t buffsize, datasize; + char path[16]; + size_t used1, used2; + int i; + + buffsize = 2000000; + assert(NULL != (buff = (char *)malloc(buffsize))); + + datasize = 10000; + assert(NULL != (data = (char *)malloc(datasize))); + memset(data, 0, datasize); + + /* + * Write a 100 files and read them all back. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_uuencode(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualInt(ARCHIVE_FILTER_UU, archive_filter_code(a, 0)); + assertEqualString("uuencode", archive_filter_name(a, 0)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used1)); + for (i = 0; i < 99; i++) { + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_size(ae, datasize); + sprintf(path, "file%03d", i); + archive_entry_copy_pathname(ae, path); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertA(datasize + == (size_t)archive_write_data(a, data, datasize)); + archive_entry_free(ae); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used1)); + for (i = 0; i < 99; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualIntA(a, 0, archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualInt(ARCHIVE_FILTER_UU, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Repeat the cycle again, this time setting name and mode + * options. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_uuencode(a)); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_filter_option(a, NULL, "nonexistent-option", "0")); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_filter_option(a, NULL, "compression-level", "abc")); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_filter_option(a, NULL, "compression-level", "99")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_filter_option(a, NULL, "name", "test.tar")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_filter_option(a, NULL, "mode", "0640")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used2)); + for (i = 0; i < 99; i++) { + sprintf(path, "file%03d", i); + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, path); + archive_entry_set_size(ae, datasize); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertA(datasize == (size_t)archive_write_data(a, data, datasize)); + archive_entry_free(ae); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used2)); + for (i = 0; i < 99; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(0, archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualInt(ARCHIVE_FILTER_UU, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Test various premature shutdown scenarios to make sure we + * don't crash or leak memory. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_uuencode(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_uuencode(a)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_uuencode(a)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_uuencode(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used2)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Clean up. + */ + free(data); + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_xz.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_xz.c new file mode 100644 index 0000000..bf1265c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_xz.c @@ -0,0 +1,265 @@ +/*- + * Copyright (c) 2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_compress_xz.c 191183 2009-04-17 01:06:31Z kientzle $"); + +/* + * A basic exercise of xz reading and writing. + * + * TODO: Add a reference file and make sure we can decompress that. + */ + +DEFINE_TEST(test_write_filter_xz) +{ + struct archive_entry *ae; + struct archive* a; + char *buff, *data; + size_t buffsize, datasize; + char path[16]; + size_t used1, used2; + int i, r; + + buffsize = 2000000; + assert(NULL != (buff = (char *)malloc(buffsize))); + if (buff == NULL) + return; + + datasize = 10000; + assert(NULL != (data = (char *)malloc(datasize))); + if (data == NULL) { + free(buff); + return; + } + memset(data, 0, datasize); + + /* + * Write a 100 files and read them all back. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + r = archive_write_add_filter_xz(a); + if (r == ARCHIVE_FATAL) { + skipping("xz writing not supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); + free(data); + return; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualInt(ARCHIVE_FILTER_XZ, archive_filter_code(a, 0)); + assertEqualString("xz", archive_filter_name(a, 0)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used1)); + assertEqualInt(ARCHIVE_FILTER_XZ, archive_filter_code(a, 0)); + assertEqualString("xz", archive_filter_name(a, 0)); + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_size(ae, datasize); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + archive_entry_copy_pathname(ae, path); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertA(datasize + == (size_t)archive_write_data(a, data, datasize)); + } + archive_entry_free(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + r = archive_read_support_filter_xz(a); + if (r == ARCHIVE_WARN) { + skipping("Can't verify xz writing by reading back;" + " xz reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used1)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Repeat the cycle again, this time setting some compression + * options. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_xz(a)); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_filter_option(a, NULL, "nonexistent-option", "0")); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_filter_option(a, NULL, "compression-level", "abc")); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_filter_option(a, NULL, "compression-level", "99")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_filter_option(a, NULL, "compression-level", "9")); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, path); + archive_entry_set_size(ae, datasize); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertA(datasize == (size_t)archive_write_data(a, data, datasize)); + archive_entry_free(ae); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Curiously, this test fails; the test data above compresses + * better at default compression than at level 9. */ + /* + failure("compression-level=9 wrote %d bytes, default wrote %d bytes", + (int)used2, (int)used1); + assert(used2 < used1); + */ + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + r = archive_read_support_filter_xz(a); + if (r == ARCHIVE_WARN) { + skipping("xz reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used2)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + failure("Trying to read %s", path); + if (!assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Repeat again, with much lower compression. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_xz(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_filter_option(a, NULL, "compression-level", "0")); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, path); + archive_entry_set_size(ae, datasize); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + failure("Writing file %s", path); + assertEqualIntA(a, datasize, + (size_t)archive_write_data(a, data, datasize)); + archive_entry_free(ae); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* I would like to assert that compression-level=0 results in + * larger data than the default compression, but that's not true + * for all versions of liblzma. */ + /* + failure("Compression-level=0 wrote %d bytes; default wrote %d bytes", + (int)used2, (int)used1); + assert(used2 > used1); + */ + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + r = archive_read_support_filter_xz(a); + if (r == ARCHIVE_WARN) { + skipping("xz reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used2)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Test various premature shutdown scenarios to make sure we + * don't crash or leak memory. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_xz(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_xz(a)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_xz(a)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_xz(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Clean up. + */ + free(data); + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_zstd.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_zstd.c new file mode 100644 index 0000000..ba1b6bf --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_filter_zstd.c @@ -0,0 +1,255 @@ +/*- + * Copyright (c) 2017 Sean Purcell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_write_filter_zstd) +{ + struct archive_entry *ae; + struct archive *a; + char *buff, *data; + size_t buffsize, datasize; + char path[16]; + size_t used1, used2, used3; + int i, r; + + buffsize = 2000000; + assert(NULL != (buff = (char *)malloc(buffsize))); + if (buff == NULL) + return; + + datasize = 10000; + assert(NULL != (data = (char *)malloc(datasize))); + if (data == NULL) { + free(buff); + return; + } + memset(data, 0, datasize); + + /* + * Write a 100 files and read them all back. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + r = archive_write_add_filter_zstd(a); + if (r != ARCHIVE_OK) { + skipping("zstd writing not supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); + free(data); + return; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualInt(ARCHIVE_FILTER_ZSTD, archive_filter_code(a, 0)); + assertEqualString("zstd", archive_filter_name(a, 0)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used1)); + assertEqualInt(ARCHIVE_FILTER_ZSTD, archive_filter_code(a, 0)); + assertEqualString("zstd", archive_filter_name(a, 0)); + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_size(ae, datasize); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + archive_entry_copy_pathname(ae, path); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertA(datasize + == (size_t)archive_write_data(a, data, datasize)); + } + archive_entry_free(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + r = archive_read_support_filter_zstd(a); + if (r == ARCHIVE_WARN) { + skipping("Can't verify zstd writing by reading back;" + " zstd reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used1)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Repeat the cycle again, this time setting some compression + * options. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_zstd(a)); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_filter_option(a, NULL, "nonexistent-option", "0")); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_filter_option(a, NULL, "compression-level", "abc")); + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_filter_option(a, NULL, "compression-level", "25")); /* too big */ + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_filter_option(a, NULL, "compression-level", "9")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_filter_option(a, NULL, "compression-level", "7")); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, path); + archive_entry_set_size(ae, datasize); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertA(datasize == (size_t)archive_write_data(a, data, datasize)); + archive_entry_free(ae); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + r = archive_read_support_filter_zstd(a); + if (r == ARCHIVE_WARN) { + skipping("zstd reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used2)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + failure("Trying to read %s", path); + if (!assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * One more time at level 1 + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_zstd(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_filter_option(a, NULL, "compression-level", "1")); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used3)); + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_size(ae, datasize); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + archive_entry_copy_pathname(ae, path); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertA(datasize == (size_t)archive_write_data(a, data, datasize)); + } + archive_entry_free(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + r = archive_read_support_filter_zstd(a); + if (r == ARCHIVE_WARN) { + skipping("zstd reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used3)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + failure("Trying to read %s", path); + if (!assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Check output sizes for various compression levels, expectation + * is that archive size for level=7 < default < level=1 + */ + failure("compression-level=7 wrote %d bytes, default wrote %d bytes", + (int)used2, (int)used1); + assert(used2 < used1); + failure("compression-level=1 wrote %d bytes, default wrote %d bytes", + (int)used3, (int)used1); + assert(used1 < used3); + + /* + * Test various premature shutdown scenarios to make sure we + * don't crash or leak memory. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_zstd(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_zstd(a)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_zstd(a)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_zstd(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Clean up. + */ + free(data); + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_7zip.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_7zip.c new file mode 100644 index 0000000..c8fdcd0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_7zip.c @@ -0,0 +1,570 @@ +/*- + * Copyright (c) 2011-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "test.h" +__FBSDID("$FreeBSD$"); + +static void +test_basic(const char *compression_type) +{ + char filedata[64]; + struct archive_entry *ae; + struct archive *a; + size_t used; + size_t buffsize = 1000; + char *buff; + + buff = malloc(buffsize); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_7zip(a)); + if (compression_type != NULL && + ARCHIVE_OK != archive_write_set_format_option(a, "7zip", + "compression", compression_type)) { + skipping("%s writing not fully supported on this platform", + compression_type); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + + /* + * Write an empty file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(10, archive_entry_mtime_nsec(ae)); + archive_entry_copy_pathname(ae, "empty"); + assertEqualString("empty", archive_entry_pathname(ae)); + archive_entry_set_mode(ae, AE_IFREG | 0755); + assertEqualInt((AE_IFREG | 0755), archive_entry_mode(ae)); + + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* + * Write another empty file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(10, archive_entry_mtime_nsec(ae)); + archive_entry_copy_pathname(ae, "empty2"); + assertEqualString("empty2", archive_entry_pathname(ae)); + archive_entry_set_mode(ae, AE_IFREG | 0444); + assertEqualInt((AE_IFREG | 0444), archive_entry_mode(ae)); + + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 100); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(100, archive_entry_mtime_nsec(ae)); + archive_entry_copy_pathname(ae, "file"); + assertEqualString("file", archive_entry_pathname(ae)); + archive_entry_set_mode(ae, AE_IFREG | 0755); + assertEqualInt((AE_IFREG | 0755), archive_entry_mode(ae)); + archive_entry_set_size(ae, 8); + + assertEqualInt(0, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(8, archive_write_data(a, "12345678", 9)); + assertEqualInt(0, archive_write_data(a, "1", 1)); + + /* + * Write another file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(10, archive_entry_mtime_nsec(ae)); + archive_entry_copy_pathname(ae, "file2"); + assertEqualString("file2", archive_entry_pathname(ae)); + archive_entry_set_mode(ae, AE_IFREG | 0755); + assertEqualInt((AE_IFREG | 0755), archive_entry_mode(ae)); + archive_entry_set_size(ae, 4); + + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(4, archive_write_data(a, "1234", 5)); + + /* + * Write a symbolic file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(10, archive_entry_mtime_nsec(ae)); + archive_entry_copy_pathname(ae, "symbolic"); + archive_entry_copy_symlink(ae, "file1"); + assertEqualString("symbolic", archive_entry_pathname(ae)); + archive_entry_set_mode(ae, AE_IFLNK | 0755); + assertEqualInt((AE_IFLNK | 0755), archive_entry_mode(ae)); + + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* + * Write a directory to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 11, 100); + archive_entry_copy_pathname(ae, "dir"); + archive_entry_set_mode(ae, AE_IFDIR | 0755); + archive_entry_set_size(ae, 512); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + failure("size should be zero so that applications know not to write"); + assertEqualInt(0, archive_entry_size(ae)); + archive_entry_free(ae); + assertEqualIntA(a, 0, archive_write_data(a, "12345678", 9)); + + /* + * Write a sub directory to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 11, 200); + archive_entry_copy_pathname(ae, "dir/subdir"); + archive_entry_set_mode(ae, AE_IFDIR | 0755); + archive_entry_set_size(ae, 512); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + failure("size should be zero so that applications know not to write"); + assertEqualInt(0, archive_entry_size(ae)); + archive_entry_free(ae); + assertEqualIntA(a, 0, archive_write_data(a, "12345678", 9)); + + /* + * Write a sub sub-directory to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 11, 300); + archive_entry_copy_pathname(ae, "dir/subdir/subdir"); + archive_entry_set_mode(ae, AE_IFDIR | 0755); + archive_entry_set_size(ae, 512); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + failure("size should be zero so that applications know not to write"); + assertEqualInt(0, archive_entry_size(ae)); + archive_entry_free(ae); + assertEqualIntA(a, 0, archive_write_data(a, "12345678", 9)); + + /* Close out the archive. */ + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Verify the initial header. */ + assertEqualMem(buff, "\x37\x7a\xbc\xaf\x27\x1c\x00\x03", 8); + + /* + * Now, read the data back. + */ + /* With the test memory reader -- seeking mode. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7)); + + /* + * Read and verify first file. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(100, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, + archive_read_data(a, filedata, sizeof(filedata))); + assertEqualMem(filedata, "12345678", 8); + + + /* + * Read the second file back. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file2", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); + assertEqualInt(4, archive_entry_size(ae)); + assertEqualIntA(a, 4, + archive_read_data(a, filedata, sizeof(filedata))); + assertEqualMem(filedata, "1234", 4); + + /* + * Read and verify a symbolic file. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("symbolic", archive_entry_pathname(ae)); + assertEqualString("file1", archive_entry_symlink(ae)); + assertEqualInt(AE_IFLNK | 0755, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + + /* + * Read and verify an empty file. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("empty", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + + /* + * Read and verify an empty file. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("empty2", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG | 0444, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + + /* + * Read the sub sub-dir entry back. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(11, archive_entry_mtime(ae)); + assertEqualInt(300, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("dir/subdir/subdir/", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR | 0755, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualIntA(a, 0, archive_read_data(a, filedata, 10)); + + /* + * Read the sub dir entry back. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(11, archive_entry_mtime(ae)); + assertEqualInt(200, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("dir/subdir/", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR | 0755, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualIntA(a, 0, archive_read_data(a, filedata, 10)); + + /* + * Read the dir entry back. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(11, archive_entry_mtime(ae)); + assertEqualInt(100, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("dir/", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR | 0755, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualIntA(a, 0, archive_read_data(a, filedata, 10)); + + /* Verify the end of the archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + free(buff); +} + +static void +test_basic2(const char *compression_type) +{ + char filedata[64]; + struct archive_entry *ae; + struct archive *a; + size_t used; + size_t buffsize = 1000; + char *buff; + + buff = malloc(buffsize); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_7zip(a)); + if (compression_type != NULL && + ARCHIVE_OK != archive_write_set_format_option(a, "7zip", + "compression", compression_type)) { + skipping("%s writing not fully supported on this platform", + compression_type); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 100); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(100, archive_entry_mtime_nsec(ae)); + archive_entry_copy_pathname(ae, "file"); + assertEqualString("file", archive_entry_pathname(ae)); + archive_entry_set_mode(ae, AE_IFREG | 0755); + assertEqualInt((AE_IFREG | 0755), archive_entry_mode(ae)); + archive_entry_set_size(ae, 8); + + assertEqualInt(0, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(8, archive_write_data(a, "12345678", 9)); + assertEqualInt(0, archive_write_data(a, "1", 1)); + + /* + * Write another file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(10, archive_entry_mtime_nsec(ae)); + archive_entry_copy_pathname(ae, "file2"); + assertEqualString("file2", archive_entry_pathname(ae)); + archive_entry_set_mode(ae, AE_IFREG | 0755); + assertEqualInt((AE_IFREG | 0755), archive_entry_mode(ae)); + archive_entry_set_size(ae, 4); + + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(4, archive_write_data(a, "1234", 5)); + + /* + * Write a directory to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 11, 100); + archive_entry_copy_pathname(ae, "dir"); + archive_entry_set_mode(ae, AE_IFDIR | 0755); + archive_entry_set_size(ae, 512); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + failure("size should be zero so that applications know not to write"); + assertEqualInt(0, archive_entry_size(ae)); + archive_entry_free(ae); + assertEqualIntA(a, 0, archive_write_data(a, "12345678", 9)); + + /* + * Write a sub directory to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 11, 200); + archive_entry_copy_pathname(ae, "dir/subdir"); + archive_entry_set_mode(ae, AE_IFDIR | 0755); + archive_entry_set_size(ae, 512); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + failure("size should be zero so that applications know not to write"); + assertEqualInt(0, archive_entry_size(ae)); + archive_entry_free(ae); + assertEqualIntA(a, 0, archive_write_data(a, "12345678", 9)); + + /* + * Write a sub sub-directory to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 11, 300); + archive_entry_copy_pathname(ae, "dir/subdir/subdir"); + archive_entry_set_mode(ae, AE_IFDIR | 0755); + archive_entry_set_size(ae, 512); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + failure("size should be zero so that applications know not to write"); + assertEqualInt(0, archive_entry_size(ae)); + archive_entry_free(ae); + assertEqualIntA(a, 0, archive_write_data(a, "12345678", 9)); + + /* Close out the archive. */ + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Verify the initial header. */ + assertEqualMem(buff, "\x37\x7a\xbc\xaf\x27\x1c\x00\x03", 8); + + /* + * Now, read the data back. + */ + /* With the test memory reader -- seeking mode. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7)); + + /* + * Read and verify first file. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(100, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, + archive_read_data(a, filedata, sizeof(filedata))); + assertEqualMem(filedata, "12345678", 8); + + + /* + * Read the second file back. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file2", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); + assertEqualInt(4, archive_entry_size(ae)); + assertEqualIntA(a, 4, + archive_read_data(a, filedata, sizeof(filedata))); + assertEqualMem(filedata, "1234", 4); + + /* + * Read the sub sub-dir entry back. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(11, archive_entry_mtime(ae)); + assertEqualInt(300, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("dir/subdir/subdir/", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR | 0755, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualIntA(a, 0, archive_read_data(a, filedata, 10)); + + /* + * Read the sub dir entry back. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(11, archive_entry_mtime(ae)); + assertEqualInt(200, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("dir/subdir/", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR | 0755, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualIntA(a, 0, archive_read_data(a, filedata, 10)); + + /* + * Read the dir entry back. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(11, archive_entry_mtime(ae)); + assertEqualInt(100, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("dir/", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR | 0755, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualIntA(a, 0, archive_read_data(a, filedata, 10)); + + /* Verify the end of the archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + free(buff); +} + +DEFINE_TEST(test_write_format_7zip) +{ + /* Test that making a 7-Zip archive file by default compression + * in whatever compressions are supported on the running platform. */ + test_basic(NULL); + /* Test that making a 7-Zip archive file without empty files. */ + test_basic2(NULL); +} + +DEFINE_TEST(test_write_format_7zip_basic_bzip2) +{ + /* Test that making a 7-Zip archive file with bzip2 compression. */ + test_basic("bzip2"); +} + +DEFINE_TEST(test_write_format_7zip_basic_copy) +{ + /* Test that making a 7-Zip archive file without compression. */ + test_basic("copy"); +} + +DEFINE_TEST(test_write_format_7zip_basic_deflate) +{ + /* Test that making a 7-Zip archive file with deflate compression. */ + test_basic("deflate"); +} + +DEFINE_TEST(test_write_format_7zip_basic_lzma1) +{ + /* Test that making a 7-Zip archive file with lzma1 compression. */ + test_basic("lzma1"); +} + +DEFINE_TEST(test_write_format_7zip_basic_lzma2) +{ + /* Test that making a 7-Zip archive file with lzma2 compression. */ + test_basic("lzma2"); +} + +DEFINE_TEST(test_write_format_7zip_basic_ppmd) +{ + /* Test that making a 7-Zip archive file with PPMd compression. */ + test_basic("ppmd"); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_7zip_empty.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_7zip_empty.c new file mode 100644 index 0000000..9a503e9 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_7zip_empty.c @@ -0,0 +1,299 @@ +/*- + * Copyright (c) 2011-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * Test writing an empty archive. + */ +DEFINE_TEST(test_write_format_7zip_empty_archive) +{ + struct archive *a; + size_t buffsize = 1000; + char *buff; + size_t used; + + buff = malloc(buffsize); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_7zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + + /* Close out the archive. */ + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Verify the archive file size. */ + assertEqualInt(32, used); + + /* Verify the initial header. */ + assertEqualMem(buff, + "\x37\x7a\xbc\xaf\x27\x1c\x00\x03" + "\x8d\x9b\xd5\x0f\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", 32); + + free(buff); +} + +/* + * Test writing an empty file. + */ +static void +test_only_empty_file(void) +{ + struct archive *a; + struct archive_entry *ae; + size_t buffsize = 1000; + char *buff; + size_t used; + + buff = malloc(buffsize); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_7zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + + /* + * Write an empty file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(10, archive_entry_mtime_nsec(ae)); + archive_entry_set_atime(ae, 2, 20); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(20, archive_entry_atime_nsec(ae)); + archive_entry_set_ctime(ae, 0, 100); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualInt(100, archive_entry_ctime_nsec(ae)); + archive_entry_copy_pathname(ae, "empty"); + assertEqualString("empty", archive_entry_pathname(ae)); + archive_entry_set_mode(ae, AE_IFREG | 0755); + assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae)); + + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Close out the archive. */ + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Verify the archive file size. */ + assertEqualInt(102, used); + + /* Verify the initial header. */ + assertEqualMem(buff, + "\x37\x7a\xbc\xaf\x27\x1c\x00\x03" + "\x00\x5b\x58\x25\x00\x00\x00\x00" + "\x00\x00\x00\x00\x46\x00\x00\x00" + "\x00\x00\x00\x00\x8f\xce\x1d\xf3", 32); + + /* + * Now, read the data back. + */ + /* With the test memory reader -- seeking mode. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7)); + + /* + * Read and verify an empty file. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_atime_nsec(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualInt(100, archive_entry_ctime_nsec(ae)); + assertEqualString("empty", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + + /* Verify the end of the archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + free(buff); +} + +static void +test_only_empty_files(void) +{ + struct archive *a; + struct archive_entry *ae; + size_t buffsize = 1000; + char *buff; + size_t used; + + buff = malloc(buffsize); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_7zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + + /* + * Write an empty file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(10, archive_entry_mtime_nsec(ae)); + archive_entry_set_atime(ae, 2, 20); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(20, archive_entry_atime_nsec(ae)); + archive_entry_copy_pathname(ae, "empty"); + assertEqualString("empty", archive_entry_pathname(ae)); + archive_entry_set_mode(ae, AE_IFREG | 0755); + assertEqualInt((AE_IFREG | 0755), archive_entry_mode(ae)); + + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* + * Write second empty file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 2, 10); + assertEqualInt(2, archive_entry_mtime(ae)); + assertEqualInt(10, archive_entry_mtime_nsec(ae)); + archive_entry_set_ctime(ae, 2, 10); + assertEqualInt(2, archive_entry_ctime(ae)); + assertEqualInt(10, archive_entry_ctime_nsec(ae)); + archive_entry_copy_pathname(ae, "empty2"); + assertEqualString("empty2", archive_entry_pathname(ae)); + archive_entry_set_mode(ae, AE_IFREG | 0644); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* + * Write third empty file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 3, 10); + assertEqualInt(3, archive_entry_mtime(ae)); + assertEqualInt(10, archive_entry_mtime_nsec(ae)); + archive_entry_copy_pathname(ae, "empty3"); + assertEqualString("empty3", archive_entry_pathname(ae)); + archive_entry_set_mode(ae, AE_IFREG | 0644); + assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); + + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Close out the archive. */ + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Verify the initial header. */ + assertEqualMem(buff, "\x37\x7a\xbc\xaf\x27\x1c\x00\x03", 8); + + /* + * Now, read the data back. + */ + /* With the test memory reader -- seeking mode. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7)); + + /* + * Read and verify an empty file. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_atime_nsec(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("empty", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + + /* + * Read and verify second empty file. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(2, archive_entry_ctime(ae)); + assertEqualInt(0, archive_entry_ctime_nsec(ae)); + assertEqualString("empty2", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG | 0644, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + + /* + * Read and verify third empty file. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(3, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("empty3", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG | 0644, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + + /* Verify the end of the archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + free(buff); +} + +DEFINE_TEST(test_write_format_7zip_empty_files) +{ + /* Test that write an empty file. */ + test_only_empty_file(); + test_only_empty_files(); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_7zip_large.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_7zip_large.c new file mode 100644 index 0000000..5c49f59 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_7zip_large.c @@ -0,0 +1,174 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "test.h" +__FBSDID("$FreeBSD$"); + +#define LARGE_SIZE (16*1024*1024) +static void +test_large(const char *compression_type) +{ + struct archive_entry *ae; + struct archive *a; + size_t used; + size_t buffsize = LARGE_SIZE + 1024 * 256; + size_t datasize = LARGE_SIZE; + char *buff, *filedata, *filedata2; + unsigned i; + + assert((buff = malloc(buffsize)) != NULL); + assert((filedata = malloc(datasize)) != NULL); + assert((filedata2 = malloc(datasize)) != NULL); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + if (a == NULL || buff == NULL || filedata == NULL || filedata2 == NULL) { + archive_write_free(a); + free(buff); + free(filedata); + free(filedata2); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_7zip(a)); + if (compression_type != NULL && + ARCHIVE_OK != archive_write_set_format_option(a, "7zip", + "compression", compression_type)) { + skipping("%s writing not fully supported on this platform", + compression_type); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); + free(filedata); + free(filedata2); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + + /* + * Write a large file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 100); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(100, archive_entry_mtime_nsec(ae)); + archive_entry_copy_pathname(ae, "file"); + assertEqualString("file", archive_entry_pathname(ae)); + archive_entry_set_mode(ae, AE_IFREG | 0755); + assertEqualInt((AE_IFREG | 0755), archive_entry_mode(ae)); + archive_entry_set_size(ae, datasize); + + assertEqualInt(0, archive_write_header(a, ae)); + archive_entry_free(ae); + if (strcmp(compression_type, "ppmd") == 0) { + /* NOTE: PPMd cannot handle random data correctly.*/ + memset(filedata, 'a', datasize); + } else { + for (i = 0; i < datasize; i++) + filedata[i] = (char)rand(); + } + assertEqualInt(datasize, archive_write_data(a, filedata, datasize)); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Verify the initial header. */ + assertEqualMem(buff, "\x37\x7a\xbc\xaf\x27\x1c\x00\x03", 8); + + /* + * Now, read the data back. + */ + /* With the test memory reader -- seeking mode. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7)); + + /* + * Read and verify a large file. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(100, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); + assertEqualInt(datasize, archive_entry_size(ae)); + assertEqualIntA(a, datasize, archive_read_data(a, filedata2, datasize)); + assertEqualMem(filedata, filedata2, datasize); + + /* Verify the end of the archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + free(buff); + free(filedata); + free(filedata2); +} + +DEFINE_TEST(test_write_format_7zip_large_bzip2) +{ + /* Test that making a 7-Zip archive file with bzip2 compression. */ + test_large("bzip2"); +} + +DEFINE_TEST(test_write_format_7zip_large_copy) +{ + /* Test that making a 7-Zip archive file without compression. */ + test_large("copy"); +} + +DEFINE_TEST(test_write_format_7zip_large_deflate) +{ + /* Test that making a 7-Zip archive file with deflate compression. */ + test_large("deflate"); +} + +DEFINE_TEST(test_write_format_7zip_large_lzma1) +{ + /* Test that making a 7-Zip archive file with lzma1 compression. */ + test_large("lzma1"); +} + +DEFINE_TEST(test_write_format_7zip_large_lzma2) +{ + /* Test that making a 7-Zip archive file with lzma2 compression. */ + test_large("lzma2"); +} + +DEFINE_TEST(test_write_format_7zip_large_ppmd) +{ + /* Test that making a 7-Zip archive file with PPMd compression. */ + test_large("ppmd"); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_ar.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_ar.c new file mode 100644 index 0000000..058d3b1 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_ar.c @@ -0,0 +1,192 @@ +/*- + * Copyright (c) 2007 Kai Wang + * Copyright (c) 2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_format_ar.c 189308 2009-03-03 17:02:51Z kientzle $"); + +static char buff[4096]; +static char buff2[64]; +static char strtab[] = "abcdefghijklmn.o/\nggghhhjjjrrrttt.o/\niiijjjdddsssppp.o/\n"; + +DEFINE_TEST(test_write_format_ar) +{ + struct archive_entry *ae; + struct archive* a; + size_t used; + + /* + * First we try to create a SVR4/GNU format archive. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ar_svr4(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used)); + + /* write the filename table */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "//"); + archive_entry_set_size(ae, strlen(strtab)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertA(strlen(strtab) == (size_t)archive_write_data(a, strtab, strlen(strtab))); + archive_entry_free(ae); + + /* write entries */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 0); + assert(1 == archive_entry_mtime(ae)); + archive_entry_set_mode(ae, S_IFREG | 0755); + assert((S_IFREG | 0755) == archive_entry_mode(ae)); + archive_entry_copy_pathname(ae, "abcdefghijklmn.o"); + archive_entry_set_size(ae, 8); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertA(8 == archive_write_data(a, "87654321", 15)); + archive_entry_free(ae); + + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "ggghhhjjjrrrttt.o"); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_size(ae, 7); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertEqualIntA(a, 7, archive_write_data(a, "7777777", 7)); + archive_entry_free(ae); + + /* test full pathname */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "/usr/home/xx/iiijjjdddsssppp.o"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 8); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertEqualIntA(a, 8, archive_write_data(a, "88877766", 8)); + archive_entry_free(ae); + + /* trailing "/" should be rejected */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "/usr/home/xx/iiijjj/"); + archive_entry_set_size(ae, 8); + assertA(0 != archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Non regular file should be rejected */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "gfgh.o"); + archive_entry_set_mode(ae, S_IFDIR | 0755); + archive_entry_set_size(ae, 6); + assertA(0 != archive_write_header(a, ae)); + archive_entry_free(ae); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(archive_filter_bytes(a, -1), + archive_filter_bytes(a, 0)); + assertEqualInt(used, archive_filter_bytes(a, 0)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Now, read the data back. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(0, archive_entry_mtime(ae)); + assertEqualString("//", archive_entry_pathname(ae)); + assertEqualInt(0, archive_entry_size(ae)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualString("abcdefghijklmn.o", archive_entry_pathname(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "87654321", 8); + + assertEqualInt(ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ggghhhjjjrrrttt.o", archive_entry_pathname(ae)); + assertEqualInt(7, archive_entry_size(ae)); + assertEqualIntA(a, 7, archive_read_data(a, buff2, 11)); + assertEqualMem(buff2, "7777777", 7); + + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualString("iiijjjdddsssppp.o", archive_entry_pathname(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff2, 17)); + assertEqualMem(buff2, "88877766", 8); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Then, we try to create a BSD format archive. + */ + memset(buff, 0, sizeof(buff)); + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ar_bsd(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used)); + + /* write a entry need long name extension */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "ttttyyyyuuuuiiii.o"); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_size(ae, 5); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertEqualInt(5, archive_entry_size(ae)); + assertEqualIntA(a, 5, archive_write_data(a, "12345", 7)); + archive_entry_free(ae); + + /* write a entry with a short name */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "ttyy.o"); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_size(ae, 6); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertEqualIntA(a, 6, archive_write_data(a, "555555", 7)); + archive_entry_free(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Now, Read the data back */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualString("ttttyyyyuuuuiiii.o", archive_entry_pathname(ae)); + assertEqualInt(5, archive_entry_size(ae)); + assertEqualIntA(a, 5, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "12345", 5); + + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualString("ttyy.o", archive_entry_pathname(ae)); + assertEqualInt(6, archive_entry_size(ae)); + assertEqualIntA(a, 6, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "555555", 6); + + /* Test EOF */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_cpio.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_cpio.c new file mode 100644 index 0000000..9f7307f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_cpio.c @@ -0,0 +1,270 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_format_cpio.c 185672 2008-12-06 06:02:26Z kientzle $"); + +static void +test_format(int (*set_format)(struct archive *)) +{ + char filedata[64]; + struct archive_entry *ae; + struct archive *a; + char *p; + size_t used; + size_t buffsize = 1000000; + char *buff; + int damaged = 0; + + buff = malloc(buffsize); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertA(0 == (*set_format)(a)); + assertA(0 == archive_write_add_filter_none(a)); + assertA(0 == archive_write_open_memory(a, buff, buffsize, &used)); + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + assert(1 == archive_entry_mtime(ae)); + assert(10 == archive_entry_mtime_nsec(ae)); + p = strdup("file"); + archive_entry_copy_pathname(ae, p); + strcpy(p, "XXXX"); + free(p); + assertEqualString("file", archive_entry_pathname(ae)); + archive_entry_set_mode(ae, S_IFREG | 0755); + assert((S_IFREG | 0755) == archive_entry_mode(ae)); + archive_entry_set_size(ae, 8); + + assertA(0 == archive_write_header(a, ae)); + archive_entry_free(ae); + assertA(8 == archive_write_data(a, "12345678", 9)); + + /* + * Write another file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + assert(1 == archive_entry_mtime(ae)); + assert(10 == archive_entry_mtime_nsec(ae)); + p = strdup("file2"); + archive_entry_copy_pathname(ae, p); + strcpy(p, "XXXX"); + free(p); + assertEqualString("file2", archive_entry_pathname(ae)); + archive_entry_set_mode(ae, S_IFREG | 0755); + assert((S_IFREG | 0755) == archive_entry_mode(ae)); + archive_entry_set_size(ae, 4); + + assertA(0 == archive_write_header(a, ae)); + archive_entry_free(ae); + assertA(4 == archive_write_data(a, "1234", 5)); + + /* + * Write a file with a name, filetype, and size. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "name"); + archive_entry_set_size(ae, 0); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + assert(archive_error_string(a) == NULL); + archive_entry_free(ae); + + /* + * Write a file with a name and filetype but no size. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "name"); + archive_entry_unset_size(ae); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae)); + assert(archive_error_string(a) != NULL); + archive_entry_free(ae); + + /* + * Write a file with a name and size but no filetype. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "name"); + archive_entry_set_size(ae, 0); + assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae)); + assert(archive_error_string(a) != NULL); + archive_entry_free(ae); + + /* + * Write a file with a size and filetype but no name. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_size(ae, 0); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae)); + assert(archive_error_string(a) != NULL); + archive_entry_free(ae); + + /* + * Write a directory to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 11, 110); + archive_entry_copy_pathname(ae, "dir"); + archive_entry_set_mode(ae, S_IFDIR | 0755); + archive_entry_set_size(ae, 512); + + assertA(0 == archive_write_header(a, ae)); + assertEqualInt(0, archive_entry_size(ae)); + archive_entry_free(ae); + assertEqualIntA(a, 0, archive_write_data(a, "12345678", 9)); + + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Damage the second entry to test the search-ahead recovery. + * TODO: Move the damage-recovery checking to a separate test; + * it doesn't really belong in this write test. + */ + { + int i; + for (i = 80; i < 150; i++) { + if (memcmp(buff + i, "07070", 5) == 0) { + damaged = 1; + buff[i] = 'X'; + break; + } + } + } + failure("Unable to locate the second header for damage-recovery test."); + assert(damaged == 1); + + /* + * Now, read the data back. + */ + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_open_memory(a, buff, used)); + + if (!assertEqualIntA(a, 0, archive_read_next_header(a, &ae))) { + archive_read_free(a); + return; + } + + assertEqualInt(1, archive_entry_mtime(ae)); + /* Not the same as above: cpio doesn't store hi-res times. */ + assert(0 == archive_entry_mtime_nsec(ae)); + assert(0 == archive_entry_atime(ae)); + assert(0 == archive_entry_ctime(ae)); + assertEqualString("file", archive_entry_pathname(ae)); + assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertA(8 == archive_read_data(a, filedata, 10)); + assertEqualMem(filedata, "12345678", 8); + + /* + * The second file can't be read because we damaged its header. + */ + + /* + * Read the third file back. + * ARCHIVE_WARN here because the damaged entry was skipped. + */ + assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae)); + assertEqualString("name", archive_entry_pathname(ae)); + + /* + * Read the dir entry back. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(11, archive_entry_mtime(ae)); + assert(0 == archive_entry_mtime_nsec(ae)); + assert(0 == archive_entry_atime(ae)); + assert(0 == archive_entry_ctime(ae)); + assertEqualString("dir", archive_entry_pathname(ae)); + assertEqualInt((S_IFDIR | 0755), archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualIntA(a, 0, archive_read_data(a, filedata, 10)); + + /* Verify the end of the archive. */ + assertEqualIntA(a, 1, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + free(buff); +} + +static void +test_big_entries(int (*set_format)(struct archive *), int64_t size, int expected) +{ + struct archive_entry *ae; + struct archive *a; + size_t buffsize = 1000000; + size_t used; + char *buff; + + buff = malloc(buffsize); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertA(0 == (*set_format)(a)); + assertA(0 == archive_write_add_filter_none(a)); + assertA(0 == archive_write_open_memory(a, buff, buffsize, &used)); + + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file"); + archive_entry_set_size(ae, size); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualInt(expected, archive_write_header(a, ae)); + if (expected != ARCHIVE_OK) + assert(archive_error_string(a) != NULL); + + archive_entry_free(ae); + archive_write_free(a); + free(buff); +} + + +DEFINE_TEST(test_write_format_cpio) +{ + int64_t size_4g = ((int64_t)1) << 32; + int64_t size_8g = ((int64_t)1) << 33; + + test_format(archive_write_set_format_cpio); + test_format(archive_write_set_format_cpio_newc); + + test_big_entries(archive_write_set_format_cpio, + size_8g - 1, ARCHIVE_OK); + test_big_entries(archive_write_set_format_cpio, + size_8g, ARCHIVE_FAILED); + test_big_entries(archive_write_set_format_cpio_newc, + size_4g - 1, ARCHIVE_OK); + test_big_entries(archive_write_set_format_cpio_newc, + size_4g, ARCHIVE_FAILED); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_cpio_empty.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_cpio_empty.c new file mode 100644 index 0000000..2ba415c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_cpio_empty.c @@ -0,0 +1,71 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_format_cpio_empty.c 201247 2009-12-30 05:59:21Z kientzle $"); + +/* + * Check that an "empty" cpio archive is correctly created. + */ + +/* Here's what an empty cpio archive should look like. */ +static char ref[] = +"070707" /* Magic number */ +"000000" /* Dev = 0 */ +"000000" /* ino = 0 */ +"000000" /* mode = 0 */ +"000000" /* uid = 0 */ +"000000" /* gid = 0 */ +"000001" /* nlink = 1 */ +"000000" /* rdev = 0 */ +"00000000000" /* mtime = 0 */ +"000013" /* Namesize = 11 */ +"00000000000" /* filesize = 0 */ +"TRAILER!!!\0"; /* Name */ + +DEFINE_TEST(test_write_format_cpio_empty) +{ + struct archive *a; + char buff[2048]; + size_t used; + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_cpio(a)); + assertA(0 == archive_write_add_filter_none(a)); + /* 1-byte block size ensures we see only the required bytes. */ + /* We're not testing the padding here. */ + assertA(0 == archive_write_set_bytes_per_block(a, 1)); + assertA(0 == archive_write_set_bytes_in_last_block(a, 1)); + assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used)); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + failure("Empty cpio archive should be exactly 87 bytes, was %zu.", used); + assert(used == 87); + failure("Empty cpio archive is incorrectly formatted."); + assertEqualMem(buff, ref, 87); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_cpio_newc.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_cpio_newc.c new file mode 100644 index 0000000..48b0b26 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_cpio_newc.c @@ -0,0 +1,209 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_format_cpio_newc.c 201247 2009-12-30 05:59:21Z kientzle $"); + + +static int +is_hex(const char *p, size_t l) +{ + while (l > 0) { + if (*p >= '0' && *p <= '9') { + /* Ascii digit */ + } else if (*p >= 'a' && *p <= 'f') { + /* lowercase letter a-f */ + } else { + /* Not hex. */ + return (0); + } + --l; + ++p; + } + return (1); +} + +/* + * Detailed verification that cpio 'newc' archives are written with + * the correct format. + */ +DEFINE_TEST(test_write_format_cpio_newc) +{ + struct archive *a; + struct archive_entry *entry; + char *buff, *e, *file; + size_t buffsize = 100000; + size_t used; + + buff = malloc(buffsize); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, 0, archive_write_set_format_cpio_newc(a)); + assertEqualIntA(a, 0, archive_write_add_filter_none(a)); + assertEqualIntA(a, 0, archive_write_open_memory(a, buff, buffsize, &used)); + + /* + * Add various files to it. + * TODO: Extend this to cover more filetypes. + */ + + /* Regular file */ + assert((entry = archive_entry_new()) != NULL); + archive_entry_set_mtime(entry, 1, 10); + archive_entry_set_pathname(entry, "file"); + archive_entry_set_mode(entry, S_IFREG | 0664); + archive_entry_set_size(entry, 10); + archive_entry_set_uid(entry, 80); + archive_entry_set_gid(entry, 90); + archive_entry_set_dev(entry, 12); + archive_entry_set_ino(entry, 89); + archive_entry_set_nlink(entry, 1); + assertEqualIntA(a, 0, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualIntA(a, 10, archive_write_data(a, "1234567890", 10)); + + /* Directory */ + assert((entry = archive_entry_new()) != NULL); + archive_entry_set_mtime(entry, 2, 20); + archive_entry_set_pathname(entry, "dir"); + archive_entry_set_mode(entry, S_IFDIR | 0775); + archive_entry_set_size(entry, 10); + archive_entry_set_nlink(entry, 2); + assertEqualIntA(a, 0, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualIntA(a, 0, archive_write_data(a, "1234567890", 10)); + + /* Symlink */ + assert((entry = archive_entry_new()) != NULL); + archive_entry_set_mtime(entry, 3, 30); + archive_entry_set_pathname(entry, "lnk"); + archive_entry_set_mode(entry, 0664); + archive_entry_set_filetype(entry, AE_IFLNK); + archive_entry_set_size(entry, 0); + archive_entry_set_uid(entry, 83); + archive_entry_set_gid(entry, 93); + archive_entry_set_dev(entry, 13); + archive_entry_set_ino(entry, 88); + archive_entry_set_nlink(entry, 1); + archive_entry_set_symlink(entry,"a"); + assertEqualIntA(a, 0, archive_write_header(a, entry)); + archive_entry_free(entry); + + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Verify the archive format. + */ + e = buff; + + /* First entry is "file" */ + file = e; + assert(is_hex(e, 110)); /* Entire header is hex digits. */ + assertEqualMem(e + 0, "070701", 6); /* Magic */ + assert(memcmp(e + 6, "00000000", 8) != 0); /* ino != 0 */ + assertEqualMem(e + 14, "000081b4", 8); /* Mode */ + assertEqualMem(e + 22, "00000050", 8); /* uid */ + assertEqualMem(e + 30, "0000005a", 8); /* gid */ + assertEqualMem(e + 38, "00000001", 8); /* nlink */ + assertEqualMem(e + 46, "00000001", 8); /* mtime */ + assertEqualMem(e + 54, "0000000a", 8); /* File size */ + assertEqualMem(e + 62, "00000000", 8); /* devmajor */ + assertEqualMem(e + 70, "0000000c", 8); /* devminor */ + assertEqualMem(e + 78, "00000000", 8); /* rdevmajor */ + assertEqualMem(e + 86, "00000000", 8); /* rdevminor */ + assertEqualMem(e + 94, "00000005", 8); /* Name size */ + assertEqualMem(e + 102, "00000000", 8); /* CRC */ + assertEqualMem(e + 110, "file\0\0", 6); /* Name contents */ + assertEqualMem(e + 116, "1234567890", 10); /* File body */ + assertEqualMem(e + 126, "\0\0", 2); /* Pad to multiple of 4 */ + e += 128; /* Must be multiple of four here! */ + + /* Second entry is "dir" */ + assert(is_hex(e, 110)); + assertEqualMem(e + 0, "070701", 6); /* Magic */ + assertEqualMem(e + 6, "00000000", 8); /* ino */ + assertEqualMem(e + 14, "000041fd", 8); /* Mode */ + assertEqualMem(e + 22, "00000000", 8); /* uid */ + assertEqualMem(e + 30, "00000000", 8); /* gid */ + assertEqualMem(e + 38, "00000002", 8); /* nlink */ + assertEqualMem(e + 46, "00000002", 8); /* mtime */ + assertEqualMem(e + 54, "00000000", 8); /* File size */ + assertEqualMem(e + 62, "00000000", 8); /* devmajor */ + assertEqualMem(e + 70, "00000000", 8); /* devminor */ + assertEqualMem(e + 78, "00000000", 8); /* rdevmajor */ + assertEqualMem(e + 86, "00000000", 8); /* rdevminor */ + assertEqualMem(e + 94, "00000004", 8); /* Name size */ + assertEqualMem(e + 102, "00000000", 8); /* CRC */ + assertEqualMem(e + 110, "dir\0", 4); /* name */ + assertEqualMem(e + 114, "\0\0", 2); /* Pad to multiple of 4 */ + e += 116; /* Must be multiple of four here! */ + + /* Third entry is "lnk" */ + assert(is_hex(e, 110)); /* Entire header is hex digits. */ + assertEqualMem(e + 0, "070701", 6); /* Magic */ + assert(memcmp(e + 6, file + 6, 8) != 0); /* ino != file ino */ + assert(memcmp(e + 6, "00000000", 8) != 0); /* ino != 0 */ + assertEqualMem(e + 14, "0000a1b4", 8); /* Mode */ + assertEqualMem(e + 22, "00000053", 8); /* uid */ + assertEqualMem(e + 30, "0000005d", 8); /* gid */ + assertEqualMem(e + 38, "00000001", 8); /* nlink */ + assertEqualMem(e + 46, "00000003", 8); /* mtime */ + assertEqualMem(e + 54, "00000001", 8); /* File size */ + assertEqualMem(e + 62, "00000000", 8); /* devmajor */ + assertEqualMem(e + 70, "0000000d", 8); /* devminor */ + assertEqualMem(e + 78, "00000000", 8); /* rdevmajor */ + assertEqualMem(e + 86, "00000000", 8); /* rdevminor */ + assertEqualMem(e + 94, "00000004", 8); /* Name size */ + assertEqualMem(e + 102, "00000000", 8); /* CRC */ + assertEqualMem(e + 110, "lnk\0\0\0", 6); /* Name contents */ + assertEqualMem(e + 116, "a\0\0\0", 4); /* File body + pad */ + e += 120; /* Must be multiple of four here! */ + + /* TODO: Verify other types of entries. */ + + /* Last entry is end-of-archive marker. */ + assert(is_hex(e, 76)); + assertEqualMem(e + 0, "070701", 6); /* Magic */ + assertEqualMem(e + 6, "00000000", 8); /* ino */ + assertEqualMem(e + 14, "00000000", 8); /* Mode */ + assertEqualMem(e + 22, "00000000", 8); /* uid */ + assertEqualMem(e + 30, "00000000", 8); /* gid */ + assertEqualMem(e + 38, "00000001", 8); /* nlink */ + assertEqualMem(e + 46, "00000000", 8); /* mtime */ + assertEqualMem(e + 54, "00000000", 8); /* File size */ + assertEqualMem(e + 62, "00000000", 8); /* devmajor */ + assertEqualMem(e + 70, "00000000", 8); /* devminor */ + assertEqualMem(e + 78, "00000000", 8); /* rdevmajor */ + assertEqualMem(e + 86, "00000000", 8); /* rdevminor */ + assertEqualMem(e + 94, "0000000b", 8); /* Name size */ + assertEqualMem(e + 102, "00000000", 8); /* CRC */ + assertEqualMem(e + 110, "TRAILER!!!\0", 11); /* Name */ + assertEqualMem(e + 121, "\0\0\0", 3); /* Pad to multiple of 4 bytes */ + e += 124; /* Must be multiple of four here! */ + + assertEqualInt((int)used, e - buff); + + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_cpio_odc.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_cpio_odc.c new file mode 100644 index 0000000..ba1fecd --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_cpio_odc.c @@ -0,0 +1,237 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_format_cpio_odc.c 201247 2009-12-30 05:59:21Z kientzle $"); + + +static int +is_octal(const char *p, size_t l) +{ + while (l > 0) { + if (*p < '0' || *p > '7') + return (0); + --l; + ++p; + } + return (1); +} + +/* + * Detailed verification that cpio 'odc' archives are written with + * the correct format. + */ +DEFINE_TEST(test_write_format_cpio_odc) +{ + struct archive *a; + struct archive_entry *entry; + char *buff, *e, *file; + size_t buffsize = 100000; + size_t used; + + buff = malloc(buffsize); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, 0, archive_write_set_format_cpio(a)); + assertEqualIntA(a, 0, archive_write_add_filter_none(a)); + assertEqualIntA(a, 0, archive_write_open_memory(a, buff, buffsize, &used)); + + /* + * Add various files to it. + * TODO: Extend this to cover more filetypes. + */ + + /* "file" with 10 bytes of content */ + assert((entry = archive_entry_new()) != NULL); + archive_entry_set_mtime(entry, 1, 10); + archive_entry_set_pathname(entry, "file"); + archive_entry_set_mode(entry, S_IFREG | 0664); + archive_entry_set_size(entry, 10); + archive_entry_set_uid(entry, 80); + archive_entry_set_gid(entry, 90); + archive_entry_set_dev(entry, 12); + archive_entry_set_ino(entry, 89); + archive_entry_set_nlink(entry, 2); + assertEqualIntA(a, 0, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualIntA(a, 10, archive_write_data(a, "1234567890", 10)); + + /* Hardlink to "file" with 10 bytes of content */ + assert((entry = archive_entry_new()) != NULL); + archive_entry_set_mtime(entry, 1, 10); + archive_entry_set_pathname(entry, "linkfile"); + archive_entry_set_mode(entry, S_IFREG | 0664); + archive_entry_set_size(entry, 10); + archive_entry_set_uid(entry, 80); + archive_entry_set_gid(entry, 90); + archive_entry_set_dev(entry, 12); + archive_entry_set_ino(entry, 89); + archive_entry_set_nlink(entry, 2); + assertEqualIntA(a, 0, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualIntA(a, 10, archive_write_data(a, "1234567890", 10)); + + /* "dir" */ + assert((entry = archive_entry_new()) != NULL); + archive_entry_set_mtime(entry, 2, 20); + archive_entry_set_pathname(entry, "dir"); + archive_entry_set_mode(entry, S_IFDIR | 0775); + archive_entry_set_size(entry, 10); + archive_entry_set_nlink(entry, 2); + assertEqualIntA(a, 0, archive_write_header(a, entry)); + archive_entry_free(entry); + /* Write of data to dir should fail == zero bytes get written. */ + assertEqualIntA(a, 0, archive_write_data(a, "1234567890", 10)); + + /* "symlink" pointing to "file" */ + assert((entry = archive_entry_new()) != NULL); + archive_entry_set_mtime(entry, 3, 30); + archive_entry_set_pathname(entry, "symlink"); + archive_entry_set_mode(entry, 0664); + archive_entry_set_filetype(entry, AE_IFLNK); + archive_entry_set_symlink(entry,"file"); + archive_entry_set_size(entry, 0); + archive_entry_set_uid(entry, 88); + archive_entry_set_gid(entry, 98); + archive_entry_set_dev(entry, 12); + archive_entry_set_ino(entry, 90); + archive_entry_set_nlink(entry, 1); + assertEqualIntA(a, 0, archive_write_header(a, entry)); + archive_entry_free(entry); + /* Write of data to symlink should fail == zero bytes get written. */ + assertEqualIntA(a, 0, archive_write_data(a, "1234567890", 10)); + + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Verify the archive format. + * + * Notes on the ino validation: cpio does not actually require + * that the ino values written to the archive match those read + * from disk. It really requires that: + * * matching non-zero ino values be written as matching + * non-zero values + * * non-matching non-zero ino values be written as non-matching + * non-zero values + * Libarchive further ensures that zero ino values get written + * as zeroes. This allows the cpio writer to generate + * synthetic ino values for the archive that may be different + * than those on disk in order to avoid problems due to truncation. + * This is especially needed for odc (POSIX format) that + * only supports 18-bit ino values. + */ + e = buff; + + /* "file" */ + file = e; /* Remember where this starts... */ + assert(is_octal(e, 76)); /* Entire header is octal digits. */ + assertEqualMem(e + 0, "070707", 6); /* Magic */ + assertEqualMem(e + 6, "000014", 6); /* dev */ + assert(memcmp(e + 12, "000000", 6) != 0); /* ino must be != 0 */ + assertEqualMem(e + 18, "100664", 6); /* Mode */ + assertEqualMem(e + 24, "000120", 6); /* uid */ + assertEqualMem(e + 30, "000132", 6); /* gid */ + assertEqualMem(e + 36, "000002", 6); /* nlink */ + assertEqualMem(e + 42, "000000", 6); /* rdev */ + assertEqualMem(e + 48, "00000000001", 11); /* mtime */ + assertEqualMem(e + 59, "000005", 6); /* Name size */ + assertEqualMem(e + 65, "00000000012", 11); /* File size */ + assertEqualMem(e + 76, "file\0", 5); /* Name contents */ + assertEqualMem(e + 81, "1234567890", 10); /* File contents */ + e += 91; + + /* hardlink to "file" */ + assert(is_octal(e, 76)); /* Entire header is octal digits. */ + assertEqualMem(e + 0, "070707", 6); /* Magic */ + assertEqualMem(e + 6, "000014", 6); /* dev */ + assertEqualMem(e + 12, file + 12, 6); /* ino must match above */ + assertEqualMem(e + 18, "100664", 6); /* Mode */ + assertEqualMem(e + 24, "000120", 6); /* uid */ + assertEqualMem(e + 30, "000132", 6); /* gid */ + assertEqualMem(e + 36, "000002", 6); /* nlink */ + assertEqualMem(e + 42, "000000", 6); /* rdev */ + assertEqualMem(e + 48, "00000000001", 11); /* mtime */ + assertEqualMem(e + 59, "000011", 6); /* Name size */ + assertEqualMem(e + 65, "00000000012", 11); /* File size */ + assertEqualMem(e + 76, "linkfile\0", 9); /* Name contents */ + assertEqualMem(e + 85, "1234567890", 10); /* File contents */ + e += 95; + + /* "dir" */ + assert(is_octal(e, 76)); + assertEqualMem(e + 0, "070707", 6); /* Magic */ + assertEqualMem(e + 6, "000000", 6); /* dev */ + assertEqualMem(e + 12, "000000", 6); /* ino */ + assertEqualMem(e + 18, "040775", 6); /* Mode */ + assertEqualMem(e + 24, "000000", 6); /* uid */ + assertEqualMem(e + 30, "000000", 6); /* gid */ + assertEqualMem(e + 36, "000002", 6); /* Nlink */ + assertEqualMem(e + 42, "000000", 6); /* rdev */ + assertEqualMem(e + 48, "00000000002", 11); /* mtime */ + assertEqualMem(e + 59, "000004", 6); /* Name size */ + assertEqualMem(e + 65, "00000000000", 11); /* File size */ + assertEqualMem(e + 76, "dir\0", 4); /* name */ + e += 80; + + /* "symlink" pointing to "file" */ + assert(is_octal(e, 76)); /* Entire header is octal digits. */ + assertEqualMem(e + 0, "070707", 6); /* Magic */ + assertEqualMem(e + 6, "000014", 6); /* dev */ + assert(memcmp(e + 12, file + 12, 6) != 0); /* ino must != file ino */ + assert(memcmp(e + 12, "000000", 6) != 0); /* ino must != 0 */ + assertEqualMem(e + 18, "120664", 6); /* Mode */ + assertEqualMem(e + 24, "000130", 6); /* uid */ + assertEqualMem(e + 30, "000142", 6); /* gid */ + assertEqualMem(e + 36, "000001", 6); /* nlink */ + assertEqualMem(e + 42, "000000", 6); /* rdev */ + assertEqualMem(e + 48, "00000000003", 11); /* mtime */ + assertEqualMem(e + 59, "000010", 6); /* Name size */ + assertEqualMem(e + 65, "00000000004", 11); /* File size */ + assertEqualMem(e + 76, "symlink\0", 8); /* Name contents */ + assertEqualMem(e + 84, "file", 4); /* File contents == link target */ + e += 88; + + /* TODO: Verify other types of entries. */ + + /* Last entry is end-of-archive marker. */ + assert(is_octal(e, 76)); + assertEqualMem(e + 0, "070707", 6); /* Magic */ + assertEqualMem(e + 6, "000000", 6); /* dev */ + assertEqualMem(e + 12, "000000", 6); /* ino */ + assertEqualMem(e + 18, "000000", 6); /* Mode */ + assertEqualMem(e + 24, "000000", 6); /* uid */ + assertEqualMem(e + 30, "000000", 6); /* gid */ + assertEqualMem(e + 36, "000001", 6); /* Nlink */ + assertEqualMem(e + 42, "000000", 6); /* rdev */ + assertEqualMem(e + 48, "00000000000", 11); /* mtime */ + assertEqualMem(e + 59, "000013", 6); /* Name size */ + assertEqualMem(e + 65, "00000000000", 11); /* File size */ + assertEqualMem(e + 76, "TRAILER!!!\0", 11); /* Name */ + e += 87; + + assertEqualInt((int)used, e - buff); + + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_gnutar.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_gnutar.c new file mode 100644 index 0000000..2a4c383 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_gnutar.c @@ -0,0 +1,258 @@ +/*- + * Copyright (c) 2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +static char buff2[64]; + +/* Some names 1026 characters long */ +static const char *longfilename = "abcdefghijklmnopqrstuvwxyz" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890"; + +static const char *longlinkname = "Xabcdefghijklmnopqrstuvwxyz" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890"; + +static const char *longhardlinkname = "Yabcdefghijklmnopqrstuvwxyz" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890"; + + +DEFINE_TEST(test_write_format_gnutar) +{ + size_t buffsize = 1000000; + char *buff; + struct archive_entry *ae; + struct archive *a; + size_t used; + + buff = malloc(buffsize); /* million bytes of work area */ + assert(buff != NULL); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_gnutar(a)); + assertA(0 == archive_write_add_filter_none(a)); + assertA(0 == archive_write_open_memory(a, buff, buffsize, &used)); + + /* + * "file" has a bunch of attributes and 8 bytes of data. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_birthtime(ae, 3, 30); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "file"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 8); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); + + /* + * A file with a very long name + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, longfilename); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 8); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 8, archive_write_data(a, "abcdefgh", 9)); + + /* + * A hardlink to the above file. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, longhardlinkname); + archive_entry_copy_hardlink(ae, longfilename); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 8); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* + * A symlink to the above file. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, longlinkname); + archive_entry_copy_symlink(ae, longfilename); + archive_entry_set_mode(ae, AE_IFLNK | 0755); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* + * A file with large UID/GID that overflow octal encoding. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "large_uid_gid"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 8); + archive_entry_set_uid(ae, 123456789); + archive_entry_set_gid(ae, 987654321); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 8, archive_write_data(a, "abcdefgh", 9)); + + /* TODO: support GNU tar sparse format and test it here. */ + /* See test_write_format_pax for an example of testing sparse files. */ + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + + /* + * Some basic verification of the low-level format. + */ + + /* Verify GNU tar magic/version fields */ + assertEqualMem(buff + 257, "ustar \0", 8); + + assertEqualInt(15360, used); + + /* + * + * Now, read the data back. + * + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, 0, archive_read_support_format_all(a)); + assertEqualIntA(a, 0, archive_read_support_filter_all(a)); + assertEqualIntA(a, 0, archive_read_open_memory(a, buff, used)); + + /* + * Read "file" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assert(!archive_entry_atime_is_set(ae)); + assert(!archive_entry_birthtime_is_set(ae)); + assert(!archive_entry_ctime_is_set(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualString("file", archive_entry_pathname(ae)); + assertEqualInt(S_IFREG | 0755, archive_entry_mode(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "12345678", 8); + + /* + * Read file with very long name. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualString(longfilename, archive_entry_pathname(ae)); + assertEqualInt(S_IFREG | 0755, archive_entry_mode(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "abcdefgh", 8); + + /* + * Read hardlink. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualString(longhardlinkname, archive_entry_pathname(ae)); + assertEqualString(longfilename, archive_entry_hardlink(ae)); + + /* + * Read symlink. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualString(longlinkname, archive_entry_pathname(ae)); + assertEqualString(longfilename, archive_entry_symlink(ae)); + assertEqualInt(AE_IFLNK | 0755, archive_entry_mode(ae)); + + /* + * Read file with large UID/GID. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(123456789, archive_entry_uid(ae)); + assertEqualInt(987654321, archive_entry_gid(ae)); + assertEqualString("large_uid_gid", archive_entry_pathname(ae)); + assertEqualInt(S_IFREG | 0755, archive_entry_mode(ae)); + + /* + * Verify the end of the archive. + */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_gnutar_filenames.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_gnutar_filenames.c new file mode 100644 index 0000000..655e998 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_gnutar_filenames.c @@ -0,0 +1,151 @@ +/*- + * Copyright (c) 2016 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * Inspired by Github issue #682, which reported that gnutar filenames + * of exactly 512 bytes weren't getting written correctly. + * + * This writes a filename of every length from 1 to 2000 bytes and + * reads back to verify it. + */ + +static char filename[2048]; + +DEFINE_TEST(test_write_format_gnutar_filenames) +{ + size_t buffsize = 1000000; + char *buff; + struct archive_entry *ae, *template; + struct archive *a; + size_t used; + int i; + + buff = malloc(buffsize); /* million bytes of work area */ + assert(buff != NULL); + + /* Create a template entry. */ + assert((template = archive_entry_new()) != NULL); + archive_entry_set_atime(template, 2, 20); + archive_entry_set_birthtime(template, 3, 30); + archive_entry_set_ctime(template, 4, 40); + archive_entry_set_mtime(template, 5, 50); + archive_entry_set_mode(template, S_IFREG | 0755); + archive_entry_set_size(template, 8); + + for (i = 0; i < 2000; ++i) { + filename[i] = 'a'; + filename[i + 1] = '\0'; + archive_entry_copy_pathname(template, filename); + + /* Write a one-item gnutar format archive. */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_gnutar(a)); + assertA(0 == archive_write_add_filter_none(a)); + assertA(0 == archive_write_open_memory(a, buff, buffsize, &used)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, template)); + assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + + + /* Read back and verify the filename. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, 0, archive_read_support_format_all(a)); + assertEqualIntA(a, 0, archive_read_support_filter_all(a)); + assertEqualIntA(a, 0, archive_read_open_memory(a, buff, used)); + + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualString(filename, archive_entry_pathname(ae)); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + } + + archive_entry_free(template); + + free(buff); +} + + +DEFINE_TEST(test_write_format_gnutar_linknames) +{ + size_t buffsize = 1000000; + char *buff; + struct archive_entry *ae, *template; + struct archive *a; + size_t used; + int i; + +#ifdef S_IFLNK + assertEqualInt(S_IFLNK, AE_IFLNK); +#endif + + buff = malloc(buffsize); /* million bytes of work area */ + assert(buff != NULL); + + /* Create a template entry. */ + assert((template = archive_entry_new()) != NULL); + archive_entry_set_atime(template, 2, 20); + archive_entry_set_birthtime(template, 3, 30); + archive_entry_set_ctime(template, 4, 40); + archive_entry_set_mtime(template, 5, 50); + archive_entry_set_mode(template, AE_IFLNK | 0755); + archive_entry_copy_pathname(template, "link"); + + for (i = 0; i < 2000; ++i) { + filename[i] = 'a'; + filename[i + 1] = '\0'; + archive_entry_copy_symlink(template, filename); + + /* Write a one-item gnutar format archive. */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_gnutar(a)); + assertA(0 == archive_write_add_filter_none(a)); + assertA(0 == archive_write_open_memory(a, buff, buffsize, &used)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, template)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + + + /* Read back and verify the filename. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, 0, archive_read_support_format_all(a)); + assertEqualIntA(a, 0, archive_read_support_filter_all(a)); + assertEqualIntA(a, 0, archive_read_open_memory(a, buff, used)); + + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualString("link", archive_entry_pathname(ae)); + assertEqualString(filename, archive_entry_symlink(ae)); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + } + + archive_entry_free(template); + + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_iso9660.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_iso9660.c new file mode 100644 index 0000000..e4e98bb --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_iso9660.c @@ -0,0 +1,1110 @@ +/*- + * Copyright (c) 2003-2008 Tim Kientzle + * Copyright (c) 2009,2010 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +static char buff2[64]; +DEFINE_TEST(test_write_format_iso9660) +{ + size_t buffsize = 1000000; + char *buff; + struct archive_entry *ae; + struct archive *a; + char dirname[1024]; + char dir[6]; + char longname[] = + "longname00aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + "cccccccccccccccccccccccccccccccccccccccccccccccccc" + "dddddddddddddddddddddddddddddddddddddddddddddddddd"; + + size_t used; + int i; + + buff = malloc(buffsize); /* million bytes of work area */ + assert(buff != NULL); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_iso9660(a)); + assertA(0 == archive_write_add_filter_none(a)); + assertA(0 == archive_write_open_memory(a, buff, buffsize, &used)); + + /* + * "file" has a bunch of attributes and 8 bytes of data. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_birthtime(ae, 3, 30); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "file"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + archive_entry_set_size(ae, 8); + archive_entry_set_nlink(ae, 2); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); + + /* + * "hardlnk" has linked to "file". + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_birthtime(ae, 3, 30); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "hardlnk"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + archive_entry_set_hardlink(ae, "file"); + archive_entry_set_nlink(ae, 2); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* + * longname is similar but has birthtime later than mtime. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_birthtime(ae, 8, 80); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, longname); + archive_entry_set_mode(ae, AE_IFREG | 0666); + archive_entry_set_size(ae, 8); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); + + /* + * "symlnk has symbolic linked to longname. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "symlnk"); + archive_entry_set_mode(ae, AE_IFLNK | 0555); + archive_entry_set_symlink(ae, longname); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* + * "dir*" has a bunch of attributes. + */ + dirname[0] = '\0'; + strcpy(dir, "/dir0"); + for (i = 0; i < 13; i++) { + dir[4] = "0123456789ABCDEF"[i]; + if (i == 0) + strcat(dirname, dir+1); + else + strcat(dirname, dir); + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_birthtime(ae, 3, 30); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, dirname); + archive_entry_set_mode(ae, S_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + } + + strcat(dirname, "/file"); + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_birthtime(ae, 3, 30); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, dirname); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 8); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); + + /* + * "dir0/dir1/file1" has 8 bytes of data. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_birthtime(ae, 3, 30); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "dir0/dir1/file1"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + archive_entry_set_size(ae, 8); + archive_entry_set_nlink(ae, 1); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); + + /* + * "dir0/dir1/file2" has 8 bytes of data. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_birthtime(ae, 3, 30); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "dir0/dir1/file2"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + archive_entry_set_size(ae, 8); + archive_entry_set_nlink(ae, 1); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); + + /* + * Add a wrong path "dir0/dir1/file2/wrong" + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_birthtime(ae, 3, 30); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "dir0/dir1/file2/wrong"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + archive_entry_set_size(ae, 8); + archive_entry_set_nlink(ae, 1); + assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + + /* + * ----------------------------------------------------------- + * Now, read the data back(read Rockridge extensions). + * ----------------------------------------------------------- + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, 0, archive_read_support_format_all(a)); + assertEqualIntA(a, 0, archive_read_support_filter_all(a)); + assertEqualIntA(a, 0, archive_read_open_memory(a, buff, used)); + + /* + * Read Root Directory + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_atime(ae), archive_entry_ctime(ae)); + assertEqualInt(archive_entry_atime(ae), archive_entry_mtime(ae)); + assertEqualString(".", archive_entry_pathname(ae)); + assert((S_IFDIR | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_birthtime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0", archive_entry_pathname(ae)); + assert((S_IFDIR | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_birthtime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1", archive_entry_pathname(ae)); + assert((S_IFDIR | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_birthtime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/dir2", archive_entry_pathname(ae)); + assert((S_IFDIR | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2/dir3" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_birthtime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/dir2/dir3", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2/dir3/dir4" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_birthtime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/dir2/dir3/dir4", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2/dir3/dir4/dir5" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_birthtime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_birthtime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_birthtime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_birthtime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_birthtime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_birthtime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_birthtime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB/dirC" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_birthtime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB/dirC", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "hardlnk" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_birthtime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("hardlnk", archive_entry_pathname(ae)); + assert((AE_IFREG | 0555) == archive_entry_mode(ae)); + assertEqualInt(2, archive_entry_nlink(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "12345678", 8); + + /* + * Read "file" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_birthtime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("file", archive_entry_pathname(ae)); + assertEqualString("hardlnk", archive_entry_hardlink(ae)); + assert((AE_IFREG | 0555) == archive_entry_mode(ae)); + assertEqualInt(2, archive_entry_nlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + + /* + * Read longname + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assert(archive_entry_atime_is_set(ae)); + assertEqualInt(2, archive_entry_atime(ae)); + /* Birthtime > mtime above, so it doesn't get stored at all. */ + assert(!archive_entry_birthtime_is_set(ae)); + assertEqualInt(0, archive_entry_birthtime(ae)); + assert(archive_entry_ctime_is_set(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assert(archive_entry_mtime_is_set(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString(longname, archive_entry_pathname(ae)); +#if !defined(_WIN32) && !defined(__CYGWIN__) + assert((AE_IFREG | 0444) == archive_entry_mode(ae)); +#else + /* On Windows and CYGWIN, always set all exec bit ON by default. */ + assert((AE_IFREG | 0555) == archive_entry_mode(ae)); +#endif + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "12345678", 8); + + /* + * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB/dirC/file" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_birthtime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB/dirC/file", archive_entry_pathname(ae)); + assert((AE_IFREG | 0555) == archive_entry_mode(ae)); + assertEqualInt(1, archive_entry_nlink(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "12345678", 8); + + /* + * Read "dir0/dir1/file1" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_birthtime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/file1", archive_entry_pathname(ae)); + assert((AE_IFREG | 0555) == archive_entry_mode(ae)); + assertEqualInt(1, archive_entry_nlink(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "12345678", 8); + + /* + * Read "dir0/dir1/file2" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_birthtime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/file2", archive_entry_pathname(ae)); + assert((AE_IFREG | 0555) == archive_entry_mode(ae)); + assertEqualInt(1, archive_entry_nlink(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "12345678", 8); + + /* + * Read "symlnk" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assert(archive_entry_atime_is_set(ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assert(!archive_entry_birthtime_is_set(ae)); + assertEqualInt(0, archive_entry_birthtime(ae)); + assert(archive_entry_ctime_is_set(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assert(archive_entry_mtime_is_set(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("symlnk", archive_entry_pathname(ae)); + assert((AE_IFLNK | 0555) == archive_entry_mode(ae)); + assertEqualString(longname, archive_entry_symlink(ae)); + + /* + * Verify the end of the archive. + */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + + /* + * ----------------------------------------------------------- + * Now, read the data back without Rockridge option + * (read Joliet extensions). + * ----------------------------------------------------------- + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, 0, archive_read_support_format_all(a)); + assertEqualIntA(a, 0, archive_read_support_filter_all(a)); + /* Disable Rockridge extensions support. */ + assertEqualInt(ARCHIVE_OK, + archive_read_set_option(a, NULL, "rockridge", NULL)); + assertEqualIntA(a, 0, archive_read_open_memory(a, buff, used)); + + /* + * Read Root Directory + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_atime(ae), archive_entry_ctime(ae)); + assertEqualInt(archive_entry_atime(ae), archive_entry_mtime(ae)); + assertEqualString(".", archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0", archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1", archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/dir2", archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2/dir3" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/dir2/dir3", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2/dir3/dir4" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/dir2/dir3/dir4", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2/dir3/dir4/dir5" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB/dirC" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB/dirC", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "file" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("file", archive_entry_pathname(ae)); + assert((AE_IFREG | 0400) == archive_entry_mode(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "12345678", 8); + + /* + * Read "hardlnk" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("hardlnk", archive_entry_pathname(ae)); + assertEqualString("file", archive_entry_hardlink(ae)); + assert((AE_IFREG | 0400) == archive_entry_mode(ae)); + assertEqualInt(2, archive_entry_nlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualIntA(a, 0, archive_read_data(a, buff2, 10)); + + /* + * Read longname + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assert(archive_entry_atime_is_set(ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assert(archive_entry_ctime_is_set(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assert(archive_entry_mtime_is_set(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + /* Trim longname to 64 characters. */ + longname[64] = '\0'; + assertEqualString(longname, archive_entry_pathname(ae)); + assert((AE_IFREG | 0400) == archive_entry_mode(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "12345678", 8); + + /* + * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB/dirC/file" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString( + "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB/dirC/file", + archive_entry_pathname(ae)); + assert((AE_IFREG | 0400) == archive_entry_mode(ae)); + assertEqualInt(1, archive_entry_nlink(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "12345678", 8); + + /* + * Read "dir0/dir1/file1" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/file1", archive_entry_pathname(ae)); + assert((AE_IFREG | 0400) == archive_entry_mode(ae)); + assertEqualInt(1, archive_entry_nlink(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "12345678", 8); + + /* + * Read "dir0/dir1/file2" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("dir0/dir1/file2", archive_entry_pathname(ae)); + assert((AE_IFREG | 0400) == archive_entry_mode(ae)); + assertEqualInt(1, archive_entry_nlink(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "12345678", 8); + + /* + * Read "symlnk" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assert(archive_entry_atime_is_set(ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assert(!archive_entry_birthtime_is_set(ae)); + assertEqualInt(0, archive_entry_birthtime(ae)); + assert(archive_entry_ctime_is_set(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assert(archive_entry_mtime_is_set(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assert((AE_IFREG | 0400) == archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + + /* + * Verify the end of the archive. + */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + + /* + * ----------------------------------------------------------- + * Now, read the data back without Rockridge and Joliet option + * (read ISO9660). + * This mode appears rr_moved directory. + * ----------------------------------------------------------- + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, 0, archive_read_support_format_all(a)); + assertEqualIntA(a, 0, archive_read_support_filter_all(a)); + /* Disable Rockridge and Joliet extensions support. */ + assertEqualInt(ARCHIVE_OK, + archive_read_set_option(a, NULL, "rockridge", NULL)); + assertEqualInt(ARCHIVE_OK, + archive_read_set_option(a, NULL, "joliet", NULL)); + assertEqualIntA(a, 0, archive_read_open_memory(a, buff, used)); + + /* + * Read Root Directory + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_atime(ae), archive_entry_ctime(ae)); + assertEqualInt(archive_entry_atime(ae), archive_entry_mtime(ae)); + assertEqualString(".", archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "rr_moved" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_atime(ae), archive_entry_ctime(ae)); + assertEqualInt(archive_entry_atime(ae), archive_entry_mtime(ae)); + assertEqualString("RR_MOVED", archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "rr_moved/dir7" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("RR_MOVED/DIR7", archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "rr_moved/dir7/dir8" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("RR_MOVED/DIR7/DIR8", archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "rr_moved/dir7/dir8/dir9" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("RR_MOVED/DIR7/DIR8/DIR9", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "rr_moved/dir7/dir8/dir9/dira" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("RR_MOVED/DIR7/DIR8/DIR9/DIRA", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "rr_moved/dir7/dir8/dir9/dira/dirB" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("RR_MOVED/DIR7/DIR8/DIR9/DIRA/DIRB", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "rr_moved/dir7/dir8/dir9/dirA/dirB/dirC" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("RR_MOVED/DIR7/DIR8/DIR9/DIRA/DIRB/DIRC", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("DIR0", archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("DIR0/DIR1", archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("DIR0/DIR1/DIR2", archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2/dir3" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("DIR0/DIR1/DIR2/DIR3", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2/dir3/dir4" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("DIR0/DIR1/DIR2/DIR3/DIR4", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2/dir3/dir4/dir5" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("DIR0/DIR1/DIR2/DIR3/DIR4/DIR5", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("DIR0/DIR1/DIR2/DIR3/DIR4/DIR5/DIR6", + archive_entry_pathname(ae)); + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "hardlink" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("HARDLNK", archive_entry_pathname(ae)); + assertEqualString(NULL, archive_entry_hardlink(ae)); + assert((AE_IFREG | 0400) == archive_entry_mode(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "12345678", 8); + + /* + * Read "file" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_birthtime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("FILE", archive_entry_pathname(ae)); + assertEqualString("HARDLNK", archive_entry_hardlink(ae)); + assert((AE_IFREG | 0400) == archive_entry_mode(ae)); + assertEqualInt(2, archive_entry_nlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualIntA(a, 0, archive_read_data(a, buff2, 10)); + + + /* + * Read longname + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assert(archive_entry_atime_is_set(ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assert(archive_entry_ctime_is_set(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assert(archive_entry_mtime_is_set(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("LONGNAME", archive_entry_pathname(ae)); + assert((AE_IFREG | 0400) == archive_entry_mode(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "12345678", 8); + + /* + * Read "rr_moved/dir7/dir8/dir9/dirA/dirB/dirC/file" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString( + "RR_MOVED/DIR7/DIR8/DIR9/DIRA/DIRB/DIRC/FILE", + archive_entry_pathname(ae)); + assert((AE_IFREG | 0400) == archive_entry_mode(ae)); + assertEqualInt(1, archive_entry_nlink(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "12345678", 8); + + /* + * Read "dir0/dir1/file1" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("DIR0/DIR1/FILE1", archive_entry_pathname(ae)); + assert((AE_IFREG | 0400) == archive_entry_mode(ae)); + assertEqualInt(1, archive_entry_nlink(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "12345678", 8); + + /* + * Read "dir0/dir1/file2" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("DIR0/DIR1/FILE2", archive_entry_pathname(ae)); + assert((AE_IFREG | 0400) == archive_entry_mode(ae)); + assertEqualInt(1, archive_entry_nlink(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "12345678", 8); + + /* + * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7" as file + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("DIR0/DIR1/DIR2/DIR3/DIR4/DIR5/DIR6/DIR7", + archive_entry_pathname(ae)); + assert((AE_IFREG | 0400) == archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + + /* + * Read "symlnk" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assert(archive_entry_atime_is_set(ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assert(!archive_entry_birthtime_is_set(ae)); + assertEqualInt(0, archive_entry_birthtime(ae)); + assert(archive_entry_ctime_is_set(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + assert(archive_entry_mtime_is_set(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("SYMLNK", archive_entry_pathname(ae)); + assert((AE_IFREG | 0400) == archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + + /* + * Verify the end of the archive. + */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_iso9660_boot.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_iso9660_boot.c new file mode 100644 index 0000000..433f633 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_iso9660_boot.c @@ -0,0 +1,276 @@ +/*- + * Copyright (c) 2009 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +/* + * Check that a "bootable CD" ISO 9660 image is correctly created. + */ + +static const unsigned char primary_id[] = { + 0x01, 0x43, 0x44, 0x30, 0x30, 0x31, 0x01, 0x00 +}; +static const unsigned char volumesize[] = { + 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26 +}; +static const unsigned char volumeidu16[] = { + 0x00, 0x43, 0x00, 0x44, 0x00, 0x52, 0x00, 0x4f, + 0x00, 0x4d, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, + 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, + 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20 +}; +static const unsigned char boot_id[] = { + 0x00, 0x43, 0x44, 0x30, 0x30, 0x31, 0x01, 0x45, + 0x4c, 0x20, 0x54, 0x4f, 0x52, 0x49, 0x54, 0x4f, + 0x20, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +static const unsigned char supplementary_id[] = { + 0x02, 0x43, 0x44, 0x30, 0x30, 0x31, 0x01, 0x00 +}; +static const unsigned char terminator_id[] = { + 0xff, 0x43, 0x44, 0x30, 0x30, 0x31, 0x01, 0x00 +}; + +static const unsigned char boot_catalog[] = { + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xaa, 0x55, 0x55, 0xaa, + 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char info_table[] = { + 0x10, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char el_torito_signature[] = { + "ER\355\001\012T\207\001RRIP_1991ATHE ROCK RIDGE " + "INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR POSIX " + "FILE SYSTEM SEMANTICSPLEASE CONTACT DISC PUBLISHER " + "FOR SPECIFICATION SOURCE. SEE PUBLISHER IDENTIFIER " + "IN PRIMARY VOLUME DESCRIPTOR FOR CONTACT INFORMATION." +}; + +static char buff2[1024]; + +static void +_test_write_format_iso9660_boot(int write_info_tbl) +{ + unsigned char nullb[2048]; + struct archive *a; + struct archive_entry *ae; + unsigned char *buff; + size_t buffsize = 39 * 2048; + size_t used; + unsigned int i; + + memset(nullb, 0, sizeof(nullb)); + buff = malloc(buffsize); + assert(buff != NULL); + + /* ISO9660 format: Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_iso9660(a)); + assertA(0 == archive_write_add_filter_none(a)); + assertA(0 == archive_write_set_option(a, NULL, "boot", "boot.img")); + if (write_info_tbl) + assertA(0 == archive_write_set_option(a, NULL, "boot-info-table", "1")); + assertA(0 == archive_write_set_option(a, NULL, "pad", NULL)); + assertA(0 == archive_write_open_memory(a, buff, buffsize, &used)); + + /* + * "boot.img" has a bunch of attributes and 10K bytes of null data. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_birthtime(ae, 3, 30); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "boot.img"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_nlink(ae, 1); + archive_entry_set_size(ae, 10*1024); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + for (i = 0; i < 10; i++) + assertEqualIntA(a, 1024, archive_write_data(a, nullb, 1024)); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + + assert(used == 2048 * 38); + /* Check System Area. */ + for (i = 0; i < 2048 * 16; i += 2048) { + assertEqualMem(buff+i, nullb, 2048); + } + + /* Primary Volume. */ + failure("Primary Volume Descriptor should be in 16 Logical Sector."); + assertEqualMem(buff+2048*16, primary_id, 8); + assertEqualMem(buff+2048*16+0x28, + "CDROM ", 32); + assertEqualMem(buff+2048*16+0x50, volumesize, 8); + + /* Boot Volume. */ + failure("Boot Volume Descriptor should be in 17 Logical Sector."); + assertEqualMem(buff+2048*17, boot_id, sizeof(boot_id)); + for (i = 0x27; i <= 0x46; i++) { + failure("Unused area must be all nulls."); + assert(buff[2048*17+i] == 0); + } + /* First sector of Boot Catalog. */ + assert(buff[2048*17+0x47] == 0x20); + assert(buff[2048*17+0x48] == 0x00); + assert(buff[2048*17+0x49] == 0x00); + assert(buff[2048*17+0x4a] == 0x00); + for (i = 0x4a; i <= 0x7ff; i++) { + failure("Unused area must be all nulls."); + assert(buff[2048*17+i] == 0); + } + + /* Supplementary Volume. */ + failure("Supplementary Volume(Joliet) Descriptor " + "should be in 18 Logical Sector."); + assertEqualMem(buff+2048*18, supplementary_id, 8); + assertEqualMem(buff+2048*18+0x28, volumeidu16, 32); + assertEqualMem(buff+2048*18+0x50, volumesize, 8); + failure("Date and Time of Primary Volume and " + "Date and Time of Supplementary Volume " + "must be the same."); + assertEqualMem(buff+2048*16+0x32d, buff+2048*18+0x32d, 0x44); + + /* Terminator. */ + failure("Volume Descriptor Set Terminator " + "should be in 19 Logical Sector."); + assertEqualMem(buff+2048*19, terminator_id, 8); + for (i = 8; i < 2048; i++) { + failure("Body of Volume Descriptor Set Terminator " + "should be all nulls."); + assert(buff[2048*19+i] == 0); + } + + /* Check signature of El-Torito. */ + assertEqualMem(buff+2048*31, el_torito_signature, 237); + assertEqualMem(buff+2048*31+237, nullb, 2048-237); + + /* Check contents of "boot.catalog". */ + assertEqualMem(buff+2048*32, boot_catalog, 64); + assertEqualMem(buff+2048*32+64, nullb, 2048-64); + + /* Check contents of "boot.img". */ + if (write_info_tbl) { + assertEqualMem(buff+2048*33, nullb, 8); + assertEqualMem(buff+2048*33+8, info_table, 56); + assertEqualMem(buff+2048*33+64, nullb, 2048-64); + } else { + assertEqualMem(buff+2048*33, nullb, 2048); + } + for (i = 2048*34; i < 2048*38; i += 2048) { + assertEqualMem(buff+i, nullb, 2048); + } + + /* + * Read ISO image. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, 0, archive_read_support_format_all(a)); + assertEqualIntA(a, 0, archive_read_support_filter_all(a)); + assertEqualIntA(a, 0, archive_read_open_memory(a, buff, used)); + + /* + * Read Root Directory + * Root Directory entry must be in ISO image. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_atime(ae), archive_entry_ctime(ae)); + assertEqualInt(archive_entry_atime(ae), archive_entry_mtime(ae)); + assertEqualString(".", archive_entry_pathname(ae)); + assert((S_IFDIR | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "boot.catalog". + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualString("boot.catalog", archive_entry_pathname(ae)); +#if !defined(_WIN32) && !defined(__CYGWIN__) + assert((S_IFREG | 0444) == archive_entry_mode(ae)); +#else + /* On Windows and CYGWIN, always set all exec bit ON by default. */ + assert((S_IFREG | 0555) == archive_entry_mode(ae)); +#endif + assertEqualInt(1, archive_entry_nlink(ae)); + assertEqualInt(2*1024, archive_entry_size(ae)); + assertEqualIntA(a, 1024, archive_read_data(a, buff2, 1024)); + assertEqualMem(buff2, boot_catalog, 64); + + /* + * Read "boot.img". + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_birthtime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("boot.img", archive_entry_pathname(ae)); + assert((S_IFREG | 0555) == archive_entry_mode(ae)); + assertEqualInt(1, archive_entry_nlink(ae)); + assertEqualInt(10*1024, archive_entry_size(ae)); + assertEqualIntA(a, 1024, archive_read_data(a, buff2, 1024)); + if (write_info_tbl) { + assertEqualMem(buff2, nullb, 8); + assertEqualMem(buff2+8, info_table, 56); + assertEqualMem(buff2+64, nullb, 1024-64); + } else + assertEqualMem(buff2, nullb, 1024); + + /* + * Verify the end of the archive. + */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + + free(buff); +} + +DEFINE_TEST(test_write_format_iso9660_boot) +{ + _test_write_format_iso9660_boot(0); + /* Use 'boot-info-table' option. */ + _test_write_format_iso9660_boot(1); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_iso9660_empty.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_iso9660_empty.c new file mode 100644 index 0000000..55c6c3c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_iso9660_empty.c @@ -0,0 +1,204 @@ +/*- + * Copyright (c) 2009-2011 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +/* + * Check that an "empty" ISO 9660 image is correctly created. + */ + +static const unsigned char primary_id[] = { + 0x01, 0x43, 0x44, 0x30, 0x30, 0x31, 0x01, 0x00 +}; +static const unsigned char volumesize[] = { + 0xb5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5 +}; +static const unsigned char volumeidu16[] = { + 0x00, 0x43, 0x00, 0x44, 0x00, 0x52, 0x00, 0x4f, + 0x00, 0x4d, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, + 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, + 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20 +}; +static const unsigned char supplementary_id[] = { + 0x02, 0x43, 0x44, 0x30, 0x30, 0x31, 0x01, 0x00 +}; +static const unsigned char terminator_id[] = { + 0xff, 0x43, 0x44, 0x30, 0x30, 0x31, 0x01, 0x00 +}; + +DEFINE_TEST(test_write_format_iso9660_empty) +{ + struct archive *a; + struct archive_entry *ae; + unsigned char *buff; + size_t buffsize = 190 * 2048; + size_t used; + unsigned int i; + + buff = malloc(buffsize); + assert(buff != NULL); + if (buff == NULL) + return; + + /* ISO9660 format: Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_iso9660(a)); + assertA(0 == archive_write_add_filter_none(a)); + assertA(0 == archive_write_set_bytes_per_block(a, 1)); + assertA(0 == archive_write_set_bytes_in_last_block(a, 1)); + assertA(0 == archive_write_open_memory(a, buff, buffsize, &used)); + + /* Add "." entry which must be ignored. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 0); + archive_entry_set_ctime(ae, 4, 0); + archive_entry_set_mtime(ae, 5, 0); + archive_entry_copy_pathname(ae, "."); + archive_entry_set_mode(ae, S_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Add ".." entry which must be ignored. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 0); + archive_entry_set_ctime(ae, 4, 0); + archive_entry_set_mtime(ae, 5, 0); + archive_entry_copy_pathname(ae, ".."); + archive_entry_set_mode(ae, S_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Add "/" entry which must be ignored. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 0); + archive_entry_set_ctime(ae, 4, 0); + archive_entry_set_mtime(ae, 5, 0); + archive_entry_copy_pathname(ae, "/"); + archive_entry_set_mode(ae, S_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Add "../" entry which must be ignored. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 0); + archive_entry_set_ctime(ae, 4, 0); + archive_entry_set_mtime(ae, 5, 0); + archive_entry_copy_pathname(ae, "../"); + archive_entry_set_mode(ae, S_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Add "../../." entry which must be ignored. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 0); + archive_entry_set_ctime(ae, 4, 0); + archive_entry_set_mtime(ae, 5, 0); + archive_entry_copy_pathname(ae, "../../."); + archive_entry_set_mode(ae, S_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Add "..//.././" entry which must be ignored. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 0); + archive_entry_set_ctime(ae, 4, 0); + archive_entry_set_mtime(ae, 5, 0); + archive_entry_copy_pathname(ae, "..//.././"); + archive_entry_set_mode(ae, S_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + + assert(used == 2048 * 181); + /* Check System Area. */ + for (i = 0; i < 2048 * 16; i++) { + failure("System Area should be all nulls."); + assert(buff[i] == 0); + } + + /* Primary Volume. */ + failure("Primary Volume Descriptor should be in 16 Logical Sector."); + assertEqualMem(buff+2048*16, primary_id, 8); + assertEqualMem(buff+2048*16+0x28, + "CDROM ", 32); + assertEqualMem(buff+2048*16+0x50, volumesize, 8); + + /* Supplementary Volume. */ + failure("Supplementary Volume(Joliet) Descriptor " + "should be in 17 Logical Sector."); + assertEqualMem(buff+2048*17, supplementary_id, 8); + assertEqualMem(buff+2048*17+0x28, volumeidu16, 32); + assertEqualMem(buff+2048*17+0x50, volumesize, 8); + failure("Date and Time of Primary Volume and " + "Date and Time of Supplementary Volume " + "must be the same."); + assertEqualMem(buff+2048*16+0x32d, buff+2048*17+0x32d, 0x44); + + /* Terminator. */ + failure("Volume Descriptor Set Terminator " + "should be in 18 Logical Sector."); + assertEqualMem(buff+2048*18, terminator_id, 8); + for (i = 8; i < 2048; i++) { + failure("Body of Volume Descriptor Set Terminator " + "should be all nulls."); + assert(buff[2048*18+i] == 0); + } + + /* Padding data. */ + for (i = 0; i < 2048*150; i++) { + failure("Padding data should be all nulls."); + assert(buff[2048*31+i] == 0); + } + + /* + * Read ISO image. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, 0, archive_read_support_format_all(a)); + assertEqualIntA(a, 0, archive_read_support_filter_all(a)); + assertEqualIntA(a, 0, archive_read_open_memory(a, buff, used)); + + /* + * Read Root Directory + * Root Directory entry must be in ISO image. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_atime(ae), archive_entry_ctime(ae)); + assertEqualInt(archive_entry_atime(ae), archive_entry_mtime(ae)); + assertEqualString(".", archive_entry_pathname(ae)); + assert((S_IFDIR | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Verify the end of the archive. + */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_iso9660_filename.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_iso9660_filename.c new file mode 100644 index 0000000..713883b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_iso9660_filename.c @@ -0,0 +1,474 @@ +/*- + * Copyright (c) 2009,2010 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +/* + * Check that an ISO 9660 image is correctly created. + */ +static void +add_entry(struct archive *a, const char *fname, const char *sym) +{ + struct archive_entry *ae; + + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_birthtime(ae, 2, 20); + archive_entry_set_atime(ae, 3, 30); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, fname); + if (sym != NULL) + archive_entry_set_symlink(ae, sym); + archive_entry_set_mode(ae, S_IFREG | 0555); + archive_entry_set_size(ae, 0); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); +} + +struct fns { + size_t maxlen; + size_t longest_len; + size_t maxflen; + size_t maxelen; + size_t alloc; + int cnt; + char **names; + int opt; +#define UPPER_CASE_ONLY 0x00001 +#define ONE_DOT 0x00002 +#define ALLOW_LDOT 0x00004 +}; + +enum vtype { + ROCKRIDGE, + JOLIET, + ISO9660 +}; + +/* + * Verify file + */ +static void +verify_file(struct archive *a, enum vtype type, struct fns *fns) +{ + struct archive_entry *ae; + int i; + + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + if (type == ROCKRIDGE) { + assertEqualInt(2, archive_entry_birthtime(ae)); + assertEqualInt(3, archive_entry_atime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + } else { + assertEqualInt(0, archive_entry_birthtime_is_set(ae)); + assertEqualInt(5, archive_entry_atime(ae)); + assertEqualInt(5, archive_entry_ctime(ae)); + } + assertEqualInt(5, archive_entry_mtime(ae)); + if (type == ROCKRIDGE) + assert((S_IFREG | 0555) == archive_entry_mode(ae)); + else + assert((S_IFREG | 0400) == archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + + /* + * Check if the same filename does not appear. + */ + for (i = 0; i < fns->cnt; i++) { + const char *p; + const char *pathname = archive_entry_pathname(ae); + const char *symlinkname = archive_entry_symlink(ae); + size_t length; + + if (symlinkname != NULL) { + length = strlen(symlinkname); + assert(length == 1 || length == 128 || length == 255); + assertEqualInt(symlinkname[length-1], 'x'); + } + failure("Found duplicate for %s", pathname); + assert(strcmp(fns->names[i], pathname) != 0); + assert((length = strlen(pathname)) <= fns->maxlen); + if (length > fns->longest_len) + fns->longest_len = length; + p = strrchr(pathname, '.'); + if (p != NULL) { + /* Check a length of file name. */ + assert((size_t)(p - pathname) <= fns->maxflen); + /* Check a length of file extension. */ + assert(strlen(p+1) <= fns->maxelen); + if (fns->opt & ONE_DOT) { + /* Do not have multi dot. */ + assert(strchr(pathname, '.') == p); + } + } + for (p = pathname; *p; p++) { + if (fns->opt & UPPER_CASE_ONLY) { + /* Do not have any lower-case character. */ + assert(*p < 'a' || *p > 'z'); + } else + break; + } + if ((fns->opt & ALLOW_LDOT) == 0) + /* Do not have a dot at the first position. */ + assert(*pathname != '.'); + } + /* Save the filename which is appeared to use above next time. */ + fns->names[fns->cnt++] = strdup(archive_entry_pathname(ae)); +} + +static void +verify(unsigned char *buff, size_t used, enum vtype type, struct fns *fns) +{ + struct archive *a; + struct archive_entry *ae; + size_t i; + + /* + * Read ISO image. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, 0, archive_read_support_format_all(a)); + assertEqualIntA(a, 0, archive_read_support_filter_all(a)); + if (type >= 1) + assertA(0 == archive_read_set_option(a, NULL, "rockridge", + NULL)); + if (type >= 2) + assertA(0 == archive_read_set_option(a, NULL, "joliet", + NULL)); + assertEqualIntA(a, 0, archive_read_open_memory(a, buff, used)); + + /* + * Read Root Directory + * Root Directory entry must be in ISO image. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_atime(ae), archive_entry_ctime(ae)); + assertEqualInt(archive_entry_atime(ae), archive_entry_mtime(ae)); + assertEqualString(".", archive_entry_pathname(ae)); + switch (type) { + case ROCKRIDGE: + assert((S_IFDIR | 0555) == archive_entry_mode(ae)); + break; + case JOLIET: + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + break; + case ISO9660: + assert((S_IFDIR | 0700) == archive_entry_mode(ae)); + break; + } + + /* + * Verify file status. + */ + memset(fns->names, 0, sizeof(char *) * fns->alloc); + fns->cnt = 0; + for (i = 0; i < fns->alloc; i++) + verify_file(a, type, fns); + for (i = 0; i < fns->alloc; i++) + free(fns->names[i]); + assertEqualInt((int)fns->longest_len, (int)fns->maxlen); + + /* + * Verify the end of the archive. + */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); +} + +static int +create_iso_image(unsigned char *buff, size_t buffsize, size_t *used, + const char *opt) +{ + struct archive *a; + int i, l, fcnt; + const int lens[] = { + 0, 1, 3, 5, 7, 8, 9, 29, 30, 31, 32, + 62, 63, 64, 65, 101, 102, 103, 104, + 191, 192, 193, 194, 204, 205, 206, 207, 208, + 252, 253, 254, 255, + -1 }; + char fname1[256]; + char fname2[256]; + char sym1[2]; + char sym128[129]; + char sym255[256]; + + /* ISO9660 format: Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_iso9660(a)); + assertA(0 == archive_write_add_filter_none(a)); + assertA(0 == archive_write_set_option(a, NULL, "pad", NULL)); + if (opt) + assertA(0 == archive_write_set_options(a, opt)); + assertA(0 == archive_write_set_bytes_per_block(a, 1)); + assertA(0 == archive_write_set_bytes_in_last_block(a, 1)); + assertA(0 == archive_write_open_memory(a, buff, buffsize, used)); + + sym1[0] = 'x'; + sym1[1] = '\0'; + for (i = 0; i < (int)sizeof(sym128)-2; i++) + sym128[i] = 'a'; + sym128[sizeof(sym128)-2] = 'x'; + sym128[sizeof(sym128)-1] = '\0'; + for (i = 0; i < (int)sizeof(sym255)-2; i++) + sym255[i] = 'a'; + sym255[sizeof(sym255)-2] = 'x'; + sym255[sizeof(sym255)-1] = '\0'; + + fcnt = 0; + for (i = 0; lens[i] >= 0; i++) { + for (l = 0; l < lens[i]; l++) { + fname1[l] = 'a'; + fname2[l] = 'A'; + } + if (l > 0) { + fname1[l] = '\0'; + fname2[l] = '\0'; + add_entry(a, fname1, NULL); + add_entry(a, fname2, sym1); + fcnt += 2; + } + if (l < 254) { + fname1[l] = '.'; + fname1[l+1] = 'c'; + fname1[l+2] = '\0'; + fname2[l] = '.'; + fname2[l+1] = 'C'; + fname2[l+2] = '\0'; + add_entry(a, fname1, sym128); + add_entry(a, fname2, sym255); + fcnt += 2; + } + if (l < 252) { + fname1[l] = '.'; + fname1[l+1] = 'p'; + fname1[l+2] = 'n'; + fname1[l+3] = 'g'; + fname1[l+4] = '\0'; + fname2[l] = '.'; + fname2[l+1] = 'P'; + fname2[l+2] = 'N'; + fname2[l+3] = 'G'; + fname2[l+4] = '\0'; + add_entry(a, fname1, NULL); + add_entry(a, fname2, sym1); + fcnt += 2; + } + if (l < 251) { + fname1[l] = '.'; + fname1[l+1] = 'j'; + fname1[l+2] = 'p'; + fname1[l+3] = 'e'; + fname1[l+4] = 'g'; + fname1[l+5] = '\0'; + fname2[l] = '.'; + fname2[l+1] = 'J'; + fname2[l+2] = 'P'; + fname2[l+3] = 'E'; + fname2[l+4] = 'G'; + fname2[l+5] = '\0'; + add_entry(a, fname1, sym128); + add_entry(a, fname2, sym255); + fcnt += 2; + } + } + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + + return (fcnt); +} + +DEFINE_TEST(test_write_format_iso9660_filename) +{ + unsigned char *buff; + size_t buffsize = 120 * 2048; + size_t used; + int fcnt; + struct fns fns; + + buff = malloc(buffsize); + assert(buff != NULL); + if (buff == NULL) + return; + memset(&fns, 0, sizeof(fns)); + + /* + * Create ISO image with no option. + */ + fcnt = create_iso_image(buff, buffsize, &used, NULL); + + fns.names = (char **)malloc(sizeof(char *) * fcnt); + assert(fns.names != NULL); + if (fns.names == NULL) { + free(buff); + return; + } + fns.alloc = fcnt; + + /* Verify rockridge filenames. */ + fns.longest_len = 0; + fns.maxlen = fns.maxflen = fns.maxelen = 255; + fns.opt = ALLOW_LDOT; + verify(buff, used, ROCKRIDGE, &fns); + + /* Verify joliet filenames. */ + fns.longest_len = 0; + fns.maxlen = fns.maxflen = fns.maxelen = 64; + fns.opt = ALLOW_LDOT; + verify(buff, used, JOLIET, &fns); + + /* Verify ISO9660 filenames. */ + fns.longest_len = 0; + fns.maxlen = 8+3+1; + fns.maxflen = 8; + fns.maxelen = 3; + fns.opt = UPPER_CASE_ONLY | ONE_DOT; + verify(buff, used, ISO9660, &fns); + + /* + * Create ISO image with iso-level=2. + */ + assertEqualInt(fcnt, create_iso_image(buff, buffsize, &used, + "iso-level=2")); + + /* Verify rockridge filenames. */ + fns.longest_len = 0; + fns.maxlen = fns.maxflen = fns.maxelen = 255; + fns.opt = ALLOW_LDOT; + verify(buff, used, ROCKRIDGE, &fns); + + /* Verify joliet filenames. */ + fns.longest_len = 0; + fns.maxlen = fns.maxflen = fns.maxelen = 64; + fns.opt = ALLOW_LDOT; + verify(buff, used, JOLIET, &fns); + + /* Verify ISO9660 filenames. */ + fns.longest_len = 0; + fns.maxlen = 31; + fns.maxflen = 30; + fns.maxelen = 30; + fns.opt = UPPER_CASE_ONLY | ONE_DOT; + verify(buff, used, ISO9660, &fns); + + /* + * Create ISO image with iso-level=3. + */ + assertEqualInt(fcnt, create_iso_image(buff, buffsize, &used, + "iso-level=3")); + + /* Verify rockridge filenames. */ + fns.longest_len = 0; + fns.maxlen = fns.maxflen = fns.maxelen = 255; + fns.opt = ALLOW_LDOT; + verify(buff, used, ROCKRIDGE, &fns); + + /* Verify joliet filenames. */ + fns.longest_len = 0; + fns.maxlen = fns.maxflen = fns.maxelen = 64; + fns.opt = ALLOW_LDOT; + verify(buff, used, JOLIET, &fns); + + /* Verify ISO9660 filenames. */ + fns.longest_len = 0; + fns.maxlen = 31; + fns.maxflen = 30; + fns.maxelen = 30; + fns.opt = UPPER_CASE_ONLY | ONE_DOT; + verify(buff, used, ISO9660, &fns); + + /* + * Create ISO image with iso-level=4. + */ + assertEqualInt(fcnt, create_iso_image(buff, buffsize, &used, + "iso-level=4")); + + /* Verify rockridge filenames. */ + fns.longest_len = 0; + fns.maxlen = fns.maxflen = fns.maxelen = 255; + fns.opt = ALLOW_LDOT; + verify(buff, used, ROCKRIDGE, &fns); + + /* Verify joliet filenames. */ + fns.longest_len = 0; + fns.maxlen = fns.maxflen = fns.maxelen = 64; + fns.opt = ALLOW_LDOT; + verify(buff, used, JOLIET, &fns); + + /* Verify ISO9660 filenames. */ + fns.longest_len = 0; + fns.maxlen = fns.maxflen = fns.maxelen = 193; + fns.opt = ALLOW_LDOT; + verify(buff, used, ISO9660, &fns); + + /* + * Create ISO image with iso-level=4 and !rockridge. + */ + assertEqualInt(fcnt, create_iso_image(buff, buffsize, &used, + "iso-level=4,!rockridge")); + + /* Verify joliet filenames. */ + fns.longest_len = 0; + fns.maxlen = fns.maxflen = fns.maxelen = 64; + fns.opt = ALLOW_LDOT; + verify(buff, used, JOLIET, &fns); + + /* Verify ISO9660 filenames. */ + fns.longest_len = 0; + fns.maxlen = fns.maxflen = fns.maxelen = 207; + fns.opt = ALLOW_LDOT; + verify(buff, used, ISO9660, &fns); + + /* + * Create ISO image with joliet=long. + */ + assertEqualInt(fcnt, create_iso_image(buff, buffsize, &used, + "joliet=long")); + + /* Verify rockridge filenames. */ + fns.longest_len = 0; + fns.maxlen = fns.maxflen = fns.maxelen = 255; + fns.opt = ALLOW_LDOT; + verify(buff, used, ROCKRIDGE, &fns); + + /* Verify joliet filenames. */ + fns.longest_len = 0; + fns.maxlen = fns.maxflen = fns.maxelen = 103; + fns.opt = ALLOW_LDOT; + verify(buff, used, JOLIET, &fns); + + /* Verify ISO9660 filenames. */ + fns.longest_len = 0; + fns.maxlen = 8+3+1; + fns.maxflen = 8; + fns.maxelen = 3; + fns.opt = UPPER_CASE_ONLY | ONE_DOT; + verify(buff, used, ISO9660, &fns); + + free(fns.names); + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_iso9660_zisofs.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_iso9660_zisofs.c new file mode 100644 index 0000000..2140ed8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_iso9660_zisofs.c @@ -0,0 +1,828 @@ +/*- + * Copyright (c) 2009-2011 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +/* + * Check that a "zisofs" ISO 9660 image is correctly created. + */ + +static const unsigned char primary_id[] = { + 0x01, 0x43, 0x44, 0x30, 0x30, 0x31, 0x01, 0x00 +}; +static const unsigned char volumesize[] = { + 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23 +}; +static const unsigned char volumesize2[] = { + 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36 +}; +static const unsigned char volumesize3[] = { + 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28 +}; +static const unsigned char volumeidu16[] = { + 0x00, 0x43, 0x00, 0x44, 0x00, 0x52, 0x00, 0x4f, + 0x00, 0x4d, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, + 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, + 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20 +}; +static const unsigned char supplementary_id[] = { + 0x02, 0x43, 0x44, 0x30, 0x30, 0x31, 0x01, 0x00 +}; +static const unsigned char terminator_id[] = { + 0xff, 0x43, 0x44, 0x30, 0x30, 0x31, 0x01, 0x00 +}; + +static const unsigned char zisofs_magic[8] = { + 0x37, 0xE4, 0x53, 0x96, 0xC9, 0xDB, 0xD6, 0x07 +}; + +static const unsigned char zisofs_data[24] = { + 0x37, 0xe4, 0x53, 0x96, 0xc9, 0xdb, 0xd6, 0x07, + 0x00, 0x80, 0x00, 0x00, 0x04, 0x0f, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00 +}; + +static const unsigned char boot_id[] = { + 0x00, 0x43, 0x44, 0x30, 0x30, 0x31, 0x01, 0x45, + 0x4c, 0x20, 0x54, 0x4f, 0x52, 0x49, 0x54, 0x4f, + 0x20, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +static const unsigned char boot_catalog[] = { + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xaa, 0x55, 0x55, 0xaa, + 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char el_torito_signature[] = { + "ER\355\001\012T\207\001RRIP_1991ATHE ROCK RIDGE " + "INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR POSIX " + "FILE SYSTEM SEMANTICSPLEASE CONTACT DISC PUBLISHER " + "FOR SPECIFICATION SOURCE. SEE PUBLISHER IDENTIFIER " + "IN PRIMARY VOLUME DESCRIPTOR FOR CONTACT INFORMATION." +}; + +static void +test_write_format_iso9660_zisofs_1(void) +{ + unsigned char buff2[1024]; + unsigned char nullb[1024]; + struct archive *a; + struct archive_entry *ae; + unsigned char *buff; + size_t buffsize = 36 * 2048; + size_t used; + unsigned int i; + int r; + + memset(nullb, 0, sizeof(nullb)); + buff = malloc(buffsize); + assert(buff != NULL); + if (buff == NULL) + return; + + /* ISO9660 format: Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, 0, archive_write_set_format_iso9660(a)); + assertEqualIntA(a, 0, archive_write_add_filter_none(a)); + r = archive_write_set_option(a, NULL, "zisofs", "1"); + if (r == ARCHIVE_FATAL) { + skipping("zisofs option not supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); + return; + } + assertEqualIntA(a, 0, archive_write_set_option(a, NULL, "pad", NULL)); + assertEqualIntA(a, 0, archive_write_open_memory(a, buff, buffsize, &used)); + + /* + * "file1" has a bunch of attributes and 256K bytes of null data. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_birthtime(ae, 3, 30); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "file1"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 256*1024); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 1024, archive_write_data(a, nullb, 1024)); + + /* + * "file2" has a bunch of attributes and 2048 bytes of null data. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_birthtime(ae, 3, 30); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "file2"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 2048); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 1024, archive_write_data(a, nullb, 1024)); + + /* + * "file3" has a bunch of attributes and 2049 bytes of null data. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_birthtime(ae, 3, 30); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "file3"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 2049); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 1024, archive_write_data(a, nullb, 1024)); + + /* + * "file4" has a bunch of attributes and 24 bytes of zisofs data + * which is compressed from 32K bytes null data. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_birthtime(ae, 3, 30); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "file4"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 24); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 24, archive_write_data(a, zisofs_data, 24)); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + + failure("The ISO image size should be 71680 bytes."); + assertEqualInt(used, 2048 * 35); + + /* Check System Area. */ + for (i = 0; i < 2048 * 16; i++) { + failure("System Area should be all nulls."); + assertEqualInt(buff[i], 0); + } + + /* Primary Volume. */ + failure("Primary Volume Descriptor should be in 16 Logical Sector."); + assertEqualMem(buff+2048*16, primary_id, 8); + assertEqualMem(buff+2048*16+0x28, + "CDROM ", 32); + assertEqualMem(buff+2048*16+0x50, volumesize, 8); + + /* Supplementary Volume. */ + failure("Supplementary Volume(Joliet) Descriptor " + "should be in 17 Logical Sector."); + assertEqualMem(buff+2048*17, supplementary_id, 8); + assertEqualMem(buff+2048*17+0x28, volumeidu16, 32); + assertEqualMem(buff+2048*17+0x50, volumesize, 8); + failure("Date and Time of Primary Volume and " + "Date and Time of Supplementary Volume " + "must be the same."); + assertEqualMem(buff+2048*16+0x32d, buff+2048*17+0x32d, 0x44); + + /* Terminator. */ + failure("Volume Descriptor Set Terminator " + "should be in 18 Logical Sector."); + assertEqualMem(buff+2048*18, terminator_id, 8); + for (i = 8; i < 2048; i++) { + failure("Body of Volume Descriptor Set Terminator " + "should be all nulls."); + assertEqualInt(buff[2048*18+i], 0); + } + + /* "file1" Contents is zisofs data. */ + failure("file1 image should be zisofs'ed."); + assertEqualMem(buff+2048*31, zisofs_magic, 8); + /* "file2" Contents is not zisofs data. */ + failure("file2 image should not be zisofs'ed."); + assertEqualMem(buff+2048*32, nullb, 8); + /* "file3" Contents is zisofs data. */ + failure("file3 image should be zisofs'ed."); + assertEqualMem(buff+2048*33, zisofs_magic, 8); + /* "file4" Contents is zisofs data. */ + failure("file4 image should be zisofs'ed."); + assertEqualMem(buff+2048*34, zisofs_magic, 8); + + /* + * Read ISO image. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, 0, archive_read_support_format_all(a)); + assertEqualIntA(a, 0, archive_read_support_filter_all(a)); + assertEqualIntA(a, 0, archive_read_open_memory(a, buff, used)); + + /* + * Read Root Directory + * Root Directory entry must be in ISO image. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_atime(ae), archive_entry_ctime(ae)); + assertEqualInt(archive_entry_atime(ae), archive_entry_mtime(ae)); + assertEqualString(".", archive_entry_pathname(ae)); + assert((S_IFDIR | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "file1" which has 256K bytes null data. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + /* assertEqualInt(3, archive_entry_birthtime(ae)); */ + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("file1", archive_entry_pathname(ae)); + assert((S_IFREG | 0555) == archive_entry_mode(ae)); + assertEqualInt(256*1024, archive_entry_size(ae)); + assertEqualIntA(a, 1024, archive_read_data(a, buff2, 1024)); + assertEqualMem(buff2, nullb, 1024); + + /* + * Read "file2" which has 2048 bytes null data. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + /* assertEqualInt(3, archive_entry_birthtime(ae)); */ + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("file2", archive_entry_pathname(ae)); + assert((S_IFREG | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualIntA(a, 1024, archive_read_data(a, buff2, 1024)); + assertEqualMem(buff2, nullb, 1024); + + /* + * Read "file3" which has 2049 bytes null data. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + /* assertEqualInt(3, archive_entry_birthtime(ae)); */ + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("file3", archive_entry_pathname(ae)); + assert((S_IFREG | 0555) == archive_entry_mode(ae)); + assertEqualInt(2049, archive_entry_size(ae)); + assertEqualIntA(a, 1024, archive_read_data(a, buff2, 1024)); + assertEqualMem(buff2, nullb, 1024); + + /* + * Read "file4" which has 32K bytes null data. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + /* assertEqualInt(3, archive_entry_birthtime(ae)); */ + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("file4", archive_entry_pathname(ae)); + assert((S_IFREG | 0555) == archive_entry_mode(ae)); + assertEqualInt(32768, archive_entry_size(ae)); + assertEqualIntA(a, 1024, archive_read_data(a, buff2, 1024)); + assertEqualMem(buff2, nullb, 1024); + + /* + * Verify the end of the archive. + */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + + free(buff); +} + +static void +test_write_format_iso9660_zisofs_2(void) +{ + unsigned char buff2[1024]; + unsigned char data[1024]; + struct archive *a; + struct archive_entry *ae; + unsigned char *buff; + size_t buffsize = 60 * 2048; + size_t used; + unsigned int i; + int r; + + buff = malloc(buffsize); + assert(buff != NULL); + if (buff == NULL) + return; + + /* ISO9660 format: Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, 0, archive_write_set_format_iso9660(a)); + assertEqualIntA(a, 0, archive_write_add_filter_none(a)); + r = archive_write_set_option(a, NULL, "zisofs", "1"); + if (r == ARCHIVE_FATAL) { + skipping("zisofs option not supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); + return; + } + assertEqualIntA(a, 0, archive_write_set_option(a, NULL, "pad", NULL)); + assertEqualIntA(a, 0, archive_write_open_memory(a, buff, buffsize, &used)); + + /* + * "file1" has a bunch of attributes and 256K bytes of random data. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_birthtime(ae, 3, 30); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "file1"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 256*1024); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + for (i = 0; i < 256; i++) { + int j; + if (i == 0) { + for (j = 0; j < (int)sizeof(data); j++) + data[j] = (i^j) & 0xff; + } else { + for (j = 0; j < (int)sizeof(data); j++) + data[j] ^= i+j; + } + assertEqualIntA(a, 1024, archive_write_data(a, data, 1024)); + } + + /* + * "file2" has a bunch of attributes and 2048 bytes data. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_birthtime(ae, 3, 30); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "file2"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 2048); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + memset(data, 'a', sizeof(data)); + assertEqualIntA(a, 1024, archive_write_data(a, data, 1024)); + memset(data, 'b', sizeof(data)); + assertEqualIntA(a, 1024, archive_write_data(a, data, 1024)); + + /* + * "file3" has a bunch of attributes and 1024 bytes of 'Z' + * + 1025 bytes of null data. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_birthtime(ae, 3, 30); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "file3"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 2049); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + memset(data, 'Z', sizeof(data)); + assertEqualIntA(a, 1024, archive_write_data(a, data, 1024)); + + /* + * "file4" has a bunch of attributes and 24 bytes of zisofs data + * which is compressed from 32K bytes null data. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_birthtime(ae, 3, 30); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "file4"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 24); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 24, archive_write_data(a, zisofs_data, 24)); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + + failure("The ISO image size should be 110592 bytes."); + assertEqualInt(used, 2048 * 54); + + /* Check System Area. */ + for (i = 0; i < 2048 * 16; i++) { + failure("System Area should be all nulls."); + assertEqualInt(buff[i], 0); + } + + /* Primary Volume. */ + failure("Primary Volume Descriptor should be in 16 Logical Sector."); + assertEqualMem(buff+2048*16, primary_id, 8); + assertEqualMem(buff+2048*16+0x28, + "CDROM ", 32); + assertEqualMem(buff+2048*16+0x50, volumesize2, 8); + + /* Supplementary Volume. */ + failure("Supplementary Volume(Joliet) Descriptor " + "should be in 17 Logical Sector."); + assertEqualMem(buff+2048*17, supplementary_id, 8); + assertEqualMem(buff+2048*17+0x28, volumeidu16, 32); + assertEqualMem(buff+2048*17+0x50, volumesize2, 8); + failure("Date and Time of Primary Volume and " + "Date and Time of Supplementary Volume " + "must be the same."); + assertEqualMem(buff+2048*16+0x32d, buff+2048*17+0x32d, 0x44); + + /* Terminator. */ + failure("Volume Descriptor Set Terminator " + "should be in 18 Logical Sector."); + assertEqualMem(buff+2048*18, terminator_id, 8); + for (i = 8; i < 2048; i++) { + failure("Body of Volume Descriptor Set Terminator " + "should be all nulls."); + assertEqualInt(buff[2048*18+i], 0); + } + + /* "file1" Contents is zisofs data. */ + failure("file1 image should be zisofs'ed."); + assertEqualMem(buff+2048*31, zisofs_magic, 8); + /* "file2" Contents is not zisofs data. */ + memset(data, 'a', sizeof(data)); + failure("file2 image should not be zisofs'ed."); + assertEqualMem(buff+2048*51, data, 1024); + memset(data, 'b', sizeof(data)); + failure("file2 image should not be zisofs'ed."); + assertEqualMem(buff+2048*51+1024, data, 1024); + /* "file3" Contents is zisofs data. */ + failure("file3 image should be zisofs'ed."); + assertEqualMem(buff+2048*52, zisofs_magic, 8); + /* "file4" Contents is zisofs data. */ + failure("file4 image should be zisofs'ed."); + assertEqualMem(buff+2048*53, zisofs_magic, 8); + + /* + * Read ISO image. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, 0, archive_read_support_format_all(a)); + assertEqualIntA(a, 0, archive_read_support_filter_all(a)); + assertEqualIntA(a, 0, archive_read_open_memory(a, buff, used)); + + /* + * Read Root Directory + * Root Directory entry must be in ISO image. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_atime(ae), archive_entry_ctime(ae)); + assertEqualInt(archive_entry_atime(ae), archive_entry_mtime(ae)); + assertEqualString(".", archive_entry_pathname(ae)); + assert((S_IFDIR | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "file1" which has 256K bytes random data. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("file1", archive_entry_pathname(ae)); + assert((S_IFREG | 0555) == archive_entry_mode(ae)); + assertEqualInt(256*1024, archive_entry_size(ae)); + assertEqualIntA(a, 1024, archive_read_data(a, buff2, 1024)); + + /* + * Read "file2" which has 2048 bytes data. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("file2", archive_entry_pathname(ae)); + assert((S_IFREG | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualIntA(a, 1024, archive_read_data(a, buff2, 1024)); + memset(data, 'a', sizeof(data)); + assertEqualMem(buff2, data, 1024); + + /* + * Read "file3" which has 2049 bytes data. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("file3", archive_entry_pathname(ae)); + assert((S_IFREG | 0555) == archive_entry_mode(ae)); + assertEqualInt(2049, archive_entry_size(ae)); + assertEqualIntA(a, 1024, archive_read_data(a, buff2, 1024)); + memset(data, 'Z', sizeof(data)); + assertEqualMem(buff2, data, 1024); + + /* + * Read "file4" which has 32K bytes null data. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("file4", archive_entry_pathname(ae)); + assert((S_IFREG | 0555) == archive_entry_mode(ae)); + assertEqualInt(32768, archive_entry_size(ae)); + assertEqualIntA(a, 1024, archive_read_data(a, buff2, 1024)); + memset(data, 0, sizeof(data)); + assertEqualMem(buff2, data, 1024); + + /* + * Verify the end of the archive. + */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + + free(buff); +} + +/* + * Make a bootable ISO image with "zisofs" option. + */ +static void +test_write_format_iso9660_zisofs_3(void) +{ + unsigned char buff2[1024]; + unsigned char nullb[2048]; + struct archive *a; + struct archive_entry *ae; + unsigned char *buff; + size_t buffsize = 50 * 2048; + size_t used; + unsigned int i; + int r; + + memset(nullb, 0, sizeof(nullb)); + buff = malloc(buffsize); + assert(buff != NULL); + if (buff == NULL) + return; + + /* ISO9660 format: Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, 0, archive_write_set_format_iso9660(a)); + assertEqualIntA(a, 0, archive_write_add_filter_none(a)); + r = archive_write_set_option(a, NULL, "zisofs", "1"); + if (r == ARCHIVE_FATAL) { + skipping("zisofs option not supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); + return; + } + assertEqualIntA(a, 0, archive_write_set_option(a, NULL, "boot", "boot.img")); + assertEqualIntA(a, 0, archive_write_set_option(a, NULL, "pad", NULL)); + assertEqualIntA(a, 0, archive_write_open_memory(a, buff, buffsize, &used)); + + /* + * "file1" has a bunch of attributes and 256K bytes of null data. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_birthtime(ae, 3, 30); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "boot.img"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 10*1024); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 1024, archive_write_data(a, nullb, 1024)); + + /* + * "file2" has a bunch of attributes and 2048 bytes of null data. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_birthtime(ae, 3, 30); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "file2"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 2048); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 1024, archive_write_data(a, nullb, 1024)); + + /* + * "file3" has a bunch of attributes and 2049 bytes of null data. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_birthtime(ae, 3, 30); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "file3"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 2049); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 1024, archive_write_data(a, nullb, 1024)); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + + failure("The ISO image size should be 81920 bytes."); + assertEqualInt(used, 2048 * 40); + + /* Check System Area. */ + for (i = 0; i < 2048 * 16; i++) { + failure("System Area should be all nulls."); + assertEqualInt(buff[i], 0); + } + + /* Primary Volume. */ + failure("Primary Volume Descriptor should be in 16 Logical Sector."); + assertEqualMem(buff+2048*16, primary_id, 8); + assertEqualMem(buff+2048*16+0x28, + "CDROM ", 32); + assertEqualMem(buff+2048*16+0x50, volumesize3, 8); + + /* Boot Volume. */ + failure("Boot Volume Descriptor should be in 17 Logical Sector."); + assertEqualMem(buff+2048*17, boot_id, sizeof(boot_id)); + for (i = 0x27; i <= 0x46; i++) { + failure("Unused area must be all nulls."); + assert(buff[2048*17+i] == 0); + } + /* First sector of Boot Catalog. */ + assert(buff[2048*17+0x47] == 0x20); + assert(buff[2048*17+0x48] == 0x00); + assert(buff[2048*17+0x49] == 0x00); + assert(buff[2048*17+0x4a] == 0x00); + for (i = 0x4a; i <= 0x7ff; i++) { + failure("Unused area must be all nulls."); + assert(buff[2048*17+i] == 0); + } + + /* Supplementary Volume. */ + failure("Supplementary Volume(Joliet) Descriptor " + "should be in 18 Logical Sector."); + assertEqualMem(buff+2048*18, supplementary_id, 8); + assertEqualMem(buff+2048*18+0x28, volumeidu16, 32); + assertEqualMem(buff+2048*18+0x50, volumesize3, 8); + failure("Date and Time of Primary Volume and " + "Date and Time of Supplementary Volume " + "must be the same."); + assertEqualMem(buff+2048*16+0x32d, buff+2048*18+0x32d, 0x44); + + /* Terminator. */ + failure("Volume Descriptor Set Terminator " + "should be in 19 Logical Sector."); + assertEqualMem(buff+2048*19, terminator_id, 8); + for (i = 8; i < 2048; i++) { + failure("Body of Volume Descriptor Set Terminator " + "should be all nulls."); + assertEqualInt(buff[2048*19+i], 0); + } + + /* Check signature of El-Torito. */ + assertEqualMem(buff+2048*31, el_torito_signature, 237); + assertEqualMem(buff+2048*31+237, nullb, 2048-237); + + /* Check contents of "boot.catalog". */ + assertEqualMem(buff+2048*32, boot_catalog, 64); + assertEqualMem(buff+2048*32+64, nullb, 2048-64); + + /* Check contents of "boot.img". */ + failure("boot.img image should not be zisofs'ed."); + assertEqualMem(buff+2048*33, nullb, 2048); + for (i = 2048*34; i < 2048*38; i += 2048) { + assertEqualMem(buff+i, nullb, 2048); + } + + /* "file2" Contents is not zisofs data. */ + failure("file2 image should not be zisofs'ed."); + assertEqualMem(buff+2048*38, nullb, 8); + /* "file3" Contents is zisofs data. */ + failure("file3 image should be zisofs'ed."); + assertEqualMem(buff+2048*39, zisofs_magic, 8); + + /* + * Read ISO image. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, 0, archive_read_support_format_all(a)); + assertEqualIntA(a, 0, archive_read_support_filter_all(a)); + assertEqualIntA(a, 0, archive_read_open_memory(a, buff, used)); + + /* + * Read Root Directory + * Root Directory entry must be in ISO image. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_atime(ae), archive_entry_ctime(ae)); + assertEqualInt(archive_entry_atime(ae), archive_entry_mtime(ae)); + assertEqualString(".", archive_entry_pathname(ae)); + assert((S_IFDIR | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "boot.catalog". + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualString("boot.catalog", archive_entry_pathname(ae)); +#if !defined(_WIN32) && !defined(__CYGWIN__) + assert((S_IFREG | 0444) == archive_entry_mode(ae)); +#else + /* On Windows and CYGWIN, always set all exec bit ON by default. */ + assert((S_IFREG | 0555) == archive_entry_mode(ae)); +#endif + assertEqualInt(1, archive_entry_nlink(ae)); + assertEqualInt(2*1024, archive_entry_size(ae)); + assertEqualIntA(a, 1024, archive_read_data(a, buff2, 1024)); + assertEqualMem(buff2, boot_catalog, 64); + + /* + * Read "boot.img". + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(3, archive_entry_birthtime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("boot.img", archive_entry_pathname(ae)); + assert((S_IFREG | 0555) == archive_entry_mode(ae)); + assertEqualInt(1, archive_entry_nlink(ae)); + assertEqualInt(10*1024, archive_entry_size(ae)); + assertEqualIntA(a, 1024, archive_read_data(a, buff2, 1024)); + assertEqualMem(buff2, nullb, 1024); + + /* + * Read "file2" which has 2048 bytes null data. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("file2", archive_entry_pathname(ae)); + assert((S_IFREG | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualIntA(a, 1024, archive_read_data(a, buff2, 1024)); + assertEqualMem(buff2, nullb, 1024); + + /* + * Read "file3" which has 2049 bytes null data. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualString("file3", archive_entry_pathname(ae)); + assert((S_IFREG | 0555) == archive_entry_mode(ae)); + assertEqualInt(2049, archive_entry_size(ae)); + assertEqualIntA(a, 1024, archive_read_data(a, buff2, 1024)); + assertEqualMem(buff2, nullb, 1024); + + /* + * Verify the end of the archive. + */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + + free(buff); +} + +DEFINE_TEST(test_write_format_iso9660_zisofs) +{ + test_write_format_iso9660_zisofs_1(); + test_write_format_iso9660_zisofs_2(); + test_write_format_iso9660_zisofs_3(); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_mtree.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_mtree.c new file mode 100644 index 0000000..5109e09 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_mtree.c @@ -0,0 +1,272 @@ +/*- + * Copyright (c) 2009 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_format_mtree.c 191183 2009-04-17 01:06:31Z kientzle $"); + +static char buff[4096]; +static struct { + const char *path; + mode_t mode; + time_t mtime; + uid_t uid; + gid_t gid; +} entries[] = { + { "./COPYING", S_IFREG | 0644, 1231975636, 1001, 1001 }, + { "./Makefile", S_IFREG | 0644, 1233041050, 1001, 1001 }, + { "./NEWS", S_IFREG | 0644, 1231975636, 1001, 1001 }, + { "./PROJECTS", S_IFREG | 0644, 1231975636, 1001, 1001 }, + { "./README", S_IFREG | 0644, 1231975636, 1001, 1001 }, + { "./subdir", S_IFDIR | 0755, 1233504586, 1001, 1001 }, + { "./subdir/README", S_IFREG | 0664, 1231975636, 1002, 1001 }, + { "./subdir/config", S_IFREG | 0664, 1232266273, 1003, 1003 }, + { "./subdir2", S_IFDIR | 0755, 1233504586, 1001, 1001 }, + { "./subdir3", S_IFDIR | 0755, 1233504586, 1001, 1001 }, + { "./subdir3/mtree", S_IFREG | 0664, 1232266273, 1003, 1003 }, + { NULL, 0, 0, 0, 0 } +}; +static struct { + const char *path; + mode_t mode; + time_t mtime; + uid_t uid; + gid_t gid; +} entries2[] = { + { "COPYING", S_IFREG | 0644, 1231975636, 1001, 1001 }, + { "Makefile", S_IFREG | 0644, 1233041050, 1001, 1001 }, + { "NEWS", S_IFREG | 0644, 1231975636, 1001, 1001 }, + { "PROJECTS", S_IFREG | 0644, 1231975636, 1001, 1001 }, + { "README", S_IFREG | 0644, 1231975636, 1001, 1001 }, + { "subdir", S_IFDIR | 0755, 1233504586, 1001, 1001 }, + { "subdir/README", S_IFREG | 0664, 1231975636, 1002, 1001 }, + { "subdir/config", S_IFREG | 0664, 1232266273, 1003, 1003 }, + { "subdir2", S_IFDIR | 0755, 1233504586, 1001, 1001 }, + { "subdir3", S_IFDIR | 0755, 1233504586, 1001, 1001 }, + { "subdir3/mtree", S_IFREG | 0664, 1232266273, 1003, 1003 }, + { NULL, 0, 0, 0, 0 } +}; + +static void +test_write_format_mtree_sub(int use_set, int dironly) +{ + struct archive_entry *ae; + struct archive* a; + size_t used; + int i; + + /* Create a mtree format archive. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_mtree(a)); + if (use_set) + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_option(a, NULL, "use-set", "1")); + if (dironly) + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_option(a, NULL, "dironly", "1")); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff)-1, &used)); + + /* Write entries */ + for (i = 0; entries[i].path != NULL; i++) { + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, entries[i].mtime, 0); + assert(entries[i].mtime == archive_entry_mtime(ae)); + archive_entry_set_mode(ae, entries[i].mode); + assert(entries[i].mode == archive_entry_mode(ae)); + archive_entry_set_uid(ae, entries[i].uid); + assert(entries[i].uid == archive_entry_uid(ae)); + archive_entry_set_gid(ae, entries[i].gid); + assert(entries[i].gid == archive_entry_gid(ae)); + archive_entry_copy_pathname(ae, entries[i].path); + if ((entries[i].mode & AE_IFMT) != S_IFDIR) + archive_entry_set_size(ae, 8); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + if ((entries[i].mode & AE_IFMT) != S_IFDIR) + assertEqualIntA(a, 8, + archive_write_data(a, "Hello012", 15)); + archive_entry_free(ae); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + if (use_set) { + const char *p; + + buff[used] = '\0'; + assert(NULL != (p = strstr(buff, "\n/set "))); + if (p != NULL) { + char *r; + const char *o; + p++; + r = strchr(p, '\n'); + if (r != NULL) + *r = '\0'; + if (dironly) + o = "/set type=dir uid=1001 gid=1001 mode=755"; + else + o = "/set type=file uid=1001 gid=1001 mode=644"; + assertEqualString(o, p); + if (r != NULL) + *r = '\n'; + } + } + + /* + * Read the data and check it. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + + /* Read entries */ + for (i = 0; entries[i].path != NULL; i++) { + if (dironly && (entries[i].mode & AE_IFMT) != S_IFDIR) + continue; + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(entries[i].mtime, archive_entry_mtime(ae)); + assertEqualInt(entries[i].mode, archive_entry_mode(ae)); + assertEqualInt(entries[i].uid, archive_entry_uid(ae)); + assertEqualInt(entries[i].gid, archive_entry_gid(ae)); + assertEqualString(entries[i].path, archive_entry_pathname(ae)); + if ((entries[i].mode & AE_IFMT) != S_IFDIR) + assertEqualInt(8, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +static void +test_write_format_mtree_sub2(int use_set, int dironly) +{ + struct archive_entry *ae; + struct archive* a; + size_t used; + int i; + char str[32]; + + /* Create a mtree format archive. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_mtree(a)); + if (use_set) + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_option(a, NULL, "use-set", "1")); + if (dironly) + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_option(a, NULL, "dironly", "1")); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff)-1, &used)); + + /* Write entries2 */ + for (i = 0; entries2[i].path != NULL; i++) { + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, entries2[i].mtime, 0); + assert(entries2[i].mtime == archive_entry_mtime(ae)); + archive_entry_set_mode(ae, entries2[i].mode); + assert(entries2[i].mode == archive_entry_mode(ae)); + archive_entry_set_uid(ae, entries2[i].uid); + assert(entries2[i].uid == archive_entry_uid(ae)); + archive_entry_set_gid(ae, entries2[i].gid); + assert(entries2[i].gid == archive_entry_gid(ae)); + archive_entry_copy_pathname(ae, entries2[i].path); + if ((entries2[i].mode & AE_IFMT) != S_IFDIR) + archive_entry_set_size(ae, 8); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + if ((entries2[i].mode & AE_IFMT) != S_IFDIR) + assertEqualIntA(a, 8, + archive_write_data(a, "Hello012", 15)); + archive_entry_free(ae); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + if (use_set) { + const char *p; + + buff[used] = '\0'; + assert(NULL != (p = strstr(buff, "\n/set "))); + if (p != NULL) { + char *r; + const char *o; + p++; + r = strchr(p, '\n'); + if (r != NULL) + *r = '\0'; + if (dironly) + o = "/set type=dir uid=1001 gid=1001 mode=755"; + else + o = "/set type=file uid=1001 gid=1001 mode=644"; + assertEqualString(o, p); + if (r != NULL) + *r = '\n'; + } + } + + /* + * Read the data and check it. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + + /* Read entries2 */ + memset(str, 0, sizeof(str)); + strcpy(str, "./"); + for (i = 0; entries2[i].path != NULL; i++) { + if (dironly && (entries2[i].mode & AE_IFMT) != S_IFDIR) + continue; + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(entries2[i].mtime, archive_entry_mtime(ae)); + assertEqualInt(entries2[i].mode, archive_entry_mode(ae)); + assertEqualInt(entries2[i].uid, archive_entry_uid(ae)); + assertEqualInt(entries2[i].gid, archive_entry_gid(ae)); + strcpy(str + 2, entries2[i].path); + assertEqualString(str, archive_entry_pathname(ae)); + if ((entries2[i].mode & AE_IFMT) != S_IFDIR) + assertEqualInt(8, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_write_format_mtree) +{ + /* Default setting */ + test_write_format_mtree_sub(0, 0); + /* Directory only */ + test_write_format_mtree_sub(0, 1); + /* Use /set keyword */ + test_write_format_mtree_sub(1, 0); + /* Use /set keyword with directory only */ + test_write_format_mtree_sub(1, 1); +} + +DEFINE_TEST(test_write_format_mtree_no_leading_dotslash) +{ + /* Default setting */ + test_write_format_mtree_sub2(0, 0); + /* Directory only */ + test_write_format_mtree_sub2(0, 1); + /* Use /set keyword */ + test_write_format_mtree_sub2(1, 0); + /* Use /set keyword with directory only */ + test_write_format_mtree_sub2(1, 1); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_mtree_absolute_path.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_mtree_absolute_path.c new file mode 100644 index 0000000..e3972f1 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_mtree_absolute_path.c @@ -0,0 +1,99 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +static char buff[4096]; + +DEFINE_TEST(test_write_format_mtree_absolute_path) +{ + struct archive_entry *ae; + struct archive* a; + size_t used; + + /* Create a mtree format archive. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_mtree(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff)-1, &used)); + + /* Write "." file. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "."); + archive_entry_set_mode(ae, AE_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Write "/file" file. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "/file"); + archive_entry_set_size(ae, 0); + archive_entry_set_mode(ae, AE_IFREG | 0644); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Write "/dir" directory. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "/dir"); + archive_entry_set_mode(ae, AE_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Read the data and check it. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + + /* Read "." file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + failure("The path should be just \".\""); + assertEqualString(archive_entry_pathname(ae), "."); + assertEqualInt(archive_entry_mode(ae), AE_IFDIR | 0755); + + /* Read "/file" file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + failure("The path should have \"./\" prefix"); + assertEqualString(archive_entry_pathname(ae), "./file"); + assertEqualInt(archive_entry_size(ae), 0); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + + /* Read "/dir" file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + failure("The path should have \"./\" prefix"); + assertEqualString(archive_entry_pathname(ae), "./dir"); + assertEqualInt(archive_entry_mode(ae), AE_IFDIR | 0755); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_mtree_classic.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_mtree_classic.c new file mode 100644 index 0000000..9a75fdd --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_mtree_classic.c @@ -0,0 +1,194 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +static char buff[4096]; +static struct { + const char *path; + mode_t mode; + int nlink; + time_t mtime; + uid_t uid; + gid_t gid; +} entries[] = { + { ".", S_IFDIR | 0755, 3, 1231975636, 1001, 1001 }, + { "./COPYING", S_IFREG | 0644, 1, 1231975636, 1001, 1001 }, + { "./Makefile", S_IFREG | 0644, 1, 1233041050, 1001, 1001 }, + { "./NEWS", S_IFREG | 0644, 1, 1231975636, 1001, 1001 }, + { "./PROJECTS", S_IFREG | 0644, 1, 1231975636, 1001, 1001 }, + { "./README", S_IFREG | 0644, 1, 1231975636, 1001, 1001 }, + { "./subdir", S_IFDIR | 0755, 3, 1233504586, 1001, 1001 }, + { "./subdir/README", S_IFREG | 0664, 1, 1231975636, 1002, 1001 }, + { "./subdir/config", S_IFREG | 0664, 1, 1232266273, 1003, 1003 }, + { "./subdir2", S_IFDIR | 0755, 3, 1233504586, 1001, 1001 }, + { "./subdir3", S_IFDIR | 0755, 3, 1233504586, 1001, 1001 }, + { "./subdir3/mtree", S_IFREG | 0664, 2, 1232266273, 1003, 1003 }, + { NULL, 0, 0, 0, 0, 0 } +}; + +static const char image [] = { +"#mtree\n" +"\n" +"# .\n" +"/set type=file uid=1001 gid=1001 mode=644\n" +". time=1231975636.0 mode=755 type=dir\n" +" COPYING time=1231975636.0 size=8\n" +" Makefile time=1233041050.0 size=8\n" +" NEWS time=1231975636.0 size=8\n" +" PROJECTS time=1231975636.0 size=8\n" +" README time=1231975636.0 size=8\n" +"\n" +"# ./subdir\n" +"/set mode=664\n" +"subdir time=1233504586.0 mode=755 type=dir\n" +" README time=1231975636.0 uid=1002 size=8\n" +" config time=1232266273.0 gid=1003 uid=1003 size=8\n" +"# ./subdir\n" +"..\n" +"\n" +"\n" +"# ./subdir2\n" +"subdir2 time=1233504586.0 mode=755 type=dir\n" +"# ./subdir2\n" +"..\n" +"\n" +"\n" +"# ./subdir3\n" +"subdir3 time=1233504586.0 mode=755 type=dir\n" +" mtree nlink=2 time=1232266273.0 gid=1003 uid=1003 size=8\n" +"# ./subdir3\n" +"..\n" +"\n" +"..\n\n" +}; + +static const char image_dironly [] = { +"#mtree\n" +"# .\n" +"/set type=dir uid=1001 gid=1001 mode=755\n" +". time=1231975636.0\n" +"# ./subdir\n" +"subdir time=1233504586.0\n" +"# ./subdir\n" +"..\n" +"# ./subdir2\n" +"subdir2 time=1233504586.0\n" +"# ./subdir2\n" +"..\n" +"# ./subdir3\n" +"subdir3 time=1233504586.0\n" +"# ./subdir3\n" +"..\n" +"..\n" +}; + +static void +test_write_format_mtree_sub(int dironly) +{ + struct archive_entry *ae; + struct archive* a; + size_t used; + int i; + + /* Create a mtree format archive. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_mtree_classic(a)); + if (dironly) + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_format_option(a, NULL, "dironly", "1")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff)-1, &used)); + + /* Write entries */ + for (i = 0; entries[i].path != NULL; i++) { + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_nlink(ae, entries[i].nlink); + assertEqualInt(entries[i].nlink, archive_entry_nlink(ae)); + archive_entry_set_mtime(ae, entries[i].mtime, 0); + assertEqualInt(entries[i].mtime, archive_entry_mtime(ae)); + archive_entry_set_mode(ae, entries[i].mode); + assertEqualInt(entries[i].mode, archive_entry_mode(ae)); + archive_entry_set_uid(ae, entries[i].uid); + assertEqualInt(entries[i].uid, archive_entry_uid(ae)); + archive_entry_set_gid(ae, entries[i].gid); + assertEqualInt(entries[i].gid, archive_entry_gid(ae)); + archive_entry_copy_pathname(ae, entries[i].path); + if ((entries[i].mode & AE_IFMT) != S_IFDIR) + archive_entry_set_size(ae, 8); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + if ((entries[i].mode & AE_IFMT) != S_IFDIR) + assertEqualIntA(a, 8, + archive_write_data(a, "Hello012", 15)); + archive_entry_free(ae); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + buff[used] = '\0'; + if (dironly) + assertEqualString(buff, image_dironly); + else + assertEqualString(buff, image); + + /* + * Read the data and check it. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + + /* Read entries */ + for (i = 0; entries[i].path != NULL; i++) { + if (dironly && (entries[i].mode & AE_IFMT) != S_IFDIR) + continue; + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(entries[i].mtime, archive_entry_mtime(ae)); + assertEqualInt(entries[i].mode, archive_entry_mode(ae)); + assertEqualInt(entries[i].uid, archive_entry_uid(ae)); + assertEqualInt(entries[i].gid, archive_entry_gid(ae)); + if (i > 0) + assertEqualString(entries[i].path + 2, + archive_entry_pathname(ae)); + else + assertEqualString(entries[i].path, + archive_entry_pathname(ae)); + if ((entries[i].mode & AE_IFMT) != S_IFDIR) + assertEqualInt(8, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_write_format_mtree_classic) +{ + /* Generate classic format. */ + test_write_format_mtree_sub(0); + /* Generate classic format and Write directory only. */ + test_write_format_mtree_sub(1); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_mtree_classic_indent.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_mtree_classic_indent.c new file mode 100644 index 0000000..6d1c549 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_mtree_classic_indent.c @@ -0,0 +1,196 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +static char buff[4096]; +static struct { + const char *path; + mode_t mode; + int nlink; + time_t mtime; + uid_t uid; + gid_t gid; +} entries[] = { + { ".", S_IFDIR | 0755, 3, 1231975636, 1001, 1001 }, + { "./COPYING", S_IFREG | 0644, 1, 1231975636, 1001, 1001 }, + { "./Makefile", S_IFREG | 0644, 1, 1233041050, 1001, 1001 }, + { "./NEWS", S_IFREG | 0644, 1, 1231975636, 1001, 1001 }, + { "./PROJECTS", S_IFREG | 0644, 1, 1231975636, 1001, 1001 }, + { "./README", S_IFREG | 0644, 1, 1231975636, 1001, 1001 }, + { "./subdir", S_IFDIR | 0755, 3, 1233504586, 1001, 1001 }, + { "./subdir/README", S_IFREG | 0664, 1, 1231975636, 1002, 1001 }, + { "./subdir/config", S_IFREG | 0664, 1, 1232266273, 1003, 1003 }, + { "./subdir2", S_IFDIR | 0755, 3, 1233504586, 1001, 1001 }, + { "./subdir3", S_IFDIR | 0755, 3, 1233504586, 1001, 1001 }, + { "./subdir3/mtree", S_IFREG | 0664, 2, 1232266273, 1003, 1003 }, + { NULL, 0, 0, 0, 0, 0 } +}; + +static const char image [] = { +"#mtree\n" +"\n" +"# .\n" +"/set type=file uid=1001 gid=1001 mode=644\n" +". time=1231975636.0 mode=755 type=dir\n" +" COPYING time=1231975636.0 size=8\n" +" Makefile time=1233041050.0 size=8\n" +" NEWS time=1231975636.0 size=8\n" +" PROJECTS time=1231975636.0 size=8\n" +" README time=1231975636.0 size=8\n" +"\n" +"# ./subdir\n" +"/set mode=664\n" +" subdir time=1233504586.0 mode=755 type=dir\n" +" README time=1231975636.0 uid=1002 size=8\n" +" config time=1232266273.0 gid=1003 uid=1003 size=8\n" +" # ./subdir\n" +" ..\n" +"\n" +"\n" +"# ./subdir2\n" +" subdir2 time=1233504586.0 mode=755 type=dir\n" +" # ./subdir2\n" +" ..\n" +"\n" +"\n" +"# ./subdir3\n" +" subdir3 time=1233504586.0 mode=755 type=dir\n" +" mtree nlink=2 time=1232266273.0 gid=1003 uid=1003 size=8\n" +" # ./subdir3\n" +" ..\n" +"\n" +"..\n\n" +}; + +static const char image_dironly [] = { +"#mtree\n" +"# .\n" +"/set type=dir uid=1001 gid=1001 mode=755\n" +". time=1231975636.0\n" +"# ./subdir\n" +" subdir time=1233504586.0\n" +" # ./subdir\n" +" ..\n" +"# ./subdir2\n" +" subdir2 time=1233504586.0\n" +" # ./subdir2\n" +" ..\n" +"# ./subdir3\n" +" subdir3 time=1233504586.0\n" +" # ./subdir3\n" +" ..\n" +"..\n" +}; + +static void +test_write_format_mtree_sub(int dironly) +{ + struct archive_entry *ae; + struct archive* a; + size_t used; + int i; + + /* Create a mtree format archive. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_mtree_classic(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_format_option(a, NULL, "indent", "1")); + if (dironly) + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_format_option(a, NULL, "dironly", "1")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff)-1, &used)); + + /* Write entries */ + for (i = 0; entries[i].path != NULL; i++) { + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_nlink(ae, entries[i].nlink); + assertEqualInt(entries[i].nlink, archive_entry_nlink(ae)); + archive_entry_set_mtime(ae, entries[i].mtime, 0); + assertEqualInt(entries[i].mtime, archive_entry_mtime(ae)); + archive_entry_set_mode(ae, entries[i].mode); + assertEqualInt(entries[i].mode, archive_entry_mode(ae)); + archive_entry_set_uid(ae, entries[i].uid); + assertEqualInt(entries[i].uid, archive_entry_uid(ae)); + archive_entry_set_gid(ae, entries[i].gid); + assertEqualInt(entries[i].gid, archive_entry_gid(ae)); + archive_entry_copy_pathname(ae, entries[i].path); + if ((entries[i].mode & AE_IFMT) != S_IFDIR) + archive_entry_set_size(ae, 8); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + if ((entries[i].mode & AE_IFMT) != S_IFDIR) + assertEqualIntA(a, 8, + archive_write_data(a, "Hello012", 15)); + archive_entry_free(ae); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + buff[used] = '\0'; + if (dironly) + assertEqualString(buff, image_dironly); + else + assertEqualString(buff, image); + + /* + * Read the data and check it. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + + /* Read entries */ + for (i = 0; entries[i].path != NULL; i++) { + if (dironly && (entries[i].mode & AE_IFMT) != S_IFDIR) + continue; + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(entries[i].mtime, archive_entry_mtime(ae)); + assertEqualInt(entries[i].mode, archive_entry_mode(ae)); + assertEqualInt(entries[i].uid, archive_entry_uid(ae)); + assertEqualInt(entries[i].gid, archive_entry_gid(ae)); + if (i > 0) + assertEqualString(entries[i].path + 2, + archive_entry_pathname(ae)); + else + assertEqualString(entries[i].path, + archive_entry_pathname(ae)); + if ((entries[i].mode & AE_IFMT) != S_IFDIR) + assertEqualInt(8, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_write_format_mtree_classic_indent) +{ + /* Generate classic format. */ + test_write_format_mtree_sub(0); + /* Generate classic format and Write directory only. */ + test_write_format_mtree_sub(1); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_mtree_fflags.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_mtree_fflags.c new file mode 100644 index 0000000..820d86f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_mtree_fflags.c @@ -0,0 +1,135 @@ +/*- + * Copyright (c) 2011 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); +#ifdef HAVE_SYS_STAT_H +#include +#endif + +/* + * Test UFS file flags with/without use-set option. + */ +#if defined(UF_IMMUTABLE) && defined(UF_NODUMP) + +static char buff[4096]; +static struct { + const char *path; + unsigned long fflags; +} entries[] = { + { "./f1", UF_IMMUTABLE | UF_NODUMP }, + { "./f11", UF_IMMUTABLE | UF_NODUMP }, + { "./f2", 0 }, + { "./f3", UF_NODUMP }, + { NULL, 0 } +}; + +static void +test_write_format_mtree_sub(int use_set) +{ + struct archive_entry *ae; + struct archive* a; + size_t used; + int i; + + /* Create a mtree format archive. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_mtree(a)); + if (use_set) + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "use-set,!all,flags,type")); + else + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "!all,flags,type")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff)-1, &used)); + + /* Write entries */ + for (i = 0; entries[i].path != NULL; i++) { + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_fflags(ae, entries[i].fflags, 0); + archive_entry_copy_pathname(ae, entries[i].path); + archive_entry_set_size(ae, 0); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + if (use_set) { + const char *p; + + buff[used] = '\0'; + assert(NULL != (p = strstr(buff, "\n/set "))); + if (p != NULL) { + char *r; + const char *o; + p++; + r = strchr(p, '\n'); + if (r != NULL) + *r = '\0'; + o = "/set type=file flags=uchg,nodump"; + assertEqualString(o, p); + if (r != NULL) + *r = '\n'; + } + } + + /* + * Read the data and check it. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + + /* Read entries */ + for (i = 0; entries[i].path != NULL; i++) { + unsigned long fset, fclr; + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + archive_entry_fflags(ae, &fset, &fclr); + assertEqualInt((int)entries[i].fflags, (int)fset); + assertEqualInt(0, (int)fclr); + assertEqualString(entries[i].path, archive_entry_pathname(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +#endif + +DEFINE_TEST(test_write_format_mtree_fflags) +{ +#if defined(UF_IMMUTABLE) && defined(UF_NODUMP) + /* Default setting */ + test_write_format_mtree_sub(0); + /* Use /set keyword */ + test_write_format_mtree_sub(1); +#else + skipping("This platform does not support UFS file flags"); +#endif +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_mtree_no_separator.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_mtree_no_separator.c new file mode 100644 index 0000000..faf42dd --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_mtree_no_separator.c @@ -0,0 +1,103 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); +#ifdef HAVE_SYS_STAT_H +#include +#endif + +static char buff[4096]; + +DEFINE_TEST(test_write_format_mtree_no_separator) +{ + struct archive_entry *ae; + struct archive* a; + size_t used; + + /* Create a mtree format archive. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_mtree(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff)-1, &used)); + + /* Write "." file. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "."); + archive_entry_set_mode(ae, AE_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Write "noseparator" file. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "noseparator"); + archive_entry_set_size(ae, 0); + archive_entry_set_mode(ae, AE_IFREG | 0644); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Write "./withseparator" file. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "./withseparator"); + archive_entry_set_size(ae, 0); + archive_entry_set_mode(ae, AE_IFREG | 0644); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Read the data and check it. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + + /* Read "." file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + failure("The path should be just \".\""); + assertEqualString(archive_entry_pathname(ae), "."); + assertEqualInt(archive_entry_mode(ae), AE_IFDIR | 0755); + + /* Read "./noseparator" file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + failure("The path should have \"./\" prefix"); + assertEqualString(archive_entry_pathname(ae), "./noseparator"); + assertEqualInt(archive_entry_size(ae), 0); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + + /* Read "./withseparator" file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "./withseparator"); + assertEqualInt(archive_entry_size(ae), 0); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_mtree_quoted_filename.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_mtree_quoted_filename.c new file mode 100644 index 0000000..63e927a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_mtree_quoted_filename.c @@ -0,0 +1,86 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +static char buff[4096]; + +static const char image [] = { +"#mtree\n" +"./a\\040!$\\043&\\075_^z\\177~ mode=644 type=file\n" +}; + + +DEFINE_TEST(test_write_format_mtree_quoted_filename) +{ + struct archive_entry *ae; + struct archive* a; + size_t used; + + /* Create a mtree format archive. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_mtree(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_format_option(a, NULL, "all", NULL)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_format_option(a, NULL, "type", "1")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_format_option(a, NULL, "mode", "1")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff)-1, &used)); + + /* Write entry which has #, = , \ and DEL(0177) in the filename. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mode(ae, AE_IFREG | 0644); + assertEqualInt(AE_IFREG | 0644, archive_entry_mode(ae)); + archive_entry_copy_pathname(ae, "./a !$#&=_^z\177~"); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + buff[used] = '\0'; + failure("#, = and \\ in the filename should be quoted"); + assertEqualString(buff, image); + + /* + * Read the data and check it. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + + /* Read entry */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(AE_IFREG | 0644, archive_entry_mode(ae)); + assertEqualString("./a !$#&=_^z\177~", archive_entry_pathname(ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_pax.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_pax.c new file mode 100644 index 0000000..4538aac --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_pax.c @@ -0,0 +1,255 @@ +/*- + * Copyright (c) 2003-2008 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +static char buff2[64]; + +DEFINE_TEST(test_write_format_pax) +{ + size_t buffsize = 1000000; + char *buff; + struct archive_entry *ae; + struct archive *a; + size_t used; + int i; + char nulls[1024]; + int64_t offset, length; + + buff = malloc(buffsize); /* million bytes of work area */ + assert(buff != NULL); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_pax(a)); + assertA(0 == archive_write_add_filter_none(a)); + assertA(0 == archive_write_open_memory(a, buff, buffsize, &used)); + + /* + * "file" has a bunch of attributes and 8 bytes of data. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_birthtime(ae, 3, 30); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "file"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 8); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); + + /* + * "file2" is similar but has birthtime later than mtime. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_birthtime(ae, 8, 80); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "file2"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 8); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); + + /* + * "file3" is sparse file and has hole size of which is + * 1024000 bytes, and has 8 bytes data after the hole. + * + * Pad the filename to make it larger than the ustar limit. + * It should still read back correctly. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_birthtime(ae, 3, 30); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "file3" + "_123456789_123456789_123456789_123456789_123456789" + "_123456789_123456789_123456789_123456789_123456789" + "_123456789_123456789_123456789_123456789_123456789"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 1024008); + archive_entry_sparse_add_entry(ae, 1024000, 8); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + memset(nulls, 0, sizeof(nulls)); + for (i = 0; i < 1024000; i += 1024) + /* write hole data, which won't be stored into an archive file. */ + assertEqualIntA(a, 1024, archive_write_data(a, nulls, 1024)); + assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); + + /* + * "file4" is similar to "file1" but has a large uid, large gid, + * uname and gname are longer than 32 characters + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_birthtime(ae, 3, 30); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "file4"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 8); + archive_entry_copy_uname(ae, + "long-uname123456789012345678901234567890"); + archive_entry_copy_gname(ae, + "long-gname123456789012345678901234567890"); + archive_entry_set_uid(ae, 536870912); + archive_entry_set_gid(ae, 536870913); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); + + /* + * XXX TODO XXX Archive directory, other file types. + * Archive extended attributes, ACLs, other metadata. + * Verify they get read back correctly. + */ + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + + /* + * + * Now, read the data back. + * + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, 0, archive_read_support_format_all(a)); + assertEqualIntA(a, 0, archive_read_support_filter_all(a)); + assertEqualIntA(a, 0, archive_read_open_memory(a, buff, used)); + + /* + * Read "file" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(20, archive_entry_atime_nsec(ae)); + assertEqualInt(3, archive_entry_birthtime(ae)); + assertEqualInt(30, archive_entry_birthtime_nsec(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(40, archive_entry_ctime_nsec(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualInt(50, archive_entry_mtime_nsec(ae)); + assertEqualString("file", archive_entry_pathname(ae)); + assert((S_IFREG | 0755) == archive_entry_mode(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "12345678", 8); + + /* + * Read "file2" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assert(archive_entry_atime_is_set(ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(20, archive_entry_atime_nsec(ae)); + /* Birthtime > mtime above, so it doesn't get stored at all. */ + assert(!archive_entry_birthtime_is_set(ae)); + assertEqualInt(0, archive_entry_birthtime(ae)); + assertEqualInt(0, archive_entry_birthtime_nsec(ae)); + assert(archive_entry_ctime_is_set(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(40, archive_entry_ctime_nsec(ae)); + assert(archive_entry_mtime_is_set(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualInt(50, archive_entry_mtime_nsec(ae)); + assertEqualString("file2", archive_entry_pathname(ae)); + assert((S_IFREG | 0755) == archive_entry_mode(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "12345678", 8); + + /* + * Read "file3" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(20, archive_entry_atime_nsec(ae)); + assertEqualInt(3, archive_entry_birthtime(ae)); + assertEqualInt(30, archive_entry_birthtime_nsec(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(40, archive_entry_ctime_nsec(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualInt(50, archive_entry_mtime_nsec(ae)); + assertEqualString("file3" + "_123456789_123456789_123456789_123456789_123456789" + "_123456789_123456789_123456789_123456789_123456789" + "_123456789_123456789_123456789_123456789_123456789", + archive_entry_pathname(ae)); + assert((S_IFREG | 0755) == archive_entry_mode(ae)); + assertEqualInt(1024008, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_sparse_reset(ae)); + assertEqualInt(ARCHIVE_OK, + archive_entry_sparse_next(ae, &offset, &length)); + assertEqualInt(1024000, offset); + assertEqualInt(8, length); + for (i = 0; i < 1024000; i += 1024) { + int j; + assertEqualIntA(a, 1024, archive_read_data(a, nulls, 1024)); + for (j = 0; j < 1024; j++) + assertEqualInt(0, nulls[j]); + } + assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "12345678", 8); + + /* + * Read "file4 + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(20, archive_entry_atime_nsec(ae)); + assertEqualInt(3, archive_entry_birthtime(ae)); + assertEqualInt(30, archive_entry_birthtime_nsec(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(40, archive_entry_ctime_nsec(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualInt(50, archive_entry_mtime_nsec(ae)); + assertEqualString("file4", archive_entry_pathname(ae)); + assertEqualString("long-uname123456789012345678901234567890", + archive_entry_uname(ae)); + assertEqualString("long-gname123456789012345678901234567890", + archive_entry_gname(ae)); + assertEqualInt(536870912, archive_entry_uid(ae)); + assertEqualInt(536870913, archive_entry_gid(ae)); + assert((S_IFREG | 0755) == archive_entry_mode(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "12345678", 8); + + /* + * Verify the end of the archive. + */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_raw.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_raw.c new file mode 100644 index 0000000..bd887ff --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_raw.c @@ -0,0 +1,123 @@ +/*- + * Copyright (c) 2013 Marek Kubica + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +static void +test_format(int (*set_format)(struct archive *)) +{ + char filedata[64]; + struct archive_entry *ae; + struct archive *a; + size_t used; + size_t buffsize = 1000000; + char *buff; + const char *err; + + buff = malloc(buffsize); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, (*set_format)(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used)); + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_pathname(ae, "test"); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 9, archive_write_data(a, "12345678", 9)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Read from it. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_raw(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualIntA(a, 9, archive_read_data(a, filedata, 10)); + assertEqualMem(filedata, "12345678", 9); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* Create a new archive */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, (*set_format)(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used)); + + /* write first file: that should succeed */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_pathname(ae, "test"); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 9, archive_write_data(a, "12345678", 9)); + + /* write second file: this should fail */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_pathname(ae, "test2"); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualIntA(a, ARCHIVE_FATAL, archive_write_header(a, ae)); + err = archive_error_string(a); + assertEqualMem(err, "Raw format only supports one entry per archive", 47); + archive_entry_free(ae); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Create a new archive */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, (*set_format)(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used)); + + /* write a directory: this should fail */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "dir"); + archive_entry_set_filetype(ae, AE_IFDIR); + archive_entry_set_size(ae, 512); + assertEqualIntA(a, ARCHIVE_FATAL, archive_write_header(a, ae)); + err = archive_error_string(a); + assertEqualMem(err, "Raw format only supports filetype AE_IFREG", 43); + archive_entry_free(ae); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + free(buff); +} + +DEFINE_TEST(test_write_format_raw) +{ + test_format(archive_write_set_format_raw); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_raw_b64.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_raw_b64.c new file mode 100644 index 0000000..f8f6728 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_raw_b64.c @@ -0,0 +1,77 @@ +/*- + * Copyright (c) 2013 Marek Kubica + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +static void +test_format(int (*set_format)(struct archive *)) +{ + char filedata[64]; + struct archive_entry *ae; + struct archive *a; + size_t used; + size_t buffsize = 1000000; + char *buff; + + buff = malloc(buffsize); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, (*set_format)(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_b64encode(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used)); + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_pathname(ae, "test"); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 9, archive_write_data(a, "12345678", 9)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Read from it. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_raw(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualIntA(a, 37, archive_read_data(a, filedata, 64)); + assertEqualMem(filedata, "begin-base64 644 -\nMTIzNDU2NzgA\n====\n", 37); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + free(buff); +} + +DEFINE_TEST(test_write_format_raw_b64) +{ + test_format(archive_write_set_format_raw); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_shar_empty.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_shar_empty.c new file mode 100644 index 0000000..13794b0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_shar_empty.c @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/lib/libarchive/test/test_write_format_shar_empty.c,v 1.3 2008/09/01 05:38:33 kientzle Exp $"); + +/* + * Check that an "empty" shar archive is correctly created as an empty file. + */ + +DEFINE_TEST(test_write_format_shar_empty) +{ + struct archive *a; + char buff[2048]; + size_t used; + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_shar(a)); + assertA(0 == archive_write_add_filter_none(a)); + /* 1-byte block size ensures we see only the required bytes. */ + /* We're not testing the padding here. */ + assertA(0 == archive_write_set_bytes_per_block(a, 1)); + assertA(0 == archive_write_set_bytes_in_last_block(a, 1)); + assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used)); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + failure("Empty shar archive should be exactly 0 bytes, was %zu.", used); + assert(used == 0); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_tar.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_tar.c new file mode 100644 index 0000000..a5ccdc0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_tar.c @@ -0,0 +1,119 @@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_format_tar.c 189308 2009-03-03 17:02:51Z kientzle $"); + +static char buff[1000000]; +static char buff2[64]; + +DEFINE_TEST(test_write_format_tar) +{ + struct archive_entry *ae; + struct archive *a; + char *p; + size_t used; + size_t blocksize; + + /* Repeat the following for a variety of odd blocksizes. */ + for (blocksize = 1; blocksize < 100000; blocksize += blocksize + 3) { + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, (int)blocksize)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_in_last_block(a, (int)blocksize)); + assertEqualInt(blocksize, + archive_write_get_bytes_in_last_block(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + assertEqualInt(blocksize, + archive_write_get_bytes_in_last_block(a)); + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(10, archive_entry_mtime_nsec(ae)); + p = strdup("file"); + archive_entry_copy_pathname(ae, p); + strcpy(p, "XXXX"); + free(p); + assertEqualString("file", archive_entry_pathname(ae)); + archive_entry_set_mode(ae, S_IFREG | 0755); + assertEqualInt(S_IFREG | 0755, archive_entry_mode(ae)); + archive_entry_set_size(ae, 8); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(8, archive_write_data(a, "12345678", 9)); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* This calculation gives "the smallest multiple of + * the block size that is at least 2048 bytes". */ + failure("blocksize=%zu", blocksize); + assertEqualInt(((2048 - 1)/blocksize+1)*blocksize, used); + + /* + * Now, read the data back. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used)); + + assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae)); + + assertEqualInt(1, archive_entry_mtime(ae)); + /* Not the same as above: ustar doesn't store hi-res times. */ + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualInt(8, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "12345678", 8); + + /* Verify the end of the archive. */ + assertEqualIntA(a, ARCHIVE_EOF, + archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + } +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_tar_empty.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_tar_empty.c new file mode 100644 index 0000000..7ccd435 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_tar_empty.c @@ -0,0 +1,74 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_format_tar_empty.c 189308 2009-03-03 17:02:51Z kientzle $"); + +/* + * Check that an "empty" tar archive is correctly created. + */ + +DEFINE_TEST(test_write_format_tar_empty) +{ + struct archive *a; + char buff[2048]; + size_t used; + unsigned int i; + + /* USTAR format: Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_ustar(a)); + assertA(0 == archive_write_add_filter_none(a)); + assertA(0 == archive_write_set_bytes_per_block(a, 512)); + assertA(0 == archive_write_set_bytes_in_last_block(a, 512)); + assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used)); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert(used == 1024); + for (i = 0; i < used; i++) { + failure("Empty tar archive should be all nulls."); + assert(buff[i] == 0); + } + + /* PAX format: Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_pax(a)); + assertA(0 == archive_write_add_filter_none(a)); + assertA(0 == archive_write_set_bytes_per_block(a, 512)); + assertA(0 == archive_write_set_bytes_in_last_block(a, 512)); + assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used)); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assertEqualInt((int)used, 1024); + for (i = 0; i < used; i++) { + failure("Empty tar archive should be all nulls."); + assert(buff[i] == 0); + } +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_tar_sparse.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_tar_sparse.c new file mode 100644 index 0000000..54ac009 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_tar_sparse.c @@ -0,0 +1,305 @@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +static char buff[1000000]; + +static void +test_1(void) +{ + struct archive_entry *ae; + struct archive *a; + size_t used; + size_t blocksize; + int64_t offset, length; + char *buff2; + size_t buff2_size = 0x13000; + char buff3[1024]; + long i; + + assert((buff2 = malloc(buff2_size)) != NULL); + /* Repeat the following for a variety of odd blocksizes. */ + for (blocksize = 1; blocksize < 100000; blocksize += blocksize + 3) { + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_format_pax(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, (int)blocksize)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_in_last_block(a, (int)blocksize)); + assertEqualInt(blocksize, + archive_write_get_bytes_in_last_block(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + assertEqualInt(blocksize, + archive_write_get_bytes_in_last_block(a)); + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(10, archive_entry_mtime_nsec(ae)); + archive_entry_copy_pathname(ae, "file"); + assertEqualString("file", archive_entry_pathname(ae)); + archive_entry_set_mode(ae, S_IFREG | 0755); + assertEqualInt(S_IFREG | 0755, archive_entry_mode(ae)); + archive_entry_set_size(ae, 0x81000); + archive_entry_sparse_add_entry(ae, 0x10000, 0x1000); + archive_entry_sparse_add_entry(ae, 0x80000, 0x1000); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + memset(buff2, 'a', buff2_size); + for (i = 0; i < 0x81000;) { + size_t ws = buff2_size; + if (i + ws > 0x81000) + ws = 0x81000 - i; + assertEqualInt(ws, + archive_write_data(a, buff2, ws)); + i += (long)ws; + } + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* This calculation gives "the smallest multiple of + * the block size that is at least 11264 bytes". */ + failure("blocksize=%zu", blocksize); + assertEqualInt(((11264 - 1)/blocksize+1)*blocksize, used); + + /* + * Now, read the data back. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used)); + + assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae)); + + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(10, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); + assertEqualInt(0x81000, archive_entry_size(ae)); + /* Verify sparse information. */ + assertEqualInt(2, archive_entry_sparse_reset(ae)); + assertEqualInt(0, + archive_entry_sparse_next(ae, &offset, &length)); + assertEqualInt(0x10000, offset); + assertEqualInt(0x1000, length); + assertEqualInt(0, + archive_entry_sparse_next(ae, &offset, &length)); + assertEqualInt(0x80000, offset); + assertEqualInt(0x1000, length); + /* Verify file contents. */ + memset(buff3, 0, sizeof(buff3)); + for (i = 0; i < 0x10000; i += 1024) { + assertEqualInt(1024, archive_read_data(a, buff2, 1024)); + failure("Read data(0x%lx - 0x%lx) should be all zero", + i, i + 1024); + assertEqualMem(buff2, buff3, 1024); + } + memset(buff3, 'a', sizeof(buff3)); + for (i = 0x10000; i < 0x11000; i += 1024) { + assertEqualInt(1024, archive_read_data(a, buff2, 1024)); + failure("Read data(0x%lx - 0x%lx) should be all 'a'", + i, i + 1024); + assertEqualMem(buff2, buff3, 1024); + } + memset(buff3, 0, sizeof(buff3)); + for (i = 0x11000; i < 0x80000; i += 1024) { + assertEqualInt(1024, archive_read_data(a, buff2, 1024)); + failure("Read data(0x%lx - 0x%lx) should be all zero", + i, i + 1024); + assertEqualMem(buff2, buff3, 1024); + } + memset(buff3, 'a', sizeof(buff3)); + for (i = 0x80000; i < 0x81000; i += 1024) { + assertEqualInt(1024, archive_read_data(a, buff2, 1024)); + failure("Read data(0x%lx - 0x%lx) should be all 'a'", + i, i + 1024); + assertEqualMem(buff2, buff3, 1024); + } + + /* Verify the end of the archive. */ + assertEqualIntA(a, ARCHIVE_EOF, + archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + } + free(buff2); +} + +/* + * Test for the case the full bytes of sparse file data is not written. + */ +static void +test_2(void) +{ + struct archive_entry *ae; + struct archive *a; + size_t used; + size_t blocksize = 20 * 512; + int64_t offset, length; + char *buff2; + size_t buff2_size = 0x11000; + char buff3[1024]; + long i; + + assert((buff2 = malloc(buff2_size)) != NULL); + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_format_pax(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, (int)blocksize)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_in_last_block(a, (int)blocksize)); + assertEqualInt(blocksize, + archive_write_get_bytes_in_last_block(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + assertEqualInt(blocksize, + archive_write_get_bytes_in_last_block(a)); + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(10, archive_entry_mtime_nsec(ae)); + archive_entry_copy_pathname(ae, "file"); + assertEqualString("file", archive_entry_pathname(ae)); + archive_entry_set_mode(ae, S_IFREG | 0755); + assertEqualInt(S_IFREG | 0755, archive_entry_mode(ae)); + archive_entry_set_size(ae, 0x81000); + archive_entry_sparse_add_entry(ae, 0x10000, 0x1000); + archive_entry_sparse_add_entry(ae, 0x80000, 0x1000); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + memset(buff2, 'a', buff2_size); + /* Write bytes less than it should be. */ + assertEqualInt(buff2_size, archive_write_data(a, buff2, buff2_size)); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* This calculation gives "the smallest multiple of + * the block size that is at least 11264 bytes". */ + failure("blocksize=%zu", blocksize); + assertEqualInt(((11264 - 1)/blocksize+1)*blocksize, used); + + /* + * Now, read the data back. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(10, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); + assertEqualInt(0x81000, archive_entry_size(ae)); + /* Verify sparse information. */ + assertEqualInt(2, archive_entry_sparse_reset(ae)); + assertEqualInt(0, archive_entry_sparse_next(ae, &offset, &length)); + assertEqualInt(0x10000, offset); + assertEqualInt(0x1000, length); + assertEqualInt(0, archive_entry_sparse_next(ae, &offset, &length)); + assertEqualInt(0x80000, offset); + assertEqualInt(0x1000, length); + /* Verify file contents. */ + memset(buff3, 0, sizeof(buff3)); + for (i = 0; i < 0x10000; i += 1024) { + assertEqualInt(1024, archive_read_data(a, buff2, 1024)); + failure("Read data(0x%lx - 0x%lx) should be all zero", + i, i + 1024); + assertEqualMem(buff2, buff3, 1024); + } + memset(buff3, 'a', sizeof(buff3)); + for (i = 0x10000; i < 0x11000; i += 1024) { + assertEqualInt(1024, archive_read_data(a, buff2, 1024)); + failure("Read data(0x%lx - 0x%lx) should be all 'a'", + i, i + 1024); + assertEqualMem(buff2, buff3, 1024); + } + memset(buff3, 0, sizeof(buff3)); + for (i = 0x11000; i < 0x80000; i += 1024) { + assertEqualInt(1024, archive_read_data(a, buff2, 1024)); + failure("Read data(0x%lx - 0x%lx) should be all zero", + i, i + 1024); + assertEqualMem(buff2, buff3, 1024); + } + memset(buff3, 0, sizeof(buff3)); + for (i = 0x80000; i < 0x81000; i += 1024) { + assertEqualInt(1024, archive_read_data(a, buff2, 1024)); + failure("Read data(0x%lx - 0x%lx) should be all 'a'", + i, i + 1024); + assertEqualMem(buff2, buff3, 1024); + } + + /* Verify the end of the archive. */ + assertEqualIntA(a, ARCHIVE_EOF, + archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + free(buff2); +} + +DEFINE_TEST(test_write_format_tar_sparse) +{ + /* Test1: archiving sparse files. */ + test_1(); + /* Test2: incompletely archiving sparse files. */ + test_2(); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_tar_ustar.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_tar_ustar.c new file mode 100644 index 0000000..7bc38f7 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_tar_ustar.c @@ -0,0 +1,354 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_format_tar_ustar.c 201247 2009-12-30 05:59:21Z kientzle $"); + +static int +is_null(const char *p, size_t l) +{ + while (l > 0) { + if (*p != '\0') + return (0); + --l; + ++p; + } + return (1); +} + +/* Verify the contents, then erase them to NUL bytes. */ +/* Tar requires all "unused" bytes be set to NUL; this allows us + * to easily verify that by invoking is_null() over the entire header + * after verifying each field. */ +#define myAssertEqualMem(a,b,s) assertEqualMem(a, b, s); memset(a, 0, s) + +/* + * Detailed verification that 'ustar' archives are written with + * the correct format. + */ +DEFINE_TEST(test_write_format_tar_ustar) +{ + struct archive *a; + struct archive_entry *entry; + char *buff, *e; + size_t buffsize = 100000; + size_t used; + int i; + char f99[100]; + char f100[101]; + char f256[257]; + + for (i = 0; i < 99; ++i) + f99[i] = 'a' + i % 26; + f99[99] = '\0'; + + for (i = 0; i < 100; ++i) + f100[i] = 'A' + i % 26; + f100[100] = '\0'; + + for (i = 0; i < 256; ++i) + f256[i] = 'A' + i % 26; + f256[155] = '/'; + f256[256] = '\0'; + + buff = malloc(buffsize); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + + /* + * Add various files to it. + * TODO: Extend this to cover more filetypes. + */ + + /* "file" with 10 bytes of content */ + assert((entry = archive_entry_new()) != NULL); + archive_entry_set_mtime(entry, 1, 10); + archive_entry_set_pathname(entry, "file"); + archive_entry_set_mode(entry, S_IFREG | 0664); + archive_entry_set_size(entry, 10); + archive_entry_set_uid(entry, 80); + archive_entry_set_gid(entry, 90); + archive_entry_set_dev(entry, 12); + archive_entry_set_ino(entry, 89); + archive_entry_set_nlink(entry, 2); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualIntA(a, 10, archive_write_data(a, "1234567890", 10)); + + /* Hardlink to "file" with 10 bytes of content */ + assert((entry = archive_entry_new()) != NULL); + archive_entry_set_mtime(entry, 1, 10); + archive_entry_set_pathname(entry, "linkfile"); + archive_entry_set_mode(entry, S_IFREG | 0664); + /* TODO: Put this back and fix the bug. */ + /* archive_entry_set_size(entry, 10); */ + archive_entry_set_uid(entry, 80); + archive_entry_set_gid(entry, 90); + archive_entry_set_dev(entry, 12); + archive_entry_set_ino(entry, 89); + archive_entry_set_nlink(entry, 2); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_header(a, entry)); + archive_entry_free(entry); + /* Write of data to dir should fail == zero bytes get written. */ + assertEqualIntA(a, 0, archive_write_data(a, "1234567890", 10)); + + /* "dir" */ + assert((entry = archive_entry_new()) != NULL); + archive_entry_set_mtime(entry, 2, 20); + archive_entry_set_pathname(entry, "dir"); + archive_entry_set_mode(entry, S_IFDIR | 0775); + archive_entry_set_size(entry, 10); + archive_entry_set_nlink(entry, 2); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_header(a, entry)); + archive_entry_free(entry); + /* Write of data to dir should fail == zero bytes get written. */ + assertEqualIntA(a, 0, archive_write_data(a, "1234567890", 10)); + + /* "symlink" pointing to "file" */ + assert((entry = archive_entry_new()) != NULL); + archive_entry_set_mtime(entry, 3, 30); + archive_entry_set_pathname(entry, "symlink"); + archive_entry_set_mode(entry, 0664); + archive_entry_set_filetype(entry, AE_IFLNK); + archive_entry_set_symlink(entry,"file"); + archive_entry_set_size(entry, 0); + archive_entry_set_uid(entry, 88); + archive_entry_set_gid(entry, 98); + archive_entry_set_dev(entry, 12); + archive_entry_set_ino(entry, 90); + archive_entry_set_nlink(entry, 1); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_header(a, entry)); + archive_entry_free(entry); + /* Write of data to symlink should fail == zero bytes get written. */ + assertEqualIntA(a, 0, archive_write_data(a, "1234567890", 10)); + + /* file with 99-char filename. */ + assert((entry = archive_entry_new()) != NULL); + archive_entry_set_mtime(entry, 1, 10); + archive_entry_set_pathname(entry, f99); + archive_entry_set_mode(entry, S_IFREG | 0664); + archive_entry_set_size(entry, 0); + archive_entry_set_uid(entry, 82); + archive_entry_set_gid(entry, 93); + archive_entry_set_dev(entry, 102); + archive_entry_set_ino(entry, 7); + archive_entry_set_nlink(entry, 1); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_header(a, entry)); + archive_entry_free(entry); + + /* file with 100-char filename. */ + assert((entry = archive_entry_new()) != NULL); + archive_entry_set_mtime(entry, 1, 10); + archive_entry_set_pathname(entry, f100); + archive_entry_set_mode(entry, S_IFREG | 0664); + archive_entry_set_size(entry, 0); + archive_entry_set_uid(entry, 82); + archive_entry_set_gid(entry, 93); + archive_entry_set_dev(entry, 102); + archive_entry_set_ino(entry, 7); + archive_entry_set_nlink(entry, 1); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_header(a, entry)); + archive_entry_free(entry); + + /* file with 256-char filename. */ + assert((entry = archive_entry_new()) != NULL); + archive_entry_set_mtime(entry, 1, 10); + archive_entry_set_pathname(entry, f256); + archive_entry_set_mode(entry, S_IFREG | 0664); + archive_entry_set_size(entry, 0); + archive_entry_set_uid(entry, 82); + archive_entry_set_gid(entry, 93); + archive_entry_set_dev(entry, 102); + archive_entry_set_ino(entry, 7); + archive_entry_set_nlink(entry, 1); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_header(a, entry)); + archive_entry_free(entry); + + /* Close out the archive. */ + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Verify the archive format. + */ + e = buff; + + /* "file" */ + myAssertEqualMem(e + 0, "file", 5); /* Filename */ + myAssertEqualMem(e + 100, "000664 ", 8); /* mode */ + myAssertEqualMem(e + 108, "000120 ", 8); /* uid */ + myAssertEqualMem(e + 116, "000132 ", 8); /* gid */ + myAssertEqualMem(e + 124, "00000000012 ", 12); /* size */ + myAssertEqualMem(e + 136, "00000000001 ", 12); /* mtime */ + myAssertEqualMem(e + 148, "010034\0 ", 8); /* checksum */ + myAssertEqualMem(e + 156, "0", 1); /* linkflag */ + myAssertEqualMem(e + 157, "", 1); /* linkname */ + myAssertEqualMem(e + 257, "ustar\000000", 8); /* signature/version */ + myAssertEqualMem(e + 265, "", 1); /* uname */ + myAssertEqualMem(e + 297, "", 1); /* gname */ + myAssertEqualMem(e + 329, "000000 ", 8); /* devmajor */ + myAssertEqualMem(e + 337, "000000 ", 8); /* devminor */ + myAssertEqualMem(e + 345, "", 1); /* prefix */ + assert(is_null(e + 0, 512)); + myAssertEqualMem(e + 512, "1234567890", 10); + assert(is_null(e + 512, 512)); + e += 1024; + + /* hardlink to "file" */ + myAssertEqualMem(e + 0, "linkfile", 9); /* Filename */ + myAssertEqualMem(e + 100, "000664 ", 8); /* mode */ + myAssertEqualMem(e + 108, "000120 ", 8); /* uid */ + myAssertEqualMem(e + 116, "000132 ", 8); /* gid */ + myAssertEqualMem(e + 124, "00000000000 ", 12); /* size */ + myAssertEqualMem(e + 136, "00000000001 ", 12); /* mtime */ + myAssertEqualMem(e + 148, "010707\0 ", 8); /* checksum */ + myAssertEqualMem(e + 156, "0", 1); /* linkflag */ + myAssertEqualMem(e + 157, "", 1); /* linkname */ + myAssertEqualMem(e + 257, "ustar\000000", 8); /* signature/version */ + myAssertEqualMem(e + 265, "", 1); /* uname */ + myAssertEqualMem(e + 297, "", 1); /* gname */ + myAssertEqualMem(e + 329, "000000 ", 8); /* devmajor */ + myAssertEqualMem(e + 337, "000000 ", 8); /* devminor */ + myAssertEqualMem(e + 345, "", 1); /* prefix */ + assert(is_null(e + 0, 512)); + e += 512; + + /* "dir" */ + myAssertEqualMem(e + 0, "dir/", 4); /* Filename */ + myAssertEqualMem(e + 100, "000775 ", 8); /* mode */ + myAssertEqualMem(e + 108, "000000 ", 8); /* uid */ + myAssertEqualMem(e + 116, "000000 ", 8); /* gid */ + myAssertEqualMem(e + 124, "00000000000 ", 12); /* size */ + myAssertEqualMem(e + 136, "00000000002 ", 12); /* mtime */ + myAssertEqualMem(e + 148, "007747\0 ", 8); /* checksum */ + myAssertEqualMem(e + 156, "5", 1); /* typeflag */ + myAssertEqualMem(e + 157, "", 1); /* linkname */ + myAssertEqualMem(e + 257, "ustar\000000", 8); /* signature/version */ + myAssertEqualMem(e + 265, "", 1); /* uname */ + myAssertEqualMem(e + 297, "", 1); /* gname */ + myAssertEqualMem(e + 329, "000000 ", 8); /* devmajor */ + myAssertEqualMem(e + 337, "000000 ", 8); /* devminor */ + myAssertEqualMem(e + 345, "", 1); /* prefix */ + assert(is_null(e + 0, 512)); + e += 512; + + /* "symlink" pointing to "file" */ + myAssertEqualMem(e + 0, "symlink", 8); /* Filename */ + myAssertEqualMem(e + 100, "000664 ", 8); /* mode */ + myAssertEqualMem(e + 108, "000130 ", 8); /* uid */ + myAssertEqualMem(e + 116, "000142 ", 8); /* gid */ + myAssertEqualMem(e + 124, "00000000000 ", 12); /* size */ + myAssertEqualMem(e + 136, "00000000003 ", 12); /* mtime */ + myAssertEqualMem(e + 148, "011446\0 ", 8); /* checksum */ + myAssertEqualMem(e + 156, "2", 1); /* linkflag */ + myAssertEqualMem(e + 157, "file", 5); /* linkname */ + myAssertEqualMem(e + 257, "ustar\000000", 8); /* signature/version */ + myAssertEqualMem(e + 265, "", 1); /* uname */ + myAssertEqualMem(e + 297, "", 1); /* gname */ + myAssertEqualMem(e + 329, "000000 ", 8); /* devmajor */ + myAssertEqualMem(e + 337, "000000 ", 8); /* devminor */ + myAssertEqualMem(e + 345, "", 1); /* prefix */ + assert(is_null(e + 0, 512)); + e += 512; + + /* File with 99-char filename */ + myAssertEqualMem(e + 0, f99, 100); /* Filename */ + myAssertEqualMem(e + 100, "000664 ", 8); /* mode */ + myAssertEqualMem(e + 108, "000122 ", 8); /* uid */ + myAssertEqualMem(e + 116, "000135 ", 8); /* gid */ + myAssertEqualMem(e + 124, "00000000000 ", 12); /* size */ + myAssertEqualMem(e + 136, "00000000001 ", 12); /* mtime */ + myAssertEqualMem(e + 148, "034242\0 ", 8); /* checksum */ + myAssertEqualMem(e + 156, "0", 1); /* linkflag */ + myAssertEqualMem(e + 157, "", 1); /* linkname */ + myAssertEqualMem(e + 257, "ustar\000000", 8); /* signature/version */ + myAssertEqualMem(e + 265, "", 1); /* uname */ + myAssertEqualMem(e + 297, "", 1); /* gname */ + myAssertEqualMem(e + 329, "000000 ", 8); /* devmajor */ + myAssertEqualMem(e + 337, "000000 ", 8); /* devminor */ + myAssertEqualMem(e + 345, "", 1); /* prefix */ + assert(is_null(e + 0, 512)); + e += 512; + + /* File with 100-char filename */ + myAssertEqualMem(e + 0, f100, 100); /* Filename */ + myAssertEqualMem(e + 100, "000664 ", 8); /* mode */ + myAssertEqualMem(e + 108, "000122 ", 8); /* uid */ + myAssertEqualMem(e + 116, "000135 ", 8); /* gid */ + myAssertEqualMem(e + 124, "00000000000 ", 12); /* size */ + myAssertEqualMem(e + 136, "00000000001 ", 12); /* mtime */ + myAssertEqualMem(e + 148, "026230\0 ", 8); /* checksum */ + myAssertEqualMem(e + 156, "0", 1); /* linkflag */ + myAssertEqualMem(e + 157, "", 1); /* linkname */ + myAssertEqualMem(e + 257, "ustar\000000", 8); /* signature/version */ + myAssertEqualMem(e + 265, "", 1); /* uname */ + myAssertEqualMem(e + 297, "", 1); /* gname */ + myAssertEqualMem(e + 329, "000000 ", 8); /* devmajor */ + myAssertEqualMem(e + 337, "000000 ", 8); /* devminor */ + myAssertEqualMem(e + 345, "", 1); /* prefix */ + assert(is_null(e + 0, 512)); + e += 512; + + /* File with 256-char filename */ + myAssertEqualMem(e + 0, f256 + 156, 100); /* Filename */ + myAssertEqualMem(e + 100, "000664 ", 8); /* mode */ + myAssertEqualMem(e + 108, "000122 ", 8); /* uid */ + myAssertEqualMem(e + 116, "000135 ", 8); /* gid */ + myAssertEqualMem(e + 124, "00000000000 ", 12); /* size */ + myAssertEqualMem(e + 136, "00000000001 ", 12); /* mtime */ + myAssertEqualMem(e + 148, "055570\0 ", 8); /* checksum */ + myAssertEqualMem(e + 156, "0", 1); /* linkflag */ + myAssertEqualMem(e + 157, "", 1); /* linkname */ + myAssertEqualMem(e + 257, "ustar\000000", 8); /* signature/version */ + myAssertEqualMem(e + 265, "", 1); /* uname */ + myAssertEqualMem(e + 297, "", 1); /* gname */ + myAssertEqualMem(e + 329, "000000 ", 8); /* devmajor */ + myAssertEqualMem(e + 337, "000000 ", 8); /* devminor */ + myAssertEqualMem(e + 345, f256, 155); /* prefix */ + assert(is_null(e + 0, 512)); + e += 512; + + /* TODO: Verify other types of entries. */ + + /* Last entry is end-of-archive marker. */ + assert(is_null(e, 1024)); + e += 1024; + + assertEqualInt((int)used, e - buff); + + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_tar_v7tar.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_tar_v7tar.c new file mode 100644 index 0000000..1690995 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_tar_v7tar.c @@ -0,0 +1,259 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +static int +is_null(const char *p, size_t l) +{ + while (l > 0) { + if (*p != '\0') + return (0); + --l; + ++p; + } + return (1); +} + +/* Verify the contents, then erase them to NUL bytes. */ +/* Tar requires all "unused" bytes be set to NUL; this allows us + * to easily verify that by invoking is_null() over the entire header + * after verifying each field. */ +#define myAssertEqualMem(a,b,s) assertEqualMem(a, b, s); memset(a, 0, s) + +/* + * Detailed verification that 'v7tar' archives are written with + * the correct format. + */ +DEFINE_TEST(test_write_format_tar_v7tar) +{ + struct archive *a; + struct archive_entry *entry; + char *buff, *e; + size_t buffsize = 100000; + size_t used; + int i; + char f99[100]; + char f100[101]; + + for (i = 0; i < 99; ++i) + f99[i] = 'a' + i % 26; + f99[99] = '\0'; + + for (i = 0; i < 100; ++i) + f100[i] = 'A' + i % 26; + f100[100] = '\0'; + + buff = malloc(buffsize); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_format_v7tar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + + /* + * Add various files to it. + * TODO: Extend this to cover more filetypes. + */ + + /* "file" with 10 bytes of content */ + assert((entry = archive_entry_new()) != NULL); + archive_entry_set_mtime(entry, 1, 10); + archive_entry_set_pathname(entry, "file"); + archive_entry_set_mode(entry, S_IFREG | 0664); + archive_entry_set_size(entry, 10); + archive_entry_set_uid(entry, 80); + archive_entry_set_gid(entry, 90); + archive_entry_set_dev(entry, 12); + archive_entry_set_ino(entry, 89); + archive_entry_set_nlink(entry, 2); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualIntA(a, 10, archive_write_data(a, "1234567890", 10)); + + /* Hardlink to "file" with 10 bytes of content */ + assert((entry = archive_entry_new()) != NULL); + archive_entry_set_mtime(entry, 1, 10); + archive_entry_set_pathname(entry, "linkfile"); + archive_entry_set_hardlink(entry, "file"); + archive_entry_set_mode(entry, S_IFREG | 0664); + archive_entry_set_size(entry, 10); + archive_entry_set_uid(entry, 80); + archive_entry_set_gid(entry, 90); + archive_entry_set_dev(entry, 12); + archive_entry_set_ino(entry, 89); + archive_entry_set_nlink(entry, 2); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + /* Write of data to dir should fail == zero bytes get written. */ + assertEqualIntA(a, 0, archive_write_data(a, "1234567890", 10)); + + /* "dir" */ + assert((entry = archive_entry_new()) != NULL); + archive_entry_set_mtime(entry, 2, 20); + archive_entry_set_pathname(entry, "dir"); + archive_entry_set_mode(entry, S_IFDIR | 0775); + archive_entry_set_size(entry, 10); + archive_entry_set_nlink(entry, 2); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + /* Write of data to dir should fail == zero bytes get written. */ + assertEqualIntA(a, 0, archive_write_data(a, "1234567890", 10)); + + /* "symlink" pointing to "file" */ + assert((entry = archive_entry_new()) != NULL); + archive_entry_set_mtime(entry, 3, 30); + archive_entry_set_pathname(entry, "symlink"); + archive_entry_set_mode(entry, 0664); + archive_entry_set_filetype(entry, AE_IFLNK); + archive_entry_set_symlink(entry,"file"); + archive_entry_set_size(entry, 0); + archive_entry_set_uid(entry, 88); + archive_entry_set_gid(entry, 98); + archive_entry_set_dev(entry, 12); + archive_entry_set_ino(entry, 90); + archive_entry_set_nlink(entry, 1); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + + /* file with 99-char filename. */ + assert((entry = archive_entry_new()) != NULL); + archive_entry_set_mtime(entry, 1, 10); + archive_entry_set_pathname(entry, f99); + archive_entry_set_mode(entry, S_IFREG | 0664); + archive_entry_set_size(entry, 0); + archive_entry_set_uid(entry, 82); + archive_entry_set_gid(entry, 93); + archive_entry_set_dev(entry, 102); + archive_entry_set_ino(entry, 7); + archive_entry_set_nlink(entry, 1); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + + /* file with 100-char filename. */ + assert((entry = archive_entry_new()) != NULL); + archive_entry_set_mtime(entry, 1, 10); + archive_entry_set_pathname(entry, f100); + archive_entry_set_mode(entry, S_IFREG | 0664); + archive_entry_set_size(entry, 0); + archive_entry_set_uid(entry, 82); + archive_entry_set_gid(entry, 93); + archive_entry_set_dev(entry, 102); + archive_entry_set_ino(entry, 7); + archive_entry_set_nlink(entry, 1); + failure("100-char filename should be rejected"); + assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, entry)); + archive_entry_free(entry); + + /* Close out the archive. */ + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Verify the archive format. + */ + e = buff; + + /* "file" */ + myAssertEqualMem(e + 0, "file", 5); /* Filename */ + myAssertEqualMem(e + 100, "000664 ", 8); /* mode */ + myAssertEqualMem(e + 108, "000120 ", 8); /* uid */ + myAssertEqualMem(e + 116, "000132 ", 8); /* gid */ + myAssertEqualMem(e + 124, "00000000012 ", 12); /* size */ + myAssertEqualMem(e + 136, "00000000001 ", 12); /* mtime */ + myAssertEqualMem(e + 148, "005335\0 ", 8); /* checksum */ + myAssertEqualMem(e + 156, "", 1); /* linkflag */ + myAssertEqualMem(e + 157, "", 1); /* linkname */ + assert(is_null(e + 0, 512)); + myAssertEqualMem(e + 512, "1234567890", 10); + assert(is_null(e + 512, 512)); + e += 1024; + + /* hardlink to "file" */ + myAssertEqualMem(e + 0, "linkfile", 9); /* Filename */ + myAssertEqualMem(e + 100, "000664 ", 8); /* mode */ + myAssertEqualMem(e + 108, "000120 ", 8); /* uid */ + myAssertEqualMem(e + 116, "000132 ", 8); /* gid */ + myAssertEqualMem(e + 124, "00000000000 ", 12); /* size */ + myAssertEqualMem(e + 136, "00000000001 ", 12); /* mtime */ + myAssertEqualMem(e + 148, "007131\0 ", 8); /* checksum */ + myAssertEqualMem(e + 156, "1", 1); /* linkflag */ + myAssertEqualMem(e + 157, "file", 5); /* linkname */ + assert(is_null(e + 0, 512)); + e += 512; + + /* "dir" */ + myAssertEqualMem(e + 0, "dir/", 4); /* Filename */ + myAssertEqualMem(e + 100, "000775 ", 8); /* mode */ + myAssertEqualMem(e + 108, "000000 ", 8); /* uid */ + myAssertEqualMem(e + 116, "000000 ", 8); /* gid */ + myAssertEqualMem(e + 124, "00000000000 ", 12); /* size */ + myAssertEqualMem(e + 136, "00000000002 ", 12); /* mtime */ + myAssertEqualMem(e + 148, "005243\0 ", 8); /* checksum */ + myAssertEqualMem(e + 156, "", 1); /* typeflag */ + myAssertEqualMem(e + 157, "", 1); /* linkname */ + assert(is_null(e + 0, 512)); + e += 512; + + /* "symlink" pointing to "file" */ + myAssertEqualMem(e + 0, "symlink", 8); /* Filename */ + myAssertEqualMem(e + 100, "000664 ", 8); /* mode */ + myAssertEqualMem(e + 108, "000130 ", 8); /* uid */ + myAssertEqualMem(e + 116, "000142 ", 8); /* gid */ + myAssertEqualMem(e + 124, "00000000000 ", 12); /* size */ + myAssertEqualMem(e + 136, "00000000003 ", 12); /* mtime */ + myAssertEqualMem(e + 148, "007027\0 ", 8); /* checksum */ + myAssertEqualMem(e + 156, "2", 1); /* linkflag */ + myAssertEqualMem(e + 157, "file", 5); /* linkname */ + assert(is_null(e + 0, 512)); + e += 512; + + /* File with 99-char filename */ + myAssertEqualMem(e + 0, f99, 100); /* Filename */ + myAssertEqualMem(e + 100, "000664 ", 8); /* mode */ + myAssertEqualMem(e + 108, "000122 ", 8); /* uid */ + myAssertEqualMem(e + 116, "000135 ", 8); /* gid */ + myAssertEqualMem(e + 124, "00000000000 ", 12); /* size */ + myAssertEqualMem(e + 136, "00000000001 ", 12); /* mtime */ + myAssertEqualMem(e + 148, "031543\0 ", 8); /* checksum */ + myAssertEqualMem(e + 156, "", 1); /* linkflag */ + myAssertEqualMem(e + 157, "", 1); /* linkname */ + assert(is_null(e + 0, 512)); + e += 512; + + /* TODO: Verify other types of entries. */ + + /* Last entry is end-of-archive marker. */ + assert(is_null(e, 1024)); + e += 1024; + + assertEqualInt((int)used, e - buff); + + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_warc.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_warc.c new file mode 100644 index 0000000..60d1898 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_warc.c @@ -0,0 +1,132 @@ +/*- + * Copyright (C) 2014 Sebastian Freundt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_write_format_warc) +{ + char filedata[64]; + struct archive *a; + struct archive_entry *ae; + const size_t bsiz = 2048U; + char *buff; + size_t used; + + buff = malloc(bsiz); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_warc(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, bsiz, &used)); + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_pathname(ae, "test"); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_size(ae, 9); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 9, archive_write_data(a, "12345678", 9)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Read from it. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_warc(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualIntA(a, 9, archive_read_data(a, filedata, 10)); + assertEqualMem(filedata, "12345678", 9); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* Create a new archive */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_warc(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, bsiz, &used)); + + /* write first file: that should succeed */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_pathname(ae, "test"); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_size(ae, 9); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 9, archive_write_data(a, "12345678", 9)); + + /* write second file: should succeed as well */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_pathname(ae, "test2"); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_size(ae, 9); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 9, archive_write_data(a, "12345678", 9)); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Create a new archive */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_warc(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, bsiz, &used)); + + /* write a directory: this should fail */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "dir"); + archive_entry_set_filetype(ae, AE_IFDIR); + archive_entry_set_size(ae, 512); + assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae)); + archive_entry_free(ae); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* test whether last archive is indeed empty */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + + /* Test EOF */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_warc_empty.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_warc_empty.c new file mode 100644 index 0000000..0bd31bd --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_warc_empty.c @@ -0,0 +1,117 @@ +/*- + * Copyright (C) 2014 Sebastian Freundt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_write_format_warc_empty) +{ + struct archive *a; + struct archive_entry *ae; + char buff[512U]; + size_t used; + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_warc(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + /* Add "." entry which must be ignored. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 0); + archive_entry_set_ctime(ae, 4, 0); + archive_entry_set_mtime(ae, 5, 0); + archive_entry_copy_pathname(ae, "."); + archive_entry_set_mode(ae, S_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Add ".." entry which must be ignored. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 0); + archive_entry_set_ctime(ae, 4, 0); + archive_entry_set_mtime(ae, 5, 0); + archive_entry_copy_pathname(ae, ".."); + archive_entry_set_mode(ae, S_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Add "/" entry which must be ignored. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 0); + archive_entry_set_ctime(ae, 4, 0); + archive_entry_set_mtime(ae, 5, 0); + archive_entry_copy_pathname(ae, "/"); + archive_entry_set_mode(ae, S_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Add "../" entry which must be ignored. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 0); + archive_entry_set_ctime(ae, 4, 0); + archive_entry_set_mtime(ae, 5, 0); + archive_entry_copy_pathname(ae, "../"); + archive_entry_set_mode(ae, S_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Add "../../." entry which must be ignored. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 0); + archive_entry_set_ctime(ae, 4, 0); + archive_entry_set_mtime(ae, 5, 0); + archive_entry_copy_pathname(ae, "../../."); + archive_entry_set_mode(ae, S_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Add "..//.././" entry which must be ignored. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 0); + archive_entry_set_ctime(ae, 4, 0); + archive_entry_set_mtime(ae, 5, 0); + archive_entry_copy_pathname(ae, "..//.././"); + archive_entry_set_mode(ae, S_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Close out the archive without writing anything. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Test whether last archive is empty indeed. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + + /* Test EOF */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_xar.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_xar.c new file mode 100644 index 0000000..02fd2c0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_xar.c @@ -0,0 +1,315 @@ +/*- + * Copyright (c) 2003-2008 Tim Kientzle + * Copyright (c) 2010 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +static void +test_xar(const char *option) +{ + char buff2[64]; + size_t buffsize = 1500; + char *buff; + struct archive_entry *ae; + struct archive *a; + size_t used; + const char *name; + const void *value; + size_t size; + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + if (archive_write_set_format_xar(a) != ARCHIVE_OK) { + skipping("xar is not supported on this platform"); + assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + return; + } + assertA(0 == archive_write_add_filter_none(a)); + if (option != NULL && + archive_write_set_options(a, option) != ARCHIVE_OK) { + skipping("option `%s` is not supported on this platform", option); + assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + return; + } + + buff = malloc(buffsize); + assert(buff != NULL); + + assertA(0 == archive_write_open_memory(a, buff, buffsize, &used)); + + /* + * "file" has a bunch of attributes and 8 bytes of data and + * 7 bytes of xattr data and 3 bytes of xattr. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "file"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + archive_entry_set_nlink(ae, 2); + archive_entry_set_size(ae, 8); + archive_entry_xattr_add_entry(ae, "user.data1", "ABCDEFG", 7); + archive_entry_xattr_add_entry(ae, "user.data2", "XYZ", 3); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); + + /* + * "file2" is symbolic link to file + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "file2"); + archive_entry_copy_symlink(ae, "file"); + archive_entry_set_mode(ae, AE_IFLNK | 0755); + archive_entry_set_size(ae, 0); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* + * "dir/file3" has a bunch of attributes and 8 bytes of data. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "dir/file"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + archive_entry_set_size(ae, 8); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 8, archive_write_data(a, "abcdefgh", 9)); + + /* + * "dir/dir2/file4" is hard link to file + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "dir/dir2/file4"); + archive_entry_copy_hardlink(ae, "file"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + archive_entry_set_nlink(ae, 2); + archive_entry_set_size(ae, 0); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* + * "dir/dir3" is a directory + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "dir/dir3"); + archive_entry_set_mode(ae, AE_IFDIR | 0755); + archive_entry_unset_size(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* + * Add a wrong path "dir/dir2/file4/wrong" + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "dir/dir2/file4/wrong"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + archive_entry_set_nlink(ae, 1); + archive_entry_set_size(ae, 0); + assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* + * XXX TODO XXX Archive directory, other file types. + * Archive extended attributes, ACLs, other metadata. + * Verify they get read back correctly. + */ + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + + /* + * + * Now, read the data back. + * + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, 0, archive_read_support_format_all(a)); + assertEqualIntA(a, 0, archive_read_support_filter_all(a)); + assertEqualIntA(a, 0, archive_read_open_memory(a, buff, used)); + + /* + * Read "file" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_atime_nsec(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(0, archive_entry_ctime_nsec(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualString("file", archive_entry_pathname(ae)); + assert((AE_IFREG | 0755) == archive_entry_mode(ae)); + assertEqualInt(2, archive_entry_nlink(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualInt(2, archive_entry_xattr_reset(ae)); + assertEqualInt(ARCHIVE_OK, + archive_entry_xattr_next(ae, &name, &value, &size)); + assertEqualString("user.data2", name); + assertEqualMem(value, "XYZ", 3); + assertEqualInt(ARCHIVE_OK, + archive_entry_xattr_next(ae, &name, &value, &size)); + assertEqualString("user.data1", name); + assertEqualMem(value, "ABCDEFG", 7); + assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "12345678", 8); + + /* + * Read "file2" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assert(archive_entry_atime_is_set(ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_atime_nsec(ae)); + assert(archive_entry_ctime_is_set(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(0, archive_entry_ctime_nsec(ae)); + assert(archive_entry_mtime_is_set(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualString("file2", archive_entry_pathname(ae)); + assertEqualString("file", archive_entry_symlink(ae)); + assert((AE_IFLNK | 0755) == archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + + /* + * Read "dir/file3" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_atime_nsec(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(0, archive_entry_ctime_nsec(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualString("dir/file", archive_entry_pathname(ae)); + assert((AE_IFREG | 0755) == archive_entry_mode(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); + assertEqualMem(buff2, "abcdefgh", 8); + + /* + * Read "dir/dir2/file4" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assert(archive_entry_atime_is_set(ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_atime_nsec(ae)); + assert(archive_entry_ctime_is_set(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(0, archive_entry_ctime_nsec(ae)); + assert(archive_entry_mtime_is_set(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualString("dir/dir2/file4", archive_entry_pathname(ae)); + assertEqualString("file", archive_entry_hardlink(ae)); + assert((AE_IFREG | 0755) == archive_entry_mode(ae)); + assertEqualInt(2, archive_entry_nlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + + /* + * Read "dir/dir3" + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assert(archive_entry_atime_is_set(ae)); + assertEqualInt(2, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_atime_nsec(ae)); + assert(archive_entry_ctime_is_set(ae)); + assertEqualInt(4, archive_entry_ctime(ae)); + assertEqualInt(0, archive_entry_ctime_nsec(ae)); + assert(archive_entry_mtime_is_set(ae)); + assertEqualInt(5, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualString("dir/dir3", archive_entry_pathname(ae)); + assert((AE_IFDIR | 0755) == archive_entry_mode(ae)); + + /* + * Verify the end of the archive. + */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + + free(buff); +} + +DEFINE_TEST(test_write_format_xar) +{ + /* Default mode. */ + test_xar(NULL); + + /* Disable TOC checksum. */ + test_xar("!toc-checksum"); + test_xar("toc-checksum=none"); + /* Specify TOC checksum type to sha1. */ + test_xar("toc-checksum=sha1"); + /* Specify TOC checksum type to md5. */ + test_xar("toc-checksum=md5"); + + /* Disable file checksum. */ + test_xar("!checksum"); + test_xar("checksum=none"); + /* Specify file checksum type to sha1. */ + test_xar("checksum=sha1"); + /* Specify file checksum type to md5. */ + test_xar("checksum=md5"); + + /* Disable compression. */ + test_xar("!compression"); + test_xar("compression=none"); + /* Specify compression type to gzip. */ + test_xar("compression=gzip"); + test_xar("compression=gzip,compression-level=1"); + test_xar("compression=gzip,compression-level=9"); + /* Specify compression type to bzip2. */ + test_xar("compression=bzip2"); + test_xar("compression=bzip2,compression-level=1"); + test_xar("compression=bzip2,compression-level=9"); + /* Specify compression type to lzma. */ + test_xar("compression=lzma"); + test_xar("compression=lzma,compression-level=1"); + test_xar("compression=lzma,compression-level=9"); + /* Specify compression type to xz. */ + test_xar("compression=xz"); + test_xar("compression=xz,compression-level=1"); + test_xar("compression=xz,compression-level=9"); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_xar_empty.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_xar_empty.c new file mode 100644 index 0000000..97c0808 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_xar_empty.c @@ -0,0 +1,120 @@ +/*- + * Copyright (c) 2010-2011 Michihiro NAKAJIMA + * Copyright (c) 2008 Anselm Strauss + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Development supported by Google Summer of Code 2008. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_write_format_xar_empty) +{ + struct archive *a; + struct archive_entry *ae; + char buff[256]; + size_t used; + + /* Xar format: Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + if (archive_write_set_format_xar(a) != ARCHIVE_OK) { + skipping("xar is not supported on this platform"); + assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_per_block(a, 1)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_in_last_block(a, 1)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + /* Add "." entry which must be ignored. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 0); + archive_entry_set_ctime(ae, 4, 0); + archive_entry_set_mtime(ae, 5, 0); + archive_entry_copy_pathname(ae, "."); + archive_entry_set_mode(ae, S_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Add ".." entry which must be ignored. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 0); + archive_entry_set_ctime(ae, 4, 0); + archive_entry_set_mtime(ae, 5, 0); + archive_entry_copy_pathname(ae, ".."); + archive_entry_set_mode(ae, S_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Add "/" entry which must be ignored. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 0); + archive_entry_set_ctime(ae, 4, 0); + archive_entry_set_mtime(ae, 5, 0); + archive_entry_copy_pathname(ae, "/"); + archive_entry_set_mode(ae, S_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Add "../" entry which must be ignored. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 0); + archive_entry_set_ctime(ae, 4, 0); + archive_entry_set_mtime(ae, 5, 0); + archive_entry_copy_pathname(ae, "../"); + archive_entry_set_mode(ae, S_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Add "../../." entry which must be ignored. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 0); + archive_entry_set_ctime(ae, 4, 0); + archive_entry_set_mtime(ae, 5, 0); + archive_entry_copy_pathname(ae, "../../."); + archive_entry_set_mode(ae, S_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Add "..//.././" entry which must be ignored. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 0); + archive_entry_set_ctime(ae, 4, 0); + archive_entry_set_mtime(ae, 5, 0); + archive_entry_copy_pathname(ae, "..//.././"); + archive_entry_set_mode(ae, S_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Close out the archive without writing anything. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Verify the correct format for an empty Xar archive. */ + assertEqualInt(used, 0); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_zip.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_zip.c new file mode 100644 index 0000000..a7ca434 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_zip.c @@ -0,0 +1,909 @@ +/*- + * Copyright (c) 2003-2008 Tim Kientzle + * Copyright (c) 2008 Anselm Strauss + * Copyright (c) 2014 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Development supported by Google Summer of Code 2008. + */ + +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_format_zip.c 201247 2009-12-30 05:59:21Z kientzle $"); + +/* + * This test doesn't actually check that the zip writer is + * correct, just that our zip reader can read the output of + * our zip writer. We do more detailed checks of the bits + * elsewhere. + */ + +/* + * Write a variety of different file types into the archive. + */ +static void +write_contents(struct archive *a) +{ + struct archive_entry *ae; + + /* + * First write things with the "default" compression. + * The library will choose "deflate" for most things if it's + * available, else "store". + */ + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + archive_entry_copy_pathname(ae, "file"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + archive_entry_set_size(ae, 8); + assertEqualInt(0, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(8, archive_write_data(a, "12345678", 9)); + assertEqualInt(0, archive_write_data(a, "1", 1)); + + /* + * Write another file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + archive_entry_copy_pathname(ae, "file2"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + archive_entry_set_size(ae, 4); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(4, archive_write_data(a, "1234", 4)); + + /* + * Write a file with an unknown size. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 2, 15); + archive_entry_copy_pathname(ae, "file3"); + archive_entry_set_mode(ae, AE_IFREG | 0621); + archive_entry_unset_size(ae); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(5, archive_write_data(a, "mnopq", 5)); + + /* + * Write symbolic link. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(10, archive_entry_mtime_nsec(ae)); + archive_entry_copy_pathname(ae, "symlink"); + assertEqualString("symlink", archive_entry_pathname(ae)); + archive_entry_copy_symlink(ae, "file1"); + assertEqualString("file1", archive_entry_symlink(ae)); + archive_entry_set_mode(ae, AE_IFLNK | 0755); + assertEqualInt((AE_IFLNK | 0755), archive_entry_mode(ae)); + archive_entry_set_size(ae, 4); + + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* + * Write a directory to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 11, 110); + archive_entry_copy_pathname(ae, "dir"); + archive_entry_set_mode(ae, S_IFDIR | 0755); + archive_entry_set_size(ae, 512); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + failure("size should be zero so that applications know not to write"); + assertEqualInt(0, archive_entry_size(ae)); + archive_entry_free(ae); + assertEqualIntA(a, 0, archive_write_data(a, "12345678", 9)); + + /* + * Force "deflate" compression if the platform supports it. + */ +#ifdef HAVE_ZLIB_H + assertEqualIntA(a, ARCHIVE_OK, archive_write_zip_set_compression_deflate(a)); + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + archive_entry_copy_pathname(ae, "file_deflate"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + archive_entry_set_size(ae, 8); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(8, archive_write_data(a, "12345678", 9)); + assertEqualInt(0, archive_write_data(a, "1", 1)); + + /* + * Write another file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + archive_entry_copy_pathname(ae, "file2_deflate"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + archive_entry_set_size(ae, 4); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(4, archive_write_data(a, "1234", 4)); + + /* + * Write a file with an unknown size. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 2, 15); + archive_entry_copy_pathname(ae, "file3_deflate"); + archive_entry_set_mode(ae, AE_IFREG | 0621); + archive_entry_unset_size(ae); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(5, archive_write_data(a, "ghijk", 5)); + + /* + * Write symbolic like file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + archive_entry_copy_pathname(ae, "symlink_deflate"); + archive_entry_copy_symlink(ae, "file1"); + archive_entry_set_mode(ae, AE_IFLNK | 0755); + archive_entry_set_size(ae, 4); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* + * Write a directory to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 11, 110); + archive_entry_copy_pathname(ae, "dir_deflate"); + archive_entry_set_mode(ae, S_IFDIR | 0755); + archive_entry_set_size(ae, 512); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + failure("size should be zero so that applications know not to write"); + assertEqualInt(0, archive_entry_size(ae)); + archive_entry_free(ae); + assertEqualIntA(a, 0, archive_write_data(a, "12345678", 9)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a)); +#endif + + /* + * Now write a bunch of entries with "store" compression. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_zip_set_compression_store(a)); + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + archive_entry_copy_pathname(ae, "file_stored"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + archive_entry_set_size(ae, 8); + assertEqualInt(0, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(8, archive_write_data(a, "12345678", 9)); + assertEqualInt(0, archive_write_data(a, "1", 1)); + + /* + * Write another file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + archive_entry_copy_pathname(ae, "file2_stored"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + archive_entry_set_size(ae, 4); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(4, archive_write_data(a, "ACEG", 4)); + + /* + * Write a file with an unknown size. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 2, 15); + archive_entry_copy_pathname(ae, "file3_stored"); + archive_entry_set_mode(ae, AE_IFREG | 0621); + archive_entry_unset_size(ae); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(5, archive_write_data(a, "ijklm", 5)); + + /* + * Write symbolic like file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + archive_entry_copy_pathname(ae, "symlink_stored"); + archive_entry_copy_symlink(ae, "file1"); + archive_entry_set_mode(ae, AE_IFLNK | 0755); + archive_entry_set_size(ae, 4); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* + * Write a directory to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 11, 110); + archive_entry_copy_pathname(ae, "dir_stored"); + archive_entry_set_mode(ae, S_IFDIR | 0755); + archive_entry_set_size(ae, 512); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + failure("size should be zero so that applications know not to write"); + assertEqualInt(0, archive_entry_size(ae)); + archive_entry_free(ae); + assertEqualIntA(a, 0, archive_write_data(a, "12345678", 9)); + + + /* Close out the archive. */ + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); +} + +/* + * Read back all of the entries and verify their values. + */ +static void +verify_contents(struct archive *a, int seeking, int content) +{ + char filedata[64]; + struct archive_entry *ae; + + /* + * Default compression options: + */ + + /* Read and verify first file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + /* Zip doesn't store high-resolution mtime. */ + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file", archive_entry_pathname(ae)); + if (seeking) { + assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); + } + assert(archive_entry_size_is_set(ae)); + assertEqualInt(8, archive_entry_size(ae)); + if (content) { + assertEqualIntA(a, 8, + archive_read_data(a, filedata, sizeof(filedata))); + assertEqualMem(filedata, "12345678", 8); + } + + /* Read the second file back. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file2", archive_entry_pathname(ae)); + if (seeking) { + assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); + } + assertEqualInt(4, archive_entry_size(ae)); + assert(archive_entry_size_is_set(ae)); + if (content) { + assertEqualIntA(a, 4, + archive_read_data(a, filedata, sizeof(filedata))); + assertEqualMem(filedata, "1234", 4); + } + + /* Read the third file back. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file3", archive_entry_pathname(ae)); + if (seeking) { + assertEqualInt(5, archive_entry_size(ae)); + assertEqualInt(AE_IFREG | 0621, archive_entry_mode(ae)); + } else { + assertEqualInt(0, archive_entry_size_is_set(ae)); + } + if (content) { + assertEqualIntA(a, 5, + archive_read_data(a, filedata, sizeof(filedata))); + assertEqualMem(filedata, "mnopq", 5); + } + + /* Read symlink. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("symlink", archive_entry_pathname(ae)); + assertEqualInt(AE_IFLNK | 0755, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualString("file1", archive_entry_symlink(ae)); + + /* Read the dir entry back. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(11, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("dir/", archive_entry_pathname(ae)); + if (seeking) + assertEqualInt(AE_IFDIR | 0755, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + if (content) { + assertEqualIntA(a, 0, archive_read_data(a, filedata, 10)); + } + +#ifdef HAVE_ZLIB_H + /* + * Deflate compression option: + */ + + /* Read and verify first file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + /* Zip doesn't store high-resolution mtime. */ + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file_deflate", archive_entry_pathname(ae)); + if (seeking) + assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assert(archive_entry_size_is_set(ae)); + if (content) { + assertEqualIntA(a, 8, + archive_read_data(a, filedata, sizeof(filedata))); + assertEqualMem(filedata, "12345678", 8); + } + + + /* Read the second file back. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file2_deflate", archive_entry_pathname(ae)); + if (seeking) + assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); + assertEqualInt(4, archive_entry_size(ae)); + assert(archive_entry_size_is_set(ae)); + if (content) { + assertEqualIntA(a, 4, + archive_read_data(a, filedata, sizeof(filedata))); + assertEqualMem(filedata, "1234", 4); + } + + /* Read the third file back. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file3_deflate", archive_entry_pathname(ae)); + if (seeking) { + assertEqualInt(5, archive_entry_size(ae)); + assertEqualInt(AE_IFREG | 0621, archive_entry_mode(ae)); + } else { + assertEqualInt(0, archive_entry_size_is_set(ae)); + } + if (content) { + assertEqualIntA(a, 5, + archive_read_data(a, filedata, sizeof(filedata))); + assertEqualMem(filedata, "ghijk", 4); + } + + /* Read symlink. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("symlink_deflate", archive_entry_pathname(ae)); + assertEqualInt(AE_IFLNK | 0755, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualString("file1", archive_entry_symlink(ae)); + + /* Read the dir entry back. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(11, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("dir_deflate/", archive_entry_pathname(ae)); + if (seeking) { + assertEqualInt(AE_IFDIR | 0755, archive_entry_mode(ae)); + } + assertEqualInt(0, archive_entry_size(ae)); + if (content) { + assertEqualIntA(a, 0, archive_read_data(a, filedata, 10)); + } +#endif + + /* + * Store compression option: + */ + + /* Read and verify first file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + /* Zip doesn't store high-resolution mtime. */ + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file_stored", archive_entry_pathname(ae)); + if (seeking) + assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); + assert(archive_entry_size_is_set(ae)); + assertEqualInt(8, archive_entry_size(ae)); + if (content) { + assertEqualIntA(a, 8, + archive_read_data(a, filedata, sizeof(filedata))); + assertEqualMem(filedata, "12345678", 8); + } + + + /* Read the second file back. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file2_stored", archive_entry_pathname(ae)); + if (seeking) + assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); + assertEqualInt(4, archive_entry_size(ae)); + assert(archive_entry_size_is_set(ae)); + if (content) { + assertEqualIntA(a, 4, + archive_read_data(a, filedata, sizeof(filedata))); + assertEqualMem(filedata, "ACEG", 4); + } + + /* Read the third file back. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file3_stored", archive_entry_pathname(ae)); + if (seeking) { + assertEqualInt(5, archive_entry_size(ae)); + assertEqualInt(AE_IFREG | 0621, archive_entry_mode(ae)); + } else { + assertEqualInt(0, archive_entry_size_is_set(ae)); + } + if (content) { + assertEqualIntA(a, 5, + archive_read_data(a, filedata, sizeof(filedata))); + assertEqualMem(filedata, "ijklm", 4); + } + + /* Read symlink. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("symlink_stored", archive_entry_pathname(ae)); + assertEqualInt(AE_IFLNK | 0755, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualString("file1", archive_entry_symlink(ae)); + + /* Read the dir entry back. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(11, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("dir_stored/", archive_entry_pathname(ae)); + if (seeking) + assertEqualInt(AE_IFDIR | 0755, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + if (content) { + assertEqualIntA(a, 0, archive_read_data(a, filedata, 10)); + } + + /* Verify the end of the archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +/* + * Do a write-then-read roundtrip. + */ +DEFINE_TEST(test_write_format_zip) +{ + struct archive *a; + size_t used; + size_t buffsize = 1000000; + char *buff; + + buff = malloc(buffsize); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "zip:experimental")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + write_contents(a); + dumpfile("constructed.zip", buff, used); + + /* + * Now, read the data back. + */ + /* With the standard memory reader. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + verify_contents(a, 1, 1); + + /* With the test memory reader -- streaming mode. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, buff, used, 7)); + /* Streaming reader doesn't see mode information from Central Directory. */ + verify_contents(a, 0, 1); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, buff, used, 7)); + /* Streaming reader doesn't see mode information from Central Directory. */ + verify_contents(a, 0, 0); + + /* With the test memory reader -- seeking mode. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7)); + verify_contents(a, 1, 1); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7)); + verify_contents(a, 1, 0); + + free(buff); +} + +/* + * Do a write-then-read roundtrip with Zip64 enabled. + */ +DEFINE_TEST(test_write_format_zip64) +{ + struct archive *a; + size_t used; + size_t buffsize = 1000000; + char *buff; + + buff = malloc(buffsize); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "zip:zip64")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "zip:experimental")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + write_contents(a); + dumpfile("constructed64.zip", buff, used); + + /* + * Now, read the data back. + */ + /* With the standard memory reader. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + verify_contents(a, 1, 1); + + /* With the test memory reader -- streaming mode. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, buff, used, 7)); + /* Streaming reader doesn't see mode information from Central Directory. */ + verify_contents(a, 0, 1); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, buff, used, 7)); + /* Streaming reader doesn't see mode information from Central Directory. */ + verify_contents(a, 0, 0); + + /* With the test memory reader -- seeking mode. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7)); + verify_contents(a, 1, 1); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7)); + verify_contents(a, 1, 0); + + free(buff); +} + +DEFINE_TEST(test_write_format_zip_traditional_pkware_encryption) +{ + struct archive *a; + size_t used; + size_t buffsize = 1000000; + char *buff; + + buff = malloc(buffsize); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + if (ARCHIVE_OK != archive_write_set_options(a, + "zip:encryption=zipcrypt")) { + skipping("This system does not have cryptographic liberary"); + archive_write_free(a); + free(buff); + return; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_passphrase(a, "password1234")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "zip:experimental")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + write_contents(a); + dumpfile("constructed.zip", buff, used); + + /* + * Now, read the data back. + */ + /* With the standard memory reader. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_add_passphrase(a, "password1234")); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + verify_contents(a, 1, 1); + + /* With the test memory reader -- streaming mode. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_add_passphrase(a, "password1234")); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, buff, used, 7)); + /* Streaming reader doesn't see mode information from Central Directory. */ + verify_contents(a, 0, 1); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_add_passphrase(a, "password1234")); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, buff, used, 7)); + /* Streaming reader doesn't see mode information from Central Directory. */ + verify_contents(a, 0, 0); + + /* With the test memory reader -- seeking mode. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_add_passphrase(a, "password1234")); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7)); + verify_contents(a, 1, 1); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_add_passphrase(a, "password1234")); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7)); + verify_contents(a, 1, 0); + + free(buff); +} + +DEFINE_TEST(test_write_format_zip_winzip_aes128_encryption) +{ + struct archive *a; + size_t used; + size_t buffsize = 1000000; + char *buff; + + buff = malloc(buffsize); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + if (ARCHIVE_OK != archive_write_set_options(a, "zip:encryption=aes128")) + { + skipping("This system does not have cryptographic liberary"); + archive_write_free(a); + free(buff); + return; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_passphrase(a, "password1234")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "zip:experimental")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + write_contents(a); + dumpfile("constructed.zip", buff, used); + + /* + * Now, read the data back. + */ + /* With the standard memory reader. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_add_passphrase(a, "password1234")); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + verify_contents(a, 1, 1); + + /* With the test memory reader -- streaming mode. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_add_passphrase(a, "password1234")); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, buff, used, 7)); + /* Streaming reader doesn't see mode information from Central Directory. */ + verify_contents(a, 0, 1); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_add_passphrase(a, "password1234")); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, buff, used, 7)); + /* Streaming reader doesn't see mode information from Central Directory. */ + verify_contents(a, 0, 0); + + /* With the test memory reader -- seeking mode. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_add_passphrase(a, "password1234")); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7)); + verify_contents(a, 1, 1); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_add_passphrase(a, "password1234")); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7)); + verify_contents(a, 1, 0); + + free(buff); +} + +DEFINE_TEST(test_write_format_zip_winzip_aes256_encryption) +{ + struct archive *a; + size_t used; + size_t buffsize = 1000000; + char *buff; + + buff = malloc(buffsize); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + if (ARCHIVE_OK != archive_write_set_options(a, "zip:encryption=aes256")) + { + skipping("This system does not have cryptographic liberary"); + archive_write_free(a); + free(buff); + return; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_passphrase(a, "password1234")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "zip:experimental")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + write_contents(a); + dumpfile("constructed.zip", buff, used); + + /* + * Now, read the data back. + */ + /* With the standard memory reader. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_add_passphrase(a, "password1234")); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + verify_contents(a, 1, 1); + + /* With the test memory reader -- streaming mode. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_add_passphrase(a, "password1234")); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, buff, used, 7)); + /* Streaming reader doesn't see mode information from Central Directory. */ + verify_contents(a, 0, 1); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_add_passphrase(a, "password1234")); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, buff, used, 7)); + /* Streaming reader doesn't see mode information from Central Directory. */ + verify_contents(a, 0, 0); + + /* With the test memory reader -- seeking mode. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_add_passphrase(a, "password1234")); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7)); + verify_contents(a, 1, 1); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_add_passphrase(a, "password1234")); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7)); + verify_contents(a, 1, 0); + + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_zip_compression_store.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_zip_compression_store.c new file mode 100644 index 0000000..c969a41 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_zip_compression_store.c @@ -0,0 +1,386 @@ +/*- + * Copyright (c) 2008 Anselm Strauss + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Development supported by Google Summer of Code 2008. + */ + +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_format_zip_no_compression.c 201247 2009-12-30 05:59:21Z kientzle $"); + +/* File data */ +static const char file_name[] = "file"; +static const char file_data1[] = {'1', '2', '3', '4', '5'}; +static const char file_data2[] = {'6', '7', '8', '9', '0'}; +static const int file_perm = 00644; +static const short file_uid = 10; +static const short file_gid = 20; + +/* Folder data */ +static const char folder_name[] = "folder/"; +static const int folder_perm = 00755; +static const short folder_uid = 30; +static const short folder_gid = 40; + +static time_t now; + +static unsigned long +bitcrc32(unsigned long c, const void *_p, size_t s) +{ + /* This is a drop-in replacement for crc32() from zlib. + * Libarchive should be able to correctly generate + * uncompressed zip archives (including correct CRCs) even + * when zlib is unavailable, and this function helps us verify + * that. Yes, this is very, very slow and unsuitable for + * production use, but it's correct, compact, and works well + * enough for this particular usage. Libarchive internally + * uses a much more efficient implementation. */ + const unsigned char *p = _p; + int bitctr; + + if (p == NULL) + return (0); + + for (; s > 0; --s) { + c ^= *p++; + for (bitctr = 8; bitctr > 0; --bitctr) { + if (c & 1) c = (c >> 1); + else c = (c >> 1) ^ 0xedb88320; + c ^= 0x80000000; + } + } + return (c); +} + +static void verify_write_uncompressed(struct archive *a) +{ + struct archive_entry *entry; + + /* Write entries. */ + + /* Regular file */ + assert((entry = archive_entry_new()) != NULL); + archive_entry_set_pathname(entry, file_name); + archive_entry_set_mode(entry, S_IFREG | 0644); + archive_entry_set_size(entry, sizeof(file_data1) + sizeof(file_data2)); + archive_entry_set_uid(entry, file_uid); + archive_entry_set_gid(entry, file_gid); + archive_entry_set_mtime(entry, now, 0); + archive_entry_set_atime(entry, now + 3, 0); + assertEqualIntA(a, 0, archive_write_header(a, entry)); + assertEqualIntA(a, sizeof(file_data1), archive_write_data(a, file_data1, sizeof(file_data1))); + assertEqualIntA(a, sizeof(file_data2), archive_write_data(a, file_data2, sizeof(file_data2))); + archive_entry_free(entry); + + /* Folder */ + assert((entry = archive_entry_new()) != NULL); + archive_entry_set_pathname(entry, folder_name); + archive_entry_set_mode(entry, S_IFDIR | folder_perm); + archive_entry_set_size(entry, 0); + archive_entry_set_uid(entry, folder_uid); + archive_entry_set_gid(entry, folder_gid); + archive_entry_set_mtime(entry, now, 0); + archive_entry_set_ctime(entry, now + 5, 0); + assertEqualIntA(a, 0, archive_write_header(a, entry)); + archive_entry_free(entry); +} + +/* Quick and dirty: Read 2-byte and 4-byte integers from Zip file. */ +static unsigned int +i2(const void *p_) +{ + const unsigned char *p = p_; + return (p[0] | (p[1] << 8)); +} + +static unsigned int +i4(const void *p_) +{ + const unsigned char *p = p_; + return (i2(p) | (i2(p + 2) << 16)); +} + +static void verify_uncompressed_contents(const char *buff, size_t used) +{ + const char *buffend; + + /* Misc variables */ + unsigned long crc; + struct tm *tm = localtime(&now); + + /* p is the pointer to walk over the central directory, + * q walks over the local headers, the data and the data descriptors. */ + const char *p, *q, *local_header, *extra_start; + + /* Remember the end of the archive in memory. */ + buffend = buff + used; + + /* Verify "End of Central Directory" record. */ + /* Get address of end-of-central-directory record. */ + p = buffend - 22; /* Assumes there is no zip comment field. */ + failure("End-of-central-directory begins with PK\\005\\006 signature"); + assertEqualMem(p, "PK\005\006", 4); + failure("This must be disk 0"); + assertEqualInt(i2(p + 4), 0); + failure("Central dir must start on disk 0"); + assertEqualInt(i2(p + 6), 0); + failure("All central dir entries are on this disk"); + assertEqualInt(i2(p + 8), i2(p + 10)); + failure("CD start (%d) + CD length (%d) should == archive size - 22", + i4(p + 12), i4(p + 16)); + assertEqualInt(i4(p + 12) + i4(p + 16), used - 22); + failure("no zip comment"); + assertEqualInt(i2(p + 20), 0); + + /* Get address of first entry in central directory. */ + p = buff + i4(buffend - 6); + failure("Central file record at offset %d should begin with" + " PK\\001\\002 signature", + i4(buffend - 10)); + + /* Verify file entry in central directory. */ + assertEqualMem(p, "PK\001\002", 4); /* Signature */ + assertEqualInt(i2(p + 4), 3 * 256 + 10); /* Version made by */ + assertEqualInt(i2(p + 6), 10); /* Version needed to extract */ + assertEqualInt(i2(p + 8), 8); /* Flags */ + assertEqualInt(i2(p + 10), 0); /* Compression method */ + assertEqualInt(i2(p + 12), (tm->tm_hour * 2048) + (tm->tm_min * 32) + (tm->tm_sec / 2)); /* File time */ + assertEqualInt(i2(p + 14), ((tm->tm_year - 80) * 512) + ((tm->tm_mon + 1) * 32) + tm->tm_mday); /* File date */ + crc = bitcrc32(0, file_data1, sizeof(file_data1)); + crc = bitcrc32(crc, file_data2, sizeof(file_data2)); + assertEqualInt(i4(p + 16), crc); /* CRC-32 */ + assertEqualInt(i4(p + 20), sizeof(file_data1) + sizeof(file_data2)); /* Compressed size */ + assertEqualInt(i4(p + 24), sizeof(file_data1) + sizeof(file_data2)); /* Uncompressed size */ + assertEqualInt(i2(p + 28), strlen(file_name)); /* Pathname length */ + assertEqualInt(i2(p + 30), 28); /* Extra field length */ + assertEqualInt(i2(p + 32), 0); /* File comment length */ + assertEqualInt(i2(p + 34), 0); /* Disk number start */ + assertEqualInt(i2(p + 36), 0); /* Internal file attrs */ + assertEqualInt(i4(p + 38) >> 16 & 01777, file_perm); /* External file attrs */ + assertEqualInt(i4(p + 42), 0); /* Offset of local header */ + assertEqualMem(p + 46, file_name, strlen(file_name)); /* Pathname */ + p = p + 46 + strlen(file_name); + assertEqualInt(i2(p), 0x5455); /* 'UT' extension header */ + assertEqualInt(i2(p + 2), 9); /* 'UT' size */ + assertEqualInt(p[4], 3); /* 'UT' flags */ + assertEqualInt(i4(p + 5), now); /* 'UT' mtime */ + assertEqualInt(i4(p + 9), now + 3); /* 'UT' atime */ + p = p + 4 + i2(p + 2); + assertEqualInt(i2(p), 0x7875); /* 'ux' extension header */ + assertEqualInt(i2(p + 2), 11); /* 'ux' size */ +/* TODO */ + p = p + 4 + i2(p + 2); + + /* Verify local header of file entry. */ + local_header = q = buff; + assertEqualMem(q, "PK\003\004", 4); /* Signature */ + assertEqualInt(i2(q + 4), 10); /* Version needed to extract */ + assertEqualInt(i2(q + 6), 8); /* Flags */ + assertEqualInt(i2(q + 8), 0); /* Compression method */ + assertEqualInt(i2(q + 10), (tm->tm_hour * 2048) + (tm->tm_min * 32) + (tm->tm_sec / 2)); /* File time */ + assertEqualInt(i2(q + 12), ((tm->tm_year - 80) * 512) + ((tm->tm_mon + 1) * 32) + tm->tm_mday); /* File date */ + assertEqualInt(i4(q + 14), 0); /* CRC-32 */ + assertEqualInt(i4(q + 18), sizeof(file_data1) + sizeof(file_data2)); /* Compressed size */ + assertEqualInt(i4(q + 22), sizeof(file_data1) + sizeof(file_data2)); /* Uncompressed size */ + assertEqualInt(i2(q + 26), strlen(file_name)); /* Pathname length */ + assertEqualInt(i2(q + 28), 41); /* Extra field length */ + assertEqualMem(q + 30, file_name, strlen(file_name)); /* Pathname */ + extra_start = q = q + 30 + strlen(file_name); + assertEqualInt(i2(q), 0x5455); /* 'UT' extension header */ + assertEqualInt(i2(q + 2), 9); /* 'UT' size */ + assertEqualInt(q[4], 3); /* 'UT' flags */ + assertEqualInt(i4(q + 5), now); /* 'UT' mtime */ + assertEqualInt(i4(q + 9), now + 3); /* 'UT' atime */ + q = q + 4 + i2(q + 2); + + assertEqualInt(i2(q), 0x7875); /* 'ux' extension header */ + assertEqualInt(i2(q + 2), 11); /* 'ux' size */ + assertEqualInt(q[4], 1); /* 'ux' version */ + assertEqualInt(q[5], 4); /* 'ux' uid size */ + assertEqualInt(i4(q + 6), file_uid); /* 'Ux' UID */ + assertEqualInt(q[10], 4); /* 'ux' gid size */ + assertEqualInt(i4(q + 11), file_gid); /* 'Ux' GID */ + q = q + 4 + i2(q + 2); + + assertEqualInt(i2(q), 0x6c78); /* 'xl' experimental extension header */ + assertEqualInt(i2(q + 2), 9); /* size */ + assertEqualInt(q[4], 7); /* Bitmap of fields included. */ + assertEqualInt(i2(q + 5) >> 8, 3); /* system & version made by */ + assertEqualInt(i2(q + 7), 0); /* internal file attributes */ + assertEqualInt(i4(q + 9) >> 16 & 01777, file_perm); /* external file attributes */ + q = q + 4 + i2(q + 2); + + assert(q == extra_start + i2(local_header + 28)); + q = extra_start + i2(local_header + 28); + + /* Verify data of file entry. */ + assertEqualMem(q, file_data1, sizeof(file_data1)); + assertEqualMem(q + sizeof(file_data1), file_data2, sizeof(file_data2)); + q = q + sizeof(file_data1) + sizeof(file_data2); + + /* Verify data descriptor of file entry. */ + assertEqualMem(q, "PK\007\010", 4); /* Signature */ + assertEqualInt(i4(q + 4), crc); /* CRC-32 */ + assertEqualInt(i4(q + 8), sizeof(file_data1) + sizeof(file_data2)); /* Compressed size */ + assertEqualInt(i4(q + 12), sizeof(file_data1) + sizeof(file_data2)); /* Uncompressed size */ + q = q + 16; + + /* Verify folder entry in central directory. */ + assertEqualMem(p, "PK\001\002", 4); /* Signature */ + assertEqualInt(i2(p + 4), 3 * 256 + 20); /* Version made by */ + assertEqualInt(i2(p + 6), 20); /* Version needed to extract */ + assertEqualInt(i2(p + 8), 0); /* Flags */ + assertEqualInt(i2(p + 10), 0); /* Compression method */ + assertEqualInt(i2(p + 12), (tm->tm_hour * 2048) + (tm->tm_min * 32) + (tm->tm_sec / 2)); /* File time */ + assertEqualInt(i2(p + 14), ((tm->tm_year - 80) * 512) + ((tm->tm_mon + 1) * 32) + tm->tm_mday); /* File date */ + crc = 0; + assertEqualInt(i4(p + 16), crc); /* CRC-32 */ + assertEqualInt(i4(p + 20), 0); /* Compressed size */ + assertEqualInt(i4(p + 24), 0); /* Uncompressed size */ + assertEqualInt(i2(p + 28), strlen(folder_name)); /* Pathname length */ + assertEqualInt(i2(p + 30), 28); /* Extra field length */ + assertEqualInt(i2(p + 32), 0); /* File comment length */ + assertEqualInt(i2(p + 34), 0); /* Disk number start */ + assertEqualInt(i2(p + 36), 0); /* Internal file attrs */ + assertEqualInt(i4(p + 38) >> 16 & 01777, folder_perm); /* External file attrs */ + assertEqualInt(i4(p + 42), q - buff); /* Offset of local header */ + assertEqualMem(p + 46, folder_name, strlen(folder_name)); /* Pathname */ + p = p + 46 + strlen(folder_name); + assertEqualInt(i2(p), 0x5455); /* 'UT' extension header */ + assertEqualInt(i2(p + 2), 9); /* 'UT' size */ + assertEqualInt(p[4], 5); /* 'UT' flags */ + assertEqualInt(i4(p + 5), now); /* 'UT' mtime */ + assertEqualInt(i4(p + 9), now + 5); /* 'UT' atime */ + p = p + 4 + i2(p + 2); + assertEqualInt(i2(p), 0x7875); /* 'ux' extension header */ + assertEqualInt(i2(p + 2), 11); /* 'ux' size */ + assertEqualInt(p[4], 1); /* 'ux' version */ + assertEqualInt(p[5], 4); /* 'ux' uid size */ + assertEqualInt(i4(p + 6), folder_uid); /* 'ux' UID */ + assertEqualInt(p[10], 4); /* 'ux' gid size */ + assertEqualInt(i4(p + 11), folder_gid); /* 'ux' GID */ + /*p = p + 4 + i2(p + 2);*/ + + /* Verify local header of folder entry. */ + local_header = q; + assertEqualMem(q, "PK\003\004", 4); /* Signature */ + assertEqualInt(i2(q + 4), 20); /* Version needed to extract */ + assertEqualInt(i2(q + 6), 0); /* Flags */ + assertEqualInt(i2(q + 8), 0); /* Compression method */ + assertEqualInt(i2(q + 10), (tm->tm_hour * 2048) + (tm->tm_min * 32) + (tm->tm_sec / 2)); /* File time */ + assertEqualInt(i2(q + 12), ((tm->tm_year - 80) * 512) + ((tm->tm_mon + 1) * 32) + tm->tm_mday); /* File date */ + assertEqualInt(i4(q + 14), 0); /* CRC-32 */ + assertEqualInt(i4(q + 18), 0); /* Compressed size */ + assertEqualInt(i4(q + 22), 0); /* Uncompressed size */ + assertEqualInt(i2(q + 26), strlen(folder_name)); /* Pathname length */ + assertEqualInt(i2(q + 28), 41); /* Extra field length */ + assertEqualMem(q + 30, folder_name, strlen(folder_name)); /* Pathname */ + extra_start = q = q + 30 + strlen(folder_name); + assertEqualInt(i2(q), 0x5455); /* 'UT' extension header */ + assertEqualInt(i2(q + 2), 9); /* 'UT' size */ + assertEqualInt(q[4], 5); /* 'UT' flags */ + assertEqualInt(i4(q + 5), now); /* 'UT' mtime */ + assertEqualInt(i4(q + 9), now + 5); /* 'UT' atime */ + q = q + 4 + i2(q + 2); + assertEqualInt(i2(q), 0x7875); /* 'ux' extension header */ + assertEqualInt(i2(q + 2), 11); /* 'ux' size */ + assertEqualInt(q[4], 1); /* 'ux' version */ + assertEqualInt(q[5], 4); /* 'ux' uid size */ + assertEqualInt(i4(q + 6), folder_uid); /* 'ux' UID */ + assertEqualInt(q[10], 4); /* 'ux' gid size */ + assertEqualInt(i4(q + 11), folder_gid); /* 'ux' GID */ + q = q + 4 + i2(q + 2); + + assertEqualInt(i2(q), 0x6c78); /* 'xl' experimental extension header */ + assertEqualInt(i2(q + 2), 9); /* size */ + assertEqualInt(q[4], 7); /* bitmap of fields */ + assertEqualInt(i2(q + 5) >> 8, 3); /* system & version made by */ + assertEqualInt(i2(q + 7), 0); /* internal file attributes */ + assertEqualInt(i4(q + 9) >> 16 & 01777, folder_perm); /* external file attributes */ + q = q + 4 + i2(q + 2); + + assert(q == extra_start + i2(local_header + 28)); + q = extra_start + i2(local_header + 28); + + /* There should not be any data in the folder entry, + * so the first central directory entry should be next: */ + assertEqualMem(q, "PK\001\002", 4); /* Signature */ +} + +DEFINE_TEST(test_write_format_zip_compression_store) +{ + /* Buffer data */ + struct archive *a; + char buff[100000]; + size_t used; + + /* Time data */ + now = time(NULL); + + /* Create new ZIP archive in memory without padding. */ + /* Use compression=store to disable compression. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "zip:compression=store")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "zip:experimental")); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_per_block(a, 1)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_in_last_block(a, 1)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used)); + + verify_write_uncompressed(a); + + /* Close the archive . */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + dumpfile("constructed.zip", buff, used); + + verify_uncompressed_contents(buff, used); + + /* Create new ZIP archive in memory without padding. */ + /* Use compression-level=0 to disable compression. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "zip:compression-level=0")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "zip:experimental")); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_per_block(a, 1)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_in_last_block(a, 1)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used)); + + verify_write_uncompressed(a); + + /* Close the archive . */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + dumpfile("constructed.zip", buff, used); + + verify_uncompressed_contents(buff, used); + +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_zip_empty.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_zip_empty.c new file mode 100644 index 0000000..73a5573 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_zip_empty.c @@ -0,0 +1,78 @@ +/*- + * Copyright (c) 2008 Anselm Strauss + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Development supported by Google Summer of Code 2008. + */ + +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_format_zip_empty.c 201247 2009-12-30 05:59:21Z kientzle $"); + +DEFINE_TEST(test_write_format_zip_empty) +{ + struct archive *a; + struct archive_entry *ae; + char buff[256]; + size_t used; + + /* Zip format: Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_per_block(a, 1)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_in_last_block(a, 1)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used)); + + /* Close out the archive without writing anything. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Verify the correct format for an empty Zip archive. */ + assertEqualInt(used, 22); + assertEqualMem(buff, + "PK\005\006\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", + 22); + + /* Verify that we read this kind of empty archive correctly. */ + /* Try with the standard memory reader, and with the test + memory reader with and without seek support. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, 22)); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, buff, 22, 1)); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, 22, 22)); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_zip_empty_zip64.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_zip_empty_zip64.c new file mode 100644 index 0000000..8f9975b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_zip_empty_zip64.c @@ -0,0 +1,103 @@ +/*- + * Copyright (c) 2008 Anselm Strauss + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Development supported by Google Summer of Code 2008. + */ + +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_format_zip_empty.c 201247 2009-12-30 05:59:21Z kientzle $"); + +DEFINE_TEST(test_write_format_zip_empty_zip64) +{ + struct archive *a; + struct archive_entry *ae; + char buff[256]; + size_t used; + + /* Zip format: Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_per_block(a, 1)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_in_last_block(a, 1)); + /* Force zip writer to use Zip64 extensions. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_option(a, "zip", "zip64", "1")); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used)); + + /* Close out the archive without writing anything. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Verify the correct format for an empty Zip archive with Zip64 extensions forced. */ + assertEqualInt(used, 98); + assertEqualMem(buff, + "PK\006\006" /* Zip64 end-of-central-directory record */ + "\x2c\0\0\0\0\0\0\0" /* 44 bytes long */ + "\x2d\0" /* Created by Zip 4.5 */ + "\x2d\0" /* Extract with Zip 4.5 or later */ + "\0\0\0\0" /* This is disk #0 */ + "\0\0\0\0" /* Central dir starts on disk #0 */ + "\0\0\0\0\0\0\0\0" /* There are 0 entries on this disk ... */ + "\0\0\0\0\0\0\0\0" /* ... out of 0 entries total ... */ + "\0\0\0\0\0\0\0\0" /* ... requiring a total of 0 bytes. */ + "\0\0\0\0\0\0\0\0" /* Directory starts at offset 0 */ + + "PK\006\007" /* Zip64 end-of-central-directory locator */ + "\0\0\0\0" /* Zip64 EOCD record is on disk #0 .. */ + "\0\0\0\0\0\0\0\0" /* .. at offset 0 .. */ + "\1\0\0\0" /* .. of 1 total disks. */ + + "PK\005\006" /* Regular Zip end-of-central-directory record */ + "\0\0" /* This is disk #0 */ + "\0\0" /* Central dir is on disk #0 */ + "\0\0" /* There are 0 entries on this disk ... */ + "\0\0" /* ... out of 0 total entries ... */ + "\0\0\0\0" /* ... requiring a total of 0 bytes. */ + "\0\0\0\0" /* Directory starts at offset 0. */ + "\0\0" /* File comment is zero bytes long. */, + 98); + + /* Verify that we read this kind of empty archive correctly. */ + /* Try with the standard memory reader, and with the test + memory reader with and without seek support. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, 98)); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, buff, 98, 1)); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, 98, 98)); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_zip_file.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_zip_file.c new file mode 100644 index 0000000..2868123 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_zip_file.c @@ -0,0 +1,251 @@ +/*- + * Copyright (c) 2003-2008 Tim Kientzle + * Copyright (c) 2008 Anselm Strauss + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Development supported by Google Summer of Code 2008. + */ + +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_format_zip.c 201247 2009-12-30 05:59:21Z kientzle $"); + +/* + * Detailed byte-for-byte verification of the format of a zip archive + * with a single file written to it. + */ + +static unsigned long +bitcrc32(unsigned long c, void *_p, size_t s) +{ + /* This is a drop-in replacement for crc32() from zlib. + * Libarchive should be able to correctly generate + * uncompressed zip archives (including correct CRCs) even + * when zlib is unavailable, and this function helps us verify + * that. Yes, this is very, very slow and unsuitable for + * production use, but it's correct, compact, and works well + * enough for this particular usage. Libarchive internally + * uses a much more efficient implementation. */ + const unsigned char *p = _p; + int bitctr; + + if (p == NULL) + return (0); + + for (; s > 0; --s) { + c ^= *p++; + for (bitctr = 8; bitctr > 0; --bitctr) { + if (c & 1) c = (c >> 1); + else c = (c >> 1) ^ 0xedb88320; + c ^= 0x80000000; + } + } + return (c); +} + +/* Quick and dirty: Read 2-byte and 4-byte integers from Zip file. */ +static unsigned i2(const unsigned char *p) { return ((p[0] & 0xff) | ((p[1] & 0xff) << 8)); } +static unsigned i4(const unsigned char *p) { return (i2(p) | (i2(p + 2) << 16)); } + +DEFINE_TEST(test_write_format_zip_file) +{ + struct archive *a; + struct archive_entry *ae; + time_t t = 1234567890; + struct tm *tm = localtime(&t); + size_t used, buffsize = 1000000; + unsigned long crc; + int file_perm = 00644; + int zip_version = 20; + int zip_compression = 8; + short file_uid = 10, file_gid = 20; + unsigned char *buff, *buffend, *p; + unsigned char *central_header, *local_header, *eocd, *eocd_record; + unsigned char *extension_start, *extension_end; + char file_data[] = {'1', '2', '3', '4', '5', '6', '7', '8'}; + const char *file_name = "file"; + +#ifndef HAVE_ZLIB_H + zip_version = 10; + zip_compression = 0; +#endif + + buff = malloc(buffsize); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "zip:experimental")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, file_name); + archive_entry_set_mode(ae, AE_IFREG | file_perm); + archive_entry_set_size(ae, sizeof(file_data)); + archive_entry_set_uid(ae, file_uid); + archive_entry_set_gid(ae, file_gid); + archive_entry_set_mtime(ae, t, 0); + assertEqualInt(0, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(8, archive_write_data(a, file_data, sizeof(file_data))); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + buffend = buff + used; + dumpfile("constructed.zip", buff, used); + + /* Verify "End of Central Directory" record. */ + /* Get address of end-of-central-directory record. */ + eocd_record = p = buffend - 22; /* Assumes there is no zip comment field. */ + failure("End-of-central-directory begins with PK\\005\\006 signature"); + assertEqualMem(p, "PK\005\006", 4); + failure("This must be disk 0"); + assertEqualInt(i2(p + 4), 0); + failure("Central dir must start on disk 0"); + assertEqualInt(i2(p + 6), 0); + failure("All central dir entries are on this disk"); + assertEqualInt(i2(p + 8), i2(p + 10)); + eocd = buff + i4(p + 12) + i4(p + 16); + failure("no zip comment"); + assertEqualInt(i2(p + 20), 0); + + /* Get address of first entry in central directory. */ + central_header = p = buff + i4(buffend - 6); + failure("Central file record at offset %d should begin with" + " PK\\001\\002 signature", + i4(buffend - 10)); + + /* Verify file entry in central directory. */ + assertEqualMem(p, "PK\001\002", 4); /* Signature */ + assertEqualInt(i2(p + 4), 3 * 256 + zip_version); /* Version made by */ + assertEqualInt(i2(p + 6), zip_version); /* Version needed to extract */ + assertEqualInt(i2(p + 8), 8); /* Flags */ + assertEqualInt(i2(p + 10), zip_compression); /* Compression method */ + assertEqualInt(i2(p + 12), (tm->tm_hour * 2048) + (tm->tm_min * 32) + (tm->tm_sec / 2)); /* File time */ + assertEqualInt(i2(p + 14), ((tm->tm_year - 80) * 512) + ((tm->tm_mon + 1) * 32) + tm->tm_mday); /* File date */ + crc = bitcrc32(0, file_data, sizeof(file_data)); + assertEqualInt(i4(p + 16), crc); /* CRC-32 */ + /* assertEqualInt(i4(p + 20), sizeof(file_data)); */ /* Compressed size */ + assertEqualInt(i4(p + 24), sizeof(file_data)); /* Uncompressed size */ + assertEqualInt(i2(p + 28), strlen(file_name)); /* Pathname length */ + /* assertEqualInt(i2(p + 30), 28); */ /* Extra field length: See below */ + assertEqualInt(i2(p + 32), 0); /* File comment length */ + assertEqualInt(i2(p + 34), 0); /* Disk number start */ + assertEqualInt(i2(p + 36), 0); /* Internal file attrs */ + assertEqualInt(i4(p + 38) >> 16 & 01777, file_perm); /* External file attrs */ + assertEqualInt(i4(p + 42), 0); /* Offset of local header */ + assertEqualMem(p + 46, file_name, strlen(file_name)); /* Pathname */ + p = extension_start = central_header + 46 + strlen(file_name); + extension_end = extension_start + i2(central_header + 30); + + assertEqualInt(i2(p), 0x5455); /* 'UT' extension header */ + assertEqualInt(i2(p + 2), 5); /* 'UT' size */ + assertEqualInt(p[4], 1); /* 'UT' flags */ + assertEqualInt(i4(p + 5), t); /* 'UT' mtime */ + p += 4 + i2(p + 2); + + assertEqualInt(i2(p), 0x7875); /* 'ux' extension header */ + assertEqualInt(i2(p + 2), 11); /* 'ux' size */ + /* TODO: verify 'ux' contents */ + p += 4 + i2(p + 2); + + /* Just in case: Report any extra extensions. */ + while (p < extension_end) { + failure("Unexpected extension 0x%04X", i2(p)); + assert(0); + p += 4 + i2(p + 2); + } + + /* Should have run exactly to end of extra data. */ + assert(p == extension_end); + + assert(p == eocd); + + /* Regular EOCD immediately follows central directory. */ + assert(p == eocd_record); + + /* Verify local header of file entry. */ + p = local_header = buff; + assertEqualMem(p, "PK\003\004", 4); /* Signature */ + assertEqualInt(i2(p + 4), zip_version); /* Version needed to extract */ + assertEqualInt(i2(p + 6), 8); /* Flags */ + assertEqualInt(i2(p + 8), zip_compression); /* Compression method */ + assertEqualInt(i2(p + 10), (tm->tm_hour * 2048) + (tm->tm_min * 32) + (tm->tm_sec / 2)); /* File time */ + assertEqualInt(i2(p + 12), ((tm->tm_year - 80) * 512) + ((tm->tm_mon + 1) * 32) + tm->tm_mday); /* File date */ + assertEqualInt(i4(p + 14), 0); /* CRC-32 */ + /* assertEqualInt(i4(p + 18), sizeof(file_data)); */ /* Compressed size */ + /* assertEqualInt(i4(p + 22), sizeof(file_data)); */ /* Uncompressed size not stored because we're using length-at-end. */ + assertEqualInt(i2(p + 26), strlen(file_name)); /* Pathname length */ + assertEqualInt(i2(p + 28), 37); /* Extra field length */ + assertEqualMem(p + 30, file_name, strlen(file_name)); /* Pathname */ + p = extension_start = local_header + 30 + strlen(file_name); + extension_end = extension_start + i2(local_header + 28); + + assertEqualInt(i2(p), 0x5455); /* 'UT' extension header */ + assertEqualInt(i2(p + 2), 5); /* size */ + assertEqualInt(p[4], 1); /* 'UT' flags */ + assertEqualInt(i4(p + 5), t); /* 'UT' mtime */ + p += 4 + i2(p + 2); + + assertEqualInt(i2(p), 0x7875); /* 'ux' extension header */ + assertEqualInt(i2(p + 2), 11); /* size */ + assertEqualInt(p[4], 1); /* 'ux' version */ + assertEqualInt(p[5], 4); /* 'ux' uid size */ + assertEqualInt(i4(p + 6), file_uid); /* 'Ux' UID */ + assertEqualInt(p[10], 4); /* 'ux' gid size */ + assertEqualInt(i4(p + 11), file_gid); /* 'Ux' GID */ + p += 4 + i2(p + 2); + + assertEqualInt(i2(p), 0x6c78); /* 'xl' experimental extension block */ + assertEqualInt(i2(p + 2), 9); /* size */ + assertEqualInt(p[4], 7); /* bitmap of fields in this block */ + assertEqualInt(i2(p + 5) >> 8, 3); /* System & version made by */ + assertEqualInt(i2(p + 7), 0); /* internal file attributes */ + assertEqualInt(i4(p + 9) >> 16 & 01777, file_perm); /* external file attributes */ + p += 4 + i2(p + 2); + + /* Just in case: Report any extra extensions. */ + while (p < extension_end) { + failure("Unexpected extension 0x%04X", i2(p)); + assert(0); + p += 4 + i2(p + 2); + } + + /* Should have run exactly to end of extra data. */ + assert(p == extension_end); + + /* Data descriptor should follow compressed data. */ + while (p < central_header && memcmp(p, "PK\007\010", 4) != 0) + ++p; + assertEqualMem(p, "PK\007\010", 4); + assertEqualInt(i4(p + 4), crc); /* CRC-32 */ + /* assertEqualInt(i4(p + 8), ???); */ /* compressed size */ + assertEqualInt(i4(p + 12), sizeof(file_data)); /* uncompressed size */ + + /* Central directory should immediately follow the only entry. */ + assert(p + 16 == central_header); + + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_zip_file_zip64.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_zip_file_zip64.c new file mode 100644 index 0000000..71da986 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_zip_file_zip64.c @@ -0,0 +1,285 @@ +/*- + * Copyright (c) 2003-2008 Tim Kientzle + * Copyright (c) 2008 Anselm Strauss + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Development supported by Google Summer of Code 2008. + */ + +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_format_zip.c 201247 2009-12-30 05:59:21Z kientzle $"); + +/* + * Detailed byte-for-byte verification of the format of a zip archive + * with a single file written to it that uses Zip64 extensions. + */ + +static unsigned long +bitcrc32(unsigned long c, void *_p, size_t s) +{ + /* This is a drop-in replacement for crc32() from zlib. + * Libarchive should be able to correctly generate + * uncompressed zip archives (including correct CRCs) even + * when zlib is unavailable, and this function helps us verify + * that. Yes, this is very, very slow and unsuitable for + * production use, but it's correct, compact, and works well + * enough for this particular usage. Libarchive internally + * uses a much more efficient implementation. */ + const unsigned char *p = _p; + int bitctr; + + if (p == NULL) + return (0); + + for (; s > 0; --s) { + c ^= *p++; + for (bitctr = 8; bitctr > 0; --bitctr) { + if (c & 1) c = (c >> 1); + else c = (c >> 1) ^ 0xedb88320; + c ^= 0x80000000; + } + } + return (c); +} + +/* Quick and dirty: Read 2-byte and 4-byte integers from Zip file. */ +static unsigned i2(const unsigned char *p) { return ((p[0] & 0xff) | ((p[1] & 0xff) << 8)); } +static unsigned i4(const unsigned char *p) { return (i2(p) | (i2(p + 2) << 16)); } +/* We're only working with small values here; ignore the 4 high bytes. */ +static unsigned i8(const unsigned char *p) { return (i4(p)); } + +DEFINE_TEST(test_write_format_zip_file_zip64) +{ + struct archive *a; + struct archive_entry *ae; + time_t t = 1234567890; + struct tm *tm = localtime(&t); + size_t used, buffsize = 1000000; + unsigned long crc; + int file_perm = 00644; + int zip_version = 45; + int zip_compression = 8; + short file_uid = 10, file_gid = 20; + unsigned char *buff, *buffend, *p; + unsigned char *central_header, *local_header, *eocd, *eocd_record; + unsigned char *extension_start, *extension_end; + char file_data[] = {'1', '2', '3', '4', '5', '6', '7', '8'}; + const char *file_name = "file"; + +#ifndef HAVE_ZLIB_H + zip_compression = 0; +#endif + + buff = malloc(buffsize); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "zip:zip64")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "zip:experimental")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, file_name); + archive_entry_set_mode(ae, AE_IFREG | file_perm); + archive_entry_set_size(ae, sizeof(file_data)); + archive_entry_set_uid(ae, file_uid); + archive_entry_set_gid(ae, file_gid); + archive_entry_set_mtime(ae, t, 0); + assertEqualInt(0, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(8, archive_write_data(a, file_data, sizeof(file_data))); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + buffend = buff + used; + dumpfile("constructed.zip", buff, used); + + /* Verify "End of Central Directory" record. */ + /* Get address of end-of-central-directory record. */ + eocd_record = p = buffend - 22; /* Assumes there is no zip comment field. */ + failure("End-of-central-directory begins with PK\\005\\006 signature"); + assertEqualMem(p, "PK\005\006", 4); + failure("This must be disk 0"); + assertEqualInt(i2(p + 4), 0); + failure("Central dir must start on disk 0"); + assertEqualInt(i2(p + 6), 0); + failure("All central dir entries are on this disk"); + assertEqualInt(i2(p + 8), i2(p + 10)); + eocd = buff + i4(p + 12) + i4(p + 16); + failure("no zip comment"); + assertEqualInt(i2(p + 20), 0); + + /* Get address of first entry in central directory. */ + central_header = p = buff + i4(buffend - 6); + failure("Central file record at offset %d should begin with" + " PK\\001\\002 signature", + i4(buffend - 10)); + + /* Verify file entry in central directory. */ + assertEqualMem(p, "PK\001\002", 4); /* Signature */ + assertEqualInt(i2(p + 4), 3 * 256 + zip_version); /* Version made by */ + assertEqualInt(i2(p + 6), zip_version); /* Version needed to extract */ + assertEqualInt(i2(p + 8), 8); /* Flags */ + assertEqualInt(i2(p + 10), zip_compression); /* Compression method */ + assertEqualInt(i2(p + 12), (tm->tm_hour * 2048) + (tm->tm_min * 32) + (tm->tm_sec / 2)); /* File time */ + assertEqualInt(i2(p + 14), ((tm->tm_year - 80) * 512) + ((tm->tm_mon + 1) * 32) + tm->tm_mday); /* File date */ + crc = bitcrc32(0, file_data, sizeof(file_data)); + assertEqualInt(i4(p + 16), crc); /* CRC-32 */ + /* assertEqualInt(i4(p + 20), sizeof(file_data)); */ /* Compressed size */ + assertEqualInt(i4(p + 24), sizeof(file_data)); /* Uncompressed size */ + assertEqualInt(i2(p + 28), strlen(file_name)); /* Pathname length */ + /* assertEqualInt(i2(p + 30), 28); */ /* Extra field length: See below */ + assertEqualInt(i2(p + 32), 0); /* File comment length */ + assertEqualInt(i2(p + 34), 0); /* Disk number start */ + assertEqualInt(i2(p + 36), 0); /* Internal file attrs */ + assertEqualInt(i4(p + 38) >> 16 & 01777, file_perm); /* External file attrs */ + assertEqualInt(i4(p + 42), 0); /* Offset of local header */ + assertEqualMem(p + 46, file_name, strlen(file_name)); /* Pathname */ + p = extension_start = central_header + 46 + strlen(file_name); + extension_end = extension_start + i2(central_header + 30); + + assertEqualInt(i2(p), 0x5455); /* 'UT' extension header */ + assertEqualInt(i2(p + 2), 5); /* 'UT' size */ + assertEqualInt(p[4], 1); /* 'UT' flags */ + assertEqualInt(i4(p + 5), t); /* 'UT' mtime */ + p += 4 + i2(p + 2); + + assertEqualInt(i2(p), 0x7875); /* 'ux' extension header */ + assertEqualInt(i2(p + 2), 11); /* 'ux' size */ + /* TODO: verify 'ux' contents */ + p += 4 + i2(p + 2); + + /* Note: We don't expect to see zip64 extension in the central + * directory, since the writer knows the actual full size by + * the time it is ready to write the central directory and has + * no reason to insert it then. Info-Zip seems to do the same + * thing. */ + + /* Just in case: Report any extra extensions. */ + while (p < extension_end) { + failure("Unexpected extension 0x%04X", i2(p)); + assert(0); + p += 4 + i2(p + 2); + } + + /* Should have run exactly to end of extra data. */ + assert(p == extension_end); + + assert(p == eocd); + + /* After Central dir, we find Zip64 eocd and Zip64 eocd locator. */ + assertEqualMem(p, "PK\006\006", 4); /* Zip64 eocd */ + assertEqualInt(i8(p + 4), 44); /* We're using v1 Zip64 eocd */ + assertEqualInt(i2(p + 12), 45); /* Written by Version 4.5 */ + assertEqualInt(i2(p + 14), 45); /* Needs version 4.5 to extract */ + assertEqualInt(i4(p + 16), 0); /* This is disk #0 */ + assertEqualInt(i4(p + 20), 0); /* Dir starts on disk #0 */ + assertEqualInt(i8(p + 24), 1); /* 1 entry on this disk */ + assertEqualInt(i8(p + 32), 1); /* 1 entry total */ + assertEqualInt(i8(p + 40), eocd - central_header); /* size of cd */ + assertEqualInt(i8(p + 48), central_header - buff); /* start of cd */ + p += 12 + i8(p + 4); + + assertEqualMem(p, "PK\006\007", 4); /* Zip64 eocd locator */ + assertEqualInt(i4(p + 4), 0); /* Zip64 eocd is on disk #0 */ + assertEqualInt(i8(p + 8), eocd - buff); /* Offset of Zip64 eocd */ + assertEqualInt(i4(p + 16), 1); /* 1 disk */ + p += 20; + + /* Regular EOCD immediately follows Zip64 records. */ + assert(p == eocd_record); + + /* Verify local header of file entry. */ + p = local_header = buff; + assertEqualMem(p, "PK\003\004", 4); /* Signature */ + assertEqualInt(i2(p + 4), zip_version); /* Version needed to extract */ + assertEqualInt(i2(p + 6), 8); /* Flags */ + assertEqualInt(i2(p + 8), zip_compression); /* Compression method */ + assertEqualInt(i2(p + 10), (tm->tm_hour * 2048) + (tm->tm_min * 32) + (tm->tm_sec / 2)); /* File time */ + assertEqualInt(i2(p + 12), ((tm->tm_year - 80) * 512) + ((tm->tm_mon + 1) * 32) + tm->tm_mday); /* File date */ + assertEqualInt(i4(p + 14), 0); /* CRC-32 */ + /* assertEqualInt(i4(p + 18), sizeof(file_data)); */ /* Compressed size */ + /* assertEqualInt(i4(p + 22), sizeof(file_data)); */ /* Uncompressed size not stored because we're using length-at-end. */ + assertEqualInt(i2(p + 26), strlen(file_name)); /* Pathname length */ + assertEqualInt(i2(p + 28), 57); /* Extra field length */ + assertEqualMem(p + 30, file_name, strlen(file_name)); /* Pathname */ + p = extension_start = local_header + 30 + strlen(file_name); + extension_end = extension_start + i2(local_header + 28); + + assertEqualInt(i2(p), 0x5455); /* 'UT' extension header */ + assertEqualInt(i2(p + 2), 5); /* 'UT' size */ + assertEqualInt(p[4], 1); /* 'UT' flags */ + assertEqualInt(i4(p + 5), t); /* 'UT' mtime */ + p += 4 + i2(p + 2); + + assertEqualInt(i2(p), 0x7875); /* 'ux' extension header */ + assertEqualInt(i2(p + 2), 11); /* 'ux' size */ + assertEqualInt(p[4], 1); /* 'ux' version */ + assertEqualInt(p[5], 4); /* 'ux' uid size */ + assertEqualInt(i4(p + 6), file_uid); /* 'Ux' UID */ + assertEqualInt(p[10], 4); /* 'ux' gid size */ + assertEqualInt(i4(p + 11), file_gid); /* 'Ux' GID */ + p += 4 + i2(p + 2); + + assertEqualInt(i2(p), 0x0001); /* Zip64 extension header */ + assertEqualInt(i2(p + 2), 16); /* size */ + assertEqualInt(i8(p + 4), 8); /* uncompressed file size */ + /* compressed file size we can't verify here */ + p += 4 + i2(p + 2); + + assertEqualInt(i2(p), 0x6c78); /* 'xl' experimental extension header */ + assertEqualInt(i2(p + 2), 9); /* size */ + assertEqualInt(p[4], 7); /* bitmap of included fields */ + assertEqualInt(i2(p + 5) >> 8, 3); /* system & version made by */ + assertEqualInt(i2(p + 7), 0); /* internal file attributes */ + assertEqualInt(i4(p + 9) >> 16 & 01777, file_perm); /* external file attributes */ + p += 4 + i2(p + 2); + + /* Just in case: Report any extra extensions. */ + while (p < extension_end) { + failure("Unexpected extension 0x%04X", i2(p)); + assert(0); + p += 4 + i2(p + 2); + } + + /* Should have run exactly to end of extra data. */ + assert(p == extension_end); + + /* Data descriptor should follow compressed data. */ + while (p < central_header && memcmp(p, "PK\007\010", 4) != 0) + ++p; + assertEqualMem(p, "PK\007\010", 4); + assertEqualInt(i4(p + 4), crc); /* CRC-32 */ + /* assertEqualInt(i8(p + 8), ???); */ /* compressed size */ + assertEqualInt(i8(p + 16), sizeof(file_data)); /* uncompressed size */ + + /* Central directory should immediately follow the only entry. */ + assert(p + 24 == central_header); + + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_zip_large.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_zip_large.c new file mode 100644 index 0000000..2f98c6d --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_zip_large.c @@ -0,0 +1,473 @@ +/*- + * Copyright (c) 2003-2007,2013 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +/* + * This is a somewhat tricky test that verifies the ability to + * write and read very large entries to zip archives. + * + * See test_tar_large.c for more information about the machinery + * being used here. + */ + +static size_t nullsize; +static void *nulldata; + +struct fileblock { + struct fileblock *next; + int size; + void *buff; + int64_t gap_size; /* Size of following gap */ +}; + +struct fileblocks { + int64_t filesize; + int64_t fileposition; + int64_t gap_remaining; + void *buff; + struct fileblock *first; + struct fileblock *current; + struct fileblock *last; +}; + +/* The following size definitions simplify things below. */ +#define KB ((int64_t)1024) +#define MB ((int64_t)1024 * KB) +#define GB ((int64_t)1024 * MB) +#define TB ((int64_t)1024 * GB) + +static int64_t memory_read_skip(struct archive *, void *, int64_t request); +static ssize_t memory_read(struct archive *, void *, const void **buff); +static ssize_t memory_write(struct archive *, void *, const void *, size_t); + +static uint16_t le16(const void *_p) { + const uint8_t *p = _p; + return p[0] | (p[1] << 8); +} + +static uint32_t le32(const void *_p) { + const uint8_t *p = _p; + return le16(p) | ((uint32_t)le16(p + 2) << 16); +} + +static uint64_t le64(const void *_p) { + const uint8_t *p = _p; + return le32(p) | ((uint64_t)le32(p + 4) << 32); +} + +static ssize_t +memory_write(struct archive *a, void *_private, const void *buff, size_t size) +{ + struct fileblocks *private = _private; + struct fileblock *block; + + (void)a; + + if ((const char *)nulldata <= (const char *)buff + && (const char *)buff < (const char *)nulldata + nullsize) { + /* We don't need to store a block of gap data. */ + private->last->gap_size += (int64_t)size; + } else { + /* Yes, we're assuming the very first write is metadata. */ + /* It's header or metadata, copy and save it. */ + block = (struct fileblock *)malloc(sizeof(*block)); + memset(block, 0, sizeof(*block)); + block->size = (int)size; + block->buff = malloc(size); + memcpy(block->buff, buff, size); + if (private->last == NULL) { + private->first = private->last = block; + } else { + private->last->next = block; + private->last = block; + } + block->next = NULL; + } + private->filesize += size; + return ((long)size); +} + +static ssize_t +memory_read(struct archive *a, void *_private, const void **buff) +{ + struct fileblocks *private = _private; + ssize_t size; + + (void)a; + + while (private->current != NULL && private->buff == NULL && private->gap_remaining == 0) { + private->current = private->current->next; + if (private->current != NULL) { + private->buff = private->current->buff; + private->gap_remaining = private->current->gap_size; + } + } + + if (private->current == NULL) + return (0); + + /* If there's real data, return that. */ + if (private->buff != NULL) { + *buff = private->buff; + size = ((char *)private->current->buff + private->current->size) + - (char *)private->buff; + private->buff = NULL; + private->fileposition += size; + return (size); + } + + /* Big gap: too big to return all at once, so just return some. */ + if (private->gap_remaining > (int64_t)nullsize) { + private->gap_remaining -= nullsize; + *buff = nulldata; + private->fileposition += nullsize; + return (nullsize); + } + + /* Small gap: finish the gap and prep for next block. */ + if (private->gap_remaining > 0) { + size = (ssize_t)private->gap_remaining; + *buff = nulldata; + private->gap_remaining = 0; + private->fileposition += size; + + private->current = private->current->next; + if (private->current != NULL) { + private->buff = private->current->buff; + private->gap_remaining = private->current->gap_size; + } + + return (size); + } + fprintf(stderr, "\n\n\nInternal failure\n\n\n"); + exit(1); +} + +static int +memory_read_open(struct archive *a, void *_private) +{ + struct fileblocks *private = _private; + + (void)a; /* UNUSED */ + + private->current = private->first; + private->fileposition = 0; + if (private->current != NULL) { + private->buff = private->current->buff; + private->gap_remaining = private->current->gap_size; + } + return (ARCHIVE_OK); +} + +static int64_t +memory_read_seek(struct archive *a, void *_private, int64_t offset, int whence) +{ + struct fileblocks *private = _private; + + (void)a; + if (whence == SEEK_END) { + offset = private->filesize + offset; + } else if (whence == SEEK_CUR) { + offset = private->fileposition + offset; + } + + if (offset < 0) { + fprintf(stderr, "\n\n\nInternal failure: negative seek\n\n\n"); + exit(1); + } + + /* We've converted the request into a SEEK_SET. */ + private->fileposition = offset; + + /* Walk the block list to find the new position. */ + offset = 0; + private->current = private->first; + while (private->current != NULL) { + if (offset + private->current->size > private->fileposition) { + /* Position is in this block. */ + private->buff = (char *)private->current->buff + + private->fileposition - offset; + private->gap_remaining = private->current->gap_size; + return private->fileposition; + } + offset += private->current->size; + if (offset + private->current->gap_size > private->fileposition) { + /* Position is in this gap. */ + private->buff = NULL; + private->gap_remaining = private->current->gap_size + - (private->fileposition - offset); + return private->fileposition; + } + offset += private->current->gap_size; + /* Skip to next block. */ + private->current = private->current->next; + } + if (private->fileposition == private->filesize) { + return private->fileposition; + } + fprintf(stderr, "\n\n\nInternal failure: over-sized seek\n\n\n"); + exit(1); +} + +static int64_t +memory_read_skip(struct archive *a, void *_private, int64_t skip) +{ + struct fileblocks *private = _private; + int64_t old_position = private->fileposition; + int64_t new_position = memory_read_seek(a, _private, skip, SEEK_CUR); + return (new_position - old_position); +} + +static struct fileblocks * +fileblocks_new(void) +{ + struct fileblocks *fileblocks; + + fileblocks = calloc(1, sizeof(struct fileblocks)); + return fileblocks; +} + +static void +fileblocks_free(struct fileblocks *fileblocks) +{ + while (fileblocks->first != NULL) { + struct fileblock *b = fileblocks->first; + fileblocks->first = fileblocks->first->next; + free(b->buff); + free(b); + } + free(fileblocks); +} + + +/* The sizes of the entries we're going to generate. */ +static int64_t test_sizes[] = { + /* Test for 32-bit signed overflow. */ + 2 * GB - 1, 2 * GB, 2 * GB + 1, + /* Test for 32-bit unsigned overflow. */ + 4 * GB - 1, 4 * GB, 4 * GB + 1, + /* And beyond ... because we can. */ + 16 * GB - 1, 16 * GB, 16 * GB + 1, + 64 * GB - 1, 64 * GB, 64 * GB + 1, + 256 * GB - 1, 256 * GB, 256 * GB + 1, + 1 * TB, + 0 +}; + + +static void +verify_large_zip(struct archive *a, struct fileblocks *fileblocks) +{ + char namebuff[64]; + struct archive_entry *ae; + int i; + + assertEqualIntA(a, ARCHIVE_OK, + archive_read_set_options(a, "zip:ignorecrc32")); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_set_open_callback(a, memory_read_open)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_set_read_callback(a, memory_read)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_set_skip_callback(a, memory_read_skip)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_set_seek_callback(a, memory_read_seek)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_set_callback_data(a, fileblocks)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open1(a)); + + /* + * Read entries back. + */ + for (i = 0; test_sizes[i] > 0; i++) { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae)); + sprintf(namebuff, "file_%d", i); + assertEqualString(namebuff, archive_entry_pathname(ae)); + assertEqualInt(test_sizes[i], archive_entry_size(ae)); + } + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualString("lastfile", archive_entry_pathname(ae)); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); +} + +DEFINE_TEST(test_write_format_zip_large) +{ + int i; + char namebuff[64]; + struct fileblocks *fileblocks = fileblocks_new(); + struct archive_entry *ae; + struct archive *a; + const char *p; + const char *cd_start, *zip64_eocd, *zip64_locator, *eocd; + int64_t cd_size; + char *buff; + int64_t filesize; + size_t writesize, buffsize, s; + + nullsize = (size_t)(1 * MB); + nulldata = malloc(nullsize); + memset(nulldata, 0xAA, nullsize); + + /* + * Open an archive for writing. + */ + a = archive_write_new(); + archive_write_set_format_zip(a); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "zip:compression=store")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "zip:fakecrc32")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 0)); /* No buffering. */ + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open(a, fileblocks, NULL, memory_write, NULL)); + + /* + * Write a series of large files to it. + */ + for (i = 0; test_sizes[i] != 0; i++) { + assert((ae = archive_entry_new()) != NULL); + sprintf(namebuff, "file_%d", i); + archive_entry_copy_pathname(ae, namebuff); + archive_entry_set_mode(ae, S_IFREG | 0755); + filesize = test_sizes[i]; + archive_entry_set_size(ae, filesize); + + assertEqualIntA(a, ARCHIVE_OK, + archive_write_header(a, ae)); + archive_entry_free(ae); + + /* + * Write the actual data to the archive. + */ + while (filesize > 0) { + writesize = nullsize; + if ((int64_t)writesize > filesize) + writesize = (size_t)filesize; + assertEqualIntA(a, (int)writesize, + (int)archive_write_data(a, nulldata, writesize)); + filesize -= writesize; + } + } + + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "lastfile"); + archive_entry_set_mode(ae, S_IFREG | 0755); + assertA(0 == archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Read back with seeking reader: + */ + a = archive_read_new(); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_zip_seekable(a)); + verify_large_zip(a, fileblocks); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Read back with streaming reader: + */ + a = archive_read_new(); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_zip_streamable(a)); + verify_large_zip(a, fileblocks); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* + * Manually verify some of the final bytes of the archives. + */ + /* Collect the final bytes together */ +#define FINAL_SIZE 8192 + buff = malloc(FINAL_SIZE); + buffsize = 0; + memory_read_open(NULL, fileblocks); + memory_read_seek(NULL, fileblocks, -FINAL_SIZE, SEEK_END); + while ((s = memory_read(NULL, fileblocks, (const void **)&p)) > 0) { + memcpy(buff + buffsize, p, s); + buffsize += s; + } + assertEqualInt(buffsize, FINAL_SIZE); + + p = buff + buffsize; + + /* Verify regular end-of-central-directory record */ + eocd = p - 22; + assertEqualMem(eocd, "PK\005\006\0\0\0\0", 8); + assertEqualMem(eocd + 8, "\021\0\021\0", 4); /* 17 entries total */ + cd_size = le32(eocd + 12); + /* Start of CD offset should be 0xffffffff */ + assertEqualMem(eocd + 16, "\xff\xff\xff\xff", 4); + assertEqualMem(eocd + 20, "\0\0", 2); /* No Zip comment */ + + /* Verify Zip64 locator */ + zip64_locator = p - 42; + assertEqualMem(zip64_locator, "PK\006\007\0\0\0\0", 8); + zip64_eocd = p - (fileblocks->filesize - le64(zip64_locator + 8)); + assertEqualMem(zip64_locator + 16, "\001\0\0\0", 4); + + /* Verify Zip64 end-of-cd record. */ + assert(zip64_eocd == p - 98); + assertEqualMem(zip64_eocd, "PK\006\006", 4); + assertEqualInt(44, le64(zip64_eocd + 4)); // Size of EoCD record - 12 + assertEqualMem(zip64_eocd + 12, "\055\0", 2); // Made by version: 45 + assertEqualMem(zip64_eocd + 14, "\055\0", 2); // Requires version: 45 + assertEqualMem(zip64_eocd + 16, "\0\0\0\0", 4); // This disk + assertEqualMem(zip64_eocd + 20, "\0\0\0\0", 4); // Total disks + assertEqualInt(17, le64(zip64_eocd + 24)); // Entries on this disk + assertEqualInt(17, le64(zip64_eocd + 32)); // Total entries + cd_size = le64(zip64_eocd + 40); + cd_start = p - (fileblocks->filesize - le64(zip64_eocd + 48)); + + assert(cd_start + cd_size == zip64_eocd); + + assertEqualInt(le64(zip64_eocd + 48) // Start of CD + + cd_size + + 56 // Size of Zip64 EOCD + + 20 // Size of Zip64 locator + + 22, // Size of EOCD + fileblocks->filesize); + + // TODO: Scan entire Central Directory, sanity-check all data + assertEqualMem(cd_start, "PK\001\002", 4); + + fileblocks_free(fileblocks); + free(buff); + free(nulldata); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_zip_zip64.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_zip_zip64.c new file mode 100644 index 0000000..c5f00a2 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_format_zip_zip64.c @@ -0,0 +1,69 @@ +/*- + * Copyright (c) 2014 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +__FBSDID("$FreeBSD$"); + +static void +verify_zip_filesize(uint64_t size, int expected) +{ + struct archive *a; + struct archive_entry *ae; + char buff[256]; + size_t used; + + /* Zip format: Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); + /* Disable Zip64 extensions. */ + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_format_option(a, "zip", "zip64", NULL)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_pathname(ae, "test"); + archive_entry_set_mode(ae, AE_IFREG | 0644); + archive_entry_set_size(ae, size); + assertEqualInt(expected, archive_write_header(a, ae)); + + archive_entry_free(ae); + + /* Don't actually write 4GB! ;-) */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); +} + +DEFINE_TEST(test_write_format_zip_zip64_oversize) +{ + /* With Zip64 extensions disabled, we should be + * able to write a file with at most 4G-1 bytes. */ + + /* Note: Tar writer pads file to declared size when the file + * is closed. If Zip writer is changed to behave the same + * way, it will be much harder to test the first case here. */ + verify_zip_filesize(0xffffffffLL, ARCHIVE_OK); + + verify_zip_filesize(0x100000000LL, ARCHIVE_FAILED); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_open_memory.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_open_memory.c new file mode 100644 index 0000000..3dbed11 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_open_memory.c @@ -0,0 +1,84 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_open_memory.c 189308 2009-03-03 17:02:51Z kientzle $"); + +/* Try to force archive_write_open_memory.c to write past the end of an array. */ +static unsigned char buff[16384]; + +DEFINE_TEST(test_write_open_memory) +{ + unsigned int i; + struct archive *a; + struct archive_entry *ae; + const char *name="/tmp/test"; + + /* Create a simple archive_entry. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_pathname(ae, name); + archive_entry_set_mode(ae, S_IFREG); + assertEqualString(archive_entry_pathname(ae), name); + + /* Try writing with different buffer sizes. */ + /* Make sure that we get failure on too-small buffers, success on + * large enough ones. */ + for (i = 100; i < 1600; i++) { + size_t used; + size_t blocksize = 94; + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_in_last_block(a, 1)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, (int)blocksize)); + buff[i] = 0xAE; + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, i, &used)); + /* If buffer is smaller than a tar header, this should fail. */ + if (i < (511/blocksize)*blocksize) + assertEqualIntA(a, ARCHIVE_FATAL, + archive_write_header(a,ae)); + else + assertEqualIntA(a, ARCHIVE_OK, + archive_write_header(a, ae)); + /* If buffer is smaller than a tar header plus 1024 byte + * end-of-archive marker, then this should fail. */ + failure("buffer size=%d\n", (int)i); + if (i < 1536) + assertEqualIntA(a, ARCHIVE_FATAL, + archive_write_close(a)); + else { + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(used, archive_filter_bytes(a, -1)); + assertEqualInt(archive_filter_bytes(a, -1), + archive_filter_bytes(a, 0)); + } + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(buff[i], 0xAE); + assert(used <= i); + } + archive_entry_free(ae); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_write_read_format_zip.c b/dependencies/libarchive-3.4.2/libarchive/test/test_write_read_format_zip.c new file mode 100644 index 0000000..4f39489 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_write_read_format_zip.c @@ -0,0 +1,751 @@ +/*- + * Copyright (c) 2003-2008 Tim Kientzle + * Copyright (c) 2008 Anselm Strauss + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Development supported by Google Summer of Code 2008. + */ + +#include "test.h" +__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_format_zip.c 201247 2009-12-30 05:59:21Z kientzle $"); + +/* + * These tests verify that our reader can read files + * created by our writer. + */ + +/* + * Write a variety of different file types into the archive. + */ +static void +write_contents(struct archive *a) +{ + struct archive_entry *ae; + + /* + * First write things with the "default" compression. + * The library will choose "deflate" for most things if it's + * available, else "store". + */ + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + archive_entry_copy_pathname(ae, "file"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + archive_entry_set_size(ae, 8); + assertEqualInt(0, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(8, archive_write_data(a, "12345678", 9)); + assertEqualInt(0, archive_write_data(a, "1", 1)); + + /* + * Write another file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + archive_entry_copy_pathname(ae, "file2"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + archive_entry_set_size(ae, 4); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(4, archive_write_data(a, "1234", 4)); + + /* + * Write a file with an unknown size. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 2, 15); + archive_entry_copy_pathname(ae, "file3"); + archive_entry_set_mode(ae, AE_IFREG | 0621); + archive_entry_unset_size(ae); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(5, archive_write_data(a, "mnopq", 5)); + + /* + * Write symbolic link. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(10, archive_entry_mtime_nsec(ae)); + archive_entry_copy_pathname(ae, "symlink"); + assertEqualString("symlink", archive_entry_pathname(ae)); + archive_entry_copy_symlink(ae, "file1"); + assertEqualString("file1", archive_entry_symlink(ae)); + archive_entry_set_mode(ae, AE_IFLNK | 0755); + assertEqualInt((AE_IFLNK | 0755), archive_entry_mode(ae)); + archive_entry_set_size(ae, 4); + + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* + * Write a directory to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 11, 110); + archive_entry_copy_pathname(ae, "dir"); + archive_entry_set_mode(ae, S_IFDIR | 0755); + archive_entry_set_size(ae, 512); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + failure("size should be zero so that applications know not to write"); + assertEqualInt(0, archive_entry_size(ae)); + archive_entry_free(ae); + assertEqualIntA(a, 0, archive_write_data(a, "12345678", 9)); + + /* + * Force "deflate" compression if the platform supports it. + */ +#ifdef HAVE_ZLIB_H + assertEqualIntA(a, ARCHIVE_OK, archive_write_zip_set_compression_deflate(a)); + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + archive_entry_copy_pathname(ae, "file_deflate"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + archive_entry_set_size(ae, 8); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(8, archive_write_data(a, "12345678", 9)); + assertEqualInt(0, archive_write_data(a, "1", 1)); + + /* + * Write another file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + archive_entry_copy_pathname(ae, "file2_deflate"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + archive_entry_set_size(ae, 4); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(4, archive_write_data(a, "1234", 4)); + + /* + * Write a file with an unknown size. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 2, 15); + archive_entry_copy_pathname(ae, "file3_deflate"); + archive_entry_set_mode(ae, AE_IFREG | 0621); + archive_entry_unset_size(ae); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(5, archive_write_data(a, "ghijk", 5)); + + /* + * Write symbolic like file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + archive_entry_copy_pathname(ae, "symlink_deflate"); + archive_entry_copy_symlink(ae, "file1"); + archive_entry_set_mode(ae, AE_IFLNK | 0755); + archive_entry_set_size(ae, 4); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* + * Write a directory to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 11, 110); + archive_entry_copy_pathname(ae, "dir_deflate"); + archive_entry_set_mode(ae, S_IFDIR | 0755); + archive_entry_set_size(ae, 512); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + failure("size should be zero so that applications know not to write"); + assertEqualInt(0, archive_entry_size(ae)); + archive_entry_free(ae); + assertEqualIntA(a, 0, archive_write_data(a, "12345678", 9)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a)); +#endif + + /* + * Now write a bunch of entries with "store" compression. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_zip_set_compression_store(a)); + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + archive_entry_copy_pathname(ae, "file_stored"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + archive_entry_set_size(ae, 8); + assertEqualInt(0, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(8, archive_write_data(a, "12345678", 9)); + assertEqualInt(0, archive_write_data(a, "1", 1)); + + /* + * Write another file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + archive_entry_copy_pathname(ae, "file2_stored"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + archive_entry_set_size(ae, 4); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(4, archive_write_data(a, "ACEG", 4)); + + /* + * Write a file with an unknown size. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 2, 15); + archive_entry_copy_pathname(ae, "file3_stored"); + archive_entry_set_mode(ae, AE_IFREG | 0621); + archive_entry_unset_size(ae); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(5, archive_write_data(a, "ijklm", 5)); + + /* + * Write symbolic like file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + archive_entry_copy_pathname(ae, "symlink_stored"); + archive_entry_copy_symlink(ae, "file1"); + archive_entry_set_mode(ae, AE_IFLNK | 0755); + archive_entry_set_size(ae, 4); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* + * Write a directory to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 11, 110); + archive_entry_copy_pathname(ae, "dir_stored"); + archive_entry_set_mode(ae, S_IFDIR | 0755); + archive_entry_set_size(ae, 512); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + failure("size should be zero so that applications know not to write"); + assertEqualInt(0, archive_entry_size(ae)); + archive_entry_free(ae); + assertEqualIntA(a, 0, archive_write_data(a, "12345678", 9)); + + + /* Close out the archive. */ + assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); +} + +/* + * Read back all of the entries and verify their values. + */ +static void +verify_contents(struct archive *a, int seeking, int improved_streaming) +{ + char filedata[64]; + struct archive_entry *ae; + + /* + * Default compression options: + */ + + /* Read and verify first file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + /* Zip doesn't store high-resolution mtime. */ + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file", archive_entry_pathname(ae)); + if (seeking || improved_streaming) { + assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); + } + assertEqualInt(8, archive_entry_size(ae)); + assert(archive_entry_size_is_set(ae)); + assertEqualIntA(a, 8, + archive_read_data(a, filedata, sizeof(filedata))); + assertEqualMem(filedata, "12345678", 8); + + + /* Read the second file back. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file2", archive_entry_pathname(ae)); + if (seeking || improved_streaming) { + assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); + } + assertEqualInt(4, archive_entry_size(ae)); + assert(archive_entry_size_is_set(ae)); + assertEqualIntA(a, 4, + archive_read_data(a, filedata, sizeof(filedata))); + assertEqualMem(filedata, "1234", 4); + + /* Read the third file back. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file3", archive_entry_pathname(ae)); + if (seeking || improved_streaming) { + assertEqualInt(AE_IFREG | 0621, archive_entry_mode(ae)); + } + if (seeking) { + assertEqualInt(5, archive_entry_size(ae)); + } else { + assertEqualInt(0, archive_entry_size_is_set(ae)); + } + assertEqualIntA(a, 5, + archive_read_data(a, filedata, sizeof(filedata))); + assertEqualMem(filedata, "mnopq", 5); + + /* Read symlink. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("symlink", archive_entry_pathname(ae)); + if (seeking || improved_streaming) { + assertEqualInt(AE_IFLNK | 0755, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualString("file1", archive_entry_symlink(ae)); + } else { + /* Streaming cannot read file type, so + * symlink body shows as regular file contents. */ + assertEqualInt(AE_IFREG | 0664, archive_entry_mode(ae)); + assertEqualInt(5, archive_entry_size(ae)); + assert(archive_entry_size_is_set(ae)); + } + + /* Read the dir entry back. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(11, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("dir/", archive_entry_pathname(ae)); + if (seeking || improved_streaming) + assertEqualInt(AE_IFDIR | 0755, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assert(archive_entry_size_is_set(ae)); + assertEqualIntA(a, 0, archive_read_data(a, filedata, 10)); + +#ifdef HAVE_ZLIB_H + /* + * Deflate compression option: + */ + + /* Read and verify first file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + /* Zip doesn't store high-resolution mtime. */ + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file_deflate", archive_entry_pathname(ae)); + if (seeking || improved_streaming) { + assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); + } + assertEqualInt(8, archive_entry_size(ae)); + assert(archive_entry_size_is_set(ae)); + assertEqualIntA(a, 8, + archive_read_data(a, filedata, sizeof(filedata))); + assertEqualMem(filedata, "12345678", 8); + + + /* Read the second file back. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file2_deflate", archive_entry_pathname(ae)); + if (seeking || improved_streaming) { + assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); + } + assertEqualInt(4, archive_entry_size(ae)); + assert(archive_entry_size_is_set(ae)); + assertEqualIntA(a, 4, + archive_read_data(a, filedata, sizeof(filedata))); + assertEqualMem(filedata, "1234", 4); + + /* Read the third file back. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file3_deflate", archive_entry_pathname(ae)); + if (seeking || improved_streaming) { + assertEqualInt(AE_IFREG | 0621, archive_entry_mode(ae)); + } + if (seeking) { + assertEqualInt(5, archive_entry_size(ae)); + } else { + assertEqualInt(0, archive_entry_size_is_set(ae)); + } + assertEqualIntA(a, 5, + archive_read_data(a, filedata, sizeof(filedata))); + assertEqualMem(filedata, "ghijk", 4); + + /* Read symlink. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("symlink_deflate", archive_entry_pathname(ae)); + if (seeking || improved_streaming) { + assertEqualInt(AE_IFLNK | 0755, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualString("file1", archive_entry_symlink(ae)); + } else { + assertEqualInt(AE_IFREG | 0664, archive_entry_mode(ae)); + assertEqualInt(5, archive_entry_size(ae)); + assertEqualIntA(a, 5, archive_read_data(a, filedata, 10)); + assertEqualMem(filedata, "file1", 5); + } + + /* Read the dir entry back. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(11, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("dir_deflate/", archive_entry_pathname(ae)); + if (seeking) { + assertEqualInt(AE_IFDIR | 0755, archive_entry_mode(ae)); + } + assertEqualInt(0, archive_entry_size(ae)); + assert(archive_entry_size_is_set(ae)); + assertEqualIntA(a, 0, archive_read_data(a, filedata, 10)); +#endif + + /* + * Store compression option: + */ + + /* Read and verify first file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + /* Zip doesn't store high-resolution mtime. */ + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file_stored", archive_entry_pathname(ae)); + if (seeking || improved_streaming) { + assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); + } + assert(archive_entry_size_is_set(ae)); + assert(archive_entry_size_is_set(ae)); + assertEqualInt(8, archive_entry_size(ae)); + assertEqualIntA(a, 8, + archive_read_data(a, filedata, sizeof(filedata))); + assertEqualMem(filedata, "12345678", 8); + + + /* Read the second file back. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file2_stored", archive_entry_pathname(ae)); + if (seeking || improved_streaming) { + assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); + } + assertEqualInt(4, archive_entry_size(ae)); + assert(archive_entry_size_is_set(ae)); + assertEqualIntA(a, 4, + archive_read_data(a, filedata, sizeof(filedata))); + assertEqualMem(filedata, "ACEG", 4); + + /* Read the third file back. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("file3_stored", archive_entry_pathname(ae)); + if (seeking || improved_streaming) + assertEqualInt(AE_IFREG | 0621, archive_entry_mode(ae)); + if (seeking) { + assertEqualInt(5, archive_entry_size(ae)); + } else { + assertEqualInt(0, archive_entry_size_is_set(ae)); + } + assertEqualIntA(a, 5, + archive_read_data(a, filedata, sizeof(filedata))); + assertEqualMem(filedata, "ijklm", 4); + + /* Read symlink. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("symlink_stored", archive_entry_pathname(ae)); + if (seeking || improved_streaming) { + assertEqualInt(AE_IFLNK | 0755, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualString("file1", archive_entry_symlink(ae)); + } else { + assertEqualInt(AE_IFREG | 0664, archive_entry_mode(ae)); + assertEqualInt(5, archive_entry_size(ae)); + assertEqualIntA(a, 5, archive_read_data(a, filedata, 10)); + assertEqualMem(filedata, "file1", 5); + } + + /* Read the dir entry back. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(11, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("dir_stored/", archive_entry_pathname(ae)); + if (seeking || improved_streaming) + assertEqualInt(AE_IFDIR | 0755, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualIntA(a, 0, archive_read_data(a, filedata, 10)); + + /* Verify the end of the archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +/* + * Do a write-then-read roundtrip. + */ +DEFINE_TEST(test_write_read_format_zip) +{ + struct archive *a; + size_t used; + size_t buffsize = 1000000; + char *buff; + + buff = malloc(buffsize); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + write_contents(a); + dumpfile("constructed.zip", buff, used); + + /* + * Now, read the data back. + */ + /* With the standard memory reader. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + verify_contents(a, 1, 0); + + /* With the test memory reader -- streaming mode. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, buff, used, 7)); + /* Streaming reader doesn't see mode information from Central Directory. */ + verify_contents(a, 0, 0); + + /* With the test memory reader -- seeking mode. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7)); + verify_contents(a, 1, 0); + + free(buff); +} + +/* + * Do a write-then-read roundtrip with 'el' extension enabled. + */ +DEFINE_TEST(test_write_read_format_zip_improved_streaming) +{ + struct archive *a; + size_t used; + size_t buffsize = 1000000; + char *buff; + + buff = malloc(buffsize); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_options(a, "zip:experimental")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + write_contents(a); + dumpfile("constructed.zip", buff, used); + + /* + * Now, read the data back. + */ + /* With the standard memory reader. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + verify_contents(a, 1, 1); + + /* With the test memory reader -- streaming mode. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, buff, used, 7)); + /* Streaming reader doesn't see mode information from Central Directory. */ + verify_contents(a, 0, 1); + + /* With the test memory reader -- seeking mode. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7)); + verify_contents(a, 1, 1); + + free(buff); +} + +/* + * Do a write-then-read roundtrip with Zip64 enabled. + */ +DEFINE_TEST(test_write_read_format_zip64) +{ + struct archive *a; + size_t used; + size_t buffsize = 1000000; + char *buff; + + buff = malloc(buffsize); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_options(a, "zip:zip64")); +#if ZIP_IMPROVED_STREAMING + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_options(a, "zip:experimental")); +#endif + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + write_contents(a); + dumpfile("constructed64.zip", buff, used); + + /* + * Now, read the data back. + */ + /* With the standard memory reader. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + verify_contents(a, 1, 0); + + /* With the test memory reader -- streaming mode. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, buff, used, 7)); + /* Streaming reader doesn't see mode information from Central Directory. */ + verify_contents(a, 0, 0); + + /* With the test memory reader -- seeking mode. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7)); + verify_contents(a, 1, 0); + + free(buff); +} + + +/* + * Do a write-then-read roundtrip with Zip64 enabled and 'el' extension enabled. + */ +DEFINE_TEST(test_write_read_format_zip64_improved_streaming) +{ + struct archive *a; + size_t used; + size_t buffsize = 1000000; + char *buff; + + buff = malloc(buffsize); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_options(a, "zip:zip64")); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_options(a, "zip:experimental")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + write_contents(a); + dumpfile("constructed64.zip", buff, used); + + /* + * Now, read the data back. + */ + /* With the standard memory reader. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + verify_contents(a, 1, 1); + + /* With the test memory reader -- streaming mode. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, buff, used, 7)); + /* Streaming reader doesn't see mode information from Central Directory. */ + verify_contents(a, 0, 1); + + /* With the test memory reader -- seeking mode. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7)); + verify_contents(a, 1, 1); + + free(buff); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_xattr_platform.c b/dependencies/libarchive-3.4.2/libarchive/test/test_xattr_platform.c new file mode 100644 index 0000000..df3f81a --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_xattr_platform.c @@ -0,0 +1,104 @@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * Copyright (c) 2017 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_xattr_platform) +{ +#if !ARCHIVE_XATTR_SUPPORT + skipping("Extended attributes are not supported on this platform"); +#else /* ARCHIVE_XATTR_SUPPORT */ + struct archive *a; + struct archive_entry *ae; + const char *name; + const void *value; + void *rvalue; + size_t size, insize; + int e, r; + const char *attrname = "user.libarchive.test"; + const char *readval = "readval"; + const char *writeval = "writeval"; + + assertMakeFile("readtest", 0644, "a"); + + if (!setXattr("readtest", attrname, readval, strlen(readval) + 1)) { + skipping("Extended attributes are not supported on this " + "filesystem"); + return; + } + + /* Read test */ + assert(NULL != (a = archive_read_disk_new())); + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_pathname(ae, "readtest"); + assertEqualInt(ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + e = archive_entry_xattr_reset(ae); + assert(e > 0); + + r = 0; + while (archive_entry_xattr_next(ae, &name, &value, + &size) == ARCHIVE_OK) { + if (name != NULL && value != NULL && size > 0 && + strcmp(name, attrname) == 0) { + failure("Attribute value does not match"); + assertEqualString((const char *)value, readval); + r = 1; + break; + } + } + failure("Attribute not found: %s", attrname); + assertEqualInt(r, 1); + + archive_entry_free(ae); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + assert(NULL != (a = archive_write_disk_new())); + archive_write_disk_set_options(a, ARCHIVE_EXTRACT_TIME | + ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_XATTR); + + /* Write test */ + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_pathname(ae, "writetest"); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_perm(ae, 0654); + archive_entry_set_mtime(ae, 123456, 7890); + archive_entry_set_size(ae, 0); + archive_entry_xattr_add_entry(ae, attrname, writeval, + strlen(writeval) + 1); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + rvalue = getXattr("writetest", attrname, &insize); + if (assertEqualInt(insize, strlen(writeval) + 1) != 0) + assertEqualMem(rvalue, writeval, insize); + free(rvalue); +#endif +} diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_zip_filename_encoding.c b/dependencies/libarchive-3.4.2/libarchive/test/test_zip_filename_encoding.c new file mode 100644 index 0000000..54cd006 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_zip_filename_encoding.c @@ -0,0 +1,527 @@ +/*- + * Copyright (c) 2011 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +#include + +DEFINE_TEST(test_zip_filename_encoding_UTF8) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } + + /* + * Verify that UTF-8 filenames are correctly stored with + * hdrcharset=UTF-8 option. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " for UTF-8."); + archive_write_free(a); + return; + } + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set a UTF-8 filename. */ + archive_entry_set_pathname(entry, "\xD0\xBF\xD1\x80\xD0\xB8"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* A bit 11 of general purpose flag should be 0x08, + * which indicates the filename charset is UTF-8. */ + assertEqualInt(0x08, buff[7]); + assertEqualMem(buff + 30, "\xD0\xBF\xD1\x80\xD0\xB8", 6); + + /* + * Verify that UTF-8 filenames are correctly stored without + * hdrcharset=UTF-8 option. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set a UTF-8 filename. */ + archive_entry_set_pathname(entry, "\xD0\xBF\xD1\x80\xD0\xB8"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* A bit 11 of general purpose flag should be 0x08, + * which indicates the filename charset is UTF-8. */ + assertEqualInt(0x08, buff[7]); + assertEqualMem(buff + 30, "\xD0\xBF\xD1\x80\xD0\xB8", 6); + + /* + * Verify that A bit 11 of general purpose flag is not set + * when ASCII filenames are stored. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set an ASCII filename. */ + archive_entry_set_pathname(entry, "abcABC"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* A bit 11 of general purpose flag should be 0, + * which indicates the filename charset is unknown. */ + assertEqualInt(0, buff[7]); + assertEqualMem(buff + 30, "abcABC", 6); +} + +DEFINE_TEST(test_zip_filename_encoding_KOI8R) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "ru_RU.KOI8-R")) { + skipping("KOI8-R locale not available on this system."); + return; + } + + /* + * Verify that KOI8-R filenames are correctly translated to UTF-8. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from KOI8-R to UTF-8."); + archive_write_free(a); + return; + } + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set a KOI8-R filename. */ + archive_entry_set_pathname(entry, "\xD0\xD2\xC9"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* A bit 11 of general purpose flag should be 0x08, + * which indicates the filename charset is UTF-8. */ + assertEqualInt(0x08, buff[7]); + /* Above three characters in KOI8-R should translate to the following + * three characters (two bytes each) in UTF-8. */ + assertEqualMem(buff + 30, "\xD0\xBF\xD1\x80\xD0\xB8", 6); + + /* + * Verify that KOI8-R filenames are not translated to UTF-8. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set a KOI8-R filename. */ + archive_entry_set_pathname(entry, "\xD0\xD2\xC9"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* A bit 11 of general purpose flag should be 0, + * which indicates the filename charset is unknown. */ + assertEqualInt(0, buff[7]); + /* Above three characters in KOI8-R should not translate to + * any character-set. */ + assertEqualMem(buff + 30, "\xD0\xD2\xC9", 3); + + /* + * Verify that A bit 11 of general purpose flag is not set + * when ASCII filenames are stored even if hdrcharset=UTF-8 + * is specified. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from KOI8-R to UTF-8."); + archive_write_free(a); + return; + } + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set an ASCII filename. */ + archive_entry_set_pathname(entry, "abcABC"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* A bit 11 of general purpose flag should be 0, + * which indicates the filename charset is unknown. */ + assertEqualInt(0, buff[7]); + assertEqualMem(buff + 30, "abcABC", 6); +} + +/* + * Do not translate CP1251 into CP866 if non Windows platform. + */ +DEFINE_TEST(test_zip_filename_encoding_ru_RU_CP1251) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "ru_RU.CP1251")) { + skipping("Russian_Russia locale not available on this system."); + return; + } + + /* + * Verify that CP1251 filenames are not translated into any + * other character-set, in particular, CP866. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set a CP1251 filename. */ + archive_entry_set_pathname(entry, "\xEF\xF0\xE8"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* A bit 11 of general purpose flag should be 0, + * which indicates the filename charset is unknown. */ + assertEqualInt(0, buff[7]); + /* Above three characters in CP1251 should not translate into + * any other character-set. */ + assertEqualMem(buff + 30, "\xEF\xF0\xE8", 3); +} + +/* + * Other archiver applications on Windows translate CP1251 filenames + * into CP866 filenames and store it in the zip file. + * Test above behavior works well. + */ +DEFINE_TEST(test_zip_filename_encoding_Russian_Russia) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "Russian_Russia")) { + skipping("Russian_Russia locale not available on this system."); + return; + } + + /* + * Verify that Russian_Russia(CP1251) filenames are correctly translated + * to UTF-8. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from Russian_Russia.CP1251 to UTF-8."); + archive_write_free(a); + return; + } + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set a CP1251 filename. */ + archive_entry_set_pathname(entry, "\xEF\xF0\xE8"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* A bit 11 of general purpose flag should be 0x08, + * which indicates the filename charset is UTF-8. */ + assertEqualInt(0x08, buff[7]); + /* Above three characters in CP1251 should translate to the following + * three characters (two bytes each) in UTF-8. */ + assertEqualMem(buff + 30, "\xD0\xBF\xD1\x80\xD0\xB8", 6); + + /* + * Verify that Russian_Russia(CP1251) filenames are correctly translated + * to CP866. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set a CP1251 filename. */ + archive_entry_set_pathname(entry, "\xEF\xF0\xE8"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* A bit 11 of general purpose flag should be 0, + * which indicates the filename charset is unknown. */ + assertEqualInt(0, buff[7]); + /* Above three characters in CP1251 should translate to the following + * three characters in CP866. */ + assertEqualMem(buff + 30, "\xAF\xE0\xA8", 3); +} + +DEFINE_TEST(test_zip_filename_encoding_EUCJP) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "ja_JP.eucJP")) { + skipping("eucJP locale not available on this system."); + return; + } + + /* + * Verify that EUC-JP filenames are correctly translated to UTF-8. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from eucJP to UTF-8."); + archive_write_free(a); + return; + } + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set an EUC-JP filename. */ + archive_entry_set_pathname(entry, "\xC9\xBD.txt"); + /* Check the Unicode version. */ + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* A bit 11 of general purpose flag should be 0x08, + * which indicates the filename charset is UTF-8. */ + assertEqualInt(0x08, buff[7]); + /* Check UTF-8 version. */ + assertEqualMem(buff + 30, "\xE8\xA1\xA8.txt", 7); + + /* + * Verify that EUC-JP filenames are not translated to UTF-8. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set an EUC-JP filename. */ + archive_entry_set_pathname(entry, "\xC9\xBD.txt"); + /* Check the Unicode version. */ + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* A bit 11 of general purpose flag should be 0, + * which indicates the filename charset is unknown. */ + assertEqualInt(0, buff[7]); + /* Above three characters in EUC-JP should not translate to + * any character-set. */ + assertEqualMem(buff + 30, "\xC9\xBD.txt", 6); + + /* + * Verify that A bit 11 of general purpose flag is not set + * when ASCII filenames are stored even if hdrcharset=UTF-8 + * is specified. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from eucJP to UTF-8."); + archive_write_free(a); + return; + } + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set an ASCII filename. */ + archive_entry_set_pathname(entry, "abcABC"); + /* Check the Unicode version. */ + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* A bit 11 of general purpose flag should be 0, + * which indicates the filename charset is unknown. */ + assertEqualInt(0, buff[7]); + assertEqualMem(buff + 30, "abcABC", 6); +} + +DEFINE_TEST(test_zip_filename_encoding_CP932) +{ + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + if (NULL == setlocale(LC_ALL, "Japanese_Japan") && + NULL == setlocale(LC_ALL, "ja_JP.SJIS")) { + skipping("CP932/SJIS locale not available on this system."); + return; + } + + /* + * Verify that EUC-JP filenames are correctly translated to UTF-8. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from CP932/SJIS to UTF-8."); + archive_write_free(a); + return; + } + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set a CP932/SJIS filename. */ + archive_entry_set_pathname(entry, "\x95\x5C.txt"); + /* Check the Unicode version. */ + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* A bit 11 of general purpose flag should be 0x08, + * which indicates the filename charset is UTF-8. */ + assertEqualInt(0x08, buff[7]); + /* Check UTF-8 version. */ + assertEqualMem(buff + 30, "\xE8\xA1\xA8.txt", 7); + + /* + * Verify that CP932/SJIS filenames are not translated to UTF-8. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set a CP932/SJIS filename. */ + archive_entry_set_pathname(entry, "\x95\x5C.txt"); + /* Check the Unicode version. */ + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* A bit 11 of general purpose flag should be 0, + * which indicates the filename charset is unknown. */ + assertEqualInt(0, buff[7]); + /* Above three characters in CP932/SJIS should not translate to + * any character-set. */ + assertEqualMem(buff + 30, "\x95\x5C.txt", 6); + + /* + * Verify that A bit 11 of general purpose flag is not set + * when ASCII filenames are stored even if hdrcharset=UTF-8 + * is specified. + */ + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from CP932/SJIS to UTF-8."); + archive_write_free(a); + return; + } + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set an ASCII filename. */ + archive_entry_set_pathname(entry, "abcABC"); + /* Check the Unicode version. */ + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* A bit 11 of general purpose flag should be 0, + * which indicates the filename charset is unknown. */ + assertEqualInt(0, buff[7]); + assertEqualMem(buff + 30, "abcABC", 6); +} diff --git a/dependencies/libarchive-3.4.2/libarchive/xxhash.c b/dependencies/libarchive-3.4.2/libarchive/xxhash.c new file mode 100644 index 0000000..70750ba --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/xxhash.c @@ -0,0 +1,521 @@ +/* +xxHash - Fast Hash algorithm +Copyright (C) 2012-2014, Yann Collet. +BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +You can contact the author at : +- xxHash source repository : http://code.google.com/p/xxhash/ +*/ +#include "archive_platform.h" + +#include +#include + +#include "archive_xxhash.h" + +#ifdef HAVE_LIBLZ4 + +/*************************************** +** Tuning parameters +****************************************/ +/* Unaligned memory access is automatically enabled for "common" CPU, such as x86. +** For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected. +** If you know your target CPU supports unaligned memory access, you want to force this option manually to improve performance. +** You can also enable this parameter if you know your input data will always be aligned (boundaries of 4, for U32). +*/ +#if defined(__ARM_FEATURE_UNALIGNED) || defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) +# define XXH_USE_UNALIGNED_ACCESS 1 +#endif + +/* XXH_ACCEPT_NULL_INPUT_POINTER : +** If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer. +** When this option is enabled, xxHash output for null input pointers will be the same as a null-length input. +** This option has a very small performance cost (only measurable on small inputs). +** By default, this option is disabled. To enable it, uncomment below define : +** #define XXH_ACCEPT_NULL_INPUT_POINTER 1 + +** XXH_FORCE_NATIVE_FORMAT : +** By default, xxHash library provides endian-independent Hash values, based on little-endian convention. +** Results are therefore identical for little-endian and big-endian CPU. +** This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format. +** Should endian-independence be of no importance for your application, you may set the #define below to 1. +** It will improve speed for Big-endian CPU. +** This option has no impact on Little_Endian CPU. +*/ +#define XXH_FORCE_NATIVE_FORMAT 0 + +/*************************************** +** Compiler Specific Options +****************************************/ +/* Disable some Visual warning messages */ +#ifdef _MSC_VER /* Visual Studio */ +# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ +#endif + +#ifdef _MSC_VER /* Visual Studio */ +# define FORCE_INLINE __forceinline +#else +# ifdef __GNUC__ +# define FORCE_INLINE inline __attribute__((always_inline)) +# else +# define FORCE_INLINE inline +# endif +#endif + +/*************************************** +** Includes & Memory related functions +****************************************/ +#define XXH_malloc malloc +#define XXH_free free +#define XXH_memcpy memcpy + + +static unsigned int XXH32 (const void*, unsigned int, unsigned int); +static void* XXH32_init (unsigned int); +static XXH_errorcode XXH32_update (void*, const void*, unsigned int); +static unsigned int XXH32_digest (void*); +/*static int XXH32_sizeofState(void);*/ +static XXH_errorcode XXH32_resetState(void*, unsigned int); +#define XXH32_SIZEOFSTATE 48 +typedef struct { long long ll[(XXH32_SIZEOFSTATE+(sizeof(long long)-1))/sizeof(long long)]; } XXH32_stateSpace_t; +static unsigned int XXH32_intermediateDigest (void*); + +/*************************************** +** Basic Types +****************************************/ +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ +# include + typedef uint8_t BYTE; + typedef uint16_t U16; + typedef uint32_t U32; + typedef int32_t S32; + typedef uint64_t U64; +#else + typedef unsigned char BYTE; + typedef unsigned short U16; + typedef unsigned int U32; + typedef signed int S32; + typedef unsigned long long U64; +#endif + +#if defined(__GNUC__) && !defined(XXH_USE_UNALIGNED_ACCESS) +# define _PACKED __attribute__ ((packed)) +#else +# define _PACKED +#endif + +#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__) +# ifdef __IBMC__ +# pragma pack(1) +# else +# pragma pack(push, 1) +# endif +#endif + +typedef struct _U32_S { U32 v; } _PACKED U32_S; + +#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__) +# pragma pack(pop) +#endif + + +/**************************************** +** Compiler-specific Functions and Macros +*****************************************/ +#define GCC_VERSION ((__GNUC__-0) * 100 + (__GNUC_MINOR__ - 0)) + +#if GCC_VERSION >= 409 +__attribute__((__no_sanitize_undefined__)) +#endif +static inline U32 A32(const void * x) +{ + return (((const U32_S *)(x))->v); +} + +/* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */ +#if defined(_MSC_VER) +# define XXH_rotl32(x,r) _rotl(x,r) +#else +# define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r))) +#endif + +#if defined(_MSC_VER) /* Visual Studio */ +# define XXH_swap32 _byteswap_ulong +#elif GCC_VERSION >= 403 +# define XXH_swap32 __builtin_bswap32 +#else +static inline U32 XXH_swap32 (U32 x) { + return ((x << 24) & 0xff000000 ) | + ((x << 8) & 0x00ff0000 ) | + ((x >> 8) & 0x0000ff00 ) | + ((x >> 24) & 0x000000ff );} +#endif + + +/*************************************** +** Constants +****************************************/ +#define PRIME32_1 2654435761U +#define PRIME32_2 2246822519U +#define PRIME32_3 3266489917U +#define PRIME32_4 668265263U +#define PRIME32_5 374761393U + + +/*************************************** +** Architecture Macros +****************************************/ +typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess; +#ifndef XXH_CPU_LITTLE_ENDIAN /* It is possible to define XXH_CPU_LITTLE_ENDIAN externally, for example using a compiler switch */ + static const int one = 1; +# define XXH_CPU_LITTLE_ENDIAN (*(const char*)(&one)) +#endif + + +/*************************************** +** Macros +****************************************/ +#define XXH_STATIC_ASSERT(c) { enum { XXH_static_assert = 1/(!!(c)) }; } /* use only *after* variable declarations */ + + +/***************************** +** Memory reads +******************************/ +typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment; + +static +FORCE_INLINE U32 XXH_readLE32_align(const U32* ptr, XXH_endianess endian, XXH_alignment align) +{ + if (align==XXH_unaligned) + return endian==XXH_littleEndian ? A32(ptr) : XXH_swap32(A32(ptr)); + else + return endian==XXH_littleEndian ? *ptr : XXH_swap32(*ptr); +} + +static +FORCE_INLINE U32 XXH_readLE32(const U32* ptr, XXH_endianess endian) { return XXH_readLE32_align(ptr, endian, XXH_unaligned); } + + +/***************************** +** Simple Hash Functions +******************************/ +static +FORCE_INLINE U32 XXH32_endian_align(const void* input, unsigned int len, U32 seed, XXH_endianess endian, XXH_alignment align) +{ + const BYTE* p = (const BYTE*)input; + const BYTE* bEnd = p + len; + U32 h32; +#define XXH_get32bits(p) XXH_readLE32_align((const U32*)p, endian, align) + +#ifdef XXH_ACCEPT_NULL_INPUT_POINTER + if (p==NULL) { len=0; bEnd=p=(const BYTE*)(size_t)16; } +#endif + + if (len>=16) + { + const BYTE* const limit = bEnd - 16; + U32 v1 = seed + PRIME32_1 + PRIME32_2; + U32 v2 = seed + PRIME32_2; + U32 v3 = seed + 0; + U32 v4 = seed - PRIME32_1; + + do + { + v1 += XXH_get32bits(p) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4; + v2 += XXH_get32bits(p) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4; + v3 += XXH_get32bits(p) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4; + v4 += XXH_get32bits(p) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4; + } while (p<=limit); + + h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18); + } + else + { + h32 = seed + PRIME32_5; + } + + h32 += (U32) len; + + while (p<=bEnd-4) + { + h32 += XXH_get32bits(p) * PRIME32_3; + h32 = XXH_rotl32(h32, 17) * PRIME32_4 ; + p+=4; + } + + while (p> 15; + h32 *= PRIME32_2; + h32 ^= h32 >> 13; + h32 *= PRIME32_3; + h32 ^= h32 >> 16; + + return h32; +} + + +U32 XXH32(const void* input, unsigned int len, U32 seed) +{ +#if 0 + // Simple version, good for code maintenance, but unfortunately slow for small inputs + void* state = XXH32_init(seed); + XXH32_update(state, input, len); + return XXH32_digest(state); +#else + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + +# if !defined(XXH_USE_UNALIGNED_ACCESS) + if ((((size_t)input) & 3) == 0) /* Input is aligned, let's leverage the speed advantage */ + { + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned); + else + return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned); + } +# endif + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned); + else + return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned); +#endif +} + +/***************************** +** Advanced Hash Functions +******************************/ + +struct XXH_state32_t +{ + U64 total_len; + U32 seed; + U32 v1; + U32 v2; + U32 v3; + U32 v4; + int memsize; + char memory[16]; +}; + +#if 0 +static +int XXH32_sizeofState(void) +{ + XXH_STATIC_ASSERT(XXH32_SIZEOFSTATE >= sizeof(struct XXH_state32_t)); /* A compilation error here means XXH32_SIZEOFSTATE is not large enough */ + return sizeof(struct XXH_state32_t); +} +#endif + +static +XXH_errorcode XXH32_resetState(void* state_in, U32 seed) +{ + struct XXH_state32_t * state = (struct XXH_state32_t *) state_in; + state->seed = seed; + state->v1 = seed + PRIME32_1 + PRIME32_2; + state->v2 = seed + PRIME32_2; + state->v3 = seed + 0; + state->v4 = seed - PRIME32_1; + state->total_len = 0; + state->memsize = 0; + return XXH_OK; +} + +static +void* XXH32_init (U32 seed) +{ + void* state = XXH_malloc (sizeof(struct XXH_state32_t)); + XXH32_resetState(state, seed); + return state; +} + +static +FORCE_INLINE XXH_errorcode XXH32_update_endian (void* state_in, const void* input, int len, XXH_endianess endian) +{ + struct XXH_state32_t * state = (struct XXH_state32_t *) state_in; + const BYTE* p = (const BYTE*)input; + const BYTE* const bEnd = p + len; + +#ifdef XXH_ACCEPT_NULL_INPUT_POINTER + if (input==NULL) return XXH_ERROR; +#endif + + state->total_len += len; + + if (state->memsize + len < 16) /* fill in tmp buffer */ + { + XXH_memcpy(state->memory + state->memsize, input, len); + state->memsize += len; + return XXH_OK; + } + + if (state->memsize) /* some data left from previous update */ + { + XXH_memcpy(state->memory + state->memsize, input, 16-state->memsize); + { + const U32* p32 = (const U32*)state->memory; + state->v1 += XXH_readLE32(p32, endian) * PRIME32_2; state->v1 = XXH_rotl32(state->v1, 13); state->v1 *= PRIME32_1; p32++; + state->v2 += XXH_readLE32(p32, endian) * PRIME32_2; state->v2 = XXH_rotl32(state->v2, 13); state->v2 *= PRIME32_1; p32++; + state->v3 += XXH_readLE32(p32, endian) * PRIME32_2; state->v3 = XXH_rotl32(state->v3, 13); state->v3 *= PRIME32_1; p32++; + state->v4 += XXH_readLE32(p32, endian) * PRIME32_2; state->v4 = XXH_rotl32(state->v4, 13); state->v4 *= PRIME32_1; p32++; + } + p += 16-state->memsize; + state->memsize = 0; + } + + if (p <= bEnd-16) + { + const BYTE* const limit = bEnd - 16; + U32 v1 = state->v1; + U32 v2 = state->v2; + U32 v3 = state->v3; + U32 v4 = state->v4; + + do + { + v1 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4; + v2 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4; + v3 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4; + v4 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4; + } while (p<=limit); + + state->v1 = v1; + state->v2 = v2; + state->v3 = v3; + state->v4 = v4; + } + + if (p < bEnd) + { + XXH_memcpy(state->memory, p, bEnd-p); + state->memsize = (int)(bEnd-p); + } + + return XXH_OK; +} + +static +XXH_errorcode XXH32_update (void* state_in, const void* input, unsigned int len) +{ + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH32_update_endian(state_in, input, len, XXH_littleEndian); + else + return XXH32_update_endian(state_in, input, len, XXH_bigEndian); +} + + + +static +FORCE_INLINE U32 XXH32_intermediateDigest_endian (void* state_in, XXH_endianess endian) +{ + struct XXH_state32_t * state = (struct XXH_state32_t *) state_in; + const BYTE * p = (const BYTE*)state->memory; + BYTE* bEnd = (BYTE*)state->memory + state->memsize; + U32 h32; + + if (state->total_len >= 16) + { + h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18); + } + else + { + h32 = state->seed + PRIME32_5; + } + + h32 += (U32) state->total_len; + + while (p<=bEnd-4) + { + h32 += XXH_readLE32((const U32*)p, endian) * PRIME32_3; + h32 = XXH_rotl32(h32, 17) * PRIME32_4; + p+=4; + } + + while (p> 15; + h32 *= PRIME32_2; + h32 ^= h32 >> 13; + h32 *= PRIME32_3; + h32 ^= h32 >> 16; + + return h32; +} + +static +U32 XXH32_intermediateDigest (void* state_in) +{ + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH32_intermediateDigest_endian(state_in, XXH_littleEndian); + else + return XXH32_intermediateDigest_endian(state_in, XXH_bigEndian); +} + +static +U32 XXH32_digest (void* state_in) +{ + U32 h32 = XXH32_intermediateDigest(state_in); + + XXH_free(state_in); + + return h32; +} + +const +struct archive_xxhash __archive_xxhash = { + XXH32, + XXH32_init, + XXH32_update, + XXH32_digest +}; +#else + +/* + * Define an empty version of the struct if we aren't using the LZ4 library. + */ +const +struct archive_xxhash __archive_xxhash = { + NULL, + NULL, + NULL, + NULL +}; + +#endif /* HAVE_LIBLZ4 */ diff --git a/dependencies/libarchive-3.4.2/libarchive_fe/err.c b/dependencies/libarchive-3.4.2/libarchive_fe/err.c new file mode 100644 index 0000000..8c86035 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive_fe/err.c @@ -0,0 +1,100 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "lafe_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_STDARG_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "err.h" + +static void lafe_vwarnc(int, const char *, va_list) __LA_PRINTFLIKE(2, 0); + +static const char *lafe_progname; + +const char * +lafe_getprogname(void) +{ + + return lafe_progname; +} + +void +lafe_setprogname(const char *name, const char *defaultname) +{ + + if (name == NULL) + name = defaultname; +#if defined(_WIN32) && !defined(__CYGWIN__) + lafe_progname = strrchr(name, '\\'); + if (strrchr(name, '/') > lafe_progname) +#endif + lafe_progname = strrchr(name, '/'); + if (lafe_progname != NULL) + lafe_progname++; + else + lafe_progname = name; +} + +static void +lafe_vwarnc(int code, const char *fmt, va_list ap) +{ + fprintf(stderr, "%s: ", lafe_progname); + vfprintf(stderr, fmt, ap); + if (code != 0) + fprintf(stderr, ": %s", strerror(code)); + fprintf(stderr, "\n"); +} + +void +lafe_warnc(int code, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + lafe_vwarnc(code, fmt, ap); + va_end(ap); +} + +void +lafe_errc(int eval, int code, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + lafe_vwarnc(code, fmt, ap); + va_end(ap); + exit(eval); +} diff --git a/dependencies/libarchive-3.4.2/libarchive_fe/err.h b/dependencies/libarchive-3.4.2/libarchive_fe/err.h new file mode 100644 index 0000000..c663103 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive_fe/err.h @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 2009 Joerg Sonnenberger + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LAFE_ERR_H +#define LAFE_ERR_H + +#if defined(__GNUC__) && (__GNUC__ > 2 || \ + (__GNUC__ == 2 && __GNUC_MINOR__ >= 5)) +#define __LA_DEAD __attribute__((__noreturn__)) +#else +#define __LA_DEAD +#endif + +#if defined(__GNUC__) && (__GNUC__ > 2 || \ + (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)) +# ifdef __MINGW_PRINTF_FORMAT +# define __LA_PRINTF_FORMAT __MINGW_PRINTF_FORMAT +# else +# define __LA_PRINTF_FORMAT __printf__ +# endif +# define __LA_PRINTFLIKE(f,a) __attribute__((__format__(__LA_PRINTF_FORMAT, f, a))) +#else +# define __LA_PRINTFLIKE(f,a) +#endif + +void lafe_warnc(int code, const char *fmt, ...) __LA_PRINTFLIKE(2, 3); +void lafe_errc(int eval, int code, const char *fmt, ...) __LA_DEAD + __LA_PRINTFLIKE(3, 4); + +const char * lafe_getprogname(void); +void lafe_setprogname(const char *name, const char *defaultname); + +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive_fe/lafe_platform.h b/dependencies/libarchive-3.4.2/libarchive_fe/lafe_platform.h new file mode 100644 index 0000000..557124b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive_fe/lafe_platform.h @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: src/usr.bin/cpio/cpio_platform.h,v 1.2 2008/12/06 07:15:42 kientzle Exp $ + */ + +/* + * This header is the first thing included in any of the libarchive_fe + * source files. As far as possible, platform-specific issues should + * be dealt with here and not within individual source files. + */ + +#ifndef LAFE_PLATFORM_H_INCLUDED +#define LAFE_PLATFORM_H_INCLUDED + +#if defined(PLATFORM_CONFIG_H) +/* Use hand-built config.h in environments that need it. */ +#include PLATFORM_CONFIG_H +#else +/* Read config.h or die trying. */ +#include "config.h" +#endif + +/* Get a real definition for __FBSDID if we can */ +#if HAVE_SYS_CDEFS_H +#include +#endif + +/* If not, define it so as to avoid dangling semicolons. */ +#ifndef __FBSDID +#define __FBSDID(a) struct _undefined_hack +#endif + +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive_fe/line_reader.c b/dependencies/libarchive-3.4.2/libarchive_fe/line_reader.c new file mode 100644 index 0000000..c7c4694 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive_fe/line_reader.c @@ -0,0 +1,168 @@ +/*- + * Copyright (c) 2008 Tim Kientzle + * Copyright (c) 2010 Joerg Sonnenberger + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "lafe_platform.h" +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include "err.h" +#include "line_reader.h" + +#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__BORLANDC__) +#define strdup _strdup +#endif + +/* + * Read lines from file and do something with each one. If option_null + * is set, lines are terminated with zero bytes; otherwise, they're + * terminated with newlines. + * + * This uses a self-sizing buffer to handle arbitrarily-long lines. + */ +struct lafe_line_reader { + FILE *f; + char *buff, *buff_end, *line_start, *line_end; + char *pathname; + size_t buff_length; + int nullSeparator; /* Lines separated by null, not CR/CRLF/etc. */ +}; + +struct lafe_line_reader * +lafe_line_reader(const char *pathname, int nullSeparator) +{ + struct lafe_line_reader *lr; + + lr = calloc(1, sizeof(*lr)); + if (lr == NULL) + lafe_errc(1, ENOMEM, "Can't open %s", pathname); + + lr->nullSeparator = nullSeparator; + lr->pathname = strdup(pathname); + + if (strcmp(pathname, "-") == 0) + lr->f = stdin; + else + lr->f = fopen(pathname, "r"); + if (lr->f == NULL) + lafe_errc(1, errno, "Couldn't open %s", pathname); + lr->buff_length = 8192; + lr->line_start = lr->line_end = lr->buff_end = lr->buff = NULL; + + return (lr); +} + +static void +lafe_line_reader_find_eol(struct lafe_line_reader *lr) +{ + + lr->line_end += strcspn(lr->line_end, + lr->nullSeparator ? "" : "\x0d\x0a"); + *lr->line_end = '\0'; /* Noop if line_end == buff_end */ +} + +const char * +lafe_line_reader_next(struct lafe_line_reader *lr) +{ + size_t bytes_wanted, bytes_read, new_buff_size; + char *line_start, *p; + + for (;;) { + /* If there's a line in the buffer, return it immediately. */ + while (lr->line_end < lr->buff_end) { + line_start = lr->line_start; + lr->line_start = ++lr->line_end; + lafe_line_reader_find_eol(lr); + + if (lr->nullSeparator || line_start[0] != '\0') + return (line_start); + } + + /* If we're at end-of-file, process the final data. */ + if (lr->f == NULL) { + if (lr->line_start == lr->buff_end) + return (NULL); /* No more text */ + line_start = lr->line_start; + lr->line_start = lr->buff_end; + return (line_start); + } + + /* Buffer only has part of a line. */ + if (lr->line_start > lr->buff) { + /* Move a leftover fractional line to the beginning. */ + memmove(lr->buff, lr->line_start, + lr->buff_end - lr->line_start); + lr->buff_end -= lr->line_start - lr->buff; + lr->line_end -= lr->line_start - lr->buff; + lr->line_start = lr->buff; + } else { + /* Line is too big; enlarge the buffer. */ + new_buff_size = lr->buff_length * 2; + if (new_buff_size <= lr->buff_length) + lafe_errc(1, ENOMEM, + "Line too long in %s", lr->pathname); + lr->buff_length = new_buff_size; + /* + * Allocate one extra byte to allow terminating + * the buffer. + */ + p = realloc(lr->buff, new_buff_size + 1); + if (p == NULL) + lafe_errc(1, ENOMEM, + "Line too long in %s", lr->pathname); + lr->buff_end = p + (lr->buff_end - lr->buff); + lr->line_end = p + (lr->line_end - lr->buff); + lr->line_start = lr->buff = p; + } + + /* Get some more data into the buffer. */ + bytes_wanted = lr->buff + lr->buff_length - lr->buff_end; + bytes_read = fread(lr->buff_end, 1, bytes_wanted, lr->f); + lr->buff_end += bytes_read; + *lr->buff_end = '\0'; /* Always terminate buffer */ + lafe_line_reader_find_eol(lr); + + if (ferror(lr->f)) + lafe_errc(1, errno, "Can't read %s", lr->pathname); + if (feof(lr->f)) { + if (lr->f != stdin) + fclose(lr->f); + lr->f = NULL; + } + } +} + +void +lafe_line_reader_free(struct lafe_line_reader *lr) +{ + free(lr->buff); + free(lr->pathname); + free(lr); +} diff --git a/dependencies/libarchive-3.4.2/libarchive_fe/line_reader.h b/dependencies/libarchive-3.4.2/libarchive_fe/line_reader.h new file mode 100644 index 0000000..d092c05 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive_fe/line_reader.h @@ -0,0 +1,35 @@ +/*- + * Copyright (c) 2009 Joerg Sonnenberger + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LAFE_LINE_READER_H +#define LAFE_LINE_READER_H + +struct lafe_line_reader; + +struct lafe_line_reader *lafe_line_reader(const char *, int nullSeparator); +const char *lafe_line_reader_next(struct lafe_line_reader *); +void lafe_line_reader_free(struct lafe_line_reader *); + +#endif diff --git a/dependencies/libarchive-3.4.2/libarchive_fe/passphrase.c b/dependencies/libarchive-3.4.2/libarchive_fe/passphrase.c new file mode 100644 index 0000000..edf72d1 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive_fe/passphrase.c @@ -0,0 +1,333 @@ +/*- + * Copyright (c) 2014 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* $OpenBSD: readpassphrase.c,v 1.27 2019/01/25 00:19:25 millert Exp $ */ + +/* + * Copyright (c) 2000-2002, 2007, 2010 + * Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ + +/* OPENBSD ORIGINAL: lib/libc/gen/readpassphrase.c */ + + +#include "lafe_platform.h" +__FBSDID("$FreeBSD$"); + +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_READPASSPHRASE_H +#include +#endif + +#include "err.h" +#include "passphrase.h" + +#ifndef HAVE_READPASSPHRASE + +#define RPP_ECHO_OFF 0x00 /* Turn off echo (default). */ +#define RPP_ECHO_ON 0x01 /* Leave echo on. */ +#define RPP_REQUIRE_TTY 0x02 /* Fail if there is no tty. */ +#define RPP_FORCELOWER 0x04 /* Force input to lower case. */ +#define RPP_FORCEUPPER 0x08 /* Force input to upper case. */ +#define RPP_SEVENBIT 0x10 /* Strip the high bit from input. */ +#define RPP_STDIN 0x20 /* Read from stdin, not /dev/tty */ + + +#if defined(_WIN32) && !defined(__CYGWIN__) +#include + +static char * +readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags) +{ + HANDLE hStdin, hStdout; + DWORD mode, rbytes; + BOOL success; + + (void)flags; + + hStdin = GetStdHandle(STD_INPUT_HANDLE); + if (hStdin == INVALID_HANDLE_VALUE) + return (NULL); + hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + if (hStdout == INVALID_HANDLE_VALUE) + return (NULL); + + success = GetConsoleMode(hStdin, &mode); + if (!success) + return (NULL); + mode &= ~ENABLE_ECHO_INPUT; + mode |= ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT; + success = SetConsoleMode(hStdin, mode); + if (!success) + return (NULL); + + success = WriteFile(hStdout, prompt, (DWORD)strlen(prompt), + NULL, NULL); + if (!success) + return (NULL); + success = ReadFile(hStdin, buf, (DWORD)bufsiz - 1, &rbytes, NULL); + if (!success) + return (NULL); + WriteFile(hStdout, "\r\n", 2, NULL, NULL); + buf[rbytes] = '\0'; + /* Remove trailing carriage return(s). */ + if (rbytes > 2 && buf[rbytes - 2] == '\r' && buf[rbytes - 1] == '\n') + buf[rbytes - 2] = '\0'; + + return (buf); +} + +#else /* _WIN32 && !__CYGWIN__ */ + +#include +#include +#include +#ifdef HAVE_PATHS_H +#include +#endif +#include +#include +#include +#include + +#ifndef _PATH_TTY +#define _PATH_TTY "/dev/tty" +#endif + +#ifdef TCSASOFT +# define _T_FLUSH (TCSAFLUSH|TCSASOFT) +#else +# define _T_FLUSH (TCSAFLUSH) +#endif + +/* SunOS 4.x which lacks _POSIX_VDISABLE, but has VDISABLE */ +#if !defined(_POSIX_VDISABLE) && defined(VDISABLE) +# define _POSIX_VDISABLE VDISABLE +#endif + +#define M(a,b) (a > b ? a : b) +#define MAX_SIGNO M(M(M(SIGALRM, SIGHUP), \ + M(SIGINT, SIGPIPE)), \ + M(M(SIGQUIT, SIGTERM), \ + M(M(SIGTSTP, SIGTTIN), SIGTTOU))) + +static volatile sig_atomic_t signo[MAX_SIGNO + 1]; + +static void +handler(int s) +{ + assert(s <= MAX_SIGNO); + signo[s] = 1; +} + +static char * +readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags) +{ + ssize_t nr; + int input, output, save_errno, i, need_restart; + char ch, *p, *end; + struct termios term, oterm; + struct sigaction sa, savealrm, saveint, savehup, savequit, saveterm; + struct sigaction savetstp, savettin, savettou, savepipe; + + /* I suppose we could alloc on demand in this case (XXX). */ + if (bufsiz == 0) { + errno = EINVAL; + return(NULL); + } + +restart: + for (i = 0; i <= MAX_SIGNO; i++) + signo[i] = 0; + nr = -1; + save_errno = 0; + need_restart = 0; + /* + * Read and write to /dev/tty if available. If not, read from + * stdin and write to stderr unless a tty is required. + */ + if ((flags & RPP_STDIN) || + (input = output = open(_PATH_TTY, O_RDWR)) == -1) { + if (flags & RPP_REQUIRE_TTY) { + errno = ENOTTY; + return(NULL); + } + input = STDIN_FILENO; + output = STDERR_FILENO; + } + + /* + * Turn off echo if possible. + * If we are using a tty but are not the foreground pgrp this will + * generate SIGTTOU, so do it *before* installing the signal handlers. + */ + if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) { + memcpy(&term, &oterm, sizeof(term)); + if (!(flags & RPP_ECHO_ON)) + term.c_lflag &= ~(ECHO | ECHONL); +#ifdef VSTATUS + if (term.c_cc[VSTATUS] != _POSIX_VDISABLE) + term.c_cc[VSTATUS] = _POSIX_VDISABLE; +#endif + (void)tcsetattr(input, _T_FLUSH, &term); + } else { + memset(&term, 0, sizeof(term)); + term.c_lflag |= ECHO; + memset(&oterm, 0, sizeof(oterm)); + oterm.c_lflag |= ECHO; + } + + /* + * Catch signals that would otherwise cause the user to end + * up with echo turned off in the shell. Don't worry about + * things like SIGXCPU and SIGVTALRM for now. + */ + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; /* don't restart system calls */ + sa.sa_handler = handler; + /* Keep this list in sync with MAX_SIGNO! */ + (void)sigaction(SIGALRM, &sa, &savealrm); + (void)sigaction(SIGHUP, &sa, &savehup); + (void)sigaction(SIGINT, &sa, &saveint); + (void)sigaction(SIGPIPE, &sa, &savepipe); + (void)sigaction(SIGQUIT, &sa, &savequit); + (void)sigaction(SIGTERM, &sa, &saveterm); + (void)sigaction(SIGTSTP, &sa, &savetstp); + (void)sigaction(SIGTTIN, &sa, &savettin); + (void)sigaction(SIGTTOU, &sa, &savettou); + + if (!(flags & RPP_STDIN)) { + int r = write(output, prompt, strlen(prompt)); + (void)r; + } + end = buf + bufsiz - 1; + p = buf; + while ((nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r') { + if (p < end) { + if ((flags & RPP_SEVENBIT)) + ch &= 0x7f; + if (isalpha((unsigned char)ch)) { + if ((flags & RPP_FORCELOWER)) + ch = (char)tolower((unsigned char)ch); + if ((flags & RPP_FORCEUPPER)) + ch = (char)toupper((unsigned char)ch); + } + *p++ = ch; + } + } + *p = '\0'; + save_errno = errno; + if (!(term.c_lflag & ECHO)) { + int r = write(output, "\n", 1); + (void)r; + } + + /* Restore old terminal settings and signals. */ + if (memcmp(&term, &oterm, sizeof(term)) != 0) { + const int sigttou = signo[SIGTTOU]; + + /* Ignore SIGTTOU generated when we are not the fg pgrp. */ + while (tcsetattr(input, _T_FLUSH, &oterm) == -1 && + errno == EINTR && !signo[SIGTTOU]) + continue; + signo[SIGTTOU] = sigttou; + } + (void)sigaction(SIGALRM, &savealrm, NULL); + (void)sigaction(SIGHUP, &savehup, NULL); + (void)sigaction(SIGINT, &saveint, NULL); + (void)sigaction(SIGQUIT, &savequit, NULL); + (void)sigaction(SIGPIPE, &savepipe, NULL); + (void)sigaction(SIGTERM, &saveterm, NULL); + (void)sigaction(SIGTSTP, &savetstp, NULL); + (void)sigaction(SIGTTIN, &savettin, NULL); + (void)sigaction(SIGTTOU, &savettou, NULL); + if (input != STDIN_FILENO) + (void)close(input); + + /* + * If we were interrupted by a signal, resend it to ourselves + * now that we have restored the signal handlers. + */ + for (i = 0; i <= MAX_SIGNO; i++) { + if (signo[i]) { + kill(getpid(), i); + switch (i) { + case SIGTSTP: + case SIGTTIN: + case SIGTTOU: + need_restart = 1; + } + } + } + if (need_restart) + goto restart; + + if (save_errno) + errno = save_errno; + return(nr == -1 ? NULL : buf); +} +#endif /* _WIN32 && !__CYGWIN__ */ +#endif /* HAVE_READPASSPHRASE */ + +char * +lafe_readpassphrase(const char *prompt, char *buf, size_t bufsiz) +{ + char *p; + + p = readpassphrase(prompt, buf, bufsiz, RPP_ECHO_OFF); + if (p == NULL) { + switch (errno) { + case EINTR: + break; + default: + lafe_errc(1, errno, "Couldn't read passphrase"); + break; + } + } + return (p); +} + diff --git a/dependencies/libarchive-3.4.2/libarchive_fe/passphrase.h b/dependencies/libarchive-3.4.2/libarchive_fe/passphrase.h new file mode 100644 index 0000000..ac7a506 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive_fe/passphrase.h @@ -0,0 +1,31 @@ +/*- + * Copyright (c) 2014 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LAFE_PASSPHRASE_H +#define LAFE_PASSPHRASE_H + +char *lafe_readpassphrase(const char *prompt, char *buf, size_t bufsiz); + +#endif diff --git a/dependencies/libarchive-3.4.2/tar/CMakeLists.txt b/dependencies/libarchive-3.4.2/tar/CMakeLists.txt new file mode 100644 index 0000000..6434791 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/CMakeLists.txt @@ -0,0 +1,50 @@ +############################################ +# +# How to build bsdtar +# +############################################ +IF(ENABLE_TAR) + + SET(bsdtar_SOURCES + bsdtar.c + bsdtar.h + bsdtar_platform.h + cmdline.c + creation_set.c + read.c + subst.c + util.c + write.c + ../libarchive_fe/err.c + ../libarchive_fe/err.h + ../libarchive_fe/lafe_platform.h + ../libarchive_fe/line_reader.c + ../libarchive_fe/line_reader.h + ../libarchive_fe/passphrase.c + ../libarchive_fe/passphrase.h + ) + INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../libarchive_fe) + IF(WIN32 AND NOT CYGWIN) + LIST(APPEND bsdtar_SOURCES bsdtar_windows.c) + LIST(APPEND bsdtar_SOURCES bsdtar_windows.h) + ENDIF(WIN32 AND NOT CYGWIN) + + # bsdtar documentation + SET(bsdtar_MANS bsdtar.1) + + # How to build bsdtar + ADD_EXECUTABLE(bsdtar ${bsdtar_SOURCES}) + IF(ENABLE_TAR_SHARED) + TARGET_LINK_LIBRARIES(bsdtar archive ${ADDITIONAL_LIBS}) + ELSE(ENABLE_TAR_SHARED) + TARGET_LINK_LIBRARIES(bsdtar archive_static ${ADDITIONAL_LIBS}) + SET_TARGET_PROPERTIES(bsdtar PROPERTIES COMPILE_DEFINITIONS + LIBARCHIVE_STATIC) + ENDIF(ENABLE_TAR_SHARED) + + # Installation rules + INSTALL(TARGETS bsdtar RUNTIME DESTINATION bin) + INSTALL_MAN(${bsdtar_MANS}) +ENDIF(ENABLE_TAR) + +add_subdirectory(test) diff --git a/dependencies/libarchive-3.4.2/tar/bsdtar.1 b/dependencies/libarchive-3.4.2/tar/bsdtar.1 new file mode 100644 index 0000000..f157423 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/bsdtar.1 @@ -0,0 +1,1320 @@ +.\" Copyright (c) 2003-2007 Tim Kientzle +.\" Copyright (c) 2017 Martin Matuska +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd January 31, 2020 +.Dt TAR 1 +.Os +.Sh NAME +.Nm tar +.Nd manipulate tape archives +.Sh SYNOPSIS +.Nm +.Op Ar bundled-flags Ao args Ac +.Op Ao Ar file Ac | Ao Ar pattern Ac ... +.Nm +.Brq Fl c +.Op Ar options +.Op Ar files | Ar directories +.Nm +.Brq Fl r | Fl u +.Fl f Ar archive-file +.Op Ar options +.Op Ar files | Ar directories +.Nm +.Brq Fl t | Fl x +.Op Ar options +.Op Ar patterns +.Sh DESCRIPTION +.Nm +creates and manipulates streaming archive files. +This implementation can extract from tar, pax, cpio, zip, jar, ar, xar, +rpm, 7-zip, and ISO 9660 cdrom images and can create tar, pax, cpio, ar, zip, +7-zip, and shar archives. +.Pp +The first synopsis form shows a +.Dq bundled +option word. +This usage is provided for compatibility with historical implementations. +See COMPATIBILITY below for details. +.Pp +The other synopsis forms show the preferred usage. +The first option to +.Nm +is a mode indicator from the following list: +.Bl -tag -compact -width indent +.It Fl c +Create a new archive containing the specified items. +The long option form is +.Fl Fl create . +.It Fl r +Like +.Fl c , +but new entries are appended to the archive. +Note that this only works on uncompressed archives stored in regular files. +The +.Fl f +option is required. +The long option form is +.Fl Fl append . +.It Fl t +List archive contents to stdout. +The long option form is +.Fl Fl list . +.It Fl u +Like +.Fl r , +but new entries are added only if they have a modification date +newer than the corresponding entry in the archive. +Note that this only works on uncompressed archives stored in regular files. +The +.Fl f +option is required. +The long form is +.Fl Fl update . +.It Fl x +Extract to disk from the archive. +If a file with the same name appears more than once in the archive, +each copy will be extracted, with later copies overwriting (replacing) +earlier copies. +The long option form is +.Fl Fl extract . +.El +.Pp +In +.Fl c , +.Fl r , +or +.Fl u +mode, each specified file or directory is added to the +archive in the order specified on the command line. +By default, the contents of each directory are also archived. +.Pp +In extract or list mode, the entire command line +is read and parsed before the archive is opened. +The pathnames or patterns on the command line indicate +which items in the archive should be processed. +Patterns are shell-style globbing patterns as +documented in +.Xr tcsh 1 . +.Sh OPTIONS +Unless specifically stated otherwise, options are applicable in +all operating modes. +.Bl -tag -width indent +.It Cm @ Ns Pa archive +(c and r modes only) +The specified archive is opened and the entries +in it will be appended to the current archive. +As a simple example, +.Dl Nm Fl c Fl f Pa - Pa newfile Cm @ Ns Pa original.tar +writes a new archive to standard output containing a file +.Pa newfile +and all of the entries from +.Pa original.tar . +In contrast, +.Dl Nm Fl c Fl f Pa - Pa newfile Pa original.tar +creates a new archive with only two entries. +Similarly, +.Dl Nm Fl czf Pa - Fl Fl format Cm pax Cm @ Ns Pa - +reads an archive from standard input (whose format will be determined +automatically) and converts it into a gzip-compressed +pax-format archive on stdout. +In this way, +.Nm +can be used to convert archives from one format to another. +.It Fl a , Fl Fl auto-compress +(c mode only) +Use the archive suffix to decide a set of the format and +the compressions. +As a simple example, +.Dl Nm Fl a Fl cf Pa archive.tgz source.c source.h +creates a new archive with restricted pax format and gzip compression, +.Dl Nm Fl a Fl cf Pa archive.tar.bz2.uu source.c source.h +creates a new archive with restricted pax format and bzip2 compression +and uuencode compression, +.Dl Nm Fl a Fl cf Pa archive.zip source.c source.h +creates a new archive with zip format, +.Dl Nm Fl a Fl jcf Pa archive.tgz source.c source.h +ignores the +.Dq -j +option, and creates a new archive with restricted pax format +and gzip compression, +.Dl Nm Fl a Fl jcf Pa archive.xxx source.c source.h +if it is unknown suffix or no suffix, creates a new archive with +restricted pax format and bzip2 compression. +.It Fl Fl acls +(c, r, u, x modes only) +Archive or extract POSIX.1e or NFSv4 ACLs. +This is the reverse of +.Fl Fl no-acls +and the default behavior in c, r, and u modes (except on Mac OS X) or if +.Nm +is run in x mode as root. +On Mac OS X this option translates extended ACLs to NFSv4 ACLs. +To store extended ACLs the +.Fl Fl mac-metadata +option is preferred. +.It Fl B , Fl Fl read-full-blocks +Ignored for compatibility with other +.Xr tar 1 +implementations. +.It Fl b Ar blocksize , Fl Fl block-size Ar blocksize +Specify the block size, in 512-byte records, for tape drive I/O. +As a rule, this argument is only needed when reading from or writing +to tape drives, and usually not even then as the default block size of +20 records (10240 bytes) is very common. +.It Fl C Ar directory , Fl Fl cd Ar directory , Fl Fl directory Ar directory +In c and r mode, this changes the directory before adding +the following files. +In x mode, change directories after opening the archive +but before extracting entries from the archive. +.It Fl Fl chroot +(x mode only) +.Fn chroot +to the current directory after processing any +.Fl C +options and before extracting any files. +.It Fl Fl clear-nochange-fflags +(x mode only) +Before removing file system objects to replace them, clear platform-specific +file attributes or file flags that might prevent removal. +.It Fl Fl exclude Ar pattern +Do not process files or directories that match the +specified pattern. +Note that exclusions take precedence over patterns or filenames +specified on the command line. +.It Fl Fl exclude-vcs +Do not process files or directories internally used by the +version control systems +.Sq Arch , +.Sq Bazaar , +.Sq CVS , +.Sq Darcs , +.Sq Mercurial , +.Sq RCS , +.Sq SCCS , +.Sq SVN +and +.Sq git . +.It Fl Fl fflags +(c, r, u, x modes only) +Archive or extract platform-specific file attributes or file flags. +This is the reverse of +.Fl Fl no-fflags +and the default behavior in c, r, and u modes or if +.Nm +is run in x mode as root. +.It Fl Fl format Ar format +(c, r, u mode only) +Use the specified format for the created archive. +Supported formats include +.Dq cpio , +.Dq pax , +.Dq shar , +and +.Dq ustar . +Other formats may also be supported; see +.Xr libarchive-formats 5 +for more information about currently-supported formats. +In r and u modes, when extending an existing archive, the format specified +here must be compatible with the format of the existing archive on disk. +.It Fl f Ar file , Fl Fl file Ar file +Read the archive from or write the archive to the specified file. +The filename can be +.Pa - +for standard input or standard output. +The default varies by system; +on +.Fx , +the default is +.Pa /dev/sa0 ; +on Linux, the default is +.Pa /dev/st0 . +.It Fl Fl gid Ar id +Use the provided group id number. +On extract, this overrides the group id in the archive; +the group name in the archive will be ignored. +On create, this overrides the group id read from disk; +if +.Fl Fl gname +is not also specified, the group name will be set to +match the group id. +.It Fl Fl gname Ar name +Use the provided group name. +On extract, this overrides the group name in the archive; +if the provided group name does not exist on the system, +the group id +(from the archive or from the +.Fl Fl gid +option) +will be used instead. +On create, this sets the group name that will be stored +in the archive; +the name will not be verified against the system group database. +.It Fl H +(c and r modes only) +Symbolic links named on the command line will be followed; the +target of the link will be archived, not the link itself. +.It Fl h +(c and r modes only) +Synonym for +.Fl L . +.It Fl I +Synonym for +.Fl T . +.It Fl Fl help +Show usage. +.It Fl Fl hfsCompression +(x mode only) +Mac OS X specific (v10.6 or later). Compress extracted regular files with HFS+ +compression. +.It Fl Fl ignore-zeros +An alias of +.Fl Fl options Cm read_concatenated_archives +for compatibility with GNU tar. +.It Fl Fl include Ar pattern +Process only files or directories that match the specified pattern. +Note that exclusions specified with +.Fl Fl exclude +take precedence over inclusions. +If no inclusions are explicitly specified, all entries are processed by +default. +The +.Fl Fl include +option is especially useful when filtering archives. +For example, the command +.Dl Nm Fl c Fl f Pa new.tar Fl Fl include='*foo*' Cm @ Ns Pa old.tgz +creates a new archive +.Pa new.tar +containing only the entries from +.Pa old.tgz +containing the string +.Sq foo . +.It Fl J , Fl Fl xz +(c mode only) +Compress the resulting archive with +.Xr xz 1 . +In extract or list modes, this option is ignored. +Note that this +.Nm tar +implementation recognizes XZ compression automatically when reading archives. +.It Fl j , Fl Fl bzip , Fl Fl bzip2 , Fl Fl bunzip2 +(c mode only) +Compress the resulting archive with +.Xr bzip2 1 . +In extract or list modes, this option is ignored. +Note that this +.Nm tar +implementation recognizes bzip2 compression automatically when reading +archives. +.It Fl k , Fl Fl keep-old-files +(x mode only) +Do not overwrite existing files. +In particular, if a file appears more than once in an archive, +later copies will not overwrite earlier copies. +.It Fl Fl keep-newer-files +(x mode only) +Do not overwrite existing files that are newer than the +versions appearing in the archive being extracted. +.It Fl L , Fl Fl dereference +(c and r modes only) +All symbolic links will be followed. +Normally, symbolic links are archived as such. +With this option, the target of the link will be archived instead. +.It Fl l , Fl Fl check-links +(c and r modes only) +Issue a warning message unless all links to each file are archived. +.It Fl Fl lrzip +(c mode only) +Compress the resulting archive with +.Xr lrzip 1 . +In extract or list modes, this option is ignored. +Note that this +.Nm tar +implementation recognizes lrzip compression automatically when reading +archives. +.It Fl Fl lz4 +(c mode only) +Compress the archive with lz4-compatible compression before writing it. +In extract or list modes, this option is ignored. +Note that this +.Nm tar +implementation recognizes lz4 compression automatically when reading archives. +.It Fl Fl zstd +(c mode only) +Compress the archive with zstd-compatible compression before writing it. +In extract or list modes, this option is ignored. +Note that this +.Nm tar +implementation recognizes zstd compression automatically when reading archives. +.It Fl Fl lzma +(c mode only) Compress the resulting archive with the original LZMA algorithm. +In extract or list modes, this option is ignored. +Use of this option is discouraged and new archives should be created with +.Fl Fl xz +instead. +Note that this +.Nm tar +implementation recognizes LZMA compression automatically when reading archives. +.It Fl Fl lzop +(c mode only) +Compress the resulting archive with +.Xr lzop 1 . +In extract or list modes, this option is ignored. +Note that this +.Nm tar +implementation recognizes LZO compression automatically when reading archives. +.It Fl m , Fl Fl modification-time +(x mode only) +Do not extract modification time. +By default, the modification time is set to the time stored in the archive. +.It Fl Fl mac-metadata +(c, r, u and x mode only) +Mac OS X specific. +Archive or extract extended ACLs and extended file +attributes using +.Xr copyfile 3 +in AppleDouble format. +This is the reverse of +.Fl Fl no-mac-metadata . +and the default behavior in c, r, and u modes or if +.Nm +is run in x mode as root. +.It Fl n , Fl Fl norecurse , Fl Fl no-recursion +Do not operate recursively on the content of directories. +.It Fl Fl newer Ar date +(c, r, u modes only) +Only include files and directories newer than the specified date. +This compares ctime entries. +.It Fl Fl newer-mtime Ar date +(c, r, u modes only) +Like +.Fl Fl newer , +except it compares mtime entries instead of ctime entries. +.It Fl Fl newer-than Pa file +(c, r, u modes only) +Only include files and directories newer than the specified file. +This compares ctime entries. +.It Fl Fl newer-mtime-than Pa file +(c, r, u modes only) +Like +.Fl Fl newer-than , +except it compares mtime entries instead of ctime entries. +.It Fl Fl nodump +(c and r modes only) +Honor the nodump file flag by skipping this file. +.It Fl Fl nopreserveHFSCompression +(x mode only) +Mac OS X specific (v10.6 or later). Do not compress extracted regular files +which were compressed with HFS+ compression before archived. +By default, compress the regular files again with HFS+ compression. +.It Fl Fl null +(use with +.Fl I +or +.Fl T ) +Filenames or patterns are separated by null characters, +not by newlines. +This is often used to read filenames output by the +.Fl print0 +option to +.Xr find 1 . +.It Fl Fl no-acls +(c, r, u, x modes only) +Do not archive or extract POSIX.1e or NFSv4 ACLs. +This is the reverse of +.Fl Fl acls +and the default behavior if +.Nm +is run as non-root in x mode (on Mac OS X as any user in c, r, u and x modes). +.It Fl Fl no-fflags +(c, r, u, x modes only) +Do not archive or extract file attributes or file flags. +This is the reverse of +.Fl Fl fflags +and the default behavior if +.Nm +is run as non-root in x mode. +.It Fl Fl no-mac-metadata +(x mode only) +Mac OS X specific. +Do not archive or extract ACLs and extended file attributes +using +.Xr copyfile 3 +in AppleDouble format. +This is the reverse of +.Fl Fl mac-metadata . +and the default behavior if +.Nm +is run as non-root in x mode. +.It Fl Fl no-safe-writes +(x mode only) +Do not create temporary files and use +.Xr rename 2 +to replace the original ones. +This is the reverse of +.Fl Fl safe-writes . +.It Fl Fl no-same-owner +(x mode only) +Do not extract owner and group IDs. +This is the reverse of +.Fl Fl same-owner +and the default behavior if +.Nm +is run as non-root. +.It Fl Fl no-same-permissions +(x mode only) +Do not extract full permissions (SGID, SUID, sticky bit, +file attributes or file flags, extended file attributes and ACLs). +This is the reverse of +.Fl p +and the default behavior if +.Nm +is run as non-root. +.It Fl Fl no-xattrs +(c, r, u, x modes only) +Do not archive or extract extended file attributes. +This is the reverse of +.Fl Fl xattrs +and the default behavior if +.Nm +is run as non-root in x mode. +.It Fl Fl numeric-owner +This is equivalent to +.Fl Fl uname +.Qq +.Fl Fl gname +.Qq . +On extract, it causes user and group names in the archive +to be ignored in favor of the numeric user and group ids. +On create, it causes user and group names to not be stored +in the archive. +.It Fl O , Fl Fl to-stdout +(x, t modes only) +In extract (-x) mode, files will be written to standard out rather than +being extracted to disk. +In list (-t) mode, the file listing will be written to stderr rather than +the usual stdout. +.It Fl o +(x mode) +Use the user and group of the user running the program rather +than those specified in the archive. +Note that this has no significance unless +.Fl p +is specified, and the program is being run by the root user. +In this case, the file modes and flags from +the archive will be restored, but ACLs or owner information in +the archive will be discarded. +.It Fl o +(c, r, u mode) +A synonym for +.Fl Fl format Ar ustar +.It Fl Fl older Ar date +(c, r, u modes only) +Only include files and directories older than the specified date. +This compares ctime entries. +.It Fl Fl older-mtime Ar date +(c, r, u modes only) +Like +.Fl Fl older , +except it compares mtime entries instead of ctime entries. +.It Fl Fl older-than Pa file +(c, r, u modes only) +Only include files and directories older than the specified file. +This compares ctime entries. +.It Fl Fl older-mtime-than Pa file +(c, r, u modes only) +Like +.Fl Fl older-than , +except it compares mtime entries instead of ctime entries. +.It Fl Fl one-file-system +(c, r, and u modes) +Do not cross mount points. +.It Fl Fl options Ar options +Select optional behaviors for particular modules. +The argument is a text string containing comma-separated +keywords and values. +These are passed to the modules that handle particular +formats to control how those formats will behave. +Each option has one of the following forms: +.Bl -tag -compact -width indent +.It Ar key=value +The key will be set to the specified value in every module that supports it. +Modules that do not support this key will ignore it. +.It Ar key +The key will be enabled in every module that supports it. +This is equivalent to +.Ar key Ns Cm =1 . +.It Ar !key +The key will be disabled in every module that supports it. +.It Ar module:key=value , Ar module:key , Ar module:!key +As above, but the corresponding key and value will be provided +only to modules whose name matches +.Ar module . +.El +.Pp +The complete list of supported modules and keys +for create and append modes is in +.Xr archive_write_set_options 3 +and for extract and list modes in +.Xr archive_read_set_options 3 . +.Pp +Examples of supported options: +.Bl -tag -compact -width indent +.It Cm iso9660:joliet +Support Joliet extensions. +This is enabled by default, use +.Cm !joliet +or +.Cm iso9660:!joliet +to disable. +.It Cm iso9660:rockridge +Support Rock Ridge extensions. +This is enabled by default, use +.Cm !rockridge +or +.Cm iso9660:!rockridge +to disable. +.It Cm gzip:compression-level +A decimal integer from 1 to 9 specifying the gzip compression level. +.It Cm gzip:timestamp +Store timestamp. +This is enabled by default, use +.Cm !timestamp +or +.Cm gzip:!timestamp +to disable. +.It Cm lrzip:compression Ns = Ns Ar type +Use +.Ar type +as compression method. +Supported values are bzip2, gzip, lzo (ultra fast), +and zpaq (best, extremely slow). +.It Cm lrzip:compression-level +A decimal integer from 1 to 9 specifying the lrzip compression level. +.It Cm lz4:compression-level +A decimal integer from 1 to 9 specifying the lzop compression level. +.It Cm lz4:stream-checksum +Enable stream checksum. +This is by default, use +.Cm lz4:!stream-checksum +to disable. +.It Cm lz4:block-checksum +Enable block checksum (Disabled by default). +.It Cm lz4:block-size +A decimal integer from 4 to 7 specifying the lz4 compression block size +(7 is set by default). +.It Cm lz4:block-dependence +Use the previous block of the block being compressed for +a compression dictionary to improve compression ratio. +.It Cm zstd:compression-level +A decimal integer from 1 to 22 specifying the zstd compression level. +.It Cm lzop:compression-level +A decimal integer from 1 to 9 specifying the lzop compression level. +.It Cm xz:compression-level +A decimal integer from 0 to 9 specifying the xz compression level. +.It Cm mtree: Ns Ar keyword +The mtree writer module allows you to specify which mtree keywords +will be included in the output. +Supported keywords include: +.Cm cksum , Cm device , Cm flags , Cm gid , Cm gname , Cm indent , +.Cm link , Cm md5 , Cm mode , Cm nlink , Cm rmd160 , Cm sha1 , Cm sha256 , +.Cm sha384 , Cm sha512 , Cm size , Cm time , Cm uid , Cm uname . +The default is equivalent to: +.Dq device, flags, gid, gname, link, mode, nlink, size, time, type, uid, uname . +.It Cm mtree:all +Enables all of the above keywords. +You can also use +.Cm mtree:!all +to disable all keywords. +.It Cm mtree:use-set +Enable generation of +.Cm /set +lines in the output. +.It Cm mtree:indent +Produce human-readable output by indenting options and splitting lines +to fit into 80 columns. +.It Cm zip:compression Ns = Ns Ar type +Use +.Ar type +as compression method. +Supported values are store (uncompressed) and deflate (gzip algorithm). +.It Cm zip:encryption +Enable encryption using traditional zip encryption. +.It Cm zip:encryption Ns = Ns Ar type +Use +.Ar type +as encryption type. +Supported values are zipcrypt (traditional zip encryption), +aes128 (WinZip AES-128 encryption) and aes256 (WinZip AES-256 encryption). +.It Cm read_concatenated_archives +Ignore zeroed blocks in the archive, which occurs when multiple tar archives +have been concatenated together. +Without this option, only the contents of +the first concatenated archive would be read. +This option is comparable to the +.Fl i , Fl Fl ignore-zeros +option of GNU tar. +.El +If a provided option is not supported by any module, that +is a fatal error. +.It Fl P , Fl Fl absolute-paths +Preserve pathnames. +By default, absolute pathnames (those that begin with a / +character) have the leading slash removed both when creating archives +and extracting from them. +Also, +.Nm +will refuse to extract archive entries whose pathnames contain +.Pa .. +or whose target directory would be altered by a symlink. +This option suppresses these behaviors. +.It Fl p , Fl Fl insecure , Fl Fl preserve-permissions +(x mode only) +Preserve file permissions. +Attempt to restore the full permissions, including file modes, file attributes +or file flags, extended file attributes and ACLs, if available, for each item +extracted from the archive. +This is the reverse of +.Fl Fl no-same-permissions +and the default if +.Nm +is being run as root. +It can be partially overridden by also specifying +.Fl Fl no-acls , +.Fl Fl no-fflags , +.Fl Fl no-mac-metadata +or +.Fl Fl no-xattrs . +.It Fl Fl passphrase Ar passphrase +The +.Pa passphrase +is used to extract or create an encrypted archive. +Currently, zip is the only supported format that supports encryption. +You shouldn't use this option unless you realize how insecure +use of this option is. +.It Fl Fl posix +(c, r, u mode only) +Synonym for +.Fl Fl format Ar pax +.It Fl q , Fl Fl fast-read +(x and t mode only) +Extract or list only the first archive entry that matches each pattern +or filename operand. +Exit as soon as each specified pattern or filename has been matched. +By default, the archive is always read to the very end, since +there can be multiple entries with the same name and, by convention, +later entries overwrite earlier entries. +This option is provided as a performance optimization. +.It Fl S +(x mode only) +Extract files as sparse files. +For every block on disk, check first if it contains only NULL bytes and seek +over it otherwise. +This works similar to the conv=sparse option of dd. +.It Fl s Ar pattern +Modify file or archive member names according to +.Pa pattern . +The pattern has the format +.Ar /old/new/ Ns Op ghHprRsS +where +.Ar old +is a basic regular expression, +.Ar new +is the replacement string of the matched part, +and the optional trailing letters modify +how the replacement is handled. +If +.Ar old +is not matched, the pattern is skipped. +Within +.Ar new , +~ is substituted with the match, \e1 to \e9 with the content of +the corresponding captured group. +The optional trailing g specifies that matching should continue +after the matched part and stop on the first unmatched pattern. +The optional trailing s specifies that the pattern applies to the value +of symbolic links. +The optional trailing p specifies that after a successful substitution +the original path name and the new path name should be printed to +standard error. +Optional trailing H, R, or S characters suppress substitutions +for hardlink targets, regular filenames, or symlink targets, +respectively. +Optional trailing h, r, or s characters enable substitutions +for hardlink targets, regular filenames, or symlink targets, +respectively. +The default is +.Ar hrs +which applies substitutions to all names. +In particular, it is never necessary to specify h, r, or s. +.It Fl Fl safe-writes +(x mode only) +Extract files atomically. +By default +.Nm +unlinks the original file with the same name as the extracted file (if it +exists), and then creates it immediately under the same name and writes to +it. +For a short period of time, applications trying to access the file might +not find it, or see incomplete results. +If +.Fl Fl safe-writes +is enabled, +.Nm +first creates a unique temporary file, then writes the new contents to +the temporary file, and finally renames the temporary file to its final +name atomically using +.Xr rename 2 . +This guarantees that an application accessing the file, will either see +the old contents or the new contents at all times. +.It Fl Fl same-owner +(x mode only) +Extract owner and group IDs. +This is the reverse of +.Fl Fl no-same-owner +and the default behavior if +.Nm +is run as root. +.It Fl Fl strip-components Ar count +Remove the specified number of leading path elements. +Pathnames with fewer elements will be silently skipped. +Note that the pathname is edited after checking inclusion/exclusion patterns +but before security checks. +.It Fl T Ar filename , Fl Fl files-from Ar filename +In x or t mode, +.Nm +will read the list of names to be extracted from +.Pa filename . +In c mode, +.Nm +will read names to be archived from +.Pa filename . +The special name +.Dq -C +on a line by itself will cause the current directory to be changed to +the directory specified on the following line. +Names are terminated by newlines unless +.Fl Fl null +is specified. +Note that +.Fl Fl null +also disables the special handling of lines containing +.Dq -C . +Note: If you are generating lists of files using +.Xr find 1 , +you probably want to use +.Fl n +as well. +.It Fl Fl totals +(c, r, u modes only) +After archiving all files, print a summary to stderr. +.It Fl U , Fl Fl unlink , Fl Fl unlink-first +(x mode only) +Unlink files before creating them. +This can be a minor performance optimization if most files +already exist, but can make things slower if most files +do not already exist. +This flag also causes +.Nm +to remove intervening directory symlinks instead of +reporting an error. +See the SECURITY section below for more details. +.It Fl Fl uid Ar id +Use the provided user id number and ignore the user +name from the archive. +On create, if +.Fl Fl uname +is not also specified, the user name will be set to +match the user id. +.It Fl Fl uname Ar name +Use the provided user name. +On extract, this overrides the user name in the archive; +if the provided user name does not exist on the system, +it will be ignored and the user id +(from the archive or from the +.Fl Fl uid +option) +will be used instead. +On create, this sets the user name that will be stored +in the archive; +the name is not verified against the system user database. +.It Fl Fl use-compress-program Ar program +Pipe the input (in x or t mode) or the output (in c mode) through +.Pa program +instead of using the builtin compression support. +.It Fl v , Fl Fl verbose +Produce verbose output. +In create and extract modes, +.Nm +will list each file name as it is read from or written to +the archive. +In list mode, +.Nm +will produce output similar to that of +.Xr ls 1 . +An additional +.Fl v +option will also provide ls-like details in create and extract mode. +.It Fl Fl version +Print version of +.Nm +and +.Nm libarchive , +and exit. +.It Fl w , Fl Fl confirmation , Fl Fl interactive +Ask for confirmation for every action. +.It Fl X Ar filename , Fl Fl exclude-from Ar filename +Read a list of exclusion patterns from the specified file. +See +.Fl Fl exclude +for more information about the handling of exclusions. +.It Fl Fl xattrs +(c, r, u, x modes only) +Archive or extract extended file attributes. +This is the reverse of +.Fl Fl no-xattrs +and the default behavior in c, r, and u modes or if +.Nm +is run in x mode as root. +.It Fl y +(c mode only) +Compress the resulting archive with +.Xr bzip2 1 . +In extract or list modes, this option is ignored. +Note that this +.Nm tar +implementation recognizes bzip2 compression automatically when reading +archives. +.It Fl Z , Fl Fl compress , Fl Fl uncompress +(c mode only) +Compress the resulting archive with +.Xr compress 1 . +In extract or list modes, this option is ignored. +Note that this +.Nm tar +implementation recognizes compress compression automatically when reading +archives. +.It Fl z , Fl Fl gunzip , Fl Fl gzip +(c mode only) +Compress the resulting archive with +.Xr gzip 1 . +In extract or list modes, this option is ignored. +Note that this +.Nm tar +implementation recognizes gzip compression automatically when reading +archives. +.El +.Sh ENVIRONMENT +The following environment variables affect the execution of +.Nm : +.Bl -tag -width ".Ev BLOCKSIZE" +.It Ev TAR_READER_OPTIONS +The default options for format readers and compression readers. +The +.Fl Fl options +option overrides this. +.It Ev TAR_WRITER_OPTIONS +The default options for format writers and compression writers. +The +.Fl Fl options +option overrides this. +.It Ev LANG +The locale to use. +See +.Xr environ 7 +for more information. +.It Ev TAPE +The default device. +The +.Fl f +option overrides this. +Please see the description of the +.Fl f +option above for more details. +.It Ev TZ +The timezone to use when displaying dates. +See +.Xr environ 7 +for more information. +.El +.Sh EXIT STATUS +.Ex -std +.Sh EXAMPLES +The following creates a new archive +called +.Ar file.tar.gz +that contains two files +.Ar source.c +and +.Ar source.h : +.Dl Nm Fl czf Pa file.tar.gz Pa source.c Pa source.h +.Pp +To view a detailed table of contents for this +archive: +.Dl Nm Fl tvf Pa file.tar.gz +.Pp +To extract all entries from the archive on +the default tape drive: +.Dl Nm Fl x +.Pp +To examine the contents of an ISO 9660 cdrom image: +.Dl Nm Fl tf Pa image.iso +.Pp +To move file hierarchies, invoke +.Nm +as +.Dl Nm Fl cf Pa - Fl C Pa srcdir \&. | Nm Fl xpf Pa - Fl C Pa destdir +or more traditionally +.Dl cd srcdir \&; Nm Fl cf Pa - \&. | ( cd destdir \&; Nm Fl xpf Pa - ) +.Pp +In create mode, the list of files and directories to be archived +can also include directory change instructions of the form +.Cm -C Ns Pa foo/baz +and archive inclusions of the form +.Cm @ Ns Pa archive-file . +For example, the command line +.Dl Nm Fl c Fl f Pa new.tar Pa foo1 Cm @ Ns Pa old.tgz Cm -C Ns Pa /tmp Pa foo2 +will create a new archive +.Pa new.tar . +.Nm +will read the file +.Pa foo1 +from the current directory and add it to the output archive. +It will then read each entry from +.Pa old.tgz +and add those entries to the output archive. +Finally, it will switch to the +.Pa /tmp +directory and add +.Pa foo2 +to the output archive. +.Pp +An input file in +.Xr mtree 5 +format can be used to create an output archive with arbitrary ownership, +permissions, or names that differ from existing data on disk: +.Bd -literal -offset indent +$ cat input.mtree +#mtree +usr/bin uid=0 gid=0 mode=0755 type=dir +usr/bin/ls uid=0 gid=0 mode=0755 type=file content=myls +$ tar -cvf output.tar @input.mtree +.Ed +.Pp +The +.Fl Fl newer +and +.Fl Fl newer-mtime +switches accept a variety of common date and time specifications, including +.Dq 12 Mar 2005 7:14:29pm , +.Dq 2005-03-12 19:14 , +.Dq 5 minutes ago , +and +.Dq 19:14 PST May 1 . +.Pp +The +.Fl Fl options +argument can be used to control various details of archive generation +or reading. +For example, you can generate mtree output which only contains +.Cm type , Cm time , +and +.Cm uid +keywords: +.Dl Nm Fl cf Pa file.tar Fl Fl format=mtree Fl Fl options='!all,type,time,uid' Pa dir +or you can set the compression level used by gzip or xz compression: +.Dl Nm Fl czf Pa file.tar Fl Fl options='compression-level=9' . +For more details, see the explanation of the +.Fn archive_read_set_options +and +.Fn archive_write_set_options +API calls that are described in +.Xr archive_read 3 +and +.Xr archive_write 3 . +.Sh COMPATIBILITY +The bundled-arguments format is supported for compatibility +with historic implementations. +It consists of an initial word (with no leading - character) in which +each character indicates an option. +Arguments follow as separate words. +The order of the arguments must match the order +of the corresponding characters in the bundled command word. +For example, +.Dl Nm Cm tbf 32 Pa file.tar +specifies three flags +.Cm t , +.Cm b , +and +.Cm f . +The +.Cm b +and +.Cm f +flags both require arguments, +so there must be two additional items +on the command line. +The +.Ar 32 +is the argument to the +.Cm b +flag, and +.Ar file.tar +is the argument to the +.Cm f +flag. +.Pp +The mode options c, r, t, u, and x and the options +b, f, l, m, o, v, and w comply with SUSv2. +.Pp +For maximum portability, scripts that invoke +.Nm tar +should use the bundled-argument format above, should limit +themselves to the +.Cm c , +.Cm t , +and +.Cm x +modes, and the +.Cm b , +.Cm f , +.Cm m , +.Cm v , +and +.Cm w +options. +.Pp +Additional long options are provided to improve compatibility with other +tar implementations. +.Sh SECURITY +Certain security issues are common to many archiving programs, including +.Nm . +In particular, carefully-crafted archives can request that +.Nm +extract files to locations outside of the target directory. +This can potentially be used to cause unwitting users to overwrite +files they did not intend to overwrite. +If the archive is being extracted by the superuser, any file +on the system can potentially be overwritten. +There are three ways this can happen. +Although +.Nm +has mechanisms to protect against each one, +savvy users should be aware of the implications: +.Bl -bullet -width indent +.It +Archive entries can have absolute pathnames. +By default, +.Nm +removes the leading +.Pa / +character from filenames before restoring them to guard against this problem. +.It +Archive entries can have pathnames that include +.Pa .. +components. +By default, +.Nm +will not extract files containing +.Pa .. +components in their pathname. +.It +Archive entries can exploit symbolic links to restore +files to other directories. +An archive can restore a symbolic link to another directory, +then use that link to restore a file into that directory. +To guard against this, +.Nm +checks each extracted path for symlinks. +If the final path element is a symlink, it will be removed +and replaced with the archive entry. +If +.Fl U +is specified, any intermediate symlink will also be unconditionally removed. +If neither +.Fl U +nor +.Fl P +is specified, +.Nm +will refuse to extract the entry. +.El +To protect yourself, you should be wary of any archives that +come from untrusted sources. +You should examine the contents of an archive with +.Dl Nm Fl tf Pa filename +before extraction. +You should use the +.Fl k +option to ensure that +.Nm +will not overwrite any existing files or the +.Fl U +option to remove any pre-existing files. +You should generally not extract archives while running with super-user +privileges. +Note that the +.Fl P +option to +.Nm +disables the security checks above and allows you to extract +an archive while preserving any absolute pathnames, +.Pa .. +components, or symlinks to other directories. +.Sh SEE ALSO +.Xr bzip2 1 , +.Xr compress 1 , +.Xr cpio 1 , +.Xr gzip 1 , +.Xr mt 1 , +.Xr pax 1 , +.Xr shar 1 , +.Xr xz 1 , +.Xr libarchive 3 , +.Xr libarchive-formats 5 , +.Xr tar 5 +.Sh STANDARDS +There is no current POSIX standard for the tar command; it appeared +in +.St -p1003.1-96 +but was dropped from +.St -p1003.1-2001 . +The options supported by this implementation were developed by surveying a +number of existing tar implementations as well as the old POSIX specification +for tar and the current POSIX specification for pax. +.Pp +The ustar and pax interchange file formats are defined by +.St -p1003.1-2001 +for the pax command. +.Sh HISTORY +A +.Nm tar +command appeared in Seventh Edition Unix, which was released in January, 1979. +There have been numerous other implementations, +many of which extended the file format. +John Gilmore's +.Nm pdtar +public-domain implementation (circa November, 1987) +was quite influential, and formed the basis of GNU tar. +GNU tar was included as the standard system tar +in +.Fx +beginning with +.Fx 1.0 . +.Pp +This is a complete re-implementation based on the +.Xr libarchive 3 +library. +It was first released with +.Fx 5.4 +in May, 2005. +.Sh BUGS +This program follows +.St -p1003.1-96 +for the definition of the +.Fl l +option. +Note that GNU tar prior to version 1.15 treated +.Fl l +as a synonym for the +.Fl Fl one-file-system +option. +.Pp +The +.Fl C Pa dir +option may differ from historic implementations. +.Pp +All archive output is written in correctly-sized blocks, even +if the output is being compressed. +Whether or not the last output block is padded to a full +block size varies depending on the format and the +output device. +For tar and cpio formats, the last block of output is padded +to a full block size if the output is being +written to standard output or to a character or block device such as +a tape drive. +If the output is being written to a regular file, the last block +will not be padded. +Many compressors, including +.Xr gzip 1 +and +.Xr bzip2 1 , +complain about the null padding when decompressing an archive created by +.Nm , +although they still extract it correctly. +.Pp +The compression and decompression is implemented internally, so +there may be insignificant differences between the compressed output +generated by +.Dl Nm Fl czf Pa - file +and that generated by +.Dl Nm Fl cf Pa - file | Nm gzip +.Pp +The default should be to read and write archives to the standard I/O paths, +but tradition (and POSIX) dictates otherwise. +.Pp +The +.Cm r +and +.Cm u +modes require that the archive be uncompressed +and located in a regular file on disk. +Other archives can be modified using +.Cm c +mode with the +.Pa @archive-file +extension. +.Pp +To archive a file called +.Pa @foo +or +.Pa -foo +you must specify it as +.Pa ./@foo +or +.Pa ./-foo , +respectively. +.Pp +In create mode, a leading +.Pa ./ +is always removed. +A leading +.Pa / +is stripped unless the +.Fl P +option is specified. +.Pp +There needs to be better support for file selection on both create +and extract. +.Pp +There is not yet any support for multi-volume archives. +.Pp +Converting between dissimilar archive formats (such as tar and cpio) using the +.Cm @ Ns Pa - +convention can cause hard link information to be lost. +(This is a consequence of the incompatible ways that different archive +formats store hardlink information.) diff --git a/dependencies/libarchive-3.4.2/tar/bsdtar.c b/dependencies/libarchive-3.4.2/tar/bsdtar.c new file mode 100644 index 0000000..af41be5 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/bsdtar.c @@ -0,0 +1,1047 @@ +/*- + * Copyright (c) 2003-2008 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "bsdtar_platform.h" +__FBSDID("$FreeBSD: src/usr.bin/tar/bsdtar.c,v 1.93 2008/11/08 04:43:24 kientzle Exp $"); + +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_COPYFILE_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_LANGINFO_H +#include +#endif +#ifdef HAVE_LOCALE_H +#include +#endif +#ifdef HAVE_PATHS_H +#include +#endif +#ifdef HAVE_SIGNAL_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_TIME_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "bsdtar.h" +#include "err.h" + +/* + * Per POSIX.1-1988, tar defaults to reading/writing archives to/from + * the default tape device for the system. Pick something reasonable here. + */ +#ifdef __linux +#define _PATH_DEFTAPE "/dev/st0" +#endif +#if defined(_WIN32) && !defined(__CYGWIN__) +#define _PATH_DEFTAPE "\\\\.\\tape0" +#endif +#if defined(__APPLE__) +#undef _PATH_DEFTAPE +#define _PATH_DEFTAPE "-" /* Mac OS has no tape support, default to stdio. */ +#endif + +#ifndef _PATH_DEFTAPE +#define _PATH_DEFTAPE "/dev/tape" +#endif + +#ifdef __MINGW32__ +int _CRT_glob = 0; /* Disable broken CRT globbing. */ +#endif + +#if defined(HAVE_SIGACTION) && (defined(SIGINFO) || defined(SIGUSR1)) +static volatile int siginfo_occurred; + +static void +siginfo_handler(int sig) +{ + (void)sig; /* UNUSED */ + siginfo_occurred = 1; +} + +int +need_report(void) +{ + int r = siginfo_occurred; + siginfo_occurred = 0; + return (r); +} +#else +int +need_report(void) +{ + return (0); +} +#endif + +static void long_help(void) __LA_DEAD; +static void only_mode(struct bsdtar *, const char *opt, + const char *valid); +static void set_mode(struct bsdtar *, char opt); +static void version(void) __LA_DEAD; + +/* A basic set of security flags to request from libarchive. */ +#define SECURITY \ + (ARCHIVE_EXTRACT_SECURE_SYMLINKS \ + | ARCHIVE_EXTRACT_SECURE_NODOTDOT) + +static char const * const vcs_files[] = { + /* CVS */ + "CVS", ".cvsignore", + /* RCS */ + "RCS", + /* SCCS */ + "SCCS", + /* SVN */ + ".svn", + /* git */ + ".git", ".gitignore", ".gitattributes", ".gitmodules", + /* Arch */ + ".arch-ids", "{arch}", "=RELEASE-ID", "=meta-update", "=update", + /* Bazaar */ + ".bzr", ".bzrignore", ".bzrtags", + /* Mercurial */ + ".hg", ".hgignore", ".hgtags", + /* darcs */ + "_darcs", + NULL +}; + +int +main(int argc, char **argv) +{ + struct bsdtar *bsdtar, bsdtar_storage; + int opt, t; + char compression, compression2; + const char *compression_name, *compression2_name; + const char *compress_program; + char *tptr; + char possible_help_request; + char buff[16]; + + /* + * Use a pointer for consistency, but stack-allocated storage + * for ease of cleanup. + */ + bsdtar = &bsdtar_storage; + memset(bsdtar, 0, sizeof(*bsdtar)); + bsdtar->fd = -1; /* Mark as "unused" */ + bsdtar->gid = -1; + bsdtar->uid = -1; + bsdtar->flags = 0; + compression = compression2 = '\0'; + compression_name = compression2_name = NULL; + compress_program = NULL; + +#if defined(HAVE_SIGACTION) + { /* Set up signal handling. */ + struct sigaction sa; + sa.sa_handler = siginfo_handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; +#ifdef SIGINFO + if (sigaction(SIGINFO, &sa, NULL)) + lafe_errc(1, errno, "sigaction(SIGINFO) failed"); +#endif +#ifdef SIGUSR1 + /* ... and treat SIGUSR1 the same way as SIGINFO. */ + if (sigaction(SIGUSR1, &sa, NULL)) + lafe_errc(1, errno, "sigaction(SIGUSR1) failed"); +#endif +#ifdef SIGPIPE + /* Ignore SIGPIPE signals. */ + sa.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &sa, NULL); +#endif + } +#endif + + /* Set lafe_progname before calling lafe_warnc. */ + lafe_setprogname(*argv, "bsdtar"); + +#if HAVE_SETLOCALE + if (setlocale(LC_ALL, "") == NULL) + lafe_warnc(0, "Failed to set default locale"); +#endif +#if defined(HAVE_NL_LANGINFO) && defined(HAVE_D_MD_ORDER) + bsdtar->day_first = (*nl_langinfo(D_MD_ORDER) == 'd'); +#endif + possible_help_request = 0; + + /* Look up uid of current user for future reference */ + bsdtar->user_uid = geteuid(); + + /* Default: open tape drive. */ + bsdtar->filename = getenv("TAPE"); + if (bsdtar->filename == NULL) + bsdtar->filename = _PATH_DEFTAPE; + + /* Default block size settings. */ + bsdtar->bytes_per_block = DEFAULT_BYTES_PER_BLOCK; + /* Allow library to default this unless user specifies -b. */ + bsdtar->bytes_in_last_block = -1; + + /* Default: preserve mod time on extract */ + bsdtar->extract_flags = ARCHIVE_EXTRACT_TIME; + + /* Default: Perform basic security checks. */ + bsdtar->extract_flags |= SECURITY; + +#ifndef _WIN32 + /* On POSIX systems, assume --same-owner and -p when run by + * the root user. This doesn't make any sense on Windows. */ + if (bsdtar->user_uid == 0) { + /* --same-owner */ + bsdtar->extract_flags |= ARCHIVE_EXTRACT_OWNER; + /* -p */ + bsdtar->extract_flags |= ARCHIVE_EXTRACT_PERM; + bsdtar->extract_flags |= ARCHIVE_EXTRACT_ACL; + bsdtar->extract_flags |= ARCHIVE_EXTRACT_XATTR; + bsdtar->extract_flags |= ARCHIVE_EXTRACT_FFLAGS; + bsdtar->extract_flags |= ARCHIVE_EXTRACT_MAC_METADATA; + } +#endif + + /* + * Enable Mac OS "copyfile()" extension by default. + * This has no effect on other platforms. + */ + bsdtar->readdisk_flags |= ARCHIVE_READDISK_MAC_COPYFILE; +#ifdef COPYFILE_DISABLE_VAR + if (getenv(COPYFILE_DISABLE_VAR)) + bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_MAC_COPYFILE; +#endif +#if defined(__APPLE__) + /* + * On Mac OS ACLs are archived with copyfile() (--mac-metadata) + * Translation to NFSv4 ACLs has to be requested explicitly with --acls + */ + bsdtar->readdisk_flags |= ARCHIVE_READDISK_NO_ACL; +#endif + + bsdtar->matching = archive_match_new(); + if (bsdtar->matching == NULL) + lafe_errc(1, errno, "Out of memory"); + bsdtar->cset = cset_new(); + if (bsdtar->cset == NULL) + lafe_errc(1, errno, "Out of memory"); + + bsdtar->argv = argv; + bsdtar->argc = argc; + + /* + * Comments following each option indicate where that option + * originated: SUSv2, POSIX, GNU tar, star, etc. If there's + * no such comment, then I don't know of anyone else who + * implements that option. + */ + while ((opt = bsdtar_getopt(bsdtar)) != -1) { + switch (opt) { + case 'a': /* GNU tar */ + bsdtar->flags |= OPTFLAG_AUTO_COMPRESS; + break; + case OPTION_ACLS: /* GNU tar */ + bsdtar->extract_flags |= ARCHIVE_EXTRACT_ACL; + bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_NO_ACL; + bsdtar->flags |= OPTFLAG_ACLS; + break; + case 'B': /* GNU tar */ + /* libarchive doesn't need this; just ignore it. */ + break; + case 'b': /* SUSv2 */ + errno = 0; + tptr = NULL; + t = (int)strtol(bsdtar->argument, &tptr, 10); + if (errno || t <= 0 || t > 8192 || + *(bsdtar->argument) == '\0' || tptr == NULL || + *tptr != '\0') { + lafe_errc(1, 0, "Invalid or out of range " + "(1..8192) argument to -b"); + } + bsdtar->bytes_per_block = 512 * t; + /* Explicit -b forces last block size. */ + bsdtar->bytes_in_last_block = bsdtar->bytes_per_block; + break; + case OPTION_B64ENCODE: + if (compression2 != '\0') + lafe_errc(1, 0, + "Can't specify both --uuencode and " + "--b64encode"); + compression2 = opt; + compression2_name = "b64encode"; + break; + case 'C': /* GNU tar */ + if (strlen(bsdtar->argument) == 0) + lafe_errc(1, 0, + "Meaningless option: -C ''"); + + set_chdir(bsdtar, bsdtar->argument); + break; + case 'c': /* SUSv2 */ + set_mode(bsdtar, opt); + break; + case OPTION_CHECK_LINKS: /* GNU tar */ + bsdtar->flags |= OPTFLAG_WARN_LINKS; + break; + case OPTION_CHROOT: /* NetBSD */ + bsdtar->flags |= OPTFLAG_CHROOT; + break; + case OPTION_CLEAR_NOCHANGE_FFLAGS: + bsdtar->extract_flags |= + ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS; + break; + case OPTION_EXCLUDE: /* GNU tar */ + if (archive_match_exclude_pattern( + bsdtar->matching, bsdtar->argument) != ARCHIVE_OK) + lafe_errc(1, 0, + "Couldn't exclude %s\n", bsdtar->argument); + break; + case OPTION_EXCLUDE_VCS: /* GNU tar */ + for(t=0; vcs_files[t]; t++) { + if (archive_match_exclude_pattern( + bsdtar->matching, + vcs_files[t]) != ARCHIVE_OK) + lafe_errc(1, 0, "Couldn't " + "exclude %s\n", vcs_files[t]); + } + break; + case OPTION_FFLAGS: + bsdtar->extract_flags |= ARCHIVE_EXTRACT_FFLAGS; + bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_NO_FFLAGS; + bsdtar->flags |= OPTFLAG_FFLAGS; + break; + case OPTION_FORMAT: /* GNU tar, others */ + cset_set_format(bsdtar->cset, bsdtar->argument); + break; + case 'f': /* SUSv2 */ + bsdtar->filename = bsdtar->argument; + break; + case OPTION_GID: /* cpio */ + errno = 0; + tptr = NULL; + t = (int)strtol(bsdtar->argument, &tptr, 10); + if (errno || t < 0 || *(bsdtar->argument) == '\0' || + tptr == NULL || *tptr != '\0') { + lafe_errc(1, 0, "Invalid argument to --gid"); + } + bsdtar->gid = t; + break; + case OPTION_GNAME: /* cpio */ + bsdtar->gname = bsdtar->argument; + break; + case OPTION_GRZIP: + if (compression != '\0') + lafe_errc(1, 0, + "Can't specify both -%c and -%c", opt, + compression); + compression = opt; + compression_name = "grzip"; + break; + case 'H': /* BSD convention */ + bsdtar->symlink_mode = 'H'; + break; + case 'h': /* Linux Standards Base, gtar; synonym for -L */ + bsdtar->symlink_mode = 'L'; + /* Hack: -h by itself is the "help" command. */ + possible_help_request = 1; + break; + case OPTION_HELP: /* GNU tar, others */ + long_help(); + exit(0); + break; + case OPTION_HFS_COMPRESSION: /* Mac OS X v10.6 or later */ + bsdtar->extract_flags |= + ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED; + break; + case OPTION_IGNORE_ZEROS: + bsdtar->flags |= OPTFLAG_IGNORE_ZEROS; + break; + case 'I': /* GNU tar */ + /* + * TODO: Allow 'names' to come from an archive, + * not just a text file. Design a good UI for + * allowing names and mode/owner to be read + * from an archive, with contents coming from + * disk. This can be used to "refresh" an + * archive or to design archives with special + * permissions without having to create those + * permissions on disk. + */ + bsdtar->names_from_file = bsdtar->argument; + break; + case OPTION_INCLUDE: + /* + * No one else has the @archive extension, so + * no one else needs this to filter entries + * when transforming archives. + */ + if (archive_match_include_pattern(bsdtar->matching, + bsdtar->argument) != ARCHIVE_OK) + lafe_errc(1, 0, + "Failed to add %s to inclusion list", + bsdtar->argument); + break; + case 'j': /* GNU tar */ + if (compression != '\0') + lafe_errc(1, 0, + "Can't specify both -%c and -%c", opt, + compression); + compression = opt; + compression_name = "bzip2"; + break; + case 'J': /* GNU tar 1.21 and later */ + if (compression != '\0') + lafe_errc(1, 0, + "Can't specify both -%c and -%c", opt, + compression); + compression = opt; + compression_name = "xz"; + break; + case 'k': /* GNU tar */ + bsdtar->extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE; + break; + case OPTION_KEEP_NEWER_FILES: /* GNU tar */ + bsdtar->extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER; + break; + case 'L': /* BSD convention */ + bsdtar->symlink_mode = 'L'; + break; + case 'l': /* SUSv2 and GNU tar beginning with 1.16 */ + /* GNU tar 1.13 used -l for --one-file-system */ + bsdtar->flags |= OPTFLAG_WARN_LINKS; + break; + case OPTION_LRZIP: + case OPTION_LZ4: + case OPTION_LZIP: /* GNU tar beginning with 1.23 */ + case OPTION_LZMA: /* GNU tar beginning with 1.20 */ + case OPTION_LZOP: /* GNU tar beginning with 1.21 */ + case OPTION_ZSTD: + if (compression != '\0') + lafe_errc(1, 0, + "Can't specify both -%c and -%c", opt, + compression); + compression = opt; + switch (opt) { + case OPTION_LRZIP: compression_name = "lrzip"; break; + case OPTION_LZ4: compression_name = "lz4"; break; + case OPTION_LZIP: compression_name = "lzip"; break; + case OPTION_LZMA: compression_name = "lzma"; break; + case OPTION_LZOP: compression_name = "lzop"; break; + case OPTION_ZSTD: compression_name = "zstd"; break; + } + break; + case 'm': /* SUSv2 */ + bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_TIME; + break; + case OPTION_MAC_METADATA: /* Mac OS X */ + bsdtar->readdisk_flags |= ARCHIVE_READDISK_MAC_COPYFILE; + bsdtar->extract_flags |= ARCHIVE_EXTRACT_MAC_METADATA; + bsdtar->flags |= OPTFLAG_MAC_METADATA; + break; + case 'n': /* GNU tar */ + bsdtar->flags |= OPTFLAG_NO_SUBDIRS; + break; + /* + * Selecting files by time: + * --newer-?time='date' Only files newer than 'date' + * --newer-?time-than='file' Only files newer than time + * on specified file (useful for incremental backups) + */ + case OPTION_NEWER_CTIME: /* GNU tar */ + if (archive_match_include_date(bsdtar->matching, + ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_NEWER, + bsdtar->argument) != ARCHIVE_OK) + lafe_errc(1, 0, "Error : %s", + archive_error_string(bsdtar->matching)); + break; + case OPTION_NEWER_CTIME_THAN: + if (archive_match_include_file_time(bsdtar->matching, + ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_NEWER, + bsdtar->argument) != ARCHIVE_OK) + lafe_errc(1, 0, "Error : %s", + archive_error_string(bsdtar->matching)); + break; + case OPTION_NEWER_MTIME: /* GNU tar */ + if (archive_match_include_date(bsdtar->matching, + ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_NEWER, + bsdtar->argument) != ARCHIVE_OK) + lafe_errc(1, 0, "Error : %s", + archive_error_string(bsdtar->matching)); + break; + case OPTION_NEWER_MTIME_THAN: + if (archive_match_include_file_time(bsdtar->matching, + ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_NEWER, + bsdtar->argument) != ARCHIVE_OK) + lafe_errc(1, 0, "Error : %s", + archive_error_string(bsdtar->matching)); + break; + case OPTION_NODUMP: /* star */ + bsdtar->readdisk_flags |= ARCHIVE_READDISK_HONOR_NODUMP; + break; + case OPTION_NOPRESERVE_HFS_COMPRESSION: + /* Mac OS X v10.6 or later */ + bsdtar->extract_flags |= + ARCHIVE_EXTRACT_NO_HFS_COMPRESSION; + break; + case OPTION_NO_ACLS: /* GNU tar */ + bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_ACL; + bsdtar->readdisk_flags |= ARCHIVE_READDISK_NO_ACL; + bsdtar->flags |= OPTFLAG_NO_ACLS; + break; + case OPTION_NO_FFLAGS: + bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_FFLAGS; + bsdtar->readdisk_flags |= ARCHIVE_READDISK_NO_FFLAGS; + bsdtar->flags |= OPTFLAG_NO_FFLAGS; + break; + case OPTION_NO_MAC_METADATA: /* Mac OS X */ + bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_MAC_COPYFILE; + bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_MAC_METADATA; + bsdtar->flags |= OPTFLAG_NO_MAC_METADATA; + break; + case OPTION_NO_SAFE_WRITES: + bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_SAFE_WRITES; + break; + case OPTION_NO_SAME_OWNER: /* GNU tar */ + bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_OWNER; + break; + case OPTION_NO_SAME_PERMISSIONS: /* GNU tar */ + bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_PERM; + bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_ACL; + bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_XATTR; + bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_FFLAGS; + bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_MAC_METADATA; + break; + case OPTION_NO_XATTRS: /* GNU tar */ + bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_XATTR; + bsdtar->readdisk_flags |= ARCHIVE_READDISK_NO_XATTR; + bsdtar->flags |= OPTFLAG_NO_XATTRS; + break; + case OPTION_NULL: /* GNU tar */ + bsdtar->flags |= OPTFLAG_NULL; + break; + case OPTION_NUMERIC_OWNER: /* GNU tar */ + bsdtar->uname = ""; + bsdtar->gname = ""; + bsdtar->flags |= OPTFLAG_NUMERIC_OWNER; + break; + case 'O': /* GNU tar */ + bsdtar->flags |= OPTFLAG_STDOUT; + break; + case 'o': /* SUSv2 and GNU conflict here, but not fatally */ + bsdtar->flags |= OPTFLAG_O; + break; + /* + * Selecting files by time: + * --older-?time='date' Only files older than 'date' + * --older-?time-than='file' Only files older than time + * on specified file + */ + case OPTION_OLDER_CTIME: + if (archive_match_include_date(bsdtar->matching, + ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_OLDER, + bsdtar->argument) != ARCHIVE_OK) + lafe_errc(1, 0, "Error : %s", + archive_error_string(bsdtar->matching)); + break; + case OPTION_OLDER_CTIME_THAN: + if (archive_match_include_file_time(bsdtar->matching, + ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_OLDER, + bsdtar->argument) != ARCHIVE_OK) + lafe_errc(1, 0, "Error : %s", + archive_error_string(bsdtar->matching)); + break; + case OPTION_OLDER_MTIME: + if (archive_match_include_date(bsdtar->matching, + ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER, + bsdtar->argument) != ARCHIVE_OK) + lafe_errc(1, 0, "Error : %s", + archive_error_string(bsdtar->matching)); + break; + case OPTION_OLDER_MTIME_THAN: + if (archive_match_include_file_time(bsdtar->matching, + ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER, + bsdtar->argument) != ARCHIVE_OK) + lafe_errc(1, 0, "Error : %s", + archive_error_string(bsdtar->matching)); + break; + case OPTION_ONE_FILE_SYSTEM: /* GNU tar */ + bsdtar->readdisk_flags |= + ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS; + break; + case OPTION_OPTIONS: + bsdtar->option_options = bsdtar->argument; + break; +#if 0 + /* + * The common BSD -P option is not necessary, since + * our default is to archive symlinks, not follow + * them. This is convenient, as -P conflicts with GNU + * tar anyway. + */ + case 'P': /* BSD convention */ + /* Default behavior, no option necessary. */ + break; +#endif + case 'P': /* GNU tar */ + bsdtar->extract_flags &= ~SECURITY; + bsdtar->flags |= OPTFLAG_ABSOLUTE_PATHS; + break; + case 'p': /* GNU tar, star */ + bsdtar->extract_flags |= ARCHIVE_EXTRACT_PERM; + bsdtar->extract_flags |= ARCHIVE_EXTRACT_ACL; + bsdtar->extract_flags |= ARCHIVE_EXTRACT_XATTR; + bsdtar->extract_flags |= ARCHIVE_EXTRACT_FFLAGS; + bsdtar->extract_flags |= ARCHIVE_EXTRACT_MAC_METADATA; + break; + case OPTION_PASSPHRASE: + bsdtar->passphrase = bsdtar->argument; + break; + case OPTION_POSIX: /* GNU tar */ + cset_set_format(bsdtar->cset, "pax"); + break; + case 'q': /* FreeBSD GNU tar --fast-read, NetBSD -q */ + bsdtar->flags |= OPTFLAG_FAST_READ; + break; + case 'r': /* SUSv2 */ + set_mode(bsdtar, opt); + break; + case 'S': /* NetBSD pax-as-tar */ + bsdtar->extract_flags |= ARCHIVE_EXTRACT_SPARSE; + break; + case 's': /* NetBSD pax-as-tar */ +#if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H) + add_substitution(bsdtar, bsdtar->argument); +#else + lafe_warnc(0, + "-s is not supported by this version of bsdtar"); + usage(); +#endif + break; + case OPTION_SAFE_WRITES: + bsdtar->extract_flags |= ARCHIVE_EXTRACT_SAFE_WRITES; + break; + case OPTION_SAME_OWNER: /* GNU tar */ + bsdtar->extract_flags |= ARCHIVE_EXTRACT_OWNER; + break; + case OPTION_STRIP_COMPONENTS: /* GNU tar 1.15 */ + errno = 0; + tptr = NULL; + t = (int)strtol(bsdtar->argument, &tptr, 10); + if (errno || t < 0 || *(bsdtar->argument) == '\0' || + tptr == NULL || *tptr != '\0') { + lafe_errc(1, 0, "Invalid argument to " + "--strip-components"); + } + bsdtar->strip_components = t; + break; + case 'T': /* GNU tar */ + bsdtar->names_from_file = bsdtar->argument; + break; + case 't': /* SUSv2 */ + set_mode(bsdtar, opt); + bsdtar->verbose++; + break; + case OPTION_TOTALS: /* GNU tar */ + bsdtar->flags |= OPTFLAG_TOTALS; + break; + case 'U': /* GNU tar */ + bsdtar->extract_flags |= ARCHIVE_EXTRACT_UNLINK; + bsdtar->flags |= OPTFLAG_UNLINK_FIRST; + break; + case 'u': /* SUSv2 */ + set_mode(bsdtar, opt); + break; + case OPTION_UID: /* cpio */ + errno = 0; + tptr = NULL; + t = (int)strtol(bsdtar->argument, &tptr, 10); + if (errno || t < 0 || *(bsdtar->argument) == '\0' || + tptr == NULL || *tptr != '\0') { + lafe_errc(1, 0, "Invalid argument to --uid"); + } + bsdtar->uid = t; + break; + case OPTION_UNAME: /* cpio */ + bsdtar->uname = bsdtar->argument; + break; + case OPTION_UUENCODE: + if (compression2 != '\0') + lafe_errc(1, 0, + "Can't specify both --uuencode and " + "--b64encode"); + compression2 = opt; + compression2_name = "uuencode"; + break; + case 'v': /* SUSv2 */ + bsdtar->verbose++; + break; + case OPTION_VERSION: /* GNU convention */ + version(); + break; +#if 0 + /* + * The -W longopt feature is handled inside of + * bsdtar_getopt(), so -W is not available here. + */ + case 'W': /* Obscure GNU convention. */ + break; +#endif + case 'w': /* SUSv2 */ + bsdtar->flags |= OPTFLAG_INTERACTIVE; + break; + case 'X': /* GNU tar */ + if (archive_match_exclude_pattern_from_file( + bsdtar->matching, bsdtar->argument, 0) + != ARCHIVE_OK) + lafe_errc(1, 0, "Error : %s", + archive_error_string(bsdtar->matching)); + break; + case 'x': /* SUSv2 */ + set_mode(bsdtar, opt); + break; + case OPTION_XATTRS: /* GNU tar */ + bsdtar->extract_flags |= ARCHIVE_EXTRACT_XATTR; + bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_NO_XATTR; + bsdtar->flags |= OPTFLAG_XATTRS; + break; + case 'y': /* FreeBSD version of GNU tar */ + if (compression != '\0') + lafe_errc(1, 0, + "Can't specify both -%c and -%c", opt, + compression); + compression = opt; + compression_name = "bzip2"; + break; + case 'Z': /* GNU tar */ + if (compression != '\0') + lafe_errc(1, 0, + "Can't specify both -%c and -%c", opt, + compression); + compression = opt; + compression_name = "compress"; + break; + case 'z': /* GNU tar, star, many others */ + if (compression != '\0') + lafe_errc(1, 0, + "Can't specify both -%c and -%c", opt, + compression); + compression = opt; + compression_name = "gzip"; + break; + case OPTION_USE_COMPRESS_PROGRAM: + compress_program = bsdtar->argument; + break; + default: + usage(); + } + } + + /* + * Sanity-check options. + */ + + /* If no "real" mode was specified, treat -h as --help. */ + if ((bsdtar->mode == '\0') && possible_help_request) { + long_help(); + exit(0); + } + + /* Otherwise, a mode is required. */ + if (bsdtar->mode == '\0') + lafe_errc(1, 0, + "Must specify one of -c, -r, -t, -u, -x"); + + /* Check boolean options only permitted in certain modes. */ + if (bsdtar->flags & OPTFLAG_AUTO_COMPRESS) + only_mode(bsdtar, "-a", "c"); + if (bsdtar->readdisk_flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) + only_mode(bsdtar, "--one-file-system", "cru"); + if (bsdtar->flags & OPTFLAG_FAST_READ) + only_mode(bsdtar, "--fast-read", "xt"); + if (bsdtar->extract_flags & ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED) + only_mode(bsdtar, "--hfsCompression", "x"); + if (bsdtar->extract_flags & ARCHIVE_EXTRACT_NO_HFS_COMPRESSION) + only_mode(bsdtar, "--nopreserveHFSCompression", "x"); + if (bsdtar->readdisk_flags & ARCHIVE_READDISK_HONOR_NODUMP) + only_mode(bsdtar, "--nodump", "cru"); + if (bsdtar->flags & OPTFLAG_ACLS) + only_mode(bsdtar, "--acls", "crux"); + if (bsdtar->flags & OPTFLAG_NO_ACLS) + only_mode(bsdtar, "--no-acls", "crux"); + if (bsdtar->flags & OPTFLAG_XATTRS) + only_mode(bsdtar, "--xattrs", "crux"); + if (bsdtar->flags & OPTFLAG_NO_XATTRS) + only_mode(bsdtar, "--no-xattrs", "crux"); + if (bsdtar->flags & OPTFLAG_FFLAGS) + only_mode(bsdtar, "--fflags", "crux"); + if (bsdtar->flags & OPTFLAG_NO_FFLAGS) + only_mode(bsdtar, "--no-fflags", "crux"); + if (bsdtar->flags & OPTFLAG_MAC_METADATA) + only_mode(bsdtar, "--mac-metadata", "crux"); + if (bsdtar->flags & OPTFLAG_NO_MAC_METADATA) + only_mode(bsdtar, "--no-mac-metadata", "crux"); + if (bsdtar->flags & OPTFLAG_O) { + switch (bsdtar->mode) { + case 'c': + /* + * In GNU tar, -o means "old format." The + * "ustar" format is the closest thing + * supported by libarchive. + */ + cset_set_format(bsdtar->cset, "ustar"); + /* TODO: bsdtar->create_format = "v7"; */ + break; + case 'x': + /* POSIX-compatible behavior. */ + bsdtar->flags |= OPTFLAG_NO_OWNER; + bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_OWNER; + break; + default: + only_mode(bsdtar, "-o", "xc"); + break; + } + } + if (bsdtar->flags & OPTFLAG_STDOUT) + only_mode(bsdtar, "-O", "xt"); + if (bsdtar->flags & OPTFLAG_UNLINK_FIRST) + only_mode(bsdtar, "-U", "x"); + if (bsdtar->flags & OPTFLAG_WARN_LINKS) + only_mode(bsdtar, "--check-links", "cr"); + + if ((bsdtar->flags & OPTFLAG_AUTO_COMPRESS) && + cset_auto_compress(bsdtar->cset, bsdtar->filename)) { + /* Ignore specified compressions if auto-compress works. */ + compression = '\0'; + compression2 = '\0'; + } + /* Check other parameters only permitted in certain modes. */ + if (compress_program != NULL) { + only_mode(bsdtar, "--use-compress-program", "cxt"); + cset_add_filter_program(bsdtar->cset, compress_program); + /* Ignore specified compressions. */ + compression = '\0'; + compression2 = '\0'; + } + if (compression != '\0') { + switch (compression) { + case 'J': case 'j': case 'y': case 'Z': case 'z': + strcpy(buff, "-?"); + buff[1] = compression; + break; + default: + strcpy(buff, "--"); + strcat(buff, compression_name); + break; + } + only_mode(bsdtar, buff, "cxt"); + cset_add_filter(bsdtar->cset, compression_name); + } + if (compression2 != '\0') { + strcpy(buff, "--"); + strcat(buff, compression2_name); + only_mode(bsdtar, buff, "cxt"); + cset_add_filter(bsdtar->cset, compression2_name); + } + if (cset_get_format(bsdtar->cset) != NULL) + only_mode(bsdtar, "--format", "cru"); + if (bsdtar->symlink_mode != '\0') { + strcpy(buff, "-?"); + buff[1] = bsdtar->symlink_mode; + only_mode(bsdtar, buff, "cru"); + } + + /* + * When creating an archive from a directory tree, the directory + * walking code will already avoid entering directories when + * recursive inclusion of directory content is disabled, therefore + * changing the matching behavior has no effect for creation modes. + * It is relevant for extraction or listing. + */ + archive_match_set_inclusion_recursion(bsdtar->matching, + !(bsdtar->flags & OPTFLAG_NO_SUBDIRS)); + + /* Filename "-" implies stdio. */ + if (strcmp(bsdtar->filename, "-") == 0) + bsdtar->filename = NULL; + + switch(bsdtar->mode) { + case 'c': + tar_mode_c(bsdtar); + break; + case 'r': + tar_mode_r(bsdtar); + break; + case 't': + tar_mode_t(bsdtar); + break; + case 'u': + tar_mode_u(bsdtar); + break; + case 'x': + tar_mode_x(bsdtar); + break; + } + + archive_match_free(bsdtar->matching); +#if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H) + cleanup_substitution(bsdtar); +#endif + cset_free(bsdtar->cset); + passphrase_free(bsdtar->ppbuff); + + if (bsdtar->return_value != 0) + lafe_warnc(0, + "Error exit delayed from previous errors."); + return (bsdtar->return_value); +} + +static void +set_mode(struct bsdtar *bsdtar, char opt) +{ + if (bsdtar->mode != '\0' && bsdtar->mode != opt) + lafe_errc(1, 0, + "Can't specify both -%c and -%c", opt, bsdtar->mode); + bsdtar->mode = opt; +} + +/* + * Verify that the mode is correct. + */ +static void +only_mode(struct bsdtar *bsdtar, const char *opt, const char *valid_modes) +{ + if (strchr(valid_modes, bsdtar->mode) == NULL) + lafe_errc(1, 0, + "Option %s is not permitted in mode -%c", + opt, bsdtar->mode); +} + + +void +usage(void) +{ + const char *p; + + p = lafe_getprogname(); + + fprintf(stderr, "Usage:\n"); + fprintf(stderr, " List: %s -tf \n", p); + fprintf(stderr, " Extract: %s -xf \n", p); + fprintf(stderr, " Create: %s -cf [filenames...]\n", p); + fprintf(stderr, " Help: %s --help\n", p); + exit(1); +} + +static void +version(void) +{ + printf("bsdtar %s - %s \n", + BSDTAR_VERSION_STRING, + archive_version_details()); + exit(0); +} + +static const char *long_help_msg = + "First option must be a mode specifier:\n" + " -c Create -r Add/Replace -t List -u Update -x Extract\n" + "Common Options:\n" + " -b # Use # 512-byte records per I/O block\n" + " -f Location of archive (default " _PATH_DEFTAPE ")\n" + " -v Verbose\n" + " -w Interactive\n" + "Create: %p -c [options] [ |

    | @ | -C ]\n" + " , add these items to archive\n" + " -z, -j, -J, --lzma Compress archive with gzip/bzip2/xz/lzma\n" + " --format {ustar|pax|cpio|shar} Select archive format\n" + " --exclude Skip files that match pattern\n" + " -C Change to before processing remaining files\n" + " @ Add entries from to output\n" + "List: %p -t [options] []\n" + " If specified, list only entries that match\n" + "Extract: %p -x [options] []\n" + " If specified, extract only entries that match\n" + " -k Keep (don't overwrite) existing files\n" + " -m Don't restore modification times\n" + " -O Write entries to stdout, don't restore to disk\n" + " -p Restore permissions (including ACLs, owner, file flags)\n"; + + +/* + * Note that the word 'bsdtar' will always appear in the first line + * of output. + * + * In particular, /bin/sh scripts that need to test for the presence + * of bsdtar can use the following template: + * + * if (tar --help 2>&1 | grep bsdtar >/dev/null 2>&1 ) then \ + * echo bsdtar; else echo not bsdtar; fi + */ +static void +long_help(void) +{ + const char *prog; + const char *p; + + prog = lafe_getprogname(); + + fflush(stderr); + + p = (strcmp(prog,"bsdtar") != 0) ? "(bsdtar)" : ""; + printf("%s%s: manipulate archive files\n", prog, p); + + for (p = long_help_msg; *p != '\0'; p++) { + if (*p == '%') { + if (p[1] == 'p') { + fputs(prog, stdout); + p++; + } else + putchar('%'); + } else + putchar(*p); + } + version(); +} diff --git a/dependencies/libarchive-3.4.2/tar/bsdtar.h b/dependencies/libarchive-3.4.2/tar/bsdtar.h new file mode 100644 index 0000000..89aa3aa --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/bsdtar.h @@ -0,0 +1,233 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: src/usr.bin/tar/bsdtar.h,v 1.37 2008/12/06 07:37:14 kientzle Exp $ + */ + +#ifndef BSDTAR_H_INCLUDED +#define BSDTAR_H_INCLUDED + +#include "bsdtar_platform.h" +#include + +#define DEFAULT_BYTES_PER_BLOCK (20*512) +#define ENV_READER_OPTIONS "TAR_READER_OPTIONS" +#define ENV_WRITER_OPTIONS "TAR_WRITER_OPTIONS" +#define IGNORE_WRONG_MODULE_NAME "__ignore_wrong_module_name__," + +struct creation_set; +/* + * The internal state for the "bsdtar" program. + * + * Keeping all of the state in a structure like this simplifies memory + * leak testing (at exit, anything left on the heap is suspect). A + * pointer to this structure is passed to most bsdtar internal + * functions. + */ +struct bsdtar { + /* Options */ + const char *filename; /* -f filename */ + char *pending_chdir; /* -C dir */ + const char *names_from_file; /* -T file */ + int bytes_per_block; /* -b block_size */ + int bytes_in_last_block; /* See -b handling. */ + int verbose; /* -v */ + unsigned int flags; /* Bitfield of boolean options */ + int extract_flags; /* Flags for extract operation */ + int readdisk_flags; /* Flags for read disk operation */ + int strip_components; /* Remove this many leading dirs */ + int gid; /* --gid */ + const char *gname; /* --gname */ + int uid; /* --uid */ + const char *uname; /* --uname */ + const char *passphrase; /* --passphrase */ + char mode; /* Program mode: 'c', 't', 'r', 'u', 'x' */ + char symlink_mode; /* H or L, per BSD conventions */ + const char *option_options; /* --options */ + char day_first; /* show day before month in -tv output */ + struct creation_set *cset; + + /* Option parser state */ + int getopt_state; + char *getopt_word; + + /* If >= 0, then close this when done. */ + int fd; + + /* Miscellaneous state information */ + int argc; + char **argv; + const char *argument; + size_t gs_width; /* For 'list_item' in read.c */ + size_t u_width; /* for 'list_item' in read.c */ + uid_t user_uid; /* UID running this program */ + int return_value; /* Value returned by main() */ + char warned_lead_slash; /* Already displayed warning */ + char next_line_is_dir; /* Used for -C parsing in -cT */ + + /* + * Data for various subsystems. Full definitions are located in + * the file where they are used. + */ + struct archive *diskreader; /* for write.c */ + struct archive_entry_linkresolver *resolver; /* for write.c */ + struct archive_dir *archive_dir; /* for write.c */ + struct name_cache *gname_cache; /* for write.c */ + char *buff; /* for write.c */ + size_t buff_size; /* for write.c */ + int first_fs; /* for write.c */ + struct archive *matching; /* for matching.c */ + struct security *security; /* for read.c */ + struct name_cache *uname_cache; /* for write.c */ + struct siginfo_data *siginfo; /* for siginfo.c */ + struct substitution *substitution; /* for subst.c */ + char *ppbuff; /* for util.c */ +}; + +/* Options for flags bitfield */ +#define OPTFLAG_AUTO_COMPRESS (0x00000001) /* -a */ +#define OPTFLAG_ABSOLUTE_PATHS (0x00000002) /* -P */ +#define OPTFLAG_CHROOT (0x00000004) /* --chroot */ +#define OPTFLAG_FAST_READ (0x00000008) /* --fast-read */ +#define OPTFLAG_IGNORE_ZEROS (0x00000010) /* --ignore-zeros */ +#define OPTFLAG_INTERACTIVE (0x00000020) /* -w */ +#define OPTFLAG_NO_OWNER (0x00000040) /* -o */ +#define OPTFLAG_NO_SUBDIRS (0x00000080) /* -n */ +#define OPTFLAG_NULL (0x00000100) /* --null */ +#define OPTFLAG_NUMERIC_OWNER (0x00000200) /* --numeric-owner */ +#define OPTFLAG_O (0x00000400) /* -o */ +#define OPTFLAG_STDOUT (0x00000800) /* -O */ +#define OPTFLAG_TOTALS (0x00001000) /* --totals */ +#define OPTFLAG_UNLINK_FIRST (0x00002000) /* -U */ +#define OPTFLAG_WARN_LINKS (0x00004000) /* --check-links */ +#define OPTFLAG_NO_XATTRS (0x00008000) /* --no-xattrs */ +#define OPTFLAG_XATTRS (0x00010000) /* --xattrs */ +#define OPTFLAG_NO_ACLS (0x00020000) /* --no-acls */ +#define OPTFLAG_ACLS (0x00040000) /* --acls */ +#define OPTFLAG_NO_FFLAGS (0x00080000) /* --no-fflags */ +#define OPTFLAG_FFLAGS (0x00100000) /* --fflags */ +#define OPTFLAG_NO_MAC_METADATA (0x00200000) /* --no-mac-metadata */ +#define OPTFLAG_MAC_METADATA (0x00400000) /* --mac-metadata */ + +/* Fake short equivalents for long options that otherwise lack them. */ +enum { + OPTION_ACLS = 1, + OPTION_B64ENCODE, + OPTION_CHECK_LINKS, + OPTION_CHROOT, + OPTION_CLEAR_NOCHANGE_FFLAGS, + OPTION_EXCLUDE, + OPTION_EXCLUDE_VCS, + OPTION_FFLAGS, + OPTION_FORMAT, + OPTION_GID, + OPTION_GNAME, + OPTION_GRZIP, + OPTION_HELP, + OPTION_HFS_COMPRESSION, + OPTION_IGNORE_ZEROS, + OPTION_INCLUDE, + OPTION_KEEP_NEWER_FILES, + OPTION_LRZIP, + OPTION_LZ4, + OPTION_LZIP, + OPTION_LZMA, + OPTION_LZOP, + OPTION_MAC_METADATA, + OPTION_NEWER_CTIME, + OPTION_NEWER_CTIME_THAN, + OPTION_NEWER_MTIME, + OPTION_NEWER_MTIME_THAN, + OPTION_NODUMP, + OPTION_NOPRESERVE_HFS_COMPRESSION, + OPTION_NO_ACLS, + OPTION_NO_FFLAGS, + OPTION_NO_MAC_METADATA, + OPTION_NO_SAFE_WRITES, + OPTION_NO_SAME_OWNER, + OPTION_NO_SAME_PERMISSIONS, + OPTION_NO_XATTRS, + OPTION_NULL, + OPTION_NUMERIC_OWNER, + OPTION_OLDER_CTIME, + OPTION_OLDER_CTIME_THAN, + OPTION_OLDER_MTIME, + OPTION_OLDER_MTIME_THAN, + OPTION_ONE_FILE_SYSTEM, + OPTION_OPTIONS, + OPTION_PASSPHRASE, + OPTION_POSIX, + OPTION_SAFE_WRITES, + OPTION_SAME_OWNER, + OPTION_STRIP_COMPONENTS, + OPTION_TOTALS, + OPTION_UID, + OPTION_UNAME, + OPTION_USE_COMPRESS_PROGRAM, + OPTION_UUENCODE, + OPTION_VERSION, + OPTION_XATTRS, + OPTION_ZSTD, +}; + +int bsdtar_getopt(struct bsdtar *); +void do_chdir(struct bsdtar *); +int edit_pathname(struct bsdtar *, struct archive_entry *); +int need_report(void); +int pathcmp(const char *a, const char *b); +void safe_fprintf(FILE *, const char *fmt, ...) __LA_PRINTF(2, 3); +void set_chdir(struct bsdtar *, const char *newdir); +const char *tar_i64toa(int64_t); +void tar_mode_c(struct bsdtar *bsdtar); +void tar_mode_r(struct bsdtar *bsdtar); +void tar_mode_t(struct bsdtar *bsdtar); +void tar_mode_u(struct bsdtar *bsdtar); +void tar_mode_x(struct bsdtar *bsdtar); +void usage(void) __LA_DEAD; +int yes(const char *fmt, ...) __LA_PRINTF(1, 2); + +#if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H) +void add_substitution(struct bsdtar *, const char *); +int apply_substitution(struct bsdtar *, const char *, char **, int, int); +void cleanup_substitution(struct bsdtar *); +#endif + +void cset_add_filter(struct creation_set *, const char *); +void cset_add_filter_program(struct creation_set *, const char *); +int cset_auto_compress(struct creation_set *, const char *); +void cset_free(struct creation_set *); +const char * cset_get_format(struct creation_set *); +struct creation_set *cset_new(void); +int cset_read_support_filter_program(struct creation_set *, + struct archive *); +void cset_set_format(struct creation_set *, const char *); +int cset_write_add_filters(struct creation_set *, + struct archive *, const void **); + +const char * passphrase_callback(struct archive *, void *); +void passphrase_free(char *); +void list_item_verbose(struct bsdtar *, FILE *, + struct archive_entry *); + +#endif diff --git a/dependencies/libarchive-3.4.2/tar/bsdtar_platform.h b/dependencies/libarchive-3.4.2/tar/bsdtar_platform.h new file mode 100644 index 0000000..e73f982 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/bsdtar_platform.h @@ -0,0 +1,132 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: src/usr.bin/tar/bsdtar_platform.h,v 1.26 2008/12/06 07:37:14 kientzle Exp $ + */ + +/* + * This header is the first thing included in any of the bsdtar + * source files. As far as possible, platform-specific issues should + * be dealt with here and not within individual source files. + */ + +#ifndef BSDTAR_PLATFORM_H_INCLUDED +#define BSDTAR_PLATFORM_H_INCLUDED + +#if defined(PLATFORM_CONFIG_H) +/* Use hand-built config.h in environments that need it. */ +#include PLATFORM_CONFIG_H +#else +/* Not having a config.h of some sort is a serious problem. */ +#include "config.h" +#endif + +#if defined(_WIN32) && !defined(__CYGWIN__) +#include "bsdtar_windows.h" +#endif + +/* Get a real definition for __FBSDID if we can */ +#if HAVE_SYS_CDEFS_H +#include +#endif + +/* If not, define it so as to avoid dangling semicolons. */ +#ifndef __FBSDID +#define __FBSDID(a) struct _undefined_hack +#endif + +#ifdef HAVE_LIBARCHIVE +/* If we're using the platform libarchive, include system headers. */ +#include +#include +#else +/* Otherwise, include user headers. */ +#include "archive.h" +#include "archive_entry.h" +#endif + +#ifdef HAVE_LIBACL +#include +#endif + +/* + * Include "dirent.h" (or its equivalent on several different platforms). + * + * This is slightly modified from the GNU autoconf recipe. + * In particular, FreeBSD includes d_namlen in its dirent structure, + * so my configure script includes an explicit test for the d_namlen + * field. + */ +#if HAVE_DIRENT_H +# include +# if HAVE_DIRENT_D_NAMLEN +# define DIRENT_NAMLEN(dirent) (dirent)->d_namlen +# else +# define DIRENT_NAMLEN(dirent) strlen((dirent)->d_name) +# endif +#else +# define dirent direct +# define DIRENT_NAMLEN(dirent) (dirent)->d_namlen +# if HAVE_SYS_NDIR_H +# include +# endif +# if HAVE_SYS_DIR_H +# include +# endif +# if HAVE_NDIR_H +# include +# endif +#endif + +#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC +#define ARCHIVE_STAT_CTIME_NANOS(st) (st)->st_ctimespec.tv_nsec +#define ARCHIVE_STAT_MTIME_NANOS(st) (st)->st_mtimespec.tv_nsec +#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC +#define ARCHIVE_STAT_CTIME_NANOS(st) (st)->st_ctim.tv_nsec +#define ARCHIVE_STAT_MTIME_NANOS(st) (st)->st_mtim.tv_nsec +#elif HAVE_STRUCT_STAT_ST_MTIME_N +#define ARCHIVE_STAT_CTIME_NANOS(st) (st)->st_ctime_n +#define ARCHIVE_STAT_MTIME_NANOS(st) (st)->st_mtime_n +#elif HAVE_STRUCT_STAT_ST_UMTIME +#define ARCHIVE_STAT_CTIME_NANOS(st) (st)->st_uctime * 1000 +#define ARCHIVE_STAT_MTIME_NANOS(st) (st)->st_umtime * 1000 +#elif HAVE_STRUCT_STAT_ST_MTIME_USEC +#define ARCHIVE_STAT_CTIME_NANOS(st) (st)->st_ctime_usec * 1000 +#define ARCHIVE_STAT_MTIME_NANOS(st) (st)->st_mtime_usec * 1000 +#else +#define ARCHIVE_STAT_CTIME_NANOS(st) (0) +#define ARCHIVE_STAT_MTIME_NANOS(st) (0) +#endif + +/* How to mark functions that don't return. */ +/* This facilitates use of some newer static code analysis tools. */ +#undef __LA_DEAD +#if defined(__GNUC__) && (__GNUC__ > 2 || \ + (__GNUC__ == 2 && __GNUC_MINOR__ >= 5)) +#define __LA_DEAD __attribute__((__noreturn__)) +#else +#define __LA_DEAD +#endif + +#endif /* !BSDTAR_PLATFORM_H_INCLUDED */ diff --git a/dependencies/libarchive-3.4.2/tar/bsdtar_windows.c b/dependencies/libarchive-3.4.2/tar/bsdtar_windows.c new file mode 100644 index 0000000..41ce6eb --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/bsdtar_windows.c @@ -0,0 +1,298 @@ +/*- + * Copyright (c) 2009 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#if defined(_WIN32) && !defined(__CYGWIN__) + +#include "bsdtar_platform.h" +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_UTIME_H +#include +#endif +#include +#include +#include +#include +#include +#include + +#include "bsdtar.h" +#include "err.h" + +/* This may actually not be needed anymore. + * TODO: Review the error handling for chdir() failures and + * simply dump this if it's not really needed. */ +static void __tar_dosmaperr(unsigned long); + +/* + * Prepend "\\?\" to the path name and convert it to unicode to permit + * an extended-length path for a maximum total path length of 32767 + * characters. + * see also http://msdn.microsoft.com/en-us/library/aa365247.aspx + */ +static wchar_t * +permissive_name(const char *name) +{ + wchar_t *wn, *wnp; + wchar_t *ws, *wsp; + DWORD l, len, slen, alloclen; + int unc; + + len = (DWORD)strlen(name); + wn = malloc((len + 1) * sizeof(wchar_t)); + if (wn == NULL) + return (NULL); + l = MultiByteToWideChar(CP_ACP, 0, name, len, wn, len); + if (l == 0) { + free(wn); + return (NULL); + } + wn[l] = L'\0'; + + /* Get a full path names */ + l = GetFullPathNameW(wn, 0, NULL, NULL); + if (l == 0) { + free(wn); + return (NULL); + } + wnp = malloc(l * sizeof(wchar_t)); + if (wnp == NULL) { + free(wn); + return (NULL); + } + len = GetFullPathNameW(wn, l, wnp, NULL); + free(wn); + wn = wnp; + + if (wnp[0] == L'\\' && wnp[1] == L'\\' && + wnp[2] == L'?' && wnp[3] == L'\\') + /* We have already permissive names. */ + return (wn); + + if (wnp[0] == L'\\' && wnp[1] == L'\\' && + wnp[2] == L'.' && wnp[3] == L'\\') { + /* Device names */ + if (((wnp[4] >= L'a' && wnp[4] <= L'z') || + (wnp[4] >= L'A' && wnp[4] <= L'Z')) && + wnp[5] == L':' && wnp[6] == L'\\') + wnp[2] = L'?';/* Not device names. */ + return (wn); + } + + unc = 0; + if (wnp[0] == L'\\' && wnp[1] == L'\\' && wnp[2] != L'\\') { + wchar_t *p = &wnp[2]; + + /* Skip server-name letters. */ + while (*p != L'\\' && *p != L'\0') + ++p; + if (*p == L'\\') { + wchar_t *rp = ++p; + /* Skip share-name letters. */ + while (*p != L'\\' && *p != L'\0') + ++p; + if (*p == L'\\' && p != rp) { + /* Now, match patterns such as + * "\\server-name\share-name\" */ + wnp += 2; + len -= 2; + unc = 1; + } + } + } + + alloclen = slen = 4 + (unc * 4) + len + 1; + ws = wsp = malloc(slen * sizeof(wchar_t)); + if (ws == NULL) { + free(wn); + return (NULL); + } + /* prepend "\\?\" */ + wcsncpy(wsp, L"\\\\?\\", 4); + wsp += 4; + slen -= 4; + if (unc) { + /* append "UNC\" ---> "\\?\UNC\" */ + wcsncpy(wsp, L"UNC\\", 4); + wsp += 4; + slen -= 4; + } + wcsncpy(wsp, wnp, slen); + free(wn); + ws[alloclen - 1] = L'\0'; + return (ws); +} + +int +__tar_chdir(const char *path) +{ + wchar_t *ws; + int r; + + r = SetCurrentDirectoryA(path); + if (r == 0) { + if (GetLastError() != ERROR_FILE_NOT_FOUND) { + __tar_dosmaperr(GetLastError()); + return (-1); + } + } else + return (0); + ws = permissive_name(path); + if (ws == NULL) { + errno = EINVAL; + return (-1); + } + r = SetCurrentDirectoryW(ws); + free(ws); + if (r == 0) { + __tar_dosmaperr(GetLastError()); + return (-1); + } + return (0); +} + +/* + * The following function was modified from PostgreSQL sources and is + * subject to the copyright below. + */ +/*------------------------------------------------------------------------- + * + * win32error.c + * Map win32 error codes to errno values + * + * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group + * + * IDENTIFICATION + * $PostgreSQL: pgsql/src/port/win32error.c,v 1.4 2008/01/01 19:46:00 momjian Exp $ + * + *------------------------------------------------------------------------- + */ +/* +PostgreSQL Database Management System +(formerly known as Postgres, then as Postgres95) + +Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group + +Portions Copyright (c) 1994, The Regents of the University of California + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose, without fee, and without a written agreement +is hereby granted, provided that the above copyright notice and this +paragraph and the following two paragraphs appear in all copies. + +IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR +DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING +LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS +DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS +ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO +PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. +*/ + +static const struct { + DWORD winerr; + int doserr; +} doserrors[] = +{ + { ERROR_INVALID_FUNCTION, EINVAL }, + { ERROR_FILE_NOT_FOUND, ENOENT }, + { ERROR_PATH_NOT_FOUND, ENOENT }, + { ERROR_TOO_MANY_OPEN_FILES, EMFILE }, + { ERROR_ACCESS_DENIED, EACCES }, + { ERROR_INVALID_HANDLE, EBADF }, + { ERROR_ARENA_TRASHED, ENOMEM }, + { ERROR_NOT_ENOUGH_MEMORY, ENOMEM }, + { ERROR_INVALID_BLOCK, ENOMEM }, + { ERROR_BAD_ENVIRONMENT, E2BIG }, + { ERROR_BAD_FORMAT, ENOEXEC }, + { ERROR_INVALID_ACCESS, EINVAL }, + { ERROR_INVALID_DATA, EINVAL }, + { ERROR_INVALID_DRIVE, ENOENT }, + { ERROR_CURRENT_DIRECTORY, EACCES }, + { ERROR_NOT_SAME_DEVICE, EXDEV }, + { ERROR_NO_MORE_FILES, ENOENT }, + { ERROR_LOCK_VIOLATION, EACCES }, + { ERROR_SHARING_VIOLATION, EACCES }, + { ERROR_BAD_NETPATH, ENOENT }, + { ERROR_NETWORK_ACCESS_DENIED, EACCES }, + { ERROR_BAD_NET_NAME, ENOENT }, + { ERROR_FILE_EXISTS, EEXIST }, + { ERROR_CANNOT_MAKE, EACCES }, + { ERROR_FAIL_I24, EACCES }, + { ERROR_INVALID_PARAMETER, EINVAL }, + { ERROR_NO_PROC_SLOTS, EAGAIN }, + { ERROR_DRIVE_LOCKED, EACCES }, + { ERROR_BROKEN_PIPE, EPIPE }, + { ERROR_DISK_FULL, ENOSPC }, + { ERROR_INVALID_TARGET_HANDLE, EBADF }, + { ERROR_INVALID_HANDLE, EINVAL }, + { ERROR_WAIT_NO_CHILDREN, ECHILD }, + { ERROR_CHILD_NOT_COMPLETE, ECHILD }, + { ERROR_DIRECT_ACCESS_HANDLE, EBADF }, + { ERROR_NEGATIVE_SEEK, EINVAL }, + { ERROR_SEEK_ON_DEVICE, EACCES }, + { ERROR_DIR_NOT_EMPTY, ENOTEMPTY }, + { ERROR_NOT_LOCKED, EACCES }, + { ERROR_BAD_PATHNAME, ENOENT }, + { ERROR_MAX_THRDS_REACHED, EAGAIN }, + { ERROR_LOCK_FAILED, EACCES }, + { ERROR_ALREADY_EXISTS, EEXIST }, + { ERROR_FILENAME_EXCED_RANGE, ENOENT }, + { ERROR_NESTING_NOT_ALLOWED, EAGAIN }, + { ERROR_NOT_ENOUGH_QUOTA, ENOMEM } +}; + +static void +__tar_dosmaperr(unsigned long e) +{ + int i; + + if (e == 0) { + errno = 0; + return; + } + + for (i = 0; i < (int)sizeof(doserrors); i++) { + if (doserrors[i].winerr == e) { + errno = doserrors[i].doserr; + return; + } + } + + /* fprintf(stderr, "unrecognized win32 error code: %lu", e); */ + errno = EINVAL; + return; +} + +#endif diff --git a/dependencies/libarchive-3.4.2/tar/bsdtar_windows.h b/dependencies/libarchive-3.4.2/tar/bsdtar_windows.h new file mode 100644 index 0000000..308ad11 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/bsdtar_windows.h @@ -0,0 +1,66 @@ +/*- + * Copyright (c) 2009 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef BSDTAR_WINDOWS_H +#define BSDTAR_WINDOWS_H 1 +#include +#include +#include +#include + +#ifndef PRId64 +#define PRId64 "I64" +#endif +#define geteuid() 0 + +#ifndef __WATCOMC__ + +#ifndef S_IFIFO +#define S_IFIFO 0010000 /* pipe */ +#endif + +#include /* Must include before redefining 'strdup' */ +#if !defined(__BORLANDC__) +#define strdup _strdup +#endif +#if !defined(__BORLANDC__) +#define getcwd _getcwd +#endif + +#define chdir __tar_chdir +int __tar_chdir(const char *); + +#ifndef S_ISREG +#define S_ISREG(a) (a & _S_IFREG) +#endif +#ifndef S_ISBLK +#define S_ISBLK(a) (0) +#endif + +#endif + +#endif /* BSDTAR_WINDOWS_H */ diff --git a/dependencies/libarchive-3.4.2/tar/cmdline.c b/dependencies/libarchive-3.4.2/tar/cmdline.c new file mode 100644 index 0000000..b80937f --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/cmdline.c @@ -0,0 +1,417 @@ +/*- + * Copyright (c) 2003-2008 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Command line parser for tar. + */ + +#include "bsdtar_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "bsdtar.h" +#include "err.h" + +/* + * Short options for tar. Please keep this sorted. + */ +static const char *short_options + = "aBb:C:cf:HhI:JjkLlmnOoPpqrSs:T:tUuvW:wX:xyZz"; + +/* + * Long options for tar. Please keep this list sorted. + * + * The symbolic names for options that lack a short equivalent are + * defined in bsdtar.h. Also note that so far I've found no need + * to support optional arguments to long options. That would be + * a small change to the code below. + */ + +static const struct bsdtar_option { + const char *name; + int required; /* 1 if this option requires an argument. */ + int equivalent; /* Equivalent short option. */ +} tar_longopts[] = { + { "absolute-paths", 0, 'P' }, + { "append", 0, 'r' }, + { "acls", 0, OPTION_ACLS }, + { "auto-compress", 0, 'a' }, + { "b64encode", 0, OPTION_B64ENCODE }, + { "block-size", 1, 'b' }, + { "blocking-factor", 1, 'b' }, + { "bunzip2", 0, 'j' }, + { "bzip", 0, 'j' }, + { "bzip2", 0, 'j' }, + { "cd", 1, 'C' }, + { "check-links", 0, OPTION_CHECK_LINKS }, + { "chroot", 0, OPTION_CHROOT }, + { "clear-nochange-fflags", 0, OPTION_CLEAR_NOCHANGE_FFLAGS }, + { "compress", 0, 'Z' }, + { "confirmation", 0, 'w' }, + { "create", 0, 'c' }, + { "dereference", 0, 'L' }, + { "directory", 1, 'C' }, + { "disable-copyfile", 0, OPTION_NO_MAC_METADATA }, + { "exclude", 1, OPTION_EXCLUDE }, + { "exclude-from", 1, 'X' }, + { "exclude-vcs", 0, OPTION_EXCLUDE_VCS }, + { "extract", 0, 'x' }, + { "fast-read", 0, 'q' }, + { "fflags", 0, OPTION_FFLAGS }, + { "file", 1, 'f' }, + { "files-from", 1, 'T' }, + { "format", 1, OPTION_FORMAT }, + { "gid", 1, OPTION_GID }, + { "gname", 1, OPTION_GNAME }, + { "grzip", 0, OPTION_GRZIP }, + { "gunzip", 0, 'z' }, + { "gzip", 0, 'z' }, + { "help", 0, OPTION_HELP }, + { "hfsCompression", 0, OPTION_HFS_COMPRESSION }, + { "ignore-zeros", 0, OPTION_IGNORE_ZEROS }, + { "include", 1, OPTION_INCLUDE }, + { "insecure", 0, 'P' }, + { "interactive", 0, 'w' }, + { "keep-newer-files", 0, OPTION_KEEP_NEWER_FILES }, + { "keep-old-files", 0, 'k' }, + { "list", 0, 't' }, + { "lrzip", 0, OPTION_LRZIP }, + { "lz4", 0, OPTION_LZ4 }, + { "lzip", 0, OPTION_LZIP }, + { "lzma", 0, OPTION_LZMA }, + { "lzop", 0, OPTION_LZOP }, + { "mac-metadata", 0, OPTION_MAC_METADATA }, + { "modification-time", 0, 'm' }, + { "newer", 1, OPTION_NEWER_CTIME }, + { "newer-ctime", 1, OPTION_NEWER_CTIME }, + { "newer-ctime-than", 1, OPTION_NEWER_CTIME_THAN }, + { "newer-mtime", 1, OPTION_NEWER_MTIME }, + { "newer-mtime-than", 1, OPTION_NEWER_MTIME_THAN }, + { "newer-than", 1, OPTION_NEWER_CTIME_THAN }, + { "no-acls", 0, OPTION_NO_ACLS }, + { "no-fflags", 0, OPTION_NO_FFLAGS }, + { "no-mac-metadata", 0, OPTION_NO_MAC_METADATA }, + { "no-recursion", 0, 'n' }, + { "no-safe-writes", 0, OPTION_NO_SAFE_WRITES }, + { "no-same-owner", 0, OPTION_NO_SAME_OWNER }, + { "no-same-permissions", 0, OPTION_NO_SAME_PERMISSIONS }, + { "no-xattr", 0, OPTION_NO_XATTRS }, + { "no-xattrs", 0, OPTION_NO_XATTRS }, + { "nodump", 0, OPTION_NODUMP }, + { "nopreserveHFSCompression",0, OPTION_NOPRESERVE_HFS_COMPRESSION }, + { "norecurse", 0, 'n' }, + { "null", 0, OPTION_NULL }, + { "numeric-owner", 0, OPTION_NUMERIC_OWNER }, + { "older", 1, OPTION_OLDER_CTIME }, + { "older-ctime", 1, OPTION_OLDER_CTIME }, + { "older-ctime-than", 1, OPTION_OLDER_CTIME_THAN }, + { "older-mtime", 1, OPTION_OLDER_MTIME }, + { "older-mtime-than", 1, OPTION_OLDER_MTIME_THAN }, + { "older-than", 1, OPTION_OLDER_CTIME_THAN }, + { "one-file-system", 0, OPTION_ONE_FILE_SYSTEM }, + { "options", 1, OPTION_OPTIONS }, + { "passphrase", 1, OPTION_PASSPHRASE }, + { "posix", 0, OPTION_POSIX }, + { "preserve-permissions", 0, 'p' }, + { "read-full-blocks", 0, 'B' }, + { "safe-writes", 0, OPTION_SAFE_WRITES }, + { "same-owner", 0, OPTION_SAME_OWNER }, + { "same-permissions", 0, 'p' }, + { "strip-components", 1, OPTION_STRIP_COMPONENTS }, + { "to-stdout", 0, 'O' }, + { "totals", 0, OPTION_TOTALS }, + { "uid", 1, OPTION_UID }, + { "uname", 1, OPTION_UNAME }, + { "uncompress", 0, 'Z' }, + { "unlink", 0, 'U' }, + { "unlink-first", 0, 'U' }, + { "update", 0, 'u' }, + { "use-compress-program", 1, OPTION_USE_COMPRESS_PROGRAM }, + { "uuencode", 0, OPTION_UUENCODE }, + { "verbose", 0, 'v' }, + { "version", 0, OPTION_VERSION }, + { "xattrs", 0, OPTION_XATTRS }, + { "xz", 0, 'J' }, + { "zstd", 0, OPTION_ZSTD }, + { NULL, 0, 0 } +}; + +/* + * This getopt implementation has two key features that common + * getopt_long() implementations lack. Apart from those, it's a + * straightforward option parser, considerably simplified by not + * needing to support the wealth of exotic getopt_long() features. It + * has, of course, been shamelessly tailored for bsdtar. (If you're + * looking for a generic getopt_long() implementation for your + * project, I recommend Gregory Pietsch's public domain getopt_long() + * implementation.) The two additional features are: + * + * Old-style tar arguments: The original tar implementation treated + * the first argument word as a list of single-character option + * letters. All arguments follow as separate words. For example, + * tar xbf 32 /dev/tape + * Here, the "xbf" is three option letters, "32" is the argument for + * "b" and "/dev/tape" is the argument for "f". We support this usage + * if the first command-line argument does not begin with '-'. We + * also allow regular short and long options to follow, e.g., + * tar xbf 32 /dev/tape -P --format=pax + * + * -W long options: There's an obscure GNU convention (only rarely + * supported even there) that allows "-W option=argument" as an + * alternative way to support long options. This was supported in + * early bsdtar as a way to access long options on platforms that did + * not support getopt_long() and is preserved here for backwards + * compatibility. (Of course, if I'd started with a custom + * command-line parser from the beginning, I would have had normal + * long option support on every platform so that hack wouldn't have + * been necessary. Oh, well. Some mistakes you just have to live + * with.) + * + * TODO: We should be able to use this to pull files and intermingled + * options (such as -C) from the command line in write mode. That + * will require a little rethinking of the argument handling in + * bsdtar.c. + * + * TODO: If we want to support arbitrary command-line options from -T + * input (as GNU tar does), we may need to extend this to handle option + * words from sources other than argv/argc. I'm not really sure if I + * like that feature of GNU tar, so it's certainly not a priority. + */ + +int +bsdtar_getopt(struct bsdtar *bsdtar) +{ + enum { state_start = 0, state_old_tar, state_next_word, + state_short, state_long }; + + const struct bsdtar_option *popt, *match = NULL, *match2 = NULL; + const char *p, *long_prefix = "--"; + size_t optlength; + int opt = '?'; + int required = 0; + + bsdtar->argument = NULL; + + /* First time through, initialize everything. */ + if (bsdtar->getopt_state == state_start) { + /* Skip program name. */ + ++bsdtar->argv; + --bsdtar->argc; + if (*bsdtar->argv == NULL) + return (-1); + /* Decide between "new style" and "old style" arguments. */ + if (bsdtar->argv[0][0] == '-') { + bsdtar->getopt_state = state_next_word; + } else { + bsdtar->getopt_state = state_old_tar; + bsdtar->getopt_word = *bsdtar->argv++; + --bsdtar->argc; + } + } + + /* + * We're parsing old-style tar arguments + */ + if (bsdtar->getopt_state == state_old_tar) { + /* Get the next option character. */ + opt = *bsdtar->getopt_word++; + if (opt == '\0') { + /* New-style args can follow old-style. */ + bsdtar->getopt_state = state_next_word; + } else { + /* See if it takes an argument. */ + p = strchr(short_options, opt); + if (p == NULL) + return ('?'); + if (p[1] == ':') { + bsdtar->argument = *bsdtar->argv; + if (bsdtar->argument == NULL) { + lafe_warnc(0, + "Option %c requires an argument", + opt); + return ('?'); + } + ++bsdtar->argv; + --bsdtar->argc; + } + } + } + + /* + * We're ready to look at the next word in argv. + */ + if (bsdtar->getopt_state == state_next_word) { + /* No more arguments, so no more options. */ + if (bsdtar->argv[0] == NULL) + return (-1); + /* Doesn't start with '-', so no more options. */ + if (bsdtar->argv[0][0] != '-') + return (-1); + /* "--" marks end of options; consume it and return. */ + if (strcmp(bsdtar->argv[0], "--") == 0) { + ++bsdtar->argv; + --bsdtar->argc; + return (-1); + } + /* Get next word for parsing. */ + bsdtar->getopt_word = *bsdtar->argv++; + --bsdtar->argc; + if (bsdtar->getopt_word[1] == '-') { + /* Set up long option parser. */ + bsdtar->getopt_state = state_long; + bsdtar->getopt_word += 2; /* Skip leading '--' */ + } else { + /* Set up short option parser. */ + bsdtar->getopt_state = state_short; + ++bsdtar->getopt_word; /* Skip leading '-' */ + } + } + + /* + * We're parsing a group of POSIX-style single-character options. + */ + if (bsdtar->getopt_state == state_short) { + /* Peel next option off of a group of short options. */ + opt = *bsdtar->getopt_word++; + if (opt == '\0') { + /* End of this group; recurse to get next option. */ + bsdtar->getopt_state = state_next_word; + return bsdtar_getopt(bsdtar); + } + + /* Does this option take an argument? */ + p = strchr(short_options, opt); + if (p == NULL) + return ('?'); + if (p[1] == ':') + required = 1; + + /* If it takes an argument, parse that. */ + if (required) { + /* If arg is run-in, bsdtar->getopt_word already points to it. */ + if (bsdtar->getopt_word[0] == '\0') { + /* Otherwise, pick up the next word. */ + bsdtar->getopt_word = *bsdtar->argv; + if (bsdtar->getopt_word == NULL) { + lafe_warnc(0, + "Option -%c requires an argument", + opt); + return ('?'); + } + ++bsdtar->argv; + --bsdtar->argc; + } + if (opt == 'W') { + bsdtar->getopt_state = state_long; + long_prefix = "-W "; /* For clearer errors. */ + } else { + bsdtar->getopt_state = state_next_word; + bsdtar->argument = bsdtar->getopt_word; + } + } + } + + /* We're reading a long option, including -W long=arg convention. */ + if (bsdtar->getopt_state == state_long) { + /* After this long option, we'll be starting a new word. */ + bsdtar->getopt_state = state_next_word; + + /* Option name ends at '=' if there is one. */ + p = strchr(bsdtar->getopt_word, '='); + if (p != NULL) { + optlength = (size_t)(p - bsdtar->getopt_word); + bsdtar->argument = (char *)(uintptr_t)(p + 1); + } else { + optlength = strlen(bsdtar->getopt_word); + } + + /* Search the table for an unambiguous match. */ + for (popt = tar_longopts; popt->name != NULL; popt++) { + /* Short-circuit if first chars don't match. */ + if (popt->name[0] != bsdtar->getopt_word[0]) + continue; + /* If option is a prefix of name in table, record it.*/ + if (strncmp(bsdtar->getopt_word, popt->name, optlength) == 0) { + match2 = match; /* Record up to two matches. */ + match = popt; + /* If it's an exact match, we're done. */ + if (strlen(popt->name) == optlength) { + match2 = NULL; /* Forget the others. */ + break; + } + } + } + + /* Fail if there wasn't a unique match. */ + if (match == NULL) { + lafe_warnc(0, + "Option %s%s is not supported", + long_prefix, bsdtar->getopt_word); + return ('?'); + } + if (match2 != NULL) { + lafe_warnc(0, + "Ambiguous option %s%s (matches --%s and --%s)", + long_prefix, bsdtar->getopt_word, match->name, match2->name); + return ('?'); + } + + /* We've found a unique match; does it need an argument? */ + if (match->required) { + /* Argument required: get next word if necessary. */ + if (bsdtar->argument == NULL) { + bsdtar->argument = *bsdtar->argv; + if (bsdtar->argument == NULL) { + lafe_warnc(0, + "Option %s%s requires an argument", + long_prefix, match->name); + return ('?'); + } + ++bsdtar->argv; + --bsdtar->argc; + } + } else { + /* Argument forbidden: fail if there is one. */ + if (bsdtar->argument != NULL) { + lafe_warnc(0, + "Option %s%s does not allow an argument", + long_prefix, match->name); + return ('?'); + } + } + return (match->equivalent); + } + + return (opt); +} diff --git a/dependencies/libarchive-3.4.2/tar/config_freebsd.h b/dependencies/libarchive-3.4.2/tar/config_freebsd.h new file mode 100644 index 0000000..37aa9dc --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/config_freebsd.h @@ -0,0 +1,84 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: src/usr.bin/tar/config_freebsd.h,v 1.8 2008/11/29 20:06:53 kientzle Exp $ + */ + +/* A default configuration for FreeBSD, used if there is no config.h. */ + +#include /* __FreeBSD_version */ + +#undef HAVE_ATTR_XATTR_H +#define HAVE_CHROOT 1 +#define HAVE_DIRENT_D_NAMLEN 1 +#define HAVE_DIRENT_H 1 +#define HAVE_D_MD_ORDER 1 +#define HAVE_ERRNO_H 1 +#undef HAVE_EXT2FS_EXT2_FS_H +#define HAVE_FCHDIR 1 +#define HAVE_FCNTL_H 1 +#define HAVE_GRP_H 1 +#define HAVE_LANGINFO_H 1 +#undef HAVE_LIBACL +#define HAVE_LIBARCHIVE 1 +#define HAVE_LIMITS_H 1 +#define HAVE_LINK 1 +#undef HAVE_LINUX_EXT2_FS_H +#undef HAVE_LINUX_FS_H +#define HAVE_LOCALE_H 1 +#define HAVE_MBTOWC 1 +#undef HAVE_NDIR_H +#if __FreeBSD_version >= 450002 /* nl_langinfo introduced */ +#define HAVE_NL_LANGINFO 1 +#endif +#define HAVE_PATHS_H 1 +#define HAVE_PWD_H 1 +#define HAVE_READLINK 1 +#define HAVE_REGEX_H 1 +#define HAVE_SETLOCALE 1 +#define HAVE_SIGNAL_H 1 +#define HAVE_STDARG_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_STRING_H 1 +#define HAVE_STRUCT_STAT_ST_FLAGS 1 +#undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC +#undef HAVE_STRUCT_STAT_ST_MTIME_N +#undef HAVE_STRUCT_STAT_ST_MTIME_USEC +#define HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1 +#undef HAVE_STRUCT_STAT_ST_UMTIME +#define HAVE_SYMLINK 1 +#define HAVE_SYS_CDEFS_H 1 +#undef HAVE_SYS_DIR_H +#define HAVE_SYS_IOCTL_H 1 +#undef HAVE_SYS_NDIR_H +#define HAVE_SYS_PARAM_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_TIME_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_UINTMAX_T 1 +#define HAVE_UNISTD_H 1 +#define HAVE_UNSIGNED_LONG_LONG +#define HAVE_WCTYPE_H 1 +#define HAVE_ZLIB_H 1 +#undef MAJOR_IN_MKDEV diff --git a/dependencies/libarchive-3.4.2/tar/creation_set.c b/dependencies/libarchive-3.4.2/tar/creation_set.c new file mode 100644 index 0000000..bdc607d --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/creation_set.c @@ -0,0 +1,318 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "bsdtar_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "bsdtar.h" +#include "err.h" + +struct creation_set { + char *create_format; + struct filter_set { + int program; /* Set 1 if filter is a program name */ + char *filter_name; + } *filters; + int filter_count; +}; + +struct suffix_code_t { + const char *suffix; + const char *form; +}; + +static const char * +get_suffix_code(const struct suffix_code_t *tbl, const char *suffix) +{ + int i; + + if (suffix == NULL) + return (NULL); + for (i = 0; tbl[i].suffix != NULL; i++) { + if (strcmp(tbl[i].suffix, suffix) == 0) + return (tbl[i].form); + } + return (NULL); +} + +static const char * +get_filter_code(const char *suffix) +{ + /* A pair of suffix and compression/filter. */ + static const struct suffix_code_t filters[] = { + { ".Z", "compress" }, + { ".bz2", "bzip2" }, + { ".gz", "gzip" }, + { ".grz", "grzip" }, + { ".lrz", "lrzip" }, + { ".lz", "lzip" }, + { ".lz4", "lz4" }, + { ".lzo", "lzop" }, + { ".lzma", "lzma" }, + { ".uu", "uuencode" }, + { ".xz", "xz" }, + { ".zst", "zstd"}, + { NULL, NULL } + }; + + return get_suffix_code(filters, suffix); +} + +static const char * +get_format_code(const char *suffix) +{ + /* A pair of suffix and format. */ + static const struct suffix_code_t formats[] = { + { ".7z", "7zip" }, + { ".ar", "arbsd" }, + { ".cpio", "cpio" }, + { ".iso", "iso9960" }, + { ".mtree", "mtree" }, + { ".shar", "shar" }, + { ".tar", "paxr" }, + { ".warc", "warc" }, + { ".xar", "xar" }, + { ".zip", "zip" }, + { NULL, NULL } + }; + + return get_suffix_code(formats, suffix); +} + +static const char * +decompose_alias(const char *suffix) +{ + static const struct suffix_code_t alias[] = { + { ".taz", ".tar.gz" }, + { ".tgz", ".tar.gz" }, + { ".tbz", ".tar.bz2" }, + { ".tbz2", ".tar.bz2" }, + { ".tz2", ".tar.bz2" }, + { ".tlz", ".tar.lzma" }, + { ".txz", ".tar.xz" }, + { ".tzo", ".tar.lzo" }, + { ".taZ", ".tar.Z" }, + { ".tZ", ".tar.Z" }, + { ".tzst", ".tar.zst" }, + { NULL, NULL } + }; + + return get_suffix_code(alias, suffix); +} + +static void +_cset_add_filter(struct creation_set *cset, int program, const char *filter) +{ + struct filter_set *new_ptr; + char *new_filter; + + new_ptr = (struct filter_set *)realloc(cset->filters, + sizeof(*cset->filters) * (cset->filter_count + 1)); + if (new_ptr == NULL) + lafe_errc(1, 0, "No memory"); + new_filter = strdup(filter); + if (new_filter == NULL) + lafe_errc(1, 0, "No memory"); + cset->filters = new_ptr; + cset->filters[cset->filter_count].program = program; + cset->filters[cset->filter_count].filter_name = new_filter; + cset->filter_count++; +} + +void +cset_add_filter(struct creation_set *cset, const char *filter) +{ + _cset_add_filter(cset, 0, filter); +} + +void +cset_add_filter_program(struct creation_set *cset, const char *filter) +{ + _cset_add_filter(cset, 1, filter); +} + +int +cset_read_support_filter_program(struct creation_set *cset, struct archive *a) +{ + int cnt = 0, i; + + for (i = 0; i < cset->filter_count; i++) { + if (cset->filters[i].program) { + archive_read_support_filter_program(a, + cset->filters[i].filter_name); + ++cnt; + } + } + return (cnt); +} + +int +cset_write_add_filters(struct creation_set *cset, struct archive *a, + const void **filter_name) +{ + int cnt = 0, i, r; + + for (i = 0; i < cset->filter_count; i++) { + if (cset->filters[i].program) + r = archive_write_add_filter_program(a, + cset->filters[i].filter_name); + else + r = archive_write_add_filter_by_name(a, + cset->filters[i].filter_name); + if (r < ARCHIVE_WARN) { + *filter_name = cset->filters[i].filter_name; + return (r); + } + ++cnt; + } + return (cnt); +} + +void +cset_set_format(struct creation_set *cset, const char *format) +{ + char *f; + + f = strdup(format); + if (f == NULL) + lafe_errc(1, 0, "No memory"); + free(cset->create_format); + cset->create_format = f; +} + +const char * +cset_get_format(struct creation_set *cset) +{ + return (cset->create_format); +} + +static void +_cleanup_filters(struct filter_set *filters, int count) +{ + int i; + + for (i = 0; i < count; i++) + free(filters[i].filter_name); + free(filters); +} + +/* + * Clean up a creation set. + */ +void +cset_free(struct creation_set *cset) +{ + _cleanup_filters(cset->filters, cset->filter_count); + free(cset->create_format); + free(cset); +} + +struct creation_set * +cset_new(void) +{ + return calloc(1, sizeof(struct creation_set)); +} + +/* + * Build a creation set by a file name suffix. + */ +int +cset_auto_compress(struct creation_set *cset, const char *filename) +{ + struct filter_set *old_filters; + char *name, *p; + const char *code; + int old_filter_count; + + name = strdup(filename); + if (name == NULL) + lafe_errc(1, 0, "No memory"); + /* Save previous filters. */ + old_filters = cset->filters; + old_filter_count = cset->filter_count; + cset->filters = NULL; + cset->filter_count = 0; + + for (;;) { + /* Get the suffix. */ + p = strrchr(name, '.'); + if (p == NULL) + break; + /* Suppose it indicates compression/filter type + * such as ".gz". */ + code = get_filter_code(p); + if (code != NULL) { + cset_add_filter(cset, code); + *p = '\0'; + continue; + } + /* Suppose it indicates format type such as ".tar". */ + code = get_format_code(p); + if (code != NULL) { + cset_set_format(cset, code); + break; + } + /* Suppose it indicates alias such as ".tgz". */ + code = decompose_alias(p); + if (code == NULL) + break; + /* Replace the suffix. */ + *p = '\0'; + name = realloc(name, strlen(name) + strlen(code) + 1); + if (name == NULL) + lafe_errc(1, 0, "No memory"); + strcat(name, code); + } + free(name); + if (cset->filters) { + struct filter_set *v; + int i, r; + + /* Release previous filters. */ + _cleanup_filters(old_filters, old_filter_count); + + v = malloc(sizeof(*v) * cset->filter_count); + if (v == NULL) + lafe_errc(1, 0, "No memory"); + /* Reverse filter sequence. */ + for (i = 0, r = cset->filter_count; r > 0; ) + v[i++] = cset->filters[--r]; + free(cset->filters); + cset->filters = v; + return (1); + } else { + /* Put previous filters back. */ + cset->filters = old_filters; + cset->filter_count = old_filter_count; + return (0); + } +} diff --git a/dependencies/libarchive-3.4.2/tar/read.c b/dependencies/libarchive-3.4.2/tar/read.c new file mode 100644 index 0000000..658c810 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/read.c @@ -0,0 +1,420 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "bsdtar_platform.h" +__FBSDID("$FreeBSD: src/usr.bin/tar/read.c,v 1.40 2008/08/21 06:41:14 kientzle Exp $"); + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif + +#ifdef HAVE_ERRNO_H +#include +#endif + +#ifdef HAVE_FCNTL_H +#include +#endif + +#ifdef HAVE_GRP_H +#include +#endif + +#ifdef HAVE_IO_H +#include +#endif + +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_PWD_H +#include +#endif +#ifdef HAVE_STDINT_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_TIME_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "bsdtar.h" +#include "err.h" + +struct progress_data { + struct bsdtar *bsdtar; + struct archive *archive; + struct archive_entry *entry; +}; + +static void read_archive(struct bsdtar *bsdtar, char mode, struct archive *); +static int unmatched_inclusions_warn(struct archive *matching, const char *); + + +void +tar_mode_t(struct bsdtar *bsdtar) +{ + read_archive(bsdtar, 't', NULL); + if (unmatched_inclusions_warn(bsdtar->matching, + "Not found in archive") != 0) + bsdtar->return_value = 1; +} + +void +tar_mode_x(struct bsdtar *bsdtar) +{ + struct archive *writer; + + writer = archive_write_disk_new(); + if (writer == NULL) + lafe_errc(1, ENOMEM, "Cannot allocate disk writer object"); + if ((bsdtar->flags & OPTFLAG_NUMERIC_OWNER) == 0) + archive_write_disk_set_standard_lookup(writer); + archive_write_disk_set_options(writer, bsdtar->extract_flags); + + read_archive(bsdtar, 'x', writer); + + if (unmatched_inclusions_warn(bsdtar->matching, + "Not found in archive") != 0) + bsdtar->return_value = 1; + archive_write_free(writer); +} + +static void +progress_func(void *cookie) +{ + struct progress_data *progress_data = (struct progress_data *)cookie; + struct bsdtar *bsdtar = progress_data->bsdtar; + struct archive *a = progress_data->archive; + struct archive_entry *entry = progress_data->entry; + uint64_t comp, uncomp; + int compression; + + if (!need_report()) + return; + + if (bsdtar->verbose) + fprintf(stderr, "\n"); + if (a != NULL) { + comp = archive_filter_bytes(a, -1); + uncomp = archive_filter_bytes(a, 0); + if (comp > uncomp) + compression = 0; + else + compression = (int)((uncomp - comp) * 100 / uncomp); + fprintf(stderr, + "In: %s bytes, compression %d%%;", + tar_i64toa(comp), compression); + fprintf(stderr, " Out: %d files, %s bytes\n", + archive_file_count(a), tar_i64toa(uncomp)); + } + if (entry != NULL) { + safe_fprintf(stderr, "Current: %s", + archive_entry_pathname(entry)); + fprintf(stderr, " (%s bytes)\n", + tar_i64toa(archive_entry_size(entry))); + } +} + +/* + * Handle 'x' and 't' modes. + */ +static void +read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer) +{ + struct progress_data progress_data; + FILE *out; + struct archive *a; + struct archive_entry *entry; + const char *reader_options; + int r; + + while (*bsdtar->argv) { + if (archive_match_include_pattern(bsdtar->matching, + *bsdtar->argv) != ARCHIVE_OK) + lafe_errc(1, 0, "Error inclusion pattern: %s", + archive_error_string(bsdtar->matching)); + bsdtar->argv++; + } + + if (bsdtar->names_from_file != NULL) + if (archive_match_include_pattern_from_file( + bsdtar->matching, bsdtar->names_from_file, + (bsdtar->flags & OPTFLAG_NULL)) != ARCHIVE_OK) + lafe_errc(1, 0, "Error inclusion pattern: %s", + archive_error_string(bsdtar->matching)); + + a = archive_read_new(); + if (cset_read_support_filter_program(bsdtar->cset, a) == 0) + archive_read_support_filter_all(a); + archive_read_support_format_all(a); + + reader_options = getenv(ENV_READER_OPTIONS); + if (reader_options != NULL) { + size_t module_len = sizeof(IGNORE_WRONG_MODULE_NAME) - 1; + size_t opt_len = strlen(reader_options) + 1; + char *p; + /* Set default read options. */ + if ((p = malloc(module_len + opt_len)) == NULL) + lafe_errc(1, errno, "Out of memory"); + /* Prepend magic code to ignore options for + * a format or modules which are not added to + * the archive read object. */ + memcpy(p, IGNORE_WRONG_MODULE_NAME, module_len); + memcpy(p + module_len, reader_options, opt_len); + r = archive_read_set_options(a, p); + free(p); + if (r == ARCHIVE_FATAL) + lafe_errc(1, 0, "%s", archive_error_string(a)); + else + archive_clear_error(a); + } + if (ARCHIVE_OK != archive_read_set_options(a, bsdtar->option_options)) + lafe_errc(1, 0, "%s", archive_error_string(a)); + if (bsdtar->flags & OPTFLAG_IGNORE_ZEROS) + if (archive_read_set_options(a, + "read_concatenated_archives") != ARCHIVE_OK) + lafe_errc(1, 0, "%s", archive_error_string(a)); + if (bsdtar->passphrase != NULL) + r = archive_read_add_passphrase(a, bsdtar->passphrase); + else + r = archive_read_set_passphrase_callback(a, bsdtar, + &passphrase_callback); + if (r != ARCHIVE_OK) + lafe_errc(1, 0, "%s", archive_error_string(a)); + if (archive_read_open_filename(a, bsdtar->filename, + bsdtar->bytes_per_block)) + lafe_errc(1, 0, "Error opening archive: %s", + archive_error_string(a)); + + do_chdir(bsdtar); + + if (mode == 'x') { + /* Set an extract callback so that we can handle SIGINFO. */ + progress_data.bsdtar = bsdtar; + progress_data.archive = a; + archive_read_extract_set_progress_callback(a, progress_func, + &progress_data); + } + + if (mode == 'x' && (bsdtar->flags & OPTFLAG_CHROOT)) { +#if HAVE_CHROOT + if (chroot(".") != 0) + lafe_errc(1, errno, "Can't chroot to \".\""); +#else + lafe_errc(1, 0, + "chroot isn't supported on this platform"); +#endif + } + +#if defined(_WIN32) && !defined(__CYGWIN__) + if (mode == 'x' && (bsdtar->flags & OPTFLAG_STDOUT)) { + _setmode(1, _O_BINARY); + } +#endif + + for (;;) { + /* Support --fast-read option */ + const char *p; + if ((bsdtar->flags & OPTFLAG_FAST_READ) && + archive_match_path_unmatched_inclusions(bsdtar->matching) == 0) + break; + + r = archive_read_next_header(a, &entry); + progress_data.entry = entry; + if (r == ARCHIVE_EOF) + break; + if (r < ARCHIVE_OK) + lafe_warnc(0, "%s", archive_error_string(a)); + if (r <= ARCHIVE_WARN) + bsdtar->return_value = 1; + if (r == ARCHIVE_RETRY) { + /* Retryable error: try again */ + lafe_warnc(0, "Retrying..."); + continue; + } + if (r == ARCHIVE_FATAL) + break; + p = archive_entry_pathname(entry); + if (p == NULL || p[0] == '\0') { + lafe_warnc(0, "Archive entry has empty or unreadable filename ... skipping."); + bsdtar->return_value = 1; + continue; + } + + if (bsdtar->uid >= 0) { + archive_entry_set_uid(entry, bsdtar->uid); + archive_entry_set_uname(entry, NULL); + } + if (bsdtar->gid >= 0) { + archive_entry_set_gid(entry, bsdtar->gid); + archive_entry_set_gname(entry, NULL); + } + if (bsdtar->uname) + archive_entry_set_uname(entry, bsdtar->uname); + if (bsdtar->gname) + archive_entry_set_gname(entry, bsdtar->gname); + + /* + * Note that pattern exclusions are checked before + * pathname rewrites are handled. This gives more + * control over exclusions, since rewrites always lose + * information. (For example, consider a rewrite + * s/foo[0-9]/foo/. If we check exclusions after the + * rewrite, there would be no way to exclude foo1/bar + * while allowing foo2/bar.) + */ + if (archive_match_excluded(bsdtar->matching, entry)) + continue; /* Excluded by a pattern test. */ + + if (mode == 't') { + /* Perversely, gtar uses -O to mean "send to stderr" + * when used with -t. */ + out = (bsdtar->flags & OPTFLAG_STDOUT) ? + stderr : stdout; + + /* + * TODO: Provide some reasonable way to + * preview rewrites. gtar always displays + * the unedited path in -t output, which means + * you cannot easily preview rewrites. + */ + if (bsdtar->verbose < 2) + safe_fprintf(out, "%s", + archive_entry_pathname(entry)); + else + list_item_verbose(bsdtar, out, entry); + fflush(out); + r = archive_read_data_skip(a); + if (r == ARCHIVE_WARN) { + fprintf(out, "\n"); + lafe_warnc(0, "%s", + archive_error_string(a)); + } + if (r == ARCHIVE_RETRY) { + fprintf(out, "\n"); + lafe_warnc(0, "%s", + archive_error_string(a)); + } + if (r == ARCHIVE_FATAL) { + fprintf(out, "\n"); + lafe_warnc(0, "%s", + archive_error_string(a)); + bsdtar->return_value = 1; + break; + } + fprintf(out, "\n"); + } else { + /* Note: some rewrite failures prevent extraction. */ + if (edit_pathname(bsdtar, entry)) + continue; /* Excluded by a rewrite failure. */ + + if ((bsdtar->flags & OPTFLAG_INTERACTIVE) && + !yes("extract '%s'", archive_entry_pathname(entry))) + continue; + + if (bsdtar->verbose > 1) { + /* GNU tar uses -tv format with -xvv */ + safe_fprintf(stderr, "x "); + list_item_verbose(bsdtar, stderr, entry); + fflush(stderr); + } else if (bsdtar->verbose > 0) { + /* Format follows SUSv2, including the + * deferred '\n'. */ + safe_fprintf(stderr, "x %s", + archive_entry_pathname(entry)); + fflush(stderr); + } + + /* TODO siginfo_printinfo(bsdtar, 0); */ + + if (bsdtar->flags & OPTFLAG_STDOUT) + r = archive_read_data_into_fd(a, 1); + else + r = archive_read_extract2(a, entry, writer); + if (r != ARCHIVE_OK) { + if (!bsdtar->verbose) + safe_fprintf(stderr, "%s", + archive_entry_pathname(entry)); + safe_fprintf(stderr, ": %s", + archive_error_string(a)); + if (!bsdtar->verbose) + fprintf(stderr, "\n"); + bsdtar->return_value = 1; + } + if (bsdtar->verbose) + fprintf(stderr, "\n"); + if (r == ARCHIVE_FATAL) + break; + } + } + + + r = archive_read_close(a); + if (r != ARCHIVE_OK) + lafe_warnc(0, "%s", archive_error_string(a)); + if (r <= ARCHIVE_WARN) + bsdtar->return_value = 1; + + if (bsdtar->verbose > 2) + fprintf(stdout, "Archive Format: %s, Compression: %s\n", + archive_format_name(a), archive_filter_name(a, 0)); + + archive_read_free(a); +} + + +static int +unmatched_inclusions_warn(struct archive *matching, const char *msg) +{ + const char *p; + int r; + + if (matching == NULL) + return (0); + + while ((r = archive_match_path_unmatched_inclusions_next( + matching, &p)) == ARCHIVE_OK) + lafe_warnc(0, "%s: %s", p, msg); + if (r == ARCHIVE_FATAL) + lafe_errc(1, errno, "Out of memory"); + + return (archive_match_path_unmatched_inclusions(matching)); +} diff --git a/dependencies/libarchive-3.4.2/tar/subst.c b/dependencies/libarchive-3.4.2/tar/subst.c new file mode 100644 index 0000000..39c54ac --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/subst.c @@ -0,0 +1,327 @@ +/*- + * Copyright (c) 2008 Joerg Sonnenberger + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "bsdtar_platform.h" +__FBSDID("$FreeBSD: src/usr.bin/tar/subst.c,v 1.4 2008/06/15 10:08:16 kientzle Exp $"); + +#if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H) +#include "bsdtar.h" + +#include +#ifdef HAVE_PCREPOSIX_H +#include +#else +#include +#endif +#include +#include + +#ifndef REG_BASIC +#define REG_BASIC 0 +#endif + +#include "err.h" + +struct subst_rule { + struct subst_rule *next; + regex_t re; + char *result; + unsigned int global:1, print:1, regular:1, symlink:1, hardlink:1; +}; + +struct substitution { + struct subst_rule *first_rule, *last_rule; +}; + +static void +init_substitution(struct bsdtar *bsdtar) +{ + struct substitution *subst; + + bsdtar->substitution = subst = malloc(sizeof(*subst)); + if (subst == NULL) + lafe_errc(1, errno, "Out of memory"); + subst->first_rule = subst->last_rule = NULL; +} + +void +add_substitution(struct bsdtar *bsdtar, const char *rule_text) +{ + struct subst_rule *rule; + struct substitution *subst; + const char *end_pattern, *start_subst; + char *pattern; + int r; + + if ((subst = bsdtar->substitution) == NULL) { + init_substitution(bsdtar); + subst = bsdtar->substitution; + } + + rule = malloc(sizeof(*rule)); + if (rule == NULL) + lafe_errc(1, errno, "Out of memory"); + rule->next = NULL; + rule->result = NULL; + + if (subst->last_rule == NULL) + subst->first_rule = rule; + else + subst->last_rule->next = rule; + subst->last_rule = rule; + + if (*rule_text == '\0') + lafe_errc(1, 0, "Empty replacement string"); + end_pattern = strchr(rule_text + 1, *rule_text); + if (end_pattern == NULL) + lafe_errc(1, 0, "Invalid replacement string"); + + pattern = malloc(end_pattern - rule_text); + if (pattern == NULL) + lafe_errc(1, errno, "Out of memory"); + memcpy(pattern, rule_text + 1, end_pattern - rule_text - 1); + pattern[end_pattern - rule_text - 1] = '\0'; + + if ((r = regcomp(&rule->re, pattern, REG_BASIC)) != 0) { + char buf[80]; + regerror(r, &rule->re, buf, sizeof(buf)); + lafe_errc(1, 0, "Invalid regular expression: %s", buf); + } + free(pattern); + + start_subst = end_pattern + 1; + end_pattern = strchr(start_subst, *rule_text); + if (end_pattern == NULL) + lafe_errc(1, 0, "Invalid replacement string"); + + rule->result = malloc(end_pattern - start_subst + 1); + if (rule->result == NULL) + lafe_errc(1, errno, "Out of memory"); + memcpy(rule->result, start_subst, end_pattern - start_subst); + rule->result[end_pattern - start_subst] = '\0'; + + /* Defaults */ + rule->global = 0; /* Don't do multiple replacements. */ + rule->print = 0; /* Don't print. */ + rule->regular = 1; /* Rewrite regular filenames. */ + rule->symlink = 1; /* Rewrite symlink targets. */ + rule->hardlink = 1; /* Rewrite hardlink targets. */ + + while (*++end_pattern) { + switch (*end_pattern) { + case 'g': + case 'G': + rule->global = 1; + break; + case 'h': + rule->hardlink = 1; + break; + case 'H': + rule->hardlink = 0; + break; + case 'p': + case 'P': + rule->print = 1; + break; + case 'r': + rule->regular = 1; + break; + case 'R': + rule->regular = 0; + break; + case 's': + rule->symlink = 1; + break; + case 'S': + rule->symlink = 0; + break; + default: + lafe_errc(1, 0, "Invalid replacement flag %c", *end_pattern); + } + } +} + +static void +realloc_strncat(char **str, const char *append, size_t len) +{ + char *new_str; + size_t old_len; + + if (*str == NULL) + old_len = 0; + else + old_len = strlen(*str); + + new_str = malloc(old_len + len + 1); + if (new_str == NULL) + lafe_errc(1, errno, "Out of memory"); + if (*str != NULL) + memcpy(new_str, *str, old_len); + memcpy(new_str + old_len, append, len); + new_str[old_len + len] = '\0'; + free(*str); + *str = new_str; +} + +static void +realloc_strcat(char **str, const char *append) +{ + char *new_str; + size_t old_len; + + if (*str == NULL) + old_len = 0; + else + old_len = strlen(*str); + + new_str = malloc(old_len + strlen(append) + 1); + if (new_str == NULL) + lafe_errc(1, errno, "Out of memory"); + if (*str != NULL) + memcpy(new_str, *str, old_len); + strcpy(new_str + old_len, append); + free(*str); + *str = new_str; +} + +int +apply_substitution(struct bsdtar *bsdtar, const char *name, char **result, + int symlink_target, int hardlink_target) +{ + const char *path = name; + regmatch_t matches[10]; + size_t i, j; + struct subst_rule *rule; + struct substitution *subst; + int c, got_match, print_match; + + *result = NULL; + + if ((subst = bsdtar->substitution) == NULL) + return 0; + + got_match = 0; + print_match = 0; + + for (rule = subst->first_rule; rule != NULL; rule = rule->next) { + if (symlink_target) { + if (!rule->symlink) + continue; + } else if (hardlink_target) { + if (!rule->hardlink) + continue; + } else { /* Regular filename. */ + if (!rule->regular) + continue; + } + + while (1) { + if (regexec(&rule->re, name, 10, matches, 0)) + break; + + got_match = 1; + print_match |= rule->print; + realloc_strncat(result, name, matches[0].rm_so); + + for (i = 0, j = 0; rule->result[i] != '\0'; ++i) { + if (rule->result[i] == '~') { + realloc_strncat(result, rule->result + j, i - j); + realloc_strncat(result, + name + matches[0].rm_so, + matches[0].rm_eo - matches[0].rm_so); + j = i + 1; + continue; + } + if (rule->result[i] != '\\') + continue; + + ++i; + c = rule->result[i]; + switch (c) { + case '~': + case '\\': + realloc_strncat(result, rule->result + j, i - j - 1); + j = i; + break; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + realloc_strncat(result, rule->result + j, i - j - 1); + if ((size_t)(c - '0') > (size_t)(rule->re.re_nsub)) { + free(*result); + *result = NULL; + return -1; + } + realloc_strncat(result, name + matches[c - '0'].rm_so, matches[c - '0'].rm_eo - matches[c - '0'].rm_so); + j = i + 1; + break; + default: + /* Just continue; */ + break; + } + + } + + realloc_strcat(result, rule->result + j); + + name += matches[0].rm_eo; + + if (!rule->global) + break; + } + } + + if (got_match) + realloc_strcat(result, name); + + if (print_match) + fprintf(stderr, "%s >> %s\n", path, *result); + + return got_match; +} + +void +cleanup_substitution(struct bsdtar *bsdtar) +{ + struct subst_rule *rule; + struct substitution *subst; + + if ((subst = bsdtar->substitution) == NULL) + return; + + while ((rule = subst->first_rule) != NULL) { + subst->first_rule = rule->next; + free(rule->result); + free(rule); + } + free(subst); +} +#endif /* defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H) */ diff --git a/dependencies/libarchive-3.4.2/tar/test/CMakeLists.txt b/dependencies/libarchive-3.4.2/tar/test/CMakeLists.txt new file mode 100644 index 0000000..2cd573a --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/CMakeLists.txt @@ -0,0 +1,127 @@ +############################################ +# +# How to build bsdtar_test +# +############################################ +IF(ENABLE_TAR AND ENABLE_TEST) + SET(bsdtar_test_SOURCES + ../../test_utils/test_utils.c + ../../test_utils/test_main.c + test.h + test_0.c + test_basic.c + test_copy.c + test_empty_mtree.c + test_extract_tar_Z.c + test_extract_tar_bz2.c + test_extract_tar_grz.c + test_extract_tar_gz.c + test_extract_tar_lrz.c + test_extract_tar_lz.c + test_extract_tar_lz4.c + test_extract_tar_lzma.c + test_extract_tar_lzo.c + test_extract_tar_xz.c + test_extract_tar_zstd.c + test_format_newc.c + test_help.c + test_leading_slash.c + test_missing_file.c + test_option_C_upper.c + test_option_C_mtree.c + test_option_H_upper.c + test_option_L_upper.c + test_option_O_upper.c + test_option_T_upper.c + test_option_U_upper.c + test_option_X_upper.c + test_option_a.c + test_option_acls.c + test_option_b.c + test_option_b64encode.c + test_option_exclude.c + test_option_exclude_vcs.c + test_option_fflags.c + test_option_gid_gname.c + test_option_grzip.c + test_option_j.c + test_option_k.c + test_option_keep_newer_files.c + test_option_lrzip.c + test_option_lz4.c + test_option_lzma.c + test_option_lzop.c + test_option_n.c + test_option_newer_than.c + test_option_nodump.c + test_option_older_than.c + test_option_passphrase.c + test_option_q.c + test_option_r.c + test_option_s.c + test_option_safe_writes.c + test_option_uid_uname.c + test_option_uuencode.c + test_option_xattrs.c + test_option_xz.c + test_option_z.c + test_option_zstd.c + test_patterns.c + test_print_longpath.c + test_stdio.c + test_strip_components.c + test_symlink_dir.c + test_version.c + test_windows.c + ) + + # + # Register target + # + ADD_EXECUTABLE(bsdtar_test ${bsdtar_test_SOURCES}) + IF(ENABLE_ACL) + SET(TEST_ACL_LIBS "") + IF(HAVE_LIBACL) + LIST(APPEND TEST_ACL_LIBS ${ACL_LIBRARY}) + ENDIF(HAVE_LIBACL) + IF(HAVE_LIBRICHACL) + LIST(APPEND TEST_ACL_LIBS ${RICHACL_LIBRARY}) + ENDIF(HAVE_LIBRICHACL) + TARGET_LINK_LIBRARIES(bsdtar_test ${TEST_ACL_LIBS}) + ENDIF(ENABLE_ACL) + SET_PROPERTY(TARGET bsdtar_test PROPERTY COMPILE_DEFINITIONS LIST_H) + + # + # Generate list.h by grepping DEFINE_TEST() lines out of the C sources. + # + GENERATE_LIST_H(${CMAKE_CURRENT_BINARY_DIR}/list.h + ${CMAKE_CURRENT_LIST_FILE} ${bsdtar_test_SOURCES}) + SET_PROPERTY(DIRECTORY APPEND PROPERTY INCLUDE_DIRECTORIES + ${CMAKE_CURRENT_BINARY_DIR}) + + # list.h has a line DEFINE_TEST(testname) for every + # test. We can use that to define the tests for cmake by + # defining a DEFINE_TEST macro and reading list.h in. + MACRO (DEFINE_TEST _testname) + ADD_TEST( + NAME bsdtar_${_testname} + COMMAND bsdtar_test -vv + -p $ + -r ${CMAKE_CURRENT_SOURCE_DIR} + ${_testname}) + ENDMACRO (DEFINE_TEST _testname) + + INCLUDE(${CMAKE_CURRENT_BINARY_DIR}/list.h) + INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) + INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/test_utils) + INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/tar/test) + + # Experimental new test handling + ADD_CUSTOM_TARGET(run_bsdtar_test + COMMAND bsdtar_test -p $ + -r ${CMAKE_CURRENT_SOURCE_DIR} + -vv) + ADD_DEPENDENCIES(run_bsdtar_test bsdtar) + ADD_DEPENDENCIES(run_all_tests run_bsdtar_test) + +ENDIF(ENABLE_TAR AND ENABLE_TEST) diff --git a/dependencies/libarchive-3.4.2/tar/test/list.h b/dependencies/libarchive-3.4.2/tar/test/list.h new file mode 100644 index 0000000..01e6721 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/list.h @@ -0,0 +1,65 @@ +DEFINE_TEST(test_0) +DEFINE_TEST(test_basic) +DEFINE_TEST(test_copy) +DEFINE_TEST(test_empty_mtree) +DEFINE_TEST(test_extract_tar_Z) +DEFINE_TEST(test_extract_tar_bz2) +DEFINE_TEST(test_extract_tar_grz) +DEFINE_TEST(test_extract_tar_gz) +DEFINE_TEST(test_extract_tar_lrz) +DEFINE_TEST(test_extract_tar_lz) +DEFINE_TEST(test_extract_tar_lz4) +DEFINE_TEST(test_extract_tar_lzma) +DEFINE_TEST(test_extract_tar_lzo) +DEFINE_TEST(test_extract_tar_xz) +DEFINE_TEST(test_extract_tar_zstd) +DEFINE_TEST(test_format_newc) +DEFINE_TEST(test_help) +DEFINE_TEST(test_leading_slash) +DEFINE_TEST(test_missing_file) +DEFINE_TEST(test_option_C_mtree) +DEFINE_TEST(test_option_C_upper) +DEFINE_TEST(test_option_H_upper) +DEFINE_TEST(test_option_L_upper) +DEFINE_TEST(test_option_O_upper) +DEFINE_TEST(test_option_T_upper) +DEFINE_TEST(test_option_U_upper) +DEFINE_TEST(test_option_X_upper) +DEFINE_TEST(test_option_a) +DEFINE_TEST(test_option_acls) +DEFINE_TEST(test_option_b) +DEFINE_TEST(test_option_b64encode) +DEFINE_TEST(test_option_exclude) +DEFINE_TEST(test_option_exclude_vcs) +DEFINE_TEST(test_option_fflags) +DEFINE_TEST(test_option_gid_gname) +DEFINE_TEST(test_option_grzip) +DEFINE_TEST(test_option_j) +DEFINE_TEST(test_option_k) +DEFINE_TEST(test_option_keep_newer_files) +DEFINE_TEST(test_option_lrzip) +DEFINE_TEST(test_option_lz4) +DEFINE_TEST(test_option_lzma) +DEFINE_TEST(test_option_lzop) +DEFINE_TEST(test_option_n) +DEFINE_TEST(test_option_newer_than) +DEFINE_TEST(test_option_nodump) +DEFINE_TEST(test_option_older_than) +DEFINE_TEST(test_option_passphrase) +DEFINE_TEST(test_option_q) +DEFINE_TEST(test_option_r) +DEFINE_TEST(test_option_s) +DEFINE_TEST(test_option_safe_writes) +DEFINE_TEST(test_option_uid_uname) +DEFINE_TEST(test_option_uuencode) +DEFINE_TEST(test_option_xattrs) +DEFINE_TEST(test_option_xz) +DEFINE_TEST(test_option_z) +DEFINE_TEST(test_option_zstd) +DEFINE_TEST(test_patterns) +DEFINE_TEST(test_print_longpath) +DEFINE_TEST(test_stdio) +DEFINE_TEST(test_strip_components) +DEFINE_TEST(test_symlink_dir) +DEFINE_TEST(test_version) +DEFINE_TEST(test_windows) diff --git a/dependencies/libarchive-3.4.2/tar/test/test.h b/dependencies/libarchive-3.4.2/tar/test/test.h new file mode 100644 index 0000000..1e1bee8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2003-2017 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* Every test program should #include "test.h" as the first thing. */ + +#define KNOWNREF "test_patterns_2.tar.uu" +#define ENVBASE "BSDTAR" /* Prefix for environment variables. */ +#define PROGRAM "bsdtar" /* Name of program being tested. */ +#define PROGRAM_ALIAS "tar" /* Generic alias for program */ +#undef LIBRARY /* Not testing a library. */ +#undef EXTRA_DUMP /* How to dump extra data */ +#undef EXTRA_ERRNO /* How to dump errno */ +/* How to generate extra version info. */ +#define EXTRA_VERSION (systemf("%s --version", testprog) ? "" : "") + +#include "test_common.h" diff --git a/dependencies/libarchive-3.4.2/tar/test/test_0.c b/dependencies/libarchive-3.4.2/tar/test/test_0.c new file mode 100644 index 0000000..b73c7a3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_0.c @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_0.c,v 1.2 2008/05/26 17:10:10 kientzle Exp $"); + +/* + * This first test does basic sanity checks on the environment. For + * most of these, we just exit on failure. + */ +#if !defined(_WIN32) || defined(__CYGWIN__) +#define DEV_NULL "/dev/null" +#else +#define DEV_NULL "NUL" +#endif + +DEFINE_TEST(test_0) +{ + struct stat st; + + failure("File %s does not exist?!", testprog); + if (!assertEqualInt(0, stat(testprogfile, &st))) { + fprintf(stderr, + "\nFile %s does not exist; aborting test.\n\n", + testprog); + exit(1); + } + + failure("%s is not executable?!", testprog); + if (!assert((st.st_mode & 0111) != 0)) { + fprintf(stderr, + "\nFile %s not executable; aborting test.\n\n", + testprog); + exit(1); + } + + /* + * Try to successfully run the program; this requires that + * we know some option that will succeed. + */ + if (0 == systemf("%s --version >" DEV_NULL, testprog)) { + /* This worked. */ + } else if (0 == systemf("%s -W version >" DEV_NULL, testprog)) { + /* This worked. */ + } else { + failure("Unable to successfully run any of the following:\n" + " * %s --version\n" + " * %s -W version\n", + testprog, testprog); + assert(0); + } + + /* TODO: Ensure that our reference files are available. */ +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_basic.c b/dependencies/libarchive-3.4.2/tar/test/test_basic.c new file mode 100644 index 0000000..b1c4983 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_basic.c @@ -0,0 +1,135 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_basic.c,v 1.2 2008/05/26 17:10:10 kientzle Exp $"); + +static const char * +make_files(void) +{ + FILE *f; + + /* File with 10 bytes content. */ + f = fopen("file", "wb"); + assert(f != NULL); + assertEqualInt(10, fwrite("123456789", 1, 10, f)); + fclose(f); + + /* hardlink to above file. */ + assertMakeHardlink("linkfile", "file"); + assertIsHardlink("file", "linkfile"); + + /* Symlink to above file. */ + if (canSymlink()) + assertMakeSymlink("symlink", "file", 0); + + /* Directory. */ + assertMakeDir("dir", 0775); + + return canSymlink() + ? "file linkfile symlink dir" + : "file linkfile dir"; +} + +static void +verify_files(const char *target) +{ + assertChdir(target); + + /* Regular file with 2 links. */ + failure("%s", target); + assertIsReg("file", -1); + failure("%s", target); + assertFileSize("file", 10); + failure("%s", target); + assertFileContents("123456789", 10, "file"); + failure("%s", target); + assertFileNLinks("file", 2); + + /* Another name for the same file. */ + failure("%s", target); + assertIsReg("linkfile", -1); + failure("%s", target); + assertFileSize("linkfile", 10); + assertFileContents("123456789", 10, "linkfile"); + assertFileNLinks("linkfile", 2); + assertIsHardlink("file", "linkfile"); + + /* Symlink */ + if (canSymlink()) + assertIsSymlink("symlink", "file", 0); + + /* dir */ + failure("%s", target); + assertIsDir("dir", 0775); + assertChdir(".."); +} + +static void +run_tar(const char *target, const char *pack_options, + const char *unpack_options, const char *flist) +{ + int r; + + assertMakeDir(target, 0775); + + /* Use the tar program to create an archive. */ + r = systemf("%s cf - %s %s >%s/archive 2>%s/pack.err", testprog, pack_options, flist, target, target); + failure("Error invoking %s cf -%s", testprog, pack_options); + assertEqualInt(r, 0); + + assertChdir(target); + + /* Verify that nothing went to stderr. */ + assertEmptyFile("pack.err"); + + /* + * Use tar to unpack the archive into another directory. + */ + r = systemf("%s xf archive %s >unpack.out 2>unpack.err", + testprog, unpack_options); + failure("Error invoking %s xf archive %s", testprog, unpack_options); + assertEqualInt(r, 0); + + /* Verify that nothing went to stderr. */ + assertEmptyFile("unpack.err"); + assertChdir(".."); +} + +DEFINE_TEST(test_basic) +{ + const char *flist; + + assertUmask(0); + flist = make_files(); + /* Archive/dearchive with a variety of options. */ + run_tar("copy", "", "", flist); + verify_files("copy"); + + run_tar("copy_ustar", "--format=ustar", "", flist); + verify_files("copy_ustar"); + + /* tar doesn't handle cpio symlinks correctly */ + /* run_tar("copy_odc", "--format=odc", ""); */ +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_copy.c b/dependencies/libarchive-3.4.2/tar/test/test_copy.c new file mode 100644 index 0000000..d618e45 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_copy.c @@ -0,0 +1,375 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_copy.c,v 1.3 2008/08/15 06:12:02 kientzle Exp $"); + +#if defined(__CYGWIN__) +# include +# include +#endif +#if defined(_WIN32) && !defined(__CYGWIN__) +# include +#endif + +/* + * Try to figure out how deep we can go in our tests. Assumes that + * the first call to this function has the longest starting cwd (which + * is currently "/original"). This is mostly to work around + * limits in our Win32 support. + * + * Background: On Posix systems, PATH_MAX is merely a limit on the + * length of the string passed into a system call. By repeatedly + * calling chdir(), you can work with arbitrarily long paths on such + * systems. In contrast, Win32 APIs apply PATH_MAX limits to the full + * absolute path, so the permissible length of a system call argument + * varies with the cwd. Some APIs actually enforce limits + * significantly less than PATH_MAX to ensure that you can create + * files within the current working directory. The Win32 limits also + * apply to Cygwin before 1.7. + * + * Someday, I want to convert the Win32 support to use newer + * wide-character paths with '\\?\' prefix, which has a 32k PATH_MAX + * instead of the rather anemic 260 character limit of the older + * system calls. Then we can drop this mess (unless we want to + * continue to special-case Cygwin 1.5 and earlier). + */ +static int +compute_loop_max(void) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + static int LOOP_MAX = 0; + char buf[MAX_PATH]; + size_t cwdlen; + + if (LOOP_MAX == 0) { + assert(_getcwd(buf, MAX_PATH) != NULL); + cwdlen = strlen(buf); + /* 12 characters = length of 8.3 filename */ + /* 4 characters = length of "/../" used in symlink tests */ + /* 1 character = length of extra "/" separator */ + LOOP_MAX = MAX_PATH - (int)cwdlen - 12 - 4 - 1; + } + return LOOP_MAX; +#elif defined(__CYGWIN__) && !defined(HAVE_CYGWIN_CONV_PATH) + static int LOOP_MAX = 0; + if (LOOP_MAX == 0) { + char wbuf[PATH_MAX]; + char pbuf[PATH_MAX]; + size_t wcwdlen; + size_t pcwdlen; + size_t cwdlen; + assert(getcwd(pbuf, PATH_MAX) != NULL); + pcwdlen = strlen(pbuf); + cygwin_conv_to_full_win32_path(pbuf, wbuf); + wcwdlen = strlen(wbuf); + cwdlen = ((wcwdlen > pcwdlen) ? wcwdlen : pcwdlen); + /* Cygwin helper needs an extra few characters. */ + LOOP_MAX = PATH_MAX - (int)cwdlen - 12 - 4 - 4; + } + return LOOP_MAX; +#else + /* cygwin-1.7 ends up here, along with "normal" unix */ + return 200; /* restore pre-r278 depth */ +#endif +} + +/* filenames[i] is a distinctive filename of length i. */ +/* To simplify interpreting failures, each filename ends with a + * decimal integer which is the length of the filename. E.g., A + * filename ending in "_92" is 92 characters long. To detect errors + * which drop or misplace characters, the filenames use a repeating + * "abcdefghijklmnopqrstuvwxyz..." pattern. */ +static char *filenames[201]; + +static void +compute_filenames(void) +{ + char buff[250]; + size_t i,j; + + filenames[0] = strdup(""); + filenames[1] = strdup("1"); + filenames[2] = strdup("a2"); + for (i = 3; i < sizeof(filenames)/sizeof(filenames[0]); ++i) { + /* Fill with "abcdefghij..." */ + for (j = 0; j < i; ++j) + buff[j] = 'a' + (j % 26); + buff[j--] = '\0'; + /* Work from the end to fill in the number portion. */ + buff[j--] = '0' + (i % 10); + if (i > 9) { + buff[j--] = '0' + ((i / 10) % 10); + if (i > 99) + buff[j--] = '0' + (char)(i / 100); + } + buff[j] = '_'; + /* Guard against obvious screwups in the above code. */ + assertEqualInt(strlen(buff), i); + filenames[i] = strdup(buff); + } +} + +static void +create_tree(void) +{ + char buff[260]; + char buff2[260]; + int i; + int LOOP_MAX; + + compute_filenames(); + + /* Log that we'll be omitting some checks. */ + if (!canSymlink()) { + skipping("Symlink checks"); + } + + assertMakeDir("original", 0775); + assertEqualInt(0, chdir("original")); + LOOP_MAX = compute_loop_max(); + + assertMakeDir("f", 0775); + assertMakeDir("l", 0775); + assertMakeDir("m", 0775); + assertMakeDir("s", 0775); + assertMakeDir("d", 0775); + + for (i = 1; i < LOOP_MAX; i++) { + failure("Internal sanity check failed: i = %d", i); + assert(filenames[i] != NULL); + + sprintf(buff, "f/%s", filenames[i]); + assertMakeFile(buff, 0777, buff); + + /* Create a link named "l/abcdef..." to the above. */ + sprintf(buff2, "l/%s", filenames[i]); + assertMakeHardlink(buff2, buff); + + /* Create a link named "m/abcdef..." to the above. */ + sprintf(buff2, "m/%s", filenames[i]); + assertMakeHardlink(buff2, buff); + + if (canSymlink()) { + /* Create a symlink named "s/abcdef..." to the above. */ + sprintf(buff, "s/%s", filenames[i]); + sprintf(buff2, "../f/%s", filenames[i]); + failure("buff=\"%s\" buff2=\"%s\"", buff, buff2); + assertMakeSymlink(buff, buff2, 0); + } + /* Create a dir named "d/abcdef...". */ + buff[0] = 'd'; + failure("buff=\"%s\"", buff); + assertMakeDir(buff, 0775); + } + + assertEqualInt(0, chdir("..")); +} + +#define LIMIT_NONE 200 +#define LIMIT_USTAR 100 + +static void +verify_tree(size_t limit) +{ + char name1[260]; + char name2[260]; + size_t i, LOOP_MAX; + + LOOP_MAX = compute_loop_max(); + + /* Generate the names we know should be there and verify them. */ + for (i = 1; i < LOOP_MAX; i++) { + /* Verify a file named "f/abcdef..." */ + sprintf(name1, "f/%s", filenames[i]); + if (i <= limit) { + assertFileExists(name1); + assertFileContents(name1, (int)strlen(name1), name1); + } + + sprintf(name2, "l/%s", filenames[i]); + if (i + 2 <= limit) { + /* Verify hardlink "l/abcdef..." */ + assertIsHardlink(name1, name2); + /* Verify hardlink "m/abcdef..." */ + name2[0] = 'm'; + assertIsHardlink(name1, name2); + } + + if (canSymlink()) { + /* Verify symlink "s/abcdef..." */ + sprintf(name1, "s/%s", filenames[i]); + sprintf(name2, "../f/%s", filenames[i]); + if (strlen(name2) <= limit) + assertIsSymlink(name1, name2, 0); + } + + /* Verify dir "d/abcdef...". */ + sprintf(name1, "d/%s", filenames[i]); + if (i + 1 <= limit) { /* +1 for trailing slash */ + if (assertIsDir(name1, -1)) { + /* TODO: opendir/readdir this + * directory and make sure + * it's empty. + */ + } + } + } + +#if !defined(_WIN32) || defined(__CYGWIN__) + { + const char *dp; + /* Now make sure nothing is there that shouldn't be. */ + for (dp = "dflms"; *dp != '\0'; ++dp) { + DIR *d; + struct dirent *de; + char dir[2]; + dir[0] = *dp; dir[1] = '\0'; + d = opendir(dir); + failure("Unable to open dir '%s'", dir); + if (!assert(d != NULL)) + continue; + while ((de = readdir(d)) != NULL) { + char *p = de->d_name; + if (p[0] == '.') + continue; + switch(dp[0]) { + case 'l': case 'm': case 'd': + failure("strlen(p)=%zu", strlen(p)); + assert(strlen(p) < limit); + assertEqualString(p, + filenames[strlen(p)]); + break; + case 'f': case 's': + failure("strlen(p)=%zu", strlen(p)); + assert(strlen(p) < limit + 1); + assertEqualString(p, + filenames[strlen(p)]); + break; + default: + failure("File %s shouldn't be here", p); + assert(0); + } + } + closedir(d); + } + } +#endif +} + +static void +copy_basic(void) +{ + int r; + + /* NOTE: for proper operation on cygwin-1.5 and windows, the + * length of the name of the directory below, "plain", must be + * less than or equal to the length of the name of the original + * directory, "original" This restriction derives from the + * extremely limited pathname lengths on those platforms. + */ + assertMakeDir("plain", 0775); + assertEqualInt(0, chdir("plain")); + + /* + * Use the tar program to create an archive. + */ + r = systemf("%s cf archive -C ../original f d l m s >pack.out 2>pack.err", + testprog); + failure("Error invoking \"%s cf\"", testprog); + assertEqualInt(r, 0); + + /* Verify that nothing went to stdout or stderr. */ + assertEmptyFile("pack.err"); + assertEmptyFile("pack.out"); + + /* + * Use tar to unpack the archive into another directory. + */ + r = systemf("%s xf archive >unpack.out 2>unpack.err", testprog); + failure("Error invoking %s xf archive", testprog); + assertEqualInt(r, 0); + + /* Verify that nothing went to stdout or stderr. */ + assertEmptyFile("unpack.err"); + assertEmptyFile("unpack.out"); + + verify_tree(LIMIT_NONE); + assertEqualInt(0, chdir("..")); +} + +static void +copy_ustar(void) +{ + const char *target = "ustar"; + int r; + + /* NOTE: for proper operation on cygwin-1.5 and windows, the + * length of the name of the directory below, "ustar", must be + * less than or equal to the length of the name of the original + * directory, "original" This restriction derives from the + * extremely limited pathname lengths on those platforms. + */ + assertMakeDir(target, 0775); + assertEqualInt(0, chdir(target)); + + /* + * Use the tar program to create an archive. + */ + r = systemf("%s cf archive --format=ustar -C ../original f d l m s >pack.out 2>pack.err", + testprog); + failure("Error invoking \"%s cf archive --format=ustar\"", testprog); + assertEqualInt(r, 0); + + /* Verify that nothing went to stdout. */ + assertEmptyFile("pack.out"); + /* Stderr is non-empty, since there are a bunch of files + * with filenames too long to archive. */ + + /* + * Use tar to unpack the archive into another directory. + */ + r = systemf("%s xf archive >unpack.out 2>unpack.err", testprog); + failure("Error invoking %s xf archive", testprog); + assertEqualInt(r, 0); + + /* Verify that nothing went to stdout or stderr. */ + assertEmptyFile("unpack.err"); + assertEmptyFile("unpack.out"); + + verify_tree(LIMIT_USTAR); + assertEqualInt(0, chdir("../..")); +} + +DEFINE_TEST(test_copy) +{ + assertUmask(0); + create_tree(); /* Create sample files in "original" dir. */ + + /* Test simple "tar -c | tar -x" pipeline copy. */ + copy_basic(); + + /* Same, but constrain to ustar format. */ + copy_ustar(); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_empty_mtree.c b/dependencies/libarchive-3.4.2/tar/test/test_empty_mtree.c new file mode 100644 index 0000000..6f8a5e9 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_empty_mtree.c @@ -0,0 +1,45 @@ +/*- + * Copyright (c) 2003-2009 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * Regression test: We used to get a bogus error message when we + * asked tar to copy entries out of an empty archive. See + * Issue 51 on libarchive.googlecode.com for details. + */ +DEFINE_TEST(test_empty_mtree) +{ + int r; + + assertMakeFile("test1.mtree", 0777, "#mtree\n"); + + r = systemf("%s cf test1.tar @test1.mtree >test1.out 2>test1.err", + testprog); + failure("Error invoking %s cf", testprog); + assertEqualInt(r, 0); + assertEmptyFile("test1.out"); + assertEmptyFile("test1.err"); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_extract.tar.Z.uu b/dependencies/libarchive-3.4.2/tar/test/test_extract.tar.Z.uu new file mode 100644 index 0000000..92713a5 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_extract.tar.Z.uu @@ -0,0 +1,9 @@ +begin 664 test_extract.tar.Z +M'YV09M*P*1,#@,&#"!,J7,BPH<.'$",BA$'1A@T:(`!0C'&C!HR,&SM^U$BQ +M9$D9,T#$D`%CAHP;-&"@Q`@C1HP9-FH```%#HL^?0(,*!5!G#ITP//JW-F?'18\FI0@5;FFOCJV:Q/JYM>NM8,62I6,6K5J!@-V^WLV[M^_?P(,+'TZ\ +0N/'CR),K7\Z\N?/GT*,K!P`` +` +end diff --git a/dependencies/libarchive-3.4.2/tar/test/test_extract.tar.bz2.uu b/dependencies/libarchive-3.4.2/tar/test/test_extract.tar.bz2.uu new file mode 100644 index 0000000..9a37413 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_extract.tar.bz2.uu @@ -0,0 +1,7 @@ +begin 664 test_extract.tar.bz2 +M0EIH.3%!629368N]6:```'U[D=(0`"!``7^```AK)9X`!```$0`(,`"X#&$Q +M,F`F``,83$R8"8``*J:")M0TCQ30-/%-3*]V3EE!&(DSM8?BJ4J)=TSJ4/"B +M,?#R_6>?9K=+H02NT0V040P3.SHF:(573*)M5&;!-%6RO=6F5":N"+,"YZ;L +AV+<]%F[GWYCR<%FRKAPR=7VY+'+1)_B[DBG"A(1=ZLT` +` +end diff --git a/dependencies/libarchive-3.4.2/tar/test/test_extract.tar.grz.uu b/dependencies/libarchive-3.4.2/tar/test/test_extract.tar.grz.uu new file mode 100644 index 0000000..44651e1 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_extract.tar.grz.uu @@ -0,0 +1,7 @@ +begin 644 test_extract.tar.grz +M1U)::7!)20`"!#HI``P``*P,``#U````SP```'<````[-=0OM"R^UP#^C?Z< +MFGU0]I:>SW7]H01)1\WY:59("M_=V4[N[R*'`H&:'E=O@5B(?T,0?@)%-:_D +M;EUP)!JVN)@V_:ABYS3+[[6/R(NU,-::]'X&;,]:,HR[*3#R!@:W)IGC`,&G +8L+IZ7]FP=8U_R?CZ2XPO)"H-ME3@P]$` +` +end diff --git a/dependencies/libarchive-3.4.2/tar/test/test_extract.tar.gz.uu b/dependencies/libarchive-3.4.2/tar/test/test_extract.tar.gz.uu new file mode 100644 index 0000000..19f8bc0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_extract.tar.gz.uu @@ -0,0 +1,7 @@ +begin 664 test_extract.tar.gz +M'XL(""S!:U```W1E26I>27%"OEI"FF@M*#'-=!.&@5T!*`X-Z*Q'23E?Q-3 +AP?_D@0*H:&)P-5? +MZX%NI60,IT@(N<,S%?7H2TLP5)FN#[-;&&[/2A#BNH4(7#C+*&ZP<>K&B)AG +M:Z(;Y=]3<5Q$)_[[5M\7=]N7A$%\ZF:H2/,Q%BK$JA4L!,K(-RZU2X[/`%69 +.9U@/B[!N",NH4]8F,M(` +` +end diff --git a/dependencies/libarchive-3.4.2/tar/test/test_extract.tar.lz.uu b/dependencies/libarchive-3.4.2/tar/test/test_extract.tar.lz.uu new file mode 100644 index 0000000..cb380e3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_extract.tar.lz.uu @@ -0,0 +1,7 @@ +begin 664 test_extract.tar.lz +M3%I)4`$,`#,:2=:X2EY2J/TZ6]L7]]N4K?J&A)E2#"A'E"T1EP+MU&;(P1FY +MV\,8BTS,N0/O2=#67;G5)%I'C,D.U?*T!NX("FYPYI9I40F>X))?^8\?E?#> +MOP";"GD#8(9*K;XP318HXZ\?_^SZ +6K-(!CH7```P```````"=```````````` +` +end diff --git a/dependencies/libarchive-3.4.2/tar/test/test_extract.tar.lz4.uu b/dependencies/libarchive-3.4.2/tar/test/test_extract.tar.lz4.uu new file mode 100644 index 0000000..a10ac02 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_extract.tar.lz4.uu @@ -0,0 +1,8 @@ +begin 644 test_extract.tar.lz4 +M!")-&&1PN:L```!O9FEL93$``0!+Z#`P,#8V-"``,#`Q-S4P"``#`@#_"3(S +M(#$R,#,R-S0P,C,T(#`Q,3,V-0`@,)<`2P("`+)U4JC].EO;%_?;E*WZAH294@PH1Y0M$9<" +M[=1FR,$9N=O#&(M,Q24U'H+5Z^7^*J;G!)OU]O'2D;AZ&0^IO?>-YA]$:-X_ +MD^O)YVM(4`^-MT$X`.D(6)*$]3HNB9KJ_H=1$QKYZ:`:,H_L"H[#"?#Z5A<] +%O_OZW=D` +` +end diff --git a/dependencies/libarchive-3.4.2/tar/test/test_extract.tar.lzo.uu b/dependencies/libarchive-3.4.2/tar/test/test_extract.tar.lzo.uu new file mode 100644 index 0000000..29dd8d8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_extract.tar.lzo.uu @@ -0,0 +1,9 @@ +begin 664 test_extract.tar.lzo +MB4Q:3P`-"AH*$#`@8`E``04#```!``"!M%!R@T``````$'1E?S@M7KY?XJIN<$F_7V +M\=*1N'H9#ZF]]XWF'T1HWC^3Z\GG:TA0#XVW03@`Z0A8DH3U.BZ)FNK^AU$3 +M&OGIH!HRC^P*CL,)\/,MGP``````2IVA+$<(^YX``94!@!@``&X^\DRQQ&?[ +(`@`````$65H` +` +end diff --git a/dependencies/libarchive-3.4.2/tar/test/test_extract.tar.zst.uu b/dependencies/libarchive-3.4.2/tar/test/test_extract.tar.zst.uu new file mode 100644 index 0000000..3df0caf --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_extract.tar.zst.uu @@ -0,0 +1,6 @@ +begin 644 test_extract.tar.zst +M*+4O_010S0,`Y+>!0*5E/PM"$7^K^1VI3SS-AX&_W0KQWY!-Z1(`_4$%[$"]test.out 2>test.err", + testprog, reffile)); + + assertFileExists("file1"); + assertTextFileContents("contents of file1.\n", "file1"); + assertFileExists("file2"); + assertTextFileContents("contents of file2.\n", "file2"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_bz2.c b/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_bz2.c new file mode 100644 index 0000000..b734dd2 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_bz2.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_extract_tar_bz2) +{ + const char *reffile = "test_extract.tar.bz2"; + int f; + + extract_reference_file(reffile); + f = systemf("%s -tf %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canBzip2()) { + assertEqualInt(0, systemf("%s -xf %s >test.out 2>test.err", + testprog, reffile)); + + assertFileExists("file1"); + assertTextFileContents("contents of file1.\n", "file1"); + assertFileExists("file2"); + assertTextFileContents("contents of file2.\n", "file2"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + } else { + skipping("It seems bzip2 is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_grz.c b/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_grz.c new file mode 100644 index 0000000..9c0615e --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_grz.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_extract_tar_grz) +{ + const char *reffile = "test_extract.tar.grz"; + int f; + + extract_reference_file(reffile); + f = systemf("%s -tf %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canGrzip()) { + assertEqualInt(0, systemf("%s -xf %s >test.out 2>test.err", + testprog, reffile)); + + assertFileExists("file1"); + assertTextFileContents("contents of file1.\n", "file1"); + assertFileExists("file2"); + assertTextFileContents("contents of file2.\n", "file2"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + } else { + skipping("It seems grzip is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_gz.c b/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_gz.c new file mode 100644 index 0000000..2fdb4ba --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_gz.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_extract_tar_gz) +{ + const char *reffile = "test_extract.tar.gz"; + int f; + + extract_reference_file(reffile); + f = systemf("%s -tf %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canGzip()) { + assertEqualInt(0, systemf("%s -xf %s >test.out 2>test.err", + testprog, reffile)); + + assertFileExists("file1"); + assertTextFileContents("contents of file1.\n", "file1"); + assertFileExists("file2"); + assertTextFileContents("contents of file2.\n", "file2"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + } else { + skipping("It seems gzip is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_lrz.c b/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_lrz.c new file mode 100644 index 0000000..56a0fb8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_lrz.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_extract_tar_lrz) +{ + const char *reffile = "test_extract.tar.lrz"; + int f; + + extract_reference_file(reffile); + f = systemf("%s -tf %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canLrzip()) { + assertEqualInt(0, systemf("%s -xf %s >test.out 2>test.err", + testprog, reffile)); + + assertFileExists("file1"); + assertTextFileContents("contents of file1.\n", "file1"); + assertFileExists("file2"); + assertTextFileContents("contents of file2.\n", "file2"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + } else { + skipping("It seems lrzip is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_lz.c b/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_lz.c new file mode 100644 index 0000000..5ec7e9a --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_lz.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_extract_tar_lz) +{ + const char *reffile = "test_extract.tar.lz"; + int f; + + extract_reference_file(reffile); + f = systemf("%s -tf %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canLzip()) { + assertEqualInt(0, systemf("%s -xf %s >test.out 2>test.err", + testprog, reffile)); + + assertFileExists("file1"); + assertTextFileContents("contents of file1.\n", "file1"); + assertFileExists("file2"); + assertTextFileContents("contents of file2.\n", "file2"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + } else { + skipping("It seems lzip is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_lz4.c b/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_lz4.c new file mode 100644 index 0000000..150d57d --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_lz4.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2012,2014 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_extract_tar_lz4) +{ + const char *reffile = "test_extract.tar.lz4"; + int f; + + extract_reference_file(reffile); + f = systemf("%s -tf %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canLz4()) { + assertEqualInt(0, systemf("%s -xf %s >test.out 2>test.err", + testprog, reffile)); + + assertFileExists("file1"); + assertTextFileContents("contents of file1.\n", "file1"); + assertFileExists("file2"); + assertTextFileContents("contents of file2.\n", "file2"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + } else { + skipping("It seems lz4 is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_lzma.c b/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_lzma.c new file mode 100644 index 0000000..2fa2af0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_lzma.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_extract_tar_lzma) +{ + const char *reffile = "test_extract.tar.lzma"; + int f; + + extract_reference_file(reffile); + f = systemf("%s -tf %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canLzma()) { + assertEqualInt(0, systemf("%s -xf %s >test.out 2>test.err", + testprog, reffile)); + + assertFileExists("file1"); + assertTextFileContents("contents of file1.\n", "file1"); + assertFileExists("file2"); + assertTextFileContents("contents of file2.\n", "file2"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + } else { + skipping("It seems lzma is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_lzo.c b/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_lzo.c new file mode 100644 index 0000000..17b4295 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_lzo.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_extract_tar_lzo) +{ + const char *reffile = "test_extract.tar.lzo"; + int f; + + extract_reference_file(reffile); + f = systemf("%s -tf %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canLzop()) { + assertEqualInt(0, systemf("%s -xf %s >test.out 2>test.err", + testprog, reffile)); + + assertFileExists("file1"); + assertTextFileContents("contents of file1.\n", "file1"); + assertFileExists("file2"); + assertTextFileContents("contents of file2.\n", "file2"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + } else { + skipping("It seems lzop is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_xz.c b/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_xz.c new file mode 100644 index 0000000..860bab7 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_xz.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_extract_tar_xz) +{ + const char *reffile = "test_extract.tar.xz"; + int f; + + extract_reference_file(reffile); + f = systemf("%s -tf %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canXz()) { + assertEqualInt(0, systemf("%s -xf %s >test.out 2>test.err", + testprog, reffile)); + + assertFileExists("file1"); + assertTextFileContents("contents of file1.\n", "file1"); + assertFileExists("file2"); + assertTextFileContents("contents of file2.\n", "file2"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + } else { + skipping("It seems xz is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_zstd.c b/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_zstd.c new file mode 100644 index 0000000..d67170c --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_extract_tar_zstd.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2017 Sean Purcell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_extract_tar_zstd) +{ + const char *reffile = "test_extract.tar.zst"; + int f; + + extract_reference_file(reffile); + f = systemf("%s -tf %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canZstd()) { + assertEqualInt(0, systemf("%s -xf %s >test.out 2>test.err", + testprog, reffile)); + + assertFileExists("file1"); + assertTextFileContents("contents of file1.\n", "file1"); + assertFileExists("file2"); + assertTextFileContents("contents of file2.\n", "file2"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + } else { + skipping("It seems zstd is not supported on this platform"); + } +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_format_newc.c b/dependencies/libarchive-3.4.2/tar/test/test_format_newc.c new file mode 100644 index 0000000..808fa4b --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_format_newc.c @@ -0,0 +1,64 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_format_newc) +{ + + assertMakeFile("file1", 0644, "file1"); + assertMakeFile("file2", 0644, "file2"); + assertMakeHardlink("file3", "file1"); + + /* Test 1: Create an archive file with a newc format. */ + assertEqualInt(0, + systemf("%s -cf test1.cpio --format newc file1 file2 file3", + testprog)); + assertMakeDir("test1", 0755); + assertChdir("test1"); + assertEqualInt(0, + systemf("%s -xf ../test1.cpio >test.out 2>test.err", testprog)); + assertFileContents("file1", 5, "file1"); + assertFileContents("file2", 5, "file2"); + assertFileContents("file1", 5, "file3"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 2: Exclude one of hardlinked files. */ + assertEqualInt(0, + systemf("%s -cf test2.cpio --format newc file1 file2", + testprog)); + assertMakeDir("test2", 0755); + assertChdir("test2"); + assertEqualInt(0, + systemf("%s -xf ../test2.cpio >test.out 2>test.err", testprog)); + assertFileContents("file1", 5, "file1"); + assertFileContents("file2", 5, "file2"); + assertFileNotExists("file3"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_help.c b/dependencies/libarchive-3.4.2/tar/test/test_help.c new file mode 100644 index 0000000..3bb517d --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_help.c @@ -0,0 +1,84 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_help.c,v 1.2 2008/05/26 17:10:10 kientzle Exp $"); + +/* + * Test that "--help", "-h", and "-W help" options all work and + * generate reasonable output. + */ + +static int +in_first_line(const char *p, const char *substring) +{ + size_t l = strlen(substring); + + while (*p != '\0' && *p != '\n') { + if (memcmp(p, substring, l) == 0) + return (1); + ++p; + } + return (0); +} + +DEFINE_TEST(test_help) +{ + int r; + char *p; + size_t plen; + + /* Exercise --help option. */ + r = systemf("%s --help >help.stdout 2>help.stderr", testprog); + assertEqualInt(r, 0); + failure("--help should generate nothing to stderr."); + assertEmptyFile("help.stderr"); + /* Help message should start with name of program. */ + p = slurpfile(&plen, "help.stdout"); + failure("Help output should be long enough."); + assert(plen >= 6); + failure("First line of help output should contain 'bsdtar': %s", p); + assert(in_first_line(p, "bsdtar")); + /* + * TODO: Extend this check to further verify that --help output + * looks approximately right. + */ + free(p); + + /* -h option should generate the same output. */ + r = systemf("%s -h >h.stdout 2>h.stderr", testprog); + assertEqualInt(r, 0); + failure("-h should generate nothing to stderr."); + assertEmptyFile("h.stderr"); + failure("stdout should be same for -h and --help"); + assertEqualFile("h.stdout", "help.stdout"); + + /* -W help should be another synonym. */ + r = systemf("%s -W help >Whelp.stdout 2>Whelp.stderr", testprog); + assertEqualInt(r, 0); + failure("-W help should generate nothing to stderr."); + assertEmptyFile("Whelp.stderr"); + failure("stdout should be same for -W help and --help"); + assertEqualFile("Whelp.stdout", "help.stdout"); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_leading_slash.c b/dependencies/libarchive-3.4.2/tar/test/test_leading_slash.c new file mode 100644 index 0000000..572c45e --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_leading_slash.c @@ -0,0 +1,50 @@ +/*- + * Copyright (c) 2003-2014 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_leading_slash) +{ + const char *reffile = "test_leading_slash.tar"; + char *errfile; + size_t errfile_size; + const char *expected_errmsg = "Removing leading '/' from member names"; + + extract_reference_file(reffile); + assertEqualInt(0, systemf("%s -xf %s >test.out 2>test.err", testprog, reffile)); + assertFileExists("foo/file"); + assertTextFileContents("foo\x0a", "foo/file"); + assertTextFileContents("foo\x0a", "foo/hardlink"); + assertIsHardlink("foo/file", "foo/hardlink"); + assertEmptyFile("test.out"); + + /* Verify the error output contains the expected text somewhere in it */ + if (assertFileExists("test.err")) { + errfile = slurpfile(&errfile_size, "test.err"); + assert(strstr(errfile, expected_errmsg) != NULL); + free(errfile); + } +} + diff --git a/dependencies/libarchive-3.4.2/tar/test/test_leading_slash.tar.uu b/dependencies/libarchive-3.4.2/tar/test/test_leading_slash.tar.uu new file mode 100644 index 0000000..eeb27c3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_leading_slash.tar.uu @@ -0,0 +1,60 @@ +begin 644 test_leading_slash.tar +M+V9O;R]F:6QE```````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````#`P,#8T-"``,#`P,#`P(``P,#`P,#`@`#`P,#`P,#`P,#`T +M(#$R-#$V,S4U-34V(#`Q,C8V-P`@,``````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````!Ustderr1", testprog)); + assertEmptyFile("stderr1"); + assert(0 != systemf("%s -cf archive.tar file1 file2 file3 2>stderr2", testprog)); + assertFileContainsNoInvalidStrings("stderr2", invalid_stderr); + assert(0 != systemf("%s -cf archive.tar 2>stderr3", testprog)); + assertFileContainsNoInvalidStrings("stderr3", invalid_stderr); + assert(0 != systemf("%s -cf archive.tar file3 file4 2>stderr4", testprog)); + assertFileContainsNoInvalidStrings("stderr4", invalid_stderr); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_C_mtree.c b/dependencies/libarchive-3.4.2/tar/test/test_option_C_mtree.c new file mode 100644 index 0000000..ccadc38 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_C_mtree.c @@ -0,0 +1,89 @@ +/*- + * Copyright (c) 2018 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Arshan Khanifar + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_C_mtree) +{ + char *p0; + size_t s; + int r; + p0 = NULL; + char *content = "./foo type=file uname=root gname=root mode=0755\n"; + char *filename = "output.tar"; +#if defined(_WIN32) && !defined(CYGWIN) + char *p; +#endif + + /* an absolute path to mtree file */ + char *mtree_file = "/METALOG.mtree"; + char *absolute_path = malloc(strlen(testworkdir) + strlen(mtree_file) + 1); + strcpy(absolute_path, testworkdir); + strcat(absolute_path, mtree_file ); + + /* Create an archive using an mtree file. */ + assertMakeFile(absolute_path, 0777, content); + assertMakeDir("bar", 0775); + assertMakeFile("bar/foo", 0777, "abc"); + +#if defined(_WIN32) && !defined(CYGWIN) + p = absolute_path; + while(*p != '\0') { + if (*p == '/') + *p = '\\'; + p++; + } + + r = systemf("%s -cf %s -C bar @%s >step1.out 2>step1.err", testprog, filename, absolute_path); + failure("Error invoking %s -cf %s -C bar @%s", testprog, filename, absolute_path); +#else + r = systemf("%s -cf %s -C bar \"@%s\" >step1.out 2>step1.err", testprog, filename, absolute_path); + failure("Error invoking %s -cf %s -C bar \"@%s\"", testprog, filename, absolute_path); +#endif + + assertEqualInt(r, 0); + assertEmptyFile("step1.out"); + assertEmptyFile("step1.err"); + + /* Do validation of the constructed archive. */ + + p0 = slurpfile(&s, "output.tar"); + if (!assert(p0 != NULL)) + goto done; + if (!assert(s >= 2048)) + goto done; + assertEqualMem(p0 + 0, "./foo", 5); + assertEqualMem(p0 + 512, "abc", 3); + assertEqualMem(p0 + 1024, "\0\0\0\0\0\0\0\0", 8); + assertEqualMem(p0 + 1536, "\0\0\0\0\0\0\0\0", 8); +done: + free(p0); + free(absolute_path); +} + + diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_C_upper.c b/dependencies/libarchive-3.4.2/tar/test/test_option_C_upper.c new file mode 100644 index 0000000..538890f --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_C_upper.c @@ -0,0 +1,149 @@ +/*- + * Copyright (c) 2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_C_upper) +{ + int r; + + assertMakeDir("d1", 0755); + assertMakeDir("d2", 0755); + assertMakeFile("d1/file1", 0644, "d1/file1"); + assertMakeFile("d1/file2", 0644, "d1/file2"); + assertMakeFile("d2/file1", 0644, "d2/file1"); + assertMakeFile("d2/file2", 0644, "d2/file2"); + + /* + * Test 1: Basic use of -C + */ + assertMakeDir("test1", 0755); + assertChdir("test1"); + assertEqualInt(0, systemf("%s -cf archive.tar -C ../d1 file1 -C ../d2 file2", testprog)); + assertEqualInt(0, + systemf("%s -xf archive.tar >test.out 2>test.err", testprog)); + assertFileContents("d1/file1", 8, "file1"); + assertFileContents("d2/file2", 8, "file2"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + + /* + * Test 2: Multiple -C + */ + assertMakeDir("test2", 0755); + assertChdir("test2"); + assertEqualInt(0, systemf("%s -cf archive.tar -C .. -C d1 file1 -C .. -C d2 file2", testprog)); + assertEqualInt(0, + systemf("%s -xf archive.tar >test.out 2>test.err", testprog)); + assertFileContents("d1/file1", 8, "file1"); + assertFileContents("d2/file2", 8, "file2"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* + * Test 3: -C fail + */ + assertMakeDir("test3", 0755); + assertChdir("test3"); + r = systemf("%s -cf archive.tar -C ../XXX file1 -C ../d2 file2 2>write.err", testprog); + assert(r != 0); + assertNonEmptyFile("write.err"); + assertEqualInt(0, + systemf("%s -xf archive.tar >test.out 2>test.err", testprog)); + assertFileNotExists("file1"); + assertFileNotExists("file2"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* + * Test 4: Absolute -C + */ + assertMakeDir("test4", 0755); + assertChdir("test4"); + assertEqualInt(0, + systemf("%s -cf archive.tar -C %s/d1 file1", + testprog, testworkdir)); + assertEqualInt(0, + systemf("%s -xf archive.tar >test.out 2>test.err", testprog)); + assertFileContents("d1/file1", 8, "file1"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* + * Test 5: Unnecessary -C ignored even if directory named doesn't exist + */ + assertMakeDir("test5", 0755); + assertChdir("test5"); + assertEqualInt(0, + systemf("%s -cf archive.tar -C XXX -C %s/d1 file1", + testprog, testworkdir)); + assertEqualInt(0, + systemf("%s -xf archive.tar >test.out 2>test.err", testprog)); + assertFileContents("d1/file1", 8, "file1"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* + * Test 6: Necessary -C not ignored if directory doesn't exist + */ + assertMakeDir("test6", 0755); + assertChdir("test6"); + r = systemf("%s -cf archive.tar -C XXX -C ../d1 file1 2>write.err", + testprog); + assert(r != 0); + assertNonEmptyFile("write.err"); + assertEqualInt(0, + systemf("%s -xf archive.tar >test.out 2>test.err", testprog)); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* + * Test 7: -C used without specifying directory + */ + assertMakeDir("test7", 0755); + assertChdir("test7"); + r = systemf("%s -cf archive.tar ../d1/file1 -C 2>write.err", testprog); + assert(r != 0); + assertNonEmptyFile("write.err"); + assertChdir(".."); + + /* + * Test 8: -C used with meaningless option '' + */ + assertMakeDir("test8", 0755); + assertChdir("test8"); + r = systemf("%s -cf archive.tar ../d1/file1 -C \"\" 2>write.err", + testprog); + assert(r != 0); + assertNonEmptyFile("write.err"); + assertChdir(".."); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_H_upper.c b/dependencies/libarchive-3.4.2/tar/test/test_option_H_upper.c new file mode 100644 index 0000000..2c2ad33 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_H_upper.c @@ -0,0 +1,92 @@ +/*- + * Copyright (c) 2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_H_upper) +{ + + if (!canSymlink()) { + skipping("Can't test symlinks on this filesystem"); + return; + } + + /* + * Create a sample archive. + */ + assertMakeDir("in", 0755); + assertChdir("in"); + assertMakeDir("d1", 0755); + assertMakeSymlink("ld1", "d1", 1); + assertMakeFile("d1/file1", 0644, "d1/file1"); + assertMakeFile("d1/file2", 0644, "d1/file2"); + assertMakeSymlink("d1/link1", "file1", 0); + assertMakeSymlink("d1/linkX", "fileX", 0); + assertMakeSymlink("link2", "d1/file2", 0); + assertMakeSymlink("linkY", "d1/fileY", 0); + assertChdir(".."); + + /* Test 1: Without -H */ + assertMakeDir("test1", 0755); + assertEqualInt(0, + systemf("%s -cf test1/archive.tar -C in . >test1/c.out 2>test1/c.err", testprog)); + assertChdir("test1"); + assertEqualInt(0, + systemf("%s -xf archive.tar >c.out 2>c.err", testprog)); + assertIsSymlink("ld1", "d1", 1); + assertIsSymlink("d1/link1", "file1", 0); + assertIsSymlink("d1/linkX", "fileX", 0); + assertIsSymlink("link2", "d1/file2", 0); + assertIsSymlink("linkY", "d1/fileY", 0); + assertChdir(".."); + + /* Test 2: With -H, no symlink on command line. */ + assertMakeDir("test2", 0755); + assertEqualInt(0, + systemf("%s -cf test2/archive.tar -H -C in . >test2/c.out 2>test2/c.err", testprog)); + assertChdir("test2"); + assertEqualInt(0, + systemf("%s -xf archive.tar >c.out 2>c.err", testprog)); + assertIsSymlink("ld1", "d1", 1); + assertIsSymlink("d1/link1", "file1", 0); + assertIsSymlink("d1/linkX", "fileX", 0); + assertIsSymlink("link2", "d1/file2", 0); + assertIsSymlink("linkY", "d1/fileY", 0); + assertChdir(".."); + + /* Test 3: With -H, some symlinks on command line. */ + assertMakeDir("test3", 0755); + assertEqualInt(0, + systemf("%s -cf test3/archive.tar -H -C in ld1 d1 link2 linkY >test2/c.out 2>test2/c.err", testprog)); + assertChdir("test3"); + assertEqualInt(0, + systemf("%s -xf archive.tar >c.out 2>c.err", testprog)); + assertIsDir("ld1", umasked(0755)); + assertIsSymlink("d1/linkX", "fileX", 0); + assertIsSymlink("d1/link1", "file1", 0); + assertIsReg("link2", umasked(0644)); + assertIsSymlink("linkY", "d1/fileY", 0); + assertChdir(".."); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_L_upper.c b/dependencies/libarchive-3.4.2/tar/test/test_option_L_upper.c new file mode 100644 index 0000000..5697b0f --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_L_upper.c @@ -0,0 +1,92 @@ +/*- + * Copyright (c) 2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_L_upper) +{ + + if (!canSymlink()) { + skipping("Can't test symlinks on this filesystem"); + return; + } + + /* + * Create a sample archive. + */ + assertMakeDir("in", 0755); + assertChdir("in"); + assertMakeDir("d1", 0755); + assertMakeSymlink("ld1", "d1", 1); + assertMakeFile("d1/file1", 0644, "d1/file1"); + assertMakeFile("d1/file2", 0644, "d1/file2"); + assertMakeSymlink("d1/link1", "file1", 0); + assertMakeSymlink("d1/linkX", "fileX", 0); + assertMakeSymlink("link2", "d1/file2", 0); + assertMakeSymlink("linkY", "d1/fileY", 0); + assertChdir(".."); + + /* Test 1: Without -L */ + assertMakeDir("test1", 0755); + assertEqualInt(0, + systemf("%s -cf test1/archive.tar -C in . >test1/c.out 2>test1/c.err", testprog)); + assertChdir("test1"); + assertEqualInt(0, + systemf("%s -xf archive.tar >c.out 2>c.err", testprog)); + assertIsSymlink("ld1", "d1", 1); + assertIsSymlink("d1/link1", "file1", 0); + assertIsSymlink("d1/linkX", "fileX", 0); + assertIsSymlink("link2", "d1/file2", 0); + assertIsSymlink("linkY", "d1/fileY", 0); + assertChdir(".."); + + /* Test 2: With -L, no symlink on command line. */ + assertMakeDir("test2", 0755); + assertEqualInt(0, + systemf("%s -cf test2/archive.tar -L -C in . >test2/c.out 2>test2/c.err", testprog)); + assertChdir("test2"); + assertEqualInt(0, + systemf("%s -xf archive.tar >c.out 2>c.err", testprog)); + assertIsDir("ld1", umasked(0755)); + assertIsReg("d1/link1", umasked(0644)); + assertIsSymlink("d1/linkX", "fileX", 0); + assertIsReg("link2", umasked(0644)); + assertIsSymlink("linkY", "d1/fileY", 0); + assertChdir(".."); + + /* Test 3: With -L, some symlinks on command line. */ + assertMakeDir("test3", 0755); + assertEqualInt(0, + systemf("%s -cf test3/archive.tar -L -C in ld1 d1 link2 linkY >test2/c.out 2>test2/c.err", testprog)); + assertChdir("test3"); + assertEqualInt(0, + systemf("%s -xf archive.tar >c.out 2>c.err", testprog)); + assertIsDir("ld1", umasked(0755)); + assertIsReg("d1/link1", umasked(0644)); + assertIsSymlink("d1/linkX", "fileX", 0); + assertIsReg("link2", umasked(0644)); + assertIsSymlink("linkY", "d1/fileY", 0); + assertChdir(".."); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_O_upper.c b/dependencies/libarchive-3.4.2/tar/test/test_option_O_upper.c new file mode 100644 index 0000000..b9c8c0c --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_O_upper.c @@ -0,0 +1,87 @@ +/*- + * Copyright (c) 2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +static const char *test4out[] = {"file1", "file2", NULL}; +static const char *test5err[] = {"file1", "file2", NULL}; + +DEFINE_TEST(test_option_O_upper) +{ + assertMakeFile("file1", 0644, "file1"); + assertMakeFile("file2", 0644, "file2"); + assertEqualInt(0, systemf("%s -cf archive.tar file1 file2", testprog)); + + /* Test 1: -x without -O */ + assertMakeDir("test1", 0755); + assertChdir("test1"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar >test.out 2>test.err", testprog)); + assertFileContents("file1", 5, "file1"); + assertFileContents("file2", 5, "file2"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 2: -x with -O */ + assertMakeDir("test2", 0755); + assertChdir("test2"); + assertEqualInt(0, + systemf("%s -xOf ../archive.tar file1 >test.out 2>test.err", testprog)); + assertFileNotExists("file1"); + assertFileNotExists("file2"); + assertFileContents("file1", 5, "test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 3: -x with -O and multiple files */ + assertMakeDir("test3", 0755); + assertChdir("test3"); + assertEqualInt(0, + systemf("%s -xOf ../archive.tar >test.out 2>test.err", testprog)); + assertFileNotExists("file1"); + assertFileNotExists("file2"); + assertFileContents("file1file2", 10, "test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 4: -t without -O */ + assertMakeDir("test4", 0755); + assertChdir("test4"); + assertEqualInt(0, + systemf("%s -tf ../archive.tar >test.out 2>test.err", testprog)); + assertFileContainsLinesAnyOrder("test.out", test4out); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 5: -t with -O */ + assertMakeDir("test5", 0755); + assertChdir("test5"); + assertEqualInt(0, + systemf("%s -tOf ../archive.tar >test.out 2>test.err", testprog)); + assertEmptyFile("test.out"); + assertFileContainsLinesAnyOrder("test.err", test5err); + assertChdir(".."); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_T_upper.c b/dependencies/libarchive-3.4.2/tar/test/test_option_T_upper.c new file mode 100644 index 0000000..f2b65d7 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_T_upper.c @@ -0,0 +1,160 @@ +/*- + * Copyright (c) 2003-2008 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_option_T.c,v 1.3 2008/08/15 06:12:02 kientzle Exp $"); + +static int +tryMakeFile(const char *fn) +{ + FILE *f = fopen(fn, "w"); + if (f == NULL) + return (0); + fclose(f); + return (1); +} + +DEFINE_TEST(test_option_T_upper) +{ + FILE *f; + int r; + int gnarlyFilesSupported; + + /* Create a simple dir hierarchy; bail if anything fails. */ + if (!assertMakeDir("d1", 0755)) return; + if (!assertMakeDir("d1/d2", 0755)) return; + if (!assertMakeFile("f", 0644, "")) return; + if (!assertMakeFile("d1/f1", 0644, "")) return; + if (!assertMakeFile("d1/f2", 0644, "")) return; + if (!assertMakeFile("d1/d2/f3", 0644, "")) return; + if (!assertMakeFile("d1/d2/f4", 0644, "")) return; + if (!assertMakeFile("d1/d2/f5", 0644, "")) return; + if (!assertMakeFile("d1/d2/f6", 0644, "")) return; + /* Some platforms don't permit such things; just skip it. */ + gnarlyFilesSupported = tryMakeFile("d1/d2/f\x0a"); + + /* Populate a file list */ + f = fopen("filelist", "w+"); + if (!assert(f != NULL)) + return; + /* Use a variety of text line endings. */ + fprintf(f, "f\x0d"); /* CR */ + fprintf(f, "d1/f1\x0d\x0a"); /* CRLF */ + fprintf(f, "d1/d2/f4\x0a"); /* NL */ + fprintf(f, "d1/d2/f6"); /* EOF */ + fclose(f); + + /* Populate a second file list */ + f = fopen("filelist2", "w+"); + if (!assert(f != NULL)) + return; + /* Use null-terminated names. */ + fprintf(f, "d1/d2/f3"); + assertEqualInt(1, fwrite("\0", 1, 1, f)); + fprintf(f, "d1/d2/f5"); + assertEqualInt(1, fwrite("\0", 1, 1, f)); + if (gnarlyFilesSupported) { + fprintf(f, "d1/d2/f\x0a"); + assertEqualInt(1, fwrite("\0", 1, 1, f)); + } + fclose(f); + + /* Use -c -T to archive up the files. */ + r = systemf("%s -c -f test1.tar -T filelist > test1.out 2> test1.err", + testprog); + assert(r == 0); + assertEmptyFile("test1.out"); + assertEmptyFile("test1.err"); + + /* Use -x -T to dearchive the files */ + if (!assertMakeDir("test1", 0755)) return; + systemf("%s -x -f test1.tar -T filelist -C test1" + " > test1b.out 2> test1b.err", testprog); + assertEmptyFile("test1b.out"); + assertEmptyFile("test1b.err"); + + /* Verify the files were extracted. */ + assertFileExists("test1/f"); + assertFileExists("test1/d1/f1"); + assertFileNotExists("test1/d1/f2"); + assertFileNotExists("test1/d1/d2/f3"); + assertFileExists("test1/d1/d2/f4"); + assertFileNotExists("test1/d1/d2/f5"); + assertFileExists("test1/d1/d2/f6"); + if (gnarlyFilesSupported) { + assertFileNotExists("test1/d1/d2/f\x0a"); + } + + /* Use -r -T to add more files to the archive. */ + systemf("%s -r -f test1.tar --null -T filelist2 > test2.out 2> test2.err", + testprog); + assertEmptyFile("test2.out"); + assertEmptyFile("test2.err"); + + /* Use -x without -T to dearchive the files (ensure -r worked) */ + if (!assertMakeDir("test3", 0755)) return; + systemf("%s -x -f test1.tar -C test3" + " > test3.out 2> test3.err", testprog); + assertEmptyFile("test3.out"); + assertEmptyFile("test3.err"); + /* Verify the files were extracted.*/ + assertFileExists("test3/f"); + assertFileExists("test3/d1/f1"); + assertFileNotExists("test3/d1/f2"); + assertFileExists("test3/d1/d2/f3"); + assertFileExists("test3/d1/d2/f4"); + assertFileExists("test3/d1/d2/f5"); + assertFileExists("test3/d1/d2/f6"); + if (gnarlyFilesSupported) { + assertFileExists("test3/d1/d2/f\x0a"); + } + + /* Use -x -T to dearchive the files (verify -x -T together) */ + if (!assertMakeDir("test2", 0755)) return; + systemf("%s -x -f test1.tar -T filelist -C test2" + " > test2b.out 2> test2b.err", testprog); + assertEmptyFile("test2b.out"); + assertEmptyFile("test2b.err"); + /* Verify the files were extracted.*/ + assertFileExists("test2/f"); + assertFileExists("test2/d1/f1"); + assertFileNotExists("test2/d1/f2"); + assertFileNotExists("test2/d1/d2/f3"); + assertFileExists("test2/d1/d2/f4"); + assertFileNotExists("test2/d1/d2/f5"); + assertFileExists("test2/d1/d2/f6"); + if (gnarlyFilesSupported) { + assertFileNotExists("test2/d1/d2/f\x0a"); + } + + assertMakeDir("test4", 0755); + assertMakeDir("test4_out", 0755); + assertMakeDir("test4_out2", 0755); + assertMakeDir("test4/d1", 0755); + assertMakeFile("test4/d1/foo", 0644, ""); + + + /* TODO: Include some use of -C directory-changing within the filelist. */ + /* I'm pretty sure -C within the filelist is broken on extract. */ +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_U_upper.c b/dependencies/libarchive-3.4.2/tar/test/test_option_U_upper.c new file mode 100644 index 0000000..d864e13 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_U_upper.c @@ -0,0 +1,159 @@ +/*- + * Copyright (c) 2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_U_upper) +{ + int r; + + assertMakeFile("file1", 0644, "file1"); + assertMakeDir("d1", 0755); + assertMakeFile("d1/file1", 0644, "d1/file1"); + assertEqualInt(0, systemf("%s -cf archive.tar file1 d1/file1", testprog)); + + /* + * bsdtar's man page used to claim that -x without -U would + * not break hard links. This was and is nonsense. The first + * two tests here simply verify that existing hard links get + * broken regardless. + */ + + /* Test 1: -x without -U */ + assertMakeDir("test1", 0755); + assertChdir("test1"); + assertMakeFile("file1", 0644, "file1new"); + assertMakeHardlink("file2", "file1"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar >test.out 2>test.err", testprog)); + assertFileContents("file1", 5, "file1"); + assertFileContents("file1new", 8, "file2"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + + /* Test 2: -x with -U */ + assertMakeDir("test2", 0755); + assertChdir("test2"); + assertMakeFile("file1", 0644, "file1new"); + assertMakeHardlink("file2", "file1"); + assertEqualInt(0, + systemf("%s -xUf ../archive.tar >test.out 2>test.err", testprog)); + assertFileContents("file1", 5, "file1"); + assertFileContents("file1new", 8, "file2"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* + * -U does make a difference in how bsdtar handles unwanted symlinks, + * though. It interacts with -P. + */ + if (!canSymlink()) + return; + + /* Test 3: Intermediate dir symlink causes error by default */ + assertMakeDir("test3", 0755); + assertChdir("test3"); + assertMakeDir("realDir", 0755); + assertMakeSymlink("d1", "realDir", 1); + r = systemf("%s -xf ../archive.tar d1/file1 >test.out 2>test.err", testprog); + assert(r != 0); + assertIsSymlink("d1", "realDir", 1); + assertFileNotExists("d1/file1"); + assertEmptyFile("test.out"); + assertNonEmptyFile("test.err"); + assertChdir(".."); + + /* Test 4: Intermediate dir symlink gets removed with -U */ + assertMakeDir("test4", 0755); + assertChdir("test4"); + assertMakeDir("realDir", 0755); + assertMakeSymlink("d1", "realDir", 1); + assertEqualInt(0, + systemf("%s -xUf ../archive.tar >test.out 2>test.err", testprog)); + assertIsDir("d1", -1); + assertFileContents("d1/file1", 8, "d1/file1"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 5: Intermediate dir symlink is followed with -P */ + assertMakeDir("test5", 0755); + assertChdir("test5"); + assertMakeDir("realDir", 0755); + assertMakeSymlink("d1", "realDir", 1); + assertEqualInt(0, + systemf("%s -xPf ../archive.tar d1/file1 >test.out 2>test.err", testprog)); + assertIsSymlink("d1", "realDir", 1); + assertFileContents("d1/file1", 8, "d1/file1"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 6: Intermediate dir symlink is followed with -PU */ + assertMakeDir("test6", 0755); + assertChdir("test6"); + assertMakeDir("realDir", 0755); + assertMakeSymlink("d1", "realDir", 1); + assertEqualInt(0, + systemf("%s -xPUf ../archive.tar d1/file1 >test.out 2>test.err", testprog)); + assertIsSymlink("d1", "realDir", 1); + assertFileContents("d1/file1", 8, "d1/file1"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 7: Final file symlink replaced by default */ + assertMakeDir("test7", 0755); + assertChdir("test7"); + assertMakeDir("d1", 0755); + assertMakeFile("d1/realfile1", 0644, "realfile1"); + assertMakeSymlink("d1/file1", "d1/realfile1", 0); + assertEqualInt(0, + systemf("%s -xf ../archive.tar d1/file1 >test.out 2>test.err", testprog)); + assertIsReg("d1/file1", umasked(0644)); + assertFileContents("d1/file1", 8, "d1/file1"); + assertFileContents("realfile1", 9, "d1/realfile1"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 8: Final file symlink replaced with -PU */ + assertMakeDir("test8", 0755); + assertChdir("test8"); + assertMakeDir("d1", 0755); + assertMakeFile("d1/realfile1", 0644, "realfile1"); + assertMakeSymlink("d1/file1", "d1/realfile1", 0); + assertEqualInt(0, + systemf("%s -xPUf ../archive.tar d1/file1 >test.out 2>test.err", testprog)); + assertIsReg("d1/file1", umasked(0644)); + assertFileContents("d1/file1", 8, "d1/file1"); + assertFileContents("realfile1", 9, "d1/realfile1"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_X_upper.c b/dependencies/libarchive-3.4.2/tar/test/test_option_X_upper.c new file mode 100644 index 0000000..4916af2 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_X_upper.c @@ -0,0 +1,159 @@ +/*- + * Copyright (c) 2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_X_upper) +{ + int r; + + /* + * Create a sample archive. + */ + assertMakeFile("file1", 0644, "file1"); + assertMakeFile("file2", 0644, "file2"); + assertMakeFile("file3a", 0644, "file3a"); + assertMakeFile("file4a", 0644, "file4a"); + assertEqualInt(0, + systemf("%s -cf archive.tar file1 file2 file3a file4a", testprog)); + + /* + * Now, try extracting from the test archive with various -X usage. + */ + + /* Test 1: Without -X */ + assertMakeDir("test1", 0755); + assertChdir("test1"); + r = systemf("%s -xf ../archive.tar >test.out 2>test.err", + testprog); + if (!assertEqualInt(0, r)) + return; + + assertFileContents("file1", 5, "file1"); + assertFileContents("file2", 5, "file2"); + assertFileContents("file3a", 6, "file3a"); + assertFileContents("file4a", 6, "file4a"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 2: Use -X to skip one file */ + assertMakeDir("test2", 0755); + assertChdir("test2"); + assertMakeFile("exclusions", 0644, "file1\n"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar -X exclusions >test.out 2>test.err", testprog)); + assertFileNotExists("file1"); + assertFileContents("file2", 5, "file2"); + assertFileContents("file3a", 6, "file3a"); + assertFileContents("file4a", 6, "file4a"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 3: Use -X to skip multiple files */ + assertMakeDir("test3", 0755); + assertChdir("test3"); + assertMakeFile("exclusions", 0644, "file1\nfile2\n"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar -X exclusions >test.out 2>test.err", testprog)); + assertFileNotExists("file1"); + assertFileNotExists("file2"); + assertFileContents("file3a", 6, "file3a"); + assertFileContents("file4a", 6, "file4a"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 4: Omit trailing \n */ + assertMakeDir("test4", 0755); + assertChdir("test4"); + assertMakeFile("exclusions", 0644, "file1\nfile2"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar -X exclusions >test.out 2>test.err", testprog)); + assertFileNotExists("file1"); + assertFileNotExists("file2"); + assertFileContents("file3a", 6, "file3a"); + assertFileContents("file4a", 6, "file4a"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 5: include/exclude without overlap */ + assertMakeDir("test5", 0755); + assertChdir("test5"); + assertMakeFile("exclusions", 0644, "file1\nfile2"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar -X exclusions file3a >test.out 2>test.err", testprog)); + assertFileNotExists("file1"); + assertFileNotExists("file2"); + assertFileContents("file3a", 6, "file3a"); + assertFileNotExists("file4a"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 6: Overlapping include/exclude */ + assertMakeDir("test6", 0755); + assertChdir("test6"); + assertMakeFile("exclusions", 0644, "file1\nfile2"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar -X exclusions file1 file3a >test.out 2>test.err", testprog)); + assertFileNotExists("file1"); + assertFileNotExists("file2"); + assertFileContents("file3a", 6, "file3a"); + assertFileNotExists("file4a"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 7: with pattern */ + assertMakeDir("test7", 0755); + assertChdir("test7"); + assertMakeFile("exclusions", 0644, "file*a\nfile1"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar -X exclusions >test.out 2>test.err", testprog)); + assertFileNotExists("file1"); + assertFileContents("file2", 5, "file2"); + assertFileNotExists("file3a"); + assertFileNotExists("file4a"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 8: with empty exclusions file */ + assertMakeDir("test8", 0755); + assertChdir("test8"); + assertMakeFile("exclusions", 0644, ""); + assertEqualInt(0, + systemf("%s -xf ../archive.tar -X exclusions >test.out 2>test.err", testprog)); + assertFileContents("file1", 5, "file1"); + assertFileContents("file2", 5, "file2"); + assertFileContents("file3a", 6, "file3a"); + assertFileContents("file4a", 6, "file4a"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_a.c b/dependencies/libarchive-3.4.2/tar/test/test_option_a.c new file mode 100644 index 0000000..d9eed87 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_a.c @@ -0,0 +1,117 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_a) +{ + size_t s; + char *p; + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Test1: archive it with .tar.Z suffix. */ + assertEqualInt(0, + systemf("%s -acf test1.tar.Z f 2>test1.err", testprog)); + assertEmptyFile("test1.err"); + /* Check that the archive file has a compress signature. */ + p = slurpfile(&s, "test1.tar.Z"); + assert(s > 2); + failure("The archive should be compressed"); + assertEqualMem(p, "\x1f\x9d", 2); + free(p); + + /* Test2: archive it with .taZ suffix. */ + assertEqualInt(0, + systemf("%s -acf test2.taZ f 2>test2.err", testprog)); + assertEmptyFile("test2.err"); + /* Check that the archive file has a compress signature. */ + p = slurpfile(&s, "test2.taZ"); + assert(s > 2); + failure("The archive should be compressed"); + assertEqualMem(p, "\x1f\x9d", 2); + free(p); + + /* Test3: archive it with .tar.Z.uu suffix. */ + assertEqualInt(0, + systemf("%s -acf test3.tar.Z.uu f 2>test3.err", testprog)); + assertEmptyFile("test3.err"); + /* Check that the archive file has a compress signature. */ + p = slurpfile(&s, "test3.tar.Z.uu"); + assert(s > 12); + failure("The archive should be uuencoded"); + assertEqualMem(p, "begin 644 -\n", 12); + free(p); + + /* Test4: archive it with .zip suffix. */ + assertEqualInt(0, + systemf("%s -acf test4.zip f 2>test4.err", testprog)); + assertEmptyFile("test4.err"); + /* Check that the archive file has a compress signature. */ + p = slurpfile(&s, "test4.zip"); + assert(s > 4); + failure("The archive should be zipped"); + assertEqualMem(p, "\x50\x4b\x03\x04", 4); + free(p); + + /* Test5: archive it with .tar.Z suffix and --uuencode option. */ + assertEqualInt(0, + systemf("%s -acf test5.tar.Z --uuencode f 2>test5.err", + testprog)); + assertEmptyFile("test5.err"); + /* Check that the archive file has a compress signature. */ + p = slurpfile(&s, "test5.tar.Z"); + assert(s > 2); + failure("The archive should be compressed, ignoring --uuencode option"); + assertEqualMem(p, "\x1f\x9d", 2); + free(p); + + /* Test6: archive it with .xxx suffix(unknown suffix) and + * --uuencode option. */ + assertEqualInt(0, + systemf("%s -acf test6.xxx --uuencode f 2>test6.err", + testprog)); + assertEmptyFile("test6.err"); + /* Check that the archive file has a compress signature. */ + p = slurpfile(&s, "test6.xxx"); + assert(s > 12); + failure("The archive should be uuencoded"); + assertEqualMem(p, "begin 644 -\n", 12); + free(p); + + /* Test7: archive it with .tar.Z suffix using a long-name option. */ + assertEqualInt(0, + systemf("%s --auto-compress -cf test7.tar.Z f 2>test7.err", + testprog)); + assertEmptyFile("test7.err"); + /* Check that the archive file has a compress signature. */ + p = slurpfile(&s, "test7.tar.Z"); + assert(s > 2); + failure("The archive should be compressed"); + assertEqualMem(p, "\x1f\x9d", 2); + free(p); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_acls.c b/dependencies/libarchive-3.4.2/tar/test/test_option_acls.c new file mode 100644 index 0000000..f7451c8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_acls.c @@ -0,0 +1,512 @@ +/*- + * Copyright (c) 2017 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +#if ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBACL +static const acl_perm_t acl_perms[] = { +#if ARCHIVE_ACL_DARWIN + ACL_READ_DATA, + ACL_LIST_DIRECTORY, + ACL_WRITE_DATA, + ACL_ADD_FILE, + ACL_EXECUTE, + ACL_SEARCH, + ACL_DELETE, + ACL_APPEND_DATA, + ACL_ADD_SUBDIRECTORY, + ACL_DELETE_CHILD, + ACL_READ_ATTRIBUTES, + ACL_WRITE_ATTRIBUTES, + ACL_READ_EXTATTRIBUTES, + ACL_WRITE_EXTATTRIBUTES, + ACL_READ_SECURITY, + ACL_WRITE_SECURITY, + ACL_CHANGE_OWNER, + ACL_SYNCHRONIZE +#else /* !ARCHIVE_ACL_DARWIN */ + ACL_EXECUTE, + ACL_WRITE, + ACL_READ, +#if ARCHIVE_ACL_FREEBSD_NFS4 + ACL_READ_DATA, + ACL_LIST_DIRECTORY, + ACL_WRITE_DATA, + ACL_ADD_FILE, + ACL_APPEND_DATA, + ACL_ADD_SUBDIRECTORY, + ACL_READ_NAMED_ATTRS, + ACL_WRITE_NAMED_ATTRS, + ACL_DELETE_CHILD, + ACL_READ_ATTRIBUTES, + ACL_WRITE_ATTRIBUTES, + ACL_DELETE, + ACL_READ_ACL, + ACL_WRITE_ACL, + ACL_WRITE_OWNER, + ACL_SYNCHRONIZE +#endif /* ARCHIVE_ACL_FREEBSD_NFS4 */ +#endif /* !ARCHIVE_ACL_DARWIN */ +}; +#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_FREEBSD_NFS4 +static const acl_flag_t acl_flags[] = { +#if ARCHIVE_ACL_DARWIN + ACL_ENTRY_INHERITED, + ACL_ENTRY_FILE_INHERIT, + ACL_ENTRY_DIRECTORY_INHERIT, + ACL_ENTRY_LIMIT_INHERIT, + ACL_ENTRY_ONLY_INHERIT +#else /* ARCHIVE_ACL_FREEBSD_NFS4 */ + ACL_ENTRY_FILE_INHERIT, + ACL_ENTRY_DIRECTORY_INHERIT, + ACL_ENTRY_NO_PROPAGATE_INHERIT, + ACL_ENTRY_INHERIT_ONLY, + ACL_ENTRY_SUCCESSFUL_ACCESS, + ACL_ENTRY_FAILED_ACCESS, +#ifdef ACL_ENTRY_INHERITED + ACL_ENTRY_INHERITED +#endif +#endif /* ARCHIVE_ACL_FREEBSD_NFS4 */ +}; +#endif /* ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_FREEBSD_NFS4 */ + +/* + * Compare two ACL entries on FreeBSD or on Mac OS X + */ +static int +compare_acl_entry(acl_entry_t ae_a, acl_entry_t ae_b, int is_nfs4) +{ + acl_tag_t tag_a, tag_b; + acl_permset_t permset_a, permset_b; + int perm_a, perm_b, perm_start, perm_end; + void *qual_a, *qual_b; +#if ARCHIVE_ACL_FREEBSD_NFS4 + acl_entry_type_t type_a, type_b; +#endif +#if ARCHIVE_ACL_FREEBSD_NFS4 || ARCHIVE_ACL_DARWIN + acl_flagset_t flagset_a, flagset_b; + int flag_a, flag_b; +#endif + int i, r; + + + /* Compare ACL tag */ + r = acl_get_tag_type(ae_a, &tag_a); + failure("acl_get_tag_type() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + return (-1); + r = acl_get_tag_type(ae_b, &tag_b); + failure("acl_get_tag_type() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + return (-1); + if (tag_a != tag_b) + return (0); + + /* Compare ACL qualifier */ +#if ARCHIVE_ACL_DARWIN + if (tag_a == ACL_EXTENDED_ALLOW || tag_b == ACL_EXTENDED_DENY) +#else + if (tag_a == ACL_USER || tag_a == ACL_GROUP) +#endif + { + qual_a = acl_get_qualifier(ae_a); + failure("acl_get_qualifier() error: %s", strerror(errno)); + if (assert(qual_a != NULL) == 0) + return (-1); + qual_b = acl_get_qualifier(ae_b); + failure("acl_get_qualifier() error: %s", strerror(errno)); + if (assert(qual_b != NULL) == 0) { + acl_free(qual_a); + return (-1); + } +#if ARCHIVE_ACL_DARWIN + if (memcmp(((guid_t *)qual_a)->g_guid, + ((guid_t *)qual_b)->g_guid, KAUTH_GUID_SIZE) != 0) +#else + if ((tag_a == ACL_USER && + (*(uid_t *)qual_a != *(uid_t *)qual_b)) || + (tag_a == ACL_GROUP && + (*(gid_t *)qual_a != *(gid_t *)qual_b))) +#endif + { + acl_free(qual_a); + acl_free(qual_b); + return (0); + } + acl_free(qual_a); + acl_free(qual_b); + } + +#if ARCHIVE_ACL_FREEBSD_NFS4 + if (is_nfs4) { + /* Compare NFS4 ACL type */ + r = acl_get_entry_type_np(ae_a, &type_a); + failure("acl_get_entry_type_np() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + return (-1); + r = acl_get_entry_type_np(ae_b, &type_b); + failure("acl_get_entry_type_np() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + return (-1); + if (type_a != type_b) + return (0); + } +#endif + + /* Compare ACL perms */ + r = acl_get_permset(ae_a, &permset_a); + failure("acl_get_permset() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + return (-1); + r = acl_get_permset(ae_b, &permset_b); + failure("acl_get_permset() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + return (-1); + + perm_start = 0; + perm_end = (int)(sizeof(acl_perms) / sizeof(acl_perms[0])); +#if ARCHIVE_ACL_FREEBSD_NFS4 + if (is_nfs4) + perm_start = 3; + else + perm_end = 3; +#endif + /* Cycle through all perms and compare their value */ + for (i = perm_start; i < perm_end; i++) { +#if ARCHIVE_ACL_LIBACL + perm_a = acl_get_perm(permset_a, acl_perms[i]); + perm_b = acl_get_perm(permset_b, acl_perms[i]); +#else + perm_a = acl_get_perm_np(permset_a, acl_perms[i]); + perm_b = acl_get_perm_np(permset_b, acl_perms[i]); +#endif + if (perm_a == -1 || perm_b == -1) + return (-1); + if (perm_a != perm_b) + return (0); + } + +#if ARCHIVE_ACL_FREEBSD_NFS4 || ARCHIVE_ACL_DARWIN + if (is_nfs4) { + r = acl_get_flagset_np(ae_a, &flagset_a); + failure("acl_get_flagset_np() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + return (-1); + r = acl_get_flagset_np(ae_b, &flagset_b); + failure("acl_get_flagset_np() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + return (-1); + /* Cycle through all flags and compare their status */ + for (i = 0; i < (int)(sizeof(acl_flags) / sizeof(acl_flags[0])); + i++) { + flag_a = acl_get_flag_np(flagset_a, acl_flags[i]); + flag_b = acl_get_flag_np(flagset_b, acl_flags[i]); + if (flag_a == -1 || flag_b == -1) + return (-1); + if (flag_a != flag_b) + return (0); + } + } +#else /* ARCHIVE_ACL_FREEBSD_NFS4 || ARCHIVE_ACL_DARWIN */ + (void)is_nfs4; /* UNUSED */ +#endif + return (1); +} +#endif /* ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBACL */ + +#if ARCHIVE_ACL_SUPPORT +/* + * Clear default ACLs or inheritance flags + */ +static void +clear_inheritance_flags(const char *path, int type) +{ + switch (type) { + case ARCHIVE_TEST_ACL_TYPE_POSIX1E: +#if ARCHIVE_ACL_POSIX1E +#if !ARCHIVE_ACL_SUNOS + acl_delete_def_file(path); +#else + /* Solaris */ + setTestAcl(path); +#endif +#endif /* ARCHIVE_ACL_POSIX1E */ + break; + case ARCHIVE_TEST_ACL_TYPE_NFS4: +#if ARCHIVE_ACL_NFS4 + setTestAcl(path); +#endif + break; + default: + (void)path; /* UNUSED */ + break; + } +} + +static int +compare_acls(const char *path_a, const char *path_b) +{ + int ret = 1; + int is_nfs4 = 0; +#if ARCHIVE_ACL_SUNOS + void *acl_a, *acl_b; + int aclcnt_a, aclcnt_b; + aclent_t *aclent_a, *aclent_b; + ace_t *ace_a, *ace_b; + int e; +#elif ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL + acl_t acl_a, acl_b; + acl_entry_t aclent_a, aclent_b; + int a, b, r; +#endif +#if ARCHIVE_ACL_LIBRICHACL + struct richacl *richacl_a, *richacl_b; + + richacl_a = NULL; + richacl_b = NULL; +#endif + +#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL || \ + ARCHIVE_ACL_SUNOS + acl_a = NULL; + acl_b = NULL; +#endif +#if ARCHIVE_ACL_SUNOS + acl_a = sunacl_get(GETACL, &aclcnt_a, 0, path_a); + if (acl_a == NULL) { +#if ARCHIVE_ACL_SUNOS_NFS4 + is_nfs4 = 1; + acl_a = sunacl_get(ACE_GETACL, &aclcnt_a, 0, path_a); +#endif + failure("acl_get() error: %s", strerror(errno)); + if (assert(acl_a != NULL) == 0) + return (-1); +#if ARCHIVE_ACL_SUNOS_NFS4 + acl_b = sunacl_get(ACE_GETACL, &aclcnt_b, 0, path_b); +#endif + } else + acl_b = sunacl_get(GETACL, &aclcnt_b, 0, path_b); + if (acl_b == NULL && (errno == ENOSYS || errno == ENOTSUP)) { + free(acl_a); + return (0); + } + failure("acl_get() error: %s", strerror(errno)); + if (assert(acl_b != NULL) == 0) { + free(acl_a); + return (-1); + } + + if (aclcnt_a != aclcnt_b) { + ret = 0; + goto exit_free; + } + + for (e = 0; e < aclcnt_a; e++) { + if (!is_nfs4) { + aclent_a = &((aclent_t *)acl_a)[e]; + aclent_b = &((aclent_t *)acl_b)[e]; + if (aclent_a->a_type != aclent_b->a_type || + aclent_a->a_id != aclent_b->a_id || + aclent_a->a_perm != aclent_b->a_perm) { + ret = 0; + goto exit_free; + } + } +#if ARCHIVE_ACL_SUNOS_NFS4 + else { + ace_a = &((ace_t *)acl_a)[e]; + ace_b = &((ace_t *)acl_b)[e]; + if (ace_a->a_who != ace_b->a_who || + ace_a->a_access_mask != ace_b->a_access_mask || + ace_a->a_flags != ace_b->a_flags || + ace_a->a_type != ace_b->a_type) { + ret = 0; + goto exit_free; + } + } +#endif + } +#else /* !ARCHIVE_ACL_SUNOS */ +#if ARCHIVE_ACL_LIBRICHACL + richacl_a = richacl_get_file(path_a); +#if !ARCHIVE_ACL_LIBACL + if (richacl_a == NULL && + (errno == ENODATA || errno == ENOTSUP || errno == ENOSYS)) + return (0); + failure("richacl_get_file() error: %s (%s)", path_a, strerror(errno)); + if (assert(richacl_a != NULL) == 0) + return (-1); +#endif + if (richacl_a != NULL) { + richacl_b = richacl_get_file(path_b); + if (richacl_b == NULL && + (errno == ENODATA || errno == ENOTSUP || errno == ENOSYS)) { + richacl_free(richacl_a); + return (0); + } + failure("richacl_get_file() error: %s (%s)", path_b, + strerror(errno)); + if (assert(richacl_b != NULL) == 0) { + richacl_free(richacl_a); + return (-1); + } + if (richacl_compare(richacl_a, richacl_b) == 0) + ret = 0; + richacl_free(richacl_a); + richacl_free(richacl_b); + return (ret); + } +#endif /* ARCHIVE_ACL_LIBRICHACL */ +#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL +#if ARCHIVE_ACL_DARWIN + is_nfs4 = 1; + acl_a = acl_get_file(path_a, ACL_TYPE_EXTENDED); +#elif ARCHIVE_ACL_FREEBSD_NFS4 + acl_a = acl_get_file(path_a, ACL_TYPE_NFS4); + if (acl_a != NULL) + is_nfs4 = 1; +#endif + if (acl_a == NULL) + acl_a = acl_get_file(path_a, ACL_TYPE_ACCESS); + failure("acl_get_file() error: %s (%s)", path_a, strerror(errno)); + if (assert(acl_a != NULL) == 0) + return (-1); +#if ARCHIVE_ACL_DARWIN + acl_b = acl_get_file(path_b, ACL_TYPE_EXTENDED); +#elif ARCHIVE_ACL_FREEBSD_NFS4 + acl_b = acl_get_file(path_b, ACL_TYPE_NFS4); +#endif +#if !ARCHIVE_ACL_DARWIN + if (acl_b == NULL) { +#if ARCHIVE_ACL_FREEBSD_NFS4 + if (is_nfs4) { + acl_free(acl_a); + return (0); + } +#endif + acl_b = acl_get_file(path_b, ACL_TYPE_ACCESS); + } + failure("acl_get_file() error: %s (%s)", path_b, strerror(errno)); + if (assert(acl_b != NULL) == 0) { + acl_free(acl_a); + return (-1); + } +#endif + a = acl_get_entry(acl_a, ACL_FIRST_ENTRY, &aclent_a); + if (a == -1) { + ret = 0; + goto exit_free; + } + b = acl_get_entry(acl_b, ACL_FIRST_ENTRY, &aclent_b); + if (b == -1) { + ret = 0; + goto exit_free; + } +#if ARCHIVE_ACL_DARWIN + while (a == 0 && b == 0) +#else /* FreeBSD, Linux */ + while (a == 1 && b == 1) +#endif + { + r = compare_acl_entry(aclent_a, aclent_b, is_nfs4); + if (r != 1) { + ret = r; + goto exit_free; + } + a = acl_get_entry(acl_a, ACL_NEXT_ENTRY, &aclent_a); + b = acl_get_entry(acl_b, ACL_NEXT_ENTRY, &aclent_b); + } + /* Entry count must match */ + if (a != b) + ret = 0; +#endif /* ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL */ +#endif /* !ARCHIVE_ACL_SUNOS */ +exit_free: +#if ARCHIVE_ACL_SUNOS + free(acl_a); + free(acl_b); +#else + acl_free(acl_a); + acl_free(acl_b); +#endif + return (ret); +} +#endif /* ARCHIVE_ACL_SUPPORT */ + +DEFINE_TEST(test_option_acls) +{ +#if !ARCHIVE_ACL_SUPPORT + skipping("ACLs are not supported on this platform"); +#else /* ARCHIVE_ACL_SUPPORT */ + int acltype, r; + + assertMakeFile("f", 0644, "a"); + acltype = setTestAcl("f"); + if (acltype == 0) { + skipping("Can't write ACLs on the filesystem"); + return; + } + + /* Archive it with acls */ + r = systemf("%s -c --no-mac-metadata --acls -f acls.tar f >acls.out 2>acls.err", testprog); + assertEqualInt(r, 0); + + /* Archive it without acls */ + r = systemf("%s -c --no-mac-metadata --no-acls -f noacls.tar f >noacls.out 2>noacls.err", testprog); + assertEqualInt(r, 0); + + /* Extract acls with acls */ + assertMakeDir("acls_acls", 0755); + clear_inheritance_flags("acls_acls", acltype); + r = systemf("%s -x -C acls_acls --no-same-permissions --acls -f acls.tar >acls_acls.out 2>acls_acls.err", testprog); + assertEqualInt(r, 0); + r = compare_acls("f", "acls_acls/f"); + assertEqualInt(r, 1); + + /* Extract acls without acls */ + assertMakeDir("acls_noacls", 0755); + clear_inheritance_flags("acls_noacls", acltype); + r = systemf("%s -x -C acls_noacls -p --no-acls -f acls.tar >acls_noacls.out 2>acls_noacls.err", testprog); + assertEqualInt(r, 0); + r = compare_acls("f", "acls_noacls/f"); + assertEqualInt(r, 0); + + /* Extract noacls with acls flag */ + assertMakeDir("noacls_acls", 0755); + clear_inheritance_flags("noacls_acls", acltype); + r = systemf("%s -x -C noacls_acls --no-same-permissions --acls -f noacls.tar >noacls_acls.out 2>noacls_acls.err", testprog); + assertEqualInt(r, 0); + r = compare_acls("f", "noacls_acls/f"); + assertEqualInt(r, 0); + + /* Extract noacls with noacls */ + assertMakeDir("noacls_noacls", 0755); + clear_inheritance_flags("noacls_noacls", acltype); + r = systemf("%s -x -C noacls_noacls -p --no-acls -f noacls.tar >noacls_noacls.out 2>noacls_noacls.err", testprog); + assertEqualInt(r, 0); + r = compare_acls("f", "noacls_noacls/f"); + assertEqualInt(r, 0); +#endif /* ARCHIVE_ACL_SUPPORT */ +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_b.c b/dependencies/libarchive-3.4.2/tar/test/test_option_b.c new file mode 100644 index 0000000..0eee80d --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_b.c @@ -0,0 +1,83 @@ +/*- + * Copyright (c) 2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +#define USTAR_OPT " --format=ustar" + +DEFINE_TEST(test_option_b) +{ + char *testprog_ustar; + + assertMakeFile("file1", 0644, "file1"); + if (systemf("cat file1 > test_cat.out 2> test_cat.err") != 0) { + skipping("This test requires a `cat` program"); + return; + } + testprog_ustar = malloc(strlen(testprog) + sizeof(USTAR_OPT) + 1); + strcpy(testprog_ustar, testprog); + strcat(testprog_ustar, USTAR_OPT); + + /* + * Bsdtar does not pad if the output is going directly to a disk file. + */ + assertEqualInt(0, systemf("%s -cf archive1.tar file1 >test1.out 2>test1.err", testprog_ustar)); + failure("bsdtar does not pad archives written directly to regular files"); + assertFileSize("archive1.tar", 2048); + assertEmptyFile("test1.out"); + assertEmptyFile("test1.err"); + + /* + * Bsdtar does pad to the block size if the output is going to a socket. + */ + /* Default is -b 20 */ + assertEqualInt(0, systemf("%s -cf - file1 2>test2.err | cat >archive2.tar ", testprog_ustar)); + failure("bsdtar does pad archives written to pipes"); + assertFileSize("archive2.tar", 10240); + assertEmptyFile("test2.err"); + + assertEqualInt(0, systemf("%s -cf - -b 20 file1 2>test3.err | cat >archive3.tar ", testprog_ustar)); + assertFileSize("archive3.tar", 10240); + assertEmptyFile("test3.err"); + + assertEqualInt(0, systemf("%s -cf - -b 10 file1 2>test4.err | cat >archive4.tar ", testprog_ustar)); + assertFileSize("archive4.tar", 5120); + assertEmptyFile("test4.err"); + + assertEqualInt(0, systemf("%s -cf - -b 1 file1 2>test5.err | cat >archive5.tar ", testprog_ustar)); + assertFileSize("archive5.tar", 2048); + assertEmptyFile("test5.err"); + + assertEqualInt(0, systemf("%s -cf - -b 8192 file1 2>test6.err | cat >archive6.tar ", testprog_ustar)); + assertFileSize("archive6.tar", 4194304); + assertEmptyFile("test6.err"); + + /* + * Note: It's not possible to verify at this level that blocks + * are getting written with the + */ + + free(testprog_ustar); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_b64encode.c b/dependencies/libarchive-3.4.2/tar/test/test_option_b64encode.c new file mode 100644 index 0000000..1d04204 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_b64encode.c @@ -0,0 +1,56 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_b64encode) +{ + char *p; + size_t s; + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Archive it with compress compression and uuencode. */ + assertEqualInt(0, + systemf("%s -cf - -Z --b64encode f >archive.out 2>archive.err", + testprog)); + /* Check that the archive file has an uuencode signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "begin-base64 644", 16); + free(p); + + /* Archive it with uuencode only. */ + assertEqualInt(0, + systemf("%s -cf - --b64encode f >archive.out 2>archive.err", + testprog)); + /* Check that the archive file has an uuencode signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "begin-base64 644", 16); + free(p); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_exclude.c b/dependencies/libarchive-3.4.2/tar/test/test_option_exclude.c new file mode 100644 index 0000000..1345f70 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_exclude.c @@ -0,0 +1,142 @@ +/*- + * Copyright (c) 2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_exclude) +{ + int r; + + assertMakeFile("file1", 0644, "file1"); + assertMakeFile("file2", 0644, "file2"); + assertEqualInt(0, systemf("%s -cf archive.tar file1 file2", testprog)); + + /* + * Now, try extracting from the test archive with various --exclude options. + */ + + /* Test 1: Without --exclude */ + assertMakeDir("test1", 0755); + assertChdir("test1"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar >test.out 2>test.err", testprog)); + assertFileContents("file1", 5, "file1"); + assertFileContents("file2", 5, "file2"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 2: Selecting just one file */ + assertMakeDir("test2", 0755); + assertChdir("test2"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar file1 >test.out 2>test.err", testprog)); + assertFileContents("file1", 5, "file1"); + assertFileNotExists("file2"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 3: Use --exclude to skip one file */ + assertMakeDir("test3", 0755); + assertChdir("test3"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar --exclude file1 >test.out 2>test.err", testprog)); + assertFileNotExists("file1"); + assertFileContents("file2", 5, "file2"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 4: Selecting one valid and one invalid file */ + assertMakeDir("test4", 0755); + assertChdir("test4"); + r = systemf("%s -xf ../archive.tar file1 file3 >test.out 2>test.err", testprog); + assert(r != 0); + assertFileContents("file1", 5, "file1"); + assertFileNotExists("file2"); + assertFileNotExists("file3"); + assertEmptyFile("test.out"); + assertNonEmptyFile("test.err"); + assertChdir(".."); + + /* Test 5: Selecting one valid file twice */ + assertMakeDir("test5", 0755); + assertChdir("test5"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar file1 file1 >test.out 2>test.err", testprog)); + assertFileContents("file1", 5, "file1"); + assertFileNotExists("file2"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 6: Include and exclude the same file */ + assertMakeDir("test6", 0755); + assertChdir("test6"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar --exclude file1 file1 >test.out 2>test.err", testprog)); + assertFileNotExists("file1"); + assertFileNotExists("file2"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 7: Exclude a non-existent file */ + assertMakeDir("test7", 0755); + assertChdir("test7"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar --exclude file3 file1 >test.out 2>test.err", testprog)); + assertFileContents("file1", 5, "file1"); + assertFileNotExists("file2"); + assertFileNotExists("file3"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 8: Include a non-existent file */ + assertMakeDir("test8", 0755); + assertChdir("test8"); + r = systemf("%s -xf ../archive.tar file3 >test.out 2>test.err", testprog); + assert(r != 0); + assertFileNotExists("file1"); + assertFileNotExists("file2"); + assertFileNotExists("file3"); + assertEmptyFile("test.out"); + assertNonEmptyFile("test.err"); + assertChdir(".."); + + /* Test 9: Include a non-existent file plus an exclusion */ + assertMakeDir("test9", 0755); + assertChdir("test9"); + r = systemf("%s -xf ../archive.tar --exclude file1 file3 >test.out 2>test.err", testprog); + assert(r != 0); + assertFileNotExists("file1"); + assertFileNotExists("file2"); + assertFileNotExists("file3"); + assertEmptyFile("test.out"); + assertNonEmptyFile("test.err"); + assertChdir(".."); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_exclude_vcs.c b/dependencies/libarchive-3.4.2/tar/test/test_option_exclude_vcs.c new file mode 100644 index 0000000..2021511 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_exclude_vcs.c @@ -0,0 +1,230 @@ +/*- + * Copyright (c) 2019 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_exclude_vcs) +{ + assertMakeDir("in", 0755); + assertChdir("in"); + assertMakeFile("file", 0644, ""); + assertMakeDir("dir", 0755); + assertMakeDir("CVS", 0755); + assertMakeFile("CVS/fileattr", 0644, ""); + assertMakeFile(".cvsignore", 0644, ""); + assertMakeDir("RCS", 0755); + assertMakeFile("RCS/somefile", 0655, ""); + assertMakeDir("SCCS", 0755); + assertMakeFile("SCCS/somefile", 0655, ""); + assertMakeDir(".svn", 0755); + assertMakeFile(".svn/format", 0655, ""); + assertMakeDir(".git", 0755); + assertMakeFile(".git/config", 0655, ""); + assertMakeFile(".gitignore", 0644, ""); + assertMakeFile(".gitattributes", 0644, ""); + assertMakeFile(".gitmodules", 0644, ""); + assertMakeDir(".arch-ids", 0755); + assertMakeFile(".arch-ids/somefile", 0644, ""); + assertMakeDir("{arch}", 0755); + assertMakeFile("{arch}/somefile", 0644, ""); + assertMakeFile("=RELEASE-ID", 0644, ""); + assertMakeFile("=meta-update", 0644, ""); + assertMakeFile("=update", 0644, ""); + assertMakeDir(".bzr", 0755); + assertMakeDir(".bzr/checkout", 0755); + assertMakeFile(".bzrignore", 0644, ""); + assertMakeFile(".bzrtags", 0644, ""); + assertMakeDir(".hg", 0755); + assertMakeFile(".hg/dirstate", 0644, ""); + assertMakeFile(".hgignore", 0644, ""); + assertMakeFile(".hgtags", 0644, ""); + assertMakeDir("_darcs", 0755); + assertMakeFile("_darcs/format", 0644, ""); + assertChdir(".."); + + assertEqualInt(0, systemf("%s -c -C in -f included.tar .", testprog)); + assertEqualInt(0, + systemf("%s -c --exclude-vcs -C in -f excluded.tar .", testprog)); + + /* No flags, archive with vcs files */ + assertMakeDir("vcs-noexclude", 0755); + assertEqualInt(0, systemf("%s -x -C vcs-noexclude -f included.tar", + testprog)); + assertChdir("vcs-noexclude"); + assertFileExists("file"); + assertIsDir("dir", 0755); + assertIsDir("CVS", 0755); + assertFileExists("CVS/fileattr"); + assertFileExists(".cvsignore"); + assertIsDir("RCS", 0755); + assertFileExists("RCS/somefile"); + assertIsDir("SCCS", 0755); + assertFileExists("SCCS/somefile"); + assertIsDir(".svn", 0755); + assertFileExists(".svn/format"); + assertIsDir(".git", 0755); + assertFileExists(".git/config"); + assertFileExists(".gitignore"); + assertFileExists(".gitattributes"); + assertFileExists(".gitmodules"); + assertIsDir(".arch-ids", 0755); + assertFileExists(".arch-ids/somefile"); + assertIsDir("{arch}", 0755); + assertFileExists("{arch}/somefile"); + assertFileExists("=RELEASE-ID"); + assertFileExists("=meta-update"); + assertFileExists("=update"); + assertIsDir(".bzr", 0755); + assertIsDir(".bzr/checkout", 0755); + assertFileExists(".bzrignore"); + assertFileExists(".bzrtags"); + assertIsDir(".hg", 0755); + assertFileExists(".hg/dirstate"); + assertFileExists(".hgignore"); + assertFileExists(".hgtags"); + assertIsDir("_darcs", 0755); + assertFileExists("_darcs/format"); + assertChdir(".."); + + /* --exclude-vcs, archive with vcs files */ + assertMakeDir("vcs-exclude", 0755); + assertEqualInt(0, + systemf("%s -x --exclude-vcs -C vcs-exclude -f included.tar", testprog)); + assertChdir("vcs-exclude"); + assertFileExists("file"); + assertIsDir("dir", 0755); + assertFileNotExists("CVS"); + assertFileNotExists("CVS/fileattr"); + assertFileNotExists(".cvsignore"); + assertFileNotExists("RCS"); + assertFileNotExists("RCS/somefile"); + assertFileNotExists("SCCS"); + assertFileNotExists("SCCS/somefile"); + assertFileNotExists(".svn"); + assertFileNotExists(".svn/format"); + assertFileNotExists(".git"); + assertFileNotExists(".git/config"); + assertFileNotExists(".gitignore"); + assertFileNotExists(".gitattributes"); + assertFileNotExists(".gitmodules"); + assertFileNotExists(".arch-ids"); + assertFileNotExists(".arch-ids/somefile"); + assertFileNotExists("{arch}"); + assertFileNotExists("{arch}/somefile"); + assertFileNotExists("=RELEASE-ID"); + assertFileNotExists("=meta-update"); + assertFileNotExists("=update"); + assertFileNotExists(".bzr"); + assertFileNotExists(".bzr/checkout"); + assertFileNotExists(".bzrignore"); + assertFileNotExists(".bzrtags"); + assertFileNotExists(".hg"); + assertFileNotExists(".hg/dirstate"); + assertFileNotExists(".hgignore"); + assertFileNotExists(".hgtags"); + assertFileNotExists("_darcs"); + assertFileNotExists("_darcs/format"); + assertChdir(".."); + + /* --exclude-vcs, archive without vcs files */ + assertMakeDir("novcs-exclude", 0755); + assertEqualInt(0, + systemf("%s -x --exclude-vcs -C novcs-exclude -f excluded.tar", + testprog)); + assertChdir("novcs-exclude"); + assertFileExists("file"); + assertIsDir("dir", 0755); + assertFileNotExists("CVS"); + assertFileNotExists("CVS/fileattr"); + assertFileNotExists(".cvsignore"); + assertFileNotExists("RCS"); + assertFileNotExists("RCS/somefile"); + assertFileNotExists("SCCS"); + assertFileNotExists("SCCS/somefile"); + assertFileNotExists(".svn"); + assertFileNotExists(".svn/format"); + assertFileNotExists(".git"); + assertFileNotExists(".git/config"); + assertFileNotExists(".gitignore"); + assertFileNotExists(".gitattributes"); + assertFileNotExists(".gitmodules"); + assertFileNotExists(".arch-ids"); + assertFileNotExists(".arch-ids/somefile"); + assertFileNotExists("{arch}"); + assertFileNotExists("{arch}/somefile"); + assertFileNotExists("=RELEASE-ID"); + assertFileNotExists("=meta-update"); + assertFileNotExists("=update"); + assertFileNotExists(".bzr"); + assertFileNotExists(".bzr/checkout"); + assertFileNotExists(".bzrignore"); + assertFileNotExists(".bzrtags"); + assertFileNotExists(".hg"); + assertFileNotExists(".hg/dirstate"); + assertFileNotExists(".hgignore"); + assertFileNotExists(".hgtags"); + assertFileNotExists("_darcs"); + assertFileNotExists("_darcs/format"); + assertChdir(".."); + + /* No flags, archive without vcs files */ + assertMakeDir("novcs-noexclude", 0755); + assertEqualInt(0, + systemf("%s -x -C novcs-noexclude -f excluded.tar", testprog)); + assertChdir("novcs-noexclude"); + assertFileExists("file"); + assertIsDir("dir", 0755); + assertFileNotExists("CVS"); + assertFileNotExists("CVS/fileattr"); + assertFileNotExists(".cvsignore"); + assertFileNotExists("RCS"); + assertFileNotExists("RCS/somefile"); + assertFileNotExists("SCCS"); + assertFileNotExists("SCCS/somefile"); + assertFileNotExists(".svn"); + assertFileNotExists(".svn/format"); + assertFileNotExists(".git"); + assertFileNotExists(".git/config"); + assertFileNotExists(".gitignore"); + assertFileNotExists(".gitattributes"); + assertFileNotExists(".gitmodules"); + assertFileNotExists(".arch-ids"); + assertFileNotExists(".arch-ids/somefile"); + assertFileNotExists("{arch}"); + assertFileNotExists("{arch}/somefile"); + assertFileNotExists("=RELEASE-ID"); + assertFileNotExists("=meta-update"); + assertFileNotExists("=update"); + assertFileNotExists(".bzr"); + assertFileNotExists(".bzr/checkout"); + assertFileNotExists(".bzrignore"); + assertFileNotExists(".bzrtags"); + assertFileNotExists(".hg"); + assertFileNotExists(".hg/dirstate"); + assertFileNotExists(".hgignore"); + assertFileNotExists(".hgtags"); + assertFileNotExists("_darcs"); + assertFileNotExists("_darcs/format"); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_fflags.c b/dependencies/libarchive-3.4.2/tar/test/test_option_fflags.c new file mode 100644 index 0000000..f223feb --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_fflags.c @@ -0,0 +1,110 @@ +/*- + * Copyright (c) 2017 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__BORLANDC__) +#define chmod _chmod +#endif + +static void +clear_fflags(const char *pathname) +{ +#if defined(HAVE_STRUCT_STAT_ST_FLAGS) + chflags(pathname, 0); +#elif (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \ + (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)) + int fd; + + fd = open(pathname, O_RDONLY | O_NONBLOCK); + if (fd < 0) + return; + ioctl(fd, +#ifdef FS_IOC_GETFLAGS + FS_IOC_GETFLAGS, +#else + EXT2_IOC_GETFLAGS, +#endif + 0); +#else + (void)pathname; /* UNUSED */ +#endif + return; +} + +DEFINE_TEST(test_option_fflags) +{ + int r; + + if (!canNodump()) { + skipping("Can't test nodump flag on this filesystem"); + return; + } + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Set nodump flag on the file */ + assertSetNodump("f"); + + /* FreeBSD ZFS workaround: ZFS sets uarch on all touched files and dirs */ + chmod("f", 0644); + + /* Archive it with fflags */ + r = systemf("%s -c --fflags -f fflags.tar f >fflags.out 2>fflags.err", testprog); + assertEqualInt(r, 0); + + /* Archive it without fflags */ + r = systemf("%s -c --no-fflags -f nofflags.tar f >nofflags.out 2>nofflags.err", testprog); + assertEqualInt(r, 0); + + /* Extract fflags with fflags */ + assertMakeDir("fflags_fflags", 0755); + clear_fflags("fflags_fflags"); + r = systemf("%s -x -C fflags_fflags --no-same-permissions --fflags -f fflags.tar >fflags_fflags.out 2>fflags_fflags.err", testprog); + assertEqualInt(r, 0); + assertEqualFflags("f", "fflags_fflags/f"); + + /* Extract fflags without fflags */ + assertMakeDir("fflags_nofflags", 0755); + clear_fflags("fflags_nofflags"); + r = systemf("%s -x -C fflags_nofflags -p --no-fflags -f fflags.tar >fflags_nofflags.out 2>fflags_nofflags.err", testprog); + assertEqualInt(r, 0); + assertUnequalFflags("f", "fflags_nofflags/f"); + + /* Extract nofflags with fflags */ + assertMakeDir("nofflags_fflags", 0755); + clear_fflags("nofflags_fflags"); + r = systemf("%s -x -C nofflags_fflags --no-same-permissions --fflags -f nofflags.tar >nofflags_fflags.out 2>nofflags_fflags.err", testprog); + assertEqualInt(r, 0); + assertUnequalFflags("f", "nofflags_fflags/f"); + + /* Extract nofflags with nofflags */ + assertMakeDir("nofflags_nofflags", 0755); + clear_fflags("nofflags_nofflags"); + r = systemf("%s -x -C nofflags_nofflags -p --no-fflags -f nofflags.tar >nofflags_nofflags.out 2>nofflags_nofflags.err", testprog); + assertEqualInt(r, 0); + assertUnequalFflags("f", "nofflags_nofflags/f"); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_gid_gname.c b/dependencies/libarchive-3.4.2/tar/test/test_option_gid_gname.c new file mode 100644 index 0000000..4e5f51c --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_gid_gname.c @@ -0,0 +1,92 @@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_gid_gname) +{ + char *reference, *data; + size_t s; + + assertUmask(0); + assertMakeFile("file", 0644, "1234567890"); + + /* Create archive with no special options. */ + failure("Error invoking %s c", testprog); + assertEqualInt(0, + systemf("%s cf archive1 --format=ustar file >stdout1.txt 2>stderr1.txt", + testprog)); + assertEmptyFile("stdout1.txt"); + assertEmptyFile("stderr1.txt"); + reference = slurpfile(&s, "archive1"); + + /* Again with both --gid and --gname */ + failure("Error invoking %s c", testprog); + assertEqualInt(0, + systemf("%s cf archive2 --gid=17 --gname=foofoofoo --format=ustar file >stdout2.txt 2>stderr2.txt", + testprog)); + assertEmptyFile("stdout2.txt"); + assertEmptyFile("stderr2.txt"); + data = slurpfile(&s, "archive2"); + /* Should force gid and gname fields in ustar header. */ + assertEqualMem(data + 116, "000021 \0", 8); + assertEqualMem(data + 297, "foofoofoo\0", 10); + free(data); + + /* Again with just --gname */ + failure("Error invoking %s c", testprog); + assertEqualInt(0, + systemf("%s cf archive4 --gname=foofoofoo --format=ustar file >stdout4.txt 2>stderr4.txt", + testprog)); + assertEmptyFile("stdout4.txt"); + assertEmptyFile("stderr4.txt"); + data = slurpfile(&s, "archive4"); + /* Gid should be unchanged from original reference. */ + assertEqualMem(data + 116, reference + 116, 8); + assertEqualMem(data + 297, "foofoofoo\0", 10); + free(data); + free(reference); + + /* Again with --gid and force gname to empty. */ + failure("Error invoking %s c", testprog); + assertEqualInt(0, + systemf("%s cf archive3 --gid=17 --gname= --format=ustar file >stdout3.txt 2>stderr3.txt", + testprog)); + assertEmptyFile("stdout3.txt"); + assertEmptyFile("stderr3.txt"); + data = slurpfile(&s, "archive3"); + assertEqualMem(data + 116, "000021 \0", 8); + /* Gname field in ustar header should be empty. */ + assertEqualMem(data + 297, "\0", 1); + free(data); + + /* TODO: It would be nice to verify that --gid= by itself + * will look up the associated gname and use that, but + * that requires some system-specific code. */ + + /* TODO: It would be nice to verify that --gid= will + * leave the gname field blank if the specified gid + * isn't used on the local system. */ +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_grzip.c b/dependencies/libarchive-3.4.2/tar/test/test_option_grzip.c new file mode 100644 index 0000000..fbff252 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_grzip.c @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_grzip) +{ + char *p; + size_t s; + + if (!canGrzip()) { + skipping("grzip is not supported on this platform"); + return; + } + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Archive it with grzip compression. */ + assertEqualInt(0, + systemf("%s -cf - --grzip f >archive.out 2>archive.err", + testprog)); + p = slurpfile(&s, "archive.err"); + p[s] = '\0'; + free(p); + + /* Check that the archive file has an grzip signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "GRZipII\x00\x02\x04:)", 12); + free(p); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_j.c b/dependencies/libarchive-3.4.2/tar/test/test_option_j.c new file mode 100644 index 0000000..838234a --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_j.c @@ -0,0 +1,59 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_j) +{ + char *p; + int r; + size_t s; + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Archive it with bzip2 compression. */ + r = systemf("%s -jcf archive.out f 2>archive.err", testprog); + p = slurpfile(&s, "archive.err"); + p[s] = '\0'; + if (r != 0) { + if (!canBzip2()) { + skipping("bzip2 is not supported on this platform"); + goto done; + } + failure("-j option is broken"); + assertEqualInt(r, 0); + goto done; + } + free(p); + assertEmptyFile("archive.err"); + /* Check that the archive file has a bzip2 signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "BZh9", 4); +done: + free(p); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_k.c b/dependencies/libarchive-3.4.2/tar/test/test_option_k.c new file mode 100644 index 0000000..e57cc27 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_k.c @@ -0,0 +1,107 @@ +/*- + * Copyright (c) 2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_k) +{ + /* + * Create an archive with a couple of different versions of the + * same file. + */ + + assertMakeFile("foo", 0644, "foo1"); + + assertEqualInt(0, systemf("%s -cf archive.tar foo", testprog)); + + assertMakeFile("foo", 0644, "foo2"); + + assertEqualInt(0, systemf("%s -rf archive.tar foo", testprog)); + + assertMakeFile("bar", 0644, "bar1"); + + assertEqualInt(0, systemf("%s -rf archive.tar bar", testprog)); + + assertMakeFile("foo", 0644, "foo3"); + + assertEqualInt(0, systemf("%s -rf archive.tar foo", testprog)); + + assertMakeFile("bar", 0644, "bar2"); + + assertEqualInt(0, systemf("%s -rf archive.tar bar", testprog)); + + /* + * Now, try extracting from the test archive with various + * combinations of -k + */ + + /* Test 1: No option */ + assertMakeDir("test1", 0755); + assertChdir("test1"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar >test.out 2>test.err", testprog)); + assertFileContents("foo3", 4, "foo"); + assertFileContents("bar2", 4, "bar"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 2: With -k, we should just get the first versions. */ + assertMakeDir("test2", 0755); + assertChdir("test2"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar -k >test.out 2>test.err", testprog)); + assertFileContents("foo1", 4, "foo"); + assertFileContents("bar1", 4, "bar"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 3: Without -k, existing files should get overwritten */ + assertMakeDir("test3", 0755); + assertChdir("test3"); + assertMakeFile("bar", 0644, "bar0"); + assertMakeFile("foo", 0644, "foo0"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar >test.out 2>test.err", testprog)); + assertFileContents("foo3", 4, "foo"); + assertFileContents("bar2", 4, "bar"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 4: With -k, existing files should not get overwritten */ + assertMakeDir("test4", 0755); + assertChdir("test4"); + assertMakeFile("bar", 0644, "bar0"); + assertMakeFile("foo", 0644, "foo0"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar -k >test.out 2>test.err", testprog)); + assertFileContents("foo0", 4, "foo"); + assertFileContents("bar0", 4, "bar"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_keep_newer_files.c b/dependencies/libarchive-3.4.2/tar/test/test_option_keep_newer_files.c new file mode 100644 index 0000000..089898c --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_keep_newer_files.c @@ -0,0 +1,56 @@ +/*- + * Copyright (c) 2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_keep_newer_files) +{ + const char *reffile = "test_option_keep_newer_files.tar.Z"; + + /* Reference file has one entry "file" with a very old timestamp. */ + extract_reference_file(reffile); + + /* Test 1: Without --keep-newer-files */ + assertMakeDir("test1", 0755); + assertChdir("test1"); + assertMakeFile("file", 0644, "new"); + assertEqualInt(0, + systemf("%s -xf ../%s >test.out 2>test.err", testprog, reffile)); + assertFileContents("old\n", 4, "file"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 2: With --keep-newer-files */ + assertMakeDir("test2", 0755); + assertChdir("test2"); + assertMakeFile("file", 0644, "new"); + assertEqualInt(0, + systemf("%s -xf ../%s --keep-newer-files >test.out 2>test.err", testprog, reffile)); + assertFileContents("new", 3, "file"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_keep_newer_files.tar.Z.uu b/dependencies/libarchive-3.4.2/tar/test/test_option_keep_newer_files.tar.Z.uu new file mode 100644 index 0000000..74a0f1e --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_keep_newer_files.tar.Z.uu @@ -0,0 +1,7 @@ +begin 644 test_option_keep_newer_files.tar.Z +M'YV09M*P*0.@H,&#"!,J7,BPH<.'$!'"F&B#!@T0`";&N%$#!D:-'#UFG$BR +MY$48,F38F&$CY8P8)V/$F,$2``@8$7/JW,FS)X`Z<^B$D3.23IHV/AD:19I4 +M8//JWarchive.out 2>archive.err", + testprog)); + p = slurpfile(&s, "archive.err"); + p[s] = '\0'; + free(p); + /* Check that the archive file has an lzma signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "LRZI\x00", 5); + free(p); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_lz4.c b/dependencies/libarchive-3.4.2/tar/test/test_option_lz4.c new file mode 100644 index 0000000..70fdaac --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_lz4.c @@ -0,0 +1,85 @@ +/*- + * Copyright (c) 2014 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_lz4) +{ + char *p; + int r; + size_t s; + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Archive it with lz4 compression. */ + r = systemf("%s -cf - --lz4 f >archive.out 2>archive.err", + testprog); + p = slurpfile(&s, "archive.err"); + p[s] = '\0'; + if (r != 0) { + if (strstr(p, "Unsupported compression") != NULL) { + skipping("This version of bsdtar was compiled " + "without lz4 support"); + goto done; + } + /* POSIX permits different handling of the spawnp + * system call used to launch the subsidiary + * program: */ + /* Some systems fail immediately to spawn the new process. */ + if (strstr(p, "Can't launch") != NULL && !canLz4()) { + skipping("This version of bsdtar uses an external lz4 program " + "but no such program is available on this system."); + goto done; + } + /* Some systems successfully spawn the new process, + * but fail to exec a program within that process. + * This results in failure at the first attempt to + * write. */ + if (strstr(p, "Can't write") != NULL && !canLz4()) { + skipping("This version of bsdtar uses an external lz4 program " + "but no such program is available on this system."); + goto done; + } + /* On some systems the error won't be detected until closing + time, by a 127 exit error returned by waitpid. */ + if (strstr(p, "Error closing") != NULL && !canLz4()) { + skipping("This version of bsdcpio uses an external lz4 program " + "but no such program is available on this system."); + return; + } + failure("--lz4 option is broken: %s", p); + assertEqualInt(r, 0); + goto done; + } + free(p); + /* Check that the archive file has an lz4 signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "\x04\x22\x4d\x18", 4); + +done: + free(p); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_lzma.c b/dependencies/libarchive-3.4.2/tar/test/test_option_lzma.c new file mode 100644 index 0000000..a618ff8 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_lzma.c @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_lzma) +{ + char *p; + int r; + size_t s; + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Archive it with lzma compression. */ + r = systemf("%s -cf - --lzma f >archive.out 2>archive.err", + testprog); + p = slurpfile(&s, "archive.err"); + p[s] = '\0'; + if (r != 0) { + if (strstr(p, "Unsupported compression") != NULL) { + skipping("This version of bsdtar was compiled " + "without lzma support"); + return; + } + failure("--lzma option is broken"); + assertEqualInt(r, 0); + goto done; + } + free(p); + /* Check that the archive file has an lzma signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "\x5d\00\00", 3); +done: + free(p); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_lzop.c b/dependencies/libarchive-3.4.2/tar/test/test_option_lzop.c new file mode 100644 index 0000000..20ef06c --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_lzop.c @@ -0,0 +1,58 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_lzop) +{ + char *p; + int r; + size_t s; + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Archive it with lzop compression. */ + r = systemf("%s -cf - --lzop f >archive.out 2>archive.err", testprog); + p = slurpfile(&s, "archive.err"); + p[s] = '\0'; + if (r != 0) { + if (!canLzop()) { + skipping("lzop is not supported on this platform"); + goto done; + } + failure("--lzop option is broken"); + assertEqualInt(r, 0); + goto done; + } + free(p); + /* Check that the archive file has an lzma signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a", 9); +done: + free(p); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_n.c b/dependencies/libarchive-3.4.2/tar/test/test_option_n.c new file mode 100644 index 0000000..f36658e --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_n.c @@ -0,0 +1,142 @@ +/*- + * Copyright (c) 2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_SYS_WAIT_H +#include +#endif + +DEFINE_TEST(test_option_n) +{ + int status; + + assertMakeDir("d1", 0755); + assertMakeFile("d1/file1", 0644, "d1/file1"); + + /* Test 1: -c without -n */ + assertMakeDir("test1", 0755); + assertChdir("test1"); + assertEqualInt(0, + systemf("%s -cf archive.tar -C .. d1 >c.out 2>c.err", testprog)); + assertEmptyFile("c.out"); + assertEmptyFile("c.err"); + assertEqualInt(0, + systemf("%s -xf archive.tar >x.out 2>x.err", testprog)); + assertEmptyFile("x.out"); + assertEmptyFile("x.err"); + assertFileContents("d1/file1", 8, "d1/file1"); + assertChdir(".."); + + /* Test 2: -c with -n */ + assertMakeDir("test2", 0755); + assertChdir("test2"); + assertEqualInt(0, + systemf("%s -cnf archive.tar -C .. d1 >c.out 2>c.err", testprog)); + assertEmptyFile("c.out"); + assertEmptyFile("c.err"); + assertEqualInt(0, + systemf("%s -xf archive.tar >x.out 2>x.err", testprog)); + assertEmptyFile("x.out"); + assertEmptyFile("x.err"); + assertIsDir("d1", umasked(0755)); + assertFileNotExists("d1/file1"); + assertChdir(".."); + + /* + * Create a test archive with the following content: + * d1/ + * d1/file1 + * d1/file2 + * file3 + * d2/file4 + * + * Extracting uses the same code as listing and thus does not + * get tested separately. This also covers the + * archive_match_set_inclusion_recursion() + * API. + */ + assertMakeFile("d1/file2", 0644, "d1/file2"); + assertMakeFile("file3", 0644, "file3"); + assertMakeDir("d2", 0755); + assertMakeFile("d2/file4", 0644, "d2/file4"); + assertEqualInt(0, + systemf("%s -cnf partial-archive.tar d1 d1/file1 d1/file2 file3 " + "d2/file4 >c.out 2>c.err", testprog)); + + /* Test 3: -t without other options */ + assertEqualInt(0, + systemf("%s -tf partial-archive.tar >test3.out 2>test3.err", + testprog)); + assertEmptyFile("test3.err"); + assertTextFileContents("d1/\n" + "d1/file1\n" + "d1/file2\n" + "file3\n" + "d2/file4\n", + "test3.out"); + + /* Test 4: -t without -n and some entries selected */ + assertEqualInt(0, + systemf("%s -tf partial-archive.tar d1 file3 d2/file4 " + ">test4.out 2>test4.err", testprog)); + assertEmptyFile("test4.err"); + assertTextFileContents("d1/\n" + "d1/file1\n" + "d1/file2\n" + "file3\n" + "d2/file4\n", + "test4.out"); + + /* Test 5: -t with -n and some entries selected */ + assertEqualInt(0, + systemf("%s -tnf partial-archive.tar d1 file3 d2/file4 " + ">test5.out 2>test5.err", testprog)); + assertEmptyFile("test5.err"); + assertTextFileContents("d1/\n" + "file3\n" + "d2/file4\n", + "test5.out"); + + /* Test 6: -t without -n and non-existent directory selected */ + assertEqualInt(0, + systemf("%s -tf partial-archive.tar d2 >test6.out 2>test6.err", + testprog)); + assertEmptyFile("test6.err"); + assertTextFileContents("d2/file4\n", + "test6.out"); + + /* Test 7: -t with -n and non-existent directory selected */ + status = systemf("%s -tnf partial-archive.tar d2 " + ">test7.out 2>test7.err", testprog); + assert(status); + assert(status != -1); +#if !defined(_WIN32) || defined(__CYGWIN__) + assert(WIFEXITED(status)); + assertEqualInt(1, WEXITSTATUS(status)); +#endif + assertNonEmptyFile("test7.err"); + assertEmptyFile("test7.out"); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_newer_than.c b/dependencies/libarchive-3.4.2/tar/test/test_option_newer_than.c new file mode 100644 index 0000000..2a5fe04 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_newer_than.c @@ -0,0 +1,78 @@ +/*- + * Copyright (c) 2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_newer_than) +{ + struct stat st; + + /* + * Basic test of --newer-than. + * First, create three files with different mtimes. + * Create test1.tar with --newer-than, test2.tar without. + */ + assertMakeDir("test1in", 0755); + assertChdir("test1in"); + assertMakeDir("a", 0755); + assertMakeDir("a/b", 0755); + assertMakeFile("old.txt", 0644, "old.txt"); + assertEqualInt(0, stat("old.txt", &st)); + sleepUntilAfter(st.st_mtime); + assertMakeFile("middle.txt", 0644, "middle.txt"); + assertEqualInt(0, stat("middle.txt", &st)); + sleepUntilAfter(st.st_mtime); + assertMakeFile("new.txt", 0644, "new"); + assertMakeFile("a/b/new.txt", 0644, "new file in old directory"); + + /* Test --newer-than on create */ + assertEqualInt(0, + systemf("%s --format pax -cf ../test1.tar " + "--newer-than middle.txt *.txt a", testprog)); + assertEqualInt(0, + systemf("%s --format pax -cf ../test2.tar *.txt a", testprog)); + assertChdir(".."); + + /* Extract test1.tar to a clean dir and verify what got archived. */ + assertMakeDir("test1out", 0755); + assertChdir("test1out"); + assertEqualInt(0, systemf("%s xf ../test1.tar", testprog)); + assertFileExists("new.txt"); + assertFileExists("a/b/new.txt"); + assertFileNotExists("middle.txt"); + assertFileNotExists("old.txt"); + assertChdir(".."); + + /* Extract test2.tar to a clean dir with --newer-than and verify. */ + assertMakeDir("test2out", 0755); + assertChdir("test2out"); + assertEqualInt(0, systemf("%s xf ../test2.tar --newer-than ../test1in/middle.txt", testprog)); + assertFileExists("new.txt"); + assertFileExists("a/b/new.txt"); + assertFileNotExists("middle.txt"); + assertFileNotExists("old.txt"); + assertChdir(".."); + +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_nodump.c b/dependencies/libarchive-3.4.2/tar/test/test_option_nodump.c new file mode 100644 index 0000000..815b08e --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_nodump.c @@ -0,0 +1,68 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_nodump) +{ + + if (!canNodump()) { + skipping("Can't test nodump on this filesystem"); + return; + } + + assertMakeFile("file1", 0644, "file1"); + assertMakeFile("file2", 0644, "file2"); + assertMakeFile("file3", 0644, "file3"); + assertSetNodump("file2"); + + /* Test 1: Without --nodump */ + assertEqualInt(0, systemf("%s -cf test1.tar file1 file2 file3", + testprog)); + assertMakeDir("test1", 0755); + assertChdir("test1"); + assertEqualInt(0, + systemf("%s -xf ../test1.tar >test.out 2>test.err", testprog)); + assertFileContents("file1", 5, "file1"); + assertFileContents("file2", 5, "file2"); + assertFileContents("file3", 5, "file3"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 2: With --nodump */ + assertEqualInt(0, systemf("%s -cf test2.tar --nodump file1 file2 file3", + testprog)); + assertMakeDir("test2", 0755); + assertChdir("test2"); + assertEqualInt(0, + systemf("%s -xf ../test2.tar >test.out 2>test.err", testprog)); + assertFileContents("file1", 5, "file1"); + assertFileNotExists("file2"); + assertFileContents("file3", 5, "file3"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_older_than.c b/dependencies/libarchive-3.4.2/tar/test/test_option_older_than.c new file mode 100644 index 0000000..4bdd2ed --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_older_than.c @@ -0,0 +1,85 @@ +/*- + * Copyright (c) 2010 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_older_than) +{ + struct stat st; + + /* + * Basic test of --older-than. + * First, create three files with different mtimes. + * Create test1.tar with --older-than, test2.tar without. + */ + assertMakeDir("test1in", 0755); + assertChdir("test1in"); + assertMakeDir("a", 0755); + assertMakeDir("a/b", 0755); + assertMakeFile("old.txt", 0644, "old.txt"); + assertMakeFile("a/b/old.txt", 0644, "old file in old directory"); + assertEqualInt(0, stat("old.txt", &st)); + sleepUntilAfter(st.st_mtime); + assertMakeFile("middle.txt", 0644, "middle.txt"); + assertEqualInt(0, stat("middle.txt", &st)); + sleepUntilAfter(st.st_mtime); + assertMakeFile("new.txt", 0644, "new"); + assertMakeFile("a/b/new.txt", 0644, "new file in old directory"); + + /* Test --older-than on create */ + assertEqualInt(0, + systemf("%s --format pax -cf ../test1.tar " + "--older-than middle.txt *.txt a", + testprog)); + assertEqualInt(0, + systemf("%s --format pax -cf ../test2.tar *.txt a", + testprog)); + assertChdir(".."); + + /* Extract test1.tar to a clean dir and verify what got archived. */ + assertMakeDir("test1out", 0755); + assertChdir("test1out"); + assertEqualInt(0, systemf("%s xf ../test1.tar", testprog)); + assertFileNotExists("new.txt"); + assertFileNotExists("a/b/new.txt"); + assertFileNotExists("middle.txt"); + assertFileExists("old.txt"); + assertFileExists("a/b/old.txt"); + assertChdir(".."); + + /* Extract test2.tar to a clean dir with --older-than and verify. */ + assertMakeDir("test2out", 0755); + assertChdir("test2out"); + assertEqualInt(0, + systemf("%s xf ../test2.tar --older-than ../test1in/middle.txt", + testprog)); + assertFileNotExists("new.txt"); + assertFileNotExists("a/b/new.txt"); + assertFileNotExists("middle.txt"); + assertFileExists("old.txt"); + assertFileExists("a/b/old.txt"); + assertChdir(".."); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_passphrase.c b/dependencies/libarchive-3.4.2/tar/test/test_option_passphrase.c new file mode 100644 index 0000000..337292c --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_passphrase.c @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 2014 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_passphrase) +{ + const char *reffile = "test_option_passphrase.zip"; + + extract_reference_file(reffile); + failure("--passphrase option is broken"); + assertEqualInt(0, systemf( + "%s --passphrase pass1 -xf %s >test.out 2>test.err", + testprog, reffile)); + assertFileExists("file1"); + assertTextFileContents("contents of file1.\n", "file1"); + assertFileExists("file2"); + assertTextFileContents("contents of file2.\n", "file2"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_passphrase.zip.uu b/dependencies/libarchive-3.4.2/tar/test/test_option_passphrase.zip.uu new file mode 100644 index 0000000..021ae85 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_passphrase.zip.uu @@ -0,0 +1,12 @@ +begin 644 test_option_passphrase.zip +M4$L#!`H`"0```#B91$7D$C4,'P```!,````%`!P`9FEL93%55`D``VS'+U0" +MQR]4=7@+``$$]0$```04````BHPD*"^*I04=XKI\_FQ*TE+#),TD7TTKSP/7 +MR6R35%!+!PCD$C4,'P```!,```!02P,$"@`)````09E$1;VL<`L``03U`0``!!0```!D#6Z\@CI8 +MV1GIJO5TISQF^I:7.;Y3<-G3$YOCL(C_4$L'"+VL +M`PH`"0```#B91$7D$C4,'P```!,````%`!@```````$```"D@0````!F:6QE +M,554!0`#;,`PH`"0```$&91$6]K',. +M'P```!,````%`!@```````$```"D@6X```!F:6QE,E54!0`#><test.out 2>test.err", + testprog); + failure("Fatal error trying to use -q option"); + if (!assertEqualInt(0, r)) + return; + + assertFileContents("foo1", 4, "foo"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 2: -q foo bar should extract up to the first bar. */ + assertMakeDir("test2", 0755); + assertChdir("test2"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar -q foo bar >test.out 2>test.err", testprog)); + assertFileContents("foo2", 4, "foo"); + assertFileContents("bar1", 4, "bar"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 3: Same as test 2, but use --fast-read spelling. */ + assertMakeDir("test3", 0755); + assertChdir("test3"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar --fast-read foo bar >test.out 2>test.err", testprog)); + assertFileContents("foo2", 4, "foo"); + assertFileContents("bar1", 4, "bar"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 4: Without -q, should extract everything. */ + assertMakeDir("test4", 0755); + assertChdir("test4"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar foo bar >test.out 2>test.err", testprog)); + assertFileContents("foo3", 4, "foo"); + assertFileContents("bar2", 4, "bar"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_r.c b/dependencies/libarchive-3.4.2/tar/test/test_option_r.c new file mode 100644 index 0000000..287e809 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_r.c @@ -0,0 +1,133 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * Also see test_option_q for additional validation of -r support. + */ +DEFINE_TEST(test_option_r) +{ + char *buff; + char *p0, *p1; + size_t buff_size = 35000; + size_t s, buff_size_rounded; + int r, i; + + buff = NULL; + p0 = NULL; + p1 = NULL; + + /* Create an archive with one file. */ + assertMakeFile("f1", 0644, "abc"); + r = systemf("%s cf archive.tar --format=ustar f1 >step1.out 2>step1.err", testprog); + failure("Error invoking %s cf archive.tar f1", testprog); + assertEqualInt(r, 0); + assertEmptyFile("step1.out"); + assertEmptyFile("step1.err"); + + /* Do some basic validation of the constructed archive. */ + p0 = slurpfile(&s, "archive.tar"); + if (!assert(p0 != NULL)) + goto done; + if (!assert(s >= 2048)) + goto done; + assertEqualMem(p0 + 0, "f1", 3); + assertEqualMem(p0 + 512, "abc", 3); + assertEqualMem(p0 + 1024, "\0\0\0\0\0\0\0\0", 8); + assertEqualMem(p0 + 1536, "\0\0\0\0\0\0\0\0", 8); + + /* Edit that file with a lot more data and update the archive with a new copy. */ + buff = malloc(buff_size); + assert(buff != NULL); + if (buff == NULL) + goto done; + + for (i = 0; i < (int)buff_size; ++i) + buff[i] = "abcdefghijklmnopqrstuvwxyz"[rand() % 26]; + buff[buff_size - 1] = '\0'; + assertMakeFile("f1", 0644, buff); + r = systemf("%s rf archive.tar --format=ustar f1 >step2.out 2>step2.err", testprog); + failure("Error invoking %s rf archive.tar f1", testprog); + assertEqualInt(r, 0); + assertEmptyFile("step2.out"); + assertEmptyFile("step2.err"); + + /* The constructed archive should just have the new entry appended. */ + p1 = slurpfile(&s, "archive.tar"); + if (!assert(p1 != NULL)) + goto done; + buff_size_rounded = ((buff_size + 511) / 512) * 512; + assert(s >= 2560 + buff_size_rounded); + /* Verify first entry is unchanged. */ + assertEqualMem(p0, p1, 1024); + /* Verify that second entry is correct. */ + assertEqualMem(p1 + 1024, "f1", 3); + assertEqualMem(p1 + 1536, buff, buff_size); + /* Verify end-of-archive marker. */ + assertEqualMem(p1 + 1536 + buff_size_rounded, "\0\0\0\0\0\0\0\0", 8); + assertEqualMem(p1 + 2048 + buff_size_rounded, "\0\0\0\0\0\0\0\0", 8); + + free(p0); + p0 = p1; + + /* Update the archive by adding a different file. */ + assertMakeFile("f2", 0644, "f2"); + r = systemf("%s rf archive.tar --format=ustar f2 >step3.out 2>step3.err", testprog); + failure("Error invoking %s rf archive.tar f2", testprog); + assertEqualInt(r, 0); + assertEmptyFile("step3.out"); + assertEmptyFile("step3.err"); + + /* Validate the constructed archive. */ + p1 = slurpfile(&s, "archive.tar"); + if (!assert(p1 != NULL)) + goto done; + assert(s >= 3584 + buff_size_rounded); + /* Verify first two entries are unchanged. */ + assertEqualMem(p0, p1, 1536 + buff_size_rounded); + /* Verify that new entry is correct. */ + assertEqualMem(p1 + 1536 + buff_size_rounded, "f2", 3); + assertEqualMem(p1 + 2048 + buff_size_rounded, "f2", 3); + /* Verify end-of-archive marker. */ + assertEqualMem(p1 + 2560 + buff_size_rounded, "\0\0\0\0\0\0\0\0", 8); + assertEqualMem(p1 + 3072 + buff_size_rounded, "\0\0\0\0\0\0\0\0", 8); + free(p1); + + /* Unpack everything */ + assertMakeDir("extract", 0775); + assertChdir("extract"); + r = systemf("%s xf ../archive.tar >extract.out 2>extract.err", testprog); + failure("Error invoking %s xf archive.tar", testprog); + assertEqualInt(r, 0); + assertEmptyFile("extract.out"); + assertEmptyFile("extract.err"); + + /* Verify that the second copy of f1 overwrote the first. */ + assertFileContents(buff, (int)strlen(buff), "f1"); +done: + free(buff); + free(p0); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_s.c b/dependencies/libarchive-3.4.2/tar/test/test_option_s.c new file mode 100644 index 0000000..fa799a2 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_s.c @@ -0,0 +1,278 @@ +/*- + * Copyright (c) 2003-2008 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_option_T.c,v 1.3 2008/08/15 06:12:02 kientzle Exp $"); + +DEFINE_TEST(test_option_s) +{ + struct stat st; + + /* Create a sample file hierarchy. */ + assertMakeDir("in", 0755); + assertMakeDir("in/d1", 0755); + assertMakeFile("in/d1/foo", 0644, "foo"); + assertMakeFile("in/d1/bar", 0644, "bar"); + if (canSymlink()) { + assertMakeFile("in/d1/realfile", 0644, "realfile"); + assertMakeSymlink("in/d1/symlink", "realfile", 0); + } + assertMakeFile("in/d1/hardlink1", 0644, "hardlinkedfile"); + assertMakeHardlink("in/d1/hardlink2", "in/d1/hardlink1"); + + /* Does tar support -s option ? */ + systemf("%s -cf - -s /foo/bar/ in/d1/foo > NUL 2> check.err", + testprog); + assertEqualInt(0, stat("check.err", &st)); + if (st.st_size != 0) { + skipping("%s does not support -s option on this platform", + testprog); + return; + } + + /* + * Test 1: Filename substitution when creating archives. + */ + assertMakeDir("test1", 0755); + systemf("%s -cf test1_1.tar -s /foo/bar/ in/d1/foo", testprog); + systemf("%s -xf test1_1.tar -C test1", testprog); + assertFileContents("foo", 3, "test1/in/d1/bar"); + systemf("%s -cf test1_2.tar -s /d1/d2/ in/d1/foo", testprog); + systemf("%s -xf test1_2.tar -C test1", testprog); + assertFileContents("foo", 3, "test1/in/d2/foo"); + + /* + * Test 2: Basic substitution when extracting archive. + */ + assertMakeDir("test2", 0755); + systemf("%s -cf test2.tar in/d1/foo", testprog); + systemf("%s -xf test2.tar -s /foo/bar/ -C test2", testprog); + assertFileContents("foo", 3, "test2/in/d1/bar"); + + /* + * Test 3: Files with empty names shouldn't be archived. + */ + systemf("%s -cf test3.tar -s ,in/d1/foo,, in/d1/foo", testprog); + systemf("%s -tvf test3.tar > in.lst", testprog); + assertEmptyFile("in.lst"); + + /* + * Test 4: Multiple substitutions when extracting archive. + */ + assertMakeDir("test4", 0755); + systemf("%s -cf test4.tar in/d1/foo in/d1/bar", + testprog); + systemf("%s -xf test4.tar -s /foo/bar/ -s }bar}baz} -C test4", + testprog); + assertFileContents("foo", 3, "test4/in/d1/bar"); + assertFileContents("bar", 3, "test4/in/d1/baz"); + + /* + * Test 5: Name-switching substitutions when extracting archive. + */ + assertMakeDir("test5", 0755); + systemf("%s -cf test5.tar in/d1/foo in/d1/bar", testprog); + systemf("%s -xf test5.tar -s /foo/bar/ -s }bar}foo} -C test5", testprog); + assertFileContents("foo", 3, "test5/in/d1/bar"); + assertFileContents("bar", 3, "test5/in/d1/foo"); + + /* + * Test 6: symlinks get renamed by default + */ + if (canSymlink()) { + /* At extraction time. */ + assertMakeDir("test6a", 0755); + systemf("%s -cf - in/d1 | %s -xf - -s /d1/d2/ -C test6a", + testprog, testprog); + assertFileContents("realfile", 8, "test6a/in/d2/realfile"); + assertFileContents("realfile", 8, "test6a/in/d2/symlink"); + assertIsSymlink("test6a/in/d2/symlink", "realfile", 0); + /* At creation time. */ + assertMakeDir("test6b", 0755); + systemf("%s -cf - -s /d1/d2/ in/d1 | %s -xf - -C test6b", + testprog, testprog); + assertFileContents("realfile", 8, "test6b/in/d2/realfile"); + assertFileContents("realfile", 8, "test6b/in/d2/symlink"); + assertIsSymlink("test6b/in/d2/symlink", "realfile", 0); + } + + /* + * Test 7: selective renaming of symlink target + */ + if (canSymlink()) { + /* At extraction. */ + assertMakeDir("test7a", 0755); + systemf("%s -cf - in/d1 | %s -xf - -s /realfile/realfile-renamed/ -C test7a", + testprog, testprog); + assertFileContents("realfile", 8, "test7a/in/d1/realfile-renamed"); + assertFileContents("realfile", 8, "test7a/in/d1/symlink"); + assertIsSymlink("test7a/in/d1/symlink", "realfile-renamed", 0); + /* At creation. */ + assertMakeDir("test7b", 0755); + systemf("%s -cf - -s /realfile/realfile-renamed/ in/d1 | %s -xf - -C test7b", + testprog, testprog); + assertFileContents("realfile", 8, "test7b/in/d1/realfile-renamed"); + assertFileContents("realfile", 8, "test7b/in/d1/symlink"); + assertIsSymlink("test7b/in/d1/symlink", "realfile-renamed", 0); + } + + /* + * Test 8: hardlinks get renamed by default + */ + /* At extraction time. */ + assertMakeDir("test8a", 0755); + systemf("%s -cf test8a.tar in/d1", testprog); + systemf("%s -xf test8a.tar -s /d1/d2/ -C test8a", testprog); + assertIsHardlink("test8a/in/d2/hardlink1", "test8a/in/d2/hardlink2"); + /* At creation time. */ + assertMakeDir("test8b", 0755); + systemf("%s -cf test8b.tar -s /d1/d2/ in/d1", testprog); + systemf("%s -xf test8b.tar -C test8b", testprog); + assertIsHardlink("test8b/in/d2/hardlink1", "test8b/in/d2/hardlink2"); + + /* + * Test 9: selective renaming of hardlink target + */ + /* At extraction. (assuming hardlink2 is the hardlink entry) */ + assertMakeDir("test9a", 0755); + systemf("%s -cf test9a.tar in/d1", testprog); + systemf("%s -xf test9a.tar -s /hardlink1/hardlink1-renamed/ -C test9a", + testprog); + assertIsHardlink("test9a/in/d1/hardlink1-renamed", "test9a/in/d1/hardlink2"); + /* At extraction. (assuming hardlink1 is the hardlink entry) */ + assertMakeDir("test9b", 0755); + systemf("%s -cf test9b.tar in/d1", testprog); + systemf("%s -xf test9b.tar -s /hardlink2/hardlink2-renamed/ -C test9b", + testprog); + assertIsHardlink("test9b/in/d1/hardlink1", "test9b/in/d1/hardlink2-renamed"); + /* At creation. (assuming hardlink2 is the hardlink entry) */ + assertMakeDir("test9c", 0755); + systemf("%s -cf test9c.tar -s /hardlink1/hardlink1-renamed/ in/d1", + testprog); + systemf("%s -xf test9c.tar -C test9c", testprog); + assertIsHardlink("test9c/in/d1/hardlink1-renamed", "test9c/in/d1/hardlink2"); + /* At creation. (assuming hardlink1 is the hardlink entry) */ + assertMakeDir("test9d", 0755); + systemf("%s -cf test9d.tar -s /hardlink2/hardlink2-renamed/ in/d1", + testprog); + systemf("%s -xf test9d.tar -C test9d", testprog); + assertIsHardlink("test9d/in/d1/hardlink1", "test9d/in/d1/hardlink2-renamed"); + + /* + * Test 10: renaming symlink target without repointing symlink + */ + if (canSymlink()) { + /* At extraction. */ + assertMakeDir("test10a", 0755); + systemf("%s -cf - in/d1 | %s -xf - -s /realfile/foo/S -s /foo/realfile/ -C test10a", + testprog, testprog); + assertFileContents("realfile", 8, "test10a/in/d1/foo"); + assertFileContents("foo", 3, "test10a/in/d1/realfile"); + assertFileContents("foo", 3, "test10a/in/d1/symlink"); + assertIsSymlink("test10a/in/d1/symlink", "realfile", 0); + /* At creation. */ + assertMakeDir("test10b", 0755); + systemf("%s -cf - -s /realfile/foo/S -s /foo/realfile/ in/d1 | %s -xf - -C test10b", + testprog, testprog); + assertFileContents("realfile", 8, "test10b/in/d1/foo"); + assertFileContents("foo", 3, "test10b/in/d1/realfile"); + assertFileContents("foo", 3, "test10b/in/d1/symlink"); + assertIsSymlink("test10b/in/d1/symlink", "realfile", 0); + } + + /* + * Test 11: repointing symlink without renaming file + */ + if (canSymlink()) { + /* At extraction. */ + assertMakeDir("test11a", 0755); + systemf("%s -cf - in/d1 | %s -xf - -s /realfile/foo/sR -C test11a", + testprog, testprog); + assertFileContents("foo", 3, "test11a/in/d1/foo"); + assertFileContents("realfile", 8, "test11a/in/d1/realfile"); + assertFileContents("foo", 3, "test11a/in/d1/symlink"); + assertIsSymlink("test11a/in/d1/symlink", "foo", 0); + /* At creation. */ + assertMakeDir("test11b", 0755); + systemf("%s -cf - -s /realfile/foo/R in/d1 | %s -xf - -C test11b", + testprog, testprog); + assertFileContents("foo", 3, "test11b/in/d1/foo"); + assertFileContents("realfile", 8, "test11b/in/d1/realfile"); + assertFileContents("foo", 3, "test11b/in/d1/symlink"); + assertIsSymlink("test11b/in/d1/symlink", "foo", 0); + } + + /* + * Test 12: renaming hardlink target without changing hardlink. + * (Requires a pre-built archive, since we otherwise can't know + * which element will be stored as the hardlink.) + */ + extract_reference_file("test_option_s.tar.Z"); + assertMakeDir("test12a", 0755); + systemf("%s -xf test_option_s.tar.Z -s /hardlink1/foo/H -s /foo/hardlink1/ %s -C test12a", + testprog, canSymlink()?"":"--exclude in/d1/symlink"); + assertFileContents("foo", 3, "test12a/in/d1/hardlink1"); + assertFileContents("hardlinkedfile", 14, "test12a/in/d1/foo"); + assertFileContents("foo", 3, "test12a/in/d1/hardlink2"); + assertIsHardlink("test12a/in/d1/hardlink1", "test12a/in/d1/hardlink2"); + /* TODO: Expand this test to verify creation as well. + * Since either hardlink1 or hardlink2 might get stored as a hardlink, + * this will either requiring testing both cases and accepting either + * pass, or some very creative renames that can be tested regardless. + */ + + /* + * Test 13: repoint hardlink without changing files + * (Requires a pre-built archive, since we otherwise can't know + * which element will be stored as the hardlink.) + */ + extract_reference_file("test_option_s.tar.Z"); + assertMakeDir("test13a", 0755); + systemf("%s -xf test_option_s.tar.Z -s /hardlink1/foo/Rh -s /foo/hardlink1/Rh %s -C test13a", + testprog, canSymlink()?"":"--exclude in/d1/symlink"); + assertFileContents("foo", 3, "test13a/in/d1/foo"); + assertFileContents("hardlinkedfile", 14, "test13a/in/d1/hardlink1"); + assertFileContents("foo", 3, "test13a/in/d1/hardlink2"); + assertIsHardlink("test13a/in/d1/foo", "test13a/in/d1/hardlink2"); + /* TODO: See above; expand this test to verify renames at creation. */ + + /* + * Test 14: Global substitutions when extracting archive. + */ + /* Global substitution. */ + assertMakeDir("test14", 0755); + systemf("%s -cf test14.tar in/d1/foo in/d1/bar", + testprog); + systemf("%s -xf test14.tar -s /o/z/g -s /bar/baz/ -C test14", + testprog); + assertFileContents("foo", 3, "test14/in/d1/fzz"); + assertFileContents("bar", 3, "test14/in/d1/baz"); + /* Singular substitution. */ + systemf("%s -cf test14.tar in/d1/foo in/d1/bar", + testprog); + systemf("%s -xf test14.tar -s /o/z/ -s /bar/baz/ -C test14", + testprog); + assertFileContents("foo", 3, "test14/in/d1/fzo"); + assertFileContents("bar", 3, "test14/in/d1/baz"); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_s.tar.Z.uu b/dependencies/libarchive-3.4.2/tar/test/test_option_s.tar.Z.uu new file mode 100644 index 0000000..df690bf --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_s.tar.Z.uu @@ -0,0 +1,16 @@ +begin 644 test_option_s.tar.Z +M'YV0:=R\(!/C!8"#"!,J7,BPH<.'$"-*1`BCXHT:-4``J`CCAHV,&SG*H*&1 +MHTF3(&+$^%@C!HT8,&C(``%#Y0T9,P"`J#&QI\^?0(,"J#.'3A@Y(>FD:2/4 +M8=$P9LPT77@21LF3&J=JWA`0<6%'/TJ]FS"3G:H$$R9,>/5RN.C%L5 +MQHR4*S&ZA"F39HR1=G7"0$NX<$*B1I%65,KTZ].H7JO2K9C5L.7+F+>219JY +ML^?/H$.+'DVZM&G+80F^,//FS6G0:MG&]0C2Y%RW=>^J9+DWYLR:(V7($/SZ +M->*RBY>:?2RUJV3.&2#JGHUGLMMB=>.:IYYX'A3A' +M'FWPN`:?[F&T8FTB:?EBERW-"&8-=N$HPYQ16F@GGPBA.>"0:Q;9)DH*5H;I +MJ*26:NJIJ*:JZJJLMNKJJ[#&*NNLM-9JZZVXYJKKKKSVZNNOP`8K[+#$%FOL +)L<@FJ^RRS.X) +` +end diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_safe_writes.c b/dependencies/libarchive-3.4.2/tar/test/test_option_safe_writes.c new file mode 100644 index 0000000..8edf5c6 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_safe_writes.c @@ -0,0 +1,77 @@ +/*- + * Copyright (c) 2020 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_safe_writes) +{ + /* Create files */ + assertMakeDir("in", 0755); + assertEqualInt(0, chdir("in")); + assertMakeFile("f", 0644, "a"); + assertMakeFile("fh", 0644, "b"); + assertMakeFile("d", 0644, "c"); + assertMakeFile("fs", 0644, "d"); + assertMakeFile("ds", 0644, "e"); + assertEqualInt(0, chdir("..")); + + /* Tar files up */ + assertEqualInt(0, + systemf("%s -c -C in -f t.tar f fh d fs ds " + ">pack.out 2>pack.err", testprog)); + + /* Verify that nothing went to stdout or stderr. */ + assertEmptyFile("pack.err"); + assertEmptyFile("pack.out"); + + /* Create various objects */ + assertMakeDir("out", 0755); + assertEqualInt(0, chdir("out")); + assertMakeFile("f", 0644, "a"); + assertMakeHardlink("fh", "f"); + assertMakeDir("d", 0755); + if (canSymlink()) { + assertMakeSymlink("fs", "f", 0); + assertMakeSymlink("ds", "d", 1); + } + assertEqualInt(0, chdir("..")); + + /* Extract created archive withe safe writes */ + assertEqualInt(0, + systemf("%s -x -C out --safe-writes -f t.tar " + ">unpack.out 2>unpack.err", testprog)); + + /* Verify that nothing went to stdout or stderr. */ + assertEmptyFile("unpack.err"); + assertEmptyFile("unpack.out"); + + /* Verify that files were overwritten properly */ + assertEqualInt(0, chdir("out")); + assertTextFileContents("a","f"); + assertTextFileContents("b","fh"); + assertTextFileContents("c","d"); + assertTextFileContents("d","fs"); + assertTextFileContents("e","ds"); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_uid_uname.c b/dependencies/libarchive-3.4.2/tar/test/test_option_uid_uname.c new file mode 100644 index 0000000..80c0619 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_uid_uname.c @@ -0,0 +1,85 @@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_uid_uname) +{ + char *reference, *data; + size_t s; + + assertUmask(0); + assertMakeFile("file", 0644, "1234567890"); + + /* Create archive with no special options. */ + failure("Error invoking %s c", testprog); + assertEqualInt(0, + systemf("%s cf archive1 --format=ustar file >stdout1.txt 2>stderr1.txt", + testprog)); + assertEmptyFile("stdout1.txt"); + assertEmptyFile("stderr1.txt"); + reference = slurpfile(&s, "archive1"); + + /* Again with both --uid and --uname */ + failure("Error invoking %s c", testprog); + assertEqualInt(0, + systemf("%s cf archive2 --uid=65123 --uname=foofoofoo --format=ustar file >stdout2.txt 2>stderr2.txt", + testprog)); + assertEmptyFile("stdout2.txt"); + assertEmptyFile("stderr2.txt"); + data = slurpfile(&s, "archive2"); + /* Should force uid and uname fields in ustar header. */ + assertEqualMem(data + 108, "177143 \0", 8); + assertEqualMem(data + 265, "foofoofoo\0", 10); + free(data); + + /* Again with just --uid */ + failure("Error invoking %s c", testprog); + assertEqualInt(0, + systemf("%s cf archive3 --uid=65123 --format=ustar file >stdout3.txt 2>stderr3.txt", + testprog)); + assertEmptyFile("stdout3.txt"); + assertEmptyFile("stderr3.txt"); + data = slurpfile(&s, "archive3"); + assertEqualMem(data + 108, "177143 \0", 8); + /* Uname field in ustar header should be empty. */ + assertEqualMem(data + 265, "\0", 1); + free(data); + + /* Again with just --uname */ + failure("Error invoking %s c", testprog); + assertEqualInt(0, + systemf("%s cf archive4 --uname=foofoofoo --format=ustar file >stdout4.txt 2>stderr4.txt", + testprog)); + assertEmptyFile("stdout4.txt"); + assertEmptyFile("stderr4.txt"); + data = slurpfile(&s, "archive4"); + /* Uid should be unchanged from original reference. */ + assertEqualMem(data + 108, reference + 108, 8); + assertEqualMem(data + 265, "foofoofoo\0", 10); + free(data); + + free(reference); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_uuencode.c b/dependencies/libarchive-3.4.2/tar/test/test_option_uuencode.c new file mode 100644 index 0000000..a28a8e3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_uuencode.c @@ -0,0 +1,56 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_uuencode) +{ + char *p; + size_t s; + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Archive it with compress compression and uuencode. */ + assertEqualInt(0, + systemf("%s -cf - -Z --uuencode f >archive.out 2>archive.err", + testprog)); + /* Check that the archive file has an uuencode signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "begin 644", 9); + free(p); + + /* Archive it with uuencode only. */ + assertEqualInt(0, + systemf("%s -cf - --uuencode f >archive.out 2>archive.err", + testprog)); + /* Check that the archive file has an uuencode signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "begin 644", 9); + free(p); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_xattrs.c b/dependencies/libarchive-3.4.2/tar/test/test_option_xattrs.c new file mode 100644 index 0000000..79dfff5 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_xattrs.c @@ -0,0 +1,88 @@ +/*- + * Copyright (c) 2017 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_xattrs) +{ +#if !ARCHIVE_XATTR_SUPPORT + skipping("Extended attributes are not supported on this platform"); +#else /* ARCHIVE_XATTR_SUPPORT */ + + const char *testattr = "user.libarchive.test"; + const char *testval = "testval"; + void *readval; + size_t size; + int r; + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + if (!setXattr("f", "user.libarchive.test", testval, + strlen(testval) + 1)) { + skipping("Can't set user extended attributes on this " + "filesystem"); + return; + } + + /* Archive with xattrs */ + r = systemf("%s -c --no-mac-metadata --xattrs -f xattrs.tar f >xattrs.out 2>xattrs.err", testprog); + assertEqualInt(r, 0); + + /* Archive without xattrs */ + r = systemf("%s -c --no-mac-metadata --no-xattrs -f noxattrs.tar f >noxattrs.out 2>noxattrs.err", testprog); + assertEqualInt(r, 0); + + /* Extract xattrs with xattrs */ + assertMakeDir("xattrs_xattrs", 0755); + r = systemf("%s -x -C xattrs_xattrs --no-same-permissions --xattrs -f xattrs.tar >xattrs_xattrs.out 2>xattrs_xattrs.err", testprog); + assertEqualInt(r, 0); + readval = getXattr("xattrs_xattrs/f", testattr, &size); + if(assertEqualInt(size, strlen(testval) + 1) != 0) + assertEqualMem(readval, testval, size); + free(readval); + + /* Extract xattrs without xattrs */ + assertMakeDir("xattrs_noxattrs", 0755); + r = systemf("%s -x -C xattrs_noxattrs -p --no-xattrs -f xattrs.tar >xattrs_noxattrs.out 2>xattrs_noxattrs.err", testprog); + assertEqualInt(r, 0); + readval = getXattr("xattrs_noxattrs/f", testattr, &size); + assert(readval == NULL); + + /* Extract noxattrs with xattrs */ + assertMakeDir("noxattrs_xattrs", 0755); + r = systemf("%s -x -C noxattrs_xattrs --no-same-permissions --xattrs -f noxattrs.tar >noxattrs_xattrs.out 2>noxattrs_xattrs.err", testprog); + assertEqualInt(r, 0); + readval = getXattr("noxattrs_xattrs/f", testattr, &size); + assert(readval == NULL); + + /* Extract noxattrs with noxattrs */ + assertMakeDir("noxattrs_noxattrs", 0755); + r = systemf("%s -x -C noxattrs_noxattrs -p --no-xattrs -f noxattrs.tar >noxattrs_noxattrs.out 2>noxattrs_noxattrs.err", testprog); + assertEqualInt(r, 0); + readval = getXattr("noxattrs_noxattrs/f", testattr, &size); + assert(readval == NULL); +#endif /* ARCHIVE_XATTR_SUPPORT */ +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_xz.c b/dependencies/libarchive-3.4.2/tar/test/test_option_xz.c new file mode 100644 index 0000000..91da073 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_xz.c @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_xz) +{ + char *p; + int r; + size_t s; + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Archive it with xz compression. */ + r = systemf("%s -cf - --xz f >archive.out 2>archive.err", + testprog); + p = slurpfile(&s, "archive.err"); + p[s] = '\0'; + if (r != 0) { + if (strstr(p, "Unsupported compression") != NULL) { + skipping("This version of bsdtar was compiled " + "without xz support"); + goto done; + } + failure("--xz option is broken"); + assertEqualInt(r, 0); + goto done; + } + free(p); + /* Check that the archive file has an xz signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "\xFD\x37\x7A\x58\x5A\x00", 6); +done: + free(p); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_z.c b/dependencies/libarchive-3.4.2/tar/test/test_option_z.c new file mode 100644 index 0000000..5974499 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_z.c @@ -0,0 +1,58 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_z) +{ + char *p; + int r; + size_t s; + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Archive it with gzip compression. */ + r = systemf("%s -zcf archive.out f 2>archive.err", testprog); + p = slurpfile(&s, "archive.err"); + p[s] = '\0'; + if (r != 0) { + if (!canGzip()) { + skipping("gzip is not supported on this platform"); + goto done; + } + failure("-z option is broken"); + assertEqualInt(r, 0); + goto done; + } + free(p); + /* Check that the archive file has a gzip signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 4); + assertEqualMem(p, "\x1f\x8b\x08\x00", 4); +done: + free(p); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_option_zstd.c b/dependencies/libarchive-3.4.2/tar/test/test_option_zstd.c new file mode 100644 index 0000000..73965e3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_option_zstd.c @@ -0,0 +1,85 @@ +/*- + * Copyright (c) 2017 Sean Purcell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_zstd) +{ + char *p; + int r; + size_t s; + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Archive it with lz4 compression. */ + r = systemf("%s -cf - --zstd f >archive.out 2>archive.err", + testprog); + p = slurpfile(&s, "archive.err"); + p[s] = '\0'; + if (r != 0) { + if (strstr(p, "Unsupported compression") != NULL) { + skipping("This version of bsdtar was compiled " + "without zstd support"); + goto done; + } + /* POSIX permits different handling of the spawnp + * system call used to launch the subsidiary + * program: */ + /* Some systems fail immediately to spawn the new process. */ + if (strstr(p, "Can't launch") != NULL && !canZstd()) { + skipping("This version of bsdtar uses an external zstd program " + "but no such program is available on this system."); + goto done; + } + /* Some systems successfully spawn the new process, + * but fail to exec a program within that process. + * This results in failure at the first attempt to + * write. */ + if (strstr(p, "Can't write") != NULL && !canZstd()) { + skipping("This version of bsdtar uses an external zstd program " + "but no such program is available on this system."); + goto done; + } + /* On some systems the error won't be detected until closing + time, by a 127 exit error returned by waitpid. */ + if (strstr(p, "Error closing") != NULL && !canZstd()) { + skipping("This version of bsdcpio uses an external zstd program " + "but no such program is available on this system."); + return; + } + failure("--zstd option is broken: %s", p); + assertEqualInt(r, 0); + goto done; + } + free(p); + /* Check that the archive file has an lz4 signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "\x28\xb5\x2f\xfd", 4); + +done: + free(p); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_patterns.c b/dependencies/libarchive-3.4.2/tar/test/test_patterns.c new file mode 100644 index 0000000..e144900 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_patterns.c @@ -0,0 +1,190 @@ +/*- + * Copyright (c) 2009 Michihiro NAKAJIMA + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_patterns.c,v 1.6 2008/08/21 22:28:00 kientzle Exp $"); + +DEFINE_TEST(test_patterns) +{ + FILE *f; + int r; + const char *reffile2 = "test_patterns_2.tar"; + const char *reffile3 = "test_patterns_3.tar"; + const char *reffile4 = "test_patterns_4.tar"; + + const char *tar2aExpected[] = { + "/tmp/foo/bar/", + "/tmp/foo/bar/baz", + NULL + }; + + /* + * Test basic command-line pattern handling. + */ + + /* + * Test 1: Files on the command line that don't get matched + * didn't produce an error. + * + * John Baldwin reported this problem in PR bin/121598 + */ + f = fopen("foo", "w"); + assert(f != NULL); + fclose(f); + r = systemf("%s cfv tar1.tgz foo > tar1a.out 2> tar1a.err", testprog); + assertEqualInt(r, 0); + r = systemf("%s xv --no-same-owner -f tar1.tgz foo bar > tar1b.out 2> tar1b.err", testprog); + failure("tar should return non-zero because a file was given on the command line that's not in the archive"); + assert(r != 0); + + /* + * Test 2: Check basic matching of full paths that start with / + */ + extract_reference_file(reffile2); + + r = systemf("%s tf %s /tmp/foo/bar > tar2a.out 2> tar2a.err", + testprog, reffile2); + assertEqualInt(r, 0); + assertFileContainsLinesAnyOrder("tar2a.out", tar2aExpected); + assertEmptyFile("tar2a.err"); + + /* + * Test 3 archive has some entries starting with '/' and some not. + */ + extract_reference_file(reffile3); + + /* Test 3a: Pattern tmp/foo/bar should not match /tmp/foo/bar */ + r = systemf("%s x --no-same-owner -f %s tmp/foo/bar > tar3a.out 2> tar3a.err", + testprog, reffile3); + assert(r != 0); + assertEmptyFile("tar3a.out"); + + /* Test 3b: Pattern /tmp/foo/baz should not match tmp/foo/baz */ + assertNonEmptyFile("tar3a.err"); + /* Again, with the '/' */ + r = systemf("%s x --no-same-owner -f %s /tmp/foo/baz > tar3b.out 2> tar3b.err", + testprog, reffile3); + assert(r != 0); + assertEmptyFile("tar3b.out"); + assertNonEmptyFile("tar3b.err"); + + /* Test 3c: ./tmp/foo/bar should not match /tmp/foo/bar */ + r = systemf("%s x --no-same-owner -f %s ./tmp/foo/bar > tar3c.out 2> tar3c.err", + testprog, reffile3); + assert(r != 0); + assertEmptyFile("tar3c.out"); + assertNonEmptyFile("tar3c.err"); + + /* Test 3d: ./tmp/foo/baz should match tmp/foo/baz */ + r = systemf("%s x --no-same-owner -f %s ./tmp/foo/baz > tar3d.out 2> tar3d.err", + testprog, reffile3); + assertEqualInt(r, 0); + assertEmptyFile("tar3d.out"); + assertEmptyFile("tar3d.err"); + assertFileExists("tmp/foo/baz/bar"); + + /* + * Test 4 archive has some entries starting with windows drive letters + * such as 'c:\', '//./c:/' or '//?/c:/'. + */ + extract_reference_file(reffile4); + + r = systemf("%s x --no-same-owner -f %s -C tmp > tar4.out 2> tar4.err", + testprog, reffile4); + assert(r != 0); + assertEmptyFile("tar4.out"); + assertNonEmptyFile("tar4.err"); + + for (r = 1; r <= 54; r++) { + char file_a[] = "tmp/fileXX"; + char file_b1[] = "tmp/server/share/fileXX"; + char file_b2[] = "tmp/server\\share\\fileXX"; + char file_c[] = "tmp/../fileXX"; + char file_d[] = "tmp/../../fileXX"; + char *filex; + int xsize; + + switch (r) { + case 15: case 18: + /* + * Including server and share names. + * //?/UNC/server/share/file15 + * //?/unc/server/share/file18 + */ + filex = file_b1; + xsize = sizeof(file_b1); + break; + case 35: case 38: case 52: + /* + * Including server and share names. + * \\?\UNC\server\share\file35 + * \\?\unc\server\share\file38 + * \/?/uNc/server\share\file52 + */ + filex = file_b2; + xsize = sizeof(file_b2); + break; + default: + filex = file_a; + xsize = sizeof(file_a); + break; + } + filex[xsize-3] = '0' + r / 10; + filex[xsize-2] = '0' + r % 10; + switch (r) { + case 5: case 6: case 17: case 20: case 25: + case 26: case 37: case 40: case 43: case 54: + /* + * Not extracted patterns. + * D:../file05 + * c:../../file06 + * //?/UNC/../file17 + * //?/unc/../file20 + * z:..\file25 + * c:..\..\file26 + * \\?\UNC\..\file37 + * \\?\unc\..\file40 + * c:../..\file43 + * \/?\UnC\../file54 + */ + assertFileNotExists(filex); + if (r == 6 || r == 26 || r == 43) { + filex = file_d; + xsize = sizeof(file_d); + } else { + filex = file_c; + xsize = sizeof(file_c); + } + filex[xsize-3] = '0' + r / 10; + filex[xsize-2] = '0' + r % 10; + assertFileNotExists(filex); + break; + default: + /* Extracted patterns. */ + assertFileExists(filex); + break; + } + } +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_patterns_2.tar.uu b/dependencies/libarchive-3.4.2/tar/test/test_patterns_2.tar.uu new file mode 100644 index 0000000..eba2dae --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_patterns_2.tar.uu @@ -0,0 +1,231 @@ +begin 644 test_patterns_2.tar +M+W1M<"]F;V\O```````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````#`P,#@`````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````P +M,#`V-#0@`#`P,3@`````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````#`P,#8T-"``,#`Q-S4P(``P,#`P,#`@`#`P,#`P +M,#`P,#`P(#$Q,#4Q,C$R-C4S(#`Q,S8V-P`@,``````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````!UCHN+EQF:6QE,C4````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````#`P,#8T-"``,#`Q-S4Q(``P,#$W-3$@`#`P,#`P,#`P +M,#`P(#$Q,34P-Ctest.out 2>test.err", testprog, reffile)); + assertTextFileContents(buff, "test.out"); + assertEmptyFile("test.err"); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_print_longpath.tar.Z.uu b/dependencies/libarchive-3.4.2/tar/test/test_print_longpath.tar.Z.uu new file mode 100644 index 0000000..05658ff --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_print_longpath.tar.Z.uu @@ -0,0 +1,24 @@ +begin 644 test_print_longpath.tar.Z +M'YV04,+@05(F#)DR,H/*E$$31(P8$6_0"$H4 +M!`R+-&@``($'IM6K6+-JWO8+O6F4,GC!R<8^J4"//JWC.^&$H8.FA\N6)DF*!(DR,6*6C2&O9#Q9Y6++ASN^4"`# +M!H@Q=-*T*=,CQ@P9-638\%B#L^?!HDF;1JV:M8(9.$`P22(DB)0A2))8*>)B +MC)R"H=^X"3VZ].G4-B;FP*'`K_7KV+-KW\Z]N_?O5S-75BS^,GG'D2F;?ZR^ +M?.87.&'0M(G39XV=]7_&EQO4*-(;2C%U@U,RH`;15#6`IZ!V8Y5UEDQN:1=A +M=OS1U=^"&&:H85@!#53000FYA]YX[&$VXGKIF2@9BC`%-1]0]N'7DW[\R125 +M#/XEM91,-3DU`T0TS#!551L6"5>#9J&EEH1+4BB7A7/%=**(*U+9WI185IFE +M>D;Z)0-#(`A&F&%;JGBEEFB>J::9;"JF4)GGI=EFB7&N6>>;;KSY!IQPQ!F'7!K*\>D<;:M55%V7G';J:896XDEB +MBG>62N>II$8$GXL]YGKW=U2)!!"+TI)[/2PHEJMY"U.%.K,[[JJHPUVB!? +MC@#N&$-J/@(I%574^AJLDF\5VR1VR/;KK;/1!KSLMP*?6"];,Y@6YF"%#0RP +MP^#:27!YVDK\\+\1BUKPBA5K#/'&%F?,;0Z;=;9G;)<>"L-T@UIJZ)\RY'!; +M;KOU]EMPPQ5W'&R5HOQRIC%O>O#07WUL-,8@>XS>JN/25RZZ,4)9(:WM]@0O +MKC3=T"O17=X+X;[7&6M=OT]*N>W$2!]]-L!<>V7MA]FJ'7+2(SLLKGSDYF3N +MTU+/!(,-[`:X4)#QVA#5D&T;Z?6P8%LGME]DUV7VW'(KO;;((27.%0TQT+#P +MF)77G?;HEY,<.MJEGPYPQZ*G3CKE2+...NRNUSYWR9Z!YK.?F>800\N[8TJ1 +M[T(3K3KF%]N.)]-X.ZTWU+'*ZAG5@G<^@X^YUJ`U"`EJKN'BC_<5/E^17W@\ +:W;-;/K?W[+?O_OOPQR___/37;__]^.>OOU<` +` +end diff --git a/dependencies/libarchive-3.4.2/tar/test/test_stdio.c b/dependencies/libarchive-3.4.2/tar/test/test_stdio.c new file mode 100644 index 0000000..d6650a5 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_stdio.c @@ -0,0 +1,126 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_stdio.c,v 1.2 2008/05/26 17:10:10 kientzle Exp $"); + +DEFINE_TEST(test_stdio) +{ + FILE *filelist; + char *p; + size_t s; + int r; + + assertUmask(0); + + /* + * Create a couple of files on disk. + */ + /* File */ + assertMakeFile("f", 0755, "abc"); + /* Link to above file. */ + assertMakeHardlink("l", "f"); + + /* Create file list (text mode here) */ + filelist = fopen("filelist", "w"); + assert(filelist != NULL); + fprintf(filelist, "f\n"); + fprintf(filelist, "l\n"); + fclose(filelist); + + /* + * Archive/dearchive with a variety of options, verifying + * stdio paths. + */ + + /* 'cf' should generate no output unless there's an error. */ + r = systemf("%s cf archive f l >cf.out 2>cf.err", testprog); + assertEqualInt(r, 0); + assertEmptyFile("cf.out"); + assertEmptyFile("cf.err"); + + /* 'cvf' should generate file list on stderr, empty stdout. */ + r = systemf("%s cvf archive f l >cvf.out 2>cvf.err", testprog); + assertEqualInt(r, 0); + failure("'cv' writes filenames to stderr, nothing to stdout (SUSv2)\n" + "Note that GNU tar writes the file list to stdout by default."); + assertEmptyFile("cvf.out"); + /* TODO: Verify cvf.err has file list in SUSv2-prescribed format. */ + + /* 'cvf -' should generate file list on stderr, archive on stdout. */ + r = systemf("%s cvf - f l >cvf-.out 2>cvf-.err", testprog); + assertEqualInt(r, 0); + failure("cvf - should write archive to stdout"); + /* TODO: Verify cvf-.out has archive. */ + failure("cvf - should write file list to stderr (SUSv2)"); + /* TODO: Verify cvf-.err has verbose file list. */ + + /* 'tf' should generate file list on stdout, empty stderr. */ + r = systemf("%s tf archive >tf.out 2>tf.err", testprog); + assertEqualInt(r, 0); + assertEmptyFile("tf.err"); + failure("'t' mode should write results to stdout"); + /* TODO: Verify tf.out has file list. */ + + /* 'tvf' should generate file list on stdout, empty stderr. */ + r = systemf("%s tvf archive >tvf.out 2>tvf.err", testprog); + assertEqualInt(r, 0); + assertEmptyFile("tvf.err"); + failure("'tv' mode should write results to stdout"); + /* TODO: Verify tvf.out has file list. */ + + /* 'tvf -' uses stdin, file list on stdout, empty stderr. */ + r = systemf("%s tvf - < archive >tvf-.out 2>tvf-.err", testprog); + assertEqualInt(r, 0); + assertEmptyFile("tvf-.err"); + /* TODO: Verify tvf-.out has file list. */ + + /* Basic 'xf' should generate no output on stdout or stderr. */ + r = systemf("%s xf archive >xf.out 2>xf.err", testprog); + assertEqualInt(r, 0); + assertEmptyFile("xf.err"); + assertEmptyFile("xf.out"); + + /* 'xvf' should generate list on stderr, empty stdout. */ + r = systemf("%s xvf archive >xvf.out 2>xvf.err", testprog); + assertEqualInt(r, 0); + assertEmptyFile("xvf.out"); + /* TODO: Verify xvf.err */ + + /* 'xvOf' should generate list on stderr, file contents on stdout. */ + r = systemf("%s xvOf archive >xvOf.out 2>xvOf.err", testprog); + assertEqualInt(r, 0); + /* Verify xvOf.out is the file contents */ + p = slurpfile(&s, "xvOf.out"); + assertEqualInt((int)s, 3); + assertEqualMem(p, "abc", 3); + /* TODO: Verify xvf.err */ + free(p); + + /* 'xvf -' should generate list on stderr, empty stdout. */ + r = systemf("%s xvf - < archive >xvf-.out 2>xvf-.err", testprog); + assertEqualInt(r, 0); + assertEmptyFile("xvf-.out"); + /* TODO: Verify xvf-.err */ +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_strip_components.c b/dependencies/libarchive-3.4.2/tar/test/test_strip_components.c new file mode 100644 index 0000000..090fb0d --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_strip_components.c @@ -0,0 +1,140 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_strip_components.c,v 1.2 2008/11/10 05:24:13 kientzle Exp $"); + +DEFINE_TEST(test_strip_components) +{ + assertMakeDir("d0", 0755); + assertChdir("d0"); + assertMakeDir("d1", 0755); + assertMakeDir("d1/d2", 0755); + assertMakeDir("d1/d2/d3", 0755); + assertMakeFile("d1/d2/f1", 0644, ""); + assertMakeHardlink("l1", "d1/d2/f1"); + assertMakeHardlink("d1/l2", "d1/d2/f1"); + if (canSymlink()) { + assertMakeSymlink("s1", "d1/d2/f1", 0); + assertMakeSymlink("d1/s2", "d2/f1", 0); + } + assertChdir(".."); + + /* + * Test 1: Strip components when extracting archives. + */ + if (canSymlink()) + assertEqualInt(0, systemf("%s -cf test.tar d0/l1 d0/s1 d0/d1", + testprog)); + else + assertEqualInt(0, systemf("%s -cf test.tar d0/l1 d0/d1", + testprog)); + + assertMakeDir("target", 0755); + assertEqualInt(0, systemf("%s -x -C target --strip-components 2 " + "-f test.tar", testprog)); + + failure("d0/ is too short and should not get restored"); + assertFileNotExists("target/d0"); + failure("d0/d1/ is too short and should not get restored"); + assertFileNotExists("target/d1"); + failure("d0/s1 is too short and should not get restored"); + assertFileNotExists("target/s1"); + failure("d0/d1/s2 is a symlink to something that won't be extracted"); + /* If platform supports symlinks, target/s2 is a broken symlink. */ + /* If platform does not support symlink, target/s2 doesn't exist. */ + if (canSymlink()) + assertIsSymlink("target/s2", "d2/f1", 0); + else + assertFileNotExists("target/s2"); + failure("d0/d1/d2 should be extracted"); + assertIsDir("target/d2", -1); + + /* + * Test 1b: Strip components extracting archives involving hardlinks. + * + * This next is a complicated case. d0/l1, d0/d1/l2, and + * d0/d1/d2/f1 are all hardlinks to the same file; d0/l1 can't + * be extracted with --strip-components=2 and the other two + * can. Remember that tar normally stores the first file with + * a body and the other as hardlink entries to the first + * appearance. So the final result depends on the order in + * which these three names get archived. If d0/l1 is first, + * none of the three can be restored. If either of the longer + * names are first, then the two longer ones can both be + * restored. Note that the "tar -cf" command above explicitly + * lists d0/l1 before d0/d1. + * + * It may be worth extending this test to exercise other + * archiving orders. + * + * Of course, this is all totally different for cpio and newc + * formats because the hardlink management is different. + * TODO: Rename this to test_strip_components_tar and create + * parallel tests for cpio and newc formats. + */ + failure("d0/l1 is too short and should not get restored"); + assertFileNotExists("target/l1"); + failure("d0/d1/l2 is a hardlink to file whose name was too short"); + assertFileNotExists("target/l2"); + failure("d0/d1/d2/f1 is a hardlink to file whose name was too short"); + assertFileNotExists("target/d2/f1"); + + /* + * Test 2: Strip components when creating archives. + */ + if (canSymlink()) + assertEqualInt(0, systemf("%s --strip-components 2 -cf test2.tar " + "d0/l1 d0/s1 d0/d1", testprog)); + else + assertEqualInt(0, systemf("%s --strip-components 2 -cf test2.tar " + "d0/l1 d0/d1", testprog)); + + assertMakeDir("target2", 0755); + assertEqualInt(0, systemf("%s -x -C target2 -f test2.tar", testprog)); + + failure("d0/ is too short and should not have been archived"); + assertFileNotExists("target2/d0"); + failure("d0/d1/ is too short and should not have been archived"); + assertFileNotExists("target2/d1"); + failure("d0/s1 is too short and should not get restored"); + assertFileNotExists("target/s1"); + /* If platform supports symlinks, target/s2 is included. */ + if (canSymlink()) { + failure("d0/d1/s2 is a symlink to something included in archive"); + assertIsSymlink("target2/s2", "d2/f1", 0); + } + failure("d0/d1/d2 should be archived"); + assertIsDir("target2/d2", -1); + + /* + * Test 2b: Strip components creating archives involving hardlinks. + */ + failure("d0/l1 is too short and should not have been archived"); + assertFileNotExists("target/l1"); + failure("d0/d1/l2 is a hardlink to file whose name was too short"); + assertFileNotExists("target/l2"); + failure("d0/d1/d2/f1 is a hardlink to file whose name was too short"); + assertFileNotExists("target/d2/f1"); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_symlink_dir.c b/dependencies/libarchive-3.4.2/tar/test/test_symlink_dir.c new file mode 100644 index 0000000..5836647 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_symlink_dir.c @@ -0,0 +1,160 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_symlink_dir.c,v 1.1 2008/09/14 02:16:04 kientzle Exp $"); + +/* + * tar -x -P should follow existing symlinks for dirs, but not other + * content. Plain tar -x should remove symlinks when they're in the + * way of a dir extraction. + */ + +DEFINE_TEST(test_symlink_dir) +{ + assertUmask(0); + + assertMakeDir("source", 0755); + assertMakeFile("source/file", 0755, "a"); + assertMakeFile("source/file2", 0755, "ab"); + assertMakeDir("source/dir", 0755); + assertMakeDir("source/dir/d", 0755); + assertMakeFile("source/dir/f", 0755, "abc"); + assertMakeDir("source/dir2", 0755); + assertMakeDir("source/dir2/d2", 0755); + assertMakeFile("source/dir2/f2", 0755, "abcd"); + assertMakeDir("source/dir3", 0755); + assertMakeDir("source/dir3/d3", 0755); + assertMakeFile("source/dir3/f3", 0755, "abcde"); + assertMakeDir("source/dir4", 0755); + assertMakeFile("source/dir4/file3", 0755, "abcdef"); + assertMakeHardlink("source/dir4/file4", "source/dir4/file3"); + + assertEqualInt(0, + systemf("%s -cf test.tar -C source dir dir2 dir3 file file2", + testprog)); + + /* Second archive with hardlinks */ + assertEqualInt(0, + systemf("%s -cf test2.tar -C source dir4", testprog)); + + /* + * Extract with -x and without -P. + */ + assertMakeDir("dest1", 0755); + /* "dir" is a symlink to an existing "dest1/real_dir" */ + assertMakeDir("dest1/real_dir", 0755); + if (canSymlink()) { + assertMakeSymlink("dest1/dir", "real_dir", 1); + /* "dir2" is a symlink to a non-existing "real_dir2" */ + assertMakeSymlink("dest1/dir2", "real_dir2", 1); + } else { + skipping("Symlinks are not supported on this platform"); + } + /* "dir3" is a symlink to an existing "non_dir3" */ + assertMakeFile("dest1/non_dir3", 0755, "abcdef"); + if (canSymlink()) + assertMakeSymlink("dest1/dir3", "non_dir3", 1); + /* "file" is a symlink to existing "real_file" */ + assertMakeFile("dest1/real_file", 0755, "abcdefg"); + if (canSymlink()) { + assertMakeSymlink("dest1/file", "real_file", 0); + /* "file2" is a symlink to non-existing "real_file2" */ + assertMakeSymlink("dest1/file2", "real_file2", 0); + } + assertEqualInt(0, systemf("%s -xf test.tar -C dest1", testprog)); + + /* dest1/dir symlink should be replaced */ + failure("symlink to dir was followed when it shouldn't be"); + assertIsDir("dest1/dir", -1); + /* dest1/dir2 symlink should be replaced */ + failure("Broken symlink wasn't replaced with dir"); + assertIsDir("dest1/dir2", -1); + /* dest1/dir3 symlink should be replaced */ + failure("Symlink to non-dir wasn't replaced with dir"); + assertIsDir("dest1/dir3", -1); + /* dest1/file symlink should be replaced */ + failure("Symlink to existing file should be replaced"); + assertIsReg("dest1/file", -1); + /* dest1/file2 symlink should be replaced */ + failure("Symlink to non-existing file should be replaced"); + assertIsReg("dest1/file2", -1); + + /* + * Extract with both -x and -P + */ + assertMakeDir("dest2", 0755); + /* "dir" is a symlink to existing "real_dir" */ + assertMakeDir("dest2/real_dir", 0755); + if (canSymlink()) + assertMakeSymlink("dest2/dir", "real_dir", 1); + /* "dir2" is a symlink to a non-existing "real_dir2" */ + if (canSymlink()) + assertMakeSymlink("dest2/dir2", "real_dir2", 1); + /* "dir3" is a symlink to an existing "non_dir3" */ + assertMakeFile("dest2/non_dir3", 0755, "abcdefgh"); + if (canSymlink()) + assertMakeSymlink("dest2/dir3", "non_dir3", 1); + /* "file" is a symlink to existing "real_file" */ + assertMakeFile("dest2/real_file", 0755, "abcdefghi"); + if (canSymlink()) + assertMakeSymlink("dest2/file", "real_file", 0); + /* "file2" is a symlink to non-existing "real_file2" */ + if (canSymlink()) + assertMakeSymlink("dest2/file2", "real_file2", 0); + assertEqualInt(0, systemf("%s -xPf test.tar -C dest2", testprog)); + + /* "dir4" is a symlink to existing "real_dir" */ + if (canSymlink()) + assertMakeSymlink("dest2/dir4", "real_dir", 1); + assertEqualInt(0, systemf("%s -xPf test2.tar -C dest2", testprog)); + + /* dest2/dir and dest2/dir4 symlinks should be followed */ + if (canSymlink()) { + assertIsSymlink("dest2/dir", "real_dir", 1); + assertIsSymlink("dest2/dir4", "real_dir", 1); + assertIsDir("dest2/real_dir", -1); + } + + /* Contents of 'dir' should be restored */ + assertIsDir("dest2/dir/d", -1); + assertIsReg("dest2/dir/f", -1); + assertFileSize("dest2/dir/f", 3); + /* dest2/dir2 symlink should be removed */ + failure("Broken symlink wasn't replaced with dir"); + assertIsDir("dest2/dir2", -1); + /* dest2/dir3 symlink should be removed */ + failure("Symlink to non-dir wasn't replaced with dir"); + assertIsDir("dest2/dir3", -1); + /* dest2/file symlink should be removed; + * even -P shouldn't follow symlinks for files */ + failure("Symlink to existing file should be removed"); + assertIsReg("dest2/file", -1); + /* dest2/file2 symlink should be removed */ + failure("Symlink to non-existing file should be removed"); + assertIsReg("dest2/file2", -1); + + /* dest2/dir4/file3 and dest2/dir4/file4 should be hard links */ + assertIsHardlink("dest2/dir4/file3", "dest2/dir4/file4"); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_version.c b/dependencies/libarchive-3.4.2/tar/test/test_version.c new file mode 100644 index 0000000..1b896c0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_version.c @@ -0,0 +1,34 @@ +/*- + * Copyright (c) 2003-2017 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +/* + * Test that --version option works and generates reasonable output. + */ + +DEFINE_TEST(test_version) +{ + assertVersion(testprog, "bsdtar"); +} diff --git a/dependencies/libarchive-3.4.2/tar/test/test_windows.c b/dependencies/libarchive-3.4.2/tar/test/test_windows.c new file mode 100644 index 0000000..d619667 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/test/test_windows.c @@ -0,0 +1,324 @@ +/*- + * Copyright (c) 2009 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +#if defined(_WIN32) && !defined(__CYGWIN__) +#include +#include + +static void +mkfile(const char *name) +{ + FILE *f; + + f = fopen(name, "wb"); + assert(f != NULL); + assertEqualInt(5, fwrite("01234", 1, 5, f)); + fclose(f); +} + +static void +mkfullpath(char **path1, char **path2, const char *tpath, int type) +{ + char *fp1 = NULL, *fp2 = NULL, *p1 = NULL, *p2 = NULL; + size_t l; + + /* + * Get full path name of "tpath" + */ + l = GetFullPathNameA(tpath, 0, NULL, NULL); + assert(0 != l); + fp1 = malloc(l); + assert(NULL != fp1); + fp2 = malloc(l*2); + assert(NULL != fp2); + l = GetFullPathNameA(tpath, (DWORD)l, fp1, NULL); + if ((type & 0x01) == 0) { + for (p1 = fp1; *p1 != '\0'; p1++) + if (*p1 == '\\') + *p1 = '/'; + } + + switch(type) { + case 0: /* start with "/" */ + case 1: /* start with "\" */ + /* strip "c:" */ + memmove(fp1, fp1 + 2, l - 2); + fp1[l -2] = '\0'; + p1 = fp1 + 1; + break; + case 2: /* start with "c:/" */ + case 3: /* start with "c:\" */ + p1 = fp1 + 3; + break; + case 4: /* start with "//./c:/" */ + case 5: /* start with "\\.\c:\" */ + case 6: /* start with "//?/c:/" */ + case 7: /* start with "\\?\c:\" */ + p1 = malloc(l + 4 + 1); + assert(NULL != p1); + if (type & 0x1) + memcpy(p1, "\\\\.\\", 4); + else + memcpy(p1, "//./", 4); + if (type == 6 || type == 7) + p1[2] = '?'; + memcpy(p1 + 4, fp1, l); + p1[l + 4] = '\0'; + free(fp1); + fp1 = p1; + p1 = fp1 + 7; + break; + } + + /* + * Strip leading drive names and converting "\" to "\\" + */ + p2 = fp2; + while (*p1 != '\0') { + if (*p1 == '\\') + *p2 = '/'; + else + *p2 = *p1; + ++p1; + ++p2; + } + *p2++ = '\r'; + *p2++ = '\n'; + *p2 = '\0'; + + *path1 = fp1; + *path2 = fp2; +} + +static const char *list1[] = {"aaa/", "aaa/file1", "aaa/xxa/", "aaa/xxb/", + "aaa/zzc/", "aaa/zzc/file1", "aaa/xxb/file1", "aaa/xxa/file1", + "aab/", "aac/", "abb/", "abc/", "abd/", NULL}; +static const char *list2[] = {"bbb/", "bbb/file1", "bbb/xxa/", "bbb/xxb/", + "bbb/zzc/", "bbb/zzc/file1", "bbb/xxb/file1", "bbb/xxa/file1", "bbc/", + "bbd/", "bcc/", "bcd/", "bce/", NULL}; +static const char *list3[] = {"aac/", "abc/", "bbc/", "bcc/", "ccc/", NULL}; +static const char *list4[] = {"fff/abca", "fff/acca", NULL}; +static const char *list5[] = {"aaa/file1", "aaa/xxa/", "aaa/xxa/file1", + "aaa/xxb/", "aaa/xxb/file1", "aaa/zzc/", "aaa/zzc/file1", NULL}; +static const char *list6[] = {"fff/abca", "fff/acca", "aaa/xxa/", + "aaa/xxa/file1", "aaa/xxb/", "aaa/xxb/file1", NULL}; +#endif /* _WIN32 && !__CYGWIN__ */ + +DEFINE_TEST(test_windows) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + char *fp1, *fp2; + + /* + * Prepare tests. + * Create directories and files. + */ + assertMakeDir("tmp", 0775); + assertChdir("tmp"); + + assertMakeDir("aaa", 0775); + assertMakeDir("aaa/xxa", 0775); + assertMakeDir("aaa/xxb", 0775); + assertMakeDir("aaa/zzc", 0775); + mkfile("aaa/file1"); + mkfile("aaa/xxa/file1"); + mkfile("aaa/xxb/file1"); + mkfile("aaa/zzc/file1"); + assertMakeDir("aab", 0775); + assertMakeDir("aac", 0775); + assertMakeDir("abb", 0775); + assertMakeDir("abc", 0775); + assertMakeDir("abd", 0775); + assertMakeDir("bbb", 0775); + assertMakeDir("bbb/xxa", 0775); + assertMakeDir("bbb/xxb", 0775); + assertMakeDir("bbb/zzc", 0775); + mkfile("bbb/file1"); + mkfile("bbb/xxa/file1"); + mkfile("bbb/xxb/file1"); + mkfile("bbb/zzc/file1"); + assertMakeDir("bbc", 0775); + assertMakeDir("bbd", 0775); + assertMakeDir("bcc", 0775); + assertMakeDir("bcd", 0775); + assertEqualInt(0, _mkdir("bce")); + assertEqualInt(0, _mkdir("ccc")); + assertEqualInt(0, _mkdir("fff")); + mkfile("fff/aaaa"); + mkfile("fff/abba"); + mkfile("fff/abca"); + mkfile("fff/acba"); + mkfile("fff/acca"); + + /* + * Test1: Command line pattern matching. + */ + assertEqualInt(0, + systemf("%s -cf ../archive1.tar a*", testprog)); + assertEqualInt(0, + systemf("%s -tf ../archive1.tar > ../list1", testprog)); + assertFileContainsLinesAnyOrder("../list1", list1); + + assertEqualInt(0, + systemf("%s -cf ../archive2.tar b*", testprog)); + assertEqualInt(0, + systemf("%s -tf ../archive2.tar > ../list2", testprog)); + assertFileContainsLinesAnyOrder("../list2", list2); + + assertEqualInt(0, + systemf("%s -cf ../archive3.tar ??c", testprog)); + assertEqualInt(0, + systemf("%s -tf ../archive3.tar > ../list3", testprog)); + assertFileContainsLinesAnyOrder("../list3", list3); + + assertEqualInt(0, + systemf("%s -cf ../archive3b.tar *c", testprog)); + assertEqualInt(0, + systemf("%s -tf ../archive3b.tar > ../list3b", testprog)); + assertFileContainsLinesAnyOrder("../list3b", list3); + + assertEqualInt(0, + systemf("%s -cf ../archive4.tar fff/a?ca", testprog)); + assertEqualInt(0, + systemf("%s -tf ../archive4.tar > ../list4", testprog)); + assertFileContainsLinesAnyOrder("../list4", list4); + + assertEqualInt(0, + systemf("%s -cf ../archive5.tar aaa\\*", testprog)); + assertEqualInt(0, + systemf("%s -tf ../archive5.tar > ../list5", testprog)); + assertFileContainsLinesAnyOrder("../list5", list5); + + assertEqualInt(0, + systemf("%s -cf ../archive6.tar fff\\a?ca aaa\\xx*", testprog)); + assertEqualInt(0, + systemf("%s -tf ../archive6.tar > ../list6", testprog)); + assertFileContainsLinesAnyOrder("../list6", list6); + + /* + * Test2: Archive the file start with drive letters. + */ + /* Test2a: start with "/" */ + mkfullpath(&fp1, &fp2, "aaa/file1", 0); + assertEqualInt(0, + systemf("%s -cf ../archive10.tar %s > ../out10 2> ../err10", + testprog, fp1)); + assertEqualInt(0, + systemf("%s -tf ../archive10.tar > ../list10", testprog)); + /* Check drive letters have been stripped. */ + assertFileContents(fp2, (int)strlen(fp2), "../list10"); + free(fp1); + free(fp2); + + /* Test2b: start with "\" */ + mkfullpath(&fp1, &fp2, "aaa/file1", 1); + assertEqualInt(0, + systemf("%s -cf ../archive11.tar %s > ../out11 2> ../err11", + testprog, fp1)); + assertEqualInt(0, + systemf("%s -tf ../archive11.tar > ../list11", testprog)); + /* Check drive letters have been stripped. */ + assertFileContents(fp2, (int)strlen(fp2), "../list11"); + free(fp1); + free(fp2); + + /* Test2c: start with "c:/" */ + mkfullpath(&fp1, &fp2, "aaa/file1", 2); + assertEqualInt(0, + systemf("%s -cf ../archive12.tar %s > ../out12 2> ../err12", + testprog, fp1)); + assertEqualInt(0, + systemf("%s -tf ../archive12.tar > ../list12", testprog)); + /* Check drive letters have been stripped. */ + assertFileContents(fp2, (int)strlen(fp2), "../list12"); + free(fp1); + free(fp2); + + /* Test2d: start with "c:\" */ + mkfullpath(&fp1, &fp2, "aaa/file1", 3); + assertEqualInt(0, + systemf("%s -cf ../archive13.tar %s > ../out13 2> ../err13", + testprog, fp1)); + assertEqualInt(0, + systemf("%s -tf ../archive13.tar > ../list13", testprog)); + /* Check drive letters have been stripped. */ + assertFileContents(fp2, (int)strlen(fp2), "../list13"); + free(fp1); + free(fp2); + + /* Test2e: start with "//./c:/" */ + mkfullpath(&fp1, &fp2, "aaa/file1", 4); + assertEqualInt(0, + systemf("%s -cf ../archive14.tar %s > ../out14 2> ../err14", + testprog, fp1)); + assertEqualInt(0, + systemf("%s -tf ../archive14.tar > ../list14", testprog)); + /* Check drive letters have been stripped. */ + assertFileContents(fp2, (int)strlen(fp2), "../list14"); + free(fp1); + free(fp2); + + /* Test2f: start with "\\.\c:\" */ + mkfullpath(&fp1, &fp2, "aaa/file1", 5); + assertEqualInt(0, + systemf("%s -cf ../archive15.tar %s > ../out15 2> ../err15", + testprog, fp1)); + assertEqualInt(0, + systemf("%s -tf ../archive15.tar > ../list15", testprog)); + /* Check drive letters have been stripped. */ + assertFileContents(fp2, (int)strlen(fp2), "../list15"); + free(fp1); + free(fp2); + + /* Test2g: start with "//?/c:/" */ + mkfullpath(&fp1, &fp2, "aaa/file1", 6); + failure("fp1=%s, fp2=%s", fp1, fp2); + assertEqualInt(0, + systemf("%s -cf ../archive16.tar %s > ../out16 2> ../err16", + testprog, fp1)); + assertEqualInt(0, + systemf("%s -tf ../archive16.tar > ../list16", testprog)); + /* Check drive letters have been stripped. */ + assertFileContents(fp2, (int)strlen(fp2), "../list16"); + free(fp1); + free(fp2); + + /* Test2h: start with "\\?\c:\" */ + mkfullpath(&fp1, &fp2, "aaa/file1", 7); + failure("fp1=%s, fp2=%s", fp1, fp2); + assertEqualInt(0, + systemf("%s -cf ../archive17.tar %s > ../out17 2> ../err17", + testprog, fp1)); + assertEqualInt(0, + systemf("%s -tf ../archive17.tar > ../list17", testprog)); + /* Check drive letters have been stripped. */ + assertFileContents(fp2, (int)strlen(fp2), "../list17"); + free(fp1); + free(fp2); +#else + skipping("Windows specific test"); +#endif /* _WIN32 && !__CYGWIN__ */ +} diff --git a/dependencies/libarchive-3.4.2/tar/util.c b/dependencies/libarchive-3.4.2/tar/util.c new file mode 100644 index 0000000..8ebec64 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/util.c @@ -0,0 +1,770 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "bsdtar_platform.h" +__FBSDID("$FreeBSD: src/usr.bin/tar/util.c,v 1.23 2008/12/15 06:00:25 kientzle Exp $"); + +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include /* Linux doesn't define mode_t, etc. in sys/stat.h. */ +#endif +#include +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_IO_H +#include +#endif +#ifdef HAVE_STDARG_H +#include +#endif +#ifdef HAVE_STDINT_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_WCTYPE_H +#include +#else +/* If we don't have wctype, we need to hack up some version of iswprint(). */ +#define iswprint isprint +#endif + +#include "bsdtar.h" +#include "err.h" +#include "passphrase.h" + +static size_t bsdtar_expand_char(char *, size_t, char); +static const char *strip_components(const char *path, int elements); + +#if defined(_WIN32) && !defined(__CYGWIN__) +#define read _read +#endif + +/* TODO: Hack up a version of mbtowc for platforms with no wide + * character support at all. I think the following might suffice, + * but it needs careful testing. + * #if !HAVE_MBTOWC + * #define mbtowc(wcp, p, n) ((*wcp = *p), 1) + * #endif + */ + +/* + * Print a string, taking care with any non-printable characters. + * + * Note that we use a stack-allocated buffer to receive the formatted + * string if we can. This is partly performance (avoiding a call to + * malloc()), partly out of expedience (we have to call vsnprintf() + * before malloc() anyway to find out how big a buffer we need; we may + * as well point that first call at a small local buffer in case it + * works), but mostly for safety (so we can use this to print messages + * about out-of-memory conditions). + */ + +void +safe_fprintf(FILE *f, const char *fmt, ...) +{ + char fmtbuff_stack[256]; /* Place to format the printf() string. */ + char outbuff[256]; /* Buffer for outgoing characters. */ + char *fmtbuff_heap; /* If fmtbuff_stack is too small, we use malloc */ + char *fmtbuff; /* Pointer to fmtbuff_stack or fmtbuff_heap. */ + int fmtbuff_length; + int length, n; + va_list ap; + const char *p; + unsigned i; + wchar_t wc; + char try_wc; + + /* Use a stack-allocated buffer if we can, for speed and safety. */ + fmtbuff_heap = NULL; + fmtbuff_length = sizeof(fmtbuff_stack); + fmtbuff = fmtbuff_stack; + + /* Try formatting into the stack buffer. */ + va_start(ap, fmt); + length = vsnprintf(fmtbuff, fmtbuff_length, fmt, ap); + va_end(ap); + + /* If the result was too large, allocate a buffer on the heap. */ + while (length < 0 || length >= fmtbuff_length) { + if (length >= fmtbuff_length) + fmtbuff_length = length+1; + else if (fmtbuff_length < 8192) + fmtbuff_length *= 2; + else if (fmtbuff_length < 1000000) + fmtbuff_length += fmtbuff_length / 4; + else { + length = fmtbuff_length; + fmtbuff_heap[length-1] = '\0'; + break; + } + free(fmtbuff_heap); + fmtbuff_heap = malloc(fmtbuff_length); + + /* Reformat the result into the heap buffer if we can. */ + if (fmtbuff_heap != NULL) { + fmtbuff = fmtbuff_heap; + va_start(ap, fmt); + length = vsnprintf(fmtbuff, fmtbuff_length, fmt, ap); + va_end(ap); + } else { + /* Leave fmtbuff pointing to the truncated + * string in fmtbuff_stack. */ + fmtbuff = fmtbuff_stack; + length = sizeof(fmtbuff_stack) - 1; + break; + } + } + + /* Note: mbrtowc() has a cleaner API, but mbtowc() seems a bit + * more portable, so we use that here instead. */ + if (mbtowc(NULL, NULL, 1) == -1) { /* Reset the shift state. */ + /* mbtowc() should never fail in practice, but + * handle the theoretical error anyway. */ + free(fmtbuff_heap); + return; + } + + /* Write data, expanding unprintable characters. */ + p = fmtbuff; + i = 0; + try_wc = 1; + while (*p != '\0') { + + /* Convert to wide char, test if the wide + * char is printable in the current locale. */ + if (try_wc && (n = mbtowc(&wc, p, length)) != -1) { + length -= n; + if (iswprint(wc) && wc != L'\\') { + /* Printable, copy the bytes through. */ + while (n-- > 0) + outbuff[i++] = *p++; + } else { + /* Not printable, format the bytes. */ + while (n-- > 0) + i += (unsigned)bsdtar_expand_char( + outbuff, i, *p++); + } + } else { + /* After any conversion failure, don't bother + * trying to convert the rest. */ + i += (unsigned)bsdtar_expand_char(outbuff, i, *p++); + try_wc = 0; + } + + /* If our output buffer is full, dump it and keep going. */ + if (i > (sizeof(outbuff) - 128)) { + outbuff[i] = '\0'; + fprintf(f, "%s", outbuff); + i = 0; + } + } + outbuff[i] = '\0'; + fprintf(f, "%s", outbuff); + + /* If we allocated a heap-based formatting buffer, free it now. */ + free(fmtbuff_heap); +} + +/* + * Render an arbitrary sequence of bytes into printable ASCII characters. + */ +static size_t +bsdtar_expand_char(char *buff, size_t offset, char c) +{ + size_t i = offset; + + if (isprint((unsigned char)c) && c != '\\') + buff[i++] = c; + else { + buff[i++] = '\\'; + switch (c) { + case '\a': buff[i++] = 'a'; break; + case '\b': buff[i++] = 'b'; break; + case '\f': buff[i++] = 'f'; break; + case '\n': buff[i++] = 'n'; break; +#if '\r' != '\n' + /* On some platforms, \n and \r are the same. */ + case '\r': buff[i++] = 'r'; break; +#endif + case '\t': buff[i++] = 't'; break; + case '\v': buff[i++] = 'v'; break; + case '\\': buff[i++] = '\\'; break; + default: + sprintf(buff + i, "%03o", 0xFF & (int)c); + i += 3; + } + } + + return (i - offset); +} + +int +yes(const char *fmt, ...) +{ + char buff[32]; + char *p; + ssize_t l; + + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, " (y/N)? "); + fflush(stderr); + + l = read(2, buff, sizeof(buff) - 1); + if (l < 0) { + fprintf(stderr, "Keyboard read failed\n"); + exit(1); + } + if (l == 0) + return (0); + buff[l] = 0; + + for (p = buff; *p != '\0'; p++) { + if (isspace((unsigned char)*p)) + continue; + switch(*p) { + case 'y': case 'Y': + return (1); + case 'n': case 'N': + return (0); + default: + return (0); + } + } + + return (0); +} + +/*- + * The logic here for -C attempts to avoid + * chdir() as long as possible. For example: + * "-C /foo -C /bar file" needs chdir("/bar") but not chdir("/foo") + * "-C /foo -C bar file" needs chdir("/foo/bar") + * "-C /foo -C bar /file1" does not need chdir() + * "-C /foo -C bar /file1 file2" needs chdir("/foo/bar") before file2 + * + * The only correct way to handle this is to record a "pending" chdir + * request and combine multiple requests intelligently until we + * need to process a non-absolute file. set_chdir() adds the new dir + * to the pending list; do_chdir() actually executes any pending chdir. + * + * This way, programs that build tar command lines don't have to worry + * about -C with non-existent directories; such requests will only + * fail if the directory must be accessed. + * + */ +void +set_chdir(struct bsdtar *bsdtar, const char *newdir) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + if (newdir[0] == '/' || newdir[0] == '\\' || + /* Detect this type, for example, "C:\" or "C:/" */ + (((newdir[0] >= 'a' && newdir[0] <= 'z') || + (newdir[0] >= 'A' && newdir[0] <= 'Z')) && + newdir[1] == ':' && (newdir[2] == '/' || newdir[2] == '\\'))) { +#else + if (newdir[0] == '/') { +#endif + /* The -C /foo -C /bar case; dump first one. */ + free(bsdtar->pending_chdir); + bsdtar->pending_chdir = NULL; + } + if (bsdtar->pending_chdir == NULL) + /* Easy case: no previously-saved dir. */ + bsdtar->pending_chdir = strdup(newdir); + else { + /* The -C /foo -C bar case; concatenate */ + char *old_pending = bsdtar->pending_chdir; + size_t old_len = strlen(old_pending); + bsdtar->pending_chdir = malloc(old_len + strlen(newdir) + 2); + if (old_pending[old_len - 1] == '/') + old_pending[old_len - 1] = '\0'; + if (bsdtar->pending_chdir != NULL) + sprintf(bsdtar->pending_chdir, "%s/%s", + old_pending, newdir); + free(old_pending); + } + if (bsdtar->pending_chdir == NULL) + lafe_errc(1, errno, "No memory"); +} + +void +do_chdir(struct bsdtar *bsdtar) +{ + if (bsdtar->pending_chdir == NULL) + return; + + if (chdir(bsdtar->pending_chdir) != 0) { + lafe_errc(1, 0, "could not chdir to '%s'\n", + bsdtar->pending_chdir); + } + free(bsdtar->pending_chdir); + bsdtar->pending_chdir = NULL; +} + +static const char * +strip_components(const char *p, int elements) +{ + /* Skip as many elements as necessary. */ + while (elements > 0) { + switch (*p++) { + case '/': +#if defined(_WIN32) && !defined(__CYGWIN__) + case '\\': /* Support \ path sep on Windows ONLY. */ +#endif + elements--; + break; + case '\0': + /* Path is too short, skip it. */ + return (NULL); + } + } + + /* Skip any / characters. This handles short paths that have + * additional / termination. This also handles the case where + * the logic above stops in the middle of a duplicate // + * sequence (which would otherwise get converted to an + * absolute path). */ + for (;;) { + switch (*p) { + case '/': +#if defined(_WIN32) && !defined(__CYGWIN__) + case '\\': /* Support \ path sep on Windows ONLY. */ +#endif + ++p; + break; + case '\0': + return (NULL); + default: + return (p); + } + } +} + +static void +warn_strip_leading_char(struct bsdtar *bsdtar, const char *c) +{ + if (!bsdtar->warned_lead_slash) { + lafe_warnc(0, + "Removing leading '%c' from member names", + c[0]); + bsdtar->warned_lead_slash = 1; + } +} + +static void +warn_strip_drive_letter(struct bsdtar *bsdtar) +{ + if (!bsdtar->warned_lead_slash) { + lafe_warnc(0, + "Removing leading drive letter from " + "member names"); + bsdtar->warned_lead_slash = 1; + } +} + +/* + * Convert absolute path to non-absolute path by skipping leading + * absolute path prefixes. + */ +static const char* +strip_absolute_path(struct bsdtar *bsdtar, const char *p) +{ + const char *rp; + + /* Remove leading "//./" or "//?/" or "//?/UNC/" + * (absolute path prefixes used by Windows API) */ + if ((p[0] == '/' || p[0] == '\\') && + (p[1] == '/' || p[1] == '\\') && + (p[2] == '.' || p[2] == '?') && + (p[3] == '/' || p[3] == '\\')) + { + if (p[2] == '?' && + (p[4] == 'U' || p[4] == 'u') && + (p[5] == 'N' || p[5] == 'n') && + (p[6] == 'C' || p[6] == 'c') && + (p[7] == '/' || p[7] == '\\')) + p += 8; + else + p += 4; + warn_strip_drive_letter(bsdtar); + } + + /* Remove multiple leading slashes and Windows drive letters. */ + do { + rp = p; + if (((p[0] >= 'a' && p[0] <= 'z') || + (p[0] >= 'A' && p[0] <= 'Z')) && + p[1] == ':') { + p += 2; + warn_strip_drive_letter(bsdtar); + } + + /* Remove leading "/../", "/./", "//", etc. */ + while (p[0] == '/' || p[0] == '\\') { + if (p[1] == '.' && + p[2] == '.' && + (p[3] == '/' || p[3] == '\\')) { + p += 3; /* Remove "/..", leave "/" for next pass. */ + } else if (p[1] == '.' && + (p[2] == '/' || p[2] == '\\')) { + p += 2; /* Remove "/.", leave "/" for next pass. */ + } else + p += 1; /* Remove "/". */ + warn_strip_leading_char(bsdtar, rp); + } + } while (rp != p); + + return (p); +} + +/* + * Handle --strip-components and any future path-rewriting options. + * Returns non-zero if the pathname should not be extracted. + * + * Note: The rewrites are applied uniformly to pathnames and hardlink + * names but not to symlink bodies. This is deliberate: Symlink + * bodies are not necessarily filenames. Even when they are, they + * need to be interpreted relative to the directory containing them, + * so simple rewrites like this are rarely appropriate. + * + * TODO: Support pax-style regex path rewrites. + */ +int +edit_pathname(struct bsdtar *bsdtar, struct archive_entry *entry) +{ + const char *name = archive_entry_pathname(entry); + const char *original_name = name; + const char *hardlinkname = archive_entry_hardlink(entry); + const char *original_hardlinkname = hardlinkname; +#if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H) + char *subst_name; + int r; + + /* Apply user-specified substitution to pathname. */ + r = apply_substitution(bsdtar, name, &subst_name, 0, 0); + if (r == -1) { + lafe_warnc(0, "Invalid substitution, skipping entry"); + return 1; + } + if (r == 1) { + archive_entry_copy_pathname(entry, subst_name); + if (*subst_name == '\0') { + free(subst_name); + return -1; + } else + free(subst_name); + name = archive_entry_pathname(entry); + original_name = name; + } + + /* Apply user-specified substitution to hardlink target. */ + if (hardlinkname != NULL) { + r = apply_substitution(bsdtar, hardlinkname, &subst_name, 0, 1); + if (r == -1) { + lafe_warnc(0, "Invalid substitution, skipping entry"); + return 1; + } + if (r == 1) { + archive_entry_copy_hardlink(entry, subst_name); + free(subst_name); + } + hardlinkname = archive_entry_hardlink(entry); + original_hardlinkname = hardlinkname; + } + + /* Apply user-specified substitution to symlink body. */ + if (archive_entry_symlink(entry) != NULL) { + r = apply_substitution(bsdtar, archive_entry_symlink(entry), &subst_name, 1, 0); + if (r == -1) { + lafe_warnc(0, "Invalid substitution, skipping entry"); + return 1; + } + if (r == 1) { + archive_entry_copy_symlink(entry, subst_name); + free(subst_name); + } + } +#endif + + /* Strip leading dir names as per --strip-components option. */ + if (bsdtar->strip_components > 0) { + name = strip_components(name, bsdtar->strip_components); + if (name == NULL) + return (1); + + if (hardlinkname != NULL) { + hardlinkname = strip_components(hardlinkname, + bsdtar->strip_components); + if (hardlinkname == NULL) + return (1); + } + } + + if ((bsdtar->flags & OPTFLAG_ABSOLUTE_PATHS) == 0) { + /* By default, don't write or restore absolute pathnames. */ + name = strip_absolute_path(bsdtar, name); + if (*name == '\0') + name = "."; + + if (hardlinkname != NULL) { + hardlinkname = strip_absolute_path(bsdtar, hardlinkname); + if (*hardlinkname == '\0') + return (1); + } + } else { + /* Strip redundant leading '/' characters. */ + while (name[0] == '/' && name[1] == '/') + name++; + } + + /* Replace name in archive_entry. */ + if (name != original_name) { + archive_entry_copy_pathname(entry, name); + } + if (hardlinkname != original_hardlinkname) { + archive_entry_copy_hardlink(entry, hardlinkname); + } + return (0); +} + +/* + * It would be nice to just use printf() for formatting large numbers, + * but the compatibility problems are quite a headache. Hence the + * following simple utility function. + */ +const char * +tar_i64toa(int64_t n0) +{ + static char buff[24]; + uint64_t n = n0 < 0 ? -n0 : n0; + char *p = buff + sizeof(buff); + + *--p = '\0'; + do { + *--p = '0' + (int)(n % 10); + } while (n /= 10); + if (n0 < 0) + *--p = '-'; + return p; +} + +/* + * Like strcmp(), but try to be a little more aware of the fact that + * we're comparing two paths. Right now, it just handles leading + * "./" and trailing '/' specially, so that "a/b/" == "./a/b" + * + * TODO: Make this better, so that "./a//b/./c/" == "a/b/c" + * TODO: After this works, push it down into libarchive. + * TODO: Publish the path normalization routines in libarchive so + * that bsdtar can normalize paths and use fast strcmp() instead + * of this. + * + * Note: This is currently only used within write.c, so should + * not handle \ path separators. + */ + +int +pathcmp(const char *a, const char *b) +{ + /* Skip leading './' */ + if (a[0] == '.' && a[1] == '/' && a[2] != '\0') + a += 2; + if (b[0] == '.' && b[1] == '/' && b[2] != '\0') + b += 2; + /* Find the first difference, or return (0) if none. */ + while (*a == *b) { + if (*a == '\0') + return (0); + a++; + b++; + } + /* + * If one ends in '/' and the other one doesn't, + * they're the same. + */ + if (a[0] == '/' && a[1] == '\0' && b[0] == '\0') + return (0); + if (a[0] == '\0' && b[0] == '/' && b[1] == '\0') + return (0); + /* They're really different, return the correct sign. */ + return (*(const unsigned char *)a - *(const unsigned char *)b); +} + +#define PPBUFF_SIZE 1024 +const char * +passphrase_callback(struct archive *a, void *_client_data) +{ + struct bsdtar *bsdtar = (struct bsdtar *)_client_data; + (void)a; /* UNUSED */ + + if (bsdtar->ppbuff == NULL) { + bsdtar->ppbuff = malloc(PPBUFF_SIZE); + if (bsdtar->ppbuff == NULL) + lafe_errc(1, errno, "Out of memory"); + } + return lafe_readpassphrase("Enter passphrase:", + bsdtar->ppbuff, PPBUFF_SIZE); +} + +void +passphrase_free(char *ppbuff) +{ + if (ppbuff != NULL) { + memset(ppbuff, 0, PPBUFF_SIZE); + free(ppbuff); + } +} + +/* + * Display information about the current file. + * + * The format here roughly duplicates the output of 'ls -l'. + * This is based on SUSv2, where 'tar tv' is documented as + * listing additional information in an "unspecified format," + * and 'pax -l' is documented as using the same format as 'ls -l'. + */ +void +list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry) +{ + char tmp[100]; + size_t w; + const char *p; + const char *fmt; + time_t tim; + static time_t now; + struct tm *ltime; +#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S) + struct tm tmbuf; +#endif +#if defined(HAVE__LOCALTIME64_S) + errno_t terr; + __time64_t tmptime; +#endif + + /* + * We avoid collecting the entire list in memory at once by + * listing things as we see them. However, that also means we can't + * just pre-compute the field widths. Instead, we start with guesses + * and just widen them as necessary. These numbers are completely + * arbitrary. + */ + if (!bsdtar->u_width) { + bsdtar->u_width = 6; + bsdtar->gs_width = 13; + } + if (!now) + time(&now); + fprintf(out, "%s %d ", + archive_entry_strmode(entry), + archive_entry_nlink(entry)); + + /* Use uname if it's present, else uid. */ + p = archive_entry_uname(entry); + if ((p == NULL) || (*p == '\0')) { + sprintf(tmp, "%lu ", + (unsigned long)archive_entry_uid(entry)); + p = tmp; + } + w = strlen(p); + if (w > bsdtar->u_width) + bsdtar->u_width = w; + fprintf(out, "%-*s ", (int)bsdtar->u_width, p); + + /* Use gname if it's present, else gid. */ + p = archive_entry_gname(entry); + if (p != NULL && p[0] != '\0') { + fprintf(out, "%s", p); + w = strlen(p); + } else { + sprintf(tmp, "%lu", + (unsigned long)archive_entry_gid(entry)); + w = strlen(tmp); + fprintf(out, "%s", tmp); + } + + /* + * Print device number or file size, right-aligned so as to make + * total width of group and devnum/filesize fields be gs_width. + * If gs_width is too small, grow it. + */ + if (archive_entry_filetype(entry) == AE_IFCHR + || archive_entry_filetype(entry) == AE_IFBLK) { + sprintf(tmp, "%lu,%lu", + (unsigned long)archive_entry_rdevmajor(entry), + (unsigned long)archive_entry_rdevminor(entry)); + } else { + strcpy(tmp, tar_i64toa(archive_entry_size(entry))); + } + if (w + strlen(tmp) >= bsdtar->gs_width) + bsdtar->gs_width = w+strlen(tmp)+1; + fprintf(out, "%*s", (int)(bsdtar->gs_width - w), tmp); + + /* Format the time using 'ls -l' conventions. */ + tim = archive_entry_mtime(entry); +#define HALF_YEAR (time_t)365 * 86400 / 2 +#if defined(_WIN32) && !defined(__CYGWIN__) +#define DAY_FMT "%d" /* Windows' strftime function does not support %e format. */ +#else +#define DAY_FMT "%e" /* Day number without leading zeros */ +#endif + if (tim < now - HALF_YEAR || tim > now + HALF_YEAR) + fmt = bsdtar->day_first ? DAY_FMT " %b %Y" : "%b " DAY_FMT " %Y"; + else + fmt = bsdtar->day_first ? DAY_FMT " %b %H:%M" : "%b " DAY_FMT " %H:%M"; +#if defined(HAVE_LOCALTIME_R) + ltime = localtime_r(&tim, &tmbuf); +#elif defined(HAVE__LOCALTIME64_S) + tmptime = tim; + terr = _localtime64_s(&tmbuf, &tmptime); + if (terr) + ltime = NULL; + else + ltime = &tmbuf; +#else + ltime = localtime(&tim); +#endif + strftime(tmp, sizeof(tmp), fmt, ltime); + fprintf(out, " %s ", tmp); + safe_fprintf(out, "%s", archive_entry_pathname(entry)); + + /* Extra information for links. */ + if (archive_entry_hardlink(entry)) /* Hard link */ + safe_fprintf(out, " link to %s", + archive_entry_hardlink(entry)); + else if (archive_entry_symlink(entry)) /* Symbolic link */ + safe_fprintf(out, " -> %s", archive_entry_symlink(entry)); +} diff --git a/dependencies/libarchive-3.4.2/tar/write.c b/dependencies/libarchive-3.4.2/tar/write.c new file mode 100644 index 0000000..09c44a3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/tar/write.c @@ -0,0 +1,1053 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "bsdtar_platform.h" +__FBSDID("$FreeBSD: src/usr.bin/tar/write.c,v 1.79 2008/11/27 05:49:52 kientzle Exp $"); + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_ATTR_XATTR_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_GRP_H +#include +#endif +#ifdef HAVE_IO_H +#include +#endif +#ifdef HAVE_LIBGEN_H +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_PATHS_H +#include +#endif +#ifdef HAVE_PWD_H +#include +#endif +#ifdef HAVE_STDINT_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "bsdtar.h" +#include "err.h" +#include "line_reader.h" + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +struct archive_dir_entry { + struct archive_dir_entry *next; + time_t mtime_sec; + int mtime_nsec; + char *name; +}; + +struct archive_dir { + struct archive_dir_entry *head, *tail; +}; + +static int append_archive(struct bsdtar *, struct archive *, + struct archive *ina); +static int append_archive_filename(struct bsdtar *, + struct archive *, const char *fname); +static void archive_names_from_file(struct bsdtar *bsdtar, + struct archive *a); +static int copy_file_data_block(struct bsdtar *, + struct archive *a, struct archive *, + struct archive_entry *); +static void excluded_callback(struct archive *, void *, + struct archive_entry *); +static void report_write(struct bsdtar *, struct archive *, + struct archive_entry *, int64_t progress); +static void test_for_append(struct bsdtar *); +static int metadata_filter(struct archive *, void *, + struct archive_entry *); +static void write_archive(struct archive *, struct bsdtar *); +static void write_entry(struct bsdtar *, struct archive *, + struct archive_entry *); +static void write_file(struct bsdtar *, struct archive *, + struct archive_entry *); +static void write_hierarchy(struct bsdtar *, struct archive *, + const char *); + +#if defined(_WIN32) && !defined(__CYGWIN__) +/* Not a full lseek() emulation, but enough for our needs here. */ +static int +seek_file(int fd, int64_t offset, int whence) +{ + LARGE_INTEGER distance; + (void)whence; /* UNUSED */ + distance.QuadPart = offset; + return (SetFilePointerEx((HANDLE)_get_osfhandle(fd), + distance, NULL, FILE_BEGIN) ? 1 : -1); +} +#define open _open +#define close _close +#define read _read +#ifdef lseek +#undef lseek +#endif +#define lseek seek_file +#endif + +static void +set_writer_options(struct bsdtar *bsdtar, struct archive *a) +{ + const char *writer_options; + int r; + + writer_options = getenv(ENV_WRITER_OPTIONS); + if (writer_options != NULL) { + size_t module_len = sizeof(IGNORE_WRONG_MODULE_NAME) - 1; + size_t opt_len = strlen(writer_options) + 1; + char *p; + /* Set default write options. */ + if ((p = malloc(module_len + opt_len)) == NULL) + lafe_errc(1, errno, "Out of memory"); + /* Prepend magic code to ignore options for + * a format or filters which are not added to + * the archive write object. */ + memcpy(p, IGNORE_WRONG_MODULE_NAME, module_len); + memcpy(p, writer_options, opt_len); + r = archive_write_set_options(a, p); + free(p); + if (r < ARCHIVE_WARN) + lafe_errc(1, 0, "%s", archive_error_string(a)); + else + archive_clear_error(a); + } + if (ARCHIVE_OK != archive_write_set_options(a, bsdtar->option_options)) + lafe_errc(1, 0, "%s", archive_error_string(a)); +} + +static void +set_reader_options(struct bsdtar *bsdtar, struct archive *a) +{ + const char *reader_options; + int r; + + (void)bsdtar; /* UNUSED */ + + reader_options = getenv(ENV_READER_OPTIONS); + if (reader_options != NULL) { + size_t module_len = sizeof(IGNORE_WRONG_MODULE_NAME) - 1; + size_t opt_len = strlen(reader_options) + 1; + char *p; + /* Set default write options. */ + if ((p = malloc(module_len + opt_len)) == NULL) + if (p == NULL) + lafe_errc(1, errno, "Out of memory"); + /* Prepend magic code to ignore options for + * a format or filters which are not added to + * the archive write object. */ + memcpy(p, IGNORE_WRONG_MODULE_NAME, module_len); + memcpy(p, reader_options, opt_len); + r = archive_read_set_options(a, p); + free(p); + if (r < ARCHIVE_WARN) + lafe_errc(1, 0, "%s", archive_error_string(a)); + else + archive_clear_error(a); + } +} + +void +tar_mode_c(struct bsdtar *bsdtar) +{ + struct archive *a; + const void *filter_name; + int r; + + if (*bsdtar->argv == NULL && bsdtar->names_from_file == NULL) + lafe_errc(1, 0, "no files or directories specified"); + + a = archive_write_new(); + + /* Support any format that the library supports. */ + if (cset_get_format(bsdtar->cset) == NULL) { + r = archive_write_set_format_pax_restricted(a); + cset_set_format(bsdtar->cset, "pax restricted"); + } else { + r = archive_write_set_format_by_name(a, + cset_get_format(bsdtar->cset)); + } + if (r != ARCHIVE_OK) { + fprintf(stderr, "Can't use format %s: %s\n", + cset_get_format(bsdtar->cset), + archive_error_string(a)); + usage(); + } + + archive_write_set_bytes_per_block(a, bsdtar->bytes_per_block); + archive_write_set_bytes_in_last_block(a, bsdtar->bytes_in_last_block); + + r = cset_write_add_filters(bsdtar->cset, a, &filter_name); + if (r < ARCHIVE_WARN) { + lafe_errc(1, 0, "Unsupported compression option --%s", + (const char *)filter_name); + } + + set_writer_options(bsdtar, a); + if (bsdtar->passphrase != NULL) + r = archive_write_set_passphrase(a, bsdtar->passphrase); + else + r = archive_write_set_passphrase_callback(a, bsdtar, + &passphrase_callback); + if (r != ARCHIVE_OK) + lafe_errc(1, 0, "%s", archive_error_string(a)); + if (ARCHIVE_OK != archive_write_open_filename(a, bsdtar->filename)) + lafe_errc(1, 0, "%s", archive_error_string(a)); + write_archive(a, bsdtar); +} + +/* + * Same as 'c', except we only support tar or empty formats in + * uncompressed files on disk. + */ +void +tar_mode_r(struct bsdtar *bsdtar) +{ + int64_t end_offset; + int format; + struct archive *a; + struct archive_entry *entry; + int r; + + /* Sanity-test some arguments and the file. */ + test_for_append(bsdtar); + + format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED; + +#if defined(__BORLANDC__) + bsdtar->fd = open(bsdtar->filename, O_RDWR | O_CREAT | O_BINARY); +#else + bsdtar->fd = open(bsdtar->filename, O_RDWR | O_CREAT | O_BINARY, 0666); +#endif + if (bsdtar->fd < 0) + lafe_errc(1, errno, + "Cannot open %s", bsdtar->filename); + + a = archive_read_new(); + archive_read_support_filter_all(a); + archive_read_support_format_empty(a); + archive_read_support_format_tar(a); + archive_read_support_format_gnutar(a); + set_reader_options(bsdtar, a); + r = archive_read_open_fd(a, bsdtar->fd, 10240); + if (r != ARCHIVE_OK) + lafe_errc(1, archive_errno(a), + "Can't read archive %s: %s", bsdtar->filename, + archive_error_string(a)); + while (0 == archive_read_next_header(a, &entry)) { + if (archive_filter_code(a, 0) != ARCHIVE_FILTER_NONE) { + archive_read_free(a); + close(bsdtar->fd); + lafe_errc(1, 0, + "Cannot append to compressed archive."); + } + /* Keep going until we hit end-of-archive */ + format = archive_format(a); + } + + end_offset = archive_read_header_position(a); + archive_read_free(a); + + /* Re-open archive for writing */ + a = archive_write_new(); + /* + * Set the format to be used for writing. To allow people to + * extend empty files, we need to allow them to specify the format, + * which opens the possibility that they will specify a format that + * doesn't match the existing format. Hence, the following bit + * of arcane ugliness. + */ + + if (cset_get_format(bsdtar->cset) != NULL) { + /* If the user requested a format, use that, but ... */ + archive_write_set_format_by_name(a, + cset_get_format(bsdtar->cset)); + /* ... complain if it's not compatible. */ + format &= ARCHIVE_FORMAT_BASE_MASK; + if (format != (int)(archive_format(a) & ARCHIVE_FORMAT_BASE_MASK) + && format != ARCHIVE_FORMAT_EMPTY) { + lafe_errc(1, 0, + "Format %s is incompatible with the archive %s.", + cset_get_format(bsdtar->cset), bsdtar->filename); + } + } else { + /* + * Just preserve the current format, with a little care + * for formats that libarchive can't write. + */ + if (format == ARCHIVE_FORMAT_EMPTY) + format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED; + archive_write_set_format(a, format); + } + if (lseek(bsdtar->fd, end_offset, SEEK_SET) < 0) + lafe_errc(1, errno, "Could not seek to archive end"); + set_writer_options(bsdtar, a); + if (ARCHIVE_OK != archive_write_open_fd(a, bsdtar->fd)) + lafe_errc(1, 0, "%s", archive_error_string(a)); + + write_archive(a, bsdtar); /* XXX check return val XXX */ + + close(bsdtar->fd); + bsdtar->fd = -1; +} + +void +tar_mode_u(struct bsdtar *bsdtar) +{ + int64_t end_offset; + struct archive *a; + struct archive_entry *entry; + int format; + struct archive_dir_entry *p; + struct archive_dir archive_dir; + + bsdtar->archive_dir = &archive_dir; + memset(&archive_dir, 0, sizeof(archive_dir)); + + format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED; + + /* Sanity-test some arguments and the file. */ + test_for_append(bsdtar); + + bsdtar->fd = open(bsdtar->filename, O_RDWR | O_BINARY); + if (bsdtar->fd < 0) + lafe_errc(1, errno, + "Cannot open %s", bsdtar->filename); + + a = archive_read_new(); + archive_read_support_filter_all(a); + archive_read_support_format_tar(a); + archive_read_support_format_gnutar(a); + set_reader_options(bsdtar, a); + if (archive_read_open_fd(a, bsdtar->fd, bsdtar->bytes_per_block) + != ARCHIVE_OK) { + lafe_errc(1, 0, + "Can't open %s: %s", bsdtar->filename, + archive_error_string(a)); + } + + /* Build a list of all entries and their recorded mod times. */ + while (0 == archive_read_next_header(a, &entry)) { + if (archive_filter_code(a, 0) != ARCHIVE_FILTER_NONE) { + archive_read_free(a); + close(bsdtar->fd); + lafe_errc(1, 0, + "Cannot append to compressed archive."); + } + if (archive_match_exclude_entry(bsdtar->matching, + ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER | + ARCHIVE_MATCH_EQUAL, entry) != ARCHIVE_OK) + lafe_errc(1, 0, "Error : %s", + archive_error_string(bsdtar->matching)); + /* Record the last format determination we see */ + format = archive_format(a); + /* Keep going until we hit end-of-archive */ + } + + end_offset = archive_read_header_position(a); + archive_read_free(a); + + /* Re-open archive for writing. */ + a = archive_write_new(); + /* + * Set format to same one auto-detected above. + */ + archive_write_set_format(a, format); + archive_write_set_bytes_per_block(a, bsdtar->bytes_per_block); + archive_write_set_bytes_in_last_block(a, bsdtar->bytes_in_last_block); + + if (lseek(bsdtar->fd, end_offset, SEEK_SET) < 0) + lafe_errc(1, errno, "Could not seek to archive end"); + set_writer_options(bsdtar, a); + if (ARCHIVE_OK != archive_write_open_fd(a, bsdtar->fd)) + lafe_errc(1, 0, "%s", archive_error_string(a)); + + write_archive(a, bsdtar); + + close(bsdtar->fd); + bsdtar->fd = -1; + + while (bsdtar->archive_dir->head != NULL) { + p = bsdtar->archive_dir->head->next; + free(bsdtar->archive_dir->head->name); + free(bsdtar->archive_dir->head); + bsdtar->archive_dir->head = p; + } + bsdtar->archive_dir->tail = NULL; +} + + +/* + * Write user-specified files/dirs to opened archive. + */ +static void +write_archive(struct archive *a, struct bsdtar *bsdtar) +{ + const char *arg; + struct archive_entry *entry, *sparse_entry; + + /* Choose a suitable copy buffer size */ + bsdtar->buff_size = 64 * 1024; + while (bsdtar->buff_size < (size_t)bsdtar->bytes_per_block) + bsdtar->buff_size *= 2; + /* Try to compensate for space we'll lose to alignment. */ + bsdtar->buff_size += 16 * 1024; + + /* Allocate a buffer for file data. */ + if ((bsdtar->buff = malloc(bsdtar->buff_size)) == NULL) + lafe_errc(1, 0, "cannot allocate memory"); + + if ((bsdtar->resolver = archive_entry_linkresolver_new()) == NULL) + lafe_errc(1, 0, "cannot create link resolver"); + archive_entry_linkresolver_set_strategy(bsdtar->resolver, + archive_format(a)); + + /* Create a read_disk object. */ + if ((bsdtar->diskreader = archive_read_disk_new()) == NULL) + lafe_errc(1, 0, "Cannot create read_disk object"); + /* Tell the read_disk how handle symlink. */ + switch (bsdtar->symlink_mode) { + case 'H': + archive_read_disk_set_symlink_hybrid(bsdtar->diskreader); + break; + case 'L': + archive_read_disk_set_symlink_logical(bsdtar->diskreader); + break; + default: + archive_read_disk_set_symlink_physical(bsdtar->diskreader); + break; + } + /* Register entry filters. */ + archive_read_disk_set_matching(bsdtar->diskreader, + bsdtar->matching, excluded_callback, bsdtar); + archive_read_disk_set_metadata_filter_callback( + bsdtar->diskreader, metadata_filter, bsdtar); + /* Set the behavior of archive_read_disk. */ + archive_read_disk_set_behavior(bsdtar->diskreader, + bsdtar->readdisk_flags); + archive_read_disk_set_standard_lookup(bsdtar->diskreader); + + if (bsdtar->names_from_file != NULL) + archive_names_from_file(bsdtar, a); + + while (*bsdtar->argv) { + arg = *bsdtar->argv; + if (arg[0] == '-' && arg[1] == 'C') { + arg += 2; + if (*arg == '\0') { + bsdtar->argv++; + arg = *bsdtar->argv; + if (arg == NULL) { + lafe_warnc(0, "%s", + "Missing argument for -C"); + bsdtar->return_value = 1; + goto cleanup; + } + if (*arg == '\0') { + lafe_warnc(0, + "Meaningless argument for -C: ''"); + bsdtar->return_value = 1; + goto cleanup; + } + } + set_chdir(bsdtar, arg); + } else { + if (*arg != '/') + do_chdir(bsdtar); /* Handle a deferred -C */ + if (*arg == '@') { + if (append_archive_filename(bsdtar, a, + arg + 1) != 0) + break; + } else + write_hierarchy(bsdtar, a, arg); + } + bsdtar->argv++; + } + + archive_read_disk_set_matching(bsdtar->diskreader, NULL, NULL, NULL); + archive_read_disk_set_metadata_filter_callback( + bsdtar->diskreader, NULL, NULL); + entry = NULL; + archive_entry_linkify(bsdtar->resolver, &entry, &sparse_entry); + while (entry != NULL) { + int r; + struct archive_entry *entry2; + struct archive *disk = bsdtar->diskreader; + + /* + * This tricky code here is to correctly read the contents + * of the entry because the disk reader bsdtar->diskreader + * is pointing at does not have any information about the + * entry by this time and using archive_read_data_block() + * with the disk reader consequently must fail. And we + * have to re-open the entry to read the contents. + */ + /* TODO: Work with -C option as well. */ + r = archive_read_disk_open(disk, + archive_entry_sourcepath(entry)); + if (r != ARCHIVE_OK) { + lafe_warnc(archive_errno(disk), + "%s", archive_error_string(disk)); + bsdtar->return_value = 1; + goto next_entry; + } + + /* + * Invoke archive_read_next_header2() to work + * archive_read_data_block(), which is called via write_file(), + * without failure. + */ + entry2 = archive_entry_new(); + r = archive_read_next_header2(disk, entry2); + archive_entry_free(entry2); + if (r != ARCHIVE_OK) { + lafe_warnc(archive_errno(disk), + "%s", archive_error_string(disk)); + if (r == ARCHIVE_FATAL) + bsdtar->return_value = 1; + archive_read_close(disk); + goto next_entry; + } + + write_file(bsdtar, a, entry); + archive_read_close(disk); +next_entry: + archive_entry_free(entry); + entry = NULL; + archive_entry_linkify(bsdtar->resolver, &entry, &sparse_entry); + } + + if (archive_write_close(a)) { + lafe_warnc(0, "%s", archive_error_string(a)); + bsdtar->return_value = 1; + } + +cleanup: + /* Free file data buffer. */ + free(bsdtar->buff); + archive_entry_linkresolver_free(bsdtar->resolver); + bsdtar->resolver = NULL; + archive_read_free(bsdtar->diskreader); + bsdtar->diskreader = NULL; + + if (bsdtar->flags & OPTFLAG_TOTALS) { + fprintf(stderr, "Total bytes written: %s\n", + tar_i64toa(archive_filter_bytes(a, -1))); + } + + archive_write_free(a); +} + +/* + * Archive names specified in file. + * + * Unless --null was specified, a line containing exactly "-C" will + * cause the next line to be a directory to pass to chdir(). If + * --null is specified, then a line "-C" is just another filename. + */ +static void +archive_names_from_file(struct bsdtar *bsdtar, struct archive *a) +{ + struct lafe_line_reader *lr; + const char *line; + + bsdtar->next_line_is_dir = 0; + + lr = lafe_line_reader(bsdtar->names_from_file, + (bsdtar->flags & OPTFLAG_NULL)); + while ((line = lafe_line_reader_next(lr)) != NULL) { + if (bsdtar->next_line_is_dir) { + if (*line != '\0') + set_chdir(bsdtar, line); + else { + lafe_warnc(0, + "Meaningless argument for -C: ''"); + bsdtar->return_value = 1; + } + bsdtar->next_line_is_dir = 0; + } else if (((bsdtar->flags & OPTFLAG_NULL) == 0) && + strcmp(line, "-C") == 0) + bsdtar->next_line_is_dir = 1; + else { + if (*line != '/') + do_chdir(bsdtar); /* Handle a deferred -C */ + write_hierarchy(bsdtar, a, line); + } + } + lafe_line_reader_free(lr); + if (bsdtar->next_line_is_dir) + lafe_errc(1, errno, + "Unexpected end of filename list; " + "directory expected after -C"); +} + +/* + * Copy from specified archive to current archive. Returns non-zero + * for write errors (which force us to terminate the entire archiving + * operation). If there are errors reading the input archive, we set + * bsdtar->return_value but return zero, so the overall archiving + * operation will complete and return non-zero. + */ +static int +append_archive_filename(struct bsdtar *bsdtar, struct archive *a, + const char *raw_filename) +{ + struct archive *ina; + const char *filename = raw_filename; + int rc; + + if (strcmp(filename, "-") == 0) + filename = NULL; /* Library uses NULL for stdio. */ + + ina = archive_read_new(); + archive_read_support_format_all(ina); + archive_read_support_filter_all(ina); + set_reader_options(bsdtar, ina); + archive_read_set_options(ina, "mtree:checkfs"); + if (bsdtar->passphrase != NULL) + rc = archive_read_add_passphrase(a, bsdtar->passphrase); + else + rc = archive_read_set_passphrase_callback(ina, bsdtar, + &passphrase_callback); + if (rc != ARCHIVE_OK) + lafe_errc(1, 0, "%s", archive_error_string(a)); + if (archive_read_open_filename(ina, filename, + bsdtar->bytes_per_block)) { + lafe_warnc(0, "%s", archive_error_string(ina)); + bsdtar->return_value = 1; + return (0); + } + + rc = append_archive(bsdtar, a, ina); + + if (rc != ARCHIVE_OK) { + lafe_warnc(0, "Error reading archive %s: %s", + raw_filename, archive_error_string(ina)); + bsdtar->return_value = 1; + } + archive_read_free(ina); + + return (rc); +} + +static int +append_archive(struct bsdtar *bsdtar, struct archive *a, struct archive *ina) +{ + struct archive_entry *in_entry; + int e; + + while (ARCHIVE_OK == (e = archive_read_next_header(ina, &in_entry))) { + if (archive_match_excluded(bsdtar->matching, in_entry)) + continue; + if ((bsdtar->flags & OPTFLAG_INTERACTIVE) && + !yes("copy '%s'", archive_entry_pathname(in_entry))) + continue; + if (bsdtar->verbose > 1) { + safe_fprintf(stderr, "a "); + list_item_verbose(bsdtar, stderr, in_entry); + } else if (bsdtar->verbose > 0) + safe_fprintf(stderr, "a %s", + archive_entry_pathname(in_entry)); + if (need_report()) + report_write(bsdtar, a, in_entry, 0); + + e = archive_write_header(a, in_entry); + if (e != ARCHIVE_OK) { + if (!bsdtar->verbose) + lafe_warnc(0, "%s: %s", + archive_entry_pathname(in_entry), + archive_error_string(a)); + else + fprintf(stderr, ": %s", archive_error_string(a)); + } + if (e == ARCHIVE_FATAL) + exit(1); + + if (e >= ARCHIVE_WARN) { + if (archive_entry_size(in_entry) == 0) + archive_read_data_skip(ina); + else if (copy_file_data_block(bsdtar, a, ina, in_entry)) + exit(1); + } + + if (bsdtar->verbose) + fprintf(stderr, "\n"); + } + + return (e == ARCHIVE_EOF ? ARCHIVE_OK : e); +} + +/* Helper function to copy file to archive. */ +static int +copy_file_data_block(struct bsdtar *bsdtar, struct archive *a, + struct archive *in_a, struct archive_entry *entry) +{ + size_t bytes_read; + ssize_t bytes_written; + int64_t offset, progress = 0; + char *null_buff = NULL; + const void *buff; + int r; + + while ((r = archive_read_data_block(in_a, &buff, + &bytes_read, &offset)) == ARCHIVE_OK) { + if (need_report()) + report_write(bsdtar, a, entry, progress); + + if (offset > progress) { + int64_t sparse = offset - progress; + size_t ns; + + if (null_buff == NULL) { + null_buff = bsdtar->buff; + memset(null_buff, 0, bsdtar->buff_size); + } + + while (sparse > 0) { + if (sparse > (int64_t)bsdtar->buff_size) + ns = bsdtar->buff_size; + else + ns = (size_t)sparse; + bytes_written = + archive_write_data(a, null_buff, ns); + if (bytes_written < 0) { + /* Write failed; this is bad */ + lafe_warnc(0, "%s", + archive_error_string(a)); + return (-1); + } + if ((size_t)bytes_written < ns) { + /* Write was truncated; warn but + * continue. */ + lafe_warnc(0, + "%s: Truncated write; file may " + "have grown while being archived.", + archive_entry_pathname(entry)); + return (0); + } + progress += bytes_written; + sparse -= bytes_written; + } + } + + bytes_written = archive_write_data(a, buff, bytes_read); + if (bytes_written < 0) { + /* Write failed; this is bad */ + lafe_warnc(0, "%s", archive_error_string(a)); + return (-1); + } + if ((size_t)bytes_written < bytes_read) { + /* Write was truncated; warn but continue. */ + lafe_warnc(0, + "%s: Truncated write; file may have grown " + "while being archived.", + archive_entry_pathname(entry)); + return (0); + } + progress += bytes_written; + } + if (r < ARCHIVE_WARN) { + lafe_warnc(archive_errno(a), "%s", archive_error_string(a)); + return (-1); + } + return (0); +} + +static void +excluded_callback(struct archive *a, void *_data, struct archive_entry *entry) +{ + struct bsdtar *bsdtar = (struct bsdtar *)_data; + + if (bsdtar->flags & OPTFLAG_NO_SUBDIRS) + return; + if (!archive_read_disk_can_descend(a)) + return; + if ((bsdtar->flags & OPTFLAG_INTERACTIVE) && + !yes("add '%s'", archive_entry_pathname(entry))) + return; + archive_read_disk_descend(a); +} + +static int +metadata_filter(struct archive *a, void *_data, struct archive_entry *entry) +{ + struct bsdtar *bsdtar = (struct bsdtar *)_data; + + /* XXX TODO: check whether this filesystem is + * synthetic and/or local. Add a new + * --local-only option to skip non-local + * filesystems. Skip synthetic filesystems + * regardless. + * + * The results should be cached, since + * tree.c doesn't usually visit a directory + * and the directory contents together. A simple + * move-to-front list should perform quite well. + * + * Use archive_read_disk_current_filesystem_is_remote(). + */ + + /* + * If the user vetoes this file/directory, skip it. + * We want this to be fairly late; if some other + * check would veto this file, we shouldn't bother + * the user with it. + */ + if ((bsdtar->flags & OPTFLAG_INTERACTIVE) && + !yes("add '%s'", archive_entry_pathname(entry))) + return (0); + + /* Note: if user vetoes, we won't descend. */ + if (((bsdtar->flags & OPTFLAG_NO_SUBDIRS) == 0) && + archive_read_disk_can_descend(a)) + archive_read_disk_descend(a); + + return (1); +} + +/* + * Add the file or dir hierarchy named by 'path' to the archive + */ +static void +write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path) +{ + struct archive *disk = bsdtar->diskreader; + struct archive_entry *entry = NULL, *spare_entry = NULL; + int r; + + r = archive_read_disk_open(disk, path); + if (r != ARCHIVE_OK) { + lafe_warnc(archive_errno(disk), + "%s", archive_error_string(disk)); + bsdtar->return_value = 1; + return; + } + bsdtar->first_fs = -1; + + for (;;) { + archive_entry_free(entry); + entry = archive_entry_new(); + r = archive_read_next_header2(disk, entry); + if (r == ARCHIVE_EOF) + break; + else if (r != ARCHIVE_OK) { + lafe_warnc(archive_errno(disk), + "%s", archive_error_string(disk)); + if (r == ARCHIVE_FATAL || r == ARCHIVE_FAILED) { + bsdtar->return_value = 1; + archive_entry_free(entry); + archive_read_close(disk); + return; + } else if (r < ARCHIVE_WARN) + continue; + } + + if (bsdtar->uid >= 0) { + archive_entry_set_uid(entry, bsdtar->uid); + if (!bsdtar->uname) + archive_entry_set_uname(entry, + archive_read_disk_uname(bsdtar->diskreader, + bsdtar->uid)); + } + if (bsdtar->gid >= 0) { + archive_entry_set_gid(entry, bsdtar->gid); + if (!bsdtar->gname) + archive_entry_set_gname(entry, + archive_read_disk_gname(bsdtar->diskreader, + bsdtar->gid)); + } + if (bsdtar->uname) + archive_entry_set_uname(entry, bsdtar->uname); + if (bsdtar->gname) + archive_entry_set_gname(entry, bsdtar->gname); + + /* + * Rewrite the pathname to be archived. If rewrite + * fails, skip the entry. + */ + if (edit_pathname(bsdtar, entry)) + continue; + + /* Display entry as we process it. */ + if (bsdtar->verbose > 1) { + safe_fprintf(stderr, "a "); + list_item_verbose(bsdtar, stderr, entry); + } else if (bsdtar->verbose > 0) { + /* This format is required by SUSv2. */ + safe_fprintf(stderr, "a %s", + archive_entry_pathname(entry)); + } + + /* Non-regular files get archived with zero size. */ + if (archive_entry_filetype(entry) != AE_IFREG) + archive_entry_set_size(entry, 0); + + archive_entry_linkify(bsdtar->resolver, &entry, &spare_entry); + + while (entry != NULL) { + write_file(bsdtar, a, entry); + archive_entry_free(entry); + entry = spare_entry; + spare_entry = NULL; + } + + if (bsdtar->verbose) + fprintf(stderr, "\n"); + } + archive_entry_free(entry); + archive_read_close(disk); +} + +/* + * Write a single file (or directory or other filesystem object) to + * the archive. + */ +static void +write_file(struct bsdtar *bsdtar, struct archive *a, + struct archive_entry *entry) +{ + write_entry(bsdtar, a, entry); +} + +/* + * Write a single entry to the archive. + */ +static void +write_entry(struct bsdtar *bsdtar, struct archive *a, + struct archive_entry *entry) +{ + int e; + + e = archive_write_header(a, entry); + if (e != ARCHIVE_OK) { + if (bsdtar->verbose > 1) { + safe_fprintf(stderr, "a "); + list_item_verbose(bsdtar, stderr, entry); + lafe_warnc(0, ": %s", archive_error_string(a)); + } else if (bsdtar->verbose > 0) { + lafe_warnc(0, "%s: %s", + archive_entry_pathname(entry), + archive_error_string(a)); + } else + fprintf(stderr, ": %s", archive_error_string(a)); + } + + if (e == ARCHIVE_FATAL) + exit(1); + + /* + * If we opened a file earlier, write it out now. Note that + * the format handler might have reset the size field to zero + * to inform us that the archive body won't get stored. In + * that case, just skip the write. + */ + if (e >= ARCHIVE_WARN && archive_entry_size(entry) > 0) { + if (copy_file_data_block(bsdtar, a, bsdtar->diskreader, entry)) + exit(1); + } +} + +static void +report_write(struct bsdtar *bsdtar, struct archive *a, + struct archive_entry *entry, int64_t progress) +{ + uint64_t comp, uncomp; + int compression; + + if (bsdtar->verbose) + fprintf(stderr, "\n"); + comp = archive_filter_bytes(a, -1); + uncomp = archive_filter_bytes(a, 0); + fprintf(stderr, "In: %d files, %s bytes;", + archive_file_count(a), tar_i64toa(uncomp)); + if (comp >= uncomp) + compression = 0; + else + compression = (int)((uncomp - comp) * 100 / uncomp); + fprintf(stderr, + " Out: %s bytes, compression %d%%\n", + tar_i64toa(comp), compression); + /* Can't have two calls to tar_i64toa() pending, so split the output. */ + safe_fprintf(stderr, "Current: %s (%s", + archive_entry_pathname(entry), + tar_i64toa(progress)); + fprintf(stderr, "/%s bytes)\n", + tar_i64toa(archive_entry_size(entry))); +} + +static void +test_for_append(struct bsdtar *bsdtar) +{ + struct stat s; + + if (*bsdtar->argv == NULL && bsdtar->names_from_file == NULL) + lafe_errc(1, 0, "no files or directories specified"); + if (bsdtar->filename == NULL) + lafe_errc(1, 0, "Cannot append to stdout."); + + if (stat(bsdtar->filename, &s) != 0) + return; + + if (!S_ISREG(s.st_mode) && !S_ISBLK(s.st_mode)) + lafe_errc(1, 0, + "Cannot append to %s: not a regular file.", + bsdtar->filename); + +/* Is this an appropriate check here on Windows? */ +/* + if (GetFileType(handle) != FILE_TYPE_DISK) + lafe_errc(1, 0, "Cannot append"); +*/ + +} diff --git a/dependencies/libarchive-3.4.2/test_utils/test_common.h b/dependencies/libarchive-3.4.2/test_utils/test_common.h new file mode 100644 index 0000000..80d54f0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/test_utils/test_common.h @@ -0,0 +1,470 @@ +/* + * Copyright (c) 2003-2017 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef TEST_COMMON_H +#define TEST_COMMON_H + +/* + * The goal of this file (and the matching test.c) is to + * simplify the very repetitive test-*.c test programs. + */ +#if defined(HAVE_CONFIG_H) +/* Most POSIX platforms use the 'configure' script to build config.h */ +#include "config.h" +#elif defined(__FreeBSD__) +/* Building as part of FreeBSD system requires a pre-built config.h. */ +#include "config_freebsd.h" +#elif defined(__NetBSD__) +/* Building as part of NetBSD system requires a pre-built config.h. */ +#include "config_netbsd.h" +#elif defined(_WIN32) && !defined(__CYGWIN__) +/* Win32 can't run the 'configure' script. */ +#include "config_windows.h" +#else +/* Warn if the library hasn't been (automatically or manually) configured. */ +#error Oops: No config.h and no pre-built configuration in test.h. +#endif + +#include /* Windows requires this before sys/stat.h */ +#include + +#if HAVE_DIRENT_H +#include +#endif +#ifdef HAVE_DIRECT_H +#include +#define dirent direct +#endif +#include +#include +#ifdef HAVE_IO_H +#include +#endif +#ifdef HAVE_STDINT_H +#include +#endif +#include +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#ifdef HAVE_ACL_LIBACL_H +#include +#endif +#ifdef HAVE_SYS_ACL_H +#include +#endif +#ifdef HAVE_SYS_RICHACL_H +#include +#endif +#ifdef HAVE_WINDOWS_H +#define NOCRYPT +#include +#include +#endif + +/* + * System-specific tweaks. We really want to minimize these + * as much as possible, since they make it harder to understand + * the mainline code. + */ + +/* Windows (including Visual Studio and MinGW but not Cygwin) */ +#if defined(_WIN32) && !defined(__CYGWIN__) +#if !defined(__BORLANDC__) +#undef chdir +#define chdir _chdir +#define strdup _strdup +#endif +#endif + +/* Visual Studio */ +#if defined(_MSC_VER) && _MSC_VER < 1900 +#define snprintf sprintf_s +#endif + +#if defined(__BORLANDC__) +#pragma warn -8068 /* Constant out of range in comparison. */ +#endif + + +#if defined(__GNUC__) && (__GNUC__ > 2 || \ + (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)) +# ifdef __MINGW_PRINTF_FORMAT +# define __LA_PRINTF_FORMAT __MINGW_PRINTF_FORMAT +# else +# define __LA_PRINTF_FORMAT __printf__ +# endif +# define __LA_PRINTFLIKE(f,a) __attribute__((__format__(__LA_PRINTF_FORMAT, f, a))) +#else +# define __LA_PRINTFLIKE(f,a) +#endif + +/* Haiku OS and QNX */ +#if defined(__HAIKU__) || defined(__QNXNTO__) +/* Haiku and QNX have typedefs in stdint.h (needed for int64_t) */ +#include +#endif + +/* Get a real definition for __FBSDID if we can */ +#if HAVE_SYS_CDEFS_H +#include +#endif + +/* If not, define it so as to avoid dangling semicolons. */ +#ifndef __FBSDID +#define __FBSDID(a) struct _undefined_hack +#endif + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +#ifndef __LIBARCHIVE_TEST_COMMON +#define __LIBARCHIVE_TEST_COMMON +#endif + +#include "archive_platform_acl.h" +#define ARCHIVE_TEST_ACL_TYPE_POSIX1E 1 +#define ARCHIVE_TEST_ACL_TYPE_NFS4 2 + +#include "archive_platform_xattr.h" + +/* + * Redefine DEFINE_TEST for use in defining the test functions. + */ +#undef DEFINE_TEST +#define DEFINE_TEST(name) void name(void); void name(void) + +/* An implementation of the standard assert() macro */ +#define assert(e) assertion_assert(__FILE__, __LINE__, (e), #e, NULL) +/* chdir() and error if it fails */ +#define assertChdir(path) \ + assertion_chdir(__FILE__, __LINE__, path) +/* Assert two files have the same file flags */ +#define assertEqualFflags(patha, pathb) \ + assertion_compare_fflags(__FILE__, __LINE__, patha, pathb, 0) +/* Assert two integers are the same. Reports value of each one if not. */ +#define assertEqualInt(v1,v2) \ + assertion_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL) +/* Assert two strings are the same. Reports value of each one if not. */ +#define assertEqualString(v1,v2) \ + assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL, 0) +#define assertEqualUTF8String(v1,v2) \ + assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL, 1) +/* As above, but v1 and v2 are wchar_t * */ +#define assertEqualWString(v1,v2) \ + assertion_equal_wstring(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL) +/* As above, but raw blocks of bytes. */ +#define assertEqualMem(v1, v2, l) \ + assertion_equal_mem(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (l), #l, NULL) +/* Assert that memory is full of a specified byte */ +#define assertMemoryFilledWith(v1, l, b) \ + assertion_memory_filled_with(__FILE__, __LINE__, (v1), #v1, (l), #l, (b), #b, NULL) +/* Assert two files are the same. */ +#define assertEqualFile(f1, f2) \ + assertion_equal_file(__FILE__, __LINE__, (f1), (f2)) +/* Assert that a file is empty. */ +#define assertEmptyFile(pathname) \ + assertion_empty_file(__FILE__, __LINE__, (pathname)) +/* Assert that a file is not empty. */ +#define assertNonEmptyFile(pathname) \ + assertion_non_empty_file(__FILE__, __LINE__, (pathname)) +#define assertFileAtime(pathname, sec, nsec) \ + assertion_file_atime(__FILE__, __LINE__, pathname, sec, nsec) +#define assertFileAtimeRecent(pathname) \ + assertion_file_atime_recent(__FILE__, __LINE__, pathname) +#define assertFileBirthtime(pathname, sec, nsec) \ + assertion_file_birthtime(__FILE__, __LINE__, pathname, sec, nsec) +#define assertFileBirthtimeRecent(pathname) \ + assertion_file_birthtime_recent(__FILE__, __LINE__, pathname) +/* Assert that a file exists; supports printf-style arguments. */ +#define assertFileExists(pathname) \ + assertion_file_exists(__FILE__, __LINE__, pathname) +/* Assert that a file exists. */ +#define assertFileNotExists(pathname) \ + assertion_file_not_exists(__FILE__, __LINE__, pathname) +/* Assert that file contents match a string. */ +#define assertFileContents(data, data_size, pathname) \ + assertion_file_contents(__FILE__, __LINE__, data, data_size, pathname) +/* Verify that a file does not contain invalid strings */ +#define assertFileContainsNoInvalidStrings(pathname, strings) \ + assertion_file_contains_no_invalid_strings(__FILE__, __LINE__, pathname, strings) +#define assertFileMtime(pathname, sec, nsec) \ + assertion_file_mtime(__FILE__, __LINE__, pathname, sec, nsec) +#define assertFileMtimeRecent(pathname) \ + assertion_file_mtime_recent(__FILE__, __LINE__, pathname) +#define assertFileNLinks(pathname, nlinks) \ + assertion_file_nlinks(__FILE__, __LINE__, pathname, nlinks) +#define assertFileSize(pathname, size) \ + assertion_file_size(__FILE__, __LINE__, pathname, size) +#define assertFileMode(pathname, mode) \ + assertion_file_mode(__FILE__, __LINE__, pathname, mode) +#define assertTextFileContents(text, pathname) \ + assertion_text_file_contents(__FILE__, __LINE__, text, pathname) +#define assertFileContainsLinesAnyOrder(pathname, lines) \ + assertion_file_contains_lines_any_order(__FILE__, __LINE__, pathname, lines) +#define assertIsDir(pathname, mode) \ + assertion_is_dir(__FILE__, __LINE__, pathname, mode) +#define assertIsHardlink(path1, path2) \ + assertion_is_hardlink(__FILE__, __LINE__, path1, path2) +#define assertIsNotHardlink(path1, path2) \ + assertion_is_not_hardlink(__FILE__, __LINE__, path1, path2) +#define assertIsReg(pathname, mode) \ + assertion_is_reg(__FILE__, __LINE__, pathname, mode) +#define assertIsSymlink(pathname, contents, isdir) \ + assertion_is_symlink(__FILE__, __LINE__, pathname, contents, isdir) +/* Create a directory, report error if it fails. */ +#define assertMakeDir(dirname, mode) \ + assertion_make_dir(__FILE__, __LINE__, dirname, mode) +#define assertMakeFile(path, mode, contents) \ + assertion_make_file(__FILE__, __LINE__, path, mode, -1, contents) +#define assertMakeBinFile(path, mode, csize, contents) \ + assertion_make_file(__FILE__, __LINE__, path, mode, csize, contents) +#define assertMakeHardlink(newfile, oldfile) \ + assertion_make_hardlink(__FILE__, __LINE__, newfile, oldfile) +#define assertMakeSymlink(newfile, linkto, targetIsDir) \ + assertion_make_symlink(__FILE__, __LINE__, newfile, linkto, targetIsDir) +#define assertSetNodump(path) \ + assertion_set_nodump(__FILE__, __LINE__, path) +#define assertUmask(mask) \ + assertion_umask(__FILE__, __LINE__, mask) +/* Assert that two files have unequal file flags */ +#define assertUnequalFflags(patha, pathb) \ + assertion_compare_fflags(__FILE__, __LINE__, patha, pathb, 1) +#define assertUtimes(pathname, atime, atime_nsec, mtime, mtime_nsec) \ + assertion_utimes(__FILE__, __LINE__, pathname, atime, atime_nsec, mtime, mtime_nsec) +#ifndef PROGRAM +#define assertEntrySetAcls(entry, acls, count) \ + assertion_entry_set_acls(__FILE__, __LINE__, entry, acls, count) +#define assertEntryCompareAcls(entry, acls, count, type, mode) \ + assertion_entry_compare_acls(__FILE__, __LINE__, entry, acls, count, type, mode) +#endif + +/* + * This would be simple with C99 variadic macros, but I don't want to + * require that. Instead, I insert a function call before each + * skipping() call to pass the file and line information down. Crude, + * but effective. + */ +#define skipping \ + skipping_setup(__FILE__, __LINE__);test_skipping + +/* Function declarations. These are defined in test_utility.c. */ +void failure(const char *fmt, ...) __LA_PRINTFLIKE(1, 2); +int assertion_assert(const char *, int, int, const char *, void *); +int assertion_chdir(const char *, int, const char *); +int assertion_compare_fflags(const char *, int, const char *, const char *, + int); +int assertion_empty_file(const char *, int, const char *); +int assertion_equal_file(const char *, int, const char *, const char *); +int assertion_equal_int(const char *, int, long long, const char *, long long, const char *, void *); +int assertion_equal_mem(const char *, int, const void *, const char *, const void *, const char *, size_t, const char *, void *); +int assertion_memory_filled_with(const char *, int, const void *, const char *, size_t, const char *, char, const char *, void *); +int assertion_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *, int); +int assertion_equal_wstring(const char *, int, const wchar_t *v1, const char *, const wchar_t *v2, const char *, void *); +int assertion_file_atime(const char *, int, const char *, long, long); +int assertion_file_atime_recent(const char *, int, const char *); +int assertion_file_birthtime(const char *, int, const char *, long, long); +int assertion_file_birthtime_recent(const char *, int, const char *); +int assertion_file_contains_lines_any_order(const char *, int, const char *, const char **); +int assertion_file_contains_no_invalid_strings(const char *, int, const char *, const char **); +int assertion_file_contents(const char *, int, const void *, int, const char *); +int assertion_file_exists(const char *, int, const char *); +int assertion_file_mode(const char *, int, const char *, int); +int assertion_file_mtime(const char *, int, const char *, long, long); +int assertion_file_mtime_recent(const char *, int, const char *); +int assertion_file_nlinks(const char *, int, const char *, int); +int assertion_file_not_exists(const char *, int, const char *); +int assertion_file_size(const char *, int, const char *, long); +int assertion_is_dir(const char *, int, const char *, int); +int assertion_is_hardlink(const char *, int, const char *, const char *); +int assertion_is_not_hardlink(const char *, int, const char *, const char *); +int assertion_is_reg(const char *, int, const char *, int); +int assertion_is_symlink(const char *, int, const char *, const char *, int); +int assertion_make_dir(const char *, int, const char *, int); +int assertion_make_file(const char *, int, const char *, int, int, const void *); +int assertion_make_hardlink(const char *, int, const char *newpath, const char *); +int assertion_make_symlink(const char *, int, const char *newpath, const char *, int); +int assertion_non_empty_file(const char *, int, const char *); +int assertion_set_nodump(const char *, int, const char *); +int assertion_text_file_contents(const char *, int, const char *buff, const char *f); +int assertion_umask(const char *, int, int); +int assertion_utimes(const char *, int, const char *, long, long, long, long ); +int assertion_version(const char*, int, const char *, const char *); + +void skipping_setup(const char *, int); +void test_skipping(const char *fmt, ...) __LA_PRINTFLIKE(1, 2); + +/* Like sprintf, then system() */ +int systemf(const char *fmt, ...) __LA_PRINTFLIKE(1, 2); + +/* Delay until time() returns a value after this. */ +void sleepUntilAfter(time_t); + +/* Return true if this platform can create symlinks. */ +int canSymlink(void); + +/* Return true if this platform can run the "bzip2" program. */ +int canBzip2(void); + +/* Return true if this platform can run the "grzip" program. */ +int canGrzip(void); + +/* Return true if this platform can run the "gzip" program. */ +int canGzip(void); + +/* Return true if this platform can run the specified command. */ +int canRunCommand(const char *); + +/* Return true if this platform can run the "lrzip" program. */ +int canLrzip(void); + +/* Return true if this platform can run the "lz4" program. */ +int canLz4(void); + +/* Return true if this platform can run the "zstd" program. */ +int canZstd(void); + +/* Return true if this platform can run the "lzip" program. */ +int canLzip(void); + +/* Return true if this platform can run the "lzma" program. */ +int canLzma(void); + +/* Return true if this platform can run the "lzop" program. */ +int canLzop(void); + +/* Return true if this platform can run the "xz" program. */ +int canXz(void); + +/* Return true if this filesystem can handle nodump flags. */ +int canNodump(void); + +/* Set test ACLs */ +int setTestAcl(const char *path); + +/* Get extended attribute */ +void *getXattr(const char *, const char *, size_t *); + +/* Set extended attribute */ +int setXattr(const char *, const char *, const void *, size_t); + +/* Return true if the file has large i-node number(>0xffffffff). */ +int is_LargeInode(const char *); + +#if ARCHIVE_ACL_SUNOS +/* Fetch ACLs on Solaris using acl() or facl() */ +void *sunacl_get(int cmd, int *aclcnt, int fd, const char *path); +#endif + +/* Suck file into string allocated via malloc(). Call free() when done. */ +/* Supports printf-style args: slurpfile(NULL, "%s/myfile", refdir); */ +char *slurpfile(size_t *, const char *fmt, ...) __LA_PRINTFLIKE(2, 3); + +/* Dump block of bytes to a file. */ +void dumpfile(const char *filename, void *, size_t); + +/* Extracts named reference file to the current directory. */ +void extract_reference_file(const char *); +/* Copies named reference file to the current directory. */ +void copy_reference_file(const char *); + +/* Extracts a list of files to the current directory. + * List must be NULL terminated. + */ +void extract_reference_files(const char **); + +/* Subtract umask from mode */ +mode_t umasked(mode_t expected_mode); + +/* Path to working directory for current test */ +extern const char *testworkdir; + +#ifndef PROGRAM +/* + * Special interfaces for libarchive test harness. + */ + +#include "archive.h" +#include "archive_entry.h" + +/* ACL structure */ +struct archive_test_acl_t { + int type; /* Type of ACL */ + int permset; /* Permissions for this class of users. */ + int tag; /* Owner, User, Owning group, group, other, etc. */ + int qual; /* GID or UID of user/group, depending on tag. */ + const char *name; /* Name of user/group, depending on tag. */ +}; + +/* Set ACLs */ +int assertion_entry_set_acls(const char *, int, struct archive_entry *, + struct archive_test_acl_t *, int); + +/* Compare ACLs */ +int assertion_entry_compare_acls(const char *, int, struct archive_entry *, + struct archive_test_acl_t *, int, int, int); + +/* Special customized read-from-memory interface. */ +int read_open_memory(struct archive *, const void *, size_t, size_t); +/* _minimal version exercises a slightly different set of libarchive APIs. */ +int read_open_memory_minimal(struct archive *, const void *, size_t, size_t); +/* _seek version produces a seekable file. */ +int read_open_memory_seek(struct archive *, const void *, size_t, size_t); + +/* Versions of above that accept an archive argument for additional info. */ +#define assertA(e) assertion_assert(__FILE__, __LINE__, (e), #e, (a)) +#define assertEqualIntA(a,v1,v2) \ + assertion_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (a)) +#define assertEqualStringA(a,v1,v2) \ + assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (a), 0) + +#else /* defined(PROGRAM) */ +/* + * Special interfaces for program test harness. + */ + +/* Pathname of exe to be tested. */ +extern const char *testprogfile; +/* Name of exe to use in printf-formatted command strings. */ +/* On Windows, this includes leading/trailing quotes. */ +extern const char *testprog; + +void assertVersion(const char *prog, const char *base); + +#endif /* defined(PROGRAM) */ + +#ifdef USE_DMALLOC +#include +#endif + +#endif /* TEST_COMMON_H */ diff --git a/dependencies/libarchive-3.4.2/test_utils/test_main.c b/dependencies/libarchive-3.4.2/test_utils/test_main.c new file mode 100644 index 0000000..7b8aa70 --- /dev/null +++ b/dependencies/libarchive-3.4.2/test_utils/test_main.c @@ -0,0 +1,4103 @@ +/* + * Copyright (c) 2003-2009 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +#include "test_utils.h" +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif +#include +#ifdef HAVE_ICONV_H +#include +#endif +/* + * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h. + * As the include guards don't agree, the order of include is important. + */ +#ifdef HAVE_LINUX_EXT2_FS_H +#include /* for Linux file flags */ +#endif +#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__) +#include /* Linux file flags, broken on Cygwin */ +#endif +#ifdef HAVE_LINUX_FS_H +#include +#endif +#include +#include +#ifdef HAVE_SIGNAL_H +#include +#endif +#include +#include + +#ifdef HAVE_SIGNAL_H +#endif +#ifdef HAVE_ACL_LIBACL_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_ACL_H +#include +#endif +#ifdef HAVE_SYS_EA_H +#include +#endif +#ifdef HAVE_SYS_EXTATTR_H +#include +#endif +#if HAVE_SYS_XATTR_H +#include +#elif HAVE_ATTR_XATTR_H +#include +#endif +#ifdef HAVE_SYS_RICHACL_H +#include +#endif +#if HAVE_MEMBERSHIP_H +#include +#endif + +/* + * + * Windows support routines + * + * Note: Configuration is a tricky issue. Using HAVE_* feature macros + * in the test harness is dangerous because they cover up + * configuration errors. The classic example of this is omitting a + * configure check. If libarchive and libarchive_test both look for + * the same feature macro, such errors are hard to detect. Platform + * macros (e.g., _WIN32 or __GNUC__) are a little better, but can + * easily lead to very messy code. It's best to limit yourself + * to only the most generic programming techniques in the test harness + * and thus avoid conditionals altogether. Where that's not possible, + * try to minimize conditionals by grouping platform-specific tests in + * one place (e.g., test_acl_freebsd) or by adding new assert() + * functions (e.g., assertMakeHardlink()) to cover up platform + * differences. Platform-specific coding in libarchive_test is often + * a symptom that some capability is missing from libarchive itself. + */ +#if defined(_WIN32) && !defined(__CYGWIN__) +#include +#include +#include +#ifndef F_OK +#define F_OK (0) +#endif +#ifndef S_ISDIR +#define S_ISDIR(m) ((m) & _S_IFDIR) +#endif +#ifndef S_ISREG +#define S_ISREG(m) ((m) & _S_IFREG) +#endif +#if !defined(__BORLANDC__) +#define access _access +#undef chdir +#define chdir _chdir +#endif +#ifndef fileno +#define fileno _fileno +#endif +/*#define fstat _fstat64*/ +#if !defined(__BORLANDC__) +#define getcwd _getcwd +#endif +#define lstat stat +/*#define lstat _stat64*/ +/*#define stat _stat64*/ +#define rmdir _rmdir +#if !defined(__BORLANDC__) +#define strdup _strdup +#define umask _umask +#endif +#define int64_t __int64 +#endif + +#if defined(HAVE__CrtSetReportMode) +# include +#endif + +mode_t umasked(mode_t expected_mode) +{ + mode_t mode = umask(0); + umask(mode); + return expected_mode & ~mode; +} + +/* Path to working directory for current test */ +const char *testworkdir; +#ifdef PROGRAM +/* Pathname of exe to be tested. */ +const char *testprogfile; +/* Name of exe to use in printf-formatted command strings. */ +/* On Windows, this includes leading/trailing quotes. */ +const char *testprog; +#endif + +#if defined(_WIN32) && !defined(__CYGWIN__) +static void *GetFunctionKernel32(const char *); +static int my_CreateSymbolicLinkA(const char *, const char *, int); +static int my_CreateHardLinkA(const char *, const char *); +static int my_GetFileInformationByName(const char *, + BY_HANDLE_FILE_INFORMATION *); + +typedef struct _REPARSE_DATA_BUFFER { + ULONG ReparseTag; + USHORT ReparseDataLength; + USHORT Reserved; + union { + struct { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + ULONG Flags; + WCHAR PathBuffer[1]; + } SymbolicLinkReparseBuffer; + struct { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + WCHAR PathBuffer[1]; + } MountPointReparseBuffer; + struct { + UCHAR DataBuffer[1]; + } GenericReparseBuffer; + } DUMMYUNIONNAME; +} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; + +static void * +GetFunctionKernel32(const char *name) +{ + static HINSTANCE lib; + static int set; + if (!set) { + set = 1; + lib = LoadLibrary("kernel32.dll"); + } + if (lib == NULL) { + fprintf(stderr, "Can't load kernel32.dll?!\n"); + exit(1); + } + return (void *)GetProcAddress(lib, name); +} + +static int +my_CreateSymbolicLinkA(const char *linkname, const char *target, + int targetIsDir) +{ + static BOOLEAN (WINAPI *f)(LPCSTR, LPCSTR, DWORD); + DWORD attrs; + static int set; + int ret, tmpflags, llen, tlen; + int flags = 0; + char *src, *tgt, *p; + if (!set) { + set = 1; + f = GetFunctionKernel32("CreateSymbolicLinkA"); + } + if (f == NULL) + return (0); + + tlen = strlen(target); + llen = strlen(linkname); + + if (tlen == 0 || llen == 0) + return (0); + + tgt = malloc((tlen + 1) * sizeof(char)); + if (tgt == NULL) + return (0); + src = malloc((llen + 1) * sizeof(char)); + if (src == NULL) { + free(tgt); + return (0); + } + + /* + * Translate slashes to backslashes + */ + p = src; + while(*linkname != '\0') { + if (*linkname == '/') + *p = '\\'; + else + *p = *linkname; + linkname++; + p++; + } + *p = '\0'; + + p = tgt; + while(*target != '\0') { + if (*target == '/') + *p = '\\'; + else + *p = *target; + target++; + p++; + } + *p = '\0'; + + /* + * Each test has to specify if a file or a directory symlink + * should be created. + */ + if (targetIsDir) { +#if defined(SYMBOLIC_LINK_FLAG_DIRECTORY) + flags |= SYMBOLIC_LINK_FLAG_DIRECTORY; +#else + flags |= 0x1; +#endif + } + +#if defined(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) + tmpflags = flags | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE; +#else + tmpflags = flags | 0x2; +#endif + /* + * Windows won't overwrite existing links + */ + attrs = GetFileAttributesA(linkname); + if (attrs != INVALID_FILE_ATTRIBUTES) { + if (attrs & FILE_ATTRIBUTE_DIRECTORY) + RemoveDirectoryA(linkname); + else + DeleteFileA(linkname); + } + + ret = (*f)(src, tgt, tmpflags); + /* + * Prior to Windows 10 the SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE + * is not understood + */ + if (!ret) + ret = (*f)(src, tgt, flags); + + free(src); + free(tgt); + return (ret); +} + +static int +my_CreateHardLinkA(const char *linkname, const char *target) +{ + static BOOLEAN (WINAPI *f)(LPCSTR, LPCSTR, LPSECURITY_ATTRIBUTES); + static int set; + if (!set) { + set = 1; + f = GetFunctionKernel32("CreateHardLinkA"); + } + return f == NULL ? 0 : (*f)(linkname, target, NULL); +} + +static int +my_GetFileInformationByName(const char *path, BY_HANDLE_FILE_INFORMATION *bhfi) +{ + HANDLE h; + int r; + + memset(bhfi, 0, sizeof(*bhfi)); + h = CreateFile(path, FILE_READ_ATTRIBUTES, 0, NULL, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (h == INVALID_HANDLE_VALUE) + return (0); + r = GetFileInformationByHandle(h, bhfi); + CloseHandle(h); + return (r); +} +#endif + +#if defined(HAVE__CrtSetReportMode) && !defined(__WATCOMC__) +static void +invalid_parameter_handler(const wchar_t * expression, + const wchar_t * function, const wchar_t * file, + unsigned int line, uintptr_t pReserved) +{ + /* nop */ + // Silence unused-parameter compiler warnings. + (void)expression; + (void)function; + (void)file; + (void)line; + (void)pReserved; +} +#endif + +/* + * + * OPTIONS FLAGS + * + */ + +/* Enable core dump on failure. */ +static int dump_on_failure = 0; +/* Default is to remove temp dirs and log data for successful tests. */ +static int keep_temp_files = 0; +/* Default is to run the specified tests once and report errors. */ +static int until_failure = 0; +/* Default is to just report pass/fail for each test. */ +static int verbosity = 0; +#define VERBOSITY_SUMMARY_ONLY -1 /* -q */ +#define VERBOSITY_PASSFAIL 0 /* Default */ +#define VERBOSITY_LIGHT_REPORT 1 /* -v */ +#define VERBOSITY_FULL 2 /* -vv */ +/* A few places generate even more output for verbosity > VERBOSITY_FULL, + * mostly for debugging the test harness itself. */ +/* Cumulative count of assertion failures. */ +static int failures = 0; +/* Cumulative count of reported skips. */ +static int skips = 0; +/* Cumulative count of assertions checked. */ +static int assertions = 0; + +/* Directory where uuencoded reference files can be found. */ +static const char *refdir; + +/* + * Report log information selectively to console and/or disk log. + */ +static int log_console = 0; +static FILE *logfile; +static void __LA_PRINTFLIKE(1, 0) +vlogprintf(const char *fmt, va_list ap) +{ +#ifdef va_copy + va_list lfap; + va_copy(lfap, ap); +#endif + if (log_console) + vfprintf(stdout, fmt, ap); + if (logfile != NULL) +#ifdef va_copy + vfprintf(logfile, fmt, lfap); + va_end(lfap); +#else + vfprintf(logfile, fmt, ap); +#endif +} + +static void __LA_PRINTFLIKE(1, 2) +logprintf(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vlogprintf(fmt, ap); + va_end(ap); +} + +/* Set up a message to display only if next assertion fails. */ +static char msgbuff[4096]; +static const char *msg, *nextmsg; +void +failure(const char *fmt, ...) +{ + va_list ap; + if (fmt == NULL) { + nextmsg = NULL; + } else { + va_start(ap, fmt); + vsprintf(msgbuff, fmt, ap); + va_end(ap); + nextmsg = msgbuff; + } +} + +/* + * Copy arguments into file-local variables. + * This was added to permit vararg assert() functions without needing + * variadic wrapper macros. Turns out that the vararg capability is almost + * never used, so almost all of the vararg assertions can be simplified + * by removing the vararg capability and reworking the wrapper macro to + * pass __FILE__, __LINE__ directly into the function instead of using + * this hook. I suspect this machinery is used so rarely that we + * would be better off just removing it entirely. That would simplify + * the code here noticeably. + */ +static const char *skipping_filename; +static int skipping_line; +void skipping_setup(const char *filename, int line) +{ + skipping_filename = filename; + skipping_line = line; +} + +/* Called at the beginning of each assert() function. */ +static void +assertion_count(const char *file, int line) +{ + (void)file; /* UNUSED */ + (void)line; /* UNUSED */ + ++assertions; + /* Proper handling of "failure()" message. */ + msg = nextmsg; + nextmsg = NULL; + /* Uncomment to print file:line after every assertion. + * Verbose, but occasionally useful in tracking down crashes. */ + /* printf("Checked %s:%d\n", file, line); */ +} + +/* + * For each test source file, we remember how many times each + * assertion was reported. Cleared before each new test, + * used by test_summarize(). + */ +static struct line { + int count; + int skip; +} failed_lines[10000]; +const char *failed_filename; + +/* Count this failure, setup up log destination and handle initial report. */ +static void __LA_PRINTFLIKE(3, 4) +failure_start(const char *filename, int line, const char *fmt, ...) +{ + va_list ap; + + /* Record another failure for this line. */ + ++failures; + failed_filename = filename; + failed_lines[line].count++; + + /* Determine whether to log header to console. */ + switch (verbosity) { + case VERBOSITY_LIGHT_REPORT: + log_console = (failed_lines[line].count < 2); + break; + default: + log_console = (verbosity >= VERBOSITY_FULL); + } + + /* Log file:line header for this failure */ + va_start(ap, fmt); +#if _MSC_VER + logprintf("%s(%d): ", filename, line); +#else + logprintf("%s:%d: ", filename, line); +#endif + vlogprintf(fmt, ap); + va_end(ap); + logprintf("\n"); + + if (msg != NULL && msg[0] != '\0') { + logprintf(" Description: %s\n", msg); + msg = NULL; + } + + /* Determine whether to log details to console. */ + if (verbosity == VERBOSITY_LIGHT_REPORT) + log_console = 0; +} + +/* Complete reporting of failed tests. */ +/* + * The 'extra' hook here is used by libarchive to include libarchive + * error messages with assertion failures. It could also be used + * to add strerror() output, for example. Just define the EXTRA_DUMP() + * macro appropriately. + */ +static void +failure_finish(void *extra) +{ + (void)extra; /* UNUSED (maybe) */ +#ifdef EXTRA_DUMP + if (extra != NULL) { + logprintf(" errno: %d\n", EXTRA_ERRNO(extra)); + logprintf(" detail: %s\n", EXTRA_DUMP(extra)); + } +#endif + + if (dump_on_failure) { + fprintf(stderr, + " *** forcing core dump so failure can be debugged ***\n"); + abort(); + } +} + +/* Inform user that we're skipping some checks. */ +void +test_skipping(const char *fmt, ...) +{ + char buff[1024]; + va_list ap; + + va_start(ap, fmt); + vsprintf(buff, fmt, ap); + va_end(ap); + /* Use failure() message if set. */ + msg = nextmsg; + nextmsg = NULL; + /* failure_start() isn't quite right, but is awfully convenient. */ + failure_start(skipping_filename, skipping_line, "SKIPPING: %s", buff); + --failures; /* Undo failures++ in failure_start() */ + /* Don't failure_finish() here. */ + /* Mark as skip, so doesn't count as failed test. */ + failed_lines[skipping_line].skip = 1; + ++skips; +} + +/* + * + * ASSERTIONS + * + */ + +/* Generic assert() just displays the failed condition. */ +int +assertion_assert(const char *file, int line, int value, + const char *condition, void *extra) +{ + assertion_count(file, line); + if (!value) { + failure_start(file, line, "Assertion failed: %s", condition); + failure_finish(extra); + } + return (value); +} + +/* chdir() and report any errors */ +int +assertion_chdir(const char *file, int line, const char *pathname) +{ + assertion_count(file, line); + if (chdir(pathname) == 0) + return (1); + failure_start(file, line, "chdir(\"%s\")", pathname); + failure_finish(NULL); + return (0); + +} + +/* Verify two integers are equal. */ +int +assertion_equal_int(const char *file, int line, + long long v1, const char *e1, long long v2, const char *e2, void *extra) +{ + assertion_count(file, line); + if (v1 == v2) + return (1); + failure_start(file, line, "%s != %s", e1, e2); + logprintf(" %s=%lld (0x%llx, 0%llo)\n", e1, v1, v1, v1); + logprintf(" %s=%lld (0x%llx, 0%llo)\n", e2, v2, v2, v2); + failure_finish(extra); + return (0); +} + +/* + * Utility to convert a single UTF-8 sequence. + */ +static int +_utf8_to_unicode(uint32_t *pwc, const char *s, size_t n) +{ + static const char utf8_count[256] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 00 - 0F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 10 - 1F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20 - 2F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 30 - 3F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40 - 4F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 50 - 5F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 60 - 6F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 70 - 7F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 80 - 8F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 90 - 9F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* A0 - AF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* B0 - BF */ + 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,/* C0 - CF */ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,/* D0 - DF */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,/* E0 - EF */ + 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* F0 - FF */ + }; + int ch; + int cnt; + uint32_t wc; + + *pwc = 0; + + /* Sanity check. */ + if (n == 0) + return (0); + /* + * Decode 1-4 bytes depending on the value of the first byte. + */ + ch = (unsigned char)*s; + if (ch == 0) + return (0); /* Standard: return 0 for end-of-string. */ + cnt = utf8_count[ch]; + + /* Invalid sequence or there are not plenty bytes. */ + if (n < (size_t)cnt) + return (-1); + + /* Make a Unicode code point from a single UTF-8 sequence. */ + switch (cnt) { + case 1: /* 1 byte sequence. */ + *pwc = ch & 0x7f; + return (cnt); + case 2: /* 2 bytes sequence. */ + if ((s[1] & 0xc0) != 0x80) return (-1); + *pwc = ((ch & 0x1f) << 6) | (s[1] & 0x3f); + return (cnt); + case 3: /* 3 bytes sequence. */ + if ((s[1] & 0xc0) != 0x80) return (-1); + if ((s[2] & 0xc0) != 0x80) return (-1); + wc = ((ch & 0x0f) << 12) + | ((s[1] & 0x3f) << 6) + | (s[2] & 0x3f); + if (wc < 0x800) + return (-1);/* Overlong sequence. */ + break; + case 4: /* 4 bytes sequence. */ + if (n < 4) + return (-1); + if ((s[1] & 0xc0) != 0x80) return (-1); + if ((s[2] & 0xc0) != 0x80) return (-1); + if ((s[3] & 0xc0) != 0x80) return (-1); + wc = ((ch & 0x07) << 18) + | ((s[1] & 0x3f) << 12) + | ((s[2] & 0x3f) << 6) + | (s[3] & 0x3f); + if (wc < 0x10000) + return (-1);/* Overlong sequence. */ + break; + default: + return (-1); + } + + /* The code point larger than 0x10FFFF is not legal + * Unicode values. */ + if (wc > 0x10FFFF) + return (-1); + /* Correctly gets a Unicode, returns used bytes. */ + *pwc = wc; + return (cnt); +} + +static void strdump(const char *e, const char *p, int ewidth, int utf8) +{ + const char *q = p; + + logprintf(" %*s = ", ewidth, e); + if (p == NULL) { + logprintf("NULL\n"); + return; + } + logprintf("\""); + while (*p != '\0') { + unsigned int c = 0xff & *p++; + switch (c) { + case '\a': logprintf("\\a"); break; + case '\b': logprintf("\\b"); break; + case '\n': logprintf("\\n"); break; + case '\r': logprintf("\\r"); break; + default: + if (c >= 32 && c < 127) + logprintf("%c", c); + else + logprintf("\\x%02X", c); + } + } + logprintf("\""); + logprintf(" (length %d)", q == NULL ? -1 : (int)strlen(q)); + + /* + * If the current string is UTF-8, dump its code points. + */ + if (utf8) { + size_t len; + uint32_t uc; + int n; + int cnt = 0; + + p = q; + len = strlen(p); + logprintf(" ["); + while ((n = _utf8_to_unicode(&uc, p, len)) > 0) { + if (p != q) + logprintf(" "); + logprintf("%04X", uc); + p += n; + len -= n; + cnt++; + } + logprintf("]"); + logprintf(" (count %d", cnt); + if (n < 0) { + logprintf(",unknown %zu bytes", len); + } + logprintf(")"); + + } + logprintf("\n"); +} + +/* Verify two strings are equal, dump them if not. */ +int +assertion_equal_string(const char *file, int line, + const char *v1, const char *e1, + const char *v2, const char *e2, + void *extra, int utf8) +{ + int l1, l2; + + assertion_count(file, line); + if (v1 == v2 || (v1 != NULL && v2 != NULL && strcmp(v1, v2) == 0)) + return (1); + failure_start(file, line, "%s != %s", e1, e2); + l1 = (int)strlen(e1); + l2 = (int)strlen(e2); + if (l1 < l2) + l1 = l2; + strdump(e1, v1, l1, utf8); + strdump(e2, v2, l1, utf8); + failure_finish(extra); + return (0); +} + +static void +wcsdump(const char *e, const wchar_t *w) +{ + logprintf(" %s = ", e); + if (w == NULL) { + logprintf("(null)"); + return; + } + logprintf("\""); + while (*w != L'\0') { + unsigned int c = *w++; + if (c >= 32 && c < 127) + logprintf("%c", c); + else if (c < 256) + logprintf("\\x%02X", c); + else if (c < 0x10000) + logprintf("\\u%04X", c); + else + logprintf("\\U%08X", c); + } + logprintf("\"\n"); +} + +#ifndef HAVE_WCSCMP +static int +wcscmp(const wchar_t *s1, const wchar_t *s2) +{ + + while (*s1 == *s2++) { + if (*s1++ == L'\0') + return 0; + } + if (*s1 > *--s2) + return 1; + else + return -1; +} +#endif + +/* Verify that two wide strings are equal, dump them if not. */ +int +assertion_equal_wstring(const char *file, int line, + const wchar_t *v1, const char *e1, + const wchar_t *v2, const char *e2, + void *extra) +{ + assertion_count(file, line); + if (v1 == v2) + return (1); + if (v1 != NULL && v2 != NULL && wcscmp(v1, v2) == 0) + return (1); + failure_start(file, line, "%s != %s", e1, e2); + wcsdump(e1, v1); + wcsdump(e2, v2); + failure_finish(extra); + return (0); +} + +/* + * Pretty standard hexdump routine. As a bonus, if ref != NULL, then + * any bytes in p that differ from ref will be highlighted with '_' + * before and after the hex value. + */ +static void +hexdump(const char *p, const char *ref, size_t l, size_t offset) +{ + size_t i, j; + char sep; + + if (p == NULL) { + logprintf("(null)\n"); + return; + } + for(i=0; i < l; i+=16) { + logprintf("%04x", (unsigned)(i + offset)); + sep = ' '; + for (j = 0; j < 16 && i + j < l; j++) { + if (ref != NULL && p[i + j] != ref[i + j]) + sep = '_'; + logprintf("%c%02x", sep, 0xff & (int)p[i+j]); + if (ref != NULL && p[i + j] == ref[i + j]) + sep = ' '; + } + for (; j < 16; j++) { + logprintf("%c ", sep); + sep = ' '; + } + logprintf("%c", sep); + for (j=0; j < 16 && i + j < l; j++) { + int c = p[i + j]; + if (c >= ' ' && c <= 126) + logprintf("%c", c); + else + logprintf("."); + } + logprintf("\n"); + } +} + +/* Verify that two blocks of memory are the same, display the first + * block of differences if they're not. */ +int +assertion_equal_mem(const char *file, int line, + const void *_v1, const char *e1, + const void *_v2, const char *e2, + size_t l, const char *ld, void *extra) +{ + const char *v1 = (const char *)_v1; + const char *v2 = (const char *)_v2; + size_t offset; + + assertion_count(file, line); + if (v1 == v2 || (v1 != NULL && v2 != NULL && memcmp(v1, v2, l) == 0)) + return (1); + if (v1 == NULL || v2 == NULL) + return (0); + + failure_start(file, line, "%s != %s", e1, e2); + logprintf(" size %s = %d\n", ld, (int)l); + /* Dump 48 bytes (3 lines) so that the first difference is + * in the second line. */ + offset = 0; + while (l > 64 && memcmp(v1, v2, 32) == 0) { + /* Two lines agree, so step forward one line. */ + v1 += 16; + v2 += 16; + l -= 16; + offset += 16; + } + logprintf(" Dump of %s\n", e1); + hexdump(v1, v2, l < 128 ? l : 128, offset); + logprintf(" Dump of %s\n", e2); + hexdump(v2, v1, l < 128 ? l : 128, offset); + logprintf("\n"); + failure_finish(extra); + return (0); +} + +/* Verify that a block of memory is filled with the specified byte. */ +int +assertion_memory_filled_with(const char *file, int line, + const void *_v1, const char *vd, + size_t l, const char *ld, + char b, const char *bd, void *extra) +{ + const char *v1 = (const char *)_v1; + size_t c = 0; + size_t i; + (void)ld; /* UNUSED */ + + assertion_count(file, line); + + for (i = 0; i < l; ++i) { + if (v1[i] == b) { + ++c; + } + } + if (c == l) + return (1); + + failure_start(file, line, "%s (size %d) not filled with %s", vd, (int)l, bd); + logprintf(" Only %d bytes were correct\n", (int)c); + failure_finish(extra); + return (0); +} + +/* Verify that the named file exists and is empty. */ +int +assertion_empty_file(const char *filename, int line, const char *f1) +{ + char buff[1024]; + struct stat st; + ssize_t s; + FILE *f; + + assertion_count(filename, line); + + if (stat(f1, &st) != 0) { + failure_start(filename, line, "Stat failed: %s", f1); + failure_finish(NULL); + return (0); + } + if (st.st_size == 0) + return (1); + + failure_start(filename, line, "File should be empty: %s", f1); + logprintf(" File size: %d\n", (int)st.st_size); + logprintf(" Contents:\n"); + f = fopen(f1, "rb"); + if (f == NULL) { + logprintf(" Unable to open %s\n", f1); + } else { + s = ((off_t)sizeof(buff) < st.st_size) ? + (ssize_t)sizeof(buff) : (ssize_t)st.st_size; + s = fread(buff, 1, s, f); + hexdump(buff, NULL, s, 0); + fclose(f); + } + failure_finish(NULL); + return (0); +} + +/* Verify that the named file exists and is not empty. */ +int +assertion_non_empty_file(const char *filename, int line, const char *f1) +{ + struct stat st; + + assertion_count(filename, line); + + if (stat(f1, &st) != 0) { + failure_start(filename, line, "Stat failed: %s", f1); + failure_finish(NULL); + return (0); + } + if (st.st_size == 0) { + failure_start(filename, line, "File empty: %s", f1); + failure_finish(NULL); + return (0); + } + return (1); +} + +/* Verify that two files have the same contents. */ +/* TODO: hexdump the first bytes that actually differ. */ +int +assertion_equal_file(const char *filename, int line, const char *fn1, const char *fn2) +{ + char buff1[1024]; + char buff2[1024]; + FILE *f1, *f2; + int n1, n2; + + assertion_count(filename, line); + + f1 = fopen(fn1, "rb"); + f2 = fopen(fn2, "rb"); + if (f1 == NULL || f2 == NULL) { + if (f1) fclose(f1); + if (f2) fclose(f2); + return (0); + } + for (;;) { + n1 = (int)fread(buff1, 1, sizeof(buff1), f1); + n2 = (int)fread(buff2, 1, sizeof(buff2), f2); + if (n1 != n2) + break; + if (n1 == 0 && n2 == 0) { + fclose(f1); + fclose(f2); + return (1); + } + if (memcmp(buff1, buff2, n1) != 0) + break; + } + fclose(f1); + fclose(f2); + failure_start(filename, line, "Files not identical"); + logprintf(" file1=\"%s\"\n", fn1); + logprintf(" file2=\"%s\"\n", fn2); + failure_finish(NULL); + return (0); +} + +/* Verify that the named file does exist. */ +int +assertion_file_exists(const char *filename, int line, const char *f) +{ + assertion_count(filename, line); + +#if defined(_WIN32) && !defined(__CYGWIN__) + if (!_access(f, 0)) + return (1); +#else + if (!access(f, F_OK)) + return (1); +#endif + failure_start(filename, line, "File should exist: %s", f); + failure_finish(NULL); + return (0); +} + +/* Verify that the named file doesn't exist. */ +int +assertion_file_not_exists(const char *filename, int line, const char *f) +{ + assertion_count(filename, line); + +#if defined(_WIN32) && !defined(__CYGWIN__) + if (_access(f, 0)) + return (1); +#else + if (access(f, F_OK)) + return (1); +#endif + failure_start(filename, line, "File should not exist: %s", f); + failure_finish(NULL); + return (0); +} + +/* Compare the contents of a file to a block of memory. */ +int +assertion_file_contents(const char *filename, int line, const void *buff, int s, const char *fn) +{ + char *contents; + FILE *f; + int n; + + assertion_count(filename, line); + + f = fopen(fn, "rb"); + if (f == NULL) { + failure_start(filename, line, + "File should exist: %s", fn); + failure_finish(NULL); + return (0); + } + contents = malloc(s * 2); + n = (int)fread(contents, 1, s * 2, f); + fclose(f); + if (n == s && memcmp(buff, contents, s) == 0) { + free(contents); + return (1); + } + failure_start(filename, line, "File contents don't match"); + logprintf(" file=\"%s\"\n", fn); + if (n > 0) + hexdump(contents, buff, n > 512 ? 512 : n, 0); + else { + logprintf(" File empty, contents should be:\n"); + hexdump(buff, NULL, s > 512 ? 512 : s, 0); + } + failure_finish(NULL); + free(contents); + return (0); +} + +/* Check the contents of a text file, being tolerant of line endings. */ +int +assertion_text_file_contents(const char *filename, int line, const char *buff, const char *fn) +{ + char *contents; + const char *btxt, *ftxt; + FILE *f; + int n, s; + + assertion_count(filename, line); + f = fopen(fn, "r"); + if (f == NULL) { + failure_start(filename, line, + "File doesn't exist: %s", fn); + failure_finish(NULL); + return (0); + } + s = (int)strlen(buff); + contents = malloc(s * 2 + 128); + n = (int)fread(contents, 1, s * 2 + 128 - 1, f); + if (n >= 0) + contents[n] = '\0'; + fclose(f); + /* Compare texts. */ + btxt = buff; + ftxt = (const char *)contents; + while (*btxt != '\0' && *ftxt != '\0') { + if (*btxt == *ftxt) { + ++btxt; + ++ftxt; + continue; + } + if (btxt[0] == '\n' && ftxt[0] == '\r' && ftxt[1] == '\n') { + /* Pass over different new line characters. */ + ++btxt; + ftxt += 2; + continue; + } + break; + } + if (*btxt == '\0' && *ftxt == '\0') { + free(contents); + return (1); + } + failure_start(filename, line, "Contents don't match"); + logprintf(" file=\"%s\"\n", fn); + if (n > 0) { + hexdump(contents, buff, n, 0); + logprintf(" expected\n"); + hexdump(buff, contents, s, 0); + } else { + logprintf(" File empty, contents should be:\n"); + hexdump(buff, NULL, s, 0); + } + failure_finish(NULL); + free(contents); + return (0); +} + +/* Verify that a text file contains the specified lines, regardless of order */ +/* This could be more efficient if we sorted both sets of lines, etc, but + * since this is used only for testing and only ever deals with a dozen or so + * lines at a time, this relatively crude approach is just fine. */ +int +assertion_file_contains_lines_any_order(const char *file, int line, + const char *pathname, const char *lines[]) +{ + char *buff; + size_t buff_size; + size_t expected_count, actual_count, i, j; + char **expected = NULL; + char *p, **actual = NULL; + char c; + int expected_failure = 0, actual_failure = 0; + + assertion_count(file, line); + + buff = slurpfile(&buff_size, "%s", pathname); + if (buff == NULL) { + failure_start(pathname, line, "Can't read file: %s", pathname); + failure_finish(NULL); + return (0); + } + + /* Make a copy of the provided lines and count up the expected + * file size. */ + for (i = 0; lines[i] != NULL; ++i) { + } + expected_count = i; + if (expected_count) { + expected = malloc(sizeof(char *) * expected_count); + if (expected == NULL) { + failure_start(pathname, line, "Can't allocate memory"); + failure_finish(NULL); + free(expected); + free(buff); + return (0); + } + for (i = 0; lines[i] != NULL; ++i) { + expected[i] = strdup(lines[i]); + } + } + + /* Break the file into lines */ + actual_count = 0; + for (c = '\0', p = buff; p < buff + buff_size; ++p) { + if (*p == '\x0d' || *p == '\x0a') + *p = '\0'; + if (c == '\0' && *p != '\0') + ++actual_count; + c = *p; + } + if (actual_count) { + actual = calloc(sizeof(char *), actual_count); + if (actual == NULL) { + failure_start(pathname, line, "Can't allocate memory"); + failure_finish(NULL); + free(expected); + free(buff); + return (0); + } + for (j = 0, p = buff; p < buff + buff_size; + p += 1 + strlen(p)) { + if (*p != '\0') { + actual[j] = p; + ++j; + } + } + } + + /* Erase matching lines from both lists */ + for (i = 0; i < expected_count; ++i) { + if (expected[i] == NULL) + continue; + for (j = 0; j < actual_count; ++j) { + if (actual[j] == NULL) + continue; + if (strcmp(expected[i], actual[j]) == 0) { + free(expected[i]); + expected[i] = NULL; + actual[j] = NULL; + break; + } + } + } + + /* If there's anything left, it's a failure */ + for (i = 0; i < expected_count; ++i) { + if (expected[i] != NULL) + ++expected_failure; + } + for (j = 0; j < actual_count; ++j) { + if (actual[j] != NULL) + ++actual_failure; + } + if (expected_failure == 0 && actual_failure == 0) { + free(buff); + free(expected); + free(actual); + return (1); + } + failure_start(file, line, "File doesn't match: %s", pathname); + for (i = 0; i < expected_count; ++i) { + if (expected[i] != NULL) { + logprintf(" Expected but not present: %s\n", expected[i]); + free(expected[i]); + } + } + for (j = 0; j < actual_count; ++j) { + if (actual[j] != NULL) + logprintf(" Present but not expected: %s\n", actual[j]); + } + failure_finish(NULL); + free(buff); + free(expected); + free(actual); + return (0); +} + +/* Verify that a text file does not contains the specified strings */ +int +assertion_file_contains_no_invalid_strings(const char *file, int line, + const char *pathname, const char *strings[]) +{ + char *buff; + int i; + + buff = slurpfile(NULL, "%s", pathname); + if (buff == NULL) { + failure_start(file, line, "Can't read file: %s", pathname); + failure_finish(NULL); + return (0); + } + + for (i = 0; strings[i] != NULL; ++i) { + if (strstr(buff, strings[i]) != NULL) { + failure_start(file, line, "Invalid string in %s: %s", pathname, + strings[i]); + failure_finish(NULL); + free(buff); + return(0); + } + } + + free(buff); + return (0); +} + +/* Test that two paths point to the same file. */ +/* As a side-effect, asserts that both files exist. */ +static int +is_hardlink(const char *file, int line, + const char *path1, const char *path2) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + BY_HANDLE_FILE_INFORMATION bhfi1, bhfi2; + int r; + + assertion_count(file, line); + r = my_GetFileInformationByName(path1, &bhfi1); + if (r == 0) { + failure_start(file, line, "File %s can't be inspected?", path1); + failure_finish(NULL); + return (0); + } + r = my_GetFileInformationByName(path2, &bhfi2); + if (r == 0) { + failure_start(file, line, "File %s can't be inspected?", path2); + failure_finish(NULL); + return (0); + } + return (bhfi1.dwVolumeSerialNumber == bhfi2.dwVolumeSerialNumber + && bhfi1.nFileIndexHigh == bhfi2.nFileIndexHigh + && bhfi1.nFileIndexLow == bhfi2.nFileIndexLow); +#else + struct stat st1, st2; + int r; + + assertion_count(file, line); + r = lstat(path1, &st1); + if (r != 0) { + failure_start(file, line, "File should exist: %s", path1); + failure_finish(NULL); + return (0); + } + r = lstat(path2, &st2); + if (r != 0) { + failure_start(file, line, "File should exist: %s", path2); + failure_finish(NULL); + return (0); + } + return (st1.st_ino == st2.st_ino && st1.st_dev == st2.st_dev); +#endif +} + +int +assertion_is_hardlink(const char *file, int line, + const char *path1, const char *path2) +{ + if (is_hardlink(file, line, path1, path2)) + return (1); + failure_start(file, line, + "Files %s and %s are not hardlinked", path1, path2); + failure_finish(NULL); + return (0); +} + +int +assertion_is_not_hardlink(const char *file, int line, + const char *path1, const char *path2) +{ + if (!is_hardlink(file, line, path1, path2)) + return (1); + failure_start(file, line, + "Files %s and %s should not be hardlinked", path1, path2); + failure_finish(NULL); + return (0); +} + +/* Verify a/b/mtime of 'pathname'. */ +/* If 'recent', verify that it's within last 10 seconds. */ +static int +assertion_file_time(const char *file, int line, + const char *pathname, long t, long nsec, char type, int recent) +{ + long long filet, filet_nsec; + int r; + +#if defined(_WIN32) && !defined(__CYGWIN__) +#define EPOC_TIME (116444736000000000ULL) + FILETIME fxtime, fbirthtime, fatime, fmtime; + ULARGE_INTEGER wintm; + HANDLE h; + fxtime.dwLowDateTime = 0; + fxtime.dwHighDateTime = 0; + + assertion_count(file, line); + /* Note: FILE_FLAG_BACKUP_SEMANTICS applies to open + * a directory file. If not, CreateFile() will fail when + * the pathname is a directory. */ + h = CreateFile(pathname, FILE_READ_ATTRIBUTES, 0, NULL, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (h == INVALID_HANDLE_VALUE) { + failure_start(file, line, "Can't access %s\n", pathname); + failure_finish(NULL); + return (0); + } + r = GetFileTime(h, &fbirthtime, &fatime, &fmtime); + switch (type) { + case 'a': fxtime = fatime; break; + case 'b': fxtime = fbirthtime; break; + case 'm': fxtime = fmtime; break; + } + CloseHandle(h); + if (r == 0) { + failure_start(file, line, "Can't GetFileTime %s\n", pathname); + failure_finish(NULL); + return (0); + } + wintm.LowPart = fxtime.dwLowDateTime; + wintm.HighPart = fxtime.dwHighDateTime; + filet = (wintm.QuadPart - EPOC_TIME) / 10000000; + filet_nsec = ((wintm.QuadPart - EPOC_TIME) % 10000000) * 100; + nsec = (nsec / 100) * 100; /* Round the request */ +#else + struct stat st; + + assertion_count(file, line); + r = lstat(pathname, &st); + if (r != 0) { + failure_start(file, line, "Can't stat %s\n", pathname); + failure_finish(NULL); + return (0); + } + switch (type) { + case 'a': filet = st.st_atime; break; + case 'm': filet = st.st_mtime; break; + case 'b': filet = 0; break; + default: fprintf(stderr, "INTERNAL: Bad type %c for file time", type); + exit(1); + } +#if defined(__FreeBSD__) + switch (type) { + case 'a': filet_nsec = st.st_atimespec.tv_nsec; break; + case 'b': filet = st.st_birthtime; + /* FreeBSD filesystems that don't support birthtime + * (e.g., UFS1) always return -1 here. */ + if (filet == -1) { + return (1); + } + filet_nsec = st.st_birthtimespec.tv_nsec; break; + case 'm': filet_nsec = st.st_mtimespec.tv_nsec; break; + default: fprintf(stderr, "INTERNAL: Bad type %c for file time", type); + exit(1); + } + /* FreeBSD generally only stores to microsecond res, so round. */ + filet_nsec = (filet_nsec / 1000) * 1000; + nsec = (nsec / 1000) * 1000; +#else + filet_nsec = nsec = 0; /* Generic POSIX only has whole seconds. */ + if (type == 'b') return (1); /* Generic POSIX doesn't have birthtime */ +#if defined(__HAIKU__) + if (type == 'a') return (1); /* Haiku doesn't have atime. */ +#endif +#endif +#endif + if (recent) { + /* Check that requested time is up-to-date. */ + time_t now = time(NULL); + if (filet < now - 10 || filet > now + 1) { + failure_start(file, line, + "File %s has %ctime %lld, %lld seconds ago\n", + pathname, type, filet, now - filet); + failure_finish(NULL); + return (0); + } + } else if (filet != t || filet_nsec != nsec) { + failure_start(file, line, + "File %s has %ctime %lld.%09lld, expected %ld.%09ld", + pathname, type, filet, filet_nsec, t, nsec); + failure_finish(NULL); + return (0); + } + return (1); +} + +/* Verify atime of 'pathname'. */ +int +assertion_file_atime(const char *file, int line, + const char *pathname, long t, long nsec) +{ + return assertion_file_time(file, line, pathname, t, nsec, 'a', 0); +} + +/* Verify atime of 'pathname' is up-to-date. */ +int +assertion_file_atime_recent(const char *file, int line, const char *pathname) +{ + return assertion_file_time(file, line, pathname, 0, 0, 'a', 1); +} + +/* Verify birthtime of 'pathname'. */ +int +assertion_file_birthtime(const char *file, int line, + const char *pathname, long t, long nsec) +{ + return assertion_file_time(file, line, pathname, t, nsec, 'b', 0); +} + +/* Verify birthtime of 'pathname' is up-to-date. */ +int +assertion_file_birthtime_recent(const char *file, int line, + const char *pathname) +{ + return assertion_file_time(file, line, pathname, 0, 0, 'b', 1); +} + +/* Verify mode of 'pathname'. */ +int +assertion_file_mode(const char *file, int line, const char *pathname, int expected_mode) +{ + int mode; + int r; + + assertion_count(file, line); +#if defined(_WIN32) && !defined(__CYGWIN__) + failure_start(file, line, "assertFileMode not yet implemented for Windows"); + (void)mode; /* UNUSED */ + (void)r; /* UNUSED */ + (void)pathname; /* UNUSED */ + (void)expected_mode; /* UNUSED */ +#else + { + struct stat st; + r = lstat(pathname, &st); + mode = (int)(st.st_mode & 0777); + } + if (r == 0 && mode == expected_mode) + return (1); + failure_start(file, line, "File %s has mode %o, expected %o", + pathname, mode, expected_mode); +#endif + failure_finish(NULL); + return (0); +} + +/* Verify mtime of 'pathname'. */ +int +assertion_file_mtime(const char *file, int line, + const char *pathname, long t, long nsec) +{ + return assertion_file_time(file, line, pathname, t, nsec, 'm', 0); +} + +/* Verify mtime of 'pathname' is up-to-date. */ +int +assertion_file_mtime_recent(const char *file, int line, const char *pathname) +{ + return assertion_file_time(file, line, pathname, 0, 0, 'm', 1); +} + +/* Verify number of links to 'pathname'. */ +int +assertion_file_nlinks(const char *file, int line, + const char *pathname, int nlinks) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + BY_HANDLE_FILE_INFORMATION bhfi; + int r; + + assertion_count(file, line); + r = my_GetFileInformationByName(pathname, &bhfi); + if (r != 0 && bhfi.nNumberOfLinks == (DWORD)nlinks) + return (1); + failure_start(file, line, "File %s has %jd links, expected %d", + pathname, (intmax_t)bhfi.nNumberOfLinks, nlinks); + failure_finish(NULL); + return (0); +#else + struct stat st; + int r; + + assertion_count(file, line); + r = lstat(pathname, &st); + if (r == 0 && (int)st.st_nlink == nlinks) + return (1); + failure_start(file, line, "File %s has %jd links, expected %d", + pathname, (intmax_t)st.st_nlink, nlinks); + failure_finish(NULL); + return (0); +#endif +} + +/* Verify size of 'pathname'. */ +int +assertion_file_size(const char *file, int line, const char *pathname, long size) +{ + int64_t filesize; + int r; + + assertion_count(file, line); +#if defined(_WIN32) && !defined(__CYGWIN__) + { + BY_HANDLE_FILE_INFORMATION bhfi; + r = !my_GetFileInformationByName(pathname, &bhfi); + filesize = ((int64_t)bhfi.nFileSizeHigh << 32) + bhfi.nFileSizeLow; + } +#else + { + struct stat st; + r = lstat(pathname, &st); + filesize = st.st_size; + } +#endif + if (r == 0 && filesize == size) + return (1); + failure_start(file, line, "File %s has size %ld, expected %ld", + pathname, (long)filesize, (long)size); + failure_finish(NULL); + return (0); +} + +/* Assert that 'pathname' is a dir. If mode >= 0, verify that too. */ +int +assertion_is_dir(const char *file, int line, const char *pathname, int mode) +{ + struct stat st; + int r; + +#if defined(_WIN32) && !defined(__CYGWIN__) + (void)mode; /* UNUSED */ +#endif + assertion_count(file, line); + r = lstat(pathname, &st); + if (r != 0) { + failure_start(file, line, "Dir should exist: %s", pathname); + failure_finish(NULL); + return (0); + } + if (!S_ISDIR(st.st_mode)) { + failure_start(file, line, "%s is not a dir", pathname); + failure_finish(NULL); + return (0); + } +#if !defined(_WIN32) || defined(__CYGWIN__) + /* Windows doesn't handle permissions the same way as POSIX, + * so just ignore the mode tests. */ + /* TODO: Can we do better here? */ + if (mode >= 0 && (mode_t)mode != (st.st_mode & 07777)) { + failure_start(file, line, "Dir %s has wrong mode", pathname); + logprintf(" Expected: 0%3o\n", mode); + logprintf(" Found: 0%3o\n", st.st_mode & 07777); + failure_finish(NULL); + return (0); + } +#endif + return (1); +} + +/* Verify that 'pathname' is a regular file. If 'mode' is >= 0, + * verify that too. */ +int +assertion_is_reg(const char *file, int line, const char *pathname, int mode) +{ + struct stat st; + int r; + +#if defined(_WIN32) && !defined(__CYGWIN__) + (void)mode; /* UNUSED */ +#endif + assertion_count(file, line); + r = lstat(pathname, &st); + if (r != 0 || !S_ISREG(st.st_mode)) { + failure_start(file, line, "File should exist: %s", pathname); + failure_finish(NULL); + return (0); + } +#if !defined(_WIN32) || defined(__CYGWIN__) + /* Windows doesn't handle permissions the same way as POSIX, + * so just ignore the mode tests. */ + /* TODO: Can we do better here? */ + if (mode >= 0 && (mode_t)mode != (st.st_mode & 07777)) { + failure_start(file, line, "File %s has wrong mode", pathname); + logprintf(" Expected: 0%3o\n", mode); + logprintf(" Found: 0%3o\n", st.st_mode & 07777); + failure_finish(NULL); + return (0); + } +#endif + return (1); +} + +/* + * Check whether 'pathname' is a symbolic link. If 'contents' is + * non-NULL, verify that the symlink has those contents. + * + * On platforms with directory symlinks, set isdir to 0 to test for a file + * symlink and to 1 to test for a directory symlink. On other platforms + * the variable is ignored. + */ +static int +is_symlink(const char *file, int line, + const char *pathname, const char *contents, int isdir) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + HANDLE h; + DWORD inbytes; + REPARSE_DATA_BUFFER *buf; + BY_HANDLE_FILE_INFORMATION st; + size_t len, len2; + wchar_t *linknamew, *contentsw; + const char *p; + char *s, *pn; + int ret = 0; + BYTE *indata; + const DWORD flag = FILE_FLAG_BACKUP_SEMANTICS | + FILE_FLAG_OPEN_REPARSE_POINT; + + /* Replace slashes with backslashes in pathname */ + pn = malloc((strlen(pathname) + 1) * sizeof(char)); + p = pathname; + s = pn; + while(*p != '\0') { + if(*p == '/') + *s = '\\'; + else + *s = *p; + p++; + s++; + } + *s = '\0'; + + h = CreateFileA(pn, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, + flag, NULL); + free(pn); + if (h == INVALID_HANDLE_VALUE) { + failure_start(file, line, "Can't access %s\n", pathname); + failure_finish(NULL); + return (0); + } + ret = GetFileInformationByHandle(h, &st); + if (ret == 0) { + failure_start(file, line, + "Can't stat: %s", pathname); + failure_finish(NULL); + } else if ((st.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0) { + failure_start(file, line, + "Not a symlink: %s", pathname); + failure_finish(NULL); + ret = 0; + } + if (isdir && ((st.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)) { + failure_start(file, line, + "Not a directory symlink: %s", pathname); + failure_finish(NULL); + ret = 0; + } + if (!isdir && + ((st.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)) { + failure_start(file, line, + "Not a file symlink: %s", pathname); + failure_finish(NULL); + ret = 0; + } + if (ret == 0) { + CloseHandle(h); + return (0); + } + + indata = malloc(MAXIMUM_REPARSE_DATA_BUFFER_SIZE); + ret = DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, indata, + 1024, &inbytes, NULL); + CloseHandle(h); + if (ret == 0) { + free(indata); + failure_start(file, line, + "Could not retrieve symlink target: %s", pathname); + failure_finish(NULL); + return (0); + } + + buf = (REPARSE_DATA_BUFFER *) indata; + if (buf->ReparseTag != IO_REPARSE_TAG_SYMLINK) { + free(indata); + /* File is not a symbolic link */ + failure_start(file, line, + "Not a symlink: %s", pathname); + failure_finish(NULL); + return (0); + } + + if (contents == NULL) { + free(indata); + return (1); + } + + len = buf->SymbolicLinkReparseBuffer.SubstituteNameLength; + + linknamew = malloc(len + sizeof(wchar_t)); + if (linknamew == NULL) { + free(indata); + return (0); + } + + memcpy(linknamew, &((BYTE *)buf->SymbolicLinkReparseBuffer.PathBuffer) + [buf->SymbolicLinkReparseBuffer.SubstituteNameOffset], len); + free(indata); + + linknamew[len / sizeof(wchar_t)] = L'\0'; + + contentsw = malloc(len + sizeof(wchar_t)); + if (contentsw == NULL) { + free(linknamew); + return (0); + } + + len2 = mbsrtowcs(contentsw, &contents, (len + sizeof(wchar_t) + / sizeof(wchar_t)), NULL); + + if (len2 > 0 && wcscmp(linknamew, contentsw) != 0) + ret = 1; + + free(linknamew); + free(contentsw); + return (ret); +#else + char buff[300]; + struct stat st; + ssize_t linklen; + int r; + + (void)isdir; /* UNUSED */ + assertion_count(file, line); + r = lstat(pathname, &st); + if (r != 0) { + failure_start(file, line, + "Symlink should exist: %s", pathname); + failure_finish(NULL); + return (0); + } + if (!S_ISLNK(st.st_mode)) + return (0); + if (contents == NULL) + return (1); + linklen = readlink(pathname, buff, sizeof(buff) - 1); + if (linklen < 0) { + failure_start(file, line, "Can't read symlink %s", pathname); + failure_finish(NULL); + return (0); + } + buff[linklen] = '\0'; + if (strcmp(buff, contents) != 0) + return (0); + return (1); +#endif +} + +/* Assert that path is a symlink that (optionally) contains contents. */ +int +assertion_is_symlink(const char *file, int line, + const char *path, const char *contents, int isdir) +{ + if (is_symlink(file, line, path, contents, isdir)) + return (1); + if (contents) + failure_start(file, line, "File %s is not a symlink to %s", + path, contents); + else + failure_start(file, line, "File %s is not a symlink", path); + failure_finish(NULL); + return (0); +} + + +/* Create a directory and report any errors. */ +int +assertion_make_dir(const char *file, int line, const char *dirname, int mode) +{ + assertion_count(file, line); +#if defined(_WIN32) && !defined(__CYGWIN__) + (void)mode; /* UNUSED */ + if (0 == _mkdir(dirname)) + return (1); +#else + if (0 == mkdir(dirname, mode)) { + if (0 == chmod(dirname, mode)) { + assertion_file_mode(file, line, dirname, mode); + return (1); + } + } +#endif + failure_start(file, line, "Could not create directory %s", dirname); + failure_finish(NULL); + return(0); +} + +/* Create a file with the specified contents and report any failures. */ +int +assertion_make_file(const char *file, int line, + const char *path, int mode, int csize, const void *contents) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + /* TODO: Rework this to set file mode as well. */ + FILE *f; + (void)mode; /* UNUSED */ + assertion_count(file, line); + f = fopen(path, "wb"); + if (f == NULL) { + failure_start(file, line, "Could not create file %s", path); + failure_finish(NULL); + return (0); + } + if (contents != NULL) { + size_t wsize; + + if (csize < 0) + wsize = strlen(contents); + else + wsize = (size_t)csize; + if (wsize != fwrite(contents, 1, wsize, f)) { + fclose(f); + failure_start(file, line, + "Could not write file %s", path); + failure_finish(NULL); + return (0); + } + } + fclose(f); + return (1); +#else + int fd; + assertion_count(file, line); + fd = open(path, O_CREAT | O_WRONLY, mode >= 0 ? mode : 0644); + if (fd < 0) { + failure_start(file, line, "Could not create %s", path); + failure_finish(NULL); + return (0); + } + if (0 != chmod(path, mode)) { + failure_start(file, line, "Could not chmod %s", path); + failure_finish(NULL); + close(fd); + return (0); + } + if (contents != NULL) { + ssize_t wsize; + + if (csize < 0) + wsize = (ssize_t)strlen(contents); + else + wsize = (ssize_t)csize; + if (wsize != write(fd, contents, wsize)) { + close(fd); + failure_start(file, line, + "Could not write to %s", path); + failure_finish(NULL); + close(fd); + return (0); + } + } + close(fd); + assertion_file_mode(file, line, path, mode); + return (1); +#endif +} + +/* Create a hardlink and report any failures. */ +int +assertion_make_hardlink(const char *file, int line, + const char *newpath, const char *linkto) +{ + int succeeded; + + assertion_count(file, line); +#if defined(_WIN32) && !defined(__CYGWIN__) + succeeded = my_CreateHardLinkA(newpath, linkto); +#elif HAVE_LINK + succeeded = !link(linkto, newpath); +#else + succeeded = 0; +#endif + if (succeeded) + return (1); + failure_start(file, line, "Could not create hardlink"); + logprintf(" New link: %s\n", newpath); + logprintf(" Old name: %s\n", linkto); + failure_finish(NULL); + return(0); +} + +/* + * Create a symlink and report any failures. + * + * Windows symlinks need to know if the target is a directory. + */ +int +assertion_make_symlink(const char *file, int line, + const char *newpath, const char *linkto, int targetIsDir) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + assertion_count(file, line); + if (my_CreateSymbolicLinkA(newpath, linkto, targetIsDir)) + return (1); +#elif HAVE_SYMLINK + (void)targetIsDir; /* UNUSED */ + assertion_count(file, line); + if (0 == symlink(linkto, newpath)) + return (1); +#else + (void)targetIsDir; /* UNUSED */ +#endif + failure_start(file, line, "Could not create symlink"); + logprintf(" New link: %s\n", newpath); + logprintf(" Old name: %s\n", linkto); + failure_finish(NULL); + return(0); +} + +/* Set umask, report failures. */ +int +assertion_umask(const char *file, int line, int mask) +{ + assertion_count(file, line); + (void)file; /* UNUSED */ + (void)line; /* UNUSED */ + umask(mask); + return (1); +} + +/* Set times, report failures. */ +int +assertion_utimes(const char *file, int line, + const char *pathname, long at, long at_nsec, long mt, long mt_nsec) +{ + int r; + +#if defined(_WIN32) && !defined(__CYGWIN__) +#define WINTIME(sec, nsec) ((Int32x32To64(sec, 10000000) + EPOC_TIME)\ + + (((nsec)/1000)*10)) + HANDLE h; + ULARGE_INTEGER wintm; + FILETIME fatime, fmtime; + FILETIME *pat, *pmt; + + assertion_count(file, line); + h = CreateFileA(pathname,GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (h == INVALID_HANDLE_VALUE) { + failure_start(file, line, "Can't access %s\n", pathname); + failure_finish(NULL); + return (0); + } + + if (at > 0 || at_nsec > 0) { + wintm.QuadPart = WINTIME(at, at_nsec); + fatime.dwLowDateTime = wintm.LowPart; + fatime.dwHighDateTime = wintm.HighPart; + pat = &fatime; + } else + pat = NULL; + if (mt > 0 || mt_nsec > 0) { + wintm.QuadPart = WINTIME(mt, mt_nsec); + fmtime.dwLowDateTime = wintm.LowPart; + fmtime.dwHighDateTime = wintm.HighPart; + pmt = &fmtime; + } else + pmt = NULL; + if (pat != NULL || pmt != NULL) + r = SetFileTime(h, NULL, pat, pmt); + else + r = 1; + CloseHandle(h); + if (r == 0) { + failure_start(file, line, "Can't SetFileTime %s\n", pathname); + failure_finish(NULL); + return (0); + } + return (1); +#else /* defined(_WIN32) && !defined(__CYGWIN__) */ + struct stat st; + struct timeval times[2]; + +#if !defined(__FreeBSD__) + mt_nsec = at_nsec = 0; /* Generic POSIX only has whole seconds. */ +#endif + if (mt == 0 && mt_nsec == 0 && at == 0 && at_nsec == 0) + return (1); + + r = lstat(pathname, &st); + if (r < 0) { + failure_start(file, line, "Can't stat %s\n", pathname); + failure_finish(NULL); + return (0); + } + + if (mt == 0 && mt_nsec == 0) { + mt = st.st_mtime; +#if defined(__FreeBSD__) + mt_nsec = st.st_mtimespec.tv_nsec; + /* FreeBSD generally only stores to microsecond res, so round. */ + mt_nsec = (mt_nsec / 1000) * 1000; +#endif + } + if (at == 0 && at_nsec == 0) { + at = st.st_atime; +#if defined(__FreeBSD__) + at_nsec = st.st_atimespec.tv_nsec; + /* FreeBSD generally only stores to microsecond res, so round. */ + at_nsec = (at_nsec / 1000) * 1000; +#endif + } + + times[1].tv_sec = mt; + times[1].tv_usec = mt_nsec / 1000; + + times[0].tv_sec = at; + times[0].tv_usec = at_nsec / 1000; + +#ifdef HAVE_LUTIMES + r = lutimes(pathname, times); +#else + r = utimes(pathname, times); +#endif + if (r < 0) { + failure_start(file, line, "Can't utimes %s\n", pathname); + failure_finish(NULL); + return (0); + } + return (1); +#endif /* defined(_WIN32) && !defined(__CYGWIN__) */ +} + +/* Compare file flags */ +int +assertion_compare_fflags(const char *file, int line, const char *patha, + const char *pathb, int nomatch) +{ +#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP) + struct stat sa, sb; + + assertion_count(file, line); + + if (stat(patha, &sa) < 0) + return (0); + if (stat(pathb, &sb) < 0) + return (0); + if (!nomatch && sa.st_flags != sb.st_flags) { + failure_start(file, line, "File flags should be identical: " + "%s=%#010x %s=%#010x", patha, sa.st_flags, pathb, + sb.st_flags); + failure_finish(NULL); + return (0); + } + if (nomatch && sa.st_flags == sb.st_flags) { + failure_start(file, line, "File flags should be different: " + "%s=%#010x %s=%#010x", patha, sa.st_flags, pathb, + sb.st_flags); + failure_finish(NULL); + return (0); + } +#elif (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS) && \ + defined(FS_NODUMP_FL)) || \ + (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS) \ + && defined(EXT2_NODUMP_FL)) + int fd, r, flagsa, flagsb; + + assertion_count(file, line); + fd = open(patha, O_RDONLY | O_NONBLOCK); + if (fd < 0) { + failure_start(file, line, "Can't open %s\n", patha); + failure_finish(NULL); + return (0); + } + r = ioctl(fd, +#ifdef FS_IOC_GETFLAGS + FS_IOC_GETFLAGS, +#else + EXT2_IOC_GETFLAGS, +#endif + &flagsa); + close(fd); + if (r < 0) { + failure_start(file, line, "Can't get flags %s\n", patha); + failure_finish(NULL); + return (0); + } + fd = open(pathb, O_RDONLY | O_NONBLOCK); + if (fd < 0) { + failure_start(file, line, "Can't open %s\n", pathb); + failure_finish(NULL); + return (0); + } + r = ioctl(fd, +#ifdef FS_IOC_GETFLAGS + FS_IOC_GETFLAGS, +#else + EXT2_IOC_GETFLAGS, +#endif + &flagsb); + close(fd); + if (r < 0) { + failure_start(file, line, "Can't get flags %s\n", pathb); + failure_finish(NULL); + return (0); + } + if (!nomatch && flagsa != flagsb) { + failure_start(file, line, "File flags should be identical: " + "%s=%#010x %s=%#010x", patha, flagsa, pathb, flagsb); + failure_finish(NULL); + return (0); + } + if (nomatch && flagsa == flagsb) { + failure_start(file, line, "File flags should be different: " + "%s=%#010x %s=%#010x", patha, flagsa, pathb, flagsb); + failure_finish(NULL); + return (0); + } +#else + (void)patha; /* UNUSED */ + (void)pathb; /* UNUSED */ + (void)nomatch; /* UNUSED */ + assertion_count(file, line); +#endif + return (1); +} + +/* Set nodump, report failures. */ +int +assertion_set_nodump(const char *file, int line, const char *pathname) +{ +#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP) + int r; + + assertion_count(file, line); + r = chflags(pathname, UF_NODUMP); + if (r < 0) { + failure_start(file, line, "Can't set nodump %s\n", pathname); + failure_finish(NULL); + return (0); + } +#elif (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS) && \ + defined(FS_NODUMP_FL)) || \ + (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS) \ + && defined(EXT2_NODUMP_FL)) + int fd, r, flags; + + assertion_count(file, line); + fd = open(pathname, O_RDONLY | O_NONBLOCK); + if (fd < 0) { + failure_start(file, line, "Can't open %s\n", pathname); + failure_finish(NULL); + return (0); + } + r = ioctl(fd, +#ifdef FS_IOC_GETFLAGS + FS_IOC_GETFLAGS, +#else + EXT2_IOC_GETFLAGS, +#endif + &flags); + if (r < 0) { + failure_start(file, line, "Can't get flags %s\n", pathname); + failure_finish(NULL); + return (0); + } +#ifdef FS_NODUMP_FL + flags |= FS_NODUMP_FL; +#else + flags |= EXT2_NODUMP_FL; +#endif + + r = ioctl(fd, +#ifdef FS_IOC_SETFLAGS + FS_IOC_SETFLAGS, +#else + EXT2_IOC_SETFLAGS, +#endif + &flags); + if (r < 0) { + failure_start(file, line, "Can't set nodump %s\n", pathname); + failure_finish(NULL); + return (0); + } + close(fd); +#else + (void)pathname; /* UNUSED */ + assertion_count(file, line); +#endif + return (1); +} + +#ifdef PROGRAM +static void assert_version_id(char **qq, size_t *ss) +{ + char *q = *qq; + size_t s = *ss; + + /* Version number is a series of digits and periods. */ + while (s > 0 && (*q == '.' || (*q >= '0' && *q <= '9'))) { + ++q; + --s; + } + + if (q[0] == 'd' && q[1] == 'e' && q[2] == 'v') { + q += 3; + s -= 3; + } + + /* Skip a single trailing a,b,c, or d. */ + if (*q == 'a' || *q == 'b' || *q == 'c' || *q == 'd') + ++q; + + /* Version number terminated by space. */ + failure("No space after version: ``%s''", q); + assert(s > 1); + failure("No space after version: ``%s''", q); + assert(*q == ' '); + + ++q; --s; + + *qq = q; + *ss = s; +} + + +/* + * Check program version + */ +void assertVersion(const char *prog, const char *base) +{ + int r; + char *p, *q; + size_t s; + size_t prog_len = strlen(base); + + r = systemf("%s --version >version.stdout 2>version.stderr", prog); + if (r != 0) + r = systemf("%s -W version >version.stdout 2>version.stderr", + prog); + + failure("Unable to run either %s --version or %s -W version", + prog, prog); + if (!assert(r == 0)) + return; + + /* --version should generate nothing to stdout. */ + assertEmptyFile("version.stderr"); + + /* Verify format of version message. */ + q = p = slurpfile(&s, "version.stdout"); + + /* Version message should start with name of program, then space. */ + assert(s > prog_len + 1); + + failure("Version must start with '%s': ``%s''", base, p); + if (!assertEqualMem(q, base, prog_len)) { + free(p); + return; + } + + q += prog_len; s -= prog_len; + + assert(*q == ' '); + q++; s--; + + assert_version_id(&q, &s); + + /* Separator. */ + failure("No `-' between program name and versions: ``%s''", p); + assertEqualMem(q, "- ", 2); + q += 2; s -= 2; + + failure("Not long enough for libarchive version: ``%s''", p); + assert(s > 11); + + failure("Libarchive version must start with `libarchive': ``%s''", p); + assertEqualMem(q, "libarchive ", 11); + + q += 11; s -= 11; + + assert_version_id(&q, &s); + + /* Skip arbitrary third-party version numbers. */ + while (s > 0 && (*q == ' ' || *q == '-' || *q == '/' || *q == '.' || + isalnum((unsigned char)*q))) { + ++q; + --s; + } + + /* All terminated by end-of-line. */ + assert(s >= 1); + + /* Skip an optional CR character (e.g., Windows) */ + failure("Version output must end with \\n or \\r\\n"); + + if (*q == '\r') { ++q; --s; } + assertEqualMem(q, "\n", 1); + + free(p); +} +#endif /* PROGRAM */ + +/* + * + * UTILITIES for use by tests. + * + */ + +/* + * Check whether platform supports symlinks. This is intended + * for tests to use in deciding whether to bother testing symlink + * support; if the platform doesn't support symlinks, there's no point + * in checking whether the program being tested can create them. + * + * Note that the first time this test is called, we actually go out to + * disk to create and verify a symlink. This is necessary because + * symlink support is actually a property of a particular filesystem + * and can thus vary between directories on a single system. After + * the first call, this returns the cached result from memory, so it's + * safe to call it as often as you wish. + */ +int +canSymlink(void) +{ + /* Remember the test result */ + static int value = 0, tested = 0; + if (tested) + return (value); + + ++tested; + assertion_make_file(__FILE__, __LINE__, "canSymlink.0", 0644, 1, "a"); + /* Note: Cygwin has its own symlink() emulation that does not + * use the Win32 CreateSymbolicLink() function. */ +#if defined(_WIN32) && !defined(__CYGWIN__) + value = my_CreateSymbolicLinkA("canSymlink.1", "canSymlink.0", 0) + && is_symlink(__FILE__, __LINE__, "canSymlink.1", "canSymlink.0", + 0); +#elif HAVE_SYMLINK + value = (0 == symlink("canSymlink.0", "canSymlink.1")) + && is_symlink(__FILE__, __LINE__, "canSymlink.1","canSymlink.0", + 0); +#endif + return (value); +} + +/* Platform-dependent options for hiding the output of a subcommand. */ +#if defined(_WIN32) && !defined(__CYGWIN__) +static const char *redirectArgs = ">NUL 2>NUL"; /* Win32 cmd.exe */ +#else +static const char *redirectArgs = ">/dev/null 2>/dev/null"; /* POSIX 'sh' */ +#endif +/* + * Can this platform run the bzip2 program? + */ +int +canBzip2(void) +{ + static int tested = 0, value = 0; + if (!tested) { + tested = 1; + if (systemf("bzip2 --help %s", redirectArgs) == 0) + value = 1; + } + return (value); +} + +/* + * Can this platform run the grzip program? + */ +int +canGrzip(void) +{ + static int tested = 0, value = 0; + if (!tested) { + tested = 1; + if (systemf("grzip -V %s", redirectArgs) == 0) + value = 1; + } + return (value); +} + +/* + * Can this platform run the gzip program? + */ +int +canGzip(void) +{ + static int tested = 0, value = 0; + if (!tested) { + tested = 1; + if (systemf("gzip --help %s", redirectArgs) == 0) + value = 1; + } + return (value); +} + +/* + * Can this platform run the lrzip program? + */ +int +canRunCommand(const char *cmd) +{ + static int tested = 0, value = 0; + if (!tested) { + tested = 1; + if (systemf("%s %s", cmd, redirectArgs) == 0) + value = 1; + } + return (value); +} + +int +canLrzip(void) +{ + static int tested = 0, value = 0; + if (!tested) { + tested = 1; + if (systemf("lrzip -V %s", redirectArgs) == 0) + value = 1; + } + return (value); +} + +/* + * Can this platform run the lz4 program? + */ +int +canLz4(void) +{ + static int tested = 0, value = 0; + if (!tested) { + tested = 1; + if (systemf("lz4 --help %s", redirectArgs) == 0) + value = 1; + } + return (value); +} + +/* + * Can this platform run the zstd program? + */ +int +canZstd(void) +{ + static int tested = 0, value = 0; + if (!tested) { + tested = 1; + if (systemf("zstd --help %s", redirectArgs) == 0) + value = 1; + } + return (value); +} + +/* + * Can this platform run the lzip program? + */ +int +canLzip(void) +{ + static int tested = 0, value = 0; + if (!tested) { + tested = 1; + if (systemf("lzip --help %s", redirectArgs) == 0) + value = 1; + } + return (value); +} + +/* + * Can this platform run the lzma program? + */ +int +canLzma(void) +{ + static int tested = 0, value = 0; + if (!tested) { + tested = 1; + if (systemf("lzma %s", redirectArgs) == 0) + value = 1; + } + return (value); +} + +/* + * Can this platform run the lzop program? + */ +int +canLzop(void) +{ + static int tested = 0, value = 0; + if (!tested) { + tested = 1; + if (systemf("lzop --help %s", redirectArgs) == 0) + value = 1; + } + return (value); +} + +/* + * Can this platform run the xz program? + */ +int +canXz(void) +{ + static int tested = 0, value = 0; + if (!tested) { + tested = 1; + if (systemf("xz --help %s", redirectArgs) == 0) + value = 1; + } + return (value); +} + +/* + * Can this filesystem handle nodump flags. + */ +int +canNodump(void) +{ +#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP) + const char *path = "cannodumptest"; + struct stat sb; + + assertion_make_file(__FILE__, __LINE__, path, 0644, 0, NULL); + if (chflags(path, UF_NODUMP) < 0) + return (0); + if (stat(path, &sb) < 0) + return (0); + if (sb.st_flags & UF_NODUMP) + return (1); +#elif (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS) \ + && defined(FS_NODUMP_FL)) || \ + (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS) \ + && defined(EXT2_NODUMP_FL)) + const char *path = "cannodumptest"; + int fd, r, flags; + + assertion_make_file(__FILE__, __LINE__, path, 0644, 0, NULL); + fd = open(path, O_RDONLY | O_NONBLOCK); + if (fd < 0) + return (0); + r = ioctl(fd, +#ifdef FS_IOC_GETFLAGS + FS_IOC_GETFLAGS, +#else + EXT2_IOC_GETFLAGS, +#endif + &flags); + if (r < 0) + return (0); +#ifdef FS_NODUMP_FL + flags |= FS_NODUMP_FL; +#else + flags |= EXT2_NODUMP_FL; +#endif + r = ioctl(fd, +#ifdef FS_IOC_SETFLAGS + FS_IOC_SETFLAGS, +#else + EXT2_IOC_SETFLAGS, +#endif + &flags); + if (r < 0) + return (0); + close(fd); + fd = open(path, O_RDONLY | O_NONBLOCK); + if (fd < 0) + return (0); + r = ioctl(fd, +#ifdef FS_IOC_GETFLAGS + FS_IOC_GETFLAGS, +#else + EXT2_IOC_GETFLAGS, +#endif + &flags); + if (r < 0) + return (0); + close(fd); +#ifdef FS_NODUMP_FL + if (flags & FS_NODUMP_FL) +#else + if (flags & EXT2_NODUMP_FL) +#endif + return (1); +#endif + return (0); +} + +/* Get extended attribute value from a path */ +void * +getXattr(const char *path, const char *name, size_t *sizep) +{ + void *value = NULL; +#if ARCHIVE_XATTR_SUPPORT + ssize_t size; +#if ARCHIVE_XATTR_LINUX + size = lgetxattr(path, name, NULL, 0); +#elif ARCHIVE_XATTR_DARWIN + size = getxattr(path, name, NULL, 0, 0, XATTR_NOFOLLOW); +#elif ARCHIVE_XATTR_AIX + size = lgetea(path, name, NULL, 0); +#elif ARCHIVE_XATTR_FREEBSD + size = extattr_get_link(path, EXTATTR_NAMESPACE_USER, name + 5, + NULL, 0); +#endif + + if (size >= 0) { + value = malloc(size); +#if ARCHIVE_XATTR_LINUX + size = lgetxattr(path, name, value, size); +#elif ARCHIVE_XATTR_DARWIN + size = getxattr(path, name, value, size, 0, XATTR_NOFOLLOW); +#elif ARCHIVE_XATTR_AIX + size = lgetea(path, name, value, size); +#elif ARCHIVE_XATTR_FREEBSD + size = extattr_get_link(path, EXTATTR_NAMESPACE_USER, name + 5, + value, size); +#endif + if (size < 0) { + free(value); + value = NULL; + } + } + if (size < 0) + *sizep = 0; + else + *sizep = (size_t)size; +#else /* !ARCHIVE_XATTR_SUPPORT */ + (void)path; /* UNUSED */ + (void)name; /* UNUSED */ + *sizep = 0; +#endif /* !ARCHIVE_XATTR_SUPPORT */ + return (value); +} + +/* + * Set extended attribute on a path + * Returns 0 on error, 1 on success + */ +int +setXattr(const char *path, const char *name, const void *value, size_t size) +{ +#if ARCHIVE_XATTR_SUPPORT +#if ARCHIVE_XATTR_LINUX + if (lsetxattr(path, name, value, size, 0) == 0) +#elif ARCHIVE_XATTR_DARWIN + if (setxattr(path, name, value, size, 0, XATTR_NOFOLLOW) == 0) +#elif ARCHIVE_XATTR_AIX + if (lsetea(path, name, value, size, 0) == 0) +#elif ARCHIVE_XATTR_FREEBSD + if (extattr_set_link(path, EXTATTR_NAMESPACE_USER, name + 5, value, + size) > -1) +#else + if (0) +#endif + return (1); +#else /* !ARCHIVE_XATTR_SUPPORT */ + (void)path; /* UNUSED */ + (void)name; /* UNUSED */ + (void)value; /* UNUSED */ + (void)size; /* UNUSED */ +#endif /* !ARCHIVE_XATTR_SUPPORT */ + return (0); +} + +#if ARCHIVE_ACL_SUNOS +/* Fetch ACLs on Solaris using acl() or facl() */ +void * +sunacl_get(int cmd, int *aclcnt, int fd, const char *path) +{ + int cnt, cntcmd; + size_t size; + void *aclp; + + if (cmd == GETACL) { + cntcmd = GETACLCNT; + size = sizeof(aclent_t); + } +#if ARCHIVE_ACL_SUNOS_NFS4 + else if (cmd == ACE_GETACL) { + cntcmd = ACE_GETACLCNT; + size = sizeof(ace_t); + } +#endif + else { + errno = EINVAL; + *aclcnt = -1; + return (NULL); + } + + aclp = NULL; + cnt = -2; + while (cnt == -2 || (cnt == -1 && errno == ENOSPC)) { + if (path != NULL) + cnt = acl(path, cntcmd, 0, NULL); + else + cnt = facl(fd, cntcmd, 0, NULL); + + if (cnt > 0) { + if (aclp == NULL) + aclp = malloc(cnt * size); + else + aclp = realloc(NULL, cnt * size); + if (aclp != NULL) { + if (path != NULL) + cnt = acl(path, cmd, cnt, aclp); + else + cnt = facl(fd, cmd, cnt, aclp); + } + } else { + free(aclp); + aclp = NULL; + break; + } + } + + *aclcnt = cnt; + return (aclp); +} +#endif /* ARCHIVE_ACL_SUNOS */ + +/* + * Set test ACLs on a path + * Return values: + * 0: error setting ACLs + * ARCHIVE_TEST_ACL_TYPE_POSIX1E: POSIX.1E ACLs have been set + * ARCHIVE_TEST_ACL_TYPE_NFS4: NFSv4 or extended ACLs have been set + */ +int +setTestAcl(const char *path) +{ +#if ARCHIVE_ACL_SUPPORT + int r = 1; +#if ARCHIVE_ACL_LIBACL || ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_DARWIN + acl_t acl; +#endif +#if ARCHIVE_ACL_LIBRICHACL + struct richacl *richacl; +#endif +#if ARCHIVE_ACL_LIBACL || ARCHIVE_ACL_FREEBSD + const char *acltext_posix1e = "user:1:rw-," + "group:15:r-x," + "user::rwx," + "group::rwx," + "other::r-x," + "mask::rwx"; +#elif ARCHIVE_ACL_SUNOS /* Solaris POSIX.1e */ + aclent_t aclp_posix1e[] = { + { USER_OBJ, -1, 4 | 2 | 1 }, + { USER, 1, 4 | 2 }, + { GROUP_OBJ, -1, 4 | 2 | 1 }, + { GROUP, 15, 4 | 1 }, + { CLASS_OBJ, -1, 4 | 2 | 1 }, + { OTHER_OBJ, -1, 4 | 2 | 1 } + }; +#endif +#if ARCHIVE_ACL_FREEBSD /* FreeBSD NFS4 */ + const char *acltext_nfs4 = "user:1:rwpaRcs::allow:1," + "group:15:rxaRcs::allow:15," + "owner@:rwpxaARWcCos::allow," + "group@:rwpxaRcs::allow," + "everyone@:rxaRcs::allow"; +#elif ARCHIVE_ACL_LIBRICHACL + const char *acltext_nfs4 = "owner:rwpxaARWcCoS::mask," + "group:rwpxaRcS::mask," + "other:rxaRcS::mask," + "user:1:rwpaRcS::allow," + "group:15:rxaRcS::allow," + "owner@:rwpxaARWcCoS::allow," + "group@:rwpxaRcS::allow," + "everyone@:rxaRcS::allow"; +#elif ARCHIVE_ACL_SUNOS_NFS4 /* Solaris NFS4 */ + ace_t aclp_nfs4[] = { + { 1, ACE_READ_DATA | ACE_WRITE_DATA | ACE_APPEND_DATA | + ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS | ACE_READ_ACL | + ACE_SYNCHRONIZE, 0, ACE_ACCESS_ALLOWED_ACE_TYPE }, + { 15, ACE_READ_DATA | ACE_EXECUTE | ACE_READ_ATTRIBUTES | + ACE_READ_NAMED_ATTRS | ACE_READ_ACL | ACE_SYNCHRONIZE, + ACE_IDENTIFIER_GROUP, ACE_ACCESS_ALLOWED_ACE_TYPE }, + { -1, ACE_READ_DATA | ACE_WRITE_DATA | ACE_APPEND_DATA | + ACE_EXECUTE | ACE_READ_ATTRIBUTES | ACE_WRITE_ATTRIBUTES | + ACE_READ_NAMED_ATTRS | ACE_WRITE_NAMED_ATTRS | + ACE_READ_ACL | ACE_WRITE_ACL | ACE_WRITE_OWNER | ACE_SYNCHRONIZE, + ACE_OWNER, ACE_ACCESS_ALLOWED_ACE_TYPE }, + { -1, ACE_READ_DATA | ACE_WRITE_DATA | ACE_APPEND_DATA | + ACE_EXECUTE | ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS | + ACE_READ_ACL | ACE_SYNCHRONIZE, ACE_GROUP | ACE_IDENTIFIER_GROUP, + ACE_ACCESS_ALLOWED_ACE_TYPE }, + { -1, ACE_READ_DATA | ACE_EXECUTE | ACE_READ_ATTRIBUTES | + ACE_READ_NAMED_ATTRS | ACE_READ_ACL | ACE_SYNCHRONIZE, + ACE_EVERYONE, ACE_ACCESS_ALLOWED_ACE_TYPE } + }; +#elif ARCHIVE_ACL_DARWIN /* Mac OS X */ + acl_entry_t aclent; + acl_permset_t permset; + const uid_t uid = 1; + uuid_t uuid; + int i; + const acl_perm_t acl_perms[] = { + ACL_READ_DATA, + ACL_WRITE_DATA, + ACL_APPEND_DATA, + ACL_EXECUTE, + ACL_READ_ATTRIBUTES, + ACL_READ_EXTATTRIBUTES, + ACL_READ_SECURITY, +#if HAVE_DECL_ACL_SYNCHRONIZE + ACL_SYNCHRONIZE +#endif + }; +#endif /* ARCHIVE_ACL_DARWIN */ + +#if ARCHIVE_ACL_FREEBSD + acl = acl_from_text(acltext_nfs4); + failure("acl_from_text() error: %s", strerror(errno)); + if (assert(acl != NULL) == 0) + return (0); +#elif ARCHIVE_ACL_LIBRICHACL + richacl = richacl_from_text(acltext_nfs4, NULL, NULL); + failure("richacl_from_text() error: %s", strerror(errno)); + if (assert(richacl != NULL) == 0) + return (0); +#elif ARCHIVE_ACL_DARWIN + acl = acl_init(1); + failure("acl_init() error: %s", strerror(errno)); + if (assert(acl != NULL) == 0) + return (0); + r = acl_create_entry(&acl, &aclent); + failure("acl_create_entry() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + goto testacl_free; + r = acl_set_tag_type(aclent, ACL_EXTENDED_ALLOW); + failure("acl_set_tag_type() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + goto testacl_free; + r = acl_get_permset(aclent, &permset); + failure("acl_get_permset() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + goto testacl_free; + for (i = 0; i < (int)(sizeof(acl_perms) / sizeof(acl_perms[0])); i++) { + r = acl_add_perm(permset, acl_perms[i]); + failure("acl_add_perm() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + goto testacl_free; + } + r = acl_set_permset(aclent, permset); + failure("acl_set_permset() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + goto testacl_free; + r = mbr_uid_to_uuid(uid, uuid); + failure("mbr_uid_to_uuid() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + goto testacl_free; + r = acl_set_qualifier(aclent, uuid); + failure("acl_set_qualifier() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + goto testacl_free; +#endif /* ARCHIVE_ACL_DARWIN */ + +#if ARCHIVE_ACL_NFS4 +#if ARCHIVE_ACL_FREEBSD + r = acl_set_file(path, ACL_TYPE_NFS4, acl); + acl_free(acl); +#elif ARCHIVE_ACL_LIBRICHACL + r = richacl_set_file(path, richacl); + richacl_free(richacl); +#elif ARCHIVE_ACL_SUNOS_NFS4 + r = acl(path, ACE_SETACL, + (int)(sizeof(aclp_nfs4)/sizeof(aclp_nfs4[0])), aclp_nfs4); +#elif ARCHIVE_ACL_DARWIN + r = acl_set_file(path, ACL_TYPE_EXTENDED, acl); + acl_free(acl); +#endif + if (r == 0) + return (ARCHIVE_TEST_ACL_TYPE_NFS4); +#endif /* ARCHIVE_ACL_NFS4 */ + +#if ARCHIVE_ACL_POSIX1E +#if ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL + acl = acl_from_text(acltext_posix1e); + failure("acl_from_text() error: %s", strerror(errno)); + if (assert(acl != NULL) == 0) + return (0); + + r = acl_set_file(path, ACL_TYPE_ACCESS, acl); + acl_free(acl); +#elif ARCHIVE_ACL_SUNOS + r = acl(path, SETACL, + (int)(sizeof(aclp_posix1e)/sizeof(aclp_posix1e[0])), aclp_posix1e); +#endif + if (r == 0) + return (ARCHIVE_TEST_ACL_TYPE_POSIX1E); + else + return (0); +#endif /* ARCHIVE_ACL_POSIX1E */ +#if ARCHIVE_ACL_DARWIN +testacl_free: + acl_free(acl); +#endif +#endif /* ARCHIVE_ACL_SUPPORT */ + (void)path; /* UNUSED */ + return (0); +} + +/* + * Sleep as needed; useful for verifying disk timestamp changes by + * ensuring that the wall-clock time has actually changed before we + * go back to re-read something from disk. + */ +void +sleepUntilAfter(time_t t) +{ + while (t >= time(NULL)) +#if defined(_WIN32) && !defined(__CYGWIN__) + Sleep(500); +#else + sleep(1); +#endif +} + +/* + * Call standard system() call, but build up the command line using + * sprintf() conventions. + */ +int +systemf(const char *fmt, ...) +{ + char buff[8192]; + va_list ap; + int r; + + va_start(ap, fmt); + vsprintf(buff, fmt, ap); + if (verbosity > VERBOSITY_FULL) + logprintf("Cmd: %s\n", buff); + r = system(buff); + va_end(ap); + return (r); +} + +/* + * Slurp a file into memory for ease of comparison and testing. + * Returns size of file in 'sizep' if non-NULL, null-terminates + * data in memory for ease of use. + */ +char * +slurpfile(size_t * sizep, const char *fmt, ...) +{ + char filename[8192]; + struct stat st; + va_list ap; + char *p; + ssize_t bytes_read; + FILE *f; + int r; + + va_start(ap, fmt); + vsprintf(filename, fmt, ap); + va_end(ap); + + f = fopen(filename, "rb"); + if (f == NULL) { + /* Note: No error; non-existent file is okay here. */ + return (NULL); + } + r = fstat(fileno(f), &st); + if (r != 0) { + logprintf("Can't stat file %s\n", filename); + fclose(f); + return (NULL); + } + p = malloc((size_t)st.st_size + 1); + if (p == NULL) { + logprintf("Can't allocate %ld bytes of memory to read file %s\n", + (long int)st.st_size, filename); + fclose(f); + return (NULL); + } + bytes_read = fread(p, 1, (size_t)st.st_size, f); + if (bytes_read < st.st_size) { + logprintf("Can't read file %s\n", filename); + fclose(f); + free(p); + return (NULL); + } + p[st.st_size] = '\0'; + if (sizep != NULL) + *sizep = (size_t)st.st_size; + fclose(f); + return (p); +} + +/* + * Slurp a file into memory for ease of comparison and testing. + * Returns size of file in 'sizep' if non-NULL, null-terminates + * data in memory for ease of use. + */ +void +dumpfile(const char *filename, void *data, size_t len) +{ + ssize_t bytes_written; + FILE *f; + + f = fopen(filename, "wb"); + if (f == NULL) { + logprintf("Can't open file %s for writing\n", filename); + return; + } + bytes_written = fwrite(data, 1, len, f); + if (bytes_written < (ssize_t)len) + logprintf("Can't write file %s\n", filename); + fclose(f); +} + +/* Read a uuencoded file from the reference directory, decode, and + * write the result into the current directory. */ +#define VALID_UUDECODE(c) (c >= 32 && c <= 96) +#define UUDECODE(c) (((c) - 0x20) & 0x3f) +void +extract_reference_file(const char *name) +{ + char buff[1024]; + FILE *in, *out; + + sprintf(buff, "%s/%s.uu", refdir, name); + in = fopen(buff, "r"); + failure("Couldn't open reference file %s", buff); + assert(in != NULL); + if (in == NULL) + return; + /* Read up to and including the 'begin' line. */ + for (;;) { + if (fgets(buff, sizeof(buff), in) == NULL) { + /* TODO: This is a failure. */ + return; + } + if (memcmp(buff, "begin ", 6) == 0) + break; + } + /* Now, decode the rest and write it. */ + out = fopen(name, "wb"); + while (fgets(buff, sizeof(buff), in) != NULL) { + char *p = buff; + int bytes; + + if (memcmp(buff, "end", 3) == 0) + break; + + bytes = UUDECODE(*p++); + while (bytes > 0) { + int n = 0; + /* Write out 1-3 bytes from that. */ + if (bytes > 0) { + assert(VALID_UUDECODE(p[0])); + assert(VALID_UUDECODE(p[1])); + n = UUDECODE(*p++) << 18; + n |= UUDECODE(*p++) << 12; + fputc(n >> 16, out); + --bytes; + } + if (bytes > 0) { + assert(VALID_UUDECODE(p[0])); + n |= UUDECODE(*p++) << 6; + fputc((n >> 8) & 0xFF, out); + --bytes; + } + if (bytes > 0) { + assert(VALID_UUDECODE(p[0])); + n |= UUDECODE(*p++); + fputc(n & 0xFF, out); + --bytes; + } + } + } + fclose(out); + fclose(in); +} + +void +copy_reference_file(const char *name) +{ + char buff[1024]; + FILE *in, *out; + size_t rbytes; + + sprintf(buff, "%s/%s", refdir, name); + in = fopen(buff, "rb"); + failure("Couldn't open reference file %s", buff); + assert(in != NULL); + if (in == NULL) + return; + /* Now, decode the rest and write it. */ + /* Not a lot of error checking here; the input better be right. */ + out = fopen(name, "wb"); + while ((rbytes = fread(buff, 1, sizeof(buff), in)) > 0) { + if (fwrite(buff, 1, rbytes, out) != rbytes) { + logprintf("Error: fwrite\n"); + break; + } + } + fclose(out); + fclose(in); +} + +int +is_LargeInode(const char *file) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + BY_HANDLE_FILE_INFORMATION bhfi; + int r; + + r = my_GetFileInformationByName(file, &bhfi); + if (r != 0) + return (0); + return (bhfi.nFileIndexHigh & 0x0000FFFFUL); +#else + struct stat st; + int64_t ino; + + if (stat(file, &st) < 0) + return (0); + ino = (int64_t)st.st_ino; + return (ino > 0xffffffff); +#endif +} + +void +extract_reference_files(const char **names) +{ + while (names && *names) + extract_reference_file(*names++); +} + +#ifndef PROGRAM +/* Set ACLs */ +int +assertion_entry_set_acls(const char *file, int line, struct archive_entry *ae, + struct archive_test_acl_t *acls, int n) +{ + int i, r, ret; + + assertion_count(file, line); + + ret = 0; + archive_entry_acl_clear(ae); + for (i = 0; i < n; i++) { + r = archive_entry_acl_add_entry(ae, + acls[i].type, acls[i].permset, acls[i].tag, + acls[i].qual, acls[i].name); + if (r != 0) { + ret = 1; + failure_start(file, line, "type=%#010x, " + "permset=%#010x, tag=%d, qual=%d name=%s", + acls[i].type, acls[i].permset, acls[i].tag, + acls[i].qual, acls[i].name); + failure_finish(NULL); + } + } + + return (ret); +} + +static int +archive_test_acl_match(struct archive_test_acl_t *acl, int type, int permset, + int tag, int qual, const char *name) +{ + if (type != acl->type) + return (0); + if (permset != acl->permset) + return (0); + if (tag != acl->tag) + return (0); + if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ) + return (1); + if (tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ) + return (1); + if (tag == ARCHIVE_ENTRY_ACL_EVERYONE) + return (1); + if (tag == ARCHIVE_ENTRY_ACL_OTHER) + return (1); + if (qual != acl->qual) + return (0); + if (name == NULL) { + if (acl->name == NULL || acl->name[0] == '\0') + return (1); + return (0); + } + if (acl->name == NULL) { + if (name[0] == '\0') + return (1); + return (0); + } + return (0 == strcmp(name, acl->name)); +} + +/* Compare ACLs */ +int +assertion_entry_compare_acls(const char *file, int line, + struct archive_entry *ae, struct archive_test_acl_t *acls, int cnt, + int want_type, int mode) +{ + int *marker; + int i, r, n, ret; + int type, permset, tag, qual; + int matched; + const char *name; + + assertion_count(file, line); + + ret = 0; + n = 0; + marker = malloc(sizeof(marker[0]) * cnt); + + for (i = 0; i < cnt; i++) { + if ((acls[i].type & want_type) != 0) { + marker[n] = i; + n++; + } + } + + if (n == 0) { + failure_start(file, line, "No ACL's to compare, type mask: %d", + want_type); + return (1); + } + + while (0 == (r = archive_entry_acl_next(ae, want_type, + &type, &permset, &tag, &qual, &name))) { + for (i = 0, matched = 0; i < n && !matched; i++) { + if (archive_test_acl_match(&acls[marker[i]], type, + permset, tag, qual, name)) { + /* We found a match; remove it. */ + marker[i] = marker[n - 1]; + n--; + matched = 1; + } + } + if (type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS + && tag == ARCHIVE_ENTRY_ACL_USER_OBJ) { + if (!matched) { + failure_start(file, line, "No match for " + "user_obj perm"); + failure_finish(NULL); + ret = 1; + } + if ((permset << 6) != (mode & 0700)) { + failure_start(file, line, "USER_OBJ permset " + "(%02o) != user mode (%02o)", permset, + 07 & (mode >> 6)); + failure_finish(NULL); + ret = 1; + } + } else if (type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS + && tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ) { + if (!matched) { + failure_start(file, line, "No match for " + "group_obj perm"); + failure_finish(NULL); + ret = 1; + } + if ((permset << 3) != (mode & 0070)) { + failure_start(file, line, "GROUP_OBJ permset " + "(%02o) != group mode (%02o)", permset, + 07 & (mode >> 3)); + failure_finish(NULL); + ret = 1; + } + } else if (type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS + && tag == ARCHIVE_ENTRY_ACL_OTHER) { + if (!matched) { + failure_start(file, line, "No match for " + "other perm"); + failure_finish(NULL); + ret = 1; + } + if ((permset << 0) != (mode & 0007)) { + failure_start(file, line, "OTHER permset " + "(%02o) != other mode (%02o)", permset, + mode & 07); + failure_finish(NULL); + ret = 1; + } + } else if (matched != 1) { + failure_start(file, line, "Could not find match for " + "ACL (type=%#010x,permset=%#010x,tag=%d,qual=%d," + "name=``%s'')", type, permset, tag, qual, name); + failure_finish(NULL); + ret = 1; + } + } + if (r != ARCHIVE_EOF) { + failure_start(file, line, "Should not exit before EOF"); + failure_finish(NULL); + ret = 1; + } + if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0 && + (mode_t)(mode & 0777) != (archive_entry_mode(ae) & 0777)) { + failure_start(file, line, "Mode (%02o) and entry mode (%02o) " + "mismatch", mode, archive_entry_mode(ae)); + failure_finish(NULL); + ret = 1; + } + if (n != 0) { + failure_start(file, line, "Could not find match for ACL " + "(type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s'')", + acls[marker[0]].type, acls[marker[0]].permset, + acls[marker[0]].tag, acls[marker[0]].qual, + acls[marker[0]].name); + failure_finish(NULL); + ret = 1; + /* Number of ACLs not matched should == 0 */ + } + free(marker); + return (ret); +} +#endif /* !defined(PROGRAM) */ + +/* + * + * TEST management + * + */ + +/* + * "list.h" is simply created by "grep DEFINE_TEST test_*.c"; it has + * a line like + * DEFINE_TEST(test_function) + * for each test. + */ + +/* Use "list.h" to declare all of the test functions. */ +#undef DEFINE_TEST +#define DEFINE_TEST(name) void name(void); +#include "list.h" + +/* Use "list.h" to create a list of all tests (functions and names). */ +#undef DEFINE_TEST +#define DEFINE_TEST(n) { n, #n, 0 }, +struct test_list_t tests[] = { + #include "list.h" +}; + +/* + * Summarize repeated failures in the just-completed test. + */ +static void +test_summarize(int failed, int skips_num) +{ + unsigned int i; + + switch (verbosity) { + case VERBOSITY_SUMMARY_ONLY: + printf(failed ? "E" : "."); + fflush(stdout); + break; + case VERBOSITY_PASSFAIL: + printf(failed ? "FAIL\n" : skips_num ? "ok (S)\n" : "ok\n"); + break; + } + + log_console = (verbosity == VERBOSITY_LIGHT_REPORT); + + for (i = 0; i < sizeof(failed_lines)/sizeof(failed_lines[0]); i++) { + if (failed_lines[i].count > 1 && !failed_lines[i].skip) + logprintf("%s:%d: Summary: Failed %d times\n", + failed_filename, i, failed_lines[i].count); + } + /* Clear the failure history for the next file. */ + failed_filename = NULL; + memset(failed_lines, 0, sizeof(failed_lines)); +} + +/* + * Actually run a single test, with appropriate setup and cleanup. + */ +static int +test_run(int i, const char *tmpdir) +{ +#ifdef PATH_MAX + char workdir[PATH_MAX * 2]; +#else + char workdir[1024 * 2]; +#endif + char logfilename[64]; + int failures_before = failures; + int skips_before = skips; + int oldumask; + + switch (verbosity) { + case VERBOSITY_SUMMARY_ONLY: /* No per-test reports at all */ + break; + case VERBOSITY_PASSFAIL: /* rest of line will include ok/FAIL marker */ + printf("%3d: %-64s", i, tests[i].name); + fflush(stdout); + break; + default: /* Title of test, details will follow */ + printf("%3d: %s\n", i, tests[i].name); + } + + /* Chdir to the top-level work directory. */ + if (!assertChdir(tmpdir)) { + fprintf(stderr, + "ERROR: Can't chdir to top work dir %s\n", tmpdir); + exit(1); + } + /* Create a log file for this test. */ + sprintf(logfilename, "%s.log", tests[i].name); + logfile = fopen(logfilename, "w"); + fprintf(logfile, "%s\n\n", tests[i].name); + /* Chdir() to a work dir for this specific test. */ + snprintf(workdir, sizeof(workdir), "%s/%s", tmpdir, tests[i].name); + testworkdir = workdir; + if (!assertMakeDir(testworkdir, 0755) + || !assertChdir(testworkdir)) { + fprintf(stderr, + "ERROR: Can't chdir to work dir %s\n", testworkdir); + exit(1); + } + /* Explicitly reset the locale before each test. */ + setlocale(LC_ALL, "C"); + /* Record the umask before we run the test. */ + umask(oldumask = umask(0)); + /* + * Run the actual test. + */ + (*tests[i].func)(); + /* + * Clean up and report afterwards. + */ + testworkdir = NULL; + /* Restore umask */ + umask(oldumask); + /* Reset locale. */ + setlocale(LC_ALL, "C"); + /* Reset directory. */ + if (!assertChdir(tmpdir)) { + fprintf(stderr, "ERROR: Couldn't chdir to temp dir %s\n", + tmpdir); + exit(1); + } + /* Report per-test summaries. */ + tests[i].failures = failures - failures_before; + test_summarize(tests[i].failures, skips - skips_before); + /* Close the per-test log file. */ + fclose(logfile); + logfile = NULL; + /* If there were no failures, we can remove the work dir and logfile. */ + if (tests[i].failures == 0) { + if (!keep_temp_files && assertChdir(tmpdir)) { +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Make sure not to leave empty directories. + * Sometimes a processing of closing files used by tests + * is not done, then rmdir will be failed and it will + * leave a empty test directory. So we should wait a few + * seconds and retry rmdir. */ + int r, t; + for (t = 0; t < 10; t++) { + if (t > 0) + Sleep(1000); + r = systemf("rmdir /S /Q %s", tests[i].name); + if (r == 0) + break; + } + systemf("del %s", logfilename); +#else + systemf("rm -rf %s", tests[i].name); + systemf("rm %s", logfilename); +#endif + } + } + /* Return appropriate status. */ + return (tests[i].failures); +} + +/* + * + * + * MAIN and support routines. + * + * + */ + +static void +usage(const char *program) +{ + static const int limit = sizeof(tests) / sizeof(tests[0]); + int i; + + printf("Usage: %s [options] ...\n", program); + printf("Default is to run all tests.\n"); + printf("Otherwise, specify the numbers of the tests you wish to run.\n"); + printf("Options:\n"); + printf(" -d Dump core after any failure, for debugging.\n"); + printf(" -k Keep all temp files.\n"); + printf(" Default: temp files for successful tests deleted.\n"); +#ifdef PROGRAM + printf(" -p Path to executable to be tested.\n"); + printf(" Default: path taken from " ENVBASE " environment variable.\n"); +#endif + printf(" -q Quiet.\n"); + printf(" -r Path to dir containing reference files.\n"); + printf(" Default: Current directory.\n"); + printf(" -u Keep running specifies tests until one fails.\n"); + printf(" -v Verbose.\n"); + printf("Available tests:\n"); + for (i = 0; i < limit; i++) + printf(" %d: %s\n", i, tests[i].name); + exit(1); +} + +static char * +get_refdir(const char *d) +{ + size_t tried_size, buff_size; + char *buff, *tried, *pwd = NULL, *p = NULL; + +#ifdef PATH_MAX + buff_size = PATH_MAX; +#else + buff_size = 8192; +#endif + buff = calloc(buff_size, 1); + if (buff == NULL) { + fprintf(stderr, "Unable to allocate memory\n"); + exit(1); + } + + /* Allocate a buffer to hold the various directories we checked. */ + tried_size = buff_size * 2; + tried = calloc(tried_size, 1); + if (tried == NULL) { + fprintf(stderr, "Unable to allocate memory\n"); + exit(1); + } + + /* If a dir was specified, try that */ + if (d != NULL) { + pwd = NULL; + snprintf(buff, buff_size, "%s", d); + p = slurpfile(NULL, "%s/%s", buff, KNOWNREF); + if (p != NULL) goto success; + strncat(tried, buff, tried_size - strlen(tried) - 1); + strncat(tried, "\n", tried_size - strlen(tried) - 1); + goto failure; + } + + /* Get the current dir. */ +#ifdef PATH_MAX + pwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */ +#else + pwd = getcwd(NULL, 0); +#endif + while (pwd[strlen(pwd) - 1] == '\n') + pwd[strlen(pwd) - 1] = '\0'; + + /* Look for a known file. */ + snprintf(buff, buff_size, "%s", pwd); + p = slurpfile(NULL, "%s/%s", buff, KNOWNREF); + if (p != NULL) goto success; + strncat(tried, buff, tried_size - strlen(tried) - 1); + strncat(tried, "\n", tried_size - strlen(tried) - 1); + + snprintf(buff, buff_size, "%s/test", pwd); + p = slurpfile(NULL, "%s/%s", buff, KNOWNREF); + if (p != NULL) goto success; + strncat(tried, buff, tried_size - strlen(tried) - 1); + strncat(tried, "\n", tried_size - strlen(tried) - 1); + +#if defined(LIBRARY) + snprintf(buff, buff_size, "%s/%s/test", pwd, LIBRARY); +#else + snprintf(buff, buff_size, "%s/%s/test", pwd, PROGRAM); +#endif + p = slurpfile(NULL, "%s/%s", buff, KNOWNREF); + if (p != NULL) goto success; + strncat(tried, buff, tried_size - strlen(tried) - 1); + strncat(tried, "\n", tried_size - strlen(tried) - 1); + +#if defined(PROGRAM_ALIAS) + snprintf(buff, buff_size, "%s/%s/test", pwd, PROGRAM_ALIAS); + p = slurpfile(NULL, "%s/%s", buff, KNOWNREF); + if (p != NULL) goto success; + strncat(tried, buff, tried_size - strlen(tried) - 1); + strncat(tried, "\n", tried_size - strlen(tried) - 1); +#endif + + if (memcmp(pwd, "/usr/obj", 8) == 0) { + snprintf(buff, buff_size, "%s", pwd + 8); + p = slurpfile(NULL, "%s/%s", buff, KNOWNREF); + if (p != NULL) goto success; + strncat(tried, buff, tried_size - strlen(tried) - 1); + strncat(tried, "\n", tried_size - strlen(tried) - 1); + + snprintf(buff, buff_size, "%s/test", pwd + 8); + p = slurpfile(NULL, "%s/%s", buff, KNOWNREF); + if (p != NULL) goto success; + strncat(tried, buff, tried_size - strlen(tried) - 1); + strncat(tried, "\n", tried_size - strlen(tried) - 1); + } + +failure: + printf("Unable to locate known reference file %s\n", KNOWNREF); + printf(" Checked following directories:\n%s\n", tried); + printf("Use -r option to specify full path to reference directory\n"); +#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG) + DebugBreak(); +#endif + exit(1); + +success: + free(p); + free(pwd); + free(tried); + + /* Copy result into a fresh buffer to reduce memory usage. */ + p = strdup(buff); + free(buff); + return p; +} + +int +main(int argc, char **argv) +{ + static const int limit = sizeof(tests) / sizeof(tests[0]); + int test_set[sizeof(tests) / sizeof(tests[0])]; + int i = 0, j = 0, tests_run = 0, tests_failed = 0, option; + time_t now; + char *refdir_alloc = NULL; + const char *progname; + char **saved_argv; + const char *tmp, *option_arg, *p; +#ifdef PATH_MAX + char tmpdir[PATH_MAX]; +#else + char tmpdir[256]; +#endif + char *pwd, *testprogdir, *tmp2 = NULL, *vlevel = NULL; + char tmpdir_timestamp[32]; + + (void)argc; /* UNUSED */ + + /* Get the current dir. */ +#ifdef PATH_MAX + pwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */ +#else + pwd = getcwd(NULL, 0); +#endif + while (pwd[strlen(pwd) - 1] == '\n') + pwd[strlen(pwd) - 1] = '\0'; + +#if defined(HAVE__CrtSetReportMode) && !defined(__WATCOMC__) + /* To stop to run the default invalid parameter handler. */ + _set_invalid_parameter_handler(invalid_parameter_handler); + /* Disable annoying assertion message box. */ + _CrtSetReportMode(_CRT_ASSERT, 0); +#endif + + /* + * Name of this program, used to build root of our temp directory + * tree. + */ + progname = p = argv[0]; + if ((testprogdir = (char *)malloc(strlen(progname) + 1)) == NULL) + { + fprintf(stderr, "ERROR: Out of memory."); + exit(1); + } + strcpy(testprogdir, progname); + while (*p != '\0') { + /* Support \ or / dir separators for Windows compat. */ + if (*p == '/' || *p == '\\') + { + progname = p + 1; + i = j; + } + ++p; + j++; + } + testprogdir[i] = '\0'; +#if defined(_WIN32) && !defined(__CYGWIN__) + if (testprogdir[0] != '/' && testprogdir[0] != '\\' && + !(((testprogdir[0] >= 'a' && testprogdir[0] <= 'z') || + (testprogdir[0] >= 'A' && testprogdir[0] <= 'Z')) && + testprogdir[1] == ':' && + (testprogdir[2] == '/' || testprogdir[2] == '\\'))) +#else + if (testprogdir[0] != '/') +#endif + { + /* Fixup path for relative directories. */ + if ((testprogdir = (char *)realloc(testprogdir, + strlen(pwd) + 1 + strlen(testprogdir) + 1)) == NULL) + { + fprintf(stderr, "ERROR: Out of memory."); + exit(1); + } + memmove(testprogdir + strlen(pwd) + 1, testprogdir, + strlen(testprogdir) + 1); + memcpy(testprogdir, pwd, strlen(pwd)); + testprogdir[strlen(pwd)] = '/'; + } + +#ifdef PROGRAM + /* Get the target program from environment, if available. */ + testprogfile = getenv(ENVBASE); +#endif + + if (getenv("TMPDIR") != NULL) + tmp = getenv("TMPDIR"); + else if (getenv("TMP") != NULL) + tmp = getenv("TMP"); + else if (getenv("TEMP") != NULL) + tmp = getenv("TEMP"); + else if (getenv("TEMPDIR") != NULL) + tmp = getenv("TEMPDIR"); + else + tmp = "/tmp"; + + /* Allow -d to be controlled through the environment. */ + if (getenv(ENVBASE "_DEBUG") != NULL) + dump_on_failure = 1; + + /* Allow -v to be controlled through the environment. */ + if (getenv("_VERBOSITY_LEVEL") != NULL) + { + vlevel = getenv("_VERBOSITY_LEVEL"); + verbosity = atoi(vlevel); + if (verbosity < VERBOSITY_SUMMARY_ONLY || verbosity > VERBOSITY_FULL) + { + /* Unsupported verbosity levels are silently ignored */ + vlevel = NULL; + verbosity = VERBOSITY_PASSFAIL; + } + } + + /* Get the directory holding test files from environment. */ + refdir = getenv(ENVBASE "_TEST_FILES"); + + /* + * Parse options, without using getopt(), which isn't available + * on all platforms. + */ + ++argv; /* Skip program name */ + while (*argv != NULL) { + if (**argv != '-') + break; + p = *argv++; + ++p; /* Skip '-' */ + while (*p != '\0') { + option = *p++; + option_arg = NULL; + /* If 'opt' takes an argument, parse that. */ + if (option == 'p' || option == 'r') { + if (*p != '\0') + option_arg = p; + else if (*argv == NULL) { + fprintf(stderr, + "Option -%c requires argument.\n", + option); + usage(progname); + } else + option_arg = *argv++; + p = ""; /* End of this option word. */ + } + + /* Now, handle the option. */ + switch (option) { + case 'd': + dump_on_failure = 1; + break; + case 'k': + keep_temp_files = 1; + break; + case 'p': +#ifdef PROGRAM + testprogfile = option_arg; +#else + fprintf(stderr, "-p option not permitted\n"); + usage(progname); +#endif + break; + case 'q': + if (!vlevel) + verbosity--; + break; + case 'r': + refdir = option_arg; + break; + case 'u': + until_failure++; + break; + case 'v': + if (!vlevel) + verbosity++; + break; + default: + fprintf(stderr, "Unrecognized option '%c'\n", + option); + usage(progname); + } + } + } + + /* + * Sanity-check that our options make sense. + */ +#ifdef PROGRAM + if (testprogfile == NULL) + { + if ((tmp2 = (char *)malloc(strlen(testprogdir) + 1 + + strlen(PROGRAM) + 1)) == NULL) + { + fprintf(stderr, "ERROR: Out of memory."); + exit(1); + } + strcpy(tmp2, testprogdir); + strcat(tmp2, "/"); + strcat(tmp2, PROGRAM); + testprogfile = tmp2; + } + + { + char *testprg; +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Command.com sometimes rejects '/' separators. */ + testprg = strdup(testprogfile); + for (i = 0; testprg[i] != '\0'; i++) { + if (testprg[i] == '/') + testprg[i] = '\\'; + } + testprogfile = testprg; +#endif + /* Quote the name that gets put into shell command lines. */ + testprg = malloc(strlen(testprogfile) + 3); + strcpy(testprg, "\""); + strcat(testprg, testprogfile); + strcat(testprg, "\""); + testprog = testprg; + } +#endif + +#if !defined(_WIN32) && defined(SIGPIPE) + { /* Ignore SIGPIPE signals */ + struct sigaction sa; + sa.sa_handler = SIG_IGN; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(SIGPIPE, &sa, NULL); + } +#endif + + /* + * Create a temp directory for the following tests. + * Include the time the tests started as part of the name, + * to make it easier to track the results of multiple tests. + */ + now = time(NULL); + for (i = 0; ; i++) { + strftime(tmpdir_timestamp, sizeof(tmpdir_timestamp), + "%Y-%m-%dT%H.%M.%S", + localtime(&now)); + if ((strlen(tmp) + 1 + strlen(progname) + 1 + + strlen(tmpdir_timestamp) + 1 + 3) > + (sizeof(tmpdir) / sizeof(char))) { + fprintf(stderr, + "ERROR: Temp directory pathname too long\n"); + exit(1); + } + snprintf(tmpdir, sizeof(tmpdir), "%s/%s.%s-%03d", tmp, + progname, tmpdir_timestamp, i); + if (assertMakeDir(tmpdir,0755)) + break; + if (i >= 999) { + fprintf(stderr, + "ERROR: Unable to create temp directory %s\n", + tmpdir); + exit(1); + } + } + + /* + * If the user didn't specify a directory for locating + * reference files, try to find the reference files in + * the "usual places." + */ + refdir = refdir_alloc = get_refdir(refdir); + + /* + * Banner with basic information. + */ + printf("\n"); + printf("If tests fail or crash, details will be in:\n"); + printf(" %s\n", tmpdir); + printf("\n"); + if (verbosity > VERBOSITY_SUMMARY_ONLY) { + printf("Reference files will be read from: %s\n", refdir); +#ifdef PROGRAM + printf("Running tests on: %s\n", testprog); +#endif + printf("Exercising: "); + fflush(stdout); + printf("%s\n", EXTRA_VERSION); + } else { + printf("Running "); + fflush(stdout); + } + + /* + * Run some or all of the individual tests. + */ + saved_argv = argv; + do { + argv = saved_argv; + do { + int test_num; + + test_num = get_test_set(test_set, limit, *argv, tests); + if (test_num < 0) { + printf("*** INVALID Test %s\n", *argv); + free(refdir_alloc); + free(testprogdir); + usage(progname); + return (1); + } + for (i = 0; i < test_num; i++) { + tests_run++; + if (test_run(test_set[i], tmpdir)) { + tests_failed++; + if (until_failure) + goto finish; + } + } + if (*argv != NULL) + argv++; + } while (*argv != NULL); + } while (until_failure); + +finish: + /* Must be freed after all tests run */ + free(tmp2); + free(testprogdir); + free(pwd); + + /* + * Report summary statistics. + */ + if (verbosity > VERBOSITY_SUMMARY_ONLY) { + printf("\n"); + printf("Totals:\n"); + printf(" Tests run: %8d\n", tests_run); + printf(" Tests failed: %8d\n", tests_failed); + printf(" Assertions checked:%8d\n", assertions); + printf(" Assertions failed: %8d\n", failures); + printf(" Skips reported: %8d\n", skips); + } + if (failures) { + printf("\n"); + printf("Failing tests:\n"); + for (i = 0; i < limit; ++i) { + if (tests[i].failures) + printf(" %d: %s (%d failures)\n", i, + tests[i].name, tests[i].failures); + } + printf("\n"); + printf("Details for failing tests: %s\n", tmpdir); + printf("\n"); + } else { + if (verbosity == VERBOSITY_SUMMARY_ONLY) + printf("\n"); + printf("%d tests passed, no failures\n", tests_run); + } + + free(refdir_alloc); + + /* If the final tmpdir is empty, we can remove it. */ + /* This should be the usual case when all tests succeed. */ + assertChdir(".."); + rmdir(tmpdir); + + return (tests_failed ? 1 : 0); +} diff --git a/dependencies/libarchive-3.4.2/test_utils/test_utils.c b/dependencies/libarchive-3.4.2/test_utils/test_utils.c new file mode 100644 index 0000000..8ea3d3c --- /dev/null +++ b/dependencies/libarchive-3.4.2/test_utils/test_utils.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2003-2012 Tim Kientzle + * Copyright (c) 2012 Andres Mejia + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test_utils.h" + +#include +#include + +/* Filter tests against a glob pattern. Returns non-zero if test matches + * pattern, zero otherwise. A '^' at the beginning of the pattern negates + * the return values (i.e. returns zero for a match, non-zero otherwise. + */ +static int +test_filter(const char *pattern, const char *test) +{ + int retval = 0; + int negate = 0; + const char *p = pattern; + const char *t = test; + + if (p[0] == '^') + { + negate = 1; + p++; + } + + while (1) + { + if (p[0] == '\\') + p++; + else if (p[0] == '*') + { + while (p[0] == '*') + p++; + if (p[0] == '\\') + p++; + if ((t = strchr(t, p[0])) == 0) + break; + } + if (p[0] != t[0]) + break; + if (p[0] == '\0') { + retval = 1; + break; + } + p++; + t++; + } + + return (negate) ? !retval : retval; +} + +int get_test_set(int *test_set, int limit, const char *test, + struct test_list_t *tests) +{ + int start, end; + int idx = 0; + + if (test == NULL) { + /* Default: Run all tests. */ + for (;idx < limit; idx++) + test_set[idx] = idx; + return (limit); + } + if (*test >= '0' && *test <= '9') { + const char *vp = test; + start = 0; + while (*vp >= '0' && *vp <= '9') { + start *= 10; + start += *vp - '0'; + ++vp; + } + if (*vp == '\0') { + end = start; + } else if (*vp == '-') { + ++vp; + if (*vp == '\0') { + end = limit - 1; + } else { + end = 0; + while (*vp >= '0' && *vp <= '9') { + end *= 10; + end += *vp - '0'; + ++vp; + } + } + } else + return (-1); + if (start < 0 || end >= limit || start > end) + return (-1); + while (start <= end) + test_set[idx++] = start++; + } else { + for (start = 0; start < limit; ++start) { + const char *name = tests[start].name; + if (test_filter(test, name)) + test_set[idx++] = start; + } + } + return ((idx == 0)?-1:idx); +} diff --git a/dependencies/libarchive-3.4.2/test_utils/test_utils.h b/dependencies/libarchive-3.4.2/test_utils/test_utils.h new file mode 100644 index 0000000..164c528 --- /dev/null +++ b/dependencies/libarchive-3.4.2/test_utils/test_utils.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2003-2012 Tim Kientzle + * Copyright (c) 2012 Andres Mejia + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TEST_UTILS_H +#define TEST_UTILS_H + +struct test_list_t +{ + void (*func)(void); + const char *name; + int failures; +}; + +int get_test_set(int *, int, const char *, struct test_list_t *); + +#endif /* TEST_UTILS_H */ diff --git a/dependencies/mountutils/.editorconfig b/dependencies/mountutils/.editorconfig new file mode 100644 index 0000000..5d12634 --- /dev/null +++ b/dependencies/mountutils/.editorconfig @@ -0,0 +1,13 @@ +# editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/dependencies/mountutils/.eslintrc.yml b/dependencies/mountutils/.eslintrc.yml new file mode 100644 index 0000000..affaa10 --- /dev/null +++ b/dependencies/mountutils/.eslintrc.yml @@ -0,0 +1,477 @@ +env: + browser: true + commonjs: true + es6: true + node: true + mocha: true +extends: 'eslint:recommended' +rules: + + # Possible Errors + + comma-dangle: + - error + - never + no-cond-assign: + - error + no-console: + - off + no-constant-condition: + - error + no-control-regex: + - error + no-debugger: + - error + no-dupe-args: + - error + no-dupe-keys: + - error + no-duplicate-case: + - error + no-empty: + - error + no-empty-character-class: + - error + no-ex-assign: + - error + no-extra-boolean-cast: + - error + no-extra-parens: + - error + no-extra-semi: + - error + no-func-assign: + - error + no-inner-declarations: + - error + - both + no-invalid-regexp: + - error + no-irregular-whitespace: + - error + no-negated-in-lhs: + - error + no-obj-calls: + - error + no-prototype-builtins: + - error + no-regex-spaces: + - error + no-sparse-arrays: + - error + no-unexpected-multiline: + - error + no-unreachable: + - error + no-unsafe-finally: + - error + use-isnan: + - error + valid-jsdoc: + - error + - requireReturn: false + requireReturnDescription: false + requireReturnType: true + requireParamDescription: true + preferType: + boolean: "Boolean" + number: "Number" + object: "Object" + string: "String" + array: "Array" + prefer: + arg: "param" + return: "returns" + valid-typeof: + - error + + # Best Practices + + accessor-pairs: + - error + array-callback-return: + - error + block-scoped-var: + - error + complexity: + - off + curly: + - error + default-case: + - error + dot-location: + - error + - property + dot-notation: + - error + eqeqeq: + - error + guard-for-in: + - error + no-alert: + - error + no-caller: + - error + no-case-declarations: + - error + no-div-regex: + - error + no-else-return: + - error + no-empty-function: + - error + no-empty-pattern: + - error + no-eq-null: + - error + no-eval: + - error + no-extend-native: + - error + no-extra-bind: + - error + no-extra-label: + - error + no-fallthrough: + - error + no-floating-decimal: + - error + no-implicit-coercion: + - error + no-implicit-globals: + - error + no-implied-eval: + - error + no-iterator: + - error + no-labels: + - error + no-lone-blocks: + - error + no-loop-func: + - error + no-multi-spaces: + - error + no-multi-str: + - error + no-native-reassign: + - error + no-new: + - error + no-new-func: + - error + no-new-wrappers: + - error + no-octal: + - error + no-octal-escape: + - error + no-proto: + - error + no-redeclare: + - error + no-return-assign: + - error + no-script-url: + - error + no-self-assign: + - error + no-self-compare: + - error + no-sequences: + - error + no-throw-literal: + - error + no-unmodified-loop-condition: + - error + no-unused-labels: + - error + no-useless-call: + - error + no-useless-concat: + - error + no-useless-escape: + - error + no-void: + - error + no-warning-comments: + - off + no-with: + - error + radix: + - error + vars-on-top: + - off + wrap-iife: + - error + - outside + yoda: + - error + + # Strict mode + + strict: + - error + - global + + # Variables + + no-catch-shadow: + - error + no-delete-var: + - error + no-label-var: + - error + no-shadow: + - error + no-shadow-restricted-names: + - error + no-undef: + - error + no-undef-init: + - error + no-unused-vars: + - error + no-use-before-define: + - error + + # NodeJS and CommonJS + + callback-return: + - error + global-require: + - off + handle-callback-err: + - error + no-mixed-requires: + - error + no-new-require: + - error + no-path-concat: + - error + no-process-env: + - off + no-process-exit: + - off + no-sync: + - off + + # Stylistic Issues + + array-bracket-spacing: + - error + - always + block-spacing: + - error + brace-style: + - error + - 1tbs + camelcase: + - error + comma-spacing: + - error + - before: false + after: true + comma-style: + - error + - last + computed-property-spacing: + - error + - never + consistent-this: + - error + - self + eol-last: + - error + func-names: + - error + - never + func-style: + - error + - expression + id-blacklist: + - error + indent: + - error + - 2 + - SwitchCase: 1 + key-spacing: + - error + - beforeColon: false + afterColon: true + mode: strict + keyword-spacing: + - error + - before: true + after: true + lines-around-comment: + - error + - beforeBlockComment: true + afterBlockComment: false + beforeLineComment: true + afterLineComment: false + allowBlockStart: true + allowBlockEnd: false + allowObjectStart: true + allowObjectEnd: false + allowArrayStart: true + allowArrayEnd: false + max-len: + - error + - code: 130 + comments: 150 + ignoreComments: false + ignoreTrailingComments: false + ignoreUrls: true + max-statements-per-line: + - error + - max: 1 + new-cap: + - error + new-parens: + - error + no-array-constructor: + - error + no-bitwise: + - error + no-continue: + - error + no-inline-comments: + - error + no-mixed-operators: + - error + no-mixed-spaces-and-tabs: + - error + no-multiple-empty-lines: + - error + - max: 1 + maxEOF: 1 + maxBOF: 0 + no-negated-condition: + - error + no-nested-ternary: + - error + no-new-object: + - error + no-plusplus: + - error + no-spaced-func: + - error + no-trailing-spaces: + - error + no-underscore-dangle: + - error + - allowAfterThis: false + no-unneeded-ternary: + - error + no-whitespace-before-property: + - error + object-curly-newline: + - error + - minProperties: 1 + object-curly-spacing: + - error + - always + object-property-newline: + - error + one-var: + - error + - never + operator-assignment: + - error + - always + operator-linebreak: + - error + - before + quote-props: + - error + - as-needed + quotes: + - error + - single + require-jsdoc: + - error + - require: + FunctionDeclaration: true + ClassDeclaration: true + MethodDefinition: true + semi: + - error + - always + semi-spacing: + - error + - before: false + after: true + space-before-blocks: + - error + space-before-function-paren: + - error + - never + space-in-parens: + - error + - never + space-infix-ops: + - error + spaced-comment: + - error + - always + unicode-bom: + - error + + # ECMAScript 6 + + arrow-body-style: + - error + - always + arrow-parens: + - error + - always + arrow-spacing: + - error + - before: true + after: true + constructor-super: + - error + generator-star-spacing: + - error + - before: true + after: false + no-class-assign: + - error + no-confusing-arrow: + - error + no-const-assign: + - error + no-dupe-class-members: + - error + no-duplicate-imports: + - error + no-new-symbol: + - error + no-this-before-super: + - error + no-useless-computed-key: + - error + no-useless-constructor: + - error + no-useless-rename: + - error + no-var: + - error + prefer-const: + - error + prefer-reflect: + - error + prefer-spread: + - error + require-yield: + - error + rest-spread-spacing: + - error + template-curly-spacing: + - error + - never + yield-star-spacing: + - error + - before: true + after: false diff --git a/dependencies/mountutils/.gitignore b/dependencies/mountutils/.gitignore new file mode 100644 index 0000000..f41f398 --- /dev/null +++ b/dependencies/mountutils/.gitignore @@ -0,0 +1,3 @@ +node_modules +build/ +prebuilds diff --git a/dependencies/mountutils/.npmignore b/dependencies/mountutils/.npmignore new file mode 100644 index 0000000..d141396 --- /dev/null +++ b/dependencies/mountutils/.npmignore @@ -0,0 +1,14 @@ +# Files +.* +*.md +*.log +*.yml + +# Directories +doc +tests +build +example +benchmark +prebuilds +scripts diff --git a/dependencies/mountutils/.travis.yml b/dependencies/mountutils/.travis.yml new file mode 100644 index 0000000..6b19e4b --- /dev/null +++ b/dependencies/mountutils/.travis.yml @@ -0,0 +1,46 @@ +language: node_js +node_js: + - 6 + - 8 + - 10 + - 12 +os: + - linux + - osx +before_install: + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then + pip install --user -r requirements.txt; + else + pip2 install -r requirements.txt; + fi +script: + - npm test +compiler: clang-4.0 +env: + global: + - CCACHE_TEMPDIR=/tmp/.ccache-temp + - CCACHE_COMPRESS=1 + - CC="clang" + - CXX="clang++" + matrix: + - TARGET_ARCH=x64 + - TARGET_ARCH=x86 +matrix: + exclude: + - os: osx + env: TARGET_ARCH=x86 +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - libstdc++-5-dev +notifications: + email: false +deploy: + skip_cleanup: true + provider: script + script: scripts/prebuild-publish.sh + on: + tags: true + branch: master diff --git a/dependencies/mountutils/CHANGELOG.md b/dependencies/mountutils/CHANGELOG.md new file mode 100644 index 0000000..b8c83a2 --- /dev/null +++ b/dependencies/mountutils/CHANGELOG.md @@ -0,0 +1,155 @@ +# Change Log + +All notable changes to this project will be documented in this file +automatically by Versionist. DO NOT EDIT THIS FILE MANUALLY! +This project adheres to [Semantic Versioning](http://semver.org/). + +## 1.3.19 - 2019-05-23 + +* Housekeeping: add CODEOWNERS [Gergely Imreh] + +## 1.3.18 - 2019-05-23 + +* Ci: update Appveyor prebuild-publish script for batch scripting fixes [Gergely Imreh] +* Scripts: remove linting from the testing step [Gergely Imreh] +* Ci: update appveyor and travis setting for extra Node versions [Gergely Imreh] +* Dependencies: Update code to be ready for Node 12 [Gergely Imreh] + +## 1.3.17 - 2019-03-12 + +* Remove useless sleeps and wrong debug "Retrying" messages [Alexis Svinartchouk] + +## 1.3.16 - 2019-01-11 + +* Fix build on Xcode 10.1 [Alexis Svinartchouk] + +## v1.3.15 - 2018-07-06 + +* Fix(linux): Use threadsafe getmntent() #69 [Jonas Hermsmeier] + +## v1.3.14 - 2018-06-19 + +* Fix(test): Add python requirements.txt #68 [Jonas Hermsmeier] + +## v1.3.13 - 2018-06-08 + +* Upgrade(package): Bump depenencies #67 [Jonas Hermsmeier] + +## v1.3.12 - 2018-05-25 + +* Fix(src): Fix nan callback->call deprecation #66 [Jonas Hermsmeier] + +## v1.3.11 - 2018-04-02 + +* Upgrade(package): Bump dependencies #65 [Jonas Hermsmeier] + +## v1.3.10 - 2018-01-20 + +* Fix(linux): Fix partial unmounts on Linux #64 [Jonas Hermsmeier] + +## v1.3.9 - 2018-01-18 + +* Fix(windows): Link to appropriate libraries #63 [Jonas Hermsmeier] + +## v1.3.8 - 2017-12-21 + +* Upgrade(package): Bump dependencies #61 [Jonas Hermsmeier] + +## v1.3.7 - 2017-12-14 + +* Fix(package): Fix prebuild script being run on build #59 [Jonas Hermsmeier] + +## v1.3.6 - 2017-12-12 + +* Test(ci): Fix pip -> pip2 on Travis CI #60 [Jonas Hermsmeier] + +## v1.3.5 - 2017-10-19 + +* Chore(scripts): Run CI on x86 as well #58 [Jonas Hermsmeier] + +## v1.3.4 - 2017-10-18 + +* Chore(scripts): Also prebuild x86 on Windows and Linux #57 [Jonas Hermsmeier] + +## v1.3.3 - 2017-10-17 + +* Upgrade(package): Bump dependencies #56 [Jonas Hermsmeier] + +## v1.3.2 - 2017-10-15 + +* Make publishing scripts executable ...hopefully this will fix deploy errors #55 [Andrew Scheller] + +## v1.3.1 - 2017-10-13 + +* Fix(scripts): Ensure the Travis box finds bash #52 [Jonas Hermsmeier] +* Chore(CHANGELOG): Fix changelog formatting #52 [Jonas Hermsmeier] + +## v1.3.0 - 2017-10-13 + +* Chore(ci): Add CI deployment scripts [Jonas Hermsmeier] +* Feat(package): Add prebuilds for native bindings [Jonas Hermsmeier] +* Chore(appveyor): Use VS2015 base image [Jonas Hermsmeier] +* Upgrade(package): Update dependencies [Jonas Hermsmeier] + +## v1.2.2 - 2017-08-28 + +### Changed + +- Retry ejection various times before giving up on Windows + +## v1.2.1 - 2017-07-23 + +### Changed + +- Retry the unmount operation if the loop times out in macOS + +## v1.2.0 - 2017-05-30 + +### Changed + +- Use `Nan::AsyncWorker` to avoid blocking the main thread +- Fix global state on Mac OS causing improper return values + +## v1.1.0 - 2017-05-11 + +### Changed + +- Add `.eject()` method to unmount & eject a device + +## v1.0.6 - 2017-04-21 + +### Changed + +- Fix "Unmount failed" error on Windows when there are network drives. + +## v1.0.5 - 2017-04-14 + +### Added + +- Add extra logging when setting `MOUNTUTILS_DEBUG`. + +## v1.0.4 - 2017-04-12 + +### Changed + +- Don't throw "invalid drive" for Windows drives that have no logical volumes + attached. + +## v1.0.3 - 2017-04-07 + +### Changed + +- Make `bindings` correctly resolve the node add-on location even when + concatenated with Browserify. + +## v1.0.2 - 2017-03-30 + +### Changed + +- Don't include build directory in npm package + +## v1.0.1 - 2017-03-27 + +### Changed + +- Fix Windows build failures when installing from npm diff --git a/dependencies/mountutils/MANUAL_TESTS.md b/dependencies/mountutils/MANUAL_TESTS.md new file mode 100644 index 0000000..c81279d --- /dev/null +++ b/dependencies/mountutils/MANUAL_TESTS.md @@ -0,0 +1,9 @@ +Manual Tests +============ + +Windows: + +- [x] SD Card reader +- [x] USB Drive +- [ ] USB HDD (does nothing) +- [x] Multi SD Card reader diff --git a/dependencies/mountutils/README.md b/dependencies/mountutils/README.md new file mode 100644 index 0000000..28d253d --- /dev/null +++ b/dependencies/mountutils/README.md @@ -0,0 +1,116 @@ +mountutils +========== + +[![npm](https://img.shields.io/npm/v/mountutils.svg?style=flat-square)](https://npmjs.com/package/mountutils) +[![npm license](https://img.shields.io/npm/l/mountutils.svg?style=flat-square)](https://npmjs.com/package/mountutils) +[![npm downloads](https://img.shields.io/npm/dm/mountutils.svg?style=flat-square)](https://npmjs.com/package/mountutils) +[![Travis CI status](https://img.shields.io/travis/resin-io-modules/mountutils/master.svg?style=flat-square&label=linux%20|%20mac)](https://travis-ci.org/resin-io-modules/mountutils/branches) +[![AppVeyor status](https://img.shields.io/appveyor/ci/resin-io/mountutils/master.svg?style=flat-square&label=windows)](https://ci.appveyor.com/project/resin-io/mountutils/branch/master) + +> Cross platform mount related utilities + +Installation +------------ + +Install `mountutils` by running: + +```sh +$ npm install --save mountutils +``` + +Debug mode +---------- + +You can enable debug mode by setting the `MOUNTUTILS_DEBUG` environment +variable. + +Documentation +------------- + + + +### mountutils.unmountDisk(device, callback) +**Kind**: static method of [mountutils](#module_mountutils) +**Summary**: Unmount a whole disk +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| device | String | device | +| callback | function | callback (error) | + +**Example** +```js +// macOS +const drive = '/dev/disk2'; + +// GNU/Linux +const drive = '/dev/sdb'; + +// Windows +const drive = '\\\\.\\PHYSICALDRIVE2'; + +mountutils.unmountDisk(drive, (error) => { + if (error) { + throw error; + } + + console.log('Done!'); +}); +``` + +Support +------- + +If you're having any problem, please [raise an issue][newissue] on GitHub and +the Resin.io team will be happy to help. + +Tests +----- + +Run the test suite by doing: + +```sh +$ npm test +``` + +Troubleshooting +--------------- + +### `error C2373: '__pfnDliNotifyHook2': redefinition` + +This error indicates that the version of npm you're running is too old. Upgrade +by running: + +```sh +npm install -g npm@latest +``` + +See the [following `node-gyp` issue](https://github.com/nodejs/node-gyp/issues/972) for more details. + +Contribute +---------- + +- Issue Tracker: [github.com/resin-io-modules/mountutils/issues][issues] +- Source Code: [github.com/resin-io-modules/mountutils][source] + +### Dependencies + +- [cpplint][cpplint] + +Before submitting a PR, please make sure that you include tests, and that +linters run without any warning: + +```sh +$ npm run lint +``` + +License +------- + +The project is licensed under the Apache 2.0 license. + +[issues]: https://github.com/resin-io-modules/mountutils/issues +[newissue]: https://github.com/resin-io-modules/mountutils/issues/new +[source]: https://github.com/resin-io-modules/mountutils +[cpplint]: https://github.com/cpplint/cpplint diff --git a/dependencies/mountutils/appveyor.yml b/dependencies/mountutils/appveyor.yml new file mode 100644 index 0000000..d585c88 --- /dev/null +++ b/dependencies/mountutils/appveyor.yml @@ -0,0 +1,40 @@ +# appveyor file +# http://www.appveyor.com/docs/appveyor-yml +image: + - Visual Studio 2015 + +init: + - git config --global core.autocrlf input + +cache: + - C:\Users\appveyor\.node-gyp + - '%AppData%\npm-cache' + +environment: + matrix: + - nodejs_version: 6 + - nodejs_version: 8 + - nodejs_version: 10 + - nodejs_version: 12 + +platform: + - x86 + - x64 + +install: + # https://www.appveyor.com/docs/lang/nodejs-iojs/#installing-any-version-of-nodejs-or-iojs + - ps: Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version) $env:PLATFORM + - npm -g install npm@latest + - set PATH=%APPDATA%\npm;%PATH% + - npm install --build-from-source + - pip install -r requirements.txt + +build: off + +test_script: + - node --version + - npm --version + - cmd: npm test + +deploy_script: + - scripts\prebuild-publish.bat diff --git a/dependencies/mountutils/binding.gyp b/dependencies/mountutils/binding.gyp new file mode 100644 index 0000000..fbb6925 --- /dev/null +++ b/dependencies/mountutils/binding.gyp @@ -0,0 +1,66 @@ +{ + "targets": [ + { + "target_name": "MountUtils", + "include_dirs" : [ + " Cross platform mount related utilities + +Installation +------------ + +Install `mountutils` by running: + +```sh +$ npm install --save mountutils +``` + +Debug mode +---------- + +You can enable debug mode by setting the `MOUNTUTILS_DEBUG` environment +variable. + +Documentation +------------- + +{{#module name="mountutils"}} +{{>body~}} +{{>member-index~}} +{{>separator~}} +{{>members~}} +{{/module}} + +Support +------- + +If you're having any problem, please [raise an issue][newissue] on GitHub and +the Resin.io team will be happy to help. + +Tests +----- + +Run the test suite by doing: + +```sh +$ npm test +``` + +Troubleshooting +--------------- + +### `error C2373: '__pfnDliNotifyHook2': redefinition` + +This error indicates that the version of npm you're running is too old. Upgrade +by running: + +```sh +npm install -g npm@latest +``` + +See the [following `node-gyp` issue](https://github.com/nodejs/node-gyp/issues/972) for more details. + +Contribute +---------- + +- Issue Tracker: [github.com/resin-io-modules/mountutils/issues][issues] +- Source Code: [github.com/resin-io-modules/mountutils][source] + +### Dependencies + +- [cpplint][cpplint] + +Before submitting a PR, please make sure that you include tests, and that +linters run without any warning: + +```sh +$ npm run lint +``` + +License +------- + +The project is licensed under the Apache 2.0 license. + +[issues]: https://github.com/resin-io-modules/mountutils/issues +[newissue]: https://github.com/resin-io-modules/mountutils/issues/new +[source]: https://github.com/resin-io-modules/mountutils +[cpplint]: https://github.com/cpplint/cpplint diff --git a/dependencies/mountutils/example/eject.js b/dependencies/mountutils/example/eject.js new file mode 100644 index 0000000..f74bec7 --- /dev/null +++ b/dependencies/mountutils/example/eject.js @@ -0,0 +1,36 @@ +#!/usr/bin/env node +/* + * Copyright 2017 resin.io + * + * 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. + */ + +'use strict'; + +const mountUtils = require('..'); + +let argv = process.argv.slice(2); +let disk = argv.shift(); + +if (!disk) { + console.error(`Usage: node example/eject `); + process.exit(1); +} + +process.env.MOUNTUTILS_DEBUG = true; + +console.log('Ejecting', disk, '...'); + +mountUtils.eject(disk, function(error) { + console.log(error || 'OK'); +}); diff --git a/dependencies/mountutils/example/unmount.js b/dependencies/mountutils/example/unmount.js new file mode 100644 index 0000000..2f7027f --- /dev/null +++ b/dependencies/mountutils/example/unmount.js @@ -0,0 +1,36 @@ +#!/usr/bin/env node +/* + * Copyright 2017 resin.io + * + * 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. + */ + +'use strict'; + +const mountUtils = require('..'); + +let argv = process.argv.slice(2); +let disk = argv.shift(); + +if (!disk) { + console.error(`Usage: node example/unmount `); + process.exit(1); +} + +process.env.MOUNTUTILS_DEBUG = true; + +console.log('Unmounting', disk, '...'); + +mountUtils.unmountDisk(disk, function(error) { + console.log(error || 'OK'); +}); diff --git a/dependencies/mountutils/index.js b/dependencies/mountutils/index.js new file mode 100644 index 0000000..f16b55a --- /dev/null +++ b/dependencies/mountutils/index.js @@ -0,0 +1,57 @@ +/* + * Copyright 2017 resin.io + * + * 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. + */ + +/** + * @module mountutils + */ + +'use strict'; + +/** + * @summary Unmount a whole disk + * @function + * @public + * @static + * @name unmountDisk + * + * @param {String} device - device + * @param {Function} callback - callback (error) + * + * @example + * // macOS + * const drive = '/dev/disk2'; + * + * // GNU/Linux + * const drive = '/dev/sdb'; + * + * // Windows + * const drive = '\\\\.\\PHYSICALDRIVE2'; + * + * mountutils.unmountDisk(drive, (error) => { + * if (error) { + * throw error; + * } + * + * console.log('Done!'); + * }); + */ + +module.exports = require('bindings')({ + bindings: 'MountUtils', + /* eslint-disable camelcase */ + module_root: __dirname + /* eslint-enable camelcase */ +}); diff --git a/dependencies/mountutils/package.json b/dependencies/mountutils/package.json new file mode 100644 index 0000000..ff6f03a --- /dev/null +++ b/dependencies/mountutils/package.json @@ -0,0 +1,52 @@ +{ + "name": "mountutils", + "version": "1.3.19", + "main": "index.js", + "description": "Cross platform mount related utilities", + "homepage": "https://github.com/resin-io-modules/mountutils", + "repository": { + "type": "git", + "url": "git://github.com/resin-io-modules/mountutils.git" + }, + "keywords": [ + "mount", + "utils", + "unmount", + "unmounDisk", + "cross", + "platform" + ], + "directories": { + "test": "tests" + }, + "scripts": { + "configure": "node-gyp configure", + "build": "node-gyp build", + "rebuild": "node-gyp rebuild", + "readme": "jsdoc2md --template docs/README.hbs index.js > README.md", + "lint-js": "eslint *.js", + "lint-cpp": "cpplint --recursive src", + "lint": "npm run lint-js && npm run lint-cpp", + "test": "mocha tests -R spec", + "install": "prebuild-install || node-gyp rebuild", + "prebuild-release": "prebuild --all --strip" + }, + "author": "Juan Cruz Viotti ", + "license": "Apache-2.0", + "devDependencies": { + "chai": "^4.1.2", + "eslint": "^4.19.1", + "jsdoc-to-markdown": "^4.0.1", + "mocha": "^5.2.0", + "prebuild": "^7.6.0" + }, + "dependencies": { + "bindings": "^1.3.0", + "nan": "^2.14.0", + "prebuild-install": "^4.0.0" + }, + "gypfile": true, + "bugs": { + "url": "https://github.com/resin-io-modules/mountutils/issues" + } +} diff --git a/dependencies/mountutils/requirements.txt b/dependencies/mountutils/requirements.txt new file mode 100644 index 0000000..ca3b3e8 --- /dev/null +++ b/dependencies/mountutils/requirements.txt @@ -0,0 +1 @@ +cpplint==1.3.0 diff --git a/dependencies/mountutils/scripts/prebuild-publish.bat b/dependencies/mountutils/scripts/prebuild-publish.bat new file mode 100644 index 0000000..536ccac --- /dev/null +++ b/dependencies/mountutils/scripts/prebuild-publish.bat @@ -0,0 +1,7 @@ +@echo off + +IF "%APPVEYOR_REPO_BRANCH%"=="master" ( + IF "%GITHUB_TOKEN%" NEQ "" ( + npm run prebuild-release -- -u %GITHUB_TOKEN% + ) +) diff --git a/dependencies/mountutils/scripts/prebuild-publish.sh b/dependencies/mountutils/scripts/prebuild-publish.sh new file mode 100644 index 0000000..dc08510 --- /dev/null +++ b/dependencies/mountutils/scripts/prebuild-publish.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +if [[ $GITHUB_TOKEN ]]; then + npm run prebuild-release -- -u "$GITHUB_TOKEN" +fi diff --git a/dependencies/mountutils/src/darwin/functions.cpp b/dependencies/mountutils/src/darwin/functions.cpp new file mode 100644 index 0000000..77e4cd2 --- /dev/null +++ b/dependencies/mountutils/src/darwin/functions.cpp @@ -0,0 +1,177 @@ +/* + * Copyright 2017 resin.io + * + * 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 +#include "../mountutils.hpp" + +struct RunLoopContext { + MOUNTUTILS_RESULT code = MOUNTUTILS_SUCCESS; +}; + +MOUNTUTILS_RESULT translate_dissenter(DADissenterRef dissenter) { + if (dissenter) { + DAReturn status = DADissenterGetStatus(dissenter); + if (status == kDAReturnBadArgument || + status == kDAReturnNotFound) { + return MOUNTUTILS_ERROR_INVALID_DRIVE; + } else if (status == kDAReturnNotPermitted || + status == kDAReturnNotPrivileged) { + return MOUNTUTILS_ERROR_ACCESS_DENIED; + } else { + MountUtilsLog("Unknown dissenter status"); + return MOUNTUTILS_ERROR_GENERAL; + } + } else { + return MOUNTUTILS_SUCCESS; + } +} + +MOUNTUTILS_RESULT +run_cb(const char* device, DADiskUnmountCallback callback, size_t times) { + RunLoopContext context; + void *ctx = &context; + + // Create a session object + MountUtilsLog("Creating DA session"); + DASessionRef session = DASessionCreate(kCFAllocatorDefault); + + if (session == NULL) { + MountUtilsLog("Session couldn't be created"); + return MOUNTUTILS_ERROR_GENERAL; + } + + // Get a disk object from the disk path + MountUtilsLog("Getting disk object"); + DADiskRef disk = DADiskCreateFromBSDName(kCFAllocatorDefault, + session, device); + + // Unmount, and then eject from the unmount callback + MountUtilsLog("Unmounting"); + DADiskUnmount(disk, + kDADiskUnmountOptionWhole | kDADiskUnmountOptionForce, + callback, + ctx); + + // Schedule a disk arbitration session + MountUtilsLog("Schedule session on run loop"); + DASessionScheduleWithRunLoop(session, + CFRunLoopGetCurrent(), + kCFRunLoopDefaultMode); + + // Start the run loop: Run with a timeout of 500ms (0.5s), + // and don't terminate after only handling one resource. + // NOTE: As the unmount callback gets called *before* the runloop can + // be started here when there's no device to be unmounted or + // the device has already been unmounted, the loop would + // hang indefinitely until stopped manually otherwise. + // Here we repeatedly run the loop for a given time, and stop + // it at some point if it hasn't gotten anywhere, or if there's + // nothing to be unmounted, or a dissent has been caught before the run. + // This way we don't have to manage state across callbacks. + MountUtilsLog("Starting run loop"); + + bool done = false; + unsigned int loop_count = 0; + + while (!done) { + loop_count++; + // See https://developer.apple.com/reference/corefoundation/1541988-cfrunloopruninmode + SInt32 status = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.5, false); + // Stop starting the runloop once it's been manually stopped + if ((status == kCFRunLoopRunStopped) || (status == kCFRunLoopRunFinished)) { + done = true; + } + // Bail out if DADiskUnmount caught a dissent and + // thus returned before the runloop even started + if (context.code != MOUNTUTILS_SUCCESS) { + MountUtilsLog("Runloop dry"); + done = true; + } + // Bail out if the runloop is timing out, but not getting anywhere + if (loop_count > 10) { + MountUtilsLog("Runloop stall"); + context.code = MOUNTUTILS_ERROR_AGAIN; + done = true; + } + } + + // Clean up the session + MountUtilsLog("Releasing session & disk object"); + DASessionUnscheduleFromRunLoop(session, + CFRunLoopGetCurrent(), + kCFRunLoopDefaultMode); + CFRelease(session); + + if (context.code == MOUNTUTILS_ERROR_AGAIN && times < 5) { + MountUtilsLog("Retrying..."); + return run_cb(device, callback, times + 1); + } + + MOUNTUTILS_RESULT result = context.code; + return result; +} + +void _unmount_cb(DADiskRef disk, DADissenterRef dissenter, void *ctx) { + MountUtilsLog("[unmount]: Unmount callback"); + RunLoopContext *context = reinterpret_cast(ctx); + if (dissenter) { + MountUtilsLog("[unmount]: Unmount dissenter"); + context->code = translate_dissenter(dissenter); + } else { + MountUtilsLog("[unmount]: Unmount success"); + context->code = MOUNTUTILS_SUCCESS; + } + CFRunLoopStop(CFRunLoopGetCurrent()); +} + +void _eject_cb(DADiskRef disk, DADissenterRef dissenter, void *ctx) { + MountUtilsLog("[eject]: Eject callback"); + RunLoopContext *context = reinterpret_cast(ctx); + if (dissenter) { + MountUtilsLog("[eject]: Eject dissenter"); + context->code = translate_dissenter(dissenter); + } else { + MountUtilsLog("[eject]: Eject success"); + context->code = MOUNTUTILS_SUCCESS; + } + CFRunLoopStop(CFRunLoopGetCurrent()); +} + +void _eject_unmount_cb(DADiskRef disk, DADissenterRef dissenter, void *ctx) { + MountUtilsLog("[eject]: Unmount callback"); + RunLoopContext *context = reinterpret_cast(ctx); + if (dissenter) { + MountUtilsLog("[eject]: Unmount dissenter"); + context->code = translate_dissenter(dissenter); + CFRunLoopStop(CFRunLoopGetCurrent()); + } else { + MountUtilsLog("[eject]: Unmount success"); + MountUtilsLog("[eject]: Ejecting..."); + context->code = MOUNTUTILS_SUCCESS; + DADiskEject(disk, + kDADiskEjectOptionDefault, + _eject_cb, + ctx); + } +} + +MOUNTUTILS_RESULT unmount_disk(const char* device) { + return run_cb(device, _unmount_cb, 0); +} + +MOUNTUTILS_RESULT eject_disk(const char* device) { + return run_cb(device, _eject_unmount_cb, 0); +} diff --git a/dependencies/mountutils/src/linux/functions.cpp b/dependencies/mountutils/src/linux/functions.cpp new file mode 100644 index 0000000..0a42721 --- /dev/null +++ b/dependencies/mountutils/src/linux/functions.cpp @@ -0,0 +1,148 @@ +/* + * Copyright 2017 resin.io + * + * 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 +#include +#include +#include +#include "../mountutils.hpp" + +MOUNTUTILS_RESULT unmount_disk(const char *device_path) { + const char *mount_path = NULL; + std::vector mount_dirs = {}; + + // Stat the device to make sure it exists + struct stat stats; + + if (stat(device_path, &stats) != 0) { + MountUtilsLog("Stat failed"); + + // TODO(jhermsmeier): See TODO below + // v8::Local argv[1] = { + // Nan::ErrnoException(errno, "stat", NULL, device_path) + // }; + // Nan::MakeCallback(Nan::GetCurrentContext()->Global(), callback, 1, argv); + return MOUNTUTILS_ERROR_GENERAL; + } else if (S_ISDIR(stats.st_mode)) { + MountUtilsLog("Device is a directory"); + + // TODO(jhermsmeier): See TODO below + // v8::Local argv[1] = { + // Nan::Error("Invalid device, path is a directory") + // }; + // Nan::MakeCallback(Nan::GetCurrentContext()->Global(), callback, 1, argv); + return MOUNTUTILS_ERROR_INVALID_DRIVE; + } + + // Get mountpaths from the device path, as `umount(device)` + // has been removed in Linux 2.3+ + struct mntent *mnt_p, data; + // See https://github.com/RasPlex/aufs-utils/commit/2d1a37468cdc1f9c779cbf22267c5ae491a44f8e + char mnt_buf[4096 + 1024]; + FILE *proc_mounts; + + MountUtilsLog("Reading /proc/mounts"); + proc_mounts = setmntent("/proc/mounts", "r"); + + if (proc_mounts == NULL) { + MountUtilsLog("Couldn't read /proc/mounts"); + // TODO(jhermsmeier): Refactor MOUNTUTILS_RESULT into a struct + // with error_msg, errno, error_code etc. and set the respective + // values on the struct and move creation of proper errors with + // the right errno messages etc. into the AsyncWorkers (even better: + // create a function which creates the proper error from a + // MOUNTUTILS_RESULT struct). + // v8::Local argv[1] = { + // Nan::ErrnoException(errno, "setmntent", NULL, "/proc/mounts") + // }; + // Nan::MakeCallback(Nan::GetCurrentContext()->Global(), callback, 1, argv); + return MOUNTUTILS_ERROR_GENERAL; + } + + while ((mnt_p = getmntent_r(proc_mounts, &data, mnt_buf, sizeof(mnt_buf)))) { + mount_path = mnt_p->mnt_fsname; + if (strncmp(mount_path, device_path, strlen(device_path)) == 0) { + MountUtilsLog("Mount point " + std::string(mount_path) + + " belongs to drive " + std::string(device_path)); + mount_dirs.push_back(std::string(mnt_p->mnt_dir)); + } + } + + MountUtilsLog("Closing /proc/mounts"); + endmntent(proc_mounts); + + // Use umount2() with the MNT_DETACH flag, which performs a lazy unmount; + // making the mount point unavailable for new accesses, + // and only actually unmounting when the mount point ceases to be busy + // TODO(jhermsmeier): See TODO above + // v8::Local argv[1] = { + // Nan::ErrnoException(errno, "umount2", NULL, mnt_p->mnt_dir) + // }; + // v8::Local ctx = Nan::GetCurrentContext()->Global(); + // Nan::MakeCallback(ctx, callback, 1, argv); + + size_t unmounts = 0; + MOUNTUTILS_RESULT result_code = MOUNTUTILS_SUCCESS; + + for (std::string mount_dir : mount_dirs) { + MountUtilsLog("Unmounting " + mount_dir + "..."); + + mount_path = mount_dir.c_str(); + + if (umount2(mount_path, MNT_EXPIRE) != 0) { + MountUtilsLog("Unmount MNT_EXPIRE " + mount_dir + ": EAGAIN"); + if (umount2(mount_path, MNT_EXPIRE) != 0) { + MountUtilsLog("Unmount MNT_EXPIRE " + mount_dir + " failed: " + + std::string(strerror(errno))); + } else { + MountUtilsLog("Unmount " + mount_dir + ": success"); + unmounts++; + continue; + } + } else { + MountUtilsLog("Unmount " + mount_dir + ": success"); + unmounts++; + continue; + } + + if (umount2(mount_path, MNT_DETACH) != 0) { + MountUtilsLog("Unmount MNT_DETACH " + mount_dir + " failed: " + + std::string(strerror(errno))); + } else { + MountUtilsLog("Unmount " + mount_dir + ": success"); + unmounts++; + continue; + } + + if (umount2(mount_path, MNT_FORCE) != 0) { + MountUtilsLog("Unmount MNT_FORCE " + mount_dir + " failed: " + + std::string(strerror(errno))); + } else { + MountUtilsLog("Unmount " + mount_dir + ": success"); + unmounts++; + continue; + } + } + + return unmounts == mount_dirs.size() ? + MOUNTUTILS_SUCCESS : MOUNTUTILS_ERROR_GENERAL; +} + +// FIXME: This is just a stub copy of `UnmountDisk()`, +// and needs implementation! +MOUNTUTILS_RESULT eject_disk(const char *device) { + return unmount_disk(device); +} diff --git a/dependencies/mountutils/src/mountutils.cpp b/dependencies/mountutils/src/mountutils.cpp new file mode 100644 index 0000000..a2d0da9 --- /dev/null +++ b/dependencies/mountutils/src/mountutils.cpp @@ -0,0 +1,33 @@ +/* + * Copyright 2017 resin.io + * + * 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 +#include +#include "mountutils.hpp" + +NAN_MODULE_INIT(MountUtilsInit) { + NAN_EXPORT(target, unmountDisk); + NAN_EXPORT(target, eject); +} + +void MountUtilsLog(std::string string) { + const char* debug = std::getenv("MOUNTUTILS_DEBUG"); + if (debug != NULL) { + std::cout << "[mountutils] " << string << std::endl; + } +} + +NODE_MODULE(MountUtils, MountUtilsInit) diff --git a/dependencies/mountutils/src/mountutils.hpp b/dependencies/mountutils/src/mountutils.hpp new file mode 100644 index 0000000..e5f9f1e --- /dev/null +++ b/dependencies/mountutils/src/mountutils.hpp @@ -0,0 +1,39 @@ +#ifndef SRC_MOUNTUTILS_HPP_ +#define SRC_MOUNTUTILS_HPP_ + +/* + * Copyright 2017 resin.io + * + * 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 +#include + +enum MOUNTUTILS_RESULT { + MOUNTUTILS_SUCCESS, + MOUNTUTILS_ERROR_INVALID_DRIVE, + MOUNTUTILS_ERROR_ACCESS_DENIED, + MOUNTUTILS_ERROR_AGAIN, + MOUNTUTILS_ERROR_GENERAL +}; + +void MountUtilsLog(std::string string); + +MOUNTUTILS_RESULT unmount_disk(const char *device); +MOUNTUTILS_RESULT eject_disk(const char *device); + +NAN_METHOD(unmountDisk); +NAN_METHOD(eject); + +#endif // SRC_MOUNTUTILS_HPP_ diff --git a/dependencies/mountutils/src/windows/functions.cpp b/dependencies/mountutils/src/windows/functions.cpp new file mode 100644 index 0000000..7734f0d --- /dev/null +++ b/dependencies/mountutils/src/windows/functions.cpp @@ -0,0 +1,557 @@ +/* + * Copyright 2017 resin.io + * + * 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. + */ + +// Adapted from https://support.microsoft.com/en-us/kb/165721 + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#include +#include +#include +#include +#include +#include +#include "../mountutils.hpp" + +HANDLE CreateVolumeHandleFromDevicePath(LPCTSTR devicePath, DWORD flags) { + return CreateFile(devicePath, + flags, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL); +} + +HANDLE CreateVolumeHandleFromDriveLetter(TCHAR driveLetter, DWORD flags) { + TCHAR devicePath[8]; + sprintf_s(devicePath, "\\\\.\\%c:", driveLetter); + return CreateVolumeHandleFromDevicePath(devicePath, flags); +} + +ULONG GetDeviceNumberFromVolumeHandle(HANDLE volume) { + STORAGE_DEVICE_NUMBER storageDeviceNumber; + DWORD bytesReturned; + + BOOL result = DeviceIoControl(volume, + IOCTL_STORAGE_GET_DEVICE_NUMBER, + NULL, 0, + &storageDeviceNumber, + sizeof(storageDeviceNumber), + &bytesReturned, + NULL); + + if (!result) { + return 0; + } + + return storageDeviceNumber.DeviceNumber; +} + +BOOL IsDriveFixed(TCHAR driveLetter) { + TCHAR rootName[5]; + sprintf_s(rootName, "%c:\\", driveLetter); + return GetDriveType(rootName) == DRIVE_FIXED; +} + +BOOL LockVolume(HANDLE volume) { + DWORD bytesReturned; + + for (size_t tries = 0; tries < 20; tries++) { + if (DeviceIoControl(volume, + FSCTL_LOCK_VOLUME, + NULL, 0, + NULL, 0, + &bytesReturned, + NULL)) { + return TRUE; + } + + Sleep(500); + } + + return FALSE; +} + +// Adapted from https://www.codeproject.com/articles/13839/how-to-prepare-a-usb-drive-for-safe-removal +// which is licensed under "The Code Project Open License (CPOL) 1.02" +// https://www.codeproject.com/info/cpol10.aspx +DEVINST GetDeviceInstanceFromDeviceNumber(ULONG deviceNumber) { + const GUID* guid = reinterpret_cast(&GUID_DEVINTERFACE_DISK); + + // Get device interface info set handle for all devices attached to system + DWORD deviceInformationFlags = DIGCF_PRESENT | DIGCF_DEVICEINTERFACE; + HDEVINFO deviceInformation = SetupDiGetClassDevs(guid, + NULL, NULL, + deviceInformationFlags); + + if (deviceInformation == INVALID_HANDLE_VALUE) { + return 0; + } + + DWORD memberIndex = 0; + BYTE buffer[1024]; + + PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData = + (PSP_DEVICE_INTERFACE_DETAIL_DATA)buffer; + + SP_DEVINFO_DATA deviceInformationData; + DWORD requiredSize; + + SP_DEVICE_INTERFACE_DATA deviceInterfaceData; + deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); + + while (true) { + if (!SetupDiEnumDeviceInterfaces(deviceInformation, + NULL, + guid, + memberIndex, + &deviceInterfaceData)) { + break; + } + + requiredSize = 0; + SetupDiGetDeviceInterfaceDetail(deviceInformation, + &deviceInterfaceData, + NULL, 0, + &requiredSize, NULL); + + if (requiredSize == 0 || requiredSize > sizeof(buffer)) { + memberIndex++; + continue; + } + + deviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); + + ZeroMemory((PVOID)&deviceInformationData, sizeof(SP_DEVINFO_DATA)); + deviceInformationData.cbSize = sizeof(SP_DEVINFO_DATA); + + BOOL result = SetupDiGetDeviceInterfaceDetail(deviceInformation, + &deviceInterfaceData, + deviceInterfaceDetailData, + sizeof(buffer), + &requiredSize, + &deviceInformationData); + + if (!result) { + memberIndex++; + continue; + } + + LPCTSTR devicePath = deviceInterfaceDetailData->DevicePath; + HANDLE driveHandle = CreateVolumeHandleFromDevicePath(devicePath, 0); + + if (driveHandle == INVALID_HANDLE_VALUE) { + memberIndex++; + continue; + } + + ULONG currentDriveDeviceNumber = + GetDeviceNumberFromVolumeHandle(driveHandle); + + CloseHandle(driveHandle); + + if (!currentDriveDeviceNumber) { + memberIndex++; + continue; + } + + if (deviceNumber == currentDriveDeviceNumber) { + SetupDiDestroyDeviceInfoList(deviceInformation); + return deviceInformationData.DevInst; + } + + memberIndex++; + } + + SetupDiDestroyDeviceInfoList(deviceInformation); + + return 0; +} + +BOOL UnlockVolume(HANDLE volume) { + DWORD bytesReturned; + + return DeviceIoControl(volume, + FSCTL_UNLOCK_VOLUME, + NULL, 0, + NULL, 0, + &bytesReturned, + NULL); +} + +BOOL DismountVolume(HANDLE volume) { + DWORD bytesReturned; + + return DeviceIoControl(volume, + FSCTL_DISMOUNT_VOLUME, + NULL, 0, + NULL, 0, + &bytesReturned, + NULL); +} + +BOOL IsVolumeMounted(HANDLE volume) { + DWORD bytesReturned; + + return DeviceIoControl(volume, + FSCTL_IS_VOLUME_MOUNTED, + NULL, 0, + NULL, 0, + &bytesReturned, + NULL); +} + +BOOL EjectRemovableVolume(HANDLE volume) { + DWORD bytesReturned; + PREVENT_MEDIA_REMOVAL buffer; + buffer.PreventMediaRemoval = FALSE; + BOOL result = DeviceIoControl(volume, + IOCTL_STORAGE_MEDIA_REMOVAL, + &buffer, sizeof(PREVENT_MEDIA_REMOVAL), + NULL, 0, + &bytesReturned, + NULL); + + if (!result) { + MountUtilsLog("Couldn't prevent media removal"); + return FALSE; + } + + for (size_t tries = 0; tries < 5; tries++) { + if (tries != 0) { + MountUtilsLog("Retrying ejection"); + Sleep(500); + } + const BOOL result = DeviceIoControl(volume, + IOCTL_STORAGE_EJECT_MEDIA, + NULL, 0, + NULL, 0, + &bytesReturned, + NULL); + if (result) { + MountUtilsLog("Volume ejected"); + return TRUE; + } + } + + return FALSE; +} + +MOUNTUTILS_RESULT EjectFixedDriveByDeviceNumber(ULONG deviceNumber) { + DEVINST deviceInstance = GetDeviceInstanceFromDeviceNumber(deviceNumber); + if (!deviceInstance) { + MountUtilsLog("Couldn't get instance from device number"); + return MOUNTUTILS_ERROR_GENERAL; + } + + CONFIGRET status; + PNP_VETO_TYPE vetoType = PNP_VetoTypeUnknown; + char vetoName[MAX_PATH]; + + // It's often seen that the removal fails on the first + // attempt but works on the second attempt. + // See https://www.codeproject.com/articles/13839/how-to-prepare-a-usb-drive-for-safe-removal + for (size_t tries = 0; tries < 3; tries++) { + if (tries != 0) { + MountUtilsLog("Retrying"); + Sleep(500); + } + MountUtilsLog("Ejecting device instance"); + status = CM_Request_Device_Eject(deviceInstance, + &vetoType, + vetoName, + MAX_PATH, + 0); + + if (status == CR_SUCCESS) { + MountUtilsLog("Ejected device instance successfully"); + return MOUNTUTILS_SUCCESS; + } + + MountUtilsLog("Ejecting was vetoed"); + + // We use this as an indicator that the device driver + // is not setting the `SurpriseRemovalOK` capability. + // See https://msdn.microsoft.com/en-us/library/windows/hardware/ff539722(v=vs.85).aspx + if (status == CR_REMOVE_VETOED && + vetoType == PNP_VetoIllegalDeviceRequest) { + MountUtilsLog("Removing subtree"); + status = CM_Query_And_Remove_SubTree(deviceInstance, + &vetoType, + vetoName, + MAX_PATH, + + // We have to add the `CM_REMOVE_NO_RESTART` flag because + // otherwise the just-removed device may be immediately + // redetected, which might happen on XP and Vista. + // See https://www.codeproject.com/articles/13839/how-to-prepare-a-usb-drive-for-safe-removal + + CM_REMOVE_NO_RESTART); + + if (status == CR_ACCESS_DENIED) { + return MOUNTUTILS_ERROR_ACCESS_DENIED; + } + + if (status == CR_SUCCESS) { + return MOUNTUTILS_SUCCESS; + } + + MountUtilsLog("Couldn't eject device instance"); + return MOUNTUTILS_ERROR_GENERAL; + } + } + + return MOUNTUTILS_ERROR_GENERAL; +} + +MOUNTUTILS_RESULT EjectDriveLetter(TCHAR driveLetter) { + DWORD volumeFlags = GENERIC_READ | GENERIC_WRITE; + HANDLE volumeHandle = CreateVolumeHandleFromDriveLetter(driveLetter, + volumeFlags); + + MountUtilsLog("Creating volume handle"); + + if (volumeHandle == INVALID_HANDLE_VALUE) { + MountUtilsLog("Couldn't create volume handle"); + return MOUNTUTILS_ERROR_INVALID_DRIVE; + } + + // Don't proceed if the volume is not mounted + if (!IsVolumeMounted(volumeHandle)) { + MountUtilsLog("Volume is not mounted"); + + if (!CloseHandle(volumeHandle)) { + MountUtilsLog("Couldn't close volume handle"); + return MOUNTUTILS_ERROR_GENERAL; + } + + return MOUNTUTILS_SUCCESS; + } + + if (IsDriveFixed(driveLetter)) { + MountUtilsLog("Drive is fixed"); + + ULONG deviceNumber = GetDeviceNumberFromVolumeHandle(volumeHandle); + if (!deviceNumber) { + MountUtilsLog("Couldn't get device number from volume handle"); + CloseHandle(volumeHandle); + return MOUNTUTILS_ERROR_GENERAL; + } + + if (!CloseHandle(volumeHandle)) { + MountUtilsLog("Couldn't close volume handle"); + return MOUNTUTILS_ERROR_GENERAL; + } + + MountUtilsLog("Ejecting fixed drive"); + return EjectFixedDriveByDeviceNumber(deviceNumber); + } + + MountUtilsLog("Locking volume"); + + if (!LockVolume(volumeHandle)) { + MountUtilsLog("Couldn't lock volume"); + CloseHandle(volumeHandle); + return MOUNTUTILS_ERROR_GENERAL; + } + + MountUtilsLog("Dismounting volume"); + + if (!DismountVolume(volumeHandle)) { + MountUtilsLog("Couldn't dismount volume"); + CloseHandle(volumeHandle); + return MOUNTUTILS_ERROR_GENERAL; + } + + MountUtilsLog("Ejecting volume"); + + if (!EjectRemovableVolume(volumeHandle)) { + MountUtilsLog("Couldn't eject volume"); + CloseHandle(volumeHandle); + return MOUNTUTILS_ERROR_GENERAL; + } + + MountUtilsLog("Unlocking volume"); + + if (!UnlockVolume(volumeHandle)) { + MountUtilsLog("Couldn't unlock volume"); + CloseHandle(volumeHandle); + return MOUNTUTILS_ERROR_GENERAL; + } + + MountUtilsLog("Closing volume handle"); + + if (!CloseHandle(volumeHandle)) { + MountUtilsLog("Couldn't close volume handle"); + return MOUNTUTILS_ERROR_GENERAL; + } + + return MOUNTUTILS_SUCCESS; +} + +BOOL IsDriveEjectable(TCHAR driveLetter) { + TCHAR devicePath[8]; + sprintf_s(devicePath, "%c:\\", driveLetter); + + MountUtilsLog("Checking whether drive is ejectable: " + + std::string(1, driveLetter)); + + switch (GetDriveType(devicePath)) { + case DRIVE_NO_ROOT_DIR: + MountUtilsLog("The drive doesn't exist"); + return FALSE; + case DRIVE_REMOVABLE: + MountUtilsLog("The drive is removable"); + return TRUE; + case DRIVE_FIXED: + MountUtilsLog("The drive is fixed"); + return TRUE; + case DRIVE_REMOTE: + MountUtilsLog("The drive is remote"); + return FALSE; + case DRIVE_CDROM: + MountUtilsLog("The drive is a CDROM"); + return FALSE; + case DRIVE_RAMDISK: + MountUtilsLog("The drive is a RAM disk"); + return FALSE; + default: + MountUtilsLog("The drive type is unknown"); + return FALSE; + } +} + +MOUNTUTILS_RESULT Eject(ULONG deviceNumber) { + DWORD logicalDrivesMask = GetLogicalDrives(); + TCHAR currentDriveLetter = 'A'; + + if (logicalDrivesMask == 0) { + MountUtilsLog("Couldn't get logical drives"); + return MOUNTUTILS_ERROR_GENERAL; + } + + while (logicalDrivesMask) { + if (logicalDrivesMask & 1 && IsDriveEjectable(currentDriveLetter)) { + MountUtilsLog("Opening drive letter handle: " + + std::string(1, currentDriveLetter)); + + HANDLE driveHandle = + CreateVolumeHandleFromDriveLetter(currentDriveLetter, 0); + + if (driveHandle == INVALID_HANDLE_VALUE) { + MountUtilsLog("Couldn't open drive letter handle"); + return MOUNTUTILS_ERROR_GENERAL; + } + + ULONG currentDeviceNumber = GetDeviceNumberFromVolumeHandle(driveHandle); + + MountUtilsLog("Closing drive letter handle"); + + if (!CloseHandle(driveHandle)) { + MountUtilsLog("Couldn't close drive letter handle"); + return MOUNTUTILS_ERROR_GENERAL; + } + + if (currentDeviceNumber == deviceNumber) { + MountUtilsLog("Drive letter device matches"); + MOUNTUTILS_RESULT result; + + // Retry ejecting 3 times, since I've seen that in some systems + // the filesystem is ejected, but the drive letter remains assigned, + // which gets fixed if you retry again. + for (size_t times = 0; times < 3; times++) { + if (times != 0) { + MountUtilsLog("Retrying"); + Sleep(500); + } + MountUtilsLog("Ejecting drive letter"); + result = EjectDriveLetter(currentDriveLetter); + + // Abort the loop if we couldn't open a handle on the drive letter + // after previous attempts worked, since this means the drive was + // completely ejected, and that we don't have to keep retrying. + if (times > 0 && result == MOUNTUTILS_ERROR_INVALID_DRIVE) { + MountUtilsLog("Drive letter has already been ejected"); + break; + } + + if (result != MOUNTUTILS_SUCCESS) { + MountUtilsLog("Couldn't eject drive letter"); + return result; + } + } + } + + MountUtilsLog("Continuing with the next available letter"); + } + + currentDriveLetter++; + logicalDrivesMask >>= 1; + } + + return MOUNTUTILS_SUCCESS; +} + +// From http://stackoverflow.com/a/12923949 +MOUNTUTILS_RESULT stringToInteger(char *string, int *out) { + if (string[0] == '\0' || isspace((unsigned char) string[0])) { + return MOUNTUTILS_ERROR_GENERAL; + } + + char *end; + errno = 0; + int result = strtol(string, &end, 10); + + if (result > INT_MAX || result < INT_MIN || + (errno == ERANGE && result == LONG_MAX) || + (errno == ERANGE && result == LONG_MIN)) { + return MOUNTUTILS_ERROR_GENERAL; + } + + if (*end != '\0') { + return MOUNTUTILS_ERROR_GENERAL; + } + + *out = result; + + return MOUNTUTILS_SUCCESS; +} + +MOUNTUTILS_RESULT unmount_disk(const char *device) { + int deviceId; + char prefix[18]; + + MountUtilsLog(std::string(device)); + + int result = sscanf(device, "%17s%i", prefix, &deviceId); + + // Return value of `sscanf` is the number of receiving arguments + // successfully assigned; and `0` or `EOF` in case of failure + if (result != 2 || result == EOF) { + return MOUNTUTILS_ERROR_INVALID_DRIVE; + } + + return Eject(deviceId); +} + +// FIXME: This is just a stub copy of `UnmountDisk()`, +// and needs implementation! +MOUNTUTILS_RESULT eject_disk(const char *device) { + return unmount_disk(device); +} diff --git a/dependencies/mountutils/src/worker-eject.cpp b/dependencies/mountutils/src/worker-eject.cpp new file mode 100644 index 0000000..e80d67e --- /dev/null +++ b/dependencies/mountutils/src/worker-eject.cpp @@ -0,0 +1,74 @@ +/* + * Copyright 2017 resin.io + * + * 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 +#include "mountutils.hpp" + +class EjectWorker : public Nan::AsyncWorker { + public: + EjectWorker(Nan::Callback *callback, std::string device) + : Nan::AsyncWorker(callback) { + device_path = device; + } + + ~EjectWorker() {} + + void Execute() { + MOUNTUTILS_RESULT result = eject_disk(device_path.c_str()); + + MountUtilsLog("Eject complete"); + + if (result != MOUNTUTILS_SUCCESS) { + switch (result) { + case MOUNTUTILS_ERROR_ACCESS_DENIED: + SetErrorMessage("Eject failed, access denied"); + break; + case MOUNTUTILS_ERROR_INVALID_DRIVE: + SetErrorMessage("Eject failed, invalid drive"); + break; + default: + SetErrorMessage("Eject failed"); + break; + } + } + } + + void HandleOKCallback() { + Nan::HandleScope scope; + v8::Local argv[] = { Nan::Null() }; + callback->Call(1, argv, async_resource); + } + + private: + std::string device_path; +}; + +NAN_METHOD(eject) { + if (!info[1]->IsFunction()) { + return Nan::ThrowError("Callback must be a function"); + } + + if (!info[0]->IsString()) { + return Nan::ThrowError("Device must be a string"); + } + + Nan::Utf8String device(Nan::To(info[0]).ToLocalChecked()); + std::string device_path(*device); + Nan::Callback *callback = new Nan::Callback(info[1].As()); + + Nan::AsyncQueueWorker(new EjectWorker(callback, device_path)); + + info.GetReturnValue().SetUndefined(); +} diff --git a/dependencies/mountutils/src/worker-unmount.cpp b/dependencies/mountutils/src/worker-unmount.cpp new file mode 100644 index 0000000..f789b21 --- /dev/null +++ b/dependencies/mountutils/src/worker-unmount.cpp @@ -0,0 +1,74 @@ +/* + * Copyright 2017 resin.io + * + * 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 +#include "mountutils.hpp" + +class UnmountWorker : public Nan::AsyncWorker { + public: + UnmountWorker(Nan::Callback *callback, std::string device) + : Nan::AsyncWorker(callback) { + device_path = device; + } + + ~UnmountWorker() {} + + void Execute() { + MOUNTUTILS_RESULT result = unmount_disk(device_path.c_str()); + + MountUtilsLog("Unmount complete"); + + if (result != MOUNTUTILS_SUCCESS) { + switch (result) { + case MOUNTUTILS_ERROR_ACCESS_DENIED: + SetErrorMessage("Unmount failed, access denied"); + break; + case MOUNTUTILS_ERROR_INVALID_DRIVE: + SetErrorMessage("Unmount failed, invalid drive"); + break; + default: + SetErrorMessage("Unmount failed"); + break; + } + } + } + + void HandleOKCallback() { + Nan::HandleScope scope; + v8::Local argv[] = { Nan::Null() }; + callback->Call(1, argv, async_resource); + } + + private: + std::string device_path; +}; + +NAN_METHOD(unmountDisk) { + if (!info[1]->IsFunction()) { + return Nan::ThrowError("Callback must be a function"); + } + + if (!info[0]->IsString()) { + return Nan::ThrowError("Device must be a string"); + } + + Nan::Utf8String device(Nan::To(info[0]).ToLocalChecked()); + std::string device_path(*device); + Nan::Callback *callback = new Nan::Callback(info[1].As()); + + Nan::AsyncQueueWorker(new UnmountWorker(callback, device_path)); + + info.GetReturnValue().SetUndefined(); +} diff --git a/dependencies/mountutils/tests/mountutils.spec.js b/dependencies/mountutils/tests/mountutils.spec.js new file mode 100644 index 0000000..9ca71f2 --- /dev/null +++ b/dependencies/mountutils/tests/mountutils.spec.js @@ -0,0 +1,106 @@ +/* + * Copyright 2017 resin.io + * + * 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. + */ + +const chai = require('chai'); +const mountutils = require('../'); + +describe('MountUtils', function() { + + describe('.unmountDisk()', function() { + + it('should be a function', function() { + chai.expect(mountutils.unmountDisk).to.be.a('function'); + }); + + context('missing / wrong arguments', function() { + + specify('throws on missing device', function() { + chai.expect(function() { + mountutils.unmountDisk(null, function() {}); + }).to.throw(/must be a string/i); + }); + + specify('throws on missing callback', function() { + chai.expect(function() { + mountutils.unmountDisk('novalue'); + }).to.throw(/must be a function/i); + }); + + }); + + context('invalid device', function() { + + specify('device is a directory', function( done ) { + mountutils.unmountDisk( __dirname, function( error ) { + chai.expect(error.message).to.match(/Unmount failed/); + done(); + }); + }); + + specify('device is an empty string', function( done ) { + mountutils.unmountDisk( '', function( error ) { + chai.expect(error.message).to.match(/Unmount failed/); + done(); + }); + }); + + }); + + }); + + describe('.eject()', function() { + + it('should be a function', function() { + chai.expect(mountutils.eject).to.be.a('function'); + }); + + context('missing / wrong arguments', function() { + + specify('throws on missing device', function() { + chai.expect(function() { + mountutils.eject(null, function() {}); + }).to.throw(/must be a string/i); + }); + + specify('throws on missing callback', function() { + chai.expect(function() { + mountutils.eject('novalue'); + }).to.throw(/must be a function/i); + }); + + }); + + context('invalid device', function() { + + specify('device is a directory', function( done ) { + mountutils.eject( __dirname, function( error ) { + chai.expect(error.message).to.match(/Eject failed/); + done(); + }); + }); + + specify('device is an empty string', function( done ) { + mountutils.eject( '', function( error ) { + chai.expect(error.message).to.match(/Eject failed/); + done(); + }); + }); + + }); + + }); + +}); diff --git a/dependencies/zlib-1.2.11/CMakeLists.txt b/dependencies/zlib-1.2.11/CMakeLists.txt new file mode 100644 index 0000000..6e2bb16 --- /dev/null +++ b/dependencies/zlib-1.2.11/CMakeLists.txt @@ -0,0 +1,250 @@ +cmake_minimum_required(VERSION 2.4.4) +set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON) + +project(zlib C) + +set(VERSION "1.2.11") + +option(ASM686 "Enable building i686 assembly implementation") +option(AMD64 "Enable building amd64 assembly implementation") + +set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables") +set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries") +set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers") +set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages") +set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files") + +include(CheckTypeSize) +include(CheckFunctionExists) +include(CheckIncludeFile) +include(CheckCSourceCompiles) +enable_testing() + +check_include_file(sys/types.h HAVE_SYS_TYPES_H) +check_include_file(stdint.h HAVE_STDINT_H) +check_include_file(stddef.h HAVE_STDDEF_H) + +# +# Check to see if we have large file support +# +set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1) +# We add these other definitions here because CheckTypeSize.cmake +# in CMake 2.4.x does not automatically do so and we want +# compatibility with CMake 2.4.x. +if(HAVE_SYS_TYPES_H) + list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_TYPES_H) +endif() +if(HAVE_STDINT_H) + list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDINT_H) +endif() +if(HAVE_STDDEF_H) + list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H) +endif() +check_type_size(off64_t OFF64_T) +if(HAVE_OFF64_T) + add_definitions(-D_LARGEFILE64_SOURCE=1) +endif() +set(CMAKE_REQUIRED_DEFINITIONS) # clear variable + +# +# Check for fseeko +# +check_function_exists(fseeko HAVE_FSEEKO) +if(NOT HAVE_FSEEKO) + add_definitions(-DNO_FSEEKO) +endif() + +# +# Check for unistd.h +# +check_include_file(unistd.h Z_HAVE_UNISTD_H) + +if(MSVC) + set(CMAKE_DEBUG_POSTFIX "d") + add_definitions(-D_CRT_SECURE_NO_DEPRECATE) + add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE) + include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +endif() + +if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) + # If we're doing an out of source build and the user has a zconf.h + # in their source tree... + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h) + message(STATUS "Renaming") + message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h") + message(STATUS "to 'zconf.h.included' because this file is included with zlib") + message(STATUS "but CMake generates it automatically in the build directory.") + file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.included) + endif() +endif() + +set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib.pc) +configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein + ${ZLIB_PC} @ONLY) +configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein + ${CMAKE_CURRENT_BINARY_DIR}/zconf.h @ONLY) +include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}) + + +#============================================================================ +# zlib +#============================================================================ + +set(ZLIB_PUBLIC_HDRS + ${CMAKE_CURRENT_BINARY_DIR}/zconf.h + zlib.h +) +set(ZLIB_PRIVATE_HDRS + crc32.h + deflate.h + gzguts.h + inffast.h + inffixed.h + inflate.h + inftrees.h + trees.h + zutil.h +) +set(ZLIB_SRCS + adler32.c + compress.c + crc32.c + deflate.c + gzclose.c + gzlib.c + gzread.c + gzwrite.c + inflate.c + infback.c + inftrees.c + inffast.c + trees.c + uncompr.c + zutil.c +) + +if(NOT MINGW) + set(ZLIB_DLL_SRCS + win32/zlib1.rc # If present will override custom build rule below. + ) +endif() + +if(CMAKE_COMPILER_IS_GNUCC) + if(ASM686) + set(ZLIB_ASMS contrib/asm686/match.S) + elseif (AMD64) + set(ZLIB_ASMS contrib/amd64/amd64-match.S) + endif () + + if(ZLIB_ASMS) + add_definitions(-DASMV) + set_source_files_properties(${ZLIB_ASMS} PROPERTIES LANGUAGE C COMPILE_FLAGS -DNO_UNDERLINE) + endif() +endif() + +if(MSVC) + if(ASM686) + ENABLE_LANGUAGE(ASM_MASM) + set(ZLIB_ASMS + contrib/masmx86/inffas32.asm + contrib/masmx86/match686.asm + ) + elseif (AMD64) + ENABLE_LANGUAGE(ASM_MASM) + set(ZLIB_ASMS + contrib/masmx64/gvmat64.asm + contrib/masmx64/inffasx64.asm + ) + endif() + + if(ZLIB_ASMS) + add_definitions(-DASMV -DASMINF) + endif() +endif() + +# parse the full version number from zlib.h and include in ZLIB_FULL_VERSION +file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h _zlib_h_contents) +string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*" + "\\1" ZLIB_FULL_VERSION ${_zlib_h_contents}) + +if(MINGW) + # This gets us DLL resource information when compiling on MinGW. + if(NOT CMAKE_RC_COMPILER) + set(CMAKE_RC_COMPILER windres.exe) + endif() + + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj + COMMAND ${CMAKE_RC_COMPILER} + -D GCC_WINDRES + -I ${CMAKE_CURRENT_SOURCE_DIR} + -I ${CMAKE_CURRENT_BINARY_DIR} + -o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj + -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc) + set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) +endif(MINGW) + +#add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) +add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) +#set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL) +#set_target_properties(zlib PROPERTIES SOVERSION 1) + +if(NOT CYGWIN) + # This property causes shared libraries on Linux to have the full version + # encoded into their final filename. We disable this on Cygwin because + # it causes cygz-${ZLIB_FULL_VERSION}.dll to be created when cygz.dll + # seems to be the default. + # + # This has no effect with MSVC, on that platform the version info for + # the DLL comes from the resource file win32/zlib1.rc +# set_target_properties(zlib PROPERTIES VERSION ${ZLIB_FULL_VERSION}) +endif() + +if(UNIX) + # On unix-like platforms the library is almost always called libz + set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z) + if(NOT APPLE) + set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"") + endif() +elseif(BUILD_SHARED_LIBS AND WIN32) + # Creates zlib1.dll when building shared library version + #set_target_properties(zlib PROPERTIES SUFFIX "1.dll") +endif() + +if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL ) + #install(TARGETS zlib zlibstatic + install(TARGETS zlibstatic + RUNTIME DESTINATION "${INSTALL_BIN_DIR}" + ARCHIVE DESTINATION "${INSTALL_LIB_DIR}" + LIBRARY DESTINATION "${INSTALL_LIB_DIR}" ) +endif() +if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL ) + install(FILES ${ZLIB_PUBLIC_HDRS} DESTINATION "${INSTALL_INC_DIR}") +endif() +if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL ) + install(FILES zlib.3 DESTINATION "${INSTALL_MAN_DIR}/man3") +endif() +if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL ) + install(FILES ${ZLIB_PC} DESTINATION "${INSTALL_PKGCONFIG_DIR}") +endif() + +#============================================================================ +# Example binaries +#============================================================================ + +#add_executable(example test/example.c) +#target_link_libraries(example zlib) +#add_test(example example) + +#add_executable(minigzip test/minigzip.c) +#target_link_libraries(minigzip zlib) + +#if(HAVE_OFF64_T) +# add_executable(example64 test/example.c) +# target_link_libraries(example64 zlib) +# set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") +# add_test(example64 example64) +# +# add_executable(minigzip64 test/minigzip.c) +# target_link_libraries(minigzip64 zlib) +# set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") +#endif() diff --git a/dependencies/zlib-1.2.11/ChangeLog b/dependencies/zlib-1.2.11/ChangeLog new file mode 100644 index 0000000..30199a6 --- /dev/null +++ b/dependencies/zlib-1.2.11/ChangeLog @@ -0,0 +1,1515 @@ + + ChangeLog file for zlib + +Changes in 1.2.11 (15 Jan 2017) +- Fix deflate stored bug when pulling last block from window +- Permit immediate deflateParams changes before any deflate input + +Changes in 1.2.10 (2 Jan 2017) +- Avoid warnings on snprintf() return value +- Fix bug in deflate_stored() for zero-length input +- Fix bug in gzwrite.c that produced corrupt gzip files +- Remove files to be installed before copying them in Makefile.in +- Add warnings when compiling with assembler code + +Changes in 1.2.9 (31 Dec 2016) +- Fix contrib/minizip to permit unzipping with desktop API [Zouzou] +- Improve contrib/blast to return unused bytes +- Assure that gzoffset() is correct when appending +- Improve compress() and uncompress() to support large lengths +- Fix bug in test/example.c where error code not saved +- Remedy Coverity warning [Randers-Pehrson] +- Improve speed of gzprintf() in transparent mode +- Fix inflateInit2() bug when windowBits is 16 or 32 +- Change DEBUG macro to ZLIB_DEBUG +- Avoid uninitialized access by gzclose_w() +- Allow building zlib outside of the source directory +- Fix bug that accepted invalid zlib header when windowBits is zero +- Fix gzseek() problem on MinGW due to buggy _lseeki64 there +- Loop on write() calls in gzwrite.c in case of non-blocking I/O +- Add --warn (-w) option to ./configure for more compiler warnings +- Reject a window size of 256 bytes if not using the zlib wrapper +- Fix bug when level 0 used with Z_HUFFMAN or Z_RLE +- Add --debug (-d) option to ./configure to define ZLIB_DEBUG +- Fix bugs in creating a very large gzip header +- Add uncompress2() function, which returns the input size used +- Assure that deflateParams() will not switch functions mid-block +- Dramatically speed up deflation for level 0 (storing) +- Add gzfread(), duplicating the interface of fread() +- Add gzfwrite(), duplicating the interface of fwrite() +- Add deflateGetDictionary() function +- Use snprintf() for later versions of Microsoft C +- Fix *Init macros to use z_ prefix when requested +- Replace as400 with os400 for OS/400 support [Monnerat] +- Add crc32_z() and adler32_z() functions with size_t lengths +- Update Visual Studio project files [AraHaan] + +Changes in 1.2.8 (28 Apr 2013) +- Update contrib/minizip/iowin32.c for Windows RT [Vollant] +- Do not force Z_CONST for C++ +- Clean up contrib/vstudio [Roß] +- Correct spelling error in zlib.h +- Fix mixed line endings in contrib/vstudio + +Changes in 1.2.7.3 (13 Apr 2013) +- Fix version numbers and DLL names in contrib/vstudio/*/zlib.rc + +Changes in 1.2.7.2 (13 Apr 2013) +- Change check for a four-byte type back to hexadecimal +- Fix typo in win32/Makefile.msc +- Add casts in gzwrite.c for pointer differences + +Changes in 1.2.7.1 (24 Mar 2013) +- Replace use of unsafe string functions with snprintf if available +- Avoid including stddef.h on Windows for Z_SOLO compile [Niessink] +- Fix gzgetc undefine when Z_PREFIX set [Turk] +- Eliminate use of mktemp in Makefile (not always available) +- Fix bug in 'F' mode for gzopen() +- Add inflateGetDictionary() function +- Correct comment in deflate.h +- Use _snprintf for snprintf in Microsoft C +- On Darwin, only use /usr/bin/libtool if libtool is not Apple +- Delete "--version" file if created by "ar --version" [Richard G.] +- Fix configure check for veracity of compiler error return codes +- Fix CMake compilation of static lib for MSVC2010 x64 +- Remove unused variable in infback9.c +- Fix argument checks in gzlog_compress() and gzlog_write() +- Clean up the usage of z_const and respect const usage within zlib +- Clean up examples/gzlog.[ch] comparisons of different types +- Avoid shift equal to bits in type (caused endless loop) +- Fix uninitialized value bug in gzputc() introduced by const patches +- Fix memory allocation error in examples/zran.c [Nor] +- Fix bug where gzopen(), gzclose() would write an empty file +- Fix bug in gzclose() when gzwrite() runs out of memory +- Check for input buffer malloc failure in examples/gzappend.c +- Add note to contrib/blast to use binary mode in stdio +- Fix comparisons of differently signed integers in contrib/blast +- Check for invalid code length codes in contrib/puff +- Fix serious but very rare decompression bug in inftrees.c +- Update inflateBack() comments, since inflate() can be faster +- Use underscored I/O function names for WINAPI_FAMILY +- Add _tr_flush_bits to the external symbols prefixed by --zprefix +- Add contrib/vstudio/vc10 pre-build step for static only +- Quote --version-script argument in CMakeLists.txt +- Don't specify --version-script on Apple platforms in CMakeLists.txt +- Fix casting error in contrib/testzlib/testzlib.c +- Fix types in contrib/minizip to match result of get_crc_table() +- Simplify contrib/vstudio/vc10 with 'd' suffix +- Add TOP support to win32/Makefile.msc +- Suport i686 and amd64 assembler builds in CMakeLists.txt +- Fix typos in the use of _LARGEFILE64_SOURCE in zconf.h +- Add vc11 and vc12 build files to contrib/vstudio +- Add gzvprintf() as an undocumented function in zlib +- Fix configure for Sun shell +- Remove runtime check in configure for four-byte integer type +- Add casts and consts to ease user conversion to C++ +- Add man pages for minizip and miniunzip +- In Makefile uninstall, don't rm if preceding cd fails +- Do not return Z_BUF_ERROR if deflateParam() has nothing to write + +Changes in 1.2.7 (2 May 2012) +- Replace use of memmove() with a simple copy for portability +- Test for existence of strerror +- Restore gzgetc_ for backward compatibility with 1.2.6 +- Fix build with non-GNU make on Solaris +- Require gcc 4.0 or later on Mac OS X to use the hidden attribute +- Include unistd.h for Watcom C +- Use __WATCOMC__ instead of __WATCOM__ +- Do not use the visibility attribute if NO_VIZ defined +- Improve the detection of no hidden visibility attribute +- Avoid using __int64 for gcc or solo compilation +- Cast to char * in gzprintf to avoid warnings [Zinser] +- Fix make_vms.com for VAX [Zinser] +- Don't use library or built-in byte swaps +- Simplify test and use of gcc hidden attribute +- Fix bug in gzclose_w() when gzwrite() fails to allocate memory +- Add "x" (O_EXCL) and "e" (O_CLOEXEC) modes support to gzopen() +- Fix bug in test/minigzip.c for configure --solo +- Fix contrib/vstudio project link errors [Mohanathas] +- Add ability to choose the builder in make_vms.com [Schweda] +- Add DESTDIR support to mingw32 win32/Makefile.gcc +- Fix comments in win32/Makefile.gcc for proper usage +- Allow overriding the default install locations for cmake +- Generate and install the pkg-config file with cmake +- Build both a static and a shared version of zlib with cmake +- Include version symbols for cmake builds +- If using cmake with MSVC, add the source directory to the includes +- Remove unneeded EXTRA_CFLAGS from win32/Makefile.gcc [Truta] +- Move obsolete emx makefile to old [Truta] +- Allow the use of -Wundef when compiling or using zlib +- Avoid the use of the -u option with mktemp +- Improve inflate() documentation on the use of Z_FINISH +- Recognize clang as gcc +- Add gzopen_w() in Windows for wide character path names +- Rename zconf.h in CMakeLists.txt to move it out of the way +- Add source directory in CMakeLists.txt for building examples +- Look in build directory for zlib.pc in CMakeLists.txt +- Remove gzflags from zlibvc.def in vc9 and vc10 +- Fix contrib/minizip compilation in the MinGW environment +- Update ./configure for Solaris, support --64 [Mooney] +- Remove -R. from Solaris shared build (possible security issue) +- Avoid race condition for parallel make (-j) running example +- Fix type mismatch between get_crc_table() and crc_table +- Fix parsing of version with "-" in CMakeLists.txt [Snider, Ziegler] +- Fix the path to zlib.map in CMakeLists.txt +- Force the native libtool in Mac OS X to avoid GNU libtool [Beebe] +- Add instructions to win32/Makefile.gcc for shared install [Torri] + +Changes in 1.2.6.1 (12 Feb 2012) +- Avoid the use of the Objective-C reserved name "id" +- Include io.h in gzguts.h for Microsoft compilers +- Fix problem with ./configure --prefix and gzgetc macro +- Include gz_header definition when compiling zlib solo +- Put gzflags() functionality back in zutil.c +- Avoid library header include in crc32.c for Z_SOLO +- Use name in GCC_CLASSIC as C compiler for coverage testing, if set +- Minor cleanup in contrib/minizip/zip.c [Vollant] +- Update make_vms.com [Zinser] +- Remove unnecessary gzgetc_ function +- Use optimized byte swap operations for Microsoft and GNU [Snyder] +- Fix minor typo in zlib.h comments [Rzesniowiecki] + +Changes in 1.2.6 (29 Jan 2012) +- Update the Pascal interface in contrib/pascal +- Fix function numbers for gzgetc_ in zlibvc.def files +- Fix configure.ac for contrib/minizip [Schiffer] +- Fix large-entry detection in minizip on 64-bit systems [Schiffer] +- Have ./configure use the compiler return code for error indication +- Fix CMakeLists.txt for cross compilation [McClure] +- Fix contrib/minizip/zip.c for 64-bit architectures [Dalsnes] +- Fix compilation of contrib/minizip on FreeBSD [Marquez] +- Correct suggested usages in win32/Makefile.msc [Shachar, Horvath] +- Include io.h for Turbo C / Borland C on all platforms [Truta] +- Make version explicit in contrib/minizip/configure.ac [Bosmans] +- Avoid warning for no encryption in contrib/minizip/zip.c [Vollant] +- Minor cleanup up contrib/minizip/unzip.c [Vollant] +- Fix bug when compiling minizip with C++ [Vollant] +- Protect for long name and extra fields in contrib/minizip [Vollant] +- Avoid some warnings in contrib/minizip [Vollant] +- Add -I../.. -L../.. to CFLAGS for minizip and miniunzip +- Add missing libs to minizip linker command +- Add support for VPATH builds in contrib/minizip +- Add an --enable-demos option to contrib/minizip/configure +- Add the generation of configure.log by ./configure +- Exit when required parameters not provided to win32/Makefile.gcc +- Have gzputc return the character written instead of the argument +- Use the -m option on ldconfig for BSD systems [Tobias] +- Correct in zlib.map when deflateResetKeep was added + +Changes in 1.2.5.3 (15 Jan 2012) +- Restore gzgetc function for binary compatibility +- Do not use _lseeki64 under Borland C++ [Truta] +- Update win32/Makefile.msc to build test/*.c [Truta] +- Remove old/visualc6 given CMakefile and other alternatives +- Update AS400 build files and documentation [Monnerat] +- Update win32/Makefile.gcc to build test/*.c [Truta] +- Permit stronger flushes after Z_BLOCK flushes +- Avoid extraneous empty blocks when doing empty flushes +- Permit Z_NULL arguments to deflatePending +- Allow deflatePrime() to insert bits in the middle of a stream +- Remove second empty static block for Z_PARTIAL_FLUSH +- Write out all of the available bits when using Z_BLOCK +- Insert the first two strings in the hash table after a flush + +Changes in 1.2.5.2 (17 Dec 2011) +- fix ld error: unable to find version dependency 'ZLIB_1.2.5' +- use relative symlinks for shared libs +- Avoid searching past window for Z_RLE strategy +- Assure that high-water mark initialization is always applied in deflate +- Add assertions to fill_window() in deflate.c to match comments +- Update python link in README +- Correct spelling error in gzread.c +- Fix bug in gzgets() for a concatenated empty gzip stream +- Correct error in comment for gz_make() +- Change gzread() and related to ignore junk after gzip streams +- Allow gzread() and related to continue after gzclearerr() +- Allow gzrewind() and gzseek() after a premature end-of-file +- Simplify gzseek() now that raw after gzip is ignored +- Change gzgetc() to a macro for speed (~40% speedup in testing) +- Fix gzclose() to return the actual error last encountered +- Always add large file support for windows +- Include zconf.h for windows large file support +- Include zconf.h.cmakein for windows large file support +- Update zconf.h.cmakein on make distclean +- Merge vestigial vsnprintf determination from zutil.h to gzguts.h +- Clarify how gzopen() appends in zlib.h comments +- Correct documentation of gzdirect() since junk at end now ignored +- Add a transparent write mode to gzopen() when 'T' is in the mode +- Update python link in zlib man page +- Get inffixed.h and MAKEFIXED result to match +- Add a ./config --solo option to make zlib subset with no library use +- Add undocumented inflateResetKeep() function for CAB file decoding +- Add --cover option to ./configure for gcc coverage testing +- Add #define ZLIB_CONST option to use const in the z_stream interface +- Add comment to gzdopen() in zlib.h to use dup() when using fileno() +- Note behavior of uncompress() to provide as much data as it can +- Add files in contrib/minizip to aid in building libminizip +- Split off AR options in Makefile.in and configure +- Change ON macro to Z_ARG to avoid application conflicts +- Facilitate compilation with Borland C++ for pragmas and vsnprintf +- Include io.h for Turbo C / Borland C++ +- Move example.c and minigzip.c to test/ +- Simplify incomplete code table filling in inflate_table() +- Remove code from inflate.c and infback.c that is impossible to execute +- Test the inflate code with full coverage +- Allow deflateSetDictionary, inflateSetDictionary at any time (in raw) +- Add deflateResetKeep and fix inflateResetKeep to retain dictionary +- Fix gzwrite.c to accommodate reduced memory zlib compilation +- Have inflate() with Z_FINISH avoid the allocation of a window +- Do not set strm->adler when doing raw inflate +- Fix gzeof() to behave just like feof() when read is not past end of file +- Fix bug in gzread.c when end-of-file is reached +- Avoid use of Z_BUF_ERROR in gz* functions except for premature EOF +- Document gzread() capability to read concurrently written files +- Remove hard-coding of resource compiler in CMakeLists.txt [Blammo] + +Changes in 1.2.5.1 (10 Sep 2011) +- Update FAQ entry on shared builds (#13) +- Avoid symbolic argument to chmod in Makefile.in +- Fix bug and add consts in contrib/puff [Oberhumer] +- Update contrib/puff/zeros.raw test file to have all block types +- Add full coverage test for puff in contrib/puff/Makefile +- Fix static-only-build install in Makefile.in +- Fix bug in unzGetCurrentFileInfo() in contrib/minizip [Kuno] +- Add libz.a dependency to shared in Makefile.in for parallel builds +- Spell out "number" (instead of "nb") in zlib.h for total_in, total_out +- Replace $(...) with `...` in configure for non-bash sh [Bowler] +- Add darwin* to Darwin* and solaris* to SunOS\ 5* in configure [Groffen] +- Add solaris* to Linux* in configure to allow gcc use [Groffen] +- Add *bsd* to Linux* case in configure [Bar-Lev] +- Add inffast.obj to dependencies in win32/Makefile.msc +- Correct spelling error in deflate.h [Kohler] +- Change libzdll.a again to libz.dll.a (!) in win32/Makefile.gcc +- Add test to configure for GNU C looking for gcc in output of $cc -v +- Add zlib.pc generation to win32/Makefile.gcc [Weigelt] +- Fix bug in zlib.h for _FILE_OFFSET_BITS set and _LARGEFILE64_SOURCE not +- Add comment in zlib.h that adler32_combine with len2 < 0 makes no sense +- Make NO_DIVIDE option in adler32.c much faster (thanks to John Reiser) +- Make stronger test in zconf.h to include unistd.h for LFS +- Apply Darwin patches for 64-bit file offsets to contrib/minizip [Slack] +- Fix zlib.h LFS support when Z_PREFIX used +- Add updated as400 support (removed from old) [Monnerat] +- Avoid deflate sensitivity to volatile input data +- Avoid division in adler32_combine for NO_DIVIDE +- Clarify the use of Z_FINISH with deflateBound() amount of space +- Set binary for output file in puff.c +- Use u4 type for crc_table to avoid conversion warnings +- Apply casts in zlib.h to avoid conversion warnings +- Add OF to prototypes for adler32_combine_ and crc32_combine_ [Miller] +- Improve inflateSync() documentation to note indeterminancy +- Add deflatePending() function to return the amount of pending output +- Correct the spelling of "specification" in FAQ [Randers-Pehrson] +- Add a check in configure for stdarg.h, use for gzprintf() +- Check that pointers fit in ints when gzprint() compiled old style +- Add dummy name before $(SHAREDLIBV) in Makefile [Bar-Lev, Bowler] +- Delete line in configure that adds -L. libz.a to LDFLAGS [Weigelt] +- Add debug records in assmebler code [Londer] +- Update RFC references to use http://tools.ietf.org/html/... [Li] +- Add --archs option, use of libtool to configure for Mac OS X [Borstel] + +Changes in 1.2.5 (19 Apr 2010) +- Disable visibility attribute in win32/Makefile.gcc [Bar-Lev] +- Default to libdir as sharedlibdir in configure [Nieder] +- Update copyright dates on modified source files +- Update trees.c to be able to generate modified trees.h +- Exit configure for MinGW, suggesting win32/Makefile.gcc +- Check for NULL path in gz_open [Homurlu] + +Changes in 1.2.4.5 (18 Apr 2010) +- Set sharedlibdir in configure [Torok] +- Set LDFLAGS in Makefile.in [Bar-Lev] +- Avoid mkdir objs race condition in Makefile.in [Bowler] +- Add ZLIB_INTERNAL in front of internal inter-module functions and arrays +- Define ZLIB_INTERNAL to hide internal functions and arrays for GNU C +- Don't use hidden attribute when it is a warning generator (e.g. Solaris) + +Changes in 1.2.4.4 (18 Apr 2010) +- Fix CROSS_PREFIX executable testing, CHOST extract, mingw* [Torok] +- Undefine _LARGEFILE64_SOURCE in zconf.h if it is zero, but not if empty +- Try to use bash or ksh regardless of functionality of /bin/sh +- Fix configure incompatibility with NetBSD sh +- Remove attempt to run under bash or ksh since have better NetBSD fix +- Fix win32/Makefile.gcc for MinGW [Bar-Lev] +- Add diagnostic messages when using CROSS_PREFIX in configure +- Added --sharedlibdir option to configure [Weigelt] +- Use hidden visibility attribute when available [Frysinger] + +Changes in 1.2.4.3 (10 Apr 2010) +- Only use CROSS_PREFIX in configure for ar and ranlib if they exist +- Use CROSS_PREFIX for nm [Bar-Lev] +- Assume _LARGEFILE64_SOURCE defined is equivalent to true +- Avoid use of undefined symbols in #if with && and || +- Make *64 prototypes in gzguts.h consistent with functions +- Add -shared load option for MinGW in configure [Bowler] +- Move z_off64_t to public interface, use instead of off64_t +- Remove ! from shell test in configure (not portable to Solaris) +- Change +0 macro tests to -0 for possibly increased portability + +Changes in 1.2.4.2 (9 Apr 2010) +- Add consistent carriage returns to readme.txt's in masmx86 and masmx64 +- Really provide prototypes for *64 functions when building without LFS +- Only define unlink() in minigzip.c if unistd.h not included +- Update README to point to contrib/vstudio project files +- Move projects/vc6 to old/ and remove projects/ +- Include stdlib.h in minigzip.c for setmode() definition under WinCE +- Clean up assembler builds in win32/Makefile.msc [Rowe] +- Include sys/types.h for Microsoft for off_t definition +- Fix memory leak on error in gz_open() +- Symbolize nm as $NM in configure [Weigelt] +- Use TEST_LDSHARED instead of LDSHARED to link test programs [Weigelt] +- Add +0 to _FILE_OFFSET_BITS and _LFS64_LARGEFILE in case not defined +- Fix bug in gzeof() to take into account unused input data +- Avoid initialization of structures with variables in puff.c +- Updated win32/README-WIN32.txt [Rowe] + +Changes in 1.2.4.1 (28 Mar 2010) +- Remove the use of [a-z] constructs for sed in configure [gentoo 310225] +- Remove $(SHAREDLIB) from LIBS in Makefile.in [Creech] +- Restore "for debugging" comment on sprintf() in gzlib.c +- Remove fdopen for MVS from gzguts.h +- Put new README-WIN32.txt in win32 [Rowe] +- Add check for shell to configure and invoke another shell if needed +- Fix big fat stinking bug in gzseek() on uncompressed files +- Remove vestigial F_OPEN64 define in zutil.h +- Set and check the value of _LARGEFILE_SOURCE and _LARGEFILE64_SOURCE +- Avoid errors on non-LFS systems when applications define LFS macros +- Set EXE to ".exe" in configure for MINGW [Kahle] +- Match crc32() in crc32.c exactly to the prototype in zlib.h [Sherrill] +- Add prefix for cross-compilation in win32/makefile.gcc [Bar-Lev] +- Add DLL install in win32/makefile.gcc [Bar-Lev] +- Allow Linux* or linux* from uname in configure [Bar-Lev] +- Allow ldconfig to be redefined in configure and Makefile.in [Bar-Lev] +- Add cross-compilation prefixes to configure [Bar-Lev] +- Match type exactly in gz_load() invocation in gzread.c +- Match type exactly of zcalloc() in zutil.c to zlib.h alloc_func +- Provide prototypes for *64 functions when building zlib without LFS +- Don't use -lc when linking shared library on MinGW +- Remove errno.h check in configure and vestigial errno code in zutil.h + +Changes in 1.2.4 (14 Mar 2010) +- Fix VER3 extraction in configure for no fourth subversion +- Update zlib.3, add docs to Makefile.in to make .pdf out of it +- Add zlib.3.pdf to distribution +- Don't set error code in gzerror() if passed pointer is NULL +- Apply destination directory fixes to CMakeLists.txt [Lowman] +- Move #cmakedefine's to a new zconf.in.cmakein +- Restore zconf.h for builds that don't use configure or cmake +- Add distclean to dummy Makefile for convenience +- Update and improve INDEX, README, and FAQ +- Update CMakeLists.txt for the return of zconf.h [Lowman] +- Update contrib/vstudio/vc9 and vc10 [Vollant] +- Change libz.dll.a back to libzdll.a in win32/Makefile.gcc +- Apply license and readme changes to contrib/asm686 [Raiter] +- Check file name lengths and add -c option in minigzip.c [Li] +- Update contrib/amd64 and contrib/masmx86/ [Vollant] +- Avoid use of "eof" parameter in trees.c to not shadow library variable +- Update make_vms.com for removal of zlibdefs.h [Zinser] +- Update assembler code and vstudio projects in contrib [Vollant] +- Remove outdated assembler code contrib/masm686 and contrib/asm586 +- Remove old vc7 and vc8 from contrib/vstudio +- Update win32/Makefile.msc, add ZLIB_VER_SUBREVISION [Rowe] +- Fix memory leaks in gzclose_r() and gzclose_w(), file leak in gz_open() +- Add contrib/gcc_gvmat64 for longest_match and inflate_fast [Vollant] +- Remove *64 functions from win32/zlib.def (they're not 64-bit yet) +- Fix bug in void-returning vsprintf() case in gzwrite.c +- Fix name change from inflate.h in contrib/inflate86/inffas86.c +- Check if temporary file exists before removing in make_vms.com [Zinser] +- Fix make install and uninstall for --static option +- Fix usage of _MSC_VER in gzguts.h and zutil.h [Truta] +- Update readme.txt in contrib/masmx64 and masmx86 to assemble + +Changes in 1.2.3.9 (21 Feb 2010) +- Expunge gzio.c +- Move as400 build information to old +- Fix updates in contrib/minizip and contrib/vstudio +- Add const to vsnprintf test in configure to avoid warnings [Weigelt] +- Delete zconf.h (made by configure) [Weigelt] +- Change zconf.in.h to zconf.h.in per convention [Weigelt] +- Check for NULL buf in gzgets() +- Return empty string for gzgets() with len == 1 (like fgets()) +- Fix description of gzgets() in zlib.h for end-of-file, NULL return +- Update minizip to 1.1 [Vollant] +- Avoid MSVC loss of data warnings in gzread.c, gzwrite.c +- Note in zlib.h that gzerror() should be used to distinguish from EOF +- Remove use of snprintf() from gzlib.c +- Fix bug in gzseek() +- Update contrib/vstudio, adding vc9 and vc10 [Kuno, Vollant] +- Fix zconf.h generation in CMakeLists.txt [Lowman] +- Improve comments in zconf.h where modified by configure + +Changes in 1.2.3.8 (13 Feb 2010) +- Clean up text files (tabs, trailing whitespace, etc.) [Oberhumer] +- Use z_off64_t in gz_zero() and gz_skip() to match state->skip +- Avoid comparison problem when sizeof(int) == sizeof(z_off64_t) +- Revert to Makefile.in from 1.2.3.6 (live with the clutter) +- Fix missing error return in gzflush(), add zlib.h note +- Add *64 functions to zlib.map [Levin] +- Fix signed/unsigned comparison in gz_comp() +- Use SFLAGS when testing shared linking in configure +- Add --64 option to ./configure to use -m64 with gcc +- Fix ./configure --help to correctly name options +- Have make fail if a test fails [Levin] +- Avoid buffer overrun in contrib/masmx64/gvmat64.asm [Simpson] +- Remove assembler object files from contrib + +Changes in 1.2.3.7 (24 Jan 2010) +- Always gzopen() with O_LARGEFILE if available +- Fix gzdirect() to work immediately after gzopen() or gzdopen() +- Make gzdirect() more precise when the state changes while reading +- Improve zlib.h documentation in many places +- Catch memory allocation failure in gz_open() +- Complete close operation if seek forward in gzclose_w() fails +- Return Z_ERRNO from gzclose_r() if close() fails +- Return Z_STREAM_ERROR instead of EOF for gzclose() being passed NULL +- Return zero for gzwrite() errors to match zlib.h description +- Return -1 on gzputs() error to match zlib.h description +- Add zconf.in.h to allow recovery from configure modification [Weigelt] +- Fix static library permissions in Makefile.in [Weigelt] +- Avoid warnings in configure tests that hide functionality [Weigelt] +- Add *BSD and DragonFly to Linux case in configure [gentoo 123571] +- Change libzdll.a to libz.dll.a in win32/Makefile.gcc [gentoo 288212] +- Avoid access of uninitialized data for first inflateReset2 call [Gomes] +- Keep object files in subdirectories to reduce the clutter somewhat +- Remove default Makefile and zlibdefs.h, add dummy Makefile +- Add new external functions to Z_PREFIX, remove duplicates, z_z_ -> z_ +- Remove zlibdefs.h completely -- modify zconf.h instead + +Changes in 1.2.3.6 (17 Jan 2010) +- Avoid void * arithmetic in gzread.c and gzwrite.c +- Make compilers happier with const char * for gz_error message +- Avoid unused parameter warning in inflate.c +- Avoid signed-unsigned comparison warning in inflate.c +- Indent #pragma's for traditional C +- Fix usage of strwinerror() in glib.c, change to gz_strwinerror() +- Correct email address in configure for system options +- Update make_vms.com and add make_vms.com to contrib/minizip [Zinser] +- Update zlib.map [Brown] +- Fix Makefile.in for Solaris 10 make of example64 and minizip64 [Torok] +- Apply various fixes to CMakeLists.txt [Lowman] +- Add checks on len in gzread() and gzwrite() +- Add error message for no more room for gzungetc() +- Remove zlib version check in gzwrite() +- Defer compression of gzprintf() result until need to +- Use snprintf() in gzdopen() if available +- Remove USE_MMAP configuration determination (only used by minigzip) +- Remove examples/pigz.c (available separately) +- Update examples/gun.c to 1.6 + +Changes in 1.2.3.5 (8 Jan 2010) +- Add space after #if in zutil.h for some compilers +- Fix relatively harmless bug in deflate_fast() [Exarevsky] +- Fix same problem in deflate_slow() +- Add $(SHAREDLIBV) to LIBS in Makefile.in [Brown] +- Add deflate_rle() for faster Z_RLE strategy run-length encoding +- Add deflate_huff() for faster Z_HUFFMAN_ONLY encoding +- Change name of "write" variable in inffast.c to avoid library collisions +- Fix premature EOF from gzread() in gzio.c [Brown] +- Use zlib header window size if windowBits is 0 in inflateInit2() +- Remove compressBound() call in deflate.c to avoid linking compress.o +- Replace use of errno in gz* with functions, support WinCE [Alves] +- Provide alternative to perror() in minigzip.c for WinCE [Alves] +- Don't use _vsnprintf on later versions of MSVC [Lowman] +- Add CMake build script and input file [Lowman] +- Update contrib/minizip to 1.1 [Svensson, Vollant] +- Moved nintendods directory from contrib to . +- Replace gzio.c with a new set of routines with the same functionality +- Add gzbuffer(), gzoffset(), gzclose_r(), gzclose_w() as part of above +- Update contrib/minizip to 1.1b +- Change gzeof() to return 0 on error instead of -1 to agree with zlib.h + +Changes in 1.2.3.4 (21 Dec 2009) +- Use old school .SUFFIXES in Makefile.in for FreeBSD compatibility +- Update comments in configure and Makefile.in for default --shared +- Fix test -z's in configure [Marquess] +- Build examplesh and minigzipsh when not testing +- Change NULL's to Z_NULL's in deflate.c and in comments in zlib.h +- Import LDFLAGS from the environment in configure +- Fix configure to populate SFLAGS with discovered CFLAGS options +- Adapt make_vms.com to the new Makefile.in [Zinser] +- Add zlib2ansi script for C++ compilation [Marquess] +- Add _FILE_OFFSET_BITS=64 test to make test (when applicable) +- Add AMD64 assembler code for longest match to contrib [Teterin] +- Include options from $SFLAGS when doing $LDSHARED +- Simplify 64-bit file support by introducing z_off64_t type +- Make shared object files in objs directory to work around old Sun cc +- Use only three-part version number for Darwin shared compiles +- Add rc option to ar in Makefile.in for when ./configure not run +- Add -WI,-rpath,. to LDFLAGS for OSF 1 V4* +- Set LD_LIBRARYN32_PATH for SGI IRIX shared compile +- Protect against _FILE_OFFSET_BITS being defined when compiling zlib +- Rename Makefile.in targets allstatic to static and allshared to shared +- Fix static and shared Makefile.in targets to be independent +- Correct error return bug in gz_open() by setting state [Brown] +- Put spaces before ;;'s in configure for better sh compatibility +- Add pigz.c (parallel implementation of gzip) to examples/ +- Correct constant in crc32.c to UL [Leventhal] +- Reject negative lengths in crc32_combine() +- Add inflateReset2() function to work like inflateEnd()/inflateInit2() +- Include sys/types.h for _LARGEFILE64_SOURCE [Brown] +- Correct typo in doc/algorithm.txt [Janik] +- Fix bug in adler32_combine() [Zhu] +- Catch missing-end-of-block-code error in all inflates and in puff + Assures that random input to inflate eventually results in an error +- Added enough.c (calculation of ENOUGH for inftrees.h) to examples/ +- Update ENOUGH and its usage to reflect discovered bounds +- Fix gzerror() error report on empty input file [Brown] +- Add ush casts in trees.c to avoid pedantic runtime errors +- Fix typo in zlib.h uncompress() description [Reiss] +- Correct inflate() comments with regard to automatic header detection +- Remove deprecation comment on Z_PARTIAL_FLUSH (it stays) +- Put new version of gzlog (2.0) in examples with interruption recovery +- Add puff compile option to permit invalid distance-too-far streams +- Add puff TEST command options, ability to read piped input +- Prototype the *64 functions in zlib.h when _FILE_OFFSET_BITS == 64, but + _LARGEFILE64_SOURCE not defined +- Fix Z_FULL_FLUSH to truly erase the past by resetting s->strstart +- Fix deflateSetDictionary() to use all 32K for output consistency +- Remove extraneous #define MIN_LOOKAHEAD in deflate.c (in deflate.h) +- Clear bytes after deflate lookahead to avoid use of uninitialized data +- Change a limit in inftrees.c to be more transparent to Coverity Prevent +- Update win32/zlib.def with exported symbols from zlib.h +- Correct spelling errors in zlib.h [Willem, Sobrado] +- Allow Z_BLOCK for deflate() to force a new block +- Allow negative bits in inflatePrime() to delete existing bit buffer +- Add Z_TREES flush option to inflate() to return at end of trees +- Add inflateMark() to return current state information for random access +- Add Makefile for NintendoDS to contrib [Costa] +- Add -w in configure compile tests to avoid spurious warnings [Beucler] +- Fix typos in zlib.h comments for deflateSetDictionary() +- Fix EOF detection in transparent gzread() [Maier] + +Changes in 1.2.3.3 (2 October 2006) +- Make --shared the default for configure, add a --static option +- Add compile option to permit invalid distance-too-far streams +- Add inflateUndermine() function which is required to enable above +- Remove use of "this" variable name for C++ compatibility [Marquess] +- Add testing of shared library in make test, if shared library built +- Use ftello() and fseeko() if available instead of ftell() and fseek() +- Provide two versions of all functions that use the z_off_t type for + binary compatibility -- a normal version and a 64-bit offset version, + per the Large File Support Extension when _LARGEFILE64_SOURCE is + defined; use the 64-bit versions by default when _FILE_OFFSET_BITS + is defined to be 64 +- Add a --uname= option to configure to perhaps help with cross-compiling + +Changes in 1.2.3.2 (3 September 2006) +- Turn off silly Borland warnings [Hay] +- Use off64_t and define _LARGEFILE64_SOURCE when present +- Fix missing dependency on inffixed.h in Makefile.in +- Rig configure --shared to build both shared and static [Teredesai, Truta] +- Remove zconf.in.h and instead create a new zlibdefs.h file +- Fix contrib/minizip/unzip.c non-encrypted after encrypted [Vollant] +- Add treebuild.xml (see http://treebuild.metux.de/) [Weigelt] + +Changes in 1.2.3.1 (16 August 2006) +- Add watcom directory with OpenWatcom make files [Daniel] +- Remove #undef of FAR in zconf.in.h for MVS [Fedtke] +- Update make_vms.com [Zinser] +- Use -fPIC for shared build in configure [Teredesai, Nicholson] +- Use only major version number for libz.so on IRIX and OSF1 [Reinholdtsen] +- Use fdopen() (not _fdopen()) for Interix in zutil.h [Bäck] +- Add some FAQ entries about the contrib directory +- Update the MVS question in the FAQ +- Avoid extraneous reads after EOF in gzio.c [Brown] +- Correct spelling of "successfully" in gzio.c [Randers-Pehrson] +- Add comments to zlib.h about gzerror() usage [Brown] +- Set extra flags in gzip header in gzopen() like deflate() does +- Make configure options more compatible with double-dash conventions + [Weigelt] +- Clean up compilation under Solaris SunStudio cc [Rowe, Reinholdtsen] +- Fix uninstall target in Makefile.in [Truta] +- Add pkgconfig support [Weigelt] +- Use $(DESTDIR) macro in Makefile.in [Reinholdtsen, Weigelt] +- Replace set_data_type() with a more accurate detect_data_type() in + trees.c, according to the txtvsbin.txt document [Truta] +- Swap the order of #include and #include "zlib.h" in + gzio.c, example.c and minigzip.c [Truta] +- Shut up annoying VS2005 warnings about standard C deprecation [Rowe, + Truta] (where?) +- Fix target "clean" from win32/Makefile.bor [Truta] +- Create .pdb and .manifest files in win32/makefile.msc [Ziegler, Rowe] +- Update zlib www home address in win32/DLL_FAQ.txt [Truta] +- Update contrib/masmx86/inffas32.asm for VS2005 [Vollant, Van Wassenhove] +- Enable browse info in the "Debug" and "ASM Debug" configurations in + the Visual C++ 6 project, and set (non-ASM) "Debug" as default [Truta] +- Add pkgconfig support [Weigelt] +- Add ZLIB_VER_MAJOR, ZLIB_VER_MINOR and ZLIB_VER_REVISION in zlib.h, + for use in win32/zlib1.rc [Polushin, Rowe, Truta] +- Add a document that explains the new text detection scheme to + doc/txtvsbin.txt [Truta] +- Add rfc1950.txt, rfc1951.txt and rfc1952.txt to doc/ [Truta] +- Move algorithm.txt into doc/ [Truta] +- Synchronize FAQ with website +- Fix compressBound(), was low for some pathological cases [Fearnley] +- Take into account wrapper variations in deflateBound() +- Set examples/zpipe.c input and output to binary mode for Windows +- Update examples/zlib_how.html with new zpipe.c (also web site) +- Fix some warnings in examples/gzlog.c and examples/zran.c (it seems + that gcc became pickier in 4.0) +- Add zlib.map for Linux: "All symbols from zlib-1.1.4 remain + un-versioned, the patch adds versioning only for symbols introduced in + zlib-1.2.0 or later. It also declares as local those symbols which are + not designed to be exported." [Levin] +- Update Z_PREFIX list in zconf.in.h, add --zprefix option to configure +- Do not initialize global static by default in trees.c, add a response + NO_INIT_GLOBAL_POINTERS to initialize them if needed [Marquess] +- Don't use strerror() in gzio.c under WinCE [Yakimov] +- Don't use errno.h in zutil.h under WinCE [Yakimov] +- Move arguments for AR to its usage to allow replacing ar [Marot] +- Add HAVE_VISIBILITY_PRAGMA in zconf.in.h for Mozilla [Randers-Pehrson] +- Improve inflateInit() and inflateInit2() documentation +- Fix structure size comment in inflate.h +- Change configure help option from --h* to --help [Santos] + +Changes in 1.2.3 (18 July 2005) +- Apply security vulnerability fixes to contrib/infback9 as well +- Clean up some text files (carriage returns, trailing space) +- Update testzlib, vstudio, masmx64, and masmx86 in contrib [Vollant] + +Changes in 1.2.2.4 (11 July 2005) +- Add inflatePrime() function for starting inflation at bit boundary +- Avoid some Visual C warnings in deflate.c +- Avoid more silly Visual C warnings in inflate.c and inftrees.c for 64-bit + compile +- Fix some spelling errors in comments [Betts] +- Correct inflateInit2() error return documentation in zlib.h +- Add zran.c example of compressed data random access to examples + directory, shows use of inflatePrime() +- Fix cast for assignments to strm->state in inflate.c and infback.c +- Fix zlibCompileFlags() in zutil.c to use 1L for long shifts [Oberhumer] +- Move declarations of gf2 functions to right place in crc32.c [Oberhumer] +- Add cast in trees.c t avoid a warning [Oberhumer] +- Avoid some warnings in fitblk.c, gun.c, gzjoin.c in examples [Oberhumer] +- Update make_vms.com [Zinser] +- Initialize state->write in inflateReset() since copied in inflate_fast() +- Be more strict on incomplete code sets in inflate_table() and increase + ENOUGH and MAXD -- this repairs a possible security vulnerability for + invalid inflate input. Thanks to Tavis Ormandy and Markus Oberhumer for + discovering the vulnerability and providing test cases. +- Add ia64 support to configure for HP-UX [Smith] +- Add error return to gzread() for format or i/o error [Levin] +- Use malloc.h for OS/2 [Necasek] + +Changes in 1.2.2.3 (27 May 2005) +- Replace 1U constants in inflate.c and inftrees.c for 64-bit compile +- Typecast fread() return values in gzio.c [Vollant] +- Remove trailing space in minigzip.c outmode (VC++ can't deal with it) +- Fix crc check bug in gzread() after gzungetc() [Heiner] +- Add the deflateTune() function to adjust internal compression parameters +- Add a fast gzip decompressor, gun.c, to examples (use of inflateBack) +- Remove an incorrect assertion in examples/zpipe.c +- Add C++ wrapper in infback9.h [Donais] +- Fix bug in inflateCopy() when decoding fixed codes +- Note in zlib.h how much deflateSetDictionary() actually uses +- Remove USE_DICT_HEAD in deflate.c (would mess up inflate if used) +- Add _WIN32_WCE to define WIN32 in zconf.in.h [Spencer] +- Don't include stderr.h or errno.h for _WIN32_WCE in zutil.h [Spencer] +- Add gzdirect() function to indicate transparent reads +- Update contrib/minizip [Vollant] +- Fix compilation of deflate.c when both ASMV and FASTEST [Oberhumer] +- Add casts in crc32.c to avoid warnings [Oberhumer] +- Add contrib/masmx64 [Vollant] +- Update contrib/asm586, asm686, masmx86, testzlib, vstudio [Vollant] + +Changes in 1.2.2.2 (30 December 2004) +- Replace structure assignments in deflate.c and inflate.c with zmemcpy to + avoid implicit memcpy calls (portability for no-library compilation) +- Increase sprintf() buffer size in gzdopen() to allow for large numbers +- Add INFLATE_STRICT to check distances against zlib header +- Improve WinCE errno handling and comments [Chang] +- Remove comment about no gzip header processing in FAQ +- Add Z_FIXED strategy option to deflateInit2() to force fixed trees +- Add updated make_vms.com [Coghlan], update README +- Create a new "examples" directory, move gzappend.c there, add zpipe.c, + fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html. +- Add FAQ entry and comments in deflate.c on uninitialized memory access +- Add Solaris 9 make options in configure [Gilbert] +- Allow strerror() usage in gzio.c for STDC +- Fix DecompressBuf in contrib/delphi/ZLib.pas [ManChesTer] +- Update contrib/masmx86/inffas32.asm and gvmat32.asm [Vollant] +- Use z_off_t for adler32_combine() and crc32_combine() lengths +- Make adler32() much faster for small len +- Use OS_CODE in deflate() default gzip header + +Changes in 1.2.2.1 (31 October 2004) +- Allow inflateSetDictionary() call for raw inflate +- Fix inflate header crc check bug for file names and comments +- Add deflateSetHeader() and gz_header structure for custom gzip headers +- Add inflateGetheader() to retrieve gzip headers +- Add crc32_combine() and adler32_combine() functions +- Add alloc_func, free_func, in_func, out_func to Z_PREFIX list +- Use zstreamp consistently in zlib.h (inflate_back functions) +- Remove GUNZIP condition from definition of inflate_mode in inflate.h + and in contrib/inflate86/inffast.S [Truta, Anderson] +- Add support for AMD64 in contrib/inflate86/inffas86.c [Anderson] +- Update projects/README.projects and projects/visualc6 [Truta] +- Update win32/DLL_FAQ.txt [Truta] +- Avoid warning under NO_GZCOMPRESS in gzio.c; fix typo [Truta] +- Deprecate Z_ASCII; use Z_TEXT instead [Truta] +- Use a new algorithm for setting strm->data_type in trees.c [Truta] +- Do not define an exit() prototype in zutil.c unless DEBUG defined +- Remove prototype of exit() from zutil.c, example.c, minigzip.c [Truta] +- Add comment in zlib.h for Z_NO_FLUSH parameter to deflate() +- Fix Darwin build version identification [Peterson] + +Changes in 1.2.2 (3 October 2004) +- Update zlib.h comments on gzip in-memory processing +- Set adler to 1 in inflateReset() to support Java test suite [Walles] +- Add contrib/dotzlib [Ravn] +- Update win32/DLL_FAQ.txt [Truta] +- Update contrib/minizip [Vollant] +- Move contrib/visual-basic.txt to old/ [Truta] +- Fix assembler builds in projects/visualc6/ [Truta] + +Changes in 1.2.1.2 (9 September 2004) +- Update INDEX file +- Fix trees.c to update strm->data_type (no one ever noticed!) +- Fix bug in error case in inflate.c, infback.c, and infback9.c [Brown] +- Add "volatile" to crc table flag declaration (for DYNAMIC_CRC_TABLE) +- Add limited multitasking protection to DYNAMIC_CRC_TABLE +- Add NO_vsnprintf for VMS in zutil.h [Mozilla] +- Don't declare strerror() under VMS [Mozilla] +- Add comment to DYNAMIC_CRC_TABLE to use get_crc_table() to initialize +- Update contrib/ada [Anisimkov] +- Update contrib/minizip [Vollant] +- Fix configure to not hardcode directories for Darwin [Peterson] +- Fix gzio.c to not return error on empty files [Brown] +- Fix indentation; update version in contrib/delphi/ZLib.pas and + contrib/pascal/zlibpas.pas [Truta] +- Update mkasm.bat in contrib/masmx86 [Truta] +- Update contrib/untgz [Truta] +- Add projects/README.projects [Truta] +- Add project for MS Visual C++ 6.0 in projects/visualc6 [Cadieux, Truta] +- Update win32/DLL_FAQ.txt [Truta] +- Update list of Z_PREFIX symbols in zconf.h [Randers-Pehrson, Truta] +- Remove an unnecessary assignment to curr in inftrees.c [Truta] +- Add OS/2 to exe builds in configure [Poltorak] +- Remove err dummy parameter in zlib.h [Kientzle] + +Changes in 1.2.1.1 (9 January 2004) +- Update email address in README +- Several FAQ updates +- Fix a big fat bug in inftrees.c that prevented decoding valid + dynamic blocks with only literals and no distance codes -- + Thanks to "Hot Emu" for the bug report and sample file +- Add a note to puff.c on no distance codes case. + +Changes in 1.2.1 (17 November 2003) +- Remove a tab in contrib/gzappend/gzappend.c +- Update some interfaces in contrib for new zlib functions +- Update zlib version number in some contrib entries +- Add Windows CE definition for ptrdiff_t in zutil.h [Mai, Truta] +- Support shared libraries on Hurd and KFreeBSD [Brown] +- Fix error in NO_DIVIDE option of adler32.c + +Changes in 1.2.0.8 (4 November 2003) +- Update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas +- Add experimental NO_DIVIDE #define in adler32.c + - Possibly faster on some processors (let me know if it is) +- Correct Z_BLOCK to not return on first inflate call if no wrap +- Fix strm->data_type on inflate() return to correctly indicate EOB +- Add deflatePrime() function for appending in the middle of a byte +- Add contrib/gzappend for an example of appending to a stream +- Update win32/DLL_FAQ.txt [Truta] +- Delete Turbo C comment in README [Truta] +- Improve some indentation in zconf.h [Truta] +- Fix infinite loop on bad input in configure script [Church] +- Fix gzeof() for concatenated gzip files [Johnson] +- Add example to contrib/visual-basic.txt [Michael B.] +- Add -p to mkdir's in Makefile.in [vda] +- Fix configure to properly detect presence or lack of printf functions +- Add AS400 support [Monnerat] +- Add a little Cygwin support [Wilson] + +Changes in 1.2.0.7 (21 September 2003) +- Correct some debug formats in contrib/infback9 +- Cast a type in a debug statement in trees.c +- Change search and replace delimiter in configure from % to # [Beebe] +- Update contrib/untgz to 0.2 with various fixes [Truta] +- Add build support for Amiga [Nikl] +- Remove some directories in old that have been updated to 1.2 +- Add dylib building for Mac OS X in configure and Makefile.in +- Remove old distribution stuff from Makefile +- Update README to point to DLL_FAQ.txt, and add comment on Mac OS X +- Update links in README + +Changes in 1.2.0.6 (13 September 2003) +- Minor FAQ updates +- Update contrib/minizip to 1.00 [Vollant] +- Remove test of gz functions in example.c when GZ_COMPRESS defined [Truta] +- Update POSTINC comment for 68060 [Nikl] +- Add contrib/infback9 with deflate64 decoding (unsupported) +- For MVS define NO_vsnprintf and undefine FAR [van Burik] +- Add pragma for fdopen on MVS [van Burik] + +Changes in 1.2.0.5 (8 September 2003) +- Add OF to inflateBackEnd() declaration in zlib.h +- Remember start when using gzdopen in the middle of a file +- Use internal off_t counters in gz* functions to properly handle seeks +- Perform more rigorous check for distance-too-far in inffast.c +- Add Z_BLOCK flush option to return from inflate at block boundary +- Set strm->data_type on return from inflate + - Indicate bits unused, if at block boundary, and if in last block +- Replace size_t with ptrdiff_t in crc32.c, and check for correct size +- Add condition so old NO_DEFLATE define still works for compatibility +- FAQ update regarding the Windows DLL [Truta] +- INDEX update: add qnx entry, remove aix entry [Truta] +- Install zlib.3 into mandir [Wilson] +- Move contrib/zlib_dll_FAQ.txt to win32/DLL_FAQ.txt; update [Truta] +- Adapt the zlib interface to the new DLL convention guidelines [Truta] +- Introduce ZLIB_WINAPI macro to allow the export of functions using + the WINAPI calling convention, for Visual Basic [Vollant, Truta] +- Update msdos and win32 scripts and makefiles [Truta] +- Export symbols by name, not by ordinal, in win32/zlib.def [Truta] +- Add contrib/ada [Anisimkov] +- Move asm files from contrib/vstudio/vc70_32 to contrib/asm386 [Truta] +- Rename contrib/asm386 to contrib/masmx86 [Truta, Vollant] +- Add contrib/masm686 [Truta] +- Fix offsets in contrib/inflate86 and contrib/masmx86/inffas32.asm + [Truta, Vollant] +- Update contrib/delphi; rename to contrib/pascal; add example [Truta] +- Remove contrib/delphi2; add a new contrib/delphi [Truta] +- Avoid inclusion of the nonstandard in contrib/iostream, + and fix some method prototypes [Truta] +- Fix the ZCR_SEED2 constant to avoid warnings in contrib/minizip + [Truta] +- Avoid the use of backslash (\) in contrib/minizip [Vollant] +- Fix file time handling in contrib/untgz; update makefiles [Truta] +- Update contrib/vstudio/vc70_32 to comply with the new DLL guidelines + [Vollant] +- Remove contrib/vstudio/vc15_16 [Vollant] +- Rename contrib/vstudio/vc70_32 to contrib/vstudio/vc7 [Truta] +- Update README.contrib [Truta] +- Invert the assignment order of match_head and s->prev[...] in + INSERT_STRING [Truta] +- Compare TOO_FAR with 32767 instead of 32768, to avoid 16-bit warnings + [Truta] +- Compare function pointers with 0, not with NULL or Z_NULL [Truta] +- Fix prototype of syncsearch in inflate.c [Truta] +- Introduce ASMINF macro to be enabled when using an ASM implementation + of inflate_fast [Truta] +- Change NO_DEFLATE to NO_GZCOMPRESS [Truta] +- Modify test_gzio in example.c to take a single file name as a + parameter [Truta] +- Exit the example.c program if gzopen fails [Truta] +- Add type casts around strlen in example.c [Truta] +- Remove casting to sizeof in minigzip.c; give a proper type + to the variable compared with SUFFIX_LEN [Truta] +- Update definitions of STDC and STDC99 in zconf.h [Truta] +- Synchronize zconf.h with the new Windows DLL interface [Truta] +- Use SYS16BIT instead of __32BIT__ to distinguish between + 16- and 32-bit platforms [Truta] +- Use far memory allocators in small 16-bit memory models for + Turbo C [Truta] +- Add info about the use of ASMV, ASMINF and ZLIB_WINAPI in + zlibCompileFlags [Truta] +- Cygwin has vsnprintf [Wilson] +- In Windows16, OS_CODE is 0, as in MSDOS [Truta] +- In Cygwin, OS_CODE is 3 (Unix), not 11 (Windows32) [Wilson] + +Changes in 1.2.0.4 (10 August 2003) +- Minor FAQ updates +- Be more strict when checking inflateInit2's windowBits parameter +- Change NO_GUNZIP compile option to NO_GZIP to cover deflate as well +- Add gzip wrapper option to deflateInit2 using windowBits +- Add updated QNX rule in configure and qnx directory [Bonnefoy] +- Make inflate distance-too-far checks more rigorous +- Clean up FAR usage in inflate +- Add casting to sizeof() in gzio.c and minigzip.c + +Changes in 1.2.0.3 (19 July 2003) +- Fix silly error in gzungetc() implementation [Vollant] +- Update contrib/minizip and contrib/vstudio [Vollant] +- Fix printf format in example.c +- Correct cdecl support in zconf.in.h [Anisimkov] +- Minor FAQ updates + +Changes in 1.2.0.2 (13 July 2003) +- Add ZLIB_VERNUM in zlib.h for numerical preprocessor comparisons +- Attempt to avoid warnings in crc32.c for pointer-int conversion +- Add AIX to configure, remove aix directory [Bakker] +- Add some casts to minigzip.c +- Improve checking after insecure sprintf() or vsprintf() calls +- Remove #elif's from crc32.c +- Change leave label to inf_leave in inflate.c and infback.c to avoid + library conflicts +- Remove inflate gzip decoding by default--only enable gzip decoding by + special request for stricter backward compatibility +- Add zlibCompileFlags() function to return compilation information +- More typecasting in deflate.c to avoid warnings +- Remove leading underscore from _Capital #defines [Truta] +- Fix configure to link shared library when testing +- Add some Windows CE target adjustments [Mai] +- Remove #define ZLIB_DLL in zconf.h [Vollant] +- Add zlib.3 [Rodgers] +- Update RFC URL in deflate.c and algorithm.txt [Mai] +- Add zlib_dll_FAQ.txt to contrib [Truta] +- Add UL to some constants [Truta] +- Update minizip and vstudio [Vollant] +- Remove vestigial NEED_DUMMY_RETURN from zconf.in.h +- Expand use of NO_DUMMY_DECL to avoid all dummy structures +- Added iostream3 to contrib [Schwardt] +- Replace rewind() with fseek() for WinCE [Truta] +- Improve setting of zlib format compression level flags + - Report 0 for huffman and rle strategies and for level == 0 or 1 + - Report 2 only for level == 6 +- Only deal with 64K limit when necessary at compile time [Truta] +- Allow TOO_FAR check to be turned off at compile time [Truta] +- Add gzclearerr() function [Souza] +- Add gzungetc() function + +Changes in 1.2.0.1 (17 March 2003) +- Add Z_RLE strategy for run-length encoding [Truta] + - When Z_RLE requested, restrict matches to distance one + - Update zlib.h, minigzip.c, gzopen(), gzdopen() for Z_RLE +- Correct FASTEST compilation to allow level == 0 +- Clean up what gets compiled for FASTEST +- Incorporate changes to zconf.in.h [Vollant] + - Refine detection of Turbo C need for dummy returns + - Refine ZLIB_DLL compilation + - Include additional header file on VMS for off_t typedef +- Try to use _vsnprintf where it supplants vsprintf [Vollant] +- Add some casts in inffast.c +- Enchance comments in zlib.h on what happens if gzprintf() tries to + write more than 4095 bytes before compression +- Remove unused state from inflateBackEnd() +- Remove exit(0) from minigzip.c, example.c +- Get rid of all those darn tabs +- Add "check" target to Makefile.in that does the same thing as "test" +- Add "mostlyclean" and "maintainer-clean" targets to Makefile.in +- Update contrib/inflate86 [Anderson] +- Update contrib/testzlib, contrib/vstudio, contrib/minizip [Vollant] +- Add msdos and win32 directories with makefiles [Truta] +- More additions and improvements to the FAQ + +Changes in 1.2.0 (9 March 2003) +- New and improved inflate code + - About 20% faster + - Does not allocate 32K window unless and until needed + - Automatically detects and decompresses gzip streams + - Raw inflate no longer needs an extra dummy byte at end + - Added inflateBack functions using a callback interface--even faster + than inflate, useful for file utilities (gzip, zip) + - Added inflateCopy() function to record state for random access on + externally generated deflate streams (e.g. in gzip files) + - More readable code (I hope) +- New and improved crc32() + - About 50% faster, thanks to suggestions from Rodney Brown +- Add deflateBound() and compressBound() functions +- Fix memory leak in deflateInit2() +- Permit setting dictionary for raw deflate (for parallel deflate) +- Fix const declaration for gzwrite() +- Check for some malloc() failures in gzio.c +- Fix bug in gzopen() on single-byte file 0x1f +- Fix bug in gzread() on concatenated file with 0x1f at end of buffer + and next buffer doesn't start with 0x8b +- Fix uncompress() to return Z_DATA_ERROR on truncated input +- Free memory at end of example.c +- Remove MAX #define in trees.c (conflicted with some libraries) +- Fix static const's in deflate.c, gzio.c, and zutil.[ch] +- Declare malloc() and free() in gzio.c if STDC not defined +- Use malloc() instead of calloc() in zutil.c if int big enough +- Define STDC for AIX +- Add aix/ with approach for compiling shared library on AIX +- Add HP-UX support for shared libraries in configure +- Add OpenUNIX support for shared libraries in configure +- Use $cc instead of gcc to build shared library +- Make prefix directory if needed when installing +- Correct Macintosh avoidance of typedef Byte in zconf.h +- Correct Turbo C memory allocation when under Linux +- Use libz.a instead of -lz in Makefile (assure use of compiled library) +- Update configure to check for snprintf or vsnprintf functions and their + return value, warn during make if using an insecure function +- Fix configure problem with compile-time knowledge of HAVE_UNISTD_H that + is lost when library is used--resolution is to build new zconf.h +- Documentation improvements (in zlib.h): + - Document raw deflate and inflate + - Update RFCs URL + - Point out that zlib and gzip formats are different + - Note that Z_BUF_ERROR is not fatal + - Document string limit for gzprintf() and possible buffer overflow + - Note requirement on avail_out when flushing + - Note permitted values of flush parameter of inflate() +- Add some FAQs (and even answers) to the FAQ +- Add contrib/inflate86/ for x86 faster inflate +- Add contrib/blast/ for PKWare Data Compression Library decompression +- Add contrib/puff/ simple inflate for deflate format description + +Changes in 1.1.4 (11 March 2002) +- ZFREE was repeated on same allocation on some error conditions. + This creates a security problem described in + http://www.zlib.org/advisory-2002-03-11.txt +- Returned incorrect error (Z_MEM_ERROR) on some invalid data +- Avoid accesses before window for invalid distances with inflate window + less than 32K. +- force windowBits > 8 to avoid a bug in the encoder for a window size + of 256 bytes. (A complete fix will be available in 1.1.5). + +Changes in 1.1.3 (9 July 1998) +- fix "an inflate input buffer bug that shows up on rare but persistent + occasions" (Mark) +- fix gzread and gztell for concatenated .gz files (Didier Le Botlan) +- fix gzseek(..., SEEK_SET) in write mode +- fix crc check after a gzeek (Frank Faubert) +- fix miniunzip when the last entry in a zip file is itself a zip file + (J Lillge) +- add contrib/asm586 and contrib/asm686 (Brian Raiter) + See http://www.muppetlabs.com/~breadbox/software/assembly.html +- add support for Delphi 3 in contrib/delphi (Bob Dellaca) +- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti) +- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren) +- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks) +- added a FAQ file + +- Support gzdopen on Mac with Metrowerks (Jason Linhart) +- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart) +- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young) +- avoid some warnings with Borland C (Tom Tanner) +- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant) +- emulate utime() for WIN32 in contrib/untgz (Gilles Vollant) +- allow several arguments to configure (Tim Mooney, Frodo Looijaard) +- use libdir and includedir in Makefile.in (Tim Mooney) +- support shared libraries on OSF1 V4 (Tim Mooney) +- remove so_locations in "make clean" (Tim Mooney) +- fix maketree.c compilation error (Glenn, Mark) +- Python interface to zlib now in Python 1.5 (Jeremy Hylton) +- new Makefile.riscos (Rich Walker) +- initialize static descriptors in trees.c for embedded targets (Nick Smith) +- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith) +- add the OS/2 files in Makefile.in too (Andrew Zabolotny) +- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane) +- fix maketree.c to allow clean compilation of inffixed.h (Mark) +- fix parameter check in deflateCopy (Gunther Nikl) +- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler) +- Many portability patches by Christian Spieler: + . zutil.c, zutil.h: added "const" for zmem* + . Make_vms.com: fixed some typos + . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists + . msdos/Makefile.msc: remove "default rtl link library" info from obj files + . msdos/Makefile.*: use model-dependent name for the built zlib library + . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc: + new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT) +- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane) +- replace __far with _far for better portability (Christian Spieler, Tom Lane) +- fix test for errno.h in configure (Tim Newsham) + +Changes in 1.1.2 (19 March 98) +- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant) + See http://www.winimage.com/zLibDll/unzip.html +- preinitialize the inflate tables for fixed codes, to make the code + completely thread safe (Mark) +- some simplifications and slight speed-up to the inflate code (Mark) +- fix gzeof on non-compressed files (Allan Schrum) +- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs) +- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn) +- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny) +- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori) +- do not wrap extern "C" around system includes (Tom Lane) +- mention zlib binding for TCL in README (Andreas Kupries) +- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert) +- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson) +- allow "configure --prefix $HOME" (Tim Mooney) +- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson) +- move Makefile.sas to amiga/Makefile.sas + +Changes in 1.1.1 (27 Feb 98) +- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson) +- remove block truncation heuristic which had very marginal effect for zlib + (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the + compression ratio on some files. This also allows inlining _tr_tally for + matches in deflate_slow. +- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier) + +Changes in 1.1.0 (24 Feb 98) +- do not return STREAM_END prematurely in inflate (John Bowler) +- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler) +- compile with -DFASTEST to get compression code optimized for speed only +- in minigzip, try mmap'ing the input file first (Miguel Albrecht) +- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain + on Sun but significant on HP) + +- add a pointer to experimental unzip library in README (Gilles Vollant) +- initialize variable gcc in configure (Chris Herborth) + +Changes in 1.0.9 (17 Feb 1998) +- added gzputs and gzgets functions +- do not clear eof flag in gzseek (Mark Diekhans) +- fix gzseek for files in transparent mode (Mark Diekhans) +- do not assume that vsprintf returns the number of bytes written (Jens Krinke) +- replace EXPORT with ZEXPORT to avoid conflict with other programs +- added compress2 in zconf.h, zlib.def, zlib.dnt +- new asm code from Gilles Vollant in contrib/asm386 +- simplify the inflate code (Mark): + . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new() + . ZALLOC the length list in inflate_trees_fixed() instead of using stack + . ZALLOC the value area for huft_build() instead of using stack + . Simplify Z_FINISH check in inflate() + +- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8 +- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi) +- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with + the declaration of FAR (Gilles VOllant) +- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann) +- read_buf buf parameter of type Bytef* instead of charf* +- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout) +- do not redeclare unlink in minigzip.c for WIN32 (John Bowler) +- fix check for presence of directories in "make install" (Ian Willis) + +Changes in 1.0.8 (27 Jan 1998) +- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant) +- fix gzgetc and gzputc for big endian systems (Markus Oberhumer) +- added compress2() to allow setting the compression level +- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong) +- use constant arrays for the static trees in trees.c instead of computing + them at run time (thanks to Ken Raeburn for this suggestion). To create + trees.h, compile with GEN_TREES_H and run "make test". +- check return code of example in "make test" and display result +- pass minigzip command line options to file_compress +- simplifying code of inflateSync to avoid gcc 2.8 bug + +- support CC="gcc -Wall" in configure -s (QingLong) +- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn) +- fix test for shared library support to avoid compiler warnings +- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant) +- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit) +- do not use fdopen for Metrowerks on Mac (Brad Pettit)) +- add checks for gzputc and gzputc in example.c +- avoid warnings in gzio.c and deflate.c (Andreas Kleinert) +- use const for the CRC table (Ken Raeburn) +- fixed "make uninstall" for shared libraries +- use Tracev instead of Trace in infblock.c +- in example.c use correct compressed length for test_sync +- suppress +vnocompatwarnings in configure for HPUX (not always supported) + +Changes in 1.0.7 (20 Jan 1998) +- fix gzseek which was broken in write mode +- return error for gzseek to negative absolute position +- fix configure for Linux (Chun-Chung Chen) +- increase stack space for MSC (Tim Wegner) +- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant) +- define EXPORTVA for gzprintf (Gilles Vollant) +- added man page zlib.3 (Rick Rodgers) +- for contrib/untgz, fix makedir() and improve Makefile + +- check gzseek in write mode in example.c +- allocate extra buffer for seeks only if gzseek is actually called +- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant) +- add inflateSyncPoint in zconf.h +- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def + +Changes in 1.0.6 (19 Jan 1998) +- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and + gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code) +- Fix a deflate bug occurring only with compression level 0 (thanks to + Andy Buckler for finding this one). +- In minigzip, pass transparently also the first byte for .Z files. +- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress() +- check Z_FINISH in inflate (thanks to Marc Schluper) +- Implement deflateCopy (thanks to Adam Costello) +- make static libraries by default in configure, add --shared option. +- move MSDOS or Windows specific files to directory msdos +- suppress the notion of partial flush to simplify the interface + (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4) +- suppress history buffer provided by application to simplify the interface + (this feature was not implemented anyway in 1.0.4) +- next_in and avail_in must be initialized before calling inflateInit or + inflateInit2 +- add EXPORT in all exported functions (for Windows DLL) +- added Makefile.nt (thanks to Stephen Williams) +- added the unsupported "contrib" directory: + contrib/asm386/ by Gilles Vollant + 386 asm code replacing longest_match(). + contrib/iostream/ by Kevin Ruland + A C++ I/O streams interface to the zlib gz* functions + contrib/iostream2/ by Tyge Løvset + Another C++ I/O streams interface + contrib/untgz/ by "Pedro A. Aranda Guti\irrez" + A very simple tar.gz file extractor using zlib + contrib/visual-basic.txt by Carlos Rios + How to use compress(), uncompress() and the gz* functions from VB. +- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression + level) in minigzip (thanks to Tom Lane) + +- use const for rommable constants in deflate +- added test for gzseek and gztell in example.c +- add undocumented function inflateSyncPoint() (hack for Paul Mackerras) +- add undocumented function zError to convert error code to string + (for Tim Smithers) +- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code. +- Use default memcpy for Symantec MSDOS compiler. +- Add EXPORT keyword for check_func (needed for Windows DLL) +- add current directory to LD_LIBRARY_PATH for "make test" +- create also a link for libz.so.1 +- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura) +- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX) +- added -soname for Linux in configure (Chun-Chung Chen, +- assign numbers to the exported functions in zlib.def (for Windows DLL) +- add advice in zlib.h for best usage of deflateSetDictionary +- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn) +- allow compilation with ANSI keywords only enabled for TurboC in large model +- avoid "versionString"[0] (Borland bug) +- add NEED_DUMMY_RETURN for Borland +- use variable z_verbose for tracing in debug mode (L. Peter Deutsch). +- allow compilation with CC +- defined STDC for OS/2 (David Charlap) +- limit external names to 8 chars for MVS (Thomas Lund) +- in minigzip.c, use static buffers only for 16-bit systems +- fix suffix check for "minigzip -d foo.gz" +- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee) +- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau) +- added makelcc.bat for lcc-win32 (Tom St Denis) +- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe) +- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion. +- check for unistd.h in configure (for off_t) +- remove useless check parameter in inflate_blocks_free +- avoid useless assignment of s->check to itself in inflate_blocks_new +- do not flush twice in gzclose (thanks to Ken Raeburn) +- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h +- use NO_ERRNO_H instead of enumeration of operating systems with errno.h +- work around buggy fclose on pipes for HP/UX +- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson) +- fix configure if CC is already equal to gcc + +Changes in 1.0.5 (3 Jan 98) +- Fix inflate to terminate gracefully when fed corrupted or invalid data +- Use const for rommable constants in inflate +- Eliminate memory leaks on error conditions in inflate +- Removed some vestigial code in inflate +- Update web address in README + +Changes in 1.0.4 (24 Jul 96) +- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF + bit, so the decompressor could decompress all the correct data but went + on to attempt decompressing extra garbage data. This affected minigzip too. +- zlibVersion and gzerror return const char* (needed for DLL) +- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno) +- use z_error only for DEBUG (avoid problem with DLLs) + +Changes in 1.0.3 (2 Jul 96) +- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS + small and medium models; this makes the library incompatible with previous + versions for these models. (No effect in large model or on other systems.) +- return OK instead of BUF_ERROR if previous deflate call returned with + avail_out as zero but there is nothing to do +- added memcmp for non STDC compilers +- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly) +- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO) +- better check for 16-bit mode MSC (avoids problem with Symantec) + +Changes in 1.0.2 (23 May 96) +- added Windows DLL support +- added a function zlibVersion (for the DLL support) +- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model) +- Bytef is define's instead of typedef'd only for Borland C +- avoid reading uninitialized memory in example.c +- mention in README that the zlib format is now RFC1950 +- updated Makefile.dj2 +- added algorithm.doc + +Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion] +- fix array overlay in deflate.c which sometimes caused bad compressed data +- fix inflate bug with empty stored block +- fix MSDOS medium model which was broken in 0.99 +- fix deflateParams() which could generate bad compressed data. +- Bytef is define'd instead of typedef'ed (work around Borland bug) +- added an INDEX file +- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32), + Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas) +- speed up adler32 for modern machines without auto-increment +- added -ansi for IRIX in configure +- static_init_done in trees.c is an int +- define unlink as delete for VMS +- fix configure for QNX +- add configure branch for SCO and HPUX +- avoid many warnings (unused variables, dead assignments, etc...) +- no fdopen for BeOS +- fix the Watcom fix for 32 bit mode (define FAR as empty) +- removed redefinition of Byte for MKWERKS +- work around an MWKERKS bug (incorrect merge of all .h files) + +Changes in 0.99 (27 Jan 96) +- allow preset dictionary shared between compressor and decompressor +- allow compression level 0 (no compression) +- add deflateParams in zlib.h: allow dynamic change of compression level + and compression strategy. +- test large buffers and deflateParams in example.c +- add optional "configure" to build zlib as a shared library +- suppress Makefile.qnx, use configure instead +- fixed deflate for 64-bit systems (detected on Cray) +- fixed inflate_blocks for 64-bit systems (detected on Alpha) +- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2) +- always return Z_BUF_ERROR when deflate() has nothing to do +- deflateInit and inflateInit are now macros to allow version checking +- prefix all global functions and types with z_ with -DZ_PREFIX +- make falloc completely reentrant (inftrees.c) +- fixed very unlikely race condition in ct_static_init +- free in reverse order of allocation to help memory manager +- use zlib-1.0/* instead of zlib/* inside the tar.gz +- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith + -Wconversion -Wstrict-prototypes -Wmissing-prototypes" +- allow gzread on concatenated .gz files +- deflateEnd now returns Z_DATA_ERROR if it was premature +- deflate is finally (?) fully deterministic (no matches beyond end of input) +- Document Z_SYNC_FLUSH +- add uninstall in Makefile +- Check for __cpluplus in zlib.h +- Better test in ct_align for partial flush +- avoid harmless warnings for Borland C++ +- initialize hash_head in deflate.c +- avoid warning on fdopen (gzio.c) for HP cc -Aa +- include stdlib.h for STDC compilers +- include errno.h for Cray +- ignore error if ranlib doesn't exist +- call ranlib twice for NeXTSTEP +- use exec_prefix instead of prefix for libz.a +- renamed ct_* as _tr_* to avoid conflict with applications +- clear z->msg in inflateInit2 before any error return +- initialize opaque in example.c, gzio.c, deflate.c and inflate.c +- fixed typo in zconf.h (_GNUC__ => __GNUC__) +- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode) +- fix typo in Make_vms.com (f$trnlnm -> f$getsyi) +- in fcalloc, normalize pointer if size > 65520 bytes +- don't use special fcalloc for 32 bit Borland C++ +- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc... +- use Z_BINARY instead of BINARY +- document that gzclose after gzdopen will close the file +- allow "a" as mode in gzopen. +- fix error checking in gzread +- allow skipping .gz extra-field on pipes +- added reference to Perl interface in README +- put the crc table in FAR data (I dislike more and more the medium model :) +- added get_crc_table +- added a dimension to all arrays (Borland C can't count). +- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast +- guard against multiple inclusion of *.h (for precompiled header on Mac) +- Watcom C pretends to be Microsoft C small model even in 32 bit mode. +- don't use unsized arrays to avoid silly warnings by Visual C++: + warning C4746: 'inflate_mask' : unsized array treated as '__far' + (what's wrong with far data in far model?). +- define enum out of inflate_blocks_state to allow compilation with C++ + +Changes in 0.95 (16 Aug 95) +- fix MSDOS small and medium model (now easier to adapt to any compiler) +- inlined send_bits +- fix the final (:-) bug for deflate with flush (output was correct but + not completely flushed in rare occasions). +- default window size is same for compression and decompression + (it's now sufficient to set MAX_WBITS in zconf.h). +- voidp -> voidpf and voidnp -> voidp (for consistency with other + typedefs and because voidnp was not near in large model). + +Changes in 0.94 (13 Aug 95) +- support MSDOS medium model +- fix deflate with flush (could sometimes generate bad output) +- fix deflateReset (zlib header was incorrectly suppressed) +- added support for VMS +- allow a compression level in gzopen() +- gzflush now calls fflush +- For deflate with flush, flush even if no more input is provided. +- rename libgz.a as libz.a +- avoid complex expression in infcodes.c triggering Turbo C bug +- work around a problem with gcc on Alpha (in INSERT_STRING) +- don't use inline functions (problem with some gcc versions) +- allow renaming of Byte, uInt, etc... with #define. +- avoid warning about (unused) pointer before start of array in deflate.c +- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c +- avoid reserved word 'new' in trees.c + +Changes in 0.93 (25 June 95) +- temporarily disable inline functions +- make deflate deterministic +- give enough lookahead for PARTIAL_FLUSH +- Set binary mode for stdin/stdout in minigzip.c for OS/2 +- don't even use signed char in inflate (not portable enough) +- fix inflate memory leak for segmented architectures + +Changes in 0.92 (3 May 95) +- don't assume that char is signed (problem on SGI) +- Clear bit buffer when starting a stored block +- no memcpy on Pyramid +- suppressed inftest.c +- optimized fill_window, put longest_match inline for gcc +- optimized inflate on stored blocks. +- untabify all sources to simplify patches + +Changes in 0.91 (2 May 95) +- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h +- Document the memory requirements in zconf.h +- added "make install" +- fix sync search logic in inflateSync +- deflate(Z_FULL_FLUSH) now works even if output buffer too short +- after inflateSync, don't scare people with just "lo world" +- added support for DJGPP + +Changes in 0.9 (1 May 95) +- don't assume that zalloc clears the allocated memory (the TurboC bug + was Mark's bug after all :) +- let again gzread copy uncompressed data unchanged (was working in 0.71) +- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented +- added a test of inflateSync in example.c +- moved MAX_WBITS to zconf.h because users might want to change that. +- document explicitly that zalloc(64K) on MSDOS must return a normalized + pointer (zero offset) +- added Makefiles for Microsoft C, Turbo C, Borland C++ +- faster crc32() + +Changes in 0.8 (29 April 95) +- added fast inflate (inffast.c) +- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this + is incompatible with previous versions of zlib which returned Z_OK. +- work around a TurboC compiler bug (bad code for b << 0, see infutil.h) + (actually that was not a compiler bug, see 0.81 above) +- gzread no longer reads one extra byte in certain cases +- In gzio destroy(), don't reference a freed structure +- avoid many warnings for MSDOS +- avoid the ERROR symbol which is used by MS Windows + +Changes in 0.71 (14 April 95) +- Fixed more MSDOS compilation problems :( There is still a bug with + TurboC large model. + +Changes in 0.7 (14 April 95) +- Added full inflate support. +- Simplified the crc32() interface. The pre- and post-conditioning + (one's complement) is now done inside crc32(). WARNING: this is + incompatible with previous versions; see zlib.h for the new usage. + +Changes in 0.61 (12 April 95) +- workaround for a bug in TurboC. example and minigzip now work on MSDOS. + +Changes in 0.6 (11 April 95) +- added minigzip.c +- added gzdopen to reopen a file descriptor as gzFile +- added transparent reading of non-gziped files in gzread. +- fixed bug in gzread (don't read crc as data) +- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose). +- don't allocate big arrays in the stack (for MSDOS) +- fix some MSDOS compilation problems + +Changes in 0.5: +- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but + not yet Z_FULL_FLUSH. +- support decompression but only in a single step (forced Z_FINISH) +- added opaque object for zalloc and zfree. +- added deflateReset and inflateReset +- added a variable zlib_version for consistency checking. +- renamed the 'filter' parameter of deflateInit2 as 'strategy'. + Added Z_FILTERED and Z_HUFFMAN_ONLY constants. + +Changes in 0.4: +- avoid "zip" everywhere, use zlib instead of ziplib. +- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush + if compression method == 8. +- added adler32 and crc32 +- renamed deflateOptions as deflateInit2, call one or the other but not both +- added the method parameter for deflateInit2. +- added inflateInit2 +- simplied considerably deflateInit and inflateInit by not supporting + user-provided history buffer. This is supported only in deflateInit2 + and inflateInit2. + +Changes in 0.3: +- prefix all macro names with Z_ +- use Z_FINISH instead of deflateEnd to finish compression. +- added Z_HUFFMAN_ONLY +- added gzerror() diff --git a/dependencies/zlib-1.2.11/FAQ b/dependencies/zlib-1.2.11/FAQ new file mode 100644 index 0000000..99b7cf9 --- /dev/null +++ b/dependencies/zlib-1.2.11/FAQ @@ -0,0 +1,368 @@ + + Frequently Asked Questions about zlib + + +If your question is not there, please check the zlib home page +http://zlib.net/ which may have more recent information. +The lastest zlib FAQ is at http://zlib.net/zlib_faq.html + + + 1. Is zlib Y2K-compliant? + + Yes. zlib doesn't handle dates. + + 2. Where can I get a Windows DLL version? + + The zlib sources can be compiled without change to produce a DLL. See the + file win32/DLL_FAQ.txt in the zlib distribution. Pointers to the + precompiled DLL are found in the zlib web site at http://zlib.net/ . + + 3. Where can I get a Visual Basic interface to zlib? + + See + * http://marknelson.us/1997/01/01/zlib-engine/ + * win32/DLL_FAQ.txt in the zlib distribution + + 4. compress() returns Z_BUF_ERROR. + + Make sure that before the call of compress(), the length of the compressed + buffer is equal to the available size of the compressed buffer and not + zero. For Visual Basic, check that this parameter is passed by reference + ("as any"), not by value ("as long"). + + 5. deflate() or inflate() returns Z_BUF_ERROR. + + Before making the call, make sure that avail_in and avail_out are not zero. + When setting the parameter flush equal to Z_FINISH, also make sure that + avail_out is big enough to allow processing all pending input. Note that a + Z_BUF_ERROR is not fatal--another call to deflate() or inflate() can be + made with more input or output space. A Z_BUF_ERROR may in fact be + unavoidable depending on how the functions are used, since it is not + possible to tell whether or not there is more output pending when + strm.avail_out returns with zero. See http://zlib.net/zlib_how.html for a + heavily annotated example. + + 6. Where's the zlib documentation (man pages, etc.)? + + It's in zlib.h . Examples of zlib usage are in the files test/example.c + and test/minigzip.c, with more in examples/ . + + 7. Why don't you use GNU autoconf or libtool or ...? + + Because we would like to keep zlib as a very small and simple package. + zlib is rather portable and doesn't need much configuration. + + 8. I found a bug in zlib. + + Most of the time, such problems are due to an incorrect usage of zlib. + Please try to reproduce the problem with a small program and send the + corresponding source to us at zlib@gzip.org . Do not send multi-megabyte + data files without prior agreement. + + 9. Why do I get "undefined reference to gzputc"? + + If "make test" produces something like + + example.o(.text+0x154): undefined reference to `gzputc' + + check that you don't have old files libz.* in /usr/lib, /usr/local/lib or + /usr/X11R6/lib. Remove any old versions, then do "make install". + +10. I need a Delphi interface to zlib. + + See the contrib/delphi directory in the zlib distribution. + +11. Can zlib handle .zip archives? + + Not by itself, no. See the directory contrib/minizip in the zlib + distribution. + +12. Can zlib handle .Z files? + + No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt + the code of uncompress on your own. + +13. How can I make a Unix shared library? + + By default a shared (and a static) library is built for Unix. So: + + make distclean + ./configure + make + +14. How do I install a shared zlib library on Unix? + + After the above, then: + + make install + + However, many flavors of Unix come with a shared zlib already installed. + Before going to the trouble of compiling a shared version of zlib and + trying to install it, you may want to check if it's already there! If you + can #include , it's there. The -lz option will probably link to + it. You can check the version at the top of zlib.h or with the + ZLIB_VERSION symbol defined in zlib.h . + +15. I have a question about OttoPDF. + + We are not the authors of OttoPDF. The real author is on the OttoPDF web + site: Joel Hainley, jhainley@myndkryme.com. + +16. Can zlib decode Flate data in an Adobe PDF file? + + Yes. See http://www.pdflib.com/ . To modify PDF forms, see + http://sourceforge.net/projects/acroformtool/ . + +17. Why am I getting this "register_frame_info not found" error on Solaris? + + After installing zlib 1.1.4 on Solaris 2.6, running applications using zlib + generates an error such as: + + ld.so.1: rpm: fatal: relocation error: file /usr/local/lib/libz.so: + symbol __register_frame_info: referenced symbol not found + + The symbol __register_frame_info is not part of zlib, it is generated by + the C compiler (cc or gcc). You must recompile applications using zlib + which have this problem. This problem is specific to Solaris. See + http://www.sunfreeware.com for Solaris versions of zlib and applications + using zlib. + +18. Why does gzip give an error on a file I make with compress/deflate? + + The compress and deflate functions produce data in the zlib format, which + is different and incompatible with the gzip format. The gz* functions in + zlib on the other hand use the gzip format. Both the zlib and gzip formats + use the same compressed data format internally, but have different headers + and trailers around the compressed data. + +19. Ok, so why are there two different formats? + + The gzip format was designed to retain the directory information about a + single file, such as the name and last modification date. The zlib format + on the other hand was designed for in-memory and communication channel + applications, and has a much more compact header and trailer and uses a + faster integrity check than gzip. + +20. Well that's nice, but how do I make a gzip file in memory? + + You can request that deflate write the gzip format instead of the zlib + format using deflateInit2(). You can also request that inflate decode the + gzip format using inflateInit2(). Read zlib.h for more details. + +21. Is zlib thread-safe? + + Yes. However any library routines that zlib uses and any application- + provided memory allocation routines must also be thread-safe. zlib's gz* + functions use stdio library routines, and most of zlib's functions use the + library memory allocation routines by default. zlib's *Init* functions + allow for the application to provide custom memory allocation routines. + + Of course, you should only operate on any given zlib or gzip stream from a + single thread at a time. + +22. Can I use zlib in my commercial application? + + Yes. Please read the license in zlib.h. + +23. Is zlib under the GNU license? + + No. Please read the license in zlib.h. + +24. The license says that altered source versions must be "plainly marked". So + what exactly do I need to do to meet that requirement? + + You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In + particular, the final version number needs to be changed to "f", and an + identification string should be appended to ZLIB_VERSION. Version numbers + x.x.x.f are reserved for modifications to zlib by others than the zlib + maintainers. For example, if the version of the base zlib you are altering + is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and + ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also + update the version strings in deflate.c and inftrees.c. + + For altered source distributions, you should also note the origin and + nature of the changes in zlib.h, as well as in ChangeLog and README, along + with the dates of the alterations. The origin should include at least your + name (or your company's name), and an email address to contact for help or + issues with the library. + + Note that distributing a compiled zlib library along with zlib.h and + zconf.h is also a source distribution, and so you should change + ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes + in zlib.h as you would for a full source distribution. + +25. Will zlib work on a big-endian or little-endian architecture, and can I + exchange compressed data between them? + + Yes and yes. + +26. Will zlib work on a 64-bit machine? + + Yes. It has been tested on 64-bit machines, and has no dependence on any + data types being limited to 32-bits in length. If you have any + difficulties, please provide a complete problem report to zlib@gzip.org + +27. Will zlib decompress data from the PKWare Data Compression Library? + + No. The PKWare DCL uses a completely different compressed data format than + does PKZIP and zlib. However, you can look in zlib's contrib/blast + directory for a possible solution to your problem. + +28. Can I access data randomly in a compressed stream? + + No, not without some preparation. If when compressing you periodically use + Z_FULL_FLUSH, carefully write all the pending data at those points, and + keep an index of those locations, then you can start decompression at those + points. You have to be careful to not use Z_FULL_FLUSH too often, since it + can significantly degrade compression. Alternatively, you can scan a + deflate stream once to generate an index, and then use that index for + random access. See examples/zran.c . + +29. Does zlib work on MVS, OS/390, CICS, etc.? + + It has in the past, but we have not heard of any recent evidence. There + were working ports of zlib 1.1.4 to MVS, but those links no longer work. + If you know of recent, successful applications of zlib on these operating + systems, please let us know. Thanks. + +30. Is there some simpler, easier to read version of inflate I can look at to + understand the deflate format? + + First off, you should read RFC 1951. Second, yes. Look in zlib's + contrib/puff directory. + +31. Does zlib infringe on any patents? + + As far as we know, no. In fact, that was originally the whole point behind + zlib. Look here for some more information: + + http://www.gzip.org/#faq11 + +32. Can zlib work with greater than 4 GB of data? + + Yes. inflate() and deflate() will process any amount of data correctly. + Each call of inflate() or deflate() is limited to input and output chunks + of the maximum value that can be stored in the compiler's "unsigned int" + type, but there is no limit to the number of chunks. Note however that the + strm.total_in and strm_total_out counters may be limited to 4 GB. These + counters are provided as a convenience and are not used internally by + inflate() or deflate(). The application can easily set up its own counters + updated after each call of inflate() or deflate() to count beyond 4 GB. + compress() and uncompress() may be limited to 4 GB, since they operate in a + single call. gzseek() and gztell() may be limited to 4 GB depending on how + zlib is compiled. See the zlibCompileFlags() function in zlib.h. + + The word "may" appears several times above since there is a 4 GB limit only + if the compiler's "long" type is 32 bits. If the compiler's "long" type is + 64 bits, then the limit is 16 exabytes. + +33. Does zlib have any security vulnerabilities? + + The only one that we are aware of is potentially in gzprintf(). If zlib is + compiled to use sprintf() or vsprintf(), then there is no protection + against a buffer overflow of an 8K string space (or other value as set by + gzbuffer()), other than the caller of gzprintf() assuring that the output + will not exceed 8K. On the other hand, if zlib is compiled to use + snprintf() or vsnprintf(), which should normally be the case, then there is + no vulnerability. The ./configure script will display warnings if an + insecure variation of sprintf() will be used by gzprintf(). Also the + zlibCompileFlags() function will return information on what variant of + sprintf() is used by gzprintf(). + + If you don't have snprintf() or vsnprintf() and would like one, you can + find a portable implementation here: + + http://www.ijs.si/software/snprintf/ + + Note that you should be using the most recent version of zlib. Versions + 1.1.3 and before were subject to a double-free vulnerability, and versions + 1.2.1 and 1.2.2 were subject to an access exception when decompressing + invalid compressed data. + +34. Is there a Java version of zlib? + + Probably what you want is to use zlib in Java. zlib is already included + as part of the Java SDK in the java.util.zip package. If you really want + a version of zlib written in the Java language, look on the zlib home + page for links: http://zlib.net/ . + +35. I get this or that compiler or source-code scanner warning when I crank it + up to maximally-pedantic. Can't you guys write proper code? + + Many years ago, we gave up attempting to avoid warnings on every compiler + in the universe. It just got to be a waste of time, and some compilers + were downright silly as well as contradicted each other. So now, we simply + make sure that the code always works. + +36. Valgrind (or some similar memory access checker) says that deflate is + performing a conditional jump that depends on an uninitialized value. + Isn't that a bug? + + No. That is intentional for performance reasons, and the output of deflate + is not affected. This only started showing up recently since zlib 1.2.x + uses malloc() by default for allocations, whereas earlier versions used + calloc(), which zeros out the allocated memory. Even though the code was + correct, versions 1.2.4 and later was changed to not stimulate these + checkers. + +37. Will zlib read the (insert any ancient or arcane format here) compressed + data format? + + Probably not. Look in the comp.compression FAQ for pointers to various + formats and associated software. + +38. How can I encrypt/decrypt zip files with zlib? + + zlib doesn't support encryption. The original PKZIP encryption is very + weak and can be broken with freely available programs. To get strong + encryption, use GnuPG, http://www.gnupg.org/ , which already includes zlib + compression. For PKZIP compatible "encryption", look at + http://www.info-zip.org/ + +39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings? + + "gzip" is the gzip format, and "deflate" is the zlib format. They should + probably have called the second one "zlib" instead to avoid confusion with + the raw deflate compressed data format. While the HTTP 1.1 RFC 2616 + correctly points to the zlib specification in RFC 1950 for the "deflate" + transfer encoding, there have been reports of servers and browsers that + incorrectly produce or expect raw deflate data per the deflate + specification in RFC 1951, most notably Microsoft. So even though the + "deflate" transfer encoding using the zlib format would be the more + efficient approach (and in fact exactly what the zlib format was designed + for), using the "gzip" transfer encoding is probably more reliable due to + an unfortunate choice of name on the part of the HTTP 1.1 authors. + + Bottom line: use the gzip format for HTTP 1.1 encoding. + +40. Does zlib support the new "Deflate64" format introduced by PKWare? + + No. PKWare has apparently decided to keep that format proprietary, since + they have not documented it as they have previous compression formats. In + any case, the compression improvements are so modest compared to other more + modern approaches, that it's not worth the effort to implement. + +41. I'm having a problem with the zip functions in zlib, can you help? + + There are no zip functions in zlib. You are probably using minizip by + Giles Vollant, which is found in the contrib directory of zlib. It is not + part of zlib. In fact none of the stuff in contrib is part of zlib. The + files in there are not supported by the zlib authors. You need to contact + the authors of the respective contribution for help. + +42. The match.asm code in contrib is under the GNU General Public License. + Since it's part of zlib, doesn't that mean that all of zlib falls under the + GNU GPL? + + No. The files in contrib are not part of zlib. They were contributed by + other authors and are provided as a convenience to the user within the zlib + distribution. Each item in contrib has its own license. + +43. Is zlib subject to export controls? What is its ECCN? + + zlib is not subject to export controls, and so is classified as EAR99. + +44. Can you please sign these lengthy legal documents and fax them back to us + so that we can use your software in our product? + + No. Go away. Shoo. diff --git a/dependencies/zlib-1.2.11/INDEX b/dependencies/zlib-1.2.11/INDEX new file mode 100644 index 0000000..2ba0641 --- /dev/null +++ b/dependencies/zlib-1.2.11/INDEX @@ -0,0 +1,68 @@ +CMakeLists.txt cmake build file +ChangeLog history of changes +FAQ Frequently Asked Questions about zlib +INDEX this file +Makefile dummy Makefile that tells you to ./configure +Makefile.in template for Unix Makefile +README guess what +configure configure script for Unix +make_vms.com makefile for VMS +test/example.c zlib usages examples for build testing +test/minigzip.c minimal gzip-like functionality for build testing +test/infcover.c inf*.c code coverage for build coverage testing +treebuild.xml XML description of source file dependencies +zconf.h.cmakein zconf.h template for cmake +zconf.h.in zconf.h template for configure +zlib.3 Man page for zlib +zlib.3.pdf Man page in PDF format +zlib.map Linux symbol information +zlib.pc.in Template for pkg-config descriptor +zlib.pc.cmakein zlib.pc template for cmake +zlib2ansi perl script to convert source files for C++ compilation + +amiga/ makefiles for Amiga SAS C +as400/ makefiles for AS/400 +doc/ documentation for formats and algorithms +msdos/ makefiles for MSDOS +nintendods/ makefile for Nintendo DS +old/ makefiles for various architectures and zlib documentation + files that have not yet been updated for zlib 1.2.x +qnx/ makefiles for QNX +watcom/ makefiles for OpenWatcom +win32/ makefiles for Windows + + zlib public header files (required for library use): +zconf.h +zlib.h + + private source files used to build the zlib library: +adler32.c +compress.c +crc32.c +crc32.h +deflate.c +deflate.h +gzclose.c +gzguts.h +gzlib.c +gzread.c +gzwrite.c +infback.c +inffast.c +inffast.h +inffixed.h +inflate.c +inflate.h +inftrees.c +inftrees.h +trees.c +trees.h +uncompr.c +zutil.c +zutil.h + + source files for sample programs +See examples/README.examples + + unsupported contributions by third parties +See contrib/README.contrib diff --git a/dependencies/zlib-1.2.11/Makefile b/dependencies/zlib-1.2.11/Makefile new file mode 100644 index 0000000..6bba86c --- /dev/null +++ b/dependencies/zlib-1.2.11/Makefile @@ -0,0 +1,5 @@ +all: + -@echo "Please use ./configure first. Thank you." + +distclean: + make -f Makefile.in distclean diff --git a/dependencies/zlib-1.2.11/Makefile.in b/dependencies/zlib-1.2.11/Makefile.in new file mode 100644 index 0000000..5a77949 --- /dev/null +++ b/dependencies/zlib-1.2.11/Makefile.in @@ -0,0 +1,410 @@ +# Makefile for zlib +# Copyright (C) 1995-2017 Jean-loup Gailly, Mark Adler +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile and test, type: +# ./configure; make test +# Normally configure builds both a static and a shared library. +# If you want to build just a static library, use: ./configure --static + +# To use the asm code, type: +# cp contrib/asm?86/match.S ./match.S +# make LOC=-DASMV OBJA=match.o + +# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type: +# make install +# To install in $HOME instead of /usr/local, use: +# make install prefix=$HOME + +CC=cc + +CFLAGS=-O +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-g -DZLIB_DEBUG +#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ +# -Wstrict-prototypes -Wmissing-prototypes + +SFLAGS=-O +LDFLAGS= +TEST_LDFLAGS=-L. libz.a +LDSHARED=$(CC) +CPP=$(CC) -E + +STATICLIB=libz.a +SHAREDLIB=libz.so +SHAREDLIBV=libz.so.1.2.11 +SHAREDLIBM=libz.so.1 +LIBS=$(STATICLIB) $(SHAREDLIBV) + +AR=ar +ARFLAGS=rc +RANLIB=ranlib +LDCONFIG=ldconfig +LDSHAREDLIBC=-lc +TAR=tar +SHELL=/bin/sh +EXE= + +prefix = /usr/local +exec_prefix = ${prefix} +libdir = ${exec_prefix}/lib +sharedlibdir = ${libdir} +includedir = ${prefix}/include +mandir = ${prefix}/share/man +man3dir = ${mandir}/man3 +pkgconfigdir = ${libdir}/pkgconfig +SRCDIR= +ZINC= +ZINCOUT=-I. + +OBJZ = adler32.o crc32.o deflate.o infback.o inffast.o inflate.o inftrees.o trees.o zutil.o +OBJG = compress.o uncompr.o gzclose.o gzlib.o gzread.o gzwrite.o +OBJC = $(OBJZ) $(OBJG) + +PIC_OBJZ = adler32.lo crc32.lo deflate.lo infback.lo inffast.lo inflate.lo inftrees.lo trees.lo zutil.lo +PIC_OBJG = compress.lo uncompr.lo gzclose.lo gzlib.lo gzread.lo gzwrite.lo +PIC_OBJC = $(PIC_OBJZ) $(PIC_OBJG) + +# to use the asm code: make OBJA=match.o, PIC_OBJA=match.lo +OBJA = +PIC_OBJA = + +OBJS = $(OBJC) $(OBJA) + +PIC_OBJS = $(PIC_OBJC) $(PIC_OBJA) + +all: static shared + +static: example$(EXE) minigzip$(EXE) + +shared: examplesh$(EXE) minigzipsh$(EXE) + +all64: example64$(EXE) minigzip64$(EXE) + +check: test + +test: all teststatic testshared + +teststatic: static + @TMPST=tmpst_$$; \ + if echo hello world | ./minigzip | ./minigzip -d && ./example $$TMPST ; then \ + echo ' *** zlib test OK ***'; \ + else \ + echo ' *** zlib test FAILED ***'; false; \ + fi; \ + rm -f $$TMPST + +testshared: shared + @LD_LIBRARY_PATH=`pwd`:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ + LD_LIBRARYN32_PATH=`pwd`:$(LD_LIBRARYN32_PATH) ; export LD_LIBRARYN32_PATH; \ + DYLD_LIBRARY_PATH=`pwd`:$(DYLD_LIBRARY_PATH) ; export DYLD_LIBRARY_PATH; \ + SHLIB_PATH=`pwd`:$(SHLIB_PATH) ; export SHLIB_PATH; \ + TMPSH=tmpsh_$$; \ + if echo hello world | ./minigzipsh | ./minigzipsh -d && ./examplesh $$TMPSH; then \ + echo ' *** zlib shared test OK ***'; \ + else \ + echo ' *** zlib shared test FAILED ***'; false; \ + fi; \ + rm -f $$TMPSH + +test64: all64 + @TMP64=tmp64_$$; \ + if echo hello world | ./minigzip64 | ./minigzip64 -d && ./example64 $$TMP64; then \ + echo ' *** zlib 64-bit test OK ***'; \ + else \ + echo ' *** zlib 64-bit test FAILED ***'; false; \ + fi; \ + rm -f $$TMP64 + +infcover.o: $(SRCDIR)test/infcover.c $(SRCDIR)zlib.h zconf.h + $(CC) $(CFLAGS) $(ZINCOUT) -c -o $@ $(SRCDIR)test/infcover.c + +infcover: infcover.o libz.a + $(CC) $(CFLAGS) -o $@ infcover.o libz.a + +cover: infcover + rm -f *.gcda + ./infcover + gcov inf*.c + +libz.a: $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + -@ ($(RANLIB) $@ || true) >/dev/null 2>&1 + +match.o: match.S + $(CPP) match.S > _match.s + $(CC) -c _match.s + mv _match.o match.o + rm -f _match.s + +match.lo: match.S + $(CPP) match.S > _match.s + $(CC) -c -fPIC _match.s + mv _match.o match.lo + rm -f _match.s + +example.o: $(SRCDIR)test/example.c $(SRCDIR)zlib.h zconf.h + $(CC) $(CFLAGS) $(ZINCOUT) -c -o $@ $(SRCDIR)test/example.c + +minigzip.o: $(SRCDIR)test/minigzip.c $(SRCDIR)zlib.h zconf.h + $(CC) $(CFLAGS) $(ZINCOUT) -c -o $@ $(SRCDIR)test/minigzip.c + +example64.o: $(SRCDIR)test/example.c $(SRCDIR)zlib.h zconf.h + $(CC) $(CFLAGS) $(ZINCOUT) -D_FILE_OFFSET_BITS=64 -c -o $@ $(SRCDIR)test/example.c + +minigzip64.o: $(SRCDIR)test/minigzip.c $(SRCDIR)zlib.h zconf.h + $(CC) $(CFLAGS) $(ZINCOUT) -D_FILE_OFFSET_BITS=64 -c -o $@ $(SRCDIR)test/minigzip.c + + +adler32.o: $(SRCDIR)adler32.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)adler32.c + +crc32.o: $(SRCDIR)crc32.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)crc32.c + +deflate.o: $(SRCDIR)deflate.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)deflate.c + +infback.o: $(SRCDIR)infback.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)infback.c + +inffast.o: $(SRCDIR)inffast.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)inffast.c + +inflate.o: $(SRCDIR)inflate.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)inflate.c + +inftrees.o: $(SRCDIR)inftrees.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)inftrees.c + +trees.o: $(SRCDIR)trees.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)trees.c + +zutil.o: $(SRCDIR)zutil.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)zutil.c + +compress.o: $(SRCDIR)compress.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)compress.c + +uncompr.o: $(SRCDIR)uncompr.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)uncompr.c + +gzclose.o: $(SRCDIR)gzclose.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzclose.c + +gzlib.o: $(SRCDIR)gzlib.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzlib.c + +gzread.o: $(SRCDIR)gzread.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzread.c + +gzwrite.o: $(SRCDIR)gzwrite.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzwrite.c + + +adler32.lo: $(SRCDIR)adler32.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/adler32.o $(SRCDIR)adler32.c + -@mv objs/adler32.o $@ + +crc32.lo: $(SRCDIR)crc32.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/crc32.o $(SRCDIR)crc32.c + -@mv objs/crc32.o $@ + +deflate.lo: $(SRCDIR)deflate.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/deflate.o $(SRCDIR)deflate.c + -@mv objs/deflate.o $@ + +infback.lo: $(SRCDIR)infback.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/infback.o $(SRCDIR)infback.c + -@mv objs/infback.o $@ + +inffast.lo: $(SRCDIR)inffast.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/inffast.o $(SRCDIR)inffast.c + -@mv objs/inffast.o $@ + +inflate.lo: $(SRCDIR)inflate.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/inflate.o $(SRCDIR)inflate.c + -@mv objs/inflate.o $@ + +inftrees.lo: $(SRCDIR)inftrees.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/inftrees.o $(SRCDIR)inftrees.c + -@mv objs/inftrees.o $@ + +trees.lo: $(SRCDIR)trees.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/trees.o $(SRCDIR)trees.c + -@mv objs/trees.o $@ + +zutil.lo: $(SRCDIR)zutil.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/zutil.o $(SRCDIR)zutil.c + -@mv objs/zutil.o $@ + +compress.lo: $(SRCDIR)compress.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/compress.o $(SRCDIR)compress.c + -@mv objs/compress.o $@ + +uncompr.lo: $(SRCDIR)uncompr.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/uncompr.o $(SRCDIR)uncompr.c + -@mv objs/uncompr.o $@ + +gzclose.lo: $(SRCDIR)gzclose.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzclose.o $(SRCDIR)gzclose.c + -@mv objs/gzclose.o $@ + +gzlib.lo: $(SRCDIR)gzlib.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzlib.o $(SRCDIR)gzlib.c + -@mv objs/gzlib.o $@ + +gzread.lo: $(SRCDIR)gzread.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzread.o $(SRCDIR)gzread.c + -@mv objs/gzread.o $@ + +gzwrite.lo: $(SRCDIR)gzwrite.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzwrite.o $(SRCDIR)gzwrite.c + -@mv objs/gzwrite.o $@ + + +placebo $(SHAREDLIBV): $(PIC_OBJS) libz.a + $(LDSHARED) $(SFLAGS) -o $@ $(PIC_OBJS) $(LDSHAREDLIBC) $(LDFLAGS) + rm -f $(SHAREDLIB) $(SHAREDLIBM) + ln -s $@ $(SHAREDLIB) + ln -s $@ $(SHAREDLIBM) + -@rmdir objs + +example$(EXE): example.o $(STATICLIB) + $(CC) $(CFLAGS) -o $@ example.o $(TEST_LDFLAGS) + +minigzip$(EXE): minigzip.o $(STATICLIB) + $(CC) $(CFLAGS) -o $@ minigzip.o $(TEST_LDFLAGS) + +examplesh$(EXE): example.o $(SHAREDLIBV) + $(CC) $(CFLAGS) -o $@ example.o -L. $(SHAREDLIBV) + +minigzipsh$(EXE): minigzip.o $(SHAREDLIBV) + $(CC) $(CFLAGS) -o $@ minigzip.o -L. $(SHAREDLIBV) + +example64$(EXE): example64.o $(STATICLIB) + $(CC) $(CFLAGS) -o $@ example64.o $(TEST_LDFLAGS) + +minigzip64$(EXE): minigzip64.o $(STATICLIB) + $(CC) $(CFLAGS) -o $@ minigzip64.o $(TEST_LDFLAGS) + +install-libs: $(LIBS) + -@if [ ! -d $(DESTDIR)$(exec_prefix) ]; then mkdir -p $(DESTDIR)$(exec_prefix); fi + -@if [ ! -d $(DESTDIR)$(libdir) ]; then mkdir -p $(DESTDIR)$(libdir); fi + -@if [ ! -d $(DESTDIR)$(sharedlibdir) ]; then mkdir -p $(DESTDIR)$(sharedlibdir); fi + -@if [ ! -d $(DESTDIR)$(man3dir) ]; then mkdir -p $(DESTDIR)$(man3dir); fi + -@if [ ! -d $(DESTDIR)$(pkgconfigdir) ]; then mkdir -p $(DESTDIR)$(pkgconfigdir); fi + rm -f $(DESTDIR)$(libdir)/$(STATICLIB) + cp $(STATICLIB) $(DESTDIR)$(libdir) + chmod 644 $(DESTDIR)$(libdir)/$(STATICLIB) + -@($(RANLIB) $(DESTDIR)$(libdir)/libz.a || true) >/dev/null 2>&1 + -@if test -n "$(SHAREDLIBV)"; then \ + rm -f $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV); \ + cp $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir); \ + echo "cp $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)"; \ + chmod 755 $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV); \ + echo "chmod 755 $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV)"; \ + rm -f $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM); \ + ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB); \ + ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM); \ + ($(LDCONFIG) || true) >/dev/null 2>&1; \ + fi + rm -f $(DESTDIR)$(man3dir)/zlib.3 + cp $(SRCDIR)zlib.3 $(DESTDIR)$(man3dir) + chmod 644 $(DESTDIR)$(man3dir)/zlib.3 + rm -f $(DESTDIR)$(pkgconfigdir)/zlib.pc + cp zlib.pc $(DESTDIR)$(pkgconfigdir) + chmod 644 $(DESTDIR)$(pkgconfigdir)/zlib.pc +# The ranlib in install is needed on NeXTSTEP which checks file times +# ldconfig is for Linux + +install: install-libs + -@if [ ! -d $(DESTDIR)$(includedir) ]; then mkdir -p $(DESTDIR)$(includedir); fi + rm -f $(DESTDIR)$(includedir)/zlib.h $(DESTDIR)$(includedir)/zconf.h + cp $(SRCDIR)zlib.h zconf.h $(DESTDIR)$(includedir) + chmod 644 $(DESTDIR)$(includedir)/zlib.h $(DESTDIR)$(includedir)/zconf.h + +uninstall: + cd $(DESTDIR)$(includedir) && rm -f zlib.h zconf.h + cd $(DESTDIR)$(libdir) && rm -f libz.a; \ + if test -n "$(SHAREDLIBV)" -a -f $(SHAREDLIBV); then \ + rm -f $(SHAREDLIBV) $(SHAREDLIB) $(SHAREDLIBM); \ + fi + cd $(DESTDIR)$(man3dir) && rm -f zlib.3 + cd $(DESTDIR)$(pkgconfigdir) && rm -f zlib.pc + +docs: zlib.3.pdf + +zlib.3.pdf: $(SRCDIR)zlib.3 + groff -mandoc -f H -T ps $(SRCDIR)zlib.3 | ps2pdf - $@ + +zconf.h.cmakein: $(SRCDIR)zconf.h.in + -@ TEMPFILE=zconfh_$$; \ + echo "/#define ZCONF_H/ a\\\\\n#cmakedefine Z_PREFIX\\\\\n#cmakedefine Z_HAVE_UNISTD_H\n" >> $$TEMPFILE &&\ + sed -f $$TEMPFILE $(SRCDIR)zconf.h.in > $@ &&\ + touch -r $(SRCDIR)zconf.h.in $@ &&\ + rm $$TEMPFILE + +zconf: $(SRCDIR)zconf.h.in + cp -p $(SRCDIR)zconf.h.in zconf.h + +mostlyclean: clean +clean: + rm -f *.o *.lo *~ \ + example$(EXE) minigzip$(EXE) examplesh$(EXE) minigzipsh$(EXE) \ + example64$(EXE) minigzip64$(EXE) \ + infcover \ + libz.* foo.gz so_locations \ + _match.s maketree contrib/infback9/*.o + rm -rf objs + rm -f *.gcda *.gcno *.gcov + rm -f contrib/infback9/*.gcda contrib/infback9/*.gcno contrib/infback9/*.gcov + +maintainer-clean: distclean +distclean: clean zconf zconf.h.cmakein docs + rm -f Makefile zlib.pc configure.log + -@rm -f .DS_Store + @if [ -f Makefile.in ]; then \ + printf 'all:\n\t-@echo "Please use ./configure first. Thank you."\n' > Makefile ; \ + printf '\ndistclean:\n\tmake -f Makefile.in distclean\n' >> Makefile ; \ + touch -r $(SRCDIR)Makefile.in Makefile ; fi + @if [ ! -f zconf.h.in ]; then rm -f zconf.h zconf.h.cmakein ; fi + @if [ ! -f zlib.3 ]; then rm -f zlib.3.pdf ; fi + +tags: + etags $(SRCDIR)*.[ch] + +adler32.o zutil.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h +gzclose.o gzlib.o gzread.o gzwrite.o: $(SRCDIR)zlib.h zconf.h $(SRCDIR)gzguts.h +compress.o example.o minigzip.o uncompr.o: $(SRCDIR)zlib.h zconf.h +crc32.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)crc32.h +deflate.o: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h +infback.o inflate.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h $(SRCDIR)inffixed.h +inffast.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h +inftrees.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h +trees.o: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)trees.h + +adler32.lo zutil.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h +gzclose.lo gzlib.lo gzread.lo gzwrite.lo: $(SRCDIR)zlib.h zconf.h $(SRCDIR)gzguts.h +compress.lo example.lo minigzip.lo uncompr.lo: $(SRCDIR)zlib.h zconf.h +crc32.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)crc32.h +deflate.lo: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h +infback.lo inflate.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h $(SRCDIR)inffixed.h +inffast.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h +inftrees.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h +trees.lo: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)trees.h diff --git a/dependencies/zlib-1.2.11/README b/dependencies/zlib-1.2.11/README new file mode 100644 index 0000000..51106de --- /dev/null +++ b/dependencies/zlib-1.2.11/README @@ -0,0 +1,115 @@ +ZLIB DATA COMPRESSION LIBRARY + +zlib 1.2.11 is a general purpose data compression library. All the code is +thread safe. The data format used by the zlib library is described by RFCs +(Request for Comments) 1950 to 1952 in the files +http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and +rfc1952 (gzip format). + +All functions of the compression library are documented in the file zlib.h +(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example +of the library is given in the file test/example.c which also tests that +the library is working correctly. Another example is given in the file +test/minigzip.c. The compression library itself is composed of all source +files in the root directory. + +To compile all files and run the test program, follow the instructions given at +the top of Makefile.in. In short "./configure; make test", and if that goes +well, "make install" should work for most flavors of Unix. For Windows, use +one of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use +make_vms.com. + +Questions about zlib should be sent to , or to Gilles Vollant + for the Windows DLL version. The zlib home page is +http://zlib.net/ . Before reporting a problem, please check this site to +verify that you have the latest version of zlib; otherwise get the latest +version and check whether the problem still exists or not. + +PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help. + +Mark Nelson wrote an article about zlib for the Jan. 1997 +issue of Dr. Dobb's Journal; a copy of the article is available at +http://marknelson.us/1997/01/01/zlib-engine/ . + +The changes made in version 1.2.11 are documented in the file ChangeLog. + +Unsupported third party contributions are provided in directory contrib/ . + +zlib is available in Java using the java.util.zip package, documented at +http://java.sun.com/developer/technicalArticles/Programming/compression/ . + +A Perl interface to zlib written by Paul Marquess is available +at CPAN (Comprehensive Perl Archive Network) sites, including +http://search.cpan.org/~pmqs/IO-Compress-Zlib/ . + +A Python interface to zlib written by A.M. Kuchling is +available in Python 1.5 and later versions, see +http://docs.python.org/library/zlib.html . + +zlib is built into tcl: http://wiki.tcl.tk/4610 . + +An experimental package to read and write files in .zip format, written on top +of zlib by Gilles Vollant , is available in the +contrib/minizip directory of zlib. + + +Notes for some targets: + +- For Windows DLL versions, please see win32/DLL_FAQ.txt + +- For 64-bit Irix, deflate.c must be compiled without any optimization. With + -O, one libpng test fails. The test works in 32 bit mode (with the -n32 + compiler flag). The compiler bug has been reported to SGI. + +- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works + when compiled with cc. + +- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is + necessary to get gzprintf working correctly. This is done by configure. + +- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with + other compilers. Use "make test" to check your compiler. + +- gzdopen is not supported on RISCOS or BEOS. + +- For PalmOs, see http://palmzlib.sourceforge.net/ + + +Acknowledgments: + + The deflate format used by zlib was defined by Phil Katz. The deflate and + zlib specifications were written by L. Peter Deutsch. Thanks to all the + people who reported problems and suggested various improvements in zlib; they + are too numerous to cite here. + +Copyright notice: + + (C) 1995-2017 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* receiving +lengthy legal documents to sign. The sources are provided for free but without +warranty of any kind. The library has been entirely written by Jean-loup +Gailly and Mark Adler; it does not include third-party code. + +If you redistribute modified sources, we would appreciate that you include in +the file ChangeLog history information documenting your changes. Please read +the FAQ for more information on the distribution of modified source versions. diff --git a/dependencies/zlib-1.2.11/adler32.c b/dependencies/zlib-1.2.11/adler32.c new file mode 100644 index 0000000..d0be438 --- /dev/null +++ b/dependencies/zlib-1.2.11/adler32.c @@ -0,0 +1,186 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2011, 2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); + +#define BASE 65521U /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* use NO_DIVIDE if your processor does not do division in hardware -- + try it both ways to see which is faster */ +#ifdef NO_DIVIDE +/* note that this assumes BASE is 65521, where 65536 % 65521 == 15 + (thank you to John Reiser for pointing this out) */ +# define CHOP(a) \ + do { \ + unsigned long tmp = a >> 16; \ + a &= 0xffffUL; \ + a += (tmp << 4) - tmp; \ + } while (0) +# define MOD28(a) \ + do { \ + CHOP(a); \ + if (a >= BASE) a -= BASE; \ + } while (0) +# define MOD(a) \ + do { \ + CHOP(a); \ + MOD28(a); \ + } while (0) +# define MOD63(a) \ + do { /* this assumes a is not negative */ \ + z_off64_t tmp = a >> 32; \ + a &= 0xffffffffL; \ + a += (tmp << 8) - (tmp << 5) + tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +# define MOD28(a) a %= BASE +# define MOD63(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32_z(adler, buf, len) + uLong adler; + const Bytef *buf; + z_size_t len; +{ + unsigned long sum2; + unsigned n; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD28(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; + DO16(buf); + buf += 16; + } + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); + } + + /* return recombined sums */ + return adler | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + return adler32_z(adler, buf, len); +} + +/* ========================================================================= */ +local uLong adler32_combine_(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* for negative len, return invalid adler32 as a clue for debugging */ + if (len2 < 0) + return 0xffffffffUL; + + /* the derivation of this formula is left as an exercise for the reader */ + MOD63(len2); /* assumes len2 >= 0 */ + rem = (unsigned)len2; + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 >= BASE) sum1 -= BASE; + if (sum1 >= BASE) sum1 -= BASE; + if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1); + if (sum2 >= BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} + +uLong ZEXPORT adler32_combine64(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} diff --git a/dependencies/zlib-1.2.11/amiga/Makefile.pup b/dependencies/zlib-1.2.11/amiga/Makefile.pup new file mode 100644 index 0000000..8940c12 --- /dev/null +++ b/dependencies/zlib-1.2.11/amiga/Makefile.pup @@ -0,0 +1,69 @@ +# Amiga powerUP (TM) Makefile +# makefile for libpng and SAS C V6.58/7.00 PPC compiler +# Copyright (C) 1998 by Andreas R. Kleinert + +LIBNAME = libzip.a + +CC = scppc +CFLAGS = NOSTKCHK NOSINT OPTIMIZE OPTGO OPTPEEP OPTINLOCAL OPTINL \ + OPTLOOP OPTRDEP=8 OPTDEP=8 OPTCOMP=8 NOVER +AR = ppc-amigaos-ar cr +RANLIB = ppc-amigaos-ranlib +LD = ppc-amigaos-ld -r +LDFLAGS = -o +LDLIBS = LIB:scppc.a LIB:end.o +RM = delete quiet + +OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \ + uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o + +TEST_OBJS = example.o minigzip.o + +all: example minigzip + +check: test +test: all + example + echo hello world | minigzip | minigzip -d + +$(LIBNAME): $(OBJS) + $(AR) $@ $(OBJS) + -$(RANLIB) $@ + +example: example.o $(LIBNAME) + $(LD) $(LDFLAGS) $@ LIB:c_ppc.o $@.o $(LIBNAME) $(LDLIBS) + +minigzip: minigzip.o $(LIBNAME) + $(LD) $(LDFLAGS) $@ LIB:c_ppc.o $@.o $(LIBNAME) $(LDLIBS) + +mostlyclean: clean +clean: + $(RM) *.o example minigzip $(LIBNAME) foo.gz + +zip: + zip -ul9 zlib README ChangeLog Makefile Make????.??? Makefile.?? \ + descrip.mms *.[ch] + +tgz: + cd ..; tar cfz zlib/zlib.tgz zlib/README zlib/ChangeLog zlib/Makefile \ + zlib/Make????.??? zlib/Makefile.?? zlib/descrip.mms zlib/*.[ch] + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +adler32.o: zlib.h zconf.h +compress.o: zlib.h zconf.h +crc32.o: crc32.h zlib.h zconf.h +deflate.o: deflate.h zutil.h zlib.h zconf.h +example.o: zlib.h zconf.h +gzclose.o: zlib.h zconf.h gzguts.h +gzlib.o: zlib.h zconf.h gzguts.h +gzread.o: zlib.h zconf.h gzguts.h +gzwrite.o: zlib.h zconf.h gzguts.h +inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h +inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h +infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h +inftrees.o: zutil.h zlib.h zconf.h inftrees.h +minigzip.o: zlib.h zconf.h +trees.o: deflate.h zutil.h zlib.h zconf.h trees.h +uncompr.o: zlib.h zconf.h +zutil.o: zutil.h zlib.h zconf.h diff --git a/dependencies/zlib-1.2.11/amiga/Makefile.sas b/dependencies/zlib-1.2.11/amiga/Makefile.sas new file mode 100644 index 0000000..749e291 --- /dev/null +++ b/dependencies/zlib-1.2.11/amiga/Makefile.sas @@ -0,0 +1,68 @@ +# SMakefile for zlib +# Modified from the standard UNIX Makefile Copyright Jean-loup Gailly +# Osma Ahvenlampi +# Amiga, SAS/C 6.56 & Smake + +CC=sc +CFLAGS=OPT +#CFLAGS=OPT CPU=68030 +#CFLAGS=DEBUG=LINE +LDFLAGS=LIB z.lib + +SCOPTIONS=OPTSCHED OPTINLINE OPTALIAS OPTTIME OPTINLOCAL STRMERGE \ + NOICONS PARMS=BOTH NOSTACKCHECK UTILLIB NOVERSION ERRORREXX \ + DEF=POSTINC + +OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \ + uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o + +TEST_OBJS = example.o minigzip.o + +all: SCOPTIONS example minigzip + +check: test +test: all + example + echo hello world | minigzip | minigzip -d + +install: z.lib + copy clone zlib.h zconf.h INCLUDE: + copy clone z.lib LIB: + +z.lib: $(OBJS) + oml z.lib r $(OBJS) + +example: example.o z.lib + $(CC) $(CFLAGS) LINK TO $@ example.o $(LDFLAGS) + +minigzip: minigzip.o z.lib + $(CC) $(CFLAGS) LINK TO $@ minigzip.o $(LDFLAGS) + +mostlyclean: clean +clean: + -delete force quiet example minigzip *.o z.lib foo.gz *.lnk SCOPTIONS + +SCOPTIONS: Makefile.sas + copy to $@ (uLong)max ? max : (uInt)left; + left -= stream.avail_out; + } + if (stream.avail_in == 0) { + stream.avail_in = sourceLen > (uLong)max ? max : (uInt)sourceLen; + sourceLen -= stream.avail_in; + } + err = deflate(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH); + } while (err == Z_OK); + + *destLen = stream.total_out; + deflateEnd(&stream); + return err == Z_STREAM_END ? Z_OK : err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +uLong ZEXPORT compressBound (sourceLen) + uLong sourceLen; +{ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + + (sourceLen >> 25) + 13; +} diff --git a/dependencies/zlib-1.2.11/configure b/dependencies/zlib-1.2.11/configure new file mode 100644 index 0000000..e974d1f --- /dev/null +++ b/dependencies/zlib-1.2.11/configure @@ -0,0 +1,921 @@ +#!/bin/sh +# configure script for zlib. +# +# Normally configure builds both a static and a shared library. +# If you want to build just a static library, use: ./configure --static +# +# To impose specific compiler or flags or install directory, use for example: +# prefix=$HOME CC=cc CFLAGS="-O4" ./configure +# or for csh/tcsh users: +# (setenv prefix $HOME; setenv CC cc; setenv CFLAGS "-O4"; ./configure) + +# Incorrect settings of CC or CFLAGS may prevent creating a shared library. +# If you have problems, try without defining CC and CFLAGS before reporting +# an error. + +# start off configure.log +echo -------------------- >> configure.log +echo $0 $* >> configure.log +date >> configure.log + +# get source directory +SRCDIR=`dirname $0` +if test $SRCDIR = "."; then + ZINC="" + ZINCOUT="-I." + SRCDIR="" +else + ZINC='-include zconf.h' + ZINCOUT='-I. -I$(SRCDIR)' + SRCDIR="$SRCDIR/" +fi + +# set command prefix for cross-compilation +if [ -n "${CHOST}" ]; then + uname="`echo "${CHOST}" | sed -e 's/^[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)-.*$/\1/'`" + CROSS_PREFIX="${CHOST}-" +fi + +# destination name for static library +STATICLIB=libz.a + +# extract zlib version numbers from zlib.h +VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < ${SRCDIR}zlib.h` +VER3=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\\.[0-9]*\).*/\1/p' < ${SRCDIR}zlib.h` +VER2=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\)\\..*/\1/p' < ${SRCDIR}zlib.h` +VER1=`sed -n -e '/VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < ${SRCDIR}zlib.h` + +# establish commands for library building +if "${CROSS_PREFIX}ar" --version >/dev/null 2>/dev/null || test $? -lt 126; then + AR=${AR-"${CROSS_PREFIX}ar"} + test -n "${CROSS_PREFIX}" && echo Using ${AR} | tee -a configure.log +else + AR=${AR-"ar"} + test -n "${CROSS_PREFIX}" && echo Using ${AR} | tee -a configure.log +fi +ARFLAGS=${ARFLAGS-"rc"} +if "${CROSS_PREFIX}ranlib" --version >/dev/null 2>/dev/null || test $? -lt 126; then + RANLIB=${RANLIB-"${CROSS_PREFIX}ranlib"} + test -n "${CROSS_PREFIX}" && echo Using ${RANLIB} | tee -a configure.log +else + RANLIB=${RANLIB-"ranlib"} +fi +if "${CROSS_PREFIX}nm" --version >/dev/null 2>/dev/null || test $? -lt 126; then + NM=${NM-"${CROSS_PREFIX}nm"} + test -n "${CROSS_PREFIX}" && echo Using ${NM} | tee -a configure.log +else + NM=${NM-"nm"} +fi + +# set defaults before processing command line options +LDCONFIG=${LDCONFIG-"ldconfig"} +LDSHAREDLIBC="${LDSHAREDLIBC--lc}" +ARCHS= +prefix=${prefix-/usr/local} +exec_prefix=${exec_prefix-'${prefix}'} +libdir=${libdir-'${exec_prefix}/lib'} +sharedlibdir=${sharedlibdir-'${libdir}'} +includedir=${includedir-'${prefix}/include'} +mandir=${mandir-'${prefix}/share/man'} +shared_ext='.so' +shared=1 +solo=0 +cover=0 +zprefix=0 +zconst=0 +build64=0 +gcc=0 +warn=0 +debug=0 +old_cc="$CC" +old_cflags="$CFLAGS" +OBJC='$(OBJZ) $(OBJG)' +PIC_OBJC='$(PIC_OBJZ) $(PIC_OBJG)' + +# leave this script, optionally in a bad way +leave() +{ + if test "$*" != "0"; then + echo "** $0 aborting." | tee -a configure.log + fi + rm -f $test.[co] $test $test$shared_ext $test.gcno ./--version + echo -------------------- >> configure.log + echo >> configure.log + echo >> configure.log + exit $1 +} + +# process command line options +while test $# -ge 1 +do +case "$1" in + -h* | --help) + echo 'usage:' | tee -a configure.log + echo ' configure [--const] [--zprefix] [--prefix=PREFIX] [--eprefix=EXPREFIX]' | tee -a configure.log + echo ' [--static] [--64] [--libdir=LIBDIR] [--sharedlibdir=LIBDIR]' | tee -a configure.log + echo ' [--includedir=INCLUDEDIR] [--archs="-arch i386 -arch x86_64"]' | tee -a configure.log + exit 0 ;; + -p*=* | --prefix=*) prefix=`echo $1 | sed 's/.*=//'`; shift ;; + -e*=* | --eprefix=*) exec_prefix=`echo $1 | sed 's/.*=//'`; shift ;; + -l*=* | --libdir=*) libdir=`echo $1 | sed 's/.*=//'`; shift ;; + --sharedlibdir=*) sharedlibdir=`echo $1 | sed 's/.*=//'`; shift ;; + -i*=* | --includedir=*) includedir=`echo $1 | sed 's/.*=//'`;shift ;; + -u*=* | --uname=*) uname=`echo $1 | sed 's/.*=//'`;shift ;; + -p* | --prefix) prefix="$2"; shift; shift ;; + -e* | --eprefix) exec_prefix="$2"; shift; shift ;; + -l* | --libdir) libdir="$2"; shift; shift ;; + -i* | --includedir) includedir="$2"; shift; shift ;; + -s* | --shared | --enable-shared) shared=1; shift ;; + -t | --static) shared=0; shift ;; + --solo) solo=1; shift ;; + --cover) cover=1; shift ;; + -z* | --zprefix) zprefix=1; shift ;; + -6* | --64) build64=1; shift ;; + -a*=* | --archs=*) ARCHS=`echo $1 | sed 's/.*=//'`; shift ;; + --sysconfdir=*) echo "ignored option: --sysconfdir" | tee -a configure.log; shift ;; + --localstatedir=*) echo "ignored option: --localstatedir" | tee -a configure.log; shift ;; + -c* | --const) zconst=1; shift ;; + -w* | --warn) warn=1; shift ;; + -d* | --debug) debug=1; shift ;; + *) + echo "unknown option: $1" | tee -a configure.log + echo "$0 --help for help" | tee -a configure.log + leave 1;; + esac +done + +# temporary file name +test=ztest$$ + +# put arguments in log, also put test file in log if used in arguments +show() +{ + case "$*" in + *$test.c*) + echo === $test.c === >> configure.log + cat $test.c >> configure.log + echo === >> configure.log;; + esac + echo $* >> configure.log +} + +# check for gcc vs. cc and set compile and link flags based on the system identified by uname +cat > $test.c <&1` in + *gcc*) gcc=1 ;; + *clang*) gcc=1 ;; +esac + +show $cc -c $test.c +if test "$gcc" -eq 1 && ($cc -c $test.c) >> configure.log 2>&1; then + echo ... using gcc >> configure.log + CC="$cc" + CFLAGS="${CFLAGS--O3}" + SFLAGS="${CFLAGS--O3} -fPIC" + if test "$ARCHS"; then + CFLAGS="${CFLAGS} ${ARCHS}" + LDFLAGS="${LDFLAGS} ${ARCHS}" + fi + if test $build64 -eq 1; then + CFLAGS="${CFLAGS} -m64" + SFLAGS="${SFLAGS} -m64" + fi + if test "$warn" -eq 1; then + if test "$zconst" -eq 1; then + CFLAGS="${CFLAGS} -Wall -Wextra -Wcast-qual -pedantic -DZLIB_CONST" + else + CFLAGS="${CFLAGS} -Wall -Wextra -pedantic" + fi + fi + if test $debug -eq 1; then + CFLAGS="${CFLAGS} -DZLIB_DEBUG" + SFLAGS="${SFLAGS} -DZLIB_DEBUG" + fi + if test -z "$uname"; then + uname=`(uname -s || echo unknown) 2>/dev/null` + fi + case "$uname" in + Linux* | linux* | GNU | GNU/* | solaris*) + LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,${SRCDIR}zlib.map"} ;; + *BSD | *bsd* | DragonFly) + LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,${SRCDIR}zlib.map"} + LDCONFIG="ldconfig -m" ;; + CYGWIN* | Cygwin* | cygwin* | OS/2*) + EXE='.exe' ;; + MINGW* | mingw*) +# temporary bypass + rm -f $test.[co] $test $test$shared_ext + echo "Please use win32/Makefile.gcc instead." | tee -a configure.log + leave 1 + LDSHARED=${LDSHARED-"$cc -shared"} + LDSHAREDLIBC="" + EXE='.exe' ;; + QNX*) # This is for QNX6. I suppose that the QNX rule below is for QNX2,QNX4 + # (alain.bonnefoy@icbt.com) + LDSHARED=${LDSHARED-"$cc -shared -Wl,-hlibz.so.1"} ;; + HP-UX*) + LDSHARED=${LDSHARED-"$cc -shared $SFLAGS"} + case `(uname -m || echo unknown) 2>/dev/null` in + ia64) + shared_ext='.so' + SHAREDLIB='libz.so' ;; + *) + shared_ext='.sl' + SHAREDLIB='libz.sl' ;; + esac ;; + Darwin* | darwin*) + shared_ext='.dylib' + SHAREDLIB=libz$shared_ext + SHAREDLIBV=libz.$VER$shared_ext + SHAREDLIBM=libz.$VER1$shared_ext + LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER3"} + if libtool -V 2>&1 | grep Apple > /dev/null; then + AR="libtool" + else + AR="/usr/bin/libtool" + fi + ARFLAGS="-o" ;; + *) LDSHARED=${LDSHARED-"$cc -shared"} ;; + esac +else + # find system name and corresponding cc options + CC=${CC-cc} + gcc=0 + echo ... using $CC >> configure.log + if test -z "$uname"; then + uname=`(uname -sr || echo unknown) 2>/dev/null` + fi + case "$uname" in + HP-UX*) SFLAGS=${CFLAGS-"-O +z"} + CFLAGS=${CFLAGS-"-O"} +# LDSHARED=${LDSHARED-"ld -b +vnocompatwarnings"} + LDSHARED=${LDSHARED-"ld -b"} + case `(uname -m || echo unknown) 2>/dev/null` in + ia64) + shared_ext='.so' + SHAREDLIB='libz.so' ;; + *) + shared_ext='.sl' + SHAREDLIB='libz.sl' ;; + esac ;; + IRIX*) SFLAGS=${CFLAGS-"-ansi -O2 -rpath ."} + CFLAGS=${CFLAGS-"-ansi -O2"} + LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so.1"} ;; + OSF1\ V4*) SFLAGS=${CFLAGS-"-O -std1"} + CFLAGS=${CFLAGS-"-O -std1"} + LDFLAGS="${LDFLAGS} -Wl,-rpath,." + LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so -Wl,-msym -Wl,-rpath,$(libdir) -Wl,-set_version,${VER}:1.0"} ;; + OSF1*) SFLAGS=${CFLAGS-"-O -std1"} + CFLAGS=${CFLAGS-"-O -std1"} + LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so.1"} ;; + QNX*) SFLAGS=${CFLAGS-"-4 -O"} + CFLAGS=${CFLAGS-"-4 -O"} + LDSHARED=${LDSHARED-"cc"} + RANLIB=${RANLIB-"true"} + AR="cc" + ARFLAGS="-A" ;; + SCO_SV\ 3.2*) SFLAGS=${CFLAGS-"-O3 -dy -KPIC "} + CFLAGS=${CFLAGS-"-O3"} + LDSHARED=${LDSHARED-"cc -dy -KPIC -G"} ;; + SunOS\ 5* | solaris*) + LDSHARED=${LDSHARED-"cc -G -h libz$shared_ext.$VER1"} + SFLAGS=${CFLAGS-"-fast -KPIC"} + CFLAGS=${CFLAGS-"-fast"} + if test $build64 -eq 1; then + # old versions of SunPRO/Workshop/Studio don't support -m64, + # but newer ones do. Check for it. + flag64=`$CC -flags | egrep -- '^-m64'` + if test x"$flag64" != x"" ; then + CFLAGS="${CFLAGS} -m64" + SFLAGS="${SFLAGS} -m64" + else + case `(uname -m || echo unknown) 2>/dev/null` in + i86*) + SFLAGS="$SFLAGS -xarch=amd64" + CFLAGS="$CFLAGS -xarch=amd64" ;; + *) + SFLAGS="$SFLAGS -xarch=v9" + CFLAGS="$CFLAGS -xarch=v9" ;; + esac + fi + fi + if test -n "$ZINC"; then + ZINC='-I- -I. -I$(SRCDIR)' + fi + ;; + SunOS\ 4*) SFLAGS=${CFLAGS-"-O2 -PIC"} + CFLAGS=${CFLAGS-"-O2"} + LDSHARED=${LDSHARED-"ld"} ;; + SunStudio\ 9*) SFLAGS=${CFLAGS-"-fast -xcode=pic32 -xtarget=ultra3 -xarch=v9b"} + CFLAGS=${CFLAGS-"-fast -xtarget=ultra3 -xarch=v9b"} + LDSHARED=${LDSHARED-"cc -xarch=v9b"} ;; + UNIX_System_V\ 4.2.0) + SFLAGS=${CFLAGS-"-KPIC -O"} + CFLAGS=${CFLAGS-"-O"} + LDSHARED=${LDSHARED-"cc -G"} ;; + UNIX_SV\ 4.2MP) + SFLAGS=${CFLAGS-"-Kconform_pic -O"} + CFLAGS=${CFLAGS-"-O"} + LDSHARED=${LDSHARED-"cc -G"} ;; + OpenUNIX\ 5) + SFLAGS=${CFLAGS-"-KPIC -O"} + CFLAGS=${CFLAGS-"-O"} + LDSHARED=${LDSHARED-"cc -G"} ;; + AIX*) # Courtesy of dbakker@arrayasolutions.com + SFLAGS=${CFLAGS-"-O -qmaxmem=8192"} + CFLAGS=${CFLAGS-"-O -qmaxmem=8192"} + LDSHARED=${LDSHARED-"xlc -G"} ;; + # send working options for other systems to zlib@gzip.org + *) SFLAGS=${CFLAGS-"-O"} + CFLAGS=${CFLAGS-"-O"} + LDSHARED=${LDSHARED-"cc -shared"} ;; + esac +fi + +# destination names for shared library if not defined above +SHAREDLIB=${SHAREDLIB-"libz$shared_ext"} +SHAREDLIBV=${SHAREDLIBV-"libz$shared_ext.$VER"} +SHAREDLIBM=${SHAREDLIBM-"libz$shared_ext.$VER1"} + +echo >> configure.log + +# define functions for testing compiler and library characteristics and logging the results + +cat > $test.c </dev/null; then + try() + { + show $* + test "`( $* ) 2>&1 | tee -a configure.log`" = "" + } + echo - using any output from compiler to indicate an error >> configure.log +else + try() + { + show $* + ( $* ) >> configure.log 2>&1 + ret=$? + if test $ret -ne 0; then + echo "(exit code "$ret")" >> configure.log + fi + return $ret + } +fi + +tryboth() +{ + show $* + got=`( $* ) 2>&1` + ret=$? + printf %s "$got" >> configure.log + if test $ret -ne 0; then + return $ret + fi + test "$got" = "" +} + +cat > $test.c << EOF +int foo() { return 0; } +EOF +echo "Checking for obsessive-compulsive compiler options..." >> configure.log +if try $CC -c $CFLAGS $test.c; then + : +else + echo "Compiler error reporting is too harsh for $0 (perhaps remove -Werror)." | tee -a configure.log + leave 1 +fi + +echo >> configure.log + +# see if shared library build supported +cat > $test.c <> configure.log + show "$NM $test.o | grep _hello" + if test "`$NM $test.o | grep _hello | tee -a configure.log`" = ""; then + CPP="$CPP -DNO_UNDERLINE" + echo Checking for underline in external names... No. | tee -a configure.log + else + echo Checking for underline in external names... Yes. | tee -a configure.log + fi ;; +esac + +echo >> configure.log + +# check for size_t +cat > $test.c < +#include +size_t dummy = 0; +EOF +if try $CC -c $CFLAGS $test.c; then + echo "Checking for size_t... Yes." | tee -a configure.log + need_sizet=0 +else + echo "Checking for size_t... No." | tee -a configure.log + need_sizet=1 +fi + +echo >> configure.log + +# find the size_t integer type, if needed +if test $need_sizet -eq 1; then + cat > $test.c < $test.c < +int main(void) { + if (sizeof(void *) <= sizeof(int)) puts("int"); + else if (sizeof(void *) <= sizeof(long)) puts("long"); + else puts("z_longlong"); + return 0; +} +EOF + else + echo "Checking for long long... No." | tee -a configure.log + cat > $test.c < +int main(void) { + if (sizeof(void *) <= sizeof(int)) puts("int"); + else puts("long"); + return 0; +} +EOF + fi + if try $CC $CFLAGS -o $test $test.c; then + sizet=`./$test` + echo "Checking for a pointer-size integer type..." $sizet"." | tee -a configure.log + else + echo "Failed to find a pointer-size integer type." | tee -a configure.log + leave 1 + fi +fi + +if test $need_sizet -eq 1; then + CFLAGS="${CFLAGS} -DNO_SIZE_T=${sizet}" + SFLAGS="${SFLAGS} -DNO_SIZE_T=${sizet}" +fi + +echo >> configure.log + +# check for large file support, and if none, check for fseeko() +cat > $test.c < +off64_t dummy = 0; +EOF +if try $CC -c $CFLAGS -D_LARGEFILE64_SOURCE=1 $test.c; then + CFLAGS="${CFLAGS} -D_LARGEFILE64_SOURCE=1" + SFLAGS="${SFLAGS} -D_LARGEFILE64_SOURCE=1" + ALL="${ALL} all64" + TEST="${TEST} test64" + echo "Checking for off64_t... Yes." | tee -a configure.log + echo "Checking for fseeko... Yes." | tee -a configure.log +else + echo "Checking for off64_t... No." | tee -a configure.log + echo >> configure.log + cat > $test.c < +int main(void) { + fseeko(NULL, 0, 0); + return 0; +} +EOF + if try $CC $CFLAGS -o $test $test.c; then + echo "Checking for fseeko... Yes." | tee -a configure.log + else + CFLAGS="${CFLAGS} -DNO_FSEEKO" + SFLAGS="${SFLAGS} -DNO_FSEEKO" + echo "Checking for fseeko... No." | tee -a configure.log + fi +fi + +echo >> configure.log + +# check for strerror() for use by gz* functions +cat > $test.c < +#include +int main() { return strlen(strerror(errno)); } +EOF +if try $CC $CFLAGS -o $test $test.c; then + echo "Checking for strerror... Yes." | tee -a configure.log +else + CFLAGS="${CFLAGS} -DNO_STRERROR" + SFLAGS="${SFLAGS} -DNO_STRERROR" + echo "Checking for strerror... No." | tee -a configure.log +fi + +# copy clean zconf.h for subsequent edits +cp -p ${SRCDIR}zconf.h.in zconf.h + +echo >> configure.log + +# check for unistd.h and save result in zconf.h +cat > $test.c < +int main() { return 0; } +EOF +if try $CC -c $CFLAGS $test.c; then + sed < zconf.h "/^#ifdef HAVE_UNISTD_H.* may be/s/def HAVE_UNISTD_H\(.*\) may be/ 1\1 was/" > zconf.temp.h + mv zconf.temp.h zconf.h + echo "Checking for unistd.h... Yes." | tee -a configure.log +else + echo "Checking for unistd.h... No." | tee -a configure.log +fi + +echo >> configure.log + +# check for stdarg.h and save result in zconf.h +cat > $test.c < +int main() { return 0; } +EOF +if try $CC -c $CFLAGS $test.c; then + sed < zconf.h "/^#ifdef HAVE_STDARG_H.* may be/s/def HAVE_STDARG_H\(.*\) may be/ 1\1 was/" > zconf.temp.h + mv zconf.temp.h zconf.h + echo "Checking for stdarg.h... Yes." | tee -a configure.log +else + echo "Checking for stdarg.h... No." | tee -a configure.log +fi + +# if the z_ prefix was requested, save that in zconf.h +if test $zprefix -eq 1; then + sed < zconf.h "/#ifdef Z_PREFIX.* may be/s/def Z_PREFIX\(.*\) may be/ 1\1 was/" > zconf.temp.h + mv zconf.temp.h zconf.h + echo >> configure.log + echo "Using z_ prefix on all symbols." | tee -a configure.log +fi + +# if --solo compilation was requested, save that in zconf.h and remove gz stuff from object lists +if test $solo -eq 1; then + sed '/#define ZCONF_H/a\ +#define Z_SOLO + +' < zconf.h > zconf.temp.h + mv zconf.temp.h zconf.h +OBJC='$(OBJZ)' +PIC_OBJC='$(PIC_OBJZ)' +fi + +# if code coverage testing was requested, use older gcc if defined, e.g. "gcc-4.2" on Mac OS X +if test $cover -eq 1; then + CFLAGS="${CFLAGS} -fprofile-arcs -ftest-coverage" + if test -n "$GCC_CLASSIC"; then + CC=$GCC_CLASSIC + fi +fi + +echo >> configure.log + +# conduct a series of tests to resolve eight possible cases of using "vs" or "s" printf functions +# (using stdarg or not), with or without "n" (proving size of buffer), and with or without a +# return value. The most secure result is vsnprintf() with a return value. snprintf() with a +# return value is secure as well, but then gzprintf() will be limited to 20 arguments. +cat > $test.c < +#include +#include "zconf.h" +int main() +{ +#ifndef STDC + choke me +#endif + return 0; +} +EOF +if try $CC -c $CFLAGS $test.c; then + echo "Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf()." | tee -a configure.log + + echo >> configure.log + cat > $test.c < +#include +int mytest(const char *fmt, ...) +{ + char buf[20]; + va_list ap; + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + return 0; +} +int main() +{ + return (mytest("Hello%d\n", 1)); +} +EOF + if try $CC $CFLAGS -o $test $test.c; then + echo "Checking for vsnprintf() in stdio.h... Yes." | tee -a configure.log + + echo >> configure.log + cat >$test.c < +#include +int mytest(const char *fmt, ...) +{ + int n; + char buf[20]; + va_list ap; + va_start(ap, fmt); + n = vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + return n; +} +int main() +{ + return (mytest("Hello%d\n", 1)); +} +EOF + + if try $CC -c $CFLAGS $test.c; then + echo "Checking for return value of vsnprintf()... Yes." | tee -a configure.log + else + CFLAGS="$CFLAGS -DHAS_vsnprintf_void" + SFLAGS="$SFLAGS -DHAS_vsnprintf_void" + echo "Checking for return value of vsnprintf()... No." | tee -a configure.log + echo " WARNING: apparently vsnprintf() does not return a value. zlib" | tee -a configure.log + echo " can build but will be open to possible string-format security" | tee -a configure.log + echo " vulnerabilities." | tee -a configure.log + fi + else + CFLAGS="$CFLAGS -DNO_vsnprintf" + SFLAGS="$SFLAGS -DNO_vsnprintf" + echo "Checking for vsnprintf() in stdio.h... No." | tee -a configure.log + echo " WARNING: vsnprintf() not found, falling back to vsprintf(). zlib" | tee -a configure.log + echo " can build but will be open to possible buffer-overflow security" | tee -a configure.log + echo " vulnerabilities." | tee -a configure.log + + echo >> configure.log + cat >$test.c < +#include +int mytest(const char *fmt, ...) +{ + int n; + char buf[20]; + va_list ap; + va_start(ap, fmt); + n = vsprintf(buf, fmt, ap); + va_end(ap); + return n; +} +int main() +{ + return (mytest("Hello%d\n", 1)); +} +EOF + + if try $CC -c $CFLAGS $test.c; then + echo "Checking for return value of vsprintf()... Yes." | tee -a configure.log + else + CFLAGS="$CFLAGS -DHAS_vsprintf_void" + SFLAGS="$SFLAGS -DHAS_vsprintf_void" + echo "Checking for return value of vsprintf()... No." | tee -a configure.log + echo " WARNING: apparently vsprintf() does not return a value. zlib" | tee -a configure.log + echo " can build but will be open to possible string-format security" | tee -a configure.log + echo " vulnerabilities." | tee -a configure.log + fi + fi +else + echo "Checking whether to use vs[n]printf() or s[n]printf()... using s[n]printf()." | tee -a configure.log + + echo >> configure.log + cat >$test.c < +int mytest() +{ + char buf[20]; + snprintf(buf, sizeof(buf), "%s", "foo"); + return 0; +} +int main() +{ + return (mytest()); +} +EOF + + if try $CC $CFLAGS -o $test $test.c; then + echo "Checking for snprintf() in stdio.h... Yes." | tee -a configure.log + + echo >> configure.log + cat >$test.c < +int mytest() +{ + char buf[20]; + return snprintf(buf, sizeof(buf), "%s", "foo"); +} +int main() +{ + return (mytest()); +} +EOF + + if try $CC -c $CFLAGS $test.c; then + echo "Checking for return value of snprintf()... Yes." | tee -a configure.log + else + CFLAGS="$CFLAGS -DHAS_snprintf_void" + SFLAGS="$SFLAGS -DHAS_snprintf_void" + echo "Checking for return value of snprintf()... No." | tee -a configure.log + echo " WARNING: apparently snprintf() does not return a value. zlib" | tee -a configure.log + echo " can build but will be open to possible string-format security" | tee -a configure.log + echo " vulnerabilities." | tee -a configure.log + fi + else + CFLAGS="$CFLAGS -DNO_snprintf" + SFLAGS="$SFLAGS -DNO_snprintf" + echo "Checking for snprintf() in stdio.h... No." | tee -a configure.log + echo " WARNING: snprintf() not found, falling back to sprintf(). zlib" | tee -a configure.log + echo " can build but will be open to possible buffer-overflow security" | tee -a configure.log + echo " vulnerabilities." | tee -a configure.log + + echo >> configure.log + cat >$test.c < +int mytest() +{ + char buf[20]; + return sprintf(buf, "%s", "foo"); +} +int main() +{ + return (mytest()); +} +EOF + + if try $CC -c $CFLAGS $test.c; then + echo "Checking for return value of sprintf()... Yes." | tee -a configure.log + else + CFLAGS="$CFLAGS -DHAS_sprintf_void" + SFLAGS="$SFLAGS -DHAS_sprintf_void" + echo "Checking for return value of sprintf()... No." | tee -a configure.log + echo " WARNING: apparently sprintf() does not return a value. zlib" | tee -a configure.log + echo " can build but will be open to possible string-format security" | tee -a configure.log + echo " vulnerabilities." | tee -a configure.log + fi + fi +fi + +# see if we can hide zlib internal symbols that are linked between separate source files +if test "$gcc" -eq 1; then + echo >> configure.log + cat > $test.c <> configure.log +echo ALL = $ALL >> configure.log +echo AR = $AR >> configure.log +echo ARFLAGS = $ARFLAGS >> configure.log +echo CC = $CC >> configure.log +echo CFLAGS = $CFLAGS >> configure.log +echo CPP = $CPP >> configure.log +echo EXE = $EXE >> configure.log +echo LDCONFIG = $LDCONFIG >> configure.log +echo LDFLAGS = $LDFLAGS >> configure.log +echo LDSHARED = $LDSHARED >> configure.log +echo LDSHAREDLIBC = $LDSHAREDLIBC >> configure.log +echo OBJC = $OBJC >> configure.log +echo PIC_OBJC = $PIC_OBJC >> configure.log +echo RANLIB = $RANLIB >> configure.log +echo SFLAGS = $SFLAGS >> configure.log +echo SHAREDLIB = $SHAREDLIB >> configure.log +echo SHAREDLIBM = $SHAREDLIBM >> configure.log +echo SHAREDLIBV = $SHAREDLIBV >> configure.log +echo STATICLIB = $STATICLIB >> configure.log +echo TEST = $TEST >> configure.log +echo VER = $VER >> configure.log +echo Z_U4 = $Z_U4 >> configure.log +echo SRCDIR = $SRCDIR >> configure.log +echo exec_prefix = $exec_prefix >> configure.log +echo includedir = $includedir >> configure.log +echo libdir = $libdir >> configure.log +echo mandir = $mandir >> configure.log +echo prefix = $prefix >> configure.log +echo sharedlibdir = $sharedlibdir >> configure.log +echo uname = $uname >> configure.log + +# udpate Makefile with the configure results +sed < ${SRCDIR}Makefile.in " +/^CC *=/s#=.*#=$CC# +/^CFLAGS *=/s#=.*#=$CFLAGS# +/^SFLAGS *=/s#=.*#=$SFLAGS# +/^LDFLAGS *=/s#=.*#=$LDFLAGS# +/^LDSHARED *=/s#=.*#=$LDSHARED# +/^CPP *=/s#=.*#=$CPP# +/^STATICLIB *=/s#=.*#=$STATICLIB# +/^SHAREDLIB *=/s#=.*#=$SHAREDLIB# +/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV# +/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM# +/^AR *=/s#=.*#=$AR# +/^ARFLAGS *=/s#=.*#=$ARFLAGS# +/^RANLIB *=/s#=.*#=$RANLIB# +/^LDCONFIG *=/s#=.*#=$LDCONFIG# +/^LDSHAREDLIBC *=/s#=.*#=$LDSHAREDLIBC# +/^EXE *=/s#=.*#=$EXE# +/^SRCDIR *=/s#=.*#=$SRCDIR# +/^ZINC *=/s#=.*#=$ZINC# +/^ZINCOUT *=/s#=.*#=$ZINCOUT# +/^prefix *=/s#=.*#=$prefix# +/^exec_prefix *=/s#=.*#=$exec_prefix# +/^libdir *=/s#=.*#=$libdir# +/^sharedlibdir *=/s#=.*#=$sharedlibdir# +/^includedir *=/s#=.*#=$includedir# +/^mandir *=/s#=.*#=$mandir# +/^OBJC *=/s#=.*#= $OBJC# +/^PIC_OBJC *=/s#=.*#= $PIC_OBJC# +/^all: */s#:.*#: $ALL# +/^test: */s#:.*#: $TEST# +" > Makefile + +# create zlib.pc with the configure results +sed < ${SRCDIR}zlib.pc.in " +/^CC *=/s#=.*#=$CC# +/^CFLAGS *=/s#=.*#=$CFLAGS# +/^CPP *=/s#=.*#=$CPP# +/^LDSHARED *=/s#=.*#=$LDSHARED# +/^STATICLIB *=/s#=.*#=$STATICLIB# +/^SHAREDLIB *=/s#=.*#=$SHAREDLIB# +/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV# +/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM# +/^AR *=/s#=.*#=$AR# +/^ARFLAGS *=/s#=.*#=$ARFLAGS# +/^RANLIB *=/s#=.*#=$RANLIB# +/^EXE *=/s#=.*#=$EXE# +/^prefix *=/s#=.*#=$prefix# +/^exec_prefix *=/s#=.*#=$exec_prefix# +/^libdir *=/s#=.*#=$libdir# +/^sharedlibdir *=/s#=.*#=$sharedlibdir# +/^includedir *=/s#=.*#=$includedir# +/^mandir *=/s#=.*#=$mandir# +/^LDFLAGS *=/s#=.*#=$LDFLAGS# +" | sed -e " +s/\@VERSION\@/$VER/g; +" > zlib.pc + +# done +leave 0 diff --git a/dependencies/zlib-1.2.11/contrib/README.contrib b/dependencies/zlib-1.2.11/contrib/README.contrib new file mode 100644 index 0000000..a411d5c --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/README.contrib @@ -0,0 +1,78 @@ +All files under this contrib directory are UNSUPPORTED. There were +provided by users of zlib and were not tested by the authors of zlib. +Use at your own risk. Please contact the authors of the contributions +for help about these, not the zlib authors. Thanks. + + +ada/ by Dmitriy Anisimkov + Support for Ada + See http://zlib-ada.sourceforge.net/ + +amd64/ by Mikhail Teterin + asm code for AMD64 + See patch at http://www.freebsd.org/cgi/query-pr.cgi?pr=bin/96393 + +asm686/ by Brian Raiter + asm code for Pentium and PPro/PII, using the AT&T (GNU as) syntax + See http://www.muppetlabs.com/~breadbox/software/assembly.html + +blast/ by Mark Adler + Decompressor for output of PKWare Data Compression Library (DCL) + +delphi/ by Cosmin Truta + Support for Delphi and C++ Builder + +dotzlib/ by Henrik Ravn + Support for Microsoft .Net and Visual C++ .Net + +gcc_gvmat64/by Gilles Vollant + GCC Version of x86 64-bit (AMD64 and Intel EM64t) code for x64 + assembler to replace longest_match() and inflate_fast() + +infback9/ by Mark Adler + Unsupported diffs to infback to decode the deflate64 format + +inflate86/ by Chris Anderson + Tuned x86 gcc asm code to replace inflate_fast() + +iostream/ by Kevin Ruland + A C++ I/O streams interface to the zlib gz* functions + +iostream2/ by Tyge Løvset + Another C++ I/O streams interface + +iostream3/ by Ludwig Schwardt + and Kevin Ruland + Yet another C++ I/O streams interface + +masmx64/ by Gilles Vollant + x86 64-bit (AMD64 and Intel EM64t) code for x64 assembler to + replace longest_match() and inflate_fast(), also masm x86 + 64-bits translation of Chris Anderson inflate_fast() + +masmx86/ by Gilles Vollant + x86 asm code to replace longest_match() and inflate_fast(), + for Visual C++ and MASM (32 bits). + Based on Brian Raiter (asm686) and Chris Anderson (inflate86) + +minizip/ by Gilles Vollant + Mini zip and unzip based on zlib + Includes Zip64 support by Mathias Svensson + See http://www.winimage.com/zLibDll/minizip.html + +pascal/ by Bob Dellaca et al. + Support for Pascal + +puff/ by Mark Adler + Small, low memory usage inflate. Also serves to provide an + unambiguous description of the deflate format. + +testzlib/ by Gilles Vollant + Example of the use of zlib + +untgz/ by Pedro A. Aranda Gutierrez + A very simple tar.gz file extractor using zlib + +vstudio/ by Gilles Vollant + Building a minizip-enhanced zlib with Microsoft Visual Studio + Includes vc11 from kreuzerkrieg and vc12 from davispuh diff --git a/dependencies/zlib-1.2.11/contrib/ada/buffer_demo.adb b/dependencies/zlib-1.2.11/contrib/ada/buffer_demo.adb new file mode 100644 index 0000000..46b8638 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/ada/buffer_demo.adb @@ -0,0 +1,106 @@ +---------------------------------------------------------------- +-- ZLib for Ada thick binding. -- +-- -- +-- Copyright (C) 2002-2004 Dmitriy Anisimkov -- +-- -- +-- Open source license information is in the zlib.ads file. -- +---------------------------------------------------------------- +-- +-- $Id: buffer_demo.adb,v 1.3 2004/09/06 06:55:35 vagul Exp $ + +-- This demo program provided by Dr Steve Sangwine +-- +-- Demonstration of a problem with Zlib-Ada (already fixed) when a buffer +-- of exactly the correct size is used for decompressed data, and the last +-- few bytes passed in to Zlib are checksum bytes. + +-- This program compresses a string of text, and then decompresses the +-- compressed text into a buffer of the same size as the original text. + +with Ada.Streams; use Ada.Streams; +with Ada.Text_IO; + +with ZLib; use ZLib; + +procedure Buffer_Demo is + EOL : Character renames ASCII.LF; + Text : constant String + := "Four score and seven years ago our fathers brought forth," & EOL & + "upon this continent, a new nation, conceived in liberty," & EOL & + "and dedicated to the proposition that `all men are created equal'."; + + Source : Stream_Element_Array (1 .. Text'Length); + for Source'Address use Text'Address; + +begin + Ada.Text_IO.Put (Text); + Ada.Text_IO.New_Line; + Ada.Text_IO.Put_Line + ("Uncompressed size : " & Positive'Image (Text'Length) & " bytes"); + + declare + Compressed_Data : Stream_Element_Array (1 .. Text'Length); + L : Stream_Element_Offset; + begin + Compress : declare + Compressor : Filter_Type; + I : Stream_Element_Offset; + begin + Deflate_Init (Compressor); + + -- Compress the whole of T at once. + + Translate (Compressor, Source, I, Compressed_Data, L, Finish); + pragma Assert (I = Source'Last); + + Close (Compressor); + + Ada.Text_IO.Put_Line + ("Compressed size : " + & Stream_Element_Offset'Image (L) & " bytes"); + end Compress; + + -- Now we decompress the data, passing short blocks of data to Zlib + -- (because this demonstrates the problem - the last block passed will + -- contain checksum information and there will be no output, only a + -- check inside Zlib that the checksum is correct). + + Decompress : declare + Decompressor : Filter_Type; + + Uncompressed_Data : Stream_Element_Array (1 .. Text'Length); + + Block_Size : constant := 4; + -- This makes sure that the last block contains + -- only Adler checksum data. + + P : Stream_Element_Offset := Compressed_Data'First - 1; + O : Stream_Element_Offset; + begin + Inflate_Init (Decompressor); + + loop + Translate + (Decompressor, + Compressed_Data + (P + 1 .. Stream_Element_Offset'Min (P + Block_Size, L)), + P, + Uncompressed_Data + (Total_Out (Decompressor) + 1 .. Uncompressed_Data'Last), + O, + No_Flush); + + Ada.Text_IO.Put_Line + ("Total in : " & Count'Image (Total_In (Decompressor)) & + ", out : " & Count'Image (Total_Out (Decompressor))); + + exit when P = L; + end loop; + + Ada.Text_IO.New_Line; + Ada.Text_IO.Put_Line + ("Decompressed text matches original text : " + & Boolean'Image (Uncompressed_Data = Source)); + end Decompress; + end; +end Buffer_Demo; diff --git a/dependencies/zlib-1.2.11/contrib/ada/mtest.adb b/dependencies/zlib-1.2.11/contrib/ada/mtest.adb new file mode 100644 index 0000000..c4dfd08 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/ada/mtest.adb @@ -0,0 +1,156 @@ +---------------------------------------------------------------- +-- ZLib for Ada thick binding. -- +-- -- +-- Copyright (C) 2002-2003 Dmitriy Anisimkov -- +-- -- +-- Open source license information is in the zlib.ads file. -- +---------------------------------------------------------------- +-- Continuous test for ZLib multithreading. If the test would fail +-- we should provide thread safe allocation routines for the Z_Stream. +-- +-- $Id: mtest.adb,v 1.4 2004/07/23 07:49:54 vagul Exp $ + +with ZLib; +with Ada.Streams; +with Ada.Numerics.Discrete_Random; +with Ada.Text_IO; +with Ada.Exceptions; +with Ada.Task_Identification; + +procedure MTest is + use Ada.Streams; + use ZLib; + + Stop : Boolean := False; + + pragma Atomic (Stop); + + subtype Visible_Symbols is Stream_Element range 16#20# .. 16#7E#; + + package Random_Elements is + new Ada.Numerics.Discrete_Random (Visible_Symbols); + + task type Test_Task; + + task body Test_Task is + Buffer : Stream_Element_Array (1 .. 100_000); + Gen : Random_Elements.Generator; + + Buffer_First : Stream_Element_Offset; + Compare_First : Stream_Element_Offset; + + Deflate : Filter_Type; + Inflate : Filter_Type; + + procedure Further (Item : in Stream_Element_Array); + + procedure Read_Buffer + (Item : out Ada.Streams.Stream_Element_Array; + Last : out Ada.Streams.Stream_Element_Offset); + + ------------- + -- Further -- + ------------- + + procedure Further (Item : in Stream_Element_Array) is + + procedure Compare (Item : in Stream_Element_Array); + + ------------- + -- Compare -- + ------------- + + procedure Compare (Item : in Stream_Element_Array) is + Next_First : Stream_Element_Offset := Compare_First + Item'Length; + begin + if Buffer (Compare_First .. Next_First - 1) /= Item then + raise Program_Error; + end if; + + Compare_First := Next_First; + end Compare; + + procedure Compare_Write is new ZLib.Write (Write => Compare); + begin + Compare_Write (Inflate, Item, No_Flush); + end Further; + + ----------------- + -- Read_Buffer -- + ----------------- + + procedure Read_Buffer + (Item : out Ada.Streams.Stream_Element_Array; + Last : out Ada.Streams.Stream_Element_Offset) + is + Buff_Diff : Stream_Element_Offset := Buffer'Last - Buffer_First; + Next_First : Stream_Element_Offset; + begin + if Item'Length <= Buff_Diff then + Last := Item'Last; + + Next_First := Buffer_First + Item'Length; + + Item := Buffer (Buffer_First .. Next_First - 1); + + Buffer_First := Next_First; + else + Last := Item'First + Buff_Diff; + Item (Item'First .. Last) := Buffer (Buffer_First .. Buffer'Last); + Buffer_First := Buffer'Last + 1; + end if; + end Read_Buffer; + + procedure Translate is new Generic_Translate + (Data_In => Read_Buffer, + Data_Out => Further); + + begin + Random_Elements.Reset (Gen); + + Buffer := (others => 20); + + Main : loop + for J in Buffer'Range loop + Buffer (J) := Random_Elements.Random (Gen); + + Deflate_Init (Deflate); + Inflate_Init (Inflate); + + Buffer_First := Buffer'First; + Compare_First := Buffer'First; + + Translate (Deflate); + + if Compare_First /= Buffer'Last + 1 then + raise Program_Error; + end if; + + Ada.Text_IO.Put_Line + (Ada.Task_Identification.Image + (Ada.Task_Identification.Current_Task) + & Stream_Element_Offset'Image (J) + & ZLib.Count'Image (Total_Out (Deflate))); + + Close (Deflate); + Close (Inflate); + + exit Main when Stop; + end loop; + end loop Main; + exception + when E : others => + Ada.Text_IO.Put_Line (Ada.Exceptions.Exception_Information (E)); + Stop := True; + end Test_Task; + + Test : array (1 .. 4) of Test_Task; + + pragma Unreferenced (Test); + + Dummy : Character; + +begin + Ada.Text_IO.Get_Immediate (Dummy); + Stop := True; +end MTest; diff --git a/dependencies/zlib-1.2.11/contrib/ada/read.adb b/dependencies/zlib-1.2.11/contrib/ada/read.adb new file mode 100644 index 0000000..1f2efbf --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/ada/read.adb @@ -0,0 +1,156 @@ +---------------------------------------------------------------- +-- ZLib for Ada thick binding. -- +-- -- +-- Copyright (C) 2002-2003 Dmitriy Anisimkov -- +-- -- +-- Open source license information is in the zlib.ads file. -- +---------------------------------------------------------------- + +-- $Id: read.adb,v 1.8 2004/05/31 10:53:40 vagul Exp $ + +-- Test/demo program for the generic read interface. + +with Ada.Numerics.Discrete_Random; +with Ada.Streams; +with Ada.Text_IO; + +with ZLib; + +procedure Read is + + use Ada.Streams; + + ------------------------------------ + -- Test configuration parameters -- + ------------------------------------ + + File_Size : Stream_Element_Offset := 100_000; + + Continuous : constant Boolean := False; + -- If this constant is True, the test would be repeated again and again, + -- with increment File_Size for every iteration. + + Header : constant ZLib.Header_Type := ZLib.Default; + -- Do not use Header other than Default in ZLib versions 1.1.4 and older. + + Init_Random : constant := 8; + -- We are using the same random sequence, in case of we catch bug, + -- so we would be able to reproduce it. + + -- End -- + + Pack_Size : Stream_Element_Offset; + Offset : Stream_Element_Offset; + + Filter : ZLib.Filter_Type; + + subtype Visible_Symbols + is Stream_Element range 16#20# .. 16#7E#; + + package Random_Elements is new + Ada.Numerics.Discrete_Random (Visible_Symbols); + + Gen : Random_Elements.Generator; + Period : constant Stream_Element_Offset := 200; + -- Period constant variable for random generator not to be very random. + -- Bigger period, harder random. + + Read_Buffer : Stream_Element_Array (1 .. 2048); + Read_First : Stream_Element_Offset; + Read_Last : Stream_Element_Offset; + + procedure Reset; + + procedure Read + (Item : out Stream_Element_Array; + Last : out Stream_Element_Offset); + -- this procedure is for generic instantiation of + -- ZLib.Read + -- reading data from the File_In. + + procedure Read is new ZLib.Read + (Read, + Read_Buffer, + Rest_First => Read_First, + Rest_Last => Read_Last); + + ---------- + -- Read -- + ---------- + + procedure Read + (Item : out Stream_Element_Array; + Last : out Stream_Element_Offset) is + begin + Last := Stream_Element_Offset'Min + (Item'Last, + Item'First + File_Size - Offset); + + for J in Item'First .. Last loop + if J < Item'First + Period then + Item (J) := Random_Elements.Random (Gen); + else + Item (J) := Item (J - Period); + end if; + + Offset := Offset + 1; + end loop; + end Read; + + ----------- + -- Reset -- + ----------- + + procedure Reset is + begin + Random_Elements.Reset (Gen, Init_Random); + Pack_Size := 0; + Offset := 1; + Read_First := Read_Buffer'Last + 1; + Read_Last := Read_Buffer'Last; + end Reset; + +begin + Ada.Text_IO.Put_Line ("ZLib " & ZLib.Version); + + loop + for Level in ZLib.Compression_Level'Range loop + + Ada.Text_IO.Put ("Level =" + & ZLib.Compression_Level'Image (Level)); + + -- Deflate using generic instantiation. + + ZLib.Deflate_Init + (Filter, + Level, + Header => Header); + + Reset; + + Ada.Text_IO.Put + (Stream_Element_Offset'Image (File_Size) & " ->"); + + loop + declare + Buffer : Stream_Element_Array (1 .. 1024); + Last : Stream_Element_Offset; + begin + Read (Filter, Buffer, Last); + + Pack_Size := Pack_Size + Last - Buffer'First + 1; + + exit when Last < Buffer'Last; + end; + end loop; + + Ada.Text_IO.Put_Line (Stream_Element_Offset'Image (Pack_Size)); + + ZLib.Close (Filter); + end loop; + + exit when not Continuous; + + File_Size := File_Size + 1; + end loop; +end Read; diff --git a/dependencies/zlib-1.2.11/contrib/ada/readme.txt b/dependencies/zlib-1.2.11/contrib/ada/readme.txt new file mode 100644 index 0000000..ce4d2ca --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/ada/readme.txt @@ -0,0 +1,65 @@ + ZLib for Ada thick binding (ZLib.Ada) + Release 1.3 + +ZLib.Ada is a thick binding interface to the popular ZLib data +compression library, available at http://www.gzip.org/zlib/. +It provides Ada-style access to the ZLib C library. + + + Here are the main changes since ZLib.Ada 1.2: + +- Attension: ZLib.Read generic routine have a initialization requirement + for Read_Last parameter now. It is a bit incompartible with previous version, + but extends functionality, we could use new parameters Allow_Read_Some and + Flush now. + +- Added Is_Open routines to ZLib and ZLib.Streams packages. + +- Add pragma Assert to check Stream_Element is 8 bit. + +- Fix extraction to buffer with exact known decompressed size. Error reported by + Steve Sangwine. + +- Fix definition of ULong (changed to unsigned_long), fix regression on 64 bits + computers. Patch provided by Pascal Obry. + +- Add Status_Error exception definition. + +- Add pragma Assertion that Ada.Streams.Stream_Element size is 8 bit. + + + How to build ZLib.Ada under GNAT + +You should have the ZLib library already build on your computer, before +building ZLib.Ada. Make the directory of ZLib.Ada sources current and +issue the command: + + gnatmake test -largs -L -lz + +Or use the GNAT project file build for GNAT 3.15 or later: + + gnatmake -Pzlib.gpr -L + + + How to build ZLib.Ada under Aonix ObjectAda for Win32 7.2.2 + +1. Make a project with all *.ads and *.adb files from the distribution. +2. Build the libz.a library from the ZLib C sources. +3. Rename libz.a to z.lib. +4. Add the library z.lib to the project. +5. Add the libc.lib library from the ObjectAda distribution to the project. +6. Build the executable using test.adb as a main procedure. + + + How to use ZLib.Ada + +The source files test.adb and read.adb are small demo programs that show +the main functionality of ZLib.Ada. + +The routines from the package specifications are commented. + + +Homepage: http://zlib-ada.sourceforge.net/ +Author: Dmitriy Anisimkov + +Contributors: Pascal Obry , Steve Sangwine diff --git a/dependencies/zlib-1.2.11/contrib/ada/test.adb b/dependencies/zlib-1.2.11/contrib/ada/test.adb new file mode 100644 index 0000000..90773ac --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/ada/test.adb @@ -0,0 +1,463 @@ +---------------------------------------------------------------- +-- ZLib for Ada thick binding. -- +-- -- +-- Copyright (C) 2002-2003 Dmitriy Anisimkov -- +-- -- +-- Open source license information is in the zlib.ads file. -- +---------------------------------------------------------------- + +-- $Id: test.adb,v 1.17 2003/08/12 12:13:30 vagul Exp $ + +-- The program has a few aims. +-- 1. Test ZLib.Ada95 thick binding functionality. +-- 2. Show the example of use main functionality of the ZLib.Ada95 binding. +-- 3. Build this program automatically compile all ZLib.Ada95 packages under +-- GNAT Ada95 compiler. + +with ZLib.Streams; +with Ada.Streams.Stream_IO; +with Ada.Numerics.Discrete_Random; + +with Ada.Text_IO; + +with Ada.Calendar; + +procedure Test is + + use Ada.Streams; + use Stream_IO; + + ------------------------------------ + -- Test configuration parameters -- + ------------------------------------ + + File_Size : Count := 100_000; + Continuous : constant Boolean := False; + + Header : constant ZLib.Header_Type := ZLib.Default; + -- ZLib.None; + -- ZLib.Auto; + -- ZLib.GZip; + -- Do not use Header other then Default in ZLib versions 1.1.4 + -- and older. + + Strategy : constant ZLib.Strategy_Type := ZLib.Default_Strategy; + Init_Random : constant := 10; + + -- End -- + + In_File_Name : constant String := "testzlib.in"; + -- Name of the input file + + Z_File_Name : constant String := "testzlib.zlb"; + -- Name of the compressed file. + + Out_File_Name : constant String := "testzlib.out"; + -- Name of the decompressed file. + + File_In : File_Type; + File_Out : File_Type; + File_Back : File_Type; + File_Z : ZLib.Streams.Stream_Type; + + Filter : ZLib.Filter_Type; + + Time_Stamp : Ada.Calendar.Time; + + procedure Generate_File; + -- Generate file of spetsified size with some random data. + -- The random data is repeatable, for the good compression. + + procedure Compare_Streams + (Left, Right : in out Root_Stream_Type'Class); + -- The procedure compearing data in 2 streams. + -- It is for compare data before and after compression/decompression. + + procedure Compare_Files (Left, Right : String); + -- Compare files. Based on the Compare_Streams. + + procedure Copy_Streams + (Source, Target : in out Root_Stream_Type'Class; + Buffer_Size : in Stream_Element_Offset := 1024); + -- Copying data from one stream to another. It is for test stream + -- interface of the library. + + procedure Data_In + (Item : out Stream_Element_Array; + Last : out Stream_Element_Offset); + -- this procedure is for generic instantiation of + -- ZLib.Generic_Translate. + -- reading data from the File_In. + + procedure Data_Out (Item : in Stream_Element_Array); + -- this procedure is for generic instantiation of + -- ZLib.Generic_Translate. + -- writing data to the File_Out. + + procedure Stamp; + -- Store the timestamp to the local variable. + + procedure Print_Statistic (Msg : String; Data_Size : ZLib.Count); + -- Print the time statistic with the message. + + procedure Translate is new ZLib.Generic_Translate + (Data_In => Data_In, + Data_Out => Data_Out); + -- This procedure is moving data from File_In to File_Out + -- with compression or decompression, depend on initialization of + -- Filter parameter. + + ------------------- + -- Compare_Files -- + ------------------- + + procedure Compare_Files (Left, Right : String) is + Left_File, Right_File : File_Type; + begin + Open (Left_File, In_File, Left); + Open (Right_File, In_File, Right); + Compare_Streams (Stream (Left_File).all, Stream (Right_File).all); + Close (Left_File); + Close (Right_File); + end Compare_Files; + + --------------------- + -- Compare_Streams -- + --------------------- + + procedure Compare_Streams + (Left, Right : in out Ada.Streams.Root_Stream_Type'Class) + is + Left_Buffer, Right_Buffer : Stream_Element_Array (0 .. 16#FFF#); + Left_Last, Right_Last : Stream_Element_Offset; + begin + loop + Read (Left, Left_Buffer, Left_Last); + Read (Right, Right_Buffer, Right_Last); + + if Left_Last /= Right_Last then + Ada.Text_IO.Put_Line ("Compare error :" + & Stream_Element_Offset'Image (Left_Last) + & " /= " + & Stream_Element_Offset'Image (Right_Last)); + + raise Constraint_Error; + + elsif Left_Buffer (0 .. Left_Last) + /= Right_Buffer (0 .. Right_Last) + then + Ada.Text_IO.Put_Line ("ERROR: IN and OUT files is not equal."); + raise Constraint_Error; + + end if; + + exit when Left_Last < Left_Buffer'Last; + end loop; + end Compare_Streams; + + ------------------ + -- Copy_Streams -- + ------------------ + + procedure Copy_Streams + (Source, Target : in out Ada.Streams.Root_Stream_Type'Class; + Buffer_Size : in Stream_Element_Offset := 1024) + is + Buffer : Stream_Element_Array (1 .. Buffer_Size); + Last : Stream_Element_Offset; + begin + loop + Read (Source, Buffer, Last); + Write (Target, Buffer (1 .. Last)); + + exit when Last < Buffer'Last; + end loop; + end Copy_Streams; + + ------------- + -- Data_In -- + ------------- + + procedure Data_In + (Item : out Stream_Element_Array; + Last : out Stream_Element_Offset) is + begin + Read (File_In, Item, Last); + end Data_In; + + -------------- + -- Data_Out -- + -------------- + + procedure Data_Out (Item : in Stream_Element_Array) is + begin + Write (File_Out, Item); + end Data_Out; + + ------------------- + -- Generate_File -- + ------------------- + + procedure Generate_File is + subtype Visible_Symbols is Stream_Element range 16#20# .. 16#7E#; + + package Random_Elements is + new Ada.Numerics.Discrete_Random (Visible_Symbols); + + Gen : Random_Elements.Generator; + Buffer : Stream_Element_Array := (1 .. 77 => 16#20#) & 10; + + Buffer_Count : constant Count := File_Size / Buffer'Length; + -- Number of same buffers in the packet. + + Density : constant Count := 30; -- from 0 to Buffer'Length - 2; + + procedure Fill_Buffer (J, D : in Count); + -- Change the part of the buffer. + + ----------------- + -- Fill_Buffer -- + ----------------- + + procedure Fill_Buffer (J, D : in Count) is + begin + for K in 0 .. D loop + Buffer + (Stream_Element_Offset ((J + K) mod (Buffer'Length - 1) + 1)) + := Random_Elements.Random (Gen); + + end loop; + end Fill_Buffer; + + begin + Random_Elements.Reset (Gen, Init_Random); + + Create (File_In, Out_File, In_File_Name); + + Fill_Buffer (1, Buffer'Length - 2); + + for J in 1 .. Buffer_Count loop + Write (File_In, Buffer); + + Fill_Buffer (J, Density); + end loop; + + -- fill remain size. + + Write + (File_In, + Buffer + (1 .. Stream_Element_Offset + (File_Size - Buffer'Length * Buffer_Count))); + + Flush (File_In); + Close (File_In); + end Generate_File; + + --------------------- + -- Print_Statistic -- + --------------------- + + procedure Print_Statistic (Msg : String; Data_Size : ZLib.Count) is + use Ada.Calendar; + use Ada.Text_IO; + + package Count_IO is new Integer_IO (ZLib.Count); + + Curr_Dur : Duration := Clock - Time_Stamp; + begin + Put (Msg); + + Set_Col (20); + Ada.Text_IO.Put ("size ="); + + Count_IO.Put + (Data_Size, + Width => Stream_IO.Count'Image (File_Size)'Length); + + Put_Line (" duration =" & Duration'Image (Curr_Dur)); + end Print_Statistic; + + ----------- + -- Stamp -- + ----------- + + procedure Stamp is + begin + Time_Stamp := Ada.Calendar.Clock; + end Stamp; + +begin + Ada.Text_IO.Put_Line ("ZLib " & ZLib.Version); + + loop + Generate_File; + + for Level in ZLib.Compression_Level'Range loop + + Ada.Text_IO.Put_Line ("Level =" + & ZLib.Compression_Level'Image (Level)); + + -- Test generic interface. + Open (File_In, In_File, In_File_Name); + Create (File_Out, Out_File, Z_File_Name); + + Stamp; + + -- Deflate using generic instantiation. + + ZLib.Deflate_Init + (Filter => Filter, + Level => Level, + Strategy => Strategy, + Header => Header); + + Translate (Filter); + Print_Statistic ("Generic compress", ZLib.Total_Out (Filter)); + ZLib.Close (Filter); + + Close (File_In); + Close (File_Out); + + Open (File_In, In_File, Z_File_Name); + Create (File_Out, Out_File, Out_File_Name); + + Stamp; + + -- Inflate using generic instantiation. + + ZLib.Inflate_Init (Filter, Header => Header); + + Translate (Filter); + Print_Statistic ("Generic decompress", ZLib.Total_Out (Filter)); + + ZLib.Close (Filter); + + Close (File_In); + Close (File_Out); + + Compare_Files (In_File_Name, Out_File_Name); + + -- Test stream interface. + + -- Compress to the back stream. + + Open (File_In, In_File, In_File_Name); + Create (File_Back, Out_File, Z_File_Name); + + Stamp; + + ZLib.Streams.Create + (Stream => File_Z, + Mode => ZLib.Streams.Out_Stream, + Back => ZLib.Streams.Stream_Access + (Stream (File_Back)), + Back_Compressed => True, + Level => Level, + Strategy => Strategy, + Header => Header); + + Copy_Streams + (Source => Stream (File_In).all, + Target => File_Z); + + -- Flushing internal buffers to the back stream. + + ZLib.Streams.Flush (File_Z, ZLib.Finish); + + Print_Statistic ("Write compress", + ZLib.Streams.Write_Total_Out (File_Z)); + + ZLib.Streams.Close (File_Z); + + Close (File_In); + Close (File_Back); + + -- Compare reading from original file and from + -- decompression stream. + + Open (File_In, In_File, In_File_Name); + Open (File_Back, In_File, Z_File_Name); + + ZLib.Streams.Create + (Stream => File_Z, + Mode => ZLib.Streams.In_Stream, + Back => ZLib.Streams.Stream_Access + (Stream (File_Back)), + Back_Compressed => True, + Header => Header); + + Stamp; + Compare_Streams (Stream (File_In).all, File_Z); + + Print_Statistic ("Read decompress", + ZLib.Streams.Read_Total_Out (File_Z)); + + ZLib.Streams.Close (File_Z); + Close (File_In); + Close (File_Back); + + -- Compress by reading from compression stream. + + Open (File_Back, In_File, In_File_Name); + Create (File_Out, Out_File, Z_File_Name); + + ZLib.Streams.Create + (Stream => File_Z, + Mode => ZLib.Streams.In_Stream, + Back => ZLib.Streams.Stream_Access + (Stream (File_Back)), + Back_Compressed => False, + Level => Level, + Strategy => Strategy, + Header => Header); + + Stamp; + Copy_Streams + (Source => File_Z, + Target => Stream (File_Out).all); + + Print_Statistic ("Read compress", + ZLib.Streams.Read_Total_Out (File_Z)); + + ZLib.Streams.Close (File_Z); + + Close (File_Out); + Close (File_Back); + + -- Decompress to decompression stream. + + Open (File_In, In_File, Z_File_Name); + Create (File_Back, Out_File, Out_File_Name); + + ZLib.Streams.Create + (Stream => File_Z, + Mode => ZLib.Streams.Out_Stream, + Back => ZLib.Streams.Stream_Access + (Stream (File_Back)), + Back_Compressed => False, + Header => Header); + + Stamp; + + Copy_Streams + (Source => Stream (File_In).all, + Target => File_Z); + + Print_Statistic ("Write decompress", + ZLib.Streams.Write_Total_Out (File_Z)); + + ZLib.Streams.Close (File_Z); + Close (File_In); + Close (File_Back); + + Compare_Files (In_File_Name, Out_File_Name); + end loop; + + Ada.Text_IO.Put_Line (Count'Image (File_Size) & " Ok."); + + exit when not Continuous; + + File_Size := File_Size + 1; + end loop; +end Test; diff --git a/dependencies/zlib-1.2.11/contrib/ada/zlib-streams.adb b/dependencies/zlib-1.2.11/contrib/ada/zlib-streams.adb new file mode 100644 index 0000000..b6497ba --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/ada/zlib-streams.adb @@ -0,0 +1,225 @@ +---------------------------------------------------------------- +-- ZLib for Ada thick binding. -- +-- -- +-- Copyright (C) 2002-2003 Dmitriy Anisimkov -- +-- -- +-- Open source license information is in the zlib.ads file. -- +---------------------------------------------------------------- + +-- $Id: zlib-streams.adb,v 1.10 2004/05/31 10:53:40 vagul Exp $ + +with Ada.Unchecked_Deallocation; + +package body ZLib.Streams is + + ----------- + -- Close -- + ----------- + + procedure Close (Stream : in out Stream_Type) is + procedure Free is new Ada.Unchecked_Deallocation + (Stream_Element_Array, Buffer_Access); + begin + if Stream.Mode = Out_Stream or Stream.Mode = Duplex then + -- We should flush the data written by the writer. + + Flush (Stream, Finish); + + Close (Stream.Writer); + end if; + + if Stream.Mode = In_Stream or Stream.Mode = Duplex then + Close (Stream.Reader); + Free (Stream.Buffer); + end if; + end Close; + + ------------ + -- Create -- + ------------ + + procedure Create + (Stream : out Stream_Type; + Mode : in Stream_Mode; + Back : in Stream_Access; + Back_Compressed : in Boolean; + Level : in Compression_Level := Default_Compression; + Strategy : in Strategy_Type := Default_Strategy; + Header : in Header_Type := Default; + Read_Buffer_Size : in Ada.Streams.Stream_Element_Offset + := Default_Buffer_Size; + Write_Buffer_Size : in Ada.Streams.Stream_Element_Offset + := Default_Buffer_Size) + is + + subtype Buffer_Subtype is Stream_Element_Array (1 .. Read_Buffer_Size); + + procedure Init_Filter + (Filter : in out Filter_Type; + Compress : in Boolean); + + ----------------- + -- Init_Filter -- + ----------------- + + procedure Init_Filter + (Filter : in out Filter_Type; + Compress : in Boolean) is + begin + if Compress then + Deflate_Init + (Filter, Level, Strategy, Header => Header); + else + Inflate_Init (Filter, Header => Header); + end if; + end Init_Filter; + + begin + Stream.Back := Back; + Stream.Mode := Mode; + + if Mode = Out_Stream or Mode = Duplex then + Init_Filter (Stream.Writer, Back_Compressed); + Stream.Buffer_Size := Write_Buffer_Size; + else + Stream.Buffer_Size := 0; + end if; + + if Mode = In_Stream or Mode = Duplex then + Init_Filter (Stream.Reader, not Back_Compressed); + + Stream.Buffer := new Buffer_Subtype; + Stream.Rest_First := Stream.Buffer'Last + 1; + Stream.Rest_Last := Stream.Buffer'Last; + end if; + end Create; + + ----------- + -- Flush -- + ----------- + + procedure Flush + (Stream : in out Stream_Type; + Mode : in Flush_Mode := Sync_Flush) + is + Buffer : Stream_Element_Array (1 .. Stream.Buffer_Size); + Last : Stream_Element_Offset; + begin + loop + Flush (Stream.Writer, Buffer, Last, Mode); + + Ada.Streams.Write (Stream.Back.all, Buffer (1 .. Last)); + + exit when Last < Buffer'Last; + end loop; + end Flush; + + ------------- + -- Is_Open -- + ------------- + + function Is_Open (Stream : Stream_Type) return Boolean is + begin + return Is_Open (Stream.Reader) or else Is_Open (Stream.Writer); + end Is_Open; + + ---------- + -- Read -- + ---------- + + procedure Read + (Stream : in out Stream_Type; + Item : out Stream_Element_Array; + Last : out Stream_Element_Offset) + is + + procedure Read + (Item : out Stream_Element_Array; + Last : out Stream_Element_Offset); + + ---------- + -- Read -- + ---------- + + procedure Read + (Item : out Stream_Element_Array; + Last : out Stream_Element_Offset) is + begin + Ada.Streams.Read (Stream.Back.all, Item, Last); + end Read; + + procedure Read is new ZLib.Read + (Read => Read, + Buffer => Stream.Buffer.all, + Rest_First => Stream.Rest_First, + Rest_Last => Stream.Rest_Last); + + begin + Read (Stream.Reader, Item, Last); + end Read; + + ------------------- + -- Read_Total_In -- + ------------------- + + function Read_Total_In (Stream : in Stream_Type) return Count is + begin + return Total_In (Stream.Reader); + end Read_Total_In; + + -------------------- + -- Read_Total_Out -- + -------------------- + + function Read_Total_Out (Stream : in Stream_Type) return Count is + begin + return Total_Out (Stream.Reader); + end Read_Total_Out; + + ----------- + -- Write -- + ----------- + + procedure Write + (Stream : in out Stream_Type; + Item : in Stream_Element_Array) + is + + procedure Write (Item : in Stream_Element_Array); + + ----------- + -- Write -- + ----------- + + procedure Write (Item : in Stream_Element_Array) is + begin + Ada.Streams.Write (Stream.Back.all, Item); + end Write; + + procedure Write is new ZLib.Write + (Write => Write, + Buffer_Size => Stream.Buffer_Size); + + begin + Write (Stream.Writer, Item, No_Flush); + end Write; + + -------------------- + -- Write_Total_In -- + -------------------- + + function Write_Total_In (Stream : in Stream_Type) return Count is + begin + return Total_In (Stream.Writer); + end Write_Total_In; + + --------------------- + -- Write_Total_Out -- + --------------------- + + function Write_Total_Out (Stream : in Stream_Type) return Count is + begin + return Total_Out (Stream.Writer); + end Write_Total_Out; + +end ZLib.Streams; diff --git a/dependencies/zlib-1.2.11/contrib/ada/zlib-streams.ads b/dependencies/zlib-1.2.11/contrib/ada/zlib-streams.ads new file mode 100644 index 0000000..8e26cd4 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/ada/zlib-streams.ads @@ -0,0 +1,114 @@ +---------------------------------------------------------------- +-- ZLib for Ada thick binding. -- +-- -- +-- Copyright (C) 2002-2003 Dmitriy Anisimkov -- +-- -- +-- Open source license information is in the zlib.ads file. -- +---------------------------------------------------------------- + +-- $Id: zlib-streams.ads,v 1.12 2004/05/31 10:53:40 vagul Exp $ + +package ZLib.Streams is + + type Stream_Mode is (In_Stream, Out_Stream, Duplex); + + type Stream_Access is access all Ada.Streams.Root_Stream_Type'Class; + + type Stream_Type is + new Ada.Streams.Root_Stream_Type with private; + + procedure Read + (Stream : in out Stream_Type; + Item : out Ada.Streams.Stream_Element_Array; + Last : out Ada.Streams.Stream_Element_Offset); + + procedure Write + (Stream : in out Stream_Type; + Item : in Ada.Streams.Stream_Element_Array); + + procedure Flush + (Stream : in out Stream_Type; + Mode : in Flush_Mode := Sync_Flush); + -- Flush the written data to the back stream, + -- all data placed to the compressor is flushing to the Back stream. + -- Should not be used until necessary, because it is decreasing + -- compression. + + function Read_Total_In (Stream : in Stream_Type) return Count; + pragma Inline (Read_Total_In); + -- Return total number of bytes read from back stream so far. + + function Read_Total_Out (Stream : in Stream_Type) return Count; + pragma Inline (Read_Total_Out); + -- Return total number of bytes read so far. + + function Write_Total_In (Stream : in Stream_Type) return Count; + pragma Inline (Write_Total_In); + -- Return total number of bytes written so far. + + function Write_Total_Out (Stream : in Stream_Type) return Count; + pragma Inline (Write_Total_Out); + -- Return total number of bytes written to the back stream. + + procedure Create + (Stream : out Stream_Type; + Mode : in Stream_Mode; + Back : in Stream_Access; + Back_Compressed : in Boolean; + Level : in Compression_Level := Default_Compression; + Strategy : in Strategy_Type := Default_Strategy; + Header : in Header_Type := Default; + Read_Buffer_Size : in Ada.Streams.Stream_Element_Offset + := Default_Buffer_Size; + Write_Buffer_Size : in Ada.Streams.Stream_Element_Offset + := Default_Buffer_Size); + -- Create the Comression/Decompression stream. + -- If mode is In_Stream then Write operation is disabled. + -- If mode is Out_Stream then Read operation is disabled. + + -- If Back_Compressed is true then + -- Data written to the Stream is compressing to the Back stream + -- and data read from the Stream is decompressed data from the Back stream. + + -- If Back_Compressed is false then + -- Data written to the Stream is decompressing to the Back stream + -- and data read from the Stream is compressed data from the Back stream. + + -- !!! When the Need_Header is False ZLib-Ada is using undocumented + -- ZLib 1.1.4 functionality to do not create/wait for ZLib headers. + + function Is_Open (Stream : Stream_Type) return Boolean; + + procedure Close (Stream : in out Stream_Type); + +private + + use Ada.Streams; + + type Buffer_Access is access all Stream_Element_Array; + + type Stream_Type + is new Root_Stream_Type with + record + Mode : Stream_Mode; + + Buffer : Buffer_Access; + Rest_First : Stream_Element_Offset; + Rest_Last : Stream_Element_Offset; + -- Buffer for Read operation. + -- We need to have this buffer in the record + -- because not all read data from back stream + -- could be processed during the read operation. + + Buffer_Size : Stream_Element_Offset; + -- Buffer size for write operation. + -- We do not need to have this buffer + -- in the record because all data could be + -- processed in the write operation. + + Back : Stream_Access; + Reader : Filter_Type; + Writer : Filter_Type; + end record; + +end ZLib.Streams; diff --git a/dependencies/zlib-1.2.11/contrib/ada/zlib-thin.adb b/dependencies/zlib-1.2.11/contrib/ada/zlib-thin.adb new file mode 100644 index 0000000..0ca4a71 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/ada/zlib-thin.adb @@ -0,0 +1,141 @@ +---------------------------------------------------------------- +-- ZLib for Ada thick binding. -- +-- -- +-- Copyright (C) 2002-2003 Dmitriy Anisimkov -- +-- -- +-- Open source license information is in the zlib.ads file. -- +---------------------------------------------------------------- + +-- $Id: zlib-thin.adb,v 1.8 2003/12/14 18:27:31 vagul Exp $ + +package body ZLib.Thin is + + ZLIB_VERSION : constant Chars_Ptr := zlibVersion; + + Z_Stream_Size : constant Int := Z_Stream'Size / System.Storage_Unit; + + -------------- + -- Avail_In -- + -------------- + + function Avail_In (Strm : in Z_Stream) return UInt is + begin + return Strm.Avail_In; + end Avail_In; + + --------------- + -- Avail_Out -- + --------------- + + function Avail_Out (Strm : in Z_Stream) return UInt is + begin + return Strm.Avail_Out; + end Avail_Out; + + ------------------ + -- Deflate_Init -- + ------------------ + + function Deflate_Init + (strm : Z_Streamp; + level : Int; + method : Int; + windowBits : Int; + memLevel : Int; + strategy : Int) + return Int is + begin + return deflateInit2 + (strm, + level, + method, + windowBits, + memLevel, + strategy, + ZLIB_VERSION, + Z_Stream_Size); + end Deflate_Init; + + ------------------ + -- Inflate_Init -- + ------------------ + + function Inflate_Init (strm : Z_Streamp; windowBits : Int) return Int is + begin + return inflateInit2 (strm, windowBits, ZLIB_VERSION, Z_Stream_Size); + end Inflate_Init; + + ------------------------ + -- Last_Error_Message -- + ------------------------ + + function Last_Error_Message (Strm : in Z_Stream) return String is + use Interfaces.C.Strings; + begin + if Strm.msg = Null_Ptr then + return ""; + else + return Value (Strm.msg); + end if; + end Last_Error_Message; + + ------------ + -- Set_In -- + ------------ + + procedure Set_In + (Strm : in out Z_Stream; + Buffer : in Voidp; + Size : in UInt) is + begin + Strm.Next_In := Buffer; + Strm.Avail_In := Size; + end Set_In; + + ------------------ + -- Set_Mem_Func -- + ------------------ + + procedure Set_Mem_Func + (Strm : in out Z_Stream; + Opaque : in Voidp; + Alloc : in alloc_func; + Free : in free_func) is + begin + Strm.opaque := Opaque; + Strm.zalloc := Alloc; + Strm.zfree := Free; + end Set_Mem_Func; + + ------------- + -- Set_Out -- + ------------- + + procedure Set_Out + (Strm : in out Z_Stream; + Buffer : in Voidp; + Size : in UInt) is + begin + Strm.Next_Out := Buffer; + Strm.Avail_Out := Size; + end Set_Out; + + -------------- + -- Total_In -- + -------------- + + function Total_In (Strm : in Z_Stream) return ULong is + begin + return Strm.Total_In; + end Total_In; + + --------------- + -- Total_Out -- + --------------- + + function Total_Out (Strm : in Z_Stream) return ULong is + begin + return Strm.Total_Out; + end Total_Out; + +end ZLib.Thin; diff --git a/dependencies/zlib-1.2.11/contrib/ada/zlib-thin.ads b/dependencies/zlib-1.2.11/contrib/ada/zlib-thin.ads new file mode 100644 index 0000000..810173c --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/ada/zlib-thin.ads @@ -0,0 +1,450 @@ +---------------------------------------------------------------- +-- ZLib for Ada thick binding. -- +-- -- +-- Copyright (C) 2002-2003 Dmitriy Anisimkov -- +-- -- +-- Open source license information is in the zlib.ads file. -- +---------------------------------------------------------------- + +-- $Id: zlib-thin.ads,v 1.11 2004/07/23 06:33:11 vagul Exp $ + +with Interfaces.C.Strings; + +with System; + +private package ZLib.Thin is + + -- From zconf.h + + MAX_MEM_LEVEL : constant := 9; -- zconf.h:105 + -- zconf.h:105 + MAX_WBITS : constant := 15; -- zconf.h:115 + -- 32K LZ77 window + -- zconf.h:115 + SEEK_SET : constant := 8#0000#; -- zconf.h:244 + -- Seek from beginning of file. + -- zconf.h:244 + SEEK_CUR : constant := 1; -- zconf.h:245 + -- Seek from current position. + -- zconf.h:245 + SEEK_END : constant := 2; -- zconf.h:246 + -- Set file pointer to EOF plus "offset" + -- zconf.h:246 + + type Byte is new Interfaces.C.unsigned_char; -- 8 bits + -- zconf.h:214 + type UInt is new Interfaces.C.unsigned; -- 16 bits or more + -- zconf.h:216 + type Int is new Interfaces.C.int; + + type ULong is new Interfaces.C.unsigned_long; -- 32 bits or more + -- zconf.h:217 + subtype Chars_Ptr is Interfaces.C.Strings.chars_ptr; + + type ULong_Access is access ULong; + type Int_Access is access Int; + + subtype Voidp is System.Address; -- zconf.h:232 + + subtype Byte_Access is Voidp; + + Nul : constant Voidp := System.Null_Address; + -- end from zconf + + Z_NO_FLUSH : constant := 8#0000#; -- zlib.h:125 + -- zlib.h:125 + Z_PARTIAL_FLUSH : constant := 1; -- zlib.h:126 + -- will be removed, use + -- Z_SYNC_FLUSH instead + -- zlib.h:126 + Z_SYNC_FLUSH : constant := 2; -- zlib.h:127 + -- zlib.h:127 + Z_FULL_FLUSH : constant := 3; -- zlib.h:128 + -- zlib.h:128 + Z_FINISH : constant := 4; -- zlib.h:129 + -- zlib.h:129 + Z_OK : constant := 8#0000#; -- zlib.h:132 + -- zlib.h:132 + Z_STREAM_END : constant := 1; -- zlib.h:133 + -- zlib.h:133 + Z_NEED_DICT : constant := 2; -- zlib.h:134 + -- zlib.h:134 + Z_ERRNO : constant := -1; -- zlib.h:135 + -- zlib.h:135 + Z_STREAM_ERROR : constant := -2; -- zlib.h:136 + -- zlib.h:136 + Z_DATA_ERROR : constant := -3; -- zlib.h:137 + -- zlib.h:137 + Z_MEM_ERROR : constant := -4; -- zlib.h:138 + -- zlib.h:138 + Z_BUF_ERROR : constant := -5; -- zlib.h:139 + -- zlib.h:139 + Z_VERSION_ERROR : constant := -6; -- zlib.h:140 + -- zlib.h:140 + Z_NO_COMPRESSION : constant := 8#0000#; -- zlib.h:145 + -- zlib.h:145 + Z_BEST_SPEED : constant := 1; -- zlib.h:146 + -- zlib.h:146 + Z_BEST_COMPRESSION : constant := 9; -- zlib.h:147 + -- zlib.h:147 + Z_DEFAULT_COMPRESSION : constant := -1; -- zlib.h:148 + -- zlib.h:148 + Z_FILTERED : constant := 1; -- zlib.h:151 + -- zlib.h:151 + Z_HUFFMAN_ONLY : constant := 2; -- zlib.h:152 + -- zlib.h:152 + Z_DEFAULT_STRATEGY : constant := 8#0000#; -- zlib.h:153 + -- zlib.h:153 + Z_BINARY : constant := 8#0000#; -- zlib.h:156 + -- zlib.h:156 + Z_ASCII : constant := 1; -- zlib.h:157 + -- zlib.h:157 + Z_UNKNOWN : constant := 2; -- zlib.h:158 + -- zlib.h:158 + Z_DEFLATED : constant := 8; -- zlib.h:161 + -- zlib.h:161 + Z_NULL : constant := 8#0000#; -- zlib.h:164 + -- for initializing zalloc, zfree, opaque + -- zlib.h:164 + type gzFile is new Voidp; -- zlib.h:646 + + type Z_Stream is private; + + type Z_Streamp is access all Z_Stream; -- zlib.h:89 + + type alloc_func is access function + (Opaque : Voidp; + Items : UInt; + Size : UInt) + return Voidp; -- zlib.h:63 + + type free_func is access procedure (opaque : Voidp; address : Voidp); + + function zlibVersion return Chars_Ptr; + + function Deflate (strm : Z_Streamp; flush : Int) return Int; + + function DeflateEnd (strm : Z_Streamp) return Int; + + function Inflate (strm : Z_Streamp; flush : Int) return Int; + + function InflateEnd (strm : Z_Streamp) return Int; + + function deflateSetDictionary + (strm : Z_Streamp; + dictionary : Byte_Access; + dictLength : UInt) + return Int; + + function deflateCopy (dest : Z_Streamp; source : Z_Streamp) return Int; + -- zlib.h:478 + + function deflateReset (strm : Z_Streamp) return Int; -- zlib.h:495 + + function deflateParams + (strm : Z_Streamp; + level : Int; + strategy : Int) + return Int; -- zlib.h:506 + + function inflateSetDictionary + (strm : Z_Streamp; + dictionary : Byte_Access; + dictLength : UInt) + return Int; -- zlib.h:548 + + function inflateSync (strm : Z_Streamp) return Int; -- zlib.h:565 + + function inflateReset (strm : Z_Streamp) return Int; -- zlib.h:580 + + function compress + (dest : Byte_Access; + destLen : ULong_Access; + source : Byte_Access; + sourceLen : ULong) + return Int; -- zlib.h:601 + + function compress2 + (dest : Byte_Access; + destLen : ULong_Access; + source : Byte_Access; + sourceLen : ULong; + level : Int) + return Int; -- zlib.h:615 + + function uncompress + (dest : Byte_Access; + destLen : ULong_Access; + source : Byte_Access; + sourceLen : ULong) + return Int; + + function gzopen (path : Chars_Ptr; mode : Chars_Ptr) return gzFile; + + function gzdopen (fd : Int; mode : Chars_Ptr) return gzFile; + + function gzsetparams + (file : gzFile; + level : Int; + strategy : Int) + return Int; + + function gzread + (file : gzFile; + buf : Voidp; + len : UInt) + return Int; + + function gzwrite + (file : in gzFile; + buf : in Voidp; + len : in UInt) + return Int; + + function gzprintf (file : in gzFile; format : in Chars_Ptr) return Int; + + function gzputs (file : in gzFile; s : in Chars_Ptr) return Int; + + function gzgets + (file : gzFile; + buf : Chars_Ptr; + len : Int) + return Chars_Ptr; + + function gzputc (file : gzFile; char : Int) return Int; + + function gzgetc (file : gzFile) return Int; + + function gzflush (file : gzFile; flush : Int) return Int; + + function gzseek + (file : gzFile; + offset : Int; + whence : Int) + return Int; + + function gzrewind (file : gzFile) return Int; + + function gztell (file : gzFile) return Int; + + function gzeof (file : gzFile) return Int; + + function gzclose (file : gzFile) return Int; + + function gzerror (file : gzFile; errnum : Int_Access) return Chars_Ptr; + + function adler32 + (adler : ULong; + buf : Byte_Access; + len : UInt) + return ULong; + + function crc32 + (crc : ULong; + buf : Byte_Access; + len : UInt) + return ULong; + + function deflateInit + (strm : Z_Streamp; + level : Int; + version : Chars_Ptr; + stream_size : Int) + return Int; + + function deflateInit2 + (strm : Z_Streamp; + level : Int; + method : Int; + windowBits : Int; + memLevel : Int; + strategy : Int; + version : Chars_Ptr; + stream_size : Int) + return Int; + + function Deflate_Init + (strm : Z_Streamp; + level : Int; + method : Int; + windowBits : Int; + memLevel : Int; + strategy : Int) + return Int; + pragma Inline (Deflate_Init); + + function inflateInit + (strm : Z_Streamp; + version : Chars_Ptr; + stream_size : Int) + return Int; + + function inflateInit2 + (strm : in Z_Streamp; + windowBits : in Int; + version : in Chars_Ptr; + stream_size : in Int) + return Int; + + function inflateBackInit + (strm : in Z_Streamp; + windowBits : in Int; + window : in Byte_Access; + version : in Chars_Ptr; + stream_size : in Int) + return Int; + -- Size of window have to be 2**windowBits. + + function Inflate_Init (strm : Z_Streamp; windowBits : Int) return Int; + pragma Inline (Inflate_Init); + + function zError (err : Int) return Chars_Ptr; + + function inflateSyncPoint (z : Z_Streamp) return Int; + + function get_crc_table return ULong_Access; + + -- Interface to the available fields of the z_stream structure. + -- The application must update next_in and avail_in when avail_in has + -- dropped to zero. It must update next_out and avail_out when avail_out + -- has dropped to zero. The application must initialize zalloc, zfree and + -- opaque before calling the init function. + + procedure Set_In + (Strm : in out Z_Stream; + Buffer : in Voidp; + Size : in UInt); + pragma Inline (Set_In); + + procedure Set_Out + (Strm : in out Z_Stream; + Buffer : in Voidp; + Size : in UInt); + pragma Inline (Set_Out); + + procedure Set_Mem_Func + (Strm : in out Z_Stream; + Opaque : in Voidp; + Alloc : in alloc_func; + Free : in free_func); + pragma Inline (Set_Mem_Func); + + function Last_Error_Message (Strm : in Z_Stream) return String; + pragma Inline (Last_Error_Message); + + function Avail_Out (Strm : in Z_Stream) return UInt; + pragma Inline (Avail_Out); + + function Avail_In (Strm : in Z_Stream) return UInt; + pragma Inline (Avail_In); + + function Total_In (Strm : in Z_Stream) return ULong; + pragma Inline (Total_In); + + function Total_Out (Strm : in Z_Stream) return ULong; + pragma Inline (Total_Out); + + function inflateCopy + (dest : in Z_Streamp; + Source : in Z_Streamp) + return Int; + + function compressBound (Source_Len : in ULong) return ULong; + + function deflateBound + (Strm : in Z_Streamp; + Source_Len : in ULong) + return ULong; + + function gzungetc (C : in Int; File : in gzFile) return Int; + + function zlibCompileFlags return ULong; + +private + + type Z_Stream is record -- zlib.h:68 + Next_In : Voidp := Nul; -- next input byte + Avail_In : UInt := 0; -- number of bytes available at next_in + Total_In : ULong := 0; -- total nb of input bytes read so far + Next_Out : Voidp := Nul; -- next output byte should be put there + Avail_Out : UInt := 0; -- remaining free space at next_out + Total_Out : ULong := 0; -- total nb of bytes output so far + msg : Chars_Ptr; -- last error message, NULL if no error + state : Voidp; -- not visible by applications + zalloc : alloc_func := null; -- used to allocate the internal state + zfree : free_func := null; -- used to free the internal state + opaque : Voidp; -- private data object passed to + -- zalloc and zfree + data_type : Int; -- best guess about the data type: + -- ascii or binary + adler : ULong; -- adler32 value of the uncompressed + -- data + reserved : ULong; -- reserved for future use + end record; + + pragma Convention (C, Z_Stream); + + pragma Import (C, zlibVersion, "zlibVersion"); + pragma Import (C, Deflate, "deflate"); + pragma Import (C, DeflateEnd, "deflateEnd"); + pragma Import (C, Inflate, "inflate"); + pragma Import (C, InflateEnd, "inflateEnd"); + pragma Import (C, deflateSetDictionary, "deflateSetDictionary"); + pragma Import (C, deflateCopy, "deflateCopy"); + pragma Import (C, deflateReset, "deflateReset"); + pragma Import (C, deflateParams, "deflateParams"); + pragma Import (C, inflateSetDictionary, "inflateSetDictionary"); + pragma Import (C, inflateSync, "inflateSync"); + pragma Import (C, inflateReset, "inflateReset"); + pragma Import (C, compress, "compress"); + pragma Import (C, compress2, "compress2"); + pragma Import (C, uncompress, "uncompress"); + pragma Import (C, gzopen, "gzopen"); + pragma Import (C, gzdopen, "gzdopen"); + pragma Import (C, gzsetparams, "gzsetparams"); + pragma Import (C, gzread, "gzread"); + pragma Import (C, gzwrite, "gzwrite"); + pragma Import (C, gzprintf, "gzprintf"); + pragma Import (C, gzputs, "gzputs"); + pragma Import (C, gzgets, "gzgets"); + pragma Import (C, gzputc, "gzputc"); + pragma Import (C, gzgetc, "gzgetc"); + pragma Import (C, gzflush, "gzflush"); + pragma Import (C, gzseek, "gzseek"); + pragma Import (C, gzrewind, "gzrewind"); + pragma Import (C, gztell, "gztell"); + pragma Import (C, gzeof, "gzeof"); + pragma Import (C, gzclose, "gzclose"); + pragma Import (C, gzerror, "gzerror"); + pragma Import (C, adler32, "adler32"); + pragma Import (C, crc32, "crc32"); + pragma Import (C, deflateInit, "deflateInit_"); + pragma Import (C, inflateInit, "inflateInit_"); + pragma Import (C, deflateInit2, "deflateInit2_"); + pragma Import (C, inflateInit2, "inflateInit2_"); + pragma Import (C, zError, "zError"); + pragma Import (C, inflateSyncPoint, "inflateSyncPoint"); + pragma Import (C, get_crc_table, "get_crc_table"); + + -- since zlib 1.2.0: + + pragma Import (C, inflateCopy, "inflateCopy"); + pragma Import (C, compressBound, "compressBound"); + pragma Import (C, deflateBound, "deflateBound"); + pragma Import (C, gzungetc, "gzungetc"); + pragma Import (C, zlibCompileFlags, "zlibCompileFlags"); + + pragma Import (C, inflateBackInit, "inflateBackInit_"); + + -- I stopped binding the inflateBack routines, because realize that + -- it does not support zlib and gzip headers for now, and have no + -- symmetric deflateBack routines. + -- ZLib-Ada is symmetric regarding deflate/inflate data transformation + -- and has a similar generic callback interface for the + -- deflate/inflate transformation based on the regular Deflate/Inflate + -- routines. + + -- pragma Import (C, inflateBack, "inflateBack"); + -- pragma Import (C, inflateBackEnd, "inflateBackEnd"); + +end ZLib.Thin; diff --git a/dependencies/zlib-1.2.11/contrib/ada/zlib.adb b/dependencies/zlib-1.2.11/contrib/ada/zlib.adb new file mode 100644 index 0000000..8b6fd68 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/ada/zlib.adb @@ -0,0 +1,701 @@ +---------------------------------------------------------------- +-- ZLib for Ada thick binding. -- +-- -- +-- Copyright (C) 2002-2004 Dmitriy Anisimkov -- +-- -- +-- Open source license information is in the zlib.ads file. -- +---------------------------------------------------------------- + +-- $Id: zlib.adb,v 1.31 2004/09/06 06:53:19 vagul Exp $ + +with Ada.Exceptions; +with Ada.Unchecked_Conversion; +with Ada.Unchecked_Deallocation; + +with Interfaces.C.Strings; + +with ZLib.Thin; + +package body ZLib is + + use type Thin.Int; + + type Z_Stream is new Thin.Z_Stream; + + type Return_Code_Enum is + (OK, + STREAM_END, + NEED_DICT, + ERRNO, + STREAM_ERROR, + DATA_ERROR, + MEM_ERROR, + BUF_ERROR, + VERSION_ERROR); + + type Flate_Step_Function is access + function (Strm : in Thin.Z_Streamp; Flush : in Thin.Int) return Thin.Int; + pragma Convention (C, Flate_Step_Function); + + type Flate_End_Function is access + function (Ctrm : in Thin.Z_Streamp) return Thin.Int; + pragma Convention (C, Flate_End_Function); + + type Flate_Type is record + Step : Flate_Step_Function; + Done : Flate_End_Function; + end record; + + subtype Footer_Array is Stream_Element_Array (1 .. 8); + + Simple_GZip_Header : constant Stream_Element_Array (1 .. 10) + := (16#1f#, 16#8b#, -- Magic header + 16#08#, -- Z_DEFLATED + 16#00#, -- Flags + 16#00#, 16#00#, 16#00#, 16#00#, -- Time + 16#00#, -- XFlags + 16#03# -- OS code + ); + -- The simplest gzip header is not for informational, but just for + -- gzip format compatibility. + -- Note that some code below is using assumption + -- Simple_GZip_Header'Last > Footer_Array'Last, so do not make + -- Simple_GZip_Header'Last <= Footer_Array'Last. + + Return_Code : constant array (Thin.Int range <>) of Return_Code_Enum + := (0 => OK, + 1 => STREAM_END, + 2 => NEED_DICT, + -1 => ERRNO, + -2 => STREAM_ERROR, + -3 => DATA_ERROR, + -4 => MEM_ERROR, + -5 => BUF_ERROR, + -6 => VERSION_ERROR); + + Flate : constant array (Boolean) of Flate_Type + := (True => (Step => Thin.Deflate'Access, + Done => Thin.DeflateEnd'Access), + False => (Step => Thin.Inflate'Access, + Done => Thin.InflateEnd'Access)); + + Flush_Finish : constant array (Boolean) of Flush_Mode + := (True => Finish, False => No_Flush); + + procedure Raise_Error (Stream : in Z_Stream); + pragma Inline (Raise_Error); + + procedure Raise_Error (Message : in String); + pragma Inline (Raise_Error); + + procedure Check_Error (Stream : in Z_Stream; Code : in Thin.Int); + + procedure Free is new Ada.Unchecked_Deallocation + (Z_Stream, Z_Stream_Access); + + function To_Thin_Access is new Ada.Unchecked_Conversion + (Z_Stream_Access, Thin.Z_Streamp); + + procedure Translate_GZip + (Filter : in out Filter_Type; + In_Data : in Ada.Streams.Stream_Element_Array; + In_Last : out Ada.Streams.Stream_Element_Offset; + Out_Data : out Ada.Streams.Stream_Element_Array; + Out_Last : out Ada.Streams.Stream_Element_Offset; + Flush : in Flush_Mode); + -- Separate translate routine for make gzip header. + + procedure Translate_Auto + (Filter : in out Filter_Type; + In_Data : in Ada.Streams.Stream_Element_Array; + In_Last : out Ada.Streams.Stream_Element_Offset; + Out_Data : out Ada.Streams.Stream_Element_Array; + Out_Last : out Ada.Streams.Stream_Element_Offset; + Flush : in Flush_Mode); + -- translate routine without additional headers. + + ----------------- + -- Check_Error -- + ----------------- + + procedure Check_Error (Stream : in Z_Stream; Code : in Thin.Int) is + use type Thin.Int; + begin + if Code /= Thin.Z_OK then + Raise_Error + (Return_Code_Enum'Image (Return_Code (Code)) + & ": " & Last_Error_Message (Stream)); + end if; + end Check_Error; + + ----------- + -- Close -- + ----------- + + procedure Close + (Filter : in out Filter_Type; + Ignore_Error : in Boolean := False) + is + Code : Thin.Int; + begin + if not Ignore_Error and then not Is_Open (Filter) then + raise Status_Error; + end if; + + Code := Flate (Filter.Compression).Done (To_Thin_Access (Filter.Strm)); + + if Ignore_Error or else Code = Thin.Z_OK then + Free (Filter.Strm); + else + declare + Error_Message : constant String + := Last_Error_Message (Filter.Strm.all); + begin + Free (Filter.Strm); + Ada.Exceptions.Raise_Exception + (ZLib_Error'Identity, + Return_Code_Enum'Image (Return_Code (Code)) + & ": " & Error_Message); + end; + end if; + end Close; + + ----------- + -- CRC32 -- + ----------- + + function CRC32 + (CRC : in Unsigned_32; + Data : in Ada.Streams.Stream_Element_Array) + return Unsigned_32 + is + use Thin; + begin + return Unsigned_32 (crc32 (ULong (CRC), + Data'Address, + Data'Length)); + end CRC32; + + procedure CRC32 + (CRC : in out Unsigned_32; + Data : in Ada.Streams.Stream_Element_Array) is + begin + CRC := CRC32 (CRC, Data); + end CRC32; + + ------------------ + -- Deflate_Init -- + ------------------ + + procedure Deflate_Init + (Filter : in out Filter_Type; + Level : in Compression_Level := Default_Compression; + Strategy : in Strategy_Type := Default_Strategy; + Method : in Compression_Method := Deflated; + Window_Bits : in Window_Bits_Type := Default_Window_Bits; + Memory_Level : in Memory_Level_Type := Default_Memory_Level; + Header : in Header_Type := Default) + is + use type Thin.Int; + Win_Bits : Thin.Int := Thin.Int (Window_Bits); + begin + if Is_Open (Filter) then + raise Status_Error; + end if; + + -- We allow ZLib to make header only in case of default header type. + -- Otherwise we would either do header by ourselfs, or do not do + -- header at all. + + if Header = None or else Header = GZip then + Win_Bits := -Win_Bits; + end if; + + -- For the GZip CRC calculation and make headers. + + if Header = GZip then + Filter.CRC := 0; + Filter.Offset := Simple_GZip_Header'First; + else + Filter.Offset := Simple_GZip_Header'Last + 1; + end if; + + Filter.Strm := new Z_Stream; + Filter.Compression := True; + Filter.Stream_End := False; + Filter.Header := Header; + + if Thin.Deflate_Init + (To_Thin_Access (Filter.Strm), + Level => Thin.Int (Level), + method => Thin.Int (Method), + windowBits => Win_Bits, + memLevel => Thin.Int (Memory_Level), + strategy => Thin.Int (Strategy)) /= Thin.Z_OK + then + Raise_Error (Filter.Strm.all); + end if; + end Deflate_Init; + + ----------- + -- Flush -- + ----------- + + procedure Flush + (Filter : in out Filter_Type; + Out_Data : out Ada.Streams.Stream_Element_Array; + Out_Last : out Ada.Streams.Stream_Element_Offset; + Flush : in Flush_Mode) + is + No_Data : Stream_Element_Array := (1 .. 0 => 0); + Last : Stream_Element_Offset; + begin + Translate (Filter, No_Data, Last, Out_Data, Out_Last, Flush); + end Flush; + + ----------------------- + -- Generic_Translate -- + ----------------------- + + procedure Generic_Translate + (Filter : in out ZLib.Filter_Type; + In_Buffer_Size : in Integer := Default_Buffer_Size; + Out_Buffer_Size : in Integer := Default_Buffer_Size) + is + In_Buffer : Stream_Element_Array + (1 .. Stream_Element_Offset (In_Buffer_Size)); + Out_Buffer : Stream_Element_Array + (1 .. Stream_Element_Offset (Out_Buffer_Size)); + Last : Stream_Element_Offset; + In_Last : Stream_Element_Offset; + In_First : Stream_Element_Offset; + Out_Last : Stream_Element_Offset; + begin + Main : loop + Data_In (In_Buffer, Last); + + In_First := In_Buffer'First; + + loop + Translate + (Filter => Filter, + In_Data => In_Buffer (In_First .. Last), + In_Last => In_Last, + Out_Data => Out_Buffer, + Out_Last => Out_Last, + Flush => Flush_Finish (Last < In_Buffer'First)); + + if Out_Buffer'First <= Out_Last then + Data_Out (Out_Buffer (Out_Buffer'First .. Out_Last)); + end if; + + exit Main when Stream_End (Filter); + + -- The end of in buffer. + + exit when In_Last = Last; + + In_First := In_Last + 1; + end loop; + end loop Main; + + end Generic_Translate; + + ------------------ + -- Inflate_Init -- + ------------------ + + procedure Inflate_Init + (Filter : in out Filter_Type; + Window_Bits : in Window_Bits_Type := Default_Window_Bits; + Header : in Header_Type := Default) + is + use type Thin.Int; + Win_Bits : Thin.Int := Thin.Int (Window_Bits); + + procedure Check_Version; + -- Check the latest header types compatibility. + + procedure Check_Version is + begin + if Version <= "1.1.4" then + Raise_Error + ("Inflate header type " & Header_Type'Image (Header) + & " incompatible with ZLib version " & Version); + end if; + end Check_Version; + + begin + if Is_Open (Filter) then + raise Status_Error; + end if; + + case Header is + when None => + Check_Version; + + -- Inflate data without headers determined + -- by negative Win_Bits. + + Win_Bits := -Win_Bits; + when GZip => + Check_Version; + + -- Inflate gzip data defined by flag 16. + + Win_Bits := Win_Bits + 16; + when Auto => + Check_Version; + + -- Inflate with automatic detection + -- of gzip or native header defined by flag 32. + + Win_Bits := Win_Bits + 32; + when Default => null; + end case; + + Filter.Strm := new Z_Stream; + Filter.Compression := False; + Filter.Stream_End := False; + Filter.Header := Header; + + if Thin.Inflate_Init + (To_Thin_Access (Filter.Strm), Win_Bits) /= Thin.Z_OK + then + Raise_Error (Filter.Strm.all); + end if; + end Inflate_Init; + + ------------- + -- Is_Open -- + ------------- + + function Is_Open (Filter : in Filter_Type) return Boolean is + begin + return Filter.Strm /= null; + end Is_Open; + + ----------------- + -- Raise_Error -- + ----------------- + + procedure Raise_Error (Message : in String) is + begin + Ada.Exceptions.Raise_Exception (ZLib_Error'Identity, Message); + end Raise_Error; + + procedure Raise_Error (Stream : in Z_Stream) is + begin + Raise_Error (Last_Error_Message (Stream)); + end Raise_Error; + + ---------- + -- Read -- + ---------- + + procedure Read + (Filter : in out Filter_Type; + Item : out Ada.Streams.Stream_Element_Array; + Last : out Ada.Streams.Stream_Element_Offset; + Flush : in Flush_Mode := No_Flush) + is + In_Last : Stream_Element_Offset; + Item_First : Ada.Streams.Stream_Element_Offset := Item'First; + V_Flush : Flush_Mode := Flush; + + begin + pragma Assert (Rest_First in Buffer'First .. Buffer'Last + 1); + pragma Assert (Rest_Last in Buffer'First - 1 .. Buffer'Last); + + loop + if Rest_Last = Buffer'First - 1 then + V_Flush := Finish; + + elsif Rest_First > Rest_Last then + Read (Buffer, Rest_Last); + Rest_First := Buffer'First; + + if Rest_Last < Buffer'First then + V_Flush := Finish; + end if; + end if; + + Translate + (Filter => Filter, + In_Data => Buffer (Rest_First .. Rest_Last), + In_Last => In_Last, + Out_Data => Item (Item_First .. Item'Last), + Out_Last => Last, + Flush => V_Flush); + + Rest_First := In_Last + 1; + + exit when Stream_End (Filter) + or else Last = Item'Last + or else (Last >= Item'First and then Allow_Read_Some); + + Item_First := Last + 1; + end loop; + end Read; + + ---------------- + -- Stream_End -- + ---------------- + + function Stream_End (Filter : in Filter_Type) return Boolean is + begin + if Filter.Header = GZip and Filter.Compression then + return Filter.Stream_End + and then Filter.Offset = Footer_Array'Last + 1; + else + return Filter.Stream_End; + end if; + end Stream_End; + + -------------- + -- Total_In -- + -------------- + + function Total_In (Filter : in Filter_Type) return Count is + begin + return Count (Thin.Total_In (To_Thin_Access (Filter.Strm).all)); + end Total_In; + + --------------- + -- Total_Out -- + --------------- + + function Total_Out (Filter : in Filter_Type) return Count is + begin + return Count (Thin.Total_Out (To_Thin_Access (Filter.Strm).all)); + end Total_Out; + + --------------- + -- Translate -- + --------------- + + procedure Translate + (Filter : in out Filter_Type; + In_Data : in Ada.Streams.Stream_Element_Array; + In_Last : out Ada.Streams.Stream_Element_Offset; + Out_Data : out Ada.Streams.Stream_Element_Array; + Out_Last : out Ada.Streams.Stream_Element_Offset; + Flush : in Flush_Mode) is + begin + if Filter.Header = GZip and then Filter.Compression then + Translate_GZip + (Filter => Filter, + In_Data => In_Data, + In_Last => In_Last, + Out_Data => Out_Data, + Out_Last => Out_Last, + Flush => Flush); + else + Translate_Auto + (Filter => Filter, + In_Data => In_Data, + In_Last => In_Last, + Out_Data => Out_Data, + Out_Last => Out_Last, + Flush => Flush); + end if; + end Translate; + + -------------------- + -- Translate_Auto -- + -------------------- + + procedure Translate_Auto + (Filter : in out Filter_Type; + In_Data : in Ada.Streams.Stream_Element_Array; + In_Last : out Ada.Streams.Stream_Element_Offset; + Out_Data : out Ada.Streams.Stream_Element_Array; + Out_Last : out Ada.Streams.Stream_Element_Offset; + Flush : in Flush_Mode) + is + use type Thin.Int; + Code : Thin.Int; + + begin + if not Is_Open (Filter) then + raise Status_Error; + end if; + + if Out_Data'Length = 0 and then In_Data'Length = 0 then + raise Constraint_Error; + end if; + + Set_Out (Filter.Strm.all, Out_Data'Address, Out_Data'Length); + Set_In (Filter.Strm.all, In_Data'Address, In_Data'Length); + + Code := Flate (Filter.Compression).Step + (To_Thin_Access (Filter.Strm), + Thin.Int (Flush)); + + if Code = Thin.Z_STREAM_END then + Filter.Stream_End := True; + else + Check_Error (Filter.Strm.all, Code); + end if; + + In_Last := In_Data'Last + - Stream_Element_Offset (Avail_In (Filter.Strm.all)); + Out_Last := Out_Data'Last + - Stream_Element_Offset (Avail_Out (Filter.Strm.all)); + end Translate_Auto; + + -------------------- + -- Translate_GZip -- + -------------------- + + procedure Translate_GZip + (Filter : in out Filter_Type; + In_Data : in Ada.Streams.Stream_Element_Array; + In_Last : out Ada.Streams.Stream_Element_Offset; + Out_Data : out Ada.Streams.Stream_Element_Array; + Out_Last : out Ada.Streams.Stream_Element_Offset; + Flush : in Flush_Mode) + is + Out_First : Stream_Element_Offset; + + procedure Add_Data (Data : in Stream_Element_Array); + -- Add data to stream from the Filter.Offset till necessary, + -- used for add gzip headr/footer. + + procedure Put_32 + (Item : in out Stream_Element_Array; + Data : in Unsigned_32); + pragma Inline (Put_32); + + -------------- + -- Add_Data -- + -------------- + + procedure Add_Data (Data : in Stream_Element_Array) is + Data_First : Stream_Element_Offset renames Filter.Offset; + Data_Last : Stream_Element_Offset; + Data_Len : Stream_Element_Offset; -- -1 + Out_Len : Stream_Element_Offset; -- -1 + begin + Out_First := Out_Last + 1; + + if Data_First > Data'Last then + return; + end if; + + Data_Len := Data'Last - Data_First; + Out_Len := Out_Data'Last - Out_First; + + if Data_Len <= Out_Len then + Out_Last := Out_First + Data_Len; + Data_Last := Data'Last; + else + Out_Last := Out_Data'Last; + Data_Last := Data_First + Out_Len; + end if; + + Out_Data (Out_First .. Out_Last) := Data (Data_First .. Data_Last); + + Data_First := Data_Last + 1; + Out_First := Out_Last + 1; + end Add_Data; + + ------------ + -- Put_32 -- + ------------ + + procedure Put_32 + (Item : in out Stream_Element_Array; + Data : in Unsigned_32) + is + D : Unsigned_32 := Data; + begin + for J in Item'First .. Item'First + 3 loop + Item (J) := Stream_Element (D and 16#FF#); + D := Shift_Right (D, 8); + end loop; + end Put_32; + + begin + Out_Last := Out_Data'First - 1; + + if not Filter.Stream_End then + Add_Data (Simple_GZip_Header); + + Translate_Auto + (Filter => Filter, + In_Data => In_Data, + In_Last => In_Last, + Out_Data => Out_Data (Out_First .. Out_Data'Last), + Out_Last => Out_Last, + Flush => Flush); + + CRC32 (Filter.CRC, In_Data (In_Data'First .. In_Last)); + end if; + + if Filter.Stream_End and then Out_Last <= Out_Data'Last then + -- This detection method would work only when + -- Simple_GZip_Header'Last > Footer_Array'Last + + if Filter.Offset = Simple_GZip_Header'Last + 1 then + Filter.Offset := Footer_Array'First; + end if; + + declare + Footer : Footer_Array; + begin + Put_32 (Footer, Filter.CRC); + Put_32 (Footer (Footer'First + 4 .. Footer'Last), + Unsigned_32 (Total_In (Filter))); + Add_Data (Footer); + end; + end if; + end Translate_GZip; + + ------------- + -- Version -- + ------------- + + function Version return String is + begin + return Interfaces.C.Strings.Value (Thin.zlibVersion); + end Version; + + ----------- + -- Write -- + ----------- + + procedure Write + (Filter : in out Filter_Type; + Item : in Ada.Streams.Stream_Element_Array; + Flush : in Flush_Mode := No_Flush) + is + Buffer : Stream_Element_Array (1 .. Buffer_Size); + In_Last : Stream_Element_Offset; + Out_Last : Stream_Element_Offset; + In_First : Stream_Element_Offset := Item'First; + begin + if Item'Length = 0 and Flush = No_Flush then + return; + end if; + + loop + Translate + (Filter => Filter, + In_Data => Item (In_First .. Item'Last), + In_Last => In_Last, + Out_Data => Buffer, + Out_Last => Out_Last, + Flush => Flush); + + if Out_Last >= Buffer'First then + Write (Buffer (1 .. Out_Last)); + end if; + + exit when In_Last = Item'Last or Stream_End (Filter); + + In_First := In_Last + 1; + end loop; + end Write; + +end ZLib; diff --git a/dependencies/zlib-1.2.11/contrib/ada/zlib.ads b/dependencies/zlib-1.2.11/contrib/ada/zlib.ads new file mode 100644 index 0000000..79ffc40 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/ada/zlib.ads @@ -0,0 +1,328 @@ +------------------------------------------------------------------------------ +-- ZLib for Ada thick binding. -- +-- -- +-- Copyright (C) 2002-2004 Dmitriy Anisimkov -- +-- -- +-- This library is free software; you can redistribute it and/or modify -- +-- it under the terms of the GNU General Public License as published by -- +-- the Free Software Foundation; either version 2 of the License, or (at -- +-- your option) any later version. -- +-- -- +-- This library is distributed in the hope that it will be useful, but -- +-- WITHOUT ANY WARRANTY; without even the implied warranty of -- +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- +-- General Public License for more details. -- +-- -- +-- You should have received a copy of the GNU General Public License -- +-- along with this library; if not, write to the Free Software Foundation, -- +-- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -- +-- -- +-- As a special exception, if other files instantiate generics from this -- +-- unit, or you link this unit with other files to produce an executable, -- +-- this unit does not by itself cause the resulting executable to be -- +-- covered by the GNU General Public License. This exception does not -- +-- however invalidate any other reasons why the executable file might be -- +-- covered by the GNU Public License. -- +------------------------------------------------------------------------------ + +-- $Id: zlib.ads,v 1.26 2004/09/06 06:53:19 vagul Exp $ + +with Ada.Streams; + +with Interfaces; + +package ZLib is + + ZLib_Error : exception; + Status_Error : exception; + + type Compression_Level is new Integer range -1 .. 9; + + type Flush_Mode is private; + + type Compression_Method is private; + + type Window_Bits_Type is new Integer range 8 .. 15; + + type Memory_Level_Type is new Integer range 1 .. 9; + + type Unsigned_32 is new Interfaces.Unsigned_32; + + type Strategy_Type is private; + + type Header_Type is (None, Auto, Default, GZip); + -- Header type usage have a some limitation for inflate. + -- See comment for Inflate_Init. + + subtype Count is Ada.Streams.Stream_Element_Count; + + Default_Memory_Level : constant Memory_Level_Type := 8; + Default_Window_Bits : constant Window_Bits_Type := 15; + + ---------------------------------- + -- Compression method constants -- + ---------------------------------- + + Deflated : constant Compression_Method; + -- Only one method allowed in this ZLib version + + --------------------------------- + -- Compression level constants -- + --------------------------------- + + No_Compression : constant Compression_Level := 0; + Best_Speed : constant Compression_Level := 1; + Best_Compression : constant Compression_Level := 9; + Default_Compression : constant Compression_Level := -1; + + -------------------------- + -- Flush mode constants -- + -------------------------- + + No_Flush : constant Flush_Mode; + -- Regular way for compression, no flush + + Partial_Flush : constant Flush_Mode; + -- Will be removed, use Z_SYNC_FLUSH instead + + Sync_Flush : constant Flush_Mode; + -- All pending output is flushed to the output buffer and the output + -- is aligned on a byte boundary, so that the decompressor can get all + -- input data available so far. (In particular avail_in is zero after the + -- call if enough output space has been provided before the call.) + -- Flushing may degrade compression for some compression algorithms and so + -- it should be used only when necessary. + + Block_Flush : constant Flush_Mode; + -- Z_BLOCK requests that inflate() stop + -- if and when it get to the next deflate block boundary. When decoding the + -- zlib or gzip format, this will cause inflate() to return immediately + -- after the header and before the first block. When doing a raw inflate, + -- inflate() will go ahead and process the first block, and will return + -- when it gets to the end of that block, or when it runs out of data. + + Full_Flush : constant Flush_Mode; + -- All output is flushed as with SYNC_FLUSH, and the compression state + -- is reset so that decompression can restart from this point if previous + -- compressed data has been damaged or if random access is desired. Using + -- Full_Flush too often can seriously degrade the compression. + + Finish : constant Flush_Mode; + -- Just for tell the compressor that input data is complete. + + ------------------------------------ + -- Compression strategy constants -- + ------------------------------------ + + -- RLE stategy could be used only in version 1.2.0 and later. + + Filtered : constant Strategy_Type; + Huffman_Only : constant Strategy_Type; + RLE : constant Strategy_Type; + Default_Strategy : constant Strategy_Type; + + Default_Buffer_Size : constant := 4096; + + type Filter_Type is tagged limited private; + -- The filter is for compression and for decompression. + -- The usage of the type is depend of its initialization. + + function Version return String; + pragma Inline (Version); + -- Return string representation of the ZLib version. + + procedure Deflate_Init + (Filter : in out Filter_Type; + Level : in Compression_Level := Default_Compression; + Strategy : in Strategy_Type := Default_Strategy; + Method : in Compression_Method := Deflated; + Window_Bits : in Window_Bits_Type := Default_Window_Bits; + Memory_Level : in Memory_Level_Type := Default_Memory_Level; + Header : in Header_Type := Default); + -- Compressor initialization. + -- When Header parameter is Auto or Default, then default zlib header + -- would be provided for compressed data. + -- When Header is GZip, then gzip header would be set instead of + -- default header. + -- When Header is None, no header would be set for compressed data. + + procedure Inflate_Init + (Filter : in out Filter_Type; + Window_Bits : in Window_Bits_Type := Default_Window_Bits; + Header : in Header_Type := Default); + -- Decompressor initialization. + -- Default header type mean that ZLib default header is expecting in the + -- input compressed stream. + -- Header type None mean that no header is expecting in the input stream. + -- GZip header type mean that GZip header is expecting in the + -- input compressed stream. + -- Auto header type mean that header type (GZip or Native) would be + -- detected automatically in the input stream. + -- Note that header types parameter values None, GZip and Auto are + -- supported for inflate routine only in ZLib versions 1.2.0.2 and later. + -- Deflate_Init is supporting all header types. + + function Is_Open (Filter : in Filter_Type) return Boolean; + pragma Inline (Is_Open); + -- Is the filter opened for compression or decompression. + + procedure Close + (Filter : in out Filter_Type; + Ignore_Error : in Boolean := False); + -- Closing the compression or decompressor. + -- If stream is closing before the complete and Ignore_Error is False, + -- The exception would be raised. + + generic + with procedure Data_In + (Item : out Ada.Streams.Stream_Element_Array; + Last : out Ada.Streams.Stream_Element_Offset); + with procedure Data_Out + (Item : in Ada.Streams.Stream_Element_Array); + procedure Generic_Translate + (Filter : in out Filter_Type; + In_Buffer_Size : in Integer := Default_Buffer_Size; + Out_Buffer_Size : in Integer := Default_Buffer_Size); + -- Compress/decompress data fetch from Data_In routine and pass the result + -- to the Data_Out routine. User should provide Data_In and Data_Out + -- for compression/decompression data flow. + -- Compression or decompression depend on Filter initialization. + + function Total_In (Filter : in Filter_Type) return Count; + pragma Inline (Total_In); + -- Returns total number of input bytes read so far + + function Total_Out (Filter : in Filter_Type) return Count; + pragma Inline (Total_Out); + -- Returns total number of bytes output so far + + function CRC32 + (CRC : in Unsigned_32; + Data : in Ada.Streams.Stream_Element_Array) + return Unsigned_32; + pragma Inline (CRC32); + -- Compute CRC32, it could be necessary for make gzip format + + procedure CRC32 + (CRC : in out Unsigned_32; + Data : in Ada.Streams.Stream_Element_Array); + pragma Inline (CRC32); + -- Compute CRC32, it could be necessary for make gzip format + + ------------------------------------------------- + -- Below is more complex low level routines. -- + ------------------------------------------------- + + procedure Translate + (Filter : in out Filter_Type; + In_Data : in Ada.Streams.Stream_Element_Array; + In_Last : out Ada.Streams.Stream_Element_Offset; + Out_Data : out Ada.Streams.Stream_Element_Array; + Out_Last : out Ada.Streams.Stream_Element_Offset; + Flush : in Flush_Mode); + -- Compress/decompress the In_Data buffer and place the result into + -- Out_Data. In_Last is the index of last element from In_Data accepted by + -- the Filter. Out_Last is the last element of the received data from + -- Filter. To tell the filter that incoming data are complete put the + -- Flush parameter to Finish. + + function Stream_End (Filter : in Filter_Type) return Boolean; + pragma Inline (Stream_End); + -- Return the true when the stream is complete. + + procedure Flush + (Filter : in out Filter_Type; + Out_Data : out Ada.Streams.Stream_Element_Array; + Out_Last : out Ada.Streams.Stream_Element_Offset; + Flush : in Flush_Mode); + pragma Inline (Flush); + -- Flushing the data from the compressor. + + generic + with procedure Write + (Item : in Ada.Streams.Stream_Element_Array); + -- User should provide this routine for accept + -- compressed/decompressed data. + + Buffer_Size : in Ada.Streams.Stream_Element_Offset + := Default_Buffer_Size; + -- Buffer size for Write user routine. + + procedure Write + (Filter : in out Filter_Type; + Item : in Ada.Streams.Stream_Element_Array; + Flush : in Flush_Mode := No_Flush); + -- Compress/Decompress data from Item to the generic parameter procedure + -- Write. Output buffer size could be set in Buffer_Size generic parameter. + + generic + with procedure Read + (Item : out Ada.Streams.Stream_Element_Array; + Last : out Ada.Streams.Stream_Element_Offset); + -- User should provide data for compression/decompression + -- thru this routine. + + Buffer : in out Ada.Streams.Stream_Element_Array; + -- Buffer for keep remaining data from the previous + -- back read. + + Rest_First, Rest_Last : in out Ada.Streams.Stream_Element_Offset; + -- Rest_First have to be initialized to Buffer'Last + 1 + -- Rest_Last have to be initialized to Buffer'Last + -- before usage. + + Allow_Read_Some : in Boolean := False; + -- Is it allowed to return Last < Item'Last before end of data. + + procedure Read + (Filter : in out Filter_Type; + Item : out Ada.Streams.Stream_Element_Array; + Last : out Ada.Streams.Stream_Element_Offset; + Flush : in Flush_Mode := No_Flush); + -- Compress/Decompress data from generic parameter procedure Read to the + -- Item. User should provide Buffer and initialized Rest_First, Rest_Last + -- indicators. If Allow_Read_Some is True, Read routines could return + -- Last < Item'Last only at end of stream. + +private + + use Ada.Streams; + + pragma Assert (Ada.Streams.Stream_Element'Size = 8); + pragma Assert (Ada.Streams.Stream_Element'Modulus = 2**8); + + type Flush_Mode is new Integer range 0 .. 5; + + type Compression_Method is new Integer range 8 .. 8; + + type Strategy_Type is new Integer range 0 .. 3; + + No_Flush : constant Flush_Mode := 0; + Partial_Flush : constant Flush_Mode := 1; + Sync_Flush : constant Flush_Mode := 2; + Full_Flush : constant Flush_Mode := 3; + Finish : constant Flush_Mode := 4; + Block_Flush : constant Flush_Mode := 5; + + Filtered : constant Strategy_Type := 1; + Huffman_Only : constant Strategy_Type := 2; + RLE : constant Strategy_Type := 3; + Default_Strategy : constant Strategy_Type := 0; + + Deflated : constant Compression_Method := 8; + + type Z_Stream; + + type Z_Stream_Access is access all Z_Stream; + + type Filter_Type is tagged limited record + Strm : Z_Stream_Access; + Compression : Boolean; + Stream_End : Boolean; + Header : Header_Type; + CRC : Unsigned_32; + Offset : Stream_Element_Offset; + -- Offset for gzip header/footer output. + end record; + +end ZLib; diff --git a/dependencies/zlib-1.2.11/contrib/ada/zlib.gpr b/dependencies/zlib-1.2.11/contrib/ada/zlib.gpr new file mode 100644 index 0000000..296b22a --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/ada/zlib.gpr @@ -0,0 +1,20 @@ +project Zlib is + + for Languages use ("Ada"); + for Source_Dirs use ("."); + for Object_Dir use "."; + for Main use ("test.adb", "mtest.adb", "read.adb", "buffer_demo"); + + package Compiler is + for Default_Switches ("ada") use ("-gnatwcfilopru", "-gnatVcdfimorst", "-gnatyabcefhiklmnoprst"); + end Compiler; + + package Linker is + for Default_Switches ("ada") use ("-lz"); + end Linker; + + package Builder is + for Default_Switches ("ada") use ("-s", "-gnatQ"); + end Builder; + +end Zlib; diff --git a/dependencies/zlib-1.2.11/contrib/amd64/amd64-match.S b/dependencies/zlib-1.2.11/contrib/amd64/amd64-match.S new file mode 100644 index 0000000..81d4a1c --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/amd64/amd64-match.S @@ -0,0 +1,452 @@ +/* + * match.S -- optimized version of longest_match() + * based on the similar work by Gilles Vollant, and Brian Raiter, written 1998 + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the BSD License. Use by owners of Che Guevarra + * parafernalia is prohibited, where possible, and highly discouraged + * elsewhere. + */ + +#ifndef NO_UNDERLINE +# define match_init _match_init +# define longest_match _longest_match +#endif + +#define scanend ebx +#define scanendw bx +#define chainlenwmask edx /* high word: current chain len low word: s->wmask */ +#define curmatch rsi +#define curmatchd esi +#define windowbestlen r8 +#define scanalign r9 +#define scanalignd r9d +#define window r10 +#define bestlen r11 +#define bestlend r11d +#define scanstart r12d +#define scanstartw r12w +#define scan r13 +#define nicematch r14d +#define limit r15 +#define limitd r15d +#define prev rcx + +/* + * The 258 is a "magic number, not a parameter -- changing it + * breaks the hell loose + */ +#define MAX_MATCH (258) +#define MIN_MATCH (3) +#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) +#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) + +/* stack frame offsets */ +#define LocalVarsSize (112) +#define _chainlenwmask ( 8-LocalVarsSize)(%rsp) +#define _windowbestlen (16-LocalVarsSize)(%rsp) +#define save_r14 (24-LocalVarsSize)(%rsp) +#define save_rsi (32-LocalVarsSize)(%rsp) +#define save_rbx (40-LocalVarsSize)(%rsp) +#define save_r12 (56-LocalVarsSize)(%rsp) +#define save_r13 (64-LocalVarsSize)(%rsp) +#define save_r15 (80-LocalVarsSize)(%rsp) + + +.globl match_init, longest_match + +/* + * On AMD64 the first argument of a function (in our case -- the pointer to + * deflate_state structure) is passed in %rdi, hence our offsets below are + * all off of that. + */ + +/* you can check the structure offset by running + +#include +#include +#include "deflate.h" + +void print_depl() +{ +deflate_state ds; +deflate_state *s=&ds; +printf("size pointer=%u\n",(int)sizeof(void*)); + +printf("#define dsWSize (%3u)(%%rdi)\n",(int)(((char*)&(s->w_size))-((char*)s))); +printf("#define dsWMask (%3u)(%%rdi)\n",(int)(((char*)&(s->w_mask))-((char*)s))); +printf("#define dsWindow (%3u)(%%rdi)\n",(int)(((char*)&(s->window))-((char*)s))); +printf("#define dsPrev (%3u)(%%rdi)\n",(int)(((char*)&(s->prev))-((char*)s))); +printf("#define dsMatchLen (%3u)(%%rdi)\n",(int)(((char*)&(s->match_length))-((char*)s))); +printf("#define dsPrevMatch (%3u)(%%rdi)\n",(int)(((char*)&(s->prev_match))-((char*)s))); +printf("#define dsStrStart (%3u)(%%rdi)\n",(int)(((char*)&(s->strstart))-((char*)s))); +printf("#define dsMatchStart (%3u)(%%rdi)\n",(int)(((char*)&(s->match_start))-((char*)s))); +printf("#define dsLookahead (%3u)(%%rdi)\n",(int)(((char*)&(s->lookahead))-((char*)s))); +printf("#define dsPrevLen (%3u)(%%rdi)\n",(int)(((char*)&(s->prev_length))-((char*)s))); +printf("#define dsMaxChainLen (%3u)(%%rdi)\n",(int)(((char*)&(s->max_chain_length))-((char*)s))); +printf("#define dsGoodMatch (%3u)(%%rdi)\n",(int)(((char*)&(s->good_match))-((char*)s))); +printf("#define dsNiceMatch (%3u)(%%rdi)\n",(int)(((char*)&(s->nice_match))-((char*)s))); +} + +*/ + + +/* + to compile for XCode 3.2 on MacOSX x86_64 + - run "gcc -g -c -DXCODE_MAC_X64_STRUCTURE amd64-match.S" + */ + + +#ifndef CURRENT_LINX_XCODE_MAC_X64_STRUCTURE +#define dsWSize ( 68)(%rdi) +#define dsWMask ( 76)(%rdi) +#define dsWindow ( 80)(%rdi) +#define dsPrev ( 96)(%rdi) +#define dsMatchLen (144)(%rdi) +#define dsPrevMatch (148)(%rdi) +#define dsStrStart (156)(%rdi) +#define dsMatchStart (160)(%rdi) +#define dsLookahead (164)(%rdi) +#define dsPrevLen (168)(%rdi) +#define dsMaxChainLen (172)(%rdi) +#define dsGoodMatch (188)(%rdi) +#define dsNiceMatch (192)(%rdi) + +#else + +#ifndef STRUCT_OFFSET +# define STRUCT_OFFSET (0) +#endif + + +#define dsWSize ( 56 + STRUCT_OFFSET)(%rdi) +#define dsWMask ( 64 + STRUCT_OFFSET)(%rdi) +#define dsWindow ( 72 + STRUCT_OFFSET)(%rdi) +#define dsPrev ( 88 + STRUCT_OFFSET)(%rdi) +#define dsMatchLen (136 + STRUCT_OFFSET)(%rdi) +#define dsPrevMatch (140 + STRUCT_OFFSET)(%rdi) +#define dsStrStart (148 + STRUCT_OFFSET)(%rdi) +#define dsMatchStart (152 + STRUCT_OFFSET)(%rdi) +#define dsLookahead (156 + STRUCT_OFFSET)(%rdi) +#define dsPrevLen (160 + STRUCT_OFFSET)(%rdi) +#define dsMaxChainLen (164 + STRUCT_OFFSET)(%rdi) +#define dsGoodMatch (180 + STRUCT_OFFSET)(%rdi) +#define dsNiceMatch (184 + STRUCT_OFFSET)(%rdi) + +#endif + + + + +.text + +/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ + +longest_match: +/* + * Retrieve the function arguments. %curmatch will hold cur_match + * throughout the entire function (passed via rsi on amd64). + * rdi will hold the pointer to the deflate_state (first arg on amd64) + */ + mov %rsi, save_rsi + mov %rbx, save_rbx + mov %r12, save_r12 + mov %r13, save_r13 + mov %r14, save_r14 + mov %r15, save_r15 + +/* uInt wmask = s->w_mask; */ +/* unsigned chain_length = s->max_chain_length; */ +/* if (s->prev_length >= s->good_match) { */ +/* chain_length >>= 2; */ +/* } */ + + movl dsPrevLen, %eax + movl dsGoodMatch, %ebx + cmpl %ebx, %eax + movl dsWMask, %eax + movl dsMaxChainLen, %chainlenwmask + jl LastMatchGood + shrl $2, %chainlenwmask +LastMatchGood: + +/* chainlen is decremented once beforehand so that the function can */ +/* use the sign flag instead of the zero flag for the exit test. */ +/* It is then shifted into the high word, to make room for the wmask */ +/* value, which it will always accompany. */ + + decl %chainlenwmask + shll $16, %chainlenwmask + orl %eax, %chainlenwmask + +/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ + + movl dsNiceMatch, %eax + movl dsLookahead, %ebx + cmpl %eax, %ebx + jl LookaheadLess + movl %eax, %ebx +LookaheadLess: movl %ebx, %nicematch + +/* register Bytef *scan = s->window + s->strstart; */ + + mov dsWindow, %window + movl dsStrStart, %limitd + lea (%limit, %window), %scan + +/* Determine how many bytes the scan ptr is off from being */ +/* dword-aligned. */ + + mov %scan, %scanalign + negl %scanalignd + andl $3, %scanalignd + +/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ +/* s->strstart - (IPos)MAX_DIST(s) : NIL; */ + + movl dsWSize, %eax + subl $MIN_LOOKAHEAD, %eax + xorl %ecx, %ecx + subl %eax, %limitd + cmovng %ecx, %limitd + +/* int best_len = s->prev_length; */ + + movl dsPrevLen, %bestlend + +/* Store the sum of s->window + best_len in %windowbestlen locally, and in memory. */ + + lea (%window, %bestlen), %windowbestlen + mov %windowbestlen, _windowbestlen + +/* register ush scan_start = *(ushf*)scan; */ +/* register ush scan_end = *(ushf*)(scan+best_len-1); */ +/* Posf *prev = s->prev; */ + + movzwl (%scan), %scanstart + movzwl -1(%scan, %bestlen), %scanend + mov dsPrev, %prev + +/* Jump into the main loop. */ + + movl %chainlenwmask, _chainlenwmask + jmp LoopEntry + +.balign 16 + +/* do { + * match = s->window + cur_match; + * if (*(ushf*)(match+best_len-1) != scan_end || + * *(ushf*)match != scan_start) continue; + * [...] + * } while ((cur_match = prev[cur_match & wmask]) > limit + * && --chain_length != 0); + * + * Here is the inner loop of the function. The function will spend the + * majority of its time in this loop, and majority of that time will + * be spent in the first ten instructions. + */ +LookupLoop: + andl %chainlenwmask, %curmatchd + movzwl (%prev, %curmatch, 2), %curmatchd + cmpl %limitd, %curmatchd + jbe LeaveNow + subl $0x00010000, %chainlenwmask + js LeaveNow +LoopEntry: cmpw -1(%windowbestlen, %curmatch), %scanendw + jne LookupLoop + cmpw %scanstartw, (%window, %curmatch) + jne LookupLoop + +/* Store the current value of chainlen. */ + movl %chainlenwmask, _chainlenwmask + +/* %scan is the string under scrutiny, and %prev to the string we */ +/* are hoping to match it up with. In actuality, %esi and %edi are */ +/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ +/* initialized to -(MAX_MATCH_8 - scanalign). */ + + mov $(-MAX_MATCH_8), %rdx + lea (%curmatch, %window), %windowbestlen + lea MAX_MATCH_8(%windowbestlen, %scanalign), %windowbestlen + lea MAX_MATCH_8(%scan, %scanalign), %prev + +/* the prefetching below makes very little difference... */ + prefetcht1 (%windowbestlen, %rdx) + prefetcht1 (%prev, %rdx) + +/* + * Test the strings for equality, 8 bytes at a time. At the end, + * adjust %rdx so that it is offset to the exact byte that mismatched. + * + * It should be confessed that this loop usually does not represent + * much of the total running time. Replacing it with a more + * straightforward "rep cmpsb" would not drastically degrade + * performance -- unrolling it, for example, makes no difference. + */ + +#undef USE_SSE /* works, but is 6-7% slower, than non-SSE... */ + +LoopCmps: +#ifdef USE_SSE + /* Preload the SSE registers */ + movdqu (%windowbestlen, %rdx), %xmm1 + movdqu (%prev, %rdx), %xmm2 + pcmpeqb %xmm2, %xmm1 + movdqu 16(%windowbestlen, %rdx), %xmm3 + movdqu 16(%prev, %rdx), %xmm4 + pcmpeqb %xmm4, %xmm3 + movdqu 32(%windowbestlen, %rdx), %xmm5 + movdqu 32(%prev, %rdx), %xmm6 + pcmpeqb %xmm6, %xmm5 + movdqu 48(%windowbestlen, %rdx), %xmm7 + movdqu 48(%prev, %rdx), %xmm8 + pcmpeqb %xmm8, %xmm7 + + /* Check the comparisions' results */ + pmovmskb %xmm1, %rax + notw %ax + bsfw %ax, %ax + jnz LeaveLoopCmps + + /* this is the only iteration of the loop with a possibility of having + incremented rdx by 0x108 (each loop iteration add 16*4 = 0x40 + and (0x40*4)+8=0x108 */ + add $8, %rdx + jz LenMaximum + add $8, %rdx + + + pmovmskb %xmm3, %rax + notw %ax + bsfw %ax, %ax + jnz LeaveLoopCmps + + + add $16, %rdx + + + pmovmskb %xmm5, %rax + notw %ax + bsfw %ax, %ax + jnz LeaveLoopCmps + + add $16, %rdx + + + pmovmskb %xmm7, %rax + notw %ax + bsfw %ax, %ax + jnz LeaveLoopCmps + + add $16, %rdx + + jmp LoopCmps +LeaveLoopCmps: add %rax, %rdx +#else + mov (%windowbestlen, %rdx), %rax + xor (%prev, %rdx), %rax + jnz LeaveLoopCmps + + mov 8(%windowbestlen, %rdx), %rax + xor 8(%prev, %rdx), %rax + jnz LeaveLoopCmps8 + + mov 16(%windowbestlen, %rdx), %rax + xor 16(%prev, %rdx), %rax + jnz LeaveLoopCmps16 + + add $24, %rdx + jnz LoopCmps + jmp LenMaximum +# if 0 +/* + * This three-liner is tantalizingly simple, but bsf is a slow instruction, + * and the complicated alternative down below is quite a bit faster. Sad... + */ + +LeaveLoopCmps: bsf %rax, %rax /* find the first non-zero bit */ + shrl $3, %eax /* divide by 8 to get the byte */ + add %rax, %rdx +# else +LeaveLoopCmps16: + add $8, %rdx +LeaveLoopCmps8: + add $8, %rdx +LeaveLoopCmps: testl $0xFFFFFFFF, %eax /* Check the first 4 bytes */ + jnz Check16 + add $4, %rdx + shr $32, %rax +Check16: testw $0xFFFF, %ax + jnz LenLower + add $2, %rdx + shrl $16, %eax +LenLower: subb $1, %al + adc $0, %rdx +# endif +#endif + +/* Calculate the length of the match. If it is longer than MAX_MATCH, */ +/* then automatically accept it as the best possible match and leave. */ + + lea (%prev, %rdx), %rax + sub %scan, %rax + cmpl $MAX_MATCH, %eax + jge LenMaximum + +/* If the length of the match is not longer than the best match we */ +/* have so far, then forget it and return to the lookup loop. */ + + cmpl %bestlend, %eax + jg LongerMatch + mov _windowbestlen, %windowbestlen + mov dsPrev, %prev + movl _chainlenwmask, %edx + jmp LookupLoop + +/* s->match_start = cur_match; */ +/* best_len = len; */ +/* if (len >= nice_match) break; */ +/* scan_end = *(ushf*)(scan+best_len-1); */ + +LongerMatch: + movl %eax, %bestlend + movl %curmatchd, dsMatchStart + cmpl %nicematch, %eax + jge LeaveNow + + lea (%window, %bestlen), %windowbestlen + mov %windowbestlen, _windowbestlen + + movzwl -1(%scan, %rax), %scanend + mov dsPrev, %prev + movl _chainlenwmask, %chainlenwmask + jmp LookupLoop + +/* Accept the current string, with the maximum possible length. */ + +LenMaximum: + movl $MAX_MATCH, %bestlend + movl %curmatchd, dsMatchStart + +/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ +/* return s->lookahead; */ + +LeaveNow: + movl dsLookahead, %eax + cmpl %eax, %bestlend + cmovngl %bestlend, %eax +LookaheadRet: + +/* Restore the registers and return from whence we came. */ + + mov save_rsi, %rsi + mov save_rbx, %rbx + mov save_r12, %r12 + mov save_r13, %r13 + mov save_r14, %r14 + mov save_r15, %r15 + + ret + +match_init: ret diff --git a/dependencies/zlib-1.2.11/contrib/asm686/README.686 b/dependencies/zlib-1.2.11/contrib/asm686/README.686 new file mode 100644 index 0000000..a0bf3be --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/asm686/README.686 @@ -0,0 +1,51 @@ +This is a patched version of zlib, modified to use +Pentium-Pro-optimized assembly code in the deflation algorithm. The +files changed/added by this patch are: + +README.686 +match.S + +The speedup that this patch provides varies, depending on whether the +compiler used to build the original version of zlib falls afoul of the +PPro's speed traps. My own tests show a speedup of around 10-20% at +the default compression level, and 20-30% using -9, against a version +compiled using gcc 2.7.2.3. Your mileage may vary. + +Note that this code has been tailored for the PPro/PII in particular, +and will not perform particuarly well on a Pentium. + +If you are using an assembler other than GNU as, you will have to +translate match.S to use your assembler's syntax. (Have fun.) + +Brian Raiter +breadbox@muppetlabs.com +April, 1998 + + +Added for zlib 1.1.3: + +The patches come from +http://www.muppetlabs.com/~breadbox/software/assembly.html + +To compile zlib with this asm file, copy match.S to the zlib directory +then do: + +CFLAGS="-O3 -DASMV" ./configure +make OBJA=match.o + + +Update: + +I've been ignoring these assembly routines for years, believing that +gcc's generated code had caught up with it sometime around gcc 2.95 +and the major rearchitecting of the Pentium 4. However, I recently +learned that, despite what I believed, this code still has some life +in it. On the Pentium 4 and AMD64 chips, it continues to run about 8% +faster than the code produced by gcc 4.1. + +In acknowledgement of its continuing usefulness, I've altered the +license to match that of the rest of zlib. Share and Enjoy! + +Brian Raiter +breadbox@muppetlabs.com +April, 2007 diff --git a/dependencies/zlib-1.2.11/contrib/asm686/match.S b/dependencies/zlib-1.2.11/contrib/asm686/match.S new file mode 100644 index 0000000..fa42109 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/asm686/match.S @@ -0,0 +1,357 @@ +/* match.S -- x86 assembly version of the zlib longest_match() function. + * Optimized for the Intel 686 chips (PPro and later). + * + * Copyright (C) 1998, 2007 Brian Raiter + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ + +#ifndef NO_UNDERLINE +#define match_init _match_init +#define longest_match _longest_match +#endif + +#define MAX_MATCH (258) +#define MIN_MATCH (3) +#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) +#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) + +/* stack frame offsets */ + +#define chainlenwmask 0 /* high word: current chain len */ + /* low word: s->wmask */ +#define window 4 /* local copy of s->window */ +#define windowbestlen 8 /* s->window + bestlen */ +#define scanstart 16 /* first two bytes of string */ +#define scanend 12 /* last two bytes of string */ +#define scanalign 20 /* dword-misalignment of string */ +#define nicematch 24 /* a good enough match size */ +#define bestlen 28 /* size of best match so far */ +#define scan 32 /* ptr to string wanting match */ + +#define LocalVarsSize (36) +/* saved ebx 36 */ +/* saved edi 40 */ +/* saved esi 44 */ +/* saved ebp 48 */ +/* return address 52 */ +#define deflatestate 56 /* the function arguments */ +#define curmatch 60 + +/* All the +zlib1222add offsets are due to the addition of fields + * in zlib in the deflate_state structure since the asm code was first written + * (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). + * (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). + * if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). + */ + +#define zlib1222add (8) + +#define dsWSize (36+zlib1222add) +#define dsWMask (44+zlib1222add) +#define dsWindow (48+zlib1222add) +#define dsPrev (56+zlib1222add) +#define dsMatchLen (88+zlib1222add) +#define dsPrevMatch (92+zlib1222add) +#define dsStrStart (100+zlib1222add) +#define dsMatchStart (104+zlib1222add) +#define dsLookahead (108+zlib1222add) +#define dsPrevLen (112+zlib1222add) +#define dsMaxChainLen (116+zlib1222add) +#define dsGoodMatch (132+zlib1222add) +#define dsNiceMatch (136+zlib1222add) + + +.file "match.S" + +.globl match_init, longest_match + +.text + +/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ +.cfi_sections .debug_frame + +longest_match: + +.cfi_startproc +/* Save registers that the compiler may be using, and adjust %esp to */ +/* make room for our stack frame. */ + + pushl %ebp + .cfi_def_cfa_offset 8 + .cfi_offset ebp, -8 + pushl %edi + .cfi_def_cfa_offset 12 + pushl %esi + .cfi_def_cfa_offset 16 + pushl %ebx + .cfi_def_cfa_offset 20 + subl $LocalVarsSize, %esp + .cfi_def_cfa_offset LocalVarsSize+20 + +/* Retrieve the function arguments. %ecx will hold cur_match */ +/* throughout the entire function. %edx will hold the pointer to the */ +/* deflate_state structure during the function's setup (before */ +/* entering the main loop). */ + + movl deflatestate(%esp), %edx + movl curmatch(%esp), %ecx + +/* uInt wmask = s->w_mask; */ +/* unsigned chain_length = s->max_chain_length; */ +/* if (s->prev_length >= s->good_match) { */ +/* chain_length >>= 2; */ +/* } */ + + movl dsPrevLen(%edx), %eax + movl dsGoodMatch(%edx), %ebx + cmpl %ebx, %eax + movl dsWMask(%edx), %eax + movl dsMaxChainLen(%edx), %ebx + jl LastMatchGood + shrl $2, %ebx +LastMatchGood: + +/* chainlen is decremented once beforehand so that the function can */ +/* use the sign flag instead of the zero flag for the exit test. */ +/* It is then shifted into the high word, to make room for the wmask */ +/* value, which it will always accompany. */ + + decl %ebx + shll $16, %ebx + orl %eax, %ebx + movl %ebx, chainlenwmask(%esp) + +/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ + + movl dsNiceMatch(%edx), %eax + movl dsLookahead(%edx), %ebx + cmpl %eax, %ebx + jl LookaheadLess + movl %eax, %ebx +LookaheadLess: movl %ebx, nicematch(%esp) + +/* register Bytef *scan = s->window + s->strstart; */ + + movl dsWindow(%edx), %esi + movl %esi, window(%esp) + movl dsStrStart(%edx), %ebp + lea (%esi,%ebp), %edi + movl %edi, scan(%esp) + +/* Determine how many bytes the scan ptr is off from being */ +/* dword-aligned. */ + + movl %edi, %eax + negl %eax + andl $3, %eax + movl %eax, scanalign(%esp) + +/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ +/* s->strstart - (IPos)MAX_DIST(s) : NIL; */ + + movl dsWSize(%edx), %eax + subl $MIN_LOOKAHEAD, %eax + subl %eax, %ebp + jg LimitPositive + xorl %ebp, %ebp +LimitPositive: + +/* int best_len = s->prev_length; */ + + movl dsPrevLen(%edx), %eax + movl %eax, bestlen(%esp) + +/* Store the sum of s->window + best_len in %esi locally, and in %esi. */ + + addl %eax, %esi + movl %esi, windowbestlen(%esp) + +/* register ush scan_start = *(ushf*)scan; */ +/* register ush scan_end = *(ushf*)(scan+best_len-1); */ +/* Posf *prev = s->prev; */ + + movzwl (%edi), %ebx + movl %ebx, scanstart(%esp) + movzwl -1(%edi,%eax), %ebx + movl %ebx, scanend(%esp) + movl dsPrev(%edx), %edi + +/* Jump into the main loop. */ + + movl chainlenwmask(%esp), %edx + jmp LoopEntry + +.balign 16 + +/* do { + * match = s->window + cur_match; + * if (*(ushf*)(match+best_len-1) != scan_end || + * *(ushf*)match != scan_start) continue; + * [...] + * } while ((cur_match = prev[cur_match & wmask]) > limit + * && --chain_length != 0); + * + * Here is the inner loop of the function. The function will spend the + * majority of its time in this loop, and majority of that time will + * be spent in the first ten instructions. + * + * Within this loop: + * %ebx = scanend + * %ecx = curmatch + * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) + * %esi = windowbestlen - i.e., (window + bestlen) + * %edi = prev + * %ebp = limit + */ +LookupLoop: + andl %edx, %ecx + movzwl (%edi,%ecx,2), %ecx + cmpl %ebp, %ecx + jbe LeaveNow + subl $0x00010000, %edx + js LeaveNow +LoopEntry: movzwl -1(%esi,%ecx), %eax + cmpl %ebx, %eax + jnz LookupLoop + movl window(%esp), %eax + movzwl (%eax,%ecx), %eax + cmpl scanstart(%esp), %eax + jnz LookupLoop + +/* Store the current value of chainlen. */ + + movl %edx, chainlenwmask(%esp) + +/* Point %edi to the string under scrutiny, and %esi to the string we */ +/* are hoping to match it up with. In actuality, %esi and %edi are */ +/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ +/* initialized to -(MAX_MATCH_8 - scanalign). */ + + movl window(%esp), %esi + movl scan(%esp), %edi + addl %ecx, %esi + movl scanalign(%esp), %eax + movl $(-MAX_MATCH_8), %edx + lea MAX_MATCH_8(%edi,%eax), %edi + lea MAX_MATCH_8(%esi,%eax), %esi + +/* Test the strings for equality, 8 bytes at a time. At the end, + * adjust %edx so that it is offset to the exact byte that mismatched. + * + * We already know at this point that the first three bytes of the + * strings match each other, and they can be safely passed over before + * starting the compare loop. So what this code does is skip over 0-3 + * bytes, as much as necessary in order to dword-align the %edi + * pointer. (%esi will still be misaligned three times out of four.) + * + * It should be confessed that this loop usually does not represent + * much of the total running time. Replacing it with a more + * straightforward "rep cmpsb" would not drastically degrade + * performance. + */ +LoopCmps: + movl (%esi,%edx), %eax + xorl (%edi,%edx), %eax + jnz LeaveLoopCmps + movl 4(%esi,%edx), %eax + xorl 4(%edi,%edx), %eax + jnz LeaveLoopCmps4 + addl $8, %edx + jnz LoopCmps + jmp LenMaximum +LeaveLoopCmps4: addl $4, %edx +LeaveLoopCmps: testl $0x0000FFFF, %eax + jnz LenLower + addl $2, %edx + shrl $16, %eax +LenLower: subb $1, %al + adcl $0, %edx + +/* Calculate the length of the match. If it is longer than MAX_MATCH, */ +/* then automatically accept it as the best possible match and leave. */ + + lea (%edi,%edx), %eax + movl scan(%esp), %edi + subl %edi, %eax + cmpl $MAX_MATCH, %eax + jge LenMaximum + +/* If the length of the match is not longer than the best match we */ +/* have so far, then forget it and return to the lookup loop. */ + + movl deflatestate(%esp), %edx + movl bestlen(%esp), %ebx + cmpl %ebx, %eax + jg LongerMatch + movl windowbestlen(%esp), %esi + movl dsPrev(%edx), %edi + movl scanend(%esp), %ebx + movl chainlenwmask(%esp), %edx + jmp LookupLoop + +/* s->match_start = cur_match; */ +/* best_len = len; */ +/* if (len >= nice_match) break; */ +/* scan_end = *(ushf*)(scan+best_len-1); */ + +LongerMatch: movl nicematch(%esp), %ebx + movl %eax, bestlen(%esp) + movl %ecx, dsMatchStart(%edx) + cmpl %ebx, %eax + jge LeaveNow + movl window(%esp), %esi + addl %eax, %esi + movl %esi, windowbestlen(%esp) + movzwl -1(%edi,%eax), %ebx + movl dsPrev(%edx), %edi + movl %ebx, scanend(%esp) + movl chainlenwmask(%esp), %edx + jmp LookupLoop + +/* Accept the current string, with the maximum possible length. */ + +LenMaximum: movl deflatestate(%esp), %edx + movl $MAX_MATCH, bestlen(%esp) + movl %ecx, dsMatchStart(%edx) + +/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ +/* return s->lookahead; */ + +LeaveNow: + movl deflatestate(%esp), %edx + movl bestlen(%esp), %ebx + movl dsLookahead(%edx), %eax + cmpl %eax, %ebx + jg LookaheadRet + movl %ebx, %eax +LookaheadRet: + +/* Restore the stack and return from whence we came. */ + + addl $LocalVarsSize, %esp + .cfi_def_cfa_offset 20 + popl %ebx + .cfi_def_cfa_offset 16 + popl %esi + .cfi_def_cfa_offset 12 + popl %edi + .cfi_def_cfa_offset 8 + popl %ebp + .cfi_def_cfa_offset 4 +.cfi_endproc +match_init: ret diff --git a/dependencies/zlib-1.2.11/contrib/blast/Makefile b/dependencies/zlib-1.2.11/contrib/blast/Makefile new file mode 100644 index 0000000..9be80ba --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/blast/Makefile @@ -0,0 +1,8 @@ +blast: blast.c blast.h + cc -DTEST -o blast blast.c + +test: blast + blast < test.pk | cmp - test.txt + +clean: + rm -f blast blast.o diff --git a/dependencies/zlib-1.2.11/contrib/blast/README b/dependencies/zlib-1.2.11/contrib/blast/README new file mode 100644 index 0000000..e3a60b3 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/blast/README @@ -0,0 +1,4 @@ +Read blast.h for purpose and usage. + +Mark Adler +madler@alumni.caltech.edu diff --git a/dependencies/zlib-1.2.11/contrib/blast/blast.c b/dependencies/zlib-1.2.11/contrib/blast/blast.c new file mode 100644 index 0000000..e6e6590 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/blast/blast.c @@ -0,0 +1,466 @@ +/* blast.c + * Copyright (C) 2003, 2012, 2013 Mark Adler + * For conditions of distribution and use, see copyright notice in blast.h + * version 1.3, 24 Aug 2013 + * + * blast.c decompresses data compressed by the PKWare Compression Library. + * This function provides functionality similar to the explode() function of + * the PKWare library, hence the name "blast". + * + * This decompressor is based on the excellent format description provided by + * Ben Rudiak-Gould in comp.compression on August 13, 2001. Interestingly, the + * example Ben provided in the post is incorrect. The distance 110001 should + * instead be 111000. When corrected, the example byte stream becomes: + * + * 00 04 82 24 25 8f 80 7f + * + * which decompresses to "AIAIAIAIAIAIA" (without the quotes). + */ + +/* + * Change history: + * + * 1.0 12 Feb 2003 - First version + * 1.1 16 Feb 2003 - Fixed distance check for > 4 GB uncompressed data + * 1.2 24 Oct 2012 - Add note about using binary mode in stdio + * - Fix comparisons of differently signed integers + * 1.3 24 Aug 2013 - Return unused input from blast() + * - Fix test code to correctly report unused input + * - Enable the provision of initial input to blast() + */ + +#include /* for NULL */ +#include /* for setjmp(), longjmp(), and jmp_buf */ +#include "blast.h" /* prototype for blast() */ + +#define local static /* for local function definitions */ +#define MAXBITS 13 /* maximum code length */ +#define MAXWIN 4096 /* maximum window size */ + +/* input and output state */ +struct state { + /* input state */ + blast_in infun; /* input function provided by user */ + void *inhow; /* opaque information passed to infun() */ + unsigned char *in; /* next input location */ + unsigned left; /* available input at in */ + int bitbuf; /* bit buffer */ + int bitcnt; /* number of bits in bit buffer */ + + /* input limit error return state for bits() and decode() */ + jmp_buf env; + + /* output state */ + blast_out outfun; /* output function provided by user */ + void *outhow; /* opaque information passed to outfun() */ + unsigned next; /* index of next write location in out[] */ + int first; /* true to check distances (for first 4K) */ + unsigned char out[MAXWIN]; /* output buffer and sliding window */ +}; + +/* + * Return need bits from the input stream. This always leaves less than + * eight bits in the buffer. bits() works properly for need == 0. + * + * Format notes: + * + * - Bits are stored in bytes from the least significant bit to the most + * significant bit. Therefore bits are dropped from the bottom of the bit + * buffer, using shift right, and new bytes are appended to the top of the + * bit buffer, using shift left. + */ +local int bits(struct state *s, int need) +{ + int val; /* bit accumulator */ + + /* load at least need bits into val */ + val = s->bitbuf; + while (s->bitcnt < need) { + if (s->left == 0) { + s->left = s->infun(s->inhow, &(s->in)); + if (s->left == 0) longjmp(s->env, 1); /* out of input */ + } + val |= (int)(*(s->in)++) << s->bitcnt; /* load eight bits */ + s->left--; + s->bitcnt += 8; + } + + /* drop need bits and update buffer, always zero to seven bits left */ + s->bitbuf = val >> need; + s->bitcnt -= need; + + /* return need bits, zeroing the bits above that */ + return val & ((1 << need) - 1); +} + +/* + * Huffman code decoding tables. count[1..MAXBITS] is the number of symbols of + * each length, which for a canonical code are stepped through in order. + * symbol[] are the symbol values in canonical order, where the number of + * entries is the sum of the counts in count[]. The decoding process can be + * seen in the function decode() below. + */ +struct huffman { + short *count; /* number of symbols of each length */ + short *symbol; /* canonically ordered symbols */ +}; + +/* + * Decode a code from the stream s using huffman table h. Return the symbol or + * a negative value if there is an error. If all of the lengths are zero, i.e. + * an empty code, or if the code is incomplete and an invalid code is received, + * then -9 is returned after reading MAXBITS bits. + * + * Format notes: + * + * - The codes as stored in the compressed data are bit-reversed relative to + * a simple integer ordering of codes of the same lengths. Hence below the + * bits are pulled from the compressed data one at a time and used to + * build the code value reversed from what is in the stream in order to + * permit simple integer comparisons for decoding. + * + * - The first code for the shortest length is all ones. Subsequent codes of + * the same length are simply integer decrements of the previous code. When + * moving up a length, a one bit is appended to the code. For a complete + * code, the last code of the longest length will be all zeros. To support + * this ordering, the bits pulled during decoding are inverted to apply the + * more "natural" ordering starting with all zeros and incrementing. + */ +local int decode(struct state *s, struct huffman *h) +{ + int len; /* current number of bits in code */ + int code; /* len bits being decoded */ + int first; /* first code of length len */ + int count; /* number of codes of length len */ + int index; /* index of first code of length len in symbol table */ + int bitbuf; /* bits from stream */ + int left; /* bits left in next or left to process */ + short *next; /* next number of codes */ + + bitbuf = s->bitbuf; + left = s->bitcnt; + code = first = index = 0; + len = 1; + next = h->count + 1; + while (1) { + while (left--) { + code |= (bitbuf & 1) ^ 1; /* invert code */ + bitbuf >>= 1; + count = *next++; + if (code < first + count) { /* if length len, return symbol */ + s->bitbuf = bitbuf; + s->bitcnt = (s->bitcnt - len) & 7; + return h->symbol[index + (code - first)]; + } + index += count; /* else update for next length */ + first += count; + first <<= 1; + code <<= 1; + len++; + } + left = (MAXBITS+1) - len; + if (left == 0) break; + if (s->left == 0) { + s->left = s->infun(s->inhow, &(s->in)); + if (s->left == 0) longjmp(s->env, 1); /* out of input */ + } + bitbuf = *(s->in)++; + s->left--; + if (left > 8) left = 8; + } + return -9; /* ran out of codes */ +} + +/* + * Given a list of repeated code lengths rep[0..n-1], where each byte is a + * count (high four bits + 1) and a code length (low four bits), generate the + * list of code lengths. This compaction reduces the size of the object code. + * Then given the list of code lengths length[0..n-1] representing a canonical + * Huffman code for n symbols, construct the tables required to decode those + * codes. Those tables are the number of codes of each length, and the symbols + * sorted by length, retaining their original order within each length. The + * return value is zero for a complete code set, negative for an over- + * subscribed code set, and positive for an incomplete code set. The tables + * can be used if the return value is zero or positive, but they cannot be used + * if the return value is negative. If the return value is zero, it is not + * possible for decode() using that table to return an error--any stream of + * enough bits will resolve to a symbol. If the return value is positive, then + * it is possible for decode() using that table to return an error for received + * codes past the end of the incomplete lengths. + */ +local int construct(struct huffman *h, const unsigned char *rep, int n) +{ + int symbol; /* current symbol when stepping through length[] */ + int len; /* current length when stepping through h->count[] */ + int left; /* number of possible codes left of current length */ + short offs[MAXBITS+1]; /* offsets in symbol table for each length */ + short length[256]; /* code lengths */ + + /* convert compact repeat counts into symbol bit length list */ + symbol = 0; + do { + len = *rep++; + left = (len >> 4) + 1; + len &= 15; + do { + length[symbol++] = len; + } while (--left); + } while (--n); + n = symbol; + + /* count number of codes of each length */ + for (len = 0; len <= MAXBITS; len++) + h->count[len] = 0; + for (symbol = 0; symbol < n; symbol++) + (h->count[length[symbol]])++; /* assumes lengths are within bounds */ + if (h->count[0] == n) /* no codes! */ + return 0; /* complete, but decode() will fail */ + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; /* one possible code of zero length */ + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; /* one more bit, double codes left */ + left -= h->count[len]; /* deduct count from possible codes */ + if (left < 0) return left; /* over-subscribed--return negative */ + } /* left > 0 means incomplete */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + h->count[len]; + + /* + * put symbols in table sorted by length, by symbol order within each + * length + */ + for (symbol = 0; symbol < n; symbol++) + if (length[symbol] != 0) + h->symbol[offs[length[symbol]]++] = symbol; + + /* return zero for complete set, positive for incomplete set */ + return left; +} + +/* + * Decode PKWare Compression Library stream. + * + * Format notes: + * + * - First byte is 0 if literals are uncoded or 1 if they are coded. Second + * byte is 4, 5, or 6 for the number of extra bits in the distance code. + * This is the base-2 logarithm of the dictionary size minus six. + * + * - Compressed data is a combination of literals and length/distance pairs + * terminated by an end code. Literals are either Huffman coded or + * uncoded bytes. A length/distance pair is a coded length followed by a + * coded distance to represent a string that occurs earlier in the + * uncompressed data that occurs again at the current location. + * + * - A bit preceding a literal or length/distance pair indicates which comes + * next, 0 for literals, 1 for length/distance. + * + * - If literals are uncoded, then the next eight bits are the literal, in the + * normal bit order in the stream, i.e. no bit-reversal is needed. Similarly, + * no bit reversal is needed for either the length extra bits or the distance + * extra bits. + * + * - Literal bytes are simply written to the output. A length/distance pair is + * an instruction to copy previously uncompressed bytes to the output. The + * copy is from distance bytes back in the output stream, copying for length + * bytes. + * + * - Distances pointing before the beginning of the output data are not + * permitted. + * + * - Overlapped copies, where the length is greater than the distance, are + * allowed and common. For example, a distance of one and a length of 518 + * simply copies the last byte 518 times. A distance of four and a length of + * twelve copies the last four bytes three times. A simple forward copy + * ignoring whether the length is greater than the distance or not implements + * this correctly. + */ +local int decomp(struct state *s) +{ + int lit; /* true if literals are coded */ + int dict; /* log2(dictionary size) - 6 */ + int symbol; /* decoded symbol, extra bits for distance */ + int len; /* length for copy */ + unsigned dist; /* distance for copy */ + int copy; /* copy counter */ + unsigned char *from, *to; /* copy pointers */ + static int virgin = 1; /* build tables once */ + static short litcnt[MAXBITS+1], litsym[256]; /* litcode memory */ + static short lencnt[MAXBITS+1], lensym[16]; /* lencode memory */ + static short distcnt[MAXBITS+1], distsym[64]; /* distcode memory */ + static struct huffman litcode = {litcnt, litsym}; /* length code */ + static struct huffman lencode = {lencnt, lensym}; /* length code */ + static struct huffman distcode = {distcnt, distsym};/* distance code */ + /* bit lengths of literal codes */ + static const unsigned char litlen[] = { + 11, 124, 8, 7, 28, 7, 188, 13, 76, 4, 10, 8, 12, 10, 12, 10, 8, 23, 8, + 9, 7, 6, 7, 8, 7, 6, 55, 8, 23, 24, 12, 11, 7, 9, 11, 12, 6, 7, 22, 5, + 7, 24, 6, 11, 9, 6, 7, 22, 7, 11, 38, 7, 9, 8, 25, 11, 8, 11, 9, 12, + 8, 12, 5, 38, 5, 38, 5, 11, 7, 5, 6, 21, 6, 10, 53, 8, 7, 24, 10, 27, + 44, 253, 253, 253, 252, 252, 252, 13, 12, 45, 12, 45, 12, 61, 12, 45, + 44, 173}; + /* bit lengths of length codes 0..15 */ + static const unsigned char lenlen[] = {2, 35, 36, 53, 38, 23}; + /* bit lengths of distance codes 0..63 */ + static const unsigned char distlen[] = {2, 20, 53, 230, 247, 151, 248}; + static const short base[16] = { /* base for length codes */ + 3, 2, 4, 5, 6, 7, 8, 9, 10, 12, 16, 24, 40, 72, 136, 264}; + static const char extra[16] = { /* extra bits for length codes */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8}; + + /* set up decoding tables (once--might not be thread-safe) */ + if (virgin) { + construct(&litcode, litlen, sizeof(litlen)); + construct(&lencode, lenlen, sizeof(lenlen)); + construct(&distcode, distlen, sizeof(distlen)); + virgin = 0; + } + + /* read header */ + lit = bits(s, 8); + if (lit > 1) return -1; + dict = bits(s, 8); + if (dict < 4 || dict > 6) return -2; + + /* decode literals and length/distance pairs */ + do { + if (bits(s, 1)) { + /* get length */ + symbol = decode(s, &lencode); + len = base[symbol] + bits(s, extra[symbol]); + if (len == 519) break; /* end code */ + + /* get distance */ + symbol = len == 2 ? 2 : dict; + dist = decode(s, &distcode) << symbol; + dist += bits(s, symbol); + dist++; + if (s->first && dist > s->next) + return -3; /* distance too far back */ + + /* copy length bytes from distance bytes back */ + do { + to = s->out + s->next; + from = to - dist; + copy = MAXWIN; + if (s->next < dist) { + from += copy; + copy = dist; + } + copy -= s->next; + if (copy > len) copy = len; + len -= copy; + s->next += copy; + do { + *to++ = *from++; + } while (--copy); + if (s->next == MAXWIN) { + if (s->outfun(s->outhow, s->out, s->next)) return 1; + s->next = 0; + s->first = 0; + } + } while (len != 0); + } + else { + /* get literal and write it */ + symbol = lit ? decode(s, &litcode) : bits(s, 8); + s->out[s->next++] = symbol; + if (s->next == MAXWIN) { + if (s->outfun(s->outhow, s->out, s->next)) return 1; + s->next = 0; + s->first = 0; + } + } + } while (1); + return 0; +} + +/* See comments in blast.h */ +int blast(blast_in infun, void *inhow, blast_out outfun, void *outhow, + unsigned *left, unsigned char **in) +{ + struct state s; /* input/output state */ + int err; /* return value */ + + /* initialize input state */ + s.infun = infun; + s.inhow = inhow; + if (left != NULL && *left) { + s.left = *left; + s.in = *in; + } + else + s.left = 0; + s.bitbuf = 0; + s.bitcnt = 0; + + /* initialize output state */ + s.outfun = outfun; + s.outhow = outhow; + s.next = 0; + s.first = 1; + + /* return if bits() or decode() tries to read past available input */ + if (setjmp(s.env) != 0) /* if came back here via longjmp(), */ + err = 2; /* then skip decomp(), return error */ + else + err = decomp(&s); /* decompress */ + + /* return unused input */ + if (left != NULL) + *left = s.left; + if (in != NULL) + *in = s.left ? s.in : NULL; + + /* write any leftover output and update the error code if needed */ + if (err != 1 && s.next && s.outfun(s.outhow, s.out, s.next) && err == 0) + err = 1; + return err; +} + +#ifdef TEST +/* Example of how to use blast() */ +#include +#include + +#define CHUNK 16384 + +local unsigned inf(void *how, unsigned char **buf) +{ + static unsigned char hold[CHUNK]; + + *buf = hold; + return fread(hold, 1, CHUNK, (FILE *)how); +} + +local int outf(void *how, unsigned char *buf, unsigned len) +{ + return fwrite(buf, 1, len, (FILE *)how) != len; +} + +/* Decompress a PKWare Compression Library stream from stdin to stdout */ +int main(void) +{ + int ret; + unsigned left; + + /* decompress to stdout */ + left = 0; + ret = blast(inf, stdin, outf, stdout, &left, NULL); + if (ret != 0) + fprintf(stderr, "blast error: %d\n", ret); + + /* count any leftover bytes */ + while (getchar() != EOF) + left++; + if (left) + fprintf(stderr, "blast warning: %u unused bytes of input\n", left); + + /* return blast() error code */ + return ret; +} +#endif diff --git a/dependencies/zlib-1.2.11/contrib/blast/blast.h b/dependencies/zlib-1.2.11/contrib/blast/blast.h new file mode 100644 index 0000000..6cf65ed --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/blast/blast.h @@ -0,0 +1,83 @@ +/* blast.h -- interface for blast.c + Copyright (C) 2003, 2012, 2013 Mark Adler + version 1.3, 24 Aug 2013 + + This software is provided 'as-is', without any express or implied + warranty. In no event will the author be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Mark Adler madler@alumni.caltech.edu + */ + + +/* + * blast() decompresses the PKWare Data Compression Library (DCL) compressed + * format. It provides the same functionality as the explode() function in + * that library. (Note: PKWare overused the "implode" verb, and the format + * used by their library implode() function is completely different and + * incompatible with the implode compression method supported by PKZIP.) + * + * The binary mode for stdio functions should be used to assure that the + * compressed data is not corrupted when read or written. For example: + * fopen(..., "rb") and fopen(..., "wb"). + */ + + +typedef unsigned (*blast_in)(void *how, unsigned char **buf); +typedef int (*blast_out)(void *how, unsigned char *buf, unsigned len); +/* Definitions for input/output functions passed to blast(). See below for + * what the provided functions need to do. + */ + + +int blast(blast_in infun, void *inhow, blast_out outfun, void *outhow, + unsigned *left, unsigned char **in); +/* Decompress input to output using the provided infun() and outfun() calls. + * On success, the return value of blast() is zero. If there is an error in + * the source data, i.e. it is not in the proper format, then a negative value + * is returned. If there is not enough input available or there is not enough + * output space, then a positive error is returned. + * + * The input function is invoked: len = infun(how, &buf), where buf is set by + * infun() to point to the input buffer, and infun() returns the number of + * available bytes there. If infun() returns zero, then blast() returns with + * an input error. (blast() only asks for input if it needs it.) inhow is for + * use by the application to pass an input descriptor to infun(), if desired. + * + * If left and in are not NULL and *left is not zero when blast() is called, + * then the *left bytes are *in are consumed for input before infun() is used. + * + * The output function is invoked: err = outfun(how, buf, len), where the bytes + * to be written are buf[0..len-1]. If err is not zero, then blast() returns + * with an output error. outfun() is always called with len <= 4096. outhow + * is for use by the application to pass an output descriptor to outfun(), if + * desired. + * + * If there is any unused input, *left is set to the number of bytes that were + * read and *in points to them. Otherwise *left is set to zero and *in is set + * to NULL. If left or in are NULL, then they are not set. + * + * The return codes are: + * + * 2: ran out of input before completing decompression + * 1: output error before completing decompression + * 0: successful decompression + * -1: literal flag not zero or one + * -2: dictionary size not in 4..6 + * -3: distance is too far back + * + * At the bottom of blast.c is an example program that uses blast() that can be + * compiled to produce a command-line decompression filter by defining TEST. + */ diff --git a/dependencies/zlib-1.2.11/contrib/blast/test.pk b/dependencies/zlib-1.2.11/contrib/blast/test.pk new file mode 100644 index 0000000..be10b2b Binary files /dev/null and b/dependencies/zlib-1.2.11/contrib/blast/test.pk differ diff --git a/dependencies/zlib-1.2.11/contrib/blast/test.txt b/dependencies/zlib-1.2.11/contrib/blast/test.txt new file mode 100644 index 0000000..bfdf1c5 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/blast/test.txt @@ -0,0 +1 @@ +AIAIAIAIAIAIA \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/delphi/ZLib.pas b/dependencies/zlib-1.2.11/contrib/delphi/ZLib.pas new file mode 100644 index 0000000..060e199 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/delphi/ZLib.pas @@ -0,0 +1,557 @@ +{*******************************************************} +{ } +{ Borland Delphi Supplemental Components } +{ ZLIB Data Compression Interface Unit } +{ } +{ Copyright (c) 1997,99 Borland Corporation } +{ } +{*******************************************************} + +{ Updated for zlib 1.2.x by Cosmin Truta } + +unit ZLib; + +interface + +uses SysUtils, Classes; + +type + TAlloc = function (AppData: Pointer; Items, Size: Integer): Pointer; cdecl; + TFree = procedure (AppData, Block: Pointer); cdecl; + + // Internal structure. Ignore. + TZStreamRec = packed record + next_in: PChar; // next input byte + avail_in: Integer; // number of bytes available at next_in + total_in: Longint; // total nb of input bytes read so far + + next_out: PChar; // next output byte should be put here + avail_out: Integer; // remaining free space at next_out + total_out: Longint; // total nb of bytes output so far + + msg: PChar; // last error message, NULL if no error + internal: Pointer; // not visible by applications + + zalloc: TAlloc; // used to allocate the internal state + zfree: TFree; // used to free the internal state + AppData: Pointer; // private data object passed to zalloc and zfree + + data_type: Integer; // best guess about the data type: ascii or binary + adler: Longint; // adler32 value of the uncompressed data + reserved: Longint; // reserved for future use + end; + + // Abstract ancestor class + TCustomZlibStream = class(TStream) + private + FStrm: TStream; + FStrmPos: Integer; + FOnProgress: TNotifyEvent; + FZRec: TZStreamRec; + FBuffer: array [Word] of Char; + protected + procedure Progress(Sender: TObject); dynamic; + property OnProgress: TNotifyEvent read FOnProgress write FOnProgress; + constructor Create(Strm: TStream); + end; + +{ TCompressionStream compresses data on the fly as data is written to it, and + stores the compressed data to another stream. + + TCompressionStream is write-only and strictly sequential. Reading from the + stream will raise an exception. Using Seek to move the stream pointer + will raise an exception. + + Output data is cached internally, written to the output stream only when + the internal output buffer is full. All pending output data is flushed + when the stream is destroyed. + + The Position property returns the number of uncompressed bytes of + data that have been written to the stream so far. + + CompressionRate returns the on-the-fly percentage by which the original + data has been compressed: (1 - (CompressedBytes / UncompressedBytes)) * 100 + If raw data size = 100 and compressed data size = 25, the CompressionRate + is 75% + + The OnProgress event is called each time the output buffer is filled and + written to the output stream. This is useful for updating a progress + indicator when you are writing a large chunk of data to the compression + stream in a single call.} + + + TCompressionLevel = (clNone, clFastest, clDefault, clMax); + + TCompressionStream = class(TCustomZlibStream) + private + function GetCompressionRate: Single; + public + constructor Create(CompressionLevel: TCompressionLevel; Dest: TStream); + destructor Destroy; override; + function Read(var Buffer; Count: Longint): Longint; override; + function Write(const Buffer; Count: Longint): Longint; override; + function Seek(Offset: Longint; Origin: Word): Longint; override; + property CompressionRate: Single read GetCompressionRate; + property OnProgress; + end; + +{ TDecompressionStream decompresses data on the fly as data is read from it. + + Compressed data comes from a separate source stream. TDecompressionStream + is read-only and unidirectional; you can seek forward in the stream, but not + backwards. The special case of setting the stream position to zero is + allowed. Seeking forward decompresses data until the requested position in + the uncompressed data has been reached. Seeking backwards, seeking relative + to the end of the stream, requesting the size of the stream, and writing to + the stream will raise an exception. + + The Position property returns the number of bytes of uncompressed data that + have been read from the stream so far. + + The OnProgress event is called each time the internal input buffer of + compressed data is exhausted and the next block is read from the input stream. + This is useful for updating a progress indicator when you are reading a + large chunk of data from the decompression stream in a single call.} + + TDecompressionStream = class(TCustomZlibStream) + public + constructor Create(Source: TStream); + destructor Destroy; override; + function Read(var Buffer; Count: Longint): Longint; override; + function Write(const Buffer; Count: Longint): Longint; override; + function Seek(Offset: Longint; Origin: Word): Longint; override; + property OnProgress; + end; + + + +{ CompressBuf compresses data, buffer to buffer, in one call. + In: InBuf = ptr to compressed data + InBytes = number of bytes in InBuf + Out: OutBuf = ptr to newly allocated buffer containing decompressed data + OutBytes = number of bytes in OutBuf } +procedure CompressBuf(const InBuf: Pointer; InBytes: Integer; + out OutBuf: Pointer; out OutBytes: Integer); + + +{ DecompressBuf decompresses data, buffer to buffer, in one call. + In: InBuf = ptr to compressed data + InBytes = number of bytes in InBuf + OutEstimate = zero, or est. size of the decompressed data + Out: OutBuf = ptr to newly allocated buffer containing decompressed data + OutBytes = number of bytes in OutBuf } +procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer; + OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer); + +{ DecompressToUserBuf decompresses data, buffer to buffer, in one call. + In: InBuf = ptr to compressed data + InBytes = number of bytes in InBuf + Out: OutBuf = ptr to user-allocated buffer to contain decompressed data + BufSize = number of bytes in OutBuf } +procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer; + const OutBuf: Pointer; BufSize: Integer); + +const + zlib_version = '1.2.11'; + +type + EZlibError = class(Exception); + ECompressionError = class(EZlibError); + EDecompressionError = class(EZlibError); + +implementation + +uses ZLibConst; + +const + Z_NO_FLUSH = 0; + Z_PARTIAL_FLUSH = 1; + Z_SYNC_FLUSH = 2; + Z_FULL_FLUSH = 3; + Z_FINISH = 4; + + Z_OK = 0; + Z_STREAM_END = 1; + Z_NEED_DICT = 2; + Z_ERRNO = (-1); + Z_STREAM_ERROR = (-2); + Z_DATA_ERROR = (-3); + Z_MEM_ERROR = (-4); + Z_BUF_ERROR = (-5); + Z_VERSION_ERROR = (-6); + + Z_NO_COMPRESSION = 0; + Z_BEST_SPEED = 1; + Z_BEST_COMPRESSION = 9; + Z_DEFAULT_COMPRESSION = (-1); + + Z_FILTERED = 1; + Z_HUFFMAN_ONLY = 2; + Z_RLE = 3; + Z_DEFAULT_STRATEGY = 0; + + Z_BINARY = 0; + Z_ASCII = 1; + Z_UNKNOWN = 2; + + Z_DEFLATED = 8; + + +{$L adler32.obj} +{$L compress.obj} +{$L crc32.obj} +{$L deflate.obj} +{$L infback.obj} +{$L inffast.obj} +{$L inflate.obj} +{$L inftrees.obj} +{$L trees.obj} +{$L uncompr.obj} +{$L zutil.obj} + +procedure adler32; external; +procedure compressBound; external; +procedure crc32; external; +procedure deflateInit2_; external; +procedure deflateParams; external; + +function _malloc(Size: Integer): Pointer; cdecl; +begin + Result := AllocMem(Size); +end; + +procedure _free(Block: Pointer); cdecl; +begin + FreeMem(Block); +end; + +procedure _memset(P: Pointer; B: Byte; count: Integer); cdecl; +begin + FillChar(P^, count, B); +end; + +procedure _memcpy(dest, source: Pointer; count: Integer); cdecl; +begin + Move(source^, dest^, count); +end; + + + +// deflate compresses data +function deflateInit_(var strm: TZStreamRec; level: Integer; version: PChar; + recsize: Integer): Integer; external; +function deflate(var strm: TZStreamRec; flush: Integer): Integer; external; +function deflateEnd(var strm: TZStreamRec): Integer; external; + +// inflate decompresses data +function inflateInit_(var strm: TZStreamRec; version: PChar; + recsize: Integer): Integer; external; +function inflate(var strm: TZStreamRec; flush: Integer): Integer; external; +function inflateEnd(var strm: TZStreamRec): Integer; external; +function inflateReset(var strm: TZStreamRec): Integer; external; + + +function zlibAllocMem(AppData: Pointer; Items, Size: Integer): Pointer; cdecl; +begin +// GetMem(Result, Items*Size); + Result := AllocMem(Items * Size); +end; + +procedure zlibFreeMem(AppData, Block: Pointer); cdecl; +begin + FreeMem(Block); +end; + +{function zlibCheck(code: Integer): Integer; +begin + Result := code; + if code < 0 then + raise EZlibError.Create('error'); //!! +end;} + +function CCheck(code: Integer): Integer; +begin + Result := code; + if code < 0 then + raise ECompressionError.Create('error'); //!! +end; + +function DCheck(code: Integer): Integer; +begin + Result := code; + if code < 0 then + raise EDecompressionError.Create('error'); //!! +end; + +procedure CompressBuf(const InBuf: Pointer; InBytes: Integer; + out OutBuf: Pointer; out OutBytes: Integer); +var + strm: TZStreamRec; + P: Pointer; +begin + FillChar(strm, sizeof(strm), 0); + strm.zalloc := zlibAllocMem; + strm.zfree := zlibFreeMem; + OutBytes := ((InBytes + (InBytes div 10) + 12) + 255) and not 255; + GetMem(OutBuf, OutBytes); + try + strm.next_in := InBuf; + strm.avail_in := InBytes; + strm.next_out := OutBuf; + strm.avail_out := OutBytes; + CCheck(deflateInit_(strm, Z_BEST_COMPRESSION, zlib_version, sizeof(strm))); + try + while CCheck(deflate(strm, Z_FINISH)) <> Z_STREAM_END do + begin + P := OutBuf; + Inc(OutBytes, 256); + ReallocMem(OutBuf, OutBytes); + strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P))); + strm.avail_out := 256; + end; + finally + CCheck(deflateEnd(strm)); + end; + ReallocMem(OutBuf, strm.total_out); + OutBytes := strm.total_out; + except + FreeMem(OutBuf); + raise + end; +end; + + +procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer; + OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer); +var + strm: TZStreamRec; + P: Pointer; + BufInc: Integer; +begin + FillChar(strm, sizeof(strm), 0); + strm.zalloc := zlibAllocMem; + strm.zfree := zlibFreeMem; + BufInc := (InBytes + 255) and not 255; + if OutEstimate = 0 then + OutBytes := BufInc + else + OutBytes := OutEstimate; + GetMem(OutBuf, OutBytes); + try + strm.next_in := InBuf; + strm.avail_in := InBytes; + strm.next_out := OutBuf; + strm.avail_out := OutBytes; + DCheck(inflateInit_(strm, zlib_version, sizeof(strm))); + try + while DCheck(inflate(strm, Z_NO_FLUSH)) <> Z_STREAM_END do + begin + P := OutBuf; + Inc(OutBytes, BufInc); + ReallocMem(OutBuf, OutBytes); + strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P))); + strm.avail_out := BufInc; + end; + finally + DCheck(inflateEnd(strm)); + end; + ReallocMem(OutBuf, strm.total_out); + OutBytes := strm.total_out; + except + FreeMem(OutBuf); + raise + end; +end; + +procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer; + const OutBuf: Pointer; BufSize: Integer); +var + strm: TZStreamRec; +begin + FillChar(strm, sizeof(strm), 0); + strm.zalloc := zlibAllocMem; + strm.zfree := zlibFreeMem; + strm.next_in := InBuf; + strm.avail_in := InBytes; + strm.next_out := OutBuf; + strm.avail_out := BufSize; + DCheck(inflateInit_(strm, zlib_version, sizeof(strm))); + try + if DCheck(inflate(strm, Z_FINISH)) <> Z_STREAM_END then + raise EZlibError.CreateRes(@sTargetBufferTooSmall); + finally + DCheck(inflateEnd(strm)); + end; +end; + +// TCustomZlibStream + +constructor TCustomZLibStream.Create(Strm: TStream); +begin + inherited Create; + FStrm := Strm; + FStrmPos := Strm.Position; + FZRec.zalloc := zlibAllocMem; + FZRec.zfree := zlibFreeMem; +end; + +procedure TCustomZLibStream.Progress(Sender: TObject); +begin + if Assigned(FOnProgress) then FOnProgress(Sender); +end; + + +// TCompressionStream + +constructor TCompressionStream.Create(CompressionLevel: TCompressionLevel; + Dest: TStream); +const + Levels: array [TCompressionLevel] of ShortInt = + (Z_NO_COMPRESSION, Z_BEST_SPEED, Z_DEFAULT_COMPRESSION, Z_BEST_COMPRESSION); +begin + inherited Create(Dest); + FZRec.next_out := FBuffer; + FZRec.avail_out := sizeof(FBuffer); + CCheck(deflateInit_(FZRec, Levels[CompressionLevel], zlib_version, sizeof(FZRec))); +end; + +destructor TCompressionStream.Destroy; +begin + FZRec.next_in := nil; + FZRec.avail_in := 0; + try + if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos; + while (CCheck(deflate(FZRec, Z_FINISH)) <> Z_STREAM_END) + and (FZRec.avail_out = 0) do + begin + FStrm.WriteBuffer(FBuffer, sizeof(FBuffer)); + FZRec.next_out := FBuffer; + FZRec.avail_out := sizeof(FBuffer); + end; + if FZRec.avail_out < sizeof(FBuffer) then + FStrm.WriteBuffer(FBuffer, sizeof(FBuffer) - FZRec.avail_out); + finally + deflateEnd(FZRec); + end; + inherited Destroy; +end; + +function TCompressionStream.Read(var Buffer; Count: Longint): Longint; +begin + raise ECompressionError.CreateRes(@sInvalidStreamOp); +end; + +function TCompressionStream.Write(const Buffer; Count: Longint): Longint; +begin + FZRec.next_in := @Buffer; + FZRec.avail_in := Count; + if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos; + while (FZRec.avail_in > 0) do + begin + CCheck(deflate(FZRec, 0)); + if FZRec.avail_out = 0 then + begin + FStrm.WriteBuffer(FBuffer, sizeof(FBuffer)); + FZRec.next_out := FBuffer; + FZRec.avail_out := sizeof(FBuffer); + FStrmPos := FStrm.Position; + Progress(Self); + end; + end; + Result := Count; +end; + +function TCompressionStream.Seek(Offset: Longint; Origin: Word): Longint; +begin + if (Offset = 0) and (Origin = soFromCurrent) then + Result := FZRec.total_in + else + raise ECompressionError.CreateRes(@sInvalidStreamOp); +end; + +function TCompressionStream.GetCompressionRate: Single; +begin + if FZRec.total_in = 0 then + Result := 0 + else + Result := (1.0 - (FZRec.total_out / FZRec.total_in)) * 100.0; +end; + + +// TDecompressionStream + +constructor TDecompressionStream.Create(Source: TStream); +begin + inherited Create(Source); + FZRec.next_in := FBuffer; + FZRec.avail_in := 0; + DCheck(inflateInit_(FZRec, zlib_version, sizeof(FZRec))); +end; + +destructor TDecompressionStream.Destroy; +begin + FStrm.Seek(-FZRec.avail_in, 1); + inflateEnd(FZRec); + inherited Destroy; +end; + +function TDecompressionStream.Read(var Buffer; Count: Longint): Longint; +begin + FZRec.next_out := @Buffer; + FZRec.avail_out := Count; + if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos; + while (FZRec.avail_out > 0) do + begin + if FZRec.avail_in = 0 then + begin + FZRec.avail_in := FStrm.Read(FBuffer, sizeof(FBuffer)); + if FZRec.avail_in = 0 then + begin + Result := Count - FZRec.avail_out; + Exit; + end; + FZRec.next_in := FBuffer; + FStrmPos := FStrm.Position; + Progress(Self); + end; + CCheck(inflate(FZRec, 0)); + end; + Result := Count; +end; + +function TDecompressionStream.Write(const Buffer; Count: Longint): Longint; +begin + raise EDecompressionError.CreateRes(@sInvalidStreamOp); +end; + +function TDecompressionStream.Seek(Offset: Longint; Origin: Word): Longint; +var + I: Integer; + Buf: array [0..4095] of Char; +begin + if (Offset = 0) and (Origin = soFromBeginning) then + begin + DCheck(inflateReset(FZRec)); + FZRec.next_in := FBuffer; + FZRec.avail_in := 0; + FStrm.Position := 0; + FStrmPos := 0; + end + else if ( (Offset >= 0) and (Origin = soFromCurrent)) or + ( ((Offset - FZRec.total_out) > 0) and (Origin = soFromBeginning)) then + begin + if Origin = soFromBeginning then Dec(Offset, FZRec.total_out); + if Offset > 0 then + begin + for I := 1 to Offset div sizeof(Buf) do + ReadBuffer(Buf, sizeof(Buf)); + ReadBuffer(Buf, Offset mod sizeof(Buf)); + end; + end + else + raise EDecompressionError.CreateRes(@sInvalidStreamOp); + Result := FZRec.total_out; +end; + + +end. diff --git a/dependencies/zlib-1.2.11/contrib/delphi/ZLibConst.pas b/dependencies/zlib-1.2.11/contrib/delphi/ZLibConst.pas new file mode 100644 index 0000000..cdfe136 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/delphi/ZLibConst.pas @@ -0,0 +1,11 @@ +unit ZLibConst; + +interface + +resourcestring + sTargetBufferTooSmall = 'ZLib error: target buffer may be too small'; + sInvalidStreamOp = 'Invalid stream operation'; + +implementation + +end. diff --git a/dependencies/zlib-1.2.11/contrib/delphi/readme.txt b/dependencies/zlib-1.2.11/contrib/delphi/readme.txt new file mode 100644 index 0000000..2dc9a8b --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/delphi/readme.txt @@ -0,0 +1,76 @@ + +Overview +======== + +This directory contains an update to the ZLib interface unit, +distributed by Borland as a Delphi supplemental component. + +The original ZLib unit is Copyright (c) 1997,99 Borland Corp., +and is based on zlib version 1.0.4. There are a series of bugs +and security problems associated with that old zlib version, and +we recommend the users to update their ZLib unit. + + +Summary of modifications +======================== + +- Improved makefile, adapted to zlib version 1.2.1. + +- Some field types from TZStreamRec are changed from Integer to + Longint, for consistency with the zlib.h header, and for 64-bit + readiness. + +- The zlib_version constant is updated. + +- The new Z_RLE strategy has its corresponding symbolic constant. + +- The allocation and deallocation functions and function types + (TAlloc, TFree, zlibAllocMem and zlibFreeMem) are now cdecl, + and _malloc and _free are added as C RTL stubs. As a result, + the original C sources of zlib can be compiled out of the box, + and linked to the ZLib unit. + + +Suggestions for improvements +============================ + +Currently, the ZLib unit provides only a limited wrapper around +the zlib library, and much of the original zlib functionality is +missing. Handling compressed file formats like ZIP/GZIP or PNG +cannot be implemented without having this functionality. +Applications that handle these formats are either using their own, +duplicated code, or not using the ZLib unit at all. + +Here are a few suggestions: + +- Checksum class wrappers around adler32() and crc32(), similar + to the Java classes that implement the java.util.zip.Checksum + interface. + +- The ability to read and write raw deflate streams, without the + zlib stream header and trailer. Raw deflate streams are used + in the ZIP file format. + +- The ability to read and write gzip streams, used in the GZIP + file format, and normally produced by the gzip program. + +- The ability to select a different compression strategy, useful + to PNG and MNG image compression, and to multimedia compression + in general. Besides the compression level + + TCompressionLevel = (clNone, clFastest, clDefault, clMax); + + which, in fact, could have used the 'z' prefix and avoided + TColor-like symbols + + TCompressionLevel = (zcNone, zcFastest, zcDefault, zcMax); + + there could be a compression strategy + + TCompressionStrategy = (zsDefault, zsFiltered, zsHuffmanOnly, zsRle); + +- ZIP and GZIP stream handling via TStreams. + + +-- +Cosmin Truta diff --git a/dependencies/zlib-1.2.11/contrib/delphi/zlibd32.mak b/dependencies/zlib-1.2.11/contrib/delphi/zlibd32.mak new file mode 100644 index 0000000..9bb00b7 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/delphi/zlibd32.mak @@ -0,0 +1,99 @@ +# Makefile for zlib +# For use with Delphi and C++ Builder under Win32 +# Updated for zlib 1.2.x by Cosmin Truta + +# ------------ Borland C++ ------------ + +# This project uses the Delphi (fastcall/register) calling convention: +LOC = -DZEXPORT=__fastcall -DZEXPORTVA=__cdecl + +CC = bcc32 +LD = bcc32 +AR = tlib +# do not use "-pr" in CFLAGS +CFLAGS = -a -d -k- -O2 $(LOC) +LDFLAGS = + + +# variables +ZLIB_LIB = zlib.lib + +OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj +OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj +OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj +OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj + + +# targets +all: $(ZLIB_LIB) example.exe minigzip.exe + +.c.obj: + $(CC) -c $(CFLAGS) $*.c + +adler32.obj: adler32.c zlib.h zconf.h + +compress.obj: compress.c zlib.h zconf.h + +crc32.obj: crc32.c zlib.h zconf.h crc32.h + +deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h + +gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h + +gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h + +gzread.obj: gzread.c zlib.h zconf.h gzguts.h + +gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h + +infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h inffixed.h + +inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h + +inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h inffixed.h + +inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h + +trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h + +uncompr.obj: uncompr.c zlib.h zconf.h + +zutil.obj: zutil.c zutil.h zlib.h zconf.h + +example.obj: test/example.c zlib.h zconf.h + +minigzip.obj: test/minigzip.c zlib.h zconf.h + + +# For the sake of the old Borland make, +# the command line is cut to fit in the MS-DOS 128 byte limit: +$(ZLIB_LIB): $(OBJ1) $(OBJ2) + -del $(ZLIB_LIB) + $(AR) $(ZLIB_LIB) $(OBJP1) + $(AR) $(ZLIB_LIB) $(OBJP2) + + +# testing +test: example.exe minigzip.exe + example + echo hello world | minigzip | minigzip -d + +example.exe: example.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) + +minigzip.exe: minigzip.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) + + +# cleanup +clean: + -del *.obj + -del *.exe + -del *.lib + -del *.tds + -del zlib.bak + -del foo.gz + diff --git a/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib.build b/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib.build new file mode 100644 index 0000000..7f90d6b --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib.build @@ -0,0 +1,33 @@ + + + A .Net wrapper library around ZLib1.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib.sln b/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib.sln new file mode 100644 index 0000000..ac45ca0 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotZLib", "DotZLib\DotZLib.csproj", "{BB1EE0B1-1808-46CB-B786-949D91117FC5}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {BB1EE0B1-1808-46CB-B786-949D91117FC5}.Debug.ActiveCfg = Debug|.NET + {BB1EE0B1-1808-46CB-B786-949D91117FC5}.Debug.Build.0 = Debug|.NET + {BB1EE0B1-1808-46CB-B786-949D91117FC5}.Release.ActiveCfg = Release|.NET + {BB1EE0B1-1808-46CB-B786-949D91117FC5}.Release.Build.0 = Release|.NET + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/AssemblyInfo.cs b/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/AssemblyInfo.cs new file mode 100644 index 0000000..0491bfc --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/AssemblyInfo.cs @@ -0,0 +1,58 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle("DotZLib")] +[assembly: AssemblyDescription(".Net bindings for ZLib compression dll 1.2.x")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Henrik Ravn")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("(c) 2004 by Henrik Ravn")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("1.0.*")] + +// +// In order to sign your assembly you must specify a key to use. Refer to the +// Microsoft .NET Framework documentation for more information on assembly signing. +// +// Use the attributes below to control which key is used for signing. +// +// Notes: +// (*) If no key is specified, the assembly is not signed. +// (*) KeyName refers to a key that has been installed in the Crypto Service +// Provider (CSP) on your machine. KeyFile refers to a file which contains +// a key. +// (*) If the KeyFile and the KeyName values are both specified, the +// following processing occurs: +// (1) If the KeyName can be found in the CSP, that key is used. +// (2) If the KeyName does not exist and the KeyFile does exist, the key +// in the KeyFile is installed into the CSP and used. +// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. +// When specifying the KeyFile, the location of the KeyFile should be +// relative to the project output directory which is +// %Project Directory%\obj\. For example, if your KeyFile is +// located in the project directory, you would specify the AssemblyKeyFile +// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] +// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework +// documentation for more information on this. +// +[assembly: AssemblyDelaySign(false)] +[assembly: AssemblyKeyFile("")] +[assembly: AssemblyKeyName("")] diff --git a/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/ChecksumImpl.cs b/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/ChecksumImpl.cs new file mode 100644 index 0000000..788b2fc --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/ChecksumImpl.cs @@ -0,0 +1,202 @@ +// +// © Copyright Henrik Ravn 2004 +// +// Use, modification and distribution are subject to the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +using System; +using System.Runtime.InteropServices; +using System.Text; + + +namespace DotZLib +{ + #region ChecksumGeneratorBase + /// + /// Implements the common functionality needed for all s + /// + /// + public abstract class ChecksumGeneratorBase : ChecksumGenerator + { + /// + /// The value of the current checksum + /// + protected uint _current; + + /// + /// Initializes a new instance of the checksum generator base - the current checksum is + /// set to zero + /// + public ChecksumGeneratorBase() + { + _current = 0; + } + + /// + /// Initializes a new instance of the checksum generator basewith a specified value + /// + /// The value to set the current checksum to + public ChecksumGeneratorBase(uint initialValue) + { + _current = initialValue; + } + + /// + /// Resets the current checksum to zero + /// + public void Reset() { _current = 0; } + + /// + /// Gets the current checksum value + /// + public uint Value { get { return _current; } } + + /// + /// Updates the current checksum with part of an array of bytes + /// + /// The data to update the checksum with + /// Where in data to start updating + /// The number of bytes from data to use + /// The sum of offset and count is larger than the length of data + /// data is a null reference + /// Offset or count is negative. + /// All the other Update methods are implmeneted in terms of this one. + /// This is therefore the only method a derived class has to implement + public abstract void Update(byte[] data, int offset, int count); + + /// + /// Updates the current checksum with an array of bytes. + /// + /// The data to update the checksum with + public void Update(byte[] data) + { + Update(data, 0, data.Length); + } + + /// + /// Updates the current checksum with the data from a string + /// + /// The string to update the checksum with + /// The characters in the string are converted by the UTF-8 encoding + public void Update(string data) + { + Update(Encoding.UTF8.GetBytes(data)); + } + + /// + /// Updates the current checksum with the data from a string, using a specific encoding + /// + /// The string to update the checksum with + /// The encoding to use + public void Update(string data, Encoding encoding) + { + Update(encoding.GetBytes(data)); + } + + } + #endregion + + #region CRC32 + /// + /// Implements a CRC32 checksum generator + /// + public sealed class CRC32Checksum : ChecksumGeneratorBase + { + #region DLL imports + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern uint crc32(uint crc, int data, uint length); + + #endregion + + /// + /// Initializes a new instance of the CRC32 checksum generator + /// + public CRC32Checksum() : base() {} + + /// + /// Initializes a new instance of the CRC32 checksum generator with a specified value + /// + /// The value to set the current checksum to + public CRC32Checksum(uint initialValue) : base(initialValue) {} + + /// + /// Updates the current checksum with part of an array of bytes + /// + /// The data to update the checksum with + /// Where in data to start updating + /// The number of bytes from data to use + /// The sum of offset and count is larger than the length of data + /// data is a null reference + /// Offset or count is negative. + public override void Update(byte[] data, int offset, int count) + { + if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); + if ((offset+count) > data.Length) throw new ArgumentException(); + GCHandle hData = GCHandle.Alloc(data, GCHandleType.Pinned); + try + { + _current = crc32(_current, hData.AddrOfPinnedObject().ToInt32()+offset, (uint)count); + } + finally + { + hData.Free(); + } + } + + } + #endregion + + #region Adler + /// + /// Implements a checksum generator that computes the Adler checksum on data + /// + public sealed class AdlerChecksum : ChecksumGeneratorBase + { + #region DLL imports + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern uint adler32(uint adler, int data, uint length); + + #endregion + + /// + /// Initializes a new instance of the Adler checksum generator + /// + public AdlerChecksum() : base() {} + + /// + /// Initializes a new instance of the Adler checksum generator with a specified value + /// + /// The value to set the current checksum to + public AdlerChecksum(uint initialValue) : base(initialValue) {} + + /// + /// Updates the current checksum with part of an array of bytes + /// + /// The data to update the checksum with + /// Where in data to start updating + /// The number of bytes from data to use + /// The sum of offset and count is larger than the length of data + /// data is a null reference + /// Offset or count is negative. + public override void Update(byte[] data, int offset, int count) + { + if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); + if ((offset+count) > data.Length) throw new ArgumentException(); + GCHandle hData = GCHandle.Alloc(data, GCHandleType.Pinned); + try + { + _current = adler32(_current, hData.AddrOfPinnedObject().ToInt32()+offset, (uint)count); + } + finally + { + hData.Free(); + } + } + + } + #endregion + +} \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/CircularBuffer.cs b/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/CircularBuffer.cs new file mode 100644 index 0000000..c1cab3a --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/CircularBuffer.cs @@ -0,0 +1,83 @@ +// +// © Copyright Henrik Ravn 2004 +// +// Use, modification and distribution are subject to the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +using System; +using System.Diagnostics; + +namespace DotZLib +{ + + /// + /// This class implements a circular buffer + /// + internal class CircularBuffer + { + #region Private data + private int _capacity; + private int _head; + private int _tail; + private int _size; + private byte[] _buffer; + #endregion + + public CircularBuffer(int capacity) + { + Debug.Assert( capacity > 0 ); + _buffer = new byte[capacity]; + _capacity = capacity; + _head = 0; + _tail = 0; + _size = 0; + } + + public int Size { get { return _size; } } + + public int Put(byte[] source, int offset, int count) + { + Debug.Assert( count > 0 ); + int trueCount = Math.Min(count, _capacity - Size); + for (int i = 0; i < trueCount; ++i) + _buffer[(_tail+i) % _capacity] = source[offset+i]; + _tail += trueCount; + _tail %= _capacity; + _size += trueCount; + return trueCount; + } + + public bool Put(byte b) + { + if (Size == _capacity) // no room + return false; + _buffer[_tail++] = b; + _tail %= _capacity; + ++_size; + return true; + } + + public int Get(byte[] destination, int offset, int count) + { + int trueCount = Math.Min(count,Size); + for (int i = 0; i < trueCount; ++i) + destination[offset + i] = _buffer[(_head+i) % _capacity]; + _head += trueCount; + _head %= _capacity; + _size -= trueCount; + return trueCount; + } + + public int Get() + { + if (Size == 0) + return -1; + + int result = (int)_buffer[_head++ % _capacity]; + --_size; + return result; + } + + } +} diff --git a/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/CodecBase.cs b/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/CodecBase.cs new file mode 100644 index 0000000..42e6da3 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/CodecBase.cs @@ -0,0 +1,198 @@ +// +// © Copyright Henrik Ravn 2004 +// +// Use, modification and distribution are subject to the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +using System; +using System.Runtime.InteropServices; + +namespace DotZLib +{ + /// + /// Implements the common functionality needed for all s + /// + public abstract class CodecBase : Codec, IDisposable + { + + #region Data members + + /// + /// Instance of the internal zlib buffer structure that is + /// passed to all functions in the zlib dll + /// + internal ZStream _ztream = new ZStream(); + + /// + /// True if the object instance has been disposed, false otherwise + /// + protected bool _isDisposed = false; + + /// + /// The size of the internal buffers + /// + protected const int kBufferSize = 16384; + + private byte[] _outBuffer = new byte[kBufferSize]; + private byte[] _inBuffer = new byte[kBufferSize]; + + private GCHandle _hInput; + private GCHandle _hOutput; + + private uint _checksum = 0; + + #endregion + + /// + /// Initializes a new instance of the CodeBase class. + /// + public CodecBase() + { + try + { + _hInput = GCHandle.Alloc(_inBuffer, GCHandleType.Pinned); + _hOutput = GCHandle.Alloc(_outBuffer, GCHandleType.Pinned); + } + catch (Exception) + { + CleanUp(false); + throw; + } + } + + + #region Codec Members + + /// + /// Occurs when more processed data are available. + /// + public event DataAvailableHandler DataAvailable; + + /// + /// Fires the event + /// + protected void OnDataAvailable() + { + if (_ztream.total_out > 0) + { + if (DataAvailable != null) + DataAvailable( _outBuffer, 0, (int)_ztream.total_out); + resetOutput(); + } + } + + /// + /// Adds more data to the codec to be processed. + /// + /// Byte array containing the data to be added to the codec + /// Adding data may, or may not, raise the DataAvailable event + public void Add(byte[] data) + { + Add(data,0,data.Length); + } + + /// + /// Adds more data to the codec to be processed. + /// + /// Byte array containing the data to be added to the codec + /// The index of the first byte to add from data + /// The number of bytes to add + /// Adding data may, or may not, raise the DataAvailable event + /// This must be implemented by a derived class + public abstract void Add(byte[] data, int offset, int count); + + /// + /// Finishes up any pending data that needs to be processed and handled. + /// + /// This must be implemented by a derived class + public abstract void Finish(); + + /// + /// Gets the checksum of the data that has been added so far + /// + public uint Checksum { get { return _checksum; } } + + #endregion + + #region Destructor & IDisposable stuff + + /// + /// Destroys this instance + /// + ~CodecBase() + { + CleanUp(false); + } + + /// + /// Releases any unmanaged resources and calls the method of the derived class + /// + public void Dispose() + { + CleanUp(true); + } + + /// + /// Performs any codec specific cleanup + /// + /// This must be implemented by a derived class + protected abstract void CleanUp(); + + // performs the release of the handles and calls the dereived CleanUp() + private void CleanUp(bool isDisposing) + { + if (!_isDisposed) + { + CleanUp(); + if (_hInput.IsAllocated) + _hInput.Free(); + if (_hOutput.IsAllocated) + _hOutput.Free(); + + _isDisposed = true; + } + } + + + #endregion + + #region Helper methods + + /// + /// Copies a number of bytes to the internal codec buffer - ready for proccesing + /// + /// The byte array that contains the data to copy + /// The index of the first byte to copy + /// The number of bytes to copy from data + protected void copyInput(byte[] data, int startIndex, int count) + { + Array.Copy(data, startIndex, _inBuffer,0, count); + _ztream.next_in = _hInput.AddrOfPinnedObject(); + _ztream.total_in = 0; + _ztream.avail_in = (uint)count; + + } + + /// + /// Resets the internal output buffers to a known state - ready for processing + /// + protected void resetOutput() + { + _ztream.total_out = 0; + _ztream.avail_out = kBufferSize; + _ztream.next_out = _hOutput.AddrOfPinnedObject(); + } + + /// + /// Updates the running checksum property + /// + /// The new checksum value + protected void setChecksum(uint newSum) + { + _checksum = newSum; + } + #endregion + + } +} diff --git a/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/Deflater.cs b/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/Deflater.cs new file mode 100644 index 0000000..c247792 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/Deflater.cs @@ -0,0 +1,106 @@ +// +// © Copyright Henrik Ravn 2004 +// +// Use, modification and distribution are subject to the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace DotZLib +{ + + /// + /// Implements a data compressor, using the deflate algorithm in the ZLib dll + /// + public sealed class Deflater : CodecBase + { + #region Dll imports + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)] + private static extern int deflateInit_(ref ZStream sz, int level, string vs, int size); + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern int deflate(ref ZStream sz, int flush); + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern int deflateReset(ref ZStream sz); + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern int deflateEnd(ref ZStream sz); + #endregion + + /// + /// Constructs an new instance of the Deflater + /// + /// The compression level to use for this Deflater + public Deflater(CompressLevel level) : base() + { + int retval = deflateInit_(ref _ztream, (int)level, Info.Version, Marshal.SizeOf(_ztream)); + if (retval != 0) + throw new ZLibException(retval, "Could not initialize deflater"); + + resetOutput(); + } + + /// + /// Adds more data to the codec to be processed. + /// + /// Byte array containing the data to be added to the codec + /// The index of the first byte to add from data + /// The number of bytes to add + /// Adding data may, or may not, raise the DataAvailable event + public override void Add(byte[] data, int offset, int count) + { + if (data == null) throw new ArgumentNullException(); + if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); + if ((offset+count) > data.Length) throw new ArgumentException(); + + int total = count; + int inputIndex = offset; + int err = 0; + + while (err >= 0 && inputIndex < total) + { + copyInput(data, inputIndex, Math.Min(total - inputIndex, kBufferSize)); + while (err >= 0 && _ztream.avail_in > 0) + { + err = deflate(ref _ztream, (int)FlushTypes.None); + if (err == 0) + while (_ztream.avail_out == 0) + { + OnDataAvailable(); + err = deflate(ref _ztream, (int)FlushTypes.None); + } + inputIndex += (int)_ztream.total_in; + } + } + setChecksum( _ztream.adler ); + } + + + /// + /// Finishes up any pending data that needs to be processed and handled. + /// + public override void Finish() + { + int err; + do + { + err = deflate(ref _ztream, (int)FlushTypes.Finish); + OnDataAvailable(); + } + while (err == 0); + setChecksum( _ztream.adler ); + deflateReset(ref _ztream); + resetOutput(); + } + + /// + /// Closes the internal zlib deflate stream + /// + protected override void CleanUp() { deflateEnd(ref _ztream); } + + } +} diff --git a/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/DotZLib.cs b/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/DotZLib.cs new file mode 100644 index 0000000..be184b4 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/DotZLib.cs @@ -0,0 +1,288 @@ +// +// © Copyright Henrik Ravn 2004 +// +// Use, modification and distribution are subject to the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; + + +namespace DotZLib +{ + + #region Internal types + + /// + /// Defines constants for the various flush types used with zlib + /// + internal enum FlushTypes + { + None, Partial, Sync, Full, Finish, Block + } + + #region ZStream structure + // internal mapping of the zlib zstream structure for marshalling + [StructLayoutAttribute(LayoutKind.Sequential, Pack=4, Size=0, CharSet=CharSet.Ansi)] + internal struct ZStream + { + public IntPtr next_in; + public uint avail_in; + public uint total_in; + + public IntPtr next_out; + public uint avail_out; + public uint total_out; + + [MarshalAs(UnmanagedType.LPStr)] + string msg; + uint state; + + uint zalloc; + uint zfree; + uint opaque; + + int data_type; + public uint adler; + uint reserved; + } + + #endregion + + #endregion + + #region Public enums + /// + /// Defines constants for the available compression levels in zlib + /// + public enum CompressLevel : int + { + /// + /// The default compression level with a reasonable compromise between compression and speed + /// + Default = -1, + /// + /// No compression at all. The data are passed straight through. + /// + None = 0, + /// + /// The maximum compression rate available. + /// + Best = 9, + /// + /// The fastest available compression level. + /// + Fastest = 1 + } + #endregion + + #region Exception classes + /// + /// The exception that is thrown when an error occurs on the zlib dll + /// + public class ZLibException : ApplicationException + { + /// + /// Initializes a new instance of the class with a specified + /// error message and error code + /// + /// The zlib error code that caused the exception + /// A message that (hopefully) describes the error + public ZLibException(int errorCode, string msg) : base(String.Format("ZLib error {0} {1}", errorCode, msg)) + { + } + + /// + /// Initializes a new instance of the class with a specified + /// error code + /// + /// The zlib error code that caused the exception + public ZLibException(int errorCode) : base(String.Format("ZLib error {0}", errorCode)) + { + } + } + #endregion + + #region Interfaces + + /// + /// Declares methods and properties that enables a running checksum to be calculated + /// + public interface ChecksumGenerator + { + /// + /// Gets the current value of the checksum + /// + uint Value { get; } + + /// + /// Clears the current checksum to 0 + /// + void Reset(); + + /// + /// Updates the current checksum with an array of bytes + /// + /// The data to update the checksum with + void Update(byte[] data); + + /// + /// Updates the current checksum with part of an array of bytes + /// + /// The data to update the checksum with + /// Where in data to start updating + /// The number of bytes from data to use + /// The sum of offset and count is larger than the length of data + /// data is a null reference + /// Offset or count is negative. + void Update(byte[] data, int offset, int count); + + /// + /// Updates the current checksum with the data from a string + /// + /// The string to update the checksum with + /// The characters in the string are converted by the UTF-8 encoding + void Update(string data); + + /// + /// Updates the current checksum with the data from a string, using a specific encoding + /// + /// The string to update the checksum with + /// The encoding to use + void Update(string data, Encoding encoding); + } + + + /// + /// Represents the method that will be called from a codec when new data + /// are available. + /// + /// The byte array containing the processed data + /// The index of the first processed byte in data + /// The number of processed bytes available + /// On return from this method, the data may be overwritten, so grab it while you can. + /// You cannot assume that startIndex will be zero. + /// + public delegate void DataAvailableHandler(byte[] data, int startIndex, int count); + + /// + /// Declares methods and events for implementing compressors/decompressors + /// + public interface Codec + { + /// + /// Occurs when more processed data are available. + /// + event DataAvailableHandler DataAvailable; + + /// + /// Adds more data to the codec to be processed. + /// + /// Byte array containing the data to be added to the codec + /// Adding data may, or may not, raise the DataAvailable event + void Add(byte[] data); + + /// + /// Adds more data to the codec to be processed. + /// + /// Byte array containing the data to be added to the codec + /// The index of the first byte to add from data + /// The number of bytes to add + /// Adding data may, or may not, raise the DataAvailable event + void Add(byte[] data, int offset, int count); + + /// + /// Finishes up any pending data that needs to be processed and handled. + /// + void Finish(); + + /// + /// Gets the checksum of the data that has been added so far + /// + uint Checksum { get; } + + + } + + #endregion + + #region Classes + /// + /// Encapsulates general information about the ZLib library + /// + public class Info + { + #region DLL imports + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern uint zlibCompileFlags(); + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern string zlibVersion(); + #endregion + + #region Private stuff + private uint _flags; + + // helper function that unpacks a bitsize mask + private static int bitSize(uint bits) + { + switch (bits) + { + case 0: return 16; + case 1: return 32; + case 2: return 64; + } + return -1; + } + #endregion + + /// + /// Constructs an instance of the Info class. + /// + public Info() + { + _flags = zlibCompileFlags(); + } + + /// + /// True if the library is compiled with debug info + /// + public bool HasDebugInfo { get { return 0 != (_flags & 0x100); } } + + /// + /// True if the library is compiled with assembly optimizations + /// + public bool UsesAssemblyCode { get { return 0 != (_flags & 0x200); } } + + /// + /// Gets the size of the unsigned int that was compiled into Zlib + /// + public int SizeOfUInt { get { return bitSize(_flags & 3); } } + + /// + /// Gets the size of the unsigned long that was compiled into Zlib + /// + public int SizeOfULong { get { return bitSize((_flags >> 2) & 3); } } + + /// + /// Gets the size of the pointers that were compiled into Zlib + /// + public int SizeOfPointer { get { return bitSize((_flags >> 4) & 3); } } + + /// + /// Gets the size of the z_off_t type that was compiled into Zlib + /// + public int SizeOfOffset { get { return bitSize((_flags >> 6) & 3); } } + + /// + /// Gets the version of ZLib as a string, e.g. "1.2.1" + /// + public static string Version { get { return zlibVersion(); } } + } + + #endregion + +} diff --git a/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/DotZLib.csproj b/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/DotZLib.csproj new file mode 100644 index 0000000..71eeb85 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/DotZLib.csproj @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/GZipStream.cs b/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/GZipStream.cs new file mode 100644 index 0000000..b161300 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/GZipStream.cs @@ -0,0 +1,301 @@ +// +// © Copyright Henrik Ravn 2004 +// +// Use, modification and distribution are subject to the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +using System; +using System.IO; +using System.Runtime.InteropServices; + +namespace DotZLib +{ + /// + /// Implements a compressed , in GZip (.gz) format. + /// + public class GZipStream : Stream, IDisposable + { + #region Dll Imports + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)] + private static extern IntPtr gzopen(string name, string mode); + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern int gzclose(IntPtr gzFile); + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern int gzwrite(IntPtr gzFile, int data, int length); + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern int gzread(IntPtr gzFile, int data, int length); + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern int gzgetc(IntPtr gzFile); + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern int gzputc(IntPtr gzFile, int c); + + #endregion + + #region Private data + private IntPtr _gzFile; + private bool _isDisposed = false; + private bool _isWriting; + #endregion + + #region Constructors + /// + /// Creates a new file as a writeable GZipStream + /// + /// The name of the compressed file to create + /// The compression level to use when adding data + /// If an error occurred in the internal zlib function + public GZipStream(string fileName, CompressLevel level) + { + _isWriting = true; + _gzFile = gzopen(fileName, String.Format("wb{0}", (int)level)); + if (_gzFile == IntPtr.Zero) + throw new ZLibException(-1, "Could not open " + fileName); + } + + /// + /// Opens an existing file as a readable GZipStream + /// + /// The name of the file to open + /// If an error occurred in the internal zlib function + public GZipStream(string fileName) + { + _isWriting = false; + _gzFile = gzopen(fileName, "rb"); + if (_gzFile == IntPtr.Zero) + throw new ZLibException(-1, "Could not open " + fileName); + + } + #endregion + + #region Access properties + /// + /// Returns true of this stream can be read from, false otherwise + /// + public override bool CanRead + { + get + { + return !_isWriting; + } + } + + + /// + /// Returns false. + /// + public override bool CanSeek + { + get + { + return false; + } + } + + /// + /// Returns true if this tsream is writeable, false otherwise + /// + public override bool CanWrite + { + get + { + return _isWriting; + } + } + #endregion + + #region Destructor & IDispose stuff + + /// + /// Destroys this instance + /// + ~GZipStream() + { + cleanUp(false); + } + + /// + /// Closes the external file handle + /// + public void Dispose() + { + cleanUp(true); + } + + // Does the actual closing of the file handle. + private void cleanUp(bool isDisposing) + { + if (!_isDisposed) + { + gzclose(_gzFile); + _isDisposed = true; + } + } + #endregion + + #region Basic reading and writing + /// + /// Attempts to read a number of bytes from the stream. + /// + /// The destination data buffer + /// The index of the first destination byte in buffer + /// The number of bytes requested + /// The number of bytes read + /// If buffer is null + /// If count or offset are negative + /// If offset + count is > buffer.Length + /// If this stream is not readable. + /// If this stream has been disposed. + public override int Read(byte[] buffer, int offset, int count) + { + if (!CanRead) throw new NotSupportedException(); + if (buffer == null) throw new ArgumentNullException(); + if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); + if ((offset+count) > buffer.Length) throw new ArgumentException(); + if (_isDisposed) throw new ObjectDisposedException("GZipStream"); + + GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned); + int result; + try + { + result = gzread(_gzFile, h.AddrOfPinnedObject().ToInt32() + offset, count); + if (result < 0) + throw new IOException(); + } + finally + { + h.Free(); + } + return result; + } + + /// + /// Attempts to read a single byte from the stream. + /// + /// The byte that was read, or -1 in case of error or End-Of-File + public override int ReadByte() + { + if (!CanRead) throw new NotSupportedException(); + if (_isDisposed) throw new ObjectDisposedException("GZipStream"); + return gzgetc(_gzFile); + } + + /// + /// Writes a number of bytes to the stream + /// + /// + /// + /// + /// If buffer is null + /// If count or offset are negative + /// If offset + count is > buffer.Length + /// If this stream is not writeable. + /// If this stream has been disposed. + public override void Write(byte[] buffer, int offset, int count) + { + if (!CanWrite) throw new NotSupportedException(); + if (buffer == null) throw new ArgumentNullException(); + if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); + if ((offset+count) > buffer.Length) throw new ArgumentException(); + if (_isDisposed) throw new ObjectDisposedException("GZipStream"); + + GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned); + try + { + int result = gzwrite(_gzFile, h.AddrOfPinnedObject().ToInt32() + offset, count); + if (result < 0) + throw new IOException(); + } + finally + { + h.Free(); + } + } + + /// + /// Writes a single byte to the stream + /// + /// The byte to add to the stream. + /// If this stream is not writeable. + /// If this stream has been disposed. + public override void WriteByte(byte value) + { + if (!CanWrite) throw new NotSupportedException(); + if (_isDisposed) throw new ObjectDisposedException("GZipStream"); + + int result = gzputc(_gzFile, (int)value); + if (result < 0) + throw new IOException(); + } + #endregion + + #region Position & length stuff + /// + /// Not supported. + /// + /// + /// Always thrown + public override void SetLength(long value) + { + throw new NotSupportedException(); + } + + /// + /// Not suppported. + /// + /// + /// + /// + /// Always thrown + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException(); + } + + /// + /// Flushes the GZipStream. + /// + /// In this implementation, this method does nothing. This is because excessive + /// flushing may degrade the achievable compression rates. + public override void Flush() + { + // left empty on purpose + } + + /// + /// Gets/sets the current position in the GZipStream. Not suppported. + /// + /// In this implementation this property is not supported + /// Always thrown + public override long Position + { + get + { + throw new NotSupportedException(); + } + set + { + throw new NotSupportedException(); + } + } + + /// + /// Gets the size of the stream. Not suppported. + /// + /// In this implementation this property is not supported + /// Always thrown + public override long Length + { + get + { + throw new NotSupportedException(); + } + } + #endregion + } +} diff --git a/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/Inflater.cs b/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/Inflater.cs new file mode 100644 index 0000000..8ed5451 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/Inflater.cs @@ -0,0 +1,105 @@ +// +// © Copyright Henrik Ravn 2004 +// +// Use, modification and distribution are subject to the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace DotZLib +{ + + /// + /// Implements a data decompressor, using the inflate algorithm in the ZLib dll + /// + public class Inflater : CodecBase + { + #region Dll imports + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)] + private static extern int inflateInit_(ref ZStream sz, string vs, int size); + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern int inflate(ref ZStream sz, int flush); + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern int inflateReset(ref ZStream sz); + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern int inflateEnd(ref ZStream sz); + #endregion + + /// + /// Constructs an new instance of the Inflater + /// + public Inflater() : base() + { + int retval = inflateInit_(ref _ztream, Info.Version, Marshal.SizeOf(_ztream)); + if (retval != 0) + throw new ZLibException(retval, "Could not initialize inflater"); + + resetOutput(); + } + + + /// + /// Adds more data to the codec to be processed. + /// + /// Byte array containing the data to be added to the codec + /// The index of the first byte to add from data + /// The number of bytes to add + /// Adding data may, or may not, raise the DataAvailable event + public override void Add(byte[] data, int offset, int count) + { + if (data == null) throw new ArgumentNullException(); + if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); + if ((offset+count) > data.Length) throw new ArgumentException(); + + int total = count; + int inputIndex = offset; + int err = 0; + + while (err >= 0 && inputIndex < total) + { + copyInput(data, inputIndex, Math.Min(total - inputIndex, kBufferSize)); + err = inflate(ref _ztream, (int)FlushTypes.None); + if (err == 0) + while (_ztream.avail_out == 0) + { + OnDataAvailable(); + err = inflate(ref _ztream, (int)FlushTypes.None); + } + + inputIndex += (int)_ztream.total_in; + } + setChecksum( _ztream.adler ); + } + + + /// + /// Finishes up any pending data that needs to be processed and handled. + /// + public override void Finish() + { + int err; + do + { + err = inflate(ref _ztream, (int)FlushTypes.Finish); + OnDataAvailable(); + } + while (err == 0); + setChecksum( _ztream.adler ); + inflateReset(ref _ztream); + resetOutput(); + } + + /// + /// Closes the internal zlib inflate stream + /// + protected override void CleanUp() { inflateEnd(ref _ztream); } + + + } +} diff --git a/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/UnitTests.cs b/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/UnitTests.cs new file mode 100644 index 0000000..44f7633 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/dotzlib/DotZLib/UnitTests.cs @@ -0,0 +1,274 @@ +// +// © Copyright Henrik Ravn 2004 +// +// Use, modification and distribution are subject to the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +using System; +using System.Collections; +using System.IO; + +// uncomment the define below to include unit tests +//#define nunit +#if nunit +using NUnit.Framework; + +// Unit tests for the DotZLib class library +// ---------------------------------------- +// +// Use this with NUnit 2 from http://www.nunit.org +// + +namespace DotZLibTests +{ + using DotZLib; + + // helper methods + internal class Utils + { + public static bool byteArrEqual( byte[] lhs, byte[] rhs ) + { + if (lhs.Length != rhs.Length) + return false; + for (int i = lhs.Length-1; i >= 0; --i) + if (lhs[i] != rhs[i]) + return false; + return true; + } + + } + + + [TestFixture] + public class CircBufferTests + { + #region Circular buffer tests + [Test] + public void SinglePutGet() + { + CircularBuffer buf = new CircularBuffer(10); + Assert.AreEqual( 0, buf.Size ); + Assert.AreEqual( -1, buf.Get() ); + + Assert.IsTrue(buf.Put( 1 )); + Assert.AreEqual( 1, buf.Size ); + Assert.AreEqual( 1, buf.Get() ); + Assert.AreEqual( 0, buf.Size ); + Assert.AreEqual( -1, buf.Get() ); + } + + [Test] + public void BlockPutGet() + { + CircularBuffer buf = new CircularBuffer(10); + byte[] arr = {1,2,3,4,5,6,7,8,9,10}; + Assert.AreEqual( 10, buf.Put(arr,0,10) ); + Assert.AreEqual( 10, buf.Size ); + Assert.IsFalse( buf.Put(11) ); + Assert.AreEqual( 1, buf.Get() ); + Assert.IsTrue( buf.Put(11) ); + + byte[] arr2 = (byte[])arr.Clone(); + Assert.AreEqual( 9, buf.Get(arr2,1,9) ); + Assert.IsTrue( Utils.byteArrEqual(arr,arr2) ); + } + + #endregion + } + + [TestFixture] + public class ChecksumTests + { + #region CRC32 Tests + [Test] + public void CRC32_Null() + { + CRC32Checksum crc32 = new CRC32Checksum(); + Assert.AreEqual( 0, crc32.Value ); + + crc32 = new CRC32Checksum(1); + Assert.AreEqual( 1, crc32.Value ); + + crc32 = new CRC32Checksum(556); + Assert.AreEqual( 556, crc32.Value ); + } + + [Test] + public void CRC32_Data() + { + CRC32Checksum crc32 = new CRC32Checksum(); + byte[] data = { 1,2,3,4,5,6,7 }; + crc32.Update(data); + Assert.AreEqual( 0x70e46888, crc32.Value ); + + crc32 = new CRC32Checksum(); + crc32.Update("penguin"); + Assert.AreEqual( 0x0e5c1a120, crc32.Value ); + + crc32 = new CRC32Checksum(1); + crc32.Update("penguin"); + Assert.AreEqual(0x43b6aa94, crc32.Value); + + } + #endregion + + #region Adler tests + + [Test] + public void Adler_Null() + { + AdlerChecksum adler = new AdlerChecksum(); + Assert.AreEqual(0, adler.Value); + + adler = new AdlerChecksum(1); + Assert.AreEqual( 1, adler.Value ); + + adler = new AdlerChecksum(556); + Assert.AreEqual( 556, adler.Value ); + } + + [Test] + public void Adler_Data() + { + AdlerChecksum adler = new AdlerChecksum(1); + byte[] data = { 1,2,3,4,5,6,7 }; + adler.Update(data); + Assert.AreEqual( 0x5b001d, adler.Value ); + + adler = new AdlerChecksum(); + adler.Update("penguin"); + Assert.AreEqual(0x0bcf02f6, adler.Value ); + + adler = new AdlerChecksum(1); + adler.Update("penguin"); + Assert.AreEqual(0x0bd602f7, adler.Value); + + } + #endregion + } + + [TestFixture] + public class InfoTests + { + #region Info tests + [Test] + public void Info_Version() + { + Info info = new Info(); + Assert.AreEqual("1.2.11", Info.Version); + Assert.AreEqual(32, info.SizeOfUInt); + Assert.AreEqual(32, info.SizeOfULong); + Assert.AreEqual(32, info.SizeOfPointer); + Assert.AreEqual(32, info.SizeOfOffset); + } + #endregion + } + + [TestFixture] + public class DeflateInflateTests + { + #region Deflate tests + [Test] + public void Deflate_Init() + { + using (Deflater def = new Deflater(CompressLevel.Default)) + { + } + } + + private ArrayList compressedData = new ArrayList(); + private uint adler1; + + private ArrayList uncompressedData = new ArrayList(); + private uint adler2; + + public void CDataAvail(byte[] data, int startIndex, int count) + { + for (int i = 0; i < count; ++i) + compressedData.Add(data[i+startIndex]); + } + + [Test] + public void Deflate_Compress() + { + compressedData.Clear(); + + byte[] testData = new byte[35000]; + for (int i = 0; i < testData.Length; ++i) + testData[i] = 5; + + using (Deflater def = new Deflater((CompressLevel)5)) + { + def.DataAvailable += new DataAvailableHandler(CDataAvail); + def.Add(testData); + def.Finish(); + adler1 = def.Checksum; + } + } + #endregion + + #region Inflate tests + [Test] + public void Inflate_Init() + { + using (Inflater inf = new Inflater()) + { + } + } + + private void DDataAvail(byte[] data, int startIndex, int count) + { + for (int i = 0; i < count; ++i) + uncompressedData.Add(data[i+startIndex]); + } + + [Test] + public void Inflate_Expand() + { + uncompressedData.Clear(); + + using (Inflater inf = new Inflater()) + { + inf.DataAvailable += new DataAvailableHandler(DDataAvail); + inf.Add((byte[])compressedData.ToArray(typeof(byte))); + inf.Finish(); + adler2 = inf.Checksum; + } + Assert.AreEqual( adler1, adler2 ); + } + #endregion + } + + [TestFixture] + public class GZipStreamTests + { + #region GZipStream test + [Test] + public void GZipStream_WriteRead() + { + using (GZipStream gzOut = new GZipStream("gzstream.gz", CompressLevel.Best)) + { + BinaryWriter writer = new BinaryWriter(gzOut); + writer.Write("hi there"); + writer.Write(Math.PI); + writer.Write(42); + } + + using (GZipStream gzIn = new GZipStream("gzstream.gz")) + { + BinaryReader reader = new BinaryReader(gzIn); + string s = reader.ReadString(); + Assert.AreEqual("hi there",s); + double d = reader.ReadDouble(); + Assert.AreEqual(Math.PI, d); + int i = reader.ReadInt32(); + Assert.AreEqual(42,i); + } + + } + #endregion + } +} + +#endif diff --git a/dependencies/zlib-1.2.11/contrib/dotzlib/LICENSE_1_0.txt b/dependencies/zlib-1.2.11/contrib/dotzlib/LICENSE_1_0.txt new file mode 100644 index 0000000..30aac2c --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/dotzlib/LICENSE_1_0.txt @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/dotzlib/readme.txt b/dependencies/zlib-1.2.11/contrib/dotzlib/readme.txt new file mode 100644 index 0000000..b239572 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/dotzlib/readme.txt @@ -0,0 +1,58 @@ +This directory contains a .Net wrapper class library for the ZLib1.dll + +The wrapper includes support for inflating/deflating memory buffers, +.Net streaming wrappers for the gz streams part of zlib, and wrappers +for the checksum parts of zlib. See DotZLib/UnitTests.cs for examples. + +Directory structure: +-------------------- + +LICENSE_1_0.txt - License file. +readme.txt - This file. +DotZLib.chm - Class library documentation +DotZLib.build - NAnt build file +DotZLib.sln - Microsoft Visual Studio 2003 solution file + +DotZLib\*.cs - Source files for the class library + +Unit tests: +----------- +The file DotZLib/UnitTests.cs contains unit tests for use with NUnit 2.1 or higher. +To include unit tests in the build, define nunit before building. + + +Build instructions: +------------------- + +1. Using Visual Studio.Net 2003: + Open DotZLib.sln in VS.Net and build from there. Output file (DotZLib.dll) + will be found ./DotZLib/bin/release or ./DotZLib/bin/debug, depending on + you are building the release or debug version of the library. Check + DotZLib/UnitTests.cs for instructions on how to include unit tests in the + build. + +2. Using NAnt: + Open a command prompt with access to the build environment and run nant + in the same directory as the DotZLib.build file. + You can define 2 properties on the nant command-line to control the build: + debug={true|false} to toggle between release/debug builds (default=true). + nunit={true|false} to include or esclude unit tests (default=true). + Also the target clean will remove binaries. + Output file (DotZLib.dll) will be found in either ./DotZLib/bin/release + or ./DotZLib/bin/debug, depending on whether you are building the release + or debug version of the library. + + Examples: + nant -D:debug=false -D:nunit=false + will build a release mode version of the library without unit tests. + nant + will build a debug version of the library with unit tests + nant clean + will remove all previously built files. + + +--------------------------------- +Copyright (c) Henrik Ravn 2004 + +Use, modification and distribution are subject to the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/dependencies/zlib-1.2.11/contrib/gcc_gvmat64/gvmat64.S b/dependencies/zlib-1.2.11/contrib/gcc_gvmat64/gvmat64.S new file mode 100644 index 0000000..dd858dd --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/gcc_gvmat64/gvmat64.S @@ -0,0 +1,574 @@ +/* +;uInt longest_match_x64( +; deflate_state *s, +; IPos cur_match); // current match + +; gvmat64.S -- Asm portion of the optimized longest_match for 32 bits x86_64 +; (AMD64 on Athlon 64, Opteron, Phenom +; and Intel EM64T on Pentium 4 with EM64T, Pentium D, Core 2 Duo, Core I5/I7) +; this file is translation from gvmat64.asm to GCC 4.x (for Linux, Mac XCode) +; Copyright (C) 1995-2010 Jean-loup Gailly, Brian Raiter and Gilles Vollant. +; +; File written by Gilles Vollant, by converting to assembly the longest_match +; from Jean-loup Gailly in deflate.c of zLib and infoZip zip. +; and by taking inspiration on asm686 with masm, optimised assembly code +; from Brian Raiter, written 1998 +; +; This software is provided 'as-is', without any express or implied +; warranty. In no event will the authors be held liable for any damages +; arising from the use of this software. +; +; Permission is granted to anyone to use this software for any purpose, +; including commercial applications, and to alter it and redistribute it +; freely, subject to the following restrictions: +; +; 1. The origin of this software must not be misrepresented; you must not +; claim that you wrote the original software. If you use this software +; in a product, an acknowledgment in the product documentation would be +; appreciated but is not required. +; 2. Altered source versions must be plainly marked as such, and must not be +; misrepresented as being the original software +; 3. This notice may not be removed or altered from any source distribution. +; +; http://www.zlib.net +; http://www.winimage.com/zLibDll +; http://www.muppetlabs.com/~breadbox/software/assembly.html +; +; to compile this file for zLib, I use option: +; gcc -c -arch x86_64 gvmat64.S + + +;uInt longest_match(s, cur_match) +; deflate_state *s; +; IPos cur_match; // current match / +; +; with XCode for Mac, I had strange error with some jump on intel syntax +; this is why BEFORE_JMP and AFTER_JMP are used + */ + + +#define BEFORE_JMP .att_syntax +#define AFTER_JMP .intel_syntax noprefix + +#ifndef NO_UNDERLINE +# define match_init _match_init +# define longest_match _longest_match +#endif + +.intel_syntax noprefix + +.globl match_init, longest_match +.text +longest_match: + + + +#define LocalVarsSize 96 +/* +; register used : rax,rbx,rcx,rdx,rsi,rdi,r8,r9,r10,r11,r12 +; free register : r14,r15 +; register can be saved : rsp +*/ + +#define chainlenwmask (rsp + 8 - LocalVarsSize) +#define nicematch (rsp + 16 - LocalVarsSize) + +#define save_rdi (rsp + 24 - LocalVarsSize) +#define save_rsi (rsp + 32 - LocalVarsSize) +#define save_rbx (rsp + 40 - LocalVarsSize) +#define save_rbp (rsp + 48 - LocalVarsSize) +#define save_r12 (rsp + 56 - LocalVarsSize) +#define save_r13 (rsp + 64 - LocalVarsSize) +#define save_r14 (rsp + 72 - LocalVarsSize) +#define save_r15 (rsp + 80 - LocalVarsSize) + + +/* +; all the +4 offsets are due to the addition of pending_buf_size (in zlib +; in the deflate_state structure since the asm code was first written +; (if you compile with zlib 1.0.4 or older, remove the +4). +; Note : these value are good with a 8 bytes boundary pack structure +*/ + +#define MAX_MATCH 258 +#define MIN_MATCH 3 +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) + +/* +;;; Offsets for fields in the deflate_state structure. These numbers +;;; are calculated from the definition of deflate_state, with the +;;; assumption that the compiler will dword-align the fields. (Thus, +;;; changing the definition of deflate_state could easily cause this +;;; program to crash horribly, without so much as a warning at +;;; compile time. Sigh.) + +; all the +zlib1222add offsets are due to the addition of fields +; in zlib in the deflate_state structure since the asm code was first written +; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). +; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). +; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). +*/ + + + +/* you can check the structure offset by running + +#include +#include +#include "deflate.h" + +void print_depl() +{ +deflate_state ds; +deflate_state *s=&ds; +printf("size pointer=%u\n",(int)sizeof(void*)); + +printf("#define dsWSize %u\n",(int)(((char*)&(s->w_size))-((char*)s))); +printf("#define dsWMask %u\n",(int)(((char*)&(s->w_mask))-((char*)s))); +printf("#define dsWindow %u\n",(int)(((char*)&(s->window))-((char*)s))); +printf("#define dsPrev %u\n",(int)(((char*)&(s->prev))-((char*)s))); +printf("#define dsMatchLen %u\n",(int)(((char*)&(s->match_length))-((char*)s))); +printf("#define dsPrevMatch %u\n",(int)(((char*)&(s->prev_match))-((char*)s))); +printf("#define dsStrStart %u\n",(int)(((char*)&(s->strstart))-((char*)s))); +printf("#define dsMatchStart %u\n",(int)(((char*)&(s->match_start))-((char*)s))); +printf("#define dsLookahead %u\n",(int)(((char*)&(s->lookahead))-((char*)s))); +printf("#define dsPrevLen %u\n",(int)(((char*)&(s->prev_length))-((char*)s))); +printf("#define dsMaxChainLen %u\n",(int)(((char*)&(s->max_chain_length))-((char*)s))); +printf("#define dsGoodMatch %u\n",(int)(((char*)&(s->good_match))-((char*)s))); +printf("#define dsNiceMatch %u\n",(int)(((char*)&(s->nice_match))-((char*)s))); +} +*/ + +#define dsWSize 68 +#define dsWMask 76 +#define dsWindow 80 +#define dsPrev 96 +#define dsMatchLen 144 +#define dsPrevMatch 148 +#define dsStrStart 156 +#define dsMatchStart 160 +#define dsLookahead 164 +#define dsPrevLen 168 +#define dsMaxChainLen 172 +#define dsGoodMatch 188 +#define dsNiceMatch 192 + +#define window_size [ rcx + dsWSize] +#define WMask [ rcx + dsWMask] +#define window_ad [ rcx + dsWindow] +#define prev_ad [ rcx + dsPrev] +#define strstart [ rcx + dsStrStart] +#define match_start [ rcx + dsMatchStart] +#define Lookahead [ rcx + dsLookahead] //; 0ffffffffh on infozip +#define prev_length [ rcx + dsPrevLen] +#define max_chain_length [ rcx + dsMaxChainLen] +#define good_match [ rcx + dsGoodMatch] +#define nice_match [ rcx + dsNiceMatch] + +/* +; windows: +; parameter 1 in rcx(deflate state s), param 2 in rdx (cur match) + +; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and +; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp +; +; All registers must be preserved across the call, except for +; rax, rcx, rdx, r8, r9, r10, and r11, which are scratch. + +; +; gcc on macosx-linux: +; see http://www.x86-64.org/documentation/abi-0.99.pdf +; param 1 in rdi, param 2 in rsi +; rbx, rsp, rbp, r12 to r15 must be preserved + +;;; Save registers that the compiler may be using, and adjust esp to +;;; make room for our stack frame. + + +;;; Retrieve the function arguments. r8d will hold cur_match +;;; throughout the entire function. edx will hold the pointer to the +;;; deflate_state structure during the function's setup (before +;;; entering the main loop. + +; ms: parameter 1 in rcx (deflate_state* s), param 2 in edx -> r8 (cur match) +; mac: param 1 in rdi, param 2 rsi +; this clear high 32 bits of r8, which can be garbage in both r8 and rdx +*/ + mov [save_rbx],rbx + mov [save_rbp],rbp + + + mov rcx,rdi + + mov r8d,esi + + + mov [save_r12],r12 + mov [save_r13],r13 + mov [save_r14],r14 + mov [save_r15],r15 + + +//;;; uInt wmask = s->w_mask; +//;;; unsigned chain_length = s->max_chain_length; +//;;; if (s->prev_length >= s->good_match) { +//;;; chain_length >>= 2; +//;;; } + + + mov edi, prev_length + mov esi, good_match + mov eax, WMask + mov ebx, max_chain_length + cmp edi, esi + jl LastMatchGood + shr ebx, 2 +LastMatchGood: + +//;;; chainlen is decremented once beforehand so that the function can +//;;; use the sign flag instead of the zero flag for the exit test. +//;;; It is then shifted into the high word, to make room for the wmask +//;;; value, which it will always accompany. + + dec ebx + shl ebx, 16 + or ebx, eax + +//;;; on zlib only +//;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + + + mov eax, nice_match + mov [chainlenwmask], ebx + mov r10d, Lookahead + cmp r10d, eax + cmovnl r10d, eax + mov [nicematch],r10d + + + +//;;; register Bytef *scan = s->window + s->strstart; + mov r10, window_ad + mov ebp, strstart + lea r13, [r10 + rbp] + +//;;; Determine how many bytes the scan ptr is off from being +//;;; dword-aligned. + + mov r9,r13 + neg r13 + and r13,3 + +//;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ? +//;;; s->strstart - (IPos)MAX_DIST(s) : NIL; + + + mov eax, window_size + sub eax, MIN_LOOKAHEAD + + + xor edi,edi + sub ebp, eax + + mov r11d, prev_length + + cmovng ebp,edi + +//;;; int best_len = s->prev_length; + + +//;;; Store the sum of s->window + best_len in esi locally, and in esi. + + lea rsi,[r10+r11] + +//;;; register ush scan_start = *(ushf*)scan; +//;;; register ush scan_end = *(ushf*)(scan+best_len-1); +//;;; Posf *prev = s->prev; + + movzx r12d,word ptr [r9] + movzx ebx, word ptr [r9 + r11 - 1] + + mov rdi, prev_ad + +//;;; Jump into the main loop. + + mov edx, [chainlenwmask] + + cmp bx,word ptr [rsi + r8 - 1] + jz LookupLoopIsZero + + + +LookupLoop1: + and r8d, edx + + movzx r8d, word ptr [rdi + r8*2] + cmp r8d, ebp + jbe LeaveNow + + + + sub edx, 0x00010000 + BEFORE_JMP + js LeaveNow + AFTER_JMP + +LoopEntry1: + cmp bx,word ptr [rsi + r8 - 1] + BEFORE_JMP + jz LookupLoopIsZero + AFTER_JMP + +LookupLoop2: + and r8d, edx + + movzx r8d, word ptr [rdi + r8*2] + cmp r8d, ebp + BEFORE_JMP + jbe LeaveNow + AFTER_JMP + sub edx, 0x00010000 + BEFORE_JMP + js LeaveNow + AFTER_JMP + +LoopEntry2: + cmp bx,word ptr [rsi + r8 - 1] + BEFORE_JMP + jz LookupLoopIsZero + AFTER_JMP + +LookupLoop4: + and r8d, edx + + movzx r8d, word ptr [rdi + r8*2] + cmp r8d, ebp + BEFORE_JMP + jbe LeaveNow + AFTER_JMP + sub edx, 0x00010000 + BEFORE_JMP + js LeaveNow + AFTER_JMP + +LoopEntry4: + + cmp bx,word ptr [rsi + r8 - 1] + BEFORE_JMP + jnz LookupLoop1 + jmp LookupLoopIsZero + AFTER_JMP +/* +;;; do { +;;; match = s->window + cur_match; +;;; if (*(ushf*)(match+best_len-1) != scan_end || +;;; *(ushf*)match != scan_start) continue; +;;; [...] +;;; } while ((cur_match = prev[cur_match & wmask]) > limit +;;; && --chain_length != 0); +;;; +;;; Here is the inner loop of the function. The function will spend the +;;; majority of its time in this loop, and majority of that time will +;;; be spent in the first ten instructions. +;;; +;;; Within this loop: +;;; ebx = scanend +;;; r8d = curmatch +;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) +;;; esi = windowbestlen - i.e., (window + bestlen) +;;; edi = prev +;;; ebp = limit +*/ +.balign 16 +LookupLoop: + and r8d, edx + + movzx r8d, word ptr [rdi + r8*2] + cmp r8d, ebp + BEFORE_JMP + jbe LeaveNow + AFTER_JMP + sub edx, 0x00010000 + BEFORE_JMP + js LeaveNow + AFTER_JMP + +LoopEntry: + + cmp bx,word ptr [rsi + r8 - 1] + BEFORE_JMP + jnz LookupLoop1 + AFTER_JMP +LookupLoopIsZero: + cmp r12w, word ptr [r10 + r8] + BEFORE_JMP + jnz LookupLoop1 + AFTER_JMP + + +//;;; Store the current value of chainlen. + mov [chainlenwmask], edx +/* +;;; Point edi to the string under scrutiny, and esi to the string we +;;; are hoping to match it up with. In actuality, esi and edi are +;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is +;;; initialized to -(MAX_MATCH_8 - scanalign). +*/ + lea rsi,[r8+r10] + mov rdx, 0xfffffffffffffef8 //; -(MAX_MATCH_8) + lea rsi, [rsi + r13 + 0x0108] //;MAX_MATCH_8] + lea rdi, [r9 + r13 + 0x0108] //;MAX_MATCH_8] + + prefetcht1 [rsi+rdx] + prefetcht1 [rdi+rdx] + +/* +;;; Test the strings for equality, 8 bytes at a time. At the end, +;;; adjust rdx so that it is offset to the exact byte that mismatched. +;;; +;;; We already know at this point that the first three bytes of the +;;; strings match each other, and they can be safely passed over before +;;; starting the compare loop. So what this code does is skip over 0-3 +;;; bytes, as much as necessary in order to dword-align the edi +;;; pointer. (rsi will still be misaligned three times out of four.) +;;; +;;; It should be confessed that this loop usually does not represent +;;; much of the total running time. Replacing it with a more +;;; straightforward "rep cmpsb" would not drastically degrade +;;; performance. +*/ + +LoopCmps: + mov rax, [rsi + rdx] + xor rax, [rdi + rdx] + jnz LeaveLoopCmps + + mov rax, [rsi + rdx + 8] + xor rax, [rdi + rdx + 8] + jnz LeaveLoopCmps8 + + + mov rax, [rsi + rdx + 8+8] + xor rax, [rdi + rdx + 8+8] + jnz LeaveLoopCmps16 + + add rdx,8+8+8 + + BEFORE_JMP + jnz LoopCmps + jmp LenMaximum + AFTER_JMP + +LeaveLoopCmps16: add rdx,8 +LeaveLoopCmps8: add rdx,8 +LeaveLoopCmps: + + test eax, 0x0000FFFF + jnz LenLower + + test eax,0xffffffff + + jnz LenLower32 + + add rdx,4 + shr rax,32 + or ax,ax + BEFORE_JMP + jnz LenLower + AFTER_JMP + +LenLower32: + shr eax,16 + add rdx,2 + +LenLower: + sub al, 1 + adc rdx, 0 +//;;; Calculate the length of the match. If it is longer than MAX_MATCH, +//;;; then automatically accept it as the best possible match and leave. + + lea rax, [rdi + rdx] + sub rax, r9 + cmp eax, MAX_MATCH + BEFORE_JMP + jge LenMaximum + AFTER_JMP +/* +;;; If the length of the match is not longer than the best match we +;;; have so far, then forget it and return to the lookup loop. +;/////////////////////////////////// +*/ + cmp eax, r11d + jg LongerMatch + + lea rsi,[r10+r11] + + mov rdi, prev_ad + mov edx, [chainlenwmask] + BEFORE_JMP + jmp LookupLoop + AFTER_JMP +/* +;;; s->match_start = cur_match; +;;; best_len = len; +;;; if (len >= nice_match) break; +;;; scan_end = *(ushf*)(scan+best_len-1); +*/ +LongerMatch: + mov r11d, eax + mov match_start, r8d + cmp eax, [nicematch] + BEFORE_JMP + jge LeaveNow + AFTER_JMP + + lea rsi,[r10+rax] + + movzx ebx, word ptr [r9 + rax - 1] + mov rdi, prev_ad + mov edx, [chainlenwmask] + BEFORE_JMP + jmp LookupLoop + AFTER_JMP + +//;;; Accept the current string, with the maximum possible length. + +LenMaximum: + mov r11d,MAX_MATCH + mov match_start, r8d + +//;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len; +//;;; return s->lookahead; + +LeaveNow: + mov eax, Lookahead + cmp r11d, eax + cmovng eax, r11d + + + +//;;; Restore the stack and return from whence we came. + + +// mov rsi,[save_rsi] +// mov rdi,[save_rdi] + mov rbx,[save_rbx] + mov rbp,[save_rbp] + mov r12,[save_r12] + mov r13,[save_r13] + mov r14,[save_r14] + mov r15,[save_r15] + + + ret 0 +//; please don't remove this string ! +//; Your can freely use gvmat64 in any free or commercial app +//; but it is far better don't remove the string in the binary! + // db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998, converted to amd 64 by Gilles Vollant 2005",0dh,0ah,0 + + +match_init: + ret 0 + + diff --git a/dependencies/zlib-1.2.11/contrib/infback9/README b/dependencies/zlib-1.2.11/contrib/infback9/README new file mode 100644 index 0000000..e75ed13 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/infback9/README @@ -0,0 +1 @@ +See infback9.h for what this is and how to use it. diff --git a/dependencies/zlib-1.2.11/contrib/infback9/infback9.c b/dependencies/zlib-1.2.11/contrib/infback9/infback9.c new file mode 100644 index 0000000..05fb3e3 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/infback9/infback9.c @@ -0,0 +1,615 @@ +/* infback9.c -- inflate deflate64 data using a call-back interface + * Copyright (C) 1995-2008 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "infback9.h" +#include "inftree9.h" +#include "inflate9.h" + +#define WSIZE 65536UL + +/* + strm provides memory allocation functions in zalloc and zfree, or + Z_NULL to use the library memory allocation functions. + + window is a user-supplied window and output buffer that is 64K bytes. + */ +int ZEXPORT inflateBack9Init_(strm, window, version, stream_size) +z_stream FAR *strm; +unsigned char FAR *window; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL || window == Z_NULL) + return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *)ZALLOC(strm, 1, + sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (voidpf)state; + state->window = window; + return Z_OK; +} + +/* + Build and output length and distance decoding tables for fixed code + decoding. + */ +#ifdef MAKEFIXED +#include + +void makefixed9(void) +{ + unsigned sym, bits, low, size; + code *next, *lenfix, *distfix; + struct inflate_state state; + code fixed[544]; + + /* literal/length table */ + sym = 0; + while (sym < 144) state.lens[sym++] = 8; + while (sym < 256) state.lens[sym++] = 9; + while (sym < 280) state.lens[sym++] = 7; + while (sym < 288) state.lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table9(LENS, state.lens, 288, &(next), &(bits), state.work); + + /* distance table */ + sym = 0; + while (sym < 32) state.lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table9(DISTS, state.lens, 32, &(next), &(bits), state.work); + + /* write tables */ + puts(" /* inffix9.h -- table for decoding deflate64 fixed codes"); + puts(" * Generated automatically by makefixed9()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", lenfix[low].op, lenfix[low].bits, + lenfix[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 5) == 0) printf("\n "); + printf("{%u,%u,%d}", distfix[low].op, distfix[low].bits, + distfix[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* Macros for inflateBack(): */ + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Assure that some input is available. If input is requested, but denied, + then return a Z_BUF_ERROR from inflateBack(). */ +#define PULL() \ + do { \ + if (have == 0) { \ + have = in(in_desc, &next); \ + if (have == 0) { \ + next = Z_NULL; \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflateBack() + with an error if there is no input available. */ +#define PULLBYTE() \ + do { \ + PULL(); \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflateBack() with + an error. */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n <= 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Assure that some output space is available, by writing out the window + if it's full. If the write fails, return from inflateBack() with a + Z_BUF_ERROR. */ +#define ROOM() \ + do { \ + if (left == 0) { \ + put = window; \ + left = WSIZE; \ + wrap = 1; \ + if (out(out_desc, put, (unsigned)left)) { \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* + strm provides the memory allocation functions and window buffer on input, + and provides information on the unused input on return. For Z_DATA_ERROR + returns, strm will also provide an error message. + + in() and out() are the call-back input and output functions. When + inflateBack() needs more input, it calls in(). When inflateBack() has + filled the window with output, or when it completes with data in the + window, it calls out() to write out the data. The application must not + change the provided input until in() is called again or inflateBack() + returns. The application must not change the window/output buffer until + inflateBack() returns. + + in() and out() are called with a descriptor parameter provided in the + inflateBack() call. This parameter can be a structure that provides the + information required to do the read or write, as well as accumulated + information on the input and output such as totals and check values. + + in() should return zero on failure. out() should return non-zero on + failure. If either in() or out() fails, than inflateBack() returns a + Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it + was in() or out() that caused in the error. Otherwise, inflateBack() + returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format + error, or Z_MEM_ERROR if it could not allocate memory for the state. + inflateBack() can also return Z_STREAM_ERROR if the input parameters + are not correct, i.e. strm is Z_NULL or the state was not initialized. + */ +int ZEXPORT inflateBack9(strm, in, in_desc, out, out_desc) +z_stream FAR *strm; +in_func in; +void FAR *in_desc; +out_func out; +void FAR *out_desc; +{ + struct inflate_state FAR *state; + z_const unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have; /* available input */ + unsigned long left; /* available output */ + inflate_mode mode; /* current inflate mode */ + int lastblock; /* true if processing last block */ + int wrap; /* true if the window has wrapped */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned extra; /* extra bits needed */ + unsigned long length; /* literal or length of data to copy */ + unsigned long offset; /* distance back to copy string from */ + unsigned long copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; +#include "inffix9.h" + + /* Check that the strm exists and that the state was initialized */ + if (strm == Z_NULL || strm->state == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* Reset the state */ + strm->msg = Z_NULL; + mode = TYPE; + lastblock = 0; + wrap = 0; + window = state->window; + next = strm->next_in; + have = next != Z_NULL ? strm->avail_in : 0; + hold = 0; + bits = 0; + put = window; + left = WSIZE; + lencode = Z_NULL; + distcode = Z_NULL; + + /* Inflate until end of block marked as last */ + for (;;) + switch (mode) { + case TYPE: + /* determine and dispatch block type */ + if (lastblock) { + BYTEBITS(); + mode = DONE; + break; + } + NEEDBITS(3); + lastblock = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + lastblock ? " (last)" : "")); + mode = STORED; + break; + case 1: /* fixed block */ + lencode = lenfix; + lenbits = 9; + distcode = distfix; + distbits = 5; + Tracev((stderr, "inflate: fixed codes block%s\n", + lastblock ? " (last)" : "")); + mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + lastblock ? " (last)" : "")); + mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + mode = BAD; + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + mode = BAD; + break; + } + length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %lu\n", + length)); + INITBITS(); + + /* copy stored block from input to output */ + while (length != 0) { + copy = length; + PULL(); + ROOM(); + if (copy > have) copy = have; + if (copy > left) copy = left; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + length -= copy; + } + Tracev((stderr, "inflate: stored end\n")); + mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); + if (state->nlen > 286) { + strm->msg = (char *)"too many length symbols"; + mode = BAD; + break; + } + Tracev((stderr, "inflate: table sizes ok\n")); + + /* get code length code lengths (not a typo) */ + state->have = 0; + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + lencode = (code const FAR *)(state->next); + lenbits = 7; + ret = inflate_table9(CODES, state->lens, 19, &(state->next), + &(lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + + /* get length and distance code code lengths */ + state->have = 0; + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = lencode[BITS(lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + NEEDBITS(here.bits); + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + mode = BAD; + break; + } + len = (unsigned)(state->lens[state->have - 1]); + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftree9.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + lencode = (code const FAR *)(state->next); + lenbits = 9; + ret = inflate_table9(LENS, state->lens, state->nlen, + &(state->next), &(lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + mode = BAD; + break; + } + distcode = (code const FAR *)(state->next); + distbits = 6; + ret = inflate_table9(DISTS, state->lens + state->nlen, + state->ndist, &(state->next), &(distbits), + state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + mode = LEN; + + case LEN: + /* get a literal, length, or end-of-block code */ + for (;;) { + here = lencode[BITS(lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(here.bits); + length = (unsigned)here.val; + + /* process literal */ + if (here.op == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + ROOM(); + *put++ = (unsigned char)(length); + left--; + mode = LEN; + break; + } + + /* process end of block */ + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + mode = TYPE; + break; + } + + /* invalid code */ + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + mode = BAD; + break; + } + + /* length code -- get extra bits, if any */ + extra = (unsigned)(here.op) & 31; + if (extra != 0) { + NEEDBITS(extra); + length += BITS(extra); + DROPBITS(extra); + } + Tracevv((stderr, "inflate: length %lu\n", length)); + + /* get distance code */ + for (;;) { + here = distcode[BITS(distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(here.bits); + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + mode = BAD; + break; + } + offset = (unsigned)here.val; + + /* get distance extra bits, if any */ + extra = (unsigned)(here.op) & 15; + if (extra != 0) { + NEEDBITS(extra); + offset += BITS(extra); + DROPBITS(extra); + } + if (offset > WSIZE - (wrap ? 0: left)) { + strm->msg = (char *)"invalid distance too far back"; + mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %lu\n", offset)); + + /* copy match from window to output */ + do { + ROOM(); + copy = WSIZE - offset; + if (copy < left) { + from = put + copy; + copy = left - copy; + } + else { + from = put - offset; + copy = left; + } + if (copy > length) copy = length; + length -= copy; + left -= copy; + do { + *put++ = *from++; + } while (--copy); + } while (length != 0); + break; + + case DONE: + /* inflate stream terminated properly -- write leftover output */ + ret = Z_STREAM_END; + if (left < WSIZE) { + if (out(out_desc, window, (unsigned)(WSIZE - left))) + ret = Z_BUF_ERROR; + } + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + default: /* can't happen, but makes compilers happy */ + ret = Z_STREAM_ERROR; + goto inf_leave; + } + + /* Return unused input */ + inf_leave: + strm->next_in = next; + strm->avail_in = have; + return ret; +} + +int ZEXPORT inflateBack9End(strm) +z_stream FAR *strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} diff --git a/dependencies/zlib-1.2.11/contrib/infback9/infback9.h b/dependencies/zlib-1.2.11/contrib/infback9/infback9.h new file mode 100644 index 0000000..1073c0a --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/infback9/infback9.h @@ -0,0 +1,37 @@ +/* infback9.h -- header for using inflateBack9 functions + * Copyright (C) 2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * This header file and associated patches provide a decoder for PKWare's + * undocumented deflate64 compression method (method 9). Use with infback9.c, + * inftree9.h, inftree9.c, and inffix9.h. These patches are not supported. + * This should be compiled with zlib, since it uses zutil.h and zutil.o. + * This code has not yet been tested on 16-bit architectures. See the + * comments in zlib.h for inflateBack() usage. These functions are used + * identically, except that there is no windowBits parameter, and a 64K + * window must be provided. Also if int's are 16 bits, then a zero for + * the third parameter of the "out" function actually means 65536UL. + * zlib.h must be included before this header file. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +ZEXTERN int ZEXPORT inflateBack9 OF((z_stream FAR *strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +ZEXTERN int ZEXPORT inflateBack9End OF((z_stream FAR *strm)); +ZEXTERN int ZEXPORT inflateBack9Init_ OF((z_stream FAR *strm, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define inflateBack9Init(strm, window) \ + inflateBack9Init_((strm), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + +#ifdef __cplusplus +} +#endif diff --git a/dependencies/zlib-1.2.11/contrib/infback9/inffix9.h b/dependencies/zlib-1.2.11/contrib/infback9/inffix9.h new file mode 100644 index 0000000..ee5671d --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/infback9/inffix9.h @@ -0,0 +1,107 @@ + /* inffix9.h -- table for decoding deflate64 fixed codes + * Generated automatically by makefixed9(). + */ + + /* WARNING: this file should *not* be used by applications. + It is part of the implementation of this library and is + subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{132,8,115},{130,7,31},{0,8,112}, + {0,8,48},{0,9,192},{128,7,10},{0,8,96},{0,8,32},{0,9,160}, + {0,8,0},{0,8,128},{0,8,64},{0,9,224},{128,7,6},{0,8,88}, + {0,8,24},{0,9,144},{131,7,59},{0,8,120},{0,8,56},{0,9,208}, + {129,7,17},{0,8,104},{0,8,40},{0,9,176},{0,8,8},{0,8,136}, + {0,8,72},{0,9,240},{128,7,4},{0,8,84},{0,8,20},{133,8,227}, + {131,7,43},{0,8,116},{0,8,52},{0,9,200},{129,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232}, + {128,7,8},{0,8,92},{0,8,28},{0,9,152},{132,7,83},{0,8,124}, + {0,8,60},{0,9,216},{130,7,23},{0,8,108},{0,8,44},{0,9,184}, + {0,8,12},{0,8,140},{0,8,76},{0,9,248},{128,7,3},{0,8,82}, + {0,8,18},{133,8,163},{131,7,35},{0,8,114},{0,8,50},{0,9,196}, + {129,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},{0,8,130}, + {0,8,66},{0,9,228},{128,7,7},{0,8,90},{0,8,26},{0,9,148}, + {132,7,67},{0,8,122},{0,8,58},{0,9,212},{130,7,19},{0,8,106}, + {0,8,42},{0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244}, + {128,7,5},{0,8,86},{0,8,22},{65,8,0},{131,7,51},{0,8,118}, + {0,8,54},{0,9,204},{129,7,15},{0,8,102},{0,8,38},{0,9,172}, + {0,8,6},{0,8,134},{0,8,70},{0,9,236},{128,7,9},{0,8,94}, + {0,8,30},{0,9,156},{132,7,99},{0,8,126},{0,8,62},{0,9,220}, + {130,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{133,8,131}, + {130,7,31},{0,8,113},{0,8,49},{0,9,194},{128,7,10},{0,8,97}, + {0,8,33},{0,9,162},{0,8,1},{0,8,129},{0,8,65},{0,9,226}, + {128,7,6},{0,8,89},{0,8,25},{0,9,146},{131,7,59},{0,8,121}, + {0,8,57},{0,9,210},{129,7,17},{0,8,105},{0,8,41},{0,9,178}, + {0,8,9},{0,8,137},{0,8,73},{0,9,242},{128,7,4},{0,8,85}, + {0,8,21},{144,8,3},{131,7,43},{0,8,117},{0,8,53},{0,9,202}, + {129,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133}, + {0,8,69},{0,9,234},{128,7,8},{0,8,93},{0,8,29},{0,9,154}, + {132,7,83},{0,8,125},{0,8,61},{0,9,218},{130,7,23},{0,8,109}, + {0,8,45},{0,9,186},{0,8,13},{0,8,141},{0,8,77},{0,9,250}, + {128,7,3},{0,8,83},{0,8,19},{133,8,195},{131,7,35},{0,8,115}, + {0,8,51},{0,9,198},{129,7,11},{0,8,99},{0,8,35},{0,9,166}, + {0,8,3},{0,8,131},{0,8,67},{0,9,230},{128,7,7},{0,8,91}, + {0,8,27},{0,9,150},{132,7,67},{0,8,123},{0,8,59},{0,9,214}, + {130,7,19},{0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139}, + {0,8,75},{0,9,246},{128,7,5},{0,8,87},{0,8,23},{77,8,0}, + {131,7,51},{0,8,119},{0,8,55},{0,9,206},{129,7,15},{0,8,103}, + {0,8,39},{0,9,174},{0,8,7},{0,8,135},{0,8,71},{0,9,238}, + {128,7,9},{0,8,95},{0,8,31},{0,9,158},{132,7,99},{0,8,127}, + {0,8,63},{0,9,222},{130,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80}, + {0,8,16},{132,8,115},{130,7,31},{0,8,112},{0,8,48},{0,9,193}, + {128,7,10},{0,8,96},{0,8,32},{0,9,161},{0,8,0},{0,8,128}, + {0,8,64},{0,9,225},{128,7,6},{0,8,88},{0,8,24},{0,9,145}, + {131,7,59},{0,8,120},{0,8,56},{0,9,209},{129,7,17},{0,8,104}, + {0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},{0,9,241}, + {128,7,4},{0,8,84},{0,8,20},{133,8,227},{131,7,43},{0,8,116}, + {0,8,52},{0,9,201},{129,7,13},{0,8,100},{0,8,36},{0,9,169}, + {0,8,4},{0,8,132},{0,8,68},{0,9,233},{128,7,8},{0,8,92}, + {0,8,28},{0,9,153},{132,7,83},{0,8,124},{0,8,60},{0,9,217}, + {130,7,23},{0,8,108},{0,8,44},{0,9,185},{0,8,12},{0,8,140}, + {0,8,76},{0,9,249},{128,7,3},{0,8,82},{0,8,18},{133,8,163}, + {131,7,35},{0,8,114},{0,8,50},{0,9,197},{129,7,11},{0,8,98}, + {0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {128,7,7},{0,8,90},{0,8,26},{0,9,149},{132,7,67},{0,8,122}, + {0,8,58},{0,9,213},{130,7,19},{0,8,106},{0,8,42},{0,9,181}, + {0,8,10},{0,8,138},{0,8,74},{0,9,245},{128,7,5},{0,8,86}, + {0,8,22},{65,8,0},{131,7,51},{0,8,118},{0,8,54},{0,9,205}, + {129,7,15},{0,8,102},{0,8,38},{0,9,173},{0,8,6},{0,8,134}, + {0,8,70},{0,9,237},{128,7,9},{0,8,94},{0,8,30},{0,9,157}, + {132,7,99},{0,8,126},{0,8,62},{0,9,221},{130,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253}, + {96,7,0},{0,8,81},{0,8,17},{133,8,131},{130,7,31},{0,8,113}, + {0,8,49},{0,9,195},{128,7,10},{0,8,97},{0,8,33},{0,9,163}, + {0,8,1},{0,8,129},{0,8,65},{0,9,227},{128,7,6},{0,8,89}, + {0,8,25},{0,9,147},{131,7,59},{0,8,121},{0,8,57},{0,9,211}, + {129,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},{0,8,137}, + {0,8,73},{0,9,243},{128,7,4},{0,8,85},{0,8,21},{144,8,3}, + {131,7,43},{0,8,117},{0,8,53},{0,9,203},{129,7,13},{0,8,101}, + {0,8,37},{0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235}, + {128,7,8},{0,8,93},{0,8,29},{0,9,155},{132,7,83},{0,8,125}, + {0,8,61},{0,9,219},{130,7,23},{0,8,109},{0,8,45},{0,9,187}, + {0,8,13},{0,8,141},{0,8,77},{0,9,251},{128,7,3},{0,8,83}, + {0,8,19},{133,8,195},{131,7,35},{0,8,115},{0,8,51},{0,9,199}, + {129,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{128,7,7},{0,8,91},{0,8,27},{0,9,151}, + {132,7,67},{0,8,123},{0,8,59},{0,9,215},{130,7,19},{0,8,107}, + {0,8,43},{0,9,183},{0,8,11},{0,8,139},{0,8,75},{0,9,247}, + {128,7,5},{0,8,87},{0,8,23},{77,8,0},{131,7,51},{0,8,119}, + {0,8,55},{0,9,207},{129,7,15},{0,8,103},{0,8,39},{0,9,175}, + {0,8,7},{0,8,135},{0,8,71},{0,9,239},{128,7,9},{0,8,95}, + {0,8,31},{0,9,159},{132,7,99},{0,8,127},{0,8,63},{0,9,223}, + {130,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143}, + {0,8,79},{0,9,255} + }; + + static const code distfix[32] = { + {128,5,1},{135,5,257},{131,5,17},{139,5,4097},{129,5,5}, + {137,5,1025},{133,5,65},{141,5,16385},{128,5,3},{136,5,513}, + {132,5,33},{140,5,8193},{130,5,9},{138,5,2049},{134,5,129}, + {142,5,32769},{128,5,2},{135,5,385},{131,5,25},{139,5,6145}, + {129,5,7},{137,5,1537},{133,5,97},{141,5,24577},{128,5,4}, + {136,5,769},{132,5,49},{140,5,12289},{130,5,13},{138,5,3073}, + {134,5,193},{142,5,49153} + }; diff --git a/dependencies/zlib-1.2.11/contrib/infback9/inflate9.h b/dependencies/zlib-1.2.11/contrib/infback9/inflate9.h new file mode 100644 index 0000000..ee9a793 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/infback9/inflate9.h @@ -0,0 +1,47 @@ +/* inflate9.h -- internal inflate state definition + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Possible inflate modes between inflate() calls */ +typedef enum { + TYPE, /* i: waiting for type bits, including last-flag bit */ + STORED, /* i: waiting for stored size (length and complement) */ + TABLE, /* i: waiting for dynamic block table lengths */ + LEN, /* i: waiting for length/lit code */ + DONE, /* finished check, done -- remain here until reset */ + BAD /* got a data error -- remain here until reset */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to the BAD mode -- not shown for clarity) + + Read deflate blocks: + TYPE -> STORED or TABLE or LEN or DONE + STORED -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN + Read deflate codes: + LEN -> LEN or TYPE + */ + +/* state maintained between inflate() calls. Approximately 7K bytes. */ +struct inflate_state { + /* sliding window */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ +}; diff --git a/dependencies/zlib-1.2.11/contrib/infback9/inftree9.c b/dependencies/zlib-1.2.11/contrib/infback9/inftree9.c new file mode 100644 index 0000000..5f4a767 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/infback9/inftree9.c @@ -0,0 +1,324 @@ +/* inftree9.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2017 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftree9.h" + +#define MAXBITS 15 + +const char inflate9_copyright[] = + " inflate9 1.2.11 Copyright 1995-2017 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int inflate_table9(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code this; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, + 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, + 131, 163, 195, 227, 3, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129, + 130, 130, 130, 130, 131, 131, 131, 131, 132, 132, 132, 132, + 133, 133, 133, 133, 144, 77, 202}; + static const unsigned short dbase[32] = { /* Distance codes 0..31 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, + 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, + 4097, 6145, 8193, 12289, 16385, 24577, 32769, 49153}; + static const unsigned short dext[32] = { /* Distance codes 0..31 extra */ + 128, 128, 128, 128, 129, 129, 130, 130, 131, 131, 132, 132, + 133, 133, 134, 134, 135, 135, 136, 136, 137, 137, 138, 138, + 139, 139, 140, 140, 141, 141, 142, 142}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) return -1; /* no codes! */ + for (min = 1; min <= MAXBITS; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftree9.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type == LENS && used >= ENOUGH_LENS) || + (type == DISTS && used >= ENOUGH_DISTS)) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + this.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + this.op = (unsigned char)0; + this.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + this.op = (unsigned char)(extra[work[sym]]); + this.val = base[work[sym]]; + } + else { + this.op = (unsigned char)(32 + 64); /* end of block */ + this.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + do { + fill -= incr; + next[(huff >> drop) + fill] = this; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += 1U << curr; + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if ((type == LENS && used >= ENOUGH_LENS) || + (type == DISTS && used >= ENOUGH_DISTS)) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)(len - drop); + this.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + curr = root; + this.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = this; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/dependencies/zlib-1.2.11/contrib/infback9/inftree9.h b/dependencies/zlib-1.2.11/contrib/infback9/inftree9.h new file mode 100644 index 0000000..5ab21f0 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/infback9/inftree9.h @@ -0,0 +1,61 @@ +/* inftree9.h -- header to use inftree9.c + * Copyright (C) 1995-2008 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 100eeeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of the dynamic table. The maximum number of code structures is + 1446, which is the sum of 852 for literal/length codes and 594 for distance + codes. These values were found by exhaustive searches using the program + examples/enough.c found in the zlib distribtution. The arguments to that + program are the number of symbols, the initial root table size, and the + maximum bit length of a code. "enough 286 9 15" for literal/length codes + returns returns 852, and "enough 32 6 15" for distance codes returns 594. + The initial root table size (9 or 6) is found in the fifth argument of the + inflate_table() calls in infback9.c. If the root table size is changed, + then these maximum sizes would be need to be recalculated and updated. */ +#define ENOUGH_LENS 852 +#define ENOUGH_DISTS 594 +#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) + +/* Type of code to build for inflate_table9() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +extern int inflate_table9 OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/dependencies/zlib-1.2.11/contrib/inflate86/inffas86.c b/dependencies/zlib-1.2.11/contrib/inflate86/inffas86.c new file mode 100644 index 0000000..7292f67 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/inflate86/inffas86.c @@ -0,0 +1,1157 @@ +/* inffas86.c is a hand tuned assembler version of + * + * inffast.c -- fast decoding + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Copyright (C) 2003 Chris Anderson + * Please use the copyright conditions above. + * + * Dec-29-2003 -- I added AMD64 inflate asm support. This version is also + * slightly quicker on x86 systems because, instead of using rep movsb to copy + * data, it uses rep movsw, which moves data in 2-byte chunks instead of single + * bytes. I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates + * from http://fedora.linux.duke.edu/fc1_x86_64 + * which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with + * 1GB ram. The 64-bit version is about 4% faster than the 32-bit version, + * when decompressing mozilla-source-1.3.tar.gz. + * + * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from + * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at + * the moment. I have successfully compiled and tested this code with gcc2.96, + * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S + * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX + * enabled. I will attempt to merge the MMX code into this version. Newer + * versions of this and inffast.S can be found at + * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/ + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* Mark Adler's comments from inffast.c: */ + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + struct inffast_ar { +/* 64 32 x86 x86_64 */ +/* ar offset register */ +/* 0 0 */ void *esp; /* esp save */ +/* 8 4 */ void *ebp; /* ebp save */ +/* 16 8 */ unsigned char FAR *in; /* esi rsi local strm->next_in */ +/* 24 12 */ unsigned char FAR *last; /* r9 while in < last */ +/* 32 16 */ unsigned char FAR *out; /* edi rdi local strm->next_out */ +/* 40 20 */ unsigned char FAR *beg; /* inflate()'s init next_out */ +/* 48 24 */ unsigned char FAR *end; /* r10 while out < end */ +/* 56 28 */ unsigned char FAR *window;/* size of window, wsize!=0 */ +/* 64 32 */ code const FAR *lcode; /* ebp rbp local strm->lencode */ +/* 72 36 */ code const FAR *dcode; /* r11 local strm->distcode */ +/* 80 40 */ unsigned long hold; /* edx rdx local strm->hold */ +/* 88 44 */ unsigned bits; /* ebx rbx local strm->bits */ +/* 92 48 */ unsigned wsize; /* window size */ +/* 96 52 */ unsigned write; /* window write index */ +/*100 56 */ unsigned lmask; /* r12 mask for lcode */ +/*104 60 */ unsigned dmask; /* r13 mask for dcode */ +/*108 64 */ unsigned len; /* r14 match length */ +/*112 68 */ unsigned dist; /* r15 match distance */ +/*116 72 */ unsigned status; /* set when state chng*/ + } ar; + +#if defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 ) +#define PAD_AVAIL_IN 6 +#define PAD_AVAIL_OUT 258 +#else +#define PAD_AVAIL_IN 5 +#define PAD_AVAIL_OUT 257 +#endif + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + ar.in = strm->next_in; + ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN); + ar.out = strm->next_out; + ar.beg = ar.out - (start - strm->avail_out); + ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT); + ar.wsize = state->wsize; + ar.write = state->wnext; + ar.window = state->window; + ar.hold = state->hold; + ar.bits = state->bits; + ar.lcode = state->lencode; + ar.dcode = state->distcode; + ar.lmask = (1U << state->lenbits) - 1; + ar.dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + + /* align in on 1/2 hold size boundary */ + while (((unsigned long)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) { + ar.hold += (unsigned long)*ar.in++ << ar.bits; + ar.bits += 8; + } + +#if defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 ) + __asm__ __volatile__ ( +" leaq %0, %%rax\n" +" movq %%rbp, 8(%%rax)\n" /* save regs rbp and rsp */ +" movq %%rsp, (%%rax)\n" +" movq %%rax, %%rsp\n" /* make rsp point to &ar */ +" movq 16(%%rsp), %%rsi\n" /* rsi = in */ +" movq 32(%%rsp), %%rdi\n" /* rdi = out */ +" movq 24(%%rsp), %%r9\n" /* r9 = last */ +" movq 48(%%rsp), %%r10\n" /* r10 = end */ +" movq 64(%%rsp), %%rbp\n" /* rbp = lcode */ +" movq 72(%%rsp), %%r11\n" /* r11 = dcode */ +" movq 80(%%rsp), %%rdx\n" /* rdx = hold */ +" movl 88(%%rsp), %%ebx\n" /* ebx = bits */ +" movl 100(%%rsp), %%r12d\n" /* r12d = lmask */ +" movl 104(%%rsp), %%r13d\n" /* r13d = dmask */ + /* r14d = len */ + /* r15d = dist */ +" cld\n" +" cmpq %%rdi, %%r10\n" +" je .L_one_time\n" /* if only one decode left */ +" cmpq %%rsi, %%r9\n" +" je .L_one_time\n" +" jmp .L_do_loop\n" + +".L_one_time:\n" +" movq %%r12, %%r8\n" /* r8 = lmask */ +" cmpb $32, %%bl\n" +" ja .L_get_length_code_one_time\n" + +" lodsl\n" /* eax = *(uint *)in++ */ +" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ +" addb $32, %%bl\n" /* bits += 32 */ +" shlq %%cl, %%rax\n" +" orq %%rax, %%rdx\n" /* hold |= *((uint *)in)++ << bits */ +" jmp .L_get_length_code_one_time\n" + +".align 32,0x90\n" +".L_while_test:\n" +" cmpq %%rdi, %%r10\n" +" jbe .L_break_loop\n" +" cmpq %%rsi, %%r9\n" +" jbe .L_break_loop\n" + +".L_do_loop:\n" +" movq %%r12, %%r8\n" /* r8 = lmask */ +" cmpb $32, %%bl\n" +" ja .L_get_length_code\n" /* if (32 < bits) */ + +" lodsl\n" /* eax = *(uint *)in++ */ +" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ +" addb $32, %%bl\n" /* bits += 32 */ +" shlq %%cl, %%rax\n" +" orq %%rax, %%rdx\n" /* hold |= *((uint *)in)++ << bits */ + +".L_get_length_code:\n" +" andq %%rdx, %%r8\n" /* r8 &= hold */ +" movl (%%rbp,%%r8,4), %%eax\n" /* eax = lcode[hold & lmask] */ + +" movb %%ah, %%cl\n" /* cl = this.bits */ +" subb %%ah, %%bl\n" /* bits -= this.bits */ +" shrq %%cl, %%rdx\n" /* hold >>= this.bits */ + +" testb %%al, %%al\n" +" jnz .L_test_for_length_base\n" /* if (op != 0) 45.7% */ + +" movq %%r12, %%r8\n" /* r8 = lmask */ +" shrl $16, %%eax\n" /* output this.val char */ +" stosb\n" + +".L_get_length_code_one_time:\n" +" andq %%rdx, %%r8\n" /* r8 &= hold */ +" movl (%%rbp,%%r8,4), %%eax\n" /* eax = lcode[hold & lmask] */ + +".L_dolen:\n" +" movb %%ah, %%cl\n" /* cl = this.bits */ +" subb %%ah, %%bl\n" /* bits -= this.bits */ +" shrq %%cl, %%rdx\n" /* hold >>= this.bits */ + +" testb %%al, %%al\n" +" jnz .L_test_for_length_base\n" /* if (op != 0) 45.7% */ + +" shrl $16, %%eax\n" /* output this.val char */ +" stosb\n" +" jmp .L_while_test\n" + +".align 32,0x90\n" +".L_test_for_length_base:\n" +" movl %%eax, %%r14d\n" /* len = this */ +" shrl $16, %%r14d\n" /* len = this.val */ +" movb %%al, %%cl\n" + +" testb $16, %%al\n" +" jz .L_test_for_second_level_length\n" /* if ((op & 16) == 0) 8% */ +" andb $15, %%cl\n" /* op &= 15 */ +" jz .L_decode_distance\n" /* if (!op) */ + +".L_add_bits_to_len:\n" +" subb %%cl, %%bl\n" +" xorl %%eax, %%eax\n" +" incl %%eax\n" +" shll %%cl, %%eax\n" +" decl %%eax\n" +" andl %%edx, %%eax\n" /* eax &= hold */ +" shrq %%cl, %%rdx\n" +" addl %%eax, %%r14d\n" /* len += hold & mask[op] */ + +".L_decode_distance:\n" +" movq %%r13, %%r8\n" /* r8 = dmask */ +" cmpb $32, %%bl\n" +" ja .L_get_distance_code\n" /* if (32 < bits) */ + +" lodsl\n" /* eax = *(uint *)in++ */ +" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ +" addb $32, %%bl\n" /* bits += 32 */ +" shlq %%cl, %%rax\n" +" orq %%rax, %%rdx\n" /* hold |= *((uint *)in)++ << bits */ + +".L_get_distance_code:\n" +" andq %%rdx, %%r8\n" /* r8 &= hold */ +" movl (%%r11,%%r8,4), %%eax\n" /* eax = dcode[hold & dmask] */ + +".L_dodist:\n" +" movl %%eax, %%r15d\n" /* dist = this */ +" shrl $16, %%r15d\n" /* dist = this.val */ +" movb %%ah, %%cl\n" +" subb %%ah, %%bl\n" /* bits -= this.bits */ +" shrq %%cl, %%rdx\n" /* hold >>= this.bits */ +" movb %%al, %%cl\n" /* cl = this.op */ + +" testb $16, %%al\n" /* if ((op & 16) == 0) */ +" jz .L_test_for_second_level_dist\n" +" andb $15, %%cl\n" /* op &= 15 */ +" jz .L_check_dist_one\n" + +".L_add_bits_to_dist:\n" +" subb %%cl, %%bl\n" +" xorl %%eax, %%eax\n" +" incl %%eax\n" +" shll %%cl, %%eax\n" +" decl %%eax\n" /* (1 << op) - 1 */ +" andl %%edx, %%eax\n" /* eax &= hold */ +" shrq %%cl, %%rdx\n" +" addl %%eax, %%r15d\n" /* dist += hold & ((1 << op) - 1) */ + +".L_check_window:\n" +" movq %%rsi, %%r8\n" /* save in so from can use it's reg */ +" movq %%rdi, %%rax\n" +" subq 40(%%rsp), %%rax\n" /* nbytes = out - beg */ + +" cmpl %%r15d, %%eax\n" +" jb .L_clip_window\n" /* if (dist > nbytes) 4.2% */ + +" movl %%r14d, %%ecx\n" /* ecx = len */ +" movq %%rdi, %%rsi\n" +" subq %%r15, %%rsi\n" /* from = out - dist */ + +" sarl %%ecx\n" +" jnc .L_copy_two\n" /* if len % 2 == 0 */ + +" rep movsw\n" +" movb (%%rsi), %%al\n" +" movb %%al, (%%rdi)\n" +" incq %%rdi\n" + +" movq %%r8, %%rsi\n" /* move in back to %rsi, toss from */ +" jmp .L_while_test\n" + +".L_copy_two:\n" +" rep movsw\n" +" movq %%r8, %%rsi\n" /* move in back to %rsi, toss from */ +" jmp .L_while_test\n" + +".align 32,0x90\n" +".L_check_dist_one:\n" +" cmpl $1, %%r15d\n" /* if dist 1, is a memset */ +" jne .L_check_window\n" +" cmpq %%rdi, 40(%%rsp)\n" /* if out == beg, outside window */ +" je .L_check_window\n" + +" movl %%r14d, %%ecx\n" /* ecx = len */ +" movb -1(%%rdi), %%al\n" +" movb %%al, %%ah\n" + +" sarl %%ecx\n" +" jnc .L_set_two\n" +" movb %%al, (%%rdi)\n" +" incq %%rdi\n" + +".L_set_two:\n" +" rep stosw\n" +" jmp .L_while_test\n" + +".align 32,0x90\n" +".L_test_for_second_level_length:\n" +" testb $64, %%al\n" +" jnz .L_test_for_end_of_block\n" /* if ((op & 64) != 0) */ + +" xorl %%eax, %%eax\n" +" incl %%eax\n" +" shll %%cl, %%eax\n" +" decl %%eax\n" +" andl %%edx, %%eax\n" /* eax &= hold */ +" addl %%r14d, %%eax\n" /* eax += len */ +" movl (%%rbp,%%rax,4), %%eax\n" /* eax = lcode[val+(hold&mask[op])]*/ +" jmp .L_dolen\n" + +".align 32,0x90\n" +".L_test_for_second_level_dist:\n" +" testb $64, %%al\n" +" jnz .L_invalid_distance_code\n" /* if ((op & 64) != 0) */ + +" xorl %%eax, %%eax\n" +" incl %%eax\n" +" shll %%cl, %%eax\n" +" decl %%eax\n" +" andl %%edx, %%eax\n" /* eax &= hold */ +" addl %%r15d, %%eax\n" /* eax += dist */ +" movl (%%r11,%%rax,4), %%eax\n" /* eax = dcode[val+(hold&mask[op])]*/ +" jmp .L_dodist\n" + +".align 32,0x90\n" +".L_clip_window:\n" +" movl %%eax, %%ecx\n" /* ecx = nbytes */ +" movl 92(%%rsp), %%eax\n" /* eax = wsize, prepare for dist cmp */ +" negl %%ecx\n" /* nbytes = -nbytes */ + +" cmpl %%r15d, %%eax\n" +" jb .L_invalid_distance_too_far\n" /* if (dist > wsize) */ + +" addl %%r15d, %%ecx\n" /* nbytes = dist - nbytes */ +" cmpl $0, 96(%%rsp)\n" +" jne .L_wrap_around_window\n" /* if (write != 0) */ + +" movq 56(%%rsp), %%rsi\n" /* from = window */ +" subl %%ecx, %%eax\n" /* eax -= nbytes */ +" addq %%rax, %%rsi\n" /* from += wsize - nbytes */ + +" movl %%r14d, %%eax\n" /* eax = len */ +" cmpl %%ecx, %%r14d\n" +" jbe .L_do_copy\n" /* if (nbytes >= len) */ + +" subl %%ecx, %%eax\n" /* eax -= nbytes */ +" rep movsb\n" +" movq %%rdi, %%rsi\n" +" subq %%r15, %%rsi\n" /* from = &out[ -dist ] */ +" jmp .L_do_copy\n" + +".align 32,0x90\n" +".L_wrap_around_window:\n" +" movl 96(%%rsp), %%eax\n" /* eax = write */ +" cmpl %%eax, %%ecx\n" +" jbe .L_contiguous_in_window\n" /* if (write >= nbytes) */ + +" movl 92(%%rsp), %%esi\n" /* from = wsize */ +" addq 56(%%rsp), %%rsi\n" /* from += window */ +" addq %%rax, %%rsi\n" /* from += write */ +" subq %%rcx, %%rsi\n" /* from -= nbytes */ +" subl %%eax, %%ecx\n" /* nbytes -= write */ + +" movl %%r14d, %%eax\n" /* eax = len */ +" cmpl %%ecx, %%eax\n" +" jbe .L_do_copy\n" /* if (nbytes >= len) */ + +" subl %%ecx, %%eax\n" /* len -= nbytes */ +" rep movsb\n" +" movq 56(%%rsp), %%rsi\n" /* from = window */ +" movl 96(%%rsp), %%ecx\n" /* nbytes = write */ +" cmpl %%ecx, %%eax\n" +" jbe .L_do_copy\n" /* if (nbytes >= len) */ + +" subl %%ecx, %%eax\n" /* len -= nbytes */ +" rep movsb\n" +" movq %%rdi, %%rsi\n" +" subq %%r15, %%rsi\n" /* from = out - dist */ +" jmp .L_do_copy\n" + +".align 32,0x90\n" +".L_contiguous_in_window:\n" +" movq 56(%%rsp), %%rsi\n" /* rsi = window */ +" addq %%rax, %%rsi\n" +" subq %%rcx, %%rsi\n" /* from += write - nbytes */ + +" movl %%r14d, %%eax\n" /* eax = len */ +" cmpl %%ecx, %%eax\n" +" jbe .L_do_copy\n" /* if (nbytes >= len) */ + +" subl %%ecx, %%eax\n" /* len -= nbytes */ +" rep movsb\n" +" movq %%rdi, %%rsi\n" +" subq %%r15, %%rsi\n" /* from = out - dist */ +" jmp .L_do_copy\n" /* if (nbytes >= len) */ + +".align 32,0x90\n" +".L_do_copy:\n" +" movl %%eax, %%ecx\n" /* ecx = len */ +" rep movsb\n" + +" movq %%r8, %%rsi\n" /* move in back to %esi, toss from */ +" jmp .L_while_test\n" + +".L_test_for_end_of_block:\n" +" testb $32, %%al\n" +" jz .L_invalid_literal_length_code\n" +" movl $1, 116(%%rsp)\n" +" jmp .L_break_loop_with_status\n" + +".L_invalid_literal_length_code:\n" +" movl $2, 116(%%rsp)\n" +" jmp .L_break_loop_with_status\n" + +".L_invalid_distance_code:\n" +" movl $3, 116(%%rsp)\n" +" jmp .L_break_loop_with_status\n" + +".L_invalid_distance_too_far:\n" +" movl $4, 116(%%rsp)\n" +" jmp .L_break_loop_with_status\n" + +".L_break_loop:\n" +" movl $0, 116(%%rsp)\n" + +".L_break_loop_with_status:\n" +/* put in, out, bits, and hold back into ar and pop esp */ +" movq %%rsi, 16(%%rsp)\n" /* in */ +" movq %%rdi, 32(%%rsp)\n" /* out */ +" movl %%ebx, 88(%%rsp)\n" /* bits */ +" movq %%rdx, 80(%%rsp)\n" /* hold */ +" movq (%%rsp), %%rax\n" /* restore rbp and rsp */ +" movq 8(%%rsp), %%rbp\n" +" movq %%rax, %%rsp\n" + : + : "m" (ar) + : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", + "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" + ); +#elif ( defined( __GNUC__ ) || defined( __ICC ) ) && defined( __i386 ) + __asm__ __volatile__ ( +" leal %0, %%eax\n" +" movl %%esp, (%%eax)\n" /* save esp, ebp */ +" movl %%ebp, 4(%%eax)\n" +" movl %%eax, %%esp\n" +" movl 8(%%esp), %%esi\n" /* esi = in */ +" movl 16(%%esp), %%edi\n" /* edi = out */ +" movl 40(%%esp), %%edx\n" /* edx = hold */ +" movl 44(%%esp), %%ebx\n" /* ebx = bits */ +" movl 32(%%esp), %%ebp\n" /* ebp = lcode */ + +" cld\n" +" jmp .L_do_loop\n" + +".align 32,0x90\n" +".L_while_test:\n" +" cmpl %%edi, 24(%%esp)\n" /* out < end */ +" jbe .L_break_loop\n" +" cmpl %%esi, 12(%%esp)\n" /* in < last */ +" jbe .L_break_loop\n" + +".L_do_loop:\n" +" cmpb $15, %%bl\n" +" ja .L_get_length_code\n" /* if (15 < bits) */ + +" xorl %%eax, %%eax\n" +" lodsw\n" /* al = *(ushort *)in++ */ +" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ +" addb $16, %%bl\n" /* bits += 16 */ +" shll %%cl, %%eax\n" +" orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ + +".L_get_length_code:\n" +" movl 56(%%esp), %%eax\n" /* eax = lmask */ +" andl %%edx, %%eax\n" /* eax &= hold */ +" movl (%%ebp,%%eax,4), %%eax\n" /* eax = lcode[hold & lmask] */ + +".L_dolen:\n" +" movb %%ah, %%cl\n" /* cl = this.bits */ +" subb %%ah, %%bl\n" /* bits -= this.bits */ +" shrl %%cl, %%edx\n" /* hold >>= this.bits */ + +" testb %%al, %%al\n" +" jnz .L_test_for_length_base\n" /* if (op != 0) 45.7% */ + +" shrl $16, %%eax\n" /* output this.val char */ +" stosb\n" +" jmp .L_while_test\n" + +".align 32,0x90\n" +".L_test_for_length_base:\n" +" movl %%eax, %%ecx\n" /* len = this */ +" shrl $16, %%ecx\n" /* len = this.val */ +" movl %%ecx, 64(%%esp)\n" /* save len */ +" movb %%al, %%cl\n" + +" testb $16, %%al\n" +" jz .L_test_for_second_level_length\n" /* if ((op & 16) == 0) 8% */ +" andb $15, %%cl\n" /* op &= 15 */ +" jz .L_decode_distance\n" /* if (!op) */ +" cmpb %%cl, %%bl\n" +" jae .L_add_bits_to_len\n" /* if (op <= bits) */ + +" movb %%cl, %%ch\n" /* stash op in ch, freeing cl */ +" xorl %%eax, %%eax\n" +" lodsw\n" /* al = *(ushort *)in++ */ +" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ +" addb $16, %%bl\n" /* bits += 16 */ +" shll %%cl, %%eax\n" +" orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ +" movb %%ch, %%cl\n" /* move op back to ecx */ + +".L_add_bits_to_len:\n" +" subb %%cl, %%bl\n" +" xorl %%eax, %%eax\n" +" incl %%eax\n" +" shll %%cl, %%eax\n" +" decl %%eax\n" +" andl %%edx, %%eax\n" /* eax &= hold */ +" shrl %%cl, %%edx\n" +" addl %%eax, 64(%%esp)\n" /* len += hold & mask[op] */ + +".L_decode_distance:\n" +" cmpb $15, %%bl\n" +" ja .L_get_distance_code\n" /* if (15 < bits) */ + +" xorl %%eax, %%eax\n" +" lodsw\n" /* al = *(ushort *)in++ */ +" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ +" addb $16, %%bl\n" /* bits += 16 */ +" shll %%cl, %%eax\n" +" orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ + +".L_get_distance_code:\n" +" movl 60(%%esp), %%eax\n" /* eax = dmask */ +" movl 36(%%esp), %%ecx\n" /* ecx = dcode */ +" andl %%edx, %%eax\n" /* eax &= hold */ +" movl (%%ecx,%%eax,4), %%eax\n"/* eax = dcode[hold & dmask] */ + +".L_dodist:\n" +" movl %%eax, %%ebp\n" /* dist = this */ +" shrl $16, %%ebp\n" /* dist = this.val */ +" movb %%ah, %%cl\n" +" subb %%ah, %%bl\n" /* bits -= this.bits */ +" shrl %%cl, %%edx\n" /* hold >>= this.bits */ +" movb %%al, %%cl\n" /* cl = this.op */ + +" testb $16, %%al\n" /* if ((op & 16) == 0) */ +" jz .L_test_for_second_level_dist\n" +" andb $15, %%cl\n" /* op &= 15 */ +" jz .L_check_dist_one\n" +" cmpb %%cl, %%bl\n" +" jae .L_add_bits_to_dist\n" /* if (op <= bits) 97.6% */ + +" movb %%cl, %%ch\n" /* stash op in ch, freeing cl */ +" xorl %%eax, %%eax\n" +" lodsw\n" /* al = *(ushort *)in++ */ +" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ +" addb $16, %%bl\n" /* bits += 16 */ +" shll %%cl, %%eax\n" +" orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ +" movb %%ch, %%cl\n" /* move op back to ecx */ + +".L_add_bits_to_dist:\n" +" subb %%cl, %%bl\n" +" xorl %%eax, %%eax\n" +" incl %%eax\n" +" shll %%cl, %%eax\n" +" decl %%eax\n" /* (1 << op) - 1 */ +" andl %%edx, %%eax\n" /* eax &= hold */ +" shrl %%cl, %%edx\n" +" addl %%eax, %%ebp\n" /* dist += hold & ((1 << op) - 1) */ + +".L_check_window:\n" +" movl %%esi, 8(%%esp)\n" /* save in so from can use it's reg */ +" movl %%edi, %%eax\n" +" subl 20(%%esp), %%eax\n" /* nbytes = out - beg */ + +" cmpl %%ebp, %%eax\n" +" jb .L_clip_window\n" /* if (dist > nbytes) 4.2% */ + +" movl 64(%%esp), %%ecx\n" /* ecx = len */ +" movl %%edi, %%esi\n" +" subl %%ebp, %%esi\n" /* from = out - dist */ + +" sarl %%ecx\n" +" jnc .L_copy_two\n" /* if len % 2 == 0 */ + +" rep movsw\n" +" movb (%%esi), %%al\n" +" movb %%al, (%%edi)\n" +" incl %%edi\n" + +" movl 8(%%esp), %%esi\n" /* move in back to %esi, toss from */ +" movl 32(%%esp), %%ebp\n" /* ebp = lcode */ +" jmp .L_while_test\n" + +".L_copy_two:\n" +" rep movsw\n" +" movl 8(%%esp), %%esi\n" /* move in back to %esi, toss from */ +" movl 32(%%esp), %%ebp\n" /* ebp = lcode */ +" jmp .L_while_test\n" + +".align 32,0x90\n" +".L_check_dist_one:\n" +" cmpl $1, %%ebp\n" /* if dist 1, is a memset */ +" jne .L_check_window\n" +" cmpl %%edi, 20(%%esp)\n" +" je .L_check_window\n" /* out == beg, if outside window */ + +" movl 64(%%esp), %%ecx\n" /* ecx = len */ +" movb -1(%%edi), %%al\n" +" movb %%al, %%ah\n" + +" sarl %%ecx\n" +" jnc .L_set_two\n" +" movb %%al, (%%edi)\n" +" incl %%edi\n" + +".L_set_two:\n" +" rep stosw\n" +" movl 32(%%esp), %%ebp\n" /* ebp = lcode */ +" jmp .L_while_test\n" + +".align 32,0x90\n" +".L_test_for_second_level_length:\n" +" testb $64, %%al\n" +" jnz .L_test_for_end_of_block\n" /* if ((op & 64) != 0) */ + +" xorl %%eax, %%eax\n" +" incl %%eax\n" +" shll %%cl, %%eax\n" +" decl %%eax\n" +" andl %%edx, %%eax\n" /* eax &= hold */ +" addl 64(%%esp), %%eax\n" /* eax += len */ +" movl (%%ebp,%%eax,4), %%eax\n" /* eax = lcode[val+(hold&mask[op])]*/ +" jmp .L_dolen\n" + +".align 32,0x90\n" +".L_test_for_second_level_dist:\n" +" testb $64, %%al\n" +" jnz .L_invalid_distance_code\n" /* if ((op & 64) != 0) */ + +" xorl %%eax, %%eax\n" +" incl %%eax\n" +" shll %%cl, %%eax\n" +" decl %%eax\n" +" andl %%edx, %%eax\n" /* eax &= hold */ +" addl %%ebp, %%eax\n" /* eax += dist */ +" movl 36(%%esp), %%ecx\n" /* ecx = dcode */ +" movl (%%ecx,%%eax,4), %%eax\n" /* eax = dcode[val+(hold&mask[op])]*/ +" jmp .L_dodist\n" + +".align 32,0x90\n" +".L_clip_window:\n" +" movl %%eax, %%ecx\n" +" movl 48(%%esp), %%eax\n" /* eax = wsize */ +" negl %%ecx\n" /* nbytes = -nbytes */ +" movl 28(%%esp), %%esi\n" /* from = window */ + +" cmpl %%ebp, %%eax\n" +" jb .L_invalid_distance_too_far\n" /* if (dist > wsize) */ + +" addl %%ebp, %%ecx\n" /* nbytes = dist - nbytes */ +" cmpl $0, 52(%%esp)\n" +" jne .L_wrap_around_window\n" /* if (write != 0) */ + +" subl %%ecx, %%eax\n" +" addl %%eax, %%esi\n" /* from += wsize - nbytes */ + +" movl 64(%%esp), %%eax\n" /* eax = len */ +" cmpl %%ecx, %%eax\n" +" jbe .L_do_copy\n" /* if (nbytes >= len) */ + +" subl %%ecx, %%eax\n" /* len -= nbytes */ +" rep movsb\n" +" movl %%edi, %%esi\n" +" subl %%ebp, %%esi\n" /* from = out - dist */ +" jmp .L_do_copy\n" + +".align 32,0x90\n" +".L_wrap_around_window:\n" +" movl 52(%%esp), %%eax\n" /* eax = write */ +" cmpl %%eax, %%ecx\n" +" jbe .L_contiguous_in_window\n" /* if (write >= nbytes) */ + +" addl 48(%%esp), %%esi\n" /* from += wsize */ +" addl %%eax, %%esi\n" /* from += write */ +" subl %%ecx, %%esi\n" /* from -= nbytes */ +" subl %%eax, %%ecx\n" /* nbytes -= write */ + +" movl 64(%%esp), %%eax\n" /* eax = len */ +" cmpl %%ecx, %%eax\n" +" jbe .L_do_copy\n" /* if (nbytes >= len) */ + +" subl %%ecx, %%eax\n" /* len -= nbytes */ +" rep movsb\n" +" movl 28(%%esp), %%esi\n" /* from = window */ +" movl 52(%%esp), %%ecx\n" /* nbytes = write */ +" cmpl %%ecx, %%eax\n" +" jbe .L_do_copy\n" /* if (nbytes >= len) */ + +" subl %%ecx, %%eax\n" /* len -= nbytes */ +" rep movsb\n" +" movl %%edi, %%esi\n" +" subl %%ebp, %%esi\n" /* from = out - dist */ +" jmp .L_do_copy\n" + +".align 32,0x90\n" +".L_contiguous_in_window:\n" +" addl %%eax, %%esi\n" +" subl %%ecx, %%esi\n" /* from += write - nbytes */ + +" movl 64(%%esp), %%eax\n" /* eax = len */ +" cmpl %%ecx, %%eax\n" +" jbe .L_do_copy\n" /* if (nbytes >= len) */ + +" subl %%ecx, %%eax\n" /* len -= nbytes */ +" rep movsb\n" +" movl %%edi, %%esi\n" +" subl %%ebp, %%esi\n" /* from = out - dist */ +" jmp .L_do_copy\n" /* if (nbytes >= len) */ + +".align 32,0x90\n" +".L_do_copy:\n" +" movl %%eax, %%ecx\n" +" rep movsb\n" + +" movl 8(%%esp), %%esi\n" /* move in back to %esi, toss from */ +" movl 32(%%esp), %%ebp\n" /* ebp = lcode */ +" jmp .L_while_test\n" + +".L_test_for_end_of_block:\n" +" testb $32, %%al\n" +" jz .L_invalid_literal_length_code\n" +" movl $1, 72(%%esp)\n" +" jmp .L_break_loop_with_status\n" + +".L_invalid_literal_length_code:\n" +" movl $2, 72(%%esp)\n" +" jmp .L_break_loop_with_status\n" + +".L_invalid_distance_code:\n" +" movl $3, 72(%%esp)\n" +" jmp .L_break_loop_with_status\n" + +".L_invalid_distance_too_far:\n" +" movl 8(%%esp), %%esi\n" +" movl $4, 72(%%esp)\n" +" jmp .L_break_loop_with_status\n" + +".L_break_loop:\n" +" movl $0, 72(%%esp)\n" + +".L_break_loop_with_status:\n" +/* put in, out, bits, and hold back into ar and pop esp */ +" movl %%esi, 8(%%esp)\n" /* save in */ +" movl %%edi, 16(%%esp)\n" /* save out */ +" movl %%ebx, 44(%%esp)\n" /* save bits */ +" movl %%edx, 40(%%esp)\n" /* save hold */ +" movl 4(%%esp), %%ebp\n" /* restore esp, ebp */ +" movl (%%esp), %%esp\n" + : + : "m" (ar) + : "memory", "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi" + ); +#elif defined( _MSC_VER ) && ! defined( _M_AMD64 ) + __asm { + lea eax, ar + mov [eax], esp /* save esp, ebp */ + mov [eax+4], ebp + mov esp, eax + mov esi, [esp+8] /* esi = in */ + mov edi, [esp+16] /* edi = out */ + mov edx, [esp+40] /* edx = hold */ + mov ebx, [esp+44] /* ebx = bits */ + mov ebp, [esp+32] /* ebp = lcode */ + + cld + jmp L_do_loop + +ALIGN 4 +L_while_test: + cmp [esp+24], edi + jbe L_break_loop + cmp [esp+12], esi + jbe L_break_loop + +L_do_loop: + cmp bl, 15 + ja L_get_length_code /* if (15 < bits) */ + + xor eax, eax + lodsw /* al = *(ushort *)in++ */ + mov cl, bl /* cl = bits, needs it for shifting */ + add bl, 16 /* bits += 16 */ + shl eax, cl + or edx, eax /* hold |= *((ushort *)in)++ << bits */ + +L_get_length_code: + mov eax, [esp+56] /* eax = lmask */ + and eax, edx /* eax &= hold */ + mov eax, [ebp+eax*4] /* eax = lcode[hold & lmask] */ + +L_dolen: + mov cl, ah /* cl = this.bits */ + sub bl, ah /* bits -= this.bits */ + shr edx, cl /* hold >>= this.bits */ + + test al, al + jnz L_test_for_length_base /* if (op != 0) 45.7% */ + + shr eax, 16 /* output this.val char */ + stosb + jmp L_while_test + +ALIGN 4 +L_test_for_length_base: + mov ecx, eax /* len = this */ + shr ecx, 16 /* len = this.val */ + mov [esp+64], ecx /* save len */ + mov cl, al + + test al, 16 + jz L_test_for_second_level_length /* if ((op & 16) == 0) 8% */ + and cl, 15 /* op &= 15 */ + jz L_decode_distance /* if (!op) */ + cmp bl, cl + jae L_add_bits_to_len /* if (op <= bits) */ + + mov ch, cl /* stash op in ch, freeing cl */ + xor eax, eax + lodsw /* al = *(ushort *)in++ */ + mov cl, bl /* cl = bits, needs it for shifting */ + add bl, 16 /* bits += 16 */ + shl eax, cl + or edx, eax /* hold |= *((ushort *)in)++ << bits */ + mov cl, ch /* move op back to ecx */ + +L_add_bits_to_len: + sub bl, cl + xor eax, eax + inc eax + shl eax, cl + dec eax + and eax, edx /* eax &= hold */ + shr edx, cl + add [esp+64], eax /* len += hold & mask[op] */ + +L_decode_distance: + cmp bl, 15 + ja L_get_distance_code /* if (15 < bits) */ + + xor eax, eax + lodsw /* al = *(ushort *)in++ */ + mov cl, bl /* cl = bits, needs it for shifting */ + add bl, 16 /* bits += 16 */ + shl eax, cl + or edx, eax /* hold |= *((ushort *)in)++ << bits */ + +L_get_distance_code: + mov eax, [esp+60] /* eax = dmask */ + mov ecx, [esp+36] /* ecx = dcode */ + and eax, edx /* eax &= hold */ + mov eax, [ecx+eax*4]/* eax = dcode[hold & dmask] */ + +L_dodist: + mov ebp, eax /* dist = this */ + shr ebp, 16 /* dist = this.val */ + mov cl, ah + sub bl, ah /* bits -= this.bits */ + shr edx, cl /* hold >>= this.bits */ + mov cl, al /* cl = this.op */ + + test al, 16 /* if ((op & 16) == 0) */ + jz L_test_for_second_level_dist + and cl, 15 /* op &= 15 */ + jz L_check_dist_one + cmp bl, cl + jae L_add_bits_to_dist /* if (op <= bits) 97.6% */ + + mov ch, cl /* stash op in ch, freeing cl */ + xor eax, eax + lodsw /* al = *(ushort *)in++ */ + mov cl, bl /* cl = bits, needs it for shifting */ + add bl, 16 /* bits += 16 */ + shl eax, cl + or edx, eax /* hold |= *((ushort *)in)++ << bits */ + mov cl, ch /* move op back to ecx */ + +L_add_bits_to_dist: + sub bl, cl + xor eax, eax + inc eax + shl eax, cl + dec eax /* (1 << op) - 1 */ + and eax, edx /* eax &= hold */ + shr edx, cl + add ebp, eax /* dist += hold & ((1 << op) - 1) */ + +L_check_window: + mov [esp+8], esi /* save in so from can use it's reg */ + mov eax, edi + sub eax, [esp+20] /* nbytes = out - beg */ + + cmp eax, ebp + jb L_clip_window /* if (dist > nbytes) 4.2% */ + + mov ecx, [esp+64] /* ecx = len */ + mov esi, edi + sub esi, ebp /* from = out - dist */ + + sar ecx, 1 + jnc L_copy_two + + rep movsw + mov al, [esi] + mov [edi], al + inc edi + + mov esi, [esp+8] /* move in back to %esi, toss from */ + mov ebp, [esp+32] /* ebp = lcode */ + jmp L_while_test + +L_copy_two: + rep movsw + mov esi, [esp+8] /* move in back to %esi, toss from */ + mov ebp, [esp+32] /* ebp = lcode */ + jmp L_while_test + +ALIGN 4 +L_check_dist_one: + cmp ebp, 1 /* if dist 1, is a memset */ + jne L_check_window + cmp [esp+20], edi + je L_check_window /* out == beg, if outside window */ + + mov ecx, [esp+64] /* ecx = len */ + mov al, [edi-1] + mov ah, al + + sar ecx, 1 + jnc L_set_two + mov [edi], al /* memset out with from[-1] */ + inc edi + +L_set_two: + rep stosw + mov ebp, [esp+32] /* ebp = lcode */ + jmp L_while_test + +ALIGN 4 +L_test_for_second_level_length: + test al, 64 + jnz L_test_for_end_of_block /* if ((op & 64) != 0) */ + + xor eax, eax + inc eax + shl eax, cl + dec eax + and eax, edx /* eax &= hold */ + add eax, [esp+64] /* eax += len */ + mov eax, [ebp+eax*4] /* eax = lcode[val+(hold&mask[op])]*/ + jmp L_dolen + +ALIGN 4 +L_test_for_second_level_dist: + test al, 64 + jnz L_invalid_distance_code /* if ((op & 64) != 0) */ + + xor eax, eax + inc eax + shl eax, cl + dec eax + and eax, edx /* eax &= hold */ + add eax, ebp /* eax += dist */ + mov ecx, [esp+36] /* ecx = dcode */ + mov eax, [ecx+eax*4] /* eax = dcode[val+(hold&mask[op])]*/ + jmp L_dodist + +ALIGN 4 +L_clip_window: + mov ecx, eax + mov eax, [esp+48] /* eax = wsize */ + neg ecx /* nbytes = -nbytes */ + mov esi, [esp+28] /* from = window */ + + cmp eax, ebp + jb L_invalid_distance_too_far /* if (dist > wsize) */ + + add ecx, ebp /* nbytes = dist - nbytes */ + cmp dword ptr [esp+52], 0 + jne L_wrap_around_window /* if (write != 0) */ + + sub eax, ecx + add esi, eax /* from += wsize - nbytes */ + + mov eax, [esp+64] /* eax = len */ + cmp eax, ecx + jbe L_do_copy /* if (nbytes >= len) */ + + sub eax, ecx /* len -= nbytes */ + rep movsb + mov esi, edi + sub esi, ebp /* from = out - dist */ + jmp L_do_copy + +ALIGN 4 +L_wrap_around_window: + mov eax, [esp+52] /* eax = write */ + cmp ecx, eax + jbe L_contiguous_in_window /* if (write >= nbytes) */ + + add esi, [esp+48] /* from += wsize */ + add esi, eax /* from += write */ + sub esi, ecx /* from -= nbytes */ + sub ecx, eax /* nbytes -= write */ + + mov eax, [esp+64] /* eax = len */ + cmp eax, ecx + jbe L_do_copy /* if (nbytes >= len) */ + + sub eax, ecx /* len -= nbytes */ + rep movsb + mov esi, [esp+28] /* from = window */ + mov ecx, [esp+52] /* nbytes = write */ + cmp eax, ecx + jbe L_do_copy /* if (nbytes >= len) */ + + sub eax, ecx /* len -= nbytes */ + rep movsb + mov esi, edi + sub esi, ebp /* from = out - dist */ + jmp L_do_copy + +ALIGN 4 +L_contiguous_in_window: + add esi, eax + sub esi, ecx /* from += write - nbytes */ + + mov eax, [esp+64] /* eax = len */ + cmp eax, ecx + jbe L_do_copy /* if (nbytes >= len) */ + + sub eax, ecx /* len -= nbytes */ + rep movsb + mov esi, edi + sub esi, ebp /* from = out - dist */ + jmp L_do_copy + +ALIGN 4 +L_do_copy: + mov ecx, eax + rep movsb + + mov esi, [esp+8] /* move in back to %esi, toss from */ + mov ebp, [esp+32] /* ebp = lcode */ + jmp L_while_test + +L_test_for_end_of_block: + test al, 32 + jz L_invalid_literal_length_code + mov dword ptr [esp+72], 1 + jmp L_break_loop_with_status + +L_invalid_literal_length_code: + mov dword ptr [esp+72], 2 + jmp L_break_loop_with_status + +L_invalid_distance_code: + mov dword ptr [esp+72], 3 + jmp L_break_loop_with_status + +L_invalid_distance_too_far: + mov esi, [esp+4] + mov dword ptr [esp+72], 4 + jmp L_break_loop_with_status + +L_break_loop: + mov dword ptr [esp+72], 0 + +L_break_loop_with_status: +/* put in, out, bits, and hold back into ar and pop esp */ + mov [esp+8], esi /* save in */ + mov [esp+16], edi /* save out */ + mov [esp+44], ebx /* save bits */ + mov [esp+40], edx /* save hold */ + mov ebp, [esp+4] /* restore esp, ebp */ + mov esp, [esp] + } +#else +#error "x86 architecture not defined" +#endif + + if (ar.status > 1) { + if (ar.status == 2) + strm->msg = "invalid literal/length code"; + else if (ar.status == 3) + strm->msg = "invalid distance code"; + else + strm->msg = "invalid distance too far back"; + state->mode = BAD; + } + else if ( ar.status == 1 ) { + state->mode = TYPE; + } + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + ar.len = ar.bits >> 3; + ar.in -= ar.len; + ar.bits -= ar.len << 3; + ar.hold &= (1U << ar.bits) - 1; + + /* update state and return */ + strm->next_in = ar.in; + strm->next_out = ar.out; + strm->avail_in = (unsigned)(ar.in < ar.last ? + PAD_AVAIL_IN + (ar.last - ar.in) : + PAD_AVAIL_IN - (ar.in - ar.last)); + strm->avail_out = (unsigned)(ar.out < ar.end ? + PAD_AVAIL_OUT + (ar.end - ar.out) : + PAD_AVAIL_OUT - (ar.out - ar.end)); + state->hold = ar.hold; + state->bits = ar.bits; + return; +} + diff --git a/dependencies/zlib-1.2.11/contrib/inflate86/inffast.S b/dependencies/zlib-1.2.11/contrib/inflate86/inffast.S new file mode 100644 index 0000000..2245a29 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/inflate86/inffast.S @@ -0,0 +1,1368 @@ +/* + * inffast.S is a hand tuned assembler version of: + * + * inffast.c -- fast decoding + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Copyright (C) 2003 Chris Anderson + * Please use the copyright conditions above. + * + * This version (Jan-23-2003) of inflate_fast was coded and tested under + * GNU/Linux on a pentium 3, using the gcc-3.2 compiler distribution. On that + * machine, I found that gzip style archives decompressed about 20% faster than + * the gcc-3.2 -O3 -fomit-frame-pointer compiled version. Your results will + * depend on how large of a buffer is used for z_stream.next_in & next_out + * (8K-32K worked best for my 256K cpu cache) and how much overhead there is in + * stream processing I/O and crc32/addler32. In my case, this routine used + * 70% of the cpu time and crc32 used 20%. + * + * I am confident that this version will work in the general case, but I have + * not tested a wide variety of datasets or a wide variety of platforms. + * + * Jan-24-2003 -- Added -DUSE_MMX define for slightly faster inflating. + * It should be a runtime flag instead of compile time flag... + * + * Jan-26-2003 -- Added runtime check for MMX support with cpuid instruction. + * With -DUSE_MMX, only MMX code is compiled. With -DNO_MMX, only non-MMX code + * is compiled. Without either option, runtime detection is enabled. Runtime + * detection should work on all modern cpus and the recomended algorithm (flip + * ID bit on eflags and then use the cpuid instruction) is used in many + * multimedia applications. Tested under win2k with gcc-2.95 and gas-2.12 + * distributed with cygwin3. Compiling with gcc-2.95 -c inffast.S -o + * inffast.obj generates a COFF object which can then be linked with MSVC++ + * compiled code. Tested under FreeBSD 4.7 with gcc-2.95. + * + * Jan-28-2003 -- Tested Athlon XP... MMX mode is slower than no MMX (and + * slower than compiler generated code). Adjusted cpuid check to use the MMX + * code only for Pentiums < P4 until I have more data on the P4. Speed + * improvment is only about 15% on the Athlon when compared with code generated + * with MSVC++. Not sure yet, but I think the P4 will also be slower using the + * MMX mode because many of it's x86 ALU instructions execute in .5 cycles and + * have less latency than MMX ops. Added code to buffer the last 11 bytes of + * the input stream since the MMX code grabs bits in chunks of 32, which + * differs from the inffast.c algorithm. I don't think there would have been + * read overruns where a page boundary was crossed (a segfault), but there + * could have been overruns when next_in ends on unaligned memory (unintialized + * memory read). + * + * Mar-13-2003 -- P4 MMX is slightly slower than P4 NO_MMX. I created a C + * version of the non-MMX code so that it doesn't depend on zstrm and zstate + * structure offsets which are hard coded in this file. This was last tested + * with zlib-1.2.0 which is currently in beta testing, newer versions of this + * and inffas86.c can be found at http://www.eetbeetee.com/zlib/ and + * http://www.charm.net/~christop/zlib/ + */ + + +/* + * if you have underscore linking problems (_inflate_fast undefined), try + * using -DGAS_COFF + */ +#if ! defined( GAS_COFF ) && ! defined( GAS_ELF ) + +#if defined( WIN32 ) || defined( __CYGWIN__ ) +#define GAS_COFF /* windows object format */ +#else +#define GAS_ELF +#endif + +#endif /* ! GAS_COFF && ! GAS_ELF */ + + +#if defined( GAS_COFF ) + +/* coff externals have underscores */ +#define inflate_fast _inflate_fast +#define inflate_fast_use_mmx _inflate_fast_use_mmx + +#endif /* GAS_COFF */ + + +.file "inffast.S" + +.globl inflate_fast + +.text +.align 4,0 +.L_invalid_literal_length_code_msg: +.string "invalid literal/length code" + +.align 4,0 +.L_invalid_distance_code_msg: +.string "invalid distance code" + +.align 4,0 +.L_invalid_distance_too_far_msg: +.string "invalid distance too far back" + +#if ! defined( NO_MMX ) +.align 4,0 +.L_mask: /* mask[N] = ( 1 << N ) - 1 */ +.long 0 +.long 1 +.long 3 +.long 7 +.long 15 +.long 31 +.long 63 +.long 127 +.long 255 +.long 511 +.long 1023 +.long 2047 +.long 4095 +.long 8191 +.long 16383 +.long 32767 +.long 65535 +.long 131071 +.long 262143 +.long 524287 +.long 1048575 +.long 2097151 +.long 4194303 +.long 8388607 +.long 16777215 +.long 33554431 +.long 67108863 +.long 134217727 +.long 268435455 +.long 536870911 +.long 1073741823 +.long 2147483647 +.long 4294967295 +#endif /* NO_MMX */ + +.text + +/* + * struct z_stream offsets, in zlib.h + */ +#define next_in_strm 0 /* strm->next_in */ +#define avail_in_strm 4 /* strm->avail_in */ +#define next_out_strm 12 /* strm->next_out */ +#define avail_out_strm 16 /* strm->avail_out */ +#define msg_strm 24 /* strm->msg */ +#define state_strm 28 /* strm->state */ + +/* + * struct inflate_state offsets, in inflate.h + */ +#define mode_state 0 /* state->mode */ +#define wsize_state 32 /* state->wsize */ +#define write_state 40 /* state->write */ +#define window_state 44 /* state->window */ +#define hold_state 48 /* state->hold */ +#define bits_state 52 /* state->bits */ +#define lencode_state 68 /* state->lencode */ +#define distcode_state 72 /* state->distcode */ +#define lenbits_state 76 /* state->lenbits */ +#define distbits_state 80 /* state->distbits */ + +/* + * inflate_fast's activation record + */ +#define local_var_size 64 /* how much local space for vars */ +#define strm_sp 88 /* first arg: z_stream * (local_var_size + 24) */ +#define start_sp 92 /* second arg: unsigned int (local_var_size + 28) */ + +/* + * offsets for local vars on stack + */ +#define out 60 /* unsigned char* */ +#define window 56 /* unsigned char* */ +#define wsize 52 /* unsigned int */ +#define write 48 /* unsigned int */ +#define in 44 /* unsigned char* */ +#define beg 40 /* unsigned char* */ +#define buf 28 /* char[ 12 ] */ +#define len 24 /* unsigned int */ +#define last 20 /* unsigned char* */ +#define end 16 /* unsigned char* */ +#define dcode 12 /* code* */ +#define lcode 8 /* code* */ +#define dmask 4 /* unsigned int */ +#define lmask 0 /* unsigned int */ + +/* + * typedef enum inflate_mode consts, in inflate.h + */ +#define INFLATE_MODE_TYPE 11 /* state->mode flags enum-ed in inflate.h */ +#define INFLATE_MODE_BAD 26 + + +#if ! defined( USE_MMX ) && ! defined( NO_MMX ) + +#define RUN_TIME_MMX + +#define CHECK_MMX 1 +#define DO_USE_MMX 2 +#define DONT_USE_MMX 3 + +.globl inflate_fast_use_mmx + +.data + +.align 4,0 +inflate_fast_use_mmx: /* integer flag for run time control 1=check,2=mmx,3=no */ +.long CHECK_MMX + +#if defined( GAS_ELF ) +/* elf info */ +.type inflate_fast_use_mmx,@object +.size inflate_fast_use_mmx,4 +#endif + +#endif /* RUN_TIME_MMX */ + +#if defined( GAS_COFF ) +/* coff info: scl 2 = extern, type 32 = function */ +.def inflate_fast; .scl 2; .type 32; .endef +#endif + +.text + +.align 32,0x90 +inflate_fast: + pushl %edi + pushl %esi + pushl %ebp + pushl %ebx + pushf /* save eflags (strm_sp, state_sp assumes this is 32 bits) */ + subl $local_var_size, %esp + cld + +#define strm_r %esi +#define state_r %edi + + movl strm_sp(%esp), strm_r + movl state_strm(strm_r), state_r + + /* in = strm->next_in; + * out = strm->next_out; + * last = in + strm->avail_in - 11; + * beg = out - (start - strm->avail_out); + * end = out + (strm->avail_out - 257); + */ + movl avail_in_strm(strm_r), %edx + movl next_in_strm(strm_r), %eax + + addl %eax, %edx /* avail_in += next_in */ + subl $11, %edx /* avail_in -= 11 */ + + movl %eax, in(%esp) + movl %edx, last(%esp) + + movl start_sp(%esp), %ebp + movl avail_out_strm(strm_r), %ecx + movl next_out_strm(strm_r), %ebx + + subl %ecx, %ebp /* start -= avail_out */ + negl %ebp /* start = -start */ + addl %ebx, %ebp /* start += next_out */ + + subl $257, %ecx /* avail_out -= 257 */ + addl %ebx, %ecx /* avail_out += out */ + + movl %ebx, out(%esp) + movl %ebp, beg(%esp) + movl %ecx, end(%esp) + + /* wsize = state->wsize; + * write = state->write; + * window = state->window; + * hold = state->hold; + * bits = state->bits; + * lcode = state->lencode; + * dcode = state->distcode; + * lmask = ( 1 << state->lenbits ) - 1; + * dmask = ( 1 << state->distbits ) - 1; + */ + + movl lencode_state(state_r), %eax + movl distcode_state(state_r), %ecx + + movl %eax, lcode(%esp) + movl %ecx, dcode(%esp) + + movl $1, %eax + movl lenbits_state(state_r), %ecx + shll %cl, %eax + decl %eax + movl %eax, lmask(%esp) + + movl $1, %eax + movl distbits_state(state_r), %ecx + shll %cl, %eax + decl %eax + movl %eax, dmask(%esp) + + movl wsize_state(state_r), %eax + movl write_state(state_r), %ecx + movl window_state(state_r), %edx + + movl %eax, wsize(%esp) + movl %ecx, write(%esp) + movl %edx, window(%esp) + + movl hold_state(state_r), %ebp + movl bits_state(state_r), %ebx + +#undef strm_r +#undef state_r + +#define in_r %esi +#define from_r %esi +#define out_r %edi + + movl in(%esp), in_r + movl last(%esp), %ecx + cmpl in_r, %ecx + ja .L_align_long /* if in < last */ + + addl $11, %ecx /* ecx = &in[ avail_in ] */ + subl in_r, %ecx /* ecx = avail_in */ + movl $12, %eax + subl %ecx, %eax /* eax = 12 - avail_in */ + leal buf(%esp), %edi + rep movsb /* memcpy( buf, in, avail_in ) */ + movl %eax, %ecx + xorl %eax, %eax + rep stosb /* memset( &buf[ avail_in ], 0, 12 - avail_in ) */ + leal buf(%esp), in_r /* in = buf */ + movl in_r, last(%esp) /* last = in, do just one iteration */ + jmp .L_is_aligned + + /* align in_r on long boundary */ +.L_align_long: + testl $3, in_r + jz .L_is_aligned + xorl %eax, %eax + movb (in_r), %al + incl in_r + movl %ebx, %ecx + addl $8, %ebx + shll %cl, %eax + orl %eax, %ebp + jmp .L_align_long + +.L_is_aligned: + movl out(%esp), out_r + +#if defined( NO_MMX ) + jmp .L_do_loop +#endif + +#if defined( USE_MMX ) + jmp .L_init_mmx +#endif + +/*** Runtime MMX check ***/ + +#if defined( RUN_TIME_MMX ) +.L_check_mmx: + cmpl $DO_USE_MMX, inflate_fast_use_mmx + je .L_init_mmx + ja .L_do_loop /* > 2 */ + + pushl %eax + pushl %ebx + pushl %ecx + pushl %edx + pushf + movl (%esp), %eax /* copy eflags to eax */ + xorl $0x200000, (%esp) /* try toggling ID bit of eflags (bit 21) + * to see if cpu supports cpuid... + * ID bit method not supported by NexGen but + * bios may load a cpuid instruction and + * cpuid may be disabled on Cyrix 5-6x86 */ + popf + pushf + popl %edx /* copy new eflags to edx */ + xorl %eax, %edx /* test if ID bit is flipped */ + jz .L_dont_use_mmx /* not flipped if zero */ + xorl %eax, %eax + cpuid + cmpl $0x756e6547, %ebx /* check for GenuineIntel in ebx,ecx,edx */ + jne .L_dont_use_mmx + cmpl $0x6c65746e, %ecx + jne .L_dont_use_mmx + cmpl $0x49656e69, %edx + jne .L_dont_use_mmx + movl $1, %eax + cpuid /* get cpu features */ + shrl $8, %eax + andl $15, %eax + cmpl $6, %eax /* check for Pentium family, is 0xf for P4 */ + jne .L_dont_use_mmx + testl $0x800000, %edx /* test if MMX feature is set (bit 23) */ + jnz .L_use_mmx + jmp .L_dont_use_mmx +.L_use_mmx: + movl $DO_USE_MMX, inflate_fast_use_mmx + jmp .L_check_mmx_pop +.L_dont_use_mmx: + movl $DONT_USE_MMX, inflate_fast_use_mmx +.L_check_mmx_pop: + popl %edx + popl %ecx + popl %ebx + popl %eax + jmp .L_check_mmx +#endif + + +/*** Non-MMX code ***/ + +#if defined ( NO_MMX ) || defined( RUN_TIME_MMX ) + +#define hold_r %ebp +#define bits_r %bl +#define bitslong_r %ebx + +.align 32,0x90 +.L_while_test: + /* while (in < last && out < end) + */ + cmpl out_r, end(%esp) + jbe .L_break_loop /* if (out >= end) */ + + cmpl in_r, last(%esp) + jbe .L_break_loop + +.L_do_loop: + /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out + * + * do { + * if (bits < 15) { + * hold |= *((unsigned short *)in)++ << bits; + * bits += 16 + * } + * this = lcode[hold & lmask] + */ + cmpb $15, bits_r + ja .L_get_length_code /* if (15 < bits) */ + + xorl %eax, %eax + lodsw /* al = *(ushort *)in++ */ + movb bits_r, %cl /* cl = bits, needs it for shifting */ + addb $16, bits_r /* bits += 16 */ + shll %cl, %eax + orl %eax, hold_r /* hold |= *((ushort *)in)++ << bits */ + +.L_get_length_code: + movl lmask(%esp), %edx /* edx = lmask */ + movl lcode(%esp), %ecx /* ecx = lcode */ + andl hold_r, %edx /* edx &= hold */ + movl (%ecx,%edx,4), %eax /* eax = lcode[hold & lmask] */ + +.L_dolen: + /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out + * + * dolen: + * bits -= this.bits; + * hold >>= this.bits + */ + movb %ah, %cl /* cl = this.bits */ + subb %ah, bits_r /* bits -= this.bits */ + shrl %cl, hold_r /* hold >>= this.bits */ + + /* check if op is a literal + * if (op == 0) { + * PUP(out) = this.val; + * } + */ + testb %al, %al + jnz .L_test_for_length_base /* if (op != 0) 45.7% */ + + shrl $16, %eax /* output this.val char */ + stosb + jmp .L_while_test + +.L_test_for_length_base: + /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out, %edx = len + * + * else if (op & 16) { + * len = this.val + * op &= 15 + * if (op) { + * if (op > bits) { + * hold |= *((unsigned short *)in)++ << bits; + * bits += 16 + * } + * len += hold & mask[op]; + * bits -= op; + * hold >>= op; + * } + */ +#define len_r %edx + movl %eax, len_r /* len = this */ + shrl $16, len_r /* len = this.val */ + movb %al, %cl + + testb $16, %al + jz .L_test_for_second_level_length /* if ((op & 16) == 0) 8% */ + andb $15, %cl /* op &= 15 */ + jz .L_save_len /* if (!op) */ + cmpb %cl, bits_r + jae .L_add_bits_to_len /* if (op <= bits) */ + + movb %cl, %ch /* stash op in ch, freeing cl */ + xorl %eax, %eax + lodsw /* al = *(ushort *)in++ */ + movb bits_r, %cl /* cl = bits, needs it for shifting */ + addb $16, bits_r /* bits += 16 */ + shll %cl, %eax + orl %eax, hold_r /* hold |= *((ushort *)in)++ << bits */ + movb %ch, %cl /* move op back to ecx */ + +.L_add_bits_to_len: + movl $1, %eax + shll %cl, %eax + decl %eax + subb %cl, bits_r + andl hold_r, %eax /* eax &= hold */ + shrl %cl, hold_r + addl %eax, len_r /* len += hold & mask[op] */ + +.L_save_len: + movl len_r, len(%esp) /* save len */ +#undef len_r + +.L_decode_distance: + /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out, %edx = dist + * + * if (bits < 15) { + * hold |= *((unsigned short *)in)++ << bits; + * bits += 16 + * } + * this = dcode[hold & dmask]; + * dodist: + * bits -= this.bits; + * hold >>= this.bits; + * op = this.op; + */ + + cmpb $15, bits_r + ja .L_get_distance_code /* if (15 < bits) */ + + xorl %eax, %eax + lodsw /* al = *(ushort *)in++ */ + movb bits_r, %cl /* cl = bits, needs it for shifting */ + addb $16, bits_r /* bits += 16 */ + shll %cl, %eax + orl %eax, hold_r /* hold |= *((ushort *)in)++ << bits */ + +.L_get_distance_code: + movl dmask(%esp), %edx /* edx = dmask */ + movl dcode(%esp), %ecx /* ecx = dcode */ + andl hold_r, %edx /* edx &= hold */ + movl (%ecx,%edx,4), %eax /* eax = dcode[hold & dmask] */ + +#define dist_r %edx +.L_dodist: + movl %eax, dist_r /* dist = this */ + shrl $16, dist_r /* dist = this.val */ + movb %ah, %cl + subb %ah, bits_r /* bits -= this.bits */ + shrl %cl, hold_r /* hold >>= this.bits */ + + /* if (op & 16) { + * dist = this.val + * op &= 15 + * if (op > bits) { + * hold |= *((unsigned short *)in)++ << bits; + * bits += 16 + * } + * dist += hold & mask[op]; + * bits -= op; + * hold >>= op; + */ + movb %al, %cl /* cl = this.op */ + + testb $16, %al /* if ((op & 16) == 0) */ + jz .L_test_for_second_level_dist + andb $15, %cl /* op &= 15 */ + jz .L_check_dist_one + cmpb %cl, bits_r + jae .L_add_bits_to_dist /* if (op <= bits) 97.6% */ + + movb %cl, %ch /* stash op in ch, freeing cl */ + xorl %eax, %eax + lodsw /* al = *(ushort *)in++ */ + movb bits_r, %cl /* cl = bits, needs it for shifting */ + addb $16, bits_r /* bits += 16 */ + shll %cl, %eax + orl %eax, hold_r /* hold |= *((ushort *)in)++ << bits */ + movb %ch, %cl /* move op back to ecx */ + +.L_add_bits_to_dist: + movl $1, %eax + shll %cl, %eax + decl %eax /* (1 << op) - 1 */ + subb %cl, bits_r + andl hold_r, %eax /* eax &= hold */ + shrl %cl, hold_r + addl %eax, dist_r /* dist += hold & ((1 << op) - 1) */ + jmp .L_check_window + +.L_check_window: + /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist + * %ecx = nbytes + * + * nbytes = out - beg; + * if (dist <= nbytes) { + * from = out - dist; + * do { + * PUP(out) = PUP(from); + * } while (--len > 0) { + * } + */ + + movl in_r, in(%esp) /* save in so from can use it's reg */ + movl out_r, %eax + subl beg(%esp), %eax /* nbytes = out - beg */ + + cmpl dist_r, %eax + jb .L_clip_window /* if (dist > nbytes) 4.2% */ + + movl len(%esp), %ecx + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + + subl $3, %ecx + movb (from_r), %al + movb %al, (out_r) + movb 1(from_r), %al + movb 2(from_r), %dl + addl $3, from_r + movb %al, 1(out_r) + movb %dl, 2(out_r) + addl $3, out_r + rep movsb + + movl in(%esp), in_r /* move in back to %esi, toss from */ + jmp .L_while_test + +.align 16,0x90 +.L_check_dist_one: + cmpl $1, dist_r + jne .L_check_window + cmpl out_r, beg(%esp) + je .L_check_window + + decl out_r + movl len(%esp), %ecx + movb (out_r), %al + subl $3, %ecx + + movb %al, 1(out_r) + movb %al, 2(out_r) + movb %al, 3(out_r) + addl $4, out_r + rep stosb + + jmp .L_while_test + +.align 16,0x90 +.L_test_for_second_level_length: + /* else if ((op & 64) == 0) { + * this = lcode[this.val + (hold & mask[op])]; + * } + */ + testb $64, %al + jnz .L_test_for_end_of_block /* if ((op & 64) != 0) */ + + movl $1, %eax + shll %cl, %eax + decl %eax + andl hold_r, %eax /* eax &= hold */ + addl %edx, %eax /* eax += this.val */ + movl lcode(%esp), %edx /* edx = lcode */ + movl (%edx,%eax,4), %eax /* eax = lcode[val + (hold&mask[op])] */ + jmp .L_dolen + +.align 16,0x90 +.L_test_for_second_level_dist: + /* else if ((op & 64) == 0) { + * this = dcode[this.val + (hold & mask[op])]; + * } + */ + testb $64, %al + jnz .L_invalid_distance_code /* if ((op & 64) != 0) */ + + movl $1, %eax + shll %cl, %eax + decl %eax + andl hold_r, %eax /* eax &= hold */ + addl %edx, %eax /* eax += this.val */ + movl dcode(%esp), %edx /* edx = dcode */ + movl (%edx,%eax,4), %eax /* eax = dcode[val + (hold&mask[op])] */ + jmp .L_dodist + +.align 16,0x90 +.L_clip_window: + /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist + * %ecx = nbytes + * + * else { + * if (dist > wsize) { + * invalid distance + * } + * from = window; + * nbytes = dist - nbytes; + * if (write == 0) { + * from += wsize - nbytes; + */ +#define nbytes_r %ecx + movl %eax, nbytes_r + movl wsize(%esp), %eax /* prepare for dist compare */ + negl nbytes_r /* nbytes = -nbytes */ + movl window(%esp), from_r /* from = window */ + + cmpl dist_r, %eax + jb .L_invalid_distance_too_far /* if (dist > wsize) */ + + addl dist_r, nbytes_r /* nbytes = dist - nbytes */ + cmpl $0, write(%esp) + jne .L_wrap_around_window /* if (write != 0) */ + + subl nbytes_r, %eax + addl %eax, from_r /* from += wsize - nbytes */ + + /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist + * %ecx = nbytes, %eax = len + * + * if (nbytes < len) { + * len -= nbytes; + * do { + * PUP(out) = PUP(from); + * } while (--nbytes); + * from = out - dist; + * } + * } + */ +#define len_r %eax + movl len(%esp), len_r + cmpl nbytes_r, len_r + jbe .L_do_copy1 /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + jmp .L_do_copy1 + + cmpl nbytes_r, len_r + jbe .L_do_copy1 /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + jmp .L_do_copy1 + +.L_wrap_around_window: + /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist + * %ecx = nbytes, %eax = write, %eax = len + * + * else if (write < nbytes) { + * from += wsize + write - nbytes; + * nbytes -= write; + * if (nbytes < len) { + * len -= nbytes; + * do { + * PUP(out) = PUP(from); + * } while (--nbytes); + * from = window; + * nbytes = write; + * if (nbytes < len) { + * len -= nbytes; + * do { + * PUP(out) = PUP(from); + * } while(--nbytes); + * from = out - dist; + * } + * } + * } + */ +#define write_r %eax + movl write(%esp), write_r + cmpl write_r, nbytes_r + jbe .L_contiguous_in_window /* if (write >= nbytes) */ + + addl wsize(%esp), from_r + addl write_r, from_r + subl nbytes_r, from_r /* from += wsize + write - nbytes */ + subl write_r, nbytes_r /* nbytes -= write */ +#undef write_r + + movl len(%esp), len_r + cmpl nbytes_r, len_r + jbe .L_do_copy1 /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl window(%esp), from_r /* from = window */ + movl write(%esp), nbytes_r /* nbytes = write */ + cmpl nbytes_r, len_r + jbe .L_do_copy1 /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + jmp .L_do_copy1 + +.L_contiguous_in_window: + /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist + * %ecx = nbytes, %eax = write, %eax = len + * + * else { + * from += write - nbytes; + * if (nbytes < len) { + * len -= nbytes; + * do { + * PUP(out) = PUP(from); + * } while (--nbytes); + * from = out - dist; + * } + * } + */ +#define write_r %eax + addl write_r, from_r + subl nbytes_r, from_r /* from += write - nbytes */ +#undef write_r + + movl len(%esp), len_r + cmpl nbytes_r, len_r + jbe .L_do_copy1 /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + +.L_do_copy1: + /* regs: %esi = from, %esi = in, %ebp = hold, %bl = bits, %edi = out + * %eax = len + * + * while (len > 0) { + * PUP(out) = PUP(from); + * len--; + * } + * } + * } while (in < last && out < end); + */ +#undef nbytes_r +#define in_r %esi + movl len_r, %ecx + rep movsb + + movl in(%esp), in_r /* move in back to %esi, toss from */ + jmp .L_while_test + +#undef len_r +#undef dist_r + +#endif /* NO_MMX || RUN_TIME_MMX */ + + +/*** MMX code ***/ + +#if defined( USE_MMX ) || defined( RUN_TIME_MMX ) + +.align 32,0x90 +.L_init_mmx: + emms + +#undef bits_r +#undef bitslong_r +#define bitslong_r %ebp +#define hold_mm %mm0 + movd %ebp, hold_mm + movl %ebx, bitslong_r + +#define used_mm %mm1 +#define dmask2_mm %mm2 +#define lmask2_mm %mm3 +#define lmask_mm %mm4 +#define dmask_mm %mm5 +#define tmp_mm %mm6 + + movd lmask(%esp), lmask_mm + movq lmask_mm, lmask2_mm + movd dmask(%esp), dmask_mm + movq dmask_mm, dmask2_mm + pxor used_mm, used_mm + movl lcode(%esp), %ebx /* ebx = lcode */ + jmp .L_do_loop_mmx + +.align 32,0x90 +.L_while_test_mmx: + /* while (in < last && out < end) + */ + cmpl out_r, end(%esp) + jbe .L_break_loop /* if (out >= end) */ + + cmpl in_r, last(%esp) + jbe .L_break_loop + +.L_do_loop_mmx: + psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ + + cmpl $32, bitslong_r + ja .L_get_length_code_mmx /* if (32 < bits) */ + + movd bitslong_r, tmp_mm + movd (in_r), %mm7 + addl $4, in_r + psllq tmp_mm, %mm7 + addl $32, bitslong_r + por %mm7, hold_mm /* hold_mm |= *((uint *)in)++ << bits */ + +.L_get_length_code_mmx: + pand hold_mm, lmask_mm + movd lmask_mm, %eax + movq lmask2_mm, lmask_mm + movl (%ebx,%eax,4), %eax /* eax = lcode[hold & lmask] */ + +.L_dolen_mmx: + movzbl %ah, %ecx /* ecx = this.bits */ + movd %ecx, used_mm + subl %ecx, bitslong_r /* bits -= this.bits */ + + testb %al, %al + jnz .L_test_for_length_base_mmx /* if (op != 0) 45.7% */ + + shrl $16, %eax /* output this.val char */ + stosb + jmp .L_while_test_mmx + +.L_test_for_length_base_mmx: +#define len_r %edx + movl %eax, len_r /* len = this */ + shrl $16, len_r /* len = this.val */ + + testb $16, %al + jz .L_test_for_second_level_length_mmx /* if ((op & 16) == 0) 8% */ + andl $15, %eax /* op &= 15 */ + jz .L_decode_distance_mmx /* if (!op) */ + + psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ + movd %eax, used_mm + movd hold_mm, %ecx + subl %eax, bitslong_r + andl .L_mask(,%eax,4), %ecx + addl %ecx, len_r /* len += hold & mask[op] */ + +.L_decode_distance_mmx: + psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ + + cmpl $32, bitslong_r + ja .L_get_dist_code_mmx /* if (32 < bits) */ + + movd bitslong_r, tmp_mm + movd (in_r), %mm7 + addl $4, in_r + psllq tmp_mm, %mm7 + addl $32, bitslong_r + por %mm7, hold_mm /* hold_mm |= *((uint *)in)++ << bits */ + +.L_get_dist_code_mmx: + movl dcode(%esp), %ebx /* ebx = dcode */ + pand hold_mm, dmask_mm + movd dmask_mm, %eax + movq dmask2_mm, dmask_mm + movl (%ebx,%eax,4), %eax /* eax = dcode[hold & lmask] */ + +.L_dodist_mmx: +#define dist_r %ebx + movzbl %ah, %ecx /* ecx = this.bits */ + movl %eax, dist_r + shrl $16, dist_r /* dist = this.val */ + subl %ecx, bitslong_r /* bits -= this.bits */ + movd %ecx, used_mm + + testb $16, %al /* if ((op & 16) == 0) */ + jz .L_test_for_second_level_dist_mmx + andl $15, %eax /* op &= 15 */ + jz .L_check_dist_one_mmx + +.L_add_bits_to_dist_mmx: + psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ + movd %eax, used_mm /* save bit length of current op */ + movd hold_mm, %ecx /* get the next bits on input stream */ + subl %eax, bitslong_r /* bits -= op bits */ + andl .L_mask(,%eax,4), %ecx /* ecx = hold & mask[op] */ + addl %ecx, dist_r /* dist += hold & mask[op] */ + +.L_check_window_mmx: + movl in_r, in(%esp) /* save in so from can use it's reg */ + movl out_r, %eax + subl beg(%esp), %eax /* nbytes = out - beg */ + + cmpl dist_r, %eax + jb .L_clip_window_mmx /* if (dist > nbytes) 4.2% */ + + movl len_r, %ecx + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + + subl $3, %ecx + movb (from_r), %al + movb %al, (out_r) + movb 1(from_r), %al + movb 2(from_r), %dl + addl $3, from_r + movb %al, 1(out_r) + movb %dl, 2(out_r) + addl $3, out_r + rep movsb + + movl in(%esp), in_r /* move in back to %esi, toss from */ + movl lcode(%esp), %ebx /* move lcode back to %ebx, toss dist */ + jmp .L_while_test_mmx + +.align 16,0x90 +.L_check_dist_one_mmx: + cmpl $1, dist_r + jne .L_check_window_mmx + cmpl out_r, beg(%esp) + je .L_check_window_mmx + + decl out_r + movl len_r, %ecx + movb (out_r), %al + subl $3, %ecx + + movb %al, 1(out_r) + movb %al, 2(out_r) + movb %al, 3(out_r) + addl $4, out_r + rep stosb + + movl lcode(%esp), %ebx /* move lcode back to %ebx, toss dist */ + jmp .L_while_test_mmx + +.align 16,0x90 +.L_test_for_second_level_length_mmx: + testb $64, %al + jnz .L_test_for_end_of_block /* if ((op & 64) != 0) */ + + andl $15, %eax + psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ + movd hold_mm, %ecx + andl .L_mask(,%eax,4), %ecx + addl len_r, %ecx + movl (%ebx,%ecx,4), %eax /* eax = lcode[hold & lmask] */ + jmp .L_dolen_mmx + +.align 16,0x90 +.L_test_for_second_level_dist_mmx: + testb $64, %al + jnz .L_invalid_distance_code /* if ((op & 64) != 0) */ + + andl $15, %eax + psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ + movd hold_mm, %ecx + andl .L_mask(,%eax,4), %ecx + movl dcode(%esp), %eax /* ecx = dcode */ + addl dist_r, %ecx + movl (%eax,%ecx,4), %eax /* eax = lcode[hold & lmask] */ + jmp .L_dodist_mmx + +.align 16,0x90 +.L_clip_window_mmx: +#define nbytes_r %ecx + movl %eax, nbytes_r + movl wsize(%esp), %eax /* prepare for dist compare */ + negl nbytes_r /* nbytes = -nbytes */ + movl window(%esp), from_r /* from = window */ + + cmpl dist_r, %eax + jb .L_invalid_distance_too_far /* if (dist > wsize) */ + + addl dist_r, nbytes_r /* nbytes = dist - nbytes */ + cmpl $0, write(%esp) + jne .L_wrap_around_window_mmx /* if (write != 0) */ + + subl nbytes_r, %eax + addl %eax, from_r /* from += wsize - nbytes */ + + cmpl nbytes_r, len_r + jbe .L_do_copy1_mmx /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + jmp .L_do_copy1_mmx + + cmpl nbytes_r, len_r + jbe .L_do_copy1_mmx /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + jmp .L_do_copy1_mmx + +.L_wrap_around_window_mmx: +#define write_r %eax + movl write(%esp), write_r + cmpl write_r, nbytes_r + jbe .L_contiguous_in_window_mmx /* if (write >= nbytes) */ + + addl wsize(%esp), from_r + addl write_r, from_r + subl nbytes_r, from_r /* from += wsize + write - nbytes */ + subl write_r, nbytes_r /* nbytes -= write */ +#undef write_r + + cmpl nbytes_r, len_r + jbe .L_do_copy1_mmx /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl window(%esp), from_r /* from = window */ + movl write(%esp), nbytes_r /* nbytes = write */ + cmpl nbytes_r, len_r + jbe .L_do_copy1_mmx /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + jmp .L_do_copy1_mmx + +.L_contiguous_in_window_mmx: +#define write_r %eax + addl write_r, from_r + subl nbytes_r, from_r /* from += write - nbytes */ +#undef write_r + + cmpl nbytes_r, len_r + jbe .L_do_copy1_mmx /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + +.L_do_copy1_mmx: +#undef nbytes_r +#define in_r %esi + movl len_r, %ecx + rep movsb + + movl in(%esp), in_r /* move in back to %esi, toss from */ + movl lcode(%esp), %ebx /* move lcode back to %ebx, toss dist */ + jmp .L_while_test_mmx + +#undef hold_r +#undef bitslong_r + +#endif /* USE_MMX || RUN_TIME_MMX */ + + +/*** USE_MMX, NO_MMX, and RUNTIME_MMX from here on ***/ + +.L_invalid_distance_code: + /* else { + * strm->msg = "invalid distance code"; + * state->mode = BAD; + * } + */ + movl $.L_invalid_distance_code_msg, %ecx + movl $INFLATE_MODE_BAD, %edx + jmp .L_update_stream_state + +.L_test_for_end_of_block: + /* else if (op & 32) { + * state->mode = TYPE; + * break; + * } + */ + testb $32, %al + jz .L_invalid_literal_length_code /* if ((op & 32) == 0) */ + + movl $0, %ecx + movl $INFLATE_MODE_TYPE, %edx + jmp .L_update_stream_state + +.L_invalid_literal_length_code: + /* else { + * strm->msg = "invalid literal/length code"; + * state->mode = BAD; + * } + */ + movl $.L_invalid_literal_length_code_msg, %ecx + movl $INFLATE_MODE_BAD, %edx + jmp .L_update_stream_state + +.L_invalid_distance_too_far: + /* strm->msg = "invalid distance too far back"; + * state->mode = BAD; + */ + movl in(%esp), in_r /* from_r has in's reg, put in back */ + movl $.L_invalid_distance_too_far_msg, %ecx + movl $INFLATE_MODE_BAD, %edx + jmp .L_update_stream_state + +.L_update_stream_state: + /* set strm->msg = %ecx, strm->state->mode = %edx */ + movl strm_sp(%esp), %eax + testl %ecx, %ecx /* if (msg != NULL) */ + jz .L_skip_msg + movl %ecx, msg_strm(%eax) /* strm->msg = msg */ +.L_skip_msg: + movl state_strm(%eax), %eax /* state = strm->state */ + movl %edx, mode_state(%eax) /* state->mode = edx (BAD | TYPE) */ + jmp .L_break_loop + +.align 32,0x90 +.L_break_loop: + +/* + * Regs: + * + * bits = %ebp when mmx, and in %ebx when non-mmx + * hold = %hold_mm when mmx, and in %ebp when non-mmx + * in = %esi + * out = %edi + */ + +#if defined( USE_MMX ) || defined( RUN_TIME_MMX ) + +#if defined( RUN_TIME_MMX ) + + cmpl $DO_USE_MMX, inflate_fast_use_mmx + jne .L_update_next_in + +#endif /* RUN_TIME_MMX */ + + movl %ebp, %ebx + +.L_update_next_in: + +#endif + +#define strm_r %eax +#define state_r %edx + + /* len = bits >> 3; + * in -= len; + * bits -= len << 3; + * hold &= (1U << bits) - 1; + * state->hold = hold; + * state->bits = bits; + * strm->next_in = in; + * strm->next_out = out; + */ + movl strm_sp(%esp), strm_r + movl %ebx, %ecx + movl state_strm(strm_r), state_r + shrl $3, %ecx + subl %ecx, in_r + shll $3, %ecx + subl %ecx, %ebx + movl out_r, next_out_strm(strm_r) + movl %ebx, bits_state(state_r) + movl %ebx, %ecx + + leal buf(%esp), %ebx + cmpl %ebx, last(%esp) + jne .L_buf_not_used /* if buf != last */ + + subl %ebx, in_r /* in -= buf */ + movl next_in_strm(strm_r), %ebx + movl %ebx, last(%esp) /* last = strm->next_in */ + addl %ebx, in_r /* in += strm->next_in */ + movl avail_in_strm(strm_r), %ebx + subl $11, %ebx + addl %ebx, last(%esp) /* last = &strm->next_in[ avail_in - 11 ] */ + +.L_buf_not_used: + movl in_r, next_in_strm(strm_r) + + movl $1, %ebx + shll %cl, %ebx + decl %ebx + +#if defined( USE_MMX ) || defined( RUN_TIME_MMX ) + +#if defined( RUN_TIME_MMX ) + + cmpl $DO_USE_MMX, inflate_fast_use_mmx + jne .L_update_hold + +#endif /* RUN_TIME_MMX */ + + psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ + movd hold_mm, %ebp + + emms + +.L_update_hold: + +#endif /* USE_MMX || RUN_TIME_MMX */ + + andl %ebx, %ebp + movl %ebp, hold_state(state_r) + +#define last_r %ebx + + /* strm->avail_in = in < last ? 11 + (last - in) : 11 - (in - last) */ + movl last(%esp), last_r + cmpl in_r, last_r + jbe .L_last_is_smaller /* if (in >= last) */ + + subl in_r, last_r /* last -= in */ + addl $11, last_r /* last += 11 */ + movl last_r, avail_in_strm(strm_r) + jmp .L_fixup_out +.L_last_is_smaller: + subl last_r, in_r /* in -= last */ + negl in_r /* in = -in */ + addl $11, in_r /* in += 11 */ + movl in_r, avail_in_strm(strm_r) + +#undef last_r +#define end_r %ebx + +.L_fixup_out: + /* strm->avail_out = out < end ? 257 + (end - out) : 257 - (out - end)*/ + movl end(%esp), end_r + cmpl out_r, end_r + jbe .L_end_is_smaller /* if (out >= end) */ + + subl out_r, end_r /* end -= out */ + addl $257, end_r /* end += 257 */ + movl end_r, avail_out_strm(strm_r) + jmp .L_done +.L_end_is_smaller: + subl end_r, out_r /* out -= end */ + negl out_r /* out = -out */ + addl $257, out_r /* out += 257 */ + movl out_r, avail_out_strm(strm_r) + +#undef end_r +#undef strm_r +#undef state_r + +.L_done: + addl $local_var_size, %esp + popf + popl %ebx + popl %ebp + popl %esi + popl %edi + ret + +#if defined( GAS_ELF ) +/* elf info */ +.type inflate_fast,@function +.size inflate_fast,.-inflate_fast +#endif diff --git a/dependencies/zlib-1.2.11/contrib/iostream/test.cpp b/dependencies/zlib-1.2.11/contrib/iostream/test.cpp new file mode 100644 index 0000000..7d265b3 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/iostream/test.cpp @@ -0,0 +1,24 @@ + +#include "zfstream.h" + +int main() { + + // Construct a stream object with this filebuffer. Anything sent + // to this stream will go to standard out. + gzofstream os( 1, ios::out ); + + // This text is getting compressed and sent to stdout. + // To prove this, run 'test | zcat'. + os << "Hello, Mommy" << endl; + + os << setcompressionlevel( Z_NO_COMPRESSION ); + os << "hello, hello, hi, ho!" << endl; + + setcompressionlevel( os, Z_DEFAULT_COMPRESSION ) + << "I'm compressing again" << endl; + + os.close(); + + return 0; + +} diff --git a/dependencies/zlib-1.2.11/contrib/iostream/zfstream.cpp b/dependencies/zlib-1.2.11/contrib/iostream/zfstream.cpp new file mode 100644 index 0000000..d0cd85f --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/iostream/zfstream.cpp @@ -0,0 +1,329 @@ + +#include "zfstream.h" + +gzfilebuf::gzfilebuf() : + file(NULL), + mode(0), + own_file_descriptor(0) +{ } + +gzfilebuf::~gzfilebuf() { + + sync(); + if ( own_file_descriptor ) + close(); + +} + +gzfilebuf *gzfilebuf::open( const char *name, + int io_mode ) { + + if ( is_open() ) + return NULL; + + char char_mode[10]; + char *p = char_mode; + + if ( io_mode & ios::in ) { + mode = ios::in; + *p++ = 'r'; + } else if ( io_mode & ios::app ) { + mode = ios::app; + *p++ = 'a'; + } else { + mode = ios::out; + *p++ = 'w'; + } + + if ( io_mode & ios::binary ) { + mode |= ios::binary; + *p++ = 'b'; + } + + // Hard code the compression level + if ( io_mode & (ios::out|ios::app )) { + *p++ = '9'; + } + + // Put the end-of-string indicator + *p = '\0'; + + if ( (file = gzopen(name, char_mode)) == NULL ) + return NULL; + + own_file_descriptor = 1; + + return this; + +} + +gzfilebuf *gzfilebuf::attach( int file_descriptor, + int io_mode ) { + + if ( is_open() ) + return NULL; + + char char_mode[10]; + char *p = char_mode; + + if ( io_mode & ios::in ) { + mode = ios::in; + *p++ = 'r'; + } else if ( io_mode & ios::app ) { + mode = ios::app; + *p++ = 'a'; + } else { + mode = ios::out; + *p++ = 'w'; + } + + if ( io_mode & ios::binary ) { + mode |= ios::binary; + *p++ = 'b'; + } + + // Hard code the compression level + if ( io_mode & (ios::out|ios::app )) { + *p++ = '9'; + } + + // Put the end-of-string indicator + *p = '\0'; + + if ( (file = gzdopen(file_descriptor, char_mode)) == NULL ) + return NULL; + + own_file_descriptor = 0; + + return this; + +} + +gzfilebuf *gzfilebuf::close() { + + if ( is_open() ) { + + sync(); + gzclose( file ); + file = NULL; + + } + + return this; + +} + +int gzfilebuf::setcompressionlevel( int comp_level ) { + + return gzsetparams(file, comp_level, -2); + +} + +int gzfilebuf::setcompressionstrategy( int comp_strategy ) { + + return gzsetparams(file, -2, comp_strategy); + +} + + +streampos gzfilebuf::seekoff( streamoff off, ios::seek_dir dir, int which ) { + + return streampos(EOF); + +} + +int gzfilebuf::underflow() { + + // If the file hasn't been opened for reading, error. + if ( !is_open() || !(mode & ios::in) ) + return EOF; + + // if a buffer doesn't exists, allocate one. + if ( !base() ) { + + if ( (allocate()) == EOF ) + return EOF; + setp(0,0); + + } else { + + if ( in_avail() ) + return (unsigned char) *gptr(); + + if ( out_waiting() ) { + if ( flushbuf() == EOF ) + return EOF; + } + + } + + // Attempt to fill the buffer. + + int result = fillbuf(); + if ( result == EOF ) { + // disable get area + setg(0,0,0); + return EOF; + } + + return (unsigned char) *gptr(); + +} + +int gzfilebuf::overflow( int c ) { + + if ( !is_open() || !(mode & ios::out) ) + return EOF; + + if ( !base() ) { + if ( allocate() == EOF ) + return EOF; + setg(0,0,0); + } else { + if (in_avail()) { + return EOF; + } + if (out_waiting()) { + if (flushbuf() == EOF) + return EOF; + } + } + + int bl = blen(); + setp( base(), base() + bl); + + if ( c != EOF ) { + + *pptr() = c; + pbump(1); + + } + + return 0; + +} + +int gzfilebuf::sync() { + + if ( !is_open() ) + return EOF; + + if ( out_waiting() ) + return flushbuf(); + + return 0; + +} + +int gzfilebuf::flushbuf() { + + int n; + char *q; + + q = pbase(); + n = pptr() - q; + + if ( gzwrite( file, q, n) < n ) + return EOF; + + setp(0,0); + + return 0; + +} + +int gzfilebuf::fillbuf() { + + int required; + char *p; + + p = base(); + + required = blen(); + + int t = gzread( file, p, required ); + + if ( t <= 0) return EOF; + + setg( base(), base(), base()+t); + + return t; + +} + +gzfilestream_common::gzfilestream_common() : + ios( gzfilestream_common::rdbuf() ) +{ } + +gzfilestream_common::~gzfilestream_common() +{ } + +void gzfilestream_common::attach( int fd, int io_mode ) { + + if ( !buffer.attach( fd, io_mode) ) + clear( ios::failbit | ios::badbit ); + else + clear(); + +} + +void gzfilestream_common::open( const char *name, int io_mode ) { + + if ( !buffer.open( name, io_mode ) ) + clear( ios::failbit | ios::badbit ); + else + clear(); + +} + +void gzfilestream_common::close() { + + if ( !buffer.close() ) + clear( ios::failbit | ios::badbit ); + +} + +gzfilebuf *gzfilestream_common::rdbuf() +{ + return &buffer; +} + +gzifstream::gzifstream() : + ios( gzfilestream_common::rdbuf() ) +{ + clear( ios::badbit ); +} + +gzifstream::gzifstream( const char *name, int io_mode ) : + ios( gzfilestream_common::rdbuf() ) +{ + gzfilestream_common::open( name, io_mode ); +} + +gzifstream::gzifstream( int fd, int io_mode ) : + ios( gzfilestream_common::rdbuf() ) +{ + gzfilestream_common::attach( fd, io_mode ); +} + +gzifstream::~gzifstream() { } + +gzofstream::gzofstream() : + ios( gzfilestream_common::rdbuf() ) +{ + clear( ios::badbit ); +} + +gzofstream::gzofstream( const char *name, int io_mode ) : + ios( gzfilestream_common::rdbuf() ) +{ + gzfilestream_common::open( name, io_mode ); +} + +gzofstream::gzofstream( int fd, int io_mode ) : + ios( gzfilestream_common::rdbuf() ) +{ + gzfilestream_common::attach( fd, io_mode ); +} + +gzofstream::~gzofstream() { } diff --git a/dependencies/zlib-1.2.11/contrib/iostream/zfstream.h b/dependencies/zlib-1.2.11/contrib/iostream/zfstream.h new file mode 100644 index 0000000..ed79098 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/iostream/zfstream.h @@ -0,0 +1,128 @@ + +#ifndef zfstream_h +#define zfstream_h + +#include +#include "zlib.h" + +class gzfilebuf : public streambuf { + +public: + + gzfilebuf( ); + virtual ~gzfilebuf(); + + gzfilebuf *open( const char *name, int io_mode ); + gzfilebuf *attach( int file_descriptor, int io_mode ); + gzfilebuf *close(); + + int setcompressionlevel( int comp_level ); + int setcompressionstrategy( int comp_strategy ); + + inline int is_open() const { return (file !=NULL); } + + virtual streampos seekoff( streamoff, ios::seek_dir, int ); + + virtual int sync(); + +protected: + + virtual int underflow(); + virtual int overflow( int = EOF ); + +private: + + gzFile file; + short mode; + short own_file_descriptor; + + int flushbuf(); + int fillbuf(); + +}; + +class gzfilestream_common : virtual public ios { + + friend class gzifstream; + friend class gzofstream; + friend gzofstream &setcompressionlevel( gzofstream &, int ); + friend gzofstream &setcompressionstrategy( gzofstream &, int ); + +public: + virtual ~gzfilestream_common(); + + void attach( int fd, int io_mode ); + void open( const char *name, int io_mode ); + void close(); + +protected: + gzfilestream_common(); + +private: + gzfilebuf *rdbuf(); + + gzfilebuf buffer; + +}; + +class gzifstream : public gzfilestream_common, public istream { + +public: + + gzifstream(); + gzifstream( const char *name, int io_mode = ios::in ); + gzifstream( int fd, int io_mode = ios::in ); + + virtual ~gzifstream(); + +}; + +class gzofstream : public gzfilestream_common, public ostream { + +public: + + gzofstream(); + gzofstream( const char *name, int io_mode = ios::out ); + gzofstream( int fd, int io_mode = ios::out ); + + virtual ~gzofstream(); + +}; + +template class gzomanip { + friend gzofstream &operator<<(gzofstream &, const gzomanip &); +public: + gzomanip(gzofstream &(*f)(gzofstream &, T), T v) : func(f), val(v) { } +private: + gzofstream &(*func)(gzofstream &, T); + T val; +}; + +template gzofstream &operator<<(gzofstream &s, const gzomanip &m) +{ + return (*m.func)(s, m.val); +} + +inline gzofstream &setcompressionlevel( gzofstream &s, int l ) +{ + (s.rdbuf())->setcompressionlevel(l); + return s; +} + +inline gzofstream &setcompressionstrategy( gzofstream &s, int l ) +{ + (s.rdbuf())->setcompressionstrategy(l); + return s; +} + +inline gzomanip setcompressionlevel(int l) +{ + return gzomanip(&setcompressionlevel,l); +} + +inline gzomanip setcompressionstrategy(int l) +{ + return gzomanip(&setcompressionstrategy,l); +} + +#endif diff --git a/dependencies/zlib-1.2.11/contrib/iostream2/zstream.h b/dependencies/zlib-1.2.11/contrib/iostream2/zstream.h new file mode 100644 index 0000000..43d2332 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/iostream2/zstream.h @@ -0,0 +1,307 @@ +/* + * + * Copyright (c) 1997 + * Christian Michelsen Research AS + * Advanced Computing + * Fantoftvegen 38, 5036 BERGEN, Norway + * http://www.cmr.no + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Christian Michelsen Research AS makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef ZSTREAM__H +#define ZSTREAM__H + +/* + * zstream.h - C++ interface to the 'zlib' general purpose compression library + * $Id: zstream.h 1.1 1997-06-25 12:00:56+02 tyge Exp tyge $ + */ + +#include +#include +#include +#include "zlib.h" + +#if defined(_WIN32) +# include +# include +# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) +#else +# define SET_BINARY_MODE(file) +#endif + +class zstringlen { +public: + zstringlen(class izstream&); + zstringlen(class ozstream&, const char*); + size_t value() const { return val.word; } +private: + struct Val { unsigned char byte; size_t word; } val; +}; + +// ----------------------------- izstream ----------------------------- + +class izstream +{ + public: + izstream() : m_fp(0) {} + izstream(FILE* fp) : m_fp(0) { open(fp); } + izstream(const char* name) : m_fp(0) { open(name); } + ~izstream() { close(); } + + /* Opens a gzip (.gz) file for reading. + * open() can be used to read a file which is not in gzip format; + * in this case read() will directly read from the file without + * decompression. errno can be checked to distinguish two error + * cases (if errno is zero, the zlib error is Z_MEM_ERROR). + */ + void open(const char* name) { + if (m_fp) close(); + m_fp = ::gzopen(name, "rb"); + } + + void open(FILE* fp) { + SET_BINARY_MODE(fp); + if (m_fp) close(); + m_fp = ::gzdopen(fileno(fp), "rb"); + } + + /* Flushes all pending input if necessary, closes the compressed file + * and deallocates all the (de)compression state. The return value is + * the zlib error number (see function error() below). + */ + int close() { + int r = ::gzclose(m_fp); + m_fp = 0; return r; + } + + /* Binary read the given number of bytes from the compressed file. + */ + int read(void* buf, size_t len) { + return ::gzread(m_fp, buf, len); + } + + /* Returns the error message for the last error which occurred on the + * given compressed file. errnum is set to zlib error number. If an + * error occurred in the file system and not in the compression library, + * errnum is set to Z_ERRNO and the application may consult errno + * to get the exact error code. + */ + const char* error(int* errnum) { + return ::gzerror(m_fp, errnum); + } + + gzFile fp() { return m_fp; } + + private: + gzFile m_fp; +}; + +/* + * Binary read the given (array of) object(s) from the compressed file. + * If the input file was not in gzip format, read() copies the objects number + * of bytes into the buffer. + * returns the number of uncompressed bytes actually read + * (0 for end of file, -1 for error). + */ +template +inline int read(izstream& zs, T* x, Items items) { + return ::gzread(zs.fp(), x, items*sizeof(T)); +} + +/* + * Binary input with the '>' operator. + */ +template +inline izstream& operator>(izstream& zs, T& x) { + ::gzread(zs.fp(), &x, sizeof(T)); + return zs; +} + + +inline zstringlen::zstringlen(izstream& zs) { + zs > val.byte; + if (val.byte == 255) zs > val.word; + else val.word = val.byte; +} + +/* + * Read length of string + the string with the '>' operator. + */ +inline izstream& operator>(izstream& zs, char* x) { + zstringlen len(zs); + ::gzread(zs.fp(), x, len.value()); + x[len.value()] = '\0'; + return zs; +} + +inline char* read_string(izstream& zs) { + zstringlen len(zs); + char* x = new char[len.value()+1]; + ::gzread(zs.fp(), x, len.value()); + x[len.value()] = '\0'; + return x; +} + +// ----------------------------- ozstream ----------------------------- + +class ozstream +{ + public: + ozstream() : m_fp(0), m_os(0) { + } + ozstream(FILE* fp, int level = Z_DEFAULT_COMPRESSION) + : m_fp(0), m_os(0) { + open(fp, level); + } + ozstream(const char* name, int level = Z_DEFAULT_COMPRESSION) + : m_fp(0), m_os(0) { + open(name, level); + } + ~ozstream() { + close(); + } + + /* Opens a gzip (.gz) file for writing. + * The compression level parameter should be in 0..9 + * errno can be checked to distinguish two error cases + * (if errno is zero, the zlib error is Z_MEM_ERROR). + */ + void open(const char* name, int level = Z_DEFAULT_COMPRESSION) { + char mode[4] = "wb\0"; + if (level != Z_DEFAULT_COMPRESSION) mode[2] = '0'+level; + if (m_fp) close(); + m_fp = ::gzopen(name, mode); + } + + /* open from a FILE pointer. + */ + void open(FILE* fp, int level = Z_DEFAULT_COMPRESSION) { + SET_BINARY_MODE(fp); + char mode[4] = "wb\0"; + if (level != Z_DEFAULT_COMPRESSION) mode[2] = '0'+level; + if (m_fp) close(); + m_fp = ::gzdopen(fileno(fp), mode); + } + + /* Flushes all pending output if necessary, closes the compressed file + * and deallocates all the (de)compression state. The return value is + * the zlib error number (see function error() below). + */ + int close() { + if (m_os) { + ::gzwrite(m_fp, m_os->str(), m_os->pcount()); + delete[] m_os->str(); delete m_os; m_os = 0; + } + int r = ::gzclose(m_fp); m_fp = 0; return r; + } + + /* Binary write the given number of bytes into the compressed file. + */ + int write(const void* buf, size_t len) { + return ::gzwrite(m_fp, (voidp) buf, len); + } + + /* Flushes all pending output into the compressed file. The parameter + * _flush is as in the deflate() function. The return value is the zlib + * error number (see function gzerror below). flush() returns Z_OK if + * the flush_ parameter is Z_FINISH and all output could be flushed. + * flush() should be called only when strictly necessary because it can + * degrade compression. + */ + int flush(int _flush) { + os_flush(); + return ::gzflush(m_fp, _flush); + } + + /* Returns the error message for the last error which occurred on the + * given compressed file. errnum is set to zlib error number. If an + * error occurred in the file system and not in the compression library, + * errnum is set to Z_ERRNO and the application may consult errno + * to get the exact error code. + */ + const char* error(int* errnum) { + return ::gzerror(m_fp, errnum); + } + + gzFile fp() { return m_fp; } + + ostream& os() { + if (m_os == 0) m_os = new ostrstream; + return *m_os; + } + + void os_flush() { + if (m_os && m_os->pcount()>0) { + ostrstream* oss = new ostrstream; + oss->fill(m_os->fill()); + oss->flags(m_os->flags()); + oss->precision(m_os->precision()); + oss->width(m_os->width()); + ::gzwrite(m_fp, m_os->str(), m_os->pcount()); + delete[] m_os->str(); delete m_os; m_os = oss; + } + } + + private: + gzFile m_fp; + ostrstream* m_os; +}; + +/* + * Binary write the given (array of) object(s) into the compressed file. + * returns the number of uncompressed bytes actually written + * (0 in case of error). + */ +template +inline int write(ozstream& zs, const T* x, Items items) { + return ::gzwrite(zs.fp(), (voidp) x, items*sizeof(T)); +} + +/* + * Binary output with the '<' operator. + */ +template +inline ozstream& operator<(ozstream& zs, const T& x) { + ::gzwrite(zs.fp(), (voidp) &x, sizeof(T)); + return zs; +} + +inline zstringlen::zstringlen(ozstream& zs, const char* x) { + val.byte = 255; val.word = ::strlen(x); + if (val.word < 255) zs < (val.byte = val.word); + else zs < val; +} + +/* + * Write length of string + the string with the '<' operator. + */ +inline ozstream& operator<(ozstream& zs, const char* x) { + zstringlen len(zs, x); + ::gzwrite(zs.fp(), (voidp) x, len.value()); + return zs; +} + +#ifdef _MSC_VER +inline ozstream& operator<(ozstream& zs, char* const& x) { + return zs < (const char*) x; +} +#endif + +/* + * Ascii write with the << operator; + */ +template +inline ostream& operator<<(ozstream& zs, const T& x) { + zs.os_flush(); + return zs.os() << x; +} + +#endif diff --git a/dependencies/zlib-1.2.11/contrib/iostream2/zstream_test.cpp b/dependencies/zlib-1.2.11/contrib/iostream2/zstream_test.cpp new file mode 100644 index 0000000..6273f62 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/iostream2/zstream_test.cpp @@ -0,0 +1,25 @@ +#include "zstream.h" +#include +#include +#include + +void main() { + char h[256] = "Hello"; + char* g = "Goodbye"; + ozstream out("temp.gz"); + out < "This works well" < h < g; + out.close(); + + izstream in("temp.gz"); // read it back + char *x = read_string(in), *y = new char[256], z[256]; + in > y > z; + in.close(); + cout << x << endl << y << endl << z << endl; + + out.open("temp.gz"); // try ascii output; zcat temp.gz to see the results + out << setw(50) << setfill('#') << setprecision(20) << x << endl << y << endl << z << endl; + out << z << endl << y << endl << x << endl; + out << 1.1234567890123456789 << endl; + + delete[] x; delete[] y; +} diff --git a/dependencies/zlib-1.2.11/contrib/iostream3/README b/dependencies/zlib-1.2.11/contrib/iostream3/README new file mode 100644 index 0000000..f7b319a --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/iostream3/README @@ -0,0 +1,35 @@ +These classes provide a C++ stream interface to the zlib library. It allows you +to do things like: + + gzofstream outf("blah.gz"); + outf << "These go into the gzip file " << 123 << endl; + +It does this by deriving a specialized stream buffer for gzipped files, which is +the way Stroustrup would have done it. :-> + +The gzifstream and gzofstream classes were originally written by Kevin Ruland +and made available in the zlib contrib/iostream directory. The older version still +compiles under gcc 2.xx, but not under gcc 3.xx, which sparked the development of +this version. + +The new classes are as standard-compliant as possible, closely following the +approach of the standard library's fstream classes. It compiles under gcc versions +3.2 and 3.3, but not under gcc 2.xx. This is mainly due to changes in the standard +library naming scheme. The new version of gzifstream/gzofstream/gzfilebuf differs +from the previous one in the following respects: +- added showmanyc +- added setbuf, with support for unbuffered output via setbuf(0,0) +- a few bug fixes of stream behavior +- gzipped output file opened with default compression level instead of maximum level +- setcompressionlevel()/strategy() members replaced by single setcompression() + +The code is provided "as is", with the permission to use, copy, modify, distribute +and sell it for any purpose without fee. + +Ludwig Schwardt + + +DSP Lab +Electrical & Electronic Engineering Department +University of Stellenbosch +South Africa diff --git a/dependencies/zlib-1.2.11/contrib/iostream3/TODO b/dependencies/zlib-1.2.11/contrib/iostream3/TODO new file mode 100644 index 0000000..7032f97 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/iostream3/TODO @@ -0,0 +1,17 @@ +Possible upgrades to gzfilebuf: + +- The ability to do putback (e.g. putbackfail) + +- The ability to seek (zlib supports this, but could be slow/tricky) + +- Simultaneous read/write access (does it make sense?) + +- Support for ios_base::ate open mode + +- Locale support? + +- Check public interface to see which calls give problems + (due to dependence on library internals) + +- Override operator<<(ostream&, gzfilebuf*) to allow direct copying + of stream buffer to stream ( i.e. os << is.rdbuf(); ) diff --git a/dependencies/zlib-1.2.11/contrib/iostream3/test.cc b/dependencies/zlib-1.2.11/contrib/iostream3/test.cc new file mode 100644 index 0000000..9423533 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/iostream3/test.cc @@ -0,0 +1,50 @@ +/* + * Test program for gzifstream and gzofstream + * + * by Ludwig Schwardt + * original version by Kevin Ruland + */ + +#include "zfstream.h" +#include // for cout + +int main() { + + gzofstream outf; + gzifstream inf; + char buf[80]; + + outf.open("test1.txt.gz"); + outf << "The quick brown fox sidestepped the lazy canine\n" + << 1.3 << "\nPlan " << 9 << std::endl; + outf.close(); + std::cout << "Wrote the following message to 'test1.txt.gz' (check with zcat or zless):\n" + << "The quick brown fox sidestepped the lazy canine\n" + << 1.3 << "\nPlan " << 9 << std::endl; + + std::cout << "\nReading 'test1.txt.gz' (buffered) produces:\n"; + inf.open("test1.txt.gz"); + while (inf.getline(buf,80,'\n')) { + std::cout << buf << "\t(" << inf.rdbuf()->in_avail() << " chars left in buffer)\n"; + } + inf.close(); + + outf.rdbuf()->pubsetbuf(0,0); + outf.open("test2.txt.gz"); + outf << setcompression(Z_NO_COMPRESSION) + << "The quick brown fox sidestepped the lazy canine\n" + << 1.3 << "\nPlan " << 9 << std::endl; + outf.close(); + std::cout << "\nWrote the same message to 'test2.txt.gz' in uncompressed form"; + + std::cout << "\nReading 'test2.txt.gz' (unbuffered) produces:\n"; + inf.rdbuf()->pubsetbuf(0,0); + inf.open("test2.txt.gz"); + while (inf.getline(buf,80,'\n')) { + std::cout << buf << "\t(" << inf.rdbuf()->in_avail() << " chars left in buffer)\n"; + } + inf.close(); + + return 0; + +} diff --git a/dependencies/zlib-1.2.11/contrib/iostream3/zfstream.cc b/dependencies/zlib-1.2.11/contrib/iostream3/zfstream.cc new file mode 100644 index 0000000..94eb933 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/iostream3/zfstream.cc @@ -0,0 +1,479 @@ +/* + * A C++ I/O streams interface to the zlib gz* functions + * + * by Ludwig Schwardt + * original version by Kevin Ruland + * + * This version is standard-compliant and compatible with gcc 3.x. + */ + +#include "zfstream.h" +#include // for strcpy, strcat, strlen (mode strings) +#include // for BUFSIZ + +// Internal buffer sizes (default and "unbuffered" versions) +#define BIGBUFSIZE BUFSIZ +#define SMALLBUFSIZE 1 + +/*****************************************************************************/ + +// Default constructor +gzfilebuf::gzfilebuf() +: file(NULL), io_mode(std::ios_base::openmode(0)), own_fd(false), + buffer(NULL), buffer_size(BIGBUFSIZE), own_buffer(true) +{ + // No buffers to start with + this->disable_buffer(); +} + +// Destructor +gzfilebuf::~gzfilebuf() +{ + // Sync output buffer and close only if responsible for file + // (i.e. attached streams should be left open at this stage) + this->sync(); + if (own_fd) + this->close(); + // Make sure internal buffer is deallocated + this->disable_buffer(); +} + +// Set compression level and strategy +int +gzfilebuf::setcompression(int comp_level, + int comp_strategy) +{ + return gzsetparams(file, comp_level, comp_strategy); +} + +// Open gzipped file +gzfilebuf* +gzfilebuf::open(const char *name, + std::ios_base::openmode mode) +{ + // Fail if file already open + if (this->is_open()) + return NULL; + // Don't support simultaneous read/write access (yet) + if ((mode & std::ios_base::in) && (mode & std::ios_base::out)) + return NULL; + + // Build mode string for gzopen and check it [27.8.1.3.2] + char char_mode[6] = "\0\0\0\0\0"; + if (!this->open_mode(mode, char_mode)) + return NULL; + + // Attempt to open file + if ((file = gzopen(name, char_mode)) == NULL) + return NULL; + + // On success, allocate internal buffer and set flags + this->enable_buffer(); + io_mode = mode; + own_fd = true; + return this; +} + +// Attach to gzipped file +gzfilebuf* +gzfilebuf::attach(int fd, + std::ios_base::openmode mode) +{ + // Fail if file already open + if (this->is_open()) + return NULL; + // Don't support simultaneous read/write access (yet) + if ((mode & std::ios_base::in) && (mode & std::ios_base::out)) + return NULL; + + // Build mode string for gzdopen and check it [27.8.1.3.2] + char char_mode[6] = "\0\0\0\0\0"; + if (!this->open_mode(mode, char_mode)) + return NULL; + + // Attempt to attach to file + if ((file = gzdopen(fd, char_mode)) == NULL) + return NULL; + + // On success, allocate internal buffer and set flags + this->enable_buffer(); + io_mode = mode; + own_fd = false; + return this; +} + +// Close gzipped file +gzfilebuf* +gzfilebuf::close() +{ + // Fail immediately if no file is open + if (!this->is_open()) + return NULL; + // Assume success + gzfilebuf* retval = this; + // Attempt to sync and close gzipped file + if (this->sync() == -1) + retval = NULL; + if (gzclose(file) < 0) + retval = NULL; + // File is now gone anyway (postcondition [27.8.1.3.8]) + file = NULL; + own_fd = false; + // Destroy internal buffer if it exists + this->disable_buffer(); + return retval; +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +// Convert int open mode to mode string +bool +gzfilebuf::open_mode(std::ios_base::openmode mode, + char* c_mode) const +{ + bool testb = mode & std::ios_base::binary; + bool testi = mode & std::ios_base::in; + bool testo = mode & std::ios_base::out; + bool testt = mode & std::ios_base::trunc; + bool testa = mode & std::ios_base::app; + + // Check for valid flag combinations - see [27.8.1.3.2] (Table 92) + // Original zfstream hardcoded the compression level to maximum here... + // Double the time for less than 1% size improvement seems + // excessive though - keeping it at the default level + // To change back, just append "9" to the next three mode strings + if (!testi && testo && !testt && !testa) + strcpy(c_mode, "w"); + if (!testi && testo && !testt && testa) + strcpy(c_mode, "a"); + if (!testi && testo && testt && !testa) + strcpy(c_mode, "w"); + if (testi && !testo && !testt && !testa) + strcpy(c_mode, "r"); + // No read/write mode yet +// if (testi && testo && !testt && !testa) +// strcpy(c_mode, "r+"); +// if (testi && testo && testt && !testa) +// strcpy(c_mode, "w+"); + + // Mode string should be empty for invalid combination of flags + if (strlen(c_mode) == 0) + return false; + if (testb) + strcat(c_mode, "b"); + return true; +} + +// Determine number of characters in internal get buffer +std::streamsize +gzfilebuf::showmanyc() +{ + // Calls to underflow will fail if file not opened for reading + if (!this->is_open() || !(io_mode & std::ios_base::in)) + return -1; + // Make sure get area is in use + if (this->gptr() && (this->gptr() < this->egptr())) + return std::streamsize(this->egptr() - this->gptr()); + else + return 0; +} + +// Fill get area from gzipped file +gzfilebuf::int_type +gzfilebuf::underflow() +{ + // If something is left in the get area by chance, return it + // (this shouldn't normally happen, as underflow is only supposed + // to be called when gptr >= egptr, but it serves as error check) + if (this->gptr() && (this->gptr() < this->egptr())) + return traits_type::to_int_type(*(this->gptr())); + + // If the file hasn't been opened for reading, produce error + if (!this->is_open() || !(io_mode & std::ios_base::in)) + return traits_type::eof(); + + // Attempt to fill internal buffer from gzipped file + // (buffer must be guaranteed to exist...) + int bytes_read = gzread(file, buffer, buffer_size); + // Indicates error or EOF + if (bytes_read <= 0) + { + // Reset get area + this->setg(buffer, buffer, buffer); + return traits_type::eof(); + } + // Make all bytes read from file available as get area + this->setg(buffer, buffer, buffer + bytes_read); + + // Return next character in get area + return traits_type::to_int_type(*(this->gptr())); +} + +// Write put area to gzipped file +gzfilebuf::int_type +gzfilebuf::overflow(int_type c) +{ + // Determine whether put area is in use + if (this->pbase()) + { + // Double-check pointer range + if (this->pptr() > this->epptr() || this->pptr() < this->pbase()) + return traits_type::eof(); + // Add extra character to buffer if not EOF + if (!traits_type::eq_int_type(c, traits_type::eof())) + { + *(this->pptr()) = traits_type::to_char_type(c); + this->pbump(1); + } + // Number of characters to write to file + int bytes_to_write = this->pptr() - this->pbase(); + // Overflow doesn't fail if nothing is to be written + if (bytes_to_write > 0) + { + // If the file hasn't been opened for writing, produce error + if (!this->is_open() || !(io_mode & std::ios_base::out)) + return traits_type::eof(); + // If gzipped file won't accept all bytes written to it, fail + if (gzwrite(file, this->pbase(), bytes_to_write) != bytes_to_write) + return traits_type::eof(); + // Reset next pointer to point to pbase on success + this->pbump(-bytes_to_write); + } + } + // Write extra character to file if not EOF + else if (!traits_type::eq_int_type(c, traits_type::eof())) + { + // If the file hasn't been opened for writing, produce error + if (!this->is_open() || !(io_mode & std::ios_base::out)) + return traits_type::eof(); + // Impromptu char buffer (allows "unbuffered" output) + char_type last_char = traits_type::to_char_type(c); + // If gzipped file won't accept this character, fail + if (gzwrite(file, &last_char, 1) != 1) + return traits_type::eof(); + } + + // If you got here, you have succeeded (even if c was EOF) + // The return value should therefore be non-EOF + if (traits_type::eq_int_type(c, traits_type::eof())) + return traits_type::not_eof(c); + else + return c; +} + +// Assign new buffer +std::streambuf* +gzfilebuf::setbuf(char_type* p, + std::streamsize n) +{ + // First make sure stuff is sync'ed, for safety + if (this->sync() == -1) + return NULL; + // If buffering is turned off on purpose via setbuf(0,0), still allocate one... + // "Unbuffered" only really refers to put [27.8.1.4.10], while get needs at + // least a buffer of size 1 (very inefficient though, therefore make it bigger?) + // This follows from [27.5.2.4.3]/12 (gptr needs to point at something, it seems) + if (!p || !n) + { + // Replace existing buffer (if any) with small internal buffer + this->disable_buffer(); + buffer = NULL; + buffer_size = 0; + own_buffer = true; + this->enable_buffer(); + } + else + { + // Replace existing buffer (if any) with external buffer + this->disable_buffer(); + buffer = p; + buffer_size = n; + own_buffer = false; + this->enable_buffer(); + } + return this; +} + +// Write put area to gzipped file (i.e. ensures that put area is empty) +int +gzfilebuf::sync() +{ + return traits_type::eq_int_type(this->overflow(), traits_type::eof()) ? -1 : 0; +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +// Allocate internal buffer +void +gzfilebuf::enable_buffer() +{ + // If internal buffer required, allocate one + if (own_buffer && !buffer) + { + // Check for buffered vs. "unbuffered" + if (buffer_size > 0) + { + // Allocate internal buffer + buffer = new char_type[buffer_size]; + // Get area starts empty and will be expanded by underflow as need arises + this->setg(buffer, buffer, buffer); + // Setup entire internal buffer as put area. + // The one-past-end pointer actually points to the last element of the buffer, + // so that overflow(c) can safely add the extra character c to the sequence. + // These pointers remain in place for the duration of the buffer + this->setp(buffer, buffer + buffer_size - 1); + } + else + { + // Even in "unbuffered" case, (small?) get buffer is still required + buffer_size = SMALLBUFSIZE; + buffer = new char_type[buffer_size]; + this->setg(buffer, buffer, buffer); + // "Unbuffered" means no put buffer + this->setp(0, 0); + } + } + else + { + // If buffer already allocated, reset buffer pointers just to make sure no + // stale chars are lying around + this->setg(buffer, buffer, buffer); + this->setp(buffer, buffer + buffer_size - 1); + } +} + +// Destroy internal buffer +void +gzfilebuf::disable_buffer() +{ + // If internal buffer exists, deallocate it + if (own_buffer && buffer) + { + // Preserve unbuffered status by zeroing size + if (!this->pbase()) + buffer_size = 0; + delete[] buffer; + buffer = NULL; + this->setg(0, 0, 0); + this->setp(0, 0); + } + else + { + // Reset buffer pointers to initial state if external buffer exists + this->setg(buffer, buffer, buffer); + if (buffer) + this->setp(buffer, buffer + buffer_size - 1); + else + this->setp(0, 0); + } +} + +/*****************************************************************************/ + +// Default constructor initializes stream buffer +gzifstream::gzifstream() +: std::istream(NULL), sb() +{ this->init(&sb); } + +// Initialize stream buffer and open file +gzifstream::gzifstream(const char* name, + std::ios_base::openmode mode) +: std::istream(NULL), sb() +{ + this->init(&sb); + this->open(name, mode); +} + +// Initialize stream buffer and attach to file +gzifstream::gzifstream(int fd, + std::ios_base::openmode mode) +: std::istream(NULL), sb() +{ + this->init(&sb); + this->attach(fd, mode); +} + +// Open file and go into fail() state if unsuccessful +void +gzifstream::open(const char* name, + std::ios_base::openmode mode) +{ + if (!sb.open(name, mode | std::ios_base::in)) + this->setstate(std::ios_base::failbit); + else + this->clear(); +} + +// Attach to file and go into fail() state if unsuccessful +void +gzifstream::attach(int fd, + std::ios_base::openmode mode) +{ + if (!sb.attach(fd, mode | std::ios_base::in)) + this->setstate(std::ios_base::failbit); + else + this->clear(); +} + +// Close file +void +gzifstream::close() +{ + if (!sb.close()) + this->setstate(std::ios_base::failbit); +} + +/*****************************************************************************/ + +// Default constructor initializes stream buffer +gzofstream::gzofstream() +: std::ostream(NULL), sb() +{ this->init(&sb); } + +// Initialize stream buffer and open file +gzofstream::gzofstream(const char* name, + std::ios_base::openmode mode) +: std::ostream(NULL), sb() +{ + this->init(&sb); + this->open(name, mode); +} + +// Initialize stream buffer and attach to file +gzofstream::gzofstream(int fd, + std::ios_base::openmode mode) +: std::ostream(NULL), sb() +{ + this->init(&sb); + this->attach(fd, mode); +} + +// Open file and go into fail() state if unsuccessful +void +gzofstream::open(const char* name, + std::ios_base::openmode mode) +{ + if (!sb.open(name, mode | std::ios_base::out)) + this->setstate(std::ios_base::failbit); + else + this->clear(); +} + +// Attach to file and go into fail() state if unsuccessful +void +gzofstream::attach(int fd, + std::ios_base::openmode mode) +{ + if (!sb.attach(fd, mode | std::ios_base::out)) + this->setstate(std::ios_base::failbit); + else + this->clear(); +} + +// Close file +void +gzofstream::close() +{ + if (!sb.close()) + this->setstate(std::ios_base::failbit); +} diff --git a/dependencies/zlib-1.2.11/contrib/iostream3/zfstream.h b/dependencies/zlib-1.2.11/contrib/iostream3/zfstream.h new file mode 100644 index 0000000..8574479 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/iostream3/zfstream.h @@ -0,0 +1,466 @@ +/* + * A C++ I/O streams interface to the zlib gz* functions + * + * by Ludwig Schwardt + * original version by Kevin Ruland + * + * This version is standard-compliant and compatible with gcc 3.x. + */ + +#ifndef ZFSTREAM_H +#define ZFSTREAM_H + +#include // not iostream, since we don't need cin/cout +#include +#include "zlib.h" + +/*****************************************************************************/ + +/** + * @brief Gzipped file stream buffer class. + * + * This class implements basic_filebuf for gzipped files. It doesn't yet support + * seeking (allowed by zlib but slow/limited), putback and read/write access + * (tricky). Otherwise, it attempts to be a drop-in replacement for the standard + * file streambuf. +*/ +class gzfilebuf : public std::streambuf +{ +public: + // Default constructor. + gzfilebuf(); + + // Destructor. + virtual + ~gzfilebuf(); + + /** + * @brief Set compression level and strategy on the fly. + * @param comp_level Compression level (see zlib.h for allowed values) + * @param comp_strategy Compression strategy (see zlib.h for allowed values) + * @return Z_OK on success, Z_STREAM_ERROR otherwise. + * + * Unfortunately, these parameters cannot be modified separately, as the + * previous zfstream version assumed. Since the strategy is seldom changed, + * it can default and setcompression(level) then becomes like the old + * setcompressionlevel(level). + */ + int + setcompression(int comp_level, + int comp_strategy = Z_DEFAULT_STRATEGY); + + /** + * @brief Check if file is open. + * @return True if file is open. + */ + bool + is_open() const { return (file != NULL); } + + /** + * @brief Open gzipped file. + * @param name File name. + * @param mode Open mode flags. + * @return @c this on success, NULL on failure. + */ + gzfilebuf* + open(const char* name, + std::ios_base::openmode mode); + + /** + * @brief Attach to already open gzipped file. + * @param fd File descriptor. + * @param mode Open mode flags. + * @return @c this on success, NULL on failure. + */ + gzfilebuf* + attach(int fd, + std::ios_base::openmode mode); + + /** + * @brief Close gzipped file. + * @return @c this on success, NULL on failure. + */ + gzfilebuf* + close(); + +protected: + /** + * @brief Convert ios open mode int to mode string used by zlib. + * @return True if valid mode flag combination. + */ + bool + open_mode(std::ios_base::openmode mode, + char* c_mode) const; + + /** + * @brief Number of characters available in stream buffer. + * @return Number of characters. + * + * This indicates number of characters in get area of stream buffer. + * These characters can be read without accessing the gzipped file. + */ + virtual std::streamsize + showmanyc(); + + /** + * @brief Fill get area from gzipped file. + * @return First character in get area on success, EOF on error. + * + * This actually reads characters from gzipped file to stream + * buffer. Always buffered. + */ + virtual int_type + underflow(); + + /** + * @brief Write put area to gzipped file. + * @param c Extra character to add to buffer contents. + * @return Non-EOF on success, EOF on error. + * + * This actually writes characters in stream buffer to + * gzipped file. With unbuffered output this is done one + * character at a time. + */ + virtual int_type + overflow(int_type c = traits_type::eof()); + + /** + * @brief Installs external stream buffer. + * @param p Pointer to char buffer. + * @param n Size of external buffer. + * @return @c this on success, NULL on failure. + * + * Call setbuf(0,0) to enable unbuffered output. + */ + virtual std::streambuf* + setbuf(char_type* p, + std::streamsize n); + + /** + * @brief Flush stream buffer to file. + * @return 0 on success, -1 on error. + * + * This calls underflow(EOF) to do the job. + */ + virtual int + sync(); + +// +// Some future enhancements +// +// virtual int_type uflow(); +// virtual int_type pbackfail(int_type c = traits_type::eof()); +// virtual pos_type +// seekoff(off_type off, +// std::ios_base::seekdir way, +// std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out); +// virtual pos_type +// seekpos(pos_type sp, +// std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out); + +private: + /** + * @brief Allocate internal buffer. + * + * This function is safe to call multiple times. It will ensure + * that a proper internal buffer exists if it is required. If the + * buffer already exists or is external, the buffer pointers will be + * reset to their original state. + */ + void + enable_buffer(); + + /** + * @brief Destroy internal buffer. + * + * This function is safe to call multiple times. It will ensure + * that the internal buffer is deallocated if it exists. In any + * case, it will also reset the buffer pointers. + */ + void + disable_buffer(); + + /** + * Underlying file pointer. + */ + gzFile file; + + /** + * Mode in which file was opened. + */ + std::ios_base::openmode io_mode; + + /** + * @brief True if this object owns file descriptor. + * + * This makes the class responsible for closing the file + * upon destruction. + */ + bool own_fd; + + /** + * @brief Stream buffer. + * + * For simplicity this remains allocated on the free store for the + * entire life span of the gzfilebuf object, unless replaced by setbuf. + */ + char_type* buffer; + + /** + * @brief Stream buffer size. + * + * Defaults to system default buffer size (typically 8192 bytes). + * Modified by setbuf. + */ + std::streamsize buffer_size; + + /** + * @brief True if this object owns stream buffer. + * + * This makes the class responsible for deleting the buffer + * upon destruction. + */ + bool own_buffer; +}; + +/*****************************************************************************/ + +/** + * @brief Gzipped file input stream class. + * + * This class implements ifstream for gzipped files. Seeking and putback + * is not supported yet. +*/ +class gzifstream : public std::istream +{ +public: + // Default constructor + gzifstream(); + + /** + * @brief Construct stream on gzipped file to be opened. + * @param name File name. + * @param mode Open mode flags (forced to contain ios::in). + */ + explicit + gzifstream(const char* name, + std::ios_base::openmode mode = std::ios_base::in); + + /** + * @brief Construct stream on already open gzipped file. + * @param fd File descriptor. + * @param mode Open mode flags (forced to contain ios::in). + */ + explicit + gzifstream(int fd, + std::ios_base::openmode mode = std::ios_base::in); + + /** + * Obtain underlying stream buffer. + */ + gzfilebuf* + rdbuf() const + { return const_cast(&sb); } + + /** + * @brief Check if file is open. + * @return True if file is open. + */ + bool + is_open() { return sb.is_open(); } + + /** + * @brief Open gzipped file. + * @param name File name. + * @param mode Open mode flags (forced to contain ios::in). + * + * Stream will be in state good() if file opens successfully; + * otherwise in state fail(). This differs from the behavior of + * ifstream, which never sets the state to good() and therefore + * won't allow you to reuse the stream for a second file unless + * you manually clear() the state. The choice is a matter of + * convenience. + */ + void + open(const char* name, + std::ios_base::openmode mode = std::ios_base::in); + + /** + * @brief Attach to already open gzipped file. + * @param fd File descriptor. + * @param mode Open mode flags (forced to contain ios::in). + * + * Stream will be in state good() if attach succeeded; otherwise + * in state fail(). + */ + void + attach(int fd, + std::ios_base::openmode mode = std::ios_base::in); + + /** + * @brief Close gzipped file. + * + * Stream will be in state fail() if close failed. + */ + void + close(); + +private: + /** + * Underlying stream buffer. + */ + gzfilebuf sb; +}; + +/*****************************************************************************/ + +/** + * @brief Gzipped file output stream class. + * + * This class implements ofstream for gzipped files. Seeking and putback + * is not supported yet. +*/ +class gzofstream : public std::ostream +{ +public: + // Default constructor + gzofstream(); + + /** + * @brief Construct stream on gzipped file to be opened. + * @param name File name. + * @param mode Open mode flags (forced to contain ios::out). + */ + explicit + gzofstream(const char* name, + std::ios_base::openmode mode = std::ios_base::out); + + /** + * @brief Construct stream on already open gzipped file. + * @param fd File descriptor. + * @param mode Open mode flags (forced to contain ios::out). + */ + explicit + gzofstream(int fd, + std::ios_base::openmode mode = std::ios_base::out); + + /** + * Obtain underlying stream buffer. + */ + gzfilebuf* + rdbuf() const + { return const_cast(&sb); } + + /** + * @brief Check if file is open. + * @return True if file is open. + */ + bool + is_open() { return sb.is_open(); } + + /** + * @brief Open gzipped file. + * @param name File name. + * @param mode Open mode flags (forced to contain ios::out). + * + * Stream will be in state good() if file opens successfully; + * otherwise in state fail(). This differs from the behavior of + * ofstream, which never sets the state to good() and therefore + * won't allow you to reuse the stream for a second file unless + * you manually clear() the state. The choice is a matter of + * convenience. + */ + void + open(const char* name, + std::ios_base::openmode mode = std::ios_base::out); + + /** + * @brief Attach to already open gzipped file. + * @param fd File descriptor. + * @param mode Open mode flags (forced to contain ios::out). + * + * Stream will be in state good() if attach succeeded; otherwise + * in state fail(). + */ + void + attach(int fd, + std::ios_base::openmode mode = std::ios_base::out); + + /** + * @brief Close gzipped file. + * + * Stream will be in state fail() if close failed. + */ + void + close(); + +private: + /** + * Underlying stream buffer. + */ + gzfilebuf sb; +}; + +/*****************************************************************************/ + +/** + * @brief Gzipped file output stream manipulator class. + * + * This class defines a two-argument manipulator for gzofstream. It is used + * as base for the setcompression(int,int) manipulator. +*/ +template + class gzomanip2 + { + public: + // Allows insertor to peek at internals + template + friend gzofstream& + operator<<(gzofstream&, + const gzomanip2&); + + // Constructor + gzomanip2(gzofstream& (*f)(gzofstream&, T1, T2), + T1 v1, + T2 v2); + private: + // Underlying manipulator function + gzofstream& + (*func)(gzofstream&, T1, T2); + + // Arguments for manipulator function + T1 val1; + T2 val2; + }; + +/*****************************************************************************/ + +// Manipulator function thunks through to stream buffer +inline gzofstream& +setcompression(gzofstream &gzs, int l, int s = Z_DEFAULT_STRATEGY) +{ + (gzs.rdbuf())->setcompression(l, s); + return gzs; +} + +// Manipulator constructor stores arguments +template + inline + gzomanip2::gzomanip2(gzofstream &(*f)(gzofstream &, T1, T2), + T1 v1, + T2 v2) + : func(f), val1(v1), val2(v2) + { } + +// Insertor applies underlying manipulator function to stream +template + inline gzofstream& + operator<<(gzofstream& s, const gzomanip2& m) + { return (*m.func)(s, m.val1, m.val2); } + +// Insert this onto stream to simplify setting of compression level +inline gzomanip2 +setcompression(int l, int s = Z_DEFAULT_STRATEGY) +{ return gzomanip2(&setcompression, l, s); } + +#endif // ZFSTREAM_H diff --git a/dependencies/zlib-1.2.11/contrib/masmx64/bld_ml64.bat b/dependencies/zlib-1.2.11/contrib/masmx64/bld_ml64.bat new file mode 100644 index 0000000..8f9343d --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/masmx64/bld_ml64.bat @@ -0,0 +1,2 @@ +ml64.exe /Flinffasx64 /c /Zi inffasx64.asm +ml64.exe /Flgvmat64 /c /Zi gvmat64.asm diff --git a/dependencies/zlib-1.2.11/contrib/masmx64/gvmat64.asm b/dependencies/zlib-1.2.11/contrib/masmx64/gvmat64.asm new file mode 100644 index 0000000..9879c28 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/masmx64/gvmat64.asm @@ -0,0 +1,553 @@ +;uInt longest_match_x64( +; deflate_state *s, +; IPos cur_match); /* current match */ + +; gvmat64.asm -- Asm portion of the optimized longest_match for 32 bits x86_64 +; (AMD64 on Athlon 64, Opteron, Phenom +; and Intel EM64T on Pentium 4 with EM64T, Pentium D, Core 2 Duo, Core I5/I7) +; Copyright (C) 1995-2010 Jean-loup Gailly, Brian Raiter and Gilles Vollant. +; +; File written by Gilles Vollant, by converting to assembly the longest_match +; from Jean-loup Gailly in deflate.c of zLib and infoZip zip. +; +; and by taking inspiration on asm686 with masm, optimised assembly code +; from Brian Raiter, written 1998 +; +; This software is provided 'as-is', without any express or implied +; warranty. In no event will the authors be held liable for any damages +; arising from the use of this software. +; +; Permission is granted to anyone to use this software for any purpose, +; including commercial applications, and to alter it and redistribute it +; freely, subject to the following restrictions: +; +; 1. The origin of this software must not be misrepresented; you must not +; claim that you wrote the original software. If you use this software +; in a product, an acknowledgment in the product documentation would be +; appreciated but is not required. +; 2. Altered source versions must be plainly marked as such, and must not be +; misrepresented as being the original software +; 3. This notice may not be removed or altered from any source distribution. +; +; +; +; http://www.zlib.net +; http://www.winimage.com/zLibDll +; http://www.muppetlabs.com/~breadbox/software/assembly.html +; +; to compile this file for infozip Zip, I use option: +; ml64.exe /Flgvmat64 /c /Zi /DINFOZIP gvmat64.asm +; +; to compile this file for zLib, I use option: +; ml64.exe /Flgvmat64 /c /Zi gvmat64.asm +; Be carrefull to adapt zlib1222add below to your version of zLib +; (if you use a version of zLib before 1.0.4 or after 1.2.2.2, change +; value of zlib1222add later) +; +; This file compile with Microsoft Macro Assembler (x64) for AMD64 +; +; ml64.exe is given with Visual Studio 2005/2008/2010 and Windows WDK +; +; (you can get Windows WDK with ml64 for AMD64 from +; http://www.microsoft.com/whdc/Devtools/wdk/default.mspx for low price) +; + + +;uInt longest_match(s, cur_match) +; deflate_state *s; +; IPos cur_match; /* current match */ +.code +longest_match PROC + + +;LocalVarsSize equ 88 + LocalVarsSize equ 72 + +; register used : rax,rbx,rcx,rdx,rsi,rdi,r8,r9,r10,r11,r12 +; free register : r14,r15 +; register can be saved : rsp + + chainlenwmask equ rsp + 8 - LocalVarsSize ; high word: current chain len + ; low word: s->wmask +;window equ rsp + xx - LocalVarsSize ; local copy of s->window ; stored in r10 +;windowbestlen equ rsp + xx - LocalVarsSize ; s->window + bestlen , use r10+r11 +;scanstart equ rsp + xx - LocalVarsSize ; first two bytes of string ; stored in r12w +;scanend equ rsp + xx - LocalVarsSize ; last two bytes of string use ebx +;scanalign equ rsp + xx - LocalVarsSize ; dword-misalignment of string r13 +;bestlen equ rsp + xx - LocalVarsSize ; size of best match so far -> r11d +;scan equ rsp + xx - LocalVarsSize ; ptr to string wanting match -> r9 +IFDEF INFOZIP +ELSE + nicematch equ (rsp + 16 - LocalVarsSize) ; a good enough match size +ENDIF + +save_rdi equ rsp + 24 - LocalVarsSize +save_rsi equ rsp + 32 - LocalVarsSize +save_rbx equ rsp + 40 - LocalVarsSize +save_rbp equ rsp + 48 - LocalVarsSize +save_r12 equ rsp + 56 - LocalVarsSize +save_r13 equ rsp + 64 - LocalVarsSize +;save_r14 equ rsp + 72 - LocalVarsSize +;save_r15 equ rsp + 80 - LocalVarsSize + + +; summary of register usage +; scanend ebx +; scanendw bx +; chainlenwmask edx +; curmatch rsi +; curmatchd esi +; windowbestlen r8 +; scanalign r9 +; scanalignd r9d +; window r10 +; bestlen r11 +; bestlend r11d +; scanstart r12d +; scanstartw r12w +; scan r13 +; nicematch r14d +; limit r15 +; limitd r15d +; prev rcx + +; all the +4 offsets are due to the addition of pending_buf_size (in zlib +; in the deflate_state structure since the asm code was first written +; (if you compile with zlib 1.0.4 or older, remove the +4). +; Note : these value are good with a 8 bytes boundary pack structure + + + MAX_MATCH equ 258 + MIN_MATCH equ 3 + MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1) + + +;;; Offsets for fields in the deflate_state structure. These numbers +;;; are calculated from the definition of deflate_state, with the +;;; assumption that the compiler will dword-align the fields. (Thus, +;;; changing the definition of deflate_state could easily cause this +;;; program to crash horribly, without so much as a warning at +;;; compile time. Sigh.) + +; all the +zlib1222add offsets are due to the addition of fields +; in zlib in the deflate_state structure since the asm code was first written +; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). +; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). +; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). + + +IFDEF INFOZIP + +_DATA SEGMENT +COMM window_size:DWORD +; WMask ; 7fff +COMM window:BYTE:010040H +COMM prev:WORD:08000H +; MatchLen : unused +; PrevMatch : unused +COMM strstart:DWORD +COMM match_start:DWORD +; Lookahead : ignore +COMM prev_length:DWORD ; PrevLen +COMM max_chain_length:DWORD +COMM good_match:DWORD +COMM nice_match:DWORD +prev_ad equ OFFSET prev +window_ad equ OFFSET window +nicematch equ nice_match +_DATA ENDS +WMask equ 07fffh + +ELSE + + IFNDEF zlib1222add + zlib1222add equ 8 + ENDIF +dsWSize equ 56+zlib1222add+(zlib1222add/2) +dsWMask equ 64+zlib1222add+(zlib1222add/2) +dsWindow equ 72+zlib1222add +dsPrev equ 88+zlib1222add +dsMatchLen equ 128+zlib1222add +dsPrevMatch equ 132+zlib1222add +dsStrStart equ 140+zlib1222add +dsMatchStart equ 144+zlib1222add +dsLookahead equ 148+zlib1222add +dsPrevLen equ 152+zlib1222add +dsMaxChainLen equ 156+zlib1222add +dsGoodMatch equ 172+zlib1222add +dsNiceMatch equ 176+zlib1222add + +window_size equ [ rcx + dsWSize] +WMask equ [ rcx + dsWMask] +window_ad equ [ rcx + dsWindow] +prev_ad equ [ rcx + dsPrev] +strstart equ [ rcx + dsStrStart] +match_start equ [ rcx + dsMatchStart] +Lookahead equ [ rcx + dsLookahead] ; 0ffffffffh on infozip +prev_length equ [ rcx + dsPrevLen] +max_chain_length equ [ rcx + dsMaxChainLen] +good_match equ [ rcx + dsGoodMatch] +nice_match equ [ rcx + dsNiceMatch] +ENDIF + +; parameter 1 in r8(deflate state s), param 2 in rdx (cur match) + +; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and +; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp +; +; All registers must be preserved across the call, except for +; rax, rcx, rdx, r8, r9, r10, and r11, which are scratch. + + + +;;; Save registers that the compiler may be using, and adjust esp to +;;; make room for our stack frame. + + +;;; Retrieve the function arguments. r8d will hold cur_match +;;; throughout the entire function. edx will hold the pointer to the +;;; deflate_state structure during the function's setup (before +;;; entering the main loop. + +; parameter 1 in rcx (deflate_state* s), param 2 in edx -> r8 (cur match) + +; this clear high 32 bits of r8, which can be garbage in both r8 and rdx + + mov [save_rdi],rdi + mov [save_rsi],rsi + mov [save_rbx],rbx + mov [save_rbp],rbp +IFDEF INFOZIP + mov r8d,ecx +ELSE + mov r8d,edx +ENDIF + mov [save_r12],r12 + mov [save_r13],r13 +; mov [save_r14],r14 +; mov [save_r15],r15 + + +;;; uInt wmask = s->w_mask; +;;; unsigned chain_length = s->max_chain_length; +;;; if (s->prev_length >= s->good_match) { +;;; chain_length >>= 2; +;;; } + + mov edi, prev_length + mov esi, good_match + mov eax, WMask + mov ebx, max_chain_length + cmp edi, esi + jl LastMatchGood + shr ebx, 2 +LastMatchGood: + +;;; chainlen is decremented once beforehand so that the function can +;;; use the sign flag instead of the zero flag for the exit test. +;;; It is then shifted into the high word, to make room for the wmask +;;; value, which it will always accompany. + + dec ebx + shl ebx, 16 + or ebx, eax + +;;; on zlib only +;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + +IFDEF INFOZIP + mov [chainlenwmask], ebx +; on infozip nice_match = [nice_match] +ELSE + mov eax, nice_match + mov [chainlenwmask], ebx + mov r10d, Lookahead + cmp r10d, eax + cmovnl r10d, eax + mov [nicematch],r10d +ENDIF + +;;; register Bytef *scan = s->window + s->strstart; + mov r10, window_ad + mov ebp, strstart + lea r13, [r10 + rbp] + +;;; Determine how many bytes the scan ptr is off from being +;;; dword-aligned. + + mov r9,r13 + neg r13 + and r13,3 + +;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ? +;;; s->strstart - (IPos)MAX_DIST(s) : NIL; +IFDEF INFOZIP + mov eax,07efah ; MAX_DIST = (WSIZE-MIN_LOOKAHEAD) (0x8000-(3+8+1)) +ELSE + mov eax, window_size + sub eax, MIN_LOOKAHEAD +ENDIF + xor edi,edi + sub ebp, eax + + mov r11d, prev_length + + cmovng ebp,edi + +;;; int best_len = s->prev_length; + + +;;; Store the sum of s->window + best_len in esi locally, and in esi. + + lea rsi,[r10+r11] + +;;; register ush scan_start = *(ushf*)scan; +;;; register ush scan_end = *(ushf*)(scan+best_len-1); +;;; Posf *prev = s->prev; + + movzx r12d,word ptr [r9] + movzx ebx, word ptr [r9 + r11 - 1] + + mov rdi, prev_ad + +;;; Jump into the main loop. + + mov edx, [chainlenwmask] + + cmp bx,word ptr [rsi + r8 - 1] + jz LookupLoopIsZero + +LookupLoop1: + and r8d, edx + + movzx r8d, word ptr [rdi + r8*2] + cmp r8d, ebp + jbe LeaveNow + sub edx, 00010000h + js LeaveNow + +LoopEntry1: + cmp bx,word ptr [rsi + r8 - 1] + jz LookupLoopIsZero + +LookupLoop2: + and r8d, edx + + movzx r8d, word ptr [rdi + r8*2] + cmp r8d, ebp + jbe LeaveNow + sub edx, 00010000h + js LeaveNow + +LoopEntry2: + cmp bx,word ptr [rsi + r8 - 1] + jz LookupLoopIsZero + +LookupLoop4: + and r8d, edx + + movzx r8d, word ptr [rdi + r8*2] + cmp r8d, ebp + jbe LeaveNow + sub edx, 00010000h + js LeaveNow + +LoopEntry4: + + cmp bx,word ptr [rsi + r8 - 1] + jnz LookupLoop1 + jmp LookupLoopIsZero + + +;;; do { +;;; match = s->window + cur_match; +;;; if (*(ushf*)(match+best_len-1) != scan_end || +;;; *(ushf*)match != scan_start) continue; +;;; [...] +;;; } while ((cur_match = prev[cur_match & wmask]) > limit +;;; && --chain_length != 0); +;;; +;;; Here is the inner loop of the function. The function will spend the +;;; majority of its time in this loop, and majority of that time will +;;; be spent in the first ten instructions. +;;; +;;; Within this loop: +;;; ebx = scanend +;;; r8d = curmatch +;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) +;;; esi = windowbestlen - i.e., (window + bestlen) +;;; edi = prev +;;; ebp = limit + +LookupLoop: + and r8d, edx + + movzx r8d, word ptr [rdi + r8*2] + cmp r8d, ebp + jbe LeaveNow + sub edx, 00010000h + js LeaveNow + +LoopEntry: + + cmp bx,word ptr [rsi + r8 - 1] + jnz LookupLoop1 +LookupLoopIsZero: + cmp r12w, word ptr [r10 + r8] + jnz LookupLoop1 + + +;;; Store the current value of chainlen. + mov [chainlenwmask], edx + +;;; Point edi to the string under scrutiny, and esi to the string we +;;; are hoping to match it up with. In actuality, esi and edi are +;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is +;;; initialized to -(MAX_MATCH_8 - scanalign). + + lea rsi,[r8+r10] + mov rdx, 0fffffffffffffef8h; -(MAX_MATCH_8) + lea rsi, [rsi + r13 + 0108h] ;MAX_MATCH_8] + lea rdi, [r9 + r13 + 0108h] ;MAX_MATCH_8] + + prefetcht1 [rsi+rdx] + prefetcht1 [rdi+rdx] + + +;;; Test the strings for equality, 8 bytes at a time. At the end, +;;; adjust rdx so that it is offset to the exact byte that mismatched. +;;; +;;; We already know at this point that the first three bytes of the +;;; strings match each other, and they can be safely passed over before +;;; starting the compare loop. So what this code does is skip over 0-3 +;;; bytes, as much as necessary in order to dword-align the edi +;;; pointer. (rsi will still be misaligned three times out of four.) +;;; +;;; It should be confessed that this loop usually does not represent +;;; much of the total running time. Replacing it with a more +;;; straightforward "rep cmpsb" would not drastically degrade +;;; performance. + + +LoopCmps: + mov rax, [rsi + rdx] + xor rax, [rdi + rdx] + jnz LeaveLoopCmps + + mov rax, [rsi + rdx + 8] + xor rax, [rdi + rdx + 8] + jnz LeaveLoopCmps8 + + + mov rax, [rsi + rdx + 8+8] + xor rax, [rdi + rdx + 8+8] + jnz LeaveLoopCmps16 + + add rdx,8+8+8 + + jnz short LoopCmps + jmp short LenMaximum +LeaveLoopCmps16: add rdx,8 +LeaveLoopCmps8: add rdx,8 +LeaveLoopCmps: + + test eax, 0000FFFFh + jnz LenLower + + test eax,0ffffffffh + + jnz LenLower32 + + add rdx,4 + shr rax,32 + or ax,ax + jnz LenLower + +LenLower32: + shr eax,16 + add rdx,2 +LenLower: sub al, 1 + adc rdx, 0 +;;; Calculate the length of the match. If it is longer than MAX_MATCH, +;;; then automatically accept it as the best possible match and leave. + + lea rax, [rdi + rdx] + sub rax, r9 + cmp eax, MAX_MATCH + jge LenMaximum + +;;; If the length of the match is not longer than the best match we +;;; have so far, then forget it and return to the lookup loop. +;/////////////////////////////////// + + cmp eax, r11d + jg LongerMatch + + lea rsi,[r10+r11] + + mov rdi, prev_ad + mov edx, [chainlenwmask] + jmp LookupLoop + +;;; s->match_start = cur_match; +;;; best_len = len; +;;; if (len >= nice_match) break; +;;; scan_end = *(ushf*)(scan+best_len-1); + +LongerMatch: + mov r11d, eax + mov match_start, r8d + cmp eax, [nicematch] + jge LeaveNow + + lea rsi,[r10+rax] + + movzx ebx, word ptr [r9 + rax - 1] + mov rdi, prev_ad + mov edx, [chainlenwmask] + jmp LookupLoop + +;;; Accept the current string, with the maximum possible length. + +LenMaximum: + mov r11d,MAX_MATCH + mov match_start, r8d + +;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len; +;;; return s->lookahead; + +LeaveNow: +IFDEF INFOZIP + mov eax,r11d +ELSE + mov eax, Lookahead + cmp r11d, eax + cmovng eax, r11d +ENDIF + +;;; Restore the stack and return from whence we came. + + + mov rsi,[save_rsi] + mov rdi,[save_rdi] + mov rbx,[save_rbx] + mov rbp,[save_rbp] + mov r12,[save_r12] + mov r13,[save_r13] +; mov r14,[save_r14] +; mov r15,[save_r15] + + + ret 0 +; please don't remove this string ! +; Your can freely use gvmat64 in any free or commercial app +; but it is far better don't remove the string in the binary! + db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998, converted to amd 64 by Gilles Vollant 2005",0dh,0ah,0 +longest_match ENDP + +match_init PROC + ret 0 +match_init ENDP + + +END diff --git a/dependencies/zlib-1.2.11/contrib/masmx64/inffas8664.c b/dependencies/zlib-1.2.11/contrib/masmx64/inffas8664.c new file mode 100644 index 0000000..e8af06f --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/masmx64/inffas8664.c @@ -0,0 +1,186 @@ +/* inffas8664.c is a hand tuned assembler version of inffast.c - fast decoding + * version for AMD64 on Windows using Microsoft C compiler + * + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Copyright (C) 2003 Chris Anderson + * Please use the copyright conditions above. + * + * 2005 - Adaptation to Microsoft C Compiler for AMD64 by Gilles Vollant + * + * inffas8664.c call function inffas8664fnc in inffasx64.asm + * inffasx64.asm is automatically convert from AMD64 portion of inffas86.c + * + * Dec-29-2003 -- I added AMD64 inflate asm support. This version is also + * slightly quicker on x86 systems because, instead of using rep movsb to copy + * data, it uses rep movsw, which moves data in 2-byte chunks instead of single + * bytes. I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates + * from http://fedora.linux.duke.edu/fc1_x86_64 + * which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with + * 1GB ram. The 64-bit version is about 4% faster than the 32-bit version, + * when decompressing mozilla-source-1.3.tar.gz. + * + * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from + * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at + * the moment. I have successfully compiled and tested this code with gcc2.96, + * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S + * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX + * enabled. I will attempt to merge the MMX code into this version. Newer + * versions of this and inffast.S can be found at + * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/ + * + */ + +#include +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* Mark Adler's comments from inffast.c: */ + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ + + + + typedef struct inffast_ar { +/* 64 32 x86 x86_64 */ +/* ar offset register */ +/* 0 0 */ void *esp; /* esp save */ +/* 8 4 */ void *ebp; /* ebp save */ +/* 16 8 */ unsigned char FAR *in; /* esi rsi local strm->next_in */ +/* 24 12 */ unsigned char FAR *last; /* r9 while in < last */ +/* 32 16 */ unsigned char FAR *out; /* edi rdi local strm->next_out */ +/* 40 20 */ unsigned char FAR *beg; /* inflate()'s init next_out */ +/* 48 24 */ unsigned char FAR *end; /* r10 while out < end */ +/* 56 28 */ unsigned char FAR *window;/* size of window, wsize!=0 */ +/* 64 32 */ code const FAR *lcode; /* ebp rbp local strm->lencode */ +/* 72 36 */ code const FAR *dcode; /* r11 local strm->distcode */ +/* 80 40 */ size_t /*unsigned long */hold; /* edx rdx local strm->hold */ +/* 88 44 */ unsigned bits; /* ebx rbx local strm->bits */ +/* 92 48 */ unsigned wsize; /* window size */ +/* 96 52 */ unsigned write; /* window write index */ +/*100 56 */ unsigned lmask; /* r12 mask for lcode */ +/*104 60 */ unsigned dmask; /* r13 mask for dcode */ +/*108 64 */ unsigned len; /* r14 match length */ +/*112 68 */ unsigned dist; /* r15 match distance */ +/*116 72 */ unsigned status; /* set when state chng*/ + } type_ar; +#ifdef ASMINF + +void inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + type_ar ar; + void inffas8664fnc(struct inffast_ar * par); + + + +#if (defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 )) || (defined(_MSC_VER) && defined(_M_AMD64)) +#define PAD_AVAIL_IN 6 +#define PAD_AVAIL_OUT 258 +#else +#define PAD_AVAIL_IN 5 +#define PAD_AVAIL_OUT 257 +#endif + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + + ar.in = strm->next_in; + ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN); + ar.out = strm->next_out; + ar.beg = ar.out - (start - strm->avail_out); + ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT); + ar.wsize = state->wsize; + ar.write = state->wnext; + ar.window = state->window; + ar.hold = state->hold; + ar.bits = state->bits; + ar.lcode = state->lencode; + ar.dcode = state->distcode; + ar.lmask = (1U << state->lenbits) - 1; + ar.dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + + /* align in on 1/2 hold size boundary */ + while (((size_t)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) { + ar.hold += (unsigned long)*ar.in++ << ar.bits; + ar.bits += 8; + } + + inffas8664fnc(&ar); + + if (ar.status > 1) { + if (ar.status == 2) + strm->msg = "invalid literal/length code"; + else if (ar.status == 3) + strm->msg = "invalid distance code"; + else + strm->msg = "invalid distance too far back"; + state->mode = BAD; + } + else if ( ar.status == 1 ) { + state->mode = TYPE; + } + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + ar.len = ar.bits >> 3; + ar.in -= ar.len; + ar.bits -= ar.len << 3; + ar.hold &= (1U << ar.bits) - 1; + + /* update state and return */ + strm->next_in = ar.in; + strm->next_out = ar.out; + strm->avail_in = (unsigned)(ar.in < ar.last ? + PAD_AVAIL_IN + (ar.last - ar.in) : + PAD_AVAIL_IN - (ar.in - ar.last)); + strm->avail_out = (unsigned)(ar.out < ar.end ? + PAD_AVAIL_OUT + (ar.end - ar.out) : + PAD_AVAIL_OUT - (ar.out - ar.end)); + state->hold = (unsigned long)ar.hold; + state->bits = ar.bits; + return; +} + +#endif diff --git a/dependencies/zlib-1.2.11/contrib/masmx64/inffasx64.asm b/dependencies/zlib-1.2.11/contrib/masmx64/inffasx64.asm new file mode 100644 index 0000000..60a8d89 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/masmx64/inffasx64.asm @@ -0,0 +1,396 @@ +; inffasx64.asm is a hand tuned assembler version of inffast.c - fast decoding +; version for AMD64 on Windows using Microsoft C compiler +; +; inffasx64.asm is automatically convert from AMD64 portion of inffas86.c +; inffasx64.asm is called by inffas8664.c, which contain more info. + + +; to compile this file, I use option +; ml64.exe /Flinffasx64 /c /Zi inffasx64.asm +; with Microsoft Macro Assembler (x64) for AMD64 +; + +; This file compile with Microsoft Macro Assembler (x64) for AMD64 +; +; ml64.exe is given with Visual Studio 2005/2008/2010 and Windows WDK +; +; (you can get Windows WDK with ml64 for AMD64 from +; http://www.microsoft.com/whdc/Devtools/wdk/default.mspx for low price) +; + + +.code +inffas8664fnc PROC + +; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and +; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp +; +; All registers must be preserved across the call, except for +; rax, rcx, rdx, r8, r-9, r10, and r11, which are scratch. + + + mov [rsp-8],rsi + mov [rsp-16],rdi + mov [rsp-24],r12 + mov [rsp-32],r13 + mov [rsp-40],r14 + mov [rsp-48],r15 + mov [rsp-56],rbx + + mov rax,rcx + + mov [rax+8], rbp ; /* save regs rbp and rsp */ + mov [rax], rsp + + mov rsp, rax ; /* make rsp point to &ar */ + + mov rsi, [rsp+16] ; /* rsi = in */ + mov rdi, [rsp+32] ; /* rdi = out */ + mov r9, [rsp+24] ; /* r9 = last */ + mov r10, [rsp+48] ; /* r10 = end */ + mov rbp, [rsp+64] ; /* rbp = lcode */ + mov r11, [rsp+72] ; /* r11 = dcode */ + mov rdx, [rsp+80] ; /* rdx = hold */ + mov ebx, [rsp+88] ; /* ebx = bits */ + mov r12d, [rsp+100] ; /* r12d = lmask */ + mov r13d, [rsp+104] ; /* r13d = dmask */ + ; /* r14d = len */ + ; /* r15d = dist */ + + + cld + cmp r10, rdi + je L_one_time ; /* if only one decode left */ + cmp r9, rsi + + jne L_do_loop + + +L_one_time: + mov r8, r12 ; /* r8 = lmask */ + cmp bl, 32 + ja L_get_length_code_one_time + + lodsd ; /* eax = *(uint *)in++ */ + mov cl, bl ; /* cl = bits, needs it for shifting */ + add bl, 32 ; /* bits += 32 */ + shl rax, cl + or rdx, rax ; /* hold |= *((uint *)in)++ << bits */ + jmp L_get_length_code_one_time + +ALIGN 4 +L_while_test: + cmp r10, rdi + jbe L_break_loop + cmp r9, rsi + jbe L_break_loop + +L_do_loop: + mov r8, r12 ; /* r8 = lmask */ + cmp bl, 32 + ja L_get_length_code ; /* if (32 < bits) */ + + lodsd ; /* eax = *(uint *)in++ */ + mov cl, bl ; /* cl = bits, needs it for shifting */ + add bl, 32 ; /* bits += 32 */ + shl rax, cl + or rdx, rax ; /* hold |= *((uint *)in)++ << bits */ + +L_get_length_code: + and r8, rdx ; /* r8 &= hold */ + mov eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */ + + mov cl, ah ; /* cl = this.bits */ + sub bl, ah ; /* bits -= this.bits */ + shr rdx, cl ; /* hold >>= this.bits */ + + test al, al + jnz L_test_for_length_base ; /* if (op != 0) 45.7% */ + + mov r8, r12 ; /* r8 = lmask */ + shr eax, 16 ; /* output this.val char */ + stosb + +L_get_length_code_one_time: + and r8, rdx ; /* r8 &= hold */ + mov eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */ + +L_dolen: + mov cl, ah ; /* cl = this.bits */ + sub bl, ah ; /* bits -= this.bits */ + shr rdx, cl ; /* hold >>= this.bits */ + + test al, al + jnz L_test_for_length_base ; /* if (op != 0) 45.7% */ + + shr eax, 16 ; /* output this.val char */ + stosb + jmp L_while_test + +ALIGN 4 +L_test_for_length_base: + mov r14d, eax ; /* len = this */ + shr r14d, 16 ; /* len = this.val */ + mov cl, al + + test al, 16 + jz L_test_for_second_level_length ; /* if ((op & 16) == 0) 8% */ + and cl, 15 ; /* op &= 15 */ + jz L_decode_distance ; /* if (!op) */ + +L_add_bits_to_len: + sub bl, cl + xor eax, eax + inc eax + shl eax, cl + dec eax + and eax, edx ; /* eax &= hold */ + shr rdx, cl + add r14d, eax ; /* len += hold & mask[op] */ + +L_decode_distance: + mov r8, r13 ; /* r8 = dmask */ + cmp bl, 32 + ja L_get_distance_code ; /* if (32 < bits) */ + + lodsd ; /* eax = *(uint *)in++ */ + mov cl, bl ; /* cl = bits, needs it for shifting */ + add bl, 32 ; /* bits += 32 */ + shl rax, cl + or rdx, rax ; /* hold |= *((uint *)in)++ << bits */ + +L_get_distance_code: + and r8, rdx ; /* r8 &= hold */ + mov eax, [r11+r8*4] ; /* eax = dcode[hold & dmask] */ + +L_dodist: + mov r15d, eax ; /* dist = this */ + shr r15d, 16 ; /* dist = this.val */ + mov cl, ah + sub bl, ah ; /* bits -= this.bits */ + shr rdx, cl ; /* hold >>= this.bits */ + mov cl, al ; /* cl = this.op */ + + test al, 16 ; /* if ((op & 16) == 0) */ + jz L_test_for_second_level_dist + and cl, 15 ; /* op &= 15 */ + jz L_check_dist_one + +L_add_bits_to_dist: + sub bl, cl + xor eax, eax + inc eax + shl eax, cl + dec eax ; /* (1 << op) - 1 */ + and eax, edx ; /* eax &= hold */ + shr rdx, cl + add r15d, eax ; /* dist += hold & ((1 << op) - 1) */ + +L_check_window: + mov r8, rsi ; /* save in so from can use it's reg */ + mov rax, rdi + sub rax, [rsp+40] ; /* nbytes = out - beg */ + + cmp eax, r15d + jb L_clip_window ; /* if (dist > nbytes) 4.2% */ + + mov ecx, r14d ; /* ecx = len */ + mov rsi, rdi + sub rsi, r15 ; /* from = out - dist */ + + sar ecx, 1 + jnc L_copy_two ; /* if len % 2 == 0 */ + + rep movsw + mov al, [rsi] + mov [rdi], al + inc rdi + + mov rsi, r8 ; /* move in back to %rsi, toss from */ + jmp L_while_test + +L_copy_two: + rep movsw + mov rsi, r8 ; /* move in back to %rsi, toss from */ + jmp L_while_test + +ALIGN 4 +L_check_dist_one: + cmp r15d, 1 ; /* if dist 1, is a memset */ + jne L_check_window + cmp [rsp+40], rdi ; /* if out == beg, outside window */ + je L_check_window + + mov ecx, r14d ; /* ecx = len */ + mov al, [rdi-1] + mov ah, al + + sar ecx, 1 + jnc L_set_two + mov [rdi], al + inc rdi + +L_set_two: + rep stosw + jmp L_while_test + +ALIGN 4 +L_test_for_second_level_length: + test al, 64 + jnz L_test_for_end_of_block ; /* if ((op & 64) != 0) */ + + xor eax, eax + inc eax + shl eax, cl + dec eax + and eax, edx ; /* eax &= hold */ + add eax, r14d ; /* eax += len */ + mov eax, [rbp+rax*4] ; /* eax = lcode[val+(hold&mask[op])]*/ + jmp L_dolen + +ALIGN 4 +L_test_for_second_level_dist: + test al, 64 + jnz L_invalid_distance_code ; /* if ((op & 64) != 0) */ + + xor eax, eax + inc eax + shl eax, cl + dec eax + and eax, edx ; /* eax &= hold */ + add eax, r15d ; /* eax += dist */ + mov eax, [r11+rax*4] ; /* eax = dcode[val+(hold&mask[op])]*/ + jmp L_dodist + +ALIGN 4 +L_clip_window: + mov ecx, eax ; /* ecx = nbytes */ + mov eax, [rsp+92] ; /* eax = wsize, prepare for dist cmp */ + neg ecx ; /* nbytes = -nbytes */ + + cmp eax, r15d + jb L_invalid_distance_too_far ; /* if (dist > wsize) */ + + add ecx, r15d ; /* nbytes = dist - nbytes */ + cmp dword ptr [rsp+96], 0 + jne L_wrap_around_window ; /* if (write != 0) */ + + mov rsi, [rsp+56] ; /* from = window */ + sub eax, ecx ; /* eax -= nbytes */ + add rsi, rax ; /* from += wsize - nbytes */ + + mov eax, r14d ; /* eax = len */ + cmp r14d, ecx + jbe L_do_copy ; /* if (nbytes >= len) */ + + sub eax, ecx ; /* eax -= nbytes */ + rep movsb + mov rsi, rdi + sub rsi, r15 ; /* from = &out[ -dist ] */ + jmp L_do_copy + +ALIGN 4 +L_wrap_around_window: + mov eax, [rsp+96] ; /* eax = write */ + cmp ecx, eax + jbe L_contiguous_in_window ; /* if (write >= nbytes) */ + + mov esi, [rsp+92] ; /* from = wsize */ + add rsi, [rsp+56] ; /* from += window */ + add rsi, rax ; /* from += write */ + sub rsi, rcx ; /* from -= nbytes */ + sub ecx, eax ; /* nbytes -= write */ + + mov eax, r14d ; /* eax = len */ + cmp eax, ecx + jbe L_do_copy ; /* if (nbytes >= len) */ + + sub eax, ecx ; /* len -= nbytes */ + rep movsb + mov rsi, [rsp+56] ; /* from = window */ + mov ecx, [rsp+96] ; /* nbytes = write */ + cmp eax, ecx + jbe L_do_copy ; /* if (nbytes >= len) */ + + sub eax, ecx ; /* len -= nbytes */ + rep movsb + mov rsi, rdi + sub rsi, r15 ; /* from = out - dist */ + jmp L_do_copy + +ALIGN 4 +L_contiguous_in_window: + mov rsi, [rsp+56] ; /* rsi = window */ + add rsi, rax + sub rsi, rcx ; /* from += write - nbytes */ + + mov eax, r14d ; /* eax = len */ + cmp eax, ecx + jbe L_do_copy ; /* if (nbytes >= len) */ + + sub eax, ecx ; /* len -= nbytes */ + rep movsb + mov rsi, rdi + sub rsi, r15 ; /* from = out - dist */ + jmp L_do_copy ; /* if (nbytes >= len) */ + +ALIGN 4 +L_do_copy: + mov ecx, eax ; /* ecx = len */ + rep movsb + + mov rsi, r8 ; /* move in back to %esi, toss from */ + jmp L_while_test + +L_test_for_end_of_block: + test al, 32 + jz L_invalid_literal_length_code + mov dword ptr [rsp+116], 1 + jmp L_break_loop_with_status + +L_invalid_literal_length_code: + mov dword ptr [rsp+116], 2 + jmp L_break_loop_with_status + +L_invalid_distance_code: + mov dword ptr [rsp+116], 3 + jmp L_break_loop_with_status + +L_invalid_distance_too_far: + mov dword ptr [rsp+116], 4 + jmp L_break_loop_with_status + +L_break_loop: + mov dword ptr [rsp+116], 0 + +L_break_loop_with_status: +; /* put in, out, bits, and hold back into ar and pop esp */ + mov [rsp+16], rsi ; /* in */ + mov [rsp+32], rdi ; /* out */ + mov [rsp+88], ebx ; /* bits */ + mov [rsp+80], rdx ; /* hold */ + + mov rax, [rsp] ; /* restore rbp and rsp */ + mov rbp, [rsp+8] + mov rsp, rax + + + + mov rsi,[rsp-8] + mov rdi,[rsp-16] + mov r12,[rsp-24] + mov r13,[rsp-32] + mov r14,[rsp-40] + mov r15,[rsp-48] + mov rbx,[rsp-56] + + ret 0 +; : +; : "m" (ar) +; : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", +; "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" +; ); + +inffas8664fnc ENDP +;_TEXT ENDS +END diff --git a/dependencies/zlib-1.2.11/contrib/masmx64/readme.txt b/dependencies/zlib-1.2.11/contrib/masmx64/readme.txt new file mode 100644 index 0000000..2da6733 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/masmx64/readme.txt @@ -0,0 +1,31 @@ +Summary +------- +This directory contains ASM implementations of the functions +longest_match() and inflate_fast(), for 64 bits x86 (both AMD64 and Intel EM64t), +for use with Microsoft Macro Assembler (x64) for AMD64 and Microsoft C++ 64 bits. + +gvmat64.asm is written by Gilles Vollant (2005), by using Brian Raiter 686/32 bits + assembly optimized version from Jean-loup Gailly original longest_match function + +inffasx64.asm and inffas8664.c were written by Chris Anderson, by optimizing + original function from Mark Adler + +Use instructions +---------------- +Assemble the .asm files using MASM and put the object files into the zlib source +directory. You can also get object files here: + + http://www.winimage.com/zLibDll/zlib124_masm_obj.zip + +define ASMV and ASMINF in your project. Include inffas8664.c in your source tree, +and inffasx64.obj and gvmat64.obj as object to link. + + +Build instructions +------------------ +run bld_64.bat with Microsoft Macro Assembler (x64) for AMD64 (ml64.exe) + +ml64.exe is given with Visual Studio 2005, Windows 2003 server DDK + +You can get Windows 2003 server DDK with ml64 and cl for AMD64 from + http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price) diff --git a/dependencies/zlib-1.2.11/contrib/masmx86/bld_ml32.bat b/dependencies/zlib-1.2.11/contrib/masmx86/bld_ml32.bat new file mode 100644 index 0000000..e1b86bf --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/masmx86/bld_ml32.bat @@ -0,0 +1,2 @@ +ml /coff /Zi /c /Flmatch686.lst match686.asm +ml /coff /Zi /c /Flinffas32.lst inffas32.asm diff --git a/dependencies/zlib-1.2.11/contrib/masmx86/inffas32.asm b/dependencies/zlib-1.2.11/contrib/masmx86/inffas32.asm new file mode 100644 index 0000000..03d20f8 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/masmx86/inffas32.asm @@ -0,0 +1,1080 @@ +;/* inffas32.asm is a hand tuned assembler version of inffast.c -- fast decoding +; * +; * inffas32.asm is derivated from inffas86.c, with translation of assembly code +; * +; * Copyright (C) 1995-2003 Mark Adler +; * For conditions of distribution and use, see copyright notice in zlib.h +; * +; * Copyright (C) 2003 Chris Anderson +; * Please use the copyright conditions above. +; * +; * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from +; * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at +; * the moment. I have successfully compiled and tested this code with gcc2.96, +; * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S +; * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX +; * enabled. I will attempt to merge the MMX code into this version. Newer +; * versions of this and inffast.S can be found at +; * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/ +; * +; * 2005 : modification by Gilles Vollant +; */ +; For Visual C++ 4.x and higher and ML 6.x and higher +; ml.exe is in directory \MASM611C of Win95 DDK +; ml.exe is also distributed in http://www.masm32.com/masmdl.htm +; and in VC++2003 toolkit at http://msdn.microsoft.com/visualc/vctoolkit2003/ +; +; +; compile with command line option +; ml /coff /Zi /c /Flinffas32.lst inffas32.asm + +; if you define NO_GZIP (see inflate.h), compile with +; ml /coff /Zi /c /Flinffas32.lst /DNO_GUNZIP inffas32.asm + + +; zlib122sup is 0 fort zlib 1.2.2.1 and lower +; zlib122sup is 8 fort zlib 1.2.2.2 and more (with addition of dmax and head +; in inflate_state in inflate.h) +zlib1222sup equ 8 + + +IFDEF GUNZIP + INFLATE_MODE_TYPE equ 11 + INFLATE_MODE_BAD equ 26 +ELSE + IFNDEF NO_GUNZIP + INFLATE_MODE_TYPE equ 11 + INFLATE_MODE_BAD equ 26 + ELSE + INFLATE_MODE_TYPE equ 3 + INFLATE_MODE_BAD equ 17 + ENDIF +ENDIF + + +; 75 "inffast.S" +;FILE "inffast.S" + +;;;GLOBAL _inflate_fast + +;;;SECTION .text + + + + .586p + .mmx + + name inflate_fast_x86 + .MODEL FLAT + +_DATA segment +inflate_fast_use_mmx: + dd 1 + + +_TEXT segment + + + +ALIGN 4 + db 'Fast decoding Code from Chris Anderson' + db 0 + +ALIGN 4 +invalid_literal_length_code_msg: + db 'invalid literal/length code' + db 0 + +ALIGN 4 +invalid_distance_code_msg: + db 'invalid distance code' + db 0 + +ALIGN 4 +invalid_distance_too_far_msg: + db 'invalid distance too far back' + db 0 + + +ALIGN 4 +inflate_fast_mask: +dd 0 +dd 1 +dd 3 +dd 7 +dd 15 +dd 31 +dd 63 +dd 127 +dd 255 +dd 511 +dd 1023 +dd 2047 +dd 4095 +dd 8191 +dd 16383 +dd 32767 +dd 65535 +dd 131071 +dd 262143 +dd 524287 +dd 1048575 +dd 2097151 +dd 4194303 +dd 8388607 +dd 16777215 +dd 33554431 +dd 67108863 +dd 134217727 +dd 268435455 +dd 536870911 +dd 1073741823 +dd 2147483647 +dd 4294967295 + + +mode_state equ 0 ;/* state->mode */ +wsize_state equ (32+zlib1222sup) ;/* state->wsize */ +write_state equ (36+4+zlib1222sup) ;/* state->write */ +window_state equ (40+4+zlib1222sup) ;/* state->window */ +hold_state equ (44+4+zlib1222sup) ;/* state->hold */ +bits_state equ (48+4+zlib1222sup) ;/* state->bits */ +lencode_state equ (64+4+zlib1222sup) ;/* state->lencode */ +distcode_state equ (68+4+zlib1222sup) ;/* state->distcode */ +lenbits_state equ (72+4+zlib1222sup) ;/* state->lenbits */ +distbits_state equ (76+4+zlib1222sup) ;/* state->distbits */ + + +;;SECTION .text +; 205 "inffast.S" +;GLOBAL inflate_fast_use_mmx + +;SECTION .data + + +; GLOBAL inflate_fast_use_mmx:object +;.size inflate_fast_use_mmx, 4 +; 226 "inffast.S" +;SECTION .text + +ALIGN 4 +_inflate_fast proc near +.FPO (16, 4, 0, 0, 1, 0) + push edi + push esi + push ebp + push ebx + pushfd + sub esp,64 + cld + + + + + mov esi, [esp+88] + mov edi, [esi+28] + + + + + + + + mov edx, [esi+4] + mov eax, [esi+0] + + add edx,eax + sub edx,11 + + mov [esp+44],eax + mov [esp+20],edx + + mov ebp, [esp+92] + mov ecx, [esi+16] + mov ebx, [esi+12] + + sub ebp,ecx + neg ebp + add ebp,ebx + + sub ecx,257 + add ecx,ebx + + mov [esp+60],ebx + mov [esp+40],ebp + mov [esp+16],ecx +; 285 "inffast.S" + mov eax, [edi+lencode_state] + mov ecx, [edi+distcode_state] + + mov [esp+8],eax + mov [esp+12],ecx + + mov eax,1 + mov ecx, [edi+lenbits_state] + shl eax,cl + dec eax + mov [esp+0],eax + + mov eax,1 + mov ecx, [edi+distbits_state] + shl eax,cl + dec eax + mov [esp+4],eax + + mov eax, [edi+wsize_state] + mov ecx, [edi+write_state] + mov edx, [edi+window_state] + + mov [esp+52],eax + mov [esp+48],ecx + mov [esp+56],edx + + mov ebp, [edi+hold_state] + mov ebx, [edi+bits_state] +; 321 "inffast.S" + mov esi, [esp+44] + mov ecx, [esp+20] + cmp ecx,esi + ja L_align_long + + add ecx,11 + sub ecx,esi + mov eax,12 + sub eax,ecx + lea edi, [esp+28] + rep movsb + mov ecx,eax + xor eax,eax + rep stosb + lea esi, [esp+28] + mov [esp+20],esi + jmp L_is_aligned + + +L_align_long: + test esi,3 + jz L_is_aligned + xor eax,eax + mov al, [esi] + inc esi + mov ecx,ebx + add ebx,8 + shl eax,cl + or ebp,eax + jmp L_align_long + +L_is_aligned: + mov edi, [esp+60] +; 366 "inffast.S" +L_check_mmx: + cmp dword ptr [inflate_fast_use_mmx],2 + je L_init_mmx + ja L_do_loop + + push eax + push ebx + push ecx + push edx + pushfd + mov eax, [esp] + xor dword ptr [esp],0200000h + + + + + popfd + pushfd + pop edx + xor edx,eax + jz L_dont_use_mmx + xor eax,eax + cpuid + cmp ebx,0756e6547h + jne L_dont_use_mmx + cmp ecx,06c65746eh + jne L_dont_use_mmx + cmp edx,049656e69h + jne L_dont_use_mmx + mov eax,1 + cpuid + shr eax,8 + and eax,15 + cmp eax,6 + jne L_dont_use_mmx + test edx,0800000h + jnz L_use_mmx + jmp L_dont_use_mmx +L_use_mmx: + mov dword ptr [inflate_fast_use_mmx],2 + jmp L_check_mmx_pop +L_dont_use_mmx: + mov dword ptr [inflate_fast_use_mmx],3 +L_check_mmx_pop: + pop edx + pop ecx + pop ebx + pop eax + jmp L_check_mmx +; 426 "inffast.S" +ALIGN 4 +L_do_loop: +; 437 "inffast.S" + cmp bl,15 + ja L_get_length_code + + xor eax,eax + lodsw + mov cl,bl + add bl,16 + shl eax,cl + or ebp,eax + +L_get_length_code: + mov edx, [esp+0] + mov ecx, [esp+8] + and edx,ebp + mov eax, [ecx+edx*4] + +L_dolen: + + + + + + + mov cl,ah + sub bl,ah + shr ebp,cl + + + + + + + test al,al + jnz L_test_for_length_base + + shr eax,16 + stosb + +L_while_test: + + + cmp [esp+16],edi + jbe L_break_loop + + cmp [esp+20],esi + ja L_do_loop + jmp L_break_loop + +L_test_for_length_base: +; 502 "inffast.S" + mov edx,eax + shr edx,16 + mov cl,al + + test al,16 + jz L_test_for_second_level_length + and cl,15 + jz L_save_len + cmp bl,cl + jae L_add_bits_to_len + + mov ch,cl + xor eax,eax + lodsw + mov cl,bl + add bl,16 + shl eax,cl + or ebp,eax + mov cl,ch + +L_add_bits_to_len: + mov eax,1 + shl eax,cl + dec eax + sub bl,cl + and eax,ebp + shr ebp,cl + add edx,eax + +L_save_len: + mov [esp+24],edx + + +L_decode_distance: +; 549 "inffast.S" + cmp bl,15 + ja L_get_distance_code + + xor eax,eax + lodsw + mov cl,bl + add bl,16 + shl eax,cl + or ebp,eax + +L_get_distance_code: + mov edx, [esp+4] + mov ecx, [esp+12] + and edx,ebp + mov eax, [ecx+edx*4] + + +L_dodist: + mov edx,eax + shr edx,16 + mov cl,ah + sub bl,ah + shr ebp,cl +; 584 "inffast.S" + mov cl,al + + test al,16 + jz L_test_for_second_level_dist + and cl,15 + jz L_check_dist_one + cmp bl,cl + jae L_add_bits_to_dist + + mov ch,cl + xor eax,eax + lodsw + mov cl,bl + add bl,16 + shl eax,cl + or ebp,eax + mov cl,ch + +L_add_bits_to_dist: + mov eax,1 + shl eax,cl + dec eax + sub bl,cl + and eax,ebp + shr ebp,cl + add edx,eax + jmp L_check_window + +L_check_window: +; 625 "inffast.S" + mov [esp+44],esi + mov eax,edi + sub eax, [esp+40] + + cmp eax,edx + jb L_clip_window + + mov ecx, [esp+24] + mov esi,edi + sub esi,edx + + sub ecx,3 + mov al, [esi] + mov [edi],al + mov al, [esi+1] + mov dl, [esi+2] + add esi,3 + mov [edi+1],al + mov [edi+2],dl + add edi,3 + rep movsb + + mov esi, [esp+44] + jmp L_while_test + +ALIGN 4 +L_check_dist_one: + cmp edx,1 + jne L_check_window + cmp [esp+40],edi + je L_check_window + + dec edi + mov ecx, [esp+24] + mov al, [edi] + sub ecx,3 + + mov [edi+1],al + mov [edi+2],al + mov [edi+3],al + add edi,4 + rep stosb + + jmp L_while_test + +ALIGN 4 +L_test_for_second_level_length: + + + + + test al,64 + jnz L_test_for_end_of_block + + mov eax,1 + shl eax,cl + dec eax + and eax,ebp + add eax,edx + mov edx, [esp+8] + mov eax, [edx+eax*4] + jmp L_dolen + +ALIGN 4 +L_test_for_second_level_dist: + + + + + test al,64 + jnz L_invalid_distance_code + + mov eax,1 + shl eax,cl + dec eax + and eax,ebp + add eax,edx + mov edx, [esp+12] + mov eax, [edx+eax*4] + jmp L_dodist + +ALIGN 4 +L_clip_window: +; 721 "inffast.S" + mov ecx,eax + mov eax, [esp+52] + neg ecx + mov esi, [esp+56] + + cmp eax,edx + jb L_invalid_distance_too_far + + add ecx,edx + cmp dword ptr [esp+48],0 + jne L_wrap_around_window + + sub eax,ecx + add esi,eax +; 749 "inffast.S" + mov eax, [esp+24] + cmp eax,ecx + jbe L_do_copy1 + + sub eax,ecx + rep movsb + mov esi,edi + sub esi,edx + jmp L_do_copy1 + + cmp eax,ecx + jbe L_do_copy1 + + sub eax,ecx + rep movsb + mov esi,edi + sub esi,edx + jmp L_do_copy1 + +L_wrap_around_window: +; 793 "inffast.S" + mov eax, [esp+48] + cmp ecx,eax + jbe L_contiguous_in_window + + add esi, [esp+52] + add esi,eax + sub esi,ecx + sub ecx,eax + + + mov eax, [esp+24] + cmp eax,ecx + jbe L_do_copy1 + + sub eax,ecx + rep movsb + mov esi, [esp+56] + mov ecx, [esp+48] + cmp eax,ecx + jbe L_do_copy1 + + sub eax,ecx + rep movsb + mov esi,edi + sub esi,edx + jmp L_do_copy1 + +L_contiguous_in_window: +; 836 "inffast.S" + add esi,eax + sub esi,ecx + + + mov eax, [esp+24] + cmp eax,ecx + jbe L_do_copy1 + + sub eax,ecx + rep movsb + mov esi,edi + sub esi,edx + +L_do_copy1: +; 862 "inffast.S" + mov ecx,eax + rep movsb + + mov esi, [esp+44] + jmp L_while_test +; 878 "inffast.S" +ALIGN 4 +L_init_mmx: + emms + + + + + + movd mm0,ebp + mov ebp,ebx +; 896 "inffast.S" + movd mm4,dword ptr [esp+0] + movq mm3,mm4 + movd mm5,dword ptr [esp+4] + movq mm2,mm5 + pxor mm1,mm1 + mov ebx, [esp+8] + jmp L_do_loop_mmx + +ALIGN 4 +L_do_loop_mmx: + psrlq mm0,mm1 + + cmp ebp,32 + ja L_get_length_code_mmx + + movd mm6,ebp + movd mm7,dword ptr [esi] + add esi,4 + psllq mm7,mm6 + add ebp,32 + por mm0,mm7 + +L_get_length_code_mmx: + pand mm4,mm0 + movd eax,mm4 + movq mm4,mm3 + mov eax, [ebx+eax*4] + +L_dolen_mmx: + movzx ecx,ah + movd mm1,ecx + sub ebp,ecx + + test al,al + jnz L_test_for_length_base_mmx + + shr eax,16 + stosb + +L_while_test_mmx: + + + cmp [esp+16],edi + jbe L_break_loop + + cmp [esp+20],esi + ja L_do_loop_mmx + jmp L_break_loop + +L_test_for_length_base_mmx: + + mov edx,eax + shr edx,16 + + test al,16 + jz L_test_for_second_level_length_mmx + and eax,15 + jz L_decode_distance_mmx + + psrlq mm0,mm1 + movd mm1,eax + movd ecx,mm0 + sub ebp,eax + and ecx, [inflate_fast_mask+eax*4] + add edx,ecx + +L_decode_distance_mmx: + psrlq mm0,mm1 + + cmp ebp,32 + ja L_get_dist_code_mmx + + movd mm6,ebp + movd mm7,dword ptr [esi] + add esi,4 + psllq mm7,mm6 + add ebp,32 + por mm0,mm7 + +L_get_dist_code_mmx: + mov ebx, [esp+12] + pand mm5,mm0 + movd eax,mm5 + movq mm5,mm2 + mov eax, [ebx+eax*4] + +L_dodist_mmx: + + movzx ecx,ah + mov ebx,eax + shr ebx,16 + sub ebp,ecx + movd mm1,ecx + + test al,16 + jz L_test_for_second_level_dist_mmx + and eax,15 + jz L_check_dist_one_mmx + +L_add_bits_to_dist_mmx: + psrlq mm0,mm1 + movd mm1,eax + movd ecx,mm0 + sub ebp,eax + and ecx, [inflate_fast_mask+eax*4] + add ebx,ecx + +L_check_window_mmx: + mov [esp+44],esi + mov eax,edi + sub eax, [esp+40] + + cmp eax,ebx + jb L_clip_window_mmx + + mov ecx,edx + mov esi,edi + sub esi,ebx + + sub ecx,3 + mov al, [esi] + mov [edi],al + mov al, [esi+1] + mov dl, [esi+2] + add esi,3 + mov [edi+1],al + mov [edi+2],dl + add edi,3 + rep movsb + + mov esi, [esp+44] + mov ebx, [esp+8] + jmp L_while_test_mmx + +ALIGN 4 +L_check_dist_one_mmx: + cmp ebx,1 + jne L_check_window_mmx + cmp [esp+40],edi + je L_check_window_mmx + + dec edi + mov ecx,edx + mov al, [edi] + sub ecx,3 + + mov [edi+1],al + mov [edi+2],al + mov [edi+3],al + add edi,4 + rep stosb + + mov ebx, [esp+8] + jmp L_while_test_mmx + +ALIGN 4 +L_test_for_second_level_length_mmx: + test al,64 + jnz L_test_for_end_of_block + + and eax,15 + psrlq mm0,mm1 + movd ecx,mm0 + and ecx, [inflate_fast_mask+eax*4] + add ecx,edx + mov eax, [ebx+ecx*4] + jmp L_dolen_mmx + +ALIGN 4 +L_test_for_second_level_dist_mmx: + test al,64 + jnz L_invalid_distance_code + + and eax,15 + psrlq mm0,mm1 + movd ecx,mm0 + and ecx, [inflate_fast_mask+eax*4] + mov eax, [esp+12] + add ecx,ebx + mov eax, [eax+ecx*4] + jmp L_dodist_mmx + +ALIGN 4 +L_clip_window_mmx: + + mov ecx,eax + mov eax, [esp+52] + neg ecx + mov esi, [esp+56] + + cmp eax,ebx + jb L_invalid_distance_too_far + + add ecx,ebx + cmp dword ptr [esp+48],0 + jne L_wrap_around_window_mmx + + sub eax,ecx + add esi,eax + + cmp edx,ecx + jbe L_do_copy1_mmx + + sub edx,ecx + rep movsb + mov esi,edi + sub esi,ebx + jmp L_do_copy1_mmx + + cmp edx,ecx + jbe L_do_copy1_mmx + + sub edx,ecx + rep movsb + mov esi,edi + sub esi,ebx + jmp L_do_copy1_mmx + +L_wrap_around_window_mmx: + + mov eax, [esp+48] + cmp ecx,eax + jbe L_contiguous_in_window_mmx + + add esi, [esp+52] + add esi,eax + sub esi,ecx + sub ecx,eax + + + cmp edx,ecx + jbe L_do_copy1_mmx + + sub edx,ecx + rep movsb + mov esi, [esp+56] + mov ecx, [esp+48] + cmp edx,ecx + jbe L_do_copy1_mmx + + sub edx,ecx + rep movsb + mov esi,edi + sub esi,ebx + jmp L_do_copy1_mmx + +L_contiguous_in_window_mmx: + + add esi,eax + sub esi,ecx + + + cmp edx,ecx + jbe L_do_copy1_mmx + + sub edx,ecx + rep movsb + mov esi,edi + sub esi,ebx + +L_do_copy1_mmx: + + + mov ecx,edx + rep movsb + + mov esi, [esp+44] + mov ebx, [esp+8] + jmp L_while_test_mmx +; 1174 "inffast.S" +L_invalid_distance_code: + + + + + + mov ecx, invalid_distance_code_msg + mov edx,INFLATE_MODE_BAD + jmp L_update_stream_state + +L_test_for_end_of_block: + + + + + + test al,32 + jz L_invalid_literal_length_code + + mov ecx,0 + mov edx,INFLATE_MODE_TYPE + jmp L_update_stream_state + +L_invalid_literal_length_code: + + + + + + mov ecx, invalid_literal_length_code_msg + mov edx,INFLATE_MODE_BAD + jmp L_update_stream_state + +L_invalid_distance_too_far: + + + + mov esi, [esp+44] + mov ecx, invalid_distance_too_far_msg + mov edx,INFLATE_MODE_BAD + jmp L_update_stream_state + +L_update_stream_state: + + mov eax, [esp+88] + test ecx,ecx + jz L_skip_msg + mov [eax+24],ecx +L_skip_msg: + mov eax, [eax+28] + mov [eax+mode_state],edx + jmp L_break_loop + +ALIGN 4 +L_break_loop: +; 1243 "inffast.S" + cmp dword ptr [inflate_fast_use_mmx],2 + jne L_update_next_in + + + + mov ebx,ebp + +L_update_next_in: +; 1266 "inffast.S" + mov eax, [esp+88] + mov ecx,ebx + mov edx, [eax+28] + shr ecx,3 + sub esi,ecx + shl ecx,3 + sub ebx,ecx + mov [eax+12],edi + mov [edx+bits_state],ebx + mov ecx,ebx + + lea ebx, [esp+28] + cmp [esp+20],ebx + jne L_buf_not_used + + sub esi,ebx + mov ebx, [eax+0] + mov [esp+20],ebx + add esi,ebx + mov ebx, [eax+4] + sub ebx,11 + add [esp+20],ebx + +L_buf_not_used: + mov [eax+0],esi + + mov ebx,1 + shl ebx,cl + dec ebx + + + + + + cmp dword ptr [inflate_fast_use_mmx],2 + jne L_update_hold + + + + psrlq mm0,mm1 + movd ebp,mm0 + + emms + +L_update_hold: + + + + and ebp,ebx + mov [edx+hold_state],ebp + + + + + mov ebx, [esp+20] + cmp ebx,esi + jbe L_last_is_smaller + + sub ebx,esi + add ebx,11 + mov [eax+4],ebx + jmp L_fixup_out +L_last_is_smaller: + sub esi,ebx + neg esi + add esi,11 + mov [eax+4],esi + + + + +L_fixup_out: + + mov ebx, [esp+16] + cmp ebx,edi + jbe L_end_is_smaller + + sub ebx,edi + add ebx,257 + mov [eax+16],ebx + jmp L_done +L_end_is_smaller: + sub edi,ebx + neg edi + add edi,257 + mov [eax+16],edi + + + + + +L_done: + add esp,64 + popfd + pop ebx + pop ebp + pop esi + pop edi + ret +_inflate_fast endp + +_TEXT ends +end diff --git a/dependencies/zlib-1.2.11/contrib/masmx86/match686.asm b/dependencies/zlib-1.2.11/contrib/masmx86/match686.asm new file mode 100644 index 0000000..3b09212 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/masmx86/match686.asm @@ -0,0 +1,479 @@ +; match686.asm -- Asm portion of the optimized longest_match for 32 bits x86 +; Copyright (C) 1995-1996 Jean-loup Gailly, Brian Raiter and Gilles Vollant. +; File written by Gilles Vollant, by converting match686.S from Brian Raiter +; for MASM. This is as assembly version of longest_match +; from Jean-loup Gailly in deflate.c +; +; http://www.zlib.net +; http://www.winimage.com/zLibDll +; http://www.muppetlabs.com/~breadbox/software/assembly.html +; +; For Visual C++ 4.x and higher and ML 6.x and higher +; ml.exe is distributed in +; http://www.microsoft.com/downloads/details.aspx?FamilyID=7a1c9da0-0510-44a2-b042-7ef370530c64 +; +; this file contain two implementation of longest_match +; +; this longest_match was written by Brian raiter (1998), optimized for Pentium Pro +; (and the faster known version of match_init on modern Core 2 Duo and AMD Phenom) +; +; for using an assembly version of longest_match, you need define ASMV in project +; +; compile the asm file running +; ml /coff /Zi /c /Flmatch686.lst match686.asm +; and do not include match686.obj in your project +; +; note: contrib of zLib 1.2.3 and earlier contained both a deprecated version for +; Pentium (prior Pentium Pro) and this version for Pentium Pro and modern processor +; with autoselect (with cpu detection code) +; if you want support the old pentium optimization, you can still use these version +; +; this file is not optimized for old pentium, but it compatible with all x86 32 bits +; processor (starting 80386) +; +; +; see below : zlib1222add must be adjuster if you use a zlib version < 1.2.2.2 + +;uInt longest_match(s, cur_match) +; deflate_state *s; +; IPos cur_match; /* current match */ + + NbStack equ 76 + cur_match equ dword ptr[esp+NbStack-0] + str_s equ dword ptr[esp+NbStack-4] +; 5 dword on top (ret,ebp,esi,edi,ebx) + adrret equ dword ptr[esp+NbStack-8] + pushebp equ dword ptr[esp+NbStack-12] + pushedi equ dword ptr[esp+NbStack-16] + pushesi equ dword ptr[esp+NbStack-20] + pushebx equ dword ptr[esp+NbStack-24] + + chain_length equ dword ptr [esp+NbStack-28] + limit equ dword ptr [esp+NbStack-32] + best_len equ dword ptr [esp+NbStack-36] + window equ dword ptr [esp+NbStack-40] + prev equ dword ptr [esp+NbStack-44] + scan_start equ word ptr [esp+NbStack-48] + wmask equ dword ptr [esp+NbStack-52] + match_start_ptr equ dword ptr [esp+NbStack-56] + nice_match equ dword ptr [esp+NbStack-60] + scan equ dword ptr [esp+NbStack-64] + + windowlen equ dword ptr [esp+NbStack-68] + match_start equ dword ptr [esp+NbStack-72] + strend equ dword ptr [esp+NbStack-76] + NbStackAdd equ (NbStack-24) + + .386p + + name gvmatch + .MODEL FLAT + + + +; all the +zlib1222add offsets are due to the addition of fields +; in zlib in the deflate_state structure since the asm code was first written +; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). +; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). +; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). + + zlib1222add equ 8 + +; Note : these value are good with a 8 bytes boundary pack structure + dep_chain_length equ 74h+zlib1222add + dep_window equ 30h+zlib1222add + dep_strstart equ 64h+zlib1222add + dep_prev_length equ 70h+zlib1222add + dep_nice_match equ 88h+zlib1222add + dep_w_size equ 24h+zlib1222add + dep_prev equ 38h+zlib1222add + dep_w_mask equ 2ch+zlib1222add + dep_good_match equ 84h+zlib1222add + dep_match_start equ 68h+zlib1222add + dep_lookahead equ 6ch+zlib1222add + + +_TEXT segment + +IFDEF NOUNDERLINE + public longest_match + public match_init +ELSE + public _longest_match + public _match_init +ENDIF + + MAX_MATCH equ 258 + MIN_MATCH equ 3 + MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1) + + + +MAX_MATCH equ 258 +MIN_MATCH equ 3 +MIN_LOOKAHEAD equ (MAX_MATCH + MIN_MATCH + 1) +MAX_MATCH_8_ equ ((MAX_MATCH + 7) AND 0FFF0h) + + +;;; stack frame offsets + +chainlenwmask equ esp + 0 ; high word: current chain len + ; low word: s->wmask +window equ esp + 4 ; local copy of s->window +windowbestlen equ esp + 8 ; s->window + bestlen +scanstart equ esp + 16 ; first two bytes of string +scanend equ esp + 12 ; last two bytes of string +scanalign equ esp + 20 ; dword-misalignment of string +nicematch equ esp + 24 ; a good enough match size +bestlen equ esp + 28 ; size of best match so far +scan equ esp + 32 ; ptr to string wanting match + +LocalVarsSize equ 36 +; saved ebx byte esp + 36 +; saved edi byte esp + 40 +; saved esi byte esp + 44 +; saved ebp byte esp + 48 +; return address byte esp + 52 +deflatestate equ esp + 56 ; the function arguments +curmatch equ esp + 60 + +;;; Offsets for fields in the deflate_state structure. These numbers +;;; are calculated from the definition of deflate_state, with the +;;; assumption that the compiler will dword-align the fields. (Thus, +;;; changing the definition of deflate_state could easily cause this +;;; program to crash horribly, without so much as a warning at +;;; compile time. Sigh.) + +dsWSize equ 36+zlib1222add +dsWMask equ 44+zlib1222add +dsWindow equ 48+zlib1222add +dsPrev equ 56+zlib1222add +dsMatchLen equ 88+zlib1222add +dsPrevMatch equ 92+zlib1222add +dsStrStart equ 100+zlib1222add +dsMatchStart equ 104+zlib1222add +dsLookahead equ 108+zlib1222add +dsPrevLen equ 112+zlib1222add +dsMaxChainLen equ 116+zlib1222add +dsGoodMatch equ 132+zlib1222add +dsNiceMatch equ 136+zlib1222add + + +;;; match686.asm -- Pentium-Pro-optimized version of longest_match() +;;; Written for zlib 1.1.2 +;;; Copyright (C) 1998 Brian Raiter +;;; You can look at http://www.muppetlabs.com/~breadbox/software/assembly.html +;;; +;; +;; This software is provided 'as-is', without any express or implied +;; warranty. In no event will the authors be held liable for any damages +;; arising from the use of this software. +;; +;; Permission is granted to anyone to use this software for any purpose, +;; including commercial applications, and to alter it and redistribute it +;; freely, subject to the following restrictions: +;; +;; 1. The origin of this software must not be misrepresented; you must not +;; claim that you wrote the original software. If you use this software +;; in a product, an acknowledgment in the product documentation would be +;; appreciated but is not required. +;; 2. Altered source versions must be plainly marked as such, and must not be +;; misrepresented as being the original software +;; 3. This notice may not be removed or altered from any source distribution. +;; + +;GLOBAL _longest_match, _match_init + + +;SECTION .text + +;;; uInt longest_match(deflate_state *deflatestate, IPos curmatch) + +;_longest_match: + IFDEF NOUNDERLINE + longest_match proc near + ELSE + _longest_match proc near + ENDIF +.FPO (9, 4, 0, 0, 1, 0) + +;;; Save registers that the compiler may be using, and adjust esp to +;;; make room for our stack frame. + + push ebp + push edi + push esi + push ebx + sub esp, LocalVarsSize + +;;; Retrieve the function arguments. ecx will hold cur_match +;;; throughout the entire function. edx will hold the pointer to the +;;; deflate_state structure during the function's setup (before +;;; entering the main loop. + + mov edx, [deflatestate] + mov ecx, [curmatch] + +;;; uInt wmask = s->w_mask; +;;; unsigned chain_length = s->max_chain_length; +;;; if (s->prev_length >= s->good_match) { +;;; chain_length >>= 2; +;;; } + + mov eax, [edx + dsPrevLen] + mov ebx, [edx + dsGoodMatch] + cmp eax, ebx + mov eax, [edx + dsWMask] + mov ebx, [edx + dsMaxChainLen] + jl LastMatchGood + shr ebx, 2 +LastMatchGood: + +;;; chainlen is decremented once beforehand so that the function can +;;; use the sign flag instead of the zero flag for the exit test. +;;; It is then shifted into the high word, to make room for the wmask +;;; value, which it will always accompany. + + dec ebx + shl ebx, 16 + or ebx, eax + mov [chainlenwmask], ebx + +;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + mov eax, [edx + dsNiceMatch] + mov ebx, [edx + dsLookahead] + cmp ebx, eax + jl LookaheadLess + mov ebx, eax +LookaheadLess: mov [nicematch], ebx + +;;; register Bytef *scan = s->window + s->strstart; + + mov esi, [edx + dsWindow] + mov [window], esi + mov ebp, [edx + dsStrStart] + lea edi, [esi + ebp] + mov [scan], edi + +;;; Determine how many bytes the scan ptr is off from being +;;; dword-aligned. + + mov eax, edi + neg eax + and eax, 3 + mov [scanalign], eax + +;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ? +;;; s->strstart - (IPos)MAX_DIST(s) : NIL; + + mov eax, [edx + dsWSize] + sub eax, MIN_LOOKAHEAD + sub ebp, eax + jg LimitPositive + xor ebp, ebp +LimitPositive: + +;;; int best_len = s->prev_length; + + mov eax, [edx + dsPrevLen] + mov [bestlen], eax + +;;; Store the sum of s->window + best_len in esi locally, and in esi. + + add esi, eax + mov [windowbestlen], esi + +;;; register ush scan_start = *(ushf*)scan; +;;; register ush scan_end = *(ushf*)(scan+best_len-1); +;;; Posf *prev = s->prev; + + movzx ebx, word ptr [edi] + mov [scanstart], ebx + movzx ebx, word ptr [edi + eax - 1] + mov [scanend], ebx + mov edi, [edx + dsPrev] + +;;; Jump into the main loop. + + mov edx, [chainlenwmask] + jmp short LoopEntry + +align 4 + +;;; do { +;;; match = s->window + cur_match; +;;; if (*(ushf*)(match+best_len-1) != scan_end || +;;; *(ushf*)match != scan_start) continue; +;;; [...] +;;; } while ((cur_match = prev[cur_match & wmask]) > limit +;;; && --chain_length != 0); +;;; +;;; Here is the inner loop of the function. The function will spend the +;;; majority of its time in this loop, and majority of that time will +;;; be spent in the first ten instructions. +;;; +;;; Within this loop: +;;; ebx = scanend +;;; ecx = curmatch +;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) +;;; esi = windowbestlen - i.e., (window + bestlen) +;;; edi = prev +;;; ebp = limit + +LookupLoop: + and ecx, edx + movzx ecx, word ptr [edi + ecx*2] + cmp ecx, ebp + jbe LeaveNow + sub edx, 00010000h + js LeaveNow +LoopEntry: movzx eax, word ptr [esi + ecx - 1] + cmp eax, ebx + jnz LookupLoop + mov eax, [window] + movzx eax, word ptr [eax + ecx] + cmp eax, [scanstart] + jnz LookupLoop + +;;; Store the current value of chainlen. + + mov [chainlenwmask], edx + +;;; Point edi to the string under scrutiny, and esi to the string we +;;; are hoping to match it up with. In actuality, esi and edi are +;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is +;;; initialized to -(MAX_MATCH_8 - scanalign). + + mov esi, [window] + mov edi, [scan] + add esi, ecx + mov eax, [scanalign] + mov edx, 0fffffef8h; -(MAX_MATCH_8) + lea edi, [edi + eax + 0108h] ;MAX_MATCH_8] + lea esi, [esi + eax + 0108h] ;MAX_MATCH_8] + +;;; Test the strings for equality, 8 bytes at a time. At the end, +;;; adjust edx so that it is offset to the exact byte that mismatched. +;;; +;;; We already know at this point that the first three bytes of the +;;; strings match each other, and they can be safely passed over before +;;; starting the compare loop. So what this code does is skip over 0-3 +;;; bytes, as much as necessary in order to dword-align the edi +;;; pointer. (esi will still be misaligned three times out of four.) +;;; +;;; It should be confessed that this loop usually does not represent +;;; much of the total running time. Replacing it with a more +;;; straightforward "rep cmpsb" would not drastically degrade +;;; performance. + +LoopCmps: + mov eax, [esi + edx] + xor eax, [edi + edx] + jnz LeaveLoopCmps + mov eax, [esi + edx + 4] + xor eax, [edi + edx + 4] + jnz LeaveLoopCmps4 + add edx, 8 + jnz LoopCmps + jmp short LenMaximum +LeaveLoopCmps4: add edx, 4 +LeaveLoopCmps: test eax, 0000FFFFh + jnz LenLower + add edx, 2 + shr eax, 16 +LenLower: sub al, 1 + adc edx, 0 + +;;; Calculate the length of the match. If it is longer than MAX_MATCH, +;;; then automatically accept it as the best possible match and leave. + + lea eax, [edi + edx] + mov edi, [scan] + sub eax, edi + cmp eax, MAX_MATCH + jge LenMaximum + +;;; If the length of the match is not longer than the best match we +;;; have so far, then forget it and return to the lookup loop. + + mov edx, [deflatestate] + mov ebx, [bestlen] + cmp eax, ebx + jg LongerMatch + mov esi, [windowbestlen] + mov edi, [edx + dsPrev] + mov ebx, [scanend] + mov edx, [chainlenwmask] + jmp LookupLoop + +;;; s->match_start = cur_match; +;;; best_len = len; +;;; if (len >= nice_match) break; +;;; scan_end = *(ushf*)(scan+best_len-1); + +LongerMatch: mov ebx, [nicematch] + mov [bestlen], eax + mov [edx + dsMatchStart], ecx + cmp eax, ebx + jge LeaveNow + mov esi, [window] + add esi, eax + mov [windowbestlen], esi + movzx ebx, word ptr [edi + eax - 1] + mov edi, [edx + dsPrev] + mov [scanend], ebx + mov edx, [chainlenwmask] + jmp LookupLoop + +;;; Accept the current string, with the maximum possible length. + +LenMaximum: mov edx, [deflatestate] + mov dword ptr [bestlen], MAX_MATCH + mov [edx + dsMatchStart], ecx + +;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len; +;;; return s->lookahead; + +LeaveNow: + mov edx, [deflatestate] + mov ebx, [bestlen] + mov eax, [edx + dsLookahead] + cmp ebx, eax + jg LookaheadRet + mov eax, ebx +LookaheadRet: + +;;; Restore the stack and return from whence we came. + + add esp, LocalVarsSize + pop ebx + pop esi + pop edi + pop ebp + + ret +; please don't remove this string ! +; Your can freely use match686 in any free or commercial app if you don't remove the string in the binary! + db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998",0dh,0ah + + + IFDEF NOUNDERLINE + longest_match endp + ELSE + _longest_match endp + ENDIF + + IFDEF NOUNDERLINE + match_init proc near + ret + match_init endp + ELSE + _match_init proc near + ret + _match_init endp + ENDIF + + +_TEXT ends +end diff --git a/dependencies/zlib-1.2.11/contrib/masmx86/readme.txt b/dependencies/zlib-1.2.11/contrib/masmx86/readme.txt new file mode 100644 index 0000000..3271f72 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/masmx86/readme.txt @@ -0,0 +1,27 @@ + +Summary +------- +This directory contains ASM implementations of the functions +longest_match() and inflate_fast(). + + +Use instructions +---------------- +Assemble using MASM, and copy the object files into the zlib source +directory, then run the appropriate makefile, as suggested below. You can +donwload MASM from here: + + http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=7a1c9da0-0510-44a2-b042-7ef370530c64 + +You can also get objects files here: + + http://www.winimage.com/zLibDll/zlib124_masm_obj.zip + +Build instructions +------------------ +* With Microsoft C and MASM: +nmake -f win32/Makefile.msc LOC="-DASMV -DASMINF" OBJA="match686.obj inffas32.obj" + +* With Borland C and TASM: +make -f win32/Makefile.bor LOCAL_ZLIB="-DASMV -DASMINF" OBJA="match686.obj inffas32.obj" OBJPA="+match686c.obj+match686.obj+inffas32.obj" + diff --git a/dependencies/zlib-1.2.11/contrib/minizip/Makefile b/dependencies/zlib-1.2.11/contrib/minizip/Makefile new file mode 100644 index 0000000..84eaad2 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/minizip/Makefile @@ -0,0 +1,25 @@ +CC=cc +CFLAGS=-O -I../.. + +UNZ_OBJS = miniunz.o unzip.o ioapi.o ../../libz.a +ZIP_OBJS = minizip.o zip.o ioapi.o ../../libz.a + +.c.o: + $(CC) -c $(CFLAGS) $*.c + +all: miniunz minizip + +miniunz: $(UNZ_OBJS) + $(CC) $(CFLAGS) -o $@ $(UNZ_OBJS) + +minizip: $(ZIP_OBJS) + $(CC) $(CFLAGS) -o $@ $(ZIP_OBJS) + +test: miniunz minizip + ./minizip test readme.txt + ./miniunz -l test.zip + mv readme.txt readme.old + ./miniunz test.zip + +clean: + /bin/rm -f *.o *~ minizip miniunz diff --git a/dependencies/zlib-1.2.11/contrib/minizip/Makefile.am b/dependencies/zlib-1.2.11/contrib/minizip/Makefile.am new file mode 100644 index 0000000..d343011 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/minizip/Makefile.am @@ -0,0 +1,45 @@ +lib_LTLIBRARIES = libminizip.la + +if COND_DEMOS +bin_PROGRAMS = miniunzip minizip +endif + +zlib_top_srcdir = $(top_srcdir)/../.. +zlib_top_builddir = $(top_builddir)/../.. + +AM_CPPFLAGS = -I$(zlib_top_srcdir) +AM_LDFLAGS = -L$(zlib_top_builddir) + +if WIN32 +iowin32_src = iowin32.c +iowin32_h = iowin32.h +endif + +libminizip_la_SOURCES = \ + ioapi.c \ + mztools.c \ + unzip.c \ + zip.c \ + ${iowin32_src} + +libminizip_la_LDFLAGS = $(AM_LDFLAGS) -version-info 1:0:0 -lz + +minizip_includedir = $(includedir)/minizip +minizip_include_HEADERS = \ + crypt.h \ + ioapi.h \ + mztools.h \ + unzip.h \ + zip.h \ + ${iowin32_h} + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = minizip.pc + +EXTRA_PROGRAMS = miniunzip minizip + +miniunzip_SOURCES = miniunz.c +miniunzip_LDADD = libminizip.la + +minizip_SOURCES = minizip.c +minizip_LDADD = libminizip.la -lz diff --git a/dependencies/zlib-1.2.11/contrib/minizip/MiniZip64_Changes.txt b/dependencies/zlib-1.2.11/contrib/minizip/MiniZip64_Changes.txt new file mode 100644 index 0000000..13a1bd9 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/minizip/MiniZip64_Changes.txt @@ -0,0 +1,6 @@ + +MiniZip 1.1 was derrived from MiniZip at version 1.01f + +Change in 1.0 (Okt 2009) + - **TODO - Add history** + diff --git a/dependencies/zlib-1.2.11/contrib/minizip/MiniZip64_info.txt b/dependencies/zlib-1.2.11/contrib/minizip/MiniZip64_info.txt new file mode 100644 index 0000000..57d7152 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/minizip/MiniZip64_info.txt @@ -0,0 +1,74 @@ +MiniZip - Copyright (c) 1998-2010 - by Gilles Vollant - version 1.1 64 bits from Mathias Svensson + +Introduction +--------------------- +MiniZip 1.1 is built from MiniZip 1.0 by Gilles Vollant ( http://www.winimage.com/zLibDll/minizip.html ) + +When adding ZIP64 support into minizip it would result into risk of breaking compatibility with minizip 1.0. +All possible work was done for compatibility. + + +Background +--------------------- +When adding ZIP64 support Mathias Svensson found that Even Rouault have added ZIP64 +support for unzip.c into minizip for a open source project called gdal ( http://www.gdal.org/ ) + +That was used as a starting point. And after that ZIP64 support was added to zip.c +some refactoring and code cleanup was also done. + + +Changed from MiniZip 1.0 to MiniZip 1.1 +--------------------------------------- +* Added ZIP64 support for unzip ( by Even Rouault ) +* Added ZIP64 support for zip ( by Mathias Svensson ) +* Reverted some changed that Even Rouault did. +* Bunch of patches received from Gulles Vollant that he received for MiniZip from various users. +* Added unzip patch for BZIP Compression method (patch create by Daniel Borca) +* Added BZIP Compress method for zip +* Did some refactoring and code cleanup + + +Credits + + Gilles Vollant - Original MiniZip author + Even Rouault - ZIP64 unzip Support + Daniel Borca - BZip Compression method support in unzip + Mathias Svensson - ZIP64 zip support + Mathias Svensson - BZip Compression method support in zip + + Resources + + ZipLayout http://result42.com/projects/ZipFileLayout + Command line tool for Windows that shows the layout and information of the headers in a zip archive. + Used when debugging and validating the creation of zip files using MiniZip64 + + + ZIP App Note http://www.pkware.com/documents/casestudies/APPNOTE.TXT + Zip File specification + + +Notes. + * To be able to use BZip compression method in zip64.c or unzip64.c the BZIP2 lib is needed and HAVE_BZIP2 need to be defined. + +License +---------------------------------------------------------- + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + +---------------------------------------------------------- + diff --git a/dependencies/zlib-1.2.11/contrib/minizip/configure.ac b/dependencies/zlib-1.2.11/contrib/minizip/configure.ac new file mode 100644 index 0000000..5b11970 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/minizip/configure.ac @@ -0,0 +1,32 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_INIT([minizip], [1.2.11], [bugzilla.redhat.com]) +AC_CONFIG_SRCDIR([minizip.c]) +AM_INIT_AUTOMAKE([foreign]) +LT_INIT + +AC_MSG_CHECKING([whether to build example programs]) +AC_ARG_ENABLE([demos], AC_HELP_STRING([--enable-demos], [build example programs])) +AM_CONDITIONAL([COND_DEMOS], [test "$enable_demos" = yes]) +if test "$enable_demos" = yes +then + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi + +case "${host}" in + *-mingw* | mingw*) + WIN32="yes" + ;; + *) + ;; +esac +AM_CONDITIONAL([WIN32], [test "${WIN32}" = "yes"]) + + +AC_SUBST([HAVE_UNISTD_H], [0]) +AC_CHECK_HEADER([unistd.h], [HAVE_UNISTD_H=1], []) +AC_CONFIG_FILES([Makefile minizip.pc]) +AC_OUTPUT diff --git a/dependencies/zlib-1.2.11/contrib/minizip/crypt.h b/dependencies/zlib-1.2.11/contrib/minizip/crypt.h new file mode 100644 index 0000000..1e9e820 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/minizip/crypt.h @@ -0,0 +1,131 @@ +/* crypt.h -- base code for crypt/uncrypt ZIPfile + + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This code is a modified version of crypting code in Infozip distribution + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + + If you don't need crypting in your application, just define symbols + NOCRYPT and NOUNCRYPT. + + This code support the "Traditional PKWARE Encryption". + + The new AES encryption added on Zip format by Winzip (see the page + http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong + Encryption is not supported. +*/ + +#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) + +/*********************************************************************** + * Return the next byte in the pseudo-random sequence + */ +static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab) +{ + unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an + * unpredictable manner on 16-bit systems; not a problem + * with any known compiler so far, though */ + + temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; + return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); +} + +/*********************************************************************** + * Update the encryption keys with the next byte of plain text + */ +static int update_keys(unsigned long* pkeys,const z_crc_t* pcrc_32_tab,int c) +{ + (*(pkeys+0)) = CRC32((*(pkeys+0)), c); + (*(pkeys+1)) += (*(pkeys+0)) & 0xff; + (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; + { + register int keyshift = (int)((*(pkeys+1)) >> 24); + (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); + } + return c; +} + + +/*********************************************************************** + * Initialize the encryption keys and the random header according to + * the given password. + */ +static void init_keys(const char* passwd,unsigned long* pkeys,const z_crc_t* pcrc_32_tab) +{ + *(pkeys+0) = 305419896L; + *(pkeys+1) = 591751049L; + *(pkeys+2) = 878082192L; + while (*passwd != '\0') { + update_keys(pkeys,pcrc_32_tab,(int)*passwd); + passwd++; + } +} + +#define zdecode(pkeys,pcrc_32_tab,c) \ + (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) + +#define zencode(pkeys,pcrc_32_tab,c,t) \ + (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) + +#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED + +#define RAND_HEAD_LEN 12 + /* "last resort" source for second part of crypt seed pattern */ +# ifndef ZCR_SEED2 +# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ +# endif + +static int crypthead(const char* passwd, /* password string */ + unsigned char* buf, /* where to write header */ + int bufSize, + unsigned long* pkeys, + const z_crc_t* pcrc_32_tab, + unsigned long crcForCrypting) +{ + int n; /* index in random header */ + int t; /* temporary */ + int c; /* random byte */ + unsigned char header[RAND_HEAD_LEN-2]; /* random header */ + static unsigned calls = 0; /* ensure different random header each time */ + + if (bufSize> 7) & 0xff; + header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); + } + /* Encrypt random header (last two bytes is high word of crc) */ + init_keys(passwd, pkeys, pcrc_32_tab); + for (n = 0; n < RAND_HEAD_LEN-2; n++) + { + buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); + } + buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); + buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); + return n; +} + +#endif diff --git a/dependencies/zlib-1.2.11/contrib/minizip/ioapi.c b/dependencies/zlib-1.2.11/contrib/minizip/ioapi.c new file mode 100644 index 0000000..7f5c191 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/minizip/ioapi.c @@ -0,0 +1,247 @@ +/* ioapi.h -- IO base function header for compress/uncompress .zip + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + +*/ + +#if defined(_WIN32) && (!(defined(_CRT_SECURE_NO_WARNINGS))) + #define _CRT_SECURE_NO_WARNINGS +#endif + +#if defined(__APPLE__) || defined(IOAPI_NO_64) +// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions +#define FOPEN_FUNC(filename, mode) fopen(filename, mode) +#define FTELLO_FUNC(stream) ftello(stream) +#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) +#else +#define FOPEN_FUNC(filename, mode) fopen64(filename, mode) +#define FTELLO_FUNC(stream) ftello64(stream) +#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin) +#endif + + +#include "ioapi.h" + +voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode) +{ + if (pfilefunc->zfile_func64.zopen64_file != NULL) + return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode); + else + { + return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode); + } +} + +long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin) +{ + if (pfilefunc->zfile_func64.zseek64_file != NULL) + return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin); + else + { + uLong offsetTruncated = (uLong)offset; + if (offsetTruncated != offset) + return -1; + else + return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin); + } +} + +ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream) +{ + if (pfilefunc->zfile_func64.zseek64_file != NULL) + return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream); + else + { + uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream); + if ((tell_uLong) == MAXU32) + return (ZPOS64_T)-1; + else + return tell_uLong; + } +} + +void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32) +{ + p_filefunc64_32->zfile_func64.zopen64_file = NULL; + p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file; + p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; + p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file; + p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file; + p_filefunc64_32->zfile_func64.ztell64_file = NULL; + p_filefunc64_32->zfile_func64.zseek64_file = NULL; + p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file; + p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; + p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque; + p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file; + p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file; +} + + + +static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode)); +static uLong ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +static uLong ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size)); +static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream)); +static long ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); +static int ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream)); +static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream)); + +static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode) +{ + FILE* file = NULL; + const char* mode_fopen = NULL; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + mode_fopen = "rb"; + else + if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + mode_fopen = "r+b"; + else + if (mode & ZLIB_FILEFUNC_MODE_CREATE) + mode_fopen = "wb"; + + if ((filename!=NULL) && (mode_fopen != NULL)) + file = fopen(filename, mode_fopen); + return file; +} + +static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode) +{ + FILE* file = NULL; + const char* mode_fopen = NULL; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + mode_fopen = "rb"; + else + if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + mode_fopen = "r+b"; + else + if (mode & ZLIB_FILEFUNC_MODE_CREATE) + mode_fopen = "wb"; + + if ((filename!=NULL) && (mode_fopen != NULL)) + file = FOPEN_FUNC((const char*)filename, mode_fopen); + return file; +} + + +static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size) +{ + uLong ret; + ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + +static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size) +{ + uLong ret; + ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + +static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream) +{ + long ret; + ret = ftell((FILE *)stream); + return ret; +} + + +static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream) +{ + ZPOS64_T ret; + ret = FTELLO_FUNC((FILE *)stream); + return ret; +} + +static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offset, int origin) +{ + int fseek_origin=0; + long ret; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + fseek_origin = SEEK_CUR; + break; + case ZLIB_FILEFUNC_SEEK_END : + fseek_origin = SEEK_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + fseek_origin = SEEK_SET; + break; + default: return -1; + } + ret = 0; + if (fseek((FILE *)stream, offset, fseek_origin) != 0) + ret = -1; + return ret; +} + +static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) +{ + int fseek_origin=0; + long ret; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + fseek_origin = SEEK_CUR; + break; + case ZLIB_FILEFUNC_SEEK_END : + fseek_origin = SEEK_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + fseek_origin = SEEK_SET; + break; + default: return -1; + } + ret = 0; + + if(FSEEKO_FUNC((FILE *)stream, offset, fseek_origin) != 0) + ret = -1; + + return ret; +} + + +static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream) +{ + int ret; + ret = fclose((FILE *)stream); + return ret; +} + +static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream) +{ + int ret; + ret = ferror((FILE *)stream); + return ret; +} + +void fill_fopen_filefunc (pzlib_filefunc_def) + zlib_filefunc_def* pzlib_filefunc_def; +{ + pzlib_filefunc_def->zopen_file = fopen_file_func; + pzlib_filefunc_def->zread_file = fread_file_func; + pzlib_filefunc_def->zwrite_file = fwrite_file_func; + pzlib_filefunc_def->ztell_file = ftell_file_func; + pzlib_filefunc_def->zseek_file = fseek_file_func; + pzlib_filefunc_def->zclose_file = fclose_file_func; + pzlib_filefunc_def->zerror_file = ferror_file_func; + pzlib_filefunc_def->opaque = NULL; +} + +void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen64_file = fopen64_file_func; + pzlib_filefunc_def->zread_file = fread_file_func; + pzlib_filefunc_def->zwrite_file = fwrite_file_func; + pzlib_filefunc_def->ztell64_file = ftell64_file_func; + pzlib_filefunc_def->zseek64_file = fseek64_file_func; + pzlib_filefunc_def->zclose_file = fclose_file_func; + pzlib_filefunc_def->zerror_file = ferror_file_func; + pzlib_filefunc_def->opaque = NULL; +} diff --git a/dependencies/zlib-1.2.11/contrib/minizip/ioapi.h b/dependencies/zlib-1.2.11/contrib/minizip/ioapi.h new file mode 100644 index 0000000..8dcbdb0 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/minizip/ioapi.h @@ -0,0 +1,208 @@ +/* ioapi.h -- IO base function header for compress/uncompress .zip + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + + Changes + + Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this) + Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux. + More if/def section may be needed to support other platforms + Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows. + (but you should use iowin32.c for windows instead) + +*/ + +#ifndef _ZLIBIOAPI64_H +#define _ZLIBIOAPI64_H + +#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) + + // Linux needs this to support file operation on files larger then 4+GB + // But might need better if/def to select just the platforms that needs them. + + #ifndef __USE_FILE_OFFSET64 + #define __USE_FILE_OFFSET64 + #endif + #ifndef __USE_LARGEFILE64 + #define __USE_LARGEFILE64 + #endif + #ifndef _LARGEFILE64_SOURCE + #define _LARGEFILE64_SOURCE + #endif + #ifndef _FILE_OFFSET_BIT + #define _FILE_OFFSET_BIT 64 + #endif + +#endif + +#include +#include +#include "zlib.h" + +#if defined(USE_FILE32API) +#define fopen64 fopen +#define ftello64 ftell +#define fseeko64 fseek +#else +#ifdef __FreeBSD__ +#define fopen64 fopen +#define ftello64 ftello +#define fseeko64 fseeko +#endif +#ifdef _MSC_VER + #define fopen64 fopen + #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC))) + #define ftello64 _ftelli64 + #define fseeko64 _fseeki64 + #else // old MSC + #define ftello64 ftell + #define fseeko64 fseek + #endif +#endif +#endif + +/* +#ifndef ZPOS64_T + #ifdef _WIN32 + #define ZPOS64_T fpos_t + #else + #include + #define ZPOS64_T uint64_t + #endif +#endif +*/ + +#ifdef HAVE_MINIZIP64_CONF_H +#include "mz64conf.h" +#endif + +/* a type choosen by DEFINE */ +#ifdef HAVE_64BIT_INT_CUSTOM +typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T; +#else +#ifdef HAS_STDINT_H +#include "stdint.h" +typedef uint64_t ZPOS64_T; +#else + +/* Maximum unsigned 32-bit value used as placeholder for zip64 */ +#define MAXU32 0xffffffff + +#if defined(_MSC_VER) || defined(__BORLANDC__) +typedef unsigned __int64 ZPOS64_T; +#else +typedef unsigned long long int ZPOS64_T; +#endif +#endif +#endif + + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define ZLIB_FILEFUNC_SEEK_CUR (1) +#define ZLIB_FILEFUNC_SEEK_END (2) +#define ZLIB_FILEFUNC_SEEK_SET (0) + +#define ZLIB_FILEFUNC_MODE_READ (1) +#define ZLIB_FILEFUNC_MODE_WRITE (2) +#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) + +#define ZLIB_FILEFUNC_MODE_EXISTING (4) +#define ZLIB_FILEFUNC_MODE_CREATE (8) + + +#ifndef ZCALLBACK + #if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) + #define ZCALLBACK CALLBACK + #else + #define ZCALLBACK + #endif +#endif + + + + +typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); +typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); +typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); +typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); + +typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); +typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); + + +/* here is the "old" 32 bits structure structure */ +typedef struct zlib_filefunc_def_s +{ + open_file_func zopen_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell_file_func ztell_file; + seek_file_func zseek_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + voidpf opaque; +} zlib_filefunc_def; + +typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream)); +typedef long (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); +typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, const void* filename, int mode)); + +typedef struct zlib_filefunc64_def_s +{ + open64_file_func zopen64_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell64_file_func ztell64_file; + seek64_file_func zseek64_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + voidpf opaque; +} zlib_filefunc64_def; + +void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def)); +void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); + +/* now internal definition, only for zip.c and unzip.h */ +typedef struct zlib_filefunc64_32_def_s +{ + zlib_filefunc64_def zfile_func64; + open_file_func zopen32_file; + tell_file_func ztell32_file; + seek_file_func zseek32_file; +} zlib_filefunc64_32_def; + + +#define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) +#define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) +//#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream)) +//#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode)) +#define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream)) +#define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream)) + +voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)); +long call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)); +ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)); + +void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32); + +#define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode))) +#define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream))) +#define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode))) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dependencies/zlib-1.2.11/contrib/minizip/iowin32.c b/dependencies/zlib-1.2.11/contrib/minizip/iowin32.c new file mode 100644 index 0000000..274f39e --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/minizip/iowin32.c @@ -0,0 +1,462 @@ +/* iowin32.c -- IO base function header for compress/uncompress .zip + Version 1.1, February 14h, 2010 + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + +*/ + +#include + +#include "zlib.h" +#include "ioapi.h" +#include "iowin32.h" + +#ifndef INVALID_HANDLE_VALUE +#define INVALID_HANDLE_VALUE (0xFFFFFFFF) +#endif + +#ifndef INVALID_SET_FILE_POINTER +#define INVALID_SET_FILE_POINTER ((DWORD)-1) +#endif + + +// see Include/shared/winapifamily.h in the Windows Kit +#if defined(WINAPI_FAMILY_PARTITION) && (!(defined(IOWIN32_USING_WINRT_API))) +#if WINAPI_FAMILY_ONE_PARTITION(WINAPI_FAMILY, WINAPI_PARTITION_APP) +#define IOWIN32_USING_WINRT_API 1 +#endif +#endif + +voidpf ZCALLBACK win32_open_file_func OF((voidpf opaque, const char* filename, int mode)); +uLong ZCALLBACK win32_read_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +uLong ZCALLBACK win32_write_file_func OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); +ZPOS64_T ZCALLBACK win32_tell64_file_func OF((voidpf opaque, voidpf stream)); +long ZCALLBACK win32_seek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); +int ZCALLBACK win32_close_file_func OF((voidpf opaque, voidpf stream)); +int ZCALLBACK win32_error_file_func OF((voidpf opaque, voidpf stream)); + +typedef struct +{ + HANDLE hf; + int error; +} WIN32FILE_IOWIN; + + +static void win32_translate_open_mode(int mode, + DWORD* lpdwDesiredAccess, + DWORD* lpdwCreationDisposition, + DWORD* lpdwShareMode, + DWORD* lpdwFlagsAndAttributes) +{ + *lpdwDesiredAccess = *lpdwShareMode = *lpdwFlagsAndAttributes = *lpdwCreationDisposition = 0; + + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + { + *lpdwDesiredAccess = GENERIC_READ; + *lpdwCreationDisposition = OPEN_EXISTING; + *lpdwShareMode = FILE_SHARE_READ; + } + else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + { + *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ; + *lpdwCreationDisposition = OPEN_EXISTING; + } + else if (mode & ZLIB_FILEFUNC_MODE_CREATE) + { + *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ; + *lpdwCreationDisposition = CREATE_ALWAYS; + } +} + +static voidpf win32_build_iowin(HANDLE hFile) +{ + voidpf ret=NULL; + + if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE)) + { + WIN32FILE_IOWIN w32fiow; + w32fiow.hf = hFile; + w32fiow.error = 0; + ret = malloc(sizeof(WIN32FILE_IOWIN)); + + if (ret==NULL) + CloseHandle(hFile); + else + *((WIN32FILE_IOWIN*)ret) = w32fiow; + } + return ret; +} + +voidpf ZCALLBACK win32_open64_file_func (voidpf opaque,const void* filename,int mode) +{ + const char* mode_fopen = NULL; + DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; + HANDLE hFile = NULL; + + win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); + +#ifdef IOWIN32_USING_WINRT_API +#ifdef UNICODE + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFile2((LPCTSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); +#else + if ((filename!=NULL) && (dwDesiredAccess != 0)) + { + WCHAR filenameW[FILENAME_MAX + 0x200 + 1]; + MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200); + hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); + } +#endif +#else + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); +#endif + + return win32_build_iowin(hFile); +} + + +voidpf ZCALLBACK win32_open64_file_funcA (voidpf opaque,const void* filename,int mode) +{ + const char* mode_fopen = NULL; + DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; + HANDLE hFile = NULL; + + win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); + +#ifdef IOWIN32_USING_WINRT_API + if ((filename!=NULL) && (dwDesiredAccess != 0)) + { + WCHAR filenameW[FILENAME_MAX + 0x200 + 1]; + MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200); + hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); + } +#else + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFileA((LPCSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); +#endif + + return win32_build_iowin(hFile); +} + + +voidpf ZCALLBACK win32_open64_file_funcW (voidpf opaque,const void* filename,int mode) +{ + const char* mode_fopen = NULL; + DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; + HANDLE hFile = NULL; + + win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); + +#ifdef IOWIN32_USING_WINRT_API + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFile2((LPCWSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition,NULL); +#else + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFileW((LPCWSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); +#endif + + return win32_build_iowin(hFile); +} + + +voidpf ZCALLBACK win32_open_file_func (voidpf opaque,const char* filename,int mode) +{ + const char* mode_fopen = NULL; + DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; + HANDLE hFile = NULL; + + win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); + +#ifdef IOWIN32_USING_WINRT_API +#ifdef UNICODE + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFile2((LPCTSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); +#else + if ((filename!=NULL) && (dwDesiredAccess != 0)) + { + WCHAR filenameW[FILENAME_MAX + 0x200 + 1]; + MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200); + hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); + } +#endif +#else + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); +#endif + + return win32_build_iowin(hFile); +} + + +uLong ZCALLBACK win32_read_file_func (voidpf opaque, voidpf stream, void* buf,uLong size) +{ + uLong ret=0; + HANDLE hFile = NULL; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + + if (hFile != NULL) + { + if (!ReadFile(hFile, buf, size, &ret, NULL)) + { + DWORD dwErr = GetLastError(); + if (dwErr == ERROR_HANDLE_EOF) + dwErr = 0; + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + } + } + + return ret; +} + + +uLong ZCALLBACK win32_write_file_func (voidpf opaque,voidpf stream,const void* buf,uLong size) +{ + uLong ret=0; + HANDLE hFile = NULL; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + + if (hFile != NULL) + { + if (!WriteFile(hFile, buf, size, &ret, NULL)) + { + DWORD dwErr = GetLastError(); + if (dwErr == ERROR_HANDLE_EOF) + dwErr = 0; + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + } + } + + return ret; +} + +static BOOL MySetFilePointerEx(HANDLE hFile, LARGE_INTEGER pos, LARGE_INTEGER *newPos, DWORD dwMoveMethod) +{ +#ifdef IOWIN32_USING_WINRT_API + return SetFilePointerEx(hFile, pos, newPos, dwMoveMethod); +#else + LONG lHigh = pos.HighPart; + DWORD dwNewPos = SetFilePointer(hFile, pos.LowPart, &lHigh, dwMoveMethod); + BOOL fOk = TRUE; + if (dwNewPos == 0xFFFFFFFF) + if (GetLastError() != NO_ERROR) + fOk = FALSE; + if ((newPos != NULL) && (fOk)) + { + newPos->LowPart = dwNewPos; + newPos->HighPart = lHigh; + } + return fOk; +#endif +} + +long ZCALLBACK win32_tell_file_func (voidpf opaque,voidpf stream) +{ + long ret=-1; + HANDLE hFile = NULL; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + if (hFile != NULL) + { + LARGE_INTEGER pos; + pos.QuadPart = 0; + + if (!MySetFilePointerEx(hFile, pos, &pos, FILE_CURRENT)) + { + DWORD dwErr = GetLastError(); + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + ret = -1; + } + else + ret=(long)pos.LowPart; + } + return ret; +} + +ZPOS64_T ZCALLBACK win32_tell64_file_func (voidpf opaque, voidpf stream) +{ + ZPOS64_T ret= (ZPOS64_T)-1; + HANDLE hFile = NULL; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream)->hf; + + if (hFile) + { + LARGE_INTEGER pos; + pos.QuadPart = 0; + + if (!MySetFilePointerEx(hFile, pos, &pos, FILE_CURRENT)) + { + DWORD dwErr = GetLastError(); + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + ret = (ZPOS64_T)-1; + } + else + ret=pos.QuadPart; + } + return ret; +} + + +long ZCALLBACK win32_seek_file_func (voidpf opaque,voidpf stream,uLong offset,int origin) +{ + DWORD dwMoveMethod=0xFFFFFFFF; + HANDLE hFile = NULL; + + long ret=-1; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + dwMoveMethod = FILE_CURRENT; + break; + case ZLIB_FILEFUNC_SEEK_END : + dwMoveMethod = FILE_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + dwMoveMethod = FILE_BEGIN; + break; + default: return -1; + } + + if (hFile != NULL) + { + LARGE_INTEGER pos; + pos.QuadPart = offset; + if (!MySetFilePointerEx(hFile, pos, NULL, dwMoveMethod)) + { + DWORD dwErr = GetLastError(); + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + ret = -1; + } + else + ret=0; + } + return ret; +} + +long ZCALLBACK win32_seek64_file_func (voidpf opaque, voidpf stream,ZPOS64_T offset,int origin) +{ + DWORD dwMoveMethod=0xFFFFFFFF; + HANDLE hFile = NULL; + long ret=-1; + + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream)->hf; + + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + dwMoveMethod = FILE_CURRENT; + break; + case ZLIB_FILEFUNC_SEEK_END : + dwMoveMethod = FILE_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + dwMoveMethod = FILE_BEGIN; + break; + default: return -1; + } + + if (hFile) + { + LARGE_INTEGER pos; + pos.QuadPart = offset; + if (!MySetFilePointerEx(hFile, pos, NULL, dwMoveMethod)) + { + DWORD dwErr = GetLastError(); + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + ret = -1; + } + else + ret=0; + } + return ret; +} + +int ZCALLBACK win32_close_file_func (voidpf opaque, voidpf stream) +{ + int ret=-1; + + if (stream!=NULL) + { + HANDLE hFile; + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + if (hFile != NULL) + { + CloseHandle(hFile); + ret=0; + } + free(stream); + } + return ret; +} + +int ZCALLBACK win32_error_file_func (voidpf opaque,voidpf stream) +{ + int ret=-1; + if (stream!=NULL) + { + ret = ((WIN32FILE_IOWIN*)stream) -> error; + } + return ret; +} + +void fill_win32_filefunc (zlib_filefunc_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen_file = win32_open_file_func; + pzlib_filefunc_def->zread_file = win32_read_file_func; + pzlib_filefunc_def->zwrite_file = win32_write_file_func; + pzlib_filefunc_def->ztell_file = win32_tell_file_func; + pzlib_filefunc_def->zseek_file = win32_seek_file_func; + pzlib_filefunc_def->zclose_file = win32_close_file_func; + pzlib_filefunc_def->zerror_file = win32_error_file_func; + pzlib_filefunc_def->opaque = NULL; +} + +void fill_win32_filefunc64(zlib_filefunc64_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen64_file = win32_open64_file_func; + pzlib_filefunc_def->zread_file = win32_read_file_func; + pzlib_filefunc_def->zwrite_file = win32_write_file_func; + pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; + pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; + pzlib_filefunc_def->zclose_file = win32_close_file_func; + pzlib_filefunc_def->zerror_file = win32_error_file_func; + pzlib_filefunc_def->opaque = NULL; +} + + +void fill_win32_filefunc64A(zlib_filefunc64_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen64_file = win32_open64_file_funcA; + pzlib_filefunc_def->zread_file = win32_read_file_func; + pzlib_filefunc_def->zwrite_file = win32_write_file_func; + pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; + pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; + pzlib_filefunc_def->zclose_file = win32_close_file_func; + pzlib_filefunc_def->zerror_file = win32_error_file_func; + pzlib_filefunc_def->opaque = NULL; +} + + +void fill_win32_filefunc64W(zlib_filefunc64_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen64_file = win32_open64_file_funcW; + pzlib_filefunc_def->zread_file = win32_read_file_func; + pzlib_filefunc_def->zwrite_file = win32_write_file_func; + pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; + pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; + pzlib_filefunc_def->zclose_file = win32_close_file_func; + pzlib_filefunc_def->zerror_file = win32_error_file_func; + pzlib_filefunc_def->opaque = NULL; +} diff --git a/dependencies/zlib-1.2.11/contrib/minizip/iowin32.h b/dependencies/zlib-1.2.11/contrib/minizip/iowin32.h new file mode 100644 index 0000000..0ca0969 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/minizip/iowin32.h @@ -0,0 +1,28 @@ +/* iowin32.h -- IO base function header for compress/uncompress .zip + Version 1.1, February 14h, 2010 + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + +*/ + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); +void fill_win32_filefunc64 OF((zlib_filefunc64_def* pzlib_filefunc_def)); +void fill_win32_filefunc64A OF((zlib_filefunc64_def* pzlib_filefunc_def)); +void fill_win32_filefunc64W OF((zlib_filefunc64_def* pzlib_filefunc_def)); + +#ifdef __cplusplus +} +#endif diff --git a/dependencies/zlib-1.2.11/contrib/minizip/make_vms.com b/dependencies/zlib-1.2.11/contrib/minizip/make_vms.com new file mode 100644 index 0000000..9ac13a9 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/minizip/make_vms.com @@ -0,0 +1,25 @@ +$ if f$search("ioapi.h_orig") .eqs. "" then copy ioapi.h ioapi.h_orig +$ open/write zdef vmsdefs.h +$ copy sys$input: zdef +$ deck +#define unix +#define fill_zlib_filefunc64_32_def_from_filefunc32 fillzffunc64from +#define Write_Zip64EndOfCentralDirectoryLocator Write_Zip64EoDLocator +#define Write_Zip64EndOfCentralDirectoryRecord Write_Zip64EoDRecord +#define Write_EndOfCentralDirectoryRecord Write_EoDRecord +$ eod +$ close zdef +$ copy vmsdefs.h,ioapi.h_orig ioapi.h +$ cc/include=[--]/prefix=all ioapi.c +$ cc/include=[--]/prefix=all miniunz.c +$ cc/include=[--]/prefix=all unzip.c +$ cc/include=[--]/prefix=all minizip.c +$ cc/include=[--]/prefix=all zip.c +$ link miniunz,unzip,ioapi,[--]libz.olb/lib +$ link minizip,zip,ioapi,[--]libz.olb/lib +$ mcr []minizip test minizip_info.txt +$ mcr []miniunz -l test.zip +$ rename minizip_info.txt; minizip_info.txt_old +$ mcr []miniunz test.zip +$ delete test.zip;* +$exit diff --git a/dependencies/zlib-1.2.11/contrib/minizip/miniunz.c b/dependencies/zlib-1.2.11/contrib/minizip/miniunz.c new file mode 100644 index 0000000..3d65401 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/minizip/miniunz.c @@ -0,0 +1,660 @@ +/* + miniunz.c + Version 1.1, February 14h, 2010 + sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications of Unzip for Zip64 + Copyright (C) 2007-2008 Even Rouault + + Modifications for Zip64 support on both zip and unzip + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) +*/ + +#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) + #ifndef __USE_FILE_OFFSET64 + #define __USE_FILE_OFFSET64 + #endif + #ifndef __USE_LARGEFILE64 + #define __USE_LARGEFILE64 + #endif + #ifndef _LARGEFILE64_SOURCE + #define _LARGEFILE64_SOURCE + #endif + #ifndef _FILE_OFFSET_BIT + #define _FILE_OFFSET_BIT 64 + #endif +#endif + +#ifdef __APPLE__ +// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions +#define FOPEN_FUNC(filename, mode) fopen(filename, mode) +#define FTELLO_FUNC(stream) ftello(stream) +#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) +#else +#define FOPEN_FUNC(filename, mode) fopen64(filename, mode) +#define FTELLO_FUNC(stream) ftello64(stream) +#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin) +#endif + + +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +# include +# include +#else +# include +# include +#endif + + +#include "unzip.h" + +#define CASESENSITIVITY (0) +#define WRITEBUFFERSIZE (8192) +#define MAXFILENAME (256) + +#ifdef _WIN32 +#define USEWIN32IOAPI +#include "iowin32.h" +#endif +/* + mini unzip, demo of unzip package + + usage : + Usage : miniunz [-exvlo] file.zip [file_to_extract] [-d extractdir] + + list the file in the zipfile, and print the content of FILE_ID.ZIP or README.TXT + if it exists +*/ + + +/* change_file_date : change the date/time of a file + filename : the filename of the file where date/time must be modified + dosdate : the new date at the MSDos format (4 bytes) + tmu_date : the SAME new date at the tm_unz format */ +void change_file_date(filename,dosdate,tmu_date) + const char *filename; + uLong dosdate; + tm_unz tmu_date; +{ +#ifdef _WIN32 + HANDLE hFile; + FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite; + + hFile = CreateFileA(filename,GENERIC_READ | GENERIC_WRITE, + 0,NULL,OPEN_EXISTING,0,NULL); + GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite); + DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal); + LocalFileTimeToFileTime(&ftLocal,&ftm); + SetFileTime(hFile,&ftm,&ftLastAcc,&ftm); + CloseHandle(hFile); +#else +#ifdef unix || __APPLE__ + struct utimbuf ut; + struct tm newdate; + newdate.tm_sec = tmu_date.tm_sec; + newdate.tm_min=tmu_date.tm_min; + newdate.tm_hour=tmu_date.tm_hour; + newdate.tm_mday=tmu_date.tm_mday; + newdate.tm_mon=tmu_date.tm_mon; + if (tmu_date.tm_year > 1900) + newdate.tm_year=tmu_date.tm_year - 1900; + else + newdate.tm_year=tmu_date.tm_year ; + newdate.tm_isdst=-1; + + ut.actime=ut.modtime=mktime(&newdate); + utime(filename,&ut); +#endif +#endif +} + + +/* mymkdir and change_file_date are not 100 % portable + As I don't know well Unix, I wait feedback for the unix portion */ + +int mymkdir(dirname) + const char* dirname; +{ + int ret=0; +#ifdef _WIN32 + ret = _mkdir(dirname); +#elif unix + ret = mkdir (dirname,0775); +#elif __APPLE__ + ret = mkdir (dirname,0775); +#endif + return ret; +} + +int makedir (newdir) + char *newdir; +{ + char *buffer ; + char *p; + int len = (int)strlen(newdir); + + if (len <= 0) + return 0; + + buffer = (char*)malloc(len+1); + if (buffer==NULL) + { + printf("Error allocating memory\n"); + return UNZ_INTERNALERROR; + } + strcpy(buffer,newdir); + + if (buffer[len-1] == '/') { + buffer[len-1] = '\0'; + } + if (mymkdir(buffer) == 0) + { + free(buffer); + return 1; + } + + p = buffer+1; + while (1) + { + char hold; + + while(*p && *p != '\\' && *p != '/') + p++; + hold = *p; + *p = 0; + if ((mymkdir(buffer) == -1) && (errno == ENOENT)) + { + printf("couldn't create directory %s\n",buffer); + free(buffer); + return 0; + } + if (hold == 0) + break; + *p++ = hold; + } + free(buffer); + return 1; +} + +void do_banner() +{ + printf("MiniUnz 1.01b, demo of zLib + Unz package written by Gilles Vollant\n"); + printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n"); +} + +void do_help() +{ + printf("Usage : miniunz [-e] [-x] [-v] [-l] [-o] [-p password] file.zip [file_to_extr.] [-d extractdir]\n\n" \ + " -e Extract without pathname (junk paths)\n" \ + " -x Extract with pathname\n" \ + " -v list files\n" \ + " -l list files\n" \ + " -d directory to extract into\n" \ + " -o overwrite files without prompting\n" \ + " -p extract crypted file using password\n\n"); +} + +void Display64BitsSize(ZPOS64_T n, int size_char) +{ + /* to avoid compatibility problem , we do here the conversion */ + char number[21]; + int offset=19; + int pos_string = 19; + number[20]=0; + for (;;) { + number[offset]=(char)((n%10)+'0'); + if (number[offset] != '0') + pos_string=offset; + n/=10; + if (offset==0) + break; + offset--; + } + { + int size_display_string = 19-pos_string; + while (size_char > size_display_string) + { + size_char--; + printf(" "); + } + } + + printf("%s",&number[pos_string]); +} + +int do_list(uf) + unzFile uf; +{ + uLong i; + unz_global_info64 gi; + int err; + + err = unzGetGlobalInfo64(uf,&gi); + if (err!=UNZ_OK) + printf("error %d with zipfile in unzGetGlobalInfo \n",err); + printf(" Length Method Size Ratio Date Time CRC-32 Name\n"); + printf(" ------ ------ ---- ----- ---- ---- ------ ----\n"); + for (i=0;i0) + ratio = (uLong)((file_info.compressed_size*100)/file_info.uncompressed_size); + + /* display a '*' if the file is crypted */ + if ((file_info.flag & 1) != 0) + charCrypt='*'; + + if (file_info.compression_method==0) + string_method="Stored"; + else + if (file_info.compression_method==Z_DEFLATED) + { + uInt iLevel=(uInt)((file_info.flag & 0x6)/2); + if (iLevel==0) + string_method="Defl:N"; + else if (iLevel==1) + string_method="Defl:X"; + else if ((iLevel==2) || (iLevel==3)) + string_method="Defl:F"; /* 2:fast , 3 : extra fast*/ + } + else + if (file_info.compression_method==Z_BZIP2ED) + { + string_method="BZip2 "; + } + else + string_method="Unkn. "; + + Display64BitsSize(file_info.uncompressed_size,7); + printf(" %6s%c",string_method,charCrypt); + Display64BitsSize(file_info.compressed_size,7); + printf(" %3lu%% %2.2lu-%2.2lu-%2.2lu %2.2lu:%2.2lu %8.8lx %s\n", + ratio, + (uLong)file_info.tmu_date.tm_mon + 1, + (uLong)file_info.tmu_date.tm_mday, + (uLong)file_info.tmu_date.tm_year % 100, + (uLong)file_info.tmu_date.tm_hour,(uLong)file_info.tmu_date.tm_min, + (uLong)file_info.crc,filename_inzip); + if ((i+1)='a') && (rep<='z')) + rep -= 0x20; + } + while ((rep!='Y') && (rep!='N') && (rep!='A')); + } + + if (rep == 'N') + skip = 1; + + if (rep == 'A') + *popt_overwrite=1; + } + + if ((skip==0) && (err==UNZ_OK)) + { + fout=FOPEN_FUNC(write_filename,"wb"); + /* some zipfile don't contain directory alone before file */ + if ((fout==NULL) && ((*popt_extract_without_path)==0) && + (filename_withoutpath!=(char*)filename_inzip)) + { + char c=*(filename_withoutpath-1); + *(filename_withoutpath-1)='\0'; + makedir(write_filename); + *(filename_withoutpath-1)=c; + fout=FOPEN_FUNC(write_filename,"wb"); + } + + if (fout==NULL) + { + printf("error opening %s\n",write_filename); + } + } + + if (fout!=NULL) + { + printf(" extracting: %s\n",write_filename); + + do + { + err = unzReadCurrentFile(uf,buf,size_buf); + if (err<0) + { + printf("error %d with zipfile in unzReadCurrentFile\n",err); + break; + } + if (err>0) + if (fwrite(buf,err,1,fout)!=1) + { + printf("error in writing extracted file\n"); + err=UNZ_ERRNO; + break; + } + } + while (err>0); + if (fout) + fclose(fout); + + if (err==0) + change_file_date(write_filename,file_info.dosDate, + file_info.tmu_date); + } + + if (err==UNZ_OK) + { + err = unzCloseCurrentFile (uf); + if (err!=UNZ_OK) + { + printf("error %d with zipfile in unzCloseCurrentFile\n",err); + } + } + else + unzCloseCurrentFile(uf); /* don't lose the error */ + } + + free(buf); + return err; +} + + +int do_extract(uf,opt_extract_without_path,opt_overwrite,password) + unzFile uf; + int opt_extract_without_path; + int opt_overwrite; + const char* password; +{ + uLong i; + unz_global_info64 gi; + int err; + FILE* fout=NULL; + + err = unzGetGlobalInfo64(uf,&gi); + if (err!=UNZ_OK) + printf("error %d with zipfile in unzGetGlobalInfo \n",err); + + for (i=0;i insert n+1 empty lines +.\" for manpage-specific macros, see man(7) +.SH NAME +miniunzip - uncompress and examine ZIP archives +.SH SYNOPSIS +.B miniunzip +.RI [ -exvlo ] +zipfile [ files_to_extract ] [-d tempdir] +.SH DESCRIPTION +.B minizip +is a simple tool which allows the extraction of compressed file +archives in the ZIP format used by the MS-DOS utility PKZIP. It was +written as a demonstration of the +.IR zlib (3) +library and therefore lack many of the features of the +.IR unzip (1) +program. +.SH OPTIONS +A number of options are supported. With the exception of +.BI \-d\ tempdir +these must be supplied before any +other arguments and are: +.TP +.BI \-l\ ,\ \-\-v +List the files in the archive without extracting them. +.TP +.B \-o +Overwrite files without prompting for confirmation. +.TP +.B \-x +Extract files (default). +.PP +The +.I zipfile +argument is the name of the archive to process. The next argument can be used +to specify a single file to extract from the archive. + +Lastly, the following option can be specified at the end of the command-line: +.TP +.BI \-d\ tempdir +Extract the archive in the directory +.I tempdir +rather than the current directory. +.SH SEE ALSO +.BR minizip (1), +.BR zlib (3), +.BR unzip (1). +.SH AUTHOR +This program was written by Gilles Vollant. This manual page was +written by Mark Brown . The -d tempdir option +was added by Dirk Eddelbuettel . diff --git a/dependencies/zlib-1.2.11/contrib/minizip/minizip.1 b/dependencies/zlib-1.2.11/contrib/minizip/minizip.1 new file mode 100644 index 0000000..1154484 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/minizip/minizip.1 @@ -0,0 +1,46 @@ +.\" Hey, EMACS: -*- nroff -*- +.TH minizip 1 "May 2, 2001" +.\" Please adjust this date whenever revising the manpage. +.\" +.\" Some roff macros, for reference: +.\" .nh disable hyphenation +.\" .hy enable hyphenation +.\" .ad l left justify +.\" .ad b justify to both left and right margins +.\" .nf disable filling +.\" .fi enable filling +.\" .br insert line break +.\" .sp insert n+1 empty lines +.\" for manpage-specific macros, see man(7) +.SH NAME +minizip - create ZIP archives +.SH SYNOPSIS +.B minizip +.RI [ -o ] +zipfile [ " files" ... ] +.SH DESCRIPTION +.B minizip +is a simple tool which allows the creation of compressed file archives +in the ZIP format used by the MS-DOS utility PKZIP. It was written as +a demonstration of the +.IR zlib (3) +library and therefore lack many of the features of the +.IR zip (1) +program. +.SH OPTIONS +The first argument supplied is the name of the ZIP archive to create or +.RI -o +in which case it is ignored and the second argument treated as the +name of the ZIP file. If the ZIP file already exists it will be +overwritten. +.PP +Subsequent arguments specify a list of files to place in the ZIP +archive. If none are specified then an empty archive will be created. +.SH SEE ALSO +.BR miniunzip (1), +.BR zlib (3), +.BR zip (1). +.SH AUTHOR +This program was written by Gilles Vollant. This manual page was +written by Mark Brown . + diff --git a/dependencies/zlib-1.2.11/contrib/minizip/minizip.c b/dependencies/zlib-1.2.11/contrib/minizip/minizip.c new file mode 100644 index 0000000..4288962 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/minizip/minizip.c @@ -0,0 +1,520 @@ +/* + minizip.c + Version 1.1, February 14h, 2010 + sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications of Unzip for Zip64 + Copyright (C) 2007-2008 Even Rouault + + Modifications for Zip64 support on both zip and unzip + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) +*/ + + +#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) + #ifndef __USE_FILE_OFFSET64 + #define __USE_FILE_OFFSET64 + #endif + #ifndef __USE_LARGEFILE64 + #define __USE_LARGEFILE64 + #endif + #ifndef _LARGEFILE64_SOURCE + #define _LARGEFILE64_SOURCE + #endif + #ifndef _FILE_OFFSET_BIT + #define _FILE_OFFSET_BIT 64 + #endif +#endif + +#ifdef __APPLE__ +// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions +#define FOPEN_FUNC(filename, mode) fopen(filename, mode) +#define FTELLO_FUNC(stream) ftello(stream) +#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) +#else +#define FOPEN_FUNC(filename, mode) fopen64(filename, mode) +#define FTELLO_FUNC(stream) ftello64(stream) +#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin) +#endif + + + +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +# include +# include +#else +# include +# include +# include +# include +#endif + +#include "zip.h" + +#ifdef _WIN32 + #define USEWIN32IOAPI + #include "iowin32.h" +#endif + + + +#define WRITEBUFFERSIZE (16384) +#define MAXFILENAME (256) + +#ifdef _WIN32 +uLong filetime(f, tmzip, dt) + char *f; /* name of file to get info on */ + tm_zip *tmzip; /* return value: access, modific. and creation times */ + uLong *dt; /* dostime */ +{ + int ret = 0; + { + FILETIME ftLocal; + HANDLE hFind; + WIN32_FIND_DATAA ff32; + + hFind = FindFirstFileA(f,&ff32); + if (hFind != INVALID_HANDLE_VALUE) + { + FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal); + FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0); + FindClose(hFind); + ret = 1; + } + } + return ret; +} +#else +#ifdef unix || __APPLE__ +uLong filetime(f, tmzip, dt) + char *f; /* name of file to get info on */ + tm_zip *tmzip; /* return value: access, modific. and creation times */ + uLong *dt; /* dostime */ +{ + int ret=0; + struct stat s; /* results of stat() */ + struct tm* filedate; + time_t tm_t=0; + + if (strcmp(f,"-")!=0) + { + char name[MAXFILENAME+1]; + int len = strlen(f); + if (len > MAXFILENAME) + len = MAXFILENAME; + + strncpy(name, f,MAXFILENAME-1); + /* strncpy doesnt append the trailing NULL, of the string is too long. */ + name[ MAXFILENAME ] = '\0'; + + if (name[len - 1] == '/') + name[len - 1] = '\0'; + /* not all systems allow stat'ing a file with / appended */ + if (stat(name,&s)==0) + { + tm_t = s.st_mtime; + ret = 1; + } + } + filedate = localtime(&tm_t); + + tmzip->tm_sec = filedate->tm_sec; + tmzip->tm_min = filedate->tm_min; + tmzip->tm_hour = filedate->tm_hour; + tmzip->tm_mday = filedate->tm_mday; + tmzip->tm_mon = filedate->tm_mon ; + tmzip->tm_year = filedate->tm_year; + + return ret; +} +#else +uLong filetime(f, tmzip, dt) + char *f; /* name of file to get info on */ + tm_zip *tmzip; /* return value: access, modific. and creation times */ + uLong *dt; /* dostime */ +{ + return 0; +} +#endif +#endif + + + + +int check_exist_file(filename) + const char* filename; +{ + FILE* ftestexist; + int ret = 1; + ftestexist = FOPEN_FUNC(filename,"rb"); + if (ftestexist==NULL) + ret = 0; + else + fclose(ftestexist); + return ret; +} + +void do_banner() +{ + printf("MiniZip 1.1, demo of zLib + MiniZip64 package, written by Gilles Vollant\n"); + printf("more info on MiniZip at http://www.winimage.com/zLibDll/minizip.html\n\n"); +} + +void do_help() +{ + printf("Usage : minizip [-o] [-a] [-0 to -9] [-p password] [-j] file.zip [files_to_add]\n\n" \ + " -o Overwrite existing file.zip\n" \ + " -a Append to existing file.zip\n" \ + " -0 Store only\n" \ + " -1 Compress faster\n" \ + " -9 Compress better\n\n" \ + " -j exclude path. store only the file name.\n\n"); +} + +/* calculate the CRC32 of a file, + because to encrypt a file, we need known the CRC32 of the file before */ +int getFileCrc(const char* filenameinzip,void*buf,unsigned long size_buf,unsigned long* result_crc) +{ + unsigned long calculate_crc=0; + int err=ZIP_OK; + FILE * fin = FOPEN_FUNC(filenameinzip,"rb"); + + unsigned long size_read = 0; + unsigned long total_read = 0; + if (fin==NULL) + { + err = ZIP_ERRNO; + } + + if (err == ZIP_OK) + do + { + err = ZIP_OK; + size_read = (int)fread(buf,1,size_buf,fin); + if (size_read < size_buf) + if (feof(fin)==0) + { + printf("error in reading %s\n",filenameinzip); + err = ZIP_ERRNO; + } + + if (size_read>0) + calculate_crc = crc32(calculate_crc,buf,size_read); + total_read += size_read; + + } while ((err == ZIP_OK) && (size_read>0)); + + if (fin) + fclose(fin); + + *result_crc=calculate_crc; + printf("file %s crc %lx\n", filenameinzip, calculate_crc); + return err; +} + +int isLargeFile(const char* filename) +{ + int largeFile = 0; + ZPOS64_T pos = 0; + FILE* pFile = FOPEN_FUNC(filename, "rb"); + + if(pFile != NULL) + { + int n = FSEEKO_FUNC(pFile, 0, SEEK_END); + pos = FTELLO_FUNC(pFile); + + printf("File : %s is %lld bytes\n", filename, pos); + + if(pos >= 0xffffffff) + largeFile = 1; + + fclose(pFile); + } + + return largeFile; +} + +int main(argc,argv) + int argc; + char *argv[]; +{ + int i; + int opt_overwrite=0; + int opt_compress_level=Z_DEFAULT_COMPRESSION; + int opt_exclude_path=0; + int zipfilenamearg = 0; + char filename_try[MAXFILENAME+16]; + int zipok; + int err=0; + int size_buf=0; + void* buf=NULL; + const char* password=NULL; + + + do_banner(); + if (argc==1) + { + do_help(); + return 0; + } + else + { + for (i=1;i='0') && (c<='9')) + opt_compress_level = c-'0'; + if ((c=='j') || (c=='J')) + opt_exclude_path = 1; + + if (((c=='p') || (c=='P')) && (i+1='a') && (rep<='z')) + rep -= 0x20; + } + while ((rep!='Y') && (rep!='N') && (rep!='A')); + if (rep=='N') + zipok = 0; + if (rep=='A') + opt_overwrite = 2; + } + } + + if (zipok==1) + { + zipFile zf; + int errclose; +# ifdef USEWIN32IOAPI + zlib_filefunc64_def ffunc; + fill_win32_filefunc64A(&ffunc); + zf = zipOpen2_64(filename_try,(opt_overwrite==2) ? 2 : 0,NULL,&ffunc); +# else + zf = zipOpen64(filename_try,(opt_overwrite==2) ? 2 : 0); +# endif + + if (zf == NULL) + { + printf("error opening %s\n",filename_try); + err= ZIP_ERRNO; + } + else + printf("creating %s\n",filename_try); + + for (i=zipfilenamearg+1;(i='0') || (argv[i][1]<='9'))) && + (strlen(argv[i]) == 2))) + { + FILE * fin; + int size_read; + const char* filenameinzip = argv[i]; + const char *savefilenameinzip; + zip_fileinfo zi; + unsigned long crcFile=0; + int zip64 = 0; + + zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour = + zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0; + zi.dosDate = 0; + zi.internal_fa = 0; + zi.external_fa = 0; + filetime(filenameinzip,&zi.tmz_date,&zi.dosDate); + +/* + err = zipOpenNewFileInZip(zf,filenameinzip,&zi, + NULL,0,NULL,0,NULL / * comment * /, + (opt_compress_level != 0) ? Z_DEFLATED : 0, + opt_compress_level); +*/ + if ((password != NULL) && (err==ZIP_OK)) + err = getFileCrc(filenameinzip,buf,size_buf,&crcFile); + + zip64 = isLargeFile(filenameinzip); + + /* The path name saved, should not include a leading slash. */ + /*if it did, windows/xp and dynazip couldn't read the zip file. */ + savefilenameinzip = filenameinzip; + while( savefilenameinzip[0] == '\\' || savefilenameinzip[0] == '/' ) + { + savefilenameinzip++; + } + + /*should the zip file contain any path at all?*/ + if( opt_exclude_path ) + { + const char *tmpptr; + const char *lastslash = 0; + for( tmpptr = savefilenameinzip; *tmpptr; tmpptr++) + { + if( *tmpptr == '\\' || *tmpptr == '/') + { + lastslash = tmpptr; + } + } + if( lastslash != NULL ) + { + savefilenameinzip = lastslash+1; // base filename follows last slash. + } + } + + /**/ + err = zipOpenNewFileInZip3_64(zf,savefilenameinzip,&zi, + NULL,0,NULL,0,NULL /* comment*/, + (opt_compress_level != 0) ? Z_DEFLATED : 0, + opt_compress_level,0, + /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */ + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + password,crcFile, zip64); + + if (err != ZIP_OK) + printf("error in opening %s in zipfile\n",filenameinzip); + else + { + fin = FOPEN_FUNC(filenameinzip,"rb"); + if (fin==NULL) + { + err=ZIP_ERRNO; + printf("error in opening %s for reading\n",filenameinzip); + } + } + + if (err == ZIP_OK) + do + { + err = ZIP_OK; + size_read = (int)fread(buf,1,size_buf,fin); + if (size_read < size_buf) + if (feof(fin)==0) + { + printf("error in reading %s\n",filenameinzip); + err = ZIP_ERRNO; + } + + if (size_read>0) + { + err = zipWriteInFileInZip (zf,buf,size_read); + if (err<0) + { + printf("error in writing %s in the zipfile\n", + filenameinzip); + } + + } + } while ((err == ZIP_OK) && (size_read>0)); + + if (fin) + fclose(fin); + + if (err<0) + err=ZIP_ERRNO; + else + { + err = zipCloseFileInZip(zf); + if (err!=ZIP_OK) + printf("error in closing %s in the zipfile\n", + filenameinzip); + } + } + } + errclose = zipClose(zf,NULL); + if (errclose != ZIP_OK) + printf("error in closing %s\n",filename_try); + } + else + { + do_help(); + } + + free(buf); + return 0; +} diff --git a/dependencies/zlib-1.2.11/contrib/minizip/minizip.pc.in b/dependencies/zlib-1.2.11/contrib/minizip/minizip.pc.in new file mode 100644 index 0000000..69b5b7f --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/minizip/minizip.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/minizip + +Name: minizip +Description: Minizip zip file manipulation library +Requires: +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lminizip +Libs.private: -lz +Cflags: -I${includedir} diff --git a/dependencies/zlib-1.2.11/contrib/minizip/mztools.c b/dependencies/zlib-1.2.11/contrib/minizip/mztools.c new file mode 100644 index 0000000..96891c2 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/minizip/mztools.c @@ -0,0 +1,291 @@ +/* + Additional tools for Minizip + Code: Xavier Roche '2004 + License: Same as ZLIB (www.gzip.org) +*/ + +/* Code */ +#include +#include +#include +#include "zlib.h" +#include "unzip.h" + +#define READ_8(adr) ((unsigned char)*(adr)) +#define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) ) +#define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) ) + +#define WRITE_8(buff, n) do { \ + *((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \ +} while(0) +#define WRITE_16(buff, n) do { \ + WRITE_8((unsigned char*)(buff), n); \ + WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \ +} while(0) +#define WRITE_32(buff, n) do { \ + WRITE_16((unsigned char*)(buff), (n) & 0xffff); \ + WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \ +} while(0) + +extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered) +const char* file; +const char* fileOut; +const char* fileOutTmp; +uLong* nRecovered; +uLong* bytesRecovered; +{ + int err = Z_OK; + FILE* fpZip = fopen(file, "rb"); + FILE* fpOut = fopen(fileOut, "wb"); + FILE* fpOutCD = fopen(fileOutTmp, "wb"); + if (fpZip != NULL && fpOut != NULL) { + int entries = 0; + uLong totalBytes = 0; + char header[30]; + char filename[1024]; + char extra[1024]; + int offset = 0; + int offsetCD = 0; + while ( fread(header, 1, 30, fpZip) == 30 ) { + int currentOffset = offset; + + /* File entry */ + if (READ_32(header) == 0x04034b50) { + unsigned int version = READ_16(header + 4); + unsigned int gpflag = READ_16(header + 6); + unsigned int method = READ_16(header + 8); + unsigned int filetime = READ_16(header + 10); + unsigned int filedate = READ_16(header + 12); + unsigned int crc = READ_32(header + 14); /* crc */ + unsigned int cpsize = READ_32(header + 18); /* compressed size */ + unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */ + unsigned int fnsize = READ_16(header + 26); /* file name length */ + unsigned int extsize = READ_16(header + 28); /* extra field length */ + filename[0] = extra[0] = '\0'; + + /* Header */ + if (fwrite(header, 1, 30, fpOut) == 30) { + offset += 30; + } else { + err = Z_ERRNO; + break; + } + + /* Filename */ + if (fnsize > 0) { + if (fnsize < sizeof(filename)) { + if (fread(filename, 1, fnsize, fpZip) == fnsize) { + if (fwrite(filename, 1, fnsize, fpOut) == fnsize) { + offset += fnsize; + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_STREAM_ERROR; + break; + } + + /* Extra field */ + if (extsize > 0) { + if (extsize < sizeof(extra)) { + if (fread(extra, 1, extsize, fpZip) == extsize) { + if (fwrite(extra, 1, extsize, fpOut) == extsize) { + offset += extsize; + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_ERRNO; + break; + } + } + + /* Data */ + { + int dataSize = cpsize; + if (dataSize == 0) { + dataSize = uncpsize; + } + if (dataSize > 0) { + char* data = malloc(dataSize); + if (data != NULL) { + if ((int)fread(data, 1, dataSize, fpZip) == dataSize) { + if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) { + offset += dataSize; + totalBytes += dataSize; + } else { + err = Z_ERRNO; + } + } else { + err = Z_ERRNO; + } + free(data); + if (err != Z_OK) { + break; + } + } else { + err = Z_MEM_ERROR; + break; + } + } + } + + /* Central directory entry */ + { + char header[46]; + char* comment = ""; + int comsize = (int) strlen(comment); + WRITE_32(header, 0x02014b50); + WRITE_16(header + 4, version); + WRITE_16(header + 6, version); + WRITE_16(header + 8, gpflag); + WRITE_16(header + 10, method); + WRITE_16(header + 12, filetime); + WRITE_16(header + 14, filedate); + WRITE_32(header + 16, crc); + WRITE_32(header + 20, cpsize); + WRITE_32(header + 24, uncpsize); + WRITE_16(header + 28, fnsize); + WRITE_16(header + 30, extsize); + WRITE_16(header + 32, comsize); + WRITE_16(header + 34, 0); /* disk # */ + WRITE_16(header + 36, 0); /* int attrb */ + WRITE_32(header + 38, 0); /* ext attrb */ + WRITE_32(header + 42, currentOffset); + /* Header */ + if (fwrite(header, 1, 46, fpOutCD) == 46) { + offsetCD += 46; + + /* Filename */ + if (fnsize > 0) { + if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) { + offsetCD += fnsize; + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_STREAM_ERROR; + break; + } + + /* Extra field */ + if (extsize > 0) { + if (fwrite(extra, 1, extsize, fpOutCD) == extsize) { + offsetCD += extsize; + } else { + err = Z_ERRNO; + break; + } + } + + /* Comment field */ + if (comsize > 0) { + if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) { + offsetCD += comsize; + } else { + err = Z_ERRNO; + break; + } + } + + + } else { + err = Z_ERRNO; + break; + } + } + + /* Success */ + entries++; + + } else { + break; + } + } + + /* Final central directory */ + { + int entriesZip = entries; + char header[22]; + char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools"; + int comsize = (int) strlen(comment); + if (entriesZip > 0xffff) { + entriesZip = 0xffff; + } + WRITE_32(header, 0x06054b50); + WRITE_16(header + 4, 0); /* disk # */ + WRITE_16(header + 6, 0); /* disk # */ + WRITE_16(header + 8, entriesZip); /* hack */ + WRITE_16(header + 10, entriesZip); /* hack */ + WRITE_32(header + 12, offsetCD); /* size of CD */ + WRITE_32(header + 16, offset); /* offset to CD */ + WRITE_16(header + 20, comsize); /* comment */ + + /* Header */ + if (fwrite(header, 1, 22, fpOutCD) == 22) { + + /* Comment field */ + if (comsize > 0) { + if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) { + err = Z_ERRNO; + } + } + + } else { + err = Z_ERRNO; + } + } + + /* Final merge (file + central directory) */ + fclose(fpOutCD); + if (err == Z_OK) { + fpOutCD = fopen(fileOutTmp, "rb"); + if (fpOutCD != NULL) { + int nRead; + char buffer[8192]; + while ( (nRead = (int)fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) { + if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) { + err = Z_ERRNO; + break; + } + } + fclose(fpOutCD); + } + } + + /* Close */ + fclose(fpZip); + fclose(fpOut); + + /* Wipe temporary file */ + (void)remove(fileOutTmp); + + /* Number of recovered entries */ + if (err == Z_OK) { + if (nRecovered != NULL) { + *nRecovered = entries; + } + if (bytesRecovered != NULL) { + *bytesRecovered = totalBytes; + } + } + } else { + err = Z_STREAM_ERROR; + } + return err; +} diff --git a/dependencies/zlib-1.2.11/contrib/minizip/mztools.h b/dependencies/zlib-1.2.11/contrib/minizip/mztools.h new file mode 100644 index 0000000..a49a426 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/minizip/mztools.h @@ -0,0 +1,37 @@ +/* + Additional tools for Minizip + Code: Xavier Roche '2004 + License: Same as ZLIB (www.gzip.org) +*/ + +#ifndef _zip_tools_H +#define _zip_tools_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#include "unzip.h" + +/* Repair a ZIP file (missing central directory) + file: file to recover + fileOut: output file after recovery + fileOutTmp: temporary file name used for recovery +*/ +extern int ZEXPORT unzRepair(const char* file, + const char* fileOut, + const char* fileOutTmp, + uLong* nRecovered, + uLong* bytesRecovered); + + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/dependencies/zlib-1.2.11/contrib/minizip/unzip.c b/dependencies/zlib-1.2.11/contrib/minizip/unzip.c new file mode 100644 index 0000000..bcfb941 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/minizip/unzip.c @@ -0,0 +1,2125 @@ +/* unzip.c -- IO for uncompress .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications of Unzip for Zip64 + Copyright (C) 2007-2008 Even Rouault + + Modifications for Zip64 support on both zip and unzip + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + + + ------------------------------------------------------------------------------------ + Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of + compatibility with older software. The following is from the original crypt.c. + Code woven in by Terry Thorsen 1/2003. + + Copyright (c) 1990-2000 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2000-Apr-09 or later + (the contents of which are also included in zip.h) for terms of use. + If, for some reason, all these files are missing, the Info-ZIP license + also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html + + crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + + ------------------------------------------------------------------------------------ + + Changes in unzip.c + + 2007-2008 - Even Rouault - Addition of cpl_unzGetCurrentFileZStreamPos + 2007-2008 - Even Rouault - Decoration of symbol names unz* -> cpl_unz* + 2007-2008 - Even Rouault - Remove old C style function prototypes + 2007-2008 - Even Rouault - Add unzip support for ZIP64 + + Copyright (C) 2007-2008 Even Rouault + + + Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again). + Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G + should only read the compressed/uncompressed size from the Zip64 format if + the size from normal header was 0xFFFFFFFF + Oct-2009 - Mathias Svensson - Applied some bug fixes from paches recived from Gilles Vollant + Oct-2009 - Mathias Svensson - Applied support to unzip files with compression mathod BZIP2 (bzip2 lib is required) + Patch created by Daniel Borca + + Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer + + Copyright (C) 1998 - 2010 Gilles Vollant, Even Rouault, Mathias Svensson + +*/ + + +#include +#include +#include + +#ifndef NOUNCRYPT + #define NOUNCRYPT +#endif + +#include "zlib.h" +#include "unzip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + + +#ifndef CASESENSITIVITYDEFAULT_NO +# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) +# define CASESENSITIVITYDEFAULT_NO +# endif +#endif + + +#ifndef UNZ_BUFSIZE +#define UNZ_BUFSIZE (16384) +#endif + +#ifndef UNZ_MAXFILENAMEINZIP +#define UNZ_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) + + +const char unz_copyright[] = + " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; + +/* unz_file_info_interntal contain internal info about a file in zipfile*/ +typedef struct unz_file_info64_internal_s +{ + ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */ +} unz_file_info64_internal; + + +/* file_in_zip_read_info_s contain internal information about a file in zipfile, + when reading and decompress it */ +typedef struct +{ + char *read_buffer; /* internal buffer for compressed data */ + z_stream stream; /* zLib stream structure for inflate */ + +#ifdef HAVE_BZIP2 + bz_stream bstream; /* bzLib stream structure for bziped */ +#endif + + ZPOS64_T pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ + uLong stream_initialised; /* flag set if stream structure is initialised*/ + + ZPOS64_T offset_local_extrafield;/* offset of the local extra field */ + uInt size_local_extrafield;/* size of the local extra field */ + ZPOS64_T pos_local_extrafield; /* position in the local extra field in read*/ + ZPOS64_T total_out_64; + + uLong crc32; /* crc32 of all data uncompressed */ + uLong crc32_wait; /* crc32 we must obtain after decompress all */ + ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */ + ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/ + zlib_filefunc64_32_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + uLong compression_method; /* compression method (0==store) */ + ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + int raw; +} file_in_zip64_read_info_s; + + +/* unz64_s contain internal information about the zipfile +*/ +typedef struct +{ + zlib_filefunc64_32_def z_filefunc; + int is64bitOpenFunction; + voidpf filestream; /* io structore of the zipfile */ + unz_global_info64 gi; /* public global information */ + ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + ZPOS64_T num_file; /* number of the current file in the zipfile*/ + ZPOS64_T pos_in_central_dir; /* pos of the current file in the central dir*/ + ZPOS64_T current_file_ok; /* flag about the usability of the current file*/ + ZPOS64_T central_pos; /* position of the beginning of the central dir*/ + + ZPOS64_T size_central_dir; /* size of the central directory */ + ZPOS64_T offset_central_dir; /* offset of start of central directory with + respect to the starting disk number */ + + unz_file_info64 cur_file_info; /* public info about the current file in zip*/ + unz_file_info64_internal cur_file_info_internal; /* private info about it*/ + file_in_zip64_read_info_s* pfile_in_zip_read; /* structure about the current + file if we are decompressing it */ + int encrypted; + + int isZip64; + +# ifndef NOUNCRYPT + unsigned long keys[3]; /* keys defining the pseudo-random sequence */ + const z_crc_t* pcrc_32_tab; +# endif +} unz64_s; + + +#ifndef NOUNCRYPT +#include "crypt.h" +#endif + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been successfully opened for reading. +*/ + + +local int unz64local_getByte OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + int *pi)); + +local int unz64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi) +{ + unsigned char c; + int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); + if (err==1) + { + *pi = (int)c; + return UNZ_OK; + } + else + { + if (ZERROR64(*pzlib_filefunc_def,filestream)) + return UNZ_ERRNO; + else + return UNZ_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int unz64local_getShort OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int unz64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX) +{ + uLong x ; + int i = 0; + int err; + + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((uLong)i)<<8; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unz64local_getLong OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int unz64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX) +{ + uLong x ; + int i = 0; + int err; + + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((uLong)i)<<8; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((uLong)i)<<16; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<24; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unz64local_getLong64 OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + ZPOS64_T *pX)); + + +local int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + ZPOS64_T *pX) +{ + ZPOS64_T x ; + int i = 0; + int err; + + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (ZPOS64_T)i; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<8; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<16; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<24; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<32; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<40; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<48; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<56; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +/* My own strcmpi / strcasecmp */ +local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2) +{ + for (;;) + { + char c1=*(fileName1++); + char c2=*(fileName2++); + if ((c1>='a') && (c1<='z')) + c1 -= 0x20; + if ((c2>='a') && (c2<='z')) + c2 -= 0x20; + if (c1=='\0') + return ((c2=='\0') ? 0 : -1); + if (c2=='\0') + return 1; + if (c1c2) + return 1; + } +} + + +#ifdef CASESENSITIVITYDEFAULT_NO +#define CASESENSITIVITYDEFAULTVALUE 2 +#else +#define CASESENSITIVITYDEFAULTVALUE 1 +#endif + +#ifndef STRCMPCASENOSENTIVEFUNCTION +#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal +#endif + +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) + +*/ +extern int ZEXPORT unzStringFileNameCompare (const char* fileName1, + const char* fileName2, + int iCaseSensitivity) + +{ + if (iCaseSensitivity==0) + iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; + + if (iCaseSensitivity==1) + return strcmp(fileName1,fileName2); + + return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); +} + +#ifndef BUFREADCOMMENT +#define BUFREADCOMMENT (0x400) +#endif + +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local ZPOS64_T unz64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); +local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) +{ + unsigned char* buf; + ZPOS64_T uSizeFile; + ZPOS64_T uBackRead; + ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ + ZPOS64_T uPosFound=0; + + if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); + if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} + + +/* + Locate the Central directory 64 of a zipfile (at the end, just before + the global comment) +*/ +local ZPOS64_T unz64local_SearchCentralDir64 OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream)); + +local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream) +{ + unsigned char* buf; + ZPOS64_T uSizeFile; + ZPOS64_T uBackRead; + ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ + ZPOS64_T uPosFound=0; + uLong uL; + ZPOS64_T relativeOffset; + + if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); + if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + if (uPosFound == 0) + return 0; + + /* Zip64 end of central directory locator */ + if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0) + return 0; + + /* the signature, already checked */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + + /* number of the disk with the start of the zip64 end of central directory */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + if (uL != 0) + return 0; + + /* relative offset of the zip64 end of central directory record */ + if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK) + return 0; + + /* total number of disks */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + if (uL != 1) + return 0; + + /* Goto end of central directory record */ + if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0) + return 0; + + /* the signature */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + + if (uL != 0x06064b50) + return 0; + + return relativeOffset; +} + +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer + "zlib/zlib114.zip". + If the zipfile cannot be opened (file doesn't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ +local unzFile unzOpenInternal (const void *path, + zlib_filefunc64_32_def* pzlib_filefunc64_32_def, + int is64bitOpenFunction) +{ + unz64_s us; + unz64_s *s; + ZPOS64_T central_pos; + uLong uL; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + ZPOS64_T number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + + int err=UNZ_OK; + + if (unz_copyright[0]!=' ') + return NULL; + + us.z_filefunc.zseek32_file = NULL; + us.z_filefunc.ztell32_file = NULL; + if (pzlib_filefunc64_32_def==NULL) + fill_fopen64_filefunc(&us.z_filefunc.zfile_func64); + else + us.z_filefunc = *pzlib_filefunc64_32_def; + us.is64bitOpenFunction = is64bitOpenFunction; + + + + us.filestream = ZOPEN64(us.z_filefunc, + path, + ZLIB_FILEFUNC_MODE_READ | + ZLIB_FILEFUNC_MODE_EXISTING); + if (us.filestream==NULL) + return NULL; + + central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream); + if (central_pos) + { + uLong uS; + ZPOS64_T uL64; + + us.isZip64 = 1; + + if (ZSEEK64(us.z_filefunc, us.filestream, + central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* size of zip64 end of central directory record */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&uL64)!=UNZ_OK) + err=UNZ_ERRNO; + + /* version made by */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK) + err=UNZ_ERRNO; + + /* version needed to extract */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central directory on this disk */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central directory */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((number_entry_CD!=us.gi.number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=UNZ_BADZIPFILE; + + /* size of the central directory */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + us.gi.size_comment = 0; + } + else + { + central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream); + if (central_pos==0) + err=UNZ_ERRNO; + + us.isZip64 = 0; + + if (ZSEEK64(us.z_filefunc, us.filestream, + central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir on this disk */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + us.gi.number_entry = uL; + + /* total number of entries in the central dir */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + number_entry_CD = uL; + + if ((number_entry_CD!=us.gi.number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=UNZ_BADZIPFILE; + + /* size of the central directory */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + us.size_central_dir = uL; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + us.offset_central_dir = uL; + + /* zipfile comment length */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) + err=UNZ_ERRNO; + } + + if ((central_pospfile_in_zip_read!=NULL) + unzCloseCurrentFile(file); + + ZCLOSE64(s->z_filefunc, s->filestream); + TRYFREE(s); + return UNZ_OK; +} + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ +extern int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_info) +{ + unz64_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + *pglobal_info=s->gi; + return UNZ_OK; +} + +extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info32) +{ + unz64_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + /* to do : check if number_entry is not truncated */ + pglobal_info32->number_entry = (uLong)s->gi.number_entry; + pglobal_info32->size_comment = s->gi.size_comment; + return UNZ_OK; +} +/* + Translate date/time from Dos format to tm_unz (readable more easilty) +*/ +local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm) +{ + ZPOS64_T uDate; + uDate = (ZPOS64_T)(ulDosDate>>16); + ptm->tm_mday = (uInt)(uDate&0x1f) ; + ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; + ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; + + ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); + ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; + ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; +} + +/* + Get Info about the current file in the zipfile, with internal only info +*/ +local int unz64local_GetCurrentFileInfoInternal OF((unzFile file, + unz_file_info64 *pfile_info, + unz_file_info64_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); + +local int unz64local_GetCurrentFileInfoInternal (unzFile file, + unz_file_info64 *pfile_info, + unz_file_info64_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize) +{ + unz64_s* s; + unz_file_info64 file_info; + unz_file_info64_internal file_info_internal; + int err=UNZ_OK; + uLong uMagic; + long lSeek=0; + uLong uL; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (ZSEEK64(s->z_filefunc, s->filestream, + s->pos_in_central_dir+s->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + + /* we check the magic */ + if (err==UNZ_OK) + { + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x02014b50) + err=UNZ_BADZIPFILE; + } + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK) + err=UNZ_ERRNO; + + unz64local_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + file_info.compressed_size = uL; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + file_info.uncompressed_size = uL; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) + err=UNZ_ERRNO; + + // relative offset of local header + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + file_info_internal.offset_curfile = uL; + + lSeek+=file_info.size_filename; + if ((err==UNZ_OK) && (szFileName!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_filename0) && (fileNameBufferSize>0)) + if (ZREAD64(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek -= uSizeRead; + } + + // Read extrafield + if ((err==UNZ_OK) && (extraField!=NULL)) + { + ZPOS64_T uSizeRead ; + if (file_info.size_file_extraz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + + if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) + if (ZREAD64(s->z_filefunc, s->filestream,extraField,(uLong)uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + + lSeek += file_info.size_file_extra - (uLong)uSizeRead; + } + else + lSeek += file_info.size_file_extra; + + + if ((err==UNZ_OK) && (file_info.size_file_extra != 0)) + { + uLong acc = 0; + + // since lSeek now points to after the extra field we need to move back + lSeek -= file_info.size_file_extra; + + if (lSeek!=0) + { + if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + + while(acc < file_info.size_file_extra) + { + uLong headerId; + uLong dataSize; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&headerId) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&dataSize) != UNZ_OK) + err=UNZ_ERRNO; + + /* ZIP64 extra fields */ + if (headerId == 0x0001) + { + uLong uL; + + if(file_info.uncompressed_size == MAXU32) + { + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) + err=UNZ_ERRNO; + } + + if(file_info.compressed_size == MAXU32) + { + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) + err=UNZ_ERRNO; + } + + if(file_info_internal.offset_curfile == MAXU32) + { + /* Relative Header offset */ + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) + err=UNZ_ERRNO; + } + + if(file_info.disk_num_start == MAXU32) + { + /* Disk Start Number */ + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + } + + } + else + { + if (ZSEEK64(s->z_filefunc, s->filestream,dataSize,ZLIB_FILEFUNC_SEEK_CUR)!=0) + err=UNZ_ERRNO; + } + + acc += 2 + 2 + dataSize; + } + } + + if ((err==UNZ_OK) && (szComment!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_commentz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + + if ((file_info.size_file_comment>0) && (commentBufferSize>0)) + if (ZREAD64(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek+=file_info.size_file_comment - uSizeRead; + } + else + lSeek+=file_info.size_file_comment; + + + if ((err==UNZ_OK) && (pfile_info!=NULL)) + *pfile_info=file_info; + + if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) + *pfile_info_internal=file_info_internal; + + return err; +} + + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. +*/ +extern int ZEXPORT unzGetCurrentFileInfo64 (unzFile file, + unz_file_info64 * pfile_info, + char * szFileName, uLong fileNameBufferSize, + void *extraField, uLong extraFieldBufferSize, + char* szComment, uLong commentBufferSize) +{ + return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); +} + +extern int ZEXPORT unzGetCurrentFileInfo (unzFile file, + unz_file_info * pfile_info, + char * szFileName, uLong fileNameBufferSize, + void *extraField, uLong extraFieldBufferSize, + char* szComment, uLong commentBufferSize) +{ + int err; + unz_file_info64 file_info64; + err = unz64local_GetCurrentFileInfoInternal(file,&file_info64,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); + if ((err==UNZ_OK) && (pfile_info != NULL)) + { + pfile_info->version = file_info64.version; + pfile_info->version_needed = file_info64.version_needed; + pfile_info->flag = file_info64.flag; + pfile_info->compression_method = file_info64.compression_method; + pfile_info->dosDate = file_info64.dosDate; + pfile_info->crc = file_info64.crc; + + pfile_info->size_filename = file_info64.size_filename; + pfile_info->size_file_extra = file_info64.size_file_extra; + pfile_info->size_file_comment = file_info64.size_file_comment; + + pfile_info->disk_num_start = file_info64.disk_num_start; + pfile_info->internal_fa = file_info64.internal_fa; + pfile_info->external_fa = file_info64.external_fa; + + pfile_info->tmu_date = file_info64.tmu_date, + + + pfile_info->compressed_size = (uLong)file_info64.compressed_size; + pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size; + + } + return err; +} +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ +extern int ZEXPORT unzGoToFirstFile (unzFile file) +{ + int err=UNZ_OK; + unz64_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + s->pos_in_central_dir=s->offset_central_dir; + s->num_file=0; + err=unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ +extern int ZEXPORT unzGoToNextFile (unzFile file) +{ + unz64_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */ + if (s->num_file+1==s->gi.number_entry) + return UNZ_END_OF_LIST_OF_FILE; + + s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; + s->num_file++; + err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ +extern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity) +{ + unz64_s* s; + int err; + + /* We remember the 'current' position in the file so that we can jump + * back there if we fail. + */ + unz_file_info64 cur_file_infoSaved; + unz_file_info64_internal cur_file_info_internalSaved; + ZPOS64_T num_fileSaved; + ZPOS64_T pos_in_central_dirSaved; + + + if (file==NULL) + return UNZ_PARAMERROR; + + if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) + return UNZ_PARAMERROR; + + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + /* Save the current state */ + num_fileSaved = s->num_file; + pos_in_central_dirSaved = s->pos_in_central_dir; + cur_file_infoSaved = s->cur_file_info; + cur_file_info_internalSaved = s->cur_file_info_internal; + + err = unzGoToFirstFile(file); + + while (err == UNZ_OK) + { + char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; + err = unzGetCurrentFileInfo64(file,NULL, + szCurrentFileName,sizeof(szCurrentFileName)-1, + NULL,0,NULL,0); + if (err == UNZ_OK) + { + if (unzStringFileNameCompare(szCurrentFileName, + szFileName,iCaseSensitivity)==0) + return UNZ_OK; + err = unzGoToNextFile(file); + } + } + + /* We failed, so restore the state of the 'current file' to where we + * were. + */ + s->num_file = num_fileSaved ; + s->pos_in_central_dir = pos_in_central_dirSaved ; + s->cur_file_info = cur_file_infoSaved; + s->cur_file_info_internal = cur_file_info_internalSaved; + return err; +} + + +/* +/////////////////////////////////////////// +// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net) +// I need random access +// +// Further optimization could be realized by adding an ability +// to cache the directory in memory. The goal being a single +// comprehensive file read to put the file I need in a memory. +*/ + +/* +typedef struct unz_file_pos_s +{ + ZPOS64_T pos_in_zip_directory; // offset in file + ZPOS64_T num_of_file; // # of file +} unz_file_pos; +*/ + +extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos) +{ + unz64_s* s; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + file_pos->pos_in_zip_directory = s->pos_in_central_dir; + file_pos->num_of_file = s->num_file; + + return UNZ_OK; +} + +extern int ZEXPORT unzGetFilePos( + unzFile file, + unz_file_pos* file_pos) +{ + unz64_file_pos file_pos64; + int err = unzGetFilePos64(file,&file_pos64); + if (err==UNZ_OK) + { + file_pos->pos_in_zip_directory = (uLong)file_pos64.pos_in_zip_directory; + file_pos->num_of_file = (uLong)file_pos64.num_of_file; + } + return err; +} + +extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos) +{ + unz64_s* s; + int err; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + + /* jump to the right spot */ + s->pos_in_central_dir = file_pos->pos_in_zip_directory; + s->num_file = file_pos->num_of_file; + + /* set the current file */ + err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + /* return results */ + s->current_file_ok = (err == UNZ_OK); + return err; +} + +extern int ZEXPORT unzGoToFilePos( + unzFile file, + unz_file_pos* file_pos) +{ + unz64_file_pos file_pos64; + if (file_pos == NULL) + return UNZ_PARAMERROR; + + file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory; + file_pos64.num_of_file = file_pos->num_of_file; + return unzGoToFilePos64(file,&file_pos64); +} + +/* +// Unzip Helper Functions - should be here? +/////////////////////////////////////////// +*/ + +/* + Read the local header of the current zipfile + Check the coherency of the local header and info in the end of central + directory about this file + store in *piSizeVar the size of extra info in local header + (filename and size of extra field data) +*/ +local int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVar, + ZPOS64_T * poffset_local_extrafield, + uInt * psize_local_extrafield) +{ + uLong uMagic,uData,uFlags; + uLong size_filename; + uLong size_extra_field; + int err=UNZ_OK; + + *piSizeVar = 0; + *poffset_local_extrafield = 0; + *psize_local_extrafield = 0; + + if (ZSEEK64(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile + + s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + + if (err==UNZ_OK) + { + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x04034b50) + err=UNZ_BADZIPFILE; + } + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; +/* + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) + err=UNZ_BADZIPFILE; +*/ + if (unz64local_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) + err=UNZ_BADZIPFILE; + + if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && +/* #ifdef HAVE_BZIP2 */ + (s->cur_file_info.compression_method!=Z_BZIP2ED) && +/* #endif */ + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */ + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */ + err=UNZ_ERRNO; + else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */ + err=UNZ_ERRNO; + else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) + err=UNZ_BADZIPFILE; + + *piSizeVar += (uInt)size_filename; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK) + err=UNZ_ERRNO; + *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + + SIZEZIPLOCALHEADER + size_filename; + *psize_local_extrafield = (uInt)size_extra_field; + + *piSizeVar += (uInt)size_extra_field; + + return err; +} + +/* + Open for reading data the current file in the zipfile. + If there is no error and the file is opened, the return value is UNZ_OK. +*/ +extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method, + int* level, int raw, const char* password) +{ + int err=UNZ_OK; + uInt iSizeVar; + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + ZPOS64_T offset_local_extrafield; /* offset of the local extra field */ + uInt size_local_extrafield; /* size of the local extra field */ +# ifndef NOUNCRYPT + char source[12]; +# else + if (password != NULL) + return UNZ_PARAMERROR; +# endif + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_PARAMERROR; + + if (s->pfile_in_zip_read != NULL) + unzCloseCurrentFile(file); + + if (unz64local_CheckCurrentFileCoherencyHeader(s,&iSizeVar, &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) + return UNZ_BADZIPFILE; + + pfile_in_zip_read_info = (file_in_zip64_read_info_s*)ALLOC(sizeof(file_in_zip64_read_info_s)); + if (pfile_in_zip_read_info==NULL) + return UNZ_INTERNALERROR; + + pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); + pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; + pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; + pfile_in_zip_read_info->pos_local_extrafield=0; + pfile_in_zip_read_info->raw=raw; + + if (pfile_in_zip_read_info->read_buffer==NULL) + { + TRYFREE(pfile_in_zip_read_info); + return UNZ_INTERNALERROR; + } + + pfile_in_zip_read_info->stream_initialised=0; + + if (method!=NULL) + *method = (int)s->cur_file_info.compression_method; + + if (level!=NULL) + { + *level = 6; + switch (s->cur_file_info.flag & 0x06) + { + case 6 : *level = 1; break; + case 4 : *level = 2; break; + case 2 : *level = 9; break; + } + } + + if ((s->cur_file_info.compression_method!=0) && +/* #ifdef HAVE_BZIP2 */ + (s->cur_file_info.compression_method!=Z_BZIP2ED) && +/* #endif */ + (s->cur_file_info.compression_method!=Z_DEFLATED)) + + err=UNZ_BADZIPFILE; + + pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; + pfile_in_zip_read_info->crc32=0; + pfile_in_zip_read_info->total_out_64=0; + pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method; + pfile_in_zip_read_info->filestream=s->filestream; + pfile_in_zip_read_info->z_filefunc=s->z_filefunc; + pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; + + pfile_in_zip_read_info->stream.total_out = 0; + + if ((s->cur_file_info.compression_method==Z_BZIP2ED) && (!raw)) + { +#ifdef HAVE_BZIP2 + pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0; + pfile_in_zip_read_info->bstream.bzfree = (free_func)0; + pfile_in_zip_read_info->bstream.opaque = (voidpf)0; + pfile_in_zip_read_info->bstream.state = (voidpf)0; + + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + pfile_in_zip_read_info->stream.next_in = (voidpf)0; + pfile_in_zip_read_info->stream.avail_in = 0; + + err=BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED; + else + { + TRYFREE(pfile_in_zip_read_info); + return err; + } +#else + pfile_in_zip_read_info->raw=1; +#endif + } + else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw)) + { + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + pfile_in_zip_read_info->stream.next_in = 0; + pfile_in_zip_read_info->stream.avail_in = 0; + + err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=Z_DEFLATED; + else + { + TRYFREE(pfile_in_zip_read_info); + return err; + } + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. + * In unzip, i don't wait absolutely Z_STREAM_END because I known the + * size of both compressed and uncompressed data + */ + } + pfile_in_zip_read_info->rest_read_compressed = + s->cur_file_info.compressed_size ; + pfile_in_zip_read_info->rest_read_uncompressed = + s->cur_file_info.uncompressed_size ; + + + pfile_in_zip_read_info->pos_in_zipfile = + s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + + iSizeVar; + + pfile_in_zip_read_info->stream.avail_in = (uInt)0; + + s->pfile_in_zip_read = pfile_in_zip_read_info; + s->encrypted = 0; + +# ifndef NOUNCRYPT + if (password != NULL) + { + int i; + s->pcrc_32_tab = get_crc_table(); + init_keys(password,s->keys,s->pcrc_32_tab); + if (ZSEEK64(s->z_filefunc, s->filestream, + s->pfile_in_zip_read->pos_in_zipfile + + s->pfile_in_zip_read->byte_before_the_zipfile, + SEEK_SET)!=0) + return UNZ_INTERNALERROR; + if(ZREAD64(s->z_filefunc, s->filestream,source, 12)<12) + return UNZ_INTERNALERROR; + + for (i = 0; i<12; i++) + zdecode(s->keys,s->pcrc_32_tab,source[i]); + + s->pfile_in_zip_read->pos_in_zipfile+=12; + s->encrypted=1; + } +# endif + + + return UNZ_OK; +} + +extern int ZEXPORT unzOpenCurrentFile (unzFile file) +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); +} + +extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, const char* password) +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, password); +} + +extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, int* method, int* level, int raw) +{ + return unzOpenCurrentFile3(file, method, level, raw, NULL); +} + +/** Addition for GDAL : START */ + +extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + s=(unz64_s*)file; + if (file==NULL) + return 0; //UNZ_PARAMERROR; + pfile_in_zip_read_info=s->pfile_in_zip_read; + if (pfile_in_zip_read_info==NULL) + return 0; //UNZ_PARAMERROR; + return pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile; +} + +/** Addition for GDAL : END */ + +/* + Read bytes from the current file. + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ +extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len) +{ + int err=UNZ_OK; + uInt iRead = 0; + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if (pfile_in_zip_read_info->read_buffer == NULL) + return UNZ_END_OF_LIST_OF_FILE; + if (len==0) + return 0; + + pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; + + pfile_in_zip_read_info->stream.avail_out = (uInt)len; + + if ((len>pfile_in_zip_read_info->rest_read_uncompressed) && + (!(pfile_in_zip_read_info->raw))) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_uncompressed; + + if ((len>pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in) && + (pfile_in_zip_read_info->raw)) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in; + + while (pfile_in_zip_read_info->stream.avail_out>0) + { + if ((pfile_in_zip_read_info->stream.avail_in==0) && + (pfile_in_zip_read_info->rest_read_compressed>0)) + { + uInt uReadThis = UNZ_BUFSIZE; + if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; + if (uReadThis == 0) + return UNZ_EOF; + if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + if (ZREAD64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->read_buffer, + uReadThis)!=uReadThis) + return UNZ_ERRNO; + + +# ifndef NOUNCRYPT + if(s->encrypted) + { + uInt i; + for(i=0;iread_buffer[i] = + zdecode(s->keys,s->pcrc_32_tab, + pfile_in_zip_read_info->read_buffer[i]); + } +# endif + + + pfile_in_zip_read_info->pos_in_zipfile += uReadThis; + + pfile_in_zip_read_info->rest_read_compressed-=uReadThis; + + pfile_in_zip_read_info->stream.next_in = + (Bytef*)pfile_in_zip_read_info->read_buffer; + pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; + } + + if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) + { + uInt uDoCopy,i ; + + if ((pfile_in_zip_read_info->stream.avail_in == 0) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + return (iRead==0) ? UNZ_EOF : iRead; + + if (pfile_in_zip_read_info->stream.avail_out < + pfile_in_zip_read_info->stream.avail_in) + uDoCopy = pfile_in_zip_read_info->stream.avail_out ; + else + uDoCopy = pfile_in_zip_read_info->stream.avail_in ; + + for (i=0;istream.next_out+i) = + *(pfile_in_zip_read_info->stream.next_in+i); + + pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uDoCopy; + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, + pfile_in_zip_read_info->stream.next_out, + uDoCopy); + pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; + pfile_in_zip_read_info->stream.avail_in -= uDoCopy; + pfile_in_zip_read_info->stream.avail_out -= uDoCopy; + pfile_in_zip_read_info->stream.next_out += uDoCopy; + pfile_in_zip_read_info->stream.next_in += uDoCopy; + pfile_in_zip_read_info->stream.total_out += uDoCopy; + iRead += uDoCopy; + } + else if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED) + { +#ifdef HAVE_BZIP2 + uLong uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + uLong uOutThis; + + pfile_in_zip_read_info->bstream.next_in = (char*)pfile_in_zip_read_info->stream.next_in; + pfile_in_zip_read_info->bstream.avail_in = pfile_in_zip_read_info->stream.avail_in; + pfile_in_zip_read_info->bstream.total_in_lo32 = pfile_in_zip_read_info->stream.total_in; + pfile_in_zip_read_info->bstream.total_in_hi32 = 0; + pfile_in_zip_read_info->bstream.next_out = (char*)pfile_in_zip_read_info->stream.next_out; + pfile_in_zip_read_info->bstream.avail_out = pfile_in_zip_read_info->stream.avail_out; + pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out; + pfile_in_zip_read_info->bstream.total_out_hi32 = 0; + + uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32; + bufBefore = (const Bytef *)pfile_in_zip_read_info->bstream.next_out; + + err=BZ2_bzDecompress(&pfile_in_zip_read_info->bstream); + + uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis; + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis)); + pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis; + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + pfile_in_zip_read_info->stream.next_in = (Bytef*)pfile_in_zip_read_info->bstream.next_in; + pfile_in_zip_read_info->stream.avail_in = pfile_in_zip_read_info->bstream.avail_in; + pfile_in_zip_read_info->stream.total_in = pfile_in_zip_read_info->bstream.total_in_lo32; + pfile_in_zip_read_info->stream.next_out = (Bytef*)pfile_in_zip_read_info->bstream.next_out; + pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out; + pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32; + + if (err==BZ_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=BZ_OK) + break; +#endif + } // end Z_BZIP2ED + else + { + ZPOS64_T uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + ZPOS64_T uOutThis; + int flush=Z_SYNC_FLUSH; + + uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; + bufBefore = pfile_in_zip_read_info->stream.next_out; + + /* + if ((pfile_in_zip_read_info->rest_read_uncompressed == + pfile_in_zip_read_info->stream.avail_out) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + flush = Z_FINISH; + */ + err=inflate(&pfile_in_zip_read_info->stream,flush); + + if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL)) + err = Z_DATA_ERROR; + + uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis; + + pfile_in_zip_read_info->crc32 = + crc32(pfile_in_zip_read_info->crc32,bufBefore, + (uInt)(uOutThis)); + + pfile_in_zip_read_info->rest_read_uncompressed -= + uOutThis; + + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + if (err==Z_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=Z_OK) + break; + } + } + + if (err==Z_OK) + return iRead; + return err; +} + + +/* + Give the current position in uncompressed data +*/ +extern z_off_t ZEXPORT unztell (unzFile file) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + return (z_off_t)pfile_in_zip_read_info->stream.total_out; +} + +extern ZPOS64_T ZEXPORT unztell64 (unzFile file) +{ + + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return (ZPOS64_T)-1; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return (ZPOS64_T)-1; + + return pfile_in_zip_read_info->total_out_64; +} + + +/* + return 1 if the end of file was reached, 0 elsewhere +*/ +extern int ZEXPORT unzeof (unzFile file) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + return 1; + else + return 0; +} + + + +/* +Read extra field from the current file (opened by unzOpenCurrentFile) +This is the local-header version of the extra field (sometimes, there is +more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field that can be read + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ +extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + uInt read_now; + ZPOS64_T size_to_read; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + size_to_read = (pfile_in_zip_read_info->size_local_extrafield - + pfile_in_zip_read_info->pos_local_extrafield); + + if (buf==NULL) + return (int)size_to_read; + + if (len>size_to_read) + read_now = (uInt)size_to_read; + else + read_now = (uInt)len ; + + if (read_now==0) + return 0; + + if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->offset_local_extrafield + + pfile_in_zip_read_info->pos_local_extrafield, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (ZREAD64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + buf,read_now)!=read_now) + return UNZ_ERRNO; + + return (int)read_now; +} + +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ +extern int ZEXPORT unzCloseCurrentFile (unzFile file) +{ + int err=UNZ_OK; + + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && + (!pfile_in_zip_read_info->raw)) + { + if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) + err=UNZ_CRCERROR; + } + + + TRYFREE(pfile_in_zip_read_info->read_buffer); + pfile_in_zip_read_info->read_buffer = NULL; + if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED) + inflateEnd(&pfile_in_zip_read_info->stream); +#ifdef HAVE_BZIP2 + else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED) + BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream); +#endif + + + pfile_in_zip_read_info->stream_initialised = 0; + TRYFREE(pfile_in_zip_read_info); + + s->pfile_in_zip_read=NULL; + + return err; +} + + +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ +extern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uSizeBuf) +{ + unz64_s* s; + uLong uReadThis ; + if (file==NULL) + return (int)UNZ_PARAMERROR; + s=(unz64_s*)file; + + uReadThis = uSizeBuf; + if (uReadThis>s->gi.size_comment) + uReadThis = s->gi.size_comment; + + if (ZSEEK64(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (uReadThis>0) + { + *szComment='\0'; + if (ZREAD64(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis) + return UNZ_ERRNO; + } + + if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) + *(szComment+s->gi.size_comment)='\0'; + return (int)uReadThis; +} + +/* Additions by RX '2004 */ +extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file) +{ + unz64_s* s; + + if (file==NULL) + return 0; //UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return 0; + if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff) + if (s->num_file==s->gi.number_entry) + return 0; + return s->pos_in_central_dir; +} + +extern uLong ZEXPORT unzGetOffset (unzFile file) +{ + ZPOS64_T offset64; + + if (file==NULL) + return 0; //UNZ_PARAMERROR; + offset64 = unzGetOffset64(file); + return (uLong)offset64; +} + +extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos) +{ + unz64_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + + s->pos_in_central_dir = pos; + s->num_file = s->gi.number_entry; /* hack */ + err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + +extern int ZEXPORT unzSetOffset (unzFile file, uLong pos) +{ + return unzSetOffset64(file,pos); +} diff --git a/dependencies/zlib-1.2.11/contrib/minizip/unzip.h b/dependencies/zlib-1.2.11/contrib/minizip/unzip.h new file mode 100644 index 0000000..2104e39 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/minizip/unzip.h @@ -0,0 +1,437 @@ +/* unzip.h -- IO for uncompress .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications of Unzip for Zip64 + Copyright (C) 2007-2008 Even Rouault + + Modifications for Zip64 support on both zip and unzip + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + + --------------------------------------------------------------------------------- + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + --------------------------------------------------------------------------------- + + Changes + + See header of unzip64.c + +*/ + +#ifndef _unz64_H +#define _unz64_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#ifndef _ZLIBIOAPI_H +#include "ioapi.h" +#endif + +#ifdef HAVE_BZIP2 +#include "bzlib.h" +#endif + +#define Z_BZIP2ED 12 + +#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagunzFile__ { int unused; } unzFile__; +typedef unzFile__ *unzFile; +#else +typedef voidp unzFile; +#endif + + +#define UNZ_OK (0) +#define UNZ_END_OF_LIST_OF_FILE (-100) +#define UNZ_ERRNO (Z_ERRNO) +#define UNZ_EOF (0) +#define UNZ_PARAMERROR (-102) +#define UNZ_BADZIPFILE (-103) +#define UNZ_INTERNALERROR (-104) +#define UNZ_CRCERROR (-105) + +/* tm_unz contain date/time info */ +typedef struct tm_unz_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_unz; + +/* unz_global_info structure contain global data about the ZIPfile + These data comes from the end of central dir */ +typedef struct unz_global_info64_s +{ + ZPOS64_T number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info64; + +typedef struct unz_global_info_s +{ + uLong number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info; + +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_info64_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + ZPOS64_T compressed_size; /* compressed size 8 bytes */ + ZPOS64_T uncompressed_size; /* uncompressed size 8 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info64; + +typedef struct unz_file_info_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + uLong compressed_size; /* compressed size 4 bytes */ + uLong uncompressed_size; /* uncompressed size 4 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info; + +extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, + const char* fileName2, + int iCaseSensitivity)); +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) +*/ + + +extern unzFile ZEXPORT unzOpen OF((const char *path)); +extern unzFile ZEXPORT unzOpen64 OF((const void *path)); +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer + "zlib/zlib113.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. + the "64" function take a const void* pointer, because the path is just the + value passed to the open64_file_func callback. + Under Windows, if UNICODE is defined, using fill_fopen64_filefunc, the path + is a pointer to a wide unicode string (LPCTSTR is LPCWSTR), so const char* + does not describe the reality +*/ + + +extern unzFile ZEXPORT unzOpen2 OF((const char *path, + zlib_filefunc_def* pzlib_filefunc_def)); +/* + Open a Zip file, like unzOpen, but provide a set of file low level API + for read/write the zip file (see ioapi.h) +*/ + +extern unzFile ZEXPORT unzOpen2_64 OF((const void *path, + zlib_filefunc64_def* pzlib_filefunc_def)); +/* + Open a Zip file, like unz64Open, but provide a set of file low level API + for read/write the zip file (see ioapi.h) +*/ + +extern int ZEXPORT unzClose OF((unzFile file)); +/* + Close a ZipFile opened with unzOpen. + If there is files inside the .Zip opened with unzOpenCurrentFile (see later), + these files MUST be closed with unzCloseCurrentFile before call unzClose. + return UNZ_OK if there is no problem. */ + +extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, + unz_global_info *pglobal_info)); + +extern int ZEXPORT unzGetGlobalInfo64 OF((unzFile file, + unz_global_info64 *pglobal_info)); +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ + + +extern int ZEXPORT unzGetGlobalComment OF((unzFile file, + char *szComment, + uLong uSizeBuf)); +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ + + +/***************************************************************************/ +/* Unzip package allow you browse the directory of the zipfile */ + +extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ + +extern int ZEXPORT unzGoToNextFile OF((unzFile file)); +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ + +extern int ZEXPORT unzLocateFile OF((unzFile file, + const char *szFileName, + int iCaseSensitivity)); +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ + + +/* ****************************************** */ +/* Ryan supplied functions */ +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_pos_s +{ + uLong pos_in_zip_directory; /* offset in zip file directory */ + uLong num_of_file; /* # of file */ +} unz_file_pos; + +extern int ZEXPORT unzGetFilePos( + unzFile file, + unz_file_pos* file_pos); + +extern int ZEXPORT unzGoToFilePos( + unzFile file, + unz_file_pos* file_pos); + +typedef struct unz64_file_pos_s +{ + ZPOS64_T pos_in_zip_directory; /* offset in zip file directory */ + ZPOS64_T num_of_file; /* # of file */ +} unz64_file_pos; + +extern int ZEXPORT unzGetFilePos64( + unzFile file, + unz64_file_pos* file_pos); + +extern int ZEXPORT unzGoToFilePos64( + unzFile file, + const unz64_file_pos* file_pos); + +/* ****************************************** */ + +extern int ZEXPORT unzGetCurrentFileInfo64 OF((unzFile file, + unz_file_info64 *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); + +extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); +/* + Get Info about the current file + if pfile_info!=NULL, the *pfile_info structure will contain somes info about + the current file + if szFileName!=NULL, the filemane string will be copied in szFileName + (fileNameBufferSize is the size of the buffer) + if extraField!=NULL, the extra field information will be copied in extraField + (extraFieldBufferSize is the size of the buffer). + This is the Central-header version of the extra field + if szComment!=NULL, the comment string of the file will be copied in szComment + (commentBufferSize is the size of the buffer) +*/ + + +/** Addition for GDAL : START */ + +extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file)); + +/** Addition for GDAL : END */ + + +/***************************************************************************/ +/* for reading the content of the current zipfile, you can open it, read data + from it, and close it (you can close it before reading all the file) + */ + +extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); +/* + Open for reading data the current file in the zipfile. + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, + const char* password)); +/* + Open for reading data the current file in the zipfile. + password is a crypting password + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, + int* method, + int* level, + int raw)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + +extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, + int* method, + int* level, + int raw, + const char* password)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + + +extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ + +extern int ZEXPORT unzReadCurrentFile OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read bytes from the current file (opened by unzOpenCurrentFile) + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ + +extern z_off_t ZEXPORT unztell OF((unzFile file)); + +extern ZPOS64_T ZEXPORT unztell64 OF((unzFile file)); +/* + Give the current position in uncompressed data +*/ + +extern int ZEXPORT unzeof OF((unzFile file)); +/* + return 1 if the end of file was reached, 0 elsewhere +*/ + +extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ + +/***************************************************************************/ + +/* Get the current file offset */ +extern ZPOS64_T ZEXPORT unzGetOffset64 (unzFile file); +extern uLong ZEXPORT unzGetOffset (unzFile file); + +/* Set the current file offset */ +extern int ZEXPORT unzSetOffset64 (unzFile file, ZPOS64_T pos); +extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); + + + +#ifdef __cplusplus +} +#endif + +#endif /* _unz64_H */ diff --git a/dependencies/zlib-1.2.11/contrib/minizip/zip.c b/dependencies/zlib-1.2.11/contrib/minizip/zip.c new file mode 100644 index 0000000..44e88a9 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/minizip/zip.c @@ -0,0 +1,2007 @@ +/* zip.c -- IO on .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + + Changes + Oct-2009 - Mathias Svensson - Remove old C style function prototypes + Oct-2009 - Mathias Svensson - Added Zip64 Support when creating new file archives + Oct-2009 - Mathias Svensson - Did some code cleanup and refactoring to get better overview of some functions. + Oct-2009 - Mathias Svensson - Added zipRemoveExtraInfoBlock to strip extra field data from its ZIP64 data + It is used when recreting zip archive with RAW when deleting items from a zip. + ZIP64 data is automatically added to items that needs it, and existing ZIP64 data need to be removed. + Oct-2009 - Mathias Svensson - Added support for BZIP2 as compression mode (bzip2 lib is required) + Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer + +*/ + + +#include +#include +#include +#include +#include "zlib.h" +#include "zip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +#ifndef VERSIONMADEBY +# define VERSIONMADEBY (0x0) /* platform depedent */ +#endif + +#ifndef Z_BUFSIZE +#define Z_BUFSIZE (64*1024) //(16384) +#endif + +#ifndef Z_MAXFILENAMEINZIP +#define Z_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +/* +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) +*/ + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ + + +// NOT sure that this work on ALL platform +#define MAKEULONG64(a, b) ((ZPOS64_T)(((unsigned long)(a)) | ((ZPOS64_T)((unsigned long)(b))) << 32)) + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +#ifndef DEF_MEM_LEVEL +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +#endif +const char zip_copyright[] =" zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; + + +#define SIZEDATA_INDATABLOCK (4096-(4*4)) + +#define LOCALHEADERMAGIC (0x04034b50) +#define CENTRALHEADERMAGIC (0x02014b50) +#define ENDHEADERMAGIC (0x06054b50) +#define ZIP64ENDHEADERMAGIC (0x6064b50) +#define ZIP64ENDLOCHEADERMAGIC (0x7064b50) + +#define FLAG_LOCALHEADER_OFFSET (0x06) +#define CRC_LOCALHEADER_OFFSET (0x0e) + +#define SIZECENTRALHEADER (0x2e) /* 46 */ + +typedef struct linkedlist_datablock_internal_s +{ + struct linkedlist_datablock_internal_s* next_datablock; + uLong avail_in_this_block; + uLong filled_in_this_block; + uLong unused; /* for future use and alignment */ + unsigned char data[SIZEDATA_INDATABLOCK]; +} linkedlist_datablock_internal; + +typedef struct linkedlist_data_s +{ + linkedlist_datablock_internal* first_block; + linkedlist_datablock_internal* last_block; +} linkedlist_data; + + +typedef struct +{ + z_stream stream; /* zLib stream structure for inflate */ +#ifdef HAVE_BZIP2 + bz_stream bstream; /* bzLib stream structure for bziped */ +#endif + + int stream_initialised; /* 1 is stream is initialised */ + uInt pos_in_buffered_data; /* last written byte in buffered_data */ + + ZPOS64_T pos_local_header; /* offset of the local header of the file + currenty writing */ + char* central_header; /* central header data for the current file */ + uLong size_centralExtra; + uLong size_centralheader; /* size of the central header for cur file */ + uLong size_centralExtraFree; /* Extra bytes allocated to the centralheader but that are not used */ + uLong flag; /* flag of the file currently writing */ + + int method; /* compression method of file currenty wr.*/ + int raw; /* 1 for directly writing raw data */ + Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/ + uLong dosDate; + uLong crc32; + int encrypt; + int zip64; /* Add ZIP64 extened information in the extra field */ + ZPOS64_T pos_zip64extrainfo; + ZPOS64_T totalCompressedData; + ZPOS64_T totalUncompressedData; +#ifndef NOCRYPT + unsigned long keys[3]; /* keys defining the pseudo-random sequence */ + const z_crc_t* pcrc_32_tab; + int crypt_header_size; +#endif +} curfile64_info; + +typedef struct +{ + zlib_filefunc64_32_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + linkedlist_data central_dir;/* datablock with central dir in construction*/ + int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/ + curfile64_info ci; /* info on the file curretly writing */ + + ZPOS64_T begin_pos; /* position of the beginning of the zipfile */ + ZPOS64_T add_position_when_writing_offset; + ZPOS64_T number_entry; + +#ifndef NO_ADDFILEINEXISTINGZIP + char *globalcomment; +#endif + +} zip64_internal; + + +#ifndef NOCRYPT +#define INCLUDECRYPTINGCODE_IFCRYPTALLOWED +#include "crypt.h" +#endif + +local linkedlist_datablock_internal* allocate_new_datablock() +{ + linkedlist_datablock_internal* ldi; + ldi = (linkedlist_datablock_internal*) + ALLOC(sizeof(linkedlist_datablock_internal)); + if (ldi!=NULL) + { + ldi->next_datablock = NULL ; + ldi->filled_in_this_block = 0 ; + ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ; + } + return ldi; +} + +local void free_datablock(linkedlist_datablock_internal* ldi) +{ + while (ldi!=NULL) + { + linkedlist_datablock_internal* ldinext = ldi->next_datablock; + TRYFREE(ldi); + ldi = ldinext; + } +} + +local void init_linkedlist(linkedlist_data* ll) +{ + ll->first_block = ll->last_block = NULL; +} + +local void free_linkedlist(linkedlist_data* ll) +{ + free_datablock(ll->first_block); + ll->first_block = ll->last_block = NULL; +} + + +local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) +{ + linkedlist_datablock_internal* ldi; + const unsigned char* from_copy; + + if (ll==NULL) + return ZIP_INTERNALERROR; + + if (ll->last_block == NULL) + { + ll->first_block = ll->last_block = allocate_new_datablock(); + if (ll->first_block == NULL) + return ZIP_INTERNALERROR; + } + + ldi = ll->last_block; + from_copy = (unsigned char*)buf; + + while (len>0) + { + uInt copy_this; + uInt i; + unsigned char* to_copy; + + if (ldi->avail_in_this_block==0) + { + ldi->next_datablock = allocate_new_datablock(); + if (ldi->next_datablock == NULL) + return ZIP_INTERNALERROR; + ldi = ldi->next_datablock ; + ll->last_block = ldi; + } + + if (ldi->avail_in_this_block < len) + copy_this = (uInt)ldi->avail_in_this_block; + else + copy_this = (uInt)len; + + to_copy = &(ldi->data[ldi->filled_in_this_block]); + + for (i=0;ifilled_in_this_block += copy_this; + ldi->avail_in_this_block -= copy_this; + from_copy += copy_this ; + len -= copy_this; + } + return ZIP_OK; +} + + + +/****************************************************************************/ + +#ifndef NO_ADDFILEINEXISTINGZIP +/* =========================================================================== + Inputs a long in LSB order to the given file + nbByte == 1, 2 ,4 or 8 (byte, short or long, ZPOS64_T) +*/ + +local int zip64local_putValue OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte)); +local int zip64local_putValue (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte) +{ + unsigned char buf[8]; + int n; + for (n = 0; n < nbByte; n++) + { + buf[n] = (unsigned char)(x & 0xff); + x >>= 8; + } + if (x != 0) + { /* data overflow - hack for ZIP64 (X Roche) */ + for (n = 0; n < nbByte; n++) + { + buf[n] = 0xff; + } + } + + if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte) + return ZIP_ERRNO; + else + return ZIP_OK; +} + +local void zip64local_putValue_inmemory OF((void* dest, ZPOS64_T x, int nbByte)); +local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte) +{ + unsigned char* buf=(unsigned char*)dest; + int n; + for (n = 0; n < nbByte; n++) { + buf[n] = (unsigned char)(x & 0xff); + x >>= 8; + } + + if (x != 0) + { /* data overflow - hack for ZIP64 */ + for (n = 0; n < nbByte; n++) + { + buf[n] = 0xff; + } + } +} + +/****************************************************************************/ + + +local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm) +{ + uLong year = (uLong)ptm->tm_year; + if (year>=1980) + year-=1980; + else if (year>=80) + year-=80; + return + (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) | + ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); +} + + +/****************************************************************************/ + +local int zip64local_getByte OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi)); + +local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def,voidpf filestream,int* pi) +{ + unsigned char c; + int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); + if (err==1) + { + *pi = (int)c; + return ZIP_OK; + } + else + { + if (ZERROR64(*pzlib_filefunc_def,filestream)) + return ZIP_ERRNO; + else + return ZIP_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int zip64local_getShort OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); + +local int zip64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) +{ + uLong x ; + int i = 0; + int err; + + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==ZIP_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int zip64local_getLong OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); + +local int zip64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) +{ + uLong x ; + int i = 0; + int err; + + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<16; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<24; + + if (err==ZIP_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int zip64local_getLong64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX)); + + +local int zip64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) +{ + ZPOS64_T x; + int i = 0; + int err; + + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (ZPOS64_T)i; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<8; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<16; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<24; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<32; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<40; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<48; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<56; + + if (err==ZIP_OK) + *pX = x; + else + *pX = 0; + + return err; +} + +#ifndef BUFREADCOMMENT +#define BUFREADCOMMENT (0x400) +#endif +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local ZPOS64_T zip64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); + +local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) +{ + unsigned char* buf; + ZPOS64_T uSizeFile; + ZPOS64_T uBackRead; + ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ + ZPOS64_T uPosFound=0; + + if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); + if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} + +/* +Locate the End of Zip64 Central directory locator and from there find the CD of a zipfile (at the end, just before +the global comment) +*/ +local ZPOS64_T zip64local_SearchCentralDir64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); + +local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) +{ + unsigned char* buf; + ZPOS64_T uSizeFile; + ZPOS64_T uBackRead; + ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ + ZPOS64_T uPosFound=0; + uLong uL; + ZPOS64_T relativeOffset; + + if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); + if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + { + // Signature "0x07064b50" Zip64 end of central directory locater + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) + { + uPosFound = uReadPos+i; + break; + } + } + + if (uPosFound!=0) + break; + } + + TRYFREE(buf); + if (uPosFound == 0) + return 0; + + /* Zip64 end of central directory locator */ + if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0) + return 0; + + /* the signature, already checked */ + if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) + return 0; + + /* number of the disk with the start of the zip64 end of central directory */ + if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) + return 0; + if (uL != 0) + return 0; + + /* relative offset of the zip64 end of central directory record */ + if (zip64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=ZIP_OK) + return 0; + + /* total number of disks */ + if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) + return 0; + if (uL != 1) + return 0; + + /* Goto Zip64 end of central directory record */ + if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0) + return 0; + + /* the signature */ + if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) + return 0; + + if (uL != 0x06064b50) // signature of 'Zip64 end of central directory' + return 0; + + return relativeOffset; +} + +int LoadCentralDirectoryRecord(zip64_internal* pziinit) +{ + int err=ZIP_OK; + ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + + ZPOS64_T size_central_dir; /* size of the central directory */ + ZPOS64_T offset_central_dir; /* offset of start of central directory */ + ZPOS64_T central_pos; + uLong uL; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + ZPOS64_T number_entry; + ZPOS64_T number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + uLong VersionMadeBy; + uLong VersionNeeded; + uLong size_comment; + + int hasZIP64Record = 0; + + // check first if we find a ZIP64 record + central_pos = zip64local_SearchCentralDir64(&pziinit->z_filefunc,pziinit->filestream); + if(central_pos > 0) + { + hasZIP64Record = 1; + } + else if(central_pos == 0) + { + central_pos = zip64local_SearchCentralDir(&pziinit->z_filefunc,pziinit->filestream); + } + +/* disable to allow appending to empty ZIP archive + if (central_pos==0) + err=ZIP_ERRNO; +*/ + + if(hasZIP64Record) + { + ZPOS64_T sizeEndOfCentralDirectory; + if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0) + err=ZIP_ERRNO; + + /* the signature, already checked */ + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK) + err=ZIP_ERRNO; + + /* size of zip64 end of central directory record */ + if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &sizeEndOfCentralDirectory)!=ZIP_OK) + err=ZIP_ERRNO; + + /* version made by */ + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionMadeBy)!=ZIP_OK) + err=ZIP_ERRNO; + + /* version needed to extract */ + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionNeeded)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of this disk */ + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of the disk with the start of the central directory */ + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK) + err=ZIP_ERRNO; + + /* total number of entries in the central directory on this disk */ + if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &number_entry)!=ZIP_OK) + err=ZIP_ERRNO; + + /* total number of entries in the central directory */ + if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&number_entry_CD)!=ZIP_OK) + err=ZIP_ERRNO; + + if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) + err=ZIP_BADZIPFILE; + + /* size of the central directory */ + if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&size_central_dir)!=ZIP_OK) + err=ZIP_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&offset_central_dir)!=ZIP_OK) + err=ZIP_ERRNO; + + // TODO.. + // read the comment from the standard central header. + size_comment = 0; + } + else + { + // Read End of central Directory info + if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=ZIP_ERRNO; + + /* the signature, already checked */ + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of this disk */ + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of the disk with the start of the central directory */ + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK) + err=ZIP_ERRNO; + + /* total number of entries in the central dir on this disk */ + number_entry = 0; + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) + err=ZIP_ERRNO; + else + number_entry = uL; + + /* total number of entries in the central dir */ + number_entry_CD = 0; + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) + err=ZIP_ERRNO; + else + number_entry_CD = uL; + + if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) + err=ZIP_BADZIPFILE; + + /* size of the central directory */ + size_central_dir = 0; + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) + err=ZIP_ERRNO; + else + size_central_dir = uL; + + /* offset of start of central directory with respect to the starting disk number */ + offset_central_dir = 0; + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) + err=ZIP_ERRNO; + else + offset_central_dir = uL; + + + /* zipfile global comment length */ + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &size_comment)!=ZIP_OK) + err=ZIP_ERRNO; + } + + if ((central_posz_filefunc, pziinit->filestream); + return ZIP_ERRNO; + } + + if (size_comment>0) + { + pziinit->globalcomment = (char*)ALLOC(size_comment+1); + if (pziinit->globalcomment) + { + size_comment = ZREAD64(pziinit->z_filefunc, pziinit->filestream, pziinit->globalcomment,size_comment); + pziinit->globalcomment[size_comment]=0; + } + } + + byte_before_the_zipfile = central_pos - (offset_central_dir+size_central_dir); + pziinit->add_position_when_writing_offset = byte_before_the_zipfile; + + { + ZPOS64_T size_central_dir_to_read = size_central_dir; + size_t buf_size = SIZEDATA_INDATABLOCK; + void* buf_read = (void*)ALLOC(buf_size); + if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0) + err=ZIP_ERRNO; + + while ((size_central_dir_to_read>0) && (err==ZIP_OK)) + { + ZPOS64_T read_this = SIZEDATA_INDATABLOCK; + if (read_this > size_central_dir_to_read) + read_this = size_central_dir_to_read; + + if (ZREAD64(pziinit->z_filefunc, pziinit->filestream,buf_read,(uLong)read_this) != read_this) + err=ZIP_ERRNO; + + if (err==ZIP_OK) + err = add_data_in_datablock(&pziinit->central_dir,buf_read, (uLong)read_this); + + size_central_dir_to_read-=read_this; + } + TRYFREE(buf_read); + } + pziinit->begin_pos = byte_before_the_zipfile; + pziinit->number_entry = number_entry_CD; + + if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET) != 0) + err=ZIP_ERRNO; + + return err; +} + + +#endif /* !NO_ADDFILEINEXISTINGZIP*/ + + +/************************************************************/ +extern zipFile ZEXPORT zipOpen3 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def) +{ + zip64_internal ziinit; + zip64_internal* zi; + int err=ZIP_OK; + + ziinit.z_filefunc.zseek32_file = NULL; + ziinit.z_filefunc.ztell32_file = NULL; + if (pzlib_filefunc64_32_def==NULL) + fill_fopen64_filefunc(&ziinit.z_filefunc.zfile_func64); + else + ziinit.z_filefunc = *pzlib_filefunc64_32_def; + + ziinit.filestream = ZOPEN64(ziinit.z_filefunc, + pathname, + (append == APPEND_STATUS_CREATE) ? + (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) : + (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING)); + + if (ziinit.filestream == NULL) + return NULL; + + if (append == APPEND_STATUS_CREATEAFTER) + ZSEEK64(ziinit.z_filefunc,ziinit.filestream,0,SEEK_END); + + ziinit.begin_pos = ZTELL64(ziinit.z_filefunc,ziinit.filestream); + ziinit.in_opened_file_inzip = 0; + ziinit.ci.stream_initialised = 0; + ziinit.number_entry = 0; + ziinit.add_position_when_writing_offset = 0; + init_linkedlist(&(ziinit.central_dir)); + + + + zi = (zip64_internal*)ALLOC(sizeof(zip64_internal)); + if (zi==NULL) + { + ZCLOSE64(ziinit.z_filefunc,ziinit.filestream); + return NULL; + } + + /* now we add file in a zipfile */ +# ifndef NO_ADDFILEINEXISTINGZIP + ziinit.globalcomment = NULL; + if (append == APPEND_STATUS_ADDINZIP) + { + // Read and Cache Central Directory Records + err = LoadCentralDirectoryRecord(&ziinit); + } + + if (globalcomment) + { + *globalcomment = ziinit.globalcomment; + } +# endif /* !NO_ADDFILEINEXISTINGZIP*/ + + if (err != ZIP_OK) + { +# ifndef NO_ADDFILEINEXISTINGZIP + TRYFREE(ziinit.globalcomment); +# endif /* !NO_ADDFILEINEXISTINGZIP*/ + TRYFREE(zi); + return NULL; + } + else + { + *zi = ziinit; + return (zipFile)zi; + } +} + +extern zipFile ZEXPORT zipOpen2 (const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def) +{ + if (pzlib_filefunc32_def != NULL) + { + zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; + fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def); + return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill); + } + else + return zipOpen3(pathname, append, globalcomment, NULL); +} + +extern zipFile ZEXPORT zipOpen2_64 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def) +{ + if (pzlib_filefunc_def != NULL) + { + zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; + zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def; + zlib_filefunc64_32_def_fill.ztell32_file = NULL; + zlib_filefunc64_32_def_fill.zseek32_file = NULL; + return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill); + } + else + return zipOpen3(pathname, append, globalcomment, NULL); +} + + + +extern zipFile ZEXPORT zipOpen (const char* pathname, int append) +{ + return zipOpen3((const void*)pathname,append,NULL,NULL); +} + +extern zipFile ZEXPORT zipOpen64 (const void* pathname, int append) +{ + return zipOpen3(pathname,append,NULL,NULL); +} + +int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local) +{ + /* write the local header */ + int err; + uInt size_filename = (uInt)strlen(filename); + uInt size_extrafield = size_extrafield_local; + + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC, 4); + + if (err==ZIP_OK) + { + if(zi->ci.zip64) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);/* version needed to extract */ + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */ + } + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2); + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2); + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4); + + // CRC / Compressed size / Uncompressed size will be filled in later and rewritten later + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */ + if (err==ZIP_OK) + { + if(zi->ci.zip64) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* compressed size, unknown */ + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */ + } + if (err==ZIP_OK) + { + if(zi->ci.zip64) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* uncompressed size, unknown */ + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */ + } + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2); + + if(zi->ci.zip64) + { + size_extrafield += 20; + } + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield,2); + + if ((err==ZIP_OK) && (size_filename > 0)) + { + if (ZWRITE64(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename) + err = ZIP_ERRNO; + } + + if ((err==ZIP_OK) && (size_extrafield_local > 0)) + { + if (ZWRITE64(zi->z_filefunc, zi->filestream, extrafield_local, size_extrafield_local) != size_extrafield_local) + err = ZIP_ERRNO; + } + + + if ((err==ZIP_OK) && (zi->ci.zip64)) + { + // write the Zip64 extended info + short HeaderID = 1; + short DataSize = 16; + ZPOS64_T CompressedSize = 0; + ZPOS64_T UncompressedSize = 0; + + // Remember position of Zip64 extended info for the local file header. (needed when we update size after done with file) + zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc,zi->filestream); + + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)HeaderID,2); + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)DataSize,2); + + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)UncompressedSize,8); + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)CompressedSize,8); + } + + return err; +} + +/* + NOTE. + When writing RAW the ZIP64 extended information in extrafield_local and extrafield_global needs to be stripped + before calling this function it can be done with zipRemoveExtraInfoBlock + + It is not done here because then we need to realloc a new buffer since parameters are 'const' and I want to minimize + unnecessary allocations. + */ +extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting, + uLong versionMadeBy, uLong flagBase, int zip64) +{ + zip64_internal* zi; + uInt size_filename; + uInt size_comment; + uInt i; + int err = ZIP_OK; + +# ifdef NOCRYPT + (crcForCrypting); + if (password != NULL) + return ZIP_PARAMERROR; +# endif + + if (file == NULL) + return ZIP_PARAMERROR; + +#ifdef HAVE_BZIP2 + if ((method!=0) && (method!=Z_DEFLATED) && (method!=Z_BZIP2ED)) + return ZIP_PARAMERROR; +#else + if ((method!=0) && (method!=Z_DEFLATED)) + return ZIP_PARAMERROR; +#endif + + zi = (zip64_internal*)file; + + if (zi->in_opened_file_inzip == 1) + { + err = zipCloseFileInZip (file); + if (err != ZIP_OK) + return err; + } + + if (filename==NULL) + filename="-"; + + if (comment==NULL) + size_comment = 0; + else + size_comment = (uInt)strlen(comment); + + size_filename = (uInt)strlen(filename); + + if (zipfi == NULL) + zi->ci.dosDate = 0; + else + { + if (zipfi->dosDate != 0) + zi->ci.dosDate = zipfi->dosDate; + else + zi->ci.dosDate = zip64local_TmzDateToDosDate(&zipfi->tmz_date); + } + + zi->ci.flag = flagBase; + if ((level==8) || (level==9)) + zi->ci.flag |= 2; + if (level==2) + zi->ci.flag |= 4; + if (level==1) + zi->ci.flag |= 6; + if (password != NULL) + zi->ci.flag |= 1; + + zi->ci.crc32 = 0; + zi->ci.method = method; + zi->ci.encrypt = 0; + zi->ci.stream_initialised = 0; + zi->ci.pos_in_buffered_data = 0; + zi->ci.raw = raw; + zi->ci.pos_local_header = ZTELL64(zi->z_filefunc,zi->filestream); + + zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global + size_comment; + zi->ci.size_centralExtraFree = 32; // Extra space we have reserved in case we need to add ZIP64 extra info data + + zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader + zi->ci.size_centralExtraFree); + + zi->ci.size_centralExtra = size_extrafield_global; + zip64local_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4); + /* version info */ + zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)versionMadeBy,2); + zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2); + zip64local_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2); + zip64local_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2); + zip64local_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4); + zip64local_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/ + zip64local_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/ + zip64local_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/ + zip64local_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2); + zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2); + zip64local_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2); + zip64local_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/ + + if (zipfi==NULL) + zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2); + else + zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2); + + if (zipfi==NULL) + zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4); + else + zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4); + + if(zi->ci.pos_local_header >= 0xffffffff) + zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)0xffffffff,4); + else + zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header - zi->add_position_when_writing_offset,4); + + for (i=0;ici.central_header+SIZECENTRALHEADER+i) = *(filename+i); + + for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+i) = + *(((const char*)extrafield_global)+i); + + for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+ + size_extrafield_global+i) = *(comment+i); + if (zi->ci.central_header == NULL) + return ZIP_INTERNALERROR; + + zi->ci.zip64 = zip64; + zi->ci.totalCompressedData = 0; + zi->ci.totalUncompressedData = 0; + zi->ci.pos_zip64extrainfo = 0; + + err = Write_LocalFileHeader(zi, filename, size_extrafield_local, extrafield_local); + +#ifdef HAVE_BZIP2 + zi->ci.bstream.avail_in = (uInt)0; + zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; + zi->ci.bstream.total_in_hi32 = 0; + zi->ci.bstream.total_in_lo32 = 0; + zi->ci.bstream.total_out_hi32 = 0; + zi->ci.bstream.total_out_lo32 = 0; +#endif + + zi->ci.stream.avail_in = (uInt)0; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + zi->ci.stream.total_in = 0; + zi->ci.stream.total_out = 0; + zi->ci.stream.data_type = Z_BINARY; + +#ifdef HAVE_BZIP2 + if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED || zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) +#else + if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) +#endif + { + if(zi->ci.method == Z_DEFLATED) + { + zi->ci.stream.zalloc = (alloc_func)0; + zi->ci.stream.zfree = (free_func)0; + zi->ci.stream.opaque = (voidpf)0; + + if (windowBits>0) + windowBits = -windowBits; + + err = deflateInit2(&zi->ci.stream, level, Z_DEFLATED, windowBits, memLevel, strategy); + + if (err==Z_OK) + zi->ci.stream_initialised = Z_DEFLATED; + } + else if(zi->ci.method == Z_BZIP2ED) + { +#ifdef HAVE_BZIP2 + // Init BZip stuff here + zi->ci.bstream.bzalloc = 0; + zi->ci.bstream.bzfree = 0; + zi->ci.bstream.opaque = (voidpf)0; + + err = BZ2_bzCompressInit(&zi->ci.bstream, level, 0,35); + if(err == BZ_OK) + zi->ci.stream_initialised = Z_BZIP2ED; +#endif + } + + } + +# ifndef NOCRYPT + zi->ci.crypt_header_size = 0; + if ((err==Z_OK) && (password != NULL)) + { + unsigned char bufHead[RAND_HEAD_LEN]; + unsigned int sizeHead; + zi->ci.encrypt = 1; + zi->ci.pcrc_32_tab = get_crc_table(); + /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/ + + sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting); + zi->ci.crypt_header_size = sizeHead; + + if (ZWRITE64(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead) + err = ZIP_ERRNO; + } +# endif + + if (err==Z_OK) + zi->in_opened_file_inzip = 1; + return err; +} + +extern int ZEXPORT zipOpenNewFileInZip4 (zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting, + uLong versionMadeBy, uLong flagBase) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting, versionMadeBy, flagBase, 0); +} + +extern int ZEXPORT zipOpenNewFileInZip3 (zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting, VERSIONMADEBY, 0, 0); +} + +extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting, int zip64) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting, VERSIONMADEBY, 0, zip64); +} + +extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, 0); +} + +extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, int zip64) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, zip64); +} + +extern int ZEXPORT zipOpenNewFileInZip64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void*extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int zip64) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, 0, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, zip64); +} + +extern int ZEXPORT zipOpenNewFileInZip (zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void*extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, 0, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, 0); +} + +local int zip64FlushWriteBuffer(zip64_internal* zi) +{ + int err=ZIP_OK; + + if (zi->ci.encrypt != 0) + { +#ifndef NOCRYPT + uInt i; + int t; + for (i=0;ici.pos_in_buffered_data;i++) + zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab, zi->ci.buffered_data[i],t); +#endif + } + + if (ZWRITE64(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data) != zi->ci.pos_in_buffered_data) + err = ZIP_ERRNO; + + zi->ci.totalCompressedData += zi->ci.pos_in_buffered_data; + +#ifdef HAVE_BZIP2 + if(zi->ci.method == Z_BZIP2ED) + { + zi->ci.totalUncompressedData += zi->ci.bstream.total_in_lo32; + zi->ci.bstream.total_in_lo32 = 0; + zi->ci.bstream.total_in_hi32 = 0; + } + else +#endif + { + zi->ci.totalUncompressedData += zi->ci.stream.total_in; + zi->ci.stream.total_in = 0; + } + + + zi->ci.pos_in_buffered_data = 0; + + return err; +} + +extern int ZEXPORT zipWriteInFileInZip (zipFile file,const void* buf,unsigned int len) +{ + zip64_internal* zi; + int err=ZIP_OK; + + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip64_internal*)file; + + if (zi->in_opened_file_inzip == 0) + return ZIP_PARAMERROR; + + zi->ci.crc32 = crc32(zi->ci.crc32,buf,(uInt)len); + +#ifdef HAVE_BZIP2 + if(zi->ci.method == Z_BZIP2ED && (!zi->ci.raw)) + { + zi->ci.bstream.next_in = (void*)buf; + zi->ci.bstream.avail_in = len; + err = BZ_RUN_OK; + + while ((err==BZ_RUN_OK) && (zi->ci.bstream.avail_in>0)) + { + if (zi->ci.bstream.avail_out == 0) + { + if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; + } + + + if(err != BZ_RUN_OK) + break; + + if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) + { + uLong uTotalOutBefore_lo = zi->ci.bstream.total_out_lo32; +// uLong uTotalOutBefore_hi = zi->ci.bstream.total_out_hi32; + err=BZ2_bzCompress(&zi->ci.bstream, BZ_RUN); + + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore_lo) ; + } + } + + if(err == BZ_RUN_OK) + err = ZIP_OK; + } + else +#endif + { + zi->ci.stream.next_in = (Bytef*)buf; + zi->ci.stream.avail_in = len; + + while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0)) + { + if (zi->ci.stream.avail_out == 0) + { + if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + } + + + if(err != ZIP_OK) + break; + + if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + { + uLong uTotalOutBefore = zi->ci.stream.total_out; + err=deflate(&zi->ci.stream, Z_NO_FLUSH); + if(uTotalOutBefore > zi->ci.stream.total_out) + { + int bBreak = 0; + bBreak++; + } + + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; + } + else + { + uInt copy_this,i; + if (zi->ci.stream.avail_in < zi->ci.stream.avail_out) + copy_this = zi->ci.stream.avail_in; + else + copy_this = zi->ci.stream.avail_out; + + for (i = 0; i < copy_this; i++) + *(((char*)zi->ci.stream.next_out)+i) = + *(((const char*)zi->ci.stream.next_in)+i); + { + zi->ci.stream.avail_in -= copy_this; + zi->ci.stream.avail_out-= copy_this; + zi->ci.stream.next_in+= copy_this; + zi->ci.stream.next_out+= copy_this; + zi->ci.stream.total_in+= copy_this; + zi->ci.stream.total_out+= copy_this; + zi->ci.pos_in_buffered_data += copy_this; + } + } + }// while(...) + } + + return err; +} + +extern int ZEXPORT zipCloseFileInZipRaw (zipFile file, uLong uncompressed_size, uLong crc32) +{ + return zipCloseFileInZipRaw64 (file, uncompressed_size, crc32); +} + +extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_size, uLong crc32) +{ + zip64_internal* zi; + ZPOS64_T compressed_size; + uLong invalidValue = 0xffffffff; + short datasize = 0; + int err=ZIP_OK; + + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip64_internal*)file; + + if (zi->in_opened_file_inzip == 0) + return ZIP_PARAMERROR; + zi->ci.stream.avail_in = 0; + + if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + { + while (err==ZIP_OK) + { + uLong uTotalOutBefore; + if (zi->ci.stream.avail_out == 0) + { + if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + } + uTotalOutBefore = zi->ci.stream.total_out; + err=deflate(&zi->ci.stream, Z_FINISH); + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; + } + } + else if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) + { +#ifdef HAVE_BZIP2 + err = BZ_FINISH_OK; + while (err==BZ_FINISH_OK) + { + uLong uTotalOutBefore; + if (zi->ci.bstream.avail_out == 0) + { + if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; + } + uTotalOutBefore = zi->ci.bstream.total_out_lo32; + err=BZ2_bzCompress(&zi->ci.bstream, BZ_FINISH); + if(err == BZ_STREAM_END) + err = Z_STREAM_END; + + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore); + } + + if(err == BZ_FINISH_OK) + err = ZIP_OK; +#endif + } + + if (err==Z_STREAM_END) + err=ZIP_OK; /* this is normal */ + + if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK)) + { + if (zip64FlushWriteBuffer(zi)==ZIP_ERRNO) + err = ZIP_ERRNO; + } + + if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + { + int tmp_err = deflateEnd(&zi->ci.stream); + if (err == ZIP_OK) + err = tmp_err; + zi->ci.stream_initialised = 0; + } +#ifdef HAVE_BZIP2 + else if((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) + { + int tmperr = BZ2_bzCompressEnd(&zi->ci.bstream); + if (err==ZIP_OK) + err = tmperr; + zi->ci.stream_initialised = 0; + } +#endif + + if (!zi->ci.raw) + { + crc32 = (uLong)zi->ci.crc32; + uncompressed_size = zi->ci.totalUncompressedData; + } + compressed_size = zi->ci.totalCompressedData; + +# ifndef NOCRYPT + compressed_size += zi->ci.crypt_header_size; +# endif + + // update Current Item crc and sizes, + if(compressed_size >= 0xffffffff || uncompressed_size >= 0xffffffff || zi->ci.pos_local_header >= 0xffffffff) + { + /*version Made by*/ + zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)45,2); + /*version needed*/ + zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)45,2); + + } + + zip64local_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/ + + + if(compressed_size >= 0xffffffff) + zip64local_putValue_inmemory(zi->ci.central_header+20, invalidValue,4); /*compr size*/ + else + zip64local_putValue_inmemory(zi->ci.central_header+20, compressed_size,4); /*compr size*/ + + /// set internal file attributes field + if (zi->ci.stream.data_type == Z_ASCII) + zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2); + + if(uncompressed_size >= 0xffffffff) + zip64local_putValue_inmemory(zi->ci.central_header+24, invalidValue,4); /*uncompr size*/ + else + zip64local_putValue_inmemory(zi->ci.central_header+24, uncompressed_size,4); /*uncompr size*/ + + // Add ZIP64 extra info field for uncompressed size + if(uncompressed_size >= 0xffffffff) + datasize += 8; + + // Add ZIP64 extra info field for compressed size + if(compressed_size >= 0xffffffff) + datasize += 8; + + // Add ZIP64 extra info field for relative offset to local file header of current file + if(zi->ci.pos_local_header >= 0xffffffff) + datasize += 8; + + if(datasize > 0) + { + char* p = NULL; + + if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree) + { + // we can not write more data to the buffer that we have room for. + return ZIP_BADZIPFILE; + } + + p = zi->ci.central_header + zi->ci.size_centralheader; + + // Add Extra Information Header for 'ZIP64 information' + zip64local_putValue_inmemory(p, 0x0001, 2); // HeaderID + p += 2; + zip64local_putValue_inmemory(p, datasize, 2); // DataSize + p += 2; + + if(uncompressed_size >= 0xffffffff) + { + zip64local_putValue_inmemory(p, uncompressed_size, 8); + p += 8; + } + + if(compressed_size >= 0xffffffff) + { + zip64local_putValue_inmemory(p, compressed_size, 8); + p += 8; + } + + if(zi->ci.pos_local_header >= 0xffffffff) + { + zip64local_putValue_inmemory(p, zi->ci.pos_local_header, 8); + p += 8; + } + + // Update how much extra free space we got in the memory buffer + // and increase the centralheader size so the new ZIP64 fields are included + // ( 4 below is the size of HeaderID and DataSize field ) + zi->ci.size_centralExtraFree -= datasize + 4; + zi->ci.size_centralheader += datasize + 4; + + // Update the extra info size field + zi->ci.size_centralExtra += datasize + 4; + zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)zi->ci.size_centralExtra,2); + } + + if (err==ZIP_OK) + err = add_data_in_datablock(&zi->central_dir, zi->ci.central_header, (uLong)zi->ci.size_centralheader); + + free(zi->ci.central_header); + + if (err==ZIP_OK) + { + // Update the LocalFileHeader with the new values. + + ZPOS64_T cur_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream); + + if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0) + err = ZIP_ERRNO; + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */ + + if(uncompressed_size >= 0xffffffff || compressed_size >= 0xffffffff ) + { + if(zi->ci.pos_zip64extrainfo > 0) + { + // Update the size in the ZIP64 extended field. + if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_zip64extrainfo + 4,ZLIB_FILEFUNC_SEEK_SET)!=0) + err = ZIP_ERRNO; + + if (err==ZIP_OK) /* compressed size, unknown */ + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, uncompressed_size, 8); + + if (err==ZIP_OK) /* uncompressed size, unknown */ + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, compressed_size, 8); + } + else + err = ZIP_BADZIPFILE; // Caller passed zip64 = 0, so no room for zip64 info -> fatal + } + else + { + if (err==ZIP_OK) /* compressed size, unknown */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4); + + if (err==ZIP_OK) /* uncompressed size, unknown */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4); + } + + if (ZSEEK64(zi->z_filefunc,zi->filestream, cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0) + err = ZIP_ERRNO; + } + + zi->number_entry ++; + zi->in_opened_file_inzip = 0; + + return err; +} + +extern int ZEXPORT zipCloseFileInZip (zipFile file) +{ + return zipCloseFileInZipRaw (file,0,0); +} + +int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip) +{ + int err = ZIP_OK; + ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writing_offset; + + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDLOCHEADERMAGIC,4); + + /*num disks*/ + if (err==ZIP_OK) /* number of the disk with the start of the central directory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); + + /*relative offset*/ + if (err==ZIP_OK) /* Relative offset to the Zip64EndOfCentralDirectory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream, pos,8); + + /*total disks*/ /* Do not support spawning of disk so always say 1 here*/ + if (err==ZIP_OK) /* number of the disk with the start of the central directory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)1,4); + + return err; +} + +int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) +{ + int err = ZIP_OK; + + uLong Zip64DataSize = 44; + + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDHEADERMAGIC,4); + + if (err==ZIP_OK) /* size of this 'zip64 end of central directory' */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)Zip64DataSize,8); // why ZPOS64_T of this ? + + if (err==ZIP_OK) /* version made by */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2); + + if (err==ZIP_OK) /* version needed */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2); + + if (err==ZIP_OK) /* number of this disk */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); + + if (err==ZIP_OK) /* number of the disk with the start of the central directory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); + + if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8); + + if (err==ZIP_OK) /* total number of entries in the central dir */ + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8); + + if (err==ZIP_OK) /* size of the central directory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)size_centraldir,8); + + if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ + { + ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; + err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (ZPOS64_T)pos,8); + } + return err; +} +int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) +{ + int err = ZIP_OK; + + /*signature*/ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4); + + if (err==ZIP_OK) /* number of this disk */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); + + if (err==ZIP_OK) /* number of the disk with the start of the central directory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); + + if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ + { + { + if(zi->number_entry >= 0xFFFF) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); + } + } + + if (err==ZIP_OK) /* total number of entries in the central dir */ + { + if(zi->number_entry >= 0xFFFF) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); + } + + if (err==ZIP_OK) /* size of the central directory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4); + + if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ + { + ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; + if(pos >= 0xffffffff) + { + err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)0xffffffff,4); + } + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writing_offset),4); + } + + return err; +} + +int Write_GlobalComment(zip64_internal* zi, const char* global_comment) +{ + int err = ZIP_OK; + uInt size_global_comment = 0; + + if(global_comment != NULL) + size_global_comment = (uInt)strlen(global_comment); + + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2); + + if (err == ZIP_OK && size_global_comment > 0) + { + if (ZWRITE64(zi->z_filefunc,zi->filestream, global_comment, size_global_comment) != size_global_comment) + err = ZIP_ERRNO; + } + return err; +} + +extern int ZEXPORT zipClose (zipFile file, const char* global_comment) +{ + zip64_internal* zi; + int err = 0; + uLong size_centraldir = 0; + ZPOS64_T centraldir_pos_inzip; + ZPOS64_T pos; + + if (file == NULL) + return ZIP_PARAMERROR; + + zi = (zip64_internal*)file; + + if (zi->in_opened_file_inzip == 1) + { + err = zipCloseFileInZip (file); + } + +#ifndef NO_ADDFILEINEXISTINGZIP + if (global_comment==NULL) + global_comment = zi->globalcomment; +#endif + + centraldir_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream); + + if (err==ZIP_OK) + { + linkedlist_datablock_internal* ldi = zi->central_dir.first_block; + while (ldi!=NULL) + { + if ((err==ZIP_OK) && (ldi->filled_in_this_block>0)) + { + if (ZWRITE64(zi->z_filefunc,zi->filestream, ldi->data, ldi->filled_in_this_block) != ldi->filled_in_this_block) + err = ZIP_ERRNO; + } + + size_centraldir += ldi->filled_in_this_block; + ldi = ldi->next_datablock; + } + } + free_linkedlist(&(zi->central_dir)); + + pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; + if(pos >= 0xffffffff || zi->number_entry > 0xFFFF) + { + ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream); + Write_Zip64EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip); + + Write_Zip64EndOfCentralDirectoryLocator(zi, Zip64EOCDpos); + } + + if (err==ZIP_OK) + err = Write_EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip); + + if(err == ZIP_OK) + err = Write_GlobalComment(zi, global_comment); + + if (ZCLOSE64(zi->z_filefunc,zi->filestream) != 0) + if (err == ZIP_OK) + err = ZIP_ERRNO; + +#ifndef NO_ADDFILEINEXISTINGZIP + TRYFREE(zi->globalcomment); +#endif + TRYFREE(zi); + + return err; +} + +extern int ZEXPORT zipRemoveExtraInfoBlock (char* pData, int* dataLen, short sHeader) +{ + char* p = pData; + int size = 0; + char* pNewHeader; + char* pTmp; + short header; + short dataSize; + + int retVal = ZIP_OK; + + if(pData == NULL || *dataLen < 4) + return ZIP_PARAMERROR; + + pNewHeader = (char*)ALLOC(*dataLen); + pTmp = pNewHeader; + + while(p < (pData + *dataLen)) + { + header = *(short*)p; + dataSize = *(((short*)p)+1); + + if( header == sHeader ) // Header found. + { + p += dataSize + 4; // skip it. do not copy to temp buffer + } + else + { + // Extra Info block should not be removed, So copy it to the temp buffer. + memcpy(pTmp, p, dataSize + 4); + p += dataSize + 4; + size += dataSize + 4; + } + + } + + if(size < *dataLen) + { + // clean old extra info block. + memset(pData,0, *dataLen); + + // copy the new extra info block over the old + if(size > 0) + memcpy(pData, pNewHeader, size); + + // set the new extra info size + *dataLen = size; + + retVal = ZIP_OK; + } + else + retVal = ZIP_ERRNO; + + TRYFREE(pNewHeader); + + return retVal; +} diff --git a/dependencies/zlib-1.2.11/contrib/minizip/zip.h b/dependencies/zlib-1.2.11/contrib/minizip/zip.h new file mode 100644 index 0000000..8aaebb6 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/minizip/zip.h @@ -0,0 +1,362 @@ +/* zip.h -- IO on .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + + --------------------------------------------------------------------------- + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + --------------------------------------------------------------------------- + + Changes + + See header of zip.h + +*/ + +#ifndef _zip12_H +#define _zip12_H + +#ifdef __cplusplus +extern "C" { +#endif + +//#define HAVE_BZIP2 + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#ifndef _ZLIBIOAPI_H +#include "ioapi.h" +#endif + +#ifdef HAVE_BZIP2 +#include "bzlib.h" +#endif + +#define Z_BZIP2ED 12 + +#if defined(STRICTZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagzipFile__ { int unused; } zipFile__; +typedef zipFile__ *zipFile; +#else +typedef voidp zipFile; +#endif + +#define ZIP_OK (0) +#define ZIP_EOF (0) +#define ZIP_ERRNO (Z_ERRNO) +#define ZIP_PARAMERROR (-102) +#define ZIP_BADZIPFILE (-103) +#define ZIP_INTERNALERROR (-104) + +#ifndef DEF_MEM_LEVEL +# if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +# else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +# endif +#endif +/* default memLevel */ + +/* tm_zip contain date/time info */ +typedef struct tm_zip_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_zip; + +typedef struct +{ + tm_zip tmz_date; /* date in understandable format */ + uLong dosDate; /* if dos_date == 0, tmu_date is used */ +/* uLong flag; */ /* general purpose bit flag 2 bytes */ + + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ +} zip_fileinfo; + +typedef const char* zipcharpc; + + +#define APPEND_STATUS_CREATE (0) +#define APPEND_STATUS_CREATEAFTER (1) +#define APPEND_STATUS_ADDINZIP (2) + +extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append)); +extern zipFile ZEXPORT zipOpen64 OF((const void *pathname, int append)); +/* + Create a zipfile. + pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on + an Unix computer "zlib/zlib113.zip". + if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip + will be created at the end of the file. + (useful if the file contain a self extractor code) + if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will + add files in existing zip (be sure you don't add file that doesn't exist) + If the zipfile cannot be opened, the return value is NULL. + Else, the return value is a zipFile Handle, usable with other function + of this zip package. +*/ + +/* Note : there is no delete function into a zipfile. + If you want delete file into a zipfile, you must open a zipfile, and create another + Of couse, you can use RAW reading and writing to copy the file you did not want delte +*/ + +extern zipFile ZEXPORT zipOpen2 OF((const char *pathname, + int append, + zipcharpc* globalcomment, + zlib_filefunc_def* pzlib_filefunc_def)); + +extern zipFile ZEXPORT zipOpen2_64 OF((const void *pathname, + int append, + zipcharpc* globalcomment, + zlib_filefunc64_def* pzlib_filefunc_def)); + +extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level)); + +extern int ZEXPORT zipOpenNewFileInZip64 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int zip64)); + +/* + Open a file in the ZIP for writing. + filename : the filename in zip (if NULL, '-' without quote will be used + *zipfi contain supplemental information + if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local + contains the extrafield data the the local header + if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global + contains the extrafield data the the local header + if comment != NULL, comment contain the comment string + method contain the compression method (0 for store, Z_DEFLATED for deflate) + level contain the level of compression (can be Z_DEFAULT_COMPRESSION) + zip64 is set to 1 if a zip64 extended information block should be added to the local file header. + this MUST be '1' if the uncompressed size is >= 0xffffffff. + +*/ + + +extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw)); + + +extern int ZEXPORT zipOpenNewFileInZip2_64 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int zip64)); +/* + Same than zipOpenNewFileInZip, except if raw=1, we write raw file + */ + +extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting)); + +extern int ZEXPORT zipOpenNewFileInZip3_64 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting, + int zip64 + )); + +/* + Same than zipOpenNewFileInZip2, except + windowBits,memLevel,,strategy : see parameter strategy in deflateInit2 + password : crypting password (NULL for no crypting) + crcForCrypting : crc of file to compress (needed for crypting) + */ + +extern int ZEXPORT zipOpenNewFileInZip4 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting, + uLong versionMadeBy, + uLong flagBase + )); + + +extern int ZEXPORT zipOpenNewFileInZip4_64 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting, + uLong versionMadeBy, + uLong flagBase, + int zip64 + )); +/* + Same than zipOpenNewFileInZip4, except + versionMadeBy : value for Version made by field + flag : value for flag field (compression level info will be added) + */ + + +extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, + const void* buf, + unsigned len)); +/* + Write data in the zipfile +*/ + +extern int ZEXPORT zipCloseFileInZip OF((zipFile file)); +/* + Close the current file in the zipfile +*/ + +extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file, + uLong uncompressed_size, + uLong crc32)); + +extern int ZEXPORT zipCloseFileInZipRaw64 OF((zipFile file, + ZPOS64_T uncompressed_size, + uLong crc32)); + +/* + Close the current file in the zipfile, for file opened with + parameter raw=1 in zipOpenNewFileInZip2 + uncompressed_size and crc32 are value for the uncompressed size +*/ + +extern int ZEXPORT zipClose OF((zipFile file, + const char* global_comment)); +/* + Close the zipfile +*/ + + +extern int ZEXPORT zipRemoveExtraInfoBlock OF((char* pData, int* dataLen, short sHeader)); +/* + zipRemoveExtraInfoBlock - Added by Mathias Svensson + + Remove extra information block from a extra information data for the local file header or central directory header + + It is needed to remove ZIP64 extra information blocks when before data is written if using RAW mode. + + 0x0001 is the signature header for the ZIP64 extra information blocks + + usage. + Remove ZIP64 Extra information from a central director extra field data + zipRemoveExtraInfoBlock(pCenDirExtraFieldData, &nCenDirExtraFieldDataLen, 0x0001); + + Remove ZIP64 Extra information from a Local File Header extra field data + zipRemoveExtraInfoBlock(pLocalHeaderExtraFieldData, &nLocalHeaderExtraFieldDataLen, 0x0001); +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _zip64_H */ diff --git a/dependencies/zlib-1.2.11/contrib/pascal/example.pas b/dependencies/zlib-1.2.11/contrib/pascal/example.pas new file mode 100644 index 0000000..5518b36 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/pascal/example.pas @@ -0,0 +1,599 @@ +(* example.c -- usage example of the zlib compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Pascal translation + * Copyright (C) 1998 by Jacques Nomssi Nzali. + * For conditions of distribution and use, see copyright notice in readme.txt + * + * Adaptation to the zlibpas interface + * Copyright (C) 2003 by Cosmin Truta. + * For conditions of distribution and use, see copyright notice in readme.txt + *) + +program example; + +{$DEFINE TEST_COMPRESS} +{DO NOT $DEFINE TEST_GZIO} +{$DEFINE TEST_DEFLATE} +{$DEFINE TEST_INFLATE} +{$DEFINE TEST_FLUSH} +{$DEFINE TEST_SYNC} +{$DEFINE TEST_DICT} + +uses SysUtils, zlibpas; + +const TESTFILE = 'foo.gz'; + +(* "hello world" would be more standard, but the repeated "hello" + * stresses the compression code better, sorry... + *) +const hello: PChar = 'hello, hello!'; + +const dictionary: PChar = 'hello'; + +var dictId: LongInt; (* Adler32 value of the dictionary *) + +procedure CHECK_ERR(err: Integer; msg: String); +begin + if err <> Z_OK then + begin + WriteLn(msg, ' error: ', err); + Halt(1); + end; +end; + +procedure EXIT_ERR(const msg: String); +begin + WriteLn('Error: ', msg); + Halt(1); +end; + +(* =========================================================================== + * Test compress and uncompress + *) +{$IFDEF TEST_COMPRESS} +procedure test_compress(compr: Pointer; comprLen: LongInt; + uncompr: Pointer; uncomprLen: LongInt); +var err: Integer; + len: LongInt; +begin + len := StrLen(hello)+1; + + err := compress(compr, comprLen, hello, len); + CHECK_ERR(err, 'compress'); + + StrCopy(PChar(uncompr), 'garbage'); + + err := uncompress(uncompr, uncomprLen, compr, comprLen); + CHECK_ERR(err, 'uncompress'); + + if StrComp(PChar(uncompr), hello) <> 0 then + EXIT_ERR('bad uncompress') + else + WriteLn('uncompress(): ', PChar(uncompr)); +end; +{$ENDIF} + +(* =========================================================================== + * Test read/write of .gz files + *) +{$IFDEF TEST_GZIO} +procedure test_gzio(const fname: PChar; (* compressed file name *) + uncompr: Pointer; + uncomprLen: LongInt); +var err: Integer; + len: Integer; + zfile: gzFile; + pos: LongInt; +begin + len := StrLen(hello)+1; + + zfile := gzopen(fname, 'wb'); + if zfile = NIL then + begin + WriteLn('gzopen error'); + Halt(1); + end; + gzputc(zfile, 'h'); + if gzputs(zfile, 'ello') <> 4 then + begin + WriteLn('gzputs err: ', gzerror(zfile, err)); + Halt(1); + end; + {$IFDEF GZ_FORMAT_STRING} + if gzprintf(zfile, ', %s!', 'hello') <> 8 then + begin + WriteLn('gzprintf err: ', gzerror(zfile, err)); + Halt(1); + end; + {$ELSE} + if gzputs(zfile, ', hello!') <> 8 then + begin + WriteLn('gzputs err: ', gzerror(zfile, err)); + Halt(1); + end; + {$ENDIF} + gzseek(zfile, 1, SEEK_CUR); (* add one zero byte *) + gzclose(zfile); + + zfile := gzopen(fname, 'rb'); + if zfile = NIL then + begin + WriteLn('gzopen error'); + Halt(1); + end; + + StrCopy(PChar(uncompr), 'garbage'); + + if gzread(zfile, uncompr, uncomprLen) <> len then + begin + WriteLn('gzread err: ', gzerror(zfile, err)); + Halt(1); + end; + if StrComp(PChar(uncompr), hello) <> 0 then + begin + WriteLn('bad gzread: ', PChar(uncompr)); + Halt(1); + end + else + WriteLn('gzread(): ', PChar(uncompr)); + + pos := gzseek(zfile, -8, SEEK_CUR); + if (pos <> 6) or (gztell(zfile) <> pos) then + begin + WriteLn('gzseek error, pos=', pos, ', gztell=', gztell(zfile)); + Halt(1); + end; + + if gzgetc(zfile) <> ' ' then + begin + WriteLn('gzgetc error'); + Halt(1); + end; + + if gzungetc(' ', zfile) <> ' ' then + begin + WriteLn('gzungetc error'); + Halt(1); + end; + + gzgets(zfile, PChar(uncompr), uncomprLen); + uncomprLen := StrLen(PChar(uncompr)); + if uncomprLen <> 7 then (* " hello!" *) + begin + WriteLn('gzgets err after gzseek: ', gzerror(zfile, err)); + Halt(1); + end; + if StrComp(PChar(uncompr), hello + 6) <> 0 then + begin + WriteLn('bad gzgets after gzseek'); + Halt(1); + end + else + WriteLn('gzgets() after gzseek: ', PChar(uncompr)); + + gzclose(zfile); +end; +{$ENDIF} + +(* =========================================================================== + * Test deflate with small buffers + *) +{$IFDEF TEST_DEFLATE} +procedure test_deflate(compr: Pointer; comprLen: LongInt); +var c_stream: z_stream; (* compression stream *) + err: Integer; + len: LongInt; +begin + len := StrLen(hello)+1; + + c_stream.zalloc := NIL; + c_stream.zfree := NIL; + c_stream.opaque := NIL; + + err := deflateInit(c_stream, Z_DEFAULT_COMPRESSION); + CHECK_ERR(err, 'deflateInit'); + + c_stream.next_in := hello; + c_stream.next_out := compr; + + while (c_stream.total_in <> len) and + (c_stream.total_out < comprLen) do + begin + c_stream.avail_out := 1; { force small buffers } + c_stream.avail_in := 1; + err := deflate(c_stream, Z_NO_FLUSH); + CHECK_ERR(err, 'deflate'); + end; + + (* Finish the stream, still forcing small buffers: *) + while TRUE do + begin + c_stream.avail_out := 1; + err := deflate(c_stream, Z_FINISH); + if err = Z_STREAM_END then + break; + CHECK_ERR(err, 'deflate'); + end; + + err := deflateEnd(c_stream); + CHECK_ERR(err, 'deflateEnd'); +end; +{$ENDIF} + +(* =========================================================================== + * Test inflate with small buffers + *) +{$IFDEF TEST_INFLATE} +procedure test_inflate(compr: Pointer; comprLen : LongInt; + uncompr: Pointer; uncomprLen : LongInt); +var err: Integer; + d_stream: z_stream; (* decompression stream *) +begin + StrCopy(PChar(uncompr), 'garbage'); + + d_stream.zalloc := NIL; + d_stream.zfree := NIL; + d_stream.opaque := NIL; + + d_stream.next_in := compr; + d_stream.avail_in := 0; + d_stream.next_out := uncompr; + + err := inflateInit(d_stream); + CHECK_ERR(err, 'inflateInit'); + + while (d_stream.total_out < uncomprLen) and + (d_stream.total_in < comprLen) do + begin + d_stream.avail_out := 1; (* force small buffers *) + d_stream.avail_in := 1; + err := inflate(d_stream, Z_NO_FLUSH); + if err = Z_STREAM_END then + break; + CHECK_ERR(err, 'inflate'); + end; + + err := inflateEnd(d_stream); + CHECK_ERR(err, 'inflateEnd'); + + if StrComp(PChar(uncompr), hello) <> 0 then + EXIT_ERR('bad inflate') + else + WriteLn('inflate(): ', PChar(uncompr)); +end; +{$ENDIF} + +(* =========================================================================== + * Test deflate with large buffers and dynamic change of compression level + *) +{$IFDEF TEST_DEFLATE} +procedure test_large_deflate(compr: Pointer; comprLen: LongInt; + uncompr: Pointer; uncomprLen: LongInt); +var c_stream: z_stream; (* compression stream *) + err: Integer; +begin + c_stream.zalloc := NIL; + c_stream.zfree := NIL; + c_stream.opaque := NIL; + + err := deflateInit(c_stream, Z_BEST_SPEED); + CHECK_ERR(err, 'deflateInit'); + + c_stream.next_out := compr; + c_stream.avail_out := Integer(comprLen); + + (* At this point, uncompr is still mostly zeroes, so it should compress + * very well: + *) + c_stream.next_in := uncompr; + c_stream.avail_in := Integer(uncomprLen); + err := deflate(c_stream, Z_NO_FLUSH); + CHECK_ERR(err, 'deflate'); + if c_stream.avail_in <> 0 then + EXIT_ERR('deflate not greedy'); + + (* Feed in already compressed data and switch to no compression: *) + deflateParams(c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); + c_stream.next_in := compr; + c_stream.avail_in := Integer(comprLen div 2); + err := deflate(c_stream, Z_NO_FLUSH); + CHECK_ERR(err, 'deflate'); + + (* Switch back to compressing mode: *) + deflateParams(c_stream, Z_BEST_COMPRESSION, Z_FILTERED); + c_stream.next_in := uncompr; + c_stream.avail_in := Integer(uncomprLen); + err := deflate(c_stream, Z_NO_FLUSH); + CHECK_ERR(err, 'deflate'); + + err := deflate(c_stream, Z_FINISH); + if err <> Z_STREAM_END then + EXIT_ERR('deflate should report Z_STREAM_END'); + + err := deflateEnd(c_stream); + CHECK_ERR(err, 'deflateEnd'); +end; +{$ENDIF} + +(* =========================================================================== + * Test inflate with large buffers + *) +{$IFDEF TEST_INFLATE} +procedure test_large_inflate(compr: Pointer; comprLen: LongInt; + uncompr: Pointer; uncomprLen: LongInt); +var err: Integer; + d_stream: z_stream; (* decompression stream *) +begin + StrCopy(PChar(uncompr), 'garbage'); + + d_stream.zalloc := NIL; + d_stream.zfree := NIL; + d_stream.opaque := NIL; + + d_stream.next_in := compr; + d_stream.avail_in := Integer(comprLen); + + err := inflateInit(d_stream); + CHECK_ERR(err, 'inflateInit'); + + while TRUE do + begin + d_stream.next_out := uncompr; (* discard the output *) + d_stream.avail_out := Integer(uncomprLen); + err := inflate(d_stream, Z_NO_FLUSH); + if err = Z_STREAM_END then + break; + CHECK_ERR(err, 'large inflate'); + end; + + err := inflateEnd(d_stream); + CHECK_ERR(err, 'inflateEnd'); + + if d_stream.total_out <> 2 * uncomprLen + comprLen div 2 then + begin + WriteLn('bad large inflate: ', d_stream.total_out); + Halt(1); + end + else + WriteLn('large_inflate(): OK'); +end; +{$ENDIF} + +(* =========================================================================== + * Test deflate with full flush + *) +{$IFDEF TEST_FLUSH} +procedure test_flush(compr: Pointer; var comprLen : LongInt); +var c_stream: z_stream; (* compression stream *) + err: Integer; + len: Integer; +begin + len := StrLen(hello)+1; + + c_stream.zalloc := NIL; + c_stream.zfree := NIL; + c_stream.opaque := NIL; + + err := deflateInit(c_stream, Z_DEFAULT_COMPRESSION); + CHECK_ERR(err, 'deflateInit'); + + c_stream.next_in := hello; + c_stream.next_out := compr; + c_stream.avail_in := 3; + c_stream.avail_out := Integer(comprLen); + err := deflate(c_stream, Z_FULL_FLUSH); + CHECK_ERR(err, 'deflate'); + + Inc(PByteArray(compr)^[3]); (* force an error in first compressed block *) + c_stream.avail_in := len - 3; + + err := deflate(c_stream, Z_FINISH); + if err <> Z_STREAM_END then + CHECK_ERR(err, 'deflate'); + + err := deflateEnd(c_stream); + CHECK_ERR(err, 'deflateEnd'); + + comprLen := c_stream.total_out; +end; +{$ENDIF} + +(* =========================================================================== + * Test inflateSync() + *) +{$IFDEF TEST_SYNC} +procedure test_sync(compr: Pointer; comprLen: LongInt; + uncompr: Pointer; uncomprLen : LongInt); +var err: Integer; + d_stream: z_stream; (* decompression stream *) +begin + StrCopy(PChar(uncompr), 'garbage'); + + d_stream.zalloc := NIL; + d_stream.zfree := NIL; + d_stream.opaque := NIL; + + d_stream.next_in := compr; + d_stream.avail_in := 2; (* just read the zlib header *) + + err := inflateInit(d_stream); + CHECK_ERR(err, 'inflateInit'); + + d_stream.next_out := uncompr; + d_stream.avail_out := Integer(uncomprLen); + + inflate(d_stream, Z_NO_FLUSH); + CHECK_ERR(err, 'inflate'); + + d_stream.avail_in := Integer(comprLen-2); (* read all compressed data *) + err := inflateSync(d_stream); (* but skip the damaged part *) + CHECK_ERR(err, 'inflateSync'); + + err := inflate(d_stream, Z_FINISH); + if err <> Z_DATA_ERROR then + EXIT_ERR('inflate should report DATA_ERROR'); + (* Because of incorrect adler32 *) + + err := inflateEnd(d_stream); + CHECK_ERR(err, 'inflateEnd'); + + WriteLn('after inflateSync(): hel', PChar(uncompr)); +end; +{$ENDIF} + +(* =========================================================================== + * Test deflate with preset dictionary + *) +{$IFDEF TEST_DICT} +procedure test_dict_deflate(compr: Pointer; comprLen: LongInt); +var c_stream: z_stream; (* compression stream *) + err: Integer; +begin + c_stream.zalloc := NIL; + c_stream.zfree := NIL; + c_stream.opaque := NIL; + + err := deflateInit(c_stream, Z_BEST_COMPRESSION); + CHECK_ERR(err, 'deflateInit'); + + err := deflateSetDictionary(c_stream, dictionary, StrLen(dictionary)); + CHECK_ERR(err, 'deflateSetDictionary'); + + dictId := c_stream.adler; + c_stream.next_out := compr; + c_stream.avail_out := Integer(comprLen); + + c_stream.next_in := hello; + c_stream.avail_in := StrLen(hello)+1; + + err := deflate(c_stream, Z_FINISH); + if err <> Z_STREAM_END then + EXIT_ERR('deflate should report Z_STREAM_END'); + + err := deflateEnd(c_stream); + CHECK_ERR(err, 'deflateEnd'); +end; +{$ENDIF} + +(* =========================================================================== + * Test inflate with a preset dictionary + *) +{$IFDEF TEST_DICT} +procedure test_dict_inflate(compr: Pointer; comprLen: LongInt; + uncompr: Pointer; uncomprLen: LongInt); +var err: Integer; + d_stream: z_stream; (* decompression stream *) +begin + StrCopy(PChar(uncompr), 'garbage'); + + d_stream.zalloc := NIL; + d_stream.zfree := NIL; + d_stream.opaque := NIL; + + d_stream.next_in := compr; + d_stream.avail_in := Integer(comprLen); + + err := inflateInit(d_stream); + CHECK_ERR(err, 'inflateInit'); + + d_stream.next_out := uncompr; + d_stream.avail_out := Integer(uncomprLen); + + while TRUE do + begin + err := inflate(d_stream, Z_NO_FLUSH); + if err = Z_STREAM_END then + break; + if err = Z_NEED_DICT then + begin + if d_stream.adler <> dictId then + EXIT_ERR('unexpected dictionary'); + err := inflateSetDictionary(d_stream, dictionary, StrLen(dictionary)); + end; + CHECK_ERR(err, 'inflate with dict'); + end; + + err := inflateEnd(d_stream); + CHECK_ERR(err, 'inflateEnd'); + + if StrComp(PChar(uncompr), hello) <> 0 then + EXIT_ERR('bad inflate with dict') + else + WriteLn('inflate with dictionary: ', PChar(uncompr)); +end; +{$ENDIF} + +var compr, uncompr: Pointer; + comprLen, uncomprLen: LongInt; + +begin + if zlibVersion^ <> ZLIB_VERSION[1] then + EXIT_ERR('Incompatible zlib version'); + + WriteLn('zlib version: ', zlibVersion); + WriteLn('zlib compile flags: ', Format('0x%x', [zlibCompileFlags])); + + comprLen := 10000 * SizeOf(Integer); (* don't overflow on MSDOS *) + uncomprLen := comprLen; + GetMem(compr, comprLen); + GetMem(uncompr, uncomprLen); + if (compr = NIL) or (uncompr = NIL) then + EXIT_ERR('Out of memory'); + (* compr and uncompr are cleared to avoid reading uninitialized + * data and to ensure that uncompr compresses well. + *) + FillChar(compr^, comprLen, 0); + FillChar(uncompr^, uncomprLen, 0); + + {$IFDEF TEST_COMPRESS} + WriteLn('** Testing compress'); + test_compress(compr, comprLen, uncompr, uncomprLen); + {$ENDIF} + + {$IFDEF TEST_GZIO} + WriteLn('** Testing gzio'); + if ParamCount >= 1 then + test_gzio(ParamStr(1), uncompr, uncomprLen) + else + test_gzio(TESTFILE, uncompr, uncomprLen); + {$ENDIF} + + {$IFDEF TEST_DEFLATE} + WriteLn('** Testing deflate with small buffers'); + test_deflate(compr, comprLen); + {$ENDIF} + {$IFDEF TEST_INFLATE} + WriteLn('** Testing inflate with small buffers'); + test_inflate(compr, comprLen, uncompr, uncomprLen); + {$ENDIF} + + {$IFDEF TEST_DEFLATE} + WriteLn('** Testing deflate with large buffers'); + test_large_deflate(compr, comprLen, uncompr, uncomprLen); + {$ENDIF} + {$IFDEF TEST_INFLATE} + WriteLn('** Testing inflate with large buffers'); + test_large_inflate(compr, comprLen, uncompr, uncomprLen); + {$ENDIF} + + {$IFDEF TEST_FLUSH} + WriteLn('** Testing deflate with full flush'); + test_flush(compr, comprLen); + {$ENDIF} + {$IFDEF TEST_SYNC} + WriteLn('** Testing inflateSync'); + test_sync(compr, comprLen, uncompr, uncomprLen); + {$ENDIF} + comprLen := uncomprLen; + + {$IFDEF TEST_DICT} + WriteLn('** Testing deflate and inflate with preset dictionary'); + test_dict_deflate(compr, comprLen); + test_dict_inflate(compr, comprLen, uncompr, uncomprLen); + {$ENDIF} + + FreeMem(compr, comprLen); + FreeMem(uncompr, uncomprLen); +end. diff --git a/dependencies/zlib-1.2.11/contrib/pascal/readme.txt b/dependencies/zlib-1.2.11/contrib/pascal/readme.txt new file mode 100644 index 0000000..60e87c8 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/pascal/readme.txt @@ -0,0 +1,76 @@ + +This directory contains a Pascal (Delphi, Kylix) interface to the +zlib data compression library. + + +Directory listing +================= + +zlibd32.mak makefile for Borland C++ +example.pas usage example of zlib +zlibpas.pas the Pascal interface to zlib +readme.txt this file + + +Compatibility notes +=================== + +- Although the name "zlib" would have been more normal for the + zlibpas unit, this name is already taken by Borland's ZLib unit. + This is somehow unfortunate, because that unit is not a genuine + interface to the full-fledged zlib functionality, but a suite of + class wrappers around zlib streams. Other essential features, + such as checksums, are missing. + It would have been more appropriate for that unit to have a name + like "ZStreams", or something similar. + +- The C and zlib-supplied types int, uInt, long, uLong, etc. are + translated directly into Pascal types of similar sizes (Integer, + LongInt, etc.), to avoid namespace pollution. In particular, + there is no conversion of unsigned int into a Pascal unsigned + integer. The Word type is non-portable and has the same size + (16 bits) both in a 16-bit and in a 32-bit environment, unlike + Integer. Even if there is a 32-bit Cardinal type, there is no + real need for unsigned int in zlib under a 32-bit environment. + +- Except for the callbacks, the zlib function interfaces are + assuming the calling convention normally used in Pascal + (__pascal for DOS and Windows16, __fastcall for Windows32). + Since the cdecl keyword is used, the old Turbo Pascal does + not work with this interface. + +- The gz* function interfaces are not translated, to avoid + interfacing problems with the C runtime library. Besides, + gzprintf(gzFile file, const char *format, ...) + cannot be translated into Pascal. + + +Legal issues +============ + +The zlibpas interface is: + Copyright (C) 1995-2003 Jean-loup Gailly and Mark Adler. + Copyright (C) 1998 by Bob Dellaca. + Copyright (C) 2003 by Cosmin Truta. + +The example program is: + Copyright (C) 1995-2003 by Jean-loup Gailly. + Copyright (C) 1998,1999,2000 by Jacques Nomssi Nzali. + Copyright (C) 2003 by Cosmin Truta. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the author be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + diff --git a/dependencies/zlib-1.2.11/contrib/pascal/zlibd32.mak b/dependencies/zlib-1.2.11/contrib/pascal/zlibd32.mak new file mode 100644 index 0000000..9bb00b7 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/pascal/zlibd32.mak @@ -0,0 +1,99 @@ +# Makefile for zlib +# For use with Delphi and C++ Builder under Win32 +# Updated for zlib 1.2.x by Cosmin Truta + +# ------------ Borland C++ ------------ + +# This project uses the Delphi (fastcall/register) calling convention: +LOC = -DZEXPORT=__fastcall -DZEXPORTVA=__cdecl + +CC = bcc32 +LD = bcc32 +AR = tlib +# do not use "-pr" in CFLAGS +CFLAGS = -a -d -k- -O2 $(LOC) +LDFLAGS = + + +# variables +ZLIB_LIB = zlib.lib + +OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj +OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj +OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj +OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj + + +# targets +all: $(ZLIB_LIB) example.exe minigzip.exe + +.c.obj: + $(CC) -c $(CFLAGS) $*.c + +adler32.obj: adler32.c zlib.h zconf.h + +compress.obj: compress.c zlib.h zconf.h + +crc32.obj: crc32.c zlib.h zconf.h crc32.h + +deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h + +gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h + +gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h + +gzread.obj: gzread.c zlib.h zconf.h gzguts.h + +gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h + +infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h inffixed.h + +inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h + +inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h inffixed.h + +inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h + +trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h + +uncompr.obj: uncompr.c zlib.h zconf.h + +zutil.obj: zutil.c zutil.h zlib.h zconf.h + +example.obj: test/example.c zlib.h zconf.h + +minigzip.obj: test/minigzip.c zlib.h zconf.h + + +# For the sake of the old Borland make, +# the command line is cut to fit in the MS-DOS 128 byte limit: +$(ZLIB_LIB): $(OBJ1) $(OBJ2) + -del $(ZLIB_LIB) + $(AR) $(ZLIB_LIB) $(OBJP1) + $(AR) $(ZLIB_LIB) $(OBJP2) + + +# testing +test: example.exe minigzip.exe + example + echo hello world | minigzip | minigzip -d + +example.exe: example.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) + +minigzip.exe: minigzip.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) + + +# cleanup +clean: + -del *.obj + -del *.exe + -del *.lib + -del *.tds + -del zlib.bak + -del foo.gz + diff --git a/dependencies/zlib-1.2.11/contrib/pascal/zlibpas.pas b/dependencies/zlib-1.2.11/contrib/pascal/zlibpas.pas new file mode 100644 index 0000000..a0dff11 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/pascal/zlibpas.pas @@ -0,0 +1,276 @@ +(* zlibpas -- Pascal interface to the zlib data compression library + * + * Copyright (C) 2003 Cosmin Truta. + * Derived from original sources by Bob Dellaca. + * For conditions of distribution and use, see copyright notice in readme.txt + *) + +unit zlibpas; + +interface + +const + ZLIB_VERSION = '1.2.11'; + ZLIB_VERNUM = $12a0; + +type + alloc_func = function(opaque: Pointer; items, size: Integer): Pointer; + cdecl; + free_func = procedure(opaque, address: Pointer); + cdecl; + + in_func = function(opaque: Pointer; var buf: PByte): Integer; + cdecl; + out_func = function(opaque: Pointer; buf: PByte; size: Integer): Integer; + cdecl; + + z_streamp = ^z_stream; + z_stream = packed record + next_in: PChar; (* next input byte *) + avail_in: Integer; (* number of bytes available at next_in *) + total_in: LongInt; (* total nb of input bytes read so far *) + + next_out: PChar; (* next output byte should be put there *) + avail_out: Integer; (* remaining free space at next_out *) + total_out: LongInt; (* total nb of bytes output so far *) + + msg: PChar; (* last error message, NULL if no error *) + state: Pointer; (* not visible by applications *) + + zalloc: alloc_func; (* used to allocate the internal state *) + zfree: free_func; (* used to free the internal state *) + opaque: Pointer; (* private data object passed to zalloc and zfree *) + + data_type: Integer; (* best guess about the data type: ascii or binary *) + adler: LongInt; (* adler32 value of the uncompressed data *) + reserved: LongInt; (* reserved for future use *) + end; + + gz_headerp = ^gz_header; + gz_header = packed record + text: Integer; (* true if compressed data believed to be text *) + time: LongInt; (* modification time *) + xflags: Integer; (* extra flags (not used when writing a gzip file) *) + os: Integer; (* operating system *) + extra: PChar; (* pointer to extra field or Z_NULL if none *) + extra_len: Integer; (* extra field length (valid if extra != Z_NULL) *) + extra_max: Integer; (* space at extra (only when reading header) *) + name: PChar; (* pointer to zero-terminated file name or Z_NULL *) + name_max: Integer; (* space at name (only when reading header) *) + comment: PChar; (* pointer to zero-terminated comment or Z_NULL *) + comm_max: Integer; (* space at comment (only when reading header) *) + hcrc: Integer; (* true if there was or will be a header crc *) + done: Integer; (* true when done reading gzip header *) + end; + +(* constants *) +const + Z_NO_FLUSH = 0; + Z_PARTIAL_FLUSH = 1; + Z_SYNC_FLUSH = 2; + Z_FULL_FLUSH = 3; + Z_FINISH = 4; + Z_BLOCK = 5; + Z_TREES = 6; + + Z_OK = 0; + Z_STREAM_END = 1; + Z_NEED_DICT = 2; + Z_ERRNO = -1; + Z_STREAM_ERROR = -2; + Z_DATA_ERROR = -3; + Z_MEM_ERROR = -4; + Z_BUF_ERROR = -5; + Z_VERSION_ERROR = -6; + + Z_NO_COMPRESSION = 0; + Z_BEST_SPEED = 1; + Z_BEST_COMPRESSION = 9; + Z_DEFAULT_COMPRESSION = -1; + + Z_FILTERED = 1; + Z_HUFFMAN_ONLY = 2; + Z_RLE = 3; + Z_FIXED = 4; + Z_DEFAULT_STRATEGY = 0; + + Z_BINARY = 0; + Z_TEXT = 1; + Z_ASCII = 1; + Z_UNKNOWN = 2; + + Z_DEFLATED = 8; + +(* basic functions *) +function zlibVersion: PChar; +function deflateInit(var strm: z_stream; level: Integer): Integer; +function deflate(var strm: z_stream; flush: Integer): Integer; +function deflateEnd(var strm: z_stream): Integer; +function inflateInit(var strm: z_stream): Integer; +function inflate(var strm: z_stream; flush: Integer): Integer; +function inflateEnd(var strm: z_stream): Integer; + +(* advanced functions *) +function deflateInit2(var strm: z_stream; level, method, windowBits, + memLevel, strategy: Integer): Integer; +function deflateSetDictionary(var strm: z_stream; const dictionary: PChar; + dictLength: Integer): Integer; +function deflateCopy(var dest, source: z_stream): Integer; +function deflateReset(var strm: z_stream): Integer; +function deflateParams(var strm: z_stream; level, strategy: Integer): Integer; +function deflateTune(var strm: z_stream; good_length, max_lazy, nice_length, max_chain: Integer): Integer; +function deflateBound(var strm: z_stream; sourceLen: LongInt): LongInt; +function deflatePending(var strm: z_stream; var pending: Integer; var bits: Integer): Integer; +function deflatePrime(var strm: z_stream; bits, value: Integer): Integer; +function deflateSetHeader(var strm: z_stream; head: gz_header): Integer; +function inflateInit2(var strm: z_stream; windowBits: Integer): Integer; +function inflateSetDictionary(var strm: z_stream; const dictionary: PChar; + dictLength: Integer): Integer; +function inflateSync(var strm: z_stream): Integer; +function inflateCopy(var dest, source: z_stream): Integer; +function inflateReset(var strm: z_stream): Integer; +function inflateReset2(var strm: z_stream; windowBits: Integer): Integer; +function inflatePrime(var strm: z_stream; bits, value: Integer): Integer; +function inflateMark(var strm: z_stream): LongInt; +function inflateGetHeader(var strm: z_stream; var head: gz_header): Integer; +function inflateBackInit(var strm: z_stream; + windowBits: Integer; window: PChar): Integer; +function inflateBack(var strm: z_stream; in_fn: in_func; in_desc: Pointer; + out_fn: out_func; out_desc: Pointer): Integer; +function inflateBackEnd(var strm: z_stream): Integer; +function zlibCompileFlags: LongInt; + +(* utility functions *) +function compress(dest: PChar; var destLen: LongInt; + const source: PChar; sourceLen: LongInt): Integer; +function compress2(dest: PChar; var destLen: LongInt; + const source: PChar; sourceLen: LongInt; + level: Integer): Integer; +function compressBound(sourceLen: LongInt): LongInt; +function uncompress(dest: PChar; var destLen: LongInt; + const source: PChar; sourceLen: LongInt): Integer; + +(* checksum functions *) +function adler32(adler: LongInt; const buf: PChar; len: Integer): LongInt; +function adler32_combine(adler1, adler2, len2: LongInt): LongInt; +function crc32(crc: LongInt; const buf: PChar; len: Integer): LongInt; +function crc32_combine(crc1, crc2, len2: LongInt): LongInt; + +(* various hacks, don't look :) *) +function deflateInit_(var strm: z_stream; level: Integer; + const version: PChar; stream_size: Integer): Integer; +function inflateInit_(var strm: z_stream; const version: PChar; + stream_size: Integer): Integer; +function deflateInit2_(var strm: z_stream; + level, method, windowBits, memLevel, strategy: Integer; + const version: PChar; stream_size: Integer): Integer; +function inflateInit2_(var strm: z_stream; windowBits: Integer; + const version: PChar; stream_size: Integer): Integer; +function inflateBackInit_(var strm: z_stream; + windowBits: Integer; window: PChar; + const version: PChar; stream_size: Integer): Integer; + + +implementation + +{$L adler32.obj} +{$L compress.obj} +{$L crc32.obj} +{$L deflate.obj} +{$L infback.obj} +{$L inffast.obj} +{$L inflate.obj} +{$L inftrees.obj} +{$L trees.obj} +{$L uncompr.obj} +{$L zutil.obj} + +function adler32; external; +function adler32_combine; external; +function compress; external; +function compress2; external; +function compressBound; external; +function crc32; external; +function crc32_combine; external; +function deflate; external; +function deflateBound; external; +function deflateCopy; external; +function deflateEnd; external; +function deflateInit_; external; +function deflateInit2_; external; +function deflateParams; external; +function deflatePending; external; +function deflatePrime; external; +function deflateReset; external; +function deflateSetDictionary; external; +function deflateSetHeader; external; +function deflateTune; external; +function inflate; external; +function inflateBack; external; +function inflateBackEnd; external; +function inflateBackInit_; external; +function inflateCopy; external; +function inflateEnd; external; +function inflateGetHeader; external; +function inflateInit_; external; +function inflateInit2_; external; +function inflateMark; external; +function inflatePrime; external; +function inflateReset; external; +function inflateReset2; external; +function inflateSetDictionary; external; +function inflateSync; external; +function uncompress; external; +function zlibCompileFlags; external; +function zlibVersion; external; + +function deflateInit(var strm: z_stream; level: Integer): Integer; +begin + Result := deflateInit_(strm, level, ZLIB_VERSION, sizeof(z_stream)); +end; + +function deflateInit2(var strm: z_stream; level, method, windowBits, memLevel, + strategy: Integer): Integer; +begin + Result := deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + ZLIB_VERSION, sizeof(z_stream)); +end; + +function inflateInit(var strm: z_stream): Integer; +begin + Result := inflateInit_(strm, ZLIB_VERSION, sizeof(z_stream)); +end; + +function inflateInit2(var strm: z_stream; windowBits: Integer): Integer; +begin + Result := inflateInit2_(strm, windowBits, ZLIB_VERSION, sizeof(z_stream)); +end; + +function inflateBackInit(var strm: z_stream; + windowBits: Integer; window: PChar): Integer; +begin + Result := inflateBackInit_(strm, windowBits, window, + ZLIB_VERSION, sizeof(z_stream)); +end; + +function _malloc(Size: Integer): Pointer; cdecl; +begin + GetMem(Result, Size); +end; + +procedure _free(Block: Pointer); cdecl; +begin + FreeMem(Block); +end; + +procedure _memset(P: Pointer; B: Byte; count: Integer); cdecl; +begin + FillChar(P^, count, B); +end; + +procedure _memcpy(dest, source: Pointer; count: Integer); cdecl; +begin + Move(source^, dest^, count); +end; + +end. diff --git a/dependencies/zlib-1.2.11/contrib/puff/Makefile b/dependencies/zlib-1.2.11/contrib/puff/Makefile new file mode 100644 index 0000000..0e2594c --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/puff/Makefile @@ -0,0 +1,42 @@ +CFLAGS=-O + +puff: puff.o pufftest.o + +puff.o: puff.h + +pufftest.o: puff.h + +test: puff + puff zeros.raw + +puft: puff.c puff.h pufftest.o + cc -fprofile-arcs -ftest-coverage -o puft puff.c pufftest.o + +# puff full coverage test (should say 100%) +cov: puft + @rm -f *.gcov *.gcda + @puft -w zeros.raw 2>&1 | cat > /dev/null + @echo '04' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 + @echo '00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 + @echo '00 00 00 00 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 254 + @echo '00 01 00 fe ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 + @echo '01 01 00 fe ff 0a' | xxd -r -p | puft -f 2>&1 | cat > /dev/null + @echo '02 7e ff ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 246 + @echo '02' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 + @echo '04 80 49 92 24 49 92 24 0f b4 ff ff c3 04' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 + @echo '04 80 49 92 24 49 92 24 71 ff ff 93 11 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 249 + @echo '04 c0 81 08 00 00 00 00 20 7f eb 0b 00 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 246 + @echo '0b 00 00' | xxd -r -p | puft -f 2>&1 | cat > /dev/null + @echo '1a 07' | xxd -r -p | puft 2> /dev/null || test $$? -eq 246 + @echo '0c c0 81 00 00 00 00 00 90 ff 6b 04' | xxd -r -p | puft 2> /dev/null || test $$? -eq 245 + @puft -f zeros.raw 2>&1 | cat > /dev/null + @echo 'fc 00 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 253 + @echo '04 00 fe ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 252 + @echo '04 00 24 49' | xxd -r -p | puft 2> /dev/null || test $$? -eq 251 + @echo '04 80 49 92 24 49 92 24 0f b4 ff ff c3 84' | xxd -r -p | puft 2> /dev/null || test $$? -eq 248 + @echo '04 00 24 e9 ff ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 250 + @echo '04 00 24 e9 ff 6d' | xxd -r -p | puft 2> /dev/null || test $$? -eq 247 + @gcov -n puff.c + +clean: + rm -f puff puft *.o *.gc* diff --git a/dependencies/zlib-1.2.11/contrib/puff/README b/dependencies/zlib-1.2.11/contrib/puff/README new file mode 100644 index 0000000..bbc4cb5 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/puff/README @@ -0,0 +1,63 @@ +Puff -- A Simple Inflate +3 Mar 2003 +Mark Adler +madler@alumni.caltech.edu + +What this is -- + +puff.c provides the routine puff() to decompress the deflate data format. It +does so more slowly than zlib, but the code is about one-fifth the size of the +inflate code in zlib, and written to be very easy to read. + +Why I wrote this -- + +puff.c was written to document the deflate format unambiguously, by virtue of +being working C code. It is meant to supplement RFC 1951, which formally +describes the deflate format. I have received many questions on details of the +deflate format, and I hope that reading this code will answer those questions. +puff.c is heavily commented with details of the deflate format, especially +those little nooks and cranies of the format that might not be obvious from a +specification. + +puff.c may also be useful in applications where code size or memory usage is a +very limited resource, and speed is not as important. + +How to use it -- + +Well, most likely you should just be reading puff.c and using zlib for actual +applications, but if you must ... + +Include puff.h in your code, which provides this prototype: + +int puff(unsigned char *dest, /* pointer to destination pointer */ + unsigned long *destlen, /* amount of output space */ + unsigned char *source, /* pointer to source data pointer */ + unsigned long *sourcelen); /* amount of input available */ + +Then you can call puff() to decompress a deflate stream that is in memory in +its entirety at source, to a sufficiently sized block of memory for the +decompressed data at dest. puff() is the only external symbol in puff.c The +only C library functions that puff.c needs are setjmp() and longjmp(), which +are used to simplify error checking in the code to improve readabilty. puff.c +does no memory allocation, and uses less than 2K bytes off of the stack. + +If destlen is not enough space for the uncompressed data, then inflate will +return an error without writing more than destlen bytes. Note that this means +that in order to decompress the deflate data successfully, you need to know +the size of the uncompressed data ahead of time. + +If needed, puff() can determine the size of the uncompressed data with no +output space. This is done by passing dest equal to (unsigned char *)0. Then +the initial value of *destlen is ignored and *destlen is set to the length of +the uncompressed data. So if the size of the uncompressed data is not known, +then two passes of puff() can be used--first to determine the size, and second +to do the actual inflation after allocating the appropriate memory. Not +pretty, but it works. (This is one of the reasons you should be using zlib.) + +The deflate format is self-terminating. If the deflate stream does not end +in *sourcelen bytes, puff() will return an error without reading at or past +endsource. + +On return, *sourcelen is updated to the amount of input data consumed, and +*destlen is updated to the size of the uncompressed data. See the comments +in puff.c for the possible return codes for puff(). diff --git a/dependencies/zlib-1.2.11/contrib/puff/puff.c b/dependencies/zlib-1.2.11/contrib/puff/puff.c new file mode 100644 index 0000000..c6c90d7 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/puff/puff.c @@ -0,0 +1,840 @@ +/* + * puff.c + * Copyright (C) 2002-2013 Mark Adler + * For conditions of distribution and use, see copyright notice in puff.h + * version 2.3, 21 Jan 2013 + * + * puff.c is a simple inflate written to be an unambiguous way to specify the + * deflate format. It is not written for speed but rather simplicity. As a + * side benefit, this code might actually be useful when small code is more + * important than speed, such as bootstrap applications. For typical deflate + * data, zlib's inflate() is about four times as fast as puff(). zlib's + * inflate compiles to around 20K on my machine, whereas puff.c compiles to + * around 4K on my machine (a PowerPC using GNU cc). If the faster decode() + * function here is used, then puff() is only twice as slow as zlib's + * inflate(). + * + * All dynamically allocated memory comes from the stack. The stack required + * is less than 2K bytes. This code is compatible with 16-bit int's and + * assumes that long's are at least 32 bits. puff.c uses the short data type, + * assumed to be 16 bits, for arrays in order to conserve memory. The code + * works whether integers are stored big endian or little endian. + * + * In the comments below are "Format notes" that describe the inflate process + * and document some of the less obvious aspects of the format. This source + * code is meant to supplement RFC 1951, which formally describes the deflate + * format: + * + * http://www.zlib.org/rfc-deflate.html + */ + +/* + * Change history: + * + * 1.0 10 Feb 2002 - First version + * 1.1 17 Feb 2002 - Clarifications of some comments and notes + * - Update puff() dest and source pointers on negative + * errors to facilitate debugging deflators + * - Remove longest from struct huffman -- not needed + * - Simplify offs[] index in construct() + * - Add input size and checking, using longjmp() to + * maintain easy readability + * - Use short data type for large arrays + * - Use pointers instead of long to specify source and + * destination sizes to avoid arbitrary 4 GB limits + * 1.2 17 Mar 2002 - Add faster version of decode(), doubles speed (!), + * but leave simple version for readabilty + * - Make sure invalid distances detected if pointers + * are 16 bits + * - Fix fixed codes table error + * - Provide a scanning mode for determining size of + * uncompressed data + * 1.3 20 Mar 2002 - Go back to lengths for puff() parameters [Gailly] + * - Add a puff.h file for the interface + * - Add braces in puff() for else do [Gailly] + * - Use indexes instead of pointers for readability + * 1.4 31 Mar 2002 - Simplify construct() code set check + * - Fix some comments + * - Add FIXLCODES #define + * 1.5 6 Apr 2002 - Minor comment fixes + * 1.6 7 Aug 2002 - Minor format changes + * 1.7 3 Mar 2003 - Added test code for distribution + * - Added zlib-like license + * 1.8 9 Jan 2004 - Added some comments on no distance codes case + * 1.9 21 Feb 2008 - Fix bug on 16-bit integer architectures [Pohland] + * - Catch missing end-of-block symbol error + * 2.0 25 Jul 2008 - Add #define to permit distance too far back + * - Add option in TEST code for puff to write the data + * - Add option in TEST code to skip input bytes + * - Allow TEST code to read from piped stdin + * 2.1 4 Apr 2010 - Avoid variable initialization for happier compilers + * - Avoid unsigned comparisons for even happier compilers + * 2.2 25 Apr 2010 - Fix bug in variable initializations [Oberhumer] + * - Add const where appropriate [Oberhumer] + * - Split if's and ?'s for coverage testing + * - Break out test code to separate file + * - Move NIL to puff.h + * - Allow incomplete code only if single code length is 1 + * - Add full code coverage test to Makefile + * 2.3 21 Jan 2013 - Check for invalid code length codes in dynamic blocks + */ + +#include /* for setjmp(), longjmp(), and jmp_buf */ +#include "puff.h" /* prototype for puff() */ + +#define local static /* for local function definitions */ + +/* + * Maximums for allocations and loops. It is not useful to change these -- + * they are fixed by the deflate format. + */ +#define MAXBITS 15 /* maximum bits in a code */ +#define MAXLCODES 286 /* maximum number of literal/length codes */ +#define MAXDCODES 30 /* maximum number of distance codes */ +#define MAXCODES (MAXLCODES+MAXDCODES) /* maximum codes lengths to read */ +#define FIXLCODES 288 /* number of fixed literal/length codes */ + +/* input and output state */ +struct state { + /* output state */ + unsigned char *out; /* output buffer */ + unsigned long outlen; /* available space at out */ + unsigned long outcnt; /* bytes written to out so far */ + + /* input state */ + const unsigned char *in; /* input buffer */ + unsigned long inlen; /* available input at in */ + unsigned long incnt; /* bytes read so far */ + int bitbuf; /* bit buffer */ + int bitcnt; /* number of bits in bit buffer */ + + /* input limit error return state for bits() and decode() */ + jmp_buf env; +}; + +/* + * Return need bits from the input stream. This always leaves less than + * eight bits in the buffer. bits() works properly for need == 0. + * + * Format notes: + * + * - Bits are stored in bytes from the least significant bit to the most + * significant bit. Therefore bits are dropped from the bottom of the bit + * buffer, using shift right, and new bytes are appended to the top of the + * bit buffer, using shift left. + */ +local int bits(struct state *s, int need) +{ + long val; /* bit accumulator (can use up to 20 bits) */ + + /* load at least need bits into val */ + val = s->bitbuf; + while (s->bitcnt < need) { + if (s->incnt == s->inlen) + longjmp(s->env, 1); /* out of input */ + val |= (long)(s->in[s->incnt++]) << s->bitcnt; /* load eight bits */ + s->bitcnt += 8; + } + + /* drop need bits and update buffer, always zero to seven bits left */ + s->bitbuf = (int)(val >> need); + s->bitcnt -= need; + + /* return need bits, zeroing the bits above that */ + return (int)(val & ((1L << need) - 1)); +} + +/* + * Process a stored block. + * + * Format notes: + * + * - After the two-bit stored block type (00), the stored block length and + * stored bytes are byte-aligned for fast copying. Therefore any leftover + * bits in the byte that has the last bit of the type, as many as seven, are + * discarded. The value of the discarded bits are not defined and should not + * be checked against any expectation. + * + * - The second inverted copy of the stored block length does not have to be + * checked, but it's probably a good idea to do so anyway. + * + * - A stored block can have zero length. This is sometimes used to byte-align + * subsets of the compressed data for random access or partial recovery. + */ +local int stored(struct state *s) +{ + unsigned len; /* length of stored block */ + + /* discard leftover bits from current byte (assumes s->bitcnt < 8) */ + s->bitbuf = 0; + s->bitcnt = 0; + + /* get length and check against its one's complement */ + if (s->incnt + 4 > s->inlen) + return 2; /* not enough input */ + len = s->in[s->incnt++]; + len |= s->in[s->incnt++] << 8; + if (s->in[s->incnt++] != (~len & 0xff) || + s->in[s->incnt++] != ((~len >> 8) & 0xff)) + return -2; /* didn't match complement! */ + + /* copy len bytes from in to out */ + if (s->incnt + len > s->inlen) + return 2; /* not enough input */ + if (s->out != NIL) { + if (s->outcnt + len > s->outlen) + return 1; /* not enough output space */ + while (len--) + s->out[s->outcnt++] = s->in[s->incnt++]; + } + else { /* just scanning */ + s->outcnt += len; + s->incnt += len; + } + + /* done with a valid stored block */ + return 0; +} + +/* + * Huffman code decoding tables. count[1..MAXBITS] is the number of symbols of + * each length, which for a canonical code are stepped through in order. + * symbol[] are the symbol values in canonical order, where the number of + * entries is the sum of the counts in count[]. The decoding process can be + * seen in the function decode() below. + */ +struct huffman { + short *count; /* number of symbols of each length */ + short *symbol; /* canonically ordered symbols */ +}; + +/* + * Decode a code from the stream s using huffman table h. Return the symbol or + * a negative value if there is an error. If all of the lengths are zero, i.e. + * an empty code, or if the code is incomplete and an invalid code is received, + * then -10 is returned after reading MAXBITS bits. + * + * Format notes: + * + * - The codes as stored in the compressed data are bit-reversed relative to + * a simple integer ordering of codes of the same lengths. Hence below the + * bits are pulled from the compressed data one at a time and used to + * build the code value reversed from what is in the stream in order to + * permit simple integer comparisons for decoding. A table-based decoding + * scheme (as used in zlib) does not need to do this reversal. + * + * - The first code for the shortest length is all zeros. Subsequent codes of + * the same length are simply integer increments of the previous code. When + * moving up a length, a zero bit is appended to the code. For a complete + * code, the last code of the longest length will be all ones. + * + * - Incomplete codes are handled by this decoder, since they are permitted + * in the deflate format. See the format notes for fixed() and dynamic(). + */ +#ifdef SLOW +local int decode(struct state *s, const struct huffman *h) +{ + int len; /* current number of bits in code */ + int code; /* len bits being decoded */ + int first; /* first code of length len */ + int count; /* number of codes of length len */ + int index; /* index of first code of length len in symbol table */ + + code = first = index = 0; + for (len = 1; len <= MAXBITS; len++) { + code |= bits(s, 1); /* get next bit */ + count = h->count[len]; + if (code - count < first) /* if length len, return symbol */ + return h->symbol[index + (code - first)]; + index += count; /* else update for next length */ + first += count; + first <<= 1; + code <<= 1; + } + return -10; /* ran out of codes */ +} + +/* + * A faster version of decode() for real applications of this code. It's not + * as readable, but it makes puff() twice as fast. And it only makes the code + * a few percent larger. + */ +#else /* !SLOW */ +local int decode(struct state *s, const struct huffman *h) +{ + int len; /* current number of bits in code */ + int code; /* len bits being decoded */ + int first; /* first code of length len */ + int count; /* number of codes of length len */ + int index; /* index of first code of length len in symbol table */ + int bitbuf; /* bits from stream */ + int left; /* bits left in next or left to process */ + short *next; /* next number of codes */ + + bitbuf = s->bitbuf; + left = s->bitcnt; + code = first = index = 0; + len = 1; + next = h->count + 1; + while (1) { + while (left--) { + code |= bitbuf & 1; + bitbuf >>= 1; + count = *next++; + if (code - count < first) { /* if length len, return symbol */ + s->bitbuf = bitbuf; + s->bitcnt = (s->bitcnt - len) & 7; + return h->symbol[index + (code - first)]; + } + index += count; /* else update for next length */ + first += count; + first <<= 1; + code <<= 1; + len++; + } + left = (MAXBITS+1) - len; + if (left == 0) + break; + if (s->incnt == s->inlen) + longjmp(s->env, 1); /* out of input */ + bitbuf = s->in[s->incnt++]; + if (left > 8) + left = 8; + } + return -10; /* ran out of codes */ +} +#endif /* SLOW */ + +/* + * Given the list of code lengths length[0..n-1] representing a canonical + * Huffman code for n symbols, construct the tables required to decode those + * codes. Those tables are the number of codes of each length, and the symbols + * sorted by length, retaining their original order within each length. The + * return value is zero for a complete code set, negative for an over- + * subscribed code set, and positive for an incomplete code set. The tables + * can be used if the return value is zero or positive, but they cannot be used + * if the return value is negative. If the return value is zero, it is not + * possible for decode() using that table to return an error--any stream of + * enough bits will resolve to a symbol. If the return value is positive, then + * it is possible for decode() using that table to return an error for received + * codes past the end of the incomplete lengths. + * + * Not used by decode(), but used for error checking, h->count[0] is the number + * of the n symbols not in the code. So n - h->count[0] is the number of + * codes. This is useful for checking for incomplete codes that have more than + * one symbol, which is an error in a dynamic block. + * + * Assumption: for all i in 0..n-1, 0 <= length[i] <= MAXBITS + * This is assured by the construction of the length arrays in dynamic() and + * fixed() and is not verified by construct(). + * + * Format notes: + * + * - Permitted and expected examples of incomplete codes are one of the fixed + * codes and any code with a single symbol which in deflate is coded as one + * bit instead of zero bits. See the format notes for fixed() and dynamic(). + * + * - Within a given code length, the symbols are kept in ascending order for + * the code bits definition. + */ +local int construct(struct huffman *h, const short *length, int n) +{ + int symbol; /* current symbol when stepping through length[] */ + int len; /* current length when stepping through h->count[] */ + int left; /* number of possible codes left of current length */ + short offs[MAXBITS+1]; /* offsets in symbol table for each length */ + + /* count number of codes of each length */ + for (len = 0; len <= MAXBITS; len++) + h->count[len] = 0; + for (symbol = 0; symbol < n; symbol++) + (h->count[length[symbol]])++; /* assumes lengths are within bounds */ + if (h->count[0] == n) /* no codes! */ + return 0; /* complete, but decode() will fail */ + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; /* one possible code of zero length */ + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; /* one more bit, double codes left */ + left -= h->count[len]; /* deduct count from possible codes */ + if (left < 0) + return left; /* over-subscribed--return negative */ + } /* left > 0 means incomplete */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + h->count[len]; + + /* + * put symbols in table sorted by length, by symbol order within each + * length + */ + for (symbol = 0; symbol < n; symbol++) + if (length[symbol] != 0) + h->symbol[offs[length[symbol]]++] = symbol; + + /* return zero for complete set, positive for incomplete set */ + return left; +} + +/* + * Decode literal/length and distance codes until an end-of-block code. + * + * Format notes: + * + * - Compressed data that is after the block type if fixed or after the code + * description if dynamic is a combination of literals and length/distance + * pairs terminated by and end-of-block code. Literals are simply Huffman + * coded bytes. A length/distance pair is a coded length followed by a + * coded distance to represent a string that occurs earlier in the + * uncompressed data that occurs again at the current location. + * + * - Literals, lengths, and the end-of-block code are combined into a single + * code of up to 286 symbols. They are 256 literals (0..255), 29 length + * symbols (257..285), and the end-of-block symbol (256). + * + * - There are 256 possible lengths (3..258), and so 29 symbols are not enough + * to represent all of those. Lengths 3..10 and 258 are in fact represented + * by just a length symbol. Lengths 11..257 are represented as a symbol and + * some number of extra bits that are added as an integer to the base length + * of the length symbol. The number of extra bits is determined by the base + * length symbol. These are in the static arrays below, lens[] for the base + * lengths and lext[] for the corresponding number of extra bits. + * + * - The reason that 258 gets its own symbol is that the longest length is used + * often in highly redundant files. Note that 258 can also be coded as the + * base value 227 plus the maximum extra value of 31. While a good deflate + * should never do this, it is not an error, and should be decoded properly. + * + * - If a length is decoded, including its extra bits if any, then it is + * followed a distance code. There are up to 30 distance symbols. Again + * there are many more possible distances (1..32768), so extra bits are added + * to a base value represented by the symbol. The distances 1..4 get their + * own symbol, but the rest require extra bits. The base distances and + * corresponding number of extra bits are below in the static arrays dist[] + * and dext[]. + * + * - Literal bytes are simply written to the output. A length/distance pair is + * an instruction to copy previously uncompressed bytes to the output. The + * copy is from distance bytes back in the output stream, copying for length + * bytes. + * + * - Distances pointing before the beginning of the output data are not + * permitted. + * + * - Overlapped copies, where the length is greater than the distance, are + * allowed and common. For example, a distance of one and a length of 258 + * simply copies the last byte 258 times. A distance of four and a length of + * twelve copies the last four bytes three times. A simple forward copy + * ignoring whether the length is greater than the distance or not implements + * this correctly. You should not use memcpy() since its behavior is not + * defined for overlapped arrays. You should not use memmove() or bcopy() + * since though their behavior -is- defined for overlapping arrays, it is + * defined to do the wrong thing in this case. + */ +local int codes(struct state *s, + const struct huffman *lencode, + const struct huffman *distcode) +{ + int symbol; /* decoded symbol */ + int len; /* length for copy */ + unsigned dist; /* distance for copy */ + static const short lens[29] = { /* Size base for length codes 257..285 */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258}; + static const short lext[29] = { /* Extra bits for length codes 257..285 */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0}; + static const short dists[30] = { /* Offset base for distance codes 0..29 */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577}; + static const short dext[30] = { /* Extra bits for distance codes 0..29 */ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13}; + + /* decode literals and length/distance pairs */ + do { + symbol = decode(s, lencode); + if (symbol < 0) + return symbol; /* invalid symbol */ + if (symbol < 256) { /* literal: symbol is the byte */ + /* write out the literal */ + if (s->out != NIL) { + if (s->outcnt == s->outlen) + return 1; + s->out[s->outcnt] = symbol; + } + s->outcnt++; + } + else if (symbol > 256) { /* length */ + /* get and compute length */ + symbol -= 257; + if (symbol >= 29) + return -10; /* invalid fixed code */ + len = lens[symbol] + bits(s, lext[symbol]); + + /* get and check distance */ + symbol = decode(s, distcode); + if (symbol < 0) + return symbol; /* invalid symbol */ + dist = dists[symbol] + bits(s, dext[symbol]); +#ifndef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + if (dist > s->outcnt) + return -11; /* distance too far back */ +#endif + + /* copy length bytes from distance bytes back */ + if (s->out != NIL) { + if (s->outcnt + len > s->outlen) + return 1; + while (len--) { + s->out[s->outcnt] = +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + dist > s->outcnt ? + 0 : +#endif + s->out[s->outcnt - dist]; + s->outcnt++; + } + } + else + s->outcnt += len; + } + } while (symbol != 256); /* end of block symbol */ + + /* done with a valid fixed or dynamic block */ + return 0; +} + +/* + * Process a fixed codes block. + * + * Format notes: + * + * - This block type can be useful for compressing small amounts of data for + * which the size of the code descriptions in a dynamic block exceeds the + * benefit of custom codes for that block. For fixed codes, no bits are + * spent on code descriptions. Instead the code lengths for literal/length + * codes and distance codes are fixed. The specific lengths for each symbol + * can be seen in the "for" loops below. + * + * - The literal/length code is complete, but has two symbols that are invalid + * and should result in an error if received. This cannot be implemented + * simply as an incomplete code since those two symbols are in the "middle" + * of the code. They are eight bits long and the longest literal/length\ + * code is nine bits. Therefore the code must be constructed with those + * symbols, and the invalid symbols must be detected after decoding. + * + * - The fixed distance codes also have two invalid symbols that should result + * in an error if received. Since all of the distance codes are the same + * length, this can be implemented as an incomplete code. Then the invalid + * codes are detected while decoding. + */ +local int fixed(struct state *s) +{ + static int virgin = 1; + static short lencnt[MAXBITS+1], lensym[FIXLCODES]; + static short distcnt[MAXBITS+1], distsym[MAXDCODES]; + static struct huffman lencode, distcode; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + int symbol; + short lengths[FIXLCODES]; + + /* construct lencode and distcode */ + lencode.count = lencnt; + lencode.symbol = lensym; + distcode.count = distcnt; + distcode.symbol = distsym; + + /* literal/length table */ + for (symbol = 0; symbol < 144; symbol++) + lengths[symbol] = 8; + for (; symbol < 256; symbol++) + lengths[symbol] = 9; + for (; symbol < 280; symbol++) + lengths[symbol] = 7; + for (; symbol < FIXLCODES; symbol++) + lengths[symbol] = 8; + construct(&lencode, lengths, FIXLCODES); + + /* distance table */ + for (symbol = 0; symbol < MAXDCODES; symbol++) + lengths[symbol] = 5; + construct(&distcode, lengths, MAXDCODES); + + /* do this just once */ + virgin = 0; + } + + /* decode data until end-of-block code */ + return codes(s, &lencode, &distcode); +} + +/* + * Process a dynamic codes block. + * + * Format notes: + * + * - A dynamic block starts with a description of the literal/length and + * distance codes for that block. New dynamic blocks allow the compressor to + * rapidly adapt to changing data with new codes optimized for that data. + * + * - The codes used by the deflate format are "canonical", which means that + * the actual bits of the codes are generated in an unambiguous way simply + * from the number of bits in each code. Therefore the code descriptions + * are simply a list of code lengths for each symbol. + * + * - The code lengths are stored in order for the symbols, so lengths are + * provided for each of the literal/length symbols, and for each of the + * distance symbols. + * + * - If a symbol is not used in the block, this is represented by a zero as + * as the code length. This does not mean a zero-length code, but rather + * that no code should be created for this symbol. There is no way in the + * deflate format to represent a zero-length code. + * + * - The maximum number of bits in a code is 15, so the possible lengths for + * any code are 1..15. + * + * - The fact that a length of zero is not permitted for a code has an + * interesting consequence. Normally if only one symbol is used for a given + * code, then in fact that code could be represented with zero bits. However + * in deflate, that code has to be at least one bit. So for example, if + * only a single distance base symbol appears in a block, then it will be + * represented by a single code of length one, in particular one 0 bit. This + * is an incomplete code, since if a 1 bit is received, it has no meaning, + * and should result in an error. So incomplete distance codes of one symbol + * should be permitted, and the receipt of invalid codes should be handled. + * + * - It is also possible to have a single literal/length code, but that code + * must be the end-of-block code, since every dynamic block has one. This + * is not the most efficient way to create an empty block (an empty fixed + * block is fewer bits), but it is allowed by the format. So incomplete + * literal/length codes of one symbol should also be permitted. + * + * - If there are only literal codes and no lengths, then there are no distance + * codes. This is represented by one distance code with zero bits. + * + * - The list of up to 286 length/literal lengths and up to 30 distance lengths + * are themselves compressed using Huffman codes and run-length encoding. In + * the list of code lengths, a 0 symbol means no code, a 1..15 symbol means + * that length, and the symbols 16, 17, and 18 are run-length instructions. + * Each of 16, 17, and 18 are follwed by extra bits to define the length of + * the run. 16 copies the last length 3 to 6 times. 17 represents 3 to 10 + * zero lengths, and 18 represents 11 to 138 zero lengths. Unused symbols + * are common, hence the special coding for zero lengths. + * + * - The symbols for 0..18 are Huffman coded, and so that code must be + * described first. This is simply a sequence of up to 19 three-bit values + * representing no code (0) or the code length for that symbol (1..7). + * + * - A dynamic block starts with three fixed-size counts from which is computed + * the number of literal/length code lengths, the number of distance code + * lengths, and the number of code length code lengths (ok, you come up with + * a better name!) in the code descriptions. For the literal/length and + * distance codes, lengths after those provided are considered zero, i.e. no + * code. The code length code lengths are received in a permuted order (see + * the order[] array below) to make a short code length code length list more + * likely. As it turns out, very short and very long codes are less likely + * to be seen in a dynamic code description, hence what may appear initially + * to be a peculiar ordering. + * + * - Given the number of literal/length code lengths (nlen) and distance code + * lengths (ndist), then they are treated as one long list of nlen + ndist + * code lengths. Therefore run-length coding can and often does cross the + * boundary between the two sets of lengths. + * + * - So to summarize, the code description at the start of a dynamic block is + * three counts for the number of code lengths for the literal/length codes, + * the distance codes, and the code length codes. This is followed by the + * code length code lengths, three bits each. This is used to construct the + * code length code which is used to read the remainder of the lengths. Then + * the literal/length code lengths and distance lengths are read as a single + * set of lengths using the code length codes. Codes are constructed from + * the resulting two sets of lengths, and then finally you can start + * decoding actual compressed data in the block. + * + * - For reference, a "typical" size for the code description in a dynamic + * block is around 80 bytes. + */ +local int dynamic(struct state *s) +{ + int nlen, ndist, ncode; /* number of lengths in descriptor */ + int index; /* index of lengths[] */ + int err; /* construct() return value */ + short lengths[MAXCODES]; /* descriptor code lengths */ + short lencnt[MAXBITS+1], lensym[MAXLCODES]; /* lencode memory */ + short distcnt[MAXBITS+1], distsym[MAXDCODES]; /* distcode memory */ + struct huffman lencode, distcode; /* length and distance codes */ + static const short order[19] = /* permutation of code length codes */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* construct lencode and distcode */ + lencode.count = lencnt; + lencode.symbol = lensym; + distcode.count = distcnt; + distcode.symbol = distsym; + + /* get number of lengths in each table, check lengths */ + nlen = bits(s, 5) + 257; + ndist = bits(s, 5) + 1; + ncode = bits(s, 4) + 4; + if (nlen > MAXLCODES || ndist > MAXDCODES) + return -3; /* bad counts */ + + /* read code length code lengths (really), missing lengths are zero */ + for (index = 0; index < ncode; index++) + lengths[order[index]] = bits(s, 3); + for (; index < 19; index++) + lengths[order[index]] = 0; + + /* build huffman table for code lengths codes (use lencode temporarily) */ + err = construct(&lencode, lengths, 19); + if (err != 0) /* require complete code set here */ + return -4; + + /* read length/literal and distance code length tables */ + index = 0; + while (index < nlen + ndist) { + int symbol; /* decoded value */ + int len; /* last length to repeat */ + + symbol = decode(s, &lencode); + if (symbol < 0) + return symbol; /* invalid symbol */ + if (symbol < 16) /* length in 0..15 */ + lengths[index++] = symbol; + else { /* repeat instruction */ + len = 0; /* assume repeating zeros */ + if (symbol == 16) { /* repeat last length 3..6 times */ + if (index == 0) + return -5; /* no last length! */ + len = lengths[index - 1]; /* last length */ + symbol = 3 + bits(s, 2); + } + else if (symbol == 17) /* repeat zero 3..10 times */ + symbol = 3 + bits(s, 3); + else /* == 18, repeat zero 11..138 times */ + symbol = 11 + bits(s, 7); + if (index + symbol > nlen + ndist) + return -6; /* too many lengths! */ + while (symbol--) /* repeat last or zero symbol times */ + lengths[index++] = len; + } + } + + /* check for end-of-block code -- there better be one! */ + if (lengths[256] == 0) + return -9; + + /* build huffman table for literal/length codes */ + err = construct(&lencode, lengths, nlen); + if (err && (err < 0 || nlen != lencode.count[0] + lencode.count[1])) + return -7; /* incomplete code ok only for single length 1 code */ + + /* build huffman table for distance codes */ + err = construct(&distcode, lengths + nlen, ndist); + if (err && (err < 0 || ndist != distcode.count[0] + distcode.count[1])) + return -8; /* incomplete code ok only for single length 1 code */ + + /* decode data until end-of-block code */ + return codes(s, &lencode, &distcode); +} + +/* + * Inflate source to dest. On return, destlen and sourcelen are updated to the + * size of the uncompressed data and the size of the deflate data respectively. + * On success, the return value of puff() is zero. If there is an error in the + * source data, i.e. it is not in the deflate format, then a negative value is + * returned. If there is not enough input available or there is not enough + * output space, then a positive error is returned. In that case, destlen and + * sourcelen are not updated to facilitate retrying from the beginning with the + * provision of more input data or more output space. In the case of invalid + * inflate data (a negative error), the dest and source pointers are updated to + * facilitate the debugging of deflators. + * + * puff() also has a mode to determine the size of the uncompressed output with + * no output written. For this dest must be (unsigned char *)0. In this case, + * the input value of *destlen is ignored, and on return *destlen is set to the + * size of the uncompressed output. + * + * The return codes are: + * + * 2: available inflate data did not terminate + * 1: output space exhausted before completing inflate + * 0: successful inflate + * -1: invalid block type (type == 3) + * -2: stored block length did not match one's complement + * -3: dynamic block code description: too many length or distance codes + * -4: dynamic block code description: code lengths codes incomplete + * -5: dynamic block code description: repeat lengths with no first length + * -6: dynamic block code description: repeat more than specified lengths + * -7: dynamic block code description: invalid literal/length code lengths + * -8: dynamic block code description: invalid distance code lengths + * -9: dynamic block code description: missing end-of-block code + * -10: invalid literal/length or distance code in fixed or dynamic block + * -11: distance is too far back in fixed or dynamic block + * + * Format notes: + * + * - Three bits are read for each block to determine the kind of block and + * whether or not it is the last block. Then the block is decoded and the + * process repeated if it was not the last block. + * + * - The leftover bits in the last byte of the deflate data after the last + * block (if it was a fixed or dynamic block) are undefined and have no + * expected values to check. + */ +int puff(unsigned char *dest, /* pointer to destination pointer */ + unsigned long *destlen, /* amount of output space */ + const unsigned char *source, /* pointer to source data pointer */ + unsigned long *sourcelen) /* amount of input available */ +{ + struct state s; /* input/output state */ + int last, type; /* block information */ + int err; /* return value */ + + /* initialize output state */ + s.out = dest; + s.outlen = *destlen; /* ignored if dest is NIL */ + s.outcnt = 0; + + /* initialize input state */ + s.in = source; + s.inlen = *sourcelen; + s.incnt = 0; + s.bitbuf = 0; + s.bitcnt = 0; + + /* return if bits() or decode() tries to read past available input */ + if (setjmp(s.env) != 0) /* if came back here via longjmp() */ + err = 2; /* then skip do-loop, return error */ + else { + /* process blocks until last block or error */ + do { + last = bits(&s, 1); /* one if last block */ + type = bits(&s, 2); /* block type 0..3 */ + err = type == 0 ? + stored(&s) : + (type == 1 ? + fixed(&s) : + (type == 2 ? + dynamic(&s) : + -1)); /* type == 3, invalid */ + if (err != 0) + break; /* return with error */ + } while (!last); + } + + /* update the lengths and return */ + if (err <= 0) { + *destlen = s.outcnt; + *sourcelen = s.incnt; + } + return err; +} diff --git a/dependencies/zlib-1.2.11/contrib/puff/puff.h b/dependencies/zlib-1.2.11/contrib/puff/puff.h new file mode 100644 index 0000000..e23a245 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/puff/puff.h @@ -0,0 +1,35 @@ +/* puff.h + Copyright (C) 2002-2013 Mark Adler, all rights reserved + version 2.3, 21 Jan 2013 + + This software is provided 'as-is', without any express or implied + warranty. In no event will the author be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Mark Adler madler@alumni.caltech.edu + */ + + +/* + * See puff.c for purpose and usage. + */ +#ifndef NIL +# define NIL ((unsigned char *)0) /* for no output option */ +#endif + +int puff(unsigned char *dest, /* pointer to destination pointer */ + unsigned long *destlen, /* amount of output space */ + const unsigned char *source, /* pointer to source data pointer */ + unsigned long *sourcelen); /* amount of input available */ diff --git a/dependencies/zlib-1.2.11/contrib/puff/pufftest.c b/dependencies/zlib-1.2.11/contrib/puff/pufftest.c new file mode 100644 index 0000000..7764814 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/puff/pufftest.c @@ -0,0 +1,165 @@ +/* + * pufftest.c + * Copyright (C) 2002-2013 Mark Adler + * For conditions of distribution and use, see copyright notice in puff.h + * version 2.3, 21 Jan 2013 + */ + +/* Example of how to use puff(). + + Usage: puff [-w] [-f] [-nnn] file + ... | puff [-w] [-f] [-nnn] + + where file is the input file with deflate data, nnn is the number of bytes + of input to skip before inflating (e.g. to skip a zlib or gzip header), and + -w is used to write the decompressed data to stdout. -f is for coverage + testing, and causes pufftest to fail with not enough output space (-f does + a write like -w, so -w is not required). */ + +#include +#include +#include "puff.h" + +#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) +# include +# include +# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) +#else +# define SET_BINARY_MODE(file) +#endif + +#define local static + +/* Return size times approximately the cube root of 2, keeping the result as 1, + 3, or 5 times a power of 2 -- the result is always > size, until the result + is the maximum value of an unsigned long, where it remains. This is useful + to keep reallocations less than ~33% over the actual data. */ +local size_t bythirds(size_t size) +{ + int n; + size_t m; + + m = size; + for (n = 0; m; n++) + m >>= 1; + if (n < 3) + return size + 1; + n -= 3; + m = size >> n; + m += m == 6 ? 2 : 1; + m <<= n; + return m > size ? m : (size_t)(-1); +} + +/* Read the input file *name, or stdin if name is NULL, into allocated memory. + Reallocate to larger buffers until the entire file is read in. Return a + pointer to the allocated data, or NULL if there was a memory allocation + failure. *len is the number of bytes of data read from the input file (even + if load() returns NULL). If the input file was empty or could not be opened + or read, *len is zero. */ +local void *load(const char *name, size_t *len) +{ + size_t size; + void *buf, *swap; + FILE *in; + + *len = 0; + buf = malloc(size = 4096); + if (buf == NULL) + return NULL; + in = name == NULL ? stdin : fopen(name, "rb"); + if (in != NULL) { + for (;;) { + *len += fread((char *)buf + *len, 1, size - *len, in); + if (*len < size) break; + size = bythirds(size); + if (size == *len || (swap = realloc(buf, size)) == NULL) { + free(buf); + buf = NULL; + break; + } + buf = swap; + } + fclose(in); + } + return buf; +} + +int main(int argc, char **argv) +{ + int ret, put = 0, fail = 0; + unsigned skip = 0; + char *arg, *name = NULL; + unsigned char *source = NULL, *dest; + size_t len = 0; + unsigned long sourcelen, destlen; + + /* process arguments */ + while (arg = *++argv, --argc) + if (arg[0] == '-') { + if (arg[1] == 'w' && arg[2] == 0) + put = 1; + else if (arg[1] == 'f' && arg[2] == 0) + fail = 1, put = 1; + else if (arg[1] >= '0' && arg[1] <= '9') + skip = (unsigned)atoi(arg + 1); + else { + fprintf(stderr, "invalid option %s\n", arg); + return 3; + } + } + else if (name != NULL) { + fprintf(stderr, "only one file name allowed\n"); + return 3; + } + else + name = arg; + source = load(name, &len); + if (source == NULL) { + fprintf(stderr, "memory allocation failure\n"); + return 4; + } + if (len == 0) { + fprintf(stderr, "could not read %s, or it was empty\n", + name == NULL ? "" : name); + free(source); + return 3; + } + if (skip >= len) { + fprintf(stderr, "skip request of %d leaves no input\n", skip); + free(source); + return 3; + } + + /* test inflate data with offset skip */ + len -= skip; + sourcelen = (unsigned long)len; + ret = puff(NIL, &destlen, source + skip, &sourcelen); + if (ret) + fprintf(stderr, "puff() failed with return code %d\n", ret); + else { + fprintf(stderr, "puff() succeeded uncompressing %lu bytes\n", destlen); + if (sourcelen < len) fprintf(stderr, "%lu compressed bytes unused\n", + len - sourcelen); + } + + /* if requested, inflate again and write decompressd data to stdout */ + if (put && ret == 0) { + if (fail) + destlen >>= 1; + dest = malloc(destlen); + if (dest == NULL) { + fprintf(stderr, "memory allocation failure\n"); + free(source); + return 4; + } + puff(dest, &destlen, source + skip, &sourcelen); + SET_BINARY_MODE(stdout); + fwrite(dest, 1, destlen, stdout); + free(dest); + } + + /* clean up */ + free(source); + return ret; +} diff --git a/dependencies/zlib-1.2.11/contrib/puff/zeros.raw b/dependencies/zlib-1.2.11/contrib/puff/zeros.raw new file mode 100644 index 0000000..0a90e76 Binary files /dev/null and b/dependencies/zlib-1.2.11/contrib/puff/zeros.raw differ diff --git a/dependencies/zlib-1.2.11/contrib/testzlib/testzlib.c b/dependencies/zlib-1.2.11/contrib/testzlib/testzlib.c new file mode 100644 index 0000000..5f659de --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/testzlib/testzlib.c @@ -0,0 +1,275 @@ +#include +#include +#include + +#include "zlib.h" + + +void MyDoMinus64(LARGE_INTEGER *R,LARGE_INTEGER A,LARGE_INTEGER B) +{ + R->HighPart = A.HighPart - B.HighPart; + if (A.LowPart >= B.LowPart) + R->LowPart = A.LowPart - B.LowPart; + else + { + R->LowPart = A.LowPart - B.LowPart; + R->HighPart --; + } +} + +#ifdef _M_X64 +// see http://msdn2.microsoft.com/library/twchhe95(en-us,vs.80).aspx for __rdtsc +unsigned __int64 __rdtsc(void); +void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) +{ + // printf("rdtsc = %I64x\n",__rdtsc()); + pbeginTime64->QuadPart=__rdtsc(); +} + +LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) +{ + LARGE_INTEGER LIres; + unsigned _int64 res=__rdtsc()-((unsigned _int64)(beginTime64.QuadPart)); + LIres.QuadPart=res; + // printf("rdtsc = %I64x\n",__rdtsc()); + return LIres; +} +#else +#ifdef _M_IX86 +void myGetRDTSC32(LARGE_INTEGER * pbeginTime64) +{ + DWORD dwEdx,dwEax; + _asm + { + rdtsc + mov dwEax,eax + mov dwEdx,edx + } + pbeginTime64->LowPart=dwEax; + pbeginTime64->HighPart=dwEdx; +} + +void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) +{ + myGetRDTSC32(pbeginTime64); +} + +LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) +{ + LARGE_INTEGER LIres,endTime64; + myGetRDTSC32(&endTime64); + + LIres.LowPart=LIres.HighPart=0; + MyDoMinus64(&LIres,endTime64,beginTime64); + return LIres; +} +#else +void myGetRDTSC32(LARGE_INTEGER * pbeginTime64) +{ +} + +void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) +{ +} + +LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) +{ + LARGE_INTEGER lr; + lr.QuadPart=0; + return lr; +} +#endif +#endif + +void BeginCountPerfCounter(LARGE_INTEGER * pbeginTime64,BOOL fComputeTimeQueryPerf) +{ + if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(pbeginTime64))) + { + pbeginTime64->LowPart = GetTickCount(); + pbeginTime64->HighPart = 0; + } +} + +DWORD GetMsecSincePerfCounter(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) +{ + LARGE_INTEGER endTime64,ticksPerSecond,ticks; + DWORDLONG ticksShifted,tickSecShifted; + DWORD dwLog=16+0; + DWORD dwRet; + if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(&endTime64))) + dwRet = (GetTickCount() - beginTime64.LowPart)*1; + else + { + MyDoMinus64(&ticks,endTime64,beginTime64); + QueryPerformanceFrequency(&ticksPerSecond); + + + { + ticksShifted = Int64ShrlMod32(*(DWORDLONG*)&ticks,dwLog); + tickSecShifted = Int64ShrlMod32(*(DWORDLONG*)&ticksPerSecond,dwLog); + + } + + dwRet = (DWORD)((((DWORD)ticksShifted)*1000)/(DWORD)(tickSecShifted)); + dwRet *=1; + } + return dwRet; +} + +int ReadFileMemory(const char* filename,long* plFileSize,unsigned char** pFilePtr) +{ + FILE* stream; + unsigned char* ptr; + int retVal=1; + stream=fopen(filename, "rb"); + if (stream==NULL) + return 0; + + fseek(stream,0,SEEK_END); + + *plFileSize=ftell(stream); + fseek(stream,0,SEEK_SET); + ptr=malloc((*plFileSize)+1); + if (ptr==NULL) + retVal=0; + else + { + if (fread(ptr, 1, *plFileSize,stream) != (*plFileSize)) + retVal=0; + } + fclose(stream); + *pFilePtr=ptr; + return retVal; +} + +int main(int argc, char *argv[]) +{ + int BlockSizeCompress=0x8000; + int BlockSizeUncompress=0x8000; + int cprLevel=Z_DEFAULT_COMPRESSION ; + long lFileSize; + unsigned char* FilePtr; + long lBufferSizeCpr; + long lBufferSizeUncpr; + long lCompressedSize=0; + unsigned char* CprPtr; + unsigned char* UncprPtr; + long lSizeCpr,lSizeUncpr; + DWORD dwGetTick,dwMsecQP; + LARGE_INTEGER li_qp,li_rdtsc,dwResRdtsc; + + if (argc<=1) + { + printf("run TestZlib [BlockSizeCompress] [BlockSizeUncompress] [compres. level]\n"); + return 0; + } + + if (ReadFileMemory(argv[1],&lFileSize,&FilePtr)==0) + { + printf("error reading %s\n",argv[1]); + return 1; + } + else printf("file %s read, %u bytes\n",argv[1],lFileSize); + + if (argc>=3) + BlockSizeCompress=atol(argv[2]); + + if (argc>=4) + BlockSizeUncompress=atol(argv[3]); + + if (argc>=5) + cprLevel=(int)atol(argv[4]); + + lBufferSizeCpr = lFileSize + (lFileSize/0x10) + 0x200; + lBufferSizeUncpr = lBufferSizeCpr; + + CprPtr=(unsigned char*)malloc(lBufferSizeCpr + BlockSizeCompress); + + BeginCountPerfCounter(&li_qp,TRUE); + dwGetTick=GetTickCount(); + BeginCountRdtsc(&li_rdtsc); + { + z_stream zcpr; + int ret=Z_OK; + long lOrigToDo = lFileSize; + long lOrigDone = 0; + int step=0; + memset(&zcpr,0,sizeof(z_stream)); + deflateInit(&zcpr,cprLevel); + + zcpr.next_in = FilePtr; + zcpr.next_out = CprPtr; + + + do + { + long all_read_before = zcpr.total_in; + zcpr.avail_in = min(lOrigToDo,BlockSizeCompress); + zcpr.avail_out = BlockSizeCompress; + ret=deflate(&zcpr,(zcpr.avail_in==lOrigToDo) ? Z_FINISH : Z_SYNC_FLUSH); + lOrigDone += (zcpr.total_in-all_read_before); + lOrigToDo -= (zcpr.total_in-all_read_before); + step++; + } while (ret==Z_OK); + + lSizeCpr=zcpr.total_out; + deflateEnd(&zcpr); + dwGetTick=GetTickCount()-dwGetTick; + dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE); + dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE); + printf("total compress size = %u, in %u step\n",lSizeCpr,step); + printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.); + printf("defcpr time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.); + printf("defcpr result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart); + } + + CprPtr=(unsigned char*)realloc(CprPtr,lSizeCpr); + UncprPtr=(unsigned char*)malloc(lBufferSizeUncpr + BlockSizeUncompress); + + BeginCountPerfCounter(&li_qp,TRUE); + dwGetTick=GetTickCount(); + BeginCountRdtsc(&li_rdtsc); + { + z_stream zcpr; + int ret=Z_OK; + long lOrigToDo = lSizeCpr; + long lOrigDone = 0; + int step=0; + memset(&zcpr,0,sizeof(z_stream)); + inflateInit(&zcpr); + + zcpr.next_in = CprPtr; + zcpr.next_out = UncprPtr; + + + do + { + long all_read_before = zcpr.total_in; + zcpr.avail_in = min(lOrigToDo,BlockSizeUncompress); + zcpr.avail_out = BlockSizeUncompress; + ret=inflate(&zcpr,Z_SYNC_FLUSH); + lOrigDone += (zcpr.total_in-all_read_before); + lOrigToDo -= (zcpr.total_in-all_read_before); + step++; + } while (ret==Z_OK); + + lSizeUncpr=zcpr.total_out; + inflateEnd(&zcpr); + dwGetTick=GetTickCount()-dwGetTick; + dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE); + dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE); + printf("total uncompress size = %u, in %u step\n",lSizeUncpr,step); + printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.); + printf("uncpr time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.); + printf("uncpr result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart); + } + + if (lSizeUncpr==lFileSize) + { + if (memcmp(FilePtr,UncprPtr,lFileSize)==0) + printf("compare ok\n"); + + } + + return 0; +} diff --git a/dependencies/zlib-1.2.11/contrib/testzlib/testzlib.txt b/dependencies/zlib-1.2.11/contrib/testzlib/testzlib.txt new file mode 100644 index 0000000..62258f1 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/testzlib/testzlib.txt @@ -0,0 +1,10 @@ +To build testzLib with Visual Studio 2005: + +copy to a directory file from : +- root of zLib tree +- contrib/testzlib +- contrib/masmx86 +- contrib/masmx64 +- contrib/vstudio/vc7 + +and open testzlib8.sln \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/untgz/Makefile b/dependencies/zlib-1.2.11/contrib/untgz/Makefile new file mode 100644 index 0000000..b54266f --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/untgz/Makefile @@ -0,0 +1,14 @@ +CC=cc +CFLAGS=-g + +untgz: untgz.o ../../libz.a + $(CC) $(CFLAGS) -o untgz untgz.o -L../.. -lz + +untgz.o: untgz.c ../../zlib.h + $(CC) $(CFLAGS) -c -I../.. untgz.c + +../../libz.a: + cd ../..; ./configure; make + +clean: + rm -f untgz untgz.o *~ diff --git a/dependencies/zlib-1.2.11/contrib/untgz/Makefile.msc b/dependencies/zlib-1.2.11/contrib/untgz/Makefile.msc new file mode 100644 index 0000000..77b8602 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/untgz/Makefile.msc @@ -0,0 +1,17 @@ +CC=cl +CFLAGS=-MD + +untgz.exe: untgz.obj ..\..\zlib.lib + $(CC) $(CFLAGS) untgz.obj ..\..\zlib.lib + +untgz.obj: untgz.c ..\..\zlib.h + $(CC) $(CFLAGS) -c -I..\.. untgz.c + +..\..\zlib.lib: + cd ..\.. + $(MAKE) -f win32\makefile.msc + cd contrib\untgz + +clean: + -del untgz.obj + -del untgz.exe diff --git a/dependencies/zlib-1.2.11/contrib/untgz/untgz.c b/dependencies/zlib-1.2.11/contrib/untgz/untgz.c new file mode 100644 index 0000000..2c391e5 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/untgz/untgz.c @@ -0,0 +1,674 @@ +/* + * untgz.c -- Display contents and extract files from a gzip'd TAR file + * + * written by Pedro A. Aranda Gutierrez + * adaptation to Unix by Jean-loup Gailly + * various fixes by Cosmin Truta + */ + +#include +#include +#include +#include +#include + +#include "zlib.h" + +#ifdef unix +# include +#else +# include +# include +#endif + +#ifdef WIN32 +#include +# ifndef F_OK +# define F_OK 0 +# endif +# define mkdir(dirname,mode) _mkdir(dirname) +# ifdef _MSC_VER +# define access(path,mode) _access(path,mode) +# define chmod(path,mode) _chmod(path,mode) +# define strdup(str) _strdup(str) +# endif +#else +# include +#endif + + +/* values used in typeflag field */ + +#define REGTYPE '0' /* regular file */ +#define AREGTYPE '\0' /* regular file */ +#define LNKTYPE '1' /* link */ +#define SYMTYPE '2' /* reserved */ +#define CHRTYPE '3' /* character special */ +#define BLKTYPE '4' /* block special */ +#define DIRTYPE '5' /* directory */ +#define FIFOTYPE '6' /* FIFO special */ +#define CONTTYPE '7' /* reserved */ + +/* GNU tar extensions */ + +#define GNUTYPE_DUMPDIR 'D' /* file names from dumped directory */ +#define GNUTYPE_LONGLINK 'K' /* long link name */ +#define GNUTYPE_LONGNAME 'L' /* long file name */ +#define GNUTYPE_MULTIVOL 'M' /* continuation of file from another volume */ +#define GNUTYPE_NAMES 'N' /* file name that does not fit into main hdr */ +#define GNUTYPE_SPARSE 'S' /* sparse file */ +#define GNUTYPE_VOLHDR 'V' /* tape/volume header */ + + +/* tar header */ + +#define BLOCKSIZE 512 +#define SHORTNAMESIZE 100 + +struct tar_header +{ /* byte offset */ + char name[100]; /* 0 */ + char mode[8]; /* 100 */ + char uid[8]; /* 108 */ + char gid[8]; /* 116 */ + char size[12]; /* 124 */ + char mtime[12]; /* 136 */ + char chksum[8]; /* 148 */ + char typeflag; /* 156 */ + char linkname[100]; /* 157 */ + char magic[6]; /* 257 */ + char version[2]; /* 263 */ + char uname[32]; /* 265 */ + char gname[32]; /* 297 */ + char devmajor[8]; /* 329 */ + char devminor[8]; /* 337 */ + char prefix[155]; /* 345 */ + /* 500 */ +}; + +union tar_buffer +{ + char buffer[BLOCKSIZE]; + struct tar_header header; +}; + +struct attr_item +{ + struct attr_item *next; + char *fname; + int mode; + time_t time; +}; + +enum { TGZ_EXTRACT, TGZ_LIST, TGZ_INVALID }; + +char *TGZfname OF((const char *)); +void TGZnotfound OF((const char *)); + +int getoct OF((char *, int)); +char *strtime OF((time_t *)); +int setfiletime OF((char *, time_t)); +void push_attr OF((struct attr_item **, char *, int, time_t)); +void restore_attr OF((struct attr_item **)); + +int ExprMatch OF((char *, char *)); + +int makedir OF((char *)); +int matchname OF((int, int, char **, char *)); + +void error OF((const char *)); +int tar OF((gzFile, int, int, int, char **)); + +void help OF((int)); +int main OF((int, char **)); + +char *prog; + +const char *TGZsuffix[] = { "\0", ".tar", ".tar.gz", ".taz", ".tgz", NULL }; + +/* return the file name of the TGZ archive */ +/* or NULL if it does not exist */ + +char *TGZfname (const char *arcname) +{ + static char buffer[1024]; + int origlen,i; + + strcpy(buffer,arcname); + origlen = strlen(buffer); + + for (i=0; TGZsuffix[i]; i++) + { + strcpy(buffer+origlen,TGZsuffix[i]); + if (access(buffer,F_OK) == 0) + return buffer; + } + return NULL; +} + + +/* error message for the filename */ + +void TGZnotfound (const char *arcname) +{ + int i; + + fprintf(stderr,"%s: Couldn't find ",prog); + for (i=0;TGZsuffix[i];i++) + fprintf(stderr,(TGZsuffix[i+1]) ? "%s%s, " : "or %s%s\n", + arcname, + TGZsuffix[i]); + exit(1); +} + + +/* convert octal digits to int */ +/* on error return -1 */ + +int getoct (char *p,int width) +{ + int result = 0; + char c; + + while (width--) + { + c = *p++; + if (c == 0) + break; + if (c == ' ') + continue; + if (c < '0' || c > '7') + return -1; + result = result * 8 + (c - '0'); + } + return result; +} + + +/* convert time_t to string */ +/* use the "YYYY/MM/DD hh:mm:ss" format */ + +char *strtime (time_t *t) +{ + struct tm *local; + static char result[32]; + + local = localtime(t); + sprintf(result,"%4d/%02d/%02d %02d:%02d:%02d", + local->tm_year+1900, local->tm_mon+1, local->tm_mday, + local->tm_hour, local->tm_min, local->tm_sec); + return result; +} + + +/* set file time */ + +int setfiletime (char *fname,time_t ftime) +{ +#ifdef WIN32 + static int isWinNT = -1; + SYSTEMTIME st; + FILETIME locft, modft; + struct tm *loctm; + HANDLE hFile; + int result; + + loctm = localtime(&ftime); + if (loctm == NULL) + return -1; + + st.wYear = (WORD)loctm->tm_year + 1900; + st.wMonth = (WORD)loctm->tm_mon + 1; + st.wDayOfWeek = (WORD)loctm->tm_wday; + st.wDay = (WORD)loctm->tm_mday; + st.wHour = (WORD)loctm->tm_hour; + st.wMinute = (WORD)loctm->tm_min; + st.wSecond = (WORD)loctm->tm_sec; + st.wMilliseconds = 0; + if (!SystemTimeToFileTime(&st, &locft) || + !LocalFileTimeToFileTime(&locft, &modft)) + return -1; + + if (isWinNT < 0) + isWinNT = (GetVersion() < 0x80000000) ? 1 : 0; + hFile = CreateFile(fname, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, + (isWinNT ? FILE_FLAG_BACKUP_SEMANTICS : 0), + NULL); + if (hFile == INVALID_HANDLE_VALUE) + return -1; + result = SetFileTime(hFile, NULL, NULL, &modft) ? 0 : -1; + CloseHandle(hFile); + return result; +#else + struct utimbuf settime; + + settime.actime = settime.modtime = ftime; + return utime(fname,&settime); +#endif +} + + +/* push file attributes */ + +void push_attr(struct attr_item **list,char *fname,int mode,time_t time) +{ + struct attr_item *item; + + item = (struct attr_item *)malloc(sizeof(struct attr_item)); + if (item == NULL) + error("Out of memory"); + item->fname = strdup(fname); + item->mode = mode; + item->time = time; + item->next = *list; + *list = item; +} + + +/* restore file attributes */ + +void restore_attr(struct attr_item **list) +{ + struct attr_item *item, *prev; + + for (item = *list; item != NULL; ) + { + setfiletime(item->fname,item->time); + chmod(item->fname,item->mode); + prev = item; + item = item->next; + free(prev); + } + *list = NULL; +} + + +/* match regular expression */ + +#define ISSPECIAL(c) (((c) == '*') || ((c) == '/')) + +int ExprMatch (char *string,char *expr) +{ + while (1) + { + if (ISSPECIAL(*expr)) + { + if (*expr == '/') + { + if (*string != '\\' && *string != '/') + return 0; + string ++; expr++; + } + else if (*expr == '*') + { + if (*expr ++ == 0) + return 1; + while (*++string != *expr) + if (*string == 0) + return 0; + } + } + else + { + if (*string != *expr) + return 0; + if (*expr++ == 0) + return 1; + string++; + } + } +} + + +/* recursive mkdir */ +/* abort on ENOENT; ignore other errors like "directory already exists" */ +/* return 1 if OK */ +/* 0 on error */ + +int makedir (char *newdir) +{ + char *buffer = strdup(newdir); + char *p; + int len = strlen(buffer); + + if (len <= 0) { + free(buffer); + return 0; + } + if (buffer[len-1] == '/') { + buffer[len-1] = '\0'; + } + if (mkdir(buffer, 0755) == 0) + { + free(buffer); + return 1; + } + + p = buffer+1; + while (1) + { + char hold; + + while(*p && *p != '\\' && *p != '/') + p++; + hold = *p; + *p = 0; + if ((mkdir(buffer, 0755) == -1) && (errno == ENOENT)) + { + fprintf(stderr,"%s: Couldn't create directory %s\n",prog,buffer); + free(buffer); + return 0; + } + if (hold == 0) + break; + *p++ = hold; + } + free(buffer); + return 1; +} + + +int matchname (int arg,int argc,char **argv,char *fname) +{ + if (arg == argc) /* no arguments given (untgz tgzarchive) */ + return 1; + + while (arg < argc) + if (ExprMatch(fname,argv[arg++])) + return 1; + + return 0; /* ignore this for the moment being */ +} + + +/* tar file list or extract */ + +int tar (gzFile in,int action,int arg,int argc,char **argv) +{ + union tar_buffer buffer; + int len; + int err; + int getheader = 1; + int remaining = 0; + FILE *outfile = NULL; + char fname[BLOCKSIZE]; + int tarmode; + time_t tartime; + struct attr_item *attributes = NULL; + + if (action == TGZ_LIST) + printf(" date time size file\n" + " ---------- -------- --------- -------------------------------------\n"); + while (1) + { + len = gzread(in, &buffer, BLOCKSIZE); + if (len < 0) + error(gzerror(in, &err)); + /* + * Always expect complete blocks to process + * the tar information. + */ + if (len != BLOCKSIZE) + { + action = TGZ_INVALID; /* force error exit */ + remaining = 0; /* force I/O cleanup */ + } + + /* + * If we have to get a tar header + */ + if (getheader >= 1) + { + /* + * if we met the end of the tar + * or the end-of-tar block, + * we are done + */ + if (len == 0 || buffer.header.name[0] == 0) + break; + + tarmode = getoct(buffer.header.mode,8); + tartime = (time_t)getoct(buffer.header.mtime,12); + if (tarmode == -1 || tartime == (time_t)-1) + { + buffer.header.name[0] = 0; + action = TGZ_INVALID; + } + + if (getheader == 1) + { + strncpy(fname,buffer.header.name,SHORTNAMESIZE); + if (fname[SHORTNAMESIZE-1] != 0) + fname[SHORTNAMESIZE] = 0; + } + else + { + /* + * The file name is longer than SHORTNAMESIZE + */ + if (strncmp(fname,buffer.header.name,SHORTNAMESIZE-1) != 0) + error("bad long name"); + getheader = 1; + } + + /* + * Act according to the type flag + */ + switch (buffer.header.typeflag) + { + case DIRTYPE: + if (action == TGZ_LIST) + printf(" %s %s\n",strtime(&tartime),fname); + if (action == TGZ_EXTRACT) + { + makedir(fname); + push_attr(&attributes,fname,tarmode,tartime); + } + break; + case REGTYPE: + case AREGTYPE: + remaining = getoct(buffer.header.size,12); + if (remaining == -1) + { + action = TGZ_INVALID; + break; + } + if (action == TGZ_LIST) + printf(" %s %9d %s\n",strtime(&tartime),remaining,fname); + else if (action == TGZ_EXTRACT) + { + if (matchname(arg,argc,argv,fname)) + { + outfile = fopen(fname,"wb"); + if (outfile == NULL) { + /* try creating directory */ + char *p = strrchr(fname, '/'); + if (p != NULL) { + *p = '\0'; + makedir(fname); + *p = '/'; + outfile = fopen(fname,"wb"); + } + } + if (outfile != NULL) + printf("Extracting %s\n",fname); + else + fprintf(stderr, "%s: Couldn't create %s",prog,fname); + } + else + outfile = NULL; + } + getheader = 0; + break; + case GNUTYPE_LONGLINK: + case GNUTYPE_LONGNAME: + remaining = getoct(buffer.header.size,12); + if (remaining < 0 || remaining >= BLOCKSIZE) + { + action = TGZ_INVALID; + break; + } + len = gzread(in, fname, BLOCKSIZE); + if (len < 0) + error(gzerror(in, &err)); + if (fname[BLOCKSIZE-1] != 0 || (int)strlen(fname) > remaining) + { + action = TGZ_INVALID; + break; + } + getheader = 2; + break; + default: + if (action == TGZ_LIST) + printf(" %s <---> %s\n",strtime(&tartime),fname); + break; + } + } + else + { + unsigned int bytes = (remaining > BLOCKSIZE) ? BLOCKSIZE : remaining; + + if (outfile != NULL) + { + if (fwrite(&buffer,sizeof(char),bytes,outfile) != bytes) + { + fprintf(stderr, + "%s: Error writing %s -- skipping\n",prog,fname); + fclose(outfile); + outfile = NULL; + remove(fname); + } + } + remaining -= bytes; + } + + if (remaining == 0) + { + getheader = 1; + if (outfile != NULL) + { + fclose(outfile); + outfile = NULL; + if (action != TGZ_INVALID) + push_attr(&attributes,fname,tarmode,tartime); + } + } + + /* + * Abandon if errors are found + */ + if (action == TGZ_INVALID) + { + error("broken archive"); + break; + } + } + + /* + * Restore file modes and time stamps + */ + restore_attr(&attributes); + + if (gzclose(in) != Z_OK) + error("failed gzclose"); + + return 0; +} + + +/* ============================================================ */ + +void help(int exitval) +{ + printf("untgz version 0.2.1\n" + " using zlib version %s\n\n", + zlibVersion()); + printf("Usage: untgz file.tgz extract all files\n" + " untgz file.tgz fname ... extract selected files\n" + " untgz -l file.tgz list archive contents\n" + " untgz -h display this help\n"); + exit(exitval); +} + +void error(const char *msg) +{ + fprintf(stderr, "%s: %s\n", prog, msg); + exit(1); +} + + +/* ============================================================ */ + +#if defined(WIN32) && defined(__GNUC__) +int _CRT_glob = 0; /* disable argument globbing in MinGW */ +#endif + +int main(int argc,char **argv) +{ + int action = TGZ_EXTRACT; + int arg = 1; + char *TGZfile; + gzFile *f; + + prog = strrchr(argv[0],'\\'); + if (prog == NULL) + { + prog = strrchr(argv[0],'/'); + if (prog == NULL) + { + prog = strrchr(argv[0],':'); + if (prog == NULL) + prog = argv[0]; + else + prog++; + } + else + prog++; + } + else + prog++; + + if (argc == 1) + help(0); + + if (strcmp(argv[arg],"-l") == 0) + { + action = TGZ_LIST; + if (argc == ++arg) + help(0); + } + else if (strcmp(argv[arg],"-h") == 0) + { + help(0); + } + + if ((TGZfile = TGZfname(argv[arg])) == NULL) + TGZnotfound(argv[arg]); + + ++arg; + if ((action == TGZ_LIST) && (arg != argc)) + help(1); + +/* + * Process the TGZ file + */ + switch(action) + { + case TGZ_LIST: + case TGZ_EXTRACT: + f = gzopen(TGZfile,"rb"); + if (f == NULL) + { + fprintf(stderr,"%s: Couldn't gzopen %s\n",prog,TGZfile); + return 1; + } + exit(tar(f, action, arg, argc, argv)); + break; + + default: + error("Unknown option"); + exit(1); + } + + return 0; +} diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/readme.txt b/dependencies/zlib-1.2.11/contrib/vstudio/readme.txt new file mode 100644 index 0000000..f67eae8 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/readme.txt @@ -0,0 +1,78 @@ +Building instructions for the DLL versions of Zlib 1.2.11 +======================================================== + +This directory contains projects that build zlib and minizip using +Microsoft Visual C++ 9.0/10.0. + +You don't need to build these projects yourself. You can download the +binaries from: + http://www.winimage.com/zLibDll + +More information can be found at this site. + + + + + +Build instructions for Visual Studio 2008 (32 bits or 64 bits) +-------------------------------------------------------------- +- Decompress current zlib, including all contrib/* files +- Compile assembly code (with Visual Studio Command Prompt) by running: + bld_ml64.bat (in contrib\masmx64) + bld_ml32.bat (in contrib\masmx86) +- Open contrib\vstudio\vc9\zlibvc.sln with Microsoft Visual C++ 2008 +- Or run: vcbuild /rebuild contrib\vstudio\vc9\zlibvc.sln "Release|Win32" + +Build instructions for Visual Studio 2010 (32 bits or 64 bits) +-------------------------------------------------------------- +- Decompress current zlib, including all contrib/* files +- Open contrib\vstudio\vc10\zlibvc.sln with Microsoft Visual C++ 2010 + +Build instructions for Visual Studio 2012 (32 bits or 64 bits) +-------------------------------------------------------------- +- Decompress current zlib, including all contrib/* files +- Open contrib\vstudio\vc11\zlibvc.sln with Microsoft Visual C++ 2012 + +Build instructions for Visual Studio 2013 (32 bits or 64 bits) +-------------------------------------------------------------- +- Decompress current zlib, including all contrib/* files +- Open contrib\vstudio\vc12\zlibvc.sln with Microsoft Visual C++ 2013 + +Build instructions for Visual Studio 2015 (32 bits or 64 bits) +-------------------------------------------------------------- +- Decompress current zlib, including all contrib/* files +- Open contrib\vstudio\vc14\zlibvc.sln with Microsoft Visual C++ 2015 + + +Important +--------- +- To use zlibwapi.dll in your application, you must define the + macro ZLIB_WINAPI when compiling your application's source files. + + +Additional notes +---------------- +- This DLL, named zlibwapi.dll, is compatible to the old zlib.dll built + by Gilles Vollant from the zlib 1.1.x sources, and distributed at + http://www.winimage.com/zLibDll + It uses the WINAPI calling convention for the exported functions, and + includes the minizip functionality. If your application needs that + particular build of zlib.dll, you can rename zlibwapi.dll to zlib.dll. + +- The new DLL was renamed because there exist several incompatible + versions of zlib.dll on the Internet. + +- There is also an official DLL build of zlib, named zlib1.dll. This one + is exporting the functions using the CDECL convention. See the file + win32\DLL_FAQ.txt found in this zlib distribution. + +- There used to be a ZLIB_DLL macro in zlib 1.1.x, but now this symbol + has a slightly different effect. To avoid compatibility problems, do + not define it here. + + +Gilles Vollant +info@winimage.com + +Visual Studio 2013 and 2015 Projects from Sean Hunt +seandhunt_7@yahoo.com diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc10/miniunz.vcxproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/miniunz.vcxproj new file mode 100644 index 0000000..74e15c9 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/miniunz.vcxproj @@ -0,0 +1,310 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {C52F9E7B-498A-42BE-8DB4-85A15694382A} + Win32Proj + + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\MiniUnzip$(Configuration)\ + x86\MiniUnzip$(Configuration)\Tmp\ + true + false + x86\MiniUnzip$(Configuration)\ + x86\MiniUnzip$(Configuration)\Tmp\ + false + false + x64\MiniUnzip$(Configuration)\ + x64\MiniUnzip$(Configuration)\Tmp\ + true + false + ia64\MiniUnzip$(Configuration)\ + ia64\MiniUnzip$(Configuration)\Tmp\ + true + false + x64\MiniUnzip$(Configuration)\ + x64\MiniUnzip$(Configuration)\Tmp\ + false + false + ia64\MiniUnzip$(Configuration)\ + ia64\MiniUnzip$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebug + false + + + $(IntDir) + Level3 + EditAndContinue + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc10/miniunz.vcxproj.filters b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/miniunz.vcxproj.filters new file mode 100644 index 0000000..0b2a3de --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/miniunz.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {048af943-022b-4db6-beeb-a54c34774ee2} + cpp;c;cxx;def;odl;idl;hpj;bat;asm + + + {c1d600d2-888f-4aea-b73e-8b0dd9befa0c} + h;hpp;hxx;hm;inl;inc + + + {0844199a-966b-4f19-81db-1e0125e141b9} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + Source Files + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc10/minizip.vcxproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/minizip.vcxproj new file mode 100644 index 0000000..917e156 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/minizip.vcxproj @@ -0,0 +1,307 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B} + Win32Proj + + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\MiniZip$(Configuration)\ + x86\MiniZip$(Configuration)\Tmp\ + true + false + x86\MiniZip$(Configuration)\ + x86\MiniZip$(Configuration)\Tmp\ + false + x64\$(Configuration)\ + x64\$(Configuration)\ + true + false + ia64\$(Configuration)\ + ia64\$(Configuration)\ + true + false + x64\$(Configuration)\ + x64\$(Configuration)\ + false + ia64\$(Configuration)\ + ia64\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebug + false + + + $(IntDir) + Level3 + EditAndContinue + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc10/minizip.vcxproj.filters b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/minizip.vcxproj.filters new file mode 100644 index 0000000..dd73cd3 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/minizip.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {c0419b40-bf50-40da-b153-ff74215b79de} + cpp;c;cxx;def;odl;idl;hpj;bat;asm + + + {bb87b070-735b-478e-92ce-7383abb2f36c} + h;hpp;hxx;hm;inl;inc + + + {f46ab6a6-548f-43cb-ae96-681abb5bd5db} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + Source Files + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc10/testzlib.vcxproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/testzlib.vcxproj new file mode 100644 index 0000000..9088d17 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/testzlib.vcxproj @@ -0,0 +1,420 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B} + testzlib + Win32Proj + + + + Application + MultiByte + true + + + Application + MultiByte + true + + + Application + MultiByte + + + Application + MultiByte + true + + + Application + MultiByte + true + + + Application + MultiByte + + + Application + true + + + Application + true + + + Application + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + true + false + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + false + false + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + false + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + true + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + false + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebug + false + + + AssemblyAndSourceCode + $(IntDir) + Level3 + EditAndContinue + + + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)testzlib.exe + true + $(OutDir)testzlib.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)testzlib.exe + true + Console + true + true + false + + + MachineX86 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDebugDLL + false + $(IntDir) + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + + + + + Itanium + + + Disabled + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + AssemblyAndSourceCode + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + $(OutDir)testzlib.pdb + Console + MachineIA64 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDLL + false + $(IntDir) + + + %(AdditionalDependencies) + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + MachineIA64 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDLL + false + $(IntDir) + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + MachineIA64 + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc10/testzlib.vcxproj.filters b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/testzlib.vcxproj.filters new file mode 100644 index 0000000..249daa8 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/testzlib.vcxproj.filters @@ -0,0 +1,58 @@ + + + + + {c1f6a2e3-5da5-4955-8653-310d3efe05a9} + cpp;c;cxx;def;odl;idl;hpj;bat;asm + + + {c2aaffdc-2c95-4d6f-8466-4bec5890af2c} + h;hpp;hxx;hm;inl;inc + + + {c274fe07-05f2-461c-964b-f6341e4e7eb5} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc10/testzlibdll.vcxproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/testzlibdll.vcxproj new file mode 100644 index 0000000..bcb08ff --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/testzlibdll.vcxproj @@ -0,0 +1,310 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {C52F9E7B-498A-42BE-8DB4-85A15694366A} + Win32Proj + + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\TestZlibDll$(Configuration)\ + x86\TestZlibDll$(Configuration)\Tmp\ + true + false + x86\TestZlibDll$(Configuration)\ + x86\TestZlibDll$(Configuration)\Tmp\ + false + false + x64\TestZlibDll$(Configuration)\ + x64\TestZlibDll$(Configuration)\Tmp\ + true + false + ia64\TestZlibDll$(Configuration)\ + ia64\TestZlibDll$(Configuration)\Tmp\ + true + false + x64\TestZlibDll$(Configuration)\ + x64\TestZlibDll$(Configuration)\Tmp\ + false + false + ia64\TestZlibDll$(Configuration)\ + ia64\TestZlibDll$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebug + false + + + $(IntDir) + Level3 + EditAndContinue + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc10/testzlibdll.vcxproj.filters b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/testzlibdll.vcxproj.filters new file mode 100644 index 0000000..53a8693 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/testzlibdll.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {fa61a89f-93fc-4c89-b29e-36224b7592f4} + cpp;c;cxx;def;odl;idl;hpj;bat;asm + + + {d4b85da0-2ba2-4934-b57f-e2584e3848ee} + h;hpp;hxx;hm;inl;inc + + + {e573e075-00bd-4a7d-bd67-a8cc9bfc5aca} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + Source Files + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc10/zlib.rc b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/zlib.rc new file mode 100644 index 0000000..fee177a --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/zlib.rc @@ -0,0 +1,32 @@ +#include + +#define IDR_VERSION1 1 +IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE + FILEVERSION 1, 2, 11, 0 + PRODUCTVERSION 1, 2, 11, 0 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS 0 + FILEOS VOS_DOS_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0 // not used +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + //language ID = U.S. English, char set = Windows, Multilingual + + BEGIN + VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" + VALUE "FileVersion", "1.2.11\0" + VALUE "InternalName", "zlib\0" + VALUE "OriginalFilename", "zlibwapi.dll\0" + VALUE "ProductName", "ZLib.DLL\0" + VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" + VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1252 + END +END diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc10/zlibstat.vcxproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/zlibstat.vcxproj new file mode 100644 index 0000000..b9f2bbe --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/zlibstat.vcxproj @@ -0,0 +1,473 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8} + + + + StaticLibrary + false + + + StaticLibrary + false + + + StaticLibrary + false + + + StaticLibrary + false + + + StaticLibrary + false + + + StaticLibrary + false + + + StaticLibrary + false + + + StaticLibrary + false + + + StaticLibrary + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + + + MultiThreadedDebug + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + cd ..\..\masmx86 +bld_ml32.bat + + + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibstat.lib + true + + + cd ..\..\masmx86 +bld_ml32.bat + + + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + cd ..\..\masmx64 +bld_ml64.bat + + + + + Itanium + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibstat.lib + true + + + cd ..\..\masmx64 +bld_ml64.bat + + + + + Itanium + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc10/zlibstat.vcxproj.filters b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/zlibstat.vcxproj.filters new file mode 100644 index 0000000..c8c7f7e --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/zlibstat.vcxproj.filters @@ -0,0 +1,77 @@ + + + + + {174213f6-7f66-4ae8-a3a8-a1e0a1e6ffdd} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Source Files + + + + + Source Files + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc10/zlibvc.def b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/zlibvc.def new file mode 100644 index 0000000..54e683d --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/zlibvc.def @@ -0,0 +1,153 @@ +LIBRARY +; zlib data compression and ZIP file I/O library + +VERSION 1.2 + +EXPORTS + adler32 @1 + compress @2 + crc32 @3 + deflate @4 + deflateCopy @5 + deflateEnd @6 + deflateInit2_ @7 + deflateInit_ @8 + deflateParams @9 + deflateReset @10 + deflateSetDictionary @11 + gzclose @12 + gzdopen @13 + gzerror @14 + gzflush @15 + gzopen @16 + gzread @17 + gzwrite @18 + inflate @19 + inflateEnd @20 + inflateInit2_ @21 + inflateInit_ @22 + inflateReset @23 + inflateSetDictionary @24 + inflateSync @25 + uncompress @26 + zlibVersion @27 + gzprintf @28 + gzputc @29 + gzgetc @30 + gzseek @31 + gzrewind @32 + gztell @33 + gzeof @34 + gzsetparams @35 + zError @36 + inflateSyncPoint @37 + get_crc_table @38 + compress2 @39 + gzputs @40 + gzgets @41 + inflateCopy @42 + inflateBackInit_ @43 + inflateBack @44 + inflateBackEnd @45 + compressBound @46 + deflateBound @47 + gzclearerr @48 + gzungetc @49 + zlibCompileFlags @50 + deflatePrime @51 + deflatePending @52 + + unzOpen @61 + unzClose @62 + unzGetGlobalInfo @63 + unzGetCurrentFileInfo @64 + unzGoToFirstFile @65 + unzGoToNextFile @66 + unzOpenCurrentFile @67 + unzReadCurrentFile @68 + unzOpenCurrentFile3 @69 + unztell @70 + unzeof @71 + unzCloseCurrentFile @72 + unzGetGlobalComment @73 + unzStringFileNameCompare @74 + unzLocateFile @75 + unzGetLocalExtrafield @76 + unzOpen2 @77 + unzOpenCurrentFile2 @78 + unzOpenCurrentFilePassword @79 + + zipOpen @80 + zipOpenNewFileInZip @81 + zipWriteInFileInZip @82 + zipCloseFileInZip @83 + zipClose @84 + zipOpenNewFileInZip2 @86 + zipCloseFileInZipRaw @87 + zipOpen2 @88 + zipOpenNewFileInZip3 @89 + + unzGetFilePos @100 + unzGoToFilePos @101 + + fill_win32_filefunc @110 + +; zlibwapi v1.2.4 added: + fill_win32_filefunc64 @111 + fill_win32_filefunc64A @112 + fill_win32_filefunc64W @113 + + unzOpen64 @120 + unzOpen2_64 @121 + unzGetGlobalInfo64 @122 + unzGetCurrentFileInfo64 @124 + unzGetCurrentFileZStreamPos64 @125 + unztell64 @126 + unzGetFilePos64 @127 + unzGoToFilePos64 @128 + + zipOpen64 @130 + zipOpen2_64 @131 + zipOpenNewFileInZip64 @132 + zipOpenNewFileInZip2_64 @133 + zipOpenNewFileInZip3_64 @134 + zipOpenNewFileInZip4_64 @135 + zipCloseFileInZipRaw64 @136 + +; zlib1 v1.2.4 added: + adler32_combine @140 + crc32_combine @142 + deflateSetHeader @144 + deflateTune @145 + gzbuffer @146 + gzclose_r @147 + gzclose_w @148 + gzdirect @149 + gzoffset @150 + inflateGetHeader @156 + inflateMark @157 + inflatePrime @158 + inflateReset2 @159 + inflateUndermine @160 + +; zlib1 v1.2.6 added: + gzgetc_ @161 + inflateResetKeep @163 + deflateResetKeep @164 + +; zlib1 v1.2.7 added: + gzopen_w @165 + +; zlib1 v1.2.8 added: + inflateGetDictionary @166 + gzvprintf @167 + +; zlib1 v1.2.9 added: + inflateCodesUsed @168 + inflateValidate @169 + uncompress2 @170 + gzfread @171 + gzfwrite @172 + deflateGetDictionary @173 + adler32_z @174 + crc32_z @175 diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc10/zlibvc.sln b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/zlibvc.sln new file mode 100644 index 0000000..6f6ffd5 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/zlibvc.sln @@ -0,0 +1,135 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcxproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcxproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib", "testzlib.vcxproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlibdll", "testzlibdll.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694366A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcxproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Itanium = Debug|Itanium + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Itanium = Release|Itanium + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium + ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32 + ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Itanium + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.Build.0 = Debug|Itanium + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.ActiveCfg = Debug|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.Build.0 = Debug|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.ActiveCfg = Release|Itanium + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.Build.0 = Release|Itanium + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.Build.0 = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.ActiveCfg = Release|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.Build.0 = Release|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.ActiveCfg = Debug|Itanium + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.Build.0 = Debug|Itanium + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.ActiveCfg = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.Build.0 = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.ActiveCfg = Debug|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.Build.0 = Debug|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.ActiveCfg = Release|Itanium + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.Build.0 = Release|Itanium + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.ActiveCfg = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.Build.0 = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.ActiveCfg = Release|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.Build.0 = Release|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Itanium + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.Build.0 = Debug|Itanium + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Itanium + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.Build.0 = Release|Itanium + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.ActiveCfg = Debug|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.Build.0 = Debug|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.Build.0 = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.ActiveCfg = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.Build.0 = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.ActiveCfg = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.Build.0 = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.Build.0 = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.Build.0 = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Itanium + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.Build.0 = Debug|Itanium + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Itanium + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.Build.0 = Release|Itanium + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.ActiveCfg = Debug|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.Build.0 = Debug|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.Build.0 = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.ActiveCfg = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.Build.0 = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.ActiveCfg = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.Build.0 = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.Build.0 = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.Build.0 = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc10/zlibvc.vcxproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/zlibvc.vcxproj new file mode 100644 index 0000000..6ff9ddb --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/zlibvc.vcxproj @@ -0,0 +1,657 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {8FD826F8-3739-44E6-8CC8-997122E53B8D} + + + + DynamicLibrary + false + true + + + DynamicLibrary + false + true + + + DynamicLibrary + false + + + DynamicLibrary + false + true + + + DynamicLibrary + false + true + + + DynamicLibrary + false + + + DynamicLibrary + false + true + + + DynamicLibrary + false + true + + + DynamicLibrary + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + true + false + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + false + false + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + false + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + true + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + true + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + false + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + false + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + false + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + zlibwapid + zlibwapi + zlibwapi + zlibwapid + zlibwapi + zlibwapi + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + + + MultiThreadedDebug + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + EditAndContinue + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + true + .\zlibvc.def + true + true + Windows + false + + + + + cd ..\..\masmx86 +bld_ml32.bat + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + true + false + .\zlibvc.def + true + Windows + false + + + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + true + false + .\zlibvc.def + true + Windows + false + + + + + cd ..\..\masmx86 +bld_ml32.bat + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + true + .\zlibvc.def + true + true + Windows + MachineX64 + + + cd ..\..\masmx64 +bld_ml64.bat + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + true + false + .\zlibvc.def + true + Windows + MachineX64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + true + false + .\zlibvc.def + true + Windows + MachineX64 + + + cd ..\..\masmx64 +bld_ml64.bat + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + + + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc10/zlibvc.vcxproj.filters b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/zlibvc.vcxproj.filters new file mode 100644 index 0000000..180b71c --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc10/zlibvc.vcxproj.filters @@ -0,0 +1,118 @@ + + + + + {07934a85-8b61-443d-a0ee-b2eedb74f3cd} + cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90 + + + {1d99675b-433d-4a21-9e50-ed4ab8b19762} + h;hpp;hxx;hm;inl;fi;fd + + + {431c0958-fa71-44d0-9084-2d19d100c0cc} + ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Source Files + + + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc11/miniunz.vcxproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc11/miniunz.vcxproj new file mode 100644 index 0000000..8f9f20b --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc11/miniunz.vcxproj @@ -0,0 +1,314 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {C52F9E7B-498A-42BE-8DB4-85A15694382A} + Win32Proj + + + + Application + MultiByte + v110 + + + Application + Unicode + v110 + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + v110 + + + Application + MultiByte + v110 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\MiniUnzip$(Configuration)\ + x86\MiniUnzip$(Configuration)\Tmp\ + true + false + x86\MiniUnzip$(Configuration)\ + x86\MiniUnzip$(Configuration)\Tmp\ + false + false + x64\MiniUnzip$(Configuration)\ + x64\MiniUnzip$(Configuration)\Tmp\ + true + false + ia64\MiniUnzip$(Configuration)\ + ia64\MiniUnzip$(Configuration)\Tmp\ + true + false + x64\MiniUnzip$(Configuration)\ + x64\MiniUnzip$(Configuration)\Tmp\ + false + false + ia64\MiniUnzip$(Configuration)\ + ia64\MiniUnzip$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc11/minizip.vcxproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc11/minizip.vcxproj new file mode 100644 index 0000000..c93d9e6 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc11/minizip.vcxproj @@ -0,0 +1,311 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B} + Win32Proj + + + + Application + MultiByte + v110 + + + Application + Unicode + v110 + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + v110 + + + Application + MultiByte + v110 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\MiniZip$(Configuration)\ + x86\MiniZip$(Configuration)\Tmp\ + true + false + x86\MiniZip$(Configuration)\ + x86\MiniZip$(Configuration)\Tmp\ + false + x64\$(Configuration)\ + x64\$(Configuration)\ + true + false + ia64\$(Configuration)\ + ia64\$(Configuration)\ + true + false + x64\$(Configuration)\ + x64\$(Configuration)\ + false + ia64\$(Configuration)\ + ia64\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc11/testzlib.vcxproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc11/testzlib.vcxproj new file mode 100644 index 0000000..6d55954 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc11/testzlib.vcxproj @@ -0,0 +1,426 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B} + testzlib + Win32Proj + + + + Application + MultiByte + true + v110 + + + Application + MultiByte + true + v110 + + + Application + Unicode + v110 + + + Application + MultiByte + true + + + Application + MultiByte + true + + + Application + MultiByte + + + Application + true + v110 + + + Application + true + v110 + + + Application + v110 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + true + false + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + false + false + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + false + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + true + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + false + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + AssemblyAndSourceCode + $(IntDir) + Level3 + ProgramDatabase + + + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)testzlib.exe + true + $(OutDir)testzlib.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)testzlib.exe + true + Console + true + true + false + + + MachineX86 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDebugDLL + false + $(IntDir) + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + + + + + Itanium + + + Disabled + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + AssemblyAndSourceCode + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + $(OutDir)testzlib.pdb + Console + MachineIA64 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDLL + false + $(IntDir) + + + %(AdditionalDependencies) + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + MachineIA64 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDLL + false + $(IntDir) + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + MachineIA64 + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc11/testzlibdll.vcxproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc11/testzlibdll.vcxproj new file mode 100644 index 0000000..9f20c78 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc11/testzlibdll.vcxproj @@ -0,0 +1,314 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {C52F9E7B-498A-42BE-8DB4-85A15694366A} + Win32Proj + + + + Application + MultiByte + v110 + + + Application + Unicode + v110 + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + v110 + + + Application + MultiByte + v110 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\TestZlibDll$(Configuration)\ + x86\TestZlibDll$(Configuration)\Tmp\ + true + false + x86\TestZlibDll$(Configuration)\ + x86\TestZlibDll$(Configuration)\Tmp\ + false + false + x64\TestZlibDll$(Configuration)\ + x64\TestZlibDll$(Configuration)\Tmp\ + true + false + ia64\TestZlibDll$(Configuration)\ + ia64\TestZlibDll$(Configuration)\Tmp\ + true + false + x64\TestZlibDll$(Configuration)\ + x64\TestZlibDll$(Configuration)\Tmp\ + false + false + ia64\TestZlibDll$(Configuration)\ + ia64\TestZlibDll$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc11/zlib.rc b/dependencies/zlib-1.2.11/contrib/vstudio/vc11/zlib.rc new file mode 100644 index 0000000..fee177a --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc11/zlib.rc @@ -0,0 +1,32 @@ +#include + +#define IDR_VERSION1 1 +IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE + FILEVERSION 1, 2, 11, 0 + PRODUCTVERSION 1, 2, 11, 0 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS 0 + FILEOS VOS_DOS_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0 // not used +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + //language ID = U.S. English, char set = Windows, Multilingual + + BEGIN + VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" + VALUE "FileVersion", "1.2.11\0" + VALUE "InternalName", "zlib\0" + VALUE "OriginalFilename", "zlibwapi.dll\0" + VALUE "ProductName", "ZLib.DLL\0" + VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" + VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1252 + END +END diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc11/zlibstat.vcxproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc11/zlibstat.vcxproj new file mode 100644 index 0000000..806b76a --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc11/zlibstat.vcxproj @@ -0,0 +1,464 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8} + + + + StaticLibrary + false + v110 + + + StaticLibrary + false + v110 + + + StaticLibrary + false + v110 + Unicode + + + StaticLibrary + false + + + StaticLibrary + false + + + StaticLibrary + false + + + StaticLibrary + false + v110 + + + StaticLibrary + false + v110 + + + StaticLibrary + false + v110 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibstat.lib + true + + + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc11/zlibvc.def b/dependencies/zlib-1.2.11/contrib/vstudio/vc11/zlibvc.def new file mode 100644 index 0000000..54e683d --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc11/zlibvc.def @@ -0,0 +1,153 @@ +LIBRARY +; zlib data compression and ZIP file I/O library + +VERSION 1.2 + +EXPORTS + adler32 @1 + compress @2 + crc32 @3 + deflate @4 + deflateCopy @5 + deflateEnd @6 + deflateInit2_ @7 + deflateInit_ @8 + deflateParams @9 + deflateReset @10 + deflateSetDictionary @11 + gzclose @12 + gzdopen @13 + gzerror @14 + gzflush @15 + gzopen @16 + gzread @17 + gzwrite @18 + inflate @19 + inflateEnd @20 + inflateInit2_ @21 + inflateInit_ @22 + inflateReset @23 + inflateSetDictionary @24 + inflateSync @25 + uncompress @26 + zlibVersion @27 + gzprintf @28 + gzputc @29 + gzgetc @30 + gzseek @31 + gzrewind @32 + gztell @33 + gzeof @34 + gzsetparams @35 + zError @36 + inflateSyncPoint @37 + get_crc_table @38 + compress2 @39 + gzputs @40 + gzgets @41 + inflateCopy @42 + inflateBackInit_ @43 + inflateBack @44 + inflateBackEnd @45 + compressBound @46 + deflateBound @47 + gzclearerr @48 + gzungetc @49 + zlibCompileFlags @50 + deflatePrime @51 + deflatePending @52 + + unzOpen @61 + unzClose @62 + unzGetGlobalInfo @63 + unzGetCurrentFileInfo @64 + unzGoToFirstFile @65 + unzGoToNextFile @66 + unzOpenCurrentFile @67 + unzReadCurrentFile @68 + unzOpenCurrentFile3 @69 + unztell @70 + unzeof @71 + unzCloseCurrentFile @72 + unzGetGlobalComment @73 + unzStringFileNameCompare @74 + unzLocateFile @75 + unzGetLocalExtrafield @76 + unzOpen2 @77 + unzOpenCurrentFile2 @78 + unzOpenCurrentFilePassword @79 + + zipOpen @80 + zipOpenNewFileInZip @81 + zipWriteInFileInZip @82 + zipCloseFileInZip @83 + zipClose @84 + zipOpenNewFileInZip2 @86 + zipCloseFileInZipRaw @87 + zipOpen2 @88 + zipOpenNewFileInZip3 @89 + + unzGetFilePos @100 + unzGoToFilePos @101 + + fill_win32_filefunc @110 + +; zlibwapi v1.2.4 added: + fill_win32_filefunc64 @111 + fill_win32_filefunc64A @112 + fill_win32_filefunc64W @113 + + unzOpen64 @120 + unzOpen2_64 @121 + unzGetGlobalInfo64 @122 + unzGetCurrentFileInfo64 @124 + unzGetCurrentFileZStreamPos64 @125 + unztell64 @126 + unzGetFilePos64 @127 + unzGoToFilePos64 @128 + + zipOpen64 @130 + zipOpen2_64 @131 + zipOpenNewFileInZip64 @132 + zipOpenNewFileInZip2_64 @133 + zipOpenNewFileInZip3_64 @134 + zipOpenNewFileInZip4_64 @135 + zipCloseFileInZipRaw64 @136 + +; zlib1 v1.2.4 added: + adler32_combine @140 + crc32_combine @142 + deflateSetHeader @144 + deflateTune @145 + gzbuffer @146 + gzclose_r @147 + gzclose_w @148 + gzdirect @149 + gzoffset @150 + inflateGetHeader @156 + inflateMark @157 + inflatePrime @158 + inflateReset2 @159 + inflateUndermine @160 + +; zlib1 v1.2.6 added: + gzgetc_ @161 + inflateResetKeep @163 + deflateResetKeep @164 + +; zlib1 v1.2.7 added: + gzopen_w @165 + +; zlib1 v1.2.8 added: + inflateGetDictionary @166 + gzvprintf @167 + +; zlib1 v1.2.9 added: + inflateCodesUsed @168 + inflateValidate @169 + uncompress2 @170 + gzfread @171 + gzfwrite @172 + deflateGetDictionary @173 + adler32_z @174 + crc32_z @175 diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc11/zlibvc.sln b/dependencies/zlib-1.2.11/contrib/vstudio/vc11/zlibvc.sln new file mode 100644 index 0000000..9fcbafd --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc11/zlibvc.sln @@ -0,0 +1,117 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcxproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcxproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib", "testzlib.vcxproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlibdll", "testzlibdll.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694366A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcxproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Itanium = Debug|Itanium + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Itanium = Release|Itanium + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium + ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32 + ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.ActiveCfg = Debug|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.Build.0 = Debug|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.ActiveCfg = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.Build.0 = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.ActiveCfg = Release|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.Build.0 = Release|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.ActiveCfg = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.ActiveCfg = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.Build.0 = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.ActiveCfg = Debug|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.Build.0 = Debug|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.ActiveCfg = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.ActiveCfg = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.Build.0 = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.ActiveCfg = Release|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.Build.0 = Release|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.Build.0 = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.ActiveCfg = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.Build.0 = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.Build.0 = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.Build.0 = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.Build.0 = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.ActiveCfg = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.Build.0 = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.Build.0 = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.Build.0 = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc11/zlibvc.vcxproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc11/zlibvc.vcxproj new file mode 100644 index 0000000..c65b95f --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc11/zlibvc.vcxproj @@ -0,0 +1,688 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {8FD826F8-3739-44E6-8CC8-997122E53B8D} + + + + DynamicLibrary + false + true + v110 + + + DynamicLibrary + false + true + v110 + + + DynamicLibrary + false + v110 + Unicode + + + DynamicLibrary + false + true + + + DynamicLibrary + false + true + + + DynamicLibrary + false + + + DynamicLibrary + false + true + v110 + + + DynamicLibrary + false + true + v110 + + + DynamicLibrary + false + v110 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + true + false + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + false + false + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + false + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + true + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + true + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + false + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + false + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + false + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + zlibwapi + zlibwapi + zlibwapi + zlibwapi + zlibwapi + zlibwapi + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + + + cd ..\..\masmx86 +bld_ml32.bat + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + + + cd ..\..\masmx86 +bld_ml32.bat + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + cd ..\..\contrib\masmx64 +bld_ml64.bat + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + cd ..\..\masmx64 +bld_ml64.bat + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + + + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc12/miniunz.vcxproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc12/miniunz.vcxproj new file mode 100644 index 0000000..d88ac7f --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc12/miniunz.vcxproj @@ -0,0 +1,316 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {C52F9E7B-498A-42BE-8DB4-85A15694382A} + Win32Proj + + + + Application + MultiByte + v120 + + + Application + Unicode + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\MiniUnzip$(Configuration)\ + x86\MiniUnzip$(Configuration)\Tmp\ + true + false + x86\MiniUnzip$(Configuration)\ + x86\MiniUnzip$(Configuration)\Tmp\ + false + false + x64\MiniUnzip$(Configuration)\ + x64\MiniUnzip$(Configuration)\Tmp\ + true + false + ia64\MiniUnzip$(Configuration)\ + ia64\MiniUnzip$(Configuration)\Tmp\ + true + false + x64\MiniUnzip$(Configuration)\ + x64\MiniUnzip$(Configuration)\Tmp\ + false + false + ia64\MiniUnzip$(Configuration)\ + ia64\MiniUnzip$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc12/minizip.vcxproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc12/minizip.vcxproj new file mode 100644 index 0000000..f1f239c --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc12/minizip.vcxproj @@ -0,0 +1,313 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B} + Win32Proj + + + + Application + MultiByte + v120 + + + Application + Unicode + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\MiniZip$(Configuration)\ + x86\MiniZip$(Configuration)\Tmp\ + true + false + x86\MiniZip$(Configuration)\ + x86\MiniZip$(Configuration)\Tmp\ + false + x64\$(Configuration)\ + x64\$(Configuration)\ + true + false + ia64\$(Configuration)\ + ia64\$(Configuration)\ + true + false + x64\$(Configuration)\ + x64\$(Configuration)\ + false + ia64\$(Configuration)\ + ia64\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc12/testzlib.vcxproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc12/testzlib.vcxproj new file mode 100644 index 0000000..64b2cbe --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc12/testzlib.vcxproj @@ -0,0 +1,430 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B} + testzlib + Win32Proj + + + + Application + MultiByte + true + v120 + + + Application + MultiByte + true + v120 + + + Application + Unicode + v120 + + + Application + MultiByte + true + v120 + + + Application + MultiByte + true + v120 + + + Application + MultiByte + v120 + + + Application + true + v120 + + + Application + true + v120 + + + Application + v120 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + true + false + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + false + false + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + false + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + true + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + false + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + AssemblyAndSourceCode + $(IntDir) + Level3 + ProgramDatabase + + + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)testzlib.exe + true + $(OutDir)testzlib.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)testzlib.exe + true + Console + true + true + false + + + MachineX86 + false + + + + + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDebugDLL + false + $(IntDir) + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + + + + + Itanium + + + Disabled + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + AssemblyAndSourceCode + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + $(OutDir)testzlib.pdb + Console + MachineIA64 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDLL + false + $(IntDir) + + + %(AdditionalDependencies) + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + MachineIA64 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDLL + false + $(IntDir) + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + MachineIA64 + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc12/testzlibdll.vcxproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc12/testzlibdll.vcxproj new file mode 100644 index 0000000..c66573a --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc12/testzlibdll.vcxproj @@ -0,0 +1,316 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {C52F9E7B-498A-42BE-8DB4-85A15694366A} + Win32Proj + + + + Application + MultiByte + v120 + + + Application + Unicode + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\TestZlibDll$(Configuration)\ + x86\TestZlibDll$(Configuration)\Tmp\ + true + false + x86\TestZlibDll$(Configuration)\ + x86\TestZlibDll$(Configuration)\Tmp\ + false + false + x64\TestZlibDll$(Configuration)\ + x64\TestZlibDll$(Configuration)\Tmp\ + true + false + ia64\TestZlibDll$(Configuration)\ + ia64\TestZlibDll$(Configuration)\Tmp\ + true + false + x64\TestZlibDll$(Configuration)\ + x64\TestZlibDll$(Configuration)\Tmp\ + false + false + ia64\TestZlibDll$(Configuration)\ + ia64\TestZlibDll$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc12/zlib.rc b/dependencies/zlib-1.2.11/contrib/vstudio/vc12/zlib.rc new file mode 100644 index 0000000..c4e4b01 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc12/zlib.rc @@ -0,0 +1,32 @@ +#include + +#define IDR_VERSION1 1 +IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE + FILEVERSION 1, 2, 11, 0 + PRODUCTVERSION 1, 2, 11, 0 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS 0 + FILEOS VOS_DOS_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0 // not used +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + //language ID = U.S. English, char set = Windows, Multilingual + + BEGIN + VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" + VALUE "FileVersion", "1.2.11\0" + VALUE "InternalName", "zlib\0" + VALUE "OriginalFilename", "zlibwapi.dll\0" + VALUE "ProductName", "ZLib.DLL\0" + VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" + VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1252 + END +END diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc12/zlibstat.vcxproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc12/zlibstat.vcxproj new file mode 100644 index 0000000..3fdee7c --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc12/zlibstat.vcxproj @@ -0,0 +1,467 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8} + + + + StaticLibrary + false + v120 + + + StaticLibrary + false + v120 + + + StaticLibrary + false + v120 + Unicode + + + StaticLibrary + false + v120 + + + StaticLibrary + false + v120 + + + StaticLibrary + false + v120 + + + StaticLibrary + false + v120 + + + StaticLibrary + false + v120 + + + StaticLibrary + false + v120 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibstat.lib + true + + + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc12/zlibvc.def b/dependencies/zlib-1.2.11/contrib/vstudio/vc12/zlibvc.def new file mode 100644 index 0000000..54e683d --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc12/zlibvc.def @@ -0,0 +1,153 @@ +LIBRARY +; zlib data compression and ZIP file I/O library + +VERSION 1.2 + +EXPORTS + adler32 @1 + compress @2 + crc32 @3 + deflate @4 + deflateCopy @5 + deflateEnd @6 + deflateInit2_ @7 + deflateInit_ @8 + deflateParams @9 + deflateReset @10 + deflateSetDictionary @11 + gzclose @12 + gzdopen @13 + gzerror @14 + gzflush @15 + gzopen @16 + gzread @17 + gzwrite @18 + inflate @19 + inflateEnd @20 + inflateInit2_ @21 + inflateInit_ @22 + inflateReset @23 + inflateSetDictionary @24 + inflateSync @25 + uncompress @26 + zlibVersion @27 + gzprintf @28 + gzputc @29 + gzgetc @30 + gzseek @31 + gzrewind @32 + gztell @33 + gzeof @34 + gzsetparams @35 + zError @36 + inflateSyncPoint @37 + get_crc_table @38 + compress2 @39 + gzputs @40 + gzgets @41 + inflateCopy @42 + inflateBackInit_ @43 + inflateBack @44 + inflateBackEnd @45 + compressBound @46 + deflateBound @47 + gzclearerr @48 + gzungetc @49 + zlibCompileFlags @50 + deflatePrime @51 + deflatePending @52 + + unzOpen @61 + unzClose @62 + unzGetGlobalInfo @63 + unzGetCurrentFileInfo @64 + unzGoToFirstFile @65 + unzGoToNextFile @66 + unzOpenCurrentFile @67 + unzReadCurrentFile @68 + unzOpenCurrentFile3 @69 + unztell @70 + unzeof @71 + unzCloseCurrentFile @72 + unzGetGlobalComment @73 + unzStringFileNameCompare @74 + unzLocateFile @75 + unzGetLocalExtrafield @76 + unzOpen2 @77 + unzOpenCurrentFile2 @78 + unzOpenCurrentFilePassword @79 + + zipOpen @80 + zipOpenNewFileInZip @81 + zipWriteInFileInZip @82 + zipCloseFileInZip @83 + zipClose @84 + zipOpenNewFileInZip2 @86 + zipCloseFileInZipRaw @87 + zipOpen2 @88 + zipOpenNewFileInZip3 @89 + + unzGetFilePos @100 + unzGoToFilePos @101 + + fill_win32_filefunc @110 + +; zlibwapi v1.2.4 added: + fill_win32_filefunc64 @111 + fill_win32_filefunc64A @112 + fill_win32_filefunc64W @113 + + unzOpen64 @120 + unzOpen2_64 @121 + unzGetGlobalInfo64 @122 + unzGetCurrentFileInfo64 @124 + unzGetCurrentFileZStreamPos64 @125 + unztell64 @126 + unzGetFilePos64 @127 + unzGoToFilePos64 @128 + + zipOpen64 @130 + zipOpen2_64 @131 + zipOpenNewFileInZip64 @132 + zipOpenNewFileInZip2_64 @133 + zipOpenNewFileInZip3_64 @134 + zipOpenNewFileInZip4_64 @135 + zipCloseFileInZipRaw64 @136 + +; zlib1 v1.2.4 added: + adler32_combine @140 + crc32_combine @142 + deflateSetHeader @144 + deflateTune @145 + gzbuffer @146 + gzclose_r @147 + gzclose_w @148 + gzdirect @149 + gzoffset @150 + inflateGetHeader @156 + inflateMark @157 + inflatePrime @158 + inflateReset2 @159 + inflateUndermine @160 + +; zlib1 v1.2.6 added: + gzgetc_ @161 + inflateResetKeep @163 + deflateResetKeep @164 + +; zlib1 v1.2.7 added: + gzopen_w @165 + +; zlib1 v1.2.8 added: + inflateGetDictionary @166 + gzvprintf @167 + +; zlib1 v1.2.9 added: + inflateCodesUsed @168 + inflateValidate @169 + uncompress2 @170 + gzfread @171 + gzfwrite @172 + deflateGetDictionary @173 + adler32_z @174 + crc32_z @175 diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc12/zlibvc.sln b/dependencies/zlib-1.2.11/contrib/vstudio/vc12/zlibvc.sln new file mode 100644 index 0000000..dcda229 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc12/zlibvc.sln @@ -0,0 +1,119 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.40629.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcxproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcxproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib", "testzlib.vcxproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlibdll", "testzlibdll.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694366A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcxproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Itanium = Debug|Itanium + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Itanium = Release|Itanium + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium + ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32 + ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.ActiveCfg = Debug|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.Build.0 = Debug|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.ActiveCfg = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.Build.0 = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.ActiveCfg = Release|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.Build.0 = Release|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.ActiveCfg = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.ActiveCfg = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.Build.0 = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.ActiveCfg = Debug|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.Build.0 = Debug|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.ActiveCfg = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.ActiveCfg = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.Build.0 = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.ActiveCfg = Release|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.Build.0 = Release|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.Build.0 = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.ActiveCfg = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.Build.0 = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.Build.0 = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.Build.0 = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.Build.0 = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.ActiveCfg = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.Build.0 = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.Build.0 = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.Build.0 = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc12/zlibvc.vcxproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc12/zlibvc.vcxproj new file mode 100644 index 0000000..ab2b6c3 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc12/zlibvc.vcxproj @@ -0,0 +1,692 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {8FD826F8-3739-44E6-8CC8-997122E53B8D} + + + + DynamicLibrary + false + true + v120 + + + DynamicLibrary + false + true + v120 + + + DynamicLibrary + false + v120 + Unicode + + + DynamicLibrary + false + true + v120 + + + DynamicLibrary + false + true + v120 + + + DynamicLibrary + false + v120 + + + DynamicLibrary + false + true + v120 + + + DynamicLibrary + false + true + v120 + + + DynamicLibrary + false + v120 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + true + false + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + false + false + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + false + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + true + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + true + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + false + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + false + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + false + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + zlibwapi + zlibwapi + zlibwapi + zlibwapi + zlibwapi + zlibwapi + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + + + cd ..\..\masmx86 +bld_ml32.bat + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + false + + + cd ..\..\masmx86 +bld_ml32.bat + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + cd ..\..\contrib\masmx64 +bld_ml64.bat + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + cd ..\..\masmx64 +bld_ml64.bat + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + + + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc14/miniunz.vcxproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc14/miniunz.vcxproj new file mode 100644 index 0000000..9b5c075 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc14/miniunz.vcxproj @@ -0,0 +1,316 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {C52F9E7B-498A-42BE-8DB4-85A15694382A} + Win32Proj + + + + Application + MultiByte + v140 + + + Application + Unicode + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\MiniUnzip$(Configuration)\ + x86\MiniUnzip$(Configuration)\Tmp\ + true + false + x86\MiniUnzip$(Configuration)\ + x86\MiniUnzip$(Configuration)\Tmp\ + false + false + x64\MiniUnzip$(Configuration)\ + x64\MiniUnzip$(Configuration)\Tmp\ + true + false + ia64\MiniUnzip$(Configuration)\ + ia64\MiniUnzip$(Configuration)\Tmp\ + true + false + x64\MiniUnzip$(Configuration)\ + x64\MiniUnzip$(Configuration)\Tmp\ + false + false + ia64\MiniUnzip$(Configuration)\ + ia64\MiniUnzip$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc14/minizip.vcxproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc14/minizip.vcxproj new file mode 100644 index 0000000..968a410 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc14/minizip.vcxproj @@ -0,0 +1,313 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B} + Win32Proj + + + + Application + MultiByte + v140 + + + Application + Unicode + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\MiniZip$(Configuration)\ + x86\MiniZip$(Configuration)\Tmp\ + true + false + x86\MiniZip$(Configuration)\ + x86\MiniZip$(Configuration)\Tmp\ + false + x64\$(Configuration)\ + x64\$(Configuration)\ + true + false + ia64\$(Configuration)\ + ia64\$(Configuration)\ + true + false + x64\$(Configuration)\ + x64\$(Configuration)\ + false + ia64\$(Configuration)\ + ia64\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc14/testzlib.vcxproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc14/testzlib.vcxproj new file mode 100644 index 0000000..2c37125 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc14/testzlib.vcxproj @@ -0,0 +1,430 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B} + testzlib + Win32Proj + + + + Application + MultiByte + true + v140 + + + Application + MultiByte + true + v140 + + + Application + Unicode + v140 + + + Application + MultiByte + true + v140 + + + Application + MultiByte + true + v140 + + + Application + MultiByte + v140 + + + Application + true + v140 + + + Application + true + v140 + + + Application + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + true + false + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + false + false + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + false + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + true + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + false + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + AssemblyAndSourceCode + $(IntDir) + Level3 + ProgramDatabase + + + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)testzlib.exe + true + $(OutDir)testzlib.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)testzlib.exe + true + Console + true + true + false + + + MachineX86 + false + + + + + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDebugDLL + false + $(IntDir) + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + + + + + Itanium + + + Disabled + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + AssemblyAndSourceCode + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + $(OutDir)testzlib.pdb + Console + MachineIA64 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDLL + false + $(IntDir) + + + %(AdditionalDependencies) + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + MachineIA64 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDLL + false + $(IntDir) + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + MachineIA64 + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc14/testzlibdll.vcxproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc14/testzlibdll.vcxproj new file mode 100644 index 0000000..d87474d --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc14/testzlibdll.vcxproj @@ -0,0 +1,316 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {C52F9E7B-498A-42BE-8DB4-85A15694366A} + Win32Proj + + + + Application + MultiByte + v140 + + + Application + Unicode + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\TestZlibDll$(Configuration)\ + x86\TestZlibDll$(Configuration)\Tmp\ + true + false + x86\TestZlibDll$(Configuration)\ + x86\TestZlibDll$(Configuration)\Tmp\ + false + false + x64\TestZlibDll$(Configuration)\ + x64\TestZlibDll$(Configuration)\Tmp\ + true + false + ia64\TestZlibDll$(Configuration)\ + ia64\TestZlibDll$(Configuration)\Tmp\ + true + false + x64\TestZlibDll$(Configuration)\ + x64\TestZlibDll$(Configuration)\Tmp\ + false + false + ia64\TestZlibDll$(Configuration)\ + ia64\TestZlibDll$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc14/zlib.rc b/dependencies/zlib-1.2.11/contrib/vstudio/vc14/zlib.rc new file mode 100644 index 0000000..c4e4b01 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc14/zlib.rc @@ -0,0 +1,32 @@ +#include + +#define IDR_VERSION1 1 +IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE + FILEVERSION 1, 2, 11, 0 + PRODUCTVERSION 1, 2, 11, 0 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS 0 + FILEOS VOS_DOS_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0 // not used +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + //language ID = U.S. English, char set = Windows, Multilingual + + BEGIN + VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" + VALUE "FileVersion", "1.2.11\0" + VALUE "InternalName", "zlib\0" + VALUE "OriginalFilename", "zlibwapi.dll\0" + VALUE "ProductName", "ZLib.DLL\0" + VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" + VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1252 + END +END diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc14/zlibstat.vcxproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc14/zlibstat.vcxproj new file mode 100644 index 0000000..3e4b986 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc14/zlibstat.vcxproj @@ -0,0 +1,467 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8} + + + + StaticLibrary + false + v140 + + + StaticLibrary + false + v140 + + + StaticLibrary + false + v140 + Unicode + + + StaticLibrary + false + v140 + + + StaticLibrary + false + v140 + + + StaticLibrary + false + v140 + + + StaticLibrary + false + v140 + + + StaticLibrary + false + v140 + + + StaticLibrary + false + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibstat.lib + true + + + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc14/zlibvc.def b/dependencies/zlib-1.2.11/contrib/vstudio/vc14/zlibvc.def new file mode 100644 index 0000000..54e683d --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc14/zlibvc.def @@ -0,0 +1,153 @@ +LIBRARY +; zlib data compression and ZIP file I/O library + +VERSION 1.2 + +EXPORTS + adler32 @1 + compress @2 + crc32 @3 + deflate @4 + deflateCopy @5 + deflateEnd @6 + deflateInit2_ @7 + deflateInit_ @8 + deflateParams @9 + deflateReset @10 + deflateSetDictionary @11 + gzclose @12 + gzdopen @13 + gzerror @14 + gzflush @15 + gzopen @16 + gzread @17 + gzwrite @18 + inflate @19 + inflateEnd @20 + inflateInit2_ @21 + inflateInit_ @22 + inflateReset @23 + inflateSetDictionary @24 + inflateSync @25 + uncompress @26 + zlibVersion @27 + gzprintf @28 + gzputc @29 + gzgetc @30 + gzseek @31 + gzrewind @32 + gztell @33 + gzeof @34 + gzsetparams @35 + zError @36 + inflateSyncPoint @37 + get_crc_table @38 + compress2 @39 + gzputs @40 + gzgets @41 + inflateCopy @42 + inflateBackInit_ @43 + inflateBack @44 + inflateBackEnd @45 + compressBound @46 + deflateBound @47 + gzclearerr @48 + gzungetc @49 + zlibCompileFlags @50 + deflatePrime @51 + deflatePending @52 + + unzOpen @61 + unzClose @62 + unzGetGlobalInfo @63 + unzGetCurrentFileInfo @64 + unzGoToFirstFile @65 + unzGoToNextFile @66 + unzOpenCurrentFile @67 + unzReadCurrentFile @68 + unzOpenCurrentFile3 @69 + unztell @70 + unzeof @71 + unzCloseCurrentFile @72 + unzGetGlobalComment @73 + unzStringFileNameCompare @74 + unzLocateFile @75 + unzGetLocalExtrafield @76 + unzOpen2 @77 + unzOpenCurrentFile2 @78 + unzOpenCurrentFilePassword @79 + + zipOpen @80 + zipOpenNewFileInZip @81 + zipWriteInFileInZip @82 + zipCloseFileInZip @83 + zipClose @84 + zipOpenNewFileInZip2 @86 + zipCloseFileInZipRaw @87 + zipOpen2 @88 + zipOpenNewFileInZip3 @89 + + unzGetFilePos @100 + unzGoToFilePos @101 + + fill_win32_filefunc @110 + +; zlibwapi v1.2.4 added: + fill_win32_filefunc64 @111 + fill_win32_filefunc64A @112 + fill_win32_filefunc64W @113 + + unzOpen64 @120 + unzOpen2_64 @121 + unzGetGlobalInfo64 @122 + unzGetCurrentFileInfo64 @124 + unzGetCurrentFileZStreamPos64 @125 + unztell64 @126 + unzGetFilePos64 @127 + unzGoToFilePos64 @128 + + zipOpen64 @130 + zipOpen2_64 @131 + zipOpenNewFileInZip64 @132 + zipOpenNewFileInZip2_64 @133 + zipOpenNewFileInZip3_64 @134 + zipOpenNewFileInZip4_64 @135 + zipCloseFileInZipRaw64 @136 + +; zlib1 v1.2.4 added: + adler32_combine @140 + crc32_combine @142 + deflateSetHeader @144 + deflateTune @145 + gzbuffer @146 + gzclose_r @147 + gzclose_w @148 + gzdirect @149 + gzoffset @150 + inflateGetHeader @156 + inflateMark @157 + inflatePrime @158 + inflateReset2 @159 + inflateUndermine @160 + +; zlib1 v1.2.6 added: + gzgetc_ @161 + inflateResetKeep @163 + deflateResetKeep @164 + +; zlib1 v1.2.7 added: + gzopen_w @165 + +; zlib1 v1.2.8 added: + inflateGetDictionary @166 + gzvprintf @167 + +; zlib1 v1.2.9 added: + inflateCodesUsed @168 + inflateValidate @169 + uncompress2 @170 + gzfread @171 + gzfwrite @172 + deflateGetDictionary @173 + adler32_z @174 + crc32_z @175 diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc14/zlibvc.sln b/dependencies/zlib-1.2.11/contrib/vstudio/vc14/zlibvc.sln new file mode 100644 index 0000000..6f4a107 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc14/zlibvc.sln @@ -0,0 +1,119 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcxproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcxproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib", "testzlib.vcxproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlibdll", "testzlibdll.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694366A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcxproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Itanium = Debug|Itanium + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Itanium = Release|Itanium + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium + ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32 + ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.ActiveCfg = Debug|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.Build.0 = Debug|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.ActiveCfg = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.Build.0 = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.ActiveCfg = Release|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.Build.0 = Release|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.ActiveCfg = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.ActiveCfg = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.Build.0 = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.ActiveCfg = Debug|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.Build.0 = Debug|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.ActiveCfg = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.ActiveCfg = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.Build.0 = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.ActiveCfg = Release|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.Build.0 = Release|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.Build.0 = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.ActiveCfg = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.Build.0 = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.Build.0 = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.Build.0 = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.Build.0 = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.ActiveCfg = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.Build.0 = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.Build.0 = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.Build.0 = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc14/zlibvc.vcxproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc14/zlibvc.vcxproj new file mode 100644 index 0000000..f8f673c --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc14/zlibvc.vcxproj @@ -0,0 +1,692 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {8FD826F8-3739-44E6-8CC8-997122E53B8D} + + + + DynamicLibrary + false + true + v140 + + + DynamicLibrary + false + true + v140 + + + DynamicLibrary + false + v140 + Unicode + + + DynamicLibrary + false + true + v140 + + + DynamicLibrary + false + true + v140 + + + DynamicLibrary + false + v140 + + + DynamicLibrary + false + true + v140 + + + DynamicLibrary + false + true + v140 + + + DynamicLibrary + false + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + true + false + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + false + false + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + false + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + true + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + true + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + false + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + false + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + false + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + zlibwapi + zlibwapi + zlibwapi + zlibwapi + zlibwapi + zlibwapi + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + + + cd ..\..\masmx86 +bld_ml32.bat + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + false + + + cd ..\..\masmx86 +bld_ml32.bat + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + cd ..\..\contrib\masmx64 +bld_ml64.bat + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + cd ..\..\masmx64 +bld_ml64.bat + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + + + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc9/miniunz.vcproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc9/miniunz.vcproj new file mode 100644 index 0000000..7da32b9 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc9/miniunz.vcproj @@ -0,0 +1,565 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc9/minizip.vcproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc9/minizip.vcproj new file mode 100644 index 0000000..e57e07d --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc9/minizip.vcproj @@ -0,0 +1,562 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc9/testzlib.vcproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc9/testzlib.vcproj new file mode 100644 index 0000000..9cb0bf8 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc9/testzlib.vcproj @@ -0,0 +1,852 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc9/testzlibdll.vcproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc9/testzlibdll.vcproj new file mode 100644 index 0000000..b1ddde0 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc9/testzlibdll.vcproj @@ -0,0 +1,565 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc9/zlib.rc b/dependencies/zlib-1.2.11/contrib/vstudio/vc9/zlib.rc new file mode 100644 index 0000000..fee177a --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc9/zlib.rc @@ -0,0 +1,32 @@ +#include + +#define IDR_VERSION1 1 +IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE + FILEVERSION 1, 2, 11, 0 + PRODUCTVERSION 1, 2, 11, 0 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS 0 + FILEOS VOS_DOS_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0 // not used +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + //language ID = U.S. English, char set = Windows, Multilingual + + BEGIN + VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" + VALUE "FileVersion", "1.2.11\0" + VALUE "InternalName", "zlib\0" + VALUE "OriginalFilename", "zlibwapi.dll\0" + VALUE "ProductName", "ZLib.DLL\0" + VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" + VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1252 + END +END diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc9/zlibstat.vcproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc9/zlibstat.vcproj new file mode 100644 index 0000000..61c76c7 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc9/zlibstat.vcproj @@ -0,0 +1,835 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc9/zlibvc.def b/dependencies/zlib-1.2.11/contrib/vstudio/vc9/zlibvc.def new file mode 100644 index 0000000..54e683d --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc9/zlibvc.def @@ -0,0 +1,153 @@ +LIBRARY +; zlib data compression and ZIP file I/O library + +VERSION 1.2 + +EXPORTS + adler32 @1 + compress @2 + crc32 @3 + deflate @4 + deflateCopy @5 + deflateEnd @6 + deflateInit2_ @7 + deflateInit_ @8 + deflateParams @9 + deflateReset @10 + deflateSetDictionary @11 + gzclose @12 + gzdopen @13 + gzerror @14 + gzflush @15 + gzopen @16 + gzread @17 + gzwrite @18 + inflate @19 + inflateEnd @20 + inflateInit2_ @21 + inflateInit_ @22 + inflateReset @23 + inflateSetDictionary @24 + inflateSync @25 + uncompress @26 + zlibVersion @27 + gzprintf @28 + gzputc @29 + gzgetc @30 + gzseek @31 + gzrewind @32 + gztell @33 + gzeof @34 + gzsetparams @35 + zError @36 + inflateSyncPoint @37 + get_crc_table @38 + compress2 @39 + gzputs @40 + gzgets @41 + inflateCopy @42 + inflateBackInit_ @43 + inflateBack @44 + inflateBackEnd @45 + compressBound @46 + deflateBound @47 + gzclearerr @48 + gzungetc @49 + zlibCompileFlags @50 + deflatePrime @51 + deflatePending @52 + + unzOpen @61 + unzClose @62 + unzGetGlobalInfo @63 + unzGetCurrentFileInfo @64 + unzGoToFirstFile @65 + unzGoToNextFile @66 + unzOpenCurrentFile @67 + unzReadCurrentFile @68 + unzOpenCurrentFile3 @69 + unztell @70 + unzeof @71 + unzCloseCurrentFile @72 + unzGetGlobalComment @73 + unzStringFileNameCompare @74 + unzLocateFile @75 + unzGetLocalExtrafield @76 + unzOpen2 @77 + unzOpenCurrentFile2 @78 + unzOpenCurrentFilePassword @79 + + zipOpen @80 + zipOpenNewFileInZip @81 + zipWriteInFileInZip @82 + zipCloseFileInZip @83 + zipClose @84 + zipOpenNewFileInZip2 @86 + zipCloseFileInZipRaw @87 + zipOpen2 @88 + zipOpenNewFileInZip3 @89 + + unzGetFilePos @100 + unzGoToFilePos @101 + + fill_win32_filefunc @110 + +; zlibwapi v1.2.4 added: + fill_win32_filefunc64 @111 + fill_win32_filefunc64A @112 + fill_win32_filefunc64W @113 + + unzOpen64 @120 + unzOpen2_64 @121 + unzGetGlobalInfo64 @122 + unzGetCurrentFileInfo64 @124 + unzGetCurrentFileZStreamPos64 @125 + unztell64 @126 + unzGetFilePos64 @127 + unzGoToFilePos64 @128 + + zipOpen64 @130 + zipOpen2_64 @131 + zipOpenNewFileInZip64 @132 + zipOpenNewFileInZip2_64 @133 + zipOpenNewFileInZip3_64 @134 + zipOpenNewFileInZip4_64 @135 + zipCloseFileInZipRaw64 @136 + +; zlib1 v1.2.4 added: + adler32_combine @140 + crc32_combine @142 + deflateSetHeader @144 + deflateTune @145 + gzbuffer @146 + gzclose_r @147 + gzclose_w @148 + gzdirect @149 + gzoffset @150 + inflateGetHeader @156 + inflateMark @157 + inflatePrime @158 + inflateReset2 @159 + inflateUndermine @160 + +; zlib1 v1.2.6 added: + gzgetc_ @161 + inflateResetKeep @163 + deflateResetKeep @164 + +; zlib1 v1.2.7 added: + gzopen_w @165 + +; zlib1 v1.2.8 added: + inflateGetDictionary @166 + gzvprintf @167 + +; zlib1 v1.2.9 added: + inflateCodesUsed @168 + inflateValidate @169 + uncompress2 @170 + gzfread @171 + gzfwrite @172 + deflateGetDictionary @173 + adler32_z @174 + crc32_z @175 diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc9/zlibvc.sln b/dependencies/zlib-1.2.11/contrib/vstudio/vc9/zlibvc.sln new file mode 100644 index 0000000..b482967 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc9/zlibvc.sln @@ -0,0 +1,144 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib", "testzlib.vcproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestZlibDll", "testzlibdll.vcproj", "{C52F9E7B-498A-42BE-8DB4-85A15694366A}" + ProjectSection(ProjectDependencies) = postProject + {8FD826F8-3739-44E6-8CC8-997122E53B8D} = {8FD826F8-3739-44E6-8CC8-997122E53B8D} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}" + ProjectSection(ProjectDependencies) = postProject + {8FD826F8-3739-44E6-8CC8-997122E53B8D} = {8FD826F8-3739-44E6-8CC8-997122E53B8D} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}" + ProjectSection(ProjectDependencies) = postProject + {8FD826F8-3739-44E6-8CC8-997122E53B8D} = {8FD826F8-3739-44E6-8CC8-997122E53B8D} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Itanium = Debug|Itanium + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Itanium = Release|Itanium + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium + ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32 + ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Itanium + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.Build.0 = Debug|Itanium + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.ActiveCfg = Debug|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.Build.0 = Debug|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.ActiveCfg = Release|Itanium + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.Build.0 = Release|Itanium + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.Build.0 = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.ActiveCfg = Release|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.Build.0 = Release|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.ActiveCfg = Debug|Itanium + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.Build.0 = Debug|Itanium + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.ActiveCfg = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.Build.0 = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.ActiveCfg = Debug|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.Build.0 = Debug|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.ActiveCfg = Release|Itanium + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.Build.0 = Release|Itanium + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.ActiveCfg = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.Build.0 = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.ActiveCfg = Release|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.Build.0 = Release|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Itanium + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.Build.0 = Debug|Itanium + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Itanium + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.Build.0 = Release|Itanium + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.ActiveCfg = Debug|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.Build.0 = Debug|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.Build.0 = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.ActiveCfg = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.Build.0 = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.ActiveCfg = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.Build.0 = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.Build.0 = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.Build.0 = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Itanium + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.Build.0 = Debug|Itanium + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Itanium + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.Build.0 = Release|Itanium + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.ActiveCfg = Debug|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.Build.0 = Debug|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.Build.0 = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.ActiveCfg = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.Build.0 = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.ActiveCfg = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.Build.0 = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.Build.0 = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.Build.0 = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/dependencies/zlib-1.2.11/contrib/vstudio/vc9/zlibvc.vcproj b/dependencies/zlib-1.2.11/contrib/vstudio/vc9/zlibvc.vcproj new file mode 100644 index 0000000..c9a8947 --- /dev/null +++ b/dependencies/zlib-1.2.11/contrib/vstudio/vc9/zlibvc.vcproj @@ -0,0 +1,1156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dependencies/zlib-1.2.11/crc32.c b/dependencies/zlib-1.2.11/crc32.c new file mode 100644 index 0000000..9580440 --- /dev/null +++ b/dependencies/zlib-1.2.11/crc32.c @@ -0,0 +1,442 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results in about a + * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id$ */ + +/* + Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore + protection on the static variables used to control the first-use generation + of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should + first call get_crc_table() to initialize the tables before allowing more than + one thread to use crc32(). + + DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h. + */ + +#ifdef MAKECRCH +# include +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +/* Definitions for doing the crc four data bytes at a time. */ +#if !defined(NOBYFOUR) && defined(Z_U4) +# define BYFOUR +#endif +#ifdef BYFOUR + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, z_size_t)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, z_size_t)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +/* Local functions for crc concatenation */ +local unsigned long gf2_matrix_times OF((unsigned long *mat, + unsigned long vec)); +local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); +local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2)); + + +#ifdef DYNAMIC_CRC_TABLE + +local volatile int crc_table_empty = 1; +local z_crc_t FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const z_crc_t FAR *)); +#endif /* MAKECRCH */ +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + z_crc_t c; + int n, k; + z_crc_t poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static volatile int first = 1; /* flag to limit concurrent making */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* See if another task is already doing this (not thread-safe, but better + than nothing -- significantly reduces duration of vulnerability in + case the advice about DYNAMIC_CRC_TABLE is ignored) */ + if (first) { + first = 0; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0; + for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++) + poly |= (z_crc_t)1 << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (z_crc_t)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, + and then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = ZSWAP32(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = ZSWAP32(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + } + else { /* not first */ + /* wait for the other guy to finish (not efficient, but rare) */ + while (crc_table_empty) + ; + } + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const z_crc_t FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const z_crc_t FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", + (unsigned long)(table[n]), + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const z_crc_t FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const z_crc_t FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32_z(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + z_size_t len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + z_crc_t endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + uInt len; +{ + return crc32_z(crc, buf, len); +} + +#ifdef BYFOUR + +/* + This BYFOUR code accesses the passed unsigned char * buffer with a 32-bit + integer pointer type. This violates the strict aliasing rule, where a + compiler can assume, for optimization purposes, that two pointers to + fundamentally different types won't ever point to the same memory. This can + manifest as a problem only if one of the pointers is written to. This code + only reads from those pointers. So long as this code remains isolated in + this compilation unit, there won't be a problem. For this reason, this code + should not be copied and pasted into a compilation unit in which other code + writes to the buffer that is passed to these routines. + */ + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + z_size_t len; +{ + register z_crc_t c; + register const z_crc_t FAR *buf4; + + c = (z_crc_t)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const z_crc_t FAR *)(const void FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *buf4++; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + z_size_t len; +{ + register z_crc_t c; + register const z_crc_t FAR *buf4; + + c = ZSWAP32((z_crc_t)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const z_crc_t FAR *)(const void FAR *)buf; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(ZSWAP32(c)); +} + +#endif /* BYFOUR */ + +#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ + +/* ========================================================================= */ +local unsigned long gf2_matrix_times(mat, vec) + unsigned long *mat; + unsigned long vec; +{ + unsigned long sum; + + sum = 0; + while (vec) { + if (vec & 1) + sum ^= *mat; + vec >>= 1; + mat++; + } + return sum; +} + +/* ========================================================================= */ +local void gf2_matrix_square(square, mat) + unsigned long *square; + unsigned long *mat; +{ + int n; + + for (n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); +} + +/* ========================================================================= */ +local uLong crc32_combine_(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + int n; + unsigned long row; + unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ + unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ + + /* degenerate case (also disallow negative lengths) */ + if (len2 <= 0) + return crc1; + + /* put operator for one zero bit in odd */ + odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ + row = 1; + for (n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } + + /* put operator for two zero bits in even */ + gf2_matrix_square(even, odd); + + /* put operator for four zero bits in odd */ + gf2_matrix_square(odd, even); + + /* apply len2 zeros to crc1 (first square will put the operator for one + zero byte, eight zero bits, in even) */ + do { + /* apply zeros operator for this bit of len2 */ + gf2_matrix_square(even, odd); + if (len2 & 1) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + if (len2 == 0) + break; + + /* another iteration of the loop with odd and even swapped */ + gf2_matrix_square(odd, even); + if (len2 & 1) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + } while (len2 != 0); + + /* return combined crc */ + crc1 ^= crc2; + return crc1; +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} + +uLong ZEXPORT crc32_combine64(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} diff --git a/dependencies/zlib-1.2.11/crc32.h b/dependencies/zlib-1.2.11/crc32.h new file mode 100644 index 0000000..9e0c778 --- /dev/null +++ b/dependencies/zlib-1.2.11/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const z_crc_t FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/dependencies/zlib-1.2.11/deflate.c b/dependencies/zlib-1.2.11/deflate.c new file mode 100644 index 0000000..1ec7614 --- /dev/null +++ b/dependencies/zlib-1.2.11/deflate.c @@ -0,0 +1,2163 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://tools.ietf.org/html/rfc1951 + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id$ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.2.11 Copyright 1995-2017 Jean-loup Gailly and Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local int deflateStateCheck OF((z_streamp strm)); +local void slide_hash OF((deflate_state *s)); +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local block_state deflate_rle OF((deflate_state *s, int flush)); +local block_state deflate_huff OF((deflate_state *s, int flush)); +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local unsigned read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifdef ASMV +# pragma message("Assembler code may have bugs -- use at your own risk") + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif + +#ifdef ZLIB_DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ +#define RANK(f) (((f) * 2) - ((f) > 4 ? 9 : 0)) + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to UPDATE_HASH are made with consecutive input + * characters, so that a running hash key can be computed from the previous + * key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to INSERT_STRING are made with consecutive input + * characters and the first MIN_MATCH bytes of str are valid (except for + * the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* =========================================================================== + * Slide the hash table when sliding the window down (could be avoided with 32 + * bit values at the expense of memory usage). We slide even when level == 0 to + * keep the hash table consistent if we switch back to level > 0 later. + */ +local void slide_hash(s) + deflate_state *s; +{ + unsigned n, m; + Posf *p; + uInt wsize = s->w_size; + + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m - wsize : NIL); + } while (--n); + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m - wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif +} + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; +#endif + } + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED || (windowBits == 8 && wrap != 1)) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + s->status = INIT_STATE; /* to pass state test in deflateReset() */ + + s->wrap = wrap; + s->gzhead = Z_NULL; + s->w_bits = (uInt)windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = (uInt)memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->high_water = 0; /* nothing written to s->window yet */ + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= + * Check for a valid deflate stream state. Return 0 if ok, 1 if not. + */ +local int deflateStateCheck (strm) + z_streamp strm; +{ + deflate_state *s; + if (strm == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) + return 1; + s = strm->state; + if (s == Z_NULL || s->strm != strm || (s->status != INIT_STATE && +#ifdef GZIP + s->status != GZIP_STATE && +#endif + s->status != EXTRA_STATE && + s->status != NAME_STATE && + s->status != COMMENT_STATE && + s->status != HCRC_STATE && + s->status != BUSY_STATE && + s->status != FINISH_STATE)) + return 1; + return 0; +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt str, n; + int wrap; + unsigned avail; + z_const unsigned char *next; + + if (deflateStateCheck(strm) || dictionary == Z_NULL) + return Z_STREAM_ERROR; + s = strm->state; + wrap = s->wrap; + if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead) + return Z_STREAM_ERROR; + + /* when using zlib wrappers, compute Adler-32 for provided dictionary */ + if (wrap == 1) + strm->adler = adler32(strm->adler, dictionary, dictLength); + s->wrap = 0; /* avoid computing Adler-32 in read_buf */ + + /* if dictionary would fill window, just replace the history */ + if (dictLength >= s->w_size) { + if (wrap == 0) { /* already empty otherwise */ + CLEAR_HASH(s); + s->strstart = 0; + s->block_start = 0L; + s->insert = 0; + } + dictionary += dictLength - s->w_size; /* use the tail */ + dictLength = s->w_size; + } + + /* insert dictionary into window and hash */ + avail = strm->avail_in; + next = strm->next_in; + strm->avail_in = dictLength; + strm->next_in = (z_const Bytef *)dictionary; + fill_window(s); + while (s->lookahead >= MIN_MATCH) { + str = s->strstart; + n = s->lookahead - (MIN_MATCH-1); + do { + UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); +#ifndef FASTEST + s->prev[str & s->w_mask] = s->head[s->ins_h]; +#endif + s->head[s->ins_h] = (Pos)str; + str++; + } while (--n); + s->strstart = str; + s->lookahead = MIN_MATCH-1; + fill_window(s); + } + s->strstart += s->lookahead; + s->block_start = (long)s->strstart; + s->insert = s->lookahead; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + strm->next_in = next; + strm->avail_in = avail; + s->wrap = wrap; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateGetDictionary (strm, dictionary, dictLength) + z_streamp strm; + Bytef *dictionary; + uInt *dictLength; +{ + deflate_state *s; + uInt len; + + if (deflateStateCheck(strm)) + return Z_STREAM_ERROR; + s = strm->state; + len = s->strstart + s->lookahead; + if (len > s->w_size) + len = s->w_size; + if (dictionary != Z_NULL && len) + zmemcpy(dictionary, s->window + s->strstart + s->lookahead - len, len); + if (dictLength != Z_NULL) + *dictLength = len; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateResetKeep (strm) + z_streamp strm; +{ + deflate_state *s; + + if (deflateStateCheck(strm)) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = +#ifdef GZIP + s->wrap == 2 ? GZIP_STATE : +#endif + s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + int ret; + + ret = deflateResetKeep(strm); + if (ret == Z_OK) + lm_init(strm->state); + return ret; +} + +/* ========================================================================= */ +int ZEXPORT deflateSetHeader (strm, head) + z_streamp strm; + gz_headerp head; +{ + if (deflateStateCheck(strm) || strm->state->wrap != 2) + return Z_STREAM_ERROR; + strm->state->gzhead = head; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePending (strm, pending, bits) + unsigned *pending; + int *bits; + z_streamp strm; +{ + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; + if (pending != Z_NULL) + *pending = strm->state->pending; + if (bits != Z_NULL) + *bits = strm->state->bi_valid; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (strm, bits, value) + z_streamp strm; + int bits; + int value; +{ + deflate_state *s; + int put; + + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; + s = strm->state; + if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) + return Z_BUF_ERROR; + do { + put = Buf_size - s->bi_valid; + if (put > bits) + put = bits; + s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid); + s->bi_valid += put; + _tr_flush_bits(s); + value >>= put; + bits -= put; + } while (bits); + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; + s = strm->state; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if ((strategy != s->strategy || func != configuration_table[level].func) && + s->high_water) { + /* Flush the last buffer: */ + int err = deflate(strm, Z_BLOCK); + if (err == Z_STREAM_ERROR) + return err; + if (strm->avail_out == 0) + return Z_BUF_ERROR; + } + if (s->level != level) { + if (s->level == 0 && s->matches != 0) { + if (s->matches == 1) + slide_hash(s); + else + CLEAR_HASH(s); + s->matches = 0; + } + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) + z_streamp strm; + int good_length; + int max_lazy; + int nice_length; + int max_chain; +{ + deflate_state *s; + + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; + s = strm->state; + s->good_match = (uInt)good_length; + s->max_lazy_match = (uInt)max_lazy; + s->nice_match = nice_length; + s->max_chain_length = (uInt)max_chain; + return Z_OK; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds for + * every combination of windowBits and memLevel. But even the conservative + * upper bound of about 14% expansion does not seem onerous for output buffer + * allocation. + */ +uLong ZEXPORT deflateBound(strm, sourceLen) + z_streamp strm; + uLong sourceLen; +{ + deflate_state *s; + uLong complen, wraplen; + + /* conservative upper bound for compressed data */ + complen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; + + /* if can't get parameters, return conservative bound plus zlib wrapper */ + if (deflateStateCheck(strm)) + return complen + 6; + + /* compute wrapper length */ + s = strm->state; + switch (s->wrap) { + case 0: /* raw deflate */ + wraplen = 0; + break; + case 1: /* zlib wrapper */ + wraplen = 6 + (s->strstart ? 4 : 0); + break; +#ifdef GZIP + case 2: /* gzip wrapper */ + wraplen = 18; + if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ + Bytef *str; + if (s->gzhead->extra != Z_NULL) + wraplen += 2 + s->gzhead->extra_len; + str = s->gzhead->name; + if (str != Z_NULL) + do { + wraplen++; + } while (*str++); + str = s->gzhead->comment; + if (str != Z_NULL) + do { + wraplen++; + } while (*str++); + if (s->gzhead->hcrc) + wraplen += 2; + } + break; +#endif + default: /* for compiler happiness */ + wraplen = 6; + } + + /* if not default parameters, return conservative bound */ + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return complen + wraplen; + + /* default settings: return tight bound for that case */ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + + (sourceLen >> 25) + 13 - 6 + wraplen; +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output, except for + * some deflate_stored() output, goes through this function so some + * applications may wish to modify it to avoid allocating a large + * strm->next_out buffer and copying into it. (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len; + deflate_state *s = strm->state; + + _tr_flush_bits(s); + len = s->pending; + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, s->pending_out, len); + strm->next_out += len; + s->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + s->pending -= len; + if (s->pending == 0) { + s->pending_out = s->pending_buf; + } +} + +/* =========================================================================== + * Update the header CRC with the bytes s->pending_buf[beg..s->pending - 1]. + */ +#define HCRC_UPDATE(beg) \ + do { \ + if (s->gzhead->hcrc && s->pending > (beg)) \ + strm->adler = crc32(strm->adler, s->pending_buf + (beg), \ + s->pending - (beg)); \ + } while (0) + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->avail_in != 0 && strm->next_in == Z_NULL) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + old_flush = s->last_flush; + s->last_flush = flush; + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Write the header */ + if (s->status == INIT_STATE) { + /* zlib header */ + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + s->status = BUSY_STATE; + + /* Compression must start with an empty pending buffer */ + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } +#ifdef GZIP + if (s->status == GZIP_STATE) { + /* gzip header */ + strm->adler = crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (s->gzhead == Z_NULL) { + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s->status = BUSY_STATE; + + /* Compression must start with an empty pending buffer */ + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } + else { + put_byte(s, (s->gzhead->text ? 1 : 0) + + (s->gzhead->hcrc ? 2 : 0) + + (s->gzhead->extra == Z_NULL ? 0 : 4) + + (s->gzhead->name == Z_NULL ? 0 : 8) + + (s->gzhead->comment == Z_NULL ? 0 : 16) + ); + put_byte(s, (Byte)(s->gzhead->time & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, s->gzhead->os & 0xff); + if (s->gzhead->extra != Z_NULL) { + put_byte(s, s->gzhead->extra_len & 0xff); + put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); + } + if (s->gzhead->hcrc) + strm->adler = crc32(strm->adler, s->pending_buf, + s->pending); + s->gzindex = 0; + s->status = EXTRA_STATE; + } + } + if (s->status == EXTRA_STATE) { + if (s->gzhead->extra != Z_NULL) { + ulg beg = s->pending; /* start of bytes to update crc */ + uInt left = (s->gzhead->extra_len & 0xffff) - s->gzindex; + while (s->pending + left > s->pending_buf_size) { + uInt copy = s->pending_buf_size - s->pending; + zmemcpy(s->pending_buf + s->pending, + s->gzhead->extra + s->gzindex, copy); + s->pending = s->pending_buf_size; + HCRC_UPDATE(beg); + s->gzindex += copy; + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + beg = 0; + left -= copy; + } + zmemcpy(s->pending_buf + s->pending, + s->gzhead->extra + s->gzindex, left); + s->pending += left; + HCRC_UPDATE(beg); + s->gzindex = 0; + } + s->status = NAME_STATE; + } + if (s->status == NAME_STATE) { + if (s->gzhead->name != Z_NULL) { + ulg beg = s->pending; /* start of bytes to update crc */ + int val; + do { + if (s->pending == s->pending_buf_size) { + HCRC_UPDATE(beg); + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + beg = 0; + } + val = s->gzhead->name[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + HCRC_UPDATE(beg); + s->gzindex = 0; + } + s->status = COMMENT_STATE; + } + if (s->status == COMMENT_STATE) { + if (s->gzhead->comment != Z_NULL) { + ulg beg = s->pending; /* start of bytes to update crc */ + int val; + do { + if (s->pending == s->pending_buf_size) { + HCRC_UPDATE(beg); + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + beg = 0; + } + val = s->gzhead->comment[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + HCRC_UPDATE(beg); + } + s->status = HCRC_STATE; + } + if (s->status == HCRC_STATE) { + if (s->gzhead->hcrc) { + if (s->pending + 2 > s->pending_buf_size) { + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + strm->adler = crc32(0L, Z_NULL, 0); + } + s->status = BUSY_STATE; + + /* Compression must start with an empty pending buffer */ + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } +#endif + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = s->level == 0 ? deflate_stored(s, flush) : + s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : + s->strategy == Z_RLE ? deflate_rle(s, flush) : + (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + if (s->lookahead == 0) { + s->strstart = 0; + s->block_start = 0L; + s->insert = 0; + } + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else +#endif + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; + + status = strm->state->status; + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (deflateStateCheck(source) || dest == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state)); + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif /* MAXSEG_64K */ +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local unsigned read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + zmemcpy(buf, strm->next_in, len); + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, buf, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, buf, len); + } +#endif + strm->next_in += len; + strm->total_in += len; + + return len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->insert = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifndef FASTEST +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +#endif +} + +#ifndef FASTEST +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = (int)s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = (int)s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} +#endif /* ASMV */ + +#else /* FASTEST */ + +/* --------------------------------------------------------------------------- + * Optimized version for FASTEST only + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} + +#endif /* FASTEST */ + +#ifdef ZLIB_DEBUG + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif /* ZLIB_DEBUG */ + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + unsigned n; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize - more); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + slide_hash(s); + more += wsize; + } + if (s->strm->avail_in == 0) break; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead + s->insert >= MIN_MATCH) { + uInt str = s->strstart - s->insert; + s->ins_h = s->window[str]; + UPDATE_HASH(s, s->ins_h, s->window[str + 1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + while (s->insert) { + UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); +#ifndef FASTEST + s->prev[str & s->w_mask] = s->head[s->ins_h]; +#endif + s->head[s->ins_h] = (Pos)str; + str++; + s->insert--; + if (s->lookahead + s->insert < MIN_MATCH) + break; + } + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); + + /* If the WIN_INIT bytes after the end of the current data have never been + * written, then zero those bytes in order to avoid memory check reports of + * the use of uninitialized (or uninitialised as Julian writes) bytes by + * the longest match routines. Update the high water mark for the next + * time through here. WIN_INIT is set to MAX_MATCH since the longest match + * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. + */ + if (s->high_water < s->window_size) { + ulg curr = s->strstart + (ulg)(s->lookahead); + ulg init; + + if (s->high_water < curr) { + /* Previous high water mark below current data -- zero WIN_INIT + * bytes or up to end of window, whichever is less. + */ + init = s->window_size - curr; + if (init > WIN_INIT) + init = WIN_INIT; + zmemzero(s->window + curr, (unsigned)init); + s->high_water = curr + init; + } + else if (s->high_water < (ulg)curr + WIN_INIT) { + /* High water mark at or above current data, but below current data + * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up + * to end of window, whichever is less. + */ + init = (ulg)curr + WIN_INIT - s->high_water; + if (init > s->window_size - s->high_water) + init = s->window_size - s->high_water; + zmemzero(s->window + s->high_water, (unsigned)init); + s->high_water += init; + } + } + + Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, + "not enough room for search"); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, last) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (last)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, last) { \ + FLUSH_BLOCK_ONLY(s, last); \ + if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ +} + +/* Maximum stored block length in deflate format (not including header). */ +#define MAX_STORED 65535 + +/* Minimum of a and b. */ +#define MIN(a, b) ((a) > (b) ? (b) : (a)) + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * + * In case deflateParams() is used to later switch to a non-zero compression + * level, s->matches (otherwise unused when storing) keeps track of the number + * of hash table slides to perform. If s->matches is 1, then one hash table + * slide will be done when switching. If s->matches is 2, the maximum value + * allowed here, then the hash table will be cleared, since two or more slides + * is the same as a clear. + * + * deflate_stored() is written to minimize the number of times an input byte is + * copied. It is most efficient with large input and output buffers, which + * maximizes the opportunites to have a single copy from next_in to next_out. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Smallest worthy block size when not flushing or finishing. By default + * this is 32K. This can be as small as 507 bytes for memLevel == 1. For + * large input and output buffers, the stored block size will be larger. + */ + unsigned min_block = MIN(s->pending_buf_size - 5, s->w_size); + + /* Copy as many min_block or larger stored blocks directly to next_out as + * possible. If flushing, copy the remaining available input to next_out as + * stored blocks, if there is enough space. + */ + unsigned len, left, have, last = 0; + unsigned used = s->strm->avail_in; + do { + /* Set len to the maximum size block that we can copy directly with the + * available input data and output space. Set left to how much of that + * would be copied from what's left in the window. + */ + len = MAX_STORED; /* maximum deflate stored block length */ + have = (s->bi_valid + 42) >> 3; /* number of header bytes */ + if (s->strm->avail_out < have) /* need room for header */ + break; + /* maximum stored block length that will fit in avail_out: */ + have = s->strm->avail_out - have; + left = s->strstart - s->block_start; /* bytes left in window */ + if (len > (ulg)left + s->strm->avail_in) + len = left + s->strm->avail_in; /* limit len to the input */ + if (len > have) + len = have; /* limit len to the output */ + + /* If the stored block would be less than min_block in length, or if + * unable to copy all of the available input when flushing, then try + * copying to the window and the pending buffer instead. Also don't + * write an empty block when flushing -- deflate() does that. + */ + if (len < min_block && ((len == 0 && flush != Z_FINISH) || + flush == Z_NO_FLUSH || + len != left + s->strm->avail_in)) + break; + + /* Make a dummy stored block in pending to get the header bytes, + * including any pending bits. This also updates the debugging counts. + */ + last = flush == Z_FINISH && len == left + s->strm->avail_in ? 1 : 0; + _tr_stored_block(s, (char *)0, 0L, last); + + /* Replace the lengths in the dummy stored block with len. */ + s->pending_buf[s->pending - 4] = len; + s->pending_buf[s->pending - 3] = len >> 8; + s->pending_buf[s->pending - 2] = ~len; + s->pending_buf[s->pending - 1] = ~len >> 8; + + /* Write the stored block header bytes. */ + flush_pending(s->strm); + +#ifdef ZLIB_DEBUG + /* Update debugging counts for the data about to be copied. */ + s->compressed_len += len << 3; + s->bits_sent += len << 3; +#endif + + /* Copy uncompressed bytes from the window to next_out. */ + if (left) { + if (left > len) + left = len; + zmemcpy(s->strm->next_out, s->window + s->block_start, left); + s->strm->next_out += left; + s->strm->avail_out -= left; + s->strm->total_out += left; + s->block_start += left; + len -= left; + } + + /* Copy uncompressed bytes directly from next_in to next_out, updating + * the check value. + */ + if (len) { + read_buf(s->strm, s->strm->next_out, len); + s->strm->next_out += len; + s->strm->avail_out -= len; + s->strm->total_out += len; + } + } while (last == 0); + + /* Update the sliding window with the last s->w_size bytes of the copied + * data, or append all of the copied data to the existing window if less + * than s->w_size bytes were copied. Also update the number of bytes to + * insert in the hash tables, in the event that deflateParams() switches to + * a non-zero compression level. + */ + used -= s->strm->avail_in; /* number of input bytes directly copied */ + if (used) { + /* If any input was used, then no unused input remains in the window, + * therefore s->block_start == s->strstart. + */ + if (used >= s->w_size) { /* supplant the previous history */ + s->matches = 2; /* clear hash */ + zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size); + s->strstart = s->w_size; + } + else { + if (s->window_size - s->strstart <= used) { + /* Slide the window down. */ + s->strstart -= s->w_size; + zmemcpy(s->window, s->window + s->w_size, s->strstart); + if (s->matches < 2) + s->matches++; /* add a pending slide_hash() */ + } + zmemcpy(s->window + s->strstart, s->strm->next_in - used, used); + s->strstart += used; + } + s->block_start = s->strstart; + s->insert += MIN(used, s->w_size - s->insert); + } + if (s->high_water < s->strstart) + s->high_water = s->strstart; + + /* If the last block was written to next_out, then done. */ + if (last) + return finish_done; + + /* If flushing and all input has been consumed, then done. */ + if (flush != Z_NO_FLUSH && flush != Z_FINISH && + s->strm->avail_in == 0 && (long)s->strstart == s->block_start) + return block_done; + + /* Fill the window with any remaining input. */ + have = s->window_size - s->strstart - 1; + if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) { + /* Slide the window down. */ + s->block_start -= s->w_size; + s->strstart -= s->w_size; + zmemcpy(s->window, s->window + s->w_size, s->strstart); + if (s->matches < 2) + s->matches++; /* add a pending slide_hash() */ + have += s->w_size; /* more space now */ + } + if (have > s->strm->avail_in) + have = s->strm->avail_in; + if (have) { + read_buf(s->strm, s->window + s->strstart, have); + s->strstart += have; + } + if (s->high_water < s->strstart) + s->high_water = s->strstart; + + /* There was not enough avail_out to write a complete worthy or flushed + * stored block to next_out. Write a stored block to pending instead, if we + * have enough input for a worthy block, or if flushing and there is enough + * room for the remaining input as a stored block in the pending buffer. + */ + have = (s->bi_valid + 42) >> 3; /* number of header bytes */ + /* maximum stored block length that will fit in pending: */ + have = MIN(s->pending_buf_size - have, MAX_STORED); + min_block = MIN(have, s->w_size); + left = s->strstart - s->block_start; + if (left >= min_block || + ((left || flush == Z_FINISH) && flush != Z_NO_FLUSH && + s->strm->avail_in == 0 && left <= have)) { + len = MIN(left, have); + last = flush == Z_FINISH && s->strm->avail_in == 0 && + len == left ? 1 : 0; + _tr_stored_block(s, (charf *)s->window + s->block_start, len, last); + s->block_start += len; + flush_pending(s->strm); + } + + /* We've done all we can with the available input and output. */ + return last ? finish_started : need_more; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = NIL; + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s->match_length = longest_match (s, hash_head); + /* longest_match() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->last_lit) + FLUSH_BLOCK(s, 0); + return block_done; +} + +#ifndef FASTEST +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = NIL; + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s->match_length = longest_match (s, hash_head); + /* longest_match() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED +#if TOO_FAR <= 32767 + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) +#endif + )) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->last_lit) + FLUSH_BLOCK(s, 0); + return block_done; +} +#endif /* FASTEST */ + +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ +local block_state deflate_rle(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + uInt prev; /* byte at distance one to match */ + Bytef *scan, *strend; /* scan goes up to strend for length of run */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest run, plus one for the unrolled loop. + */ + if (s->lookahead <= MAX_MATCH) { + fill_window(s); + if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + s->match_length = 0; + if (s->lookahead >= MIN_MATCH && s->strstart > 0) { + scan = s->window + s->strstart - 1; + prev = *scan; + if (prev == *++scan && prev == *++scan && prev == *++scan) { + strend = s->window + s->strstart + MAX_MATCH; + do { + } while (prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + scan < strend); + s->match_length = MAX_MATCH - (uInt)(strend - scan); + if (s->match_length > s->lookahead) + s->match_length = s->lookahead; + } + Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->strstart - 1, s->match_length); + + _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + s->strstart += s->match_length; + s->match_length = 0; + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + s->insert = 0; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->last_lit) + FLUSH_BLOCK(s, 0); + return block_done; +} + +/* =========================================================================== + * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. + * (It will be regenerated if this run of deflate switches away from Huffman.) + */ +local block_state deflate_huff(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we have a literal to write. */ + if (s->lookahead == 0) { + fill_window(s); + if (s->lookahead == 0) { + if (flush == Z_NO_FLUSH) + return need_more; + break; /* flush the current block */ + } + } + + /* Output a literal byte */ + s->match_length = 0; + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + if (bflush) FLUSH_BLOCK(s, 0); + } + s->insert = 0; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->last_lit) + FLUSH_BLOCK(s, 0); + return block_done; +} diff --git a/dependencies/zlib-1.2.11/deflate.h b/dependencies/zlib-1.2.11/deflate.h new file mode 100644 index 0000000..23ecdd3 --- /dev/null +++ b/dependencies/zlib-1.2.11/deflate.h @@ -0,0 +1,349 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2016 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define Buf_size 16 +/* size of bit buffer in bi_buf */ + +#define INIT_STATE 42 /* zlib header -> BUSY_STATE */ +#ifdef GZIP +# define GZIP_STATE 57 /* gzip header -> BUSY_STATE | EXTRA_STATE */ +#endif +#define EXTRA_STATE 69 /* gzip extra block -> NAME_STATE */ +#define NAME_STATE 73 /* gzip file name -> COMMENT_STATE */ +#define COMMENT_STATE 91 /* gzip comment -> HCRC_STATE */ +#define HCRC_STATE 103 /* gzip header CRC -> BUSY_STATE */ +#define BUSY_STATE 113 /* deflate -> FINISH_STATE */ +#define FINISH_STATE 666 /* stream complete */ +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + const static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + ulg pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + gz_headerp gzhead; /* gzip header information to write */ + ulg gzindex; /* where in extra, name, or comment */ + Byte method; /* can only be DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to suppress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + uInt insert; /* bytes at end of window left to insert */ + +#ifdef ZLIB_DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + + ulg high_water; + /* High water mark offset in window for initialized bytes -- bytes above + * this are set to zero in order to avoid memory check warnings when + * longest match routines access bytes past the input. This is then + * updated to the new high water mark. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (Bytef)(c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + +#define WIN_INIT MAX_MATCH +/* Number of bytes after end of data in window to initialize in order to avoid + memory checker errors from longest match routines */ + + /* in trees.c */ +void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); +int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, + ulg stored_len, int last)); +void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s)); +void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); +void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, + ulg stored_len, int last)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef ZLIB_DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch ZLIB_INTERNAL _length_code[]; + extern uch ZLIB_INTERNAL _dist_code[]; +#else + extern const uch ZLIB_INTERNAL _length_code[]; + extern const uch ZLIB_INTERNAL _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (uch)(length); \ + ush dist = (ush)(distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/dependencies/zlib-1.2.11/doc/algorithm.txt b/dependencies/zlib-1.2.11/doc/algorithm.txt new file mode 100644 index 0000000..c97f495 --- /dev/null +++ b/dependencies/zlib-1.2.11/doc/algorithm.txt @@ -0,0 +1,209 @@ +1. Compression algorithm (deflate) + +The deflation algorithm used by gzip (also zip and zlib) is a variation of +LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in +the input data. The second occurrence of a string is replaced by a +pointer to the previous string, in the form of a pair (distance, +length). Distances are limited to 32K bytes, and lengths are limited +to 258 bytes. When a string does not occur anywhere in the previous +32K bytes, it is emitted as a sequence of literal bytes. (In this +description, `string' must be taken as an arbitrary sequence of bytes, +and is not restricted to printable characters.) + +Literals or match lengths are compressed with one Huffman tree, and +match distances are compressed with another tree. The trees are stored +in a compact form at the start of each block. The blocks can have any +size (except that the compressed data for one block must fit in +available memory). A block is terminated when deflate() determines that +it would be useful to start another block with fresh trees. (This is +somewhat similar to the behavior of LZW-based _compress_.) + +Duplicated strings are found using a hash table. All input strings of +length 3 are inserted in the hash table. A hash index is computed for +the next 3 bytes. If the hash chain for this index is not empty, all +strings in the chain are compared with the current input string, and +the longest match is selected. + +The hash chains are searched starting with the most recent strings, to +favor small distances and thus take advantage of the Huffman encoding. +The hash chains are singly linked. There are no deletions from the +hash chains, the algorithm simply discards matches that are too old. + +To avoid a worst-case situation, very long hash chains are arbitrarily +truncated at a certain length, determined by a runtime option (level +parameter of deflateInit). So deflate() does not always find the longest +possible match but generally finds a match which is long enough. + +deflate() also defers the selection of matches with a lazy evaluation +mechanism. After a match of length N has been found, deflate() searches for +a longer match at the next input byte. If a longer match is found, the +previous match is truncated to a length of one (thus producing a single +literal byte) and the process of lazy evaluation begins again. Otherwise, +the original match is kept, and the next match search is attempted only N +steps later. + +The lazy match evaluation is also subject to a runtime parameter. If +the current match is long enough, deflate() reduces the search for a longer +match, thus speeding up the whole process. If compression ratio is more +important than speed, deflate() attempts a complete second search even if +the first match is already long enough. + +The lazy match evaluation is not performed for the fastest compression +modes (level parameter 1 to 3). For these fast modes, new strings +are inserted in the hash table only when no match was found, or +when the match is not too long. This degrades the compression ratio +but saves time since there are both fewer insertions and fewer searches. + + +2. Decompression algorithm (inflate) + +2.1 Introduction + +The key question is how to represent a Huffman code (or any prefix code) so +that you can decode fast. The most important characteristic is that shorter +codes are much more common than longer codes, so pay attention to decoding the +short codes fast, and let the long codes take longer to decode. + +inflate() sets up a first level table that covers some number of bits of +input less than the length of longest code. It gets that many bits from the +stream, and looks it up in the table. The table will tell if the next +code is that many bits or less and how many, and if it is, it will tell +the value, else it will point to the next level table for which inflate() +grabs more bits and tries to decode a longer code. + +How many bits to make the first lookup is a tradeoff between the time it +takes to decode and the time it takes to build the table. If building the +table took no time (and if you had infinite memory), then there would only +be a first level table to cover all the way to the longest code. However, +building the table ends up taking a lot longer for more bits since short +codes are replicated many times in such a table. What inflate() does is +simply to make the number of bits in the first table a variable, and then +to set that variable for the maximum speed. + +For inflate, which has 286 possible codes for the literal/length tree, the size +of the first table is nine bits. Also the distance trees have 30 possible +values, and the size of the first table is six bits. Note that for each of +those cases, the table ended up one bit longer than the ``average'' code +length, i.e. the code length of an approximately flat code which would be a +little more than eight bits for 286 symbols and a little less than five bits +for 30 symbols. + + +2.2 More details on the inflate table lookup + +Ok, you want to know what this cleverly obfuscated inflate tree actually +looks like. You are correct that it's not a Huffman tree. It is simply a +lookup table for the first, let's say, nine bits of a Huffman symbol. The +symbol could be as short as one bit or as long as 15 bits. If a particular +symbol is shorter than nine bits, then that symbol's translation is duplicated +in all those entries that start with that symbol's bits. For example, if the +symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a +symbol is nine bits long, it appears in the table once. + +If the symbol is longer than nine bits, then that entry in the table points +to another similar table for the remaining bits. Again, there are duplicated +entries as needed. The idea is that most of the time the symbol will be short +and there will only be one table look up. (That's whole idea behind data +compression in the first place.) For the less frequent long symbols, there +will be two lookups. If you had a compression method with really long +symbols, you could have as many levels of lookups as is efficient. For +inflate, two is enough. + +So a table entry either points to another table (in which case nine bits in +the above example are gobbled), or it contains the translation for the symbol +and the number of bits to gobble. Then you start again with the next +ungobbled bit. + +You may wonder: why not just have one lookup table for how ever many bits the +longest symbol is? The reason is that if you do that, you end up spending +more time filling in duplicate symbol entries than you do actually decoding. +At least for deflate's output that generates new trees every several 10's of +kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code +would take too long if you're only decoding several thousand symbols. At the +other extreme, you could make a new table for every bit in the code. In fact, +that's essentially a Huffman tree. But then you spend too much time +traversing the tree while decoding, even for short symbols. + +So the number of bits for the first lookup table is a trade of the time to +fill out the table vs. the time spent looking at the second level and above of +the table. + +Here is an example, scaled down: + +The code being decoded, with 10 symbols, from 1 to 6 bits long: + +A: 0 +B: 10 +C: 1100 +D: 11010 +E: 11011 +F: 11100 +G: 11101 +H: 11110 +I: 111110 +J: 111111 + +Let's make the first table three bits long (eight entries): + +000: A,1 +001: A,1 +010: A,1 +011: A,1 +100: B,2 +101: B,2 +110: -> table X (gobble 3 bits) +111: -> table Y (gobble 3 bits) + +Each entry is what the bits decode as and how many bits that is, i.e. how +many bits to gobble. Or the entry points to another table, with the number of +bits to gobble implicit in the size of the table. + +Table X is two bits long since the longest code starting with 110 is five bits +long: + +00: C,1 +01: C,1 +10: D,2 +11: E,2 + +Table Y is three bits long since the longest code starting with 111 is six +bits long: + +000: F,2 +001: F,2 +010: G,2 +011: G,2 +100: H,2 +101: H,2 +110: I,3 +111: J,3 + +So what we have here are three tables with a total of 20 entries that had to +be constructed. That's compared to 64 entries for a single table. Or +compared to 16 entries for a Huffman tree (six two entry tables and one four +entry table). Assuming that the code ideally represents the probability of +the symbols, it takes on the average 1.25 lookups per symbol. That's compared +to one lookup for the single table, or 1.66 lookups per symbol for the +Huffman tree. + +There, I think that gives you a picture of what's going on. For inflate, the +meaning of a particular symbol is often more than just a letter. It can be a +byte (a "literal"), or it can be either a length or a distance which +indicates a base value and a number of bits to fetch after the code that is +added to the base value. Or it might be the special end-of-block code. The +data structures created in inftrees.c try to encode all that information +compactly in the tables. + + +Jean-loup Gailly Mark Adler +jloup@gzip.org madler@alumni.caltech.edu + + +References: + +[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data +Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3, +pp. 337-343. + +``DEFLATE Compressed Data Format Specification'' available in +http://tools.ietf.org/html/rfc1951 diff --git a/dependencies/zlib-1.2.11/doc/rfc1950.txt b/dependencies/zlib-1.2.11/doc/rfc1950.txt new file mode 100644 index 0000000..ce6428a --- /dev/null +++ b/dependencies/zlib-1.2.11/doc/rfc1950.txt @@ -0,0 +1,619 @@ + + + + + + +Network Working Group P. Deutsch +Request for Comments: 1950 Aladdin Enterprises +Category: Informational J-L. Gailly + Info-ZIP + May 1996 + + + ZLIB Compressed Data Format Specification version 3.3 + +Status of This Memo + + This memo provides information for the Internet community. This memo + does not specify an Internet standard of any kind. Distribution of + this memo is unlimited. + +IESG Note: + + The IESG takes no position on the validity of any Intellectual + Property Rights statements contained in this document. + +Notices + + Copyright (c) 1996 L. Peter Deutsch and Jean-Loup Gailly + + Permission is granted to copy and distribute this document for any + purpose and without charge, including translations into other + languages and incorporation into compilations, provided that the + copyright notice and this notice are preserved, and that any + substantive changes or deletions from the original are clearly + marked. + + A pointer to the latest version of this and related documentation in + HTML format can be found at the URL + . + +Abstract + + This specification defines a lossless compressed data format. The + data can be produced or consumed, even for an arbitrarily long + sequentially presented input data stream, using only an a priori + bounded amount of intermediate storage. The format presently uses + the DEFLATE compression method but can be easily extended to use + other compression methods. It can be implemented readily in a manner + not covered by patents. This specification also defines the ADLER-32 + checksum (an extension and improvement of the Fletcher checksum), + used for detection of data corruption, and provides an algorithm for + computing it. + + + + +Deutsch & Gailly Informational [Page 1] + +RFC 1950 ZLIB Compressed Data Format Specification May 1996 + + +Table of Contents + + 1. Introduction ................................................... 2 + 1.1. Purpose ................................................... 2 + 1.2. Intended audience ......................................... 3 + 1.3. Scope ..................................................... 3 + 1.4. Compliance ................................................ 3 + 1.5. Definitions of terms and conventions used ................ 3 + 1.6. Changes from previous versions ............................ 3 + 2. Detailed specification ......................................... 3 + 2.1. Overall conventions ....................................... 3 + 2.2. Data format ............................................... 4 + 2.3. Compliance ................................................ 7 + 3. References ..................................................... 7 + 4. Source code .................................................... 8 + 5. Security Considerations ........................................ 8 + 6. Acknowledgements ............................................... 8 + 7. Authors' Addresses ............................................. 8 + 8. Appendix: Rationale ............................................ 9 + 9. Appendix: Sample code ..........................................10 + +1. Introduction + + 1.1. Purpose + + The purpose of this specification is to define a lossless + compressed data format that: + + * Is independent of CPU type, operating system, file system, + and character set, and hence can be used for interchange; + + * Can be produced or consumed, even for an arbitrarily long + sequentially presented input data stream, using only an a + priori bounded amount of intermediate storage, and hence can + be used in data communications or similar structures such as + Unix filters; + + * Can use a number of different compression methods; + + * Can be implemented readily in a manner not covered by + patents, and hence can be practiced freely. + + The data format defined by this specification does not attempt to + allow random access to compressed data. + + + + + + + +Deutsch & Gailly Informational [Page 2] + +RFC 1950 ZLIB Compressed Data Format Specification May 1996 + + + 1.2. Intended audience + + This specification is intended for use by implementors of software + to compress data into zlib format and/or decompress data from zlib + format. + + The text of the specification assumes a basic background in + programming at the level of bits and other primitive data + representations. + + 1.3. Scope + + The specification specifies a compressed data format that can be + used for in-memory compression of a sequence of arbitrary bytes. + + 1.4. Compliance + + Unless otherwise indicated below, a compliant decompressor must be + able to accept and decompress any data set that conforms to all + the specifications presented here; a compliant compressor must + produce data sets that conform to all the specifications presented + here. + + 1.5. Definitions of terms and conventions used + + byte: 8 bits stored or transmitted as a unit (same as an octet). + (For this specification, a byte is exactly 8 bits, even on + machines which store a character on a number of bits different + from 8.) See below, for the numbering of bits within a byte. + + 1.6. Changes from previous versions + + Version 3.1 was the first public release of this specification. + In version 3.2, some terminology was changed and the Adler-32 + sample code was rewritten for clarity. In version 3.3, the + support for a preset dictionary was introduced, and the + specification was converted to RFC style. + +2. Detailed specification + + 2.1. Overall conventions + + In the diagrams below, a box like this: + + +---+ + | | <-- the vertical bars might be missing + +---+ + + + + +Deutsch & Gailly Informational [Page 3] + +RFC 1950 ZLIB Compressed Data Format Specification May 1996 + + + represents one byte; a box like this: + + +==============+ + | | + +==============+ + + represents a variable number of bytes. + + Bytes stored within a computer do not have a "bit order", since + they are always treated as a unit. However, a byte considered as + an integer between 0 and 255 does have a most- and least- + significant bit, and since we write numbers with the most- + significant digit on the left, we also write bytes with the most- + significant bit on the left. In the diagrams below, we number the + bits of a byte so that bit 0 is the least-significant bit, i.e., + the bits are numbered: + + +--------+ + |76543210| + +--------+ + + Within a computer, a number may occupy multiple bytes. All + multi-byte numbers in the format described here are stored with + the MOST-significant byte first (at the lower memory address). + For example, the decimal number 520 is stored as: + + 0 1 + +--------+--------+ + |00000010|00001000| + +--------+--------+ + ^ ^ + | | + | + less significant byte = 8 + + more significant byte = 2 x 256 + + 2.2. Data format + + A zlib stream has the following structure: + + 0 1 + +---+---+ + |CMF|FLG| (more-->) + +---+---+ + + + + + + + + +Deutsch & Gailly Informational [Page 4] + +RFC 1950 ZLIB Compressed Data Format Specification May 1996 + + + (if FLG.FDICT set) + + 0 1 2 3 + +---+---+---+---+ + | DICTID | (more-->) + +---+---+---+---+ + + +=====================+---+---+---+---+ + |...compressed data...| ADLER32 | + +=====================+---+---+---+---+ + + Any data which may appear after ADLER32 are not part of the zlib + stream. + + CMF (Compression Method and flags) + This byte is divided into a 4-bit compression method and a 4- + bit information field depending on the compression method. + + bits 0 to 3 CM Compression method + bits 4 to 7 CINFO Compression info + + CM (Compression method) + This identifies the compression method used in the file. CM = 8 + denotes the "deflate" compression method with a window size up + to 32K. This is the method used by gzip and PNG (see + references [1] and [2] in Chapter 3, below, for the reference + documents). CM = 15 is reserved. It might be used in a future + version of this specification to indicate the presence of an + extra field before the compressed data. + + CINFO (Compression info) + For CM = 8, CINFO is the base-2 logarithm of the LZ77 window + size, minus eight (CINFO=7 indicates a 32K window size). Values + of CINFO above 7 are not allowed in this version of the + specification. CINFO is not defined in this specification for + CM not equal to 8. + + FLG (FLaGs) + This flag byte is divided as follows: + + bits 0 to 4 FCHECK (check bits for CMF and FLG) + bit 5 FDICT (preset dictionary) + bits 6 to 7 FLEVEL (compression level) + + The FCHECK value must be such that CMF and FLG, when viewed as + a 16-bit unsigned integer stored in MSB order (CMF*256 + FLG), + is a multiple of 31. + + + + +Deutsch & Gailly Informational [Page 5] + +RFC 1950 ZLIB Compressed Data Format Specification May 1996 + + + FDICT (Preset dictionary) + If FDICT is set, a DICT dictionary identifier is present + immediately after the FLG byte. The dictionary is a sequence of + bytes which are initially fed to the compressor without + producing any compressed output. DICT is the Adler-32 checksum + of this sequence of bytes (see the definition of ADLER32 + below). The decompressor can use this identifier to determine + which dictionary has been used by the compressor. + + FLEVEL (Compression level) + These flags are available for use by specific compression + methods. The "deflate" method (CM = 8) sets these flags as + follows: + + 0 - compressor used fastest algorithm + 1 - compressor used fast algorithm + 2 - compressor used default algorithm + 3 - compressor used maximum compression, slowest algorithm + + The information in FLEVEL is not needed for decompression; it + is there to indicate if recompression might be worthwhile. + + compressed data + For compression method 8, the compressed data is stored in the + deflate compressed data format as described in the document + "DEFLATE Compressed Data Format Specification" by L. Peter + Deutsch. (See reference [3] in Chapter 3, below) + + Other compressed data formats are not specified in this version + of the zlib specification. + + ADLER32 (Adler-32 checksum) + This contains a checksum value of the uncompressed data + (excluding any dictionary data) computed according to Adler-32 + algorithm. This algorithm is a 32-bit extension and improvement + of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073 + standard. See references [4] and [5] in Chapter 3, below) + + Adler-32 is composed of two sums accumulated per byte: s1 is + the sum of all bytes, s2 is the sum of all s1 values. Both sums + are done modulo 65521. s1 is initialized to 1, s2 to zero. The + Adler-32 checksum is stored as s2*65536 + s1 in most- + significant-byte first (network) order. + + + + + + + + +Deutsch & Gailly Informational [Page 6] + +RFC 1950 ZLIB Compressed Data Format Specification May 1996 + + + 2.3. Compliance + + A compliant compressor must produce streams with correct CMF, FLG + and ADLER32, but need not support preset dictionaries. When the + zlib data format is used as part of another standard data format, + the compressor may use only preset dictionaries that are specified + by this other data format. If this other format does not use the + preset dictionary feature, the compressor must not set the FDICT + flag. + + A compliant decompressor must check CMF, FLG, and ADLER32, and + provide an error indication if any of these have incorrect values. + A compliant decompressor must give an error indication if CM is + not one of the values defined in this specification (only the + value 8 is permitted in this version), since another value could + indicate the presence of new features that would cause subsequent + data to be interpreted incorrectly. A compliant decompressor must + give an error indication if FDICT is set and DICTID is not the + identifier of a known preset dictionary. A decompressor may + ignore FLEVEL and still be compliant. When the zlib data format + is being used as a part of another standard format, a compliant + decompressor must support all the preset dictionaries specified by + the other format. When the other format does not use the preset + dictionary feature, a compliant decompressor must reject any + stream in which the FDICT flag is set. + +3. References + + [1] Deutsch, L.P.,"GZIP Compressed Data Format Specification", + available in ftp://ftp.uu.net/pub/archiving/zip/doc/ + + [2] Thomas Boutell, "PNG (Portable Network Graphics) specification", + available in ftp://ftp.uu.net/graphics/png/documents/ + + [3] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification", + available in ftp://ftp.uu.net/pub/archiving/zip/doc/ + + [4] Fletcher, J. G., "An Arithmetic Checksum for Serial + Transmissions," IEEE Transactions on Communications, Vol. COM-30, + No. 1, January 1982, pp. 247-252. + + [5] ITU-T Recommendation X.224, Annex D, "Checksum Algorithms," + November, 1993, pp. 144, 145. (Available from + gopher://info.itu.ch). ITU-T X.244 is also the same as ISO 8073. + + + + + + + +Deutsch & Gailly Informational [Page 7] + +RFC 1950 ZLIB Compressed Data Format Specification May 1996 + + +4. Source code + + Source code for a C language implementation of a "zlib" compliant + library is available at ftp://ftp.uu.net/pub/archiving/zip/zlib/. + +5. Security Considerations + + A decoder that fails to check the ADLER32 checksum value may be + subject to undetected data corruption. + +6. Acknowledgements + + Trademarks cited in this document are the property of their + respective owners. + + Jean-Loup Gailly and Mark Adler designed the zlib format and wrote + the related software described in this specification. Glenn + Randers-Pehrson converted this document to RFC and HTML format. + +7. Authors' Addresses + + L. Peter Deutsch + Aladdin Enterprises + 203 Santa Margarita Ave. + Menlo Park, CA 94025 + + Phone: (415) 322-0103 (AM only) + FAX: (415) 322-1734 + EMail: + + + Jean-Loup Gailly + + EMail: + + Questions about the technical content of this specification can be + sent by email to + + Jean-Loup Gailly and + Mark Adler + + Editorial comments on this specification can be sent by email to + + L. Peter Deutsch and + Glenn Randers-Pehrson + + + + + + +Deutsch & Gailly Informational [Page 8] + +RFC 1950 ZLIB Compressed Data Format Specification May 1996 + + +8. Appendix: Rationale + + 8.1. Preset dictionaries + + A preset dictionary is specially useful to compress short input + sequences. The compressor can take advantage of the dictionary + context to encode the input in a more compact manner. The + decompressor can be initialized with the appropriate context by + virtually decompressing a compressed version of the dictionary + without producing any output. However for certain compression + algorithms such as the deflate algorithm this operation can be + achieved without actually performing any decompression. + + The compressor and the decompressor must use exactly the same + dictionary. The dictionary may be fixed or may be chosen among a + certain number of predefined dictionaries, according to the kind + of input data. The decompressor can determine which dictionary has + been chosen by the compressor by checking the dictionary + identifier. This document does not specify the contents of + predefined dictionaries, since the optimal dictionaries are + application specific. Standard data formats using this feature of + the zlib specification must precisely define the allowed + dictionaries. + + 8.2. The Adler-32 algorithm + + The Adler-32 algorithm is much faster than the CRC32 algorithm yet + still provides an extremely low probability of undetected errors. + + The modulo on unsigned long accumulators can be delayed for 5552 + bytes, so the modulo operation time is negligible. If the bytes + are a, b, c, the second sum is 3a + 2b + c + 3, and so is position + and order sensitive, unlike the first sum, which is just a + checksum. That 65521 is prime is important to avoid a possible + large class of two-byte errors that leave the check unchanged. + (The Fletcher checksum uses 255, which is not prime and which also + makes the Fletcher check insensitive to single byte changes 0 <-> + 255.) + + The sum s1 is initialized to 1 instead of zero to make the length + of the sequence part of s2, so that the length does not have to be + checked separately. (Any sequence of zeroes has a Fletcher + checksum of zero.) + + + + + + + + +Deutsch & Gailly Informational [Page 9] + +RFC 1950 ZLIB Compressed Data Format Specification May 1996 + + +9. Appendix: Sample code + + The following C code computes the Adler-32 checksum of a data buffer. + It is written for clarity, not for speed. The sample code is in the + ANSI C programming language. Non C users may find it easier to read + with these hints: + + & Bitwise AND operator. + >> Bitwise right shift operator. When applied to an + unsigned quantity, as here, right shift inserts zero bit(s) + at the left. + << Bitwise left shift operator. Left shift inserts zero + bit(s) at the right. + ++ "n++" increments the variable n. + % modulo operator: a % b is the remainder of a divided by b. + + #define BASE 65521 /* largest prime smaller than 65536 */ + + /* + Update a running Adler-32 checksum with the bytes buf[0..len-1] + and return the updated checksum. The Adler-32 checksum should be + initialized to 1. + + Usage example: + + unsigned long adler = 1L; + + while (read_buffer(buffer, length) != EOF) { + adler = update_adler32(adler, buffer, length); + } + if (adler != original_adler) error(); + */ + unsigned long update_adler32(unsigned long adler, + unsigned char *buf, int len) + { + unsigned long s1 = adler & 0xffff; + unsigned long s2 = (adler >> 16) & 0xffff; + int n; + + for (n = 0; n < len; n++) { + s1 = (s1 + buf[n]) % BASE; + s2 = (s2 + s1) % BASE; + } + return (s2 << 16) + s1; + } + + /* Return the adler32 of the bytes buf[0..len-1] */ + + + + +Deutsch & Gailly Informational [Page 10] + +RFC 1950 ZLIB Compressed Data Format Specification May 1996 + + + unsigned long adler32(unsigned char *buf, int len) + { + return update_adler32(1L, buf, len); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Deutsch & Gailly Informational [Page 11] + diff --git a/dependencies/zlib-1.2.11/doc/rfc1951.txt b/dependencies/zlib-1.2.11/doc/rfc1951.txt new file mode 100644 index 0000000..403c8c7 --- /dev/null +++ b/dependencies/zlib-1.2.11/doc/rfc1951.txt @@ -0,0 +1,955 @@ + + + + + + +Network Working Group P. Deutsch +Request for Comments: 1951 Aladdin Enterprises +Category: Informational May 1996 + + + DEFLATE Compressed Data Format Specification version 1.3 + +Status of This Memo + + This memo provides information for the Internet community. This memo + does not specify an Internet standard of any kind. Distribution of + this memo is unlimited. + +IESG Note: + + The IESG takes no position on the validity of any Intellectual + Property Rights statements contained in this document. + +Notices + + Copyright (c) 1996 L. Peter Deutsch + + Permission is granted to copy and distribute this document for any + purpose and without charge, including translations into other + languages and incorporation into compilations, provided that the + copyright notice and this notice are preserved, and that any + substantive changes or deletions from the original are clearly + marked. + + A pointer to the latest version of this and related documentation in + HTML format can be found at the URL + . + +Abstract + + This specification defines a lossless compressed data format that + compresses data using a combination of the LZ77 algorithm and Huffman + coding, with efficiency comparable to the best currently available + general-purpose compression methods. The data can be produced or + consumed, even for an arbitrarily long sequentially presented input + data stream, using only an a priori bounded amount of intermediate + storage. The format can be implemented readily in a manner not + covered by patents. + + + + + + + + +Deutsch Informational [Page 1] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + +Table of Contents + + 1. Introduction ................................................... 2 + 1.1. Purpose ................................................... 2 + 1.2. Intended audience ......................................... 3 + 1.3. Scope ..................................................... 3 + 1.4. Compliance ................................................ 3 + 1.5. Definitions of terms and conventions used ................ 3 + 1.6. Changes from previous versions ............................ 4 + 2. Compressed representation overview ............................. 4 + 3. Detailed specification ......................................... 5 + 3.1. Overall conventions ....................................... 5 + 3.1.1. Packing into bytes .................................. 5 + 3.2. Compressed block format ................................... 6 + 3.2.1. Synopsis of prefix and Huffman coding ............... 6 + 3.2.2. Use of Huffman coding in the "deflate" format ....... 7 + 3.2.3. Details of block format ............................. 9 + 3.2.4. Non-compressed blocks (BTYPE=00) ................... 11 + 3.2.5. Compressed blocks (length and distance codes) ...... 11 + 3.2.6. Compression with fixed Huffman codes (BTYPE=01) .... 12 + 3.2.7. Compression with dynamic Huffman codes (BTYPE=10) .. 13 + 3.3. Compliance ............................................... 14 + 4. Compression algorithm details ................................. 14 + 5. References .................................................... 16 + 6. Security Considerations ....................................... 16 + 7. Source code ................................................... 16 + 8. Acknowledgements .............................................. 16 + 9. Author's Address .............................................. 17 + +1. Introduction + + 1.1. Purpose + + The purpose of this specification is to define a lossless + compressed data format that: + * Is independent of CPU type, operating system, file system, + and character set, and hence can be used for interchange; + * Can be produced or consumed, even for an arbitrarily long + sequentially presented input data stream, using only an a + priori bounded amount of intermediate storage, and hence + can be used in data communications or similar structures + such as Unix filters; + * Compresses data with efficiency comparable to the best + currently available general-purpose compression methods, + and in particular considerably better than the "compress" + program; + * Can be implemented readily in a manner not covered by + patents, and hence can be practiced freely; + + + +Deutsch Informational [Page 2] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + * Is compatible with the file format produced by the current + widely used gzip utility, in that conforming decompressors + will be able to read data produced by the existing gzip + compressor. + + The data format defined by this specification does not attempt to: + + * Allow random access to compressed data; + * Compress specialized data (e.g., raster graphics) as well + as the best currently available specialized algorithms. + + A simple counting argument shows that no lossless compression + algorithm can compress every possible input data set. For the + format defined here, the worst case expansion is 5 bytes per 32K- + byte block, i.e., a size increase of 0.015% for large data sets. + English text usually compresses by a factor of 2.5 to 3; + executable files usually compress somewhat less; graphical data + such as raster images may compress much more. + + 1.2. Intended audience + + This specification is intended for use by implementors of software + to compress data into "deflate" format and/or decompress data from + "deflate" format. + + The text of the specification assumes a basic background in + programming at the level of bits and other primitive data + representations. Familiarity with the technique of Huffman coding + is helpful but not required. + + 1.3. Scope + + The specification specifies a method for representing a sequence + of bytes as a (usually shorter) sequence of bits, and a method for + packing the latter bit sequence into bytes. + + 1.4. Compliance + + Unless otherwise indicated below, a compliant decompressor must be + able to accept and decompress any data set that conforms to all + the specifications presented here; a compliant compressor must + produce data sets that conform to all the specifications presented + here. + + 1.5. Definitions of terms and conventions used + + Byte: 8 bits stored or transmitted as a unit (same as an octet). + For this specification, a byte is exactly 8 bits, even on machines + + + +Deutsch Informational [Page 3] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + which store a character on a number of bits different from eight. + See below, for the numbering of bits within a byte. + + String: a sequence of arbitrary bytes. + + 1.6. Changes from previous versions + + There have been no technical changes to the deflate format since + version 1.1 of this specification. In version 1.2, some + terminology was changed. Version 1.3 is a conversion of the + specification to RFC style. + +2. Compressed representation overview + + A compressed data set consists of a series of blocks, corresponding + to successive blocks of input data. The block sizes are arbitrary, + except that non-compressible blocks are limited to 65,535 bytes. + + Each block is compressed using a combination of the LZ77 algorithm + and Huffman coding. The Huffman trees for each block are independent + of those for previous or subsequent blocks; the LZ77 algorithm may + use a reference to a duplicated string occurring in a previous block, + up to 32K input bytes before. + + Each block consists of two parts: a pair of Huffman code trees that + describe the representation of the compressed data part, and a + compressed data part. (The Huffman trees themselves are compressed + using Huffman encoding.) The compressed data consists of a series of + elements of two types: literal bytes (of strings that have not been + detected as duplicated within the previous 32K input bytes), and + pointers to duplicated strings, where a pointer is represented as a + pair . The representation used in the + "deflate" format limits distances to 32K bytes and lengths to 258 + bytes, but does not limit the size of a block, except for + uncompressible blocks, which are limited as noted above. + + Each type of value (literals, distances, and lengths) in the + compressed data is represented using a Huffman code, using one code + tree for literals and lengths and a separate code tree for distances. + The code trees for each block appear in a compact form just before + the compressed data for that block. + + + + + + + + + + +Deutsch Informational [Page 4] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + +3. Detailed specification + + 3.1. Overall conventions In the diagrams below, a box like this: + + +---+ + | | <-- the vertical bars might be missing + +---+ + + represents one byte; a box like this: + + +==============+ + | | + +==============+ + + represents a variable number of bytes. + + Bytes stored within a computer do not have a "bit order", since + they are always treated as a unit. However, a byte considered as + an integer between 0 and 255 does have a most- and least- + significant bit, and since we write numbers with the most- + significant digit on the left, we also write bytes with the most- + significant bit on the left. In the diagrams below, we number the + bits of a byte so that bit 0 is the least-significant bit, i.e., + the bits are numbered: + + +--------+ + |76543210| + +--------+ + + Within a computer, a number may occupy multiple bytes. All + multi-byte numbers in the format described here are stored with + the least-significant byte first (at the lower memory address). + For example, the decimal number 520 is stored as: + + 0 1 + +--------+--------+ + |00001000|00000010| + +--------+--------+ + ^ ^ + | | + | + more significant byte = 2 x 256 + + less significant byte = 8 + + 3.1.1. Packing into bytes + + This document does not address the issue of the order in which + bits of a byte are transmitted on a bit-sequential medium, + since the final data format described here is byte- rather than + + + +Deutsch Informational [Page 5] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + bit-oriented. However, we describe the compressed block format + in below, as a sequence of data elements of various bit + lengths, not a sequence of bytes. We must therefore specify + how to pack these data elements into bytes to form the final + compressed byte sequence: + + * Data elements are packed into bytes in order of + increasing bit number within the byte, i.e., starting + with the least-significant bit of the byte. + * Data elements other than Huffman codes are packed + starting with the least-significant bit of the data + element. + * Huffman codes are packed starting with the most- + significant bit of the code. + + In other words, if one were to print out the compressed data as + a sequence of bytes, starting with the first byte at the + *right* margin and proceeding to the *left*, with the most- + significant bit of each byte on the left as usual, one would be + able to parse the result from right to left, with fixed-width + elements in the correct MSB-to-LSB order and Huffman codes in + bit-reversed order (i.e., with the first bit of the code in the + relative LSB position). + + 3.2. Compressed block format + + 3.2.1. Synopsis of prefix and Huffman coding + + Prefix coding represents symbols from an a priori known + alphabet by bit sequences (codes), one code for each symbol, in + a manner such that different symbols may be represented by bit + sequences of different lengths, but a parser can always parse + an encoded string unambiguously symbol-by-symbol. + + We define a prefix code in terms of a binary tree in which the + two edges descending from each non-leaf node are labeled 0 and + 1 and in which the leaf nodes correspond one-for-one with (are + labeled with) the symbols of the alphabet; then the code for a + symbol is the sequence of 0's and 1's on the edges leading from + the root to the leaf labeled with that symbol. For example: + + + + + + + + + + + +Deutsch Informational [Page 6] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + /\ Symbol Code + 0 1 ------ ---- + / \ A 00 + /\ B B 1 + 0 1 C 011 + / \ D 010 + A /\ + 0 1 + / \ + D C + + A parser can decode the next symbol from an encoded input + stream by walking down the tree from the root, at each step + choosing the edge corresponding to the next input bit. + + Given an alphabet with known symbol frequencies, the Huffman + algorithm allows the construction of an optimal prefix code + (one which represents strings with those symbol frequencies + using the fewest bits of any possible prefix codes for that + alphabet). Such a code is called a Huffman code. (See + reference [1] in Chapter 5, references for additional + information on Huffman codes.) + + Note that in the "deflate" format, the Huffman codes for the + various alphabets must not exceed certain maximum code lengths. + This constraint complicates the algorithm for computing code + lengths from symbol frequencies. Again, see Chapter 5, + references for details. + + 3.2.2. Use of Huffman coding in the "deflate" format + + The Huffman codes used for each alphabet in the "deflate" + format have two additional rules: + + * All codes of a given bit length have lexicographically + consecutive values, in the same order as the symbols + they represent; + + * Shorter codes lexicographically precede longer codes. + + + + + + + + + + + + +Deutsch Informational [Page 7] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + We could recode the example above to follow this rule as + follows, assuming that the order of the alphabet is ABCD: + + Symbol Code + ------ ---- + A 10 + B 0 + C 110 + D 111 + + I.e., 0 precedes 10 which precedes 11x, and 110 and 111 are + lexicographically consecutive. + + Given this rule, we can define the Huffman code for an alphabet + just by giving the bit lengths of the codes for each symbol of + the alphabet in order; this is sufficient to determine the + actual codes. In our example, the code is completely defined + by the sequence of bit lengths (2, 1, 3, 3). The following + algorithm generates the codes as integers, intended to be read + from most- to least-significant bit. The code lengths are + initially in tree[I].Len; the codes are produced in + tree[I].Code. + + 1) Count the number of codes for each code length. Let + bl_count[N] be the number of codes of length N, N >= 1. + + 2) Find the numerical value of the smallest code for each + code length: + + code = 0; + bl_count[0] = 0; + for (bits = 1; bits <= MAX_BITS; bits++) { + code = (code + bl_count[bits-1]) << 1; + next_code[bits] = code; + } + + 3) Assign numerical values to all codes, using consecutive + values for all codes of the same length with the base + values determined at step 2. Codes that are never used + (which have a bit length of zero) must not be assigned a + value. + + for (n = 0; n <= max_code; n++) { + len = tree[n].Len; + if (len != 0) { + tree[n].Code = next_code[len]; + next_code[len]++; + } + + + +Deutsch Informational [Page 8] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + } + + Example: + + Consider the alphabet ABCDEFGH, with bit lengths (3, 3, 3, 3, + 3, 2, 4, 4). After step 1, we have: + + N bl_count[N] + - ----------- + 2 1 + 3 5 + 4 2 + + Step 2 computes the following next_code values: + + N next_code[N] + - ------------ + 1 0 + 2 0 + 3 2 + 4 14 + + Step 3 produces the following code values: + + Symbol Length Code + ------ ------ ---- + A 3 010 + B 3 011 + C 3 100 + D 3 101 + E 3 110 + F 2 00 + G 4 1110 + H 4 1111 + + 3.2.3. Details of block format + + Each block of compressed data begins with 3 header bits + containing the following data: + + first bit BFINAL + next 2 bits BTYPE + + Note that the header bits do not necessarily begin on a byte + boundary, since a block does not necessarily occupy an integral + number of bytes. + + + + + +Deutsch Informational [Page 9] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + BFINAL is set if and only if this is the last block of the data + set. + + BTYPE specifies how the data are compressed, as follows: + + 00 - no compression + 01 - compressed with fixed Huffman codes + 10 - compressed with dynamic Huffman codes + 11 - reserved (error) + + The only difference between the two compressed cases is how the + Huffman codes for the literal/length and distance alphabets are + defined. + + In all cases, the decoding algorithm for the actual data is as + follows: + + do + read block header from input stream. + if stored with no compression + skip any remaining bits in current partially + processed byte + read LEN and NLEN (see next section) + copy LEN bytes of data to output + otherwise + if compressed with dynamic Huffman codes + read representation of code trees (see + subsection below) + loop (until end of block code recognized) + decode literal/length value from input stream + if value < 256 + copy value (literal byte) to output stream + otherwise + if value = end of block (256) + break from loop + otherwise (value = 257..285) + decode distance from input stream + + move backwards distance bytes in the output + stream, and copy length bytes from this + position to the output stream. + end loop + while not last block + + Note that a duplicated string reference may refer to a string + in a previous block; i.e., the backward distance may cross one + or more block boundaries. However a distance cannot refer past + the beginning of the output stream. (An application using a + + + +Deutsch Informational [Page 10] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + preset dictionary might discard part of the output stream; a + distance can refer to that part of the output stream anyway) + Note also that the referenced string may overlap the current + position; for example, if the last 2 bytes decoded have values + X and Y, a string reference with + adds X,Y,X,Y,X to the output stream. + + We now specify each compression method in turn. + + 3.2.4. Non-compressed blocks (BTYPE=00) + + Any bits of input up to the next byte boundary are ignored. + The rest of the block consists of the following information: + + 0 1 2 3 4... + +---+---+---+---+================================+ + | LEN | NLEN |... LEN bytes of literal data...| + +---+---+---+---+================================+ + + LEN is the number of data bytes in the block. NLEN is the + one's complement of LEN. + + 3.2.5. Compressed blocks (length and distance codes) + + As noted above, encoded data blocks in the "deflate" format + consist of sequences of symbols drawn from three conceptually + distinct alphabets: either literal bytes, from the alphabet of + byte values (0..255), or pairs, + where the length is drawn from (3..258) and the distance is + drawn from (1..32,768). In fact, the literal and length + alphabets are merged into a single alphabet (0..285), where + values 0..255 represent literal bytes, the value 256 indicates + end-of-block, and values 257..285 represent length codes + (possibly in conjunction with extra bits following the symbol + code) as follows: + + + + + + + + + + + + + + + + +Deutsch Informational [Page 11] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + Extra Extra Extra + Code Bits Length(s) Code Bits Lengths Code Bits Length(s) + ---- ---- ------ ---- ---- ------- ---- ---- ------- + 257 0 3 267 1 15,16 277 4 67-82 + 258 0 4 268 1 17,18 278 4 83-98 + 259 0 5 269 2 19-22 279 4 99-114 + 260 0 6 270 2 23-26 280 4 115-130 + 261 0 7 271 2 27-30 281 5 131-162 + 262 0 8 272 2 31-34 282 5 163-194 + 263 0 9 273 3 35-42 283 5 195-226 + 264 0 10 274 3 43-50 284 5 227-257 + 265 1 11,12 275 3 51-58 285 0 258 + 266 1 13,14 276 3 59-66 + + The extra bits should be interpreted as a machine integer + stored with the most-significant bit first, e.g., bits 1110 + represent the value 14. + + Extra Extra Extra + Code Bits Dist Code Bits Dist Code Bits Distance + ---- ---- ---- ---- ---- ------ ---- ---- -------- + 0 0 1 10 4 33-48 20 9 1025-1536 + 1 0 2 11 4 49-64 21 9 1537-2048 + 2 0 3 12 5 65-96 22 10 2049-3072 + 3 0 4 13 5 97-128 23 10 3073-4096 + 4 1 5,6 14 6 129-192 24 11 4097-6144 + 5 1 7,8 15 6 193-256 25 11 6145-8192 + 6 2 9-12 16 7 257-384 26 12 8193-12288 + 7 2 13-16 17 7 385-512 27 12 12289-16384 + 8 3 17-24 18 8 513-768 28 13 16385-24576 + 9 3 25-32 19 8 769-1024 29 13 24577-32768 + + 3.2.6. Compression with fixed Huffman codes (BTYPE=01) + + The Huffman codes for the two alphabets are fixed, and are not + represented explicitly in the data. The Huffman code lengths + for the literal/length alphabet are: + + Lit Value Bits Codes + --------- ---- ----- + 0 - 143 8 00110000 through + 10111111 + 144 - 255 9 110010000 through + 111111111 + 256 - 279 7 0000000 through + 0010111 + 280 - 287 8 11000000 through + 11000111 + + + +Deutsch Informational [Page 12] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + The code lengths are sufficient to generate the actual codes, + as described above; we show the codes in the table for added + clarity. Literal/length values 286-287 will never actually + occur in the compressed data, but participate in the code + construction. + + Distance codes 0-31 are represented by (fixed-length) 5-bit + codes, with possible additional bits as shown in the table + shown in Paragraph 3.2.5, above. Note that distance codes 30- + 31 will never actually occur in the compressed data. + + 3.2.7. Compression with dynamic Huffman codes (BTYPE=10) + + The Huffman codes for the two alphabets appear in the block + immediately after the header bits and before the actual + compressed data, first the literal/length code and then the + distance code. Each code is defined by a sequence of code + lengths, as discussed in Paragraph 3.2.2, above. For even + greater compactness, the code length sequences themselves are + compressed using a Huffman code. The alphabet for code lengths + is as follows: + + 0 - 15: Represent code lengths of 0 - 15 + 16: Copy the previous code length 3 - 6 times. + The next 2 bits indicate repeat length + (0 = 3, ... , 3 = 6) + Example: Codes 8, 16 (+2 bits 11), + 16 (+2 bits 10) will expand to + 12 code lengths of 8 (1 + 6 + 5) + 17: Repeat a code length of 0 for 3 - 10 times. + (3 bits of length) + 18: Repeat a code length of 0 for 11 - 138 times + (7 bits of length) + + A code length of 0 indicates that the corresponding symbol in + the literal/length or distance alphabet will not occur in the + block, and should not participate in the Huffman code + construction algorithm given earlier. If only one distance + code is used, it is encoded using one bit, not zero bits; in + this case there is a single code length of one, with one unused + code. One distance code of zero bits means that there are no + distance codes used at all (the data is all literals). + + We can now define the format of the block: + + 5 Bits: HLIT, # of Literal/Length codes - 257 (257 - 286) + 5 Bits: HDIST, # of Distance codes - 1 (1 - 32) + 4 Bits: HCLEN, # of Code Length codes - 4 (4 - 19) + + + +Deutsch Informational [Page 13] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + (HCLEN + 4) x 3 bits: code lengths for the code length + alphabet given just above, in the order: 16, 17, 18, + 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 + + These code lengths are interpreted as 3-bit integers + (0-7); as above, a code length of 0 means the + corresponding symbol (literal/length or distance code + length) is not used. + + HLIT + 257 code lengths for the literal/length alphabet, + encoded using the code length Huffman code + + HDIST + 1 code lengths for the distance alphabet, + encoded using the code length Huffman code + + The actual compressed data of the block, + encoded using the literal/length and distance Huffman + codes + + The literal/length symbol 256 (end of data), + encoded using the literal/length Huffman code + + The code length repeat codes can cross from HLIT + 257 to the + HDIST + 1 code lengths. In other words, all code lengths form + a single sequence of HLIT + HDIST + 258 values. + + 3.3. Compliance + + A compressor may limit further the ranges of values specified in + the previous section and still be compliant; for example, it may + limit the range of backward pointers to some value smaller than + 32K. Similarly, a compressor may limit the size of blocks so that + a compressible block fits in memory. + + A compliant decompressor must accept the full range of possible + values defined in the previous section, and must accept blocks of + arbitrary size. + +4. Compression algorithm details + + While it is the intent of this document to define the "deflate" + compressed data format without reference to any particular + compression algorithm, the format is related to the compressed + formats produced by LZ77 (Lempel-Ziv 1977, see reference [2] below); + since many variations of LZ77 are patented, it is strongly + recommended that the implementor of a compressor follow the general + algorithm presented here, which is known not to be patented per se. + The material in this section is not part of the definition of the + + + +Deutsch Informational [Page 14] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + specification per se, and a compressor need not follow it in order to + be compliant. + + The compressor terminates a block when it determines that starting a + new block with fresh trees would be useful, or when the block size + fills up the compressor's block buffer. + + The compressor uses a chained hash table to find duplicated strings, + using a hash function that operates on 3-byte sequences. At any + given point during compression, let XYZ be the next 3 input bytes to + be examined (not necessarily all different, of course). First, the + compressor examines the hash chain for XYZ. If the chain is empty, + the compressor simply writes out X as a literal byte and advances one + byte in the input. If the hash chain is not empty, indicating that + the sequence XYZ (or, if we are unlucky, some other 3 bytes with the + same hash function value) has occurred recently, the compressor + compares all strings on the XYZ hash chain with the actual input data + sequence starting at the current point, and selects the longest + match. + + The compressor searches the hash chains starting with the most recent + strings, to favor small distances and thus take advantage of the + Huffman encoding. The hash chains are singly linked. There are no + deletions from the hash chains; the algorithm simply discards matches + that are too old. To avoid a worst-case situation, very long hash + chains are arbitrarily truncated at a certain length, determined by a + run-time parameter. + + To improve overall compression, the compressor optionally defers the + selection of matches ("lazy matching"): after a match of length N has + been found, the compressor searches for a longer match starting at + the next input byte. If it finds a longer match, it truncates the + previous match to a length of one (thus producing a single literal + byte) and then emits the longer match. Otherwise, it emits the + original match, and, as described above, advances N bytes before + continuing. + + Run-time parameters also control this "lazy match" procedure. If + compression ratio is most important, the compressor attempts a + complete second search regardless of the length of the first match. + In the normal case, if the current match is "long enough", the + compressor reduces the search for a longer match, thus speeding up + the process. If speed is most important, the compressor inserts new + strings in the hash table only when no match was found, or when the + match is not "too long". This degrades the compression ratio but + saves time since there are both fewer insertions and fewer searches. + + + + + +Deutsch Informational [Page 15] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + +5. References + + [1] Huffman, D. A., "A Method for the Construction of Minimum + Redundancy Codes", Proceedings of the Institute of Radio + Engineers, September 1952, Volume 40, Number 9, pp. 1098-1101. + + [2] Ziv J., Lempel A., "A Universal Algorithm for Sequential Data + Compression", IEEE Transactions on Information Theory, Vol. 23, + No. 3, pp. 337-343. + + [3] Gailly, J.-L., and Adler, M., ZLIB documentation and sources, + available in ftp://ftp.uu.net/pub/archiving/zip/doc/ + + [4] Gailly, J.-L., and Adler, M., GZIP documentation and sources, + available as gzip-*.tar in ftp://prep.ai.mit.edu/pub/gnu/ + + [5] Schwartz, E. S., and Kallick, B. "Generating a canonical prefix + encoding." Comm. ACM, 7,3 (Mar. 1964), pp. 166-169. + + [6] Hirschberg and Lelewer, "Efficient decoding of prefix codes," + Comm. ACM, 33,4, April 1990, pp. 449-459. + +6. Security Considerations + + Any data compression method involves the reduction of redundancy in + the data. Consequently, any corruption of the data is likely to have + severe effects and be difficult to correct. Uncompressed text, on + the other hand, will probably still be readable despite the presence + of some corrupted bytes. + + It is recommended that systems using this data format provide some + means of validating the integrity of the compressed data. See + reference [3], for example. + +7. Source code + + Source code for a C language implementation of a "deflate" compliant + compressor and decompressor is available within the zlib package at + ftp://ftp.uu.net/pub/archiving/zip/zlib/. + +8. Acknowledgements + + Trademarks cited in this document are the property of their + respective owners. + + Phil Katz designed the deflate format. Jean-Loup Gailly and Mark + Adler wrote the related software described in this specification. + Glenn Randers-Pehrson converted this document to RFC and HTML format. + + + +Deutsch Informational [Page 16] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + +9. Author's Address + + L. Peter Deutsch + Aladdin Enterprises + 203 Santa Margarita Ave. + Menlo Park, CA 94025 + + Phone: (415) 322-0103 (AM only) + FAX: (415) 322-1734 + EMail: + + Questions about the technical content of this specification can be + sent by email to: + + Jean-Loup Gailly and + Mark Adler + + Editorial comments on this specification can be sent by email to: + + L. Peter Deutsch and + Glenn Randers-Pehrson + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Deutsch Informational [Page 17] + diff --git a/dependencies/zlib-1.2.11/doc/rfc1952.txt b/dependencies/zlib-1.2.11/doc/rfc1952.txt new file mode 100644 index 0000000..a8e51b4 --- /dev/null +++ b/dependencies/zlib-1.2.11/doc/rfc1952.txt @@ -0,0 +1,675 @@ + + + + + + +Network Working Group P. Deutsch +Request for Comments: 1952 Aladdin Enterprises +Category: Informational May 1996 + + + GZIP file format specification version 4.3 + +Status of This Memo + + This memo provides information for the Internet community. This memo + does not specify an Internet standard of any kind. Distribution of + this memo is unlimited. + +IESG Note: + + The IESG takes no position on the validity of any Intellectual + Property Rights statements contained in this document. + +Notices + + Copyright (c) 1996 L. Peter Deutsch + + Permission is granted to copy and distribute this document for any + purpose and without charge, including translations into other + languages and incorporation into compilations, provided that the + copyright notice and this notice are preserved, and that any + substantive changes or deletions from the original are clearly + marked. + + A pointer to the latest version of this and related documentation in + HTML format can be found at the URL + . + +Abstract + + This specification defines a lossless compressed data format that is + compatible with the widely used GZIP utility. The format includes a + cyclic redundancy check value for detecting data corruption. The + format presently uses the DEFLATE method of compression but can be + easily extended to use other compression methods. The format can be + implemented readily in a manner not covered by patents. + + + + + + + + + + +Deutsch Informational [Page 1] + +RFC 1952 GZIP File Format Specification May 1996 + + +Table of Contents + + 1. Introduction ................................................... 2 + 1.1. Purpose ................................................... 2 + 1.2. Intended audience ......................................... 3 + 1.3. Scope ..................................................... 3 + 1.4. Compliance ................................................ 3 + 1.5. Definitions of terms and conventions used ................. 3 + 1.6. Changes from previous versions ............................ 3 + 2. Detailed specification ......................................... 4 + 2.1. Overall conventions ....................................... 4 + 2.2. File format ............................................... 5 + 2.3. Member format ............................................. 5 + 2.3.1. Member header and trailer ........................... 6 + 2.3.1.1. Extra field ................................... 8 + 2.3.1.2. Compliance .................................... 9 + 3. References .................................................. 9 + 4. Security Considerations .................................... 10 + 5. Acknowledgements ........................................... 10 + 6. Author's Address ........................................... 10 + 7. Appendix: Jean-Loup Gailly's gzip utility .................. 11 + 8. Appendix: Sample CRC Code .................................. 11 + +1. Introduction + + 1.1. Purpose + + The purpose of this specification is to define a lossless + compressed data format that: + + * Is independent of CPU type, operating system, file system, + and character set, and hence can be used for interchange; + * Can compress or decompress a data stream (as opposed to a + randomly accessible file) to produce another data stream, + using only an a priori bounded amount of intermediate + storage, and hence can be used in data communications or + similar structures such as Unix filters; + * Compresses data with efficiency comparable to the best + currently available general-purpose compression methods, + and in particular considerably better than the "compress" + program; + * Can be implemented readily in a manner not covered by + patents, and hence can be practiced freely; + * Is compatible with the file format produced by the current + widely used gzip utility, in that conforming decompressors + will be able to read data produced by the existing gzip + compressor. + + + + +Deutsch Informational [Page 2] + +RFC 1952 GZIP File Format Specification May 1996 + + + The data format defined by this specification does not attempt to: + + * Provide random access to compressed data; + * Compress specialized data (e.g., raster graphics) as well as + the best currently available specialized algorithms. + + 1.2. Intended audience + + This specification is intended for use by implementors of software + to compress data into gzip format and/or decompress data from gzip + format. + + The text of the specification assumes a basic background in + programming at the level of bits and other primitive data + representations. + + 1.3. Scope + + The specification specifies a compression method and a file format + (the latter assuming only that a file can store a sequence of + arbitrary bytes). It does not specify any particular interface to + a file system or anything about character sets or encodings + (except for file names and comments, which are optional). + + 1.4. Compliance + + Unless otherwise indicated below, a compliant decompressor must be + able to accept and decompress any file that conforms to all the + specifications presented here; a compliant compressor must produce + files that conform to all the specifications presented here. The + material in the appendices is not part of the specification per se + and is not relevant to compliance. + + 1.5. Definitions of terms and conventions used + + byte: 8 bits stored or transmitted as a unit (same as an octet). + (For this specification, a byte is exactly 8 bits, even on + machines which store a character on a number of bits different + from 8.) See below for the numbering of bits within a byte. + + 1.6. Changes from previous versions + + There have been no technical changes to the gzip format since + version 4.1 of this specification. In version 4.2, some + terminology was changed, and the sample CRC code was rewritten for + clarity and to eliminate the requirement for the caller to do pre- + and post-conditioning. Version 4.3 is a conversion of the + specification to RFC style. + + + +Deutsch Informational [Page 3] + +RFC 1952 GZIP File Format Specification May 1996 + + +2. Detailed specification + + 2.1. Overall conventions + + In the diagrams below, a box like this: + + +---+ + | | <-- the vertical bars might be missing + +---+ + + represents one byte; a box like this: + + +==============+ + | | + +==============+ + + represents a variable number of bytes. + + Bytes stored within a computer do not have a "bit order", since + they are always treated as a unit. However, a byte considered as + an integer between 0 and 255 does have a most- and least- + significant bit, and since we write numbers with the most- + significant digit on the left, we also write bytes with the most- + significant bit on the left. In the diagrams below, we number the + bits of a byte so that bit 0 is the least-significant bit, i.e., + the bits are numbered: + + +--------+ + |76543210| + +--------+ + + This document does not address the issue of the order in which + bits of a byte are transmitted on a bit-sequential medium, since + the data format described here is byte- rather than bit-oriented. + + Within a computer, a number may occupy multiple bytes. All + multi-byte numbers in the format described here are stored with + the least-significant byte first (at the lower memory address). + For example, the decimal number 520 is stored as: + + 0 1 + +--------+--------+ + |00001000|00000010| + +--------+--------+ + ^ ^ + | | + | + more significant byte = 2 x 256 + + less significant byte = 8 + + + +Deutsch Informational [Page 4] + +RFC 1952 GZIP File Format Specification May 1996 + + + 2.2. File format + + A gzip file consists of a series of "members" (compressed data + sets). The format of each member is specified in the following + section. The members simply appear one after another in the file, + with no additional information before, between, or after them. + + 2.3. Member format + + Each member has the following structure: + + +---+---+---+---+---+---+---+---+---+---+ + |ID1|ID2|CM |FLG| MTIME |XFL|OS | (more-->) + +---+---+---+---+---+---+---+---+---+---+ + + (if FLG.FEXTRA set) + + +---+---+=================================+ + | XLEN |...XLEN bytes of "extra field"...| (more-->) + +---+---+=================================+ + + (if FLG.FNAME set) + + +=========================================+ + |...original file name, zero-terminated...| (more-->) + +=========================================+ + + (if FLG.FCOMMENT set) + + +===================================+ + |...file comment, zero-terminated...| (more-->) + +===================================+ + + (if FLG.FHCRC set) + + +---+---+ + | CRC16 | + +---+---+ + + +=======================+ + |...compressed blocks...| (more-->) + +=======================+ + + 0 1 2 3 4 5 6 7 + +---+---+---+---+---+---+---+---+ + | CRC32 | ISIZE | + +---+---+---+---+---+---+---+---+ + + + + +Deutsch Informational [Page 5] + +RFC 1952 GZIP File Format Specification May 1996 + + + 2.3.1. Member header and trailer + + ID1 (IDentification 1) + ID2 (IDentification 2) + These have the fixed values ID1 = 31 (0x1f, \037), ID2 = 139 + (0x8b, \213), to identify the file as being in gzip format. + + CM (Compression Method) + This identifies the compression method used in the file. CM + = 0-7 are reserved. CM = 8 denotes the "deflate" + compression method, which is the one customarily used by + gzip and which is documented elsewhere. + + FLG (FLaGs) + This flag byte is divided into individual bits as follows: + + bit 0 FTEXT + bit 1 FHCRC + bit 2 FEXTRA + bit 3 FNAME + bit 4 FCOMMENT + bit 5 reserved + bit 6 reserved + bit 7 reserved + + If FTEXT is set, the file is probably ASCII text. This is + an optional indication, which the compressor may set by + checking a small amount of the input data to see whether any + non-ASCII characters are present. In case of doubt, FTEXT + is cleared, indicating binary data. For systems which have + different file formats for ascii text and binary data, the + decompressor can use FTEXT to choose the appropriate format. + We deliberately do not specify the algorithm used to set + this bit, since a compressor always has the option of + leaving it cleared and a decompressor always has the option + of ignoring it and letting some other program handle issues + of data conversion. + + If FHCRC is set, a CRC16 for the gzip header is present, + immediately before the compressed data. The CRC16 consists + of the two least significant bytes of the CRC32 for all + bytes of the gzip header up to and not including the CRC16. + [The FHCRC bit was never set by versions of gzip up to + 1.2.4, even though it was documented with a different + meaning in gzip 1.2.4.] + + If FEXTRA is set, optional extra fields are present, as + described in a following section. + + + +Deutsch Informational [Page 6] + +RFC 1952 GZIP File Format Specification May 1996 + + + If FNAME is set, an original file name is present, + terminated by a zero byte. The name must consist of ISO + 8859-1 (LATIN-1) characters; on operating systems using + EBCDIC or any other character set for file names, the name + must be translated to the ISO LATIN-1 character set. This + is the original name of the file being compressed, with any + directory components removed, and, if the file being + compressed is on a file system with case insensitive names, + forced to lower case. There is no original file name if the + data was compressed from a source other than a named file; + for example, if the source was stdin on a Unix system, there + is no file name. + + If FCOMMENT is set, a zero-terminated file comment is + present. This comment is not interpreted; it is only + intended for human consumption. The comment must consist of + ISO 8859-1 (LATIN-1) characters. Line breaks should be + denoted by a single line feed character (10 decimal). + + Reserved FLG bits must be zero. + + MTIME (Modification TIME) + This gives the most recent modification time of the original + file being compressed. The time is in Unix format, i.e., + seconds since 00:00:00 GMT, Jan. 1, 1970. (Note that this + may cause problems for MS-DOS and other systems that use + local rather than Universal time.) If the compressed data + did not come from a file, MTIME is set to the time at which + compression started. MTIME = 0 means no time stamp is + available. + + XFL (eXtra FLags) + These flags are available for use by specific compression + methods. The "deflate" method (CM = 8) sets these flags as + follows: + + XFL = 2 - compressor used maximum compression, + slowest algorithm + XFL = 4 - compressor used fastest algorithm + + OS (Operating System) + This identifies the type of file system on which compression + took place. This may be useful in determining end-of-line + convention for text files. The currently defined values are + as follows: + + + + + + +Deutsch Informational [Page 7] + +RFC 1952 GZIP File Format Specification May 1996 + + + 0 - FAT filesystem (MS-DOS, OS/2, NT/Win32) + 1 - Amiga + 2 - VMS (or OpenVMS) + 3 - Unix + 4 - VM/CMS + 5 - Atari TOS + 6 - HPFS filesystem (OS/2, NT) + 7 - Macintosh + 8 - Z-System + 9 - CP/M + 10 - TOPS-20 + 11 - NTFS filesystem (NT) + 12 - QDOS + 13 - Acorn RISCOS + 255 - unknown + + XLEN (eXtra LENgth) + If FLG.FEXTRA is set, this gives the length of the optional + extra field. See below for details. + + CRC32 (CRC-32) + This contains a Cyclic Redundancy Check value of the + uncompressed data computed according to CRC-32 algorithm + used in the ISO 3309 standard and in section 8.1.1.6.2 of + ITU-T recommendation V.42. (See http://www.iso.ch for + ordering ISO documents. See gopher://info.itu.ch for an + online version of ITU-T V.42.) + + ISIZE (Input SIZE) + This contains the size of the original (uncompressed) input + data modulo 2^32. + + 2.3.1.1. Extra field + + If the FLG.FEXTRA bit is set, an "extra field" is present in + the header, with total length XLEN bytes. It consists of a + series of subfields, each of the form: + + +---+---+---+---+==================================+ + |SI1|SI2| LEN |... LEN bytes of subfield data ...| + +---+---+---+---+==================================+ + + SI1 and SI2 provide a subfield ID, typically two ASCII letters + with some mnemonic value. Jean-Loup Gailly + is maintaining a registry of subfield + IDs; please send him any subfield ID you wish to use. Subfield + IDs with SI2 = 0 are reserved for future use. The following + IDs are currently defined: + + + +Deutsch Informational [Page 8] + +RFC 1952 GZIP File Format Specification May 1996 + + + SI1 SI2 Data + ---------- ---------- ---- + 0x41 ('A') 0x70 ('P') Apollo file type information + + LEN gives the length of the subfield data, excluding the 4 + initial bytes. + + 2.3.1.2. Compliance + + A compliant compressor must produce files with correct ID1, + ID2, CM, CRC32, and ISIZE, but may set all the other fields in + the fixed-length part of the header to default values (255 for + OS, 0 for all others). The compressor must set all reserved + bits to zero. + + A compliant decompressor must check ID1, ID2, and CM, and + provide an error indication if any of these have incorrect + values. It must examine FEXTRA/XLEN, FNAME, FCOMMENT and FHCRC + at least so it can skip over the optional fields if they are + present. It need not examine any other part of the header or + trailer; in particular, a decompressor may ignore FTEXT and OS + and always produce binary output, and still be compliant. A + compliant decompressor must give an error indication if any + reserved bit is non-zero, since such a bit could indicate the + presence of a new field that would cause subsequent data to be + interpreted incorrectly. + +3. References + + [1] "Information Processing - 8-bit single-byte coded graphic + character sets - Part 1: Latin alphabet No.1" (ISO 8859-1:1987). + The ISO 8859-1 (Latin-1) character set is a superset of 7-bit + ASCII. Files defining this character set are available as + iso_8859-1.* in ftp://ftp.uu.net/graphics/png/documents/ + + [2] ISO 3309 + + [3] ITU-T recommendation V.42 + + [4] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification", + available in ftp://ftp.uu.net/pub/archiving/zip/doc/ + + [5] Gailly, J.-L., GZIP documentation, available as gzip-*.tar in + ftp://prep.ai.mit.edu/pub/gnu/ + + [6] Sarwate, D.V., "Computation of Cyclic Redundancy Checks via Table + Look-Up", Communications of the ACM, 31(8), pp.1008-1013. + + + + +Deutsch Informational [Page 9] + +RFC 1952 GZIP File Format Specification May 1996 + + + [7] Schwaderer, W.D., "CRC Calculation", April 85 PC Tech Journal, + pp.118-133. + + [8] ftp://ftp.adelaide.edu.au/pub/rocksoft/papers/crc_v3.txt, + describing the CRC concept. + +4. Security Considerations + + Any data compression method involves the reduction of redundancy in + the data. Consequently, any corruption of the data is likely to have + severe effects and be difficult to correct. Uncompressed text, on + the other hand, will probably still be readable despite the presence + of some corrupted bytes. + + It is recommended that systems using this data format provide some + means of validating the integrity of the compressed data, such as by + setting and checking the CRC-32 check value. + +5. Acknowledgements + + Trademarks cited in this document are the property of their + respective owners. + + Jean-Loup Gailly designed the gzip format and wrote, with Mark Adler, + the related software described in this specification. Glenn + Randers-Pehrson converted this document to RFC and HTML format. + +6. Author's Address + + L. Peter Deutsch + Aladdin Enterprises + 203 Santa Margarita Ave. + Menlo Park, CA 94025 + + Phone: (415) 322-0103 (AM only) + FAX: (415) 322-1734 + EMail: + + Questions about the technical content of this specification can be + sent by email to: + + Jean-Loup Gailly and + Mark Adler + + Editorial comments on this specification can be sent by email to: + + L. Peter Deutsch and + Glenn Randers-Pehrson + + + +Deutsch Informational [Page 10] + +RFC 1952 GZIP File Format Specification May 1996 + + +7. Appendix: Jean-Loup Gailly's gzip utility + + The most widely used implementation of gzip compression, and the + original documentation on which this specification is based, were + created by Jean-Loup Gailly . Since this + implementation is a de facto standard, we mention some more of its + features here. Again, the material in this section is not part of + the specification per se, and implementations need not follow it to + be compliant. + + When compressing or decompressing a file, gzip preserves the + protection, ownership, and modification time attributes on the local + file system, since there is no provision for representing protection + attributes in the gzip file format itself. Since the file format + includes a modification time, the gzip decompressor provides a + command line switch that assigns the modification time from the file, + rather than the local modification time of the compressed input, to + the decompressed output. + +8. Appendix: Sample CRC Code + + The following sample code represents a practical implementation of + the CRC (Cyclic Redundancy Check). (See also ISO 3309 and ITU-T V.42 + for a formal specification.) + + The sample code is in the ANSI C programming language. Non C users + may find it easier to read with these hints: + + & Bitwise AND operator. + ^ Bitwise exclusive-OR operator. + >> Bitwise right shift operator. When applied to an + unsigned quantity, as here, right shift inserts zero + bit(s) at the left. + ! Logical NOT operator. + ++ "n++" increments the variable n. + 0xNNN 0x introduces a hexadecimal (base 16) constant. + Suffix L indicates a long value (at least 32 bits). + + /* Table of CRCs of all 8-bit messages. */ + unsigned long crc_table[256]; + + /* Flag: has the table been computed? Initially false. */ + int crc_table_computed = 0; + + /* Make the table for a fast CRC. */ + void make_crc_table(void) + { + unsigned long c; + + + +Deutsch Informational [Page 11] + +RFC 1952 GZIP File Format Specification May 1996 + + + int n, k; + for (n = 0; n < 256; n++) { + c = (unsigned long) n; + for (k = 0; k < 8; k++) { + if (c & 1) { + c = 0xedb88320L ^ (c >> 1); + } else { + c = c >> 1; + } + } + crc_table[n] = c; + } + crc_table_computed = 1; + } + + /* + Update a running crc with the bytes buf[0..len-1] and return + the updated crc. The crc should be initialized to zero. Pre- and + post-conditioning (one's complement) is performed within this + function so it shouldn't be done by the caller. Usage example: + + unsigned long crc = 0L; + + while (read_buffer(buffer, length) != EOF) { + crc = update_crc(crc, buffer, length); + } + if (crc != original_crc) error(); + */ + unsigned long update_crc(unsigned long crc, + unsigned char *buf, int len) + { + unsigned long c = crc ^ 0xffffffffL; + int n; + + if (!crc_table_computed) + make_crc_table(); + for (n = 0; n < len; n++) { + c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8); + } + return c ^ 0xffffffffL; + } + + /* Return the CRC of the bytes buf[0..len-1]. */ + unsigned long crc(unsigned char *buf, int len) + { + return update_crc(0L, buf, len); + } + + + + +Deutsch Informational [Page 12] + diff --git a/dependencies/zlib-1.2.11/doc/txtvsbin.txt b/dependencies/zlib-1.2.11/doc/txtvsbin.txt new file mode 100644 index 0000000..3d0f063 --- /dev/null +++ b/dependencies/zlib-1.2.11/doc/txtvsbin.txt @@ -0,0 +1,107 @@ +A Fast Method for Identifying Plain Text Files +============================================== + + +Introduction +------------ + +Given a file coming from an unknown source, it is sometimes desirable +to find out whether the format of that file is plain text. Although +this may appear like a simple task, a fully accurate detection of the +file type requires heavy-duty semantic analysis on the file contents. +It is, however, possible to obtain satisfactory results by employing +various heuristics. + +Previous versions of PKZip and other zip-compatible compression tools +were using a crude detection scheme: if more than 80% (4/5) of the bytes +found in a certain buffer are within the range [7..127], the file is +labeled as plain text, otherwise it is labeled as binary. A prominent +limitation of this scheme is the restriction to Latin-based alphabets. +Other alphabets, like Greek, Cyrillic or Asian, make extensive use of +the bytes within the range [128..255], and texts using these alphabets +are most often misidentified by this scheme; in other words, the rate +of false negatives is sometimes too high, which means that the recall +is low. Another weakness of this scheme is a reduced precision, due to +the false positives that may occur when binary files containing large +amounts of textual characters are misidentified as plain text. + +In this article we propose a new, simple detection scheme that features +a much increased precision and a near-100% recall. This scheme is +designed to work on ASCII, Unicode and other ASCII-derived alphabets, +and it handles single-byte encodings (ISO-8859, MacRoman, KOI8, etc.) +and variable-sized encodings (ISO-2022, UTF-8, etc.). Wider encodings +(UCS-2/UTF-16 and UCS-4/UTF-32) are not handled, however. + + +The Algorithm +------------- + +The algorithm works by dividing the set of bytecodes [0..255] into three +categories: +- The white list of textual bytecodes: + 9 (TAB), 10 (LF), 13 (CR), 32 (SPACE) to 255. +- The gray list of tolerated bytecodes: + 7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB), 27 (ESC). +- The black list of undesired, non-textual bytecodes: + 0 (NUL) to 6, 14 to 31. + +If a file contains at least one byte that belongs to the white list and +no byte that belongs to the black list, then the file is categorized as +plain text; otherwise, it is categorized as binary. (The boundary case, +when the file is empty, automatically falls into the latter category.) + + +Rationale +--------- + +The idea behind this algorithm relies on two observations. + +The first observation is that, although the full range of 7-bit codes +[0..127] is properly specified by the ASCII standard, most control +characters in the range [0..31] are not used in practice. The only +widely-used, almost universally-portable control codes are 9 (TAB), +10 (LF) and 13 (CR). There are a few more control codes that are +recognized on a reduced range of platforms and text viewers/editors: +7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB) and 27 (ESC); but these +codes are rarely (if ever) used alone, without being accompanied by +some printable text. Even the newer, portable text formats such as +XML avoid using control characters outside the list mentioned here. + +The second observation is that most of the binary files tend to contain +control characters, especially 0 (NUL). Even though the older text +detection schemes observe the presence of non-ASCII codes from the range +[128..255], the precision rarely has to suffer if this upper range is +labeled as textual, because the files that are genuinely binary tend to +contain both control characters and codes from the upper range. On the +other hand, the upper range needs to be labeled as textual, because it +is used by virtually all ASCII extensions. In particular, this range is +used for encoding non-Latin scripts. + +Since there is no counting involved, other than simply observing the +presence or the absence of some byte values, the algorithm produces +consistent results, regardless what alphabet encoding is being used. +(If counting were involved, it could be possible to obtain different +results on a text encoded, say, using ISO-8859-16 versus UTF-8.) + +There is an extra category of plain text files that are "polluted" with +one or more black-listed codes, either by mistake or by peculiar design +considerations. In such cases, a scheme that tolerates a small fraction +of black-listed codes would provide an increased recall (i.e. more true +positives). This, however, incurs a reduced precision overall, since +false positives are more likely to appear in binary files that contain +large chunks of textual data. Furthermore, "polluted" plain text should +be regarded as binary by general-purpose text detection schemes, because +general-purpose text processing algorithms might not be applicable. +Under this premise, it is safe to say that our detection method provides +a near-100% recall. + +Experiments have been run on many files coming from various platforms +and applications. We tried plain text files, system logs, source code, +formatted office documents, compiled object code, etc. The results +confirm the optimistic assumptions about the capabilities of this +algorithm. + + +-- +Cosmin Truta +Last updated: 2006-May-28 diff --git a/dependencies/zlib-1.2.11/examples/README.examples b/dependencies/zlib-1.2.11/examples/README.examples new file mode 100644 index 0000000..56a3171 --- /dev/null +++ b/dependencies/zlib-1.2.11/examples/README.examples @@ -0,0 +1,49 @@ +This directory contains examples of the use of zlib and other relevant +programs and documentation. + +enough.c + calculation and justification of ENOUGH parameter in inftrees.h + - calculates the maximum table space used in inflate tree + construction over all possible Huffman codes + +fitblk.c + compress just enough input to nearly fill a requested output size + - zlib isn't designed to do this, but fitblk does it anyway + +gun.c + uncompress a gzip file + - illustrates the use of inflateBack() for high speed file-to-file + decompression using call-back functions + - is approximately twice as fast as gzip -d + - also provides Unix uncompress functionality, again twice as fast + +gzappend.c + append to a gzip file + - illustrates the use of the Z_BLOCK flush parameter for inflate() + - illustrates the use of deflatePrime() to start at any bit + +gzjoin.c + join gzip files without recalculating the crc or recompressing + - illustrates the use of the Z_BLOCK flush parameter for inflate() + - illustrates the use of crc32_combine() + +gzlog.c +gzlog.h + efficiently and robustly maintain a message log file in gzip format + - illustrates use of raw deflate, Z_PARTIAL_FLUSH, deflatePrime(), + and deflateSetDictionary() + - illustrates use of a gzip header extra field + +zlib_how.html + painfully comprehensive description of zpipe.c (see below) + - describes in excruciating detail the use of deflate() and inflate() + +zpipe.c + reads and writes zlib streams from stdin to stdout + - illustrates the proper use of deflate() and inflate() + - deeply commented in zlib_how.html (see above) + +zran.c + index a zlib or gzip stream and randomly access it + - illustrates the use of Z_BLOCK, inflatePrime(), and + inflateSetDictionary() to provide random access diff --git a/dependencies/zlib-1.2.11/examples/enough.c b/dependencies/zlib-1.2.11/examples/enough.c new file mode 100644 index 0000000..b991144 --- /dev/null +++ b/dependencies/zlib-1.2.11/examples/enough.c @@ -0,0 +1,572 @@ +/* enough.c -- determine the maximum size of inflate's Huffman code tables over + * all possible valid and complete Huffman codes, subject to a length limit. + * Copyright (C) 2007, 2008, 2012 Mark Adler + * Version 1.4 18 August 2012 Mark Adler + */ + +/* Version history: + 1.0 3 Jan 2007 First version (derived from codecount.c version 1.4) + 1.1 4 Jan 2007 Use faster incremental table usage computation + Prune examine() search on previously visited states + 1.2 5 Jan 2007 Comments clean up + As inflate does, decrease root for short codes + Refuse cases where inflate would increase root + 1.3 17 Feb 2008 Add argument for initial root table size + Fix bug for initial root table size == max - 1 + Use a macro to compute the history index + 1.4 18 Aug 2012 Avoid shifts more than bits in type (caused endless loop!) + Clean up comparisons of different types + Clean up code indentation + */ + +/* + Examine all possible Huffman codes for a given number of symbols and a + maximum code length in bits to determine the maximum table size for zilb's + inflate. Only complete Huffman codes are counted. + + Two codes are considered distinct if the vectors of the number of codes per + length are not identical. So permutations of the symbol assignments result + in the same code for the counting, as do permutations of the assignments of + the bit values to the codes (i.e. only canonical codes are counted). + + We build a code from shorter to longer lengths, determining how many symbols + are coded at each length. At each step, we have how many symbols remain to + be coded, what the last code length used was, and how many bit patterns of + that length remain unused. Then we add one to the code length and double the + number of unused patterns to graduate to the next code length. We then + assign all portions of the remaining symbols to that code length that + preserve the properties of a correct and eventually complete code. Those + properties are: we cannot use more bit patterns than are available; and when + all the symbols are used, there are exactly zero possible bit patterns + remaining. + + The inflate Huffman decoding algorithm uses two-level lookup tables for + speed. There is a single first-level table to decode codes up to root bits + in length (root == 9 in the current inflate implementation). The table + has 1 << root entries and is indexed by the next root bits of input. Codes + shorter than root bits have replicated table entries, so that the correct + entry is pointed to regardless of the bits that follow the short code. If + the code is longer than root bits, then the table entry points to a second- + level table. The size of that table is determined by the longest code with + that root-bit prefix. If that longest code has length len, then the table + has size 1 << (len - root), to index the remaining bits in that set of + codes. Each subsequent root-bit prefix then has its own sub-table. The + total number of table entries required by the code is calculated + incrementally as the number of codes at each bit length is populated. When + all of the codes are shorter than root bits, then root is reduced to the + longest code length, resulting in a single, smaller, one-level table. + + The inflate algorithm also provides for small values of root (relative to + the log2 of the number of symbols), where the shortest code has more bits + than root. In that case, root is increased to the length of the shortest + code. This program, by design, does not handle that case, so it is verified + that the number of symbols is less than 2^(root + 1). + + In order to speed up the examination (by about ten orders of magnitude for + the default arguments), the intermediate states in the build-up of a code + are remembered and previously visited branches are pruned. The memory + required for this will increase rapidly with the total number of symbols and + the maximum code length in bits. However this is a very small price to pay + for the vast speedup. + + First, all of the possible Huffman codes are counted, and reachable + intermediate states are noted by a non-zero count in a saved-results array. + Second, the intermediate states that lead to (root + 1) bit or longer codes + are used to look at all sub-codes from those junctures for their inflate + memory usage. (The amount of memory used is not affected by the number of + codes of root bits or less in length.) Third, the visited states in the + construction of those sub-codes and the associated calculation of the table + size is recalled in order to avoid recalculating from the same juncture. + Beginning the code examination at (root + 1) bit codes, which is enabled by + identifying the reachable nodes, accounts for about six of the orders of + magnitude of improvement for the default arguments. About another four + orders of magnitude come from not revisiting previous states. Out of + approximately 2x10^16 possible Huffman codes, only about 2x10^6 sub-codes + need to be examined to cover all of the possible table memory usage cases + for the default arguments of 286 symbols limited to 15-bit codes. + + Note that an unsigned long long type is used for counting. It is quite easy + to exceed the capacity of an eight-byte integer with a large number of + symbols and a large maximum code length, so multiple-precision arithmetic + would need to replace the unsigned long long arithmetic in that case. This + program will abort if an overflow occurs. The big_t type identifies where + the counting takes place. + + An unsigned long long type is also used for calculating the number of + possible codes remaining at the maximum length. This limits the maximum + code length to the number of bits in a long long minus the number of bits + needed to represent the symbols in a flat code. The code_t type identifies + where the bit pattern counting takes place. + */ + +#include +#include +#include +#include + +#define local static + +/* special data types */ +typedef unsigned long long big_t; /* type for code counting */ +typedef unsigned long long code_t; /* type for bit pattern counting */ +struct tab { /* type for been here check */ + size_t len; /* length of bit vector in char's */ + char *vec; /* allocated bit vector */ +}; + +/* The array for saving results, num[], is indexed with this triplet: + + syms: number of symbols remaining to code + left: number of available bit patterns at length len + len: number of bits in the codes currently being assigned + + Those indices are constrained thusly when saving results: + + syms: 3..totsym (totsym == total symbols to code) + left: 2..syms - 1, but only the evens (so syms == 8 -> 2, 4, 6) + len: 1..max - 1 (max == maximum code length in bits) + + syms == 2 is not saved since that immediately leads to a single code. left + must be even, since it represents the number of available bit patterns at + the current length, which is double the number at the previous length. + left ends at syms-1 since left == syms immediately results in a single code. + (left > sym is not allowed since that would result in an incomplete code.) + len is less than max, since the code completes immediately when len == max. + + The offset into the array is calculated for the three indices with the + first one (syms) being outermost, and the last one (len) being innermost. + We build the array with length max-1 lists for the len index, with syms-3 + of those for each symbol. There are totsym-2 of those, with each one + varying in length as a function of sym. See the calculation of index in + count() for the index, and the calculation of size in main() for the size + of the array. + + For the deflate example of 286 symbols limited to 15-bit codes, the array + has 284,284 entries, taking up 2.17 MB for an 8-byte big_t. More than + half of the space allocated for saved results is actually used -- not all + possible triplets are reached in the generation of valid Huffman codes. + */ + +/* The array for tracking visited states, done[], is itself indexed identically + to the num[] array as described above for the (syms, left, len) triplet. + Each element in the array is further indexed by the (mem, rem) doublet, + where mem is the amount of inflate table space used so far, and rem is the + remaining unused entries in the current inflate sub-table. Each indexed + element is simply one bit indicating whether the state has been visited or + not. Since the ranges for mem and rem are not known a priori, each bit + vector is of a variable size, and grows as needed to accommodate the visited + states. mem and rem are used to calculate a single index in a triangular + array. Since the range of mem is expected in the default case to be about + ten times larger than the range of rem, the array is skewed to reduce the + memory usage, with eight times the range for mem than for rem. See the + calculations for offset and bit in beenhere() for the details. + + For the deflate example of 286 symbols limited to 15-bit codes, the bit + vectors grow to total approximately 21 MB, in addition to the 4.3 MB done[] + array itself. + */ + +/* Globals to avoid propagating constants or constant pointers recursively */ +local int max; /* maximum allowed bit length for the codes */ +local int root; /* size of base code table in bits */ +local int large; /* largest code table so far */ +local size_t size; /* number of elements in num and done */ +local int *code; /* number of symbols assigned to each bit length */ +local big_t *num; /* saved results array for code counting */ +local struct tab *done; /* states already evaluated array */ + +/* Index function for num[] and done[] */ +#define INDEX(i,j,k) (((size_t)((i-1)>>1)*((i-2)>>1)+(j>>1)-1)*(max-1)+k-1) + +/* Free allocated space. Uses globals code, num, and done. */ +local void cleanup(void) +{ + size_t n; + + if (done != NULL) { + for (n = 0; n < size; n++) + if (done[n].len) + free(done[n].vec); + free(done); + } + if (num != NULL) + free(num); + if (code != NULL) + free(code); +} + +/* Return the number of possible Huffman codes using bit patterns of lengths + len through max inclusive, coding syms symbols, with left bit patterns of + length len unused -- return -1 if there is an overflow in the counting. + Keep a record of previous results in num to prevent repeating the same + calculation. Uses the globals max and num. */ +local big_t count(int syms, int len, int left) +{ + big_t sum; /* number of possible codes from this juncture */ + big_t got; /* value returned from count() */ + int least; /* least number of syms to use at this juncture */ + int most; /* most number of syms to use at this juncture */ + int use; /* number of bit patterns to use in next call */ + size_t index; /* index of this case in *num */ + + /* see if only one possible code */ + if (syms == left) + return 1; + + /* note and verify the expected state */ + assert(syms > left && left > 0 && len < max); + + /* see if we've done this one already */ + index = INDEX(syms, left, len); + got = num[index]; + if (got) + return got; /* we have -- return the saved result */ + + /* we need to use at least this many bit patterns so that the code won't be + incomplete at the next length (more bit patterns than symbols) */ + least = (left << 1) - syms; + if (least < 0) + least = 0; + + /* we can use at most this many bit patterns, lest there not be enough + available for the remaining symbols at the maximum length (if there were + no limit to the code length, this would become: most = left - 1) */ + most = (((code_t)left << (max - len)) - syms) / + (((code_t)1 << (max - len)) - 1); + + /* count all possible codes from this juncture and add them up */ + sum = 0; + for (use = least; use <= most; use++) { + got = count(syms - use, len + 1, (left - use) << 1); + sum += got; + if (got == (big_t)0 - 1 || sum < got) /* overflow */ + return (big_t)0 - 1; + } + + /* verify that all recursive calls are productive */ + assert(sum != 0); + + /* save the result and return it */ + num[index] = sum; + return sum; +} + +/* Return true if we've been here before, set to true if not. Set a bit in a + bit vector to indicate visiting this state. Each (syms,len,left) state + has a variable size bit vector indexed by (mem,rem). The bit vector is + lengthened if needed to allow setting the (mem,rem) bit. */ +local int beenhere(int syms, int len, int left, int mem, int rem) +{ + size_t index; /* index for this state's bit vector */ + size_t offset; /* offset in this state's bit vector */ + int bit; /* mask for this state's bit */ + size_t length; /* length of the bit vector in bytes */ + char *vector; /* new or enlarged bit vector */ + + /* point to vector for (syms,left,len), bit in vector for (mem,rem) */ + index = INDEX(syms, left, len); + mem -= 1 << root; + offset = (mem >> 3) + rem; + offset = ((offset * (offset + 1)) >> 1) + rem; + bit = 1 << (mem & 7); + + /* see if we've been here */ + length = done[index].len; + if (offset < length && (done[index].vec[offset] & bit) != 0) + return 1; /* done this! */ + + /* we haven't been here before -- set the bit to show we have now */ + + /* see if we need to lengthen the vector in order to set the bit */ + if (length <= offset) { + /* if we have one already, enlarge it, zero out the appended space */ + if (length) { + do { + length <<= 1; + } while (length <= offset); + vector = realloc(done[index].vec, length); + if (vector != NULL) + memset(vector + done[index].len, 0, length - done[index].len); + } + + /* otherwise we need to make a new vector and zero it out */ + else { + length = 1 << (len - root); + while (length <= offset) + length <<= 1; + vector = calloc(length, sizeof(char)); + } + + /* in either case, bail if we can't get the memory */ + if (vector == NULL) { + fputs("abort: unable to allocate enough memory\n", stderr); + cleanup(); + exit(1); + } + + /* install the new vector */ + done[index].len = length; + done[index].vec = vector; + } + + /* set the bit */ + done[index].vec[offset] |= bit; + return 0; +} + +/* Examine all possible codes from the given node (syms, len, left). Compute + the amount of memory required to build inflate's decoding tables, where the + number of code structures used so far is mem, and the number remaining in + the current sub-table is rem. Uses the globals max, code, root, large, and + done. */ +local void examine(int syms, int len, int left, int mem, int rem) +{ + int least; /* least number of syms to use at this juncture */ + int most; /* most number of syms to use at this juncture */ + int use; /* number of bit patterns to use in next call */ + + /* see if we have a complete code */ + if (syms == left) { + /* set the last code entry */ + code[len] = left; + + /* complete computation of memory used by this code */ + while (rem < left) { + left -= rem; + rem = 1 << (len - root); + mem += rem; + } + assert(rem == left); + + /* if this is a new maximum, show the entries used and the sub-code */ + if (mem > large) { + large = mem; + printf("max %d: ", mem); + for (use = root + 1; use <= max; use++) + if (code[use]) + printf("%d[%d] ", code[use], use); + putchar('\n'); + fflush(stdout); + } + + /* remove entries as we drop back down in the recursion */ + code[len] = 0; + return; + } + + /* prune the tree if we can */ + if (beenhere(syms, len, left, mem, rem)) + return; + + /* we need to use at least this many bit patterns so that the code won't be + incomplete at the next length (more bit patterns than symbols) */ + least = (left << 1) - syms; + if (least < 0) + least = 0; + + /* we can use at most this many bit patterns, lest there not be enough + available for the remaining symbols at the maximum length (if there were + no limit to the code length, this would become: most = left - 1) */ + most = (((code_t)left << (max - len)) - syms) / + (((code_t)1 << (max - len)) - 1); + + /* occupy least table spaces, creating new sub-tables as needed */ + use = least; + while (rem < use) { + use -= rem; + rem = 1 << (len - root); + mem += rem; + } + rem -= use; + + /* examine codes from here, updating table space as we go */ + for (use = least; use <= most; use++) { + code[len] = use; + examine(syms - use, len + 1, (left - use) << 1, + mem + (rem ? 1 << (len - root) : 0), rem << 1); + if (rem == 0) { + rem = 1 << (len - root); + mem += rem; + } + rem--; + } + + /* remove entries as we drop back down in the recursion */ + code[len] = 0; +} + +/* Look at all sub-codes starting with root + 1 bits. Look at only the valid + intermediate code states (syms, left, len). For each completed code, + calculate the amount of memory required by inflate to build the decoding + tables. Find the maximum amount of memory required and show the code that + requires that maximum. Uses the globals max, root, and num. */ +local void enough(int syms) +{ + int n; /* number of remaing symbols for this node */ + int left; /* number of unused bit patterns at this length */ + size_t index; /* index of this case in *num */ + + /* clear code */ + for (n = 0; n <= max; n++) + code[n] = 0; + + /* look at all (root + 1) bit and longer codes */ + large = 1 << root; /* base table */ + if (root < max) /* otherwise, there's only a base table */ + for (n = 3; n <= syms; n++) + for (left = 2; left < n; left += 2) + { + /* look at all reachable (root + 1) bit nodes, and the + resulting codes (complete at root + 2 or more) */ + index = INDEX(n, left, root + 1); + if (root + 1 < max && num[index]) /* reachable node */ + examine(n, root + 1, left, 1 << root, 0); + + /* also look at root bit codes with completions at root + 1 + bits (not saved in num, since complete), just in case */ + if (num[index - 1] && n <= left << 1) + examine((n - left) << 1, root + 1, (n - left) << 1, + 1 << root, 0); + } + + /* done */ + printf("done: maximum of %d table entries\n", large); +} + +/* + Examine and show the total number of possible Huffman codes for a given + maximum number of symbols, initial root table size, and maximum code length + in bits -- those are the command arguments in that order. The default + values are 286, 9, and 15 respectively, for the deflate literal/length code. + The possible codes are counted for each number of coded symbols from two to + the maximum. The counts for each of those and the total number of codes are + shown. The maximum number of inflate table entires is then calculated + across all possible codes. Each new maximum number of table entries and the + associated sub-code (starting at root + 1 == 10 bits) is shown. + + To count and examine Huffman codes that are not length-limited, provide a + maximum length equal to the number of symbols minus one. + + For the deflate literal/length code, use "enough". For the deflate distance + code, use "enough 30 6". + + This uses the %llu printf format to print big_t numbers, which assumes that + big_t is an unsigned long long. If the big_t type is changed (for example + to a multiple precision type), the method of printing will also need to be + updated. + */ +int main(int argc, char **argv) +{ + int syms; /* total number of symbols to code */ + int n; /* number of symbols to code for this run */ + big_t got; /* return value of count() */ + big_t sum; /* accumulated number of codes over n */ + code_t word; /* for counting bits in code_t */ + + /* set up globals for cleanup() */ + code = NULL; + num = NULL; + done = NULL; + + /* get arguments -- default to the deflate literal/length code */ + syms = 286; + root = 9; + max = 15; + if (argc > 1) { + syms = atoi(argv[1]); + if (argc > 2) { + root = atoi(argv[2]); + if (argc > 3) + max = atoi(argv[3]); + } + } + if (argc > 4 || syms < 2 || root < 1 || max < 1) { + fputs("invalid arguments, need: [sym >= 2 [root >= 1 [max >= 1]]]\n", + stderr); + return 1; + } + + /* if not restricting the code length, the longest is syms - 1 */ + if (max > syms - 1) + max = syms - 1; + + /* determine the number of bits in a code_t */ + for (n = 0, word = 1; word; n++, word <<= 1) + ; + + /* make sure that the calculation of most will not overflow */ + if (max > n || (code_t)(syms - 2) >= (((code_t)0 - 1) >> (max - 1))) { + fputs("abort: code length too long for internal types\n", stderr); + return 1; + } + + /* reject impossible code requests */ + if ((code_t)(syms - 1) > ((code_t)1 << max) - 1) { + fprintf(stderr, "%d symbols cannot be coded in %d bits\n", + syms, max); + return 1; + } + + /* allocate code vector */ + code = calloc(max + 1, sizeof(int)); + if (code == NULL) { + fputs("abort: unable to allocate enough memory\n", stderr); + return 1; + } + + /* determine size of saved results array, checking for overflows, + allocate and clear the array (set all to zero with calloc()) */ + if (syms == 2) /* iff max == 1 */ + num = NULL; /* won't be saving any results */ + else { + size = syms >> 1; + if (size > ((size_t)0 - 1) / (n = (syms - 1) >> 1) || + (size *= n, size > ((size_t)0 - 1) / (n = max - 1)) || + (size *= n, size > ((size_t)0 - 1) / sizeof(big_t)) || + (num = calloc(size, sizeof(big_t))) == NULL) { + fputs("abort: unable to allocate enough memory\n", stderr); + cleanup(); + return 1; + } + } + + /* count possible codes for all numbers of symbols, add up counts */ + sum = 0; + for (n = 2; n <= syms; n++) { + got = count(n, 1, 2); + sum += got; + if (got == (big_t)0 - 1 || sum < got) { /* overflow */ + fputs("abort: can't count that high!\n", stderr); + cleanup(); + return 1; + } + printf("%llu %d-codes\n", got, n); + } + printf("%llu total codes for 2 to %d symbols", sum, syms); + if (max < syms - 1) + printf(" (%d-bit length limit)\n", max); + else + puts(" (no length limit)"); + + /* allocate and clear done array for beenhere() */ + if (syms == 2) + done = NULL; + else if (size > ((size_t)0 - 1) / sizeof(struct tab) || + (done = calloc(size, sizeof(struct tab))) == NULL) { + fputs("abort: unable to allocate enough memory\n", stderr); + cleanup(); + return 1; + } + + /* find and show maximum inflate table usage */ + if (root > max) /* reduce root to max length */ + root = max; + if ((code_t)syms < ((code_t)1 << (root + 1))) + enough(syms); + else + puts("cannot handle minimum code lengths > root"); + + /* done */ + cleanup(); + return 0; +} diff --git a/dependencies/zlib-1.2.11/examples/fitblk.c b/dependencies/zlib-1.2.11/examples/fitblk.c new file mode 100644 index 0000000..c61de5c --- /dev/null +++ b/dependencies/zlib-1.2.11/examples/fitblk.c @@ -0,0 +1,233 @@ +/* fitblk.c: example of fitting compressed output to a specified size + Not copyrighted -- provided to the public domain + Version 1.1 25 November 2004 Mark Adler */ + +/* Version history: + 1.0 24 Nov 2004 First version + 1.1 25 Nov 2004 Change deflateInit2() to deflateInit() + Use fixed-size, stack-allocated raw buffers + Simplify code moving compression to subroutines + Use assert() for internal errors + Add detailed description of approach + */ + +/* Approach to just fitting a requested compressed size: + + fitblk performs three compression passes on a portion of the input + data in order to determine how much of that input will compress to + nearly the requested output block size. The first pass generates + enough deflate blocks to produce output to fill the requested + output size plus a specfied excess amount (see the EXCESS define + below). The last deflate block may go quite a bit past that, but + is discarded. The second pass decompresses and recompresses just + the compressed data that fit in the requested plus excess sized + buffer. The deflate process is terminated after that amount of + input, which is less than the amount consumed on the first pass. + The last deflate block of the result will be of a comparable size + to the final product, so that the header for that deflate block and + the compression ratio for that block will be about the same as in + the final product. The third compression pass decompresses the + result of the second step, but only the compressed data up to the + requested size minus an amount to allow the compressed stream to + complete (see the MARGIN define below). That will result in a + final compressed stream whose length is less than or equal to the + requested size. Assuming sufficient input and a requested size + greater than a few hundred bytes, the shortfall will typically be + less than ten bytes. + + If the input is short enough that the first compression completes + before filling the requested output size, then that compressed + stream is return with no recompression. + + EXCESS is chosen to be just greater than the shortfall seen in a + two pass approach similar to the above. That shortfall is due to + the last deflate block compressing more efficiently with a smaller + header on the second pass. EXCESS is set to be large enough so + that there is enough uncompressed data for the second pass to fill + out the requested size, and small enough so that the final deflate + block of the second pass will be close in size to the final deflate + block of the third and final pass. MARGIN is chosen to be just + large enough to assure that the final compression has enough room + to complete in all cases. + */ + +#include +#include +#include +#include "zlib.h" + +#define local static + +/* print nastygram and leave */ +local void quit(char *why) +{ + fprintf(stderr, "fitblk abort: %s\n", why); + exit(1); +} + +#define RAWLEN 4096 /* intermediate uncompressed buffer size */ + +/* compress from file to def until provided buffer is full or end of + input reached; return last deflate() return value, or Z_ERRNO if + there was read error on the file */ +local int partcompress(FILE *in, z_streamp def) +{ + int ret, flush; + unsigned char raw[RAWLEN]; + + flush = Z_NO_FLUSH; + do { + def->avail_in = fread(raw, 1, RAWLEN, in); + if (ferror(in)) + return Z_ERRNO; + def->next_in = raw; + if (feof(in)) + flush = Z_FINISH; + ret = deflate(def, flush); + assert(ret != Z_STREAM_ERROR); + } while (def->avail_out != 0 && flush == Z_NO_FLUSH); + return ret; +} + +/* recompress from inf's input to def's output; the input for inf and + the output for def are set in those structures before calling; + return last deflate() return value, or Z_MEM_ERROR if inflate() + was not able to allocate enough memory when it needed to */ +local int recompress(z_streamp inf, z_streamp def) +{ + int ret, flush; + unsigned char raw[RAWLEN]; + + flush = Z_NO_FLUSH; + do { + /* decompress */ + inf->avail_out = RAWLEN; + inf->next_out = raw; + ret = inflate(inf, Z_NO_FLUSH); + assert(ret != Z_STREAM_ERROR && ret != Z_DATA_ERROR && + ret != Z_NEED_DICT); + if (ret == Z_MEM_ERROR) + return ret; + + /* compress what was decompresed until done or no room */ + def->avail_in = RAWLEN - inf->avail_out; + def->next_in = raw; + if (inf->avail_out != 0) + flush = Z_FINISH; + ret = deflate(def, flush); + assert(ret != Z_STREAM_ERROR); + } while (ret != Z_STREAM_END && def->avail_out != 0); + return ret; +} + +#define EXCESS 256 /* empirically determined stream overage */ +#define MARGIN 8 /* amount to back off for completion */ + +/* compress from stdin to fixed-size block on stdout */ +int main(int argc, char **argv) +{ + int ret; /* return code */ + unsigned size; /* requested fixed output block size */ + unsigned have; /* bytes written by deflate() call */ + unsigned char *blk; /* intermediate and final stream */ + unsigned char *tmp; /* close to desired size stream */ + z_stream def, inf; /* zlib deflate and inflate states */ + + /* get requested output size */ + if (argc != 2) + quit("need one argument: size of output block"); + ret = strtol(argv[1], argv + 1, 10); + if (argv[1][0] != 0) + quit("argument must be a number"); + if (ret < 8) /* 8 is minimum zlib stream size */ + quit("need positive size of 8 or greater"); + size = (unsigned)ret; + + /* allocate memory for buffers and compression engine */ + blk = malloc(size + EXCESS); + def.zalloc = Z_NULL; + def.zfree = Z_NULL; + def.opaque = Z_NULL; + ret = deflateInit(&def, Z_DEFAULT_COMPRESSION); + if (ret != Z_OK || blk == NULL) + quit("out of memory"); + + /* compress from stdin until output full, or no more input */ + def.avail_out = size + EXCESS; + def.next_out = blk; + ret = partcompress(stdin, &def); + if (ret == Z_ERRNO) + quit("error reading input"); + + /* if it all fit, then size was undersubscribed -- done! */ + if (ret == Z_STREAM_END && def.avail_out >= EXCESS) { + /* write block to stdout */ + have = size + EXCESS - def.avail_out; + if (fwrite(blk, 1, have, stdout) != have || ferror(stdout)) + quit("error writing output"); + + /* clean up and print results to stderr */ + ret = deflateEnd(&def); + assert(ret != Z_STREAM_ERROR); + free(blk); + fprintf(stderr, + "%u bytes unused out of %u requested (all input)\n", + size - have, size); + return 0; + } + + /* it didn't all fit -- set up for recompression */ + inf.zalloc = Z_NULL; + inf.zfree = Z_NULL; + inf.opaque = Z_NULL; + inf.avail_in = 0; + inf.next_in = Z_NULL; + ret = inflateInit(&inf); + tmp = malloc(size + EXCESS); + if (ret != Z_OK || tmp == NULL) + quit("out of memory"); + ret = deflateReset(&def); + assert(ret != Z_STREAM_ERROR); + + /* do first recompression close to the right amount */ + inf.avail_in = size + EXCESS; + inf.next_in = blk; + def.avail_out = size + EXCESS; + def.next_out = tmp; + ret = recompress(&inf, &def); + if (ret == Z_MEM_ERROR) + quit("out of memory"); + + /* set up for next reocmpression */ + ret = inflateReset(&inf); + assert(ret != Z_STREAM_ERROR); + ret = deflateReset(&def); + assert(ret != Z_STREAM_ERROR); + + /* do second and final recompression (third compression) */ + inf.avail_in = size - MARGIN; /* assure stream will complete */ + inf.next_in = tmp; + def.avail_out = size; + def.next_out = blk; + ret = recompress(&inf, &def); + if (ret == Z_MEM_ERROR) + quit("out of memory"); + assert(ret == Z_STREAM_END); /* otherwise MARGIN too small */ + + /* done -- write block to stdout */ + have = size - def.avail_out; + if (fwrite(blk, 1, have, stdout) != have || ferror(stdout)) + quit("error writing output"); + + /* clean up and print results to stderr */ + free(tmp); + ret = inflateEnd(&inf); + assert(ret != Z_STREAM_ERROR); + ret = deflateEnd(&def); + assert(ret != Z_STREAM_ERROR); + free(blk); + fprintf(stderr, + "%u bytes unused out of %u requested (%lu input)\n", + size - have, size, def.total_in); + return 0; +} diff --git a/dependencies/zlib-1.2.11/examples/gun.c b/dependencies/zlib-1.2.11/examples/gun.c new file mode 100644 index 0000000..be44fa5 --- /dev/null +++ b/dependencies/zlib-1.2.11/examples/gun.c @@ -0,0 +1,702 @@ +/* gun.c -- simple gunzip to give an example of the use of inflateBack() + * Copyright (C) 2003, 2005, 2008, 2010, 2012 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + Version 1.7 12 August 2012 Mark Adler */ + +/* Version history: + 1.0 16 Feb 2003 First version for testing of inflateBack() + 1.1 21 Feb 2005 Decompress concatenated gzip streams + Remove use of "this" variable (C++ keyword) + Fix return value for in() + Improve allocation failure checking + Add typecasting for void * structures + Add -h option for command version and usage + Add a bunch of comments + 1.2 20 Mar 2005 Add Unix compress (LZW) decompression + Copy file attributes from input file to output file + 1.3 12 Jun 2005 Add casts for error messages [Oberhumer] + 1.4 8 Dec 2006 LZW decompression speed improvements + 1.5 9 Feb 2008 Avoid warning in latest version of gcc + 1.6 17 Jan 2010 Avoid signed/unsigned comparison warnings + 1.7 12 Aug 2012 Update for z_const usage in zlib 1.2.8 + */ + +/* + gun [ -t ] [ name ... ] + + decompresses the data in the named gzip files. If no arguments are given, + gun will decompress from stdin to stdout. The names must end in .gz, -gz, + .z, -z, _z, or .Z. The uncompressed data will be written to a file name + with the suffix stripped. On success, the original file is deleted. On + failure, the output file is deleted. For most failures, the command will + continue to process the remaining names on the command line. A memory + allocation failure will abort the command. If -t is specified, then the + listed files or stdin will be tested as gzip files for integrity (without + checking for a proper suffix), no output will be written, and no files + will be deleted. + + Like gzip, gun allows concatenated gzip streams and will decompress them, + writing all of the uncompressed data to the output. Unlike gzip, gun allows + an empty file on input, and will produce no error writing an empty output + file. + + gun will also decompress files made by Unix compress, which uses LZW + compression. These files are automatically detected by virtue of their + magic header bytes. Since the end of Unix compress stream is marked by the + end-of-file, they cannot be concantenated. If a Unix compress stream is + encountered in an input file, it is the last stream in that file. + + Like gunzip and uncompress, the file attributes of the original compressed + file are maintained in the final uncompressed file, to the extent that the + user permissions allow it. + + On my Mac OS X PowerPC G4, gun is almost twice as fast as gunzip (version + 1.2.4) is on the same file, when gun is linked with zlib 1.2.2. Also the + LZW decompression provided by gun is about twice as fast as the standard + Unix uncompress command. + */ + +/* external functions and related types and constants */ +#include /* fprintf() */ +#include /* malloc(), free() */ +#include /* strerror(), strcmp(), strlen(), memcpy() */ +#include /* errno */ +#include /* open() */ +#include /* read(), write(), close(), chown(), unlink() */ +#include +#include /* stat(), chmod() */ +#include /* utime() */ +#include "zlib.h" /* inflateBackInit(), inflateBack(), */ + /* inflateBackEnd(), crc32() */ + +/* function declaration */ +#define local static + +/* buffer constants */ +#define SIZE 32768U /* input and output buffer sizes */ +#define PIECE 16384 /* limits i/o chunks for 16-bit int case */ + +/* structure for infback() to pass to input function in() -- it maintains the + input file and a buffer of size SIZE */ +struct ind { + int infile; + unsigned char *inbuf; +}; + +/* Load input buffer, assumed to be empty, and return bytes loaded and a + pointer to them. read() is called until the buffer is full, or until it + returns end-of-file or error. Return 0 on error. */ +local unsigned in(void *in_desc, z_const unsigned char **buf) +{ + int ret; + unsigned len; + unsigned char *next; + struct ind *me = (struct ind *)in_desc; + + next = me->inbuf; + *buf = next; + len = 0; + do { + ret = PIECE; + if ((unsigned)ret > SIZE - len) + ret = (int)(SIZE - len); + ret = (int)read(me->infile, next, ret); + if (ret == -1) { + len = 0; + break; + } + next += ret; + len += ret; + } while (ret != 0 && len < SIZE); + return len; +} + +/* structure for infback() to pass to output function out() -- it maintains the + output file, a running CRC-32 check on the output and the total number of + bytes output, both for checking against the gzip trailer. (The length in + the gzip trailer is stored modulo 2^32, so it's ok if a long is 32 bits and + the output is greater than 4 GB.) */ +struct outd { + int outfile; + int check; /* true if checking crc and total */ + unsigned long crc; + unsigned long total; +}; + +/* Write output buffer and update the CRC-32 and total bytes written. write() + is called until all of the output is written or an error is encountered. + On success out() returns 0. For a write failure, out() returns 1. If the + output file descriptor is -1, then nothing is written. + */ +local int out(void *out_desc, unsigned char *buf, unsigned len) +{ + int ret; + struct outd *me = (struct outd *)out_desc; + + if (me->check) { + me->crc = crc32(me->crc, buf, len); + me->total += len; + } + if (me->outfile != -1) + do { + ret = PIECE; + if ((unsigned)ret > len) + ret = (int)len; + ret = (int)write(me->outfile, buf, ret); + if (ret == -1) + return 1; + buf += ret; + len -= ret; + } while (len != 0); + return 0; +} + +/* next input byte macro for use inside lunpipe() and gunpipe() */ +#define NEXT() (have ? 0 : (have = in(indp, &next)), \ + last = have ? (have--, (int)(*next++)) : -1) + +/* memory for gunpipe() and lunpipe() -- + the first 256 entries of prefix[] and suffix[] are never used, could + have offset the index, but it's faster to waste the memory */ +unsigned char inbuf[SIZE]; /* input buffer */ +unsigned char outbuf[SIZE]; /* output buffer */ +unsigned short prefix[65536]; /* index to LZW prefix string */ +unsigned char suffix[65536]; /* one-character LZW suffix */ +unsigned char match[65280 + 2]; /* buffer for reversed match or gzip + 32K sliding window */ + +/* throw out what's left in the current bits byte buffer (this is a vestigial + aspect of the compressed data format derived from an implementation that + made use of a special VAX machine instruction!) */ +#define FLUSHCODE() \ + do { \ + left = 0; \ + rem = 0; \ + if (chunk > have) { \ + chunk -= have; \ + have = 0; \ + if (NEXT() == -1) \ + break; \ + chunk--; \ + if (chunk > have) { \ + chunk = have = 0; \ + break; \ + } \ + } \ + have -= chunk; \ + next += chunk; \ + chunk = 0; \ + } while (0) + +/* Decompress a compress (LZW) file from indp to outfile. The compress magic + header (two bytes) has already been read and verified. There are have bytes + of buffered input at next. strm is used for passing error information back + to gunpipe(). + + lunpipe() will return Z_OK on success, Z_BUF_ERROR for an unexpected end of + file, read error, or write error (a write error indicated by strm->next_in + not equal to Z_NULL), or Z_DATA_ERROR for invalid input. + */ +local int lunpipe(unsigned have, z_const unsigned char *next, struct ind *indp, + int outfile, z_stream *strm) +{ + int last; /* last byte read by NEXT(), or -1 if EOF */ + unsigned chunk; /* bytes left in current chunk */ + int left; /* bits left in rem */ + unsigned rem; /* unused bits from input */ + int bits; /* current bits per code */ + unsigned code; /* code, table traversal index */ + unsigned mask; /* mask for current bits codes */ + int max; /* maximum bits per code for this stream */ + unsigned flags; /* compress flags, then block compress flag */ + unsigned end; /* last valid entry in prefix/suffix tables */ + unsigned temp; /* current code */ + unsigned prev; /* previous code */ + unsigned final; /* last character written for previous code */ + unsigned stack; /* next position for reversed string */ + unsigned outcnt; /* bytes in output buffer */ + struct outd outd; /* output structure */ + unsigned char *p; + + /* set up output */ + outd.outfile = outfile; + outd.check = 0; + + /* process remainder of compress header -- a flags byte */ + flags = NEXT(); + if (last == -1) + return Z_BUF_ERROR; + if (flags & 0x60) { + strm->msg = (char *)"unknown lzw flags set"; + return Z_DATA_ERROR; + } + max = flags & 0x1f; + if (max < 9 || max > 16) { + strm->msg = (char *)"lzw bits out of range"; + return Z_DATA_ERROR; + } + if (max == 9) /* 9 doesn't really mean 9 */ + max = 10; + flags &= 0x80; /* true if block compress */ + + /* clear table */ + bits = 9; + mask = 0x1ff; + end = flags ? 256 : 255; + + /* set up: get first 9-bit code, which is the first decompressed byte, but + don't create a table entry until the next code */ + if (NEXT() == -1) /* no compressed data is ok */ + return Z_OK; + final = prev = (unsigned)last; /* low 8 bits of code */ + if (NEXT() == -1) /* missing a bit */ + return Z_BUF_ERROR; + if (last & 1) { /* code must be < 256 */ + strm->msg = (char *)"invalid lzw code"; + return Z_DATA_ERROR; + } + rem = (unsigned)last >> 1; /* remaining 7 bits */ + left = 7; + chunk = bits - 2; /* 7 bytes left in this chunk */ + outbuf[0] = (unsigned char)final; /* write first decompressed byte */ + outcnt = 1; + + /* decode codes */ + stack = 0; + for (;;) { + /* if the table will be full after this, increment the code size */ + if (end >= mask && bits < max) { + FLUSHCODE(); + bits++; + mask <<= 1; + mask++; + } + + /* get a code of length bits */ + if (chunk == 0) /* decrement chunk modulo bits */ + chunk = bits; + code = rem; /* low bits of code */ + if (NEXT() == -1) { /* EOF is end of compressed data */ + /* write remaining buffered output */ + if (outcnt && out(&outd, outbuf, outcnt)) { + strm->next_in = outbuf; /* signal write error */ + return Z_BUF_ERROR; + } + return Z_OK; + } + code += (unsigned)last << left; /* middle (or high) bits of code */ + left += 8; + chunk--; + if (bits > left) { /* need more bits */ + if (NEXT() == -1) /* can't end in middle of code */ + return Z_BUF_ERROR; + code += (unsigned)last << left; /* high bits of code */ + left += 8; + chunk--; + } + code &= mask; /* mask to current code length */ + left -= bits; /* number of unused bits */ + rem = (unsigned)last >> (8 - left); /* unused bits from last byte */ + + /* process clear code (256) */ + if (code == 256 && flags) { + FLUSHCODE(); + bits = 9; /* initialize bits and mask */ + mask = 0x1ff; + end = 255; /* empty table */ + continue; /* get next code */ + } + + /* special code to reuse last match */ + temp = code; /* save the current code */ + if (code > end) { + /* Be picky on the allowed code here, and make sure that the code + we drop through (prev) will be a valid index so that random + input does not cause an exception. The code != end + 1 check is + empirically derived, and not checked in the original uncompress + code. If this ever causes a problem, that check could be safely + removed. Leaving this check in greatly improves gun's ability + to detect random or corrupted input after a compress header. + In any case, the prev > end check must be retained. */ + if (code != end + 1 || prev > end) { + strm->msg = (char *)"invalid lzw code"; + return Z_DATA_ERROR; + } + match[stack++] = (unsigned char)final; + code = prev; + } + + /* walk through linked list to generate output in reverse order */ + p = match + stack; + while (code >= 256) { + *p++ = suffix[code]; + code = prefix[code]; + } + stack = p - match; + match[stack++] = (unsigned char)code; + final = code; + + /* link new table entry */ + if (end < mask) { + end++; + prefix[end] = (unsigned short)prev; + suffix[end] = (unsigned char)final; + } + + /* set previous code for next iteration */ + prev = temp; + + /* write output in forward order */ + while (stack > SIZE - outcnt) { + while (outcnt < SIZE) + outbuf[outcnt++] = match[--stack]; + if (out(&outd, outbuf, outcnt)) { + strm->next_in = outbuf; /* signal write error */ + return Z_BUF_ERROR; + } + outcnt = 0; + } + p = match + stack; + do { + outbuf[outcnt++] = *--p; + } while (p > match); + stack = 0; + + /* loop for next code with final and prev as the last match, rem and + left provide the first 0..7 bits of the next code, end is the last + valid table entry */ + } +} + +/* Decompress a gzip file from infile to outfile. strm is assumed to have been + successfully initialized with inflateBackInit(). The input file may consist + of a series of gzip streams, in which case all of them will be decompressed + to the output file. If outfile is -1, then the gzip stream(s) integrity is + checked and nothing is written. + + The return value is a zlib error code: Z_MEM_ERROR if out of memory, + Z_DATA_ERROR if the header or the compressed data is invalid, or if the + trailer CRC-32 check or length doesn't match, Z_BUF_ERROR if the input ends + prematurely or a write error occurs, or Z_ERRNO if junk (not a another gzip + stream) follows a valid gzip stream. + */ +local int gunpipe(z_stream *strm, int infile, int outfile) +{ + int ret, first, last; + unsigned have, flags, len; + z_const unsigned char *next = NULL; + struct ind ind, *indp; + struct outd outd; + + /* setup input buffer */ + ind.infile = infile; + ind.inbuf = inbuf; + indp = &ind; + + /* decompress concatenated gzip streams */ + have = 0; /* no input data read in yet */ + first = 1; /* looking for first gzip header */ + strm->next_in = Z_NULL; /* so Z_BUF_ERROR means EOF */ + for (;;) { + /* look for the two magic header bytes for a gzip stream */ + if (NEXT() == -1) { + ret = Z_OK; + break; /* empty gzip stream is ok */ + } + if (last != 31 || (NEXT() != 139 && last != 157)) { + strm->msg = (char *)"incorrect header check"; + ret = first ? Z_DATA_ERROR : Z_ERRNO; + break; /* not a gzip or compress header */ + } + first = 0; /* next non-header is junk */ + + /* process a compress (LZW) file -- can't be concatenated after this */ + if (last == 157) { + ret = lunpipe(have, next, indp, outfile, strm); + break; + } + + /* process remainder of gzip header */ + ret = Z_BUF_ERROR; + if (NEXT() != 8) { /* only deflate method allowed */ + if (last == -1) break; + strm->msg = (char *)"unknown compression method"; + ret = Z_DATA_ERROR; + break; + } + flags = NEXT(); /* header flags */ + NEXT(); /* discard mod time, xflgs, os */ + NEXT(); + NEXT(); + NEXT(); + NEXT(); + NEXT(); + if (last == -1) break; + if (flags & 0xe0) { + strm->msg = (char *)"unknown header flags set"; + ret = Z_DATA_ERROR; + break; + } + if (flags & 4) { /* extra field */ + len = NEXT(); + len += (unsigned)(NEXT()) << 8; + if (last == -1) break; + while (len > have) { + len -= have; + have = 0; + if (NEXT() == -1) break; + len--; + } + if (last == -1) break; + have -= len; + next += len; + } + if (flags & 8) /* file name */ + while (NEXT() != 0 && last != -1) + ; + if (flags & 16) /* comment */ + while (NEXT() != 0 && last != -1) + ; + if (flags & 2) { /* header crc */ + NEXT(); + NEXT(); + } + if (last == -1) break; + + /* set up output */ + outd.outfile = outfile; + outd.check = 1; + outd.crc = crc32(0L, Z_NULL, 0); + outd.total = 0; + + /* decompress data to output */ + strm->next_in = next; + strm->avail_in = have; + ret = inflateBack(strm, in, indp, out, &outd); + if (ret != Z_STREAM_END) break; + next = strm->next_in; + have = strm->avail_in; + strm->next_in = Z_NULL; /* so Z_BUF_ERROR means EOF */ + + /* check trailer */ + ret = Z_BUF_ERROR; + if (NEXT() != (int)(outd.crc & 0xff) || + NEXT() != (int)((outd.crc >> 8) & 0xff) || + NEXT() != (int)((outd.crc >> 16) & 0xff) || + NEXT() != (int)((outd.crc >> 24) & 0xff)) { + /* crc error */ + if (last != -1) { + strm->msg = (char *)"incorrect data check"; + ret = Z_DATA_ERROR; + } + break; + } + if (NEXT() != (int)(outd.total & 0xff) || + NEXT() != (int)((outd.total >> 8) & 0xff) || + NEXT() != (int)((outd.total >> 16) & 0xff) || + NEXT() != (int)((outd.total >> 24) & 0xff)) { + /* length error */ + if (last != -1) { + strm->msg = (char *)"incorrect length check"; + ret = Z_DATA_ERROR; + } + break; + } + + /* go back and look for another gzip stream */ + } + + /* clean up and return */ + return ret; +} + +/* Copy file attributes, from -> to, as best we can. This is best effort, so + no errors are reported. The mode bits, including suid, sgid, and the sticky + bit are copied (if allowed), the owner's user id and group id are copied + (again if allowed), and the access and modify times are copied. */ +local void copymeta(char *from, char *to) +{ + struct stat was; + struct utimbuf when; + + /* get all of from's Unix meta data, return if not a regular file */ + if (stat(from, &was) != 0 || (was.st_mode & S_IFMT) != S_IFREG) + return; + + /* set to's mode bits, ignore errors */ + (void)chmod(to, was.st_mode & 07777); + + /* copy owner's user and group, ignore errors */ + (void)chown(to, was.st_uid, was.st_gid); + + /* copy access and modify times, ignore errors */ + when.actime = was.st_atime; + when.modtime = was.st_mtime; + (void)utime(to, &when); +} + +/* Decompress the file inname to the file outnname, of if test is true, just + decompress without writing and check the gzip trailer for integrity. If + inname is NULL or an empty string, read from stdin. If outname is NULL or + an empty string, write to stdout. strm is a pre-initialized inflateBack + structure. When appropriate, copy the file attributes from inname to + outname. + + gunzip() returns 1 if there is an out-of-memory error or an unexpected + return code from gunpipe(). Otherwise it returns 0. + */ +local int gunzip(z_stream *strm, char *inname, char *outname, int test) +{ + int ret; + int infile, outfile; + + /* open files */ + if (inname == NULL || *inname == 0) { + inname = "-"; + infile = 0; /* stdin */ + } + else { + infile = open(inname, O_RDONLY, 0); + if (infile == -1) { + fprintf(stderr, "gun cannot open %s\n", inname); + return 0; + } + } + if (test) + outfile = -1; + else if (outname == NULL || *outname == 0) { + outname = "-"; + outfile = 1; /* stdout */ + } + else { + outfile = open(outname, O_CREAT | O_TRUNC | O_WRONLY, 0666); + if (outfile == -1) { + close(infile); + fprintf(stderr, "gun cannot create %s\n", outname); + return 0; + } + } + errno = 0; + + /* decompress */ + ret = gunpipe(strm, infile, outfile); + if (outfile > 2) close(outfile); + if (infile > 2) close(infile); + + /* interpret result */ + switch (ret) { + case Z_OK: + case Z_ERRNO: + if (infile > 2 && outfile > 2) { + copymeta(inname, outname); /* copy attributes */ + unlink(inname); + } + if (ret == Z_ERRNO) + fprintf(stderr, "gun warning: trailing garbage ignored in %s\n", + inname); + break; + case Z_DATA_ERROR: + if (outfile > 2) unlink(outname); + fprintf(stderr, "gun data error on %s: %s\n", inname, strm->msg); + break; + case Z_MEM_ERROR: + if (outfile > 2) unlink(outname); + fprintf(stderr, "gun out of memory error--aborting\n"); + return 1; + case Z_BUF_ERROR: + if (outfile > 2) unlink(outname); + if (strm->next_in != Z_NULL) { + fprintf(stderr, "gun write error on %s: %s\n", + outname, strerror(errno)); + } + else if (errno) { + fprintf(stderr, "gun read error on %s: %s\n", + inname, strerror(errno)); + } + else { + fprintf(stderr, "gun unexpected end of file on %s\n", + inname); + } + break; + default: + if (outfile > 2) unlink(outname); + fprintf(stderr, "gun internal error--aborting\n"); + return 1; + } + return 0; +} + +/* Process the gun command line arguments. See the command syntax near the + beginning of this source file. */ +int main(int argc, char **argv) +{ + int ret, len, test; + char *outname; + unsigned char *window; + z_stream strm; + + /* initialize inflateBack state for repeated use */ + window = match; /* reuse LZW match buffer */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + ret = inflateBackInit(&strm, 15, window); + if (ret != Z_OK) { + fprintf(stderr, "gun out of memory error--aborting\n"); + return 1; + } + + /* decompress each file to the same name with the suffix removed */ + argc--; + argv++; + test = 0; + if (argc && strcmp(*argv, "-h") == 0) { + fprintf(stderr, "gun 1.6 (17 Jan 2010)\n"); + fprintf(stderr, "Copyright (C) 2003-2010 Mark Adler\n"); + fprintf(stderr, "usage: gun [-t] [file1.gz [file2.Z ...]]\n"); + return 0; + } + if (argc && strcmp(*argv, "-t") == 0) { + test = 1; + argc--; + argv++; + } + if (argc) + do { + if (test) + outname = NULL; + else { + len = (int)strlen(*argv); + if (strcmp(*argv + len - 3, ".gz") == 0 || + strcmp(*argv + len - 3, "-gz") == 0) + len -= 3; + else if (strcmp(*argv + len - 2, ".z") == 0 || + strcmp(*argv + len - 2, "-z") == 0 || + strcmp(*argv + len - 2, "_z") == 0 || + strcmp(*argv + len - 2, ".Z") == 0) + len -= 2; + else { + fprintf(stderr, "gun error: no gz type on %s--skipping\n", + *argv); + continue; + } + outname = malloc(len + 1); + if (outname == NULL) { + fprintf(stderr, "gun out of memory error--aborting\n"); + ret = 1; + break; + } + memcpy(outname, *argv, len); + outname[len] = 0; + } + ret = gunzip(&strm, *argv, outname, test); + if (outname != NULL) free(outname); + if (ret) break; + } while (argv++, --argc); + else + ret = gunzip(&strm, NULL, NULL, test); + + /* clean up */ + inflateBackEnd(&strm); + return ret; +} diff --git a/dependencies/zlib-1.2.11/examples/gzappend.c b/dependencies/zlib-1.2.11/examples/gzappend.c new file mode 100644 index 0000000..662dec3 --- /dev/null +++ b/dependencies/zlib-1.2.11/examples/gzappend.c @@ -0,0 +1,504 @@ +/* gzappend -- command to append to a gzip file + + Copyright (C) 2003, 2012 Mark Adler, all rights reserved + version 1.2, 11 Oct 2012 + + This software is provided 'as-is', without any express or implied + warranty. In no event will the author be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Mark Adler madler@alumni.caltech.edu + */ + +/* + * Change history: + * + * 1.0 19 Oct 2003 - First version + * 1.1 4 Nov 2003 - Expand and clarify some comments and notes + * - Add version and copyright to help + * - Send help to stdout instead of stderr + * - Add some preemptive typecasts + * - Add L to constants in lseek() calls + * - Remove some debugging information in error messages + * - Use new data_type definition for zlib 1.2.1 + * - Simplfy and unify file operations + * - Finish off gzip file in gztack() + * - Use deflatePrime() instead of adding empty blocks + * - Keep gzip file clean on appended file read errors + * - Use in-place rotate instead of auxiliary buffer + * (Why you ask? Because it was fun to write!) + * 1.2 11 Oct 2012 - Fix for proper z_const usage + * - Check for input buffer malloc failure + */ + +/* + gzappend takes a gzip file and appends to it, compressing files from the + command line or data from stdin. The gzip file is written to directly, to + avoid copying that file, in case it's large. Note that this results in the + unfriendly behavior that if gzappend fails, the gzip file is corrupted. + + This program was written to illustrate the use of the new Z_BLOCK option of + zlib 1.2.x's inflate() function. This option returns from inflate() at each + block boundary to facilitate locating and modifying the last block bit at + the start of the final deflate block. Also whether using Z_BLOCK or not, + another required feature of zlib 1.2.x is that inflate() now provides the + number of unusued bits in the last input byte used. gzappend will not work + with versions of zlib earlier than 1.2.1. + + gzappend first decompresses the gzip file internally, discarding all but + the last 32K of uncompressed data, and noting the location of the last block + bit and the number of unused bits in the last byte of the compressed data. + The gzip trailer containing the CRC-32 and length of the uncompressed data + is verified. This trailer will be later overwritten. + + Then the last block bit is cleared by seeking back in the file and rewriting + the byte that contains it. Seeking forward, the last byte of the compressed + data is saved along with the number of unused bits to initialize deflate. + + A deflate process is initialized, using the last 32K of the uncompressed + data from the gzip file to initialize the dictionary. If the total + uncompressed data was less than 32K, then all of it is used to initialize + the dictionary. The deflate output bit buffer is also initialized with the + last bits from the original deflate stream. From here on, the data to + append is simply compressed using deflate, and written to the gzip file. + When that is complete, the new CRC-32 and uncompressed length are written + as the trailer of the gzip file. + */ + +#include +#include +#include +#include +#include +#include "zlib.h" + +#define local static +#define LGCHUNK 14 +#define CHUNK (1U << LGCHUNK) +#define DSIZE 32768U + +/* print an error message and terminate with extreme prejudice */ +local void bye(char *msg1, char *msg2) +{ + fprintf(stderr, "gzappend error: %s%s\n", msg1, msg2); + exit(1); +} + +/* return the greatest common divisor of a and b using Euclid's algorithm, + modified to be fast when one argument much greater than the other, and + coded to avoid unnecessary swapping */ +local unsigned gcd(unsigned a, unsigned b) +{ + unsigned c; + + while (a && b) + if (a > b) { + c = b; + while (a - c >= c) + c <<= 1; + a -= c; + } + else { + c = a; + while (b - c >= c) + c <<= 1; + b -= c; + } + return a + b; +} + +/* rotate list[0..len-1] left by rot positions, in place */ +local void rotate(unsigned char *list, unsigned len, unsigned rot) +{ + unsigned char tmp; + unsigned cycles; + unsigned char *start, *last, *to, *from; + + /* normalize rot and handle degenerate cases */ + if (len < 2) return; + if (rot >= len) rot %= len; + if (rot == 0) return; + + /* pointer to last entry in list */ + last = list + (len - 1); + + /* do simple left shift by one */ + if (rot == 1) { + tmp = *list; + memcpy(list, list + 1, len - 1); + *last = tmp; + return; + } + + /* do simple right shift by one */ + if (rot == len - 1) { + tmp = *last; + memmove(list + 1, list, len - 1); + *list = tmp; + return; + } + + /* otherwise do rotate as a set of cycles in place */ + cycles = gcd(len, rot); /* number of cycles */ + do { + start = from = list + cycles; /* start index is arbitrary */ + tmp = *from; /* save entry to be overwritten */ + for (;;) { + to = from; /* next step in cycle */ + from += rot; /* go right rot positions */ + if (from > last) from -= len; /* (pointer better not wrap) */ + if (from == start) break; /* all but one shifted */ + *to = *from; /* shift left */ + } + *to = tmp; /* complete the circle */ + } while (--cycles); +} + +/* structure for gzip file read operations */ +typedef struct { + int fd; /* file descriptor */ + int size; /* 1 << size is bytes in buf */ + unsigned left; /* bytes available at next */ + unsigned char *buf; /* buffer */ + z_const unsigned char *next; /* next byte in buffer */ + char *name; /* file name for error messages */ +} file; + +/* reload buffer */ +local int readin(file *in) +{ + int len; + + len = read(in->fd, in->buf, 1 << in->size); + if (len == -1) bye("error reading ", in->name); + in->left = (unsigned)len; + in->next = in->buf; + return len; +} + +/* read from file in, exit if end-of-file */ +local int readmore(file *in) +{ + if (readin(in) == 0) bye("unexpected end of ", in->name); + return 0; +} + +#define read1(in) (in->left == 0 ? readmore(in) : 0, \ + in->left--, *(in->next)++) + +/* skip over n bytes of in */ +local void skip(file *in, unsigned n) +{ + unsigned bypass; + + if (n > in->left) { + n -= in->left; + bypass = n & ~((1U << in->size) - 1); + if (bypass) { + if (lseek(in->fd, (off_t)bypass, SEEK_CUR) == -1) + bye("seeking ", in->name); + n -= bypass; + } + readmore(in); + if (n > in->left) + bye("unexpected end of ", in->name); + } + in->left -= n; + in->next += n; +} + +/* read a four-byte unsigned integer, little-endian, from in */ +unsigned long read4(file *in) +{ + unsigned long val; + + val = read1(in); + val += (unsigned)read1(in) << 8; + val += (unsigned long)read1(in) << 16; + val += (unsigned long)read1(in) << 24; + return val; +} + +/* skip over gzip header */ +local void gzheader(file *in) +{ + int flags; + unsigned n; + + if (read1(in) != 31 || read1(in) != 139) bye(in->name, " not a gzip file"); + if (read1(in) != 8) bye("unknown compression method in", in->name); + flags = read1(in); + if (flags & 0xe0) bye("unknown header flags set in", in->name); + skip(in, 6); + if (flags & 4) { + n = read1(in); + n += (unsigned)(read1(in)) << 8; + skip(in, n); + } + if (flags & 8) while (read1(in) != 0) ; + if (flags & 16) while (read1(in) != 0) ; + if (flags & 2) skip(in, 2); +} + +/* decompress gzip file "name", return strm with a deflate stream ready to + continue compression of the data in the gzip file, and return a file + descriptor pointing to where to write the compressed data -- the deflate + stream is initialized to compress using level "level" */ +local int gzscan(char *name, z_stream *strm, int level) +{ + int ret, lastbit, left, full; + unsigned have; + unsigned long crc, tot; + unsigned char *window; + off_t lastoff, end; + file gz; + + /* open gzip file */ + gz.name = name; + gz.fd = open(name, O_RDWR, 0); + if (gz.fd == -1) bye("cannot open ", name); + gz.buf = malloc(CHUNK); + if (gz.buf == NULL) bye("out of memory", ""); + gz.size = LGCHUNK; + gz.left = 0; + + /* skip gzip header */ + gzheader(&gz); + + /* prepare to decompress */ + window = malloc(DSIZE); + if (window == NULL) bye("out of memory", ""); + strm->zalloc = Z_NULL; + strm->zfree = Z_NULL; + strm->opaque = Z_NULL; + ret = inflateInit2(strm, -15); + if (ret != Z_OK) bye("out of memory", " or library mismatch"); + + /* decompress the deflate stream, saving append information */ + lastbit = 0; + lastoff = lseek(gz.fd, 0L, SEEK_CUR) - gz.left; + left = 0; + strm->avail_in = gz.left; + strm->next_in = gz.next; + crc = crc32(0L, Z_NULL, 0); + have = full = 0; + do { + /* if needed, get more input */ + if (strm->avail_in == 0) { + readmore(&gz); + strm->avail_in = gz.left; + strm->next_in = gz.next; + } + + /* set up output to next available section of sliding window */ + strm->avail_out = DSIZE - have; + strm->next_out = window + have; + + /* inflate and check for errors */ + ret = inflate(strm, Z_BLOCK); + if (ret == Z_STREAM_ERROR) bye("internal stream error!", ""); + if (ret == Z_MEM_ERROR) bye("out of memory", ""); + if (ret == Z_DATA_ERROR) + bye("invalid compressed data--format violated in", name); + + /* update crc and sliding window pointer */ + crc = crc32(crc, window + have, DSIZE - have - strm->avail_out); + if (strm->avail_out) + have = DSIZE - strm->avail_out; + else { + have = 0; + full = 1; + } + + /* process end of block */ + if (strm->data_type & 128) { + if (strm->data_type & 64) + left = strm->data_type & 0x1f; + else { + lastbit = strm->data_type & 0x1f; + lastoff = lseek(gz.fd, 0L, SEEK_CUR) - strm->avail_in; + } + } + } while (ret != Z_STREAM_END); + inflateEnd(strm); + gz.left = strm->avail_in; + gz.next = strm->next_in; + + /* save the location of the end of the compressed data */ + end = lseek(gz.fd, 0L, SEEK_CUR) - gz.left; + + /* check gzip trailer and save total for deflate */ + if (crc != read4(&gz)) + bye("invalid compressed data--crc mismatch in ", name); + tot = strm->total_out; + if ((tot & 0xffffffffUL) != read4(&gz)) + bye("invalid compressed data--length mismatch in", name); + + /* if not at end of file, warn */ + if (gz.left || readin(&gz)) + fprintf(stderr, + "gzappend warning: junk at end of gzip file overwritten\n"); + + /* clear last block bit */ + lseek(gz.fd, lastoff - (lastbit != 0), SEEK_SET); + if (read(gz.fd, gz.buf, 1) != 1) bye("reading after seek on ", name); + *gz.buf = (unsigned char)(*gz.buf ^ (1 << ((8 - lastbit) & 7))); + lseek(gz.fd, -1L, SEEK_CUR); + if (write(gz.fd, gz.buf, 1) != 1) bye("writing after seek to ", name); + + /* if window wrapped, build dictionary from window by rotating */ + if (full) { + rotate(window, DSIZE, have); + have = DSIZE; + } + + /* set up deflate stream with window, crc, total_in, and leftover bits */ + ret = deflateInit2(strm, level, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); + if (ret != Z_OK) bye("out of memory", ""); + deflateSetDictionary(strm, window, have); + strm->adler = crc; + strm->total_in = tot; + if (left) { + lseek(gz.fd, --end, SEEK_SET); + if (read(gz.fd, gz.buf, 1) != 1) bye("reading after seek on ", name); + deflatePrime(strm, 8 - left, *gz.buf); + } + lseek(gz.fd, end, SEEK_SET); + + /* clean up and return */ + free(window); + free(gz.buf); + return gz.fd; +} + +/* append file "name" to gzip file gd using deflate stream strm -- if last + is true, then finish off the deflate stream at the end */ +local void gztack(char *name, int gd, z_stream *strm, int last) +{ + int fd, len, ret; + unsigned left; + unsigned char *in, *out; + + /* open file to compress and append */ + fd = 0; + if (name != NULL) { + fd = open(name, O_RDONLY, 0); + if (fd == -1) + fprintf(stderr, "gzappend warning: %s not found, skipping ...\n", + name); + } + + /* allocate buffers */ + in = malloc(CHUNK); + out = malloc(CHUNK); + if (in == NULL || out == NULL) bye("out of memory", ""); + + /* compress input file and append to gzip file */ + do { + /* get more input */ + len = read(fd, in, CHUNK); + if (len == -1) { + fprintf(stderr, + "gzappend warning: error reading %s, skipping rest ...\n", + name); + len = 0; + } + strm->avail_in = (unsigned)len; + strm->next_in = in; + if (len) strm->adler = crc32(strm->adler, in, (unsigned)len); + + /* compress and write all available output */ + do { + strm->avail_out = CHUNK; + strm->next_out = out; + ret = deflate(strm, last && len == 0 ? Z_FINISH : Z_NO_FLUSH); + left = CHUNK - strm->avail_out; + while (left) { + len = write(gd, out + CHUNK - strm->avail_out - left, left); + if (len == -1) bye("writing gzip file", ""); + left -= (unsigned)len; + } + } while (strm->avail_out == 0 && ret != Z_STREAM_END); + } while (len != 0); + + /* write trailer after last entry */ + if (last) { + deflateEnd(strm); + out[0] = (unsigned char)(strm->adler); + out[1] = (unsigned char)(strm->adler >> 8); + out[2] = (unsigned char)(strm->adler >> 16); + out[3] = (unsigned char)(strm->adler >> 24); + out[4] = (unsigned char)(strm->total_in); + out[5] = (unsigned char)(strm->total_in >> 8); + out[6] = (unsigned char)(strm->total_in >> 16); + out[7] = (unsigned char)(strm->total_in >> 24); + len = 8; + do { + ret = write(gd, out + 8 - len, len); + if (ret == -1) bye("writing gzip file", ""); + len -= ret; + } while (len); + close(gd); + } + + /* clean up and return */ + free(out); + free(in); + if (fd > 0) close(fd); +} + +/* process the compression level option if present, scan the gzip file, and + append the specified files, or append the data from stdin if no other file + names are provided on the command line -- the gzip file must be writable + and seekable */ +int main(int argc, char **argv) +{ + int gd, level; + z_stream strm; + + /* ignore command name */ + argc--; argv++; + + /* provide usage if no arguments */ + if (*argv == NULL) { + printf( + "gzappend 1.2 (11 Oct 2012) Copyright (C) 2003, 2012 Mark Adler\n" + ); + printf( + "usage: gzappend [-level] file.gz [ addthis [ andthis ... ]]\n"); + return 0; + } + + /* set compression level */ + level = Z_DEFAULT_COMPRESSION; + if (argv[0][0] == '-') { + if (argv[0][1] < '0' || argv[0][1] > '9' || argv[0][2] != 0) + bye("invalid compression level", ""); + level = argv[0][1] - '0'; + if (*++argv == NULL) bye("no gzip file name after options", ""); + } + + /* prepare to append to gzip file */ + gd = gzscan(*argv++, &strm, level); + + /* append files on command line, or from stdin if none */ + if (*argv == NULL) + gztack(NULL, gd, &strm, 1); + else + do { + gztack(*argv, gd, &strm, argv[1] == NULL); + } while (*++argv != NULL); + return 0; +} diff --git a/dependencies/zlib-1.2.11/examples/gzjoin.c b/dependencies/zlib-1.2.11/examples/gzjoin.c new file mode 100644 index 0000000..89e8098 --- /dev/null +++ b/dependencies/zlib-1.2.11/examples/gzjoin.c @@ -0,0 +1,449 @@ +/* gzjoin -- command to join gzip files into one gzip file + + Copyright (C) 2004, 2005, 2012 Mark Adler, all rights reserved + version 1.2, 14 Aug 2012 + + This software is provided 'as-is', without any express or implied + warranty. In no event will the author be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Mark Adler madler@alumni.caltech.edu + */ + +/* + * Change history: + * + * 1.0 11 Dec 2004 - First version + * 1.1 12 Jun 2005 - Changed ssize_t to long for portability + * 1.2 14 Aug 2012 - Clean up for z_const usage + */ + +/* + gzjoin takes one or more gzip files on the command line and writes out a + single gzip file that will uncompress to the concatenation of the + uncompressed data from the individual gzip files. gzjoin does this without + having to recompress any of the data and without having to calculate a new + crc32 for the concatenated uncompressed data. gzjoin does however have to + decompress all of the input data in order to find the bits in the compressed + data that need to be modified to concatenate the streams. + + gzjoin does not do an integrity check on the input gzip files other than + checking the gzip header and decompressing the compressed data. They are + otherwise assumed to be complete and correct. + + Each joint between gzip files removes at least 18 bytes of previous trailer + and subsequent header, and inserts an average of about three bytes to the + compressed data in order to connect the streams. The output gzip file + has a minimal ten-byte gzip header with no file name or modification time. + + This program was written to illustrate the use of the Z_BLOCK option of + inflate() and the crc32_combine() function. gzjoin will not compile with + versions of zlib earlier than 1.2.3. + */ + +#include /* fputs(), fprintf(), fwrite(), putc() */ +#include /* exit(), malloc(), free() */ +#include /* open() */ +#include /* close(), read(), lseek() */ +#include "zlib.h" + /* crc32(), crc32_combine(), inflateInit2(), inflate(), inflateEnd() */ + +#define local static + +/* exit with an error (return a value to allow use in an expression) */ +local int bail(char *why1, char *why2) +{ + fprintf(stderr, "gzjoin error: %s%s, output incomplete\n", why1, why2); + exit(1); + return 0; +} + +/* -- simple buffered file input with access to the buffer -- */ + +#define CHUNK 32768 /* must be a power of two and fit in unsigned */ + +/* bin buffered input file type */ +typedef struct { + char *name; /* name of file for error messages */ + int fd; /* file descriptor */ + unsigned left; /* bytes remaining at next */ + unsigned char *next; /* next byte to read */ + unsigned char *buf; /* allocated buffer of length CHUNK */ +} bin; + +/* close a buffered file and free allocated memory */ +local void bclose(bin *in) +{ + if (in != NULL) { + if (in->fd != -1) + close(in->fd); + if (in->buf != NULL) + free(in->buf); + free(in); + } +} + +/* open a buffered file for input, return a pointer to type bin, or NULL on + failure */ +local bin *bopen(char *name) +{ + bin *in; + + in = malloc(sizeof(bin)); + if (in == NULL) + return NULL; + in->buf = malloc(CHUNK); + in->fd = open(name, O_RDONLY, 0); + if (in->buf == NULL || in->fd == -1) { + bclose(in); + return NULL; + } + in->left = 0; + in->next = in->buf; + in->name = name; + return in; +} + +/* load buffer from file, return -1 on read error, 0 or 1 on success, with + 1 indicating that end-of-file was reached */ +local int bload(bin *in) +{ + long len; + + if (in == NULL) + return -1; + if (in->left != 0) + return 0; + in->next = in->buf; + do { + len = (long)read(in->fd, in->buf + in->left, CHUNK - in->left); + if (len < 0) + return -1; + in->left += (unsigned)len; + } while (len != 0 && in->left < CHUNK); + return len == 0 ? 1 : 0; +} + +/* get a byte from the file, bail if end of file */ +#define bget(in) (in->left ? 0 : bload(in), \ + in->left ? (in->left--, *(in->next)++) : \ + bail("unexpected end of file on ", in->name)) + +/* get a four-byte little-endian unsigned integer from file */ +local unsigned long bget4(bin *in) +{ + unsigned long val; + + val = bget(in); + val += (unsigned long)(bget(in)) << 8; + val += (unsigned long)(bget(in)) << 16; + val += (unsigned long)(bget(in)) << 24; + return val; +} + +/* skip bytes in file */ +local void bskip(bin *in, unsigned skip) +{ + /* check pointer */ + if (in == NULL) + return; + + /* easy case -- skip bytes in buffer */ + if (skip <= in->left) { + in->left -= skip; + in->next += skip; + return; + } + + /* skip what's in buffer, discard buffer contents */ + skip -= in->left; + in->left = 0; + + /* seek past multiples of CHUNK bytes */ + if (skip > CHUNK) { + unsigned left; + + left = skip & (CHUNK - 1); + if (left == 0) { + /* exact number of chunks: seek all the way minus one byte to check + for end-of-file with a read */ + lseek(in->fd, skip - 1, SEEK_CUR); + if (read(in->fd, in->buf, 1) != 1) + bail("unexpected end of file on ", in->name); + return; + } + + /* skip the integral chunks, update skip with remainder */ + lseek(in->fd, skip - left, SEEK_CUR); + skip = left; + } + + /* read more input and skip remainder */ + bload(in); + if (skip > in->left) + bail("unexpected end of file on ", in->name); + in->left -= skip; + in->next += skip; +} + +/* -- end of buffered input functions -- */ + +/* skip the gzip header from file in */ +local void gzhead(bin *in) +{ + int flags; + + /* verify gzip magic header and compression method */ + if (bget(in) != 0x1f || bget(in) != 0x8b || bget(in) != 8) + bail(in->name, " is not a valid gzip file"); + + /* get and verify flags */ + flags = bget(in); + if ((flags & 0xe0) != 0) + bail("unknown reserved bits set in ", in->name); + + /* skip modification time, extra flags, and os */ + bskip(in, 6); + + /* skip extra field if present */ + if (flags & 4) { + unsigned len; + + len = bget(in); + len += (unsigned)(bget(in)) << 8; + bskip(in, len); + } + + /* skip file name if present */ + if (flags & 8) + while (bget(in) != 0) + ; + + /* skip comment if present */ + if (flags & 16) + while (bget(in) != 0) + ; + + /* skip header crc if present */ + if (flags & 2) + bskip(in, 2); +} + +/* write a four-byte little-endian unsigned integer to out */ +local void put4(unsigned long val, FILE *out) +{ + putc(val & 0xff, out); + putc((val >> 8) & 0xff, out); + putc((val >> 16) & 0xff, out); + putc((val >> 24) & 0xff, out); +} + +/* Load up zlib stream from buffered input, bail if end of file */ +local void zpull(z_streamp strm, bin *in) +{ + if (in->left == 0) + bload(in); + if (in->left == 0) + bail("unexpected end of file on ", in->name); + strm->avail_in = in->left; + strm->next_in = in->next; +} + +/* Write header for gzip file to out and initialize trailer. */ +local void gzinit(unsigned long *crc, unsigned long *tot, FILE *out) +{ + fwrite("\x1f\x8b\x08\0\0\0\0\0\0\xff", 1, 10, out); + *crc = crc32(0L, Z_NULL, 0); + *tot = 0; +} + +/* Copy the compressed data from name, zeroing the last block bit of the last + block if clr is true, and adding empty blocks as needed to get to a byte + boundary. If clr is false, then the last block becomes the last block of + the output, and the gzip trailer is written. crc and tot maintains the + crc and length (modulo 2^32) of the output for the trailer. The resulting + gzip file is written to out. gzinit() must be called before the first call + of gzcopy() to write the gzip header and to initialize crc and tot. */ +local void gzcopy(char *name, int clr, unsigned long *crc, unsigned long *tot, + FILE *out) +{ + int ret; /* return value from zlib functions */ + int pos; /* where the "last block" bit is in byte */ + int last; /* true if processing the last block */ + bin *in; /* buffered input file */ + unsigned char *start; /* start of compressed data in buffer */ + unsigned char *junk; /* buffer for uncompressed data -- discarded */ + z_off_t len; /* length of uncompressed data (support > 4 GB) */ + z_stream strm; /* zlib inflate stream */ + + /* open gzip file and skip header */ + in = bopen(name); + if (in == NULL) + bail("could not open ", name); + gzhead(in); + + /* allocate buffer for uncompressed data and initialize raw inflate + stream */ + junk = malloc(CHUNK); + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit2(&strm, -15); + if (junk == NULL || ret != Z_OK) + bail("out of memory", ""); + + /* inflate and copy compressed data, clear last-block bit if requested */ + len = 0; + zpull(&strm, in); + start = in->next; + last = start[0] & 1; + if (last && clr) + start[0] &= ~1; + strm.avail_out = 0; + for (;;) { + /* if input used and output done, write used input and get more */ + if (strm.avail_in == 0 && strm.avail_out != 0) { + fwrite(start, 1, strm.next_in - start, out); + start = in->buf; + in->left = 0; + zpull(&strm, in); + } + + /* decompress -- return early when end-of-block reached */ + strm.avail_out = CHUNK; + strm.next_out = junk; + ret = inflate(&strm, Z_BLOCK); + switch (ret) { + case Z_MEM_ERROR: + bail("out of memory", ""); + case Z_DATA_ERROR: + bail("invalid compressed data in ", in->name); + } + + /* update length of uncompressed data */ + len += CHUNK - strm.avail_out; + + /* check for block boundary (only get this when block copied out) */ + if (strm.data_type & 128) { + /* if that was the last block, then done */ + if (last) + break; + + /* number of unused bits in last byte */ + pos = strm.data_type & 7; + + /* find the next last-block bit */ + if (pos != 0) { + /* next last-block bit is in last used byte */ + pos = 0x100 >> pos; + last = strm.next_in[-1] & pos; + if (last && clr) + in->buf[strm.next_in - in->buf - 1] &= ~pos; + } + else { + /* next last-block bit is in next unused byte */ + if (strm.avail_in == 0) { + /* don't have that byte yet -- get it */ + fwrite(start, 1, strm.next_in - start, out); + start = in->buf; + in->left = 0; + zpull(&strm, in); + } + last = strm.next_in[0] & 1; + if (last && clr) + in->buf[strm.next_in - in->buf] &= ~1; + } + } + } + + /* update buffer with unused input */ + in->left = strm.avail_in; + in->next = in->buf + (strm.next_in - in->buf); + + /* copy used input, write empty blocks to get to byte boundary */ + pos = strm.data_type & 7; + fwrite(start, 1, in->next - start - 1, out); + last = in->next[-1]; + if (pos == 0 || !clr) + /* already at byte boundary, or last file: write last byte */ + putc(last, out); + else { + /* append empty blocks to last byte */ + last &= ((0x100 >> pos) - 1); /* assure unused bits are zero */ + if (pos & 1) { + /* odd -- append an empty stored block */ + putc(last, out); + if (pos == 1) + putc(0, out); /* two more bits in block header */ + fwrite("\0\0\xff\xff", 1, 4, out); + } + else { + /* even -- append 1, 2, or 3 empty fixed blocks */ + switch (pos) { + case 6: + putc(last | 8, out); + last = 0; + case 4: + putc(last | 0x20, out); + last = 0; + case 2: + putc(last | 0x80, out); + putc(0, out); + } + } + } + + /* update crc and tot */ + *crc = crc32_combine(*crc, bget4(in), len); + *tot += (unsigned long)len; + + /* clean up */ + inflateEnd(&strm); + free(junk); + bclose(in); + + /* write trailer if this is the last gzip file */ + if (!clr) { + put4(*crc, out); + put4(*tot, out); + } +} + +/* join the gzip files on the command line, write result to stdout */ +int main(int argc, char **argv) +{ + unsigned long crc, tot; /* running crc and total uncompressed length */ + + /* skip command name */ + argc--; + argv++; + + /* show usage if no arguments */ + if (argc == 0) { + fputs("gzjoin usage: gzjoin f1.gz [f2.gz [f3.gz ...]] > fjoin.gz\n", + stderr); + return 0; + } + + /* join gzip files on command line and write to stdout */ + gzinit(&crc, &tot, stdout); + while (argc--) + gzcopy(*argv++, argc, &crc, &tot, stdout); + + /* done */ + return 0; +} diff --git a/dependencies/zlib-1.2.11/examples/gzlog.c b/dependencies/zlib-1.2.11/examples/gzlog.c new file mode 100644 index 0000000..b8c2927 --- /dev/null +++ b/dependencies/zlib-1.2.11/examples/gzlog.c @@ -0,0 +1,1059 @@ +/* + * gzlog.c + * Copyright (C) 2004, 2008, 2012, 2016 Mark Adler, all rights reserved + * For conditions of distribution and use, see copyright notice in gzlog.h + * version 2.2, 14 Aug 2012 + */ + +/* + gzlog provides a mechanism for frequently appending short strings to a gzip + file that is efficient both in execution time and compression ratio. The + strategy is to write the short strings in an uncompressed form to the end of + the gzip file, only compressing when the amount of uncompressed data has + reached a given threshold. + + gzlog also provides protection against interruptions in the process due to + system crashes. The status of the operation is recorded in an extra field + in the gzip file, and is only updated once the gzip file is brought to a + valid state. The last data to be appended or compressed is saved in an + auxiliary file, so that if the operation is interrupted, it can be completed + the next time an append operation is attempted. + + gzlog maintains another auxiliary file with the last 32K of data from the + compressed portion, which is preloaded for the compression of the subsequent + data. This minimizes the impact to the compression ratio of appending. + */ + +/* + Operations Concept: + + Files (log name "foo"): + foo.gz -- gzip file with the complete log + foo.add -- last message to append or last data to compress + foo.dict -- dictionary of the last 32K of data for next compression + foo.temp -- temporary dictionary file for compression after this one + foo.lock -- lock file for reading and writing the other files + foo.repairs -- log file for log file recovery operations (not compressed) + + gzip file structure: + - fixed-length (no file name) header with extra field (see below) + - compressed data ending initially with empty stored block + - uncompressed data filling out originally empty stored block and + subsequent stored blocks as needed (16K max each) + - gzip trailer + - no junk at end (no other gzip streams) + + When appending data, the information in the first three items above plus the + foo.add file are sufficient to recover an interrupted append operation. The + extra field has the necessary information to restore the start of the last + stored block and determine where to append the data in the foo.add file, as + well as the crc and length of the gzip data before the append operation. + + The foo.add file is created before the gzip file is marked for append, and + deleted after the gzip file is marked as complete. So if the append + operation is interrupted, the data to add will still be there. If due to + some external force, the foo.add file gets deleted between when the append + operation was interrupted and when recovery is attempted, the gzip file will + still be restored, but without the appended data. + + When compressing data, the information in the first two items above plus the + foo.add file are sufficient to recover an interrupted compress operation. + The extra field has the necessary information to find the end of the + compressed data, and contains both the crc and length of just the compressed + data and of the complete set of data including the contents of the foo.add + file. + + Again, the foo.add file is maintained during the compress operation in case + of an interruption. If in the unlikely event the foo.add file with the data + to be compressed is missing due to some external force, a gzip file with + just the previous compressed data will be reconstructed. In this case, all + of the data that was to be compressed is lost (approximately one megabyte). + This will not occur if all that happened was an interruption of the compress + operation. + + The third state that is marked is the replacement of the old dictionary with + the new dictionary after a compress operation. Once compression is + complete, the gzip file is marked as being in the replace state. This + completes the gzip file, so an interrupt after being so marked does not + result in recompression. Then the dictionary file is replaced, and the gzip + file is marked as completed. This state prevents the possibility of + restarting compression with the wrong dictionary file. + + All three operations are wrapped by a lock/unlock procedure. In order to + gain exclusive access to the log files, first a foo.lock file must be + exclusively created. When all operations are complete, the lock is + released by deleting the foo.lock file. If when attempting to create the + lock file, it already exists and the modify time of the lock file is more + than five minutes old (set by the PATIENCE define below), then the old + lock file is considered stale and deleted, and the exclusive creation of + the lock file is retried. To assure that there are no false assessments + of the staleness of the lock file, the operations periodically touch the + lock file to update the modified date. + + Following is the definition of the extra field with all of the information + required to enable the above append and compress operations and their + recovery if interrupted. Multi-byte values are stored little endian + (consistent with the gzip format). File pointers are eight bytes long. + The crc's and lengths for the gzip trailer are four bytes long. (Note that + the length at the end of a gzip file is used for error checking only, and + for large files is actually the length modulo 2^32.) The stored block + length is two bytes long. The gzip extra field two-byte identification is + "ap" for append. It is assumed that writing the extra field to the file is + an "atomic" operation. That is, either all of the extra field is written + to the file, or none of it is, if the operation is interrupted right at the + point of updating the extra field. This is a reasonable assumption, since + the extra field is within the first 52 bytes of the file, which is smaller + than any expected block size for a mass storage device (usually 512 bytes or + larger). + + Extra field (35 bytes): + - Pointer to first stored block length -- this points to the two-byte length + of the first stored block, which is followed by the two-byte, one's + complement of that length. The stored block length is preceded by the + three-bit header of the stored block, which is the actual start of the + stored block in the deflate format. See the bit offset field below. + - Pointer to the last stored block length. This is the same as above, but + for the last stored block of the uncompressed data in the gzip file. + Initially this is the same as the first stored block length pointer. + When the stored block gets to 16K (see the MAX_STORE define), then a new + stored block as added, at which point the last stored block length pointer + is different from the first stored block length pointer. When they are + different, the first bit of the last stored block header is eight bits, or + one byte back from the block length. + - Compressed data crc and length. This is the crc and length of the data + that is in the compressed portion of the deflate stream. These are used + only in the event that the foo.add file containing the data to compress is + lost after a compress operation is interrupted. + - Total data crc and length. This is the crc and length of all of the data + stored in the gzip file, compressed and uncompressed. It is used to + reconstruct the gzip trailer when compressing, as well as when recovering + interrupted operations. + - Final stored block length. This is used to quickly find where to append, + and allows the restoration of the original final stored block state when + an append operation is interrupted. + - First stored block start as the number of bits back from the final stored + block first length byte. This value is in the range of 3..10, and is + stored as the low three bits of the final byte of the extra field after + subtracting three (0..7). This allows the last-block bit of the stored + block header to be updated when a new stored block is added, for the case + when the first stored block and the last stored block are the same. (When + they are different, the numbers of bits back is known to be eight.) This + also allows for new compressed data to be appended to the old compressed + data in the compress operation, overwriting the previous first stored + block, or for the compressed data to be terminated and a valid gzip file + reconstructed on the off chance that a compression operation was + interrupted and the data to compress in the foo.add file was deleted. + - The operation in process. This is the next two bits in the last byte (the + bits under the mask 0x18). The are interpreted as 0: nothing in process, + 1: append in process, 2: compress in process, 3: replace in process. + - The top three bits of the last byte in the extra field are reserved and + are currently set to zero. + + Main procedure: + - Exclusively create the foo.lock file using the O_CREAT and O_EXCL modes of + the system open() call. If the modify time of an existing lock file is + more than PATIENCE seconds old, then the lock file is deleted and the + exclusive create is retried. + - Load the extra field from the foo.gz file, and see if an operation was in + progress but not completed. If so, apply the recovery procedure below. + - Perform the append procedure with the provided data. + - If the uncompressed data in the foo.gz file is 1MB or more, apply the + compress procedure. + - Delete the foo.lock file. + + Append procedure: + - Put what to append in the foo.add file so that the operation can be + restarted if this procedure is interrupted. + - Mark the foo.gz extra field with the append operation in progress. + + Restore the original last-block bit and stored block length of the last + stored block from the information in the extra field, in case a previous + append operation was interrupted. + - Append the provided data to the last stored block, creating new stored + blocks as needed and updating the stored blocks last-block bits and + lengths. + - Update the crc and length with the new data, and write the gzip trailer. + - Write over the extra field (with a single write operation) with the new + pointers, lengths, and crc's, and mark the gzip file as not in process. + Though there is still a foo.add file, it will be ignored since nothing + is in process. If a foo.add file is leftover from a previously + completed operation, it is truncated when writing new data to it. + - Delete the foo.add file. + + Compress and replace procedures: + - Read all of the uncompressed data in the stored blocks in foo.gz and write + it to foo.add. Also write foo.temp with the last 32K of that data to + provide a dictionary for the next invocation of this procedure. + - Rewrite the extra field marking foo.gz with a compression in process. + * If there is no data provided to compress (due to a missing foo.add file + when recovering), reconstruct and truncate the foo.gz file to contain + only the previous compressed data and proceed to the step after the next + one. Otherwise ... + - Compress the data with the dictionary in foo.dict, and write to the + foo.gz file starting at the bit immediately following the last previously + compressed block. If there is no foo.dict, proceed anyway with the + compression at slightly reduced efficiency. (For the foo.dict file to be + missing requires some external failure beyond simply the interruption of + a compress operation.) During this process, the foo.lock file is + periodically touched to assure that that file is not considered stale by + another process before we're done. The deflation is terminated with a + non-last empty static block (10 bits long), that is then located and + written over by a last-bit-set empty stored block. + - Append the crc and length of the data in the gzip file (previously + calculated during the append operations). + - Write over the extra field with the updated stored block offsets, bits + back, crc's, and lengths, and mark foo.gz as in process for a replacement + of the dictionary. + @ Delete the foo.add file. + - Replace foo.dict with foo.temp. + - Write over the extra field, marking foo.gz as complete. + + Recovery procedure: + - If not a replace recovery, read in the foo.add file, and provide that data + to the appropriate recovery below. If there is no foo.add file, provide + a zero data length to the recovery. In that case, the append recovery + restores the foo.gz to the previous compressed + uncompressed data state. + For the the compress recovery, a missing foo.add file results in foo.gz + being restored to the previous compressed-only data state. + - Append recovery: + - Pick up append at + step above + - Compress recovery: + - Pick up compress at * step above + - Replace recovery: + - Pick up compress at @ step above + - Log the repair with a date stamp in foo.repairs + */ + +#include +#include /* rename, fopen, fprintf, fclose */ +#include /* malloc, free */ +#include /* strlen, strrchr, strcpy, strncpy, strcmp */ +#include /* open */ +#include /* lseek, read, write, close, unlink, sleep, */ + /* ftruncate, fsync */ +#include /* errno */ +#include /* time, ctime */ +#include /* stat */ +#include /* utimes */ +#include "zlib.h" /* crc32 */ + +#include "gzlog.h" /* header for external access */ + +#define local static +typedef unsigned int uint; +typedef unsigned long ulong; + +/* Macro for debugging to deterministically force recovery operations */ +#ifdef GZLOG_DEBUG + #include /* longjmp */ + jmp_buf gzlog_jump; /* where to go back to */ + int gzlog_bail = 0; /* which point to bail at (1..8) */ + int gzlog_count = -1; /* number of times through to wait */ +# define BAIL(n) do { if (n == gzlog_bail && gzlog_count-- == 0) \ + longjmp(gzlog_jump, gzlog_bail); } while (0) +#else +# define BAIL(n) +#endif + +/* how old the lock file can be in seconds before considering it stale */ +#define PATIENCE 300 + +/* maximum stored block size in Kbytes -- must be in 1..63 */ +#define MAX_STORE 16 + +/* number of stored Kbytes to trigger compression (must be >= 32 to allow + dictionary construction, and <= 204 * MAX_STORE, in order for >> 10 to + discard the stored block headers contribution of five bytes each) */ +#define TRIGGER 1024 + +/* size of a deflate dictionary (this cannot be changed) */ +#define DICT 32768U + +/* values for the operation (2 bits) */ +#define NO_OP 0 +#define APPEND_OP 1 +#define COMPRESS_OP 2 +#define REPLACE_OP 3 + +/* macros to extract little-endian integers from an unsigned byte buffer */ +#define PULL2(p) ((p)[0]+((uint)((p)[1])<<8)) +#define PULL4(p) (PULL2(p)+((ulong)PULL2(p+2)<<16)) +#define PULL8(p) (PULL4(p)+((off_t)PULL4(p+4)<<32)) + +/* macros to store integers into a byte buffer in little-endian order */ +#define PUT2(p,a) do {(p)[0]=a;(p)[1]=(a)>>8;} while(0) +#define PUT4(p,a) do {PUT2(p,a);PUT2(p+2,a>>16);} while(0) +#define PUT8(p,a) do {PUT4(p,a);PUT4(p+4,a>>32);} while(0) + +/* internal structure for log information */ +#define LOGID "\106\035\172" /* should be three non-zero characters */ +struct log { + char id[4]; /* contains LOGID to detect inadvertent overwrites */ + int fd; /* file descriptor for .gz file, opened read/write */ + char *path; /* allocated path, e.g. "/var/log/foo" or "foo" */ + char *end; /* end of path, for appending suffices such as ".gz" */ + off_t first; /* offset of first stored block first length byte */ + int back; /* location of first block id in bits back from first */ + uint stored; /* bytes currently in last stored block */ + off_t last; /* offset of last stored block first length byte */ + ulong ccrc; /* crc of compressed data */ + ulong clen; /* length (modulo 2^32) of compressed data */ + ulong tcrc; /* crc of total data */ + ulong tlen; /* length (modulo 2^32) of total data */ + time_t lock; /* last modify time of our lock file */ +}; + +/* gzip header for gzlog */ +local unsigned char log_gzhead[] = { + 0x1f, 0x8b, /* magic gzip id */ + 8, /* compression method is deflate */ + 4, /* there is an extra field (no file name) */ + 0, 0, 0, 0, /* no modification time provided */ + 0, 0xff, /* no extra flags, no OS specified */ + 39, 0, 'a', 'p', 35, 0 /* extra field with "ap" subfield */ + /* 35 is EXTRA, 39 is EXTRA + 4 */ +}; + +#define HEAD sizeof(log_gzhead) /* should be 16 */ + +/* initial gzip extra field content (52 == HEAD + EXTRA + 1) */ +local unsigned char log_gzext[] = { + 52, 0, 0, 0, 0, 0, 0, 0, /* offset of first stored block length */ + 52, 0, 0, 0, 0, 0, 0, 0, /* offset of last stored block length */ + 0, 0, 0, 0, 0, 0, 0, 0, /* compressed data crc and length */ + 0, 0, 0, 0, 0, 0, 0, 0, /* total data crc and length */ + 0, 0, /* final stored block data length */ + 5 /* op is NO_OP, last bit 8 bits back */ +}; + +#define EXTRA sizeof(log_gzext) /* should be 35 */ + +/* initial gzip data and trailer */ +local unsigned char log_gzbody[] = { + 1, 0, 0, 0xff, 0xff, /* empty stored block (last) */ + 0, 0, 0, 0, /* crc */ + 0, 0, 0, 0 /* uncompressed length */ +}; + +#define BODY sizeof(log_gzbody) + +/* Exclusively create foo.lock in order to negotiate exclusive access to the + foo.* files. If the modify time of an existing lock file is greater than + PATIENCE seconds in the past, then consider the lock file to have been + abandoned, delete it, and try the exclusive create again. Save the lock + file modify time for verification of ownership. Return 0 on success, or -1 + on failure, usually due to an access restriction or invalid path. Note that + if stat() or unlink() fails, it may be due to another process noticing the + abandoned lock file a smidge sooner and deleting it, so those are not + flagged as an error. */ +local int log_lock(struct log *log) +{ + int fd; + struct stat st; + + strcpy(log->end, ".lock"); + while ((fd = open(log->path, O_CREAT | O_EXCL, 0644)) < 0) { + if (errno != EEXIST) + return -1; + if (stat(log->path, &st) == 0 && time(NULL) - st.st_mtime > PATIENCE) { + unlink(log->path); + continue; + } + sleep(2); /* relinquish the CPU for two seconds while waiting */ + } + close(fd); + if (stat(log->path, &st) == 0) + log->lock = st.st_mtime; + return 0; +} + +/* Update the modify time of the lock file to now, in order to prevent another + task from thinking that the lock is stale. Save the lock file modify time + for verification of ownership. */ +local void log_touch(struct log *log) +{ + struct stat st; + + strcpy(log->end, ".lock"); + utimes(log->path, NULL); + if (stat(log->path, &st) == 0) + log->lock = st.st_mtime; +} + +/* Check the log file modify time against what is expected. Return true if + this is not our lock. If it is our lock, touch it to keep it. */ +local int log_check(struct log *log) +{ + struct stat st; + + strcpy(log->end, ".lock"); + if (stat(log->path, &st) || st.st_mtime != log->lock) + return 1; + log_touch(log); + return 0; +} + +/* Unlock a previously acquired lock, but only if it's ours. */ +local void log_unlock(struct log *log) +{ + if (log_check(log)) + return; + strcpy(log->end, ".lock"); + unlink(log->path); + log->lock = 0; +} + +/* Check the gzip header and read in the extra field, filling in the values in + the log structure. Return op on success or -1 if the gzip header was not as + expected. op is the current operation in progress last written to the extra + field. This assumes that the gzip file has already been opened, with the + file descriptor log->fd. */ +local int log_head(struct log *log) +{ + int op; + unsigned char buf[HEAD + EXTRA]; + + if (lseek(log->fd, 0, SEEK_SET) < 0 || + read(log->fd, buf, HEAD + EXTRA) != HEAD + EXTRA || + memcmp(buf, log_gzhead, HEAD)) { + return -1; + } + log->first = PULL8(buf + HEAD); + log->last = PULL8(buf + HEAD + 8); + log->ccrc = PULL4(buf + HEAD + 16); + log->clen = PULL4(buf + HEAD + 20); + log->tcrc = PULL4(buf + HEAD + 24); + log->tlen = PULL4(buf + HEAD + 28); + log->stored = PULL2(buf + HEAD + 32); + log->back = 3 + (buf[HEAD + 34] & 7); + op = (buf[HEAD + 34] >> 3) & 3; + return op; +} + +/* Write over the extra field contents, marking the operation as op. Use fsync + to assure that the device is written to, and in the requested order. This + operation, and only this operation, is assumed to be atomic in order to + assure that the log is recoverable in the event of an interruption at any + point in the process. Return -1 if the write to foo.gz failed. */ +local int log_mark(struct log *log, int op) +{ + int ret; + unsigned char ext[EXTRA]; + + PUT8(ext, log->first); + PUT8(ext + 8, log->last); + PUT4(ext + 16, log->ccrc); + PUT4(ext + 20, log->clen); + PUT4(ext + 24, log->tcrc); + PUT4(ext + 28, log->tlen); + PUT2(ext + 32, log->stored); + ext[34] = log->back - 3 + (op << 3); + fsync(log->fd); + ret = lseek(log->fd, HEAD, SEEK_SET) < 0 || + write(log->fd, ext, EXTRA) != EXTRA ? -1 : 0; + fsync(log->fd); + return ret; +} + +/* Rewrite the last block header bits and subsequent zero bits to get to a byte + boundary, setting the last block bit if last is true, and then write the + remainder of the stored block header (length and one's complement). Leave + the file pointer after the end of the last stored block data. Return -1 if + there is a read or write failure on the foo.gz file */ +local int log_last(struct log *log, int last) +{ + int back, len, mask; + unsigned char buf[6]; + + /* determine the locations of the bytes and bits to modify */ + back = log->last == log->first ? log->back : 8; + len = back > 8 ? 2 : 1; /* bytes back from log->last */ + mask = 0x80 >> ((back - 1) & 7); /* mask for block last-bit */ + + /* get the byte to modify (one or two back) into buf[0] -- don't need to + read the byte if the last-bit is eight bits back, since in that case + the entire byte will be modified */ + buf[0] = 0; + if (back != 8 && (lseek(log->fd, log->last - len, SEEK_SET) < 0 || + read(log->fd, buf, 1) != 1)) + return -1; + + /* change the last-bit of the last stored block as requested -- note + that all bits above the last-bit are set to zero, per the type bits + of a stored block being 00 and per the convention that the bits to + bring the stream to a byte boundary are also zeros */ + buf[1] = 0; + buf[2 - len] = (*buf & (mask - 1)) + (last ? mask : 0); + + /* write the modified stored block header and lengths, move the file + pointer to after the last stored block data */ + PUT2(buf + 2, log->stored); + PUT2(buf + 4, log->stored ^ 0xffff); + return lseek(log->fd, log->last - len, SEEK_SET) < 0 || + write(log->fd, buf + 2 - len, len + 4) != len + 4 || + lseek(log->fd, log->stored, SEEK_CUR) < 0 ? -1 : 0; +} + +/* Append len bytes from data to the locked and open log file. len may be zero + if recovering and no .add file was found. In that case, the previous state + of the foo.gz file is restored. The data is appended uncompressed in + deflate stored blocks. Return -1 if there was an error reading or writing + the foo.gz file. */ +local int log_append(struct log *log, unsigned char *data, size_t len) +{ + uint put; + off_t end; + unsigned char buf[8]; + + /* set the last block last-bit and length, in case recovering an + interrupted append, then position the file pointer to append to the + block */ + if (log_last(log, 1)) + return -1; + + /* append, adding stored blocks and updating the offset of the last stored + block as needed, and update the total crc and length */ + while (len) { + /* append as much as we can to the last block */ + put = (MAX_STORE << 10) - log->stored; + if (put > len) + put = (uint)len; + if (put) { + if (write(log->fd, data, put) != put) + return -1; + BAIL(1); + log->tcrc = crc32(log->tcrc, data, put); + log->tlen += put; + log->stored += put; + data += put; + len -= put; + } + + /* if we need to, add a new empty stored block */ + if (len) { + /* mark current block as not last */ + if (log_last(log, 0)) + return -1; + + /* point to new, empty stored block */ + log->last += 4 + log->stored + 1; + log->stored = 0; + } + + /* mark last block as last, update its length */ + if (log_last(log, 1)) + return -1; + BAIL(2); + } + + /* write the new crc and length trailer, and truncate just in case (could + be recovering from partial append with a missing foo.add file) */ + PUT4(buf, log->tcrc); + PUT4(buf + 4, log->tlen); + if (write(log->fd, buf, 8) != 8 || + (end = lseek(log->fd, 0, SEEK_CUR)) < 0 || ftruncate(log->fd, end)) + return -1; + + /* write the extra field, marking the log file as done, delete .add file */ + if (log_mark(log, NO_OP)) + return -1; + strcpy(log->end, ".add"); + unlink(log->path); /* ignore error, since may not exist */ + return 0; +} + +/* Replace the foo.dict file with the foo.temp file. Also delete the foo.add + file, since the compress operation may have been interrupted before that was + done. Returns 1 if memory could not be allocated, or -1 if reading or + writing foo.gz fails, or if the rename fails for some reason other than + foo.temp not existing. foo.temp not existing is a permitted error, since + the replace operation may have been interrupted after the rename is done, + but before foo.gz is marked as complete. */ +local int log_replace(struct log *log) +{ + int ret; + char *dest; + + /* delete foo.add file */ + strcpy(log->end, ".add"); + unlink(log->path); /* ignore error, since may not exist */ + BAIL(3); + + /* rename foo.name to foo.dict, replacing foo.dict if it exists */ + strcpy(log->end, ".dict"); + dest = malloc(strlen(log->path) + 1); + if (dest == NULL) + return -2; + strcpy(dest, log->path); + strcpy(log->end, ".temp"); + ret = rename(log->path, dest); + free(dest); + if (ret && errno != ENOENT) + return -1; + BAIL(4); + + /* mark the foo.gz file as done */ + return log_mark(log, NO_OP); +} + +/* Compress the len bytes at data and append the compressed data to the + foo.gz deflate data immediately after the previous compressed data. This + overwrites the previous uncompressed data, which was stored in foo.add + and is the data provided in data[0..len-1]. If this operation is + interrupted, it picks up at the start of this routine, with the foo.add + file read in again. If there is no data to compress (len == 0), then we + simply terminate the foo.gz file after the previously compressed data, + appending a final empty stored block and the gzip trailer. Return -1 if + reading or writing the log.gz file failed, or -2 if there was a memory + allocation failure. */ +local int log_compress(struct log *log, unsigned char *data, size_t len) +{ + int fd; + uint got, max; + ssize_t dict; + off_t end; + z_stream strm; + unsigned char buf[DICT]; + + /* compress and append compressed data */ + if (len) { + /* set up for deflate, allocating memory */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + if (deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 8, + Z_DEFAULT_STRATEGY) != Z_OK) + return -2; + + /* read in dictionary (last 32K of data that was compressed) */ + strcpy(log->end, ".dict"); + fd = open(log->path, O_RDONLY, 0); + if (fd >= 0) { + dict = read(fd, buf, DICT); + close(fd); + if (dict < 0) { + deflateEnd(&strm); + return -1; + } + if (dict) + deflateSetDictionary(&strm, buf, (uint)dict); + } + log_touch(log); + + /* prime deflate with last bits of previous block, position write + pointer to write those bits and overwrite what follows */ + if (lseek(log->fd, log->first - (log->back > 8 ? 2 : 1), + SEEK_SET) < 0 || + read(log->fd, buf, 1) != 1 || lseek(log->fd, -1, SEEK_CUR) < 0) { + deflateEnd(&strm); + return -1; + } + deflatePrime(&strm, (8 - log->back) & 7, *buf); + + /* compress, finishing with a partial non-last empty static block */ + strm.next_in = data; + max = (((uint)0 - 1) >> 1) + 1; /* in case int smaller than size_t */ + do { + strm.avail_in = len > max ? max : (uint)len; + len -= strm.avail_in; + do { + strm.avail_out = DICT; + strm.next_out = buf; + deflate(&strm, len ? Z_NO_FLUSH : Z_PARTIAL_FLUSH); + got = DICT - strm.avail_out; + if (got && write(log->fd, buf, got) != got) { + deflateEnd(&strm); + return -1; + } + log_touch(log); + } while (strm.avail_out == 0); + } while (len); + deflateEnd(&strm); + BAIL(5); + + /* find start of empty static block -- scanning backwards the first one + bit is the second bit of the block, if the last byte is zero, then + we know the byte before that has a one in the top bit, since an + empty static block is ten bits long */ + if ((log->first = lseek(log->fd, -1, SEEK_CUR)) < 0 || + read(log->fd, buf, 1) != 1) + return -1; + log->first++; + if (*buf) { + log->back = 1; + while ((*buf & ((uint)1 << (8 - log->back++))) == 0) + ; /* guaranteed to terminate, since *buf != 0 */ + } + else + log->back = 10; + + /* update compressed crc and length */ + log->ccrc = log->tcrc; + log->clen = log->tlen; + } + else { + /* no data to compress -- fix up existing gzip stream */ + log->tcrc = log->ccrc; + log->tlen = log->clen; + } + + /* complete and truncate gzip stream */ + log->last = log->first; + log->stored = 0; + PUT4(buf, log->tcrc); + PUT4(buf + 4, log->tlen); + if (log_last(log, 1) || write(log->fd, buf, 8) != 8 || + (end = lseek(log->fd, 0, SEEK_CUR)) < 0 || ftruncate(log->fd, end)) + return -1; + BAIL(6); + + /* mark as being in the replace operation */ + if (log_mark(log, REPLACE_OP)) + return -1; + + /* execute the replace operation and mark the file as done */ + return log_replace(log); +} + +/* log a repair record to the .repairs file */ +local void log_log(struct log *log, int op, char *record) +{ + time_t now; + FILE *rec; + + now = time(NULL); + strcpy(log->end, ".repairs"); + rec = fopen(log->path, "a"); + if (rec == NULL) + return; + fprintf(rec, "%.24s %s recovery: %s\n", ctime(&now), op == APPEND_OP ? + "append" : (op == COMPRESS_OP ? "compress" : "replace"), record); + fclose(rec); + return; +} + +/* Recover the interrupted operation op. First read foo.add for recovering an + append or compress operation. Return -1 if there was an error reading or + writing foo.gz or reading an existing foo.add, or -2 if there was a memory + allocation failure. */ +local int log_recover(struct log *log, int op) +{ + int fd, ret = 0; + unsigned char *data = NULL; + size_t len = 0; + struct stat st; + + /* log recovery */ + log_log(log, op, "start"); + + /* load foo.add file if expected and present */ + if (op == APPEND_OP || op == COMPRESS_OP) { + strcpy(log->end, ".add"); + if (stat(log->path, &st) == 0 && st.st_size) { + len = (size_t)(st.st_size); + if ((off_t)len != st.st_size || + (data = malloc(st.st_size)) == NULL) { + log_log(log, op, "allocation failure"); + return -2; + } + if ((fd = open(log->path, O_RDONLY, 0)) < 0) { + log_log(log, op, ".add file read failure"); + return -1; + } + ret = (size_t)read(fd, data, len) != len; + close(fd); + if (ret) { + log_log(log, op, ".add file read failure"); + return -1; + } + log_log(log, op, "loaded .add file"); + } + else + log_log(log, op, "missing .add file!"); + } + + /* recover the interrupted operation */ + switch (op) { + case APPEND_OP: + ret = log_append(log, data, len); + break; + case COMPRESS_OP: + ret = log_compress(log, data, len); + break; + case REPLACE_OP: + ret = log_replace(log); + } + + /* log status */ + log_log(log, op, ret ? "failure" : "complete"); + + /* clean up */ + if (data != NULL) + free(data); + return ret; +} + +/* Close the foo.gz file (if open) and release the lock. */ +local void log_close(struct log *log) +{ + if (log->fd >= 0) + close(log->fd); + log->fd = -1; + log_unlock(log); +} + +/* Open foo.gz, verify the header, and load the extra field contents, after + first creating the foo.lock file to gain exclusive access to the foo.* + files. If foo.gz does not exist or is empty, then write the initial header, + extra, and body content of an empty foo.gz log file. If there is an error + creating the lock file due to access restrictions, or an error reading or + writing the foo.gz file, or if the foo.gz file is not a proper log file for + this object (e.g. not a gzip file or does not contain the expected extra + field), then return true. If there is an error, the lock is released. + Otherwise, the lock is left in place. */ +local int log_open(struct log *log) +{ + int op; + + /* release open file resource if left over -- can occur if lock lost + between gzlog_open() and gzlog_write() */ + if (log->fd >= 0) + close(log->fd); + log->fd = -1; + + /* negotiate exclusive access */ + if (log_lock(log) < 0) + return -1; + + /* open the log file, foo.gz */ + strcpy(log->end, ".gz"); + log->fd = open(log->path, O_RDWR | O_CREAT, 0644); + if (log->fd < 0) { + log_close(log); + return -1; + } + + /* if new, initialize foo.gz with an empty log, delete old dictionary */ + if (lseek(log->fd, 0, SEEK_END) == 0) { + if (write(log->fd, log_gzhead, HEAD) != HEAD || + write(log->fd, log_gzext, EXTRA) != EXTRA || + write(log->fd, log_gzbody, BODY) != BODY) { + log_close(log); + return -1; + } + strcpy(log->end, ".dict"); + unlink(log->path); + } + + /* verify log file and load extra field information */ + if ((op = log_head(log)) < 0) { + log_close(log); + return -1; + } + + /* check for interrupted process and if so, recover */ + if (op != NO_OP && log_recover(log, op)) { + log_close(log); + return -1; + } + + /* touch the lock file to prevent another process from grabbing it */ + log_touch(log); + return 0; +} + +/* See gzlog.h for the description of the external methods below */ +gzlog *gzlog_open(char *path) +{ + size_t n; + struct log *log; + + /* check arguments */ + if (path == NULL || *path == 0) + return NULL; + + /* allocate and initialize log structure */ + log = malloc(sizeof(struct log)); + if (log == NULL) + return NULL; + strcpy(log->id, LOGID); + log->fd = -1; + + /* save path and end of path for name construction */ + n = strlen(path); + log->path = malloc(n + 9); /* allow for ".repairs" */ + if (log->path == NULL) { + free(log); + return NULL; + } + strcpy(log->path, path); + log->end = log->path + n; + + /* gain exclusive access and verify log file -- may perform a + recovery operation if needed */ + if (log_open(log)) { + free(log->path); + free(log); + return NULL; + } + + /* return pointer to log structure */ + return log; +} + +/* gzlog_compress() return values: + 0: all good + -1: file i/o error (usually access issue) + -2: memory allocation failure + -3: invalid log pointer argument */ +int gzlog_compress(gzlog *logd) +{ + int fd, ret; + uint block; + size_t len, next; + unsigned char *data, buf[5]; + struct log *log = logd; + + /* check arguments */ + if (log == NULL || strcmp(log->id, LOGID)) + return -3; + + /* see if we lost the lock -- if so get it again and reload the extra + field information (it probably changed), recover last operation if + necessary */ + if (log_check(log) && log_open(log)) + return -1; + + /* create space for uncompressed data */ + len = ((size_t)(log->last - log->first) & ~(((size_t)1 << 10) - 1)) + + log->stored; + if ((data = malloc(len)) == NULL) + return -2; + + /* do statement here is just a cheap trick for error handling */ + do { + /* read in the uncompressed data */ + if (lseek(log->fd, log->first - 1, SEEK_SET) < 0) + break; + next = 0; + while (next < len) { + if (read(log->fd, buf, 5) != 5) + break; + block = PULL2(buf + 1); + if (next + block > len || + read(log->fd, (char *)data + next, block) != block) + break; + next += block; + } + if (lseek(log->fd, 0, SEEK_CUR) != log->last + 4 + log->stored) + break; + log_touch(log); + + /* write the uncompressed data to the .add file */ + strcpy(log->end, ".add"); + fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd < 0) + break; + ret = (size_t)write(fd, data, len) != len; + if (ret | close(fd)) + break; + log_touch(log); + + /* write the dictionary for the next compress to the .temp file */ + strcpy(log->end, ".temp"); + fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd < 0) + break; + next = DICT > len ? len : DICT; + ret = (size_t)write(fd, (char *)data + len - next, next) != next; + if (ret | close(fd)) + break; + log_touch(log); + + /* roll back to compressed data, mark the compress in progress */ + log->last = log->first; + log->stored = 0; + if (log_mark(log, COMPRESS_OP)) + break; + BAIL(7); + + /* compress and append the data (clears mark) */ + ret = log_compress(log, data, len); + free(data); + return ret; + } while (0); + + /* broke out of do above on i/o error */ + free(data); + return -1; +} + +/* gzlog_write() return values: + 0: all good + -1: file i/o error (usually access issue) + -2: memory allocation failure + -3: invalid log pointer argument */ +int gzlog_write(gzlog *logd, void *data, size_t len) +{ + int fd, ret; + struct log *log = logd; + + /* check arguments */ + if (log == NULL || strcmp(log->id, LOGID)) + return -3; + if (data == NULL || len <= 0) + return 0; + + /* see if we lost the lock -- if so get it again and reload the extra + field information (it probably changed), recover last operation if + necessary */ + if (log_check(log) && log_open(log)) + return -1; + + /* create and write .add file */ + strcpy(log->end, ".add"); + fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd < 0) + return -1; + ret = (size_t)write(fd, data, len) != len; + if (ret | close(fd)) + return -1; + log_touch(log); + + /* mark log file with append in progress */ + if (log_mark(log, APPEND_OP)) + return -1; + BAIL(8); + + /* append data (clears mark) */ + if (log_append(log, data, len)) + return -1; + + /* check to see if it's time to compress -- if not, then done */ + if (((log->last - log->first) >> 10) + (log->stored >> 10) < TRIGGER) + return 0; + + /* time to compress */ + return gzlog_compress(log); +} + +/* gzlog_close() return values: + 0: ok + -3: invalid log pointer argument */ +int gzlog_close(gzlog *logd) +{ + struct log *log = logd; + + /* check arguments */ + if (log == NULL || strcmp(log->id, LOGID)) + return -3; + + /* close the log file and release the lock */ + log_close(log); + + /* free structure and return */ + if (log->path != NULL) + free(log->path); + strcpy(log->id, "bad"); + free(log); + return 0; +} diff --git a/dependencies/zlib-1.2.11/examples/gzlog.h b/dependencies/zlib-1.2.11/examples/gzlog.h new file mode 100644 index 0000000..86f0cec --- /dev/null +++ b/dependencies/zlib-1.2.11/examples/gzlog.h @@ -0,0 +1,91 @@ +/* gzlog.h + Copyright (C) 2004, 2008, 2012 Mark Adler, all rights reserved + version 2.2, 14 Aug 2012 + + This software is provided 'as-is', without any express or implied + warranty. In no event will the author be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Mark Adler madler@alumni.caltech.edu + */ + +/* Version History: + 1.0 26 Nov 2004 First version + 2.0 25 Apr 2008 Complete redesign for recovery of interrupted operations + Interface changed slightly in that now path is a prefix + Compression now occurs as needed during gzlog_write() + gzlog_write() now always leaves the log file as valid gzip + 2.1 8 Jul 2012 Fix argument checks in gzlog_compress() and gzlog_write() + 2.2 14 Aug 2012 Clean up signed comparisons + */ + +/* + The gzlog object allows writing short messages to a gzipped log file, + opening the log file locked for small bursts, and then closing it. The log + object works by appending stored (uncompressed) data to the gzip file until + 1 MB has been accumulated. At that time, the stored data is compressed, and + replaces the uncompressed data in the file. The log file is truncated to + its new size at that time. After each write operation, the log file is a + valid gzip file that can decompressed to recover what was written. + + The gzlog operations can be interupted at any point due to an application or + system crash, and the log file will be recovered the next time the log is + opened with gzlog_open(). + */ + +#ifndef GZLOG_H +#define GZLOG_H + +/* gzlog object type */ +typedef void gzlog; + +/* Open a gzlog object, creating the log file if it does not exist. Return + NULL on error. Note that gzlog_open() could take a while to complete if it + has to wait to verify that a lock is stale (possibly for five minutes), or + if there is significant contention with other instantiations of this object + when locking the resource. path is the prefix of the file names created by + this object. If path is "foo", then the log file will be "foo.gz", and + other auxiliary files will be created and destroyed during the process: + "foo.dict" for a compression dictionary, "foo.temp" for a temporary (next) + dictionary, "foo.add" for data being added or compressed, "foo.lock" for the + lock file, and "foo.repairs" to log recovery operations performed due to + interrupted gzlog operations. A gzlog_open() followed by a gzlog_close() + will recover a previously interrupted operation, if any. */ +gzlog *gzlog_open(char *path); + +/* Write to a gzlog object. Return zero on success, -1 if there is a file i/o + error on any of the gzlog files (this should not happen if gzlog_open() + succeeded, unless the device has run out of space or leftover auxiliary + files have permissions or ownership that prevent their use), -2 if there is + a memory allocation failure, or -3 if the log argument is invalid (e.g. if + it was not created by gzlog_open()). This function will write data to the + file uncompressed, until 1 MB has been accumulated, at which time that data + will be compressed. The log file will be a valid gzip file upon successful + return. */ +int gzlog_write(gzlog *log, void *data, size_t len); + +/* Force compression of any uncompressed data in the log. This should be used + sparingly, if at all. The main application would be when a log file will + not be appended to again. If this is used to compress frequently while + appending, it will both significantly increase the execution time and + reduce the compression ratio. The return codes are the same as for + gzlog_write(). */ +int gzlog_compress(gzlog *log); + +/* Close a gzlog object. Return zero on success, -3 if the log argument is + invalid. The log object is freed, and so cannot be referenced again. */ +int gzlog_close(gzlog *log); + +#endif diff --git a/dependencies/zlib-1.2.11/examples/zlib_how.html b/dependencies/zlib-1.2.11/examples/zlib_how.html new file mode 100644 index 0000000..444ff1c --- /dev/null +++ b/dependencies/zlib-1.2.11/examples/zlib_how.html @@ -0,0 +1,545 @@ + + + + +zlib Usage Example + + + +

    zlib Usage Example

    +We often get questions about how the deflate() and inflate() functions should be used. +Users wonder when they should provide more input, when they should use more output, +what to do with a Z_BUF_ERROR, how to make sure the process terminates properly, and +so on. So for those who have read zlib.h (a few times), and +would like further edification, below is an annotated example in C of simple routines to compress and decompress +from an input file to an output file using deflate() and inflate() respectively. The +annotations are interspersed between lines of the code. So please read between the lines. +We hope this helps explain some of the intricacies of zlib. +

    +Without further adieu, here is the program zpipe.c: +

    
    +/* zpipe.c: example of proper use of zlib's inflate() and deflate()
    +   Not copyrighted -- provided to the public domain
    +   Version 1.4  11 December 2005  Mark Adler */
    +
    +/* Version history:
    +   1.0  30 Oct 2004  First version
    +   1.1   8 Nov 2004  Add void casting for unused return values
    +                     Use switch statement for inflate() return values
    +   1.2   9 Nov 2004  Add assertions to document zlib guarantees
    +   1.3   6 Apr 2005  Remove incorrect assertion in inf()
    +   1.4  11 Dec 2005  Add hack to avoid MSDOS end-of-line conversions
    +                     Avoid some compiler warnings for input and output buffers
    + */
    +
    +We now include the header files for the required definitions. From +stdio.h we use fopen(), fread(), fwrite(), +feof(), ferror(), and fclose() for file i/o, and +fputs() for error messages. From string.h we use +strcmp() for command line argument processing. +From assert.h we use the assert() macro. +From zlib.h +we use the basic compression functions deflateInit(), +deflate(), and deflateEnd(), and the basic decompression +functions inflateInit(), inflate(), and +inflateEnd(). +
    
    +#include <stdio.h>
    +#include <string.h>
    +#include <assert.h>
    +#include "zlib.h"
    +
    +This is an ugly hack required to avoid corruption of the input and output data on +Windows/MS-DOS systems. Without this, those systems would assume that the input and output +files are text, and try to convert the end-of-line characters from one standard to +another. That would corrupt binary data, and in particular would render the compressed data unusable. +This sets the input and output to binary which suppresses the end-of-line conversions. +SET_BINARY_MODE() will be used later on stdin and stdout, at the beginning of main(). +
    
    +#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
    +#  include <fcntl.h>
    +#  include <io.h>
    +#  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
    +#else
    +#  define SET_BINARY_MODE(file)
    +#endif
    +
    +CHUNK is simply the buffer size for feeding data to and pulling data +from the zlib routines. Larger buffer sizes would be more efficient, +especially for inflate(). If the memory is available, buffers sizes +on the order of 128K or 256K bytes should be used. +
    
    +#define CHUNK 16384
    +
    +The def() routine compresses data from an input file to an output file. The output data +will be in the zlib format, which is different from the gzip or zip +formats. The zlib format has a very small header of only two bytes to identify it as +a zlib stream and to provide decoding information, and a four-byte trailer with a fast +check value to verify the integrity of the uncompressed data after decoding. +
    
    +/* Compress from file source to file dest until EOF on source.
    +   def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
    +   allocated for processing, Z_STREAM_ERROR if an invalid compression
    +   level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
    +   version of the library linked do not match, or Z_ERRNO if there is
    +   an error reading or writing the files. */
    +int def(FILE *source, FILE *dest, int level)
    +{
    +
    +Here are the local variables for def(). ret will be used for zlib +return codes. flush will keep track of the current flushing state for deflate(), +which is either no flushing, or flush to completion after the end of the input file is reached. +have is the amount of data returned from deflate(). The strm structure +is used to pass information to and from the zlib routines, and to maintain the +deflate() state. in and out are the input and output buffers for +deflate(). +
    
    +    int ret, flush;
    +    unsigned have;
    +    z_stream strm;
    +    unsigned char in[CHUNK];
    +    unsigned char out[CHUNK];
    +
    +The first thing we do is to initialize the zlib state for compression using +deflateInit(). This must be done before the first use of deflate(). +The zalloc, zfree, and opaque fields in the strm +structure must be initialized before calling deflateInit(). Here they are +set to the zlib constant Z_NULL to request that zlib use +the default memory allocation routines. An application may also choose to provide +custom memory allocation routines here. deflateInit() will allocate on the +order of 256K bytes for the internal state. +(See zlib Technical Details.) +

    +deflateInit() is called with a pointer to the structure to be initialized and +the compression level, which is an integer in the range of -1 to 9. Lower compression +levels result in faster execution, but less compression. Higher levels result in +greater compression, but slower execution. The zlib constant Z_DEFAULT_COMPRESSION, +equal to -1, +provides a good compromise between compression and speed and is equivalent to level 6. +Level 0 actually does no compression at all, and in fact expands the data slightly to produce +the zlib format (it is not a byte-for-byte copy of the input). +More advanced applications of zlib +may use deflateInit2() here instead. Such an application may want to reduce how +much memory will be used, at some price in compression. Or it may need to request a +gzip header and trailer instead of a zlib header and trailer, or raw +encoding with no header or trailer at all. +

    +We must check the return value of deflateInit() against the zlib constant +Z_OK to make sure that it was able to +allocate memory for the internal state, and that the provided arguments were valid. +deflateInit() will also check that the version of zlib that the zlib.h +file came from matches the version of zlib actually linked with the program. This +is especially important for environments in which zlib is a shared library. +

    +Note that an application can initialize multiple, independent zlib streams, which can +operate in parallel. The state information maintained in the structure allows the zlib +routines to be reentrant. +

    
    +    /* allocate deflate state */
    +    strm.zalloc = Z_NULL;
    +    strm.zfree = Z_NULL;
    +    strm.opaque = Z_NULL;
    +    ret = deflateInit(&strm, level);
    +    if (ret != Z_OK)
    +        return ret;
    +
    +With the pleasantries out of the way, now we can get down to business. The outer do-loop +reads all of the input file and exits at the bottom of the loop once end-of-file is reached. +This loop contains the only call of deflate(). So we must make sure that all of the +input data has been processed and that all of the output data has been generated and consumed +before we fall out of the loop at the bottom. +
    
    +    /* compress until end of file */
    +    do {
    +
    +We start off by reading data from the input file. The number of bytes read is put directly +into avail_in, and a pointer to those bytes is put into next_in. We also +check to see if end-of-file on the input has been reached. If we are at the end of file, then flush is set to the +zlib constant Z_FINISH, which is later passed to deflate() to +indicate that this is the last chunk of input data to compress. We need to use feof() +to check for end-of-file as opposed to seeing if fewer than CHUNK bytes have been read. The +reason is that if the input file length is an exact multiple of CHUNK, we will miss +the fact that we got to the end-of-file, and not know to tell deflate() to finish +up the compressed stream. If we are not yet at the end of the input, then the zlib +constant Z_NO_FLUSH will be passed to deflate to indicate that we are still +in the middle of the uncompressed data. +

    +If there is an error in reading from the input file, the process is aborted with +deflateEnd() being called to free the allocated zlib state before returning +the error. We wouldn't want a memory leak, now would we? deflateEnd() can be called +at any time after the state has been initialized. Once that's done, deflateInit() (or +deflateInit2()) would have to be called to start a new compression process. There is +no point here in checking the deflateEnd() return code. The deallocation can't fail. +

    
    +        strm.avail_in = fread(in, 1, CHUNK, source);
    +        if (ferror(source)) {
    +            (void)deflateEnd(&strm);
    +            return Z_ERRNO;
    +        }
    +        flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
    +        strm.next_in = in;
    +
    +The inner do-loop passes our chunk of input data to deflate(), and then +keeps calling deflate() until it is done producing output. Once there is no more +new output, deflate() is guaranteed to have consumed all of the input, i.e., +avail_in will be zero. +
    
    +        /* run deflate() on input until output buffer not full, finish
    +           compression if all of source has been read in */
    +        do {
    +
    +Output space is provided to deflate() by setting avail_out to the number +of available output bytes and next_out to a pointer to that space. +
    
    +            strm.avail_out = CHUNK;
    +            strm.next_out = out;
    +
    +Now we call the compression engine itself, deflate(). It takes as many of the +avail_in bytes at next_in as it can process, and writes as many as +avail_out bytes to next_out. Those counters and pointers are then +updated past the input data consumed and the output data written. It is the amount of +output space available that may limit how much input is consumed. +Hence the inner loop to make sure that +all of the input is consumed by providing more output space each time. Since avail_in +and next_in are updated by deflate(), we don't have to mess with those +between deflate() calls until it's all used up. +

    +The parameters to deflate() are a pointer to the strm structure containing +the input and output information and the internal compression engine state, and a parameter +indicating whether and how to flush data to the output. Normally deflate will consume +several K bytes of input data before producing any output (except for the header), in order +to accumulate statistics on the data for optimum compression. It will then put out a burst of +compressed data, and proceed to consume more input before the next burst. Eventually, +deflate() +must be told to terminate the stream, complete the compression with provided input data, and +write out the trailer check value. deflate() will continue to compress normally as long +as the flush parameter is Z_NO_FLUSH. Once the Z_FINISH parameter is provided, +deflate() will begin to complete the compressed output stream. However depending on how +much output space is provided, deflate() may have to be called several times until it +has provided the complete compressed stream, even after it has consumed all of the input. The flush +parameter must continue to be Z_FINISH for those subsequent calls. +

    +There are other values of the flush parameter that are used in more advanced applications. You can +force deflate() to produce a burst of output that encodes all of the input data provided +so far, even if it wouldn't have otherwise, for example to control data latency on a link with +compressed data. You can also ask that deflate() do that as well as erase any history up to +that point so that what follows can be decompressed independently, for example for random access +applications. Both requests will degrade compression by an amount depending on how often such +requests are made. +

    +deflate() has a return value that can indicate errors, yet we do not check it here. Why +not? Well, it turns out that deflate() can do no wrong here. Let's go through +deflate()'s return values and dispense with them one by one. The possible values are +Z_OK, Z_STREAM_END, Z_STREAM_ERROR, or Z_BUF_ERROR. Z_OK +is, well, ok. Z_STREAM_END is also ok and will be returned for the last call of +deflate(). This is already guaranteed by calling deflate() with Z_FINISH +until it has no more output. Z_STREAM_ERROR is only possible if the stream is not +initialized properly, but we did initialize it properly. There is no harm in checking for +Z_STREAM_ERROR here, for example to check for the possibility that some +other part of the application inadvertently clobbered the memory containing the zlib state. +Z_BUF_ERROR will be explained further below, but +suffice it to say that this is simply an indication that deflate() could not consume +more input or produce more output. deflate() can be called again with more output space +or more available input, which it will be in this code. +

    
    +            ret = deflate(&strm, flush);    /* no bad return value */
    +            assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
    +
    +Now we compute how much output deflate() provided on the last call, which is the +difference between how much space was provided before the call, and how much output space +is still available after the call. Then that data, if any, is written to the output file. +We can then reuse the output buffer for the next call of deflate(). Again if there +is a file i/o error, we call deflateEnd() before returning to avoid a memory leak. +
    
    +            have = CHUNK - strm.avail_out;
    +            if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
    +                (void)deflateEnd(&strm);
    +                return Z_ERRNO;
    +            }
    +
    +The inner do-loop is repeated until the last deflate() call fails to fill the +provided output buffer. Then we know that deflate() has done as much as it can with +the provided input, and that all of that input has been consumed. We can then fall out of this +loop and reuse the input buffer. +

    +The way we tell that deflate() has no more output is by seeing that it did not fill +the output buffer, leaving avail_out greater than zero. However suppose that +deflate() has no more output, but just so happened to exactly fill the output buffer! +avail_out is zero, and we can't tell that deflate() has done all it can. +As far as we know, deflate() +has more output for us. So we call it again. But now deflate() produces no output +at all, and avail_out remains unchanged as CHUNK. That deflate() call +wasn't able to do anything, either consume input or produce output, and so it returns +Z_BUF_ERROR. (See, I told you I'd cover this later.) However this is not a problem at +all. Now we finally have the desired indication that deflate() is really done, +and so we drop out of the inner loop to provide more input to deflate(). +

    +With flush set to Z_FINISH, this final set of deflate() calls will +complete the output stream. Once that is done, subsequent calls of deflate() would return +Z_STREAM_ERROR if the flush parameter is not Z_FINISH, and do no more processing +until the state is reinitialized. +

    +Some applications of zlib have two loops that call deflate() +instead of the single inner loop we have here. The first loop would call +without flushing and feed all of the data to deflate(). The second loop would call +deflate() with no more +data and the Z_FINISH parameter to complete the process. As you can see from this +example, that can be avoided by simply keeping track of the current flush state. +

    
    +        } while (strm.avail_out == 0);
    +        assert(strm.avail_in == 0);     /* all input will be used */
    +
    +Now we check to see if we have already processed all of the input file. That information was +saved in the flush variable, so we see if that was set to Z_FINISH. If so, +then we're done and we fall out of the outer loop. We're guaranteed to get Z_STREAM_END +from the last deflate() call, since we ran it until the last chunk of input was +consumed and all of the output was generated. +
    
    +        /* done when last data in file processed */
    +    } while (flush != Z_FINISH);
    +    assert(ret == Z_STREAM_END);        /* stream will be complete */
    +
    +The process is complete, but we still need to deallocate the state to avoid a memory leak +(or rather more like a memory hemorrhage if you didn't do this). Then +finally we can return with a happy return value. +
    
    +    /* clean up and return */
    +    (void)deflateEnd(&strm);
    +    return Z_OK;
    +}
    +
    +Now we do the same thing for decompression in the inf() routine. inf() +decompresses what is hopefully a valid zlib stream from the input file and writes the +uncompressed data to the output file. Much of the discussion above for def() +applies to inf() as well, so the discussion here will focus on the differences between +the two. +
    
    +/* Decompress from file source to file dest until stream ends or EOF.
    +   inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
    +   allocated for processing, Z_DATA_ERROR if the deflate data is
    +   invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
    +   the version of the library linked do not match, or Z_ERRNO if there
    +   is an error reading or writing the files. */
    +int inf(FILE *source, FILE *dest)
    +{
    +
    +The local variables have the same functionality as they do for def(). The +only difference is that there is no flush variable, since inflate() +can tell from the zlib stream itself when the stream is complete. +
    
    +    int ret;
    +    unsigned have;
    +    z_stream strm;
    +    unsigned char in[CHUNK];
    +    unsigned char out[CHUNK];
    +
    +The initialization of the state is the same, except that there is no compression level, +of course, and two more elements of the structure are initialized. avail_in +and next_in must be initialized before calling inflateInit(). This +is because the application has the option to provide the start of the zlib stream in +order for inflateInit() to have access to information about the compression +method to aid in memory allocation. In the current implementation of zlib +(up through versions 1.2.x), the method-dependent memory allocations are deferred to the first call of +inflate() anyway. However those fields must be initialized since later versions +of zlib that provide more compression methods may take advantage of this interface. +In any case, no decompression is performed by inflateInit(), so the +avail_out and next_out fields do not need to be initialized before calling. +

    +Here avail_in is set to zero and next_in is set to Z_NULL to +indicate that no input data is being provided. +

    
    +    /* allocate inflate state */
    +    strm.zalloc = Z_NULL;
    +    strm.zfree = Z_NULL;
    +    strm.opaque = Z_NULL;
    +    strm.avail_in = 0;
    +    strm.next_in = Z_NULL;
    +    ret = inflateInit(&strm);
    +    if (ret != Z_OK)
    +        return ret;
    +
    +The outer do-loop decompresses input until inflate() indicates +that it has reached the end of the compressed data and has produced all of the uncompressed +output. This is in contrast to def() which processes all of the input file. +If end-of-file is reached before the compressed data self-terminates, then the compressed +data is incomplete and an error is returned. +
    
    +    /* decompress until deflate stream ends or end of file */
    +    do {
    +
    +We read input data and set the strm structure accordingly. If we've reached the +end of the input file, then we leave the outer loop and report an error, since the +compressed data is incomplete. Note that we may read more data than is eventually consumed +by inflate(), if the input file continues past the zlib stream. +For applications where zlib streams are embedded in other data, this routine would +need to be modified to return the unused data, or at least indicate how much of the input +data was not used, so the application would know where to pick up after the zlib stream. +
    
    +        strm.avail_in = fread(in, 1, CHUNK, source);
    +        if (ferror(source)) {
    +            (void)inflateEnd(&strm);
    +            return Z_ERRNO;
    +        }
    +        if (strm.avail_in == 0)
    +            break;
    +        strm.next_in = in;
    +
    +The inner do-loop has the same function it did in def(), which is to +keep calling inflate() until has generated all of the output it can with the +provided input. +
    
    +        /* run inflate() on input until output buffer not full */
    +        do {
    +
    +Just like in def(), the same output space is provided for each call of inflate(). +
    
    +            strm.avail_out = CHUNK;
    +            strm.next_out = out;
    +
    +Now we run the decompression engine itself. There is no need to adjust the flush parameter, since +the zlib format is self-terminating. The main difference here is that there are +return values that we need to pay attention to. Z_DATA_ERROR +indicates that inflate() detected an error in the zlib compressed data format, +which means that either the data is not a zlib stream to begin with, or that the data was +corrupted somewhere along the way since it was compressed. The other error to be processed is +Z_MEM_ERROR, which can occur since memory allocation is deferred until inflate() +needs it, unlike deflate(), whose memory is allocated at the start by deflateInit(). +

    +Advanced applications may use +deflateSetDictionary() to prime deflate() with a set of likely data to improve the +first 32K or so of compression. This is noted in the zlib header, so inflate() +requests that that dictionary be provided before it can start to decompress. Without the dictionary, +correct decompression is not possible. For this routine, we have no idea what the dictionary is, +so the Z_NEED_DICT indication is converted to a Z_DATA_ERROR. +

    +inflate() can also return Z_STREAM_ERROR, which should not be possible here, +but could be checked for as noted above for def(). Z_BUF_ERROR does not need to be +checked for here, for the same reasons noted for def(). Z_STREAM_END will be +checked for later. +

    
    +            ret = inflate(&strm, Z_NO_FLUSH);
    +            assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
    +            switch (ret) {
    +            case Z_NEED_DICT:
    +                ret = Z_DATA_ERROR;     /* and fall through */
    +            case Z_DATA_ERROR:
    +            case Z_MEM_ERROR:
    +                (void)inflateEnd(&strm);
    +                return ret;
    +            }
    +
    +The output of inflate() is handled identically to that of deflate(). +
    
    +            have = CHUNK - strm.avail_out;
    +            if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
    +                (void)inflateEnd(&strm);
    +                return Z_ERRNO;
    +            }
    +
    +The inner do-loop ends when inflate() has no more output as indicated +by not filling the output buffer, just as for deflate(). In this case, we cannot +assert that strm.avail_in will be zero, since the deflate stream may end before the file +does. +
    
    +        } while (strm.avail_out == 0);
    +
    +The outer do-loop ends when inflate() reports that it has reached the +end of the input zlib stream, has completed the decompression and integrity +check, and has provided all of the output. This is indicated by the inflate() +return value Z_STREAM_END. The inner loop is guaranteed to leave ret +equal to Z_STREAM_END if the last chunk of the input file read contained the end +of the zlib stream. So if the return value is not Z_STREAM_END, the +loop continues to read more input. +
    
    +        /* done when inflate() says it's done */
    +    } while (ret != Z_STREAM_END);
    +
    +At this point, decompression successfully completed, or we broke out of the loop due to no +more data being available from the input file. If the last inflate() return value +is not Z_STREAM_END, then the zlib stream was incomplete and a data error +is returned. Otherwise, we return with a happy return value. Of course, inflateEnd() +is called first to avoid a memory leak. +
    
    +    /* clean up and return */
    +    (void)inflateEnd(&strm);
    +    return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
    +}
    +
    +That ends the routines that directly use zlib. The following routines make this +a command-line program by running data through the above routines from stdin to +stdout, and handling any errors reported by def() or inf(). +

    +zerr() is used to interpret the possible error codes from def() +and inf(), as detailed in their comments above, and print out an error message. +Note that these are only a subset of the possible return values from deflate() +and inflate(). +

    
    +/* report a zlib or i/o error */
    +void zerr(int ret)
    +{
    +    fputs("zpipe: ", stderr);
    +    switch (ret) {
    +    case Z_ERRNO:
    +        if (ferror(stdin))
    +            fputs("error reading stdin\n", stderr);
    +        if (ferror(stdout))
    +            fputs("error writing stdout\n", stderr);
    +        break;
    +    case Z_STREAM_ERROR:
    +        fputs("invalid compression level\n", stderr);
    +        break;
    +    case Z_DATA_ERROR:
    +        fputs("invalid or incomplete deflate data\n", stderr);
    +        break;
    +    case Z_MEM_ERROR:
    +        fputs("out of memory\n", stderr);
    +        break;
    +    case Z_VERSION_ERROR:
    +        fputs("zlib version mismatch!\n", stderr);
    +    }
    +}
    +
    +Here is the main() routine used to test def() and inf(). The +zpipe command is simply a compression pipe from stdin to stdout, if +no arguments are given, or it is a decompression pipe if zpipe -d is used. If any other +arguments are provided, no compression or decompression is performed. Instead a usage +message is displayed. Examples are zpipe < foo.txt > foo.txt.z to compress, and +zpipe -d < foo.txt.z > foo.txt to decompress. +
    
    +/* compress or decompress from stdin to stdout */
    +int main(int argc, char **argv)
    +{
    +    int ret;
    +
    +    /* avoid end-of-line conversions */
    +    SET_BINARY_MODE(stdin);
    +    SET_BINARY_MODE(stdout);
    +
    +    /* do compression if no arguments */
    +    if (argc == 1) {
    +        ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION);
    +        if (ret != Z_OK)
    +            zerr(ret);
    +        return ret;
    +    }
    +
    +    /* do decompression if -d specified */
    +    else if (argc == 2 && strcmp(argv[1], "-d") == 0) {
    +        ret = inf(stdin, stdout);
    +        if (ret != Z_OK)
    +            zerr(ret);
    +        return ret;
    +    }
    +
    +    /* otherwise, report usage */
    +    else {
    +        fputs("zpipe usage: zpipe [-d] < source > dest\n", stderr);
    +        return 1;
    +    }
    +}
    +
    +
    +Copyright (c) 2004, 2005 by Mark Adler
    Last modified 11 December 2005
    + + diff --git a/dependencies/zlib-1.2.11/examples/zpipe.c b/dependencies/zlib-1.2.11/examples/zpipe.c new file mode 100644 index 0000000..83535d1 --- /dev/null +++ b/dependencies/zlib-1.2.11/examples/zpipe.c @@ -0,0 +1,205 @@ +/* zpipe.c: example of proper use of zlib's inflate() and deflate() + Not copyrighted -- provided to the public domain + Version 1.4 11 December 2005 Mark Adler */ + +/* Version history: + 1.0 30 Oct 2004 First version + 1.1 8 Nov 2004 Add void casting for unused return values + Use switch statement for inflate() return values + 1.2 9 Nov 2004 Add assertions to document zlib guarantees + 1.3 6 Apr 2005 Remove incorrect assertion in inf() + 1.4 11 Dec 2005 Add hack to avoid MSDOS end-of-line conversions + Avoid some compiler warnings for input and output buffers + */ + +#include +#include +#include +#include "zlib.h" + +#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) +# include +# include +# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) +#else +# define SET_BINARY_MODE(file) +#endif + +#define CHUNK 16384 + +/* Compress from file source to file dest until EOF on source. + def() returns Z_OK on success, Z_MEM_ERROR if memory could not be + allocated for processing, Z_STREAM_ERROR if an invalid compression + level is supplied, Z_VERSION_ERROR if the version of zlib.h and the + version of the library linked do not match, or Z_ERRNO if there is + an error reading or writing the files. */ +int def(FILE *source, FILE *dest, int level) +{ + int ret, flush; + unsigned have; + z_stream strm; + unsigned char in[CHUNK]; + unsigned char out[CHUNK]; + + /* allocate deflate state */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + ret = deflateInit(&strm, level); + if (ret != Z_OK) + return ret; + + /* compress until end of file */ + do { + strm.avail_in = fread(in, 1, CHUNK, source); + if (ferror(source)) { + (void)deflateEnd(&strm); + return Z_ERRNO; + } + flush = feof(source) ? Z_FINISH : Z_NO_FLUSH; + strm.next_in = in; + + /* run deflate() on input until output buffer not full, finish + compression if all of source has been read in */ + do { + strm.avail_out = CHUNK; + strm.next_out = out; + ret = deflate(&strm, flush); /* no bad return value */ + assert(ret != Z_STREAM_ERROR); /* state not clobbered */ + have = CHUNK - strm.avail_out; + if (fwrite(out, 1, have, dest) != have || ferror(dest)) { + (void)deflateEnd(&strm); + return Z_ERRNO; + } + } while (strm.avail_out == 0); + assert(strm.avail_in == 0); /* all input will be used */ + + /* done when last data in file processed */ + } while (flush != Z_FINISH); + assert(ret == Z_STREAM_END); /* stream will be complete */ + + /* clean up and return */ + (void)deflateEnd(&strm); + return Z_OK; +} + +/* Decompress from file source to file dest until stream ends or EOF. + inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be + allocated for processing, Z_DATA_ERROR if the deflate data is + invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and + the version of the library linked do not match, or Z_ERRNO if there + is an error reading or writing the files. */ +int inf(FILE *source, FILE *dest) +{ + int ret; + unsigned have; + z_stream strm; + unsigned char in[CHUNK]; + unsigned char out[CHUNK]; + + /* allocate inflate state */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit(&strm); + if (ret != Z_OK) + return ret; + + /* decompress until deflate stream ends or end of file */ + do { + strm.avail_in = fread(in, 1, CHUNK, source); + if (ferror(source)) { + (void)inflateEnd(&strm); + return Z_ERRNO; + } + if (strm.avail_in == 0) + break; + strm.next_in = in; + + /* run inflate() on input until output buffer not full */ + do { + strm.avail_out = CHUNK; + strm.next_out = out; + ret = inflate(&strm, Z_NO_FLUSH); + assert(ret != Z_STREAM_ERROR); /* state not clobbered */ + switch (ret) { + case Z_NEED_DICT: + ret = Z_DATA_ERROR; /* and fall through */ + case Z_DATA_ERROR: + case Z_MEM_ERROR: + (void)inflateEnd(&strm); + return ret; + } + have = CHUNK - strm.avail_out; + if (fwrite(out, 1, have, dest) != have || ferror(dest)) { + (void)inflateEnd(&strm); + return Z_ERRNO; + } + } while (strm.avail_out == 0); + + /* done when inflate() says it's done */ + } while (ret != Z_STREAM_END); + + /* clean up and return */ + (void)inflateEnd(&strm); + return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR; +} + +/* report a zlib or i/o error */ +void zerr(int ret) +{ + fputs("zpipe: ", stderr); + switch (ret) { + case Z_ERRNO: + if (ferror(stdin)) + fputs("error reading stdin\n", stderr); + if (ferror(stdout)) + fputs("error writing stdout\n", stderr); + break; + case Z_STREAM_ERROR: + fputs("invalid compression level\n", stderr); + break; + case Z_DATA_ERROR: + fputs("invalid or incomplete deflate data\n", stderr); + break; + case Z_MEM_ERROR: + fputs("out of memory\n", stderr); + break; + case Z_VERSION_ERROR: + fputs("zlib version mismatch!\n", stderr); + } +} + +/* compress or decompress from stdin to stdout */ +int main(int argc, char **argv) +{ + int ret; + + /* avoid end-of-line conversions */ + SET_BINARY_MODE(stdin); + SET_BINARY_MODE(stdout); + + /* do compression if no arguments */ + if (argc == 1) { + ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION); + if (ret != Z_OK) + zerr(ret); + return ret; + } + + /* do decompression if -d specified */ + else if (argc == 2 && strcmp(argv[1], "-d") == 0) { + ret = inf(stdin, stdout); + if (ret != Z_OK) + zerr(ret); + return ret; + } + + /* otherwise, report usage */ + else { + fputs("zpipe usage: zpipe [-d] < source > dest\n", stderr); + return 1; + } +} diff --git a/dependencies/zlib-1.2.11/examples/zran.c b/dependencies/zlib-1.2.11/examples/zran.c new file mode 100644 index 0000000..4fec659 --- /dev/null +++ b/dependencies/zlib-1.2.11/examples/zran.c @@ -0,0 +1,409 @@ +/* zran.c -- example of zlib/gzip stream indexing and random access + * Copyright (C) 2005, 2012 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + Version 1.1 29 Sep 2012 Mark Adler */ + +/* Version History: + 1.0 29 May 2005 First version + 1.1 29 Sep 2012 Fix memory reallocation error + */ + +/* Illustrate the use of Z_BLOCK, inflatePrime(), and inflateSetDictionary() + for random access of a compressed file. A file containing a zlib or gzip + stream is provided on the command line. The compressed stream is decoded in + its entirety, and an index built with access points about every SPAN bytes + in the uncompressed output. The compressed file is left open, and can then + be read randomly, having to decompress on the average SPAN/2 uncompressed + bytes before getting to the desired block of data. + + An access point can be created at the start of any deflate block, by saving + the starting file offset and bit of that block, and the 32K bytes of + uncompressed data that precede that block. Also the uncompressed offset of + that block is saved to provide a referece for locating a desired starting + point in the uncompressed stream. build_index() works by decompressing the + input zlib or gzip stream a block at a time, and at the end of each block + deciding if enough uncompressed data has gone by to justify the creation of + a new access point. If so, that point is saved in a data structure that + grows as needed to accommodate the points. + + To use the index, an offset in the uncompressed data is provided, for which + the latest access point at or preceding that offset is located in the index. + The input file is positioned to the specified location in the index, and if + necessary the first few bits of the compressed data is read from the file. + inflate is initialized with those bits and the 32K of uncompressed data, and + the decompression then proceeds until the desired offset in the file is + reached. Then the decompression continues to read the desired uncompressed + data from the file. + + Another approach would be to generate the index on demand. In that case, + requests for random access reads from the compressed data would try to use + the index, but if a read far enough past the end of the index is required, + then further index entries would be generated and added. + + There is some fair bit of overhead to starting inflation for the random + access, mainly copying the 32K byte dictionary. So if small pieces of the + file are being accessed, it would make sense to implement a cache to hold + some lookahead and avoid many calls to extract() for small lengths. + + Another way to build an index would be to use inflateCopy(). That would + not be constrained to have access points at block boundaries, but requires + more memory per access point, and also cannot be saved to file due to the + use of pointers in the state. The approach here allows for storage of the + index in a file. + */ + +#include +#include +#include +#include "zlib.h" + +#define local static + +#define SPAN 1048576L /* desired distance between access points */ +#define WINSIZE 32768U /* sliding window size */ +#define CHUNK 16384 /* file input buffer size */ + +/* access point entry */ +struct point { + off_t out; /* corresponding offset in uncompressed data */ + off_t in; /* offset in input file of first full byte */ + int bits; /* number of bits (1-7) from byte at in - 1, or 0 */ + unsigned char window[WINSIZE]; /* preceding 32K of uncompressed data */ +}; + +/* access point list */ +struct access { + int have; /* number of list entries filled in */ + int size; /* number of list entries allocated */ + struct point *list; /* allocated list */ +}; + +/* Deallocate an index built by build_index() */ +local void free_index(struct access *index) +{ + if (index != NULL) { + free(index->list); + free(index); + } +} + +/* Add an entry to the access point list. If out of memory, deallocate the + existing list and return NULL. */ +local struct access *addpoint(struct access *index, int bits, + off_t in, off_t out, unsigned left, unsigned char *window) +{ + struct point *next; + + /* if list is empty, create it (start with eight points) */ + if (index == NULL) { + index = malloc(sizeof(struct access)); + if (index == NULL) return NULL; + index->list = malloc(sizeof(struct point) << 3); + if (index->list == NULL) { + free(index); + return NULL; + } + index->size = 8; + index->have = 0; + } + + /* if list is full, make it bigger */ + else if (index->have == index->size) { + index->size <<= 1; + next = realloc(index->list, sizeof(struct point) * index->size); + if (next == NULL) { + free_index(index); + return NULL; + } + index->list = next; + } + + /* fill in entry and increment how many we have */ + next = index->list + index->have; + next->bits = bits; + next->in = in; + next->out = out; + if (left) + memcpy(next->window, window + WINSIZE - left, left); + if (left < WINSIZE) + memcpy(next->window + left, window, WINSIZE - left); + index->have++; + + /* return list, possibly reallocated */ + return index; +} + +/* Make one entire pass through the compressed stream and build an index, with + access points about every span bytes of uncompressed output -- span is + chosen to balance the speed of random access against the memory requirements + of the list, about 32K bytes per access point. Note that data after the end + of the first zlib or gzip stream in the file is ignored. build_index() + returns the number of access points on success (>= 1), Z_MEM_ERROR for out + of memory, Z_DATA_ERROR for an error in the input file, or Z_ERRNO for a + file read error. On success, *built points to the resulting index. */ +local int build_index(FILE *in, off_t span, struct access **built) +{ + int ret; + off_t totin, totout; /* our own total counters to avoid 4GB limit */ + off_t last; /* totout value of last access point */ + struct access *index; /* access points being generated */ + z_stream strm; + unsigned char input[CHUNK]; + unsigned char window[WINSIZE]; + + /* initialize inflate */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit2(&strm, 47); /* automatic zlib or gzip decoding */ + if (ret != Z_OK) + return ret; + + /* inflate the input, maintain a sliding window, and build an index -- this + also validates the integrity of the compressed data using the check + information at the end of the gzip or zlib stream */ + totin = totout = last = 0; + index = NULL; /* will be allocated by first addpoint() */ + strm.avail_out = 0; + do { + /* get some compressed data from input file */ + strm.avail_in = fread(input, 1, CHUNK, in); + if (ferror(in)) { + ret = Z_ERRNO; + goto build_index_error; + } + if (strm.avail_in == 0) { + ret = Z_DATA_ERROR; + goto build_index_error; + } + strm.next_in = input; + + /* process all of that, or until end of stream */ + do { + /* reset sliding window if necessary */ + if (strm.avail_out == 0) { + strm.avail_out = WINSIZE; + strm.next_out = window; + } + + /* inflate until out of input, output, or at end of block -- + update the total input and output counters */ + totin += strm.avail_in; + totout += strm.avail_out; + ret = inflate(&strm, Z_BLOCK); /* return at end of block */ + totin -= strm.avail_in; + totout -= strm.avail_out; + if (ret == Z_NEED_DICT) + ret = Z_DATA_ERROR; + if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR) + goto build_index_error; + if (ret == Z_STREAM_END) + break; + + /* if at end of block, consider adding an index entry (note that if + data_type indicates an end-of-block, then all of the + uncompressed data from that block has been delivered, and none + of the compressed data after that block has been consumed, + except for up to seven bits) -- the totout == 0 provides an + entry point after the zlib or gzip header, and assures that the + index always has at least one access point; we avoid creating an + access point after the last block by checking bit 6 of data_type + */ + if ((strm.data_type & 128) && !(strm.data_type & 64) && + (totout == 0 || totout - last > span)) { + index = addpoint(index, strm.data_type & 7, totin, + totout, strm.avail_out, window); + if (index == NULL) { + ret = Z_MEM_ERROR; + goto build_index_error; + } + last = totout; + } + } while (strm.avail_in != 0); + } while (ret != Z_STREAM_END); + + /* clean up and return index (release unused entries in list) */ + (void)inflateEnd(&strm); + index->list = realloc(index->list, sizeof(struct point) * index->have); + index->size = index->have; + *built = index; + return index->size; + + /* return error */ + build_index_error: + (void)inflateEnd(&strm); + if (index != NULL) + free_index(index); + return ret; +} + +/* Use the index to read len bytes from offset into buf, return bytes read or + negative for error (Z_DATA_ERROR or Z_MEM_ERROR). If data is requested past + the end of the uncompressed data, then extract() will return a value less + than len, indicating how much as actually read into buf. This function + should not return a data error unless the file was modified since the index + was generated. extract() may also return Z_ERRNO if there is an error on + reading or seeking the input file. */ +local int extract(FILE *in, struct access *index, off_t offset, + unsigned char *buf, int len) +{ + int ret, skip; + z_stream strm; + struct point *here; + unsigned char input[CHUNK]; + unsigned char discard[WINSIZE]; + + /* proceed only if something reasonable to do */ + if (len < 0) + return 0; + + /* find where in stream to start */ + here = index->list; + ret = index->have; + while (--ret && here[1].out <= offset) + here++; + + /* initialize file and inflate state to start there */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit2(&strm, -15); /* raw inflate */ + if (ret != Z_OK) + return ret; + ret = fseeko(in, here->in - (here->bits ? 1 : 0), SEEK_SET); + if (ret == -1) + goto extract_ret; + if (here->bits) { + ret = getc(in); + if (ret == -1) { + ret = ferror(in) ? Z_ERRNO : Z_DATA_ERROR; + goto extract_ret; + } + (void)inflatePrime(&strm, here->bits, ret >> (8 - here->bits)); + } + (void)inflateSetDictionary(&strm, here->window, WINSIZE); + + /* skip uncompressed bytes until offset reached, then satisfy request */ + offset -= here->out; + strm.avail_in = 0; + skip = 1; /* while skipping to offset */ + do { + /* define where to put uncompressed data, and how much */ + if (offset == 0 && skip) { /* at offset now */ + strm.avail_out = len; + strm.next_out = buf; + skip = 0; /* only do this once */ + } + if (offset > WINSIZE) { /* skip WINSIZE bytes */ + strm.avail_out = WINSIZE; + strm.next_out = discard; + offset -= WINSIZE; + } + else if (offset != 0) { /* last skip */ + strm.avail_out = (unsigned)offset; + strm.next_out = discard; + offset = 0; + } + + /* uncompress until avail_out filled, or end of stream */ + do { + if (strm.avail_in == 0) { + strm.avail_in = fread(input, 1, CHUNK, in); + if (ferror(in)) { + ret = Z_ERRNO; + goto extract_ret; + } + if (strm.avail_in == 0) { + ret = Z_DATA_ERROR; + goto extract_ret; + } + strm.next_in = input; + } + ret = inflate(&strm, Z_NO_FLUSH); /* normal inflate */ + if (ret == Z_NEED_DICT) + ret = Z_DATA_ERROR; + if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR) + goto extract_ret; + if (ret == Z_STREAM_END) + break; + } while (strm.avail_out != 0); + + /* if reach end of stream, then don't keep trying to get more */ + if (ret == Z_STREAM_END) + break; + + /* do until offset reached and requested data read, or stream ends */ + } while (skip); + + /* compute number of uncompressed bytes read after offset */ + ret = skip ? 0 : len - strm.avail_out; + + /* clean up and return bytes read or error */ + extract_ret: + (void)inflateEnd(&strm); + return ret; +} + +/* Demonstrate the use of build_index() and extract() by processing the file + provided on the command line, and the extracting 16K from about 2/3rds of + the way through the uncompressed output, and writing that to stdout. */ +int main(int argc, char **argv) +{ + int len; + off_t offset; + FILE *in; + struct access *index = NULL; + unsigned char buf[CHUNK]; + + /* open input file */ + if (argc != 2) { + fprintf(stderr, "usage: zran file.gz\n"); + return 1; + } + in = fopen(argv[1], "rb"); + if (in == NULL) { + fprintf(stderr, "zran: could not open %s for reading\n", argv[1]); + return 1; + } + + /* build index */ + len = build_index(in, SPAN, &index); + if (len < 0) { + fclose(in); + switch (len) { + case Z_MEM_ERROR: + fprintf(stderr, "zran: out of memory\n"); + break; + case Z_DATA_ERROR: + fprintf(stderr, "zran: compressed data error in %s\n", argv[1]); + break; + case Z_ERRNO: + fprintf(stderr, "zran: read error on %s\n", argv[1]); + break; + default: + fprintf(stderr, "zran: error %d while building index\n", len); + } + return 1; + } + fprintf(stderr, "zran: built index with %d access points\n", len); + + /* use index by reading some bytes from an arbitrary offset */ + offset = (index->list[index->have - 1].out << 1) / 3; + len = extract(in, index, offset, buf, CHUNK); + if (len < 0) + fprintf(stderr, "zran: extraction failed: %s error\n", + len == Z_MEM_ERROR ? "out of memory" : "input corrupted"); + else { + fwrite(buf, 1, len, stdout); + fprintf(stderr, "zran: extracted %d bytes at %llu\n", len, offset); + } + + /* clean up and exit */ + free_index(index); + fclose(in); + return 0; +} diff --git a/dependencies/zlib-1.2.11/gzclose.c b/dependencies/zlib-1.2.11/gzclose.c new file mode 100644 index 0000000..caeb99a --- /dev/null +++ b/dependencies/zlib-1.2.11/gzclose.c @@ -0,0 +1,25 @@ +/* gzclose.c -- zlib gzclose() function + * Copyright (C) 2004, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +/* gzclose() is in a separate file so that it is linked in only if it is used. + That way the other gzclose functions can be used instead to avoid linking in + unneeded compression or decompression routines. */ +int ZEXPORT gzclose(file) + gzFile file; +{ +#ifndef NO_GZCOMPRESS + gz_statep state; + + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + + return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file); +#else + return gzclose_r(file); +#endif +} diff --git a/dependencies/zlib-1.2.11/gzguts.h b/dependencies/zlib-1.2.11/gzguts.h new file mode 100644 index 0000000..990a4d2 --- /dev/null +++ b/dependencies/zlib-1.2.11/gzguts.h @@ -0,0 +1,218 @@ +/* gzguts.h -- zlib internal header definitions for gz* operations + * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef _LARGEFILE64_SOURCE +# ifndef _LARGEFILE_SOURCE +# define _LARGEFILE_SOURCE 1 +# endif +# ifdef _FILE_OFFSET_BITS +# undef _FILE_OFFSET_BITS +# endif +#endif + +#ifdef HAVE_HIDDEN +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include +#include "zlib.h" +#ifdef STDC +# include +# include +# include +#endif + +#ifndef _POSIX_SOURCE +# define _POSIX_SOURCE +#endif +#include + +#ifdef _WIN32 +# include +#endif + +#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) +# include +#endif + +#if defined(_WIN32) || defined(__CYGWIN__) +# define WIDECHAR +#endif + +#ifdef WINAPI_FAMILY +# define open _open +# define read _read +# define write _write +# define close _close +#endif + +#ifdef NO_DEFLATE /* for compatibility with old definition */ +# define NO_GZCOMPRESS +#endif + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS +/* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 +/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) +# define vsnprintf _vsnprintf +# endif +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +# ifdef VMS +# define NO_vsnprintf +# endif +# ifdef __OS400__ +# define NO_vsnprintf +# endif +# ifdef __MVS__ +# define NO_vsnprintf +# endif +#endif + +/* unlike snprintf (which is required in C99), _snprintf does not guarantee + null termination of the result -- however this is only used in gzlib.c where + the result is assured to fit in the space provided */ +#if defined(_MSC_VER) && _MSC_VER < 1900 +# define snprintf _snprintf +#endif + +#ifndef local +# define local static +#endif +/* since "static" is used to mean two completely different things in C, we + define "local" for the non-static meaning of "static", for readability + (compile with -Dlocal if your debugger can't find static symbols) */ + +/* gz* functions always use library allocation functions */ +#ifndef STDC + extern voidp malloc OF((uInt size)); + extern void free OF((voidpf ptr)); +#endif + +/* get errno and strerror definition */ +#if defined UNDER_CE +# include +# define zstrerror() gz_strwinerror((DWORD)GetLastError()) +#else +# ifndef NO_STRERROR +# include +# define zstrerror() strerror(errno) +# else +# define zstrerror() "stdio error (consult errno)" +# endif +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); +#endif + +/* default memLevel */ +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif + +/* default i/o buffer size -- double this for output when reading (this and + twice this must be able to fit in an unsigned type) */ +#define GZBUFSIZE 8192 + +/* gzip modes, also provide a little integrity check on the passed structure */ +#define GZ_NONE 0 +#define GZ_READ 7247 +#define GZ_WRITE 31153 +#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */ + +/* values for gz_state how */ +#define LOOK 0 /* look for a gzip header */ +#define COPY 1 /* copy input directly */ +#define GZIP 2 /* decompress a gzip stream */ + +/* internal gzip file state data structure */ +typedef struct { + /* exposed contents for gzgetc() macro */ + struct gzFile_s x; /* "x" for exposed */ + /* x.have: number of bytes available at x.next */ + /* x.next: next output data to deliver or write */ + /* x.pos: current position in uncompressed data */ + /* used for both reading and writing */ + int mode; /* see gzip modes above */ + int fd; /* file descriptor */ + char *path; /* path or fd for error messages */ + unsigned size; /* buffer size, zero if not allocated yet */ + unsigned want; /* requested buffer size, default is GZBUFSIZE */ + unsigned char *in; /* input buffer (double-sized when writing) */ + unsigned char *out; /* output buffer (double-sized when reading) */ + int direct; /* 0 if processing gzip, 1 if transparent */ + /* just for reading */ + int how; /* 0: get header, 1: copy, 2: decompress */ + z_off64_t start; /* where the gzip data started, for rewinding */ + int eof; /* true if end of input file reached */ + int past; /* true if read requested past end */ + /* just for writing */ + int level; /* compression level */ + int strategy; /* compression strategy */ + /* seek request */ + z_off64_t skip; /* amount to skip (already rewound if backwards) */ + int seek; /* true if seek request pending */ + /* error information */ + int err; /* error code */ + char *msg; /* error message */ + /* zlib inflate or deflate stream */ + z_stream strm; /* stream structure in-place (not a pointer) */ +} gz_state; +typedef gz_state FAR *gz_statep; + +/* shared functions */ +void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); +#if defined UNDER_CE +char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); +#endif + +/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t + value -- needed when comparing unsigned to z_off64_t, which is signed + (possible z_off64_t types off_t, off64_t, and long are all signed) */ +#ifdef INT_MAX +# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) +#else +unsigned ZLIB_INTERNAL gz_intmax OF((void)); +# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) +#endif diff --git a/dependencies/zlib-1.2.11/gzlib.c b/dependencies/zlib-1.2.11/gzlib.c new file mode 100644 index 0000000..4105e6a --- /dev/null +++ b/dependencies/zlib-1.2.11/gzlib.c @@ -0,0 +1,637 @@ +/* gzlib.c -- zlib functions common to reading and writing gzip files + * Copyright (C) 2004-2017 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +#if defined(_WIN32) && !defined(__BORLANDC__) && !defined(__MINGW32__) +# define LSEEK _lseeki64 +#else +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +# define LSEEK lseek64 +#else +# define LSEEK lseek +#endif +#endif + +/* Local functions */ +local void gz_reset OF((gz_statep)); +local gzFile gz_open OF((const void *, int, const char *)); + +#if defined UNDER_CE + +/* Map the Windows error number in ERROR to a locale-dependent error message + string and return a pointer to it. Typically, the values for ERROR come + from GetLastError. + + The string pointed to shall not be modified by the application, but may be + overwritten by a subsequent call to gz_strwinerror + + The gz_strwinerror function does not change the current setting of + GetLastError. */ +char ZLIB_INTERNAL *gz_strwinerror (error) + DWORD error; +{ + static char buf[1024]; + + wchar_t *msgbuf; + DWORD lasterr = GetLastError(); + DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, + error, + 0, /* Default language */ + (LPVOID)&msgbuf, + 0, + NULL); + if (chars != 0) { + /* If there is an \r\n appended, zap it. */ + if (chars >= 2 + && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { + chars -= 2; + msgbuf[chars] = 0; + } + + if (chars > sizeof (buf) - 1) { + chars = sizeof (buf) - 1; + msgbuf[chars] = 0; + } + + wcstombs(buf, msgbuf, chars + 1); + LocalFree(msgbuf); + } + else { + sprintf(buf, "unknown win32 error (%ld)", error); + } + + SetLastError(lasterr); + return buf; +} + +#endif /* UNDER_CE */ + +/* Reset gzip file state */ +local void gz_reset(state) + gz_statep state; +{ + state->x.have = 0; /* no output data available */ + if (state->mode == GZ_READ) { /* for reading ... */ + state->eof = 0; /* not at end of file */ + state->past = 0; /* have not read past end yet */ + state->how = LOOK; /* look for gzip header */ + } + state->seek = 0; /* no seek request pending */ + gz_error(state, Z_OK, NULL); /* clear error */ + state->x.pos = 0; /* no uncompressed data yet */ + state->strm.avail_in = 0; /* no input data yet */ +} + +/* Open a gzip file either by name or file descriptor. */ +local gzFile gz_open(path, fd, mode) + const void *path; + int fd; + const char *mode; +{ + gz_statep state; + z_size_t len; + int oflag; +#ifdef O_CLOEXEC + int cloexec = 0; +#endif +#ifdef O_EXCL + int exclusive = 0; +#endif + + /* check input */ + if (path == NULL) + return NULL; + + /* allocate gzFile structure to return */ + state = (gz_statep)malloc(sizeof(gz_state)); + if (state == NULL) + return NULL; + state->size = 0; /* no buffers allocated yet */ + state->want = GZBUFSIZE; /* requested buffer size */ + state->msg = NULL; /* no error message yet */ + + /* interpret mode */ + state->mode = GZ_NONE; + state->level = Z_DEFAULT_COMPRESSION; + state->strategy = Z_DEFAULT_STRATEGY; + state->direct = 0; + while (*mode) { + if (*mode >= '0' && *mode <= '9') + state->level = *mode - '0'; + else + switch (*mode) { + case 'r': + state->mode = GZ_READ; + break; +#ifndef NO_GZCOMPRESS + case 'w': + state->mode = GZ_WRITE; + break; + case 'a': + state->mode = GZ_APPEND; + break; +#endif + case '+': /* can't read and write at the same time */ + free(state); + return NULL; + case 'b': /* ignore -- will request binary anyway */ + break; +#ifdef O_CLOEXEC + case 'e': + cloexec = 1; + break; +#endif +#ifdef O_EXCL + case 'x': + exclusive = 1; + break; +#endif + case 'f': + state->strategy = Z_FILTERED; + break; + case 'h': + state->strategy = Z_HUFFMAN_ONLY; + break; + case 'R': + state->strategy = Z_RLE; + break; + case 'F': + state->strategy = Z_FIXED; + break; + case 'T': + state->direct = 1; + break; + default: /* could consider as an error, but just ignore */ + ; + } + mode++; + } + + /* must provide an "r", "w", or "a" */ + if (state->mode == GZ_NONE) { + free(state); + return NULL; + } + + /* can't force transparent read */ + if (state->mode == GZ_READ) { + if (state->direct) { + free(state); + return NULL; + } + state->direct = 1; /* for empty file */ + } + + /* save the path name for error messages */ +#ifdef WIDECHAR + if (fd == -2) { + len = wcstombs(NULL, path, 0); + if (len == (z_size_t)-1) + len = 0; + } + else +#endif + len = strlen((const char *)path); + state->path = (char *)malloc(len + 1); + if (state->path == NULL) { + free(state); + return NULL; + } +#ifdef WIDECHAR + if (fd == -2) + if (len) + wcstombs(state->path, path, len + 1); + else + *(state->path) = 0; + else +#endif +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + (void)snprintf(state->path, len + 1, "%s", (const char *)path); +#else + strcpy(state->path, path); +#endif + + /* compute the flags for open() */ + oflag = +#ifdef O_LARGEFILE + O_LARGEFILE | +#endif +#ifdef O_BINARY + O_BINARY | +#endif +#ifdef O_CLOEXEC + (cloexec ? O_CLOEXEC : 0) | +#endif + (state->mode == GZ_READ ? + O_RDONLY : + (O_WRONLY | O_CREAT | +#ifdef O_EXCL + (exclusive ? O_EXCL : 0) | +#endif + (state->mode == GZ_WRITE ? + O_TRUNC : + O_APPEND))); + + /* open the file with the appropriate flags (or just use fd) */ + state->fd = fd > -1 ? fd : ( +#ifdef WIDECHAR + fd == -2 ? _wopen(path, oflag, 0666) : +#endif + open((const char *)path, oflag, 0666)); + if (state->fd == -1) { + free(state->path); + free(state); + return NULL; + } + if (state->mode == GZ_APPEND) { + LSEEK(state->fd, 0, SEEK_END); /* so gzoffset() is correct */ + state->mode = GZ_WRITE; /* simplify later checks */ + } + + /* save the current position for rewinding (only if reading) */ + if (state->mode == GZ_READ) { + state->start = LSEEK(state->fd, 0, SEEK_CUR); + if (state->start == -1) state->start = 0; + } + + /* initialize stream */ + gz_reset(state); + + /* return stream */ + return (gzFile)state; +} + +/* -- see zlib.h -- */ +gzFile ZEXPORT gzopen(path, mode) + const char *path; + const char *mode; +{ + return gz_open(path, -1, mode); +} + +/* -- see zlib.h -- */ +gzFile ZEXPORT gzopen64(path, mode) + const char *path; + const char *mode; +{ + return gz_open(path, -1, mode); +} + +/* -- see zlib.h -- */ +gzFile ZEXPORT gzdopen(fd, mode) + int fd; + const char *mode; +{ + char *path; /* identifier for error messages */ + gzFile gz; + + if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) + return NULL; +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + (void)snprintf(path, 7 + 3 * sizeof(int), "", fd); +#else + sprintf(path, "", fd); /* for debugging */ +#endif + gz = gz_open(path, fd, mode); + free(path); + return gz; +} + +/* -- see zlib.h -- */ +#ifdef WIDECHAR +gzFile ZEXPORT gzopen_w(path, mode) + const wchar_t *path; + const char *mode; +{ + return gz_open(path, -2, mode); +} +#endif + +/* -- see zlib.h -- */ +int ZEXPORT gzbuffer(file, size) + gzFile file; + unsigned size; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* make sure we haven't already allocated memory */ + if (state->size != 0) + return -1; + + /* check and set requested size */ + if ((size << 1) < size) + return -1; /* need to be able to double it */ + if (size < 2) + size = 2; /* need two bytes to check magic header */ + state->want = size; + return 0; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzrewind(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return -1; + + /* back up and start over */ + if (LSEEK(state->fd, state->start, SEEK_SET) == -1) + return -1; + gz_reset(state); + return 0; +} + +/* -- see zlib.h -- */ +z_off64_t ZEXPORT gzseek64(file, offset, whence) + gzFile file; + z_off64_t offset; + int whence; +{ + unsigned n; + z_off64_t ret; + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* check that there's no error */ + if (state->err != Z_OK && state->err != Z_BUF_ERROR) + return -1; + + /* can only seek from start or relative to current position */ + if (whence != SEEK_SET && whence != SEEK_CUR) + return -1; + + /* normalize offset to a SEEK_CUR specification */ + if (whence == SEEK_SET) + offset -= state->x.pos; + else if (state->seek) + offset += state->skip; + state->seek = 0; + + /* if within raw area while reading, just go there */ + if (state->mode == GZ_READ && state->how == COPY && + state->x.pos + offset >= 0) { + ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR); + if (ret == -1) + return -1; + state->x.have = 0; + state->eof = 0; + state->past = 0; + state->seek = 0; + gz_error(state, Z_OK, NULL); + state->strm.avail_in = 0; + state->x.pos += offset; + return state->x.pos; + } + + /* calculate skip amount, rewinding if needed for back seek when reading */ + if (offset < 0) { + if (state->mode != GZ_READ) /* writing -- can't go backwards */ + return -1; + offset += state->x.pos; + if (offset < 0) /* before start of file! */ + return -1; + if (gzrewind(file) == -1) /* rewind, then skip to offset */ + return -1; + } + + /* if reading, skip what's in output buffer (one less gzgetc() check) */ + if (state->mode == GZ_READ) { + n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ? + (unsigned)offset : state->x.have; + state->x.have -= n; + state->x.next += n; + state->x.pos += n; + offset -= n; + } + + /* request skip (if not zero) */ + if (offset) { + state->seek = 1; + state->skip = offset; + } + return state->x.pos + offset; +} + +/* -- see zlib.h -- */ +z_off_t ZEXPORT gzseek(file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + z_off64_t ret; + + ret = gzseek64(file, (z_off64_t)offset, whence); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} + +/* -- see zlib.h -- */ +z_off64_t ZEXPORT gztell64(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* return position */ + return state->x.pos + (state->seek ? state->skip : 0); +} + +/* -- see zlib.h -- */ +z_off_t ZEXPORT gztell(file) + gzFile file; +{ + z_off64_t ret; + + ret = gztell64(file); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} + +/* -- see zlib.h -- */ +z_off64_t ZEXPORT gzoffset64(file) + gzFile file; +{ + z_off64_t offset; + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* compute and return effective offset in file */ + offset = LSEEK(state->fd, 0, SEEK_CUR); + if (offset == -1) + return -1; + if (state->mode == GZ_READ) /* reading */ + offset -= state->strm.avail_in; /* don't count buffered input */ + return offset; +} + +/* -- see zlib.h -- */ +z_off_t ZEXPORT gzoffset(file) + gzFile file; +{ + z_off64_t ret; + + ret = gzoffset64(file); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzeof(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return 0; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return 0; + + /* return end-of-file state */ + return state->mode == GZ_READ ? state->past : 0; +} + +/* -- see zlib.h -- */ +const char * ZEXPORT gzerror(file, errnum) + gzFile file; + int *errnum; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return NULL; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return NULL; + + /* return error information */ + if (errnum != NULL) + *errnum = state->err; + return state->err == Z_MEM_ERROR ? "out of memory" : + (state->msg == NULL ? "" : state->msg); +} + +/* -- see zlib.h -- */ +void ZEXPORT gzclearerr(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return; + + /* clear error and end-of-file */ + if (state->mode == GZ_READ) { + state->eof = 0; + state->past = 0; + } + gz_error(state, Z_OK, NULL); +} + +/* Create an error message in allocated memory and set state->err and + state->msg accordingly. Free any previous error message already there. Do + not try to free or allocate space if the error is Z_MEM_ERROR (out of + memory). Simply save the error message as a static string. If there is an + allocation failure constructing the error message, then convert the error to + out of memory. */ +void ZLIB_INTERNAL gz_error(state, err, msg) + gz_statep state; + int err; + const char *msg; +{ + /* free previously allocated message and clear */ + if (state->msg != NULL) { + if (state->err != Z_MEM_ERROR) + free(state->msg); + state->msg = NULL; + } + + /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */ + if (err != Z_OK && err != Z_BUF_ERROR) + state->x.have = 0; + + /* set error code, and if no message, then done */ + state->err = err; + if (msg == NULL) + return; + + /* for an out of memory error, return literal string when requested */ + if (err == Z_MEM_ERROR) + return; + + /* construct error message with path */ + if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == + NULL) { + state->err = Z_MEM_ERROR; + return; + } +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, + "%s%s%s", state->path, ": ", msg); +#else + strcpy(state->msg, state->path); + strcat(state->msg, ": "); + strcat(state->msg, msg); +#endif +} + +#ifndef INT_MAX +/* portably return maximum value for an int (when limits.h presumed not + available) -- we need to do this to cover cases where 2's complement not + used, since C standard permits 1's complement and sign-bit representations, + otherwise we could just use ((unsigned)-1) >> 1 */ +unsigned ZLIB_INTERNAL gz_intmax() +{ + unsigned p, q; + + p = 1; + do { + q = p; + p <<= 1; + p++; + } while (p > q); + return q >> 1; +} +#endif diff --git a/dependencies/zlib-1.2.11/gzread.c b/dependencies/zlib-1.2.11/gzread.c new file mode 100644 index 0000000..956b91e --- /dev/null +++ b/dependencies/zlib-1.2.11/gzread.c @@ -0,0 +1,654 @@ +/* gzread.c -- zlib functions for reading gzip files + * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +/* Local functions */ +local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *)); +local int gz_avail OF((gz_statep)); +local int gz_look OF((gz_statep)); +local int gz_decomp OF((gz_statep)); +local int gz_fetch OF((gz_statep)); +local int gz_skip OF((gz_statep, z_off64_t)); +local z_size_t gz_read OF((gz_statep, voidp, z_size_t)); + +/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from + state->fd, and update state->eof, state->err, and state->msg as appropriate. + This function needs to loop on read(), since read() is not guaranteed to + read the number of bytes requested, depending on the type of descriptor. */ +local int gz_load(state, buf, len, have) + gz_statep state; + unsigned char *buf; + unsigned len; + unsigned *have; +{ + int ret; + unsigned get, max = ((unsigned)-1 >> 2) + 1; + + *have = 0; + do { + get = len - *have; + if (get > max) + get = max; + ret = read(state->fd, buf + *have, get); + if (ret <= 0) + break; + *have += (unsigned)ret; + } while (*have < len); + if (ret < 0) { + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + if (ret == 0) + state->eof = 1; + return 0; +} + +/* Load up input buffer and set eof flag if last data loaded -- return -1 on + error, 0 otherwise. Note that the eof flag is set when the end of the input + file is reached, even though there may be unused data in the buffer. Once + that data has been used, no more attempts will be made to read the file. + If strm->avail_in != 0, then the current data is moved to the beginning of + the input buffer, and then the remainder of the buffer is loaded with the + available data from the input file. */ +local int gz_avail(state) + gz_statep state; +{ + unsigned got; + z_streamp strm = &(state->strm); + + if (state->err != Z_OK && state->err != Z_BUF_ERROR) + return -1; + if (state->eof == 0) { + if (strm->avail_in) { /* copy what's there to the start */ + unsigned char *p = state->in; + unsigned const char *q = strm->next_in; + unsigned n = strm->avail_in; + do { + *p++ = *q++; + } while (--n); + } + if (gz_load(state, state->in + strm->avail_in, + state->size - strm->avail_in, &got) == -1) + return -1; + strm->avail_in += got; + strm->next_in = state->in; + } + return 0; +} + +/* Look for gzip header, set up for inflate or copy. state->x.have must be 0. + If this is the first time in, allocate required memory. state->how will be + left unchanged if there is no more input data available, will be set to COPY + if there is no gzip header and direct copying will be performed, or it will + be set to GZIP for decompression. If direct copying, then leftover input + data from the input buffer will be copied to the output buffer. In that + case, all further file reads will be directly to either the output buffer or + a user buffer. If decompressing, the inflate state will be initialized. + gz_look() will return 0 on success or -1 on failure. */ +local int gz_look(state) + gz_statep state; +{ + z_streamp strm = &(state->strm); + + /* allocate read buffers and inflate memory */ + if (state->size == 0) { + /* allocate buffers */ + state->in = (unsigned char *)malloc(state->want); + state->out = (unsigned char *)malloc(state->want << 1); + if (state->in == NULL || state->out == NULL) { + free(state->out); + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + state->size = state->want; + + /* allocate inflate memory */ + state->strm.zalloc = Z_NULL; + state->strm.zfree = Z_NULL; + state->strm.opaque = Z_NULL; + state->strm.avail_in = 0; + state->strm.next_in = Z_NULL; + if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */ + free(state->out); + free(state->in); + state->size = 0; + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + } + + /* get at least the magic bytes in the input buffer */ + if (strm->avail_in < 2) { + if (gz_avail(state) == -1) + return -1; + if (strm->avail_in == 0) + return 0; + } + + /* look for gzip magic bytes -- if there, do gzip decoding (note: there is + a logical dilemma here when considering the case of a partially written + gzip file, to wit, if a single 31 byte is written, then we cannot tell + whether this is a single-byte file, or just a partially written gzip + file -- for here we assume that if a gzip file is being written, then + the header will be written in a single operation, so that reading a + single byte is sufficient indication that it is not a gzip file) */ + if (strm->avail_in > 1 && + strm->next_in[0] == 31 && strm->next_in[1] == 139) { + inflateReset(strm); + state->how = GZIP; + state->direct = 0; + return 0; + } + + /* no gzip header -- if we were decoding gzip before, then this is trailing + garbage. Ignore the trailing garbage and finish. */ + if (state->direct == 0) { + strm->avail_in = 0; + state->eof = 1; + state->x.have = 0; + return 0; + } + + /* doing raw i/o, copy any leftover input to output -- this assumes that + the output buffer is larger than the input buffer, which also assures + space for gzungetc() */ + state->x.next = state->out; + if (strm->avail_in) { + memcpy(state->x.next, strm->next_in, strm->avail_in); + state->x.have = strm->avail_in; + strm->avail_in = 0; + } + state->how = COPY; + state->direct = 1; + return 0; +} + +/* Decompress from input to the provided next_out and avail_out in the state. + On return, state->x.have and state->x.next point to the just decompressed + data. If the gzip stream completes, state->how is reset to LOOK to look for + the next gzip stream or raw data, once state->x.have is depleted. Returns 0 + on success, -1 on failure. */ +local int gz_decomp(state) + gz_statep state; +{ + int ret = Z_OK; + unsigned had; + z_streamp strm = &(state->strm); + + /* fill output buffer up to end of deflate stream */ + had = strm->avail_out; + do { + /* get more input for inflate() */ + if (strm->avail_in == 0 && gz_avail(state) == -1) + return -1; + if (strm->avail_in == 0) { + gz_error(state, Z_BUF_ERROR, "unexpected end of file"); + break; + } + + /* decompress and handle errors */ + ret = inflate(strm, Z_NO_FLUSH); + if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { + gz_error(state, Z_STREAM_ERROR, + "internal error: inflate stream corrupt"); + return -1; + } + if (ret == Z_MEM_ERROR) { + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ + gz_error(state, Z_DATA_ERROR, + strm->msg == NULL ? "compressed data error" : strm->msg); + return -1; + } + } while (strm->avail_out && ret != Z_STREAM_END); + + /* update available output */ + state->x.have = had - strm->avail_out; + state->x.next = strm->next_out - state->x.have; + + /* if the gzip stream completed successfully, look for another */ + if (ret == Z_STREAM_END) + state->how = LOOK; + + /* good decompression */ + return 0; +} + +/* Fetch data and put it in the output buffer. Assumes state->x.have is 0. + Data is either copied from the input file or decompressed from the input + file depending on state->how. If state->how is LOOK, then a gzip header is + looked for to determine whether to copy or decompress. Returns -1 on error, + otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the + end of the input file has been reached and all data has been processed. */ +local int gz_fetch(state) + gz_statep state; +{ + z_streamp strm = &(state->strm); + + do { + switch(state->how) { + case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */ + if (gz_look(state) == -1) + return -1; + if (state->how == LOOK) + return 0; + break; + case COPY: /* -> COPY */ + if (gz_load(state, state->out, state->size << 1, &(state->x.have)) + == -1) + return -1; + state->x.next = state->out; + return 0; + case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */ + strm->avail_out = state->size << 1; + strm->next_out = state->out; + if (gz_decomp(state) == -1) + return -1; + } + } while (state->x.have == 0 && (!state->eof || strm->avail_in)); + return 0; +} + +/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ +local int gz_skip(state, len) + gz_statep state; + z_off64_t len; +{ + unsigned n; + + /* skip over len bytes or reach end-of-file, whichever comes first */ + while (len) + /* skip over whatever is in output buffer */ + if (state->x.have) { + n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ? + (unsigned)len : state->x.have; + state->x.have -= n; + state->x.next += n; + state->x.pos += n; + len -= n; + } + + /* output buffer empty -- return if we're at the end of the input */ + else if (state->eof && state->strm.avail_in == 0) + break; + + /* need more data to skip -- load up output buffer */ + else { + /* get more output, looking for header if required */ + if (gz_fetch(state) == -1) + return -1; + } + return 0; +} + +/* Read len bytes into buf from file, or less than len up to the end of the + input. Return the number of bytes read. If zero is returned, either the + end of file was reached, or there was an error. state->err must be + consulted in that case to determine which. */ +local z_size_t gz_read(state, buf, len) + gz_statep state; + voidp buf; + z_size_t len; +{ + z_size_t got; + unsigned n; + + /* if len is zero, avoid unnecessary operations */ + if (len == 0) + return 0; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return 0; + } + + /* get len bytes to buf, or less than len if at the end */ + got = 0; + do { + /* set n to the maximum amount of len that fits in an unsigned int */ + n = -1; + if (n > len) + n = len; + + /* first just try copying data from the output buffer */ + if (state->x.have) { + if (state->x.have < n) + n = state->x.have; + memcpy(buf, state->x.next, n); + state->x.next += n; + state->x.have -= n; + } + + /* output buffer empty -- return if we're at the end of the input */ + else if (state->eof && state->strm.avail_in == 0) { + state->past = 1; /* tried to read past end */ + break; + } + + /* need output data -- for small len or new stream load up our output + buffer */ + else if (state->how == LOOK || n < (state->size << 1)) { + /* get more output, looking for header if required */ + if (gz_fetch(state) == -1) + return 0; + continue; /* no progress yet -- go back to copy above */ + /* the copy above assures that we will leave with space in the + output buffer, allowing at least one gzungetc() to succeed */ + } + + /* large len -- read directly into user buffer */ + else if (state->how == COPY) { /* read directly */ + if (gz_load(state, (unsigned char *)buf, n, &n) == -1) + return 0; + } + + /* large len -- decompress directly into user buffer */ + else { /* state->how == GZIP */ + state->strm.avail_out = n; + state->strm.next_out = (unsigned char *)buf; + if (gz_decomp(state) == -1) + return 0; + n = state->x.have; + state->x.have = 0; + } + + /* update progress */ + len -= n; + buf = (char *)buf + n; + got += n; + state->x.pos += n; + } while (len); + + /* return number of bytes read into user buffer */ + return got; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzread(file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return -1; + + /* since an int is returned, make sure len fits in one, otherwise return + with an error (this avoids a flaw in the interface) */ + if ((int)len < 0) { + gz_error(state, Z_STREAM_ERROR, "request does not fit in an int"); + return -1; + } + + /* read len or fewer bytes to buf */ + len = gz_read(state, buf, len); + + /* check for an error */ + if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR) + return -1; + + /* return the number of bytes read (this is assured to fit in an int) */ + return (int)len; +} + +/* -- see zlib.h -- */ +z_size_t ZEXPORT gzfread(buf, size, nitems, file) + voidp buf; + z_size_t size; + z_size_t nitems; + gzFile file; +{ + z_size_t len; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return 0; + + /* compute bytes to read -- error on overflow */ + len = nitems * size; + if (size && len / size != nitems) { + gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); + return 0; + } + + /* read len or fewer bytes to buf, return the number of full items read */ + return len ? gz_read(state, buf, len) / size : 0; +} + +/* -- see zlib.h -- */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +#else +# undef gzgetc +#endif +int ZEXPORT gzgetc(file) + gzFile file; +{ + int ret; + unsigned char buf[1]; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return -1; + + /* try output buffer (no need to check for skip request) */ + if (state->x.have) { + state->x.have--; + state->x.pos++; + return *(state->x.next)++; + } + + /* nothing there -- try gz_read() */ + ret = gz_read(state, buf, 1); + return ret < 1 ? -1 : buf[0]; +} + +int ZEXPORT gzgetc_(file) +gzFile file; +{ + return gzgetc(file); +} + +/* -- see zlib.h -- */ +int ZEXPORT gzungetc(c, file) + int c; + gzFile file; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return -1; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return -1; + } + + /* can't push EOF */ + if (c < 0) + return -1; + + /* if output buffer empty, put byte at end (allows more pushing) */ + if (state->x.have == 0) { + state->x.have = 1; + state->x.next = state->out + (state->size << 1) - 1; + state->x.next[0] = (unsigned char)c; + state->x.pos--; + state->past = 0; + return c; + } + + /* if no room, give up (must have already done a gzungetc()) */ + if (state->x.have == (state->size << 1)) { + gz_error(state, Z_DATA_ERROR, "out of room to push characters"); + return -1; + } + + /* slide output data if needed and insert byte before existing data */ + if (state->x.next == state->out) { + unsigned char *src = state->out + state->x.have; + unsigned char *dest = state->out + (state->size << 1); + while (src > state->out) + *--dest = *--src; + state->x.next = dest; + } + state->x.have++; + state->x.next--; + state->x.next[0] = (unsigned char)c; + state->x.pos--; + state->past = 0; + return c; +} + +/* -- see zlib.h -- */ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + unsigned left, n; + char *str; + unsigned char *eol; + gz_statep state; + + /* check parameters and get internal structure */ + if (file == NULL || buf == NULL || len < 1) + return NULL; + state = (gz_statep)file; + + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return NULL; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return NULL; + } + + /* copy output bytes up to new line or len - 1, whichever comes first -- + append a terminating zero to the string (we don't check for a zero in + the contents, let the user worry about that) */ + str = buf; + left = (unsigned)len - 1; + if (left) do { + /* assure that something is in the output buffer */ + if (state->x.have == 0 && gz_fetch(state) == -1) + return NULL; /* error */ + if (state->x.have == 0) { /* end of file */ + state->past = 1; /* read past end */ + break; /* return what we have */ + } + + /* look for end-of-line in current output buffer */ + n = state->x.have > left ? left : state->x.have; + eol = (unsigned char *)memchr(state->x.next, '\n', n); + if (eol != NULL) + n = (unsigned)(eol - state->x.next) + 1; + + /* copy through end-of-line, or remainder if not found */ + memcpy(buf, state->x.next, n); + state->x.have -= n; + state->x.next += n; + state->x.pos += n; + left -= n; + buf += n; + } while (left && eol == NULL); + + /* return terminated string, or if nothing, end of file */ + if (buf == str) + return NULL; + buf[0] = 0; + return str; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzdirect(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + + /* if the state is not known, but we can find out, then do so (this is + mainly for right after a gzopen() or gzdopen()) */ + if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) + (void)gz_look(state); + + /* return 1 if transparent, 0 if processing a gzip stream */ + return state->direct; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzclose_r(file) + gzFile file; +{ + int ret, err; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + + /* check that we're reading */ + if (state->mode != GZ_READ) + return Z_STREAM_ERROR; + + /* free memory and close file */ + if (state->size) { + inflateEnd(&(state->strm)); + free(state->out); + free(state->in); + } + err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK; + gz_error(state, Z_OK, NULL); + free(state->path); + ret = close(state->fd); + free(state); + return ret ? Z_ERRNO : err; +} diff --git a/dependencies/zlib-1.2.11/gzwrite.c b/dependencies/zlib-1.2.11/gzwrite.c new file mode 100644 index 0000000..c7b5651 --- /dev/null +++ b/dependencies/zlib-1.2.11/gzwrite.c @@ -0,0 +1,665 @@ +/* gzwrite.c -- zlib functions for writing gzip files + * Copyright (C) 2004-2017 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +/* Local functions */ +local int gz_init OF((gz_statep)); +local int gz_comp OF((gz_statep, int)); +local int gz_zero OF((gz_statep, z_off64_t)); +local z_size_t gz_write OF((gz_statep, voidpc, z_size_t)); + +/* Initialize state for writing a gzip file. Mark initialization by setting + state->size to non-zero. Return -1 on a memory allocation failure, or 0 on + success. */ +local int gz_init(state) + gz_statep state; +{ + int ret; + z_streamp strm = &(state->strm); + + /* allocate input buffer (double size for gzprintf) */ + state->in = (unsigned char *)malloc(state->want << 1); + if (state->in == NULL) { + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + + /* only need output buffer and deflate state if compressing */ + if (!state->direct) { + /* allocate output buffer */ + state->out = (unsigned char *)malloc(state->want); + if (state->out == NULL) { + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + + /* allocate deflate memory, set up for gzip compression */ + strm->zalloc = Z_NULL; + strm->zfree = Z_NULL; + strm->opaque = Z_NULL; + ret = deflateInit2(strm, state->level, Z_DEFLATED, + MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy); + if (ret != Z_OK) { + free(state->out); + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + strm->next_in = NULL; + } + + /* mark state as initialized */ + state->size = state->want; + + /* initialize write buffer if compressing */ + if (!state->direct) { + strm->avail_out = state->size; + strm->next_out = state->out; + state->x.next = strm->next_out; + } + return 0; +} + +/* Compress whatever is at avail_in and next_in and write to the output file. + Return -1 if there is an error writing to the output file or if gz_init() + fails to allocate memory, otherwise 0. flush is assumed to be a valid + deflate() flush value. If flush is Z_FINISH, then the deflate() state is + reset to start a new gzip stream. If gz->direct is true, then simply write + to the output file without compressing, and ignore flush. */ +local int gz_comp(state, flush) + gz_statep state; + int flush; +{ + int ret, writ; + unsigned have, put, max = ((unsigned)-1 >> 2) + 1; + z_streamp strm = &(state->strm); + + /* allocate memory if this is the first time through */ + if (state->size == 0 && gz_init(state) == -1) + return -1; + + /* write directly if requested */ + if (state->direct) { + while (strm->avail_in) { + put = strm->avail_in > max ? max : strm->avail_in; + writ = write(state->fd, strm->next_in, put); + if (writ < 0) { + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + strm->avail_in -= (unsigned)writ; + strm->next_in += writ; + } + return 0; + } + + /* run deflate() on provided input until it produces no more output */ + ret = Z_OK; + do { + /* write out current buffer contents if full, or if flushing, but if + doing Z_FINISH then don't write until we get to Z_STREAM_END */ + if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && + (flush != Z_FINISH || ret == Z_STREAM_END))) { + while (strm->next_out > state->x.next) { + put = strm->next_out - state->x.next > (int)max ? max : + (unsigned)(strm->next_out - state->x.next); + writ = write(state->fd, state->x.next, put); + if (writ < 0) { + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + state->x.next += writ; + } + if (strm->avail_out == 0) { + strm->avail_out = state->size; + strm->next_out = state->out; + state->x.next = state->out; + } + } + + /* compress */ + have = strm->avail_out; + ret = deflate(strm, flush); + if (ret == Z_STREAM_ERROR) { + gz_error(state, Z_STREAM_ERROR, + "internal error: deflate stream corrupt"); + return -1; + } + have -= strm->avail_out; + } while (have); + + /* if that completed a deflate stream, allow another to start */ + if (flush == Z_FINISH) + deflateReset(strm); + + /* all done, no errors */ + return 0; +} + +/* Compress len zeros to output. Return -1 on a write error or memory + allocation failure by gz_comp(), or 0 on success. */ +local int gz_zero(state, len) + gz_statep state; + z_off64_t len; +{ + int first; + unsigned n; + z_streamp strm = &(state->strm); + + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return -1; + + /* compress len zeros (len guaranteed > 0) */ + first = 1; + while (len) { + n = GT_OFF(state->size) || (z_off64_t)state->size > len ? + (unsigned)len : state->size; + if (first) { + memset(state->in, 0, n); + first = 0; + } + strm->avail_in = n; + strm->next_in = state->in; + state->x.pos += n; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return -1; + len -= n; + } + return 0; +} + +/* Write len bytes from buf to file. Return the number of bytes written. If + the returned value is less than len, then there was an error. */ +local z_size_t gz_write(state, buf, len) + gz_statep state; + voidpc buf; + z_size_t len; +{ + z_size_t put = len; + + /* if len is zero, avoid unnecessary operations */ + if (len == 0) + return 0; + + /* allocate memory if this is the first time through */ + if (state->size == 0 && gz_init(state) == -1) + return 0; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return 0; + } + + /* for small len, copy to input buffer, otherwise compress directly */ + if (len < state->size) { + /* copy to input buffer, compress when full */ + do { + unsigned have, copy; + + if (state->strm.avail_in == 0) + state->strm.next_in = state->in; + have = (unsigned)((state->strm.next_in + state->strm.avail_in) - + state->in); + copy = state->size - have; + if (copy > len) + copy = len; + memcpy(state->in + have, buf, copy); + state->strm.avail_in += copy; + state->x.pos += copy; + buf = (const char *)buf + copy; + len -= copy; + if (len && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + } while (len); + } + else { + /* consume whatever's left in the input buffer */ + if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + + /* directly compress user buffer to file */ + state->strm.next_in = (z_const Bytef *)buf; + do { + unsigned n = (unsigned)-1; + if (n > len) + n = len; + state->strm.avail_in = n; + state->x.pos += n; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + len -= n; + } while (len); + } + + /* input was all buffered or compressed */ + return put; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzwrite(file, buf, len) + gzFile file; + voidpc buf; + unsigned len; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* since an int is returned, make sure len fits in one, otherwise return + with an error (this avoids a flaw in the interface) */ + if ((int)len < 0) { + gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); + return 0; + } + + /* write len bytes from buf (the return value will fit in an int) */ + return (int)gz_write(state, buf, len); +} + +/* -- see zlib.h -- */ +z_size_t ZEXPORT gzfwrite(buf, size, nitems, file) + voidpc buf; + z_size_t size; + z_size_t nitems; + gzFile file; +{ + z_size_t len; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* compute bytes to read -- error on overflow */ + len = nitems * size; + if (size && len / size != nitems) { + gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); + return 0; + } + + /* write len bytes to buf, return the number of full items written */ + return len ? gz_write(state, buf, len) / size : 0; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned have; + unsigned char buf[1]; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return -1; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return -1; + } + + /* try writing to input buffer for speed (state->size == 0 if buffer not + initialized) */ + if (state->size) { + if (strm->avail_in == 0) + strm->next_in = state->in; + have = (unsigned)((strm->next_in + strm->avail_in) - state->in); + if (have < state->size) { + state->in[have] = (unsigned char)c; + strm->avail_in++; + state->x.pos++; + return c & 0xff; + } + } + + /* no room in buffer or not initialized, use gz_write() */ + buf[0] = (unsigned char)c; + if (gz_write(state, buf, 1) != 1) + return -1; + return c & 0xff; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzputs(file, str) + gzFile file; + const char *str; +{ + int ret; + z_size_t len; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return -1; + + /* write string */ + len = strlen(str); + ret = gz_write(state, str, len); + return ret == 0 && len != 0 ? -1 : ret; +} + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +#include + +/* -- see zlib.h -- */ +int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) +{ + int len; + unsigned left; + char *next; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return Z_STREAM_ERROR; + + /* make sure we have some buffer space */ + if (state->size == 0 && gz_init(state) == -1) + return state->err; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return state->err; + } + + /* do the printf() into the input buffer, put length in len -- the input + buffer is double-sized just for this function, so there is guaranteed to + be state->size bytes available after the current contents */ + if (strm->avail_in == 0) + strm->next_in = state->in; + next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in); + next[state->size - 1] = 0; +#ifdef NO_vsnprintf +# ifdef HAS_vsprintf_void + (void)vsprintf(next, format, va); + for (len = 0; len < state->size; len++) + if (next[len] == 0) break; +# else + len = vsprintf(next, format, va); +# endif +#else +# ifdef HAS_vsnprintf_void + (void)vsnprintf(next, state->size, format, va); + len = strlen(next); +# else + len = vsnprintf(next, state->size, format, va); +# endif +#endif + + /* check that printf() results fit in buffer */ + if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0) + return 0; + + /* update buffer and position, compress first half if past that */ + strm->avail_in += (unsigned)len; + state->x.pos += len; + if (strm->avail_in >= state->size) { + left = strm->avail_in - state->size; + strm->avail_in = state->size; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return state->err; + memcpy(state->in, state->in + state->size, left); + strm->next_in = state->in; + strm->avail_in = left; + } + return len; +} + +int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) +{ + va_list va; + int ret; + + va_start(va, format); + ret = gzvprintf(file, format, va); + va_end(va); + return ret; +} + +#else /* !STDC && !Z_HAVE_STDARG_H */ + +/* -- see zlib.h -- */ +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + unsigned len, left; + char *next; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that can really pass pointer in ints */ + if (sizeof(int) != sizeof(void *)) + return Z_STREAM_ERROR; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return Z_STREAM_ERROR; + + /* make sure we have some buffer space */ + if (state->size == 0 && gz_init(state) == -1) + return state->error; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return state->error; + } + + /* do the printf() into the input buffer, put length in len -- the input + buffer is double-sized just for this function, so there is guaranteed to + be state->size bytes available after the current contents */ + if (strm->avail_in == 0) + strm->next_in = state->in; + next = (char *)(strm->next_in + strm->avail_in); + next[state->size - 1] = 0; +#ifdef NO_snprintf +# ifdef HAS_sprintf_void + sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, + a13, a14, a15, a16, a17, a18, a19, a20); + for (len = 0; len < size; len++) + if (next[len] == 0) + break; +# else + len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, + a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#else +# ifdef HAS_snprintf_void + snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = strlen(next); +# else + len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#endif + + /* check that printf() results fit in buffer */ + if (len == 0 || len >= state->size || next[state->size - 1] != 0) + return 0; + + /* update buffer and position, compress first half if past that */ + strm->avail_in += len; + state->x.pos += len; + if (strm->avail_in >= state->size) { + left = strm->avail_in - state->size; + strm->avail_in = state->size; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return state->err; + memcpy(state->in, state->in + state->size, left); + strm->next_in = state->in; + strm->avail_in = left; + } + return (int)len; +} + +#endif + +/* -- see zlib.h -- */ +int ZEXPORT gzflush(file, flush) + gzFile file; + int flush; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return Z_STREAM_ERROR; + + /* check flush parameter */ + if (flush < 0 || flush > Z_FINISH) + return Z_STREAM_ERROR; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return state->err; + } + + /* compress remaining data with requested flush */ + (void)gz_comp(state, flush); + return state->err; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzsetparams(file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return Z_STREAM_ERROR; + + /* if no change is requested, then do nothing */ + if (level == state->level && strategy == state->strategy) + return Z_OK; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return state->err; + } + + /* change compression parameters for subsequent input */ + if (state->size) { + /* flush previous input with previous parameters before changing */ + if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1) + return state->err; + deflateParams(strm, level, strategy); + } + state->level = level; + state->strategy = strategy; + return Z_OK; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzclose_w(file) + gzFile file; +{ + int ret = Z_OK; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + + /* check that we're writing */ + if (state->mode != GZ_WRITE) + return Z_STREAM_ERROR; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + ret = state->err; + } + + /* flush, free memory, and close file */ + if (gz_comp(state, Z_FINISH) == -1) + ret = state->err; + if (state->size) { + if (!state->direct) { + (void)deflateEnd(&(state->strm)); + free(state->out); + } + free(state->in); + } + gz_error(state, Z_OK, NULL); + free(state->path); + if (close(state->fd) == -1) + ret = Z_ERRNO; + free(state); + return ret; +} diff --git a/dependencies/zlib-1.2.11/infback.c b/dependencies/zlib-1.2.11/infback.c new file mode 100644 index 0000000..59679ec --- /dev/null +++ b/dependencies/zlib-1.2.11/infback.c @@ -0,0 +1,640 @@ +/* infback.c -- inflate using a call-back interface + * Copyright (C) 1995-2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + This code is largely copied from inflate.c. Normally either infback.o or + inflate.o would be linked into an application--not both. The interface + with inffast.c is retained so that optimized assembler-coded versions of + inflate_fast() can be used with either inflate.c or infback.c. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); + +/* + strm provides memory allocation functions in zalloc and zfree, or + Z_NULL to use the library memory allocation functions. + + windowBits is in the range 8..15, and window is a user-supplied + window and output buffer that is 2**windowBits bytes. + */ +int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) +z_streamp strm; +int windowBits; +unsigned char FAR *window; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL || window == Z_NULL || + windowBits < 8 || windowBits > 15) + return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; +#endif + } + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif + state = (struct inflate_state FAR *)ZALLOC(strm, 1, + sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->dmax = 32768U; + state->wbits = (uInt)windowBits; + state->wsize = 1U << windowBits; + state->window = window; + state->wnext = 0; + state->whave = 0; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +/* Macros for inflateBack(): */ + +/* Load returned state from inflate_fast() */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Set state from registers for inflate_fast() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Assure that some input is available. If input is requested, but denied, + then return a Z_BUF_ERROR from inflateBack(). */ +#define PULL() \ + do { \ + if (have == 0) { \ + have = in(in_desc, &next); \ + if (have == 0) { \ + next = Z_NULL; \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflateBack() + with an error if there is no input available. */ +#define PULLBYTE() \ + do { \ + PULL(); \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflateBack() with + an error. */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Assure that some output space is available, by writing out the window + if it's full. If the write fails, return from inflateBack() with a + Z_BUF_ERROR. */ +#define ROOM() \ + do { \ + if (left == 0) { \ + put = state->window; \ + left = state->wsize; \ + state->whave = left; \ + if (out(out_desc, put, left)) { \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* + strm provides the memory allocation functions and window buffer on input, + and provides information on the unused input on return. For Z_DATA_ERROR + returns, strm will also provide an error message. + + in() and out() are the call-back input and output functions. When + inflateBack() needs more input, it calls in(). When inflateBack() has + filled the window with output, or when it completes with data in the + window, it calls out() to write out the data. The application must not + change the provided input until in() is called again or inflateBack() + returns. The application must not change the window/output buffer until + inflateBack() returns. + + in() and out() are called with a descriptor parameter provided in the + inflateBack() call. This parameter can be a structure that provides the + information required to do the read or write, as well as accumulated + information on the input and output such as totals and check values. + + in() should return zero on failure. out() should return non-zero on + failure. If either in() or out() fails, than inflateBack() returns a + Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it + was in() or out() that caused in the error. Otherwise, inflateBack() + returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format + error, or Z_MEM_ERROR if it could not allocate memory for the state. + inflateBack() can also return Z_STREAM_ERROR if the input parameters + are not correct, i.e. strm is Z_NULL or the state was not initialized. + */ +int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) +z_streamp strm; +in_func in; +void FAR *in_desc; +out_func out; +void FAR *out_desc; +{ + struct inflate_state FAR *state; + z_const unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* Check that the strm exists and that the state was initialized */ + if (strm == Z_NULL || strm->state == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* Reset the state */ + strm->msg = Z_NULL; + state->mode = TYPE; + state->last = 0; + state->whave = 0; + next = strm->next_in; + have = next != Z_NULL ? strm->avail_in : 0; + hold = 0; + bits = 0; + put = state->window; + left = state->wsize; + + /* Inflate until end of block marked as last */ + for (;;) + switch (state->mode) { + case TYPE: + /* determine and dispatch block type */ + if (state->last) { + BYTEBITS(); + state->mode = DONE; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + + /* copy stored block from input to output */ + while (state->length != 0) { + copy = state->length; + PULL(); + ROOM(); + if (copy > have) copy = have; + if (copy > left) copy = left; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + + /* get code length code lengths (not a typo) */ + state->have = 0; + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + + /* get length and distance code code lengths */ + state->have = 0; + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = (unsigned)(state->lens[state->have - 1]); + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + + case LEN: + /* use inflate_fast() if we have enough input and output */ + if (have >= 6 && left >= 258) { + RESTORE(); + if (state->whave < state->wsize) + state->whave = state->wsize - left; + inflate_fast(strm, state->wsize); + LOAD(); + break; + } + + /* get a literal, length, or end-of-block code */ + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(here.bits); + state->length = (unsigned)here.val; + + /* process literal */ + if (here.op == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + ROOM(); + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + } + + /* process end of block */ + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + + /* invalid code */ + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + + /* length code -- get extra bits, if any */ + state->extra = (unsigned)(here.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + + /* get distance code */ + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(here.bits); + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + + /* get distance extra bits, if any */ + state->extra = (unsigned)(here.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->wsize - (state->whave < state->wsize ? + left : 0)) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + + /* copy match from window to output */ + do { + ROOM(); + copy = state->wsize - state->offset; + if (copy < left) { + from = put + copy; + copy = left - copy; + } + else { + from = put - state->offset; + copy = left; + } + if (copy > state->length) copy = state->length; + state->length -= copy; + left -= copy; + do { + *put++ = *from++; + } while (--copy); + } while (state->length != 0); + break; + + case DONE: + /* inflate stream terminated properly -- write leftover output */ + ret = Z_STREAM_END; + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left)) + ret = Z_BUF_ERROR; + } + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + default: /* can't happen, but makes compilers happy */ + ret = Z_STREAM_ERROR; + goto inf_leave; + } + + /* Return unused input */ + inf_leave: + strm->next_in = next; + strm->avail_in = have; + return ret; +} + +int ZEXPORT inflateBackEnd(strm) +z_streamp strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} diff --git a/dependencies/zlib-1.2.11/inffast.c b/dependencies/zlib-1.2.11/inffast.c new file mode 100644 index 0000000..0dbd1db --- /dev/null +++ b/dependencies/zlib-1.2.11/inffast.c @@ -0,0 +1,323 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2017 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef ASMINF +# pragma message("Assembler code may have bugs -- use at your own risk") +#else + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void ZLIB_INTERNAL inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + z_const unsigned char FAR *in; /* local strm->next_in */ + z_const unsigned char FAR *last; /* have enough input while in < last */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code here; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in; + last = in + (strm->avail_in - 5); + out = strm->next_out; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + wnext = state->wnext; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + here = lcode[hold & lmask]; + dolen: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op == 0) { /* literal */ + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + *out++ = (unsigned char)(here.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + here = dcode[hold & dmask]; + dodist: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state->sane) { + strm->msg = + (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + if (len <= op - whave) { + do { + *out++ = 0; + } while (--len); + continue; + } + len -= op - whave; + do { + *out++ = 0; + } while (--op > whave); + if (op == 0) { + from = out - dist; + do { + *out++ = *from++; + } while (--len); + continue; + } +#endif + } + from = window; + if (wnext == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + *out++ = *from++; + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + *out++ = *from++; + } while (--op); + from = window; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + *out++ = *from++; + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + *out++ = *from++; + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + *out++ = *from++; + *out++ = *from++; + *out++ = *from++; + len -= 3; + } + if (len) { + *out++ = *from++; + if (len > 1) + *out++ = *from++; + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + *out++ = *from++; + *out++ = *from++; + *out++ = *from++; + len -= 3; + } while (len > 2); + if (len) { + *out++ = *from++; + if (len > 1) + *out++ = *from++; + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + here = dcode[here.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + here = lcode[here.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in; + strm->next_out = out; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and wnext == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/dependencies/zlib-1.2.11/inffast.h b/dependencies/zlib-1.2.11/inffast.h new file mode 100644 index 0000000..e5c1aa4 --- /dev/null +++ b/dependencies/zlib-1.2.11/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/dependencies/zlib-1.2.11/inffixed.h b/dependencies/zlib-1.2.11/inffixed.h new file mode 100644 index 0000000..d628327 --- /dev/null +++ b/dependencies/zlib-1.2.11/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. + It is part of the implementation of this library and is + subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/dependencies/zlib-1.2.11/inflate.c b/dependencies/zlib-1.2.11/inflate.c new file mode 100644 index 0000000..ac333e8 --- /dev/null +++ b/dependencies/zlib-1.2.11/inflate.c @@ -0,0 +1,1561 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common wnext == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local int inflateStateCheck OF((z_streamp strm)); +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, + unsigned copy)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, + unsigned len)); + +local int inflateStateCheck(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) + return 1; + state = (struct inflate_state FAR *)strm->state; + if (state == Z_NULL || state->strm != strm || + state->mode < HEAD || state->mode > SYNC) + return 1; + return 0; +} + +int ZEXPORT inflateResetKeep(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + if (state->wrap) /* to support ill-conceived Java test suite */ + strm->adler = state->wrap & 1; + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + state->sane = 1; + state->back = -1; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + state->wsize = 0; + state->whave = 0; + state->wnext = 0; + return inflateResetKeep(strm); +} + +int ZEXPORT inflateReset2(strm, windowBits) +z_streamp strm; +int windowBits; +{ + int wrap; + struct inflate_state FAR *state; + + /* get the state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 5; +#ifdef GUNZIP + if (windowBits < 48) + windowBits &= 15; +#endif + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) + return Z_STREAM_ERROR; + if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { + ZFREE(strm, state->window); + state->window = Z_NULL; + } + + /* update state and reset the rest of it */ + state->wrap = wrap; + state->wbits = (unsigned)windowBits; + return inflateReset(strm); +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + int ret; + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; +#endif + } + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->strm = strm; + state->window = Z_NULL; + state->mode = HEAD; /* to pass state test in inflateReset2() */ + ret = inflateReset2(strm, windowBits); + if (ret != Z_OK) { + ZFREE(strm, state); + strm->state = Z_NULL; + } + return ret; +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +int ZEXPORT inflatePrime(strm, bits, value) +z_streamp strm; +int bits; +int value; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits < 0) { + state->hold = 0; + state->bits = 0; + return Z_OK; + } + if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += (unsigned)value << state->bits; + state->bits += (uInt)bits; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, + state.lencode[low].bits, state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, end, copy) +z_streamp strm; +const Bytef *end; +unsigned copy; +{ + struct inflate_state FAR *state; + unsigned dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->wnext = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + if (copy >= state->wsize) { + zmemcpy(state->window, end - state->wsize, state->wsize); + state->wnext = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->wnext; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->wnext, end - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, end - copy, copy); + state->wnext = copy; + state->whave = state->wsize; + } + else { + state->wnext += dist; + if (state->wnext == state->wsize) state->wnext = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + z_const unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (inflateStateCheck(strm) || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + if (state->wbits == 0) + state->wbits = 15; + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (state->wbits == 0) + state->wbits = len; + if (len > 15 || len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = (Bytef)len; + } while (len && copy < have); + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = (Bytef)len; + } while (len && copy < have); + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if ((state->wrap & 4) && hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = ZSWAP32(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN_; /* decode codes */ + if (flush == Z_TREES) { + DROPBITS(2); + goto inf_leave; + } + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY_; + if (flush == Z_TREES) goto inf_leave; + case COPY_: + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (const code FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (const code FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (const code FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN_; + if (flush == Z_TREES) goto inf_leave; + case LEN_: + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + if (state->mode == TYPE) + state->back = -1; + break; + } + state->back = 0; + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + state->length = (unsigned)here.val; + if ((int)(here.op) == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + state->mode = LIT; + break; + } + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->back = -1; + state->mode = TYPE; + break; + } + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(here.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->was = state->length; + state->mode = DIST; + case DIST: + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + state->extra = (unsigned)(here.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->whave) { + if (state->sane) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + Trace((stderr, "inflate.c too far\n")); + copy -= state->whave; + if (copy > state->length) copy = state->length; + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = 0; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; +#endif + } + if (copy > state->wnext) { + copy -= state->wnext; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->wnext - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if ((state->wrap & 4) && out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if ((state->wrap & 4) && ( +#ifdef GUNZIP + state->flags ? hold : +#endif + ZSWAP32(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (out != strm->avail_out && state->mode < BAD && + (state->mode < CHECK || flush != Z_FINISH))) + if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if ((state->wrap & 4) && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = (int)state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0) + + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (inflateStateCheck(strm)) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength) +z_streamp strm; +Bytef *dictionary; +uInt *dictLength; +{ + struct inflate_state FAR *state; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* copy dictionary */ + if (state->whave && dictionary != Z_NULL) { + zmemcpy(dictionary, state->window + state->wnext, + state->whave - state->wnext); + zmemcpy(dictionary + state->whave - state->wnext, + state->window, state->wnext); + } + if (dictLength != Z_NULL) + *dictLength = state->whave; + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long dictid; + int ret; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary identifier */ + if (state->mode == DICT) { + dictid = adler32(0L, Z_NULL, 0); + dictid = adler32(dictid, dictionary, dictLength); + if (dictid != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + ret = updatewindow(strm, dictionary + dictLength, dictLength); + if (ret) { + state->mode = MEM; + return Z_MEM_ERROR; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader(strm, head) +z_streamp strm; +gz_headerp head; +{ + struct inflate_state FAR *state; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +const unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (inflateStateCheck(source) || dest == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); + zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); + copy->strm = dest; + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} + +int ZEXPORT inflateUndermine(strm, subvert) +z_streamp strm; +int subvert; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + state->sane = !subvert; + return Z_OK; +#else + (void)subvert; + state->sane = 1; + return Z_DATA_ERROR; +#endif +} + +int ZEXPORT inflateValidate(strm, check) +z_streamp strm; +int check; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (check) + state->wrap |= 4; + else + state->wrap &= ~4; + return Z_OK; +} + +long ZEXPORT inflateMark(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) + return -(1L << 16); + state = (struct inflate_state FAR *)strm->state; + return (long)(((unsigned long)((long)state->back)) << 16) + + (state->mode == COPY ? state->length : + (state->mode == MATCH ? state->was - state->length : 0)); +} + +unsigned long ZEXPORT inflateCodesUsed(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (inflateStateCheck(strm)) return (unsigned long)-1; + state = (struct inflate_state FAR *)strm->state; + return (unsigned long)(state->next - state->codes); +} diff --git a/dependencies/zlib-1.2.11/inflate.h b/dependencies/zlib-1.2.11/inflate.h new file mode 100644 index 0000000..a46cce6 --- /dev/null +++ b/dependencies/zlib-1.2.11/inflate.h @@ -0,0 +1,125 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD = 16180, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY_, /* i/o: same as COPY below, but only first time in */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN_, /* i: same as LEN below, but only first time in */ + LEN, /* i: waiting for length/lit/eob code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to BAD or MEM on error -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) or (raw) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> + HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + (raw) -> TYPEDO + Read deflate blocks: + TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK + STORED -> COPY_ -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN_ + LEN_ -> LEN + Read deflate codes in fixed or dynamic block: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* State maintained between inflate() calls -- approximately 7K bytes, not + including the allocated sliding window, which is up to 32K bytes. */ +struct inflate_state { + z_streamp strm; /* pointer back to this zlib stream */ + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip, + bit 2 true to validate check value */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ + int sane; /* if false, allow invalid distance too far */ + int back; /* bits back of last unprocessed length/lit */ + unsigned was; /* initial length of match */ +}; diff --git a/dependencies/zlib-1.2.11/inftrees.c b/dependencies/zlib-1.2.11/inftrees.c new file mode 100644 index 0000000..2ea08fc --- /dev/null +++ b/dependencies/zlib-1.2.11/inftrees.c @@ -0,0 +1,304 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2017 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.11 Copyright 1995-2017 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code here; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + unsigned match; /* use base and extra for symbol >= match */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 77, 202}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)1; + here.val = (unsigned short)0; + *(*table)++ = here; /* make a table to force an error */ + *(*table)++ = here; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + match = 20; + break; + case LENS: + base = lbase; + extra = lext; + match = 257; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + match = 0; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here.bits = (unsigned char)(len - drop); + if (work[sym] + 1U < match) { + here.op = (unsigned char)0; + here.val = work[sym]; + } + else if (work[sym] >= match) { + here.op = (unsigned char)(extra[work[sym] - match]); + here.val = base[work[sym] - match]; + } + else { + here.op = (unsigned char)(32 + 64); /* end of block */ + here.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = here; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* fill in remaining table entry if code is incomplete (guaranteed to have + at most one remaining entry, since if the code is incomplete, the + maximum code length that was allowed to get this far is one bit) */ + if (huff != 0) { + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)(len - drop); + here.val = (unsigned short)0; + next[huff] = here; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/dependencies/zlib-1.2.11/inftrees.h b/dependencies/zlib-1.2.11/inftrees.h new file mode 100644 index 0000000..baa53a0 --- /dev/null +++ b/dependencies/zlib-1.2.11/inftrees.h @@ -0,0 +1,62 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of the dynamic table. The maximum number of code structures is + 1444, which is the sum of 852 for literal/length codes and 592 for distance + codes. These values were found by exhaustive searches using the program + examples/enough.c found in the zlib distribtution. The arguments to that + program are the number of symbols, the initial root table size, and the + maximum bit length of a code. "enough 286 9 15" for literal/length codes + returns returns 852, and "enough 30 6 15" for distance codes returns 592. + The initial root table size (9 or 6) is found in the fifth argument of the + inflate_table() calls in inflate.c and infback.c. If the root table size is + changed, then these maximum sizes would be need to be recalculated and + updated. */ +#define ENOUGH_LENS 852 +#define ENOUGH_DISTS 592 +#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) + +/* Type of code to build for inflate_table() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/dependencies/zlib-1.2.11/make_vms.com b/dependencies/zlib-1.2.11/make_vms.com new file mode 100644 index 0000000..65e9d0c --- /dev/null +++ b/dependencies/zlib-1.2.11/make_vms.com @@ -0,0 +1,867 @@ +$! make libz under VMS written by +$! Martin P.J. Zinser +$! +$! In case of problems with the install you might contact me at +$! zinser@zinser.no-ip.info(preferred) or +$! martin.zinser@eurexchange.com (work) +$! +$! Make procedure history for Zlib +$! +$!------------------------------------------------------------------------------ +$! Version history +$! 0.01 20060120 First version to receive a number +$! 0.02 20061008 Adapt to new Makefile.in +$! 0.03 20091224 Add support for large file check +$! 0.04 20100110 Add new gzclose, gzlib, gzread, gzwrite +$! 0.05 20100221 Exchange zlibdefs.h by zconf.h.in +$! 0.06 20120111 Fix missing amiss_err, update zconf_h.in, fix new exmples +$! subdir path, update module search in makefile.in +$! 0.07 20120115 Triggered by work done by Alexey Chupahin completly redesigned +$! shared image creation +$! 0.08 20120219 Make it work on VAX again, pre-load missing symbols to shared +$! image +$! 0.09 20120305 SMS. P1 sets builder ("MMK", "MMS", " " (built-in)). +$! "" -> automatic, preference: MMK, MMS, built-in. +$! +$ on error then goto err_exit +$! +$ true = 1 +$ false = 0 +$ tmpnam = "temp_" + f$getjpi("","pid") +$ tt = tmpnam + ".txt" +$ tc = tmpnam + ".c" +$ th = tmpnam + ".h" +$ define/nolog tconfig 'th' +$ its_decc = false +$ its_vaxc = false +$ its_gnuc = false +$ s_case = False +$! +$! Setup variables holding "config" information +$! +$ Make = "''p1'" +$ name = "Zlib" +$ version = "?.?.?" +$ v_string = "ZLIB_VERSION" +$ v_file = "zlib.h" +$ ccopt = "/include = []" +$ lopts = "" +$ dnsrl = "" +$ aconf_in_file = "zconf.h.in#zconf.h_in#zconf_h.in" +$ conf_check_string = "" +$ linkonly = false +$ optfile = name + ".opt" +$ mapfile = name + ".map" +$ libdefs = "" +$ vax = f$getsyi("HW_MODEL").lt.1024 +$ axp = f$getsyi("HW_MODEL").ge.1024 .and. f$getsyi("HW_MODEL").lt.4096 +$ ia64 = f$getsyi("HW_MODEL").ge.4096 +$! +$! 2012-03-05 SMS. +$! Why is this needed? And if it is needed, why not simply ".not. vax"? +$! +$!!! if axp .or. ia64 then set proc/parse=extended +$! +$ whoami = f$parse(f$environment("Procedure"),,,,"NO_CONCEAL") +$ mydef = F$parse(whoami,,,"DEVICE") +$ mydir = f$parse(whoami,,,"DIRECTORY") - "][" +$ myproc = f$parse(whoami,,,"Name") + f$parse(whoami,,,"type") +$! +$! Check for MMK/MMS +$! +$ if (Make .eqs. "") +$ then +$ If F$Search ("Sys$System:MMS.EXE") .nes. "" Then Make = "MMS" +$ If F$Type (MMK) .eqs. "STRING" Then Make = "MMK" +$ else +$ Make = f$edit( Make, "trim") +$ endif +$! +$ gosub find_version +$! +$ open/write topt tmp.opt +$ open/write optf 'optfile' +$! +$ gosub check_opts +$! +$! Look for the compiler used +$! +$ gosub check_compiler +$ close topt +$ close optf +$! +$ if its_decc +$ then +$ ccopt = "/prefix=all" + ccopt +$ if f$trnlnm("SYS") .eqs. "" +$ then +$ if axp +$ then +$ define sys sys$library: +$ else +$ ccopt = "/decc" + ccopt +$ define sys decc$library_include: +$ endif +$ endif +$! +$! 2012-03-05 SMS. +$! Why /NAMES = AS_IS? Why not simply ".not. vax"? And why not on VAX? +$! +$ if axp .or. ia64 +$ then +$ ccopt = ccopt + "/name=as_is/opt=(inline=speed)" +$ s_case = true +$ endif +$ endif +$ if its_vaxc .or. its_gnuc +$ then +$ if f$trnlnm("SYS").eqs."" then define sys sys$library: +$ endif +$! +$! Build a fake configure input header +$! +$ open/write conf_hin config.hin +$ write conf_hin "#undef _LARGEFILE64_SOURCE" +$ close conf_hin +$! +$! +$ i = 0 +$FIND_ACONF: +$ fname = f$element(i,"#",aconf_in_file) +$ if fname .eqs. "#" then goto AMISS_ERR +$ if f$search(fname) .eqs. "" +$ then +$ i = i + 1 +$ goto find_aconf +$ endif +$ open/read/err=aconf_err aconf_in 'fname' +$ open/write aconf zconf.h +$ACONF_LOOP: +$ read/end_of_file=aconf_exit aconf_in line +$ work = f$edit(line, "compress,trim") +$ if f$extract(0,6,work) .nes. "#undef" +$ then +$ if f$extract(0,12,work) .nes. "#cmakedefine" +$ then +$ write aconf line +$ endif +$ else +$ cdef = f$element(1," ",work) +$ gosub check_config +$ endif +$ goto aconf_loop +$ACONF_EXIT: +$ write aconf "" +$ write aconf "/* VMS specifics added by make_vms.com: */" +$ write aconf "#define VMS 1" +$ write aconf "#include " +$ write aconf "#include " +$ write aconf "#ifdef _LARGEFILE" +$ write aconf "# define off64_t __off64_t" +$ write aconf "# define fopen64 fopen" +$ write aconf "# define fseeko64 fseeko" +$ write aconf "# define lseek64 lseek" +$ write aconf "# define ftello64 ftell" +$ write aconf "#endif" +$ write aconf "#if !defined( __VAX) && (__CRTL_VER >= 70312000)" +$ write aconf "# define HAVE_VSNPRINTF" +$ write aconf "#endif" +$ close aconf_in +$ close aconf +$ if f$search("''th'") .nes. "" then delete 'th';* +$! Build the thing plain or with mms +$! +$ write sys$output "Compiling Zlib sources ..." +$ if make.eqs."" +$ then +$ if (f$search( "example.obj;*") .nes. "") then delete example.obj;* +$ if (f$search( "minigzip.obj;*") .nes. "") then delete minigzip.obj;* +$ CALL MAKE adler32.OBJ "CC ''CCOPT' adler32" - + adler32.c zlib.h zconf.h +$ CALL MAKE compress.OBJ "CC ''CCOPT' compress" - + compress.c zlib.h zconf.h +$ CALL MAKE crc32.OBJ "CC ''CCOPT' crc32" - + crc32.c zlib.h zconf.h +$ CALL MAKE deflate.OBJ "CC ''CCOPT' deflate" - + deflate.c deflate.h zutil.h zlib.h zconf.h +$ CALL MAKE gzclose.OBJ "CC ''CCOPT' gzclose" - + gzclose.c zutil.h zlib.h zconf.h +$ CALL MAKE gzlib.OBJ "CC ''CCOPT' gzlib" - + gzlib.c zutil.h zlib.h zconf.h +$ CALL MAKE gzread.OBJ "CC ''CCOPT' gzread" - + gzread.c zutil.h zlib.h zconf.h +$ CALL MAKE gzwrite.OBJ "CC ''CCOPT' gzwrite" - + gzwrite.c zutil.h zlib.h zconf.h +$ CALL MAKE infback.OBJ "CC ''CCOPT' infback" - + infback.c zutil.h inftrees.h inflate.h inffast.h inffixed.h +$ CALL MAKE inffast.OBJ "CC ''CCOPT' inffast" - + inffast.c zutil.h zlib.h zconf.h inffast.h +$ CALL MAKE inflate.OBJ "CC ''CCOPT' inflate" - + inflate.c zutil.h zlib.h zconf.h infblock.h +$ CALL MAKE inftrees.OBJ "CC ''CCOPT' inftrees" - + inftrees.c zutil.h zlib.h zconf.h inftrees.h +$ CALL MAKE trees.OBJ "CC ''CCOPT' trees" - + trees.c deflate.h zutil.h zlib.h zconf.h +$ CALL MAKE uncompr.OBJ "CC ''CCOPT' uncompr" - + uncompr.c zlib.h zconf.h +$ CALL MAKE zutil.OBJ "CC ''CCOPT' zutil" - + zutil.c zutil.h zlib.h zconf.h +$ write sys$output "Building Zlib ..." +$ CALL MAKE libz.OLB "lib/crea libz.olb *.obj" *.OBJ +$ write sys$output "Building example..." +$ CALL MAKE example.OBJ "CC ''CCOPT' [.test]example" - + [.test]example.c zlib.h zconf.h +$ call make example.exe "LINK example,libz.olb/lib" example.obj libz.olb +$ write sys$output "Building minigzip..." +$ CALL MAKE minigzip.OBJ "CC ''CCOPT' [.test]minigzip" - + [.test]minigzip.c zlib.h zconf.h +$ call make minigzip.exe - + "LINK minigzip,libz.olb/lib" - + minigzip.obj libz.olb +$ else +$ gosub crea_mms +$ write sys$output "Make ''name' ''version' with ''Make' " +$ 'make' +$ endif +$! +$! Create shareable image +$! +$ gosub crea_olist +$ write sys$output "Creating libzshr.exe" +$ call map_2_shopt 'mapfile' 'optfile' +$ LINK_'lopts'/SHARE=libzshr.exe modules.opt/opt,'optfile'/opt +$ write sys$output "Zlib build completed" +$ delete/nolog tmp.opt;* +$ exit +$AMISS_ERR: +$ write sys$output "No source for config.hin found." +$ write sys$output "Tried any of ''aconf_in_file'" +$ goto err_exit +$CC_ERR: +$ write sys$output "C compiler required to build ''name'" +$ goto err_exit +$ERR_EXIT: +$ set message/facil/ident/sever/text +$ close/nolog optf +$ close/nolog topt +$ close/nolog aconf_in +$ close/nolog aconf +$ close/nolog out +$ close/nolog min +$ close/nolog mod +$ close/nolog h_in +$ write sys$output "Exiting..." +$ exit 2 +$! +$! +$MAKE: SUBROUTINE !SUBROUTINE TO CHECK DEPENDENCIES +$ V = 'F$Verify(0) +$! P1 = What we are trying to make +$! P2 = Command to make it +$! P3 - P8 What it depends on +$ +$ If F$Search(P1) .Eqs. "" Then Goto Makeit +$ Time = F$CvTime(F$File(P1,"RDT")) +$arg=3 +$Loop: +$ Argument = P'arg +$ If Argument .Eqs. "" Then Goto Exit +$ El=0 +$Loop2: +$ File = F$Element(El," ",Argument) +$ If File .Eqs. " " Then Goto Endl +$ AFile = "" +$Loop3: +$ OFile = AFile +$ AFile = F$Search(File) +$ If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl +$ If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit +$ Goto Loop3 +$NextEL: +$ El = El + 1 +$ Goto Loop2 +$EndL: +$ arg=arg+1 +$ If arg .Le. 8 Then Goto Loop +$ Goto Exit +$ +$Makeit: +$ VV=F$VERIFY(0) +$ write sys$output P2 +$ 'P2 +$ VV='F$Verify(VV) +$Exit: +$ If V Then Set Verify +$ENDSUBROUTINE +$!------------------------------------------------------------------------------ +$! +$! Check command line options and set symbols accordingly +$! +$!------------------------------------------------------------------------------ +$! Version history +$! 0.01 20041206 First version to receive a number +$! 0.02 20060126 Add new "HELP" target +$ CHECK_OPTS: +$ i = 1 +$ OPT_LOOP: +$ if i .lt. 9 +$ then +$ cparm = f$edit(p'i',"upcase") +$! +$! Check if parameter actually contains something +$! +$ if f$edit(cparm,"trim") .nes. "" +$ then +$ if cparm .eqs. "DEBUG" +$ then +$ ccopt = ccopt + "/noopt/deb" +$ lopts = lopts + "/deb" +$ endif +$ if f$locate("CCOPT=",cparm) .lt. f$length(cparm) +$ then +$ start = f$locate("=",cparm) + 1 +$ len = f$length(cparm) - start +$ ccopt = ccopt + f$extract(start,len,cparm) +$ if f$locate("AS_IS",f$edit(ccopt,"UPCASE")) .lt. f$length(ccopt) - + then s_case = true +$ endif +$ if cparm .eqs. "LINK" then linkonly = true +$ if f$locate("LOPTS=",cparm) .lt. f$length(cparm) +$ then +$ start = f$locate("=",cparm) + 1 +$ len = f$length(cparm) - start +$ lopts = lopts + f$extract(start,len,cparm) +$ endif +$ if f$locate("CC=",cparm) .lt. f$length(cparm) +$ then +$ start = f$locate("=",cparm) + 1 +$ len = f$length(cparm) - start +$ cc_com = f$extract(start,len,cparm) + if (cc_com .nes. "DECC") .and. - + (cc_com .nes. "VAXC") .and. - + (cc_com .nes. "GNUC") +$ then +$ write sys$output "Unsupported compiler choice ''cc_com' ignored" +$ write sys$output "Use DECC, VAXC, or GNUC instead" +$ else +$ if cc_com .eqs. "DECC" then its_decc = true +$ if cc_com .eqs. "VAXC" then its_vaxc = true +$ if cc_com .eqs. "GNUC" then its_gnuc = true +$ endif +$ endif +$ if f$locate("MAKE=",cparm) .lt. f$length(cparm) +$ then +$ start = f$locate("=",cparm) + 1 +$ len = f$length(cparm) - start +$ mmks = f$extract(start,len,cparm) +$ if (mmks .eqs. "MMK") .or. (mmks .eqs. "MMS") +$ then +$ make = mmks +$ else +$ write sys$output "Unsupported make choice ''mmks' ignored" +$ write sys$output "Use MMK or MMS instead" +$ endif +$ endif +$ if cparm .eqs. "HELP" then gosub bhelp +$ endif +$ i = i + 1 +$ goto opt_loop +$ endif +$ return +$!------------------------------------------------------------------------------ +$! +$! Look for the compiler used +$! +$! Version history +$! 0.01 20040223 First version to receive a number +$! 0.02 20040229 Save/set value of decc$no_rooted_search_lists +$! 0.03 20060202 Extend handling of GNU C +$! 0.04 20090402 Compaq -> hp +$CHECK_COMPILER: +$ if (.not. (its_decc .or. its_vaxc .or. its_gnuc)) +$ then +$ its_decc = (f$search("SYS$SYSTEM:DECC$COMPILER.EXE") .nes. "") +$ its_vaxc = .not. its_decc .and. (F$Search("SYS$System:VAXC.Exe") .nes. "") +$ its_gnuc = .not. (its_decc .or. its_vaxc) .and. (f$trnlnm("gnu_cc") .nes. "") +$ endif +$! +$! Exit if no compiler available +$! +$ if (.not. (its_decc .or. its_vaxc .or. its_gnuc)) +$ then goto CC_ERR +$ else +$ if its_decc +$ then +$ write sys$output "CC compiler check ... hp C" +$ if f$trnlnm("decc$no_rooted_search_lists") .nes. "" +$ then +$ dnrsl = f$trnlnm("decc$no_rooted_search_lists") +$ endif +$ define/nolog decc$no_rooted_search_lists 1 +$ else +$ if its_vaxc then write sys$output "CC compiler check ... VAX C" +$ if its_gnuc +$ then +$ write sys$output "CC compiler check ... GNU C" +$ if f$trnlnm(topt) then write topt "gnu_cc:[000000]gcclib.olb/lib" +$ if f$trnlnm(optf) then write optf "gnu_cc:[000000]gcclib.olb/lib" +$ cc = "gcc" +$ endif +$ if f$trnlnm(topt) then write topt "sys$share:vaxcrtl.exe/share" +$ if f$trnlnm(optf) then write optf "sys$share:vaxcrtl.exe/share" +$ endif +$ endif +$ return +$!------------------------------------------------------------------------------ +$! +$! If MMS/MMK are available dump out the descrip.mms if required +$! +$CREA_MMS: +$ write sys$output "Creating descrip.mms..." +$ create descrip.mms +$ open/append out descrip.mms +$ copy sys$input: out +$ deck +# descrip.mms: MMS description file for building zlib on VMS +# written by Martin P.J. Zinser +# + +OBJS = adler32.obj, compress.obj, crc32.obj, gzclose.obj, gzlib.obj\ + gzread.obj, gzwrite.obj, uncompr.obj, infback.obj\ + deflate.obj, trees.obj, zutil.obj, inflate.obj, \ + inftrees.obj, inffast.obj + +$ eod +$ write out "CFLAGS=", ccopt +$ write out "LOPTS=", lopts +$ write out "all : example.exe minigzip.exe libz.olb" +$ copy sys$input: out +$ deck + @ write sys$output " Example applications available" + +libz.olb : libz.olb($(OBJS)) + @ write sys$output " libz available" + +example.exe : example.obj libz.olb + link $(LOPTS) example,libz.olb/lib + +minigzip.exe : minigzip.obj libz.olb + link $(LOPTS) minigzip,libz.olb/lib + +clean : + delete *.obj;*,libz.olb;*,*.opt;*,*.exe;* + + +# Other dependencies. +adler32.obj : adler32.c zutil.h zlib.h zconf.h +compress.obj : compress.c zlib.h zconf.h +crc32.obj : crc32.c zutil.h zlib.h zconf.h +deflate.obj : deflate.c deflate.h zutil.h zlib.h zconf.h +example.obj : [.test]example.c zlib.h zconf.h +gzclose.obj : gzclose.c zutil.h zlib.h zconf.h +gzlib.obj : gzlib.c zutil.h zlib.h zconf.h +gzread.obj : gzread.c zutil.h zlib.h zconf.h +gzwrite.obj : gzwrite.c zutil.h zlib.h zconf.h +inffast.obj : inffast.c zutil.h zlib.h zconf.h inftrees.h inffast.h +inflate.obj : inflate.c zutil.h zlib.h zconf.h +inftrees.obj : inftrees.c zutil.h zlib.h zconf.h inftrees.h +minigzip.obj : [.test]minigzip.c zlib.h zconf.h +trees.obj : trees.c deflate.h zutil.h zlib.h zconf.h +uncompr.obj : uncompr.c zlib.h zconf.h +zutil.obj : zutil.c zutil.h zlib.h zconf.h +infback.obj : infback.c zutil.h inftrees.h inflate.h inffast.h inffixed.h +$ eod +$ close out +$ return +$!------------------------------------------------------------------------------ +$! +$! Read list of core library sources from makefile.in and create options +$! needed to build shareable image +$! +$CREA_OLIST: +$ open/read min makefile.in +$ open/write mod modules.opt +$ src_check_list = "OBJZ =#OBJG =" +$MRLOOP: +$ read/end=mrdone min rec +$ i = 0 +$SRC_CHECK_LOOP: +$ src_check = f$element(i, "#", src_check_list) +$ i = i+1 +$ if src_check .eqs. "#" then goto mrloop +$ if (f$extract(0,6,rec) .nes. src_check) then goto src_check_loop +$ rec = rec - src_check +$ gosub extra_filnam +$ if (f$element(1,"\",rec) .eqs. "\") then goto mrloop +$MRSLOOP: +$ read/end=mrdone min rec +$ gosub extra_filnam +$ if (f$element(1,"\",rec) .nes. "\") then goto mrsloop +$MRDONE: +$ close min +$ close mod +$ return +$!------------------------------------------------------------------------------ +$! +$! Take record extracted in crea_olist and split it into single filenames +$! +$EXTRA_FILNAM: +$ myrec = f$edit(rec - "\", "trim,compress") +$ i = 0 +$FELOOP: +$ srcfil = f$element(i," ", myrec) +$ if (srcfil .nes. " ") +$ then +$ write mod f$parse(srcfil,,,"NAME"), ".obj" +$ i = i + 1 +$ goto feloop +$ endif +$ return +$!------------------------------------------------------------------------------ +$! +$! Find current Zlib version number +$! +$FIND_VERSION: +$ open/read h_in 'v_file' +$hloop: +$ read/end=hdone h_in rec +$ rec = f$edit(rec,"TRIM") +$ if (f$extract(0,1,rec) .nes. "#") then goto hloop +$ rec = f$edit(rec - "#", "TRIM") +$ if f$element(0," ",rec) .nes. "define" then goto hloop +$ if f$element(1," ",rec) .eqs. v_string +$ then +$ version = 'f$element(2," ",rec)' +$ goto hdone +$ endif +$ goto hloop +$hdone: +$ close h_in +$ return +$!------------------------------------------------------------------------------ +$! +$CHECK_CONFIG: +$! +$ in_ldef = f$locate(cdef,libdefs) +$ if (in_ldef .lt. f$length(libdefs)) +$ then +$ write aconf "#define ''cdef' 1" +$ libdefs = f$extract(0,in_ldef,libdefs) + - + f$extract(in_ldef + f$length(cdef) + 1, - + f$length(libdefs) - in_ldef - f$length(cdef) - 1, - + libdefs) +$ else +$ if (f$type('cdef') .eqs. "INTEGER") +$ then +$ write aconf "#define ''cdef' ", 'cdef' +$ else +$ if (f$type('cdef') .eqs. "STRING") +$ then +$ write aconf "#define ''cdef' ", """", '''cdef'', """" +$ else +$ gosub check_cc_def +$ endif +$ endif +$ endif +$ return +$!------------------------------------------------------------------------------ +$! +$! Check if this is a define relating to the properties of the C/C++ +$! compiler +$! +$ CHECK_CC_DEF: +$ if (cdef .eqs. "_LARGEFILE64_SOURCE") +$ then +$ copy sys$input: 'tc' +$ deck +#include "tconfig" +#define _LARGEFILE +#include + +int main(){ +FILE *fp; + fp = fopen("temp.txt","r"); + fseeko(fp,1,SEEK_SET); + fclose(fp); +} + +$ eod +$ test_inv = false +$ comm_h = false +$ gosub cc_prop_check +$ return +$ endif +$ write aconf "/* ", line, " */" +$ return +$!------------------------------------------------------------------------------ +$! +$! Check for properties of C/C++ compiler +$! +$! Version history +$! 0.01 20031020 First version to receive a number +$! 0.02 20031022 Added logic for defines with value +$! 0.03 20040309 Make sure local config file gets not deleted +$! 0.04 20041230 Also write include for configure run +$! 0.05 20050103 Add processing of "comment defines" +$CC_PROP_CHECK: +$ cc_prop = true +$ is_need = false +$ is_need = (f$extract(0,4,cdef) .eqs. "NEED") .or. (test_inv .eq. true) +$ if f$search(th) .eqs. "" then create 'th' +$ set message/nofac/noident/nosever/notext +$ on error then continue +$ cc 'tmpnam' +$ if .not. ($status) then cc_prop = false +$ on error then continue +$! The headers might lie about the capabilities of the RTL +$ link 'tmpnam',tmp.opt/opt +$ if .not. ($status) then cc_prop = false +$ set message/fac/ident/sever/text +$ on error then goto err_exit +$ delete/nolog 'tmpnam'.*;*/exclude='th' +$ if (cc_prop .and. .not. is_need) .or. - + (.not. cc_prop .and. is_need) +$ then +$ write sys$output "Checking for ''cdef'... yes" +$ if f$type('cdef_val'_yes) .nes. "" +$ then +$ if f$type('cdef_val'_yes) .eqs. "INTEGER" - + then call write_config f$fao("#define !AS !UL",cdef,'cdef_val'_yes) +$ if f$type('cdef_val'_yes) .eqs. "STRING" - + then call write_config f$fao("#define !AS !AS",cdef,'cdef_val'_yes) +$ else +$ call write_config f$fao("#define !AS 1",cdef) +$ endif +$ if (cdef .eqs. "HAVE_FSEEKO") .or. (cdef .eqs. "_LARGE_FILES") .or. - + (cdef .eqs. "_LARGEFILE64_SOURCE") then - + call write_config f$string("#define _LARGEFILE 1") +$ else +$ write sys$output "Checking for ''cdef'... no" +$ if (comm_h) +$ then + call write_config f$fao("/* !AS */",line) +$ else +$ if f$type('cdef_val'_no) .nes. "" +$ then +$ if f$type('cdef_val'_no) .eqs. "INTEGER" - + then call write_config f$fao("#define !AS !UL",cdef,'cdef_val'_no) +$ if f$type('cdef_val'_no) .eqs. "STRING" - + then call write_config f$fao("#define !AS !AS",cdef,'cdef_val'_no) +$ else +$ call write_config f$fao("#undef !AS",cdef) +$ endif +$ endif +$ endif +$ return +$!------------------------------------------------------------------------------ +$! +$! Check for properties of C/C++ compiler with multiple result values +$! +$! Version history +$! 0.01 20040127 First version +$! 0.02 20050103 Reconcile changes from cc_prop up to version 0.05 +$CC_MPROP_CHECK: +$ cc_prop = true +$ i = 1 +$ idel = 1 +$ MT_LOOP: +$ if f$type(result_'i') .eqs. "STRING" +$ then +$ set message/nofac/noident/nosever/notext +$ on error then continue +$ cc 'tmpnam'_'i' +$ if .not. ($status) then cc_prop = false +$ on error then continue +$! The headers might lie about the capabilities of the RTL +$ link 'tmpnam'_'i',tmp.opt/opt +$ if .not. ($status) then cc_prop = false +$ set message/fac/ident/sever/text +$ on error then goto err_exit +$ delete/nolog 'tmpnam'_'i'.*;* +$ if (cc_prop) +$ then +$ write sys$output "Checking for ''cdef'... ", mdef_'i' +$ if f$type(mdef_'i') .eqs. "INTEGER" - + then call write_config f$fao("#define !AS !UL",cdef,mdef_'i') +$ if f$type('cdef_val'_yes) .eqs. "STRING" - + then call write_config f$fao("#define !AS !AS",cdef,mdef_'i') +$ goto msym_clean +$ else +$ i = i + 1 +$ goto mt_loop +$ endif +$ endif +$ write sys$output "Checking for ''cdef'... no" +$ call write_config f$fao("#undef !AS",cdef) +$ MSYM_CLEAN: +$ if (idel .le. msym_max) +$ then +$ delete/sym mdef_'idel' +$ idel = idel + 1 +$ goto msym_clean +$ endif +$ return +$!------------------------------------------------------------------------------ +$! +$! Write configuration to both permanent and temporary config file +$! +$! Version history +$! 0.01 20031029 First version to receive a number +$! +$WRITE_CONFIG: SUBROUTINE +$ write aconf 'p1' +$ open/append confh 'th' +$ write confh 'p1' +$ close confh +$ENDSUBROUTINE +$!------------------------------------------------------------------------------ +$! +$! Analyze the project map file and create the symbol vector for a shareable +$! image from it +$! +$! Version history +$! 0.01 20120128 First version +$! 0.02 20120226 Add pre-load logic +$! +$ MAP_2_SHOPT: Subroutine +$! +$ SAY := "WRITE_ SYS$OUTPUT" +$! +$ IF F$SEARCH("''P1'") .EQS. "" +$ THEN +$ SAY "MAP_2_SHOPT-E-NOSUCHFILE: Error, inputfile ''p1' not available" +$ goto exit_m2s +$ ENDIF +$ IF "''P2'" .EQS. "" +$ THEN +$ SAY "MAP_2_SHOPT: Error, no output file provided" +$ goto exit_m2s +$ ENDIF +$! +$ module1 = "deflate#deflateEnd#deflateInit_#deflateParams#deflateSetDictionary" +$ module2 = "gzclose#gzerror#gzgetc#gzgets#gzopen#gzprintf#gzputc#gzputs#gzread" +$ module3 = "gzseek#gztell#inflate#inflateEnd#inflateInit_#inflateSetDictionary" +$ module4 = "inflateSync#uncompress#zlibVersion#compress" +$ open/read map 'p1 +$ if axp .or. ia64 +$ then +$ open/write aopt a.opt +$ open/write bopt b.opt +$ write aopt " CASE_SENSITIVE=YES" +$ write bopt "SYMBOL_VECTOR= (-" +$ mod_sym_num = 1 +$ MOD_SYM_LOOP: +$ if f$type(module'mod_sym_num') .nes. "" +$ then +$ mod_in = 0 +$ MOD_SYM_IN: +$ shared_proc = f$element(mod_in, "#", module'mod_sym_num') +$ if shared_proc .nes. "#" +$ then +$ write aopt f$fao(" symbol_vector=(!AS/!AS=PROCEDURE)",- + f$edit(shared_proc,"upcase"),shared_proc) +$ write bopt f$fao("!AS=PROCEDURE,-",shared_proc) +$ mod_in = mod_in + 1 +$ goto mod_sym_in +$ endif +$ mod_sym_num = mod_sym_num + 1 +$ goto mod_sym_loop +$ endif +$MAP_LOOP: +$ read/end=map_end map line +$ if (f$locate("{",line).lt. f$length(line)) .or. - + (f$locate("global:", line) .lt. f$length(line)) +$ then +$ proc = true +$ goto map_loop +$ endif +$ if f$locate("}",line).lt. f$length(line) then proc = false +$ if f$locate("local:", line) .lt. f$length(line) then proc = false +$ if proc +$ then +$ shared_proc = f$edit(line,"collapse") +$ chop_semi = f$locate(";", shared_proc) +$ if chop_semi .lt. f$length(shared_proc) then - + shared_proc = f$extract(0, chop_semi, shared_proc) +$ write aopt f$fao(" symbol_vector=(!AS/!AS=PROCEDURE)",- + f$edit(shared_proc,"upcase"),shared_proc) +$ write bopt f$fao("!AS=PROCEDURE,-",shared_proc) +$ endif +$ goto map_loop +$MAP_END: +$ close/nolog aopt +$ close/nolog bopt +$ open/append libopt 'p2' +$ open/read aopt a.opt +$ open/read bopt b.opt +$ALOOP: +$ read/end=aloop_end aopt line +$ write libopt line +$ goto aloop +$ALOOP_END: +$ close/nolog aopt +$ sv = "" +$BLOOP: +$ read/end=bloop_end bopt svn +$ if (svn.nes."") +$ then +$ if (sv.nes."") then write libopt sv +$ sv = svn +$ endif +$ goto bloop +$BLOOP_END: +$ write libopt f$extract(0,f$length(sv)-2,sv), "-" +$ write libopt ")" +$ close/nolog bopt +$ delete/nolog/noconf a.opt;*,b.opt;* +$ else +$ if vax +$ then +$ open/append libopt 'p2' +$ mod_sym_num = 1 +$ VMOD_SYM_LOOP: +$ if f$type(module'mod_sym_num') .nes. "" +$ then +$ mod_in = 0 +$ VMOD_SYM_IN: +$ shared_proc = f$element(mod_in, "#", module'mod_sym_num') +$ if shared_proc .nes. "#" +$ then +$ write libopt f$fao("UNIVERSAL=!AS",- + f$edit(shared_proc,"upcase")) +$ mod_in = mod_in + 1 +$ goto vmod_sym_in +$ endif +$ mod_sym_num = mod_sym_num + 1 +$ goto vmod_sym_loop +$ endif +$VMAP_LOOP: +$ read/end=vmap_end map line +$ if (f$locate("{",line).lt. f$length(line)) .or. - + (f$locate("global:", line) .lt. f$length(line)) +$ then +$ proc = true +$ goto vmap_loop +$ endif +$ if f$locate("}",line).lt. f$length(line) then proc = false +$ if f$locate("local:", line) .lt. f$length(line) then proc = false +$ if proc +$ then +$ shared_proc = f$edit(line,"collapse") +$ chop_semi = f$locate(";", shared_proc) +$ if chop_semi .lt. f$length(shared_proc) then - + shared_proc = f$extract(0, chop_semi, shared_proc) +$ write libopt f$fao("UNIVERSAL=!AS",- + f$edit(shared_proc,"upcase")) +$ endif +$ goto vmap_loop +$VMAP_END: +$ else +$ write sys$output "Unknown Architecture (Not VAX, AXP, or IA64)" +$ write sys$output "No options file created" +$ endif +$ endif +$ EXIT_M2S: +$ close/nolog map +$ close/nolog libopt +$ endsubroutine diff --git a/dependencies/zlib-1.2.11/msdos/Makefile.bor b/dependencies/zlib-1.2.11/msdos/Makefile.bor new file mode 100644 index 0000000..3d12a2c --- /dev/null +++ b/dependencies/zlib-1.2.11/msdos/Makefile.bor @@ -0,0 +1,115 @@ +# Makefile for zlib +# Borland C++ +# Last updated: 15-Mar-2003 + +# To use, do "make -fmakefile.bor" +# To compile in small model, set below: MODEL=s + +# WARNING: the small model is supported but only for small values of +# MAX_WBITS and MAX_MEM_LEVEL. For example: +# -DMAX_WBITS=11 -DDEF_WBITS=11 -DMAX_MEM_LEVEL=3 +# If you wish to reduce the memory requirements (default 256K for big +# objects plus a few K), you can add to the LOC macro below: +# -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14 +# See zconf.h for details about the memory requirements. + +# ------------ Turbo C++, Borland C++ ------------ + +# Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7) +# should be added to the environment via "set LOCAL_ZLIB=-DFOO" or added +# to the declaration of LOC here: +LOC = $(LOCAL_ZLIB) + +# type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc. +CPU_TYP = 0 + +# memory model: one of s, m, c, l (small, medium, compact, large) +MODEL=l + +# replace bcc with tcc for Turbo C++ 1.0, with bcc32 for the 32 bit version +CC=bcc +LD=bcc +AR=tlib + +# compiler flags +# replace "-O2" by "-O -G -a -d" for Turbo C++ 1.0 +CFLAGS=-O2 -Z -m$(MODEL) $(LOC) + +LDFLAGS=-m$(MODEL) -f- + + +# variables +ZLIB_LIB = zlib_$(MODEL).lib + +OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj +OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj +OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj +OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj + + +# targets +all: $(ZLIB_LIB) example.exe minigzip.exe + +.c.obj: + $(CC) -c $(CFLAGS) $*.c + +adler32.obj: adler32.c zlib.h zconf.h + +compress.obj: compress.c zlib.h zconf.h + +crc32.obj: crc32.c zlib.h zconf.h crc32.h + +deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h + +gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h + +gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h + +gzread.obj: gzread.c zlib.h zconf.h gzguts.h + +gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h + +infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h inffixed.h + +inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h + +inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h inffixed.h + +inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h + +trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h + +uncompr.obj: uncompr.c zlib.h zconf.h + +zutil.obj: zutil.c zutil.h zlib.h zconf.h + +example.obj: test/example.c zlib.h zconf.h + +minigzip.obj: test/minigzip.c zlib.h zconf.h + + +# the command line is cut to fit in the MS-DOS 128 byte limit: +$(ZLIB_LIB): $(OBJ1) $(OBJ2) + -del $(ZLIB_LIB) + $(AR) $(ZLIB_LIB) $(OBJP1) + $(AR) $(ZLIB_LIB) $(OBJP2) + +example.exe: example.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) + +minigzip.exe: minigzip.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) + +test: example.exe minigzip.exe + example + echo hello world | minigzip | minigzip -d + +clean: + -del *.obj + -del *.lib + -del *.exe + -del zlib_*.bak + -del foo.gz diff --git a/dependencies/zlib-1.2.11/msdos/Makefile.dj2 b/dependencies/zlib-1.2.11/msdos/Makefile.dj2 new file mode 100644 index 0000000..59d2037 --- /dev/null +++ b/dependencies/zlib-1.2.11/msdos/Makefile.dj2 @@ -0,0 +1,104 @@ +# Makefile for zlib. Modified for djgpp v2.0 by F. J. Donahoe, 3/15/96. +# Copyright (C) 1995-1998 Jean-loup Gailly. +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile, or to compile and test, type: +# +# make -fmakefile.dj2; make test -fmakefile.dj2 +# +# To install libz.a, zconf.h and zlib.h in the djgpp directories, type: +# +# make install -fmakefile.dj2 +# +# after first defining LIBRARY_PATH and INCLUDE_PATH in djgpp.env as +# in the sample below if the pattern of the DJGPP distribution is to +# be followed. Remember that, while 'es around <=> are ignored in +# makefiles, they are *not* in batch files or in djgpp.env. +# - - - - - +# [make] +# INCLUDE_PATH=%\>;INCLUDE_PATH%%\DJDIR%\include +# LIBRARY_PATH=%\>;LIBRARY_PATH%%\DJDIR%\lib +# BUTT=-m486 +# - - - - - +# Alternately, these variables may be defined below, overriding the values +# in djgpp.env, as +# INCLUDE_PATH=c:\usr\include +# LIBRARY_PATH=c:\usr\lib + +CC=gcc + +#CFLAGS=-MMD -O +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-MMD -g -DZLIB_DEBUG +CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ + -Wstrict-prototypes -Wmissing-prototypes + +# If cp.exe is available, replace "copy /Y" with "cp -fp" . +CP=copy /Y +# If gnu install.exe is available, replace $(CP) with ginstall. +INSTALL=$(CP) +# The default value of RM is "rm -f." If "rm.exe" is found, comment out: +RM=del +LDLIBS=-L. -lz +LD=$(CC) -s -o +LDSHARED=$(CC) + +INCL=zlib.h zconf.h +LIBS=libz.a + +AR=ar rcs + +prefix=/usr/local +exec_prefix = $(prefix) + +OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \ + uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o + +OBJA = +# to use the asm code: make OBJA=match.o + +TEST_OBJS = example.o minigzip.o + +all: example.exe minigzip.exe + +check: test +test: all + ./example + echo hello world | .\minigzip | .\minigzip -d + +%.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +libz.a: $(OBJS) $(OBJA) + $(AR) $@ $(OBJS) $(OBJA) + +%.exe : %.o $(LIBS) + $(LD) $@ $< $(LDLIBS) + +# INCLUDE_PATH and LIBRARY_PATH were set for [make] in djgpp.env . + +.PHONY : uninstall clean + +install: $(INCL) $(LIBS) + -@if not exist $(INCLUDE_PATH)\nul mkdir $(INCLUDE_PATH) + -@if not exist $(LIBRARY_PATH)\nul mkdir $(LIBRARY_PATH) + $(INSTALL) zlib.h $(INCLUDE_PATH) + $(INSTALL) zconf.h $(INCLUDE_PATH) + $(INSTALL) libz.a $(LIBRARY_PATH) + +uninstall: + $(RM) $(INCLUDE_PATH)\zlib.h + $(RM) $(INCLUDE_PATH)\zconf.h + $(RM) $(LIBRARY_PATH)\libz.a + +clean: + $(RM) *.d + $(RM) *.o + $(RM) *.exe + $(RM) libz.a + $(RM) foo.gz + +DEPS := $(wildcard *.d) +ifneq ($(DEPS),) +include $(DEPS) +endif diff --git a/dependencies/zlib-1.2.11/msdos/Makefile.emx b/dependencies/zlib-1.2.11/msdos/Makefile.emx new file mode 100644 index 0000000..e30f67b --- /dev/null +++ b/dependencies/zlib-1.2.11/msdos/Makefile.emx @@ -0,0 +1,69 @@ +# Makefile for zlib. Modified for emx 0.9c by Chr. Spieler, 6/17/98. +# Copyright (C) 1995-1998 Jean-loup Gailly. +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile, or to compile and test, type: +# +# make -fmakefile.emx; make test -fmakefile.emx +# + +CC=gcc + +#CFLAGS=-MMD -O +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-MMD -g -DZLIB_DEBUG +CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ + -Wstrict-prototypes -Wmissing-prototypes + +# If cp.exe is available, replace "copy /Y" with "cp -fp" . +CP=copy /Y +# If gnu install.exe is available, replace $(CP) with ginstall. +INSTALL=$(CP) +# The default value of RM is "rm -f." If "rm.exe" is found, comment out: +RM=del +LDLIBS=-L. -lzlib +LD=$(CC) -s -o +LDSHARED=$(CC) + +INCL=zlib.h zconf.h +LIBS=zlib.a + +AR=ar rcs + +prefix=/usr/local +exec_prefix = $(prefix) + +OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \ + uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o + +TEST_OBJS = example.o minigzip.o + +all: example.exe minigzip.exe + +test: all + ./example + echo hello world | .\minigzip | .\minigzip -d + +%.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +zlib.a: $(OBJS) + $(AR) $@ $(OBJS) + +%.exe : %.o $(LIBS) + $(LD) $@ $< $(LDLIBS) + + +.PHONY : clean + +clean: + $(RM) *.d + $(RM) *.o + $(RM) *.exe + $(RM) zlib.a + $(RM) foo.gz + +DEPS := $(wildcard *.d) +ifneq ($(DEPS),) +include $(DEPS) +endif diff --git a/dependencies/zlib-1.2.11/msdos/Makefile.msc b/dependencies/zlib-1.2.11/msdos/Makefile.msc new file mode 100644 index 0000000..ae83786 --- /dev/null +++ b/dependencies/zlib-1.2.11/msdos/Makefile.msc @@ -0,0 +1,112 @@ +# Makefile for zlib +# Microsoft C 5.1 or later +# Last updated: 19-Mar-2003 + +# To use, do "make makefile.msc" +# To compile in small model, set below: MODEL=S + +# If you wish to reduce the memory requirements (default 256K for big +# objects plus a few K), you can add to the LOC macro below: +# -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14 +# See zconf.h for details about the memory requirements. + +# ------------- Microsoft C 5.1 and later ------------- + +# Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7) +# should be added to the environment via "set LOCAL_ZLIB=-DFOO" or added +# to the declaration of LOC here: +LOC = $(LOCAL_ZLIB) + +# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc. +CPU_TYP = 0 + +# Memory model: one of S, M, C, L (small, medium, compact, large) +MODEL=L + +CC=cl +CFLAGS=-nologo -A$(MODEL) -G$(CPU_TYP) -W3 -Oait -Gs $(LOC) +#-Ox generates bad code with MSC 5.1 +LIB_CFLAGS=-Zl $(CFLAGS) + +LD=link +LDFLAGS=/noi/e/st:0x1500/noe/farcall/packcode +# "/farcall/packcode" are only useful for `large code' memory models +# but should be a "no-op" for small code models. + + +# variables +ZLIB_LIB = zlib_$(MODEL).lib + +OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj +OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj + + +# targets +all: $(ZLIB_LIB) example.exe minigzip.exe + +.c.obj: + $(CC) -c $(LIB_CFLAGS) $*.c + +adler32.obj: adler32.c zlib.h zconf.h + +compress.obj: compress.c zlib.h zconf.h + +crc32.obj: crc32.c zlib.h zconf.h crc32.h + +deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h + +gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h + +gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h + +gzread.obj: gzread.c zlib.h zconf.h gzguts.h + +gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h + +infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h inffixed.h + +inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h + +inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h inffixed.h + +inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h + +trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h + +uncompr.obj: uncompr.c zlib.h zconf.h + +zutil.obj: zutil.c zutil.h zlib.h zconf.h + +example.obj: test/example.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +minigzip.obj: test/minigzip.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + + +# the command line is cut to fit in the MS-DOS 128 byte limit: +$(ZLIB_LIB): $(OBJ1) $(OBJ2) + if exist $(ZLIB_LIB) del $(ZLIB_LIB) + lib $(ZLIB_LIB) $(OBJ1); + lib $(ZLIB_LIB) $(OBJ2); + +example.exe: example.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) example.obj,,,$(ZLIB_LIB); + +minigzip.exe: minigzip.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) minigzip.obj,,,$(ZLIB_LIB); + +test: example.exe minigzip.exe + example + echo hello world | minigzip | minigzip -d + +clean: + -del *.obj + -del *.lib + -del *.exe + -del *.map + -del zlib_*.bak + -del foo.gz diff --git a/dependencies/zlib-1.2.11/msdos/Makefile.tc b/dependencies/zlib-1.2.11/msdos/Makefile.tc new file mode 100644 index 0000000..5aec82a --- /dev/null +++ b/dependencies/zlib-1.2.11/msdos/Makefile.tc @@ -0,0 +1,100 @@ +# Makefile for zlib +# Turbo C 2.01, Turbo C++ 1.01 +# Last updated: 15-Mar-2003 + +# To use, do "make -fmakefile.tc" +# To compile in small model, set below: MODEL=s + +# WARNING: the small model is supported but only for small values of +# MAX_WBITS and MAX_MEM_LEVEL. For example: +# -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3 +# If you wish to reduce the memory requirements (default 256K for big +# objects plus a few K), you can add to CFLAGS below: +# -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14 +# See zconf.h for details about the memory requirements. + +# ------------ Turbo C 2.01, Turbo C++ 1.01 ------------ +MODEL=l +CC=tcc +LD=tcc +AR=tlib +# CFLAGS=-O2 -G -Z -m$(MODEL) -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3 +CFLAGS=-O2 -G -Z -m$(MODEL) +LDFLAGS=-m$(MODEL) -f- + + +# variables +ZLIB_LIB = zlib_$(MODEL).lib + +OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj +OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj +OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj +OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj + + +# targets +all: $(ZLIB_LIB) example.exe minigzip.exe + +.c.obj: + $(CC) -c $(CFLAGS) $*.c + +adler32.obj: adler32.c zlib.h zconf.h + +compress.obj: compress.c zlib.h zconf.h + +crc32.obj: crc32.c zlib.h zconf.h crc32.h + +deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h + +gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h + +gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h + +gzread.obj: gzread.c zlib.h zconf.h gzguts.h + +gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h + +infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h inffixed.h + +inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h + +inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h inffixed.h + +inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h + +trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h + +uncompr.obj: uncompr.c zlib.h zconf.h + +zutil.obj: zutil.c zutil.h zlib.h zconf.h + +example.obj: test/example.c zlib.h zconf.h + +minigzip.obj: test/minigzip.c zlib.h zconf.h + + +# the command line is cut to fit in the MS-DOS 128 byte limit: +$(ZLIB_LIB): $(OBJ1) $(OBJ2) + -del $(ZLIB_LIB) + $(AR) $(ZLIB_LIB) $(OBJP1) + $(AR) $(ZLIB_LIB) $(OBJP2) + +example.exe: example.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) + +minigzip.exe: minigzip.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) + +test: example.exe minigzip.exe + example + echo hello world | minigzip | minigzip -d + +clean: + -del *.obj + -del *.lib + -del *.exe + -del zlib_*.bak + -del foo.gz diff --git a/dependencies/zlib-1.2.11/nintendods/Makefile b/dependencies/zlib-1.2.11/nintendods/Makefile new file mode 100644 index 0000000..21337d0 --- /dev/null +++ b/dependencies/zlib-1.2.11/nintendods/Makefile @@ -0,0 +1,126 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") +endif + +include $(DEVKITARM)/ds_rules + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# DATA is a list of directories containing data files +# INCLUDES is a list of directories containing header files +#--------------------------------------------------------------------------------- +TARGET := $(shell basename $(CURDIR)) +BUILD := build +SOURCES := ../../ +DATA := data +INCLUDES := include + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -mthumb -mthumb-interwork + +CFLAGS := -Wall -O2\ + -march=armv5te -mtune=arm946e-s \ + -fomit-frame-pointer -ffast-math \ + $(ARCH) + +CFLAGS += $(INCLUDE) -DARM9 +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions + +ASFLAGS := $(ARCH) -march=armv5te -mtune=arm946e-s +LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(LIBNDS) + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/lib/libz.a + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + +export DEPSDIR := $(CURDIR)/$(BUILD) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES := $(addsuffix .o,$(BINFILES)) \ + $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +.PHONY: $(BUILD) clean all + +#--------------------------------------------------------------------------------- +all: $(BUILD) + @[ -d $@ ] || mkdir -p include + @cp ../../*.h include + +lib: + @[ -d $@ ] || mkdir -p $@ + +$(BUILD): lib + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) lib + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(OUTPUT) : $(OFILES) + +#--------------------------------------------------------------------------------- +%.bin.o : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/dependencies/zlib-1.2.11/nintendods/README b/dependencies/zlib-1.2.11/nintendods/README new file mode 100644 index 0000000..ba7a37d --- /dev/null +++ b/dependencies/zlib-1.2.11/nintendods/README @@ -0,0 +1,5 @@ +This Makefile requires devkitARM (http://www.devkitpro.org/category/devkitarm/) and works inside "contrib/nds". It is based on a devkitARM template. + +Eduardo Costa +January 3, 2009 + diff --git a/dependencies/zlib-1.2.11/old/Makefile.emx b/dependencies/zlib-1.2.11/old/Makefile.emx new file mode 100644 index 0000000..612b037 --- /dev/null +++ b/dependencies/zlib-1.2.11/old/Makefile.emx @@ -0,0 +1,69 @@ +# Makefile for zlib. Modified for emx/rsxnt by Chr. Spieler, 6/16/98. +# Copyright (C) 1995-1998 Jean-loup Gailly. +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile, or to compile and test, type: +# +# make -fmakefile.emx; make test -fmakefile.emx +# + +CC=gcc -Zwin32 + +#CFLAGS=-MMD -O +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-MMD -g -DZLIB_DEBUG +CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ + -Wstrict-prototypes -Wmissing-prototypes + +# If cp.exe is available, replace "copy /Y" with "cp -fp" . +CP=copy /Y +# If gnu install.exe is available, replace $(CP) with ginstall. +INSTALL=$(CP) +# The default value of RM is "rm -f." If "rm.exe" is found, comment out: +RM=del +LDLIBS=-L. -lzlib +LD=$(CC) -s -o +LDSHARED=$(CC) + +INCL=zlib.h zconf.h +LIBS=zlib.a + +AR=ar rcs + +prefix=/usr/local +exec_prefix = $(prefix) + +OBJS = adler32.o compress.o crc32.o deflate.o gzclose.o gzlib.o gzread.o \ + gzwrite.o infback.o inffast.o inflate.o inftrees.o trees.o uncompr.o zutil.o + +TEST_OBJS = example.o minigzip.o + +all: example.exe minigzip.exe + +test: all + ./example + echo hello world | .\minigzip | .\minigzip -d + +%.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +zlib.a: $(OBJS) + $(AR) $@ $(OBJS) + +%.exe : %.o $(LIBS) + $(LD) $@ $< $(LDLIBS) + + +.PHONY : clean + +clean: + $(RM) *.d + $(RM) *.o + $(RM) *.exe + $(RM) zlib.a + $(RM) foo.gz + +DEPS := $(wildcard *.d) +ifneq ($(DEPS),) +include $(DEPS) +endif diff --git a/dependencies/zlib-1.2.11/old/Makefile.riscos b/dependencies/zlib-1.2.11/old/Makefile.riscos new file mode 100644 index 0000000..57e29d3 --- /dev/null +++ b/dependencies/zlib-1.2.11/old/Makefile.riscos @@ -0,0 +1,151 @@ +# Project: zlib_1_03 +# Patched for zlib 1.1.2 rw@shadow.org.uk 19980430 +# test works out-of-the-box, installs `somewhere' on demand + +# Toolflags: +CCflags = -c -depend !Depend -IC: -g -throwback -DRISCOS -fah +C++flags = -c -depend !Depend -IC: -throwback +Linkflags = -aif -c++ -o $@ +ObjAsmflags = -throwback -NoCache -depend !Depend +CMHGflags = +LibFileflags = -c -l -o $@ +Squeezeflags = -o $@ + +# change the line below to where _you_ want the library installed. +libdest = lib:zlib + +# Final targets: +@.lib: @.o.adler32 @.o.compress @.o.crc32 @.o.deflate @.o.gzio \ + @.o.infblock @.o.infcodes @.o.inffast @.o.inflate @.o.inftrees @.o.infutil @.o.trees \ + @.o.uncompr @.o.zutil + LibFile $(LibFileflags) @.o.adler32 @.o.compress @.o.crc32 @.o.deflate \ + @.o.gzio @.o.infblock @.o.infcodes @.o.inffast @.o.inflate @.o.inftrees @.o.infutil \ + @.o.trees @.o.uncompr @.o.zutil +test: @.minigzip @.example @.lib + @copy @.lib @.libc A~C~DF~L~N~P~Q~RS~TV + @echo running tests: hang on. + @/@.minigzip -f -9 libc + @/@.minigzip -d libc-gz + @/@.minigzip -f -1 libc + @/@.minigzip -d libc-gz + @/@.minigzip -h -9 libc + @/@.minigzip -d libc-gz + @/@.minigzip -h -1 libc + @/@.minigzip -d libc-gz + @/@.minigzip -9 libc + @/@.minigzip -d libc-gz + @/@.minigzip -1 libc + @/@.minigzip -d libc-gz + @diff @.lib @.libc + @echo that should have reported '@.lib and @.libc identical' if you have diff. + @/@.example @.fred @.fred + @echo that will have given lots of hello!'s. + +@.minigzip: @.o.minigzip @.lib C:o.Stubs + Link $(Linkflags) @.o.minigzip @.lib C:o.Stubs +@.example: @.o.example @.lib C:o.Stubs + Link $(Linkflags) @.o.example @.lib C:o.Stubs + +install: @.lib + cdir $(libdest) + cdir $(libdest).h + @copy @.h.zlib $(libdest).h.zlib A~C~DF~L~N~P~Q~RS~TV + @copy @.h.zconf $(libdest).h.zconf A~C~DF~L~N~P~Q~RS~TV + @copy @.lib $(libdest).lib A~C~DF~L~N~P~Q~RS~TV + @echo okay, installed zlib in $(libdest) + +clean:; remove @.minigzip + remove @.example + remove @.libc + -wipe @.o.* F~r~cV + remove @.fred + +# User-editable dependencies: +.c.o: + cc $(ccflags) -o $@ $< + +# Static dependencies: + +# Dynamic dependencies: +o.example: c.example +o.example: h.zlib +o.example: h.zconf +o.minigzip: c.minigzip +o.minigzip: h.zlib +o.minigzip: h.zconf +o.adler32: c.adler32 +o.adler32: h.zlib +o.adler32: h.zconf +o.compress: c.compress +o.compress: h.zlib +o.compress: h.zconf +o.crc32: c.crc32 +o.crc32: h.zlib +o.crc32: h.zconf +o.deflate: c.deflate +o.deflate: h.deflate +o.deflate: h.zutil +o.deflate: h.zlib +o.deflate: h.zconf +o.gzio: c.gzio +o.gzio: h.zutil +o.gzio: h.zlib +o.gzio: h.zconf +o.infblock: c.infblock +o.infblock: h.zutil +o.infblock: h.zlib +o.infblock: h.zconf +o.infblock: h.infblock +o.infblock: h.inftrees +o.infblock: h.infcodes +o.infblock: h.infutil +o.infcodes: c.infcodes +o.infcodes: h.zutil +o.infcodes: h.zlib +o.infcodes: h.zconf +o.infcodes: h.inftrees +o.infcodes: h.infblock +o.infcodes: h.infcodes +o.infcodes: h.infutil +o.infcodes: h.inffast +o.inffast: c.inffast +o.inffast: h.zutil +o.inffast: h.zlib +o.inffast: h.zconf +o.inffast: h.inftrees +o.inffast: h.infblock +o.inffast: h.infcodes +o.inffast: h.infutil +o.inffast: h.inffast +o.inflate: c.inflate +o.inflate: h.zutil +o.inflate: h.zlib +o.inflate: h.zconf +o.inflate: h.infblock +o.inftrees: c.inftrees +o.inftrees: h.zutil +o.inftrees: h.zlib +o.inftrees: h.zconf +o.inftrees: h.inftrees +o.inftrees: h.inffixed +o.infutil: c.infutil +o.infutil: h.zutil +o.infutil: h.zlib +o.infutil: h.zconf +o.infutil: h.infblock +o.infutil: h.inftrees +o.infutil: h.infcodes +o.infutil: h.infutil +o.trees: c.trees +o.trees: h.deflate +o.trees: h.zutil +o.trees: h.zlib +o.trees: h.zconf +o.trees: h.trees +o.uncompr: c.uncompr +o.uncompr: h.zlib +o.uncompr: h.zconf +o.zutil: c.zutil +o.zutil: h.zutil +o.zutil: h.zlib +o.zutil: h.zconf diff --git a/dependencies/zlib-1.2.11/old/README b/dependencies/zlib-1.2.11/old/README new file mode 100644 index 0000000..800bf07 --- /dev/null +++ b/dependencies/zlib-1.2.11/old/README @@ -0,0 +1,3 @@ +This directory contains files that have not been updated for zlib 1.2.x + +(Volunteers are encouraged to help clean this up. Thanks.) diff --git a/dependencies/zlib-1.2.11/old/descrip.mms b/dependencies/zlib-1.2.11/old/descrip.mms new file mode 100644 index 0000000..7066da5 --- /dev/null +++ b/dependencies/zlib-1.2.11/old/descrip.mms @@ -0,0 +1,48 @@ +# descrip.mms: MMS description file for building zlib on VMS +# written by Martin P.J. Zinser + +cc_defs = +c_deb = + +.ifdef __DECC__ +pref = /prefix=all +.endif + +OBJS = adler32.obj, compress.obj, crc32.obj, gzio.obj, uncompr.obj,\ + deflate.obj, trees.obj, zutil.obj, inflate.obj, infblock.obj,\ + inftrees.obj, infcodes.obj, infutil.obj, inffast.obj + +CFLAGS= $(C_DEB) $(CC_DEFS) $(PREF) + +all : example.exe minigzip.exe + @ write sys$output " Example applications available" +libz.olb : libz.olb($(OBJS)) + @ write sys$output " libz available" + +example.exe : example.obj libz.olb + link example,libz.olb/lib + +minigzip.exe : minigzip.obj libz.olb + link minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib + +clean : + delete *.obj;*,libz.olb;* + + +# Other dependencies. +adler32.obj : zutil.h zlib.h zconf.h +compress.obj : zlib.h zconf.h +crc32.obj : zutil.h zlib.h zconf.h +deflate.obj : deflate.h zutil.h zlib.h zconf.h +example.obj : zlib.h zconf.h +gzio.obj : zutil.h zlib.h zconf.h +infblock.obj : zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h +infcodes.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h infcodes.h inffast.h +inffast.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h inffast.h +inflate.obj : zutil.h zlib.h zconf.h infblock.h +inftrees.obj : zutil.h zlib.h zconf.h inftrees.h +infutil.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h +minigzip.obj : zlib.h zconf.h +trees.obj : deflate.h zutil.h zlib.h zconf.h +uncompr.obj : zlib.h zconf.h +zutil.obj : zutil.h zlib.h zconf.h diff --git a/dependencies/zlib-1.2.11/old/os2/Makefile.os2 b/dependencies/zlib-1.2.11/old/os2/Makefile.os2 new file mode 100644 index 0000000..bb426c0 --- /dev/null +++ b/dependencies/zlib-1.2.11/old/os2/Makefile.os2 @@ -0,0 +1,136 @@ +# Makefile for zlib under OS/2 using GCC (PGCC) +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile and test, type: +# cp Makefile.os2 .. +# cd .. +# make -f Makefile.os2 test + +# This makefile will build a static library z.lib, a shared library +# z.dll and a import library zdll.lib. You can use either z.lib or +# zdll.lib by specifying either -lz or -lzdll on gcc's command line + +CC=gcc -Zomf -s + +CFLAGS=-O6 -Wall +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-g -DZLIB_DEBUG +#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ +# -Wstrict-prototypes -Wmissing-prototypes + +#################### BUG WARNING: ##################### +## infcodes.c hits a bug in pgcc-1.0, so you have to use either +## -O# where # <= 4 or one of (-fno-ommit-frame-pointer or -fno-force-mem) +## This bug is reportedly fixed in pgcc >1.0, but this was not tested +CFLAGS+=-fno-force-mem + +LDFLAGS=-s -L. -lzdll -Zcrtdll +LDSHARED=$(CC) -s -Zomf -Zdll -Zcrtdll + +VER=1.1.0 +ZLIB=z.lib +SHAREDLIB=z.dll +SHAREDLIBIMP=zdll.lib +LIBS=$(ZLIB) $(SHAREDLIB) $(SHAREDLIBIMP) + +AR=emxomfar cr +IMPLIB=emximp +RANLIB=echo +TAR=tar +SHELL=bash + +prefix=/usr/local +exec_prefix = $(prefix) + +OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ + zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o + +TEST_OBJS = example.o minigzip.o + +DISTFILES = README INDEX ChangeLog configure Make*[a-z0-9] *.[ch] descrip.mms \ + algorithm.txt zlib.3 msdos/Make*[a-z0-9] msdos/zlib.def msdos/zlib.rc \ + nt/Makefile.nt nt/zlib.dnt contrib/README.contrib contrib/*.txt \ + contrib/asm386/*.asm contrib/asm386/*.c \ + contrib/asm386/*.bat contrib/asm386/zlibvc.d?? contrib/iostream/*.cpp \ + contrib/iostream/*.h contrib/iostream2/*.h contrib/iostream2/*.cpp \ + contrib/untgz/Makefile contrib/untgz/*.c contrib/untgz/*.w32 + +all: example.exe minigzip.exe + +test: all + @LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ + echo hello world | ./minigzip | ./minigzip -d || \ + echo ' *** minigzip test FAILED ***' ; \ + if ./example; then \ + echo ' *** zlib test OK ***'; \ + else \ + echo ' *** zlib test FAILED ***'; \ + fi + +$(ZLIB): $(OBJS) + $(AR) $@ $(OBJS) + -@ ($(RANLIB) $@ || true) >/dev/null 2>&1 + +$(SHAREDLIB): $(OBJS) os2/z.def + $(LDSHARED) -o $@ $^ + +$(SHAREDLIBIMP): os2/z.def + $(IMPLIB) -o $@ $^ + +example.exe: example.o $(LIBS) + $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) + +minigzip.exe: minigzip.o $(LIBS) + $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) + +clean: + rm -f *.o *~ example minigzip libz.a libz.so* foo.gz + +distclean: clean + +zip: + mv Makefile Makefile~; cp -p Makefile.in Makefile + rm -f test.c ztest*.c + v=`sed -n -e 's/\.//g' -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\ + zip -ul9 zlib$$v $(DISTFILES) + mv Makefile~ Makefile + +dist: + mv Makefile Makefile~; cp -p Makefile.in Makefile + rm -f test.c ztest*.c + d=zlib-`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\ + rm -f $$d.tar.gz; \ + if test ! -d ../$$d; then rm -f ../$$d; ln -s `pwd` ../$$d; fi; \ + files=""; \ + for f in $(DISTFILES); do files="$$files $$d/$$f"; done; \ + cd ..; \ + GZIP=-9 $(TAR) chofz $$d/$$d.tar.gz $$files; \ + if test ! -d $$d; then rm -f $$d; fi + mv Makefile~ Makefile + +tags: + etags *.[ch] + +depend: + makedepend -- $(CFLAGS) -- *.[ch] + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +adler32.o: zlib.h zconf.h +compress.o: zlib.h zconf.h +crc32.o: zlib.h zconf.h +deflate.o: deflate.h zutil.h zlib.h zconf.h +example.o: zlib.h zconf.h +gzio.o: zutil.h zlib.h zconf.h +infblock.o: infblock.h inftrees.h infcodes.h infutil.h zutil.h zlib.h zconf.h +infcodes.o: zutil.h zlib.h zconf.h +infcodes.o: inftrees.h infblock.h infcodes.h infutil.h inffast.h +inffast.o: zutil.h zlib.h zconf.h inftrees.h +inffast.o: infblock.h infcodes.h infutil.h inffast.h +inflate.o: zutil.h zlib.h zconf.h infblock.h +inftrees.o: zutil.h zlib.h zconf.h inftrees.h +infutil.o: zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h +minigzip.o: zlib.h zconf.h +trees.o: deflate.h zutil.h zlib.h zconf.h trees.h +uncompr.o: zlib.h zconf.h +zutil.o: zutil.h zlib.h zconf.h diff --git a/dependencies/zlib-1.2.11/old/os2/zlib.def b/dependencies/zlib-1.2.11/old/os2/zlib.def new file mode 100644 index 0000000..4c753f1 --- /dev/null +++ b/dependencies/zlib-1.2.11/old/os2/zlib.def @@ -0,0 +1,51 @@ +; +; Slightly modified version of ../nt/zlib.dnt :-) +; + +LIBRARY Z +DESCRIPTION "Zlib compression library for OS/2" +CODE PRELOAD MOVEABLE DISCARDABLE +DATA PRELOAD MOVEABLE MULTIPLE + +EXPORTS + adler32 + compress + crc32 + deflate + deflateCopy + deflateEnd + deflateInit2_ + deflateInit_ + deflateParams + deflateReset + deflateSetDictionary + gzclose + gzdopen + gzerror + gzflush + gzopen + gzread + gzwrite + inflate + inflateEnd + inflateInit2_ + inflateInit_ + inflateReset + inflateSetDictionary + inflateSync + uncompress + zlibVersion + gzprintf + gzputc + gzgetc + gzseek + gzrewind + gztell + gzeof + gzsetparams + zError + inflateSyncPoint + get_crc_table + compress2 + gzputs + gzgets diff --git a/dependencies/zlib-1.2.11/old/visual-basic.txt b/dependencies/zlib-1.2.11/old/visual-basic.txt new file mode 100644 index 0000000..57efe58 --- /dev/null +++ b/dependencies/zlib-1.2.11/old/visual-basic.txt @@ -0,0 +1,160 @@ +See below some functions declarations for Visual Basic. + +Frequently Asked Question: + +Q: Each time I use the compress function I get the -5 error (not enough + room in the output buffer). + +A: Make sure that the length of the compressed buffer is passed by + reference ("as any"), not by value ("as long"). Also check that + before the call of compress this length is equal to the total size of + the compressed buffer and not zero. + + +From: "Jon Caruana" +Subject: Re: How to port zlib declares to vb? +Date: Mon, 28 Oct 1996 18:33:03 -0600 + +Got the answer! (I haven't had time to check this but it's what I got, and +looks correct): + +He has the following routines working: + compress + uncompress + gzopen + gzwrite + gzread + gzclose + +Declares follow: (Quoted from Carlos Rios , in Vb4 form) + +#If Win16 Then 'Use Win16 calls. +Declare Function compress Lib "ZLIB.DLL" (ByVal compr As + String, comprLen As Any, ByVal buf As String, ByVal buflen + As Long) As Integer +Declare Function uncompress Lib "ZLIB.DLL" (ByVal uncompr + As String, uncomprLen As Any, ByVal compr As String, ByVal + lcompr As Long) As Integer +Declare Function gzopen Lib "ZLIB.DLL" (ByVal filePath As + String, ByVal mode As String) As Long +Declare Function gzread Lib "ZLIB.DLL" (ByVal file As + Long, ByVal uncompr As String, ByVal uncomprLen As Integer) + As Integer +Declare Function gzwrite Lib "ZLIB.DLL" (ByVal file As + Long, ByVal uncompr As String, ByVal uncomprLen As Integer) + As Integer +Declare Function gzclose Lib "ZLIB.DLL" (ByVal file As + Long) As Integer +#Else +Declare Function compress Lib "ZLIB32.DLL" + (ByVal compr As String, comprLen As Any, ByVal buf As + String, ByVal buflen As Long) As Integer +Declare Function uncompress Lib "ZLIB32.DLL" + (ByVal uncompr As String, uncomprLen As Any, ByVal compr As + String, ByVal lcompr As Long) As Long +Declare Function gzopen Lib "ZLIB32.DLL" + (ByVal file As String, ByVal mode As String) As Long +Declare Function gzread Lib "ZLIB32.DLL" + (ByVal file As Long, ByVal uncompr As String, ByVal + uncomprLen As Long) As Long +Declare Function gzwrite Lib "ZLIB32.DLL" + (ByVal file As Long, ByVal uncompr As String, ByVal + uncomprLen As Long) As Long +Declare Function gzclose Lib "ZLIB32.DLL" + (ByVal file As Long) As Long +#End If + +-Jon Caruana +jon-net@usa.net +Microsoft Sitebuilder Network Level 1 Member - HTML Writer's Guild Member + + +Here is another example from Michael that he +says conforms to the VB guidelines, and that solves the problem of not +knowing the uncompressed size by storing it at the end of the file: + +'Calling the functions: +'bracket meaning: [optional] {Range of possible values} +'Call subCompressFile( [, , [level of compression {1..9}]]) +'Call subUncompressFile() + +Option Explicit +Private lngpvtPcnSml As Long 'Stores value for 'lngPercentSmaller' +Private Const SUCCESS As Long = 0 +Private Const strFilExt As String = ".cpr" +Private Declare Function lngfncCpr Lib "zlib.dll" Alias "compress2" (ByRef +dest As Any, ByRef destLen As Any, ByRef src As Any, ByVal srcLen As Long, +ByVal level As Integer) As Long +Private Declare Function lngfncUcp Lib "zlib.dll" Alias "uncompress" (ByRef +dest As Any, ByRef destLen As Any, ByRef src As Any, ByVal srcLen As Long) +As Long + +Public Sub subCompressFile(ByVal strargOriFilPth As String, Optional ByVal +strargCprFilPth As String, Optional ByVal intLvl As Integer = 9) + Dim strCprPth As String + Dim lngOriSiz As Long + Dim lngCprSiz As Long + Dim bytaryOri() As Byte + Dim bytaryCpr() As Byte + lngOriSiz = FileLen(strargOriFilPth) + ReDim bytaryOri(lngOriSiz - 1) + Open strargOriFilPth For Binary Access Read As #1 + Get #1, , bytaryOri() + Close #1 + strCprPth = IIf(strargCprFilPth = "", strargOriFilPth, strargCprFilPth) +'Select file path and name + strCprPth = strCprPth & IIf(Right(strCprPth, Len(strFilExt)) = +strFilExt, "", strFilExt) 'Add file extension if not exists + lngCprSiz = (lngOriSiz * 1.01) + 12 'Compression needs temporary a bit +more space then original file size + ReDim bytaryCpr(lngCprSiz - 1) + If lngfncCpr(bytaryCpr(0), lngCprSiz, bytaryOri(0), lngOriSiz, intLvl) = +SUCCESS Then + lngpvtPcnSml = (1# - (lngCprSiz / lngOriSiz)) * 100 + ReDim Preserve bytaryCpr(lngCprSiz - 1) + Open strCprPth For Binary Access Write As #1 + Put #1, , bytaryCpr() + Put #1, , lngOriSiz 'Add the the original size value to the end +(last 4 bytes) + Close #1 + Else + MsgBox "Compression error" + End If + Erase bytaryCpr + Erase bytaryOri +End Sub + +Public Sub subUncompressFile(ByVal strargFilPth As String) + Dim bytaryCpr() As Byte + Dim bytaryOri() As Byte + Dim lngOriSiz As Long + Dim lngCprSiz As Long + Dim strOriPth As String + lngCprSiz = FileLen(strargFilPth) + ReDim bytaryCpr(lngCprSiz - 1) + Open strargFilPth For Binary Access Read As #1 + Get #1, , bytaryCpr() + Close #1 + 'Read the original file size value: + lngOriSiz = bytaryCpr(lngCprSiz - 1) * (2 ^ 24) _ + + bytaryCpr(lngCprSiz - 2) * (2 ^ 16) _ + + bytaryCpr(lngCprSiz - 3) * (2 ^ 8) _ + + bytaryCpr(lngCprSiz - 4) + ReDim Preserve bytaryCpr(lngCprSiz - 5) 'Cut of the original size value + ReDim bytaryOri(lngOriSiz - 1) + If lngfncUcp(bytaryOri(0), lngOriSiz, bytaryCpr(0), lngCprSiz) = SUCCESS +Then + strOriPth = Left(strargFilPth, Len(strargFilPth) - Len(strFilExt)) + Open strOriPth For Binary Access Write As #1 + Put #1, , bytaryOri() + Close #1 + Else + MsgBox "Uncompression error" + End If + Erase bytaryCpr + Erase bytaryOri +End Sub +Public Property Get lngPercentSmaller() As Long + lngPercentSmaller = lngpvtPcnSml +End Property diff --git a/dependencies/zlib-1.2.11/os400/README400 b/dependencies/zlib-1.2.11/os400/README400 new file mode 100644 index 0000000..4f98334 --- /dev/null +++ b/dependencies/zlib-1.2.11/os400/README400 @@ -0,0 +1,48 @@ + ZLIB version 1.2.11 for OS/400 installation instructions + +1) Download and unpack the zlib tarball to some IFS directory. + (i.e.: /path/to/the/zlib/ifs/source/directory) + + If the installed IFS command suppors gzip format, this is straightforward, +else you have to unpack first to some directory on a system supporting it, +then move the whole directory to the IFS via the network (via SMB or FTP). + +2) Edit the configuration parameters in the compilation script. + + EDTF STMF('/path/to/the/zlib/ifs/source/directory/os400/make.sh') + +Tune the parameters according to your needs if not matching the defaults. +Save the file and exit after edition. + +3) Enter qshell, then work in the zlib OS/400 specific directory. + + QSH + cd /path/to/the/zlib/ifs/source/directory/os400 + +4) Compile and install + + sh make.sh + +The script will: +- create the libraries, objects and IFS directories for the zlib environment, +- compile all modules, +- create a service program, +- create a static and a dynamic binding directory, +- install header files for C/C++ and for ILE/RPG, both for compilation in + DB2 and IFS environments. + +That's all. + + +Notes: For OS/400 ILE RPG programmers, a /copy member defining the ZLIB + API prototypes for ILE RPG can be found in ZLIB/H(ZLIB.INC). + In the ILE environment, the same definitions are available from + file zlib.inc located in the same IFS include directory as the + C/C++ header files. + Please read comments in this member for more information. + + Remember that most foreign textual data are ASCII coded: this + implementation does not handle conversion from/to ASCII, so + text data code conversions must be done explicitely. + + Mainly for the reason above, always open zipped files in binary mode. diff --git a/dependencies/zlib-1.2.11/os400/bndsrc b/dependencies/zlib-1.2.11/os400/bndsrc new file mode 100644 index 0000000..5e6e0a2 --- /dev/null +++ b/dependencies/zlib-1.2.11/os400/bndsrc @@ -0,0 +1,119 @@ +STRPGMEXP PGMLVL(*CURRENT) SIGNATURE('ZLIB') + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/* Version 1.1.3 entry points. */ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + EXPORT SYMBOL("adler32") + EXPORT SYMBOL("compress") + EXPORT SYMBOL("compress2") + EXPORT SYMBOL("crc32") + EXPORT SYMBOL("get_crc_table") + EXPORT SYMBOL("deflate") + EXPORT SYMBOL("deflateEnd") + EXPORT SYMBOL("deflateSetDictionary") + EXPORT SYMBOL("deflateCopy") + EXPORT SYMBOL("deflateReset") + EXPORT SYMBOL("deflateParams") + EXPORT SYMBOL("deflatePrime") + EXPORT SYMBOL("deflateInit_") + EXPORT SYMBOL("deflateInit2_") + EXPORT SYMBOL("gzopen") + EXPORT SYMBOL("gzdopen") + EXPORT SYMBOL("gzsetparams") + EXPORT SYMBOL("gzread") + EXPORT SYMBOL("gzwrite") + EXPORT SYMBOL("gzprintf") + EXPORT SYMBOL("gzputs") + EXPORT SYMBOL("gzgets") + EXPORT SYMBOL("gzputc") + EXPORT SYMBOL("gzgetc") + EXPORT SYMBOL("gzflush") + EXPORT SYMBOL("gzseek") + EXPORT SYMBOL("gzrewind") + EXPORT SYMBOL("gztell") + EXPORT SYMBOL("gzeof") + EXPORT SYMBOL("gzclose") + EXPORT SYMBOL("gzerror") + EXPORT SYMBOL("inflate") + EXPORT SYMBOL("inflateEnd") + EXPORT SYMBOL("inflateSetDictionary") + EXPORT SYMBOL("inflateSync") + EXPORT SYMBOL("inflateReset") + EXPORT SYMBOL("inflateInit_") + EXPORT SYMBOL("inflateInit2_") + EXPORT SYMBOL("inflateSyncPoint") + EXPORT SYMBOL("uncompress") + EXPORT SYMBOL("zlibVersion") + EXPORT SYMBOL("zError") + EXPORT SYMBOL("z_errmsg") + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/* Version 1.2.1 additional entry points. */ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + EXPORT SYMBOL("compressBound") + EXPORT SYMBOL("deflateBound") + EXPORT SYMBOL("deflatePending") + EXPORT SYMBOL("gzungetc") + EXPORT SYMBOL("gzclearerr") + EXPORT SYMBOL("inflateBack") + EXPORT SYMBOL("inflateBackEnd") + EXPORT SYMBOL("inflateBackInit_") + EXPORT SYMBOL("inflateCopy") + EXPORT SYMBOL("zlibCompileFlags") + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/* Version 1.2.4 additional entry points. */ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + EXPORT SYMBOL("adler32_combine") + EXPORT SYMBOL("adler32_combine64") + EXPORT SYMBOL("crc32_combine") + EXPORT SYMBOL("crc32_combine64") + EXPORT SYMBOL("deflateSetHeader") + EXPORT SYMBOL("deflateTune") + EXPORT SYMBOL("gzbuffer") + EXPORT SYMBOL("gzclose_r") + EXPORT SYMBOL("gzclose_w") + EXPORT SYMBOL("gzdirect") + EXPORT SYMBOL("gzoffset") + EXPORT SYMBOL("gzoffset64") + EXPORT SYMBOL("gzopen64") + EXPORT SYMBOL("gzseek64") + EXPORT SYMBOL("gztell64") + EXPORT SYMBOL("inflateGetHeader") + EXPORT SYMBOL("inflateMark") + EXPORT SYMBOL("inflatePrime") + EXPORT SYMBOL("inflateReset2") + EXPORT SYMBOL("inflateUndermine") + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/* Version 1.2.6 additional entry points. */ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + EXPORT SYMBOL("deflateResetKeep") + EXPORT SYMBOL("gzgetc_") + EXPORT SYMBOL("inflateResetKeep") + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/* Version 1.2.8 additional entry points. */ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + EXPORT SYMBOL("gzvprintf") + EXPORT SYMBOL("inflateGetDictionary") + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/* Version 1.2.9 additional entry points. */ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + EXPORT SYMBOL("adler32_z") + EXPORT SYMBOL("crc32_z") + EXPORT SYMBOL("deflateGetDictionary") + EXPORT SYMBOL("gzfread") + EXPORT SYMBOL("gzfwrite") + EXPORT SYMBOL("inflateCodesUsed") + EXPORT SYMBOL("inflateValidate") + EXPORT SYMBOL("uncompress2") + +ENDPGMEXP diff --git a/dependencies/zlib-1.2.11/os400/make.sh b/dependencies/zlib-1.2.11/os400/make.sh new file mode 100644 index 0000000..19eec11 --- /dev/null +++ b/dependencies/zlib-1.2.11/os400/make.sh @@ -0,0 +1,366 @@ +#!/bin/sh +# +# ZLIB compilation script for the OS/400. +# +# +# This is a shell script since make is not a standard component of OS/400. + + +################################################################################ +# +# Tunable configuration parameters. +# +################################################################################ + +TARGETLIB='ZLIB' # Target OS/400 program library +STATBNDDIR='ZLIB_A' # Static binding directory. +DYNBNDDIR='ZLIB' # Dynamic binding directory. +SRVPGM="ZLIB" # Service program. +IFSDIR='/zlib' # IFS support base directory. +TGTCCSID='500' # Target CCSID of objects +DEBUG='*NONE' # Debug level +OPTIMIZE='40' # Optimisation level +OUTPUT='*NONE' # Compilation output option. +TGTRLS='V6R1M0' # Target OS release + +export TARGETLIB STATBNDDIR DYNBNDDIR SRVPGM IFSDIR +export TGTCCSID DEBUG OPTIMIZE OUTPUT TGTRLS + + +################################################################################ +# +# OS/400 specific definitions. +# +################################################################################ + +LIBIFSNAME="/QSYS.LIB/${TARGETLIB}.LIB" + + +################################################################################ +# +# Procedures. +# +################################################################################ + +# action_needed dest [src] +# +# dest is an object to build +# if specified, src is an object on which dest depends. +# +# exit 0 (succeeds) if some action has to be taken, else 1. + +action_needed() + +{ + [ ! -e "${1}" ] && return 0 + [ "${2}" ] || return 1 + [ "${1}" -ot "${2}" ] && return 0 + return 1 +} + + +# make_module module_name source_name [additional_definitions] +# +# Compile source name into module if needed. +# As side effect, append the module name to variable MODULES. +# Set LINK to "YES" if the module has been compiled. + +make_module() + +{ + MODULES="${MODULES} ${1}" + MODIFSNAME="${LIBIFSNAME}/${1}.MODULE" + CSRC="`basename \"${2}\"`" + + if action_needed "${MODIFSNAME}" "${2}" + then : + elif [ ! "`sed -e \"//,/<\\\\/source>/!d\" \ + -e '/ tmphdrfile + + # Need to translate to target CCSID. + + CMD="CPY OBJ('`pwd`/tmphdrfile') TOOBJ('${DEST}')" + CMD="${CMD} TOCCSID(${TGTCCSID}) DTAFMT(*TEXT) REPLACE(*YES)" + system "${CMD}" + # touch -r "${HFILE}" "${DEST}" + rm -f tmphdrfile + fi + + IFSFILE="${IFSDIR}/include/`basename \"${HFILE}\"`" + + if action_needed "${IFSFILE}" "${DEST}" + then rm -f "${IFSFILE}" + ln -s "${DEST}" "${IFSFILE}" + fi +done + + +# Install the ILE/RPG header file. + + +HFILE="${SCRIPTDIR}/zlib.inc" +DEST="${SRCPF}/ZLIB.INC.MBR" + +if action_needed "${DEST}" "${HFILE}" +then CMD="CPY OBJ('${HFILE}') TOOBJ('${DEST}')" + CMD="${CMD} TOCCSID(${TGTCCSID}) DTAFMT(*TEXT) REPLACE(*YES)" + system "${CMD}" + # touch -r "${HFILE}" "${DEST}" +fi + +IFSFILE="${IFSDIR}/include/`basename \"${HFILE}\"`" + +if action_needed "${IFSFILE}" "${DEST}" +then rm -f "${IFSFILE}" + ln -s "${DEST}" "${IFSFILE}" +fi + + +# Create and compile the identification source file. + +echo '#pragma comment(user, "ZLIB version '"${VERSION}"'")' > os400.c +echo '#pragma comment(user, __DATE__)' >> os400.c +echo '#pragma comment(user, __TIME__)' >> os400.c +echo '#pragma comment(copyright, "Copyright (C) 1995-2017 Jean-Loup Gailly, Mark Adler. OS/400 version by P. Monnerat.")' >> os400.c +make_module OS400 os400.c +LINK= # No need to rebuild service program yet. +MODULES= + + +# Get source list. + +CSOURCES=`sed -e '/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Library + + Medium + + 2.0 + + + + zlib + zlib + alain.bonnefoy@icbt.com + Public + public + www.gzip.org/zlib + + + Jean-Loup Gailly,Mark Adler + www.gzip.org/zlib + + zlib@gzip.org + + + A massively spiffy yet delicately unobtrusive compression library. + zlib is designed to be a free, general-purpose, legally unencumbered, lossless data compression library for use on virtually any computer hardware and operating system. + http://www.gzip.org/zlib + + + + + 1.2.11 + Medium + Stable + + + + + + + No License + + + + Software Development/Libraries and Extensions/C Libraries + zlib,compression + qnx6 + qnx6 + None + Developer + + + + + + + + + + + + + + Install + Post + No + Ignore + + No + Optional + + + + + + + + + + + + + InstallOver + zlib + + + + + + + + + + + + + InstallOver + zlib-dev + + + + + + + + + diff --git a/dependencies/zlib-1.2.11/test/example.c b/dependencies/zlib-1.2.11/test/example.c new file mode 100644 index 0000000..eee17ce --- /dev/null +++ b/dependencies/zlib-1.2.11/test/example.c @@ -0,0 +1,602 @@ +/* example.c -- usage example of the zlib compression library + * Copyright (C) 1995-2006, 2011, 2016 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zlib.h" +#include + +#ifdef STDC +# include +# include +#endif + +#if defined(VMS) || defined(RISCOS) +# define TESTFILE "foo-gz" +#else +# define TESTFILE "foo.gz" +#endif + +#define CHECK_ERR(err, msg) { \ + if (err != Z_OK) { \ + fprintf(stderr, "%s error: %d\n", msg, err); \ + exit(1); \ + } \ +} + +static z_const char hello[] = "hello, hello!"; +/* "hello world" would be more standard, but the repeated "hello" + * stresses the compression code better, sorry... + */ + +static const char dictionary[] = "hello"; +static uLong dictId; /* Adler32 value of the dictionary */ + +void test_deflate OF((Byte *compr, uLong comprLen)); +void test_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_large_deflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_large_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_flush OF((Byte *compr, uLong *comprLen)); +void test_sync OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_dict_deflate OF((Byte *compr, uLong comprLen)); +void test_dict_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +int main OF((int argc, char *argv[])); + + +#ifdef Z_SOLO + +void *myalloc OF((void *, unsigned, unsigned)); +void myfree OF((void *, void *)); + +void *myalloc(q, n, m) + void *q; + unsigned n, m; +{ + (void)q; + return calloc(n, m); +} + +void myfree(void *q, void *p) +{ + (void)q; + free(p); +} + +static alloc_func zalloc = myalloc; +static free_func zfree = myfree; + +#else /* !Z_SOLO */ + +static alloc_func zalloc = (alloc_func)0; +static free_func zfree = (free_func)0; + +void test_compress OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_gzio OF((const char *fname, + Byte *uncompr, uLong uncomprLen)); + +/* =========================================================================== + * Test compress() and uncompress() + */ +void test_compress(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + uLong len = (uLong)strlen(hello)+1; + + err = compress(compr, &comprLen, (const Bytef*)hello, len); + CHECK_ERR(err, "compress"); + + strcpy((char*)uncompr, "garbage"); + + err = uncompress(uncompr, &uncomprLen, compr, comprLen); + CHECK_ERR(err, "uncompress"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad uncompress\n"); + exit(1); + } else { + printf("uncompress(): %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Test read/write of .gz files + */ +void test_gzio(fname, uncompr, uncomprLen) + const char *fname; /* compressed file name */ + Byte *uncompr; + uLong uncomprLen; +{ +#ifdef NO_GZCOMPRESS + fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n"); +#else + int err; + int len = (int)strlen(hello)+1; + gzFile file; + z_off_t pos; + + file = gzopen(fname, "wb"); + if (file == NULL) { + fprintf(stderr, "gzopen error\n"); + exit(1); + } + gzputc(file, 'h'); + if (gzputs(file, "ello") != 4) { + fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err)); + exit(1); + } + if (gzprintf(file, ", %s!", "hello") != 8) { + fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err)); + exit(1); + } + gzseek(file, 1L, SEEK_CUR); /* add one zero byte */ + gzclose(file); + + file = gzopen(fname, "rb"); + if (file == NULL) { + fprintf(stderr, "gzopen error\n"); + exit(1); + } + strcpy((char*)uncompr, "garbage"); + + if (gzread(file, uncompr, (unsigned)uncomprLen) != len) { + fprintf(stderr, "gzread err: %s\n", gzerror(file, &err)); + exit(1); + } + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad gzread: %s\n", (char*)uncompr); + exit(1); + } else { + printf("gzread(): %s\n", (char*)uncompr); + } + + pos = gzseek(file, -8L, SEEK_CUR); + if (pos != 6 || gztell(file) != pos) { + fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n", + (long)pos, (long)gztell(file)); + exit(1); + } + + if (gzgetc(file) != ' ') { + fprintf(stderr, "gzgetc error\n"); + exit(1); + } + + if (gzungetc(' ', file) != ' ') { + fprintf(stderr, "gzungetc error\n"); + exit(1); + } + + gzgets(file, (char*)uncompr, (int)uncomprLen); + if (strlen((char*)uncompr) != 7) { /* " hello!" */ + fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err)); + exit(1); + } + if (strcmp((char*)uncompr, hello + 6)) { + fprintf(stderr, "bad gzgets after gzseek\n"); + exit(1); + } else { + printf("gzgets() after gzseek: %s\n", (char*)uncompr); + } + + gzclose(file); +#endif +} + +#endif /* Z_SOLO */ + +/* =========================================================================== + * Test deflate() with small buffers + */ +void test_deflate(compr, comprLen) + Byte *compr; + uLong comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + uLong len = (uLong)strlen(hello)+1; + + c_stream.zalloc = zalloc; + c_stream.zfree = zfree; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_in = (z_const unsigned char *)hello; + c_stream.next_out = compr; + + while (c_stream.total_in != len && c_stream.total_out < comprLen) { + c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + } + /* Finish the stream, still forcing small buffers: */ + for (;;) { + c_stream.avail_out = 1; + err = deflate(&c_stream, Z_FINISH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "deflate"); + } + + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with small buffers + */ +void test_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = zalloc; + d_stream.zfree = zfree; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = 0; + d_stream.next_out = uncompr; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) { + d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */ + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "inflate"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad inflate\n"); + exit(1); + } else { + printf("inflate(): %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Test deflate() with large buffers and dynamic change of compression level + */ +void test_large_deflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + + c_stream.zalloc = zalloc; + c_stream.zfree = zfree; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_BEST_SPEED); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_out = compr; + c_stream.avail_out = (uInt)comprLen; + + /* At this point, uncompr is still mostly zeroes, so it should compress + * very well: + */ + c_stream.next_in = uncompr; + c_stream.avail_in = (uInt)uncomprLen; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + if (c_stream.avail_in != 0) { + fprintf(stderr, "deflate not greedy\n"); + exit(1); + } + + /* Feed in already compressed data and switch to no compression: */ + deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); + c_stream.next_in = compr; + c_stream.avail_in = (uInt)comprLen/2; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + + /* Switch back to compressing mode: */ + deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED); + c_stream.next_in = uncompr; + c_stream.avail_in = (uInt)uncomprLen; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + fprintf(stderr, "deflate should report Z_STREAM_END\n"); + exit(1); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with large buffers + */ +void test_large_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = zalloc; + d_stream.zfree = zfree; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = (uInt)comprLen; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + for (;;) { + d_stream.next_out = uncompr; /* discard the output */ + d_stream.avail_out = (uInt)uncomprLen; + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "large inflate"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (d_stream.total_out != 2*uncomprLen + comprLen/2) { + fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out); + exit(1); + } else { + printf("large_inflate(): OK\n"); + } +} + +/* =========================================================================== + * Test deflate() with full flush + */ +void test_flush(compr, comprLen) + Byte *compr; + uLong *comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + uInt len = (uInt)strlen(hello)+1; + + c_stream.zalloc = zalloc; + c_stream.zfree = zfree; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_in = (z_const unsigned char *)hello; + c_stream.next_out = compr; + c_stream.avail_in = 3; + c_stream.avail_out = (uInt)*comprLen; + err = deflate(&c_stream, Z_FULL_FLUSH); + CHECK_ERR(err, "deflate"); + + compr[3]++; /* force an error in first compressed block */ + c_stream.avail_in = len - 3; + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + CHECK_ERR(err, "deflate"); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); + + *comprLen = c_stream.total_out; +} + +/* =========================================================================== + * Test inflateSync() + */ +void test_sync(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = zalloc; + d_stream.zfree = zfree; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = 2; /* just read the zlib header */ + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + d_stream.next_out = uncompr; + d_stream.avail_out = (uInt)uncomprLen; + + err = inflate(&d_stream, Z_NO_FLUSH); + CHECK_ERR(err, "inflate"); + + d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */ + err = inflateSync(&d_stream); /* but skip the damaged part */ + CHECK_ERR(err, "inflateSync"); + + err = inflate(&d_stream, Z_FINISH); + if (err != Z_DATA_ERROR) { + fprintf(stderr, "inflate should report DATA_ERROR\n"); + /* Because of incorrect adler32 */ + exit(1); + } + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + printf("after inflateSync(): hel%s\n", (char *)uncompr); +} + +/* =========================================================================== + * Test deflate() with preset dictionary + */ +void test_dict_deflate(compr, comprLen) + Byte *compr; + uLong comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + + c_stream.zalloc = zalloc; + c_stream.zfree = zfree; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_BEST_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + err = deflateSetDictionary(&c_stream, + (const Bytef*)dictionary, (int)sizeof(dictionary)); + CHECK_ERR(err, "deflateSetDictionary"); + + dictId = c_stream.adler; + c_stream.next_out = compr; + c_stream.avail_out = (uInt)comprLen; + + c_stream.next_in = (z_const unsigned char *)hello; + c_stream.avail_in = (uInt)strlen(hello)+1; + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + fprintf(stderr, "deflate should report Z_STREAM_END\n"); + exit(1); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with a preset dictionary + */ +void test_dict_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = zalloc; + d_stream.zfree = zfree; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = (uInt)comprLen; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + d_stream.next_out = uncompr; + d_stream.avail_out = (uInt)uncomprLen; + + for (;;) { + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + if (err == Z_NEED_DICT) { + if (d_stream.adler != dictId) { + fprintf(stderr, "unexpected dictionary"); + exit(1); + } + err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary, + (int)sizeof(dictionary)); + } + CHECK_ERR(err, "inflate with dict"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad inflate with dict\n"); + exit(1); + } else { + printf("inflate with dictionary: %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Usage: example [output.gz [input.gz]] + */ + +int main(argc, argv) + int argc; + char *argv[]; +{ + Byte *compr, *uncompr; + uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */ + uLong uncomprLen = comprLen; + static const char* myVersion = ZLIB_VERSION; + + if (zlibVersion()[0] != myVersion[0]) { + fprintf(stderr, "incompatible zlib version\n"); + exit(1); + + } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) { + fprintf(stderr, "warning: different zlib version\n"); + } + + printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n", + ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags()); + + compr = (Byte*)calloc((uInt)comprLen, 1); + uncompr = (Byte*)calloc((uInt)uncomprLen, 1); + /* compr and uncompr are cleared to avoid reading uninitialized + * data and to ensure that uncompr compresses well. + */ + if (compr == Z_NULL || uncompr == Z_NULL) { + printf("out of memory\n"); + exit(1); + } + +#ifdef Z_SOLO + (void)argc; + (void)argv; +#else + test_compress(compr, comprLen, uncompr, uncomprLen); + + test_gzio((argc > 1 ? argv[1] : TESTFILE), + uncompr, uncomprLen); +#endif + + test_deflate(compr, comprLen); + test_inflate(compr, comprLen, uncompr, uncomprLen); + + test_large_deflate(compr, comprLen, uncompr, uncomprLen); + test_large_inflate(compr, comprLen, uncompr, uncomprLen); + + test_flush(compr, &comprLen); + test_sync(compr, comprLen, uncompr, uncomprLen); + comprLen = uncomprLen; + + test_dict_deflate(compr, comprLen); + test_dict_inflate(compr, comprLen, uncompr, uncomprLen); + + free(compr); + free(uncompr); + + return 0; +} diff --git a/dependencies/zlib-1.2.11/test/infcover.c b/dependencies/zlib-1.2.11/test/infcover.c new file mode 100644 index 0000000..2be0164 --- /dev/null +++ b/dependencies/zlib-1.2.11/test/infcover.c @@ -0,0 +1,671 @@ +/* infcover.c -- test zlib's inflate routines with full code coverage + * Copyright (C) 2011, 2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* to use, do: ./configure --cover && make cover */ + +#include +#include +#include +#include +#include "zlib.h" + +/* get definition of internal structure so we can mess with it (see pull()), + and so we can call inflate_trees() (see cover5()) */ +#define ZLIB_INTERNAL +#include "inftrees.h" +#include "inflate.h" + +#define local static + +/* -- memory tracking routines -- */ + +/* + These memory tracking routines are provided to zlib and track all of zlib's + allocations and deallocations, check for LIFO operations, keep a current + and high water mark of total bytes requested, optionally set a limit on the + total memory that can be allocated, and when done check for memory leaks. + + They are used as follows: + + z_stream strm; + mem_setup(&strm) initializes the memory tracking and sets the + zalloc, zfree, and opaque members of strm to use + memory tracking for all zlib operations on strm + mem_limit(&strm, limit) sets a limit on the total bytes requested -- a + request that exceeds this limit will result in an + allocation failure (returns NULL) -- setting the + limit to zero means no limit, which is the default + after mem_setup() + mem_used(&strm, "msg") prints to stderr "msg" and the total bytes used + mem_high(&strm, "msg") prints to stderr "msg" and the high water mark + mem_done(&strm, "msg") ends memory tracking, releases all allocations + for the tracking as well as leaked zlib blocks, if + any. If there was anything unusual, such as leaked + blocks, non-FIFO frees, or frees of addresses not + allocated, then "msg" and information about the + problem is printed to stderr. If everything is + normal, nothing is printed. mem_done resets the + strm members to Z_NULL to use the default memory + allocation routines on the next zlib initialization + using strm. + */ + +/* these items are strung together in a linked list, one for each allocation */ +struct mem_item { + void *ptr; /* pointer to allocated memory */ + size_t size; /* requested size of allocation */ + struct mem_item *next; /* pointer to next item in list, or NULL */ +}; + +/* this structure is at the root of the linked list, and tracks statistics */ +struct mem_zone { + struct mem_item *first; /* pointer to first item in list, or NULL */ + size_t total, highwater; /* total allocations, and largest total */ + size_t limit; /* memory allocation limit, or 0 if no limit */ + int notlifo, rogue; /* counts of non-LIFO frees and rogue frees */ +}; + +/* memory allocation routine to pass to zlib */ +local void *mem_alloc(void *mem, unsigned count, unsigned size) +{ + void *ptr; + struct mem_item *item; + struct mem_zone *zone = mem; + size_t len = count * (size_t)size; + + /* induced allocation failure */ + if (zone == NULL || (zone->limit && zone->total + len > zone->limit)) + return NULL; + + /* perform allocation using the standard library, fill memory with a + non-zero value to make sure that the code isn't depending on zeros */ + ptr = malloc(len); + if (ptr == NULL) + return NULL; + memset(ptr, 0xa5, len); + + /* create a new item for the list */ + item = malloc(sizeof(struct mem_item)); + if (item == NULL) { + free(ptr); + return NULL; + } + item->ptr = ptr; + item->size = len; + + /* insert item at the beginning of the list */ + item->next = zone->first; + zone->first = item; + + /* update the statistics */ + zone->total += item->size; + if (zone->total > zone->highwater) + zone->highwater = zone->total; + + /* return the allocated memory */ + return ptr; +} + +/* memory free routine to pass to zlib */ +local void mem_free(void *mem, void *ptr) +{ + struct mem_item *item, *next; + struct mem_zone *zone = mem; + + /* if no zone, just do a free */ + if (zone == NULL) { + free(ptr); + return; + } + + /* point next to the item that matches ptr, or NULL if not found -- remove + the item from the linked list if found */ + next = zone->first; + if (next) { + if (next->ptr == ptr) + zone->first = next->next; /* first one is it, remove from list */ + else { + do { /* search the linked list */ + item = next; + next = item->next; + } while (next != NULL && next->ptr != ptr); + if (next) { /* if found, remove from linked list */ + item->next = next->next; + zone->notlifo++; /* not a LIFO free */ + } + + } + } + + /* if found, update the statistics and free the item */ + if (next) { + zone->total -= next->size; + free(next); + } + + /* if not found, update the rogue count */ + else + zone->rogue++; + + /* in any case, do the requested free with the standard library function */ + free(ptr); +} + +/* set up a controlled memory allocation space for monitoring, set the stream + parameters to the controlled routines, with opaque pointing to the space */ +local void mem_setup(z_stream *strm) +{ + struct mem_zone *zone; + + zone = malloc(sizeof(struct mem_zone)); + assert(zone != NULL); + zone->first = NULL; + zone->total = 0; + zone->highwater = 0; + zone->limit = 0; + zone->notlifo = 0; + zone->rogue = 0; + strm->opaque = zone; + strm->zalloc = mem_alloc; + strm->zfree = mem_free; +} + +/* set a limit on the total memory allocation, or 0 to remove the limit */ +local void mem_limit(z_stream *strm, size_t limit) +{ + struct mem_zone *zone = strm->opaque; + + zone->limit = limit; +} + +/* show the current total requested allocations in bytes */ +local void mem_used(z_stream *strm, char *prefix) +{ + struct mem_zone *zone = strm->opaque; + + fprintf(stderr, "%s: %lu allocated\n", prefix, zone->total); +} + +/* show the high water allocation in bytes */ +local void mem_high(z_stream *strm, char *prefix) +{ + struct mem_zone *zone = strm->opaque; + + fprintf(stderr, "%s: %lu high water mark\n", prefix, zone->highwater); +} + +/* release the memory allocation zone -- if there are any surprises, notify */ +local void mem_done(z_stream *strm, char *prefix) +{ + int count = 0; + struct mem_item *item, *next; + struct mem_zone *zone = strm->opaque; + + /* show high water mark */ + mem_high(strm, prefix); + + /* free leftover allocations and item structures, if any */ + item = zone->first; + while (item != NULL) { + free(item->ptr); + next = item->next; + free(item); + item = next; + count++; + } + + /* issue alerts about anything unexpected */ + if (count || zone->total) + fprintf(stderr, "** %s: %lu bytes in %d blocks not freed\n", + prefix, zone->total, count); + if (zone->notlifo) + fprintf(stderr, "** %s: %d frees not LIFO\n", prefix, zone->notlifo); + if (zone->rogue) + fprintf(stderr, "** %s: %d frees not recognized\n", + prefix, zone->rogue); + + /* free the zone and delete from the stream */ + free(zone); + strm->opaque = Z_NULL; + strm->zalloc = Z_NULL; + strm->zfree = Z_NULL; +} + +/* -- inflate test routines -- */ + +/* Decode a hexadecimal string, set *len to length, in[] to the bytes. This + decodes liberally, in that hex digits can be adjacent, in which case two in + a row writes a byte. Or they can be delimited by any non-hex character, + where the delimiters are ignored except when a single hex digit is followed + by a delimiter, where that single digit writes a byte. The returned data is + allocated and must eventually be freed. NULL is returned if out of memory. + If the length is not needed, then len can be NULL. */ +local unsigned char *h2b(const char *hex, unsigned *len) +{ + unsigned char *in, *re; + unsigned next, val; + + in = malloc((strlen(hex) + 1) >> 1); + if (in == NULL) + return NULL; + next = 0; + val = 1; + do { + if (*hex >= '0' && *hex <= '9') + val = (val << 4) + *hex - '0'; + else if (*hex >= 'A' && *hex <= 'F') + val = (val << 4) + *hex - 'A' + 10; + else if (*hex >= 'a' && *hex <= 'f') + val = (val << 4) + *hex - 'a' + 10; + else if (val != 1 && val < 32) /* one digit followed by delimiter */ + val += 240; /* make it look like two digits */ + if (val > 255) { /* have two digits */ + in[next++] = val & 0xff; /* save the decoded byte */ + val = 1; /* start over */ + } + } while (*hex++); /* go through the loop with the terminating null */ + if (len != NULL) + *len = next; + re = realloc(in, next); + return re == NULL ? in : re; +} + +/* generic inflate() run, where hex is the hexadecimal input data, what is the + text to include in an error message, step is how much input data to feed + inflate() on each call, or zero to feed it all, win is the window bits + parameter to inflateInit2(), len is the size of the output buffer, and err + is the error code expected from the first inflate() call (the second + inflate() call is expected to return Z_STREAM_END). If win is 47, then + header information is collected with inflateGetHeader(). If a zlib stream + is looking for a dictionary, then an empty dictionary is provided. + inflate() is run until all of the input data is consumed. */ +local void inf(char *hex, char *what, unsigned step, int win, unsigned len, + int err) +{ + int ret; + unsigned have; + unsigned char *in, *out; + z_stream strm, copy; + gz_header head; + + mem_setup(&strm); + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit2(&strm, win); + if (ret != Z_OK) { + mem_done(&strm, what); + return; + } + out = malloc(len); assert(out != NULL); + if (win == 47) { + head.extra = out; + head.extra_max = len; + head.name = out; + head.name_max = len; + head.comment = out; + head.comm_max = len; + ret = inflateGetHeader(&strm, &head); assert(ret == Z_OK); + } + in = h2b(hex, &have); assert(in != NULL); + if (step == 0 || step > have) + step = have; + strm.avail_in = step; + have -= step; + strm.next_in = in; + do { + strm.avail_out = len; + strm.next_out = out; + ret = inflate(&strm, Z_NO_FLUSH); assert(err == 9 || ret == err); + if (ret != Z_OK && ret != Z_BUF_ERROR && ret != Z_NEED_DICT) + break; + if (ret == Z_NEED_DICT) { + ret = inflateSetDictionary(&strm, in, 1); + assert(ret == Z_DATA_ERROR); + mem_limit(&strm, 1); + ret = inflateSetDictionary(&strm, out, 0); + assert(ret == Z_MEM_ERROR); + mem_limit(&strm, 0); + ((struct inflate_state *)strm.state)->mode = DICT; + ret = inflateSetDictionary(&strm, out, 0); + assert(ret == Z_OK); + ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_BUF_ERROR); + } + ret = inflateCopy(©, &strm); assert(ret == Z_OK); + ret = inflateEnd(©); assert(ret == Z_OK); + err = 9; /* don't care next time around */ + have += strm.avail_in; + strm.avail_in = step > have ? have : step; + have -= strm.avail_in; + } while (strm.avail_in); + free(in); + free(out); + ret = inflateReset2(&strm, -8); assert(ret == Z_OK); + ret = inflateEnd(&strm); assert(ret == Z_OK); + mem_done(&strm, what); +} + +/* cover all of the lines in inflate.c up to inflate() */ +local void cover_support(void) +{ + int ret; + z_stream strm; + + mem_setup(&strm); + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit(&strm); assert(ret == Z_OK); + mem_used(&strm, "inflate init"); + ret = inflatePrime(&strm, 5, 31); assert(ret == Z_OK); + ret = inflatePrime(&strm, -1, 0); assert(ret == Z_OK); + ret = inflateSetDictionary(&strm, Z_NULL, 0); + assert(ret == Z_STREAM_ERROR); + ret = inflateEnd(&strm); assert(ret == Z_OK); + mem_done(&strm, "prime"); + + inf("63 0", "force window allocation", 0, -15, 1, Z_OK); + inf("63 18 5", "force window replacement", 0, -8, 259, Z_OK); + inf("63 18 68 30 d0 0 0", "force split window update", 4, -8, 259, Z_OK); + inf("3 0", "use fixed blocks", 0, -15, 1, Z_STREAM_END); + inf("", "bad window size", 0, 1, 0, Z_STREAM_ERROR); + + mem_setup(&strm); + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit_(&strm, ZLIB_VERSION - 1, (int)sizeof(z_stream)); + assert(ret == Z_VERSION_ERROR); + mem_done(&strm, "wrong version"); + + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit(&strm); assert(ret == Z_OK); + ret = inflateEnd(&strm); assert(ret == Z_OK); + fputs("inflate built-in memory routines\n", stderr); +} + +/* cover all inflate() header and trailer cases and code after inflate() */ +local void cover_wrap(void) +{ + int ret; + z_stream strm, copy; + unsigned char dict[257]; + + ret = inflate(Z_NULL, 0); assert(ret == Z_STREAM_ERROR); + ret = inflateEnd(Z_NULL); assert(ret == Z_STREAM_ERROR); + ret = inflateCopy(Z_NULL, Z_NULL); assert(ret == Z_STREAM_ERROR); + fputs("inflate bad parameters\n", stderr); + + inf("1f 8b 0 0", "bad gzip method", 0, 31, 0, Z_DATA_ERROR); + inf("1f 8b 8 80", "bad gzip flags", 0, 31, 0, Z_DATA_ERROR); + inf("77 85", "bad zlib method", 0, 15, 0, Z_DATA_ERROR); + inf("8 99", "set window size from header", 0, 0, 0, Z_OK); + inf("78 9c", "bad zlib window size", 0, 8, 0, Z_DATA_ERROR); + inf("78 9c 63 0 0 0 1 0 1", "check adler32", 0, 15, 1, Z_STREAM_END); + inf("1f 8b 8 1e 0 0 0 0 0 0 1 0 0 0 0 0 0", "bad header crc", 0, 47, 1, + Z_DATA_ERROR); + inf("1f 8b 8 2 0 0 0 0 0 0 1d 26 3 0 0 0 0 0 0 0 0 0", "check gzip length", + 0, 47, 0, Z_STREAM_END); + inf("78 90", "bad zlib header check", 0, 47, 0, Z_DATA_ERROR); + inf("8 b8 0 0 0 1", "need dictionary", 0, 8, 0, Z_NEED_DICT); + inf("78 9c 63 0", "compute adler32", 0, 15, 1, Z_OK); + + mem_setup(&strm); + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit2(&strm, -8); + strm.avail_in = 2; + strm.next_in = (void *)"\x63"; + strm.avail_out = 1; + strm.next_out = (void *)&ret; + mem_limit(&strm, 1); + ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR); + ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR); + mem_limit(&strm, 0); + memset(dict, 0, 257); + ret = inflateSetDictionary(&strm, dict, 257); + assert(ret == Z_OK); + mem_limit(&strm, (sizeof(struct inflate_state) << 1) + 256); + ret = inflatePrime(&strm, 16, 0); assert(ret == Z_OK); + strm.avail_in = 2; + strm.next_in = (void *)"\x80"; + ret = inflateSync(&strm); assert(ret == Z_DATA_ERROR); + ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_STREAM_ERROR); + strm.avail_in = 4; + strm.next_in = (void *)"\0\0\xff\xff"; + ret = inflateSync(&strm); assert(ret == Z_OK); + (void)inflateSyncPoint(&strm); + ret = inflateCopy(©, &strm); assert(ret == Z_MEM_ERROR); + mem_limit(&strm, 0); + ret = inflateUndermine(&strm, 1); assert(ret == Z_DATA_ERROR); + (void)inflateMark(&strm); + ret = inflateEnd(&strm); assert(ret == Z_OK); + mem_done(&strm, "miscellaneous, force memory errors"); +} + +/* input and output functions for inflateBack() */ +local unsigned pull(void *desc, unsigned char **buf) +{ + static unsigned int next = 0; + static unsigned char dat[] = {0x63, 0, 2, 0}; + struct inflate_state *state; + + if (desc == Z_NULL) { + next = 0; + return 0; /* no input (already provided at next_in) */ + } + state = (void *)((z_stream *)desc)->state; + if (state != Z_NULL) + state->mode = SYNC; /* force an otherwise impossible situation */ + return next < sizeof(dat) ? (*buf = dat + next++, 1) : 0; +} + +local int push(void *desc, unsigned char *buf, unsigned len) +{ + buf += len; + return desc != Z_NULL; /* force error if desc not null */ +} + +/* cover inflateBack() up to common deflate data cases and after those */ +local void cover_back(void) +{ + int ret; + z_stream strm; + unsigned char win[32768]; + + ret = inflateBackInit_(Z_NULL, 0, win, 0, 0); + assert(ret == Z_VERSION_ERROR); + ret = inflateBackInit(Z_NULL, 0, win); assert(ret == Z_STREAM_ERROR); + ret = inflateBack(Z_NULL, Z_NULL, Z_NULL, Z_NULL, Z_NULL); + assert(ret == Z_STREAM_ERROR); + ret = inflateBackEnd(Z_NULL); assert(ret == Z_STREAM_ERROR); + fputs("inflateBack bad parameters\n", stderr); + + mem_setup(&strm); + ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK); + strm.avail_in = 2; + strm.next_in = (void *)"\x03"; + ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL); + assert(ret == Z_STREAM_END); + /* force output error */ + strm.avail_in = 3; + strm.next_in = (void *)"\x63\x00"; + ret = inflateBack(&strm, pull, Z_NULL, push, &strm); + assert(ret == Z_BUF_ERROR); + /* force mode error by mucking with state */ + ret = inflateBack(&strm, pull, &strm, push, Z_NULL); + assert(ret == Z_STREAM_ERROR); + ret = inflateBackEnd(&strm); assert(ret == Z_OK); + mem_done(&strm, "inflateBack bad state"); + + ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK); + ret = inflateBackEnd(&strm); assert(ret == Z_OK); + fputs("inflateBack built-in memory routines\n", stderr); +} + +/* do a raw inflate of data in hexadecimal with both inflate and inflateBack */ +local int try(char *hex, char *id, int err) +{ + int ret; + unsigned len, size; + unsigned char *in, *out, *win; + char *prefix; + z_stream strm; + + /* convert to hex */ + in = h2b(hex, &len); + assert(in != NULL); + + /* allocate work areas */ + size = len << 3; + out = malloc(size); + assert(out != NULL); + win = malloc(32768); + assert(win != NULL); + prefix = malloc(strlen(id) + 6); + assert(prefix != NULL); + + /* first with inflate */ + strcpy(prefix, id); + strcat(prefix, "-late"); + mem_setup(&strm); + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit2(&strm, err < 0 ? 47 : -15); + assert(ret == Z_OK); + strm.avail_in = len; + strm.next_in = in; + do { + strm.avail_out = size; + strm.next_out = out; + ret = inflate(&strm, Z_TREES); + assert(ret != Z_STREAM_ERROR && ret != Z_MEM_ERROR); + if (ret == Z_DATA_ERROR || ret == Z_NEED_DICT) + break; + } while (strm.avail_in || strm.avail_out == 0); + if (err) { + assert(ret == Z_DATA_ERROR); + assert(strcmp(id, strm.msg) == 0); + } + inflateEnd(&strm); + mem_done(&strm, prefix); + + /* then with inflateBack */ + if (err >= 0) { + strcpy(prefix, id); + strcat(prefix, "-back"); + mem_setup(&strm); + ret = inflateBackInit(&strm, 15, win); + assert(ret == Z_OK); + strm.avail_in = len; + strm.next_in = in; + ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL); + assert(ret != Z_STREAM_ERROR); + if (err) { + assert(ret == Z_DATA_ERROR); + assert(strcmp(id, strm.msg) == 0); + } + inflateBackEnd(&strm); + mem_done(&strm, prefix); + } + + /* clean up */ + free(prefix); + free(win); + free(out); + free(in); + return ret; +} + +/* cover deflate data cases in both inflate() and inflateBack() */ +local void cover_inflate(void) +{ + try("0 0 0 0 0", "invalid stored block lengths", 1); + try("3 0", "fixed", 0); + try("6", "invalid block type", 1); + try("1 1 0 fe ff 0", "stored", 0); + try("fc 0 0", "too many length or distance symbols", 1); + try("4 0 fe ff", "invalid code lengths set", 1); + try("4 0 24 49 0", "invalid bit length repeat", 1); + try("4 0 24 e9 ff ff", "invalid bit length repeat", 1); + try("4 0 24 e9 ff 6d", "invalid code -- missing end-of-block", 1); + try("4 80 49 92 24 49 92 24 71 ff ff 93 11 0", + "invalid literal/lengths set", 1); + try("4 80 49 92 24 49 92 24 f b4 ff ff c3 84", "invalid distances set", 1); + try("4 c0 81 8 0 0 0 0 20 7f eb b 0 0", "invalid literal/length code", 1); + try("2 7e ff ff", "invalid distance code", 1); + try("c c0 81 0 0 0 0 0 90 ff 6b 4 0", "invalid distance too far back", 1); + + /* also trailer mismatch just in inflate() */ + try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 1", "incorrect data check", -1); + try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 1", + "incorrect length check", -1); + try("5 c0 21 d 0 0 0 80 b0 fe 6d 2f 91 6c", "pull 17", 0); + try("5 e0 81 91 24 cb b2 2c 49 e2 f 2e 8b 9a 47 56 9f fb fe ec d2 ff 1f", + "long code", 0); + try("ed c0 1 1 0 0 0 40 20 ff 57 1b 42 2c 4f", "length extra", 0); + try("ed cf c1 b1 2c 47 10 c4 30 fa 6f 35 1d 1 82 59 3d fb be 2e 2a fc f c", + "long distance and extra", 0); + try("ed c0 81 0 0 0 0 80 a0 fd a9 17 a9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6", "window end", 0); + inf("2 8 20 80 0 3 0", "inflate_fast TYPE return", 0, -15, 258, + Z_STREAM_END); + inf("63 18 5 40 c 0", "window wrap", 3, -8, 300, Z_OK); +} + +/* cover remaining lines in inftrees.c */ +local void cover_trees(void) +{ + int ret; + unsigned bits; + unsigned short lens[16], work[16]; + code *next, table[ENOUGH_DISTS]; + + /* we need to call inflate_table() directly in order to manifest not- + enough errors, since zlib insures that enough is always enough */ + for (bits = 0; bits < 15; bits++) + lens[bits] = (unsigned short)(bits + 1); + lens[15] = 15; + next = table; + bits = 15; + ret = inflate_table(DISTS, lens, 16, &next, &bits, work); + assert(ret == 1); + next = table; + bits = 1; + ret = inflate_table(DISTS, lens, 16, &next, &bits, work); + assert(ret == 1); + fputs("inflate_table not enough errors\n", stderr); +} + +/* cover remaining inffast.c decoding and window copying */ +local void cover_fast(void) +{ + inf("e5 e0 81 ad 6d cb b2 2c c9 01 1e 59 63 ae 7d ee fb 4d fd b5 35 41 68" + " ff 7f 0f 0 0 0", "fast length extra bits", 0, -8, 258, Z_DATA_ERROR); + inf("25 fd 81 b5 6d 59 b6 6a 49 ea af 35 6 34 eb 8c b9 f6 b9 1e ef 67 49" + " 50 fe ff ff 3f 0 0", "fast distance extra bits", 0, -8, 258, + Z_DATA_ERROR); + inf("3 7e 0 0 0 0 0", "fast invalid distance code", 0, -8, 258, + Z_DATA_ERROR); + inf("1b 7 0 0 0 0 0", "fast invalid literal/length code", 0, -8, 258, + Z_DATA_ERROR); + inf("d c7 1 ae eb 38 c 4 41 a0 87 72 de df fb 1f b8 36 b1 38 5d ff ff 0", + "fast 2nd level codes and too far back", 0, -8, 258, Z_DATA_ERROR); + inf("63 18 5 8c 10 8 0 0 0 0", "very common case", 0, -8, 259, Z_OK); + inf("63 60 60 18 c9 0 8 18 18 18 26 c0 28 0 29 0 0 0", + "contiguous and wrap around window", 6, -8, 259, Z_OK); + inf("63 0 3 0 0 0 0 0", "copy direct from output", 0, -8, 259, + Z_STREAM_END); +} + +int main(void) +{ + fprintf(stderr, "%s\n", zlibVersion()); + cover_support(); + cover_wrap(); + cover_back(); + cover_inflate(); + cover_trees(); + cover_fast(); + return 0; +} diff --git a/dependencies/zlib-1.2.11/test/minigzip.c b/dependencies/zlib-1.2.11/test/minigzip.c new file mode 100644 index 0000000..e22fb08 --- /dev/null +++ b/dependencies/zlib-1.2.11/test/minigzip.c @@ -0,0 +1,651 @@ +/* minigzip.c -- simulate gzip using the zlib compression library + * Copyright (C) 1995-2006, 2010, 2011, 2016 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * minigzip is a minimal implementation of the gzip utility. This is + * only an example of using zlib and isn't meant to replace the + * full-featured gzip. No attempt is made to deal with file systems + * limiting names to 14 or 8+3 characters, etc... Error checking is + * very limited. So use minigzip only for testing; use gzip for the + * real thing. On MSDOS, use only on file names without extension + * or in pipe mode. + */ + +/* @(#) $Id$ */ + +#include "zlib.h" +#include + +#ifdef STDC +# include +# include +#endif + +#ifdef USE_MMAP +# include +# include +# include +#endif + +#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) +# include +# include +# ifdef UNDER_CE +# include +# endif +# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) +#else +# define SET_BINARY_MODE(file) +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1900 +# define snprintf _snprintf +#endif + +#ifdef VMS +# define unlink delete +# define GZ_SUFFIX "-gz" +#endif +#ifdef RISCOS +# define unlink remove +# define GZ_SUFFIX "-gz" +# define fileno(file) file->__file +#endif +#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fileno */ +#endif + +#if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE) +#ifndef WIN32 /* unlink already in stdio.h for WIN32 */ + extern int unlink OF((const char *)); +#endif +#endif + +#if defined(UNDER_CE) +# include +# define perror(s) pwinerror(s) + +/* Map the Windows error number in ERROR to a locale-dependent error + message string and return a pointer to it. Typically, the values + for ERROR come from GetLastError. + + The string pointed to shall not be modified by the application, + but may be overwritten by a subsequent call to strwinerror + + The strwinerror function does not change the current setting + of GetLastError. */ + +static char *strwinerror (error) + DWORD error; +{ + static char buf[1024]; + + wchar_t *msgbuf; + DWORD lasterr = GetLastError(); + DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, + error, + 0, /* Default language */ + (LPVOID)&msgbuf, + 0, + NULL); + if (chars != 0) { + /* If there is an \r\n appended, zap it. */ + if (chars >= 2 + && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { + chars -= 2; + msgbuf[chars] = 0; + } + + if (chars > sizeof (buf) - 1) { + chars = sizeof (buf) - 1; + msgbuf[chars] = 0; + } + + wcstombs(buf, msgbuf, chars + 1); + LocalFree(msgbuf); + } + else { + sprintf(buf, "unknown win32 error (%ld)", error); + } + + SetLastError(lasterr); + return buf; +} + +static void pwinerror (s) + const char *s; +{ + if (s && *s) + fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ())); + else + fprintf(stderr, "%s\n", strwinerror(GetLastError ())); +} + +#endif /* UNDER_CE */ + +#ifndef GZ_SUFFIX +# define GZ_SUFFIX ".gz" +#endif +#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1) + +#define BUFLEN 16384 +#define MAX_NAME_LEN 1024 + +#ifdef MAXSEG_64K +# define local static + /* Needed for systems with limitation on stack size. */ +#else +# define local +#endif + +#ifdef Z_SOLO +/* for Z_SOLO, create simplified gz* functions using deflate and inflate */ + +#if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE) +# include /* for unlink() */ +#endif + +void *myalloc OF((void *, unsigned, unsigned)); +void myfree OF((void *, void *)); + +void *myalloc(q, n, m) + void *q; + unsigned n, m; +{ + (void)q; + return calloc(n, m); +} + +void myfree(q, p) + void *q, *p; +{ + (void)q; + free(p); +} + +typedef struct gzFile_s { + FILE *file; + int write; + int err; + char *msg; + z_stream strm; +} *gzFile; + +gzFile gzopen OF((const char *, const char *)); +gzFile gzdopen OF((int, const char *)); +gzFile gz_open OF((const char *, int, const char *)); + +gzFile gzopen(path, mode) +const char *path; +const char *mode; +{ + return gz_open(path, -1, mode); +} + +gzFile gzdopen(fd, mode) +int fd; +const char *mode; +{ + return gz_open(NULL, fd, mode); +} + +gzFile gz_open(path, fd, mode) + const char *path; + int fd; + const char *mode; +{ + gzFile gz; + int ret; + + gz = malloc(sizeof(struct gzFile_s)); + if (gz == NULL) + return NULL; + gz->write = strchr(mode, 'w') != NULL; + gz->strm.zalloc = myalloc; + gz->strm.zfree = myfree; + gz->strm.opaque = Z_NULL; + if (gz->write) + ret = deflateInit2(&(gz->strm), -1, 8, 15 + 16, 8, 0); + else { + gz->strm.next_in = 0; + gz->strm.avail_in = Z_NULL; + ret = inflateInit2(&(gz->strm), 15 + 16); + } + if (ret != Z_OK) { + free(gz); + return NULL; + } + gz->file = path == NULL ? fdopen(fd, gz->write ? "wb" : "rb") : + fopen(path, gz->write ? "wb" : "rb"); + if (gz->file == NULL) { + gz->write ? deflateEnd(&(gz->strm)) : inflateEnd(&(gz->strm)); + free(gz); + return NULL; + } + gz->err = 0; + gz->msg = ""; + return gz; +} + +int gzwrite OF((gzFile, const void *, unsigned)); + +int gzwrite(gz, buf, len) + gzFile gz; + const void *buf; + unsigned len; +{ + z_stream *strm; + unsigned char out[BUFLEN]; + + if (gz == NULL || !gz->write) + return 0; + strm = &(gz->strm); + strm->next_in = (void *)buf; + strm->avail_in = len; + do { + strm->next_out = out; + strm->avail_out = BUFLEN; + (void)deflate(strm, Z_NO_FLUSH); + fwrite(out, 1, BUFLEN - strm->avail_out, gz->file); + } while (strm->avail_out == 0); + return len; +} + +int gzread OF((gzFile, void *, unsigned)); + +int gzread(gz, buf, len) + gzFile gz; + void *buf; + unsigned len; +{ + int ret; + unsigned got; + unsigned char in[1]; + z_stream *strm; + + if (gz == NULL || gz->write) + return 0; + if (gz->err) + return 0; + strm = &(gz->strm); + strm->next_out = (void *)buf; + strm->avail_out = len; + do { + got = fread(in, 1, 1, gz->file); + if (got == 0) + break; + strm->next_in = in; + strm->avail_in = 1; + ret = inflate(strm, Z_NO_FLUSH); + if (ret == Z_DATA_ERROR) { + gz->err = Z_DATA_ERROR; + gz->msg = strm->msg; + return 0; + } + if (ret == Z_STREAM_END) + inflateReset(strm); + } while (strm->avail_out); + return len - strm->avail_out; +} + +int gzclose OF((gzFile)); + +int gzclose(gz) + gzFile gz; +{ + z_stream *strm; + unsigned char out[BUFLEN]; + + if (gz == NULL) + return Z_STREAM_ERROR; + strm = &(gz->strm); + if (gz->write) { + strm->next_in = Z_NULL; + strm->avail_in = 0; + do { + strm->next_out = out; + strm->avail_out = BUFLEN; + (void)deflate(strm, Z_FINISH); + fwrite(out, 1, BUFLEN - strm->avail_out, gz->file); + } while (strm->avail_out == 0); + deflateEnd(strm); + } + else + inflateEnd(strm); + fclose(gz->file); + free(gz); + return Z_OK; +} + +const char *gzerror OF((gzFile, int *)); + +const char *gzerror(gz, err) + gzFile gz; + int *err; +{ + *err = gz->err; + return gz->msg; +} + +#endif + +static char *prog; + +void error OF((const char *msg)); +void gz_compress OF((FILE *in, gzFile out)); +#ifdef USE_MMAP +int gz_compress_mmap OF((FILE *in, gzFile out)); +#endif +void gz_uncompress OF((gzFile in, FILE *out)); +void file_compress OF((char *file, char *mode)); +void file_uncompress OF((char *file)); +int main OF((int argc, char *argv[])); + +/* =========================================================================== + * Display error message and exit + */ +void error(msg) + const char *msg; +{ + fprintf(stderr, "%s: %s\n", prog, msg); + exit(1); +} + +/* =========================================================================== + * Compress input to output then close both files. + */ + +void gz_compress(in, out) + FILE *in; + gzFile out; +{ + local char buf[BUFLEN]; + int len; + int err; + +#ifdef USE_MMAP + /* Try first compressing with mmap. If mmap fails (minigzip used in a + * pipe), use the normal fread loop. + */ + if (gz_compress_mmap(in, out) == Z_OK) return; +#endif + for (;;) { + len = (int)fread(buf, 1, sizeof(buf), in); + if (ferror(in)) { + perror("fread"); + exit(1); + } + if (len == 0) break; + + if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err)); + } + fclose(in); + if (gzclose(out) != Z_OK) error("failed gzclose"); +} + +#ifdef USE_MMAP /* MMAP version, Miguel Albrecht */ + +/* Try compressing the input file at once using mmap. Return Z_OK if + * if success, Z_ERRNO otherwise. + */ +int gz_compress_mmap(in, out) + FILE *in; + gzFile out; +{ + int len; + int err; + int ifd = fileno(in); + caddr_t buf; /* mmap'ed buffer for the entire input file */ + off_t buf_len; /* length of the input file */ + struct stat sb; + + /* Determine the size of the file, needed for mmap: */ + if (fstat(ifd, &sb) < 0) return Z_ERRNO; + buf_len = sb.st_size; + if (buf_len <= 0) return Z_ERRNO; + + /* Now do the actual mmap: */ + buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0); + if (buf == (caddr_t)(-1)) return Z_ERRNO; + + /* Compress the whole file at once: */ + len = gzwrite(out, (char *)buf, (unsigned)buf_len); + + if (len != (int)buf_len) error(gzerror(out, &err)); + + munmap(buf, buf_len); + fclose(in); + if (gzclose(out) != Z_OK) error("failed gzclose"); + return Z_OK; +} +#endif /* USE_MMAP */ + +/* =========================================================================== + * Uncompress input to output then close both files. + */ +void gz_uncompress(in, out) + gzFile in; + FILE *out; +{ + local char buf[BUFLEN]; + int len; + int err; + + for (;;) { + len = gzread(in, buf, sizeof(buf)); + if (len < 0) error (gzerror(in, &err)); + if (len == 0) break; + + if ((int)fwrite(buf, 1, (unsigned)len, out) != len) { + error("failed fwrite"); + } + } + if (fclose(out)) error("failed fclose"); + + if (gzclose(in) != Z_OK) error("failed gzclose"); +} + + +/* =========================================================================== + * Compress the given file: create a corresponding .gz file and remove the + * original. + */ +void file_compress(file, mode) + char *file; + char *mode; +{ + local char outfile[MAX_NAME_LEN]; + FILE *in; + gzFile out; + + if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) { + fprintf(stderr, "%s: filename too long\n", prog); + exit(1); + } + +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + snprintf(outfile, sizeof(outfile), "%s%s", file, GZ_SUFFIX); +#else + strcpy(outfile, file); + strcat(outfile, GZ_SUFFIX); +#endif + + in = fopen(file, "rb"); + if (in == NULL) { + perror(file); + exit(1); + } + out = gzopen(outfile, mode); + if (out == NULL) { + fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile); + exit(1); + } + gz_compress(in, out); + + unlink(file); +} + + +/* =========================================================================== + * Uncompress the given file and remove the original. + */ +void file_uncompress(file) + char *file; +{ + local char buf[MAX_NAME_LEN]; + char *infile, *outfile; + FILE *out; + gzFile in; + unsigned len = strlen(file); + + if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) { + fprintf(stderr, "%s: filename too long\n", prog); + exit(1); + } + +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + snprintf(buf, sizeof(buf), "%s", file); +#else + strcpy(buf, file); +#endif + + if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) { + infile = file; + outfile = buf; + outfile[len-3] = '\0'; + } else { + outfile = file; + infile = buf; +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + snprintf(buf + len, sizeof(buf) - len, "%s", GZ_SUFFIX); +#else + strcat(infile, GZ_SUFFIX); +#endif + } + in = gzopen(infile, "rb"); + if (in == NULL) { + fprintf(stderr, "%s: can't gzopen %s\n", prog, infile); + exit(1); + } + out = fopen(outfile, "wb"); + if (out == NULL) { + perror(file); + exit(1); + } + + gz_uncompress(in, out); + + unlink(infile); +} + + +/* =========================================================================== + * Usage: minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...] + * -c : write to standard output + * -d : decompress + * -f : compress with Z_FILTERED + * -h : compress with Z_HUFFMAN_ONLY + * -r : compress with Z_RLE + * -1 to -9 : compression level + */ + +int main(argc, argv) + int argc; + char *argv[]; +{ + int copyout = 0; + int uncompr = 0; + gzFile file; + char *bname, outmode[20]; + +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + snprintf(outmode, sizeof(outmode), "%s", "wb6 "); +#else + strcpy(outmode, "wb6 "); +#endif + + prog = argv[0]; + bname = strrchr(argv[0], '/'); + if (bname) + bname++; + else + bname = argv[0]; + argc--, argv++; + + if (!strcmp(bname, "gunzip")) + uncompr = 1; + else if (!strcmp(bname, "zcat")) + copyout = uncompr = 1; + + while (argc > 0) { + if (strcmp(*argv, "-c") == 0) + copyout = 1; + else if (strcmp(*argv, "-d") == 0) + uncompr = 1; + else if (strcmp(*argv, "-f") == 0) + outmode[3] = 'f'; + else if (strcmp(*argv, "-h") == 0) + outmode[3] = 'h'; + else if (strcmp(*argv, "-r") == 0) + outmode[3] = 'R'; + else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' && + (*argv)[2] == 0) + outmode[2] = (*argv)[1]; + else + break; + argc--, argv++; + } + if (outmode[3] == ' ') + outmode[3] = 0; + if (argc == 0) { + SET_BINARY_MODE(stdin); + SET_BINARY_MODE(stdout); + if (uncompr) { + file = gzdopen(fileno(stdin), "rb"); + if (file == NULL) error("can't gzdopen stdin"); + gz_uncompress(file, stdout); + } else { + file = gzdopen(fileno(stdout), outmode); + if (file == NULL) error("can't gzdopen stdout"); + gz_compress(stdin, file); + } + } else { + if (copyout) { + SET_BINARY_MODE(stdout); + } + do { + if (uncompr) { + if (copyout) { + file = gzopen(*argv, "rb"); + if (file == NULL) + fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv); + else + gz_uncompress(file, stdout); + } else { + file_uncompress(*argv); + } + } else { + if (copyout) { + FILE * in = fopen(*argv, "rb"); + + if (in == NULL) { + perror(*argv); + } else { + file = gzdopen(fileno(stdout), outmode); + if (file == NULL) error("can't gzdopen stdout"); + + gz_compress(in, file); + } + + } else { + file_compress(*argv, outmode); + } + } + } while (argv++, --argc); + } + return 0; +} diff --git a/dependencies/zlib-1.2.11/treebuild.xml b/dependencies/zlib-1.2.11/treebuild.xml new file mode 100644 index 0000000..fd75525 --- /dev/null +++ b/dependencies/zlib-1.2.11/treebuild.xml @@ -0,0 +1,116 @@ + + + + zip compression library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dependencies/zlib-1.2.11/trees.c b/dependencies/zlib-1.2.11/trees.c new file mode 100644 index 0000000..50cf4b4 --- /dev/null +++ b/dependencies/zlib-1.2.11/trees.c @@ -0,0 +1,1203 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2017 Jean-loup Gailly + * detect_data_type() function provided freely by Cosmin Truta, 2006 + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id$ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef ZLIB_DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local const static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local const static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local const static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, const ct_data *ltree, + const ct_data *dtree)); +local int detect_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef ZLIB_DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* !ZLIB_DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef ZLIB_DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (ush)value << s->bi_valid; + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= (ush)value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !ZLIB_DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = (int)value;\ + s->bi_buf |= (ush)val << s->bi_valid;\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (ush)(value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* ZLIB_DEBUG */ + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ +#ifdef NO_INIT_GLOBAL_POINTERS + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; +#endif + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef ZLIB_DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, + "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void ZLIB_INTERNAL _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef ZLIB_DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (unsigned)(bits + xbits); + if (stree) s->static_len += (ulg)f * (unsigned)(stree[n].Len + xbits); + } + if (overflow == 0) return; + + Tracev((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if ((unsigned) tree[m].Len != (unsigned) bits) { + Tracev((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((ulg)bits - tree[m].Len) * tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + unsigned code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + code = (code + bl_count[bits-1]) << 1; + next_code[bits] = (ush)code; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*((ulg)max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int last; /* one if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */ + bi_windup(s); /* align on byte boundary */ + put_short(s, (ush)stored_len); + put_short(s, (ush)~stored_len); + zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len); + s->pending += stored_len; +#ifdef ZLIB_DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; + s->bits_sent += 2*16; + s->bits_sent += stored_len<<3; +#endif +} + +/* =========================================================================== + * Flush the bits in the bit buffer to pending output (leaves at most 7 bits) + */ +void ZLIB_INTERNAL _tr_flush_bits(s) + deflate_state *s; +{ + bi_flush(s); +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + */ +void ZLIB_INTERNAL _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef ZLIB_DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and write out the encoded block. + */ +void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int last; /* one if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is binary or text */ + if (s->strm->data_type == Z_UNKNOWN) + s->strm->data_type = detect_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, last); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+last, 3); + compress_block(s, (const ct_data *)static_ltree, + (const ct_data *)static_dtree); +#ifdef ZLIB_DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+last, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (const ct_data *)s->dyn_ltree, + (const ct_data *)s->dyn_dtree); +#ifdef ZLIB_DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (last) { + bi_windup(s); +#ifdef ZLIB_DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*last)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int ZLIB_INTERNAL _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + const ct_data *ltree; /* literal tree */ + const ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= (unsigned)base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); +} + +/* =========================================================================== + * Check if the data type is TEXT or BINARY, using the following algorithm: + * - TEXT if the two conditions below are satisfied: + * a) There are no non-portable control characters belonging to the + * "black list" (0..6, 14..25, 28..31). + * b) There is at least one printable character belonging to the + * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). + * - BINARY otherwise. + * - The following partially-portable control characters form a + * "gray list" that is ignored in this detection algorithm: + * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). + * IN assertion: the fields Freq of dyn_ltree are set. + */ +local int detect_data_type(s) + deflate_state *s; +{ + /* black_mask is the bit mask of black-listed bytes + * set bits 0..6, 14..25, and 28..31 + * 0xf3ffc07f = binary 11110011111111111100000001111111 + */ + unsigned long black_mask = 0xf3ffc07fUL; + int n; + + /* Check for non-textual ("black-listed") bytes. */ + for (n = 0; n <= 31; n++, black_mask >>= 1) + if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0)) + return Z_BINARY; + + /* Check for textual ("white-listed") bytes. */ + if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 + || s->dyn_ltree[13].Freq != 0) + return Z_TEXT; + for (n = 32; n < LITERALS; n++) + if (s->dyn_ltree[n].Freq != 0) + return Z_TEXT; + + /* There are no "black-listed" or "white-listed" bytes: + * this stream either is empty or has tolerated ("gray-listed") bytes only. + */ + return Z_BINARY; +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef ZLIB_DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} diff --git a/dependencies/zlib-1.2.11/trees.h b/dependencies/zlib-1.2.11/trees.h new file mode 100644 index 0000000..d35639d --- /dev/null +++ b/dependencies/zlib-1.2.11/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/dependencies/zlib-1.2.11/uncompr.c b/dependencies/zlib-1.2.11/uncompr.c new file mode 100644 index 0000000..f03a1a8 --- /dev/null +++ b/dependencies/zlib-1.2.11/uncompr.c @@ -0,0 +1,93 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2003, 2010, 2014, 2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. *sourceLen is + the byte length of the source buffer. Upon entry, *destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, + *destLen is the size of the decompressed data and *sourceLen is the number + of source bytes consumed. Upon return, source + *sourceLen points to the + first unused input byte. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, or + Z_DATA_ERROR if the input data was corrupted, including if the input data is + an incomplete zlib stream. +*/ +int ZEXPORT uncompress2 (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong *sourceLen; +{ + z_stream stream; + int err; + const uInt max = (uInt)-1; + uLong len, left; + Byte buf[1]; /* for detection of incomplete stream when *destLen == 0 */ + + len = *sourceLen; + if (*destLen) { + left = *destLen; + *destLen = 0; + } + else { + left = 1; + dest = buf; + } + + stream.next_in = (z_const Bytef *)source; + stream.avail_in = 0; + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + stream.next_out = dest; + stream.avail_out = 0; + + do { + if (stream.avail_out == 0) { + stream.avail_out = left > (uLong)max ? max : (uInt)left; + left -= stream.avail_out; + } + if (stream.avail_in == 0) { + stream.avail_in = len > (uLong)max ? max : (uInt)len; + len -= stream.avail_in; + } + err = inflate(&stream, Z_NO_FLUSH); + } while (err == Z_OK); + + *sourceLen -= len + stream.avail_in; + if (dest != buf) + *destLen = stream.total_out; + else if (stream.total_out && err == Z_BUF_ERROR) + left = 1; + + inflateEnd(&stream); + return err == Z_STREAM_END ? Z_OK : + err == Z_NEED_DICT ? Z_DATA_ERROR : + err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR : + err; +} + +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return uncompress2(dest, destLen, source, &sourceLen); +} diff --git a/dependencies/zlib-1.2.11/watcom/watcom_f.mak b/dependencies/zlib-1.2.11/watcom/watcom_f.mak new file mode 100644 index 0000000..37f4d74 --- /dev/null +++ b/dependencies/zlib-1.2.11/watcom/watcom_f.mak @@ -0,0 +1,43 @@ +# Makefile for zlib +# OpenWatcom flat model +# Last updated: 28-Dec-2005 + +# To use, do "wmake -f watcom_f.mak" + +C_SOURCE = adler32.c compress.c crc32.c deflate.c & + gzclose.c gzlib.c gzread.c gzwrite.c & + infback.c inffast.c inflate.c inftrees.c & + trees.c uncompr.c zutil.c + +OBJS = adler32.obj compress.obj crc32.obj deflate.obj & + gzclose.obj gzlib.obj gzread.obj gzwrite.obj & + infback.obj inffast.obj inflate.obj inftrees.obj & + trees.obj uncompr.obj zutil.obj + +CC = wcc386 +LINKER = wcl386 +CFLAGS = -zq -mf -3r -fp3 -s -bt=dos -oilrtfm -fr=nul -wx +ZLIB_LIB = zlib_f.lib + +.C.OBJ: + $(CC) $(CFLAGS) $[@ + +all: $(ZLIB_LIB) example.exe minigzip.exe + +$(ZLIB_LIB): $(OBJS) + wlib -b -c $(ZLIB_LIB) -+adler32.obj -+compress.obj -+crc32.obj + wlib -b -c $(ZLIB_LIB) -+gzclose.obj -+gzlib.obj -+gzread.obj -+gzwrite.obj + wlib -b -c $(ZLIB_LIB) -+deflate.obj -+infback.obj + wlib -b -c $(ZLIB_LIB) -+inffast.obj -+inflate.obj -+inftrees.obj + wlib -b -c $(ZLIB_LIB) -+trees.obj -+uncompr.obj -+zutil.obj + +example.exe: $(ZLIB_LIB) example.obj + $(LINKER) -ldos32a -fe=example.exe example.obj $(ZLIB_LIB) + +minigzip.exe: $(ZLIB_LIB) minigzip.obj + $(LINKER) -ldos32a -fe=minigzip.exe minigzip.obj $(ZLIB_LIB) + +clean: .SYMBOLIC + del *.obj + del $(ZLIB_LIB) + @echo Cleaning done diff --git a/dependencies/zlib-1.2.11/watcom/watcom_l.mak b/dependencies/zlib-1.2.11/watcom/watcom_l.mak new file mode 100644 index 0000000..193eed7 --- /dev/null +++ b/dependencies/zlib-1.2.11/watcom/watcom_l.mak @@ -0,0 +1,43 @@ +# Makefile for zlib +# OpenWatcom large model +# Last updated: 28-Dec-2005 + +# To use, do "wmake -f watcom_l.mak" + +C_SOURCE = adler32.c compress.c crc32.c deflate.c & + gzclose.c gzlib.c gzread.c gzwrite.c & + infback.c inffast.c inflate.c inftrees.c & + trees.c uncompr.c zutil.c + +OBJS = adler32.obj compress.obj crc32.obj deflate.obj & + gzclose.obj gzlib.obj gzread.obj gzwrite.obj & + infback.obj inffast.obj inflate.obj inftrees.obj & + trees.obj uncompr.obj zutil.obj + +CC = wcc +LINKER = wcl +CFLAGS = -zq -ml -s -bt=dos -oilrtfm -fr=nul -wx +ZLIB_LIB = zlib_l.lib + +.C.OBJ: + $(CC) $(CFLAGS) $[@ + +all: $(ZLIB_LIB) example.exe minigzip.exe + +$(ZLIB_LIB): $(OBJS) + wlib -b -c $(ZLIB_LIB) -+adler32.obj -+compress.obj -+crc32.obj + wlib -b -c $(ZLIB_LIB) -+gzclose.obj -+gzlib.obj -+gzread.obj -+gzwrite.obj + wlib -b -c $(ZLIB_LIB) -+deflate.obj -+infback.obj + wlib -b -c $(ZLIB_LIB) -+inffast.obj -+inflate.obj -+inftrees.obj + wlib -b -c $(ZLIB_LIB) -+trees.obj -+uncompr.obj -+zutil.obj + +example.exe: $(ZLIB_LIB) example.obj + $(LINKER) -fe=example.exe example.obj $(ZLIB_LIB) + +minigzip.exe: $(ZLIB_LIB) minigzip.obj + $(LINKER) -fe=minigzip.exe minigzip.obj $(ZLIB_LIB) + +clean: .SYMBOLIC + del *.obj + del $(ZLIB_LIB) + @echo Cleaning done diff --git a/dependencies/zlib-1.2.11/win32/DLL_FAQ.txt b/dependencies/zlib-1.2.11/win32/DLL_FAQ.txt new file mode 100644 index 0000000..12c0090 --- /dev/null +++ b/dependencies/zlib-1.2.11/win32/DLL_FAQ.txt @@ -0,0 +1,397 @@ + + Frequently Asked Questions about ZLIB1.DLL + + +This document describes the design, the rationale, and the usage +of the official DLL build of zlib, named ZLIB1.DLL. If you have +general questions about zlib, you should see the file "FAQ" found +in the zlib distribution, or at the following location: + http://www.gzip.org/zlib/zlib_faq.html + + + 1. What is ZLIB1.DLL, and how can I get it? + + - ZLIB1.DLL is the official build of zlib as a DLL. + (Please remark the character '1' in the name.) + + Pointers to a precompiled ZLIB1.DLL can be found in the zlib + web site at: + http://www.zlib.net/ + + Applications that link to ZLIB1.DLL can rely on the following + specification: + + * The exported symbols are exclusively defined in the source + files "zlib.h" and "zlib.def", found in an official zlib + source distribution. + * The symbols are exported by name, not by ordinal. + * The exported names are undecorated. + * The calling convention of functions is "C" (CDECL). + * The ZLIB1.DLL binary is linked to MSVCRT.DLL. + + The archive in which ZLIB1.DLL is bundled contains compiled + test programs that must run with a valid build of ZLIB1.DLL. + It is recommended to download the prebuilt DLL from the zlib + web site, instead of building it yourself, to avoid potential + incompatibilities that could be introduced by your compiler + and build settings. If you do build the DLL yourself, please + make sure that it complies with all the above requirements, + and it runs with the precompiled test programs, bundled with + the original ZLIB1.DLL distribution. + + If, for any reason, you need to build an incompatible DLL, + please use a different file name. + + + 2. Why did you change the name of the DLL to ZLIB1.DLL? + What happened to the old ZLIB.DLL? + + - The old ZLIB.DLL, built from zlib-1.1.4 or earlier, required + compilation settings that were incompatible to those used by + a static build. The DLL settings were supposed to be enabled + by defining the macro ZLIB_DLL, before including "zlib.h". + Incorrect handling of this macro was silently accepted at + build time, resulting in two major problems: + + * ZLIB_DLL was missing from the old makefile. When building + the DLL, not all people added it to the build options. In + consequence, incompatible incarnations of ZLIB.DLL started + to circulate around the net. + + * When switching from using the static library to using the + DLL, applications had to define the ZLIB_DLL macro and + to recompile all the sources that contained calls to zlib + functions. Failure to do so resulted in creating binaries + that were unable to run with the official ZLIB.DLL build. + + The only possible solution that we could foresee was to make + a binary-incompatible change in the DLL interface, in order to + remove the dependency on the ZLIB_DLL macro, and to release + the new DLL under a different name. + + We chose the name ZLIB1.DLL, where '1' indicates the major + zlib version number. We hope that we will not have to break + the binary compatibility again, at least not as long as the + zlib-1.x series will last. + + There is still a ZLIB_DLL macro, that can trigger a more + efficient build and use of the DLL, but compatibility no + longer dependents on it. + + + 3. Can I build ZLIB.DLL from the new zlib sources, and replace + an old ZLIB.DLL, that was built from zlib-1.1.4 or earlier? + + - In principle, you can do it by assigning calling convention + keywords to the macros ZEXPORT and ZEXPORTVA. In practice, + it depends on what you mean by "an old ZLIB.DLL", because the + old DLL exists in several mutually-incompatible versions. + You have to find out first what kind of calling convention is + being used in your particular ZLIB.DLL build, and to use the + same one in the new build. If you don't know what this is all + about, you might be better off if you would just leave the old + DLL intact. + + + 4. Can I compile my application using the new zlib interface, and + link it to an old ZLIB.DLL, that was built from zlib-1.1.4 or + earlier? + + - The official answer is "no"; the real answer depends again on + what kind of ZLIB.DLL you have. Even if you are lucky, this + course of action is unreliable. + + If you rebuild your application and you intend to use a newer + version of zlib (post- 1.1.4), it is strongly recommended to + link it to the new ZLIB1.DLL. + + + 5. Why are the zlib symbols exported by name, and not by ordinal? + + - Although exporting symbols by ordinal is a little faster, it + is risky. Any single glitch in the maintenance or use of the + DEF file that contains the ordinals can result in incompatible + builds and frustrating crashes. Simply put, the benefits of + exporting symbols by ordinal do not justify the risks. + + Technically, it should be possible to maintain ordinals in + the DEF file, and still export the symbols by name. Ordinals + exist in every DLL, and even if the dynamic linking performed + at the DLL startup is searching for names, ordinals serve as + hints, for a faster name lookup. However, if the DEF file + contains ordinals, the Microsoft linker automatically builds + an implib that will cause the executables linked to it to use + those ordinals, and not the names. It is interesting to + notice that the GNU linker for Win32 does not suffer from this + problem. + + It is possible to avoid the DEF file if the exported symbols + are accompanied by a "__declspec(dllexport)" attribute in the + source files. You can do this in zlib by predefining the + ZLIB_DLL macro. + + + 6. I see that the ZLIB1.DLL functions use the "C" (CDECL) calling + convention. Why not use the STDCALL convention? + STDCALL is the standard convention in Win32, and I need it in + my Visual Basic project! + + (For readability, we use CDECL to refer to the convention + triggered by the "__cdecl" keyword, STDCALL to refer to + the convention triggered by "__stdcall", and FASTCALL to + refer to the convention triggered by "__fastcall".) + + - Most of the native Windows API functions (without varargs) use + indeed the WINAPI convention (which translates to STDCALL in + Win32), but the standard C functions use CDECL. If a user + application is intrinsically tied to the Windows API (e.g. + it calls native Windows API functions such as CreateFile()), + sometimes it makes sense to decorate its own functions with + WINAPI. But if ANSI C or POSIX portability is a goal (e.g. + it calls standard C functions such as fopen()), it is not a + sound decision to request the inclusion of , or to + use non-ANSI constructs, for the sole purpose to make the user + functions STDCALL-able. + + The functionality offered by zlib is not in the category of + "Windows functionality", but is more like "C functionality". + + Technically, STDCALL is not bad; in fact, it is slightly + faster than CDECL, and it works with variable-argument + functions, just like CDECL. It is unfortunate that, in spite + of using STDCALL in the Windows API, it is not the default + convention used by the C compilers that run under Windows. + The roots of the problem reside deep inside the unsafety of + the K&R-style function prototypes, where the argument types + are not specified; but that is another story for another day. + + The remaining fact is that CDECL is the default convention. + Even if an explicit convention is hard-coded into the function + prototypes inside C headers, problems may appear. The + necessity to expose the convention in users' callbacks is one + of these problems. + + The calling convention issues are also important when using + zlib in other programming languages. Some of them, like Ada + (GNAT) and Fortran (GNU G77), have C bindings implemented + initially on Unix, and relying on the C calling convention. + On the other hand, the pre- .NET versions of Microsoft Visual + Basic require STDCALL, while Borland Delphi prefers, although + it does not require, FASTCALL. + + In fairness to all possible uses of zlib outside the C + programming language, we choose the default "C" convention. + Anyone interested in different bindings or conventions is + encouraged to maintain specialized projects. The "contrib/" + directory from the zlib distribution already holds a couple + of foreign bindings, such as Ada, C++, and Delphi. + + + 7. I need a DLL for my Visual Basic project. What can I do? + + - Define the ZLIB_WINAPI macro before including "zlib.h", when + building both the DLL and the user application (except that + you don't need to define anything when using the DLL in Visual + Basic). The ZLIB_WINAPI macro will switch on the WINAPI + (STDCALL) convention. The name of this DLL must be different + than the official ZLIB1.DLL. + + Gilles Vollant has contributed a build named ZLIBWAPI.DLL, + with the ZLIB_WINAPI macro turned on, and with the minizip + functionality built in. For more information, please read + the notes inside "contrib/vstudio/readme.txt", found in the + zlib distribution. + + + 8. I need to use zlib in my Microsoft .NET project. What can I + do? + + - Henrik Ravn has contributed a .NET wrapper around zlib. Look + into contrib/dotzlib/, inside the zlib distribution. + + + 9. If my application uses ZLIB1.DLL, should I link it to + MSVCRT.DLL? Why? + + - It is not required, but it is recommended to link your + application to MSVCRT.DLL, if it uses ZLIB1.DLL. + + The executables (.EXE, .DLL, etc.) that are involved in the + same process and are using the C run-time library (i.e. they + are calling standard C functions), must link to the same + library. There are several libraries in the Win32 system: + CRTDLL.DLL, MSVCRT.DLL, the static C libraries, etc. + Since ZLIB1.DLL is linked to MSVCRT.DLL, the executables that + depend on it should also be linked to MSVCRT.DLL. + + +10. Why are you saying that ZLIB1.DLL and my application should + be linked to the same C run-time (CRT) library? I linked my + application and my DLLs to different C libraries (e.g. my + application to a static library, and my DLLs to MSVCRT.DLL), + and everything works fine. + + - If a user library invokes only pure Win32 API (accessible via + and the related headers), its DLL build will work + in any context. But if this library invokes standard C API, + things get more complicated. + + There is a single Win32 library in a Win32 system. Every + function in this library resides in a single DLL module, that + is safe to call from anywhere. On the other hand, there are + multiple versions of the C library, and each of them has its + own separate internal state. Standalone executables and user + DLLs that call standard C functions must link to a C run-time + (CRT) library, be it static or shared (DLL). Intermixing + occurs when an executable (not necessarily standalone) and a + DLL are linked to different CRTs, and both are running in the + same process. + + Intermixing multiple CRTs is possible, as long as their + internal states are kept intact. The Microsoft Knowledge Base + articles KB94248 "HOWTO: Use the C Run-Time" and KB140584 + "HOWTO: Link with the Correct C Run-Time (CRT) Library" + mention the potential problems raised by intermixing. + + If intermixing works for you, it's because your application + and DLLs are avoiding the corruption of each of the CRTs' + internal states, maybe by careful design, or maybe by fortune. + + Also note that linking ZLIB1.DLL to non-Microsoft CRTs, such + as those provided by Borland, raises similar problems. + + +11. Why are you linking ZLIB1.DLL to MSVCRT.DLL? + + - MSVCRT.DLL exists on every Windows 95 with a new service pack + installed, or with Microsoft Internet Explorer 4 or later, and + on all other Windows 4.x or later (Windows 98, Windows NT 4, + or later). It is freely distributable; if not present in the + system, it can be downloaded from Microsoft or from other + software provider for free. + + The fact that MSVCRT.DLL does not exist on a virgin Windows 95 + is not so problematic. Windows 95 is scarcely found nowadays, + Microsoft ended its support a long time ago, and many recent + applications from various vendors, including Microsoft, do not + even run on it. Furthermore, no serious user should run + Windows 95 without a proper update installed. + + +12. Why are you not linking ZLIB1.DLL to + <> ? + + - We considered and abandoned the following alternatives: + + * Linking ZLIB1.DLL to a static C library (LIBC.LIB, or + LIBCMT.LIB) is not a good option. People are using the DLL + mainly to save disk space. If you are linking your program + to a static C library, you may as well consider linking zlib + in statically, too. + + * Linking ZLIB1.DLL to CRTDLL.DLL looks appealing, because + CRTDLL.DLL is present on every Win32 installation. + Unfortunately, it has a series of problems: it does not + work properly with Microsoft's C++ libraries, it does not + provide support for 64-bit file offsets, (and so on...), + and Microsoft discontinued its support a long time ago. + + * Linking ZLIB1.DLL to MSVCR70.DLL or MSVCR71.DLL, supplied + with the Microsoft .NET platform, and Visual C++ 7.0/7.1, + raises problems related to the status of ZLIB1.DLL as a + system component. According to the Microsoft Knowledge Base + article KB326922 "INFO: Redistribution of the Shared C + Runtime Component in Visual C++ .NET", MSVCR70.DLL and + MSVCR71.DLL are not supposed to function as system DLLs, + because they may clash with MSVCRT.DLL. Instead, the + application's installer is supposed to put these DLLs + (if needed) in the application's private directory. + If ZLIB1.DLL depends on a non-system runtime, it cannot + function as a redistributable system component. + + * Linking ZLIB1.DLL to non-Microsoft runtimes, such as + Borland's, or Cygwin's, raises problems related to the + reliable presence of these runtimes on Win32 systems. + It's easier to let the DLL build of zlib up to the people + who distribute these runtimes, and who may proceed as + explained in the answer to Question 14. + + +13. If ZLIB1.DLL cannot be linked to MSVCR70.DLL or MSVCR71.DLL, + how can I build/use ZLIB1.DLL in Microsoft Visual C++ 7.0 + (Visual Studio .NET) or newer? + + - Due to the problems explained in the Microsoft Knowledge Base + article KB326922 (see the previous answer), the C runtime that + comes with the VC7 environment is no longer considered a + system component. That is, it should not be assumed that this + runtime exists, or may be installed in a system directory. + Since ZLIB1.DLL is supposed to be a system component, it may + not depend on a non-system component. + + In order to link ZLIB1.DLL and your application to MSVCRT.DLL + in VC7, you need the library of Visual C++ 6.0 or older. If + you don't have this library at hand, it's probably best not to + use ZLIB1.DLL. + + We are hoping that, in the future, Microsoft will provide a + way to build applications linked to a proper system runtime, + from the Visual C++ environment. Until then, you have a + couple of alternatives, such as linking zlib in statically. + If your application requires dynamic linking, you may proceed + as explained in the answer to Question 14. + + +14. I need to link my own DLL build to a CRT different than + MSVCRT.DLL. What can I do? + + - Feel free to rebuild the DLL from the zlib sources, and link + it the way you want. You should, however, clearly state that + your build is unofficial. You should give it a different file + name, and/or install it in a private directory that can be + accessed by your application only, and is not visible to the + others (i.e. it's neither in the PATH, nor in the SYSTEM or + SYSTEM32 directories). Otherwise, your build may clash with + applications that link to the official build. + + For example, in Cygwin, zlib is linked to the Cygwin runtime + CYGWIN1.DLL, and it is distributed under the name CYGZ.DLL. + + +15. May I include additional pieces of code that I find useful, + link them in ZLIB1.DLL, and export them? + + - No. A legitimate build of ZLIB1.DLL must not include code + that does not originate from the official zlib source code. + But you can make your own private DLL build, under a different + file name, as suggested in the previous answer. + + For example, zlib is a part of the VCL library, distributed + with Borland Delphi and C++ Builder. The DLL build of VCL + is a redistributable file, named VCLxx.DLL. + + +16. May I remove some functionality out of ZLIB1.DLL, by enabling + macros like NO_GZCOMPRESS or NO_GZIP at compile time? + + - No. A legitimate build of ZLIB1.DLL must provide the complete + zlib functionality, as implemented in the official zlib source + code. But you can make your own private DLL build, under a + different file name, as suggested in the previous answer. + + +17. I made my own ZLIB1.DLL build. Can I test it for compliance? + + - We prefer that you download the official DLL from the zlib + web site. If you need something peculiar from this DLL, you + can send your suggestion to the zlib mailing list. + + However, in case you do rebuild the DLL yourself, you can run + it with the test programs found in the DLL distribution. + Running these test programs is not a guarantee of compliance, + but a failure can imply a detected problem. + +** + +This document is written and maintained by +Cosmin Truta diff --git a/dependencies/zlib-1.2.11/win32/Makefile.bor b/dependencies/zlib-1.2.11/win32/Makefile.bor new file mode 100644 index 0000000..d152bbb --- /dev/null +++ b/dependencies/zlib-1.2.11/win32/Makefile.bor @@ -0,0 +1,110 @@ +# Makefile for zlib +# Borland C++ for Win32 +# +# Usage: +# make -f win32/Makefile.bor +# make -f win32/Makefile.bor LOCAL_ZLIB=-DASMV OBJA=match.obj OBJPA=+match.obj + +# ------------ Borland C++ ------------ + +# Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7) +# should be added to the environment via "set LOCAL_ZLIB=-DFOO" or +# added to the declaration of LOC here: +LOC = $(LOCAL_ZLIB) + +CC = bcc32 +AS = bcc32 +LD = bcc32 +AR = tlib +CFLAGS = -a -d -k- -O2 $(LOC) +ASFLAGS = $(LOC) +LDFLAGS = $(LOC) + + +# variables +ZLIB_LIB = zlib.lib + +OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj +OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj +#OBJA = +OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj +OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj +#OBJPA= + + +# targets +all: $(ZLIB_LIB) example.exe minigzip.exe + +.c.obj: + $(CC) -c $(CFLAGS) $< + +.asm.obj: + $(AS) -c $(ASFLAGS) $< + +adler32.obj: adler32.c zlib.h zconf.h + +compress.obj: compress.c zlib.h zconf.h + +crc32.obj: crc32.c zlib.h zconf.h crc32.h + +deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h + +gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h + +gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h + +gzread.obj: gzread.c zlib.h zconf.h gzguts.h + +gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h + +infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h inffixed.h + +inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h + +inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h inffixed.h + +inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h + +trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h + +uncompr.obj: uncompr.c zlib.h zconf.h + +zutil.obj: zutil.c zutil.h zlib.h zconf.h + +example.obj: test/example.c zlib.h zconf.h + +minigzip.obj: test/minigzip.c zlib.h zconf.h + + +# For the sake of the old Borland make, +# the command line is cut to fit in the MS-DOS 128 byte limit: +$(ZLIB_LIB): $(OBJ1) $(OBJ2) $(OBJA) + -del $(ZLIB_LIB) + $(AR) $(ZLIB_LIB) $(OBJP1) + $(AR) $(ZLIB_LIB) $(OBJP2) + $(AR) $(ZLIB_LIB) $(OBJPA) + + +# testing +test: example.exe minigzip.exe + example + echo hello world | minigzip | minigzip -d + +example.exe: example.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) + +minigzip.exe: minigzip.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) + + +# cleanup +clean: + -del $(ZLIB_LIB) + -del *.obj + -del *.exe + -del *.tds + -del zlib.bak + -del foo.gz diff --git a/dependencies/zlib-1.2.11/win32/Makefile.gcc b/dependencies/zlib-1.2.11/win32/Makefile.gcc new file mode 100644 index 0000000..305be50 --- /dev/null +++ b/dependencies/zlib-1.2.11/win32/Makefile.gcc @@ -0,0 +1,182 @@ +# Makefile for zlib, derived from Makefile.dj2. +# Modified for mingw32 by C. Spieler, 6/16/98. +# Updated for zlib 1.2.x by Christian Spieler and Cosmin Truta, Mar-2003. +# Last updated: Mar 2012. +# Tested under Cygwin and MinGW. + +# Copyright (C) 1995-2003 Jean-loup Gailly. +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile, or to compile and test, type from the top level zlib directory: +# +# make -fwin32/Makefile.gcc; make test testdll -fwin32/Makefile.gcc +# +# To use the asm code, type: +# cp contrib/asm?86/match.S ./match.S +# make LOC=-DASMV OBJA=match.o -fwin32/Makefile.gcc +# +# To install libz.a, zconf.h and zlib.h in the system directories, type: +# +# make install -fwin32/Makefile.gcc +# +# BINARY_PATH, INCLUDE_PATH and LIBRARY_PATH must be set. +# +# To install the shared lib, append SHARED_MODE=1 to the make command : +# +# make install -fwin32/Makefile.gcc SHARED_MODE=1 + +# Note: +# If the platform is *not* MinGW (e.g. it is Cygwin or UWIN), +# the DLL name should be changed from "zlib1.dll". + +STATICLIB = libz.a +SHAREDLIB = zlib1.dll +IMPLIB = libz.dll.a + +# +# Set to 1 if shared object needs to be installed +# +SHARED_MODE=0 + +#LOC = -DASMV +#LOC = -DZLIB_DEBUG -g + +PREFIX = +CC = $(PREFIX)gcc +CFLAGS = $(LOC) -O3 -Wall + +AS = $(CC) +ASFLAGS = $(LOC) -Wall + +LD = $(CC) +LDFLAGS = $(LOC) + +AR = $(PREFIX)ar +ARFLAGS = rcs + +RC = $(PREFIX)windres +RCFLAGS = --define GCC_WINDRES + +STRIP = $(PREFIX)strip + +CP = cp -fp +# If GNU install is available, replace $(CP) with install. +INSTALL = $(CP) +RM = rm -f + +prefix ?= /usr/local +exec_prefix = $(prefix) + +OBJS = adler32.o compress.o crc32.o deflate.o gzclose.o gzlib.o gzread.o \ + gzwrite.o infback.o inffast.o inflate.o inftrees.o trees.o uncompr.o zutil.o +OBJA = + +all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) example.exe minigzip.exe example_d.exe minigzip_d.exe + +test: example.exe minigzip.exe + ./example + echo hello world | ./minigzip | ./minigzip -d + +testdll: example_d.exe minigzip_d.exe + ./example_d + echo hello world | ./minigzip_d | ./minigzip_d -d + +.c.o: + $(CC) $(CFLAGS) -c -o $@ $< + +.S.o: + $(AS) $(ASFLAGS) -c -o $@ $< + +$(STATICLIB): $(OBJS) $(OBJA) + $(AR) $(ARFLAGS) $@ $(OBJS) $(OBJA) + +$(IMPLIB): $(SHAREDLIB) + +$(SHAREDLIB): win32/zlib.def $(OBJS) $(OBJA) zlibrc.o + $(CC) -shared -Wl,--out-implib,$(IMPLIB) $(LDFLAGS) \ + -o $@ win32/zlib.def $(OBJS) $(OBJA) zlibrc.o + $(STRIP) $@ + +example.exe: example.o $(STATICLIB) + $(LD) $(LDFLAGS) -o $@ example.o $(STATICLIB) + $(STRIP) $@ + +minigzip.exe: minigzip.o $(STATICLIB) + $(LD) $(LDFLAGS) -o $@ minigzip.o $(STATICLIB) + $(STRIP) $@ + +example_d.exe: example.o $(IMPLIB) + $(LD) $(LDFLAGS) -o $@ example.o $(IMPLIB) + $(STRIP) $@ + +minigzip_d.exe: minigzip.o $(IMPLIB) + $(LD) $(LDFLAGS) -o $@ minigzip.o $(IMPLIB) + $(STRIP) $@ + +example.o: test/example.c zlib.h zconf.h + $(CC) $(CFLAGS) -I. -c -o $@ test/example.c + +minigzip.o: test/minigzip.c zlib.h zconf.h + $(CC) $(CFLAGS) -I. -c -o $@ test/minigzip.c + +zlibrc.o: win32/zlib1.rc + $(RC) $(RCFLAGS) -o $@ win32/zlib1.rc + +.PHONY: install uninstall clean + +install: zlib.h zconf.h $(STATICLIB) $(IMPLIB) + @if test -z "$(DESTDIR)$(INCLUDE_PATH)" -o -z "$(DESTDIR)$(LIBRARY_PATH)" -o -z "$(DESTDIR)$(BINARY_PATH)"; then \ + echo INCLUDE_PATH, LIBRARY_PATH, and BINARY_PATH must be specified; \ + exit 1; \ + fi + -@mkdir -p '$(DESTDIR)$(INCLUDE_PATH)' + -@mkdir -p '$(DESTDIR)$(LIBRARY_PATH)' '$(DESTDIR)$(LIBRARY_PATH)'/pkgconfig + -if [ "$(SHARED_MODE)" = "1" ]; then \ + mkdir -p '$(DESTDIR)$(BINARY_PATH)'; \ + $(INSTALL) $(SHAREDLIB) '$(DESTDIR)$(BINARY_PATH)'; \ + $(INSTALL) $(IMPLIB) '$(DESTDIR)$(LIBRARY_PATH)'; \ + fi + -$(INSTALL) zlib.h '$(DESTDIR)$(INCLUDE_PATH)' + -$(INSTALL) zconf.h '$(DESTDIR)$(INCLUDE_PATH)' + -$(INSTALL) $(STATICLIB) '$(DESTDIR)$(LIBRARY_PATH)' + sed \ + -e 's|@prefix@|${prefix}|g' \ + -e 's|@exec_prefix@|${exec_prefix}|g' \ + -e 's|@libdir@|$(LIBRARY_PATH)|g' \ + -e 's|@sharedlibdir@|$(LIBRARY_PATH)|g' \ + -e 's|@includedir@|$(INCLUDE_PATH)|g' \ + -e 's|@VERSION@|'`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' zlib.h`'|g' \ + zlib.pc.in > '$(DESTDIR)$(LIBRARY_PATH)'/pkgconfig/zlib.pc + +uninstall: + -if [ "$(SHARED_MODE)" = "1" ]; then \ + $(RM) '$(DESTDIR)$(BINARY_PATH)'/$(SHAREDLIB); \ + $(RM) '$(DESTDIR)$(LIBRARY_PATH)'/$(IMPLIB); \ + fi + -$(RM) '$(DESTDIR)$(INCLUDE_PATH)'/zlib.h + -$(RM) '$(DESTDIR)$(INCLUDE_PATH)'/zconf.h + -$(RM) '$(DESTDIR)$(LIBRARY_PATH)'/$(STATICLIB) + +clean: + -$(RM) $(STATICLIB) + -$(RM) $(SHAREDLIB) + -$(RM) $(IMPLIB) + -$(RM) *.o + -$(RM) *.exe + -$(RM) foo.gz + +adler32.o: zlib.h zconf.h +compress.o: zlib.h zconf.h +crc32.o: crc32.h zlib.h zconf.h +deflate.o: deflate.h zutil.h zlib.h zconf.h +gzclose.o: zlib.h zconf.h gzguts.h +gzlib.o: zlib.h zconf.h gzguts.h +gzread.o: zlib.h zconf.h gzguts.h +gzwrite.o: zlib.h zconf.h gzguts.h +inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h +inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h +infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h +inftrees.o: zutil.h zlib.h zconf.h inftrees.h +trees.o: deflate.h zutil.h zlib.h zconf.h trees.h +uncompr.o: zlib.h zconf.h +zutil.o: zutil.h zlib.h zconf.h diff --git a/dependencies/zlib-1.2.11/win32/Makefile.msc b/dependencies/zlib-1.2.11/win32/Makefile.msc new file mode 100644 index 0000000..6831882 --- /dev/null +++ b/dependencies/zlib-1.2.11/win32/Makefile.msc @@ -0,0 +1,163 @@ +# Makefile for zlib using Microsoft (Visual) C +# zlib is copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler +# +# Usage: +# nmake -f win32/Makefile.msc (standard build) +# nmake -f win32/Makefile.msc LOC=-DFOO (nonstandard build) +# nmake -f win32/Makefile.msc LOC="-DASMV -DASMINF" \ +# OBJA="inffas32.obj match686.obj" (use ASM code, x86) +# nmake -f win32/Makefile.msc AS=ml64 LOC="-DASMV -DASMINF -I." \ +# OBJA="inffasx64.obj gvmat64.obj inffas8664.obj" (use ASM code, x64) + +# The toplevel directory of the source tree. +# +TOP = . + +# optional build flags +LOC = + +# variables +STATICLIB = zlib.lib +SHAREDLIB = zlib1.dll +IMPLIB = zdll.lib + +CC = cl +AS = ml +LD = link +AR = lib +RC = rc +CFLAGS = -nologo -MD -W3 -O2 -Oy- -Zi -Fd"zlib" $(LOC) +WFLAGS = -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE +ASFLAGS = -coff -Zi $(LOC) +LDFLAGS = -nologo -debug -incremental:no -opt:ref +ARFLAGS = -nologo +RCFLAGS = /dWIN32 /r + +OBJS = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj \ + gzwrite.obj infback.obj inflate.obj inftrees.obj inffast.obj trees.obj uncompr.obj zutil.obj +OBJA = + + +# targets +all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) \ + example.exe minigzip.exe example_d.exe minigzip_d.exe + +$(STATICLIB): $(OBJS) $(OBJA) + $(AR) $(ARFLAGS) -out:$@ $(OBJS) $(OBJA) + +$(IMPLIB): $(SHAREDLIB) + +$(SHAREDLIB): $(TOP)/win32/zlib.def $(OBJS) $(OBJA) zlib1.res + $(LD) $(LDFLAGS) -def:$(TOP)/win32/zlib.def -dll -implib:$(IMPLIB) \ + -out:$@ -base:0x5A4C0000 $(OBJS) $(OBJA) zlib1.res + if exist $@.manifest \ + mt -nologo -manifest $@.manifest -outputresource:$@;2 + +example.exe: example.obj $(STATICLIB) + $(LD) $(LDFLAGS) example.obj $(STATICLIB) + if exist $@.manifest \ + mt -nologo -manifest $@.manifest -outputresource:$@;1 + +minigzip.exe: minigzip.obj $(STATICLIB) + $(LD) $(LDFLAGS) minigzip.obj $(STATICLIB) + if exist $@.manifest \ + mt -nologo -manifest $@.manifest -outputresource:$@;1 + +example_d.exe: example.obj $(IMPLIB) + $(LD) $(LDFLAGS) -out:$@ example.obj $(IMPLIB) + if exist $@.manifest \ + mt -nologo -manifest $@.manifest -outputresource:$@;1 + +minigzip_d.exe: minigzip.obj $(IMPLIB) + $(LD) $(LDFLAGS) -out:$@ minigzip.obj $(IMPLIB) + if exist $@.manifest \ + mt -nologo -manifest $@.manifest -outputresource:$@;1 + +{$(TOP)}.c.obj: + $(CC) -c $(WFLAGS) $(CFLAGS) $< + +{$(TOP)/test}.c.obj: + $(CC) -c -I$(TOP) $(WFLAGS) $(CFLAGS) $< + +{$(TOP)/contrib/masmx64}.c.obj: + $(CC) -c $(WFLAGS) $(CFLAGS) $< + +{$(TOP)/contrib/masmx64}.asm.obj: + $(AS) -c $(ASFLAGS) $< + +{$(TOP)/contrib/masmx86}.asm.obj: + $(AS) -c $(ASFLAGS) $< + +adler32.obj: $(TOP)/adler32.c $(TOP)/zlib.h $(TOP)/zconf.h + +compress.obj: $(TOP)/compress.c $(TOP)/zlib.h $(TOP)/zconf.h + +crc32.obj: $(TOP)/crc32.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/crc32.h + +deflate.obj: $(TOP)/deflate.c $(TOP)/deflate.h $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h + +gzclose.obj: $(TOP)/gzclose.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h + +gzlib.obj: $(TOP)/gzlib.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h + +gzread.obj: $(TOP)/gzread.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h + +gzwrite.obj: $(TOP)/gzwrite.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h + +infback.obj: $(TOP)/infback.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h $(TOP)/inflate.h \ + $(TOP)/inffast.h $(TOP)/inffixed.h + +inffast.obj: $(TOP)/inffast.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h $(TOP)/inflate.h \ + $(TOP)/inffast.h + +inflate.obj: $(TOP)/inflate.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h $(TOP)/inflate.h \ + $(TOP)/inffast.h $(TOP)/inffixed.h + +inftrees.obj: $(TOP)/inftrees.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h + +trees.obj: $(TOP)/trees.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/deflate.h $(TOP)/trees.h + +uncompr.obj: $(TOP)/uncompr.c $(TOP)/zlib.h $(TOP)/zconf.h + +zutil.obj: $(TOP)/zutil.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h + +gvmat64.obj: $(TOP)/contrib\masmx64\gvmat64.asm + +inffasx64.obj: $(TOP)/contrib\masmx64\inffasx64.asm + +inffas8664.obj: $(TOP)/contrib\masmx64\inffas8664.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h \ + $(TOP)/inftrees.h $(TOP)/inflate.h $(TOP)/inffast.h + +inffas32.obj: $(TOP)/contrib\masmx86\inffas32.asm + +match686.obj: $(TOP)/contrib\masmx86\match686.asm + +example.obj: $(TOP)/test/example.c $(TOP)/zlib.h $(TOP)/zconf.h + +minigzip.obj: $(TOP)/test/minigzip.c $(TOP)/zlib.h $(TOP)/zconf.h + +zlib1.res: $(TOP)/win32/zlib1.rc + $(RC) $(RCFLAGS) /fo$@ $(TOP)/win32/zlib1.rc + +# testing +test: example.exe minigzip.exe + example + echo hello world | minigzip | minigzip -d + +testdll: example_d.exe minigzip_d.exe + example_d + echo hello world | minigzip_d | minigzip_d -d + + +# cleanup +clean: + -del $(STATICLIB) + -del $(SHAREDLIB) + -del $(IMPLIB) + -del *.obj + -del *.res + -del *.exp + -del *.exe + -del *.pdb + -del *.manifest + -del foo.gz diff --git a/dependencies/zlib-1.2.11/win32/README-WIN32.txt b/dependencies/zlib-1.2.11/win32/README-WIN32.txt new file mode 100644 index 0000000..df7ab7f --- /dev/null +++ b/dependencies/zlib-1.2.11/win32/README-WIN32.txt @@ -0,0 +1,103 @@ +ZLIB DATA COMPRESSION LIBRARY + +zlib 1.2.11 is a general purpose data compression library. All the code is +thread safe. The data format used by the zlib library is described by RFCs +(Request for Comments) 1950 to 1952 in the files +http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) +and rfc1952.txt (gzip format). + +All functions of the compression library are documented in the file zlib.h +(volunteer to write man pages welcome, contact zlib@gzip.org). Two compiled +examples are distributed in this package, example and minigzip. The example_d +and minigzip_d flavors validate that the zlib1.dll file is working correctly. + +Questions about zlib should be sent to . The zlib home page +is http://zlib.net/ . Before reporting a problem, please check this site to +verify that you have the latest version of zlib; otherwise get the latest +version and check whether the problem still exists or not. + +PLEASE read DLL_FAQ.txt, and the the zlib FAQ http://zlib.net/zlib_faq.html +before asking for help. + + +Manifest: + +The package zlib-1.2.11-win32-x86.zip will contain the following files: + + README-WIN32.txt This document + ChangeLog Changes since previous zlib packages + DLL_FAQ.txt Frequently asked questions about zlib1.dll + zlib.3.pdf Documentation of this library in Adobe Acrobat format + + example.exe A statically-bound example (using zlib.lib, not the dll) + example.pdb Symbolic information for debugging example.exe + + example_d.exe A zlib1.dll bound example (using zdll.lib) + example_d.pdb Symbolic information for debugging example_d.exe + + minigzip.exe A statically-bound test program (using zlib.lib, not the dll) + minigzip.pdb Symbolic information for debugging minigzip.exe + + minigzip_d.exe A zlib1.dll bound test program (using zdll.lib) + minigzip_d.pdb Symbolic information for debugging minigzip_d.exe + + zlib.h Install these files into the compilers' INCLUDE path to + zconf.h compile programs which use zlib.lib or zdll.lib + + zdll.lib Install these files into the compilers' LIB path if linking + zdll.exp a compiled program to the zlib1.dll binary + + zlib.lib Install these files into the compilers' LIB path to link zlib + zlib.pdb into compiled programs, without zlib1.dll runtime dependency + (zlib.pdb provides debugging info to the compile time linker) + + zlib1.dll Install this binary shared library into the system PATH, or + the program's runtime directory (where the .exe resides) + zlib1.pdb Install in the same directory as zlib1.dll, in order to debug + an application crash using WinDbg or similar tools. + +All .pdb files above are entirely optional, but are very useful to a developer +attempting to diagnose program misbehavior or a crash. Many additional +important files for developers can be found in the zlib127.zip source package +available from http://zlib.net/ - review that package's README file for details. + + +Acknowledgments: + +The deflate format used by zlib was defined by Phil Katz. The deflate and +zlib specifications were written by L. Peter Deutsch. Thanks to all the +people who reported problems and suggested various improvements in zlib; they +are too numerous to cite here. + + +Copyright notice: + + (C) 1995-2017 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* receiving +lengthy legal documents to sign. The sources are provided for free but without +warranty of any kind. The library has been entirely written by Jean-loup +Gailly and Mark Adler; it does not include third-party code. + +If you redistribute modified sources, we would appreciate that you include in +the file ChangeLog history information documenting your changes. Please read +the FAQ for more information on the distribution of modified source versions. diff --git a/dependencies/zlib-1.2.11/win32/VisualC.txt b/dependencies/zlib-1.2.11/win32/VisualC.txt new file mode 100644 index 0000000..1005b21 --- /dev/null +++ b/dependencies/zlib-1.2.11/win32/VisualC.txt @@ -0,0 +1,3 @@ + +To build zlib using the Microsoft Visual C++ environment, +use the appropriate project from the contrib/vstudio/ directory. diff --git a/dependencies/zlib-1.2.11/win32/zlib.def b/dependencies/zlib-1.2.11/win32/zlib.def new file mode 100644 index 0000000..784b138 --- /dev/null +++ b/dependencies/zlib-1.2.11/win32/zlib.def @@ -0,0 +1,94 @@ +; zlib data compression library +EXPORTS +; basic functions + zlibVersion + deflate + deflateEnd + inflate + inflateEnd +; advanced functions + deflateSetDictionary + deflateGetDictionary + deflateCopy + deflateReset + deflateParams + deflateTune + deflateBound + deflatePending + deflatePrime + deflateSetHeader + inflateSetDictionary + inflateGetDictionary + inflateSync + inflateCopy + inflateReset + inflateReset2 + inflatePrime + inflateMark + inflateGetHeader + inflateBack + inflateBackEnd + zlibCompileFlags +; utility functions + compress + compress2 + compressBound + uncompress + uncompress2 + gzopen + gzdopen + gzbuffer + gzsetparams + gzread + gzfread + gzwrite + gzfwrite + gzprintf + gzvprintf + gzputs + gzgets + gzputc + gzgetc + gzungetc + gzflush + gzseek + gzrewind + gztell + gzoffset + gzeof + gzdirect + gzclose + gzclose_r + gzclose_w + gzerror + gzclearerr +; large file functions + gzopen64 + gzseek64 + gztell64 + gzoffset64 + adler32_combine64 + crc32_combine64 +; checksum functions + adler32 + adler32_z + crc32 + crc32_z + adler32_combine + crc32_combine +; various hacks, don't look :) + deflateInit_ + deflateInit2_ + inflateInit_ + inflateInit2_ + inflateBackInit_ + gzgetc_ + zError + inflateSyncPoint + get_crc_table + inflateUndermine + inflateValidate + inflateCodesUsed + inflateResetKeep + deflateResetKeep + gzopen_w diff --git a/dependencies/zlib-1.2.11/win32/zlib1.rc b/dependencies/zlib-1.2.11/win32/zlib1.rc new file mode 100644 index 0000000..234e641 --- /dev/null +++ b/dependencies/zlib-1.2.11/win32/zlib1.rc @@ -0,0 +1,40 @@ +#include +#include "../zlib.h" + +#ifdef GCC_WINDRES +VS_VERSION_INFO VERSIONINFO +#else +VS_VERSION_INFO VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE +#endif + FILEVERSION ZLIB_VER_MAJOR,ZLIB_VER_MINOR,ZLIB_VER_REVISION,0 + PRODUCTVERSION ZLIB_VER_MAJOR,ZLIB_VER_MINOR,ZLIB_VER_REVISION,0 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS 1 +#else + FILEFLAGS 0 +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0 // not used +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + //language ID = U.S. English, char set = Windows, Multilingual + BEGIN + VALUE "FileDescription", "zlib data compression library\0" + VALUE "FileVersion", ZLIB_VERSION "\0" + VALUE "InternalName", "zlib1.dll\0" + VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" + VALUE "OriginalFilename", "zlib1.dll\0" + VALUE "ProductName", "zlib\0" + VALUE "ProductVersion", ZLIB_VERSION "\0" + VALUE "Comments", "For more information visit http://www.zlib.net/\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1252 + END +END diff --git a/dependencies/zlib-1.2.11/zconf.h.cmakein b/dependencies/zlib-1.2.11/zconf.h.cmakein new file mode 100644 index 0000000..a7f24cc --- /dev/null +++ b/dependencies/zlib-1.2.11/zconf.h.cmakein @@ -0,0 +1,536 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H +#cmakedefine Z_PREFIX +#cmakedefine Z_HAVE_UNISTD_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols and init macros */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define crc32_z z_crc32_z +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary +# define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateValidate z_inflateValidate +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# define uncompress2 z_uncompress2 +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +#ifdef Z_SOLO + typedef unsigned long z_size_t; +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/dependencies/zlib-1.2.11/zconf.h.in b/dependencies/zlib-1.2.11/zconf.h.in new file mode 100644 index 0000000..5e1d68a --- /dev/null +++ b/dependencies/zlib-1.2.11/zconf.h.in @@ -0,0 +1,534 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols and init macros */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define crc32_z z_crc32_z +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary +# define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateValidate z_inflateValidate +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# define uncompress2 z_uncompress2 +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +#ifdef Z_SOLO + typedef unsigned long z_size_t; +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/dependencies/zlib-1.2.11/zconf.h.included b/dependencies/zlib-1.2.11/zconf.h.included new file mode 100644 index 0000000..5e1d68a --- /dev/null +++ b/dependencies/zlib-1.2.11/zconf.h.included @@ -0,0 +1,534 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols and init macros */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define crc32_z z_crc32_z +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary +# define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateValidate z_inflateValidate +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# define uncompress2 z_uncompress2 +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +#ifdef Z_SOLO + typedef unsigned long z_size_t; +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/dependencies/zlib-1.2.11/zlib.3 b/dependencies/zlib-1.2.11/zlib.3 new file mode 100644 index 0000000..bda4eb0 --- /dev/null +++ b/dependencies/zlib-1.2.11/zlib.3 @@ -0,0 +1,149 @@ +.TH ZLIB 3 "15 Jan 2017" +.SH NAME +zlib \- compression/decompression library +.SH SYNOPSIS +[see +.I zlib.h +for full description] +.SH DESCRIPTION +The +.I zlib +library is a general purpose data compression library. +The code is thread safe, assuming that the standard library functions +used are thread safe, such as memory allocation routines. +It provides in-memory compression and decompression functions, +including integrity checks of the uncompressed data. +This version of the library supports only one compression method (deflation) +but other algorithms may be added later +with the same stream interface. +.LP +Compression can be done in a single step if the buffers are large enough +or can be done by repeated calls of the compression function. +In the latter case, +the application must provide more input and/or consume the output +(providing more output space) before each call. +.LP +The library also supports reading and writing files in +.IR gzip (1) +(.gz) format +with an interface similar to that of stdio. +.LP +The library does not install any signal handler. +The decoder checks the consistency of the compressed data, +so the library should never crash even in the case of corrupted input. +.LP +All functions of the compression library are documented in the file +.IR zlib.h . +The distribution source includes examples of use of the library +in the files +.I test/example.c +and +.IR test/minigzip.c, +as well as other examples in the +.IR examples/ +directory. +.LP +Changes to this version are documented in the file +.I ChangeLog +that accompanies the source. +.LP +.I zlib +is built in to many languages and operating systems, including but not limited to +Java, Python, .NET, PHP, Perl, Ruby, Swift, and Go. +.LP +An experimental package to read and write files in the .zip format, +written on top of +.I zlib +by Gilles Vollant (info@winimage.com), +is available at: +.IP +http://www.winimage.com/zLibDll/minizip.html +and also in the +.I contrib/minizip +directory of the main +.I zlib +source distribution. +.SH "SEE ALSO" +The +.I zlib +web site can be found at: +.IP +http://zlib.net/ +.LP +The data format used by the +.I zlib +library is described by RFC +(Request for Comments) 1950 to 1952 in the files: +.IP +http://tools.ietf.org/html/rfc1950 (for the zlib header and trailer format) +.br +http://tools.ietf.org/html/rfc1951 (for the deflate compressed data format) +.br +http://tools.ietf.org/html/rfc1952 (for the gzip header and trailer format) +.LP +Mark Nelson wrote an article about +.I zlib +for the Jan. 1997 issue of Dr. Dobb's Journal; +a copy of the article is available at: +.IP +http://marknelson.us/1997/01/01/zlib-engine/ +.SH "REPORTING PROBLEMS" +Before reporting a problem, +please check the +.I zlib +web site to verify that you have the latest version of +.IR zlib ; +otherwise, +obtain the latest version and see if the problem still exists. +Please read the +.I zlib +FAQ at: +.IP +http://zlib.net/zlib_faq.html +.LP +before asking for help. +Send questions and/or comments to zlib@gzip.org, +or (for the Windows DLL version) to Gilles Vollant (info@winimage.com). +.SH AUTHORS AND LICENSE +Version 1.2.11 +.LP +Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler +.LP +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. +.LP +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: +.LP +.nr step 1 1 +.IP \n[step]. 3 +The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software +in a product, an acknowledgment in the product documentation would be +appreciated but is not required. +.IP \n+[step]. +Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. +.IP \n+[step]. +This notice may not be removed or altered from any source distribution. +.LP +Jean-loup Gailly Mark Adler +.br +jloup@gzip.org madler@alumni.caltech.edu +.LP +The deflate format used by +.I zlib +was defined by Phil Katz. +The deflate and +.I zlib +specifications were written by L. Peter Deutsch. +Thanks to all the people who reported problems and suggested various +improvements in +.IR zlib ; +who are too numerous to cite here. +.LP +UNIX manual page by R. P. C. Rodgers, +U.S. National Library of Medicine (rodgers@nlm.nih.gov). +.\" end of man page diff --git a/dependencies/zlib-1.2.11/zlib.3.pdf b/dependencies/zlib-1.2.11/zlib.3.pdf new file mode 100644 index 0000000..6fa519c Binary files /dev/null and b/dependencies/zlib-1.2.11/zlib.3.pdf differ diff --git a/dependencies/zlib-1.2.11/zlib.h b/dependencies/zlib-1.2.11/zlib.h new file mode 100644 index 0000000..f09cdaf --- /dev/null +++ b/dependencies/zlib-1.2.11/zlib.h @@ -0,0 +1,1912 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.11, January 15th, 2017 + + Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.11" +#define ZLIB_VERNUM 0x12b0 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 11 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip and raw deflate streams in + memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in the case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + z_const Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total number of input bytes read so far */ + + Bytef *next_out; /* next output byte will go here */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total number of bytes output so far */ + + z_const char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text + for deflate, or the decoding state for inflate */ + uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. In that case, zlib is thread-safe. When zalloc and zfree are + Z_NULL on entry to the initialization function, they are set to internal + routines that use the standard library functions malloc() and free(). + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use by the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field for deflate() */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary. Some output may be provided even if + flush is zero. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. See deflatePending(), + which can be used if desired to determine whether or not there is more ouput + in that case. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed + codes block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this + function must be called again with Z_FINISH and more output space (updated + avail_out) but no more input data, until it returns with Z_STREAM_END or an + error. After deflate has returned Z_STREAM_END, the only possible operations + on the stream are deflateReset or deflateEnd. + + Z_FINISH can be used in the first deflate call after deflateInit if all the + compression is to be done in a single step. In order to complete in one + call, avail_out must be at least the value returned by deflateBound (see + below). Then deflate is guaranteed to return Z_STREAM_END. If not enough + output space is provided, deflate will not return Z_STREAM_END, and it must + be called again as described above. + + deflate() sets strm->adler to the Adler-32 checksum of all input read + so far (that is, total_in bytes). If a gzip stream is being generated, then + strm->adler will be the CRC-32 checksum of the input read so far. (See + deflateInit2 below.) + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is + considered binary. This field is only for information purposes and does not + affect the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL or the state was inadvertently written over + by the application), or Z_BUF_ERROR if no progress is possible (for example + avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and + deflate() can be called again with more input and more output space to + continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. In the current version of inflate, the provided input is not + read or consumed. The allocation of a sliding window will be deferred to + the first call of inflate (if the decompression does not complete on the + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression. + Actual decompression will be done by inflate(). So next_in, and avail_in, + next_out, and avail_out are unused and unchanged. The current + implementation of inflateInit() does not process any header information -- + that is deferred until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), then next_in and avail_in are updated + accordingly, and processing will resume at this point for the next call of + inflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. If the + caller of inflate() does not provide both available input and available + output space, it is possible that there will be no progress made. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + To assist in this, on return inflate() always sets strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the Adler-32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed Adler-32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained unless inflateGetHeader() is used. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + produced so far. The CRC-32 is checked against the gzip trailer, as is the + uncompressed length, modulo 2^32. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value, in which case strm->msg points to a string with a more specific + error), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL, or the state was inadvertently written over + by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR + if no progress was possible or if there was not enough room in the output + buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is to be attempted. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state + was inconsistent. +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by the + caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + For the current implementation of deflate(), a windowBits value of 8 (a + window size of 256 bytes) is not supported. As a result, a request for 8 + will result in 9 (a 512-byte window). In that case, providing 8 to + inflateInit2() will result in an error when the zlib header with 9 is + checked against the initialization of inflate(). The remedy is to not use 8 + with deflateInit2() with this initialization, or at least in that case use 9 + with inflateInit2(). + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute a check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to the appropriate value, + if the operating system was determined at compile time. If a gzip stream is + being written, strm->adler is a CRC-32 instead of an Adler-32. + + For raw deflate or gzip encoding, a request for a 256-byte window is + rejected as invalid, since only the zlib header provides a means of + transmitting the window size to the decompressor. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the Adler-32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler-32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + Adler-32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by deflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If deflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + deflateGetDictionary() may return a length less than the window size, even + when more than the window size in input has been provided. It may return up + to 258 bytes less in that case, due to how zlib's implementation of deflate + manages the sliding window and lookahead for matches, where matches can be + up to 258 bytes long. If the application needs the last window-size bytes of + input, then that would need to be saved by the application outside of zlib. + + deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, but + does not free and reallocate the internal compression state. The stream + will leave the compression level and any other attributes that may have been + set unchanged. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2(). This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression approach (which is a function of the level) or the + strategy is changed, and if any input has been consumed in a previous + deflate() call, then the input available so far is compressed with the old + level and strategy using deflate(strm, Z_BLOCK). There are three approaches + for the compression levels 0, 1..3, and 4..9 respectively. The new level + and strategy will take effect at the next call of deflate(). + + If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does + not have enough output space to complete, then the parameter change will not + take effect. In this case, deflateParams() can be called again with the + same parameters and more output space to try again. + + In order to assure a change in the parameters on the first try, the + deflate stream should be flushed using deflate() with Z_BLOCK or other flush + request until strm.avail_out is not zero, before calling deflateParams(). + Then no more input data should be provided before the deflateParams() call. + If this is done, the old level and strategy will be applied to the data + compressed before deflateParams(), and the new level and strategy will be + applied to the the data compressed after deflateParams(). + + deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream + state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if + there was not enough output space to complete the compression of the + available input data before a change in the strategy or approach. Note that + in the case of a Z_BUF_ERROR, the parameters are not changed. A return + value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be + retried with more output space. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. +*/ + +ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, + unsigned *pending, + int *bits)); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an Adler-32 or a CRC-32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see + below), inflate() will not automatically decode concatenated gzip streams. + inflate() will return Z_STREAM_END at the end of the gzip stream. The state + would need to be reset to continue decoding a subsequent gzip stream. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler-32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler-32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current current value of + total_in which indicates where valid compressed data was found. In the + error case, the application may repeatedly call inflateSync, providing more + input each time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. If the window size is changed, then the + memory allocated for the window is freed, and the window will be reallocated + by inflate() if needed. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above, or -65536 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the parameters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, + z_const unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the default + behavior of inflate(), which expects a zlib header and trailer around the + deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero -- buf is ignored in that + case -- and inflateBack() will return a buffer error. inflateBack() will + call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. + out() should return zero on success, or non-zero on failure. If out() + returns non-zero, inflateBack() will return with an error. Neither in() nor + out() are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: ZLIB_DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + +#ifndef Z_SOLO + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. compress() is equivalent to compress2() with a level + parameter of Z_DEFAULT_COMPRESSION. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed data. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. +*/ + +ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen)); +/* + Same as uncompress, except that sourceLen is a pointer, where the + length of the source is *sourceLen. On return, *sourceLen is the number of + source bytes consumed. +*/ + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Opens a gzip (.gz) file for reading or writing. The mode parameter is as + in fopen ("rb" or "wb") but can also include a compression level ("wb9") or + a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only + compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) 'T' will + request transparent writing or appending with no compression and not using + the gzip format. + + "a" can be used instead of "w" to request that the gzip stream that will + be written be appended to the file. "+" will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + "x" when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of "e" when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen associates a gzFile with the file descriptor fd. File descriptors + are obtained from calls like open, dup, creat, pipe or fileno (if the file + has been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Three times that size in buffer space is allocated. A larger buffer + size of, for example, 64K or 128K bytes will noticeably increase the speed + of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. Previously provided + data is flushed before the parameter change. + + gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not + opened for writing, Z_ERRNO if there is an error writing the flushed data, + or Z_MEM_ERROR if there is a memory allocation error. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. If + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. If len is too large to fit in an int, + then nothing is read, -1 is returned, and the error state is set to + Z_STREAM_ERROR. +*/ + +ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, + gzFile file)); +/* + Read up to nitems items of size size from file to buf, otherwise operating + as gzread() does. This duplicates the interface of stdio's fread(), with + size_t request and return types. If the library defines size_t, then + z_size_t is identical to size_t. If not, then z_size_t is an unsigned + integer type that can contain a pointer. + + gzfread() returns the number of full items read of size size, or zero if + the end of the file was reached and a full item could not be read, or if + there was an error. gzerror() must be consulted if zero is returned in + order to determine if there was an error. If the multiplication of size and + nitems overflows, i.e. the product does not fit in a z_size_t, then nothing + is read, zero is returned, and the error state is set to Z_STREAM_ERROR. + + In the event that the end of file is reached and only a partial item is + available at the end, i.e. the remaining uncompressed data length is not a + multiple of size, then the final partial item is nevetheless read into buf + and the end-of-file flag is set. The length of the partial item read is not + provided, but could be inferred from the result of gztell(). This behavior + is the same as the behavior of fread() implementations in common libraries, + but it prevents the direct use of gzfread() to read a concurrently written + file, reseting and retrying on end-of-file, when size is not 1. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes written or 0 in case of + error. +*/ + +ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, + z_size_t nitems, gzFile file)); +/* + gzfwrite() writes nitems items of size size from buf to file, duplicating + the interface of stdio's fwrite(), with size_t request and return types. If + the library defines size_t, then z_size_t is identical to size_t. If not, + then z_size_t is an unsigned integer type that can contain a pointer. + + gzfwrite() returns the number of full items written of size size, or zero + if there was an error. If the multiplication of size and nitems overflows, + i.e. the product does not fit in a z_size_t, then nothing is written, zero + is returned, and the error state is set to Z_STREAM_ERROR. +*/ + +ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or a negative zlib error code in case + of error. The number of uncompressed bytes written is limited to 8191, or + one less than the buffer size given to gzbuffer(). The caller should assure + that this limit is not exceeded. If it is exceeded, then gzprintf() will + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. + This can be determined using zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or a + newline character is read and transferred to buf, or an end-of-file + condition is encountered. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte or -1 + in case of end of file or error. This is implemented as a macro for speed. + As such, it does not do all of the checking the other functions do. I.e. + it does not check to see if file is NULL, nor whether the structure file + points to has been clobbered or not. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter flush + is as in the deflate() function. The return value is the zlib error number + (see function gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatenated gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); + + Returns the starting position for the next gzread or gzwrite on the given + compressed file. This position represents a number of bytes in the + uncompressed data stream, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the given + compressed file. errnum is set to zlib error number. If an error occurred + in the file system and not in the compression library, errnum is set to + Z_ERRNO and the application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + +#endif /* !Z_SOLO */ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is Z_NULL, this function returns the + required initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as adler32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is Z_NULL, this function returns the required + initial value for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as crc32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#ifdef Z_PREFIX_SET +# define z_deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define z_inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#else +# define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#endif + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +# define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#else +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#endif + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#ifdef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# endif +# ifndef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); +#endif + +#else /* Z_SOLO */ + + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + +#endif /* !Z_SOLO */ + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp)); +ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); +ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); +#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, + const char *mode)); +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, + const char *format, + va_list va)); +# endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/dependencies/zlib-1.2.11/zlib.map b/dependencies/zlib-1.2.11/zlib.map new file mode 100644 index 0000000..40fa9db --- /dev/null +++ b/dependencies/zlib-1.2.11/zlib.map @@ -0,0 +1,94 @@ +ZLIB_1.2.0 { + global: + compressBound; + deflateBound; + inflateBack; + inflateBackEnd; + inflateBackInit_; + inflateCopy; + local: + deflate_copyright; + inflate_copyright; + inflate_fast; + inflate_table; + zcalloc; + zcfree; + z_errmsg; + gz_error; + gz_intmax; + _*; +}; + +ZLIB_1.2.0.2 { + gzclearerr; + gzungetc; + zlibCompileFlags; +} ZLIB_1.2.0; + +ZLIB_1.2.0.8 { + deflatePrime; +} ZLIB_1.2.0.2; + +ZLIB_1.2.2 { + adler32_combine; + crc32_combine; + deflateSetHeader; + inflateGetHeader; +} ZLIB_1.2.0.8; + +ZLIB_1.2.2.3 { + deflateTune; + gzdirect; +} ZLIB_1.2.2; + +ZLIB_1.2.2.4 { + inflatePrime; +} ZLIB_1.2.2.3; + +ZLIB_1.2.3.3 { + adler32_combine64; + crc32_combine64; + gzopen64; + gzseek64; + gztell64; + inflateUndermine; +} ZLIB_1.2.2.4; + +ZLIB_1.2.3.4 { + inflateReset2; + inflateMark; +} ZLIB_1.2.3.3; + +ZLIB_1.2.3.5 { + gzbuffer; + gzoffset; + gzoffset64; + gzclose_r; + gzclose_w; +} ZLIB_1.2.3.4; + +ZLIB_1.2.5.1 { + deflatePending; +} ZLIB_1.2.3.5; + +ZLIB_1.2.5.2 { + deflateResetKeep; + gzgetc_; + inflateResetKeep; +} ZLIB_1.2.5.1; + +ZLIB_1.2.7.1 { + inflateGetDictionary; + gzvprintf; +} ZLIB_1.2.5.2; + +ZLIB_1.2.9 { + inflateCodesUsed; + inflateValidate; + uncompress2; + gzfread; + gzfwrite; + deflateGetDictionary; + adler32_z; + crc32_z; +} ZLIB_1.2.7.1; diff --git a/dependencies/zlib-1.2.11/zlib.pc.cmakein b/dependencies/zlib-1.2.11/zlib.pc.cmakein new file mode 100644 index 0000000..a5e6429 --- /dev/null +++ b/dependencies/zlib-1.2.11/zlib.pc.cmakein @@ -0,0 +1,13 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=@CMAKE_INSTALL_PREFIX@ +libdir=@INSTALL_LIB_DIR@ +sharedlibdir=@INSTALL_LIB_DIR@ +includedir=@INSTALL_INC_DIR@ + +Name: zlib +Description: zlib compression library +Version: @VERSION@ + +Requires: +Libs: -L${libdir} -L${sharedlibdir} -lz +Cflags: -I${includedir} diff --git a/dependencies/zlib-1.2.11/zlib.pc.in b/dependencies/zlib-1.2.11/zlib.pc.in new file mode 100644 index 0000000..7e5acf9 --- /dev/null +++ b/dependencies/zlib-1.2.11/zlib.pc.in @@ -0,0 +1,13 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +sharedlibdir=@sharedlibdir@ +includedir=@includedir@ + +Name: zlib +Description: zlib compression library +Version: @VERSION@ + +Requires: +Libs: -L${libdir} -L${sharedlibdir} -lz +Cflags: -I${includedir} diff --git a/dependencies/zlib-1.2.11/zlib2ansi b/dependencies/zlib-1.2.11/zlib2ansi new file mode 100644 index 0000000..15e3e16 --- /dev/null +++ b/dependencies/zlib-1.2.11/zlib2ansi @@ -0,0 +1,152 @@ +#!/usr/bin/perl + +# Transform K&R C function definitions into ANSI equivalent. +# +# Author: Paul Marquess +# Version: 1.0 +# Date: 3 October 2006 + +# TODO +# +# Asumes no function pointer parameters. unless they are typedefed. +# Assumes no literal strings that look like function definitions +# Assumes functions start at the beginning of a line + +use strict; +use warnings; + +local $/; +$_ = <>; + +my $sp = qr{ \s* (?: /\* .*? \*/ )? \s* }x; # assume no nested comments + +my $d1 = qr{ $sp (?: [\w\*\s]+ $sp)* $sp \w+ $sp [\[\]\s]* $sp }x ; +my $decl = qr{ $sp (?: \w+ $sp )+ $d1 }xo ; +my $dList = qr{ $sp $decl (?: $sp , $d1 )* $sp ; $sp }xo ; + + +while (s/^ + ( # Start $1 + ( # Start $2 + .*? # Minimal eat content + ( ^ \w [\w\s\*]+ ) # $3 -- function name + \s* # optional whitespace + ) # $2 - Matched up to before parameter list + + \( \s* # Literal "(" + optional whitespace + ( [^\)]+ ) # $4 - one or more anythings except ")" + \s* \) # optional whitespace surrounding a Literal ")" + + ( (?: $dList )+ ) # $5 + + $sp ^ { # literal "{" at start of line + ) # Remember to $1 + //xsom + ) +{ + my $all = $1 ; + my $prefix = $2; + my $param_list = $4 ; + my $params = $5; + + StripComments($params); + StripComments($param_list); + $param_list =~ s/^\s+//; + $param_list =~ s/\s+$//; + + my $i = 0 ; + my %pList = map { $_ => $i++ } + split /\s*,\s*/, $param_list; + my $pMatch = '(\b' . join('|', keys %pList) . '\b)\W*$' ; + + my @params = split /\s*;\s*/, $params; + my @outParams = (); + foreach my $p (@params) + { + if ($p =~ /,/) + { + my @bits = split /\s*,\s*/, $p; + my $first = shift @bits; + $first =~ s/^\s*//; + push @outParams, $first; + $first =~ /^(\w+\s*)/; + my $type = $1 ; + push @outParams, map { $type . $_ } @bits; + } + else + { + $p =~ s/^\s+//; + push @outParams, $p; + } + } + + + my %tmp = map { /$pMatch/; $_ => $pList{$1} } + @outParams ; + + @outParams = map { " $_" } + sort { $tmp{$a} <=> $tmp{$b} } + @outParams ; + + print $prefix ; + print "(\n" . join(",\n", @outParams) . ")\n"; + print "{" ; + +} + +# Output any trailing code. +print ; +exit 0; + + +sub StripComments +{ + + no warnings; + + # Strip C & C++ coments + # From the perlfaq + $_[0] =~ + + s{ + /\* ## Start of /* ... */ comment + [^*]*\*+ ## Non-* followed by 1-or-more *'s + ( + [^/*][^*]*\*+ + )* ## 0-or-more things which don't start with / + ## but do end with '*' + / ## End of /* ... */ comment + + | ## OR C++ Comment + // ## Start of C++ comment // + [^\n]* ## followed by 0-or-more non end of line characters + + | ## OR various things which aren't comments: + + ( + " ## Start of " ... " string + ( + \\. ## Escaped char + | ## OR + [^"\\] ## Non "\ + )* + " ## End of " ... " string + + | ## OR + + ' ## Start of ' ... ' string + ( + \\. ## Escaped char + | ## OR + [^'\\] ## Non '\ + )* + ' ## End of ' ... ' string + + | ## OR + + . ## Anything other char + [^/"'\\]* ## Chars which doesn't start a comment, string or escape + ) + }{$2}gxs; + +} diff --git a/dependencies/zlib-1.2.11/zutil.c b/dependencies/zlib-1.2.11/zutil.c new file mode 100644 index 0000000..a76c6b0 --- /dev/null +++ b/dependencies/zlib-1.2.11/zutil.c @@ -0,0 +1,325 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2017 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" +#ifndef Z_SOLO +# include "gzguts.h" +#endif + +z_const char * const z_errmsg[10] = { + (z_const char *)"need dictionary", /* Z_NEED_DICT 2 */ + (z_const char *)"stream end", /* Z_STREAM_END 1 */ + (z_const char *)"", /* Z_OK 0 */ + (z_const char *)"file error", /* Z_ERRNO (-1) */ + (z_const char *)"stream error", /* Z_STREAM_ERROR (-2) */ + (z_const char *)"data error", /* Z_DATA_ERROR (-3) */ + (z_const char *)"insufficient memory", /* Z_MEM_ERROR (-4) */ + (z_const char *)"buffer error", /* Z_BUF_ERROR (-5) */ + (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */ + (z_const char *)"" +}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch ((int)(sizeof(uInt))) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch ((int)(sizeof(uLong))) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch ((int)(sizeof(voidpf))) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch ((int)(sizeof(z_off_t))) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef ZLIB_DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1L << 16; +#endif +#ifdef NO_GZIP + flags += 1L << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1L << 20; +#endif +#ifdef FASTEST + flags += 1L << 21; +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifdef NO_vsnprintf + flags += 1L << 25; +# ifdef HAS_vsprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1L << 26; +# endif +# endif +#else + flags += 1L << 24; +# ifdef NO_snprintf + flags += 1L << 25; +# ifdef HAS_sprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1L << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef ZLIB_DEBUG +#include +# ifndef verbose +# define verbose 0 +# endif +int ZLIB_INTERNAL z_verbose = verbose; + +void ZLIB_INTERNAL z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. + */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void ZLIB_INTERNAL zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int ZLIB_INTERNAL zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void ZLIB_INTERNAL zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + +#ifndef Z_SOLO + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf; + ulg bsize = (ulg)items*size; + + (void)opaque; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + int n; + + (void)opaque; + + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) +{ + (void)opaque; + return _halloc((long)items, size); +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + (void)opaque; + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + (void)opaque; + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void ZLIB_INTERNAL zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + (void)opaque; + free(ptr); +} + +#endif /* MY_ZCALLOC */ + +#endif /* !Z_SOLO */ diff --git a/dependencies/zlib-1.2.11/zutil.h b/dependencies/zlib-1.2.11/zutil.h new file mode 100644 index 0000000..b079ea6 --- /dev/null +++ b/dependencies/zlib-1.2.11/zutil.h @@ -0,0 +1,271 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#ifdef HAVE_HIDDEN +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include "zlib.h" + +#if defined(STDC) && !defined(Z_SOLO) +# if !(defined(_WIN32_WCE) && defined(_MSC_VER)) +# include +# endif +# include +# include +#endif + +#ifdef Z_SOLO + typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */ +#endif + +#ifndef local +# define local static +#endif +/* since "static" is used to mean two completely different things in C, we + define "local" for the non-static meaning of "static", for readability + (compile with -Dlocal if your debugger can't find static symbols) */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# ifndef Z_SOLO +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 1 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 2 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#ifdef __370__ +# if __TARGET_LIB__ < 0x20000000 +# define OS_CODE 4 +# elif __TARGET_LIB__ < 0x40000000 +# define OS_CODE 11 +# else +# define OS_CODE 8 +# endif +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 5 +#endif + +#ifdef OS2 +# define OS_CODE 6 +# if defined(M_I86) && !defined(Z_SOLO) +# include +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 7 +# ifndef Z_SOLO +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +# endif +#endif + +#ifdef __acorn +# define OS_CODE 13 +#endif + +#if defined(WIN32) && !defined(__CYGWIN__) +# define OS_CODE 10 +#endif + +#ifdef _BEOS_ +# define OS_CODE 16 +#endif + +#ifdef __TOS_OS400__ +# define OS_CODE 18 +#endif + +#ifdef __APPLE__ +# define OS_CODE 19 +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + +#if defined(__BORLANDC__) && !defined(MSDOS) + #pragma warn -8004 + #pragma warn -8008 + #pragma warn -8066 +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_WIN32) && \ + (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 3 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(pyr) || defined(Z_SOLO) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef ZLIB_DEBUG +# include + extern int ZLIB_INTERNAL z_verbose; + extern void ZLIB_INTERNAL z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + +#ifndef Z_SOLO + voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, + unsigned size)); + void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); +#endif + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +/* Reverse the bytes in a 32-bit value */ +#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +#endif /* ZUTIL_H */ diff --git a/downloadextractthread.cpp b/downloadextractthread.cpp new file mode 100644 index 0000000..acf2766 --- /dev/null +++ b/downloadextractthread.cpp @@ -0,0 +1,427 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +#include "downloadextractthread.h" +#include "config.h" +#include "dependencies/drivelist/src/drivelist.hpp" +#include "dependencies/mountutils/src/mountutils.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +const int DownloadExtractThread::MAX_QUEUE_SIZE = 64; + +class _extractThreadClass : public QThread { +public: + _extractThreadClass(DownloadExtractThread *parent) + : QThread(parent), _de(parent) + { + } + + virtual void run() + { + if (_de->isImage()) + _de->extractImageRun(); + else + _de->extractMultiFileRun(); + } + +protected: + DownloadExtractThread *_de; +}; + +DownloadExtractThread::DownloadExtractThread(const QByteArray &url, const QByteArray &localfilename, const QByteArray &expectedHash, QObject *parent) + : DownloadThread(url, localfilename, expectedHash, parent), _abufsize(IMAGEWRITER_BLOCKSIZE), _ethreadStarted(false), + _isImage(true), _inputHash(OSLIST_HASH_ALGORITHM) +{ + _extractThread = new _extractThreadClass(this); + _abuf = (char *) qMallocAligned(_abufsize, 4096); +} + +DownloadExtractThread::~DownloadExtractThread() +{ + if (!_extractThread->wait(2000)) + { + _extractThread->terminate(); + } + _queue.clear(); + _cv.notify_one(); + qFreeAligned(_abuf); +} + +size_t DownloadExtractThread::_writeData(const char *buf, size_t len) +{ + if (_cancelled) + return 0; + + _writeCache(buf, len); + + if (!_ethreadStarted) + { + // Extract thread is started when first data comes in + _ethreadStarted = true; + _extractThread->start(); + msleep(100); + } + + if (!_isImage) + { + _inputHash.addData(buf, len); + } + + _pushQueue(buf, len); + + return len; +} + +void DownloadExtractThread::_onDownloadSuccess() +{ + _pushQueue("", 0); +} + +void DownloadExtractThread::_onDownloadError(const QString &msg) +{ + DownloadThread::_onDownloadError(msg); + _cancelExtract(); +} + +void DownloadExtractThread::_cancelExtract() +{ + std::unique_lock lock(_queueMutex); + _queue.clear(); + _queue.push_back(QByteArray()); + + if (_queue.size() == 1) + { + lock.unlock(); + _cv.notify_one(); + } +} + +void DownloadExtractThread::cancelDownload() +{ + DownloadThread::cancelDownload(); + _cancelExtract(); +} + +// Raise exception on libarchive errors +static inline void _checkResult(int r, struct archive *a) +{ + if (r < ARCHIVE_OK) + // Warning + cerr << archive_error_string(a) << endl; + if (r < ARCHIVE_WARN) + // Fatal + throw runtime_error(archive_error_string(a)); +} + +// libarchive thread +void DownloadExtractThread::extractImageRun() +{ + struct archive *a = archive_read_new(); + struct archive_entry *entry; + int r; + + archive_read_support_filter_all(a); + archive_read_support_format_all(a); + archive_read_support_format_raw(a); // for .gz and such + archive_read_open(a, this, NULL, &DownloadExtractThread::_archive_read, &DownloadExtractThread::_archive_close); + + try + { + r = archive_read_next_header(a, &entry); + _checkResult(r, a); + + while (true) + { + ssize_t size = archive_read_data(a, _abuf, _abufsize); + if (size < 0) + throw runtime_error(archive_error_string(a)); + if (size == 0) + break; + + if (_writeFile(_abuf, size) != (size_t) size) + { + if (!_cancelled) + { + DownloadThread::cancelDownload(); + emit error(tr("Error writing to storage")); + } + archive_read_free(a); + return; + } + } + + _writeComplete(); + } + catch (exception &e) + { + if (!_cancelled) + { + // Fatal error + DownloadThread::cancelDownload(); + emit error(tr("Error extracting archive: %1").arg(e.what())); + } + } + + archive_read_free(a); +} + +void DownloadExtractThread::extractMultiFileRun() +{ + QString folder; + QStringList filesExtracted, dirExtracted; + QByteArray devlower = _filename.toLower(); + + /* See if OS auto-mounted the device */ + for (int tries = 0; tries < 3; tries++) + { + QThread::sleep(1); + auto l = Drivelist::ListStorageDevices(); + for (auto i : l) + { + if (QByteArray::fromStdString(i.device).toLower() == devlower && i.mountpoints.size() == 1) + { + folder = QByteArray::fromStdString(i.mountpoints.front()); + break; + } + } + } + +#ifdef Q_OS_LINUX + bool manualmount = false; + + if (folder.isEmpty()) + { + /* Manually mount folder */ + QTemporaryDir td; + QStringList args; + folder = td.path(); + QByteArray fatpartition = _filename; + if (isdigit(fatpartition.at(fatpartition.length()-1))) + fatpartition += "p1"; + else + fatpartition += "1"; + args << fatpartition << folder; + + if (QProcess::execute("mount", args) != 0) + { + emit error(tr("Error mounting FAT32 partition")); + return; + } + td.setAutoRemove(false); + manualmount = true; + } +#endif + + if (folder.isEmpty()) + { + emit error(tr("Operating system did not mount FAT32 partition")); + return; + } + + QString currentDir; + struct archive *a = archive_read_new(); + struct archive *ext = archive_write_disk_new(); + struct archive_entry *entry; + /* Extra safety checks: do not allow existing files to be overwritten (SD card should be formatted by previous step), + * do not allow absolute paths, do not allow insecure symlinks, no special permissions */ + int r, flags = ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS + | ARCHIVE_EXTRACT_SECURE_NODOTDOT | ARCHIVE_EXTRACT_SECURE_SYMLINKS | ARCHIVE_EXTRACT_NO_OVERWRITE + /*ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_XATTR*/; +#ifndef Q_OS_WIN + if (::getuid() == 0) + flags |= ARCHIVE_EXTRACT_OWNER; +#endif + + currentDir = QDir::currentPath(); + + if (!QDir::setCurrent(folder)) + { + DownloadThread::cancelDownload(); + emit error(tr("Error changing to directory '%1'").arg(folder)); + return; + } + + archive_read_support_filter_all(a); + archive_read_support_format_all(a); + archive_write_disk_set_options(ext, flags); + archive_read_open(a, this, NULL, &DownloadExtractThread::_archive_read, &DownloadExtractThread::_archive_close); + + try + { + while ( (r = archive_read_next_header(a, &entry)) != ARCHIVE_EOF) + { + _checkResult(r, a); + r = archive_write_header(ext, entry); + if (r < ARCHIVE_OK) + qDebug() << archive_error_string(ext); + else if (archive_entry_size(entry) > 0) + { + //checkResult(copyData(a, ext), a); + const void *buff; + size_t size; + int64_t offset; + QString filename = QString::fromWCharArray(archive_entry_pathname_w(entry)); + + if (archive_entry_filetype(entry) == AE_IFDIR) // Empty directory + dirExtracted.append(filename); + else + filesExtracted.append(filename); + + while ( (r = archive_read_data_block(a, &buff, &size, &offset)) != ARCHIVE_EOF) + { + _checkResult(r, a); + _checkResult(archive_write_data_block(ext, buff, size, offset), ext); + _bytesWritten += size; + } + } + _checkResult(archive_write_finish_entry(ext), ext); + } + + QByteArray computedHash = _inputHash.result().toHex(); + qDebug() << "Hash of compressed multi-file zip:" << computedHash; + if (!_expectedHash.isEmpty() && _expectedHash != computedHash) + { + qDebug() << "Mismatch with expected hash:" << _expectedHash; + throw runtime_error("Download corrupt. SHA256 does not match"); + } + if (_cacheEnabled && _expectedHash == computedHash) + { + _cachefile.close(); + emit cacheFileUpdated(computedHash); + } + + emit success(); + } + catch (exception &e) + { + if (_cachefile.isOpen()) + _cachefile.remove(); + + qDebug() << "Deleting extracted files"; + for (auto filename : filesExtracted) + { + QFileInfo fi(filename); + QString path = fi.path(); + if (!path.isEmpty() && path != "." && !dirExtracted.contains(path)) + dirExtracted.append(path); + + QFile::remove(filename); + } + for (int idx = dirExtracted.count()-1; idx >= 0; idx--) + { + QDir d; + d.rmdir(dirExtracted[idx]); + } + qDebug() << filesExtracted << dirExtracted; + + if (!_cancelled) + { + /* Fatal error */ + DownloadThread::cancelDownload(); + emit error(tr("Error extracting archive: %1").arg(e.what())); + } + } + + archive_read_free(a); + archive_write_free(ext); + QDir::setCurrent(currentDir); + +#ifdef Q_OS_LINUX + if (manualmount) + { + QStringList args; + args << folder; + QProcess::execute("umount", args); + QDir d; + d.rmdir(folder); + } +#endif + + eject_disk(_filename.constData()); +} + +ssize_t DownloadExtractThread::_on_read(struct archive *, const void **buff) +{ + _buf = _popQueue(); + *buff = _buf.data(); + return _buf.size(); +} + +int DownloadExtractThread::_on_close(struct archive *) +{ + return 0; +} + +// static callback functions that call object oriented equivalents +ssize_t DownloadExtractThread::_archive_read(struct archive *a, void *client_data, const void **buff) +{ + return static_cast(client_data)->_on_read(a, buff); +} + +int DownloadExtractThread::_archive_close(struct archive *a, void *client_data) +{ + return static_cast(client_data)->_on_close(a); +} + +bool DownloadExtractThread::isImage() +{ + return _isImage; +} + +void DownloadExtractThread::enableMultipleFileExtraction() +{ + _isImage = false; +} + +// Synchronized queue using monitor consumer/producer pattern +QByteArray DownloadExtractThread::_popQueue() +{ + std::unique_lock lock(_queueMutex); + + _cv.wait(lock, [this]{ + return _queue.size() != 0; + }); + + QByteArray result = _queue.front(); + _queue.pop_front(); + + if (_queue.size() == (MAX_QUEUE_SIZE-1)) + { + lock.unlock(); + _cv.notify_one(); + } + + return result; +} + +void DownloadExtractThread::_pushQueue(const char *data, size_t len) +{ + std::unique_lock lock(_queueMutex); + + _cv.wait(lock, [this]{ + return _queue.size() != MAX_QUEUE_SIZE; + }); + + _queue.emplace_back(data, len); + + if (_queue.size() == 1) + { + lock.unlock(); + _cv.notify_one(); + } +} diff --git a/downloadextractthread.h b/downloadextractthread.h new file mode 100644 index 0000000..ec54085 --- /dev/null +++ b/downloadextractthread.h @@ -0,0 +1,59 @@ +#ifndef DOWNLOADEXTRACTTHREAD_H +#define DOWNLOADEXTRACTTHREAD_H + +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +#include "downloadthread.h" +#include +#include + +class _extractThreadClass; + +class DownloadExtractThread : public DownloadThread +{ + Q_OBJECT +public: + /* + * Constructor + * + * - url: URL to download + * - localfolder: Folder to extract archive to + */ + explicit DownloadExtractThread(const QByteArray &url, const QByteArray &localfilename = "", const QByteArray &expectedHash = "", QObject *parent = nullptr); + + virtual ~DownloadExtractThread(); + virtual void cancelDownload(); + virtual void extractImageRun(); + virtual void extractMultiFileRun(); + virtual bool isImage(); + virtual void enableMultipleFileExtraction(); + +protected: + char *_abuf; + size_t _abufsize; + _extractThreadClass *_extractThread; + std::deque _queue; + static const int MAX_QUEUE_SIZE; + std::mutex _queueMutex; + std::condition_variable _cv; + bool _ethreadStarted, _isImage; + QCryptographicHash _inputHash; + + QByteArray _popQueue(); + void _pushQueue(const char *data, size_t len); + void _cancelExtract(); + virtual size_t _writeData(const char *buf, size_t len); + virtual void _onDownloadSuccess(); + virtual void _onDownloadError(const QString &msg); + + ssize_t _on_read(struct archive *a, const void **buff); + int _on_close(struct archive *a); + + static ssize_t _archive_read(struct archive *a, void *client_data, const void **buff); + static int _archive_close(struct archive *a, void *client_data); +}; + +#endif // DOWNLOADEXTRACTTHREAD_H diff --git a/downloadthread.cpp b/downloadthread.cpp new file mode 100644 index 0000000..7f44d89 --- /dev/null +++ b/downloadthread.cpp @@ -0,0 +1,649 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +#include "downloadthread.h" +#include "config.h" +#include "dependencies/mountutils/src/mountutils.hpp" +#include "dependencies/drivelist/src/drivelist.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef Q_OS_LINUX +#include +#include +#include "linux/udisks2api.h" +#endif + +using namespace std; + +QByteArray DownloadThread::_proxy; +int DownloadThread::_curlCount = 0; + +DownloadThread::DownloadThread(const QByteArray &url, const QByteArray &localfilename, const QByteArray &expectedHash, QObject *parent) : + QThread(parent), _startOffset(0), _lastDlTotal(0), _lastDlNow(0), _verifyTotal(0), _lastVerifyNow(0), _bytesWritten(0), _url(url), _filename(localfilename), _expectedHash(expectedHash), + _firstBlock(nullptr), _cancelled(false), _successful(false), _verifyEnabled(false), _cacheEnabled(false), _lastModified(0), _serverTime(0), _lastFailureTime(0), + _file(NULL), _writehash(OSLIST_HASH_ALGORITHM), _verifyhash(OSLIST_HASH_ALGORITHM) +{ + if (!_curlCount) + curl_global_init(CURL_GLOBAL_DEFAULT); + _curlCount++; +} + +DownloadThread::~DownloadThread() +{ + _cancelled = true; + wait(); + if (_file.isOpen()) + _file.close(); + + if (_firstBlock) + qFreeAligned(_firstBlock); + + if (!--_curlCount) + curl_global_cleanup(); +} + +void DownloadThread::setProxy(const QByteArray &proxy) +{ + _proxy = proxy; +} + +QByteArray DownloadThread::proxy() +{ + return _proxy; +} + +void DownloadThread::setUserAgent(const QByteArray &ua) +{ + _useragent = ua; +} + +/* Curl write callback function, let it call the object oriented version */ +size_t DownloadThread::_curl_write_callback(char *ptr, size_t size, size_t nmemb, void *userdata) +{ + return static_cast(userdata)->_writeData(ptr, size * nmemb); +} + +int DownloadThread::_curl_xferinfo_callback(void *userdata, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) +{ + return (static_cast(userdata)->_progress(dltotal, dlnow, ultotal, ulnow) == false); +} + +size_t DownloadThread::_curl_header_callback( void *ptr, size_t size, size_t nmemb, void *userdata) +{ + int len = size*nmemb; + string headerstr((char *) ptr, len); + static_cast(userdata)->_header(headerstr); + + return len; +} + +bool DownloadThread::_openAndPrepareDevice() +{ + if (_filename.startsWith("/dev/")) + { + unmount_disk(_filename.constData()); + } + + _file.setFileName(_filename); + +#ifdef Q_OS_WIN + qDebug() << "device" << _filename; + + std::regex windriveregex("\\\\\\\\.\\\\PHYSICALDRIVE([0-9]+)", std::regex_constants::icase); + std::cmatch m; + + if (std::regex_match(_filename.constData(), m, windriveregex)) + { + QByteArray nr = QByteArray::fromStdString(m[1]); + + if (!nr.isEmpty()) { + qDebug() << "Removing partition table from Windows drive #" << nr << "(" << _filename << ")"; + + QProcess proc; + proc.start("diskpart"); + proc.waitForStarted(); + proc.write("select disk "+nr+"\r\n" + "clean\r\n" + "rescan\r\n"); + proc.closeWriteChannel(); + proc.waitForFinished(); + + if (proc.exitCode()) + { + emit error(tr("Error running diskpart: %1").arg(QString(proc.readAllStandardError()))); + return false; + } + } + } + + auto l = Drivelist::ListStorageDevices(); + QByteArray devlower = _filename.toLower(); + QByteArray driveLetter; + for (auto i : l) + { + if (QByteArray::fromStdString(i.device).toLower() == devlower) + { + if (i.mountpoints.size() == 1) + { + driveLetter = QByteArray::fromStdString(i.mountpoints.front()); + if (driveLetter.endsWith("\\")) + driveLetter.chop(1); + } + else if (i.mountpoints.size() > 1) + { + emit error(tr("Error removing existing partitions")); + return false; + } + else + { + qDebug() << "Device no longer has any volumes. Nothing to lock."; + } + } + } + + qDebug() << "sleeping to let Windows discovers there are no partitions"; + sleep(2); + qDebug() << "done sleeping"; + + if (!driveLetter.isEmpty()) + { + _volumeFile.setFileName("\\\\.\\"+driveLetter); + if (_volumeFile.open(QIODevice::ReadWrite)) + _volumeFile.lockVolume(); + } + +#endif + +#ifdef Q_OS_DARWIN + _filename.replace("/dev/disk", "/dev/rdisk"); + + if (!_file.authOpen(_filename)) { + emit error(tr("Error running authopen to gain access to disk device '%1'").arg(QString(_filename))); + return false; + } +#else + if (!_file.open(QIODevice::ReadWrite | QIODevice::Unbuffered)) + { +#ifdef Q_OS_LINUX + /* Opening device directly did not work, ask udisks2 to do it for us, + * if necessary prompting for authorization */ + UDisks2Api udisks; + int fd = udisks.authOpen(_filename); + if (fd != -1) + { + _file.open(fd, QIODevice::ReadWrite | QIODevice::Unbuffered, QFileDevice::AutoCloseHandle); + } + else + { +#endif + emit error(tr("Cannot open storage device '%1'.").arg(QString(_filename))); + return false; +#ifdef Q_OS_LINUX + } +#endif + } +#endif + +#ifndef Q_OS_WIN + // Zero out MBR + qint64 knownsize = _file.size(); + QByteArray emptyMB(1024*1024, 0); + + if (!_file.write(emptyMB.data(), emptyMB.size()) || !_file.flush()) + { + emit error(tr("Write error while zero'ing out MBR")); + return false; + } + + // Zero out last part of card (may have GPT backup table) + if (knownsize > emptyMB.size()) + { + if (!_file.seek(knownsize-emptyMB.size()) + || !_file.write(emptyMB.data(), emptyMB.size()) + || !_file.flush() + || !::fsync(_file.handle())) + { + emit error(tr("Write error while trying to zero out last part of card.\n" + "Card could be advertising wrong capacity (possible counterfeit)")); + return false; + } + } + emptyMB.clear(); + _file.seek(0); +#endif + +#ifdef Q_OS_LINUX + /* Optional optimizations for Linux */ + + /* See if we can DISCARD/TRIM the SD card */ + uint64_t devsize, range[2]; + int fd = _file.handle(); + + if (::ioctl(fd, BLKGETSIZE64, &devsize) == -1) { + qDebug() << "Error getting device/sector size with BLKGETSIZE64 ioctl():" << strerror(errno); + } + else + { + int secsize; + ::ioctl(fd, BLKSSZGET, &secsize); + qDebug() << "Sector size:" << secsize << "Device size:" << devsize; + + qDebug() << "Try to perform TRIM/DISCARD on device"; + range[0] = 0; + range[1] = devsize; + if (::ioctl(fd, BLKDISCARD, &range) == -1) + { + qDebug() << "BLKDISCARD not supported"; + } + else + { + qDebug() << "BLKDISCARD successful"; + } + } +#endif + + return true; +} + +void DownloadThread::run() +{ + if (isImage() && !_openAndPrepareDevice()) + { + return; + } + + char errorBuf[CURL_ERROR_SIZE] = {0}; + _c = curl_easy_init(); + curl_easy_setopt(_c, CURLOPT_NOSIGNAL, 1); + curl_easy_setopt(_c, CURLOPT_WRITEFUNCTION, &DownloadThread::_curl_write_callback); + curl_easy_setopt(_c, CURLOPT_WRITEDATA, this); + curl_easy_setopt(_c, CURLOPT_XFERINFOFUNCTION, &DownloadThread::_curl_xferinfo_callback); + curl_easy_setopt(_c, CURLOPT_PROGRESSDATA, this); + curl_easy_setopt(_c, CURLOPT_NOPROGRESS, 0); + curl_easy_setopt(_c, CURLOPT_URL, _url.constData()); + curl_easy_setopt(_c, CURLOPT_FOLLOWLOCATION, 1); + curl_easy_setopt(_c, CURLOPT_MAXREDIRS, 10); + curl_easy_setopt(_c, CURLOPT_ERRORBUFFER, errorBuf); + curl_easy_setopt(_c, CURLOPT_FAILONERROR, 1); + curl_easy_setopt(_c, CURLOPT_HEADERFUNCTION, &DownloadThread::_curl_header_callback); + curl_easy_setopt(_c, CURLOPT_HEADERDATA, this); + + if (!_useragent.isEmpty()) + curl_easy_setopt(_c, CURLOPT_USERAGENT, _useragent.constData()); + if (!_proxy.isEmpty()) + curl_easy_setopt(_c, CURLOPT_PROXY, _proxy.constData()); + + + _timer.start(); + CURLcode ret = curl_easy_perform(_c); + + /* Deal with badly configured HTTP servers that terminate the connection quickly + if connections stalls for some seconds while kernel commits buffers to slow SD card */ + while (ret == CURLE_PARTIAL_FILE) + { + time_t t = time(NULL); + qDebug() << "HTTP connection lost. Time:" << t; + + /* If last failure happened less than 5 seconds ago, something else may + be wrong. Sleep some time to prevent hammering server */ + if (t - _lastFailureTime < 5) + { + qDebug() << "Sleeping 5 seconds"; + ::sleep(5); + } + _lastFailureTime = t; + + _startOffset = _lastDlNow; + curl_easy_setopt(_c, CURLOPT_RESUME_FROM_LARGE, _startOffset); + + ret = curl_easy_perform(_c); + } + + curl_easy_cleanup(_c); + + switch (ret) + { + case CURLE_OK: + _successful = true; + qDebug() << "Download done in" << _timer.elapsed() / 1000 << "seconds"; + _onDownloadSuccess(); + break; + case CURLE_WRITE_ERROR: + deleteDownloadedFile(); + _onDownloadError("Error writing file to disk"); + break; + case CURLE_ABORTED_BY_CALLBACK: + deleteDownloadedFile(); + break; + default: + deleteDownloadedFile(); + _onDownloadError(errorBuf); + } +} + +size_t DownloadThread::_writeData(const char *buf, size_t len) +{ + _writeCache(buf, len); + + if (!_filename.isEmpty()) + { + return _writeFile(buf, len); + } + else + { + _buf.append(buf, len); + return len; + } +} + +void DownloadThread::_writeCache(const char *buf, size_t len) +{ + if (!_cacheEnabled || _cancelled) + return; + + if (_cachefile.write(buf, len) != len) + { + qDebug() << "Error writing to cache file. Disabling caching."; + _cacheEnabled = false; + _cachefile.remove(); + } +} + +void DownloadThread::setCacheFile(const QString &filename, qint64 filesize) +{ + _cachefile.setFileName(filename); + if (_cachefile.open(QIODevice::WriteOnly)) + { + _cacheEnabled = true; + if (filesize) + { + /* Pre-allocate space */ + _cachefile.resize(filesize); + } + } + else + { + qDebug() << "Error opening cache file for writing. Disabling caching."; + } +} + +size_t DownloadThread::_writeFile(const char *buf, size_t len) +{ + if (_cancelled) + return len; + + _writehash.addData(buf, len); + + if (!_firstBlock) + { + _firstBlock = (char *) qMallocAligned(len, 4096); + _firstBlockSize = len; + ::memcpy(_firstBlock, buf, len); + //_firstBlock = QByteArray(buf, len); + + return _file.seek(len) ? len : 0; + } + + qint64 written = _file.write(buf, len); + _bytesWritten += written; + + if ((size_t) written != len) + { + qDebug() << "Write error:" << _file.errorString() << "while writing len:" << len; + if (len % 512) + qDebug() << "NOT SECTOR SIZE write len:" << len; + if (((uintptr_t)buf) % 512) + qDebug() << "Memory not aligned to sector size"; + } + + return (written < 0) ? 0 : written; +} + +bool DownloadThread::_progress(curl_off_t dltotal, curl_off_t dlnow, curl_off_t /*ultotal*/, curl_off_t /*ulnow*/) +{ + if (dltotal) + _lastDlTotal = _startOffset + dltotal; + _lastDlNow = _startOffset + dlnow; + + return !_cancelled; +} + +void DownloadThread::_header(const string &header) +{ + if (header.compare(0, 6, "Date: ") == 0) + { + _serverTime = curl_getdate(header.data()+6, NULL); + } + else if (header.compare(0, 15, "Last-Modified: ") == 0) + { + _lastModified = curl_getdate(header.data()+15, NULL); + } + qDebug() << "Received header:" << header.c_str(); +} + +void DownloadThread::cancelDownload() +{ + _cancelled = true; + //deleteDownloadedFile(); +} + +QByteArray DownloadThread::data() +{ + return _buf; +} + +bool DownloadThread::successfull() +{ + return _successful; +} + +time_t DownloadThread::lastModified() +{ + return _lastModified; +} + +time_t DownloadThread::serverTime() +{ + return _serverTime; +} + +void DownloadThread::deleteDownloadedFile() +{ + if (!_filename.isEmpty()) + { + _file.close(); + if (_cachefile.isOpen()) + _cachefile.remove(); +#ifdef Q_OS_WIN + _volumeFile.close(); +#endif + + if (!_filename.startsWith("/dev/") && !_filename.startsWith("\\\\.\\")) + { + //_file.remove(); + } + } +} + +uint64_t DownloadThread::dlNow() +{ + return _lastDlNow; +} + +uint64_t DownloadThread::dlTotal() +{ + return _lastDlTotal; +} + +uint64_t DownloadThread::verifyNow() +{ + return _lastVerifyNow; +} + +uint64_t DownloadThread::verifyTotal() +{ + return _verifyTotal; +} + +uint64_t DownloadThread::bytesWritten() +{ + return _bytesWritten; +} + +void DownloadThread::_onDownloadSuccess() +{ + _writeComplete(); +} + +void DownloadThread::_onDownloadError(const QString &msg) +{ + emit error(msg); +} + +void DownloadThread::_writeComplete() +{ + if (!_file.flush()) + { + DownloadThread::_onDownloadError(tr("Error writing to storage (while flushing)")); + return; + } + +#ifndef Q_OS_WIN + if (::fsync(_file.handle()) != 0) { + DownloadThread::_onDownloadError(tr("Error writing to storage (while fsync)")); + return; + } +#endif + + qDebug() << "Write done in" << _timer.elapsed() / 1000 << "seconds"; + QByteArray computedHash = _writehash.result().toHex(); + qDebug() << "Hash of uncompressed image:" << computedHash; + if (!_expectedHash.isEmpty() && _expectedHash != computedHash) + { + qDebug() << "Mismatch with expected hash:" << _expectedHash; + _file.close(); + if (_cachefile.isOpen()) + _cachefile.remove(); +#ifdef Q_OS_WIN + _volumeFile.close(); +#endif + DownloadThread::_onDownloadError(tr("Download corrupt. Hash does not match")); + return; + } + if (_cacheEnabled && _expectedHash == computedHash) + { + _cachefile.close(); + emit cacheFileUpdated(computedHash); + } + + /* Verify */ + if (_verifyEnabled && !_verify()) + { + _file.close(); +#ifdef Q_OS_WIN + _volumeFile.close(); +#endif + return; + } + + emit finalizing(); + + if (_firstBlock) + { + qDebug() << "Writing first block (which we skipped at first)"; + _file.seek(0); + if (!_file.write(_firstBlock, _firstBlockSize) || !_file.flush()) + { + qFreeAligned(_firstBlock); + _firstBlock = nullptr; + + DownloadThread::_onDownloadError(tr("Error writing first block (partition table)")); + return; + } + _bytesWritten += _firstBlockSize; + qFreeAligned(_firstBlock); + _firstBlock = nullptr; + } + + _file.close(); +#ifdef Q_OS_WIN + _volumeFile.close(); +#endif + +#ifdef Q_OS_DARWIN + QThread::sleep(1); + _filename.replace("/dev/rdisk", "/dev/disk"); +#endif + eject_disk(_filename.constData()); + + emit success(); +} + +bool DownloadThread::_verify() +{ + char *verifyBuf = (char *) qMallocAligned(IMAGEWRITER_VERIFY_BLOCKSIZE, 4096); + _lastVerifyNow = 0; + _verifyTotal = _file.pos(); + + if (!_firstBlock) + { + _file.seek(0); + } + else + { + _verifyhash.addData(_firstBlock, _firstBlockSize); + _file.seek(_firstBlockSize); + _lastVerifyNow += _firstBlockSize; + } + + while (_verifyEnabled && _lastVerifyNow < _verifyTotal && !_cancelled) + { + qint64 lenRead = _file.read(verifyBuf, IMAGEWRITER_VERIFY_BLOCKSIZE); + if (lenRead == -1) + { + DownloadThread::_onDownloadError(tr("Error reading from storage.\n" + "SD card may be broken.")); + return false; + } + + _verifyhash.addData(verifyBuf, lenRead); + _lastVerifyNow += lenRead; + } + qFreeAligned(verifyBuf); + + qDebug() << "Verify hash:" << _verifyhash.result().toHex(); + + if (_verifyhash.result() == _writehash.result() || !_verifyEnabled || _cancelled) + { + return true; + } + else + { + DownloadThread::_onDownloadError(tr("Verifying write failed. Contents of SD card is different then what was written to it." + /*"SD card may be broken, or other application may have accessed storage."*/)); + } + + return false; +} + +void DownloadThread::setVerifyEnabled(bool verify) +{ + _verifyEnabled = verify; +} + +bool DownloadThread::isImage() +{ + return true; +} diff --git a/downloadthread.h b/downloadthread.h new file mode 100644 index 0000000..c8457e7 --- /dev/null +++ b/downloadthread.h @@ -0,0 +1,171 @@ +#ifndef DOWNLOADTHREAD_H +#define DOWNLOADTHREAD_H + +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef Q_OS_WIN +#include "windows/winfile.h" +#endif +#ifdef Q_OS_DARWIN +#include "mac/macfile.h" +#endif + + +class DownloadThread : public QThread +{ + Q_OBJECT +public: + /* + * Constructor + * + * - url: URL to download + * - localfilename: File name to save downloaded file as. If empty, store data in memory buffer + */ + explicit DownloadThread(const QByteArray &url, const QByteArray &localfilename = "", const QByteArray &expectedHash = "", QObject *parent = nullptr); + + /* + * Destructor + * + * Waits until download is complete + * If this is not desired, call cancelDownload() first + */ + virtual ~DownloadThread(); + + /* + * Cancel download + * + * Async function. Returns immedeately, but can take a second before download actually stops + */ + virtual void cancelDownload(); + + /* + * Set proxy server. + * Specify a string like this: user:pass@proxyserver:8080/ + * Used globally, for all connections + */ + static void setProxy(const QByteArray &proxy); + + /* + * Returns proxy server used + */ + static QByteArray proxy(); + + /* + * Set user-agent header string + */ + void setUserAgent(const QByteArray &ua); + + /* + * Returns true if download has been successful + */ + bool successfull(); + + /* + * Returns the downloaded data if saved to memory buffer instead of file + */ + QByteArray data(); + + /* + * Delete downloaded file + */ + void deleteDownloadedFile(); + + /* + * Return last-modified date (if available) as unix timestamp + * (seconds since 1970) + */ + time_t lastModified(); + + /* + * Return current server time as unix timestamp + */ + time_t serverTime(); + + /* + * Enable/disable verification + */ + void setVerifyEnabled(bool verify); + + /* + * Enable disk cache + */ + void setCacheFile(const QString &filename, qint64 filesize = 0); + + /* + * Thread safe download progress query functions + */ + uint64_t dlNow(); + uint64_t dlTotal(); + uint64_t verifyNow(); + uint64_t verifyTotal(); + uint64_t bytesWritten(); + + virtual bool isImage(); + +signals: + void success(); + void error(QString msg); + void cacheFileUpdated(QByteArray sha256); + void finalizing(); + +protected: + virtual void run(); + virtual void _onDownloadSuccess(); + virtual void _onDownloadError(const QString &msg); + + size_t _writeFile(const char *buf, size_t len); + void _writeComplete(); + bool _verify(); + int _authopen(const QByteArray &filename); + bool _openAndPrepareDevice(); + void _writeCache(const char *buf, size_t len); + + /* + * libcurl callbacks + */ + virtual size_t _writeData(const char *buf, size_t len); + bool _progress(curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow); + void _header(const std::string &header); + + static size_t _curl_write_callback(char *ptr, size_t size, size_t nmemb, void *userdata); + static int _curl_xferinfo_callback(void *userdata, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow); + static size_t _curl_header_callback( void *ptr, size_t size, size_t nmemb, void *userdata); + + CURL *_c; + curl_off_t _startOffset; + std::atomic _lastDlTotal, _lastDlNow, _verifyTotal, _lastVerifyNow, _bytesWritten; + QByteArray _url, _useragent, _buf, _filename, _lastError, _expectedHash; + char *_firstBlock; + size_t _firstBlockSize; + static QByteArray _proxy; + static int _curlCount; + bool _cancelled, _successful, _verifyEnabled, _cacheEnabled; + time_t _lastModified, _serverTime, _lastFailureTime; + QElapsedTimer _timer; + +#ifdef Q_OS_WIN + WinFile _file, _volumeFile; +#elif defined(Q_OS_DARWIN) + MacFile _file; +#else + QFile _file; +#endif + QFile _cachefile; + + QCryptographicHash _writehash, _verifyhash; +}; + +#endif // DOWNLOADTHREAD_H diff --git a/driveformatthread.cpp b/driveformatthread.cpp new file mode 100644 index 0000000..48ed680 --- /dev/null +++ b/driveformatthread.cpp @@ -0,0 +1,211 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +#include "driveformatthread.h" +#include "dependencies/drivelist/src/drivelist.hpp" +#include "dependencies/mountutils/src/mountutils.hpp" +#include +#include +#include +#include +#include + +#ifdef Q_OS_LINUX +#include "linux/udisks2api.h" +#include +#endif + +DriveFormatThread::DriveFormatThread(const QByteArray &device, QObject *parent) + : QThread(parent), _device(device) +{ + +} + +DriveFormatThread::~DriveFormatThread() +{ + wait(); +} + +void DriveFormatThread::run() +{ +#ifdef Q_OS_WIN + std::regex windriveregex("\\\\\\\\.\\\\PHYSICALDRIVE([0-9]+)", std::regex_constants::icase); + std::cmatch m; + + if (std::regex_match(_device.constData(), m, windriveregex)) + { + QByteArray nr = QByteArray::fromStdString(m[1]); + + qDebug() << "Formatting Windows drive #" << nr << "(" << _device << ")"; + + QProcess proc; + QByteArray diskpartCmds = + "select disk "+nr+"\r\n" + "clean\r\n" + "create partition primary\r\n" + "select partition 1\r\n" + "set id=0e\r\n" + "assign\r\n"; + proc.start("diskpart"); + proc.waitForStarted(); + proc.write(diskpartCmds); + proc.closeWriteChannel(); + proc.waitForFinished(); + + QByteArray output = proc.readAllStandardError(); + qDebug() << output; + qDebug() << "Done running diskpart. Exit status code =" << proc.exitCode(); + + if (proc.exitCode()) + { + emit error(tr("Error partitioning: %1").arg(QString(output))); + } + else + { + auto l = Drivelist::ListStorageDevices(); + QByteArray devlower = _device.toLower(); + for (auto i : l) + { + if (QByteArray::fromStdString(i.device).toLower() == devlower && i.mountpoints.size() == 1) + { + QByteArray driveLetter = QByteArray::fromStdString(i.mountpoints.front()); + if (driveLetter.endsWith("\\")) + driveLetter.chop(1); + qDebug() << "Drive letter of device:" << driveLetter; + + QProcess f32format; + QStringList args; + args << "-y" << driveLetter; + f32format.start(QCoreApplication::applicationDirPath()+"/fat32format.exe", args); + if (!f32format.waitForStarted()) + { + emit error(tr("Error starting fat32format")); + return; + } + + //f32format.write("y\r\n"); + f32format.closeWriteChannel(); + f32format.waitForFinished(120000); + + if (f32format.exitStatus() || f32format.exitCode()) + { + emit error(tr("Error running fat32format: %1").arg(QString(f32format.readAll()))); + } + else + { + emit success(); + } + return; + } + } + + emit error(tr("Error determining new drive letter")); + } + } + else + { + emit error(tr("Invalid device: %1").arg(QString(_device))); + } +#elif defined(Q_OS_DARWIN) + QProcess proc; + QStringList args; + args << "eraseDisk" << "FAT32" << "SDCARD" << "MBRFormat" << _device; + proc.start("diskutil", args); + proc.waitForFinished(); + + QByteArray output = proc.readAllStandardError(); + qDebug() << args; + qDebug() << "diskutil output:" << output; + + if (proc.exitCode()) + { + emit error(tr("Error partitioning: %1").arg(QString(output))); + } + else + { + emit success(); + } + +#elif defined(Q_OS_LINUX) + + if (::access(_device, W_OK) != 0) + { + /* Not running as root, try to outsource formatting to udisks2 */ + + UDisks2Api udisks2; + if (udisks2.formatDrive(_device)) + { + emit success(); + } + else + { + emit error(tr("Error formatting (through udisks2)")); + } + + return; + } + + + QProcess proc; + QByteArray partitionTable; + QStringList args; + QByteArray fatpartition = _device; + partitionTable = "8192,,0E\n" + "0,0\n" + "0,0\n" + "0,0\n"; + args << "-uS" << _device; + if (isdigit(fatpartition.at(fatpartition.length()-1))) + fatpartition += "p1"; + else + fatpartition += "1"; + + unmount_disk(_device); + proc.setProcessChannelMode(proc.MergedChannels); + proc.start("sfdisk", args); + if (!proc.waitForStarted()) + { + emit error(tr("Error starting sfdisk")); + return; + } + proc.write(partitionTable); + proc.closeWriteChannel(); + proc.waitForFinished(); + QByteArray output = proc.readAll(); + qDebug() << "sfdisk:" << output; + + if (proc.exitCode()) + { + emit error(tr("Error partitioning: %1").arg(QString(output))); + return; + } + + proc.execute("partprobe"); + + args.clear(); + args << fatpartition; + proc.start("mkfs.fat", args); + if (!proc.waitForStarted()) + { + emit error(tr("Error starting mkfs.fat")); + return; + } + + proc.waitForFinished(); + output = proc.readAll(); + qDebug() << "mkfs.fat:" << output; + + if (proc.exitCode()) + { + emit error(tr("Error running mkfs.fat: %1").arg(QString(output))); + return; + } + + emit success(); + +#else + emit error(tr("Formatting not implemented for this platform")); +#endif +} diff --git a/driveformatthread.h b/driveformatthread.h new file mode 100644 index 0000000..7dd483b --- /dev/null +++ b/driveformatthread.h @@ -0,0 +1,27 @@ +#ifndef DRIVEFORMATTHREAD_H +#define DRIVEFORMATTHREAD_H + +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +#include + +class DriveFormatThread : public QThread +{ + Q_OBJECT +public: + DriveFormatThread(const QByteArray &device, QObject *parent = nullptr); + virtual ~DriveFormatThread(); + virtual void run(); + +signals: + void success(); + void error(QString msg); + +protected: + QByteArray _device; +}; + +#endif // DRIVEFORMATTHREAD_H diff --git a/drivelistitem.cpp b/drivelistitem.cpp new file mode 100644 index 0000000..5256d97 --- /dev/null +++ b/drivelistitem.cpp @@ -0,0 +1,17 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +#include "drivelistitem.h" + +DriveListItem::DriveListItem(QString device, QString description, quint64 size, bool isUsb, bool isScsi, QStringList mountpoints, QObject *parent) + : QObject(parent), _device(device), _description(description), _mountpoints(mountpoints), _size(size), _isUsb(isUsb), _isScsi(isScsi) +{ + +} + +int DriveListItem::sizeInGb() +{ + return _size / 1000000000; +} diff --git a/drivelistitem.h b/drivelistitem.h new file mode 100644 index 0000000..1dc6567 --- /dev/null +++ b/drivelistitem.h @@ -0,0 +1,39 @@ +#ifndef DRIVELISTITEM_H +#define DRIVELISTITEM_H + +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +#include +#include + +class DriveListItem : public QObject +{ + Q_OBJECT +public: + explicit DriveListItem(QString device, QString description, quint64 size, bool isUsb = false, bool isScsi = false, QStringList mountpoints = QStringList(), QObject *parent = nullptr); + + Q_PROPERTY(QString device MEMBER _device CONSTANT) + Q_PROPERTY(QString description MEMBER _description CONSTANT) + Q_PROPERTY(quint64 size MEMBER _size CONSTANT) + Q_PROPERTY(QStringList mountpoints MEMBER _mountpoints CONSTANT) + Q_PROPERTY(bool isUsb MEMBER _isUsb CONSTANT) + Q_PROPERTY(bool isScsi MEMBER _isScsi CONSTANT) + Q_INVOKABLE int sizeInGb(); + +signals: + +public slots: + +protected: + QString _device; + QString _description; + QStringList _mountpoints; + quint64 _size; + bool _isUsb; + bool _isScsi; +}; + +#endif // DRIVELISTITEM_H diff --git a/drivelistmodel.cpp b/drivelistmodel.cpp new file mode 100644 index 0000000..a87850a --- /dev/null +++ b/drivelistmodel.cpp @@ -0,0 +1,109 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +#include "drivelistmodel.h" +#include "config.h" +#include "dependencies/drivelist/src/drivelist.hpp" +#include +#include + +DriveListModel::DriveListModel(QObject *parent) + : QAbstractListModel(parent) +{ + _rolenames = { + {deviceRole, "device"}, + {descriptionRole, "description"}, + {sizeRole, "size"}, + {isUsbRole, "isUsb"}, + {isScsiRole, "isScsi"}, + {mountpointsRole, "mountpoints"} + }; +} + +int DriveListModel::rowCount(const QModelIndex &) const +{ + return _drivelist.count(); +} + +QHash DriveListModel::roleNames() const +{ + return _rolenames; +} + +QVariant DriveListModel::data(const QModelIndex &index, int role) const +{ + int row = index.row(); + if (row < 0 || row >= _drivelist.count()) + return QVariant(); + + QByteArray propertyName = _rolenames.value(role); + if (propertyName.isEmpty()) + return QVariant(); + else + return _drivelist.values().at(row)->property(propertyName); +} + +void DriveListModel::refreshDriveList() +{ + bool changes = false; + bool filterSystemDrives = DRIVELIST_FILTER_SYSTEM_DRIVES; + auto l = Drivelist::ListStorageDevices(); + QSet drivesInNewList; + + for (auto &i: l) + { + // Convert STL vector to Qt QStringList + QStringList mountpoints; + for (auto &s: i.mountpoints) + { + mountpoints.append(QString::fromStdString(s)); + } + + if (filterSystemDrives) + { + if (i.isSystem || i.isReadOnly) + continue; + + // Should already be caught by isSystem variable, but just in case... + if (mountpoints.contains("/") || mountpoints.contains("C://")) + continue; + } + + QString device = QString::fromStdString(i.device); + drivesInNewList.insert(device); + + if (!_drivelist.contains(device)) + { + // Found new drive + if (!changes) + { + beginResetModel(); + changes = true; + } + + _drivelist[device] = new DriveListItem(device, QString::fromStdString(i.description), i.size, i.isUSB, i.isSCSI, mountpoints, this); + } + } + + // Look for drives removed + QStringList drivesInOldList = _drivelist.keys(); + for (auto &device: drivesInOldList) + { + if (!drivesInNewList.contains(device)) + { + if (!changes) + { + beginResetModel(); + changes = true; + } + + _drivelist.value(device)->deleteLater(); + _drivelist.remove(device); + } + } + + if (changes) + endResetModel(); +} diff --git a/drivelistmodel.h b/drivelistmodel.h new file mode 100644 index 0000000..68266ca --- /dev/null +++ b/drivelistmodel.h @@ -0,0 +1,34 @@ +#ifndef DRIVELISTMODEL_H +#define DRIVELISTMODEL_H + +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +#include +#include +#include +#include "drivelistitem.h" + +class DriveListModel : public QAbstractListModel +{ +public: + DriveListModel(QObject *parent = nullptr); + virtual int rowCount(const QModelIndex &) const; + virtual QHash roleNames() const; + virtual QVariant data(const QModelIndex &index, int role) const; + + enum driveListRoles { + deviceRole = Qt::UserRole + 1, descriptionRole, sizeRole, isUsbRole, isScsiRole, mountpointsRole + }; + +public slots: + void refreshDriveList(); + +protected: + QMap _drivelist; + QHash _rolenames; +}; + +#endif // DRIVELISTMODEL_H diff --git a/fonts/Roboto-Bold.ttf b/fonts/Roboto-Bold.ttf new file mode 100644 index 0000000..68822ca Binary files /dev/null and b/fonts/Roboto-Bold.ttf differ diff --git a/fonts/Roboto-Light.ttf b/fonts/Roboto-Light.ttf new file mode 100644 index 0000000..aa45340 Binary files /dev/null and b/fonts/Roboto-Light.ttf differ diff --git a/fonts/Roboto-Regular.ttf b/fonts/Roboto-Regular.ttf new file mode 100644 index 0000000..0e58508 Binary files /dev/null and b/fonts/Roboto-Regular.ttf differ diff --git a/icons/Logo Stacked.png b/icons/Logo Stacked.png new file mode 100644 index 0000000..17fca8c Binary files /dev/null and b/icons/Logo Stacked.png differ diff --git a/icons/ic_build_40px.png b/icons/ic_build_40px.png new file mode 100644 index 0000000..4790c36 Binary files /dev/null and b/icons/ic_build_40px.png differ diff --git a/icons/ic_build_48px.svg b/icons/ic_build_48px.svg new file mode 100644 index 0000000..ac42b58 --- /dev/null +++ b/icons/ic_build_48px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/ic_chevron_left_40px.png b/icons/ic_chevron_left_40px.png new file mode 100644 index 0000000..4d3f16c Binary files /dev/null and b/icons/ic_chevron_left_40px.png differ diff --git a/icons/ic_chevron_left_48px.svg b/icons/ic_chevron_left_48px.svg new file mode 100644 index 0000000..4449fbd --- /dev/null +++ b/icons/ic_chevron_left_48px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/ic_chevron_right_40px.png b/icons/ic_chevron_right_40px.png new file mode 100644 index 0000000..2b8b449 Binary files /dev/null and b/icons/ic_chevron_right_40px.png differ diff --git a/icons/ic_chevron_right_48px.svg b/icons/ic_chevron_right_48px.svg new file mode 100644 index 0000000..ab7c4c5 --- /dev/null +++ b/icons/ic_chevron_right_48px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/ic_close_18px.png b/icons/ic_close_18px.png new file mode 100644 index 0000000..6825159 Binary files /dev/null and b/icons/ic_close_18px.png differ diff --git a/icons/ic_close_18px.svg b/icons/ic_close_18px.svg new file mode 100644 index 0000000..6170eec --- /dev/null +++ b/icons/ic_close_18px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/ic_computer_40px.png b/icons/ic_computer_40px.png new file mode 100644 index 0000000..5cf5172 Binary files /dev/null and b/icons/ic_computer_40px.png differ diff --git a/icons/ic_computer_48px.svg b/icons/ic_computer_48px.svg new file mode 100644 index 0000000..49ac0cb --- /dev/null +++ b/icons/ic_computer_48px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/ic_delete_40px.png b/icons/ic_delete_40px.png new file mode 100644 index 0000000..699a10e Binary files /dev/null and b/icons/ic_delete_40px.png differ diff --git a/icons/ic_delete_48px.svg b/icons/ic_delete_48px.svg new file mode 100644 index 0000000..3051156 --- /dev/null +++ b/icons/ic_delete_48px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/ic_sd_storage_40px.png b/icons/ic_sd_storage_40px.png new file mode 100644 index 0000000..c0bea0a Binary files /dev/null and b/icons/ic_sd_storage_40px.png differ diff --git a/icons/ic_sd_storage_48px.svg b/icons/ic_sd_storage_48px.svg new file mode 100644 index 0000000..17de23a --- /dev/null +++ b/icons/ic_sd_storage_48px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/ic_settings_48px.svg b/icons/ic_settings_48px.svg new file mode 100644 index 0000000..7a01c33 --- /dev/null +++ b/icons/ic_settings_48px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/ic_storage_40px.png b/icons/ic_storage_40px.png new file mode 100644 index 0000000..f5ce8d7 Binary files /dev/null and b/icons/ic_storage_40px.png differ diff --git a/icons/ic_storage_48px.svg b/icons/ic_storage_48px.svg new file mode 100644 index 0000000..c5f46be --- /dev/null +++ b/icons/ic_storage_48px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/ic_usb_40px.png b/icons/ic_usb_40px.png new file mode 100644 index 0000000..667e9fd Binary files /dev/null and b/icons/ic_usb_40px.png differ diff --git a/icons/ic_usb_48px.svg b/icons/ic_usb_48px.svg new file mode 100644 index 0000000..23479df --- /dev/null +++ b/icons/ic_usb_48px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/imagingutility-old.icns b/icons/imagingutility-old.icns new file mode 100644 index 0000000..9a4a922 Binary files /dev/null and b/icons/imagingutility-old.icns differ diff --git a/icons/imagingutility.icns b/icons/imagingutility.icns new file mode 100644 index 0000000..66ccc0b Binary files /dev/null and b/icons/imagingutility.icns differ diff --git a/icons/imagingutility.ico b/icons/imagingutility.ico new file mode 100644 index 0000000..fd2b93e Binary files /dev/null and b/icons/imagingutility.ico differ diff --git a/icons/imagingutility.png b/icons/imagingutility.png new file mode 100644 index 0000000..4146ac1 Binary files /dev/null and b/icons/imagingutility.png differ diff --git a/icons/rpi.png b/icons/rpi.png new file mode 100644 index 0000000..de06b9b Binary files /dev/null and b/icons/rpi.png differ diff --git a/icons/rpi2.png b/icons/rpi2.png new file mode 100644 index 0000000..1a9c130 Binary files /dev/null and b/icons/rpi2.png differ diff --git a/imagewriter.cpp b/imagewriter.cpp new file mode 100644 index 0000000..3ee6e85 --- /dev/null +++ b/imagewriter.cpp @@ -0,0 +1,438 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +#include "imagewriter.h" +#include "drivelistitem.h" +#include "downloadextractthread.h" +#include "dependencies/drivelist/src/drivelist.hpp" +#include "driveformatthread.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef Q_OS_WIN +#include +#include +#endif + +ImageWriter::ImageWriter(QObject *parent) + : QObject(parent), _repo(QUrl(QString(OSLIST_URL))), _dlnow(0), _verifynow(0), + _engine(nullptr), _thread(nullptr), _verifyEnabled(false), _cachingEnabled(false) +{ + connect(&_polltimer, SIGNAL(timeout()), SLOT(pollProgress())); + +#ifdef Q_OS_WIN + QProcess *p = new QProcess(this); + p->start("net stop ShellHWDetection"); +#endif + + if (!_settings.isWritable() && !_settings.fileName().isEmpty()) + { + /* Settings file is not writable, probably run by root previously */ + QString settingsFile = _settings.fileName(); + qDebug() << "Settings file" << settingsFile << "not writable. Recreating it"; + QFile f(_settings.fileName()); + QByteArray oldsettings; + + if (f.open(f.ReadOnly)) + { + oldsettings = f.readAll(); + f.close(); + } + f.remove(); + if (f.open(f.WriteOnly)) + { + f.write(oldsettings); + f.close(); + _settings.sync(); + } + else + { + qDebug() << "Error deleting and recreating settings file. Please remove manually."; + } + } + + _settings.beginGroup("caching"); + _cachingEnabled = _settings.value("enabled", IMAGEWRITER_ENABLE_CACHE_DEFAULT).toBool(); + _cachedFileHash = _settings.value("lastDownloadSHA256").toByteArray(); + _cacheFileName = QStandardPaths::writableLocation(QStandardPaths::CacheLocation)+QDir::separator()+"lastdownload.cache"; + if (!_cachedFileHash.isEmpty()) + { + QFileInfo f(_cacheFileName); + if (!f.exists() || !f.isReadable() || !f.size()) + { + _cachedFileHash.clear(); + _settings.remove("lastDownloadSHA256"); + _settings.sync(); + } + } + _settings.endGroup(); +} + +ImageWriter::~ImageWriter() +{ +#ifdef Q_OS_WIN + QProcess *p = new QProcess(this); + p->startDetached("net start ShellHWDetection"); +#endif +} + +void ImageWriter::setEngine(QQmlApplicationEngine *engine) +{ + _engine = engine; +} + +/* Set URL to download from */ +void ImageWriter::setSrc(const QUrl &url, quint64 downloadLen, quint64 extrLen, QByteArray expectedHash, bool multifilesinzip) +{ + _src = url; + _downloadLen = downloadLen; + _extrLen = extrLen; + _expectedHash = expectedHash; + _multipleFilesInZip = multifilesinzip; + + if (!_downloadLen && url.isLocalFile()) + { + QFileInfo fi(url.toLocalFile()); + _downloadLen = fi.size(); + } +} + +/* Set device to write to */ +void ImageWriter::setDst(const QString &device, quint64 deviceSize) +{ + _dst = device; + _devLen = deviceSize; +} + +/* Returns true if src and dst are set */ +bool ImageWriter::readyToWrite() +{ + return !_src.isEmpty() && !_dst.isEmpty(); +} + +/* Start writing */ +void ImageWriter::startWrite() +{ + if (!readyToWrite()) + return; + + if (_src.toString() == "internal://format") + { + DriveFormatThread *dft = new DriveFormatThread(_dst.toLatin1(), this); + connect(dft, SIGNAL(success()), SLOT(onSuccess())); + connect(dft, SIGNAL(error(QString)), SLOT(onError(QString))); + dft->start(); + return; + } + + QByteArray urlstr = _src.toString(_src.FullyEncoded).toLatin1(); + QString lowercaseurl = urlstr.toLower(); + bool compressed = lowercaseurl.endsWith(".zip") || lowercaseurl.endsWith(".xz") || lowercaseurl.endsWith(".bz2") || lowercaseurl.endsWith(".gz") || lowercaseurl.endsWith(".7z") || lowercaseurl.endsWith(".cache"); + if (!_extrLen && _src.isLocalFile()) + { + if (!compressed) + _extrLen = _downloadLen; + else if (lowercaseurl.endsWith(".zip")) + _parseCompressedFile(); + } + + if (_devLen && _extrLen > _devLen) + { + emit error(tr("Storage capacity is not large enough.\nNeeds to be at least %1 GB").arg(QString::number(_extrLen/1000000000.0, 'f', 1))); + return; + } + + if (_extrLen && !_multipleFilesInZip && _extrLen % 512 != 0) + { + emit error(tr("Input file is not a valid disk image.\nFile size %1 bytes is not a multiple of 512 bytes.").arg(_extrLen)); + return; + } + + if (!_expectedHash.isEmpty() && _cachedFileHash == _expectedHash) + { + // Use cached file + urlstr = QUrl::fromLocalFile(_cacheFileName).toString(_src.FullyEncoded).toLatin1(); + } + + if (compressed) + { + _thread = new DownloadExtractThread(urlstr, _dst.toLatin1(), _expectedHash, this); + } + else + { + _thread = new DownloadThread(urlstr, _dst.toLatin1(), _expectedHash, this); + } + + _powersave.applyBlock(tr("Downloading and writing image")); + + connect(_thread, SIGNAL(success()), SLOT(onSuccess())); + connect(_thread, SIGNAL(error(QString)), SLOT(onError(QString))); + _thread->setVerifyEnabled(_verifyEnabled); + + if (!_expectedHash.isEmpty() && _cachedFileHash != _expectedHash && _cachingEnabled) + { + if (!_cachedFileHash.isEmpty()) + { + if (_settings.isWritable() && QFile::remove(_cacheFileName)) + { + _settings.remove("caching/lastDownloadSHA256"); + _settings.sync(); + _cachedFileHash.clear(); + } + else + { + qDebug() << "Error removing old cache file. Disabling caching"; + _cachingEnabled = false; + } + } + + if (_cachingEnabled) + { + QStorageInfo si(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)); + qint64 avail = si.bytesAvailable(); + qDebug() << "Available disk space for caching:" << avail/1024/1024/1024 << "GB"; + + if (avail-_downloadLen < IMAGEWRITER_MINIMAL_SPACE_FOR_CACHING) + { + qDebug() << "Low disk space. Not caching files to disk."; + } + else + { + _thread->setCacheFile(_cacheFileName, _downloadLen); + connect(_thread, SIGNAL(cacheFileUpdated(QByteArray)), SLOT(onCacheFileUpdated(QByteArray))); + } + } + } + + if (_multipleFilesInZip) + { + static_cast(_thread)->enableMultipleFileExtraction(); + DriveFormatThread *dft = new DriveFormatThread(_dst.toLatin1(), this); + connect(dft, SIGNAL(success()), _thread, SLOT(start())); + connect(dft, SIGNAL(error(QString)), SLOT(onError(QString))); + dft->start(); + } + else + { + _thread->start(); + } + + _polltimer.start(PROGRESS_UPDATE_INTERVAL); +} + +void ImageWriter::onCacheFileUpdated(QByteArray sha256) +{ + _settings.setValue("caching/lastDownloadSHA256", sha256); + _settings.sync(); + _cachedFileHash = sha256; + qDebug() << "Done writing cache file"; +} + +/* Cancel write */ +void ImageWriter::cancelWrite() +{ + if (_thread) + { + connect(_thread, SIGNAL(finished()), SLOT(onCancelled())); + _thread->cancelDownload(); + } + + if (!_thread || !_thread->isRunning()) + { + emit cancelled(); + } +} + +void ImageWriter::onCancelled() +{ + sender()->deleteLater(); + if (sender() == _thread) + { + _thread = nullptr; + } + emit cancelled(); +} + +/* Return true if url is in our local disk cache */ +bool ImageWriter::isCached(const QUrl &, const QByteArray &sha256) +{ + return !sha256.isEmpty() && _cachedFileHash == sha256; +} + +/* Utility function to return filename part from URL */ +QString ImageWriter::fileNameFromUrl(const QUrl &url) +{ + //return QFileInfo(url.toLocalFile()).fileName(); + return url.fileName(); +} + +QString ImageWriter::srcFileName() +{ + return _src.isEmpty() ? "" : _src.fileName(); +} + +/* Function to return OS list URL */ +QUrl ImageWriter::constantOsListUrl() const +{ + return _repo; +} + +void ImageWriter::setCustomOsListUrl(const QUrl &url) +{ + _repo = url; +} + +/* Refresh the list of available drives */ +void ImageWriter::refreshDriveList() +{ + _drivelist.refreshDriveList(); +} + +DriveListModel *ImageWriter::getDriveList() +{ + return &_drivelist; +} + +void ImageWriter::pollProgress() +{ + if (!_thread) + return; + + quint64 newDlNow, dlTotal; + if (_extrLen) + { + newDlNow = _thread->bytesWritten(); + dlTotal = _extrLen; + } + else + { + newDlNow = _thread->dlNow(); + dlTotal = _thread->dlTotal(); + } + + if (newDlNow != _dlnow) + { + _dlnow = newDlNow; + emit downloadProgress(newDlNow, dlTotal); + } + + quint64 newVerifyNow = _thread->verifyNow(); + + if (newVerifyNow != _verifynow) + { + _verifynow = newVerifyNow; + quint64 verifyTotal = _thread->verifyTotal(); + emit verifyProgress(newVerifyNow, verifyTotal); + } +} + +void ImageWriter::setVerifyEnabled(bool verify) +{ + _verifyEnabled = verify; + if (_thread) + _thread->setVerifyEnabled(verify); +} + +/* Relay events from download thread to QML */ +void ImageWriter::onSuccess() +{ + _polltimer.stop(); + pollProgress(); + _powersave.removeBlock(); + emit success(); +} + +void ImageWriter::onError(QString msg) +{ + _polltimer.stop(); + pollProgress(); + _powersave.removeBlock(); + emit error(msg); +} + +void ImageWriter::onFinalizing() +{ + _polltimer.stop(); + emit finalizing(); +} + +void ImageWriter::openFileDialog() +{ + QFileDialog *fd = new QFileDialog(nullptr, tr("Select image"), + QStandardPaths::writableLocation(QStandardPaths::DownloadLocation), + "Image files (*.img *.zip *.gz *.xz);;All files (*.*)"); + connect(fd, SIGNAL(fileSelected(QString)), SLOT(onFileSelected(QString))); + + if (_engine) + { + fd->createWinId(); + QWindow *handle = fd->windowHandle(); + QWindow *qmlwindow = qobject_cast(_engine->rootObjects().value(0)); + if (qmlwindow) + { + handle->setTransientParent(qmlwindow); + } + } + + fd->show(); +} + +void ImageWriter::onFileSelected(QString filename) +{ + QFileInfo fi(filename); + + if (fi.isFile()) + { + emit fileSelected(QUrl::fromLocalFile(filename)); + } + else + { + qDebug() << "Item selected is not a regular file"; + } + + sender()->deleteLater(); +} + +void ImageWriter::_parseCompressedFile() +{ + struct archive *a = archive_read_new(); + struct archive_entry *entry; + QByteArray fn = _src.toLocalFile().toLatin1(); + int numFiles = 0; + _extrLen = 0; + + archive_read_support_filter_all(a); + archive_read_support_format_all(a); + + if (archive_read_open_filename(a, fn.data(), 10240) == ARCHIVE_OK) + { + while ( (archive_read_next_header(a, &entry)) == ARCHIVE_OK) + { + if (archive_entry_size(entry) > 0) + { + _extrLen += archive_entry_size(entry); + numFiles++; + } + } + } + + if (numFiles > 1) + _multipleFilesInZip = true; + + qDebug() << "Parsed .zip file containing" << numFiles << "files, uncompressed size:" << _extrLen; +} + +void MountUtilsLog(std::string msg) { + qDebug() << "mountutils:" << msg.c_str(); +} diff --git a/imagewriter.h b/imagewriter.h new file mode 100644 index 0000000..90f8a27 --- /dev/null +++ b/imagewriter.h @@ -0,0 +1,108 @@ +#ifndef IMAGEWRITER_H +#define IMAGEWRITER_H + +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +#include +#include +#include +#include +#include +#include "config.h" +#include "powersaveblocker.h" +#include "drivelistmodel.h" + +class QQmlApplicationEngine; +class DownloadThread; + +class ImageWriter : public QObject +{ + Q_OBJECT +public: + explicit ImageWriter(QObject *parent = nullptr); + virtual ~ImageWriter(); + void setEngine(QQmlApplicationEngine *engine); + + /* Set URL to download from, and if known download length and uncompressed length */ + Q_INVOKABLE void setSrc(const QUrl &url, quint64 downloadLen = 0, quint64 extrLen = 0, QByteArray expectedHash = "", bool multifilesinzip = false); + + /* Set device to write to */ + Q_INVOKABLE void setDst(const QString &device, quint64 deviceSize = 0); + + /* Enable/disable verification */ + Q_INVOKABLE void setVerifyEnabled(bool verify); + + /* Returns true if src and dst are set */ + Q_INVOKABLE bool readyToWrite(); + + /* Start writing */ + Q_INVOKABLE void startWrite(); + + /* Cancel write */ + Q_INVOKABLE void cancelWrite(); + + /* Return true if url is in our local disk cache */ + Q_INVOKABLE bool isCached(const QUrl &url, const QByteArray &sha256); + + /* Refresh the list of available drives */ + Q_INVOKABLE void refreshDriveList(); + + /* Return list of available drives. Call refreshDriveList() first */ + DriveListModel *getDriveList(); + + /* Utility function to return filename part from URL */ + Q_INVOKABLE QString fileNameFromUrl(const QUrl &url); + + /* Function to return OS list URL */ + Q_INVOKABLE QUrl constantOsListUrl() const; + + /* Set custom repository */ + Q_INVOKABLE void setCustomOsListUrl(const QUrl &url); + + /* Utility function to open OS file dialog */ + Q_INVOKABLE void openFileDialog(); + + /* Return filename part of URL set */ + Q_INVOKABLE QString srcFileName(); + +signals: + /* We are emiting signals with QVariant as parameters because QML likes it that way */ + + void downloadProgress(QVariant dlnow, QVariant dltotal); + void verifyProgress(QVariant now, QVariant total); + void error(QVariant msg); + void success(); + void fileSelected(QVariant filename); + void cancelled(); + void finalizing(); + +protected slots: + + void pollProgress(); + void onSuccess(); + void onError(QString msg); + void onFileSelected(QString filename); + void onCancelled(); + void onCacheFileUpdated(QByteArray sha256); + void onFinalizing(); + +protected: + QUrl _src, _repo; + QString _dst, _cacheFileName; + QByteArray _expectedHash, _cachedFileHash; + quint64 _downloadLen, _extrLen, _devLen, _dlnow, _verifynow; + DriveListModel _drivelist; + QQmlApplicationEngine *_engine; + QTimer _polltimer; + PowerSaveBlocker _powersave; + DownloadThread *_thread; + bool _verifyEnabled, _multipleFilesInZip, _cachingEnabled; + QSettings _settings; + + void _parseCompressedFile(); +}; + +#endif // IMAGEWRITER_H diff --git a/license.txt b/license.txt new file mode 100644 index 0000000..b3e53bc --- /dev/null +++ b/license.txt @@ -0,0 +1,1742 @@ +== +Raspberry Pi Imaging Utility main code license terms +== + +Copyright (C) 2020 Raspberry Pi (Trading) Limited + +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. + + +== +Third-party components license summary +== + +This software depends on the following third-party components covered by open source licenses: + +- Qt (LGPL license) +- GNU C library (LGPL license) +- MinGW library (MIT license) +- Balena.io drivelist (Apache license) +- Balena.io mountutils (Apache license) +- libarchive (new BSD license) +- liblzma (public domain) +- zlib (zlib license) +- libcurl (libcurl license) +- fat32format.exe (GPL license) + +fat32format is only used on the Windows platform +(to get around 32 GB limit of the official Windows format command) + + +== +Qt license +== + + GNU LESSER GENERAL PUBLIC LICENSE + + The Qt Toolkit is Copyright (C) 2016 The Qt Company Ltd. + Contact: http://www.qt.io/licensing/ + + You may use, distribute and copy the Qt Toolkit under the terms of + GNU Lesser General Public License version 3, which is displayed below. + This license makes reference to the version 3 of the GNU General + Public License, which you can find in the LICENSE.GPL3 file. + +------------------------------------------------------------------------- + + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright © 2007 Free Software Foundation, Inc. +Everyone is permitted to copy and distribute verbatim copies of this +licensedocument, but changing it is not allowed. + +This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + +0. Additional Definitions. + + As used herein, “this License†refers to version 3 of the GNU Lesser +General Public License, and the “GNU GPL†refers to version 3 of the +GNU General Public License. + + “The Library†refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An “Application†is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A “Combined Work†is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the “Linked +Versionâ€. + + The “Minimal Corresponding Source†for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The “Corresponding Application Code†for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + +1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + +2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort + to ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + +3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this + license document. + +4. Combined Works. + + You may convey a Combined Work under terms of your choice that, taken +together, effectively do not restrict modification of the portions of +the Library contained in the Combined Work and reverse engineering for +debugging such modifications, if you also do each of the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this + license document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of + this License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with + the Library. A suitable mechanism is one that (a) uses at run + time a copy of the Library already present on the user's + computer system, and (b) will operate properly with a modified + version of the Library that is interface-compatible with the + Linked Version. + + e) Provide Installation Information, but only if you would + otherwise be required to provide such information under section 6 + of the GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the Application + with a modified version of the Linked Version. (If you use option + 4d0, the Installation Information must accompany the Minimal + Corresponding Source and Corresponding Application Code. If you + use option 4d1, you must provide the Installation Information in + the manner specified by section 6 of the GNU GPL for conveying + Corresponding Source.) + +5. Combined Libraries. + + You may place library facilities that are a work based on the Library +side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities, conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of + it is a work based on the Library, and explaining where to find + the accompanying uncombined form of the same work. + +6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +as you received it specifies that a certain numbered version of the +GNU Lesser General Public License “or any later version†applies to +it, you have the option of following the terms and conditions either +of that published version or of any later version published by the +Free Software Foundation. If the Library as you received it does not +specify a version number of the GNU Lesser General Public License, +you may choose any version of the GNU Lesser General Public License +ever published by the Free Software Foundation. + +If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the Library. + +== +Mingw license (used by Windows builds only) +== + +Copyright (c) 2012 MinGW.org project + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice, this permission notice and the below disclaimer +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + + +== +GNU C library +== + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + +== +Apache license +== + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + + +== +libarchive license +== + +The libarchive distribution as a whole is Copyright by Tim Kientzle +and is subject to the copyright notice reproduced at the bottom of +this file. + +Each individual file in this distribution should have a clear +copyright/licensing statement at the beginning of the file. If any do +not, please let me know and I will rectify it. The following is +intended to summarize the copyright status of the individual files; +the actual statements in the files are controlling. + +* Except as listed below, all C sources (including .c and .h files) + and documentation files are subject to the copyright notice reproduced + at the bottom of this file. + +* The following source files are also subject in whole or in part to + a 3-clause UC Regents copyright; please read the individual source + files for details: + libarchive/archive_entry.c + libarchive/archive_read_support_filter_compress.c + libarchive/archive_write_add_filter_compress.c + libarchive/mtree.5 + +* The following source files are in the public domain: + libarchive/archive_getdate.c + +* The following source files are triple-licensed with the ability to choose + from CC0 1.0 Universal, OpenSSL or Apache 2.0 licenses: + libarchive/archive_blake2.h + libarchive/archive_blake2_impl.h + libarchive/archive_blake2s_ref.c + libarchive/archive_blake2sp_ref.c + +* The build files---including Makefiles, configure scripts, + and auxiliary scripts used as part of the compile process---have + widely varying licensing terms. Please check individual files before + distributing them to see if those restrictions apply to you. + +I intend for all new source code to use the license below and hope over +time to replace code with other licenses with new implementations that +do use the license below. The varying licensing of the build scripts +seems to be an unavoidable mess. + + +Copyright (c) 2003-2018 +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer + in this position and unchanged. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +== +liblzma license +== + +- liblzma is in the public domain. + +== +zlib license +== + + Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + +== +libcurl license +== + +COPYRIGHT AND PERMISSION NOTICE + +Copyright (c) 1996 - 2019, Daniel Stenberg, , and many +contributors, see the THANKS file. + +All rights reserved. + +Permission to use, copy, modify, and distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright +notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall not +be used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization of the copyright holder. + + +== +fat32format.exe (used by Windows builds only) +== + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. + +== diff --git a/linux/imagingutility.desktop b/linux/imagingutility.desktop new file mode 100644 index 0000000..de9ec70 --- /dev/null +++ b/linux/imagingutility.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Type=Application +Version=1.0 +Name=Imager +Comment=Raspberry Pi Imager +Icon=imagingutility +Exec=imagingutility +Categories=Utility +StartupNotify=false diff --git a/linux/linuxdrivelist.cpp b/linux/linuxdrivelist.cpp new file mode 100644 index 0000000..5ac5be9 --- /dev/null +++ b/linux/linuxdrivelist.cpp @@ -0,0 +1,127 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +#include "../dependencies/drivelist/src/drivelist.hpp" +#include +#include +#include +#include +#include + +/* + * Our third-party drivelist module does not provide a C++ implementation + * for listing drives on Linux (only Javascript) + * So roll our own for Linux using same function/data structure as the drivelist one + */ + +namespace Drivelist +{ + static void _walkStorageChildren(Drivelist::DeviceDescriptor &d, QStringList &labels, QJsonArray &ca) + { + for (auto j : ca) + { + QJsonObject child = j.toObject(); + QString label = child["label"].toString(); + QString mp = child["mountpoint"].toString(); + if (!label.isEmpty()) + { + labels.append(label); + } + if (!mp.isEmpty()) + { + d.mountpoints.push_back(mp.toStdString()); + d.mountpointLabels.push_back(label.toStdString()); + } + + QJsonArray subca = child["children"].toArray(); + if (subca.count()) + { + _walkStorageChildren(d, labels, subca); + } + } + } + + std::vector ListStorageDevices() + { + std::vector deviceList; + + QProcess p; + p.start("lsblk --bytes --json --paths --output-all"); + p.waitForFinished(2000); + QByteArray output = p.readAll(); + + if (p.exitStatus() != QProcess::NormalExit || p.exitCode() || output.isEmpty()) + { + qDebug() << "Error executing lsblk"; + return deviceList; + } + + QJsonDocument d = QJsonDocument::fromJson(output); + QJsonArray a = d.object()["blockdevices"].toArray(); + for (auto i : a) + { + DeviceDescriptor d; + QJsonObject bdev = i.toObject(); + QString name = bdev["kname"].toString(); + QString subsystems = bdev["subsystems"].toString(); + if (name.startsWith("/dev/loop") || name.startsWith("/dev/sr") || name.startsWith("/dev/ram") || name.isEmpty()) + continue; + + d.busType = bdev["busType"].toString().toStdString(); + d.device = name.toStdString(); + d.raw = true; + d.isVirtual = subsystems == "block"; + if (bdev["ro"].isBool()) + { + /* With some lsblk versions it is a bool in others a "0" or "1" string */ + d.isReadOnly = bdev["ro"].toBool(); + d.isRemovable= bdev["rm"].toBool() || bdev["hotplug"].toBool() || d.isVirtual; + } + else + { + d.isReadOnly = bdev["ro"].toString() == "1"; + d.isRemovable= bdev["rm"].toString() == "1" || bdev["hotplug"].toString() == "1" || d.isVirtual; + } + if (bdev["size"].isString()) + { + d.size = bdev["size"].toString().toULongLong(); + } + else + { + d.size = bdev["size"].toDouble(); + } + d.isSystem = !d.isRemovable && !d.isVirtual; + d.isUSB = subsystems.contains("usb"); + d.isSCSI = subsystems.contains("scsi") && !d.isUSB; + d.blockSize = bdev["phy-sec"].toInt(); + d.logicalBlockSize = bdev["log-sec"].toInt(); + + QStringList dp = { + bdev["label"].toString().trimmed(), + bdev["vendor"].toString().trimmed(), + bdev["model"].toString().trimmed() + }; + + QString mp = bdev["mountpoint"].toString(); + if (!mp.isEmpty()) + { + d.mountpoints.push_back(mp.toStdString()); + d.mountpointLabels.push_back(bdev["label"].toString().toStdString()); + } + QStringList labels; + QJsonArray ca = bdev["children"].toArray(); + _walkStorageChildren(d, labels, ca); + + if (labels.count()) { + dp.append("("+labels.join(", ")+")"); + } + dp.removeAll(""); + d.description = dp.join(" ").toStdString(); + deviceList.push_back(d); + } + + return deviceList; + } +} diff --git a/linux/udisks2api.cpp b/linux/udisks2api.cpp new file mode 100644 index 0000000..97f25a6 --- /dev/null +++ b/linux/udisks2api.cpp @@ -0,0 +1,172 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +#include "udisks2api.h" +#include +#include +#include +#include +#include +#include +#include + +UDisks2Api::UDisks2Api(QObject *parent) + : QObject(parent) +{ +} + +int UDisks2Api::authOpen(const QString &device, const QString &mode) +{ + QString devpath = _resolveDevice(device); + if (devpath.isEmpty()) + return -1; + + QDBusInterface blockdevice("org.freedesktop.UDisks2", devpath, + "org.freedesktop.UDisks2.Block", QDBusConnection::systemBus()); + QString drive = blockdevice.property("Drive").value().path(); + if (!drive.isEmpty() && drive != "/") + { + _unmountDrive(drive); + } + + // User may need to enter password in authentication dialog so set long timeout + blockdevice.setTimeout(3600 * 1000); + QVariantMap options = {{"flags", O_EXCL}}; + QDBusReply dbusfd = blockdevice.call("OpenDevice", mode, options); + + if (!blockdevice.isValid() || !dbusfd.isValid() || !dbusfd.value().isValid()) + return -1; + + int fd = ::dup(dbusfd.value().fileDescriptor()); + + return fd; +} + +QString UDisks2Api::_resolveDevice(const QString &device) +{ + QDBusInterface manager("org.freedesktop.UDisks2", "/org/freedesktop/UDisks2/Manager", + "org.freedesktop.UDisks2.Manager", QDBusConnection::systemBus()); + QVariantMap devspec = {{"path", device}}; + QVariantMap options; + + QDBusReply> list = manager.call("ResolveDevice", devspec, options); + + if (!manager.isValid() || !list.isValid() || list.value().isEmpty()) + return QString(); + + return list.value().first().path(); +} + +void UDisks2Api::_unmountDrive(const QString &driveDbusPath) +{ + qDebug() << "Drive:" << driveDbusPath; + + QDBusInterface manager("org.freedesktop.UDisks2", "/org/freedesktop/UDisks2/Manager", + "org.freedesktop.UDisks2.Manager", QDBusConnection::systemBus()); + QVariantMap options; + QDBusReply> list = manager.call("GetBlockDevices", options); + + if (!manager.isValid() || !list.isValid()) + return; + + for (auto devpath : list.value()) + { + QString devpathStr = devpath.path(); + + QDBusInterface blockdevice("org.freedesktop.UDisks2", devpathStr, + "org.freedesktop.UDisks2.Block", QDBusConnection::systemBus()); + QString driveOfDev = blockdevice.property("Drive").value().path(); + if (driveOfDev != driveDbusPath) + continue; + + qDebug() << "Device:" << devpathStr << "belongs to same drive"; + QDBusInterface filesystem("org.freedesktop.UDisks2", devpathStr, + "org.freedesktop.UDisks2.Filesystem", QDBusConnection::systemBus()); + + QDBusReply reply = filesystem.call("Unmount", options); + if (reply.isValid()) + qDebug() << "Unmounted" << devpathStr << "successfully"; + } +} + +bool UDisks2Api::formatDrive(const QString &device, bool mountAfterwards) +{ + QString devpath = _resolveDevice(device); + if (devpath.isEmpty()) + return false; + + QDBusInterface blockdevice("org.freedesktop.UDisks2", devpath, + "org.freedesktop.UDisks2.Block", QDBusConnection::systemBus()); + + QString drive = blockdevice.property("Drive").value().path(); + if (!drive.isEmpty() && drive != "/") + { + _unmountDrive(drive); + } + + qDebug() << "Repartitioning drive"; + QVariantMap options; + QDBusReply reply = blockdevice.call("Format", "dos", options); + if (!reply.isValid()) + { + qDebug() << "Error repartitioning device:" << reply.error().message(); + return false; + } + + QVariantMap partOptions, formatOptions; + QDBusInterface partitiontable("org.freedesktop.UDisks2", devpath, + "org.freedesktop.UDisks2.PartitionTable", QDBusConnection::systemBus()); + + /* The all-in-one CreatePartitionAndFormat udisks2 method seems to not always + work properly. Do seperate actions with sleep in between instead */ + qDebug() << "Adding partition"; + QDBusReply newpartition = partitiontable.call("CreatePartition", QVariant((qulonglong) 4*1024*1024), QVariant((qulonglong) 0), "0x0e", "", partOptions); + if (!newpartition.isValid()) + { + qDebug() << "Error adding partition:" << newpartition.error().message(); + return false; + } + qDebug() << "New partition:" << newpartition.value().path(); + QThread::sleep(1); + qDebug() << "Formatting drive as FAT32"; + QDBusInterface newblockdevice("org.freedesktop.UDisks2", newpartition.value().path(), + "org.freedesktop.UDisks2.Block", QDBusConnection::systemBus()); + newblockdevice.setTimeout(120 * 1000); + QDBusReply fatformatreply = newblockdevice.call("Format", "vfat", formatOptions); + if (!fatformatreply.isValid()) + { + qDebug() << "Error from udisks2 while performing FAT32 format:" << fatformatreply.error().message() + << "(going to try to mount anyway, as errors are sometimes false positive)"; + /* udisks2 sometimes report + "Error synchronizing after formatting with type `vfat': Timed out waiting for object" + when there is nothing actually wrong with the format */ + } + + if (mountAfterwards) + { + QDBusInterface filesystem("org.freedesktop.UDisks2", newpartition.value().path(), + "org.freedesktop.UDisks2.Filesystem", QDBusConnection::systemBus()); + QVariantMap mountOptions; + + for (int attempt = 0; attempt < 10; attempt++) + { + qDebug() << "Mounting partition"; + QDBusReply mp = filesystem.call("Mount", mountOptions); + + if (mp.isValid()) + { + qDebug() << "Mounted new file system at:" << mp; + return true; + } + + QThread::sleep(1); + } + + qDebug() << "Failed to mount new file system."; + return false; + } + + return true; +} diff --git a/linux/udisks2api.h b/linux/udisks2api.h new file mode 100644 index 0000000..8fe1dde --- /dev/null +++ b/linux/udisks2api.h @@ -0,0 +1,29 @@ +#ifndef UDISKS2API_H +#define UDISKS2API_H + +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +#include +#include + +class UDisks2Api : public QObject +{ + Q_OBJECT +public: + explicit UDisks2Api(QObject *parent = nullptr); + int authOpen(const QString &device, const QString &mode = "rw"); + bool formatDrive(const QString &device, bool mountAfterwards = true); + +protected: + QString _resolveDevice(const QString &device); + void _unmountDrive(const QString &driveDbusPath); + +signals: + +public slots: +}; + +#endif // UDISKS2API_H diff --git a/mac/macfile.cpp b/mac/macfile.cpp new file mode 100644 index 0000000..7f890b9 --- /dev/null +++ b/mac/macfile.cpp @@ -0,0 +1,126 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +#include "macfile.h" +#include +#include +#include +#include +#include + +MacFile::MacFile(QObject *parent) + : QFile(parent) +{ + +} + +/* Prevent that Qt thinks /dev/rdisk does not permit seeks because it does not report size */ +bool MacFile::isSequential() const +{ + return false; +} + +bool MacFile::authOpen(const QByteArray &filename) +{ + int fd = -1; + + QByteArray right = "sys.openfile.readwrite."+filename; + AuthorizationItem item = {right, 0, nullptr, 0}; + AuthorizationRights rights = {1, &item}; + AuthorizationFlags flags = kAuthorizationFlagInteractionAllowed | + kAuthorizationFlagExtendRights | + kAuthorizationFlagPreAuthorize; + AuthorizationRef authRef; + if (AuthorizationCreate(&rights, nullptr, flags, &authRef) != 0) + return false; + + AuthorizationExternalForm externalForm; + if (AuthorizationMakeExternalForm(authRef, &externalForm) != 0) + { + AuthorizationFree(authRef, 0); + return false; + } + + const char *cmd = "/usr/libexec/authopen"; + QByteArray mode = QByteArray::number(O_RDWR); + int pipe[2]; + int stdinpipe[2]; + ::socketpair(AF_UNIX, SOCK_STREAM, 0, pipe); + ::pipe(stdinpipe); + pid_t pid = ::fork(); + if (pid == 0) + { + // child + ::close(pipe[0]); + ::close(stdinpipe[1]); + ::dup2(pipe[1], STDOUT_FILENO); + ::dup2(stdinpipe[0], STDIN_FILENO); + ::execl(cmd, cmd, "-stdoutpipe", "-extauth", "-o", mode.data(), filename.data(), NULL); + ::exit(-1); + } + else + { + ::close(pipe[1]); + ::close(stdinpipe[0]); + ::write(stdinpipe[1], externalForm.bytes, sizeof(externalForm.bytes)); + ::close(stdinpipe[1]); + + const size_t bufSize = CMSG_SPACE(sizeof(int)); + char buf[bufSize]; + struct iovec io_vec[1]; + io_vec[0].iov_base = buf; + io_vec[0].iov_len = bufSize; + const size_t cmsgSize = CMSG_SPACE(sizeof(int)); + char cmsg[cmsgSize]; + + struct msghdr msg = {0}; + msg.msg_iov = io_vec; + msg.msg_iovlen = 1; + msg.msg_control = cmsg; + msg.msg_controllen = cmsgSize; + + ssize_t size; + do { + size = recvmsg(pipe[0], &msg, 0); + } while (size == -1 && errno == EINTR); + + qDebug() << "RECEIVED SIZE:" << size; + + if (size > 0) { + struct cmsghdr *chdr = CMSG_FIRSTHDR(&msg); + if (chdr && chdr->cmsg_type == SCM_RIGHTS) { + qDebug() << "SCMRIGHTS"; + fd = *( (int*) (CMSG_DATA(chdr)) ); + } + else + { + qDebug() << "NOT SCMRIGHTS"; + } + } + + pid_t wpid; + int status; + + do { + wpid = ::waitpid(pid, &status, 0); + } while (wpid == -1 && errno == EINTR); + + if (wpid == -1) + { + qDebug() << "waitpid() failed executing authopen"; + return false; + } + if (WEXITSTATUS(status)) + { + qDebug() << "authopen returned failure code" << WEXITSTATUS(status); + return false; + } + + qDebug() << "fd received:" << fd; + } + AuthorizationFree(authRef, 0); + + return open(fd, QIODevice::ReadWrite | QIODevice::ExistingOnly | QIODevice::Unbuffered, QFileDevice::AutoCloseHandle); +} diff --git a/mac/macfile.h b/mac/macfile.h new file mode 100644 index 0000000..6bc842a --- /dev/null +++ b/mac/macfile.h @@ -0,0 +1,20 @@ +#ifndef MACFILE_H +#define MACFILE_H + +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +#include + +class MacFile : public QFile +{ + Q_OBJECT +public: + MacFile(QObject *parent = nullptr); + virtual bool isSequential() const; + bool authOpen(const QByteArray &filename); +}; + +#endif // MACFILE_H diff --git a/main-orig.qml b/main-orig.qml new file mode 100644 index 0000000..e138702 --- /dev/null +++ b/main-orig.qml @@ -0,0 +1,726 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +import QtQuick 2.9 +import QtQuick.Window 2.2 +import QtQuick.Controls 2.2 +import QtQuick.Layouts 1.0 +import QtQuick.Controls.Material 2.2 +import Qt.labs.settings 1.0 + +ApplicationWindow { + id: window + visible: true + width: 680 + height: 420 + /*minimumWidth: width + maximumWidth: width + minimumHeight: height + maximumHeight: height + minimumHeight: gridLayout.height+100*/ + minimumWidth: 680 + maximumWidth: 680 + minimumHeight: 420 + maximumHeight: 420 + + title: qsTr("Raspberry Pi Imaging Utility") + + GridLayout { + id: gridLayout + rowSpacing: 25 + anchors.top: parent.top + anchors.topMargin: 50 + anchors.right: parent.right + anchors.rightMargin: 50 + anchors.left: parent.left + anchors.leftMargin: 50 + rows: 4 + columns: 3 + + Image { + id: image + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + Layout.columnSpan: 3 + Layout.preferredHeight: 92 + Layout.preferredWidth: 330 + fillMode: Image.PreserveAspectFit + source: "icons/rpi.png" + } + + ColumnLayout { + id: columnLayout + spacing: 0 + Layout.fillWidth: true + + Text { + id: text1 + color: "#696969" + text: qsTr("Operating System") + Layout.fillWidth: true + Layout.preferredHeight: 17 + Layout.preferredWidth: 132 + font.pixelSize: 12 + } + + Button { + id: osbutton + text: imageWriter.srcFileName() === "" ? qsTr("CHOOSE OS") : imageWriter.srcFileName() + spacing: 0 + padding: 0 + bottomPadding: 0 + topPadding: 0 + Layout.minimumHeight: 40 + Layout.fillWidth: true + Layout.minimumWidth: 0 + onClicked: { + ospopup.open() + // force property bindings to refresh + window.setHeight(window.height) + } + Material.background: "#ffffff" + Material.foreground: "#c51a4a" + } + } + + Item { + id: spacer1 + Layout.preferredHeight: 10 + Layout.preferredWidth: 25 + } + + ColumnLayout { + id: columnLayout2 + spacing: 0 + Layout.fillWidth: true + + Text { + id: text2 + color: "#696969" + text: qsTr("SD Card") + Layout.fillWidth: true + Layout.preferredHeight: 17 + Layout.preferredWidth: 127 + font.pixelSize: 12 + } + + Button { + id: dstbutton + text: qsTr("CHOOSE SD") + Layout.minimumHeight: 40 + Layout.fillWidth: true + onClicked: { + imageWriter.refreshDriveList() + drivePollTimer.start() + dstpopup.open() + } + Material.background: "#ffffff" + Material.foreground: "#c51a4a" + } + } + + + Switch { + Layout.columnSpan: 3 + Layout.alignment: Qt.AlignHCenter + Layout.maximumHeight: 25 + + id: verifySwitch + text: qsTr("Verify written data") + checked: true + onCheckedChanged: { + imageWriter.setVerifyEnabled(verifySwitch.checked) + } + } + + ColumnLayout { + id: columnLayout3 + Layout.columnSpan: 3 + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + + Button { + id: writebutton + text: qsTr("WRITE") + font.pointSize: 11 + Layout.minimumWidth: 100 + Layout.minimumHeight: 50 + topPadding: 12 + enabled: false + Material.foreground: "#ffffff" + Material.background: "#c51a4a" + onClicked: { + if (!imageWriter.readyToWrite()) + return; + visible = false + cancelbutton.enabled = true + cancelbutton.visible = true + progressText.visible = true + progressBar.visible = true + progressBar.indeterminate = true + progressBar.Material.accent = Material.Pink + osbutton.enabled = false + dstbutton.enabled = false + imageWriter.setVerifyEnabled(verifySwitch.checked) + imageWriter.startWrite() + } + } + + Text { + id: progressText + font.pointSize: 10 + color: "grey" + text: qsTr("Writing... %1%").arg("0") + visible: false + } + + ProgressBar { + id: progressBar + Layout.fillWidth: true + visible: false + } + + Button { + id: cancelbutton + text: qsTr("CANCEL") + onClicked: { + enabled = false + imageWriter.cancelWrite() + } + Material.background: "#ffffff" + Material.foreground: "#c51a4a" + Layout.alignment: Qt.AlignRight + visible: false + } + } + } + + /* + Popup for OS selection + */ + Popup { + id: ospopup + x: 50 + y: 25 + width: parent.width-100 + height: parent.height-50 + padding: 25 + focus: true + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside + + ColumnLayout { + spacing: 10 + + Text { + text: qsTr("Operating System") + font.pointSize: 14 + } + Rectangle { + id: hr + implicitWidth: parent.width //540 + implicitHeight: 1 + color: "#1E000000" + } + + Item { + clip: true + width: oslist.width + height: oslist.height + + SwipeView { + id: osswipeview + interactive: false + + ListView { + id: oslist + model: osmodel + delegate: osdelegate + width: window.width-140 //540 + height: window.height-170 //250 + focus: true + boundsBehavior: Flickable.StopAtBounds + ScrollBar.vertical: ScrollBar { + width: 10 + policy: ScrollBar.AlwaysOn + } + } + + ListView { + id: suboslist + model: subosmodel + delegate: osdelegate + width: window.width-140 //540 + height: window.height-170 //250 + boundsBehavior: Flickable.StopAtBounds + ScrollBar.vertical: ScrollBar { + width: 10 + policy: ScrollBar.AlwaysOn + } + } + } + } + } + } + + ListModel { + id: osmodel + + ListElement { + url: "internal://format" + icon: "icons/ic_delete_48px.svg" + extract_size: 0 + image_download_size: 0 + extract_sha256: "" + contains_multiple_files: false + release_date: "" + subitems_url: "" + subitems: [] + name: qsTr("Erase") + description: qsTr("Format card as FAT32") + } + + ListElement { + url: "" + icon: "icons/ic_computer_48px.svg" + name: qsTr("Use custom") + description: qsTr("Select a custom .img from your computer") + } + + Component.onCompleted: { + httpRequest(imageWriter.constantOsListUrl(), function (x) { + var o = JSON.parse(x.responseText) + if (!"os_list" in o) { + onError(qsTr("Error parsing os_list.json")) + return; + } + var oslist = o["os_list"] + for (var i in oslist) { + osmodel.insert(osmodel.count-2, oslist[i]) + } + }) + } + } + + ListModel { + id: subosmodel + + ListElement { + url: "" + icon: "icons/ic_chevron_left_48px.svg" + extract_size: 0 + image_download_size: 0 + extract_sha256: "" + contains_multiple_files: false + release_date: "" + subitems_url: "internal://back" + subitems: [] + name: qsTr("Back") + description: qsTr("Go back to main menu") + } + } + + Component { + id: osdelegate + + Item { + width: window.width-140 //540 + height: image_download_size ? 100 : 60 + + Rectangle { + id: bgrect + anchors.fill: parent + color: "#f5f5f5" + visible: false + } + + Row { + Column { + width: 64 + + Image { + source: icon + verticalAlignment: Image.AlignVCenter + height: parent.parent.parent.height + fillMode: Image.Pad + } + Text { + text: " " + visible: !icon + } + } + Column { + width: parent.parent.width-64-50 + //height: parent.parent.height + + Text { + verticalAlignment: Text.AlignVCenter + height: parent.parent.parent.height + textFormat: Text.StyledText + text: { + var txt = ""+name+"
    " + txt += ""+description + if (typeof(release_date) == "string" && release_date) + txt += "
    "+qsTr("Released: %1").arg(release_date) + if (typeof(url) == "string" && url != "" && url != "internal://format") { + if (typeof(extract_sha256) != "undefined" && imageWriter.isCached(url,extract_sha256)) { + txt += "
    "+qsTr("Cached on your computer") + } else { + txt += "
    "+qsTr("Online - %1 GB download").arg((image_download_size/1073741824).toFixed(1)); + } + } + txt += "
    "; + + return txt; + } + } + + } + Column { + Image { + source: "icons/ic_chevron_right_48px.svg" + visible: (typeof(subitems) == "object" && subitems.count) || (typeof(subitems_url) == "string" && subitems_url != "" && subitems_url != "internal://back") + height: parent.parent.parent.height + fillMode: Image.Pad + } + } + } + + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + hoverEnabled: true + + onEntered: { + bgrect.visible = true + } + + onExited: { + bgrect.visible = false + } + + onClicked: { + if (typeof(subitems) == "object" && subitems.count) { + if (subosmodel.count>1) + { + subosmodel.remove(1, subosmodel.count-1) + } + for (var i=0; i1) + { + subosmodel.remove(1, subosmodel.count-1) + } + + httpRequest(subitems_url, function (x) { + var o = JSON.parse(x.responseText) + if (!"os_list" in o) { + onError(qsTr("Error parsing os_list.json")) + return; + } + var oslist = o["os_list"] + for (var i in oslist) { + subosmodel.append(oslist[i]) + } + }) + osswipeview.setCurrentIndex(1) + } + } else if (url == "") { + //fileDialog.open() + imageWriter.openFileDialog() + } else { + imageWriter.setSrc(url, image_download_size, extract_size, typeof(extract_sha256) != "undefined" ? extract_sha256 : "", typeof(contains_multiple_files) != "undefined" ? contains_multiple_files : false) + osbutton.text = name + ospopup.close() + if (imageWriter.readyToWrite()) { + writebutton.enabled = true + } + } + } + } + } + } + + + /* + Popup for SD card device selection + */ + Popup { + id: dstpopup + x: 50 + y: 25 + width: parent.width-100 + height: parent.height-50 + padding: 25 + focus: true + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside + + ColumnLayout { + spacing: 10 + + Text { + text: qsTr("SD Card") + font.pointSize: 14 + } + Text { + text: qsTr("Any existing data on the device selected will be DELETED") + font.pointSize: 10 + color: "#c51a4a" + } + Rectangle { + implicitWidth: parent.width //540 + implicitHeight: 1 + color: "#1E000000" + } + + Item { + clip: true + width: dstlist.width + height: dstlist.height + + ListView { + id: dstlist + model: driveListModel + delegate: dstdelegate + width: window.width-140 //540 + height: window.height-170 //250 + focus: true + boundsBehavior: Flickable.StopAtBounds + ScrollBar.vertical: ScrollBar { + width: 10 + } + } + } + } + } + + Component { + id: dstdelegate + + Item { + width: window.width-140 //540 + height: 50 + + Rectangle { + id: dstbgrect + anchors.fill: parent + color: "#f5f5f5" + visible: false + } + + Row { + Column { + width: 64 + + Image { + source: isUsb ? "icons/ic_usb_48px.svg" : isScsi ? "icons/ic_storage_48px.svg" : "icons/ic_sd_storage_48px.svg" + } + } + Column { + width: parent.parent.width-64 + + Text { + textFormat: Text.StyledText + text: { + var txt = ""+description+" - "+Math.floor(size/1000000000)+" GB"+"
    " + if (mountpoints.length > 0) { + txt += ""+qsTr("Mounted as %1").arg(mountpoints.join(", "))+"" + } + return txt; + } + } + } + } + + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + hoverEnabled: true + + onEntered: { + dstbgrect.visible = true + } + + onExited: { + dstbgrect.visible = false + } + + onClicked: { + drivePollTimer.stop() + dstpopup.close() + imageWriter.setDst(device, size) + dstbutton.text = description + if (imageWriter.readyToWrite()) { + writebutton.enabled = true + } + } + } + } + } + + Popup { + id: msgpopup + x: 75 + y: 50 + width: parent.width-150 + height: parent.height-100 + padding: 25 + focus: true + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside + + ColumnLayout { + spacing: 10 + anchors.fill: parent + + Text { + id: msgpopupheader + font.pointSize: 14 + } + + Text { + id: msgpopupbody + font.pointSize: 12 + wrapMode: Text.Wrap + Layout.maximumWidth: msgpopup.width-50 //msgpopup.width-20 + } + + RowLayout { + Layout.alignment: Qt.AlignRight | Qt.AlignBottom + spacing: 20 + + Button { + id: quitbutton + text: qsTr("QUIT APP") + onClicked: Qt.quit() + Material.background: "#ffffff" + Material.foreground: "#c51a4a" + } + + Button { + id: continuebutton + text: qsTr("CONTINUE") + onClicked: msgpopup.close() + Material.background: "#ffffff" + Material.foreground: "#6cc04a" + } + + Text { text: " " } + } + } + } + + /* Persistent settings */ + Settings { + category: "General" + property alias x: window.x + property alias y: window.y + property alias verifyEnabled: verifySwitch.checked + } + + /* Timer for polling drivelist changes */ + Timer { + id: drivePollTimer + repeat: true + onTriggered: imageWriter.refreshDriveList() + } + + /* Utility functions */ + function httpRequest(url, callback) { + var xhr = new XMLHttpRequest(); + xhr.timeout = 5000 + xhr.onreadystatechange = (function(x) { + return function() { + if (x.readyState === x.DONE) + { + if (x.status === 200) + { + callback(x) + } + else + { + onError(qsTr("Error downloading OS list from Internet")) + } + } + } + })(xhr) + xhr.open("GET", url) + xhr.send() + } + + /* Slots for signals imagewrite emits */ + function onDownloadProgress(now,total) { + var newPos + if (total) { + newPos = now/(total+1) + } else { + newPos = 0 + } + if (progressBar.value != newPos) { + progressText.text = qsTr("Writing... %1%").arg(Math.floor(newPos*100)) + progressBar.indeterminate = false + progressBar.value = newPos + } + } + + function onVerifyProgress(now,total) { + var newPos + if (total) { + newPos = now/total + } else { + newPos = 0 + } + + if (progressBar.value != newPos) { + progressText.text = qsTr("Verifying... %1%").arg(Math.floor(newPos*100)) + progressBar.Material.accent = "#6cc04a" + progressBar.value = newPos + } + } + + function resetWriteButton() { + progressText.visible = false + progressBar.visible = false + osbutton.enabled = true + dstbutton.enabled = true + writebutton.visible = true + cancelbutton.visible = false + } + + function onError(msg) { + msgpopupheader.text = qsTr("Error") + msgpopupbody.text = msg + msgpopup.open() + resetWriteButton() + } + + function onSuccess() { + msgpopupheader.text = qsTr("Write Successful") + msgpopupbody.text = osbutton.text+" "+qsTr("has been written to")+" "+dstbutton.text+"\r\n"+qsTr("You can now remove card from reader"); + continuebutton.visible = false + msgpopup.open() + resetWriteButton() + } + + function onFileSelected(file) { + imageWriter.setSrc(file) + osbutton.text = imageWriter.srcFileName() + ospopup.close() + if (imageWriter.readyToWrite()) { + writebutton.enabled = true + } + } + + function onCancelled() { + resetWriteButton() + } +} diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..d68bac8 --- /dev/null +++ b/main.cpp @@ -0,0 +1,142 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include "imagewriter.h" +#include "drivelistmodel.h" +#include "networkaccessmanagerfactory.h" +#include +#include +#include + +static QTextStream cerr(stderr); + +#ifdef Q_OS_WIN +static void consoleMsgHandler(QtMsgType, const QMessageLogContext &, const QString &str) { + cerr << str << endl; +} +#endif + +int main(int argc, char *argv[]) +{ + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#ifdef Q_OS_WIN + // prefer ANGLE (DirectX) over desktop OpenGL + QApplication::setAttribute(Qt::AA_UseOpenGLES); +#endif + QApplication app(argc, argv); + app.setOrganizationName("Raspberry Pi"); + app.setOrganizationDomain("raspberrypi.org"); + app.setApplicationName("Imager"); + app.setWindowIcon(QIcon(":/icons/imagingutility.ico")); + ImageWriter imageWriter; + NetworkAccessManagerFactory namf; + QQmlApplicationEngine engine; + + /* Parse commandline arguments (if any) */ + QString customRepo; + QUrl url; + QStringList args = app.arguments(); + for (int i=1; i < args.size(); i++) + { + if (!args[i].startsWith("-") && url.isEmpty()) + { + if (args[i].startsWith("http:", Qt::CaseInsensitive) || args[i].startsWith("https:", Qt::CaseInsensitive)) + { + url = args[i]; + } + else + { + QFileInfo fi(args[i]); + + if (fi.isFile()) + { + url = QUrl::fromLocalFile(args[i]); + } + else + { + cerr << "Argument ignored because it is not a regular file: " << args[i] << endl;; + } + } + } + else if (args[i] == "--repo") + { + if (args.size()-i < 2 || args[i+1].startsWith("-")) + { + cerr << "Missing URL after --repo" << endl; + return 1; + } + + customRepo = args[++i]; + if (customRepo.startsWith("http://") || customRepo.startsWith("https://")) + { + imageWriter.setCustomOsListUrl(customRepo); + } + else + { + QFileInfo fi(customRepo); + if (!fi.isFile()) + { + cerr << "Custom repository file does not exist or is not a regular file: " << customRepo << endl; + return 1; + } + + imageWriter.setCustomOsListUrl(QUrl::fromLocalFile(customRepo)); + } + } + else if (args[i] == "--debug") + { +#ifdef Q_OS_WIN + /* Allocate console for debug messages on Windows */ + if (::AttachConsole(ATTACH_PARENT_PROCESS) || ::AllocConsole()) + { + freopen("CONOUT$", "w", stdout); + freopen("CONOUT$", "w", stderr); + std::ios::sync_with_stdio(); + qInstallMessageHandler(consoleMsgHandler); + } +#endif + } + else if (args[i] == "--help") + { + cerr << args[0] << " [--debug] [--repo ] []" << endl; + return 0; + } + else + { + cerr << "Ignoring unknown argument: " << args[i] << endl; + } + } + + if (!url.isEmpty()) + imageWriter.setSrc(url); + imageWriter.setEngine(&engine); + engine.setNetworkAccessManagerFactory(&namf); + engine.rootContext()->setContextProperty("imageWriter", &imageWriter); + engine.rootContext()->setContextProperty("driveListModel", imageWriter.getDriveList()); + engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); + + if (engine.rootObjects().isEmpty()) + return -1; + + QObject *qmlwindow = engine.rootObjects().value(0); + qmlwindow->connect(&imageWriter, SIGNAL(downloadProgress(QVariant,QVariant)), qmlwindow, SLOT(onDownloadProgress(QVariant,QVariant))); + qmlwindow->connect(&imageWriter, SIGNAL(verifyProgress(QVariant,QVariant)), qmlwindow, SLOT(onVerifyProgress(QVariant,QVariant))); + qmlwindow->connect(&imageWriter, SIGNAL(error(QVariant)), qmlwindow, SLOT(onError(QVariant))); + qmlwindow->connect(&imageWriter, SIGNAL(success()), qmlwindow, SLOT(onSuccess())); + qmlwindow->connect(&imageWriter, SIGNAL(fileSelected(QVariant)), qmlwindow, SLOT(onFileSelected(QVariant))); + qmlwindow->connect(&imageWriter, SIGNAL(cancelled()), qmlwindow, SLOT(onCancelled())); + qmlwindow->connect(&imageWriter, SIGNAL(finalizing()), qmlwindow, SLOT(onFinalizing())); + + int rc = app.exec(); + return rc; +} + diff --git a/main.qml b/main.qml new file mode 100644 index 0000000..2a5a3c0 --- /dev/null +++ b/main.qml @@ -0,0 +1,912 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +import QtQuick 2.9 +import QtQuick.Window 2.2 +import QtQuick.Controls 2.2 +import QtQuick.Layouts 1.0 +import QtQuick.Controls.Material 2.2 +import Qt.labs.settings 1.0 + +ApplicationWindow { + id: window + visible: true + width: 680 + height: 420 + minimumWidth: 680 + maximumWidth: 680 + minimumHeight: 420 + maximumHeight: 420 + + title: qsTr("Raspberry Pi Imager") + + FontLoader {id: roboto; source: "fonts/Roboto-Regular.ttf"} + FontLoader {id: robotoLight; source: "fonts/Roboto-Light.ttf"} + FontLoader {id: robotoBold; source: "fonts/Roboto-Bold.ttf"} + + ColumnLayout { + id: bg + spacing: 0 + + Image { + id: image + Layout.fillWidth: true + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + Layout.preferredWidth: window.width + fillMode: Image.PreserveAspectFit + source: "icons/rpi2.png" + } + + Rectangle { + color: "#c31c4a" + implicitWidth: window.width + implicitHeight: window.height/2 + + GridLayout { + id: gridLayout + rowSpacing: 25 + + anchors.fill: parent + anchors.topMargin: 25 + anchors.rightMargin: 50 + anchors.leftMargin: 50 + + rows: 3 + columns: 3 + columnSpacing: 25 + + ColumnLayout { + id: columnLayout + spacing: 0 + Layout.fillWidth: true + anchors.top: parent.top + + Text { + id: text1 + color: "#ffffff" + text: qsTr("Operating System") + Layout.fillWidth: true + Layout.preferredHeight: 17 + Layout.preferredWidth: 100 + font.pixelSize: 12 + font.family: robotoBold.name + font.bold: true + horizontalAlignment: Text.AlignHCenter + } + + Button { + id: osbutton + text: imageWriter.srcFileName() === "" ? qsTr("CHOOSE OS") : imageWriter.srcFileName() + font.family: roboto.name + spacing: 0 + padding: 0 + bottomPadding: 0 + topPadding: 0 + Layout.minimumHeight: 40 + Layout.fillWidth: true + onClicked: ospopup.open() + Material.background: "#ffffff" + Material.foreground: "#c51a4a" + } + } + + ColumnLayout { + id: columnLayout2 + spacing: 0 + Layout.fillWidth: true + anchors.top: parent.top + + Text { + id: text2 + color: "#ffffff" + text: qsTr("SD Card") + Layout.fillWidth: true + Layout.preferredHeight: 17 + Layout.preferredWidth: 100 + font.pixelSize: 12 + font.family: robotoBold.name + font.bold: true + horizontalAlignment: Text.AlignHCenter + } + + Button { + id: dstbutton + text: qsTr("CHOOSE SD CARD") + font.family: roboto.name + Layout.minimumHeight: 40 + Layout.preferredWidth: 100 + Layout.fillWidth: true + onClicked: { + imageWriter.refreshDriveList() + drivePollTimer.start() + dstpopup.open() + } + Material.background: "#ffffff" + Material.foreground: "#c51a4a" + } + } + + ColumnLayout { + spacing: 0 + Layout.fillWidth: true + anchors.top: parent.top + + Text { + text: " " + Layout.preferredHeight: 17 + Layout.preferredWidth: 100 + } + + Button { + id: writebutton + text: qsTr("WRITE") + font.family: roboto.name + Layout.minimumHeight: 40 + Layout.fillWidth: true + + enabled: false + Material.background: "#ffffff" + Material.foreground: "#c51a4a" + onClicked: { + if (!imageWriter.readyToWrite()) + return; + enabled = false + cancelwritebutton.enabled = true + cancelwritebutton.visible = true + cancelverifybutton.enabled = true + progressText.text = qsTr("Writing... %1%").arg("0") + progressText.visible = true + progressBar.visible = true + progressBar.indeterminate = true + progressBar.Material.accent = "#ffffff" + osbutton.enabled = false + dstbutton.enabled = false + imageWriter.setVerifyEnabled(true) + imageWriter.startWrite() + } + } + } + + ColumnLayout { + id: columnLayout3 + Layout.columnSpan: 3 + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + + Text { + id: progressText + font.pointSize: 10 + color: "white" + font.family: robotoBold.name + font.bold: true + visible: false + horizontalAlignment: Text.AlignHCenter + Layout.fillWidth: true + } + + ProgressBar { + id: progressBar + Layout.fillWidth: true + visible: false + Material.background: "#d15d7d" + } + + Button { + id: cancelwritebutton + text: qsTr("CANCEL WRITE") + onClicked: { + enabled = false + progressText.text = qsTr("Cancelling...") + imageWriter.cancelWrite() + } + Material.background: "#ffffff" + Material.foreground: "#c51a4a" + Layout.alignment: Qt.AlignRight + visible: false + font.family: roboto.name + } + Button { + id: cancelverifybutton + text: qsTr("CANCEL VERIFY") + onClicked: { + enabled = false + progressText.text = qsTr("Finalizing...") + imageWriter.setVerifyEnabled(false) + } + Material.background: "#ffffff" + Material.foreground: "#c51a4a" + Layout.alignment: Qt.AlignRight + visible: false + font.family: roboto.name + } + } + } + } + } + + + /* + Popup for OS selection + */ + Popup { + id: ospopup + x: 50 + y: 25 + width: parent.width-100 + height: parent.height-50 + padding: 0 + focus: true + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside + + // background of title + Rectangle { + color: "#f5f5f5" + anchors.right: parent.right + anchors.top: parent.top + height: 35 + width: parent.width + } + // line under title + Rectangle { + color: "#afafaf" + width: parent.width + y: 35 + implicitHeight: 1 + } + + Text { + text: "X" + anchors.right: parent.right + anchors.top: parent.top + anchors.rightMargin: 25 + anchors.topMargin: 10 + font.family: roboto.name + font.bold: true + + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: { + ospopup.close() + } + } + } + + ColumnLayout { + spacing: 10 + + Text { + text: qsTr("Operating System") + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + Layout.fillWidth: true + Layout.topMargin: 10 + font.family: roboto.name + font.bold: true + } + + Item { + clip: true + width: oslist.width + height: oslist.height + + SwipeView { + id: osswipeview + interactive: false + + ListView { + id: oslist + model: osmodel + delegate: osdelegate + width: window.width-100 + height: window.height-100 + focus: true + boundsBehavior: Flickable.StopAtBounds + ScrollBar.vertical: ScrollBar { + width: 10 + //policy: ScrollBar.AlwaysOn + } + } + + ListView { + id: suboslist + model: subosmodel + delegate: osdelegate + width: window.width-100 + height: window.height-100 + boundsBehavior: Flickable.StopAtBounds + ScrollBar.vertical: ScrollBar { + width: 10 + //policy: ScrollBar.AlwaysOn + } + } + } + } + } + } + + ListModel { + id: osmodel + + ListElement { + url: "internal://format" + icon: "icons/ic_delete_40px.png" + extract_size: 0 + image_download_size: 0 + extract_sha256: "" + contains_multiple_files: false + release_date: "" + subitems_url: "" + subitems: [] + name: qsTr("Erase") + description: qsTr("Format card as FAT32") + } + + ListElement { + url: "" + icon: "icons/ic_computer_40px.png" + name: qsTr("Use custom") + description: qsTr("Select a custom .img from your computer") + } + + Component.onCompleted: { + httpRequest(imageWriter.constantOsListUrl(), function (x) { + var o = JSON.parse(x.responseText) + if (!"os_list" in o) { + onError(qsTr("Error parsing os_list.json")) + return; + } + var oslist = o["os_list"] + for (var i in oslist) { + osmodel.insert(osmodel.count-2, oslist[i]) + } + }) + } + } + + ListModel { + id: subosmodel + + ListElement { + url: "" + icon: "icons/ic_chevron_left_40px.png" + extract_size: 0 + image_download_size: 0 + extract_sha256: "" + contains_multiple_files: false + release_date: "" + subitems_url: "internal://back" + subitems: [] + name: qsTr("Back") + description: qsTr("Go back to main menu") + } + } + + Component { + id: osdelegate + + Item { + width: window.width-100 + height: image_download_size ? 100 : 60 + + Rectangle { + id: bgrect + anchors.fill: parent + color: "#f5f5f5" + visible: false + } + Rectangle { + id: borderrect + implicitHeight: 1 + implicitWidth: parent.width + color: "#dcdcdc" + y: parent.height + } + + Row { + leftPadding: 25 + + Column { + width: 64 + + Image { + source: icon == "icons/ic_build_48px.svg" ? "icons/ic_build_40px.png": icon + verticalAlignment: Image.AlignVCenter + height: parent.parent.parent.height + fillMode: Image.Pad + } + Text { + text: " " +// visible: !icon + } + } + Column { + width: parent.parent.width-64-50-25 + + Text { + verticalAlignment: Text.AlignVCenter + height: parent.parent.parent.height + font.family: roboto.name + textFormat: Text.RichText + text: { + var txt = "

    "+name+"

    " + txt += ""+description+"" + if (typeof(release_date) == "string" && release_date) + txt += "
    "+qsTr("Released: %1").arg(release_date) + if (typeof(url) == "string" && url != "" && url != "internal://format") { + if (typeof(extract_sha256) != "undefined" && imageWriter.isCached(url,extract_sha256)) { + txt += "
    "+qsTr("Cached on your computer") + } else { + txt += "
    "+qsTr("Online - %1 GB download").arg((image_download_size/1073741824).toFixed(1)); + } + } + txt += "
    "; + + return txt; + } + } + + } + Column { + Image { + source: "icons/ic_chevron_right_40px.png" + visible: (typeof(subitems) == "object" && subitems.count) || (typeof(subitems_url) == "string" && subitems_url != "" && subitems_url != "internal://back") + height: parent.parent.parent.height + fillMode: Image.Pad + } + } + } + + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + hoverEnabled: true + + onEntered: { + bgrect.visible = true + } + + onExited: { + bgrect.visible = false + } + + onClicked: { + if (typeof(subitems) == "object" && subitems.count) { + if (subosmodel.count>1) + { + subosmodel.remove(1, subosmodel.count-1) + } + for (var i=0; i1) + { + subosmodel.remove(1, subosmodel.count-1) + } + + httpRequest(subitems_url, function (x) { + var o = JSON.parse(x.responseText) + if (!"os_list" in o) { + onError(qsTr("Error parsing os_list.json")) + return; + } + var oslist = o["os_list"] + for (var i in oslist) { + subosmodel.append(oslist[i]) + } + }) + osswipeview.setCurrentIndex(1) + } + } else if (url == "") { + imageWriter.openFileDialog() + } else { + imageWriter.setSrc(url, image_download_size, extract_size, typeof(extract_sha256) != "undefined" ? extract_sha256 : "", typeof(contains_multiple_files) != "undefined" ? contains_multiple_files : false) + osbutton.text = name + ospopup.close() + if (imageWriter.readyToWrite()) { + writebutton.enabled = true + } + } + } + } + } + } + + + /* + Popup for SD card device selection + */ + Popup { + id: dstpopup + x: 50 + y: 25 + width: parent.width-100 + height: parent.height-50 + padding: 0 + focus: true + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside + + // background of title + Rectangle { + color: "#f5f5f5" + anchors.right: parent.right + anchors.top: parent.top + height: 35 + width: parent.width + } + // line under title + Rectangle { + color: "#afafaf" + width: parent.width + y: 35 + implicitHeight: 1 + } + + Text { + text: "X" + anchors.right: parent.right + anchors.top: parent.top + anchors.rightMargin: 25 + anchors.topMargin: 10 + font.family: roboto.name + font.bold: true + + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: { + dstpopup.close() + } + } + } + + ColumnLayout { + spacing: 10 + + Text { + text: qsTr("SD Card") + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + Layout.fillWidth: true + Layout.topMargin: 10 + font.family: roboto.name + font.bold: true + } + + Item { + clip: true + width: dstlist.width + height: dstlist.height + + ListView { + id: dstlist + model: driveListModel + delegate: dstdelegate + width: window.width-100 + height: window.height-170 + focus: true + boundsBehavior: Flickable.StopAtBounds + ScrollBar.vertical: ScrollBar { + width: 10 + } + } + } + } + } + + Component { + id: dstdelegate + + Item { + width: window.width-100 + height: 60 + + Rectangle { + id: dstbgrect + anchors.fill: parent + color: "#f5f5f5" + visible: false + } + Rectangle { + id: dstborderrect + implicitHeight: 1 + implicitWidth: parent.width + color: "#dcdcdc" + y: parent.height + } + + Row { + leftPadding: 25 + + Column { + width: 64 + + Image { + source: isUsb ? "icons/ic_usb_40px.png" : isScsi ? "icons/ic_storage_40px.png" : "icons/ic_sd_storage_40px.png" + verticalAlignment: Image.AlignVCenter + height: parent.parent.parent.height + fillMode: Image.Pad + } + } + Column { + width: parent.parent.width-64 + + Text { + textFormat: Text.StyledText + height: parent.parent.parent.height + verticalAlignment: Text.AlignVCenter + font.family: roboto.name + text: { + var txt = "

    "+description+" - "+Math.floor(size/1000000000)+" GB"+"

    " + if (mountpoints.length > 0) { + txt += ""+qsTr("Mounted as %1").arg(mountpoints.join(", "))+"" + } + return txt; + } + } + } + } + + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + hoverEnabled: true + + onEntered: { + dstbgrect.visible = true + } + + onExited: { + dstbgrect.visible = false + } + + onClicked: { + drivePollTimer.stop() + dstpopup.close() + imageWriter.setDst(device, size) + dstbutton.text = description + if (imageWriter.readyToWrite()) { + writebutton.enabled = true + } + } + } + } + } + + Popup { + id: msgpopup + x: 75 + y: parent.height/2-100 + width: parent.width-150 + height: msgpopupbody.implicitHeight+150 //200 + padding: 0 + focus: true + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside + + // background of title + Rectangle { + color: "#f5f5f5" + anchors.right: parent.right + anchors.top: parent.top + height: 35 + width: parent.width + } + // line under title + Rectangle { + color: "#afafaf" + width: parent.width + y: 35 + implicitHeight: 1 + } + + Text { + id: msgx + text: "X" + anchors.right: parent.right + anchors.top: parent.top + anchors.rightMargin: 25 + anchors.topMargin: 10 + font.family: roboto.name + font.bold: true + + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: { + if (continuebutton.visible) + msgpopup.close() + else + Qt.quit() + } + } + } + + ColumnLayout { + spacing: 20 + anchors.fill: parent + + Text { + id: msgpopupheader + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + Layout.fillWidth: true + anchors.top: parent.top + anchors.topMargin: 10 + font.family: roboto.name + font.bold: true + } + + Text { + id: msgpopupbody + font.pointSize: 12 + wrapMode: Text.Wrap + textFormat: Text.StyledText + font.family: roboto.name + Layout.maximumWidth: msgpopup.width-50 + Layout.fillHeight: true + Layout.leftMargin: 25 + Layout.topMargin: 25 + } + + RowLayout { + Layout.alignment: Qt.AlignCenter | Qt.AlignBottom + Layout.bottomMargin: 10 + spacing: 20 + + Button { + id: quitbutton + text: qsTr("QUIT APP") + onClicked: Qt.quit() + Material.foreground: "#ffffff" + Material.background: "#c51a4a" + font.family: roboto.name + visible: false + } + + Button { + id: continuebutton + text: qsTr("CONTINUE") + onClicked: msgpopup.close() + Material.foreground: "#ffffff" + Material.background: "#c51a4a" + font.family: roboto.name + } + + Text { text: " " } + } + } + } + + /* Persistent settings */ + Settings { + category: "General" + property alias x: window.x + property alias y: window.y + } + + /* Timer for polling drivelist changes */ + Timer { + id: drivePollTimer + repeat: true + onTriggered: imageWriter.refreshDriveList() + } + + /* Utility functions */ + function httpRequest(url, callback) { + var xhr = new XMLHttpRequest(); + xhr.timeout = 5000 + xhr.onreadystatechange = (function(x) { + return function() { + if (x.readyState === x.DONE) + { + if (x.status === 200) + { + callback(x) + } + else + { + onError(qsTr("Error downloading OS list from Internet")) + } + } + } + })(xhr) + xhr.open("GET", url) + xhr.send() + } + + /* Slots for signals imagewrite emits */ + function onDownloadProgress(now,total) { + var newPos + if (total) { + newPos = now/(total+1) + } else { + newPos = 0 + } + if (progressBar.value != newPos) { + if (progressText.text == qsTr("Cancelling...")) + return + + progressText.text = qsTr("Writing... %1%").arg(Math.floor(newPos*100)) + progressBar.indeterminate = false + progressBar.value = newPos + } + } + + function onVerifyProgress(now,total) { + var newPos + if (total) { + newPos = now/total + } else { + newPos = 0 + } + + if (progressBar.value != newPos) { + if (cancelwritebutton.visible) { + cancelwritebutton.visible = false + cancelverifybutton.visible = true + } + + if (progressText.text == qsTr("Finalizing...")) + return + + progressText.text = qsTr("Verifying... %1%").arg(Math.floor(newPos*100)) + progressBar.Material.accent = "#6cc04a" + progressBar.value = newPos + } + } + + function resetWriteButton() { + progressText.visible = false + progressBar.visible = false + osbutton.enabled = true + dstbutton.enabled = true + writebutton.visible = true + writebutton.enabled = imageWriter.readyToWrite() + cancelwritebutton.visible = false + cancelverifybutton.visible = false + } + + function onError(msg) { + msgpopupheader.text = qsTr("Error") + msgpopupbody.text = msg + msgpopup.open() + resetWriteButton() + } + + function onSuccess() { + msgpopupheader.text = qsTr("Write Successful") + msgpopupbody.text = qsTr("%1 has been written to %2

    You can now remove the SD card from the reader").arg(osbutton.text).arg(dstbutton.text) + msgpopup.open() + imageWriter.setDst("") + dstbutton.text = qsTr("CHOOSE SD CARD") + resetWriteButton() + } + + function onFileSelected(file) { + imageWriter.setSrc(file) + osbutton.text = imageWriter.srcFileName() + ospopup.close() + if (imageWriter.readyToWrite()) { + writebutton.enabled = true + } + } + + function onCancelled() { + resetWriteButton() + } + + function onFinalizing() { + progressText.text = qsTr("Finalizing...") + } +} diff --git a/nan.h b/nan.h new file mode 100644 index 0000000..7de9844 --- /dev/null +++ b/nan.h @@ -0,0 +1,21 @@ +#ifndef NAN_H +#define NAN_H + +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +// Dummy Node.js macros for 3rd party dependencies +#define NAN_METHOD(x) + +namespace v8 { + class Object; + template class Local; +} + +// mountutils also expects some #include files to be there +#include +#include + +#endif // NAN_H diff --git a/networkaccessmanagerfactory.cpp b/networkaccessmanagerfactory.cpp new file mode 100644 index 0000000..35b3080 --- /dev/null +++ b/networkaccessmanagerfactory.cpp @@ -0,0 +1,32 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +#include "networkaccessmanagerfactory.h" +#include "config.h" +#include +#include +#include +#include +#include +#include + +/* Configure caching for files downloaded from Internet by QML (e.g. os_list.json and icons) */ +NetworkAccessManagerFactory::NetworkAccessManagerFactory() +{ + _c = new QNetworkDiskCache(this); + _c->setCacheDirectory(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)+QDir::separator()+"oslistcache"); + /* Only cache images and not the .json */ + //_c->remove(QUrl(OSLIST_URL)); + + /* Clear all for now as we do not know any potential subitems_url in advance */ + _c->clear(); +} + +QNetworkAccessManager *NetworkAccessManagerFactory::create(QObject *parent) +{ + QNetworkAccessManager *nam = new QNetworkAccessManager(parent); + nam->setCache(_c); + return nam; +} diff --git a/networkaccessmanagerfactory.h b/networkaccessmanagerfactory.h new file mode 100644 index 0000000..de240b1 --- /dev/null +++ b/networkaccessmanagerfactory.h @@ -0,0 +1,23 @@ +#ifndef NETWORKACCESSMANAGERFACTORY_H +#define NETWORKACCESSMANAGERFACTORY_H + +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +#include + +class QNetworkDiskCache; + +class NetworkAccessManagerFactory : public QObject, public QQmlNetworkAccessManagerFactory +{ +public: + NetworkAccessManagerFactory(); + virtual QNetworkAccessManager *create(QObject *parent); + +protected: + QNetworkDiskCache *_c; +}; + +#endif // NETWORKACCESSMANAGERFACTORY_H diff --git a/powersaveblocker.cpp b/powersaveblocker.cpp new file mode 100644 index 0000000..3c724bc --- /dev/null +++ b/powersaveblocker.cpp @@ -0,0 +1,57 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +#include "powersaveblocker.h" +#include +#include + +PowerSaveBlocker::PowerSaveBlocker(QObject *parent) : + QObject(parent), _stayingAwake(false) +{ +} + +PowerSaveBlocker::~PowerSaveBlocker() +{ + if (_stayingAwake) + removeBlock(); +} + +void PowerSaveBlocker::applyBlock(const QString &reason) +{ + if (_stayingAwake) + return; + +#ifdef Q_OS_WIN + REASON_CONTEXT rc; + std::wstring wreason = reason.toStdWString(); + rc.Version = POWER_REQUEST_CONTEXT_VERSION; + rc.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING; + rc.Reason.SimpleReasonString = (wchar_t *) wreason.c_str(); + _powerRequest = PowerCreateRequest(&rc); + + if (_powerRequest == INVALID_HANDLE_VALUE) + { + qDebug() << "Error creating power request:" << GetLastError(); + return; + } + + _stayingAwake = PowerSetRequest(_powerRequest, PowerRequestDisplayRequired); + if (!_stayingAwake) + { + qDebug() << "Error running PowerSetRequest():" << GetLastError(); + } +#endif +} + +void PowerSaveBlocker::removeBlock() +{ + if (!_stayingAwake) + return; + +#ifdef Q_OS_WIN + PowerClearRequest(_powerRequest, PowerRequestDisplayRequired); + CloseHandle(_powerRequest); +#endif +} diff --git a/powersaveblocker.h b/powersaveblocker.h new file mode 100644 index 0000000..5569612 --- /dev/null +++ b/powersaveblocker.h @@ -0,0 +1,33 @@ +#ifndef POWERSAVEBLOCKER_H +#define POWERSAVEBLOCKER_H + +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +#include +#ifdef Q_OS_WIN +#include +#endif + +class PowerSaveBlocker : public QObject +{ + Q_OBJECT +public: + explicit PowerSaveBlocker(QObject *parent = nullptr); + virtual ~PowerSaveBlocker(); + void applyBlock(const QString &reason); + void removeBlock(); + +signals: + +protected: + bool _stayingAwake; + +#ifdef Q_OS_WIN + HANDLE _powerRequest; +#endif +}; + +#endif // POWERSAVEBLOCKER_H diff --git a/qml.qrc b/qml.qrc new file mode 100644 index 0000000..8a879a2 --- /dev/null +++ b/qml.qrc @@ -0,0 +1,21 @@ + + + main.qml + qtquickcontrols2.conf + icons/rpi.png + icons/imagingutility.ico + icons/rpi2.png + fonts/Roboto-Bold.ttf + fonts/Roboto-Light.ttf + fonts/Roboto-Regular.ttf + icons/ic_chevron_right_40px.png + icons/ic_chevron_left_40px.png + icons/ic_computer_40px.png + icons/ic_delete_40px.png + icons/ic_usb_40px.png + icons/ic_storage_40px.png + icons/ic_sd_storage_40px.png + icons/ic_build_40px.png + icons/ic_close_18px.png + + diff --git a/qtquickcontrols2.conf b/qtquickcontrols2.conf new file mode 100644 index 0000000..b6c7c87 --- /dev/null +++ b/qtquickcontrols2.conf @@ -0,0 +1,2 @@ +[Controls] +Style=Material diff --git a/windows/imagingutility.manifest b/windows/imagingutility.manifest new file mode 100644 index 0000000..e0c139d --- /dev/null +++ b/windows/imagingutility.manifest @@ -0,0 +1,13 @@ + + + + Raspberry Pi Imager + + + + + + + + + diff --git a/windows/imagingutility.nsi b/windows/imagingutility.nsi new file mode 100644 index 0000000..f870f47 --- /dev/null +++ b/windows/imagingutility.nsi @@ -0,0 +1,1029 @@ +!define INSTALLER_NAME "setup.exe" +!ifndef INNER +!finalize '"c:\Program Files (x86)\Microsoft SDKs\ClickOnce\SignTool\signtool.exe" sign /tr http://timestamp.digicert.com /td sha256 /fd sha256 /a "%1"' +!endif + +############################################################################################ +# NSIS Installation Script created by NSIS Quick Setup Script Generator v1.09.18 +# Entirely Edited with NullSoft Scriptable Installation System +# by Vlasis K. Barkas aka Red Wine red_wine@freemail.gr Sep 2006 +############################################################################################ + +!define APP_NAME "Raspberry Pi Imager" +!define COMP_NAME "Raspberry Pi" +#!define WEB_SITE "https://www.raspberrypi.org/" +!define VERSION "00.00.00.01" +!define COPYRIGHT "Raspberry Pi" +!define DESCRIPTION "Raspberry Pi Imager" +!define MAIN_APP_EXE "imagingutility.exe" +!define INSTALL_TYPE "SetShellVarContext current" +!define REG_ROOT "HKCU" +!define REG_APP_PATH "Software\Microsoft\Windows\CurrentVersion\App Paths\${MAIN_APP_EXE}" +!define UNINSTALL_PATH "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}" + +###################################################################### + +VIProductVersion "${VERSION}" +VIAddVersionKey "ProductName" "${APP_NAME}" +VIAddVersionKey "CompanyName" "${COMP_NAME}" +VIAddVersionKey "LegalCopyright" "${COPYRIGHT}" +VIAddVersionKey "FileDescription" "${DESCRIPTION}" +VIAddVersionKey "FileVersion" "${VERSION}" + +###################################################################### + +SetCompressor LZMA +Name "${APP_NAME}" +Caption "${APP_NAME}" +OutFile "${INSTALLER_NAME}" +BrandingText "${APP_NAME}" +XPStyle on +InstallDirRegKey "${REG_ROOT}" "${REG_APP_PATH}" "" +InstallDir "$PROGRAMFILES\Raspberry Pi Imager" + +###################################################################### + +### Stuff for signing uninstaller +!ifdef INNER + !echo "Inner invocation" ; just to see what's going on + OutFile "$%TEMP%\tempinstaller.exe" ; not really important where this is + SetCompress off +!else + !echo "Outer invocation" + + ; Call makensis again against current file, defining INNER. This writes an installer for us which, when + ; it is invoked, will just write the uninstaller to some location, and then exit. + + !makensis '/DINNER "${__FILE__}"' = 0 + + ; So now run that installer we just created as %TEMP%\tempinstaller.exe. Since it + ; calls quit the return value isn't zero. + + !system "$%TEMP%\tempinstaller.exe" = 2 + + ; That will have written an uninstaller binary for us. Now we sign it with your + ; favorite code signing tool. + + !system '"c:\Program Files (x86)\Microsoft SDKs\ClickOnce\SignTool\signtool.exe" sign /tr http://timestamp.digicert.com /td sha256 /fd sha256 /a "$%TEMP%\uninstall.exe"' = 0 + + ; Good. Now we can carry on writing the real installer. + + OutFile "setup.exe" + SetCompressor /SOLID lzma +!endif + +### + + +!include "MUI.nsh" + +!define MUI_ABORTWARNING +!define MUI_UNABORTWARNING + +!insertmacro MUI_PAGE_WELCOME + +!ifdef LICENSE_TXT +!insertmacro MUI_PAGE_LICENSE "${LICENSE_TXT}" +!endif + +!ifdef REG_START_MENU +!define MUI_STARTMENUPAGE_NODISABLE +!define MUI_STARTMENUPAGE_DEFAULTFOLDER "Raspberry Pi" +!define MUI_STARTMENUPAGE_REGISTRY_ROOT "${REG_ROOT}" +!define MUI_STARTMENUPAGE_REGISTRY_KEY "${UNINSTALL_PATH}" +!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${REG_START_MENU}" +!insertmacro MUI_PAGE_STARTMENU Application $SM_Folder +!endif + +!insertmacro MUI_PAGE_INSTFILES + +!define MUI_FINISHPAGE_RUN "$INSTDIR\${MAIN_APP_EXE}" +!insertmacro MUI_PAGE_FINISH + +!insertmacro MUI_UNPAGE_CONFIRM + +!insertmacro MUI_UNPAGE_INSTFILES + +!insertmacro MUI_UNPAGE_FINISH + +!insertmacro MUI_LANGUAGE "English" + +###################################################################### + +Section -MainProgram +${INSTALL_TYPE} +SetOverwrite ifnewer +SetOutPath "$INSTDIR" +File "deploy\D3Dcompiler_47.dll" +#File "deploy\opengl32sw.dll" +File "deploy\libssl-1_1.dll" +File "deploy\libcrypto-1_1.dll" +File "deploy\fat32format.exe" +File "deploy\libEGL.dll" +File "deploy\libgcc_s_dw2-1.dll" +File "deploy\libGLESV2.dll" +File "deploy\libstdc++-6.dll" +File "deploy\libwinpthread-1.dll" +File "deploy\license.txt" +File "deploy\Qt5Core.dll" +File "deploy\Qt5Gui.dll" +File "deploy\Qt5Network.dll" +File "deploy\Qt5Qml.dll" +File "deploy\Qt5QmlModels.dll" +File "deploy\Qt5QmlWorkerScript.dll" +File "deploy\Qt5Quick.dll" +File "deploy\Qt5QuickControls2.dll" +File "deploy\Qt5QuickTemplates2.dll" +File "deploy\Qt5Svg.dll" +File "deploy\Qt5Widgets.dll" +File "deploy\imagingutility.exe" +SetOutPath "$INSTDIR\styles" +File "deploy\styles\qwindowsvistastyle.dll" +SetOutPath "$INSTDIR\QtQuick.2" +File "deploy\QtQuick.2\plugins.qmltypes" +File "deploy\QtQuick.2\qmldir" +File "deploy\QtQuick.2\qtquick2plugin.dll" +SetOutPath "$INSTDIR\QtQuick\Window.2" +File "deploy\QtQuick\Window.2\plugins.qmltypes" +File "deploy\QtQuick\Window.2\qmldir" +File "deploy\QtQuick\Window.2\windowplugin.dll" +SetOutPath "$INSTDIR\QtQuick\Templates.2" +File "deploy\QtQuick\Templates.2\plugins.qmltypes" +File "deploy\QtQuick\Templates.2\qmldir" +File "deploy\QtQuick\Templates.2\qtquicktemplates2plugin.dll" +SetOutPath "$INSTDIR\QtQuick\Layouts" +File "deploy\QtQuick\Layouts\plugins.qmltypes" +File "deploy\QtQuick\Layouts\qmldir" +File "deploy\QtQuick\Layouts\qquicklayoutsplugin.dll" +SetOutPath "$INSTDIR\QtQuick\Controls.2" +File "deploy\QtQuick\Controls.2\AbstractButton.qml" +File "deploy\QtQuick\Controls.2\Action.qml" +File "deploy\QtQuick\Controls.2\ActionGroup.qml" +File "deploy\QtQuick\Controls.2\ApplicationWindow.qml" +File "deploy\QtQuick\Controls.2\BusyIndicator.qml" +File "deploy\QtQuick\Controls.2\Button.qml" +File "deploy\QtQuick\Controls.2\ButtonGroup.qml" +File "deploy\QtQuick\Controls.2\CheckBox.qml" +File "deploy\QtQuick\Controls.2\CheckDelegate.qml" +File "deploy\QtQuick\Controls.2\ComboBox.qml" +File "deploy\QtQuick\Controls.2\Container.qml" +File "deploy\QtQuick\Controls.2\Control.qml" +File "deploy\QtQuick\Controls.2\DelayButton.qml" +File "deploy\QtQuick\Controls.2\Dial.qml" +File "deploy\QtQuick\Controls.2\Dialog.qml" +File "deploy\QtQuick\Controls.2\DialogButtonBox.qml" +File "deploy\QtQuick\Controls.2\Drawer.qml" +File "deploy\QtQuick\Controls.2\Frame.qml" +File "deploy\QtQuick\Controls.2\GroupBox.qml" +File "deploy\QtQuick\Controls.2\ItemDelegate.qml" +File "deploy\QtQuick\Controls.2\Label.qml" +File "deploy\QtQuick\Controls.2\Menu.qml" +File "deploy\QtQuick\Controls.2\MenuBar.qml" +File "deploy\QtQuick\Controls.2\MenuBarItem.qml" +File "deploy\QtQuick\Controls.2\MenuItem.qml" +File "deploy\QtQuick\Controls.2\MenuSeparator.qml" +File "deploy\QtQuick\Controls.2\Page.qml" +File "deploy\QtQuick\Controls.2\PageIndicator.qml" +File "deploy\QtQuick\Controls.2\Pane.qml" +File "deploy\QtQuick\Controls.2\plugins.qmltypes" +File "deploy\QtQuick\Controls.2\Popup.qml" +File "deploy\QtQuick\Controls.2\ProgressBar.qml" +File "deploy\QtQuick\Controls.2\qmldir" +File "deploy\QtQuick\Controls.2\qtquickcontrols2plugin.dll" +File "deploy\QtQuick\Controls.2\RadioButton.qml" +File "deploy\QtQuick\Controls.2\RadioDelegate.qml" +File "deploy\QtQuick\Controls.2\RangeSlider.qml" +File "deploy\QtQuick\Controls.2\RoundButton.qml" +File "deploy\QtQuick\Controls.2\ScrollBar.qml" +File "deploy\QtQuick\Controls.2\ScrollIndicator.qml" +File "deploy\QtQuick\Controls.2\ScrollView.qml" +File "deploy\QtQuick\Controls.2\Slider.qml" +File "deploy\QtQuick\Controls.2\SpinBox.qml" +File "deploy\QtQuick\Controls.2\SplitView.qml" +File "deploy\QtQuick\Controls.2\StackView.qml" +File "deploy\QtQuick\Controls.2\SwipeDelegate.qml" +File "deploy\QtQuick\Controls.2\SwipeView.qml" +File "deploy\QtQuick\Controls.2\Switch.qml" +File "deploy\QtQuick\Controls.2\SwitchDelegate.qml" +File "deploy\QtQuick\Controls.2\TabBar.qml" +File "deploy\QtQuick\Controls.2\TabButton.qml" +File "deploy\QtQuick\Controls.2\TextArea.qml" +File "deploy\QtQuick\Controls.2\TextField.qml" +File "deploy\QtQuick\Controls.2\ToolBar.qml" +File "deploy\QtQuick\Controls.2\ToolButton.qml" +File "deploy\QtQuick\Controls.2\ToolSeparator.qml" +File "deploy\QtQuick\Controls.2\ToolTip.qml" +File "deploy\QtQuick\Controls.2\Tumbler.qml" +SetOutPath "$INSTDIR\QtQuick\Controls.2\Universal" +File "deploy\QtQuick\Controls.2\Universal\ApplicationWindow.qml" +File "deploy\QtQuick\Controls.2\Universal\BusyIndicator.qml" +File "deploy\QtQuick\Controls.2\Universal\Button.qml" +File "deploy\QtQuick\Controls.2\Universal\CheckBox.qml" +File "deploy\QtQuick\Controls.2\Universal\CheckDelegate.qml" +File "deploy\QtQuick\Controls.2\Universal\CheckIndicator.qml" +File "deploy\QtQuick\Controls.2\Universal\ComboBox.qml" +File "deploy\QtQuick\Controls.2\Universal\DelayButton.qml" +File "deploy\QtQuick\Controls.2\Universal\Dial.qml" +File "deploy\QtQuick\Controls.2\Universal\Dialog.qml" +File "deploy\QtQuick\Controls.2\Universal\DialogButtonBox.qml" +File "deploy\QtQuick\Controls.2\Universal\Drawer.qml" +File "deploy\QtQuick\Controls.2\Universal\Frame.qml" +File "deploy\QtQuick\Controls.2\Universal\GroupBox.qml" +File "deploy\QtQuick\Controls.2\Universal\ItemDelegate.qml" +File "deploy\QtQuick\Controls.2\Universal\Label.qml" +File "deploy\QtQuick\Controls.2\Universal\Menu.qml" +File "deploy\QtQuick\Controls.2\Universal\MenuBar.qml" +File "deploy\QtQuick\Controls.2\Universal\MenuBarItem.qml" +File "deploy\QtQuick\Controls.2\Universal\MenuItem.qml" +File "deploy\QtQuick\Controls.2\Universal\MenuSeparator.qml" +File "deploy\QtQuick\Controls.2\Universal\Page.qml" +File "deploy\QtQuick\Controls.2\Universal\PageIndicator.qml" +File "deploy\QtQuick\Controls.2\Universal\Pane.qml" +File "deploy\QtQuick\Controls.2\Universal\plugins.qmltypes" +File "deploy\QtQuick\Controls.2\Universal\Popup.qml" +File "deploy\QtQuick\Controls.2\Universal\ProgressBar.qml" +File "deploy\QtQuick\Controls.2\Universal\qmldir" +File "deploy\QtQuick\Controls.2\Universal\qtquickcontrols2universalstyleplugin.dll" +File "deploy\QtQuick\Controls.2\Universal\RadioButton.qml" +File "deploy\QtQuick\Controls.2\Universal\RadioDelegate.qml" +File "deploy\QtQuick\Controls.2\Universal\RadioIndicator.qml" +File "deploy\QtQuick\Controls.2\Universal\RangeSlider.qml" +File "deploy\QtQuick\Controls.2\Universal\RoundButton.qml" +File "deploy\QtQuick\Controls.2\Universal\ScrollBar.qml" +File "deploy\QtQuick\Controls.2\Universal\ScrollIndicator.qml" +File "deploy\QtQuick\Controls.2\Universal\Slider.qml" +File "deploy\QtQuick\Controls.2\Universal\SpinBox.qml" +File "deploy\QtQuick\Controls.2\Universal\SplitView.qml" +File "deploy\QtQuick\Controls.2\Universal\StackView.qml" +File "deploy\QtQuick\Controls.2\Universal\SwipeDelegate.qml" +File "deploy\QtQuick\Controls.2\Universal\Switch.qml" +File "deploy\QtQuick\Controls.2\Universal\SwitchDelegate.qml" +File "deploy\QtQuick\Controls.2\Universal\SwitchIndicator.qml" +File "deploy\QtQuick\Controls.2\Universal\TabBar.qml" +File "deploy\QtQuick\Controls.2\Universal\TabButton.qml" +File "deploy\QtQuick\Controls.2\Universal\TextArea.qml" +File "deploy\QtQuick\Controls.2\Universal\TextField.qml" +File "deploy\QtQuick\Controls.2\Universal\ToolBar.qml" +File "deploy\QtQuick\Controls.2\Universal\ToolButton.qml" +File "deploy\QtQuick\Controls.2\Universal\ToolSeparator.qml" +File "deploy\QtQuick\Controls.2\Universal\ToolTip.qml" +File "deploy\QtQuick\Controls.2\Universal\Tumbler.qml" +SetOutPath "$INSTDIR\QtQuick\Controls.2\Material" +File "deploy\QtQuick\Controls.2\Material\ApplicationWindow.qml" +File "deploy\QtQuick\Controls.2\Material\BoxShadow.qml" +File "deploy\QtQuick\Controls.2\Material\BusyIndicator.qml" +File "deploy\QtQuick\Controls.2\Material\Button.qml" +File "deploy\QtQuick\Controls.2\Material\CheckBox.qml" +File "deploy\QtQuick\Controls.2\Material\CheckDelegate.qml" +File "deploy\QtQuick\Controls.2\Material\CheckIndicator.qml" +File "deploy\QtQuick\Controls.2\Material\ComboBox.qml" +File "deploy\QtQuick\Controls.2\Material\CursorDelegate.qml" +File "deploy\QtQuick\Controls.2\Material\DelayButton.qml" +File "deploy\QtQuick\Controls.2\Material\Dial.qml" +File "deploy\QtQuick\Controls.2\Material\Dialog.qml" +File "deploy\QtQuick\Controls.2\Material\DialogButtonBox.qml" +File "deploy\QtQuick\Controls.2\Material\Drawer.qml" +File "deploy\QtQuick\Controls.2\Material\ElevationEffect.qml" +File "deploy\QtQuick\Controls.2\Material\Frame.qml" +File "deploy\QtQuick\Controls.2\Material\GroupBox.qml" +File "deploy\QtQuick\Controls.2\Material\ItemDelegate.qml" +File "deploy\QtQuick\Controls.2\Material\Label.qml" +File "deploy\QtQuick\Controls.2\Material\Menu.qml" +File "deploy\QtQuick\Controls.2\Material\MenuBar.qml" +File "deploy\QtQuick\Controls.2\Material\MenuBarItem.qml" +File "deploy\QtQuick\Controls.2\Material\MenuItem.qml" +File "deploy\QtQuick\Controls.2\Material\MenuSeparator.qml" +File "deploy\QtQuick\Controls.2\Material\Page.qml" +File "deploy\QtQuick\Controls.2\Material\PageIndicator.qml" +File "deploy\QtQuick\Controls.2\Material\Pane.qml" +File "deploy\QtQuick\Controls.2\Material\plugins.qmltypes" +File "deploy\QtQuick\Controls.2\Material\Popup.qml" +File "deploy\QtQuick\Controls.2\Material\ProgressBar.qml" +File "deploy\QtQuick\Controls.2\Material\qmldir" +File "deploy\QtQuick\Controls.2\Material\qtquickcontrols2materialstyleplugin.dll" +File "deploy\QtQuick\Controls.2\Material\RadioButton.qml" +File "deploy\QtQuick\Controls.2\Material\RadioDelegate.qml" +File "deploy\QtQuick\Controls.2\Material\RadioIndicator.qml" +File "deploy\QtQuick\Controls.2\Material\RangeSlider.qml" +File "deploy\QtQuick\Controls.2\Material\RectangularGlow.qml" +File "deploy\QtQuick\Controls.2\Material\RoundButton.qml" +File "deploy\QtQuick\Controls.2\Material\ScrollBar.qml" +File "deploy\QtQuick\Controls.2\Material\ScrollIndicator.qml" +File "deploy\QtQuick\Controls.2\Material\Slider.qml" +File "deploy\QtQuick\Controls.2\Material\SliderHandle.qml" +File "deploy\QtQuick\Controls.2\Material\SpinBox.qml" +File "deploy\QtQuick\Controls.2\Material\SplitView.qml" +File "deploy\QtQuick\Controls.2\Material\StackView.qml" +File "deploy\QtQuick\Controls.2\Material\SwipeDelegate.qml" +File "deploy\QtQuick\Controls.2\Material\SwipeView.qml" +File "deploy\QtQuick\Controls.2\Material\Switch.qml" +File "deploy\QtQuick\Controls.2\Material\SwitchDelegate.qml" +File "deploy\QtQuick\Controls.2\Material\SwitchIndicator.qml" +File "deploy\QtQuick\Controls.2\Material\TabBar.qml" +File "deploy\QtQuick\Controls.2\Material\TabButton.qml" +File "deploy\QtQuick\Controls.2\Material\TextArea.qml" +File "deploy\QtQuick\Controls.2\Material\TextField.qml" +File "deploy\QtQuick\Controls.2\Material\ToolBar.qml" +File "deploy\QtQuick\Controls.2\Material\ToolButton.qml" +File "deploy\QtQuick\Controls.2\Material\ToolSeparator.qml" +File "deploy\QtQuick\Controls.2\Material\ToolTip.qml" +File "deploy\QtQuick\Controls.2\Material\Tumbler.qml" +SetOutPath "$INSTDIR\QtQuick\Controls.2\Imagine" +File "deploy\QtQuick\Controls.2\Imagine\ApplicationWindow.qml" +File "deploy\QtQuick\Controls.2\Imagine\BusyIndicator.qml" +File "deploy\QtQuick\Controls.2\Imagine\Button.qml" +File "deploy\QtQuick\Controls.2\Imagine\CheckBox.qml" +File "deploy\QtQuick\Controls.2\Imagine\CheckDelegate.qml" +File "deploy\QtQuick\Controls.2\Imagine\ComboBox.qml" +File "deploy\QtQuick\Controls.2\Imagine\DelayButton.qml" +File "deploy\QtQuick\Controls.2\Imagine\Dial.qml" +File "deploy\QtQuick\Controls.2\Imagine\Dialog.qml" +File "deploy\QtQuick\Controls.2\Imagine\DialogButtonBox.qml" +File "deploy\QtQuick\Controls.2\Imagine\Drawer.qml" +File "deploy\QtQuick\Controls.2\Imagine\Frame.qml" +File "deploy\QtQuick\Controls.2\Imagine\GroupBox.qml" +File "deploy\QtQuick\Controls.2\Imagine\ItemDelegate.qml" +File "deploy\QtQuick\Controls.2\Imagine\Label.qml" +File "deploy\QtQuick\Controls.2\Imagine\Menu.qml" +File "deploy\QtQuick\Controls.2\Imagine\MenuItem.qml" +File "deploy\QtQuick\Controls.2\Imagine\MenuSeparator.qml" +File "deploy\QtQuick\Controls.2\Imagine\Page.qml" +File "deploy\QtQuick\Controls.2\Imagine\PageIndicator.qml" +File "deploy\QtQuick\Controls.2\Imagine\Pane.qml" +File "deploy\QtQuick\Controls.2\Imagine\plugins.qmltypes" +File "deploy\QtQuick\Controls.2\Imagine\Popup.qml" +File "deploy\QtQuick\Controls.2\Imagine\ProgressBar.qml" +File "deploy\QtQuick\Controls.2\Imagine\qmldir" +File "deploy\QtQuick\Controls.2\Imagine\qtquickcontrols2imaginestyleplugin.dll" +File "deploy\QtQuick\Controls.2\Imagine\RadioButton.qml" +File "deploy\QtQuick\Controls.2\Imagine\RadioDelegate.qml" +File "deploy\QtQuick\Controls.2\Imagine\RangeSlider.qml" +File "deploy\QtQuick\Controls.2\Imagine\RoundButton.qml" +File "deploy\QtQuick\Controls.2\Imagine\ScrollBar.qml" +File "deploy\QtQuick\Controls.2\Imagine\ScrollIndicator.qml" +File "deploy\QtQuick\Controls.2\Imagine\Slider.qml" +File "deploy\QtQuick\Controls.2\Imagine\SpinBox.qml" +File "deploy\QtQuick\Controls.2\Imagine\SplitView.qml" +File "deploy\QtQuick\Controls.2\Imagine\StackView.qml" +File "deploy\QtQuick\Controls.2\Imagine\SwipeDelegate.qml" +File "deploy\QtQuick\Controls.2\Imagine\SwipeView.qml" +File "deploy\QtQuick\Controls.2\Imagine\Switch.qml" +File "deploy\QtQuick\Controls.2\Imagine\SwitchDelegate.qml" +File "deploy\QtQuick\Controls.2\Imagine\TabBar.qml" +File "deploy\QtQuick\Controls.2\Imagine\TabButton.qml" +File "deploy\QtQuick\Controls.2\Imagine\TextArea.qml" +File "deploy\QtQuick\Controls.2\Imagine\TextField.qml" +File "deploy\QtQuick\Controls.2\Imagine\ToolBar.qml" +File "deploy\QtQuick\Controls.2\Imagine\ToolButton.qml" +File "deploy\QtQuick\Controls.2\Imagine\ToolSeparator.qml" +File "deploy\QtQuick\Controls.2\Imagine\ToolTip.qml" +File "deploy\QtQuick\Controls.2\Imagine\Tumbler.qml" +SetOutPath "$INSTDIR\QtQuick\Controls.2\Fusion" +File "deploy\QtQuick\Controls.2\Fusion\ApplicationWindow.qml" +File "deploy\QtQuick\Controls.2\Fusion\BusyIndicator.qml" +File "deploy\QtQuick\Controls.2\Fusion\Button.qml" +File "deploy\QtQuick\Controls.2\Fusion\ButtonPanel.qml" +File "deploy\QtQuick\Controls.2\Fusion\CheckBox.qml" +File "deploy\QtQuick\Controls.2\Fusion\CheckDelegate.qml" +File "deploy\QtQuick\Controls.2\Fusion\CheckIndicator.qml" +File "deploy\QtQuick\Controls.2\Fusion\ComboBox.qml" +File "deploy\QtQuick\Controls.2\Fusion\DelayButton.qml" +File "deploy\QtQuick\Controls.2\Fusion\Dial.qml" +File "deploy\QtQuick\Controls.2\Fusion\Dialog.qml" +File "deploy\QtQuick\Controls.2\Fusion\DialogButtonBox.qml" +File "deploy\QtQuick\Controls.2\Fusion\Drawer.qml" +File "deploy\QtQuick\Controls.2\Fusion\Frame.qml" +File "deploy\QtQuick\Controls.2\Fusion\GroupBox.qml" +File "deploy\QtQuick\Controls.2\Fusion\ItemDelegate.qml" +File "deploy\QtQuick\Controls.2\Fusion\Label.qml" +File "deploy\QtQuick\Controls.2\Fusion\Menu.qml" +File "deploy\QtQuick\Controls.2\Fusion\MenuBar.qml" +File "deploy\QtQuick\Controls.2\Fusion\MenuBarItem.qml" +File "deploy\QtQuick\Controls.2\Fusion\MenuItem.qml" +File "deploy\QtQuick\Controls.2\Fusion\MenuSeparator.qml" +File "deploy\QtQuick\Controls.2\Fusion\Page.qml" +File "deploy\QtQuick\Controls.2\Fusion\PageIndicator.qml" +File "deploy\QtQuick\Controls.2\Fusion\Pane.qml" +File "deploy\QtQuick\Controls.2\Fusion\plugins.qmltypes" +File "deploy\QtQuick\Controls.2\Fusion\Popup.qml" +File "deploy\QtQuick\Controls.2\Fusion\ProgressBar.qml" +File "deploy\QtQuick\Controls.2\Fusion\qmldir" +File "deploy\QtQuick\Controls.2\Fusion\qtquickcontrols2fusionstyleplugin.dll" +File "deploy\QtQuick\Controls.2\Fusion\RadioButton.qml" +File "deploy\QtQuick\Controls.2\Fusion\RadioDelegate.qml" +File "deploy\QtQuick\Controls.2\Fusion\RadioIndicator.qml" +File "deploy\QtQuick\Controls.2\Fusion\RangeSlider.qml" +File "deploy\QtQuick\Controls.2\Fusion\RoundButton.qml" +File "deploy\QtQuick\Controls.2\Fusion\ScrollBar.qml" +File "deploy\QtQuick\Controls.2\Fusion\ScrollIndicator.qml" +File "deploy\QtQuick\Controls.2\Fusion\Slider.qml" +File "deploy\QtQuick\Controls.2\Fusion\SliderGroove.qml" +File "deploy\QtQuick\Controls.2\Fusion\SliderHandle.qml" +File "deploy\QtQuick\Controls.2\Fusion\SpinBox.qml" +File "deploy\QtQuick\Controls.2\Fusion\SplitView.qml" +File "deploy\QtQuick\Controls.2\Fusion\SwipeDelegate.qml" +File "deploy\QtQuick\Controls.2\Fusion\Switch.qml" +File "deploy\QtQuick\Controls.2\Fusion\SwitchDelegate.qml" +File "deploy\QtQuick\Controls.2\Fusion\SwitchIndicator.qml" +File "deploy\QtQuick\Controls.2\Fusion\TabBar.qml" +File "deploy\QtQuick\Controls.2\Fusion\TabButton.qml" +File "deploy\QtQuick\Controls.2\Fusion\TextArea.qml" +File "deploy\QtQuick\Controls.2\Fusion\TextField.qml" +File "deploy\QtQuick\Controls.2\Fusion\ToolBar.qml" +File "deploy\QtQuick\Controls.2\Fusion\ToolButton.qml" +File "deploy\QtQuick\Controls.2\Fusion\ToolSeparator.qml" +File "deploy\QtQuick\Controls.2\Fusion\ToolTip.qml" +File "deploy\QtQuick\Controls.2\Fusion\Tumbler.qml" +SetOutPath "$INSTDIR\QtGraphicalEffects" +File "deploy\QtGraphicalEffects\Blend.qml" +File "deploy\QtGraphicalEffects\BrightnessContrast.qml" +File "deploy\QtGraphicalEffects\Colorize.qml" +File "deploy\QtGraphicalEffects\ColorOverlay.qml" +File "deploy\QtGraphicalEffects\ConicalGradient.qml" +File "deploy\QtGraphicalEffects\Desaturate.qml" +File "deploy\QtGraphicalEffects\DirectionalBlur.qml" +File "deploy\QtGraphicalEffects\Displace.qml" +File "deploy\QtGraphicalEffects\DropShadow.qml" +File "deploy\QtGraphicalEffects\FastBlur.qml" +File "deploy\QtGraphicalEffects\GammaAdjust.qml" +File "deploy\QtGraphicalEffects\GaussianBlur.qml" +File "deploy\QtGraphicalEffects\Glow.qml" +File "deploy\QtGraphicalEffects\HueSaturation.qml" +File "deploy\QtGraphicalEffects\InnerShadow.qml" +File "deploy\QtGraphicalEffects\LevelAdjust.qml" +File "deploy\QtGraphicalEffects\LinearGradient.qml" +File "deploy\QtGraphicalEffects\MaskedBlur.qml" +File "deploy\QtGraphicalEffects\OpacityMask.qml" +File "deploy\QtGraphicalEffects\plugins.qmltypes" +File "deploy\QtGraphicalEffects\qmldir" +File "deploy\QtGraphicalEffects\qtgraphicaleffectsplugin.dll" +File "deploy\QtGraphicalEffects\RadialBlur.qml" +File "deploy\QtGraphicalEffects\RadialGradient.qml" +File "deploy\QtGraphicalEffects\RectangularGlow.qml" +File "deploy\QtGraphicalEffects\RecursiveBlur.qml" +File "deploy\QtGraphicalEffects\ThresholdMask.qml" +File "deploy\QtGraphicalEffects\ZoomBlur.qml" +SetOutPath "$INSTDIR\QtGraphicalEffects\private" +File "deploy\QtGraphicalEffects\private\DropShadowBase.qml" +File "deploy\QtGraphicalEffects\private\DropShadowBase.qmlc" +File "deploy\QtGraphicalEffects\private\FastGlow.qml" +File "deploy\QtGraphicalEffects\private\FastGlow.qmlc" +File "deploy\QtGraphicalEffects\private\FastInnerShadow.qml" +File "deploy\QtGraphicalEffects\private\FastInnerShadow.qmlc" +File "deploy\QtGraphicalEffects\private\FastMaskedBlur.qml" +File "deploy\QtGraphicalEffects\private\FastMaskedBlur.qmlc" +File "deploy\QtGraphicalEffects\private\GaussianDirectionalBlur.qml" +File "deploy\QtGraphicalEffects\private\GaussianDirectionalBlur.qmlc" +File "deploy\QtGraphicalEffects\private\GaussianGlow.qml" +File "deploy\QtGraphicalEffects\private\GaussianGlow.qmlc" +File "deploy\QtGraphicalEffects\private\GaussianInnerShadow.qml" +File "deploy\QtGraphicalEffects\private\GaussianInnerShadow.qmlc" +File "deploy\QtGraphicalEffects\private\GaussianMaskedBlur.qml" +File "deploy\QtGraphicalEffects\private\GaussianMaskedBlur.qmlc" +File "deploy\QtGraphicalEffects\private\qmldir" +File "deploy\QtGraphicalEffects\private\qtgraphicaleffectsprivate.dll" +SetOutPath "$INSTDIR\Qt\labs\settings" +File "deploy\Qt\labs\settings\plugins.qmltypes" +File "deploy\Qt\labs\settings\qmldir" +File "deploy\Qt\labs\settings\qmlsettingsplugin.dll" +SetOutPath "$INSTDIR\qmltooling" +File "deploy\qmltooling\qmldbg_debugger.dll" +File "deploy\qmltooling\qmldbg_inspector.dll" +File "deploy\qmltooling\qmldbg_local.dll" +File "deploy\qmltooling\qmldbg_messages.dll" +File "deploy\qmltooling\qmldbg_native.dll" +File "deploy\qmltooling\qmldbg_nativedebugger.dll" +File "deploy\qmltooling\qmldbg_preview.dll" +File "deploy\qmltooling\qmldbg_profiler.dll" +File "deploy\qmltooling\qmldbg_quickprofiler.dll" +File "deploy\qmltooling\qmldbg_server.dll" +File "deploy\qmltooling\qmldbg_tcp.dll" +SetOutPath "$INSTDIR\platforms" +File "deploy\platforms\qwindows.dll" +SetOutPath "$INSTDIR\imageformats" +File "deploy\imageformats\qicns.dll" +File "deploy\imageformats\qico.dll" +File "deploy\imageformats\qjpeg.dll" +File "deploy\imageformats\qsvg.dll" +File "deploy\imageformats\qtga.dll" +File "deploy\imageformats\qwbmp.dll" +SetOutPath "$INSTDIR\iconengines" +File "deploy\iconengines\qsvgicon.dll" +SetOutPath "$INSTDIR\bearer" +File "deploy\bearer\qgenericbearer.dll" +SectionEnd + +###################################################################### + +Section -Icons_Reg + +!ifndef INNER +SetOutPath "$INSTDIR" +File "$%TEMP%\uninstall.exe" +!endif + +!ifdef REG_START_MENU +!insertmacro MUI_STARTMENU_WRITE_BEGIN Application +CreateDirectory "$SMPROGRAMS\$SM_Folder" +CreateShortCut "$SMPROGRAMS\$SM_Folder\${APP_NAME}.lnk" "$INSTDIR\${MAIN_APP_EXE}" +!ifdef WEB_SITE +WriteIniStr "$INSTDIR\${APP_NAME} website.url" "InternetShortcut" "URL" "${WEB_SITE}" +CreateShortCut "$SMPROGRAMS\$SM_Folder\${APP_NAME} Website.lnk" "$INSTDIR\${APP_NAME} website.url" +!endif +!insertmacro MUI_STARTMENU_WRITE_END +!endif + +!ifndef REG_START_MENU +CreateDirectory "$SMPROGRAMS\Raspberry Pi" +CreateShortCut "$SMPROGRAMS\Raspberry Pi\${APP_NAME}.lnk" "$INSTDIR\${MAIN_APP_EXE}" +!ifdef WEB_SITE +WriteIniStr "$INSTDIR\${APP_NAME} website.url" "InternetShortcut" "URL" "${WEB_SITE}" +CreateShortCut "$SMPROGRAMS\Raspberry Pi\${APP_NAME} Website.lnk" "$INSTDIR\${APP_NAME} website.url" +!endif +!endif + +WriteRegStr ${REG_ROOT} "${REG_APP_PATH}" "" "$INSTDIR\${MAIN_APP_EXE}" +WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "DisplayName" "${APP_NAME}" +WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "UninstallString" "$INSTDIR\uninstall.exe" +WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "DisplayIcon" "$INSTDIR\${MAIN_APP_EXE}" +WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "DisplayVersion" "${VERSION}" +WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "Publisher" "${COMP_NAME}" + +!ifdef WEB_SITE +WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "URLInfoAbout" "${WEB_SITE}" +!endif + + +WriteRegStr SHCTX "Software\Classes\.zip\OpenWithProgIds" "RPI_IMAGINGUTILITY" "" +WriteRegStr SHCTX "Software\Classes\.gz\OpenWithProgIds" "RPI_IMAGINGUTILITY" "" +WriteRegStr SHCTX "Software\Classes\.xz\OpenWithProgIds" "RPI_IMAGINGUTILITY" "" +WriteRegStr SHCTX "Software\Classes\.img\OpenWithProgIds" "RPI_IMAGINGUTILITY" "" +WriteRegStr SHCTX "Software\Classes\RPI_IMAGINGUTILITY\shell\open" "FriendlyAppName" "Raspberry Pi Imager" +WriteRegStr SHCTX "Software\Classes\RPI_IMAGINGUTILITY\shell\open\command" "" '"$INSTDIR\imagingutility.exe" "%1"' + +SectionEnd + +###################################################################### + +Section Uninstall +${INSTALL_TYPE} +Delete "$INSTDIR\D3Dcompiler_47.dll" +Delete "$INSTDIR\opengl32sw.dll" +Delete "$INSTDIR\libssl-1_1.dll" +Delete "$INSTDIR\libcrypto-1_1.dll" +Delete "$INSTDIR\fat32format.exe" +Delete "$INSTDIR\libEGL.dll" +Delete "$INSTDIR\libgcc_s_dw2-1.dll" +Delete "$INSTDIR\libGLESV2.dll" +Delete "$INSTDIR\libstdc++-6.dll" +Delete "$INSTDIR\libwinpthread-1.dll" +Delete "$INSTDIR\license.txt" +Delete "$INSTDIR\Qt5Core.dll" +Delete "$INSTDIR\Qt5Gui.dll" +Delete "$INSTDIR\Qt5Network.dll" +Delete "$INSTDIR\Qt5Qml.dll" +Delete "$INSTDIR\Qt5QmlModels.dll" +Delete "$INSTDIR\Qt5QmlWorkerScript.dll" +Delete "$INSTDIR\Qt5Quick.dll" +Delete "$INSTDIR\Qt5QuickControls2.dll" +Delete "$INSTDIR\Qt5QuickTemplates2.dll" +Delete "$INSTDIR\Qt5Svg.dll" +Delete "$INSTDIR\Qt5Widgets.dll" +Delete "$INSTDIR\imagingutility.exe" +Delete "$INSTDIR\styles\qwindowsvistastyle.dll" +Delete "$INSTDIR\QtQuick.2\plugins.qmltypes" +Delete "$INSTDIR\QtQuick.2\qmldir" +Delete "$INSTDIR\QtQuick.2\qtquick2plugin.dll" +Delete "$INSTDIR\QtQuick\Window.2\plugins.qmltypes" +Delete "$INSTDIR\QtQuick\Window.2\qmldir" +Delete "$INSTDIR\QtQuick\Window.2\windowplugin.dll" +Delete "$INSTDIR\QtQuick\Templates.2\plugins.qmltypes" +Delete "$INSTDIR\QtQuick\Templates.2\qmldir" +Delete "$INSTDIR\QtQuick\Templates.2\qtquicktemplates2plugin.dll" +Delete "$INSTDIR\QtQuick\Layouts\plugins.qmltypes" +Delete "$INSTDIR\QtQuick\Layouts\qmldir" +Delete "$INSTDIR\QtQuick\Layouts\qquicklayoutsplugin.dll" +Delete "$INSTDIR\QtQuick\Controls.2\AbstractButton.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Action.qml" +Delete "$INSTDIR\QtQuick\Controls.2\ActionGroup.qml" +Delete "$INSTDIR\QtQuick\Controls.2\ApplicationWindow.qml" +Delete "$INSTDIR\QtQuick\Controls.2\BusyIndicator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Button.qml" +Delete "$INSTDIR\QtQuick\Controls.2\ButtonGroup.qml" +Delete "$INSTDIR\QtQuick\Controls.2\CheckBox.qml" +Delete "$INSTDIR\QtQuick\Controls.2\CheckDelegate.qml" +Delete "$INSTDIR\QtQuick\Controls.2\ComboBox.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Container.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Control.qml" +Delete "$INSTDIR\QtQuick\Controls.2\DelayButton.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Dial.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Dialog.qml" +Delete "$INSTDIR\QtQuick\Controls.2\DialogButtonBox.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Drawer.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Frame.qml" +Delete "$INSTDIR\QtQuick\Controls.2\GroupBox.qml" +Delete "$INSTDIR\QtQuick\Controls.2\ItemDelegate.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Label.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Menu.qml" +Delete "$INSTDIR\QtQuick\Controls.2\MenuBar.qml" +Delete "$INSTDIR\QtQuick\Controls.2\MenuBarItem.qml" +Delete "$INSTDIR\QtQuick\Controls.2\MenuItem.qml" +Delete "$INSTDIR\QtQuick\Controls.2\MenuSeparator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Page.qml" +Delete "$INSTDIR\QtQuick\Controls.2\PageIndicator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Pane.qml" +Delete "$INSTDIR\QtQuick\Controls.2\plugins.qmltypes" +Delete "$INSTDIR\QtQuick\Controls.2\Popup.qml" +Delete "$INSTDIR\QtQuick\Controls.2\ProgressBar.qml" +Delete "$INSTDIR\QtQuick\Controls.2\qmldir" +Delete "$INSTDIR\QtQuick\Controls.2\qtquickcontrols2plugin.dll" +Delete "$INSTDIR\QtQuick\Controls.2\RadioButton.qml" +Delete "$INSTDIR\QtQuick\Controls.2\RadioDelegate.qml" +Delete "$INSTDIR\QtQuick\Controls.2\RangeSlider.qml" +Delete "$INSTDIR\QtQuick\Controls.2\RoundButton.qml" +Delete "$INSTDIR\QtQuick\Controls.2\ScrollBar.qml" +Delete "$INSTDIR\QtQuick\Controls.2\ScrollIndicator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\ScrollView.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Slider.qml" +Delete "$INSTDIR\QtQuick\Controls.2\SpinBox.qml" +Delete "$INSTDIR\QtQuick\Controls.2\SplitView.qml" +Delete "$INSTDIR\QtQuick\Controls.2\StackView.qml" +Delete "$INSTDIR\QtQuick\Controls.2\SwipeDelegate.qml" +Delete "$INSTDIR\QtQuick\Controls.2\SwipeView.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Switch.qml" +Delete "$INSTDIR\QtQuick\Controls.2\SwitchDelegate.qml" +Delete "$INSTDIR\QtQuick\Controls.2\TabBar.qml" +Delete "$INSTDIR\QtQuick\Controls.2\TabButton.qml" +Delete "$INSTDIR\QtQuick\Controls.2\TextArea.qml" +Delete "$INSTDIR\QtQuick\Controls.2\TextField.qml" +Delete "$INSTDIR\QtQuick\Controls.2\ToolBar.qml" +Delete "$INSTDIR\QtQuick\Controls.2\ToolButton.qml" +Delete "$INSTDIR\QtQuick\Controls.2\ToolSeparator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\ToolTip.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Tumbler.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\ApplicationWindow.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\BusyIndicator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\Button.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\CheckBox.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\CheckDelegate.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\CheckIndicator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\ComboBox.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\DelayButton.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\Dial.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\Dialog.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\DialogButtonBox.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\Drawer.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\Frame.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\GroupBox.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\ItemDelegate.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\Label.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\Menu.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\MenuBar.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\MenuBarItem.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\MenuItem.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\MenuSeparator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\Page.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\PageIndicator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\Pane.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\plugins.qmltypes" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\Popup.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\ProgressBar.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\qmldir" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\qtquickcontrols2universalstyleplugin.dll" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\RadioButton.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\RadioDelegate.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\RadioIndicator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\RangeSlider.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\RoundButton.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\ScrollBar.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\ScrollIndicator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\Slider.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\SpinBox.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\SplitView.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\StackView.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\SwipeDelegate.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\Switch.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\SwitchDelegate.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\SwitchIndicator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\TabBar.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\TabButton.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\TextArea.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\TextField.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\ToolBar.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\ToolButton.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\ToolSeparator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\ToolTip.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Universal\Tumbler.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\ApplicationWindow.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\BoxShadow.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\BusyIndicator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\Button.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\CheckBox.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\CheckDelegate.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\CheckIndicator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\ComboBox.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\CursorDelegate.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\DelayButton.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\Dial.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\Dialog.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\DialogButtonBox.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\Drawer.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\ElevationEffect.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\Frame.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\GroupBox.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\ItemDelegate.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\Label.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\Menu.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\MenuBar.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\MenuBarItem.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\MenuItem.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\MenuSeparator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\Page.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\PageIndicator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\Pane.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\plugins.qmltypes" +Delete "$INSTDIR\QtQuick\Controls.2\Material\Popup.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\ProgressBar.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\qmldir" +Delete "$INSTDIR\QtQuick\Controls.2\Material\qtquickcontrols2materialstyleplugin.dll" +Delete "$INSTDIR\QtQuick\Controls.2\Material\RadioButton.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\RadioDelegate.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\RadioIndicator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\RangeSlider.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\RectangularGlow.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\RoundButton.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\ScrollBar.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\ScrollIndicator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\Slider.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\SliderHandle.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\SpinBox.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\SplitView.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\StackView.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\SwipeDelegate.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\SwipeView.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\Switch.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\SwitchDelegate.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\SwitchIndicator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\TabBar.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\TabButton.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\TextArea.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\TextField.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\ToolBar.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\ToolButton.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\ToolSeparator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\ToolTip.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Material\Tumbler.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\ApplicationWindow.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\BusyIndicator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\Button.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\CheckBox.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\CheckDelegate.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\ComboBox.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\DelayButton.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\Dial.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\Dialog.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\DialogButtonBox.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\Drawer.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\Frame.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\GroupBox.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\ItemDelegate.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\Label.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\Menu.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\MenuItem.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\MenuSeparator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\Page.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\PageIndicator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\Pane.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\plugins.qmltypes" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\Popup.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\ProgressBar.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\qmldir" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\qtquickcontrols2imaginestyleplugin.dll" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\RadioButton.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\RadioDelegate.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\RangeSlider.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\RoundButton.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\ScrollBar.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\ScrollIndicator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\Slider.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\SpinBox.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\SplitView.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\StackView.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\SwipeDelegate.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\SwipeView.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\Switch.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\SwitchDelegate.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\TabBar.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\TabButton.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\TextArea.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\TextField.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\ToolBar.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\ToolButton.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\ToolSeparator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\ToolTip.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Imagine\Tumbler.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\ApplicationWindow.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\BusyIndicator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\Button.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\ButtonPanel.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\CheckBox.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\CheckDelegate.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\CheckIndicator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\ComboBox.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\DelayButton.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\Dial.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\Dialog.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\DialogButtonBox.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\Drawer.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\Frame.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\GroupBox.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\ItemDelegate.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\Label.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\Menu.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\MenuBar.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\MenuBarItem.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\MenuItem.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\MenuSeparator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\Page.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\PageIndicator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\Pane.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\plugins.qmltypes" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\Popup.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\ProgressBar.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\qmldir" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\qtquickcontrols2fusionstyleplugin.dll" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\RadioButton.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\RadioDelegate.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\RadioIndicator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\RangeSlider.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\RoundButton.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\ScrollBar.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\ScrollIndicator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\Slider.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\SliderGroove.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\SliderHandle.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\SpinBox.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\SplitView.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\SwipeDelegate.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\Switch.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\SwitchDelegate.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\SwitchIndicator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\TabBar.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\TabButton.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\TextArea.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\TextField.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\ToolBar.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\ToolButton.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\ToolSeparator.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\ToolTip.qml" +Delete "$INSTDIR\QtQuick\Controls.2\Fusion\Tumbler.qml" +Delete "$INSTDIR\QtGraphicalEffects\Blend.qml" +Delete "$INSTDIR\QtGraphicalEffects\BrightnessContrast.qml" +Delete "$INSTDIR\QtGraphicalEffects\Colorize.qml" +Delete "$INSTDIR\QtGraphicalEffects\ColorOverlay.qml" +Delete "$INSTDIR\QtGraphicalEffects\ConicalGradient.qml" +Delete "$INSTDIR\QtGraphicalEffects\Desaturate.qml" +Delete "$INSTDIR\QtGraphicalEffects\DirectionalBlur.qml" +Delete "$INSTDIR\QtGraphicalEffects\Displace.qml" +Delete "$INSTDIR\QtGraphicalEffects\DropShadow.qml" +Delete "$INSTDIR\QtGraphicalEffects\FastBlur.qml" +Delete "$INSTDIR\QtGraphicalEffects\GammaAdjust.qml" +Delete "$INSTDIR\QtGraphicalEffects\GaussianBlur.qml" +Delete "$INSTDIR\QtGraphicalEffects\Glow.qml" +Delete "$INSTDIR\QtGraphicalEffects\HueSaturation.qml" +Delete "$INSTDIR\QtGraphicalEffects\InnerShadow.qml" +Delete "$INSTDIR\QtGraphicalEffects\LevelAdjust.qml" +Delete "$INSTDIR\QtGraphicalEffects\LinearGradient.qml" +Delete "$INSTDIR\QtGraphicalEffects\MaskedBlur.qml" +Delete "$INSTDIR\QtGraphicalEffects\OpacityMask.qml" +Delete "$INSTDIR\QtGraphicalEffects\plugins.qmltypes" +Delete "$INSTDIR\QtGraphicalEffects\qmldir" +Delete "$INSTDIR\QtGraphicalEffects\qtgraphicaleffectsplugin.dll" +Delete "$INSTDIR\QtGraphicalEffects\RadialBlur.qml" +Delete "$INSTDIR\QtGraphicalEffects\RadialGradient.qml" +Delete "$INSTDIR\QtGraphicalEffects\RectangularGlow.qml" +Delete "$INSTDIR\QtGraphicalEffects\RecursiveBlur.qml" +Delete "$INSTDIR\QtGraphicalEffects\ThresholdMask.qml" +Delete "$INSTDIR\QtGraphicalEffects\ZoomBlur.qml" +Delete "$INSTDIR\QtGraphicalEffects\private\DropShadowBase.qml" +Delete "$INSTDIR\QtGraphicalEffects\private\DropShadowBase.qmlc" +Delete "$INSTDIR\QtGraphicalEffects\private\FastGlow.qml" +Delete "$INSTDIR\QtGraphicalEffects\private\FastGlow.qmlc" +Delete "$INSTDIR\QtGraphicalEffects\private\FastInnerShadow.qml" +Delete "$INSTDIR\QtGraphicalEffects\private\FastInnerShadow.qmlc" +Delete "$INSTDIR\QtGraphicalEffects\private\FastMaskedBlur.qml" +Delete "$INSTDIR\QtGraphicalEffects\private\FastMaskedBlur.qmlc" +Delete "$INSTDIR\QtGraphicalEffects\private\GaussianDirectionalBlur.qml" +Delete "$INSTDIR\QtGraphicalEffects\private\GaussianDirectionalBlur.qmlc" +Delete "$INSTDIR\QtGraphicalEffects\private\GaussianGlow.qml" +Delete "$INSTDIR\QtGraphicalEffects\private\GaussianGlow.qmlc" +Delete "$INSTDIR\QtGraphicalEffects\private\GaussianInnerShadow.qml" +Delete "$INSTDIR\QtGraphicalEffects\private\GaussianInnerShadow.qmlc" +Delete "$INSTDIR\QtGraphicalEffects\private\GaussianMaskedBlur.qml" +Delete "$INSTDIR\QtGraphicalEffects\private\GaussianMaskedBlur.qmlc" +Delete "$INSTDIR\QtGraphicalEffects\private\qmldir" +Delete "$INSTDIR\QtGraphicalEffects\private\qtgraphicaleffectsprivate.dll" +Delete "$INSTDIR\Qt\labs\settings\plugins.qmltypes" +Delete "$INSTDIR\Qt\labs\settings\qmldir" +Delete "$INSTDIR\Qt\labs\settings\qmlsettingsplugin.dll" +Delete "$INSTDIR\qmltooling\qmldbg_debugger.dll" +Delete "$INSTDIR\qmltooling\qmldbg_inspector.dll" +Delete "$INSTDIR\qmltooling\qmldbg_local.dll" +Delete "$INSTDIR\qmltooling\qmldbg_messages.dll" +Delete "$INSTDIR\qmltooling\qmldbg_native.dll" +Delete "$INSTDIR\qmltooling\qmldbg_nativedebugger.dll" +Delete "$INSTDIR\qmltooling\qmldbg_preview.dll" +Delete "$INSTDIR\qmltooling\qmldbg_profiler.dll" +Delete "$INSTDIR\qmltooling\qmldbg_quickprofiler.dll" +Delete "$INSTDIR\qmltooling\qmldbg_server.dll" +Delete "$INSTDIR\qmltooling\qmldbg_tcp.dll" +Delete "$INSTDIR\platforms\qwindows.dll" +Delete "$INSTDIR\imageformats\qicns.dll" +Delete "$INSTDIR\imageformats\qico.dll" +Delete "$INSTDIR\imageformats\qjpeg.dll" +Delete "$INSTDIR\imageformats\qsvg.dll" +Delete "$INSTDIR\imageformats\qtga.dll" +Delete "$INSTDIR\imageformats\qwbmp.dll" +Delete "$INSTDIR\iconengines\qsvgicon.dll" +Delete "$INSTDIR\bearer\qgenericbearer.dll" + +RmDir "$INSTDIR\bearer" +RmDir "$INSTDIR\iconengines" +RmDir "$INSTDIR\imageformats" +RmDir "$INSTDIR\platforms" +RmDir "$INSTDIR\qmltooling" +RmDir "$INSTDIR\Qt\labs\settings" +RmDir "$INSTDIR\Qt\labs" +RmDir "$INSTDIR\Qt" +RmDir "$INSTDIR\QtGraphicalEffects\private" +RmDir "$INSTDIR\QtGraphicalEffects" +RmDir "$INSTDIR\QtQuick\Controls.2\Fusion" +RmDir "$INSTDIR\QtQuick\Controls.2\Imagine" +RmDir "$INSTDIR\QtQuick\Controls.2\Material" +RmDir "$INSTDIR\QtQuick\Controls.2\Universal" +RmDir "$INSTDIR\QtQuick\Controls.2" +RmDir "$INSTDIR\QtQuick\Layouts" +RmDir "$INSTDIR\QtQuick\Templates.2" +RmDir "$INSTDIR\QtQuick\Window.2" +RmDir "$INSTDIR\QtQuick" +RmDir "$INSTDIR\QtQuick.2" +RmDir "$INSTDIR\styles" + +Delete "$INSTDIR\uninstall.exe" +!ifdef WEB_SITE +Delete "$INSTDIR\${APP_NAME} website.url" +!endif + +RmDir "$INSTDIR" + +!ifdef REG_START_MENU +!insertmacro MUI_STARTMENU_GETFOLDER "Application" $SM_Folder +Delete "$SMPROGRAMS\$SM_Folder\${APP_NAME}.lnk" +!ifdef WEB_SITE +Delete "$SMPROGRAMS\$SM_Folder\${APP_NAME} Website.lnk" +!endif +RmDir "$SMPROGRAMS\$SM_Folder" +!endif + +!ifndef REG_START_MENU +Delete "$SMPROGRAMS\Raspberry Pi\${APP_NAME}.lnk" +!ifdef WEB_SITE +Delete "$SMPROGRAMS\Raspberry Pi\${APP_NAME} Website.lnk" +!endif +RmDir "$SMPROGRAMS\Raspberry Pi" +!endif + +DeleteRegKey ${REG_ROOT} "${REG_APP_PATH}" +DeleteRegKey ${REG_ROOT} "${UNINSTALL_PATH}" + +# File associations +DeleteRegValue SHCTX "Software\Classes\.zip\OpenWithProgIds" "RPI_IMAGINGUTILITY" +DeleteRegValue SHCTX "Software\Classes\.gz\OpenWithProgIds" "RPI_IMAGINGUTILITY" +DeleteRegValue SHCTX "Software\Classes\.xz\OpenWithProgIds" "RPI_IMAGINGUTILITY" +DeleteRegValue SHCTX "Software\Classes\.zip\OpenWithProgIds" "RPI_IMAGINGUTILITY" +DeleteRegKey SHCTX "Software\Classes\RPI_IMAGINGUTILITY" + +DeleteRegKey ${REG_ROOT} "" + +RMDir /r "$APPDATA\Raspberry Pi\Imager" +RMDir "$APPDATA\Raspberry Pi" +RMDir /r "$LOCALAPPDATA\Raspberry Pi\Imager" +RMDir "$LOCALAPPDATA\Raspberry Pi" + +SectionEnd + +###################################################################### + + +Function .onInit +!ifdef INNER + + ; If INNER is defined, then we aren't supposed to do anything except write out + ; the uninstaller. This is better than processing a command line option as it means + ; this entire code path is not present in the final (real) installer. + SetSilent silent + WriteUninstaller "$%TEMP%\uninstall.exe" + Quit ; just bail out quickly when running the "inner" installer +!endif +FunctionEnd + diff --git a/windows/imagingutility.rc b/windows/imagingutility.rc new file mode 100644 index 0000000..ba9db52 --- /dev/null +++ b/windows/imagingutility.rc @@ -0,0 +1,22 @@ +#include + +IDI_ICON1 ICON DISCARDABLE "../icons/imagingutility.ico" +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "imagingutility.manifest" + +1 VERSIONINFO +FILEVERSION 1,0,0,0 +PRODUCTVERSION 1,0,0,0 +{ + BLOCK "StringFileInfo" + { + BLOCK "040904b0" + { + VALUE "CompanyName", "Raspberry Pi" + VALUE "FileDescription", "Raspberry Pi Imager" + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} diff --git a/windows/winfile.cpp b/windows/winfile.cpp new file mode 100644 index 0000000..fc23636 --- /dev/null +++ b/windows/winfile.cpp @@ -0,0 +1,193 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +#include "winfile.h" +#include +#include + +WinFile::WinFile(QObject *parent) + : QObject(parent), _locked(false), _h(INVALID_HANDLE_VALUE) +{ + +} + +WinFile::~WinFile() +{ + if (isOpen()) + close(); +} + +void WinFile::setFileName(const QString &name) +{ + _name = name; +} + +bool WinFile::open(QIODevice::OpenMode) +{ + QByteArray n = _name.toLatin1(); + + for (int attempt = 0; attempt < 20; attempt++) + { + _h = CreateFileA(n.data(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (_h != INVALID_HANDLE_VALUE) + break; + + qDebug() << "Error opening device. Retrying..."; + QThread::msleep(100); + } + + // Try with FILE_SHARE_WRITE + if (_h == INVALID_HANDLE_VALUE) + _h = CreateFileA(n.data(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);; + + if (_h == INVALID_HANDLE_VALUE) + { + _lasterror = qt_error_string(); + qDebug() << "Error opening:" << _lasterror; + return false; + } + + return true; +} + +void WinFile::close() +{ + if (!isOpen()) + return; + + if (_locked) + { + unlockVolume(); + } + + CloseHandle(_h); + _h = INVALID_HANDLE_VALUE; +} + +bool WinFile::isOpen() +{ + return _h != INVALID_HANDLE_VALUE; +} + +qint64 WinFile::write(const char *data, qint64 maxSize) +{ + DWORD bytesWritten; + + if (maxSize % 512) + qDebug() << "write: NOT SECTOR ALIGNED"; + + if (!WriteFile(_h, data, maxSize, &bytesWritten, NULL)) + { + _lasterror = qt_error_string(); + return -1; + } + + return bytesWritten; +} + +qint64 WinFile::read(char *data, qint64 maxSize) +{ + DWORD bytesRead; + + if (!ReadFile(_h, data, maxSize, &bytesRead, NULL)) + { + _lasterror = qt_error_string(); + return -1; + } + + return bytesRead; +} + +bool WinFile::seek(qint64 pos) +{ + LARGE_INTEGER current; + LARGE_INTEGER offset; + offset.QuadPart = pos; + if (!SetFilePointerEx(_h, offset, ¤t, FILE_BEGIN)) + { + _lasterror = qt_error_string(); + qDebug() << "Error seeking:" << _lasterror; + return false; + } + + return true; +} + +qint64 WinFile::pos() +{ + LARGE_INTEGER current; + LARGE_INTEGER offset; + offset.QuadPart = 0; + if (!SetFilePointerEx(_h, offset, ¤t, FILE_CURRENT)) + { + _lasterror = qt_error_string(); + return 0; + } + + return qint64(current.QuadPart); +} + +HANDLE WinFile::handle() +{ + return _h; +} + +QString WinFile::errorString() const +{ + return _lasterror; +} + +bool WinFile::flush() +{ + if (!FlushFileBuffers(_h)) + { + _lasterror = qt_error_string(); + return false; + } + + return true; +} + +bool WinFile::lockVolume() +{ + DWORD bytesRet; + DeviceIoControl(_h, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0, &bytesRet, NULL); + for (int attempt = 0; attempt < 20; attempt++) + { + qDebug() << "Locking volume" << _name; + + if (DeviceIoControl(_h, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &bytesRet, NULL)) + { + _locked = true; + qDebug() << "Locked volume"; + return true; + } + + qDebug() << "FSCTL_LOCK_VOLUME failed. Retrying in 0.1 sec"; + QThread::msleep(100); + } + + qDebug() << "Giving up locking volume"; + return false; +} + +bool WinFile::unlockVolume() +{ + if (!_locked) + return true; + + DWORD bytesRet; + if (DeviceIoControl(_h, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &bytesRet, NULL)) + { + _locked = false; + qDebug() << "Unlocked volume"; + return true; + } + else + { + qDebug() << "FSCTL_UNLOCK_VOLUME failed"; + return false; + } +} diff --git a/windows/winfile.h b/windows/winfile.h new file mode 100644 index 0000000..f709835 --- /dev/null +++ b/windows/winfile.h @@ -0,0 +1,39 @@ +#ifndef WINFILE_H +#define WINFILE_H + +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2020 Raspberry Pi (Trading) Limited + */ + +#include +#include +#include + +class WinFile : public QObject +{ + Q_OBJECT +public: + explicit WinFile(QObject *parent = nullptr); + virtual ~WinFile(); + void setFileName(const QString &name); + bool open(QIODevice::OpenMode mode); + void close(); + bool isOpen(); + qint64 write(const char *data, qint64 maxSize); + qint64 read(char *data, qint64 maxSize); + HANDLE handle(); + QString errorString() const; + bool flush(); + bool seek(qint64 pos); + qint64 pos(); + bool lockVolume(); + bool unlockVolume(); + +protected: + bool _locked; + QString _name, _lasterror; + HANDLE _h; +}; + +#endif // WINFILE_H

    IY>\[L_A +M=*H,T%HA_EQ#JJ-+(&7@E69WBK?!HS*%-]QNH6*$786_YOBQ2D/P9VIK,\(" +M`)TQ[_$U+'5FYSG3A6V=&"IC<"$M2N449*AI5)/CC?];BCXV%52L@/JFX@28N841C7]`#BIZ]&R>>9Q]#*H9'4H3HT@#1MHF +M7YZ'L>C-5#3XYB\!LFI/L_NJ%LLL'LT;8@*>152(F?#J:1W$<2&#KLNX8N@T +ML&9[VL99H<"68!2*7H,!EK)+$M86Y1T/[UI)R"!%`O@T-+_+_T4X^=D)@U=( +M\4DJ%<]$>>X3SJ&5GG6IV1VBEH$U]*L"7MQFO;7)&/X:DJHA(O#B0"2.$R"S +M?-@;-,*;E*PVO5\P-DRY`;9/[@2 +M[B%,/I'FB%I*E"&H`RJ!7:8#5">"_\V^G-%QV7\LF_?N![:S=%H@E#9*U:;# +M6E%2U'F09V;%!%!#`#7O>O$%=/^X4;ZYR56I@O6;T="J-@\YY$8$7NJ<4/4* +M[1>[?S"ZJHJF])CKA]K7-HV[6:Y%"+<2<$N-M\(^Z=].HX=I+`5,/U$)[GAD +M-^*"):<;=O^7,435AK@(9ZC<9<<%@EZW'!NC4\+R(;,V\=,C:"'T8//J) +MDO$1UEHBQ:=B@N!4J"W4*1FOZ]V-1.YG3!W?O+?IG>72B^J*C5&L<"(_%ISM +M?7VAYW3B7+)DCA:!'D:+KB4A4@1@R\$XB57-PY6,U!F:3*EL4(C+L&(2.&P= +MBYE[SQL<.@%1VO,-SEV%T'A2+/?>2A6OXS_H_.>3*OOU2X3H=5G*E"^2G_#PL_R=?VP.2*94EKL/D%3:\7=6&FB_.JEYWZ/0],2S-J +M=:Q>OZHG"S`FF9Z7/K6]0DN21,=!,!I?9.H%[MF>TY?LTPHT=#BIO$*76;WU +MYUA6,.VX:;6.UC\[O(M_H@=,I?4<4HU"-.JJDCS**(I]S?F:_C;9WWES]4@6 +M+6%)W:'E+;^,.@T'F2)]*J9&`/\FF9OM@-IG.S>?_%&)[]HPSJPOH6WAU',I +M:KFQMY+I3/CN[^$BOXFX"LN>O_:Y +M`5!2'(UZF>E^42CN1BZ[H3)<\XLPUJ[&7PD7L475@N3)_A+HM+JNST*02#^- +MEWYD"I'6;0^0C:^93=99Z'Y#]A"D%FF(1CZL[^XEE)?!J;<\(@AX^S!,UQ@U +M'H0$C>KEC-K\01NQ:/0B,W<<"B%5W?#6.73]& +M=5#%CQGTXS)U/[$--I"UY0!C\%\9$"]%>$(P^3I@ROTG&P95:O1[9G^=J@?*@R9@5-_ +M<@!IEECI()`LHWW+#OFOX8S8!6VWFF8]T-BA8[+E/^FMBT\2`3\F$<%[G0+Y +ML/N]M-CC%$46J,&@SM6.CGC[J%T;))7;56U_\J`W(1[2G^4KM2LH[9Y/`M5` +M=95WP#.W+T^E5/Y?SL\Z?LGP=W9$N$^P?:WM)TR7?WN>I&Y?!!)\^"AYNC57 +M%"8+<=1_Q:/]];UY("GLGSI:1F7JW\C-PL,.%U!IV%0T"@H.>_I[48>C:T\? +M)D[YO;5U8!N_!JZT,>PSO6)4`/97!:+WA])B@:19ARW]LPGNY-^'%^>F2S44 +MC0*!4]A*5"2R0!?K8&XZ\<]SH@*2^*_D:,PP, +M/*2T-XP.7"(F$N9^N/YXB$TIPF]_%F:ZTL_@O1'Z*+ZZ=/!30R[./&.:`"`G +M9!A*QZX?5%Y-$'_>>4K#]R4*/#=L7>&E!AS=RA<__0^ZE"!"BZOYO]Q'J-\U +MP!M@]T2LNHLWYSKTEG-&OK<,22^Q2QFT&_9[D4)@FRU`QO#*\OWMX?$ES7KN +MZN*P#2H4NI=19=/=.F>(X9G0Z=1R/3P*#&!G`&?*L/6 +MSJV`+:;LVCL*^#!R!RZ%9F)Q=A]?=!)R[B&`HYLS]">J#%G=[^VV^S;<"\LV +M)"EOB@&[I@3ZW-4.QDNH(>HI2[1/.&X]_[IAQD`VZ;!>2)%0<3E$4B\'DL!4 +M9QYY+*?:GK%HQL%^[3->I_K8_*7NW:SD#@8M-7@(\7O2:43UEYQX5>)^U(.U +M@I;7;Y?9\@(7/+U;]68RC@Q4TX!RB!/8`N[36*>M"X2@7[QH2-6IMN.ILL"T +M(Q',->\87=!3#N3+/S/%(:"]B>\U2'=`K6CR*_E/M?YIKUE0?CK!4D^@]B,7 +M_)TI9[QM>3,0=\)O"\^O04D^T$>Z$/O*(Y4NX1K:.0R6JO>\\J"'7\3@QCS' +M*SFNSJMF$Z$QV-M1$&-5AD)?S6-386YG:BR,*S/Z[CX[LV(@?;RA3(4!+8Y^ +MKF9Z`UUK\5FSA*?!J$!IJVC]4EP7:,BDC_V6R91-1/"J]0\0QEH2#YXU=`!$ +MIV&+-.\![?2<6?8X4Z!`>$`G,4*9_QY)T\@3N/3HK(:]^&5GK4X(:58V_Q8< +M`936BL/5*H#F(HTV?\_TUB,[K#A=6HA:)X@.;&1Z+FC*C!,)U4>6OWV]L"'D +MAW]`3_^7ID$P2A__MZF!4R;1@?5=!`'NS'6,L4EIN8*E8BK^=P)4 +M50UQ/H+!;E^(!A?\>'C3R86=S@5I,P/C2*,)DF][%?5ZFGL/:JLQFEF;GDJT +MX/Z](LU*EB6A+5'($?'[;$A[V/)Q!%@5PB6KTD/0S+E*AC%GL*"7 +MS*(5^^Y@!1D[@;]:Z7#7*%:6H=#>3(>OOK>A!88J>9ZBPR"G4W,P;X..N<46 +M+6'F).F?1/FE]0:S[AMPB5"DDRFSK/E6,?KJ+U4-W=:]:I6WY-`BR^+C$=`I +M;F@ZB'KDL=8;1'8SE3 +M:$B&R%E3J'&@FSI`_()GUV2T+:F/SW-*/T@UW?T!M`SR#CNLHIHLQ83IG54?-:?RVWTXE2E8$I>-V\?F:;_,P4E9]/U&(V+2TBX\ +M--9;AAX3#?M0V%^/63>%-)71EJVT^?#*6J]4%,Y8?&I*!%*'/GRJ1ZNR)Y'T +MKW&!M/*";N_0&X-1RK?GY;ZK"9C]:J!-S8:5;0+C>]8 +MWH2(YX!:OP29MU:_NL0H5$&"K=`K',&0=MR%A!:];=;!:MVTYLOYQN64L-"5-#\S`S\?[[]?N8L-F^+99KI?`)$=?5GM +MN?<9S-XTS5^4*(XM)6IMKZT= +M2_7('\!P1/_S[\EBKM>CE0E.-U;N\E=)9T+M)U];1`@TW#(H+$69R!Z5)1Z+ +MVCS*Z=&&$$RKLEK07C8?;E(T+;VI"FW\BR$54]C`&?7AT+3Y&+AL +M0_-LF&+7XZN/H3N.G@0`B:;';MT'368KDS5!+"-KRV%"K[^,(F +MZD&"%A/"1'7N)Y[*3"S.++'/H_0#@7"=%>!D6ZC]5=4:3\_"@<$(P%) +M=SW!M*P+L()5_J[A\#CU-CGIAC\OPQ#!8<8239S/%)_U/`WHHG?U(N#&P`U* +M#2]*RL:^M8J#8JX]IJV5BULX+'FT&I\;+E^5-_/?`D:+3O[4^'*7PT'M_,A= +M:#\ECNN9`"^86J#IIMFG57HQ<2EHG`!@$6Q'G&I3),#&F[3Q4`D'X[ZCOB(T4J[4H[:D]@X: +MJ8[QYYP+-&1M6I':3([Z(!NW7@D:.JT"K%,ZE@:U9%C*R+,GN$R`*;]9YF* +M]CMF'/FLS0,A?BL;*8 +MLUT>5($%P4JO;D4.*HR0*-K7K>'FOJ_G",PKSU)A0/5TT6<2L6#[L1::YJ%. +M0]+UX=W^*X0=>"Z![2QA)JYVDKHBMC5/+FG1U)[A_LUQK[),U,9/U>?T.Z`V +M!CQ^`M^.YR_\K2O3D?SQR4`J+:YX!2=6*0'N@E@YZ+H,`[%2ZVHSR"[YU),1 +MCD5TP,J/3\613.^ANW];?U[6](NP+>ALY%GP)HK_//"0*5.1:D=HX6IO=!;5 +M5+KQ!^&.^3A5:6)D>#40-^8C*;?&@FK0;Z>`^5INC(%H'/E#&4MAP=7H8@VT +MD*KXDW+6]7\`#3_6GFIEM-\K\L7WG7'C`8S +M/'Q"1R@I5ZE!=`[VK\;IL,=Z*CJ2DJ(B^CE82G0<1`WXH>KHF;CURSPB82=> +M40&)M.KW'C8SM6HSL':R5\Q3B1$^,53I3"+'CC*@[?.,#.7"Z:>A7,9'AM!? +MC8EVKS_Y0<@KQ9VZH*XN$PC?[]*R)E$`8*6UX0%#P7MS@=-VG#*(6^@K6A7- +MMZ3808:Z.%!/PK@["(]U^^G5@V0`@\0KB/'L#2_6D>/D38QXL%+.=[IOL:_7 +M5Q`OHK#O6-0-M8FVE^],'(-V97OT\C0_!CI+FF8W!0M<(*Y&4]Z16+1?*=S1 +MT4XB28+9R?UM=&,82LA_1/Y(JEQ@J,$<*LG+T.`MG=,35G4UL!O=K4L6&#X< +MTI?1]-*Y=4.O;$%A2,.8A"C[C$$76,GJM]E-%S^7M`5XKK0XCL^Y&)5$ +M-NE=1!BSGXP[S[RP7R'8)M>4EN[KDR`[.(,T"-A<`9IX87^5AL89Q='#)/C? +M"$5EW-.JQ81>!*E^H"!!"5R)2CK>F)'I[SB2TG66@!_'*W6X?D!V%F)H#D7W +MD/5'H'=H;CGZF&B.\/H%R)YS67K"5LL2>H2:QOB@%M*D`&JI`8%+;+5*-N +MD;D6(C>=_8`A>8<22XJ04PT\LHY28@DE`T$5DBV5]7>.PNE#+U;YLP,"L[[1 +M-+V(W9YN$H\_"'KJ>$D6-OJ!1S_?JY->,+Z@Z-R'5+M[T>GY&223QQA336[^ +M$#,-5* +MLH^715V1@Y;O463D"MB4+N#08$SC4#, +MFCMGH&UD\0@D+C?)#%5R0YCNL,+U&G\AI#/)<.,=(HYVS;U,9FBQZ6%,W)#/ +MWMH>J,7S5%'<$A!EI+B6-]^"V!=U=.B#I47T!3)G'.&"[)T:VEG/(^-*W9?.@?]-Y2.(>:V^LICJP"%+7%O)CB[I.-G$7: +M>T+;25TQ_C_]2)E3V1$9$0S_D!/VF%4H)D`;$Y!!`>8/M<<1HMT^LJM"\/2R +MRI)EEM+JLET[Z]1UZ>\MK/7UE'[UZ8[LOPZ?:NH,0T;XZ/42MDV`D@RPO7.? +M\:WF@,-T7MOTK7Q_I6M[+0N,N:]."D$:IEI@#1N=,X&\*DY0'DHSMHYYNL*K +ML"/LI/(45V?-?+'UM3458Y%6*$8#N'@S'F+SWCK3J:A> +MT^9>)[D)F4A+I<R3^CDR;S.O#+)OKR",:Q4/3_>(P4/`LFW`76F5V/'^6C+3YJ1#R=!; +M?TZ8'%=OJT#Y9H76(XCT@ +MPGB^.7%Q^QP4[]>KMP2GG<%('%4;7`O\)K"BS)BW[&0&O#&+OS,::=2Q\;#1 +MC\]+E*3PTH5CO3!L;$-YU.60CW_!U6S4&-9V_#I0L,C('OCGY[VZD"EC`:R[ +MY`;3=!SI[C2&DA])R[00/?##L6$LXEAVHNME-[W)3$+K*+JO<]NM1U&WX:'X +M%YT:T1+?=RNU2\>4T.NL)^\.KW?,$-0<1LQ3EPRO%+AE!G1YE>=4E!+;[`\R +MAFLS)=;9,E[J"&]$U3O=['3F1XBE#[?N\YU>>9;3:+DEGK2,JQM;"7%ZJ.&D +M[I)WVOP)3P-3=A0$B;Q&(%II5L4<:,,#JOP>BAG1T^24A*E2EVI$,]78"WIP +M[O%002;?S=#,,KB[5`$2+T[;>S4&^VGR-8G/I#UC2 +MBO&8.6&^4N4)86\0.BB-0>0.!YK]5E5+PVW)I_=5T^^\#J;`JY<85-G:)%*9 +M>39_XLPQ%9*HMX,GIWG#<+:3I%_:51C`I=)M56UQA)KW,NLB/P:Z9['W#ZD' +M'Z<^\"/D*I62$4L17#4%WIZU/LPJRD0";Q^5Y1^\H``"R5N`2VZK][S/CU)= +MV&:')YE*\31UVD;O8O-;T9GMYJR#X0`3\2'VU*J@0"$GC?2GN1MG5-'(35$; +M,A^#=X]764"N?@D$)^D44#E%?&F3P2?0HJ%>N&0L6P>O>-KLXK>E?O`;D5+] +M[HN#II.0)?OO08-ZZCY=KM,UJ5GN[LPM+%^0_^3JSPO)LV +MVZ/V"(K>#*O\Z['3`W%9J*H/=696XL6YR1,<**L^/("_@A#B>SE0@>D)'DUA +MIQH%"$^H7F=3Y#J24WD.W`3QYU>#UO<3!/Z3.3FLKR"VGKZ`4-H.I)+(O*=1 +MT+IPX$'_)J(*?(`AKO8^3.B>$QDWN]4-;IL$"/;O0*R-Q86% +M.Q\+T7+;\5 +M;-"+X"QURDN7E!KQD>'';W)5,AKX'V5GJ$8YL:3&]M4GDHAUF +MT?EBBSPN/HG)P*9:\J.B(R4@4=7T$!$CG6`AE^V['17WN16YI,`_,<(C%*K7 +M;+E@?8-25AM_7'"!VL#'TMYX]SYOH60KU3A\U5ZH''H>T87.^,_(GP6S_A`B +ME2-,*_G=JWUIA*4T`.][4.FE[^51R>.YD +M?^V,N/;%Y[-`5[UKW("==Q4OXWOGRQ.R_P4V[2&W[VFQMO:.XF421D-O,0.G +M-6Q(\OIU*"C5!?!P:V46L^.IE]O%EQ8!L",8XB;E-.-B?1O%`5$1GKXW@)?=,#3/<6&Q&=-M$N>G)GQ[(GQMIEX?,G)O0GJI1Y +M2G^FMU3#"EEC1.9C/9B3F=OL7AX8O&:]M)(^^2D$G\C6E64S]4W.G*RBG`I. +M@,,ZJ@89*4WQ(O?QIKF&X#]/;YGYE18D:T7/H?L)L0:F[`._Z"DODDE?.V]7 +M5C50PQ1TOT"=<(D5*FSH^^)D@>L9%J![G'OH%TVP,9/0`):&M,75)D?'LO(M +M1-;[A$83L3OP$DJ:PG<$/OUK2%,"NF[<)*9<7]7WZ66%C(.J$J?L2N[7^A%4 +MM_*-79QHKLQK!,4;7N^DD38&")[78FX@GJI)%\A3NEX2;F +MQ?KF,7Y":RD;(%@,X&/,NE=Q/0/>?4ZR"5?<+TQ.[RO^6"TGY\, +M]X+#:;4\-41?.,1#"_/DB]*J$]>P-1Y3RZFECLCMB7R&ETX+L^NA,87/X#'* +M@QJD\FVK0$OL=!H;Q*XIUCS!4U_7P,B1%R#CL%S>NX8XVE0`'BC +MG4?G!S:)#EPS'85_9M!LJ?QLA&H&4FZ=@K-FP,?D\!T\CR@8&0`6]?F-*=/7>N._J+7]U`VZ8-).OS$!IADF_(>@?RI:D[R`3@VG +M=5KBA,\S1))C?$+Y@A/X9+T>`<'+H"]&KD$9JI2?8:A*9L5\9']IM+T)A)A\ +MD.EI-6<"D?&/6U:L):2'-"V4*LB;"PX%36IM3'CNG(]OGXE(LJ5`GD`"<=DP +MT&?\+UNQ*G7-9)\8%EL-;]"UJ9+4+NPTET87O,DV.:^?Z>J&LV(B1#Y<\^8) +MZG-L5`XGI?5%I_]1T'<*\Y4\@(;0"],M6KA0&$&C5"Y_1-Y_3J]5SCO^MWZ& +M:L7`^_?@_L/E:'_"J,U`5WS[,3=ZHR@3S`&%9<#GKPOH1%1C=X%+6"H66)WS +M37YS6EP+T]8>Y;^E;!.[H$<,-D)1A-@%:>1U6R;J6$C3(?9_:4$,+ +M'?DP+86H$ZN!J2AOK`>/(6+M]KJ5(=54-:YYWOS2?D?J<\X[2>![F5\_5_2K +M5ZS9ZF,@+_IAY7]5\3%WH\@HRM./,P:&X!3H`=!)?$\ZUTL41T43;]:1R.G2 +MJHYOC;UJD_*U0,=ZW@3?W'@2>.S0ZVI29R*Z?MB*KF>U9VPCOGI?FKVW +MG#DOVXI%'!B,E5YFP3!1CDC?[8:4,8.&FD@721M*QCZ3F')>(4%($T0C,W^J +M\SR0R?RHM.J^%PL:Z>$FZ^.1O/49+B(9&%/Z=D].=H6WLOL +M]\@G#JFWBRO;7ND$Q[9^/2'GON$E=O5F)F%%T:6:=#43V=CTRJPG)][?Y+LD +MT.K2.4>4IXNQ3!.ULQ7=DY=HH'1`=A"59NIH2F>C]2\D9DT\5S)A#,'[X'/6 +M7:6H2W+L:K+F]X?A`WNGY0K1NBW7KAWLGR`W317)+ZO +M9G9A-&<@0"EI9!S@BA1^*,W@^/#6/(1'NFK@36;OF=7*]==TBU\!?>PNM>2G6#Q,L'1+3[MQERB%MS) +M:\Y%##(-P<'606QE:<'V-!0\ELQO83]I`2I1*_C^%@?VW+2\"GB]'&-53O." +M8(%9^N\4`6`]D\XBZFK-KBUAD":H?/Q'OD;DE$#B@#D+>9)H)!92IMIVQ<3[ +MS_G,"B;X`$L&R9[(J'$=7&],V9$;UV(K0(\%CVU!)F;KPEU#>ZARVZWX7@0% +MGJGN#R"27F>D.N2WP'G:RTF:RVW%#RSU.:M@#?\\!D-%+=%A3:1>N]*:AH*/ +MM6]+HZ<31SL;XC]J7IK#:)>4KGHHXVZ6@#6U?)*O +M>%!;;_\^A(8J!#R3+M8'=YE6<4P;;6$TC`XZI@F'N*P`=/[+/@2Z3FA6E@_) +M^@WA%D\'7$9W]IE9D(Y%708T4*/5Z%D]C&M,@_O$<^%*:*>\$,'?<7W)>R*S]!GU +MG!K"67!)I#@)%&MC%'2C)'Z=EJ'(US,$@:N'0%:(^]THC8EL\Q!K/TX-*'@G +M)0B%F,EL1B?7:47Z*M-.E^8=[)N6&\W(NY8M,.@(L`NG8KV_KH@CSAHT<7:" +M_LGA;G=A9I^)(U`.$/M;Y>;!G`?\<78Y_Y54[H.#("0: +MJ'<=&ZNMN%#!:/=/E;_@;G:%RJ73M/&-JU(?A&3.$<11+Y#[$%Y5BQ9:DSUR +M(%79+<_J2GT^/`B_!*_7AG^8!H1@@^(#M!MO"0G^P;O)(5J;-Y7OM_^Y1)-> +MZL:!OA/(`GSAGV:KJ4&T45;M- +M=0TWXWL:J32I)U +M+GIW:0SR9"JGC"L>1M+<\M]75(WQ::D2W0*12]]M72Y]7?;&/(D'!K'FYL(X +MYOLIV:P7M];XV-T':BUP'WES(17$K%-W:CR5];$'(7,1E9B*KG/M[AG==QUP +M\%:%/%M5JFF?11)W+Q)B_IBX8:FNB[H541<%[BDIM?C9'SP6U.8]HFD.GQ26 +M"X47_@&.R\?3(R]Q\0Q?W&^2C4M7$@UC"ME>9'KDH.=$,1Y)(KYP6M2M)5Q1 +M5U1DB;T%'R*3LB!9=(\3=0-UXZ?'6NL?"X+[JJG++`*+M=I_GJ,Z5+5G+X[L +MQD0RW83SE6`I"%YK+?=]0*_VG'KU5!OB/#C?D\M/YL'$D*NG3Z8;C7^5H9^H-7B(-)OZ&5!;`ADJ%N]BD1O@[2 +MB^N/_DM>2':)BBE8_VQENL-/>S><7]]P/8BO'\T=1I)?H=IZSGCF=H94NF&E +M[+A1<5$KT3?Z&VZ\!0-"0I-\KVP[KX8)0#3.6GVU*MFN2[!32F_Y23JPAIN +M*G?ZA"PL@2Q\XJ_HA"]::9K`E_L?3F6PS+?C#"^(\Z5)K#=6E`"2_@_ZS_T1AZ&SC;80L/9I%E^U'_AS&&J3/86DV.$M'9PJ.E6) +MJ/OLE%=CXP'Q84S57$VP8:\1[D.63YGWSN2MOK9D@:X%ETS+Z=2?J^YD,W"M +MP0T=H%H3-E&!Q#Z2VS#!^/U\D4?T_QT,UG;?1Y[`G!;Y;V,-&VUO:_.3L8'E +M4U]1SSO]'(]M)E+':W.EEEX4EA=ZE"RX(XZEIS9Z+9K7=IC."!+BZ3I2DQ_G +MUK$M$.4,$&=?$]8R`(YY]NOU-URQMH=IME]9LP+:RII<#EYL[$@[]V`E4/Y+;H+G/-[ +M54#!(H@"))?@*^M0O"@,.A*EOSOE",,"P5XW^U[:P3[WYJE4`!$/H"$"Y<088UIK\P@$ZF@;UQ&SFUT`X+V>"8.AV,OZ>CHGPK.RW'FPV2'D +M27ML'9NS%CS#@3K!P$R&^67]V\,RJE!<2ADDQMG-!T,5T9M6R,71$N^[O36$C?T@Y""SB/_>^W!0;GQ">,P +M/V37B4VG"?\0.PR5=[L=R##:D6`0]7]3X2WB09I)@@]!X6SQA/[F#BFD$^(9 +MF@!,`&7A8DP14/-YE/1$K!%*>;O+UY2/9IX2@WT35L##N$*80C>$.-*-$`:B +M*JMQ:TNT_'H@A"0TE_@+OJR%]VO[J34&:=L4W"'-Q/T]A]_22_^'?PK&QY_. +MOQIHY51P5OQCK^KA&S:1"^+763YYM@2-(O]2[D`'U+QF$>-/PG,N<15P3BM% +M69@0)+-_HG4&"8'5[ZDO&*286,TOOU$JIQCO0Z3Q=1NR_G7C[50&Y:1J>1_Q +M1AN4]L$5$G7_GWE7##C[D-;Q]6NX$ECR`FP;/4F!)B^Q4HM@]5AGLY49A7YP)XN@\R`[1>DX[NM?E?WO%*Y_Y?O[7->4W2*/+-EF,\M83B^#S;/]<&%ZD7&IB2S,Y) +M31MM"-SF(>\PT@$ZG5G<7*T$T)YUWC#N^"^B2(8[22*7T5V^9^[,C.*EC=8= +M0$K2FL(!>29M@H+XN;[UPT2VHA<=/F1F\_W^3TUR1J_0C^_2U+[:=K\#10-5G*R%['R#JU?*2'L8FGS91?4_J(_!$&-[CPK3PE!Z +MT@+M&[2Y?+E@!"*&U:GP;@JLT@W3NF-@'!\.6'4RU$'ZP$E_M+:YY3"H>GQ? +M"_SRI_EKLG,8#N<<0_OP"QN&!%"K%<-3TS&MB27"].>W4P,\Q3,Y=9VZCR5< +M`-_Z'TPBRJ((X9PMJLK5IEL`3M_2]^V-AX/(R)A>FQ`VPQ6JM%+(, +M%Q9]$5WVYS,0@8R0O#9$5]LDFF-`N6E\:"+<.2FTNEEH3%-\$RH4,3J@A+Y[ +M[4!.YB=3**S\I;\A"^>4UY1EHJL'-#>0RHC+HU4\/]9T<5.U1Y^W1975!'JX +M.O#6OO2T\``27W1CF"?1'L:=:FP!H*S4KGJ)E2AF]2HV@NWHX1*'K)U!6HZ! +MJ_Q%`A,8E]4'N!P#J\,X +M?5?J>GO(^+,C'F@MK#D,]M+X-0F.=[3KF,(K)0!BGW2V@D9_H.B4LX;,^J8% +M%AMUI$DHDDHG\+48:19$5?IG9W#>\WB$N3/F<,"1,&21LYE\,=!LVF2:?YJ]\"61UQ&`PKHR +M9MG[#3;_0LN.EM79V132((^9EJ_VETP802SZUI-;A5916+(>XBY,F)E$59V= +M-ZAP;&2V49D,\=]20USH[93IAP58PA>?-RXF(_N2@09A:9C@?LEJV"/GARLE +M1>#0K4R^RO]:86[2XC'SB#R+NL_P-<_=*:2@_*.[5+RG^KF4/0M]4U#V"U9C +M2-^;T$G@H4.UGM*120+VF,`AC(FHF>'1TW54X^=$6ZV` +MD@OL8!#^CFO,'Z)90*%`9Q5HOV%*-RUBH*LH/^'?'>I+VV2@I/L-ZJ*4^R8-6*$\T+'W6;< +MOU&"L^E#R_!8J_\V'HC%R;M"K@YS=]HO9+A_ +MMY2H)6LHZ;O_2`_XM)3S\Q-V=8%0/94HMZU_PD#&DZ@LD-^L6%`#SBO5BU?, +M`U@3!_"&I$A4&S3R,^[Z=2<.SU0XD(NFRK.`W8H=/:5TLO;?&"`5B[ +MQUA#/M>[&B$R[V'35M$,4!6NJRI3EP7VE+MNZ2&.C-9_ +MJ&*0AH"?CS#F:EV@VX3GS^K`'B->/)CPWGU@&F#U$7%@`.N:<""Y1<=>$-Z8 +MZ76$%09HT.D2@;AV(L>*4BGT\":Q@>\29+/4!YPKU)HB>?[31UE!Z>T?"C"I +MW*"!V]?W`28`PDP^R'67;)=6=$DCT<8$CU6R8&2];-8;;=3^-'%![*-J/PSB:Z%=*MA#ZISH +M<5$Y=+4M_8)H2#F*]"8Q_W8SF6ZPX>AU&L%FJ/N$$YGR!XPQ0(P1,-3T-11N +M.[RRO/1\UWUN@!.0.3$O_VT-F1P?'9L2`_RZT474/G=(B!;AD\"OCU#F-(V) +M&P= +MME;IJ4T;DK\-/V8LA_S5CMX1J;_<;+>!%$\W3O.*,(G'1)/PRB@[Z^M97!AZ +M1TQX-[_!1D!60*0G`P259&@*S3%?[%PO`,[,1V!2[W8Y +M^,?JX5%.:YV1IUZ2A\$"]?YHMHA6,.FJNK/=2+A*Y;.3Z81)'I*@0Q@I*IOM46,*=CI`I,PC58,AW:YYG",Y(6\8^C$RA +MN2>6>[,VDOHB=;-VS? +M&+55.G%=UB8@*$EPJMG"]"*#0/8/I5V"4FJ9)Z(34]?]1FSK7=(-+.\,C1]DB^(`IX+8`LT$YXF\;- +M$1%8Q]H:932D5?2)`T.-1.FZ1^OX88%_Z#1QAI-6475S^077DI^'JV881`#V +M*CC,L4Q@I[R_GV<\J0XPBYGW)4[$6XD9B\:OU;*Y10O$!')T3/1P%"?8.ZS1 +MB497$V)'WZ49UZH-[L87'&LE4!JS[L]OG<2B'NQVRFL@,VLL_1H;:V"U^$I+ +M/1F,!6:^;)1[+;7$MC%E=;+TUMQ_"G"6%7<_E.?XN:!XJ'7^^#@(SS]YVY@) +MI_9G2M[M`J!1RI`9PK,B9N*%A`4M"'W=H?9$FOWFA8P;[]7=1B[Y3K8[UAZQ +M^(V5HYH"_M(.%Y2%1G@@/-PVXI_`31&W0)O]-_ADK614ZRA?^';YO(;DE*'U +M/?1`BD]Z#A8FTF(&,#6A58LX0R^>TKD+J:&C#2$_74'VFZ0H[;1 +MCMU1>S$(QCQ:BWE7`8S\Q&I'A_NKTOH-9/A=(NAM=S-7Q^D;+_M"$BYH0K=N +MT$KP?E3#Q=7[(Q[3:K9Q=#\&Z$4AK*)=T5F_HM*7[*K5!NLBW,0NNFV3U*!W +M">4>NW4<]:R\O;,2&?"K7-"RP:::.K?_5-'QHGG][P$.O."IJRL$ZW=2]+'C +MN9!V1P!+8(BP8C!J^^9:IJR1!KC;3/KB&>4IGZ[I)2FY.";&HA%Q+%>JX;"` +MN)%E-]H(MJ;L^=#^K?=5T4!*$@"C#]!<$)N+`Y"4S1K4"*/1I3SCUE_UT6.. +MD18L"CWD`1(D@+PWVB2I?U,@VPPZI^EK3N).[I8NUQZ31`VB73-"G:M%V0IY +MU00]R-)@)EM#4;9%Y;$V;(T@OY-)R-R[@T`L`6>^X=O5+GYQ%T^I]V +MWG#7$P1'4B?R1KG43^IZHOF;5B%)DZSU2*(>GOWI3LV!+039^!@+A$'EO!G< +M4VMM10[5!_RK9X+_A8]7$9GC7]V.6OPT;0`3^B&*.\>.NB\=O%A-%T]7*24M +MFNQ@:/Q[^1\:@0<+I_X`:-R0##)*RK4F?L"[C&2.<":97#^*KMRR!"M[NROV +MR*GH;"T:I'$E!=547`?=%_D([<'.A79/LMSCV;%!JB@-T>+7YF+8\Q="[;35 +MY(N[@N=PT94,N?/2MDUFO=L_I==T[/M<_8*]H279\E#F2+#B8$7E#CO:N-#R +MKN(-AM$FL>'$=(86RAS_A(Z1:AI^IKM30%AZW6B?RJXCK;?:( +M`%C))V15$=G*K_*]AC/.OEKI=*5D#X3@7'DG.Y3;?]^)$"*1YAE0$A]RBD9C +MD^)63AP451A]VE03P$(^'[@1GL4"_9J]2Y5DU\X>3F5/Z2\?+K)_2M%8@W^# +M65H0SG';L`Z?"X9NT3'CU&=#HTT.N>-PP*1M1U>HIO,-D&U2`_NGR0EM8P0K:_OZQ\USZF`UC^ +MU_]7<":+UE'/$W.&Z4/U(2KBD!-!S+\MIQX6L!=H?[R_N-*C86/@T7JE<^3[ +M-P-D_L"#XH$W07QB\TYMA:)39V4`HO1@SA]AD4>+/\3E-"M9\E<7:^8@N=?W +M4+07J+_$S&'*7+;2T'HP1"Y=/XC13XX@`:!`H2YDW(R+H%T/9"!FP@0MP?C% +M)VA$$!)&[YY$,^WB]U0ESWAK&$;GE(U2Q41S!]+],)&LJV]!FR3=C-Q#L3`9 +M8,]GSU6#G'#I)Y1;B+E.AI*DN",*[H+'G47$&\2ZNPQH0@"+4:]5SP"4_0R56/C75PJUG45L02\8]]]ODG;][%YMDH4 +M+WDQ([%;/Y6?@1:92/1H7):("-QA'K(*$MYC;U,C&*H(#A_"P*GX61S +M>)J2WR\>I77Q%.^IUB"V@^I0S=C+3@HZ<)WAXM^^<0K:->WO=/G8E6`J.HD3 +M%8$4818T-,/RA6Q0B.)I:AV0K(\9O#B;-LYS.`B[[,"*"R<.&:,CW"=].]%I`2&LR*BB[=(H"L_K/KX#PVV%^>VT-H+M/M?]X +M%I/FQ5\,M=I\<7<-QX:,N8ZJG>)I'280QN>2WOQC!8O[T)U#0`O:8,Y5;&VV +ME$0+/JR"H-O4:XZ1,M@%],US]['@7(*I!`TZ(>R1_3`%,U:I;6ER*?BXX.S(B09?DFJ=4*'#!]:&M<'Q)X-_ +M&O=2AU;NJ[W7JF>LQ)P.70HL370-11X5#!(-P8HHM%'..O]$7QM#V\;DNS%% +M_]OXLY1+OGVUPO$_OV3='ODD"J)I-?)PN]QIP."61E,59\3RI8IDG<9ZYSY% +M[.67[(4P+0H8]PC-VU'JNWX6(8[U4QJ-O& +M8=R>B_IECZS@+UY6Y/U>)8AH00_<>72&NOQ<19";5S4@D",$%@>9=E>R1[LC +MO#\I>MV/0>O0P^,E"K8I;[?'V(L_G@ODAG.M:!%2+5+I$`0?;S_[%TK`X2JD +M^P*R:!)X!]NS.2_Q&_-0Y3@WMV\A+9.+CM7PR22&#OX[O6*?F +M*1K*71G6EI8^HV.BN-I_H8XY#&\CP?9V9>E/0")\@:73R/[ +M"F.2&(WKZ90T@\"*X_/G\+;%-\N6D*5I\.\71DHE>&C6[14`.XGHR-O;>SPS +M>*!)?^*JH`16PI[;YU&6V=N]`DFQ]N-VU4J=$` +M)(>N^SN!<>>C>R\8;7NP6,O9BND!$:-;.6-2V\VC(^,-EFS(PBCUW11Q)F?$49$?.XBQA +M_XJ`8JN(!;O_*P9?4:'9ND`\C9"([*9RR+./*-YO+:(?RNDBW^7FRAY8?7ZS +M&9#F]+[;LVWLU4W^QF[)7+Q#17S$!*3,(%]X9K%!I7SF_9E>"'G.!\'(P3GO +MBZB60T?WH;1$LZV:ZKU7F"\)T^/6%=5F](]^E@M;6K&YTPF*,^9MA@,/OYM( +M/@I:N_;6$3[EJ6:C^!KY0CC!CDJR2C!_Z6SV!+PV3,"[==OK*WXW7<$@?-,9 +M)F;9%^A?HT85O-CJ>%0OE9!DLPIS4K>C4+&>SA*?$4[X8!.G&NG +M0M;WFN>1[]![]8)2V4[LXNT\P31K,^?V#< +M((14)!&PV:;C^'S0IS2$36HSJIGB9#9J<+X!";:"%/TEXE#L<5/EEH.I?/Q_ +MPIMX!78M!14N,H'$/ZR +M6F>%-6TPD#[W<'<#.[#.L(?%9'&_X,)HN>#7`A%-T"D?/XM*QS2_UK"MY>E4)K)=JV-?9P><"YYHZ(? +MOE91PYT)FU#\P*@@&O>-&8:?"VU+"*V@/2__2S+LYGU$ +MDXHZK-8H!\E+8-EE)'.@Q\#/(0RKG+UU;Q#9A&FUVXI$O$];-#+IV$)&"\Z9 +M-E-I+OE?28I=@08GAQ"]KEMNR1BAS_N:$F#:;:,)G +M&+(\]#;!ZQ.Z59(XSV``7U2-,,VG69Q__/7OE6+L+\"NQX__VO_%.,SPI?$F +MEEJ0-1\8)N47EP,LF246LG]E:\'#8T`($W.6*A^A]C_-`/7CU_ED;F@.]VDF(K`M +M0=]I[IC;VMUYO/3@,Z"#Q`U^]2A,G#;WPIX86\^OV9/"T;.9I3*@Q,[5$,6W&L;;`YAH[B?1@\F@M=Z4B:KC`T*]7- +MG"410*M3-7(R6"OW1ADCD3*_6TR&JN=?S1%56:O0N[>P0JS6'2.Q"("DG)P^ +MNEE"E@Z!NIC?&8?E:P=%3YCV=P>9VZ6ND>8F^35FJUOY#/,-DM@.L"0WUO@] +MDZH%'P-)8MG6176;>IOOM#/2"QTI@9YW,^!4,SV_C>]X_+Y>8,-"L6DV)[K_# +M)G.M>.DE5G]%=M^8NHQWITR,PH<*)N)D$'F2C0_YT&U'^;#[?7#V=:_MWKZC +M^4R"RFBG.:7_^U-^5=\]L;8.)SNZ\04/[BQTJQOD\1BH`[I$B"5TXW +M&1UX!$G$B@?F,X39M`T/+3O+ZLV$J]>+MVX0JZ'*L$1/%>WL80E^7JZLXHS% +M>;"%>,;#]!*7$V70%1TWJZ'6N>0$C_TA`?TLJ3$'6BGN(]2?DM]NH[D[.!,$ +MGP-$!3U0YL60*ST"=EE&NQ5,+Y\9;/&,<_)_3WWOX(PE^I_YJ$3M$,>^@`J] +M0++!/9E!S3-GH4]%*';$F>+OFF`K.!L`56!-=%647O(W8KA;S"'KR=@)O5S1 +MW1S8B0MY#$@3G0=$R6$R>E*_;26UE7^F\!\8L'7O,J^\ESJ:)HG*FE/M%QPM +ML&M>Z&+>+)]U8DC(IT=^1?U[==9PV4[BEJ7QEWTJ_VY".R;G37[9IR;\T@\M +MO%)ANO_1Q2AI64-G<3F3X8QA5PO'@R%0#8$-0+:S-O0Y_E#JMF7,S>]X0$\\ +M[A>G#"!ZDM&)0J?R3V],,);DSP1&;[]P>A8%LS4;?T;X2WW`ET\.8XRSR.OQ +MS@:@VD0D0P:@(./94H'12FA4%NAR6GO"MJU,%HQK$Z7G>6Y5V5;2/Q,%+/U= +M73S**(-ZY[I^PUQ-K(S<0M>I(OTTR.\6568B:;+P$X4)Q+!'"CGZN+B.):7$?.1M- +M";O%!HHDXJGT^-Q39B^]FR*JZ1Q&-M%YG+$0.?]!33W;NEF41GN]D%`"<%)B)6O.FO` +M=?^SI?02;!>-3H3.,!QJ*:3U:-X]WO\)O:T&$`R^JIFBN2Z:]X"+$6(F%5K9 +MW_-+`U>T%4#6T*LN=-,1)8-T-(IV!@KXF[-;<&L7`#37/9ULV<]S04T'E*9U+^^L^1 +MBD[]*B;[R`218'6&2B2J;Y7__+F%F[KBO*V=]4)RR#'6P!PQ%C(L8G-W>IL@?',"? +M7OSZ@LL.FV;8W7>!?8OLGE/[;:-4KZ'Z?A+:VO>N_]\98=P"1?,";<_D#?7) +MH%8::F#>/IE5__@\L4<][9L*<8F]=>ST7<6>'M?*R@R=[KL(4"IY-=A$8,PK +M%]N2BT)1<$3J)P(O_+E&73N3=6]/]Q%T(:'X1B<]:)+WW4L0F;T\PX]M2+R, +MTT$I,YRTO:EX&NF9?31$?*2`\("G-N;UYD$CC$1R)_.F#34#EPXEK\2K4"@*/F[)=!H$2D86BH[:A?A\ +M/A6:7;H)-&SN5DQM71CE9C*`'91.4=3EZC]3\[Y&3BNCUZ'[>/GTX)=E=.FLRD$)@+4=ZHJ`M[C^`_J=WJN>]*L1H7P?F!+3[=<]*@ZY3QG@9_O +M[28AQ#M$))D-8OEN.7X\_DAUBW*;_Y'O$8(CIC5V_'O'$._P8#QC1O98'G`3 +MO'8&[<_)(%A4OJ0R:AA[*XG:/.*" +M/<4R#V=W,V+J=N..<;AP1HFFR';0CC%(+T4I_;R5Z.A!W[LQ+=^K\)J8>-T'<"DZ'.>I6XL+T/,2/MLF81+J^$EEV +M1/V&+JX?_?M)*-JGARXI,U#L$^[0(TWM05#!4KZ3-N%;Y_*F`9`1WE*/.10C +M6_G).-/.J)65E!>3EDZL09=A&IJ&?!N61TSOC&MMS1WG=X8X0(<0%K0UUDSU +M&P.X_$035BJ=E#7LX)`/554PCESNF14YOH+%N@JQPU/,PZKR*`3HPV'M^M"< +MWG@_/#099T9EI6>/@-ZM2*VU2V4Z9NUZ48]J,/?RW4;\6[OH(7;F*#P%<`V4 +M"N087*O'C!;*Z*"9U%,A"X#OBV$WE8ZS_ +MT0-U6FW:*49&Y/B8QFK,&,\2&[\1'S6FLUDN)3]1ITN\8(C:!LZ/Z4KX]`]9 +MM)>^G.%S[_6T>D)F@C-_K2DYLC&#`A*6V#A-:[8<=-+_Z1Y!"P\WM%LD"\BB7#32:*LPAV#TJST:46Q+;Y[LZ4-*B4[\$S +M23NZ"ZU()&5?J@+]0-)V/2!G28)^VV*;Y##S#BA$-(.]*H +M=,(0=4K9.8>5[&\#6F"U)JN4O##+6>/PHC2.(MP:1_X6B&I3A5:F&YHBL'XN +ML(=]2=,\K/YH^Y'"27ZB'K<@20QWQL/X(!*"*;]A4`@4< +MA)(ZXZ2X_9=I5$AR5KY#[M>\LT)0>V1>3(M;Q%H1MEJG'=5[E14:P\?EVRIS +MS[*5%H73O@N.\[BW>V3,2A./A72M0MZ(H8"@C!SL<`["A=_-K::!OWC"BEI6 +MVIZX#@#^)N4X7:=?D>UCS/*VY8ZY/ZBPW88MK"-1F,PU+9)GQ?;XK4LW)63@ +MDU%@$VD)_MG@2I@F^[*SZ\CJGX)0P5)Q7_Z%Q-W2NV8X>XOK:KH=PD\4..H& +M[+>!C20E(19_]A?>^W/SI5]EXZV3LM4?WW(Q;HJ/&@++Y]''^L#_R02*9,D< +MOI(`=O(N7=A11D>$]N_3MA\!;3+4U>^U5QIZ.A6D8B47=]Z:2NS=QB4OU=!V$`EF6Z+4O4@9R,*_DXR@;D>2<+TC7.>7/$_D,<#6 +ME=!I+LVWW?E3AFQ.RFVE113^"=`6;6Y@WP!S@)!.FFAO5TVZ>^O69=Z<3-P\ +M8QK697]:^<6U?)?WAI@!052IT`>]45#UW1"U>=\-SC?L6%QDITS/T[*EO_R$ +MQSX=>LUD^$ZJMY&:<+9JXZM-Y@%'%JTZ*&"MOS,9(W"JIJQ97]_D]F^&3E:/ +M8!&-@TET4V=ZG2X.NC]05B!%.U$):CCF4>]TNNRK:(+[_Q^&]XSN]OEHQ**` +M92\)]K'@S>NU*RX$+(_)+3@*WSNJ"JKREPYM3G&:X!"`!A8PT(YF&. +MW+R=(=I#$OASUD_]!;#F=^"P8))BWA''L_N7E&IQUMN1"TS:6@6U]C7;U^X4 +MZ-25($[+^,V&\M>$ZW1#%%I)Q53>S(KCE6![B\#B=N`F2@E,NR319*Z;*#E\ +M0^FK(.'P#;>=/IUF&UR;"^T#@A*#M]T.U`(!,9#[8E2M8T)5>6?<'.?-4>NM +M$1)Z\HH^FONCP33>E2N/$(HHTIZ/8S>_]_FQGN"BK8@"!2OCIRG*BT2"FMJV +MV(IU[)`O+E=$_*2ES#7-DK)ZV!:\+CL,Z&I0V.)QM!F\[1MZ!I'YHN'4ML@0 +MXCD:#2/3P4D*6)!_2T!+$"+,%\)3HH=T1G`H5O[_3E(Q1@'X%OX_8%0^@#NECNR1I+V`,5S($-@JEJ3[TQ/2ZN4/OT*N, +MF?*6,_\KIW%$J?V[="7[E +MHS&OA*OU+/5N+UM`Y&1<_OD:;Q!_XAZ.X?$'S_DSF*8$Q)U= +M[KG4<`IFK89"+V*E$;O2#J+/52KM+T1(TL@KU/%O\(:P<8A\DBB+&Y:/_N@E +MWJ;AX!)+%FRN$+/O9G[)N)BKWNQ[$WCV%U"L"2_:'%WO;$7/M?\7)+VXS$M? +MHF$O;1CY+PPW[BH!(4!ZU+[O%C=?WQ)GC^(1(CPPLF_3K7_'Q^))9L::`@ZJ +MUJK]U&"8`?0TLD.3BU^MFT5.>[PIX;9E.3P+$ZTJ +MV10)2\OA'%^"4Y?0TB_6PM!1/JA%*WHQP'R@X+IE9P4]9$/4G"/P +M\MJ-O\D+)^-UV$S8[N"CE9WHG#DIPK=JD&(ER3J4;S:CT#)!9ITV^FA&,(SE +MLGA9X<#'PDI01$V2$\X<;_50F]4E\GMU!+4JT`Y!S@@KTOYJFDS!)I\(??!*>=[H"ZL]%"C6L74:\,'>^[HOYQ(5(S4 +M,PQH:G!`"T.Y]IX,3('RK@G_]$D3W5$-30QHJ/VA_VQ75`"N)L\0WO90I@!# +MOV**Y%R7WZJCMTW/>PRH*D%$Q59(MS2=<9F<:I:_$'Y%D<9 +M'T>(ZGYLVGB#!_ME=W&W(>Y5K1AZ*BVM>Q^E#N^;%RG.NR-!/@#T[#E$F0Y[ +M]E<%^^=47,M>A3Z+2+791))J).F6)\M/KJ1%DD29$_$+FF]9^9.#0A-!Y!K9 +M.:^#2E$.6:4,":$895J[B+W<`4]6^+9PMM$D5PBTK*%*_J_N1[&CI1]M,W\A +MB#I!M3)@5R+A)$,SF6&`/@C9@41U9UF10(CG'QR%#S\K/4`K5EL-PF`DQ4CK +MJN=.34'8!!(_"*F4LFGPK>RBY_,.P;M*1#II=:SMF>/Y*452Y&3(`V(MX?*@ +ME::>%M#DEU6>8%Y$=RT)CJAN69/V;"3LJ=#7Q.Y7Q,*:,99\8&\^U$NV,=,W +M#A2]!@&S9P()=@SH6>LS)G;:2HY;EMO))JNYS(B6U%"B/F]:/,TQ\K[.,6(X9]!<;9?G]6KL*^/>=?)XU`SJ[6.Y&^C'P-LY +M;2E!^G+[K&+KGW=4K\:]+0PV4GTEV<&'+3'Z]%_;YU0FSV^=@5<4__5#'YC+ +M2:H((G+^_$JK2P/.M#`/=2LRVR*9%F%=SU_2\G1(7>QT? +M,&\,#J/PW<4L%1#7&76BG',UBTJ5$B>106GR]MH(-H+S^,7S6VTE\6XM\J?D +MF+]"8^?/;^Y=LE8T!372X:"-0CHY:^GT:IZ!11#>!!]_0G4S77CGOAX\`0DM +M9L#D!AP5`I=EV?CZW^P]'D.QME%XA!4VH]P%>*JX'H*89H6V-QW=1#"USHRY +M\U`'`)3QERRVC9G'201?X#JF'(F"R,M'7Z.-`4O4Z;P$+Q,?!A +M@JO13>Y;4VBN6B&55=[6*T]<3G@2S9+P(&[<%Q,KTTN%97<([/A,\@C +MC3Q[E[6KO2-D=,R4I7ED-VJ1SWE83#)..?6=L?@V+^29"=4:.!D8J[6,.E$9 +M[A;:'#2%'J6*C!=O\.'-+6&^0N`#Z +MD!BEJHCI`!<-J0)MNXK;CS>#3L(\FN:RP";L77SN-C2O!RCY+E;OOUNQ1U8* +MQN10)T$MMT9'GK:\,1II$Q%MTG)AJ,2:1%/^^<*,``#9?9"+]G\]NDV<%C=E +MO)+I^(2^("`$"C(,+O)^J['NF5(LVFO8!8`F=X%<@7QU^O_:2$K9?>-E]MU5 +M%$BZWQP$NM&X]PJYTR3'V4D6MXH$#NEDHN$E\12(-LW(@KB5!.MEG1@@%=[L +M46%)-U^0PBGWFW05QCL+^DFF%+PPL9SQ/@A)MCIH>$04:F3V!Q'KY`KR%@$Q +M.5]Y3GE3&S*=-<'-#=:57+6XGC?/QN/CC?/J%!#=!7:89UC9G8?%.9*1@ZCW +M(FBJ'A`$339^\_#W<4(G;Y2O_],"](U;5;HUT+U0WBI^'7P48TXM8YE3,?O; +M&!HAG.!H+?O:;(`1R]=$-]6(&WG;$P$!Q]7"(->2THC:6#+K5>MM,?6K[8KH +MWQD>U"'!>\OPG&6O'`/P=`3E+KEW;P3G\RT41>3#U3&;$]IV?2V?#_IG>O&@ +M#2/;]!5LB1P.T16%:6=A2BRLRTW!;'1[6B+MZ18[GY&(42LC]X:4:`2D[>ZO +M'GRRLCC9J>KOQE<=&WLFDZ8''1XV[LFM7JW6@5PQ)8MT$1+8#:1D>7!<)S[I +MIIG#HHQDRD]VAJZ9P#N#XN28*/EAZ/A'2+<.'7@^W/`A*)_>3%"JRY-9#J/W +M15*7$GY>^C_2Q82V%Q6)XEI%'F4C;)@F+Y&+I_L0G!"U3^8D8P=;XP%*&$-G +M1ST?!?YWS4RX6'F&P4S*&V->TL:\&)+CMDA\"ZQ1>A##X5[`6(,1=;]W?$=Y +MYON2GNNCQ*;GH6, +MU%[3]`8OJ;ZW]$C(/#YJ`6N8)>;\*N!$EPTZ]G3&WQ5BA&%(*F* +MX!^7^:-AL]*?`UOD-YO`LV#JTB[L?X[&\3$.YTZ+"&A9]@56@UEP:-+Q_P"# +M<"C_\2E%X**I"2ZQ!OLU9XCT*@F<49JL+Q`$MN1?*2`3ISHO"""WU!HU,HL< +M]?6BO6-,*D4E3;V-3Z!G_3[\''DT6&%-6M%&RVAI8:?='NQZ2R@)^\6X(V$2 +M\UI@@LE&.!SJEYJ+'1@<)C3VD'_S:YV@//H5Y`*,;U\9!5N8:5+0U+,!`@OW +MC1.K5'Z#09"+:@=)$2/"I@-YKJ0F:0RYH7KV35+#@3Q]PIQ*W,`7IZ;:=3>5 +MFC+#3X*G%Z=002!7JY7\?VR4UWAJP<>0WMJ&.]H#/%Q/#",6MC5D\_%MHKYL +M=X*2_VGW%<,A.5"_'>GFT.0M-8R'P&EW'.Y?`:@8=6BEIUF]6[^`6C7+ZX;Q +MX!*\JIG#"RR(#I$A3Z7[3P;^Y9(P"0YGV9Z+^K4/T=NR/C]RCGU5EVPD.4+0 +M,S$<5/^R8RYF$_$A]CT=6(7=ZTP7=UK&];CUO1[?T_:<@U1I46D\[6W]JP2X +M9C)YNMGXQB:?5,33%.#18J)X$/Z/?X/6,WWAHG7HD,I>H@33):L'W7&$\7LG +M9@C'DXN7=QP*ST^GK-\ZD='/;W'VLZ00&[FME5J98V0MX\RUB5?,A7%PE9UR +M!=(\&19A?6;\=V^93R=E__.OOD5G^"#Z4KX,5)482P0WWM)591LV8,KQ[R1& +MIX;%"=OFO5.BD-H8@*L,8*/HV?,9$((I;=`S3P51&DK"ZK>V9$)&'MQ"QRO: +M$59(;FB41/X8L4L=%B'?DO;1*74%"5S`*Y;`0O;]*5I +MEMU$HP2(T9IY\9^!^/OC:&[G3JEO,<;,!N8?Q]E.;)7E +M"\D0-F?&=U:X-]`PI9RY[W^#ZKYN7:V];)(<7$",#Q8>SU9;029:EYOVRV_3 +MG#2'645/XC$8;_R06!NXL9[H+^*21$F"#*&]IAI2YM)/2\FEAR73(%#G(2XK +MRT54X-RM\#I&N9LA`R54\)U,@)\G.Q%_M^!V+R-_5OB9_TW6Y6/25+6,;/'\=K!Z +MR;JFZ,)/C_KG/$E`GEJG#1_$Z/9/W=-0H.*]+Z&]2Q41>[-I3'^3L?^4;@TQ +MD)?$J0VDJ+)$=N1X%IGZYV+H8ISU:,B?* +M1"G>>L+GO;Z(2SOUG,^%DXCQEON=K,G/$G[II9RB32,KB/I7B4\=YD<%K'1FT,N1_,9Z&DS#N^PF7"]/`(/1R=12Q^/GU*C)::&M"A`+ +M/V3]4!Z'X%/N_=H58TV#&.:'ESU.MVVL")[IAF#>FA9NE%XF(NM0%EC@M1N0 +M,Z+U4G+5!0!=36S#MO<&V+]!6=_W+3:%4O_#$;].KETJE,&7JKP=/JW9J^&R +MP*7"*\,HXL#ET!3R_+_*=:A._W28C^A7'W'?;*FQ$NY5)8JJ]X+<P*6P1 +M:9)XO%>RE./I8F^>9_S8I=^FQZ%+AC?Q6+CA;%()T[!+-B+G^._);'Y?'UU" +MLHUK!^!R.O7AX[U[4&A..J&9["]_2&[;0)P_1&N?.C#'C^G:4@6UA;KE;O56 +M%7$V_HA21]5E790W2"K(BY6>\YI3\#HH5L[=D=%L"%;[CLQ>=_(7MLZ]N@<[ICG[[KZ6JV_$8@!0@;]S=/:%D0709T/V(2?$#;H4)\%[+R0$:U +M7;PF"1=A./?;_ME]6*<><)CLORU*-8.[(QPN6(-,G:U-5%"\N\S-_\5T7;OW +M2#6=.1B[]+L*C`=/R@4Y-YC'_2?B_4,D:!7GW'>H!]^Y7)`6TEJ9\G)0(^0I +MII:_V9S^.L)ND?=5*=.Y)?0/!MYV>F)/MT,T*)0WDKV@(6/6^GVM`)[`X-@? +MY?;4MRD-&RDTU6X"'"7I/!`S'L.9L=0;/KEF!"L'8NU/91&7%+X.Y5NJ\O/W +MANV+#KE!KRM0*Y8X5/`N*41(G)9!_%AB`U2ME5*FBG:_H`PK7;.VSY?0!E<\ +M&;$=OC_":R!P7>KW%(4'0+DY!I8R%$PYI\:G$37ROR8)=^ERDK9??12(">8* +M-R/+'!F'50U/-S/UI"'1RFH$#,'$5Y"RG6VB*-&0(H0E)_1%A__NZ;9\&]H@ +MSG^5SA/AL(K7_U5%HD>"0P+03N@-2;2F2,A^2\!,5D_]Q)0TT"=RGWST>KI< +MVDI,)1[F5T3+2M@WKG'Z[A@^`;,0'I=&I3UQJ/KU)E^#S8;:C!`M-`YJ,#0U +M9?V(/^.;=JW4=0&%X\XU\GR6682F?].3Q)R1F1YMCO:1C)E=*P](?^%I*.!:,20&O#6'L5ZM836X1U^*2& +MCUY\K6:?-00I1;>QGG-PG3)B4'A(C2,`Z-&[M&ZBGUU]3\*]241.3F`)-+W= +MYQRB+[9[]FV?AXEP>DGV\@PDQEJJ7/:!:E1+YZSU&*`]V@T@.%;1F2)O<-8L +MYU2^,+C\I)ICX[W_N/Z"C:]4(:=-8MQD&)^Y47`^C^K^^8ORO6.7-\^7)1EJ +M&G$"LO/H#6!F;?V, +MIH@>\BF:F19\^F")']X7=S+R\3?"`\K7G_-(0?`R\CK=! +ML6+#1+P3_;96[V\!B-&2J$&`:'P"[[9&`?;9"E48S)=*%@PRC;'EB?3,K*&N +M]\O!V]3_HX%P^2MX#Q0'_>\E"T!G`;'"G^AA3;M]\O8L`8>,ID#"-*7N##U< +M_8E>P/!X,&"!B`<;BL(9))VGKK4FTAWEMK:91TU+X@]F*CR_%K8A/@Y3+)_K\ZGM8?O_WUD +M=HD^C,`7./QP-&LL/*4.D[NY_V](GE"Z24IP32`FV9*-U;'*7DG<_M];";BM +MRCGZEG")\.J84JH/%57F'!J;5%]9.7BRIBJ8+6E^KP]#A$2CZ[P,$ +M($2(9W0;V%+^8L^RA)GJ/<>#.^_=QY)3`_'>,?6YP-9F*-Z9*\2M5$:A72N: +MF]*31":!95H"ZGKP_5I^0ALN75YZQQP`A$(\MKA>>"I+Z7$E.'AN/3*AVNY9 +M]1:M):`+DF4$Q-?PQ2%IH;OF7Z=`V((:5G/OO?8X%U\N-::4G+C+!''G:!_5 +MA4D='E)X1APVM()2^FW@J-M@?V01I890=A.QFEV/(^XU^"]7!3BO-ZI*FBQ` +M:+6\>PN0YPQ@-I6?F;K6U2W\!H2D_<7*-5LZK6%SK'R:QVJ<&@JS47_ZI18=^92&G0IJ60E&*%8(V" +MH64K%H5%C!A7+X?PHY54;&IYS@WH-A55C!M_N)+YR^]3!RUF,A?HK +ME`;A_P$0O'0]PO,_0L&:.;J&,?IFR/B#>!L=@-P!6S$X<1VG6V(RY_Z^UG!, +M$!Z!VI/M:`\7>R3'5,&X!%KP36-$3".J3-1P0TWY0H9D7GY8=',D +M39/K94W1H'6=$1;E)#TVSV!-EM6,$WOJ4-!.1J&44G=1G_I3K1*.,`00>(W/ +M%-/0=])"*A#S+Y[$D4BVR/HJ,A41WP"35CBI] +M`<(-CAG^!W*3[SJK'NN=Z07WHNMY'+W-)I$GT-A:X64H1Y07E#0%*;1(.C=7 +MKPYCSM_H@=?JRKH>-B\&9UUVRZ+!`.76`MD;;$`T5Y/F;0T>@T0VS +M3#U`,.8PDR#+EDS_19DA?!\OP*]4N.F(]G`@:Q/]"0=.1F!M&W[^"?\I!8MUX4*@:)SXL]Q2[/ +M=`+^*1(#>N^B6S%LHA_9_+I(6)`=<]^KZ^T2M]G5#D9QU7ZZ7TV6@I_R,$3P*YJO6!V2VJR0?,7VE +M$WTV8J9;7\P=A/(:DK19>*D3:!,RPZAM=B5"TRA4`9R;"[5G%2602K;.>C0` +M&;SY"8_#_53@.-25SO$@VBW(K/`NU!'^!^\I!B.V%6MK5-/('Z*Q3\58'@-" +MAUP"G"'G6@FPNS\^@FM:ERT&F8/IM,V=[,CPWX7!/S;XA+8AC6C>Q7/^APN"F@0W1#X!@I]"`I)!;E^L;_>X\48_=/L +M%OJ$I"!(<6R8+48??\UY/AKI'KG5,`(E-`"2S6CL&P55M@TP?M#'GS-!OAW5 +MYXI-*ZZ"31FH.YN$R)73F8,4\4TO96>X(\36=)EYQ#ERAM4AM69"`*2Z-H4M +M(*"G-MUCB^3TW!+)K6FN1;.N`',H./'HR&`#\N;!1=-OD45:F(/6(][)`!R1 +M#:J9XBYT4'I[$.OV*(0=-VPTJ@0>/(O460<2_^*`,BM_V"X'4XJ/X.FN&3:L +ML3R(E:N'<6/8AA0.;458&LI54>!K]K4$)#!W4WHY.FX*OW+"@` +MR_'N"NA!0\4=`^[[AT*B''J[(<@D4)@DX;6;W"UGI9YHQC*2S+ZV+Y.$MZOS +M_?4QKH#ZSA7[63-7<,0R8B4?'VG*5,B+TF;;J,>ZFL9>R(">4.PJ+%5.PR;* +M\$3PJ-9QTT/TWY;XC#:ODV:>$&A'MUZMKW-I>(CF3@+7O'#FK%-;;=MA'71+ +M+7B3G.)1%<;0`ZG(Z\K^E4W*+)(>)LS8QWUK-W/@@4(F9;2`,*O^N[%=6&.^ +M3@7`8OD.OPT(?! +M)B:L^8B7*K4/RT^(_6""/,02[S=N;D,6#X>H[?R&->X2T#86*N0!6*>CS!H0O),.:D)F@1, +M%I&D=*7ZM24NJF4)$.V/"EE]9PQ%XE&'-Y]JH$DTP9Q(K$0?!C`_2BFJ)9.G +MH!K.R`YZ$P:3^.HUD<\[9+L`'/92E$J1[)%[34>=`[O&=*(:M%W_2`,*A3)' +M=..*R<3S=&-H`,U"^-/<5XL(/A:CS3<\$T._]['%OXP6V2HB"J=]/:UZ5MX^ +MA(0[O-=EXE#(%'P0PH%=`<0W%>+)WQ/T3SKV5XM9-DV6M3I4)&<#H>F5P2J==+&C46=P +M!RAJ@=!L12/#_G5P<@@R[^P@H)8&`Q-T&! +MNUYU$Q\\3TN:.\U`.\5\[ZO[F/1^`+J>2U^._K0WNG^CU@EX:]MA?'][I'_Q +MF3KJ>`/`_'S!EM*HT<*JM*X7PH[6^:Z,!JO7(S=?X^T-M +MY5Y&*"4?_7>M9D7*22#Z-=*]C=7.U]E7#*+]@X8X=@3VJ7$<^*.E\YO]9;DO +M:&QA/77&ZS+"V2OQ$ER@>/A5U$RM4P)=""N&'TS/.[^K?/ZIE#Q3]5=LBFY/ +MW%!;`6B>&R^8$N7L*2#I"%^.A^VJX\\EPWG/#H-G(#%Y3/QD'3E1((__YX+% +M;2F7;/XYD^_P]L7ZT3`]R7:0$*BMT&M]AYU$8B+@#W"U,-3?$)P2_"34%;8& +MF(=!.':,\"HY!VP.?JRJ'W`3!O))^>0,=TW_W7.IS/+96YM=1`8]M*R.TG`M +MV,2-1_UZF%,YOX.*ZVVZER$L5"8TI*4BAY*TO$OWH/)+QL^1 +M^6+EMY/X3-DY>:?PT0A!<+BZ)J9KO+^Z@EKX6X>7Y8[HBO$KZ:0H3>%U"^VD +M\.B!J+WW?YP? +MQFCD\%F07'[TN)]P;VU'A$5F2:'1I&WJS[\^X?I$`,4:)+0!VX5Y$YV-"*9? +M70?3I`,4G2:'+OK^' +M:81@97C?*`)7#[)Q09@2WGX^Z",![3K947UI0LN(L!@"<5A.]EX7N0[;H +MZ//HCJ**P"506`L>B^$,5K?\#`WAWCC/1@F(!3SYWTSV=CUMVW<*`01OFTC` +M%P;=%3G2FD[Z,C)UF:?&>=*5[OTT.N5@S.CY/L5.E%0D`+NZY(#FQTE +M72).3^2,=*@:[96L/IT.\]>FU4I.12]G!76Z,Z[7EN57'"F)[#KEP&!SS#!R +MZUR;5Q`^_LVIO0S_#.26C7L_JMO>0F]S_T@1M\P"4W8%S9#ABR<@/N)L\8V2 +M%U"S?[^)=`/0+O^TKTCC[7@PCV(/>,"PK$T1NP#E)_0[T;8?/*#*E8D>9-L: +M(EHW^:\N+K[:!CJ!J3M1XQM%*IK+7^*_P[2!579%SE.R?6P84]4<&?WG6FGJ +MJ;+I6ZN4Y?P+%G.4$#T)/YZTHI`3<(G/_Q5WP"VOYT*"7#7T_<`X9ZZ2B^0S +M[H:0_[%]B%A2V%_;[_D7"3J0?R]2E_(I]]FW[#K]`*@497G3`E`U:J9-+3)4 +M?ZK5*.ZP^!,9PZNB,-SKVU=S8YGO64N!@7OI,"6^0Z*F.:N6-MB2[7S.%OU# +MJQ/R-\EX8;A:`/^%M+5>JVVL:#E$7@+^+]=Z]/9UOKWXQZ:/DK=65"4DHCVY +MM)PDD+XXHL.&.^^%M`A9)7/[H0^>0:F$!:UA!E'=[VVX`O9S4`P\ +M*-05(+EV\X]#T%YV',-'O:YAQP'\DE0!=R5@:`1LMO"&-`\<,1RS%!'Y@>,B +MV1RVHVEV%85UE\8H&:O$SJPPU,AM48LT525%`MN+8M':+8$`3OZS>_\XJW'XCJ&-PEP""8+6 +MY_W^$G."Q;S7;8K[;OCT/CP+/>P@A39_>"*'7?)P-QWN[0B;E]R(/H:PVN( +M`QSV=D@IQW6"8X_MCG;G]E.\0Q@U`@<;<53.=(1DAZQQP:,JI=`VT`ETLXV# +M&`LZ\685$P&E?R8W$"P[X3^V5846'=+:TK=**LZ&86"A>)"CA63RUCL73ZI> +M55_%SND6&1!5\^*8N)H;_87XBP8]YJB73^K)Y>``[269>+)8SUDGE`88>!Z@ +M6A!6["F<*H5",4-:V\/O!"&(7OSA]+V+T4CR6`(?]@&F$W>A3P67CYFU'$, +MJD`GB<%OBE2!HV'@$3`]#IFG%:P/Y$73+QG3?./)(V5L++V:!.72N\&@#4C9!6D"^T]YBQ$EDQ.8/96(!F!- +MHPF9QEFS/.-V)6$9L>N?(9LX_?))"-`=%'V\TS+RDO6\C`6(1:QM3GY>(-`/ +M[C:DWWB5\(?I&JC0`:Z +MI\8E[:XPNSYE'Q42&TJ6KF#9YI>T+*C@*6AQ)W^/,U/')Z!%IF?-VI4 +MJ>17PM<^8S"D]RU9=B.4GG*^Z'\2+SV%#WGJ_2BCEB`"ITK,+'%SLJ65JTQN +MI=^K!CL5VP%W1C$F>U[T/ZJ4R<]38/@"0HH&Z1F#[ZIGXMT&@%2I`:&\$%+R +MAU%1](2>+E2HNR#QN3&C,VA5[!NXLJH+=-ESG)$_M](I/AV)0:!'VQ(`H''Z +M\ZQR95Y\H7N))'9&J\<_LL.SML"A%0YG$2Q$FS,PE77VJ77.GO(=9-NZ[UO( +MJ#([B04'Y4T*Q/SB&*=S`6%P5/C<.IR'E(Z +M>_<1?Z%:'>JF=62SO8&RU_40\D$DDG;^3F[#G?\WN6%S2LO"$CKQ*57(E#I[ +M53HV[5?).`WH[PIB5U%P!?3I6#J;^P+GR)HI.)1*;U%,C4@2F+M+&I8W=>/J +MW`Y'/)K"2_S-0(`YY>R5C_&U8*/F;##]$&T["C'?:+0>&9.B:N.$(3?'@P)3 +MI$*%)/EJ@B1!V!D'4>XR\BD62:.\S%G98AMQNP5V7=A_ES]1*?7M%#K08&"+ +M,7H,RIK:MDPP4SK`*8H=CIXS!0'K(KC219*+S-LLD1[K#,PV8HS7EQY0'7%) +M6VI.LP%M+);-8\RU1]75ZZ]>'X&B2OT\A'GI\!F%*&QVIC9P*$];X^2LMI0A +MWO,WC==F!L<>1'>-YR`$&_N@U:5S]99DFMC*"N4+U2+&+5J"K9FT#U&)-^&!1=!R +M:37-X^ZU"J5`1KPL&MN1*16S`2#,-()4%BUT`:K3G$L[9G4I/D_^G:\5NM:B +M9.QNR2?KE50-?4YAG8UEX[^=CS1*<`E^5F!2D642C0";V\42S"_I!@%_&)9N +MW>7Q]X31-)?=,:TM,*:!PC6(=S\LD:G$C%E79>$H5DG]FEG@O85AK&+OP=!, +M+N0C$&1A93VOOM!#(][J3;$Y_JQP22P"./23+YT`*V'-J8M8=^[<25==$6U` +MK%:S74BA'+O$8EX.9'D^R0+S:\>E)@%%6)>64M]I/S"*TLJ +MXK+G*]8(1#3D:5(8JI'R(;/"PFCB2RUK-ER>!&?L"6[QQ]PR8Z>B?=/#E<;D +MV4"W$4/^UC*J;\TZ77XT`>3LUV*>YG.X?(U1(\RJ3#;WO";SO[8\@-NV4@,A +MNB=LS$T#_2][2MIJ+`]VMN_P8I%G.GNQS7+P!5^E8<'3FN)8J/[X`B+B7P5( +M<=FO'^1*^8B,G_":"T2)N8ME.7WZ0T6R,[P,@L6.`GEV!XE@64D7BK +MZ:$;P>I(I?YLXN3`?UK0`6&ST8B685JH3S^21!?Y8(1Y*91`MZEY!1GX?/," +M6]XIQ4$LKBH)9Y9D::$U27')@J2IN-]U=6+[]U[U^#2'BBMGQ=OCR3;;\>F= +MH87?>2$_6I8D+H&`"BN@=4!7@'3'KX[=^@3.+L@A\>]-:(-YV\4OT2=U#M1K +M1.S&$CB&EJFN.>7*&UNMQZYT=\CF)Y#ZI_XL2:[9<._AR2!)O@\;S78>`_QK +M_*3Z:#"B$I:W6A;H2::;9K//HVCN/H$=[W7]]??%JP&>TFY(`+T^F=!-7.9^ +M?(==07^Y8REU_FMP0(G!Q&T9?H)6=UV:G2GL$.J8![_&/Q7O[>HFK&]:WD09 +MK>K-8)K)0KU5-SKWSCMN`P&@^]JNA2"TQPY +MH,W>1MG469V(/!,I_)$2_5)+'QP[*C@?4-&"P8\_!V&*(--X";*;#)SA +M!($4QK&RPQ-;J:W-)`N_J^+/A_5H"@8J3*_O8^#6GHLU0P._YVG/YF=!/[;[7%D]41Y5.XZST/QL83P`M:@ +M<)WV==Q,)B'P:CZT(I).0H.71%!^X(?,5AXR(]TU>]8W5-O3#AH&9,::!LUW]>3KRC>&`S``09$1.\5$GJ("#.YU6<$3 +M0>(W4)Y$6MN-B[C&[&<*,(Y+KS?Z:M.615\;ONOBZ'O`PEPA2$I(8Q0'6Y+, +MTU'2F_\BT!TB&">8X"%\M2JNF6V=*@+/XRB,Y<+\'Z(@Q.:0\:S=`5LQA?;` +MAK"]DT];[6R^X.12V=9RM<7/'*J`B;?/:8>8XEX2`BX7=(HDO=]-%CTZ'Y$B +MT`#+5+=5Z'2R=!ES'4I&Q7+HDPK(;;C0/X3KZM&-HG)P-;V!X16?7K]UB!G- +MN$\4O&%39;2DN'5@]M%L_Q/_5,B81JE!VI/(UZ)4R>#W>Y5#6!9@Z)EZGLQRZ".PPZ"?;\A;?3>@6KI1?D;YSJEU;1I( +MQYD9H`^MEW,.<9NG;LUWLH@[/MP1">N>\S[15X27F]6]`3K1-*D.0!&JGD$M +M!3)_*IPB@;3YZUF"'?,X=16+UY_9`(WOR-5-HH:`A^1^OWW3_/`(QHCN+6\0 +M!5#UX-IYIZ_@D1/L5"%AGAIYIN1+_O@20C*]!_]*P3 +MS(49PTYZ+?-H>HYC(FUL.0_0*DZW";F!N$E\)(MTI8=+F"(WWD9!BINV3&Q9 +MZR8J=)ZHYZZ[H1&K'L+CT/\3FKR,8+N^@D.#OZSJ-[U\N&3; +MW!-)?P[?G\YB=3ZE_J8AC$*O`8S#YP;&#H]@_:?\@("K;PW/M62M-<69[&?4Q*5R +ML:)5[;NY7D5:%#BA_&,O:3;[&+JKGN4EAB/+\Z;"1Z +M()IZ?W438D:_/\;_O*?!+E>'^70S!.411_%H7E?K"-246@4J +MMK0OZM+!LFR%G#P,U%"<#4PSZ@S>N6$PR-0WQ5,.:1AF`+I#9^\".NZ/;BOV +M8H;*%@P9(2M'.]=5#^/]W0N\!^H#=G]T^=]'TPQ7P7.>)#DZ,Z(\;_,)H/C, +M2CY6>GP_A(AJA%[QK\ESIZOY@"9C1X/3LS<=4EW:V<\]SQ@]$M2HJ8"KM2"5 +MDO)A2F)-#*-PIK'7/WC$GA6._U,]W)E/@VL>C>83O=['VFEP4`^Q8#%#ZJ&4 +MB=J>UQJ%5/1D8J$9:_H]1ULIBK6J%E=B<:V0% +M?_>HEF01OCVDJ#W(,*APK!XQ'VFYH"#E0AEZ\#3K+%,DKK!C==^[5PMUE>'* +MY,1%*;$R6-Y#>P>S1S0._H@>]'ME5N48\B-7*6C0@):R47^H8?,D"9C1^38( +M_M<=PVKI/*;H,5W?"P&>J06TM$$:UE9F\+UN(MYKIJF9-8ZZ>U@<\U8^$&]5 +MLNL@\;#RM%.KHB2Q>KSW/YIX,S)3UT."R%@_XG4^LQ)&H!L&^JG58EFQR&Z' +M(_NLQ`!83-R7WK#Y?&<2*"]!:"RL)/9"CHV9-A0YX7`.^0\^AV&+HX!B-.4: +M(``^$CC2P<"N)M"ISGNG#["GPM$AK&*E7#6`PKB]NI_P7DN\WMF*`/N2[!.% +M.KQX7OEMF"V;E:WQ9(X(D]B?7SPTT=ISQ7CEYDF'A0\)R';^PFB:ZN=^'+=L +M7MZ&IJ=#(E),#ZYCSMF/HH9O<:@ZAXWX/I)&OX6%R0[``O/2^`ZAJA+QS-": +M9Z*T-AO\Q1D!#@E%6DP9,:QO[V?.+PH2!2IGU!2\H3(NB$OSR&D'^+B"W +M6O:BTZ@+WS(1>3YTWHB0"X3!;@.*B)X$F,@$(Y8"8KPH_?V=6"`@4:5!;;X5>-$ZP"RT>-E_YKZ.H^6UT05=`\G?28[B)2*ZTTNPY;QCRG%+'% +M&Y"T32<(WT%"`H\#=ITE"]9"L+M<&!A&$_61'F[%EY?M,B,F$K''\+K`Q,AL +M?;<'_"8GI:Z,-S2]0&=A<4*&X%^21#E[VS;>@A,3SB:QBIDODJ$@R#-:1`:( +MTE1=-,ZS/&>PJ0`4YH0=VGC%4D4=&=*:\NT0Q._&HLI,GMU^M<1W/0,S2J=U +M%TW#`+I++^P7;J0^:5W6L;WR_])>U']B]3WPP;1ZVBU!H10::E?^M2YRA#Y4 +M<`9$O8L?OZ>=0WH[C7Y?#RC"-XT\@OIE2L)-R+RH.!.T]":=BE;T&%%H[?_J18LGK/'F"NE::ZL>VS%E(F*"=2MK"[7^,R]I +MWA`KH]XI`<7\<=2M"W^SH2@/L(%;&O%Q/HY8!Q/J:5GYBZ)8E<>=F?<4-63J +MFPI&&XLB[6_S3(59C(AW?Y[A:!.7MQ./XO0U%G+R6*QC3SWUZ6==?4!*^_M- +M]:[OL+B^<>06?IZ@8A7>$"CQ+F`($9+2#KYNFTPJJ^74,CJF>X$/F-HD$+AW +MRP^Y5-O!%%POI'I+>W3HOE/,QFJ.W[7RQB9U3D'>0Y;OE5N=%+]$Q'"[8K5% +M6M02Z5SPZF05CK&B!^GJ5^(R#O$(6)O[_);"L+03G*T68!F).PJB8U%1J$AJ+U=K&77-.7^/3J6I(BFET2)W6)')Z$A4R!,"$IIR-5_6%%$B8# +MC4=Y?R2Q2^XDD`B&D?M`'!SW8]5J`B?^`BOD*O$='`6@AH!G.;('>E9$X5#_ +M_SXS4?U>TF:"]ZPW:%)GK9GEKZN1.;(<=()PU(=,*H5J2:Q:I"ZX_-[O'I6U +MH2US^(0\NI_B.U<2?G>C')QLIYFM>X.22YR.D_YZ?W!K8\9X9>(K$2,]\YA()M:\W%D=0R4Y,(24S*=(:FQ+]D-XLC!&O+17)V#EX +MI44#DAO28KR`-_G7"9K`V5ET,!HAL;"8A32Y6V;&52;MPR[_4@5O>-0H_JNB +MDM&YC$T.#\`_S9U:RS7)#]G%J$1@VRWIEPA+6+SCAG7.,G"6"-6_K6AYA!@#`[% +M[^X_&I_`79/>Q"KF@L^I5(XX8J-T_);%._<;J8%QI1;=ZKMA.'JCM5:-X/"& +M2@Y<+9Y$HV[2>F\4<U!!)4BE +MCR_*"XCH$9.>/40T,SIN=&7_D.X?B^/'0][JP)RQ&OK]F11O]UQ_U9]:\)$@ +MH%LZ3#THX0;?_LM0J>``[9$7D]A`KG*ORS1L/359:-7F,J\WLJEFV@:*7?UZA<)8[U2X*[ +M",=T"@5G4WO%.:S/)W3&$T(/YC#9U[%@C;86OY0DFQ4SSI=K#$HD1GKEIU45 +M>I44%!=0$WGK"@>=LJU@%<6O76V1NJ0))P`0G?T/Z>$)3]=2CO"*W.34_#-5Z7T`]_69N^(""YD_%^(W( +M&[*=V)RI0I(H-:/SX"FKG$Y**BUK.)03ATI\/[38"00D.HPX1',.5JK-T.V" +M[!HH_I>09,W(I^7XT2&6A3#V@);2WEL&2WQ.,Y!@K**U=.<:WN+-\R5SZZ7H +M.J#5VVME%U-96S:-="!FQ;L(6PY2\TQ-++E"FGH"5Q8X9MB5YY:4B4".QBYQ +MU<]!32VWOQ@R*'07S9AS3\@QQ]);[^(!-@Y/[)I/X>/7&X<%'A7N.OBL6STF\8\R>7?^SA@W\=(BK!+^SL>>QG][F_JDPLI5#/ +M*)U"&(ZI,K1BWL\;-*[F8D0LGN7>(LY[][1U=D/$8_?!:2<:.KT]M`)(O=$T +M]&T^J+%%:T6)\H&:GOSG>TG)*N&EI0_+[M6SA#2L#0MW0[4$3G6J$L.3X:+7 +M`$D4PY"ON09AFQL<9.HMC]2WHI&WSQ.!-#K3DNP"0 +MHGJ!7#!_]Y&WH3SK*XZR-S0I28510#JI99(98L#6(AY*^]ASDV3\G!9V@S(! +M6;5)R/R1>N8Q+UZR`H!J;($7'"9+M=(J_.'46=YM5^!?]$H"[*Y/!)FINFZ. +M9/-Z'NT1\@0=M9"B4";<;8^9?5N:X6`$OV@%_`PA%Y8]?KEU^ +M\[B`$&[8H%EGMQ,RY6)TWK"[KV$)KLYK^F3F/_5F"I\T_(G2+R:]N"8*ZD"^ +MV;A%)C(=S(OR>]7,T&2!066Z>GUN_YK8Z3Q$Y?AHCQ>%UDD)5!^VFZ=U^\J8 +M&S$[K4>$[#$4B,U]CUT2M?4@L5^/<$MJ&HMU.`\V%_*%BQ".K+N!(X]VS[51 +M`#5=-TI\-]R8V_@2)F_^?1.U]N?SM9G)Y?DBFL#NY2?T[8[1H#_[1G(ZI:?T +M5199AT$.J0!(J6Z!+#)FL1+:K3Z3%%K49O/T&V10GSQ9,7^K1136,@#SH^&# +M"J!4T2UTS+R3B)N?'[&%(_):--%,]6&Z2<,WLK@@A)XITN'**.,#AID&K_1_ +M_P]HGM#%"3M$;'M8"@T"H[DGAMP^])"[,#G#S5^&?XU;0H8L@[6T);:,PHA3 +MB@.O7/SIV:FOO^5QV$(!%3Z.]I0?'VD8TV/%1FCBF!=MA?G/:O))LHZ2?7PI +MC(F1G>3;/6H*&.!:K6FIFS["_($^B>/)@V2$D2.A,KEPN-+QF*JOE-SCDK3- +MR0>224E>F'SUIS)DR=[E317H"8HOP!"R%?1AE@.(`S^[BZJT0\)4M[-WG/=8 +MHU#G""J:>33P/*8US^]-CT.\L/Y]V'.7W>O-'G7ZSHV@]O[*DF\LF_U%42K> +M4Y&H0%>#=&7_=:ZP*A7)463,[!P+#.09XQ726/SF[9'572:0>3YMYZ%];0C4 +MNUV3WI`Z<:[@LAVV+FG'R;H:+4#@TF[%7C5H\:&P,@HMK>L0%"^E;_`J4O^= +M'NG:]SKCC,])0;(D\=%YN_7:_^M@M3F=!6[(P@L1<7')O*O7]QU/5T3,:'[, +M,#0?P?>:'#[X5K.3#*IE]^P[W]25GPP2.8[I!P.8Q"9*"\!Q90>\O5SP:MJ! +M]=-[*)3D"VB[?^S3W*'7[Y!L'77-($?:&;!Y?OVMAL5*/'KDD6&>T?]MB<52 +M""`@6766_S-S\ZMWM0N?Q)B'Y?4F3X&9!3#DIF^=K.(5,@)>B%A+W?L5BD&^ +M-FDW&E1P+XB`1Q^%[%:EO%J48&5ZX\'7=";`^A?#9G&.0C;(7Q=4=)49UR0K"*FJ[0O(_";U,@%@$#JNY4OTYEP@\Q&MTR1L9?( +MN,`P"-=KN%=9@)\[,D509*E_U@DF0*V6':7N$R.O26H/9+3+T6]HINW+1X7C +M".=3Q'K8YAQI@_.0]CYH7IO8I9>(=PWN;5[<)K[$LQULMBJ-*BPI286G=(L[ +M\J1_YI'F6N*WX_3V+MHA44$4AS;GO*%K:?.72?'68$_L19-CYF6`RVYO5J*; +MOXU9M()4F8K0U#^>.J=[=[3JT2F7(M(U;@SG6Y2QVTALZ)1M)`(&"10G!WH9 +MIWVI,EP/,G*%#ZKD+G,O"I3CV9@OGRH(:5?2\T`,1MW<&5FX24,G_=5-&C+) +M#(]Y+$)SI[6+VQI*AQ./GY\L7/&@8.?=@>EC::?8IO\5NH$`/G,U&F;;RYN2 +MG=]OGVWSFA<>7)=U):"-]3KL"#F@AE'/MAME#/>-!"E(+M)&7S;MX;LOZ?P& +MJ_X>LGF,?6WNZ-A2E)Y#/SM[S:8=\?4[LW5@34'-&DFQW.T1O019L&V2+!)? +M'_QNBN4N3Y&SJ'#1H.(S;\_"_8+Y=9EEO?3)(`]0<.HKT6U!N1LPO_]`20R^ +M%4#1"E<*HPO^D\VS`#W()HA]DXO-"*(O%66,S@?4,K44+)',16%*Q$G&*7(Y +M.^AY8A^/B-!`'+U"T>8G,V3WWP%2@F?L8:B2.#QWB#F>ICO7LNW?7Q=;GXA- +M='1?`T%+".?,,EJZ->!#43;)PVSJ!_7N*1*W\S`Z6"&YF +MXEIL'M0BW]][.7*=_1".[$;?OFAX$7H"3H" +M1>&/F$8#,"@$/M,YHU +M,5T(J!(ORA7X,K*28#K2O190J=X/+83IZ8Z9>:Q"(GZTND\J#U` +M?^BT`N?]O"11S*?P6*P[:O&+Y/X9UD(:=<0P705%B01;B&\;Y*8VS!?YYLE^ +M@`V-JF1KGQ'Y`P.OIPPC>UZ'TZ-HF@-%YAEEB&ZJS(RMZI_L31NOD:K,#Q!46#* +M0"]M3;(/6T%/8S&?'+GP@!9L7Z("8X7(=69E#,>7D%( +M&YP7GWC_H%3FP^5Z($,7Q`^R-.@Y_&"BOF43+TO%<'&*CSF7U]RK&PIXBGOP +MTJ%<4Q5%CO678YSH-A?E\[=N[)ZOZK9C0'1__GA01S@E">;.,2PR(-5^D+<3 +MC(RNI7AL<6Y9_8S56%]I49AIG#IM91KD-Q^P(D`4,8RX@:\&;+4L'``0I8J$ +M,NWV->8.'S^6FZ!N2P>P!!;2=^MX0]$Z7[UDZ9Q<;D-,WFH-0#N3FEKML>T& +M3.HX&)0?45]]R4&XE8M1,.K:I:#^TJKP03[[>DJ%$2T;/:?SC`:JT;ZQZE8] +ME2Y'W(43.>.8;!LOLNJ=-_J\_YJ9FG]H%[705H7?MJ8*D\V6CIS^SA#[W6JW +M^B==FZJ!U.T'?!S\%,D&>,4RRU=8:UGH87%@S9X!C`]5:3J$7%!IW.PR_PO' +M/+PWA;_!/JQ%V&G&EU",H(ZM/&P2I$%Z9]VAP7RA^;#)P+F,B28SU!BTTE3* +M&OG:*/11XF-0I.5>PUP@^559U(NY9$M+.4?<'6F]NW3T0EQ'-7K(8P`=TMFNRF-CIVQ!8[P>"PY-/:F9?^,U!+G=%4SW(M +M;WL>1]'"6$;J+*1=NC0MT*;SV/Y3)CU\S?0&K;_[?OK4_2UWC6.(BP60>MMZ +MM\8PV?\<&`1BU!,&9^RC!;(A2)"FQ:WXW^?-I@,ZC@@+ACFQGT:`W.EU`R@M +MQ@LTYN2A_Q4-0+:OEE*+^RC-C%W4HQ2_I^+*8[!M>(;\V>,DI>(AM`7)T-&XGN/D/G?)_)%^):'KOA` +MRTLB]@$4GU?:AMNRC220V(6K&&1K"W,_^1[W!6K,AN3*%38.G@/39)S?N;HD +M]XI.CW7G0UR"LIEHA-M:P3-B#PH<5)'+4[%8`\TG(.PS$^I'W%-##]AZ/4?:D7-CX%O3X&)J<^OE3'IS:2?4* +M/)!(9/]LN??79U)87F72=*7N+,I!.XR*YS'I"95I7EDCY":;+1\I5ARU]!HE +MD<#33@2[^G6`]W&,2:W-V+L;^?W7?S!HG51Y=X0$XPI +M,79@5L%C=8MRG'F#:D`MDP&KZ=&@O'OVH?]&`&!$WR2VJ*-P'I/$N!GA6U+& +M]!=\T$Y61=M3MUD-.-T^@5!YMR15$BLITBF6MW5\4RQ,^F:D6)';JUKO.4DV +MF&FK'<#&E>WD>?!>#;[`CGZ>7J9[G2!Q;QQU6JX1J=>-9I*(Z7?2V.2SZQX$ +M?OCHF.Z&-HU$*:JL>G$\C8.0+G]?A_)?GP;0KY?S!0JI*?][`Z/@NS6MY3RC +MNTF(7?V-B\16)8G+R)Q%.WHA*5\5SDX7`8=Z)8`PN*Y5JB,$BP_B"Q`(>)G4 +M;+KDL`7Z.AE9JRL#:IT;\+B'V!L=ZKX>AQND3M'J:!V__"2N%=]7(TX>,03U +M7??SN)P&$KA_B':^/Y??@W.P,8UD4,:!$ETA0S+QR;L60,'&G"J8^%@O)R@C +M379N:5'&`NDG5B'1>Z_V^3O^Z?;5AD_N7QU48B/-IHQ%0>I6&C_\Z7^(+>_' +MI\'3/B@[UR.;W,'\;)3PR^]SFMF!-47\.CM)'%"%!(3MJRMRKFM/41@Z +MR.6HK3N@8&9C&I]*0G"&[:]A;WZITP=@XIV]M1&.[%R/2F9!6D!O(^>`08W# +M#*A>XZ*S`_RO_E9&*;IJ6ED"&='+LB[W+[[9LA\#/_C3Z!T#8O2#PU/&VI>* +M\85Z@*O+)I5&HKL;_]&8?*5E'4-9H8#D_)O;[C06P):.]KS1>Y*=V.>3H0:' +M=M.>UP$+(JY0NVA]I!M'XS5X$J]AZ5'2>.OV)SY3-U1.7<.Y@/JC5$]\WS&I +MM31[*HAO]`(2M5:5_D!KX]S_)].OBV4/7=!<4U%#L7'?;22=+&"GP8O!NQU.^``>` +M)3L(X"&RR"YFO]*\_&*]U^^NM.W63F:P98>F/U6/$O%47CN3X?:%M@9QOSLQ._ +MC$&QWGW()+DJM)=#%/Y&6J4;2?`"HJ!7/01WJ=J[VK%?R][ZFM*KOMLR@N,`U&!H!TK>AS9A)#'+I>1%ECVNV +MRA=')L0@/AH^C-4?DKFN5A!\XCP-F)J/E2">Z\TX.L8]HH-/%PVCC,20P(1E +M+_=BU?!,`WYTFL].!(\P\L"H-:')MU>-5]+@3)]W#=%X&![!9V;,:3ETQ)+? +M*>%W9G`60#!@ZZI`8\_Z;[VS$_>3%P0:"-,CO47M0F4T\,TJV+F.DUKHBFRW] +MAM)WZ06\99T$D_D$>CJ4NVJK<#+X+$/>9/$WDF/3W+6\GK@/.PZZ`JV' +ML?Q7/E;W-<2"!)8@!#DBD^1J%J-@@/2;($G$_6].9!6K.DL=3:GMFNWI]Q"W2&@OYJ%(I$ +M\:)A@_B3T>U^)MD@MY"PV3/8`L>2#JLJ,R#T3V\%4:S'H6EQ,`_!IP<&0Z^7 +MJJV&&D<5=I9>OF'U0YTB1]*Q93*EJC[_7]\;(MX' +M41A()%T'N1$MBR;D"=8FS(DX4+W-Q>?T!X]KM./V59]'RSP+(@'-C-N):<.8 +MLVN72023VT@W/$W^@X.%K2Q2V8=_&ICVQS9\>1FW#-MAF"C30J(_99+B!+.: +M[6>2TIMUF1ZGEFSTZP$OIK\`C!SUP&J):HAI@*0B@G&4-&9(6K,>J7E:IT^'7]2:GQ[@- +MI3_7*C,^5>@@PBTW5N4"064.E:@P'*7KH.A+UQQC':O.-,-R4:GM)^KC#TZ! +MT_C&Q`N$N86S<9-WQ][J-M^=I7T+"'&GCD>0,KB._:N-!^>*$V1=QS'O@:C8 +M+\G3DA'8^KN_?G3A5Y$[3"7AAO,J:UUM(>@4$I!R\1%SEQ+ZVT1*#JB2_P=A +MQ^X<16]JTS.PNBM"H8(3>Y\IPBXXI38^I&Z<T_H'H.A3V;%2O +MGE(\MG&@C+X_.L\V`70OMXX>;0R4M.DWXTH_86BP9R\:`X\L/*WPR;I]P"53 +M*B.Z>..AJ;1AV9LJ8/V6'X61#3ZRG+NHS`N"JB%J7(_VB[A$7(/:VR&>\!M* +M[/"F$C0IS703TM@/P=6DF:J2[N&*/O-(@2BN`2I_!9WP6#D1BG+R;^9]-AA- +MQBVZ`M2QXI/7V,PLYFWC:V<<+%T$D.C^!%D+Z=5+JZ\1&8XVCY!`VO\"[TI" +M0QS27.%_9FGZ2&2EOK"NF:F'[`RA)) +M?YW2\<>!ZCC'-A"39]U$9`UUM4L.WFCW*\<\;XU8^C.:W_L]W@JF]%_7$4BY +M\Y"][)1P>0UA:@3$^Q8/L9.AC6@@PCMM;^Z:0ST/Q$HE0R+XV6GB\#M52'1T +MD\S0*[,)HD?MZRK@!H/^37`%"TX4Y+^7B#)32Z):8W7@)6,6R8:TT?41?6`U +M]?FV9,.R>A4U+AHLGUA7C`^>DY%!1479DM?\@\N=I>_=@<3_&R?1(.SU6`SMZ3?W +MLFG*YFT3,]9_HV^IOWVBN$CPU'3ZK;BO;[^+[\,_O1X`)S'0F_?W'G3H3K^* +M5)BKPVX!Z0'EWM4V#F^.&;BQ0N:?Z+1-*;MZ:*1CA!9%P8R%#2&Q"Q`X5K>7 +MD\@UR&\K]/>*4'L%N;K+DTMR93WL2DHB:8FJY-VHM")PZ[<6%5(JPC6>5G/W +M=^?\!]]*7FM%E1+;KZRAQ*1#Z'6%A8XRU`7+BZ8];O\7U9"2:*[OJ(-9GOP7 +M"IXI"U?-18LDHR54C\:[4EX\F,!TM0,DG@J1EAT1.YXF=,;,_6-7G$%0"&(` +MX!**LL]KC?++N*OJ)U%*IX`KJ(907PVC>_KB0^EPH>Q,!#TR9VV/3)-26O#M +MP,1;2@6>?"0PKS<&W^QR.L3+\8Q8LIPBLS$]!0SXHVD*7[YE(=/(#P!'OYO +MVN<\B!67APMBI,FKLOS%P_YZ-!NFLOQ$\4_:>)V@3HC>8[9Y.-"AC3J[KU$):K`PU" +M6:>VQD:^#J!7-7,AB7\\'E33R0.LAH.J/<<@/(`',8[8I4V?&XH,-LMRX^#0 +MA1I1K(,)-'9*H:6\\T5N*W=+QE491[NOW-Z9S]^2XTPNZKN1 +M>.$;&>25)FMI>>D5EJ7HNZA$7:U#KR_2F8^R(\1R#..K'^N\VN'^E<YX5>,#K3)S5#TQL>H'/CL.YF,A +MVY^<YO>`Y1_,34B7FDKHQ,W6_(W;M.)=ZI<3`9@SA'$HE.Y +M0/-BR7`QP/<.&/KSA<=(SO0E$+#5&)URQN2%?KOM7%O09U^=) +MF8,UR=-^E;!D)8J[E-`4FZP(\?W96?YF%W#;P.LU6N9N(*%/Z?CDPR(5P'Q% +MD89B+7,PNT<.P<11D/-UF5R.R<+=:7AE1<OFA_F(5W*Q4* +M1EWRBX<$``:*V",#H>:ZK?D,U?WK!@_=F_YYN,)Z-,[%=T4A-$;R$K;4EC3Y +MAC&_KZE#8O_6U6!I,G.C,E>D4'J^F9#4!TCQ7>=4ITQ%A)9$9GJ0W7^6&?U. +M-,H>ZJ\VWO36.53>N,/FF-\$:%!]G<\Y'("[,R*5W#W`:FFI^B(DK>MDG;]T +M[VEZD@WZWHIZ'OYV@]JP"9<.7*;W* +M9,#*M&[=BXFI9Q"8XW``MZ.M/$LH\A=>9BY*UB0!LO&*%#N/OL_5@(X/E:-L +MP.P;\`FI$A>T*-$41"K]>3BBVOPB&+YM59:@3X_YN/4EOQ!A5%.ZYC`][&N8 +MA-LW19H*P!5J^(7+U9&RU$]2;N)_OM@)IINUBI' +M-VE=>'T=Q'">7?_H5VN[#(3])WOQR$6T(0!7VHO5,L=(]TFA4%G+_U0GK)9= +M=R!.[9<:18X->$;/+SH#Z!K/[_=*D:C2MYV@&^OTD:4VBR0G/HI(4'H6.*92 +M5(:WX3:FW*'$08E;5?/CQ91_N^P#+W`UYWPS@^&$JN#NBIJY;4NQ^[QJ:AJA +MZCMX@&2F@/0"\KM;4U02-/*1OLF!<`63_J:_(L^A%=C1'W=!>.=?\'P)+W80=132^=M@&@*CLGA:L\%]8J[JJ`4&5(=*P8+*DF;B]G>*_V1C(_I95T->T2P4'B(?T +MU65X*ML$[+NN0>*8/@HAG?JZJ:*Z8H^2OH![[9)+5YD9'+1*]+*1=)%8?==< +MKM^]5_4P-*IB&D9.]:L=:/L3A8T\35:]`Q-I"GOO`;_M]@,1H$$+692KWAHZ +MSLR=YM*AG^/9.\.)O0EI2*7"#0ROU7\5:5Q"*)?<36S`%X-`&D%KGM+GC&H( +M'J"M5B)'O&GBQ&C0LKZK,LZ)CEZO+3R;L,0+>HWTL9P>\"_MR^5EL>U7HMS? +MB%7;T`$?X_M>R*BT8KDNWSSF4&@AWX."BN6A=@C1(`,R"?W;4/64F&><)/23 +M6%H6\]M,)R/TTUYM=_JI_=PJ::VT7'N`>>\4QU#@:9&FSB6^R +MO#V?B>U\DG0"J]$;H7\2T$);A64*]6J^KN&CK!81WF)C/O+9M7U]!9\^!57> +M5-3ER"<)""QYV`!&::8>OP<-T`A,IU#)$3QOS"B*:?XWG.R;'UDBR)75U_@A +M-5IQP3_"=C<#=Y9*1X\@=XE`2.$.N!FFJE<)J&\_,:TX=%.7 +M8$5LY1-K`6"T8-'U!;HC*J;>F"8@M$[[X2Z`-J,^+C^]['1YX!7E'H]T__4D +MXK2J(6IIN(67XSJG_[[T*>^W1X13RFH7^9ACK3[/D +MF*LK2Z(;CQFZID2,:71T^6@9:@>Z._%')-KC@R")Y6RZ$^<#U2&,#KJ2682/ +M:/9W(E`)@S-T+,.]FZDK2HGU$1K[CO_RXX.-T$UFS1?%FP/OH*9K4:`+O?&! +M=*MYKGEHE800U/X=V$5A,W\U\*S4'[C<87X:Q68UJ@.4#M!;[9"[/@\PG&G5 +M?"2K'K:@?SV))AO;**6$ABR\"V[^*-%J<"C4:(%Z/&2ESBX6,(2+(G4.!L+P +MN!E"I/^5RLJC2\]`O+3BC%68$M>K0&##=8D228%'"ZG@?3B2V(E2CLT^+2YY +M=P6)COTP*&$N[WKK^ZEZ&DEJV/^MQ0B;[-I/5Z9&)ZO=&LXB\-A[&V;'RB!P@+:Q;CQ`I\FL!5*=I'0N:["DY2#W/V.+Z:WEOE[?PB74(:0EF>:7UT$H;*;IQ9HN+IC:ZOW,*K/6 +M)CH[0OL+S5[@LH*U,T0=YM%2&<6KD:'ZBT0?R(*HEKNW4EY$S1)5)0;JI_1\ +MRO*($;C9IS>>B.'P'/7650.H,=.@49-A@LXSSH$4VR4 +M'B2^MO5'JC-)SKD$!W6Z?%S/OY/Z">>$!A)!W;K?O'-3C>1A%\5DQ!;5E#E#Z)4?10MM*&/I +M[<>WC`).4>/B-I?_/NH4YN^*Z:F?(#(N.[ZTY.D-DXL/= +M]^&<)%DK>O!%Q+T2)/,>3JE(-$CBT-Z(*%EK.9*H]`IJ4LCB,)?O-XCM*)@N +M:$?A2(,!D)U#NU4YK$G<\H^>LZ&7:Y*`N7!(?JV.H&MD.VX2E0QO>8;W9/\/ +MH4*IHS]VJJ3_X25$KEK\]&_B0_?G:S#6?WN83Y=:\G<5$KLEEGYY$\)I,WFL +MQ3WK:)ZF2'/<;([!\+A'A%'QW=+1,(Y>/[E(<(';5?2W+Z'&"GNLVF%(X[-- +MIG/L/D?&`]S3(`F7M?B[E[/,KV,YCF5+0![ST)?&;FW93!N/@<%.7\Z7D"Z5 +MU?*TS&G<2S??[\'[^'?9J'M;P>40".-!%)!@IJT^PHWPHXHVNU\?5,#]?4HH +M#K)@.X?)%]E6R_GY8(%9HM!QOMI7ZA>(GDD!NY-?7_.@IEL.$AFGN"-MMO%G +M2;1YV.7I6RF83-'J,:\Q5]74KZ2RT?V%%ND^NU-<.U5`CXFZ@5/Z?@+JG(R] +M@GQ]?0H3>.WT3+.O@4#8^,+QRJI5','KHK.X?B^5.[L+R2"36ED^HP0V!V#A +M869D8Y^.+:W)QQZL0>U[Q^6%_$W"2.CB9_6!-E$(5,%A0DVEM+88S$+X^2^@ +M]1`UE6&@/EOM&0J3NRHO9.^B95CRUYV(H9H#^]@S +M;#.S<[EL$D-OIH6F'-5J;%H;[X/2@)]#L)JC:"`87[<^XF09NJ"ITE"9\,(U +M;8NRLQQDOPOX($_V.53]P0ADZ'L0<"M6P#V\P8'[SM5-D6:^`CI+[(',C.#4 +M2I[M?D..J>.6;!2%\,/E6O1!._[7((,*SS3[T^G]W=:*W^5.(O87HAN8 +M[P+;_K"%X,`E1R?P7S>S8C^(,U=20>S>,G&=;->*N[XZ5<#2';AW@ZST[H@3 +MQR=FU89-+GX*X9GT?@P;EWZKF8/?3_O-QX!U;2>A[O<5&_85MXB'R6L4MHNU +M2X;0#7>,H[]J"UHT#C\OI`EG\%1W.-W@_9@\YCC\<Q +MY.E2HE"FL5ZJIRU&E:#!^A:CN&X^T\JE`L&6_.\LBK$`$T'?)WV-G[&`@+O- +M"H7@(=J>-U@'A=KY3CW`J?R%T2$(+/BA+_6]2)`,K?(CZ5'D*YB93V#L.W7)M95ED4ZK?)2910_+Z=(V,4LLZU>.4O2;DA +M+)44L;HCV*P9B).B&=!8T1?!U3TVBHH2U4"YX,M9=D?[%#!6WX'\<5@<9*M* +M%C"*7\1!=;*C(>X`YIM]6F-@6@5?5=@TF="FS[J]T\`U;FW$QZ)^,YNE_0D\ +M30?WIV3?Y-J?M^53@-G%U#[V;U+IH.H4>'IEA4Y0V\@$@?AZ +M/(2/5^FC(,4:BX!R$#NBJKE]P&6B&Z:O,N4%<\XGQS6B=ZYZ9_VUG58S,WI< +MW*;9^%-5P;5B`9%^X;=:"V[*"3-"+RD,,LNY"-H=KH^94%LJ=@`7>)MOWJ,N +M56J5B,2[&R?"6;L":09U14DKNV,R7*OLSK4#3]SJUFF[`#]>8 +M8BEM7F,2<)G?3QAX_U#=,;Q#F`&.&?L#P0`UD'EY02DCFXTWM71SZ@BQ8&XP +M=?>R%RD$`^?2M\^:\"7)7!63PC&(=B!I2XF%ICV[T)_*D(]IXXUY:I4_'@NQ +M@1/1V;@KI[=QS[&]PNH_^<%L52\R<7XIASA=CUG_OA=3;9WVY1B/LW7X'F:X +M)DT6I_*>37(.K(2MYDWFJ0VSG>I/(R>*C/80RDH2A(6T@Z:.#8NJC0<`SC+\6IIKMCB%83RW79 +MRC()2;XD*K)9^<\>YXX'MX<85X8CN;:+'\(,"X@Q&85@(ZF#T:MH^!L2[-8.++SUF(/XZZ"BQ$KLVNLJ +M)8,DD6"GI]NV=))<5/+\0EM>(N#OYM:F/3F/]*>2`>X6C6QG74NL`;7F+@TF +MO$J?"X(%$#PIQ#8=HOSK(U(?C7I$`<%VM[A&4K\V[]FOGUM;5I#A0:9"NMT5 +M/^CLGGOGF"R&A+Y*CC.=SMYLG.M&)W\/K,,"R4B2B]25YUYO'*T)::,K.I;. +MRLCY&Q!P,Z2!;1?:V'8"N^QHEE]+E#/"".4!_&'X +MHZ`?5(10\8N]$`NQT55#2%/_MACPQD_*7U30;(,?2=B( +MBOA4G?%I'-W'"8P,2(3U8@,63(@WT*%Q3D=6L>PRAP_.,GP=R_5DP7%/S.T6 +M#@ETVF1.6I4JL9`P6410YHH]X4'DI0:AA;Y]K1%/=-Z=$VF!B00`P]-AP798 +M*.M2/@Q";?JP>;%H#H`'ON[ZORZ10X(=3;4\5>]%'V.GXS,YQY-/V#(MP=?V?.V>6IPU]%+- +M^[&=N`>KN:2'&X<@B4'67V:H'SD#'=1E7"\FZVOY=6"N:BEZR?Q9<,V2SF!: +M<1O)EILE3):[7FH-.FU@<>-0*WK&&\SZA;*`@E6C'Z\+9_T3A#>.FFJY$K#; +M,"/R`,'+S5*#<5TVN5>7MD0")(;?4;N_)@YP]/)8R-Y^S^KT(NC2L=3.E7_X(T`@<6=E0!BJQ3#B8B+@5:DM +MN::R/!WNB0VWIO@Z=SH';(^YI^WAG&Y.&:LJ=`V;UX"1&C.V/& +M(9N;U[YC/&-/E8PQJT?;],^);H]2*A"]GAY^:^?/P+V6\2+7[UY7STZ_J0ZU +M/^%/A;GF?\[TE>31(A8;6BKK>K+\B.:N#NC.:ADUX)G26[+A0YKNVQS%+ +M6?UH*P3F/6-NTV>9>,(LCU>@S-[:_?>RVVM\)KK#ZOB9D,,*;UUS!P<_0$N@ +M:*N:%^$XZ/5K;O]"M_!'-F`8'*57CLF*W@K(FJ0X(P@%^@/`QX@V*3)[45J` +M75<7[*$PD-OEOZA:*;IKT[Q>%GZVDH>'_+@G(6F=XT86FO;JSN*QJ^[8+H=2 +M:+.@/ZVB;@4"Z$5L<7C^S9THZBX +M^(2C,N8\3Y/H]$E'+QITGF=!VD3ML2V^)%Y8B<+-UVS_D#*B<@WV57P"7XJX +MQMU!!*K*:DVU)^-*:#QA:N1\<3/I[[XIV=- +M4>7O69XC$FAG=]BU42R!3$'GTM4-3OP:%X_$PO`DS]A'#@"1-3J1:=Q9VQ-X +M$'+<=%E5U>/O"EIQ>2Z<.@4&>]5GMBPME2/([^]?U_;?<'ONU.U`#R*T6OT0 +M=\1[G>!`7^,P2<::$SB!8=9_2R7RLS`GQ"&)W>L?\I1O%O7PBM5-2K,`/]<^`(UF3PRT.^QA^&YP0 +M_JV22O&!(LK0$?-Q22MU\@D0DZ@>Q]RYXT#;^W?=AF!!NR=R5WKOZJ#59CU2 +M'*KX6V>N!$"Y*_Z;+N,$11"6$YWJJ.SL&9]1BEJ8RTFJE,K,^(T#/1J9*!;_ +M3P>TA+5C]"=0'%I&-./0P_I?WQ_!Z;Z(,[.UW$PI].N_-VX^&\\00VH'I4/%2(?>2)L?(4P*>@5RTTQ< +M+RBQ!FSZ)=]#Y?6:W)ZML"&ZCG+9_;]_>-8AEP;K8XL")(<_7!=?LN'9AR[( +M;,1N\AYE1MC+[4Y\>$=`YN@OF`U!6'`,_M9-6:+A;T-5C[5CXB-M?S=-BO4-\=? +M5MR,W[;8MRHR,,"GCW4IC!=4,)CCJRS7$]MF&>4T92UPBD#C6WK<$S#S*KE? +MR3C[9XPA.\W5)ZP=?U[M.[)2(VOMNDQ[LN6V +MGDTIKTI;RPMAXW:N,3HA<&;"CG^%[TQ!`\RINTIM7R/D6[W[]YL--:ZO-6]? +M!:-%4,:\\^59E7LU$4^+T>W_)?"M0%#BJ5/DC?H%6Q+B)%'_I\MV)+2B%8"! +M)&$>#'NAI3!M)PH.LU?QA/'8\&[7.>R\/J"`-BE>4+R&16>S.1*OR0&:LO@K +M-@4924$]_/W@V`W),G-Q+:(I]Z(\AR]9,VVX\.?^&&:=E'=X79YJ<#S3&Z9F +MB1!%9:P&V*]OOH7#JW8])&NBK*B)H(Y!S&H^"4"Y.FM];*=3;[J:J(O5'^^P +M$M(H)@?4N(?".*64@;#E@=?N0]N^PAW-K00O(OF_L_`6OH`?(KUACDG4P=_X +MZP>8?#Z.TC9R.G7-ZFGT90>4UJD4OS(F)5TC21F1TCN\HQ0-R"%(/E!JCLKC88-81&A&18J@)3:0O1[,5JKE6P$=WMJ$*YR^4=@L(!)LUJ\U:":_T>[]21 +M]H47^:Y;R&9(<^V&P0_)HG$OA;5B]#20X\_99'5"#8"A7#\\:;C&@&'BYZR< +MC30@S(TD%($'`/+(CJ^>2A$]>M%N.Z^%4CR+1/Q"?0`J81) +MS%RN>6)DKK^56.(4.LU+4Y]B/J_CQ0W\_9+V]JY=K>$NJ+HHZX\H1$M`_R<"T4@:R=FB"WW,EK_L26+1_N/X$1CJ*D>]CU!8[X[^'I19 +MLYY#H0M2H"$;J$@7GWBM_99Q<'ZR24FWE0P!)SHAX7S>6"X-`Y:ZBE^C[?K4 +M>%"S0EV]24?A?JO;A45^].#RYVV&AD_&DH.&4))Q^O>ERHGO(SH:[$(I,D9I +M46?_H+^Y-&JEIO$L:3#.Q^S*K*HC6PY98026$7CSZEO56(0^8YYIKL\WEYY- +M`H!S/W0M]_M/U@J\CE'/&$I/RGJ$MV,1X-IC0:'9_\G>H_J,-V%0($&94I,' +M/30Q=]$.M"/T98R[GGL:9U-1MY[@S7/'>9-5S=B\BZ0'(!\<2-Y^%DE;[<%Z +M4K*L3AD+\'+%]>?6/24Y_-[=IN&[_JLDD=9?N/[WU`#K`J'C3+V,<%OT;B:G +M;NB<+B.VMNL$A"#B>!P!I$06$R2*'K362Q':"?7G;NJQL!`8)%L%=4*[7SA]9,-@&C7S(?CI[7'B,8,9/S9AKC=>B!"=!_'?!F5SD`R`BZ.,XVC,\[)9OL&LXQ15:8@JV;)/)U_GA103L+ +M3QJOM"8GT5URW--"D_XNH')?U8C;W7[62-EKBY29BGR1#0"UBY8!6)1*#B1N +MPQBV'3J3Q55,<^+-6U^V/H1,='E*CW&5-0SO20RTFGKRXFX9O%Y\FM=+K[K0`P'36;/1[LS +M[NHM4Z='WCJ0C:L8?L1@I6?O>P;+4[7^S2EX+LK5B3-]VGW4?/H2'MWQ#(LX +MMOOHU1N!=U8X1L#6&+%PN +M,#5%0>X_#T'-S3*>+7N?MB(!;D-WL?BG:ZU0Z^I_0L!I[QT_0#[4%&V!X[H" +MS5J`^D<$Y"&,73Y+4F8C@T*QD/^-+_3FW"*@ZC8C!]@.'P[C,NDZ7(""8D+' +MR,0Z/.J:TZ>F>7B&I?GTI/*%MY7D+6S6K]+1!X7-R(7LIW%$ZW>]#-Y/%HI1 +M')%7!(/JD91+LOZ/I/9SOA.QSQ>*\S9D>=H-5AK]+0C6T`5:2>B:TR/\K*)> +M'F.]Y5+DKPTB/#ZO>G.:!\CX1.+N-?I_X=!%8K,V,3]*8AR"-DGY4UW$;;*& +M[/=,R;G>GR6*3,P(30AJ%DYYBI_W?^`"%T5A1511T]0R%N4_B?+;H8FN +M6S(,1J'F\A^0-E^CJ8OU/K^M"25?.9;G4X?>!-V#<5[$1Z\$*'O=HJ?D[ +MA"5EL:/`U`(PE9#$,"3^8`T@I^KG:#^&/JVE=B83%Q7(42@'"!E.#BT[7_19 +M!V'T1E^02A!*+2GFH'`:ZWAA4][8LBL8::[&&VZ$VJJ@KV6DUM77F\I$UU8^>/5Y(6MG7@;ZZ0_XP2I;^Z(P +M2;A:,,-U'`?9I4%GR)*!09S6;O2JJFA=PYBB>*&/\@E".6VH^)"D`C]&:$>< +MMLN_TZV1FLT0SJNG%X87O-B$'8G$=5\HT[C4*JN`4?GXUQ'[MIR.5L(+;3]% +MVGFG"]L!*(*IL"-1C)&$5T5/8\H[$WMJ@(V6/KM,;&TW$W[]518!2 +M1R)(*R&J']J-]DW0WRJK6Z"!V;CEC^5`SZD,:-3&[B1H;Z-!)"S +M=Y845?UF`]#70T\`6K6O(E<+;]:.;H!:`S]7T/\)$HC28+_>J1 +MJ2I[]ZLQ$KP`GCO0R/(\9E8_/_%ST\EF14E6W'=Q;GT)&3J7+T^1\1N.OA[> +M3F/8*5&T;%Y&^@?(FUNU%!/-X7(W#I!1,:+US"?HZ-+KH8&(.,P*JFY^>>3` +M7!FR9\*0D0CYJL&A3>G#X!&6&>I14A$]Q4WEQ<'@49[D.K(/=&:0>6EKYXY^ +M]?-YWSG\DH+0WIDL5B!3>?M+LN8&).DX`X'R$"CUQ2"V+F*=#LH2X,Q!MR+^ +MIU\@=VVES_B^,`*VS`="YOBQ4+Y2P-DF54[2Z8<(=HXZ^Y"):NI1]W8_8+!7 +MWZ5?S'T#)X0"_YV$H8%,SS\X(ORY(].1Z\IN,Y(<;U+O).P*SY?7)MB'%\_/ +M*HY;TE)(,.L^?(U)P17C@/VMX'V&E%9"4HWTY6PO>+@6P?E9TBVXWHU>5(O7 +MAH"W!R#Z?4GP\":UJFF-R'/.]K8\9QIC0@4;_JA0!ZJ>]Z_5MF_V=U5HG^<5BN96R0[>;7Z<*[:?8)$&(T$RSI<2PR$NGX +M@WWKUO:(I1@.?LW@18130693]1Q]K5$?@6706<2AV52Q##_+1X<,<8P80;"+ +M^E-=;T_LM?U# +M8200,/6<")HO\X00.BN-\=^V\9$4NYI*^!F)RIPOYP]N6>,/ +M9V +MRD"P_\WF#Q9>WW[K/\6RZR\S'&1RO+8L52XM^:1W;%O?/:$-#("/'='"B5M; +M0$IS`^R>$^A9KAA)7\?0Q.Q>V_'JJY0N.:/"U4'V;_7152[U1$2^T\VAWF7H +M<*M&J]$3,WJE%S-K.NN5#=@HTT?V-X]J/C=/;TE$;"+_D!])`Y5XZ$Q'8'>J +M)S\F(77SY[+P:?EX(#GWF[*QVA.E[R]^&15%IC0M1ZTWDC[\F2H!:4X')I6. +MVBDK:ZTD"#AHYGI9LO,\TK*J[U\W +M9DKQ"6VD>=W1R]8/)4E1[W1?#PFC5/N_F1(W..B9O-N'4%E5=K_/#:-(_][0 +M6J&;+PW`UH4Y")!YL?B0)#DX.CKM3^E15%-M- +MM0A,7X5L[]?S%DQ*1WS#VA^*N&.O`V-">,\S../,5)*#D>,N\[5:0HSP9DF2K;Q]6*6 +MHLHETHV8OU3(8F.C\NRK.N'E3^%2;%L&M@X2.I14QS5.2('0@DQ]R(K$! +M#LQ\!O4ZNLJ3C@G]R3!Y9Q3'!HY=GU,+]:EK5+=Z`S +M;CU9S%D\Q-LS@+W7&3?Z+KU'!IOG!*OS`_\KC$JPO7JI&N_Z_5#'M'6`S9$D> +M.G#QV9B2F(131/8G.-N$I`;6Z::F%IL&TIJ!M%,LM("RL#_@P3'MQF`.:5K(=2!8!,:&]ODT7M_16DZQ0?C9U]]9TL3YVZ=.R(PB`TVA1Y +M>FAV"=CL'2NX)>#3SOS"!0STW4JDJ0W$`:-0Y3CX/:[`0-[" +M(C!M?OR<8LP#U7I0R3XB'?_SI6(GJGNN6U%'H\@^,]-;:5E#",O1GPT0$T77 +M"9*!7R#U$S_=P/U$/^WL&/9SXN8*/<_(F4SF!!.F!C,#_H.--GN]RN37'!W@ +M_WO2KQ"^Z^8[@-F7A2:+700AP1#7VBT=NEN<^5[%'_^`_7#\#'7*AR,2).?RH`\E(PMU1/2%3_T$K0KA;TZ`(4".J1_ZZ:7^(Q6XS0/&D4 +M`;;BSTTDP@R<[I<%:/.1W6]G]GM9%43E"1$-62L7(`>)*/_RA+:XAT#8U0VT +M$"!=!X`OT"YET5=I5<'8\1:&D(/9+WK^(Q)NTHFSAG.+_,>B_8)_5U]"TK^S +M)V0@K@N;&^.\GV05G.(-TM45MMBPEW:,/ +MF*$&R^U$;KXT"IU:^FMI]AI!I6,N+'7SV/:/\;6.G)FGI(2X&^8#WCR,B$2\ +MA>EU#C^E_1U@-.MS]SS/^.JN?#G7()JTW>^9DW6U&[XO5`,SUC_A:^8H>OIUE)NY#ZB= +MEZJ83MS+3X<6+4\^T,K#ZQ&D7".DJ1&ARUIEE7+062P0^J/IES5?[;%&$0%> +MUYHN;(=BUFK,DS,2J<&`[)%3;LUL,\!3L,27_KQY;]PLY\.+V4?'`VP.P$E/ +M_E/\A0F1NC-#ZM,084#Y%26H^'*R^T]6-.5A/:CQC8["[GHD(TW +MY#JAQF\FPXIFBY,.>7Y!#,5NL>_&VQZM/="H&&-,@V.Q\EMZ;\R-%(-U\C@:ZB*@]F%6*[3";(4QQ+5!EB&2Z),$+H9]'G:V0O6CVD#VR10UW_J +MV^7!N$Q*"@S_`F5Q-JX8B\\R^1IIUMC<]_?(0]MV26*%"OLYYK9B8',&AUA`DDD2I0%N53YZ_(/8R:'M+W +MO)'E_\Q*H4_KNE"!VG$2.A>H_'BZ"+?W"14.+VD*KA.%FRHBQDW9%`MR"9X: +MMD/52QC^XN]+S,_%&R*<,50@G<'E*%-`2NRB;3[&2HF2$QV^5W9,,D-0''RX +M.1%&!%/XFF%;B?W5%KY<5`F*D85G]D(916(5:A'JO59]4UA,M-1PL@V+#[L; +M999@53!0W>.K\)6^ZE`E)9'[^>QIT\,2\E%LX%$LXR`B]'AI72U"8%9 +M,1ZJ@M9LNS(*Q?,2W=\TE:@_0SC)T,Z'`N'O4`9/T33Z<-2M;`1"R^C<"U+V +MP8WI%A?TX1EF_2PINZ2Z044,*D26PH0UGMMYN`VT +M8#P?\[.0;W+X(*1/FQ'^^8-FX0TRD>-SH'G$U-;3BW4-`"!\E-G@'3"KY;9* +M,TNTO$\WWFR8TPZ([F92@"&J/YB1BG=J0>NM__U(V-?9@,#-"F$4!"D$58BS +M$4G-9((./^Q&?AH_<.^S3@#'Q(C]B4;DXFJ&?U81`.#7C;!?2:9'O]OXI2"8 +M2^OUK8<[ZHK$UNBH1A?6''63##Q0YMR,94LE5D)L2Z=>-XPM()CK75`U].:< +M/_VL65O62!W*Z\.-H3&?B[?0X(Y5-;]^P>IW+,=STE-/Y?'I>U&8%GY7*8F/ +M/T&(;YAEOPJI_`CD'>_60PM$BP5942_X9P26_HGNMQA$6\'-1>71@K( +M$EG6%6A2DMR)'@0R;3J_*-X+`L1RC0<`,83U1.HWH;7_BB";G49-(8Z+(2M% +M`LS(,Y&*9"U5"2\^P<=;S>G+8$'YD_;Y)83HBHGRYL`.T%2KZZ,61J9T2O^< +M+\+HC"7`%PT#@>M6,$799?ZKE7>TZA5`G`,=**J586I/N4TQ.895$)1N28V8+@ +M6U\Y5_/[ZY5G>>EPG>QJEA3.>B;.(^YU6QF_ESI6O-X +M4'O$O'"9S+2_5)@3`9;[E?_AMNV+(SU_4KYX-GU.:95CB_!DN-TTPI??#J-B +M9^G5$2X7J$+<7IITB#*_C>.*:H/B,&%\%V=Y?('E>X61J[6M +M3/51"63[_/S"32^Z#3TUV7FGUX4]L$RPCW37C7!_*7+=?_0[.QC7H_L$.*:U +MHA0]``&:OBTD>+AHY4JIF+4FMSV=XNJ&&RR6M2(8R6AB,)_8NV57L,#]5F2Z +M&?(SC%?W@,37UWJTSH8NGTK<'):<*W*=;OK/FP7&$:.2<:WF)(!>Q19I,!_W#WH`Q#R.VCNNE'C)EZ+]\G*6RH'MZ$B9_ +M?A1'Z-)>QB'!1@_?;IP=RJV_M3U*AS%T9M +M:0N5#R1)F:O0\Q_Q!G[(YIYI,`R]0L4BL=O>3<9-O(YFMKW<75$$Q%[D'2@] +M89.W*?8:%I'#-F]/UBE[6XG<=0[7YZ9!FA'4DJ81F`7^=9]:9D/`9[-EBR4) +M"[]_#H;D`J9QM]WX.S*?#X@?$,P-.`(MKR]5+'*EC!H`HD]XNE12SB?.9 +MT;_V"+KZV@K^A*S^ZE)\CQ;P###&>.81;(^F/2=GT_O9(M2-.HS]&*]$:FP] +M4V9%,Z!Y`P%+W4_Y"M6Q;@U=1,$<8LM[NR]L8\R0<<_,NTC@>L^N3ZE('G*\ +MM)%]!;':JNA+(S"P;\A5O,P_1'TA]NK3SH($9[1X7?+%O;%33C`A`L)^.$_0 +MK6FXZA05B<6-)=S_REYFNBQ#U1R8N4?>8<=<-([EU`MZ%+4E@[Q-G-H0:R$4 +M8%@N*Y'*F@@WB/J*@'WY"UL8!Z#Q*K9?O-K^3CK9JHP0PR)Q*JP<>,@"B6(6 +MGM;?ZU:Y0DWSRS/`.)[EN'-P0R+=UQG:!ZS=COY@TEQA@XF/DS8S;G"]H?[# +M-3:3KE1)*[_>YI\"+*&DPMNC%M3WI@*/*A"J'WDQYV-N]PRBH&+U;<[;.'[^OT!@],)H_9)H&3:K5!KY&CC-=:.".]NU7 +M7D.R[KC4%\%X:9>FX:1D=V+WF3#^_%Q4'J/Y\!31'+KC4G&'W62]N_"U5_\0 +M%Y32R/6PU?0]1]$/^ +M!PTJ,XZP@\$[(7/8#A4GN%*N+K>'*VMJTX,#K-0(X]'Q\_4!^[U?Z_4[!!K?$&^,]Q49\WX&,A!4%:>O +M$S[7:KUH'Q#XWJ;]GA/Y1HR;]N`T#D_@1Z;2N7D6:K[R&/]D""HH%'_X=A`J +M*9)Z8,=`IAGR`P3=R!HYBOVDP>9*U$@79'C185C*LBMJ\JEJC5NBDJ1($]18SX +M(BG=5DA^U=9:R/O@X)[X7O>4%==3_YP4+7#?G!!TT7T[3H=BR3M05#?<9TCD +M0GUM+6IW+.\CZJ/LMBP-GCG$C?-2<-(?BV_]_E6&B[I4STA/ZBE,Q(!^S%ZK_Q2+P(T&DB +M(0=E.A!MTK\%%+'$MF81WL@N*C89\8WGEBE^D;HS-6%:N:RC,62/G%4>+99F +MZS[VG.L$PX<0^9\V))0X=!RF=XYV(6(:"IM"JYWR")3EM%7Z"]@--7D]R[/: +MA"2\-M#E_+/9+V"8`P4-T6<*S.RD3:%O^' +MD9&*17OESOJKWBK4'TN_GD1FF^(FY;T8Y$\FF"^=K+/L7$\[M_62-HK^!$AA +M50/SB+1FX;NX=0O5V1.8>`?G!-M!YB/'*TLX-+_(&X27(A'5U9G"E-^L@*C_ +MR+;+R2H"2LNJX.I0VCY%0&&)H57.GZ7O8Q7,_]A?6BW<)@D&98% +MLE;<(_+\#+P`73)'M!28P/G"S>87DL0ZNRAO>HJ$9QS-BG8RE`GY*%#"9\]5 +MK,MR1C/)_0:/[EZY7.)T/9Z2S`B%@2/%Z^M!;-F"%>CB#^C=TCNH+G="VAZ1 +M#5?KG0+\DV@W_8&\>S2JM)]RUGHKJ-6J!AA4T@K>&7=[5B_A1J3;=10#31K9] +M@G`PM=2=<@'BJU$)GY)F%O%OX,5E1?CREG;A?N.^=%Y,Q_HF".WHVZGA<%IK +MFR@SR%[3"#`P?;D^TANW;O*_,<#M[;VD>C>%+CA^B+?9.A/EB'I?WOC`=LM*&Z-/Z<;<'2I.*T_!N8' +MFKPA%-P>>%#RDQT&.Y('=A6#(]RUX2_0IVG"W.1#Z-L$`5\=L=S->1;0`8(1 +M2F6\EO&H@N!%5VKW*7\*\L^M;E`#JRP8PG(OG&)8X>F1VS,K9D"Z-FTQ5@$1 +M1J%*"_8LW-8Z4O0"\OE%J%>?V@X;1)TU'3,IS?@*>-8T0/N +M_]O,M!\Z,B3FILT23XTDBN,2809NO^LMT")]0][^-&BP2[8?T;TL:,N@TW%8 +M/.E@5K>W)\E,/=Q5`W`_.>#MF\/YYR@]<;!7,7V'00HZ-^>?6U0]BRO]*!O` +M1Z<#Q4V234LH&>:P1(-7:FA<5FZ1C9!C,A^0;^YF>DO<90\T)#BI%_#::EF- +MMC(52\:L<'TA@X7P4/#N>&D&C*J$AYG:1E,+LW[<.'C,+&=*DU.J5$`\ +M@*:NZ!!>-BK^@B==/;*/XH#^-K5&]%MFT?P/G$EKVH%7T.1;_N[W^@.K7[46 +MFK^-X&JU0ARF:-MVT4\?ML-;WGN/[Q*".DV,)IG)#G/&H/4IDI7E6WK?E>\) +M!SO5UAC]"),J"D,]D8'B.JV&9[0E:(DWO)?IK2=]QN%VWZU6PLGB1#H']PU* +M1C.,-M]O.1@2^T]_O\$G)=.K=-0.C[A_:?43 +M]&3WFTA<5MX=@J!@.AT]Q],^V1$(<;!&S51YX-3;@X+DWQ,QL],Q>'0@^6@Z +MFZ;D+'IU*FX87Y5C6N3W<"-L%(TTZ`L=<6;^3E0H\7XW=ULN2%;3^80ZTQHL +MLK`TM#`Y0O8_`BX0(EYEL8L(]*1M_9SU(2DQF01#Y9QGS>9*-;E+06EPD^!@ +MV9GHM*Z*[=[4'^?#]7\!:W9J*(ITL169HU\,]V!M(M^_,YDQX*7,? +MC\`1,'@XZ;":"<*18\T!W +M\/9$K@/M$*-Z2KP\2HG4$;1!V;'*4*S?)D%O<40].SZ+COKM*,>@Z+)38V2Q +M3:14SNWZV'2VQMS/PNM%,BSQC13:+>`VA%$U$2:E!'3VB0L@.])+`0E?K.MX +M'`4QGCE?RE$'^B`;LPB2YT>V+6''W./VT-X&R-$ +M]3\=]G*+,Y#P[Q5>CU=#FX!9($Z'8+EC=[%RM\"J>,=>T*B'TU4>.TU"/7Q` +M""=H!2==[/;8!%03IR_>E2075(>E-$\\G<%]%B^J\+.P2"562,?@5;%H20RK +M%'H?\H8F6IMVCR\7`VS;GN>"C+IKB-:S)4<-I27VE)WD*&-@G]C&9;.'J/G= +M(WR.(%IE(.:HR.MD`O4_Q:*>4I;MMO.$9G4C4Z66XALE%E^4M"PF!3N>Z\\6 +MG6W8-)S%+$**.;%DCGNCO_TO3L1/Q)8@FFS)NA@,":F(:#)7$M"\:3?1LD`; +MO\*N\*7IQH62>IEN\0X>G+O[*&3%":2\TO>NGX6Q?X!]1L83$HA-^PH=#J@& +M"\R2BQGE`K87!?]*I2AZWA`B;O1.LRWB'A,&2.+K[S;4ZE#Q4=M`16Y +MDS/36BO?EE:E!8$`]9RCW5.PD"ENR6WJ)*TMN7R@55A5Y.F_SIW7 +MDOTE$OEQH2Z?*+?L_7"3>,#&[:[LY5B*6-"HW2>Q6=YWM!?0IUKVR4Z.!?^MD\PBPE68!%A +MATX-+Z=^@O9D;>=RR.SP6Y4`4TU5!RRD`W[[C:*&Z#/X=V"$.)RM8H11>K45 +M\EQ#+(D%%WQ3W\,U])6$\B]]WE*!Y\9VQ)$'D8(;W:$L/T_QQZLWPB02F]2: +M->N'AW:MX;?+[&),N];=QV5V\4^C\O<7Y+?D,$_STZD`];8,[S\?AD]?22\_^X+L?+J^7*A8WS4!29TYA;JQ*6G2%7 +MFB4W^H9`%!1F/1-B0D>XN.R!?KJ;2 +M9+-/]V["32XEW@<"!ZWTDEJ(QDK=:WK?5$NB2S&+?UE3,)@FH5+FPML4PBN+ +M-.'(7CA9[VI=:.T'Q,U@OM`T)GHT]>BWT#7_8HE\V_VB\\N9A\$#WHZ)@=M< +M>M2ASZBS$[#M_RI%?WAWB#YMF1:6:@ZQ=.BPD*5I>'_?:=:?IWN709%[="C3S.2BH#Y=_#$TA +MX'&*>ENL>W`>.N*F@F.&H.EYR<].F[S51'+Q6J]XHT5HSE%!`KX@=:M\J2)G +M10,C:T+?DF4XC%`\$UUS2937&31GMF/<<3Q/#*3*]BBK7":>@;>77_)E5""BXUL%0DZI5 +MJ)!Y:-MM@L(DQ<:J(HNI[_Z7#M9":/VP.KUV$S&F&A%HCTV0"-)-4;@S.3=T +M[U(@E:IS`@R]MU*,\CW`*RGVO`.%GO7H*\W6FP2'YO:,KVZ02:4**0I0-297 +MN0]DM#.*7&;G8[68I1G7B*=K6M#73Z\,0DIUI!I4MS5/DJ+H/J)37%79AF#E +MOKNJN'VF[Z.,ZV:2I43S]PJ +MS>4\\T+K[&ZSDM'0P:,42KB#PXP]"!_6\!O65$CLFMFA8L/@>N=790)H`)4A +M)6"QQ7-BIR!Y6'`B$,PX/;*=Z?"NR*+21X.8IJI0,0>KE%K2V;XWXL)SN3,V +MQQY_'',@]LAQ%68?81N\TH@YF&I`$7PR]J`[??L#(D(O,]K6;F\>Z$_\X2=: +M1>#X4&9,0Q_.NA[^OQ9>D,%;'5'S&OB\JTI>'?T'I-.LYS-+KX"+"O*=%1)] +M)'TIDAP00U[[,%XP*^H"D@%6WO?W>3,X;@G5[=X3!WC=F)OMK!%&ZO+\LT@6 +M#":;;=S]6&]%FYS^GF7)Y$TCN\[0HG]1*G\8?["O_BN!,:S+YN_O'VFDOQ7%O(V"90N@X<7+Y(!E\=@"X'_.FXA`-^UUN>4?X +M-YD25KET3D&W.5GU[2C`2>'!>W)F'=E%_!WB^!;=()0V +MF7Y8EBYN(PT>*Z'LJM;*G[U+E:VM,[+_W# +M=;-G=9;1IO@YD9LU(:8Q10DK&@2C;A)$63*_`,WG*(Z7%6LL['YZ>:[_Z9XMIH(=?VF(G9R +M#WBS["`)JV,#1/DF"%G,CF""S%XUTBL\Z<=;_V?!`E*#HAM(#)L8F"2(I<^% +MK8!_`Q`IU2*\.D$X_352O#!)JLK0GGF%*A@`.F-ZX)?5HI%)(T#VU^RUB +M>/[/=DY\X[_0K1(Q2ONW\>6UL2%]Y8B,**LQDMEDYY#*"Y1$L,-'O-]>&)^^>_EDQ$EDYJQVZ/3]JG+1;>H5^YE1D8`&%8[ +MZPKK)\PH=*L%HV(GV*^=(D#"UY3MLN1_MMK7YO^;`@E5[.692RJ?0R3#/4QL +M)E,X93]..X9#,HD?;GDHHOQG=JOHX^0;)S2BMHDUR1^-L0\\?(B1>#^Y:<>NE/KP +MV]T)7."+9:.(>W!;_.2!\,S,=B&`\3KPJM,`>!4O_7D.]$%'^_`CV +M]3Y#VE9ME*BG5J!F^51[\UC;XQ@TI=K4D"_2J[::(;\*5:)ZR1EDS,05 +MG+<3_TZQ9`X!F%4%#K;\DF17Q'FM8*C0]5!@&NF'76B[:.+Z4NR_JE4U25^( +M;SX4)3HC..^VU@Q[(9D(7V0!FD%>7^G?(]Y9H- +M\Z:5DKJRQP6O!O8,PO,_BE>`C.^NF+O[OL`&'4I41HV))`*G2T=/!).\H%^6D?ZN\OKFHXB=91SUVA!I/7;D&N=Q_[,%]`".HC?Q'$R#-#J +MSGMO,5!29Q!K,7JY-0;BJ_%$I'F&J2B_4E#-5FD])JR\?0L;J^JSR&876%.; +MM17FZ.!<9X."%LU2B5N0>$+RP'GLZEY\\I:E,KII#W\TZ(BTDHJ(3LE80F>#>/NW]M\45+ +MM&K/?134?31\%>GL=E@T;TFV" +M+#"Y<^4;T):(M^(W*K$4H.S?T(.00%`OCQHPK890T65I5Z9RT=9JL"J=O<4<1&+]" +M9JM'1?K$^/1K9V5$E>YBR4VI/R-2_[JPT$"5DG5&3C3Q-7+8K`W8WR)82$QI +M=X5HFYZ>R7SPC%1$PH)^]D4&M(4V9OZ>2QS#YC=-<4$]D)0WF79I4KYZV_#A5),[ +ML8&_7&V@:>2%D6RC+0_0I"P1WU,T9P&LML'U$]WA_+PQBU56!YY4MF+9WM#A +M7ZR-*&RM;45N8&C%>T;)-)E^"=/!QB`N> +MN9JFQJ%0YHUAOGE35U7KY6D[D+AV?[LJG4`".9\;]J9AW.,38]$*/BD8I+9;QL&%'N-GRF!G1Q=EDTA4-RE\R;V%P*3, +ML4@VOEO#AKG2GRTIK<;9L#&X]WQA%!>>LLKOAP=>T:.G(X""AHK=RDMEHO<* +MI[*S7__./"+MR2KPHZ6,K>Q[>Q',G=TMUKJ^D5VB4.ILG6J#?'9\>FE&,2+. +MEFSUG[0@;:7[9;#,%AK&]O^XB0;?!;-@=05B[YV:U9+KGQ.'DT1S0/P#VD6= +MWXA[A8P=5ZR<:JNHCXP%DM<*YY\_'P]PTFX+)5(I]"UWM@/_Z"!9#>NW,P/A +MNYT?WYIBT/73L:$.J*>2$A$QR8/\6"SQN@DD.R=0[L0/J"2G6\M::MR:F2SM +M,7*;W_+G&EOF#'_,4S*N-L&J'?N%'TQF@Z[GV0"[MS&043\)*78I27;L>TTZ +MI2V!QJM/Z(?N+B3&L)MCWB-GH62SYV;[B\3L8R]0Z'$<3\&:F4;[QVS7#8"*@@_T$WAIDB@TEN*1E-*\H6D_Z4!<^9 +MY.Y]TVQA6*Z=!)!(,`[8VK@L&+C)<'4#`N^3R';4UP6%I6R5@X +M5$9^M@Y,!J)M=AP>?(,W/J:Y_7GR+*`H"*;98YO6NZ[`E*-6"1E)KP3Y-@2? +MQ\!0(5[CA$UH#,:"QN-#VL^WI:#=H[5(4R",%)?DU)5N&;L03O>D#D#M]?E5+GPP,T7V[-`J*%[CQ` +MQ5)VHN(:+*"][#CB+YW=DCPBIBK8BO"@E5V@R(W&OAD2$&:N.^F#$:26<-F\ +M*D_5B_1P>2)BW9AX&<4K>LB69EUBD(WY/15JD3N4SLR6%9&JH$5/2\=BAUW9T<$6*4[D^LK/IY4^4CO^.,0M\!#_I[(O+.NR +MME<1]8$8*,]MF?7'"L@/EEBL#4?] +M3N>7T/>`ZXJ<0K<802RR2+/(,^!&L]XADG1&?2V)#TD^:()@*&#-.XH6[W%W +M\QNQ*K]T0Q+]L210=UCH&1_G/H=[@E*,B>W%H=^4GY84V']L'6F1(AR(V-8` +MO.18%T5(<\RP$U +MH6,+W'`,]XR%:@\VU$,0\@K/E;>J02&$;N&['F^V8^S`3^Z_F]\V1SC\,[E5 +M)/N"6)'G"#Q9_-54=[C*H)_[&BB]][",DZQ]-F[0?_2Z+,L72QV6D=B9=/\@ +M9W[]@6O->CC!;[NXDIM>O1>4LAG?HXS<(@]233@R*`<0Y3*@6Y;^[7YE+K.& +M)^=1$B`D0]M=&B,?.[ZN>&2*@#4\&Z)?;TPP@6,U^G->4MP%='X2BU!=4%&U +MCE>R>KB7L'Z-@0%Z@5&JX5_[ONWMA=*+BG0/=KHKJL)TL3W"J%A\'S>D(RT24Y"EF_ESNP"A_.H +M7#?>VZR$-&89(\&3MF9ZL"P#>IT?WFKM&%1Q?(P>43!P.G$9.C/$+X9-050* +MDT>+=XD]9WK'JMVC,EH]OF)Y]";-NPV@--F#O3B='?9-Y\=2T9/K$=)3VN3+ +M[S5E^%B/NXA;0IF.98%N0`(Y4EUXUMW[$Q^N[;TT;'\(2@<[J6TOT/,B==I4 +M5\H+^ZHQ0$.+O$>O2:]D)7'02"R\9;O7IK=O',!9#QA@QN?QGBY/L,3`OH7K +M8^*@2Z]+#+^0#?N8+.;60K'1"0=\A:I44YQL?(N6VV-?+=`*64+#K18>!.?U +MO$#7""(GH=@+"'ZN<9R.?BA<)G)*\MWT3):PVXQPK7&']*S]M_J+XTS>!U_T +M=RS8A(GB"67Q)O]X1%S*2%[Q!1-ZQ8_G_00S%_.+@XZ8G*.Q/Z$PX_2A&STI +MGU[`3D3ZA#YK%;-^3B8JJ0D"PV6W.=)Z;O%BP@/=NIL8A$-%%M*B/N-@,.;Q +M"*1,*8-FP4HZ:9+LQ;NW>8JX3ZJ:-+`@'&IL2W`NYXD7W*+V*`?\.J1@KD&E +M5K1)8D5`I!Z9UHI0/X&P8RI7$2Q-S^CLL/Y9O12WS0DMO,]8P@I6?./R;T"0 +M/Q#0$U39Z8@W-E\E(BSNN&J#R$DFUYQ%@+$JRHB_T7MV-QZ^+DL(/3QM-75];;B%]8+HV+ +M7N?X;5DKZQ![/H"GM8X>!'/4?2DPU**>\D-F,P7M,FL^H'LO:E=6`;,)KBRN +M-PY)!LTE(AB)MKEIN]ZQUZ*ES&S8:S_/F?TA+)AY%,'KN+`4+;3(-JRA]*0; +M1`/[ZB,/YN/P/N36KE4O=AHVS+\8-YIA9 +M!;F=?/E"ZTM'%T1;Q3\=243!>X#G*N);^)SVZ[MG9\;W!98%O'XH8&I&&6`= +M>SCF9U.392IB6`4++],=;6$SGHBT`7&>J12XJ>!2]V9[?QLED.\\E7)6M6I& +M960WFU$2V>%[9$+OGI&4_3(IVI-PI>>96)(A5XQY2C2.!Q?BOTWC/)[1S!EF +MW6(%^U3FEQ>&"A.Z4X&#M_U%DXOU&;&K<`@IU?&?U!*":I:/'%+X:^@5%4^3$1ISD="7%.^,N=![=OEB^10_Y^'*FE($3?_G7V6*2D7;\9GFFMP62J2%L6_-("C=C/N.Y!N"GR&&)G'A:9D3>&[_ +MIR`^U2`6GOIEO6E0UG!O4T0+2<^#,$NFI+ZQT#*-X3I5W[NBG8% +M#^O;%]8M3T^`CS)`31H"F-3T'P3F)J/#+NLMVZ[Y"43<:&]XE(JA$C"H63,1 +M(T>"@P/6L"`_78Z.AG>T^T$A?S`3H&23 +M"F6H;=1\04JL2;GL\*8$#L.<0-OXXPH+"F:3]\<&\YEV+DY0CT:Y8),7>):2 +M;T`U4=#I)W4_\J/(6@S=DRKBQ@[1-MX]]6N6A)]+OXT;LUKRDVK@)?@L$/0N +M&,CVN$QY20A6"W7J5V$6S!SPU.4YANAXAJ1L%D@'KW3GK%DJP9_[YLJ=@TLV`]9B%[EM(3S*?E"?QZ9RK:.4W"53+)O77*C]_"W,=0)P?A_L5/['@5;I@VU((]\ +MI.L^7@NN7E_:W(\RAXK_Y76@9U'L'@K*ZK23L8FH9^/>Z-HY_E>*DG"L'G"# +MA-=N])W`N)Z(H?Y2";P+"N//?)@.KJ].=PRY01IX>BXR!]!JI*[2VSA(<3L5 +M:O3.X^7['(T$"XR0U:]W:KJR046U_23;&<8_C_!EM20P-<)Q#!YKIN=+W=\] +M;,.M57_'".19355V'KO)J9DE#5*AO`ZTI3EBE2!]\4!5>.OT?R.]&-QL-.#6 +M+P7Z6:H6QZF52SQ92EZL4GC='RN75)ICR^?J?NF=?I/&X\N,@[6<\0Y?+5(=WL4X>Q0`-/:;>]^W,V_GI);TBXR +M*"OON/=9FC9O/-#0K+T*@5?FT`48-/V:/HKGF.MQ",K!D^V-_$I/+$#9IWW; +M^_6M?L@6F7C$XT/%UZ@8L`'28I.-RNS2V.70;1T^7M/[_UGDJ!S<'(LDO&M_ +MD!C*"U.$J87*+0\!V3&<<20L@^VI'WH#YU7O#Q--7\L3@CS +M\,*=8TQPI;8HF\Z'5W!`X\OPQ[[%`B1RO+!YE\>KTC22Q^P1'&!'*$L80?8^ +M>:CB86/+X?.'<"CHDQG*-JU=PD_-[^GPN'-4V.20ZH/H/B_`(?&_=43K'0`I9IQ]VEP`?X +M6?YK9,;:6:QIJ#-`@U:+N!^MU:15QL?(QR!_Y\7GK-<0HQ8>:587QO@H2^`_ +M_AOE&VM/O..W*3_WS2,)GR1XF@G!P@"GPQ)>X-=!/6Y3\2I2ND;PS"4U+TAZUC'27\US(%T26XHV62;4-&0XJ$S. +MD:+9A=96.K..*VJY_9K9?55P_7';')0N1M]$'[HQ`XN:_2Y/8:M,Y&EE15R,S7OHS%/1>#?;:/3=%"TQJ!(6Z$?Y8., +MHH6LYE[^2;9R"3GL#0N-38@&ZH#V3*S@]2[V.,V)Y``!UP/GY&/>TY3)J)&O +MO6091MWP1]U%J/XXV_+=''O(O"/>%:`!1-T;CZG?<J)OJ +M*FKJ/6(KI'TK,6"M?<6YL)7^8=DV,Z'@1V3]7A4'-'[3#8X&PL`.QX5_B,,! +M6B/DOVLOUA8I@_1L6@^/E)D4J@(`>A*5;X?);>EP!MO1H6?G2S(I#BIJ::^2 +M<"R9/6H4"[22T^%RE$LSMJ\;B%C?[TD?!SG&+[X)XX^7_"6YJSD/]#RI)$VQ:T0GZ_3H:O9,?5E4-L"'`11[_G-"!]F68W5H+U= +MZ(+N&0PV-;(;^%.I2@SY`"?*Y3X*M'H?XV322(P2!P"#K4*A(R^_)(%*CU7L +M5^>P.^XP0>TFFO.6HL5$WVRKA96R(EG`]OG\[%`R[M"@F$IMV(19L3`;^!Z& +ME=)^._FNZ^<\1:1B[_NY?GF[#-X=$%LKCX$A]4\"!@ITJ8HML9C!RT.\PBBI +MK..E%QN=[&J_]X.\T1EY-<2<2+IO0_S/,"#E1\*EBB-B29%5LJ?CH\34(&'` +M,'!M9MVBY$5''*NZ;HW-V\I#``XYN\0OWF@?E\>K+>?SUOKC./>=&V7 +M;BKPA9@CW/`TF#SG**]3];H#'8K/1@^\N$D/6DX@JZ4>&=FWOVSH8MP=ZZ# +MG1MNRQ>S'FK$X,S9S&=@)%.<=F&I>Y8AW78I@RM$:6B3.UZ*3W.QA1_)9SSV +M`@:`M%4171MJ4\0:/HDZH5T5YH0;`?5-L+U)9]H9/%[/E.\Q= +MM!:GKW>M43%R,"8L)"1O/Y#!_O0'(*R/Z`#-YI@E#A*>6N0".6]@#ZVQE@E, +MMNOR:RH\;6`ATA6(A!YV7;R@I]OY593CK,;N[/<,T'_M7*TIK$%?UQT4$VL1 +M&,#%#[*C4XZO=[Z:_J,#;/;#*K]_SU_Z7/W@*34]3^Q+2,;N6_W(U$TNLV[W +M6VP&UBWKK+=.P%I$D=.W@#=\JR:__#>VGU3]+)Y5(19 +M(S!G^)!;L]>T=;=*^:0[JI7F:Y4@/Y'Y]S`F$IB0;3,1NX"-K;'8S#GA&`O] +M?M*EB*+F:5A6K.ZS,FA'AG.UZ7-44*O:*OV"31WV1FAB3!++0I;\6OA3K(`! +M(<9QQN[YZ&FF<>#AK_%]_/8FW'K5YR_T99_"1.VP:YE5@@F_6P(\KXP8\8\ZWCTYGFDS`8 +MR3I)YO_:D-GO/K1/,[N9H?>F5D>\CB]D)."<37$QGQ?:G4IMN;^[62,Q5`KE +ML1./K?:#_EP5=>$TAXF&6/.8*6LF\%I,ZMEB6NV$R9?&XQ>]1E"E\W5SSLL93)6%6@=.N"3S77--:8-8" +M#>-1BFPR5V.EC'7\=FX@6=682\$&+H8"N1O19HY+3O$E=E@FG1`I][0(1XR% +M^1N+*G3YL5Y]NV>&PK9FK(%[>2TP?1\Z@!J.;U5P;C4N;A])HC1,?)NU"?]- +M^..^-0T[[K0[P4F&N*"YH`K$]A/Y$?$;E7_WF^W +M*61Y!F?2-MT13?+&]/NK;?JNU%G3*S +M:N0S8F0N6F6K-ZVP+>H$/8',0&\]H..)M2/\0U)8:F8@9_4X8$W+*Y_!0:+* +MOEQN!LCC_FHEL'5!2"`1=WO.!@!N%QTI5YGMQ5FL!Z[1R(W.(R(*1ME->V)J +MFLIB/!_BN3?.A*U6^0A;9I))`:CI\\_W$7\GE/>AD+!A_TOSST**$\>MW!)4 +MM3GBQ+3\-82\*$\/9^BE(T"VHY5;Z5]^<1L[@O`HW[85U[6>QS^IB9<*RCZX +M%6L<>;QEC;M(T#P2:EBO#+E%3W3&RQL%1C@3EH?)]/M#UYJ]_"N=ZQ2>GD); +M6V7VCG./0K9`6JKIH=N>?"Y8-G1].7-+]`-"\R21_M#KJK243%K^FG?K",^1 +M0G&WDSI6#+X5YG[DX=J!YW\0HS5#5H_S$.'#C\8%RBX+"^8ZV0QPQ>K-1P3, +M)$K5[_]WC(@WR8'M0@B\[[W$3^JD=6.E%IT+^9T0#TXZ# +M$YNC4',23\+\PHT1AY^1.V!_N/D(G"U=RS=/0)X]LO$Q#@9`H3&!M!, +M_+R/$_,^:L%XU(7W8:8B6"RZRQRC[#/Z=F'2AT?(3ZFLMKP8.M,/B,NU4#:- +M+A'A7]>OKV$OZRBXPQ<([T"_T+-MD9(RAB@X,@J?':7FF'E[.]-X")GPXDWF +M)J`3!MHUG3#V#[0+L?(*<-B+&:_>"Y3X+.A;8A(_"-H&@H8>K1=)U+YMN8A! +MN?S:.K_(\4MJD1B*G#']1MX=%#2,8@CA#41$4]RC!A8N*Z'^>D9%"CFW"'"$8Q`U^&YC;&;W]`%C_LBN)$GWI9\'0P0M/=% +M=/7`^3-!ZEXDM(`\\YB/H9XB8&I>](<((NY@JBDZ=I'@*S-&3G28M6>2NSM; +M0>%X2-!P\$DOX?485FEWM5B++&0\Y^N,2P->XS^D,*W/0V<2,=)?5%4(63=# +MK'L=4YFI]^\+3[:])8J>E=)CZ1+1QIE"&44F?OEHVL(>^58[AF]"8)YD.EZ3 +MPYSK:U0P:DQ93R,_;RZN_:=1Z0!U3-D#4]M`,U-9O-?!^2/T9+)T8W*^!6M/:U,C%Q3<&'+=K4 +M5MHX8;G'H#DST/;JIX,.`7,P_8?B5K-2Z'O4;X#(X3Y[;YN6D*>GGJ%(PL2V +M-:!NBL_/VO<#9]B8)0N1:7D@'_R\2HVNL6ZLX'[7UJUY?.[%QH9X^R$GD-6< +M1^7%L0RMG6#PE<'[R(PG@HGDL6IBR)$\E+>/XIS]B$\X\#E))R7_S&6`"]IN +M6C2BNJMHC:<1ND(81*<*P[_R.Q`F-G0K[@!+(B[8OS*1S"=YE&*":I\4.2-A +M"1V]\JB*ZM%X[$\^3MT39`QU[#%@PE?-+V;]>MG*)C+_Y5;FKNL1!3H5!WSO +M*-CCWZ:V%GO(2P;[HP^J]M`MPWF6$I;WF$`))=C/CV,ZT$3X>5E2HO?\1L!; +M7N4A'.)5&&R0!MQ!N<]HX4KD[/+AE=F1_LS_,D+%-8SKE1K6657-L$8()^$6 +MY:/'X>K>ZN]GH+U!P\L./XV;1DAS+-,3I(_*.$@#%1(?/%ROX1;F5"8G57:4 +M>SWSJ9(5O:_<.ILS9+*URXQ`Z@[(4?+3:>_]#)ZMUYT*A+V5>P'<+NU\D=U- +MVKK;PQ.;$IV&B2A/L':HZJFTG6B>^JH?@QX50.=6B0<%P`BHH7L`PZ]U+OSM +M`O*H1:2,.U84]5>_]65=6!?G*?!)B)#`UNSL3)"[?+`6PC:AJNS@0$.%3^Z+?Y;1>#ID^*,\EC` +M+"7_>1>J +M<4;0VQR**])X_"W.0SC1:L!'HSF9N(RG)8YJO2%8.4-4L$!ZOWL]:U4V*+:% +MTF8D):4\!<*7P/_71IR^AMFG0GR8>M].Y4YAJW'UQ!XN&Z\0YL[=Z;Q<^5IF +MO@M._!&M/&GN]VI&(M4SA'(]5,*.;2MBP=Z8_#+K@-4`989YF1JXX4`1:>L; +M&@@;@EQ8LT_0W(]J^G=224D%.<:>$]'E(T'K.)H:@)+MQ_%@--U5[EG,MJJY +MW>6[8.07D]2#P5@L^PS!%W[I[6Y/J(27937I.3%_*[O>R7`^M +MUVN-T]&8:JR-<]+\4&&!L656UB_LM\+2FJ#<9_J*"[GG"DH*%0M33UC-K,VN +MLI)Y<1U^YXAAD_P4CA(&2SA_5V2>E_M5!7[)M2IXV@IQX\*F@B@0O-F>V1H= +M_[Z9;BFU\"?>[H$1,N^*C7?6M^"R-M>GD#F8$VZ8VRH"ZY>=M+Q$":":_^" +MC-(B:*;$PJJXY)=!3RIZ2K1#$D2*\V3NP+K4!Y7=J<=A.#F4-GC^,]_.L1NX +MZ(>B*[U&FC>)TFU)ZDFG42(+GT919+BC#LVQQ,KP$.A_U_A54G&4,#C]M'Z0 +M!M-3*\RZ/H;V[_.E3N"(:WOGMO5H.*?QDD]UH&P!A79\6H9VF+3\*VI>[`] +M1V/I/$*:_MRP#K7:3GN+HFR"8VX[5(%M6!04`6$>7_Z`2-C/V13!&0WV&@D; +M=/YC!!>1SZQU!.*481B]$L+Q)>POE;O5-!W[:6(]`M6*BVJ.'EF,8]$QA!:X\N8\<1 +M)+!6Q]5E6_+&E:1\Z*[*/:\CV/>DW;K:1'X\E`P*G?((*2FJF#'YC@H%QPNJFAJET7QM`=Y3&CS%`-6EQ7)*/_93HQX@D^'E6=+.R@QNZ8H?VS#;)00K3ZA$+JKESNM8,]W]]]4`7Z`T'_ +MF30QOT$Y!R@=1I74$8A\03H"#9[+5/$D8(0SE$ZRNA0)9O9$7C$1S3]^QY6X^R6FJU<>1-MW*(. +M1_I!(>I#+UJ;N@P%Y#XDQB>R7X\.%%0XRU/`CCI`JX..W:VFUP%/+/VY@#,W +MU4@8%V&..3H1<_E_W#9Z[ML+5B`ILVG&(OM^E[24#%3W^1=J98&P);>)<:>5\J +M;6!BP^0QG"XS)*UPJVAT_2"JQNFG-+>A:W)G""K>%[1\`&IM,=L0IXF9W$O%RV,Z>M8K?+/L=%9!405FI=QQMC"&:RQ+W"P@/DXFV([]0$FZ,N>PGBY4GK_UJR-;=$VUMP]K +M8WPJ@YA2AWIW*3=[[\],DKI)#L$GQ+^Q8-=Y_;$=VB3CNUXE;P)PGHFW*3"I +MAZ#+6T*.!;Q(>$.=%1*HLW9<[C=+:%YF&X1TH90?(F#V2B+'C,>48ARUK+;Y +M)PXMB7DF^I84+CB0MHIU5%L)#>V!SY(.0]"J@R_4<$$#E4XP/51!G-7N#?0S +MM16"=^8_E-^B(SQ>S;&H/M-YCR?>9F8_7H[VR7<_?'W*6&I:ZA19[ +M<^*TU"8;W_A*\&9 +M_*^V5M(EJR`[X@41;*0^P`&.^L&;KYI#D\>GAX;5VQFZ>@$CZC%O(_<%']6; +MBPFK[8FVCU#&*DE.U&AG)9@4K*Z6OOIKY9%M'E).J-7]R:G8KV#'MZV2!'DP +M7@RR]-@@7*QLT24\3=4FT'E03DA`/J"TQT^\G`R>3R*<_L:-_0,]?*!=[E1A +M^P2M56NN`&+.:[DS!PE?)PA#[E"^=C9/L].GLDLQ!2<(PYY46"U(G2[7SR'5 +M%X`W#2&T0MP;=IO1]MEL,73`9%OK&5I'2%=_&_$U=2S].CFQ\Y'23+VIJ]"Q:`88NI1FLW"9ZJP;0.&U[<-/ZF@Q[/ZQ.RHSI20;YI=GON*5,'J$LIW+H@S].[M9AM*&F9#!) +M^5RD5SX^9X!\&5"9M_;GM#CWW?'5,K9T*SBM;@X9$":MJ;P5>4_&CQW0)FE. +M&+-?U:A`4D%4B_^SL*+%=TF8C02\NG);P*D_?/[@A,\6<%X"[3I4+1F=625_ +MVI=PA`0PA:[/FQ$;:2ZC^A'@55CTZ>.@I:R_!32",\>4D":=.'8NH-\\74&" +M@&+_J*&9=^)A,J;`JAOSF3UI"SR+JJF`D8ITE*,V),=:N(\)D"_1XS/9G"N( +M7JMB!0QTB;=BA_>EY/)$`.`/]48TV4P2^_K*FWRY`%"S0R.IR?IWHBT/,8O3 +M=>6)ZA]AFN]=:K#BR^_^)4/_.:?^1K9_YVT,_X6\B22^A-R?Y+#A=?+>6UEJ +M#OVA,JR!#[X/!ISE^G)L.,=S3U#:KA^U< +M[Z,A1H(W]\JK94=^N\4+Q%O1[KYW7W([+V"`K+P'#:#'6H7B#B^Q@N"1"7"`AL +MM[M*#$,5PD!^G*)UWDH%Q$H&KW65Q-MJ%0U*PW1CG@$IQG+T-YQ.BODM#K.E +M%3RZM\%?K+CY1.<*NV=]D2[L4KG3_@33R?+,$%E"!W%%1:DA=^HQ:B-S`+0K +M=]2DK*F>W=B2&IXC)FRX0*&F3@B1F(5[0J1H:V9MS+'.X'N1;AT47RS\4`H6 +MU%DK*`&ROR7MXO59##%8A_;72]%Z/R&#-G% +M]Q''"FK\W$T@7";P6;KG[FDYVU94Y'(.9VB3&=7#[EL5]P026NT=[,>)E(?1 +M_OB`\WV6^&R5!77;'0;\J*"W?!Z'F2+#(0S6T`I/YS/B!^+)3.XE#3ZD- +MCG9N7R*,N,U@E9H*(+P_\KEO0H)F`6+YR$LW,/ +M_E[?/WP?NY0PQ\>@N"^)S/W-S9G<,J--D;4+UEFJ2B.<);SB2`1^)X?A^_"[ +M]EJ\1;R"Y0>Q7?SQ'DN`%67[)G&";(XKD?Z`]7JP5O[C?:IMO!QDB$[U'U=(W +ME[(_2`?MX4/J"GD40'90`@L,;(.O-X]$KO/U5'_DJ'=217!G%S$W1_VD.NF' +M<%EMO;08`GCTFB7&[9.A#R.@`Y`NI[`G^@:Q4"]@X<(DKEJH:8Q>=53E"(=$ +MZ--MB6$6(Z?,Z&ZT9C1_V!7-8)X(OJH#*0MAP1$F,0#D3K.J%HXIW(^[`,/8 +M;1'R_/8@4,8DU-H1J6R(1#+7="XG!P[,`:Y8'I/JF(J^$0#<9FF]!,2$(R<'NEMC=\:X(%.6X(?K"_Q< +M(F-D!J'>PO-K_\VZ%!#Q5MQY)G>:,`K:K$03Q74>]T2@UV,?I.6);IE=1L*` +M%*2B%_7GM"MA-]+IG'\"B$&[N>E?2%CU\)3>H>AVB87.4F`BCI(^-%/+3S&7 +MC^Y=%T'BO0%Q@RET2J[GI!TLUN/P)M[\Y5TDVSV@UN+E8]!@Z6M:;SF^V9U( +M>B&(?'ZOEBCY-0C-@$T;H[!"0A(]L@LY^*]GK-HY;LM]^M>A]1Z!`=\/Q+G. +MSDJUG+?M+\VG`"PH:5H9.&``*"'PT.QX$:?S\WVO27JN1*A6&4=JR,_BW-LQ +M>5H)\`\=K@GV%#2Y_?MAJJ8SWP;MZ]9C6>]HOP@2C+:FXT[(;H\*"\U+)3=5 +MQCCYD]*S)+X,* +MC)P!]PNIE3&RU\ETI>+:F5+0*WTC65HR3LI"K)G2P3$XQR`'4\**S +MI[RAQJD@$;FVZ:4NV>>K&T5R4*9\9B+XM0>'BW37FS-%B4E"7%M?5@8MP/S7 +M&IN+Z?G1Z;'7,/H>8+/FJ$>@&JU\KQU^N0L:S=4Z[[R?A&YX7-3?<;D][X\; +M%=")F!K*KSN1[?*5>S&M#,I!*14+6FLI^]A]GD7>\/8_72ZT.\QO%L"M%\O+ +M+^R>Z#\!)5#5%LT59CS3/VANJ&^FU'JB`Y?LE@HV +M)Q;YJN'7/P8^!^V3M_#]$C:1#YUTY2%0._]F[.M-,='="=!L.SWZ84Z&KCZ7QI@?MED(O#.-<'' +M:30RW4"/X'T4+&Y`QX,[<0Q%P*_P!`MT(6(-T[D2S?=)S$&`&!#(\/COOX^. +MDYQ0:N3>"&0I:ALC/XHD+\D6*F661QS=$(9P^Z)J+_XX#7:*1*/7F[S)"4_=G4 +MN.ZSMI%2"]H9G^T%[298=LF*ODMWA)FBX(^95G\W8 +M(@C,8ZW)8CYYE]9\+J9L_-,*[>*`B@73>'"CE'V[QT8#_\ULU]XV,ZBE=HAT +M[52T#:\"AV^`78VXC7]]C0=Z#ZI??"B/QC*=7J,0,)6A6F'H]&X*_"NO1).5 +M+2!T1\&183:\;ET/\W]#`X75":+0-(ZSOAI6K#!0CZD*U,C7]GK-\JDAE +M:LQ4!F7R3\_GH2S]I\[3WK;8SVI`%ARK,G8OH+Q:HDNA4ZJ:L++O%K-(G_@I +M]G7*5M0Q:[/-A-63W@D2G4E@=*C:D7`L!Y>YTV+46#/:5A7==/B-M2[GI8F3 +M8#>7C'YWMM%ZQ-$4^:OZ79TP[ALTFQ;QO(*+8?]TF$=1+"LV8[>+2_\X),84.-G4J5RY%ZEBHY[G'OXNB*4V%6J +M292Q)5($Z$N"79IO;7!B%!Y?'KE"\;]K_CKK*&ZCCH+ZF.M8TUU3PUE1:IO: +M2IA09OB"O,]D+!0VV$S\G;/B4!XN,`Z;">9]3?X%R]BU">G>W)YXN2L<:X!E +M;%#I:%DMM:O\U;]:%U^>)I/G;FPST2Z3^=7W:K>)"'^UXF9A)VV.&.`:J(NJ +M)Q>EJ(M)D?AK+;VV0PTJ,NC%\9\MDX)\U&'FTXUB[+X25Y$7&>G22Q/L3B6,/]@.1A[VG:!+?S^'WGR! +M!`8V@3J,L.$>L_X728&@]+KGIWW +M4752$>]_`4V!\^%J#GS2;9BP2,.-1./_13FHG3-/L"\!&\(1/OGUUDXHNJ&3 +M+9KI0]7"_P#_X$]YY!;[C12?M^V"2.E`#+9)GGN\MH%A;R;N`4*!TS.WG8HR +M7N+CDBVX_UYG`:5G$58\:V(J6OAPAW>D3A(YAXPJ>F=ME%&P*OSME#'6]O0B +M^4SU='FIWE55O=GH7D8W+26+V1O?(U60KH2'A7):#@J?/#/1%#N>XJ1*M,#[ +MKINMCMO6=228^06TE\29(5=QX2<[T+K#Q^C('0,7?]Y0^Q>KQB[=14U+)O#( +M*2=IQ1E9'\$*(R:K1?'P17B1B&%;:MR5%B$LSY$CRFU.QKM>9M\SE+47>LD. +M(]5G!TY^#"+Q$B(*\'(BB-BQ:ZTU\UJI&`:H^,FSW7_/%] +MQ6S/T\+*H6!D`D6/XU4%DO/?`<]U^=D?HYM?<'`(R`,9Y.T^U36X3OD>P!S5 +M;Y@0K)%V4X`Y"=2GT(U\^E@;R.ED5HZ'-9Z0Z+O'T*1M@"(/(AK)[-!R*[06 +M'*K.,X,7+]ZS`>;/:*HU:XVQ+L/#X.'4&':GJ7]XYR6.U[O7T9>:@MU4'&1= +M)U/+J'G_"X4LD\>/IZ33B^<#UB99@0Y?G_88W5-P)F;D(FBLHO@C`>&\IJ;6 +M*2&FP#%ENCY:%7,30D]VU:)R4'013@C^XW/9;`@1D$M"WK;"*3MGP_/:I?WD +M&\V!Y36EM?I@I\(^KA[5`M4ZV>88PMP/_"U*UDV)8V6YM'5W'4OP*DMFH^\= +M\8`H=J*"%=OJD@#E1(SO?GA3XS14/IMG7%M]&YWK^3@[+R*"$MJ]SBT+D\+# +M5T4S_W9L[>+AJOLH5=5^Q[Z/3[6;$!>64'(C)+/&\E+H,XX(L_YL^9\+"",% +M-ZRHQ!]*B@@NZ"VC;32;"Y;T"Z:8DEUPD#IH5'T*4MU>Y)&QW*V(12)A<[\> +M*6=;`A]3:FIKA440B,OC]6NE==IITR.EUQ74,4#FT[ZS][7:\%V_@0>9D5"_ +M@LU.4C,1XZ>!1QV5#98-B;I"3@`ZHG[\%-P?&:$(XVOKW.7S"B&W]8SC(G>0 +M'6VQ@+`8*W'J!LIC'PG[IF+LIJKC_D;!2O`%@2@MB*J,5?4:%H+\<7@*O7A[ +MVLSB&&I(J?\"U@R7:BOK*F7()G)[[S9E@FTI-O* +M)A34(5<7IN!FSE.N',!D/K[/,L9I3-**)7#2BF3BW,("EM3?N)+1GS*V3QFD +M-X*]CL)1RX0CM\F=?]QZ5J5TIHS_J0%6I1]%<[E[B"D6I,QC*$Z`RG*\CZJQ +M;L7O) +MY!4Z3F:ET%B>M&?$?W%8OL/+Y,3-_HR`LF8%%TENCH`'S7XDF[M_56(VZ:_LDC[@;J2H_XP`_L6O2SVXZ[V)6\"5YL$'G3TAZ +MS/X$./_16$&%"Q\B@BPJ5!\54BF85"!<)JI72;3L"\I:JAG2VAI.55)_MSLD +MRI8X`#Q,Y#SD_162__6!PSZ+J!KRQ)%T?9ON\YL;GV3QPB_8^!S`YK"H805D +M7.:H[IOYOIU%CR.@K\:L1F7A114()9^:'IJ&(**4)5*J$RZ'*[)],R90J](% +M"/0WN/:FE5D,H+(:UV(U6VW_D]L:*UVNCB'T#J6VO^\R[,/5WX%?GI`@3Q=P +M:14AQV6%[AEDC*L5`'BKNK'AJY,"U??E@`;.-FTUJ"!&?:;OSO7WM(,S'U`5RA?)83PY1.-UD%4LV3`B4\*OG +M.HT?_F1.[#6+FHI,>HVR.^ +M0#.%(?];$=O9*;7]OV*XX28V,%SLJ,&@A!+/S0Z_3:Q9]4O +M*3#((N;+(['Q=RBX+S[V(14I)]!4D?6!RJ>AX]TU189_,I:VE@`QZ"*X9.P( +M58<`,HL504T2PU171,!B<(D_"4\;CU"2$`CLQ,MC]:,21_;6B`57FS"G&M!O +ME_KIH"B$+IIKDYCE2HTFD>"FCW0@\0]OZE!=2?AA"#4_J41GK_5`ZTST;`;S +MJ7QWBB@ZEWE2%6OF^;,KU((SW>;;@R$[#?JWP:N#JS^CUH#>Q5&SR)W&[RY9 +M39:'588+\M$82W#IJ^_*'S,#T@[4G(M6\=9!I_8EI'U]Z&Z[C7+LL.%#X8Q' +M\Q$\3#V2W!^\]]4:1ORQ'@U04;[DL`FUD5*]&7<%"I4:A>*?#8KGA%D^>BV^ +ML4]E1]4_T&G`]W7+2!:]OD?818GWFL$,%>*:%G$68&S57HI`K^IH*&$6D9$O +M(6TA?7'_U3.\#$DW@929>*\&."Q)YP\*[6(^6EK7_S51Y#1+G,(`'JT2&Q4^ +MK2;DTG)E+CI#2TT2#5N_RO,G^?Z@=2%67Q;!R6EH\_S`5?C8I$N\90'0$.4B +MP`+H)TK8HUX0V`NB\5",#Z8F";/VQ`5DVCE+E`L'V///LP<6M`?LWP.;@>9! +MT:;XUK$`H(ZYC\H]F.#M^*G^MZ,I[;@[=<=:<#3[$\P%MU"8.K8Q1%R*$#L% +M`;O>RPG!@33J4Y:X1:\;^JB:N5AZ68VZK7COF6U3OXFM +M:>NG*2B%VE_Z]U:%2MP@V'>-7B9$HGD"E0]5BXH".(^0[F3XD"J58HM@/W*= +M^8E9'Y>'6X/\V[UG-%'HAT-Q$*'KU_V$H_S#\_H:'BPRT7@@CC"+K:88 +MR/9Y0M>%)]#F^7W7?S]]!DB@W;<1"GQN8:R9J67.O^8))#CK*1H24&B7X)I7 +M/.(S+QYTF&G=OH.#XEJFIS.\`O"?-5T?L1(6=E,]T&IL@P(@--4>&A\G:EC^*A^Z13G920:"E*$!1*^I_#ZH>#A%?L"+5K>CQ+-)Q#KCB4"VX +MFJ(:UIU3&O.:S_L#GZSQM$F4J +M!_JQE>I,@I*D[W'R:2FCK.AQ-?S3+!:OE)KP-7]+7`O\"CG[;8*?.G2M!"BTVX_,";()Q28QMJ'D,=937,7=P8?+%U6EPX73G%"I +MEV!E]Y)9"+7,[$L^=_2KP.OG0Y+L,JH6"EX?]7256M3W!>%-"((ELBW#,@W84L_S5D;'YF`&VD`<$NK]="T!Q;](V#HA]9/1\'J*]W?Q +M;'*9YO"!\&N):@*!L+N]@5!'8:\C*Y4^Z#>Z?PQN;N$$->J=:(W=AC0:FJ,+ +MMK,:H9N[(E=2G,$GN`%OGF2/0B"T"5&T-;MJL"-#H0@34%"X^RV<9LF$:PI2 +MS:O@V.$%-4150MI).;K-23TXVYLST>XJ1@(XN'S>T(N^[LT"/88HY7V6\A[@ +M41)T,E'S^[VU0`3H?:L,$.-TH#T;P68[-LOYK*H=>#[^Z"QA_V]00KRVDA\1 +M7+Q#=WQ9GS/_6ZIOH=GI=Q(H/[3:QQU`8\JU1]UZYY>8]/G/*W;=: +MGW8K2U`&W12J/\U]V=++B=)@-?I?`DRB:1X8R@,1\7+%N+&X*0XK$A3Y4&'Y +M"/X&3X,)HS@T'Q"_*'1)URL)P8_P@*=G"PD1)H3-TL$-G<259[$<:N7)4*6E +MJ[BR1OI$@+Z`I7N914>A+O(!`+S\EFH2Q4,LA<#<)`B2IB!,=PQKR9#[!$<- +M[W55^K_DD$_A6W>G.$%2FQM<(^P8`,VFP#&[,9!+O&`5P3-2_W(=TOMI7O%Y +M1&@<]D+]+077$N=41TZ6/JQJB\)?&F.6XNL$ID)`)T7HWG&`?*#K@O'Q#)"( +MNVU6,C[KMOH[F=C+1$\()3>4*_*=CK0?&U]5M +MR/\7$ +M_JHZ1WA+6CP9TW'MC",M&QHIN35FNBO59K8G9$UM:J<5)H3?R^&UAB'/YV=2 +M:<-X("=E&W^%E#S[G[$VAJ9U#QT3@/?KS]>,9U-F/^_L;P4-J'V2G$E:4MI. +MEA+:C[/?M:^O='>65>PRF>9X^@N1)S;#= +M=C%Y[A=A=ML58^Y[Y6A8LHU/8.R[9<$1`8XX(R%LR$TGA!ER'$*!)RJMF[BN +M0-^CI*!.%>[H%EA+:*`'(Q0=O31*^Q&9G"`WL;&)6_]?V4@X0`XY)G-&93AN +M]*C\^I6V-65;V7.H77\`L*-`CZ#!76PCCNZH<'ID7\33\,I*9H&`?^=Q2_`" +MT0#7]Z1*GHLP%L\$`BC6?Y!XJY#@/[9I66?3P.1J$CNG%K+^-<_@Z3+1PL5[ +MP783?"Z=4THC!/E[+*2R'EBL^;LC)E0@G-Y,<(SGDS='=5DF'!T^((XKH%[_%/T!1L +M#O0;:< +M)$P+-FR=0PR;SE[:1`B.?'OA%B>6(2*;Y5+:X/'!US8+Y"?V3@RN+F'YN7?_ +MUKZ]:\.T-;\27*/](M@PK+Y6^H*-"U-3%"&:RN>Q=JRP?LLKA(*_>.`FP[!= +MEG6,ZW)X9UUEG5^NFV/3\HD9NT@)T5:9P+C64;*K'L=HE +MON:F/$-GP1Z9R:JR-:A]>$68:^*2>Q*CV':&KS3V'MRZW/%I(/A= +MS?N(+4<^,WI,PZH>(OOC\6,[9>(\`B\=19.8SA-2TB@V`?5ZN%JWTUU_,C>_ +MX4KE+O`($X`E]#.)]-=B!.U2RPSY;?R%IA:)>B&2G'R,S\>I'@\:K)I$CD`] +M3;;&52OH-F))-<]-`A>4Y,A8WC&TH#X+]^G%U)2$+K +MV8(1);A[\4"(*`?FP!4#M8HX.].O?)%CUU"&]\A;:$)"`EK)<(RP3MP6R0#7 +M8OCX*R3G-"DM9\99^,W/V)*>8., +M!,AN?F`/O'A`C$F*GO&:ONOW3*"U63YB[=_`G>)"EDO_;*(%@Y-[F])*T>F)AX< +MUD>=2I\2%U?;^*W/E#5+[3JIAEP#>UPT8U!;`Q+.G(FS#Q0.5)&1CQTQB`/% +M((!^F`)D]R-4PG]K_3'K9E(C4GDGX&[G].]G>YJ!ZG.=5N^@U%_RNIQBV"V' +M@\(JMRF;J'LZHV2,_S2I5_Q/(6J&;@ME:*5[8]1CUG\1+.B/YT=Y%IQ%)G-( +MSZGMJ-Y$&JTX0P`+P/3T +ML)SG?**"49#))[$SLV3FJ,']5$7;SO!2@0311B$YL"$P&)4_EK];-PV!1YM$^JCV<@],S8Q%*][T45K(/,^%>J(\X,`07_<3\< +MPY/LVX?@/#T,ZFYV>,@R832 +M]+^-+'M4WB6U:7%%1'>;N^,0,X>,82TO>7,$.KNV3A,XY^L`T/ZLP)BV[V0N +MA/WJ,5,S*O"[8_Z-@\]]21X3ZC7RN507W6OO+!>IZ)8_8K:#MNZ!]@RL>^;8 +MQ_^4$6";8U^IUW"HK.L\DXYJF0]PYDCW)]N#`AYPKLJ5-C[E[TE^GF?ALS\" +M8*CV.$US$4]*_Z!WSMZ#LB1TO'V\"FE9020BV1ULBR*U>=^$[0W)R*8),T/M +M:5'LT./.4*5ZXTPJ-5,W1:N]WLQ@(6A4[2LB_7HQ@<)#FI63S>@Y"NL +MHD'&"DO)\[P\ALH7CIG!%,YR1KU$[9I,U7R>+;)O9OW4334PU+R6ZV);'"VE +M6V*R'%O"AJ\.O.CV`_PY+Y3GS+IZLXHD;E^5.3\Z?,;RV,]1@YA""\J3U%<* +MDV.PP*OKMU`-##^F3EO6,G/_1[3XC,/I+I+T_1.)3";R\ZB9">%&1L]9!]U7 +M2"T":*.\,X.+UK%WJPUO`Z\A],VN)XDF#/FS@P4EG:"GOJX7"ZP1\<^H#$%D +MKCIUD0>,BSOE'<5@!@>TIU3[F+MN:@JU9K\`[ARU@!@%;U.RDG=RO^#][5J] +MR;3I0X`'?/(%GH-&=@.S$BA\9,L)@;Y\!WNS'SHV;!FK!&X810@XH$'7[L$A +MT6/;A'N$&4DO6IN2YNPTFL$<^/2J!P$V`4Q!!:#_/8VSWX?.PZ1_R-6*=2E[ +MX!%@J/+'B[@'4IRYB\LAE9@7V0J#TG4[9/K8K&O*!,6EO[JV`"`.Q`XRCLWN +M=X\IX72+?P%OV^A%;Q,&H,"-1H-"=:D0A[[SU6G$I`>M2N=@6\K',.G7,^350[`B_.:1X\PJ)3R>%E+XINGGY^. +M\U760Z:-M_U3=6<#U5++7'*W(/WN2@UBT2A;@VRMBQ`TOTYY,_:1-@L!,9'7 +M)F$%H+K=`7!9]A8,KEQ$%M-1W@E6C?3H!29;H8&F_#W]M"H%7FFJUKM<\PPR +MY(-FU5AQW<.N/@^9]![FO)$99$(.L>*A80`<>F795T`G<($&:^C!)P*)K,%] +M^??6A0@MM=4STC5F)6:"]V3O:,QG2&A38J#;P7[5]%K?.7`5MMM'/;7E=XQ6 +MR1_ANOJYVS>PYT`5:T8EE2O.!#0;@TZ6;6&SJF,FA +MN08H[Y6!(,=Y\5UI>N)A+7=(KW@$HSWX6)+&R.%11'`[WAJUN%%(AHVK$X=) +MJS+<_\Z8OW&0965%+B`TXM/4T-3/Q1>8V;,07(Z)#15(=K)ECH"1=4?X?+4. +MM$^<87$BZ`R!!&RU[5S'GS0%]M2\*]U$I&1,5KS,#%X@65AF&C(($]Q0^G$6 +M"N>_6VQ7]19"O>]X]YT%Y+'KY;K$W\.!-]L\7-S^TN9?#MR.#A!2^JK=G.Q) +M%[N&R\TF2[B;/B*>&,DR6=:.C\DWQ<3(.3U?:%EB%S/:J7!)!@LVJ]/`2%-Q +M2,%B;]YK5RBFRA;ZIVI)5`%LO[<]#!;)-2*\_OV;QMUA.X"`>]=S5&_Y%&_[ +MD^[&T;UYFF249F#[B`M7#[J>TL_/1&4QNYNSJ25D%+W5#,G9)*47Z*4OF<5? +M_=AZ#1&3SB#*+-=O[3C>"F/HQ97-K.31M@B5T\P[W-6/O_ALM\&Y$?K'^VC[ +M2N8+:[^@F,Q1T3",I-^<.K>`@1G`;&Y@&=J0,F`7PT=B;V1RNPC5^)=J=XXZ +MG1,.G>JSJ!N,D_85Y#NSQ#%^VDS^'^`))"["_.L#JL:Q3M8;8?58J+,QV=@&AM,:3THYWFK?W8@Q@P99*G,0H/V +M2@NC#_3H>X=N"1:=MOF*/GR+)]-&E)(=5U1\T[?RTA2"1>:K4!T%I>M=[!#R +MG16C6ZL@%;&W'1HM!W\'T4X=.T]V>+JI"0`CVO]7[1'&:J3HL\9;=)!O^\<5 +MM40@:A"=WM+"*ED0!W8Z3J>-FQC[QNSA#D4\:S"0FZ!>*4/."_<$AI7'P@'- +M"Y*P$R(SF:S.],BKD(L<+#8QAR_T88FPSG#R!ZJK.NC3B<&62\TH':(#MS9- +MW#,LA$JP`FS`]*S;I%[%7Y]72QH/5'[&ANLLF%@G=_7S76@\YB'JVZ&YXL@: +ME0$+P=P:"[KNE/GTB)/Z9:S7+1(.J9;.F!X(S=[N0CW0%8UO)@9UQB*'9=/' +M6N*%C,?#F\+QSFZW5Z8/0CRISQFEMIC(\4O$[]=77=!.S`;$H6HU3'M789+_ +MZW=5U_W;0MQ_'_ZC7MHS]C4US6:=AI5XF* +MTV7A(_4F(5LZ'Z"4=2FH/)1JIX!8^HQJE)W2 +MG'%@+6:(@B>EC6HJV7(\[1UWF/0J-T3(N1W4VRZ6"J$ZMW'60^,PY4=9M3JH +M8[8@I)P0DN)+_Z50WQ(A@-F8#$`E4NS-B+0IICI0'`\4]K%!M +MC=E(RDH`W59\%39!LG53[*'5'?5-2;JN&:,]T`3]$0PT +M*07*"::M/KU +MS=NJ88KUG+Y'_I9`Y+>(_QA*T8HHD-P!$'HL'<(?VRSWPW?WWCY*6:N +M!2@GXG+X?-\GJOT;I+BQFB=1='*"!VC_ES1QM(&H?QB)*7F;!VX>L`)W0$K$ +M/CL#"4`RK,D'2O-@O.CZ$4P1Q6[V6XKI +M.0NC@>24RZY<&_E\K;1!B"L'4QH8SDS/*>R$6*N5U&CES=TM;_\&$DLKS.WN +M^A+MG@`Y'N#V\H'BKBJ/0SN34NQO588&SHTE$%."J+% +MAIBU_,WM?*EL5@5\JEMK(8SI+VRRXBPC2UR5$VO7H^$$Q04@08F@'@?"\7V_ +MEU1>R.8BC4W9>QT2H6.8;4'_"3%[?(Y9*I.X]&U1OT+5JJ"_'/+C"?@71H2K +MJJ2\M7*G*P]1:X&`*>+'`\[M_J^]6+M^C?8AWU0I"%AQ$$(0ZY(=<<1Y#)-^ +MX>6.N73IKY_(#\BT.^Z653($ZI[O7HLC,L'U4TM"Y*[N:N+XK(FX0:,PISM/ +M5R:=6JW66D&75H=56_3],);6+7&55V4:NAB6]=UOH//;OE02;.%TFINMWBR- +M$&N%&]P*A$VA3Y//!A&#XK5-DKRO##@.1G]>-0_"D5B;$4TP.^Y(O.`_VDV\ +MJ@2!L%<&3+<,6HI&X.FGIDUW1V\W,]IOJZL?&:]ZLDFB!HI';CP_^VH!1*T) +M[=QT&XVY&UZ\X1[X4LEU@D=YTHG/]?!'V75G@F51,%*(QA$>_SA77P9('0O! +MG;ZXX3GC",0?9B'!!>DVNY!Q*;D#;FV(O?.>4I:!?27KK,'0CDDP!-D@YQ\K +MCX@LX>$WN`;\O4QM1C\D+("/U;^R#$LQ-\!GI1>E^`;05X>L[#G@8>'8_M_R +M&>Q`QG59.6%9QGHV&48;#P12FD#:ZF0DG<[2N90HXO//+PP_`;[7_;A-0!#6 +M/YT")-O%)8;Z>E&R66[N6G(C06QE;LJK4%V,/A2*RZ`O*DZ4F8W-,)[)!]L$ +M-ERS)C\R.0HLVLZSUEPQ=!P4-N?][0,YQX9CS0>-N +MT;G3"=ELY8Z$Z]V&=[XUP>SH0U2S]ABM3W:78U<6,^BI7/.\*4>/#;8HS[E/ +MVF^RV(5#9Y<6FDV1J#V&Z("$9`9#G40?@NO?Z\2VK#S+VSDT"3;)VQ3U)/?G +M02*<+LF/@QY#FD*L%6:`DZ:OF;&2#"EA+EO$8E_M,Z(D.N +MH:N20%H'8KL)P\';QCZ54E%27#NLC2HC1\6R,$^P][JE,H(#(H?2?=Y4Q#@I\8;N8FX?_HRPNCIPG$M_D-IA5?6L9==5NFLDUX +MU;L.!/ML*VJ(EP(0[4D'^5AZ*[`VU=SC]L0K%:E_H>(B]%^%76A[(X3)[':H +M=G3_UM^,SO>TX_JBB2-X90?S@MCT +MM))F.P]XUGTP4AE(M5B;%[0EFXG,<:RU.,_&>!61NA3E#!.`7!3->O'R"J21 +M<];5SYBCU$%F54%)8=G\CK:W-DY0[S=V@H!L+!6L]H4>Q9(TPY`[KX(;Y0\% +M'YU'/EH6F/SW'Y$TE7H#\>)@^YZ(>H6#'V.W5PFN$&/',]-+PL2HY3V8U$+> +M[;>.TONE@2M6\<0*^V#L*ESXMTQA+CY&?"OL:;'0J\`F_73AK1-E1&K][=JN +M+YO_4>@1B8 +M:?1Q-E?Q9733X\)(9R+%X;YUCV7N]`?#UX=ERTXB=*QTX\A/]\W+647N_4"' +M8B>J4>1D*$523U)%NDYY0\];,#M03MZ^`TT:^W8W/;,<(B.>]!?*%\HT^H1D +ME\U]Z$T*SM5OJ,+&*!QE56^.X?RM4AW/3E_&W/-V.7`<#.H_D#L9(&FW*2.Q +M.]E`@<"N`MFT-9R3S]3`)CU=`8F07_7F]"WEH-0DN,F`<\,7#R).`7\``5ZK +M.BABYG-N"(HA'ZW]Z$H`%19/1SA!RJ"2!\%FZ)%B+V3=+3R#;8:M'GA]&._2%YWXW4RDQDUDR]M^0."R>9VV`#9\"QQR1K#!.^2-KO +M7VPQJCJQ;_60GXH +ML]XO-S?]$83?)S&D=*:Q;!@'3="(T_3!+?FLIB>I9J(-(:KG46&\MM(]L?B\ +MQL->P"$$41[XL$?H-A!P3%UP6K([-V6W%(L`SU>G^#=04'J#CE]`P8 +M^N+K[HZ"SN/!59,J+L>[FU+NN$K)UY>#:@QSUJ@-/0RA+K=%WY5VD[*Y7_7/ +MM$,L>D%6^_BV!KDF3MI_+`N4B$'#!`0&T(7\@]V>N$QV]KICPPAW0L&DM'\\ +M9!J$CW[U9JU(S-T4L87<&2P%[79+&A(;<(9C^2"+^S(3%!"4#1A2'M5R**)^ +M:BD]EG.'V5(INUK%]Y3A7>&],Z0QI:NWDWNINZ":T>'*)3&T&K'3Y41'WU/+ +MC6H&XMMXSM),%D:Z2QTD?.X8X5`QME\(4^?J%F,S[[I2H1_U@(2I'RFKC-*" +MAGG%&'Q/M)M1L^4K3Q6$*GC,B[A@K3/+EG3&OTBY6Q^/C0["N;-J6Y4[P=BQ +M*DF&;D6P,.-6=4ZQ;K_W-=#;6/\K:P6I/`N]&_<<$A4V$8H!L)%)85Z2L)\O +M`MHU?JPF)M]Y;`7,PUON2X'E'SY43S,R$@L'!'>6EX=B`6\X8@E?V#GO),K: +M_E??LA^`/<:$AB.@R=N6UD,="^XJRF"7XMAHS"X/[RFGZ6]6:X26 +MSX4)B)>+-9OS\:,ONTZ1UX3;W%`I:HY*0(1L5%(;#H!QLP:J:Z5J!%>)2SD`4! +M^+EBTV4.#[J&RW5#N#^%Q3WV.AL9B!D^BY`6A=:LFBJRYY;=*$\L0G/5#IE7 +MQJ2`YO2C5<],AA\251P6?,R3XV#8VP0Z&BDM8*_".-$9M.(R\_AI\WM&`MO] +MU'_.B[9=9#Q+<*WS,N/*,!)'#K'%<@25[G4W)/=4WH(THP^1T"G.V!G_S$0& +M86T9Y4C!]$ +ME9G1O*SF78W5GYXY9S+X45Z*6R49XE?[Q'ZDO +M-?6PZ4$_F5&C86BXZB\\Y1M,T:D)%BD,,%6V%(')YX%J7&CV+DJ0UM>DSI$N +MD#!^P4H*W%%ZRP#-W_E<5)+GC\(!`&00@_16KBLZ`?2 +M&61J\9KOF3BHHA/49CR-;:TN_O.;USQMER\"XQ-+\01G&=V%<.!'?@'N/;+- +M/6_LDP5OI*3?(L=`7*%M./F"+*C!'[U,3-/*MS099NKO4@`32S,(0ZB!N*9Q +MP!:F!B0%ZFHF8ST\2`.TQ*A>HAT33_U5_8BSY'C=J38E&I"/-9[^\*"C-<4>OC8`M0'?'J<:RU\YGH3+$>G5K_OWZ=V.,G/9N4?/L +MUL)`]DK`G>6EZN9 +MW$QFR%8E_Q1VB%ZU05#GAV?#HNT!N1=:PF)T[$<"0+]M&-3M_'NU?2_67G+$ +ME8<(FM?6T?KZO:+%T1KSQ'#J(262T:U)^2P;[3U.X!9BSSJ%HMGB)ZXH* +M0F<1'/:B[+^NQME"E+UE0>0X_NNE"(34)XI*I*9!5'$4?QWRVV9=+)3'=.J> +MQOYN1?/1;.-_K,S"QLZR3#I/(?X@CSZHK?ZIHLG1+LR?#V^)>SJU#7:Q87U? +M7F!QG"2R/:-47=O@N3MQLNL(QK&->9$R=<(Z$)4QJ#FZUE+9*!&:WHXI12WQ +M-R`E*"\)*06.V%1&0T4>B\63"K3XN1$5S[AOC?B%J! +ML797*ML7$G>E])VTE@C,%HVN1%K/Q$8&T4.L=UTST]O/M8`]]Y`S.RIO7#T! +M41IX_KA(&(O^A&R7-6<71KR\Y.^_>"B7S!F9S>/,J2#$QM6+6]K:&NW-)?>] +MSTGH(YN0+L1G5P1Y&%^_(9_/ZLCU6U@.R0L=^&&.#9HJ;G +M(.EDYK\(BU9PI_XM=H#=I<[4?(P5\0G>Q/W7311(]>2+ZJYT)(UM8G4:ZPHOK;,I89@E:4?U?-"?/$"E=-8>80(?M\@FIS92X'GHN(T3D),(M +M!9Y.]8J`)G*M>K!.)L:@_9$\=8;Q=W9=FQ.@OM1'IDP7L`MGL3\",\6EINQ0 +MPER:$(5M[FO;9HVAG;)@OLNE$LENQ^5<%6Y,WRF-;.`BLODNH+)ES[NHU('N +MT+[L0CV;P_%HI@U<^$!<1*Q_')3X"H:,XN#)3,<=5_B-00.T?GJ4A]"SYE_1 +M__E"]QS@IL'OO0E5Q-3$Y+3&A'^M#<`5,P8K`F4;5RFEEC$0.#5F@8.URN!] +MRFF&LJ?]U98#B?0=?31F-3IDC&T`3`:>F-5$@T,=ZY_@7;U^)`$TRHI`$=.' +M3;_Z$Y6=3:5^#WC2Q!C8BX=E,S'_/(2L#Y4''_[SW/6OG=4X>#8@R?N#AFS3 +MO@(>NZ[]UT-W[;Y]GP.B;Y`H$>?II-L=$%A9)IFEDE3@2`:0XN\X)#,K&)A+ +M=+;.;J&?$:X8'_+A?!.-0PE^_"@%]\#K1%]6UC]P0O0!;_TLGUI3N4]JCU\D +M[_(];:Z;N8)0?P>>DVPD?K#"+I6.TF[_)%Z8G)T-S=!!=<9%)D<&4BRBBZTS +M[@*[$=2W_:9J:"V@C&=V(1L>ZT\4+(=UPA]@PP#GAO(<^;;LYJJ3JO9&I$BP +ML,HH%_0S_D*:US)'\Y[K.EU&<61J*`6+?-_S<,\$`-FU5S@S#CXM$I&2C72:^YF&4E)P]0559#^(0:YK`V$>'FCE3;[\-YSHNS8=N;?0-J;5$ +M&'="N_$0-/S`Q333'I4RPNE<-7MWF[2W^EE'@?I:M__H2-5]T,P0 +MT-8HU6C?WJ<(@)$N2-O"<7*/T/\=27#ZF132"`>5/ZKTF0U6SLA[1PK$OAG' +M[O+F.,CFMDIPQ.!@@:M)3PM>B^-K\PV+2)R^I3=[]LTQH-0`!^H\;DMEY>`L +MUTI\#B9P$ICH8EK;C4VJ#NTX&EJ'&?]>[H"R"5`MXLNG5%&JJ;&'S6^P4X/2 +M]?)(SI?*G-%3;E1BS4*,B,>!ML1A**^Y[FRK"39ZM*QB8D=^.NU:%/XG[R(" +MD7.(!6<6RP>I.7``84&CS.3B\CHD>/]RS*FW#Q'Y!9AZ'OGS1E<^H*9?;_RJ +M_!BA4+*NX)R/`E7ENX@YJ:8E+^2,5``HYO\JN!))%EM*'77!,VS,T=5[V)O( +MKCKR*3:.&!/9JEMRX&8WKH.HA4JKS.V)?\Z#)G6+V6`?/:Z/-_SEH&@"`!XY= +M"A1.^OF`<*,$'YXP@=]D!RIBU*N_MYN#7&,&)I?FY:D$0JD*?[#%;Q@4G(^? +M$F"-ZT;;O\[U!L`@V*KPSBC@=IA#>[N'?!MS7)U3(_(/*E<-[G!=CN\;U/[4 +M0;NSN36"Y+8L[7E^R4ZEUM(E\O?;:%Z)^*QNXB%D5I)#/[4ZB.WUI#M?R +M;(_&UYVT)H*TX)IDD!*]/OF=>2?\84"XS\N01\"0__"8(O=1/<2R]L5ITPV#V]#A3XR'KKJ4IGR?![ +M_E!U1.")[Q0T1U&+*P#JA]27@)[O6IGG@O31EE3>_S8EF_H5Y`NMN*!#FDW +MSK&*=K(.)HD_@CSLB*'Y$K-7`*B=*$Z!S)%)_EFP`L(?9*0:A3NO(UU$K5VN +ML>1#N8W?YF)]R4M@+R$^*9>Y1I_]#H_8#9<)#38:NAXL&.QDF3'TZ`2`7>VB +M5L?^?KG@FF>"$YVI":Z_66!D9`^;?B(6.HL*"48ZVO07?PO4Q0=+^%2/O#LE +MJ70>NUC9$]27^CN)AOW":WAJ-$)37*D-/"8!$MV5&Y9^?RYC'XYEX:-.LN#8 +M'1YS.ZR(,7U]?[62V6WJ?!B"RTUG0VCJKADN-T47P^E_D6`R`2(&NJ,$M_GZ +MFG$RIOD%JT,5VP]B56B141&*C>BW:$M[5C[>&3)O."V<\SC +MN>Z\;?X;U:/>J5\0UID8&=C`L.Y*(*N*!:>\(\BQ0D$%5.5!"II^A8IM6,OF3H"HMJV[DR>-F88/ZLMY,2G +MKEB`?K");I1"._D%E>['V[7>>9V1G)?IT9@S@H>.+2X1^6C"FRY4R&P]E?E: +M'!X,#[[Y:1/+#183:\%ZF!SQLY1=XG!@=:SW+UI?3$L723DX2^5X? +ME_S#9K,U9K!VG.=#-1!IW_I\J(Y@=,A&W>A=V8!X@*"K:;TH*"IVZ086[W]D +M,]F1-`^DN'(2@9UD[@U"JA9'-F+Z\#?!#PS%GEM#ZO(X^EM&P5/V:A!+.5E; +M5>^.\M=>%7R;#B3FY_MKK:!NA&MHS.8,`]H2HZ\1#SPM#2_M37*LA!OQAL8_ +MZ%271L^@-X]?;]V=P$]#L4*:PHIGNQ?,%V\%A&7&F(ZUR\DQID7,UINU4)Z( +M5=M!0"UJJ,I0!UCJ@D:>PJW:5>AD2%-J1-'Y\>"*3GQ;HO\)8_9MX(YUB%=U9'*D8VCLW7\R94:F9LV!Q`K%M0JYBD6<:,=XL#V8Z6+PPR%C:/T!P.>9NG&A +ML(T?>FOV*5G^0G);9H>F?L"`?-4[8>Q>CG"LS_5`9K_DS;2Z)EGUG234_1SW +M\&(!#A0).:B&0#O+.YCB]E?1,`;9*GIS7[W6`:,&`#!BLT]\P8 +MNOJ2,3_CVN>X[E`1;<;SK>\N'A+#]E_4[V2#UF^G$@,XDML:ZCSJ$N`I]EOX +M22E?MO$B&YV*5%/)HFK12%I&=2^K\:5=ZRA8"11%0@H9%\@/Z$&30"?!U4-H +M+;>HI:*F"/A,:*@3""?S4FLCFL"W_?%U%OP1?@1X>U]2K><1("..XT@<8G?^ +M?5@6DL]9-\*(T=J;*8`Y63Z0TT;"`ZK*\ +M^X=ELA&UH9Z/AJZHOW!`76^N'V9!0PO1HF.D2Q_4F1ZKD>S+1!"4_R>WNZKL +M2@H\:A-OY6RDSR5Z0&$.MZB-?OS!S%*EGP'.*?=YCV!>&3"N"657G/A68;2R +MDO+'YQ="XY%``=*.]5Z#P]:]H@W!/X=QO3"J7K-F.(TAGR!_Y9>89#D.J_.T +M)BQ@;%.&+V=5?R08I=$8-(*2W]:ZQ-* +ME?R(K)\)X=SN#WJWQ-OU60_[=AJU52F-.,S&WZQ/=*XJ?E'8Q]=D*A9<23/8 +MB5:#GWA/Q,?8V/?#5$,'=FYF1<[&]HY93']P_%BN5GL>D9*^)GW_THRWK_QG +M&.5"9)C$)R;PV#?..\GU*2EJW`:I)R<]#3O8DS1H&`F=F3J^=Q'9$QP3U>LH +M(GB=Y2PP,Y@#QP]@A58VHM1>=B!&F>#\YW212[G,DH;TWRNCR"ACO$RIQ$6< +M"J8PK\=V,-)XHZ]8\<\'M`1\,;,4.DHEWNC@V\4S_59QEZ)UPAR;/ROQ`;6M +MS4PY/OG\A#VDA]W,2?KMB'\%#!Z\N60W +MQ9,=&OO_8JB2P0"221EAMC@DA^77LW/1VR((90_L&*&'R0`24/(5,A_4Q,-G +MR"J!Z$(M)OBKHO2#WK1E-F$.AG&"F8`Z`4ZP-_RG":O08"@%1UO.XZJC,/53 +MK@J/OC(XEOCX;0[ZYJ#Q?.%^6&7M2@JB3R%.ETDU5>P,"`:PH0&_TF8/2^XA +MY@%M?_H,U3-*"J2M\R0%1%O[5TZ)J9%KKI5)]%GM+2U`Z$;.,II&R77T4;"> +M3IW),EHOQ!12I;K\?`3OXM<555Z!WO/:O\ISV-H;_U,MG.2*.O#J,[9LYB)MD\!82JQ?6:7P6A:L&%^S[C]G*( +MH9D!TVK#[C$5'(K!NQ>04_1PPWGT/I5^AA5DP-QB='!=U6SGR0=)DV`1,>A6 +M5S;J')Z%#Q;Q)Q7Y<:WQ7Q*$SD1JFA]43!:+L +M0*^62Z7^LZJD%`$)!PUU$)GF/!;"`PY,*]C442I*YX2QO-X+F^A\T3^9?JSX +M[4G($;?*G>:<^VD9CCIH93AM6[X)'KM9["#0/S&PK2<6EB1O,`MU%'`HSVA: +M;@\-,F40"DLOTX3T868=X0A9%,HLY*8V#9_P.\Z%"J\9*$<&FW1)NVMZ'Q/& +M#K,7ESX^`Z+BA(Z.@&.!UCT?8ZA.#B#=Z^LOR.ZL=^U(57[>.L&8N26N4^@P +MP$L9B"=WIT)2L@R,U-K1`%M:JG#\T6E?1.SV4`HLWC!$1-0-'#WWO+&I>6": +MA%+``Y=;4?I;RZ7"[3-=[UC$2_SE +MBP'OIS,'%XP'X4W!1AZ:@W$Q^[G"5(S7=/V/93S<'L>_`8BU'7G3&[*W3\P) +M>;K7-W-A%7V=%\R>O.+^RQ"IGVV^@\[VSG5__B&I=*STC(.6WP43SISKWU;& +M2R:3(].0*M-<'3ZM"M/\X`+KFJ4&:1';B5:-6OG\+Y=2TVIUD\@@>BXS2XL! +MQ..P1Z!(2F]1L!TUI/5UCTKQI>."X02!%?GALVO#9>,ETZ&\1[Y'W6MOR)R2 +M1IL33@[1(T4LHO)!,0/;34C2B9%M,_-<\)7MS85C%?9(Q%*LA:9N/F24T$0[ +M+6[)>6R1CAWA7D&1QJ^J/)#P%MI7VT*>99)^;X`.V +M*RD2L0WUT$Z%#Y01/N;@V0QT&5A4EMT1OVFQAMUGEH4?6O*5_N86TP"8>4ZJ +M59=.&8T]OY<[VU?8@<\">T$5/XS3(:!4R[G9O5HYJD6^-'YO$R[HTV!R@N8Z +MBE;K3;PP#94M;=3]?8`_5LO*\GHJAD0FEO96*3'KK:<>:]-)8H@`0)! +M"$SSK;6*N`?6SQ!'GG=Z^*&3Z?)L\GL>/AM*L5"[2<`P`718@[6@*[`,5`?[ +M*U?UW]VA&.8PD9TQ9G>>J\G(&P`D*V(-KK4[Q95;;]O$TB=1@;+_ZG@:K>E? +MCL@AV4D$,972#WK/U`=,6\)3JSP+3:+G%`@T@<(%(+>&DX+%(-0D`$FUCLV_ +MDAS4)BU2L_0#D&A;NC!*9`V3X8MYXD`SULLM^?_B04-!50ULHI?X +M7T,/F\/KT;LOKQP +MC<7\H.G:B>O77CY#Y@YWYV27)$=-T4DG`0?=;$`0'@=#S`GOR>0#&\^NZU2T +M.VSU*"C8<6!X5G3#O6I.7E'3>>M2>EY__?BZ]6//,W3DGS^:$S<$JE`P[W2\ +M^(O97J9VV^UX1OY`1_ID6O1["Z0S38WH?%B'6W>=<1Q;J/CO,Q"ST!0KL)DH +MT.4A$I8"XM.(S4.VML/4813FC4UU+B)<70A\RBZ$S;^TY-BS=T$8=L&`YUIY +MRSN<(4;RE7M2`]SKD46[?A6K),(,?*?Y6NJH/T<=R:9-9A_6!W#TRNV?J4@$ +MT)700%=%Y9F,E,^Q5;H&<AF\B +M&(;B#(<(>H?.!C8V@&:+'WF#S[F2^VB`,JNVM5VGC`3@F(6.5EW;FSIV66&R +M$@*R':="^V^UF,.^CW1*=9-5[-A6W>IJ8<=%?X.MBV@#Z!EPR/FS$'(H)+0: +M-WUDV;AVBA4-R8QW`$E21*J3H%@Y.SCJ<@@,`,S4BE`IY-)+P5MIV]&?7A^< +M0?34(5T7&Z@G_K[=_U+J*T]0=^6IA+TB38>743JM5GI^NY+!#XGZ"*^7G[X7 +M01'HGH!QRX:_>AXGX!F6,>KJ!VX)M<$N;:.*Z,FAU7C"@Q?C._M-NND*)K9)A%>$(+H-ST?L;2U;P/2./^ +M.+I5_,BP!2_)+M4WS4Y,AJ7[A1H7*&,(E"]C;D\*3#,L)(9"?*Q"X@7Q"E(F<0_\+'"+^X37< +MPY$&<@61(`COJ-O.>I[)P%)B>$:W93UTX]O5?2->V:.-19H=`G'81OL]TW@"*MGX%,>.$+++U2HEA>YF+\[W=EBV!;X$[V\E1&>,5 +M>R`S^J_4K&@.KNO`]5]727E:JD@PL&:!Y +M4_DN%=O!"3%PRG>PM`KP'4'"(_UWBY,)<\.4K!7"U4(Q?2%U1.;44HK$KA@5 +MJ%!:>^8C`O5]C-<538-L!:%Q8XS6HS@>7&L<5TV1Y/^[:M#90[_5$28U$`7< +M5[\%M6]8EY_-O'/T&N->R4"3$UB,R'?,U0\1]&BKO=XZ3W>;&L#C,^8L>9_+U60:@;(LXRK5)[3Z>CQZI +M(!$[CINE,IY8\#;F9&0$`E"$ZFF_^'J*F$)\DT&8=N&D3J)/:H[8IG+4T+T5 +MCIM%6F,K``8V"D?0W)T1MI +M3H^4C+IP,P0RG:E79'4"B78]Y&UD.RBX.]CFP`87WEHG)3`"[*R6\VZ>BBH8 +MMJS1]XQMU]NDS$*[<236U*@VRK%9"_<4Q:75TS'SN:`U(3B,8S&R]&;F#G%G +MV?(J`4_3)%P+N:E\B26$^_M3P/I!+1#1`RM]@4-I6C`ZY/XHL'>799C3WXP$ +M[6045X8'8.EU\A1#C:CLE-"?\#+PB=NG8#G+NE85O-UMWC4I+._Z59F1*CQT +M^E6TXT94/RQ6-.&+:ILB(GCB1H^^T^,'UH8@%V1K5FS"8&T":9QO,!D5;.I0 +MD"^2)+LS?P>Y( +MXN$JE8'N*D!C2R)\\V=G]W%3HDF1CS7Z1Q[]3^A5Q=W%#>,>A:"MDV,E&>5= +M3ZASW"5R=8AOIS5%N0VI&J#0W>N`R;C9_Q-8XE.A]*OQ.7ILG.02-?R2_EVI +MC0P.=U3G:T(Z;^Z5P6T)WQ#8EOP&$OXV#[?V9I`NG*?!U;K]:E:5=?`Q*%H2 +M*_F=I%I\0>/=%.:CXS%JQFY`9]P%QJ*@0&P0.(]9O_E@.KV_H=V)P*Z]''(L +M@'JUOXHOH7M,ZI`=AL_2:=,!4*$E5Z;5;Y.3//'$`;Q49]-"3M?T31TLG^:] +MV`!\)#N']H:P+!A'E>YHARMR_EV$5-7Y$8MV^D>2-9K5:7%=8MB`\\Q]=(-5 +M6M"3O#\ZB\_%Q#=DX^JQB=:G"-'=V1<,6?R6:_ND/I*X/F]W?"OYDG&N9Q/# +MM(3/N*<%1;]W=+`UASYNAWG%Y4=\?C<,4CR>^R_WL6JPH^4VR91_MAFI!<*2 +MQ.SN=WH'%#7(:S93(3CC(:W,GP(C?N/$]UI5=!RG:OE%)KY!XOR=C/EVH +M>8`#PA$9L9EN5P +MWRJ<[@N=H_(='C@LRXSL`2Y+NKEAI?$Q\89)YNK9?.6/F!,O`MCQ>Z%7U?'#1FL/5=U(&0:WLKMQ02.$[D,^, +MV29KG'%XT>15[4^G(ZHIV;5ZS"B]'=TN/G3FU2%NPZ!2-5:M8_T8:FXRZ4%G +M5Y99X?'%R7^2$&2=G"*CXX%/RXE6K4OA7B.&"B`EJ&Z+'SI"#IHTE&IYPTAO +MC?N.P4!X96!?B\BWVI65M7N2MK*RP7$8SVP7OK/AMY(N.ZZF^+0P(ZG!?*P% +MK\L`C(QV6)21/H2NFU8>[=""6#RD;M7],?4D\PDV,JL\*U. +M_6GVP7EB_;&P2]LGLAV2HW@""!*YH=5`]O23J0:IT7FF3=BCQT,TS2%T#LHW +MR@FV^4(WT=CJH>)R2@(M*J<(WDDC43#(`SK@$;0DL4*)VWR1K[G7J"M)P^^L +M!M8CH?:@]R*;&Q\UELINMJWX;!2?_^P,*G+)Z)/#]K)N#(KX`Q;SN`M4LL>= +MC/1L^#!,\3S?\IQ>,,0^<^ADCE:3Y4T7[>8[WCP!X_76&G8S^H1URRH;#I=< +MW:$)DXS*7="F/9B3LN$:8]6*;#PO!8OK1C9ISM_$.M2()IA0]62FR`8"";ZL +M_RRXG`B)P](3[!3W/\-'LTFBJBX%0.>*)#4GH8@PG:;DP@F/G`'30'>BMH&> +M]3HEIUL92!2O9($'5_6.%8O$R)GX\#RG2ND`F1;)Z"ID4H#>Z\1HT8N+0U#G +MKMTEFN7]U.Z5:_^,E%UA):)'U)_^APY$]J&'U8I1HP8$1MQ[7/I5<7@$O] +MHK$\$8(!Z[2?8F9P52FP2H"T-N%&/EI4T@Z=%LHFW``4^!OPWLJ3&,0;>Y7* +M%]Q'HUS&C_NR=!TRE>S.1286ISJ* +MO4V94Z?,T9]*F%#'"+#O[E'/<:'3MZ]POX@B&I[3V<]]>SG?_%'6Y(L+52PM +M7J2V_4I65Z=7'*'G0)@P(]?7#6,)J]$8_"(["X/Q]A4]'640E42&I:"E+NZ$ +M;@4-UL6MDA,+AM6WK(WO=6CYL7OMLPX`39VWV.8ZCTNJLDA=V:,2M.9O] +MN;>'#PA@<98.CY0Y'YWAUGV7:T?D#XYX+U3CVJ^8ZN$YED1ACE"PQ^5Y1]/@A4PA(9MIA/V:N]R7X]C\#\V-J +M6.%1V*2?H*0@0Y7\'HS(*2:E*+L"?C;-15\)Y,$BK#SVC>XU"">S5Q`GI:`S8M]5H!,UWD +M6+"?L%T75F3<<-5U7(8HT!;DU@NDSS4]3)`X^T.US2=A6+(QASBS=$C;X3\/ +M"EZ":0TCI0_>VD"OY7'?%_NC!X)[T[IU.);=C>;0-&7):>.;I3L"AL8W8X\) +M97LF\%`K3E@`H7D'IGGS=*>!G%$[$+;Q#.X&1?WG"EB$85ZL$KR3:UC<**PN +M#2U8-]XC/?^LMI>VL=!VYGB%E)[M,)*TQ'!DBI>_$\*`>C7K6BKL"]FW]Z^/ +M%C?6K`I0`3)SP/CF[R])=WVUN8/O$A#:D35P%VYB;QI7XWPB"O@JCK"SZ"`U +MYMQ_ND;EW8MAX+@@:@6[?.^/*>G@>4^[N/;)0U.E%-#?_`;^1+IR>H>5E1TM')R%U` +M-/HD(,[T40E^`8;=K70*]![VC7K"X2RMMZ$E*RHBN#GB:HQ!Y<])W9Z+ZR%U +M6$B.C;Q0-+',SKFUU.6Q?N0X*HPC4UDN^5W52D1%701)BG+?\F\Z8)0,!>F) +M$._`%Y&S0[F,M+`N0,$]1.+8;35+Q=6^IG4I0+NHA'DN_,C5ZLG;BBCA?V6S +M:*32ME%R\5DEI$)]AGN03"7\LHS/_ +MW[!5=(=OGS1^E!7JH8QYLX$K"E/H?1R?DH3X53EIX2&\5>F.>4T53D,NZ^ZN +M4(E7^AWN/'+:MBI4=I$6WF?*]]>H7(0W,,HJ82IYOR5B&OCF5Y"-EJQ!8 +M^Y612[8T*D7TSNR9M[^N3`>U8\=,_>^`H_@'5P-&E;=OU;Q.AT:829WR0P), +M>P!T%IH0*>CU)@XQZ&%CG/P<_%I>SML74HV;B7C-(A#,1&(14HG6_RX`W6@F +ME>6UTWM\`\ +M"K'KK[2PJN`4'54,/=!S_B*="T61*%ZI"ZW1J,L==5(\BE7B+CE5F4KJXLEV%N:D4W^Y&40%F'L1AZ +M&W?+76EA^KQ=.-^E\';OU'NBDG1?!]S!X,!@TF!86U[XK)`7+-I$8^M;<3JM +MK?1HB#6HCS,W\&VG(VD/4I>/?*T<&XZ2&9WI^>+:NSQRJAU(S[[".-"CAE-E3I +MH<``N#=+WZ^0E;!W%15Y +MAR70;\82=<[(WEITB,P,HC_@H&NS!1!GM?]M;/O[]\VR:?L$3_E%%S(]_#)[ +MMO8U",*F;;$*G.TM!:WTO-2E"^0R\H'-PF#.0\F!I>B%E!CE![Q1!,';X_X7 +M#!6U&!_U[@KZ8RMK1F-Z!Z\Y*>AVV1UNYJ`1X^L)&OJ8+<[*V?0JUIK<'=WN +M&A`Z8$_P@4EIQE,8J1N1(*U]MO>6O_&)LQS4?*W[F&Z,8ZI1VRAM8,T3..!/ +M30(J.C@%>J9K&%@<.5\B;>5MWPD7@?ME[(ZGU5-K>"9)]D\6N&JT=)OL4ADM_FC.WK'07"-K\+XG( +M7AJF;&A"L5#`YD:]E0=Q0\KZAX23D1:;I2K(ER(3AX&`@J:GAV3KT:L+$VLN +M\P[)%SGLN7<[+\>4KA?*`2H/1VJ,(6C,1C*+J-I_H^SE,7ZUAAWU%MYG_`7, +M$=O2$I="__.$_B9>S<1/D,JLWW& +MG%"Z`SJ]F]WV8].\_8AMF)G4ONK0WO'V><2UK%OXW^!CT*[IL4M0Y"K&"F)X +M!W3QJNX)^A#[X"O\%'TG[$R%7_<@-[LG'E@;1N]*85W+'V'J5`1U<+]+>*H& +M(=3]`ZJUT,FPYMR9OV@7X#+)KMC[NI%?0$LAK@ +MO]X,W'F7DRN0B"Z]O&'T@I;JI4O]@&F`@A1T]IL?]VR6.5Z7R\&-N!0]OOAY +M\D3SJI+9JOZ"EZW-WV_&`B++D4%>(6V$I)@<"UY`.R2 +M9IRH^A-]FID0!.[][.ZD.AE[[,^(VUMS&D710"S]2U=D$$:FO/!P?IS3\>[YEIF6N?#'L:O2<0'0P_9N>7U.G!-BW]$W/:_Z>6LK<1=-6,]#V)3/DA`R6/!QP1B +M2AFK[VV`4([JAZP2M/@SOK7_A8E`F=%?3O7V8CP% +M^V:^BBHK?VVE&(Z38[`S32.X#*&*2>M!4FC7['*V9NR/6S)8DVK%+`PAG'AH +MS('NP%SG,&T;GZ@1YR3[RRK(YN#-=G?*2\O.N)FJ`D&35HY=VP&VJ9JQJF+# +MF7S.=]`'Z:/9S[]3!^3`S^$L('L$C+<34MTR$,J1B*V4A!(:"7F+)&1MS/QM +MDI&X@N39?R+$%=!SPU%>WQQ3G3K[LRYV]&R?EN`)K!"L#R0&S8_(SG@TU6BA +M:U;O_$@*3NS$Q4!#`ILZ&*8D=#7S^&;1\J*:SSHP'#A%N6(2%SQ;K;,\_?+2 +M\]%T>=]3DT!Z!`\RY%ANIO.G^<(QXAS,R`-^E9TM>>7!F%+45!D^$A5KA9=C +MUG:SA0-.?[KO:>9C5[[9NV`]=_^4Q@4UK_R0SPX#!:,H,O(&7* +MB^X2B1`IT>B^U*&+B.5F,^A-2]U6X`H9X*&;C&L31I;8>&<%Q.]9QO +M7G/9]:YP_0ZA2;F'B&?58=NT3H4$E/.L+8EZE)-S..A/K2CEKB1>H`S915C#=FXQ-G3B`4ZN_>32:CDMQ%7!&9!"J9:,"9, +M5S'?'/!#'U:"53QJV(O.I4Q/.F0.Z(<%+LM?UY_=]VY1F-Z^MU>I()OLRV9J +MO4:_GO_W7C*UVR8[$Q9KPS\LD7RX' +MR&O@B)8["LK[N<.8'`@%6_.9O$6)DFZJPK`3RGZ+@WT(M8X;^V@"R#VH +M_+0F&2D@10M=U<+DR +MV\"3S4QV_:X;FDY&5%]'<+]9TY+6X;&/N=N!^J5$">`M%MX0+1%R^6W&CH"Y +MTKQ5>[T'9N5MS*)O82S0^P;C(,>M>*AN7E=.HH,T/JV[]-_$"NBQ4GT)6B` +M&A'2)?]Z2LJ;WUZB'RW0LP$H%;B8KMP#--Y\EAB)FH`0YI2X`TE%I=WART\H +MY!.D5-*[ZX0+`^0?%!"'+X"Q-IQS1P>)4QAS@%]\:3^9"1)!DGY3`Z`1C&`? +M'"OMD^;#/0!E01`J_O/S*G$@NW"*M*TSWE##DDT6H_TCON'O5_QS>F7%JD2C +MB6VVBA"!:Q/+%!WC&AA6_]79$QZ<5. +MN0ZJDJM-<(%I5S1W`.15Y66A+0?SU8FDZ),[$&U'3CR6U0^LE(W8=[MC+0I'[#[6+'Y9A +MIN,O@/8B,A*'.J5*27&"[\%HI#I5:5B:"'/0Q[:9#P8-65TGKFTMB9%LO;@` +M[%-6T-\"BZ6\4K3WZN+EQY:WP/JYYG1RE,&&P+@<15X%< +M71`^)>1LUR\ATUDU9JQT/4E6A2=4_VQ$QZD%?R/^QQKTGPR.4L>UN%-P31"P +MY2V"UM/)NR30OC6](GT/1CA8'G!7)T,DJ%]A\!J8Q<'=9J/6*PA;V7P1%)3K +MTV>47$5.:V9SUBE$-3XH@"`8R'QV.945A=J:9YQ#0C3HS*<,=51"/6<8^?IXUWRS\AKL2CU-7$L%@CX2G#I&/`WF.["Z$N-/8IOJT'[XEAV.E.2W8F2V +M+^@*'H(BKR5#%BP9GHA5?^KP&R6/N%@`VO6CV&7RW?L3QPANXC`7G]Q(1F38 +M\9MU^[=N7Z7NL^,9"?!U4&H>7/JH$A?U9.LD%/-(<"?HO_%^ODFK)%X5:E+L +MBT"!ZGZ]J%S("?-+]KW%;V(E8Q]2W]J156M%G83?M6YI=.)5O0X)0$;ORA#W +M`!,L*87=-4WPN2$^YSEDGZ@V'EC*!IG*U\8=,,0BBP"WVC*H4/U,G)N=OZF& +M)LUMMB#*'"9V-(385$;P);59^"!S`%XABA"H-Q8R8\3QGY@1>AI+1BF[/?K^ +M\RIUL(XY!54"(D%\K'R-,9_M'\:M4QJV[)P\DF!`XKWV=@^`:,^_(TP@5LSA +MT[Y,[T98,@P5`4FW.>#%6P'"*7=RYT#;UQ<2^ST,GMZ^0X+*E$UX7<(V5%WO +M(-:5VO4Z4O5*49CPO$P1=811615VK,-+ECK6-!27"-2K?SJB!NDQ^W+%84>L +M4"\M^NT+W%3S![YX3!]79.NV9KA1I*Y?HYG3H\0'S5L=LE5Y9))[>T[2/4-U +M>0T/'!@4I[Z7-=V*&]&'>=U%GF/A+8%DW$WA9:YJSA%5J4@39V%_'F56*JT\N!9!)@RA9#G<)3Z;!2I[P$<++#" +M;5+I(&L=;`!E8^>47Q5S@%+6_M8U7X9FLQJ`AZP3JTE+:_^S`K&?L9`L_Z#V +M3AVKVMF!3(S%4F,/*$1?XLL_"ZKI;HL(;^^Q-=ON9DSO65E +MVF%#'R!XF'W`)_#7T9L(&2;5R*W\!#I*'U'7_RD[DW);A@UB2A4T/O'8+4"@KK(D.CG +MC:M!Z,\G-HQT*(^!<$MG0MJ(WR-==#3L#@G$11@:H:-B$&U$;"ZU; +M*`7%:,TM6_XV/T#XE/*-A/JA`T_;>CL+7+'^4-FFT%-04BZ+&#H(]^A'VHLT +M#/F+79W;>1A3DI?`!^J^B2,6/DK_*8",0H1H*P8X9)&`^KZOO[I!E0%T2NE\ +MAD$=W;=>4XX\#8^F[R>@:\YG3YWD8&+C2T>?6O]YM\KE_4X>IZ3J9'DZK)$3 +MK;S%<#':,N4IVP21FJ+NN+IK.&"B(7!#MV`^Z^2FG=SPZ`3DU(4B\-W5A^7R +MD[3A_JX"DDZSHC8>/+B5*+,V[K5^/3\H\,2DOL>>)]IK0OS`/^+\,8HXZ(E3:@B!SEE$_90EI67\>%&;4RSC37&QS\NJ!!.C1ER. +M"E@UC3F4FI:U?6.J%PTPR!O!2U2.`05Z._>"%!DQ58#53=S8H8;92 +M#F7;XH1`(,2).X>_5X,B@("CRVB\?;&_#SV:NRZD!A +M/47<8L2=-25E3"%$D]^@(CF5O5'N,HF3O"M*P_N,99E5A`L21ZO.[O;P!%,Z +MLJC609B0\VW1D0!;NVYV*1NM1LRD]1_+_1^WODEBT]=.! +M1JB?<6D<"*)YB:Y`%"L:3[L!-Z[LF8^GF$8((+#49%E8,4G]KJ3D:@'S:1]5Q.K?Y#:`R\V#BRL7H>#`#5D9`[A)$5"(8(KD!$W$VIS +MXD*YP9)JH#!K,>_@!05:<*]SD"5BOKX!&*%A=%_!@*/"6]N$+Y4;'Z.>7%;1 +MD8)O?&KP'^YWAG3#`VX_[_$X7C6SJK-_5_?P9_(/<*>$"S<63"8(1V(GN4FJ +MGZ=X:W*50+AHC=O(1WE`5X-(KEY`+^&Q$KS2'U(4S0"3>[+[I!7F&]A/[%?$ +M\/XV[-UQXA"9%"HF%J;.FG1[2T+V@G(*(2735#*V\,X4)?Y/?8>,+,EXZ,\` +MO[:0ABEK83N2Y-_,OU(KW.'_6,VO-VPM<48#FZ/`YI(6>\`" +MQ%_%BNK2]$)!R030G><(6";T\KK/M[8TLX($O?O)V`S_%=+NM:&-%.S7HA(> +M1P?Z)F)WC$M;&X;%=K`SSD:3"HN5(6OQ""LN$)_ +M/**$PI#26;MPE+S63*P!,)6QX)>4J@N<[MMU\3]J2+X5EG/U1?BI#\0QC6'C +M<7<3%W-C9SK5R?AKI^]G+#E`)8U\;27&*S#-`L25\1FKMX'PY58@R$J\BB.T +MN_9%9P#.))*RF<>^S!2CT=)OOPS+ZY\@(Y:'-*>(Q]5LRS[S]*0X'14LU/JP +M=FQ<&1G`]QIG+K7U]N7_#::&,*`T(5KXS\HZ1-@1D+\:OK/GF\_`;_(.D*]W +M,HZ?=E(#+_CDP>KJ]=$?Y+*Z)UV';=0FX*M(;M2R!^ZRF:EQPMU-Z6CEA$MN1=/IZ.-<_89G+$6M[U/Z('/K(.XV&W@AM +MU+5LMLVMA9WU=](2MPHSR-YWFCH]"1S>3ALR?KP#:=1MDP#HK*(/0^R6A)HB +M]MEVL`"5,ZV/!8OQR?HVY[LR]O5*(=8+?OBEV=^16R@Y[?U?QZA"@(3#5/7V +M4D>7G\\"G44&8+]0YNCT,.1'GB(!I]KK^?K"YV((RA(\JO?^-$4U9W[\?SAJ09=M +MAWRF)9O7M@+DHJ1[B12`]?-ST.T,WW??MF99(&`%6>+Y'EV?D)&7C\CBNWH$=+>2` +MA?91Y)FS6'2UOL&@&U1U-[%KQ*TE+"?`A%@!740NTDW?$1)JJC.(!Q>HY:O12!F6HOCCI)=A +MC+#.L$@AQY&Z*W4<__!TE)\B,J;#W8)M0>?S/^)ER`4[U8 +MK&T&TX/%>Y+:\VY.L`1VC5(5QZWX-.$!_Y&R^Z9DP"7H?1MUP:,>]\E`*VZO +M<70(\8TV`9]'5[+"W)2`VCR7/&^:RXRX_P7?_JV>L4*+/2N]FO0@DAZ5%TD* +M&ONJE*+>*XS%^C/X>(2D6G5HS^9O)G/YB9>W`UF')"Z>W( +MP#77(;@"[\S">P;V$1%%$#SV^"=A361S@C&_R0;8V=,0>08(QKW!PY]:F@;CU` +M5("$RD6,()0("8U/8LS$&&<3BAP,7FW_:;D\XZ;VQRN=>1O+'?.FD/-T';(@ +ML:=9!4%WZ97<5FSYO,;-19@,257ZTJG-D\ +M(1,]!O$JU[PENXVLM=_6H5:;S$LE`J.9<`+L1UI=JWYL+30HTWDE.60N0LN% +M*1U358B2KN(419ZF3??PH+4*KQVKD3<'C)RP->:I-!ZHD/FMI$;EHYY/:`6V +M-!O1+B>B:%!JP"?-%_-[2O;'MN:?.DY!C]CCT"/`6@B"(".\$BZR_\+\LL4*+D_@ +M>)C#SG5,8K=UI9)7Y@V&CPHFS%]P_:?"W^'?Z-+$.@:X9>J0Z4ZDZ5Y;U`VF +MX]/Z0A>2[R'>01DALCL)-(<(D7'<]B^-NWXKFN0]P&^?M*?U!1ET!VZ*S@(0 +M>`7]#Y^7D^>Y7EQBX`LV?9$6,4`V7-[7+IX+4.TZ$DK@=ZMF$ZI$2RQ?FH?. +M'J,B()3SI`HRV4>&;X_%F^5EE^R9#`[]U'VWW);@P.XX`0C1HHU%0[$O'C(+ +MM[*"0>HA=L>7;C%T\P_BD])$?)JS95T.3*=6AA./3511*U_T"9(F9GG*=Y$= +MM8B76'6KR]NK5?MO)4%2.7/AMO[D2/)2`"2:3HW#K9B!/>Q/KEU5'I@SW+L) +M'[KKSX3TNI&XZZ^@JCW025$A8.F;#1L<;FBJC+@[;228CUP@DU2#T$@^#)DL +M>TOYZHUZ#)3J:Z7VP#%^O0PVIG%_2EY)#!C<2"]@*H6V$_?PI(B9R1<]7ZGY +M+H\HCK.X'Y_#TAJ0]_N<=:W1*M]1J0%,?\!F-2H'D_&0D*.1;`R_@70]! +M:&`!I3=@C^/[CE3XX?:[RL[3*QJ\+N228"NRT./@ +M.6GI[GOV!\[_#G*>;-S&UD]C'&_$"UD$MD/G43XPM@*[6DOM99(GJR&.1XF= +M6Q+"(CC_H5&UI43R:_WE1%$G=R2M&*^YOX+:FRV`92`H'KW=""=H9F4*:&5K +MQ0.2*>TS1K>,MCW`01-$B]5B$9YTG&H::<%"5:+&"OMH\@+^S=M624+N]5#F +M&,2LEVPME%I@4*"A33R>;*0!$L$#*Y"LN`2Q69I+M;ZR90C+C@#E<7=MT'*\"\:F4_17$=J85YQ'\I&42-`8`L(J +M\ZW,L/Z#%O)J0^<,&^W"3[Z0GS7$/[P+R\$!5X4G(*_ +M8;(A\'15P"_M.[.('7&:U3GOB"BJO;2G8H\OH7M6XFS4&3QZ$Z?]5E-UX3-2 +MNCJMC4$?->+%BE6HQ%E!+3+^3J/M[#*)C@''.1WR\#?.V"O(R=1%(E;'].QA +M[]5/]>U;/2VQG,C,!"`!XQM&\;E3S8#%#!H=A?M2JMD>6,'1'=00F_H"@OI( +MFE&]+FX_Z2-=QL:#GHBPR#E"RNAKV"4F +M]SAJZ1EM<6(45NH1Z]#?B5";,+_ORQ:5O__8U(M_"V84F`H`RP4CL0E2!Z%47'=E>RC\*# +M6IB1XSS[$A6++03D +MLMO<+%[E:CTH$?L$_$+N@/(=&"!F4CN9>5LZ5]I8W_2J6*`3WE"D@F^TW7?L +M$RJ[2J&=HRA!?47F(,DOK,E3B32X&4TU4A<14C`9'J0(.=7;(3SF;86.[E#P +MF1:&\T:-CK$4@:P?\]Q\W/XM3IF+>-[&D9/,=+R,=9WW-CUN+PUUT_MM_Z)% +MN3V.\KOD^O9YB%S`E%G>[2MZQ-`EE +M>5,CS",B97]W^[U(3^`D`6#0,YK(_U),X%/X\=+H*$;6-5_G&BX9=M&$HO[H +MA3+Z<`<9E1`(`_?TP+-/9;7@UJ[NP$8'HPAM4`U/M6H!0S59#6U>-EPB47B4 +M%,RQ,$1+?`JDC_W!)WMU+7DR$G<>=+2>WH;D?`HUY(8DV"E5(3N>&.`O\&?< +M(7-292E71S97'#R\-NI`4RN"-`AD5TKJEU7P\E##=3%^P&JB?F,PMRIL3\/O +M0]`:ZO5_Y7,024U7#MO&Q!^6MM7;4/<9CV_%-^%):8R)L'XXWZ[.(!&(Q[G" +MRJ?ZH,7.&>XX$];&4<(H*/;5!HN8*[2/\3JA2\_J/1[/Z_<^/1?:V$^G.M_8 +M]JZ"3;?GW\48Q4_CBJI\AEO`7.8XZ#D?3PTW#[:<0D$C&F(N_$KCORAC#^), +M58F83\MQN>6?/*)-U<^LPSL66H9\?$7_@J>^2!F;)(UJO>95TUF[Z'HI]_7< +MP$M/##`YQ$2S[M_ZM]\>C>IV.@K=ZC&DYM$>(#%H%8_VNWU8"_/L.X,MGE@T/OIK; +M+DS/T3((70)2V;](KQ@W$VWC3&-G,4%QC!WRW%:XST#ZUODY&%X;_<#T`*E9 +M!QE.$M5#U!!20POLO&Q)P&%<9T#(=.B!_*;:#[*[?JE+AY9VS`FK)+B+X/3, +M9FQQ#3MACN.%F:J:'O67I2L4A7'\!?1`XA\[G"8;A_+/BY9^G&'T+9CF?V`R9SZO,62VR'U"D<5]A/D_PU;F6()`-1TFF:-D +M>0FH4!'LFF$P_#!GF.'//FYMN'YS\B=C\;+B*RCV0:!/C*[-J5S0.I:8O5;5 +M;J<]_<&,15@9WWZ*`/Q1M>8?&/A[0HK9B)?UE4)*4S0("<]\6.E6!YSRO_F.GV4PPL!*J:4Q6A2"TN@HG:^75$HP^ +M\B4`A2?\AP4^)$?=J4HDNGTF:RO4;=P[I;Z^<'0%<51+6>.*SL^`G9<,D+CK +MNS^H\2BNIY3^ELIE0(;U.N>0J0MRGJ?P#Q;;X&C_`5!+,@HT0V&)+*OSI3(! +M736:+TZGW_VE>1F?LNKY7KZXKY@A6F@?#Z%^G4A]6MXW743A&JO\BO6H(!X= +M+M>2:G<F[)[E6'N+0Q +M)!Q5L)D\Y-#U?C5MD+N.KMGN1=U)'U5=P*_2J>0TECPI;-'.'WYO*Z68LO)L0_M62_[+1:W(_M'2CYNQ^+(L'W&"D! +M)[^U96D#'6Q'P+/1FJ$O1G,IRB:^4DU)`-,4W]9 +M\<6``(G>KCN8VGN(UX'56S#B^,5YF4F=#JNG5^G$--H(B5*)OU4_VOA>+(T' +MRL0POK1Y1G$(\?[<.^Z4P'(TMKI`EXKR=&_KM(`,]CW']>9A9\[>\X%AP5D` +M'!2DBW3*3>J_8)_DUIU,_0),!?ZZ!%8%(RSEW?E-N#^4R:_9A9D_UF:=0K@B +MH0\YH*VD69'8ZB3#OCK3TWPJ'B-9 +MCWP]FR8'"5%%F<#:W16.%/B@?Z`2?"ES/JO0J;K=IN0*)^O\$_9#0M!K1GR! +M+6?W><%YD%^Y:(!Q^`TO+D0EE(Z[EKDRCM:/MW'P@CE531%*EEO`7HCNW]LD +M<".NV.C%JFO<9C."3B:W^2Z)",X\H#0[(4_K/R.Q1&Y/_OJD*;\)?BT_HU3B +M?ACC,0,U(BV<)\$3RHQ1CO7MJ)47KCBNR`;CKE%7/EJ32`K+SK\;J,0M&F4J +MV-#:@A`I1HHOQ#&B^N032X-)/JPZB)%4_+&@!:]=YGW\#'3JMH&D@XS@;0JE +M:.>-D(IF0GQ(.BZ81C2RD<4=GJ\2#B7B@U9EDZATH"9AG;QS.,!Y36!9XF3J +MWS?Q:7;<>P7=YQ9T& +M;F_+H^J'MLR!#_<*&/LM0#RH.<@'Z'AN1X20X)Z4N$)K9T#3]<#S/]K?HJ:K +M=^'`\'X;"*=_P]'3$8$OB-K,A!YM%:"1RWFLFC_)@FL%1Q!35B4U@Y_=C=@* +MJJ-A)`RVF9DITW-3-ITV;%JVZ"/5G*L"ITSD!T1LE\#$RB!\0!J0X^W$(XG/ +M':1G]*88Y@G+!>C/R[,^FN;>#Y0`_V7`DG'?%0*1-DIX>=0>&$M<>H<1%?'D +M8"`BXVW+B[H<'"ALVXE)*6.1H355MW@R"7K-/6Z1 +MVF;_X_$T;KZ9OP;^S>HD;7$EYS*/$.9.>@O3F:1/;6J!Q#*'0^R,B1G3(>QB +MRSJPC33'6&3Z]C`J2W8%41%!\H,C`%Z0V[C4+*#4LJ3'L"N5`YN_?'HLGR1_ +MN&QZ*CNB/EN*3[YY[:207/S9=Y>GWG,O2EA_VEBJB!1*(,W7R6NXH]BL'7Z( +MU^`"('I9/VDU;WX0G]<5YRWY>VQE:=[,&:9SU^0-;@4]WS&":JCF#7S#G[*N +MR+P>779Z_]NZ5-"*#92JE>W!/WO#3_YJ,#HM\4=*AT?0K&`RPO(%8*B_]$_: +M6F#0.M@IT9?:$G"B%/%1_`6&$O[>2)QVQ,0N(7=_JL-X-1L=+*<,B`P@/N+0 +M?0J^?XFI821QLFML\(P +M/$&DR31GO!AXP[U!9W%I[6F<9B/4;09.1JA4S!/0!U5O<6O8_K[--UO92C:' +M8V`ZQ1Y$<\;W7FD=&5?G&1>%>L*J[Z!9@X;FN/,1M*F>/.N5N!^Q.E2I/CB5@6[]*^6##2O@8 +MH+'5**'L=RSFLZRAD7)-T(TMM>K'($N-P^01`QIY%>6>''\".LWR&LK%L3/@ +M1H,?RU8C,P2X,N--O?`!M=9^%7%@B4.S>66^#9T),Q/>D_R`"Y(,\-`\F$49 +M^0H^%/&M;NJ>^4=[I,-[9W:X]NT/KP'&3Y$0\$:X=>*#6ESXK1.[Q2^\S'.XU\LO:J!Y@I4?FG-85"MTV>TBSLC['M\MH'1DG/L +MEPY$;[2H+:1#7A<]T^L'S''R14C2"",>3*@YY4)9<9K"-*\#^*1,?Q_QKJN$ +M%@#37'ICHTA88?1Z@O]XF+I9*S8).[BC/X)4LR\8(%1[FU&XV\"?:F9D] +M^_L6`2"OA'PGK+_YW@VU*YG/^Q%#YT]YK%QUHW]71.%L=SU3R!+*/$+$790SRCZ+8&IN:+& +M,G8/MJVX/.(-P5S0U/5KS7]O>/W%.,YW-[3AH+*8P'/Q%S_L`I_/;I@(&<*Y9+X]*E6F'GPSNU(6HPD;BXU``VGM; +MC=J<#CO"K9U:^*D"4_R77E_W"5M_"[+%^`T5X*HE2;*X?==HB3>G'4;I"^LW7C@ER^ +MQZQ.7;__IOBT'W$6VPM2!9EM^3.>BX#6P(_^@E-]^4WZ[P[<@S=JQN%$!K"\ +MYCDM=5BOUM/O:%XY9*$65F(IF8YN_!`NF`8Z,#Y.&`UBR/Y2=";ZLVM:T_B! +ME:?0;$CN&I/L;D(P+*GI6Y/$L-AH-]G!\P[N0)JM.^YO4]=U.+F-%_Y)M[,R4Y%_,DLY'"84-Q0T"`@$Z)#*)' +M@//XR"FNR^Z8")[FL&#.08E\I<;)M?3?I-M4@W63Y.K$QD->9C6^W!>"Z>UR +MU.7#MAJL4/ZM/P1`+'Y3Q6^H&!7>"#>J0_MR3EJ^ +M>)!*:29BK#U\R&3=0'/Z8:$)/N\3GH:!7^U:&F&WGW#:BR4AN)[5,/M<2Z/$ +M@OGN/_RF2+Z57*XKTD8+R)4S;M3W\1;9GM2)X"_C4V)WJ!JQ[.(QIQX8.@8? +MBY.8MU5%)]0'.GU&BUI\P`K,N\7+ +MZ+=DJ'Y6:\(^I80#T7#=1,.%A_>V]=!-YTK7M%:1N7#6]?B%&@[N!$[J6["! +M4G9R=`K%@T$E353#/J]3,_<92=3JU#9KNW)@&>E8)F/4`L:\^^0 +M[6``!3JP5`IJ=1DLHG6>7Q\"Q*@[5^&V-WKFXONH"I":LU"+\ICQU+&JQLBP +M^2%L,%DRHR3@O9N,Z:YX?)(SJM(X:YA$PB#,\^MH+COHP,%`_4C/%L +M$$]$[*.@-$LC6&+RRB7T*=D-B6K9::-1][*_RW6PPE"H9$X!P/S@^,R?.>=U +MFU1ZEKTI\KZG=B5!#,AV0/=Q@L%,3$U_^GQGP[7XASX@4V$/^F*VX@@G:]<# +MK=":`>S"&T[3!*R!7&`S2Z#;5@E'&"H#^+B +M4$R\\K6`DE]\Z@R92-T.K6<0[U49[C,\JPD"DN&)`O8/C``&1F@2:NCH4OMQ +MLN_;F7O7=HBSO]`/?=%N,2+W@N'7[ZMR8CO#`-^XL8R8J$W9B@MNSETW<'D[ +M.+[BR`C(/Z29C$A%H??9-W\VU&9QN@"J@O17SJ(YZTG-S&1*)?O_O@&%Z?L)>_J#S`PJ<.GJCUJRA?#-NP4=8Y +M=?E,H^8ED,3^Z2V`3=6TP[/-2A)K@V-L52G-GV0_^BRR@NQ0HIV6O>FL/JZN +M%9\1KY]E[#T/W#O'MFU[FW%"OV32>3&$ZH[7?OE>V"[Q.'LZ7-0^7\`DL^]) +M&)7X"&F*7_'R)L^"#0\T%@\68FX9VFR`.3]OX7?%C +MT,(I*YIDCOI<;E)^(/B3(Y;23Q1]^!Q']9J\$ME$C`;`1#IX!36E';JH";]\ +MD"H'K'V[V:/!'WSL%L/%W-2%D1(^[XW77F\&L<.'@]6UOC>?H.3XG51-5I)/ +M292V!29+UA7G0P&HGT/X\6S?L'#?'!5,'4YX5=>G>7!@2*O16*>.B7C>PTT/ +M'+:+/G:;&/Y2SQPBWVX9\Z^BYI9+!(*5VV/I95M&J3B4(8XFW`9/?%V-3B#; +MC3=:A;;4HUVP?<7ST1_?A.C[G:9&L'JDFL2/ORRG(T>RZ>"91\VY)1>1N0>EUMPW5!OJ_%(9ZS.>B! +MP0\[*`J7ZX=<:7;&K?./9`LH,V_FH7R1+85F.4)*3@@[!CJ^6!$_\ +MX_:`@4"&C:*-.SYNZL8G2!?\K$`V_`9$SB4^0GL2$7">4_WO[GA8AG3RU +M?2%?47@6:0X`6I/MQK\`K'UB)BE!7]%JQ*$\J\7[KONK\XRHYK0H<=;LI1[J +MTP8-K6`N.5`9/'XEPL8_E[OC:??8-%-`+@IWKIE.*\Y\L&@]+_YM_GQZ7!M4 +M-#@'W,5L8Y?JZ`E+/9D`D;1Z0_MD1PX@5"&0E5S**J$63D#"2'GKU#Q`/1A& +M`AGV(TNI0!OATXL$@0#S$`T#_UEDS_9]B391S?[][K-8+8O-ARZ@$C<.!I_G&?YPI`W_OR!^2RG +MQ&04UB=%^+EPKQ1!&,`G6!5:;V5'507BB_O9Q6D9^R&9WEP^_=\4+&CSH0>\ +ME?BJ;IJZ3RT"#0/W\&,-+E:-=O/DS_W2KSPADTKZB.021!D%4_;1,!,9`1KD +M_/GN6+U'1GO"Z>B0T2(!]`/*NELYV769024=)9Y_!67[#.JGTLU<^LTAW?PS +M;)^UES.MDFLIV$S(>&MKYC>S==16%3=9R+7&/6^Q1V0E!@[*:9^U;\<=Y0^* +M0EVH9@ZN&+?,BGV3%4/DQL6G%-`9T/F?NGH+9Z%^;YYQ(0]R_63R-G],D@%_ +M6I8:J=\X!Z/;G(RY4VTL>D='D1E?QS(Q18UC&8Q#0F`-=Z9`4>W,R?*YZ*6; +MG]F'=F/#T+$_^5>BTM+R_JR&*WIX`WH`A9)-5J7#^B\,6BHWF.4(*`5(8[!* +M!-M#,EH,[=ZA$0M,'$FREP90HDA?)TRS0K`+_PT)J:R>0\WK5_3,?,U4W:F) +MIP+V$GFK"3/P(*R8_,<6S$"'!-=<69FN*LQ6RMU)WX7ZAV8MO.=TLHA:!(NS +M!*46O)3V#N;YU@:F)WW\)7M-780O0H?BC(4?`WRO"R +MC4*?!`7(ZEU$9Z/OU_#'E'M3/KA&A&P/PSR\8'9GW("<+W50%M;T;,W6UWYI +M4[KSI;VEYX._D!YAHD])Y3M6>P6E-D@E)L&H3A.:(,&N>399%]-?= +M6W=H(W,NXDY!I(=;WBAFW>LEU6?V9MCDD>7A=:K7(R0A]C5Z30[\>0-'_*U( +M0+7Z4RG!];Y#(V;X*[EJRRE*5>,$W[=<:&7X.>+'`MUJA:I]NQJS=)">R3Q7 +M@+^<\GH.[&JIR/)$]GY0/RQ-00X)JS@+6'X.D-]ESNBK?0+.)H)KI(/N??!L +MN*Y:*L/TPSWB!BN_&YD>3>`9=?M`6? +M#!#,-WXSIFA19#6+SBW^,EL/G>X$G%0@/7F0!(#$"F=>A5"-&'8%?%^E^(@\ +MV^N;22V*N&)WIAFA[B.Q-IHR&,P"J=_VRY(:]Q-@0BZ!(4QE8QU8M]"N]233 +MFSHK7RKUVU-&G>@YT<>]NL"DD*1-)VSX@F9`A!+$JL%-YWV[Y+-F?:H-(>K,H>Z;AGM##46YA69`WT\#01:U,@3/L;NH5!Z"5:)<\YS(A5LJ1C'#^4`HV-Y-DI/!#G(:RD*#F,*V6:SM5Z#S\LD`G2 +MCJ7Z9*=5:3RYR\R#:\&?'3.7F1D*U;-J7H0[2K0,DYTVB?9M7FNG*50`0

    / +MC<`(M2A)9(3T.X[+\FCZGPH7-DMHOH,;Q$=551M-I7V;5155599%WY.7DIC' +MQG,-66XV=37UU;5-#XU%>;Z:QW#61(=T5%L:RNL,BT*G6MF.JQJMVBZH\$=_ +ME!4_&ILJC85F:+\-:W2TM-I-+W'T>ATE)H$\9Q#;*VRL[\^`3T0?V@8 +M;,!]:1T#]4">55:6(#^"]-5=:.U59UYAM2/]5UFOJ+2NL\D`9U`EHT6^QK01 +M@`X`O6Q`,5@!L$>5U<'=UNO:!&]H`="5**JU]G:;74:G5%AL2/\9C^&\/YLK +M`!Q6Z\/:LB]3G;@O=74+@ZJ+'86FS(>P[@>P+_`#8-V"#=&#HE.SOG1"_S\; +M#J^;PS5Z$_--4510F"$2-=+_58"&.Q6[`B-9?#[/QGMUI@UMJT%QH`P0=9U6 +M]G7AKP(/7;7)&=;.PKB1RUE&B+!_Z/]3^<;0`R1N)/"P_45<`^GXVVDCOGG0 +M17E9450;"B?B0_5+8%S55`HO.`_F/UGJ(0[W`=IICNK)(C8CKL+$>NQ$S[`/ +M010#^S%(Z2(K!>JD?&TXHC1L]GJ-)K-`[LOI!XC)9&5VMHJ:P@_DBX/3$X(T +MV8*X:T&4V&4H57X_^R-_@G;Y%@.[)Z#D>35IM*T^P*N%`S1T,7,9FAZ_L>P( +MO@(S9&&ZBLK&"U<[[(W@@SMDDGM%1:0VI%YH4EJ)O_MAXU5F`^@7V@7_XE)75`@<*)WLZ\0ZU];5+H^ +MB\,OX9QBSM+*7I/>2PH$>%F:6)Z\)E8N6#=@MJ`P84`KQ*_V(!FRK,U?/\4HLSSGK2.Y>C?4!U7UUIL]I92J!3[@.];V?=:/0=Q]%W +MPMD$QRE`]!GM@/\):(X>,W:&#&1J*[;5&XLLCA9'MB`\@OX3&!_('T*GN11A +M#]@.*_(D/G;O'+2YGDR_%69G+XV[=RLC^6:91.0_\,Q//XD^@.AC+-9850>3 +M(5DX\'R/C7GK:559?S]R8J46?E"?5?2`ZV`?R']U%F]%!!!\BKHNAI_F@V=1 +M5661:8_(FN:PG[@@_U_QPO$H3XRWPAZ`=5%2)ONBJ-30D!9,]*ZR>D^D%SH6 +MZH3V"'O7[C`$M@/D&9$3Y5F>;(FZ!A_,GE>S^A&[[)&3^9%LJ8>F?-$B!:E_ +MZNK=E6&B2E17+:4J3=%785)\@KP.A&%SSH5_P'^B:;J0&F)ROS2KL"@ +M?2PI:5U=1)1_L"2%_);D:5GOCLUN]!6:]=$NP5[=DR#^IM+._&SNOVPF"E>$ +MJ'>P!>K2PE3SP1VJ)=+Y_?E"WX:5EX_]I;O.4PJ>XM-@:Z%FCBH>KW"ZXRP< +MJ-IN,*!BTLDF2Q^^S1`OZ"BU.2>G'EDP;`D-BX[P.[T1G'8=AA7[O<5+W4+E +M=F*Y+J)YZ/7(V;*R6/X)PTE&\V*IL;0()FB*+:2?\2=X"N?Y55]+=MI7A:))_G:'Y%_>$'_`(YK@<.<`:.DB]@R="J>2>/W@?-*S^ +M\@_HB#2`Q16=>9QGY'#\B'6_0=X`2X0``W(0#BPKZUB1>5%\>F^&=C6@;[LZ +M7.TU-H-/W",.%(!3\H?PH#S9!-;7-//UA4M!\DJ!]JQ!L5/[N`=(:GQ19W)3 +MDJDV43G="`>@]4`M!16&2PHW +M6^//-!+'G\@)1_`SZ$SO\$:H5D45-B3^+Y+>23S6;<"?V@^3?GI$MFDOD:]P +M$B_[J1]HMD@+LJVIK42+#O8T3DT+^B1I:1*2R0R3!+`XEW]7\R9OJR]E/WZ4OL#=UE@+#=DQ]+JG.O +ME5]I#3=HJ"8>"&`ORBM`_^BV`ZP2K5;UYWAD.;%$3X6>S29]#WSW"H'06,_J +M*[!9OV&;;2]"T*!VA_^#!6`Q8)X\1&M@/-=A,7S?63\7:G9M9ZD_E?\OKJ,( +MYEI3"`EA0X(8*E*]P@73#%O*RQB_LZ^7KOYB/G>4+#?FB>+YHD)ZLI45[G)= +M+.08^6L$M'P[NBHC.,=*#Q&3XU^0-BR"&YE&CK"">+3:"O:';7\JWLJ`^R-= +M99%)?3$N"Q5#1#-F!^:BN20QID)WWEI7ADHC+23D3[`^6+N_3#`KN58!HUU5 +MOZEB8GL*5[?CQM*?IYHESP&A/RD\89.L%)M&VLH5FOA[M1+L9X#KY0LMW$-% +ML4)\L38JV6`.O&G<+=F7/C0F-KQUPN;NH^-B<2K2^(_*P:E +M2"C2](==*[];/+SJR7-+JZ46IPBK<'YA.RL>AVM50KA"-P/!$ZZHK-$\PQMV +MM\(HUN?F4D/23_*W_U%ETHOLO;S_"!8@.005#!):4+RP.$\C..D[U3&RJPDK +MFOL7E!\!VNR6_L@+LSRSQ7_SU#[Z[0Z73]OG:;"+$=L=@F+)^7-Y86-89UI#SQ +MD0L(K,CV2$ZOG=_(@;H\V%'A2A^@SWRU#*:">.G`E;LZ_"`9$YII.#9':64T +MAM'@?$]XOS7V6%2.4C/T*Z)/P?UMR34D.,BNX>Y&A8[C")N5&R(G@?_KP8$) +M[]7;@G;J25:T$]I=+J-)JF1_J&BV=_?O!:3F_*K^P146B#%,3+^(N64SWV5_5I_6[2651I*@W)FU^.!DC>V=H42TL3HW*X8;OLDQ +M.>[)9?)#V/F.*2X(JT5$B/=7^2W*DO[*J$-"7=K=U+R6'K@N=J(/[19-VZO7 +M@5A7Y6O-^6'W1:ISUK)\P%PW]3N&5U)1_R@#6(3XBNLAEP6KL!10UJ-! +M2#YD782SXD-;9[AJ4ZX&Q>J/""?35/B.T`ZK+%=L\2ZF@W-\IXE1K85U0(.Q +M'T%[6RF;`^97Q?W5ZJ:\B'TKWEDDM_?F<1>.2B8C@#W8,32+4SR)@E>_@42; +M>H%E="<_4<7MT=\.V3-DA?_9(+2-27=V4X;EIVU"UVX_VB;%,]I7#0-B,WJP +M#F743@O#5'G;!>__;GHW3=W]O'\+HL$5U*5#46)^M*_$LJV@[+C=M&TWPF'M +MD\I_('\J11,RUTRA&IPSL>63WV:+=I7$WYD*WO14F`;G9FX86R'_PM+Y9O\- +MFLSEE9FZ3FQETF@E^0"A+"K07Z^2?!#_3`Y<4FH[L4$TNGU`FW.UK;$.2J_, +MYM0#JM091<_(3#`(JSI_9#YKP/0W%4%^,8A2U8FK*4H[XP>%T%E]Y1)-T`E, +M,KS8K/V*A_SI>V%?VC7Y$39(@3+1@_V=D\J7-_O$YED>WN#;_C++?Z+*?5H* +M\!GW8K3#W!WZEU.25=OLR>9S3UE@:-H7B9J;38&K_3Y$?@^@C^!!NT!6:ZRC +M;#:6F4DFP7>?-B`(H'"7C_YL>WT`[>B[C4M7SDN-C9V=AFLKE=L/[*//SE;* +MOU]GMA-^LK?.F54:)%W\URZ%RM!:@-2G)#_@H/1#Y9HZY4PP/_[M]+#_@N@K +MBRKET/N41J4#B7:Q'=?2$9TL"#3C9H#)_M"DT[-#@4)FKKZI(KA;^*%JQM-I +MFEW"XOA_DO:)7S>O,BL`A>]J)+E/-Y#_W(NMX.^5!18Y6R%E&LRLIB?:;4Z6 +MFTG<:+NTK[H^Z*3\,1Z0[#N:VK6=\&C:EISEI7B_O_S3+Y#/:6DU/;]QJ,$` +MO'WUST//\8#NFSO:$S?8(`2O0IMKXX'CS_7A-ABJJO7[#8UNRKMFX6'>!`_; +M3:[;-;<.,]G]#HM'I,U2=QIM.!]YK4ZK64;Z5!TDZPL98#&3_B'64/_=()U* +M*JTMRG)'8#>WRC6H%PGX'YJ-H^S]0" +MNBPU%5VP*QWM:'`,6>TI-+GNV[M(GX?U^],F;D/RQTVD[?0/2O%\.%!O5IG\ +MP7;P[+,X\^Y6[V^OQT:`,1&M:U:0;^CD%JMKR9_/4[[KLAH\UD.WR3%496F/ +MM%?H/T!,AJZ+(;,?X0=+=MTU&4R'<#S[W`L\NZ(\EV@_/3R)>5H'P1O>],Q[ +MV=?M$6;P9ETLBRCIE"4D:K!(=Y0^;,#^B[5H$JY7@IT<"O_=]W*KRC`Q/IM/ +M.%_.I\)[]%;ZR8:Z]H.W0=:\_3/G5]Y+L@QVFT7=EH`_H"[NB^AM"'@_/PX$ +M5E;`')IYW=3465877ZF2%)M>'XJY6!BCYVOLLB]E\#2(>%U%NL:,.JVJ6D?" +MUHTD\EVA_LU*5#T8G%17&X3S<43%[-\'Q`AE>%_/+YP2"A1MP9G'D)Q\>_S= +M:#(97/Z33Z#/CL?=6\>59BT^^,NUCZ_W1IID3$_N4NCP +M^>`6?'SUU<,7.E5S3+Q%/:2@*.$-W1[RL%'#Y]?L!W!F(M?/R.LI??:42DB_ +M&7-91S\DN_725@F48T3O+Y,&O0CH$`4?&8:/2J/U/>49>C&UX. +MUH@B>@D"J>8UHSRM]-[^WQ^@!'5=\W!#95\OTF&^>K:ONV[?14U+H +M-89`&-49C(ERIMST`$6DUZ^]&VE?U=?_L(*35@X>^@SU,^K-!L-%LNVV?; +MV%+9TVXU?>ZPG7C.M=QJ:2D,5C:ZV+]%K;!7G%@*=R;$^;$&-V`N7]"*S;UE +M4X;@5']LPGDKJX)U,KE*ZMJ0F>*ZSHL#BG9B^QSDVO&8_?]9TNCU"YBCU#W[ +M[^U,5;S/6819%KXK[D_SI]2&]8IY,W6%CXI^HQ$79F5WHGI[S)*JBV8\:D4- +M8E?V0V>5R%6/\AI7D#%^:3OM[N$&\7B2M`.LDEA=GS3L^H,]DGTY2"M>=H+* +M8T5+2;7+]=FDL!R?.5;#>7-I_@G>JRQE)Y\]8#5SKOH92[BOM#./V,UG7O6Z$]A;48@31)E_]UP +M*V;`,]"OJ^;,%:W6DVE4$JSLZS9G#`[?8U%H4;^0 +M!MV?1LI_HI2OE?O7(DG[76];?_8MJ(:"E?95CY792JECK`)WD)8Y_BTG>1EF +MNRM->$5_-E)O^$V\78YOAD&W]EIJ1,HUYW49[2:1USVCSN +MGU&@IL[2:0,(2+Y\E6.HRG`8]KQ)-_,W[[=4#5Q#7]/"],OZ>TZI2/K##/J^`QUL< +M^^,5?]>AT:_@[E>.F?55NXWB9-KSBR3J_HC3%7V.R\_5P$.,VY],2OZN=^8I +M\[PV>>[/?$-QG&>7CM1!X()[W$.0UKU3GGOSN&^^7_W.U4KYO'&C\7__QTY/ +M.UM]**>(^6M3/)B?[;]D?L3UL!DF[7.K/ET3NTI1]H'O>A=N85E\[Y.;/0R>.A_(\5W@Y'<6XZK,IG>TT@NIZV#WJ4"]J;2MKJNB%F?W=&UZ/&KW&T%D( +MSN`=L:6(/Q?_3NRUV-97(Z,\+"NLTAXK3_Z6(\RA^GOL-5>?I3<"'[3]OE`O +MKZKVX\JS8A1')LETMW_=U%B/3<.;E>?TJJQ6)R'8K:HP]@:GU6#NI%AL90V( +MX!^\8$#,Q"N++Y3(2=EDBA^O!7ZMROYZ85&.;>=#]=N.+2LS"KC59V*G8MX] +M7E-N;[X.@[">[P7'$S##Y+[Z\#]!X8DPGV7!=Q3PEGZ/Y-B+S`V"Y7WU4RH8 +MYTS@A$[A\L^#D)[O.GDS!LIVF97W6L/XGF3_/>Q*T]9;Z]@[/I+S.6`RHYN\ +M4K=^(D(IE)=T-33SG';P5;AJSWSPS-,K"9OJF-[[`1=VTNZ(:1QT(K=@D-/V" +MIJE;Z9WGDWX%<>8W,8+#/YEY;9!8@%]B3Z?Z5Y;ER%`I'<]/+OLQ+S7'FJ]/ +MHR:Y$^P97[WV#&7E;^:7!2@M'3IZC_I9"_GEW2ZUL"2N&95EWKV'O-V)\>ZN +M%Q#5Y+N38K/9W66E.Q+(N>VP"]]!;_)_1#+1X)3H\*WW]K2Z?N5Y0"?UTF(. +M`P;!``#!``"```$"44^A\!DE/`"%P`(WC,$\)C("`PO.OP($N,4%[8,"ZY%O +JB(`%`1)E;&8M3&EN=7@M05)-=CRW#!V][-VM'MJ^^#686N9>>L\.7ZE#3!_/][K2S]G1DR+Z^7F8BN1X0 +M5C;9*7958_V2?B;;=J=N[KHV+"ZA!YHY#/G_C>:Y+\RFMN%A8]94O?OY_AM< +MPE=<8[N7Y/@&A*5GFV:9E;M&8JU!O/TIK!)5X(1%@FPVF'!BV@KI;P1X;E7% +MUF:9HH_W^02_+:F+$Y(@/'B`PID.TWYQE_\RLWU#)O3.[Q($`^A166GIT;W; +MTJ2BC%X%D3X'SO%DLWP[4Y@FL"%R-TR'QED.B&5!.:-0?\(Z*Y>@-Q\DTM%F$NB_) +MR2,7&FYP>)NZC>$5IF2H83OILZ:Z@5?,CH';."Z1XHD*/TW>0;:#%+'H].L@ +M]Y$F)>Z]H[`(+UQGS7TRO#-_QJ!U%RCGU1\95849&LP&15-H7.]MZ[78W*#A +M&G"U:H/3OF)^-H<4X%:Q^/'7#KVGX!=*N0!%4X-1'89S/0E)E,ZW!'')%(R( +MD].ET_+8,B]G5;8>I3T*8I8CH+E&UKAJ]WA;%(A/KO`R^M\ +,"^WWU!UW5E$#!00` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_block_size_is_too_small.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_block_size_is_too_small.rar.uu new file mode 100644 index 0000000..5cad219 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_block_size_is_too_small.rar.uu @@ -0,0 +1,8 @@ +begin 644 test_read_format_rar5_block_size_is_too_small.rar +M4F%R(1H'`0"-[P+2``+'(!P,("`@N`,!`B`@("`@("`@("`@("`@("#_("`@ +M("`@("`@("`@((:Q;2!4-'-^4B`!((WO`M(``O\@$/\@-R`@("`@("`@("`@ +M``X@("`@("`@____("`@("`@(/\@("`@("`@("`@("#_(+6U,2"UM;6UM[CU +M)B`@*(0G(`!.`#D\3R``(/__(,+_````-0#_($&%*/HE=C+N`"```"```"`D +J`)$#("#_("#__P`@__\@_R#_("`@("`@("#_("#__R`@(/__("#__R`" +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_compressed.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_compressed.rar.uu new file mode 100644 index 0000000..f9f811c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_compressed.rar.uu @@ -0,0 +1,13 @@ +begin 644 rar5_compressed.rar +M4F%R(1H'`0#SX8+K"P$%!P`&`0&`@(``B<9?VB8"`POI`@2P":2#`LUPRGR` +M!0$(=&5S="YB:6X*`Q.+5ZQ;^!BM'LKT90$G96!4'U5V7;^4DG')SV6660QP +MV663&,62$X9"223AD)"2220DXY))(0A))"$)))"22$(2$LVU;WM],PZ`?1T# +MKC^>NI_W0?[WVO?=>:\Z7^@`0`$`R""?GX]O7T\O'O[NSKZNGHY^7DX^+AX- +M_=W-K9U];5U-/2T,_-S,K)R,?&Q<3#P;^]O+NYN+>VM;2SLK&OKJVKJJFGI: +M2CHJ&@GYV'9T$&P`\Q!(R">9A6-`NFH9;8 +M-YN'@X!@<@^N81.@IG88#P-MZ'N]AU?0C?Q80(T8,><*'DT)@V+XX.8Z'"($ +?J>&%%CMC0_GQ4(!L(0T(A-(QG)`O)0`==U91`P4$```` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_different_solid_window_size.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_different_solid_window_size.rar.uu new file mode 100644 index 0000000..b131e6f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_different_solid_window_size.rar.uu @@ -0,0 +1,73 @@ +begin 644 test_read_format_rar5_different_solid_window_size.rar +M4F%R(1H'`0"-[P+2``'#M#P\7P$'`0"-[P+2``7#````1H68F`#___\````` +M```0^OKZ^OJ%F)B8F)A)`)@"F-(%87)4`,.T/#Q?`0\"T@`"QP\`"7(A +MFC$!$AHCTBT``B@A4F%2(1H'&.D````!`(WO`M(`!<-%````1A?'#P`)\"T@`"QP\`"7(AFC$! +M$AHCTBT``B@A4F%2(1H'&.D````!`(WO`M(`!<-%````1A?'#P`)7!E/6P*+@HN"BYT+G0@='G^6_]P9\"T@`"TGX!M,-'4CQ2:7`)20`&`````````(WO`M(``0!R(8WO`M(``0!R +M(8WO`M(``0!R(8WO`M(`M`%?C>\"T@`"TGX!M,-'4CQ:!@!I`'`)20`````` +M`(WO`M(``0!R(8WO`M(``0!R(8WO`M(``0!R(8WO`M(`M`%?C>^NT@`"TGX! +MM%)A\"T@`"PP<<@`<`_O__T?___^@@JP#_Q00``B$<`0(`#@`` +M`0``_@C2(`$>____"```_?__$`#_W5A04)#_!&R&;;%DS,RWL0!)`(/__P#_ +M`/\`^?__\&3/)#)(L0!)`#J#+O_______REH%PHHV#!="0"N)$%SF_J;$___ +M_YP#%9,I````_________Q/_____________________________________ +M_RC_____`P````````#_____*/]!04%!0=U891/_9?]0/2[_______\I:!<* +M*-@P70D`KB1!\"T@`````````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_different_window_size.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_different_window_size.rar.uu new file mode 100644 index 0000000..bb4c4a6 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_different_window_size.rar.uu @@ -0,0 +1,675 @@ +begin 600 test_read_format_rar5_different_window_size.rar +M4F%R(1H'`0"-[P+2``'#M#P\7P$'`0"-[P+2``7#`/KZ^OKZA5N8F)B8F)@` +MF`*8T@7"F!=A_________P$$_____________________R%285(A&@?_____ +M_________________V@`[E##M#P\7P$'`0"-[P+2``7"87)26`!W=%)A\"T@`"QP\)`'(A&@\"T@`" +MQP\`"7(AFC`!&B/2+0`"*"%285(A&@<8`0"-[P+2``7#10!A4B$:!Q@!`#)S +M-/_______U)A\"T@`"!QS1T='1T='1T='6T='1T='1T='1T='1 +MT='1T='1T='1T='1T=&UQX`.`"'X"/\E``*H'#`"`/+__TO__O_G*_____\` +M`"\O``#_02+M____`-X`_["&AFVQJ@,#45TW,?;V]@$``/____\3]O;V]O;_ +M_S\``/]!(.VG+R\``/]!(.T)__^PWOS_```O+S$``/8@[;L````````````` +M-3XR9%Q<7%Q<7%Q<7%Q<7%QZ7%PJ7%Q<7"]<7%Q<7%Q<7%Q<7%Q<7%Q<7%Q< +M7#)<7#9<,F1I9V5R=#4V,61I870]+@HN"G0@9&5V270@9&1I9V5S7%Q<7'=E +M9"XR9&EG97)T-38R9&EA=#TN"BX*="!D979)="!D9&EG97-T/2X*+@HN"@HF +M+BX**%)A\"T@`"!QS1T='1T='1T='6T='1T='1T='1T='1T='1 +MT='1T='1T='1T=&UQX`.`"'X"/\E``*H'#`"`/+__TO__O_G*_____\``"\O +M``#_02+M____`-X`_["&AFVQJ@,#45TW,?;V]@$````````3]O;V]O;__S\` +M`/]!(.VG+R\``/]!(.T)__^PWOS_```O+P```/8@[;L`````````````-38R +M9%Q<7%Q<7%Q<7%Q<7%QZ7%PJ7%Q<7"]<7%Q<7%Q<7%Q<7%Q<7%Q<7%Q<7#)< +M7#9<,F1I9V5R=#4V,61I870]+@HN"G0@9&5V270@9&1I9V5S7%Q<7'=E9"XR +M9&EG97)T-38R9&EA=#TN"BX*="!D979)="!D9&EG97-T/2X*+@HN"@HF+E)A +M\"T@`"PP<KJZNKJZNKJZNKJZNKJZNKJ +MZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK#P\/#P\/#P\/#R\-MP\/# +MP\/#P\/#P\/#P\/#P\/#`\"T@`#QP\`"2$:TB,M``(H(5)A4B$:!Q@!`(WO`M(`!0`````````````` +M`````````0``````_____P#_965E965E965E965E965E965E8'-T/2X*+@HN +M"C(P-S`W,&EA='EAEQ<*EQ<7%PO7%Q<7%Q<7%Q<7%Q<7%Q<7%Q<7%PR7%PV7#!D:6=E +M\"T@`%PP`:!P`$9P`` +M````````[P+2``+'#P`)`"X),AP`_0$`%___"0`N"3(<`/T!`!?__Q%287(A +M_Q%287(A&H\Q`"@HW,@```/V-[P+2 +M``+'`"X),1P`_0$`%___$5)A<@$`C>\"T@`%PP`:!P`$9P``````````[P+2 +M``+'#P`)`"X),AP`_0$`%___$5)A\"T@`#QP\`"2$:TB,M``DA +M&M(C+0`"*"%285(A&@<8`0"-[P+2``7#`!H'`/R8__]E965E965E965E965E +M965E965@6%R(0HN"@HF+B8N"B@*+@HN"BY0 +M7B]A,C5I-F1G97-T/2X*+@HN"@HF+BX*"@HF+BX**`HN"BX*+E!<-3,R-C)D +M+W-.="`@6W-T/3TN"BX*+@H*)BXN"B@*+@HN"BY07#4S,C8A(2$A(2$A(2$A +M(2$A(2$A(2$A(2$A(2$A(2$A(2$A(2$A(2$A(2$A(2$A(2$A(2$A(2$A(2$A +M(2$A(2$A(2$A(2$A(2$A(2$A+@H*)BXN+EPV7#)D:6=E\"T@`%```` +M```````````````````!``````#_____```O+P``_T$@[?___[#>`/\`AH:Q +M;?;V]@.J_O;_S_\`Q+[?$?;?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?___?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W_^[XP## +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````#_________ +M__________________________________________\````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````"`````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````+8````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````!287(A&@\"T@`%PF%R4E@`=W1287(A&@EFZ>45J>E"(8*1QP&#AP1O__`````!X````````````` +MNKJZNKJZN@'U``"R____`````!X```"````````````````````````````` +M`"Q!`````````"T`%0``:#H`6@$M\"T@`"PP<< +MP@2```#_;24``F<<`0(`#@```0!02P@#`"8F)@!`___/0T+_____\?__K2-T +M='3_______[______R9"____,3,U__\3$Q,3$Q,3$Q,3$Q,3$Q,3$Q,3$Q,3 +M$Q,3$Q,3$Q,3$Q,3$Q,3$Q,3$R8J8BQB`/______0D)"0D)"0D)"0D)"0D)" +M0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D+;V]O;V]O;V]O;V]O;-C8V +M-C8V&4PA`C8V-C8V-C8V-C8V-C8V&4PA`C8V-C8V-C8V-C8V-C8H*"@H*"@H +M*"@H*"@H(1H'`0"-[P(H*"@H*"@V-C8V-C8V-C8V-I8V-C8V-C8V-MO;VP`` +M````````````````````````````V]O;V]L`VP````#;V]L`VR@H*"@H*#8V +M-C8V-C8V-C8VEC8V-C8V-C8VV]O;``````````````````````````````#; +MV]O;VP#;`````-O;VP#;``````````````````````!"0D)"0D)"0D)S0D)" +M0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0EU=75)A4B$:!V%R0D)"0D)"0D)" +M0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0MO;V]O;V]O; +MV]O;V]LV-C8V-C893"$"-C8V-C8V-C8V-C8V-C893"$"-C8V-C8V-C8V-C8V +M-B@H*"@H*"@H*"@H*"@A&@\" +M*"@H*"@H-C8V-C8V-C8V-C:6-C8V-C8V-C;;V]L````````````````````` +M`````````-O;V]O;`-L`````V]O;`-L``````````````````````$)"0D)" +M0D)"0G-"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"75U=4F%2(1H'87)" +M0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)" +MV]O;V]O;V]O;V]O;VS8V-C8V-AE,(0(V-C8V-C8V-C8V-C8V-AE,(0(V-C8V +M-C8V-C8V-C8V*"@H*"@H*"@H*"@H*"$:!P$`C>\"*"@H*"@H-C8V-C8V-C8V +M-C:6-C8V-C8V-C;;V]L``````````````````````````````-O;V]O;`-L` +M````V]O;`-LH*"@H*"@V-C8V-C8V-C8V-I8V-C8V-C8V-MO;VP`````````` +M````````````````````V]O;V]L`VP````#;V]L`VP`````````````````` +M````0D)"0D)"0D)"\"T@`%PT4```!&%<\"T@`%PF%R4E@`=W1287(A&@7EY0H```#EY>7EY>7EY>7EY>7EY>7EY>7EY>7E +MY>7EY>7EY>5W=V%R(2\O+R`N"@H*75U=75U9R,C(R,C(R,C(R,C(R"<.`'\` +M``I=70!=!UU=7=D`Y>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7E +MY>7EY>7EY>7EY>7EY>7EY>7EY4$X.#@X]C@X+3@X.#@X.#@X.#@X.#@X.#@X +M.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#AR.#@X.#@X.#@X.#@X.#@X.#@X +M.#@X./DX.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X\"T@`%P_J%6YB8F)B8F`"8`IC2!<*8%V'_ +M________`03_____________________(5)A4B$:!___________________ +M____:`#N4,.T/#Q?`0\"T@`" +MQP\)`'(A&@\"T@`"QP\`"7(AFC`! +M&B/2+0`"*"%285(A&@<8`0"-[P+2``7#15\!!P$`C>\"T@`%PF%R4E@`=W12 +M87(A&@\"T@`%PP```$85!<)A +M\"T@`%PT4```!&%<\"T@`%PF%R4E@` +M=W1287(A&@`````````````+JZNKJZNKH!]0``LO___P`````>```` +M@``````````````````````````````L00`````````M`!4``&@Z`%H!+7-L +M-S8`R!$`````````XJ$`8VDP`#(`93$``/_______________P`````````` +M``H*"@H```!=75U=75U=75U=75U=75T````````````````````````````` +M``````!287(A&@7E"@```.7EY>7EY>7EY>7EY>7EY>7EY>7E +MY>7EY>7EY>7EY7=W87(A+R\O("X*"@I=75U=75G(R,C(R,C(R,C(R,C()PX` +M?P``"EU=`%T'75U=V0#EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7E +MY>7EY>7EY>7EY>7EY>7EY>7EY>7E03@X.#CV.#@M.#@X.#@X.#@X.#@X.#@X +M.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.'(X.#@X.#@X.#@X.#@X.#@X +M.#@X.#@X^3@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#AR.#@X=_[_________ +M&4PA`C8V-C8V-C8V-C8V-C8R&4PA`C8V-C8V-C8V-C8V-C8V-C8V-C8V"#8V +M-C:6-C8V-C8V-C;;V]O;V]O;V__;V]O;V]O;V]O;V]O;V]O;VS8V-C8V-C8V +M-C8V-C8V-@@V-C8VEC8V-C8V-C8VV]O;V]O;V]O;V]O;V]O;V]O;V]O;V]O; +MV]LV-C8V-C;;V]O;V]O;V]O;VUU=75U=75U=75U=75U=75U=75U=V]O;V]O; +MV]LV-C8V-C8V&4PA`C8V-C8V-C8V-MO;V]O;V]O;V]O;V]O;V]O;V]O;V]O; +MV]O;-C8V-C8V-AE,(0(V-C8V-C8V-C8V-C8V-AE,(0(V-C8V-C8V-C8V-C8V +M-C8V-C8V-C8V-C:6-C8V-C8V-C;;V]O;V]O;V]O;V]O;V]O;V]O;V]O;V]O; +MV]O;V]O;V]O;V]O;V]O;V]O;V]O;V]M"0D)"```````````````````````` +M``````````````````````````````````````````````````!"0D)"0D)" +M0D)S0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0EU=75)A4B$:!V%R0D)" +M0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0MO; +MV]O;V]O;V]O;V]LV-C8V-C893"$"-C8V-C8V-C8V-C8V-C893"$"-C8V-C8V +M-C8V-C8V-B@H*"@H*"@H*"@H*"@A&@\"*"@H*"@H-C8V-C8V-C8V-C:6-C8V-C8V +M-C;;V]L``````````````````````````````-O;V]O;`-L`````V]O;`-O_ +M____________________________________________________________ +M_____________________R8@)B8?)B8F)B8F)B8F)B8F)R8F```````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````/8``)0X.#@X73@X..7EY>4*```` +MY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7E=W=A7EY>7EY>7E +MY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>5!.#@X +M./8X."TX.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X +M.#@X\"*"@H*"@H-C8V-C8V-C8V-C:6-C8V-C8V-C;;V]L````````````````` +M`````````````-O;V]O;`-L`````V]O;`-L``````````````````````$)" +M0D)"0D)"0G-"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"75U=4F%2(1H' +M87)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)" +M0D)"V]O;V]O;V]O;V]O;VS8V-C8V-AE,(0(V-C8V-C8V-C8V-C8V-AE,(0(V +M-C8V-C8V-C8V-C8V*"@H*"@H*"@H*"@H*"$:!P$`C>\"*"@H*"@H-C8V-C8V +M-C8V-C:6-C8V-C8V-C;;V]L``````````````````````````````-O;V]O; +M`-L`````V]O;`-LH*"@H*"@V-C8V-C8V-C8V-I8V-C8V-C8V-MO;VP`````` +M````````````````````````V]O;V]L`VP````#;V]L`VP`````````````` +M````````0D)"0D)"0D)"\"*"@H*"@H-C8V-C8V-C8V-C:6-C8V-C8V-C;;V]L````` +M`````````````````````````-O;V]O;`-L`````V]O;`-L"-C8V-C8V-C8V +M-C8V-B@H*"@H*"@H*"@H*"@A&@\"*"@H*"@H-C8V-C8V-C8V-C:6-C8V-C8V-C;; +MV]L``````````````````````````````-O;V]O;`-L`````V]O;`-O_____ +M____________________________________________________________ +M_________________R8@)B8?)B8F)B8F)B8F)B8F)R8F```````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````/8``)0X.#@X73@X..7EY>4*````Y>7E +MY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7E=W=A7EY>7EY>7EY>7E +MY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>5!.#@X./8X +M."TX.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X +M\" +M*"@H*"@H-C8V-C8V-C8V-C:6-C8V-C8V-C;;V]L````````````````````` +M`````````-O;V]O;`-L`````V]O;`-L``````````````````````$)"0D)" +M0D)"0G-"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"75U=4F%2(1H'87)" +M0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)" +MV]O;V]O;V]O;V]O;VS8V-C8V-AE,(0(V-C8V-C8V-C8V-C8V-AE,(0(V-C8V +M-C8V-C8V-C8V*"@H*"@H*"@H*"@H*"$:!P$`C>\"*"@H*"@H-C8V-C8V-C8V +M-C:6-C8V-C8V-C;;V]L``````````````````````````````-O;V]O;`-L` +M````V]O;`-LH*"@H*"@V-C8V-C8V-C8V-I8V-C8V-C8V-MO;VP`````````` +M````````````````````V]O;V]L`VP````#;V]L`VP`````````````````` +M````0D)"0D)"0D)"\"*"@H*"@H-C8V-C8V-C8V-C:6-C8V-C8V-C;;V]L````````` +@`````````````````````-O;V]O;`-L`````V]O;`-L` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_different_winsize_on_merge.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_different_winsize_on_merge.rar.uu new file mode 100644 index 0000000..85391fa --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_different_winsize_on_merge.rar.uu @@ -0,0 +1,16 @@ +begin 644 test_read_format_rar5_different_winsize_on_merge.rar.uu +M4F%R(1H'`0"-[P+2``+''QP,!`H``"0`N)$#`0(H$"<"``X`/3Q/`0"V```` +MQ@$````V`/^%02`H^B7&,NX``"F&AK%M-50O\"T@`"_[6U,1"U +MM;6UM[BU45)AXM5%287*U +MM;6UM;2UM0``//_____W______________\`!F$`C>\"TM(``](?________ +M`+3#6@0&D0,!`B@0)P(`#@`]/$\!`+8```#&`0```#8`_X5!("CZ)<8R[@`` +M*8:&L6TU5"]S?E(````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````!0?*``P$(8FEN +M+S)T;S/%R58E54(_=00]^44QFE=*A'1*>B"DP(_`YD!;_"1"2H/>.\JSNCIR +MJ-=&]E9KQFVN#YI-S-P&5:6-!8((VI)'0OV.CF2X\:/J9V`>ID+B:L^4G\B- +,X$E:P!UW5E$#!00` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_fileattr.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_fileattr.rar.uu new file mode 100644 index 0000000..456b025 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_fileattr.rar.uu @@ -0,0 +1,13 @@ +begin 640 test_read_format_rar5_fileattr.rar +M4F%R(1H'`0#SX8+K"P$%!P`&`0&`@(``-$;*1"@"`PN+``2+`"&+W8Z;@``` +M#')E861O;FQY+G1X=`H#`J*C5`BE!M4!,3(S-#4V-S@@#0JYZ,#-)@(#"XL` +M!(L`(F^$/86````*:&ED9&5N+G1X=`H#`G(Q.0^E!M4!,C,T-38W.#D@#0H> +M%_EV)@(#"XL`!(L`)"V,TBB````*$42*0(#"XL`!(L`(RZ?$!V````-0H#`HS,%ABE!M4!Q!O^+"0"`PL`!0`2`````(````ID:7)?:&ED +M9&5N"@,">JRV&:4&U0'&L*8=)`(#"P`%`!0`````@```"F1I7-T96T* +M`P(@+D4;I0;5`2YJ1$0F`@,+``4`$P````"````,9&ER7W)O:&ED9&5N"@," +0CW7S@JT&U0$==U91`P4$```` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_hardlink.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_hardlink.rar.uu new file mode 100644 index 0000000..0ec085d --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_hardlink.rar.uu @@ -0,0 +1,6 @@ +begin 644 test_read_format_rar5_hardlink.rar +M4F%R(1H'`0`SDK7E"@$%!@`%`0&`@`!KI,1X'@("A0`&A0"D@P(XC;=<(1>3 +M?8```0AF:6QE+G1X=#$R,S0*[8@"T2X"`PT`!@6D@P(XC;=<`````(```0QH +@87)D;&EN:RYT>'0,!00`"&9I;&4N='AT'7=640,%!``` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_invalid_dict_reference.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_invalid_dict_reference.rar.uu new file mode 100644 index 0000000..9b78c9b --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_invalid_dict_reference.rar.uu @@ -0,0 +1,9 @@ +begin 644 test_read_format_rar5_invalid_dict_reference.rar +M4F%R(1H'`0"-[P+2``+#!QR`!P`F^P#_^_O[^_O[^R4``B$<`0(`#@```0`` +M`"#2````_____QH(`/__^P#_W5)04(#_`(:&;;%DS+?,L0```````````+%D +MS+*RLK*R/@``____Y`"R````XP```````!4``````.X````````````````` +M%52$A(2$A(2$A(2$A(2$A(2$Q(2$A(2$A(2$A(2)]( +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_leftshift1.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_leftshift1.rar.uu new file mode 100644 index 0000000..694a27f --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_leftshift1.rar.uu @@ -0,0 +1,9 @@ +begin 644 test_read_format_rar5_leftshift1.rar +M4F%R(1H'`0"-[P+2``(''(`'`"``_R4``B$<`0(`#@```0```"#2````____ +M_P`(`/__^P#_W0`"(8#_`(:&;;%DS+?,L=:NL0#(3`$````````````````` +M``"``````````+!DS+*RL[*RL@```-P``````````````````(`````````` +ML&3,LK*RLK*R````W`````#X____````````````````````````%5H>;&@T +M+3HW"2!SB^)_@`````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_leftshift2.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_leftshift2.rar.uu new file mode 100644 index 0000000..57ffad7 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_leftshift2.rar.uu @@ -0,0 +1,6 @@ +begin 644 test_read_format_rar5_leftshift2.rar +M4F%R(1H'`0"-[P+2``(''(`'`2``_RL``B'+`0(`,O__````-WJ\KR<<)0`" +M(;<*`BY*`!```&;%T#%24%"`_R4`[@K+(2Y*`&$``'__`/\E``(N2@`0`0(` +0(?__`%N&?Q2UH.CHZ.CHZ``` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_multiarchive.part01.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_multiarchive.part01.rar.uu new file mode 100644 index 0000000..a83c78c --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_multiarchive.part01.rar.uu @@ -0,0 +1,345 @@ +begin 644 rar5_multiarchive.part01.rar +M4F%R(1H'`0!5`$'/#`$%"`$'`0'O]H"``.>[Y2I7`A,+@O8`!.#I".V#`FI) +M!96`%0$W:&]M92]A;G1E:R]T96UP+V)U:6QD+W5NKN2Y+ +MN8P3!#"EF%)(!"&"&:0"!($@0P01"!)"8"0)A)+N$!,$"$4C&#'`*<45'BIP +M5.+'`*(@,!.`.."BL5%)QX<>08*SBBL5$GS>MW-;WNJNZJY@!>^?//GG77?7 +MGI\[ZZ[]5A=UNM[UCWK>MX*P2J_%=?0O]_ZUO>L%56ZIDA[W\`_Z`!``=?]( +M`#H`("__2`"Z`=*_Z@```D`&1?91$7EUZYX` +MX9+&)/)OV_)7U)V*.JL'M&V77AABX,Z8OO5)^SZ7E(,+@JV5M?*G"-L)/S:C +M`%"!HN=_VX8+9!OJ@TVS6XH,%L9C=5^R@<]KK.\:[*!\:N6BZ\-59*LC;=A9 +MZ+M1I[J&N.0O3+)!A1H<;_EI*(&_\GW;/L[QT##<7SH!TGZV^/Q=9Y0WVRQ> +M&42]OM4KWPLS,:?%8G"S,IA!D3;6APE#C,5A!WX.?G(/#H1-^4"\QFXY)1U] +M0A(I[DI-E62ZZJ@MALY7<=QYUAS\W6LO;@O+]_NI(#-J$=X`\3(/$.+7&42Z +MXHE="O7N9=?"/V6DMG9K]89"";A)FQ$ +M/CKE?!)<1<;B(E?U^IJHVX7$4%=6+"`2A!0EX8W*$$G:##7'9PT-MK-N>-!5 +M#O+[_?-M(I8098IJP7/2$Z.A^<49N;[H"'5W0E.Q4G]$!V2IL^CZI4/I`-*3 +M3-C3A64;:EBFH)+AK4@3))QMJ=*:LC0E"37*R'KP-@39$HB&8IM"E'9ZVH': +M$[5S1/;-M=L!3$VY*@G=D[PFX)WQ-R77?@>`77@@>$I+\0#Q@UO`-Z3R%-_R +M0/*O3\[V/9C/CH.SLO?V>9HM2]8[OGG!9:IA8AV +M_;]9+0M:ZI^:<5I><#Z^TKM8_[;/P?R] +MGB[SI/6\[GQ^0R%\GM_ +MX\*OP\KW-TXKOC(^[=]8:GNIWE[^Z9Y?H0KSBO8]3SL1I_E^O^5 +M?]O[=,GB^'"ZOV\SJ>__KFO\57QZO17GU/Q@_TUG:"C^9Z4SJI_CN +MM?_*1@9R@]'VOCO=YHF7YTVAT'DF%Q.@D_Q.YH.Q^?QNUVO+WOT_A"4'L\&[ +M_7,37F;C:_Z_:=_#IYKX_2T'Z3.+P_#]1]H(&]=O>;_G_JW^EYPG^YWWY+U, +M\*7X?KB(O'U["2_EJ665^%ZCL5DWNMW62?)/.XS*=G\+*E[:%?=Y3\WL,Q&\ +MEIH]Y]N&>4O?D-5LN_U_X9ZDR[I-;W"W'M>A-;)AGFFJ]/QY_T=],U/WQHEO +M>4EV^_P<#&.G70';8RMS'3]_V]KB9^V7WZ@8`EQM$XF]G:T_W>^Y=V\'"=IQ +M.O]AVA/AG-UWM\\C;8=Z\GS<7QH+;?*^QCY?_JB/TWV/VFD@_]W'@06MD_\] +M*]]G=/@OT^3RKGW]^_9=C-_]>Y@Z:[^+Y +M7X^+ZK&%UFPZ$MINY^/YDM/3X>/]3N/CU5_J_\T;SQ]CN\F[4W1PK_WW?M)? +M6=#Z.7[GR\;_.B@-%Z^+R^>X_@]M_G;^II>V]VX>[K/;%='K6P/J^++\[.9^ +M"Q#6"LEQ_\4L@U9?LPLC?CHN3W3;%W47]1/[^CJ81$@?L/X,XDZF%1`S!IO^,FR +M=.G9.PTHS8F`2$N-OB:1`G0Y4,,#2#%Q,8>IU%Z7_\G\^PJ^Y\#WMT"/16#\ +MY`RZR"B_J*2%R5DY#(NGK*=N,'^N)]P25R7_N?S[RGXO`0WVK9?X#C-[._4_ +M(\Q^"R=/N-M)B[BE_!+_W/Y&O41%?#F/5D:9?W:_19Y*!TW](?TJ3$4<5H-= +M.=K$XCL<1A/.OL/H^#:9SE?MU_:\'[OB^G(_W +M?-/X_L:KSLIC=%%7;P];A^;>GSQV4G'Q^0_+_%+G?#R-7_R4JVGK:"LV'>=? +M=K&RN&V\?>^9H<)Z=]O=+G/O[#&_%V\&E='CX,?^,5HETQ^OO]?]G&=HE_\/_/2P=^]7'^5 +M]'C,EX%W +MVDH[8MBZZCG^IVL_(#\TY[B4 +M/W\7SNNX.H'U[F=TAU0>2DYDVI\89*0BM!&2$I*STK +MJ)B?:#L'JD).7'[+20E0\Z,L432FM5*3`_HEP1)Z;G)`Z5B2A7XX))B(%)2<%$Q*1 +MT81-F5>6%>)P2`EK).?.`S3@SF&3$>3$R"L\AISDE(R$">Z`Y$,74A*PT8K% +M/B@8SDT=6Y0=:LU1QB;.,F:F*`'$I/6"HN$7$)!`D9[M4`R[0"&SX"=AB6M"/Z>8'<$0]MRU*I9]15)"*SB*DI!J-/*+5-G9F2M-5)TP-/"LIAT0N0$'$N3D\-L5 +M#K,Y.K2#,Z[$HW]8($>%O:$H<5&0BNQ>-BYI:#O/FM8+'G7(H23F;:J%4>]54YK +MA`7!6LT>UUFW$G1BV^T,*&$6+`M.,ZFY9:\":?6->USD2%KJ!GK9641.3W0T^N;?PK[/^/_A$U)QM-P"MF4C;_M!QD(__UT\9@-&Z +MI4"KCZ_>=SWKLV:S;EL4YNY3$P]MF$#YJF_UP.Z)?2&FMWF&1FAV"A/4X_^Q +M+J=A2QRG.?9AJ)N(8;[\:7."]BSB1+F63QS$N7,=[010AE3'_T15Y814AG6AJJ#/C^8H+ESVH:K`SM*D(K0SWP:L`S@4\FA8ES_ +M,-,>N#"F3O?G.?\]MIF&?2#4`&>*&L8&?`\\(A@SRPU&AG9>@$:(,UH:EPS) +M[\(G0S8!JB#*F8GVQ8&MV&;D&JD,\#TE-IB3I'LE"17QHZB+5])MB/Q +M*@EP)N2*N1U]V6O7$WI+F2I)="<`EU)5$?RRA?H-/66`YYOU]O<,:2??-S@[T+S")%/D!+@I[P)>%/8!.@4XP)U"G! +M!,`IYP)V"GD@G<*?S!,0IWX)D%.Z!/`4[8$\A3:`GH*:X$]A2>!/@4U()]"F +MG!/P4T8*X!3/`KB%,R"ZX*90%<@IC@5S"F'!70*00*ZA2^@G\*7<%=@I<05W +M"CP"O`47@KR%/T^<"]!3[@77A3Z@5["GT`F84^0%?`I[P*^A3V`5^"G&!7\* +M<$%@`IYP+L`IY(+`A3^8*`"G?@H$*=T"@@IVP+!!3:`L&%-<"P@4G@4&%-2" +MPH4TX)L%WHP6&"F>!8<*9D%B`IE`6)"F.!0H4PX+%!2"!8L*7T%C`I=P6-"E +MQ!8X*/`+'A1>"R`4_3Y@,B%/N!9(*?4"R84^@%#!3Y`4.%/>!90*>P"RH4XP +M++!LT'_#?7%4O+TT32_1$T?/L(W01=.PWG:V;1-.]X5&S([<8-UE<[[\K9NE +M4&WNR-"G$#-9GB<;8M+F,+K\?D"&5E6OM['H'I+UE-I@^!!X6^@H'J1/%ZCH +M)JL!V5V3B5W(B>7U&ER,0/\AIB#2PC.65#YT?HLC>C#:37$1PI!D>,8)$*I? +M\M'L1;(NWS'1FI--5V^&M+D,.D+7%VE]:6@Q'MJD?X,I5+-$_.3^AS3!<<8A +MC%XA!V;"L'ZUJ^3$5W;BX*V;HH3:FB#3L18&VU9+$E@^^BED-,U>C`*X%1C, +MKF\]'M7=&_7QK;<$UB*]@M`X)I8*@Y;1/O$$QTQ*7X1-/)KM>+Y2#C1["Q2: +M0J8$_'IS!.,XS7L%!3:U35D9,X<7J:_KDR:/Y8KNAP3*)45ZZH$>Z)'H?VN$ +MO=Y5"'U5>Z"+UWK^LHNT,"%=>8.R.Y0_8RJL]B'\I)KA:^]%;HQ.YB:>Y4C= +MAB[C&FZ5?1F7TTC'Q',U_RCMYG0V>,13\HZK85]V^'7*M[&OO<7X-&:4)BYX +M*OO]-'<^EJ^+6KUU6NJAG^>W8)54=="+C;ZMFF%V+R&\;L>0J7IC9L)$%3Z] +MJWI<(UD5@P8">3(\)17'!\<"R-\0N%'L!4JA?A +M:>+!M@="L>#;&$54YIFGC1/(K.)NZ-/F1D1G1B9/WHFG>MPAIL +MKYU1C4@::$)%W`?^*/%8?T4I&Q7QC(*C=IH9BAXN.L4-4.Y@U&O`;'-[&I5! +MTM6KCG@N>!SP7\CN-L#"%>P0FC=Q9G2C0^J<9KMT,4$37TQ`^F8Q'W#2?RJ[ +M\(DX"V]CF4$S.N`@$D/;884IIXRM&9&>'Z[6;:$R8KA_^='!OY=^';#OU,P[ +MKY4)?=QMZWOY3L.,%1AB3[AU-W0QJ34+4$H"S`*GCJT,U!K"8GO$!`J=71XV +M.5$=V?1K4(?PX`RNCLW^B!]Q(DIY<"+I:2=!Z>A`VK9F;[`Q%$/V,J"1V[)I +M:DDK5$FJLC6M)L+!6LU)$F$Q6GDTD(;:;"%#)Q($(>DIX@RSTF,.::>DC4'" +MDAD;NXA`5-2)HF>KOS,8A1T$__RU*B:-!?2:O<3R6#U]2,4W7Z+_TUAY`Q^^ +M'\8,*FFK3IV'F_&EXE.&!6*YK@K5!* +M%,@FIGWPC1ZA-4&8-K[F(J\!#[X:<]=0$5I/X?2FW%_C +MBO-_6OJF"8H,"AM3_I%M3$@>,:6>-.T&[08=Z>A07KH&.2PUG^D/&""9'XD, +M">!G,S\01U1T>CZ)E6V%B."?^$\'/``>R:4,YQ>";#P\1#_4+PGZA;&?J#G#2M3OZ='#'V(B)GLRBK^ +M?^DKY:S7)80X!_E-"YKZ44V0!"14Q?EC)N?W;,X?R4-SE!L7"!UGP$->PL$FL&-PO74RD`0Z4:$.AJ*M.)Z`<9X-]/:3&.#;KK27#;M<>7S/ +M]BDM)5-7?@'46OPUI-O[4091>+'-:)M9>#-S:94JTE8/V,J[8/./&D:O"#GT +M-D./#&[2&[\CJU0]15+RDS[3!T&]0'!61AOL<05W$)L$6+YDH6H@U8>\F*U8 +M!5A,0&=@_6E2A48R?M1:B@:KI&'3Q"%8D9,4DB0&50W0V$Q&"<*7FQ42RD,S +MT7*+GR>[-;<=7X<*NC`AFG<:*\SZ>%".%%;IKVF0/^[)Y`7-+OT%R<\Z--:` +MZONU=A9,B<,5J.MV1\(/74HX7;IN$)%'JIP!^1-D,FBLRF&>+6NPT +M;N1`\K$!*.395?\(IJ`:_JYW>GWTJHU;@AG&,4+B#>]Q?H=MG]%4^D9<9R(J +M:&1'2V>PZ5D9*WWM?]V8J)QJA736*R__QDG4`W3JZEW$=`@O-H:&98QG[!TM +M*G';FL69T#LL@;67!!EK\"GL9FR6R*)^2H'<(>C5/C9*/5%I5+.<:`-BEK54 +ML=PJ6,X#GB@#8RX^6[CN4,KA'?_E-@%Z/8"M36Z&G^R"_0X<0BZYXOM)A3W +M]&1T[E3FB[M'PP,,#/DUV0&-LGD'D$R,"XA8RWW:CTX?R8CFGG4Q:(3;XF/& +MWZXPRSS"`+'B'-+@:D=@N.2O0;/N[-RG>>,$!<(JG(@1*M&)T7(B%1@U* +MQ"F06V8Q4AS*)LL]LOY&(U2&>:@N;H+G#-:_GC.(I:4+FF.V#IJ]L`Y33`'BXM(`^>):7QL,H2F_G +MS,;6L;BL$:`0WG>4W'"JUKDM%\(BY/;M9RJUFXOAHM!XM;/]#F9@K_VUH7W^ +M83A6T\:ZE*VF.FHW$Y[!G3)TR>`M%Z_1;,:4UJA4`;`,8L%9!;RPQ=&\_X(7 +M.A@H)2#9-E0BD6TW_KX!_Q8D[)*Y)1Q/KT[]6N3<,BX0'3P86EMG`EY.A#JC +M`AJ$;V\NB:3KJ+6UJUX93/ZJ:1RA&SUC]K0A?TLR!R8BP/,]#R,RB!$C0S%U +M6=J&F6B'(B*]F8/L0>JBD+Y5I-,.9&[`EB.AD(T,^K/IA\8I.<5";KC:3CC. +M,T=3$60M81-&Q']JR#3H/?^M8%OX)J:@F9]-S,.V+[K,6%!!,:.F!=KCSW:K +M@Y=F%W(=H/C<`WR4`648C7QUM*K2Q'1'1S[WL1L#]'8[(G1!^[6D:O-%KLEL +MTK3JX!G6=V:'NU)1%%GW*%FS/26FVM;-80LBVPOYHK($P#JH_FBV*S[$[<]?>D]2^-.OG@*0O=&9R,28917]95WZ\/2IY9#5-+35]7'8[JV +MG62Q[/HU:,^;$@4N_RQ\X!N#9U1RQ'U-N$4=-2("%2Q4^XD4Y\XFI&"X0)ID +MQG4$FFWZL:33;[Y^W\R/T(7.'TB.H.(N'X$YVVBIY8=%"`=AWDK:\AF-\&%% +M`IX7Q4R+7=N;0.*6DC3SM'PS[$FMZ;@R"EKPO7M5#=P1Y=IM^K&FT,9X/2 +MOS(O-U!JY+=(D`'LP.Y!;Z^QK$'Y7Y`N/^0/P$;*>I`M#!$`160'EH,P@3IX +M7L]6LGL/U5I$KNLF/0O>=1PY+JA6IJ=54.+A.$G3)=[CG;F/ +M4F>TI?)URMK5+BBN07ZWL<=8:9W-Y]-INOQ"%=MK30/"G`^O5SE_<,-`\X=R$W%=ZMKB#":8BGQ`96[;=#D0^78A%'J4'F,3 +M2L4HQ0%H=64P5.(FPL;B$VQ@AWUY-F:4;8^YLR(G/1\P'8^FKC75^.,0&`74 +M&JLB::BF-ICU.&6+4^M&"BY5*UXX'`)4TT=QSDQ95C4@>/-!Y")-0:*#G1&H;\X$ +M%]0H'CP*=\+H>.3;JO7*J!K?"6HZ29B)60T.GN<=,E[D\5ET-47`KWL8T-M> +M!:'/%0Q93)=/$;L7H,EJE3O'?4B" +MG6(SHV04"16\Q!I*%O@%7S5!Z=#8:5"&5((W).]2N.U)3@VE,?A5!N01#<." +M:_,AN$16GT89]VOM)(T-$_(.+=]JJ1JE,731CA#Q0S<:FT5[K&N50;/!Q5MH +MVCRWE/#5W!#:)HM@(4U?C[B+$9FB[UY1([=H)Z,Y1/?U%D`FA +M]VOKH9_O1?#]4W#RQ7-#0*L"K#IH)@/W'OR'"KY)4FE[,_XX8L8_KN,B'DO, +MG_`7)RT0SS0)!U57E6A4_-4JAZ'=Z1.TRJ*%4W;(*Z@KR@2S4\(ZV4%38W:U+R4DK9.2=#7W6H48B(#CXC>ONTR1M&N75#A +MUT9VM)T^H1N]E?[:8:T=1%MRN6C<][RC'$"]I0PW*37$C^[H_ +M%!W#@;DXW5K8SI750/XC;(@>?K+!EPITN'")MFB/&CY,LKBZ]4J;6,2VX3F0 +MX05LT2#WJ@PL9QOEED;J[-DR_I:X<8=>0M$[/CFN"=)I5>KB*]?'3+O&&.9J +MY5.UXLCG'Y>]/@=*Q/7F2Q$2H>OP:8UR-TD2_&`I@:)W-K6-+%3-,8D_(JO9 +M6P%,5:!M],+R]N(-:+QVOA:.S9=;!H#[OJ6IFC4`160'EI3[BK3GTQI%!VXYY*EI/:LRCX9_U(^C$'`*;?J +MR*VA\DP]63C8?N\MB;@+Y@RM691D5`^+3*\IOC',!;N*9WJC(?X!R:A[.P?13E;?&60+ +M$V0/`61&=D0>4?\L)7VQN4WK0ZH@2IJ3&6QH\\`%&T9:R!'_2P<`IM^K(K:) +MSJE=O0]`RP/O$0B='8Z=I?Q_)II<2237`HP%I])AK\N>&"IN8V)Y*)!W+<&( +MXCE6!A(G&H0?7O[B;JEP:?=O^1S(I/X)LXD#BBEB#7%IZ9Q +M:K-J/HL<[&"$M]76E)(.E'QWZU6BJ:<;CZ0U>!L-0A83;YUS::D3W3H91PR\ +MK+?G#1_68.<@15+^<.H\<[VJAC/]]IP%K\/S'AI]8YV*#(AJ4H?TS'5(4&/8 +MWO,DA@-KV:W,:7!$.A%SY/&UR%^]0W3A^C3A[CKPJ019`Z+9)[2U/#6K:XRS +MC5B"]V,#H9Y!&-HP%DN/,1Y[9.B!-;G3(WL>;F-M2$Y%TW#;*FIX]#F^,L@2 +ML[PZIR&]2%OV\/^2XM-!^B:_\^HA#=X\'NB>6@QJQO$8/`(CSJ&_VPWEO<5> +MSI2_GMQ:QN/H3_A+8C7QAU]Q#P`KOH`>ZJ1(,V#<-$*NGT5LKS%!7 +M\X\/\/_/KE:9.UE(34+L@]>ATASB2=K9(;^L9^&2M\H7H/E1G=82?=L;^)L) +MP%'T#C4QWB,;QFD_;AB]C2!E,4/DA./I`LL+1Z7@!?]] +MQV(>NIU0?NIM&'#-Z,.64L[E_"DO/SO:?)47((8]0'2#NN00_ATA`AB'2_@] +M_"6(.K(I8W?9!ZO(QW19EU&]6N[`>%5&/#4CI>DIA\43=/3U2I%N#@URG(5W +M11Q9"`/2B,0`+6Y"W$=O`>HZ>K3[A0U')BFMR[@Z)#PQ^J<,5C\.GDENLZH. +MLLCO1:I7DZI,^INM,%;.1^U&B#-??;1PE33Z+^!E%2M86CA91^38D'6SF#Q`/>C\!`6JM],H8VVQPO7Y.Q#_BIH8A6K9,E0C_2$*Z26MM.ARRO58$_4'AU(BE:;11EB +M]-(:TDJ##@/2"@C/3PRPJ&YDV?=J/\KQ&3S!1NXK-3P&UQ7LAF.9$[EOTZ.+ +M`!T-JE]PY*-8*QHT#3,*BU:40J="'VK\`JF$/`*B39M]?2LK(]:7KVSI,EHJ +M86\O2]$[,S]3NGYD,24?XCQ-Z!LR7W0EIX-+61(/UVAF)'ZR!V-D1*TWQHYWAB&C1;$"L0_&C)61!YG*?AV=>:8?@>Y&DL0=.-;W< +M^KONW\.F0!\@"UIKD0X!3;]7TM*V7PYT/5!F;HK<0AY3T(8\XX2"YD/3;T!^ +M3-B0.C/"4T8*Q<'W?RS_^/'\#CBXKRHG\OJB>+^CN>3Q;$4F@>,5JMQH,#\X +MZ@SIJ#U>Z`W5BMB'_"SQP\Z'Q/PW+0FO)XCHCB;1X;X)OV% +M<.R(JE;!7/2B==G0^%?)'+;0):A]="'RZPP@*MWG_FNXY^-#UU6LMZKL]6.( +MM)6>0]:^9%I-'RH8>2ZU"XO!H8/IAP]GUPZCU=KJSH+.F/R1Z:YO1*L:]X1V +M%FFC\Z;FZ&>/V`?@VG/M7L%C[C>5*#RRH8FHY&7E6MV4WEX*@:H+3H"=&XE) +M*B]IVET#)9/.!M_QQ0R1B;>^-@'D:06("]Y``<.7B#.+"'XL +M"NY^2,Q9N0NGFPNH:F;[WBTC8L(A26&;#;ACYV@CU/(_%B.L32JA8^0;I<%R +M?%<^D/CX;ZS7ON$8I-J9Q+F`W,2:7A4`?0'0SEJJF^]:K!QQS5-@$9PEY#9N +M->&!%#>8C)[]")B +M68\(B@7IYE&MJCAA[@ITO4.+WZ&FV"#DFE:ZK4384NP1MX_*2=9:KA.$C`>3 +M"/IBW#J%89^QP1AY4;*A[#CTZG29^SUBMWNQC+2L:BOW.Z`9[4KS*\ZD'8P7 +MYM!^]*,36+4DEHL*J(&O"J\'<'#DAT,!V+RY6,N6FL,V1U"I=>G;B;6$8">0 +M/:C`?WXPB0:U81YF:#L>0J\VPSJO?[:;.>6.50SK>K=IS&\K"-/7)A6G$)!M +M//KH\W&2J9^4FA8(?LD,^^D,OTJJCK6(N:;=0LONX6,D>`C9$YV9#=FWZQ;F +MQT_+4]O)TX:!]46"7`?+%@_2RA/5S012$F\R&&[ZP\CGVST]!3,.)SEQLSL\ +MC)X`'0?]B/7:/D&E%?=FD&/,N2'/<>^F?.'"BNB`XG]$SU]\4!(S95"QD6B: +MQL6`GD[((R60*)ZYX4XKY@1PP2W0K$<7K$ZP8`H)``:51)68.UQ')87$!%V, +MPZ[O$^PF7ZYI7#X,$/`-]?SA`@_^OG5$CG?.&^7\X3['=AOBAV[X)W@5\()J +M`ILPG:AVZH)E2-^PT$$OX"E:K\X1U>%/\=T& +M_RS(=GS?,&_B^94LWN_,&^+\P3W[@D<$.W=!/>A7;A-$%,Z$]F';I`F."L8$ +MY,*,0G(AVW<)N05>@GJQ"/;1&"0T9`^`RZELTP1: +MN,]KL395R6M3U6WN=H<4CN>-YE:F,1'IY9:%"#<\^+HY[<3+V%A/5$J$P&,, +M?X_,LK*VT.]8$H'Q/5D+4!V:97V8!T2K89SA"=6XF*W[$4HZ7X$11C-=M1E. +M"WXCFJ[9ET.81;+4YIL9HZ=LL4[L&S.F?F&I8PA:NE8GVWYIV#YF'#IQQOVL +M0FM%=VYDGIDC3.#Q*CW%_S#GCE$G*\\O.8!_<>$@7\\J&D(8A7L4&^(E1)I9 +M%X<]:JC49G$GY^MME/3Q9*]X/R13D,2KY'V'4[]A]+CLWDS2!^<'^SG!/.#' +M."_.".<3G$YP7IF&`[@R^6*_8WAQ2'R%\0KU!YQ1"RLUA"DOYMVF1^F+)T6M +MKA"V[O@/+_.V6_D?G_[-B.Y,5WXK[KYPON_G"V]^<'.&E)'YP[F\S3PO%QZO +MI9RB^>R!'V*=68W#;`DZ(SY!G5^,8@U*)CD4OQ5TR?4=]?\]D`?]2:8E8VB? +MRQ%1+'H-):9*WYT-P>4GW*M9T=;DQ(U6UM2";]F2#SW^)"]8'3/Y(,U@=N; +MR0/X(18XT*5@1YIP=O`']+(VB&"/1UE.>0HVE-`UL8#&G9PTZXQCON261M<2 +M86.:KEM=>3M\C4GSW,CA_ANU) +MQE>/+/W*4M[(U(Q6]U1QB6-8V;&Q@J%G];;)XTIH](I3]+[?#4*^[9-*UKJ9 +M@[CJQ='8V31V&-+BJ_4&[M],AQX7QC4W7NYI'0PRIS/MSL?8=IM4-.Z.'*8@ +MXFU?S=D;CC/B$?@-VW(7@9$,U%,P[@`>YO7>!&Z-OWB+?N*=Z? +M>)]SOMC%N5#XH0;.*N5!V@)Z7F2F9]L=(MCNFA\.]Y%7U+H(DNV>PZ;[@24% +M/$\EAD3!1_G!HL8,CB)DG(Y`"NX6&5=R]9T<4/2\/=?:?%WU'VVCE/EAZ0Y> +M6EI/&-1#+\P'WI/``%M;[M>Y2/DOLW34B"-:>\:0J'J1[CGTUR7I@:$_HL@& +MTZA^IM`K#6\3;R'9D0NB$@=3C"'$^!Z0ON*Q0$3DT)9@S&_RP5-N$`M/"L\LQT3#8;3JA;A0V*5YX$5N["QTDMX>_' +M9`C.<*+'26!MBG*A_F"YKQ$GY64-]AD10SLV8?E["XU2M@;9Z?UIZ)Q_=#2> +MCB0/5F@0]1",/:.%&IOH"/;!.&T7/^J9)R6S0H?Q8YMYFI>:3U387:NO)IAQ +MWJ>I-\9W5'ZCD<>WE[^[8@G4?X:[R6$#["+!:T=,:YT+JG,+$(8.2CL-A1%M +MBR\!"MH!@CV-*7BV\D^C`-W?RCD"&]#W@0#*N;E,*,[@]C?%400:.^9;;]1) +M!JW"+_C8*0:]>.L)[)"PSRI@#![!W7$!+3/V\3Z;8(;G>J/_(HL. +M%[>*4,FD76'%PV^2S^;&*X`9M>NQ@'"A$2V.-"F-"N,)IB3I-T2J)8$L27_' +M!2&"LN35!M2XHQX*UF%837H@#I]NFX?'+%G-'YIF$.-4N-&3K^"X>%6<5]1U +MUV;;6!JM/;[5Y@]'68U0_+[/#<=>ZHXO`IJ'9H8'^,$YPNST5.]Y@Q/.SB%]I32_;3U[\ +M^TF:8..I`,,F)FS<\"/%3HVR/W>`/2GYLYPW5`PU")ORT`G=@V9T.[W2<5]$ +M,3FH%!4NONZKN,XH.5:>@?6Q0FZZZ:X_*U@/]X(/"(Q@;]C$!RBW4/[LI +M@0I:B7\3%AX;C%AN[AS\-T#^[NNP#P'B/EV0BATVN@>/SXH-R>'#E7KP_N^7 +M`!YM"N52&*#PP(2><+PQ8?WW\+Q%7P6*-$-X\*%Z34KDZ<^0'6.@_;@0\,_" +MANLA`Y2RX/[HV_N2IVHF?*Q(>'AXD-W\.>_2#^[=7X*&QE0S/7'0NGR.:Q*N +MY9<<6.DW*?&8UP![KUQ&SJ*]^'_O9'@CN13/X5EJ=?%JNN/U.$%I=\#UC??? +MN[`,/M^RU\O<#Y*K[`C['/LM/R:3>FG#I*,G?!-23T`U$MF2^UQ*L%4[8EU: +M(VM(Q,'GS;QY"V-"G-)QOK=IT1Q.$:8.G1\VS25J)*>P=WE!!7;D);KH%=]@ +M.V5D>].KVH11,8I0_'Y(??%>['M>O#2:"(1>F.U +MBE.V@9Y%*NHT3:Y4-;6J:^13)@4G5MSFHR"N;FQ]VK!=:694OK*`;B975@M' +M7N2=/6(M=AW-:!V/&'#M[NT+ +M#%K`BY@8\,U^C-.05H!;L3$@,@Z6,(&7P&85ZK?,!?0$F$QX]1/3Z22;?.8L +MHL^:8]963K%#R5BG45OC<;C81!ARF89.?/H+>O>1E8D'7[&YJK4`F.[H\:DR +MFS5%)A>#<]T'LPL>A/>*=O*=FXW*AC[2.J]5.'TF7<.5HY-]7H2*8Z?<3U4T +M\I'=X6DX!YX40K`U1\,\Q.M'M.1/"9Z5)P/'[/6/SBW0<5K]*J@$CT@X+WUZ +MGC+WN$%JGA:K"N69>50&HC<`U?>;:4:L1.,/"00$'.F0E]'72E'8W%][4>P! +M5+5*?RC80G^N&1E:A_@YOB'LYU=E6\EAY.K16.=A0[WAA8Q[09J5ARN"N4FA +M7L]3[78"I.RU:/XBI0&D5\RJ#=S)TV>P2M,!04"8JHO-@$'V(R9&KG6 +MW9X>$#NK@BP##>9Y/%/JDM+QDR`0KWU416'BG*?)I&8"&AHE*-[[<#DGT1-)52(Y)OY'JO9N2\(1;V+6J +MC+"XP!!A.J3K4F81$7@TS]J?1#_>X,&XC-3-6)J;5_8YW1RR^07>LX(+BZ@% +M+W:)R)L!I0&<:T,V$0`5RF##LI^&@CTV_1?-[A$4ZDK3L!Z+&FISJ+G3=<.6 +M`1@,':VG94?'?E!=OIU'E/@/E;X$M"# +MSHSM.7=":\BCN+GJ>]!'PI8LE1LI6'\C4GJC_6$*Z/1H<]3@@THD2 +M,2AR,$%E0@)=RR$MH=D8T1@.<.\4+FHM3Z*X->8&!F/0M`7O)EQK*YM["N!K +MOL$MTJ?(ZJ"42NO9FW:2T$C2A=$%05_?PA_^VS=$XI1TS]30O]<(X?6IWO2: +ME,@S(Y8(0OA`4?#/^I:V.<"BB./SF?4VP*8S1Q"LA+1$"/TRW$^4>QZG8)K\ +MK1GQA2Y/#,[FFVJB*(A.-?YB +MR*NT8J7N[E%N^T>L6F&I02!W??`1KSEA]EO*K.-)&W@:]@GI?;P%TM0IP2?>J,$U`74K78.PNVXU& +MX^]N;A\RQ1%5K;*P(>%?!CJ%\ +MIZSLX/8\9O.EO#-66GQ::U>VY0S=BWY7*-/VCC)+##>C#9[HCB&D'3)?!`>B"&,8GP/;D>:#Y +MB72!/\$'`K=_YK=%KN%S]@]Z.MBG/GX1E!)`L.F?]I`I\:=4/>9"/9U`/TX$ +M.77A/4@5G-NS2(,2K*I![&I;@KBQ<=(7"(6,`HQ/)A'V0"B)V[QG(W%]Z=A[ +M\"IRD38M^+XB<]J@]1R>A"<):CJ.F)VC*NWVQ0EM!'Z/JN?FGG\`$20;K[[Q,"G-9L$]8]$ONG"-]UD7'%7DU< +MW@>']/,"U0'CW>R#NV`2U#I+AGO`K%DI"8D.R^!65#CK0\/8\L+:&98*WLG8D=P[.E`!3&!QBP\/K_J%L4'CS;6JYOP3>`Z/@9QX5^Z`" +MF#"OR0`=>26KR'&]A?C<2]ICS,Z"_EGD+0ZA?)$M$)#)P(.S"/C4M^&3"3!7 +MT(XJM2-!`JE\\@JS6<6)(S`QP0.J7,(=.58`1*I.K`%?`B("B-1#S_Q65DY5 +M=X;?`A[TPG[&[J?T32)ZHKN="$V[?*6CV:UR93-R"@0CA`KW'(G_4!)W$OC6 +MHLAJB?'M=V;M/*"VW"ZIU'O@GD$3J$X1'Y>0%N!;]T8YK'XX3X(=*@,\((X@5FB>L2.#LR@5W@<>"'AUP7\>W[I,N>Z +M">V#IKPSY`1Y05[(GFDAP[(/]W>[F@8>0%VZW+5Z?]Z"1T5&A?NTMFSC3A/L +M.<P!;;-R@K3C/-M:QPN+/YN;IU>&;L6+Q!.&#DS`!62@`C+DTD`&)\.FV!1(1!N, +M-UD=QDG;;B2XN.AZ7]H?0"CV`YF=()'I\(?;GXN!.LK'45W3-P9#B_LZ-. +MOPWRG\&]XNE_0?_^.6I?MA[*YLP$_CL!*8YFD\),RMEI6?DYZ8G1\?Z!FAH3:JHS@A^,Y:&]- +M!"("'I9N.BXL9J^I1\D/_TY)LD\)*DQ_1$X3#Z(0J`$U"F;27$-E!,+/2#_Q +MHX3$C/:4U`*CM9MH:?2P8[=5-SFLFS2Q4/6M!7Y*!;F)!A@)MJ)W&:CVJ!J/ +MCAV8PE]>%)\=IIZA,0_&^*8.`P;E``#E``"```$"44])V*\C8`#>=ESGN^4J +M5P(3"X+V``3@Z0CM@P)J2065@!4!-VAO;64O86YT96LO=&5M<"]B=6EL9"]U +M;G)A1OF.'>GM.B9CIL?*BU +MFTG!2*=&A0DB!=42C[T^A*YB4,-S$G)3)ADR;RN&R)JQWA3=PY%B)F\C!;2E +M)R6YT*?D@JSE!D8$:6:%9I.74*ZA63^**JA'<&J%6[`CJPF41)`IJDS0$#L69F\G +MU6Y?.5Q))C+)GGBL-L'!H_1)PJC."=S'S43CPE;P?!X"$QJ!91@JR=M`N/E/ +M$,N<6!AO0,:TE\:`ZN3ZP(E+5!T6CW,^V;9:8GK2^,82F$6#))F,,A`(H1M9 +M/"M>H0CBJOT12$P&(,O@S.7&#XXWEA^5BZ/*6GU`-#A;=@!_)Q],)1,-X6:>]J)5HS-Y6FHFV['TYIO` +MC<0QSG3(X"_0F&A*%5)MP7E)B6-Y1UM"^"=D(R!G\I5'""&^9N<&@G9*3$AR +M0^4US-'E9R)'D9$03`X%(3+DF9O'&;"B;!6'"B2!!-5A126@PK6;GI*>A1]% +M)1V2P0J.DXGON"HD5C)!").9)XD8K&+N138DHP\69SHU0(+8I$G@1X\[ +M?8^>'"-7T?HD81*2<>7$T'"+-P:/)'=H-@V1KG<2TM./E.=H=6P;<+2F)MPK6GE=0 +M;=2%QU+0P\7%9:0CH[+1&5S@_8"=TD)I8&U)S#`(-240AE9_,LAX3\O"%GE? +MS:GEHHIY?IN7EJHY^6'[CS)/MKS"U3\Q`7'F&+:GE^(L\QDK1Y@4+?,A5S\N +MJ&_EN>X\R!U?F'1$)3FJ9P&?@7@VT;\2'BHMX6Y4_/M9J:DIX<9OESXZ,V"" +M/=9#5WB#.P83%8F?4E(=7B,]GLYGAW45W'RC9G1Q_\ZS'S"2-?*IU\P2?`L1T_):@]\FSTDX?,,3^E +M9Y`S"\DWV08_!&,M*RTD)9'(,SZEP4-B)F<`%,#L7SAK26L&FE<&-W_*RM%)!A?S\NH2A(&<3/../C3\)*)Y4H^:-1>C"O +MNM4S1^#/8_1FC1L@FRR&$U0-FI65G5$3,-&L.IHPGEFDT^QRNE01I]J;S5PE +MFJBEF*XT0X=0(R6J-; +MV&$FSRF?RV5A]`#3=!,#B!9HV0/H)*>F#DI!KU8_8CQLA8M@&VNM^5:ST\%=HV#T9H< +M>`1@WS9" +MM8=:%&&&6K'/"@5'"J)FXHL!G+RCXHN-S*=9TXK,S=J"EGG.-6CBXC@TD5X) +M:",CHGN@-87<9!HZWGPG0[IFT3>H4ND[-A(,)B) +M1P+N*CD\>.T65L*@=%[:-EI#N&>3?#3,:FEO1%"(W)S$^:@'3`5>*T\:%@D +M^C.*:"<%%)D[Z!YJ?-8AQS-O\P&,/HL>@<*:;+^+*%OIAPTTFAWO'6?8W&"Z +MS^JF)TQGE9VY6BB+E>438U +M.CYGP#G`9N<<#XTL'!I2GN65ET;9^S]JS>T`W!*D*U0'+(LU)__S?B0?O7AS +M=`RZ@E8[<5/JF>@-I)#C3%\G?$C8H&`5>=">#9]@#0*?EY)U?,3C$%/$N1^2 +M$(.8B/\>+8.&/9F\]J5''8,<#(XT#5Q=O&1>`-2F)Y]&#[!G"88?D";$TJ(L +MJ+[D,%\'&8L59'=SCGN+XN9UJ+.*P9L]N,31!ZC7(R2HE1!J1FOT2C9F^60T +M']ZS]3%W"T9N54G!3-\BC9_@003H?*-ILX%.IU%K@8/(X.V7_,8M2EL)BVDX$V^ +M*O!_(RC_\.W.@;,B5NK@CY"&M:(\]MX"^VX&WW!LU(0F#-@YC0B8&U5P6)_: +M,K:FJ*V9T?_I*^C+PGAHIISU9;;86_]XNN&<2<.3$*F%)_&_`D1R;-H8G!O% +MM4VC@WA):F2UE?6"O_QJRH3^)4.GGIU;_O6ZN.:OFS[W5;4'\5'S%KK)(3@S +MQ:\&]&F#=7M@6JJ_6-T07\I<6TJQ@5R57^+=3ID[K&ZH_BJ>7-M*@<&JP3'*S/_#@?M[.O\9EZD0#K&SWU2$DL:=;3$;667_R(.Z$:ZR7 +M^UUDH%2Q*YM"N,CLN?)63C-,UP:2P\*T +M24/\28GAT%0?1J(S.I>U!U/3SV>!1I? +M^!/P+%.6.ON2$LB3MR;/2%"D%IBA3WY$H4]N2 +M*.P-\.G`*>/)E"GIRI0IK]04*2,N4*9K4E"D5JBA3:S11W!OR*8,FIFRA2]S +MI0IM)XH4\"A!JD#XM:#58&*[,&L`/((_,0:\Z\D(![&Q!HT"Y[(&G0-$2H)X +MI*DGTDJR?WHBA3![,HR!IPI"$TFT*%(ZC*%'BD*%*+M"A2^;8H4]4E@21I2A +ML^)3%&QYI(TD=VY0I2DJ">1MRA2_=R4*;/NBA3H]V4>09IN0"EW_D4*29)TF +M^)4$_`E23,]^4*=V2P)S2/ST#8#P"A2;)&D](DZ1+=%"D42I)_3P2A30>$4* +M;HC\]@VC\,H4I"1I.^W90I!>*4*>L2I)<-Z4/3^04*7'R2CX#1C8A";;RBA2 +M(J2A34^:#=N!A^`#;X#3\@&Y@#QR@;I`?Z)P#:`#8^R#-`+ +M][0-W@#'VP;T`//)S"=][A0IV?NE'X&D*L`I@.64*59&A/0]XH4W/OE"G4)S +M"/'PE"F[)T!B29#X@;7@19.\),DWQ.W)QR)^A%:[79X?M"_+KP].[&H +M7)S]Y`Y0VIS>>P^6=WX%?T>>I\;F&S2+JV'Q^R[X_YE]>=8QHDLG=\?!8B_W +MU/VA/CP-G%MF_*S4.(1VB_*O;LO^XQA3I]>!HHP&NJ\*NEQ7G`"K=`9P8#^# +M6#^H0/%?A`:2S/"6E_^03S0/C*>R%^0$],#:C!WZ1;_:$WD6#Z(81]];6TJH +M_Y`IHR8H+:L*1X$Z2P7+%?KUP;UY2&&&_DFUM:%-TV-,3/+1^,">$!4#$7E+ +M.\@$\UL1NC]\-P?7K1_Z0G(&I]8-P_U&U_S"8\".E`;'K4?Q03KRD[+`T +M^%YL)W0'K6?'A`70;H_?V=ZD)YH'E#=3R:T_Z8'9@=,GV#=?W9V+6)HW1T>G +M9P8V8VX_\#==Y!M?%A(]_N[+5E:06T^C"30(\E/VXH=$V.Y#CNP.>3RRW\AM +M-4V)Z@!LTM'\N$UH'@E,J%MBXLQCZ+Z55GQ9V97EXPP#YK`;]0O^(3(@=`I; +M1?H@+E0APW8&+*=$M_]!-4`Z:VV[,=:4^9L6RY&/HVY/#@N+=J$PP&:'"EZ9:G_9! +M,BV*7M0;5!>6":(#F#A>]LZEM1NH;W8&0IP;>+5?\0)JBG&)%!?+!-:!7AQ' +M^`7C1`<<..[`^L.-4!=.X#A6@9,.(^DUD +MN7BS`[DELUOPQ3W:@&_K9WWH3(@1XXR.);7RH31`;4G$"_IA.[`OHXUO!%M+ +M.'OZHIA"7%:C[V$UH%['')]W9WVX2D..S[K<`W\K._>!+,U.\]Z#9M8\_%!, +M,4QMF=HM/^S"9%L>&..[[-:7Z`)H@/T;&/"U`JA_E+GNB-KXH)J@(0<@'PUJ +M/\`'?P*TGM^(#8`+*%OI@?#_,&Y3L%O6/=^&Q<]Y')'['R$9`=9>/WY\32!0 +MCY8P/VGI`V]6I'XH3*-A\],&^98P.L"=J:G]D./C`;;@APXX$1Z@<.>`OX0- +MXX7W82ZCE-^U*?Y"]:$W\"+X8-Y07W@3E@/B);.%'E"G@<0.&U`D/5#AXP%^ +MJ@;D!?BA/'`]%_;'-)+!>2"]X18NR2SUN +M/O`:8EU=R)^MR]Y2Z3]56W._ +M+=`VCU3?7EU0J$]3`)N[;5U)C,"Y3^VOKDF]2ZEADYG_];*RG%BQ=13??U!^ +MR+IN@]@76^9A'YAJ`2__:?$_?E$]$G()\)/I)^)';$%T778$Q1,N30DEB4!.T)WI-X3T2<@GPD^ +MDGXD=L271==@3%$RY-"26)0*O5KQQZ^_I^OMZ2WU]G3]?5TEOKZ?'N<_7AK4 +MAE/U\?UI7[`N8'T5GKQN7?,#5R#*?KPO?BY3]=_\27*?KO/DBY\8-109S&5RN.9P +M&8S<=`L\9!X>#A$L&WAN(B5:V%4+#HE:_Q,/NB\-]KC`CG3P'S^?,!M1W@OI<8L-J/(%],O&AM1ZCQR\YK0!M1\#_ +M)>?G:(-N7MT0D7O^./#:C^'/+S>Y(-J6""^D/*AM2Q`7T:S`;4L<<@O/RIH- +MN7M^`D7O][5AM2S1U1#W:@#:EH"S],=K@WNN`$3R\.7)V(;4M8=[9\^CM`VI +M;(O1?&XF.Z,&VQ7>*`].Z/?*BU;9"^_C9U?U_7L=.1TUYYEF\2=FG2\OIMR^ +M/LPC$:$?:#%V8N],5,6'SI[/ +MC0#L3(ZN]0F.1J)Q@/K=Z87[0C*'*+HM@6O[F)>/!1O8`X@5LL\;,'QATY=.YX&R>#I,NC+IWZX^_4[)Y:O0&<=D +MP[0/0]9_CO/81HGJ8E*$&C5*6/>_H40&^)PGIXVUZH)T0+LCL:*TBD^/B4"<`W2MZ,BL"^!IZ:#N00:,@/H8LSBOT!2YO80YQKKPO*(J +MK7D7D7HK57HJR7D=$5XNIG`F&F,4E\#=,>>7KW@#!79",H<'8#YA3K^XNV4L +MU?7H"HNR`KP`76=`-Q>$3\T^`=Z@M,/I,])WUX[-L +MYR_N;LA"OM9`=^VA\.'^%=P<>365^[O?9H>7=CH+OKTBA_,X+YMY![B>?]5, +M=NQR3QKX1W8YE<=@!S$ZGEL,>9(W2('RDI*TX^-B.N'L`KD]`3/7#X][,'XT +M^ZN]Q_0$\@,*RZH4?8F7=VO'7'L<43NP9&XHRROQIQW=[F>6+\YP?^QI3R>0 +M*U,-8ZG05T\(TT]58LJ?F(_/S.+;,Q78O#T;@/I6&F3R2\`,GJYXP'7HL^+T6K7@ZNY->H>;V)%\\QMJ'B#8OSH3M#*B\0CW +MM"O>A;L\0KWO#J,RXIBD\9%]XB1SGXQ]S)/AF./[+2G$X9[VX%Y9#RUP\0[W +MWY1F(,P`RK(S5+^RPSZ4B$%J`986S69>S-1A&7UKRF;N`^RSV,9+RJ-?F9MR +M&*ST!I+F9A$2RBWDI'MGT3)J<@:4KR[(>H]GC4W4Z@T(R#KJS=%%@&[?9&/# +MSA'S+&GGOCF_'F#1+82(N8O5WN1K!#"N,=7N`O$:86?/<,6NR-(>)@WY,-R1 +M9L^_[,@#^-)O#33]P3$$91^$I/W-=V\MU?N6Z@C8T%B_2F+!WYEL78#&`[^RT+$#&@[-EMW +ML#'`\`RFUX&/!X1E^;Z!D`<1EB>AR(/#,O-.0(8'B678L`(<'C65*Z@90'T3 +M+2N@&6NF7,`2+*^')N7N0\QO2[+RCB<2A-9UD/+.+[%(W&C+P7H#,O)JSJ%E +MM3T,9<39%6B901U"S8A%F;1EK5Q,XQSQB/1LNS.)YU]TYMS;,O$!=D]_"4J& +M7>%6DNLU9FY$Z&8A'W:ALS=LO/.I^E0AV]92#(#3,C-?J65=9J0>.T`X#+3- +ME(H1NJ96!5IV.Q,)\=)AWYB<_.]V-6'Q$=% +MTZ^!G<:;O))\!`7MPWUP&=-,.IYEA]IORX8E_RQBD]WJYFETK +MYYJ#(9P-[V@MTN';(F7OZ#"=PIDY>K,'7&[O1T\>.\*?2P.5W7Y3T?&?`+Q= +MSS3W.G!^O!WOBGG[V#W(??0YA$KG\]`ZOKL8;23'6ZX(VB9L;KI#`"3]=="?=9W7&&NC(:ZXTX%1/^P, +M:A+@\T'KW^^FH75_NIID=YX,Y[WSLFP@9;V/MQ)UWAOAS8]SCNV-VFE>/=2G +MB7#LP6J.![P(U8+RPC(@O,![M_=>`_KD4%V]LQQN5[7OOYH5'3*'>@7/%IRX$I<\>5V'PF.ET@+Q$G#@I +MW:OS=PUDP!]/X+R\&6:](&>OZ`M.8W=_=QYO5O?S#5?=[N@ZWN/,AUWO![%0 +MKG#F6&[]?=#B[%C>,8O'D3]E!&#;QCGSZ$(#9&`;QCWS;E=B_7C)K^Y.!S;L +M!#O":2WM^*91X*[+Z3'B\96X'.[$XAF%_&<%2*"V9""QF@VSO&<7O;(F="V> +M#7*7@9]!N8LKN\`:#KOL/=%YHRMWB.1N/YSW).F&.2K\=+)-[0N3+B'`Y1&X +M)N9MFTSMGP+V/+ZMXE7H?#7!IT0[)?M24Z`:5^C4(& +M[/@$N\'-;\<[3*_>DP!JK9M][-"@OIUEG$TT.!M%_QD_HZ@4"A4'E/6\:Q16 +M.T!4/7&M3O0I/.WC$,,J\`-6)(5V1+TAS!D';(&KB=SHAEG8U8%\D)YH#1;L +M:JB][8S1M"[&J#O>N.O4PFM_.9`3KMM06S/+UKL=-$D'W/O";K-X'!:7B_LO +M">"2AUE[!-YAJ9AD`R*[+`GH8('8GOZ+Q"$>A5XZ6]FR.M3\DP'F;F\:]@8E^,^&S8WJ]L*PZH;X"]7VX>2>7"+@!/1JBQ"/K>$WV+TB2=ESNQ.B +MP_IQEZQ!IG+E#*6,L]Z[!AZ)QIEH'4"#?O[+D(X9*;UA@?;,H(7MK +MUB7HUJ6H1%?S3RHN\,*JG)-VYQB%>>O77<]!=AY'(!P`U?O]NP'ZG@WC.R*/;H2_5C`I^P:E`WZSJ!9 +M!J7)?\2R`'XI/3(;-!77,B[G29-X`>0VT)PWD![#="2^KP'Y$-`K40;'H2!= +MZI*U0&CPF37VN`*K)]$'T!S9B!-U&]%6[#7834_J`;$AO= +MW\-1SXD>>NX1O0VQ*LVW#:DC^=&LX&^`76!OEF,5VI7/N'&SK`-#->U2,>@. +MZ]`ID($&>' +M`QL])^Z4SQKAKYW+VFZ9OY\ +MY[OWMV.11!ZC3=A,-F#/M&%`4`9$1$,C5G!(:+TU=U>K-:T"0EB2Q8DLQ+-* +MU@D"U`M`(1KQ&G$EFI!BS,,U(0"2!"&AM@TC0V-FA8F#?4,$A#!@,2#HVQMH +M8-L.Z`&#?6/HD"T@(6@$:4N7$WGD3-55W=9F(TOO[A^;]YSWWX>\]^6:+J=$ +M3$Q$3$Q.BJJ\RZF?\E'\$\CR/(\B9B:K+PO.'.7R_F_/#B&AV,/'B^LDO/($B0M6"4'LW@YVC0#Y9`=8>G`3)+;"951^ +M`)>@0HB/DPWQJFW$4T86PQ['Z&ITX9"\)*<0$0EZA"HN0X;HIGB6Y( +M?`=(OZ0-*%THR:;#N33K[D1R_5X4:,1]M7A2![!PA:@S(G!VBBYZF(_8$^HZ +M0`TU^(EDRK\91.V6@`+K(DS\,!5!#@9K\_3B+J2=X'1L->OX2C2FM# +M?DE/EH;F+7,91SMGK*CW6!E]15"0"],)?T\Y+FM+RD-_U[E.0/3G=/%/YHEG +M9SGS0WRJD61A2SF:?E,H2K%),0+R2R1I\#V<)9C#Y0\E2_&"/WWZ$!]YF`<4=]2!86&YS/;$L&Y:*[TBB?[1ZJ.F$E@F?TK=SQ.W*C6JGR0!*U +MQ0ZY):^3"34F^WK"7DO"=?+$*+1)`(C%22FGU*2PN/4AC44TY+G15Y<)A3;U +MQ`=B:?O,0-T^(VY#\B3+_7"8J0=K&'B)*O]B'VY"J-)G[4/N:8';L4B37`F. +M9^Y&7(E?DRQ1IH*HZ98,CHI_]SU3^;)4J3FU\*4Y$JI-:DM/,@N;PT+7$7VR +M.6?JCIU+R,*P6?*3=GN422NR@I0YW'9$NICRG,RY1GX"@*^,*3::=LAE&WYX +M,3DTKW>@'^BKJ]`\B#`[-*Y&VTP(OY35([5`FNQ)=?(&RD8WV45'8!%6RE6/ +MNP7R8T)?MC&5P/O05_"57&#\=O2'`0R7H"0YPT=]O!2M5&'J6RK#G^$N3=@A +M,XDMZ5`_;JR6<:ISTDPAB.G$8Z`L]"3]`JZ$F)S/VSV->2O@L5Q`5,YS"28L +M(+Y5,WEVV)Y7[+$[9]TQQG3&ML08C_,!<7`I!_LLCG*@J:`J^^U0![*#RZZH +MZ\,+[3_A05/YV7566HJVIKD'$JK39B<^)R49>#`KHU50KB,&,@9]Q/=$=.4I +M!2P7[C5$NT=$_Q3*(A+J`IE+QX#IVNGHJK1V:8'")(-`]"+BIQ1+2UP._4"; +M/RM.E1B7)"`M_)BZ`(A^%MTG,FFW:S)._@U=2D]/B@)7([#KI'YCK(B=&,T +M8,,`4TA:ORBA-.?R0$:I++Y8!5V_E*(#B0"KM?*(4FR-3C>":>D9F6?:HMYQ +M!LTQEZTJD]@E\Y#*,82M]3%\J/(?%*)]S$4!7I5+^83../)"OL"0IZU`Y&`O +MD'RAC.<<;(O)P(G9,TGCJK%SZS]4PTI5F"OCKP3`$PJ#6*7[#_"LB.?[M9$\ +MA@'JE8;TNB_ZU"V)7V47OB=*2[XGG5*IA_C$$UI53GW +M[]=2XN?G$3L7[*VJ![J1AGV#7Y?K(O2-4H^ZB)PIZ=^R@N=JA8_V+]A'5*:2 +M`]@(J<_T2&!_#)41O3K,\VQ(W[OMV;MNHNQ#7LEW) +M4!C$-4[*(6TU!<=H5Y8GK"WC!%=J5]\=+F))6*.=P5XLGJRWC!%?;*\"F'G$ +M+#%SC;T3G8NH+>,$5UQ75D9HEZ^G+CL"N\D](6Z`BNJ*_O$7I+[Q<^L5KD[` +MMT!%697ETAWP+HG.%SB+V3^%E.K'^]"J[ +MF,<3QQ/^,7.EO67*38Y=.E[")9B=LB&77?LWR_N$BCE&G]*XH\>;1/CP7&J +MMF"!Z9IF=M#(FBZ?ITQL[\*FPM%9627U(IIAG4S3?Y"=T1-DPTL\(V$_]'Q3 +MA+5'&1OK-W'`%@8RS$_@'BG^'9->?Q#Y$\DR@=+4WVWQ5GR(>HJH)7`171$) +MPU"=.P0.QLHNE:N*V^18`IU&X?T2&[AHG*(<^_3`:A]+,T$S]D_1-]8D.244 +M7=%OW1:#_,&#?QJI9SDD*:CEEJC;77E";>#X-`\?CR8`K\P0/;Z9@LQ`85B_ +MT("4;7IHH]7IJ+06:7\WU*@#4$)9^4X9B`X?5T6C1.-);[JY^O>%.2(@EW"3 +M%XY@TQAV57V[,/BN<'L$BYS(G!)/H`8,0/1%-&VX]K/,)[1&_ODC",-GU::J?-/2JWZJ +M?(P[?JCK!\X]*NUZI6!OP^`*@:[B>S#E$3C!IZ*HM_=6E"9Q/VDY>BM%_V6+6Q(^02HF2&RI7_K%`%AI*JX'^)0U$)&& +M7C4!GZ)'\I+<5,7-E='.$P!2=;`/T7<3X:R'16:7LWU+#,B9(A_A268%]5-J +M;VS$XMO"U8@>L5]LWIV[:+VQ:\]"5`9ME)DXE8[[T='QI-[V+-L6E#YR8"$A3>@B[)JZ[4^$)PD/8%48(KO8L-FL%V^F3.D,D,\FTS +M$ZPXIW9:?ST-4!B-+3$Z=7\6>_(RL,GD<6A6@$AFC`OTZ9DXCQ$['/DK)I-O[8Y]@ +M"PD;*\0Y_.QE.-74;WS0UOV)CY`N9_"DP!8)&X?XA&_`+*`BZ$ +M=4T.?UH7K=)%IFK'?S$6`*]QEL.KBB`9Y0F@*F7]A)`[>+G24Y%UAVT]&@?T +M>,)C\M!I(LQ(M6/^GA5M>K(=XF=?]&"8UW1Q<@5\IAB8`L=)7<\/\HAI5:V# +MQ%_L@1IPBL\ZR2KB;^1XQABJP\^([]XS=O8P[`Z8J0EU_/Q;V])U\]%`%BV+ +MEBPN\(#DT+@E6)90UN8P\IV4J(1`]?3,$+BR>85R:S&/&,\1UFGG/MIF3&O& +ML4;$?*?WM@`[?3I+Q-R>465J3F +M$!#5BK\@\?*JN_8$=NG)1R+-#.K$!C'Q3?27V].XGNR2:7!=I11@N= +M)4[3`>BGV<[Z`%/-8A&XD0&.0O$0$H&0,U&0+>BJJY+_HB0-:<3>#/?=LT6S +MCP[_A\#N(PN5.9Q\I_-$J49T`YX;MG/+3SZSX7;%+?+3MDEZ_)!L=W*1U_%@ +MP*[FV]U\_BBP!8.2Q>0?XE#47T89=G`%T5DE]S#$=DE&9&'2(6S*O1*TE9_L +M6_^Y,8MX^5:L*_UFCOOV!CJRYL +MBL`4FQ9#^CN-0]RJ+'M:LYU*%R^=B\BTH'D<03`%@457DA`42*KPB6CC'*1J +M0:2+S9*WKYS4I$>J=L\G;C#L"/7E=M.U1B+[#MGD]E>'](19Y/6@)F+5NV;C +MG&BD(P"7GUX,G*':CZ-"YCF(O$1?>(L`4ZA;9BOL(#%(7F::,*-+_E)+EM5> +M[*Q,I\X&.(C)JH/B&#Y1%%36J(H +M'V)L7G^I +M?N$O\$KD-4K.IFND98`UALN<2[9RZ0VBN*:>C&"Z5)MOB7DYJ+^II.'"18`L +M`CW=/E4:=#B9YA+K#`5 +MP="_Q.EV69SB>^X:['[G2:"O5Y4E_&/?PZ,F`+!HW#^A15$:&_.=3*0M$)H( +M\YHS<[1&BKSVHW,)H%\^.=:DS_O=08HZ8[OHHOHY@_1S^$$KZ*O"BB_:4T:3_MH7IY=OC5N9I"?VV +MBE8N9@?T"*4>/8NI9FD!!#[`,FG&GLF(U2S*G^`0V#S^X5S^V@QIO#`]7G:T +MHUKIBQRK`^I",`D#`HSZ;FSKJ'0,8*3OFE6Z3$J0WG6IL.?+!+ZBCSW^ATJ6 +M8UC-"-.Q/@@,J2V&G//$>:=,KLXC8,S)^EP2_[I%)1Z$GG7&)_0KP?O>ZRG% +M//.Z]U`9K^VAR"P=0L<[(Y@[5'IW3XES@%E<&B]BT_#.C%RQSVY^-RFB#59* +MY')^TC86U.D"OJ7EQ%%9)>XAE7*N0<:SS[FO2+OE;N>W1U0MVP5_DX&!0LZXI-`DA/$0/NJ\)/ +M%OCE'G6RO0?T-PZ0^F,<8)_OO($N"5^P +M4,&"(Z::..,L<6M'^"(43Q#F<>W7\P>-:$(CKRC&'+;[Y&]$/#QQ+NRNSBH% +MZ9:X)EX?8-,7<1.<0Z);XP+S4Y?+CM!?'>X:G_:+\\Y:[=LP\<;X].6(=I>4 +MQHM"<$G+#NV?L/A83#K3-XXI'C/;V^1E23;O3:NP"/95V\T\+5Y%>17D5Y%> +M17A4>09O$4IVKMX)!67>*[=V5$HJ-*NW:D%ZO\KA%OD%X.W.G9)<^VTWC]?( +MN2HXW]:+>0IK>."Z%S[;#6H%[ZZ*EJ*'4E:V+A]A%6R,IKXJW)1.VBK9*'T\ +M5;)P^KBK%LMEU#I"6S4/8E:VB4)]R")0GW(HE"?9!$H3[(HE"?9)$H3[)HE"?91$H3[+7C;NR;[E +M)G=HA"?%L^BOLU!V)6^+9]%?K_U=I]4Q +M$#Y5>0L"XH0IM5XD8AT]>%""@2Q0H+PY.8*'B3D3`PAVR2_[")E3=O4T[PHQ +M?_9N)A(+_[5PD&`5&QGTA_H+9]HTQ?Z8A1?..3!0AVR3`)0B,"_JAX!T<^$T +M0@&\(=KHP==$UZ9&@P24(C!U\L==V$@P?QL`:#!)0B,'P43*H,$JE2,*_NI2 +M8629Z5H8QA8!B"A(,.<4OR@PR4(C#)0B,,E*CM;J)USF9-%(,3Q4 +M*6QA\@%P;ENUK<]S+GC1<)$S;EGD0E$8B9N`@K<@B<+`05N11-%`05L@B<=`05LBBZ*(!%;F933HC5P$%;/);^:R`@K=#>?LNBB`16Z*]]M&BW@(*W1J( +M[80$%;I'_5Q8$5:F@:U$>/`05BJ`16T*_<.BMZ^O8_S/2"@K3\2$2Z1T13$0 +MSIB22\2X?/&\A(6J2Z0M8B%!??DXQ'DCR?)@5XQ?=A$_2H<9J,8Q??91*Z"^ +M^TP[05R4/PC@/@=(G>IBT%>^<=\%P4%&FGIVR0EP%R+_71!WL$N +M@OR2Y%^27(O_QL`:"_)+D7Y:ORV@%'9I:GZ=#@%"8)=!@SBE^4&"27(P22Y& +M"6L(H-%:)A%"GB#"*$&6Z=!OCEO7J1'D)B>/B)!1>])@9+!?FN0F,,,\$]*_ +M1*FWLUE*X-'E#])+>%[4.T)1N$>K!%,Z_*^\*FWN5]G9Y'E#UB4;A'(],FEA->(!7+RY)M[M:[^ +M?1Y0]TDWKU(CV98M:67'^5H.;\R^S\N_(W^.Q$5<:WL$KSJ*;>]97=XA'E#[ +M4N4MZ]5QTT13[\=A-]\J;>_8.4H4>4/2(WUS<<(=^D4/9)-Z]2/V<.&5TJX[_Y2I70S +M))M_2RO2QJ/*$W,E,;A'[/5EBOJF&&;;^MG?=QZ/*'3$;XYN./F.I\^P*?6E +MRO^<:FW]K2I>11Y0_V(XARQ_A*T)TAY8Y%+V(<4+#"CG)>P#RB43"!GYB8"? +M7-&_UJGU*XF?(2)\`YY^08;533'^:.58"^*Z86O&V4%3R%G9>M#S!,B<8/3` +M%/'3)7@IHDV_OE^9R*/*%ZFDL1&]>J-`N6."*JTA,%,":*ZQAA(V_PR3>ISW(_)9S@XDQ!=Q+Y$#F7?2MY%8683O;4O$F$:F +M9\E>ONY2]I'0, +MI8B9T2/I20#$&5)L#R6D";%YIF#>)EDP/CZA,LQ2S!;30^*K]X>.0;48R$]W +MG"E%]"C=Z4X,37O%2,H8(WCE4OWS&I0A?9ISA$T5\>LI_?KRW,^_R*`Q_@<$ +MDB'`0Y"C\/L")NY5DCSI,P3>FZ!'@#L[L1'5[H"'.A4NA85YNH6T11)EC1R09)A5 +M(V):3B\2RO+BC$3C%W5.'WB6,N-I.)QMU#^-6.NZM"@8]O6?^@53Y.J0L21* +M"RPI:I$^@54;G5`AR-1F(3E",K,B=\NPK(C_8N@NW[=`4"+!DC=A$ +MX;*&(D7Z8=\E2_,?_0!`$;_IW_W@;I?^[*\*99%O +M\OJ@?XBIC]TQ_MUSO!N5GO`M%HEIJ5GW7++6:T#EEGD8+]&(8.ULVM#BP50CVA6A<^ +M'"`_C!\/5Z(J]9X1MGCSDUK +MZ.,VM,CE5CFJ#M/"S1#I[2F1PX@*R-(/U>L`;:@/'Y"3%";Y=/!?(+7M/$3V +M[3)1-D`%,]45-X2_ZU:84+%I0&`_U-I<`2:'N%I;NT`2=YD1Z\Z(6SN`Q*9I +M@)?2:3_-[(%TV$+TA"BA`''(5YBP=&0UP`F#,P"2=!# +M00++Y;K2NL$@\@'-MXPQ"TX[JA#1'?'T`+D2*^@:RJXB5PF9<0$L$L>`"/`- +M@4RSG6C:O.K3Q>U280(8>YYTZ"A',7\U&N>=%_8_BR?HJZGK;0!5#H=%9MX& +MRZBZ0(2_J+"I9AS&M#5T]/0Z3'8RFQF*Q%A3JTDSZL>E"?_&X-2F3$T82'Q_ +M"-9!(Q"Q;J0=.R@:$8MF;MX0LK.H$GJD0L4CF8&(/]KF)'34UEHJL:$ZL<,L +M;2G-ZCKTDC=%<%D8.V$%F>J+#T%755\B^KDH2!+-:'S;$VGH@#L1* +MF"#'\?/=]HY:M>]0L+D7?6.:#?B`]H5H/W++52SL5.5]:=8%W +MT`CE^V7Z5UGI<1Z^!=8B8-_UR_WB*Q!:#KHOA@%PR8B"OM0\]1W*KZQ:9V*9 +MA"!I[*T#T[@;,1.0=4J1-.+2^X`$(+CC"0]\E:I79I*V4SP'FN=B?1+GKM_ +MY#!?K^S&'09-@M9PB#9]I)"NMDZGP\X\.\%5'$V@!-P[A*(4SM7F#G]U@1ZO +MS,?(XDX2A.3("P&<`3>ZM%11G?T&*1'IJ#X`?.M`U(`_)X?DP\\T<->;/*Y +M2'YI^D8^:4C\A(##B0'4_DB`G"!;+.W?3V;N'D`:F$BB`?6J4!9&C7`HB;A9 +MT&X@2P[M`BEUT`='PX_/+7P%'>Q()4?D1U/3(C%Y<.*&Z>#ZB`&IK\M5KF-S +M$H&B]G%=Q.M,44C!3NCX.O2/T>&7:RN*^)$K"=3D6I`HX`]3#'P&2P-!X;D1 +MN>223X?DH[TN:.,"N="]`E1H(L"@AJ40LB?J/UZ)Z=`M<\8T2HE2('`,4VDD@J\$)F+*T!V04HP +M=)D#!,%>:UG@H][8C5%$'K4DN[O5!(J_+,64MFJQHN!?T\$5:&2J]"%QE$*[ +M?T!R72,$(^("S2=BT6,5F%NP\?1;XP*DU;/`6PQ*=8>S,5^`O#C\G@_G`[>9 +M`Y=K?GLE-5EUEU6A%*J1NU6\+M`=_B`K5<$5RFK3;YNLPR&@LWYP1E%*BVY` +M:N@/JM@]F%'<%<'XVAW>R4R5)B]&P,'?2A5ETP"N7=Z](T)1%_3%%NJ^9IIJ +MB,=-HKMNK9Y-S&=<\T5"W>)8SVKJD$ +MMJR6)7`.ZW:KJ>&(CO-FS5,$7MTW>#/&3:T\F#!BLLQ%Q)W8`)M?:I`7R_0# +M@ZP,N:A8K3^REFNF;<\]V[WJ$CSVBZ;4AF@IDR^?D(\BTKJ=ETD@^(',Z9K2 +MB;NSNHD%ESN"<`A#UX?NL$)%#JU<:OU%)YU@7S,&'X^MSAP3SNV$WO.ARIE3 +MN-P`8'[KE]=&PEM&)TO1SE+I7QM66TF>9;?W=%]L43,4*KANS,I-&\"=8=*M +M-^F"!%[/.C<5S-HJD7K1$IX)0<`H0CJW4<]HMACE^_7[-;!G8>BU#7Z[7,41 +M&[K6$]2,QP2#SR%N.`YA@53@FF>%Y6R"IL6(00#RFV3.K[:ZE-Y'H6+[H\S> +M>SUP*)+J_25ZFHSX.@]GD'P`#OKEKZ$.VJ5MQQP4PDWL*I13O# +M7(FSJ8T"J@U*I<8(YE@KF)9$V(0H#B>!7C7`<01^0+E3@'W +M>09?9!-`9@F`(\BP6U*FNPD;RG2'5&F,TF>0C)[?$'MHS@F$K+IP"1V%K +MK/*2%]]:;F&)TECX0;1D +M=X96![OS+-EY[RF\U^98-B9)7TBFABBGM4?F"O\*8V&5S9;K$+ZI"SNKVFT4 +MH()$;)>0&7($'AX,\+B)XJ'W?%?>EKCF`E4Q+U#(%^'7&.#5!9K9[L*:]*9V +M6)7#8M,-2D1N9G>5M4M.TX#?-D+2.DC2R*TJUHHJIH2QJSQ/!9"Q"8 +MM#81!Z?!YFS@0L?I$@RY4[OZX-9\O,2&13GZ/&KZ[KF,)(JS+2+3.X/U%@L+ +M;;P5IH8._R*P%9K2@6W]6"]P(KD!:MU;!!)S@K"@Z(,X[P+K[0`CC'G2G@YW +M5HOM!8\VD\D!7I#;8/]B/7P0!4(O`K`&9IB3"C#-BTCZ)(+,$I5@:S9;X@E/11< +MM'70B^I3Y`>E"#\?4H$70#(<]CE=^M,[D.^"9GA,P547UX0#LB#J>%7?KUH! +MG:\7$Z.M4ZQ9R9<2,.LH:XNT%YK!`#(>]J&R%"07\@W2]&>&)=9,/H12)KH) +MEB!$KAH(MP:,!]$+A%XT89IFYYRGS@P.0C0\S2V-58X/2@9L9ED\%_>&`R=8 +MB:5>H58,@(42H89](8,+'3;N]"UZ>\N>1['4BV6X6E0=%[.5##Z +ML2=Z17])-F]FB2[WGQ&Z(2^K=PQB?^69ECX*,A<,W+^W.+Q?TN)?;40"!"S9 +MUEUQ@28<80"-)QF1H^9/-WY4*)^#&#K#*JC0*LV#YU+3U:>.K1,O:` +M[21AH5NH?YR2MG.H"(,B('KQGH,!?;)SIG@GE886<>6AW/E;5'8&0OW$!D56 +ME$HS>,,G#9`@,@.X)P?4D,\[_6X%(>U!3]4(=W]H56Z(6G`42._FNI].#Z>G +MD:ID=_J9&G/XSZ\7\Y.(1I!)OP10=[FMRRLLLP9&57W"=M,8O-IN*!T6"!VAD>.%`,CN]5-*S[M8QY19YB0)L$9=C"7/ +MOY*B8.J,Y^[UJ>04&9OFIL_DU,_203O#B;PV]`9N$2NG!R*]68U-6],>ELXJ +M;D\094!/#8IK?QX7K4VI[VK5![$A:W=.;$M2-6\OB%+`FUA3D2_6^*=M)3^# +MV?N^FLW>D$(N8_>>$J^Q.[ZDW'(D+MWS1W"W)A3F>FU^B-,.Z+E?U0D\\+\> +M0K#*NA`S$^(1+7/O4B*T*!+X1)Z[A[=FYC3%H:ED1BYF+X%5C:!7-Q78Y*=W +MZTO)6-+GH'?J.0H]_(9=9,Q[E)K&CJ!G&@!YN*)C!M)9[51'6*R@I*+%Q.2O +M7S5KY@A/8Y.96'@@KQ0IN66*4W#P">!W,$%'DTRAUB952&!9B_=#D6-:^>RH +MQLKW>#";^29'4CK(S`G=WI77)N3O:(.8ZK)W1T9.[KQF$7)D("]*Q>U8CKF0 +MLL>7C[=-:*2"IA>9/E3SH5@O/,(G;P&Z_[A953,B,;^0F1A^AC?77("WZW`! +MSLXL%+IQ=U4K+D\U%.E-W+9IUCA.$NN+=0Y&[A)(CRE[3:)^MJ?V@GA3P@9V +MK'%\<1=8V66E9#"[U0Y`@!%>=JM.=:#1U267B^;5E(T/\((;8R#X8EQ\@.QD +M8QS>%%@P?P8?X(':+/O!BN(IR?%?HUZ1*G'D'G,T/D3M:#RH'.'(SE"6+$X@ +M8&*9-3B(4Y7K/F([IBB>F2[]$1N^6B@T9].*6E%[A"_"LXW'!2#5`6X`[UEY +M2TN[\G3]VM+.Y?(91W`R&5#_+90\`+-A.KWR2'`3BR\W2"HF]]I:&`D8@S!# +M\7MSYJMX!YK>OX:_1)1.!U>O21(<+BJI*.XF:6@H@92=QYU51S(VW/+U;3$5[KTN(70#`(#-WP.I86GE4K'-TJT\J]PP>A/*.8/>(`N +M@.E%K$8C%^GR`DQ\ADFSS-M_J3R6N&;P9:E*#/Y-DJ\Z#()O-2<`YLE$X!I: +M>YY?A+7HZL9A8ML'GJK33K%!2P.IH95&+_V)L6]82(R0#-P'M"HAZ^F=C>;M +M>B8A*)?@BV#S@8<]WU:1X\$V3#ODA7R&71=FM>3P[E`I&@H,U('HM5#K_S+N +M4%'81Z#IV@H.>N#0;2'@A($V8ME=TJ +M>]29$:EC[,MNN9@SN=QRB5%*QLQ%LVEC\Z=9^59R[)VX0?]3S@.63>8WF>-& +M#I?5;D*U7SV56'_FO=NZ@CGH']8KIQV+GZ5SU)CY#2W/GEOU'GD]RY[='!/H +MW0_U%TM<]2=_/N>.K?.N=XK%^"Q:K%TR?.Z&N=$L?X%$[P;GP#Y#2^3<0 +M^65D)(R+77LP-&3@_B:L^!SG]U@KPZO(I0VB:8K0OBKOIO1[$?YC67?32S24 +M\+A8K6+1X7X/"U>%_@8_O(SN^.1T;8?/[3P.PHF8RPN&QGU>;=8P8Z@.@7+ESM4T?6I?>#Y7U_7FC_>%_#_(JOVD+YS;;*X]_R2FV+[Q7ROI^N](' +MXO!+W^[*;$OMQ\U(_KU1WUNS+&R&<.B?">$6V +MQV*:*=IM'7-32_\FJ*[?_'+,UKYMTH^8A?E;54!1',K^F5_X[992'S?M1\QX +MS-$M]1^KT_\IO^4?YQK(^8[CP_IU'_^1U@/K[AL]/XGTZD#\93U!?>_7^Y)4 +M_YBW.SJVCKGI&Y'][_D5%*?G6PCYK#>+QNY)_Y'9I?7S)!O^/%1[_E?XYAHY +M'YYXH^8\?QOH.2#R5(/ME/3E]L/GDQ]>J.F/>SEW@'*T/@++\%/.I%QS;(=` +M$+/^=67;=?(O^8$ISU&.9S;LD[ +M^Y6=9L=)5)H9KJFKT%P/H_AV@8]@;Y'4H&$F'>0%3439ZFF@)&SM=!6@R`.[ +M&SFX\5HE:E-5DXJA!I\`=3@_`2BKTDP83]H]$/7E$C%B6'0.#H$=H*9K4SSL]+35`A3H7N6I>`JICP,V77J/@4QQPU..HY'4VAJ:H4V.*NPIJ^JJC3JKP[_#4@_5J<6L# +MRF/4B`5X"\V/$0)3,B=P?AOHIK:QT01?7'J5'F1AZDPM-H*BHL0]-R=+@"JH +M>(A(*R'^),M+T_$"'H&.&ANG4RL/PAP";A]IE*8K06-6J94SC4JF>Z=2I:[- +M28!GONAP>I_(:"#H2`?;:*HLZPXX-)P?=H*+=*,/?76AFY;&JT9A5`7A.J4$ +M%`U:WICU*TK4#.UJ:UQ;&M0@G2)8R6I9I3A2T$936%>)!I*.INC4UN^8U*DS +M"0*PP;#A5)J9H.NL%NK&Z=2HGC.IE49Q)H8K0G%/A503J8&*U*6U)=K:^G3, +MTGJ<$<9U):C4^2I2)75IFVRKQ0-'$"9BDM3<6L!-'J6I4R4::42"ID]37T5( +MTKQ-:E,0&-0I?71L5$FO8=)7@6+47@E%JI1D*9&B(+(52=3(&F.H$H_KEJ9& +M'X9N6EUJ\-C*H&3;&K>?[4Z"Y:D]TEJ53I44"-;)1YB:01=5C@2U>.-=HJ=) +MFL:GW3*`[JU*4U&A6"^M`[4JGG5.T`&EI8'P`R8U,-0T^M#/RFL`?-$X2H<)$?1V]VZH)"O8Q1P(.I$]&S=8J? +M`1BT.IZ812JFJJXR:0#%PI,CZGM]M3V2:7[.U8HK"314;$K/PIYLL=*9->8% +M_=^INCF>;T@F2KT2=4DI-(P7"`2-4C5.J6ZE$PHBJ%(D%!(#:AEF% +M9A)(6D4Z)VF@QQEJ#`-4)CJ`5U766=W +MZFKIH54PYCH@L!J;9:"F85AD]4I-3G20%R-$`4*=A<]K4ZX. +MO+1J]:2[=3?`R/`\J:VHLH["=0Y"3ZFU`Q:U-J`KI3UPD=:U9WIL?KHL;#MX +M;IU0MH[*%5KP.)W$5-=/FU+G6I^'A,..H`@2B9)Y62D;I7J4%'XG%X]E6=O0 +MI34!U>?BM759TI-FK.:?GNJ/?=VJC&W$)K**'MA7A89+$/%GPIV+"%A;L]52 +M2RK([>]JD,+Z6C`C##5(@JSU2*#,P3+:FJ'8U;%8IK54JNNV\;ZI%PH23<#3 +MH$QF*-+1W<1JC)II!5I4M^D:HF-:Q95G2(:`U,]#\07\86'35/475J@A2&J: +M8;'Y)6"DNP%ZHLX]8L[*%,*02RG",7&CLJLUS?F=56RRIE5-[EJB5 +M)FH\`HH&2R"3`VP.FI/5388NJ4A)[)-BP9%J\0N1N38!"@Z2K>*2JQ8!@L-! +M5IID#7*F9NB],HT&7-H/$9:;^T30,85813E"3(-``;2V%8J[T"1):.4:O6DC +MTDJO!4BPF-7-.J;4FY5FW435N"1:>LK:A1T':[T]J8"+AO(,PCU7Q[IU3YQ? +M<%,%$V^!DUH*T$SH#+*U8KTW7JK55H)&PN)T"O70I.2JJ/IWBJNCZJ5YX@9* +M.P)<32)2M9Z5-5?C&J>9':;FWONS51B,WU6R7&M5:N0'R364M*=+MHKQ=?F2 +ME=4VR3W$+H0HV;5RF41MFI(1VI9L6;,7'/1)H4.GUO,LCJMJV*;(DQMI+,5! +M$AMHJWN/#J(@Z3%5**=A4/0UN@KNF3`!,[-;5*)K4WC&K/KH*9K5A,,OQ9Z6 +M*2$-.BJ\+&,G-<<>UWPAF5Y&)$DR$ZJ*#6JP@E?(6%1D=H;/275A1%695/6* +MF8%5:6%A4IP(8;#VI4SC^J9DYDIM8*VD85^.DFFCXC1JW"3!'XDMSF*TL0EZ +MM!+"9SH9T20>Z=6F!MJN/TS!)W5JNU'40J#O@UJI/"FM-I7"G^HI&L/@FU&N +MW!D)-,[Z@FZ":`V_=F+KFKPUYT7TGP_72/697U#P]8*\*N&QJ[_ +M%;-]0\-3WU7PT%2,#_W1UO&?GK.C"S/SU?1@0FS +MO*.I\S\\KT879^>C$RX]`NN:9U7#T8O#/SZW +M1B\N,E+EU7IG5:71B]N+J^D#CB[;XX1U(%]<(ZD#CR[;]%O[A'"=?3?WN+&X +M7+MF"AT*=]F69I%>N6<*53>++')*GN].,PPC=E'O+W$W.D>S9$]@6=04W-0_ +M77:7_@%3;YKA>/=H?YC)3Y^*\B_\7%5#>'VY56%G?E5:6?D*K`LK.25F5`'^ +M1Y\G2_[^=PS`OX>+K/R]MWW/V_"_-X4/&5;.MJ8W^O-TW;X#(>9[/T*D17#_?VFP[CILO^9QV>YF+3B1AZ+S1]3N''2>-U_ZG'ZX-$XO +MNWS>Q7\;)^?WG/?$)XF=[@J+8Z/Q?Z<&%V-EV.\U<7UYOS\5?>XS-'_&:F_. +MT/(5#'S>M3KN/;;&N>(Y5KRXW;XL!!KR]_%\_U_!6R49'6ZANGZ!H.KJC.(Z +M.$DH=@@CUSK^*YDA>>MWJY5KOTI<24F/7H89)2XF[B+NJ#__#_UPO]<9P>'Q +M??X+SA^YO]]P-_[WN[[A\/I/P9+P/^#XN%&'P;X!/N<#VQ^^ +M[[F]WON^WP=_P-+;:W0<2QT7NT?N\#A_!P_;$%?_.WV]]SA[W=;SW=U\'M_! +M_WMX/]M^'OMH'L\/=;GV_=JNNWOO>W[WP[W><+;^X(3A[OV]OO-[W7,;S=\# +MVN!OOB$+&'I36EZGVP2']CD6_N![`]/;X&SS'M>T))NM_NA*/<]3A_]Q-[P= +MY\.\$R>Z"!'IN_:V[WL-#ON%Z^\]_>"9N")B^/V]W[N\W.^W?P_!_S\&W\^? +M``"L^#=^^)1[^]]G=;O2[OL@7(DOL^P)JW.[$\>V"CV_"XMSV`A^_B>]*..* +M77Q>,03P7:N2MWI.X^<5-N7(/>&O=`CCR%+]UQ'_P-HYH0LOFBY:C5^&ZXES +M*)L]COW+[AR3[_X9^N*Q>JD\(^P)3XQ?=T@;GY49-9IW\KI3KBF*!?/!][Y& +MV_E/>N6P,:=7/7ZJ<\5SQ>,`^_B1]@78SPN@61W1@(%OSC8'6;Z5%!CLB^%=J35`?$;Y%%M[Z0]>;VYM-OC^.!\+[XW7PN8/$AN.!#:^ +MQ-+F`X5`.&'Y[`\:\IX)A8P3^GZB>8(A5.TA#A3B'NH"9'&29![R2E,9`C(; +M$O2^W-ZX$:3@N%>F`S@&X2:L>>&)[4-F7$>'^CH[NNI^K$.?_^VQ^KX8^OZ: +M'PG!\.OL:65_WW%CT>%_AM.YXN7^3@K_(CJS?Z\KWU)^[O8V:CN2$Y_/9N-A +M>IO8:CQ_+S^SVO!E7'EY)QV5CC_V_RPFPI?RYQQZ_K\KF0`=S4X\OC\%TO +MW>BOG8..]Z)QAI28_,X]/O/.R&G<4O0^U5473O<\X\3&]CC^8R7EZC`^5\.H +M]7EYO!;&5W?KXQQF/'[/RMGHOZWOI^)YM6X[&RZ'XN_J=GO.(Z6^/]F:#,:R +M['_3/:CJGD[ZO<_D\CULCN=-O8O\^+@]]%W5YW7$^6MUOR\3=_+[_!XYQF_S +M7'7_#B_'Y?)_H_Y+(G1`@>_EB/@_'SW@\SX.%]%YZ]GM7&HU&DU?,>%U>IZP +M%MO77:N-,X[.NM_7U&LL/N]*X[G99FDPDRXR_/^")HVV.B]Q4D?W?JO'?V\O +MW5/&C4Y7D,YQ?#1%CV7N>3SOZLCE\;UP20XVGWN2L,E`IO3\_Q''>0_Q=_E^ +M2SO%:V$5[F1R*SB +M7:PI^9V%3YML4_;>J%3DT3A&+LR4;B.KM>QP]G)J+C_U-M\-I-U*W +M5L2)_ENV'O$L79A2@?EZ9UR/V<<5D%!\-O\U0!SWS168YTW3V-G96=I551NF +MM@.Q36>C'5,MAT%:'-G7V-E3:"TT@DM?H[!/DIXQM)CL9=@( +M?52X<6-CH.HIJFNL['J'%4'6CJ0`6FCT?4'(I%Z>OEO)A4CVE!(=G]2'3U;; +MK@AMUYC)=@K-=7YL]H+)ZK[C]3!R'8GZNFRI#IL9CJA9GIQVY=6Y2/8NC;J; +MF1['SDNI2I/J\QOV&&UV#M08S'T6+9ZZB8Z_J8['2NCK$*Y=-T*\F`^-Q(^T +M]A0I=4DEV&!(`>.BX^0AL=(2K'8I&N.+21#<>6F/+7'EICXN*HBL.D:1@BT! +M&M&6E&6M&6E&6M(6E(6M(6E(2C]13L]7B)ZM0/MM4!&+,ZX_:K[,+C*.C:]U +MT&W3>7&NFL+ETQU(],"2;RZ>D0N@N72G+>!J]+3'L&[N,S&9^,[!T*[@;ZML%R4[!^EL +M/V=@\S(0V)^G;!?(]A#ZVF!.PBQ;0;':)#&P=V;4P5ES$C;82LR$;BKKZZR/ +MNQ6YD2)>W'"NN>F\(K803MH7^Z[!K%.PFP;#RZ4S)V$L-S(2GMFRI*MA+DVA +M)#8.`G7A;1O&=@X8WV$H+:5IV%)3:#/851W(@!VXG<8DNYZ)#86_`'8V!D?S +M[8.^)V$_+:89+MR]6PN=N2[3;8/1Q]A:PQQ2NA=TJ^C;!]Y.PN +M9D!?1XK_SM@_BGNAYL8?S[80"W17&^D["!K1W0IJG8;#-H/_P-A"$K88&-FC +M]D73_XVPAH5L.(VQ!_/-A#ZSL.G/G-OO9)[,`/S!;W)B?57.WI;W6QC8;#M@ +M7YYL(UV-AWZVEO_\VPCM/MG1M/EU>PH![#^9L$7;L)%&-AS0V#KMV$E0V'>; +M8*:ZY\3L/?VT;=^PE0D/+N=':E?.-A+.8AN^9E=PG)\N=-W@AL^N,;$7+YK8 +M33IQ)]A=TP27=Y3&P_GN\-XUL)T4UN;NE?&-A/));$(2[;Y9)X7-6Q&3;!DC +ML14I%BHQL2@(]'Z?8WMM+F>\JG%`95V>@T)\1,2%6-.3.D2BPN`%(JF@R>4S +M.('C$P,"P,[+@#V:>.N=0'Y;C'R+\ +M;1_TA1Q9$O_`FXV.EKP-QC9O+K1 +M_&?7,R_*1<=A+C&D>HTO!=/91]EL7=&RWWOGS%/_87&9NB;<<^WD$JC/:QLZ +MC%(Q@]6CL:^OP(SL-K&Q#^9+^W;5?VVRZ_B_%V[?LB6ZFB]&'+M_?WI+59(O1CBINC_FMP2_#=L_H>5+MX/Q$L^X +M<%^;FZ^A+J7XT*BOT7`,-:V[7]_(*=R7UJ[VP-CK +MRDGN5P(3"[RP``3HJ!;M@P)=CGKX@!4!-VAO;64O86YT96LO=&5M<"]B=6EL +M9"]U;G)AT1.U13)#`@**D5$14P1$5@P$@@)`F'OG57*P]^>^?M?O/K[](DOE5P6)I+.2@ +MO,I3/3:6;S\U:>Z#/)2:;7E<+*-#P'Z,HUH8+W$PBDVCSLT(S47P(#JN_V/Q +M\)G!*&^F6+PR?17JI7O:(_)XZV6NT1\;9BR,NSSEFSENMEF+WV>1S%GA$(F^ +M*!=ZOZ'N'--I;5,ZDI-GI]E7ML^S6.VE@R,=MM\Z?1)7*MOF>FY4U)AU".\` +M>KW2U.^EV\Q!#&C7Z4Y#=]5AH'E/D%J8'&V7F+X75W_RG*#?( +MV,]5=3FF*-RVZY_DX;97G<1$"NBJE6\`N_37U#3.E>>+_C<`OJ!4%='=TI,0 +M=2*08CGE331WFTE*]YNQ:O^.6@+8M>;R^ZG'+LLNTV"QOV]J/U1T+Q`&+I1I +M<6!C5O?CE.L:!'*2\@!D4LDEE4H]++)9=*02S*4BH%L@&:6:2S:6>6EO/@:! +M+0I:)(S`Y-O0_4@2J4LEK$M:,RX&NI'V`&QI,^@!LTMHMI]J!ZJ7KI;A+V4O +M:;S7[;3/N`;I+=C/O`?Y2]]+X*3.]2^,#?I4 +MM.?,`^927]*G7Z@/K2^RDSSP/M2-`&^X#HJ3_X@=)+II=1*:2_)+\V]5_T`F +MY9%F3L;)/KV5*/\OKD+KS._!O&SQMBS&B88)E^'ZV.^^AC;C[EM^;@^_!YKF +M\#*[_V)&O?JP?>_PO!B;CC;'[^;_QE=Q^?MS7E;:NU_9_A]'Y^G`8GD>_]6Y +M_7O_IBKE=?8^W><]R'O9;OV*P5/X[U\T]ZG-NW%Q+#*][!2?E0LMI7NHZCL9;19K01>!VNJ +MK4%6-7`6#Y=+-UJ`T=.OG>C\IY6`Y;)YOG&EZ#TRB<)COQ[7W8?U/U)U7N_/?,IZ5O_F5@, +MKKO+Y6`>M_[]\^_X\)?>@5)WE=]D7T/N+US7G4?V?V>.IJ[/W?7J=DH=9A^#M]=FL+*:J%8T)6=YQGE7SJ_?4=%P?ZL_B +MP^BVKS\W-OQ>W&VSA>S+=*P4,AWZ#J;C4::U,RJ7/Q]MA-3I-$^6_U+KYW;W +M>3ZGAE?,PD!C[W'QF$YG8W5]_.8?JY^%8^G86^L<'\]?GW/+;FT3^#HK-$6_ +M^/Z^.4:8N\/]O9Z?O=WJO52ZWILN,5)]3">U&]4W?]:[#_GQ"M;L,3I?7>[A +MZ#S^5ZH/L>Z#[WS]C49_WV[1>O.O'G="G8+6,=]E-%Z6?G#S[[]>W[30=MH/ +MX2]4M0=1@M5;MS9O>K<.ZT,_4^,[6[T9SMT/^#*W1?'D?2\!@/*TZ\=#$>SV +M[39]SI(/,70I/TE\T>47?_2_-Y@I6\?AFG;;QDS3N7&Q/3JZZ]SV.HLYN+U^ +M71L>"?92J[>CW*Z=V=^U.,Y]ZE9OA0471C[AXL1C77 +MZV?]:31?MTH2H1>AB<_8,-[&+N/^;W[ELW7HN7@S\[OGWY[[D<'"1-TU7[]V +MX]*)SW)*MGSR+AX)B#?<)[&KKM%%?#^-OK/Z:*:XF4 +M^O!NCYXN^\]FK44_WGV>R?I]NG]QR_[=?\4P?:WY>S_6?RVQA:"L;38W;REU +M<\^H6:UYV4H?NJV=NGQ03S&]JQ=1\V-5A+<[=S3;+\>]^4/GM'UK9E,)LV.. +MFZ+XLCL,G_5OYEM]RN_+<.[V.]]5\AE]?O>T[CH\.?<8^#Q.2^?73^=2:&C+?(T!;WVC3OG*-3X- +MWKTP`O8O5"2SJ^D-$Y+1XTVM!34B]H:$U^D6<+_Q2X;YH3?!J!<@-*%N2A=H +MSAZ92.0G(TCZ_E?>[VZCXJ"A=N^\QQ;_&C/@%O_4?G.Z;M^_]4,AL7OQ=G.R +M]`N?(W:.JX?B_4%V_J? +M>OY=6,9K%Q/Q7Q]-VHW/^E[SWW/N.]#4/XD=C1SY/[^2FZ[=%WW7PU*@HG/P +MND=K'*A=G;P$^WN[/<\/6U#Q6UXF+Y*X&-ZN>@%SW]57O5':H5F&S;G +MA_4\/QU_E3/!=/+U=W).O>#WX#UYSNP71\WE.].M&=D[JY +M87HQMY;=?;]G;^;ZWC:?^OIYVU88?DRLW7/2T4[6 +M*BGYY][;JQB]91,'*B7$^Z\%.1=Y45%X2Y^ZC73[DY+BG(O[XF!;Q5>6[++2 +M^)U/0+SW>D^>>/)3O"3?M`Y'ZN4\ZN7].]$6[TG_"]4+F4'/>)HO5*.B+E5&A*"%ZE*A1_NO/A=*#Q,:/PTY!B*$E%RY5SLNKKW6+KXK;9RR +M_Y=/`QG?_5W?^U83C]XH[5O;OV5[KX7>A=\AM/"N'XK:43EW%U1&#^N?=> +MYF=A/T=02]'PUO[W5CW9^H1>U\#EE=B[>&>7?^K_/0>("\:M[38-M[M4]WZX^;(?A:\=C^O3GC![O4^&LP^JIW/\KVO5RE]B8;%9S= +M]ZN77:V+F?'9/%^TQU+5KZ@\XB0]'NX=WO5AJ?:Y_GV;>VJ=O>$_)U^F_.VT +M75E]=\]A]9?]W'2;#7^FYS?M^CE,WR/0JGZX6^_KI(IV^&G:Y=S;#]L/SOUM +MOW9 +MM/TS/NVJL0E.]%W^#3^CH/XP=JA("]^KJ\KO[SAI/0L5(6/X;-\G]? +M?+_E++G9Y[;W'>I/.?>HWRB7.7?GW2B+F+J,^8[+F.CYB\TM?13[J;LH'1>6 +M2B]D-^EOKRYH?OO%`YG`39HDX>::-F6S2C?#E1(DF)CE/,*/PN_B=:&A=9]? +M0E[W0T^Z4+"AH%SJOGRE=SH:-UHB]CLZ3Q:>CGW>BHG2@H"A;I/N;H44GG:? +MH7:CHBTACV5!RD9>YT%$P\-.*`,"I:4O%(=$9-"A),%))3=XBTQ93D4G^)W* +M<5WBHW,I(8.7B7,&F')A/43N8<\3MX6!224Q.9@MTVL\6B>OW85'OFU@[9NW +M:>LEJ__59?_T'1T[KE'^K0>)TG7)\GJ/O//B7YEYJ![3HY%QI7A[S"G>"??*'OO:[_U/YMJG_%%0>%AWJ>Y8_8^&H47;9 +M;3_M[O_NC/?>1Y4K2^/FOZ>$=ZYY:T%$Y4B(FR0W?B)[U;%UZ'^'Y=XNZZ^% +MT>*#)ZQZ\-.7KB?B?KX\?L7N>[JYEZLX^T<\\QGH^!VH)!=(LHW,,V2[(2!? +MC'KLM'9;'R&=+V8^/S$C'+LS&9>-79O'R./RQ0;+1D>6;QY@W,X^,&,Q(1Q: +M+)YE=%Q>/99TLN+QT6>DR,82CR]F=+W%*A25'1D:7=N8.)8_-E,D>;KG"SI:,L_F\SDRB!>A"4,R>1C"D0I(RZXM'F +M,F4%*42H*7N*DB$&R10R1*0XZ0.@A1N+*4,N6DR>>CCJ'ELQFB]2C./CI&10 +M%&3\W0R*9@Z9%WDK'Q9>^,S+*+*JI15=FBKV4YY=ED"@>74D$QG#4[(W7(4D +MQXT<=Q\BS.<"HD5$,O$YXI%71V<*7S)5%E,F0*9BJP4\FIBHX4HE5;#"#@^9 +MSV3*@Y5;*1XO,2!U4B[Q%LY"0CD4F"9Y>\9@J;F;@V`.$&6R;R&0CXS(R)Q2 +M].!0D(PJX2&2*A!:NS26F$3A2IE5$-63>3D8O+Y@HMDHS,HJ5.CQR8WBJM.V +MC)5?R*9UD<[ECTL69PE8`G-11[,1KB@9P:1RI3+(%$\B4;CF15:71<=&QC*, +M3)N0S&9*#%Z9>.S>/;54\U/M4;"6K>+C\SGFT"D7`_1AG)3)1CX[+LFT)9LR +MU.'1MF4UE0LI]<4W.,)B)08M@EL&RAT=('1XH>@+D6VDC\]F&VHORZ4JZ*M) +M7YXM#.XYE2BKY%N59:W9YF.I0ZYP6*I.6C!4U.6O6)*$E3R]Y&*K/+-K/L,*9HLB1-.)P3,@X+5CLF7LR2%N64$=Y +MK.,CS)$6VAD6]XA-[,@J*66X7*ILA&%+J(U<469*"7;(%IRP"8YEA#`UVQ\?35 +M9REL!93F%%'+"U"W]QH2)89<@XCF4;KU]99 +MO4FXS'Q[=&X6*EDHZ/D'&I;'9Z$<5;S#)2P0V,J02FRT@W7H/F)PR%@&S,W= +MN(S,K<68AQ0MPC-HNCCVO&R>BG"WN>[OI8H+0,M@O,9D]LHF]W>\1<)9[3:U92R3:AHO_0ILQX2J?> +MYMLVZ(^6LZP5GZ4"6E'14GNM*T;G2I%;?%U(MCKO/=1@O^Y=(#S=2R>3+H(91+ZU.^ +MHB"B?2)EG5LG3C50_JH3T^5SNY,P/F$7,;Y^9B@MSUA9KW[PE[)XDU/F"7J? +MSJ%\EXJ@3#X*>G?_'_Z;`?YY3\FG>>'UDNA7ZRIQ`EI?_8G/_C'Z=29_I623 +MG2@QY.GZPBB7?_]OQ#UY/^7I[_^)#E7_\Z.2[+B?ZBGNY.^"?G_WH/M[6NHV +MD45&*-W:KW42W]I-Z).?PRXG^(G7T\-MK;Q8^2RNEJ/1X=GR,F^?CP(3'ZE[ +MZ>^M6.U3SU;QNO2Q7?GOYH/U=66AM=&:#+9#3 +M_';-Y<*]\V&]*H]7Y*S#;O:17V0%9^KMN<9J=W=>;6>+8['S.F_2N1T65DATOG2>:U4C+9?7Y;89# +MTL454M[Y7`O/!AIBZ<>Y\BX(E6'RZUR71$G,,G*CF2S/)=^02*.%ZQIZCK_7-\ +ML:U#&DG[\D>B[$!@%Q!^`*\-]8+D&^8%S#<<%T#<`%@&]\%U#?X!=@WK`NX; +MT@:<&UX+P&U0+R&TH+T&SP+V&S(-/#90%B&QP+X&Q`+Z&P0-0#7P&HAKN#4@ +MUP!?@T(#4PUC!J@:N`OX:K`U4-4`:L&>`:N&<@8`-XM8!6`W\@UD-^X-:#=8 +M&!#?@#6PWU@UP-\P-=#<<&O!N`#7PWO@V`-_@&PAO6!@@WI`V(-KP;&&U0-D +M#:4&RAL\#9@V9!LX;*`V@-C@8,-B`;2&P0,(&O@-J#7<&UAK@#"AH0&V!K&# +M;0U`;B&<@;D&\4L!U>Y3ZL9$2G6B)+KSN`PD3+,/BUR]=$2SW=4=+GK"Q'J-^S +M.J*+]Z7-W:38%BKE`\\?I;YYD_%BU>5J@J=1S3&M:,T4SD*=3!^!$0M\!L5% +M$<:B;N7F%GFF.RA-I6'-.P\Z;K,I3R4ZQ^)=C`*\&2+,KVL]BF;LCOG,`TFQLX><8-H'8V4ZL#FVB8\0ICE4I3H%-/+F]U +M@3J\8XR6@GES*%3`GP].8)MW'9V!04TTPSIQDS[B4Y44R:7XGE_8RAIB7G%\ +MN4>[*3T7YFRE[8S!0^8G',HO-_+R%%VA@2KKSR](KF%_;],4DE#^8N9VB4F>--.2^97S!9_KM6"3$E-P:\W>M9I:-"\B;?H>4 +ML7IWI,%(A5/G&;6ELS/&M@P8">3(\4HKS@OEE915<,F>YL/-B\VE5`\X\;XV +M^&(7"2T!5*SCX5IY6#:`Z%7$8T,&LIS3,M@"GDJSE-W9EKX61?NS$8_ZXB6> +MMDAIL4!\THY*"_USD@HQJ+--%"2NX%_Q4>)@OR5*2V*^.9!4=LK#.Z'BXJ>0 +MU0[F%?+7@6QS6BU*H.E*U<=<'K@=<'T3N-L#"$XP0FC5Q:!E"T/%.,S?9P1? +M@IKH"@=`8Q'[#2?!,UTHDJ%M;',:4S.E?-=@'1RTE2F6OTT69+/%_76DQYAD +MQ7E_V!+AC_*?"];L^2K`V$O,E]6+;U\O6I%4TP5?C$GZ6AN6$.FS#V#T*@+Z +M(,M%30O+FL)E/=J"*ITWJRV.5$=TG9FD(?PX(RNEZ;W#"-EC4I;)`1,I)R`B +M6S@&F:8@6-BA]&7]OTNE%;=+%[Q*.F$LM,I,YI+03JU9I.(,)E6GER<&;J;# +M=%DVL"#/22T.99Y.W'-,M)X!!PDX9';LH,&5DTT3/5W%X="CH)__EJ5$22"^ +MN9O<1RV%R]-&Z"SF&_^-8>46/WVBW-DWTL&<58?D:66=8=;;.7DESE-!/2C/ +MO&K?,'\!(LGO%D;\XQBVP!E6$<8IR4PO+28HY<+WR>V08\T?H52)$@(6HKI. +MS.JM+E-[7D-*?Q]85!.9JU$4XNK!38Y7`A,+O+`` +M!.BH%NV#`EV.>OB`%0$W:&]M92]A;G1E:R]T96UP+V)U:6QD+W5NG(I3D +M`9Y>SLE*@FY3()J9CZ9H]135C#!LX_%%;@$Q]1.>O0"*TG\?)*[*O-]:/!UZ +M]=OCP(J$T?IK7F_MKZI@GT18J&S6T1;4M8'/-+/&G9%NT&'*/0H+V0%N6P]K +M:(K#*"9:50P)X+.9Z5"\@Z/)=DRK:">*-6"5/!SKX$^;`TRG&X!L4CQ%Z,%" +M[&.DWNL(EGRX1*7:V>9UT$/\__W4$2"GQ-EGQ6#GQ2W3X@X:3$L_IT<,?HB( +MF>S*57Y+TB0RI#RV'F@'_)6%\X\P6FCP2D5,7^HLE^NYL/&4>0W.I8HS:'?5 +M`%O.6%'*%=8878XDM=ON1ICENA?6Y)J7JRB;]G0E'+R=1\"G:YE(J=+@=IN) +ME(>:E8KO*X/WJ8DUZ[.KF=G+<+S+'-:)MLO!FIM,J4TET2_M^F:8/- +MQ+2,WA!S[%HC#S90@QZFAF]RG,3/OXZUQ6MF7!67XW[%)%7E5>9%/"A'"B8H')E0%[* +MK=C_*<\YLLZ`Z,=,ZE9,B<,5I*:T1\(/-RA<+M0*H25'IA>C#?U\OO/BYFR& +M3):93#/&FG4M&[)('EH@4HW6G3/_2*:@&Y>3.[TQ^.8-6X4,XYBA4!CZ^-UG +M72=:88I4[CMQ%30R'[VDT'>HS)6QU'J+ +M%J6<\``6Q2SF)2*X4I?M\WXH`V,N/ENXKF%E<([__PZL5DM`5:F=3-/^V*]C +M+9!%URW3M3CCLI+BV<`7%EQ4PFRVC`+"_*2YIW96@_SFW+8T"Q"U^`JHM<#%.M9JLT@T.;?RM;0KD]*MH'4VL_ +M^8J=03WN+&3M![^BY^^W4YHN[*GF!BP,^7-XHL;9/(/()FV%2A99;'3=LW=R +MX?I'G4Q:'3;XF/&[YLPS(-R/7I`%<2AS)]-2>8*ER5Z#9=V^=ZY8("\HJG(L +M12K)%.B]$0J_%J5AU,@M:2Q4BYE$V6>T7HF(RX7Z2"YV=4V3IPS.OYXSB*7[ +MQ4TQ^`VXTHW-6GJ:N[C9V:;E&?7/%4)B9+<.B!S&5?/%Q90 +M1\\2RK;0L?[M0*Y'*@<@3!\\(D,HA?)E[55.7-TXHW#N:^]4&L8JHQ&U +MA829I>\3(&Z'SS:E]]%9-$462;H6<">D<;:U,UA%9%J2OYHK(*8"ZJ/&%;%2 +M<$[<\Y6$]2UU5DM=^^S/WIU\[Y2%[B#.1E)AE%?VRKOY; +MM*)Y9#@R3C5]-G8[QO[:QZ3LS*,^;$`2F]O)\X!LC9U1NQ'TKLD4K1I--KP-F[,C]C],P=,Y.7.(JOP)SM-%2 +MBTHNH0#L.\6E%2S%`+**!+0O=3(LW9<(?0CL`>=DN&?HN9UAJ#(*7SBLXS4- +MW`+]);1%S1\L?+XYB'AD)3LD^DL@HRTG.@(T6DQL[.`$-@0F`[]X1&C;Q%'2E=2*,F$!!*IS\11D +MVN0!YV5WJT::+#:0>DY?"O-RYJY/&D3.#V8'<@\>ON`=Q',\`/)\`C?(Z2V\ +M`<&"(`B80'D8LP@3EH7FZ-L)TF[%IL&2X9P,N9$-)/,49EP:S;$PT +M>2I6JU`D4$V'18=K,B#LD")7)T4_U'=W;'42GCHH1793?@:NH4R$=("50'7% +M$MG'%0$_:N9VDLCI"()P2-O1E>)3(YMFQEI:=GUJ1+;K)W['.\U&W)>0*TK+ +M+*ARN$Z#1#""0V6YCU)GM*>;HFZVMO%:*-%?[]CC^QIG=99)M->L(A7::TT# +M^-"/E\F=1@;K8LNI$SW1Z`>G +M8^AF;-`EW':(V9R?)E;7K8?LJ7YYW(3;KO,L[4833$4]P&6N +MVU,Y$08,`H]2@\WY-*RI1IP'!U93!4E5PE#;A-H;&7OCY +M@.>WZV-=.7`Q`BA50:F4DTU*F+C'J598VI\X8*+F2C/D@;Y+>2L5R3DQLJQW +M@'?SX[%$F8@BYV?'K!YQ!3WRN:12FWK>_HU6U\B*0(R.CT7"CS0P;"HSD&G2KKD\,[FH` +MW)[9PAY2>G1&H:ZJ(.4NH'EV*>GDR7?)MK.+UE`SK:5*.DF8B3"&ARS]['G$ +MY)XK*W^<2Q5[T.`$L]\X.>+!B-%3/9H$C/U;XE9RS&#?TSPY*!/^V[%@RWG. +MI0(:#4RC/3-,;+.(V>F0;L!Q-C!<7?,'&3=9D$O39A;4&5BM,8QZE:\RF2Y: +M'VY7H-9GECO%Z]E!3Z*,Z-'IV+-H4(9O`3<)WWB\[4 +ME-FTE3[50;@(AMN"9]-#<(>:/HPS'3?.N1H:)^`XM7VIA&J4Q,K?E4/*AGZ9 +MUPKW;&N3`D\'%:VAN2:Y^,2$MJLM`]?:%%%C#P#Z5 +M#^@H@T/S)R[I\*9>V3RUE/#-V!+:)T>@*%,WP_8BQ&9HNY7J=^I*1S=W,2BM +MN@GHSE&9]TK("FACIOE0S_RKU-,-9.A1;9KVT;S/UJ,<0+N*#DUM0 +M5B$DQ):#9KF=K+\[4^Z#JN!MSC39LF7\7-EQAT`*1&DY)K@ +MG$XM;JXBW7QTR[QRQS.,R7HM>-D#S1Z3A<,_LNBF*EX2%$6_ +MCLZL::45W&DRGDXV'^WEL3;"^8,FFS*,E4#4:);E-[W48-KHQ$%1I0-&D7B/]Y*5]2;B;S@ZH@2E9.W4QH\\$&:*\T8)_ +MDB.`2N]6D5HN+Y"NWL1NF)ACQ$(G)3V.95XOQEF502C&=A1@+3Z3#.>4>&"I +MV6^(Y:)!W+;*4<1Q6!A=\@;FHV);#E\^"`7@[4T`7EG8*C%,2>`4E:/AG(&. +M4U%DZ(EUKPN"S_PN:I>]'P]J=L=/I)3;Q$6]"#Y]_5FYA>,L=9X#F12?LC2" +MD#C%2Q!KB4],XI5FTEV7?`WXH2UU=;X9`;27)?*5:*IIQMQDS5X&PU"%A-WG +M7-EE"GN60RCAD\J/>G#2_,"(.0+W*>&[*/'86E4,@?][3@*7V_,NVG]%OL4& +M1#*+KMOR[UJN*@Q[&_SZ1#`:7LUMXTO"NR$7/D\:7(7^ZAN.'\&.'N77A5P5 +M&(1;)/:6EH:E;7%Y5U8@G*W#8SR",;17R_66@M[8W +MB_%V"(\ZAO],-Y:W%57RQ/W_&+66X^@_^$MB-?&+K[B'@"KOA!%44B0W&3@U +MJ\7\8X:(55'IV-QJB83M;+BW]=S+_$ +MM_CBAEA\4D=UA(M_'92/C#%5ALF*'R0E2RHHV%H]*[ +MBO^]'IY,>6OI*D_97.1^;VGR5%2"=Z +M(0N'*I!/XV@PG<;5X17AIW$+2*13N2'KP98Z^1%$UJUVX#PLHR[:D=+URF'Q +M1-RTM,+$6X%E7J<"NH$;LA!'I2C$$#G;EXQ'^?.5QPVE3W\C_T,HJ +M3$ZX;64?AL4VHO9^+=PC=.8,16#["`VJMY\F8VTQM>MCR(_14T,0F)J\RD/S +MXDO7F-_(BS,SSC`NL&%J3W"\04/X_$NQW^NF4,XDK0CP+X@H70<,$V%0W)-F.FDC=Y9//*C=0;-3P+:XG +M*<68Y\1LVOCHY6`%T-J4^DP&]`V\897I86G%$%P^>1, +MIS^*%?[N@#N#^3;R&GY\"=]]8D9$3%%&CE-A<6-%YH+?1H^)\:^$X.-I&'G4 +M>1N(1%6X(7TSXQ(^48AWHTESC?&ESO#N,FBV(%8=\-&2HTB\G*?"]*R:8?!% +M2-)=Q"<:V\;%;?=OXVN0BY`YTUR(<`E=ZM\6E:&P1@]4&9JBM0">4]"&/.*I +M`_)'IMR`^)FQ<(1GA)6_%6+@<[P8/\_8VG)*XKS(CP?O$<;Q.QY/&GBI-8N. +M3$RKH,#XKY!G*RQRY_:'#X".6V4,X,8X1:P"6N0\-UCO[?#7]`#6"4IP$[F<1<;AS'+6Q0IT8G0N8MX">_>12?L0^V:#TUC1MQ@Y$8/B+KG/D$U;.""Q<83Y.R/T*2SV/B/MN7F&O +M)X?LEQ-I=M\*;]!-EZ0\PM8*WZ43\V-'P3D8K&U.)6Q(]9R/*TF2YD,7A=:A<S%5U'R;76SP+. +M5/PCTUS>B5/3CPCT+-EC\TW-X,\?T`_9V77I7T%C]+65&EXRH8FHX,O',ZJI +MW.0.:9H+3F"YM1*,6%[',JF)Q[(:C5?1(J+Q+6XP3S,00&2,IM]`V`>1I!90 +M%[U8!<.7:C.+%#]0!-[&+,Q9J0HD64-4"QV+:1M0%"I0PTJQ\[02^3R/A%%3 +MQI4NV/D&\7!;GQ6_Q#X^&^I#7548A?8,XESQCGKF576`$(-C.6K*:\-JL''& +M]4XH+RTH_%C)MZ\WSF>;?K@8!XF#3IXD%\RYY9E>EH6S8QPX.I.H:M#]%&&* +MP"\["K?QV.O;3PO"PZ7=Q2C3$9!M'%F>]BVZI?HFB-HU"I0AX&C9S<265VS! +M-[+>8ED_N`7)BDRSZ(.3RJ-;5+AAWU-'D;=GV*?Z:#DFE:^9438J760W< +M?B2?1I5PG08H1CPK8L3R'Z)]@O:D8O%&R$OH<>64\3/M.S6N]Q%*+&HK[]D# +M46"RCD97L(D7HPP1U;+VNRBQ90+XL2'40-R#N0A4X50;&`YYY;K&5;Q8C+A8 +M3$C>G>,3:&$/($`%74L!BDO-2H\0.#R'>:89U./]--G/++E4,"UJW9<]K*LS +M+Y4K0RXB5G9?!-O44=/WQ2:*P0_I(9C\99?QS$E-.Y7--8H66.R;&28A#@VB +M2M&($EEWW%-['3\:G\=H_>:42)DT@QYWQC7=CW'N_/G#BHKN33/$]I,]7@ +M%\UIY<+MJ0EFI3$@)Y.RQF2S.HGG[1'%?>">P6W0K$;O64ZXP`J"88#%J)+@ +M!#.U&SPT^CCTM>)Z&O# +M?3KQ,QKQJTI<_$#AM!K9)-?0T$FF4+:,9L:?IJ[@&S$*"IJAQOXU$`*5JPRJ +M.P@;87<3>AQ>QIV6K-1ZX3W-<-7Q4D/`X_/KA/*UP;B#6\#+QKFX<<)4:DP^ +M@&LP&WUV$RPXWP:O(>Y#5G#9@:\L<:<-.8>?EQ/:EQJP)/HX\R7$\>7#<`:W +M0;IPPG[,,.&H&M(D;#CM_J)%AZ9AU2^1NV_7*[8\>VB6"0RIPAG%*6S3!%*X +MSV;Z]:["[.IZK;=O7.*177+>94IC$2^/+-H44&ZY\71UVHF3@1)ZHEG#`988 +M^3]ZCHZ;0Z1@0%`^(\DA:@/`IE=]`.B4U#-\(3R6YBM?1%*/%^"B*,9K;MPC +M^>ES\V"6>LR\Y>E.(1X-3"/7Z>1@Y4QP]''^[1T:HEG:DMCEJFM%$]GN)T4>,[=%&)O;?2!9DLG6_6,T>.V3R'!D'E&J^MC"&U=.BGZWYEF&,\Q5TY`W +MA$UHF]69)Y5<:9^<09[AEYC?CE%S=>>1_F"/I>%P/\X(90AB%>M@GB&V:$YP +MVN"3\`=GH@&*/SZVF4]/%DG'@_"*>EA%O!]BZG?H/U5]-Y0*X1U1]YU1KJBW +M5%>J%U4NJEU165811;G>2GG+0U=6D/D+XI;J#RM$5G6!2DZ\;ME4?)BR=%J: +MVA;;UL1DNHT.]QO4_[-B.S,5WPD;7J"NWZ@IN>H(.&D&-Z@Y-9F6A7V^K?%G +M-'U*,$_13RS'C;D%.B,Z0:"KQS$'>(F.5*?<40 +M_2YZ%01MZ.W00S:JEO'DJ6EG));ZJ@/':TZ-KZDCN=+F52;0!#ISY3)9\<\D +MWQ@CYER%VF"I3PO:K*ZZ/I<$*'2\^TS''YIJQ_=)CJ(I9H#2OHQF,P0JKX5P +MUL5PSH(YCAY:J7#G<:Z@RQZ1/QZ(J;5L),KY\Y]5HK+>VSR'=:+H0_N8%MBL +M<,X"WQ6^S@1&->5P/GWX95#=-FG,_D,*PN\1I!6U('17HC;U[\+]$9QIP<3(H?I1L] +M8W-Y4<04[O(U"S#7B1A-J:\\G:Y&I/G%KRPF9QV-(M]V6.9\(['V'Q6YR09HG!D%J.)LW\WI&XXSB$GP##M2% +MA,`+RXQQ0"^S>MB%\YN[EP]`=BF4+Z\1:^Q3NQ$)^SOM#$MU#]@1LXJW4'Q` +MO3D9*>OJ"Z1;%4"'P_N\M;Y+H427Z304#&PI9J6B.6PWI@H_YP-';EZ/)&Z3 +M$>8DS?9P*SV7K(%Q0\IP]KVSXN^7[;AQ/EA^UM**2DGN#419?5$;E+F@%;6Q +MTQ?ZTE,FM_E9-!&&\<3?G@QOW[^*( +MA('4XPAQ/M>D+[IX1E:[*8W]2V'(NR0"RT+,7^F>>U>.0J[#)L:*F2/ +M3I2$LI1:H(F6'NF0#QQ;_2T#)4KTH),7UP23QP][(@SG"BQRE@410SLV89B3D]T9W5'R:'UY%>_6LX+H7Z +M0-Y;#U=,BP6VCIC7!"JQS">"BKP+>[:Q3MQ(\&'OF"K(>QI*<;QR3O`!O;^4 +MF@0W(]_OLQX$IN)A4/O'L;Y"UA&COF6W!F[B+QA%V`1E7SY1_Q6I(TG,K&`, +M'L1A+N-,L'XXGW$`S;D0F9^^K=.]4?^11?N*^.*4[94)%_8W<-KDL]E?5L`, +MV$6OH'SX!$N8#]Q*=2J<2&@@^$2SB6Y2WB722GDH&_!JZ)4N*+B#2S"NG9$0 +M!T_73?AB6Q9S1^95@;*/V\LG/\!5X5LW7U'G79NO1&9H]OM;F#T>9C38$VN+ +ML9A2KP;2?W)_5@\G$C*PTG(ITT3TR1P*"-/?)&4'&UI'X^SPU?/=4;O`IJ'9 +MH8%JN*]NA=GHI9[HSZ(05G$+`7FE/)KS^>_,9.^L&OD@"-Z"XY\W/8B[J=@* +M,_MX`]*?1:[+@O(!AJ$L+RVG/-(NQ>#)Z>*^B&)`(87,SE66>QG%!R93T#ZF +M*$WG73+F%]C\MK`;3$(-5@=>K$":"&'E;1]>RM8I +M#S/`=T:(;I8@5D\HO3ISY`=L=!NMM'1Y55."'GD%X^NV]J%J43/3WH=,+>A+ +M*ZCRWJX?7=F$#&QE19GF^4!+7-SO2VY95W8ZKMT^68A`#W7JL;.7G'PO^>TG +MA)V24S^'1I3SXM9YQ^IM!<[YXCHM>_&Z\`P^U]+7\Q]&)3AW+^#@^]@_X;_2 +MT_+DX@TX=)2R8D:P"6$&8AIC;K)4NELQEPC:R>Y-0GS;QY#;&A3FDXWWC:=$ +M<3A&F(,$V;9D]&B2GT+VY((D-2$W:Z!_`7\`FO3JO8PGX/]4..$KLE"YJ1!\ +M]WM2\$QO:A^/PA^GK>W%,ZR,IH(A%Y4[6)0[:"SR*5?)(FUZP:TTPS]N53`L +M?,M3FHR#4M38QTS!>XLRE.0H!JS*_HE:.Y-R=:NF&'/5B'#CWD<6XQ2V&7N- +M72]J"RSTL/OX&L'2G.F_GP=*IT6S1+;E:V8_AN6"I@*58M:#63SI+92`N5X_ +MC-I%FK`-%QOK^:8?E@')R!ASL:+C(6%T;`A^`[MX%IS$&G.L-*`OU#:U@<8; +M;Q*GC##UP%.\P%Z38)EWZCUK"Y+DV^:MLHL&:8\Y:3MFAE>S38S$EJ9*OC,P +MY*L,Q83Z"WGWDLJ-$.6A?EEJ`ICO@"X*WK"DPOIIXKRYK,+OV*YR3MY3LW&X +MH8QDW1R63A])EV3=:.3?5[#XF.G[$]5-/*1[>%D\,>>*B&<&9+AGF)!D]IR, +MR4SRBY4>/Z>L?%;=!Q68@@(.J#'4%]`%2DPI]4;%"8XKH!LK47Z'-PYI97 +ME:.:Y;#\*^BL<["B]W.%#'M!FE&$,SL# +M?\'[\44`U0,P!I`;ZJ-W88D6M%E`8,F&$+7UC%]'=AZ+6Z,9.X%\:!6MH+-= +MA36L&$FR'#"PPY:D*7%FLSR^,?5)93CHX$U] +MW\[LW@BJ=]JXD_85`HB:44?%(BE[PGQ;P:KBPBL*N-3K4CS-T/O=LQVT_"'[^7"[ +M\2!3S5G"1'3D'"Z.;+Y!?R%2"K=0%2]UB+F;`:9HSC6GK@4$'\5T'"6X:"/* +M[U%\WLD13I.:/.279=R[PL:8P)O.')T+IW2EM.RDN2^*"[73J/2.TY?V*QRC?4P;#]:VC2;ZM\9VX[=" +M>I])1A\IJ3BE^VP)O%(T.?)70942)&)0T-T%%@@4NL@"I;G-$8T:`0<.Q(J: +MBZT@YC.1%BZW(X!?0@5=97-W>TJ->7=&W2I[G7;FHE)(^,*7IX9G9RNF411#@)]P#MW^3Z?4^R +M1\96725?SK1]0:\M-P),;N*$XS_O-D5=D[J7N[=%N[9?,6F'I()!>W[`$]>< +M\>IVY6]Q1W&A:G8+ES:ZYOKD,RJ%<.SC=7(4E4*4B@]T685.D!(W8OWZR,^\ +M+S0G>"_(`,D&F_H;>J)5J)[%YYIT6/W4OI]W]51/5G&6-\<#65*S5 +MQ\:^=+/W4-3\1^8G9IT[(GK.RI[+9S.EO#-66GNTU*^MRBS<\UXN4:?<-Y)8 +M>W'J6_>7(S<`ES+D/`F*@JBWS"I_0>\E-7MOY\)O[D(M29_A`=BKL +MN7'RHB?JZ6Z\>>_/RHDZP+.6[,HTZ?JTWM#:',:<,%@507U&U0%4OE+BHS*] +M!:*XJ)EXW>D3;PL5/]P"41VYUDLN$6:RFW,3TP5=2TXE&@W<;@/"R^0/:8(6 +MM;OHI>[<@$!E>"N1**FGMH10?DW$1=#D:S! +M]1U@TAMWUA-->/Q+@F/90&>:L;;;;9JM]^?#G%.=E.G%T"A0>!JFP4Y0L\(" +M'[P7`@A@EP+SJ137"I=2SY9@]J-NYSA=PN3<`*LR%(H6<@M.#>0M:<4K6H%( +M&EU:^4AB`L0"2TY8%@ +M`3.,R]+\B!/[,1FX7G.2,35%IB[^"0FW@_(@2IA,WTE&?ZBI4Q8YT=VMO;/' +MO:`PF^""@Z8#ZPT=/S_8*BEJ@ZW-;>6OMY_$&XU-!=?;FVU3-GH\@%F@47*S +M]BS,)R86,MR?C[IVBA4/L8+(+ +MZ;:))C)VX!F%\5M<*F7Q$5'/I;(X`PUYD,^_Z$XDB(?)B1SSG^6A?H1TN?+. +MN6*^I`KP3RZOSCK\U#/:"]E+=A_6$J('OB_^7)E]F3F_@WQWZ!]6@Z-$GBS/,+IM1^R(X'R7_L\ +MD_^/F;.M$<;]W-;A!W(_0W98BJK*?,6?DIB,.K^RFD:`J@@E`-2;%='EKVLW +M<4'G,^DU[S9L*4-[/(Y6F8''&@EIE!_^CYT_PEG$\RT1!TH3"T&IV*"<7063 +MDVG,=/[:-");RV8L%R__&[#3'_+-^/S5S:FOC3;D3'([\%BM;QR_!(F3S?D2 +M,WM)Y2Z++V;9!0+AN:)9G)%+"><+N#][E"ZND]R%L180TB7FVP55'4.(<9JD +M[7BBNCQ1L#@75FY)%"OB-(A4S/'L=/,T),&P*TV-FS$0P;D-YN3^QK%N9USB +M:]-'.?"@<+$HET8"+>-WQBL5F>A0-D%[,*I$)I,30.?.>%8"_VPJF!HZ<*IA +M$_/"RL*1YO/&0N4D^D92VIFW8/HA742UI-@#Z05<&V(B_PHJB@6_<*'+Q#F?A%;ABTG*%$ +M>J%%VL9I4AR0@W%=9JAHP?QM8WV2=$@!OB0[A,R^&U(\8#) +MQK`:=HA&>'@@!)@Y:W(7I@[R7'/CX<;5X?'N@KP)3>J8Z;X%U+F?$!DV4<:U +M"]*BM><4=ER;$"=$F5SU]2-J%'`!0G_P!24(GBVN4BDC6TC78711(>-,0=\% +M=@3/$R02:BW$]BUCJX]"UW-?:G&S[.P@F+A$N"%VK2'\=RR>0UJ +M8WETA@Z"*;I1%:X&3%CQ+5]_VEU+)-YWF-[/.M!CJL%/*245OWR;J42EU\HK]?'/ +M\@O>M#7'"N!QY\4X)-FAV-NM:AM@5'^D]=9XG[$7E6A3'!<%VK1BQU&V7B_,M`;A6@94)K6K=">VT6;P)#;&WT0,^IJ6Z+Q'VV8FFX; +M5KA_G!C*8#E%QX-?2LZ?HYW]K.$ZIE&2!DL@2'QJNE*)SH+./(^\B[-JYHW> +MD:S +M!69,WWD5)C)G4:#"@K(1L0>?M(3X-%0'<843=Z51_3JTM])XUL4_6RA6Y+<6 +M,6@0;B%J;&&J(-R"D*2>*;'A3>8_!$[=;(XU$6>R"=M8TKJ%9&P\+,Y,5]WW +MT)$C.)-<"9?TQ;O6(F5-/;;SCG[*)L@UY86_L3;7U>_,$X6RBW>`LBM+*)$7 +M>#\JQ)2MD"PJ5[;3?+/V;LA!B`K-8E:XN-%"8NR4H@_KJTN22)PN@HYC./"X +MT$+7,'(!>Q!-&@SS^1"EA/%C2/[HX^H-<""$Y0*(@AP3`,PE803Z(+:RX'F; +MLQ;OF;K'6:_Q`N5PXQAP)WOE<@B5*;T#7T77M]LBGHAEAF\(HRMG9'&Q9AU: +M65LA/#3"F=3:38TS7U6E\4T*>PK.Q% +M)Z@U:&U15J26QJW3)V037$S?B6Z#@=:U-<WN1.@!:;,K&E0(/.9H4 +M++@V`)W6BWF!10-A"[!UA[>M/JU&!:&""^I8Q&[@V(+?CI8TO7P0I6!5'KH! +MD]S?S)XGO^1##+MHH[TRT9B-7=)-A=K)?(+5P?R/?PK\M7?PV,C7LC_E8R-: +M0CV)G*YQ+.G-:(%/0_)^QBC:VJJ#I;L"*/`ZU'U! +M5S;13OV,G6@L8FT#:MB^##L$KB%<`_ZI6Q+Z4JR%6`_O)55+T$GA+1#A'AYL +M>+H.GT>6*>"QCIBA;9DKUB=NP-0`VIXO=0_\K&9V$*P$?[$JXEP4B$@IP?:I +M,$M,E_5C#1XX8.TK\). +MW!&OXL8O-)/H?DI>%#,YZQD;V`_>L8:6#D)!^(?+I?" +M.FKOHINQUO`MA6E?1)VVXU]@V^07\%C#>V'ZH74#ZI+\$LREQPN,'P:7#2N* +M6[2KHX/@?5CQVXZ5N^"FP'6L^J*]F]BFA':3&M\-O\"_3#ZQ+Y`N2'S"4PEA +M4MR%[0>W)>NE`I;%)W'#OV(-G1XRPZ?%$"FC'7(BVD)7*D[9D:]@;>@+_*'\ +MY+_(6\#XI+=)7E)H2#8!Z^EK4GM+1I=^Q#?K!\8/',CI?;T*1PZ[P6J;2N`) +MVPHUJAMGQ?W0^-2V06Q#W9*72L26<"S8=X2D4OYL0:-#_@.'+#W@>.%'2:AQ +M2^#KJVV-7[C2L*3MP)9M*GI186,#]NQ!L0'^YH]]2 +MXHX;H/!CD9E>&J!00[74:H+$)3J:@"4*%,'0W?OV"*-^GH)6JKO02>TT&`[`'JS0*5 +M;3+1W=+>'(]F"W0DT_^QQM.M_8K-)PZ-(;0%GP_R@P84:"FP'9W<3N[$.OR6 +M(3XH)*%"JT%2E0G0.:K8%X;"1N)2&VA?D"3+\J@7KCMP!K-I6\+T+"2VBL(: +M1L(%P"S%A#>JM`]D#<0KZ)I!)`W(*U`^U(B,NT'$N9%5P4VP19#=`G,/@`;J +M%.6!OXF$L]_#S2WZ>\L*/I[-'EI2S^"^$>K$X$W\"-J?P&*;WY;-@O#/D;YL +M^FO7#F!/J0PG;03;$\ZY_Y)Z4;WZYJ9KZSC@D:=XG6]KVW5!KGP()MWKM^^P +MZ^VX*.5>.-Z_%Y$%2GOD8H/PVXB'7V2GF#=M47!@EX*=4#Q!-_O*GVG`BF+4 +M+S$SE-[_P+-F6X"9*3J[XH)&3Y\DPS%U49?[`]#.Z$UDK"%>DL=81;/#;6@W +ML*%5=%N>D;PA[TYRP4/UP-]"8`^&00EO&N@G1#T^2P!^!8`O+2^&P"V*&V:@ +MFO)A=18"-E1MT:0DQHP<&%A:0D/C]JK@W#W&_?H(1-&E8@*;4L>)X!SD7-9R +M4S%P5,058V"$^@-5X*4;M??W\$KJZ66@E;[#U8(0:Q&I=,7^"::>Y=.FTP*= +MTM:"/YH6*!3NG7PA_71JP4D\!+/$V3N-YJPJ(8;G5Q??F4M"P=+66#_53\ZV +M?>I+=Q()%@I.Y7TQ.7CZKG'W4=U+"3/+AYOWZ`^!"_"PC;F6%7`V?)84IYQ" +M?U!)G:$DM>?.N*C^/T6$43^L-55C.AY`G@D,,312T[&:O7`H9JV]IAD-?R-F +MUGSF%74J&P$T9YTO*6;)!*[!QU#TU]T*##4!I]@AYD)`F\3M"<+"1\^1]Y3A=B/5B3X]Q5K@&JA!*U>'0=I#6DN@*=2W<4P&Y7`[%!#:J+* +MJ.6LR2U43;V%7'=659@_- +M382-4B._V\3E[".LM81/RV%).W[\S9&A*3?FMPG;CM[PUYR5G6.7K,*5QK"` +M[KA&XL"N)7PE@(WKK0/:`IXF.#)+028-I"?U;B9^S1Y^$"7!\B#:@INO@,8M +M/R=LNT*GI$\/WS2%-L$*LP]?P5\C?';1-8':Y#62L`E/$(Y.ODMDU2;=;`.M +M_L`FK#2F(O)1H,;8`UXKZN(_[M>(UW6@=P!3Q)?.)+05ZP-?"9;!,2V,21]C3-T%[(6`1? +M`GBO#3]@[`K@ROYKH$_F!']0HGYZ]3#`OX6KKJ +MN/6.0E,'NR6S_R@X`+%`TF>`0IX/J\D?W`<$%906QK1JO\*$QKI':'#!>"N$ +MT_3EK`E6'>M:C`;O7QUP-?$^Q74L2%[-<;7PO95)N?KHZRM=$X4:Q86&%"#; +M5T-HZX!C`H.N++?]=`BUP5<#GG\:3)'R(,83-;!Q(8[8,@N(JVJT/84AR+3) +M"TS[5J$;RU"395@:V(U`7?K(:Z'2S4A=.LDDF+R#*!?)61?5`ZP+^K9,J>0N5M7!^;2MJXKWGUMNXK3RJVKA#O-K9&>T(R;Z6R1]Q->Y6V +MVH[X3`O[6<;;T:/Q7DF"-PZV']^MMFC>=^!);95M73G_O602M0>?MP7&#%_C +M+:%U\"XYFH_\BD-SFL2A^)/"$9Z!5YH]@#^NE"DZYF_J`]MT>>M)BZ>#TNY* +M5<)3[`8?J@8+P648&7;NF!RQ6.\='4^V(3^[U2Y9>M-GUJ`4@,#??AS4C=*! +M!&4&7[P5IORQ'Z5I7*IXVM*Y;+H.(3R04\ +MIG;"28Y;VM"/A/368*J$D@]@+<`IY2.>K)&RX6L!3@+?>1\^%H04X#'`(S]' +MUI6`-ZS?'"P1Z2UA29-2K#L6-2-5;:U3%Y%C*T).GQ$G;QN-9%NS60U:67"$ +MDJ9L"'@%."Y%$>>"\585RKEL(S]-GGTX+=9(5M0?SUE7*2KZP1HZQ"?@K +M(Z_A61)T^(D[5'QP!+9`&'"VD`&HX(3^E8'7O5@3P:PV^B7<"W&5[^"`:1[T +M`KEP[/`$;W4Z;=`WL)B'VP6U!3RW,[5R-D`M."GEP/J([(+-`Q(7OAGZ-//I +MY:WTB%;4&=>U,K]H*NT;\K")YU,L==2:.GQ$GEF+55R6T585UI>J58HTY" +MFTI@1.@*>8OR))XNX;3#/58##A7@'@:I!"_6K)3;0X@*O-&?N@>?3S'+T0F8 +M53%Q(]5@-$5@5 +MD9^R,`1MLWV'+]`$;1D?DUX3"4R]MAQK;I-,VQI?]JN1JL1\8J98T=I$:N"3 +M3,RTH00B'V;/5R-[JQ_BRA62KD;6+::`"JX),Y@C_HA_-@0M,X`C]T+OU8C6 +MDC/WYU8C56K"_+JX:@JJ4-71.[JXZ_;5Q)T^)7WZJ+1E7#>?54OPK@F:JPZ] +MNK"?BJPO$U6FX4'L556XIKU5)EN@Q;:JJW%RZJD;6541+54C?D_TO"ES-55N +M,^&_K"%C0L=52-Z9)(,!50VG?VZI+ZJL1LF_I>[6Q/!IEEG\C4I527K3^+96 +MK!G-_2O2IEOU5'7%54371HF=_5!X5`@).NJE)T>']6XXRU45:?/U01XJH1K_ +M5!TZM4#6-:0OH"YU4(SR22#AU0-W:F*F7)?5F^+;VZJKL]O=JJL9?IU5P">: +M"TS\I)*VGIUH3/CLY-:S[*U?\KH6B%%'.G>K*[9[C&MLTL_.U56["\I99_Q" +MJ!=$=NVUKL]M).[7H']MU`?I/[7A2TR_JW<'/?U=@.XBT#]\%.[:WA):#A55 +M6[(V;^1O=JJMV#HUL_Z8*=UUDF^R;IJJK=`WTFJ3$>#"!6I:__61,4.S(:\] +M_$IW8W8)0QE^6J)0H1G@%->6^,\^G=8;TDFVK)8QZ6JBMUP>Q>TS[+^KH9^= +MJA&]`\^G=/1A"M8,[556Y:O-4(W;?U;E.RM11H(:L">@_CKVG\3K:HDG^#S3P@NE4U;C3 +M?'`H3.-(^BIJW%NW?EBH\2ID;4OQ+VA_(V5?B-5`<"%@WX-D:N)H:H.M2&OB +M?A*=Q33B6?GTZ-80+M5)5,GON?,A:9]^:^LL?IJ1&[+\1OBJ5+\94/]J5\ZJ +M"J/IHQ'UUD^K/7YK9_&T+6(F=P].!KJE'^3:;_1.ZK1??JBL$*.;`3I`%8EL +MZHWQU=15%<8A:JH3)Q'W0L@-\*"GC(UY*:$*UC>R`IPN^=4R/Y83D-Z.IJPU +M=L2D"%,U,;=`&U!944[CL(],;^Z"G#OMY*<<*/&^F!3B"NQ*;``TWE@:>7-W +MFXZ!"Y$W<:=QX/C/9%]]J:\%/&G[M^6:JV4S-?9&[D'KE3$J4CL'=QM3@_=? +MA=W#^N+)^R787;/R%)XS\/72/PCR@NO4@^:=:8.3\X(>O#X@:4MIWQ^2\Q^` +M7K(4K.I$I2IJX52'CVZD-NK4A,Y4DDX:KP2AO[8_RM+'#%CRT(WRXUGDO+"] +M&HTQ[/ZE6&+J:GH2BI.//?FWBNT74A"<+2[5%>3434E<5G8JBK&VNE25Q5CZ +MUGVDV2I*XF[O5!9!PE'1".3#\)IXJ8:A@<8%OP5#?:@4]ZF]5;/V`''!2@-K +M1>^5,AQX7FAW@&-"PX*=]915$"."NQ'[X.0"L2TC]DA3WM%]:/^8.2"\+ZH' +MG<,?S4O/!R@7X@H%95A[U248A\E1%^\<2D`MR"3/ZGG_-"EQ*E0'V'I&04B" +M27ES$754W[T;?>#FPK<'YH.<"@:1^&"IO%[[2-[K0^<%.O@;U0<^%T029V0. +M@"F%H?JP4]X1W-(\D"3,N1\\#HPLX)I-94'2A8AK2J,UQ8.G"N;X'Z*\13JB +M)NHV\T&4"@98+@$> +MX@ZP+U@29M`*>\:ZIH]@!EPLRM(]8!UP6(#U(%IF[L:39@#L0J\U%23X*@!Z +M`3LQ;>0;31Z39A?O3Q?Z`?1"^@;<$%'L#'>$DL0^D<)V@6G!(9R"E +MYROE_U<2K24`E54JFE47'ZH(^59Z-ZQE0<"[$@P(414&WD*&D3PR=P?&C>=2%/-`UQ\5:W]#X-J!BKFDYYB1NNQ$>P^*ZG/][$ +MC2U/$U<=H0:\M\$IYI;6L26S;$-E6*N:FR+$C5=\2=7PC7ABD9FY)LBR&]C7 +MPC5%;/X$&'"GZ>FR93UZ/@%F2S]DX2G@Y_JIZK:-8^*YA'?T]NJ=S;XKF%MJ +ML%'N+?#M;^:GM>/_:"GJ:^/*L+2]M)NKYY+AL1FN$&$"A:>-/<\BL+'T]7,+ +MU.GJZ<)?Z>1J)[5B]V-BKA8OU>TJNQ2^E[:\.Q>CS^'"^(%:P+?'I,4%Z()$ +M_;=H<6%I'`4NH*>%TC2,]V%-4->]JX7N'>U6;^%Y$ZBGTP\GZ=/$\%[2C`I] +MZ#I^\]["]JX<[\'I/51BO&5![#O:N':^)Z(W6>R-Z;TJT?['LC:=;/\D$FB-C&A3PX-O%0O*K1_\O`EV' +M:P#4B]"4WA2M)YCR&X3RKB6X]Y(VS>B-A'DC2 +MAY_,A7(/G@9$*O`DIO7MKR+=V>2-MFA3Q-';>&E_=>E<3;];P1ME2`"(\W]> +M8`9453(D:'!&AN0"!"""-VC;;BXQL0%)AY)#"D$$!040$Q*@H3$$2$@3`$!P +MBC@,"**VMN`5%L?0-MC:.`3'#')#T%`0)#'#T'UONM\JJW6]U6]\YR8`?/WG +ME]?WP']_C@23"K34* +ME:_PT*1KK7"-"PI&[BN$;AULC15<(VPK;@RW%`QH/ZUM=MD=G\T'XGQ[:NMM +M8D&QQ$4Q)CQMZ)OXNF2M_>)6R-DF#$>F<%>@#W%;2?7B5H*"K@Z^!TP67K:R +M%R]QH0CN+CO=?6TKG[30A-%/U!UL-RC,^9R)#\T(FB_ZXD9BMD.R/ZP!-1Y`J>G]:XE=#=PB8GWQ/1ZP,(^/:T0B5UK>UI +MZU?7@EH0X(]<'-UHC4T*,\.M"/8!^&M!KY60HV%'6\PH75PBR%[/P*T3PQE: +M2O?HJM$;!UI:_UI*^+TU:(W;PJUAA4KW^EK(C;6T]`7U,(UK?S0UEZT&=G]T +M'\0_'/!OO`Y4@7#E?>[&%6KL*UE(6MPL$)MCZZ[*`36UK8;K";P@!-9A"( +MD=KA3QX]F$2L_>C")7B,4DR/[X%9!]8"T`VT/YBV(`M(/7*3!5@K;6`VJP1ZS6TK]_?5HCW!IJ1'L0::@3I#L]Y!\D(IRL +MQ!AOJ.Y45'SPB!![V4(^3`14<68B.3^LKMV!,O2[K*[5E5GZ@`FN!6%[_@=L +MOP-$`37O/0]UF*PNWHKP2V<@TU)/TZP1O\]"K#7W08ZZZ#"=P:S-216"6AZP +MUE,BR5@C>)6"-U#3.O%TK`:VUA-2/;^KD:)560$I?H,-)U=:WD!-72KI/>[%>"6O=834FX:KD:S<\*L#MVPG[ZN% +MA0==5A;-59K*A/Z58C<)Z%]98B7C:U8-J:LFI&XRK*'*>A?6#5"LA5R-=R`F +MKPN":M!'MX$X"[`5/%E*PNU7JQ&\U<(J1&]@EVS-7&W%JR:DGFX(C:OFA6^L +M#K-5@*\58E\3!$M@()-2,OT$1LG!)J/UO@B-Y,$M-02[=C!$:0@B-6E0JZJQ +M&X+I=N$=P\L'6JL^W`\P']@%Z;NKIJ0_PNB-1+A%1UR#I=OV&_K02:C]@71& +MG.8%YD$.OS007"=$OU3HEN?T'351TY9NMDY42Z32+=FO#U:P[E0]7#LZ^N%SB-S3 +M@E?6O7!-G&ALQ3/5N"YT".O&N=)N$7RCM:[Z!T/ +M@-,,-9>ICC@M[K=FZR=2^.'2'<]`Z3IW;&1XX5D':T"8]J4 +M3'J24+OW8%L!P_/%HX>/3"_5NCH.HJ5^Q<]=JXOX0[H#IA%9!Z=;6\\AM[UR +M=?(XP7[M'W)?>&:"&)YX5R!\KG"W%-+OHJ,)(C+YV_0=#O6!?-,(.W1;^O.# +M?2/#0#-8$98'[5M%SED5+S2 +MT/%S(KH>:,HJ(E=RR-MN:.]7YP"XV1#N5OJYBV"6^SECP +MO/#"^[GCK0\\*#YBV%!O?+%M[STW#W:>62VOY]3T'?]\L90OM<'E$;_/+'?, +M,Z*>*-8L'`CI6A&1*7103^EISB-][)9+A@U^)8TISIF/>$ZK10&2]G%3;1RW%ZNQG..@OC@=$S,9J"I.'V;\Y56#*9^F+T +MO-)>F&VM8E'(7H>(N_5(V7T>#7&-M%6[YT$T6YOA\U2FW9.4Q85M.K8,/ +M.O'#/.0S0'_F(.RHW*/,')^B":V8O<*%<.,L>6N41O_I=QW[+FCP\WF!\4B8 +MAEP9GF$Y]5!#-&'IV'V6Y@\*T*7P:2'3R-!9+/G\D!6LF8@S#F:)@XG +ML\AFO<%FTS'.NF6.(#_+1ZQ9G5(<\T`QG!NV$@C[P^*'G>\94-.ZY(H^7/Z[ +M4U6LL'(8ET;!$$5P!.DS&DW;06M(]&DXX?-<<':+?AQP[-A^QIC";8'U^.31 +M9.&(/?T$4M&7:[P41+D)KP]%R%(\:W`,8*%4]^PY+#-P`*X65L^@]6SQ:P1# +M3<9;=+;KC/T@;#D"-V#G^,+_KR`T]2A?AR!YSWב-\#)"A(_3D#/8#OV +MR]'8UP`>J)RG@.$#QN*+WX/\M(%?!Z/EXH?W>*#Q5O6XHM,`W7C#M?B4NXUQ +MP>Z%"+M0.4#81M70^NW059'HUW$#Z;B`\U;.\06ZD'R>*.V1)3/!Q`HVF +M6]5QQMG..UXUFS/'(W#-UJ:I2SEB9OQCV>.];F\<5_8'0;FK*;-V.H#%\`C6 +M#Y#MS7Q13RB-JP*?V;AG^4$/R=P\.;ZP[+EF)R/G2_5CL9UEIG;E"-;"??2X +M\`J@GU<<+@\=:(!SC>1%'ZCCJT;68-O$/9*P`9M +MRX@>`X$2D:M,.VX$]TM:`?ZB];Y`M8QGKS)?[40TG%#?R7';@T`#@4JQR!U[ +M/D!9?C.+)VQS:1_9A%P`M@."#VD#N`;L.']AVMXF.6MP,(+=2,R8'<@TG$#> +M"!;P:#B#>X#M)"@T'#%6*Y_IVVY)CD.9C_XAP>VQ%D($2?S +M"=WR`KFRBLBUOW(J?8/!R_)MLPRB^.LZ-K!G^OD`&G%?)Y!,G&HD?W0IH +MLI#C>/`[%UVM&%*0(IO-$UA9$P=9..3AMN./@S?'&8X'8\8LQ#[W&Z*L4PX9WKY0I:_CNFFLX.D%"1]_%#?)Q4T;__/%4 +M*[7'9[2#D0$7JI_CC)HW9OBD;'+A?5^(^*`M8-O`7I2\9-$EVG%(U"N+:#7N +M*DQ&\V07X\8=31?$.':GK4;,0$H:!_IXB:([Y>(F^B]GQ$F>HCN6X`^:`363 +M`11"R_$4*[R^*FA\O2K/-`$U:P%3$>,`B@AV/$(TD`35:XA&_?8A7,5?V13] +M_XQYJWO@?VX8T8JOHX8;WS=;-R$^YPUVH3L]V!QH"$":Z`C0#E=\3Q'1&X:[ +M8-<7@'MP&,BV>"0,864[,@7I]9C;WP&L\-)FO8>B^@\#A$;1[`+&<6`((]_B +MA=_PUO!!RW";R*/1X0;&<(1X0/C\(-]ST7X&3`)K#&-PQA::Z/0]U($'A@QH +M>\`>(#UW")>S\5-R>]"F(W8KB1!I`":SNO"K<(*3!]VF)8NVQ#-R +MJ^73*%)^!V>5!E@\Z8RF"![\@7U*D&#!M(>^@2P/94SDO-UQ&M:.:P1].N$: +MT4\%=M#K@OPX@Z[GB!7:F6F0?AX+=`/(<$-Y/!$88'%\$-]CT8<&1`)K?')B +M:![Q=[X]AFY2'BX08CNR!C"G_K"/:`)T&K<%P9Z9`7UN>`1KZ!B@=,N":^;6 +MA=P*O^8[AN$,^,#YW`&C!&'X#6M/6%X"A/OA.S^0#>P^U(/)!CR/WX:3WXC'`X%Z":]<@QX-R#ZC@M84#BB/:S&_9$'JR![J'(/1!=`$U +MV!!D@:7?"*3F\_H,VX46W()\]Z4O*^!C4+VV`YKA.A/%X3:P2<>(+X1/<-\6 +M-.$FDAC.$1%9Z,!%'K@R#4^P9@0]H_.D'TGVV^]MJVKTIX5/6->T?"=!OVX0 +M**,*L\(E"A;6:H+*#T3HIXHTBBK^ZF?BUSDN$F_PLFF9]CS@JEZF2/9./`3# +M^8'HY%,'WU,"BC$C"42YL=PF!'\PTCSP`84@\'^Z4])Q2A^W_!),??U1DR^I +M"OP]%Z%+F->(#D^"*P0.$6VO!:Q@_P7!)?P0$44W>$>W+?R$VT>C[N"'^/@@ +MRBV_X`Y2(-K`117L]P"7NZE$'\G`(UH#S.H"CAZ*\*5<:EP>\'/O@?:X":-3 +MLB*!6`FQ1#?R4CA)JT7)IDU>S*43\)1C;8>\M+5$\*`U +M&'""]_A.+!$]95,#*I^16`L2I3]G2_KZP"C.;X:S2?"?:\?I3"W24(6,IG([ +M:5+4\)VQ0G>-4_J*M+M."O;].$FP+LXI3`^U<1@/S\$6RHXTS'P__SC5@-?Y +MX0$(R)Q(\GA#.,X0KWW!&T'9().NC?F,`B%$7H&_+8`:15_U9)NFQ1O;H`HS +M@N#GO*2U=>3M>A/N\$)%"]ZG`);TN$FKU3JE/3YG"(WA\!>TT.I;&MN4X^'6 +MNM,%;V!8T(B)IE<-WN;OZ?.E%TP57IADT[<2*\R"$5@C+DW;[LS>,9&# +MC].R'X*J'-=7%U(Y'YU-4E*O +ME<`*@X`SJN`MK.`P9-%7Q_G?+^C*G.U!"/3!R2V79!"*PQ?R;]$^/=6-B)\J +MG;V8/]J8-X%,*W&"&?%IAMX5,F;.W'!3.:X/2A6R`Q=WL3Z34S+#@^V+'M'C +M"&,;`?(5]C=ITHC,A[VZFJ?:5[LF%KN-6ZK@DY=K3(PX/RN"JG[7QJ.!U_`' +MA4^*,T#YK@N3Y_;P6O)/WSD?CZ,+5<%O2];A!C:/@U$<,OT/]SGD,;'U"H-V +M4'N>"&^/@BO-0X_Q;3C+;RA[]JM/7\0U%`TH&?X7/Z!HZ]W]CIS&,Q4RT1*? +MGP&V'Y[]P1\';\$91/WL/P'[&^/!I\5_?S7)_8D=0R.MH!C2=JZ)^S?!(4A.L)1>.AO5JPZ&8;?IO/?A[U-P +M>_MOE'+5P.Y!TX1(\4[.A2'_`@7U?B!"BQ[Q'N@%Q!\\!>AC=(Q[/+;U=NL> +MBY@]_O2-E\^%5X"93K!.4WH3-L\[TEM]O`VQWB5);:[PC?2H;CW-ZE2??GO% +MVOJ\+K_.\7:Y'9[L#D0]I`0HPFR!>AD/&;9&OF\7;SGH17P[8T]C%";>PWRA +M=O&L?)=3O$W9U=7UU[W=IMI7>;M=KKG@NFWHZ]GO0H[>+(K[>5W;<]'G;L-\ +MN\3;4L]NR-<5(C,>!X0-ZW9&ICL]^!M>[(VV(+^#_8/J`$6TCIB!>G=&C-P( +M/!I1&_ZLVA)40]$@#K0/$WG/Z#V#&*);U=VFP#WU'==T_KT%J3>#;S:41)`X +MT"&$+Q29P(QQ2<[IO`M/2_VQ'YC,H#:3@N(WC%,PO'84H:2WB;`DZ@[I_+G' +M(>#VBKEM0&"!W](D]&/W:;;=U=(MBSL\L#^H?"`>*#\0#?<>UK)!V@/TJ)CX[-U9.Q"0R:"<^5NV3 +MR1.\<5_]XCA,O*!ZQO$TK%F42GX6[38!78$?;[M-*U62/J3L]E!X!TBJ3G]! +M=9C=II%Z(@[OJAGX'H0K/9@@_&D7SR*4;;NE32'_3(/C.`\C!X3-*F?>&.WC +MB?Y;L)%)?MQP?^ND:1QY5*(JX,S2I6$_ZD%JYAG3DK!JJ5-)+!'9^KXPSGP+ +M,#NU$7?P(+.#1$X/E4NY8O8-V&N>['*_;L;=[NPVK.,LY8#FSM/[+J)@)K_= +M"?*6)K(D&,W0)-7_=CZGF['P&BV:W:N5HXB]J>OIJ+J=:W8$&(WE*,F2')&_ +MI041D:.D_A*I=[3XE+CZ5*[*><15NI6G_U"^JE[+QLP]XYNE'M]/YN$@F=A' +M7M(>K/SR":JH<(>'(RC,DE'^C2^JS"3W.=4?WSB\4QLY'*CLA-K-4A&]&EV# +M8$^,&UH\$+!L\1[A2PWCK1@;W!X(5=XHC^/2^**RK6C,!7RD?]C?\)2#WL%\`MGMT&M#>,;<`W.D)X7&D#VJ +MD%?%J3*?0B_PTNZ4SVG7"Z31*]QNDUH.,_X%BM +MT.N3W06@W3BQ^>-N5(CS4/T+7FOW*5/GUUQ8@Y(UZ2SY&#N2 +M8?U[X:Q%5YBX57.'[OA`S%'U.Y2E>K^Y(W-W"4JN21-/;M@$)7]BS& +MPTV5\!"Z=F2(IO#A-Q2@W"4K/[[@BR1_H1?$SH3LK??&9^FX9B$GQ*$U;L2K +M'T>*0OQ,0]E!OD`$)IV`G/!CC@!-R60G]0_N3PMHW>`(J]GL?NFQMX9]=?:@ +M(DCRY$O'L_Z"ZK<#K<4C?,AWN`WX[= +MPAC&;A*9'N;=*.V#(^-VZ9AC[/N"NT"%RZ"?NV[?)-%I)?,;=-J_=>0,>`_V +M=.S]P#!AY$"V@[_;)D[=L06X'5A_?_=-JE?J0-B\TIVQ"]3E2!?7^WH[H''; +M8C?[^T+X?W'7-_N%^&V6[L&V;86S.V3:OT-MB-H5POJ%(^"`0O[<.C>M%+CO +M0=@'RVW3:JV<(.33V^R9K"[CL&X_N&Q7[BO]P<=^XVQ'[I5OH-225)OKKO`" +M)N]L=N1K:-X@!$W]]Q$9GKX")OOVB#4^P>*BN_8%S-N.L*)M#4C\BEUNVW?E +MP?^I_=,T]$*2)N;MTS.?5$?(?6%1P(1.1MPLN2430>EVS>R^^RV[6*/]@VZ9 +MG&6VR;7%JZKEY&V33IXPC[G;!M>`BHV7\B,S^]MTTXMP($9"?D"*;%E(^,`) +MKJ5)%N.^H*5@)@_($_>244QNCHWY$-Z6W33%?-1D;$;I1D:#2(E^'::$Q +M2R)JONR47C*48;)T:9K?L:-)OWDT9&K5&UD`J75?N!HTS8?[[4C6';$;2;5= +MNJVQ&^]5GK0%O!]P`Y;U)49\SMDR3OR4F]_CVQ&^%S.6:O;)42O.VSA1G.!V +M5#W![9=CA,EO[[9*A%;-LF7MYKZZ_1`[91%E\4$KEMAPD=L%A=LWR>=049/# +MN7V'CSJT0#Z]&3E7AQ@Q/`HW$M6[D\=U1C;74:98?5$1G7H1O0@(ED[[:I4@ +M0GSA9FC'7?T85M2-^T`_#M26_+Y@NKVPZQ*2]X>U"1*6O3<'\E8#'N947+1M +M7"-=CVR9(O6[5*3U?VR9'-7VJ9<_8I%SD0(JN*)OI)1)KS&T);`;5,F_[NT3 +M2GI;:D;SE6>$`N`.%#_1M$J+E[($4XV7(%]1Y'B:-*A582!4RE_HTT_<)M"- +M<%POJFV:[=-\H3P=N_$W#:!74'X]F+73:)O4K(;,C7QZ+N#-!^-LVLG=>$1_ +M9`O`/<@+Z^$@O(/:A^NVJ;UU_ELZC4L(NNZ?VHX(G5%<.>4GQJW,+1;4=:;: +MA6=J1,A31#T;ZV&U4?%E![ +M:C3.]_F1[%1IG=O\J4#/5T:9V3(M,[;7URL/DR/R-JH]N.1\Y\076CMV(FW4 +M;B=T^G:ML$!0S[#/E`(\5TD?O!/$@,37($Z)J6LA49C7M^3M1MO0$3F]9#ZC +M+!:8G:@$]^LOK]-H2U"-_3VB;ML]+:$;PA-7':M"=?M'$]?N!+^&-^8`A4\Z +MHC[?_(6SV@Z[7:!2`E$][I=F_%:?<[1,XG]&S(VF(_K*35[`)$3+BI=XC);. +M9VBLKAMCR+;)%N?V;?/I]X2AM\_)ZEE!]/LTWR+S]DFJ(JVS(WH[1K!-6\V1 +M&\C:$;4*L\PI.(_(@5GO+UM$S>WN[))C]K`)KSMD1N_^$*Q0&)+NA-#L@KV# +MV^R;K6KO9*%=\0%\!_GLDU!:C5#L2-BMFU@F+6[$C>*=G\$']@]^` +M\('Y`%3*41VSPP<@`3687'B`S6Q(UL^`++;,==)LPOUV*V!!L>Q%J[L0WJ[% +MK!-SK8D;3*N7]`)$'9;`C2NR:P2QGM@1KZ=GDP?I#W("4!_N`2F`V;6!]\3L +M"-W8!-8#8$;MLJ%%CM=Q/S[`+"`V#8"W+UX;K]BUF2C?O877Y;`-S]@UDE&B +MUY&O)W[,`_<`35P>B9!]H/'`88'RP'&LR+:+E^1-_\2Z&!OGR*'I<][1=6G] +M=^#9.9OSUMDFB2R.R(U)[P67V3>9YSQFW1"=:L^:>>;79.@VJV2NT-KL=DW4 +M'__-DFBBJZDQ]\VR2OV;U,D4NF6<=_C9/MT-L?'V#KKD16?9,W@[V6R&;3L5NKV0K8MB+:XEZ;8M`B +MEV(SP-@M1[$%%%/1[`G!>E&3,((^T']$"?S)-=N#[0XKT]HDRP,ZMC1I%'7> +M"7HTZ2'C_4-P)I#L\VW%B+8VG.[VWTO-+J'9F_RNV^SUUQ +M^AY&\S?+J^/T.;Y/8V3.8^APF:ZRR9O'Z$OT#;R6C-M*K@M&5'!;"Z++>Z?\ +M*Q"8ZK%U#P<4[3<->FHW\3KR-J?<"^#8/LA7+I;< +MZL3AI->'S6O5P%;7->2WO[!-3"X.N(WJ;!-,YK=<2V-UXX4K\U$ROFP4P&3D +M]@QFCN4&;:B983?2#2C)7.2R;J%1(TM.7 +M)Q>@R%S0I>QKQ'0G:,P-\=(G8D:13MX4ESF,K*QOH/?M"Q*#)I&L<0V[7#-K +M&D4_78/X'0@X=4)W6M&>&@IZX-7X&@UCF66KE2_<=<8]>NK#[.K(P6+DW5>@*:YDR6LTNRNK4P"MDLJ&:R#U(U.`_OJ7,M,J +M=OL?5SV?A:>JVM:T&N_#4K;S6+>]J5N7ZX5#K'U.[9);=NL3AP]2'I-2#XZS +MS4BWYZQK0;[JM21OLUA&Y^H(D_*JXVK2]"4S6R,VG^#C/EK4&H0LUM_."K?Y +M,):ZH\%CT_;B+-K&LZ`>:QQ;=E_.V0P-@")'>:P;6L[K[,'>ZMT28@F[L#^P +M.;"1\3K;F9Z5L;N@.T!]((L3&UU;#=3:M-DJ3)`QM'7W6K?`5^^K39(]Q(^D +M!U0':@]H`QYKD^?UF4,]#JU40-K&R5T&J%B_6GO.1;*XY\NJ +M9O(]D8.RIA_\*Q[R8EJ\F*O\-6FZ3L)JB:,_W!]4+W7`^9&#U26KZ14J1W_- +M6UC5'B:I-B"=1JF:G@OT-2M/[W'P-XL3\HV^\/6`$>0@:DFFB2]L"X`^WJ0W +M8"?)&U7$^6-O\!\EJ4K!UMU)&SWJ!8L;?,EJR`L6YY=6FQ*>&S+E:(;R0$*G +MVKU!&\%(!@B;6Q+5.$\M#J$V%+XVH36N\:JY?]`>"#?0FA<\4#Q`;4&L&9R8 +MC(P?_,FT)'?.1CL&40X_7$WE\&K$!^QU";`[U%$1I$/6]0FP1_K:;1$:$!@A/8O@JQ^K:PRE\E$FO>6Q=XE5RXT!%?(ZPB)BNX2B82 +M]U::^?YE"(HLDH,_-U36D8NTH2-(^F,W[TPMMJA?H:H-!`3H/LT(;A*N79T( +MC$`S@1(S]",FF9D>./][73^.U]QW7Y0/;*CI]GI#/R^D%[`VT(>ZG$[S`=S0 +M$;.!^U`QH.;H`WWZIAN_P0>:#\)`J=K*@>>#YU`&K:!GJPG&#;_0?Y:!K2&+ +MN"/]*WFGN#D`-UC%)FD@_P#A0_"]$DDVUB\S)-L6#D`/;!ZL;,"=E0>9IB-Y0F6&TF +M)\4;>P#\X&6!^/3"_T@?&#CP]=$^H-N'D0LF-OV!UH'S@QHVH@/I!_H']Q(8 +MS!-L8)UHVVX/'`^T'.:47Y('^@?BTH:R"=J-J\)YPVKC"FOV>K$?@#=R)J8& +M_N'KYW7^H/::4C?/D!G_.0"X0V[52<[N>E$9H&CTA&ZM6?S.YN+;G2 +M",X#[(1B8W>D&:,QKCHQ&L)I4=/8)0[EUI-$?'J@FX`:X'D:)0F++HTK'6O!UVB<1 +M17T#8@_GH@W<8X9M&."LPV\-40\YHA&T!G0B1WJI%_D=R[4'OP]L(^+(*,&' +M(\CHAG^8&V!KP3*X`[G0DTI\B;>86+\3/$-T7+(UV[^@!XQW+P`94/UQ'],@X(/ +MST*)B\2.TU(O1G=7.!Y<^3C7PH0&4\\/]HVX>I4&3?3XAU!#/OSY&/"A%"@0 +M2'+XP?5*@G+`58&^A+Q]H/E`5=#=:`%9XO+';(4'K9\C>_YP62U(OYJ6KVWP +MG_Z!Z\!TX.;T`;YE7+R=`U\3[_ND1H$[(3T[Y#^LB9P;>N'R9PWU0-O(_;+8 +ML#^@/8AH%8**?TUGLNI#26I&U_U+H35M2Z6LWFA=QJ1?K4M5I;E8I7>L#J0C +M'85SK5[NH7H53HU*;`5\MFKA&553L_:@RP8VE!$QJ7]IK/Y>-"R&H%Y5+5:X +M$.V-$\74+WI35(/ZOG1F]2P:+4NEYTM$&_74NA/^Z(6^I[QIB:E[D$:0^(?/ +MU(SD=2MDM2*WVB&];%/3U+H:D$`C!K2XU9P:^-R-&^8%'T0O_5+5$P$YZ5$_ +M)1+W]RA%O;U+H3Y5"&]+4NA."H1;R2>W):@*TZ@9MFH6MI_9K=@K"T*_H[(9 +M@A%?!KRW8L@BX`YV@)X4F,"IJ`7TJ6K.:@G7E:@+PJ%OHG5=:`EHS4INL\\H +M"-8@.^!ZR@%OZ#J73K27?#K5ZB"I=01<&A5TU;S&GI\Z7"H5UG:$9T="MIV0 +M1WX,T-R7X7L<_H9.JF:![AJ!M&ZA-J?HC4$9YY06!@,3?E""D_8HARG=017EA.+P%K]J%Z^#3DNCOO)"[:!%-W@G7T2]^ +MA0DX?A1#X#DQCUY^ZA'+)T2ZF*(9FZ);$41*SE"/K??@%9\-$Z"^E'47Z@M_ +MF)#=#GVJ)-%X$A;W!Z,0*80:M" +MEF(<8>=]ZB:QLMB4V6K!['QFH3]0>BL"G*1,.QX/:-T>D;T##A?XQ%+??\J( +M\EB.W7K<]CY\*G^TIUJ!<>(8O%/UF2411%Y]6=:*NJW`^]&'?4JJ3L=X@B^7 +M@RA^H&9PV[L@E%%WY$!H%V346,!%")=Z`C?[Q876#T;.@#ZB@![I;H:<=["* +MF\C#MMM_O5,2G;DME].--#S6@$40_LZ=IA?=T+6))J/3$:X"=@/0:SXR3(Z<&]+>GIAW/)Z)Y?'0#-\!N(55: +M-&4H1MZ-"F[]//H2->)X+[:%_:!SYVAJMH5_]RA'6N4(;TZ%^:!]*"03A\]" +M']^A7K]U`3V<+0CX.^H24O%`.5Y.IC5D180;2M::$E;!0?P.K#QH(WM`YC:V +M-`&U=`MBL0%T*`=*X/G'+%4"-&7;W0#,A0+8"@)7$Z=[^-71OSM.E9^Y&G6^^<"[ +M(G6S4%5M)%:]0#KX^G3&U""Q'L3E_15+Z)+QM.`DCWHG@36^TP;-:.?[!#S?#/-[TZLL_?`R'LUN3C\;#LR.4),B+C?U('PBOU!M:V2TP:VC3'PT2_UAB1D?70 +MRG7(5*('S:8/[VF!1(-=DJC!GQ=$>933M9@LY9D-F-U6M]T[I>=OI6<*BL1\ +MJ#96@;D)B!Q?YCOKTPRA++R6D[Y;ZLTZ5:N53#N2L'7'9[V#=0&/@47YDRY$ +M:"'OV0'P5N5I`W/TS627^V>A?5,07X'1`$USI@7U6F'O9;2C.!!G`^HTS6*6 +MK^1\\!(@W`//#;Y!Q?$.YG2!Y/2*[$2MUHR5L'LZ9K)(VCT:@IY#3$;_2K/X +MX'B@^V`;,/+'V.1I1)_;"C-W$WRIQO\KI!F`Z),1C=9# +MDCC8;[!>C_=[-U;H_VI0.++XS=4(]`5K@C)Y$WV)-_E@I65E3Y!+JPG)7**R +M+#J/"]WYR/L'D@J''Z/'5^G7RQ]Z?-DS>/T;X!N>+LEE!XWDQ?3^AV#CY>U5 +M=4MN1I`F0&U\TE*_H6,X9L(J5F<_DCHZRV`S-ZHK +M7A'_M&45)[\`8N?&M[URK9^0/4@&E#Y/&L)Z(+.S=/Z4)3_RZ-\O?14(_5"+ +MPM(U]NL;7VX=GEMG^W'C\BXU%9V"]E^G=6?\[<?\ZC9[M[Y!> +MO9!1K+PC%W/Y%RB^+]=O#+-DH[E:-TS])#[&L/HQ'']JWY.=J-_I\5HP,BP+ +M/;L=G3Y+#GIWU0@?&BNX0(A!5^G](OUWS:"X\$TW'L\&,L&?D%ZT<`M7B_:, +M+TM&WTSAC&\\?9$2N_.,M6?9X6C:SN%[)NME>C[EF<%JG:C:NZ&*^:--XK^9 +MHQ*/%\6C>M9=&$5UW\^`G+Z=N1\?Z2`_T$\QUN)F/M9V*RWJ!9"$_MHQF)!T +MFB2N14KC>'Y"G!OTD+ZV4VB%9^EQGE&\."VG!!:W1-ZKWLB_;1&F*38Z)2DS +MH=$KE@]&Z(EOOT36+RNKT1&^$[/'@NA);/Q*A9"H!&O@IWHU;@?LT(K'X+1* +MK2#0_TX%P!\S0AK,)_V/1KM"'TVA!N:T6+^HM'_*X8"T^)1J&/U'HD!2^#2% +MD7\I\E;``RLD^]/B2E!\A_;A/ICT?O/A]=/JY3:M9+RH"%EIV1[^-L[)A8<> +MB4%/"&L`#F=`+74!"RG\.@3&B^)@]:QZ.3H`^_T"OCKWOR7KX$J#'"2LY?GW +M$RLE=>J(U%)!4FA'G-BF#&L(#I<^+%PQFC*+_[<^I!Z3$_./1613F9]7)Y>` +M)8]Z?8S0CI1JQ:'2NJY-$TA:LKC<*JU^:)T*,HO1&A&>KSZW:,@)"VKH\\][ +MP=?SX>#&D;F\9XE;!1&!B,G'N^SU1T)YF@8^8[Y[`'XF<'KEE1 +M'9^Q!R0"F>KOV.V.P<,T]B+X@.R!O(V]("&!LP1BL\J?GS[#INX% +MQ!]0`F2JTS<)(W:$7.?38QTEGF=6'H_N'R'O#GTV!G:E1IO@V\@"2!ZA5U3H +MV]\!$_U2YT1M/9Y_052(J_B!>7/CKE9\+SL\LB>L]?.DV^_PPLQ`@#7"8Y:9 +M!N(H1<,Y"HGS/[9U=KDF#-<.VS$Z/.A30.PSA+;P;=-H4V$%]6<(T%H1?M-" +MUDC+S575]N>%]/GFLR^7XB9B/11F3@.1%KN5SC#ZKIX#1NR`0(1N=:$:=_A5=59SXO%`9`'%!*_.3Q$\E],^ +MBI%LXY_3[68KO34G^-"&9=?XJ3R4HNEX^D;^ZI/.]N1--F2`14[_8.:(;Q@$ +M3W^"(^&?8%D9]/C8&@)>\`64'\M`+VX"'!]W0!K0-^V`B`9L;=>`BJK7PFW3 +M`10-I#U<;\C0)H7W3DVW9VQX#P\^H"-GH!MJ-`FMPT.?33*G+^2,_H$T.GS` +M$SD8/R/!9EF?G`:%/8">KGQ=NKH*#\2)XP[?>:!-!OJ6FPBMHC7(+_L-`1OH`0HF:5#=0`(H*/1(M[#,U9G%9Y-V*9?0" +MAB!><^YB+S(%T!MF>&E:,SZ40O]8%U!ZH(P3^!\C=_P!=P=]G27,J9^>0X_0 +M)JW>>SJA4>.#C`+T#\26XM]XOH7BP&+>8$]3GPF,"]W[.MY\Z;T#]G'/`SZ; +M@9LF=(WD/]W[8!X8/,S@;$CG*`(JVVF(^*'.3`13A^^0'^$_D?XQ.=T`15I< +M.1,Q,SV@:S.B]9QPD[(`84&SYP7,@1:\\,W+0)IA^GSB(EVSIL0/:@(I1*3- +MI0NZ\;]2`BJ7_US;\2"[9`3YF?3;Z7KD?@/B:FZ.ZYX'"+\H,'3@8L&WA-G3 +MP\Z,_<`BE8ZTB+G?%Z"]S/P!(O*9\+(9Q;R0:+-!VT+ZABG/9,@\P'XLT&Q0 +MG%#MY(GJ5L:#?AROPB_@X,U/;Z`,3FFE$2NQZ&[F`(IXZ^1,H_^O.V8\'B?L +MA-LBZPY'9('6$VK8'I`Y@`Z7*,E:'#'I@Y0`^SKR/ILX_9`GW9UK-$4Q^R9+ +MV\?[O_&!ZX-M#^;GAR]T#V@?Y?LF4>\\G/%@90'<9D37?081_FJ`,S[Y#G\R +MQDR1&F6>1@_5O!OIDJ\?/,?8+F:&&-AG[,]R?)'V#4GZO8SPH9U)X0L6Z^W/ +M'ZVW7POZX]NO=NQ_.MUZNF2L)=J)Q0;DH<_O>;I9#6PG"8*EYMV,#V;YU7G. +MPB]B?A$)NF/Y9?_Q[AC^#;NAU.R*YL[!7*T[.=WB^,]"7[P[=?[<7\\2W8!3 +MA#E/`$\(?V3/WE'3AE__/-],\70L/Y\DO[?C>ENRPK*OQXDN2VX7:6>%UO__ +M0GJ"I_C'#L,W:K#)VIVZA73LF+A*34=EY(8G[W.Z]V< +M$.KI7(PR&Y*J;'#%Z8:R&$9WV4>]!H`QZ+U1]AEYX&-U,RK!VC-=C0YBB_=E$0HGS\CRSO$RQQS*))G"[3$OBDBT5HE#'MF9H +MO[DIPIT3DA.*G/]T;I+"V#*3)3;%B/&Y'K]J9!+M#8:#UJ2)^WL:,F%9[7 +MBS8538DQE;[NCN2W-"0]-S/R7O.YL9=E_#,K8(8 +MB6*B?*+LFQ[%0G.!T5`TK-)&F$CF8*P2V%E$A!PR4%F@>2.S$P66'96/V4'%).9+#)H?8*9A75/ +M.$188JTL/ADP[9E?'R7E*%+US+9WID[E?0@K0[L1?\S3H=P\.S`Y0ZST1!^6!5V\;,!>5]1#A?7=4'DF@XFIU?$H6B_ +MRAY!2D+3*.](6=$P88HITY!;B"SF*+RA^8`M.,[[9@RI_5\9"^%G9L\U/-3C +M%)I8BF^:./(EY7(L.Z:>$'YP,/8BQ?IS$RA@F=JFI#"G1S/.*,P]-I`L-#NX +M9T7\1QWQ%>"P5+FE(*_Q1>P6#/.!IB//^,DX[71]Q +MT8,&#^/091DP"FUPQ8HF`Z49$*)-_.?_?YHJHY#%_"@@KTD$\K&41%-NPK7; +M#HU&4VRQTIZW4B7D]O.X@PN`_&^*8.`P;E``#E``"```$"44\WL#A.8`#==ER(]4(L +M5P(;"X'V``3HJ!;M@P+]F?Z`@!4!-VAO;64O86YT96LO=&5M<"]B=6EL9"]U +M;G)A%K5P(;"X'V``3HJ!;M@P(] +M(D2J@!4!-VAO;64O86YT96LO=&5M<"]B=6EL9"]U;G)AR +ME$,I7L,7KCB]D//65AG,S3PTQU3)DAR09O+RB+DR4O)*7P$J5RX4W*V18[([ +M-RT7S2PCM)EG!EDYU;\*BEZ4I"3T=:)8KA0%L,NRK(F95"@D>0:RH[A<;?=B_ECPU^BO#LC\9(L0Q!CJXL&M/RW>PJO +M*WR?E&6;\LJ5.\KA[PG]RG"0+E'Y?G+*&_>6B^WY2^H%RK7/[E-T<6M#7*CY5$6]]Y3/GYRIU/SE-HNC]8WYRU4OSEQXO:_'P% +MI"GN56Z1?_*Q_?G*=??>7/=_7$:XNIG".['>;)"F]RKE^W7.Z0K:PN;S.X7" +MR$T6M([H]<-,OV'6'"SDL89NL,/9HV;9ZF)[%QO%XNUX+VL3K!["%-/0+_\, +M[+RWUF6_Z)V.(*0,$ZQ)NB%IU\MWK;VSI9GF%($+.*I=DUA73O%%&8JA3-X-D&%`5V1 +M#=J/6N8>3186A['W86KBE_Q3-C\V4]%2Q8^Y9LDUA]0^$&.]+)@R*IGX>3HP +M+2+$$0/UJ5;6`1-SIN8+3^N^YO-PO5NO`Q,8B6+5;^%-7><1(34L<&,0 +M;AR_G?SLL6'(A->Q#E%ZUEBY-#R80:,ACEN%-7EF]+N_RA;YV:FCP>:JK^(4 +M")U!MRQ",`YB+DHC3:#&ELJTH8=ED>G/Y-L#3B!@JOW(S,V8>+=B#,QR#0X6 +MHS?84)Y)7G[BPMX5O+)P#R(+1FF44["Q43YOK\9*PG[B(@B9V;FHF9D?%57^ +M60RQ9I+XI!)L:%OP928+8,18X&$PLM&":,>,5EJA679>RDF8^;$@4X>93'*@ +M[+HC.F58(:.DS)[NT[.)5C8ATQ'DZO7?7>X7-CV+^7%G]'8"DYA<,RYL!W5S*QWEB32@8H^6 +M0`,C_O1I#*:\(TQZIC!,J_KW!0'%1DFE\IB.17(3C@%-1%7.580G. +MB::H/RN!5)2REDY%3/RY;"&+:1!ZXY,&1)4?-X;1M*.EA;7+)<81RO"$Q40* +MS;)%QGBOV2EC*=Q;9K5K#Y+@Z-;-%SNIUH0IAIMBR?UZF2BM+G32.Q39I$=J +M=M>K#:#VF;>DD?-8LS9I:MG@K=),(^VI[P:?1-7G"2V&-!,IAIDK>R`+Y-0O +M'&EQ)C=V.PR;,XE-EHIB^K@@Y)[,C;O9BA9DT&<-3TE@*REL"-+P5MB(AU]/ +MY\_H1OZ0#\_-^M>C,Q[->.2N\((_JL>W\?^[ZZ7N,.K$\ZN+U@!5_^X9_&;, +M"-:U2;9Y[CLG1JO'8U.96_97?:#%D=11W_J58Q)>@\Y$Q^L!%%L80_J%@$)= +MN[D)$J+C*"\051?)LY=-&P86;&9M,`'M.7M'<5%E]60U7+9%A0(DS*2:9V7Q3"CG,8IE1):GS;5"NW?:MK'Y2P)@4TAXU;Y/4\Y5 +MJM,=%GI/6>"GMBWD9&QUFL]HM+'-2U8X9+##65W%F_\452KLA73%%L4:8PC$ +M.LVB:99\.P.VFEJU-B<#L)5:J(9IN21)%(6'.49O_;"SR[-C1/#]A;/DPD0: +MRV#USLLZ?Q$SA#1+,O@J+\K4ERL@$\,-`4X4G9AAQ,6;PSV-.^Z?H9;OYTV> +M1Z\RQOB61OB4.QX!'4CT6R'7CJ6+(.FBV9G8Y&=E2FVZ(B9.&2Q,(LE=B=Z* +M)\M/*58FD)=F[]VN\MW^Q3J5=%9\*6&G1[>4N9H+FC-+N;+"LM.8I`":GIY8 +M]VI'B<-2,3=^EO#:1)E36%5+G_6%6FUBZ!OS^YR./='SL_2Q=42C(:-=D6B] +M)A4DSO23E9?"E_;B[%S.4]HUE;4PP@V6&LD>86D]CNUE0\PI2"5&Q+7X;K#/ +MQU'M.5F6K-X-FH?&N9TM+R4S-#S^AGJ(OY5Q&>'$[>TY2;'>N&ERK5YHIV.R +M&LB4R64.H>WEJ-$2S$_=E:"W)V[PI1`[MBB1L!3=AF`;#*IMM/=RFB!)OJ=3 +M85354>'3"8R";-TEM_RR/PF6R?ZJI4/V3"&IX(,BE$JHJQ)T6&/79GLAS0($!L/[O'UI>"&A0Z:%^_BP:TO":G!X__9,@Q"?PQH[F:Z^BD45SL7! +MPA3;FYW#,+J9:@H50Z,REFA)PTC6!(LFM?__WAV3$(3]`]I_$_BQ;H?W_\.= +M@CD]Q\."7_[]*F7'Z4N/Y9RB'W1!$IP+,R0CQC]QB;.9AVJX5)8:6F6J\Z[.]4%(@CG;9\MH@ +M53`2D4AHFV'TU'@M?]5!;]CC?T(J6^F\,OL3*+2K5(YX/2_!)J:^GT2WCX6' +M@^Y?Q)5B`0Y<&Y%=I_VUB+)KM/!AK#=Z,MF#`(+8M3,#,8H-P4I,%#)KMN*G +M?P9K%%-;D&(-B'3:&E149A%R.!V,/;-8I:3B&,H"PQ<1^6R/=V9;NI::+=BQ +M>?*LTH[!OQ_T7T!W8F+V[L1L-MHZW4M,8"5.\8!:QX:RNX9#0?(OA23*;50V +M30[,>C-E2BM2]600H2DV:\OC78?,"RXEJ8.$ZP;]`&OH,L$31L4QS +M?_SZ`#@C"SI[6/,\`9APLW@K(XN= +MYG()+L]]9-3_U5QY4PYPU0!)FZ67L:)UM/5O+8P@2SC$F*+C(9L?:I3_MIG5 +MN$ZA`9_W&)!+P\([(?`Y?]^B.\?PA-/*,=5)@"7>?H?QD#)$8,QJ7_C6#'U_ +M=7W?L.LA.3B^BY[EMB58J&!$+QFG(?Q):B5?'U:*FOF& +MAF[\9]%O>J9F39:1'G=;LV+!(\I3%J0^"4ZBX%/Q\59XZ.A73"I_/3C1/?7& +M]6ZZ7;NV+LO]*3-+-W*&=+J0D6/X[_L3;W@+HO0?]M4!G@OLDQ+B0.5= +MGB$7JK$R2(M6NTQ^8%6055!3B@,8]/V?>:?DE3E5!3CR?M6_MZQRX'BY.![> +M"KP&`5DGH@%5#/\L,4`#!4%C4*1XZ6/WX-.P2_QA_!!IN071\A%T'^T70?C7 +M0?J70?K+_6395:,Z0D0NPVI^JQT^JDJNI_V?>=*V7"H5WLG>J2]I4"]0@079 +M]#*",J=9Q-4@$_TC(""%^52X14NIFIJ9D:I'BCBQ.#Z6?6) +M-/\]'R,7H26@#+7-'4J?HE2%XAD)B,74:M'+69:%*)G;'B6+"DW.)Q?Q*UU` +M3KL*D#0J729,9&+P7^*8Q>4?%Y*LL!?^IAO2'O3MIX=VQV2C/8Q5\X\!^8;C +M3+/,I)OW1HM'+69:%21, +MT+PY<;T-B.>,D0\;$.\2-SQ)"J,<93AJ6#.Q@U&-@M&*`(DJL:#,Q@>,6C!: +M,6C%HQ9/="H(NJ4=+1HB5>!GBS9E)IX'>+/'!`>+/%GBSQ:-1^\`T(['2B<$ +M,ZT]#-:-Z-NW#;.%X\PA*RY3M+2V3^I=&&DMU$M*%?_TJ7%[Z-H^ +M;WT8*487^&XB7N$M-0$P&3JP`2468?2B=',@F[U5!3Z0*J@)])JS,B3>ZJ`D +MG![\KZ)5G.>-JJ=J=CB">E8'M'2TI'@"5+\DD&/:-D*FW%"0)E#@W)%3GU`E +MR_5*5":IV3>8AV%=&T!3-HN%3X1#^`[4==.KA#@H=%`I^2GR!M/^WC,]LJQ, +MRD:RB +M09K+9QXD%,B]Q'A%&)7(L[\1!3[R?LC9@%*O,VD*#T-=ZP+I)HKW +M0KJ+>-R)C8@N+C6A3C8&;E^NHF\:)8=]@=XV`C<9OPS$;D=%#$;(E_(J,$1K +MW%W[VKUAU&N#PC@2K_314I$V.IX_-1/I]K>;`.5?E1)(*`Y;!3$R;4-U6!V) +M,[E#FS1$\7T_A/6:`*[-3'T3=`.7EK34F0G9R9AVA]:LPBSN)8]G@5"35(!/ +MLV8P&%7!@(@C?E66K"Q=*XS?Q$XD,$O@MV%JZ5S&NB;I";@4.3<1))@/#SL@ +M5YRLL4/V\"'92NMJOQL=TB):?I5)C"SPX2/T'/$I6@6]VEE0%"X2NAS&\EIM +MBD-?HY6Q+U5'7`/R"2UI>+1VH$=^0RAG+HKXQ#Z`P6W))LPI@^CO-`$="2G7 +M=5IJ,JU#@MBKY;'44*"O>H(:/9^0B`EF_83?D9#8N6[#$RJ"O]++X)%E1A), +M:=`9LGO`&8&1-4[U)G%Z-="1VA.B5#O`F,$&^DBISZ?I/,>GM'^3IB4PTMAE",>"7BI^4B=#R +M);_9;BM&#C&((^Z?I`JD`GZ2[9O45A6P>BQ:-'&-I\45/`1/"-$QHX-P_CAQ +MCFA>7ZO?=7\(X2A63>TM$7:7C>`[,.-F@*4*J`*G!DLPE15NZ5JI+.H"&9M" +M@\/<0\.EN-289!2)DIKM?JUBJP"<5715THJM3%07*#\A-RA0D:H'X9T^,):J +MY%V9L.*HC^)T)]72M#2QJ,VU9'/_Z=ZI3MLN,.-M9=51`$`%RIAX52MF-U5`_/2R`*H!)]K!-3QIC!^< +MOY/VVQE^].(5GZ+35&(F,'GT9.$GU:/Q$DIA6EC7<\=I?F%;&*0MFL,H`1JB +M(CI9K`S/:0L]BF4G%*RRH!'N'`&3WLU(94%(ZF2"4J=+=G@55K?X\6QN_6X^ +MX"!0W$RK7>T+]Q5^7+:U5>Z?$-R73XRJB.TQGJ_;<6WRLXJJ9MM$?MCEX<1* +M*F0Y8VPMM=#^%FG#1P$2X`@\W-2^LL3*](2(,ZS6*:;*,3\'YI#0WTF1%N-) +MHCOEW;#Y6"+5S9Z<9R1(QVN)KGI`%.%)A5TNFT'-!^XTI9>+P8NX^+LY^@Y? +M1Y;]>1_Z>$MX*L=K]G@?^'!3:AAU#11O3R+=EQO\SU$P>RZNV=Q +M95N%H*XTB4=RI[$N=Y:;.73W\W(Z-JH0\:*L=L`-3_`!I^&>C0\:*1KIK5HE +M@QSA!$8.%/"=&"L93I4_P`:)QC`\8*&R`>+C_Z+Z/F$%T8/FJ\M3-(OF:RRI +M5#D/RG:H9`*J34A].)@EL%'Y6#W=WCPB@%SN9;ES++1MJLD,Z99G56K +M!>TU8/O/X"N(\56N,^*E`)@A)5R7]MUU,TM^*%D:Q/S,LB4L824F#J1K]+CN +M?"P=I*4Y_V8GZ,2LEDQQ9_UTHJPPABI?M9#2&G,;+ESN(PC,+%W6352P":'H +M,/D6?]/X)G9JB`#.4E3!$80//^NKA,/A.C;_)PE3!4.9D\6(I7%WSJG/`ZJ+ +ML.2<]T@D2^!R2=(PS.Y,S8:=P2$_#`JGG=29EY.%J**AP((>'..(<9AUJEX6 +M154!0`=.D3\R[-`B7'\$N/NEQ^;=+QX1Z!]#.C])?Y?@1W2M`2?2OQR4"L=0 +M%?;==[F$G/,WT$8-,70AGQ=8OA%Q(Q,A-L.B61Y*5.'YX29`Z*XS+R!1P6!3 +MBS`03.S9KIR*PRD\QJ^P<"HNGICR'F8*%`B6,P'D&?`8&8]V(MHA6]YD5%%4)HV3+^1=HAG58AN^ZM-*% +MTL@SA3X2,)4K'TN@TSZJF@@T-,H1,B34U1?7^>CI._E50&D;EV)=X9U&?P9D +M3.&'"9PP^!GU4O2WYD/ZFEN]@Q=6BTE0?20Q'2!O>50LKR8@W?%R"XAG6/NG +MA79U787K(4IFK3TOH("8/D=MK#B[-)U`<_/%=]^Y=*&IZG*5%./)O!S#2ZGG_H&S,5+'#]+F8Z(+I139BY:8Z.C)9\4P+@Y^7_ +M1,B90Y15RI"<*+S/;#,^`U\++2.@:QI.*SDG +M!Z;DD_@)P1%>8-"`%T]Z5`^B>UT:6%_!O"W2TX!KQZN3Z+<_^7/CIT,U(%FIH*?N#G +M:<%%/`RI6$L5.$TNE>DKT?=%,TI<<'$D^YNM$7`M+-G[I9RYE/HLG=5T/_2T +M4K_,:66E`D8XTL\JMI9T7Q44XU,@8!W@\IH;I?SI1_L-%N2A'68XT +MG&0W\I1V`*&)V8+E2HKJ,0;I@C3/5DESNAGN:)IA[J,^C);,V(*J)R;%,JQTQ(!J*A':N$9U.98G/]FA*3 +M9^"]!X;/`(EVD2G=L,GJ4YI_'.1S)J=+"_HGO34&&`R;'YJEH,G@1!30\ +MJ-K!F`DQR())=KO9BYL +MT@X3PPW._'=LPE#JH/,ALSU1[(0%:E$MV5F4@JJF7!D\FDI3`M'LP:#ZZG#:T(L`<\BV$%0P]`3&V<&SR* +M_G(BZXM$@U#Y':E&=PBRRU/L<+1(,@HFDSGK_9HL&15B)0POZ9N;B)(JS-=H +MD607`(9D1SM+0S23B*DK!4LS+Y%_:?5O9[60]`S0DAZ)-R+,G4L +MS).$F*R:\R8]$F.<7%2%3YE!IZ.\M3UJ69JE-BI!H*N)YE1A:>SEF5ER%97_ +M.HJ,2(#,WSA)GW?19D1TD1RBZJSP#B]-WA(D1<@T"2;1;_,]%CG%R-.&9O$# +M,/%C46-XL=(L-*JPHO&#?HQ&9%1DC!J,?1,C(".T8OUC548(8:<56E5NE* +MO$4:<7$X)CI,YS?F+3*SC68':&C%XMPP&=YU3X9J:&)GI*J@9V/S__FX]@8N +MX^S%L6DN-!)WI''A=/X]A_$055/'ND79[/%QL8,L]1&BK0/:*/!`^V:3&.28 +MJACC*G4"E&:4?NN]%.:-`0'"Y8N1THS",SVH+IGL:S$73 +MNC:%`HOAP%D]Z,L^*AI'4R5C:Y0&I)V[;``@4(B95&P85$ +M8UD-)L='MJ\:Y?YHV&7DT0S_&SEY_3XQN#//C*J,[3&8:61.=QZ+>9::F +MQRTY@Y)\S:,6V.7AQ&4J<#EC-F,#D?[^%FG#9P$2X`BLW-R^LIA!TO.Y<6Q\ZSXOP/"+B +MV9&>^.E34XM3*5.+'PU+\Z\0]32WC4:APM!=/%K0@K_8Y&$=(QKGTL5)_*GC +M9`!V/_T<:P8AI_X^2J9CX#`%7_17]_I00D'_U2Q\F\*@S(QQO)YSU/NT1ARQQ@XQHR7:">:M[5QVFK&^)/=?KB]ZZJI$M0HVORG$.S.8M4\P +M6+/@9ACND$)%,]B:=QI\SV(4H'TSB9B4/KQ2V!9[_T88I%L#\BE5C-W(U'9F +MI29_I22D"X'R/K`?.F)@C$DB[%S:D#%_G4`?RFL5@*35B8 +MF")9#*#R?S+PJ=Y`RO&Q9O`4LSI1C26'\7QPA\#48*1@F,6C`U.AE +M4<\6OI4Z\8"EF=*,=0!F(?3&1DDV#4D)DEGI>^^T.4F*28F367TH^CBM4$$F +ML20K@B`HU4(C6@]&M!^AA=?=&=#H;5G\;=9/NT).I/B.^:]&D,+'#W&SM7Y? +MPP!58"F1@^[9VD6F]%-;/=(EU"JKY,Y4SRVB<'_`;W><0\LD+=2M+$[AWW91X-)Z +M:!*-5,.V"74?4CBG!8=2!F#;SCQ +M#+MQ"7>:<+LW>5V4>=V:>B&-U&.K&6319)M&'!67AR3,\&G@FF,BDXKHV4!M +MMY?,^$DY-'B*>3&&>F5*T2[#7+C$V?R_:QW38PC(M"MPLDR462N_%G_&Z$8]%?8!48"+D#U +M0"OS(%)AB/MZ?%3RP9<*'C*\:=V-XX<+(6*WE_4FR/I23BF'R6(OHA^1:D,E +M/E59_383,(FWAP(KNL_394@(G.S3DF)F6-IS#&'/50:\9`TF,,PP_G1)O&H! +M+]$#"7%Y<:9NR0XY,+MXH)*N]FH!CKO*8&2"GC<$GD&=&@QB209#Y_(Z*X8T +M?)#YODBFHP$5(*GY,551):0P3^%_2DGCF4FU)_L`)Q`(&Z&X:J5)1@Y`L[G( +MEW5R(G(,H>O#R:$1PZ/`E49$"_A[[_%"TLD%I!3_D7GY`'@>H)$'Z/'1-"!K +M:O4]P=8D58)57L>-NLY3F=LFW8Y +M5LY(QMUFHTCNZ4;LDJV*8"$9,$P +M53]R.!]<[B9<4EAFB@:?K/MW?&M&&#+)6EIQ7;4PS*9[D]FP:F`C/D^[.TIC +MTDC>V<8[EY4"#61$S`L`=JAX'W+WRK^IIE*5;;VYFGT=W/@14;U,85XC]Q+9 +M`MX,IZ7C./&F6-M&?>+8.699&\8[P%3J1%Y=WV)=XXBY?SD;1=)$:-;A5XW> +M;]\;`?CH@`:B9-7KE:EQ,E_HF>DW1/D0]4P8S-/W+!&,:^A5.GVIIH7! +MWOINKS5'3WK948^O<4>N5>'Z!M=54)?C2O<ZK64GMEJKOQMM7M[Z-Y#`2.`P-VO^EH_/^'UY[PO^/WW7?[S;XO8S_J_I]'9>UW4_J\]\=%M-IQH_ +M=%%7ZLMXESL=JS4G9H79WKXLKNMIW-BM5SVO6_?]O-_>AR=-1T=C==##SF_B +M=+_:K5YUEBRL?S@J:8D.67^I!8K05&4O+2X7_\_G=`WZYYNTS,7LY:\,.(W^ +M.VGARN&8!'?G-*`V'!C_'_10>YQ7[ +MQRLW+YG0Y'%XO)YIG(5Z\=US>85EY7.)@P#+Z*U?R^5R&)` +M]K=8[$E\3+\S?Z_N'N/1@JQ6>-.?QR>.A_Y`*Z"/Z3XOPBNL&/@B_^=1*NO^ +MH_I%(-_2_`@X6J-*XMU>K_GU:WUVLU;A]-6H0_]8,/'$0GQ\[H?TJRK?5_Y5 +M8[B(,H<#_(3%E("+!,/XF?T$5SY1CWA2K>TD(V0C'DC2"N@$\T1&_,,<45X( +MGKC#B$^&[QWPG]!%M^H8DUZX`3LB1YJ\3`K+">:(U"T!,CKBQ,^1]9,?,VB1EA-K +M>Q6?N'A?Q'I_>,,)\SF!C<"NU$]<68NO_Y$QO6[QNA-K,WV+]!CGDKRA-_ +M$0?ZC';MQ19A/CDAW^PQ-BLP)R@B;7\?T$:!;+KU^T3LA%^S8Q)-X1X@R[$< +MU;WLZ,?UK(>Y8VKU?IJRF!7=8&/6T2UK%;.)MKV/LT8Q@!7PA.!$<#24X0N, +M)%NTH\,J(_NM]9*_,T<7-+Q#4`QWI*]T)HR1WRUO%/)3)E+_6E>PU.O#M['N +M$\;:(S*W,%>.)P(CVJ&G`C&",\O!.V5$4A(WQ*T@G-"/OHH')EHR1DM1`T)2 +M_2I=#:HF,0W;\.)=B)[5C'P"N4$VT1RM9`YX7`DC$ZTSP2N4$XP1R5LJW"/< +M$Y4\(UXQ]Q*_2)S0BM[`8RPK[XFC$9)>(T4F5(\5H8^`D.VR*.M$NR#9#&+% +M9T3;1',V@QXC<<>")P)(M-&,805E1.,$>;MAC'5@4QM8"RHC?;D8^->OP/67 +MB:W0QX/$ORF=SQ/%V(WZU[%;N)MHB&I*<>,"([TGCC!$X/'*B/=' +MCFA&@'C1B."/$O]%%W5TI/!V(MRT!C1;21Y6[&/J>U^43@1'3;P8N1*V\3C! +M$:MF17,""1GP& +MX19A.:$4?&&/U;BC\1GJWH)'D:(\_F#&AK(IG3T?[^QW+7!B(JW +M/Z$57G%(CLZ\@8F03<#.FS5\8GVXRYP3)KQL^H&.Y;M\>)\T1T/Y#`"(6=U6 +M4`E55$(C9F!)>*[WM=JNUBO!57E+R`7867=F=`3`F%2W`,LR*!8"F%"[`04% +M,,'%`45(Q0LU=W1 +M@5\\\^^^/4\]]FI]]K7VO?P"BJ[OG-\W@YS?-\P]P5?;ZO\0W_PG^P[WOO.\ +MLZ4(&M5=V_GS1^=\LU$=X#.\$STH`[>SR_M`SR@/;RH#36:>/1AF]$\1DO@T +MP#,.X#N7X#WF3X:H]^Z5#+48G73`"[V:>>Y1F!\"4`VVA +M`I$\.B`?T#7^(-"1]^!W-(`X[@"VZ!_/9.Z,3_>&BOHV*A_"!ZFT\3D +M52M_``9FU".0OJ[8&Q`^[3AX>>!J:@/ +M#X0/45(>#\FY_UU0^%L`R=P#PPH'&7$!GU@TSBP7E@/Y;H`K6=>B#.O$_5$V +MEFJ#_E#-B)[2[@/#'7P`SSQ-%>0$K9Y?)!GP@9F]`+0]#28>MU[W\@`E\%$U +M%F3^_B>H6#6X&+YW"@*.S.-YX&RN@./T//`+J&MP#*X#K*P!F+-4KRH9K!/N +M8P!?K+-/H[%XGXS)=8T!AW@Z5;P+]03=\F`_D^#3V'P7P0/TYL!DWX:=&_"X +MH!R/:`*`=9P,X(&M[82]#5[8K_)`,IL./O+Q;) +MY^)^JS-S[@,Z`3_GO`$S9J7Y0,KA/Q_C`=U9FQ^Y#-8)S?@@/XAKZX9XP&HV +M0#G[-0_S@9Z@G(>,`Q=G7_[P=!.O_-R0_PY,!/^/$_/%U\4,N#)\?:`/6L\O +M],,Z`#FML`\P=?(#*X#*[@!>[--_=PS6";EY`#N+-2_VP9XPGQ?+`>;%U\L, +M]0#B]V`_R&OR!G!`U7H`*&SH_:`R'"`7']L38V:M__X#+A%/D?O`8JS,?]"& +M=`)X7\@&/D0TQ4B%UP&\?'R-A_6";E_CD;7_C";I\P#<6=7_T!GJ"?5^H!ZX +MZ^H&<$#^#A\CH?APP%QXO)*?XI\]3B\6?8#2;8'!/['@#?#K[8=!/9/@'-V: +M=_`AFL$_ID@%6&N$#/&`_WE@#FS._^*P&"?3G@$Y9:W]8'3@B?1B6L-,B$OS +MADR@#VQ.2!8`!^!6_P9?L5B]I[L',2U=>O@8-1J'42Z:5WS4&]Y@ODB'4%ZM +M7,E'B)>)(Q&&0^2<^I7B*<.3]"UYS4<:1ZCT7'F_&S_,I'%9U--[_D8=UKL7PNYR?H_IZ +M;ZM+I/>TG::+UO`A4_Z>_T_IWGV=_^ZJX63U,EPO:M.KM]XI.MJ]K_*M]K8Y +MZAQ?5UWSZS&\+OKVZVFTS_H=IUGN8OPO\^!A7N'["T9VLJI#PWV$W?O8]+# +M]NMD.)J=!<+UV',6CO)JEVN9W6[ARF\\;)[[M^E^K/Y^1VE#0_S^*JFN]O?( +M9W_`41FW.SJYC^M#[3AP?^5^I;W+1]#O@GA_'$][?T%@1/,NWIVW@0"\L>;] +MU/Q5/4MG&ZT8B4;.S!\8)#_Q)&+1O_IN'H\*G]7A3>_1ZFO>X4S[_"F/@X4O +M\/"E?[<*4_OPH7R<*3^3AR/`X'!_QPW_S<-CZN&ZX?#<\7AJJDXO4:?BY[K>+7=AQ+S6TXM_VKB][EQS'DN+S]?^4)/%/R^6S_UE\D@7B63\ +M?]>2>21/9QC_IOX?F+B_\CT23#_=XJH8S^AJ\SR.)R?XO:":P.]]]T)WH=\>%>+Q_\HE] +MG5#/S57VR/YJ^WV[3UJYKG,/:YZZ4]53U#BV-^35XP#M?0A(/']YBVA^55"[ +MGB`G\LV'EZ%U"VO*N(_6H/EG;T%^U^P)L%P\LA?@O1>F$\61#RT&$"ZC>A/W +MN'`>.OPP6OO@DGR=/_,Y\+EO="=*/G]/W@O2?U#TJ?%A?Q;\/2Z/'A=9[X>E +MVN1"_U?`'I>;E`NG^(/2XF6"_P_V#TJKI@MS\8>E6UX7F?D#TNWZ<+]CY0]+ +MT.I"T>+KF(S_)JE^^ZL+V_S!)X?/-Z@+]KZ0GACY^9UH7U_""2JH>7#[$+[K +MB!+0]#RH.S"]RPTA&HY.G_B]L%X!_%E&Z#RW?X@OI6JK%U'S]O7A?>2X3,6\V(7UMO"9-^'EPMF%_)>@FT=AY4_Y;% +M#^:"?3R:B_"[8+[WG@EN%]UEQG\8OG_/UPOJLR$Y_DU%_S^ +MT%^GG0F+Y-.?.^X%V[I_L2?\[[H7Z6@"?G9\[#WPO4]2$];DY?_O_8+Q^C"> +M9%\^8X`72=6$O?)J7\/\P76Z8)W')FG^'P@M7K`GFQ?.&HHV/^?UX3_(^>V= +M#?DZL)0\G6_^CT;WW9!-CR9U>Q(#>K_"$Q7)JE_=PAOX>["8_DUS/PDP-X7Q +MF?2[&<&ZW]'V&O?N9\;U.U";CDTY\_2!>`W(3UP\\U2A<[Y/V%F_]-.-[[]7 +MV%O^#;QMN_T3[`^7/W0+;P`&^B^?F7AFV\`QS?)F#X=\"V\!A5\G'Z:_A;>! +M(<\FLO^9P3-MX&"<<.!\<1S86W@>+6/X9-5KSB_&%.[$OS>#\#D&`X5+P%$) +M=6T,='%*W4(@9YZ?+Y%;MY(P)^0RJ"0L7[:?E:!WH63(N'*Z1XO?.@72CK[P +MEV>89,%$EY=H;IAWUPIA?^+7QZZ1=CG!2KO(1'+O5-2RK3"+R2B!EWJ`+R^, +ME3"KH-D]]YI)Y9ICQ3N-88P]OZ1&61MJZO`O>Y2%1HD`B_/>K!W1"C?9A^!PSIH>Z!^7Y4CD%`"5C_*Y'/@*MN-Q<#LFT!GVF7L +MV?R_SN:(2Q")FA&/<0=Q6-1>*<18^.;M3.R+0@5]Y7803B][:!+O09E&4:FA +MLE"7S.(RO/?23&S#4JP+2ET=.T%>WV+!6EM'*Q\F1VJ,E;\T5M<$*?UQ`4H4 +M:`^-VFHKRR"_K9A*%;]X![>+%4#^NF0>]0D5A.Z%+2Y;M0*[&< +M3$_$@5\2;!OD([^EJ6RZ"3Y,_$=L8-1$P"#$Y1MKW`TC6O\GXH+(01.'DO-! +M0'X'+0K8@3-=W4U"14XZIVN\+@F%Y-G".WOT8(IYX)HHP^+]8- +MQ.,G]^*O_(O'C$^JV+O'T2&!>/Y2Z`U4U?%4UK7J%=O2K9YG2(NQ,VZI[3L2 +M*P(U1>U$#2"YLI]GMQ@=\A1GA<$FO;S(;AP@Y]V@#F()S.2[SG42.]P.Q`S; +MS3HB;Y`[<#//.Y7B7UXXP7E'AWP![TDLA0<^6PA=9 +MY9M8"+4#AF-/K;!OT2`7Z>.WU.G;7Z`F,7\S#.H0O_,TI@6J:JSDT'R3'\0> +MP]RI^V5C$@J)??-`)(1-AY1&+2%S2!(O,\Z`W0'+O, +M.P!NH.>>:2`!NP.U/,FJ!NX,IS)`3>`8A1$3>0=[>;-!`O8/`O*M<#?`=61- +M<@>9!UCSH5@-^E<`8ACWDH*P$/"F!E'G>(D>!2FN:>8%$3@HKKGG:OP.#?'2 +M=GWF?97-R=P`]4\H4*%SA##)TCP[Z_(89CGC(^E>5R)'SLAT9@:EYVX+$0/5 +M$ZIYV`K%2V7.)UI'0YD,7,9^*;!YL4*?C$H=W[PDJ$XUX<[^S>?S0!CGNH`^ +M.\^\RL>E&]R\]H5T;&B.1^4X7[,R=(NY@Z0Y+RUF3309,OV8_.V+XNCW1$(J +M1(1=JG@H6ZF!)]:_1M92)L'T3.+MC?8A<(#SIP#E$"OOS]I*X2]^,I0.Y*8> +M2ZR#XB3(;`<#0E/I)=:F!@7"6/;ZX)TACTG,OT)X]U@GW5T%=S[*(O\T$#-3 +M*(*`;3,G:$B\#\J(>=!P_G*:-?`J2Z(AS(.D&^TG[RDJ[,R"I>@0T=(N) +MEVD>?H6)B8N#'\42OSC1*8N3Q+@^\H56YI`(3(=_,!FD"J&:OH=M3PWH279] +MRFWIK-.)E-H]HISF)F7=U!P4[ZI47S,RDZSM65-DS-(J5$N=V-89FT2J).PQ +M-714N&AWE"8[-7:#[B4!^F@BXI^$[Q8#C)&K2@?TH4'*/4&N10=LLKW\2B. +MBW,2&ABMA`GF6DT%5ROKQ"XNXFLZV5"XH]FL\VK&C!9^$=:=^23YJ:MZ]]>@ +M:YB)<72=O$H,%X=7@Z8B\[DZ:OSHZ0)_'9NN`85T=%$[U9SC="Z.@.=)"Q.5 +M:6_UG@'-.M,"T"-OIW2$T<)/O/O6F69HKEI-43S7/8E85=N:I&FF,P" +MWDTB)I0;"+>B:J(C]YWR$MT+Q"U2+A?NCGCZA=!=7-[%-X&1-L.>8G)U?UD* +MAX(&"'[.$>N`!(8^)ZTVQ.)V437.V$(L7NB4OSR^[6SDTQ=R8H> +M8DUGG*1?\R)4\YMR!IY'RT6J6M-*9RI!ZEY+$UM.7!^=:75)>OX1\VN][)54 +M$F806YNT*3*(B8]=`$Z$H#RGA3\4!XMZ-T3AAZ`N*PU-<<#N@O+@M@!]L*H? +MC=`?J0YO*%O?O*A/27`\,*OP7MG('BA6!B45O>`2_C<-A0LW*ZCP;JXET>@7 +MP7T$3\SX#`"ZRQ(BH&12[0$8\+70A$H-Y2)Z*"W*J(LJ1&:"D.F=83.E&*XL +M@0OS:#9;R-VE?BNJ"J3+YS)@+@%]5]`5@H+A$-,A-2%J"NZ`J>=;`:9,Y@I:C%.=L_AZE) +M4:\QQ6EV:%L\6`HA"_=V[A/\J(+>(EW!-C4UO>I$D5EEM7L<73>A()@);Z'0 +M*PQ=$C&+^-`A8U$P;EX$HD8SW\L!T@BEC$,9295D?F@.FB/X^+I.D0%`";8B +M+,FU64!#";D!TSX'0A/*`>&$N,3=$0:!&-R]$A$N.)5/'@,7Z* +M]5C*(N0G2GZ($$YG61ZQ".Z0GFT*1#._)%"_,-!3:QA'VP!YM`H=/>\@L)G.\_%M/>CI>:8UM +MQY(>I?H"B"_:/SM%'=.FV'NK)U]49%`A+IF=\?1T4D;4N`@/-0HC('J+M7*0 +MY0)5T56($V[D+S)<+SY5`A!3.7U^.IDL2OYQ,S'58ZB+]IX2FY?M +M,;>V4!U9S_>4(]YV"L`'@(4ORW[52#6,C\B$K\P;UH#''.9^L;[C'$MNP01- +M>2,*;-F7<,V\D!SSY,=#:4C%TV[=)#G@E8A9M@_D+N%576JH1)\1S\-LFN`O +MX@79228ZD0`R,H5GRA7:6](17PGR)G,(W*="&8*3`XAZD2FFF)M%29PLHV_0 +M^@WI#=WHD'ER0V1NM$2%\(V2-8(\O9!-19%904>W911T^S6>2RQ +MVKYVB-*=_/&4HH[9\QXB1#=$&7.SPX"`$]$I#S)S=ZU\AJID>MGDV'/H286L +M2"%K +M5P(;"X'V``3HJ!;M@P(](D2J@!4!-VAO;64O86YT96LO=&5M<"]B=6EL9"]U +M;G)AM_S>`T=L>UF3U(95SP!J/\HNSTC5?K +M0E-]`?Q[\)^&-0![HK"L)CI5IO:F\!\D.DDTUEJC+9+,"K>FM-@:+@*`;^^> +MYAFJTJXC2C",>XI<.=.4@^0X7PG?!.S5"^]AB2'4B4-`#DEIVVCJ*W+UR(&T +MH0,1Z,2X4246DHH\%(IL]QHT,,280H"PV\3HBF]LVX[PBDE(C2AD)2@S4[@"BG/A/1ZH3+AO0K6[A*`<1Z%:S<`*KN +MCLA?@(TP6S+31J+>@%5R(R7T"9^R1?FH`&Y!*OO(FXL9#^8#3>#+)$I=-+^! +M0<;J$*OL2(9#+"+N]8O#M)1HH1NB[X]@]BW2?C#>:>R\286`K`ADS*A9"33( +M.42WV0=J;(=-VRXN[3[I+,,LP+P+3_@C&>`D4_&(.='%=V,V09V,3\876!/Q +MA=6EE,@[D*-J5)S\%XPEL7'T0O9/&VM1']#JDX]I5^'L(F-C4H_W$T0/IGC< +MQ=)6E8_YMXU-U6'.00+T:HOQ()Y!P`G0$8/:!+9^J2Y":3LH:8"=0%$47<5 +M4#5D#66#)I$/1#/7L`VN` +MSISJQ_L&2W&E&WS(7^V)4!K%`U<`SS`6X">AK@VTX9N0NU!J(&K8&*(N%N>8;-5E%84N5,-1^TJ +M[P*N$:J%-V@;(2G&G332K$':6INZ:K&5,0KC+3'3?_ET+R6K"=X&=58E,A*B +M'4@Z<;^4Z3?F=23=PAAP8KI!HC'XB'6PSQM5$\0,X,0A*CC$-ED';AG01/Y! +M>!""!J]T7/&P'_-U&Q#M+V)UDM:T!.A9"4^SJ0=,-HN0OX1Z5 +MC]ES34?5TUY>`Z-MN;7P!=TGW5DJT>/&1/(V]ZVO6EB47[39B_6Z?-W1HJMA +MW@32-)KG.QB;"--3!G@LA*>LU!I!THWH5Q=X&TIJR,%&IQMD5=,$_?V$37!F +M;L3&0E0#J0=L&T3,YNQIQ2O)!T+-VZY`K^$N'7MJ/&G]FI\+(2EVJK_4-&0H +M"@34@TPA%8'`.@KY]"T9F1:0GQZ%-_FYUT[04&1L^I153YYT%6'4461-UYS[ +MI%Y\9&MZ@ZP?0.@K6=0G`WVR?"J8JL>!4B432"@I<1<6\ZP)^4,NU`%D)#W +M*`'N('N('LXB*!IXASX_S&2&IB?3&8KWHX0E/CV*`IA["+R.2S`O"I>4V&BH +ML:=JA_1>-D-*$'WJX5Y6BM^*;/5+$2F_]UY`+.)ZY&7G-)30_?B?"&=+0A9" +M5"/8H"VCV\E>2#.W4%SMFFP])>)^Y<.M:"V@3V]1$OH9^FQ08A*UV:JX0=O& +MTH(R+^S1%/RP7BA.T"L(&5-$%D)6>M@08Y%?Y%QNHKD`SVA:=D0@1!VH)@2O +MJIO3>T:./;Z>)]09[,3M(^G;M(G:!UPS],!A&YS*)#1W;6,WQSFZT+W6BM^^ +M;/519:=N[#6Y&\P[`9][3Q\]]NHPLA*VCJ0=S'7L8TS8C@'8=:<8_TX;;"Q* +M9"5(.I!U`ZZB+KJ`[L@>F'-V/HAF[TW&*+_@,T44B`?C/1ZN)X4:Z[9"TA;\;[\*9`UWD2`W6"UNB +M0=(`0M`\T31U@1!&I*`^])`[?@U$N3*;I'PN\M**6D=HD,@N_M2&-?'T5%B% +M$P$()N4,[2(7XR:\=S#I;[`VT,C0XNC7>A"S1@K].@R<1R+QC:]YR-/ +M;^L<(2M+.I!U(W?3J&\5R-TV"9E%&NHW^#F:^5HQ^_U0;4UJ"R$J$=2#MHZ\ +M`.X@6$Z[1Q,=&L=_*'(HF&9W_4Q"@*$9W@A)E\P((UL3!!**)JCMIZ +MD1[3EJ>/=7M-Q-\!RUABLH>?$>"Y;NWK(TATQ502Y9^),.@O,TL0A* +MXM7+%IMXH"]#."%6]N9K?LC\ZP-*""/;T32"W$+P*=&LN3EK/$=5HZ+3H,ES +ML=KY=!"=-LV:,V[NK1N1I%F20 +MLQ0$!.*MO=)D"!NSEVFJ[]\H[W%`-W;H9U)0%Q=@YL)U^C<4OWT*EP5D34>G +M7A,A&<#U%,WG?1"5+&Q",5E`709XPA$PPC!LPDWJ*W,(#Q80E6HD7@S_*S=% +MM%\Z,#JM!"J+FW:0Y0)6%G0"GSK-YY:>?6?0LU2WA:3.(!>!"?':I!:_:TH% +MHKH^Z^?M'"$J.S8O(@[>-I3YD7]O`%U&<0%AFHZ]I4QD8T9LPKT@Q"6?N#7T +MPLL6]TZ%9V[2/>#G(]P//VP;(2L[FL@[B-$?T`\U&L*_%.SQ\%HHW0-\X&$) +M6=RR0=3%ZD#?1RO.X@Z49P\U$N\9@.\VT+(2H!K,A"@*@:S)32U+*YEFA55$ +MY\)89FBTB"'IUF]';9&I!:@,SU)6F0OOK-Z/9F2#J@3>CUB$&+4K-W'-DU0) +MZ$\_,DI-W.U'RXSBYF)Q!SNQPA*D&;IJOL4!VM+R)J,=G1-.M)# +MF=R*`VU$V8@M$$MRS]MTZ061BJ:;KRU'1LBH61AI3J;='D65,-&QBF+QSWS# +MH4Z#5(TB#75-N`#??@8K&K!*^/0A7*A*]O0EBKI!T8Z/PLE/06X$8+'T7X +MCM8H,98,HXJ;8C##*J8C*M*I#C5?=>5]/J,TB,E&U:J,WDJU`;5P'O:$8(&H +M02T/G4EQD79J`V:+&+^BK?&C<"B@7S[%:TSS_L5?1"W8[+>!FI?G[*=T2*]7DVD)>1F'-69'(B(C& +M[%RHSR`;2T8*NW_P;D7865VA"4"IYX[(&K5@?Q3]#P/QQF6ZJWIF;JXQL,^9I`518GLN=4)P%S:S0@ +M0D^"+Z$[_1GGB//*MMLVVL3T^%\EPU_/R"!*;0!%-1G$`VUMG+,"KFWKW.403N&I#]HQMX2!,-$DCOE"P0]C/*E! +MI&,'EJ1!@DE7S29Y$FET;+TM^/4$=&<*<5PY_8>W2[\ZH7OM)?TF/B><.9NX +M-LH$)3[.I!TPZ?`2'6I4>A!3HZ"+:U&LP1>1U(/FANEQJ#9[32'\+'1,P&>9 +M$(2L^=4D&.)T+92ZQKBE_!`AZ+13UH5D0R[7$+(2M`ZD':AOMEQ=4$Q]-ICN +M>_I*1L(RO&$8#&M&?GHS@3L+BUN#R4P(I,!7,6*A;<%7-1TK)MOQZTW%>;(?E\6$^.Q0 +M*?N3=P5S8VWH9$46L;:20H"[LW<$HG7!=AHG%R]A":U@CW,4$N09T5R;G6K( +MZBJL#'%S]$[4RK4=;EN7T`9L+%(ZN.9Z(.W1;JCW8QN1'_S\2$X(9_0"TH)1 +MTI&6-F70.M3V)W_VE$*8F/;\H[G&()1TL/:V!IV`*7`9#$!-<&5T01+MO<$2 +M\@J-$7%-%\QT2S31/-CEVP7`OMT^(V/^S8Z%2-P[9;+$KW5&6(=G+(C2M":% +M&6'=H\:"*PF+@TURXJG+?#V]+(A([DM-F)\?^*>'FG(=7,1S$\R&PB+\Q![2(O>X'31%[Y`ZF +M(N&B]_26AB^#@;(,7YR2]-P%KUH +M66V*LX_!.K:7['IRVV4ZIQ;!\,JNZECSE@IV&CNY/$BHMW`A^^)&.PT=Q'>#? +M;(,=AH[B.\,Q\:P6[YTAMR-N\1`_0&.\5+/G(6[Q!CL-'?1L3;D$YB,.YB_&2(`IW308,1TQ_)9'NB(>FW6A%T4IHA=X<7! +MZU^C:=.0.P?`I("D;M@7"`EXB8CM$"_+ADEYUD&^GMND4[OV4\ZV*WXIYUT6 +M"GH4;F?/G_B39WET19<,DO9J91!/Q3T(_!/9U,.7[*;''B1D$(_ORX71?:\D +MF1(V4^"/P3[821UW7XI]WS0F*?!'X)]X8N1%/@J1!/YU60A+H4]#4+*?S[4$ +M_%0*)+?(J`$?@H`1_0`8`21+A;J#IE(9S5R(J#^1L`5!_,,DJ$GMBE(I'O:U +M.XDSQHMJ@X11O0A/>,>+U0+QGT_>A4=RL>K*$?V>0/7UV'3&GLCR_3AWCG@Y +MN)G-M@Z-&V*@E[D\3(7HI>YI`D7HI>Z"Y=Z*7NHN>> +MBE[L+M3T4O=Q=0]%+W@7='HI>\B[V]%+WL7@7HI>^"ZMZ*7YD76/12]^E3S$ +M_'O12^`AY5DY1Z*7"GH)<*>@E\&^R41[$7"GH)<*>@E\,QF50+T$OSLAHQ.I +M>BE\0A_YJGHI?%2Q;[+ZUZ*7Q@>R0]/T8V]`H@F!3ZB2WR*?!&`3X(P"?!U?@3FK%OP*0!3\"*DLJ*SZGT_ +MN"::-=W:4Y%)ZU$;H(*!D[^9"U2`\2H7*1%E=O&\:+2ZCF5*%.\;XN2`S#5X!ZI`$RBNZP\P`J=E[@R\.*GH5M`R;S6 +M@I]ZB7PG"*Y4LI&QPS\NTL1!TVP4+5!%+TZ=N0%NJEC] +M:K5V0=!HZN3SK@QUG1SLEF<@@G +MNO)`$2-E/;`8*>A(()[WS0F*>A(()Z$DP3T*DP3X#((O,"#E)LI\!1!013^B +M2WR*?U310%/PD$$_"28*`!.:N3%0`*0!4`"*2K?6-WFS=.(78GK_&4@].)>+ +M=4G?!6'LT0N744<[V/QMTI=T15]`3_N!/Z1GD-)4#LV%Y9Q+]&@U^2IG/8:%-PO&'(1,%S!\-P> +M3#1\%DR.AA89`[Y3M$65Y2(/,`O+"O;ZF9RL4>8\":T`77MID/PG?Z&:FO:: +M+C7/@B9R)9$W\L@A1RR-HH^G"OW!A1W^'E$DN;/0D"6;7?YA4J0O'`Y4U*^9 +MY4)#]`I;X@5,!9ESB/NN2?-SH40*&^D$Z;%+*$PH;QDO?\\:,O<;D/K+ETW` +M4^^I=$_\71=W;WVT.I+"1EG_66,Q*-//ZT=>N;TZP:Z]T-$ADOJ$%SI2(#5D +M7X<:SWW\7,N[WX1),S#4ZVY('I`+X)NNI:3?YPOZ'$YKP5W1N:H2\1$VB-D$CBH0XFX@=.G"H[GU=SUM'E#(A(^O4.\(\N6C +M8IUIQGQ7H9Z(5'="LIZW#RAM0D?7J'U'#\,DX02.Z-;?VJ!Y0Y^$#9V'U%(` +M9U`5'=*NMK5#RADPC.P^HK!#/W!4=TZ^ZRX#RAN`C.P^HM(!EJAA([J6%T-R +M'E"%#!L[#ZCF1#.D"H[JV-170>4-D$9V'U%Y(,_4%1W6LK@74>4%Y0&SL/J. +MI,,F90)'=>SO(NX\H8H(SL/J.X09F0J.^A:78WD>4/%",[#^:$#8AAFZ"H[Z +M-K8R]#R@ZE0;.RG<'Q(&7K^MBX6EI4)'?2KVJO@\H5H*G4H?G";14+OQR(N& +M;J@*Z"3S1`5*48$8^%FD2>J>:M(58XA\X@.@4^]9'&U:XC$N4.54$TGD4-*X +MM(U2^",D\L73&5HCY015H=&4DJ&;(*COIXU<+Z/*'6@IM2/KU1^#7JY/2(&) +MV+6!Q]>I/*T^V(C; +M1((VV15N(4:@HF:D#XMBXD_ +M@%1WULZ>X(>4-T"G5(NPG-5!8(%*$%T*BD\X61X/-6GH4=&Y/B$#WFCA;-!$ +MHVQOQR#/GVY2"U=7>X7CHCK6V%@87=`J4*JX?Z@5_)`T_7W=O1XY"9#*F7"1 +MWU^:7P@\H3DN#CZ]0E+A;^P=-0%1WV.!?\V/*&;"1=A.&!_LF@SUPJ.^SM$M +MAAY/@(]G[EM6RVY+]:'$T/A,EXML]^G-*)+T40LX%>C$DYF8`SJD78G*6A![ +M>;#+M,!([[7%R/.CR?):$W"U(IT+5>K#Q$[DFUH"U-=#^#R02UM;U-0B^F@J +ME*V%CW$.G0'.*1&W&U^<1NB(&8.,F&M7>D[-T1.3HVGP3@9WC3GZ.^W[7#Y\ +M>4-],,N/KU#NEQ)[-H#/H"H[[GG]7T(\H7:9!Q=AWIP?G3H9BYD)'?=\23Q` +M\HTR?4,K:SP9^]IQC'?>\:[XH?V>0=;4^2 +M.2>Y#KW(+M7H&]R1M\N9PW*N&DLDVYAVP>V"UZ=.V,=5+&@"W0:.KD\ +M[8,=7-(`QU=!8QU=18QU=A8QU=Q8QU>!8QU>18QU>Q8QU?!8QUS(L8ZOTKV8 +M8ZP$/\,1T&CJ(ZP;[J0QT&CJ(ZPS&O#'7.R'AQ'6(@=9$=8J6VD1UBYCRXCK +M&)0X8ZQKSM`QUCGOD1'0:.NC8\X.CMW,<`+=!G8@^`"[DM]4QTU`=/RQ-RJV +M-^R.G>.`/LA;'60?E!Z`+8ZU,"+8ZYK;L>H/L#^;)M*P.;6"GDU,VEE,]66\ +MG4P\`Z.<>SW>Z^#5A<6A8T+>]\T)L]66-"QL6*\D7VP6*\D;?T26^6>K+&A8 +MTYM,T!HY!.W=05)+'6?=EUMERK$0!`G#B==8YN^[[$]N2QYD`LD\1#O%O +M;O[6;G>.B%\U10O.PG1_,2WT]$^8]F%PT1W[6NH1N4AYM`,@$RSB4Z1E0$?0 +MTB0PK1!O"H67W)&E;\T)3*$8+-HX52@1D8 +MQTO<)>;/Z"GL4#E`=9"?!)")CX7[4#\PI!NHO`PN"$EXE7#Z)D3,8O>.1OZ- +M`3P)MC/PI^T:[]+=T;_[<$J,RU,>XE^L03>"IO<(I9_L>7+E4-F#^L7_!H_9 +M3E0LP?U)"X+?T*.F<\B69!$S[=@5=8T\,Q[Z8V=1`E]/;IC^Z0ZD)J@%2#N[ +M7T\/DMV*R3]=,?WXC]LR"A!-B`A"JV1JTS#R4XD*:"5'9Z.:*=+ +M--3P>-HVNF5G14`92382._`K3FLID]$B);OHF4;QNW.T(9F +MFG$T=^#5=/T0\H?DFV7'UZA.:LG$]^?FWRB#/::<8QWX56\#HQY0 +MW8*;4CZ]47?#`ZFC#.8G`D=^'46'R0\H4TX!NJE"S7ZEANU)Y-R7>,XHA6A` +MW/J-N%HWT&2AG]60)]OZ1RN+TAREA:0,T05'?B6+C,F/*'G`IM2/KU")/R$1 +M-H:P5=9)G][A+1#:Y6;V34/JMO([.;M(9_-IR%'?BVQ694>4)ZT,N/KU#^3" +M`[S:@R]V@)'?C6U/]*/*%4EQC%V';-@6^9VI./I\+A'R(NNJF,S(=KQ:PSK& +MG)T=^/?/`RP\H:$%-J1]>I3N$[C5S5*&>4TX6COR+@5S(\H09T'%VXWZ4*8W$TXI%V^PY%]]5BXQZ\*CORK9[G-CRAU`*;4B[# +M+1%TG8D\';GU*WJ0M+D[Z;8&>P%1WY=\;FN'E#=@IQ2/KU?;,T-NRG,:-GM] +M%M#)>>"1WYF+]GG1Y0Z&>!Q=A_5NBBW5V?17/GIPRO&H[\W-JW/CRADP4VI% +MVBE'WV&WEN#-FTX6COSL=N&@9_RCP4OEX][6S5HD`Z)NWWZZ@,?3X2.[`2MX +MZ@>4,)/@X^O4.=]4Q*]IPM'=A'R@T3/^4<:;Y><4CWM;-3L$.E"#[6J#/T!4 +M=V)]*GJAY0X82/KU<;O&'/@]1;PR@H`D=V-Z]_U8\H0Z!#B:+M'\F/>V!YVX +M!G2M.)(_LCP:8>4,8"G5(NPD_P?_GV^MU1=;]*!OK=3FJD3`:Y$#'^3NM"UR +M'Y95$#+F[+)]\@PT3]J,Q\(G/='&YR#Y4P7@39Z-'6_#2*;?NU`I.5':BXAG +MF-.FH[LLE^1J&?\H^.F\@1[VMFK0'6]`\[<@R6H0D=V;P\AUH\H*4(./KU?\ +M'EA;GKF&9EIR%'=G];%]>/*&)!3BD7:+^3&`\G=`SS6G&,=VCV)[L1Y0>T0& +M;4B["?(-R70-_6TWQ$!4(562?Z`5$QU+3E$^P*Y1M.4\">5.4@,@+\UPYCE+ +MK&S'E#^X*;4B[?;>4-N@\P+OBX+)7@,O- +M&$CNVC,QVH\H9^C!L[(_+>N-].A"[#UUCM.P87:($.G887B?,4@E`6@8ET]@Q"% +M.(#T(,MT:^X0%U#%J3':0`X!=2Q=(KU0#\`+1(J["._(G4X+1NVNQZ"GZH4H +M-L$8AFR7C!O0EJ"Y8)=`N`XE`2=N1$9E%V3S]Y#/SM/1([MR]^IK1Y0[NC9< +M?7J4[C),JQX&:+L:E(WE>G7:(MD>WF865L7JWGD#T@%X$]$!TH%^$]3,N#\5 +M(24.<`NR3_@T.@R_-.38[N#N4GIO[2P]+>XGQS!D1D.Z1Q%3`4:A/*=2]3$:7E) +MBC4&>]R_:\S,(+;U<.JLN:LW"/@'X%@-(!(H@A(EL%K:*F@C)Q\Q(63CJPV1 +M+UK(E#EI.EY6RH`:MH60U7C+6Q"4LLS;P-GJBA;"(E]/F3K<<"_CYSX%F6*] +M3%X-)8*#H@O2%D'!4B%M%R2LB-EG7L(P$2R%/FLT-N*7:3:4*P(<2KE0E:95 +MD/I\[99@R>L +MRUFFAGX%DH_(*@(W+[-73D5:$1=8^L_]HJGV>J +M0N$%BFW%,:D3[151XVJ!`LM1F"%R`*1XUN"2CEQLJWR;3,@_V..)V\CY@GL1 +M]9E=?AB62P9*1\ULK_T+X?[0QNN'ZDK9G14 +M!NNQ:PY=UOA/W'.RU[+)K#D/E]R"6%_JVXXPO_>.,L^S5SO]LZWO^O%^_^V?= +M_^HM[I/]&4G?ZYN/7)\13_];INW_LRN__J'(*?^RZG:X5UE$' +M#EQW9AXRZ!IF)E&N&AO]H][@_]*J\7Z"DB]%W>=R)OU02/"?'$T/_*?:/((# +M<.+)MT^01+K*'E`3AN7>X5=RR&,84,6 +MVOA%X$1\F$=6Y=_]XM@0\9#LO=T45+X@HVNBAC!D.YY>1."+TQA4>[["&0J@ +MHUTMF*PB&L\+V;+YGEX9+&Y4K2VT?%<)5=5AH<7R0U>:HO\QE"'0)0'FEKXH*30-\O):X +M04G&2E1))!TJ%`0M0(EF'C*U+:E'RZK40A3,.L0JJ3!&&G38:Z%4/WC\ +M=[5/[7C;=T>5KH^!SG3\=$BE_3YK)-PYE6W9/(9"W9^Z7+'7*X6W-9!'_GFC +MR9>UN/]1MD:4V8S( +MEU8EZOLA?.!Z+-Y-H^7CHRB,L*/O`PME7`8+"W]HHV3901F;Z?.%XL?A?N"@ +M:*"$%:BJ_,'"9%K;R9*#F&14]U=[O(HV91-X5 +MK$$:B7D]\0D4%,F,D#MUZ+PEZ8]J0$+9->;J"V-Z4,1QMLJQP2-12IB&A"$5 +MX*Q#C!37(2!VP1ZD=FA+9#$$7->L1]*7.EGFT:3]CW61B;XTFM$")6?ZH057 +MPE:8@)PMNAK3B:\A3?+/TH*:VL0C/ZM`7N\-1[S;SA+<)'WI!*Z]6UPE;2CT4;JXF(N)(TM+?*4=L&01?E>Z-/"51Z7J3(:=%" +MOJ484-1I<]RQ#,_NB`V)),21L8/CPB:"V<.4` +M/R/4N4A=DE3XDTD#V"E3JV7H@-V7QL#=Y<9(?K@T%'=@R]/Q#6Q9"U37L`1P +M>YY=9;IJY:!>"52TQ"@'>=1,%>:E@B1!WRZI/Q"G86KRFI5Q);1_$YB%YHDC +MF"D$B7J"K2PRC&),MBW<=^'=00FE[\ODV#*YD4BHQ71%H.D,D5323JG\*^J? +MLY-.UT_+%O*5E/JGLK/R[5E+7)L:(HG4?`U7FBK%N)L9*"K/*GL1CGV[E@AK\VLN=8102GV.0[4J#+D3?U&>V9ZU!D.&=!KPG-_JKN<0BY +MC*]#&2A?NT.9\ZK5%+@(&P(-6A*10,FGYR?K)GYU1-YF+% +MZ=V!PY(\MGB-[G%7TTIWV^(6)?=>QKV>R'T9'27,Y2:&\O7M9R +M_Y6.R7HSL/2M0V--KVJ(CV\LU/U93&^`.=HO,D68!$JB(TTI7E:\)-BX!\0O +M(;I!U=[;2HO(]N:ONCG"8C$114(VK19KU-4G\*D#2BMB0MA2/1.QB7 +M8C[VFLL_)]U0'3^F!P:*D*(B.5);)E/17L;8W53'A-J<52E@E>>;\DW)NO3+ +MS93.YU#6Y?-#"0KUJ2PIW9MD3QU,:=-0:L2V,4W,D3.92R#LBF4)8G),\:\B +MP^+T]L#KLH5=9.`068K$8!]:\-A7A%`9BD^"N[2;5B*[""O(8TZHT+!H/)39 +M.N,5YV`=5[>"80TNC`)'86JXA,X7X5Z*RI7L61ER0%"3X0.TD`-!6*A=VC"! +M2!/9ER+,CAR53:$@6#0^!4P32+D0WBSTGVIH\6$F-47O9(E<$WN!`4$1@Y9+ +M7A/P[]4EH-#SV8!'22/X?5[9;M:<#W:&W;+GY$OYK0VX;(R2/J@[=$*GM,?@ +M0SND1L`,G@U7`3:9EELGM=JE@0I$;I>R%*[`')X,\FQ$?*2]^,,[P.MT:&4F +M)C(MB7=:\RP;(+=;/WR8UZ0ULX"*B:6--@`KEYHYFBPR#$\1ZQ)DF[JVJ'KT +M(FDY+:"N3AW<&TR?6K/=4EIJXH<^+3&].5Y,3O(HU;3J-U81P<#.D9B(]"7J +MUM)_*M6=5A^[FN:2YUB4.8VBK6MVJ,-MR&[X_#DAMR!4P?"4[DF5P +M2*M3)VZR>Y7558YB(:T/7'9NK[)-;1*1'89.A%I:@VK61SNU<1*'? +M?7]@U!?*5SK%1[Y@I[3156GA6\]FW`[A8P8H9;U:,TUWY7KIZ:HR;)/X7\)> +M`T=7V\0L5YE`C&-X\54D%:2LB[RS4K@-6F&E00N8AQGX")W$4=1CL_`K^'8G +M/@`KU#"L8DO_!QLZI6%:Y6\M>V$4VB+CUNE["R*Q":M#7X!T?PYPAP)-'Y]`LP%+3K!*L[8A63(IS +M]G,:^NZ]K"2)LRT$TUN(-*8+E;;>&O*%@[]IE"2S5@2MO\F2>T!5R":K5SQ3 +M$F<$X4'*D[CE2NOM.2'&7.D/!SJU[&U*QYK[%#&,N:0PD/&D6X-FCCM8)]AI +MI*X*W`D(AK6_>D+E5!\(BM9KN1:W`'7<=<(+[",-%81+_DL0"B9/QEYPAB$; +M"$GG6MJU`'6>.7^P'1NK6B@,KTNJM:"0)VE,M+8S4&=22OO3I5L8(Z:OK1(I +MS9A+*$A&97N\-,3G4U]*UI+V>KSJ++=QZ=-9#CR'K@;$,LO==]I'01V[O=V0 +MEY\WV#S9%[^&0E;BOUN)?'=81"Q)9#GLK[\J +M\/?EM\$U/*>8F5&-@4P/A`%:4JN^H7>FMKE@CHKIU;BJ6# +M"ND\M+E:].N;/(]CJ1>%OEY$EHF#E18?5J3N@3'JHLWL&$8=?>*-RI2_)K0" +MQ/^%;ECLF&2;#/9>6!Q=Q_X<2[VQ0`A_A#K+L%@28#(>@JKDLC'WD\W?D283 +M\-D*VM-49[DSIEK\G++*,%(L;Y&6C'>N3?984V*2^-(D2/8GF\M100RI=-R>>``6U9C +MQ8=Z6."+!HDT%"*_N9PIHSA*,!(1("M$1#E*\VUD#N^1$FCQ/G9'7'A`Y4K/ +M8KA9>`!GC?)FKKRO"93+%4D8O;6%--39,LH@*T(AX1&*5R:L96`71'-J6H*L?+X(-HC:H'>0]-V#W5F/Y+L\6Z6N6SY0C!E]SXB;[$M-H +M5Q0I"LMSQW"V^$QS2SS&+.>'W@W8]@ISSPOQY"L65=%`PJ8H1#W/O$$*O`E+ +MWX1TM`WK=S&A5YL606KF8Q0)L;2)<]$6+13O!7D[-8TJ8E;UE"8>]=)I8\O'WJ*T5F&H3$,]*>5*L% +MYYC%)*D_7\TK*J'92C.@(98?HL;ZK=BM^M\0N=G%0R:,7=6IRY/!Q#I36DL& +MK=".$FP5NH1LF%WK2T!`B%+ +M;9>BTA*CIT.O&,(G*1H'=$@VRL@18EQV(6+(QC-Y,+$X?HR#H26TK/NC*N(G +M9/Y8QC%4ACC:'G,T"[G:T'E0/.'(SE"'+%$(H(AHU1"4[+&4^LCNE`TL,/QY +M4%R.6E0:6?3E2TE/;2'AE.3QQ,0:LMPO)K;?1ZY>26D[QS*SV\7T@[ +M]S)X`6>*?5UMP'`1BR\)5%43=?U7@$,EB#*$O3%@>JK;$\UO8_(QBT33D6I? +MU19;#!55)!:#@UWPDLI.G#JJEJ1M@>7JV!QQI^64;:YNXA-9T*`V!N.M@4C_HO,$+4 +M9J]O2L%I`[X-!,8FS5J^$%M$7R`LD,/`UE9A-[.$#=V\%)CT&2>/,V +MWFE/):X!@%EJ4@6?R>$F\Z%D$V[0L!:LE!X!SM.L0Q_A>7.K&8V5M@Y]A>45 +MN!,6%M2A95&5_[(V+^R4B-$"=N$NS^H+WWAV-Y[;%0U"5#'!*V#YPG'.NZE! +M<OV=>;ZJ1U[6F/V!_TG!QH\ +M2>>L>S`]\C.6;"^P9.MA5%]6QN]\:\;Y&97Q1!MR$/)"-Z>54%*:8G@V?/!"/9XR;(^\D]Z4T(TK7]--M,W!G< +M[CE$B5*QNQ%\(AS\JKCY%O+LEG`K])YP')(O,;G$'-@JQI]^3-4U[J;#_=NM +MZJ^+70/=B*N.P4_X>NI)_>Q3QNN6_\G7)^,UVZQ%/MVX_U1QFNTQM=26^S:X +MZO]BUO%JA5B,=8>R\+2?76)1= +MM,'$3N@U7@%=JQGF$Y/\?^5HBQZK&WC0"`MK'$M$,5J_7WPP,\<45J$3TLCB +MK3E>U#__CLDV*"N6V56N^!^M=U"N45!@SO_#^GVB\EOSN,TE7V3W +M*R9+*0WN)769$M9-)&/,$G]DUF9BVIL0RU6C@HN$TOIHH5IR%'E8O",(\D*( +ME3.\+5)"NF"MI+&=%$0P,$`[B3Q7!UCU3N+A14Z-3.5SJ2FJQS"3FJK?R +MMZ$P!"5V%+=,6Y+S1V46DF)-CNMBC5*<4VV63N`FRH!W!U7PB;O3_45*E2=U +MX@KAY?B0RY$E%1*(]Z.(5I'1E;YEHZ.F1!GZH!"4../:1"O2@FO3E/1:>CO6 +M97+39HRH9L8RZ%R]X]3K>=FG/9&CQG!S7 +MH/$H%'%L(]G97G/5G(*.5#&-6V=\B%EJF"G_=%=K"UU'=&B=/#/!R7@O70P\2C9P$2H.2E$`Y#L0V,?T(?"3F/"$J.*Q19,JARWX"+D)GQ^K6;R4F +MN5>R@:[X.:T^H=@(C$,-4DPDV#B*+=E$T`?5[/Y*E'*O1>UWM_EIM1%8#PMJ +MKSQU9=XU_HU&'F@^H#[$CR5N>5>C*6]T.WAKNCSGZ@A-ZHG`3N-GI;-24QV1 +M/-Z"'RVTFH\EB\?>-)_4/W]V#T(?8^5NDSXM__W36:RP>^UGOA_]66#WS]7P +M!_]>@N#/O=/\0?O^<#ZD/LF7Z+E:I._#_;_NNLYF0][<_'_W3:;Y\/?,S\G_ +M=+VDO",XY6J3O8^4/W_2^[>:TV;R;#!]XO_!L:25<*K2PC],>NKSDHC3U.//7RWHH+>G[9%LJTY;[5V^6/=/!N-*G +M!`CZ\=`*,;Q&OM[C[MY\E'>3,V/O'M?3&KL:1>#OO#3GRD(&?]3ODM7%OO:L +MQLBTZPI+MD4@^/$Z.ZXEDM5].6X$!TVTL)`A#3 +M#MQ9P&'E&I#R6":(*M'#LY"XPM66`\T'&MU_F4Y8V5^5_7&6NX_*M.EQ3=OU +MV-+LO#7G=DO<6)Y>W[1>7O"ZO`8Q#%2='^U:USA6D/<8]&N=.V,^?"G]-)GR +MI;5J"^5=,K?"C>:1Z766T"N"4Y@H.D(V[56:*FA;EBEDP_ +MG-6-J:<>1Q$9@K_'+%8&88?D/>2XXNKA$T[<>QT.>;@D`-0?)8'>1T=O(UP% +M][EBKTM3XJ\+X+DT66RK$AH%(UY(=L9Y*%*Z5BP0R]7V +M3^IY-A&.9]$9Q@WG0^(KF-]>)JH;%3_5Z!;LM&K;%%Z.\KTA>J6\E_K;$/W6 +MOJSZ\%"K0[PM,11)EM*+3,\AW+U7+$W9AP^0M=O4A.%*BE&%+6>J\XHAU*KJ$1Z,'7O&\'YO&F/<]&M1"=^;5N41T+O`]../WV*,* +M^^>%HV-4307IN$M!]@_&^*8.`P;E``#E``"```$"44\@K5VG8`#==ES=K"Q/ +M5P(;"X'V``3HJ!;M@P*V0J=E@!4!-VAO;64O86YT96LO=&5M<"]B=6EL9"]U +M;G)AD75]Y6EE$6MB<^R//L(18\[;_\R#E`VW`?#QX7/(-98"P +MY!=R']2/YR.\H['.0RV1\3IN@QT'\/C_.,5W&M7^:"OZ$G#%. +MNZ+DI[;V,1&Y))7,)K^/0K_7IY+#/^\+8O".0P-8CD&(0+_LU[CP%UB#=F\B +M.\6/DR&/A"Y5JEM02(#J(P"Q#7+N0^6JV2**PJ]NN\3$E#%!31!.>T7JN/I9QV%@6!\W6>H+C.I_4%R`"(_VJ6:Y@T/CY,`OM*?+"E5:OKFN +M1';Q:DTD;DP&7)-99:18TA"-/N2>-O9Z]_+%&^*4L+2E<5\Y6_FXTB#->&,( +MD_D],;Y+K+]Z43H0.%#LCF.<7'JAV(Q2UH:X50A1N7!*\SB3Y6B +M\`J2[]+*X0]73.]3:"-M9U&QR'XT)O\CIF\C[M;G/\;Y&BH^\>IT,?<(RIRY +MR5:MJ3MNX\-NVWQO+%@<4^*_WRM4A?YK([%ZQ5SDQR/+VX^_UV6_T9ZS:?3& +MA?KI;R,2XPH)@OK(B-F(CE7[L[D01WD52#[PUVN6SXMC6AE"BN9X<8)X#\)6_GK%VWXR%P0+:Q\-LB'(8$N88NT18R>7]VMT8 +M;/Y#JX^\.,M9+A*[W[?(MZTRS5PP+V6$%T1'5O*<_-LEPME0/H^ +MZR]EN]7OG?VI1C=MT<+WD\1J7(_Y#]);$L0D89_$[6R9-R7-IUJ[_ON6++X. +ME#WOJLS9+OS5JTL,[KWR#WF>37@[C,XMI87V2(C7:Q->#3!]=XWR(6>5=AUK +MM&(-\"];=ND3GH?&4KV,%&I1Y8[7O+![_;NG#]+;!\$ZA]3G@^N\KG&(/I:" +MRWSEJU]\T.I\\G:==SB"YP`N\:D"VISR1/1-%SA++%6P):@UQ8.GL>:KHHC( +MK:94JZJ+<:M;IHU.NQ76^$Z6FN#J,%"LWP6XL1^H;=/UCG:_&0!,#YU%=7W% +M.6'.YD>1%=RM5VE>LX_OY=BF]UPBXS6A\@XSOLL1&T4]O?PI]RQ5[3\AT(?G +M_G]?&MLQ"H:\>KX2H"4#X(U?*4CM+;.OI^0'H@^NV7R(&.5>OPUV+=8W-)-B +M%Q[FDK#Y8LSTZ8/>]]V5DNP*T#2?6YGLUQ5.CIY4WO;KR?-`OK8)=9;$GO7= +M:4;UV[BG@F+DG%;)$KFI0^NZ +MA='`'GAET@SI4<^>JE/4/1'PPCKH:MNEWPR@!6U'2M'!M;P(.L2O*[U&7,%I`O4S>"J=R\]M6\2UKE@6L^[ER>SG_G-R5^'N[)@@U=^U!>M90"9K_A]:(DBOM-&Y$,GY_A$L&PQE@W'B3*?LAOQ +MA6Y$>^/"Y(#_':KR)=!=_O6/1**-TY78\U'P8R/P+/SZFON4=>+7*"&CY^WD +M=CVD^^UB6`=+$5A\=B5U#]D9>?_CEAW,%LGCZ)#[QA?&#^&GV;?- +M;G[MML?>*W]'_#WLLM'+#O&4CQWLN5O18=K9*W,'WMDNKXJ,^27=_ +MH778^5=;"F%:9>.WC%/@AM$&_`%OX=KUW*N`DTZL/?CIULT5OFCW@-S]ETW\]5M^LT:WSP^Q\K=*$[Y/_3Z;[/*\L.JHP?Z[S>>M%"TBK:2S"UC5E1<7TRM +M+9X!,<78[8/@%7TMLL7U+(55M4,X,G!3'3ER3.2';81\!KYVQ!KP.>#XKLGE +M\W8DI,<\1*M9H,PD80(6>`$A*!A11)IIMD3\*T +MFXW"T\;2TIJF8>&2Z`N6D(!AY4"E(!9#PAAXPRGA#(%'"X6PA"-Q^\SZ/73 +MI_L$(=S2]A3:FL[_L?5K2\">WA;6[QZ/NM.S\C\F]_UL!17_*K&'ZY.Q=;L_4=3?K82956;^V=D75QJL3-=- +M[5>@ICIF<+GT;KI1VA7D6/:P\K]6OMYP\Y_TY^?H;9M>%3?5*C&83$S>X/]O +M3&1+__P?)A,652&&,5-:KAC6SF6SMGBV);#>64OQAKQ+.JG&,)H(7^!T\XZ^ +MK7:PHW;QBK=XM_Z-OB8Y_>XCHAO)$=QN\IDB/:O+[5".S==$/QCR$<<&]"N\ +M6/XLVY5K_3F]DT<,<(6,;N"L7.?(JP3;Z;7JK^[`_J^K>.%;;=+E +M;O"/]L.9G)&H?=0CX(ZO1"3X&]*]UI<QBE/V +MU9$P)H/1L]!/^]-L2RY:]S(,8R;.?XC?//XN8)+Z)J](T0V3CZ+'$DVCE2/_ +M6;/RPE?+'W#_GTZI%T&\:)+;$S/3JV_8KYPZCJXMWO5*W[&8'P:OTYCH6/I= +M6GHJ-X'MQ>I.1(_2CK0/NDP`/T)<-Q<;2%ND@BW(Z)MO3"STCAZ<4%1^&LVX +M1+4+'_FW^V#=S&41]AN#2:">SAMHT7.Y6FA!QT7-EO\K*6A)D:$'-D(YQ!C1 +MJ(SCC4I,'`:8K+I-XUA1G:^\/T5`^7CDO"TSS0HPEH?A3&"-`ZSQVN'^T0M: +M[?!M*9Q,/WT(V"1D1-HBC$#'/I![+KLYH!Z?HV[)SD'P)BZ+@T+R!`9@<[>T +M3\3XJ4=2[J'[\I=3[B]T'FGK*@.HY!.7'9*072^_Q-7("A*2L;L^]4C`?>N4 +M!0'U%.WCY]5!B7*4ZH=3\7?Z@HQ%_AHB&8D@29XC@]<`_L@E%N,&X>5$(MCJ +MJ,YE,<:(YG<`_`!S#Z3%_T<>"(_#>72@FF+#OUE*^A4A=88?$1TJQ--K1``5 +M_2BYK"HIE$)\*;152!5;$58&K+;!_=8J.&IMKA]-X*+X].ZF14+8_3/)]R]R>'@?%8>@R*&121,;JN +MQV5/L\?DP_;PE'\QBFM4"\D?B).L*C>7]1/$P^0YJ'TKFH*"36">.8-(@6_S +MH@M4#WOBE+W0)`@/.O(&XA\N9XH4@=3X1M-1/*J<\!4JZDN`=R`_4HY<)3,K +M)XA[E3.*(1I?1"HN45HL^(;P3A^5HM-ZLH^#M]3[+J&H'!Y%\,$C@@3J?]/= +MJ%JQLK-9%3X$,7AE"['2/4U/7&-.`1.$YC`@'IK*&":=^%6(FK$IHJ-A]DHV +M'+V-KLU>80_CP?VMHM/6@R49U%[$TXPIA!TOC<#7AAI)A-$^/)()B0[7R]F. +MPI8UE^H6#=4QQ-!:KORFM8M!2ZE.>'B&T1JIEZESB(#QFC`(DT[%#4]G([(0 +M6P%C\59`\TQKJ,0D6!B@(3"DXA2!!8<[!#1\2J$;C;FH2J/4E$$($!L(#J.W +M;YY7"%U'20H\'Z2E(V>P_9DFJ05"JNHHSMA!00]N@9SJ:PTMHLP1,^_8N(#B +M"?R8@>.R'ZZF?0G\JJ46#YYM(14J8Z(&KH#^7VX?[DS;VFG>,72G.%,ZE#E% +M$$4U5P_R`J]<\?UGXX'Z=E`\%RB@/H+-A:J&G#S@,7>I +MKH1PNFH+&=Z+AJ%7`@&DF-)B:G4=R$IA), +MW597\)Z%ZE/4$III'NZ313HR,>#!`TF.B#2"9!*D<BG=5H(8L-3$"C`@:P43`91M^5Q:OHK"+B#U+G?>)"!I44 +MFP!I2_9O,E*H6&]8FL8M(*,U"?B\0&I@(NJRF^*0,]GH2DVE%%3JZ*N<0_X= +MD02F*Q^6@3EU(Q4,)FL*5U"9M(YPF?UAN:RA$F*E-!HRICR00=@@NSU,4Q`- +MHQJ+()'P.-?X%!IY`$&7A0RK$5XW(0;D@""-3@6>']7IHR/WTK*:%+`@M`4FP(&8 +MGS2HPM::JE'Q!#]FTL*WD!L(\GI7H!6*D(8&ZE-,>4_"9E:"$#%4:Y^(K5L(4_S.VK/? +MTEER%B4XYZD="BA\]@/*?5F:!+$O6P-)-6$P.(8O/';*EV((?B[IJC0$*6\] +M=Q&<@BDOV#`&Y>F^AY&B00@<@N(-^&IVBX?*!SV%6N64X/=?T-(PC%5U0E>@""P,Y3,TIG +M.X"&1#<0@+<1"&,J@CXL7U6'EQ/:NU=.)^'T^QEY#7FD=R7AHF%C1#8/)X[/ +MN-+ZI"F5#*"DMZS$6"T4RX",=*_KEV\RD#Z?X'N&1'P?;J*C\\Y)MQ\A*BDF +M@,`\%#:H6#5,?\=_*:/3:;HG>DS_3'O_#NCB\O'_'^#*D?L^*N86#B*A]/$R +M+M!)<"PGR\;1]94'ZT^H92I60TFLYB)5-4C-<,7P8NT#TB6.A`J`;!03K6/R +M#CQ?#5M^,2HQJ4/N6()=4@',&*:44O*/LD:W!1[FEHK&_$& +ML]`_>Y&6*B_;/#&5LP1$(-(LK*H8C"D&(N!I-V4$V3_,_#=AX/R/$<'L:IX; +ME!T9R0B,,F^\1)6Q`4A(ORM*@]10F8WV@/& +M#?9MX.4]$Y5-C">;3S*1JGJ[)6?48E$7BM3[ME4\0'"5N4<;&U2+DDTTSR6][(+*[]J'"+*: +MG_+*I"502R531^),ORM;]% +M@:XS>/IMG#*UL.G7R7UGM*Q0::TW<-6K2N5ZMM=^EW=0^[+).S-WV.52TOJB +MV3*A9LL;L?=LT2N2=;*]/=KG/&K4;V[9V6Y\DGWB%3E]#8]GE^,^OVQO,J5I +M4@V&68EC=(X4+BJ(+\8=U.$;YZWQ>2T?/D4;J:.42`G\ +MVA/R7;=?<;FXVM)7]M7WM[B +M]IJM>RXM?MMIX>J6&T^+*;2^/XO51B7O8*%P\W0=GB]OFLE^'[GN[/_:)R5] +M"[.^6S=9Z]!P=U]>:4R?I>GJNQAW@W,A'*MX"4'HHX]%N=M;<@J9W->S\.*O +M[''R2-GF:.X5&/G:2=Z;K]?4]USEBK']LE^G6"#4VZA]5L%-5>:?,>KJEA_A +MY&,[_\VXT?F:#TO4_Q?\M_&O[_5=K`M`W9SVN\?^UG">>K[>:RNW$9_0\!3% +M>_F*;)ZZ;VG8FV<`5?U/M]O8=FJ-EH=C]_5>YM]EO-5#K>?P^>4NN.4KLE1* +M?\_SU:F7V]AC5-MJ>)I.PPLXIKM7-9?#=KGHF/L:#M9^*0^\&>]@>,IC>A$OWJ\WYG\QPO"P +M!N>DKX<2^WMS#4N;)3AT]YSP67*@TPPNBGH\`B*0.._17?)XNIQS$E_;1/Q# +M\GE_N>_MA\3I_!OH=E#N[I^IT7E.4KG8@O^/TGD"*>8AP_?RO?.^)?<*'NF[ +M@G#_C./'J6.ZR.`=G#OHFCBG]M#(YM>9]CDUHP_#X>'X&'G_5F^VI;!1WWWX +M/$4ZGP'G>NH>.PU!V&S];O514.O].N^77U/;"/>3^3K+S,0;I[X?/]_%'X_S +M<__+PNG5.MV&[[2L4["C!_]2QJ*[^O4ZG=#I1;/>=ZC%0OR*CG-IT?DY&FJ] +MA6[S6:G29_P5.L[)3O/A[?%UOQ=\IM=KX'MJ9#?WN,ZJ)^E2VY#OMO_?F9JH +MVN=GZ[RIC[/9=7=\MK<7T6:_+8]'N.3^UX_+[_;3[_J,]1;+X:Z;O?KP<-`Z^P[N_I^XT?L=7^'7=QR76 +M^WWW=4G<V>G7,Q"AN)V$A\`IGA;$4/M[(W23P,3DR.@O$YS\B7 +M0,ZS<)B^=-H]F$Y\3QF.9FSS:1/B+FA=L/P:'`A#:A#Z)XF>C#K0*"[FB"E! +M5EY(F;F(R//_ZJ\&P:LY>7T6;Z:ONKV_\[U437N^;VWEZ[Q/P:^[V/\,3FZ. +M.XA_VNM[KE>:]8=/TICPN\N_5[N%^3W<2U%/JN\?Q9L5,?Z'.JFZV_'V_-12 +M!-H:1^+-3DK.8Q@XE4\_H(HW61O9OQE.XUNB#=\GY=?VO +MW=%IOX=I6"$.$ZCKLEV?MY_$#+C>C0?VR7PFIU-#W_CX_ +M<54[8[$VTAZZCR[K7=S7JCEMQV76#)#^1E,IFZ'H<1R"A=;"ZGP+ZSVP+E[[ +MD+V5.7ZOT.AU?/;%3V<]W%;4\C5C&E8NR)Q)DA14@.0./A34.)-23=-(WT42MN&V$4.@)PIWF%F6F,R!_O" +M_Y1W\3B83?'A\T,IQ.!=3 +M5[;;^XN=_OK>XO;WD-X^[.VNKL.*[]NK";#G6%W:V>]WMD +M7FQ']8VMUO[.TLC>+R\LKH>MQ:\"VL;FXL;*SN;&T!R^6TMK6UN+"SL+"XB@ +M.^S!O#&R'1M=]]?XI[U(=52V\];@KWEZ''=='W=P'7>V@<6]O+6\W5IN^YZ? +M?VEJ&=K8;T-V\O0:[6WLON^N&6^X-N#@.C9V>[$!;2]^:RM=W9\"T^;F_)MP +MU66_N;3?V%SPAR[RUM/ST5EUNL'"W^4GD&T'+YAZ7(,MIY$">!<#J"`-T#W9<,CF([6HB +MI8B'O!O/AO-V(V_/^O4%'<-=MOQX$>>`()6]M;<`CU;;VR@T'-6UN74!-N-X +M(-B!XD,!3B3EX6%C2;=XB/%R]FXP\3/$4Q6^98N96OIIR@PIA^`9^.4?HD?8), +MW4Y=R2/G_VGQQ%ML0O>QR[+WQ'4.9;]G;7]W.16LF)`0B<8?YB1#=(=K?WN= +M?WO8%_B'YIF(APR,5C%F>(Z._AVQZ(.U"CS<-NKO\5OH\*:9Q=H%-AI(]0*; +M&GB5,2=UQC(VYF,P?X.:DNX><5D#`_%7T179EAM7)[O"87A\KN\AN(O6(#4? +M@5^NO@E[N.S_G<@\V(V\JBA;AB$,5#M1>4=Y),W8%E$=X?$G9&?2';OA"8<;'$,/8[>?E!YQZ.-RC^NT,E$&8F)Y!&84H +M8+M2'F@Z-"(;U9B*/9#I'['\U%1LI9\')#G:E+_#"B%=/6HLCK(?$3_W-A*O +MN0OJ6GI80T@[50H,*K?ORYGU%545'2AB/GS],$.U4Y(MZ?5#NC'.]>0!RPJB +MJ@NWE76EI?HRMLAG)_.YN..0D/.#DJJIY7'TP\_'-340<%734U<3R:L0*5V- +MW4U2,\T2'PT0E@DBP=)&&S9&K;"(\ETB*&1``RAHAHCD0Z#U&B#T$(<;70A/ +M&(AW:HYY20U\U1WPV0R>W1&BFC6S>>R^:71="A&=Z$=KN")1XQ!^1U +M;Q_.9@>3(VF-S3[9&XK1QYV_SS1NSK1]9W,K+G54:NW/*IGE5SRJ9Z_S.75Z +M',LD4+=+!99Y5)Y59Y5)Y59]5)]59]5)]664+8KHC),B%4DGIAT9L2,LI)D7 +M;CJ#/Y( +M@ON/(*HE;1F8N@M+J8,0'\Y("^::%"C4`?.*``G'7PSAKUO!&O# +MVTO>"-1C,VL97'6#$CU@6UUB$X:MHDFK +M+F-5LN.JCH[JNYIJG"2:HE3U.U(]2KI]9SU(Y&ZCAC=0SIM4>T_8XZ>N3;&N +MG;L$Z=#3TWFFSC(UR33%SCI96,;$]*NQNDYDM(X,LX]I!:.:.4C=&L,-3EHR +M(D3#Z'I,_I.>=\]I>=',3$PK`ZVP7(1T6^@U!T65$P@([Y_2]*"YT"YEZ#G>D6.HTE`P;^?T>FT&?T;O3:'0Z?GM0.AG]!HPY$A +M6)PA68_G.<9%.S@@'5)I0CHPA6>A+IN:1`Q<\A,-:3K0*S.I-RZ/,"5P>7`] +M%K'5V9*H8FV,C+-)S."$0G>BU&D=LXJ(2-%BH-0$KJG2\*D0Y8%98Q0PH:FN +M2*%,$RL)-3=33"'4.*@W8.%9HQ*U!3*LD%9M5T;*1Y\-DNK`5M;D)C$J:!6Z +M])S?2L5GU(5RG2A&@5Q*:-V8.*Y7I.F0)+2$%(UW.-F:??<2).A=+20H'&5Z +MJ"X/SF1F@D<5Q12I2TD:=C6+5#JW8Z0_BR"K3JYF1BM7AD["I$Z0H`.(5U6D +M#PC@K7(B@FD^3BNIR3;]""MA]-1'K"26?)-3D79FD`KV$D02%>L$FLPKVFDV +M&I-1DYK(K<>5J*EU<$"MS20KV`D0RCM&6XS\H:P8_,,1E"8%JA.!K9.A!22P +M52G3&P6*X%$*_#I&&/"N#T`R6/6M<25Q7#$6D1LG9):"+"2.1%FCIB;5K.W9 +MZZD>?4G%<;"%A6FA!GLS+8KC^9.H24$\%BN29A8.%)^%;Z1E+'Z*%396MRCU@@5TXP`X2 +M^2P*ZFD=C8A9*^CXI%=9"LXY8%=:26.B)+%7J"LH'\;BOC"R)J39@L5VGK(+ +MC>`_^4*[>IJ?TC-"]R%=V"38FE$-R^EV&N,`CA5.@X5^6&02*/&`5X5.++E8 +M#<:A7BL&FHI4C`PD@LA9Q]QZLL"O*+18R:9E7DXKS0133@:FG9\RJ*0DY/H( +M5Z.-EQ'++A2D*]4&[X,E@9(Y]#`'%H$8^[9>%>TC6Z4@RM2^`<3^EUFHM&G) +M*)XH2G5E<'%T'[OR'73I6@+06FZ:W31Z-M$TO03)0<2?T@%?9E,L46!!EZ7$ +M036FD8Y1)V"94X`%/&BRV?T&BRH3]TAC1T]7EB^JN,J/8DXMJ0L"/EGU=3D3 +MT<5@CHKX>!LP%PQEA#B`\,Z%^6I@0C'(8'W+%4\'J;LC`Z=0;-`Y:BI$>T[T +MCZJ:,4/$_9CUI8YR+`ZXE.!U$+S^B#`@F"[VP`/K*JBIS-86(^B>[RGHQ5D7 +M9#ZGU9Z3UZ(15C#$L/(QSGC(CF7?TO^.495&"UH35.&:O]N,4 +MOSJSI:==GEGW;I+C]I;CSJIX$2)4*WFYE9K1=X81CKX#Z4__VL!:][ADN.=Q +MJLX5>/<6^/5K4MABE/+Y'`;?\=(Y/^J5,1K#_)JS8U^!6FF)&_^% +M%K+M&J+C]9-OF$^,S,.7R+G@X%9>26?_(+:[S9Z=,W02 +M0_\PKI[ZNBSF/!5X9U6DY/_@R)ZO&MY9;A0*Z=+H8LZI11;?,.0JK7Y46NFR +MBL\JJ?<<+7^<:T.XJS=2K(__SRX&$8?_K8&G4]HK/1S"O``/QOBF#@,&Y0`` +MY0``@``!`E%/)F(;8F``WD9Q%Y^ +M@!T!"F-E8G5L82YT>'0*`Q/8Y%145$1$141$145%1.^>;>U=^K-WCMV<@_CTG";^$.F?K1 +MFY=Y=U5>]ZKPS2O\[5755=5ZZNJ]=X7ZO?WL#"_PNS`N_\-K&I$ZZ977UCC$ +MJ9,:MW&+6GHV2_23&6)DIIAL83YEYX#[M"8Y>[NUE#9V+3S[#SDB\W0=#W'K +MET]BI$C2L5Y+BK/N31%LU-.5:XT"H&#=.8'5!HYSND".4WER>-,XMV2-@KC4 +M;S6F*GM3`](Z437!*Q2>8,LMH;3]2F3`@8%'3/8\;=F*C +M9I+#\]QVR-3`&D@!+,7-$ +M.//S@J'9T4]GF*B?[EZ@>XV"H&Y$FJ;ZO86DIXR0:ZV +MHEC][MY[?M>S=^OZOJ>EZ'G^=YOF>7Y7D>-XGA^%X/?]]WO>=WW7<]Q +MVW:=GN>Q[#KJ'6=6^[-F74NXMI,CJNIW'4=/TW2[39[+H]CT/0:VSU>JU.HY +M[G>;YKF;*QTEAHM#H&.5Y3DN0X_C>,XKB>(7X;A.#RZV)DV)6QS0U>$-5^WC +MJ%(2ZWLI):36Y"G$*2:4JDPDU6"I2U84RI;?^M#B*NMEELMP5*V8S",SPJ,Y +MPZ,]F4:/-(T^;1K^+1M\XAOCD=EG4;OD4>GR:/ESR/WSZ,WH$:70HVVB1UM@ +MCQ](CXK%%_9(Y;2HM-,CM^<1[&G1_7/HY?4H:U2/%U:/MLT9_7(9UZ/)V"/T +MZ)&FV2.OV:/?VB,[MD6]HCUMNC-;A`!NQ<]L)P(#"Y(!!(`@I(,"QK(3?L`= +M`0ET97-T,2YB:6X*`Q-G7ZQ;&EJ>$$21CZ(`(`(`:V3GPCE^!]$U^_]''MAU +M>&'5?MXZPTA+K>RDEI-;D*<(I)I2J3"358*E+5A3+[P2)>)2O6"H):I4DM)K +ME^L6RU4R_RM7\V5\O\Q_F`E[Z/ +MJR<"`PNS``2`(*2#`O)5T;G`'0$)=&5S=#4N8FEN"@,37&>L6QO411!#*3"B +M`"`"`'A1_+_.^J_SB]RS8D-+M219L+#I=J2+-@8-+M219KZ_I?PM7\V5\O\Q +M_F#Z$YWU)P(#"YP`!(`@I(,"_TBD-L`=`0ET97-T-BYB:6X*`Q-?9ZQ;.X_4 +M%T$"&:(`(`(`>#'\O\X[X*1[+_*U?S97R_S'^8"MJZ3<,@(3"\?9``2XQ07M +M@P(B1.PAP!T!$F5L9BU,:6YU>"U!4DUV-RUL<$DR9(!D)!8PBF1!6,07#@5EE%<%%1:5N`Q45/4@G`BHK$!4 +MI2MR!#@0(V'`@)P)+:6I6BLK2VE:-L%@I1&LJ#;*I:YP&)$0&*BV+12[UO,[ +M[\WO<,"MX/?OO??OO[W[_/WX#+=N];UP><.M:\UYKS7!A^+9F=;WG>\SK>9U +MUUWK7F\[FY-[#/[^V2$_!_[``@`J_[(`*H`"`?]D`&4`"'_9`"%``0#_L@!* +M@&V_[0```+<,3^UT^'ZAPX<<;[KLL4/^V5JUY0F>8CM63*G!*D-6TIX8DPW+NE1PIK&-SZR[N6G]:_H\(E +MB3#<6DNQMS)U1FG6T?-#R2[E3;+RARK3PT\,23+DHPSB2UBMX59>YD\1(RV/ +M_O1?):ESV3[?M91C[\/7=]]E^=RO><[@6H]\V6]3UG7-)%JA>6Z:@;/4EW-3 +MF($/3>?X?,>_K_)]+"_AT?>Z;V7N-;G/U+U`>.J?:1SA;SS,%]!B=*M5+:/" +M80"]92>GL;AJ"E26>$[]7S8G_'NF6@K7SR9Y]67TR$W!ZNDT?*>3A'0X80%+C[K2?5B;#"Z9R*S\XSW-C_@%NK>75Q97X`Y@T,/'^ +MV_K`7QX3VO`.[KHK&EF6A`#XN2)O^NC9RQQ/,-W7O#?WR:GE%Z.7F] +M*RD4\PW#YI3S:LIE-]7@+X!N+P+?OH%-.O4+X-?HU^D7PB_4K]4W/=6QGU%. +M'DYUBG$K]:O4K]I[#Z"N<4I[%?LF'%K]HO5+XY7WRN+C-/I:-U]GE +ML/][LO>K^O]D0]AW_:]5TW@Q#PGY^#[G3>=ZSHOC]G^@,_N/+P5M +MC,M]/;9^:=K^C\'3YGNLKG-MT%VMO*Z'S-% +MZM5J?>N_;=5U7+N+W\FO>PJGZFM_2`W2]/Z_`T_.XM[_5=O+W^Z]ZZ[?Z4&]_=>6WN3TVH_AW,+[77?R[WZ5MA7TY&]W96O>XJCQW\[Y, +M:+THE5L=?"YBFM(O+_D^[_2[WG7?O\[]?-7CH/TQ])F?FW4&[=5[OLO,]]3. +M>WYT+O_&]ZDQUV]&+\?Y]7HWG%^#DO;^+VL)]_]-UZ6\?D_IWGTK"#]OE?FI +M>5T5'2>K-BGO+"7^7[=O/W_9YJZ9;U_*=_CZOI_J?K]CL+S9VG\J#T^N]-_^ +MK.@K=_WD>K^QC;Z^OG?"9XW+^EL'70]_\VGK.EV#_M5Z +M_-9VWT^9KZ?\N8]WO/'_I?_>]S:>].8CY*\T)'W+]]W2_O]+!=%Y/TKI_#UM +MMS7N_Q\.WP-F"Z-V%G0S_E7'-1.U+P[NU>&Y_G\M=-<_= +M.KGAU\$%5QK_%E@7KA5=6,J\<%7XONL8J[F7J=6JJLTH:KWBF#JE5YLEM%65 +MEXW7G<_*;YX +MRJY1AWLO+\V1VSEP5W4Y^7(NBE,[+TM;*<5)OY2;4$N5>`PU,O._%)=3V\L3 +M?FDJTO+QR&LY<%W;#M)9#7Z2ZR7*MTX4R\[BJ7\N.C*=%+_?)$-AI<5D6&CE +MSJD4US)5@Y9!?FY"LN[,O0RX[MU,*7*MS);Y+TOLFHI?[WSB6+D( +MNN,O;JOY"+[J9<$<'UIKW#&75;]"%4N7>,9T[QPHAZPLO2TYE\E+_?ARG!W* +M*G$P>T4LCLG*=BQ?O$FHY<4\=,,O?*4OE77\A>:_2FAEJNS+,Y_+)K7*7?'$4EIY'EYWAFE52XZD8=Y+(;M&&X8NW,OKY?[>,-;*OR.01VX(;ARX+ZBG;J +MN*9>E5?/DVLE660ULQ?VS2JY>=HR11%7^.2TLF_PH72R"\`Y!X8NP/O!,7B3 +M.S\O]_?(++2X8LP/I<=2&7Q\O.R!I6:K'YI^M-)OQ%-#+FWNL."EY?]9\JF+ +MAG":62S@TN(JZHF=;"5>V/WCY?"(W6ESK]YI0%7ZS#IE7AY3;2;Y*4Y.7G#X +M[?M<=C:LY,YP"V,ZJI^KC,?D,ID.V[?*Y8>I)TV3[SN\A4XWM#_^0R^6$\9^\LA/K&X[)KW]8P&:&0[O+93Z_&^01QVTD^O5Y!F(-.A +M*@OG'M!QIWVV.QP*S5/X*^8W(`CSV^,[[N_`7$_..JV"KRD!D_A)^.@6R.1R +M??97)+`OSE!)_7,_XE1/9;(B?62[D27=]UC\$IE>W[;NP/$?O*JF53[!,`H +M)]Y7N33H5'T"]I3V#^L:#_BW;Y7P&2^ULH#_.3)'E8'X`]!+Z`YA-/8#UC>Z +M"6[\F?07R*SX`_`/XA?W(CY,`(NA6`K?K($?..*7^B9`_P^.^R@]8W+D7H4^ +MY9LSDT_L#0NB#C)Y#NU@?C(8Y"N";Y$_81^P7\$%/3*/_C@/COTFG_Y%X)WG +MN^\QF3;(_!)]`//08)*>"EZ:0AG[R.7)WO+&1QA!UW!DC%2U4$7>-Q^/00B/ +MZA/`1=>!V^/RQK3']YWPD,B)7(=SWC84A,BB=0CK+"6"7MHPR@/]F,";XEH\ +M@7&3XP]C.^R(GX\!;N\F(O&@[R);(]XR5VS5]RT^64?CM4-\H0Y`G(L/_&Y3 +MMD+\BI]"<*=H3Z)^)7IHKR#^A3D)N^\[5FL^]WD!(9+ON[!O*3_APO8M'K*X +MX#,B@(@2'Z0>C;N.[!'K(^!E`5@7X-F\"K_]YD=_D +M.,B`9P*CTMVHN_LW7H"_=UC3],H.^-=^D+^I8OK5=QD\8G[-^1='+&\E6#/* +M2I4'+2M\,@]DOR"XWI-B]H`!/LW#Z1V42P>LC5]]ELK+"Y*B[[SMF3_?:= +M1^:_G7T/_ID^./[XW_!%R?@X_WY%PJT_IC_3/F5_"6GI8R=LF4S]'1'_M +M,TZPB6D+HO0XOC=;;SM!S_I\6<]N)XNHYS;<1(<#:OOQ=<_B8;[W*[V@X$[P +MW?$XCNX><.=H?;Y+?W?A77X'OQS/RN?G^=S\LS\;WX+KPKOO^2]NBC-VNJR.G[C2 +M=WX>4T'?YW,9KP?!S68SO?Z#*>'W>D[C3Y'5=KXW:?=[+\'7^1B?*ZSS.K_- +MU'F]+^KH_/J/1Z#<8#]O.^M3?OYGV.7_GRT:B_ZP_Y<1W.W'R3('Q`M(5C/\%];U.QZWR?I[; +MFOX_5_)\SIWQ/]Z>]JD^M^/#[+"?K`/'`H)WA]-YT6]4-M?-Y +M]+TL'9@WH%?P5X]^[`W_R?N1'X,_VM*#>.5CXCRP7UZ_.=3^AU\P%Y!_CV>8 +M<<4&^`[_>IT_Z;S(`],?U@V5/M\3Y4U\@/^WJ+V&P'_0=]$F(E@^*`Y4__M_^69KO +MC!\+3I/GRS,M#^*<6__>_N2YY@UG9N1[OZ]@J7Q1KU2\J-@J8Y1L53LU%BJ# +M(?C9,3ME#R#?O<\=\M[KR'YUL[B7Z0/-=(NL3[<1Y;_JD:FR%CO1^W&H]QHH +MVIM]I(N8=>J\^O#7RZ]6ODEZI?%+PE\,O!7IUX"]*N_7H5WR[Q=967E3<<55 +M6ZKMEXB]JO:+[=>R7V:]BOL%[!?4KUZ^?7AKY=>K7R2]4OBEX2^&7@KTZ\!> +ME7?KT*[Y=XNLOU7M%]NO9+[->Q7V"]@OJ5Z]?/KPU\NO5KY) +M>J7Q2\)?#+P5Z=>`O2KOUZ%=\N\767N/F55NJ[9>(O:KVB^W7LE]FO8K[!>P +M7U*]>OGUX:^77JU\DO5+XI>$OAEX*].O`7I5)6I.K:Z1.OI2_7@*-=-+>[._ +MB<+<#R%_P74.FOORC!]&(^W^L)O]/:^K&6@:60M!L(H='^D;O`UTAQ"E&+P( +MH/KT)DRM81_^)J2\LH?762>"PO#[\R94.R`;D +MNE#\Q]57R/QTWIB92*8`\A4VAD"G_KP+/XD>MJ!#>0)14F+\Z_B8'/YZZ$G' +MWI]N%SJGZT!$D=%K5Y)"C[GO=#>/.QOIWC9W#!8RG9=Q*'9GMG*>`P_+,D.JX48:LSW#5P!G9!9, +MG9X"V+GN9,G`495VMYJ$#J>U.^\;H1%PC,?D8[P&A:I52ARI$W]\@:H_H^6$ +MZB<+@NY43*=_71K12/NKCNV&WP8B_CO2_Y(&C"9ZU@`"\1)U@0&>$.V5_T,H +M)$]0%526JKI$R^`V9E-+`%-WL$H*%%]$?\HKCHI)2O]:#2DS8H0Q-MO))>JU +M%]DD:AABF6LHC-(#S!,$!F;Z)>Q-"^V0B[S--$FE.'I$IKU?TU?^ZP76?R\KEK*"=G:?=OIT9$XG>'1[U:^B#@GV66U.2U +M^+9E[%\HI7E!2SMCBYW#[3%3I_C/O+3N+68_X[&G)/K!@GSV/_K`\.&M)^Q_ +M@N_#WQ6?LPT:4:V']_.W_S^LQ_7C4Y(=#7UTCUU0Q^WE/K,-+RC6!XQ=B%H6K@ +M3L.]'G+75@N+[M8MN_T,7;F>67N05E`VLCT#%B'JT6\YE.RJ-"9>)'HQ@L_= +MEX!!O'2&PT +M<,1^O2@V)2+L)+N_2),3A9>;"W0KNQ[EEX3:GW72U$/L+N(]I6Q:Y`?;;$^8 +M2;1-DCI?/M_:Q#F)6J9@S3AVK&'%="1JVED8J[L'V5+IN3S"G;\FRCVU",[^ +M3EF1V5;%:8(:K;(2E>Z,/#S.N9`X9OWDC%[*H93)H.F#03&.ED]*9\0]!>.T +M;*T_S`H;WF$'M)(MN9%;&8(\0_3!\]N)*Y/WP[P?8,G%OSYGH)KZN$TP[8R] +M"M7>YO4CPQ1YG2+>Z<,J087;LT)@6)='[^\<8S[32.S/MRV,A=`IJQ0P9(VQ +M-)V$=L).A%Z^88'H#K:^I,?**&!FHUZYH4("HXS<2^8*OD&P5^4U;='++U:D +MU0E+@<^KE;\PJ9J)<8%1*G*L-3R7&MI7J>JXIL5)"QY>#+OB`UYIMOIF@P!: +M0"C.G2+3I$38FQ;4RZ!C314L#/>*C$,PPVF":)@7PQO>.VC6$V2T"]3>%2LB +M;MA->?'\RAX0/M!*7PS=G3:MFELQ=H#H9ACS@_,S8=Y)*=_*6[N9G+23VS]U +M+8VK7R:G@:9HV +M^!%@"&%?H\F39"TI"/';*$S-FANT436*397$&@;*?49:4\U@HN6Z,3VQ,G[#_-Q;5QJI!4SAWN@D>2V?0!>-Y'S,W*DS +MQS#M]*AXS:D7EBNA?9`K=^&(Y68V;C@Z'S18J?9M9)C&FZ#Y^`'4T["$B(>M +M0.BFV8,]W[J4BTSH&QS:B,ZTD#:MFV,N9/[39>*O,RW#V*GZZL-G>_8Q+_,. +MQG^,M0J&[ML(GWW*#66DTG1L[RW'1>-5OE%)2/LA)G5EI(OPN%GKMSJQ?B$5 +M#M+^EPMH$/;@@-"OPPO;4GW,&7^J%UK.D$T3]8F.'9\ZJ!@`H1_TL9U89J(Z +M?>MOC8(.V^/10U:72UYIG#[Y4L6^3B\6B0.0)4$B27M?NBEM!;%)[38#V4J! +MU*07:IF&3F?$?N+QL",V)$N%T&_E<*&U8Z4EVQOX0ZJTLC1-@'(,[HM$+DY= +M*!G'_CWS*AJ3]5PHHWZ^+4NUQ/[B9_&&7W-(;9#[Q9A\"DW2M=B9N[8SKU/F +M42BOIO09,G@L3HN7:DYB4V;=(V2\F_[I6OJ$"B[.7`W1BTR2_.DEQYB^(,OV +M?%TC?4UI.BPYW5Y&)0K23O[R;2]@*BZCSW6(SEEC!0]AQ59V,"K\HN^91M"3 +MRB?G(S4Q?Z<7B[@4F4%?"&<&CEA\;CTG2V_&P//MP,R[;J-EBQ#Q?*K[`^[X +M8O%;M1EV&?J1/OM>(`<;24N_347<;P\?>'/EA:*.'^Q>Q,.S8;8@VQ7Q6Y,6 +MPVVP459C]H?>22`PV["=?9^-&_5EZAER-M3Y +M0?M8,$2"R,W;RG=L*Q/[R]F/6S]"2:R4PS+\,C80SEN(?NOW2;#4;!:AR0MG +M)H#9F\`C;<^4)"89AWFODI]VQ%1`J^-Z<[/;2@;)MAR!P1%M2D\*SO7F99RF +MI/W#DM4?>7")JV'6>HSGHUIGM%)81BWB\[^!0[).M"'69`VAATI"[?LR0OKU +MQRE'JH%17P`YD;(5S-"]&E&)3^"51M-(S1F.V_;]A8ALF_&+(/(.KD54"]&> +MJ8XG5T@9X7M7"'V_ARBQI/$#A'4I9L\K[!P\@9R26'BS!NH_LB%L-89/LH_Y +M30P*"F$V=$VUD.X0IKX&01FTBO21"/SLCA-9W9P,!K%J[4`@?L&B"X1X4K'Z +MT`?-A#.AM5[#ZUA%0G>>+\[R_@D^/7"/^/U1YNH?A1069N,^,[>!3ZXK/4BE +M:5!`KDM\Q!#)##90ZW?[>+:T@F6(4FN##YR_,KIZ$D8>\5%PQNA6`-NZ8%EI +M4#QS`QT2[$E^P+EJG`$>^VHM*(4;4B0,K!#>Z$@VUBY,R:1=O*6U!!"T5CHQ +M'_CJ/XL_?TB;;3:L'\X&\5JEZ6]7B=,R!=U#AIR\"FOD4+\>##"**QP+A_Z& +M"$7#Y_'.UJ;9A%G!.1[`PJT>9I@&"$=)O\P8R+\2U@ZXM73ST,I;1,=&$5T\ +MH%!42@!B#/Y$V86\1SVI\]1Q*@5=S@\=D,)/$Q?N`#4;OETCTG:0^9MF&DOQ +M$;6`3%NB7@HQROJ!5"!7+9,C.:$?!A$5.7&$]0&T/.AS\#MWQKB%"C8T*P+2 +M,_!S@_=U_BL_?2LSWBE +MB-%+)[WYEFLOC%BVLY,0XO%9P[5]0SD@\PLN4#-S)EMHT6%0G'&`N6GBE9A2 +M78E9_5ECTX]DQZEF\9,JU7W2A[K[V`SO`9J1F33&A'6Z=EFWI$;$[!%Z>X%G +M''CZ_-M`,>)-[,U>>C(1MB2:97STU)WP^*H%+^$CG"&TPNMMS+I/4`8S'&A' +M5+^%&VH">:*MCN0YS;0AJ/]3!F=JOCSY?%Q;:/U(%J)O"+V2'%&4;_-R,(<@ +M!(FW;/E_-Q7KAIDY9IU+VY,H,Q>D=586\7I&4PIZ!&991[*/\9)6)8:\2?LL +M2>U:G<1."T3M'P`E56T#R!"-A0N$]?9IFLDK +MM5JWJ3)ZEN/\\TV8&:=0F+L7NZ9&TSE0VQ9ZP3[6T8EZ=2\@,U^PHNSKT#+: +M7_$MKFW*N70FPU"K1=YMO`Y^F/D[XG'W5,-T9.?W(6]_`60W:% +MM$OB(^C+.XB,G3A2#Q$K'+,.M)VS)%<^0,J>D3`%8K)$.\#W,29YYBW=?J[E +M9;M5E5C%E=FR1QAIT0I?@Q&SM]"PDD]]12'(#UMA5`;O2*-1F\/>W4MVJ-M= +MGGU&[O]JK70G[;;D\4ST#JFA53RAJ1H>.?(8'1>SF3D&'NF06&#FS"E*!^,[ +MED/)T85@RG,1^";`G#%P^\_!"3S?/_F$93%4;9[43=U#T,5SDV;6N+(:1)), +M3SU&2Z_?\P8]5S\13+V*;L]8*SQA5UW@>N9?IHV5@>][ +M=T,F$NS>%>WKQ'5_AU^SO&E\0N-7I4P_9KRU&)B)"#IHCB%]\>&@<4V&"\'G +M97H.&/$%\V5-LJ+=W_UV107FHO,J&H?1J34B#CC!4"NQOR65*R:5LW?%0M\? +M"UD^P:,8E;NB_SM*5O%1P;%+1O$;FNV\483+/&K839F88Q)?:=6)IN$W8\J?3$7-AEZ2:QIB[12.R)QN3-?+ZTS#G4S)^ +M[2H#C"F'CI_VL2[$D&3+5::\EHK1HT2^%1!:[R'DZHNSZ(S1M"1H-E71GPKV +MT)"*;2VP\T5M.A#%J-])IJ#,"XXI3_*W3>"1F\PM\,YXU@4,!GM#ARJ*4#,^ +MCY,_>F#'VBP8B]%AV5<[,TH%56CA=ZWYRZF_+N%LI&P)2=(CRVE"#+X]-OBM +MS3&+^$(&RPA2ZI2^,^+#L>NX@U,;^J9W4DX2:=B1YOKL&1@)W.KT5BW1YM!1 +M#O(IFA:]G[?W0591CR^7X^R4G4I\NZ^%&=M)]X1&C[T2O78D^P_*_XU3686- +MDN5_Y;.W._(RY1XA"H386^J*UZ"PO&UC);$@M.+B^7RU;&V=T:A\-QID<6V? +M1#[L^59P#%?#FDTN^Z4TVU-R&E`;`$CV=:P=L@=IC\=1Y\Q]XE:X(&X-&X)[ +M<=$K9KI;EA#U350UQQA%Q#?W0&&`8R\#=2.Z/WG5SYOZ#HY0_:SV@G:5''GX +MA@NPMUO2.2<<%`70BL:6JA;]?3?DLK&3QYHV&$%8M-.A0T>_%7ZPA#[AV#@' +M?1A%#T$9YQTF2<'-#W6RFT1IUC-L8QPR[*W$BR\H735>@D;L!P]K: +MJ1$(-VC9US\IX'C7I-33Q_+ZJ,7VNI#KZA@UR,9:GI=7(U.:'VY>`JNHU+U] +M,?DY+-3V>B#Z$.LNX]NU+A]X43[AL`1W77]@L"%O"C0:GEP*OI8^)T5'A7ZD +MG5NP(@$/N!)"+J8N]'O0&J0,$]X/]1%Y>]7KZ!W>XS0;OE.IZ1+`,T`(S<@, +MH;_8>6HB!Y=NX!.Q\W9.=W/ZY7JS(K(FBBHA90O/MFZ4;,S-G>SX:)L(Z:3O +M9*E."[T)'9"P&2(= +MD@\NLGH*VO=4J9$2[@.K]27`N=9,%5^M>M/F%7Q>N3@QU3NM=KW)N"S?Q]5U[,6@\'=N_@&HG^ZWO1*(XAUP+C,"GH_\4DT9 +M1]9+FF:&1/BASZLC0EP.3()H)+@ET))V!GDCT;=>" +M'&Y5K(H0H7G^PG_M&:E)*.9,.@:T!U?@-6*8ER42R:5(C[$Q\-`5`IRC.S#0 +M1-$O5^4T,BY"BU$^@;)26YS=ON:Y$"X)4<7;1]JKEGK=F&S%K:!5,/QG2O6" +MBT@)X/ORDXDGS)$ZPQ?N278P5&Q67F@DWH#.-KWW()\UI%5\( +M;']^5EJSY!FE"WC>+,OQ']8*]%B-_EEF;?JNK:+B?IZ@XG&N^U(OA7M.YIUI +MWAZX2_(;"^]5EW3P`\6,]9F'LS369\V"]#*;Y*8"19G89AN#0 +M>#C'P#NP/1!;1]K=[=#9I_?@^8'CZR)=9#V=GX$"Z)$-F>L->0OC"GO!GW0& +M/H"9.H'VXCE_I1;W$Q^6XO/.,C\8+V#U!(G";F%^0#]4@540'?^MCO(?G:E* +M*S4-Y@10BGW;#CY?U9Y$B4U*II59TU_&+G29N)Z#ZQ2:\0>04D/`2])OD:,- +M"*I!_&[9%GRBAL7S+R01=F#8SKX4.DJ"1%U]SD4N25@#QR3(*CV!56]Q3%.& +M;J"RZRBYKJ$U!F2"`L9,7S6D$1]H'=@!=<,*U2$'RPGW$E$N)@1$6U--:O]S +M*<0O"5E@Z&4]ORFEG[+E$--3"3C7*#T(R<,,`P[_FXB2[L*2#_<]<([=.E0/ +MR +MB1_M0[`B,7'G0O+J6#?WST6#7[9?9!]S;GVM7[L";#JHW0!S8],RH7Q>W4?[ +M7FRVRNRKVZNA)-C[*MVZNA:P)U7]6&-NQCBX^M4XJ_1WKB%G(Q1.R.K%9"7Z +M((K^4H>ZN2XLP_QK]H?=@U@O"*C0LW(MYIFR"4,NU47CJ>(23=_^9\=_L5_!CNH/V?_`)J/_*(I6, +M@'W3R\]!,/>?Z0[>\C]\!6<->QEQUZLIT8F"S86-;LSRBG/=[H(D"KZF-Q:N +M:C))T!LH+"W<6;3`LA,V6+--83_(P:`#V'C'%=.A2;XN*S[CG+Z]82UE=& +M'WEYM?@K@I8.$I!0*9R8?@5?O>WOV'[2\A+[Q>\K^PB +M`Q,?S&!ZX8;ZA9#XUZ/3)(<"PW5#6PL?#!<[?!K:##&(;-&'#3`DK>N$FPE# +MY2X&DXY)DE!-UQUX""]1;#'1)%&MD)FY;BV<%&`$UF'VP79!S).(`JQ9DW(PO`_"F['`AZ:3T`/$1NS"F3.4@:1[05JP/5G#*5*"K8`^ +MWPU!PFCS](K"C0[/I**I>,[R,,#:?BS2/VU[&8M=XKAK&E%Y-B+"\!-E +MHC,7,ZD(].$T=OO$D3NIZ&#`)<`;$$DS=W+UFX1QYGI%Q]OSK8>Q-%N-^;'#7'\RG#80)HR]+9U +M0#K,-T/PQ]0A)&PQ?TG3><6-;&3[.5J<;BPAHM&,<)1J..T`TVJ^3$I3-;U# +M[!H.X.,\/ +MVL^U"90QM"=]>!A$P8O8`'Y9!=9B\+&H&3=_@T2214YR@@I!CIQ>EDO"^EOA +M"N-"C"RT5R3J\FX8SWLX`!T,526:9S)07&( +MCZZ13P#6.MD?$U69X0HX++^Q$YS[`#K[*3A.@SYX)T5S3?4&';1R(*SD?;T0 +M\'`'NE`^XQTNG-$&!$R81(]+93DC]G0J7L*.A+DU%,)<3DI4K["1J=\HMPXS +M>=C4*>OC\N%)DE\&^GFMHN>_Q/`B%+N)3(9J=:[G6:BXW`,O[DCX+^[M; +M1YZYJ!]G.()Z?&XE!>@#V7YY`N9\\"D#4K^\B^6L9%@`K+P<1#<]IR0/[11; +MBW:Y&^`J$)3D&=U>;B30LEGD,>X48+-:Z0N(+F'_31J(E6);"EC:!9.I)99U$I@@DCIRS3_MXDRID,\ +M&<5!=4AP8>'/N^0!->+:7?=_,LZVC@2[I8EF"4>:X@=5&>OJV(X?_"'35F,= +M*DJBHGM?X4249P9SM.F8H6<,C44.9:@HM3A$%1[QQ82[0(<::@>@#BT^K +M$0I>/ZX2[]@.:5-3@"(S=>&NB_`Y%%=&IY::9J"98(J!@38056ZF4#"9"C-$ +M!YC^OBN.;&GP-/48<:$CRJ^Q+0D`G +M82Z-8;A)Q?-D^WUFC,VV2+?J7\G^KV"Y@8]-EC)B3!"W_47H4#11H3^&KP_Z6 +MZO8_YK1/6-5BQ/_:"C=`7(3TR52PM_NA9=-+*%O\Y;HT0UZ8]K_2&:+F@[5L +M?25FG"M=JAQ&6FT4FS#3S-QB%L>9V9SWGFYYQ^SK +M1@AF8T[`_)$DPL99\/3UGM002C%Q^49"-CU$H>O<0=+:B@MTNJ6GCC^=4THG +MU294G5(<,(V]V9N18TPP">NN4Q`?L]Z'Y7F([]Z(TR4DF2BPBI[FH&)DN5C. +MEVV"Q8=]:\%F&%&(Y[!@:[D=E0X@LLN$VIKX9?9TB@Z(@]YLS=,+G`2U]6-AJP4V&_&0HP]V^CM9(FI6[&/K\!72$VC;4GWUL?"& +M'::-05]#8VOJ1EZU,,S-(N(A3H'"3N^OY?6LEXM[&^H;S40-:Y +M&&V7&FV+2""0W.W^9@>PR'#%9UZXJ8;(4;(3=0XBT(QC'9"0 +M5`V05R`VZFUF;)F7P=_;CZ]1^AK!Y&CF&XNZ<2D7#]$%% +MC87^9DE()\]G%H`K<`>P5Q]XPQXM461IK+E]#F,,Z +MM@9.XP@<'MXL +M''T#-BRZ4"<,M8RXW[4Z2Q#CB809$`9H]`N]N!88;2H9Z(ZV`DCBK9S&O++2 +ML(IG8=+)NAWH!S5FT;I0@=U>QD"Y[53@Y4!S!$4`8&MNBZ.OCX4A=9WJ6JCZ +M:>+E4#SUQI=]S?)(<`;.O]0.8$*9_73!UCA2&9G$CQWRZXAUQV;@+P]O"QP1 +MSPQ=Z&88X$':A`EB(BC#>M(UW`38+@1#9L=B"ZT,[@X#!L```,```(```0)1 +M3SO.F(P[`/Y9-ZVKI-PR`A,+Q]D`!+C%!>V#`B)$["'`'0$296QF+4QI;G5X +E+4%2378W+6QS"@,3JRFO6QUI@`R+1U$F`P4$`0`````````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_multiarchive_solid.part02.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_multiarchive_solid.part02.rar.uu new file mode 100644 index 0000000..1d77567 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_multiarchive_solid.part02.rar.uu @@ -0,0 +1,299 @@ +begin 644 test_read_format_rar5_multiarchive_solid.part02.rar +M4F%R(1H'`0#DXV:^#0$%"``@`":(E[$,@(;"\OF``2XQ07M@P)P +M7N0FP!T!$F5L9BU,:6YU>"U!4DUV-RULG"KNSBH>3 +MI(PX'#!UPNKA8QM*13CXV$;FBU+2B9_FLSA(2[)!MK9(-2YR,U[:!I''!/NG:=FBK)X6@-/?7C8_"&LO: +MW=G=UAI*H`.GZ!P!#=9'!\@4;_0K>@#2AH!L6&=R,^6K4R\##`[(6LY-10F+ +M3V\;DUE)T9V#)!,#I9"4SSWF!/L3?0D=Z07#EL_Y` +M8>'B?HO'"2]18EN9>M"DVF,S3#/J["!#Y`F6H.S[5HL)=&M>'ZYVLX#;*>0W +M%RKA(QFO9\7K65_SJ//L>SQS;HEO&Z'&0:B$\FX&DKUY@&=.D+5>Z9G>L(`T +MRD.F=_6FR9IZ4AB.!\@];]2$*2M"PH5R*\=!98;_S1?=`)W5EW3V0W%8[["& +M-IUY278@]YR1<8$1_#I-,FKZLTZ;)O +MO@"V=_TS&X"A"$?=;(^B#5:G8WM70-\N0IOBDY?+?/`Y0P65G[9(]KFRW[(= +ML.&M>L,W%%0V&GD9E_^\*DO<9"-SAD[L]>ACF%'K9*X/OQ5Q_,'@I]L(?>.L +M@8;HRKXQ=RPSB]TDD_V:^_-D7?2Z:0\:4@BLD]F[98/&@JEO`9 +M"GB3B'UD*$Z%7@79,[$H*AJ`2:>YU-AL?'U5IV:;X2(&P_4I, +M;[@&=?`UD:QF%$54-9I>L/%:M`UMBQJKO_H8LYT9;>KC#GQO82_1.;$$?X4= +ME4YTY;MT:Q"5CM<'2YHE-$\=:;&C5YQN=B.X&G3D5FF.KF>("BJW'&3">\>W +M]APM'Z4CQNF+-)3XIKOF2&2?R/MS.44>=14,L7GC?V,W^M^S%A,P$T4W7B3J +ML[=_9"0\GBR4T:)>>5?)-_=HPG0"SD/8H.RH9BS#GQM*G,Z),F +M#K:RA[=Y>72+/W/E_^O''[[=6L]&*8^?_(0'5-AI;??75AV*]&$@-MSW*C5< +ME)OMB*3[^\CMF6CS#G_&--^Z5D3M&5.0\6SH,%9-H?'+E-@$7>.BP"MC82.Y +M<"GW0K,U.H&_;Y2-@NSWSM!D!6S81%9!6&T"WMI"'G4!M74^?)$P833721R+ +M3.A4M`XKFM?X++/F=L!7CB=DW(AN>R!($9B%?%VV!/==;&^!=58\T-=T9)U( +M6OWB)FR!*M1`971C>R;?X\-!B[E/,/1M803X)'Q[UGHT[!&<=29N)FL`&`'U +M9$L"OE]X4;>'W'Y!K`;+`9T\+3`5?!:QZO^0--CJ0$S,&TD%Y>*D#NS7LH.E +MUB^B6D;@F&*AC[R5D/`59Q@)&I1#D<_2RC+884:6H96#^4ST,[RR2_M`NH\&NV"D)QG=;J`-!%]&'O6AL- +M51&>"Q["S_.Q'X3SB!Z.]$?U\7B%_N6#SZ!;L@94+OQJ9U$A!%]\UG$MHIH" +MP0\46?'/@FZZV.WW/X@O2!)O^Z!'Z3-!$;28?<`1:NMM%MW_J1;6^[>+<'WF1E$.C.. +M_.%K,-4::0YEDP`+*;#WK1HCBYC2R9?*IPKA_TL8;N@1?P2'",[,IR3/DED^ +M+8T[--;0MZ,BY+D(.C:SY8-2\Z#72.KX(**6)X<:$]E#I]XV^J=PC(:*[@:J +M1T`'UN`E?-G8F.).[2/@!]^;:R#JBPXCA@B_M$8.3'PX5;CU3/.K+)KXN/N4 +MCR<>FP;_G"0"V,ANUWUB5JH6M@J^DR>_.F3E^8`@W*-RSH9703:V1?!JPW9; +MK(U5S\L6&ZXO2AHM1P-_;OL&3R<@@32G``[UTQ,BN6[3N(.?<+2K6']]IC:(V6FFM&=L]JPU?;1)VRST3;AE\U +MOAAM_PDZV1MPLFK&4FM#.I&6\5'8N_/@K'Q5 +M:GG#.>YQ[#.2""1`V($()-"5]/S'A6`F@@TX_D0:F0K>?D +M31P$"-O+VS=]:8W2'BV6LSMHK@/R0IVBLW07CX(5C5YY-#]$,VT#2B=2E7(A +M"B9I7K/1/:)%GS,X#6D6IAA5>")=BN4^_/4Y;`M%+MK(!HB+:AI*B>SHSC:( +M:`[-Q)49JBPCL<-I-8H#!())G*.*1_$6-"%?DY!V!K@J*4>_/RAN_JQH(>7P +MTU/3-`V5DS`OEVDVMZ1@0`9.*- +MS&"5W#=U;Z"-YJ3'$]GTT2;0/,/FH6<7>L/(X"@BA7_H[YDVJ@X?/_0D8MAI +M196^V3!A:(%W+NY(_%ST[.PXL$7Q$R(*^R8HV2?'[U;WAH49N+A32'#/&RI5VH[)JF&_6*NJ-"(:@1<-.S)V%_9KX +MW=G9;`0K,(V,Z%W!TVUJ[VT4NJ+=SZD7=+*+A8>W,Z79++JFW696^M#+L:&O +M#U)IIT-*>&;;-6Y^JI@&+*XW;ZK-4!*6:4N54OCRA1IGNL`"PK-\ +M4*5U(A'Z=:Y:!\!F5DWI1L&910DQR/;5GG)>J!GD&M"R@"7/R!M`1O2R4R!, +M;@&,276T4CW^0TA#JN[P^4;3-M?P1/Q4]%=N*6A;$P]W^).?&'/L^F,@=<,^ +M[8^9B,N=;#)G7-&QJ#F4YB:"J38VC8P.X7YD=9N0V'CQ.A-HDZ%[/!D#T +MI%I?Q[MCY?:A1@E-.O@U[ZMGAIFN+JLUP=EJE&+!O$*VF9TX$)!#S]K%M>FL@[C8D!++=!0JWFEX.=67KLP[D_'1HXGQ\56F]'Y# +M#^O_H:-2#T]Q^A.1!7(=_F)`YK,?'^"L&P2_YQEV6_5T(#&L`!DC!M5;65:R +MN&:M8GY?C5Y&"_PDYO00R>CUTC)UBMG'!P%0'0.]P7S;=GD]KK+:")?P6F$U +M-X%D73;`5K,[@,]J^+TPJ-?"L4B'X>[')Z-C4=!QXK)Q95(!MMKI%%DK=M`U +MTQ?$>8C&D]E^:ID`"Q,[+A8+$*UIR`R^`&R`9Q?:E +M6CN&/,+\2]K\ +M"Y?'%UE+Z27$DE,6E6#T-Z-)=(;?`#E7/ZUE&T=\UTP7ZONJ1,U+2O1L*1?C +M!:Y%"%^V+^*^V!Z']%*ADCZBC+E]JT60-P>F#3?Q(Q`9WWNEWR3)411L*� +M<(6JSD9W@!+S(^QC3UQ"DO`)2`OU8!U'\#'H]WL-+7OCC,XL&=,=N5/T1V<5 +M[4N'ZM1-M:8OKJ6N76LB/8*]IUCST/1SEG022V0I@E1H-<_RBIIV]KLY%2G: +M\0F@OZ%DY@`IFCHXZ&[(Y@7``;0#8^FSU83J=A$>P!GJ^"=HV\)-+IEW5-Z/ +M-Q"__)]K0]&=G0XAC0>,7*-2>-VTQ*G@T:#H;LSRZ=3:Q$+'C**CG2+.N]"Z +MQW7Y;?XN?:,5@AIJ&#)VSQ!CF,=5>>B&HSRR3G$&^Y).8AZS?-U@]6&ZYZ\1 +MXMXDP:3L;W`DOH4U+;88/4:9DD,\4(DNA3NY)1=JI65BUWU9XBE`L$.@=2N` +M.;#82775E8T3&SR/_=*AQ%=R]F!6:KI-=X@0'B=,'1V/O[-9)I`5Z;@1"EZB +M")4^7LE!OS.C,$]@$L@)MZH+"/>K1`S>(TF^.J!,-B949(7ZB=?:M-(9[C1, +M0BY@#U,=22::T;1"Q$8;0$%;.1)EI'C4;?2UG:13LX"J=*A+$JDY"I2@\QW3 +MREN[8*#11A#H)QD1K?[M9!R*L&WJ2_/UO.MOP^X)Z^L[<3GE+7$W;^7A_I7T +M*_2RVA9_Z+$G^O&-N?\6%C&V*^+AL5_]XAQ]LKV?^X8EZ67(PVDK;`(V:I>3 +M2C2VPVE7^QLS0UZQHL\,?+3M)V6VQ4"L5IPK%E\4KPZGE=\G +M_11?_4MEQ/;E?B8>5VU;/$O+56C.P[%T-D5(BTV'XI],2<@!:Q/UD\&P[5;6?4Y\O^R%OOJ^%4SK/F0X,7-[&U&8/$D?ZA$GD-88.Y) +M,^7X/[C&Y$5ZO'BJS+FC)E"+`CV'IF(70W'8C==''5>CA;G$IG!E1A0&7Q(T +M?T8N]D]TRDNRR4#8L.SX`*N7#D-3P&AW"'2O@D#HE65VLB/_Q^G+Q.-P$T[] +M@"/5&>,\T*C/]7J)$[$'E.ZG"1'.UVD6E6$--1Z&I"&!O0EY\:.-UC>&'^Y@ +M\/&PT>P9\E1T%))B@?0<[(\(F;15!`^A>5%?O)'/+=BF>D4#H(8B/T0?UJ?[ +MPDRQ:\K\[&_,P4SIGB:CB#J]GBRFO"A0Q'9XTDP$UF7_HR/3/&NT\B[4SF,Y +MF\3'&GV>[FDU";&0P\%3!^A2>LS]\FI\CG1G,@^C%]9;/"Y;KB$J7#UGLF,8 +M@L,UGD#.Q\,'/-<8=%0%P^43G/C]S^7?`W"O)X=;U2TW\)$.4C0(BEW)0C5( +MNPTN7J^55)L/V#[W.C``=([5P,Z=R+:X7T49C;N__P1NSEY+RR$M_$]ZT//) +M;TY(1U27DZ[ZD8H'"Z6<`MHF$9';V02-T[3_A.H&]A6O1<+*6H?F*8%0""=\)G/+XY^P#:D:#X1=QGU;+BMEQ;, +M;.6]_U+(:W<9]D*X)KMVS#:H+.KR>D$&W,.64O*1'`\L=OKCP=$-!P=R&TJ7 +MMS<\'*O)&K=@K>Q($9]H^K(W;TB!L3']I+B9:,3S`K&3F1Y/A[^HC9;#O#I( +M"FQXV9,8=>5VD?&C,%I'J0X4?M%*`.S/O1D6HU9^U-/7$1Z\@QLH=4RSO^J2 +MT6A-K<`RBUGQ^P6K3/2VQ.AG[EMB)F6&6V%[9*<'*2Y4Q#!JD*<*2&7MS6-Z +MCS&&7>UO)Z[Z'JS3G18ANV"IT^:$^.D"ET\[VM +M!>8W/:_G]=MK07G8)-H>BX:?!2A4DPN2&N-4(^\J1YSHXGRV@B`W[#C35AN` +M<6GU3#KHPUW'KV(<]FCRTWKDQYMI<"P4V*O$K4PC^QD<\8O +MGA3N?,]0-KB-\)EA-CSDNAU?M0`K[='&"29Z(XX>BA(\0F[>AW-HZAG3XO*2 +M;7:SB9%V&_(3RC"B;D_7VH5O8X)1?7JY3K6P!RX1U*^'W?8@\*N*2^*+K?&FL,VL-P)*A:=-LMYY +M`0Q+WN\\:CA5,&BU!/U8GXU4"PVKN^"D+F1,*]S6VPU-J$<;6][$7AJ@?=F3 +MXK89[$)[:C5(TC2!P2S-QU.2'L.99L$R]XSLCUS9V!NSRX?YMSWV^:39U&X7 +MX#%R8Y@>$'!X#1O4IN!H!V`@?9=:S3#?4(>FV/3F:7/[>3+-TQ?CK,66<,/A +MA2KI/PG(OJ"H:QG;A3#/9\&Y7V8'HR-,?N^"RV6@)N:CI,2^%L(=KN)S,M86 +M8AJ[)NFL:C^#>`ZBFVY?C%M=%Y\7 +M#A/C<7B:'P51I).L$+"0&%&"4V6$59_#/X'O`&@VVXU11V.(Z85M96,`X4^OLW, +M#JB1-S9_#N;6=TO,\9;@J7T!=[T-^`.X'X%7)*1+8B?Z\TV,,.PYZPGD,D?D +MC$]##*L<34LB*?Q..F@:\R5(CVU^]@DKA_ZZ+Z&!K@.Z7MNV8'4".IFU7^)3N6>=0;*C;L7: +MF"VTWB3C.HCXRC6=A"#M#D0R,*!9(GRBY/S;K1PV?=^+16JWHQS&6?E`8__Q'(#8B.K]IH_>5]P"]HE+' +MB8YC]KZ4;_X]BT)3"5XLU[S'[3N8W_DN5V_%PF/N*I35*\7[*OVL6*KV);BC +MD*6]*6\_X.*)R+PF#II"M-:HOT7%%ZZ/,?X'>#M6;**QR_Y1>E[SD(W^+BY5 +MZO+^+@_](6?XTS7J_Q]BKF.7]#)*7BE@,E@*\\9PH6C2R;7L[I$_F&/V;[NT//W9S+4?!5TWU>A7=KV +M]W5T;Q73MU]DO8+Z)?+KX]>$O@UZ5>@767X$\KHM5=-FO8KZQ?/KY97TX^>U +MW'=\(-P@,M`ZI[#W].+D;6-VC8/D9T`S(%)KO[K4O_HB`RYNF_X:SGI(L]&Z +M[.N-^*<7J7`Y#M?H4L23'(D5^'>=/N0,/\T[?*1VMN"&1=59(>\6I/$@87WD +ML&+/F3\I1LK$R_F,#O9+X53`_*H@_F7WOYU\O^A>)YJ]3M%WGZE[13K+)1J? +M/7I?07T5FO;;9>A]%>$IX"\[MU&O4[1?=KW"]LN_"D*IAV*^/9Y6X]1D%%'E +M"!7/U)IO\2-[#L=P*MK9'ZB=G%S,1(GJ/O-&T+%Z&#BJ>&UF'3NG0I0^/4@( +MO&(=P,.*P^@:.Y<3BK#]\RWQ5M@WFS#I\N9"X!S^.29ZTA\R(6>H!>,A$[4, +MXG`[%Z>_>X;)K"#KLXX@UFD0E^8ASN2EYE,,[9HY[UFS^S.NQ+1U5Q6*!"V@ +M/=..,M'K0?:,EVJ>F&YP@$^ZPLDY'KYG042A<9P#9.AR08?@CQ"Q.=[LQ^ +M26B\ZCI\+.#O91^`!8`E.C:'YF_'?!.V?Q52]`28[L?SR!T[B4AM%>289MGO +MMAQ.W&M\>L9HF14!.=X.H6>!R1IZA_$NJ8<9B/,6%@X]P[^,GY&,7BLO6$$Q +MSGA;CW`)T^>&\SN"3313J7(57!VW&4&DB#PW..G*;.PGVNF#Y>&(W>`R\69N +MY\ +M\56@&U*:=X/;@9@-GB?47+!,';M6`F1*=FX;4OV7,KUO%4G9W"V8#56=C)2F +M@G'R6JZ]%033]J;P`D&N_N]Q.5B326#L*K&\;#,&/WB_X=N=;YY.M6!PP='$ +M94S;D\>;H7U/@WU!LJ.^=0Y"9_2D"$=P&;BYYIYVMZSSM@57333ET=V, +MWJW&Z40_=&*YP+/2SC.MD$(!%/^C2UJ'PY4@ZW<@T.6_;]W"_.B73+76C+,V +M;%`FTR#?B:02!':,DYN06VL,%GD^W:WH*]6;6J^15JVED>+TUR_W/1W>PG7/ +M.&;4N?L_DFU[(66H#=R-V,-@LM+.HQ9S22I8U.W($,\NV=]R(]/W8S=7FM]U +M3MB,^8:4+ZW+I3%X(;7DGN&STL"&AJVA%67QA'Z)A=14[>O^@VDCGH%2#F#E +M8SJ#LHA[&I;(1`"A1:<%[4@+G(CA^7RS.J28NVN?LPZ$=#BDT=%T+QM`DNW5 +MXOKG%55@+5"RZKAG8X`OUG8GS)<*%&'*E/*<)VT,F"VG.HIMMN3FA-GF53MM +MOFZM'9)N>:?*`@`(^E +M8#K(C7YKH3DZ5V%'?,GZM5Z?-G9)-B'[>2>">/9+;7:H6/4&WX-[IY9G5TQY +MAE7:9&$G:R6<7D43^5/VXG7P"62^4LF"&L8 +M9,O`)@YG)("C:R'%D/'+]1))#5Z<0*$JA(A=EU/\476:"9 +M=2.&>>2\O[2D%-?(_$UCI@Z6YQPH2]9/9NV*EG8,):D8:^L?Y(WHK![S/4:?@],\=$K]ST8=*D.@K)::PA1C68K6G) +M+0F>YY%[L4-):R]LU8L_0$-?H(D>1'3E^*(]Y]-:],OVJ"?B/61Y1H[-\X@! +MT&.#)U7'_KLTMX+1OD9[8UMP4)-.CQY5GN^QU`PL=OP/[Y\?"66'CF3:X`9$:3),S:'"C/N-_@IW=)#:T%TVP +M\Z^RL9.E^278,@D6ME#Q70')/8M-4HZ/17F:X`YG]>,(]]^]-3E`#E\O)*EK +M5LZED"!F'9]@4'(@MNKHSRJK@Y-'F6I6=9P#A5(^]ZE8XB24=8N^7'=AG`G(CMD.A49V:OW +MF&Q,F48&&'(9U?E&@$/I5:SR'-@)KJ&`@[-HZ>XAPTGOED0+%)G9Q_!0V&R/5_: +MK`5<)OEK''`@?H"E$[8Z&(;6SD`GP7$P=;']92E`;S"E9)/,(X$ZPBH:#O&4P4?7/:Z'&[.3/&81NC/,Q]IIMCY>>$/2.G418N^5JV +MV;R_UR-$%H9^<+LQNN"_S&NX/I9CA\)]\OO\(.P +M[]CE>X]K@^VW]T"CLG7<:7@\HD7W&R5H7&]A;N!367CF&IA+>RNDO0%T-!(W-B$:'3,+.1'( +MM9-#5VFFG;@:@J+F&DY)J$SD]%;`@SIY7!80<,GFC#>(\ +M+8`XBSD,)A6&`&6;`TK!3/+'DI$RCI#LQWHH#H/)(H!"(/E1FG5Z8;A[`L). +M'(.20V%6L=,B&G'S*1=E#F?QCA^IQ.V7B'GB%99*0G"B(O.&96LEE\@YQD"/ +MU)D("K1W83)"26!J9`[>,;,_O';EA<,6%..%,B4J\GY--\+ZEG)"&V1)WQ^` +MS)(1X?X%P?@0SK\!R!1T89D,10B\_(06VBDX]#J,R4$V]0`,LV@=\TMF*X2JF!![Z(@0:[4EEM.D4P`6:_'W/E84&!S")ME`R&L8AON +M08@HI(WB1WPPC8=@"'B8'$.!-I!#AZ2258\P*%T2L4C*`_[N(^(U$;"K%$%2 +M_Y:Y9<=F&6;&MUR/O27-G4+P*U3%!X$;$\.-,+=HK37Y4,RTX)>,_H7DC\DS +M^517YB9X4TPI%XI3D>SV?"K]`H2>R/V!#NG=\=_M3,_G6E)F0#..BUD`)LL[6Q38\CNTW6O"?DV +MD*C=A`!16J6O]9OG9DUMK61%0=I"4@;L3:)MI3VJ3N#L62A)G]&%W9:>1-$J +M0,&H=!;W.0\G-P1ZB.;>AA)@D3;@%[%)S^1BC/(E-3(:_1[/&ZR63KU.@:JZ +M3&(R\@J48V'1+GD//APEUL4-_M`V]"IVM_6:9!>MV+26L.$)R+-&F^.:&O?:Y'68Q[B@A5LCQ1^=:UBK,-.MV +MV;BS8X?8F&KP/^3D33)QB3UO9W! +M'V_?^(EV)QIRZRY@TR8[DDRP0<0P`<;#\"#K8WPL[V!PEUW)LSC;\\JIH3Q\ +M-<$:.5MH$Z+L*8?B_)CJU=5^U>\@QN^%&UA^#F80NQO'LSHYG<%/T +MBQ+3^-JE!O%SX5+>*3KZ&:UT<26>&JQ0^PO5-HSKRM6F.CDE*9#K9P>QQ9MP +M"SQ$50VJ7Y&QJ#P[?&WDOJG`CIV6>PZT=00F!PUDQ2PHT'K^4>"52ASG]UAJ +MZ1S;3_JAAB91U9'H@J,&4,[]R&>86NBS+W`!1-.!0DC`P +M,#!]6F9=YA7E%?$T:I(/=;('9Y'&IF7(]1L]7[S''))836W*,-^BQI?3 +M@.SC+TPW>:_8G'0(271DE!1]O%WB\ZO.KH1D(!^425NLX&8B,\9ZY,65<2F( +M:NC%!GU,WNO7K/#F%3[K;P<;6WMKGN/$X-`*AZCN+@9$VZX+H_?4#(IX^8R/ +M"WS62X5_>X=P4X;+>$C=B>A5!8"^):GQ$9>//K,*U4RS`AN-LP[3<^%QBRT6 +M%F(;D,RX9M-NK5GLF"H@$OKJUDMP7U1,\(V/2L$^U^5F.2ZI,F.QVY.IB^[ZNBC%2#JRF3UT2UC7GH8TXT]D=P]0+?08SY.*D'I5A +M>\&0.2P0&'$%U8V%(D]BS]@&"@*L3G\E8`D8=A66DZ.P*]1O]-#,`OJH'Z<( +M_QA'ME,M+/7)V2:"BI1D=,:&'PJ4*XP<*2.+'.1BDLS?@%V +M&!N>KG49EP&KN#)B0T-U]/Z^&+;_++3B.'H1Z,@5AH`&Y),NE&0Y-&B!UI_3 +MQ.HN_;J]=P4&#]6Z;)>05!4H%N1@CP3I/RE0I$=6M.PNX/2"C>E?:&]/67>G2.5IY&EF?Q_9AGIOJX$= +M46B%^78M27QAK('-?%K0J:3+06!;K[[4I3[2/2+?#$=0/KG_,7K2DE;!X'M)*DORI11#01 +M#3+55LY84I#IDIQ;LB$UJ.70ZVT#L_8QG7L.M,#_%CNB+Y#/^"/3M?D(AMQ,,\7 +M[FX"2X,!L#CI*8H:`[<#N:BAF?Z^01O]P_QH(VXV\.J:?-VO,0NY9/3J7IQ^ +MUJ6P$X717FXJ>["PGIL>.!^[Y-DV,.DFZ_N(F*!5&F&KJS;[11'MS2#GM;$O +M#LV#>TWL-ZR9X8%ZE:+%L\F`-3'[=@GQ<2\.(%G0#W77C`#--NA)8&9E1#,C +M16!0=[X%P6DK`MM,(AQR%,;8TV)-VFV`\8R.V/C!`TVTP?#,%Q-M1IM(7`^` +MAF8FTV-C;)$-L(QQR-.!-X;S#>\4P)O)DPW-H;`A"$S"8!(\F$^W:M-`X881 +MYGQA#ZXKH_DZ +MJN]57FJUWJJ\[[\UKRK]K2N[Z5]*^E_%(NY#/L@?)D""=\>#-Q^%1`SD7>QY3?,A*Z=LY99>/T@#- +MB,-L*%\$SL9NA93)\U2D<#`?*:Y]85",,5MB<&92>J%W +MY5&=8;==O(BE3BUZ-\CHCAZLK,Q>(;2F+&T^I1;4`4!AEX,F$-(>9C[^F(6( +M8Z".LOTPB9@":`R!'G&N$#T08_XLYX\>"(&\9M8R9EHE_JE1E#PSN<^K81=' +M=22'&-.`AS8CJG(@CIR7G'JXYS"U!.G@X2Z[SQ%&_>DIC6XOC+S&W7(,S[RP +MX;:V=(K\YU,SD4^_)SG!D9L^<$:DL1+R_9P48&9"YC2O8IH) +MRP4MY!9D4Z/_X2%&P5$%H?>V$I1*QKMKY!I/+RJ6&RC*6$(C'VR7D\4M<"W# +M$7A3"BF_L6V]%^\XEXD\7Z;[PCAR0*4(G.W`*8"]1U&-Q- +MK9S3@J$X<$AKW]0HW?4SKFVC6R1H]=@A34XPTIP:/--Z3C#L233C(5)U1[]^ +MZ"TQO_5,$-A+NWSPB(@">F+V\O[_]U.N5TOAZW`#5!G\*\-%'0)J!/04B!T] +M]VI@EL"ZBT(T.YN.GN0"SS7A#SKBU__C+C:3J\]2^]=-^LYI\_A9<:;ZH-?S +MQ7N(;9U%[WAO:>P-M=F%JP,7!12+["U<+[>8D:CX8MV;+$I,L*C(S5T@O_)` +MS*,VO#`0HUMS?91RD%IO`%IC>7QN6@7:B^*\@X=Y3;%?$XN=3$#>?;$6QN*W +M3K6$TWJHKJ/6\9Q+5?8D8MK@JRG>J9JQ5P:R'[6AYK?>JY]YXA2$PL#;*_%4KWI" +MT;J_BZ.^E!GPW^\Q4'7(@]PFOB3[MTKTF<1[!;+9:^B%?XLX:E8%QC`UD+72 +M8#@S=TF`P&0Z0`FE@#WW(LI+?NW3C(G=:\!$0<^3NGO_,%PC^YG<3-7._B!, +M6"@0#3&'%#(1[PD>5"ZXN4%2H4)![\KFG4/21/A8H2S;0=0]TY2N8TV4(2]$0&+:T"4> +M]T$G-#(.+>#">KP84U*`0J([5VR"3:J497]W=N:1U:J.!'9C +M+9Q[O-7^#UG1&IL5/-33]J6"E6RU"8TG2,@-WN6%B#L,]),T]'6=$@&-J1Y< +M["+-DBGJD+YCC%ICX+B).E$AF[`<)TXTXQ.X;`%DODTCZZ6I&(@:)`U)\S*I +M0P?`OH;.K[C^YMI`*VQ?8%3NE6M52V-LF&N?3,%GO#WGMOD7>Z>]],^\P+?C +MI)/[&4^BS#!Q])R)F8BSP5=?K\U?#/3?:7DHNA5S?)$!O?6DUII_80,!D\O. +M610)1K>48*58I<*&DDDPMLMO8YJ6/_=>V.O+JO[+_#A/7\,[P@:?4UB6QMHY7G'IN +MTQH=&?Z@=O>S=,G`N9Z03B/[H=P>*J16S=(.`PT6$>ACZ(% +M)'O8,77HJ%[`+H!L*`?`.#>!)A++M,4\,7TS)*S;5:)2AO>WB$VE'*N9W[%] +MM65,OSK)P/H36!3_6L'&D<6C?]UD\>:3U'^U2ZH&.FKO;NM0>XLV#J,(QC,ZQ9-7H"297P`)W\M,$.^TPWG!;EZHZ8'?U8BI*+.2 +M*,/XE?'AOQ&JI7\B,;T:T8TJ- +MC"X6W'!D(I6BG@PTD/<^)[9NFBPVZX$B>%[4F+:2>+6'7P9#U01Z]:! +M%#TXL4`XG4.0M9C +M`[V))HWIY*@JQ:E[D<>]#SRQB<"QPN]X_MF8Q;>8@:V,=&<;D5A8C@QV:LIH +M/68XGK%:JQ![-XA'781R:JY#9^L'>/?#:H;A]<(A5F[_"90U[ST`51UPTL4R +M1_C;:/O67$)LA1NP7*KS2!,EQ*3^[R1-1:P\*P&4VCOH)%0+W2;O\L)"7MMM +M+@ +MAPK:,L"/PDM`XXHL:<*NICPHX'<&W)0)-,SS&#^K[_N.AHD4Y4;$#F$O#'); +M@8S[XR'+7JA4TY5[J5[C]?O>].IZQN`JZ%3\UN"W1GSH&YAO,M]2W,LOZF)2 +ME7U[ZY)9:RF_F:),%K?P3M64XFUA*`)# +M(J;NHX'SR[93BS3S/_HIFWA*4AKD:4M*\MT(Z<<]>2WY#?E-W+9,%M%/WO=& +MF;#K06\?7?V02"ESR&S5=\D(M*\3ISYN2C%Q71M+J.<=U\H2;Q44:09`V16, +M7$)?"=F84\VF,%U2BB/5>O\>Y,:MPBTRL(^H\-((M+R$7*&L5F2A&1NZ,AG/ +M!.)W%?(M^?4\UO'L5ZB7L^-XB:-/=?(%5M\9"ZT,[@X#!L```,```(```0)1 +M3^Z#+\,[`()G-YHB7L0R`AL+R^8`!+C%!>V#`G!>Y";`'0$296QF+4QI;G5X +E+4%2378W+6QS"@,3JRFO6QUI@`R+1U$F`P4$`0`````````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_multiarchive_solid.part03.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_multiarchive_solid.part03.rar.uu new file mode 100644 index 0000000..4ec0e55 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_multiarchive_solid.part03.rar.uu @@ -0,0 +1,299 @@ +begin 644 test_read_format_rar5_multiarchive_solid.part03.rar +M4F%R(1H'`0`AW^N'#0$%"`<"!P$!E.>`@`"ZSSQ%,@(;"\OF``2XQ07M@P+@ +MS>)=P!T!$F5L9BU,:6YU>"U!4DUV-RUL;\CU%4T+;3=`W$;A-^OJ6-[GTJ?4JQ2O=Z& +MG5OU^[=X1GD_R0`YVUVH8((UN_Y)">9W!(#/K!N%G&?M?FOLXG&1$FC)/9]O&W<:1W\3]?M?.?:8H +M8;_O[O^CV@E5O;N@Y%]U7J&OR&BS#YCZ_HCKR^SCZG1`J+L#L(-T;`'J=D`T +M;Q3J[SK8ES;EGWD")ZF]@82QP568%&')G"UR9%>#29NVGV\M).L:F3Q +MP0U*0:3C^WB,M/QWZ'>=W>ST\WYTEXJPE.#FZX93IBY4!USWF:8YEYC%5D$&\Q+V%N,,P@KA +MIELH6$!ET&O6%"$BWT1N7H`WJ +M.#FR0:%9O7`H,DV(V!:;NDH;1S4H-H8YV76H9\SJN1?5Y8UK%:;M3W^!O:-E,BT;E`.Q?W\K?PLBJYT9N)+#)].H4I/42ERJ;*)QOX%KF-^9N18K)Q`\ +MWHZW;B6-I6X+3)RDNQ1;2_1(A&8EP;Y`IW;6+_X]I&,IW,V;X%JXOO+:X5YU +MN1&$0ZT*;("'N0WV)O.V/%X0"9L23KA51/1+>/C[;[!XRKF[D*+J6@-5>PQ& +MQ_=[M)S9A]R^RAD4R'CW.Y$'6_W4.YY8&A:T8_M\E1-TTS(F[F=W4$3.FXXE +M.%I6Z88Z9QE@E,H?TWP,FTTZ6/30DFM'\3+]J0KI&N9+ZE\L8+7$\_D)6SCI=]>KH^!#$`!^"3>M5E'"!>9 +MRW=SZE&,UX/G;*<>4I-@Q'2`Z\5N;EW5ZOS@R#'84#GOE +MP:_D.+P(ZSRZR\-?(C\YHIP9D2"T*-69TR8EC18#J+H"]^%((>_P*D=03(5D +M-=K(S81QI6Z87^75"_F(<9;;R/"C`2 +M5$D11-G18QK&6XHY5+G45J;:]V1J9/>Q;^1-+1K<]VB@;2EOFXH#(5M;A#WW +M[[6BVIC5[/*+OGW+$5:IUYNLPCNY_LD%&V4#"?`70-2K$FV***P1%*T*SA&) +ML^S1MD!'IFQ&M,$EFJ-YB+XIKA>9;)K]?M9M*)=->_!T.CQD,0+UI^P30X[% +M2P4DQ.X'&UDM/)_`/.=WY]Z%'!J4951WSJ:4VZ-=_@PN\*@'SN1?8RX7-4SY +M^BYH)E;OD+]Y,U18\*&A-5]889C[A +MV^EK@"=T\.FYK-IRA[>B[E]SBB(GV14T*='5?'+>Y3TG7$IR8WXV*,<%2)C[ +MM6,B\3*"78^M4E1]\QEC7SM,^S/DMT3,S]N6*XJ]MLW8X"<&&=IOK)RT!]<" +M"$1U9T/9]8XL$*G,T_NO`D?/@?3&9PWXXX0,?C%@VU[X'W'3&&!\#S@HB6/UQ9>22B&(&BD).]- +MSL-AH.&F#=R(;28K6&Q1).KP6-`2TUVT"YG!CS=_=);@MCF;/`Q&\]N"O=Q* +M`@3JHJ3BL]SQ/TPM"W178Z1K`TX#9@N,&7X,(%O1#0%`PJBB0Q(:5GJ0II\0 +M-?1=\`#$"AB8;,T;CZ8FG&\G*8'2L\2V5XS*KR>4@X`6` +M-Q\$,ONLB/Y$/.\/VS7CF'YR',B`"\Q\3G(..R@?7\^!H;J"!FS#1>IO.IQ[) +MN(0P&*D/Q+RE2T/`?IIM&L*=U>P@2[D'!MPIB<8/OB(B47<\TYR0AQV5]Q;Z +M,-#03>-3R9X_S9Y`-%=@Z:+6'(?``U1U[Y">T;S=WR:,(FY5'IZ#"C0-0\_Q +M![$&$\^8KJ(NA3_9,!,O$UJE.7I1H8L431S!6TG0P$QWSPF+YUG9 +M!C#IX4B**"&B$5YY!J/D'P9_XYU%7C'>DAO_E2-0)-!4`0%Z'M*`4V-AH%-Q +MZ.!M4@:\:MEL4RPSJ'WX.<@\Z8OOV^U+T1T&2A"C[(F,[;QT;^LIIE;&.OLJ +M>#SBLUBW>*OI0KF[X@8_3R))E#E`?G^A11PWS%]**>>RGU8Y$CGC)F:B)C8N +M:$P.8\*F@RG<68,K!C8(6L$/P<[`"/3,6LN3S>R6NR(7-&XH*]((#\30;GP_ +M@E1/WD9D-\-2^;PV,/UW^.>(X!5+I=I@TCDZ=3#>?$#'LU2[5Z@9;V)OHX+-['`YWIS04->?D#%FP +MZ0'&1:J^^%E]!S!FQ/W('$J^4F@Q/Z079AQ-U+Y.["MPK&AND+OBWV?^J"D< +MC6PPB*M00&.AN^/?=_,-QBS_I"[&*++$.VT8H`X,T*9^R84&6K#8WN/N@@R. +M/_"YA1=@>6'/-/'OF]D)?*->CBAUZ\JR=Z<6H,@>XS>7,I;469:/PA*+2;OU +MCD2$@(I%1HE3JQ7!CCY\ENC7PU"+$I3H(CZFCVX4J;_;_/Y"WPWMV<2W\U!Q +M:,SIMY'`)&D;P;CM0>`-YH]T>TR.F_4:D:55_1`TT=+:(X_$\$ZTL'>^11H% +MLA9]`W<-Z5L9S+X1\X8J.]\Q;)^M3JJY14?_&]-6?_L`G/^DKV8QRQS#-\]" +MQ#W]3O5%U)>*V[V[\^^9>8]57JW3'OSCU<;)1\5BQ[^?LW4];ZU8QW=JP),.0BPIP:A +M9\J3MICYF@7W9[D7W?X_["4FS;+SS_I,/L7NU+__%>Z=1E2EVN@FS+YV2;$- +M2A>3B<.. +MXV<44ANSLDUMYZ1RUWNCP74W]I4.`XW'"N7+RV*.PEXI69IJX4<*QPCT%+]H +M4*S+2T[DR>!&:J]W3IBZ(&,1PGO!B`5G'4)IKWLG@B.76?'GX1TB4Q5$42#%,J*A:W&1]U)0IT +M.CD&+)#>9!P)TH\RV1]^2*FD517ZY\9E3^6#@98C!*8A5Y9&AO8O*( +MRG>W4HX>F!>B(?XSBD@H0%B3-#%P70#?X2/.^/F%BQ_YI`&JXT>-!`QUO0Z/ +MWP1!YVD+D#K,MW$/E1^'F_3CUCB"'=1_4Z@!G*ZVHCP[G?AGRWI`EMM]'Y6< +M#'Z66JQY[JJCP3W],#Y<*3M8\+N&X_["Q$Y>E\NTL02H(3S+6KDA%UG1-CJVZ?ZP'H +MPG%B;MRX1!K>K'%Z4";R89F7I@R`SZI;*;MM%PWB +MWU\]#3>-7)YG7#1J!"\+'7G]-H)"O=.+X,Y"$>>:%*@Y;DT8@LA"Y?ID,[A_7V3UP><%-V18C"JM +M;^1BZ@&@/ +M'\3M>;SRLRF\V@0Y+=SY:`"J.Y4.]2YIG;H!I12VT!:IV%<[*/.W(T.)K"8W +MEA,CSMP&O]!5C.\$H#G80LO."KT* +MWG&,7)]BK:C>*"<,73VW1\/G/LT80,;!R;J +M3DH%F%Y2V*G!K4CTG13$%0X&&=,JSUSL1YDW#U6T)58+C$9*M5T.BL81P7N. +M0@DZN%35RU6W]_/Q^U^K&CZ'[N;/N_&K?>]'HJ^.=5:ME"EGT%TJ'(I!1Y$= +M5TFV1E;XX0M\L9QDTPQ#SS7J1S$)0LH[1@]P0FJG^\!@AI$#.%\5VZUX-A$, +M_U>8^Z;Q^.Y"&&T`I-Q@/,FHMNN"&E(_`!32K34-5'^+=!TW6-!WL4=0XM7' +MFW7BV_*=`>SEB?3M<:H]MAA,YT%;]*!R%BN,<0&CI!9`>>W$%6-/1*.8JQ5( +M+EK>Y>`5"W4WN@'?TR-[=O-=`I=ABU&?[ZKB>A@39(2GRWFN>;S`G\]^D"YFY)%ME&*"MPW`WO,J- +M'(W4AV9L'AX>6`J.+C#5?&#:;M^*Q@CZ5Q7/D:P;YH70_CRIU'K>\?\?+C +MF-!FP<\)&&=E5T%H^??"_IQ;@1:][_54_N:*]2J\;H*V*HG#\7H='Y51:,FS +MP'H)QU0PSH,7E/4']#\'?-^AY?VO#?>P_??"%Y.PU[AP@Z]'W3YQSU^0NQ$R +M(?]Q!-<]9O/\M-M!6.Q83]]P\?I.%[OXAX&LSP`"SIF+NGZZN`)>L#$J8[D!TGC[L//OUEV.=:AC&."O4X>G2]7-)IAJ>BL#$S +MMMOY&:!R@?J?/6CQ(5N@/=QH^I\RV`)RXMU><7=;F.\D;R470`^T9/9]P,_` +MNNU1'H5)2+$X$ATC#J)&'*`,69Q)D(822Y^XE3P3:?U&:AJ-(#^$1]Z\W:!= +M*-0-LE0[IJD-42"$:C^Y[8X\`989]$.OIX\O?0Y!E9J[T5K,:6?+OW=`IY'Q +M.;&882%1P%"SAD5MQ0ZF?"KU,)0Q%GFQ4(;G0`NE"5E1K0B;+U,M(*,J:P5- +M>)>FEGFXWK$N47C/2;;+FU)CLHVQJWC_]OC73SI_C69!_)M`#(_T/-?CHH6N +MDR\XF&S+W-\H07:Y00$O*P);)'@L.\^'XEF1>E@G%$_;W"3\^*]!?\OB9!"C +M=W16G1:T\H(->%!@1[K+""\-KK8YU`T'2SA`XI`HE(@#>*4=9HL_"BL=$>S$ +MNX/XP*6]'3/GWF7G+L0:(XLU(YA9R/B3;D/TKTCY[:\>*P@8%E!FO4FE4H6T +M8L<6)T%++3%NE(ZR[YE>V@=N)5(BK%4NCCII5J[.*0QZ"1-+T4$S$EYA6E\+ +M:07*86]-J:51!G. +M27[DS<7/)0:%#3TQ,C'LGT>H"^5?9>@FGZ/1EBJ[X<7*)^XDB3$9P1=T)'') +MYADQ?+LF/^):?PQYU"D!1@_J.Q.WKNAT=9%[`.D$5+!#2H<% +MP*LV*T[;M5`K]O_R1HD$J/0-"+:1#NP\-!8:;C<2=TT1>H$-!KD]?XEVGCUJ +M8Y/G?$INL\+OGYH_#!>I&J+/,(UX79@@_&IY4`#E`*P3/1=836WGJETFVZ`B +M'LES=Y<..KZ<5I0#$?G$@?24+JC\FTG21?ADKU90:JU^1,E#$H4\<^]/Z(#8URX%;DFS*!LY8ESZP3T+/#"2UH];O\ZC](,^<>?/XOS*(I] +M^>XOFZ!QS$EIV]NWW*9K`;/;G +M\%(48"7,X-Q1-M*1L*`XV[NO1Z/N5_Y\*V;HSD))-Z,NZ_BV,D1>!3JD%L;` +M0,"]-\RS(E1I8AS<&@3'J`';[-<29#)F3!?<7R+*`/>JM,K"\HZ:E?*PV"LR +MUP^Z9LK8TTA42\1C>&=0&TSX_F/5\EJTXKPW>6\>-NXHY:5#C>)<5?%F'\?X +M5\\U2"&V`.42RSX=XMQ`%EM`_T>'?YC_2W`15N260(S'DRN_^'#O?$(;8M\I +MYZ@*F2I`P41@U0@\-0:M^%]J+;W`TCP->Y/$IAD;YBQ8"Y&)=^%X!_SO]9"' +M`@)Q;Y>#D6'Z_138%-5-*X>U.*:.//C-DD,C(KK+[$-B6QWF*L)T5;,T!RD9 +MCV3BC4R#-*G&HN`W=DGT&QP>8)J_>]-1CS<9=*FLQ(:].H0.VF)%I&Z/M/231KU]&8C)M26' +MZOA.:."<39P))&MKYF^)<>@;<#6==6BZ#6G4R>-?+TG#%Q5[/$.HY*;_"2ZE +M,NLMM[?>U)>M+HG-(JC6+C:__L%*1;B]@O(S>U)<\_>/WT/=LZX+WGS'N[O5H][Z.79XF#<"5>BX;<'\XC +MD9:0Q]@1MW>C$5)I_M[W?!K\-+&@Q"@24&#.3K7@QQG0H[_X>W!#DZ,Z7D_] +M5,&*E]U@3.J#W=W-(IRXYL<,]32V>93K-KSZHVFZ)[,<*HN7^O"A-&`%MW3C +M4*AXL[>X-\A*LDU3D1;U<;ANW5V]A7,PK]OX5*WXJGAX3`?,>$J>?SU+G2>XM +M3/#EB96:DYWIHH]X= +M-X7].;#C[?CS2\3!$31O'U,M(1\U@3J(.>V;N$][YLG8A\Q18GJA;IFY1V77 +M'LX4H#<_UR:_L;G$8RQ\*`K43USQ81\^YF;83$SSH_`TW#!Y]12^N_K'6>">`<6QJ#HB7QDOMA.YHV*R'-^ +MRKQS[GTKSFJT'2\C53$TF)F%_B`FK+[HV'=Z1KKSDQ/90\%2_5O5/V_ +MHNSMW$S""S#+GB9]3Q0MK/'\%G5$]Y[?@L[N]9A[W]+@2S'KN!@G'/W[O#DW +M;K082SN]NKX24P<731:+X)/_\E&+-]2 +M9%@5'@7HSP5+L[$_QD=0%L6=N>-'GKK^=*78D1%1H0UX(/,WH5#/9]M#R!CG +M]ZY?]E(U+DWQD\-ME#>_^,&DX&8`A_-V=O>;_'C4P`BQ1P&GUS +M'RX'+8=[J_-=_T4_V_*8&$KZOEJ_3,*^KQ5?IF5?5_B5.0KT^;_$6NXG)R/3MVXF-"K4$!BZS3SNN><<+/@7^G-1R +MC[Q7O>4X]IRI7LE/A*G]=_^#&FO6@5DU'1_W\CX=9Q\]7Q:PN"LI(7R_* +MU33)R/AW"IGU,:X.J(GO0UG?J::S"P`1,I;CX=+U%J0624@,BD, +M8>V>1;(G,469P'O&WD<)N>VJ=,Q?,F+_2[@P"N3+6-$&OU[D![AQ +MVDN`J!N37\P%!>DW6)8,.P@<0+"^CG!EX.#J=^Q`;<0&:>I32-^@U7R#'Z=]P)#-NH&'*#"DS*]Q0&DW)Z/OSL-N5.WS +M/3^8>797WE\ZZB^L)Z[_VP3/J`\T=>;%_M.HC('5A'5>D("E3[XWH)J7A8,! +MYJ#KEWQ"\\1=N1]ZV8'OO.PV3ADYTZ@]II_X#F0B?GCF./>A7L%R+-IC>!O/ +ML-KPCRB;G%[BT%Q._T0U\0J#"4QGO-[2/EW]G(U>+@X+A5]NHYU$E]P(_LG1N<^OS"T$Z:B/P8/XAHBF$DS+ +M*HG_SDQ9[WOX!H11Z?A%L1>OI)R+Y_MSK,A4C;Z^J2$]*F$=3^BB#J#%]@YL +MX/Q*T2=ZD6>$X[N,'/O)7X+M6X'+2?!10M0I\I2LJ)H'@PY7W*> +M,M<+*#==3+2Z_\C+M_I$J#2A+G\Z]>)[LP/XI?S0D&E32)4OKG$KDT\KP13S +MB'KR&X?]ZCS#WMG%Y823`Z-[>O@45!,K.2MLE2@7EY]GOU+-TV+WZD:-+II, +M.VHQY]PWG4O+$4;T#'Z_U&U\P\SUII-7"$Q+U12^91XM[&4>%RGE-%,=?Z$S +MLH4@JK/P9SR/.,<\2^?PY\[G;*@J.)4)S"/2JT@1+C]0R'0V-1R>K)E"+B:3 +M`CNG)T3HSI#+`B`_"&1!I$0N3,YCSS.7NSLS1./D#I(M+T:2%&P6K)L933*& +M:Q=FDFKXM]SYGT4WI;%Y9%G@)R$I?[U\?M:8K0K^T&71%IP4B\8%N('X.B=B +M9RPO,1E1U!B]K'ZR+9R+>+;Q$)L'_3ZHG>@$W/4!8]:^U''>,T_>\W!PW/3O +M,_3J7*Z.O3*O3*7:Z.L-5AJ7:Z.L\JSREVNCK.JLZI=KHZSBK.*7:Z.L)5A* +M7:Z.LVJS:EVNCK-*LTI=KHZS*K,J7:Z.LPJS"EVNCK!58*EVNCK`58"EVNCJ +M_57ZEVNCJ^57REVNCA`7SV1^O\J%=ADKUC55(BP&-:;'9'G^I#L'!,BLY.P3 +M/H5#(FYPGT$&*YT[?4@8C&R'QTP+CA00.-R*5+<:AM?9@4,B@'-WQ,1`N_$Q +M'G^GS\1Z!ZW`F1Y';!O^WK+05?*W^D3<_1,QMV#FM!&9C14=%_C$QU_[]B,P +M9;?]]]`?XB]?]4H?^C +M3/>9LAI^F3`MUU[BYX"UK4#:1/YH;7"!Z7WZ,5=B^8$G,1#44F))N01,4+YXU +M=U7]^(/O%QFY_+$@7/Y8,:GCB&;FY4\EOR9B-'O.L#'(Z9`,;B&)GIXHC@#: +MR1%F))B(%L`7%;Q8P&^L8SP%,PH2M5QI)BYO_,/_S`'>QQTA_U6-!6@"#JFT +M&)&/$$N7BI0*7IA3NXV[X@VLH$:1TCZ&.DO$Q,22'WH/(].Z*^KB[81E?Q!' +MW$;G'(Z/]!Q#`;G+'SS)D3^0#%[U`]T4VHWI!2&8ALS9?OXIWEYB'^AN))W7 +M",+2"$^9N9]@Y%,<#\!4#O#<&A++EHQS+B,YW2#Y)P(6()A*CM4=.&IMF@-. +M5B+F\J9("CIQUTA(9EKU/>4"=/W"A)J8CSKVW0Z4"V +M4UI#3.+@&,.<0)S!-ZR?64),;^,0S7&DHP9SSA%C6ZQ-_WQNZCM1:J1$Y8D@ +MR;!MDF0%KV/I67&`LVP4W.T8TFF@@2C%T#H=X_+;]Z)B^J]Z;+/H?IS/O?A^F&.)Z?S/>AM`BO&Q7L@WM'N^=&U^'C0 +M-RO*_A1[C?];'F:;=1YB-W1[_AC\^-RSM=LON4I?!HGG +MP:)TN)F"'FC+VDH8XP#CAOE=^>O+>(A25>N<1%ZT=8BSW6(Q^^%33DC>*HBQB<;DSL*5 +M]&'Q(?-^;*LW"MKQ,H3J3@`(46YP!YID[!B7]T04+I=;<3&;D(A-_C-*8B4X +MRCF+=D\^T^-1O?VQN&ESPY@7#B.?:7F0D%;I+7A(C;BF1CV3C-V-9'Q_DB*M +MPV18O]`!*C(A4G57KJ!TGJ#[H%V28(C(`R<<=6KRZM7Y'.MLS31[QZ+=DLL68*4<*T^^*S +MP7;6*EIX,:839Y3B_(M[\E158MFRBDJ=L.@ +MWY@(!*NGM''W +M1"%C&EA/<-[M&7VH/#^N)=1@Q2;KP.C*X+:G.:$U%I`C2LX#V3#49]7.*5U; +MJ=4W9J&:MS*FUME-RM`QSJ=5#!.+TAJ-"K%1H6SSQ;41YV__)43KTW+B6"SF +MWWI"0HX!=5>3*45^LDV?QN:U3?I%GFB::;DW`&@U",=O-./PMSZKVBM!KFG) +M4*:A5'?PT<_YN_IVRF9IF]\P]AA9F6.UF9,ECY,C0*7)3.;ZO.P\-OL:1NA\D<'JKI +MSU-.[M/?;W6%F\R'I.OI<%02CZ[C#3`S.-"N^.2+I)&T49H?D0D.[!!#>##1 +M8Y#12UIG!&=XRV859A6MX0CFW-.6G<4,EB5<><>HQ0J=5=@J./B3<%6N%,S) +MQ/LS3.-#NNMFKD:@#A-=ABHYW$2\;]Y.[35<>:V +M-M>=VO@,(TQ(40FP>]TO;KSY"4F^D^VI,I8%QI`QW?!MO"4DRAI9[#-UB`R2 +ME"HY2U`ZF:;ZH@*AR5H$;9:Z;W`2!T(_*^;Q0/RMAVIB+]TX08S*9#95&KE5 +M_MZN++GG;[S`/E.BD#C(J?F8!^A^G>XD7AG\OT"9`'Z:X?4POP.F;^Z&'U%_ +MH@B;]-!'MG862?%FW9NEP#%GF>P.N.>]Q^912JW;=%1SL2']XQQH/ +MTNGF=`N9\>]+)8I9XWZR)3UJN>HA_L;B27'_"H\A3Q3[U_O*/*('7.NWDO2? +MV/_].%#TP!/7^-NQAR3CGWCMXK]JC8^NZ3'^[=W$"G9U(*^KMI85E:SY'0/D=L\IFF +MYUL&&/IM?R/+,O,^Y<>8YG3./-EWV=4^^K.G0\Y@.9?JOE./F-^ +M:WY[?JM\QQYKSR5_,^48R9*???+CXD=!PS:>HC:#3%'OC'5IM]+P."#S@A*C +MY0J3-Y+SA?O-Z0RQL+.NV]&^/[Q+HRYIW9Z;GHU4EUS=0>H?JL%:QQV+=>W8 +MMVC>W;[]NVDPB&[;WSCP6[AOB-\5OCMW+?D-^2\3,4IZ>7AG3/0O4.OSF_FM +MXL]4#?5MUE;M2:\=X")8OC\7C$N]?*KT:;FVR;F+%?+/X/C"X:QO: +M-+]-K6V5F/C(A:[*KRM?9Y2K1U:R%>/D\Z?9#)CNTOY0DH4_@Y[ZML->U0VM +M=M+0"\;<`UF,SF!Z94]NP4=?__2F,?&5]>'=UVO:!& +M]H`="5*.KU]I:[74:G5%ALB/\9C^&\/YL[$!Q7:\/:PB]3O<`O=94K@ZJ;+8 +M6NS(>P[@>P+_`#8-V*#=&#HE.SOW1"_S\;#J_;PS6"$_--4=31&"$2-=+_5@ +M"&.Q7;`B-;?C[/QGMUQ@UMJX%QH`P0=9U6]G8!KP8/7;7I&=;.QKR1RUE&B+ +M!_J/]3^<;4`R1N)/"P_4=>`^GXVVDCOGG017E;4U8;"B?B0_538%S5U(HO." +M_F/UGJ,0[W`=IICNK-(C8CKL+(>NQ$S[`/010#^T%(Z2(K!>JH?&TXHS1L]I +MJ-)K-`[LOI!XC)9F5VMHJJT@_DBX/3$X(TV8*X:T&4V&4HE7Y/^R.!@G<9%@ +M.[-Z#D>35KM*X^P*N'`S2447,9FB[#LNQ(O@(S9F&ZBMK6"U<[[(W@@SMDDG +MM51@[GZ+OA;()CE*!Z#/;$?\):(X>,W: +M&#&1J:_;5.XL\CAY'MD`\@OX3&!_('T*GN11A#]@.+#(D/G3(5DX\'R/C7GK:5=;@3]R8J4 +M>?E"?5G2`ZV`?R']U-H]%!!!\BKHNAI_F@V=35V>1:8_(FN:TG[@@_U_R0O$ +MH3XRWPAZ`=5-4)ONCJ=31$!9L]*^S>D^D%SH6ZL3V"'O7[C!$MB/D&9$3Y6& +M>;(FZ%A_,GE>T^A&[_)&3^9%LJ8>F?-&B!:E_ZOKME6FET^?EQ,U=E8"M,T>W%(_L-F&\^6S4`Z^UW?"2E37K:4J3= +M'7X=)\@KP.A&%SSH5_P'^B:;J@&F)ROS2KL"@?2PI:U]?1I1_L&2%_);D:5G +MOCM%N]!6;!=$NP5[=DR#^JM;3`&SNPVPF"E>$J'>P!>K6QE3SP1VJ-=+Y_=E +M"WX:5EX_]I;O.4PZ>XM=@:Z%FCBI>KW"ZXRPG'EFP;`D-BX[P.[T1G'8=AA7[O<5+W4KE=F*Y+J)YZ/7(VC*R6/X)PTE +M&\V*IL;4()FC*+:2?\2=X*N?Y55]+=MI7A:-)_G:' +MY%_>&'_`(YKP<.<$:.DB]@R="J>2>/W@?-*S^X@_HR#2`Q1VE@9QGY7#\B'7 +M`0=X(2X8``W(0#BQL*YB1>5-^>F_&=C7`;[M*;.T]/H-/W*,.'(!3\H?PH#S +M9A-;7M//UATM!\DJ!]K!!L5/[N`=(:GQ1YW)3LJDV43G=$`>@]4`M#1V.2PXW6_//-#+'G\@)1_`SZ$SO\$: +MHED45-B3^+]+>23S6[<"?VH^3?GI$MFDOT:]P4B_\*1]H]D@+LJZJKD2+#O8 +MT3DT+^C1I:1*2S0R3"+`XEW]8$R9OZR]E/WZ4OL#=UMB+#=DQ]+JG.OE5]I#3=HJ"8>"&`ORCM0_^C +MV`ZPBK5;UYWAD.;)$3X6>S29]#WSW*H'06,_J:_"9OV&;;2]"T*!VA_^#!6@ +MQ8)X\1&M@/-?AL7S?V3\7:G9M9ZD_EA^_UU&$X8+IABW +ME98Q?VEA+UW\Q'SO:)AOS1O%\T:$]6[4:[&>`Z^43+=Q#1;)"?+(V*MG@CKW*9`)@&>`S +M>):+%@BBLF(NG8_(4UBSKMK@7Z2<<68+W+H[_?NS7FLN@7\C]E#N>D(ZEU$M +M>A'AIW"W9ESXT1C:\=<+F[J/D8G$JTOB/RL&I4@HTO2'72N_6SR\ZLES2ZNE +M'J<,JW!^83LK'H=K542X0C<#P1.NJ.T1/,,;=K?B*-;GYE)#TD_RM_]39]*+ +M[+V\_PP6(#D$%2P26M$\L#A/(SCI.]6QLJ\-*YL+)Y0?`=KLUOW*5I;\:)&> +M[*MPQ.,UTI..D?+]"Y+6+[U%/JZ70?(1/%F8=W]#\6[W#*%'K("[,\L\5_X] +M0^^OT.ET_<9VGPRQ';'8)BR?ES>6-E6F=:0\\9$+"*W(]FA.K]W?RH&Z3-A1 +MX4H?H,]\M12F@GCIP)6[2PPP&1.::3@V1VEE-(;1X'Q/>,`U]GATCE(S]"NB +M3\'];_5^X)VZDE8M!/:;2ZC2:ID +M?ZAHMI@7[PFDYP"J_L(5%H@Q3DR_B'-4BP.\]I:6_,.PDO(K[9%Q5'_U4;$3 +M;19E\6[N6HN,RRK2U_X:N>V47UR?O:M.Y=^?"ZT,[@X#!L```,```(```0)1 +M3TK_DO<[`()G-[K//$4R`AL+R^8`!+C%!>V#`N#-XEW`'0$296QF+4QI;G5X +E+4%2378W+6QS"@,3JRFO6QUI@`R+1U$F`P4$`0`````````````` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_multiarchive_solid.part04.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_multiarchive_solid.part04.rar.uu new file mode 100644 index 0000000..efba21d --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_multiarchive_solid.part04.rar.uu @@ -0,0 +1,76 @@ +begin 644 test_read_format_rar5_multiarchive_solid.part04.rar +M4F%R(1H'`0":-0&C#0$%"`<#!P$!@("`@`#=A_^>,@(+"_>8``2XQ07M@P+K +MD6^(P!T!$F5L9BU,:6YU>"U!4DUV-RUL +MN64SWV>!5I_7;2651I*@W)FU^2!DC>VEJ42TL3HW*X8;OLDQ.>[-9?)#V/F. +M*2X(JT=&B/=8&2W*DO[.K$-"7=K=U+R6'K@N=J(/[59-VZO7@UA8!6O. +M`6'W1ZISUK)\P5PW]5N&5U)1_R@#6(3XBNLAEPFKL!10UJ-!2CYD782SXD-= +M:;AJ4ZX.Q>J3#"?35/B.T`ZK;)=L\2ZF@W-\IXE1K8U]2(.Q'T%[6RF;`^97 +MQ@75ZJ:\B'TKWEDDN!?F=1>.2B8C@#W8,32+4SR)@E>_@42;>I%E="<_4D7N +M$=\.V3-DA?^9(+2-27=VTSAH&Q&;U8!S+J)P7AJCSM +MPO?_N#T;IN\"WC^%T6"*ZE*AJ+$_6E?B65;4=EQNVC:;X3#VS>4_D#^50HF9 +M:Z90C4Z9V/+)[[1%NTKB<`R%;WHJ3`-SLS<,+9#_H6E\LW^&S69VSM#=)S92 +MZ302_(!0EA6(+]?I/@A_IP5+G`WB`S[LEIA[A;] +M2ZG)*NWV9/,[IZVQ-&T+Q,U5KL#5_I\B/P?01_`@W:@K-?9QMAM+7*238+O/ +MFQ`$4#A+Q_\V/;Z`=O1=SJ6K]R7&QM+2QS65RNV']E'GYRMG8:^TVPF_65OW +M3*J-$B[^:]="Y6@M0&I3DA_PD'HA\M$=U$ERGF\A_[D76\'?*@HLLK9BRC6Y64Q/M-J=+3Z3N=%WB5]T? +M=%)^&(](=AW-=6+.^#1M2TYRTKQ@7_YIE\AGM+2ZGN.YU&$`7C[ZYZ'G^,!W +M3YWM29OL(`)7H4VU\D#QY_KPFPQ5=9K]AL:[95^S<+'O0@?MKM=MFMN'&>S^ +MAT6CTF:I>YTVG`^\UJ=5K*1]*@Z2=86,L!C)_QCK*'_.D$ZE%5:6Y3N:XX7-8"T7C[3AO$CL!O<91K4"X3\#\U.T?9^I!718:FK[<%8[Z +MN#@&+/:TNESW;]XD3\/[`>F3-R'Y8Z?2=QH'I7B_'"@WJTS^8+MX=EF<>?=+ +M=[?WXZ-`&(C6M:M(-_1R"U6UY,_GJ=]U^0T>:R'<9)BJ,K3'VCP$'Z`F0U=' +MD-F/^$'2W;=-1E,AW(\^^P;/+NB/)=H/ST\B7E]G8;1%F\&9=+ +M(LHZ90E)&JT2'>4/FS`_HNU:A*N5X*='`K_WG>2J\HP,3Z;3SA?SJ?">_16^ +MLF&NP:#MT/7//TSYU?>2[,,=KM%W9:`/Z$N[H_H;0AX/S\.!%96P!R:>=Y55 +M-G6EU_BR0I-L`_%9*P,4?.U]ED7LO@:1#PNHMUK1AU75:TCX6M&DGDNT/^S4 +MI4/1B<5->;A/-Q1L7LWX?$"&5X7\\OG"(*%&W"F<>0G'Q[_-UH,AE<_I-/H, +M^.Q]Q_FHU/:RWM*:Z-,$/&H=.D4AE#[I]L0JC1^?/_M.\>1K5"/GF[VM;WAA +MT/GP;R37:=HU%0):[0B-AL-H)/^L98FI1_`SA8,2O,L-7)F_LJ7WA1A]?9S. +M`%V9"1:3L\OF'N_8J?8/,>7=N61K[+L\Q2.2*HR[WOF%3,*,L\SN](Z +M?-UO;OA2]/EJ7727C]IYUCQY5F+3[Y"[6/L#=&FF1,3^Y2Z/#YX)9\?/75PQ +MGTF2]\GB0"*__<-P)ER2[5NQ$ +MLB=P@'Q2O]94!73ZNU]&G9\BX62Y"J:R`5UK(:N_\UG>/*4X1\3M7U8CH>JU +MO7F81QKS#NQ/='=U0GV*L];,^];MRWECL[62[!L1_=AMC#74$=%P8U.SJJX,I29PIMPNJZC.;*Y1W5$\Z'Z`O+25)\A +MS49445R]B5]MLY^3U*7.>_\?F#$'I]CGK2\YJ59C[(5]K.EGJK6KV5;:*]95 +MGS69IRM4.0!1K\AD,DB-.SJ=N\[MJO`?M@B#:1Z^[?N-%3TV@UAD`8U1F,B7 +M2FX/0`1:77K[TC:5_5U_^P@I=6#@:?3Z#/4[ZMT&PT6R[?9]Q8TUI3[C5]]K +M"=>,ZUW.II:4Q6-KK8OT6ML%><6(IW)L3YL08W8"Y?T(K-O6U;AN!4?VS">2 +MOKPG4RN4KZZJ"9XK[2CP>*=F+_'.3:\9C][UW2[/4+F*/5/?O_[DQ5O,]=A% +MD6WC/N3_0GU(;UJGDS=:6/BGZC$1=F97>C>GO,DJZ/9CQJA0UB5_9#9Y7(5@ +M_Y#2O(&+\TG?;W<(-XO$E:$=9)+"[/FG9]0Y[)/IVE%:\[064QHJ:EVN7Z_- +M)8#D^[BPM3./V,UI8/6[$]A;48@31)F!]UP*V;!,]$OJ_; +M,):W6=PYO^5`/ET"]W_?W/RX:?\8>841$5PVZ$S#C4,F,'J4@[99[O2;2K"59V=;LSA@=OL:FU*-_(`V[/HV4_T4I +M7ROWKT23]KKNNP/L6U$-!2OLJQ\K\I5RQU@$[R$L<_Q:3O(RS79VNO"*_FRN +M<*=V:(=(RDKVP$W_";>+LUXDF_E;^!NK!JXAK^GA>F7]/:=6I'UAAGU?`8ZV.??&*O^W0Z-A +MP=RO'3/J*W<[Q,FUYQ9)Y?T1IU-_CLO/U"">_Q#D-;!4YY[\[AOOW_^YVJE?-XXT?C?_>.G)Y^MOY13Q'RU +MJ9Y,5_=@,C]B>O@LDW:YU:`NB=VE*/M"][T3MS"LOG?+F\&ZY]5I7+3MZYVU +MC=?+@IH%M)*SZY'4IIB_WCQS9Z&3QSCYA,\H^^,Q;/.[UT!?=/\&]W9K]\H$ +MT6>SV::H17FQ$.)J$_G'\[`Q,Q/O\4_ZE_\R#0/^K?XN!\V#C'_6@7.4L]B3=Z'\CQ7> +M#D=Q;CJMRF=[72"ZGK8/>I0+VJM:ZOK*,69_=T;7H\:S<;060C.X!VQI8@_& +M!].\+795M>CHSPL:^T2'BN/^I8CS*'Z>^PU6!^E-P(?M/W&4"^OJS;CRK=B% +M$"OU;E?STPJ,=/IF#93M,RONM8?Q/,G^>_BEIZRWU[!V?27F`(D(IE) +M=T-33SW';P5;AJSW[PS-,K"9OJV-[[!1=VTNZ(:1QT*K=BD-/V"IJE;Z9WGDX +M`%<>8W,83#/YUY;9!8@%]F3Z?ZEY;ER%`I'<]/+O\Q+S7'FJ]/I2:Y$^P97[ +MWV#&7E;^67!2@M'3IZK_I9"_FEW2[UL"2N&95EWKV7O-V)\>ZN%S#5Y+R38K +H/9W66E.Q+(N>XP"]]!;_)_1#+2813H\*W_]K2Z?M5Y0==U91`P4$```` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_multiple_files.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_multiple_files.rar.uu new file mode 100644 index 0000000..3fa8930 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_multiple_files.rar.uu @@ -0,0 +1,40 @@ +begin 644 rar5_multiple_files.rar +M4F%R(1H'`0#SX8+K"P$%!P`&`0&`@(```Q:>PB<"`POD`@2`(*2#`L:R$WZ` +M!0$)=&5S=#$N8FEN"@,39U^L6QI:GA#*\6`!$&149R]7!6]2222222222222 +M2222222222222222222222222222222222222222222222223]_>QS,[=]KH +MNGVI+KKMQN[YG1YO.?)\8S,,Z9YISXGZ@`@`@!L,/'3AMZ>?EX^'?W +M=O9U]73T<_-R\G'QUL[&OK:NIIZ6CH9^=FYF7E9.1CXV+B8>%@ +MX%_?7MY=W5S<6]M:VEG96-A7UU;65=54U%/34M)1T5#03\].SDW-3,Q+RTK* +M20G`@,+Y`($@""D@P++KV;Q@`4!"71E +M;SGR?&,S#.G,-:<^)^H`(`(`:F'CIPV]//R\?#O[NWLZ^KI +MZ.?FY>3CXN'@W][=W-O:V=C7UM74T]+1T,_.SVM;2SLK&PKZZMK*NJJ:BGIJ6DHZ*AH)^>G9R;FIF8EY:5E).2D9"/ +MCHV,BXJ)B(>&A82#@H&`?WY]?'MZ_ON^Q[HI<*6[[.*%`9^&`%LZ(WB-`0Z$ +M+6!8#A$[=I:>$/SLT`LP`MG1&Z1H"'0A:P+`<(G;E+3PA^$/SP"W)P(#"_`"!(`@I(,"V2.QGX`%`0ET97-T,RYB +M:6X*`Q-^7ZQ;T#T``\G^;`$0=%5&+W5]2222222222222222222222222222 +M2222222222222222222222222222222223?M^W[>QSF>.F[VO"\=J2\Z]?EX^'?W=O9U]73T<_ +M-R\G'QUL[&OK:NIIZ6CH9^=FYF7E9.1CXV+B8>%@X%_?7MY=W5 +MS<6]M:VEG96-A7UU;65=54U%/34M)1T5#03\].SDW-3,Q+RTK*2]3W!#?Q#9>S$&#J;"`FDX$V"95@TP3;D +MPGC2984NWA$H>#3P`Z&(":3@37)E5S0\:;D`-I,L*7;LB4/!IV`=#$!-)P)K +M$RJQH>--R`&TF6%+MT1*'@TZ`.AB`FDX$U2954T/&FY`#:3+"E]3]\$?F.5' +MWVDCZ;\1\Q.9UASN?OW#G\GZ@`@`@!KNF%E5/3S\O'P[^[ +MM[.OJZ>CGYN7DX^+AX-_>W=S;VMG8U];5U-/2T=#/SLW,R\K)R,?&Q<3#PL' +M`O[Z]O+NZN;BWMK6TL[*QL*^NK:RKJJFHIZ:EI*.BH:"?GIV6E92 +M3DI&0CXZ-C(N*B8B'AH6$@X*!@']^?7Q[>O[[WNO<$-_$-E[,08.IL(":3@3 +M8)E6#3!-N3">-)EA2[7(E#P:7`.AB`FDX$UB958T/&FY`#:3+"EV\(E#P:>` +M'0Q`32<":I,JJ:'C3<@!M)EA2[=D2AX-.P#H8@)I.!-0F54-#QIN0`VDRPI? +D=?O@C\QRH^^TD?3?B/F+D.=:AQZT.#3\5'_^`!UW5E$#!00` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_multiple_files_solid.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_multiple_files_solid.rar.uu new file mode 100644 index 0000000..4a8acb0 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_multiple_files_solid.rar.uu @@ -0,0 +1,19 @@ +begin 644 rar5_multiple_files_solid.rar +M4F%R(1H'`0`)[\AO"P$%!P0&`0&`@(``&8R4_R<"`POY`@2`(*2#`L:R$WZ` +M'0$)=&5S=#$N8FEN"@,39U^L6QI:GA#)YW4!&&5492;T@%?U\^?/DDDDDDDD +MDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDO\\YG#6M +MEU>^U%T\J3G5RSM\>Y[K?1K,SKP\_'=-M[V;Z=_QC-9YYK#.K,Z<_!W``(`( +M`;##?S\>_N[>SKZNGHY^;EY./BX>#?WMWFI:2CHJ&@GYZ=G) +MN:F9B7EI64DY*1D(^.C8R+BHF(AX:%A(."@8!_?GU\>WIY>/__O[_/W[V8]@ +MIG"F6O5\HHC7\D(6UP%MQ8#$T:+90ED3*`YM@Q@Q-FR(B6D(6UP%^8L!B:-% +MLH2R)E`<_(,8,3;R1$2TA"VN`OQ%@,31HME"61,H#GX!C!B;>"(B6D(6UP%] +MXL!B:-%LH2R)E`:8=>%?F.N5]]Q:OIMZKYB^ISUY3E[BG(VOBL7^`#MSXI$G +M`@,+F0`$@""D@P++KV;QP!T!"71E#%ZG\PZ\._C^7^`):4S(``#__^_P```4```& +M`````````````+`!`@`A`/_F````(-(```#_____``@`___[`/_=``(A``++ +M``"`]/^`!P!#^_____\"(2$!`@`A````_R4``B$A`0(`@````0```"#&`/_= +M``(A@/\`AH9ML63,M\R`_P```,@;`````!@`````_0`````````!87(A&@<` +5`(WO`M(``O8'&X`'`#C[_X`E``(A +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_owner.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_owner.rar.uu new file mode 100644 index 0000000..285bdb9 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_owner.rar.uu @@ -0,0 +1,8 @@ +begin 644 test_read_format_rar5_owner.rar +M4F%R(1H'`0`SDK7E"@$%!@`%`0&`@`!W:E-^+0(##H4`!H4`I(,"_8VW7"$7 +MDWV```$('0-!@,$2YT>'01!@,&;F]B;V1Y!VYO9W)O=7`U +M-CB#;(H```0MN=6UE\"T@`"T@"4RQ_5]0#O0````,L?Q_T``(`" +MT@"4RQ_=V-C8`)3+']W=]0"-\`+2`)3+']WU`(WO`M(``M(`E,L?U?4`[P+2 +M`)3+'\?]``"``M(`E,L?W=C8V`"4RQ_=]0#V`(WO`M'UV,?8V-C8$=C8V-C8 +MV(W8V-C8V-C8V-C8V-C8V-C8V-C8V-C8V-C8!]C8V-C8V-C8V-C8V-C8V-C8 +MV-C8V-C8V-C(V-C8V-C2`)3+']W8V-C8V-C8V-C8V-C8V-C8@-C8V-C8V-C8 +MV/+8V-C8V-C8V-C8`038V-C8V-C8V-C8V-C8V-C8V`?8V-C8V-C8V-C8!-C8 +MV-C8V-C8V-C8V-C8V-C8V`?8V-C8V-C8V-C8V-C8`(`"V`7V`(WO`M'U`]L? +MW?4`C>\"T@`"T@"4'__U`(WO`N``E,L?W84`C0`0T@"4RQ_=V-C8V-C8V`"4 +MR_\R]0#V`(W8V-C8V-C8V-C8V-C8V-C8V-C8V-C8V`?8V-C8V-C8V-C8V-C8 +MV-C8V-C8V-C8V-C8R-C8V-C8T@"4RQ_=V-C8V-C8V-C8V-C8V-C8V(#8V-C8 +MV-C8````9-C8V-C8V!'8V-C8V-C8]]C8V-C8V-C8V-C8V/+8V-C8V-C8V-C8 +=`038V-C8V-C8V-C8V-C8V-C8V`?8V-C8V-C8V-@` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_solid.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_solid.rar.uu new file mode 100644 index 0000000..f4d06c7 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_solid.rar.uu @@ -0,0 +1,27 @@ +begin 644 test_read_format_rar5_solid.rar +M4F%R(1H'`0`)[\AO"P$%!P0&`0&`@(``Y3=C#"8"`PNG`P2P":2#`LUPRGR` +M'0$(=&5S="YB:6X*`Q.+5ZQ;^!BM'LTUHP$H=E560?1@6-L,?'&,&#'QQBRR +MQC&63&#!9999#'QLLLF,8LD)\9"223XR$A)))(2?.222$(220A"220DDA"$O +M?GOFO?-:2EV7.C+W-]O[F][\UT:YS?7KE^_SOEJUK5:Z=?W.;K=OHWNY6]_X9H`$`!`-2EP'SS]?G[_;Z?/X_#W^[V^SU>GT>?S>7R>+ +MP]_O=SM]KL]CK]7J=+H\_G;O=;G<;?;;39[+8:_ +M7:S5:G4:?3:72:+0Z#/9S-YG,5V7RV5RE54U&3R./QV,IJ6DH\7B<1AL+A)^ +M>G9R;FIG`7^_7R]7F[W:Z7.Y7&WVVV2"H4:^RH@6WA;;=>TLP;<\(C9ES0)A +M"0S24<&6T))M+(Q2K/T7"3U5J_?EK'DC(E)6XI6X%+R18*3*BE"I[J5;*EH[ +MP6QEBW][+H7TO'+E]9@I29*@FBJYLM7.%Q9TO!/$]GRP-`590EM<.76HB_&* +M+!T99VD+ATI>NF*8QI9JG+CY`OEDBH:@M;4EW:HI:K+/UA=.M*3KB,S<;NDG +M`@,+@0$$@""D@P+&LA-^P!T!"71E_Z1)!;Q!;;KVH)@VYX1&S+F@3`$AFDHX,MH23:61C&_!'Q +MI+GZ`VDHC9ES0)?"0S24<&6T))M+(QC>@CXTESU`;241LRYH$O!(9I*.#+:$ +MDVED8I3OA=ECKEQN^6NQ;W5V$7ZXO7RXKWBXHW7_KC/PKJ>2!"<"`PN8``2` +M(*2#`LNO9O'`'0$)=&5S=#(N8FEN"@,3>E^L6RU4P_X4[XC_'\S\!M2\W-)P(#"Y@`!(`@I(," +M_TBD-L`=`0ET97-T-BYB:6X*`Q-?9ZQ;.X_4%T4*%6@`0`0`W[/C^B,#&;'\ +/IWQ'^/YGX!UW5E$#!00` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_stored.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_stored.rar.uu new file mode 100644 index 0000000..405b879 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_stored.rar.uu @@ -0,0 +1,6 @@ +begin 644 rar5_stored.rar +M4F%R(1H'`0`SDK7E"@$%!@`%`0&`@``X,`9C+`(#"YT`!)T`I(,"M$.@E8`` +M`0YH96QL;W=OPH@("`@<&%C:U]U=64@)&%R9W8*?0JEGN@6*`(#"ZX&!*X&I(,"GL1> +M?H```0IC96)U;&$N='AT"@,3V'*P6X;U-RQ#96)U;&$*"D-O(&EN;F5G;R!C +M96)U;&$N"D]N82!N:64@;6$@=V[$F71R>FYOQ9MC:2X*2F5S="!S;V+$A2!N +M82!WF5N:6$L +M"FUO9\6"86)Y('=E:G)Z9<2'('<@GEZ;F$@:2!D>FEK;\6;Q(<*;&5D=VEE('-K +MP[-RQ(4@<')Z>6MR>71A+`II;F9E2!C +M96)U;&$@='=OGEL:2!T2!BF-Z92P@;F5R=WDL(,6\><6">2P*Q9ML=7IY(&D@FT@9&]S:V]N8<6" +M;\6;8VDN"@HH5VESQ8)A=V$@4WIY;6)OP$``*,!``#-`0``^0$``"<"``!7`@``B0(` +M`+T"``#S`@``*P,``&4#``"A`P``WP,``!\$``!A!```I00``.L$```S!0`` +M?04``,D%```7!@``9P8``+D&```-!P``8P<``+L'```5"```<0@``,\(```O +M"0``D0D``/4)``!;"@``PPH``"T+``"9"P``!PP``'<,``#I#```70T``-,- +M``!+#@``Q0X``$$/``"_#P``/Q```,$0``!%$0``RQ$``%,2``#=$@``:1,` +M`/<3``"'%```&14``*T5``!#%@``VQ8``'47```1&```KQ@``$\9``#Q&0`` +ME1H``#L;``#C&P``C1P``#D=``#G'0``EQX``$D?``#]'P``LR```&LA```E +M(@``X2(``)\C``!?)```(24``.4E``"K)@````"K7P``Y6```"%B``!?8P``GV0` +M`.%E```E9P``:V@``+-I``#]:@``26P``)=M``#G;@``.7```(UQ``#C<@`` +M.W0``)5U``#Q=@``3W@``*]Y```1>P``=7P``-M]``!#?P``K8```!F"``"' +M@P``]X0``&F&``#=AP``4XD``,N*``!%C```P8T``#^/``"_D```09(``,63 +M``!+E0``TY8``%V8``#IF0``=YL```>=``"9G@``+:```,.A``!;HP``]:0` +M`)&F```OJ```SZD``'&K```5K0``NZX``&.P```-L@``N;,``&>U```7MP`` +MR;@``'VZ```SO```Z[T``*6_``!AP0``'\,``-_$``"AQ@``9<@``"O*``#S +MRP``O,``+7E``";YP``@^D``&WK``!9[0``1^\``#?Q```I\P``'?4` +M`!/W```+^0``!?L```']``#__@``_P`!``$#`0`%!0$`"P3 +M?8!``0AF:6QE+G1X=#$R,S0*8QI3.2T"`PT`!@CMPP)7C;=<`````(!``0MS +M>6UL:6YK+G1X=`P%`0`(9FEL92YT>'2.NOQU)`(#"``&`^W#`DF6MUP````` +M@$`!!V1IWMNP$+-5H*^@`!`$OOB]$````0"S5:*@`` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_win32.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_win32.rar.uu new file mode 100644 index 0000000..16d9fce --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar5_win32.rar.uu @@ -0,0 +1,69 @@ +begin 644 test_read_format_rar5_win32.rar +M4F%R(1H'`0#SX8+K"P$%!P`&`0&`@(``EV&"+"$"`PL`!0`0`````(````=T +M97-T9&ER"@,"5NNI_W0?[W +MVO?=>:\Z7^@`0`$`R""?GX]O7T\O'O[NSKZNGHY^7DX^+AX-_=W-K9U];5U- +M/2T,_-S,K)R,?&Q<3#P;^]O+NYN+>VM;2SLK&OKJVKJJFGI:2CHJ&@GYV'9T$&P`\Q!(R">9A6-`NFH9;8-YN'@X!@<@^N +M81.@IG88#P-MZ'N]AU?0C?Q80(T8,><*'DT)@V+XX.8Z'"($J>&%%CMC0_GQ +M4(!L(0T(A-(QG)`O)0`QGD%J)0(#"^L"!(`@(,:R$WZ``P`)=&5S=#$N8FEN +M"@,"$I6A@`U:U`'-\6<7#G7SNUN[YG1F[ +MO3O]%F,,Z?#,/6YOF>>GO;]_`_=OV`"`"`&PPZ<-FGU\_'O[>OIY^7CX=_=V +M]G7U=/1S\W+R5DY&/C8N)AX6#@ +M7]]>WEW=7-Q;VUK:6=E8V%?75M95U5344]-2TE'14-!/ST[.3FYH!9@!;-"-LC0$.A +M"U@6`X1/;5+3@AZ:F@%F`%LT(VB-`0Z$+6!8#A$UA]Z%,?GS*>SVE?X8*>=C +M4\-BG=.J=HXIZ?]R?M!(:PP')0(#"^L"!(`@(<7#G7SNUN[YG1F[ +MO3O]%F,,Z?#,/6YOF>>GO;]_`_=OV`"`"`&IATX;-/KY^/?V]?3S\O'P[^[M +M[.OJZ>CGYN7DX^+AX-_>W=S;VMG8U];5U-/2T=#/SLW,R\K)R,?&Q<3#PL'` +MO[Z]O+NZN;BWMK6TL[*QL*^NK:RKJJFHIZ:EI*.BH:"?GIV6E923 +MDI&0CXZ-C(N*B8B'AH6$@X*!@'_WO8_D*7"EJ_4J%`9V,`+9H1ND:`AT(6L" +MP'")[\[SO-RUK/'AS>Z]>]72\[VUGX; +MSPS6]^._Z+,89X_&9MAOF??:->O/X'?K\@`@`@!LK,L+N/CW]O7T\_+Q\._N +M[>SKZNGHY^;EY./BX>#?WMWFI:2CHJ&@GYZ=G)N:F9B7EI64 +MDY*1D(^.C8R+BHF(AX:%A(."@8!_?O_[[UOQB$^$)+[%!@ZJP@)I6!-DF59- +M,DTP85+::84MW9$H?1AV`=#$!-*P)L$RK!I@FF#"I;33"ENZ(E#Z,.@#H8@) +MI6!-UH>G1#RK4/$L0^/_<7F@SHER0)0(#"_<"!(`@(-0^Q!"` +M`P`)=&5S=#0N8FEN"@,"`HP9@0U:U`'/YW,!$&1552]7!7XDDDDDDDDDDDDD +MDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDG.\[SG-RUK/' +MASFZ]>]72\[VUGX;SPS6]^._Z+,89X_&9MAOF??:->O/X'?K\@`@`@!L*,KK +M*_'O[>OIY^7CX=_=V]G7U=/1S\W+R5DY&/C8N)AX6#@7]]>WEW=7-Q;VUK:6=E8V%?75M95U5344]-2TE'14-! +M/ST[.3$.%]B +M@P=380$TG`FR3*LFF2;D&$RVFF%+=@B4/HPP`=#$!-)P)KDRJYI<SKZNGHY^;EY./BX>#?WMWFI:2CHJ&@GYZ=G)N:F9B7EI64DY*1D(^.C8R+BHF(AX:%A(."@8!_? +MO_[[W'XXA.D)1LT$"OW!PR6LE*QQ<,847-+AIH@;:C`.CV[!$+6S=F"ILX9+ +M62E8XL&,*+&E@TT0-M1@'1[=`B%K9NC!4V<,EK)2L<5#&%%32H::(&VHP#H] +MN01"ULW)@J;.&2UDI6.*!C"BAI0--$#;48!T?G'][B''U_9#Z?:1^AHA[VM# +MT\$/*RH>)D0^/_<?EX^'?W= +MO9U]73T<_-R\G'QUL[&OK:NIIZ6CH9^=FYF7E9.1CXV+B8>%@X +M%_?7MY=W5S<6]M:VEG96-A7UU;65=54U%/34M)1T5#03\].SDW-3,Q+RTK*2 +MW((A:V;DP5-G#):R4K'%`QA10TH&FB!M +KJ,`Z/SC^]Q#CZ_LA]/M(_0T0][6AZ>"'E94/$R(?'_N'S0`==U91`P4$```` +` +end diff --git a/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_binary_data.rar.uu b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_binary_data.rar.uu new file mode 100644 index 0000000..4d1cbd3 --- /dev/null +++ b/dependencies/libarchive-3.4.2/libarchive/test/test_read_format_rar_binary_data.rar.uu @@ -0,0 +1,24041 @@ +begin 644 - +M4F%R(1H'`,^0FQ_"3YH!RD,Z._X"C +M/3#[L-WCJ0?Q9",77X67HMV_1C2F(]0P@?Z"9RE>_0N+T*7C84;A.$^%HPA; +M/KUC-]:V(`P@K9E&,@HSQ]U%GA;<)"GN_\AU$IRQ\KUSU;63D\I.`4(_S07> +M>$9$ND1O4EV);?>1KZZW"N/>"ZG*OF:N2,7H]!YS]"['2*H#!:)Y59O#/R\` +MM5')`+4BR:67<3XVKC3Q7E>-;3[CX&%KM8F>0(%==8/R5-J:IG?W?5P"D>U= +M%!__'*.I(1-Y1FVS.%=5N,3+3$P[E0 +M30J[Y//-1_PYW"5":O`88AEH37"5D8`,8^C!Z[\7^I$,>`0%2:3IQ&`X?&:( +M(,!!%TMGR`#P>3]6F/8[X`.,^O!J!NG>1;V9&QO/*6!H15"H\[_27B^$5E)! +M773$UGJ>J\234H#^5=@E]=$4JQIC::ZU02/SA6V@$-41FXK>Y(W$"3_O0SF9 +MJ[>EGV^>OP@GM)&8B!"9)72FL`@A;:,@-!^4-X=65NE*$8S5/BKC`6[(AH;8)VO/U,KZZG6!VW_C1`%@3YH +M]G]K;?MK*%"J.4L?N!*76PBI$EN,RS)G>:8J1F"7(*!G;!*.?AAPV45D71.T"2"$Z&C'0>IQS->4S[HEPMZ_G`5'!0^0)F.8YV +MS!,*!XVJ3ZH'[Q,'"<2H3W._Y0\MBG(G=#8GL#0<[20A/G;@+Q%&4B^Q\X$E +MPZWD]J1,_@==SDD]&F;[*PUXIQ4NC!#S3'!;15_7P`U(*A.YD:F]TIXL?D:N +M,9LG5"_X#>1]3E23QD`GVQ8_2(O$>E#%[)$?MJ//V7.(?"+3X@F99&=%L&:B +M__]<*N??GVC52W1`I9T87);1!2MLR\O!G9R>N5MI3R1K@6*2M@)W4[/WQ"V[ +M>N(HLU;(A$4KST@UXM4"><",_U*+V5J#686%64H=%D#YV]UMY-=RJ\]+95N2 +M%%JU]F^[A,IK1/6;H^T=)!RVW1>)'>2VD0AQZEZ\]H%E!3M-^M,XYZK"W$]K +M#&"/?=O&F]KX`#<:@CH8@MP^1.#KXT!Q2XWC&HRE[:^A2&P!26IP*3!V"-1J +MQ9=!=>%;CHYSAC.W;F@$?36-+-+\M0/`3M@ +M!U-P0'^H??-M,%M=B&(P)+!#:28%<.9$-<8W5>MK!U)(!43<_TSSTSO% +MN)K"K`\J]FJ'TB35L*@/3ERCT`X0KH3-3.SK<,*YWC3F67EM>L,K>33;,^:8 +M;`E$ZUQG`1J$W]QRUG.,)<>B[2F4>XYS^+:DW+`N'-^L6^[/("-F.6RX^[*H +M3L3/P/W>C@#/>F?O"%4:E>V&G"6)29K!6Y_G"SD]WF^4N'P +M/8#B#@EG>I9S(TM+Z=A^_.EU.'UR;_ZS,80F2"FQ-X78_E*.C)VU(ZX^4"F3-CX*`J-US0G8R; +MW%@39U`!(D_T8U0>%`8H/JT_`$OMQ>GQ3%34E'NU#U9#'(V$"=775 +M;N]Y?6^FP/NZ;AXOR4/6YBH<\>S0JZ'.?$JQIH)KAE='5K0VR?*-3Y'K#_YX +M*F2:RW;UV,K[N<>3^L(VL@'J->$MJ0K5_>,,G>2\JG(3]H`HU(SPY@R2:0'0]VC1(D\EO)9CH">V!I +M!7[A\D]KI%UE7_A"VP)N]F9Y4$`W-'GLXUNP3PZ[_%4]HV/A.,+_[?!#O/5` +MOI1GNU?G<2HF5JI%L"`*Z4C'RI+5S$_7@1 +M%Y!*!Z +M[\6F^SMVP.NYW<03D2^<%Y&5<').^5!5+Y`\YTA&U+3]=(O)L%`%29]=R3I9 +ME>%`MZ7!5G$%AZO'6Y`V?#SUY*3%HH^%[/L0I)E@X51:1(,R]LM_-\_-$S8K +M;(W8HW<\9VVKS:;`S+#(7J$Y&295B_](,PRHB!.BF=00C?7N3&.1"^N,7@LPI@ADB8U<(7JQV"7UN">9?A +MBJ*Z&R,T%#TH4KSTRS=/&'ZB.KV_B<][@ZV+$6'\/\"PI]>-5'I`.QC1!:(A +MBGI]:/MP;\RE>+SXO?9../0H[HV.R$(.XOR:V?P/?QN^9M=`?YA/0L,[7423;2AW@."7:#=!CR9<6RF\M:)_AC35I91)4Z]>OA6ID%XDGU.MDA=&I-.!>T.Y +M):E2QJ(!GJ,YBL*CV__]ZW^NB+*9FB*BW?.2F!@9$)XD[@4\=]/3OF6&`XM, +M^Q!(\SR*.A<@:0K0Y7/O0/D[RGT&T#\^WM/>VMIT^?`LW'L-"6?>FU08*16P +M-1ME7]]KT(H"I&IX3>BV:4S8M&D?X^-+IHPON)R&'\6*AJYSIHAX"/ +MS]KU3*X=&M@78DOS73O=QI+DCLR3\SW][+5"'J`R'_='S_CPW11'= +M9*F'@3RCNU<$VXNGI^+/N]5,V9Z*;`/N#3E9\.#:3?(.]8[N)=`J@EMO++!^ +M%%#5U(Y",#-#R25FD/B4*N^SZ];>[1/?XT..1#$?L;HQ6,F(0:!G7N!`PAGP +MEGO^.]U=MF+$FKT9-ELHN!VVR%]".J*1)*8WG0&P2LDEZ(`=R']?Z?S+G24!A6 +M[PW]"D:S0M=]DND8WW('`(,(@")(GJ!7M6]4#/H`/$6,JX`<22S2$JOE_,#; +M87]/E[;TDE\:O3L75_XI;E8L.^2J_M*$8-8I>&_W8M22RW>`?TB:`&6?).,8 +M^.B,:8%_!_&.VW@2J7@X0USTY2IK!LFB#C;E%#.@75&&;"=&AH'\$/R7#W@F +MC\BD9D3P?`>FT=8%_2`5"ULZ*E`J`X#;0II@%@.))P\Z6?F?0%W/&[VJZUN/@9#N1T(P[1;F<"L!NB8F!$GFUV'7?E$%M6;EBC +M?C/+.W'9%)J+\+8[HVSF;05=RBG_OC+@_\[=HGS:IFKH<;O?XC/P*82F$QXQ +M<]EU!A49;_<'D_9-S`EC,$KJ1D+"?*IG;"IQ?XF7L$Z33#,N"98\N) +M/ZC<6ZUA>)>7^)3#"GU@5[!ZA:TX)49%U=BMN%F&,7_"<(BOL=E*]VD\T/3Y`WA?#F!9YD@C^[6B1(*/8MI=?KVAI=G#=;$LR=U? +MDV:Y_`;EC2RRYB,6H54!\[1H5K?83B3.@'"&4-H1QT:SVJ,N\V&T:\2WN6KV +MORFXI,E=;:552I;X\#QF386"&L+%G<*[30$87%'&"=F)H)GQ(GT2(M[`/T?_ +MP#=*K??&082="_G;)C%0FQ77`QQW\?F"5%<9[#\"KNP[#T#K.*W1Z.C($3Y+ +M'I$)P.D?=W[)#H(F]UG)'C`DILT7`J(;EUEP+*?8@[WM4 +M_*'\DT*72G9W2*!]#HVNT-P,""*0Z#48@4 +MSR.+=\CS6AS$#N:EQK0)NZ0=NJ"'\FWY]@>_D!F/L'MNG@>1`W)Z@KH/LG!S +M'8[L%V232-KRZF&%3,A[RA%6GW='`&0^@\,QZ7!R!!\&1S*KD7V +M8$;]$:C8$D4P+1(`4U.J:83`*T1FO`[T!=RI3$PS+]:(Q/-<:23M:3:;[B7^ +M9Q%*W>X==BY75JK#^$4)@H>-OPL[!VH@'XY7!@S&8[*>GJ/(BPA#,W4-71234 +MX-0-21@"2?@`/&AJY3MSM@1IS*_]_]1E7=,'H7WX:;EW]3_KFCDFJ!7_^V%U +MD&:WAYPNZ5_YN-S`&O8_HZ8:E%/QA2QV4*T9O0/VX5U<,&ZHNFHOO-29@SDC +M9BJ".0AAYSH."$FRY@6KAYX;"_+LY!LRS*HZB%-ISA(9$#637*/0G$$$U!,% +ME3AP^\V-`$(D>//3[@ETG+B,&+KNL(XY=)Q/-7\X+;#PU!`(RS'SI4AWH,SZ +MN=T`SIV[((A/,HI78I\-RSBR?KU5#>^`]L6OB^@U&S)8P73996!3G"F<9TWN +MES`%PU*U;B846?T*+)>^=%M5?/Z1:(GKBQ+RG\1,_7.@7B7FC(2)=?V7(N-8 +ML.V+V]>Z_TM6$R*A'\^J@BD=PD'O1,/IRUGJY<$*)9X?KN:W462LE:@M(D*+ +MGNGE(P%IJ;=!X4D5%VUH0A*&9`K<'HR:T+3)$!77\]W+!41VX>)>;SL_;"[4 +MG-*P#[SYO:^%QK(8UB;!:(5/UHJL\]3=CH#LE<2&N72&J@&#G.15U/C0L(`_0S[Z9H#T""-M'@^EH3PVG)/<-O'UT?CX<+VMU'M.^=?E[<*- +MK^>\,RS=2U+7])N-_[VL,>T=FSQYFQ#;M:E7)Z0J=;@^[_5I#T(]UXA>Z-_4 +M#[()K1:T%I+W'8`P,:4;,6O`=^(&*".'L/:!7223,>IRQ`@$-[:(SL>#9;=) +M;5:`3R?W].RN^VA)0?*PQ37<9+WS&&V\4JV-T$7SC%C;CS(A9ZJ13^VPXD28 +MUO^J/;]GBR2^^+>^%I"I^:(LZ03P.)RHDO4P7V:IQ@*TRD?*XB9MO)JBBO%< +MD\TH1S:8@]DMED'!0S!EQG5S;WM-6YZY##A3P#AQ\"*(@J")B]Z:#O8\`+]B +M_30TAI@I-#\WPQ@W9M6]RS3D%\*0@I^6#&GDK-/>J3FPJE&#X[I7I;S@(_[J2+2LGC*+9A:8>* +M(8T!=F$4XUYEG[X8RT[1,L@](8\5(-8(A%I$,"#U$A7ZDU**!N#H:\&W-DVO +M\G#<'HVX?JQ0J8"I4'`HZ9%[LG;N..8Y)9KB_W4.-_0O$E07`C77?`XNZ5Z! +M8P[&*NUEQWMO!U;7-5Z'5XCL/SU2)1S-Q%%PY^2C?V&K]#_`W43;QKK:$E6;/YD'&80NP3_KIW/>[[4X +M4=M)WW0\/U6`03C49S)4(@<33F>&?KG9H/.SBQAJ)K,#[UL??L#K2R$X)'Q$ +MLQ<'+*+=`4@[[^WB<].".>[NA>D:;HI-#PN++\>W_,2=JMKR8G-,7CJ2)PW3N+9G'0/.\-#<^!>+HA=K!61.^EL$U!C^)K@08DT<'<>MV +M7N!O7V5;DO2RI\.>Q@1L?[&6X3?'OR5FI!`:FCSF><('!96%WTX"66YW^/G9 +MQ[3ARQN?0NWQ@O:=H9>E,L!Z[%^`D,>49TCL@WGTE83Q_FJ=)G?+/3[GH2L> +M^I:\B`(L/NDWRM&&^O#[3^F0KJ&CP(H,0Y,=>RX*B1W-2"ESBI0O&@4;OO' +M7P9&/Q1`KZPSZ3JA[*WQ1*6?;2JBCH-E>="F5R\`7]%>S3 +MK:+ETPPE0RCMT8&RSGSLRJ#;(@K-35(YDO3< +MI:X(\8;(6(?0TA:)V,V+4![\<5I?U?9M@!G?!C8;38^ZY:+0@0V9\$)\\>[* +M\/<@ZQ!\$5AJ@E41=5LS:L-0#Z8]WLWG`T.Z$ZYLC#)AW0/1BH0P8')_NX'> +M/_;OY%[0&/%3(GYG-`*TS:QH6TI`:K9NX<&L'GGTZP^7W(P[B)BK?\HD['4! +MB8'-$:ZVWU$2W[AFB0$3`UH4)PTF<=IJP2V#U")`[D]"RD+X6A6O^LEWK(B= +MP=>S\L4XY:UQ*$C#P^T9QH`OH^?XDW!0^SL2/2.CC_8'Q`E49^@I^?TN@0YM +MF7]'(6+IXWK)C``P\M&H=,=;0`WJ:3U"8P+*4C_/>MZ(^'#DUR"4L(VN\R^L +MY8>/A +MC"&6T]CBGX"Q^T(*U&D1;82JL)6]U?6Z9H_\@1)*>Y[6[(@?C=!U/^+5+`>8 +M0:B1SX,)34/=X67F-?C"_##_:\>'1Q?Q[(`N*D50752V@2V6&?P\^JA"/BSL +M#EFT&H!1.$S+TYKARJW7]!T<8_?P&P`I`EX$#KTS"K?J%98($G1V\#U;R'R2YQO._->^(,WR!*WUD8XZ5IG\NVF=>6:_J5=;XIT+ +M^OQY\U!@^KT<7(!R(%E`.O:+/NLFSU\\G)"X/&]$`2@*>#)B5'5S:G*VY"\6 +MYV5"#Y'2;ZQ[04DLJ((I7OM'1XVR1(K)YSH?LTO-_@)C2@9"6!EY(?S)*Z.@ +MBD*`9?(0_*6((HLT>F29+F,BW7R6Y1MOHV27:',XW\DGSY45ZID`*@(A +M%N)[6C[R5/Y\W>F*D75TL@U-N'NJY3A(!*\4\C7Y3G4$SVT*YX$5;"`XKKO) +M!1R'6A^6X:U:A^@R%%.<&^#`2,K:LL+>Y(F40HZYN^A"BN: +M4@.`!D[L@X9OU`;B8MG^,D)3@&M>L%3,ZB%/Y6L;5H!KN)(/(H("1:_TU8&-3/)TF'^HHQ8`1\.`FI8GU9SUCI +M+\*F]:[X)Z3@L\^V)66=D!Y5J^9\K2L,#Q[;8Y\+G4ZE2ZLGFPFRO/Y8N>"] +MVQ74BS$X-=;C[UG/T/=Z[)S9X7DP'AHR690 +M!1J15IP6PT9PJ@)NGC,=(-O[4\M8MQZH1P.=$&ESSGN!^>3W7B211(T11X`O +M;D!7@9.Z+XY!O&U6!X_[IFSP,\A]:*Y!_JCVC0/[HH +MK;-0:'N"T\E6FUQ=PI]IFJ;1J0Z\96XNO>#-6+O'!M$!N3YV>]26( +M3J*4A-O/B:',7N?U0,0X7U&J.MI_I-$%P,EFXP'=5=K$ +MXJ;)6L^6/_?8J3G?B#OOXS[E*[7N(EL)X"PJ1X-,0+P)*I?=,,8]Z&Z1T,": +MA2M4K[R2,!B--=2TQCPZ;HD0Y[C$?0$=:EQCR';XTT/RZ(N=FK5'/4K4LV(> +MH*$J&JL@(>VOQB`UQ--DXZK*9#D.0R8D_XLZ!"5_X)0N>=$RDI<M14E00-6O4T0?LXMFM48&9,54%$N8="JS-T2P`- +M5X6>3*+D9SA9G:T5(_2JB?()M;<>(G,>1>Q2VRUR];;,;W$&;[]?\41QZ'O( +M$'5C8A1H;+S#>J6E$A\!SO,U]^/Z,B/C24&/T.:A2:Z71N"3((?CQCAVG8GU +M070P<%A/--_F3+$%@@K8\I>7;PLRQ?0B2'>6GD"*LCTG62DV?*H:_+) +M+;U,!:6H:TOML`-CD*K`LFEC'%L]5.7:ZH58':6;T?&XP\H3QO<*=J0[,R5> +M,)(0U94NPYU!C?UI<+NJY=2(*421XQ;A=5>IJ[+S1'5`'_>"C*A'>"19+4&' +M;:B[(K0,U;GW,`L!.DA09Q[C0R*L!GU8!=%6\M&UW"`1RA(H6,,0I5*V"\L$ +MA6^-7[D>QNOH0"YZMLM#^Y:`+V@'R?">O'LSR9X]:$N-`S?);%[#9?X*2#V! +MMDF6R#SS3H--B"P`&DY`:@UD"ZH`A.+PZ>K=8\NLW3#0R$"1BN7,TUA?X9A>9(P%W`Z*(0PFEF"`>&F+!*ZV_9LS +ME"QOZ38?S[27N/ENZ;73TWNRW<=;B7/@%!S'%UP-MQEM8"+(.>:F'Q94YX;_ +MV:L@B/)<)1XFM5FR95YN7:\`YO[6)8MOK#2P>ODA;N167(U6KX(P'I*LZ.CM +MR'OAS_>\QT4K?6H)$3VN06E(V'/IN`@)9E#-2HYRAX?ZZ^V'Q_1VI.25`Z@. +MEV0K>G:(E=WSDI^R<7TN'2\[S.99;F11+NHI54)3/M)8]Y.5OY@;KN> +MK2ECNDE_WJ&K_*?Y_B7&OX5)E1+[HG/E1(M\J6?)*L=*\TEH\TR#Z[3+<:^8 +M+]6/.@AG63B)Y[;X"'_T+=6((O&'>+>`V@\9^6$%3,1A_E:/%]0O5454))_- +MAYXDY&95UK?_T9J8855UN$"`([!L"";_=6EGG*?6QB&AD]XUI\3YWGB^5>KK +MVC_7K=SUP242V(Z5J9U2.]Q+5J.$]6I7Q&N]Q#S8X!&3MP9<2-,=M,CINTJ+ +MAK=[I@_K +M`9C2[6!D]L>*@72X_8[8#0DY@E2\2C=W(:2'\S]1CA#\*YWGQ&H!M)=3=BU& +M%IX>'-2,F5## +M\_$5O6ZNXD?Y&8#C5!EV`726O[A8F?J1S2>09Y,%[$<<53YO!P_(6AGM4#=& +MO[ZL'_0Y>O0TF=]D9.S_IO,S2"1'&95G093O6,RRG@`I[THCR31.\^^04%OI +M[5?<:-3C8/.H,"3!9DOA1U2:>2SY$A@!"'0;+-C^^3:AFE7>)CF\^PW.@6*J +MZYXIB/:0TGC0S4Q0NY>12ZD`XP4B#=%HP=&A_W1`($4Y[!_L^/5CIJTE%T)` +MY9G7D-:&(W7BW$19!?WHI(@BGOK;$DYB3K#&#-]]/ +M-N`#>X52'T751^A@!,N]Y?D;JW^8>'XM8CI/Z8Q+%*2K$Z[VY* +MB'*T`<(4AXAU@#WM\/^1&ET$0'"@0Q'?M58L5+TB+\;FG`O"$+(X#!\\AAUF%B;6U/"$>0G)69'5]&1`Z*O0X_:DII76)E*+98O\NI*'HK>$FQ\G&R>^%V(KP,>G?`I>$99!+0= +M&;K482>/#SV-?`1LA3LP8&"V`!;RT*?6Q2-^Q]&[ZH#):7#@D?\%GY/3H;Z0 +MK\C8_637'5\`%'J]\)C.KQX@7"-F$BR<#Q\3@2Q*G.+_S]&O19Z0%2^PDQ!@ +M'V,HX-L_'6RN8E_&#T6QEDJP,5C8SAG"\`X5@E?:G&SGD:-`BFT'9PYRKTP- +M>%AP-WTE*Z'(^>`2$:2"NIT+U_V`(SCM\/Y%>O3N//Z<7P1?O%7H%8.<*_. +MTK/;TX!DYS"6A7#0+5A_#<0YXYR,477$JH'%A+)-W6Z=AES71G=`2I`BNV,$C5UCPF> +MAT;S4#X#^`YQY<HS*R1J(7H'>H%GKZ>!DFH)U_FK;?ZM1(GF*\.HQW`?.Z9K;HNB"O +MJY4R6^;YSR:02O@E>WWE88?PU4D'S$[GVD.3QR[9^-/N#1\E(2$HM3U^KTSD +M:>C9R=F>YC!7,)4[/MROT@1X7%AWE`_XO/WS#<0JP'%'@<]5#3W_RLJ4H_%7 +M$+LM;\C[3R"_P6IS].G@;>(=_50UO0,V4C?`5BW!J1[M/(10W[Y<,_+!JLA, +MPA9XRX+!?[13631P:HD@9,36DB&/!1ZA7S74JZW_AAX;X'#LK6V[.C>H4O^O +M]E]/7AF%X^)3(89U>(JARM^+?FBKDVA0`:W^5X4*JP7)+.??!Q]VTE+O)IN@ +MDR#G6UN<'(+TX!U`;`#[VYZR#:+S:]'([8,YQ(AJSYHDAX/H;TIYRH[=%I3] +M&.2HVD1)+9^UU2C3CA`-(F0@Q+._=(N;8_X(\7"WYCK.K-V^;?2/EG+'-3'6 +M:3ZSC;+.18S63*CT:6)2"L'[12.5VTV7\*/4`32>J%A9U(Z*8>4@\1PJ]/S* +M7[EG"-BVP_)1*916COMMZFNL1F-P%HL0AJ[^7;[N"6U,`6$MRB'&GQ-,4 +M$I=P=5*B1!CR"!$F-=HS9D@]WL&2I5GED)*32$U`4P1]OT;MQ%T;?LK5`-&MU"[ +M+H!D"F*)*W'>>*4-0&32$ +M@DP!?-CL#9*!\>\*_YEL1&RVW"W-F6^?[GLG&9'YSW.].\W +M*7CFK$E'QNK_=A\^=,Y8"KFR#OG86K?;1F@`QM4\32U71*I6B#*1B)<7A_GF +MN@`(.DT-^1,_X"\JVNOS&^MR+]O^*-B(XBLS=SAX<9A.IP450:`]!X@:!V/W +M`*/\SJX0"60P=B^L4K$0&RHQ^B&W-$+!Z-73>J,"XJS&2^%BN5.VV4P6C;%!V"T +MH'34PO#[8667]A"..>2C[B4-..+.=3P4]!J+N`N^;E.X0J#`V:RXK#UHT]5L +MQ#3XTDJ@!["+U1.6<"BRS.)TD7GR(D'6VX47/7P=@L9HIT:^(.05T70&9&3N +M:E85CX>G>#8X7>R&9[(=JYXX<1*L359.7/=G[,1V(IE@_<3V/N3C76=%T\ZX +M37>_E)62XIM$V+Y3`0+O+4P`C<_ZT`BSO19"5><.T0+-.7$M*"O^71SD)((G +M#=Y`1E1CRA7"JS8F!+8NBZY.&EY)?830#A8/7/QJOZY2<,O?0V.4[FA==H45@2[?%'NQ;+V +M.%%@*5#8[^Z49]Q)*EQ?[\?C.-_I'M9(^P/WCNX(GT>J_ +M=18QC[#,L8(4D.LE.H8]0E7&))&AA2Y1+!&Z0/UY?Y:6NCAZN^R=T4\9?ZU_7P1=]V*&;LN)N! +M6R"\5$`WEW(K=[;0>6!/@[*AZ+=:;L+.![E;=D/3ZK@W4-B-(>:[B-*ASGF? +M:%]L)A/LN+>%N.B-XE0O'K[:A*?LH01X=:=2^1)'>U.!G?$?KEU+G):TK=BH +M?+M9Y$<4&$WH[=HOD*WU&`8^2A[IY?)0,HK*A?8< +MNVS?K&1Y6.+[2%\3C^X"J0G2E;?E-YP1W;$ZTS(.4I:1R],2,Z*,+6C)^2I=WQ;?%AF*9N +M!2M%R]J2Y&ZP*ZZ8H'E`4?5WD;ZWP(9?TE0U1BF&U(9]/]KHWR4B],KHIWP6 +M+N%`Z&RX0B$:S6)^E14:HI%`RU^"=OD/_)9N!ER,B)EA8=M?8(*[S??',LSUHZ.7_JGG6;;36O$9%L#BQ2PMNBL +MUOOA;!K5LU_OJ1TKV:"[;N,(EX+(,PLIV#@Y+,-.U^8(42U<1EURDWC]-;XW +M-^GI.)'31DVD\A4GHS=O&K8($E7Y7A244(H+)DSNU'%[!]@1-CDNR8=#TL<$ +MV/")>;]:*_S0A]Y"!LBWT[A>26!E)Y3L#[K@I1Q213'@X&DL:[W#E6?(">BJ +MRM"I<`:9V=^`'4F'G47'JO4OY8O\)`(Z3'RL-%,'`LE#I';?T(T:7?%(XI5& +M'G'A;O`E:1@8ISR+J:OTS9`S%%.LW9);0K"3I6.GQ7L85(AO-3LDM$I +M9U/P#^M>AA?A7<+<=V%?B=MW22G3(^Q;"^M3_=\0[":(#Z-Y%I=X;D1_90I; +M.#,<;=&O\L.[D(*V+%_6='O(Z%"T_YE=8R2YARW%!">;G)I-Y<.+2>$5.JID +M+RT5S368)IS/[D)1PN!W"2H\"F%\KR@=+!6$_^*5PWST3AOLD]2J8&CF%5V_ +M(7;,)WM.%L%(W9ATNI25!?_QA2?AD$W3+"0#_K4""Y'NZK?`='=;Q"O;MXP& +M2;M)1"AKYA@!&CUX1<]N:-F71S8&I7<8H'[(O9+JF9^ +M&:CR67=?H&PQ>,N=07B>&GB2^)AW70B_^M_$\20.<`".#;]--:32D:0YV6N# +M$UKA.(A@.0"49W!/)W2A.I%,,F6&!%LJ+UA]RK&WTZBJ!''6TDOY:M>^Q(>A +M@2NXO+\T]6X'[1\"`$>%E!UDHV&EKD(3_9""K!8!ZA?`,.6H3WQA>HO`M^AUSS7W?WA\? +M7)WL]5=;((S+.^(`D\'Q8_+XU[!9]LZ5*3`)3R>2WPT$.Z%MWGW3M:*6"$ZI +M@=Z1TP;9P$5`\C\JKLN5(\CXX_.PS37>.SYP-+F)(&:Y!3A%`_&31DX.6<6_ +MVT<1.4_=F/"C#VTJ0TF>S"CD:8E_K&&:N//%,3O,&S:[57F@XZ+:-!.=G^AX +M*)$:V@W;]@QQI_E +M-)<\*E0;S&`SU'4#.'*TM7,=J>4RFCGG57,M]3BG8>X=/:!R>?WU8;L274&_G-,CB@R5HY9;02!+5S8+F?@M]WDJG:/+6CA)W6PQ&, +MI[E?,T(*4?B:W0HS_MC#;FVAA=J5;2=BQLCN,MV_=6-AT,FIX8CB:>Q([P'Z +MTNC@EZ]6)L38L>&'_1')NDJ^Q9Q+78CH>!)=%K_I^*I-:68H&*V=XFCR0=@L +MRIK0A'F>/%M'#R`T6(SI4ADUGB=V[5TIC`B;[[=Z+]!RA2..9H +M!3^!XV)/W`7[1W0^LB;/C%=T_,H-Q?`<#!/ +M_2+QYR[X$5=M/YE`+WA8Z:`Z]7YN>;9(UHJH7ZS:]^QXQ-"51*.=6*=T+CCZ +M4V,KH7C+TV+TQSYG@1^/L1>^\R"*'`S.77]A&-,]SZ6B,4W$/MGR7.%IV%QC +M70[DZZHC&IBN<_]0]_`*MR_]N)9:/3KG)"0-.]WQKQ'.`$MX4&/6?EI_^`-0 +M$'L#/'B@LSNU6!C[&0J#O3@8I1&,3!%<\'ESTTV6]P6&&(DH-?J,=A]638MW +MF<,*:U$Q`YWYU8]DQ`M/KC3@DPVJK$@6H$+=-]M#^E[T<72D+]6D(&CL*>#J)!N\!7]MWZ>P\;G:%RYO$^O +MB^,;$WRF=4MKZ8K6./3!R[;EI->&>YWP^XC^%Q>F+8";-?7M6>ONZ! +M'R"*G(1*_<+U7?(;I>TP0>?=B((9OI-"-^3YX3[)];#T5HS?`YOGIY`&L=R] +MJ`@%Z(8[=V\\%GY(1L_/9?VF"X=34SQ]!]

    <" + "A NAME=\"Life_cycle_of_a_te"; + const char file_test_txt5[] = "LE=\"margin-bottom: 0in\">DO use runtime te" + "sts for platform\n\tfeatu"; + const char file_test_txt6[] = "rough test suite is essential\nboth for ver" + "ifying new ports and f"; + const char file_test_txt7[] = "m: 0in\">Creates a temporary directory\n\tw" + "hose name matches the na"; + const char file_test_txt8[] = "lt\ninput file and verify the results. Thes" + "e use \n", buff); + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, -1, archive_seek_data(a, -(((int)sizeof(buff)-1)*2), SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), archive_seek_data(a, 0, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualIntA(a, ((sizeof(buff)-1)*2), archive_seek_data(a, 0, SEEK_CUR)); + assertEqualStringA(a, "\n\n\t\n\t\n\t 0); + + /* Seek to the end minus (sizeof(buff)-1) bytes */ + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, -((int)sizeof(buff)-1), SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + /* Seek back to the beginning */ + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, archive_seek_data(a, -20111, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + /* Test that SEEK_SET works correctly between data blocks */ + assertEqualIntA(a, 0, archive_seek_data(a, 0, SEEK_SET)); + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 13164, + archive_seek_data(a, 13164, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "ertEqualInt,\n\tassertEqualString, " + "assertEqualMem to test equalit", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, 0, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 20111 - (int)(sizeof(buff)-1), SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 13164, + archive_seek_data(a, 13164, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "ertEqualInt,\n\tassertEqualString, " + "assertEqualMem to test equalit", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 20111 - (int)(sizeof(buff)-1), SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, 0, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 20111 - (int)(sizeof(buff)-1), SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 13164, + archive_seek_data(a, 13164, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "ertEqualInt,\n\tassertEqualString, " + "assertEqualMem to test equalit", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, 0, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + /* Test that SEEK_CUR works correctly between data blocks */ + assertEqualIntA(a, 0, archive_seek_data(a, 0, SEEK_SET)); + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 13164, + archive_seek_data(a, 13164, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "ertEqualInt,\n\tassertEqualString, " + "assertEqualMem to test equalit", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -13227, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 19985, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 13164, + archive_seek_data(a, -6947, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "ertEqualInt,\n\tassertEqualString, " + "assertEqualMem to test equalit", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 6821, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -20111, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 19985, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 13164, + archive_seek_data(a, -6947, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "ertEqualInt,\n\tassertEqualString, " + "assertEqualMem to test equalit", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -13227, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + /* Test that SEEK_END works correctly between data blocks */ + assertEqualIntA(a, 0, archive_seek_data(a, 0, SEEK_SET)); + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 13164, + archive_seek_data(a, -6947, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "ertEqualInt,\n\tassertEqualString, " + "assertEqualMem to test equalit", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -20111, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, -((int)sizeof(buff)-1), SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 13164, + archive_seek_data(a, -6947, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "ertEqualInt,\n\tassertEqualString, " + "assertEqualMem to test equalit", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, -((int)sizeof(buff)-1), SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -20111, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, -((int)sizeof(buff)-1), SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 13164, + archive_seek_data(a, -6947, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "ertEqualInt,\n\tassertEqualString, " + "assertEqualMem to test equalit", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -20111, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + test_read_format_rar_multivolume_uncompressed_files_helper(a); + + /* + * Second header. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualStringA(a, "testdir/testsubdir/LibarchiveAddingTest2.html", + archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualIntA(a, 20111, archive_entry_size(ae)); + assertEqualIntA(a, 33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + test_read_format_rar_multivolume_uncompressed_files_helper(a); + + /* Read from the beginning to the end of the file */ + assertEqualIntA(a, 0, archive_seek_data(a, 0, SEEK_SET)); + do + { + memset(buff, 0, sizeof(buff)); + bytes_read = archive_read_data(a, buff, (sizeof(buff)-1)); + } while (bytes_read > 0); + + /* Seek to the end minus (sizeof(buff)-1) bytes */ + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, -((int)sizeof(buff)-1), SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + /* Seek back to the beginning */ + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, archive_seek_data(a, -20111, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + /* Test that SEEK_SET works correctly between data blocks */ + assertEqualIntA(a, 0, archive_seek_data(a, 0, SEEK_SET)); + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 6162, + archive_seek_data(a, 6162, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "arguments satisfy certain conditions. " + "If the assertion fails--f", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 19347, + archive_seek_data(a, 19347, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, " when a block being written out by\n" + "the archive writer is the sa", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 20111 - (int)(sizeof(buff)-1), SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 19347, + archive_seek_data(a, 19347, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, " when a block being written out by\n" + "the archive writer is the sa", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 6162, + archive_seek_data(a, 6162, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "arguments satisfy certain conditions. " + "If the assertion fails--f", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, 0, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 20111 - (int)(sizeof(buff)-1), SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 6162, + archive_seek_data(a, 6162, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "arguments satisfy certain conditions. " + "If the assertion fails--f", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 19347, + archive_seek_data(a, 19347, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, " when a block being written out by\n" + "the archive writer is the sa", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, 0, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 20111 - (int)(sizeof(buff)-1), SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, 0, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 19347, + archive_seek_data(a, 19347, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, " when a block being written out by\n" + "the archive writer is the sa", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 6162, + archive_seek_data(a, 6162, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "arguments satisfy certain conditions. " + "If the assertion fails--f", buff); + + /* Test that SEEK_CUR works correctly between data blocks */ + assertEqualIntA(a, 0, archive_seek_data(a, 0, SEEK_SET)); + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 6162, + archive_seek_data(a, 6162, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "arguments satisfy certain conditions. " + "If the assertion fails--f", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 19347, + archive_seek_data(a, 13122, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, " when a block being written out by\n" + "the archive writer is the sa", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 638, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 19347, + archive_seek_data(a, -764, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, " when a block being written out by\n" + "the archive writer is the sa", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 6162, + archive_seek_data(a, -13248, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "arguments satisfy certain conditions. " + "If the assertion fails--f", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -6225, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 19985, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 6162, + archive_seek_data(a, -13949, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "arguments satisfy certain conditions. " + "If the assertion fails--f", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 19347, + archive_seek_data(a, 13122, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, " when a block being written out by\n" + "the archive writer is the sa", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -19410, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 19985, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -20111, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 19347, + archive_seek_data(a, 19284, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, " when a block being written out by\n" + "the archive writer is the sa", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 6162, + archive_seek_data(a, -13248, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "arguments satisfy certain conditions. " + "If the assertion fails--f", buff); + + /* Test that SEEK_END works correctly between data blocks */ + assertEqualIntA(a, 0, archive_seek_data(a, 0, SEEK_SET)); + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 6162, + archive_seek_data(a, -13949, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "arguments satisfy certain conditions. " + "If the assertion fails--f", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 19347, + archive_seek_data(a, -764, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, " when a block being written out by\n" + "the archive writer is the sa", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, -((int)sizeof(buff)-1), SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 19347, + archive_seek_data(a, -764, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, " when a block being written out by\n" + "the archive writer is the sa", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 6162, + archive_seek_data(a, -13949, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "arguments satisfy certain conditions. " + "If the assertion fails--f", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -20111, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, -((int)sizeof(buff)-1), SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 6162, + archive_seek_data(a, -13949, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "arguments satisfy certain conditions. " + "If the assertion fails--f", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 19347, + archive_seek_data(a, -764, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, " when a block being written out by\n" + "the archive writer is the sa", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -20111, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, -((int)sizeof(buff)-1), SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -20111, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 19347, + archive_seek_data(a, -764, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, " when a block being written out by\n" + "the archive writer is the sa", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 6162, + archive_seek_data(a, -13949, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "arguments satisfy certain conditions. " + "If the assertion fails--f", buff); + + test_read_format_rar_multivolume_uncompressed_files_helper(a); + + /* + * Third header. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualStringA(a, "LibarchiveAddingTest2.html", + archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualIntA(a, 20111, archive_entry_size(ae)); + assertEqualIntA(a, 33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + test_read_format_rar_multivolume_uncompressed_files_helper(a); + + /* Read from the beginning to the end of the file */ + assertEqualIntA(a, 0, archive_seek_data(a, 0, SEEK_SET)); + do + { + memset(buff, 0, sizeof(buff)); + bytes_read = archive_read_data(a, buff, (sizeof(buff)-1)); + } while (bytes_read > 0); + + /* Seek to the end minus (sizeof(buff)-1) bytes */ + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, -((int)sizeof(buff)-1), SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + /* Seek back to the beginning */ + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, archive_seek_data(a, -20111, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + /* Test that SEEK_SET works correctly between data blocks */ + assertEqualIntA(a, 0, archive_seek_data(a, 0, SEEK_SET)); + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 12353, + archive_seek_data(a, 12353, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, " 0.2in\">    " + "extract_reference_file("test_foo.tar", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, 0, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 20111 - (int)(sizeof(buff)-1), SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 12353, + archive_seek_data(a, 12353, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, " 0.2in\">    " + "extract_reference_file("test_foo.tar", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 20111 - (int)(sizeof(buff)-1), SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, 0, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 20111 - (int)(sizeof(buff)-1), SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 12353, + archive_seek_data(a, 12353, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, " 0.2in\">    " + "extract_reference_file("test_foo.tar", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, 0, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + /* Test that SEEK_CUR works correctly between data blocks */ + assertEqualIntA(a, 0, archive_seek_data(a, 0, SEEK_SET)); + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 12353, + archive_seek_data(a, 12353, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, " 0.2in\">    " + "extract_reference_file("test_foo.tar", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -12416, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 19985, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 12353, + archive_seek_data(a, -7758, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, " 0.2in\">    " + "extract_reference_file("test_foo.tar", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 7632, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -20111, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 19985, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 12353, + archive_seek_data(a, -7758, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, " 0.2in\">    " + "extract_reference_file("test_foo.tar", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -12416, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + /* Test that SEEK_END works correctly between data blocks */ + assertEqualIntA(a, 0, archive_seek_data(a, 0, SEEK_SET)); + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 12353, + archive_seek_data(a, -7758, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, " 0.2in\">    " + "extract_reference_file("test_foo.tar", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -20111, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, -((int)sizeof(buff)-1), SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 12353, + archive_seek_data(a, -7758, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, " 0.2in\">    " + "extract_reference_file("test_foo.tar", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, -((int)sizeof(buff)-1), SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -20111, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, -((int)sizeof(buff)-1), SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 12353, + archive_seek_data(a, -7758, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, " 0.2in\">    " + "extract_reference_file("test_foo.tar", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -20111, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + test_read_format_rar_multivolume_uncompressed_files_helper(a); + + /* + * Fourth header. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualStringA(a, "testdir/LibarchiveAddingTest.html", + archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualIntA(a, 20111, archive_entry_size(ae)); + assertEqualIntA(a, 33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + test_read_format_rar_multivolume_uncompressed_files_helper(a); + + /* Read from the beginning to the end of the file */ + assertEqualIntA(a, 0, archive_seek_data(a, 0, SEEK_SET)); + do + { + memset(buff, 0, sizeof(buff)); + bytes_read = archive_read_data(a, buff, (sizeof(buff)-1)); + } while (bytes_read > 0); + + /* Seek to the end minus (sizeof(buff)-1) bytes */ + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, -((int)sizeof(buff)-1), SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + /* Seek back to the beginning */ + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, archive_seek_data(a, -20111, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + /* Test that SEEK_SET works correctly between data blocks */ + assertEqualIntA(a, 0, archive_seek_data(a, 0, SEEK_SET)); + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 5371, + archive_seek_data(a, 5371, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "zip)\n  {\n    " + "/* ... setup omitted ... */\n  ", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 13165, + archive_seek_data(a, 13165, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "rtEqualInt,\n\tassertEqualString, " + "assertEqualMem to test equality", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 20111 - (int)(sizeof(buff)-1), SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 13165, + archive_seek_data(a, 13165, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "rtEqualInt,\n\tassertEqualString, " + "assertEqualMem to test equality", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 5371, + archive_seek_data(a, 5371, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "zip)\n  {\n    " + "/* ... setup omitted ... */\n  ", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, 0, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 20111 - (int)(sizeof(buff)-1), SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 5371, + archive_seek_data(a, 5371, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "zip)\n  {\n    " + "/* ... setup omitted ... */\n  ", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 13165, + archive_seek_data(a, 13165, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "rtEqualInt,\n\tassertEqualString, " + "assertEqualMem to test equality", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, 0, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 20111 - (int)(sizeof(buff)-1), SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, 0, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 13165, + archive_seek_data(a, 13165, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "rtEqualInt,\n\tassertEqualString, " + "assertEqualMem to test equality", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 5371, + archive_seek_data(a, 5371, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "zip)\n  {\n    " + "/* ... setup omitted ... */\n  ", buff); + + /* Test that SEEK_CUR works correctly between data blocks */ + assertEqualIntA(a, 0, archive_seek_data(a, 0, SEEK_SET)); + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 5371, + archive_seek_data(a, 5371, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "zip)\n  {\n    " + "/* ... setup omitted ... */\n  ", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 13165, + archive_seek_data(a, 7731, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "rtEqualInt,\n\tassertEqualString, " + "assertEqualMem to test equality", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 6820, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 13165, + archive_seek_data(a, -6946, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "rtEqualInt,\n\tassertEqualString, " + "assertEqualMem to test equality", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 5371, + archive_seek_data(a, -7857, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "zip)\n  {\n    " + "/* ... setup omitted ... */\n  ", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -5434, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 19985, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 5371, + archive_seek_data(a, -14740, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "zip)\n  {\n    " + "/* ... setup omitted ... */\n  ", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 13165, + archive_seek_data(a, 7731, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "rtEqualInt,\n\tassertEqualString, " + "assertEqualMem to test equality", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -13228, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 19985, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -20111, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 13165, + archive_seek_data(a, 13102, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "rtEqualInt,\n\tassertEqualString, " + "assertEqualMem to test equality", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 5371, + archive_seek_data(a, -7857, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "zip)\n  {\n    " + "/* ... setup omitted ... */\n  ", buff); + + /* Test that SEEK_END works correctly between data blocks */ + assertEqualIntA(a, 0, archive_seek_data(a, 0, SEEK_SET)); + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 5371, + archive_seek_data(a, -14740, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "zip)\n  {\n    " + "/* ... setup omitted ... */\n  ", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 13165, + archive_seek_data(a, -6946, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "rtEqualInt,\n\tassertEqualString, " + "assertEqualMem to test equality", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, -((int)sizeof(buff)-1), SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 13165, + archive_seek_data(a, -6946, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "rtEqualInt,\n\tassertEqualString, " + "assertEqualMem to test equality", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 5371, + archive_seek_data(a, -14740, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "zip)\n  {\n    " + "/* ... setup omitted ... */\n  ", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -20111, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, -((int)sizeof(buff)-1), SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 5371, + archive_seek_data(a, -14740, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "zip)\n  {\n    " + "/* ... setup omitted ... */\n  ", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 13165, + archive_seek_data(a, -6946, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "rtEqualInt,\n\tassertEqualString, " + "assertEqualMem to test equality", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -20111, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, -((int)sizeof(buff)-1), SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -20111, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 13165, + archive_seek_data(a, -6946, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "rtEqualInt,\n\tassertEqualString, " + "assertEqualMem to test equality", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 5371, + archive_seek_data(a, -14740, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "zip)\n  {\n    " + "/* ... setup omitted ... */\n  ", buff); + + test_read_format_rar_multivolume_uncompressed_files_helper(a); + + /* + * Fifth header. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualStringA(a, "testdir/testsubdir/LibarchiveAddingTest.html", + archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualIntA(a, 20111, archive_entry_size(ae)); + assertEqualIntA(a, 33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + test_read_format_rar_multivolume_uncompressed_files_helper(a); + + /* Read from the beginning to the end of the file */ + assertEqualIntA(a, 0, archive_seek_data(a, 0, SEEK_SET)); + do + { + memset(buff, 0, sizeof(buff)); + bytes_read = archive_read_data(a, buff, (sizeof(buff)-1)); + } while (bytes_read > 0); + + /* Seek to the end minus (sizeof(buff)-1) bytes */ + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, -((int)sizeof(buff)-1), SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + /* Seek back to the beginning */ + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, archive_seek_data(a, -20111, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + /* Test that SEEK_SET works correctly between data blocks */ + assertEqualIntA(a, 0, archive_seek_data(a, 0, SEEK_SET)); + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 11568, + archive_seek_data(a, 11568, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ", assertFileContents," + "\n\t\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 20111 - (int)(sizeof(buff)-1), SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 11568, + archive_seek_data(a, 11568, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ", assertFileContents," + "\n\t\n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, 0, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 20111 - (int)(sizeof(buff)-1), SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 11568, + archive_seek_data(a, 11568, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ", assertFileContents," + "\n\t\n", buff); + + /* Test that SEEK_CUR works correctly between data blocks */ + assertEqualIntA(a, 0, archive_seek_data(a, 0, SEEK_SET)); + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 11568, + archive_seek_data(a, 11568, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ", assertFileContents," + "\n\t\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 19985, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 11568, + archive_seek_data(a, -8543, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ", assertFileContents," + "\n\t\n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -20111, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 19985, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 11568, + archive_seek_data(a, -8543, SEEK_CUR)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ", assertFileContents," + "\n\t\n", buff); + + /* Test that SEEK_END works correctly between data blocks */ + assertEqualIntA(a, 0, archive_seek_data(a, 0, SEEK_SET)); + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 11568, + archive_seek_data(a, -8543, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ", assertFileContents," + "\n\t\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, -((int)sizeof(buff)-1), SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 11568, + archive_seek_data(a, -8543, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ", assertFileContents," + "\n\t\n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, + archive_seek_data(a, -20111, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, -((int)sizeof(buff)-1), SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 11568, + archive_seek_data(a, -8543, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ", assertFileContents," + "\n\t\n", buff); + + test_read_format_rar_multivolume_uncompressed_files_helper(a); + + /* + * Sixth header. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualStringA(a, "LibarchiveAddingTest.html", + archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertA((int)archive_entry_ctime(ae)); + assertA((int)archive_entry_atime(ae)); + assertEqualIntA(a, 20111, archive_entry_size(ae)); + assertEqualIntA(a, 33188, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); + + test_read_format_rar_multivolume_uncompressed_files_helper(a); + + /* Read from the beginning to the end of the file */ + assertEqualIntA(a, 0, archive_seek_data(a, 0, SEEK_SET)); + do + { + memset(buff, 0, sizeof(buff)); + bytes_read = archive_read_data(a, buff, (sizeof(buff)-1)); + } while (bytes_read > 0); + + /* Seek to the end minus (sizeof(buff)-1) bytes */ + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, -((int)sizeof(buff)-1), SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + /* Seek back to the beginning */ + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 0, archive_seek_data(a, -20111, SEEK_END)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\n", buff); + + /* Test that SEEK_SET works correctly between data blocks */ + assertEqualIntA(a, 0, archive_seek_data(a, 0, SEEK_SET)); + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 4576, + archive_seek_data(a, 4576, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "hat was expected. \n

    \n

    Large tar tester

    \n

    The " + "large tar tester attempts to", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 20111 - (int)(sizeof(buff)-1), + archive_seek_data(a, 20111 - (int)(sizeof(buff)-1), SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, ". \n

    \n


    \n" + "

    \n\n", buff); + + memset(buff, 0, sizeof(buff)); + assertEqualIntA(a, 17749, + archive_seek_data(a, 17749, SEEK_SET)); + assertEqualIntA(a, (sizeof(buff)-1), + archive_read_data(a, buff, (sizeof(buff)-1))); + assertEqualStringA(a, "\">Large tar tester